From 148110c2b3280933bb1fe3379495db8a043901f2 Mon Sep 17 00:00:00 2001 From: Kilian Saffran Date: Fri, 17 May 2019 18:04:43 +0200 Subject: [PATCH] generate invoice sendmail --- api/invoicetemplate.json | 50 - api/lib/pgsql.pm | 10 +- api/lib/report.pm | 243 + api/lib/sendemail.pm | 93 + api/mailtemplate.txt | 25 - api/process.cgi | 39 +- api/reports/DKS_JD190517-000002.pdf | Bin 0 -> 79615 bytes api/reports/DKS_JD201905-000020.pdf | Bin 0 -> 79510 bytes api/sql.log | 34 + backoffice/index.cgi | 4 +- backoffice/js/modules_global.js | 4 +- backoffice/sql.log | 5023 --- backoffice/tmpl/module/applications.tt | 23 +- backoffice/tmpl/module/js/applications.js | 68 +- lib/CGI.pm | 2 + lib/CGI/Carp.pm | 2 + lib/CGI/Cookie.pm | 2 + lib/CGI/File/Temp.pm | 2 + lib/CGI/Util.pm | 2 + lib/DBD/DBM.pm | 2 + lib/DBD/ExampleP.pm | 2 + lib/DBD/File.pm | 2 + lib/DBD/Gofer.pm | 2 + lib/DBD/Gofer/Policy/Base.pm | 2 + lib/DBD/Gofer/Policy/classic.pm | 2 + lib/DBD/Gofer/Policy/pedantic.pm | 2 + lib/DBD/Gofer/Policy/rush.pm | 2 + lib/DBD/Gofer/Transport/Base.pm | 2 + lib/DBD/Gofer/Transport/corostream.pm | 2 + lib/DBD/Gofer/Transport/null.pm | 2 + lib/DBD/Gofer/Transport/pipeone.pm | 2 + lib/DBD/Gofer/Transport/stream.pm | 2 + lib/DBD/NullP.pm | 2 + lib/DBD/PgPP.pm | 2 + lib/DBD/SQLite.pm | 2 + lib/DBD/SQLite/Constants.pm | 2 + lib/DBD/SQLite/GetInfo.pm | 2 + lib/DBD/SQLite/VirtualTable.pm | 2 + lib/DBD/SQLite/VirtualTable/FileContent.pm | 2 + lib/DBD/SQLite/VirtualTable/PerlData.pm | 2 + lib/DBD/Sponge.pm | 2 + lib/DBD/mysql.pm | 2 + lib/DBD/mysql/GetInfo.pm | 2 + lib/DBI.pm | 2 + lib/DBI/Const/GetInfo/ANSI.pm | 2 + lib/DBI/Const/GetInfo/ODBC.pm | 2 + lib/DBI/Const/GetInfoType.pm | 2 + lib/DBI/DBD/SqlEngine.pm | 2 + lib/DBI/Gofer/Execute.pm | 2 + lib/DBI/Gofer/Request.pm | 2 + lib/DBI/Gofer/Response.pm | 2 + lib/DBI/Gofer/Serializer/Base.pm | 2 + lib/DBI/Gofer/Serializer/DataDumper.pm | 2 + lib/DBI/Gofer/Serializer/Storable.pm | 2 + lib/DBI/Gofer/Transport/Base.pm | 2 + lib/DBI/PurePerl.pm | 2 + lib/DBI/SQL/Nano.pm | 2 + lib/DBI/Util/_accessor.pm | 2 + lib/Digest/SHA/PurePerl.pm | 2 + lib/Fh.pm | 2 + lib/Font/TTF/Font.pm | 633 + lib/Font/TTF/Table.pm | 303 + lib/Font/TTF/Utils.pm | 495 + lib/Font/TTF/Woff.pm | 16 + lib/Font/TTF/Woff/MetaData.pm | 14 + lib/Font/TTF/Woff/PrivateData.pm | 15 + lib/HTML/Entities.pm | 2 + lib/HTML/Parser.pm | 2 + lib/IO/String.pm | 427 + lib/Image/ExifTool.pm | 8280 ++++ lib/Image/ExifTool.pod | 2646 ++ lib/Image/ExifTool/AES.pm | 501 + lib/Image/ExifTool/AFCP.pm | 281 + lib/Image/ExifTool/AIFF.pm | 297 + lib/Image/ExifTool/APE.pm | 287 + lib/Image/ExifTool/APP12.pm | 322 + lib/Image/ExifTool/ASF.pm | 898 + lib/Image/ExifTool/Apple.pm | 161 + lib/Image/ExifTool/Audible.pm | 317 + lib/Image/ExifTool/BMP.pm | 361 + lib/Image/ExifTool/BPG.pm | 253 + lib/Image/ExifTool/BZZ.pm | 472 + lib/Image/ExifTool/BigTIFF.pm | 297 + lib/Image/ExifTool/BuildTagLookup.pm | 2631 ++ lib/Image/ExifTool/Canon.pm | 9513 +++++ lib/Image/ExifTool/CanonCustom.pm | 2780 ++ lib/Image/ExifTool/CanonRaw.pm | 910 + lib/Image/ExifTool/CanonVRD.pm | 2260 ++ lib/Image/ExifTool/CaptureOne.pm | 235 + lib/Image/ExifTool/Casio.pm | 2060 + lib/Image/ExifTool/Charset.pm | 431 + lib/Image/ExifTool/Charset/Arabic.pm | 39 + lib/Image/ExifTool/Charset/Baltic.pm | 35 + lib/Image/ExifTool/Charset/Cyrillic.pm | 45 + lib/Image/ExifTool/Charset/DOSLatin1.pm | 49 + lib/Image/ExifTool/Charset/DOSLatinUS.pm | 49 + lib/Image/ExifTool/Charset/Greek.pm | 40 + lib/Image/ExifTool/Charset/Hebrew.pm | 36 + lib/Image/ExifTool/Charset/JIS.pm | 1735 + lib/Image/ExifTool/Charset/Latin.pm | 24 + lib/Image/ExifTool/Charset/Latin2.pm | 36 + lib/Image/ExifTool/Charset/MacArabic.pm | 47 + lib/Image/ExifTool/Charset/MacChineseCN.pm | 2088 + lib/Image/ExifTool/Charset/MacChineseTW.pm | 3623 ++ lib/Image/ExifTool/Charset/MacCroatian.pm | 43 + lib/Image/ExifTool/Charset/MacCyrillic.pm | 47 + lib/Image/ExifTool/Charset/MacGreek.pm | 45 + lib/Image/ExifTool/Charset/MacHebrew.pm | 47 + lib/Image/ExifTool/Charset/MacIceland.pm | 42 + lib/Image/ExifTool/Charset/MacJapanese.pm | 1933 + lib/Image/ExifTool/Charset/MacKorean.pm | 2720 ++ lib/Image/ExifTool/Charset/MacLatin2.pm | 44 + lib/Image/ExifTool/Charset/MacRSymbol.pm | 2087 + lib/Image/ExifTool/Charset/MacRoman.pm | 42 + lib/Image/ExifTool/Charset/MacRomanian.pm | 42 + lib/Image/ExifTool/Charset/MacThai.pm | 49 + lib/Image/ExifTool/Charset/MacTurkish.pm | 42 + lib/Image/ExifTool/Charset/PDFDoc.pm | 28 + lib/Image/ExifTool/Charset/ShiftJIS.pm | 1835 + lib/Image/ExifTool/Charset/Symbol.pm | 54 + lib/Image/ExifTool/Charset/Thai.pm | 41 + lib/Image/ExifTool/Charset/Turkish.pm | 25 + lib/Image/ExifTool/Charset/Vietnam.pm | 27 + lib/Image/ExifTool/DICOM.pm | 3881 ++ lib/Image/ExifTool/DJI.pm | 138 + lib/Image/ExifTool/DNG.pm | 842 + lib/Image/ExifTool/DPX.pm | 182 + lib/Image/ExifTool/DV.pm | 319 + lib/Image/ExifTool/DarwinCore.pm | 362 + lib/Image/ExifTool/DjVu.pm | 378 + lib/Image/ExifTool/EXE.pm | 1425 + lib/Image/ExifTool/Exif.pm | 6384 +++ lib/Image/ExifTool/FLAC.pm | 307 + lib/Image/ExifTool/FLIF.pm | 353 + lib/Image/ExifTool/FLIR.pm | 1629 + lib/Image/ExifTool/Fixup.pm | 366 + lib/Image/ExifTool/Flash.pm | 755 + lib/Image/ExifTool/FlashPix.pm | 2395 ++ lib/Image/ExifTool/Font.pm | 647 + lib/Image/ExifTool/FotoStation.pm | 261 + lib/Image/ExifTool/FujiFilm.pm | 1591 + lib/Image/ExifTool/GE.pm | 81 + lib/Image/ExifTool/GIF.pm | 560 + lib/Image/ExifTool/GIMP.pm | 294 + lib/Image/ExifTool/GPS.pm | 585 + lib/Image/ExifTool/GeoTiff.pm | 2263 ++ lib/Image/ExifTool/Geotag.pm | 1327 + lib/Image/ExifTool/GoPro.pm | 709 + lib/Image/ExifTool/H264.pm | 1134 + lib/Image/ExifTool/HP.pm | 263 + lib/Image/ExifTool/HTML.pm | 583 + lib/Image/ExifTool/HtmlDump.pm | 909 + lib/Image/ExifTool/ICC_Profile.pm | 1287 + lib/Image/ExifTool/ID3.pm | 1580 + lib/Image/ExifTool/IPTC.pm | 1274 + lib/Image/ExifTool/ISO.pm | 206 + lib/Image/ExifTool/ITC.pm | 215 + lib/Image/ExifTool/Import.pm | 357 + lib/Image/ExifTool/InDesign.pm | 279 + lib/Image/ExifTool/JPEG.pm | 616 + lib/Image/ExifTool/JPEGDigest.pm | 2617 ++ lib/Image/ExifTool/JSON.pm | 142 + lib/Image/ExifTool/JVC.pm | 130 + lib/Image/ExifTool/Jpeg2000.pm | 898 + lib/Image/ExifTool/Kodak.pm | 3272 ++ lib/Image/ExifTool/KyoceraRaw.pm | 173 + lib/Image/ExifTool/LNK.pm | 723 + lib/Image/ExifTool/Lang/cs.pm | 1588 + lib/Image/ExifTool/Lang/de.pm | 8708 ++++ lib/Image/ExifTool/Lang/en_ca.pm | 1002 + lib/Image/ExifTool/Lang/en_gb.pm | 1045 + lib/Image/ExifTool/Lang/es.pm | 4021 ++ lib/Image/ExifTool/Lang/fi.pm | 2854 ++ lib/Image/ExifTool/Lang/fr.pm | 4767 +++ lib/Image/ExifTool/Lang/it.pm | 7918 ++++ lib/Image/ExifTool/Lang/ja.pm | 5846 +++ lib/Image/ExifTool/Lang/ko.pm | 2330 ++ lib/Image/ExifTool/Lang/nl.pm | 3222 ++ lib/Image/ExifTool/Lang/pl.pm | 1276 + lib/Image/ExifTool/Lang/ru.pm | 768 + lib/Image/ExifTool/Lang/sv.pm | 638 + lib/Image/ExifTool/Lang/tr.pm | 544 + lib/Image/ExifTool/Lang/zh_cn.pm | 1330 + lib/Image/ExifTool/Lang/zh_tw.pm | 801 + lib/Image/ExifTool/Leaf.pm | 517 + lib/Image/ExifTool/Lytro.pm | 213 + lib/Image/ExifTool/M2TS.pm | 730 + lib/Image/ExifTool/MIE.pm | 2568 ++ lib/Image/ExifTool/MIEUnits.pod | 377 + lib/Image/ExifTool/MIFF.pm | 279 + lib/Image/ExifTool/MNG.pm | 684 + lib/Image/ExifTool/MOI.pm | 158 + lib/Image/ExifTool/MPC.pm | 156 + lib/Image/ExifTool/MPEG.pm | 735 + lib/Image/ExifTool/MPF.pm | 288 + lib/Image/ExifTool/MWG.pm | 765 + lib/Image/ExifTool/MXF.pm | 3031 ++ lib/Image/ExifTool/MacOS.pm | 568 + lib/Image/ExifTool/MakerNotes.pm | 1818 + lib/Image/ExifTool/Matroska.pm | 933 + lib/Image/ExifTool/Microsoft.pm | 906 + lib/Image/ExifTool/Minolta.pm | 3048 ++ lib/Image/ExifTool/MinoltaRaw.pm | 535 + lib/Image/ExifTool/Motorola.pm | 62 + lib/Image/ExifTool/Nikon.pm | 9506 +++++ lib/Image/ExifTool/NikonCapture.pm | 940 + lib/Image/ExifTool/NikonCustom.pm | 9554 +++++ lib/Image/ExifTool/Nintendo.pm | 128 + lib/Image/ExifTool/OOXML.pm | 409 + lib/Image/ExifTool/Ogg.pm | 240 + lib/Image/ExifTool/Olympus.pm | 4037 ++ lib/Image/ExifTool/OpenEXR.pm | 323 + lib/Image/ExifTool/Opus.pm | 98 + lib/Image/ExifTool/PCX.pm | 138 + lib/Image/ExifTool/PDF.pm | 2380 ++ lib/Image/ExifTool/PGF.pm | 143 + lib/Image/ExifTool/PICT.pm | 1260 + lib/Image/ExifTool/PLIST.pm | 462 + lib/Image/ExifTool/PLUS.pm | 2607 ++ lib/Image/ExifTool/PNG.pm | 1471 + lib/Image/ExifTool/PPM.pm | 169 + lib/Image/ExifTool/PSP.pm | 306 + lib/Image/ExifTool/Palm.pm | 403 + lib/Image/ExifTool/Panasonic.pm | 2654 ++ lib/Image/ExifTool/PanasonicRaw.pm | 845 + lib/Image/ExifTool/Pentax.pm | 6268 +++ lib/Image/ExifTool/PhaseOne.pm | 731 + lib/Image/ExifTool/PhotoCD.pm | 506 + lib/Image/ExifTool/PhotoMechanic.pm | 256 + lib/Image/ExifTool/Photoshop.pm | 1157 + lib/Image/ExifTool/PostScript.pm | 724 + lib/Image/ExifTool/PrintIM.pm | 125 + lib/Image/ExifTool/Qualcomm.pm | 1344 + lib/Image/ExifTool/QuickTime.pm | 8094 ++++ lib/Image/ExifTool/QuickTimeStream.pl | 1697 + lib/Image/ExifTool/README | 1064 + lib/Image/ExifTool/RIFF.pm | 1745 + lib/Image/ExifTool/RSRC.pm | 241 + lib/Image/ExifTool/RTF.pm | 385 + lib/Image/ExifTool/Radiance.pm | 144 + lib/Image/ExifTool/Rawzor.pm | 190 + lib/Image/ExifTool/Real.pm | 739 + lib/Image/ExifTool/Reconyx.pm | 444 + lib/Image/ExifTool/Red.pm | 325 + lib/Image/ExifTool/Ricoh.pm | 1146 + lib/Image/ExifTool/Samsung.pm | 1342 + lib/Image/ExifTool/Sanyo.pm | 440 + lib/Image/ExifTool/Scalado.pm | 141 + lib/Image/ExifTool/Shift.pl | 625 + lib/Image/ExifTool/Shortcuts.pm | 344 + lib/Image/ExifTool/Sigma.pm | 772 + lib/Image/ExifTool/SigmaRaw.pm | 665 + lib/Image/ExifTool/Sony.pm | 10555 +++++ lib/Image/ExifTool/SonyIDC.pm | 393 + lib/Image/ExifTool/Stim.pm | 196 + lib/Image/ExifTool/TagInfoXML.pm | 830 + lib/Image/ExifTool/TagLookup.pm | 10946 +++++ lib/Image/ExifTool/TagNames.pod | 33624 ++++++++++++++++ lib/Image/ExifTool/Theora.pm | 145 + lib/Image/ExifTool/Torrent.pm | 317 + lib/Image/ExifTool/Unknown.pm | 66 + lib/Image/ExifTool/VCard.pm | 443 + lib/Image/ExifTool/Validate.pm | 626 + lib/Image/ExifTool/Vorbis.pm | 255 + lib/Image/ExifTool/WTV.pm | 319 + lib/Image/ExifTool/WriteCanonRaw.pl | 637 + lib/Image/ExifTool/WriteExif.pl | 2563 ++ lib/Image/ExifTool/WriteIPTC.pl | 728 + lib/Image/ExifTool/WritePDF.pl | 772 + lib/Image/ExifTool/WritePNG.pl | 408 + lib/Image/ExifTool/WritePhotoshop.pl | 266 + lib/Image/ExifTool/WritePostScript.pl | 772 + lib/Image/ExifTool/WriteQuickTime.pl | 384 + lib/Image/ExifTool/WriteXMP.pl | 1505 + lib/Image/ExifTool/Writer.pl | 6730 ++++ lib/Image/ExifTool/XMP.pm | 4041 ++ lib/Image/ExifTool/XMP2.pl | 1831 + lib/Image/ExifTool/XMPStruct.pl | 846 + lib/Image/ExifTool/ZIP.pm | 712 + lib/Image/ExifTool/iWork.pm | 230 + lib/Image/Size.pm | 982 + lib/JSON/PP.pm | 2 + lib/JSON/PP/Boolean.pm | 2 + lib/PDF/API2.pm | 1429 + lib/PDF/API2/Annotation.pm | 278 + lib/PDF/API2/Basic/PDF/Array.pm | 102 + lib/PDF/API2/Basic/PDF/Bool.pm | 35 + lib/PDF/API2/Basic/PDF/Dict.pm | 273 + lib/PDF/API2/Basic/PDF/File.pm | 1099 + lib/PDF/API2/Basic/PDF/Filter.pm | 68 + .../API2/Basic/PDF/Filter/ASCII85Decode.pm | 90 + .../API2/Basic/PDF/Filter/ASCIIHexDecode.pm | 60 + lib/PDF/API2/Basic/PDF/Filter/FlateDecode.pm | 152 + lib/PDF/API2/Basic/PDF/Filter/LZWDecode.pm | 99 + .../API2/Basic/PDF/Filter/RunLengthDecode.pm | 111 + lib/PDF/API2/Basic/PDF/Literal.pm | 89 + lib/PDF/API2/Basic/PDF/Name.pm | 84 + lib/PDF/API2/Basic/PDF/Null.pm | 65 + lib/PDF/API2/Basic/PDF/Number.pm | 35 + lib/PDF/API2/Basic/PDF/Objind.pm | 182 + lib/PDF/API2/Basic/PDF/Page.pm | 80 + lib/PDF/API2/Basic/PDF/Pages.pm | 356 + lib/PDF/API2/Basic/PDF/String.pm | 188 + lib/PDF/API2/Basic/PDF/Utils.pm | 96 + lib/PDF/API2/Content.pm | 1652 + lib/PDF/API2/Content/Text.pm | 19 + lib/PDF/API2/Matrix.pm | 74 + lib/PDF/API2/NamedDestination.pm | 179 + lib/PDF/API2/Outline.pm | 244 + lib/PDF/API2/Outlines.pm | 22 + lib/PDF/API2/Page.pm | 301 + lib/PDF/API2/Resource.pm | 64 + lib/PDF/API2/Resource/BaseFont.pm | 572 + lib/PDF/API2/Resource/CIDFont.pm | 328 + lib/PDF/API2/Resource/CIDFont/CJKFont.pm | 300 + lib/PDF/API2/Resource/CIDFont/TrueType.pm | 166 + .../Resource/CIDFont/TrueType/FontFile.pm | 682 + lib/PDF/API2/Resource/ColorSpace.pm | 66 + lib/PDF/API2/Resource/ColorSpace/DeviceN.pm | 88 + lib/PDF/API2/Resource/ColorSpace/Indexed.pm | 116 + .../Resource/ColorSpace/Indexed/ACTFile.pm | 51 + .../API2/Resource/ColorSpace/Indexed/Hue.pm | 53 + .../Resource/ColorSpace/Indexed/WebColor.pm | 61 + .../API2/Resource/ColorSpace/Separation.pm | 129 + lib/PDF/API2/Resource/Colors.pm | 697 + lib/PDF/API2/Resource/ExtGState.pm | 270 + lib/PDF/API2/Resource/Font.pm | 213 + lib/PDF/API2/Resource/Font/BdFont.pm | 205 + lib/PDF/API2/Resource/Font/CoreFont.pm | 297 + .../API2/Resource/Font/CoreFont/bankgothic.pm | 517 + .../API2/Resource/Font/CoreFont/courier.pm | 790 + .../Resource/Font/CoreFont/courierbold.pm | 520 + .../Font/CoreFont/courierboldoblique.pm | 520 + .../Resource/Font/CoreFont/courieroblique.pm | 520 + .../API2/Resource/Font/CoreFont/georgia.pm | 863 + .../Resource/Font/CoreFont/georgiabold.pm | 863 + .../Font/CoreFont/georgiabolditalic.pm | 863 + .../Resource/Font/CoreFont/georgiaitalic.pm | 863 + .../API2/Resource/Font/CoreFont/helvetica.pm | 520 + .../Resource/Font/CoreFont/helveticabold.pm | 520 + .../Font/CoreFont/helveticaboldoblique.pm | 519 + .../Font/CoreFont/helveticaoblique.pm | 519 + lib/PDF/API2/Resource/Font/CoreFont/symbol.pm | 481 + .../API2/Resource/Font/CoreFont/timesbold.pm | 520 + .../Resource/Font/CoreFont/timesbolditalic.pm | 519 + .../Resource/Font/CoreFont/timesitalic.pm | 521 + .../API2/Resource/Font/CoreFont/timesroman.pm | 606 + .../API2/Resource/Font/CoreFont/trebuchet.pm | 577 + .../Resource/Font/CoreFont/trebuchetbold.pm | 577 + .../Font/CoreFont/trebuchetbolditalic.pm | 635 + .../Resource/Font/CoreFont/trebuchetitalic.pm | 635 + .../API2/Resource/Font/CoreFont/verdana.pm | 844 + .../Resource/Font/CoreFont/verdanabold.pm | 848 + .../Font/CoreFont/verdanabolditalic.pm | 848 + .../Resource/Font/CoreFont/verdanaitalic.pm | 847 + .../API2/Resource/Font/CoreFont/webdings.pm | 770 + .../API2/Resource/Font/CoreFont/wingdings.pm | 512 + .../Resource/Font/CoreFont/zapfdingbats.pm | 494 + lib/PDF/API2/Resource/Font/Postscript.pm | 499 + lib/PDF/API2/Resource/Font/SynFont.pm | 197 + lib/PDF/API2/Resource/Glyphs.pm | 9782 +++++ lib/PDF/API2/Resource/PaperSizes.pm | 49 + lib/PDF/API2/Resource/Pattern.pm | 21 + lib/PDF/API2/Resource/Shading.pm | 12 + lib/PDF/API2/Resource/UniFont.pm | 229 + lib/PDF/API2/Resource/XObject.pm | 37 + lib/PDF/API2/Resource/XObject/Form.pm | 68 + lib/PDF/API2/Resource/XObject/Form/BarCode.pm | 174 + .../Resource/XObject/Form/BarCode/codabar.pm | 38 + .../Resource/XObject/Form/BarCode/code128.pm | 227 + .../Resource/XObject/Form/BarCode/code3of9.pm | 115 + .../Resource/XObject/Form/BarCode/ean13.pm | 80 + .../Resource/XObject/Form/BarCode/int2of5.pm | 64 + lib/PDF/API2/Resource/XObject/Form/Hybrid.pm | 60 + lib/PDF/API2/Resource/XObject/Image.pm | 98 + lib/PDF/API2/Resource/XObject/Image/GD.pm | 74 + lib/PDF/API2/Resource/XObject/Image/GIF.pm | 229 + lib/PDF/API2/Resource/XObject/Image/JPEG.pm | 99 + lib/PDF/API2/Resource/XObject/Image/PNG.pm | 694 + lib/PDF/API2/Resource/XObject/Image/PNM.pm | 187 + lib/PDF/API2/Resource/XObject/Image/TIFF.pm | 295 + .../API2/Resource/XObject/Image/TIFF/File.pm | 283 + lib/PDF/API2/Util.pm | 684 + lib/PDF/Table.pm | 942 + lib/URI/Encode.pm | 2 + tmpl/page/rendezvous.tt | 0 386 files changed, 364947 insertions(+), 5164 deletions(-) delete mode 100644 api/invoicetemplate.json create mode 100644 api/lib/report.pm create mode 100644 api/lib/sendemail.pm delete mode 100644 api/mailtemplate.txt create mode 100644 api/reports/DKS_JD190517-000002.pdf create mode 100644 api/reports/DKS_JD201905-000020.pdf create mode 100644 api/sql.log create mode 100644 lib/Font/TTF/Font.pm create mode 100644 lib/Font/TTF/Table.pm create mode 100644 lib/Font/TTF/Utils.pm create mode 100644 lib/Font/TTF/Woff.pm create mode 100644 lib/Font/TTF/Woff/MetaData.pm create mode 100644 lib/Font/TTF/Woff/PrivateData.pm create mode 100644 lib/IO/String.pm create mode 100644 lib/Image/ExifTool.pm create mode 100644 lib/Image/ExifTool.pod create mode 100644 lib/Image/ExifTool/AES.pm create mode 100644 lib/Image/ExifTool/AFCP.pm create mode 100644 lib/Image/ExifTool/AIFF.pm create mode 100644 lib/Image/ExifTool/APE.pm create mode 100644 lib/Image/ExifTool/APP12.pm create mode 100644 lib/Image/ExifTool/ASF.pm create mode 100644 lib/Image/ExifTool/Apple.pm create mode 100644 lib/Image/ExifTool/Audible.pm create mode 100644 lib/Image/ExifTool/BMP.pm create mode 100644 lib/Image/ExifTool/BPG.pm create mode 100644 lib/Image/ExifTool/BZZ.pm create mode 100644 lib/Image/ExifTool/BigTIFF.pm create mode 100644 lib/Image/ExifTool/BuildTagLookup.pm create mode 100644 lib/Image/ExifTool/Canon.pm create mode 100644 lib/Image/ExifTool/CanonCustom.pm create mode 100644 lib/Image/ExifTool/CanonRaw.pm create mode 100644 lib/Image/ExifTool/CanonVRD.pm create mode 100644 lib/Image/ExifTool/CaptureOne.pm create mode 100644 lib/Image/ExifTool/Casio.pm create mode 100644 lib/Image/ExifTool/Charset.pm create mode 100644 lib/Image/ExifTool/Charset/Arabic.pm create mode 100644 lib/Image/ExifTool/Charset/Baltic.pm create mode 100644 lib/Image/ExifTool/Charset/Cyrillic.pm create mode 100644 lib/Image/ExifTool/Charset/DOSLatin1.pm create mode 100644 lib/Image/ExifTool/Charset/DOSLatinUS.pm create mode 100644 lib/Image/ExifTool/Charset/Greek.pm create mode 100644 lib/Image/ExifTool/Charset/Hebrew.pm create mode 100644 lib/Image/ExifTool/Charset/JIS.pm create mode 100644 lib/Image/ExifTool/Charset/Latin.pm create mode 100644 lib/Image/ExifTool/Charset/Latin2.pm create mode 100644 lib/Image/ExifTool/Charset/MacArabic.pm create mode 100644 lib/Image/ExifTool/Charset/MacChineseCN.pm create mode 100644 lib/Image/ExifTool/Charset/MacChineseTW.pm create mode 100644 lib/Image/ExifTool/Charset/MacCroatian.pm create mode 100644 lib/Image/ExifTool/Charset/MacCyrillic.pm create mode 100644 lib/Image/ExifTool/Charset/MacGreek.pm create mode 100644 lib/Image/ExifTool/Charset/MacHebrew.pm create mode 100644 lib/Image/ExifTool/Charset/MacIceland.pm create mode 100644 lib/Image/ExifTool/Charset/MacJapanese.pm create mode 100644 lib/Image/ExifTool/Charset/MacKorean.pm create mode 100644 lib/Image/ExifTool/Charset/MacLatin2.pm create mode 100644 lib/Image/ExifTool/Charset/MacRSymbol.pm create mode 100644 lib/Image/ExifTool/Charset/MacRoman.pm create mode 100644 lib/Image/ExifTool/Charset/MacRomanian.pm create mode 100644 lib/Image/ExifTool/Charset/MacThai.pm create mode 100644 lib/Image/ExifTool/Charset/MacTurkish.pm create mode 100644 lib/Image/ExifTool/Charset/PDFDoc.pm create mode 100644 lib/Image/ExifTool/Charset/ShiftJIS.pm create mode 100644 lib/Image/ExifTool/Charset/Symbol.pm create mode 100644 lib/Image/ExifTool/Charset/Thai.pm create mode 100644 lib/Image/ExifTool/Charset/Turkish.pm create mode 100644 lib/Image/ExifTool/Charset/Vietnam.pm create mode 100644 lib/Image/ExifTool/DICOM.pm create mode 100644 lib/Image/ExifTool/DJI.pm create mode 100644 lib/Image/ExifTool/DNG.pm create mode 100644 lib/Image/ExifTool/DPX.pm create mode 100644 lib/Image/ExifTool/DV.pm create mode 100644 lib/Image/ExifTool/DarwinCore.pm create mode 100644 lib/Image/ExifTool/DjVu.pm create mode 100644 lib/Image/ExifTool/EXE.pm create mode 100644 lib/Image/ExifTool/Exif.pm create mode 100644 lib/Image/ExifTool/FLAC.pm create mode 100644 lib/Image/ExifTool/FLIF.pm create mode 100644 lib/Image/ExifTool/FLIR.pm create mode 100644 lib/Image/ExifTool/Fixup.pm create mode 100644 lib/Image/ExifTool/Flash.pm create mode 100644 lib/Image/ExifTool/FlashPix.pm create mode 100644 lib/Image/ExifTool/Font.pm create mode 100644 lib/Image/ExifTool/FotoStation.pm create mode 100644 lib/Image/ExifTool/FujiFilm.pm create mode 100644 lib/Image/ExifTool/GE.pm create mode 100644 lib/Image/ExifTool/GIF.pm create mode 100644 lib/Image/ExifTool/GIMP.pm create mode 100644 lib/Image/ExifTool/GPS.pm create mode 100644 lib/Image/ExifTool/GeoTiff.pm create mode 100644 lib/Image/ExifTool/Geotag.pm create mode 100644 lib/Image/ExifTool/GoPro.pm create mode 100644 lib/Image/ExifTool/H264.pm create mode 100644 lib/Image/ExifTool/HP.pm create mode 100644 lib/Image/ExifTool/HTML.pm create mode 100644 lib/Image/ExifTool/HtmlDump.pm create mode 100644 lib/Image/ExifTool/ICC_Profile.pm create mode 100644 lib/Image/ExifTool/ID3.pm create mode 100644 lib/Image/ExifTool/IPTC.pm create mode 100644 lib/Image/ExifTool/ISO.pm create mode 100644 lib/Image/ExifTool/ITC.pm create mode 100644 lib/Image/ExifTool/Import.pm create mode 100644 lib/Image/ExifTool/InDesign.pm create mode 100644 lib/Image/ExifTool/JPEG.pm create mode 100644 lib/Image/ExifTool/JPEGDigest.pm create mode 100644 lib/Image/ExifTool/JSON.pm create mode 100644 lib/Image/ExifTool/JVC.pm create mode 100644 lib/Image/ExifTool/Jpeg2000.pm create mode 100644 lib/Image/ExifTool/Kodak.pm create mode 100644 lib/Image/ExifTool/KyoceraRaw.pm create mode 100644 lib/Image/ExifTool/LNK.pm create mode 100644 lib/Image/ExifTool/Lang/cs.pm create mode 100644 lib/Image/ExifTool/Lang/de.pm create mode 100644 lib/Image/ExifTool/Lang/en_ca.pm create mode 100644 lib/Image/ExifTool/Lang/en_gb.pm create mode 100644 lib/Image/ExifTool/Lang/es.pm create mode 100644 lib/Image/ExifTool/Lang/fi.pm create mode 100644 lib/Image/ExifTool/Lang/fr.pm create mode 100644 lib/Image/ExifTool/Lang/it.pm create mode 100644 lib/Image/ExifTool/Lang/ja.pm create mode 100644 lib/Image/ExifTool/Lang/ko.pm create mode 100644 lib/Image/ExifTool/Lang/nl.pm create mode 100644 lib/Image/ExifTool/Lang/pl.pm create mode 100644 lib/Image/ExifTool/Lang/ru.pm create mode 100644 lib/Image/ExifTool/Lang/sv.pm create mode 100644 lib/Image/ExifTool/Lang/tr.pm create mode 100644 lib/Image/ExifTool/Lang/zh_cn.pm create mode 100644 lib/Image/ExifTool/Lang/zh_tw.pm create mode 100644 lib/Image/ExifTool/Leaf.pm create mode 100644 lib/Image/ExifTool/Lytro.pm create mode 100644 lib/Image/ExifTool/M2TS.pm create mode 100644 lib/Image/ExifTool/MIE.pm create mode 100644 lib/Image/ExifTool/MIEUnits.pod create mode 100644 lib/Image/ExifTool/MIFF.pm create mode 100644 lib/Image/ExifTool/MNG.pm create mode 100644 lib/Image/ExifTool/MOI.pm create mode 100644 lib/Image/ExifTool/MPC.pm create mode 100644 lib/Image/ExifTool/MPEG.pm create mode 100644 lib/Image/ExifTool/MPF.pm create mode 100644 lib/Image/ExifTool/MWG.pm create mode 100644 lib/Image/ExifTool/MXF.pm create mode 100644 lib/Image/ExifTool/MacOS.pm create mode 100644 lib/Image/ExifTool/MakerNotes.pm create mode 100644 lib/Image/ExifTool/Matroska.pm create mode 100644 lib/Image/ExifTool/Microsoft.pm create mode 100644 lib/Image/ExifTool/Minolta.pm create mode 100644 lib/Image/ExifTool/MinoltaRaw.pm create mode 100644 lib/Image/ExifTool/Motorola.pm create mode 100644 lib/Image/ExifTool/Nikon.pm create mode 100644 lib/Image/ExifTool/NikonCapture.pm create mode 100644 lib/Image/ExifTool/NikonCustom.pm create mode 100644 lib/Image/ExifTool/Nintendo.pm create mode 100644 lib/Image/ExifTool/OOXML.pm create mode 100644 lib/Image/ExifTool/Ogg.pm create mode 100644 lib/Image/ExifTool/Olympus.pm create mode 100644 lib/Image/ExifTool/OpenEXR.pm create mode 100644 lib/Image/ExifTool/Opus.pm create mode 100644 lib/Image/ExifTool/PCX.pm create mode 100644 lib/Image/ExifTool/PDF.pm create mode 100644 lib/Image/ExifTool/PGF.pm create mode 100644 lib/Image/ExifTool/PICT.pm create mode 100644 lib/Image/ExifTool/PLIST.pm create mode 100644 lib/Image/ExifTool/PLUS.pm create mode 100644 lib/Image/ExifTool/PNG.pm create mode 100644 lib/Image/ExifTool/PPM.pm create mode 100644 lib/Image/ExifTool/PSP.pm create mode 100644 lib/Image/ExifTool/Palm.pm create mode 100644 lib/Image/ExifTool/Panasonic.pm create mode 100644 lib/Image/ExifTool/PanasonicRaw.pm create mode 100644 lib/Image/ExifTool/Pentax.pm create mode 100644 lib/Image/ExifTool/PhaseOne.pm create mode 100644 lib/Image/ExifTool/PhotoCD.pm create mode 100644 lib/Image/ExifTool/PhotoMechanic.pm create mode 100644 lib/Image/ExifTool/Photoshop.pm create mode 100644 lib/Image/ExifTool/PostScript.pm create mode 100644 lib/Image/ExifTool/PrintIM.pm create mode 100644 lib/Image/ExifTool/Qualcomm.pm create mode 100644 lib/Image/ExifTool/QuickTime.pm create mode 100644 lib/Image/ExifTool/QuickTimeStream.pl create mode 100644 lib/Image/ExifTool/README create mode 100644 lib/Image/ExifTool/RIFF.pm create mode 100644 lib/Image/ExifTool/RSRC.pm create mode 100644 lib/Image/ExifTool/RTF.pm create mode 100644 lib/Image/ExifTool/Radiance.pm create mode 100644 lib/Image/ExifTool/Rawzor.pm create mode 100644 lib/Image/ExifTool/Real.pm create mode 100644 lib/Image/ExifTool/Reconyx.pm create mode 100644 lib/Image/ExifTool/Red.pm create mode 100644 lib/Image/ExifTool/Ricoh.pm create mode 100644 lib/Image/ExifTool/Samsung.pm create mode 100644 lib/Image/ExifTool/Sanyo.pm create mode 100644 lib/Image/ExifTool/Scalado.pm create mode 100644 lib/Image/ExifTool/Shift.pl create mode 100644 lib/Image/ExifTool/Shortcuts.pm create mode 100644 lib/Image/ExifTool/Sigma.pm create mode 100644 lib/Image/ExifTool/SigmaRaw.pm create mode 100644 lib/Image/ExifTool/Sony.pm create mode 100644 lib/Image/ExifTool/SonyIDC.pm create mode 100644 lib/Image/ExifTool/Stim.pm create mode 100644 lib/Image/ExifTool/TagInfoXML.pm create mode 100644 lib/Image/ExifTool/TagLookup.pm create mode 100644 lib/Image/ExifTool/TagNames.pod create mode 100644 lib/Image/ExifTool/Theora.pm create mode 100644 lib/Image/ExifTool/Torrent.pm create mode 100644 lib/Image/ExifTool/Unknown.pm create mode 100644 lib/Image/ExifTool/VCard.pm create mode 100644 lib/Image/ExifTool/Validate.pm create mode 100644 lib/Image/ExifTool/Vorbis.pm create mode 100644 lib/Image/ExifTool/WTV.pm create mode 100644 lib/Image/ExifTool/WriteCanonRaw.pl create mode 100644 lib/Image/ExifTool/WriteExif.pl create mode 100644 lib/Image/ExifTool/WriteIPTC.pl create mode 100644 lib/Image/ExifTool/WritePDF.pl create mode 100644 lib/Image/ExifTool/WritePNG.pl create mode 100644 lib/Image/ExifTool/WritePhotoshop.pl create mode 100644 lib/Image/ExifTool/WritePostScript.pl create mode 100644 lib/Image/ExifTool/WriteQuickTime.pl create mode 100644 lib/Image/ExifTool/WriteXMP.pl create mode 100644 lib/Image/ExifTool/Writer.pl create mode 100644 lib/Image/ExifTool/XMP.pm create mode 100644 lib/Image/ExifTool/XMP2.pl create mode 100644 lib/Image/ExifTool/XMPStruct.pl create mode 100644 lib/Image/ExifTool/ZIP.pm create mode 100644 lib/Image/ExifTool/iWork.pm create mode 100644 lib/Image/Size.pm create mode 100644 lib/PDF/API2.pm create mode 100644 lib/PDF/API2/Annotation.pm create mode 100644 lib/PDF/API2/Basic/PDF/Array.pm create mode 100644 lib/PDF/API2/Basic/PDF/Bool.pm create mode 100644 lib/PDF/API2/Basic/PDF/Dict.pm create mode 100644 lib/PDF/API2/Basic/PDF/File.pm create mode 100644 lib/PDF/API2/Basic/PDF/Filter.pm create mode 100644 lib/PDF/API2/Basic/PDF/Filter/ASCII85Decode.pm create mode 100644 lib/PDF/API2/Basic/PDF/Filter/ASCIIHexDecode.pm create mode 100644 lib/PDF/API2/Basic/PDF/Filter/FlateDecode.pm create mode 100644 lib/PDF/API2/Basic/PDF/Filter/LZWDecode.pm create mode 100644 lib/PDF/API2/Basic/PDF/Filter/RunLengthDecode.pm create mode 100644 lib/PDF/API2/Basic/PDF/Literal.pm create mode 100644 lib/PDF/API2/Basic/PDF/Name.pm create mode 100644 lib/PDF/API2/Basic/PDF/Null.pm create mode 100644 lib/PDF/API2/Basic/PDF/Number.pm create mode 100644 lib/PDF/API2/Basic/PDF/Objind.pm create mode 100644 lib/PDF/API2/Basic/PDF/Page.pm create mode 100644 lib/PDF/API2/Basic/PDF/Pages.pm create mode 100644 lib/PDF/API2/Basic/PDF/String.pm create mode 100644 lib/PDF/API2/Basic/PDF/Utils.pm create mode 100644 lib/PDF/API2/Content.pm create mode 100644 lib/PDF/API2/Content/Text.pm create mode 100644 lib/PDF/API2/Matrix.pm create mode 100644 lib/PDF/API2/NamedDestination.pm create mode 100644 lib/PDF/API2/Outline.pm create mode 100644 lib/PDF/API2/Outlines.pm create mode 100644 lib/PDF/API2/Page.pm create mode 100644 lib/PDF/API2/Resource.pm create mode 100644 lib/PDF/API2/Resource/BaseFont.pm create mode 100644 lib/PDF/API2/Resource/CIDFont.pm create mode 100644 lib/PDF/API2/Resource/CIDFont/CJKFont.pm create mode 100644 lib/PDF/API2/Resource/CIDFont/TrueType.pm create mode 100644 lib/PDF/API2/Resource/CIDFont/TrueType/FontFile.pm create mode 100644 lib/PDF/API2/Resource/ColorSpace.pm create mode 100644 lib/PDF/API2/Resource/ColorSpace/DeviceN.pm create mode 100644 lib/PDF/API2/Resource/ColorSpace/Indexed.pm create mode 100644 lib/PDF/API2/Resource/ColorSpace/Indexed/ACTFile.pm create mode 100644 lib/PDF/API2/Resource/ColorSpace/Indexed/Hue.pm create mode 100644 lib/PDF/API2/Resource/ColorSpace/Indexed/WebColor.pm create mode 100644 lib/PDF/API2/Resource/ColorSpace/Separation.pm create mode 100644 lib/PDF/API2/Resource/Colors.pm create mode 100644 lib/PDF/API2/Resource/ExtGState.pm create mode 100644 lib/PDF/API2/Resource/Font.pm create mode 100644 lib/PDF/API2/Resource/Font/BdFont.pm create mode 100644 lib/PDF/API2/Resource/Font/CoreFont.pm create mode 100644 lib/PDF/API2/Resource/Font/CoreFont/bankgothic.pm create mode 100644 lib/PDF/API2/Resource/Font/CoreFont/courier.pm create mode 100644 lib/PDF/API2/Resource/Font/CoreFont/courierbold.pm create mode 100644 lib/PDF/API2/Resource/Font/CoreFont/courierboldoblique.pm create mode 100644 lib/PDF/API2/Resource/Font/CoreFont/courieroblique.pm create mode 100644 lib/PDF/API2/Resource/Font/CoreFont/georgia.pm create mode 100644 lib/PDF/API2/Resource/Font/CoreFont/georgiabold.pm create mode 100644 lib/PDF/API2/Resource/Font/CoreFont/georgiabolditalic.pm create mode 100644 lib/PDF/API2/Resource/Font/CoreFont/georgiaitalic.pm create mode 100644 lib/PDF/API2/Resource/Font/CoreFont/helvetica.pm create mode 100644 lib/PDF/API2/Resource/Font/CoreFont/helveticabold.pm create mode 100644 lib/PDF/API2/Resource/Font/CoreFont/helveticaboldoblique.pm create mode 100644 lib/PDF/API2/Resource/Font/CoreFont/helveticaoblique.pm create mode 100644 lib/PDF/API2/Resource/Font/CoreFont/symbol.pm create mode 100644 lib/PDF/API2/Resource/Font/CoreFont/timesbold.pm create mode 100644 lib/PDF/API2/Resource/Font/CoreFont/timesbolditalic.pm create mode 100644 lib/PDF/API2/Resource/Font/CoreFont/timesitalic.pm create mode 100644 lib/PDF/API2/Resource/Font/CoreFont/timesroman.pm create mode 100644 lib/PDF/API2/Resource/Font/CoreFont/trebuchet.pm create mode 100644 lib/PDF/API2/Resource/Font/CoreFont/trebuchetbold.pm create mode 100644 lib/PDF/API2/Resource/Font/CoreFont/trebuchetbolditalic.pm create mode 100644 lib/PDF/API2/Resource/Font/CoreFont/trebuchetitalic.pm create mode 100644 lib/PDF/API2/Resource/Font/CoreFont/verdana.pm create mode 100644 lib/PDF/API2/Resource/Font/CoreFont/verdanabold.pm create mode 100644 lib/PDF/API2/Resource/Font/CoreFont/verdanabolditalic.pm create mode 100644 lib/PDF/API2/Resource/Font/CoreFont/verdanaitalic.pm create mode 100644 lib/PDF/API2/Resource/Font/CoreFont/webdings.pm create mode 100644 lib/PDF/API2/Resource/Font/CoreFont/wingdings.pm create mode 100644 lib/PDF/API2/Resource/Font/CoreFont/zapfdingbats.pm create mode 100644 lib/PDF/API2/Resource/Font/Postscript.pm create mode 100644 lib/PDF/API2/Resource/Font/SynFont.pm create mode 100644 lib/PDF/API2/Resource/Glyphs.pm create mode 100644 lib/PDF/API2/Resource/PaperSizes.pm create mode 100644 lib/PDF/API2/Resource/Pattern.pm create mode 100644 lib/PDF/API2/Resource/Shading.pm create mode 100644 lib/PDF/API2/Resource/UniFont.pm create mode 100644 lib/PDF/API2/Resource/XObject.pm create mode 100644 lib/PDF/API2/Resource/XObject/Form.pm create mode 100644 lib/PDF/API2/Resource/XObject/Form/BarCode.pm create mode 100644 lib/PDF/API2/Resource/XObject/Form/BarCode/codabar.pm create mode 100644 lib/PDF/API2/Resource/XObject/Form/BarCode/code128.pm create mode 100644 lib/PDF/API2/Resource/XObject/Form/BarCode/code3of9.pm create mode 100644 lib/PDF/API2/Resource/XObject/Form/BarCode/ean13.pm create mode 100644 lib/PDF/API2/Resource/XObject/Form/BarCode/int2of5.pm create mode 100644 lib/PDF/API2/Resource/XObject/Form/Hybrid.pm create mode 100644 lib/PDF/API2/Resource/XObject/Image.pm create mode 100644 lib/PDF/API2/Resource/XObject/Image/GD.pm create mode 100644 lib/PDF/API2/Resource/XObject/Image/GIF.pm create mode 100644 lib/PDF/API2/Resource/XObject/Image/JPEG.pm create mode 100644 lib/PDF/API2/Resource/XObject/Image/PNG.pm create mode 100644 lib/PDF/API2/Resource/XObject/Image/PNM.pm create mode 100644 lib/PDF/API2/Resource/XObject/Image/TIFF.pm create mode 100644 lib/PDF/API2/Resource/XObject/Image/TIFF/File.pm create mode 100644 lib/PDF/API2/Util.pm create mode 100644 lib/PDF/Table.pm create mode 100644 tmpl/page/rendezvous.tt diff --git a/api/invoicetemplate.json b/api/invoicetemplate.json deleted file mode 100644 index 421cadf..0000000 --- a/api/invoicetemplate.json +++ /dev/null @@ -1,50 +0,0 @@ -{ - "section":{ - "13headerimg":{"x":50,"y":755,"width":160,"type":"image"}, - "02headerline":{"type":"line","color":"black","width":1,"start":{"x":50,"y":753},"end":{"x":285,"y":753}}, - "03dkstext":{"type":"text","align":"center","font":{"name":"Helvetica","size":9},"x":200,"y":743}, - "04dksfooter":{"type":"text","align":"center","font":{"name":"Helvetica","size":10},"x":297.5,"y":25,"lineheight":15}, - "05adrline":{"type":"line","color":"black","width":1,"start":{"x":52,"y":662},"end":{"x":280,"y":662}}, - "06header_right":{"type":"text","align":"right","font":{"name":"Helvetica","size":11},"x":550,"y":820,"lineheight":14}, - "07reporttype":{"type":"text","align":"right","font":{"name":"HelveticaBold","size":30},"x":550,"y":704,"lineheight":14}, - "08tbladdress":{"type":"table","x":"50","w":"230","font":"Helvetica","font_size":"11","start_y":"680","start_h":"620","next_y":"750","next_h":"500","padding":"2","padding_bottom":"3","padding_top":"3","padding_right":"5","column_props":[{ "min_w":"200", "max_w":"200", "justify":"left" }],"header_props":[{ "font_size":"11", "font":"HelveticaBold", "bg_color":"white", "font_color":"black", "repeat":"1", "justify":"left" }],"border":"0"}, - "09tblinvoicedata":{"type":"table","x":"390","w":"175","font":"Helvetica","font_size":"11","start_y":"680","start_h":"620","next_y":"750","next_h":"500","padding":"2","padding_bottom":"3","padding_top":"3","padding_right":"5","column_props":[ { "min_w":"70","max_w":"70","justify":"left" },{ "min_w":"90","max_w":"90","justify":"left","font":"HelveticaBold" } ],"border":"0"}, - "10tblproductdata":{"type":"table","x":"50","w":"500","font":"Helvetica","font_size":"11","start_y":"570","start_h":"300","next_y":"750","next_h":"500","padding":"2","padding_left":"5","padding_bottom":"10","padding_top":"5","padding_right":"5","header_props":[{"font_size":"11","font":"HelveticaBold","bg_color":"#e6e6e6","font_color":"black","repeat":"1","justify":"center" }],"column_props":[ { },{ "min_w":"40","max_w":"40","justify":"right" },{ "min_w":"20","max_w":"20","justify":"right" },{ "min_w":"50","max_w":"50","justify":"right","font":"Helvetica" } ],"border":"0.5"}, - "11totalsums":{"type":"table","x":"349.5","w":"201","font":"Helvetica","font_size":"11","start_y":"%%10tblproductdata:y%%","start_h":"150","next_y":"750","next_h":"500","padding":"2","padding_left":"5","padding_bottom":"10","padding_top":"5","padding_right":"5","column_props":[ { "justify":"right" },{ "min_w":"70","max_w":"70","justify":"right","font":"HelveticaBold" } ],"border":"0.5"}, - "12payementnote":{"type":"text","align":"left","font":{"name":"Helvetica","size":12},"x":50,"y":"%%11totalsums:y%%","lineheight":15} - }, - "data":{"fr":{ - "13headerimg":{"src":"dks_1000.png"}, - "03dkstext":{"text":["Database Knowledge Solutions - Simplify IT!"]}, - "04dksfooter":{"text":["DKS, Société à responsabilité limitée, RC Luxembourg,B168572 - TVA: LU 2537 5617 - No. Aut: 10024550 / 0","IBAN: LU25 0020 1100 2783 8700; BIC: BILLLULL"]}, - "06header_right":{"text":["DKS s.à r.l.","8b, rue du Moulin","6914 Roodt/Syre","Tel: +352 691 504574","info@dks.lu / www.dks.lu"]}, - "08tbladdress":{"text":[ ["À:"], ["%%RECIPIENT%%"], ["%%ADDRESS%%"], ["%%COUNTRYSHORT%%-%%ZIP%% %%CITY%%"] ]}, - "07reporttype":{"text":["Facture"]}, - "09tblinvoicedata":{"text":[ ["NO. Facture","%%REFERENCE%%"], ["Date","%%INVOICEDATE%%"], ["Échéance","%%REMINDERDATE%%"], ["No Client","%%CLIENTNUMBER%%"] ]}, - "10tblproductdata":{"text":[ ["Produit", "Quantité","Prix Unitaire","Prix Net"],["%%PRODUCTLIST:START%%"], ["%%PRODUCT%%", "%%QUANTITY%% %%UNIT%%","%%UNITAMOUNT%% %%CURRENCY%%","%%NETAMOUNT%% %%CURRENCY%%"],["%%PRODUCTLIST:END%%"] ]}, - "11totalsums":{"text":[ ["Total Net :","%%SUMNETAMOUNT%% %%CURRENCY%%"], ["TVA (%%VATPERCENT%%%) :","%%SUMVATAMOUNT%% %%CURRENCY%%"], ["Total à payer:","%%SUMGROSSAMOUNT%% %%CURRENCY%%"] ]}, - "12payementnote":{"text":["nous vous prions de verser le montant à payer","au compte courrant LU25 0020 1100 2783 8700","avec le message: %%REFERENCE%%"]} - },"de":{ - "13headerimg":{"src":"dks_1000.png"}, - "03dkstext":{"text":["Database Knowledge Solutions - Simplify IT!"]}, - "04dksfooter":{"text":["DKS, Société à responsabilité limitée, RC Luxembourg,B168572 - TVA: LU 2537 5617 - No. Aut: 10024550 / 0","IBAN: LU25 0020 1100 2783 8700; BIC: BILLLULL"]}, - "06header_right":{"text":["DKS s.à r.l.","8b, rue du Moulin","6914 Roodt/Syre","Tel: +352 691 504574","info@dks.lu / www.dks.lu"]}, - "08tbladdress":{"text":[ ["An:"], ["%%RECIPIENT%%"], ["%%ADDRESS%%"], ["%%COUNTRYSHORT%%-%%ZIP%% %%CITY%%"] ]}, - "07reporttype":{"text":["Rechnung"]}, - "09tblinvoicedata":{"text":[ ["Rechnungs-Nr.","%%REFERENCE%%"], ["Datum","%%INVOICEDATE%%"], ["Fälligkeit","%%REMINDERDATE%%"], ["Kunden-Nr.","%%CLIENTNUMBER%%"], ["Ust-Id","%%VATID%%"] ]}, - "10tblproductdata":{"text":[ ["Produkt", "Anzahl","EinzelPreis","Netto-Preis"], ["%%PRODUCT%%", "%%QUANTITY%% %%UNIT%%","%%UNITAMOUNT%% %%CURRENCY%%","%%NETAMOUNT%% %%CURRENCY%%"] ]}, - "11totalsums":{"text":[ ["Gesamt Netto :","%%SUMNETAMOUNT%% %%CURRENCY%%"], ["MwSt. (%%VATPERCENT%%%) :","%%SUMVATAMOUNT%% %%CURRENCY%%€"], ["Gesamt Brutto :","%%SUMGROSSAMOUNT%% %%CURRENCY%%"] ]} - },"en":{ - "13headerimg":{"src":"dks_1000.png"}, - "03dkstext":{"text":["Database Knowledge Solutions - Simplify IT!"]}, - "04dksfooter":{"text":["DKS, Société à responsabilité limitée, RC Luxembourg,B168572 - TVA: LU 2537 5617 - No. Aut: 10024550 / 0","IBAN: LU25 0020 1100 2783 8700; BIC: BILLLULL"]}, - "06header_right":{"text":["DKS s.à r.l.","8b, rue du Moulin","6914 Roodt/Syre","Tel: +352 691 504574","info@dks.lu / www.dks.lu"]}, - "08tbladdress":{"text":[ ["To:"],["%%RECIPIENT%%"], ["%%ADDRESS%%"], ["%%COUNTRYSHORT%%-%%ZIP%% %%CITY%%"] ]}, - "07reporttype":{"text":["Invoice"]}, - "09tblinvoicedata":{"text":[ ["Reference.","%%REFERENCE%%"], ["Date","%%INVOICEDATE%%"], ["Due Date","%%REMINDERDATE%"], ["Client-Id","%%CLIENTNUMBER%%"], ["VAT-Id","%%VATID%%"] ]}, - "10tblproductdata":{"text":[ ["Product", "Quantity","Unit Amount","Net Amount"], ["%%PRODUCT%%", "%%QUANTITY%% %%UNIT%%","%%UNITAMOUNT%% %%CURRENCY%%","%%NETAMOUNT%% %%CURRENCY%%"] ]}, - "11totalsums":{"text":[ ["Net Total :","%%SUMNETAMOUNT%% %%CURRENCY%%"], ["VAT (%%VATPERCENT%%%) :","%%SUMVATAMOUNT%% %%CURRENCY%%€"], ["Total to Pay:","%%SUMGROSSAMOUNT%% %%CURRENCY%%"] ] - } - } -} -} \ No newline at end of file diff --git a/api/lib/pgsql.pm b/api/lib/pgsql.pm index 8f83bce..bbe572a 100644 --- a/api/lib/pgsql.pm +++ b/api/lib/pgsql.pm @@ -78,17 +78,17 @@ sub dbquery(){ sub dbquerysorted(){ my $self = shift; my $stat = shift; - my $vw_info = shift; + # my $vw_info = shift; my $retdata; my $dbh = DBI->connect('DBI:'.$self->{dbtype}.':dbname='.$self->{dbname}.';host='.$self->{dbhost},$self->{dbuser},$self->{dbpassword},{PrintError=>0,RaiseError=>0,AutoCommit=>1}) or return $retdata->{error} = "dbquery Connection Error!".$!; $stat = encode("utf8", $stat); - # open FILE,">>sql.log"; - # print FILE "\n==\n$stat\n==\n"; - # close FILE; + open FILE,">>sql.log"; + print FILE "\n==\n$stat\n==\n"; + close FILE; my $sth = $dbh->prepare($stat); - $sth->execute() or return $retdata->{error} = "dbquery: ".$sth->errstr; + $sth->execute() or return $retdata->{error} = "dbquerysorted: ".$sth->errstr; my $count = 0; while(my $data = $sth->fetchrow_hashref()) diff --git a/api/lib/report.pm b/api/lib/report.pm new file mode 100644 index 0000000..8bf4e3e --- /dev/null +++ b/api/lib/report.pm @@ -0,0 +1,243 @@ +package report; + +use strict; +use File::Basename; +use Getopt::Long; +use utf8; + +use Image::Size; +use lib ('./lib'); +use lib ('.'); +use pgsql; +use PDF::API2; +use PDF::Table; +use JSON::PP qw/encode_json decode_json/; +use Encode; + +sub new { + my $class = shift; + my $self = bless {}, $class; + $self->{db} = pgsql->new(); + $self->{endpoints} = (); + return $self; +} + +sub generatepdf(){ + my $self = shift; + my $dataid = shift; + my $datatable = shift; + my $datafield =shift; + my $pdfnamefield = shift; + my $report = shift; + my $lang = shift; + my $outpath= shift; + + my $strpdfdata =""; + my $db = pgsql->new(); + my $templatedata = $db->dbquerysorted("select report,structure,data_".$lang." from reporttemplates where report='".$report."';"); + if (keys(%{$templatedata}) > 0){ + $templatedata = $templatedata->{0}; + } + my $filldata = $db->dbquerysorted("select ".$datafield.",".$pdfnamefield." from ".$datatable." where id='".$dataid."';"); + if (keys(%{$filldata}) > 0){ + $filldata = $filldata->{0}; + } + my $xindata = ""; + my $pdfout = $outpath.'/'.$filldata->{$pdfnamefield}; + $self->{endpoints} = (); + if (-e $pdfout){ + unlink($pdfout); + } + # print "Test get Template!\n"; + + my $pdfdata->{section} = decode_json($templatedata->{structure}); + $filldata->{$datafield} = encode("utf-8",$filldata->{$datafield}); + $filldata->{$datafield} =~ s/"(\d+)\.(\d+)"/"$1,$2"/g; + $pdfdata->{data} = $self->mergedata($templatedata->{"data_".$lang},decode_json($filldata->{$datafield})); + + my $pdf = PDF::API2->new(); + $pdf->preferences({-fitwindow => 1}); + # print "Start PDF creation!
"; + my $page = $pdf->page(); + $page->mediabox('A4'); + foreach my $s (sort keys(%{$pdfdata->{section}})){ + $self->{endpoints}->{$s} = {final_y => '', lastpage => 1,pages => 1}; + if ($pdfdata->{section}->{$s}->{type} eq "image"){ + # print "Add Image $s
"; + $self->{endpoints}->{$s}->{y} = $self->addimage($pdf,$page,$pdfdata->{section}->{$s},$pdfdata->{data}->{$s}); + } elsif ($pdfdata->{section}->{$s}->{type} eq "line"){ + # print "Add Line $s
"; + $self->{endpoints}->{$s}->{y} = $self->addline($page,$pdfdata->{section}->{$s}); + } elsif ($pdfdata->{section}->{$s}->{type} eq "text"){ + # print "Add Text $s
"; + $self->{endpoints}->{$s}->{y} = $self->addtext($pdf,$page,$pdfdata->{section}->{$s},$pdfdata->{data}->{$s}); + } elsif ($pdfdata->{section}->{$s}->{type} eq "table"){ + # print "Add Table $s
"; + ($self->{endpoints}->{$s}->{lastpage}, $self->{endpoints}->{$s}->{pages}, $self->{endpoints}->{$s}->{y}) = $self->addtable($pdf,$page,$pdfdata->{section}->{$s},$pdfdata->{data}->{$s}); + } + } + # print "save pdf to:".$pdfout."
"; + $pdf->saveas($pdfout); + $pdf->end; + if (! -e $pdfout){ + return undef; + } + return $pdfout; +} + +sub mergedata($$){ + my $self = shift; + my $strdtmpl = shift; + my $dvalues = shift; + #my $dvalues = JSON::PP::decode_json($strdvalues); + + foreach my $k (keys(%{$dvalues})){ + + if (ref($dvalues->{$k}) eq "ARRAY"){ + my $search = uc($k); + my $tblsearch = '\["%%'.$search.':START.*'.$search.':END%%"\]'; + + my ($tblrow) = $strdtmpl =~ m/\["%%${search}:START%%"\]\s*,\s*(.*)\s*,\s*\["%%${search}:END%%"\]/; + my @strrows = (); + foreach my $rk (sort @{$dvalues->{$k}}){ + my $nrow = $tblrow; + foreach my $sk (keys(%{$rk})){ + my $rsearch = '%%'.uc($sk).'%%'; + my $rreplace = $rk->{$sk}; + $nrow =~ s/$rsearch/$rreplace/g; + } + push(@strrows,$nrow); + + } + + + my $tblreplace = join(',',@strrows); + + $strdtmpl =~ s/$tblsearch/$tblreplace/; + } + else { + my $search = '%%'.uc($k).'%%'; + my $replace = $dvalues->{$k}; + $strdtmpl =~ s/$search/$replace/g; + } + } + print ($strdtmpl); + my $dtmpl = decode_json($strdtmpl); + return $dtmpl; +} + +sub addimage($$$$){ + my $self = shift; + my $pdf = shift; + my $page = shift; + my $section = shift; + my $data = shift; + my $gfx = $page->gfx(); + + if (! -e $data->{src}){ + # print "Image:".dirname($0).'/'.$data->{src}." does not exist!
"; + return $section->{y}; + } + $data->{src} = $data->{src}; + # print "Image datasource:".$data->{src}.'
'; + my ($iw, $ih) = imgsize($data->{src}); + + my $nimgw = $section->{width}; + my $nimgh = ($nimgw/$iw) * $ih; + $gfx->translate($section->{x},$section->{y}); + my $img = $pdf->image_png($data->{src}); + $gfx->image($img,0,0,$nimgw,$nimgh); + $gfx->translate(0,0); + $gfx->save; + return $nimgh + $section->{y}; +} + +sub addline($$){ + my $self = shift; + my $page = shift; + my $section = shift; + my $line = $page->gfx(); + $line->translate($section->{x},$section->{y}); + $line->strokecolor($section->{color}); + $line->linewidth($section->{width}); + $line->move( $section->{start}->{x}, $section->{start}->{y} ); + $line->line( $section->{end}->{x}, $section->{end}->{y} ); + $line->stroke; + $line->save; + return $section->{end}->{y}; +} + +sub addtext($$$$){ + my $self = shift; + my $pdf = shift; + my $page = shift; + my $section = shift; + my $data = shift; + + my $textobj = $page->text(); + if (exists($section->{y})){ + if ($section->{y} =~ /^%%.*%%$/){ + my ($sec,$k) = $section->{y} =~ /^%%(.+):(.+)%%$/; + $section->{y} = $self->{endpoints}->{$sec}->{$k}; + } + } + my @textrows = split('',$data->{text}); + $textobj->translate($section->{x}, $section->{y}); + $textobj->font($pdf->corefont($section->{font}->{name}),$section->{font}->{size}); + foreach my $d (@textrows){ + if ($section->{align} eq "center"){ + $textobj->text_center($d); + } elsif ($section->{align} eq "right"){ + $textobj->text_right($d); + } else { + $textobj->text($d); + } + $section->{y} = $section->{y} - $section->{lineheight}; + $textobj->translate($section->{x}, $section->{y}); + } + $textobj->save; + return $section->{y}; +} + +sub addtable($$$$){ + my $self = shift; + my $pdf = shift; + my $page = shift; + my $section = shift; + my $data = shift; + my $pdftbl = new PDF::Table; + delete($section->{type}); + if (exists($section->{font})){ + $section->{font} = $pdf->corefont($section->{font}); + } + if (exists($section->{start_y})){ + if ($section->{start_y} =~ /^%%.*%%$/){ + my ($sec,$k) = $section->{start_y} =~ /^%%(.+):(.+)%%$/; + $section->{start_y} = $self->{endpoints}->{$sec}->{$k}; + } + } + if (exists($section->{header_props})){ + foreach (my $i=0;$i{header_props}});$i++){ + my $tmpdata = @{$section->{header_props}}[$i]; + if (exists($tmpdata->{font})){ + $tmpdata->{font} = $pdf->corefont($tmpdata->{font}); + } + @{$section->{header_props}}[$i] = $tmpdata; + } + } + + if (exists($section->{column_props})){ + foreach (my $i=0;$i{column_props}});$i++){ + my $tmpdata = @{$section->{column_props}}[$i]; + if (exists($tmpdata->{font})){ + $tmpdata->{font} = $pdf->corefont($tmpdata->{font}); + } + @{$section->{column_props}}[$i] = $tmpdata; + } + } + + my ($lastpage, $tblpages, $final_y) = $pdftbl->table($pdf,$page, $data->{text}, %{$section}); + return ($lastpage, $tblpages, $final_y); +} + +1; \ No newline at end of file diff --git a/api/lib/sendemail.pm b/api/lib/sendemail.pm new file mode 100644 index 0000000..07bf066 --- /dev/null +++ b/api/lib/sendemail.pm @@ -0,0 +1,93 @@ +package sendemail; + +use strict; +use lib ('./lib'); +use lib ('.'); +use pgsql; + +sub new { + my $class = shift; + my $self = bless {}, $class; + $self->{server} = "mail.your-server.de"; + $self->{port} = "587"; + $self->{user} = "ksaffran@dks.lu"; + $self->{password} = "FB1ia1ka"; + return $self; +} + +sub sendemail(){ + my $self = shift; + my $template = shift; + my $data = shift; + my $attach = shift; + my $body = ""; + my $subject = ""; + my $maildata = (); + my $db = pgsql->new(); + my $tmpl = $db->dbquerysorted("select *,ml.mailtemplate from mailtemplates mt join maillayouts ml on (mt.id_maillayout=ml.id) where templatename='".$template."';"); + if (keys(%{$tmpl}) > 0){ + $tmpl = $tmpl->{0}; + } + my $datasql = $tmpl->{'emaildatasql'}; + foreach my $key (keys(%{$data})){ + my $srch = '%%'.lc($key).'%%'; + my $repl = $data->{$key}; + $datasql =~ s/$srch/$repl/g; + } + my $maildata = $db->dbquerysorted($datasql); + + $body = $tmpl->{'emailtext'}; + $subject = $tmpl->{'mailsubject'}; + foreach my $key (keys(%{$data})){ + my $srch = '%%'.lc($key).'%%'; + my $repl = $data->{$key}; + $body =~ s/$srch/$repl/g; + $subject =~ s/$srch/$repl/g; + } + foreach my $key (keys(%{$maildata->{0}}){ + my $srch = '%%'.lc($key).'%%'; + my $repl = $data->{$key}; + $body =~ s/$srch/$repl/g; + $subject =~ s/$srch/$repl/g; + } + my $bodytmpl = $tmpl->{mailtemplate}; + $bodytmpl =~ s/%%BODYCONTENT%%/$body/; + my $siteurl = $ENV['REQUEST_SCHEME'].'://'.$ENV["HTTP_HOST"]; + $bodytmpl =~ s/%%SITEURL%%/$siteurl/g; + $bodytmpl =~ s/\r//g; + $bodytmpl =~ s/\n//g; + $bodytmpl =~ s/"/\\\"/g; + #PROD REPLACE all not replaced DATA + #$bodytmpl =~ s/%%\w+%%//g; + if (($bodytmpl ne "") && ($subject ne "")){ + $cmd= 'perl "'.dirname($ENV{'SCRIPT_FILENAME'}).'/sendEmail" -f '.$tmpl->{"from"}.' '; + $cmd .= ' -s "'.$self->{server}.':'.$self->{port}.'" -xu "'.$self->{user}.'" -xp "'.$self->{password}.'"'; + $cmd .= '-o tls=auto '; + $cmd .= '-o message-content-type=html '; + $cmd .= '-o message-charset=utf-8 '; + $cmd .= '-t "'.$data->{"email"}.'" '; + $cmd .= '-u "'.$subject.'" '; + $cmd .= '-m "'.$bodytmpl.'" '; + if ($attach != undef){ + $cmd .= " -a"; + my @att = ; + foreach my $a (@{$attach}){ + $cmd .= " ".$a." "; + } + } + $status = 1; + my $mailout = `$cmd`; + $cmd =~ s/'/''/g; + $mailout =~ s/'/""/g; + $db->dbexec("INSERT INTO maillog (command, logdata) VALUES('".$cmd."', '".$mailout."');"); + # system($cmd,$status); + # if ($status==0){ + # error_log("Mail sended to ".$data["email"].' with template:'.$template); + # }else { + # error_log("Mail send failed ".$cmd); + # } + # return $status; + + } + return 0; +} \ No newline at end of file diff --git a/api/mailtemplate.txt b/api/mailtemplate.txt deleted file mode 100644 index fd525b1..0000000 --- a/api/mailtemplate.txt +++ /dev/null @@ -1,25 +0,0 @@ - - - - - - -
- juridig -
-
- %%BODYCONTENT%% -
-
-
- juridig
- l'avocat en ère numerique -
-
- - \ No newline at end of file diff --git a/api/process.cgi b/api/process.cgi index cf3f5bd..069950e 100644 --- a/api/process.cgi +++ b/api/process.cgi @@ -7,9 +7,11 @@ use CGI::Cookie; use CGI::Carp qw/fatalsToBrowser/; use File::Basename; use JSON::PP; +use Data::Dumper; use lib ('./lib'); -use session; +use report; use pgsql; +use session; my $cgi = new CGI(); my $scriptpath = $cgi->url(-absolute => 1); my $p = (); @@ -57,16 +59,45 @@ if (($cgi->request_method() eq "GET") || ($cgi->request_method() eq "POST")){ } } elsif ($p->{fn} eq "paypal_payement"){ + # open (FF,">>paypalpayement.txt"); + # print FF Dumper($p); + # close(FF); + my $paypaldata = JSON::PP::decode_json($p->{paypal}); + if ($paypaldata->{purchase_units}){ + my $ppd = @{$paypaldata->{purchase_units}}[0]; + my @keys = ("description","reference_id","amount","payee","shipping"); + foreach my $k (@keys){ + if (exists($ppd->{$k})){ + $paypaldata->{$k} = $ppd->{$k}; + } + } + delete $paypaldata->{purchase_units}; + delete $paypaldata->{links}; + } + my $appinfo = JSON::PP::decode_json($p->{appinfo}); + my $sql = "select * from create_invoice('".$appinfo->{id_user}."','paypal','".JSON::PP::encode_json($appinfo)."','".JSON::PP::encode_json($paypaldata)."');"; #set corrrect data to invoicedata #set correct data to paypal_data #send invoice to email - my $sql = "select * from create_invoice('".JSON::PP::encode_json($p)."');"; my $res = $db->dbquerysorted($sql); if (keys(%{$res})> 0){ - $html->{result} = $res->{0}; + my $invid = $res->{0}; + my $rep = report->new(); + my $pdffile = $rep->generatepdf($invid,'invoices','invoicedata','pdfname','invoice_dks','fr',dirname($ENV{"SCRIPT_FILENAME"}).'/reports'); + if ($pdffile != undef){ + + } } } + elsif ($p->{fn} eq "testinvoice"){ + my $invid = $p->{inv}; + my $rep = report->new(); + $rep->generatepdf($invid,'invoices','invoicedata','pdfname','invoice_dks','fr',dirname($ENV{"SCRIPT_FILENAME"}).'/reports'); + } } } -print JSON::PP::encode_json($html); \ No newline at end of file +print JSON::PP::encode_json($html); +for my $e ( keys %ENV ) { + print "$e: $ENV{$e}
"; +} \ No newline at end of file diff --git a/api/reports/DKS_JD190517-000002.pdf b/api/reports/DKS_JD190517-000002.pdf new file mode 100644 index 0000000000000000000000000000000000000000..3969299635aaf7f115653be2d38007aef78a4bc1 GIT binary patch literal 79615 zcmeFa2|U$Z_c*FlN>RoNaZ-j%$2?2sd7eUsgM-5{&vPYnC@C_}L?~0HGzcM6hGa@) zCK(IGe}4~3&-1+Zd7t0C_x->BdrzN^y}x@{d#$yH?_S@v_S$r+lG3akY~1*C^(`%> z_#7~Hn4O6gOjsBO*YvPQ!r&4JX9U{L0tQz_SRfS<9(FFyFt`TF)&h-$Qnu5T?94z+ z%L%D$XS-;HO_5F*;Gm$i3mUCq>WDv~LW!MF4rZ_iA@1LSn7NoD9bt?BhM=IBsvIYb zlZ~B=3#N}o*}AwJT-Z|)LU6bBZT4>SP{PjE8ENYb(ZGvAm=E(;0P~jv>J)Vt$2LDX zpvJ)y|8}rlgp(cf#JNo^=XMd!ZFX>O7vb72!nF;IYa1BXb`h@aM!B|I<=O_#wOx;U zy8>XU64DHX5Vvy&NJ6l91bATl+?;?hU}%7zb>8jpU(AO_ku)F;)8n#8aXSfdNnZ{g z9)1pX9(F!%7{_+=@a-(wy;+<)qh~uyX>S(SHhG{H+EqeaY;V>!<~up!dviFp$=}J6 z_$_OjYdcv|zh!MRW+zK#Zx-h^Uv{$Oe#`o;mcnmYzhS7jHw%my%zW7jT$l$MCZb;g4t4<5%EI zlV=%gM~FWXPu-7mfC}FfAI$0Pio3HL8g&0|!yFs}zqM@BB0_kb{nXWudDXUpr}Q)T zrymXxJ@>(!%8D^dE|or|zOJ}=-y5f^c=-Fm<1BmRZ_`s|n7Y`1EQPxo*(he+RYQqK zlw5gToR2W<>lm6H=Ks2I=8BVB7l*J6&Bisl(s}9^PiP`I_3fpUx5#r*6L^j9XyJb* z0qWFU61Jx`X4JzqTuhuXizt)`mML+B6LLET>SUxd$`k>EOW6YMg7tLIn)@>eQ{&f@ z4$4-{)(Q11K@w&Db5(_AC7jLH&e;rUj*a{aCOFw6Ou-8Z>28Wf*udZpE_TjHGZQon zZtG%Wf^>93S=hqhW_D;a!Vw0yM}k)fSiRr~8xVCu*qZIsaKgO)KmlmoLnF;W5lqw( zWnl>wcLK8q1Jzynw)I{?ZFjc~Gr!99_Vb}%^Rz3J=* zV$PP}l?a2IgBKY1i*f~VCzLz*gLH*zBe&bIML{oGQ#-UBNOMBkpmw5Yq!VZn>EMC@ zL|K3d3Qc4{C(_9o1rfCLLi1Vkd>j|rd$FdtwK=mr^pV=y=h2DgI20V@GHpeCRI zu*e=z1cL**0I7f;7Z}_X26uzO0hc@gL$`54?qUSWLAU^}@AMA9#2JN#b}S}f3j#I( za48q44|bn0qXN^%CSbw>WYBhwDA4lmXxUChqR}XOClo-z3}Imbad|t$45w{M&Cy7J z66kMdOFNhC@uOjiaD@87!UcuKG_j4Piqx;>^>&KvqO%)fn%^#tiSE#|i`AYSfWl7Z zZe6hIVg?)1W;@)W-`NpihO|LA0{%Mv5wRTzc6-?5xl=~h3+fVAy7 z1I+=j0Rp{f>f#7({6NomKm*vs(asuaYXVI$C-7#%jLKi|OzrGFc3XBdGY12Ed!$4B zLL+VLcE%alk%Gk&4OY8f^U4uvfr45^f+1vsFvYOh3<>4{pa7bP02DME!6b8X!OTH` z0cNuOdPJDIID^tQU_^lljR0fQ9*n{52@8?64cruLgun`cnY6#^+BurpAe>BH0MP)% zPkeWYv4!TOBW5;&xo(L-gCUM-eJ2@UwmVC=*(kO%GsJd~65Bhb#CAGR>=)<6z!(MG z7Lx)~`zMA{J3yp%fJp5HBK51X+)g>UopN$}%gOyJCk5XAaOIuGRdy<=>{L?OTS;ZN z(67oiE@)?zJsJ!Im7O(0YX^eX4g{^e5VU^P)ZNL~w6t@CCJ)ll2CT*=Xuve6lQ0X& zP7%aj5QrTl5Whenw%LRLePsHRO<OJLPs(wC#D0`c)1I zvB`F)al4&Lb~}~q_5!!tE%d9h8Ojv}ElzejOmf+&@3K?hWp90#U-dk8^1)&QG0Ed+ z4n}l=OQRf}oFy#5yaStmxFUE-VIDYnctDRLY(Rs5v7v_Rpv;^tA-RN;k00~n0_Ayl zcribIegPOSFCUCUfCI(__OF;9NaNw>-YyH$cI)ld`MdCEc>n`~gZY8>IM{)-05t~v z_<(o-{V>l!KH>w&LC;WS9(Hz2I@Az9Kmbz~q+{ysl>1q42ZjJQ_ckmDK7hB21Qc@f z0)hZ6h`67~gEn^Km^OD9!U^F3eh>~&2(`akZa2ihf$||-p?V+=;RuDhKQ18SaPqQ) zHn$nT#k1WW6k_1-;KRWVRoZDB0*pz3sQdWmP?0vp;pTFGWGQndjx9%zTm&aGfKBoJKR-^MO zIa3NKD96Z>)CRVeWJ|vGUUi}GQxF*s9@Ke{?zi3IJtn*|ec&BqQW2>GLB}hx?Ac@b zW#`NWIZB1klayAQwo6f_ic*rhoMI6#o9&iF#7J}P3tl=>eJ<`C%VL+_O@}k1QZJm) z1AT2@j=ru|1jtI``;m<0d)R-5$)g5s!8LUn@eM~ zYKMMm)o{Py8~%mF18MnoC7!<%4mkw=ARM;8z`uTp^kBPDg+ltN38f_}8#3(^Qt=6i zB}d3IF1+AGbv{|Wpj&q2Q~uD%6}FSXte0*L62;Pq(;?cvysM~!kJR0Xm55>qKSYGS zM#}R3xxOvQmAa#)_9i!QXU9cl4kag$*5}|Dx+kRAI+_uR+qvhcL`;n+ubx7WCfD&i5s$bbk}Rvt=`jQxYmwCY6Fi|U$7v(97%*CNYoq_&Q! zZASQO@lg!XzLc~23uf%q`eVgEtoVmj(1GvMSOuL8RzZhV&|wvHKh;}U1sz8H`(Li0 z`^|U_EB;}{Kdkuo-zxs?H5C3kA&j5zHwB&68zI6=swXaWetp@Q2ien5sck*`2VE6;_ck4lAA^dlFiZLAo zJmlmDCWJe@#7HPm9bihhOCwb7e`3D~n!o+CJ;F zyTgQ-@-q&}VBiOB=%EmMZVGIrf65|2rof(?`U}})cl7Ma9Y3FU%R(X|6bIpNa>rhm z6aP@|!0J5y^Zq5UIuESQ!wKuO0lsro9INxd>O3&MH?U3{uudC*(*{WAA-&gK*zdvz zw2j2-Jho5O?|y}bc(VJYdiU!#v{QuQSe?heA$#mH5+m7SbspQ=v)vK3%beZtH`!ya zueiT63H#%TAXR&OHP!a7vMm>!TpjbdxOqz1xgk%AYV6#ahvm|XZeC|@=RAlLQ%EKI z7nWZC#9ajcZ?728C*r-j%dlntJ#3B$LGIrB(gk5V(+rE-EOflc}qdc`q)# zZDwxd>S!mmN>j-x2&s5*P5k-B4=)AcrMDWX;}^>J`>XH6$yZm;{tNQ4;s80aiZ+ZLzUua<)Cs|50w(D|bNgy?UoV#&>Pw{*(?FygSZdSQi2b`N9ROpm zPjQXk^izd@)KB3y@{b7#c^Kb4UE)c4%1-DF*27c6ElRooMB$L(kpytaI1-{Wshd0k3J|ZSF-=?s@cHsJ?nWl0K zy;5?u+);P(*g%x)!qc(4(Q!mN19xH92YvWI&M|#Wah0&Yd9{aP^#*}-9#1W;a<0?; zh{plp6iv+D@bA~7`VfIbC5*6IvI>%+o9-c^b#k2!Vpj-qrcXPb)={+Q^gASwcE`5y zBlSe%)tn@&wB=ij>TL`x!xjzPg`0)b`HYsK(?Tn+TWhN~J>7A9+@j?Eg1^{vSO0k- z@qczR7gn!@)oWq(T3Edn_P#1`ks9{CD&WZhbMYAVzN%mMRsDAL>hGc@v^mD!R|R(I zdo>t)wH44=E9|)|?0r>Wgg~PN{Qf9g?xz1`_)qm(*mGC^M_tT|6+W=S2UhsN3LjYE z11o%BFUy5)&i(DOTu84ak3Dw<>8db-76`Gv=Kh_#a z@9=TGd*)^jbN*k|dHfTv3p~GH!}^;&-QvSP+S8>=*2m{&-8PE^ULQ2@ahle7Z~WQT zi;I2FS)#u)eEavjK5*@Ii|}_KIXSt1Gtf(Xt7QF>{S@Ap!bMTR%f;uF%ssUZ)ja=_ z>3RE16U7)&zr145Ec^FL-!QF(_Rs7k=YwwG`FbRY?(^jM!uhDG(AVzUxf0&%)DKuJNFcmg7z^%WUPZu1CDuuLRlDmP0M4@!@|g2B%>LH+yP2hu9e zuV@*PZxt)qdbfFB;WFLyoG+`p6_b-u!LgJk>@C>m#pH-qkhx%U!q|MN%NMUXS8s6q zqQg)nxkq4NNT2oDqU(gLFQbV%)d)Dh-*-yr`^0!ZM?sy3v06)%_}M0LD)KM*zxOQH z-!V(z4_81%R1sWdKPIVDafFuPl_Tdqkz-;c6cjxS-_Bhd7UI;@5ctD*aoh7K|eRQlJ#2ekjjI%LN>WdA8_{S>;ehJpWi z!$7Wo;u!+?$o!WMFBTvCQ9-xu@M6v6ZfY3yL7fy_GMpzU#?ODDcG>HX;qP=r|E7*^ z?@_D21IfYnyWT0W;|2cpODF0Vbk^9eiKDst3knAHj?m_IzNHg#f5aAeme@Ijx>Tm| zhAR9lXG}ldT&GU~3FX~#?W?axT4iws2OEqsgTJFIPLwOzFOPI4y#nOey4x)q{_S^BIBo{zkoskXNJjQQt=2-ef;h zK*%-v@+K)!bk@+zq4Lbghg8ps$)mGk0=0asy>ZshIQ$hu_ZoZt9rXf#P`a|K;=F*l z9mEyU2yi@TN}>R>v9e6Pm1k^ag@c^9RHwueK0E^By)y9T*jYle+B&6UCq^#05{9lF z<`KZB&&u))G*>;sh)3&he=t|>M9|4h<^#+)IGpDgZvREc{}bgf2m9~6w5=Ux*JQ^L zmpG__dys?#H{jNlgFca637i%T&jckjG>%H(YT!DN9F#a0aEm*@@?iM&S4}baA;<@f z`1>Mm?~AyIFYo|AaNP4ymZ$Wgzlh#Dh;@vQbs&OuAoBYeKFF9>`Cp6bSYz5qUB5?r{Ca_(m)g^CMIHM_ox_?}r>@JBG2!4G z%OL#z7xK?uqt0#l=dy~4719)JzcgG-oIUKpj!w=7VF3bhl(Um6(ow?B#vYs>vvr2? z!{8F&NSLFBJ=n6r;F3sJlqphOMjVQo+L<9$5so%aFnyS?@c%_+Cm0t7jEjw}6O4l$ zSYiWO4PfwpDeTH_pGo89<%Gc%k+v4jmN0He>#7ceD;wk`rC4`eTj2kip z1z9>MGf;3BzLPUJt7e1m-ZwYcZ`(OZ9k}3vO3==+p?W8iqcy@$4s$pzV4C7U#l%0! zYJbO|OyiWXWqf#|`;ynPRmlBPx0*q}t!G>NaFkU@^9`SExD)x|k5+ei^T^*5tM>lh z{GKTmDV7k>7%AFTezZkU3Q1_l}yH9Ormwy604cn)Ey63ZyF_`+4 z3_Plmh^6I!=HeOuRa8nOmKx+-I+Ng2ZfX?Ea2Pyrw`jd7cUL~!3HdV3!IgMp#4bXd z=&}#sNO7vc>P>PdBX1Lg4u5pVjlqSe5qQrL@MI4QjJ4xCq9oPKj^Ow6t4ElN15*tN!H)O=W%J zM=&Vx2Vb3fto4#?=ixEM607s-cq_Oy4+m$JUTMC8qj{tboi~6jL4bNL{CHS0(g8b1pUMBDjO%PRYsiuIu6ryL#rn8Mt)ZW$G2mHN|GWhKT?j)>B6 z*Pv7kXO|8f3(a@A{gCw($S^+MR91-&og>Bf08cm@j+xKBy*khJ=$-^my?0=(?@9Za z5SV`VdYRH|c&)V(WIQ*NywldFKNn@6*#lwO8?>NU*3Bj%LX5%b(eb|N&zEN$ELuPw zP8G4#2c-U-`s8Ch7V>)pAmtHrQNAmW$ivehZhU-yR)cbA=@W=2tJioQ>vx$lO=AdF z$Xm=V%@ZOOSYqE|u(Gs=xm-dyTcIk$8G(0J9rSaMd^{34$U zG&y?j)tPYgXuGwwR&JNnuXnO>`HJuHdK>0PdHum3J z8%EN(UL~`@z@ssxbYs-P z$A#Mu8F21}0^3OF zt;=e!6@`NMRaV90XCrH)*)h|~M)CM~E#kd4hN5A*lJ0KIsOH~)t*kOAo_f1;-1i0g zV>%nBGo2*V7PI&~cREn4A6WaMY4htdJZoqvaSv=i;lwizV$X>bkK4EqU{(kUde1Ez zmT9$G)yM%oh~T8N38*}Mf9c}PQix(k%&z3Tp{9YK5e*f+!vKbWZ$1w1nfuSyWY2;bKHyZW`ofpn70v9ae zld`}1!f-AfJz}PRdV1gR#O-gZya_Sdmk=`1jX4YThVI-n^#ME`nduik@JrXrp-yOJ z`%sexzMWlNsfzTq#(93bqNb)>TgSq{m_Ir-G``!tX6O~Yd^4>sLHQ8t(NV2aI?~!v zWXV!36gVjY^$zt`IdXzC`)$sK)|}MmjJ@~q^~>_!%j8iCPqe_tSp2;67ZRBQ3|Yy^ z$-w(yf6PO@<0-`~_T>Yk)d6AF0Fze1MtL}Zq?N^LG$eZTO+af)U zQxxgL-bTb0HeK`VKJk>@_s#RQLM0-_(-gRN;)Z&(9h!Fq*_~U52JVh|-Tiuju^{sN zQC~&5{+oy&0+K7)B&G^R4K#jh{86RTG=@CH@cxjPIP~#&wDgqx7<+H9TO%R6u9b3d2&hXGNBq11EUK=<5t5Gf2*{E zuYfLDOo~x4`O6EP>GkIDH0nuewUSfWV-j#dx_l&H+_DYbZ{Qj+Bq@LTy<@j>u!{VpiUBY4|Ee|jMpvXU*r>&Nm?9nsfb*<7T z`=o*<)d5QnmeE=RhvEZr4#k>{YK`q8ZKDlob^2rIwsZZthB1R?CQm=+@JjK+BYq&+ zH{NCCEb2UI38b_7YLg@rShAnhgQMmtK@`%X`TYB5jk3#T@e7VMbCyXm9d2P0I-zc1 zWa>s<%sS@@X_e-~ibX=-)x9u`coVNxp%Ra%obP_o?Zmh#~1TJ**ZIUx*|aWMS^Fy*SQn-hDaLyL05> zx2etQi)d{p3|m&x;1W( zYsk&_t-X>{<$OZn#8HKErB^>lpGqV-E~c#8G?Au~4?EiUFsACCc*`7|2|0E6DMRJo_t;ib#s|S-6o}6s2%=q|8rNe?4Q$&dqz_ z74l%vQQO`NS%@eX%N{F!3;K8Y?o+~OohxwOvcTY`qwAs8hX;c?W0PcG=}D>KMezHF zP=3kh5YfAFo|$$%9T(wTizD_mc*u`ATS+b|`=r&t;_$e2mC|wRa@$USoqW1%=jEsT znXIz3>-}>Hi9YT7k0zEklaKNrCI0BumtUWsXj7m5si#n*N}6QpfId+qVZvLQCpEy&*gu=_J6a^6Zgajb5l^N#?${?+`C084;DFMcJMN zw^mC|TgdaNnzHpzciE;b7rV$xR*_D+6p7J!)~~GO3ldtjw?vsS%rEM!m@Vmdfvu9V zmC_O^QAZNe(_mUTgqmLaePCC$moPtyIb-D6U?J>du8xPcTmgP$Frlo%<;16IUJ>Vr zGPiCl4o#5`-eSwnUbth8KiJ+f#$TEglGEHx^F&#bn{qr>CxWwvQ_vt>|CB`o+^JLh z$!#Mp@)iEdQO5P5dD4shp_7vf)(?tvl6AuB%8xnmcRygQOrUB*T#S1pM4`q__E5B7 zaAA}3TwE~4mvi~izA5!GG3~;oJo}?qBh-DVbL(v~e1pagMy<5CJ}Bd%E$J){c0N>f-|m{o9pIG9$bbSd#YxV7Wck9cb^cqbGK1?QY;3gyc-^=O~c(puW*b?uO; z57l}(*=bGFA=Y~H_7iH&xvi8|`~B}Z`S{EbN#U{xi<*ra#|=fAW_kAC8TsOm=ZZ&E z%JC*K*5x8g=)|22A_~V6H@g{AG`{{F?bO-|>DG$_2g%8ZO8FXl?u#A{J*h)BW$f18 zzG4NRk&x5$kIUmIeB#}fMw{lUPvbCN{&@{)mPqpB-cYeq$vYWqWgRXzRgoJcO1;53 z%sqJ78loX1rFxEOTiTU#mkYf3w5hve-&E!|d{zyUluUf?R?>!{8+C*x6xJ z%!A&X)2F09B=!acmbtXkr6JCrO$o@MW9VaQvzVD4Z=bMgJ)~*po)U9my|r0V5?4SL}=6LI?1k}&}V*BQ-datFW(3;#_LFW964c4AZ|Ej{_L6MhM{YNx6Q%{ zA{x?&Hbz|vS83*DjA~rk7GLm7026RMp0vr*+$>d!;xsKs_$nkW96hHYZuzVYzs6rgpB!-UX4A z^|f`0RX`=?7-HJw<_jAxQ!jv_xjBC8e^HYPWxJ7o;$89RVzTUS<$6v$qMGmUe|UF zGR7q~(@WV1mg+5IA6InLArYzXNO%6V^g)o97D zV7bg{vtk787Xrpz>3l^jSv;TYBBS9mJr>VLEo|BEO?lHzw`7@O+O?{uZ=?!#sS4#K zOv+Nn`dPp6sEsRIAy$i=D6gq0mCYeLNP%>46Ijo`d`F}W71{Jj|3MkSDgh%)&vMx4 z)0XH9G}q5aW?L4e=HxCgv?NR|oFDz99D^&^vcY~K`Gc7HxL(4eOQWwI&`(Va2fdfV zlYVlviYK8UnI<)$Ow;wS>xsmiRe?C~9;KXxlgdmLU+1s1}*H|!^JVh{@1`F)2ctk+iCmevOwE)l%G zH-0Eto$rD9LA_eZuB}O8-!`r-w#Lv1jjnN@@}1hIdla(_6?c=Wn$jUGwj6CurLk`80yf`qka0-B{f zDdq`pGr=q9VOjKR4*_KDm%>Sy{~#Z)X-s82;(Q7Cudap7Yl_|CTcK0Wlu0%+U0q;@pFcOE!iKx+~O| z359!vEoa;-UG)gnJ;q|2(%pS>W8D!+nyDYXxg4Emk4R=0SK+yTWB#1dmmH0F<2Hy7 zB!@Z2g}O|VMJC-u(0wz<2H7HX;&cgKKG3h@2K$~)=HlF^3oYY!nDT77;x(ezLKuu}Q`3u#P}8Hj)4GzE`&M9x zlrlk?mh)Zb#r1d#l;^xq%KLr`rlF2}Wuf=(xxU{SiEdT+9$n5^D$xPbwI$LKk0)10 z*c4~e%B|d|QgbrS`i__L8}0NOmmb!L+o~pKd8lICJaE3jM^S8f8O-oxcJe9y)9>Cr zF@12MsAmJ=#x5vZMt1eil}qE@u62{KLbU;hr%I;%KWevl8Ai`9ky7o?dxw+z-O{+s93GhWkGz2`LJ6F5xxFp?Q!a6LYHV zTbyjTz*Um>XQo7z>+Ur?0D>lYu8-tMq|28R>j&j*NUxGOBn=4>_ft&;S0=yXU=*GX zOe?vg7Fo>a7WHuQJm;zXm!`7AYa&;8QP%GU*gKx*-jPL~ez`hpvYIYUo6&>&JmiDy zY{b2BN3)LQ*7ey(YR^uyso;zBkwhx=o>4gz<8$Cl0nQ_#K(FHzM7>9)?|477dGKn5 z+h~w$3IN!n0F`02$^VlMj-sxi+sgKL9Tyi6ey+?8a5Kq~_FT zsRDGu4stzwa?gS)Ht!!8vtnF!fcsl5~*nHHlH$O;Ri7cR?Aq?|B|OuX{UJ z8i&=fQgFF1n(<;Bzi*K2dk39(jYOAt{*RsTd*m*)ORh`Z1~|(}jb?~Y8SB}I?mTh} z>y(9I)9R9=pX7SZbgWk0DnEOboFggZ<&)8lk=Fre??jiGbF3B(uQM`RZD_eJUN!7L zQ{*S0(7{GMtp{G&3oc|&kmn*TXf3d4<* zCzLaa!clPB*Df)U>zl;d&iDh(I&wVJ`d!atnzCV@3+M$+HRY#_>!%t_Xf74rQXdLD z&%C6+Kx+DIi+}lM+7tt$fWY(pf2+ zC6XsT#510fJ?73a=Xl2T&x}G9tr{T@-5W#ZINm?zH}_3D=YvG!tr&J_M&Y#U+T}{j zb`_{;+<8P0R`=5Pw*AWWL83w*4+_=I?(qF5QmoHLf;axmEBU&J$EE4UR?X}pNg-h< zGVxljOQC)Vg@c5bbWY8byZ0q@AF0Bv`m9TteeTHFg@q&uq_wl0HupES%kuO=Z@{NT zc(yLLL13rLsfiaXdF!Eevz^s%zJ%z+KhsUR*O+C~7x`?!STHp-ZalsD>@b>%;?*4J}>F3?uo6E{nV@hEgR2DZ4~@zc$>|Q-B6F- zD2!S@3T%8IUp1j5Y}G4zM*#7tu=6>gl~4HEZSxbtmdOgsB?M7ql;=ISTJjzAfBV)t4R*^Vje^2~z#L7V?)3wyE%x6Cdi6j=>lzzGIO3RZE z)n#jqUFCN6i|?r}r_H^&#qyBlcJqa7Bc;zX$K6gg3WmNzx^{XSc=t1%zkRSV(n|(^ z()Va-(|BdV!?a1S53>;!$>nW!#LJ>z5HzLL%cUPXa8o%&(r|OdbAueHTRAyy6BLq% zDaC2%K2jxt zh+jbxVpS^1%kvs3CbsZaVR7W(#rrIRo>+3UB_1pr$}8x7s%8gkyF3FQ3o}uDV9hSl`d9 zkw*TIRn=qGy~Pst%xJc0B#~zDA<%_gp1f6mS8e&}HcZ?&+%af4C>;lr(!`aka<#^vf9B4)Ez`!tTdv4+9--8iS_v zhrTuKiW*nHM3yTv4{r8#3|k(~KcAaHm>eA(oYYoup?I;cN8rWmqDH2k$NBWroultt zPn8WdsL(d^eg_dF=Pr{REtl!v6GX4pQ*T)DW3si*UP%gJ6m@}gdp z>1sFKEmNiOVyP#l)F1f=2T!+rkBqq3CiqE0sAh^Np8Bx9*VU$%?~~ZFjJZ~u`OqId zF0K#-=giE%9SsnrC+TcZ{__0`Q$0~IeX`AyvZ>jYLF(+1gx=M_$5EU{dX1t)E0-D? zpQ#)8dV_VOI@IBz<8gSJE9#xm7ssL~vu^FNlZ|=?WJD_ui7OVOk9}AxuZ%nDaVc}n z_*|b*EH&6kwI8aed*3kyPe04^kUs6AE=}FRuJ+eOAer#hNwsWGje5NQnbGCO^1DBz zBz?Fq*;*5L*gs6INPB30_6q(m0WtN`9nZmN6b-r|x-Nb_WdATHD8@!1@;Z3UkQ(IOoz+I73W?P0 ztjR3a&K?m4U+nr6w@pvG;mZY$Yk zG`E#PFyJOmeJWxqRl~Yj*SEi#lb=}uTUX@Zi zWDTT~i!O``VU=zTZE@2ees z)J1q!W@gPKPp=H9>EBwX-F!8~kd~BfU?XCoYRCLQ`_z>#iKycpys6VgrzTRflqS50 z)!Istwkolfd5+P{=*ra*DgCB50>&X_EwrzVx^FX5N*#TACOBvQ;7xs({n0jbpRRqp zd!I`r*p;y}FOv&#D|SIlQsmwHpsER#m)uXk-i^4uRlj`63txo3V%i*hYasH=eK8&5 zDkb?t`@49Z%<#dt5A>u`0u!9BDW~~-?wl1ipf2A?qcn;N_AHqE!S`M}n@zK;7r!V! zczsxg2_59mobN41J6(}pf9_MXtBkt7KWPdf^{i)_Kb0pQUQq+rph0j>LsPPqOJ@7% zDZ`?<&>z>%1qf%&5~h*R%(5BLPOqI6*xESj!875Gx&qf;$CY7SZdZ)Yp?@-TR%k)k zpsAWREj95Lz6b^1I`P4AOa0WKa5+u=sRl8+iN<_8SxKMnF|#qEw@L0K_QYUqwA3N) z)@?aSW9D;nyrLJ6Xyr-onrK$gq0w+A^2JNd;?w~3>1T$=o2n_=dTP!R5u{EI3-f4~ zcHe(~Y3@rQF;BYx{(*BEts#~;jiNfBSuORpN&S?I)M&-D@nub}#{6|r`$NQ_Pe+!? z?065rKV7@`qFBDGqyfeG{=<5Cg84|4WLI&6J?RfGroj5p3(L(#DRtrZ*F-l|}Um zmT#Epd|GQfHR8?fx3SA*;{D>(X$g|qB^L>mUWBLJ{enm2QaK>emHtBCJjr7w%^-l9 zm%d{v(f2r>?WYc58Yh4>o=egYUPNKNv#f^OrBpmM6(@%!?x&*s-xoxN1psi=^sp6g z&ViDk;qg2Jxvr?*hLx4MkMWgp!m(4gR3y*jdLH!-%F4)RyCEDr`M~7)EUoUlqEdMF z{k()=LC57W$7kKKri^OGtD=Sh-{AqB63od#8cbnaRyqWpV(A!#3knlyj2Hz z6A{;;5vGeHImaek=<_bwr~Ih-eR~F?+Z0Zh!Uc$aAbeQjj>H6YmVUCLC0?0y2^Z+Z zWgQVV=({VK`1*Q8nwIIrb0166!$fLu>o)`|m*Nj2^@&_$CZ>uya6i)O2I){{hPIz0DT zs@*&8-3mf8)9zc&4;gV8ZimrMM+>{XScatu;ZfX1a!6oSW=NBuJ5qg3Wx68l-U+37v|JkX73LP6!9jn(s3>Ht zS(8MtWu$RIBy9THP@pi{KCNbwR`*F)-R(^cDju<^Mi#<^fvW4lNt#9Y;iRN1m;8YC zlxRg(>}`1KoK|&di5R|DM(9nm@snTseGE3w7G!BM)+kffrPeL3!TWk=Hr8|TOq_<^v47v4NJ~_Iy-kQC(_Mr-eg8=LDs=AU%|qC zE$FS5;nTAL3cisnr1HGJqe{^q9cax?Ut|;=oX&o%dWdLzjD~GQCE)Rw>8?clh&LvW z%M(ZsX=XK;_LFMmb9v(((V4VJ#cSBFW|W-HYU$iJHV<{WPD5d$Rpojjk+uiri6V`7MV-`>Pz2roVYs zSGPN)kwnnzOp*oK6A|z)S&`A{CE^GHYX>}8Cqb2YKd+o`^oqxq11!_5@oq;+ygTto zruAxP`q>}v@oN>A4&4+QBy>o-6;xI!sY&i4|Kp(RXtxQGJf-E!)0}OaOWL7x8k%$X39hJ%R=4b&O<(rjEtx*g#wRNIn z8(l0x!VzHr{fsYEIkk}uXN`1TkA8d*>Ftw0kRC!_^>q~<5jdoc$$qg6T4wlk``L1$ zPi7x3jia@Lu(%-wZC}9`uzI?h?^hYhZW5Vp&#N2BoQx{WXd|nXfBeFRkG3!Mi?FN2 zJ{2<}c9Cg&2Q*@2O@3v@F}IhhVOYK^D%h1(IJqJfNB2OuC8sWWA(O_NQ9x&s(Q0H8 zR>y2uld4CP$4I=1;~VM8Peu4tqs-?AlZK7>0~05z+T};@EbWfVxvqXJSiU$_bn%UP z`yx$@vf8Dt(Qhgr7QE-2y5}|CB2OyypLrk=wQ5ru=et&MtI2lNgr;^yUA|_&q=;38 zuB(t@h7EVh_c{u{VOXa`D*2om@;hJQYpL%cRd&xKID7DhwMD9H-`3g&CM7WE7qnMM zyd_URLxN6P2$Jj+O16BhC93vH=g^bfPGdj6jaDQ5RxPfeiqPZSH_9qY;w?7j=EB05 zZXUdNDBsd#8ZS_RJ;trlZEV;#X%+9ZEkVU;8w>6imLqp%`>Dh{PRtMA#3!-M5qm~c zzf{^uhRY+8fU}Y7ertBECCzS$6z~ zW7G|~8vcicui1JUqE^JTW|LN~Q4i+MKNEPr>Le+t_Tx#UwvN(j@@>Ab#0y?VTl!1Q z3S7%wEu#%8@NDffTDs(!PwwCn_&gV`66u7Gx{!zlsrM92$fnqdA)W^2a0)6XYKHd!VzlrAnu0jKk4K zH$dqt9{*HRSr69bcT)V=plIwjJ&6k!QaK;-*gy63?F>KS7bUv`wG~?p;+%>-npSlChwHMw!U2i4j*C^bcPqDM zmNgSg8qzdnP-ni#&*F~VI@gb|uaxaMV^9D-FHfXDJ2-#UwS2MnOi=W_4-b`Bn#oj5 zq-bPNn&qKsckh_IzIiYpsE5a`Z*6^GY5C$8>$meQ@2|fy2qb~5+9tlA@cY*2bJ$Q) zCU4_JKJ`N<`db#6_o|C^ye(JW`f0{yD!V4!=n#&n^p54KCgY2y8L_MawZa!XL~WYw#=N6!aW9?UkAK#WGY!Y_^;lzi_#jLY>tk@(xo& zV`6e_U;BL$f4Vrq04v#8bhjNvJ+-WiVu^y8A;EBh_g0HKO{nO{Ih(C_#WZnAm$%eP z?1$6U_SeEZrx|axdwt?e)+|6ren9at6Hp!MxM;$g64l=vLX)`3cK4>`G-slB*|TYP zr!u#ob(e^zrxZh0#M5mn313cmUbWWWe^vw)()Nzfud7Mo)#6eI@#HngkSzV& z#9#ndIR3^8Z&+Qx#?U=`Udza9vsXOn2^r%e^-j?#L`1|zm-;<&VPD}&d=4Y9tr4`U zROX=z8tkyHI>$?0Qc3^N$x|;zqr;nOxJF^=@j_MUT2qmf%;$$3**zhBj%6P>>olSX zWR>`*{rEbB6n=E9pBPNHpb=g@?26>ny;;FyWwY<`WOSio!i?D=+1wRdyktbk56)ms zW`)E%p=Exn2|mWTrp(~0nq~FMFr|@BS@ws|W>ZCAi`tr|tg8Ik-Z;05^5F^s(Oz74 z^R|J%g)R#@a)0)*yhF#9yEqQH^<|A~v1hZ$5EyWitzm^^2CERS1;O`8m z3CUxc|Cac2nSZ5XuC!AgY?nS|f=?|gzV;gJVZ==h$+roSXTo!ilej(%=QVp1VPPGl z_M(K70&>oIK| z#mMZCw0Td%j<5@1;z9nIZ$4T$bN5|!Sgf#EaHh`hVPyX7#ucx;P^2d-ccvVG;(fW) zgC|O6L()K_|W)tQ_Jrq;745hXfSP=T6Wbuh*$38Th&JxtAJlGdjLl7?6Zu@x6~!A}*J7sNLj8$t~96BB8PgV6jJ^W@BLC6rWdH?fdmH%h-u=e#fRC%eJb` zED0Nf`hHO-BPYzj7xdN#<+U#(mSBbgqEm(U!x3rht}@IQe^@-6AhR*>@-6U@&yH0j z@4j?tWt2g-C^T&z_lo0-*`A~M5~(NVB$HCnsj7NZL$b>W1(G7J+58?|KJ9FWHv0-t ze%e~b1O0MO8dD5jna~&WIh_#8CZ5(FZZblO{Y*;P*>7d<8ycp zS$=~kGP)=COm4XsyDXtqw zv8ubiH$0mXnN&D`2qz(YW?UEb99BhNOvH~ocQVEXuq zMy3(V`97BqsC$l7q4QU|!N(RG4f=Oq8-?l?CrvM9+$4In)?KYI=-IjKn_z~xa=$i# zSM!~#>UphxrL&8&RU%IVxvGaX$%BwRJ;a0P*u;mf!P#y1dgSJp?DA$G7O9SaRlvsM zjbvn}V!a_xSFCh#se~acO1b+SUG&0bw?mv^>0_0gvw<>UNsEVKR%H$ErE1L;Q-num zO#NW|aYgAv@279NXy_i`TtegTL;zg1plH3cXxLheM^!4BbvPYc# zKf->8bIg5JYvOo4QX-R?`crSc|qwjB|(euM|-yJShra^j2&^YYQp;g%4)oXo8A zpWjsEo{T{62Wpc&@{+U2Y_+~FmbW2;WQk)OGxzk;hq^{taYmnJo-yS%3a@%7& zwCIXms)2x;GHeQjh(?VGC|K`LD~_oX>iI#OTfV6)+bEV92JqIlr>yBLWSyQWiZjlF!UX%C?-oM!K8gP}?EEaZv3})w zC-}_=RYlHH)vQDF++IF8l?9s;t+BGg2up%|x0B_QZG{=RrI;_zT)x6WD5s3LjS4m> zPSp59CrQjJ(&CQ1r;Rh&D6AfhA*?dLQrG#1MXDe5@8S zjvVOVXx4)<1D8k4ciI#?R_ghQoX@dJ<0sHXNShY7K zpX*AcP-vhjn^sU-2I@>LCTPRyzB&SOL{ut~TTUNIvoShd-wwi!;pIO-p>fh5+N6hX z_|=PtmxN0XeY`(zMGa)9Oe%2l&k~c77Y!-%DqT+S(d4Bu#DKgd{2JE+Ce;$quxOl) zNXHecV4#4wXf<&3889eugXe^=e2TS#J!f2dPvm)NI%y@Wm(bPN2=hbY1rdZpT%V#y zDf94k4di2y3%4XUA!<>`S5|gl$JXeeh)VhZ;VHS84CH*TwrR3|&aqJpNyP8+@|Kok zpe;Wgkdul#YyRFnD6emDiZTKT{;>l;2cfV`sMa5r$4q`3~f21`*a_r4? zC}U?@t!g~P`)fMfXlUou!Nf$=4gTTcRc2Zoole9%su`WFPIzcDKiUjEodq9qPcqC) zsP;taFb_V-h2~q9SiXGc!BHgI_E@CZ^w~H+5MJ>fT!wz2k%iYBIch z3JKY);xQW49XP?r_CLV5?8Z#K$zx&3s^>4;@$%wa(_|M)omc)O?tGx`{GgVU`8~)N zLoibHYZGoqz&Ox7<-Ls(ojFygb^Rx?;Ne+c<_zc=s^tOgWss@9$@R`cJ2)ds%s4+g zi$~F}kmxF=5<`Ufh;L?Yh!>YZ!|%)wFyoB@Tw?+|Izg_|vI+cvr#Boqmeq{dBNN-9nVfR3XvCjRe!u}IJe%WNWW%bXw zItU&zoRK!~OxYnzpUtwj18l4hN&RXm8_1u;V$nWJ!{RVf(Se2}7SRX|;oq`?>mpYd z4Jh2b+RfZgCo)l%*m;YfJ$aNEeUH@|G#njsd6bX{VOAy#K`v6cfcLo&-og6)fNmpP zc1o{8dX-o*9g=z-GqxFZ8SwhLM#X*&27h(5S5@#{7^lo?~iE*&ILWIGe(02p?mPk%1hG=}h88fef6(?Z7#}CkGm6 zhvZDG4+hN~{mF3(;-4Wu9~HGlcH(dEHezzN34Qh>$tUyNZ7w0)vp~U?*RxC;t36lV z&L+6P5!qe($;pk3Z(q^o^8La+VlZDR6)p$TN~@a>55SQQPl0bkrZD!Tpm&jd+eVV= zhrHm4RIt0IrltdzWr4jBcf>!UA7Z$qrvy@GA&WVf*=hP(9I$)YD z!l~4KTUb3_l|8e(*hO!$5*U?K7ydYi{bUj}jUxD^?BOswacEfLN>04!)oH%^Qb5=B zDAFVPPU$A&x}aP{jmX7lN0OLQ%fRZZzEuDMz-LDUBBP5+c<6aKl%JkJiSVefWGG4_~mGi{r$T; zZz{u?6aY8kxaW4c&o(i{^BaBCYfi|EvY>%&hgugHK~nO2N$spPHvpF>*Sg$S?@k`&%pG%yCzSX0IOV!!-oJZiid+Aj0r0DOxas8hoH-S& zU55l3dA94Vbae10xRv$UkOT~nb*nRFyAS+7xRGfhu#JKbeX@^ms9VE*0sa)IEglmXka}AI z_cJtNMsv4ZQJkC50K)WIb*@gLlb*Xzm1e=m!s`{kfxayYwIM&;0RD4znha}`KJ&{2 zoVg`fxTa&(Jh1i4Kj(RnFP{lpO8Cm%Z2>``4Zi`;pdC89vOt7X7&kL00qA3XJxB&bW zFq0%QhEaO+A&s0DokFtFo0a_PDab4>khHFe9e!n|$u&#DsupKS_tG zh5TxKRzZ7)Ds=t}Dlv+xlb%B@p646O+8R>;0OAm|r1{2p<8`8KkB{4pPPg-AgEO#3 zicwPZ6dC)4W!qcYieP{m!JgICod@r6_;0b!mfE%RkreD{d%MQp)Ftu8fE7_^mOpeA z6|NuwIlhAfMP??&cH#B zZiM6($rPQXp}80J_@V!{pn;RCv>2pN;m4B*7~lvpa$v_X4Qfs;2mXF(!s+i8wgYu| z$z6JscdMR3);9mBodg-+|BfaR8Tm9f@w&>+}h?9p4Zc^iX1W}#Z0$9Row zmMX`y^+XO*#^P6Zy%=)%GStBm7N(-HQ>(rwP zaU@tD#N9uue|tiJmJH;aVWug!@2bjTH9_mox0%(S+oe-E3RpmU|Gd+=9AYq^$zSmu zCkg=oV1Wdk-r`Pb47?P3LrwUqw!86~ldt|oJsuGz$}C5f*C>2{+6<~<@y)>9m^8%b zoBRtE)B~Ae-mz}np2mo&-lqqrmcc=3IMB%is1AV3ad_z1@wi9&*rMu)r*6I_UaOgS*t7v`JU!m{h6FffKx6285++CT zF#JE@`v1*;^#2prFXdzC{g@3~qi!52qlz;J3}q%dILQ zkNE-gjV>=JY%D8tNNOld{v0$5->F_2mS0hBqih4JN0$;)#tNsOgoI0wu6w~K3sa~| zKjXj6Tt2)#e7~I(*nAe^e+0tECGOZJ3knEy`gr@iy+UvVh=}x%<*wLgGLf^<@o_OR zu`ZL~gMFi7+B)>xg!(Ra(f&z%&j&|ZUU8BQQyO6y)*tciVbOdL(gzbgZ=PwcGB#?B z#7E%5+Oclq8`>Hv3jlq~KsnJ06&HYqTUe%Y7W@k^{EJ#G+7J&C`V)ADZMh|8k1{R* z?x?6t2^U(-06_Vzs!ehRA0C1f%&*)Eb3c~_u=7PuH@gKc7%a{|{seyj42b9tX|22n zR2MM-^bfJB>E=uO_XEO|a9n(PQ4zwyP_tQ*qj#jF5&fUOsw@MGJ{banii<{t433bZ z!BDeUEeRxy%n|*s&NNnm8M&;0yf0@}qeAiEe=8L&-GJ{Qg8=`{#)Xuc9OVUr zWJGijq&(;Im&zFdqX5`R?h}Fm*S~BT8k@kbkWoOG0@b}w?-jK%^e5{Oc9w{yI6Oe@ za?dXy-6vB((4dg6Pj(AJDi~_IDt(hJn{p9H{8aA8ZTVDUkavbkCydXtY~i-L+aTFyWw5i>xLDHB5e5=PhYj`j+H6JEC7(E)CBoF;DunQKmC?)2l#+U{w*xpgq-przX4%m<<{Q4(+HnI zq6Bz&!89O2OkQ@Bs!6Mh!fcKanfJ zP=A0$dG~Ii{4Hf`;RWL~Kz~xT{;Y{7Arpq=U*cYW6RtB25=iYG1uBYI0fP2<=<}bj zv>{08Y?mvd43Yam{D10h;QGo@2>>cuQ{zDGPu2j)fdgvxeEYx^0IV##sZcz0Ef{L@ z$aoYvm?20~Div>l3)Fm0l3^1_4U|SO)Fh3c&p`&Tzo9=VtJkwfa48c2SZiB*CV``3 zwt)UUJXfK3u)l2KXHh!>f4K~o@FXxn1$kVi7<}wcAf^Ho{%n>Gs8%r4L=s$l39n%! z|DTks91(PJ1OPIN@o5@1n;dR{=#7wAehchhE-}RD9VHM~T+*jXoMmt^oEA4C2QK}x=>g+HKnWMe=$I)7_>zS{S}IkA*u zLAJ>>T^a2?Jb46T9U1kiRgCaLy_f&UQT<@MSrEZ)3}K2fF$+W%y(Is#QEwC5lP~mc zcpba?!I!SxLW99XxZZSj`v~o38zrUgZ_!fom5{T-e=GQmN7Z7xIQ4Zx$!p3)lZ%{I zio7dhx;mJi68d>Iu}}$@`jdTqP5I1w<4B}mcx!>DG1KMOJKyY(hd4r9ny6A0=fEv$ z1D(qCt=R65w>w=3omrF+r6YB$KY_(9y$xgw!CO!~K|_(d*w(zs23sTh(b-RGq71)` zIKHib-w))t>tQ~gkaV2brv<sI``7rxL>a9-C6KkCt*xMZyrw)^LkQa1rO(bo zfq_Td(9DJ4K=hD2kXSaHENiOJy+8#IoggKRL?K@f5EeJ?CX6)9RMy%yX3}~6frbnY zks74lU=QtcYNo{N-&!fl-H&4^Qy$%IwXN=Y8F__j%O-ymAIg;Twf3ZA=cQ%3_;%Mc zoc+Ux*X1m3gPEgJFX9WUSB;H5iB=)M`-`9>jKRnXFERVfk9wG?Dlr=7*Zm`^`jket z$qPMUzu8k}F4~cXUy(~qObUBl=a5e5sakp+G)j~T}!y> zhT-O4BjD42cem1~f7dr$oy8v!IE|Zgf<;80ml&WnB`~Jq!hMSn-98dD9$dl2!fr(8 zo+4b*JeMi(wAM-8km0hsy1VW^MA}B133o$M|L!|g!Zz&X1l;s^t)ngCgeT79T2vS<#ikSR#;Gd6gKu-;TE>Lw41UHUT)N`CsQr0 zb*Zl@fC#64&fZTPjhO5{uJ@~=k0u^h9P^}*k;Y(swv!M?apeBX`2gNy3dQgv?x-h+ z)uz$bRnGBkO2ww@lRP{j*(EjJ47P0?O!AAL2TP)k@x?1!TY$;wE%`3KJjIgkRp+Mu z^u{F%<03i|n^Nl#bUgf-C#R@@Y0!Jo~9HAjf8TMTEW;l9Bzr;drwj}BkM z5u4Yv7dXl{H*`Bz&-%neD{;h5uv$GY*_dt_=^PmAF^+9!eks!1Oz4IKh|Xm$%@xo- za{j)g9~6xA)zn;46UF~32-4sz>BloVi`P6Tz&!rG3FNn4LODH^$$ z%@DOSqZiZKc$9)p$J*+cPOZ_m&wXIDD&c9`G!x}`o`W}0>4j(@B5|t9^y`_90q|hN zf$PbZx%w&tvS0JWh1VIuAe@i$>w-(qp%(V7Cxv@mZ{w!u9Ql`2d{cl6PRTWyvq?%5 z`r}mt9Z6NMFOlVO<0t5=qK@fT$XH$x^ql=`9E2lnVQwujt=5=qS~hIL@$Ncqfm?q4 zvC6Vx9+As_HB8?GE?E}e2|ULAahZ8_drgjPWyqb+b=lQR2DX(U*f3Me#n2Y-2cW*p3Nr6B-X%8Td#>##|jcvniPjK1N-&jP5irFi!LneOh_4 zSQ)M{KBsW98~-e^N0N`@5kD4bf}&&j?orD26x{B}aq~k^E?A$&ra}2(EV@aRQ97`4 ze9SpUrz1T}V!_cO*igyhkGN*fL>M%H)NPG%qKPb&t#93#;q zCcNhh>`m7&%Tb4#+%L4;#RyA{Mi^n3h<>i*kk!Xkn%Z1Sp^W!gdf5&qfj`6CXCp|- zIb9&2s;uqQKqh>sx-=kiP5&low@$_B8^ru$Sh} zrgz~ZsZq+}c`ikDd|Nq6C5oodl~nk6JQ+&)G2B)PjY{n4i(t1qa^X=w$CZl``9;vM zxxxzd$th|cVbS4iAziE}%X3BL}M4ZVG%blGG`9c5E zCl}E<5htt}kKuKiP5YJpTv&~z;0-27wBjMiG@T3{2WCo3?^89Uk5pQ(XcG^zRi8a{FS(Y$+eJYPmahmzoGOLuxyhw}2fnYm7U zKE!V8o?|0^SvR8ukzaeL2M*qFO)#^_>G?)HIsdXwQZY6R3FXeAHbZ{kjpFB&i{6|C z?D~KWNd^=NFfM5{qW4hK1jVIKU#&|Dx6TMV+FEVx=JR~kn0<=MK~=2I3T@EU5)uwe zuzewUHVU^g=c^6V2v*Tu3EsM{+L!X*LyM`u$qjlwzG7)34(TWtDRE-;$ymrfx_=F{B|{mxP4x7Ot|P?mtgnGu?JvbKI;P7& zLMX{Y9bm=O0s_9wNBAkpAj4;SWWRmXjKL$QZp@ zxAG*P2&7pBG`n|qUuWwx5Bqi9G#mYw4iu^MM?v^hWg)L8Xeu=hHdz1c}7X!NkyI?|GB9@I-& z04f@K_VSEWJ5A+Rk2AZhJkVz9Vv3m4_E)X{E~%DstG2V;taIw%w0s2Ws08aO?OlypT{)4Dv5@YLNWsV@ihK` zeVNYdmg@28YP`lAr#*@=l)ng7TX_6MtFuB(AE~S;OeVEce38pFM#Bcf>VAeFvg`Of zhN{rqQ5HV?rvz;wAFh7FGEb=yoP;JF5gFc-PdQpFtd}Yn)hTGAd^q zapXSR9xv=8A!WLubC#?NUL;XcSa$hdE`t0n#aP|-X1DUW0ZMtdp+%B$k7kHPh-A$+ z-`=kb47;rD(L%=Ckh`_NEX%>{a6E+`m@u8T^6+jW$Q#9(egat^@#9BnGqo6cHp^X6 ziuOGrriZylplSGS0=15~pj4x}~7)v`%o<0xk4HbF)*PjU%I75@toc z0-Ze)W=Z^PmLRf}`MqUh(b}%|xLXh66y_k0>!S*&vX>hd5AWV9=mf2ac-}&facQOZ z?;QLN#%BK+ad45Vl*`WQaM_?fR9 z87vOokw+-ua?(Gm7>OWJvPw#uT{=`2$`_T7w$V>4e(zA|^X{#bOHY036%P?NXE_}` zNWP`rMkINtkThqgVoZVCtW~y zZ1Q%-VYjti54SLB&rUH`s=+i~diuqA3=cNMV;j~#4zZ?|+_{kTxh;1y0~K_?myBwV zXIII37{yI4bf>KL4hd3n@p)<#FrA&o zg&T4BylF22t1J!lwh5ZYTqL-bi;@&oj}>@wHg^hoPDVC3V|J2hTrXTY_`3wm#iyg5 z4Xh|0vs>Z}T_iq7k0&))b4`{BYR?d1;&f$(|xK7rc+^~Uy>0iD%iXSzSiL6@1cB;mqX zYmtiiACw;x7`ZjU9X#C%{H$BSe2Nm5a08?6?#~@Z)p$4pI_0Ykx5K=m<#KrZ)ZEOo zJOvbsJJoe)o4~W<45ZU!ecsNP9u#;=PFtn^oo6zUOT_ETwS}?#i1hUGS}mz&N8qyPk!sOf(YUrtubV(YNUX@}WqWZI@XY z-p^leAo{Zq6}1-f?WOcWt{LuAZ$4X#fl&B(Jcn9?Hw1APTS7AWUa6adx=fA?4rvV4 zq8Ir$Zt-St{50euzx>V!OfSyPA+rX2#C~K}lAwowgm+-?i`K;xZiRm&Dc4uI*l&9z z-=)l22iVC|{vo)*#U~Oq^j|Arw*2Oa;1_Eol26qpwMT+qn{Ciw57r!q^$S)jQhwd$ zz&l)@)^6d)5Dg|d0p=fk+O(J0Vc57uhV3&p>c-1j!m+0^aiQGTSjn|?yk%;qEa^nT zgoqBx;X(jLS~JEFRqUnl4O}64bV-UQU9VHvxM9|{dR}}o<+AeC(=L*4VI)0mvI?*m z81(9T@tHH1EwZ)#dtML)jfG>UhDc?)KKrO8MT*k&@b{Ll>9&C-*5tqW*61f;q-FAs z#BPN3{(yJq`Ou{*0e5L3Uz=$nRIT{qU4OoR>z4O2rquGCdYs+nTpM-KY{S9U%R{}G z%GSgzWb<&}-i!<*qz*Pm@l?%%H{Os~zuz1fS&fTz zmKlE$*p{~qPGihe0&-!#cW1v;^Hj%q{FHtvxqV`tjc3ug;iEO3va#Xl3i6iBC8R<< z4NW(bO>8ygzg-`qv<$Q^7%voX{q(Swh(c=vAvrMtGB_~@kY za`Oh0>I1bbPPRWmbwB-bFo@4;^PE24eX7E%JC>H56(=}7X}@l}JW^DkjW)#p;ISK{ zm5SUoURkeOTdd*~WtufDj1PIkuI`mjn59XYdF^{m&Ra@cHZmDT^wcis8Y`44iN?ZN}EdFVI-mBo4z~yF^8BVvJ57{O$`zff3?=0^d7V7KmIhiHcN+4&SdK z7@aPHStJmz;u*EV#F%M`a_p>RZCtCBluh4kQB)aESfoh;axm?#U6{&OX@@I^a3~P> zhmQ@E|M9%}6Qo1EqE2j#>xH6r-3Dg@yqySSaqx(7Ebk|Z@HN-=NGN12TDqlG4q@TG zP{L?&dVcs89!-v@K%ZT;2Qx@{JLn33Gne`mnQw!ZwpwZF+i)iHZS*?h^cG@JuAHV~ zSc?F7X=01mc63Ox@M#p$YY8@j!Ei#xEn#HLP>PqFH6}@}0oJd}!l+?&@FAh2o1IR; zbxZNHt3!A+I6)XZWlu_oN9>1|)l zL!iF|ol`Z?B@Q3isdgXkk|BwRCf5>n@#z@mn+HgmkpFp%g4Yz_fmn$%>b`*rt$v7G z0t!jyv%T4kJ|$D?y^tbtvSn)6Kbg~pM;oHxCm%C7u$1Ml50_7e;7-|o`xqW%N1>K^bTOVV|fH&JM;VCn)LAEliwtTMm4jdHyW#f^ z$$;G%3Ca(X*{{0-)hcoygDxEvJT1xhII(i482dFm+N$d59)j&whvCA5VqDPH#_tuO z9iihe`Mg-Ef>`5=ozAPxT^p&0=c*>#+!fs|a-ioq;6T+`k(Dh$5h-r z&6&OL2zo(>X2Z4qtx*19)v8a(V(S;5o5Gf#M~vw%a*f%c-Yj~zZGLW>KQ@Tx*T;Qs zM{D&`;#byRFYif!mEwy@4RsNW5_lqDlZbF1M7q>EZ_G(F5N#? zl28gS^6jcPtrUOuQup@mUf<}R9oNE-*5e5-?vX^rs5c3y5pVoPnv>mpVjXQ=tsk!& zGh8Fwq(9rFc6Smnm#dsfh3G_Zj&BsXxH>tNpKWh%AFq$^>W{9!j6^TJO>v#~JqsDu zNYM`bN#w5KfrmG=gMt!}Y4i}Ne$mbWjz8MB591933Yw{Kgz8xjcS95PDQY`Of8@jzmoiPRK!BLCb zh^;lT2E@U{kHX{LT=gkIGdjT;>fy@#?tO`OW<=keP(-IQ@7)fiTX-TOmsNLh&1vUPViFNqBZpT^l{gKhC=wI*mMaK0hO z&IQb|?c-EHkdW#gA(N-8WzG_UySaOx^|;bJ%As_>pr5u>_w4|GC7Et7k9_{qZB6XE zK$Yq6+m2rjyM=7nSl)uom{@KfM&Qo{Nk#s9gmJ(eS^RwVYz0!F`>H1VPLY~07#4xy)TgH}JzUon zM(^>e4(Uwp(8M_V5($L^2I#yjYw5fv;V4svMAz)dYy;;t(_9YpOEae7q$Yx@5KIoS zx#N(+&&GL8--sPju?OklI(hI_1kFr*>q!ecSHQS(f!Qo`FMh3ET!46t(gEz7!Aih#tcy1QSV2UHeYjP81DhSsEk9q~3p*9~N=DOrNr$xL z1sf;7)VHPG7LIz%2ior|K|&p`M)OxKK-t!OI_*}a-$sRZb2=rUZFwla@{gKM(h?={ zW?xYB!dINay+a+%W|f+@-4peR;%>nxkA_5()+5WrIIeiir{6@2M6(jK-YZt>HkcJL zUfpJUt1)NU^6#HxN?J|e%`sAQt0c?VK4oa2nQ2{<)jm`#Lz zUoeYW+_!Nky9&MUQp6vT+&){7?AFVA!zdZbpbXPSxwhW1-gpccM=!=c)YdLls!78@ znAm;UtdG6txXwTDROCo+!ODmgUiD^Hl$Z_GDpcZm9XPryFeZjF@AdV|g$#@}$zu#Z zDLdRmlt@cMY97od>4}0SCc0(l@qCCE(vrO@xyKl%d1$6Bk(_LYESn5SQ$NI*U|W*r zXTK!p*kbYdNQ|CVDR&YBrnlsKRj3#^?fE7(0p>J5tfE`2I12j{Y&LVk}^B&iltFIx;j#|nxyiW zZGu!X&+>*@5*W&(|A5M683-j?+;>1Yg>4pTiY#@i6|Hn<+(2Qg0JaYt+I62Rb^I<_ z8O?L-%sJf=9mQ-GzK2QsQIDQ&K5`@&ivbm*QhXJ5>ncT-uYOwx40krOgma?j7Omji zRH`%-b2E}eSu5h8s{t~>3G8&p_Oql!p;1Ntz&fDbMH$e3SUQtC7l>%+H2fXrG_^!rum_kl>7$kyTqLz^w0qWAU&f66!jzIIAo;d17(`dB zEmeP8@?D~i(_SFP&(X+M8WnCSuy-_J6?5KY=G_t69Kgo0OSS9d1xO+sV20S6!TIz? zE*s(FnG$8Dj?xaZ8g_u2+$IC80Qh4SJnbYH6SOg$36nI?^=X3~M=j1;=#ip;>a~*6CGz8r{5F3d-^1(8^7^E z0cVo-E*D)u^SCpy(0CKecFgFd{WY(niDAZKeCn=Y&gh41`oe2{kQ2O^Drb*PUc!%K zEBQ!xuP{T*AyOI(pzV=sY(W-bneG`{4$c&*y2vN^n_P#)+;ahRU5hlzDtOZ8X zd(@@KlxMklU;)C{d~Zduqo0}(XjQ8*s$T-0$@vB*-ocq%o`?+BF?g?(l9&i`euXuVC zg8{_@BcbhOkDU<`VaJ%)jHT`37Dy?}jy^R5D^a(^@bQW|D=|_}ZA6%~M3byb(3rGE zUkYFnx)SDfydonRN;?@e!|TMWn4bB=uE&s?eElMlk^ERt2Rzb$DjI}U$j?*Jb^9eG zQWrDwPwDI1<72RrM$+bbIyEBf~h? zq1Q95V_Y;EG`apP(r3!isia&yZB?pUe7sk@+x$g_#PIp>8UM>@+Ud5BT2_D4Whbvr zzx+|ZdFzvZ4ybRRkl7z_AN!?*jV&t*(Xt+TSI$mzhtG@q^V(6>1*bS4m+zOTuVWsdhZq zJoDQT>}?ShA$9BJwaBsxQy+*AP$7o2aGhv0k1K-V_Y{_3kx{gHVNZA4mz?ukuZ$XL zL5Cj=HeGYKQrD=TjwT9M-za|@9lYma&zeS4LZIIH!hPP{x;Bo$J634wDi2nqwP@O{__ zf-2gTk5M2RiJXUWrgFKE2_c`>8RQIxjn^b$b3)w%rpZNK%hn zztQ~tF}B+iVp%3EkT6{|P<&<{f%{E5*XO*7;_#h%Ftvr=ZiVi(6f@wippOkoQ3Vp+ z8=<1WDc|-o$d-?GQYfzhuMi7;$^3I%j_S`}jkLeJN!xrqZHP1Bi_>ggVzWPP$!1)m zj#AV#hLvyKjDcvL^!5>XXq(rycwudoZ7@-p^=FSur{5P$)0;)%2qqZ!fN<{J%eqS5 z#nX1gLbijw_xy&;CJ}ncyMkDj?$%NXpMM3riRE}|N`^&H0`3nP7;lc6k^WuKo*h9 z3Z#nX;r$Nzaz*K)jTbDS#`?Y`qmN&iv$6>b)hsfUL-LBQk{l)FXJBa_dye9*- z>*44ELtxjo_DEi8dY6C=KRM!dX;cXsf@xl9@y#*G|T(Fm7U`l z5tIZkFK(@71~IaPGQ`(fIP!IMSu#FpN9=*@7ae<`=@E?KZKeb-S63c6=Z5xLMJZi1 z2GZ-;aaeR=3*LoQzI5y=ZicWr8cCUhADo#VgIGgRkRjF6(FOSiok+9P3b9f*W@h~t zEBXcTtRR#X|A~aC&+IvpCCQPX!joy7>Qtgmcb*yt#dEn*0DBlb3%|61=8aNe5 zFk4WT$z5}Zt%l~MeVxAMv7K$h34rI9WWz|K*xl7MY{oMhbKb-^=>Q;DZ1fDrbg;f5 zN&-nx<3+fwQv%mXu;a7URHZGbCH&xe* z2JxbX%G^?koF2lm1I-a%b~-c-9ptiBw?^2Y<82IA`(bas5u%MDymiSaY=ajuxw$kg_>@L9 z`_h1g(nnb(4(YK<-ov=kSR!nGP>sm6-qG?Jt^J%*K)ddm0#udOb<=K?`8peY*C1k8 z{=3N=yiuiW;^$DXl|1Y^jPvS-Vr|}W$Be8X`AgWt{hwje#@a{1t7DXxYMq8D;&$t= zFc>H|w#BP}ZY+ibWc4Su;|cx1_8*ey>;=|i0VJW9U0?fKOtM~C_wEnJThN29Kryw- zEntOeHiwgZb?)vM@-p^$NoI#V7+p^WFX5{7-+yG)Sg8$PF}Xyhz6kpDGS;@cZ+lV9 z$qJBLs}h(Q(?^rp>5_B@*g+|LIF7V2&d^Lz9$r;@6;RO(5=CwhwaVZ;JQp;-yl}ZP z-)VHwtPx5OK6ZKQIK~bOwC$~PF-a>~>G+U!s7N#KspK6p$(^G8nR9~38hB-d?lAPBVxo!AmjYCDK~(hNeH@ zcu9}k2D5Nad6_vmBIi#_Bgtb~uq(=Ve|m$`TAai|5#$dU42nZ!t1s{hpyWNVpcbMy z_%v3AR0j9FD3CVc&ChbK&ZuoL>G#oAEO@yiOTtW%BcxLqW+ks{#Xqk?o~AN+Nru80 zC_re2fi-Z0BPGe6`8!h+FetrpoK74%xIxxXGBYhZMc1eZ(4?%KSC#SWv?}mdN$Gku zSmwanZoG@E022-gP1@mmc7M{b6%L(W(q!m8bRTeIL5ivsAQ z+>!b(C7JKNtn^p=eqLlPSob>X;EO#^lJe8JDLojFbpODSULJy7kQ^-1T%(a3reDE$ zX`MsQr*Qm(lJzqmQr+Jxu?lQgSikAMr0{{HDN(C(@$=M$Hvi=tU{kUN=38SYqSB`S zueht>CGjXwIxnal)#bUvjcG~_0dl^XafI#9wVAL0`u?V`eXgCMN@)bdXjth#)pJw` zLkt0$f|F|a&8N>RKWT4MY}R~sK&OYA5YYgD(vI?A{_^emixssz(wnc#UiQ%BI${9O zpXdW-r-Q| zJj?&ONVzyU**Qr~N&gp(6(sxjBDMWrG*&K9FaM#jaj^VDV`t(0m&V2QUm7b5I|!8W zzqiNA%K1+ptn3{Bw8z2uZ@(No>^%Q%kB5c*AN_b(IYCJ-|Mz}*IM_f5IR7^qD=Qc4 zfAwQ!<>vnHI9NG&K{NgzS)PCAij9>Wl(+ML=VN2#;Q6mC8!IO$=jDI-xIydp9~uWQ z&p++)u>PYT8xK3nKe9aRy#F098xPk%`mwX}{4-bVoGcvwZI7MjUprvuVdwgnkAw5S z{j&3L|Jw%-FWZ0T0JK7^-2a&a4o>!e)(B)8f75^dz5bW&a&U68{VU7O^Iu&!IC=lE zH4cy&{MQaRc-jBej~B%GpMJSGd075C4sIUKf9wTB=cXBdH{TiT+aoUMFS2Xhe9 z!JyO}?6g0t(~c>J0V8gU$K{3rg?6 z(r|V_YN1>}Lpb09AQFrPvX0!_--rs?kyCPA}FcttqSXfd+ksHR% z!O6n|Gqgq9yLuR%-PI66aHsbz_HOY|+QHrhW$yyfz>h^(0Q*-6`Z&aRro=gS3>49~U2= zAQvYm50?OpYpZ+sR*}N)BJSTwQyGVX_5%(5fwu=;hEBdXK@^3}IVW_gZ2+SDldf6gNZFdpx7V=;g z!~fx&gjGvpSQm1(2p5zL3JI-m zFwiO}drKE97%xB69OL4QLf8>{Bx!MKbK*%Iypwb|>j=fw_g5H32(u0lj%L*nmJ`ZR zWtr+mNj;EC+l#l4mJmq@*7R1xoz)FZy8pCeE-sB)5xhRY!1}Kw zK!dtN!q&3J&U(0(tC9{#ZSgCm zhqjlr$Dn^@$e=BLK2@Pr3FokPa4|<&;3EHq2^dEN61<>L9!Oh+9SrW|>fnMhH?xJo z?OpB6P|g^%r9BL8?qF++aE8GhQQ#EbYc!7bxXg3hYpgq7JlpE9%rg`VQ_sI+yDkQb4DO-P%c|+Faz;zy0-Iw@&t)S zBhk)CSHN~xdvm}~q=Pdc!O|H4kqG!>2Iv9I2iOC;K>^?x4337utzmG$N12`B(8 zas(8?;D9bbDxk*|26uzO-C=ORB~QT6Eu2t07=d~aE`aOXqXRH;LEAz*7BjE~0UH3g ztSdAIJ1Oj}z>cvQSg-&YTL)(}=y_+hY~`YCZPAVxG(f=|VQC3*c`L+Dr!7h?Y*7Fu zFy1a!4z64CM+=E?hQ`6t6>W>{Vhc-k*1`~V%rcLcCpE8yNI`lCz{q$)6WGkz!3Je-1}!iQcr#&VDQD8wMz}$2Mb8u_HLS$_LM}mzIctT(o?XR{D&gOOq4AK=44M6GOzuBW(NPjPoW#b5Pg!P_6Mw%xhl z$NmHbg<$;rU>`5U1>*txSL_eu@d@&7)dhJw?RMJyUHG#;fC0h5{y=|RoIqNDI)i=! zKsY`g7xKih4?5aQ+Cf(5|`@OF@ZLSBAA z5P$^{_Y-;0$4(sE=QcyQAsoOD!T}1Q{&(u_gjhIGIfN_J4#XiGp>XHN17sX-eooNm z76W+rw)%rYEc|VJfE@J;5eP6g1ETI{0%`)01cf`zArMdn>~9-1w&l-O5F$_lVhq#@ zN<&~Fq@nyBVs=6ZStt&b2>>~gM_?N-FoHkxKp8KD?{*%P{}UEyvjZEO&%ZUx1OWqf zeh?MdfrAF=FF!2yKWD_QLI~*YA9gkX^06}plI|TnVgq8w! z^tNZhPWkS>q4-YzA4AYTMC8Ae?F=#qcYlU}1oR!Tz6fzoAzC=)zg%AZM5R!m+Fc42-J#_i-)h>wAU^=a5Uq*)|kcZ$92bzvlp& zv$-p3pWIQJ2>K>36OYX%hN#dBWu{U;Ua`@p5)gb_7&+RsoFP1;CTON*@835&vsRJI zX4j>Yk@@rm%}{5coVs=FD{j6w87YUaebL~bD(m+l5>rpQ7_e`SvF)g?HEZeh&;*4C zR`Rbajj|}XA2VFz8qZZ>*yOf-WyZO%lAb*gSaBaoc=;hmV2O*ns7)X-lHRSEi65e+Nlo6Px8~YO!nU)qXBgOb0O_N(5uN2T3EecYS5*q(O;(_#hI}*>|iHAUb{!Kj8iF^nt)()7A$i@HIptp9qckPv6499`v z6Zi6*=HC@$xUZeOcO)oR?x30Djnt&V`eDAz3FN6GOs-U1r;q8X`1+@vxQ%-15c%Pu z_WN~~!UDT@4UadoTC15bzH|Hg_n(;l1H!v?^EeR=C!*ohXy7X{PK{=VQ={S3XgD?6 zPbCyijfPdy{ts89{bpi@6VY%Y8csy}pDLp5Hs}32K}k^HcR8u~8L#pMpY6*;DF zxl}gmGR*_8U@w`-5KGg?N2UpU@MMj{N~JhXAWlzERqIt%b@xfhMvNXmm4D=T_E}Al zmND0JT&L4EDGOtZ?t0qLG2EoQ@dwf9Uk!)YW?=MrqZ9^@bnIX>15Hg6~`o8i1BQwK)ISBN-d;}SQ z@d^OTw_V@uA$u%ta58DfXpHCo(9CcL&QBA=ZQCm$0lqDZLC8jI`-ipv0w3~sY{Pc! zxS(>#Uh99?$`HZGLb+G&aJ$6>H&%u_1OL|$i#>MKcSM=( z5CXdU_p>3$-)&)t9fAK-D?>m8M9A*n?!KY;&Mf#-2+g!V<^z~JOxkT_$hG@q7)~vN zQ_JAgGB~x&uWbwNbQA7$6LfkJce)98x(PZv_di@M^V{+M-^C7S!}?LM?y`F_HPO;XEAQh1w6cbrJO)8n`g_}zIL`IA1Gw)7@}Q1${r$_E z9nSSPFsl16aQzMGr+&ME=Xc=)r=R+zDcI2%;Pg|FG7fhpXUjkQjxe?p?r1D`!W~WK zpTd87CI@@b*MF+g0fV&L^S9P-`l+J7>ZkA<1V=lXtK^)IF&;d)kxc8Pf9 z0%uV*9i3Q24DBEIi#vDqUoRy7@7esDOzg>{}yJ(5iYk?g)R%*bVyZVb;1Kh1r|Mj;@apTTi{a8Hs2_HD&11Ego zgb$qXfxFTcy5IJ{g(E(u#a$)zADLX>gc8Jq!K{j=N zVG5Mq(P!<1f6`~|gYcRS`I`11EOi#15R;ffGA$V#mLT9ky=LQp*2c?7;3iac6mOXL^FP5`TW1y(`CriCFW+`FpmaaAG8SZDyaD{{j04P59hA4M1N=a z_Mdru;MwgK;qO3lbMyXYOPBmc(&i;61;N*%d2zM&_}l!3UOM{*B(mI$gM!U6L_6GG zY1a|g6iq#TaPy=A36j0x)TbBl+4V!5Ay+nfzo^%|_?-BN{|rh(9VYd3C4<4C$xiYy zzT}j1a0rPQ|5LKve#SZ?rUysW9^|Fv^hju( zXk>5K9xge4Z!s=MkSL>pK{Qo=(7^LnlF~O=gwf`=3l=R!_#$+Axy*0>fGqBwT%2Jb z!Wm`1eJ3UY=a3!ekR9ic9p!9`#@&;PyC?UjR}I`fx&JrZldFOgl7CaF@bYh|T_A1ba<`lQotd(ul-mh+^8XnALx=1duoQ4jkp~GqDa2h(Ch7PBp`xgxzWEiOW?}ZPX!wa0l3#`NRziypzhJpVLhJif) z#4`lYtN&Yv7xVZ3s-W9)c(G!3D=nOEzusMZO1y#=mi9lWU3U9p_&XiZf2gC|ebnmj zKynHEu6IiActLno;%MER-U^4Llr7IxVc~$mA%@(}H;f`44>*EOk-3D@mC83<(}17i zz8x4y?{9%Ob$La&Y4+j3d3~E2ne)M>K_Z(gX%>x#pLlZqU?B@jQ+#RU^s0+eCjptN zbJ0WagPXKj^sJBg&9&@<7iJ}SO>R8L1| z%a1;VR)mUV7R!^pM0$95+LDxS{uNQ)-CE>-D4^r4XK~iEIO|zp)eD200c&6w+#J~c z0;^$Q`U`^t^&%Puw}!!OU~pgzYzKn_`(I#S>shsbFPr16 zXLrtJ;S_^7#o&LtVvzTrn3@8YF24!qzhonfmR8{BOMz1RrFrll|J1jFt{{01Lmyd2)1l6xD3h-jYM6Lmx7{52XmAL!r2Z3 zGlYqX{y#Lvz<97=TJFfLAh?1u;=82sN#w+dT_(0KW|VQ>|cy`_s4j2BX~UVy>X z5RmsI4G(E4b%4Gq0%HT?g)BcoksjI{RNR4&aRG4zh6Jf#P9#FeyH2#Mg5&ItH;u})j+Q6ZQw9AK2DNgdK&yS{etnnzxq`-z~@wQ^8n81>uRHMklExIGA0{(YIH&C2x zn-4UXZr_=`n++hCV)mFYL`2%>0mVF>pMC1jsB`CD;7@&N+eDu`949K#4{fR3Emc+ z<|iI%r#d0$r8)T0%_f{;WXZ030FKnh>#dtpJ6ZS}A#?;|JFX4P#SFoF4uO;-EGXWA z>urswBuETuT%>|eiavX+1`?O0L(=y*y=1|F_+50N#fjk|#!l%-A*c}xq1cfn5W$Nw z^RjYSN|zA>@yh{Ek{ZkUqz++G5Dd9I@lfX_<#ysB^#Z%g@@Ol#CJzs9nMrlFo~vo7 z);8}wHiH;Jd)U*KQF%Wo6nwp?5KlRJXfKGjB+{KbER6-8H52t&Epo-}!W0C7*3|34 z*|JWBE{IxFFW#b%2`GEIDX&(_&}gOr#4l$Z%CaTQA^_2L!L+i9e%2BLDEk>#M*y}m zuf6-d^0ErUN$avlrcjBPDv4Wg8kVyQ`;LSaxZcQTKMo2^NgB&4Y{OXdyTKOR)B)%#xghC`V41c95Z_$EPI3JRLZ(J zq{YavI6WZgoBVQd%E__?l;Ks9$$mr`&RiIOXmE}yjtJyDU@Ia){T~ES!F6_V8eL{A{PbJ7Nx0 z#_K0ndpjL6P*Ttp4>6&Vi~p4meM1>Uh#Rli5w4HYT-X`Xdu73;A*xqe4?D|Ek3}r> zs-Iri2WY%(WGXYQZ*g8g9aL#i&Z?Qg(NL! zqo}cg6lnjPKf}-#VzFr12Tv*5SKS(YF{O%xnWb=n_zR zHFGONYr3~_(NvPw+$#h-x8RuN(Wn*JCqhtSmEe^AxErAveRhj`FBjYUCpnE;y0>c1 zbEyC zP_ZtZu2e>hiL4N$E;EN_DeFp$NsFb=#*u@JuM}Q}-CD@P5)MwzH;d;JKI~txjXf72 zNHYBNJBG9AzlEtB-&)eH9;{a=_+{P^K6whS;61-lURBktt7mCsDj1s&fZHP^QYZP~+Vds&lHd&QTPe+G}?ztm>E{cYNHZ*Ds&+UZjdq zeyjsNzY^x1Ih)KHXv|JUMG4*qdvE6(klZafM-|?Lc3Zm0_>indOzME%ttwZ`nLT*R z&s7Z!3+g|IkL=^MMqP6{AGVO|Sea|0k?l70T49APmdb=x{xIHGZbWW@ePpuhFIYEu@AZ2X8(4l=x znA4^8!~0t!-nYJ;Whsn4bJ$Nsu|EQ_E+n&*O^#GHsi*f}5sWFFq&MaxgZGEtCK>c_ z)geZW)@fGhRyl~!B#mZKOud}+jmV$s9v7!%&4<~r_+toX+AohJyLFvHBvvaFW9-t zSpTf8R;N?Tb#puMy~!g8QNy4SkDj5`*WO8TG(W!A57qJdx{@qr=9fI{?h=)J)RKR3 zox0#)o~~wQs%Oub_mv9Y>|@H>wEL_)&kffYIhE{FbSlwq&}?WIYa6aluQeR8Z9Cnc zYkYga-0az>9DZ3rc+@(IbM0+b&b;2^mLNv!Z+0p2L67#bdvaAhBZ@(JHl2A_-Jq~& zo;c@RHDi?`-{BrUrWfWOPIxxl%2`z}<9=MO?1r9&;X}izq)8juPb*(v(d(-x9+Z_Q zOHHD5nXDAi9X-VR+SAMAgBI$`^(UT~0*$5f7X<$b*`piA5-) zfpcvAHRng!EV?g-`E(BDuPXOn$$4?p&DMiWgFH~k8_IA;+yjp9TGovsGD4-fLi0CZ7=UL_t-s^WX&b@LdU+8^6z&m8q%3n?vg%1v1Hvy z`gViQA&qP)|FkaMv&~UQd}CgL@9h=b>SvOQ)+Y7l)_RN&PdM6ekwjfe-^k)HFZ$@~ z(!8ho4vm9D%^8yKcSI6zP&Ru}5*$JqcAxJG7%M0MyDD;Brb+Mb8BgzLOeB+&NHc}y zK07KxzIw|VfAgf6bB^VG&^R<9W%;4G?Hip#0|vF{AfD`3oaS$rm#$*#b#+CP(&?AyNgaPpHTs$s#yWS_kI3hD}y?dmc<_Y`SW z%8@VZGbD{BPI@D=XuAQPZf*wYr4ccx<5N+}1WPZi`!jeIu8B@YV}#h%s~m+yEjxlPz3vwtLLe! zSV$NhLad;CG5MLMchqUp%*|`_A0{XUu5)B(&)u{k9B6MD5iCs!&1veUf2^j>OEVg; z7sXx0Eo>BNc-*ocj_K5We8Yr?YDutSm}T|DEXDc$u<`LZoBJg>se0kHPmW*&yYI7C zB+<4Z&L=z&q1NQ3%oi^lnA@N^oe)C(^>jh3-`zU-+wG#Ie0yWqqb~T-<<{BV^9#0sVW|XCy`83Rt-mUeliPWJTY>R?)lFdF$>2(g~fn&Yj zV%|Is6V@qsZ=Q~(VE6fCVcksWMSJKpI%M36U`@8zZPH9R_iB`iOp0)VkLz+8sb$kG zGG@(aj?>7vkf=OSrD{R%InizviNwGPW042eFW-@UJuX0*XCUlN^NmR#E#pEh^l46p zyJ5{Cf_U=gX|V{K*yAdpE#~ZX;(*pN7zrS2r=^kdGF#Pg03UNY2T| zFoA5OXZwVX&cYt=D+iFiw5v}jPiP}Qu-93%AJuHiZKbi^8xV)_^_?P>#Xl!1Za!+7 z@F5zR<<)<4=xYFh8v$u4S95Z_>-lqGV>j=SQae9#cbG!j5*psrO{*!FYd!ydKNTfu zsX#-|9r1%<$Mh&COx@etm#pDa(u&#v33*&akA2$G8PeSh>77QOd|5%6CzG$oeJH^^ zdMj_ErpM#1A$E;iwKpV(t%o36OFVR_)WA7?Q@3K~VxhNyE?swgb45Y@7maWkndCQ~ z)?KF65yV9KAt}1?(}U>S_j_|r9GCr=+#4KJ=GxAfjyQAbZeR{0b02G)<<#V8` z0c{75ySLA-wl>Mg;44Z=h#&!XzECH62LU^)Qb=`tZ2}(b zf%SH~&eO?jX~JC^B6&&U3Uu-QHqD+j31v%Un$crVs;WvAawzvxqnzA@RtqlP6l+6A zH-0v}Uq-Y{#B#1@F?{%0OYB+tt0!f$t%}ofa_5*^k|yTP41ZR;jW67?#(6gNqvVBA zgQN!%!>{f$O^gi&zmp}9dwjT(FR3t_4+4a1rdF0(8iE{7(ZCIOdaczKUH7=KMtKkw3_C_^N%C0eSLc z5$#y=4pXwiq?KwR?NYwG7D;b1!7C`gEcUgh5T|eaMmnrjWqpb$ae|*%ks-#BkC(rs zH=iI^ycz6CGZP0_SNV_2MQ|sLNaoWZ=+})J3ie4cP{-k`j@@MSuX!b5T{r%EjcdAS zAo20z20aue*R$%uwbjYlgwPW5jzJfp6JA}z(=EvlZ*^TuOz3cWD!O9KI7(T6qn78g zY@Tsw$btJGqGkO)eO14mq^9jY;y@+)A+nxn{EIY4YomFtxo66UwUfcm&5Iq?-qI=+c=+bVdmvJ@(?0p|IJ-14l~YkwVCAetoq4d_@<5wa75`P=o7uXZ&=F<_C1}bHE)>+ zrcAN<@rcs%id`9pvTqI%=Nf{YjHQluh=B&HanwrqZ6&|2;R7!k-fv#(@38G&IzXzq zC>B4U>*P~?mT$pasV6}A2cy2`jC%{6XStP6c744Ia~~hS@4Yv_VZ7(l z(>9LxQ&atU+*gr%wCt!EYtDx1yq8>RD#?8|*D`vOHP4CzsVNX;MRe?4NJnUiGQR_L_!D7EG!vA8s|WQ_c5^~$|o#7bs4la!bv z*DWPiQqR5vcYF$a%Jr!1`s1=U6^~8c%h}T~HrssYfu4JUlm3$%1S7qt?`Zc6rg&yr7au(8)Ra?JBIevZhq=ji${ zP?mZkwFaSHR2xqu)n@;&ieqEJRI$xofMVXM7=(}fhWExYdp|!)!dcqLDrBUwPezQmuu_L@%lTo zeRXa!Oqdv z_%NCy?;aaGm6K{h@Wk7kgk}jV+mss7FdIa?o0j&GFA$lv@$$}d=e-}f*D+zNGcw>I zd1!Hv%OifX9Qyk?^0$w-eNRw`6uM0Q?&O5HT5VkYeIRI3<@(ADMZ11Iy1HM{j^Z-8 zQ_2SsvVPi$kc!l|Tr8rKLFtcfYDSj`xX0v=pW!~fS7IVNvMPFsA8qsYJ!i-B+?xuh z6EByi&6YFd81D7pKM(z=FdY>)>TKSz*t$CXK(qP;hdQBHA9=KL?@9Fow|)1WEW~>t z668%nP1<`{?xs(^-ThZfRF2D^IAYCZnFYjN&0Rs%v~@O~BR(}@43J@4AHSdalxO2g z(|zzVl0H;K&1qU$Lt#O8iZ)O$d_PZh^w}E&y#+(|U0EV(FDW@S(kGI69vFp{a9X%8 zy4TBoWS`%ddAHpE6j^(+tKxYuwVbKry$LaT+kThj7wGq!zLv?~6g5{fTc%WFC`T9(Hvr|^znA4q$Zp(+=we?@wj zVS~b&?QQVA8*yGo&gkFBmBV9qt`J`Ai)A^VAm|sY@XkpuQ7hRsQSehIJdVn>X2ETt z+X!zlrNJB#CT}wx)tyIWX>)gO5c%}c;m?XaCp(rauRl3;nTjhV^yTB>j-l6qwm!+O zQ>WQ2>tEl?Y_((HIe*!>|75Yhka7nH-J}6{WzV@%K1Q96wq&sCdguF!lwdJ7{QJ$* zQP~uB!=g)8)3(XBBFoN#O|>F9!)QEZ_dV^>W4V4Q?CmV;w(LVBVK#4j#?#e|^IX9w zXltrHV_7|3Z$>Xsbp67IpfhX>hI16i^+FNBuHjeNtDnOIl2<9^F3EPhbj4e|thxH` zj+-;|iBDGa#P=sF*3mAi+2^A95<|TbX*h4+JmQkbvigNZq`XxtG~c5kbcXBQLqQ9_ z^wYj5TY@Fy4(%Acc72Cj>FKUQO|6>`h{9`M`rU9`x;j8wd0yT0h^ z_b!^=Wu)!M+w+qj*S^zVTuBfMAsa7?#1+*aH>;o z#6DI4-(+9G3mmH+;8j2Vv9i?X1a)+`e){;DXGMfXo@Vip7*Q6#mNR)N-}H}eKH5vi z9@w&0U23NsK+oS~Vd{>4(5yUc^&qI>U1H^!s;G6Z_)Q_igQCvo#MZu%D>p2Tidv;A zFFqoQp`$U#|6IJ3&Vv&lYGXawN1w*b!CtGooN+IAPev!97QbcXGN~0 zePcWISwt+kFhcI-o=Yu{KRzv6Y3O?5;5h$|_G0=>^YwH2=WaBe%{Ec}GDYHktU);J zEy}Ia$H=Fj^~{a^4bk56gyVjPOB+WklJe8Xy+2Mzm8U*wb0Aw3|B9e5eY#lssRKWa zTPz(vS1LEyiLRBK>jqH~Rk&(`mi_|`N~L|#%Y6=4?wKw->+kFC-BZdbR~V+#7ru|3 zYnA-KTUw{D^V9w>b&zyHL&SvTk6QIe8#ZhC&V22g`i~qkX0gRG6A!V`ht-&MITjER3H?>I#i-WaE^+5a(47?U!6c7D0X=ETd} z_#NQW&zQsdat|{jLprmz+{eBZ-SR3o|KxL*rtU}dbqrb^EI5;Uk2p0pBqXJ+@NCI^ zUysm>>3OY81J5%VCpw4UwH`0~&~V}0+%!jiEWRn!`piUKIuzoy;`nu95F%d~${k10l_L=9wkv;YMlx00-WVFNg zIOi%Rj7>b7^O$k!8xW+$3Q8$@BaYX-Ll0?3>|0aVGN4dbO`VzOvSlhA^etJuaJ=ZW*A< zew5U^9P}`T+r*$joODT|zM=Ypk)IEEjyw%>%6BG#r@NuwntXLGjxq1n9XZxuU_?o} zluuSZ7klL6%9DzO!=4hEE2gLWMB?edPOAMtdF{K733$dSzI>+i^ZN9)`@7mpJ~zG| zM(W*Wo4c&EAi37?xKt#@u;?9s|4Dz{A(n5jbicC+ALc@qKe>0Q9+T%6BWruBTOLyu z=4F-IZ!zqY^n=macllFm{i$?6&n7+ah8QL5S_~)g?$Qf>F(N3Op|~-{Wk!?o{iuTR z>&H(Oda5oY2AmvTYm0sg#OVcTMFUqjty@+z7A8d%D6DO5pm@JyIb;&6HA7*PcWYV~g)So1bg-ecTsd_}6nwo~B#L&!L^4rN4&BR=H)AflcX9S{hN-9t zW>4wbVr#mUK)oif(W<>nm&wfLU848yQgp|oCepNQn$!aH!UOfM6g(#Xmb5wOA#>_*Xz+l)ywa7-US)|gCh}*O-fJ3OUuD>M^?^A(CELhO%u>UF?Y{2u zOI^}2Bpv)|lf}o!(y~;?yva1%N>TRe@m6`xv23;#%R{n;jm<))p=B)$uT8pdu+YdJ zes(e>XLf&tq3hmQJI2pfKHa**BNpPu(wUdZgSZ|)Cn+QL_FZu0nEFfJXWwo`-Po*K zl<+1LV=AAt0N)x&{c~ST-gc9fS=ap`RVzQZ|IK{^*}FkWm@8`OzF#`0MUCj5tfkYK z#DsVij;{;6)6M44?&>8hE(lp2lxMXK4qz+rQDm4b&!{{7Io3`7f?)u~U1GXvuk-*~ zF9L$%dY%EJkevF)RBPAF_Tl5k#WP{+S560tW=#{PlhaRgm@rJPoD$kxJLSnY=7GKh z*ImVzXJ2erNz7q-{Na?yoTyRbQ-<`kwy`$w$|(}E)vwGAigB^k#W3LF$< ze7i@?M@ZkKc#u1ifoG$Y9$B}3%Q1R$--yxjUINmk$Gt1!S-}T}BU!2DC7Pt@0P2&~ z#w3kTsoQ$0PLUF&jSq_Q>6Uiic`h;YwTO%_BVh0Q(^{>eR(K8KdZ1gK3vJ_uchA$= zs-%xDYV$M{tcp7xAOmAMv`Fc|zYqTTO5BSQrLITyXzq6(SDz$V48_QFmDD>@tb4Nt z)rFm1eExt?%+@n~6qERI`lE)J*QP2F6X}v-#&;9Fr>zx{tYPtVR(B>4NV1a|lRxg- z_Sc$yq5)qOoC}NnORCCssgH0z6lv#p)XgY7$w0kuoii-dnbBaI*I?;j^tz0Jx`M{K>b!Y>mBG2@p;PItsn>K? zN=)r<)+O7rJv#huSSGs(V|;R2V374pdTSybqWQ*~_{B1*ekr>2B$@0-=ZRHcM5f>R zNZQ^!QI9|?i|=MGVN3_zN|HRS_AR8gIaf|k2P8iA%d z#%Y1~nYiGOIk7<@031CzXw9Fq?@{pJXr7T`S4?mH($dVQ#EJyb_=)T4GADDr4*LXW z-7Da@CK@t+-|YD`gZ|s%Qh4^Ayrd9e=fx4{>h5?XizZ2BOb#k+$km9(C)SVS%SrIo z=}UGp5FYalmSa$QNR4?EQe04Ic}R23MaPC_x#JAUj0=OcUB&(A_IMy7r&L;zoCYAC z**{M((i#5Dp@AnQGehK~F~FaUxC+fMeLR^N4$>x2e8Q4qM!DWG1~qjgg2HB3(!L zo=Z4%JGis-vo!4LEt%xkSEJH(kYmq%ttbwXYQk-riIyZ1526f7 zUFF9niaYQ>G3W;yOp%i+KG|z-NZMgbd9v1@^1Tny(7D)fS(&aS!_(zU?`4(Sb#Lc{ zQ!_SYB$EL_OVX_M7^$Wn-<@+$Jv!p92ivkS>{%=b9daFPhcQgXin_m8gry4;wyDQe ztyw=j&e-%|_2XbLjKRzc&+raV825`Tlf{k8Pzi;#}q@YaSNB(%j_>P6=@kqo$PhLUwL9TAQ;esuct zshKM|(eCcEW>Y$I3Qooa%9b80!EbbopPdR+_KQA8p~UYutQz~tiNXBDc^2`3$?S(3 z2S`Up=sAYe10Q~!>`Eq#YBqcLB#GjHc2+&IpF*dA$A{pM-neBNLH%A$lhh1$D{ogH zpt$z%rm3A85))$Ww?o~+RQ-@%g0ru?|$7e z&@X|G|FmZHdhm@Y3-#8{wIR>y4%r_QAFp0r$xX0`S=YDvDos;4m<_%buEY;~Iu$Q0 zptdQ+;TAdjd{JT(Og@EvHoVOdXI9dwSB!_w%g$7QubZV#28-Z9qBM=Ha2eWD$*m+V zA{J%m^<%taOsi|tj@iW4I*F?PI@I(_BUQ5Y&H9_HU-_&Z#JO)_0=3c$I6A(*551E? z(i^~OQf zd*^&-QXyFkv`V)jxDg}$_UHro*2|q4r`F#Q)~GBTh!7bdc1ph?zW8u-5V#2y^lbFb2EZgCp%>euAWU&4XM$M*FFi?f` z8lMlRfQ|?8G}-sT>qUD0 zMUpI0O!V0n^5j$a^1($xAse}QGUw=ezcA@=ds68A5JU`hpESKN6g*5HUq(kN=E}xM zYxcY;R!C1RqJp(GhMB&mR(xcw>s+vCR5(EY-dEb3n&|pdCVH=jKi!Y^@hy0t5lU70 zZ5bXF^g$O}{9+OG%>4OA^tNtOoQEak3uXZSN zJf`Sg8)b#k!xwe}41H-|Mct(LsGE~=icLB?*&>Ekl$NHPb9-s)2bH>FLfqIzQ_Iuv z^!G(taqHX8Wzzew29Wtqy4fOea+GZrK-I$V%FvQZXzo8?0E0~sHOHFgmp@%QO#(geh3u3mi-Z0>F_*? zyN6&lX{WWc^-e-#<8{CNvZjzxluj!0#|T~kE>?A)ZPlGyvedh zsfi5dU9P%)UGA~8Rp?iZBPi?5R{AvFV0gFncwTETg_=J7xVYZXQ|6_-DfIi|dH+EH z?c1H?%ql&X{fA#fN?b`oEG9T-QRER5mXvG=))HnJCu$BJN)Pq~txm6x=9x^}O^h0o#rY2TC&;lAyHLOD)*+SR1s zAH;MPy2-PYO-i{&Dv1*a_+`pS)}3RnDOL&Q7ro}_sgGHb)R|6Mxc=B0qlTE{gCS{(*u9o3?b$GV!NgaKv%*QwJiF}`nR*H4Phh53V zgD>$Yc0$5%n`sUyO#hjOacQR8%eF^9@jXj$C2JIuQ{@3T+fz-OuW^8 zzTh(PN=|;7_)zoOGred%Ce!#XQkO@>cgBxuK04|~>nvrlb~{JS=AJL1@GDBa4|@tZ zzbS8~oX98nq4bc>!{WfCewavC`Qi&!Mql@iL-#`6nxqSp*EADu6(se3O{aNch~}P% zKb&5CW8H1hPB_L(hphPaUH%R7g%$c(C`O-->?{MpkoThdhz1zYmxV-j@0`XaSMA5o$$^~ z|7sPcCprCuj<9I4g!%%zXY@_h`iA7x_`dc#**i+^O1yw$UHa0&GOI2RhE1 z@!yT{C`f>47P84_k2hK#^8Yto66JtbdM^S@-bcpx3xNaXa}p57aq=4 zmaa4w%gTSr=gRI0?Q<^s$X%-yOQfJGIO#9YA)>tAv3hhM!;)Tf`Jfw$TR)20}8oI_5`Vj&~@$*Z8qiPn_*@C%SpbbxkxtfRn6+@(jbkAURn0XFXj`) zV2j$CuBM^(#nCjkiza^wfoLzOjksYHV5xtO3bi-;NL~ddpwcV*o?LgT;HHwUXVW1@ zeWK};sFsrRR^Q5w@Dpz|N(*)dR)yxV&VEmRxhS|)K2zGM1hz|`Gr^~pB|k^4_HeSs z`qUf5sFRU7B;;=Sk^JV(QI`l7u?)48Oz0Ym?oW6@*g;0t=|{U^QnC>}TAf0w}MkXcAHci8T z_JhJ=QlX5PTehHQmv1}AfsMXGw7;&7>HB`g#|?LlUYXGw9d3)X^qk8R67uIxDPlXE z&>2*A!yxyW8GWZncyL$BH`CJuPFel~XiCP%ac0*&N?aFg)s<>IlZbgKE)bnBaX|~P zQysS4ND=umQ?MjmdBz0wj3%l_vC)mqY0mVu`Tj?zd>O;uONt-))O#;Jir`7p%j=>Q z6P~>0-1?Vl^SF?AmTz@#+&ze7SeC53<#)}iF_~4JdtEdI6*Jkts9kbwW4I&1ve?r* z&F2SFLt$~l(4Q*XByRGnpwJ}Al2)e4xifvPAJK8nv|+QCy1~a5J1wTS-x@?}=f{x} z_aaDNt#m(C9`Nd1^h+{FT)I<}#IOCi&5)7%@{j((ft5-c*aNt z_jHhac*^{N+sg{ZacMd;CDf78_a@d^)-S1k?EU;*-`3?R>@Il~2M4n*#SHTD5xXD* z3{|jGs@<%4_w9S%GRp6E`?k074%`(TYCM(Q?ejG zZwWKkUpfM}c^~HQ@HOLe`?q^q#`{#Fy^!?OqwU6}W5e-m9^Yo%7Wh=06ANhuDBtsW z8_<80W=jh3Ldvx1-WO^r9UE_b8%H(sO>~(2Ly)7fo7@o5msZ)E;Zr9oM%m9WOe$vu zpMG}7=IYI`<(@v`Rhtjq4<^E!hQ<>l?Us5l1!oE=872dg#_~z5Gj8`@FJ(U={a1-K#lOO2)R2DZQ2Xl2CIZlGk0ey~>;C?BPQMPi%mEpJA@AI`mrlq@Hjd zTghG;rE$JjaUt<^roI|Hgck42IyS$`zpG|x}M-) z@Z#?7?(P>4?v~&L2=49qmHS zzDt(0EGN#iFfSkd9Bv7*%f-Sr|M^Wt?#T%BexNqlBQH6N%vS5`VtpGjNR~LpF>_BZ zeW+`c6=(8k1{P|O{Pw`PliMEKp+i^fQVj&$lwngKL^NtlK*4%{T5(LBP|pu)mVF8g zGxyU~{7Fp1gqUGgfl@XStz1!PouO*PK8k+X+wx6a*+#LVdrPLjrA+fJHc;0s48-ns%9OU=l1f+sjS$PXpNN>MpzQ$yPd3` zY%9#jEya9+bNLDjpV3R#6Jz+1@v&OSIC7waqgfBe3|t;D-)U3qSgGeHaz4ibipU~zqQG6* zXI?ZS{u6^F4}w{>x-8K^V0n4k@(`|1eD5mBi`ZaIA< z&CcX>eLDy@hL`^Ug~r8jXp76K9b2P^A}Z+vgs0?U zGLrMX+NR0=ImbpZBoV*M%UfEGfwuf~Ku#*|toeKQpuE1pDar^W_{R?X9E8F$jn8+0 zpnPKl7Zrb@br5q|_#>?elH+KmM;SZQYE=Ug@2~0bprM^p2NM%fH~5E(SD9&Xb~+L7 zsAhDwI^m(s{Ae@ubQXNbJ;^XHq1qFv!#wyT7nWxzQbh@YF@tbXr`fB9Qh~ydYA!7) z)e%9RP2^)vlW%N+O@=0@n`oZ(jfB=m0h>c5yS|KDGSm{;IS>@WZaF9|?icC#(|Q%7 zmy&?vQ<$fgaMs?;i=85`^DGB8%Y+zBUN(B;1Q%J~e6_3%V?!W~`w*LXfZ8v7}O&$wNRy}{&j+Ynb znkKtY>b&wNapwbd=LfZ<%0{0>**vDerBR=q#y1t?NID1rN{qGG{=~ zP%RL&mqDibCf7R)?cj_kG2{H~EFML-LZYjfN(>R^BfgorAzoYt4Zkx#z=AghaE%G< z=mfbY_askEHY^e{i^ozDuD#3O*TO+(-l^P(#G@f6KLls4;VGTIB>H=TU=aHQpjf6URYO`H}fgBfTlT zgxv!j#ya<>3j0s^_+^vfmeoJ!>L7q*I3sP|nX*HcKAUB42iRC2lKRzBHjqDw#iD(d zhQ(o|q5};{ETRz_!oOt&*F~-_8c?`){G#njsfl5e( zFe?*=AQ!1z!24VX?_m9YK(`St2c=gbgGwx!4oSU^8T*X740wHAqhh}XgmZEztFHQd zjBTe;KM;g7(CyBkjLx!1I_Y9JCvW#ZY9){9sF^0h{4~`PCahcfwTd6Cu?9GKiUK3d zD(G3H!FO6G1Uf;4%*!Tn2-M=1{m~W!(FYeMe%(foGQ(( zGLU02ok^T1kb!f!9XJR0) zx>!UA z7Z$qrvy@GA&WVf**VH7^I$)YT!l~4KTUb3_l_Rsf*hO!$k~S)-F8py2`^h9|8b$C+ z*~4LW;?S_fm7I9dtJ8e-rGT#MQKU!oozhLlbwRm^8j*|9jwCUqmVwn*eX9TjfX|Ky zL`D~t@X+&eC_e*%65EN~0sTF-Z2R>=awm3i3=81sp2B$YLis452Tif-idXpsnVHER zEa%YP7yl%{0DaB7@ypR3$NP78-c-gjDFAN7anJ2?pKW4@=QoC^*PM_SWkCbm4z(^Y zfY@KB%*BvU8u5ybfll60JCm4#+2`m4liFEp9sn*d*Sg$S?@k`&%pG$H7|MHloO0bV z@87*M#iM`D2>4Y!+;nn$&XNk&u0sNiJlpkFIy!h0+{*TBNCF1PI_N1}9y9Zg*I9}s z-HyyT7bU1yU|BOk2;Bn*tcCf<3FNI}hID@ZVycEwyXs zBPlr2_I8cGsY~LG(N;vAS^m&fRJei!_BvW+OhUQ+>o8BqrpUTaH{RnP#<$h(c$UI1%%G~@a0^gr?He-V;?0XGRrvF%})+|lTV7MSGXyr zg$BV6V~^gN&D$9DF$>k|JjQEevs5{sttWDjG8VtO>&1}6m!S@pure2oom%xhf!b4f z=2B-@^mX3EKV$6?PgH7%2z5v}k0ZhQAnyKI{o4})G-V*?3=2)UeOFZ$n+aNfzRj%u z+%CP!QNRM)`{$j`hXv$ zQD!-+yhh>s(`HZ=t8WJG#-t%e-{fDYpdM%$<{j(C?P-jd>V0}}Y8f1qh69~Ufa(Ca zoQKCg&R;aio0H=|AGjr}j}*Ne#qzCf4Rvt*FEFk@MI5%PEFRBDAA3|C@zl+?#A`JZ z51TfCji<*O-;e<345$x%Pr~F#9)|x1T>pO)9{vBs^-DP#fG%kI|Afl_djaA93-mtI z<6G1a$>8Q!^l%EY3x3<&yxgi1@|YjAzR~3cg^gup4oMA#$)AH};XBn!!}2T2ZIo?5 z_2^P!%2?qHlaO!;(seHwWnl_+>1X`6nahW_hwrzO0-Mi5{ExKoafv&&$$|m`oj%?^ zZ?6!X0U{zjWVtK$nat$u^nBdR%xudf_+a0tn70o7HleWquy(B5_=dJd$_hZ=GEh#mLd6B(;TD#uoCW^^ z4F955i#EiAg#HAcVOwsA*`tgLfIBKGQ^JK7GXPM2t7?;+!H0(+1@kMn!raeg1?+s0 z)6H&y3kHkxk3Yd50Ha0phqP8+q*WI&0Q3*Bsp;lR`}YIFlyF>pdQlO=!BDeVlcRT} zq!Im}zN#$K7JV`V1Qi#J3K<+BMT4Pcu~`yG7?~sbU!7^J(q`nc0rI|_RgDV8ga55m zv~;6=4;ci&#;!!>hbT8$*Ax4&h*pXo|xF)Gqh@qNV?23J4k$()G!1K}ZEdO?O4)!#pJ802tm< zLF6w%{Uy~SMj4`k1kLH$ui*Nmj}ZN*J4SkG_53FRuoK+ak}6ny5Txv`7Kq;DW7wjg zqK%d_EwhLjAjp&%A%6)b6AU#C5?its^Do=}9b=RsV-WNwV?DENjF3rGd_eqiZ$GW2 zh&cdq@B$ejd$=iZ762=6MNJe@{qZS4=Eq!40653b za3x&5?;wG3Q*KEW6j=yT=BDPKPeEO{1<;?qYS$erQ;JytAWf+W@`2!mV5mR+mT(97 zXp#I|ShWec=IafR;azE5T5IfJJ%tZlU}wWozLD<1|2jQnmi9i6Tclr%25dbDq2(HwA!Dn z0gwX+)ExQtfhz!5Sq@X7c<5R%)Z~%zC~`1Ekfc;9-T*hK`J5!fCXg8@jbNxr8b6p^AehFMB7;3yEqYwEQ@^=VQ z@?9gP3Gy!Xz$_4BN*$*s8_9Ggcs_){725}2iwhp z2o7TiQ;dmOT4d2n@-G|pHnBbVLhpvxv8x|^>Dnzc7|ew0O=q`{&~CO-QtJK|Ej3>W zxhnj(g3o}e7Td+CuMnp&$EezO1RXY?CWdFXWkn}BK^W! z3p|aPFTdXTW`{h)5#rKBm8v)gZc!WPRIYEuc7MFx=|bqtqJ$_Nsbl>KENJL~sY3q(6+Co;lr$2B zd_6!|+_;-C(lAq5YulJf@AU^7GB`wPka~k7w9l!T60d)2r7U+pjf{ri- zBP+bb95X-aVWz6YXjoqNkErTX8rdf=^o0FpPg%I>MjC!aE;Th}sm~%us9DbDUJj4w zS4HxrTE>MM&1H+k;J~HhcTsdL;iemgn}3afPygNB%8>qD-*9yne?;IkZq5l75qVx> zfZCM6n2Ha7puArohu$Cv`)H+wSV_y894m8*L`s4N3jG z?^FrM_g~Hj@E%hrh97Z9Jvps5jkd0Gj&D;cHeH|O;R(qusqtp8ZR22)U;I2+ z6LpL)UfJ6MOipjfck$&ZmUOQ=H}$7CE?Fs0<3A2iiTnjOl%`&gkoX6LIpH>4YquZ| z!3PWdf|Ugzstd^GBFC2>Wq;ulbA&g$;EePithnhi?eA7F%qLBHy22)`iB7QLrWgzU zY$mKZLTue)JTndV4Td>&OniQH_!^Gbyr#XtS-!cU+p&7qCmvdfBX)w->Uqh|e9J`d zz*LWMY%}vqk-=s{Hyl88E^}$FfcBBARXipvPJZeD-fD9!bm66_Zh_v!R7{Nd4f=JE zM^B=p0ONEbsCyRHc5F=Addx}D$i-}isGSA9n9jzd6m&Y)R>yp5jlO;E1EW<5Pt&HE zCR;m| z9BB)4Yk_IC#$?yBVHb{f*KrHn^6QUPmJRcWT=uJB{w8qAy7*4uG47Ac!mHbBa%3w* z?tHGxpl~xSfmMxp7py&Df?4! zyCdh#4?($LeHxnv<%hB8CRHZsz{>G4=NO%i^el-5M~h%XC5u1enmrR?JkVG*NXgGT zB?d6n{*PVJ8T(?+P!7e^f3)OSoK?EoFZgR&;;_ev)Q3t>zF$S`Wo{vsViY=!| z^&Mt!GZZjLpj zJycGUCH$`U0{ooJG1Q+{O#5<-#DJLao-eRBUBe> zA6IE=b18)~-e>7$JDddm40E5IASLH?fq<&Awo?O{@S*C`fXFrdn*geGpql8}jPo?5 zwo6hM#||bDFlpCo(829%1Y%(?&7Do}!bei0l*RL0it6~ba+FFGO`$8P@bP#ul=5S^ ztrQxS*wYumZg=FuqkhgS7bWtGpkZ@`73z~y)I7qX!`VXmSW(vX{6jAy6`BEFw^2DF zJlJUnNrBSwbi#-@lOfhSI}`GQ{-sYYqH`inSTi2O>olA8EB(2!8cV?&%#disLy&1g z+mUYOB!>sPZp%xzEla0>_AFz{9fde~lJDFq&oGb&GLr&L@lArU;EZP6(c!wQoV+?| zX$ni0w&aYh%Ma!;->_pZyN76>blIY1l7subd%Z{u4TH8mAb0BO3mDS3tXQLEQmT@y z^Y#{7iu-AoSzgPPshG2?`;2)G9vAS}llJzU92^`p5)u>Zhq2jnDT%U=JfVNY!5n@i zk>*Sq8oFm>)^^#n6`bkt@O~Mc4o~aS)!`{iWB525a~F6Ko$`Ma(~ugN;lqB!!b+#D z9N^9A(7O9n086~7Xo&h&1gDPL->*9+>{I{ce5WYl^M0^F{ld^jp~@47n)y@ECRB@v z@7kt>&D4I`GVXo;CCejG8=jPg((&cK>M)zutwH4O(~ply79;$b8n{K1n(wdS6UQIT zyEn)4WhC?{39h#Er$==tFTa~v>cr}oK#|bKC5=Y(9%`DPxb*3(bxGmY8DU3T ztF7I9p3fSyPfm22LN<~-YLulm4 zw81O~>znef2%5t>6z_x6g6VuP+gfs^iinSx^gV^)!jA079>}s;;1hY@=jsV%r^CtN=l|F|h zvi{D}0Pp-_oUib)o8R;R@4)F6|J`saPx6UCnoTgCuMKwy6JHCnczA^;zrJ3SxY!51X+kH2&IRk*6W(%!%UzIVO3H`!QbtC>2Ah6H5UIZhFqapp#w^TSV# zRj&nmuanuEon(SW4~wlMExG1Fy_5x7MMKYC;7GO8RDSh1i_6LbU8XLkh&f$<)%x#} zYALsBJIl>F_r8lu@2+>2XFa_Ss5uNt-kl!d_%lDQY6-inCB>x05vL=cP)~}MPMZaP z=-_mOs%1giSAY4{1TzEAUR(m{H96hEy%*olIzEq~Dl~VLh0p#eL08C!tDmq8EH#3Y(4;3K!+Y|{ zXDHRVjOcTVNW&~=d|hWVB1dqNrD(vq!=riJ#3HM3yqYw`?q0+tnU->p`5t66A4x zQ~_1?a^vFR-FpR{pfwTCTj((^t@Qq#lb=>v&zi+i?Od$Dv#^V|PD}7azYyc7Q;3q1 zj$0y1aezmn()_s+y3}5ZuUs-2lHEXPF?;+6S2hRv-axuU#r|!$<8u(PQ)-#YAJ){7 z@acpkXSD73hP?Z3YjBfxJT8Ri3hYT0)$gxXK8CZ9v)y%h(xKmEE4igZA=tHv&KA(Z z?dw9afKy+DKOCBADH@ADh7U1*<|{`Ai-ULM5lXn6^v^0rB1n|1lG0_D4wZ%SMdhPy z^b?EUI~4l7dn@HKP@j6mL&VKlPDc-tZ)vv?NggUB%^9i~l&jfPX9yYm3@uO(2%$uF zFEFRIGA5A(GD%|BeO^zbyoVD*tXsKBqHt(%&xWx{K7(aRbfwLBgfbgD!GQKr+iNUz zSP~(tyB!hs*tz0ZZYa?!0bNujVkjhOsFT);8A9|1g<6I?-(Fe|?_?CJpD-?D0JI7n zZ({U;C4}Zv(T6RSMHdY9!Rw1Do*`{yk|hGiNKMy;LMuNoN#L#BJd04>G>OYBsFSuu z*m3svlWyF}*t#b3P+R-#RDSK4AmWQn-p(}awzlix7AEc4DaJ-Mn8wS%usDz5!H#%r z!}iA^*3^h{jWCL;-~Uen^`u4gs~N7{83KDJPBVTz#iey9;cXce;_Z)vv{qGL6?h? zXd_za8Cw=RBJb9Yl8>rC(AQc6tsQ4xzVc`i_<54eM1~Pv(%2%yd$xy#XfhwkGrBoc z_P~!IvxI(SK{oL7!4mHNe+(Ua1}mTs;*h)XX*(C&R8Q z(BI{#2F@pRGIWWT$F`K0P=BI#Bnom2p`fp9*u@e;)pN zPQHFJJnSrcK9UFjlNdgGP+MQ3 z&nBXcVd@J|ptZ{)pM>@m5hZsucL7KFx8C9wa%(F(ua`YX;~(sY3zxK)KPUvk=jHnZ zZUfXC+g}EBR*RkK|0oAtX3mm?3uCQCD&~JseoSEG)&zF|yA}A^wu1Q-B`o0vM%~?? zJC3UHa0GP9R~v4Jc}2_R@c5~DSZ09*6pK66b!eNkXU7>xr^))foiRNq@RVG(O8q;} zWFnV{*OzMxWBC#3>E*RrQq7LU_noUx4_7GDQJJr)uJeOLFuPTSU#iyzf;$n`Yio8r z3s;$GB*0DME#RVW(+A{3kucjXvogG&zurLfXCW$TE#%uv>4jV~-lyJtwiW}S@bQ3$ zT7x$PaTi-cGWuSrn}fQ{j*JdzjMbtS`8RIyW^nv8EPrST11A$fF3iYI-qQ`op+ z*0p+Gd@|*-^3~HWl5b%o16{HTZ82@otLw#Qu3YxW*81;xK@>C=j-47JmFfB%qm~pY zO4GyNTfU~-29{Wp|K?j`n1qp*$vYCe5!U+y-ks+|pQ=Q=O9%PdOcSAM#UJnb^Zi@5 zyq7VhmhaT#>^9fhsEcMB4z^w%>cv#HCT1bKhx_(sWH{kmT%0klir{6FZsw{Wrq+bX zEnFdWusMpSY8JflhQ#{)=D^5mT&%Oq_=~`{ylrqAQ>GFvH|BeH_DeOeI?m&#^h?R@ z6WeS&tHuo6e2+d{&$1^!e^n6<*!3 zwB)Qf!Rbl+b=&2Uq5@sCA^r!@Zj4SUa@Tley>4x>ic6Gv*0eA_<-o{o!;$)f&<~fMXDnc{r%T2vEQ_X-B<+1#xe4Z zfp%4x&Aw_(Ov0a_Sty$`G@YBzrN-?2xe5n~FI8(7H*|w6b$^2LLscLEPm-%XQNl+>Cl$UnE4nu;bGp4t&Lxxv93uRhP`%)ir~T+oj&;8 z7mNZU#Qy}ocdjfDxnL3%sSq8$UqdiDT?Dg8AYKI=wZg=hX^C>|tYm9ktCf^Z-)vD- z8BbWGNuuRs-d(#em9NqcR}SG+Anp$z8z}$ddGjYohk8Yw*cjIfMeVu`&V=@MB9PU= zBgV13pD4oDT-zg|kgaIxmQFc@mFGeUqs8g@;ahk#IidnXcGVutAm#0#EBwt|>Q`jG z4LZ7NrKNAfnJl-_>rB&Ih(Wn>nu=j90^p^IEn?fzA<4q0QADpL*a!y02^qJ9kugIl zUUJr$B)JAyzb*@-hSkA`gpO`@Isw-$#m}w|;nCm(Vephib!h9>#V5IlD%k4;Dx2F^ z>m*bUa6B1=Oh4ybqGcXs>63Ct@FYrq?Y4_iaYulet5e$_YZ;cmb*S&J{^KPW&7=8A`tyWTuXj1RV*md0Z$HcGXPj{)E)T7)1ACT3!NvEI?x60 z0jtG?m}2qS@P_PR(_73iUo(Q*gt++hkjlh{>Eb@8ulLJY_p<8Fz|5HWXVZk=%t~BV zAw?o2OeF)}?6-ucEYt=L zn7CAPdy!LToe(ZEs8Li7ezot0-#a7&c4s6gKTKx7?g~_^$bAgDbW{LalJ9Y1ggVW?N*23!h>Sm(ALK96`>uW<1qQWSgC?oYRxR=I1Coa^~+QW_p!w=l!&Y;rd)`G5g0<+&s;hz3&KmL5F6;wf?P8{$bUsPsn2H7oVHLmY+vV z=`M1O*`eO7dbe$UZksO-F_>D9tyZOXA+PYdlUN>gAMz~3Twn^>oBw{I7Ig<*}iQpRFC~|RiawNDv~M5A z8wM0KQ{f2X_uxBz@q*}fHwOxct7uHJzWbk1H$0KiK(uCNRgP?L96f+m3^k)~ls}t* zL?DLu_xO5nw$ytm{Y3U4o4A!9rbSE{WIX#QPH+P_k3#E__fo=%?BBD=YndjCX6-}P zT86H}#3z9@^rx}5N$mbGaf?4_im*WG0c*Uk z9LVeg=QY#Z4h%~(rs1R}f~pYA4zao8kiyT#c}?Gl9a6Ce8Q?mB_$q>CCcgEgg`F#4 z+_|*btaC4ZtzF}<>;7LJZi3E{0&I5d+hJU2@tC9oI5vZoXv?)qI~S=JQ&M9E5h3>B zR`CsNc09NIe04AERNyO_Oz$Nf(vlZ!ocvPXmUde>>oFhbzOMucb-WtQU$xN6w&v4o zw<`TMD!iN1DFJQEL;00|)O3=TD2X@wf}$6`;uP*3>S#8r)U@rMs81Ak3r2Y~B$~7y zStiDD$74SICR!w#m7w!pu~N6etcdaIHrrc`Im?!R{~S}&Y65SLk(yg2S;qb;Lj%oB z>zb_gp<*HL{JE;-bx|{24y`E}{7?UaS=8dbjYHX0=zW(W{)puE*@9%ZUe+5%$xsGm zm^R9_^^Wz%W576iG4`RhcBxWL8V16|?#pI<>^_1-H!PC0p+NlyRBp>aDB0q^1Hvh6vq)29 zsZ*_Jr90yW3R?xRecGX2_qkHX?~;|#z+-2w>5k|q7PIg@OuCPH^lbByBf(eBT1CCB2M}mT4p$boetT4)|4nTs>mN$ z2h_VL1KJPkXSPs64go5G$3~(CuPs5mYw9f}SQz^kEyAnVRo^)V93z};j32{YD}L+* zD$q}QG8^bIrhQq0cf>ri{$!wmV$+2+M#oO2PvdjUO+n_z&4g24=m>YqV<-W-az+-3 zxwn>om89PhzAv^4{iWZ(JxVo-&85+UFq<|M&Sm)m5e=P&zr&oSmWUhn0Fx$t)DnZ6 zq_&N2&l>B?n6Y1&QW6Cu-xda==!&(a>TgTFOVn|?3&i+28re#t!Yu`kjwY;PuDi^< zJ3^ZS*fNdsMC+Qv*lLn~i>%4<(70KX-FXKDj3Sz;zbA8qNkjFNGs}D`~iVltCgpqk-33w3? z9tIIdt|6P~INLb=p6K1vCqdo#jSmVqlXQ2v=mMI@or#6Un^?AEMlbEJc^yrRGZy1h zcMWq!KV;JvUh9LL;KfwAdTjC%ejHoLN5XrB8Db8R(pb>i9=XOAWD%C>o}uO7Owrjs zMOtGhlGF&w<}$q+FjSTMck__qw8iX^TuEzG-{d2L=ec0cQ=dU+nlh-_s|cJcRatrG zGB<<}_1tCe3sf4u6-OLl!koZbU^Kl)U5ZS3mYW9_AbidDRunt>sR@BrwHl-PCE%Hy zZ(!mboZ01x$Z#FQr?BMI5YM~M`_6>C)(MxTAAb9=tZCCu!WmwyCDObzoMPMzauvJv zcb`Y7$KoyK_eIG#xy#>zd=~Ah(#609anf|!XInz2fJx4VPd#E!)sD~CdH@Hc32aK5 zl~RGeCQ<3)oDLS6MNQ$Kebh^WSWL5R!xxGzDL9)!QS! zVK8Ypy3fp^UKpp&u6_Z6ySRSE)1w#+C>|IIZ7+N5jF1RB#=K@KZ5OvdN?CUFsTo*_ zx+R8>SJYXFk$P$)!lWabWLtv9q$~PT0F%&_Ft6hk8Od1M$*37#Ctk(;%pZ0=hScQi z7moIo@pJ^qS2tq^=FYjQ_fB$<>G0pQr+U?z2e>G zFES*C&xg>)q6*1qxeBgtzE4_XrOx;13|CSu$7+A<$0$-TowE|DBrjZsXu z25jXgx1J2`dwpwvZo2hdm|Ja6uC_D#*e02Td-2ftu8MrkQc>+=l}1^knc`K4R(j@- zMHggwK2&0}MKqCqI}F**5Vj$(?GP2_g3?D>G*@oO zC=6BKnew1%7Y%ljXl$eqa~23$L@q0kDxQb;JLJn1rHeLRuz(ud`<9G8er3+eCM;C5 z$WW4F1gdlIQy|F{x&Mn>sFVp6!NTi4Vsy)QbrQUia*y)Lr*F}(!wzPD}7j|0sVhI*=iiWDb zhFF;kD`!LmKKzre0N?-Zvv?334OChWXBQX(hqkpx@>0{g1Z?=p5syowO3)BY^GZzt zRqfU4xP-iFR@Zx37dedHwiYZ6!)OA+2PUM1L<~%_%3iLkIlky<5IDBzSpoYc(^7ktLKNzShE#udB8ml2UdN8Zq6=H_F0AsUV^?uAgw@eV${hUQ%={R| z8j6Apsh*B5$T#Rknx$5VmAWxA>%UkrEQlw6tF6}W^vyKynT30lS>4)xA#ZB47v>*W zskukOcp#zP9dlKUbWL*{C)gfc?@h!;+p5r{QS=o>7P)KV8-*+jeo1!jw=(oBvp0Tw z@T40^qkD|8Hyb3+YSpl<pH(6P1vxmbBnGj@W&USfr8iGbK*5&P8DhN?hBJ@ zhpeh&o1@ADFaJgPUU+Zz5r)>lr9gt&g0f8RnnP?gG%xMz^fizDY#UAhJijCxMjFNL zuBKr#p2?W&Cca4r0KsabXE>&V^$k&ymIO6kgvUB1aGeC}9&!G&>B?+uJrZ&v_V_uh zf`q1MR?AcHoPZI2rN?XIqS2IpWJsho+%}T-NH=2s?DV zjp1rP?9Deqv@wLYE*XVw@FM2CXRF7Y0Jt3KRCb>tq=lGNV> zwbbF=otH?AAI>wfGwak3O|;uKu~t!z9~2UyPkf}82!WN4LD4b-x`r9oq3G{Y&5bT- z)Gg60zX*sOd{s8trJu+Z;(6T9SG$2Ro<&PLxgh!~dtZt@0iR4JSIITUOq54#TIyt<)Sn|ItXBP&S$ z683QaXV|o{_L1=F80Do}r(ue?-TEsG2Fi_X@hYGji!lLN{fYf}LO-zmha@^jf%RAb zN$6$Q*ZvlhtXHSR)?Fu!7T0Gu%A|HA78b}3`4FbVe~4Tbc?LkKm7!eIzBjZxI;K6) z<#sdbgYbzU3cf)2*z}C0&zfz<=}^l7t;d&m z81M~UPMSc1gN~Eh?c&umiF+D`ra$0#NsrtHvv5y&nI$czGgA z!c37Pq*EDZC9iA6Kd(ZbrZRg;hQb&qKxl@6HSmBVCCQ%oJ5v)dD!p=^P8>S8LDo>R zFfThr*Qf~4q^z7*mGSGeD)3iH>3TI-=D^!-yo;>RCL9u)w8Qu8{-kFw96Ax@6w;gq zFw$Of82>rxD_~CRrpg?yipR#HW#Zn6M9VD8y#_x}J--@k!1Ah&V~sGn89B{q3}a7u zWX!(tY^QHQA+R4D>C?c-i|iVhr(GB=vHqrlopv!OVHx<^c|A>&6KvD?AXdb@nOSmZ zi20@PcZ2dvE6e3#Fyg5yg4-JSEM|EI$1Wb)#KU;6m1D#*WzStCIeNYe8NTpkg8BDP zv}+x2jvQ2>3EJ5v9pB=fzOmHukq&x>pY>t1Iae6iYc!I>3@aEft#j!46pnvTvVP`6s{4B-R)Osb>o?t(6h4qN zC2CbJexAC}=D&OcY)aO^d~57PRND0a6?ZkfBpwAy=LNN+x;%HdF-^%SK+ZQaj{+==4w%A{qct z+EE_NU%p*`v7(kodh>PJ%O09sM+~6#C;EWdDPsLUrEUD1@X*fCl9Y{`m4}_w#MT(} z2cGjU;NpK#*|~tg|C{RWXkrS_O3KL%&-%ZAq}*Iw99*QPr2m`729o{zBenhCG&XLK zmVapMoUH$$aj^3Km&VQgFO7|r0|ZL>pY5@+as5XJ8wclq+T-N`^(A80m>-+KW*j)4e7spJU~wF ze{BKLfd3D@&W;8a)+UbdfAgfu*qYjrg8K6pIQ7}i&Y2Ws^WX9p3r`c!GYm=u3-9D? X;OP9no@yQ-7aJQq6_tdNB>evcLfX1w literal 0 HcmV?d00001 diff --git a/api/sql.log b/api/sql.log new file mode 100644 index 0000000..b356c3d --- /dev/null +++ b/api/sql.log @@ -0,0 +1,34 @@ + +== +select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se +join users us on (us.id=se.id_user) +left join appaccess ac on (us.id=ac.id_user) +where se.idsession='3e1ICuedp5qVuLSk0ccB7F43IHoGL81uBm8GLV0H13DJeqBNVs' +and se.remote_addr='::1' +and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.157 Safari/537.36' and us.confirmkey is null and blocked is null; +== + +== +select report,structure,data_fr from reporttemplates where report='invoice_dks'; +== + +== +select invoicedata,pdfname from invoices where id='21'; +== + +== +select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se +join users us on (us.id=se.id_user) +left join appaccess ac on (us.id=ac.id_user) +where se.idsession='3e1ICuedp5qVuLSk0ccB7F43IHoGL81uBm8GLV0H13DJeqBNVs' +and se.remote_addr='::1' +and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.157 Safari/537.36' and us.confirmkey is null and blocked is null; +== + +== +select report,structure,data_fr from reporttemplates where report='invoice_dks'; +== + +== +select invoicedata,pdfname from invoices where id='21'; +== diff --git a/backoffice/index.cgi b/backoffice/index.cgi index a35ec7d..3af884b 100644 --- a/backoffice/index.cgi +++ b/backoffice/index.cgi @@ -111,8 +111,8 @@ $template->process($skl,$vars) || die "Template process failed: ", $template->er #print $skl; # my %headers = map { $_ => $cgi->http($_) } $cgi->http(); # print "Got the following headers:\n"; -# for my $header ( keys %headers ) { -# print "$header: $headers{$header}
"; +# for my $e ( keys %ENV ) { +# print "$e: $ENV{$e}
"; # } # print Dumper($skl); # print Dumper($vars); diff --git a/backoffice/js/modules_global.js b/backoffice/js/modules_global.js index a6fba9d..7981e05 100644 --- a/backoffice/js/modules_global.js +++ b/backoffice/js/modules_global.js @@ -6,8 +6,8 @@ strdata = ""; for (var i in data){ - if (typeof(data[i]) == object){ - strdata += "&" + i + "=" + encodeURIComponent(JSON.stringify(data[i]); + if (typeof(data[i]) == "object"){ + strdata += "&" + i + "=" + encodeURIComponent(JSON.stringify(data[i])); } else { strdata += "&" + i + "=" + encodeURIComponent(data[i]); } diff --git a/backoffice/sql.log b/backoffice/sql.log index f8562c4..e69de29 100644 --- a/backoffice/sql.log +++ b/backoffice/sql.log @@ -1,5023 +0,0 @@ -select id from users where username='kilian@juridig.lu' and userpassword='0ecf731e2426a8a469f06e9f4a3bcbed6f8071d9d3e3ef7ef5fd9165021e27ec' and confirmkey is null and blocked is null; -DELETE FROM sessions where id_user='4' and remote_addr='::1' and user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36'; -INSERT INTO sessions (id_user, idsession, remote_addr, user_agent) VALUES('4', '3C5oDjVm8U8u7OlDH2F0CQTfnUq47jt0Me30JCoI50eX8034KO', '::1', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36'); -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -join appaccess ac on (us.id=ac.id_user) -where se.idsession='3C5oDjVm8U8u7OlDH2F0CQTfnUq47jt0Me30JCoI50eX8034KO' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -join appaccess ac on (us.id=ac.id_user) -where se.idsession='3C5oDjVm8U8u7OlDH2F0CQTfnUq47jt0Me30JCoI50eX8034KO' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -join appaccess ac on (us.id=ac.id_user) -where se.idsession='3C5oDjVm8U8u7OlDH2F0CQTfnUq47jt0Me30JCoI50eX8034KO' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -join appaccess ac on (us.id=ac.id_user) -where se.idsession='3C5oDjVm8U8u7OlDH2F0CQTfnUq47jt0Me30JCoI50eX8034KO' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36' and us.confirmkey is null and blocked is null; -select id from users where username='kilian@juridig.lu' and userpassword='0ecf731e2426a8a469f06e9f4a3bcbed6f8071d9d3e3ef7ef5fd9165021e27ec' and confirmkey is null and blocked is null; -DELETE FROM sessions where id_user='4' and remote_addr='::1' and user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36'; -INSERT INTO sessions (id_user, idsession, remote_addr, user_agent) VALUES('4', 'A287QLL40FGV2DK77015cxM1h4XvxLGHg5kJwHdthR26LSVniW', '::1', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36'); -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -join appaccess ac on (us.id=ac.id_user) -where se.idsession='A287QLL40FGV2DK77015cxM1h4XvxLGHg5kJwHdthR26LSVniW' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -join appaccess ac on (us.id=ac.id_user) -where se.idsession='A287QLL40FGV2DK77015cxM1h4XvxLGHg5kJwHdthR26LSVniW' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -join appaccess ac on (us.id=ac.id_user) -where se.idsession='A287QLL40FGV2DK77015cxM1h4XvxLGHg5kJwHdthR26LSVniW' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -join appaccess ac on (us.id=ac.id_user) -where se.idsession='A287QLL40FGV2DK77015cxM1h4XvxLGHg5kJwHdthR26LSVniW' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36' and us.confirmkey is null and blocked is null; -select id from users where username='kilian@juridig.lu' and userpassword='0ecf731e2426a8a469f06e9f4a3bcbed6f8071d9d3e3ef7ef5fd9165021e27ec' and confirmkey is null and blocked is null; -DELETE FROM sessions where id_user='4' and remote_addr='::1' and user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36'; -INSERT INTO sessions (id_user, idsession, remote_addr, user_agent) VALUES('4', 'JMF1XpHDO8n4lL5v778P68tq51oKhdWuEU001IN0uAmp0Q5MB8', '::1', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36'); -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -join appaccess ac on (us.id=ac.id_user) -where se.idsession='JMF1XpHDO8n4lL5v778P68tq51oKhdWuEU001IN0uAmp0Q5MB8' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -join appaccess ac on (us.id=ac.id_user) -where se.idsession='JMF1XpHDO8n4lL5v778P68tq51oKhdWuEU001IN0uAmp0Q5MB8' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -join appaccess ac on (us.id=ac.id_user) -where se.idsession='JMF1XpHDO8n4lL5v778P68tq51oKhdWuEU001IN0uAmp0Q5MB8' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -join appaccess ac on (us.id=ac.id_user) -where se.idsession='JMF1XpHDO8n4lL5v778P68tq51oKhdWuEU001IN0uAmp0Q5MB8' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36' and us.confirmkey is null and blocked is null; -select id from users where username='kilian@juridig.lu' and userpassword='0ecf731e2426a8a469f06e9f4a3bcbed6f8071d9d3e3ef7ef5fd9165021e27ec' and confirmkey is null and blocked is null; -DELETE FROM sessions where id_user='4' and remote_addr='::1' and user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36'; -INSERT INTO sessions (id_user, idsession, remote_addr, user_agent) VALUES('4', '2836OMLovfIh3nMW71O5DPq0EuW25qH728a3m0lAHU6347GIm4', '::1', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36'); -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -join appaccess ac on (us.id=ac.id_user) -where se.idsession='2836OMLovfIh3nMW71O5DPq0EuW25qH728a3m0lAHU6347GIm4' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -join appaccess ac on (us.id=ac.id_user) -where se.idsession='2836OMLovfIh3nMW71O5DPq0EuW25qH728a3m0lAHU6347GIm4' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -join appaccess ac on (us.id=ac.id_user) -where se.idsession='2836OMLovfIh3nMW71O5DPq0EuW25qH728a3m0lAHU6347GIm4' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -join appaccess ac on (us.id=ac.id_user) -where se.idsession='2836OMLovfIh3nMW71O5DPq0EuW25qH728a3m0lAHU6347GIm4' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -join appaccess ac on (us.id=ac.id_user) -where se.idsession='2836OMLovfIh3nMW71O5DPq0EuW25qH728a3m0lAHU6347GIm4' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -join appaccess ac on (us.id=ac.id_user) -where se.idsession='2836OMLovfIh3nMW71O5DPq0EuW25qH728a3m0lAHU6347GIm4' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -join appaccess ac on (us.id=ac.id_user) -where se.idsession='2836OMLovfIh3nMW71O5DPq0EuW25qH728a3m0lAHU6347GIm4' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -join appaccess ac on (us.id=ac.id_user) -where se.idsession='2836OMLovfIh3nMW71O5DPq0EuW25qH728a3m0lAHU6347GIm4' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='2836OMLovfIh3nMW71O5DPq0EuW25qH728a3m0lAHU6347GIm4' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='2836OMLovfIh3nMW71O5DPq0EuW25qH728a3m0lAHU6347GIm4' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='2836OMLovfIh3nMW71O5DPq0EuW25qH728a3m0lAHU6347GIm4' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='2836OMLovfIh3nMW71O5DPq0EuW25qH728a3m0lAHU6347GIm4' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='2836OMLovfIh3nMW71O5DPq0EuW25qH728a3m0lAHU6347GIm4' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='2836OMLovfIh3nMW71O5DPq0EuW25qH728a3m0lAHU6347GIm4' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='2836OMLovfIh3nMW71O5DPq0EuW25qH728a3m0lAHU6347GIm4' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='2836OMLovfIh3nMW71O5DPq0EuW25qH728a3m0lAHU6347GIm4' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='2836OMLovfIh3nMW71O5DPq0EuW25qH728a3m0lAHU6347GIm4' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='2836OMLovfIh3nMW71O5DPq0EuW25qH728a3m0lAHU6347GIm4' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='2836OMLovfIh3nMW71O5DPq0EuW25qH728a3m0lAHU6347GIm4' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='2836OMLovfIh3nMW71O5DPq0EuW25qH728a3m0lAHU6347GIm4' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='2836OMLovfIh3nMW71O5DPq0EuW25qH728a3m0lAHU6347GIm4' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='2836OMLovfIh3nMW71O5DPq0EuW25qH728a3m0lAHU6347GIm4' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='2836OMLovfIh3nMW71O5DPq0EuW25qH728a3m0lAHU6347GIm4' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='2836OMLovfIh3nMW71O5DPq0EuW25qH728a3m0lAHU6347GIm4' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='2836OMLovfIh3nMW71O5DPq0EuW25qH728a3m0lAHU6347GIm4' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='2836OMLovfIh3nMW71O5DPq0EuW25qH728a3m0lAHU6347GIm4' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='2836OMLovfIh3nMW71O5DPq0EuW25qH728a3m0lAHU6347GIm4' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='2836OMLovfIh3nMW71O5DPq0EuW25qH728a3m0lAHU6347GIm4' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='2836OMLovfIh3nMW71O5DPq0EuW25qH728a3m0lAHU6347GIm4' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='2836OMLovfIh3nMW71O5DPq0EuW25qH728a3m0lAHU6347GIm4' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='2836OMLovfIh3nMW71O5DPq0EuW25qH728a3m0lAHU6347GIm4' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='2836OMLovfIh3nMW71O5DPq0EuW25qH728a3m0lAHU6347GIm4' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='2836OMLovfIh3nMW71O5DPq0EuW25qH728a3m0lAHU6347GIm4' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='2836OMLovfIh3nMW71O5DPq0EuW25qH728a3m0lAHU6347GIm4' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='2836OMLovfIh3nMW71O5DPq0EuW25qH728a3m0lAHU6347GIm4' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='2836OMLovfIh3nMW71O5DPq0EuW25qH728a3m0lAHU6347GIm4' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='2836OMLovfIh3nMW71O5DPq0EuW25qH728a3m0lAHU6347GIm4' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='2836OMLovfIh3nMW71O5DPq0EuW25qH728a3m0lAHU6347GIm4' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='2836OMLovfIh3nMW71O5DPq0EuW25qH728a3m0lAHU6347GIm4' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='2836OMLovfIh3nMW71O5DPq0EuW25qH728a3m0lAHU6347GIm4' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='2836OMLovfIh3nMW71O5DPq0EuW25qH728a3m0lAHU6347GIm4' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='2836OMLovfIh3nMW71O5DPq0EuW25qH728a3m0lAHU6347GIm4' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='2836OMLovfIh3nMW71O5DPq0EuW25qH728a3m0lAHU6347GIm4' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='2836OMLovfIh3nMW71O5DPq0EuW25qH728a3m0lAHU6347GIm4' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='2836OMLovfIh3nMW71O5DPq0EuW25qH728a3m0lAHU6347GIm4' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='2836OMLovfIh3nMW71O5DPq0EuW25qH728a3m0lAHU6347GIm4' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='2836OMLovfIh3nMW71O5DPq0EuW25qH728a3m0lAHU6347GIm4' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='2836OMLovfIh3nMW71O5DPq0EuW25qH728a3m0lAHU6347GIm4' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='2836OMLovfIh3nMW71O5DPq0EuW25qH728a3m0lAHU6347GIm4' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='2836OMLovfIh3nMW71O5DPq0EuW25qH728a3m0lAHU6347GIm4' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='2836OMLovfIh3nMW71O5DPq0EuW25qH728a3m0lAHU6347GIm4' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='2836OMLovfIh3nMW71O5DPq0EuW25qH728a3m0lAHU6347GIm4' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='2836OMLovfIh3nMW71O5DPq0EuW25qH728a3m0lAHU6347GIm4' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='2836OMLovfIh3nMW71O5DPq0EuW25qH728a3m0lAHU6347GIm4' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='2836OMLovfIh3nMW71O5DPq0EuW25qH728a3m0lAHU6347GIm4' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='2836OMLovfIh3nMW71O5DPq0EuW25qH728a3m0lAHU6347GIm4' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='2836OMLovfIh3nMW71O5DPq0EuW25qH728a3m0lAHU6347GIm4' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='2836OMLovfIh3nMW71O5DPq0EuW25qH728a3m0lAHU6347GIm4' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='2836OMLovfIh3nMW71O5DPq0EuW25qH728a3m0lAHU6347GIm4' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='2836OMLovfIh3nMW71O5DPq0EuW25qH728a3m0lAHU6347GIm4' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='2836OMLovfIh3nMW71O5DPq0EuW25qH728a3m0lAHU6347GIm4' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='2836OMLovfIh3nMW71O5DPq0EuW25qH728a3m0lAHU6347GIm4' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='2836OMLovfIh3nMW71O5DPq0EuW25qH728a3m0lAHU6347GIm4' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='2836OMLovfIh3nMW71O5DPq0EuW25qH728a3m0lAHU6347GIm4' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='2836OMLovfIh3nMW71O5DPq0EuW25qH728a3m0lAHU6347GIm4' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='2836OMLovfIh3nMW71O5DPq0EuW25qH728a3m0lAHU6347GIm4' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='2836OMLovfIh3nMW71O5DPq0EuW25qH728a3m0lAHU6347GIm4' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='2836OMLovfIh3nMW71O5DPq0EuW25qH728a3m0lAHU6347GIm4' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='2836OMLovfIh3nMW71O5DPq0EuW25qH728a3m0lAHU6347GIm4' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='2836OMLovfIh3nMW71O5DPq0EuW25qH728a3m0lAHU6347GIm4' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='2836OMLovfIh3nMW71O5DPq0EuW25qH728a3m0lAHU6347GIm4' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='2836OMLovfIh3nMW71O5DPq0EuW25qH728a3m0lAHU6347GIm4' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='2836OMLovfIh3nMW71O5DPq0EuW25qH728a3m0lAHU6347GIm4' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='2836OMLovfIh3nMW71O5DPq0EuW25qH728a3m0lAHU6347GIm4' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='2836OMLovfIh3nMW71O5DPq0EuW25qH728a3m0lAHU6347GIm4' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='2836OMLovfIh3nMW71O5DPq0EuW25qH728a3m0lAHU6347GIm4' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='2836OMLovfIh3nMW71O5DPq0EuW25qH728a3m0lAHU6347GIm4' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='2836OMLovfIh3nMW71O5DPq0EuW25qH728a3m0lAHU6347GIm4' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='2836OMLovfIh3nMW71O5DPq0EuW25qH728a3m0lAHU6347GIm4' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='2836OMLovfIh3nMW71O5DPq0EuW25qH728a3m0lAHU6347GIm4' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='2836OMLovfIh3nMW71O5DPq0EuW25qH728a3m0lAHU6347GIm4' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='2836OMLovfIh3nMW71O5DPq0EuW25qH728a3m0lAHU6347GIm4' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='2836OMLovfIh3nMW71O5DPq0EuW25qH728a3m0lAHU6347GIm4' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='2836OMLovfIh3nMW71O5DPq0EuW25qH728a3m0lAHU6347GIm4' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='2836OMLovfIh3nMW71O5DPq0EuW25qH728a3m0lAHU6347GIm4' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='2836OMLovfIh3nMW71O5DPq0EuW25qH728a3m0lAHU6347GIm4' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='2836OMLovfIh3nMW71O5DPq0EuW25qH728a3m0lAHU6347GIm4' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='2836OMLovfIh3nMW71O5DPq0EuW25qH728a3m0lAHU6347GIm4' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='2836OMLovfIh3nMW71O5DPq0EuW25qH728a3m0lAHU6347GIm4' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='2836OMLovfIh3nMW71O5DPq0EuW25qH728a3m0lAHU6347GIm4' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='2836OMLovfIh3nMW71O5DPq0EuW25qH728a3m0lAHU6347GIm4' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='2836OMLovfIh3nMW71O5DPq0EuW25qH728a3m0lAHU6347GIm4' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='2836OMLovfIh3nMW71O5DPq0EuW25qH728a3m0lAHU6347GIm4' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='2836OMLovfIh3nMW71O5DPq0EuW25qH728a3m0lAHU6347GIm4' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='2836OMLovfIh3nMW71O5DPq0EuW25qH728a3m0lAHU6347GIm4' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='2836OMLovfIh3nMW71O5DPq0EuW25qH728a3m0lAHU6347GIm4' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='2836OMLovfIh3nMW71O5DPq0EuW25qH728a3m0lAHU6347GIm4' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='2836OMLovfIh3nMW71O5DPq0EuW25qH728a3m0lAHU6347GIm4' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='2836OMLovfIh3nMW71O5DPq0EuW25qH728a3m0lAHU6347GIm4' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='2836OMLovfIh3nMW71O5DPq0EuW25qH728a3m0lAHU6347GIm4' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='2836OMLovfIh3nMW71O5DPq0EuW25qH728a3m0lAHU6347GIm4' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='2836OMLovfIh3nMW71O5DPq0EuW25qH728a3m0lAHU6347GIm4' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='2836OMLovfIh3nMW71O5DPq0EuW25qH728a3m0lAHU6347GIm4' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='2836OMLovfIh3nMW71O5DPq0EuW25qH728a3m0lAHU6347GIm4' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='2836OMLovfIh3nMW71O5DPq0EuW25qH728a3m0lAHU6347GIm4' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='2836OMLovfIh3nMW71O5DPq0EuW25qH728a3m0lAHU6347GIm4' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='2836OMLovfIh3nMW71O5DPq0EuW25qH728a3m0lAHU6347GIm4' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='2836OMLovfIh3nMW71O5DPq0EuW25qH728a3m0lAHU6347GIm4' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='2836OMLovfIh3nMW71O5DPq0EuW25qH728a3m0lAHU6347GIm4' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='2836OMLovfIh3nMW71O5DPq0EuW25qH728a3m0lAHU6347GIm4' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='2836OMLovfIh3nMW71O5DPq0EuW25qH728a3m0lAHU6347GIm4' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='2836OMLovfIh3nMW71O5DPq0EuW25qH728a3m0lAHU6347GIm4' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='2836OMLovfIh3nMW71O5DPq0EuW25qH728a3m0lAHU6347GIm4' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='2836OMLovfIh3nMW71O5DPq0EuW25qH728a3m0lAHU6347GIm4' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='2836OMLovfIh3nMW71O5DPq0EuW25qH728a3m0lAHU6347GIm4' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='2836OMLovfIh3nMW71O5DPq0EuW25qH728a3m0lAHU6347GIm4' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='2836OMLovfIh3nMW71O5DPq0EuW25qH728a3m0lAHU6347GIm4' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='2836OMLovfIh3nMW71O5DPq0EuW25qH728a3m0lAHU6347GIm4' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='2836OMLovfIh3nMW71O5DPq0EuW25qH728a3m0lAHU6347GIm4' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='2836OMLovfIh3nMW71O5DPq0EuW25qH728a3m0lAHU6347GIm4' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='2836OMLovfIh3nMW71O5DPq0EuW25qH728a3m0lAHU6347GIm4' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='2836OMLovfIh3nMW71O5DPq0EuW25qH728a3m0lAHU6347GIm4' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='2836OMLovfIh3nMW71O5DPq0EuW25qH728a3m0lAHU6347GIm4' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='2836OMLovfIh3nMW71O5DPq0EuW25qH728a3m0lAHU6347GIm4' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='2836OMLovfIh3nMW71O5DPq0EuW25qH728a3m0lAHU6347GIm4' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='2836OMLovfIh3nMW71O5DPq0EuW25qH728a3m0lAHU6347GIm4' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='2836OMLovfIh3nMW71O5DPq0EuW25qH728a3m0lAHU6347GIm4' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='2836OMLovfIh3nMW71O5DPq0EuW25qH728a3m0lAHU6347GIm4' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='2836OMLovfIh3nMW71O5DPq0EuW25qH728a3m0lAHU6347GIm4' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='2836OMLovfIh3nMW71O5DPq0EuW25qH728a3m0lAHU6347GIm4' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='2836OMLovfIh3nMW71O5DPq0EuW25qH728a3m0lAHU6347GIm4' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='2836OMLovfIh3nMW71O5DPq0EuW25qH728a3m0lAHU6347GIm4' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='2836OMLovfIh3nMW71O5DPq0EuW25qH728a3m0lAHU6347GIm4' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='2836OMLovfIh3nMW71O5DPq0EuW25qH728a3m0lAHU6347GIm4' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='2836OMLovfIh3nMW71O5DPq0EuW25qH728a3m0lAHU6347GIm4' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='2836OMLovfIh3nMW71O5DPq0EuW25qH728a3m0lAHU6347GIm4' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='2836OMLovfIh3nMW71O5DPq0EuW25qH728a3m0lAHU6347GIm4' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='2836OMLovfIh3nMW71O5DPq0EuW25qH728a3m0lAHU6347GIm4' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='2836OMLovfIh3nMW71O5DPq0EuW25qH728a3m0lAHU6347GIm4' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='2836OMLovfIh3nMW71O5DPq0EuW25qH728a3m0lAHU6347GIm4' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='2836OMLovfIh3nMW71O5DPq0EuW25qH728a3m0lAHU6347GIm4' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='2836OMLovfIh3nMW71O5DPq0EuW25qH728a3m0lAHU6347GIm4' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='2836OMLovfIh3nMW71O5DPq0EuW25qH728a3m0lAHU6347GIm4' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='2836OMLovfIh3nMW71O5DPq0EuW25qH728a3m0lAHU6347GIm4' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='2836OMLovfIh3nMW71O5DPq0EuW25qH728a3m0lAHU6347GIm4' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='2836OMLovfIh3nMW71O5DPq0EuW25qH728a3m0lAHU6347GIm4' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='2836OMLovfIh3nMW71O5DPq0EuW25qH728a3m0lAHU6347GIm4' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='2836OMLovfIh3nMW71O5DPq0EuW25qH728a3m0lAHU6347GIm4' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='2836OMLovfIh3nMW71O5DPq0EuW25qH728a3m0lAHU6347GIm4' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='2836OMLovfIh3nMW71O5DPq0EuW25qH728a3m0lAHU6347GIm4' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='2836OMLovfIh3nMW71O5DPq0EuW25qH728a3m0lAHU6347GIm4' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (iPhone; CPU iPhone OS 11_0 like Mac OS X) AppleWebKit/604.1.38 (KHTML, like Gecko) Version/11.0 Mobile/15A372 Safari/604.1' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='2836OMLovfIh3nMW71O5DPq0EuW25qH728a3m0lAHU6347GIm4' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (iPhone; CPU iPhone OS 11_0 like Mac OS X) AppleWebKit/604.1.38 (KHTML, like Gecko) Version/11.0 Mobile/15A372 Safari/604.1' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='2836OMLovfIh3nMW71O5DPq0EuW25qH728a3m0lAHU6347GIm4' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (iPhone; CPU iPhone OS 11_0 like Mac OS X) AppleWebKit/604.1.38 (KHTML, like Gecko) Version/11.0 Mobile/15A372 Safari/604.1' and us.confirmkey is null and blocked is null; -select id from users where username='kilian@juridig.lu' and userpassword='0ecf731e2426a8a469f06e9f4a3bcbed6f8071d9d3e3ef7ef5fd9165021e27ec' and confirmkey is null and blocked is null; -DELETE FROM sessions where id_user='4' and remote_addr='::1' and user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36'; -INSERT INTO sessions (id_user, idsession, remote_addr, user_agent) VALUES('4', 'A4032K3B34Wb5F5eIQbx15ad2orrOkQkkE10Jiac68BounG14J', '::1', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36'); -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='A4032K3B34Wb5F5eIQbx15ad2orrOkQkkE10Jiac68BounG14J' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='A4032K3B34Wb5F5eIQbx15ad2orrOkQkkE10Jiac68BounG14J' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='A4032K3B34Wb5F5eIQbx15ad2orrOkQkkE10Jiac68BounG14J' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='A4032K3B34Wb5F5eIQbx15ad2orrOkQkkE10Jiac68BounG14J' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='A4032K3B34Wb5F5eIQbx15ad2orrOkQkkE10Jiac68BounG14J' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='A4032K3B34Wb5F5eIQbx15ad2orrOkQkkE10Jiac68BounG14J' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='A4032K3B34Wb5F5eIQbx15ad2orrOkQkkE10Jiac68BounG14J' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='A4032K3B34Wb5F5eIQbx15ad2orrOkQkkE10Jiac68BounG14J' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='A4032K3B34Wb5F5eIQbx15ad2orrOkQkkE10Jiac68BounG14J' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='A4032K3B34Wb5F5eIQbx15ad2orrOkQkkE10Jiac68BounG14J' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='A4032K3B34Wb5F5eIQbx15ad2orrOkQkkE10Jiac68BounG14J' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='A4032K3B34Wb5F5eIQbx15ad2orrOkQkkE10Jiac68BounG14J' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='A4032K3B34Wb5F5eIQbx15ad2orrOkQkkE10Jiac68BounG14J' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='A4032K3B34Wb5F5eIQbx15ad2orrOkQkkE10Jiac68BounG14J' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='A4032K3B34Wb5F5eIQbx15ad2orrOkQkkE10Jiac68BounG14J' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='A4032K3B34Wb5F5eIQbx15ad2orrOkQkkE10Jiac68BounG14J' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='A4032K3B34Wb5F5eIQbx15ad2orrOkQkkE10Jiac68BounG14J' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='A4032K3B34Wb5F5eIQbx15ad2orrOkQkkE10Jiac68BounG14J' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='A4032K3B34Wb5F5eIQbx15ad2orrOkQkkE10Jiac68BounG14J' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='A4032K3B34Wb5F5eIQbx15ad2orrOkQkkE10Jiac68BounG14J' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='A4032K3B34Wb5F5eIQbx15ad2orrOkQkkE10Jiac68BounG14J' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='A4032K3B34Wb5F5eIQbx15ad2orrOkQkkE10Jiac68BounG14J' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='A4032K3B34Wb5F5eIQbx15ad2orrOkQkkE10Jiac68BounG14J' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='A4032K3B34Wb5F5eIQbx15ad2orrOkQkkE10Jiac68BounG14J' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='A4032K3B34Wb5F5eIQbx15ad2orrOkQkkE10Jiac68BounG14J' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='A4032K3B34Wb5F5eIQbx15ad2orrOkQkkE10Jiac68BounG14J' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='A4032K3B34Wb5F5eIQbx15ad2orrOkQkkE10Jiac68BounG14J' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='A4032K3B34Wb5F5eIQbx15ad2orrOkQkkE10Jiac68BounG14J' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='A4032K3B34Wb5F5eIQbx15ad2orrOkQkkE10Jiac68BounG14J' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='A4032K3B34Wb5F5eIQbx15ad2orrOkQkkE10Jiac68BounG14J' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='A4032K3B34Wb5F5eIQbx15ad2orrOkQkkE10Jiac68BounG14J' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='A4032K3B34Wb5F5eIQbx15ad2orrOkQkkE10Jiac68BounG14J' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='A4032K3B34Wb5F5eIQbx15ad2orrOkQkkE10Jiac68BounG14J' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='A4032K3B34Wb5F5eIQbx15ad2orrOkQkkE10Jiac68BounG14J' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='A4032K3B34Wb5F5eIQbx15ad2orrOkQkkE10Jiac68BounG14J' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='A4032K3B34Wb5F5eIQbx15ad2orrOkQkkE10Jiac68BounG14J' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='A4032K3B34Wb5F5eIQbx15ad2orrOkQkkE10Jiac68BounG14J' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='A4032K3B34Wb5F5eIQbx15ad2orrOkQkkE10Jiac68BounG14J' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='A4032K3B34Wb5F5eIQbx15ad2orrOkQkkE10Jiac68BounG14J' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='A4032K3B34Wb5F5eIQbx15ad2orrOkQkkE10Jiac68BounG14J' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='A4032K3B34Wb5F5eIQbx15ad2orrOkQkkE10Jiac68BounG14J' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='A4032K3B34Wb5F5eIQbx15ad2orrOkQkkE10Jiac68BounG14J' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='A4032K3B34Wb5F5eIQbx15ad2orrOkQkkE10Jiac68BounG14J' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='A4032K3B34Wb5F5eIQbx15ad2orrOkQkkE10Jiac68BounG14J' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='A4032K3B34Wb5F5eIQbx15ad2orrOkQkkE10Jiac68BounG14J' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='A4032K3B34Wb5F5eIQbx15ad2orrOkQkkE10Jiac68BounG14J' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='A4032K3B34Wb5F5eIQbx15ad2orrOkQkkE10Jiac68BounG14J' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='A4032K3B34Wb5F5eIQbx15ad2orrOkQkkE10Jiac68BounG14J' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='A4032K3B34Wb5F5eIQbx15ad2orrOkQkkE10Jiac68BounG14J' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='A4032K3B34Wb5F5eIQbx15ad2orrOkQkkE10Jiac68BounG14J' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='A4032K3B34Wb5F5eIQbx15ad2orrOkQkkE10Jiac68BounG14J' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='A4032K3B34Wb5F5eIQbx15ad2orrOkQkkE10Jiac68BounG14J' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='A4032K3B34Wb5F5eIQbx15ad2orrOkQkkE10Jiac68BounG14J' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='A4032K3B34Wb5F5eIQbx15ad2orrOkQkkE10Jiac68BounG14J' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='A4032K3B34Wb5F5eIQbx15ad2orrOkQkkE10Jiac68BounG14J' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='A4032K3B34Wb5F5eIQbx15ad2orrOkQkkE10Jiac68BounG14J' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='A4032K3B34Wb5F5eIQbx15ad2orrOkQkkE10Jiac68BounG14J' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='A4032K3B34Wb5F5eIQbx15ad2orrOkQkkE10Jiac68BounG14J' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='A4032K3B34Wb5F5eIQbx15ad2orrOkQkkE10Jiac68BounG14J' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='A4032K3B34Wb5F5eIQbx15ad2orrOkQkkE10Jiac68BounG14J' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='A4032K3B34Wb5F5eIQbx15ad2orrOkQkkE10Jiac68BounG14J' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='A4032K3B34Wb5F5eIQbx15ad2orrOkQkkE10Jiac68BounG14J' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='A4032K3B34Wb5F5eIQbx15ad2orrOkQkkE10Jiac68BounG14J' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='A4032K3B34Wb5F5eIQbx15ad2orrOkQkkE10Jiac68BounG14J' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='A4032K3B34Wb5F5eIQbx15ad2orrOkQkkE10Jiac68BounG14J' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='A4032K3B34Wb5F5eIQbx15ad2orrOkQkkE10Jiac68BounG14J' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='A4032K3B34Wb5F5eIQbx15ad2orrOkQkkE10Jiac68BounG14J' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='A4032K3B34Wb5F5eIQbx15ad2orrOkQkkE10Jiac68BounG14J' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='A4032K3B34Wb5F5eIQbx15ad2orrOkQkkE10Jiac68BounG14J' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='A4032K3B34Wb5F5eIQbx15ad2orrOkQkkE10Jiac68BounG14J' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='A4032K3B34Wb5F5eIQbx15ad2orrOkQkkE10Jiac68BounG14J' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='A4032K3B34Wb5F5eIQbx15ad2orrOkQkkE10Jiac68BounG14J' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='A4032K3B34Wb5F5eIQbx15ad2orrOkQkkE10Jiac68BounG14J' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='A4032K3B34Wb5F5eIQbx15ad2orrOkQkkE10Jiac68BounG14J' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='A4032K3B34Wb5F5eIQbx15ad2orrOkQkkE10Jiac68BounG14J' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='A4032K3B34Wb5F5eIQbx15ad2orrOkQkkE10Jiac68BounG14J' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='A4032K3B34Wb5F5eIQbx15ad2orrOkQkkE10Jiac68BounG14J' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='A4032K3B34Wb5F5eIQbx15ad2orrOkQkkE10Jiac68BounG14J' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='A4032K3B34Wb5F5eIQbx15ad2orrOkQkkE10Jiac68BounG14J' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='A4032K3B34Wb5F5eIQbx15ad2orrOkQkkE10Jiac68BounG14J' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36' and us.confirmkey is null and blocked is null; -select id from users where username='kilian@juridig.lu' and userpassword='0ecf731e2426a8a469f06e9f4a3bcbed6f8071d9d3e3ef7ef5fd9165021e27ec' and confirmkey is null and blocked is null; -DELETE FROM sessions where id_user='4' and remote_addr='::1' and user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36'; -INSERT INTO sessions (id_user, idsession, remote_addr, user_agent) VALUES('4', '3i7XKna805FV377wF5lLHmhjbm6g6TWEt2Mh0nHxMqQvXV6BF2', '::1', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36'); -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='3i7XKna805FV377wF5lLHmhjbm6g6TWEt2Mh0nHxMqQvXV6BF2' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='3i7XKna805FV377wF5lLHmhjbm6g6TWEt2Mh0nHxMqQvXV6BF2' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='3i7XKna805FV377wF5lLHmhjbm6g6TWEt2Mh0nHxMqQvXV6BF2' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='3i7XKna805FV377wF5lLHmhjbm6g6TWEt2Mh0nHxMqQvXV6BF2' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36' and us.confirmkey is null and blocked is null; -select id from users where username='kilian@juridig.lu' and userpassword='0ecf731e2426a8a469f06e9f4a3bcbed6f8071d9d3e3ef7ef5fd9165021e27ec' and confirmkey is null and blocked is null; -DELETE FROM sessions where id_user='4' and remote_addr='::1' and user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36'; -INSERT INTO sessions (id_user, idsession, remote_addr, user_agent) VALUES('4', 'eaLWwtWDHl2gitlnSIJksbh4b3C5310t60065b31wk1mRe7R0p', '::1', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36'); -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='eaLWwtWDHl2gitlnSIJksbh4b3C5310t60065b31wk1mRe7R0p' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='eaLWwtWDHl2gitlnSIJksbh4b3C5310t60065b31wk1mRe7R0p' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='eaLWwtWDHl2gitlnSIJksbh4b3C5310t60065b31wk1mRe7R0p' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36' and us.confirmkey is null and blocked is null; -select id from users where username='kilian@juridig.lu' and userpassword='0ecf731e2426a8a469f06e9f4a3bcbed6f8071d9d3e3ef7ef5fd9165021e27ec' and confirmkey is null and blocked is null; -DELETE FROM sessions where id_user='4' and remote_addr='::1' and user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36'; -INSERT INTO sessions (id_user, idsession, remote_addr, user_agent) VALUES('4', 'vwPVehJlIb0dM27b00RWdOCtTAle6Olbq1T35dU7uCQeS0Ffcl', '::1', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36'); -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='vwPVehJlIb0dM27b00RWdOCtTAle6Olbq1T35dU7uCQeS0Ffcl' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='vwPVehJlIb0dM27b00RWdOCtTAle6Olbq1T35dU7uCQeS0Ffcl' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='vwPVehJlIb0dM27b00RWdOCtTAle6Olbq1T35dU7uCQeS0Ffcl' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='vwPVehJlIb0dM27b00RWdOCtTAle6Olbq1T35dU7uCQeS0Ffcl' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='vwPVehJlIb0dM27b00RWdOCtTAle6Olbq1T35dU7uCQeS0Ffcl' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='vwPVehJlIb0dM27b00RWdOCtTAle6Olbq1T35dU7uCQeS0Ffcl' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36' and us.confirmkey is null and blocked is null; -select id from users where username='kilian@juridig.lu' and userpassword='0ecf731e2426a8a469f06e9f4a3bcbed6f8071d9d3e3ef7ef5fd9165021e27ec' and confirmkey is null and blocked is null; -DELETE FROM sessions where id_user='4' and remote_addr='::1' and user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36'; -INSERT INTO sessions (id_user, idsession, remote_addr, user_agent) VALUES('4', 'Q4MtRvCr2U0i2Tb5iJ4vhaU33d1j4usDJKkHx7FvBsFVJ3NGak', '::1', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36'); -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='Q4MtRvCr2U0i2Tb5iJ4vhaU33d1j4usDJKkHx7FvBsFVJ3NGak' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='Q4MtRvCr2U0i2Tb5iJ4vhaU33d1j4usDJKkHx7FvBsFVJ3NGak' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='Q4MtRvCr2U0i2Tb5iJ4vhaU33d1j4usDJKkHx7FvBsFVJ3NGak' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36' and us.confirmkey is null and blocked is null; -select id from users where username='kilian@juridig.lu' and userpassword='0ecf731e2426a8a469f06e9f4a3bcbed6f8071d9d3e3ef7ef5fd9165021e27ec' and confirmkey is null and blocked is null; -DELETE FROM sessions where id_user='4' and remote_addr='::1' and user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36'; -INSERT INTO sessions (id_user, idsession, remote_addr, user_agent) VALUES('4', '2E7RdS0xpKC4uaH86Q6U5K3s7ko3D6r1B4f7U882rFO7024R2k', '::1', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36'); -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='2E7RdS0xpKC4uaH86Q6U5K3s7ko3D6r1B4f7U882rFO7024R2k' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='2E7RdS0xpKC4uaH86Q6U5K3s7ko3D6r1B4f7U882rFO7024R2k' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='2E7RdS0xpKC4uaH86Q6U5K3s7ko3D6r1B4f7U882rFO7024R2k' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='2E7RdS0xpKC4uaH86Q6U5K3s7ko3D6r1B4f7U882rFO7024R2k' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36' and us.confirmkey is null and blocked is null; -select id from users where username='kilian@juridig.lu' and userpassword='0ecf731e2426a8a469f06e9f4a3bcbed6f8071d9d3e3ef7ef5fd9165021e27ec' and confirmkey is null and blocked is null; -DELETE FROM sessions where id_user='4' and remote_addr='::1' and user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36'; -INSERT INTO sessions (id_user, idsession, remote_addr, user_agent) VALUES('4', 'nCoFc4mc8Lb68m52hN4UdJ2MlEnc5VdN8Ufn267oS6GMb7KkKS', '::1', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36'); -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='nCoFc4mc8Lb68m52hN4UdJ2MlEnc5VdN8Ufn267oS6GMb7KkKS' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='nCoFc4mc8Lb68m52hN4UdJ2MlEnc5VdN8Ufn267oS6GMb7KkKS' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='nCoFc4mc8Lb68m52hN4UdJ2MlEnc5VdN8Ufn267oS6GMb7KkKS' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='nCoFc4mc8Lb68m52hN4UdJ2MlEnc5VdN8Ufn267oS6GMb7KkKS' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='nCoFc4mc8Lb68m52hN4UdJ2MlEnc5VdN8Ufn267oS6GMb7KkKS' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36' and us.confirmkey is null and blocked is null; -select id from users where username='kilian@juridig.lu' and userpassword='0ecf731e2426a8a469f06e9f4a3bcbed6f8071d9d3e3ef7ef5fd9165021e27ec' and confirmkey is null and blocked is null; -DELETE FROM sessions where id_user='4' and remote_addr='::1' and user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36'; -INSERT INTO sessions (id_user, idsession, remote_addr, user_agent) VALUES('4', 'VdX1TLf4mbKv6u2am8A6r8qmX244nAttPDEkH762Civ38oeVC8', '::1', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36'); -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='VdX1TLf4mbKv6u2am8A6r8qmX244nAttPDEkH762Civ38oeVC8' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='VdX1TLf4mbKv6u2am8A6r8qmX244nAttPDEkH762Civ38oeVC8' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='VdX1TLf4mbKv6u2am8A6r8qmX244nAttPDEkH762Civ38oeVC8' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36' and us.confirmkey is null and blocked is null; -select id from users where username='kilian@juridig.lu' and userpassword='0ecf731e2426a8a469f06e9f4a3bcbed6f8071d9d3e3ef7ef5fd9165021e27ec' and confirmkey is null and blocked is null; -DELETE FROM sessions where id_user='4' and remote_addr='::1' and user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36'; -INSERT INTO sessions (id_user, idsession, remote_addr, user_agent) VALUES('4', '2r1plk7w4el4o2ShP36BGpeWrgF4r4Rq6QLBeqRE8GLmSQr467', '::1', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36'); -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='2r1plk7w4el4o2ShP36BGpeWrgF4r4Rq6QLBeqRE8GLmSQr467' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='2r1plk7w4el4o2ShP36BGpeWrgF4r4Rq6QLBeqRE8GLmSQr467' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='2r1plk7w4el4o2ShP36BGpeWrgF4r4Rq6QLBeqRE8GLmSQr467' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36' and us.confirmkey is null and blocked is null; -select id from users where username='kilian@juridig.lu' and userpassword='0ecf731e2426a8a469f06e9f4a3bcbed6f8071d9d3e3ef7ef5fd9165021e27ec' and confirmkey is null and blocked is null; -DELETE FROM sessions where id_user='4' and remote_addr='::1' and user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36'; -INSERT INTO sessions (id_user, idsession, remote_addr, user_agent) VALUES('4', '3165I4KrrrdS5f5g66jo8tLp2x77BC64rPVN6L060wA77m32m3', '::1', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36'); -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='3165I4KrrrdS5f5g66jo8tLp2x77BC64rPVN6L060wA77m32m3' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='3165I4KrrrdS5f5g66jo8tLp2x77BC64rPVN6L060wA77m32m3' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='3165I4KrrrdS5f5g66jo8tLp2x77BC64rPVN6L060wA77m32m3' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='3165I4KrrrdS5f5g66jo8tLp2x77BC64rPVN6L060wA77m32m3' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36' and us.confirmkey is null and blocked is null; -select id from users where username='kilian@juridig.lu' and userpassword='0ecf731e2426a8a469f06e9f4a3bcbed6f8071d9d3e3ef7ef5fd9165021e27ec' and confirmkey is null and blocked is null; -DELETE FROM sessions where id_user='4' and remote_addr='::1' and user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36'; -INSERT INTO sessions (id_user, idsession, remote_addr, user_agent) VALUES('4', 'opaQ1pEAWTDjTm2n4P3vB3733icb6gscoE0Jg7j5g3K6I8s7f3', '::1', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36'); -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='opaQ1pEAWTDjTm2n4P3vB3733icb6gscoE0Jg7j5g3K6I8s7f3' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='opaQ1pEAWTDjTm2n4P3vB3733icb6gscoE0Jg7j5g3K6I8s7f3' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='opaQ1pEAWTDjTm2n4P3vB3733icb6gscoE0Jg7j5g3K6I8s7f3' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='opaQ1pEAWTDjTm2n4P3vB3733icb6gscoE0Jg7j5g3K6I8s7f3' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36' and us.confirmkey is null and blocked is null; -select id from users where username='kilian@juridig.lu' and userpassword='0ecf731e2426a8a469f06e9f4a3bcbed6f8071d9d3e3ef7ef5fd9165021e27ec' and confirmkey is null and blocked is null; -DELETE FROM sessions where id_user='4' and remote_addr='::1' and user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36'; -INSERT INTO sessions (id_user, idsession, remote_addr, user_agent) VALUES('4', 'QAD5e5ICM8I6CEK57b2bEkn6fodQ6485elrnC2qhvoROb50RM4', '::1', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36'); -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='QAD5e5ICM8I6CEK57b2bEkn6fodQ6485elrnC2qhvoROb50RM4' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='QAD5e5ICM8I6CEK57b2bEkn6fodQ6485elrnC2qhvoROb50RM4' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='QAD5e5ICM8I6CEK57b2bEkn6fodQ6485elrnC2qhvoROb50RM4' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36' and us.confirmkey is null and blocked is null; -select id from users where username='kilian@juridig.lu' and userpassword='0ecf731e2426a8a469f06e9f4a3bcbed6f8071d9d3e3ef7ef5fd9165021e27ec' and confirmkey is null and blocked is null; -DELETE FROM sessions where id_user='4' and remote_addr='::1' and user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36'; -INSERT INTO sessions (id_user, idsession, remote_addr, user_agent) VALUES('4', '1UB3C041Wa4D7rkR8FNCOWw2b5GNgdudFwsVlv25r07P5n66oT', '::1', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36'); -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='1UB3C041Wa4D7rkR8FNCOWw2b5GNgdudFwsVlv25r07P5n66oT' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='1UB3C041Wa4D7rkR8FNCOWw2b5GNgdudFwsVlv25r07P5n66oT' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='1UB3C041Wa4D7rkR8FNCOWw2b5GNgdudFwsVlv25r07P5n66oT' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='1UB3C041Wa4D7rkR8FNCOWw2b5GNgdudFwsVlv25r07P5n66oT' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36' and us.confirmkey is null and blocked is null; -select id from users where username='kilian@juridig.lu' and userpassword='0ecf731e2426a8a469f06e9f4a3bcbed6f8071d9d3e3ef7ef5fd9165021e27ec' and confirmkey is null and blocked is null; -DELETE FROM sessions where id_user='4' and remote_addr='::1' and user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36'; -INSERT INTO sessions (id_user, idsession, remote_addr, user_agent) VALUES('4', 'bi3borD5wVwVSrkSm2EM42hgFPmj6Hp77N08brtXcl5ef5jW67', '::1', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36'); -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='bi3borD5wVwVSrkSm2EM42hgFPmj6Hp77N08brtXcl5ef5jW67' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='bi3borD5wVwVSrkSm2EM42hgFPmj6Hp77N08brtXcl5ef5jW67' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='bi3borD5wVwVSrkSm2EM42hgFPmj6Hp77N08brtXcl5ef5jW67' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='bi3borD5wVwVSrkSm2EM42hgFPmj6Hp77N08brtXcl5ef5jW67' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='bi3borD5wVwVSrkSm2EM42hgFPmj6Hp77N08brtXcl5ef5jW67' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='bi3borD5wVwVSrkSm2EM42hgFPmj6Hp77N08brtXcl5ef5jW67' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36' and us.confirmkey is null and blocked is null; -select id from users where username='kilian@juridig.lu' and userpassword='0ecf731e2426a8a469f06e9f4a3bcbed6f8071d9d3e3ef7ef5fd9165021e27ec' and confirmkey is null and blocked is null; -DELETE FROM sessions where id_user='4' and remote_addr='::1' and user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36'; -INSERT INTO sessions (id_user, idsession, remote_addr, user_agent) VALUES('4', '11Jvr6Sf7Ol8KHtWO8108o6K0G3b4V50BfSvnu2tlLw5Nm73qO', '::1', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36'); -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='11Jvr6Sf7Ol8KHtWO8108o6K0G3b4V50BfSvnu2tlLw5Nm73qO' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='11Jvr6Sf7Ol8KHtWO8108o6K0G3b4V50BfSvnu2tlLw5Nm73qO' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='11Jvr6Sf7Ol8KHtWO8108o6K0G3b4V50BfSvnu2tlLw5Nm73qO' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='11Jvr6Sf7Ol8KHtWO8108o6K0G3b4V50BfSvnu2tlLw5Nm73qO' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36' and us.confirmkey is null and blocked is null; -select id from users where username='kilian@juridig.lu' and userpassword='0ecf731e2426a8a469f06e9f4a3bcbed6f8071d9d3e3ef7ef5fd9165021e27ec' and confirmkey is null and blocked is null; -DELETE FROM sessions where id_user='4' and remote_addr='::1' and user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36'; -INSERT INTO sessions (id_user, idsession, remote_addr, user_agent) VALUES('4', 'qdF8lVNjAwDtJGmn3LhOQ6j84tf0845Gcfx8a8WL8w7123EsXj', '::1', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36'); -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='qdF8lVNjAwDtJGmn3LhOQ6j84tf0845Gcfx8a8WL8w7123EsXj' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='qdF8lVNjAwDtJGmn3LhOQ6j84tf0845Gcfx8a8WL8w7123EsXj' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='qdF8lVNjAwDtJGmn3LhOQ6j84tf0845Gcfx8a8WL8w7123EsXj' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='qdF8lVNjAwDtJGmn3LhOQ6j84tf0845Gcfx8a8WL8w7123EsXj' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='qdF8lVNjAwDtJGmn3LhOQ6j84tf0845Gcfx8a8WL8w7123EsXj' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36' and us.confirmkey is null and blocked is null; -select id from users where username='kilian@juridig.lu' and userpassword='0ecf731e2426a8a469f06e9f4a3bcbed6f8071d9d3e3ef7ef5fd9165021e27ec' and confirmkey is null and blocked is null; -DELETE FROM sessions where id_user='4' and remote_addr='::1' and user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36'; -INSERT INTO sessions (id_user, idsession, remote_addr, user_agent) VALUES('4', '03s00MBi8wovwKnUKW0We34HcXQH2RX6jCHDc44wdOsqv5Sw5T', '::1', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36'); -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='03s00MBi8wovwKnUKW0We34HcXQH2RX6jCHDc44wdOsqv5Sw5T' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='03s00MBi8wovwKnUKW0We34HcXQH2RX6jCHDc44wdOsqv5Sw5T' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='03s00MBi8wovwKnUKW0We34HcXQH2RX6jCHDc44wdOsqv5Sw5T' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='03s00MBi8wovwKnUKW0We34HcXQH2RX6jCHDc44wdOsqv5Sw5T' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36' and us.confirmkey is null and blocked is null; -select id from users where username='kilian@juridig.lu' and userpassword='0ecf731e2426a8a469f06e9f4a3bcbed6f8071d9d3e3ef7ef5fd9165021e27ec' and confirmkey is null and blocked is null; -DELETE FROM sessions where id_user='4' and remote_addr='::1' and user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36'; -INSERT INTO sessions (id_user, idsession, remote_addr, user_agent) VALUES('4', 'Xa1Aj4288QLJFX4ma1b30ejJ64c0K0U6bvKB21kXGXDJ6x33D4', '::1', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36'); -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='Xa1Aj4288QLJFX4ma1b30ejJ64c0K0U6bvKB21kXGXDJ6x33D4' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='Xa1Aj4288QLJFX4ma1b30ejJ64c0K0U6bvKB21kXGXDJ6x33D4' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='Xa1Aj4288QLJFX4ma1b30ejJ64c0K0U6bvKB21kXGXDJ6x33D4' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='Xa1Aj4288QLJFX4ma1b30ejJ64c0K0U6bvKB21kXGXDJ6x33D4' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='Xa1Aj4288QLJFX4ma1b30ejJ64c0K0U6bvKB21kXGXDJ6x33D4' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='Xa1Aj4288QLJFX4ma1b30ejJ64c0K0U6bvKB21kXGXDJ6x33D4' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36' and us.confirmkey is null and blocked is null; -select id from users where username='kilian@juridig.lu' and userpassword='0ecf731e2426a8a469f06e9f4a3bcbed6f8071d9d3e3ef7ef5fd9165021e27ec' and confirmkey is null and blocked is null; -DELETE FROM sessions where id_user='4' and remote_addr='::1' and user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36'; -INSERT INTO sessions (id_user, idsession, remote_addr, user_agent) VALUES('4', 'lWnhh8h17VuQLLmFX3erQd54r0DstBMOdSK6uHsu10iogpgK5H', '::1', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36'); -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='lWnhh8h17VuQLLmFX3erQd54r0DstBMOdSK6uHsu10iogpgK5H' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='lWnhh8h17VuQLLmFX3erQd54r0DstBMOdSK6uHsu10iogpgK5H' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='lWnhh8h17VuQLLmFX3erQd54r0DstBMOdSK6uHsu10iogpgK5H' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='lWnhh8h17VuQLLmFX3erQd54r0DstBMOdSK6uHsu10iogpgK5H' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36' and us.confirmkey is null and blocked is null; -select id from users where username='kilian@juridig.lu' and userpassword='0ecf731e2426a8a469f06e9f4a3bcbed6f8071d9d3e3ef7ef5fd9165021e27ec' and confirmkey is null and blocked is null; -DELETE FROM sessions where id_user='4' and remote_addr='::1' and user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36'; -INSERT INTO sessions (id_user, idsession, remote_addr, user_agent) VALUES('4', 'eD3dp367XfAx1s4N4fhMB2k7VX2VDOG4GEw83fBGKQNWeWR445', '::1', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36'); -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='eD3dp367XfAx1s4N4fhMB2k7VX2VDOG4GEw83fBGKQNWeWR445' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='eD3dp367XfAx1s4N4fhMB2k7VX2VDOG4GEw83fBGKQNWeWR445' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='eD3dp367XfAx1s4N4fhMB2k7VX2VDOG4GEw83fBGKQNWeWR445' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='eD3dp367XfAx1s4N4fhMB2k7VX2VDOG4GEw83fBGKQNWeWR445' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36' and us.confirmkey is null and blocked is null; -select id from users where username='kilian@juridig.lu' and userpassword='0ecf731e2426a8a469f06e9f4a3bcbed6f8071d9d3e3ef7ef5fd9165021e27ec' and confirmkey is null and blocked is null; -DELETE FROM sessions where id_user='4' and remote_addr='::1' and user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36'; -INSERT INTO sessions (id_user, idsession, remote_addr, user_agent) VALUES('4', 'fVbIeoB7Nj2PCX13nvOwo744lIT1dxP650d1mJ6Sjwo7t15A32', '::1', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36'); -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='fVbIeoB7Nj2PCX13nvOwo744lIT1dxP650d1mJ6Sjwo7t15A32' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='fVbIeoB7Nj2PCX13nvOwo744lIT1dxP650d1mJ6Sjwo7t15A32' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='fVbIeoB7Nj2PCX13nvOwo744lIT1dxP650d1mJ6Sjwo7t15A32' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='fVbIeoB7Nj2PCX13nvOwo744lIT1dxP650d1mJ6Sjwo7t15A32' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='fVbIeoB7Nj2PCX13nvOwo744lIT1dxP650d1mJ6Sjwo7t15A32' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='fVbIeoB7Nj2PCX13nvOwo744lIT1dxP650d1mJ6Sjwo7t15A32' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='fVbIeoB7Nj2PCX13nvOwo744lIT1dxP650d1mJ6Sjwo7t15A32' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='fVbIeoB7Nj2PCX13nvOwo744lIT1dxP650d1mJ6Sjwo7t15A32' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='fVbIeoB7Nj2PCX13nvOwo744lIT1dxP650d1mJ6Sjwo7t15A32' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='fVbIeoB7Nj2PCX13nvOwo744lIT1dxP650d1mJ6Sjwo7t15A32' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='fVbIeoB7Nj2PCX13nvOwo744lIT1dxP650d1mJ6Sjwo7t15A32' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='fVbIeoB7Nj2PCX13nvOwo744lIT1dxP650d1mJ6Sjwo7t15A32' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='fVbIeoB7Nj2PCX13nvOwo744lIT1dxP650d1mJ6Sjwo7t15A32' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='fVbIeoB7Nj2PCX13nvOwo744lIT1dxP650d1mJ6Sjwo7t15A32' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='fVbIeoB7Nj2PCX13nvOwo744lIT1dxP650d1mJ6Sjwo7t15A32' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='fVbIeoB7Nj2PCX13nvOwo744lIT1dxP650d1mJ6Sjwo7t15A32' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='fVbIeoB7Nj2PCX13nvOwo744lIT1dxP650d1mJ6Sjwo7t15A32' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='fVbIeoB7Nj2PCX13nvOwo744lIT1dxP650d1mJ6Sjwo7t15A32' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='fVbIeoB7Nj2PCX13nvOwo744lIT1dxP650d1mJ6Sjwo7t15A32' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='fVbIeoB7Nj2PCX13nvOwo744lIT1dxP650d1mJ6Sjwo7t15A32' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='fVbIeoB7Nj2PCX13nvOwo744lIT1dxP650d1mJ6Sjwo7t15A32' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='fVbIeoB7Nj2PCX13nvOwo744lIT1dxP650d1mJ6Sjwo7t15A32' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='fVbIeoB7Nj2PCX13nvOwo744lIT1dxP650d1mJ6Sjwo7t15A32' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='fVbIeoB7Nj2PCX13nvOwo744lIT1dxP650d1mJ6Sjwo7t15A32' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='fVbIeoB7Nj2PCX13nvOwo744lIT1dxP650d1mJ6Sjwo7t15A32' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='fVbIeoB7Nj2PCX13nvOwo744lIT1dxP650d1mJ6Sjwo7t15A32' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='fVbIeoB7Nj2PCX13nvOwo744lIT1dxP650d1mJ6Sjwo7t15A32' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='fVbIeoB7Nj2PCX13nvOwo744lIT1dxP650d1mJ6Sjwo7t15A32' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='fVbIeoB7Nj2PCX13nvOwo744lIT1dxP650d1mJ6Sjwo7t15A32' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='fVbIeoB7Nj2PCX13nvOwo744lIT1dxP650d1mJ6Sjwo7t15A32' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='fVbIeoB7Nj2PCX13nvOwo744lIT1dxP650d1mJ6Sjwo7t15A32' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='fVbIeoB7Nj2PCX13nvOwo744lIT1dxP650d1mJ6Sjwo7t15A32' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (iPhone; CPU iPhone OS 11_0 like Mac OS X) AppleWebKit/604.1.38 (KHTML, like Gecko) Version/11.0 Mobile/15A372 Safari/604.1' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='fVbIeoB7Nj2PCX13nvOwo744lIT1dxP650d1mJ6Sjwo7t15A32' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (iPhone; CPU iPhone OS 11_0 like Mac OS X) AppleWebKit/604.1.38 (KHTML, like Gecko) Version/11.0 Mobile/15A372 Safari/604.1' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='fVbIeoB7Nj2PCX13nvOwo744lIT1dxP650d1mJ6Sjwo7t15A32' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (iPhone; CPU iPhone OS 11_0 like Mac OS X) AppleWebKit/604.1.38 (KHTML, like Gecko) Version/11.0 Mobile/15A372 Safari/604.1' and us.confirmkey is null and blocked is null; -select id from users where username='kilian@juridig.lu' and userpassword='0ecf731e2426a8a469f06e9f4a3bcbed6f8071d9d3e3ef7ef5fd9165021e27ec' and confirmkey is null and blocked is null; -DELETE FROM sessions where id_user='4' and remote_addr='::1' and user_agent='Mozilla/5.0 (iPhone; CPU iPhone OS 11_0 like Mac OS X) AppleWebKit/604.1.38 (KHTML, like Gecko) Version/11.0 Mobile/15A372 Safari/604.1'; -INSERT INTO sessions (id_user, idsession, remote_addr, user_agent) VALUES('4', 'A7qecrA83lD2ohxKMcBk4Rudd3LKoTubFc8P8p3hI5frFAD27B', '::1', 'Mozilla/5.0 (iPhone; CPU iPhone OS 11_0 like Mac OS X) AppleWebKit/604.1.38 (KHTML, like Gecko) Version/11.0 Mobile/15A372 Safari/604.1'); -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='A7qecrA83lD2ohxKMcBk4Rudd3LKoTubFc8P8p3hI5frFAD27B' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (iPhone; CPU iPhone OS 11_0 like Mac OS X) AppleWebKit/604.1.38 (KHTML, like Gecko) Version/11.0 Mobile/15A372 Safari/604.1' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='A7qecrA83lD2ohxKMcBk4Rudd3LKoTubFc8P8p3hI5frFAD27B' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (iPhone; CPU iPhone OS 11_0 like Mac OS X) AppleWebKit/604.1.38 (KHTML, like Gecko) Version/11.0 Mobile/15A372 Safari/604.1' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='A7qecrA83lD2ohxKMcBk4Rudd3LKoTubFc8P8p3hI5frFAD27B' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (iPhone; CPU iPhone OS 11_0 like Mac OS X) AppleWebKit/604.1.38 (KHTML, like Gecko) Version/11.0 Mobile/15A372 Safari/604.1' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='A7qecrA83lD2ohxKMcBk4Rudd3LKoTubFc8P8p3hI5frFAD27B' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (iPhone; CPU iPhone OS 11_0 like Mac OS X) AppleWebKit/604.1.38 (KHTML, like Gecko) Version/11.0 Mobile/15A372 Safari/604.1' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='A7qecrA83lD2ohxKMcBk4Rudd3LKoTubFc8P8p3hI5frFAD27B' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (iPhone; CPU iPhone OS 11_0 like Mac OS X) AppleWebKit/604.1.38 (KHTML, like Gecko) Version/11.0 Mobile/15A372 Safari/604.1' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='A7qecrA83lD2ohxKMcBk4Rudd3LKoTubFc8P8p3hI5frFAD27B' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (iPhone; CPU iPhone OS 11_0 like Mac OS X) AppleWebKit/604.1.38 (KHTML, like Gecko) Version/11.0 Mobile/15A372 Safari/604.1' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='A7qecrA83lD2ohxKMcBk4Rudd3LKoTubFc8P8p3hI5frFAD27B' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (iPhone; CPU iPhone OS 11_0 like Mac OS X) AppleWebKit/604.1.38 (KHTML, like Gecko) Version/11.0 Mobile/15A372 Safari/604.1' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='A7qecrA83lD2ohxKMcBk4Rudd3LKoTubFc8P8p3hI5frFAD27B' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (iPhone; CPU iPhone OS 11_0 like Mac OS X) AppleWebKit/604.1.38 (KHTML, like Gecko) Version/11.0 Mobile/15A372 Safari/604.1' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='A7qecrA83lD2ohxKMcBk4Rudd3LKoTubFc8P8p3hI5frFAD27B' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (iPhone; CPU iPhone OS 11_0 like Mac OS X) AppleWebKit/604.1.38 (KHTML, like Gecko) Version/11.0 Mobile/15A372 Safari/604.1' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='A7qecrA83lD2ohxKMcBk4Rudd3LKoTubFc8P8p3hI5frFAD27B' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (iPhone; CPU iPhone OS 11_0 like Mac OS X) AppleWebKit/604.1.38 (KHTML, like Gecko) Version/11.0 Mobile/15A372 Safari/604.1' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='A7qecrA83lD2ohxKMcBk4Rudd3LKoTubFc8P8p3hI5frFAD27B' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (iPhone; CPU iPhone OS 11_0 like Mac OS X) AppleWebKit/604.1.38 (KHTML, like Gecko) Version/11.0 Mobile/15A372 Safari/604.1' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='A7qecrA83lD2ohxKMcBk4Rudd3LKoTubFc8P8p3hI5frFAD27B' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (iPhone; CPU iPhone OS 11_0 like Mac OS X) AppleWebKit/604.1.38 (KHTML, like Gecko) Version/11.0 Mobile/15A372 Safari/604.1' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='A7qecrA83lD2ohxKMcBk4Rudd3LKoTubFc8P8p3hI5frFAD27B' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='A7qecrA83lD2ohxKMcBk4Rudd3LKoTubFc8P8p3hI5frFAD27B' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='A7qecrA83lD2ohxKMcBk4Rudd3LKoTubFc8P8p3hI5frFAD27B' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='A7qecrA83lD2ohxKMcBk4Rudd3LKoTubFc8P8p3hI5frFAD27B' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='A7qecrA83lD2ohxKMcBk4Rudd3LKoTubFc8P8p3hI5frFAD27B' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='A7qecrA83lD2ohxKMcBk4Rudd3LKoTubFc8P8p3hI5frFAD27B' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36' and us.confirmkey is null and blocked is null; -select id from users where username='kilian@juridig.lu' and userpassword='0ecf731e2426a8a469f06e9f4a3bcbed6f8071d9d3e3ef7ef5fd9165021e27ec' and confirmkey is null and blocked is null; -DELETE FROM sessions where id_user='4' and remote_addr='::1' and user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36'; -INSERT INTO sessions (id_user, idsession, remote_addr, user_agent) VALUES('4', 'g2FjE1wxa3q3BIg2ovJ3fAX7LmRO2MQ0w1D6nr8CTT2InNn563', '::1', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36'); -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='g2FjE1wxa3q3BIg2ovJ3fAX7LmRO2MQ0w1D6nr8CTT2InNn563' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='g2FjE1wxa3q3BIg2ovJ3fAX7LmRO2MQ0w1D6nr8CTT2InNn563' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='g2FjE1wxa3q3BIg2ovJ3fAX7LmRO2MQ0w1D6nr8CTT2InNn563' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='g2FjE1wxa3q3BIg2ovJ3fAX7LmRO2MQ0w1D6nr8CTT2InNn563' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='g2FjE1wxa3q3BIg2ovJ3fAX7LmRO2MQ0w1D6nr8CTT2InNn563' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='g2FjE1wxa3q3BIg2ovJ3fAX7LmRO2MQ0w1D6nr8CTT2InNn563' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='g2FjE1wxa3q3BIg2ovJ3fAX7LmRO2MQ0w1D6nr8CTT2InNn563' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='g2FjE1wxa3q3BIg2ovJ3fAX7LmRO2MQ0w1D6nr8CTT2InNn563' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='g2FjE1wxa3q3BIg2ovJ3fAX7LmRO2MQ0w1D6nr8CTT2InNn563' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='g2FjE1wxa3q3BIg2ovJ3fAX7LmRO2MQ0w1D6nr8CTT2InNn563' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='g2FjE1wxa3q3BIg2ovJ3fAX7LmRO2MQ0w1D6nr8CTT2InNn563' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='g2FjE1wxa3q3BIg2ovJ3fAX7LmRO2MQ0w1D6nr8CTT2InNn563' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='g2FjE1wxa3q3BIg2ovJ3fAX7LmRO2MQ0w1D6nr8CTT2InNn563' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='g2FjE1wxa3q3BIg2ovJ3fAX7LmRO2MQ0w1D6nr8CTT2InNn563' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='g2FjE1wxa3q3BIg2ovJ3fAX7LmRO2MQ0w1D6nr8CTT2InNn563' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='g2FjE1wxa3q3BIg2ovJ3fAX7LmRO2MQ0w1D6nr8CTT2InNn563' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='g2FjE1wxa3q3BIg2ovJ3fAX7LmRO2MQ0w1D6nr8CTT2InNn563' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='g2FjE1wxa3q3BIg2ovJ3fAX7LmRO2MQ0w1D6nr8CTT2InNn563' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='g2FjE1wxa3q3BIg2ovJ3fAX7LmRO2MQ0w1D6nr8CTT2InNn563' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='g2FjE1wxa3q3BIg2ovJ3fAX7LmRO2MQ0w1D6nr8CTT2InNn563' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='g2FjE1wxa3q3BIg2ovJ3fAX7LmRO2MQ0w1D6nr8CTT2InNn563' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='g2FjE1wxa3q3BIg2ovJ3fAX7LmRO2MQ0w1D6nr8CTT2InNn563' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='g2FjE1wxa3q3BIg2ovJ3fAX7LmRO2MQ0w1D6nr8CTT2InNn563' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='g2FjE1wxa3q3BIg2ovJ3fAX7LmRO2MQ0w1D6nr8CTT2InNn563' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='g2FjE1wxa3q3BIg2ovJ3fAX7LmRO2MQ0w1D6nr8CTT2InNn563' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='g2FjE1wxa3q3BIg2ovJ3fAX7LmRO2MQ0w1D6nr8CTT2InNn563' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='g2FjE1wxa3q3BIg2ovJ3fAX7LmRO2MQ0w1D6nr8CTT2InNn563' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='g2FjE1wxa3q3BIg2ovJ3fAX7LmRO2MQ0w1D6nr8CTT2InNn563' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='g2FjE1wxa3q3BIg2ovJ3fAX7LmRO2MQ0w1D6nr8CTT2InNn563' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='g2FjE1wxa3q3BIg2ovJ3fAX7LmRO2MQ0w1D6nr8CTT2InNn563' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='g2FjE1wxa3q3BIg2ovJ3fAX7LmRO2MQ0w1D6nr8CTT2InNn563' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='g2FjE1wxa3q3BIg2ovJ3fAX7LmRO2MQ0w1D6nr8CTT2InNn563' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='g2FjE1wxa3q3BIg2ovJ3fAX7LmRO2MQ0w1D6nr8CTT2InNn563' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='g2FjE1wxa3q3BIg2ovJ3fAX7LmRO2MQ0w1D6nr8CTT2InNn563' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='g2FjE1wxa3q3BIg2ovJ3fAX7LmRO2MQ0w1D6nr8CTT2InNn563' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='g2FjE1wxa3q3BIg2ovJ3fAX7LmRO2MQ0w1D6nr8CTT2InNn563' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='g2FjE1wxa3q3BIg2ovJ3fAX7LmRO2MQ0w1D6nr8CTT2InNn563' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='g2FjE1wxa3q3BIg2ovJ3fAX7LmRO2MQ0w1D6nr8CTT2InNn563' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='g2FjE1wxa3q3BIg2ovJ3fAX7LmRO2MQ0w1D6nr8CTT2InNn563' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='g2FjE1wxa3q3BIg2ovJ3fAX7LmRO2MQ0w1D6nr8CTT2InNn563' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='g2FjE1wxa3q3BIg2ovJ3fAX7LmRO2MQ0w1D6nr8CTT2InNn563' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='g2FjE1wxa3q3BIg2ovJ3fAX7LmRO2MQ0w1D6nr8CTT2InNn563' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='g2FjE1wxa3q3BIg2ovJ3fAX7LmRO2MQ0w1D6nr8CTT2InNn563' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='g2FjE1wxa3q3BIg2ovJ3fAX7LmRO2MQ0w1D6nr8CTT2InNn563' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='g2FjE1wxa3q3BIg2ovJ3fAX7LmRO2MQ0w1D6nr8CTT2InNn563' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='g2FjE1wxa3q3BIg2ovJ3fAX7LmRO2MQ0w1D6nr8CTT2InNn563' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='g2FjE1wxa3q3BIg2ovJ3fAX7LmRO2MQ0w1D6nr8CTT2InNn563' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='g2FjE1wxa3q3BIg2ovJ3fAX7LmRO2MQ0w1D6nr8CTT2InNn563' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='g2FjE1wxa3q3BIg2ovJ3fAX7LmRO2MQ0w1D6nr8CTT2InNn563' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='g2FjE1wxa3q3BIg2ovJ3fAX7LmRO2MQ0w1D6nr8CTT2InNn563' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='g2FjE1wxa3q3BIg2ovJ3fAX7LmRO2MQ0w1D6nr8CTT2InNn563' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='g2FjE1wxa3q3BIg2ovJ3fAX7LmRO2MQ0w1D6nr8CTT2InNn563' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='g2FjE1wxa3q3BIg2ovJ3fAX7LmRO2MQ0w1D6nr8CTT2InNn563' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='g2FjE1wxa3q3BIg2ovJ3fAX7LmRO2MQ0w1D6nr8CTT2InNn563' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='g2FjE1wxa3q3BIg2ovJ3fAX7LmRO2MQ0w1D6nr8CTT2InNn563' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='g2FjE1wxa3q3BIg2ovJ3fAX7LmRO2MQ0w1D6nr8CTT2InNn563' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='g2FjE1wxa3q3BIg2ovJ3fAX7LmRO2MQ0w1D6nr8CTT2InNn563' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='g2FjE1wxa3q3BIg2ovJ3fAX7LmRO2MQ0w1D6nr8CTT2InNn563' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='g2FjE1wxa3q3BIg2ovJ3fAX7LmRO2MQ0w1D6nr8CTT2InNn563' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='g2FjE1wxa3q3BIg2ovJ3fAX7LmRO2MQ0w1D6nr8CTT2InNn563' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='g2FjE1wxa3q3BIg2ovJ3fAX7LmRO2MQ0w1D6nr8CTT2InNn563' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='g2FjE1wxa3q3BIg2ovJ3fAX7LmRO2MQ0w1D6nr8CTT2InNn563' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='g2FjE1wxa3q3BIg2ovJ3fAX7LmRO2MQ0w1D6nr8CTT2InNn563' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='g2FjE1wxa3q3BIg2ovJ3fAX7LmRO2MQ0w1D6nr8CTT2InNn563' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='g2FjE1wxa3q3BIg2ovJ3fAX7LmRO2MQ0w1D6nr8CTT2InNn563' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='g2FjE1wxa3q3BIg2ovJ3fAX7LmRO2MQ0w1D6nr8CTT2InNn563' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='g2FjE1wxa3q3BIg2ovJ3fAX7LmRO2MQ0w1D6nr8CTT2InNn563' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='g2FjE1wxa3q3BIg2ovJ3fAX7LmRO2MQ0w1D6nr8CTT2InNn563' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='g2FjE1wxa3q3BIg2ovJ3fAX7LmRO2MQ0w1D6nr8CTT2InNn563' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='g2FjE1wxa3q3BIg2ovJ3fAX7LmRO2MQ0w1D6nr8CTT2InNn563' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='g2FjE1wxa3q3BIg2ovJ3fAX7LmRO2MQ0w1D6nr8CTT2InNn563' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='g2FjE1wxa3q3BIg2ovJ3fAX7LmRO2MQ0w1D6nr8CTT2InNn563' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='g2FjE1wxa3q3BIg2ovJ3fAX7LmRO2MQ0w1D6nr8CTT2InNn563' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='g2FjE1wxa3q3BIg2ovJ3fAX7LmRO2MQ0w1D6nr8CTT2InNn563' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='g2FjE1wxa3q3BIg2ovJ3fAX7LmRO2MQ0w1D6nr8CTT2InNn563' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='g2FjE1wxa3q3BIg2ovJ3fAX7LmRO2MQ0w1D6nr8CTT2InNn563' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='g2FjE1wxa3q3BIg2ovJ3fAX7LmRO2MQ0w1D6nr8CTT2InNn563' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='g2FjE1wxa3q3BIg2ovJ3fAX7LmRO2MQ0w1D6nr8CTT2InNn563' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='g2FjE1wxa3q3BIg2ovJ3fAX7LmRO2MQ0w1D6nr8CTT2InNn563' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='g2FjE1wxa3q3BIg2ovJ3fAX7LmRO2MQ0w1D6nr8CTT2InNn563' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='g2FjE1wxa3q3BIg2ovJ3fAX7LmRO2MQ0w1D6nr8CTT2InNn563' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='g2FjE1wxa3q3BIg2ovJ3fAX7LmRO2MQ0w1D6nr8CTT2InNn563' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='g2FjE1wxa3q3BIg2ovJ3fAX7LmRO2MQ0w1D6nr8CTT2InNn563' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='g2FjE1wxa3q3BIg2ovJ3fAX7LmRO2MQ0w1D6nr8CTT2InNn563' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='g2FjE1wxa3q3BIg2ovJ3fAX7LmRO2MQ0w1D6nr8CTT2InNn563' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='g2FjE1wxa3q3BIg2ovJ3fAX7LmRO2MQ0w1D6nr8CTT2InNn563' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='g2FjE1wxa3q3BIg2ovJ3fAX7LmRO2MQ0w1D6nr8CTT2InNn563' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='g2FjE1wxa3q3BIg2ovJ3fAX7LmRO2MQ0w1D6nr8CTT2InNn563' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='g2FjE1wxa3q3BIg2ovJ3fAX7LmRO2MQ0w1D6nr8CTT2InNn563' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='g2FjE1wxa3q3BIg2ovJ3fAX7LmRO2MQ0w1D6nr8CTT2InNn563' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='g2FjE1wxa3q3BIg2ovJ3fAX7LmRO2MQ0w1D6nr8CTT2InNn563' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='g2FjE1wxa3q3BIg2ovJ3fAX7LmRO2MQ0w1D6nr8CTT2InNn563' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='g2FjE1wxa3q3BIg2ovJ3fAX7LmRO2MQ0w1D6nr8CTT2InNn563' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='g2FjE1wxa3q3BIg2ovJ3fAX7LmRO2MQ0w1D6nr8CTT2InNn563' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='g2FjE1wxa3q3BIg2ovJ3fAX7LmRO2MQ0w1D6nr8CTT2InNn563' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='g2FjE1wxa3q3BIg2ovJ3fAX7LmRO2MQ0w1D6nr8CTT2InNn563' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='g2FjE1wxa3q3BIg2ovJ3fAX7LmRO2MQ0w1D6nr8CTT2InNn563' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36' and us.confirmkey is null and blocked is null; -select id from users where username='kilian@juridig.lu' and userpassword='0ecf731e2426a8a469f06e9f4a3bcbed6f8071d9d3e3ef7ef5fd9165021e27ec' and confirmkey is null and blocked is null; -DELETE FROM sessions where id_user='4' and remote_addr='::1' and user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.157 Safari/537.36'; -INSERT INTO sessions (id_user, idsession, remote_addr, user_agent) VALUES('4', 'BohIm775E00VG0c13ax8buOcCMF1mg5e15PSABjt57w4o8T3Vk', '::1', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.157 Safari/537.36'); -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='BohIm775E00VG0c13ax8buOcCMF1mg5e15PSABjt57w4o8T3Vk' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.157 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='BohIm775E00VG0c13ax8buOcCMF1mg5e15PSABjt57w4o8T3Vk' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.157 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='BohIm775E00VG0c13ax8buOcCMF1mg5e15PSABjt57w4o8T3Vk' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.157 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='BohIm775E00VG0c13ax8buOcCMF1mg5e15PSABjt57w4o8T3Vk' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.157 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='BohIm775E00VG0c13ax8buOcCMF1mg5e15PSABjt57w4o8T3Vk' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.157 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='BohIm775E00VG0c13ax8buOcCMF1mg5e15PSABjt57w4o8T3Vk' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.157 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='BohIm775E00VG0c13ax8buOcCMF1mg5e15PSABjt57w4o8T3Vk' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.157 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='BohIm775E00VG0c13ax8buOcCMF1mg5e15PSABjt57w4o8T3Vk' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.157 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='BohIm775E00VG0c13ax8buOcCMF1mg5e15PSABjt57w4o8T3Vk' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.157 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='BohIm775E00VG0c13ax8buOcCMF1mg5e15PSABjt57w4o8T3Vk' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.157 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='BohIm775E00VG0c13ax8buOcCMF1mg5e15PSABjt57w4o8T3Vk' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.157 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='BohIm775E00VG0c13ax8buOcCMF1mg5e15PSABjt57w4o8T3Vk' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.157 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='BohIm775E00VG0c13ax8buOcCMF1mg5e15PSABjt57w4o8T3Vk' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.157 Safari/537.36' and us.confirmkey is null and blocked is null; -select id from users where username='kilian@juridig.lu' and userpassword='0ecf731e2426a8a469f06e9f4a3bcbed6f8071d9d3e3ef7ef5fd9165021e27ec' and confirmkey is null and blocked is null; -DELETE FROM sessions where id_user='4' and remote_addr='::1' and user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.157 Safari/537.36'; -INSERT INTO sessions (id_user, idsession, remote_addr, user_agent) VALUES('4', 'v4dXl4JppUlWP63piApFBu2Pd8CRk8Q1fGVLO5Mc6UFgg8xK1r', '::1', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.157 Safari/537.36'); -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='v4dXl4JppUlWP63piApFBu2Pd8CRk8Q1fGVLO5Mc6UFgg8xK1r' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.157 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='v4dXl4JppUlWP63piApFBu2Pd8CRk8Q1fGVLO5Mc6UFgg8xK1r' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.157 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='v4dXl4JppUlWP63piApFBu2Pd8CRk8Q1fGVLO5Mc6UFgg8xK1r' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.157 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='v4dXl4JppUlWP63piApFBu2Pd8CRk8Q1fGVLO5Mc6UFgg8xK1r' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.157 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='v4dXl4JppUlWP63piApFBu2Pd8CRk8Q1fGVLO5Mc6UFgg8xK1r' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.157 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='v4dXl4JppUlWP63piApFBu2Pd8CRk8Q1fGVLO5Mc6UFgg8xK1r' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.157 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='v4dXl4JppUlWP63piApFBu2Pd8CRk8Q1fGVLO5Mc6UFgg8xK1r' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.157 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='v4dXl4JppUlWP63piApFBu2Pd8CRk8Q1fGVLO5Mc6UFgg8xK1r' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.157 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='v4dXl4JppUlWP63piApFBu2Pd8CRk8Q1fGVLO5Mc6UFgg8xK1r' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.157 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='v4dXl4JppUlWP63piApFBu2Pd8CRk8Q1fGVLO5Mc6UFgg8xK1r' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.157 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='v4dXl4JppUlWP63piApFBu2Pd8CRk8Q1fGVLO5Mc6UFgg8xK1r' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.157 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='v4dXl4JppUlWP63piApFBu2Pd8CRk8Q1fGVLO5Mc6UFgg8xK1r' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.157 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='v4dXl4JppUlWP63piApFBu2Pd8CRk8Q1fGVLO5Mc6UFgg8xK1r' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.157 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='v4dXl4JppUlWP63piApFBu2Pd8CRk8Q1fGVLO5Mc6UFgg8xK1r' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.157 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='v4dXl4JppUlWP63piApFBu2Pd8CRk8Q1fGVLO5Mc6UFgg8xK1r' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.157 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='v4dXl4JppUlWP63piApFBu2Pd8CRk8Q1fGVLO5Mc6UFgg8xK1r' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.157 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='v4dXl4JppUlWP63piApFBu2Pd8CRk8Q1fGVLO5Mc6UFgg8xK1r' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.157 Safari/537.36' and us.confirmkey is null and blocked is null; -select id from users where username='kilian@juridig.lu' and userpassword='0ecf731e2426a8a469f06e9f4a3bcbed6f8071d9d3e3ef7ef5fd9165021e27ec' and confirmkey is null and blocked is null; -DELETE FROM sessions where id_user='4' and remote_addr='::1' and user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.157 Safari/537.36'; -INSERT INTO sessions (id_user, idsession, remote_addr, user_agent) VALUES('4', 'MnAn8Q42RK2EIrHkVICcGiL0546msRJ1eSlEt8jqG3tIa3CNI2', '::1', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.157 Safari/537.36'); -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='MnAn8Q42RK2EIrHkVICcGiL0546msRJ1eSlEt8jqG3tIa3CNI2' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.157 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='MnAn8Q42RK2EIrHkVICcGiL0546msRJ1eSlEt8jqG3tIa3CNI2' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.157 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='MnAn8Q42RK2EIrHkVICcGiL0546msRJ1eSlEt8jqG3tIa3CNI2' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.157 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='MnAn8Q42RK2EIrHkVICcGiL0546msRJ1eSlEt8jqG3tIa3CNI2' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.157 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='MnAn8Q42RK2EIrHkVICcGiL0546msRJ1eSlEt8jqG3tIa3CNI2' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.157 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='MnAn8Q42RK2EIrHkVICcGiL0546msRJ1eSlEt8jqG3tIa3CNI2' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.157 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='MnAn8Q42RK2EIrHkVICcGiL0546msRJ1eSlEt8jqG3tIa3CNI2' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.157 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='MnAn8Q42RK2EIrHkVICcGiL0546msRJ1eSlEt8jqG3tIa3CNI2' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.157 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='MnAn8Q42RK2EIrHkVICcGiL0546msRJ1eSlEt8jqG3tIa3CNI2' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.157 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='MnAn8Q42RK2EIrHkVICcGiL0546msRJ1eSlEt8jqG3tIa3CNI2' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.157 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='MnAn8Q42RK2EIrHkVICcGiL0546msRJ1eSlEt8jqG3tIa3CNI2' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.157 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='MnAn8Q42RK2EIrHkVICcGiL0546msRJ1eSlEt8jqG3tIa3CNI2' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.157 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='MnAn8Q42RK2EIrHkVICcGiL0546msRJ1eSlEt8jqG3tIa3CNI2' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.157 Safari/537.36' and us.confirmkey is null and blocked is null; -select id from users where username='kilian@juridig.lu' and userpassword='0ecf731e2426a8a469f06e9f4a3bcbed6f8071d9d3e3ef7ef5fd9165021e27ec' and confirmkey is null and blocked is null; -DELETE FROM sessions where id_user='4' and remote_addr='::1' and user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.157 Safari/537.36'; -INSERT INTO sessions (id_user, idsession, remote_addr, user_agent) VALUES('4', 'Kfun464NGOo21DQ80ulh27b7u2640SEd1k6O6n81o4O0Vd6QSk', '::1', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.157 Safari/537.36'); -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='Kfun464NGOo21DQ80ulh27b7u2640SEd1k6O6n81o4O0Vd6QSk' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.157 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='Kfun464NGOo21DQ80ulh27b7u2640SEd1k6O6n81o4O0Vd6QSk' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.157 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='Kfun464NGOo21DQ80ulh27b7u2640SEd1k6O6n81o4O0Vd6QSk' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.157 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='Kfun464NGOo21DQ80ulh27b7u2640SEd1k6O6n81o4O0Vd6QSk' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.157 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='Kfun464NGOo21DQ80ulh27b7u2640SEd1k6O6n81o4O0Vd6QSk' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.157 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='Kfun464NGOo21DQ80ulh27b7u2640SEd1k6O6n81o4O0Vd6QSk' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.157 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='Kfun464NGOo21DQ80ulh27b7u2640SEd1k6O6n81o4O0Vd6QSk' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.157 Safari/537.36' and us.confirmkey is null and blocked is null; -select id from users where username='kilian@juridig.lu' and userpassword='0ecf731e2426a8a469f06e9f4a3bcbed6f8071d9d3e3ef7ef5fd9165021e27ec' and confirmkey is null and blocked is null; -DELETE FROM sessions where id_user='4' and remote_addr='::1' and user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.157 Safari/537.36'; -INSERT INTO sessions (id_user, idsession, remote_addr, user_agent) VALUES('4', 'R7NbUQSow5GMuSF027Oni5CK548DnToJXtA8lg6CNBCELWe7ks', '::1', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.157 Safari/537.36'); -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='R7NbUQSow5GMuSF027Oni5CK548DnToJXtA8lg6CNBCELWe7ks' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.157 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='R7NbUQSow5GMuSF027Oni5CK548DnToJXtA8lg6CNBCELWe7ks' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.157 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='R7NbUQSow5GMuSF027Oni5CK548DnToJXtA8lg6CNBCELWe7ks' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.157 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='R7NbUQSow5GMuSF027Oni5CK548DnToJXtA8lg6CNBCELWe7ks' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.157 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='R7NbUQSow5GMuSF027Oni5CK548DnToJXtA8lg6CNBCELWe7ks' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.157 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='R7NbUQSow5GMuSF027Oni5CK548DnToJXtA8lg6CNBCELWe7ks' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.157 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='R7NbUQSow5GMuSF027Oni5CK548DnToJXtA8lg6CNBCELWe7ks' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.157 Safari/537.36' and us.confirmkey is null and blocked is null; -select id from users where username='kilian@juridig.lu' and userpassword='0ecf731e2426a8a469f06e9f4a3bcbed6f8071d9d3e3ef7ef5fd9165021e27ec' and confirmkey is null and blocked is null; -DELETE FROM sessions where id_user='4' and remote_addr='::1' and user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.157 Safari/537.36'; -INSERT INTO sessions (id_user, idsession, remote_addr, user_agent) VALUES('4', 'k5Nr61i6I4B1DxMMs6Es782NvvG0g3wd0rFjI73J0w3o0m3j02', '::1', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.157 Safari/537.36'); -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='k5Nr61i6I4B1DxMMs6Es782NvvG0g3wd0rFjI73J0w3o0m3j02' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.157 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='k5Nr61i6I4B1DxMMs6Es782NvvG0g3wd0rFjI73J0w3o0m3j02' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.157 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='k5Nr61i6I4B1DxMMs6Es782NvvG0g3wd0rFjI73J0w3o0m3j02' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.157 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='k5Nr61i6I4B1DxMMs6Es782NvvG0g3wd0rFjI73J0w3o0m3j02' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.157 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='k5Nr61i6I4B1DxMMs6Es782NvvG0g3wd0rFjI73J0w3o0m3j02' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.157 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='k5Nr61i6I4B1DxMMs6Es782NvvG0g3wd0rFjI73J0w3o0m3j02' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.157 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='k5Nr61i6I4B1DxMMs6Es782NvvG0g3wd0rFjI73J0w3o0m3j02' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.157 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='k5Nr61i6I4B1DxMMs6Es782NvvG0g3wd0rFjI73J0w3o0m3j02' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.157 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='k5Nr61i6I4B1DxMMs6Es782NvvG0g3wd0rFjI73J0w3o0m3j02' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.157 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='k5Nr61i6I4B1DxMMs6Es782NvvG0g3wd0rFjI73J0w3o0m3j02' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.157 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='k5Nr61i6I4B1DxMMs6Es782NvvG0g3wd0rFjI73J0w3o0m3j02' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.157 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='k5Nr61i6I4B1DxMMs6Es782NvvG0g3wd0rFjI73J0w3o0m3j02' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.157 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='k5Nr61i6I4B1DxMMs6Es782NvvG0g3wd0rFjI73J0w3o0m3j02' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.157 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='k5Nr61i6I4B1DxMMs6Es782NvvG0g3wd0rFjI73J0w3o0m3j02' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.157 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='k5Nr61i6I4B1DxMMs6Es782NvvG0g3wd0rFjI73J0w3o0m3j02' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.157 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='k5Nr61i6I4B1DxMMs6Es782NvvG0g3wd0rFjI73J0w3o0m3j02' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.157 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='k5Nr61i6I4B1DxMMs6Es782NvvG0g3wd0rFjI73J0w3o0m3j02' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.157 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='k5Nr61i6I4B1DxMMs6Es782NvvG0g3wd0rFjI73J0w3o0m3j02' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.157 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='k5Nr61i6I4B1DxMMs6Es782NvvG0g3wd0rFjI73J0w3o0m3j02' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.157 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='k5Nr61i6I4B1DxMMs6Es782NvvG0g3wd0rFjI73J0w3o0m3j02' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.157 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='k5Nr61i6I4B1DxMMs6Es782NvvG0g3wd0rFjI73J0w3o0m3j02' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.157 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='k5Nr61i6I4B1DxMMs6Es782NvvG0g3wd0rFjI73J0w3o0m3j02' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.157 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='k5Nr61i6I4B1DxMMs6Es782NvvG0g3wd0rFjI73J0w3o0m3j02' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.157 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='k5Nr61i6I4B1DxMMs6Es782NvvG0g3wd0rFjI73J0w3o0m3j02' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.157 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='k5Nr61i6I4B1DxMMs6Es782NvvG0g3wd0rFjI73J0w3o0m3j02' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.157 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='k5Nr61i6I4B1DxMMs6Es782NvvG0g3wd0rFjI73J0w3o0m3j02' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.157 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='k5Nr61i6I4B1DxMMs6Es782NvvG0g3wd0rFjI73J0w3o0m3j02' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.157 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='k5Nr61i6I4B1DxMMs6Es782NvvG0g3wd0rFjI73J0w3o0m3j02' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.157 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='k5Nr61i6I4B1DxMMs6Es782NvvG0g3wd0rFjI73J0w3o0m3j02' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.157 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='k5Nr61i6I4B1DxMMs6Es782NvvG0g3wd0rFjI73J0w3o0m3j02' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.157 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='k5Nr61i6I4B1DxMMs6Es782NvvG0g3wd0rFjI73J0w3o0m3j02' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.157 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='k5Nr61i6I4B1DxMMs6Es782NvvG0g3wd0rFjI73J0w3o0m3j02' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.157 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='k5Nr61i6I4B1DxMMs6Es782NvvG0g3wd0rFjI73J0w3o0m3j02' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.157 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='k5Nr61i6I4B1DxMMs6Es782NvvG0g3wd0rFjI73J0w3o0m3j02' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.157 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='k5Nr61i6I4B1DxMMs6Es782NvvG0g3wd0rFjI73J0w3o0m3j02' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.157 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='k5Nr61i6I4B1DxMMs6Es782NvvG0g3wd0rFjI73J0w3o0m3j02' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.157 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='k5Nr61i6I4B1DxMMs6Es782NvvG0g3wd0rFjI73J0w3o0m3j02' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.157 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='k5Nr61i6I4B1DxMMs6Es782NvvG0g3wd0rFjI73J0w3o0m3j02' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.157 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='k5Nr61i6I4B1DxMMs6Es782NvvG0g3wd0rFjI73J0w3o0m3j02' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.157 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='k5Nr61i6I4B1DxMMs6Es782NvvG0g3wd0rFjI73J0w3o0m3j02' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.157 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='k5Nr61i6I4B1DxMMs6Es782NvvG0g3wd0rFjI73J0w3o0m3j02' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.157 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='k5Nr61i6I4B1DxMMs6Es782NvvG0g3wd0rFjI73J0w3o0m3j02' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.157 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='k5Nr61i6I4B1DxMMs6Es782NvvG0g3wd0rFjI73J0w3o0m3j02' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.157 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='k5Nr61i6I4B1DxMMs6Es782NvvG0g3wd0rFjI73J0w3o0m3j02' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.157 Safari/537.36' and us.confirmkey is null and blocked is null; -select id from users where username='kilian@juridig.lu' and userpassword='0ecf731e2426a8a469f06e9f4a3bcbed6f8071d9d3e3ef7ef5fd9165021e27ec' and confirmkey is null and blocked is null; -DELETE FROM sessions where id_user='4' and remote_addr='::1' and user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.157 Safari/537.36'; -INSERT INTO sessions (id_user, idsession, remote_addr, user_agent) VALUES('4', '2Bc1bAE1Sr104gj2668DxnGd76v6NNW4lBv7gdFtQCGDFG4Hv1', '::1', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.157 Safari/537.36'); -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='2Bc1bAE1Sr104gj2668DxnGd76v6NNW4lBv7gdFtQCGDFG4Hv1' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.157 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='2Bc1bAE1Sr104gj2668DxnGd76v6NNW4lBv7gdFtQCGDFG4Hv1' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.157 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='2Bc1bAE1Sr104gj2668DxnGd76v6NNW4lBv7gdFtQCGDFG4Hv1' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.157 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='2Bc1bAE1Sr104gj2668DxnGd76v6NNW4lBv7gdFtQCGDFG4Hv1' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.157 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='2Bc1bAE1Sr104gj2668DxnGd76v6NNW4lBv7gdFtQCGDFG4Hv1' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.157 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='2Bc1bAE1Sr104gj2668DxnGd76v6NNW4lBv7gdFtQCGDFG4Hv1' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.157 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='2Bc1bAE1Sr104gj2668DxnGd76v6NNW4lBv7gdFtQCGDFG4Hv1' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.157 Safari/537.36' and us.confirmkey is null and blocked is null; -select id from users where username='kilian@juridig.lu' and userpassword='0ecf731e2426a8a469f06e9f4a3bcbed6f8071d9d3e3ef7ef5fd9165021e27ec' and confirmkey is null and blocked is null; -DELETE FROM sessions where id_user='4' and remote_addr='::1' and user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.157 Safari/537.36'; -INSERT INTO sessions (id_user, idsession, remote_addr, user_agent) VALUES('4', 'M1jr8W62e4Cg82Tv8ReJQn7wB1FJ678F45nxFh4A6C41Kl7Tgu', '::1', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.157 Safari/537.36'); -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='M1jr8W62e4Cg82Tv8ReJQn7wB1FJ678F45nxFh4A6C41Kl7Tgu' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.157 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='M1jr8W62e4Cg82Tv8ReJQn7wB1FJ678F45nxFh4A6C41Kl7Tgu' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.157 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='M1jr8W62e4Cg82Tv8ReJQn7wB1FJ678F45nxFh4A6C41Kl7Tgu' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.157 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='M1jr8W62e4Cg82Tv8ReJQn7wB1FJ678F45nxFh4A6C41Kl7Tgu' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.157 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='M1jr8W62e4Cg82Tv8ReJQn7wB1FJ678F45nxFh4A6C41Kl7Tgu' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.157 Safari/537.36' and us.confirmkey is null and blocked is null; -select id from users where username='kilian@juridig.lu' and userpassword='0ecf731e2426a8a469f06e9f4a3bcbed6f8071d9d3e3ef7ef5fd9165021e27ec' and confirmkey is null and blocked is null; -DELETE FROM sessions where id_user='4' and remote_addr='::1' and user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.157 Safari/537.36'; -INSERT INTO sessions (id_user, idsession, remote_addr, user_agent) VALUES('4', '6j45hQ6l2fo2Q786S1MqkrCp6I54SoI6xIIlrvf353s4q77RQT', '::1', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.157 Safari/537.36'); -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='6j45hQ6l2fo2Q786S1MqkrCp6I54SoI6xIIlrvf353s4q77RQT' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.157 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='6j45hQ6l2fo2Q786S1MqkrCp6I54SoI6xIIlrvf353s4q77RQT' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.157 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='6j45hQ6l2fo2Q786S1MqkrCp6I54SoI6xIIlrvf353s4q77RQT' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.157 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='6j45hQ6l2fo2Q786S1MqkrCp6I54SoI6xIIlrvf353s4q77RQT' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.157 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='6j45hQ6l2fo2Q786S1MqkrCp6I54SoI6xIIlrvf353s4q77RQT' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.157 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='6j45hQ6l2fo2Q786S1MqkrCp6I54SoI6xIIlrvf353s4q77RQT' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.157 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='6j45hQ6l2fo2Q786S1MqkrCp6I54SoI6xIIlrvf353s4q77RQT' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.157 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='6j45hQ6l2fo2Q786S1MqkrCp6I54SoI6xIIlrvf353s4q77RQT' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.157 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='6j45hQ6l2fo2Q786S1MqkrCp6I54SoI6xIIlrvf353s4q77RQT' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.157 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='6j45hQ6l2fo2Q786S1MqkrCp6I54SoI6xIIlrvf353s4q77RQT' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.157 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='6j45hQ6l2fo2Q786S1MqkrCp6I54SoI6xIIlrvf353s4q77RQT' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.157 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='6j45hQ6l2fo2Q786S1MqkrCp6I54SoI6xIIlrvf353s4q77RQT' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.157 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='6j45hQ6l2fo2Q786S1MqkrCp6I54SoI6xIIlrvf353s4q77RQT' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.157 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='6j45hQ6l2fo2Q786S1MqkrCp6I54SoI6xIIlrvf353s4q77RQT' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.157 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='6j45hQ6l2fo2Q786S1MqkrCp6I54SoI6xIIlrvf353s4q77RQT' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.157 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='6j45hQ6l2fo2Q786S1MqkrCp6I54SoI6xIIlrvf353s4q77RQT' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.157 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='6j45hQ6l2fo2Q786S1MqkrCp6I54SoI6xIIlrvf353s4q77RQT' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.157 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='6j45hQ6l2fo2Q786S1MqkrCp6I54SoI6xIIlrvf353s4q77RQT' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.157 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='6j45hQ6l2fo2Q786S1MqkrCp6I54SoI6xIIlrvf353s4q77RQT' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.157 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='6j45hQ6l2fo2Q786S1MqkrCp6I54SoI6xIIlrvf353s4q77RQT' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.157 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='6j45hQ6l2fo2Q786S1MqkrCp6I54SoI6xIIlrvf353s4q77RQT' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.157 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='6j45hQ6l2fo2Q786S1MqkrCp6I54SoI6xIIlrvf353s4q77RQT' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.157 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='6j45hQ6l2fo2Q786S1MqkrCp6I54SoI6xIIlrvf353s4q77RQT' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.157 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='6j45hQ6l2fo2Q786S1MqkrCp6I54SoI6xIIlrvf353s4q77RQT' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.157 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='6j45hQ6l2fo2Q786S1MqkrCp6I54SoI6xIIlrvf353s4q77RQT' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.157 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='6j45hQ6l2fo2Q786S1MqkrCp6I54SoI6xIIlrvf353s4q77RQT' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.157 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='6j45hQ6l2fo2Q786S1MqkrCp6I54SoI6xIIlrvf353s4q77RQT' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.157 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='6j45hQ6l2fo2Q786S1MqkrCp6I54SoI6xIIlrvf353s4q77RQT' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.157 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='6j45hQ6l2fo2Q786S1MqkrCp6I54SoI6xIIlrvf353s4q77RQT' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.157 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='6j45hQ6l2fo2Q786S1MqkrCp6I54SoI6xIIlrvf353s4q77RQT' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.157 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='6j45hQ6l2fo2Q786S1MqkrCp6I54SoI6xIIlrvf353s4q77RQT' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.157 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='6j45hQ6l2fo2Q786S1MqkrCp6I54SoI6xIIlrvf353s4q77RQT' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.157 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='6j45hQ6l2fo2Q786S1MqkrCp6I54SoI6xIIlrvf353s4q77RQT' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.157 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='6j45hQ6l2fo2Q786S1MqkrCp6I54SoI6xIIlrvf353s4q77RQT' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.157 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='6j45hQ6l2fo2Q786S1MqkrCp6I54SoI6xIIlrvf353s4q77RQT' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.157 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='6j45hQ6l2fo2Q786S1MqkrCp6I54SoI6xIIlrvf353s4q77RQT' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.157 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='6j45hQ6l2fo2Q786S1MqkrCp6I54SoI6xIIlrvf353s4q77RQT' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.157 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='6j45hQ6l2fo2Q786S1MqkrCp6I54SoI6xIIlrvf353s4q77RQT' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.157 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='6j45hQ6l2fo2Q786S1MqkrCp6I54SoI6xIIlrvf353s4q77RQT' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.157 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='6j45hQ6l2fo2Q786S1MqkrCp6I54SoI6xIIlrvf353s4q77RQT' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.157 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='6j45hQ6l2fo2Q786S1MqkrCp6I54SoI6xIIlrvf353s4q77RQT' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.157 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='6j45hQ6l2fo2Q786S1MqkrCp6I54SoI6xIIlrvf353s4q77RQT' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.157 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='6j45hQ6l2fo2Q786S1MqkrCp6I54SoI6xIIlrvf353s4q77RQT' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.157 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='6j45hQ6l2fo2Q786S1MqkrCp6I54SoI6xIIlrvf353s4q77RQT' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.157 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='6j45hQ6l2fo2Q786S1MqkrCp6I54SoI6xIIlrvf353s4q77RQT' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.157 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='6j45hQ6l2fo2Q786S1MqkrCp6I54SoI6xIIlrvf353s4q77RQT' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.157 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='6j45hQ6l2fo2Q786S1MqkrCp6I54SoI6xIIlrvf353s4q77RQT' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.157 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='6j45hQ6l2fo2Q786S1MqkrCp6I54SoI6xIIlrvf353s4q77RQT' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.157 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='6j45hQ6l2fo2Q786S1MqkrCp6I54SoI6xIIlrvf353s4q77RQT' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.157 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='6j45hQ6l2fo2Q786S1MqkrCp6I54SoI6xIIlrvf353s4q77RQT' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.157 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='6j45hQ6l2fo2Q786S1MqkrCp6I54SoI6xIIlrvf353s4q77RQT' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.157 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='6j45hQ6l2fo2Q786S1MqkrCp6I54SoI6xIIlrvf353s4q77RQT' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.157 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='6j45hQ6l2fo2Q786S1MqkrCp6I54SoI6xIIlrvf353s4q77RQT' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.157 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='6j45hQ6l2fo2Q786S1MqkrCp6I54SoI6xIIlrvf353s4q77RQT' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.157 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='6j45hQ6l2fo2Q786S1MqkrCp6I54SoI6xIIlrvf353s4q77RQT' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.157 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='6j45hQ6l2fo2Q786S1MqkrCp6I54SoI6xIIlrvf353s4q77RQT' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.157 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='6j45hQ6l2fo2Q786S1MqkrCp6I54SoI6xIIlrvf353s4q77RQT' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.157 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='6j45hQ6l2fo2Q786S1MqkrCp6I54SoI6xIIlrvf353s4q77RQT' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.157 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='6j45hQ6l2fo2Q786S1MqkrCp6I54SoI6xIIlrvf353s4q77RQT' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.157 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='6j45hQ6l2fo2Q786S1MqkrCp6I54SoI6xIIlrvf353s4q77RQT' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.157 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='6j45hQ6l2fo2Q786S1MqkrCp6I54SoI6xIIlrvf353s4q77RQT' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.157 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='6j45hQ6l2fo2Q786S1MqkrCp6I54SoI6xIIlrvf353s4q77RQT' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.157 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='6j45hQ6l2fo2Q786S1MqkrCp6I54SoI6xIIlrvf353s4q77RQT' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.157 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='6j45hQ6l2fo2Q786S1MqkrCp6I54SoI6xIIlrvf353s4q77RQT' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.157 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='6j45hQ6l2fo2Q786S1MqkrCp6I54SoI6xIIlrvf353s4q77RQT' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.157 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='6j45hQ6l2fo2Q786S1MqkrCp6I54SoI6xIIlrvf353s4q77RQT' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.157 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='6j45hQ6l2fo2Q786S1MqkrCp6I54SoI6xIIlrvf353s4q77RQT' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.157 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='6j45hQ6l2fo2Q786S1MqkrCp6I54SoI6xIIlrvf353s4q77RQT' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.157 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='6j45hQ6l2fo2Q786S1MqkrCp6I54SoI6xIIlrvf353s4q77RQT' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.157 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='6j45hQ6l2fo2Q786S1MqkrCp6I54SoI6xIIlrvf353s4q77RQT' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.157 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='6j45hQ6l2fo2Q786S1MqkrCp6I54SoI6xIIlrvf353s4q77RQT' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.157 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='6j45hQ6l2fo2Q786S1MqkrCp6I54SoI6xIIlrvf353s4q77RQT' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.157 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='6j45hQ6l2fo2Q786S1MqkrCp6I54SoI6xIIlrvf353s4q77RQT' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.157 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='6j45hQ6l2fo2Q786S1MqkrCp6I54SoI6xIIlrvf353s4q77RQT' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.157 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='6j45hQ6l2fo2Q786S1MqkrCp6I54SoI6xIIlrvf353s4q77RQT' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.157 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='6j45hQ6l2fo2Q786S1MqkrCp6I54SoI6xIIlrvf353s4q77RQT' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.157 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='6j45hQ6l2fo2Q786S1MqkrCp6I54SoI6xIIlrvf353s4q77RQT' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.157 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='6j45hQ6l2fo2Q786S1MqkrCp6I54SoI6xIIlrvf353s4q77RQT' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.157 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='6j45hQ6l2fo2Q786S1MqkrCp6I54SoI6xIIlrvf353s4q77RQT' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.157 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='6j45hQ6l2fo2Q786S1MqkrCp6I54SoI6xIIlrvf353s4q77RQT' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.157 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='6j45hQ6l2fo2Q786S1MqkrCp6I54SoI6xIIlrvf353s4q77RQT' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.157 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='6j45hQ6l2fo2Q786S1MqkrCp6I54SoI6xIIlrvf353s4q77RQT' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.157 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='6j45hQ6l2fo2Q786S1MqkrCp6I54SoI6xIIlrvf353s4q77RQT' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.157 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='6j45hQ6l2fo2Q786S1MqkrCp6I54SoI6xIIlrvf353s4q77RQT' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.157 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='6j45hQ6l2fo2Q786S1MqkrCp6I54SoI6xIIlrvf353s4q77RQT' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.157 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='6j45hQ6l2fo2Q786S1MqkrCp6I54SoI6xIIlrvf353s4q77RQT' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.157 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='6j45hQ6l2fo2Q786S1MqkrCp6I54SoI6xIIlrvf353s4q77RQT' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.157 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='6j45hQ6l2fo2Q786S1MqkrCp6I54SoI6xIIlrvf353s4q77RQT' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.157 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='6j45hQ6l2fo2Q786S1MqkrCp6I54SoI6xIIlrvf353s4q77RQT' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.157 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='6j45hQ6l2fo2Q786S1MqkrCp6I54SoI6xIIlrvf353s4q77RQT' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.157 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='6j45hQ6l2fo2Q786S1MqkrCp6I54SoI6xIIlrvf353s4q77RQT' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.157 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='6j45hQ6l2fo2Q786S1MqkrCp6I54SoI6xIIlrvf353s4q77RQT' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.157 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='6j45hQ6l2fo2Q786S1MqkrCp6I54SoI6xIIlrvf353s4q77RQT' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.157 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='6j45hQ6l2fo2Q786S1MqkrCp6I54SoI6xIIlrvf353s4q77RQT' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.157 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='6j45hQ6l2fo2Q786S1MqkrCp6I54SoI6xIIlrvf353s4q77RQT' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.157 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='6j45hQ6l2fo2Q786S1MqkrCp6I54SoI6xIIlrvf353s4q77RQT' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.157 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='6j45hQ6l2fo2Q786S1MqkrCp6I54SoI6xIIlrvf353s4q77RQT' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.157 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='6j45hQ6l2fo2Q786S1MqkrCp6I54SoI6xIIlrvf353s4q77RQT' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.157 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='6j45hQ6l2fo2Q786S1MqkrCp6I54SoI6xIIlrvf353s4q77RQT' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.157 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='6j45hQ6l2fo2Q786S1MqkrCp6I54SoI6xIIlrvf353s4q77RQT' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.157 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='6j45hQ6l2fo2Q786S1MqkrCp6I54SoI6xIIlrvf353s4q77RQT' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.157 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='6j45hQ6l2fo2Q786S1MqkrCp6I54SoI6xIIlrvf353s4q77RQT' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.157 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='6j45hQ6l2fo2Q786S1MqkrCp6I54SoI6xIIlrvf353s4q77RQT' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.157 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='6j45hQ6l2fo2Q786S1MqkrCp6I54SoI6xIIlrvf353s4q77RQT' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.157 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='6j45hQ6l2fo2Q786S1MqkrCp6I54SoI6xIIlrvf353s4q77RQT' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.157 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='6j45hQ6l2fo2Q786S1MqkrCp6I54SoI6xIIlrvf353s4q77RQT' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.157 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='6j45hQ6l2fo2Q786S1MqkrCp6I54SoI6xIIlrvf353s4q77RQT' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.157 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='6j45hQ6l2fo2Q786S1MqkrCp6I54SoI6xIIlrvf353s4q77RQT' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.157 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='6j45hQ6l2fo2Q786S1MqkrCp6I54SoI6xIIlrvf353s4q77RQT' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.157 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='6j45hQ6l2fo2Q786S1MqkrCp6I54SoI6xIIlrvf353s4q77RQT' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.157 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='6j45hQ6l2fo2Q786S1MqkrCp6I54SoI6xIIlrvf353s4q77RQT' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.157 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='6j45hQ6l2fo2Q786S1MqkrCp6I54SoI6xIIlrvf353s4q77RQT' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.157 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='6j45hQ6l2fo2Q786S1MqkrCp6I54SoI6xIIlrvf353s4q77RQT' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.157 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='6j45hQ6l2fo2Q786S1MqkrCp6I54SoI6xIIlrvf353s4q77RQT' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.157 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='6j45hQ6l2fo2Q786S1MqkrCp6I54SoI6xIIlrvf353s4q77RQT' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.157 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='6j45hQ6l2fo2Q786S1MqkrCp6I54SoI6xIIlrvf353s4q77RQT' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.157 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='6j45hQ6l2fo2Q786S1MqkrCp6I54SoI6xIIlrvf353s4q77RQT' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.157 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='6j45hQ6l2fo2Q786S1MqkrCp6I54SoI6xIIlrvf353s4q77RQT' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.157 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='6j45hQ6l2fo2Q786S1MqkrCp6I54SoI6xIIlrvf353s4q77RQT' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.157 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='6j45hQ6l2fo2Q786S1MqkrCp6I54SoI6xIIlrvf353s4q77RQT' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.157 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='6j45hQ6l2fo2Q786S1MqkrCp6I54SoI6xIIlrvf353s4q77RQT' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.157 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='6j45hQ6l2fo2Q786S1MqkrCp6I54SoI6xIIlrvf353s4q77RQT' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.157 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='6j45hQ6l2fo2Q786S1MqkrCp6I54SoI6xIIlrvf353s4q77RQT' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.157 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='6j45hQ6l2fo2Q786S1MqkrCp6I54SoI6xIIlrvf353s4q77RQT' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.157 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='6j45hQ6l2fo2Q786S1MqkrCp6I54SoI6xIIlrvf353s4q77RQT' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.157 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='6j45hQ6l2fo2Q786S1MqkrCp6I54SoI6xIIlrvf353s4q77RQT' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.157 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='6j45hQ6l2fo2Q786S1MqkrCp6I54SoI6xIIlrvf353s4q77RQT' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.157 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='6j45hQ6l2fo2Q786S1MqkrCp6I54SoI6xIIlrvf353s4q77RQT' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.157 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='6j45hQ6l2fo2Q786S1MqkrCp6I54SoI6xIIlrvf353s4q77RQT' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.157 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='6j45hQ6l2fo2Q786S1MqkrCp6I54SoI6xIIlrvf353s4q77RQT' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.157 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='6j45hQ6l2fo2Q786S1MqkrCp6I54SoI6xIIlrvf353s4q77RQT' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.157 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='6j45hQ6l2fo2Q786S1MqkrCp6I54SoI6xIIlrvf353s4q77RQT' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.157 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='6j45hQ6l2fo2Q786S1MqkrCp6I54SoI6xIIlrvf353s4q77RQT' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.157 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='6j45hQ6l2fo2Q786S1MqkrCp6I54SoI6xIIlrvf353s4q77RQT' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.157 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='6j45hQ6l2fo2Q786S1MqkrCp6I54SoI6xIIlrvf353s4q77RQT' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.157 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='6j45hQ6l2fo2Q786S1MqkrCp6I54SoI6xIIlrvf353s4q77RQT' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.157 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='6j45hQ6l2fo2Q786S1MqkrCp6I54SoI6xIIlrvf353s4q77RQT' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.157 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='6j45hQ6l2fo2Q786S1MqkrCp6I54SoI6xIIlrvf353s4q77RQT' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.157 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='6j45hQ6l2fo2Q786S1MqkrCp6I54SoI6xIIlrvf353s4q77RQT' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.157 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='6j45hQ6l2fo2Q786S1MqkrCp6I54SoI6xIIlrvf353s4q77RQT' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.157 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='6j45hQ6l2fo2Q786S1MqkrCp6I54SoI6xIIlrvf353s4q77RQT' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.157 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='6j45hQ6l2fo2Q786S1MqkrCp6I54SoI6xIIlrvf353s4q77RQT' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.157 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='6j45hQ6l2fo2Q786S1MqkrCp6I54SoI6xIIlrvf353s4q77RQT' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.157 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='6j45hQ6l2fo2Q786S1MqkrCp6I54SoI6xIIlrvf353s4q77RQT' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.157 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='6j45hQ6l2fo2Q786S1MqkrCp6I54SoI6xIIlrvf353s4q77RQT' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.157 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='6j45hQ6l2fo2Q786S1MqkrCp6I54SoI6xIIlrvf353s4q77RQT' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.157 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='6j45hQ6l2fo2Q786S1MqkrCp6I54SoI6xIIlrvf353s4q77RQT' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.157 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='6j45hQ6l2fo2Q786S1MqkrCp6I54SoI6xIIlrvf353s4q77RQT' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.157 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='6j45hQ6l2fo2Q786S1MqkrCp6I54SoI6xIIlrvf353s4q77RQT' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.157 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='6j45hQ6l2fo2Q786S1MqkrCp6I54SoI6xIIlrvf353s4q77RQT' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.157 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='6j45hQ6l2fo2Q786S1MqkrCp6I54SoI6xIIlrvf353s4q77RQT' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.157 Safari/537.36' and us.confirmkey is null and blocked is null; -select id from users where username='kilian@jurdig.lu' and userpassword='0ecf731e2426a8a469f06e9f4a3bcbed6f8071d9d3e3ef7ef5fd9165021e27ec' and confirmkey is null and blocked is null; -select id from users where username='kilian@juridig.lu' and userpassword='0ecf731e2426a8a469f06e9f4a3bcbed6f8071d9d3e3ef7ef5fd9165021e27ec' and confirmkey is null and blocked is null; -DELETE FROM sessions where id_user='4' and remote_addr='::1' and user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.157 Safari/537.36'; -INSERT INTO sessions (id_user, idsession, remote_addr, user_agent) VALUES('4', '7d0C27FjmDDFqO7d4nAou674Q262ioC0D8Hc1C1M372Pm2145m', '::1', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.157 Safari/537.36'); -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='7d0C27FjmDDFqO7d4nAou674Q262ioC0D8Hc1C1M372Pm2145m' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.157 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='7d0C27FjmDDFqO7d4nAou674Q262ioC0D8Hc1C1M372Pm2145m' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.157 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='7d0C27FjmDDFqO7d4nAou674Q262ioC0D8Hc1C1M372Pm2145m' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.157 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='7d0C27FjmDDFqO7d4nAou674Q262ioC0D8Hc1C1M372Pm2145m' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.157 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='7d0C27FjmDDFqO7d4nAou674Q262ioC0D8Hc1C1M372Pm2145m' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.157 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='7d0C27FjmDDFqO7d4nAou674Q262ioC0D8Hc1C1M372Pm2145m' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.157 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='7d0C27FjmDDFqO7d4nAou674Q262ioC0D8Hc1C1M372Pm2145m' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.157 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='7d0C27FjmDDFqO7d4nAou674Q262ioC0D8Hc1C1M372Pm2145m' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.157 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='7d0C27FjmDDFqO7d4nAou674Q262ioC0D8Hc1C1M372Pm2145m' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.157 Safari/537.36' and us.confirmkey is null and blocked is null; -select id from users where username='kilian@juridig.lu' and userpassword='0ecf731e2426a8a469f06e9f4a3bcbed6f8071d9d3e3ef7ef5fd9165021e27ec' and confirmkey is null and blocked is null; -DELETE FROM sessions where id_user='4' and remote_addr='::1' and user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.157 Safari/537.36'; -INSERT INTO sessions (id_user, idsession, remote_addr, user_agent) VALUES('4', 'K7D75GJ6X8JpcfF5S6uldS61wOFMuP6sr1RubjjIG6IwSpiSXR', '::1', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.157 Safari/537.36'); -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='K7D75GJ6X8JpcfF5S6uldS61wOFMuP6sr1RubjjIG6IwSpiSXR' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.157 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='K7D75GJ6X8JpcfF5S6uldS61wOFMuP6sr1RubjjIG6IwSpiSXR' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.157 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='K7D75GJ6X8JpcfF5S6uldS61wOFMuP6sr1RubjjIG6IwSpiSXR' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.157 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='K7D75GJ6X8JpcfF5S6uldS61wOFMuP6sr1RubjjIG6IwSpiSXR' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.157 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='K7D75GJ6X8JpcfF5S6uldS61wOFMuP6sr1RubjjIG6IwSpiSXR' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.157 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='K7D75GJ6X8JpcfF5S6uldS61wOFMuP6sr1RubjjIG6IwSpiSXR' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.157 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='K7D75GJ6X8JpcfF5S6uldS61wOFMuP6sr1RubjjIG6IwSpiSXR' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.157 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='K7D75GJ6X8JpcfF5S6uldS61wOFMuP6sr1RubjjIG6IwSpiSXR' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.157 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='K7D75GJ6X8JpcfF5S6uldS61wOFMuP6sr1RubjjIG6IwSpiSXR' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.157 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='K7D75GJ6X8JpcfF5S6uldS61wOFMuP6sr1RubjjIG6IwSpiSXR' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.157 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='K7D75GJ6X8JpcfF5S6uldS61wOFMuP6sr1RubjjIG6IwSpiSXR' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.157 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='K7D75GJ6X8JpcfF5S6uldS61wOFMuP6sr1RubjjIG6IwSpiSXR' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.157 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='K7D75GJ6X8JpcfF5S6uldS61wOFMuP6sr1RubjjIG6IwSpiSXR' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.157 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='K7D75GJ6X8JpcfF5S6uldS61wOFMuP6sr1RubjjIG6IwSpiSXR' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.157 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='K7D75GJ6X8JpcfF5S6uldS61wOFMuP6sr1RubjjIG6IwSpiSXR' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.157 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='K7D75GJ6X8JpcfF5S6uldS61wOFMuP6sr1RubjjIG6IwSpiSXR' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.157 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='K7D75GJ6X8JpcfF5S6uldS61wOFMuP6sr1RubjjIG6IwSpiSXR' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.157 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='K7D75GJ6X8JpcfF5S6uldS61wOFMuP6sr1RubjjIG6IwSpiSXR' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.157 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='K7D75GJ6X8JpcfF5S6uldS61wOFMuP6sr1RubjjIG6IwSpiSXR' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.157 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='K7D75GJ6X8JpcfF5S6uldS61wOFMuP6sr1RubjjIG6IwSpiSXR' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.157 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='K7D75GJ6X8JpcfF5S6uldS61wOFMuP6sr1RubjjIG6IwSpiSXR' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.157 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='K7D75GJ6X8JpcfF5S6uldS61wOFMuP6sr1RubjjIG6IwSpiSXR' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.157 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='K7D75GJ6X8JpcfF5S6uldS61wOFMuP6sr1RubjjIG6IwSpiSXR' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.157 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='K7D75GJ6X8JpcfF5S6uldS61wOFMuP6sr1RubjjIG6IwSpiSXR' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.157 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='K7D75GJ6X8JpcfF5S6uldS61wOFMuP6sr1RubjjIG6IwSpiSXR' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.157 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='K7D75GJ6X8JpcfF5S6uldS61wOFMuP6sr1RubjjIG6IwSpiSXR' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.157 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='K7D75GJ6X8JpcfF5S6uldS61wOFMuP6sr1RubjjIG6IwSpiSXR' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.157 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='K7D75GJ6X8JpcfF5S6uldS61wOFMuP6sr1RubjjIG6IwSpiSXR' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.157 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='K7D75GJ6X8JpcfF5S6uldS61wOFMuP6sr1RubjjIG6IwSpiSXR' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.157 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='K7D75GJ6X8JpcfF5S6uldS61wOFMuP6sr1RubjjIG6IwSpiSXR' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.157 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='K7D75GJ6X8JpcfF5S6uldS61wOFMuP6sr1RubjjIG6IwSpiSXR' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.157 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='K7D75GJ6X8JpcfF5S6uldS61wOFMuP6sr1RubjjIG6IwSpiSXR' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.157 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='K7D75GJ6X8JpcfF5S6uldS61wOFMuP6sr1RubjjIG6IwSpiSXR' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.157 Safari/537.36' and us.confirmkey is null and blocked is null; -select id from users where username='kilian@juridig.lu' and userpassword='0ecf731e2426a8a469f06e9f4a3bcbed6f8071d9d3e3ef7ef5fd9165021e27ec' and confirmkey is null and blocked is null; -DELETE FROM sessions where id_user='4' and remote_addr='::1' and user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.157 Safari/537.36'; -INSERT INTO sessions (id_user, idsession, remote_addr, user_agent) VALUES('4', 'Qn6gdim687lNL2Fja6H8252tWnE5Pw2ie4nIOjBL40Rn8t0WB6', '::1', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.157 Safari/537.36'); -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='Qn6gdim687lNL2Fja6H8252tWnE5Pw2ie4nIOjBL40Rn8t0WB6' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.157 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='Qn6gdim687lNL2Fja6H8252tWnE5Pw2ie4nIOjBL40Rn8t0WB6' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.157 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='Qn6gdim687lNL2Fja6H8252tWnE5Pw2ie4nIOjBL40Rn8t0WB6' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.157 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='Qn6gdim687lNL2Fja6H8252tWnE5Pw2ie4nIOjBL40Rn8t0WB6' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.157 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='Qn6gdim687lNL2Fja6H8252tWnE5Pw2ie4nIOjBL40Rn8t0WB6' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.157 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='Qn6gdim687lNL2Fja6H8252tWnE5Pw2ie4nIOjBL40Rn8t0WB6' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.157 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='Qn6gdim687lNL2Fja6H8252tWnE5Pw2ie4nIOjBL40Rn8t0WB6' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.157 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='Qn6gdim687lNL2Fja6H8252tWnE5Pw2ie4nIOjBL40Rn8t0WB6' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.157 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='Qn6gdim687lNL2Fja6H8252tWnE5Pw2ie4nIOjBL40Rn8t0WB6' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.157 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='Qn6gdim687lNL2Fja6H8252tWnE5Pw2ie4nIOjBL40Rn8t0WB6' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.157 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='Qn6gdim687lNL2Fja6H8252tWnE5Pw2ie4nIOjBL40Rn8t0WB6' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.157 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='Qn6gdim687lNL2Fja6H8252tWnE5Pw2ie4nIOjBL40Rn8t0WB6' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.157 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='Qn6gdim687lNL2Fja6H8252tWnE5Pw2ie4nIOjBL40Rn8t0WB6' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.157 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='Qn6gdim687lNL2Fja6H8252tWnE5Pw2ie4nIOjBL40Rn8t0WB6' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.157 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='Qn6gdim687lNL2Fja6H8252tWnE5Pw2ie4nIOjBL40Rn8t0WB6' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.157 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='Qn6gdim687lNL2Fja6H8252tWnE5Pw2ie4nIOjBL40Rn8t0WB6' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.157 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='Qn6gdim687lNL2Fja6H8252tWnE5Pw2ie4nIOjBL40Rn8t0WB6' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.157 Safari/537.36' and us.confirmkey is null and blocked is null; -select id from users where username='kilian@juridig.lu' and userpassword='0ecf731e2426a8a469f06e9f4a3bcbed6f8071d9d3e3ef7ef5fd9165021e27ec' and confirmkey is null and blocked is null; -DELETE FROM sessions where id_user='4' and remote_addr='::1' and user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.157 Safari/537.36'; -INSERT INTO sessions (id_user, idsession, remote_addr, user_agent) VALUES('4', '4N3Kd7PQ3TCJ1GVwFcaGUqXiERU8Oq3HFRamvMwLPdBP244COv', '::1', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.157 Safari/537.36'); -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='4N3Kd7PQ3TCJ1GVwFcaGUqXiERU8Oq3HFRamvMwLPdBP244COv' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.157 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='4N3Kd7PQ3TCJ1GVwFcaGUqXiERU8Oq3HFRamvMwLPdBP244COv' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.157 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='4N3Kd7PQ3TCJ1GVwFcaGUqXiERU8Oq3HFRamvMwLPdBP244COv' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.157 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='4N3Kd7PQ3TCJ1GVwFcaGUqXiERU8Oq3HFRamvMwLPdBP244COv' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.157 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='4N3Kd7PQ3TCJ1GVwFcaGUqXiERU8Oq3HFRamvMwLPdBP244COv' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.157 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='4N3Kd7PQ3TCJ1GVwFcaGUqXiERU8Oq3HFRamvMwLPdBP244COv' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.157 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='4N3Kd7PQ3TCJ1GVwFcaGUqXiERU8Oq3HFRamvMwLPdBP244COv' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.157 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='4N3Kd7PQ3TCJ1GVwFcaGUqXiERU8Oq3HFRamvMwLPdBP244COv' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.157 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='4N3Kd7PQ3TCJ1GVwFcaGUqXiERU8Oq3HFRamvMwLPdBP244COv' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.157 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='4N3Kd7PQ3TCJ1GVwFcaGUqXiERU8Oq3HFRamvMwLPdBP244COv' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.157 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='4N3Kd7PQ3TCJ1GVwFcaGUqXiERU8Oq3HFRamvMwLPdBP244COv' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.157 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='4N3Kd7PQ3TCJ1GVwFcaGUqXiERU8Oq3HFRamvMwLPdBP244COv' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.157 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='4N3Kd7PQ3TCJ1GVwFcaGUqXiERU8Oq3HFRamvMwLPdBP244COv' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.157 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='4N3Kd7PQ3TCJ1GVwFcaGUqXiERU8Oq3HFRamvMwLPdBP244COv' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.157 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='4N3Kd7PQ3TCJ1GVwFcaGUqXiERU8Oq3HFRamvMwLPdBP244COv' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.157 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='4N3Kd7PQ3TCJ1GVwFcaGUqXiERU8Oq3HFRamvMwLPdBP244COv' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.157 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='4N3Kd7PQ3TCJ1GVwFcaGUqXiERU8Oq3HFRamvMwLPdBP244COv' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.157 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='4N3Kd7PQ3TCJ1GVwFcaGUqXiERU8Oq3HFRamvMwLPdBP244COv' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.157 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='4N3Kd7PQ3TCJ1GVwFcaGUqXiERU8Oq3HFRamvMwLPdBP244COv' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.157 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='4N3Kd7PQ3TCJ1GVwFcaGUqXiERU8Oq3HFRamvMwLPdBP244COv' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.157 Safari/537.36' and us.confirmkey is null and blocked is null; -select se.idsession,us.id,us.username,us.email,us.prename,us.surname from sessions se -join users us on (us.id=se.id_user) -left join appaccess ac on (us.id=ac.id_user) -where se.idsession='4N3Kd7PQ3TCJ1GVwFcaGUqXiERU8Oq3HFRamvMwLPdBP244COv' -and se.remote_addr='::1' -and se.user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.157 Safari/537.36' and us.confirmkey is null and blocked is null; diff --git a/backoffice/tmpl/module/applications.tt b/backoffice/tmpl/module/applications.tt index 6c2a001..5d8a441 100644 --- a/backoffice/tmpl/module/applications.tt +++ b/backoffice/tmpl/module/applications.tt @@ -80,37 +80,30 @@ - - - - - - - -
Coordonnées de facturation
+
Coordonnées de facturation
-
+
-
+
-
+
-
+
-
+
@@ -118,7 +111,7 @@
 
- +
diff --git a/backoffice/tmpl/module/js/applications.js b/backoffice/tmpl/module/js/applications.js index 4358ae6..52ddf7e 100644 --- a/backoffice/tmpl/module/js/applications.js +++ b/backoffice/tmpl/module/js/applications.js @@ -10,9 +10,9 @@ var iduser=[% session.id %]; [% END %] }; var subscribe_data = {}; - var paypal_data ={"amount":{"currency_code":"EUR","value":null},"description":null,"soft_descriptor":"juridig.lu"}; + var paypal_data ={"amount":{"currency_code":"EUR","value":null},"description":null,"soft_descriptor":"juridig"}; function subscribeplan(app,package,type){ - //console.log(appdata[app]["packages"][package]); + $("#voucher_data").hide(); $("#checkout_data").hide(); $("#checkout_package").hide(); @@ -28,28 +28,20 @@ var iduser=[% session.id %]; var sumvat = sumnet * 0.17; var sumgross = sumnet + sumvat; paypal_data.amount["value"] = sumgross.toFixed(2); - paypal_data.description = "Souscription juridig - " + appdata[app]["name"] + ' - ' + package; + paypal_data.description = "Souscription juridig.lu - " + appdata[app]["name"] + ' - ' + package; $("#checkout_data").html("durée: "+ appdata[app]["packages"][package]["duration"] +" mois
Prix (TVA inclus): "+ sumgross.toFixed(2) +" €"); $("#checkout_data").show(); if (sumgross == 0.0){ $("#paypal-button-container").hide(); $("#btn_activate").show(); + }else { + $(".frmdata").hide(); } $("#id_app").val(app); $("#package").val(package); - $("#quantiy").val(appdata[app]["packages"][package]["duration"]); - $("#unitamount").val(unitamount); - $("#unit").val('mois'); - $("#vatpercent").val(appdata[app]["packages"][package]["vatpercent"]); - $("#netamount").val(sumnet); - $("#vatamount").val(sumvat); - $("#grossamount").val(sumgross); + } - - - - $("section").hide(); $("#terms").show(); return false; @@ -88,19 +80,16 @@ var iduser=[% session.id %]; if (sumgross == 0.0){ $("#paypal-button-container").hide(); $("#btn_activate").show(); + } else { + $("#invadrdata").show(); + $(".frmdata").show(); } $("#id_app").val(app); $("#package").val(package); - $("#quantiy").val(appdata[app]["packages"][package]["duration"]); - $("#unitamount").val(unitamount); - $("#unit").val('mois'); - $("#vatpercent").val(appdata[app]["packages"][package]["vatpercent"]); - $("#netamount").val(sumnet); - $("#vatamount").val(sumvat); - $("#grossamount").val(sumgross); + $("#voucher").val($("#coupon").val()); $("#coupon").attr("readonly",true); - $("#invadrdata").show(); - $("#voucherinfo").html(); + + $("#voucherinfo").html(""); } else { $("#voucherinfo").html('
Le coupon demandé n\'est plus valide!
'); } @@ -122,26 +111,29 @@ var iduser=[% session.id %]; process_data(pdata,activate_callback); } -function buy_viainvoice(){ - if (!$("#frm_invoicedata").hasClass("was-validated")){ - console.log("Validation NOT OK!RETURN"); - return false; - } - var pdata = {fn:"activateapp"}; - $("input,select").each(function(){ - pdata[$(this).attr("id")] = $(this).val(); - }); - console.log(pdata); - process_data(pdata,lauchinvoice_callback); -} +// function buy_viainvoice(){ +// if (!$("#frm_invoicedata").hasClass("was-validated")){ +// console.log("Validation NOT OK!RETURN"); +// return false; +// } +// var pdata = {fn:"activateapp"}; +// $("input,select").each(function(){ +// pdata[$(this).attr("id")] = $(this).val(); +// }); +// console.log(pdata); +// process_data(pdata,lauchinvoice_callback); +// } function activate_callback(data){ + console.log("activate (voucher) callback"); console.log(data); parent.location.reload(); } function paypal_callback(data){ - + console.log("Paypal callback"); + console.log(data); + parent.location.reload(); } paypal.Buttons({ @@ -161,11 +153,11 @@ function buy_viainvoice(){ return actions.order.capture().then(function(details) { console.log(details); var pdata ={ "paypal": details, "appinfo": {},"fn":"paypal_payement"}; - $("input,select").each(function(){ + $("input[type='hidden']").each(function(){ pdata["appinfo"][$(this).attr("id")] = $(this).val(); }); - process_data(pdata,lauchpaypal_callback); + process_data(pdata,paypal_callback); //alert('Transaction completed by ' + details+ '!'); }); diff --git a/lib/CGI.pm b/lib/CGI.pm index 297f95e..f6f5f1a 100644 --- a/lib/CGI.pm +++ b/lib/CGI.pm @@ -1,4 +1,6 @@ #line 1 "CGI.pm" +#line 1 "CGI.pm" +#line 1 "CGI.pm" package CGI; require 5.008001; use if $] >= 5.019, 'deprecate'; diff --git a/lib/CGI/Carp.pm b/lib/CGI/Carp.pm index 4a8a234..cc69673 100644 --- a/lib/CGI/Carp.pm +++ b/lib/CGI/Carp.pm @@ -1,4 +1,6 @@ #line 1 "CGI/Carp.pm" +#line 1 "CGI/Carp.pm" +#line 1 "CGI/Carp.pm" package CGI::Carp; use if $] >= 5.019, 'deprecate'; diff --git a/lib/CGI/Cookie.pm b/lib/CGI/Cookie.pm index b0c78c4..6deef14 100644 --- a/lib/CGI/Cookie.pm +++ b/lib/CGI/Cookie.pm @@ -1,4 +1,6 @@ #line 1 "CGI/Cookie.pm" +#line 1 "CGI/Cookie.pm" +#line 1 "CGI/Cookie.pm" package CGI::Cookie; use strict; diff --git a/lib/CGI/File/Temp.pm b/lib/CGI/File/Temp.pm index 19b1461..2e2e326 100644 --- a/lib/CGI/File/Temp.pm +++ b/lib/CGI/File/Temp.pm @@ -1,4 +1,6 @@ #line 1 "CGI/File/Temp.pm" +#line 1 "CGI/File/Temp.pm" +#line 1 "CGI/File/Temp.pm" # this is a back compatibility wrapper around File::Temp. DO NOT # use this package outside of CGI, i won't provide any help if # you use it directly and your code breaks horribly. diff --git a/lib/CGI/Util.pm b/lib/CGI/Util.pm index 35d2838..8e8e8cb 100644 --- a/lib/CGI/Util.pm +++ b/lib/CGI/Util.pm @@ -1,4 +1,6 @@ #line 1 "CGI/Util.pm" +#line 1 "CGI/Util.pm" +#line 1 "CGI/Util.pm" package CGI::Util; use base 'Exporter'; require 5.008001; diff --git a/lib/DBD/DBM.pm b/lib/DBD/DBM.pm index 8e2c50b..348eb71 100644 --- a/lib/DBD/DBM.pm +++ b/lib/DBD/DBM.pm @@ -1,4 +1,6 @@ #line 1 "DBD/DBM.pm" +#line 1 "DBD/DBM.pm" +#line 1 "DBD/DBM.pm" ####################################################################### # # DBD::DBM - a DBI driver for DBM files diff --git a/lib/DBD/ExampleP.pm b/lib/DBD/ExampleP.pm index a5cbb04..5320519 100644 --- a/lib/DBD/ExampleP.pm +++ b/lib/DBD/ExampleP.pm @@ -1,4 +1,6 @@ #line 1 "DBD/ExampleP.pm" +#line 1 "DBD/ExampleP.pm" +#line 1 "DBD/ExampleP.pm" { package DBD::ExampleP; diff --git a/lib/DBD/File.pm b/lib/DBD/File.pm index ab0419c..6a61a09 100644 --- a/lib/DBD/File.pm +++ b/lib/DBD/File.pm @@ -1,4 +1,6 @@ #line 1 "DBD/File.pm" +#line 1 "DBD/File.pm" +#line 1 "DBD/File.pm" # -*- perl -*- # # DBD::File - A base class for implementing DBI drivers that diff --git a/lib/DBD/Gofer.pm b/lib/DBD/Gofer.pm index c23ba78..6d39caa 100644 --- a/lib/DBD/Gofer.pm +++ b/lib/DBD/Gofer.pm @@ -1,4 +1,6 @@ #line 1 "DBD/Gofer.pm" +#line 1 "DBD/Gofer.pm" +#line 1 "DBD/Gofer.pm" { package DBD::Gofer; diff --git a/lib/DBD/Gofer/Policy/Base.pm b/lib/DBD/Gofer/Policy/Base.pm index 32d6651..5cd28a6 100644 --- a/lib/DBD/Gofer/Policy/Base.pm +++ b/lib/DBD/Gofer/Policy/Base.pm @@ -1,4 +1,6 @@ #line 1 "DBD/Gofer/Policy/Base.pm" +#line 1 "DBD/Gofer/Policy/Base.pm" +#line 1 "DBD/Gofer/Policy/Base.pm" package DBD::Gofer::Policy::Base; # $Id: Base.pm 10087 2007-10-16 12:42:37Z Tim $ diff --git a/lib/DBD/Gofer/Policy/classic.pm b/lib/DBD/Gofer/Policy/classic.pm index b67a2f7..6cf6036 100644 --- a/lib/DBD/Gofer/Policy/classic.pm +++ b/lib/DBD/Gofer/Policy/classic.pm @@ -1,4 +1,6 @@ #line 1 "DBD/Gofer/Policy/classic.pm" +#line 1 "DBD/Gofer/Policy/classic.pm" +#line 1 "DBD/Gofer/Policy/classic.pm" package DBD::Gofer::Policy::classic; # $Id: classic.pm 10087 2007-10-16 12:42:37Z Tim $ diff --git a/lib/DBD/Gofer/Policy/pedantic.pm b/lib/DBD/Gofer/Policy/pedantic.pm index 7108722..8292f2c 100644 --- a/lib/DBD/Gofer/Policy/pedantic.pm +++ b/lib/DBD/Gofer/Policy/pedantic.pm @@ -1,4 +1,6 @@ #line 1 "DBD/Gofer/Policy/pedantic.pm" +#line 1 "DBD/Gofer/Policy/pedantic.pm" +#line 1 "DBD/Gofer/Policy/pedantic.pm" package DBD::Gofer::Policy::pedantic; # $Id: pedantic.pm 10087 2007-10-16 12:42:37Z Tim $ diff --git a/lib/DBD/Gofer/Policy/rush.pm b/lib/DBD/Gofer/Policy/rush.pm index 5391906..e50049e 100644 --- a/lib/DBD/Gofer/Policy/rush.pm +++ b/lib/DBD/Gofer/Policy/rush.pm @@ -1,4 +1,6 @@ #line 1 "DBD/Gofer/Policy/rush.pm" +#line 1 "DBD/Gofer/Policy/rush.pm" +#line 1 "DBD/Gofer/Policy/rush.pm" package DBD::Gofer::Policy::rush; # $Id: rush.pm 10087 2007-10-16 12:42:37Z Tim $ diff --git a/lib/DBD/Gofer/Transport/Base.pm b/lib/DBD/Gofer/Transport/Base.pm index 0970145..3d9aba7 100644 --- a/lib/DBD/Gofer/Transport/Base.pm +++ b/lib/DBD/Gofer/Transport/Base.pm @@ -1,4 +1,6 @@ #line 1 "DBD/Gofer/Transport/Base.pm" +#line 1 "DBD/Gofer/Transport/Base.pm" +#line 1 "DBD/Gofer/Transport/Base.pm" package DBD::Gofer::Transport::Base; # $Id: Base.pm 14120 2010-06-07 19:52:19Z H.Merijn $ diff --git a/lib/DBD/Gofer/Transport/corostream.pm b/lib/DBD/Gofer/Transport/corostream.pm index e0ce313..a72c482 100644 --- a/lib/DBD/Gofer/Transport/corostream.pm +++ b/lib/DBD/Gofer/Transport/corostream.pm @@ -1,4 +1,6 @@ #line 1 "DBD/Gofer/Transport/corostream.pm" +#line 1 "DBD/Gofer/Transport/corostream.pm" +#line 1 "DBD/Gofer/Transport/corostream.pm" package DBD::Gofer::Transport::corostream; use strict; diff --git a/lib/DBD/Gofer/Transport/null.pm b/lib/DBD/Gofer/Transport/null.pm index f2f23ee..2384473 100644 --- a/lib/DBD/Gofer/Transport/null.pm +++ b/lib/DBD/Gofer/Transport/null.pm @@ -1,4 +1,6 @@ #line 1 "DBD/Gofer/Transport/null.pm" +#line 1 "DBD/Gofer/Transport/null.pm" +#line 1 "DBD/Gofer/Transport/null.pm" package DBD::Gofer::Transport::null; # $Id: null.pm 10087 2007-10-16 12:42:37Z Tim $ diff --git a/lib/DBD/Gofer/Transport/pipeone.pm b/lib/DBD/Gofer/Transport/pipeone.pm index 89b98a4..6616559 100644 --- a/lib/DBD/Gofer/Transport/pipeone.pm +++ b/lib/DBD/Gofer/Transport/pipeone.pm @@ -1,4 +1,6 @@ #line 1 "DBD/Gofer/Transport/pipeone.pm" +#line 1 "DBD/Gofer/Transport/pipeone.pm" +#line 1 "DBD/Gofer/Transport/pipeone.pm" package DBD::Gofer::Transport::pipeone; # $Id: pipeone.pm 10087 2007-10-16 12:42:37Z Tim $ diff --git a/lib/DBD/Gofer/Transport/stream.pm b/lib/DBD/Gofer/Transport/stream.pm index 3826131..8a665c8 100644 --- a/lib/DBD/Gofer/Transport/stream.pm +++ b/lib/DBD/Gofer/Transport/stream.pm @@ -1,4 +1,6 @@ #line 1 "DBD/Gofer/Transport/stream.pm" +#line 1 "DBD/Gofer/Transport/stream.pm" +#line 1 "DBD/Gofer/Transport/stream.pm" package DBD::Gofer::Transport::stream; # $Id: stream.pm 14598 2010-12-21 22:53:25Z Tim $ diff --git a/lib/DBD/NullP.pm b/lib/DBD/NullP.pm index 40917bf..8e5dfa3 100644 --- a/lib/DBD/NullP.pm +++ b/lib/DBD/NullP.pm @@ -1,4 +1,6 @@ #line 1 "DBD/NullP.pm" +#line 1 "DBD/NullP.pm" +#line 1 "DBD/NullP.pm" use strict; { package DBD::NullP; diff --git a/lib/DBD/PgPP.pm b/lib/DBD/PgPP.pm index 8d4219b..a384130 100644 --- a/lib/DBD/PgPP.pm +++ b/lib/DBD/PgPP.pm @@ -1,4 +1,6 @@ #line 1 "DBD/PgPP.pm" +#line 1 "DBD/PgPP.pm" +#line 1 "DBD/PgPP.pm" package DBD::PgPP; use strict; diff --git a/lib/DBD/SQLite.pm b/lib/DBD/SQLite.pm index b33f384..1e8ee78 100644 --- a/lib/DBD/SQLite.pm +++ b/lib/DBD/SQLite.pm @@ -1,4 +1,6 @@ #line 1 "DBD/SQLite.pm" +#line 1 "DBD/SQLite.pm" +#line 1 "DBD/SQLite.pm" package DBD::SQLite; use 5.006; diff --git a/lib/DBD/SQLite/Constants.pm b/lib/DBD/SQLite/Constants.pm index b1c33da..707bad6 100644 --- a/lib/DBD/SQLite/Constants.pm +++ b/lib/DBD/SQLite/Constants.pm @@ -1,4 +1,6 @@ #line 1 "DBD/SQLite/Constants.pm" +#line 1 "DBD/SQLite/Constants.pm" +#line 1 "DBD/SQLite/Constants.pm" package DBD::SQLite::Constants; # This module is generated by a script. diff --git a/lib/DBD/SQLite/GetInfo.pm b/lib/DBD/SQLite/GetInfo.pm index e1ac444..c30b656 100644 --- a/lib/DBD/SQLite/GetInfo.pm +++ b/lib/DBD/SQLite/GetInfo.pm @@ -1,4 +1,6 @@ #line 1 "DBD/SQLite/GetInfo.pm" +#line 1 "DBD/SQLite/GetInfo.pm" +#line 1 "DBD/SQLite/GetInfo.pm" package DBD::SQLite::GetInfo; use 5.006; diff --git a/lib/DBD/SQLite/VirtualTable.pm b/lib/DBD/SQLite/VirtualTable.pm index 3a2ba3c..e82be60 100644 --- a/lib/DBD/SQLite/VirtualTable.pm +++ b/lib/DBD/SQLite/VirtualTable.pm @@ -1,4 +1,6 @@ #line 1 "DBD/SQLite/VirtualTable.pm" +#line 1 "DBD/SQLite/VirtualTable.pm" +#line 1 "DBD/SQLite/VirtualTable.pm" #====================================================================== package DBD::SQLite::VirtualTable; #====================================================================== diff --git a/lib/DBD/SQLite/VirtualTable/FileContent.pm b/lib/DBD/SQLite/VirtualTable/FileContent.pm index 5380705..a9694ff 100644 --- a/lib/DBD/SQLite/VirtualTable/FileContent.pm +++ b/lib/DBD/SQLite/VirtualTable/FileContent.pm @@ -1,4 +1,6 @@ #line 1 "DBD/SQLite/VirtualTable/FileContent.pm" +#line 1 "DBD/SQLite/VirtualTable/FileContent.pm" +#line 1 "DBD/SQLite/VirtualTable/FileContent.pm" #====================================================================== package DBD::SQLite::VirtualTable::FileContent; #====================================================================== diff --git a/lib/DBD/SQLite/VirtualTable/PerlData.pm b/lib/DBD/SQLite/VirtualTable/PerlData.pm index 4d6f48f..16fa29f 100644 --- a/lib/DBD/SQLite/VirtualTable/PerlData.pm +++ b/lib/DBD/SQLite/VirtualTable/PerlData.pm @@ -1,4 +1,6 @@ #line 1 "DBD/SQLite/VirtualTable/PerlData.pm" +#line 1 "DBD/SQLite/VirtualTable/PerlData.pm" +#line 1 "DBD/SQLite/VirtualTable/PerlData.pm" #====================================================================== package DBD::SQLite::VirtualTable::PerlData; #====================================================================== diff --git a/lib/DBD/Sponge.pm b/lib/DBD/Sponge.pm index 1c593c9..630f4f6 100644 --- a/lib/DBD/Sponge.pm +++ b/lib/DBD/Sponge.pm @@ -1,4 +1,6 @@ #line 1 "DBD/Sponge.pm" +#line 1 "DBD/Sponge.pm" +#line 1 "DBD/Sponge.pm" use strict; { package DBD::Sponge; diff --git a/lib/DBD/mysql.pm b/lib/DBD/mysql.pm index e942256..0653172 100644 --- a/lib/DBD/mysql.pm +++ b/lib/DBD/mysql.pm @@ -1,5 +1,7 @@ #!/usr/bin/perl #line 2 "DBD/mysql.pm" +#line 2 "DBD/mysql.pm" +#line 2 "DBD/mysql.pm" use strict; use warnings; diff --git a/lib/DBD/mysql/GetInfo.pm b/lib/DBD/mysql/GetInfo.pm index ff817a1..3ed749a 100644 --- a/lib/DBD/mysql/GetInfo.pm +++ b/lib/DBD/mysql/GetInfo.pm @@ -1,4 +1,6 @@ #line 1 "DBD/mysql/GetInfo.pm" +#line 1 "DBD/mysql/GetInfo.pm" +#line 1 "DBD/mysql/GetInfo.pm" package DBD::mysql::GetInfo; ######################################## # DBD::mysql::GetInfo diff --git a/lib/DBI.pm b/lib/DBI.pm index 49a429b..9c5bb73 100644 --- a/lib/DBI.pm +++ b/lib/DBI.pm @@ -1,4 +1,6 @@ #line 1 "DBI.pm" +#line 1 "DBI.pm" +#line 1 "DBI.pm" # $Id$ # vim: ts=8:sw=4:et # diff --git a/lib/DBI/Const/GetInfo/ANSI.pm b/lib/DBI/Const/GetInfo/ANSI.pm index 5f22e0f..1d5c1b4 100644 --- a/lib/DBI/Const/GetInfo/ANSI.pm +++ b/lib/DBI/Const/GetInfo/ANSI.pm @@ -1,4 +1,6 @@ #line 1 "DBI/Const/GetInfo/ANSI.pm" +#line 1 "DBI/Const/GetInfo/ANSI.pm" +#line 1 "DBI/Const/GetInfo/ANSI.pm" # $Id: ANSI.pm 8696 2007-01-24 23:12:38Z Tim $ # # Copyright (c) 2002 Tim Bunce Ireland diff --git a/lib/DBI/Const/GetInfo/ODBC.pm b/lib/DBI/Const/GetInfo/ODBC.pm index 2c31c00..afe24a6 100644 --- a/lib/DBI/Const/GetInfo/ODBC.pm +++ b/lib/DBI/Const/GetInfo/ODBC.pm @@ -1,4 +1,6 @@ #line 1 "DBI/Const/GetInfo/ODBC.pm" +#line 1 "DBI/Const/GetInfo/ODBC.pm" +#line 1 "DBI/Const/GetInfo/ODBC.pm" # $Id: ODBC.pm 11373 2008-06-02 19:01:33Z Tim $ # # Copyright (c) 2002 Tim Bunce Ireland diff --git a/lib/DBI/Const/GetInfoType.pm b/lib/DBI/Const/GetInfoType.pm index 0c26516..0c71e51 100644 --- a/lib/DBI/Const/GetInfoType.pm +++ b/lib/DBI/Const/GetInfoType.pm @@ -1,4 +1,6 @@ #line 1 "DBI/Const/GetInfoType.pm" +#line 1 "DBI/Const/GetInfoType.pm" +#line 1 "DBI/Const/GetInfoType.pm" # $Id: GetInfoType.pm 8696 2007-01-24 23:12:38Z Tim $ # # Copyright (c) 2002 Tim Bunce Ireland diff --git a/lib/DBI/DBD/SqlEngine.pm b/lib/DBI/DBD/SqlEngine.pm index 5637be9..87df7ee 100644 --- a/lib/DBI/DBD/SqlEngine.pm +++ b/lib/DBI/DBD/SqlEngine.pm @@ -1,4 +1,6 @@ #line 1 "DBI/DBD/SqlEngine.pm" +#line 1 "DBI/DBD/SqlEngine.pm" +#line 1 "DBI/DBD/SqlEngine.pm" # -*- perl -*- # # DBI::DBD::SqlEngine - A base class for implementing DBI drivers that diff --git a/lib/DBI/Gofer/Execute.pm b/lib/DBI/Gofer/Execute.pm index 59d132d..3419375 100644 --- a/lib/DBI/Gofer/Execute.pm +++ b/lib/DBI/Gofer/Execute.pm @@ -1,4 +1,6 @@ #line 1 "DBI/Gofer/Execute.pm" +#line 1 "DBI/Gofer/Execute.pm" +#line 1 "DBI/Gofer/Execute.pm" package DBI::Gofer::Execute; # $Id: Execute.pm 14282 2010-07-26 00:12:54Z David $ diff --git a/lib/DBI/Gofer/Request.pm b/lib/DBI/Gofer/Request.pm index eb31376..ab513cf 100644 --- a/lib/DBI/Gofer/Request.pm +++ b/lib/DBI/Gofer/Request.pm @@ -1,4 +1,6 @@ #line 1 "DBI/Gofer/Request.pm" +#line 1 "DBI/Gofer/Request.pm" +#line 1 "DBI/Gofer/Request.pm" package DBI::Gofer::Request; # $Id: Request.pm 12536 2009-02-24 22:37:09Z Tim $ diff --git a/lib/DBI/Gofer/Response.pm b/lib/DBI/Gofer/Response.pm index f927041..9cc5972 100644 --- a/lib/DBI/Gofer/Response.pm +++ b/lib/DBI/Gofer/Response.pm @@ -1,4 +1,6 @@ #line 1 "DBI/Gofer/Response.pm" +#line 1 "DBI/Gofer/Response.pm" +#line 1 "DBI/Gofer/Response.pm" package DBI::Gofer::Response; # $Id: Response.pm 11565 2008-07-22 20:17:33Z Tim $ diff --git a/lib/DBI/Gofer/Serializer/Base.pm b/lib/DBI/Gofer/Serializer/Base.pm index 28fc6bb..8ae2230 100644 --- a/lib/DBI/Gofer/Serializer/Base.pm +++ b/lib/DBI/Gofer/Serializer/Base.pm @@ -1,4 +1,6 @@ #line 1 "DBI/Gofer/Serializer/Base.pm" +#line 1 "DBI/Gofer/Serializer/Base.pm" +#line 1 "DBI/Gofer/Serializer/Base.pm" package DBI::Gofer::Serializer::Base; # $Id: Base.pm 9949 2007-09-18 09:38:15Z Tim $ diff --git a/lib/DBI/Gofer/Serializer/DataDumper.pm b/lib/DBI/Gofer/Serializer/DataDumper.pm index 935bc82..1bad1ef 100644 --- a/lib/DBI/Gofer/Serializer/DataDumper.pm +++ b/lib/DBI/Gofer/Serializer/DataDumper.pm @@ -1,4 +1,6 @@ #line 1 "DBI/Gofer/Serializer/DataDumper.pm" +#line 1 "DBI/Gofer/Serializer/DataDumper.pm" +#line 1 "DBI/Gofer/Serializer/DataDumper.pm" package DBI::Gofer::Serializer::DataDumper; use strict; diff --git a/lib/DBI/Gofer/Serializer/Storable.pm b/lib/DBI/Gofer/Serializer/Storable.pm index 5c48428..1103515 100644 --- a/lib/DBI/Gofer/Serializer/Storable.pm +++ b/lib/DBI/Gofer/Serializer/Storable.pm @@ -1,4 +1,6 @@ #line 1 "DBI/Gofer/Serializer/Storable.pm" +#line 1 "DBI/Gofer/Serializer/Storable.pm" +#line 1 "DBI/Gofer/Serializer/Storable.pm" package DBI::Gofer::Serializer::Storable; use strict; diff --git a/lib/DBI/Gofer/Transport/Base.pm b/lib/DBI/Gofer/Transport/Base.pm index c35d589..f36ab36 100644 --- a/lib/DBI/Gofer/Transport/Base.pm +++ b/lib/DBI/Gofer/Transport/Base.pm @@ -1,4 +1,6 @@ #line 1 "DBI/Gofer/Transport/Base.pm" +#line 1 "DBI/Gofer/Transport/Base.pm" +#line 1 "DBI/Gofer/Transport/Base.pm" package DBI::Gofer::Transport::Base; # $Id: Base.pm 12536 2009-02-24 22:37:09Z Tim $ diff --git a/lib/DBI/PurePerl.pm b/lib/DBI/PurePerl.pm index 66a92d0..0f227f1 100644 --- a/lib/DBI/PurePerl.pm +++ b/lib/DBI/PurePerl.pm @@ -1,4 +1,6 @@ #line 1 "DBI/PurePerl.pm" +#line 1 "DBI/PurePerl.pm" +#line 1 "DBI/PurePerl.pm" ######################################################################## package # hide from PAUSE DBI; diff --git a/lib/DBI/SQL/Nano.pm b/lib/DBI/SQL/Nano.pm index 5b3de44..98b343b 100644 --- a/lib/DBI/SQL/Nano.pm +++ b/lib/DBI/SQL/Nano.pm @@ -1,4 +1,6 @@ #line 1 "DBI/SQL/Nano.pm" +#line 1 "DBI/SQL/Nano.pm" +#line 1 "DBI/SQL/Nano.pm" ####################################################################### # # DBI::SQL::Nano - a very tiny SQL engine diff --git a/lib/DBI/Util/_accessor.pm b/lib/DBI/Util/_accessor.pm index 96ed4fe..a67b176 100644 --- a/lib/DBI/Util/_accessor.pm +++ b/lib/DBI/Util/_accessor.pm @@ -1,4 +1,6 @@ #line 1 "DBI/Util/_accessor.pm" +#line 1 "DBI/Util/_accessor.pm" +#line 1 "DBI/Util/_accessor.pm" package DBI::Util::_accessor; use strict; use Carp; diff --git a/lib/Digest/SHA/PurePerl.pm b/lib/Digest/SHA/PurePerl.pm index 602cc74..705abcd 100644 --- a/lib/Digest/SHA/PurePerl.pm +++ b/lib/Digest/SHA/PurePerl.pm @@ -1,4 +1,6 @@ #line 1 "Digest/SHA/PurePerl.pm" +#line 1 "Digest/SHA/PurePerl.pm" +#line 1 "Digest/SHA/PurePerl.pm" package Digest::SHA::PurePerl; require 5.003000; diff --git a/lib/Fh.pm b/lib/Fh.pm index 98c2d4c..96c84e1 100644 --- a/lib/Fh.pm +++ b/lib/Fh.pm @@ -1,4 +1,6 @@ #line 1 "Fh.pm" +#line 1 "Fh.pm" +#line 1 "Fh.pm" # back compatibility package for any code explicitly checking # that the filehandle object is a Fh package Fh; diff --git a/lib/Font/TTF/Font.pm b/lib/Font/TTF/Font.pm new file mode 100644 index 0000000..7cbbd98 --- /dev/null +++ b/lib/Font/TTF/Font.pm @@ -0,0 +1,633 @@ +#line 1 "Font/TTF/Font.pm" +#line 1 "Font/TTF/Font.pm" +package Font::TTF::Font; + +#line 139 + +use IO::File; + +use strict; +use vars qw(%tables $VERSION $dumper); +use Symbol(); + +require 5.004; + +my $havezlib = eval {require Compress::Zlib}; + +$VERSION = 0.39; # MJPH 2-FEB-2008 Add DSIG table +# $VERSION = 0.38; # MJPH 2-FEB-2008 Add Sill table +# $VERSION = 0.37; # MJPH 7-OCT-2005 Force hhea update if dirty, give more OS/2 stuff in update +# $VERSION = 0.36; # MJPH 19-AUG-2005 Change cmap::reverse api to be opts based +# $VERSION = 0.35; # MJPH 4-MAY-2004 Various fixes to OpenType stuff, separate off scripts +# $VERSION = 0.34; # MJPH 22-MAY-2003 Update PSNames to latest AGL +# $VERSION = 0.33; # MJPH 9-OCT-2002 Support CFF OpenType (just by version=='OTTO'?!) +# $VERSION = 0.32; # MJPH 2-OCT-2002 Bug fixes to TTFBuilder, new methods and some +# extension table support in Ttopen and Coverage +# $VERSION = 0.31; # MJPH 1-JUL-2002 fix read format 12 cmap (bart@cs.pdx.edu) +# improve surrogate support in ttfremap +# fix return warn to return warn,undef +# ensure correct indexToLocFormat +# $VERSION = 0.30; # MJPH 28-MAY-2002 add updated release +# $VERSION = 0.29; # MJPH 9-APR-2002 update ttfbuilder, sort out surrogates +# $VERSION = 0.28; # MJPH 13-MAR-2002 update ttfbuilder, add Font::TTF::Cmap::ms_enc() +# $VERSION = 0.27; # MJPH 6-FEB-2002 update ttfbuilder, support no fpgm, no more __DATA__ +# $VERSION = 0.26; # MJPH 19-SEP-2001 Update ttfbuilder +# $VERSION = 0.25; # MJPH 18-SEP-2001 problems in update of head +# $VERSION = 0.24; # MJPH 1-AUG-2001 Sort out update +# $VERSION = 0.23; # GST 30-MAY-2001 Memory leak fixed +# $VERSION = 0.22; # MJPH 09-APR-2001 Ensure all of AAT stuff included +# $VERSION = 0.21; # MJPH 23-MAR-2001 Improve Opentype support +# $VERSION = 0.20; # MJPH 13-JAN-2001 Add XML output and some of XML input, AAT & OT tables +# $VERSION = 0.19; # MJPH 29-SEP-2000 Add cmap::is_unicode, debug makefile.pl +# $VERSION = 0.18; # MJPH 21-JUL-2000 Debug Utils::TTF_bininfo +# $VERSION = 0.17; # MJPH 16-JUN-2000 Add utf8 support to names +# $VERSION = 0.16; # MJPH 26-APR-2000 Mark read tables as read, tidy up POD +# $VERSION = 0.15; # MJPH 5-FEB-2000 Ensure right versions released +# $VERSION = 0.14; # MJPH 11-SEP-1999 Sort out Unixisms, agian! +# $VERSION = 0.13; # MJPH 9-SEP-1999 Add empty, debug update_bbox +# $VERSION = 0.12; # MJPH 22-JUL-1999 Add update_bbox +# $VERSION = 0.11; # MJPH 7-JUL-1999 Don't store empties in cmaps +# $VERSION = 0.10; # MJPH 21-JUN-1999 Use IO::File +# $VERSION = 0.09; # MJPH 9-JUN-1999 Add 5.004 require, minor tweeks in cmap +# $VERSION = 0.08; # MJPH 19-MAY-1999 Sort out line endings for Unix +# $VERSION = 0.07; # MJPH 28-APR-1999 Get the regression tests to work +# $VERSION = 0.06; # MJPH 26-APR-1999 Start to add to CVS, correct MANIFEST.SKIP +# $VERSION = 0.05; # MJPH 13-APR-1999 See changes for 0.05 +# $VERSION = 0.04; # MJPH 13-MAR-1999 Tidy up Tarball +# $VERSION = 0.03; # MJPH 9-MAR-1999 Move to Font::TTF for CPAN +# $VERSION = 0.02; # MJPH 12-FEB-1999 Add support for ' nocsum' for DSIGS +# $VERSION = 0.0001; + +%tables = ( + 'table' => 'Font::TTF::Table', + 'DSIG' => 'Font::TTF::DSIG', + 'EBDT' => 'Font::TTF::EBDT', + 'EBLC' => 'Font::TTF::EBLC', + 'Feat' => 'Font::TTF::GrFeat', + 'GDEF' => 'Font::TTF::GDEF', + 'Glat' => 'Font::TTF::Glat', + 'Gloc' => 'Font::TTF::Gloc', + 'GPOS' => 'Font::TTF::GPOS', + 'GSUB' => 'Font::TTF::GSUB', + 'Glat' => 'Font::TTF::Glat', + 'Gloc' => 'Font::TTF::Gloc', + 'LTSH' => 'Font::TTF::LTSH', + 'OS/2' => 'Font::TTF::OS_2', + 'PCLT' => 'Font::TTF::PCLT', + 'Sill' => 'Font::TTF::Sill', + 'Silf' => 'Font::TTF::Silf', + 'bsln' => 'Font::TTF::Bsln', + 'cmap' => 'Font::TTF::Cmap', + 'cvt ' => 'Font::TTF::Cvt_', + 'fdsc' => 'Font::TTF::Fdsc', + 'feat' => 'Font::TTF::Feat', + 'fmtx' => 'Font::TTF::Fmtx', + 'fpgm' => 'Font::TTF::Fpgm', + 'glyf' => 'Font::TTF::Glyf', + 'hdmx' => 'Font::TTF::Hdmx', + 'head' => 'Font::TTF::Head', + 'hhea' => 'Font::TTF::Hhea', + 'hmtx' => 'Font::TTF::Hmtx', + 'kern' => 'Font::TTF::Kern', + 'loca' => 'Font::TTF::Loca', + 'maxp' => 'Font::TTF::Maxp', + 'mort' => 'Font::TTF::Mort', + 'name' => 'Font::TTF::Name', + 'post' => 'Font::TTF::Post', + 'prep' => 'Font::TTF::Prep', + 'prop' => 'Font::TTF::Prop', + 'vhea' => 'Font::TTF::Vhea', + 'vmtx' => 'Font::TTF::Vmtx', + ); + +# This is special code because I am fed up of every time I x a table in the debugger +# I get the whole font printed. Thus substitutes my 3 line change to dumpvar into +# the debugger. Clunky, but nice. You are welcome to a copy if you want one. + +BEGIN { + my ($p); + + foreach $p (@INC) + { + if (-f "$p/mydumpvar.pl") + { + $dumper = 'mydumpvar.pl'; + last; + } + } + $dumper ||= 'dumpvar.pl'; +} + +sub main::dumpValue +{ do $dumper; &main::dumpValue; } + + +#line 264 + +sub AddTable +{ + my ($class, $table, $useclass) = @_; + + $tables{$table} = $useclass; +# $useclass =~ s|::|/|oig; +# require "$useclass.pm"; +} + + +#line 282 + +sub Init +{ + my ($class) = @_; + my ($t); + + foreach $t (values %tables) + { + $t =~ s|::|/|oig; + require "$t.pm"; + } +} + +#line 303 + +sub new +{ + my ($class, %props) = @_; + my ($self) = {}; + + bless $self, $class; + + foreach (keys %props) + { $self->{" $_"} = $props{$_}; } + $self; +} + + +#line 323 + +sub open +{ + my ($class, $fname) = @_; + my ($fh); + my ($self) = {}; + + unless (ref($fname)) + { + $fh = IO::File->new($fname) or return undef; + binmode $fh; + } else + { $fh = $fname; } + + $self->{' INFILE'} = $fh; + $self->{' fname'} = $fname; + $self->{' OFFSET'} = 0; + bless $self, $class; + + $self->read; +} + +#line 352 + +sub read +{ + my ($self) = @_; + my ($fh) = $self->{' INFILE'}; + my ($dat, $i, $ver, $dir_num, $type, $name, $check, $off, $len, $t); + my ($iswoff, $woffLength, $sfntSize, $zlen); # needed for WOFF files + + $fh->seek($self->{' OFFSET'}, 0); + $fh->read($dat, 4); + $ver = unpack("N", $dat); + $iswoff = ($ver == unpack('N', 'wOFF')); + if ($iswoff) + { + require Font::TTF::Woff; + my $woff = Font::TTF::Woff->new(PARENT => $self); + $fh->read($dat, 32); + ($ver, $woffLength, $dir_num, undef, $sfntSize, $woff->{'majorVersion'}, $woff->{'minorVersion'}, + $off, $zlen, $len) = unpack('NNnnNnnNNN', $dat); + # TODO: According to WOFF spec we should verify $woffLength and $sfntSize, and fail if the values are wrong. + if ($off) + { + # Font has metadata + if ($off + $zlen > $woffLength) + { + warn "invalid WOFF header in $self->{' fname'}: meta data beyond end."; + return undef; + } + require Font::TTF::Woff::MetaData; + $woff->{'metaData'} = Font::TTF::Woff::MetaData->new( + PARENT => $woff, + INFILE => $fh, + OFFSET => $off, + LENGTH => $len, + ZLENGTH => $zlen); + } + + $fh->read($dat, 8); + ($off, $len) = unpack('NN', $dat); + if ($off) + { + # Font has private data + if ($off + $len > $woffLength) + { + warn "invalid WOFF header in $self->{' fname'}: private data beyond end."; + return undef; + } + require Font::TTF::Woff::PrivateData; + $woff->{'privateData'} = Font::TTF::Woff::PrivateData->new( + PARENT => $woff, + INFILE => $fh, + OFFSET => $off, + LENGTH => $len); + } + + $self->{' WOFF'} = $woff; + } + else + { + $fh->read($dat, 8); + $dir_num = unpack("n", $dat); + } + + $ver == 1 << 16 # TrueType outlines + || $ver == unpack('N', 'OTTO') # 0x4F54544F CFF outlines + || $ver == unpack('N', 'true') # 0x74727565 Mac sfnts + or return undef; # else unrecognized type + + + for ($i = 0; $i < $dir_num; $i++) + { + $fh->read($dat, $iswoff ? 20 : 16) || die "Reading table entry"; + if ($iswoff) + { + ($name, $off, $zlen, $len, $check) = unpack("a4NNNN", $dat); + if ($off + $zlen > $woffLength || $zlen > $len) + { + my $err; + $err = "Offset + compressed length > total length. " if $off + $zlen > $woffLength; + $err = "Compressed length > uncompressed length. " if $zlen > $len; + warn "invalid WOFF '$name' table in $self->{' fname'}: $err\n"; + return undef; + } + } + else + { + ($name, $check, $off, $len) = unpack("a4NNN", $dat); + $zlen = $len; + } + $self->{$name} = $self->{' PARENT'}->find($self, $name, $check, $off, $len) and next + if (defined $self->{' PARENT'}); + $type = $tables{$name} || 'Font::TTF::Table'; + $t = $type; + if ($^O eq "MacOS") + { $t =~ s/^|::/:/oig; } + else + { $t =~ s|::|/|oig; } + require "$t.pm"; + $self->{$name} = $type->new(PARENT => $self, + NAME => $name, + INFILE => $fh, + OFFSET => $off, + LENGTH => $len, + ZLENGTH => $zlen, + CSUM => $check); + } + + foreach $t ('head', 'maxp') + { $self->{$t}->read if defined $self->{$t}; } + + $self; +} + + +#line 481 + +sub out +{ + my ($self, $fname, @tlist) = @_; + my ($fh); + my ($dat, $numTables, $sRange, $eSel); + my (%dir, $k, $mloc, $count); + my ($csum, $lsum, $msum, $loc, $oldloc, $len, $shift); + + my ($iswoff); # , $woffLength, $sfntSize, $zlen); # needed for WOFF files + + unless (ref($fname)) + { + $fh = IO::File->new("+>$fname") || return warn("Unable to open $fname for writing"), undef; + binmode $fh; + } else + { $fh = $fname; } + + $self->{' oname'} = $fname; + $self->{' outfile'} = $fh; + + if ($self->{' wantsig'}) + { + $self->{' nocsum'} = 1; +# $self->{'head'}{'checkSumAdjustment'} = 0; + $self->{' tempDSIG'} = $self->{'DSIG'}; + $self->{' tempcsum'} = $self->{'head'}{' CSUM'}; + delete $self->{'DSIG'}; + @tlist = sort {$self->{$a}{' OFFSET'} <=> $self->{$b}{' OFFSET'}} + grep (length($_) == 4 && defined $self->{$_}, keys %$self) if ($#tlist < 0); + } + elsif ($#tlist < 0) + { @tlist = sort keys %$self; } + + @tlist = grep(length($_) == 4 && defined $self->{$_}, @tlist); + $numTables = $#tlist + 1; + $numTables++ if ($self->{' wantsig'}); + + if ($iswoff) + { + } + else + { + ($numTables, $sRange, $eSel, $shift) = Font::TTF::Utils::TTF_bininfo($numTables, 16); + $dat = pack("Nnnnn", 1 << 16, $numTables, $sRange, $eSel, $shift); + $fh->print($dat); + $msum = unpack("%32N*", $dat); + } + +# reserve place holders for each directory entry + foreach $k (@tlist) + { + $dir{$k} = pack("A4NNN", $k, 0, 0, 0); + $fh->print($dir{$k}); + } + + $fh->print(pack('A4NNN', '', 0, 0, 0)) if ($self->{' wantsig'}); + + $loc = $fh->tell(); + if ($loc & 3) + { + $fh->print(substr("\000" x 4, $loc & 3)); + $loc += 4 - ($loc & 3); + } + + foreach $k (@tlist) + { + $oldloc = $loc; + if ($iswoff && $havezlib && + # output font is WOFF -- should we try to compress this table? + exists ($self->{$k}->{' nocompress'}) ? $self->{$k}->{' nocompress'} != -1 : + ref($self->{' nocompress'}) eq 'ARRAY' ? !exists($self->{' nocompress'}{$k}) : + ref($self->{' nocompress'}) eq 'SCALAR' && $self->{' nocompress'} != -1) + { + # Yes -- we may want to compress this table. + # Create string file handle to hold uncompressed table + my $dat; + my $fh2 = IO::String->new($dat); + binmode $fh2; + $self->{$k}->out($fh2); + $len = $fh2->tell(); + close $fh2; + + # Is table long enough to try compression? + unless ( + exists ($self->{$k}->{' nocompress'}) && $len <= $self->{$k}->{' nocompress'} || + ref($self->{' nocompress'}) eq 'SCALAR' && $len <= $self->{' nocompress'}) + { + # Yes -- so compress and check lengths: + my $zdat = Compress::Zlib::compress($dat); + my $zlen = bytes::length($zdat); + if ($zlen < $len) + { + # write the compressed $zdat + + } + else + { + # write the uncompressed $dat + } + } + else + { + # write uncompressed $dat + } + + + } + else + { + # Output table normally + $self->{$k}->out($fh); + $loc = $fh->tell(); + $len = $loc - $oldloc; + } + if ($loc & 3) + { + $fh->print(substr("\000" x 4, $loc & 3)); + $loc += 4 - ($loc & 3); + } + $fh->seek($oldloc, 0); + $csum = 0; $mloc = $loc; + while ($mloc > $oldloc) + { + $count = ($mloc - $oldloc > 4096) ? 4096 : $mloc - $oldloc; + $fh->read($dat, $count); + $csum += unpack("%32N*", $dat); +# this line ensures $csum stays within 32 bit bounds, clipping as necessary + if ($csum > 0xffffffff) { $csum -= 0xffffffff; $csum--; } + $mloc -= $count; + } + $dir{$k} = pack("A4NNN", $k, $csum, $oldloc, $len); + $msum += $csum + unpack("%32N*", $dir{$k}); + while ($msum > 0xffffffff) { $msum -= 0xffffffff; $msum--; } + $fh->seek($loc, 0); + } + + unless ($self->{' nocsum'}) # assuming we want a file checksum + { +# Now we need to sort out the head table's checksum + if (!defined $dir{'head'}) + { # you have to have a head table + $fh->close(); + return warn("No 'head' table to output in $fname"), undef; + } + ($csum, $loc, $len) = unpack("x4NNN", $dir{'head'}); + $fh->seek($loc + 8, 0); + $fh->read($dat, 4); + $lsum = unpack("N", $dat); + if ($lsum != 0) + { + $csum -= $lsum; + if ($csum < 0) { $csum += 0xffffffff; $csum++; } + $msum -= $lsum * 2; # twice (in head and in csum) + while ($msum < 0) { $msum += 0xffffffff; $msum++; } + } + $lsum = 0xB1B0AFBA - $msum; + $fh->seek($loc + 8, 0); + $fh->print(pack("N", $lsum)); + $dir{'head'} = pack("A4NNN", 'head', $csum, $loc, $len); + } elsif ($self->{' wantsig'}) + { + if (!defined $dir{'head'}) + { # you have to have a head table + $fh->close(); + return warn("No 'head' table to output in $fname"), undef; + } + ($csum, $loc, $len) = unpack("x4NNN", $dir{'head'}); + $fh->seek($loc + 8, 0); + $fh->print(pack("N", 0)); +# $dir{'head'} = pack("A4NNN", 'head', $self->{' tempcsum'}, $loc, $len); + } + +# Now we can output the directory again + if ($self->{' wantsig'}) + { @tlist = sort @tlist; } + $fh->seek(12, 0); + foreach $k (@tlist) + { $fh->print($dir{$k}); } + $fh->print(pack('A4NNN', '', 0, 0, 0)) if ($self->{' wantsig'}); + $fh->close(); + $self; +} + + +#line 671 + +sub out_xml +{ + my ($self, $fname, @tlist) = @_; + my ($fh, $context, $numTables, $k); + + $context->{'indent'} = ' ' x 4; + + unless (ref($fname)) + { + $fh = IO::File->new("+>$fname") || return warn("Unable to open $fname"), undef; + binmode $fh; + } else + { $fh = $fname; } + + unless (scalar @tlist > 0) + { + @tlist = sort keys %$self; + @tlist = grep(length($_) == 4 && defined $self->{$_}, @tlist); + } + $numTables = $#tlist + 1; + + $context->{'fh'} = $fh; + $fh->print("\n"); + $fh->print("\n\n"); + + foreach $k (@tlist) + { + $fh->print("\n"); + $self->{$k}->out_xml($context, $context->{'indent'}); + $fh->print("
\n"); + } + + $fh->print("
\n"); + $fh->close; + $self; +} + + +#line 716 + +sub XML_start +{ + my ($self, $context, $tag, %attrs) = @_; + my ($name, $type, $t); + + if ($tag eq 'font') + { $context->{'tree'}[-1] = $self; } + elsif ($tag eq 'table') + { + $name = $attrs{'name'}; + unless (defined $self->{$name}) + { + $type = $tables{$name} || 'Font::TTF::Table'; + $t = $type; + if ($^O eq "MacOS") + { $t =~ s/^|::/:/oig; } + else + { $t =~ s|::|/|oig; } + require "$t.pm"; + $self->{$name} = $type->new('PARENT' => $self, 'NAME' => $name, 'read' => 1); + } + $context->{'receiver'} = ($context->{'tree'}[-1] = $self->{$name}); + } + $context; +} + + +sub XML_end +{ + my ($self) = @_; + my ($context, $tag, %attrs) = @_; + my ($i); + + return undef unless ($tag eq 'table' && $attrs{'name'} eq 'loca'); + if (defined $context->{'glyphs'} && $context->{'glyphs'} ne $self->{'loca'}{'glyphs'}) + { + for ($i = 0; $i <= $#{$context->{'glyphs'}}; $i++) + { $self->{'loca'}{'glyphs'}[$i] = $context->{'glyphs'}[$i] if defined $context->{'glyphs'}[$i]; } + $context->{'glyphs'} = $self->{'loca'}{'glyphs'}; + } + return undef; +} + +#line 766 + +sub update +{ + my ($self) = @_; + + $self->tables_do(sub { $_[0]->update; }); + + $self; +} + +#line 781 + +sub dirty +{ $_[0]->tables_do(sub { $_[0]->dirty; }); $_[0]; } + +#line 796 + +sub tables_do +{ + my ($self, $func, @tables) = @_; + my ($t); + + foreach $t (@tables ? @tables : sort grep {length($_) == 4} keys %$self) + { &$func($self->{$t}, $t); } + $self; +} + + +#line 830 + +sub release +{ + my ($self) = @_; + +# delete stuff that we know we can, here + + my @tofree = map { delete $self->{$_} } keys %{$self}; + + while (my $item = shift @tofree) + { + my $ref = ref($item); + if (UNIVERSAL::can($item, 'release')) + { $item->release(); } + elsif ($ref eq 'ARRAY') + { push( @tofree, @{$item} ); } + elsif (UNIVERSAL::isa($ref, 'HASH')) + { release($item); } + } + +# check that everything has gone - it better had! + foreach my $key (keys %{$self}) + { warn ref($self) . " still has '$key' key left after release.\n"; } +} + +1; + +#line 927 + diff --git a/lib/Font/TTF/Table.pm b/lib/Font/TTF/Table.pm new file mode 100644 index 0000000..b555759 --- /dev/null +++ b/lib/Font/TTF/Table.pm @@ -0,0 +1,303 @@ +#line 1 "Font/TTF/Table.pm" +#line 1 "Font/TTF/Table.pm" +package Font::TTF::Table; + +#line 63 + +use strict; +use vars qw($VERSION); +use Font::TTF::Utils; +use IO::String; +$VERSION = 0.0001; + +my $havezlib = eval {require Compress::Zlib}; + +#line 78 + +sub new +{ + my ($class, %parms) = @_; + my ($self) = {}; + my ($p); + + $class = ref($class) || $class; + foreach $p (keys %parms) + { $self->{" $p"} = $parms{$p}; } + bless $self, $class; +} + +#line 104 + +sub read +{ + my ($self) = @_; + + return $self->read_dat if (ref($self) eq "Font::TTF::Table"); + return undef if $self->{' read'}; + $self->{' INFILE'}->seek($self->{' OFFSET'}, 0); + if (0 < $self->{' ZLENGTH'} && $self->{' ZLENGTH'} < $self->{' LENGTH'}) + { + # WOFF table is compressed. Uncompress it to memory and create new fh + die ("Cannot uncompress WOFF data: Compress::Zlib not present.\n") unless $havezlib; + $self->{' ORIGINALOFFSET'} = $self->{' OFFSET'}; # Preserve this for those who care + my $dat; + $self->{' INFILE'}->read($dat, $self->{' ZLENGTH'}); + $dat = Compress::Zlib::uncompress($dat); + warn "$self->{' NAME'} table decompressed to wrong length" if $self->{' LENGTH'} != bytes::length($dat); + $self->{' INFILE'} = IO::String->new($dat); + binmode $self->{' INFILE'}; + $self->{' OFFSET'} = 0; + } + $self->{' read'} = 1; + $self; +} + + +#line 136 + +sub read_dat +{ + my ($self) = @_; + +# can't just $self->read here otherwise those tables which start their read sub with +# $self->read_dat are going to permanently loop + return undef if ($self->{' read'}); +# $self->{' read'} = 1; # Let read do this, now out will call us for subclasses + $self->{' INFILE'}->seek($self->{' OFFSET'}, 0); + if (0 < $self->{' ZLENGTH'} && $self->{' ZLENGTH'} < $self->{' LENGTH'}) + { + # WOFF table is compressed. Uncompress it directly to ' dat' + die ("Cannot uncompress WOFF data: Compress::Zlib not present.\n") unless $havezlib; + my $dat; + $self->{' INFILE'}->read($dat, $self->{' ZLENGTH'}); + $dat = Compress::Zlib::uncompress($dat); + warn "$self->{' NAME'} table decompressed to wrong length" if $self->{' LENGTH'} != bytes::length($dat); + $self->{' dat'} = $dat; + } + else + { + $self->{' INFILE'}->read($self->{' dat'}, $self->{' LENGTH'}); + } + $self; +} + +#line 170 + +sub out +{ + my ($self, $fh) = @_; + my ($dat, $i, $len, $count); + + if (defined $self->{' dat'}) + { + $fh->print($self->{' dat'}); + return $self; + } + + return undef unless defined $self->{' INFILE'}; + + if (0 < $self->{' ZLENGTH'} && $self->{' ZLENGTH'} < $self->{' LENGTH'}) + { + # WOFF table is compressed. Have to uncompress first + $self->read_dat; + $fh->print($self->{' dat'}); + return $self; + } + + # We don't really have to keep the following code... we could have + # just always done a full read_dat() on the table. But the following + # is more memory-friendly so I've kept it for the more common case + # of non-compressed tables. + + $self->{' INFILE'}->seek($self->{' OFFSET'}, 0); + $len = $self->{' LENGTH'}; + while ($len > 0) + { + $count = ($len > 4096) ? 4096 : $len; + $self->{' INFILE'}->read($dat, $count); + $fh->print($dat); + $len -= $count; + } + $self; +} + + +#line 216 + +sub out_xml +{ + my ($self, $context, $depth) = @_; + my ($k); + + if (ref($self) eq __PACKAGE__) + { + $self->read_dat; + Font::TTF::Utils::XML_hexdump($context, $depth, $self->{' dat'}); + } + else + { + $self->read; + foreach $k (sort grep {$_ !~ m/^\s/o} keys %{$self}) + { + $self->XML_element($context, $depth, $k, $self->{$k}); + } + } + $self; +} + + +#line 244 + +sub XML_element +{ + my ($self, $context, $depth, $k, $dat, $ind) = @_; + my ($fh) = $context->{'fh'}; + my ($ndepth, $d); + + return unless defined $dat; + + if (!ref($dat)) + { + $fh->printf("%s<%s>%s\n", $depth, $k, $dat, $k); + return $self; + } + + if ($ind) + { $fh->printf("%s<%s i='%d'>\n", $depth, $k, $ind); } + else + { $fh->printf("%s<%s>\n", $depth, $k); } + $ndepth = $depth . $context->{'indent'}; + + if (ref($dat) eq 'SCALAR') + { $self->XML_element($context, $ndepth, 'scalar', $$dat); } + elsif (ref($dat) eq 'ARRAY') + { + my ($c) = 1; + foreach $d (@{$dat}) + { $self->XML_element($context, $ndepth, 'elem', $d, $c++); } + } + elsif (ref($dat) eq 'HASH') + { + foreach $d (sort grep {$_ !~ m/^\s/o} keys %{$dat}) + { $self->XML_element($context, $ndepth, $d, $dat->{$d}); } + } + else + { + $context->{'name'} = ref($dat); + $context->{'name'} =~ s/^.*://o; + $dat->out_xml($context, $ndepth); + } + + $fh->printf("%s\n", $depth, $k); + $self; +} + + +#line 295 + +sub XML_end +{ + my ($self, $context, $tag, %attrs) = @_; + my ($dat, $addr); + + return undef unless ($tag eq 'data'); + $dat = $context->{'text'}; + $dat =~ s/([0-9a-f]{2})\s*/hex($1)/oig; + if (defined $attrs{'addr'}) + { $addr = hex($attrs{'addr'}); } + else + { $addr = length($self->{' dat'}); } + substr($self->{' dat'}, $addr, length($dat)) = $dat; + return $context; +} + + +#line 319 + +sub minsize +{ + return 0; +} + +#line 331 + +sub dirty +{ + my ($self, $val) = @_; + my ($res) = $self->{' isDirty'}; + + $self->{' isDirty'} = defined $val ? $val : 1; + $res; +} + +#line 353 + +sub update +{ + my ($self) = @_; + + if ($self->{' isDirty'}) + { + $self->read; + $self->{' isDirty'} = 0; + return $self; + } + else + { return undef; } +} + + +#line 374 + +sub empty +{ + my ($self) = @_; + my (%keep); + + foreach (qw(INFILE LENGTH OFFSET CSUM PARENT)) + { $keep{" $_"} = 1; } + + map {delete $self->{$_} unless $keep{$_}} keys %$self; + $self; +} + + +#line 409 + +sub release +{ + my ($self) = @_; + +# delete stuff that we know we can, here + + my @tofree = map { delete $self->{$_} } keys %{$self}; + + while (my $item = shift @tofree) + { + my $ref = ref($item); + if (UNIVERSAL::can($item, 'release')) + { $item->release(); } + elsif ($ref eq 'ARRAY') + { push( @tofree, @{$item} ); } + elsif (UNIVERSAL::isa($ref, 'HASH')) + { release($item); } + } + +# check that everything has gone - it better had! + foreach my $key (keys %{$self}) + { warn ref($self) . " still has '$key' key left after release.\n"; } +} + + +sub __dumpvar__ +{ + my ($self, $key) = @_; + + return ($key eq ' PARENT' ? '...parent...' : $self->{$key}); +} + +1; + +#line 463 + + diff --git a/lib/Font/TTF/Utils.pm b/lib/Font/TTF/Utils.pm new file mode 100644 index 0000000..f2d0f93 --- /dev/null +++ b/lib/Font/TTF/Utils.pm @@ -0,0 +1,495 @@ +#line 1 "Font/TTF/Utils.pm" +#line 1 "Font/TTF/Utils.pm" +package Font::TTF::Utils; + +#line 16 + +use strict; +use vars qw(@ISA @EXPORT $VERSION @EXPORT_OK); +require Exporter; + +@ISA = qw(Exporter); +@EXPORT = qw(TTF_Init_Fields TTF_Read_Fields TTF_Out_Fields TTF_Pack + TTF_Unpack TTF_word_utf8 TTF_utf8_word TTF_bininfo); +@EXPORT_OK = (@EXPORT, qw(XML_hexdump)); +$VERSION = 0.0001; + +#line 33 + +sub TTF_Init_Fields +{ + my ($str, $pos, $inval) = @_; + my ($key, $val, $res, $len, $rel); + + $str =~ s/\r?\n$//o; + if ($inval) + { ($key, $val) = ($str, $inval); } + else + { ($key, $val) = split(',\s*', $str); } + return (undef, undef, 0) unless (defined $key && $key ne ""); + if ($val =~ m/^(\+?)(\d*)(\D+)(\d*)/oi) + { + $rel = $1; + if ($rel eq "+") + { $pos += $2; } + elsif ($2 ne "") + { $pos = $2; } + $val = $3; + $len = $4; + } + $len = "" unless defined $len; + $pos = 0 if !defined $pos || $pos eq ""; + $res = "$pos:$val:$len"; + if ($val eq "f" || $val eq 'v' || $val =~ m/^[l]/oi) + { $pos += 4 * ($len ne "" ? $len : 1); } + elsif ($val eq "F" || $val =~ m/^[s]/oi) + { $pos += 2 * ($len ne "" ? $len : 1); } + else + { $pos += 1 * ($len ne "" ? $len : 1); } + + ($key, $res, $pos); +} + + +#line 77 + +sub TTF_Read_Fields +{ + my ($self, $dat, $fields) = @_; + my ($pos, $type, $res, $f, $arrlen, $arr, $frac); + + foreach $f (keys %{$fields}) + { + ($pos, $type, $arrlen) = split(':', $fields->{$f}); + $pos = 0 if $pos eq ""; + if ($arrlen ne "") + { $self->{$f} = [TTF_Unpack("$type$arrlen", substr($dat, $pos))]; } + else + { $self->{$f} = TTF_Unpack("$type", substr($dat, $pos)); } + } + $self; +} + + +#line 117 + +sub TTF_Unpack +{ + my ($fmt, $dat) = @_; + my ($res, $frac, $i, $arrlen, $type, @res); + + while ($fmt =~ s/^([cflsv])(\d+|\*)?//oi) + { + $type = $1; + $arrlen = $2; + $arrlen = 1 if !defined $arrlen || $arrlen eq ""; + $arrlen = -1 if $arrlen eq "*"; + + for ($i = 0; ($arrlen == -1 && $dat ne "") || $i < $arrlen; $i++) + { + if ($type eq "f") + { + ($res, $frac) = unpack("nn", $dat); + substr($dat, 0, 4) = ""; + $res -= 65536 if $res > 32767; + $res += $frac / 65536.; + } + elsif ($type eq "v") + { + ($res, $frac) = unpack("nn", $dat); + substr($dat, 0, 4) = ""; + $res = sprintf("%d.%04X", $res, $frac); + } + elsif ($type eq "F") + { + $res = unpack("n", $dat); + substr($dat, 0, 2) = ""; +# $res -= 65536 if $res >= 32768; + $frac = $res & 0x3fff; + $res >>= 14; + $res -= 4 if $res > 1; +# $frac -= 16384 if $frac > 8191; + $res += $frac / 16384.; + } + elsif ($type =~ m/^[l]/oi) + { + $res = unpack("N", $dat); + substr($dat, 0, 4) = ""; + $res -= (1 << 32) if ($type eq "l" && $res >= 1 << 31); + } + elsif ($type =~ m/^[s]/oi) + { + $res = unpack("n", $dat); + substr($dat, 0, 2) = ""; + $res -= 65536 if ($type eq "s" && $res >= 32768); + } + elsif ($type eq "c") + { + $res = unpack("c", $dat); + substr($dat, 0, 1) = ""; + } + else + { + $res = unpack("C", $dat); + substr($dat, 0, 1) = ""; + } + push (@res, $res); + } + } + return wantarray ? @res : $res[0]; +} + + +#line 191 + +sub TTF_Out_Fields +{ + my ($obj, $fields, $len) = @_; + my ($dat) = "\000" x $len; + my ($f, $pos, $type, $res, $arr, $arrlen, $frac); + + foreach $f (keys %{$fields}) + { + ($pos, $type, $arrlen) = split(':', $fields->{$f}); + if ($arrlen ne "") + { $res = TTF_Pack("$type$arrlen", @{$obj->{$f}}); } + else + { $res = TTF_Pack("$type", $obj->{$f}); } + substr($dat, $pos, length($res)) = $res; + } + $dat; +} + + +#line 217 + +sub TTF_Pack +{ + my ($fmt, @obj) = @_; + my ($type, $i, $arrlen, $dat, $res, $frac); + + $dat = ''; + while ($fmt =~ s/^([flscv])(\d+|\*)?//oi) + { + $type = $1; + $arrlen = $2 || ""; + $arrlen = $#obj + 1 if $arrlen eq "*"; + $arrlen = 1 if $arrlen eq ""; + + for ($i = 0; $i < $arrlen; $i++) + { + $res = shift(@obj) || 0; + if ($type eq "f") + { + $frac = int(($res - int($res)) * 65536); + $res = (int($res) << 16) + $frac; + $dat .= pack("N", $res); + } + elsif ($type eq "v") + { + if ($res =~ s/\.([0-9a-f]+)$//oi) + { + $frac = $1; + $frac .= "0" x (4 - length($frac)); + } + else + { $frac = 0; } + $dat .= pack('nn', $res, hex($frac)); + } + elsif ($type eq "F") + { + $frac = int(($res - int($res)) * 16384); + $res = (int($res) << 14) + $frac; + $dat .= pack("n", $res); + } + elsif ($type =~ m/^[l]/oi) + { + $res += 1 << 32 if ($type eq 'L' && $res < 0); + $dat .= pack("N", $res); + } + elsif ($type =~ m/^[s]/oi) + { + $res += 1 << 16 if ($type eq 'S' && $res < 0); + $dat .= pack("n", $res); + } + elsif ($type eq "c") + { $dat .= pack("c", $res); } + else + { $dat .= pack("C", $res); } + } + } + $dat; +} + + +#line 282 + +sub TTF_bininfo +{ + my ($num, $block) = @_; + my ($range, $select, $shift); + + $range = 1; + for ($select = 0; $range <= $num; $select++) + { $range *= 2; } + $select--; $range /= 2; + $range *= $block; + + $shift = $num * $block - $range; + ($num, $range, $select, $shift); +} + + +#line 305 + +sub TTF_word_utf8 +{ + my ($str) = @_; + my ($res, $i); + my (@dat) = unpack("n*", $str); + + return pack("U*", @dat) if ($] >= 5.006); + for ($i = 0; $i <= $#dat; $i++) + { + my ($dat) = $dat[$i]; + if ($dat < 0x80) # Thanks to Gisle Aas for some of his old code + { $res .= chr($dat); } + elsif ($dat < 0x800) + { $res .= chr(0xC0 | ($dat >> 6)) . chr(0x80 | ($dat & 0x3F)); } + elsif ($dat >= 0xD800 && $dat < 0xDC00) + { + my ($dat1) = $dat[++$i]; + my ($top) = (($dat & 0x3C0) >> 6) + 1; + $res .= chr(0xF0 | ($top >> 2)) + . chr(0x80 | (($top & 1) << 4) | (($dat & 0x3C) >> 2)) + . chr(0x80 | (($dat & 0x3) << 4) | (($dat1 & 0x3C0) >> 6)) + . chr(0x80 | ($dat1 & 0x3F)); + } else + { $res .= chr(0xE0 | ($dat >> 12)) . chr(0x80 | (($dat >> 6) & 0x3F)) + . chr(0x80 | ($dat & 0x3F)); } + } + $res; +} + + +#line 342 + +sub TTF_utf8_word +{ + my ($str) = @_; + my ($res); + + return pack("n*", unpack("U*", $str)) if ($^V ge v5.6.0); + $str = "$str"; # copy $str + while (length($str)) # Thanks to Gisle Aas for some of his old code + { + $str =~ s/^[\x80-\xBF]+//o; + if ($str =~ s/^([\x00-\x7F]+)//o) + { $res .= pack("n*", unpack("C*", $1)); } + elsif ($str =~ s/^([\xC0-\xDF])([\x80-\xBF])//o) + { $res .= pack("n", ((ord($1) & 0x1F) << 6) | (ord($2) & 0x3F)); } + elsif ($str =~ s/^([\0xE0-\xEF])([\x80-\xBF])([\x80-\xBF])//o) + { $res .= pack("n", ((ord($1) & 0x0F) << 12) + | ((ord($2) & 0x3F) << 6) + | (ord($3) & 0x3F)); } + elsif ($str =~ s/^([\xF0-\xF7])([\x80-\xBF])([\x80-\xBF])([\x80-\xBF])//o) + { + my ($b1, $b2, $b3, $b4) = (ord($1), ord($2), ord($3), ord($4)); + $res .= pack("n", ((($b1 & 0x07) << 8) | (($b2 & 0x3F) << 2) + | (($b3 & 0x30) >> 4)) + 0xD600); # account for offset + $res .= pack("n", ((($b3 & 0x0F) << 6) | ($b4 & 0x3F)) + 0xDC00); + } + elsif ($str =~ s/^[\xF8-\xFF][\x80-\xBF]*//o) + { } + } + $res; +} + + +#line 380 + +sub XML_hexdump +{ + my ($context, $depth, $dat) = @_; + my ($fh) = $context->{'fh'}; + my ($i, $len, $out); + + $len = length($dat); + for ($i = 0; $i < $len; $i += 16) + { + $out = join(' ', map {sprintf("%02X", ord($_))} (split('', substr($dat, $i, 16)))); + $fh->printf("%s%s\n", $depth, $i, $out); + } +} + + +#line 401 + +{ + my (@hints) = ( + ['SVTCA[0]'], ['SVTCA[1]'], ['SPVTCA[0]'], ['SPVTCA[1]'], ['SFVTCA[0]'], ['SFVTCA[1]'], ['SPVTL[0]'], ['SPVTL[1]'], + ['SFVTL[0]'], ['SFVTL[1]'], ['SPVFS'], ['SFVFS'], ['GPV'], ['GFV'], ['SVFTPV'], ['ISECT'], +# 10 + ['SRP0'], ['SRP1'], ['SRP2'], ['SZP0'], ['SZP1'], ['SZP2'], ['SZPS'], ['SLOOP'], + ['RTG'], ['RTHG'], ['SMD'], ['ELSE'], ['JMPR'], ['SCVTCI'], ['SSWCI'], ['SSW'], +# 20 + ['DUP'], ['POP'], ['CLEAR'], ['SWAP'], ['DEPTH'], ['CINDEX'], ['MINDEX'], ['ALIGNPTS'], + [], ['UTP'], ['LOOPCALL'], ['CALL'], ['FDEF'], ['ENDF'], ['MDAP[0]'], ['MDAP[1]'], +# 30 + ['IUP[0]'], ['IUP[1]'], ['SHP[0]'], ['SHP[1]'], ['SHC[0]'], ['SHC[1]'], ['SHZ[0]'], ['SHZ[1]'], + ['SHPIX'], ['IP'], ['MSIRP[0]'], ['MSIRP[1]'], ['ALIGNRP'], ['RTDG'], ['MIAP[0]'], ['MIAP[1]'], +# 40 + ['NPUSHB', -1, 1], ['NPUSHW', -1, 2], ['WS', 0, 0], ['RS', 0, 0], ['WCVTP', 0, 0], ['RCVT', 0, 0], ['GC[0]'], ['GC[1]'], + ['SCFS'], ['MD[0]'], ['MD[1]'], ['MPPEM'], ['MPS'], ['FLIPON'], ['FLIPOFF'], ['DEBUG'], +# 50 + ['LT'], ['LTEQ'], ['GT'], ['GTEQ'], ['EQ'], ['NEQ'], ['ODD'], ['EVEN'], + ['IF'], ['EIF'], ['AND'], ['OR'], ['NOT'], ['DELTAP1'], ['SDB'], ['SDS'], +# 60 + ['ADD'], ['SUB'], ['DIV'], ['MULT'], ['ABS'], ['NEG'], ['FLOOR'], ['CEILING'], + ['ROUND[0]'], ['ROUND[1]'], ['ROUND[2]'], ['ROUND[3]'], ['NROUND[0]'], ['NROUND[1]'], ['NROUND[2]'], ['NROUND[3]'], +# 70 + ['WCVTF'], ['DELTAP2'], ['DELTAP3'], ['DELTAC1'], ['DELTAC2'], ['DELTAC3'], ['SROUND'], ['S45ROUND'], + ['JROT'], ['JROF'], ['ROFF'], [], ['RUTG'], ['RDTG'], ['SANGW'], [], +# 80 + ['FLIPPT'], ['FLIPRGON'], ['FLIPRGOFF'], [], [], ['SCANCTRL'], ['SDPVTL[0]'], ['SDPVTL[1]'], + ['GETINFO'], ['IDEF'], ['ROLL'], ['MAX'], ['MIN'], ['SCANTYPE'], ['INSTCTRL'], [], +# 90 + [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], +# A0 + [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], +# B0 + ['PUSHB1', 1, 1], ['PUSHB2', 2, 1], ['PUSHB3', 3, 1], ['PUSHB4', 4, 1], ['PUSHB5', 5, 1], ['PUSHB6', 6, 1], ['PUSHB7', 7, 1], ['PUSHB8', 8, 1], + ['PUSHW1', 1, 2], ['PUSHW2', 2, 2], ['PUSHW3', 3, 2], ['PUSHW4', 4, 2], ['PUSHW5', 5, 2], ['PUSHW6', 6, 2], ['PUSHW7', 7, 2], ['PUSHW8', 8, 2], +# C0 + ['MDRP[0]'], ['MDRP[1]'], ['MDRP[2]'], ['MDRP[3]'], ['MDRP[4]'], ['MDRP[5]'], ['MDRP[6]'], ['MDRP[7]'], + ['MDRP[8]'], ['MDRP[9]'], ['MDRP[A]'], ['MDRP[B]'], ['MDRP[C]'], ['MDRP[D]'], ['MDRP[E]'], ['MDRP[F]'], +# D0 + ['MDRP[10]'], ['MDRP[11]'], ['MDRP[12]'], ['MDRP[13]'], ['MDRP[14]'], ['MDRP[15]'], ['MDRP[16]'], ['MDRP[17]'], + ['MDRP[18]'], ['MDRP[19]'], ['MDRP[1A]'], ['MDRP[1B]'], ['MDRP[1C]'], ['MDRP[1D]'], ['MDRP[1E]'], ['MDRP[1F]'], +# E0 + ['MIRP[0]'], ['MIRP[1]'], ['MIRP[2]'], ['MIRP[3]'], ['MIRP[4]'], ['MIRP[5]'], ['MIRP[6]'], ['MIRP[7]'], + ['MIRP[8]'], ['MIRP[9]'], ['MIRP[A]'], ['MIRP[B]'], ['MIRP[C]'], ['MIRP[D]'], ['MIRP[E]'], ['MIRP[F]'], +# F0 + ['MIRP[10]'], ['MIRP[11]'], ['MIRP[12]'], ['MIRP[13]'], ['MIRP[14]'], ['MIRP[15]'], ['MIRP[16]'], ['MIRP[17]'], + ['MIRP[18]'], ['MIRP[19]'], ['MIRP[1A]'], ['MIRP[1B]'], ['MIRP[1C]'], ['MIRP[1D]'], ['MIRP[1E]'], ['MIRP[1F]']); + + my ($i); + my (%hints) = map { $_->[0] => $i++ if (defined $_->[0]); } @hints; + + sub XML_binhint + { + my ($dat) = @_; + my ($len) = length($dat); + my ($res, $i, $text, $size, $num); + + for ($i = 0; $i < $len; $i++) + { + ($text, $num, $size) = @{$hints[ord(substr($dat, $i, 1))]}; + $num = 0 unless (defined $num); + $text = sprintf("UNK[%02X]", ord(substr($dat, $i, 1))) unless defined $text; + $res .= $text; + if ($num != 0) + { + if ($num < 0) + { + $i++; + my ($nnum) = unpack($num == -1 ? 'C' : 'n', substr($dat, $i, -$num)); + $i += -$num - 1; + $num = $nnum; + } + $res .= "\t" . join(' ', unpack($size == 1 ? 'C*' : 'n*', substr($dat, $i + 1, $num * $size))); + $i += $num * $size; + } + $res .= "\n"; + } + $res; + } + + sub XML_hintbin + { + my ($dat) = @_; + my ($l, $res, @words, $num); + + foreach $l (split(/\s*\n\s*/, $dat)) + { + @words = split(/\s*/, $l); + next unless (defined $hints{$words[0]}); + $num = $hints{$words[0]}; + $res .= pack('C', $num); + if ($hints[$num][1] < 0) + { + $res .= pack($hints[$num][1] == -1 ? 'C' : 'n', $#words); + $res .= pack($hints[$num][2] == 1 ? 'C*' : 'n*', @words[1 .. $#words]); + } + elsif ($hints[$num][1] > 0) + { + $res .= pack($hints[$num][2] == 1 ? 'C*' : 'n*', @words[1 .. $hints[$num][1]]); + } + } + $res; + } +} + + +#line 561 + +sub make_circle +{ + my ($font, $cmap, $dia, $sb, %opts) = @_; + my ($upem) = $font->{'head'}{'unitsPerEm'}; + my ($glyph) = Font::TTF::Glyph->new('PARENT' => $font, 'read' => 2, 'isDirty' => 1); + my ($PI) = 3.1415926535; + my ($R, $r, $xorg, $yorg); + my ($i, $j, $numg, $maxp); + my ($numc) = $opts{'-numDots'} || 16; + my ($nump) = ($opts{'-numPoints'} * 2) || 8; + my ($uid) = $opts{'-uid'} || 0x25CC; + my ($pname) = $opts{'-pname'} || 'uni25CC'; + + $dia ||= $upem * .8; # .95 to fit exactly + $sb ||= $upem * .1; + $R = $dia / 2; + $r = $opts{'-dRadius'} || ($R * .1); + ($xorg, $yorg) = ($R + $r, $R); + + $xorg += $sb; + $font->{'post'}->read; + $font->{'glyf'}->read; + for ($i = 0; $i < $numc; $i++) + { + my ($pxorg, $pyorg) = ($xorg + $R * cos(2 * $PI * $i / $numc), + $yorg + $R * sin(2 * $PI * $i / $numc)); + for ($j = 0; $j < $nump; $j++) + { + push (@{$glyph->{'x'}}, int ($pxorg + ($j & 1 ? 1/cos(2*$PI/$nump) : 1) * $r * cos(2 * $PI * $j / $nump))); + push (@{$glyph->{'y'}}, int ($pyorg + ($j & 1 ? 1/cos(2*$PI/$nump) : 1) * $r * sin(2 * $PI * $j / $nump))); + push (@{$glyph->{'flags'}}, $j & 1 ? 0 : 1); + } + push (@{$glyph->{'endPoints'}}, $#{$glyph->{'x'}}); + } + $glyph->{'numberOfContours'} = $#{$glyph->{'endPoints'}} + 1; + $glyph->{'numPoints'} = $#{$glyph->{'x'}} + 1; + $glyph->update; + $numg = $font->{'maxp'}{'numGlyphs'}; + $font->{'maxp'}{'numGlyphs'}++; + + $font->{'hmtx'}{'advance'}[$numg] = int($xorg + $R + $r + $sb + .5); + $font->{'hmtx'}{'lsb'}[$numg] = int($xorg - $R - $r + .5); + $font->{'loca'}{'glyphs'}[$numg] = $glyph; + $cmap->{'val'}{$uid} = $numg if ($cmap); + $font->{'post'}{'VAL'}[$numg] = $pname; + delete $font->{'hdmx'}; + delete $font->{'VDMX'}; + delete $font->{'LTSH'}; + + $font->tables_do(sub {$_[0]->dirty;}); + $font->update; + return ($numg - 1); +} + + +1; + +#line 638 + + diff --git a/lib/Font/TTF/Woff.pm b/lib/Font/TTF/Woff.pm new file mode 100644 index 0000000..52bace5 --- /dev/null +++ b/lib/Font/TTF/Woff.pm @@ -0,0 +1,16 @@ +#line 1 "Font/TTF/Woff.pm" +#line 1 "Font/TTF/Woff.pm" +package Font::TTF::Woff; + +#line 37 + +use strict; +use vars qw(@ISA %fields @field_info); + +require Font::TTF::Table; + +@ISA = qw(Font::TTF::Table); + +1; + +#line 61 \ No newline at end of file diff --git a/lib/Font/TTF/Woff/MetaData.pm b/lib/Font/TTF/Woff/MetaData.pm new file mode 100644 index 0000000..60fd3ac --- /dev/null +++ b/lib/Font/TTF/Woff/MetaData.pm @@ -0,0 +1,14 @@ +#line 1 "Font/TTF/Woff/MetaData.pm" +#line 1 "Font/TTF/Woff/MetaData.pm" +package Font::TTF::Woff::MetaData; + +#line 12 + +use Font::TTF::Utils; +require Font::TTF::Table; + +@ISA = qw(Font::TTF::Table); + +1; + +#line 32 diff --git a/lib/Font/TTF/Woff/PrivateData.pm b/lib/Font/TTF/Woff/PrivateData.pm new file mode 100644 index 0000000..aae8a3b --- /dev/null +++ b/lib/Font/TTF/Woff/PrivateData.pm @@ -0,0 +1,15 @@ +#line 1 "Font/TTF/Woff/PrivateData.pm" +#line 1 "Font/TTF/Woff/PrivateData.pm" +package Font::TTF::Woff::PrivateData; + +#line 12 + +use Font::TTF::Utils; +require Font::TTF::Table; + +@ISA = qw(Font::TTF::Table); + +1; + +#line 32 + diff --git a/lib/HTML/Entities.pm b/lib/HTML/Entities.pm index 297fc33..435f136 100644 --- a/lib/HTML/Entities.pm +++ b/lib/HTML/Entities.pm @@ -1,4 +1,6 @@ #line 1 "HTML/Entities.pm" +#line 1 "HTML/Entities.pm" +#line 1 "HTML/Entities.pm" package HTML::Entities; diff --git a/lib/HTML/Parser.pm b/lib/HTML/Parser.pm index f216ed9..248e8a9 100644 --- a/lib/HTML/Parser.pm +++ b/lib/HTML/Parser.pm @@ -1,4 +1,6 @@ #line 1 "HTML/Parser.pm" +#line 1 "HTML/Parser.pm" +#line 1 "HTML/Parser.pm" package HTML::Parser; use strict; diff --git a/lib/IO/String.pm b/lib/IO/String.pm new file mode 100644 index 0000000..da5a4b0 --- /dev/null +++ b/lib/IO/String.pm @@ -0,0 +1,427 @@ +#line 1 "IO/String.pm" +#line 1 "IO/String.pm" +package IO::String; + +# Copyright 1998-2005 Gisle Aas. +# +# This library is free software; you can redistribute it and/or +# modify it under the same terms as Perl itself. + +require 5.005_03; +use strict; +use vars qw($VERSION $DEBUG $IO_CONSTANTS); +$VERSION = "1.08"; # $Date: 2005/12/05 12:00:47 $ + +use Symbol (); + +sub new +{ + my $class = shift; + my $self = bless Symbol::gensym(), ref($class) || $class; + tie *$self, $self; + $self->open(@_); + return $self; +} + +sub open +{ + my $self = shift; + return $self->new(@_) unless ref($self); + + if (@_) { + my $bufref = ref($_[0]) ? $_[0] : \$_[0]; + $$bufref = "" unless defined $$bufref; + *$self->{buf} = $bufref; + } + else { + my $buf = ""; + *$self->{buf} = \$buf; + } + *$self->{pos} = 0; + *$self->{lno} = 0; + return $self; +} + +sub pad +{ + my $self = shift; + my $old = *$self->{pad}; + *$self->{pad} = substr($_[0], 0, 1) if @_; + return "\0" unless defined($old) && length($old); + return $old; +} + +sub dump +{ + require Data::Dumper; + my $self = shift; + print Data::Dumper->Dump([$self], ['*self']); + print Data::Dumper->Dump([*$self{HASH}], ['$self{HASH}']); + return; +} + +sub TIEHANDLE +{ + print "TIEHANDLE @_\n" if $DEBUG; + return $_[0] if ref($_[0]); + my $class = shift; + my $self = bless Symbol::gensym(), $class; + $self->open(@_); + return $self; +} + +sub DESTROY +{ + print "DESTROY @_\n" if $DEBUG; +} + +sub close +{ + my $self = shift; + delete *$self->{buf}; + delete *$self->{pos}; + delete *$self->{lno}; + undef *$self if $] eq "5.008"; # workaround for some bug + return 1; +} + +sub opened +{ + my $self = shift; + return defined *$self->{buf}; +} + +sub binmode +{ + my $self = shift; + return 1 unless @_; + # XXX don't know much about layers yet :-( + return 0; +} + +sub getc +{ + my $self = shift; + my $buf; + return $buf if $self->read($buf, 1); + return undef; +} + +sub ungetc +{ + my $self = shift; + $self->setpos($self->getpos() - 1); + return 1; +} + +sub eof +{ + my $self = shift; + return length(${*$self->{buf}}) <= *$self->{pos}; +} + +sub print +{ + my $self = shift; + if (defined $\) { + if (defined $,) { + $self->write(join($,, @_).$\); + } + else { + $self->write(join("",@_).$\); + } + } + else { + if (defined $,) { + $self->write(join($,, @_)); + } + else { + $self->write(join("",@_)); + } + } + return 1; +} +*printflush = \*print; + +sub printf +{ + my $self = shift; + print "PRINTF(@_)\n" if $DEBUG; + my $fmt = shift; + $self->write(sprintf($fmt, @_)); + return 1; +} + + +my($SEEK_SET, $SEEK_CUR, $SEEK_END); + +sub _init_seek_constants +{ + if ($IO_CONSTANTS) { + require IO::Handle; + $SEEK_SET = &IO::Handle::SEEK_SET; + $SEEK_CUR = &IO::Handle::SEEK_CUR; + $SEEK_END = &IO::Handle::SEEK_END; + } + else { + $SEEK_SET = 0; + $SEEK_CUR = 1; + $SEEK_END = 2; + } +} + + +sub seek +{ + my($self,$off,$whence) = @_; + my $buf = *$self->{buf} || return 0; + my $len = length($$buf); + my $pos = *$self->{pos}; + + _init_seek_constants() unless defined $SEEK_SET; + + if ($whence == $SEEK_SET) { $pos = $off } + elsif ($whence == $SEEK_CUR) { $pos += $off } + elsif ($whence == $SEEK_END) { $pos = $len + $off } + else { die "Bad whence ($whence)" } + print "SEEK(POS=$pos,OFF=$off,LEN=$len)\n" if $DEBUG; + + $pos = 0 if $pos < 0; + $self->truncate($pos) if $pos > $len; # extend file + *$self->{pos} = $pos; + return 1; +} + +sub pos +{ + my $self = shift; + my $old = *$self->{pos}; + if (@_) { + my $pos = shift || 0; + my $buf = *$self->{buf}; + my $len = $buf ? length($$buf) : 0; + $pos = $len if $pos > $len; + *$self->{pos} = $pos; + } + return $old; +} + +sub getpos { shift->pos; } + +*sysseek = \&seek; +*setpos = \&pos; +*tell = \&getpos; + + + +sub getline +{ + my $self = shift; + my $buf = *$self->{buf} || return; + my $len = length($$buf); + my $pos = *$self->{pos}; + return if $pos >= $len; + + unless (defined $/) { # slurp + *$self->{pos} = $len; + return substr($$buf, $pos); + } + + unless (length $/) { # paragraph mode + # XXX slow&lazy implementation using getc() + my $para = ""; + my $eol = 0; + my $c; + while (defined($c = $self->getc)) { + if ($c eq "\n") { + $eol++; + next if $eol > 2; + } + elsif ($eol > 1) { + $self->ungetc($c); + last; + } + else { + $eol = 0; + } + $para .= $c; + } + return $para; # XXX wantarray + } + + my $idx = index($$buf,$/,$pos); + if ($idx < 0) { + # return rest of it + *$self->{pos} = $len; + $. = ++ *$self->{lno}; + return substr($$buf, $pos); + } + $len = $idx - $pos + length($/); + *$self->{pos} += $len; + $. = ++ *$self->{lno}; + return substr($$buf, $pos, $len); +} + +sub getlines +{ + die "getlines() called in scalar context\n" unless wantarray; + my $self = shift; + my($line, @lines); + push(@lines, $line) while defined($line = $self->getline); + return @lines; +} + +sub READLINE +{ + goto &getlines if wantarray; + goto &getline; +} + +sub input_line_number +{ + my $self = shift; + my $old = *$self->{lno}; + *$self->{lno} = shift if @_; + return $old; +} + +sub truncate +{ + my $self = shift; + my $len = shift || 0; + my $buf = *$self->{buf}; + if (length($$buf) >= $len) { + substr($$buf, $len) = ''; + *$self->{pos} = $len if $len < *$self->{pos}; + } + else { + $$buf .= ($self->pad x ($len - length($$buf))); + } + return 1; +} + +sub read +{ + my $self = shift; + my $buf = *$self->{buf}; + return undef unless $buf; + + my $pos = *$self->{pos}; + my $rem = length($$buf) - $pos; + my $len = $_[1]; + $len = $rem if $len > $rem; + return undef if $len < 0; + if (@_ > 2) { # read offset + substr($_[0],$_[2]) = substr($$buf, $pos, $len); + } + else { + $_[0] = substr($$buf, $pos, $len); + } + *$self->{pos} += $len; + return $len; +} + +sub write +{ + my $self = shift; + my $buf = *$self->{buf}; + return unless $buf; + + my $pos = *$self->{pos}; + my $slen = length($_[0]); + my $len = $slen; + my $off = 0; + if (@_ > 1) { + $len = $_[1] if $_[1] < $len; + if (@_ > 2) { + $off = $_[2] || 0; + die "Offset outside string" if $off > $slen; + if ($off < 0) { + $off += $slen; + die "Offset outside string" if $off < 0; + } + my $rem = $slen - $off; + $len = $rem if $rem < $len; + } + } + substr($$buf, $pos, $len) = substr($_[0], $off, $len); + *$self->{pos} += $len; + return $len; +} + +*sysread = \&read; +*syswrite = \&write; + +sub stat +{ + my $self = shift; + return unless $self->opened; + return 1 unless wantarray; + my $len = length ${*$self->{buf}}; + + return ( + undef, undef, # dev, ino + 0666, # filemode + 1, # links + $>, # user id + $), # group id + undef, # device id + $len, # size + undef, # atime + undef, # mtime + undef, # ctime + 512, # blksize + int(($len+511)/512) # blocks + ); +} + +sub FILENO { + return undef; # XXX perlfunc says this means the file is closed +} + +sub blocking { + my $self = shift; + my $old = *$self->{blocking} || 0; + *$self->{blocking} = shift if @_; + return $old; +} + +my $notmuch = sub { return }; + +*fileno = $notmuch; +*error = $notmuch; +*clearerr = $notmuch; +*sync = $notmuch; +*flush = $notmuch; +*setbuf = $notmuch; +*setvbuf = $notmuch; + +*untaint = $notmuch; +*autoflush = $notmuch; +*fcntl = $notmuch; +*ioctl = $notmuch; + +*GETC = \&getc; +*PRINT = \&print; +*PRINTF = \&printf; +*READ = \&read; +*WRITE = \&write; +*SEEK = \&seek; +*TELL = \&getpos; +*EOF = \&eof; +*CLOSE = \&close; +*BINMODE = \&binmode; + + +sub string_ref +{ + my $self = shift; + return *$self->{buf}; +} +*sref = \&string_ref; + +1; + +__END__ + +#line 552 diff --git a/lib/Image/ExifTool.pm b/lib/Image/ExifTool.pm new file mode 100644 index 0000000..593a4ce --- /dev/null +++ b/lib/Image/ExifTool.pm @@ -0,0 +1,8280 @@ +#------------------------------------------------------------------------------ +# File: ExifTool.pm +# +# Description: Read and write meta information +# +# URL: http://owl.phy.queensu.ca/~phil/exiftool/ +# +# Revisions: Nov. 12/2003 - P. Harvey Created +# (See html/history.html for revision history) +# +# Legal: Copyright (c) 2003-2019, Phil Harvey (phil at owl.phy.queensu.ca) +# This library is free software; you can redistribute it and/or +# modify it under the same terms as Perl itself. +#------------------------------------------------------------------------------ + +package Image::ExifTool; + +use strict; +require 5.004; # require 5.004 for UNIVERSAL::isa (otherwise 5.002 would do) +require Exporter; +use File::RandomAccess; + +use vars qw($VERSION $RELEASE @ISA @EXPORT_OK %EXPORT_TAGS $AUTOLOAD @fileTypes + %allTables @tableOrder $exifAPP1hdr $xmpAPP1hdr $xmpExtAPP1hdr + $psAPP13hdr $psAPP13old @loadAllTables %UserDefined $evalWarning + %noWriteFile %magicNumber @langs $defaultLang %langName %charsetName + %mimeType $swapBytes $swapWords $currentByteOrder %unpackStd + %jpegMarker %specialTags %fileTypeLookup); + +$VERSION = '11.30'; +$RELEASE = ''; +@ISA = qw(Exporter); +%EXPORT_TAGS = ( + # all public non-object-oriented functions: + Public => [qw( + ImageInfo GetTagName GetShortcuts GetAllTags GetWritableTags + GetAllGroups GetDeleteGroups GetFileType CanWrite CanCreate + AddUserDefinedTags + )], + # exports not part of the public API, but used by ExifTool modules: + DataAccess => [qw( + ReadValue GetByteOrder SetByteOrder ToggleByteOrder Get8u Get8s Get16u + Get16s Get32u Get32s Get64u GetFloat GetDouble GetFixed32s Write + WriteValue Tell Set8u Set8s Set16u Set32u + )], + Utils => [qw(GetTagTable TagTableKeys GetTagInfoList AddTagToTable HexDump)], + Vars => [qw(%allTables @tableOrder @fileTypes)], +); + +# set all of our EXPORT_TAGS in EXPORT_OK +Exporter::export_ok_tags(keys %EXPORT_TAGS); + +# test for problems that can arise if encoding.pm is used +{ my $t = "\xff"; die "Incompatible encoding!\n" if ord($t) != 0xff; } + +# The following functions defined in Image::ExifTool::Writer are declared +# here so their prototypes will be available. These Writer routines will be +# autoloaded when any of them is called. +sub SetNewValue($;$$%); +sub SetNewValuesFromFile($$;@); +sub GetNewValue($$;$); +sub GetNewValues($$;$); +sub CountNewValues($); +sub SaveNewValues($); +sub RestoreNewValues($); +sub WriteInfo($$;$$); +sub SetFileModifyDate($$;$$$); +sub SetFileName($$;$$$); +sub SetSystemTags($$); +sub GetAllTags(;$); +sub GetWritableTags(;$); +sub GetAllGroups($); +sub GetNewGroups($); +sub GetDeleteGroups(); +sub AddUserDefinedTags($%); +# non-public routines below +sub InsertTagValues($$$;$$$); +sub IsWritable($); +sub IsSameFile($$$); +sub GetNewFileName($$); +sub LoadAllTables(); +sub GetNewTagInfoList($;$); +sub GetNewTagInfoHash($@); +sub GetLangInfo($$); +sub Get64s($$); +sub Get64u($$); +sub GetFixed64s($$); +sub GetExtended($$); +sub DecodeBits($$;$); +sub EncodeBits($$;$$); +sub HexDump($;$%); +sub DumpTrailer($$); +sub DumpUnknownTrailer($$); +sub VerboseInfo($$$%); +sub VerboseValue($$$;$); +sub VPrint($$@); +sub Rationalize($;$); +sub Write($@); +sub WriteTrailerBuffer($$$); +sub AddNewTrailers($;@); +sub Tell($); +sub WriteValue($$;$$$$); +sub WriteDirectory($$$;$); +sub WriteBinaryData($$$); +sub CheckBinaryData($$$); +sub WriteTIFF($$$); +sub PackUTF8(@); +sub UnpackUTF8($); +sub SetPreferredByteOrder($); +sub CopyBlock($$$); +sub CopyFileAttrs($$$); +sub TimeNow(;$$); +sub NewGUID(); +sub MakeTiffHeader($$$$;$$); + +# other subroutine definitions +sub EncodeFileName($$;$); +sub Open($*$;$); +sub Exists($$); +sub IsDirectory($$); +sub Rename($$$); +sub Unlink($@); +sub SetFileTime($$;$$$$); +sub DoEscape($$); +sub ConvertFileSize($); +sub ParseArguments($;@); #(defined in attempt to avoid mod_perl problem) +sub ReadValue($$$$$;$); + +# list of main tag tables to load in LoadAllTables() (sub-tables are recursed +# automatically). Note: They will appear in this order in the documentation +# unless tweaked in BuildTagLookup::GetTableOrder(). +@loadAllTables = qw( + PhotoMechanic Exif GeoTiff CanonRaw KyoceraRaw Lytro MinoltaRaw PanasonicRaw + SigmaRaw JPEG GIMP Jpeg2000 GIF BMP BMP::OS2 BMP::Extra BPG BPG::Extensions + PICT PNG MNG FLIF DjVu DPX OpenEXR MIFF PCX PGF PSP PhotoCD Radiance PDF + PostScript Photoshop::Header Photoshop::Layers Photoshop::ImageData + FujiFilm::RAF FujiFilm::IFD Samsung::Trailer Sony::SRF2 Sony::SR2SubIFD + Sony::PMP ITC ID3 FLAC Ogg Vorbis APE APE::NewHeader APE::OldHeader Audible + MPC MPEG::Audio MPEG::Video MPEG::Xing M2TS QuickTime QuickTime::ImageFile + QuickTime::Stream Matroska MOI MXF DV Flash Flash::FLV Real::Media + Real::Audio Real::Metafile Red RIFF AIFF ASF WTV DICOM MIE JSON HTML + XMP::SVG Palm Palm::MOBI Palm::EXTH Torrent EXE EXE::PEVersion EXE::PEString + EXE::MachO EXE::PEF EXE::ELF EXE::AR EXE::CHM LNK Font VCard + VCard::VCalendar RSRC Rawzor ZIP ZIP::GZIP ZIP::RAR RTF OOXML iWork ISO + FLIR::AFF FLIR::FPF MacOS::MDItem MacOS::XAttr FlashPix::DocTable +); + +# alphabetical list of current Lang modules +@langs = qw(cs de en en_ca en_gb es fi fr it ja ko nl pl ru sv tr zh_cn zh_tw); + +$defaultLang = 'en'; # default language + +# language names +%langName = ( + cs => 'Czech (Čeština)', + de => 'German (Deutsch)', + en => 'English', + en_ca => 'Canadian English', + en_gb => 'British English', + es => 'Spanish (Español)', + fi => 'Finnish (Suomi)', + fr => 'French (Français)', + it => 'Italian (Italiano)', + ja => 'Japanese (日本語)', + ko => 'Korean (한국어)', + nl => 'Dutch (Nederlands)', + pl => 'Polish (Polski)', + ru => 'Russian (Русский)', + sv => 'Swedish (Svenska)', + 'tr'=> 'Turkish (Türkçe)', + zh_cn => 'Simplified Chinese (简体中文)', + zh_tw => 'Traditional Chinese (繁體中文)', +); + +# recognized file types, in the order we test unknown files +# Notes: 1) There is no need to test for like types separately here +# 2) Put types with weak file signatures at end of list to avoid false matches +# 3) PLIST must be in this list for the binary PLIST format, although it may +# cause a file to be checked twice for XML +@fileTypes = qw(JPEG EXV CRW DR4 TIFF GIF MRW RAF X3F JP2 PNG MIE MIFF PS PDF + PSD XMP BMP BPG PPM RIFF AIFF ASF MOV MPEG Real SWF PSP FLV OGG + FLAC APE MPC MKV MXF DV PMP IND PGF ICC ITC FLIR FLIF FPF LFP + HTML VRD RTF XCF DSS QTIF FPX PICT ZIP GZIP PLIST RAR BZ2 TAR + RWZ EXE EXR HDR CHM LNK WMF AVC DEX DPX RAW Font RSRC M2TS PHP + PCX DCX DWF DWG WTV Torrent VCard LRI R3D AA PDB MOI ISO JSON + MP3 DICOM PCD); + +# file types that we can write (edit) +my @writeTypes = qw(JPEG TIFF GIF CRW MRW ORF RAF RAW PNG MIE PSD XMP PPM EPS + X3F PS PDF ICC VRD DR4 JP2 EXIF AI AIT IND MOV EXV FLIF); +my %writeTypes; # lookup for writable file types (hash filled if required) + +# file extensions that we can't write for various base types +%noWriteFile = ( + TIFF => [ qw(3FR DCR K25 KDC SRF) ], + XMP => [ qw(SVG INX) ], + JP2 => [ qw(J2C JPC) ], + MOV => [ qw(HEIC HEIF INSV) ], +); + +# file types that we can create from scratch +# - must update CanCreate() documentation if this list is changed! +my %createTypes = map { $_ => 1 } qw(XMP ICC MIE VRD DR4 EXIF EXV); + +# file type lookup for all recognized file extensions +# (if extension may be more than one type, the type is a list where +# the writable type should come first if it exists) +%fileTypeLookup = ( + '3FR' => ['TIFF', 'Hasselblad RAW format'], + '3G2' => ['MOV', '3rd Gen. Partnership Project 2 audio/video'], + '3GP' => ['MOV', '3rd Gen. Partnership Project audio/video'], + '3GP2'=> '3G2', + '3GPP'=> '3GP', + A => ['EXE', 'Static library'], + AA => ['AA', 'Audible Audiobook'], + AAE => ['PLIST','Apple edit information'], + AAX => ['MOV', 'Audible Enhanced Audiobook'], + ACR => ['DICOM','American College of Radiology ACR-NEMA'], + ACFM => ['Font', 'Adobe Composite Font Metrics'], + AFM => ['Font', 'Adobe Font Metrics'], + AMFM => ['Font', 'Adobe Multiple Master Font Metrics'], + AI => [['PDF','PS'], 'Adobe Illustrator'], + AIF => 'AIFF', + AIFC => ['AIFF', 'Audio Interchange File Format Compressed'], + AIFF => ['AIFF', 'Audio Interchange File Format'], + AIT => 'AI', + APE => ['APE', "Monkey's Audio format"], + APNG => ['PNG', 'Animated Portable Network Graphics'], + ARW => ['TIFF', 'Sony Alpha RAW format'], + ARQ => ['TIFF', 'Sony Alpha Pixel-Shift RAW format'], + ASF => ['ASF', 'Microsoft Advanced Systems Format'], + AVC => ['AVC', 'Advanced Video Connection'], # (extensions are actually _AU,_AD,_IM,_ID) + AVI => ['RIFF', 'Audio Video Interleaved'], + AZW => 'MOBI', # (see http://wiki.mobileread.com/wiki/AZW) + AZW3 => 'MOBI', + BMP => ['BMP', 'Windows Bitmap'], + BPG => ['BPG', 'Better Portable Graphics'], + BTF => ['BTF', 'Big Tagged Image File Format'], #(unofficial) + BZ2 => ['BZ2', 'BZIP2 archive'], + CHM => ['CHM', 'Microsoft Compiled HTML format'], + CIFF => ['CRW', 'Camera Image File Format'], + COS => ['COS', 'Capture One Settings'], + CR2 => ['TIFF', 'Canon RAW 2 format'], + CR3 => ['MOV', 'Canon RAW 3 format'], + CRM => ['MOV', 'Canon RAW Movie'], + CRW => ['CRW', 'Canon RAW format'], + CS1 => ['PSD', 'Sinar CaptureShop 1-Shot RAW'], + DC3 => 'DICM', + DCM => 'DICM', + DCP => ['TIFF', 'DNG Camera Profile'], + DCR => ['TIFF', 'Kodak Digital Camera RAW'], + DCX => ['DCX', 'Multi-page PC Paintbrush'], + DEX => ['DEX', 'Dalvik Executable format'], + DFONT=> ['Font', 'Macintosh Data fork Font'], + DIB => ['BMP', 'Device Independent Bitmap'], + DIC => 'DICM', + DICM => ['DICOM','Digital Imaging and Communications in Medicine'], + DIVX => ['ASF', 'DivX media format'], + DJV => 'DJVU', + DJVU => ['AIFF', 'DjVu image'], + DLL => ['EXE', 'Windows Dynamic Link Library'], + DNG => ['TIFF', 'Digital Negative'], + DOC => ['FPX', 'Microsoft Word Document'], + DOCM => [['ZIP','FPX'], 'Office Open XML Document Macro-enabled'], + # Note: I have seen a password-protected DOCX file which was FPX-like, so I assume + # that any other MS Office file could be like this too. The only difference is + # that the ZIP and FPX formats are checked first, so if this is wrong, no biggie. + DOCX => [['ZIP','FPX'], 'Office Open XML Document'], + DOT => ['FPX', 'Microsoft Word Template'], + DOTM => [['ZIP','FPX'], 'Office Open XML Document Template Macro-enabled'], + DOTX => [['ZIP','FPX'], 'Office Open XML Document Template'], + DPX => ['DPX', 'Digital Picture Exchange' ], + DR4 => ['DR4', 'Canon VRD version 4 Recipe'], + DS2 => ['DSS', 'Digital Speech Standard 2'], + DSS => ['DSS', 'Digital Speech Standard'], + DV => ['DV', 'Digital Video'], + DVB => ['MOV', 'Digital Video Broadcasting'], + 'DVR-MS'=>['ASF', 'Microsoft Digital Video recording'], + DWF => ['DWF', 'Autodesk drawing (Design Web Format)'], + DWG => ['DWG', 'AutoCAD Drawing'], + DYLIB=> ['EXE', 'Mach-O Dynamic Link Library'], + EIP => ['ZIP', 'Capture One Enhanced Image Package'], + EPS => ['EPS', 'Encapsulated PostScript Format'], + EPS2 => 'EPS', + EPS3 => 'EPS', + EPSF => 'EPS', + EPUB => ['ZIP', 'Electronic Publication'], + ERF => ['TIFF', 'Epson Raw Format'], + EXE => ['EXE', 'Windows executable file'], + EXR => ['EXR', 'Open EXR'], + EXIF => ['EXIF', 'Exchangable Image File Metadata'], + EXV => ['EXV', 'Exiv2 metadata'], + F4A => ['MOV', 'Adobe Flash Player 9+ Audio'], + F4B => ['MOV', 'Adobe Flash Player 9+ audio Book'], + F4P => ['MOV', 'Adobe Flash Player 9+ Protected'], + F4V => ['MOV', 'Adobe Flash Player 9+ Video'], + FFF => [['TIFF','FLIR'], 'Hasselblad Flexible File Format'], + FLAC => ['FLAC', 'Free Lossless Audio Codec'], + FLA => ['FPX', 'Macromedia/Adobe Flash project'], + FLIF => ['FLIF', 'Free Lossless Image Format'], + FLIR => ['FLIR', 'FLIR File Format'], # (not an actual extension) + FLV => ['FLV', 'Flash Video'], + FPF => ['FPF', 'FLIR Public image Format'], + FPX => ['FPX', 'FlashPix'], + GIF => ['GIF', 'Compuserve Graphics Interchange Format'], + GPR => ['TIFF', 'GoPro RAW'], + GZ => 'GZIP', + GZIP => ['GZIP', 'GNU ZIP compressed archive'], + HDP => ['TIFF', 'Windows HD Photo'], + HDR => ['HDR', 'Radiance RGBE High Dynamic Range'], + HEIC => ['MOV', 'High Efficiency Image Format still image'], + HEIF => ['MOV', 'High Efficiency Image Format'], + HTM => 'HTML', + HTML => ['HTML', 'HyperText Markup Language'], + ICAL => 'ICS', + ICC => ['ICC', 'International Color Consortium'], + ICM => 'ICC', + ICS => ['VCard','iCalendar Schedule'], + IDML => ['ZIP', 'Adobe InDesign Markup Language'], + IIQ => ['TIFF', 'Phase One Intelligent Image Quality RAW'], + IND => ['IND', 'Adobe InDesign'], + INDD => ['IND', 'Adobe InDesign Document'], + INDT => ['IND', 'Adobe InDesign Template'], + INSV => 'MP4', + INX => ['XMP', 'Adobe InDesign Interchange'], + ISO => ['ISO', 'ISO 9660 disk image'], + ITC => ['ITC', 'iTunes Cover Flow'], + J2C => ['JP2', 'JPEG 2000 codestream'], + J2K => 'J2C', + JNG => ['PNG', 'JPG Network Graphics'], + JP2 => ['JP2', 'JPEG 2000 file'], + # JP4? - looks like a JPEG but the image data is different + JPC => 'J2C', + JPE => 'JPEG', + JPEG => ['JPEG', 'Joint Photographic Experts Group'], + JPF => 'JP2', + JPG => 'JPEG', + JPM => ['JP2', 'JPEG 2000 compound image'], + JPX => ['JP2', 'JPEG 2000 with extensions'], + JSON => ['JSON', 'JavaScript Object Notation'], + JXR => ['TIFF', 'JPEG XR'], + K25 => ['TIFF', 'Kodak DC25 RAW'], + KDC => ['TIFF', 'Kodak Digital Camera RAW'], + KEY => ['ZIP', 'Apple Keynote presentation'], + KTH => ['ZIP', 'Apple Keynote Theme'], + LA => ['RIFF', 'Lossless Audio'], + LFP => ['LFP', 'Lytro Light Field Picture'], + LFR => 'LFP', # (Light Field RAW) + LNK => ['LNK', 'Windows shortcut'], + LRI => ['LRI', 'Light RAW'], + LRV => ['MOV', 'Low-Resolution Video'], + M2T => 'M2TS', + M2TS => ['M2TS', 'MPEG-2 Transport Stream'], + M2V => ['MPEG', 'MPEG-2 Video'], + M4A => ['MOV', 'MPEG-4 Audio'], + M4B => ['MOV', 'MPEG-4 audio Book'], + M4P => ['MOV', 'MPEG-4 Protected'], + M4V => ['MOV', 'MPEG-4 Video'], + MAX => ['FPX', '3D Studio MAX'], + MEF => ['TIFF', 'Mamiya (RAW) Electronic Format'], + MIE => ['MIE', 'Meta Information Encapsulation format'], + MIF => 'MIFF', + MIFF => ['MIFF', 'Magick Image File Format'], + MKA => ['MKV', 'Matroska Audio'], + MKS => ['MKV', 'Matroska Subtitle'], + MKV => ['MKV', 'Matroska Video'], + MNG => ['PNG', 'Multiple-image Network Graphics'], + MOBI => ['PDB', 'Mobipocket electronic book'], + MODD => ['PLIST','Sony Picture Motion metadata'], + MOI => ['MOI', 'MOD Information file'], + MOS => ['TIFF', 'Creo Leaf Mosaic'], + MOV => ['MOV', 'Apple QuickTime movie'], + MP3 => ['MP3', 'MPEG-1 Layer 3 audio'], + MP4 => ['MOV', 'MPEG-4 video'], + MPC => ['MPC', 'Musepack Audio'], + MPEG => ['MPEG', 'MPEG-1 or MPEG-2 audio/video'], + MPG => 'MPEG', + MPO => ['JPEG', 'Extended Multi-Picture format'], + MQV => ['MOV', 'Sony Mobile Quicktime Video'], + MRW => ['MRW', 'Minolta RAW format'], + MTS => 'M2TS', + MXF => ['MXF', 'Material Exchange Format'], + # NDPI => ['TIFF', 'Hamamatsu NanoZoomer Digital Pathology Image'], + NEF => ['TIFF', 'Nikon (RAW) Electronic Format'], + NEWER => 'COS', + NMBTEMPLATE => ['ZIP','Apple Numbers Template'], + NRW => ['TIFF', 'Nikon RAW (2)'], + NUMBERS => ['ZIP','Apple Numbers spreadsheet'], + O => ['EXE', 'Relocatable Object'], + ODB => ['ZIP', 'Open Document Database'], + ODC => ['ZIP', 'Open Document Chart'], + ODF => ['ZIP', 'Open Document Formula'], + ODG => ['ZIP', 'Open Document Graphics'], + ODI => ['ZIP', 'Open Document Image'], + ODP => ['ZIP', 'Open Document Presentation'], + ODS => ['ZIP', 'Open Document Spreadsheet'], + ODT => ['ZIP', 'Open Document Text file'], + OFR => ['RIFF', 'OptimFROG audio'], + OGG => ['OGG', 'Ogg Vorbis audio file'], + OGV => ['OGG', 'Ogg Video file'], + OPUS => ['OGG', 'Ogg Opus audio file'], + ORF => ['ORF', 'Olympus RAW format'], + OTF => ['Font', 'Open Type Font'], + PAC => ['RIFF', 'Lossless Predictive Audio Compression'], + PAGES => ['ZIP', 'Apple Pages document'], + PBM => ['PPM', 'Portable BitMap'], + PCD => ['PCD', 'Kodak Photo CD Image Pac'], + PCT => 'PICT', + PCX => ['PCX', 'PC Paintbrush'], + PDB => ['PDB', 'Palm Database'], + PDF => ['PDF', 'Adobe Portable Document Format'], + PEF => ['TIFF', 'Pentax (RAW) Electronic Format'], + PFA => ['Font', 'PostScript Font ASCII'], + PFB => ['Font', 'PostScript Font Binary'], + PFM => ['Font', 'Printer Font Metrics'], + PGF => ['PGF', 'Progressive Graphics File'], + PGM => ['PPM', 'Portable Gray Map'], + PHP => ['PHP', 'PHP Hypertext Preprocessor'], + PHP3 => 'PHP', + PHP4 => 'PHP', + PHP5 => 'PHP', + PHPS => 'PHP', + PHTML=> 'PHP', + PICT => ['PICT', 'Apple PICTure'], + PLIST=> ['PLIST','Apple Property List'], + PMP => ['PMP', 'Sony DSC-F1 Cyber-Shot PMP'], # should stand for Proprietery Metadata Package ;) + PNG => ['PNG', 'Portable Network Graphics'], + POT => ['FPX', 'Microsoft PowerPoint Template'], + POTM => [['ZIP','FPX'], 'Office Open XML Presentation Template Macro-enabled'], + POTX => [['ZIP','FPX'], 'Office Open XML Presentation Template'], + PPM => ['PPM', 'Portable Pixel Map'], + PPS => ['FPX', 'Microsoft PowerPoint Slideshow'], + PPSM => [['ZIP','FPX'], 'Office Open XML Presentation Slideshow Macro-enabled'], + PPSX => [['ZIP','FPX'], 'Office Open XML Presentation Slideshow'], + PPT => ['FPX', 'Microsoft PowerPoint Presentation'], + PPTM => [['ZIP','FPX'], 'Office Open XML Presentation Macro-enabled'], + PPTX => [['ZIP','FPX'], 'Office Open XML Presentation'], + PRC => ['PDB', 'Palm Database'], + PS => ['PS', 'PostScript'], + PS2 => 'PS', + PS3 => 'PS', + PSB => ['PSD', 'Photoshop Large Document'], + PSD => ['PSD', 'Photoshop Document'], + PSDT => ['PSD', 'Photoshop Document Template'], + PSP => ['PSP', 'Paint Shop Pro'], + PSPFRAME => 'PSP', + PSPIMAGE => 'PSP', + PSPSHAPE => 'PSP', + PSPTUBE => 'PSP', + QIF => 'QTIF', + QT => 'MOV', + QTI => 'QTIF', + QTIF => ['QTIF', 'QuickTime Image File'], + R3D => ['R3D', 'Redcode RAW Video'], + RA => ['Real', 'Real Audio'], + RAF => ['RAF', 'FujiFilm RAW Format'], + RAM => ['Real', 'Real Audio Metafile'], + RAR => ['RAR', 'RAR Archive'], + RAW => [['RAW','TIFF'], 'Kyocera Contax N Digital RAW or Panasonic RAW'], + RIF => 'RIFF', + RIFF => ['RIFF', 'Resource Interchange File Format'], + RM => ['Real', 'Real Media'], + RMVB => ['Real', 'Real Media Variable Bitrate'], + RPM => ['Real', 'Real Media Plug-in Metafile'], + RSRC => ['RSRC', 'Mac OS Resource'], + RTF => ['RTF', 'Rich Text Format'], + RV => ['Real', 'Real Video'], + RW2 => ['TIFF', 'Panasonic RAW 2'], + RWL => ['TIFF', 'Leica RAW'], + RWZ => ['RWZ', 'Rawzor compressed image'], + SEQ => ['FLIR', 'FLIR image Sequence'], + SKETCH => ['ZIP', 'Sketch design file'], + SO => ['EXE', 'Shared Object file'], + SR2 => ['TIFF', 'Sony RAW Format 2'], + SRF => ['TIFF', 'Sony RAW Format'], + SRW => ['TIFF', 'Samsung RAW format'], + SVG => ['XMP', 'Scalable Vector Graphics'], + SWF => ['SWF', 'Shockwave Flash'], + TAR => ['TAR', 'TAR archive'], + THM => ['JPEG', 'Thumbnail'], + THMX => [['ZIP','FPX'], 'Office Open XML Theme'], + TIF => 'TIFF', + TIFF => ['TIFF', 'Tagged Image File Format'], + TORRENT => ['Torrent', 'BitTorrent description file'], + TS => 'M2TS', + TTC => ['Font', 'True Type Font Collection'], + TTF => ['Font', 'True Type Font'], + TUB => 'PSP', + VCARD=> ['VCard','Virtual Card'], + VCF => 'VCARD', + VOB => ['MPEG', 'Video Object'], + VRD => ['VRD', 'Canon VRD Recipe Data'], + VSD => ['FPX', 'Microsoft Visio Drawing'], + WAV => ['RIFF', 'WAVeform (Windows digital audio)'], + WDP => ['TIFF', 'Windows Media Photo'], + WEBM => ['MKV', 'Google Web Movie'], + WEBP => ['RIFF', 'Google Web Picture'], + WMA => ['ASF', 'Windows Media Audio'], + WMF => ['WMF', 'Windows Metafile Format'], + WMV => ['ASF', 'Windows Media Video'], + WV => ['RIFF', 'WavePack lossless audio'], + X3F => ['X3F', 'Sigma RAW format'], + XCF => ['XCF', 'GIMP native image format'], + XHTML=> ['HTML', 'Extensible HyperText Markup Language'], + XLA => ['FPX', 'Microsoft Excel Add-in'], + XLAM => [['ZIP','FPX'], 'Office Open XML Spreadsheet Add-in Macro-enabled'], + XLS => ['FPX', 'Microsoft Excel Spreadsheet'], + XLSB => [['ZIP','FPX'], 'Office Open XML Spreadsheet Binary'], + XLSM => [['ZIP','FPX'], 'Office Open XML Spreadsheet Macro-enabled'], + XLSX => [['ZIP','FPX'], 'Office Open XML Spreadsheet'], + XLT => ['FPX', 'Microsoft Excel Template'], + XLTM => [['ZIP','FPX'], 'Office Open XML Spreadsheet Template Macro-enabled'], + XLTX => [['ZIP','FPX'], 'Office Open XML Spreadsheet Template'], + XMP => ['XMP', 'Extensible Metadata Platform'], + WTV => ['WTV', 'Windows recorded TV show'], + ZIP => ['ZIP', 'ZIP archive'], +); + +# typical extension for each file type (if different than FileType) +# - case is not significant +my %fileTypeExt = ( + 'Canon 1D RAW' => 'tif', + DICOM => 'dcm', + FLIR => 'fff', + GZIP => 'gz', + JPEG => 'jpg', + M2TS => 'mts', + MPEG => 'mpg', + TIFF => 'tif', + VCard => 'vcf', +); + +# descriptions for file types not found in above file extension lookup +my %fileDescription = ( + DICOM => 'Digital Imaging and Communications in Medicine', + XML => 'Extensible Markup Language', + 'Win32 EXE' => 'Windows 32-bit Executable', + 'Win32 DLL' => 'Windows 32-bit Dynamic Link Library', + 'Win64 EXE' => 'Windows 64-bit Executable', + 'Win64 DLL' => 'Windows 64-bit Dynamic Link Library', +); + +# MIME types for applicable file types above +# (missing entries default to 'application/unknown', but note that other MIME +# types may be specified by some modules, eg. QuickTime.pm and RIFF.pm) +%mimeType = ( + '3FR' => 'image/x-hasselblad-3fr', + AA => 'audio/audible', + AAE => 'application/vnd.apple.photos', + AI => 'application/vnd.adobe.illustrator', + AIFF => 'audio/x-aiff', + APE => 'audio/x-monkeys-audio', + APNG => 'image/apng', + ASF => 'video/x-ms-asf', + ARW => 'image/x-sony-arw', + BMP => 'image/bmp', + BPG => 'image/bpg', + BTF => 'image/x-tiff-big', #(NC) (ref http://www.asmail.be/msg0055371937.html) + BZ2 => 'application/bzip2', + 'Canon 1D RAW' => 'image/x-raw', # (uses .TIF file extension) + CHM => 'application/x-chm', + CR2 => 'image/x-canon-cr2', + CR3 => 'image/x-canon-cr3', + CRM => 'video/x-canon-crm', + CRW => 'image/x-canon-crw', + DCR => 'image/x-kodak-dcr', + DCX => 'image/dcx', + DEX => 'application/octet-stream', + DFONT=> 'application/x-dfont', + DICOM=> 'application/dicom', + DIVX => 'video/divx', + DJVU => 'image/vnd.djvu', + DNG => 'image/x-adobe-dng', + DOC => 'application/msword', + DOCM => 'application/vnd.ms-word.document.macroEnabled', + DOCX => 'application/vnd.openxmlformats-officedocument.wordprocessingml.document', + DOT => 'application/msword', + DOTM => 'application/vnd.ms-word.template.macroEnabledTemplate', + DOTX => 'application/vnd.openxmlformats-officedocument.wordprocessingml.template', + DPX => 'image/x-dpx', + DS2 => 'audio/x-ds2', + DSS => 'audio/x-dss', + DV => 'video/x-dv', + 'DVR-MS' => 'video/x-ms-dvr', + DWF => 'model/vnd.dwf', + DWG => 'image/vnd.dwg', + EIP => 'application/x-captureone', #(NC) + EPS => 'application/postscript', + ERF => 'image/x-epson-erf', + EXE => 'application/octet-stream', + EXV => 'image/x-exv', + FFF => 'image/x-hasselblad-fff', + FLA => 'application/vnd.adobe.fla', + FLAC => 'audio/flac', + FLIF => 'image/flif', + FLV => 'video/x-flv', + Font => 'application/x-font-type1', # covers PFA, PFB and PFM (not sure about PFM) + FPX => 'image/vnd.fpx', + GIF => 'image/gif', + GPR => 'image/x-gopro-gpr', + GZIP => 'application/x-gzip', + HDP => 'image/vnd.ms-photo', + HDR => 'image/vnd.radiance', + HTML => 'text/html', + ICC => 'application/vnd.iccprofile', + ICS => 'text/calendar', + IDML => 'application/vnd.adobe.indesign-idml-package', + IIQ => 'image/x-raw', + IND => 'application/x-indesign', + INX => 'application/x-indesign-interchange', #PH (NC) + ISO => 'application/x-iso9660-image', + ITC => 'application/itunes', + JNG => 'image/jng', + J2C => 'image/x-j2c', #PH (NC) + JP2 => 'image/jp2', + JPEG => 'image/jpeg', + JPM => 'image/jpm', + JPX => 'image/jpx', + JSON => 'application/json', + K25 => 'image/x-kodak-k25', + KDC => 'image/x-kodak-kdc', + KEY => 'application/x-iwork-keynote-sffkey', + LFP => 'image/x-lytro-lfp', #PH (NC) + LNK => 'application/octet-stream', + LRI => 'image/x-light-lri', + MAX => 'application/x-3ds', + M2T => 'video/mpeg', + M2TS => 'video/m2ts', + MEF => 'image/x-mamiya-mef', + MIE => 'application/x-mie', + MIFF => 'application/x-magick-image', + MKA => 'audio/x-matroska', + MKS => 'application/x-matroska', + MKV => 'video/x-matroska', + MNG => 'video/mng', + MOBI => 'application/x-mobipocket-ebook', + MOS => 'image/x-raw', + MOV => 'video/quicktime', + MP3 => 'audio/mpeg', + MP4 => 'video/mp4', + MPC => 'audio/x-musepack', + MPEG => 'video/mpeg', + MRW => 'image/x-minolta-mrw', + MXF => 'application/mxf', + NEF => 'image/x-nikon-nef', + NRW => 'image/x-nikon-nrw', + NUMBERS => 'application/x-iwork-numbers-sffnumbers', + ODB => 'application/vnd.oasis.opendocument.database', + ODC => 'application/vnd.oasis.opendocument.chart', + ODF => 'application/vnd.oasis.opendocument.formula', + ODG => 'application/vnd.oasis.opendocument.graphics', + ODI => 'application/vnd.oasis.opendocument.image', + ODP => 'application/vnd.oasis.opendocument.presentation', + ODS => 'application/vnd.oasis.opendocument.spreadsheet', + ODT => 'application/vnd.oasis.opendocument.text', + OGG => 'audio/ogg', + OGV => 'video/ogg', + EXR => 'image/x-exr', + ORF => 'image/x-olympus-orf', + OTF => 'application/x-font-otf', + PAGES=> 'application/x-iwork-pages-sffpages', + PBM => 'image/x-portable-bitmap', + PCD => 'image/x-photo-cd', + PCX => 'image/pcx', + PDB => 'application/vnd.palm', + PDF => 'application/pdf', + PEF => 'image/x-pentax-pef', + PFA => 'application/x-font-type1', # (needed if handled by PostScript module) + PGF => 'image/pgf', + PGM => 'image/x-portable-graymap', + PHP => 'application/x-httpd-php', + PICT => 'image/pict', + PLIST=> 'application/xml', # (binary PLIST format is 'application/x-plist', recognized at run time) + PNG => 'image/png', + POT => 'application/vnd.ms-powerpoint', + POTM => 'application/vnd.ms-powerpoint.template.macroEnabled', + POTX => 'application/vnd.openxmlformats-officedocument.presentationml.template', + PPM => 'image/x-portable-pixmap', + PPS => 'application/vnd.ms-powerpoint', + PPSM => 'application/vnd.ms-powerpoint.slideshow.macroEnabled', + PPSX => 'application/vnd.openxmlformats-officedocument.presentationml.slideshow', + PPT => 'application/vnd.ms-powerpoint', + PPTM => 'application/vnd.ms-powerpoint.presentation.macroEnabled', + PPTX => 'application/vnd.openxmlformats-officedocument.presentationml.presentation', + PS => 'application/postscript', + PSD => 'application/vnd.adobe.photoshop', + PSP => 'image/x-paintshoppro', #(NC) + QTIF => 'image/x-quicktime', + R3D => 'video/x-red-r3d', #PH (invented) + RA => 'audio/x-pn-realaudio', + RAF => 'image/x-fujifilm-raf', + RAM => 'audio/x-pn-realaudio', + RAR => 'application/x-rar-compressed', + RAW => 'image/x-raw', + RM => 'application/vnd.rn-realmedia', + RMVB => 'application/vnd.rn-realmedia-vbr', + RPM => 'audio/x-pn-realaudio-plugin', + RSRC => 'application/ResEdit', + RTF => 'text/rtf', + RV => 'video/vnd.rn-realvideo', + RW2 => 'image/x-panasonic-rw2', + RWL => 'image/x-leica-rwl', + RWZ => 'image/x-rawzor', #(duplicated in Rawzor.pm) + SKETCH => 'application/sketch', + SR2 => 'image/x-sony-sr2', + SRF => 'image/x-sony-srf', + SRW => 'image/x-samsung-srw', + SVG => 'image/svg+xml', + SWF => 'application/x-shockwave-flash', + TAR => 'application/x-tar', + THMX => 'application/vnd.ms-officetheme', + TIFF => 'image/tiff', + Torrent => 'application/x-bittorrent', + TTC => 'application/x-font-ttf', + TTF => 'application/x-font-ttf', + VCard=> 'text/vcard', + VSD => 'application/x-visio', + WDP => 'image/vnd.ms-photo', + WEBM => 'video/webm', + WMA => 'audio/x-ms-wma', + WMF => 'application/x-wmf', + WMV => 'video/x-ms-wmv', + WTV => 'video/x-ms-wtv', + X3F => 'image/x-sigma-x3f', + XCF => 'image/x-xcf', + XLA => 'application/vnd.ms-excel', + XLAM => 'application/vnd.ms-excel.addin.macroEnabled', + XLS => 'application/vnd.ms-excel', + XLSB => 'application/vnd.ms-excel.sheet.binary.macroEnabled', + XLSM => 'application/vnd.ms-excel.sheet.macroEnabled', + XLSX => 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet', + XLT => 'application/vnd.ms-excel', + XLTM => 'application/vnd.ms-excel.template.macroEnabled', + XLTX => 'application/vnd.openxmlformats-officedocument.spreadsheetml.template', + XML => 'application/xml', + XMP => 'application/rdf+xml', + ZIP => 'application/zip', +); + +# module names for processing routines of each file type +# - undefined entries default to same module name as file type +# - module name '' defaults to Image::ExifTool +# - module name '0' indicates a recognized but unsupported file +my %moduleName = ( + AA => 'Audible', + AVC => 0, + BTF => 'BigTIFF', + BZ2 => 0, + CRW => 'CanonRaw', + CHM => 'EXE', + COS => 'CaptureOne', + DEX => 0, + DOCX => 'OOXML', + DCX => 0, + DR4 => 'CanonVRD', + DSS => 'Olympus', + DWF => 0, + DWG => 0, + EPS => 'PostScript', + EXIF => '', + EXR => 'OpenEXR', + EXV => '', + ICC => 'ICC_Profile', + IND => 'InDesign', + FLV => 'Flash', + FPF => 'FLIR', + FPX => 'FlashPix', + GZIP => 'ZIP', + HDR => 'Radiance', + JP2 => 'Jpeg2000', + JPEG => '', + LFP => 'Lytro', + LRI => 0, + MOV => 'QuickTime', + MKV => 'Matroska', + MP3 => 'ID3', + MRW => 'MinoltaRaw', + OGG => 'Ogg', + ORF => 'Olympus', + PDB => 'Palm', + PCD => 'PhotoCD', + PHP => 0, + PMP => 'Sony', + PS => 'PostScript', + PSD => 'Photoshop', + QTIF => 'QuickTime', + R3D => 'Red', + RAF => 'FujiFilm', + RAR => 'ZIP', + RAW => 'KyoceraRaw', + RWZ => 'Rawzor', + SWF => 'Flash', + TAR => 0, + TIFF => '', + VRD => 'CanonVRD', + WMF => 0, + X3F => 'SigmaRaw', + XCF => 'GIMP', +); + +# quick "magic number" file test used to avoid loading module unnecessarily: +# - regular expression evaluated on first 1024 bytes of file +# - must match beginning at first byte in file +# - this test must not be more stringent than module logic +%magicNumber = ( + AA => '.{4}\x57\x90\x75\x36', + AIFF => '(FORM....AIF[FC]|AT&TFORM)', + APE => '(MAC |APETAGEX|ID3)', + ASF => '\x30\x26\xb2\x75\x8e\x66\xcf\x11\xa6\xd9\x00\xaa\x00\x62\xce\x6c', + AVC => '\+A\+V\+C\+', + Torrent => 'd\d+:\w+', + BMP => 'BM', + BPG => "BPG\xfb", + BTF => '(II\x2b\0|MM\0\x2b)', + BZ2 => 'BZh[1-9]\x31\x41\x59\x26\x53\x59', + CHM => 'ITSF.{20}\x10\xfd\x01\x7c\xaa\x7b\xd0\x11\x9e\x0c\0\xa0\xc9\x22\xe6\xec', + CRW => '(II|MM).{4}HEAP(CCDR|JPGM)', + DCX => '\xb1\x68\xde\x3a', + DEX => "dex\n035\0", + DICOM=> '(.{128}DICM|\0[\x02\x04\x06\x08]\0[\0-\x20]|[\x02\x04\x06\x08]\0[\0-\x20]\0)', + DOCX => 'PK\x03\x04', + DPX => '(SDPX|XPDS)', + DR4 => 'IIII\x04\0\x04\0', + DSS => '(\x02dss|\x03ds2)', + DV => '\x1f\x07\0[\x3f\xbf]', # (not tested if extension recognized) + DWF => '\(DWF V\d', + DWG => 'AC10\d{2}\0', + EPS => '(%!PS|%!Ad|\xc5\xd0\xd3\xc6)', + EXE => '(MZ|\xca\xfe\xba\xbe|\xfe\xed\xfa[\xce\xcf]|[\xce\xcf]\xfa\xed\xfe|Joy!peff|\x7fELF|#!\s*/\S*bin/|!\x0a)', + EXIF => '(II\x2a\0|MM\0\x2a)', + EXR => '\x76\x2f\x31\x01', + EXV => '\xff\x01Exiv2', + FLAC => '(fLaC|ID3)', + FLIF => 'FLIF[0-\x6f][0-2]', + FLIR => '[AF]FF\0', + FLV => 'FLV\x01', + Font => '((\0\x01\0\0|OTTO|true|typ1)[\0\x01]|ttcf\0[\x01\x02]\0\0|\0[\x01\x02]|' . + '(.{6})?%!(PS-(AdobeFont-|Bitstream )|FontType1-)|Start(Comp|Master)?FontMetrics)', + FPF => 'FPF Public Image Format\0', + FPX => '\xd0\xcf\x11\xe0\xa1\xb1\x1a\xe1', + GIF => 'GIF8[79]a', + GZIP => '\x1f\x8b\x08', + HDR => '#\?(RADIANCE|RGBE)\x0a', + HTML => '(\xef\xbb\xbf)?\s*(?i)<(!DOCTYPE\s+HTML|HTML|\?xml)', # (case insensitive) + ICC => '.{12}(scnr|mntr|prtr|link|spac|abst|nmcl|nkpf)(XYZ |Lab |Luv |YCbr|Yxy |RGB |GRAY|HSV |HLS |CMYK|CMY |[2-9A-F]CLR){2}', + IND => '\x06\x06\xed\xf5\xd8\x1d\x46\xe5\xbd\x31\xef\xe7\xfe\x74\xb7\x1d', + # ISO => signature is at byte 32768 + ITC => '.{4}itch', + JP2 => '(\0\0\0\x0cjP( |\x1a\x1a)\x0d\x0a\x87\x0a|\xff\x4f\xff\x51\0)', + JPEG => '\xff\xd8\xff', + JSON => '(\xef\xbb\xbf)?\s*(\[\s*)?\{\s*"[^"]+"\s*:', + LFP => '\x89LFP\x0d\x0a\x1a\x0a', + LNK => '.{4}\x01\x14\x02\0{5}\xc0\0{6}\x46', + LRI => 'LELR \0', + M2TS => '(....)?\x47', + MIE => '~[\x10\x18]\x04.0MIE', + MIFF => 'id=ImageMagick', + MKV => '\x1a\x45\xdf\xa3', + MOV => '.{4}(free|skip|wide|ftyp|pnot|PICT|pict|moov|mdat|junk|uuid)', # (duplicated in WriteQuickTime.pl !!) + # MP3 => difficult to rule out + MPC => '(MP\+|ID3)', + MOI => 'V6', + MPEG => '\0\0\x01[\xb0-\xbf]', + MRW => '\0MR[MI]', + MXF => '\x06\x0e\x2b\x34\x02\x05\x01\x01\x0d\x01\x02', # (not tested if extension recognized) + OGG => '(OggS|ID3)', + ORF => '(II|MM)', + PDB => '.{60}(\.pdfADBE|TEXtREAd|BVokBDIC|DB99DBOS|PNRdPPrs|DataPPrs|vIMGView|PmDBPmDB|InfoINDB|ToGoToGo|SDocSilX|JbDbJBas|JfDbJFil|DATALSdb|Mdb1Mdb1|BOOKMOBI|DataPlkr|DataSprd|SM01SMem|TEXtTlDc|InfoTlIf|DataTlMl|DataTlPt|dataTDBP|TdatTide|ToRaTRPW|zTXTGPlm|BDOCWrdS)', + # PCD => signature is at byte 2048 + PCX => '\x0a[\0-\x05]\x01[\x01\x02\x04\x08].{64}[\0-\x02]', + PDF => '\s*%PDF-\d+\.\d+', + PGF => 'PGF', + PHP => '<\?php\s', + PICT => '(.{10}|.{522})(\x11\x01|\x00\x11)', + PLIST=> '(bplist0|\s*<|\xfe\xff\x00)', + PMP => '.{8}\0{3}\x7c.{112}\xff\xd8\xff\xdb', + PNG => '(\x89P|\x8aM|\x8bJ)NG\r\n\x1a\n', + PPM => 'P[1-6]\s+', + PS => '(%!PS|%!Ad|\xc5\xd0\xd3\xc6)', + PSD => '8BPS\0[\x01\x02]', + PSP => 'Paint Shop Pro Image File\x0a\x1a\0{5}', + QTIF => '.{4}(idsc|idat|iicc)', + R3D => '\0\0..RED(1|2)', + RAF => 'FUJIFILM', + RAR => 'Rar!\x1a\x07\0', + RAW => '(.{25}ARECOYK|II|MM)', + Real => '(\.RMF|\.ra\xfd|pnm://|rtsp://|http://)', + RIFF => '(RIFF|LA0[234]|OFR |LPAC|wvpk|RF64)', # RIFF plus other variants + RSRC => '(....)?\0\0\x01\0', + RTF => '[\n\r]*\\{[\n\r]*\\\\rtf', + RWZ => 'rawzor', + SWF => '[FC]WS[^\0]', + TAR => '.{257}ustar( )?\0', # (this doesn't catch old-style tar files) + TIFF => '(II|MM)', # don't test magic number (some raw formats are different) + VCard=> '(?i)BEGIN:(VCARD|VCALENDAR)\r\n', + VRD => 'CANON OPTIONAL DATA\0', + WMF => '(\xd7\xcd\xc6\x9a\0\0|\x01\0\x09\0\0\x03)', + WTV => '\xb7\xd8\x00\x20\x37\x49\xda\x11\xa6\x4e\x00\x07\xe9\x5e\xad\x8d', + X3F => 'FOVb', + XCF => 'gimp xcf ', + XMP => '\0{0,3}(\xfe\xff|\xff\xfe|\xef\xbb\xbf)?\0{0,3}\s*<', + ZIP => 'PK\x03\x04', +); + +# file types with weak magic number recognition +my %weakMagic = ( MP3 => 1 ); + +# file types that are determined by the process proc when FastScan == 3 +# (when done, the process proc must exit after SetFileType if FastScan is 3) +my %processType = map { $_ => 1 } qw(JPEG TIFF XMP AIFF EXE Font PS Real VCard); + +# lookup for valid character set names (keys are all lower case) +%charsetName = ( + # Charset setting alias(es) + # ------------------------- -------------------------------------------- + utf8 => 'UTF8', cp65001 => 'UTF8', 'utf-8' => 'UTF8', + latin => 'Latin', cp1252 => 'Latin', latin1 => 'Latin', + latin2 => 'Latin2', cp1250 => 'Latin2', + cyrillic => 'Cyrillic', cp1251 => 'Cyrillic', russian => 'Cyrillic', + greek => 'Greek', cp1253 => 'Greek', + turkish => 'Turkish', cp1254 => 'Turkish', + hebrew => 'Hebrew', cp1255 => 'Hebrew', + arabic => 'Arabic', cp1256 => 'Arabic', + baltic => 'Baltic', cp1257 => 'Baltic', + vietnam => 'Vietnam', cp1258 => 'Vietnam', + thai => 'Thai', cp874 => 'Thai', + doslatinus => 'DOSLatinUS', cp437 => 'DOSLatinUS', + doslatin1 => 'DOSLatin1', cp850 => 'DOSLatin1', + macroman => 'MacRoman', cp10000 => 'MacRoman', mac => 'MacRoman', roman => 'MacRoman', + maclatin2 => 'MacLatin2', cp10029 => 'MacLatin2', + maccyrillic => 'MacCyrillic', cp10007 => 'MacCyrillic', + macgreek => 'MacGreek', cp10006 => 'MacGreek', + macturkish => 'MacTurkish', cp10081 => 'MacTurkish', + macromanian => 'MacRomanian', cp10010 => 'MacRomanian', + maciceland => 'MacIceland', cp10079 => 'MacIceland', + maccroatian => 'MacCroatian', cp10082 => 'MacCroatian', +); + +# default group priority for writing +# (NOTE: tags in groups not specified here will not be written unless +# overridden by the module or specified when writing) +my @defaultWriteGroups = qw(EXIF IPTC XMP MakerNotes Photoshop ICC_Profile CanonVRD Adobe); + +# group hash for ExifTool-generated tags +my %allGroupsExifTool = ( 0 => 'ExifTool', 1 => 'ExifTool', 2 => 'ExifTool' ); + +# special tag names (not used for tag info) +%specialTags = map { $_ => 1 } qw( + TABLE_NAME SHORT_NAME PROCESS_PROC WRITE_PROC CHECK_PROC + GROUPS FORMAT FIRST_ENTRY TAG_PREFIX PRINT_CONV + WRITABLE TABLE_DESC NOTES IS_OFFSET IS_SUBDIR + EXTRACT_UNKNOWN NAMESPACE PREFERRED SRC_TABLE PRIORITY + AVOID WRITE_GROUP LANG_INFO VARS DATAMEMBER + SET_GROUP1 +); + +# headers for various segment types +$exifAPP1hdr = "Exif\0\0"; +$xmpAPP1hdr = "http://ns.adobe.com/xap/1.0/\0"; +$xmpExtAPP1hdr = "http://ns.adobe.com/xmp/extension/\0"; +$psAPP13hdr = "Photoshop 3.0\0"; +$psAPP13old = 'Adobe_Photoshop2.5:'; + +sub DummyWriteProc { return 1; } + +# lookup for user lenses defined in @Image::ExifTool::UserDefined::Lenses +%Image::ExifTool::userLens = ( ); + +# queued plug-in tags to add to lookup +@Image::ExifTool::pluginTags = ( ); +%Image::ExifTool::pluginTags = ( ); + +my %systemTagsNotes = ( + Notes => q{ + extracted only if specifically requested or the SystemTags or RequestAll API + option is set + }, +); + +# tag information for preview image -- this should be used for all +# PreviewImage tags so they are handled properly when reading/writing +%Image::ExifTool::previewImageTagInfo = ( + Name => 'PreviewImage', + Writable => 'undef', + # a value of 'none' is ok... + WriteCheck => '$val eq "none" ? undef : $self->CheckImage(\$val)', + DataTag => 'PreviewImage', + # accept either scalar or scalar reference + RawConv => '$self->ValidateImage(ref $val ? $val : \$val, $tag)', + # we allow preview image to be set to '', but we don't want a zero-length value + # in the IFD, so set it temorarily to 'none'. Note that the length is <= 4, + # so this value will fit in the IFD so the preview fixup won't be generated. + ValueConvInv => '$val eq "" and $val="none"; $val', +); + +# extra tags that aren't truly EXIF tags, but are generated by the script +# Note: any tag in this list with a name corresponding to a Group0 name is +# used to write the entire corresponding directory as a block. +%Image::ExifTool::Extra = ( + GROUPS => { 0 => 'File', 1 => 'File', 2 => 'Image' }, + VARS => { NO_ID => 1 }, # tag ID's aren't meaningful for these tags + WRITE_PROC => \&DummyWriteProc, + Error => { + Priority => 0, + Groups => \%allGroupsExifTool, + Notes => q{ + returns errors that may have occurred while reading or writing a file. Any + Error will prevent the file from being processed. Minor errors may be + downgraded to warnings with the -m or IgnoreMinorErrors option + }, + }, + Warning => { + Priority => 0, + Groups => \%allGroupsExifTool, + Notes => q{ + returns warnings that may have occurred while reading or writing a file. + Use the -a or Duplicates option to see all warnings if more than one + occurred. Minor warnings may be ignored with the -m or IgnoreMinorErrors + option. Minor warnings with a capital "M" in the "[Minor]" designation + indicate that the processing is affected by ignoring the warning + }, + }, + Comment => { + Notes => 'comment embedded in JPEG, GIF89a or PPM/PGM/PBM image', + Writable => 1, + WriteGroup => 'Comment', + Priority => 0, # to preserve order of JPEG COM segments + }, + Directory => { + Groups => { 1 => 'System' }, + Notes => q{ + the directory of the file as specified in the call to ExifTool, or "." if no + directory was specified. May be written to move the file to another + directory that will be created if doesn't already exist + }, + Writable => 1, + WritePseudo => 1, + DelCheck => q{"Can't delete"}, + Protected => 1, + RawConv => '$self->ConvertFileName($val)', + # translate backslashes in directory names and add trailing '/' + ValueConvInv => '$_ = $self->InverseFileName($val); m{[^/]$} and $_ .= "/"; $_', + }, + FileName => { + Groups => { 1 => 'System' }, + Writable => 1, + WritePseudo => 1, + DelCheck => q{"Can't delete"}, + Protected => 1, + Notes => q{ + may be written with a full path name to set FileName and Directory in one + operation. This is such a powerful feature that a TestName tag is provided + to allow dry-run tests before actually writing the file name. See + L for more information on writing the + FileName, Directory and TestName tags + }, + RawConv => '$self->ConvertFileName($val)', + ValueConvInv => '$self->InverseFileName($val)', + }, + FilePath => { + Groups => { 1 => 'System' }, + Notes => q{ + absolute path of source file. Not generated unless specifically requested or + the RequestAll API option is set. Does not support Windows Unicode file + names + }, + }, + TestName => { + Writable => 1, + WritePseudo => 1, + DelCheck => q{"Can't delete"}, + Protected => 1, + WriteOnly => 1, + Notes => q{ + this write-only tag may be used instead of FileName for dry-run tests of the + file renaming feature. Writing this tag prints the old and new file names + to the console, but does not affect the file itself + }, + ValueConvInv => '$self->InverseFileName($val)', + }, + FileSequence => { + Groups => { 0 => 'ExifTool', 1 => 'ExifTool', 2 => 'Other' }, + Notes => q{ + sequence number for each source file when extracting or copying information, + including files that fail the -if condition of the command-line application, + beginning at 0 for the first file. Not generated unless specifically + requested or the RequestAll API option is set + }, + }, + FileSize => { + Groups => { 1 => 'System' }, + Notes => q{ + note that the print conversion for this tag uses historic prefixes: 1 kB = + 1024 bytes, etc. + }, + PrintConv => \&ConvertFileSize, + }, + ResourceForkSize => { + Groups => { 1 => 'System' }, + Notes => q{ + size of the file's resource fork if it contains data. Mac OS only. If this + tag is generated the ExtractEmbedded option may be used to extract + resource-fork information as a sub-document. When writing, the resource + fork is preserved by default, but it may be deleted with C<-rsrc:all=> on + the command line + }, + PrintConv => \&ConvertFileSize, + }, + FileType => { + Notes => q{ + a short description of the file type. For many file types this is the just + the uppercase file extension + }, + }, + FileTypeExtension => { + Notes => q{ + a common lowercase extension for this file type, or uppercase with the -n + option + }, + PrintConv => 'lc $val', + }, + FileModifyDate => { + Description => 'File Modification Date/Time', + Notes => q{ + the filesystem modification date/time. Note that ExifTool may not be able + to handle filesystem dates before 1970 depending on the limitations of the + system's standard libraries + }, + Groups => { 1 => 'System', 2 => 'Time' }, + Writable => 1, + WritePseudo => 1, + DelCheck => q{"Can't delete"}, + # all writable pseudo-tags must be protected so -tagsfromfile fails with + # unrecognized files unless a pseudo tag is specified explicitly + Protected => 1, + Shift => 'Time', + ValueConv => 'ConvertUnixTime($val,1)', + ValueConvInv => 'GetUnixTime($val,1)', + PrintConv => '$self->ConvertDateTime($val)', + PrintConvInv => '$self->InverseDateTime($val)', + }, + FileAccessDate => { + Description => 'File Access Date/Time', + Notes => q{ + the date/time of last access of the file. Note that this access time is + updated whenever any software, including ExifTool, reads the file + }, + Groups => { 1 => 'System', 2 => 'Time' }, + ValueConv => 'ConvertUnixTime($val,1)', + PrintConv => '$self->ConvertDateTime($val)', + }, + FileCreateDate => { + Description => 'File Creation Date/Time', + Notes => q{ + the filesystem creation date/time. Windows/Mac only. In Windows, the file + creation date/time is preserved by default when writing if Win32API::File + and Win32::API are available. On Mac, this tag is extracted only if it or + the MacOS group is specifically requested or the RequestAll API option is + set to 2 or higher. Requires "setfile" for writing on Mac + }, + Groups => { 1 => 'System', 2 => 'Time' }, + Writable => 1, + WritePseudo => 1, + DelCheck => q{"Can't delete"}, + Protected => 1, # all writable pseudo-tags must be protected! + Shift => 'Time', + ValueConv => '$^O eq "darwin" ? $val : ConvertUnixTime($val,1)', + ValueConvInv => q{ + return GetUnixTime($val,1) if $^O eq 'MSWin32'; + return $val if $^O eq 'darwin'; + warn "This tag is Windows/Mac only\n"; + return undef; + }, + PrintConv => '$self->ConvertDateTime($val)', + PrintConvInv => '$self->InverseDateTime($val)', + }, + FileInodeChangeDate => { + Description => 'File Inode Change Date/Time', + Notes => q{ + the date/time when the file's directory information was last changed. + Non-Windows systems only + }, + Groups => { 1 => 'System', 2 => 'Time' }, + ValueConv => 'ConvertUnixTime($val,1)', + PrintConv => '$self->ConvertDateTime($val)', + }, + FilePermissions => { + Groups => { 1 => 'System' }, + Notes => q{ + r=read, w=write and x=execute permissions for the file owner, group and + others. The ValueConv value is an octal number so bit test operations on + this value should be done in octal, eg. 'oct($filePermissions#) & 0200' + }, + Writable => 1, + WritePseudo => 1, + DelCheck => q{"Can't delete"}, + Protected => 1, # all writable pseudo-tags must be protected! + ValueConv => 'sprintf("%.3o", $val & 0777)', + ValueConvInv => 'oct($val)', + PrintConv => sub { + my ($mask, $str, $val) = (0400, '', oct(shift)); + while ($mask) { + foreach (qw(r w x)) { + $str .= $val & $mask ? $_ : '-'; + $mask >>= 1; + } + } + return $str; + }, + PrintConvInv => sub { + my ($bit, $val, $str) = (8, 0, shift); + return undef if length($str) != 9; + while ($bit >= 0) { + foreach (qw(r w x)) { + $val |= (1 << $bit) if substr($str, 8-$bit, 1) eq $_; + --$bit; + } + } + return sprintf('%.3o', $val); + }, + }, + FileAttributes => { + Groups => { 1 => 'System' }, + Notes => q{ + extracted only if specifically requested or the SystemTags or RequestAll API + option is set. 2 or 3 values: 0. File type, 1. Attribute bits, 2. Windows + attribute bits if Win32API::File is available + }, + PrintHex => 1, + PrintConvColumns => 2, + PrintConv => [{ # stat device types (bitmask 0xf000) + 0x0000 => 'Unknown', + 0x1000 => 'FIFO', + 0x2000 => 'Character', + 0x3000 => 'Mux Character', + 0x4000 => 'Directory', + 0x5000 => 'XENIX Named', + 0x6000 => 'Block', + 0x7000 => 'Mux Block', + 0x8000 => 'Regular', + 0x9000 => 'VxFS Compressed', + 0xa000 => 'Symbolic Link', + 0xb000 => 'Solaris Shadow Inode', + 0xc000 => 'Socket', + 0xd000 => 'Solaris Door', + 0xe000 => 'BSD Whiteout', + },{ BITMASK => { # stat attribute bits (bitmask 0x0e00) + 9 => 'Sticky', + 10 => 'Set Group ID', + 11 => 'Set User ID', + }},{ BITMASK => { # Windows attribute bits + 0 => 'Read Only', + 1 => 'Hidden', + 2 => 'System', + 3 => 'Volume Label', + 4 => 'Directory', + 5 => 'Archive', + 6 => 'Device', + 7 => 'Normal', + 8 => 'Temporary', + 9 => 'Sparse File', + 10 => 'Reparse Point', + 11 => 'Compressed', + 12 => 'Offline', + 13 => 'Not Content Indexed', + 14 => 'Encrypted', + }}], + }, + FileDeviceID => { + Groups => { 1 => 'System' }, + %systemTagsNotes, + PrintConv => '(($val >> 24) & 0xff) . "." . ($val & 0xffffff)', # (major.minor) + }, + FileDeviceNumber => { Groups => { 1 => 'System' }, %systemTagsNotes }, + FileInodeNumber => { Groups => { 1 => 'System' }, %systemTagsNotes }, + FileHardLinks => { Groups => { 1 => 'System' }, %systemTagsNotes }, + FileUserID => { + Groups => { 1 => 'System' }, + Notes => q{ + extracted only if specifically requested or the SystemTags or RequestAll API + option is set. Returns user ID number with the -n option, or name + otherwise. May be written with either user name or number + }, + Writable => 1, + WritePseudo => 1, + DelCheck => q{"Can't delete"}, + Protected => 1, # all writable pseudo-tags must be protected! + PrintConv => 'eval { getpwuid($val) } || $val', + PrintConvInv => 'eval { getpwnam($val) } || ($val=~/[^0-9]/ ? undef : $val)', + }, + FileGroupID => { + Groups => { 1 => 'System' }, + Notes => q{ + extracted only if specifically requested or the SystemTags or RequestAll API + option is set. Returns group ID number with the -n option, or name + otherwise. May be written with either group name or number + }, + Writable => 1, + WritePseudo => 1, + DelCheck => q{"Can't delete"}, + Protected => 1, # all writable pseudo-tags must be protected! + PrintConv => 'eval { getgrgid($val) } || $val', + PrintConvInv => 'eval { getgrnam($val) } || ($val=~/[^0-9]/ ? undef : $val)', + }, + FileBlockSize => { Groups => { 1 => 'System' }, %systemTagsNotes }, + FileBlockCount => { Groups => { 1 => 'System' }, %systemTagsNotes }, + HardLink => { + Writable => 1, + DelCheck => q{"Can't delete"}, + WriteOnly => 1, + WritePseudo => 1, + Protected => 1, + Notes => q{ + this write-only tag is used to create a hard link to the file. If the file + is edited, copied, renamed or moved in the same operation as writing + HardLink, then the link is made to the updated file. Note that subsequent + editing of either the linked file or the original by the exiftool + application will break the link unless the -overwrite_original_in_place + option is used + }, + ValueConvInv => '$val=~tr/\\\\/\//; $val', + }, + MIMEType => { Notes => 'the MIME type of the source file' }, + ImageWidth => { Notes => 'the width of the image in number of pixels' }, + ImageHeight => { Notes => 'the height of the image in number of pixels' }, + XResolution => { Notes => 'the horizontal pixel resolution' }, + YResolution => { Notes => 'the vertical pixel resolution' }, + MaxVal => { Notes => 'maximum pixel value in PPM or PGM image' }, + EXIF => { + Notes => q{ + the full EXIF data block from JPEG, PNG, JP2, MIE and MIFF images. This tag + is generated only if specifically requested + }, + Groups => { 0 => 'EXIF', 1 => 'EXIF' }, + Flags => ['Writable' ,'Protected', 'Binary'], + WriteCheck => q{ + return undef if $val =~ /^(II\x2a\0|MM\0\x2a)/; + return 'Invalid EXIF data'; + }, + }, + IPTC => { + Notes => q{ + the full IPTC data block. This tag is generated only if specifically + requested + }, + Groups => { 0 => 'IPTC', 1 => 'IPTC' }, + Flags => ['Writable', 'Protected', 'Binary'], + Priority => 0, # so main IPTC (which hopefully comes first) takes priority + WriteCheck => q{ + return undef if $val =~ /^(\x1c|\0+$)/; + return 'Invalid IPTC data'; + }, + }, + XMP => { + Notes => q{ + the XMP data block, but note that extended XMP in JPEG images may be split + into multiple blocks. This tag is generated only if specifically requested + }, + Groups => { 0 => 'XMP', 1 => 'XMP' }, + Flags => ['Writable', 'Protected', 'Binary'], + Priority => 0, # so main xmp (which usually comes first) takes priority + WriteCheck => q{ + require Image::ExifTool::XMP; + return Image::ExifTool::XMP::CheckXMP($self, $tagInfo, \$val); + }, + }, + ICC_Profile => { + Notes => q{ + the full ICC_Profile data block. This tag is generated only if specifically + requested + }, + Groups => { 0 => 'ICC_Profile', 1 => 'ICC_Profile' }, + Flags => ['Writable' ,'Protected', 'Binary'], + WriteCheck => q{ + require Image::ExifTool::ICC_Profile; + return Image::ExifTool::ICC_Profile::ValidateICC(\$val); + }, + }, + CanonVRD => { + Notes => q{ + the full Canon DPP VRD trailer block. This tag is generated only if + specifically requested + }, + Groups => { 0 => 'CanonVRD', 1 => 'CanonVRD' }, + Flags => ['Writable' ,'Protected', 'Binary'], + Permanent => 0, # (this is 1 by default for MakerNotes tags) + WriteCheck => q{ + return undef if $val =~ /^CANON OPTIONAL DATA\0/; + return 'Invalid CanonVRD data'; + }, + }, + CanonDR4 => { + Notes => q{ + the full Canon DPP version 4 DR4 block. This tag is generated only if + specifically requested + }, + Groups => { 0 => 'CanonVRD', 1 => 'CanonVRD' }, + Flags => ['Writable' ,'Protected', 'Binary'], + Permanent => 0, # (this is 1 by default for MakerNotes tags) + WriteCheck => q{ + return undef if $val =~ /^IIII\x04\0\x04\0/; + return 'Invalid CanonDR4 data'; + }, + }, + Adobe => { + Notes => q{ + the JPEG APP14 Adobe segment. Extracted only if specified. See the + L for more information + }, + Groups => { 0 => 'APP14', 1 => 'Adobe' }, + WriteGroup => 'Adobe', + Flags => ['Writable' ,'Protected', 'Binary'], + }, + CurrentIPTCDigest => { + Notes => q{ + MD5 digest of existing IPTC data. All zeros if IPTC exists but Digest::MD5 + is not installed. Only calculated for IPTC in the standard location as + specified by the L. ExifTool + automates the handling of this tag in the MWG module -- see the + L for details + }, + ValueConv => 'unpack("H*", $val)', + }, + PreviewImage => { + Notes => 'JPEG-format embedded preview image', + Groups => { 2 => 'Preview' }, + Writable => 1, + WriteCheck => '$self->CheckImage(\$val)', + WriteGroup => 'All', + # can't delete, so set to empty string and return no error + DelCheck => '$val = ""; return undef', + # accept either scalar or scalar reference + RawConv => '$self->ValidateImage(ref $val ? $val : \$val, $tag)', + }, + ThumbnailImage => { + Groups => { 2 => 'Preview' }, + Notes => 'JPEG-format embedded thumbnail image', + RawConv => '$self->ValidateImage(ref $val ? $val : \$val, $tag)', + }, + OtherImage => { + Groups => { 2 => 'Preview' }, + Notes => 'other JPEG-format embedded image', + RawConv => '$self->ValidateImage(ref $val ? $val : \$val, $tag)', + }, + PreviewPNG => { + Groups => { 2 => 'Preview' }, + Notes => 'PNG-format embedded preview image', + Binary => 1, + }, + PreviewWMF => { + Groups => { 2 => 'Preview' }, + Notes => 'WMF-format embedded preview image', + Binary => 1, + }, + PreviewTIFF => { + Groups => { 2 => 'Preview' }, + Notes => 'TIFF-format embedded preview image', + Binary => 1, + }, + PreviewPDF => { + Groups => { 2 => 'Preview' }, + Notes => 'PDF-format embedded preview image', + Binary => 1, + }, + ExifByteOrder => { + Writable => 1, + DelCheck => q{"Can't delete"}, + Notes => q{ + represents the byte order of EXIF information. May be written to set the + byte order only for newly created EXIF segments + }, + PrintConv => { + II => 'Little-endian (Intel, II)', + MM => 'Big-endian (Motorola, MM)', + }, + }, + ExifUnicodeByteOrder => { + Writable => 1, + WriteOnly => 1, + DelCheck => q{"Can't delete"}, + Notes => q{ + specifies the byte order to use when writing EXIF Unicode text. The EXIF + specification is particularly vague about this byte ordering, and different + applications use different conventions. By default ExifTool writes Unicode + text in EXIF byte order, but this write-only tag may be used to force a + specific order. Applies to the EXIF UserComment tag when writing special + characters + }, + PrintConv => { + II => 'Little-endian (Intel, II)', + MM => 'Big-endian (Motorola, MM)', + }, + }, + ExifToolVersion => { + Description => 'ExifTool Version Number', + Groups => \%allGroupsExifTool, + Notes => 'the version of ExifTool currently running', + }, + ProcessingTime => { + Groups => { 0 => 'ExifTool', 1 => 'ExifTool', 2 => 'Other' }, + Notes => q{ + the clock time in seconds taken by ExifTool to extract information from this + file. Not generated unless specifically requested or the RequestAll API + option is set. Requires Time::HiRes + }, + PrintConv => 'sprintf("%.3g s", $val)', + }, + RAFVersion => { Notes => 'RAF file version number' }, + JPEGDigest => { + Notes => q{ + an MD5 digest of the JPEG quantization tables is combined with the component + sub-sampling values to generate the value of this tag. The result is + compared to known values in an attempt to deduce the originating software + based only on the JPEG image data. For performance reasons, this tag is + generated only if specifically requested or the RequestAll API option is set + to 3 or higher + }, + }, + JPEGQualityEstimate => { + Notes => q{ + an estimate of the IJG JPEG quality setting for the image, calculated from + the quantization tables. For performance reasons, this tag is generated + only if specifically requested or the RequestAll API option is set to 3 or + higher + }, + }, + # Validate (added from Validate.pm) + Now => { + Groups => { 0 => 'ExifTool', 1 => 'ExifTool', 2 => 'Time' }, + Notes => q{ + the current date/time. Useful when setting the tag values, eg. + C<"-modifydate. Not generated unless specifically requested or the + RequestAll API option is set + }, + PrintConv => '$self->ConvertDateTime($val)', + }, + NewGUID => { + Groups => { 0 => 'ExifTool', 1 => 'ExifTool', 2 => 'Other' }, + Notes => q{ + generates a new, random GUID with format + YYYYmmdd-HHMM-SSNN-PPPP-RRRRRRRRRRRR, where Y=year, m=month, d=day, H=hour, + M=minute, S=second, N=file sequence number in hex, P=process ID in hex, and + R=random hex number; without dashes with the -n option. Not generated + unless specifically requested or the RequestAll API option is set + }, + PrintConv => '$val =~ s/(.{8})(.{4})(.{4})(.{4})/$1-$2-$3-$4-/; $val', + }, + ID3Size => { Notes => 'size of the ID3 data block' }, + Geotag => { + Writable => 1, + WriteOnly => 1, + WriteNothing => 1, + AllowGroup => '(exif|gps|xmp|xmp-exif)', + Notes => q{ + this write-only tag is used to define the GPS track log data or track log + file name. Currently supported track log formats are GPX, NMEA RMC/GGA/GLL, + KML, IGC, Garmin XML and TCX, Magellan PMGNTRK, Honeywell PTNTHPR, Winplus + Beacon text, and Bramor gEO log files. May be set to the special value of + "DATETIMEONLY" (all caps) to set GPS date/time tags if no input track points + are available. See L for details + }, + DelCheck => q{ + require Image::ExifTool::Geotag; + # delete associated tags + Image::ExifTool::Geotag::SetGeoValues($self, undef, $wantGroup); + }, + ValueConvInv => q{ + require Image::ExifTool::Geotag; + # always warn because this tag is never set (warning is "\n" on success) + my $result = Image::ExifTool::Geotag::LoadTrackLog($self, $val); + return '' if not defined $result; # deleting geo tags + return $result if ref $result; # geotag data hash reference + warn "$result\n"; # error string + }, + }, + Geotime => { + Writable => 1, + WriteOnly => 1, + AllowGroup => '(exif|gps|xmp|xmp-exif)', + Notes => q{ + this write-only tag is used to define a date/time for interpolating a + position in the GPS track specified by the Geotag tag. Writing this tag + causes GPS information to be written into the EXIF or XMP of the target + files. The local system timezone is assumed if the date/time value does not + contain a timezone. May be deleted to delete associated GPS tags. A group + name of 'EXIF' or 'XMP' may be specified to write or delete only EXIF or XMP + GPS tags + }, + DelCheck => q{ + require Image::ExifTool::Geotag; + # delete associated tags + Image::ExifTool::Geotag::SetGeoValues($self, undef, $wantGroup); + }, + ValueConvInv => q{ + require Image::ExifTool::Geotag; + warn Image::ExifTool::Geotag::SetGeoValues($self, $val, $wantGroup) . "\n"; + return undef; + }, + }, + Geosync => { + Writable => 1, + WriteOnly => 1, + WriteNothing => 1, + AllowGroup => '(exif|gps|xmp|xmp-exif)', + Shift => 'Time', # enables "+=" syntax as well as "=+" + Notes => q{ + this write-only tag specifies a time difference to add to Geotime for + synchronization with the GPS clock. For example, set this to "-12" if the + camera clock is 12 seconds faster than GPS time. Input format is + "[+-][[[DD ]HH:]MM:]SS[.ss]". Additional features allow calculation of time + differences and time drifts, and extraction of synchronization times from + image files. See the L for details + }, + ValueConvInv => q{ + require Image::ExifTool::Geotag; + return Image::ExifTool::Geotag::ConvertGeosync($self, $val); + }, + }, + ForceWrite => { + Groups => { 0 => '*', 1 => '*', 2 => '*' }, + Writable => 1, + WriteOnly => 1, + Notes => q{ + write-only tag used to force EXIF, IPTC and/or XMP in a file to be + rewritten. May be set to "EXIF", "IPTC" or "XMP" to force the corresponding + metadata type to be rewritten, "FixBase" to cause EXIF to be rewritten only if + the MakerNotes offset base was fixed, or "All" to rewrite all of these metadata + types. Values are case insensitive, and multiple values may be separated with + commas, eg. C<-ForceWrite=exif,xmp> + }, + }, +); + +# YCbCrSubSampling values (used by JPEG SOF, EXIF and XMP) +%Image::ExifTool::JPEG::yCbCrSubSampling = ( + '1 1' => 'YCbCr4:4:4 (1 1)', #PH + '2 1' => 'YCbCr4:2:2 (2 1)', #14 in Exif.pm + '2 2' => 'YCbCr4:2:0 (2 2)', #14 in Exif.pm + '4 1' => 'YCbCr4:1:1 (4 1)', #14 in Exif.pm + '4 2' => 'YCbCr4:1:0 (4 2)', #PH + '1 2' => 'YCbCr4:4:0 (1 2)', #PH + '1 4' => 'YCbCr4:4:1 (1 4)', #JD + '2 4' => 'YCbCr4:2:1 (2 4)', #JD +); + +# define common JPEG segments here to avoid overhead of loading JPEG module + +# JPEG SOF (start of frame) tags +# (ref http://www.w3.org/Graphics/JPEG/itu-t81.pdf) +%Image::ExifTool::JPEG::SOF = ( + GROUPS => { 0 => 'File', 1 => 'File', 2 => 'Image' }, + NOTES => 'This information is extracted from the JPEG Start Of Frame segment.', + VARS => { NO_ID => 1 }, # tag ID's aren't meaningful for these tags + EncodingProcess => { + PrintHex => 1, + PrintConv => { + 0x0 => 'Baseline DCT, Huffman coding', + 0x1 => 'Extended sequential DCT, Huffman coding', + 0x2 => 'Progressive DCT, Huffman coding', + 0x3 => 'Lossless, Huffman coding', + 0x5 => 'Sequential DCT, differential Huffman coding', + 0x6 => 'Progressive DCT, differential Huffman coding', + 0x7 => 'Lossless, Differential Huffman coding', + 0x9 => 'Extended sequential DCT, arithmetic coding', + 0xa => 'Progressive DCT, arithmetic coding', + 0xb => 'Lossless, arithmetic coding', + 0xd => 'Sequential DCT, differential arithmetic coding', + 0xe => 'Progressive DCT, differential arithmetic coding', + 0xf => 'Lossless, differential arithmetic coding', + } + }, + BitsPerSample => { }, + ImageHeight => { }, + ImageWidth => { }, + ColorComponents => { }, + YCbCrSubSampling => { + Notes => 'calculated from components table', + PrintConv => \%Image::ExifTool::JPEG::yCbCrSubSampling, + }, +); + +# JPEG JFIF APP0 definitions +%Image::ExifTool::JFIF::Main = ( + PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData, + WRITE_PROC => \&Image::ExifTool::WriteBinaryData, + CHECK_PROC => \&Image::ExifTool::CheckBinaryData, + GROUPS => { 0 => 'JFIF', 1 => 'JFIF', 2 => 'Image' }, + DATAMEMBER => [ 2, 3, 5 ], + 0 => { + Name => 'JFIFVersion', + Format => 'int8u[2]', + PrintConv => 'sprintf("%d.%.2d", split(" ",$val))', + Mandatory => 1, + }, + 2 => { + Name => 'ResolutionUnit', + Writable => 1, + RawConv => '$$self{JFIFResolutionUnit} = $val', + PrintConv => { + 0 => 'None', + 1 => 'inches', + 2 => 'cm', + }, + Priority => -1, + Mandatory => 1, + }, + 3 => { + Name => 'XResolution', + Format => 'int16u', + Writable => 1, + Priority => -1, + RawConv => '$$self{JFIFXResolution} = $val', + Mandatory => 1, + }, + 5 => { + Name => 'YResolution', + Format => 'int16u', + Writable => 1, + Priority => -1, + RawConv => '$$self{JFIFYResolution} = $val', + Mandatory => 1, + }, + 7 => { + Name => 'ThumbnailWidth', + RawConv => '$val ? $$self{JFIFThumbnailWidth} = $val : undef', + }, + 8 => { + Name => 'ThumbnailHeight', + RawConv => '$val ? $$self{JFIFThumbnailHeight} = $val : undef', + }, + 9 => { + Name => 'ThumbnailTIFF', + Groups => { 2 => 'Preview' }, + Format => 'undef[3*($val{7}||0)*($val{8}||0)]', + Notes => 'raw RGB thumbnail data, extracted as a TIFF image', + RawConv => 'length($val) ? $val : undef', + ValueConv => sub { + my ($val, $et) = @_; + my $len = length $val; + return \ "Binary data $len bytes" unless $et->Options('Binary'); + my $img = MakeTiffHeader($$et{JFIFThumbnailWidth},$$et{JFIFThumbnailHeight},3,8) . $val; + return \$img; + }, + }, +); +%Image::ExifTool::JFIF::Extension = ( + GROUPS => { 0 => 'JFIF', 1 => 'JFXX', 2 => 'Image' }, + NOTES => 'Thumbnail images extracted from the JFXX segment.', + 0x10 => { + Name => 'ThumbnailImage', + Groups => { 2 => 'Preview' }, + Notes => 'JPEG-format thumbnail image', + RawConv => '$self->ValidateImage(\$val,$tag)', + }, + 0x11 => { # (untested) + Name => 'ThumbnailTIFF', + Groups => { 2 => 'Preview' }, + Notes => 'raw palette-color thumbnail data, extracted as a TIFF image', + RawConv => '(length $val > 770 and $val !~ /^\0\0/) ? $val : undef', + ValueConv => sub { + my ($val, $et) = @_; + my $len = length $val; + return \ "Binary data $len bytes" unless $et->Options('Binary'); + my ($w, $h) = unpack('CC', $val); + my $img = MakeTiffHeader($w,$h,1,8,undef,substr($val,2,768)) . substr($val,770); + return \$img; + }, + }, + 0x13 => { + Name => 'ThumbnailTIFF', + Groups => { 2 => 'Preview' }, + Notes => 'raw RGB thumbnail data, extracted as a TIFF image', + RawConv => '(length $val > 2 and $val !~ /^\0\0/) ? $val : undef', + ValueConv => sub { + my ($val, $et) = @_; + my $len = length $val; + return \ "Binary data $len bytes" unless $et->Options('Binary'); + my ($w, $h) = unpack('CC', $val); + my $img = MakeTiffHeader($w,$h,3,8) . substr($val,2); + return \$img; + }, + }, +); + +# Composite tags (accumulation of all Composite tag tables) +%Image::ExifTool::Composite = ( + GROUPS => { 0 => 'Composite', 1 => 'Composite' }, + TABLE_NAME => 'Image::ExifTool::Composite', + SHORT_NAME => 'Composite', + VARS => { NO_ID => 1 }, # want empty tagID's for Composite tags + WRITE_PROC => \&DummyWriteProc, +); + +# static private ExifTool variables + +%allTables = ( ); # list of all tables loaded (except Composite tags) +@tableOrder = ( ); # order the tables were loaded + +#------------------------------------------------------------------------------ +# Warning handler routines (warning string stored in $evalWarning) +# +# Set warning message +# Inputs: 0) warning string (undef to reset warning) +sub SetWarning($) { $evalWarning = $_[0]; } + +# Get warning message +sub GetWarning() { return $evalWarning; } + +# Clean unnecessary information (line number, LF) from warning +# Inputs: 0) warning string or undef to use $evalWarning +# Returns: cleaned warning +sub CleanWarning(;$) +{ + my $str = shift; + unless (defined $str) { + return undef unless defined $evalWarning; + $str = $evalWarning; + } + $str = $1 if $str =~ /(.*) at /s; + $str =~ s/\s+$//s; + return $str; +} + +#============================================================================== +# New - create new ExifTool object +# Inputs: 0) reference to exiftool object or ExifTool class name +# Returns: blessed ExifTool object ref +sub new +{ + local $_; + my $that = shift; + my $class = ref($that) || $that || 'Image::ExifTool'; + my $self = bless {}, $class; + + # make sure our main Exif tag table has been loaded + GetTagTable("Image::ExifTool::Exif::Main"); + + $self->ClearOptions(); # create default options hash + $$self{VALUE} = { }; # must initialize this for warning messages + $$self{PATH} = [ ]; # (this too) + $$self{DEL_GROUP} = { }; # lookup for groups to delete when writing + $$self{SAVE_COUNT} = 0; # count calls to SaveNewValues() + $$self{FILE_SEQUENCE} = 0; # sequence number for files when reading + + # initialize our new groups for writing + $self->SetNewGroups(@defaultWriteGroups); + + return $self; +} + +#------------------------------------------------------------------------------ +# ImageInfo - return specified information from image file +# Inputs: 0) [optional] ExifTool object reference +# 1) filename, file reference, or scalar data reference +# 2-N) list of tag names to find (or tag list reference or options reference) +# Returns: reference to hash of tag/value pairs (with "Error" entry on error) +# Notes: +# - if no tags names are specified, the values of all tags are returned +# - tags may be specified with leading '-' to exclude, or trailing '#' for ValueConv +# - can pass a reference to list of tags to find, in which case the list will +# be updated with the tags found in the proper case and in the specified order. +# - can pass reference to hash specifying options +# - returned tag values may be scalar references indicating binary data +# - see ClearOptions() below for a list of options and their default values +# Examples: +# use Image::ExifTool 'ImageInfo'; +# my $info = ImageInfo($file, 'DateTimeOriginal', 'ImageSize'); +# - or - +# my $et = new Image::ExifTool; +# my $info = $et->ImageInfo($file, \@tagList, {Sort=>'Group0'} ); +sub ImageInfo($;@) +{ + local $_; + # get our ExifTool object ($self) or create one if necessary + my $self; + if (ref $_[0] and UNIVERSAL::isa($_[0],'Image::ExifTool')) { + $self = shift; + } else { + $self = new Image::ExifTool; + } + my %saveOptions = %{$$self{OPTIONS}}; # save original options + + # initialize file information + $$self{FILENAME} = $$self{RAF} = undef; + + $self->ParseArguments(@_); # parse our function arguments + $self->ExtractInfo(undef); # extract meta information from image + my $info = $self->GetInfo(undef); # get requested information + + $$self{OPTIONS} = \%saveOptions; # restore original options + + return $info; # return requested information +} + +#------------------------------------------------------------------------------ +# Get/set ExifTool options +# Inputs: 0) ExifTool object reference, +# 1) Parameter name (case insensitive), 2) Value to set the option +# 3-N) More parameter/value pairs +# Returns: original value of last option specified +sub Options($$;@) +{ + local $_; + my $self = shift; + my $options = $$self{OPTIONS}; + my $oldVal; + + while (@_) { + my $param = shift; + # fix parameter case if necessary + unless (exists $$options{$param}) { + my ($fixed) = grep /^$param$/i, keys %$options; + if ($fixed) { + $param = $fixed; + } else { + $param =~ s/^Group(\d*)$/Group$1/i; + } + } + $oldVal = $$options{$param}; + last unless @_; + my $newVal = shift; + if ($param eq 'Lang') { + # allow this to be set to undef to select the default language + $newVal = $defaultLang unless defined $newVal; + if ($newVal eq $defaultLang) { + $$options{$param} = $newVal; + delete $$self{CUR_LANG}; + # make sure the language is available + } elsif (eval "require Image::ExifTool::Lang::$newVal") { + my $xlat = "Image::ExifTool::Lang::${newVal}::Translate"; + no strict 'refs'; + if (%$xlat) { + $$self{CUR_LANG} = \%$xlat; + $$options{$param} = $newVal; + } + } # else don't change Lang + } elsif ($param eq 'Exclude' and defined $newVal) { + # clone Exclude list and expand shortcuts + my @exclude; + if (ref $newVal eq 'ARRAY') { + @exclude = @$newVal; + } else { + @exclude = ($newVal); + } + ExpandShortcuts(\@exclude, 1); # (also remove '#' suffix) + $$options{$param} = \@exclude; + } elsif ($param =~ /^Charset/ or $param eq 'IPTCCharset') { + # only allow valid character sets to be set + if ($newVal) { + my $charset = $charsetName{lc $newVal}; + if ($charset) { + $$options{$param} = $charset; + # maintain backward-compatibility with old IPTCCharset option + $$options{CharsetIPTC} = $charset if $param eq 'IPTCCharset'; + } else { + warn "Invalid Charset $newVal\n"; + } + } elsif ($param eq 'CharsetEXIF' or $param eq 'CharsetFileName' or $param eq 'CharsetRIFF') { + $$options{$param} = $newVal; # only these may be set to a false value + } elsif ($param eq 'CharsetQuickTime') { + $$options{$param} = 'MacRoman'; # QuickTime defaults to MacRoman + } else { + $$options{$param} = 'Latin'; # all others default to Latin + } + } elsif ($param eq 'UserParam') { + # clear options if $newVal is undef + defined $newVal or $$options{$param} = {}, next; + # allow initialization of entire UserParam hash + if (ref $newVal eq 'HASH') { + my %newParams; + $newParams{lc $_} = $$newVal{$_} foreach sort keys %$newVal; + $$options{$param} = \%newParams; + next; + } + my $force; + # set/reset single UserParam parameter + if ($newVal =~ /(.*?)=(.*)/s) { + $param = lc $1; + $newVal = $2; + $force = 1 if $param =~ s/\^$//; + } else { + $param = lc $newVal; + undef $newVal; + } + $oldVal = $$options{UserParam}{$param}; + if (defined $newVal) { + if (length $newVal or $force) { + $$options{UserParam}{$param} = $newVal; + } else { + delete $$options{UserParam}{$param}; + } + } + } elsif ($param eq 'RequestTags') { + if (defined $newVal) { + # parse list from delimited string if necessary + my @reqList = (ref $newVal eq 'ARRAY') ? @$newVal : ($newVal =~ /[-\w?*:]+/g); + ExpandShortcuts(\@reqList); + # add to existing list + $$options{$param} or $$options{$param} = [ ]; + foreach (@reqList) { + /^(.*:)?([-\w?*]*)#?$/ or next; + push @{$$options{$param}}, lc($2) if $2; + next unless $1; + push @{$$options{$param}}, lc($_).':' foreach split /:/, $1; + } + } else { + $$options{$param} = undef; # clear the list + } + } elsif ($param eq 'ListJoin') { + $$options{$param} = $newVal; + # ListJoin just sets the List and ListSep options for backward compatibility + if (defined $newVal) { + $$options{List} = 0; + $$options{ListSep} = $newVal; + } else { + $$options{List} = 1; + # (ListSep must be defined) + } + } else { + if ($param eq 'Escape') { + # set ESCAPE_PROC + if (defined $newVal and $newVal eq 'XML') { + require Image::ExifTool::XMP; + $$self{ESCAPE_PROC} = \&Image::ExifTool::XMP::EscapeXML; + } elsif (defined $newVal and $newVal eq 'HTML') { + require Image::ExifTool::HTML; + $$self{ESCAPE_PROC} = \&Image::ExifTool::HTML::EscapeHTML; + } else { + delete $$self{ESCAPE_PROC}; + } + # must forget saved values since they depend on Escape method + $$self{BOTH} = { }; + } elsif ($param eq 'GlobalTimeShift') { + delete $$self{GLOBAL_TIME_OFFSET}; # reset our calculated offset + } elsif ($param eq 'TimeZone' and defined $newVal and length $newVal) { + $ENV{TZ} = $newVal; + eval { require POSIX; POSIX::tzset() }; + } elsif ($param eq 'Validate') { + # load Validate module if Validate option enabled + $newVal and require Image::ExifTool::Validate; + } + $$options{$param} = $newVal; + } + } + return $oldVal; +} + +#------------------------------------------------------------------------------ +# ClearOptions - set options to default values +# Inputs: 0) ExifTool object reference +sub ClearOptions($) +{ + local $_; + my $self = shift; + + # create options hash with default values + # +-----------------------------------------------------+ + # ! DON'T FORGET!! When adding any new option, must ! + # ! decide how it is handled in SetNewValuesFromFile() ! + # +-----------------------------------------------------+ + # (Note: All options must exist in this lookup, even if undefined, + # to facilitate case-insensitive options. 'Group#' is handled specially) + $$self{OPTIONS} = { + Binary => undef, # flag to extract binary values even if tag not specified + ByteOrder => undef, # default byte order when creating EXIF information + Charset => 'UTF8', # character set for converting Unicode characters + CharsetEXIF => undef, # internal EXIF "ASCII" string encoding + CharsetFileName => undef, # external encoding for file names + CharsetID3 => 'Latin', # internal ID3v1 character set + CharsetIPTC => 'Latin', # fallback IPTC character set if no CodedCharacterSet + CharsetPhotoshop => 'Latin', # internal encoding for Photoshop resource names + CharsetQuickTime => 'MacRoman', # internal QuickTime string encoding + CharsetRIFF => 0, # internal RIFF string encoding (0=default to Latin) + Compact => undef, # compact XMP and IPTC data + Composite => 1, # flag to calculate Composite tags + Compress => undef, # flag to write new values as compressed if possible + CoordFormat => undef, # GPS lat/long coordinate format + DateFormat => undef, # format for date/time + Duplicates => 1, # flag to save duplicate tag values + Escape => undef, # escape special characters + Exclude => undef, # tags to exclude + ExtendedXMP => 1, # strategy for reading extended XMP + ExtractEmbedded =>undef,# flag to extract information from embedded documents + FastScan => undef, # flag to avoid scanning for trailer + Filter => undef, # output filter for all tag values + FixBase => undef, # fix maker notes base offsets + GeoMaxIntSecs => 1800, # geotag maximum interpolation time (secs) + GeoMaxExtSecs => 1800, # geotag maximum extrapolation time (secs) + GeoMaxHDOP => undef, # geotag maximum HDOP + GeoMaxPDOP => undef, # geotag maximum PDOP + GeoMinSats => undef, # geotag minimum satellites + GeoSpeedRef => undef, # geotag GPSSpeedRef + GlobalTimeShift => undef, # apply time shift to all extracted date/time values + # Group# => undef, # return tags for specified groups in family # + HtmlDump => 0, # HTML dump (0-3, higher # = bigger limit) + HtmlDumpBase => undef, # base address for HTML dump + IgnoreMinorErrors => undef, # ignore minor errors when reading/writing + Lang => $defaultLang,# localized language for descriptions etc + LargeFileSupport => undef, # flag indicating support of 64-bit file offsets + List => undef, # extract lists of PrintConv values into arrays [no longer documented] + ListItem => undef, # used to return a specific item from lists + ListJoin => ', ', # join lists together with this separator + ListSep => ', ', # list item separator [no longer documented] + ListSplit => undef, # regex for splitting list-type tag values when writing + MakerNotes => undef, # extract maker notes as a block + MDItemTags => undef, # extract MacOS metadata item tags + MissingTagValue =>undef,# value for missing tags when expanded in expressions + NoPDFList => undef, # flag to avoid splitting PDF List-type tag values + Password => undef, # password for password-protected PDF documents + PNGEarlyXMP => undef, # write XMP in PNG images before IDAT chunk + PrintConv => 1, # flag to enable print conversion + QuickTimeUTC=> undef, # assume that QuickTime date/time tags are stored as UTC + RequestAll => undef, # extract all tags that must be specifically requested + RequestTags => undef, # extra tags to request (on top of those in the tag list) + SavePath => undef, # (undocumented) save family 5 location path + ScanForXMP => undef, # flag to scan for XMP information in all files + Sort => 'Input', # order to sort found tags (Input, File, Tag, Descr, Group#) + Sort2 => 'File', # secondary sort order for tags in a group (File, Tag, Descr) + StrictDate => undef, # flag to return undef for invalid date conversions + Struct => undef, # return structures as hash references + SystemTags => undef, # extract additional File System tags + TextOut => \*STDOUT,# file for Verbose/HtmlDump output + TimeZone => undef, # local time zone + Unknown => 0, # flag to get values of unknown tags (0-2) + UserParam => { }, # user parameters for InsertTagValues() + Validate => undef, # perform additional validation + Verbose => 0, # print verbose messages (0-5, higher # = more verbose) + WriteMode => 'wcg', # enable all write modes by default + XAttrTags => undef, # extract MacOS extended attribute tags + XMPAutoConv => 1, # automatic conversion of unknown XMP tag values + }; + # keep necessary member variables in sync with options + delete $$self{CUR_LANG}; + delete $$self{ESCAPE_PROC}; + + # load user-defined default options + if (%Image::ExifTool::UserDefined::Options) { + foreach (keys %Image::ExifTool::UserDefined::Options) { + $self->Options($_, $Image::ExifTool::UserDefined::Options{$_}); + } + } +} + +#------------------------------------------------------------------------------ +# Extract meta information from image +# Inputs: 0) ExifTool object reference +# 1-N) Same as ImageInfo() +# Returns: 1 if this was a valid image, 0 otherwise +# Notes: pass an undefined value to avoid parsing arguments +# Internal 'ReEntry' option allows this routine to be called recursively +sub ExtractInfo($;@) +{ + local $_; + my $self = shift; + my $options = $$self{OPTIONS}; # pointer to current options + my $fast = $$options{FastScan}; + my $req = $$self{REQ_TAG_LOOKUP}; + my $reqAll = $$options{RequestAll} || 0; + my (%saveOptions, $reEntry, $rsize, $type, @startTime); + + # check for internal ReEntry option to allow recursive calls to ExtractInfo + if (ref $_[1] eq 'HASH' and $_[1]{ReEntry} and + (ref $_[0] eq 'SCALAR' or ref $_[0] eq 'GLOB')) + { + # save necessary members for restoring later + $reEntry = { + RAF => $$self{RAF}, + PROCESSED => $$self{PROCESSED}, + EXIF_DATA => $$self{EXIF_DATA}, + EXIF_POS => $$self{EXIF_POS}, + FILE_TYPE => $$self{FILE_TYPE}, + }; + $$self{RAF} = new File::RandomAccess($_[0]); + $$self{PROCESSED} = { }; + delete $$self{EXIF_DATA}; + delete $$self{EXIF_POS}; + } else { + if (defined $_[0] or $$options{HtmlDump} or $$req{validate}) { + %saveOptions = %$options; # save original options + + # require duplicates for html dump + $self->Options(Duplicates => 1) if $$options{HtmlDump}; + # enable Validate option if Validate tag is requested + $self->Options(Validate => 1) if $$req{validate}; + + if (defined $_[0]) { + # only initialize filename if called with arguments + $$self{FILENAME} = undef; # name of file (or '' if we didn't open it) + $$self{RAF} = undef; # RandomAccess object reference + + $self->ParseArguments(@_); # initialize from our arguments + } + } + # initialize ExifTool object members + $self->Init(); + + delete $$self{MAKER_NOTE_FIXUP}; # fixup information for extracted maker notes + delete $$self{MAKER_NOTE_BYTE_ORDER}; + + # return our version number + $self->FoundTag('ExifToolVersion', "$VERSION$RELEASE"); + $self->FoundTag('Now', $self->TimeNow()) if $$req{now} or $reqAll; + $self->FoundTag('NewGUID', NewGUID()) if $$req{newguid} or $reqAll; + # generate sequence number if necessary + $self->FoundTag('FileSequence', $$self{FILE_SEQUENCE}) if $$req{filesequence} or $reqAll; + + if ($$req{processingtime} or $reqAll) { + eval { require Time::HiRes; @startTime = Time::HiRes::gettimeofday() }; + if (not @startTime and $$req{processingtime}) { + $self->WarnOnce('Install Time::HiRes to generate ProcessingTime'); + } + } + + ++$$self{FILE_SEQUENCE}; # count files read + } + + my $filename = $$self{FILENAME}; # image file name ('' if already open) + my $raf = $$self{RAF}; # RandomAccess object + + local *EXIFTOOL_FILE; # avoid clashes with global namespace + + my $realname = $filename; + unless ($raf) { + # save file name + if (defined $filename and $filename ne '') { + unless ($filename eq '-') { + # extract file name from pipe if necessary + $realname =~ /\|$/ and $realname =~ s/^.*?"(.*?)".*/$1/s; + my ($dir, $name); + if (eval { require File::Basename }) { + $dir = File::Basename::dirname($realname); + $name = File::Basename::basename($realname); + } else { + ($name = $realname) =~ tr/\\/\//; + # remove path + $dir = length($1) ? $1 : '/' if $name =~ s/(.*)\///; + } + $self->FoundTag('FileName', $name); + $self->FoundTag('Directory', $dir) if defined $dir and length $dir; + if ($$req{filepath} or + ($reqAll and not $$self{EXCL_TAG_LOOKUP}{filepath})) + { + local $SIG{'__WARN__'} = \&SetWarning; + if (eval { require Cwd }) { + my $path = eval { Cwd::abs_path($filename) }; + $self->FoundTag('FilePath', $path) if defined $path; + } elsif ($$req{filepath}) { + $self->WarnOnce('The Perl Cwd module must be installed to use FilePath'); + } + } + # get size of resource fork on Mac OS + $rsize = -s "$filename/..namedfork/rsrc" if $^O eq 'darwin' and not $$self{IN_RESOURCE}; + } + # open the file + if ($self->Open(\*EXIFTOOL_FILE, $filename)) { + # create random access file object + $raf = new File::RandomAccess(\*EXIFTOOL_FILE); + # patch to force pipe to be buffered because seek returns success + # in Windows cmd shell pipe even though it really failed + $$raf{TESTED} = -1 if $filename eq '-' or $filename =~ /\|$/; + $$self{RAF} = $raf; + } else { + $self->Error('Error opening file'); + } + } else { + $self->Error('No file specified'); + } + } + + while ($raf) { + my (@stat, $fileSize); + if ($reEntry) { + # we already set these tags + } elsif (not $$raf{FILE_PT}) { + # get file size from image in memory + $self->FoundTag('FileSize', length ${$$raf{BUFF_PT}}); + } elsif (-f $$raf{FILE_PT}) { + # get file tags if this is a plain file + $fileSize = -s _; + @stat = stat _; + my ($aTime, $mTime, $cTime) = $self->GetFileTime($$raf{FILE_PT}); + $self->FoundTag('FileSize', $fileSize) if defined $fileSize; + $self->FoundTag('ResourceForkSize', $rsize) if $rsize; + $self->FoundTag('FileModifyDate', $mTime) if defined $mTime; + $self->FoundTag('FileAccessDate', $aTime) if defined $aTime; + my $cTag = $^O eq 'MSWin32' ? 'FileCreateDate' : 'FileInodeChangeDate'; + $self->FoundTag($cTag, $cTime) if defined $cTime; + $self->FoundTag('FilePermissions', $stat[2]) if defined $stat[2]; + } else { + @stat = stat $$raf{FILE_PT}; + } + # extract more system info if SystemTags option is set + if (@stat) { + my $sys = $$options{SystemTags} || ($reqAll and not defined $$options{SystemTags}); + if ($sys or $$req{fileattributes}) { + my @attr = ($stat[2] & 0xf000, $stat[2] & 0x0e00); + # add Windows file attributes if available + if ($^O eq 'MSWin32' and defined $filename and $filename ne '' and $filename ne '-') { + local $SIG{'__WARN__'} = \&SetWarning; + if (eval { require Win32API::File }) { + my $wattr; + my $file = $filename; + if ($self->EncodeFileName($file)) { + $wattr = eval { Win32API::File::GetFileAttributesW($file) }; + } else { + $wattr = eval { Win32API::File::GetFileAttributes($file) }; + } + push @attr, $wattr if defined $wattr and $wattr != 0xffffffff; + } + } + $self->FoundTag('FileAttributes', "@attr"); + } + $self->FoundTag('FileDeviceNumber', $stat[0]) if $sys or $$req{filedevicenumber}; + $self->FoundTag('FileInodeNumber', $stat[1]) if $sys or $$req{fileinodenumber}; + $self->FoundTag('FileHardLinks', $stat[3]) if $sys or $$req{filehardlinks}; + $self->FoundTag('FileUserID', $stat[4]) if $sys or $$req{fileuserid}; + $self->FoundTag('FileGroupID', $stat[5]) if $sys or $$req{filegroupid}; + $self->FoundTag('FileDeviceID', $stat[6]) if $sys or $$req{filedeviceid}; + $self->FoundTag('FileBlockSize', $stat[11]) if $sys or $$req{fileblocksize}; + $self->FoundTag('FileBlockCount', $stat[12]) if $sys or $$req{fileblockcount}; + } + # extract MDItem tags if requested (only on plain files) + if ($^O eq 'darwin' and defined $filename and $filename ne '' and defined $fileSize) { + my $reqMacOS = ($reqAll > 1 or $$req{'macos:'}); + my $crDate = ($reqMacOS || $$req{filecreatedate}); + my $mdItem = ($reqMacOS || $$options{MDItemTags} || grep /^mditem/, keys %$req); + my $xattr = ($reqMacOS || $$options{XAttrTags} || grep /^xattr/, keys %$req); + if ($crDate or $mdItem or $xattr) { + require Image::ExifTool::MacOS; + Image::ExifTool::MacOS::GetFileCreateDate($self, $filename) if $crDate; + Image::ExifTool::MacOS::ExtractMDItemTags($self, $filename) if $mdItem; + Image::ExifTool::MacOS::ExtractXAttrTags($self, $filename) if $xattr; + } + } + + # get list of file types to check + my ($tiffType, %noMagic, $recognizedExt); + my $ext = $$self{FILE_EXT} = GetFileExtension($realname); + # set $recognizedExt if this file type is recognized by extension only + $recognizedExt = $ext if defined $ext and not defined $magicNumber{$ext} and + defined $moduleName{$ext} and not $moduleName{$ext}; + my @fileTypeList = GetFileType($realname); + if ($fast and $fast >= 4) { + if (@fileTypeList) { + $type = shift @fileTypeList; + $self->SetFileType($$self{FILE_TYPE} = $type); + } else { + $self->Error('Unknown file type'); + } + last; # don't read the file + } + if (@fileTypeList) { + # add remaining types to end of list so we test them all + my $pat = join '|', @fileTypeList; + push @fileTypeList, grep(!/^($pat)$/, @fileTypes); + $tiffType = $$self{FILE_EXT}; + unless ($fast and $fast == 3) { + $noMagic{MXF} = 1; # don't do magic number test on MXF or DV files + $noMagic{DV} = 1; + } + } else { + # scan through all recognized file types + @fileTypeList = @fileTypes; + $tiffType = 'TIFF'; + } + push @fileTypeList, ''; # end of list marker + # initialize the input file for seeking in binary data + $raf->BinMode(); # set binary mode before we start reading + my $pos = $raf->Tell(); # get file position so we can rewind + my %dirInfo = ( RAF => $raf, Base => $pos ); + # loop through list of file types to test + my ($buff, $seekErr); + # read start of file for testing + my $testLen = 1024; + $raf->Read($buff, $testLen) or $buff = ''; + $raf->Seek($pos, 0) or $seekErr = 1; + until ($seekErr) { + my $unkHeader; + $type = shift @fileTypeList; + if ($type) { + if ($magicNumber{$type}) { + # do quick test for this file type to avoid loading module unnecessarily + next if $buff !~ /^$magicNumber{$type}/s and not $noMagic{$type}; + } else { + # keep checking for other types if we recognize this file only by extension + next if defined $moduleName{$type} and not $moduleName{$type}; + } + next if $weakMagic{$type} and defined $recognizedExt; + } elsif (not defined $type) { + last; + } elsif ($recognizedExt) { + $type = $recognizedExt; # set type from recognized file extension only + } else { + # last ditch effort to scan past unknown header for JPEG/TIFF + next unless $buff =~ /(\xff\xd8\xff|MM\0\x2a|II\x2a\0)/g; + $type = ($1 eq "\xff\xd8\xff") ? 'JPEG' : 'TIFF'; + my $skip = pos($buff) - length($1); + $dirInfo{Base} = $pos + $skip; + $raf->Seek($pos + $skip, 0) or $seekErr = 1, last; + $self->Warn("Processing $type-like data after unknown $skip-byte header"); + $unkHeader = 1 unless $$self{DOC_NUM}; + } + # save file type in member variable + $$self{FILE_TYPE} = $type; + $dirInfo{Parent} = ($type eq 'TIFF') ? $tiffType : $type; + # don't process the file when FastScan == 3 + if ($fast and $fast == 3 and not $processType{$type}) { + unless ($weakMagic{$type} and (not $ext or $ext ne $type)) { + $self->SetFileType($dirInfo{Parent}); + } + last; + } + my $module = $moduleName{$type}; + $module = $type unless defined $module; + my $func = "Process$type"; + + # load module if necessary + if ($module) { + require "Image/ExifTool/$module.pm"; + $func = "Image::ExifTool::${module}::$func"; + } elsif ($module eq '0') { + $self->SetFileType(); + $self->Warn('Unsupported file type'); + last; + } + push @{$$self{PATH}}, $type; # save file type in metadata PATH + + # process the file + no strict 'refs'; + my $result = &$func($self, \%dirInfo); + use strict 'refs'; + + pop @{$$self{PATH}}; + + if ($result) { # all done if successful + if ($unkHeader) { + $self->DeleteTag('FileType'); + $self->DeleteTag('FileTypeExtension'); + $self->DeleteTag('MIMEType'); + $self->VPrint(0,"Reset file type due to unknown header\n"); + } + last; + } + # seek back to try again from the same position in the file + $raf->Seek($pos, 0) or $seekErr = 1, last; + } + if (not defined $type and not $$self{DOC_NUM}) { + # if we were given a single image with a known type there + # must be a format error since we couldn't read it, otherwise + # it is likely we don't support images of this type + my $fileType = GetFileType($realname) || ''; + my $err; + if (not length $buff) { + $err = 'File is empty'; + } else { + my $ch = substr($buff, 0, 1); + if (length $buff < 16 or $buff =~ /[^\Q$ch\E]/) { + if ($fileType eq 'RAW') { + $err = 'Unsupported RAW file type'; + } elsif ($fileType) { + $err = 'File format error'; + } else { + $err = 'Unknown file type'; + } + } else { + # provide some insight into the content of some corrupted files + if ($$self{OPTIONS}{FastScan}) { + $err = 'File header is all'; + } else { + my $num = length $buff; + for (;;) { + $raf->Read($buff, 65536) or undef($num), last; + $buff =~ /[^\Q$ch\E]/g and $num += pos($buff) - 1, last; + $num += length($buff); + } + if ($num) { + $err = 'First ' . ConvertFileSize($num) . ' of file is'; + } else { + $err = 'Entire file is'; + } + } + if ($ch eq "\0") { + $err .= ' binary zeros'; + } elsif ($ch eq ' ') { + $err .= ' ASCII spaces'; + } elsif ($ch =~ /[a-zA-Z0-9]/) { + $err .= " ASCII '${ch}' characters"; + } else { + $err .= sprintf(" binary 0x%.2x's", ord $ch); + } + } + } + $self->Error($err); + } + if ($seekErr) { + $self->Error('Error seeking in file'); + } elsif ($self->Options('ScanForXMP') and (not defined $type or + (not $fast and not $$self{FoundXMP}))) + { + # scan for XMP + $raf->Seek($pos, 0); + require Image::ExifTool::XMP; + Image::ExifTool::XMP::ScanForXMP($self, $raf) and $type = ''; + } + # extract binary EXIF data block only if requested + if (defined $$self{EXIF_DATA} and length $$self{EXIF_DATA} > 16 and + ($$req{exif} or + # (not extracted normally, so check TAGS_FROM_FILE) + ($$self{TAGS_FROM_FILE} and not $$self{EXCL_TAG_LOOKUP}{exif}))) + { + $self->FoundTag('EXIF', $$self{EXIF_DATA}); + } + unless ($reEntry) { + $$self{PATH} = [ ]; # reset PATH + # calculate Composite tags + $self->BuildCompositeTags() if $$options{Composite}; + # do our HTML dump if requested + if ($$self{HTML_DUMP}) { + $raf->Seek(0, 2); # seek to end of file + $$self{HTML_DUMP}->FinishTiffDump($self, $raf->Tell()); + my $pos = $$options{HtmlDumpBase}; + $pos = ($$self{FIRST_EXIF_POS} || 0) unless defined $pos; + my $dataPt = defined $$self{EXIF_DATA} ? \$$self{EXIF_DATA} : undef; + undef $dataPt if defined $$self{EXIF_POS} and $pos != $$self{EXIF_POS}; + undef $dataPt if $$self{ExtendedEXIF}; # can't use EXIF block if not contiguous + my $success = $$self{HTML_DUMP}->Print($raf, $dataPt, $pos, + $$options{TextOut}, $$options{HtmlDump}, + $$self{FILENAME} ? "HTML Dump ($$self{FILENAME})" : 'HTML Dump'); + $self->Warn("Error reading $$self{HTML_DUMP}{ERROR}") if $success < 0; + } + } + if ($filename) { + $raf->Close(); # close the file if we opened it + # process the resource fork as an embedded file on Mac filesystems + if ($rsize and $$options{ExtractEmbedded}) { + local *RESOURCE_FILE; + if ($self->Open(\*RESOURCE_FILE, "$filename/..namedfork/rsrc")) { + $$self{DOC_NUM} = $$self{DOC_COUNT} + 1; + $$self{IN_RESOURCE} = 1; + $self->ExtractInfo(\*RESOURCE_FILE, { ReEntry => 1 }); + close RESOURCE_FILE; + delete $$self{IN_RESOURCE}; + } else { + $self->Warn('Error opening resource fork'); + } + } + } + last; # (loop was a cheap "goto") + } + + # generate Validate tag if requested + if ($$options{Validate} and not $reEntry) { + Image::ExifTool::Validate::FinishValidate($self, $$req{validate}); + } + + @startTime and $self->FoundTag('ProcessingTime', Time::HiRes::tv_interval(\@startTime)); + + # restore original options + %saveOptions and $$self{OPTIONS} = \%saveOptions; + + if ($reEntry) { + # restore necessary members when exiting re-entrant code + $$self{$_} = $$reEntry{$_} foreach keys %$reEntry; + } + + # ($type may be undef without an Error when processing sub-documents) + return 0 if not defined $type or exists $$self{VALUE}{Error}; + return 1; +} + +#------------------------------------------------------------------------------ +# Get hash of extracted meta information +# Inputs: 0) ExifTool object reference +# 1-N) options hash reference, tag list reference or tag names +# Returns: Reference to information hash +# Notes: - pass an undefined value to avoid parsing arguments +# - If groups are specified, first groups take precedence if duplicate +# tags found but Duplicates option not set. +# - tag names may end in '#' to extract ValueConv value +sub GetInfo($;@) +{ + local $_; + my $self = shift; + my %saveOptions; + + unless (@_ and not defined $_[0]) { + %saveOptions = %{$$self{OPTIONS}}; # save original options + # must set FILENAME so it isn't parsed from the arguments + $$self{FILENAME} = '' unless defined $$self{FILENAME}; + $self->ParseArguments(@_); + } + + # get reference to list of tags for which we will return info + my ($rtnTags, $byValue, $wildTags) = $self->SetFoundTags(); + + # build hash of tag information + my (%info, %ignored); + my $conv = $$self{OPTIONS}{PrintConv} ? 'PrintConv' : 'ValueConv'; + foreach (@$rtnTags) { + my $val = $self->GetValue($_, $conv); + defined $val or $ignored{$_} = 1, next; + $info{$_} = $val; + } + + # override specified tags with ValueConv value if necessary + if (@$byValue) { + # first determine the number of times each non-ValueConv value is used + my %nonVal; + $nonVal{$_} = ($nonVal{$_} || 0) + 1 foreach @$rtnTags; + --$nonVal{$$rtnTags[$_]} foreach @$byValue; + # loop through ValueConv tags, updating tag keys and returned values + foreach (@$byValue) { + my $tag = $$rtnTags[$_]; + my $val = $self->GetValue($tag, 'ValueConv'); + next unless defined $val; + my $vtag = $tag; + # generate a new tag key like "Tag #" or "Tag #(1)" + $vtag =~ s/( |$)/ #/; + unless (defined $$self{VALUE}{$vtag}) { + $$self{VALUE}{$vtag} = $$self{VALUE}{$tag}; + $$self{TAG_INFO}{$vtag} = $$self{TAG_INFO}{$tag}; + $$self{TAG_EXTRA}{$vtag} = $$self{TAG_EXTRA}{$tag}; + $$self{FILE_ORDER}{$vtag} = $$self{FILE_ORDER}{$tag}; + # remove existing PrintConv entry unless we are using it too + delete $info{$tag} unless $nonVal{$tag}; + } + $$rtnTags[$_] = $vtag; # store ValueConv value with new tag key + $info{$vtag} = $val; # return ValueConv value + } + } + + # remove ignored tags from the list + my $reqTags = $$self{REQUESTED_TAGS} || [ ]; + if (%ignored) { + if (not @$reqTags) { + my @goodTags; + foreach (@$rtnTags) { + push @goodTags, $_ unless $ignored{$_}; + } + $rtnTags = $$self{FOUND_TAGS} = \@goodTags; + } elsif (@$wildTags) { + # only remove tags specified by wildcard + my @goodTags; + my $i = 0; + foreach (@$rtnTags) { + if (@$wildTags and $i == $$wildTags[0]) { + shift @$wildTags; + push @goodTags, $_ unless $ignored{$_}; + } else { + push @goodTags, $_; + } + ++$i; + } + $rtnTags = $$self{FOUND_TAGS} = \@goodTags; + } + } + + # return sorted tag list if provided with a list reference + if ($$self{IO_TAG_LIST}) { + # use file order by default if no tags specified + # (no such thing as 'Input' order in this case) + my $sort = $$self{OPTIONS}{Sort}; + $sort = 'File' unless @$reqTags or ($sort and $sort ne 'Input'); + # return tags in specified sort order + @{$$self{IO_TAG_LIST}} = $self->GetTagList($rtnTags, $sort, $$self{OPTIONS}{Sort2}); + } + + # restore original options + %saveOptions and $$self{OPTIONS} = \%saveOptions; + + return \%info; +} + +#------------------------------------------------------------------------------ +# Inputs: 0) ExifTool object reference +# 1) [optional] reference to info hash or tag list ref (default is found tags) +# 2) [optional] sort order ('File', 'Input', ...) +# 3) [optional] secondary sort order +# Returns: List of tags in specified order +sub GetTagList($;$$$) +{ + local $_; + my ($self, $info, $sort, $sort2) = @_; + + my $foundTags; + if (ref $info eq 'HASH') { + my @tags = keys %$info; + $foundTags = \@tags; + } elsif (ref $info eq 'ARRAY') { + $foundTags = $info; + } + my $fileOrder = $$self{FILE_ORDER}; + + if ($foundTags) { + # make sure a FILE_ORDER entry exists for all tags + # (note: already generated bogus entries for FOUND_TAGS case below) + foreach (@$foundTags) { + next if defined $$fileOrder{$_}; + $$fileOrder{$_} = 999; + } + } else { + $sort = $info if $info and not $sort; + $foundTags = $$self{FOUND_TAGS} || $self->SetFoundTags() or return undef; + } + $sort or $sort = $$self{OPTIONS}{Sort}; + + # return original list if no sort order specified + return @$foundTags unless $sort and $sort ne 'Input'; + + if ($sort eq 'Tag' or $sort eq 'Alpha') { + return sort @$foundTags; + } elsif ($sort =~ /^Group(\d*(:\d+)*)/) { + my $family = $1 || 0; + # want to maintain a basic file order with the groups + # ordered in the way they appear in the file + my (%groupCount, %groupOrder); + my $numGroups = 0; + my $tag; + foreach $tag (sort { $$fileOrder{$a} <=> $$fileOrder{$b} } @$foundTags) { + my $group = $self->GetGroup($tag, $family); + my $num = $groupCount{$group}; + $num or $num = $groupCount{$group} = ++$numGroups; + $groupOrder{$tag} = $num; + } + $sort2 or $sort2 = $$self{OPTIONS}{Sort2}; + if ($sort2) { + if ($sort2 eq 'Tag' or $sort2 eq 'Alpha') { + return sort { $groupOrder{$a} <=> $groupOrder{$b} or $a cmp $b } @$foundTags; + } elsif ($sort2 eq 'Descr') { + my $desc = $self->GetDescriptions($foundTags); + return sort { $groupOrder{$a} <=> $groupOrder{$b} or + $$desc{$a} cmp $$desc{$b} } @$foundTags; + } + } + return sort { $groupOrder{$a} <=> $groupOrder{$b} or + $$fileOrder{$a} <=> $$fileOrder{$b} } @$foundTags; + } elsif ($sort eq 'Descr') { + my $desc = $self->GetDescriptions($foundTags); + return sort { $$desc{$a} cmp $$desc{$b} } @$foundTags; + } else { + return sort { $$fileOrder{$a} <=> $$fileOrder{$b} } @$foundTags; + } +} + +#------------------------------------------------------------------------------ +# Get list of found tags in specified sort order +# Inputs: 0) ExifTool object reference, 1) sort order ('File', 'Input', ...) +# 2) secondary sort order +# Returns: List of tag keys in specified order +# Notes: If not specified, sort order is taken from OPTIONS +sub GetFoundTags($;$$) +{ + local $_; + my ($self, $sort, $sort2) = @_; + my $foundTags = $$self{FOUND_TAGS} || $self->SetFoundTags() or return undef; + return $self->GetTagList($foundTags, $sort, $sort2); +} + +#------------------------------------------------------------------------------ +# Get list of requested tags +# Inputs: 0) ExifTool object reference +# Returns: List of requested tag keys +sub GetRequestedTags($) +{ + local $_; + return @{$_[0]{REQUESTED_TAGS}}; +} + +#------------------------------------------------------------------------------ +# Get tag value +# Inputs: 0) ExifTool object reference +# 1) tag key or tag name with optional group names (case sensitive) +# (or flattened tagInfo for getting field values, not part of public API) +# 2) [optional] Value type: PrintConv, ValueConv, Both, Raw or Rational, the default +# is PrintConv or ValueConv, depending on the PrintConv option setting +# 3) raw field value (not part of public API) +# Returns: Scalar context: tag value or undefined +# List context: list of values or empty list +sub GetValue($$;$) +{ + local $_; + my ($self, $tag, $type) = @_; # plus: ($fieldValue) + my (@convTypes, $tagInfo, $valueConv, $both); + my $rawValue = $$self{VALUE}; + + # get specific tag key if tag has a group name + if ($tag =~ /^(.*):(.+)/) { + my ($gp, $tg) = ($1, $2); + my ($i, $key, @keys); + # build list of tag keys in the order of priority (no index + # is top priority, otherwise higher index is higher priority) + for ($key=$tg, $i=$$self{DUPL_TAG}{$tg} || 0; ; --$i) { + push @keys, $key if defined $$rawValue{$key}; + last if $i <= 0; + $key = "$tg ($i)"; + } + if (@keys) { + $key = $self->GroupMatches($gp, \@keys); + $tag = $key if $key; + } + } + # figure out what conversions to do + if ($type) { + return $$self{RATIONAL}{$tag} if $type eq 'Rational'; + } else { + $type = $$self{OPTIONS}{PrintConv} ? 'PrintConv' : 'ValueConv'; + } + + # start with the raw value + my $value = $$rawValue{$tag}; + if (not defined $value) { + return () unless ref $tag; + # get the value of a structure field + $tagInfo = $tag; + $tag = $$tagInfo{Name}; + $value = $_[3]; + # (note: type "Both" is not allowed for structure fields) + if ($type ne 'Raw') { + push @convTypes, 'ValueConv'; + push @convTypes, 'PrintConv' unless $type eq 'ValueConv'; + } + } else { + $tagInfo = $$self{TAG_INFO}{$tag}; + if ($$tagInfo{Struct} and ref $value) { + # must load XMPStruct.pl just in case (should already be loaded if + # a structure was extracted, but we could also arrive here if a simple + # list of values was stored incorrectly in a Struct tag) + require 'Image/ExifTool/XMPStruct.pl'; + # convert strucure field values + unless ($type eq 'Both') { + # (note: ConvertStruct handles the filtering and escaping too if necessary) + return Image::ExifTool::XMP::ConvertStruct($self,$tagInfo,$value,$type); + } + $valueConv = Image::ExifTool::XMP::ConvertStruct($self,$tagInfo,$value,'ValueConv'); + $value = Image::ExifTool::XMP::ConvertStruct($self,$tagInfo,$value,'PrintConv'); + # (must not save these in $$self{BOTH} because the values may have been escaped) + return ($valueConv, $value); + } + if ($type ne 'Raw') { + # use values we calculated already if we stored them + $both = $$self{BOTH}{$tag}; + if ($both) { + if ($type eq 'PrintConv') { + $value = $$both[1]; + } elsif ($type eq 'ValueConv') { + $value = $$both[0]; + $value = $$both[1] unless defined $value; + } else { + ($valueConv, $value) = @$both; + } + } else { + push @convTypes, 'ValueConv'; + push @convTypes, 'PrintConv' unless $type eq 'ValueConv'; + } + } + } + + # do the conversions + my (@val, @prt, @raw, $convType); + foreach $convType (@convTypes) { + # don't convert a scalar reference or structure + last if ref $value eq 'SCALAR' and not $$tagInfo{ConvertBinary}; + my $conv = $$tagInfo{$convType}; + unless (defined $conv) { + if ($convType eq 'ValueConv') { + next unless $$tagInfo{Binary}; + $conv = '\$val'; # return scalar reference for binary values + } else { + # use PRINT_CONV from tag table if PrintConv doesn't exist + next unless defined($conv = $$tagInfo{Table}{PRINT_CONV}); + next if exists $$tagInfo{$convType}; + } + } + # save old ValueConv value if we want Both + $valueConv = $value if $type eq 'Both' and $convType eq 'PrintConv'; + my ($i, $val, $vals, @values, $convList); + # split into list if conversion is an array + if (ref $conv eq 'ARRAY') { + $convList = $conv; + $conv = $$convList[0]; + my @valList = (ref $value eq 'ARRAY') ? @$value : split ' ', $value; + # reorganize list if specified (Note: The writer currently doesn't + # relist values, so they may be grouped but the order must not change) + my $relist = $$tagInfo{Relist}; + if ($relist) { + my (@newList, $oldIndex); + foreach $oldIndex (@$relist) { + my ($newVal, @join); + if (ref $oldIndex) { + foreach (@$oldIndex) { + push @join, $valList[$_] if defined $valList[$_]; + } + $newVal = join(' ', @join) if @join; + } else { + $newVal = $valList[$oldIndex]; + } + push @newList, $newVal if defined $newVal; + } + $value = \@newList; + } else { + $value = \@valList; + } + return () unless @$value; + } + # initialize array so we can iterate over values in list + if (ref $value eq 'ARRAY') { + if (defined $$tagInfo{RawJoin}) { + $val = join ' ', @$value; + } else { + $i = 0; + $vals = $value; + $val = $$vals[0]; + } + } else { + $val = $value; + } + # loop through all values in list + for (;;) { + if (defined $conv) { + # get values of required tags if this is a Composite tag + if (ref $val eq 'HASH' and not @val) { + # disable escape of source values so we don't double escape them + my $oldEscape = $$self{ESCAPE_PROC}; + delete $$self{ESCAPE_PROC}; + # temporarily delete filter so it isn't applied to the Require'd values + my $oldFilter = $$self{OPTIONS}{Filter}; + delete $$self{OPTIONS}{Filter}; + foreach (keys %$val) { + $raw[$_] = $$rawValue{$$val{$_}}; + ($val[$_], $prt[$_]) = $self->GetValue($$val{$_}, 'Both'); + next if defined $val[$_] or not $$tagInfo{Require}{$_}; + $$self{OPTIONS}{Filter} = $oldFilter if defined $oldFilter; + $$self{ESCAPE_PROC} = $oldEscape; + return (); + } + $$self{OPTIONS}{Filter} = $oldFilter if defined $oldFilter; + $$self{ESCAPE_PROC} = $oldEscape; + # set $val to $val[0], or \@val for a CODE ref conversion + $val = ref $conv eq 'CODE' ? \@val : $val[0]; + } + if (ref $conv eq 'HASH') { + # look up converted value in hash + my $lc; + if (defined($value = $$conv{$val})) { + # override with our localized language PrintConv if available + if ($$self{CUR_LANG} and $convType eq 'PrintConv' and + # (no need to check for lang-alt tag names -- they won't have a PrintConv) + ref($lc = $$self{CUR_LANG}{$$tagInfo{Name}}) eq 'HASH' and + ($lc = $$lc{PrintConv}) and ($lc = $$lc{$value})) + { + $value = $self->Decode($lc, 'UTF8'); + } + } else { + if ($$conv{BITMASK}) { + $value = DecodeBits($val, $$conv{BITMASK}, $$tagInfo{BitsPerWord}); + # override with localized language strings + if (defined $value and $$self{CUR_LANG} and $convType eq 'PrintConv' and + ref($lc = $$self{CUR_LANG}{$$tagInfo{Name}}) eq 'HASH' and + ($lc = $$lc{PrintConv})) + { + my @vals = split ', ', $value; + foreach (@vals) { + $_ = $$lc{$_} if defined $$lc{$_}; + } + $value = join ', ', @vals; + } + } else { + # use alternate conversion routine if available + if ($$conv{OTHER}) { + local $SIG{'__WARN__'} = \&SetWarning; + undef $evalWarning; + $value = &{$$conv{OTHER}}($val, undef, $conv); + $self->Warn("$convType $tag: " . CleanWarning()) if $evalWarning; + } + if (not defined $value) { + if ($$tagInfo{PrintHex} and $val and IsInt($val) and + $convType eq 'PrintConv') + { + $val = sprintf('0x%x',$val); + } + $value = "Unknown ($val)"; + } + } + } + } else { + # call subroutine or do eval to convert value + local $SIG{'__WARN__'} = \&SetWarning; + undef $evalWarning; + if (ref $conv eq 'CODE') { + $value = &$conv($val, $self); + } else { + #### eval ValueConv/PrintConv ($val, $self, @val, @prt, @raw) + $value = eval $conv; + $@ and $evalWarning = $@; + } + $self->Warn("$convType $tag: " . CleanWarning()) if $evalWarning; + } + } else { + $value = $val; + } + last unless $vals; + # must store a separate copy of each binary data value in the list + if (ref $value eq 'SCALAR') { + my $tval = $$value; + $value = \$tval; + } + # save this converted value and step to next value in list + push @values, $value if defined $value; + if (++$i >= scalar(@$vals)) { + $value = \@values if @values; + last; + } + $val = $$vals[$i]; + if ($convList) { + my $nextConv = $$convList[$i]; + if ($nextConv and $nextConv eq 'REPEAT') { + undef $convList; + } else { + $conv = $nextConv; + } + } + } + # return undefined now if no value + return () unless defined $value; + # join back into single value if split for conversion list + if ($convList and ref $value eq 'ARRAY') { + $value = join($convType eq 'PrintConv' ? '; ' : ' ', @$value); + } + } + if ($type eq 'Both') { + # save both (unescaped) values because we often need them again + # (Composite tags need "Both" and often Require one tag for various Composite tags) + $$self{BOTH}{$tag} = [ $valueConv, $value ] unless $both; + # escape values if necessary + if ($$self{ESCAPE_PROC}) { + DoEscape($value, $$self{ESCAPE_PROC}); + if (defined $valueConv) { + DoEscape($valueConv, $$self{ESCAPE_PROC}); + } else { + $valueConv = $value; + } + } elsif (not defined $valueConv) { + # $valueConv is undefined if there was no print conversion done + $valueConv = $value; + } + $self->Filter(\$value) if defined $$self{OPTIONS}{Filter}; + # return Both values as a list (ValueConv, PrintConv) + return ($valueConv, $value); + } + # escape value if necessary + DoEscape($value, $$self{ESCAPE_PROC}) if $$self{ESCAPE_PROC}; + + # filter if necessary + $self->Filter(\$value) if defined $$self{OPTIONS}{Filter} and $type eq 'PrintConv'; + + if (ref $value eq 'ARRAY') { + if (defined $$self{OPTIONS}{ListItem}) { + $value = $$value[$$self{OPTIONS}{ListItem}]; + } elsif (wantarray) { + # return array if requested + return @$value; + } elsif ($type eq 'PrintConv' and not $$self{OPTIONS}{List} and not ref $$value[0]) { + # join PrintConv values in comma-separated string if List option not used + # and list contains simple scalars (otherwise return ARRAY ref) + $value = join $$self{OPTIONS}{ListSep}, @$value; + } + } + return $value; +} + +#------------------------------------------------------------------------------ +# Get tag identification number +# Inputs: 0) ExifTool object reference, 1) tag key +# Returns: Scalar context: tag ID if available, otherwise '' +# List context: 0) tag ID (or ''), 1) language code (or undef) +sub GetTagID($$) +{ + my ($self, $tag) = @_; + my $tagInfo = $$self{TAG_INFO}{$tag}; + return '' unless $tagInfo and defined $$tagInfo{TagID}; + return ($$tagInfo{TagID}, $$tagInfo{LangCode}) if wantarray; + return $$tagInfo{TagID}; +} + +#------------------------------------------------------------------------------ +# Get description for specified tag +# Inputs: 0) ExifTool object reference, 1) tag key +# Returns: Tag description +# Notes: Will always return a defined value, even if description isn't available +sub GetDescription($$) +{ + local $_; + my ($self, $tag) = @_; + my ($desc, $name); + my $tagInfo = $$self{TAG_INFO}{$tag}; + # ($tagInfo won't be defined for missing tags extracted with -f) + if ($tagInfo) { + # use alternate language description if available + while ($$self{CUR_LANG}) { + $desc = $$self{CUR_LANG}{$$tagInfo{Name}}; + if ($desc) { + # must look up Description if this tag also has a PrintConv + $desc = $$desc{Description} or last if ref $desc; + } else { + # look up default language of lang-alt tag + last unless $$tagInfo{LangCode} and + ($name = $$tagInfo{Name}) =~ s/-$$tagInfo{LangCode}$// and + $desc = $$self{CUR_LANG}{$name}; + $desc = $$desc{Description} or last if ref $desc; + $desc .= " ($$tagInfo{LangCode})"; + } + # escape description if necessary + DoEscape($desc, $$self{ESCAPE_PROC}) if $$self{ESCAPE_PROC}; + # return description in proper Charset + return $self->Decode($desc, 'UTF8'); + } + $desc = $$tagInfo{Description}; + } + # just make the tag more readable if description doesn't exist + unless ($desc) { + $desc = MakeDescription(GetTagName($tag)); + # save description in tag information + $$tagInfo{Description} = $desc if $tagInfo; + } + return $desc; +} + +#------------------------------------------------------------------------------ +# Get group name for specified tag +# Inputs: 0) ExifTool object reference +# 1) tag key (or reference to tagInfo hash, not part of the public API) +# 2) [optional] group family (-1 to get extended group list, or multiple +# families separated by colons to return multiple groups as a string) +# Returns: Scalar context: group name (for family 0 if not otherwise specified) +# List context: group name if family specified, otherwise list of +# group names for each family. Returns '' for undefined tag. +# Notes: Mutiple families may be specified with ':' in family argument (eg. '1:2') +sub GetGroup($$;$) +{ + local $_; + my ($self, $tag, $family) = @_; + my ($tagInfo, @groups, @families, $simplify, $byTagInfo, $ex); + if (ref $tag eq 'HASH') { + $tagInfo = $tag; + $tag = $$tagInfo{Name}; + # set flag so we don't get extra information for an extracted tag + $byTagInfo = 1; + } else { + $tagInfo = $$self{TAG_INFO}{$tag} || { }; + $ex = $$self{TAG_EXTRA}{$tag}; + } + my $groups = $$tagInfo{Groups}; + # fill in default groups unless already done + # (after this, Groups 0-2 in tagInfo are guaranteed to be defined) + unless ($$tagInfo{GotGroups}) { + my $tagTablePtr = $$tagInfo{Table} || { GROUPS => { } }; + # construct our group list + $groups or $groups = $$tagInfo{Groups} = { }; + # fill in default groups + foreach (0..2) { + $$groups{$_} = $$tagTablePtr{GROUPS}{$_} || '' unless $$groups{$_}; + } + # set flag indicating group list was built + $$tagInfo{GotGroups} = 1; + } + if (defined $family and $family ne '-1') { + if ($family =~ /[^\d]/) { + @families = ($family =~ /\d+/g); + return(($ex && $$ex{G0}) || $$groups{0}) unless @families; + $simplify = 1 unless $family =~ /^:/; + undef $family; + foreach (0..2) { $groups[$_] = $$groups{$_}; } + } else { + return(($ex && $$ex{"G$family"}) || $$groups{$family}) if $family == 0 or $family == 2; + $groups[1] = $$groups{1}; + } + } else { + return(($ex && $$ex{G0}) || $$groups{0}) unless wantarray; + foreach (0..2) { $groups[$_] = $$groups{$_}; } + } + $groups[3] = 'Main'; + $groups[4] = ($tag =~ /\((\d+)\)$/) ? "Copy$1" : ''; + # handle dynamic group names if necessary + if ($ex and not $byTagInfo) { + $groups[0] = $$ex{G0} if $$ex{G0}; + $groups[1] = $$ex{G1} =~ /^\+(.*)/ ? "$groups[1]$1" : $$ex{G1} if $$ex{G1}; + $groups[3] = 'Doc' . $$ex{G3} if $$ex{G3}; + $groups[5] = $$ex{G5} || $groups[1] if defined $$ex{G5}; + } + if ($family) { + return $groups[$family] || '' if $family > 0; + # add additional matching group names to list + # eg) for MIE-Doc, also add MIE1, MIE1-Doc, MIE-Doc1 and MIE1-Doc1 + # and for MIE2-Doc3, also add MIE2, MIE-Doc3, MIE2-Doc and MIE-Doc + if ($groups[1] =~ /^MIE(\d*)-(.+?)(\d*)$/) { + push @groups, 'MIE' . ($1 || '1'); + push @groups, 'MIE' . ($1 ? '' : '1') . "-$2$3"; + push @groups, "MIE$1-$2" . ($3 ? '' : '1'); + push @groups, 'MIE' . ($1 ? '' : '1') . "-$2" . ($3 ? '' : '1'); + } + } + if (@families) { + my @grps; + # create list of group names (without identical adjacent groups if simplifying) + foreach (@families) { + my $grp = $groups[$_] or next; + push @grps, $grp unless $simplify and @grps and $grp eq $grps[-1]; + } + # remove leading "Main:" if simplifying + shift @grps if $simplify and @grps > 1 and $grps[0] eq 'Main'; + # return colon-separated string of group names + return join ':', @grps; + } + return @groups; +} + +#------------------------------------------------------------------------------ +# Get group names for specified tags +# Inputs: 0) ExifTool object reference +# 1) [optional] information hash reference (default all extracted info) +# 2) [optional] group family (default 0) +# Returns: List of group names in alphabetical order +sub GetGroups($;$$) +{ + local $_; + my $self = shift; + my $info = shift; + my $family; + + # figure out our arguments + if (ref $info ne 'HASH') { + $family = $info; + $info = $$self{VALUE}; + } else { + $family = shift; + } + $family = 0 unless defined $family; + + # get a list of all groups in specified information + my ($tag, %groups); + foreach $tag (keys %$info) { + $groups{ $self->GetGroup($tag, $family) } = 1; + } + return sort keys %groups; +} + +#------------------------------------------------------------------------------ +# Set priority for group where new values are written +# Inputs: 0) ExifTool object reference, +# 1-N) group names (reset to default if no groups specified) +sub SetNewGroups($;@) +{ + local $_; + my ($self, @groups) = @_; + @groups or @groups = @defaultWriteGroups; + my $count = @groups; + my %priority; + foreach (@groups) { + $priority{lc($_)} = $count--; + } + $priority{file} = 10; # 'File' group is always written (Comment) + $priority{composite} = 10; # 'Composite' group is always written + # set write priority (higher # is higher priority) + $$self{WRITE_PRIORITY} = \%priority; + $$self{WRITE_GROUPS} = \@groups; +} + +#------------------------------------------------------------------------------ +# Build Composite tags from Require'd/Desire'd tags +# Inputs: 0) ExifTool object reference +# Note: Tag values are calculated in alphabetical order unless a tag Require's +# or Desire's another Composite tag, in which case the calculation is +# deferred until after the other tag is calculated. +sub BuildCompositeTags($) +{ + local $_; + my $self = shift; + + $$self{BuildingComposite} = 1; + + my $compTable = GetTagTable('Image::ExifTool::Composite'); + my @tagList = sort keys %$compTable; + my $rawValue = $$self{VALUE}; + my (%tagsUsed, %cache); + + for (;;) { + my (%notBuilt, $tag, @deferredTags); + $notBuilt{$_} = 1 foreach @tagList; +COMPOSITE_TAG: + foreach $tag (@tagList) { + next if $specialTags{$tag}; + my $tagInfo = $self->GetTagInfo($compTable, $tag); + next unless $tagInfo; + # put required tags into array and make sure they all exist + my $subDoc = ($$tagInfo{SubDoc} and $$self{DOC_COUNT}); + my $require = $$tagInfo{Require} || { }; + my $desire = $$tagInfo{Desire} || { }; + my $inhibit = $$tagInfo{Inhibit} || { }; + # loop through sub-documents if necessary + my $docNum = 0; + for (;;) { + my (%tagKey, $found, $index); + # save Require'd and Desire'd tag values in list + for ($index=0; ; ++$index) { + my $reqTag = $$require{$index} || $$desire{$index} || $$inhibit{$index}; + unless ($reqTag) { + # allow Composite with no Require'd or Desire'd tags + $found = 1 if $index == 0; + last; + } + if ($subDoc) { + # handle SubDoc tags specially to cache tag keys for faster + # processing when there are a large number of sub-documents + # - get document number from the tag groups if specified, + # otherwise we are looping through all documents for this tag + my $doc = $reqTag =~ s/\b(Main|Doc(\d+)):// ? ($2 || 0) : $docNum; + # make fast lookup for keys of this tag with specified groups other than doc group + # (similar to code in InsertTagValues(), but this is case-sensitive) + my $cacheTag = $cache{$reqTag}; + unless ($cacheTag) { + $cacheTag = $cache{$reqTag} = [ ]; + my $reqGroup; + $reqTag =~ s/^(.*):// and $reqGroup = $1; + my ($i, $key, @keys); + # build list of tag keys in order of precedence + for ($key=$reqTag, $i=$$self{DUPL_TAG}{$reqTag} || 0; ; --$i) { + push @keys, $key if defined $$rawValue{$key}; + last if $i <= 0; + $key = "$reqTag ($i)"; + } + @keys = $self->GroupMatches($reqGroup, \@keys) if defined $reqGroup; + if (@keys) { + my $ex = $$self{TAG_EXTRA}; + # loop through tags in reverse order of precedence so the higher + # priority tag will win in the case of duplicates within a doc + $$cacheTag[$$ex{$_} ? $$ex{$_}{G3} || 0 : 0] = $_ foreach reverse @keys; + } + } + # (set $reqTag to a bogus key if not found) + $reqTag = $$cacheTag[$doc] || "$reqTag (0)"; + } elsif ($reqTag =~ /^(.*):(.+)/) { + my ($reqGroup, $name) = ($1, $2); + if ($reqGroup eq 'Composite' and $notBuilt{$name}) { + push @deferredTags, $tag; + next COMPOSITE_TAG; + } + # (CAREFUL! keys may not be sequential if one was deleted) + my ($i, $key, @keys); + for ($key=$name, $i=$$self{DUPL_TAG}{$name} || 0; ; --$i) { + push @keys, $key if defined $$rawValue{$key}; + last if $i <= 0; + $key = "$name ($i)"; + } + # find first matching tag + $key = $self->GroupMatches($reqGroup, \@keys); + $reqTag = $key || "$name (0)"; + } elsif ($notBuilt{$reqTag}) { + # calculate this tag later if it relies on another + # Composite tag which hasn't been calculated yet + push @deferredTags, $tag; + next COMPOSITE_TAG; + } + if (defined $$rawValue{$reqTag}) { + if ($$inhibit{$index}) { + $found = 0; + last; + } else { + $found = 1; + } + } elsif ($$require{$index}) { + $found = 0; + last; # don't continue since we require this tag + } + $tagKey{$index} = $reqTag; + } + if ($docNum) { + if ($found) { + $$self{DOC_NUM} = $docNum; + $self->FoundTag($tagInfo, \%tagKey); + delete $$self{DOC_NUM}; + } + next if ++$docNum <= $$self{DOC_COUNT}; + last; + } elsif ($found) { + delete $notBuilt{$tag}; # this tag is OK to build now + # keep track of all Require'd tag keys + foreach (keys %tagKey) { + # only tag keys with same name as a Composite tag + # can be replaced (also eliminates keys with + # instance numbers which can't be replaced either) + next unless $$compTable{$tagKey{$_}}; + my $keyRef = \$tagKey{$_}; + $tagsUsed{$$keyRef} or $tagsUsed{$$keyRef} = [ ]; + push @{$tagsUsed{$$keyRef}}, $keyRef; + } + # save reference to tag key lookup as value for Composite tag + my $key = $self->FoundTag($tagInfo, \%tagKey); + # check to see if we just replaced one of the tag keys we Require'd + if (defined $key and $tagsUsed{$key}) { + foreach (@{$tagsUsed{$key}}) { + $$_ = $$self{MOVED_KEY}; # replace with new tag key + } + delete $tagsUsed{$key}; # can't be replaced again + } + } elsif (not defined $found) { + delete $notBuilt{$tag}; # tag can't be built anyway + } + last unless $subDoc; + # don't process sub-documents if there is no chance to build this tag + # (can be very time-consuming if there are many docs) + if (%$require) { + foreach (keys %$require) { + my $reqTag = $$require{$_}; + $reqTag =~ s/.*://; + next COMPOSITE_TAG unless defined $$rawValue{$reqTag}; + } + $docNum = 1; # go ahead and process the 1st sub-document + } else { + my @try = ref $$tagInfo{SubDoc} ? @{$$tagInfo{SubDoc}} : keys %$desire; + # at least one of the specified desire tags must exist + foreach (@try) { + my $desTag = $$desire{$_} or next; + $desTag =~ s/.*://; + defined $$rawValue{$desTag} and $docNum = 1, last; + } + last unless $docNum; + } + } + } + last unless @deferredTags; + if (@deferredTags == @tagList) { + # everything was deferred in the last pass, + # must be a circular dependency + warn "Circular dependency in Composite tags\n"; + last; + } + @tagList = @deferredTags; # calculate deferred tags now + } + delete $$self{BuildingComposite}; +} + +#------------------------------------------------------------------------------ +# Get tag name (removes copy index) +# Inputs: 0) Tag key +# Returns: Tag name +sub GetTagName($) +{ + local $_; + $_[0] =~ /^(\S+)/; + return $1; +} + +#------------------------------------------------------------------------------ +# Get list of shortcuts +# Returns: Shortcut list (sorted alphabetically) +sub GetShortcuts() +{ + local $_; + require Image::ExifTool::Shortcuts; + return sort keys %Image::ExifTool::Shortcuts::Main; +} + +#------------------------------------------------------------------------------ +# Get file type for specified extension +# Inputs: 0) file name or extension (case is not significant), +# or FileType value if a description is requested +# 1) flag to return long description instead of type ('0' to return any recognized type) +# Returns: File type (or desc) or undef if extension not supported or if +# description is the same as the input FileType. In list context, +# may return more than one file type if the file may be different formats. +# Returns list of all supported extensions if no file specified +sub GetFileType(;$$) +{ + local $_; + my ($file, $desc) = @_; + unless (defined $file) { + my @types; + if (defined $desc and $desc eq '0') { + # return all recognized types + @types = sort keys %fileTypeLookup; + } else { + # return all supported types + foreach (sort keys %fileTypeLookup) { + my $module = $moduleName{$_}; + $module = $moduleName{$fileTypeLookup{$_}} unless defined $module; + push @types, $_ unless defined $module and $module eq '0'; + } + } + return @types; + } + my ($fileType, $subType); + my $fileExt = GetFileExtension($file); + unless ($fileExt) { + if ($file =~ s/ \((.*)\)$//) { + $subType = $1; + $fileExt = GetFileExtension($file); + } + $fileExt = uc($file) unless $fileExt; + } + $fileExt and $fileType = $fileTypeLookup{$fileExt}; # look up the file type + $fileType = $fileTypeLookup{$fileType} while $fileType and not ref $fileType; + # return description if specified + # (allow input $file to be a FileType for this purpose) + if ($desc) { + $desc = $fileType ? $$fileType[1] : $fileDescription{$file}; + $desc .= ", $subType" if $subType; + return $desc; + } elsif ($fileType and (not defined $desc or $desc ne '0')) { + # return only supported file types + my $mod = $moduleName{$$fileType[0]}; + undef $fileType if defined $mod and $mod eq '0'; + } + $fileType or return (); + $fileType = $$fileType[0]; # get file type (or list of types) + if (wantarray) { + return @$fileType if ref $fileType eq 'ARRAY'; + } elsif ($fileType) { + $fileType = $fileExt if ref $fileType eq 'ARRAY'; + } + return $fileType; +} + +#------------------------------------------------------------------------------ +# Return true if we can write the specified file type +# Inputs: 0) file name or ext +# Returns: true if writable, 0 if not writable, undef if unrecognized +sub CanWrite($) +{ + local $_; + my $file = shift or return undef; + my ($type) = GetFileType($file) or return undef; + if ($noWriteFile{$type}) { + # can't write TIFF files with certain extensions (various RAW formats) + my $ext = GetFileExtension($file) || uc($file); + return grep(/^$ext$/, @{$noWriteFile{$type}}) ? 0 : 1 if $ext; + } + unless (%writeTypes) { + $writeTypes{$_} = 1 foreach @writeTypes; + } + return $writeTypes{$type}; +} + +#------------------------------------------------------------------------------ +# Return true if we can create the specified file type +# Inputs: 0) file name or ext +# Returns: true if creatable, 0 if not writable, undef if unrecognized +sub CanCreate($) +{ + local $_; + my $file = shift or return undef; + my $ext = GetFileExtension($file) || uc($file); + my $type = GetFileType($file) or return undef; + return 1 if $createTypes{$ext} or $createTypes{$type}; + return 0; +} + +#============================================================================== +# Functions below this are not part of the public API + +# Initialize member variables for reading or writing a new file +# Inputs: 0) ExifTool object reference +sub Init($) +{ + local $_; + my $self = shift; + # delete all DataMember variables (lower-case names) + foreach (keys %$self) { + /[a-z]/ and delete $$self{$_}; + } + delete $$self{FOUND_TAGS}; # list of found tags + delete $$self{EXIF_DATA}; # the EXIF data block + delete $$self{EXIF_POS}; # EXIF position in file + delete $$self{FIRST_EXIF_POS}; # position of first EXIF in file + delete $$self{HTML_DUMP}; # html dump information + delete $$self{SET_GROUP0}; # group0 name override + delete $$self{SET_GROUP1}; # group1 name override + delete $$self{DOC_NUM}; # current embedded document number + $$self{DOC_COUNT} = 0; # count of embedded documents processed + $$self{BASE} = 0; # base for offsets from start of file + $$self{FILE_ORDER} = { }; # * hash of tag order in file ('*' = based on tag key) + $$self{VALUE} = { }; # * hash of raw tag values + $$self{BOTH} = { }; # * hash for Value/PrintConv values of Require'd tags + $$self{RATIONAL} = { }; # * hash of original rational components + $$self{TAG_INFO} = { }; # * hash of tag information + $$self{TAG_EXTRA} = { }; # * hash of extra tag information (dynamic group names) + $$self{PRIORITY} = { }; # * priority of current tags + $$self{LIST_TAGS} = { }; # hash of tagInfo refs for active List-type tags + $$self{PROCESSED} = { }; # hash of processed directory start positions + $$self{DIR_COUNT} = { }; # count various types of directories + $$self{DUPL_TAG} = { }; # last-used index for duplicate-tag keys + $$self{WARNED_ONCE}= { }; # WarnOnce() warnings already issued + $$self{WRITTEN} = { }; # list of tags written (selected tags only) + $$self{FORCE_WRITE}= { }; # ForceWrite lookup (set from ForceWrite tag) + $$self{FOUND_DIR} = { }; # hash of directory names found in file + $$self{PATH} = [ ]; # current subdirectory path in file when reading + $$self{NUM_FOUND} = 0; # total number of tags found (incl. duplicates) + $$self{CHANGED} = 0; # number of tags changed (writer only) + $$self{INDENT} = ' '; # initial indent for verbose messages + $$self{PRIORITY_DIR} = ''; # the priority directory name + $$self{LOW_PRIORITY_DIR} = { PreviewIFD => 1 }; # names of priority 0 directories + $$self{TIFF_TYPE} = ''; # type of TIFF data (APP1, TIFF, NEF, etc...) + $$self{FMT_EXPR} = undef; # current advanced formatting expression + $$self{Make} = ''; # camera make + $$self{Model} = ''; # camera model + $$self{CameraType} = ''; # Olympus camera type + if ($self->Options('HtmlDump')) { + require Image::ExifTool::HtmlDump; + $$self{HTML_DUMP} = new Image::ExifTool::HtmlDump; + } + # make sure our TextOut is a file reference + $$self{OPTIONS}{TextOut} = \*STDOUT unless ref $$self{OPTIONS}{TextOut}; +} + +#------------------------------------------------------------------------------ +# Combine information from a list of info hashes +# Unless Duplicates is enabled, first entry found takes priority +# Inputs: 0) ExifTool object reference, 1-N) list of info hash references +# Returns: Combined information hash reference +sub CombineInfo($;@) +{ + local $_; + my $self = shift; + my (%combinedInfo, $info, $tag, %haveInfo); + + if ($$self{OPTIONS}{Duplicates}) { + while ($info = shift) { + foreach $tag (keys %$info) { + $combinedInfo{$tag} = $$info{$tag}; + } + } + } else { + while ($info = shift) { + foreach $tag (keys %$info) { + my $tagName = GetTagName($tag); + next if $haveInfo{$tagName}; + $haveInfo{$tagName} = 1; + $combinedInfo{$tag} = $$info{$tag}; + } + } + } + return \%combinedInfo; +} + +#------------------------------------------------------------------------------ +# Get tag table name +# Inputs: 0) ExifTool object reference, 1) tag key +# Returns: Table name if available, otherwise '' +sub GetTableName($$) +{ + my ($self, $tag) = @_; + my $tagInfo = $$self{TAG_INFO}{$tag} or return ''; + return $$tagInfo{Table}{SHORT_NAME}; +} + +#------------------------------------------------------------------------------ +# Get tag index number +# Inputs: 0) ExifTool object reference, 1) tag key +# Returns: Table index number, or undefined if this tag isn't indexed +sub GetTagIndex($$) +{ + my ($self, $tag) = @_; + my $tagInfo = $$self{TAG_INFO}{$tag} or return undef; + return $$tagInfo{Index}; +} + +#------------------------------------------------------------------------------ +# Find value for specified tag +# Inputs: 0) ExifTool ref, 1) tag name, 2) tag group (family 1) +# Returns: value or undef +sub FindValue($$$) +{ + my ($et, $tag, $grp) = @_; + my ($i, $val); + my $value = $$et{VALUE}; + for ($i=0; ; ++$i) { + my $key = $tag . ($i ? " ($i)" : ''); + last unless defined $$value{$key}; + if ($et->GetGroup($key, 1) eq $grp) { + $val = $$value{$key}; + last; + } + } + return $val; +} + +#------------------------------------------------------------------------------ +# Get tag key for next existing tag +# Inputs: 0) ExifTool ref, 1) tag key or case-sensitive tag name +# Returns: Key of next existing tag, or undef if no more +# Notes: This routine is provided for iterating through duplicate tags in the +# ValueConv of Composite tags. +sub NextTagKey($$) +{ + my ($self, $tag) = @_; + my $i = ($tag =~ s/ \((\d+)\)$//) ? $1 + 1 : 1; + $tag = "$tag ($i)"; + return $tag if defined $$self{VALUE}{$tag}; + return undef; +} + +#------------------------------------------------------------------------------ +# Encode file name for calls to system i/o routines +# Inputs: 0) ExifTool ref, 1) file name in CharSetFileName, 2) flag to force conversion +# Returns: true if Windows Unicode routines should be used (in which case +# the file name will be encoded as a null-terminated UTF-16LE string) +sub EncodeFileName($$;$) +{ + my ($self, $file, $force) = @_; + my $enc = $$self{OPTIONS}{CharsetFileName}; + if ($enc) { + if ($file =~ /[\x80-\xff]/ or $force) { + # encode for use in Windows Unicode functions if necessary + if ($^O eq 'MSWin32') { + local $SIG{'__WARN__'} = \&SetWarning; + if (eval { require Win32API::File }) { + # recode as UTF-16LE and add null terminator + $_[1] = $self->Decode($file, $enc, undef, 'UTF16', 'II') . "\0\0"; + return 1; + } + $self->WarnOnce('Install Win32API::File for Windows Unicode file support'); + } else { + # recode as UTF-8 for other platforms if necessary + $_[1] = $self->Decode($file, $enc, undef, 'UTF8') unless $enc eq 'UTF8'; + } + } + } elsif ($^O eq 'MSWin32' and $file =~ /[\x80-\xff]/ and not defined $enc) { + require Image::ExifTool::XMP; + if (Image::ExifTool::XMP::IsUTF8(\$file) < 0) { + $self->WarnOnce('FileName encoding not specified'); + } + } + return 0; +} + +#------------------------------------------------------------------------------ +# Modified perl open() routine to properly handle special characters in file names +# Inputs: 0) ExifTool ref, 1) filehandle, 2) filename, +# 3) mode: '<' or undef = read, '>' = write, '+<' = update +# Returns: true on success +# Note: Must call like "$et->Open(\*FH,$file)", not "$et->Open(FH,$file)" to avoid +# "unopened filehandle" errors due to a change in scope of the filehandle +sub Open($*$;$) +{ + my ($self, $fh, $file, $mode) = @_; + + $file =~ s/^([\s&])/.\/$1/; # protect leading whitespace or ampersand + # default to read mode ('<') unless input is a pipe + $mode = ($file =~ /\|$/ ? '' : '<') unless $mode; + if ($mode) { + if ($self->EncodeFileName($file)) { + # handle Windows Unicode file name + local $SIG{'__WARN__'} = \&SetWarning; + my ($access, $create); + if ($mode eq '>') { + eval { + $access = Win32API::File::GENERIC_WRITE(); + $create = Win32API::File::CREATE_ALWAYS(); + } + } else { + eval { + $access = Win32API::File::GENERIC_READ(); + $access |= Win32API::File::GENERIC_WRITE() if $mode eq '+<'; # update + $create = Win32API::File::OPEN_EXISTING(); + } + } + my $wh = eval { Win32API::File::CreateFileW($file, $access, 0, [], $create, 0, []) }; + return undef unless $wh; + my $fd = eval { Win32API::File::OsFHandleOpenFd($wh, 0) }; + if (not defined $fd or $fd < 0) { + eval { Win32API::File::CloseHandle($wh) }; + return undef; + } + $file = "&=$fd"; # specify file by descriptor + } else { + # add leading space to protect against leading characters like '>' + # in file name, and trailing "\0" to protect trailing spaces + $file = " $file\0"; + } + } + return open $fh, "$mode$file"; +} + +#------------------------------------------------------------------------------ +# Check to see if a file exists (with Windows Unicode support) +# Inputs: 0) ExifTool ref, 1) file name +# Returns: true if file exists +sub Exists($$) +{ + my ($self, $file) = @_; + + if ($self->EncodeFileName($file)) { + local $SIG{'__WARN__'} = \&SetWarning; + my $wh = eval { Win32API::File::CreateFileW($file, + Win32API::File::GENERIC_READ(), 0, [], + Win32API::File::OPEN_EXISTING(), 0, []) }; + return 0 unless $wh; + eval { Win32API::File::CloseHandle($wh) }; + } else { + return -e $file; + } + return 1; +} + +#------------------------------------------------------------------------------ +# Return true if file is a directory (with Windows Unicode support) +# Inputs: 0) ExifTool ref, 1) file name +# Returns: true if file is a directory (false if file isn't, or doesn't exist) +sub IsDirectory($$) +{ + my ($et, $file) = @_; + if ($et->EncodeFileName($file)) { + local $SIG{'__WARN__'} = \&SetWarning; + my $attrs = eval { Win32API::File::GetFileAttributesW($file) }; + my $dirBit = eval { Win32API::File::FILE_ATTRIBUTE_DIRECTORY() } || 0; + return 1 if $attrs and $attrs != 0xffffffff and $attrs & $dirBit; + } else { + return -d $file; + } + return 0; +} + +#------------------------------------------------------------------------------ +# Get file times (Unix seconds since the epoch) +# Inputs: 0) ExifTool ref, 1) file name or ref +# Returns: 0) access time, 1) modification time, 2) creation time (or undefs on error) +my $k32GetFileTime; +sub GetFileTime($$) +{ + my ($self, $file) = @_; + + # open file by name if necessary + unless (ref $file) { + local *FH; + $self->Open(\*FH, $file) or $self->Warn("GetFileTime error for '${file}'"), return (); + $file = *FH; # (not \*FH, so *FH will be kept open until $file goes out of scope) + } + # on Windows, try to work around incorrect file times when daylight saving time is in effect + if ($^O eq 'MSWin32') { + if (not eval { require Win32::API }) { + $self->WarnOnce('Install Win32::API for proper handling of Windows file times'); + } elsif (not eval { require Win32API::File }) { + $self->WarnOnce('Install Win32API::File for proper handling of Windows file times'); + } else { + # get Win32 handle, needed for GetFileTime + my $win32Handle = eval { Win32API::File::GetOsFHandle($file) }; + unless ($win32Handle) { + $self->Warn("Win32API::File::GetOsFHandle returned invalid handle"); + return (); + } + # get FILETIME structs + my ($atime, $mtime, $ctime, $time); + $atime = $mtime = $ctime = pack 'LL', 0, 0; + unless ($k32GetFileTime) { + return () if defined $k32GetFileTime; + $k32GetFileTime = new Win32::API('KERNEL32', 'GetFileTime', 'NPPP', 'I'); + unless ($k32GetFileTime) { + $self->Warn('Error calling Win32::API::GetFileTime'); + $k32GetFileTime = 0; + return (); + } + } + unless ($k32GetFileTime->Call($win32Handle, $ctime, $atime, $mtime)) { + $self->Warn("Win32::API::GetFileTime returned " . Win32::GetLastError()); + return (); + } + # convert FILETIME structs to Unix seconds + foreach $time ($atime, $mtime, $ctime) { + my ($lo, $hi) = unpack 'LL', $time; # unpack FILETIME struct + # FILETIME is in 100 ns intervals since 0:00 UTC Jan 1, 1601 + # (89 leap years between 1601 and 1970) + $time = ($hi * 4294967296 + $lo) * 1e-7 - (((1970-1601)*365+89)*24*3600); + } + return ($atime, $mtime, $ctime); + } + } + # other os (or Windows fallback) + return (stat $file)[8, 9, 10]; +} + +#------------------------------------------------------------------------------ +# Parse function arguments and set member variables accordingly +# Inputs: Same as ImageInfo() +# - sets REQUESTED_TAGS, REQ_TAG_LOOKUP, IO_TAG_LIST, FILENAME, RAF, OPTIONS +sub ParseArguments($;@) +{ + my $self = shift; + my $options = $$self{OPTIONS}; + my @oldGroupOpts = grep /^Group/, keys %{$$self{OPTIONS}}; + my (@exclude, $wasExcludeOpt); + + $$self{REQUESTED_TAGS} = [ ]; + $$self{REQ_TAG_LOOKUP} = { }; + $$self{EXCL_TAG_LOOKUP} = { }; + $$self{IO_TAG_LIST} = undef; + + # handle our input arguments + while (@_) { + my $arg = shift; + if (ref $arg) { + if (ref $arg eq 'ARRAY') { + $$self{IO_TAG_LIST} = $arg; + foreach (@$arg) { + if (/^-(.*)/) { + push @exclude, $1; + } else { + push @{$$self{REQUESTED_TAGS}}, $_; + } + } + } elsif (ref $arg eq 'HASH') { + my $opt; + foreach $opt (keys %$arg) { + # a single new group option overrides all old group options + if (@oldGroupOpts and $opt =~ /^Group/) { + foreach (@oldGroupOpts) { + delete $$options{$_}; + } + undef @oldGroupOpts; + } + $self->Options($opt, $$arg{$opt}); + $opt eq 'Exclude' and $wasExcludeOpt = 1; + } + } elsif (ref $arg eq 'SCALAR' or UNIVERSAL::isa($arg,'GLOB')) { + next if defined $$self{RAF}; + # convert image data from UTF-8 to character stream if necessary + # (patches RHEL 3 UTF8 LANG problem) + if (ref $arg eq 'SCALAR' and $] >= 5.006 and + (eval { require Encode; Encode::is_utf8($$arg) } or $@)) + { + # repack by hand if Encode isn't available + my $buff = $@ ? pack('C*',unpack($] < 5.010000 ? 'U0C*' : 'C0C*',$$arg)) : Encode::encode('utf8',$$arg); + $arg = \$buff; + } + $$self{RAF} = new File::RandomAccess($arg); + # set filename to empty string to indicate that + # we have a file but we didn't open it + $$self{FILENAME} = ''; + } elsif (UNIVERSAL::isa($arg, 'File::RandomAccess')) { + $$self{RAF} = $arg; + $$self{FILENAME} = ''; + } else { + warn "Don't understand ImageInfo argument $arg\n"; + } + } elsif (defined $$self{FILENAME}) { + if ($arg =~ /^-(.*)/) { + push @exclude, $1; + } else { + push @{$$self{REQUESTED_TAGS}}, $arg; + } + } else { + $$self{FILENAME} = $arg; + } + } + # add additional requested tags to lookup + if ($$options{RequestTags}) { + $$self{REQ_TAG_LOOKUP}{$_} = 1 foreach @{$$options{RequestTags}}; + } + # expand shortcuts in tag arguments if provided + if (@{$$self{REQUESTED_TAGS}}) { + ExpandShortcuts($$self{REQUESTED_TAGS}); + # initialize lookup for requested tags + foreach (@{$$self{REQUESTED_TAGS}}) { + /^(.*:)?([-\w?*]*)#?$/ or next; + $$self{REQ_TAG_LOOKUP}{lc($2)} = 1 if $2; + next unless $1; + $$self{REQ_TAG_LOOKUP}{lc($_).':'} = 1 foreach split /:/, $1; + } + } + if (@exclude or $wasExcludeOpt) { + # must add existing excluded tags + push @exclude, @{$$options{Exclude}} if $$options{Exclude}; + $$options{Exclude} = \@exclude; + # expand shortcuts in new exclude list + ExpandShortcuts($$options{Exclude}, 1); # (also remove '#' suffix) + } + # generate lookup for excluded tags + if ($$options{Exclude}) { + foreach (@{$$options{Exclude}}) { + /([-\w]+)#?$/ and $$self{EXCL_TAG_LOOKUP}{lc($1)} = 1; + } + # exclude list is used only for EXCL_TAG_LOOKUP when TAGS_FROM_FILE is set + undef $$options{Exclude} if $$self{TAGS_FROM_FILE}; + } +} + +#------------------------------------------------------------------------------ +# Get list of tags in specified group +# Inputs: 0) ExifTool ref, 1) group spec, 2) tag key or reference to list of tag keys +# Returns: list of matching tags in list context, or first match in scalar context +# Notes: Group spec may contain multiple groups separated by colons, each +# possibly with a leading family number +sub GroupMatches($$$) +{ + my ($self, $group, $tagList) = @_; + $tagList = [ $tagList ] unless ref $tagList; + my ($tag, @matches); + if ($group =~ /:/) { + # check each group name individually (eg. "Author:1IPTC") + my @grps = split ':', lc $group; + my (@fmys, $g); + for ($g=0; $g<@grps; ++$g) { + $fmys[$g] = $1 if $grps[$g] =~ s/^(\d+)//; + } + foreach $tag (@$tagList) { + my @groups = $self->GetGroup($tag, -1); + for ($g=0; $g<@grps; ++$g) { + my $grp = $grps[$g]; + next if $grp eq '*' or $grp eq 'all'; + if (defined $fmys[$g]) { + my $f = $fmys[$g]; + last unless $groups[$f] and $grps[$g] eq lc $groups[$f]; + } else { + last unless grep /^$grps[$g]$/i, @groups; + } + } + if ($g == @grps) { + return $tag unless wantarray; + push @matches, $tag; + } + } + } else { + my $family = ($group =~ s/^(\d+)//) ? $1 : -1; + foreach $tag (@$tagList) { + my @groups = $self->GetGroup($tag, $family); + if (grep(/^$group$/i, @groups)) { + return $tag unless wantarray; + push @matches, $tag; + } + } + } + return wantarray ? @matches : $matches[0]; +} + +#------------------------------------------------------------------------------ +# Remove specified tags from returned tag list, updating indices in other lists +# Inputs: 0) tag list ref, 1) index list ref, 2) index list ref, 3) hash ref, +# 4) true to include tags from hash instead of excluding +# Returns: nothing, but updates input lists +sub RemoveTagsFromList($$$$;$) +{ + local $_; + my ($tags, $list1, $list2, $exclude, $inv) = @_; + my @filteredTags; + + if (@$list1 or @$list2) { + while (@$tags) { + my $tag = pop @$tags; + my $i = @$tags; + if ($$exclude{$tag} xor $inv) { + # remove index of excluded tag from each list + @$list1 = map { $_ < $i ? $_ : $_ == $i ? () : $_ - 1 } @$list1; + @$list2 = map { $_ < $i ? $_ : $_ == $i ? () : $_ - 1 } @$list2; + } else { + unshift @filteredTags, $tag; + } + } + } else { + foreach (@$tags) { + push @filteredTags, $_ unless $$exclude{$_} xor $inv; + } + } + $_[0] = \@filteredTags; # update tag list +} + +#------------------------------------------------------------------------------ +# Set list of found tags from previously requested tags +# Inputs: 0) ExifTool object reference +# Returns: 0) Reference to list of found tag keys (in order of requested tags) +# 1) Reference to list of indices for tags requested by value +# 2) Reference to list of indices for tags specified by wildcard or "all" +# Notes: index lists are returned in increasing order +sub SetFoundTags($) +{ + my $self = shift; + my $options = $$self{OPTIONS}; + my $reqTags = $$self{REQUESTED_TAGS} || [ ]; + my $duplicates = $$options{Duplicates}; + my $exclude = $$options{Exclude}; + my $fileOrder = $$self{FILE_ORDER}; + my @groupOptions = sort grep /^Group/, keys %$options; + my $doDups = $duplicates || $exclude || @groupOptions; + my ($tag, $rtnTags, @byValue, @wildTags); + + # only return requested tags if specified + if (@$reqTags) { + $rtnTags or $rtnTags = [ ]; + # scan through the requested tags and generate a list of tags we found + my $tagHash = $$self{VALUE}; + my $reqTag; + foreach $reqTag (@$reqTags) { + my (@matches, $group, $allGrp, $allTag, $byValue); + if ($reqTag =~ /^(.*):(.+)/) { + ($group, $tag) = ($1, $2); + if ($group =~ /^(\*|all)$/i) { + $allGrp = 1; + } elsif ($group !~ /^[-\w:]*$/) { + $self->Warn("Invalid group name '${group}'"); + $group = 'invalid'; + } + } else { + $tag = $reqTag; + } + $byValue = 1 if $tag =~ s/#$// and $$options{PrintConv}; + if (defined $$tagHash{$reqTag} and not $doDups) { + $matches[0] = $tag; + } elsif ($tag =~ /^(\*|all)$/i) { + # tag name of '*' or 'all' matches all tags + if ($doDups or $allGrp) { + @matches = grep(!/#/, keys %$tagHash); + } else { + @matches = grep(!/ /, keys %$tagHash); + } + next unless @matches; # don't want entry in list for '*' tag + $allTag = 1; + } elsif ($tag =~ /[*?]/) { + # allow wildcards in tag names + $tag =~ s/\*/[-\\w]*/g; + $tag =~ s/\?/[-\\w]/g; + $tag .= '( \\(.*)?' if $doDups or $allGrp; + @matches = grep(/^$tag$/i, keys %$tagHash); + next unless @matches; # don't want entry in list for wildcard tags + $allTag = 1; + } elsif ($doDups or defined $group) { + # must also look for tags like "Tag (1)" + # (but be sure not to match temporary ValueConv entries like "Tag #") + @matches = grep(/^$tag( \(|$)/i, keys %$tagHash); + } elsif ($tag =~ /^[-\w]+$/) { + # find first matching value + # (use in list context to return value instead of count) + ($matches[0]) = grep /^$tag$/i, keys %$tagHash; + defined $matches[0] or undef @matches; + } else { + $self->Warn("Invalid tag name '${tag}'"); + } + if (defined $group and not $allGrp) { + # keep only specified group + @matches = $self->GroupMatches($group, \@matches); + next unless @matches or not $allTag; + } + if (@matches > 1) { + # maintain original file order for multiple tags + @matches = sort { $$fileOrder{$a} <=> $$fileOrder{$b} } @matches; + # return only the highest priority tag unless duplicates wanted + unless ($doDups or $allTag or $allGrp) { + $tag = shift @matches; + my $oldPriority = $$self{PRIORITY}{$tag} || 1; + foreach (@matches) { + my $priority = $$self{PRIORITY}{$_}; + $priority = 1 unless defined $priority; + next unless $priority >= $oldPriority; + $tag = $_; + $oldPriority = $priority || 1; + } + @matches = ( $tag ); + } + } elsif (not @matches) { + # put entry in return list even without value (value is undef) + $matches[0] = $byValue ? "$tag #(0)" : "$tag (0)"; + # bogus file order entry to avoid warning if sorting in file order + $$self{FILE_ORDER}{$matches[0]} = 9999; + } + # save indices of tags extracted by value + push @byValue, scalar(@$rtnTags) .. (scalar(@$rtnTags)+scalar(@matches)-1) if $byValue; + # save indices of wildcard tags + push @wildTags, scalar(@$rtnTags) .. (scalar(@$rtnTags)+scalar(@matches)-1) if $allTag; + push @$rtnTags, @matches; + } + } else { + # no requested tags, so we want all tags + my @allTags; + if ($doDups) { + @allTags = keys %{$$self{VALUE}}; + } else { + # only include tag if it doesn't end in a copy number + @allTags = grep(!/ /, keys %{$$self{VALUE}}); + } + $rtnTags = \@allTags; + } + + # filter excluded tags and group options + while (($exclude or @groupOptions) and @$rtnTags) { + if ($exclude) { + my ($pat, %exclude); + foreach $pat (@$exclude) { + my $group; + if ($pat =~ /^(.*):(.+)/) { + ($group, $tag) = ($1, $2); + if ($group =~ /^(\*|all)$/i) { + undef $group; + } elsif ($group !~ /^[-\w:]*$/) { + $self->Warn("Invalid group name '${group}'"); + $group = 'invalid'; + } + } else { + $tag = $pat; + } + my @matches; + if ($tag =~ /^(\*|all)$/i) { + @matches = @$rtnTags; + } else { + # allow wildcards in tag names + $tag =~ s/\*/[-\\w]*/g; + $tag =~ s/\?/[-\\w]/g; + @matches = grep(/^$tag( |$)/i, @$rtnTags); + } + @matches = $self->GroupMatches($group, \@matches) if $group and @matches; + $exclude{$_} = 1 foreach @matches; + } + if (%exclude) { + # remove excluded tags from return list(s) + RemoveTagsFromList($rtnTags, \@byValue, \@wildTags, \%exclude); + last unless @$rtnTags; # all done if nothing left + } + last if $duplicates and not @groupOptions; + } + # filter groups if requested, or to remove duplicates + my (%keepTags, %wantGroup, $family, $groupOpt); + my $allGroups = 1; + # build hash of requested/excluded group names for each group family + my $wantOrder = 0; + foreach $groupOpt (@groupOptions) { + $groupOpt =~ /^Group(\d*(:\d+)*)/ or next; + $family = $1 || 0; + $wantGroup{$family} or $wantGroup{$family} = { }; + my $groupList; + if (ref $$options{$groupOpt} eq 'ARRAY') { + $groupList = $$options{$groupOpt}; + } else { + $groupList = [ $$options{$groupOpt} ]; + } + foreach (@$groupList) { + # groups have priority in order they were specified + ++$wantOrder; + my ($groupName, $want); + if (/^-(.*)/) { + # excluded group begins with '-' + $groupName = $1; + $want = 0; # we don't want tags in this group + } else { + $groupName = $_; + $want = $wantOrder; # we want tags in this group + $allGroups = 0; # don't want all groups if we requested one + } + $wantGroup{$family}{$groupName} = $want; + } + } + # loop through all tags and decide which ones we want + my (@tags, %bestTag); +GR_TAG: foreach $tag (@$rtnTags) { + my $wantTag = $allGroups; # want tag by default if want all groups + foreach $family (keys %wantGroup) { + my $group = $self->GetGroup($tag, $family); + my $wanted = $wantGroup{$family}{$group}; + next unless defined $wanted; + next GR_TAG unless $wanted; # skip tag if group excluded + # take lowest non-zero want flag + next if $wantTag and $wantTag < $wanted; + $wantTag = $wanted; + } + next unless $wantTag; + $duplicates and $keepTags{$tag} = 1, next; + # determine which tag we want to keep + my $tagName = GetTagName($tag); + my $bestTag = $bestTag{$tagName}; + if (defined $bestTag) { + next if $wantTag > $keepTags{$bestTag}; + if ($wantTag == $keepTags{$bestTag}) { + # want two tags with the same name -- keep the latest one + if ($tag =~ / \((\d+)\)$/) { + my $tagNum = $1; + next if $bestTag !~ / \((\d+)\)$/ or $1 > $tagNum; + } + } + # this tag is better, so delete old best tag + delete $keepTags{$bestTag}; + } + $keepTags{$tag} = $wantTag; # keep this tag (for now...) + $bestTag{$tagName} = $tag; # this is our current best tag + } + # include only tags we want to keep in return lists + RemoveTagsFromList($rtnTags, \@byValue, \@wildTags, \%keepTags, 1); + last; + } + $$self{FOUND_TAGS} = $rtnTags; # save found tags + + # return reference to found tag keys (and list of indices of tags to extract by value) + return wantarray ? ($rtnTags, \@byValue, \@wildTags) : $rtnTags; +} + +#------------------------------------------------------------------------------ +# Utility to load our write routines if required (called via AUTOLOAD) +# Inputs: 0) autoload function, 1-N) function arguments +# Returns: result of function or dies if function not available +sub DoAutoLoad(@) +{ + my $autoload = shift; + my @callInfo = split(/::/, $autoload); + my $file = 'Image/ExifTool/Write'; + + return if $callInfo[$#callInfo] eq 'DESTROY'; + if (@callInfo == 4) { + # load Image/ExifTool/WriteMODULE.pl + $file .= "$callInfo[2].pl"; + } elsif ($callInfo[-1] eq 'ShiftTime') { + $file = 'Image/ExifTool/Shift.pl'; # load Shift.pl + } else { + # load Image/ExifTool/Writer.pl + $file .= 'r.pl'; + } + # attempt to load the package + eval { require $file } or die "Error while attempting to call $autoload\n$@\n"; + unless (defined &$autoload) { + my @caller = caller(0); + # reproduce Perl's standard 'undefined subroutine' message: + die "Undefined subroutine $autoload called at $caller[1] line $caller[2]\n"; + } + no strict 'refs'; + return &$autoload(@_); # call the function +} + +#------------------------------------------------------------------------------ +# AutoLoad our writer routines when necessary +# +sub AUTOLOAD +{ + return DoAutoLoad($AUTOLOAD, @_); +} + +#------------------------------------------------------------------------------ +# Add warning tag +# Inputs: 0) ExifTool object reference, 1) warning message +# 2) true if minor (2 if behaviour changes when warning is ignored, +# or 3 if warning shouldn't be issued when Validate option is used) +# Returns: true if warning tag was added +sub Warn($$;$) +{ + my ($self, $str, $ignorable) = @_; + if ($ignorable) { + return 0 if $$self{OPTIONS}{IgnoreMinorErrors}; + return 0 if $ignorable eq '3' and $$self{OPTIONS}{Validate}; + $str = $ignorable eq '2' ? "[Minor] $str" : "[minor] $str"; + } + $self->FoundTag('Warning', $str); + return 1; +} + +#------------------------------------------------------------------------------ +# Add warning tag only once per processed file +# Inputs: 0) ExifTool object reference, 1) warning message, 2) true if minor +# Returns: true if warning tag was added +sub WarnOnce($$;$) +{ + my ($self, $str, $ignorable) = @_; + return 0 if $ignorable and $$self{OPTIONS}{IgnoreMinorErrors}; + unless ($$self{WARNED_ONCE}{$str}) { + $self->Warn($str, $ignorable); + $$self{WARNED_ONCE}{$str} = 1; + } + return 1; +} + +#------------------------------------------------------------------------------ +# Add error tag +# Inputs: 0) ExifTool object reference, 1) error message, 2) true if minor +# Returns: true if error tag was added, otherwise warning was added +sub Error($$;$) +{ + my ($self, $str, $ignorable) = @_; + if ($$self{DemoteErrors}) { + $self->Warn($str) and ++$$self{DemoteErrors}; + return 1; + } elsif ($ignorable) { + $$self{OPTIONS}{IgnoreMinorErrors} and $self->Warn($str), return 0; + $str = "[minor] $str"; + } + $self->FoundTag('Error', $str); + return 1; +} + +#------------------------------------------------------------------------------ +# Expand shortcuts +# Inputs: 0) reference to list of tags, 1) set to remove trailing '#' +# Notes: Handles leading '-' for excluded tags, trailing '#' for ValueConv, +# multiple group names, and redirected tags +sub ExpandShortcuts($;$) +{ + my ($tagList, $removeSuffix) = @_; + return unless $tagList and @$tagList; + + require Image::ExifTool::Shortcuts; + + # expand shortcuts + my $suffix = $removeSuffix ? '' : '#'; + my @expandedTags; + my ($entry, $tag, $excl); + foreach $entry (@$tagList) { + # skip things like options hash references in list + if (ref $entry) { + push @expandedTags, $entry; + next; + } + # remove leading '-' + ($excl, $tag) = $entry =~ /^(-?)(.*)/s; + my ($post, @post, $pre, $v); + # handle redirection + if (not $excl and $tag =~ /(.+?)([-+]?[<>].+)/s) { + ($tag, $post) = ($1, $2); + if ($post =~ /^[-+]?>/ or $post !~ /\$/) { + # expand shortcuts in postfix (rhs of redirection) + my ($op, $p2, $t2) = ($post =~ /([-+]?[<>])(.+:)?(.+)/); + $p2 = '' unless defined $p2; + $v = ($t2 =~ s/#$//) ? $suffix : ''; # ValueConv suffix + my ($match) = grep /^\Q$t2\E$/i, keys %Image::ExifTool::Shortcuts::Main; + if ($match) { + foreach (@{$Image::ExifTool::Shortcuts::Main{$match}}) { + /^-/ and next; # ignore excluded tags + if ($p2 and /(.+:)(.+)/) { + push @post, "$op$_$v"; + } else { + push @post, "$op$p2$_$v"; + } + } + next unless @post; + $post = shift @post; + } + } + } else { + $post = ''; + } + # handle group names + if ($tag =~ /(.+:)(.+)/) { + ($pre, $tag) = ($1, $2); + } else { + $pre = ''; + } + $v = ($tag =~ s/#$//) ? $suffix : ''; # ValueConv suffix + # loop over all postfixes + for (;;) { + # expand the tag name + my ($match) = grep /^\Q$tag\E$/i, keys %Image::ExifTool::Shortcuts::Main; + if ($match) { + if ($excl) { + # entry starts with '-', so exclude all tags in this shortcut + foreach (@{$Image::ExifTool::Shortcuts::Main{$match}}) { + /^-/ and next; # ignore excluded exclude tags + # group of expanded tag takes precedence + if ($pre and /(.+:)(.+)/) { + push @expandedTags, "$excl$_"; + } else { + push @expandedTags, "$excl$pre$_"; + } + } + } elsif (length $pre or length $post or $v) { + foreach (@{$Image::ExifTool::Shortcuts::Main{$match}}) { + /(-?)(.+:)?(.+)/; + if ($2) { + # group from expanded tag takes precedence + push @expandedTags, "$_$v$post"; + } else { + push @expandedTags, "$1$pre$3$v$post"; + } + } + } else { + push @expandedTags, @{$Image::ExifTool::Shortcuts::Main{$match}}; + } + } else { + push @expandedTags, "$excl$pre$tag$v$post"; + } + last unless @post; + $post = shift @post; + } + } + @$tagList = @expandedTags; +} + +#------------------------------------------------------------------------------ +# Add hash of Composite tags to our composites +# Inputs: 0) hash reference to table of Composite tags to add or module name, +# 1) override existing tag definition +sub AddCompositeTags($;$) +{ + local $_; + my ($add, $override) = @_; + my $module; + unless (ref $add) { + $module = $add; + $add .= '::Composite'; + no strict 'refs'; + $add = \%$add; + } + my $defaultGroups = $$add{GROUPS}; + my $compTable = GetTagTable('Image::ExifTool::Composite'); + + # make sure default groups are defined in families 0 and 1 + if ($defaultGroups) { + $$defaultGroups{0} or $$defaultGroups{0} = 'Composite'; + $$defaultGroups{1} or $$defaultGroups{1} = 'Composite'; + $$defaultGroups{2} or $$defaultGroups{2} = 'Other'; + } else { + $defaultGroups = $$add{GROUPS} = { 0 => 'Composite', 1 => 'Composite', 2 => 'Other' }; + } + SetupTagTable($add); # generate Name, TagID, etc + my $tagID; + foreach $tagID (sort keys %$add) { + next if $specialTags{$tagID}; # must skip special tags + my $tagInfo = $$add{$tagID}; + # tagID's MUST be the exact tag name for logic in BuildCompositeTags() + my $tag = $$tagInfo{Name}; + $$tagInfo{Module} = $module if $$tagInfo{Writable}; + $$tagInfo{Override} = 1 if $override and not defined $$tagInfo{Override}; + $$tagInfo{IsComposite} = 1; + # allow Composite tags with the same name + if ($$compTable{$tag}) { + # determine if we want to override this tag + # (=0 keep both, >0 override, <0 keep existing) + my $over = ($$tagInfo{Override} || 0) - ($$compTable{$tag}{Override} || 0); + next if $over < 0; + my $n; + my $new = $tag; + while ($$compTable{$new}) { + delete $$compTable{$new} if $over; # delete existing entries + $n = ($n || 1) + 1; + $new = "${tag}-$n"; + } + # use new ID and save it so we can use it in TagLookup + $$tagInfo{NewTagID} = $tag = $new unless $over; + } + # convert scalar Require/Desire entries + my $type; + foreach $type ('Require','Desire') { + my $req = $$tagInfo{$type} or next; + $$tagInfo{$type} = { 0 => $req } if ref($req) ne 'HASH'; + } + # add this Composite tag to our main Composite table + $$tagInfo{Table} = $compTable; + # (use the original TagID, even if we changed it, so don't do this:) + # $$tagInfo{TagID} = $tag; + # save tag under NewTagID in Composite table + $$compTable{$tag} = $tagInfo; + # set all default groups in tag + my $groups = $$tagInfo{Groups}; + $groups or $groups = $$tagInfo{Groups} = { }; + # fill in default groups + foreach (keys %$defaultGroups) { + $$groups{$_} or $$groups{$_} = $$defaultGroups{$_}; + } + # set flag indicating group list was built + $$tagInfo{GotGroups} = 1; + } +} + +#------------------------------------------------------------------------------ +# Add tags to TagLookup (used for writing) +# Inputs: 0) source hash of tag definitions, 1) name of destination tag table +sub AddTagsToLookup($$) +{ + my ($tagHash, $table) = @_; + if (defined &Image::ExifTool::TagLookup::AddTags) { + Image::ExifTool::TagLookup::AddTags($tagHash, $table); + } elsif (not $Image::ExifTool::pluginTags{$tagHash}) { + # queue these tags until TagLookup is loaded + push @Image::ExifTool::pluginTags, [ $tagHash, $table ]; + # set flag so we don't load same tags twice + $Image::ExifTool::pluginTags{$tagHash} = 1; + } +} + +#------------------------------------------------------------------------------ +# Expand tagInfo Flags +# Inputs: 0) tagInfo hash ref +# Notes: $$tagInfo{Flags} must be defined to call this routine +sub ExpandFlags($) +{ + my $tagInfo = shift; + my $flags = $$tagInfo{Flags}; + if (ref $flags eq 'ARRAY') { + foreach (@$flags) { + $$tagInfo{$_} = 1; + } + } elsif (ref $flags eq 'HASH') { + my $key; + foreach $key (keys %$flags) { + $$tagInfo{$key} = $$flags{$key}; + } + } else { + $$tagInfo{$flags} = 1; + } +} + +#------------------------------------------------------------------------------ +# Set up tag table (must be done once for each tag table used) +# Inputs: 0) Reference to tag table +# Notes: - generates 'Name' field from key if it doesn't exist +# - stores 'Table' pointer and 'TagID' value +# - expands 'Flags' for quick lookup +sub SetupTagTable($) +{ + my $tagTablePtr = shift; + my $avoid = $$tagTablePtr{AVOID}; + my ($tagID, $tagInfo); + foreach $tagID (TagTableKeys($tagTablePtr)) { + my @infoArray = GetTagInfoList($tagTablePtr,$tagID); + # process conditional tagInfo arrays + foreach $tagInfo (@infoArray) { + $$tagInfo{Table} = $tagTablePtr; + $$tagInfo{TagID} = $tagID; + $$tagInfo{Name} or $$tagInfo{Name} = MakeTagName($tagID); + $$tagInfo{Flags} and ExpandFlags($tagInfo); + $$tagInfo{Avoid} = $avoid if defined $avoid; + # calculate BitShift from Mask if necessary + if ($$tagInfo{Mask} and not defined $$tagInfo{BitShift}) { + my ($mask, $bitShift) = ($$tagInfo{Mask}, 0); + ++$bitShift until $mask & (1 << $bitShift); + $$tagInfo{BitShift} = $bitShift; + } + } + next unless @infoArray > 1; + # add an "Index" member to each tagInfo in a list + my $index = 0; + foreach $tagInfo (@infoArray) { + $$tagInfo{Index} = $index++; + } + } +} + +#------------------------------------------------------------------------------ +# Utilities to check for numerical types +# Inputs: 0) value; Returns: true if value is a numerical type +# Notes: May change commas to decimals in floats for use in other locales +sub IsFloat($) { + return 1 if $_[0] =~ /^[+-]?(?=\d|\.\d)\d*(\.\d*)?([Ee]([+-]?\d+))?$/; + # allow comma separators (for other locales) + return 0 unless $_[0] =~ /^[+-]?(?=\d|,\d)\d*(,\d*)?([Ee]([+-]?\d+))?$/; + $_[0] =~ tr/,/./; # but translate ',' to '.' + return 1; +} +sub IsInt($) { return scalar($_[0] =~ /^[+-]?\d+$/); } +sub IsHex($) { return scalar($_[0] =~ /^(0x)?[0-9a-f]{1,8}$/i); } +sub IsRational($) { return scalar($_[0] =~ m{^[-+]?\d+/\d+$}); } + +# round floating point value to specified number of significant digits +# Inputs: 0) value, 1) number of sig digits; Returns: rounded number +sub RoundFloat($$) +{ + my ($val, $sig) = @_; + return sprintf("%.${sig}g", $val); +} + +# Convert strings to floating point numbers (or undef) +# Inputs: 0-N) list of strings (may be undef) +# Returns: last value converted +sub ToFloat(@) +{ + local $_; + foreach (@_) { + next unless defined $_; + # (add 0 to convert "0.0" to "0" for tests) + $_ = /((?:[+-]?)(?=\d|\.\d)\d*(?:\.\d*)?(?:[Ee](?:[+-]?\d+))?)/ ? $1 + 0 : undef; + } + return $_[-1]; +} + +#------------------------------------------------------------------------------ +# Utility routines to for reading binary data values from file + +my %unpackMotorola = ( S => 'n', L => 'N', C => 'C', c => 'c' ); +my %unpackIntel = ( S => 'v', L => 'V', C => 'C', c => 'c' ); +my %unpackRev = ( N => 'V', V => 'N', C => 'C', n => 'v', v => 'n', c => 'c' ); + +# the following 4 variables are defined in 'use vars' instead of using 'my' +# because mod_perl 5.6.1 apparently has a problem with setting file-scope 'my' +# variables from within subroutines (ref communication with Pavel Merdin): +# $swapBytes - set if EXIF header is not native byte ordering +# $swapWords - swap 32-bit words in doubles (ARM quirk) +$currentByteOrder = 'MM'; # current byte ordering ('II' or 'MM') +%unpackStd = %unpackMotorola; + +# Swap bytes in data if necessary +# Inputs: 0) data, 1) number of bytes +# Returns: swapped data +sub SwapBytes($$) +{ + return $_[0] unless $swapBytes; + my ($val, $bytes) = @_; + my $newVal = ''; + $newVal .= substr($val, $bytes, 1) while $bytes--; + return $newVal; +} +# Swap words. Inputs: 8 bytes of data, Returns: swapped data +sub SwapWords($) +{ + return $_[0] unless $swapWords and length($_[0]) == 8; + return substr($_[0],4,4) . substr($_[0],0,4) +} + +# Unpack value, letting unpack() handle byte swapping +# Inputs: 0) unpack template, 1) data reference, 2) offset +# Returns: unpacked number +# - uses value of %unpackStd to determine the unpack template +# - can only be called for 'S' or 'L' templates since these are the only +# templates for which you can specify the byte ordering. +sub DoUnpackStd(@) +{ + $_[2] and return unpack("x$_[2] $unpackStd{$_[0]}", ${$_[1]}); + return unpack($unpackStd{$_[0]}, ${$_[1]}); +} +# same, but with reversed byte order +sub DoUnpackRev(@) +{ + my $fmt = $unpackRev{$unpackStd{$_[0]}}; + $_[2] and return unpack("x$_[2] $fmt", ${$_[1]}); + return unpack($fmt, ${$_[1]}); +} +# Pack value +# Inputs: 0) template, 1) value, 2) data ref (or undef), 3) offset (if data ref) +# Returns: packed value +sub DoPackStd(@) +{ + my $val = pack($unpackStd{$_[0]}, $_[1]); + $_[2] and substr(${$_[2]}, $_[3], length($val)) = $val; + return $val; +} +# same, but with reversed byte order +sub DoPackRev(@) +{ + my $val = pack($unpackRev{$unpackStd{$_[0]}}, $_[1]); + $_[2] and substr(${$_[2]}, $_[3], length($val)) = $val; + return $val; +} + +# Unpack value, handling the byte swapping manually +# Inputs: 0) # bytes, 1) unpack template, 2) data reference, 3) offset +# Returns: unpacked number +# - uses value of $swapBytes to determine byte ordering +sub DoUnpack(@) +{ + my ($bytes, $template, $dataPt, $pos) = @_; + my $val; + if ($swapBytes) { + $val = ''; + $val .= substr($$dataPt,$pos+$bytes,1) while $bytes--; + } else { + $val = substr($$dataPt,$pos,$bytes); + } + defined($val) or return undef; + return unpack($template,$val); +} + +# Unpack double value +# Inputs: 0) unpack template, 1) data reference, 2) offset +# Returns: unpacked number +sub DoUnpackDbl(@) +{ + my ($template, $dataPt, $pos) = @_; + my $val = substr($$dataPt,$pos,8); + defined($val) or return undef; + # swap bytes and 32-bit words (ARM quirk) if necessary, then unpack value + return unpack($template, SwapWords(SwapBytes($val, 8))); +} + +# Inputs: 0) data reference, 1) offset into data +sub Get8s($$) { return DoUnpackStd('c', @_); } +sub Get8u($$) { return DoUnpackStd('C', @_); } +sub Get16s($$) { return DoUnpack(2, 's', @_); } +sub Get16u($$) { return DoUnpackStd('S', @_); } +sub Get32s($$) { return DoUnpack(4, 'l', @_); } +sub Get32u($$) { return DoUnpackStd('L', @_); } +sub GetFloat($$) { return DoUnpack(4, 'f', @_); } +sub GetDouble($$) { return DoUnpackDbl('d', @_); } +sub Get16uRev($$) { return DoUnpackRev('S', @_); } +sub Get32uRev($$) { return DoUnpackRev('L', @_); } + +# rationals may be a floating point number, 'inf' or 'undef' +my ($ratNumer, $ratDenom); +sub GetRational32s($$) +{ + my ($dataPt, $pos) = @_; + $ratNumer = Get16s($dataPt,$pos); + $ratDenom = Get16s($dataPt, $pos + 2) or return $ratNumer ? 'inf' : 'undef'; + # round off to a reasonable number of significant figures + return RoundFloat($ratNumer / $ratDenom, 7); +} +sub GetRational32u($$) +{ + my ($dataPt, $pos) = @_; + $ratNumer = Get16u($dataPt,$pos); + $ratDenom = Get16u($dataPt, $pos + 2) or return $ratNumer ? 'inf' : 'undef'; + return RoundFloat($ratNumer / $ratDenom, 7); +} +sub GetRational64s($$) +{ + my ($dataPt, $pos) = @_; + $ratNumer = Get32s($dataPt,$pos); + $ratDenom = Get32s($dataPt, $pos + 4) or return $ratNumer ? 'inf' : 'undef'; + return RoundFloat($ratNumer / $ratDenom, 10); +} +sub GetRational64u($$) +{ + my ($dataPt, $pos) = @_; + $ratNumer = Get32u($dataPt,$pos); + $ratDenom = Get32u($dataPt, $pos + 4) or return $ratNumer ? 'inf' : 'undef'; + return RoundFloat($ratNumer / $ratDenom, 10); +} +sub GetFixed16s($$) +{ + my ($dataPt, $pos) = @_; + my $val = Get16s($dataPt, $pos) / 0x100; + return int($val * 1000 + ($val<0 ? -0.5 : 0.5)) / 1000; +} +sub GetFixed16u($$) +{ + my ($dataPt, $pos) = @_; + return int((Get16u($dataPt, $pos) / 0x100) * 1000 + 0.5) / 1000; +} +sub GetFixed32s($$) +{ + my ($dataPt, $pos) = @_; + my $val = Get32s($dataPt, $pos) / 0x10000; + # remove insignificant digits + return int($val * 1e5 + ($val>0 ? 0.5 : -0.5)) / 1e5; +} +sub GetFixed32u($$) +{ + my ($dataPt, $pos) = @_; + # remove insignificant digits + return int((Get32u($dataPt, $pos) / 0x10000) * 1e5 + 0.5) / 1e5; +} +# Inputs: 0) value, 1) data ref, 2) offset +sub Set8s(@) { return DoPackStd('c', @_); } +sub Set8u(@) { return DoPackStd('C', @_); } +sub Set16u(@) { return DoPackStd('S', @_); } +sub Set32u(@) { return DoPackStd('L', @_); } +sub Set16uRev(@) { return DoPackRev('S', @_); } + +#------------------------------------------------------------------------------ +# Get current byte order ('II' or 'MM') +sub GetByteOrder() { return $currentByteOrder; } + +#------------------------------------------------------------------------------ +# Set byte ordering +# Inputs: 0) 'MM'=motorola, 'II'=intel (will translate 'BigEndian', 'LittleEndian') +# Returns: 1 on success +sub SetByteOrder($) +{ + my $order = shift; + + if ($order eq 'MM') { # big endian (Motorola) + %unpackStd = %unpackMotorola; + } elsif ($order eq 'II') { # little endian (Intel) + %unpackStd = %unpackIntel; + } elsif ($order =~ /^Big/i) { + $order = 'MM'; + %unpackStd = %unpackMotorola; + } elsif ($order =~ /^Little/i) { + $order = 'II'; + %unpackStd = %unpackIntel; + } else { + return 0; + } + my $val = unpack('S','A '); + my $nativeOrder; + if ($val == 0x4120) { # big endian + $nativeOrder = 'MM'; + } elsif ($val == 0x2041) { # little endian + $nativeOrder = 'II'; + } else { + warn sprintf("Unknown native byte order! (pattern %x)\n",$val); + return 0; + } + $currentByteOrder = $order; # save current byte order + + # swap bytes if our native CPU byte ordering is not the same as the EXIF + $swapBytes = ($order ne $nativeOrder); + + # little-endian ARM has big-endian words for doubles (thanks Riku Voipio) + # (Note: Riku's patch checked for '0ff3', but I think it should be 'f03f' since + # 1 is '000000000000f03f' on an x86 -- so check for both, but which is correct?) + my $pack1d = pack('d', 1); + $swapWords = ($pack1d eq "\0\0\x0f\xf3\0\0\0\0" or + $pack1d eq "\0\0\xf0\x3f\0\0\0\0"); + return 1; +} + +#------------------------------------------------------------------------------ +# Change byte order +sub ToggleByteOrder() +{ + SetByteOrder(GetByteOrder() eq 'II' ? 'MM' : 'II'); +} + +#------------------------------------------------------------------------------ +# hash lookups for reading values from data +my %formatSize = ( + int8s => 1, + int8u => 1, + int16s => 2, + int16u => 2, + int16uRev => 2, + int32s => 4, + int32u => 4, + int32uRev => 4, + int64s => 8, + int64u => 8, + rational32s => 4, + rational32u => 4, + rational64s => 8, + rational64u => 8, + fixed16s => 2, + fixed16u => 2, + fixed32s => 4, + fixed32u => 4, + fixed64s => 8, + float => 4, + double => 8, + extended => 10, + unicode => 2, + complex => 8, + string => 1, + binary => 1, + 'undef' => 1, + ifd => 4, + ifd64 => 8, + ue7 => 1, +); +my %readValueProc = ( + int8s => \&Get8s, + int8u => \&Get8u, + int16s => \&Get16s, + int16u => \&Get16u, + int16uRev => \&Get16uRev, + int32s => \&Get32s, + int32u => \&Get32u, + int32uRev => \&Get32uRev, + int64s => \&Get64s, + int64u => \&Get64u, + rational32s => \&GetRational32s, + rational32u => \&GetRational32u, + rational64s => \&GetRational64s, + rational64u => \&GetRational64u, + fixed16s => \&GetFixed16s, + fixed16u => \&GetFixed16u, + fixed32s => \&GetFixed32s, + fixed32u => \&GetFixed32u, + fixed64s => \&GetFixed64s, + float => \&GetFloat, + double => \&GetDouble, + extended => \&GetExtended, + ifd => \&Get32u, + ifd64 => \&Get64u, +); +# lookup for all rational types +my %isRational = ( + rational32u => 1, + rational32s => 1, + rational64u => 1, + rational64s => 1, +); +sub FormatSize($) { return $formatSize{$_[0]}; } + +#------------------------------------------------------------------------------ +# Read value from binary data (with current byte ordering) +# Inputs: 0) data reference, 1) value offset, 2) format string, +# 3) number of values (or undef to use all data) +# 4) valid data length relative to offset, 5) optional pointer to returned rational +# Returns: converted value, or undefined if data isn't there +# or list of values in list context +sub ReadValue($$$$$;$) +{ + my ($dataPt, $offset, $format, $count, $size, $ratPt) = @_; + + my $len = $formatSize{$format}; + unless ($len) { + warn "Unknown format $format"; + $len = 1; + } + unless ($count) { + return '' if defined $count or $size < $len; + $count = int($size / $len); + } + # make sure entry is inside data + if ($len * $count > $size) { + $count = int($size / $len); # shorten count if necessary + $count < 1 and return undef; # return undefined if no data + } + my @vals; + my $proc = $readValueProc{$format}; + if (not $proc) { + # handle undef/binary/string (also unsupported unicode/complex) + $vals[0] = substr($$dataPt, $offset, $count * $len); + # truncate string at null terminator if necessary + $vals[0] =~ s/\0.*//s if $format eq 'string'; + } elsif ($isRational{$format} and $ratPt) { + # store rationals separately as string fractions + my @rat; + for (;;) { + push @vals, &$proc($dataPt, $offset); + push @rat, "$ratNumer/$ratDenom"; + last if --$count <= 0; + $offset += $len; + } + $$ratPt = join(' ',@rat); + } else { + for (;;) { + push @vals, &$proc($dataPt, $offset); + last if --$count <= 0; + $offset += $len; + } + } + return @vals if wantarray; + return join(' ', @vals) if @vals > 1; + return $vals[0]; +} + +#------------------------------------------------------------------------------ +# Decode string with specified encoding +# Inputs: 0) ExifTool object ref, 1) string to decode +# 2) source character set name (undef for current Charset) +# 3) optional source byte order (2-byte and 4-byte fixed-width sets only) +# 4) optional destination character set (defaults to Charset setting) +# 5) optional destination byte order (2-byte and 4-byte fixed-width only) +# Returns: string in destination encoding +# Note: ExifTool ref may be undef if character both character sets are provided +# (but in this case no warnings will be issued) +sub Decode($$$;$$$) +{ + my ($self, $val, $from, $fromOrder, $to, $toOrder) = @_; + $from or $from = $$self{OPTIONS}{Charset}; + $to or $to = $$self{OPTIONS}{Charset}; + if ($from ne $to and length $val) { + require Image::ExifTool::Charset; + my $cs1 = $Image::ExifTool::Charset::csType{$from}; + my $cs2 = $Image::ExifTool::Charset::csType{$to}; + if ($cs1 and $cs2 and not $cs2 & 0x002) { + # treat as straight ASCII if no character will need remapping + if (($cs1 | $cs2) & 0x680 or $val =~ /[\x80-\xff]/) { + my $uni = Image::ExifTool::Charset::Decompose($self, $val, $from, $fromOrder); + $val = Image::ExifTool::Charset::Recompose($self, $uni, $to, $toOrder); + } + } elsif ($self) { + my $set = $cs1 ? $to : $from; + unless ($$self{"DecodeWarn$set"}) { + $self->Warn("Unsupported character set ($set)"); + $$self{"DecodeWarn$set"} = 1; + } + } + } + return $val; +} + +#------------------------------------------------------------------------------ +# Encode string with specified encoding +# Inputs: 0) ExifTool object ref, 1) string, 2) destination character set name, +# 3) optional destination byte order (2-byte and 4-byte fixed-width sets only) +# Returns: string in specified encoding +sub Encode($$$;$) +{ + my ($self, $val, $to, $toOrder) = @_; + return $self->Decode($val, undef, undef, $to, $toOrder); +} + +#------------------------------------------------------------------------------ +# Decode bit mask +# Inputs: 0) value to decode, 1) Reference to hash for decoding (or undef) +# 2) optional bits per word (defaults to 32) +sub DecodeBits($$;$) +{ + my ($vals, $lookup, $bits) = @_; + $bits or $bits = 32; + my ($val, $i, @bitList); + my $num = 0; + foreach $val (split ' ', $vals) { + for ($i=0; $i<$bits; ++$i) { + next unless $val & (1 << $i); + my $n = $i + $num; + if (not $lookup) { + push @bitList, $n; + } elsif ($$lookup{$n}) { + push @bitList, $$lookup{$n}; + } else { + push @bitList, "[$n]"; + } + } + $num += $bits; + } + return '(none)' unless @bitList; + return join($lookup ? ', ' : ',', @bitList); +} + +#------------------------------------------------------------------------------ +# Validate an extracted image and repair if necessary +# Inputs: 0) ExifTool object reference, 1) image reference, 2) tag name or key +# Returns: image reference or undef if it wasn't valid +# Note: should be called from RawConv, not ValueConv +sub ValidateImage($$$) +{ + my ($self, $imagePt, $tag) = @_; + return undef if $$imagePt eq 'none'; + unless ($$imagePt =~ /^(Binary data|\xff\xd8\xff)/ or + # the first byte of the preview of some Minolta cameras is wrong, + # so check for this and set it back to 0xff if necessary + $$imagePt =~ s/^.(\xd8\xff\xdb)/\xff$1/s or + $self->Options('IgnoreMinorErrors')) + { + # issue warning only if the tag was specifically requested + if ($$self{REQ_TAG_LOOKUP}{lc GetTagName($tag)}) { + $self->Warn("$tag is not a valid JPEG image",1); + return undef; + } + } + return $imagePt; +} + +#------------------------------------------------------------------------------ +# Validate a tag name argument (including group name and wildcards, etc) +# Inputs: 0) tag name +# Returns: true if tag name is valid +# - a tag name may contain [-_A-Za-z0-9], but may not start with [-0-9] +# - tag names may contain wildcards [?*], and end with a hash [#] +# - may have group name prefixes (which may have family number prefix), separated by colons +# - a group name may be zero or more characters +sub ValidTagName($) +{ + my $tag = shift; + return $tag =~ /^(([-\w]*|\d*\*):)*[_a-zA-Z?*][-\w?*]*#?$/; +} + +#------------------------------------------------------------------------------ +# Generate a valid tag name based on the tag ID or name +# Inputs: 0) tag ID or name +# Returns: valid tag name +sub MakeTagName($) +{ + my $name = shift; + $name =~ tr/-_a-zA-Z0-9//dc; # remove illegal characters + $name = ucfirst $name; # capitalize first letter + $name = "Tag$name" if length($name) < 2; # must at least 2 characters long + return $name; +} + +#------------------------------------------------------------------------------ +# Make description from a tag name +# Inputs: 0) tag name 1) optional tagID to add at end of description +# Returns: description +sub MakeDescription($;$) +{ + my ($tag, $tagID) = @_; + # start with the tag name and force first letter to be upper case + my $desc = ucfirst($tag); + # translate underlines to spaces + $desc =~ tr/_/ /; + # remove hex TagID from name (to avoid inserting spaces in the number) + $desc =~ s/ (0x[\da-f]+)$//i and $tagID = $1 unless defined $tagID; + # put a space between lower/UPPER case and lower/number combinations + $desc =~ s/([a-z])([A-Z\d])/$1 $2/g; + # put a space between acronyms and words + $desc =~ s/([A-Z])([A-Z][a-z])/$1 $2/g; + # put spaces after numbers (if more than one character follows the number) + $desc =~ s/(\d)([A-Z]\S)/$1 $2/g; + # add TagID to description + $desc .= ' ' . $tagID if defined $tagID; + return $desc; +} + +#------------------------------------------------------------------------------ +# Get descriptions for all tags in an array +# Inputs: 0) ExifTool ref, 1) reference to list of tag keys +# Returns: reference to hash lookup for descriptions +# Note: Returned descriptions are NOT escaped by ESCAPE_PROC +sub GetDescriptions($$) +{ + local $_; + my ($self, $tags) = @_; + my %desc; + my $oldEscape = $$self{ESCAPE_PROC}; + delete $$self{ESCAPE_PROC}; + $desc{$_} = $self->GetDescription($_) foreach @$tags; + $$self{ESCAPE_PROC} = $oldEscape; + return \%desc; +} + +#------------------------------------------------------------------------------ +# Apply filter to value(s) if necessary +# Inputs: 0) ExifTool ref, 1-N) references to values(s) to filter +# Returns: nothing, but changes values if necessary +sub Filter($@) +{ + local $_; + my $self = shift; + return unless defined $$self{OPTIONS}{Filter}; + while (@_) { + my $valPt = shift; + next unless defined $$valPt; + if (not ref $$valPt) { + $_ = $$valPt; + #### eval Filter ($_) + eval $$self{OPTIONS}{Filter}; + $$valPt = $_ if defined $_; + } elsif (ref $$valPt eq 'SCALAR') { + my $val = $$$valPt; # make a copy to avoid filtering twice + $self->Filter(\$val); + $$valPt = \$val; + } elsif (ref $$valPt eq 'ARRAY') { + my @val = @{$$valPt}; # make a copy to avoid filtering twice + $self->Filter(\$_) foreach @val; + $$valPt = \@val; + } elsif (ref $$valPt eq 'HASH') { + my %val = %{$$valPt}; # make a copy to avoid filtering twice + $self->Filter(\$val{$_}) foreach keys %val; + $$valPt = \%val; + } + } +} + +#------------------------------------------------------------------------------ +# Return printable value +# Inputs: 0) ExifTool object reference +# 1) value to print, 2) line length limit (undef defaults to 60, 0=unlimited) +sub Printable($;$) +{ + my ($self, $outStr, $maxLen) = @_; + return '(undef)' unless defined $outStr; + $outStr =~ tr/\x01-\x1f\x7f-\xff/./; + $outStr =~ s/\x00//g; + my $verbose = $$self{OPTIONS}{Verbose}; + if ($verbose < 4) { + if ($maxLen) { + $maxLen = 20 if $maxLen < 20; # minimum length is 20 + } elsif (defined $maxLen) { + $maxLen = length $outStr; # 0 is unlimited + } else { + $maxLen = 60; # default maximum is 60 + } + } else { + $maxLen = length $outStr; + # limit to 2048 characters if verbose < 5 + $maxLen = 2048 if $maxLen > 2048 and $verbose < 5; + } + + # limit length if necessary + $outStr = substr($outStr,0,$maxLen-6) . '[snip]' if length($outStr) > $maxLen; + return $outStr; +} + +#------------------------------------------------------------------------------ +# Convert date/time from Exif format +# Inputs: 0) ExifTool object reference, 1) Date/time in EXIF format +# Returns: Formatted date/time string +sub ConvertDateTime($$) +{ + my ($self, $date) = @_; + my $fmt = $$self{OPTIONS}{DateFormat}; + my $shift = $$self{OPTIONS}{GlobalTimeShift}; + if ($shift) { + my $dir = ($shift =~ s/^([-+])// and $1 eq '-') ? -1 : 1; + my $offset = $$self{GLOBAL_TIME_OFFSET}; + $offset or $offset = $$self{GLOBAL_TIME_OFFSET} = { }; + ShiftTime($date, $shift, $dir, $offset); + } + # only convert date if a format was specified and the date is recognizable + if ($fmt) { + # separate time zone if it exists + my $tz; + $date =~ s/([-+]\d{2}:\d{2}|Z)$// and $tz = $1; + # a few cameras use incorrect date/time formatting: + # - slashes instead of colons in date (RolleiD330, ImpressCam) + # - date/time values separated by colon instead of space (Polariod, Sanyo, Sharp, Vivitar) + # - single-digit seconds with leading space (HP scanners) + my @a = reverse ($date =~ /\d+/g); # be very flexible about date/time format + if (@a and $a[-1] >= 1000 and $a[-1] < 3000 and eval { require POSIX }) { + shift @a while @a > 6; # remove superfluous entries + unshift @a, 1 while @a < 3; # add month and day if necessary + unshift @a, 0 while @a < 6; # add h,m,s if necessary + $a[5] -= 1900; # base year is 1900 + $a[4] -= 1; # base month is 1 + # parse %z and %s ourself (to handle time zones properly) + if ($fmt =~ /%[sz]/) { + # use system time zone unless otherwise specified + $tz = TimeZoneString(\@a, TimeLocal(@a)) if not $tz and eval { require Time::Local }; + # remove colon, setting to UTC if time zone is not numeric + $tz = ($tz and $tz=~/^([-+]\d{2}):(\d{2})$/) ? "$1$2" : '+0000'; + $fmt =~ s/(^|[^%])((%%)*)%z/$1$2$tz/g; # convert '%z' format codes + if ($fmt =~ /%s/ and eval { require Time::Local }) { + # calculate seconds since the Epoch, UTC + my $s = Time::Local::timegm(@a) - 60 * ($tz - int($tz/100) * 40); + $fmt =~ s/(^|[^%])((%%)*)%s/$1$2$s/g; # convert '%s' format codes + } + } + $date = POSIX::strftime($fmt, @a); # generate the formatted date/time + } elsif ($$self{OPTIONS}{StrictDate}) { + undef $date; + } + } + return $date; +} + +#------------------------------------------------------------------------------ +# Print conversion for time span value +# Inputs: 0) time ticks, 1) number of seconds per tick (default 1) +# Returns: readable time +sub ConvertTimeSpan($;$) +{ + my ($val, $mult) = @_; + if (Image::ExifTool::IsFloat($val) and $val != 0) { + $val *= $mult if $mult; + if ($val < 60) { + $val = "$val seconds"; + } elsif ($val < 3600) { + my $fmt = ($mult and $mult >= 60) ? '%d' : '%.1f'; + my $s = ($val == 60 and $mult) ? '' : 's'; + $val = sprintf("$fmt minute$s", $val / 60); + } elsif ($val < 24 * 3600) { + $val = sprintf("%.1f hours", $val / 3600); + } else { + $val = sprintf("%.1f days", $val / (24 * 3600)); + } + } + return $val; +} + +#------------------------------------------------------------------------------ +# Patched timelocal() that fixes ActivePerl timezone bug +# Inputs/Returns: same as timelocal() +# Notes: must 'require Time::Local' before calling this routine +sub TimeLocal(@) +{ + my $tm = Time::Local::timelocal(@_); + if ($^O eq 'MSWin32') { + # patch for ActivePerl timezone bug + my @t2 = localtime($tm); + my $t2 = Time::Local::timelocal(@t2); + # adjust timelocal() return value to be consistent with localtime() + $tm += $tm - $t2; + } + return $tm; +} + +#------------------------------------------------------------------------------ +# Get time zone in minutes +# Inputs: 0) localtime array ref, 1) gmtime array ref +# Returns: time zone offset in minutes +sub GetTimeZone($$) +{ + my ($tm, $gm) = @_; + # compute the number of minutes between localtime and gmtime + my $min = $$tm[2] * 60 + $$tm[1] - ($$gm[2] * 60 + $$gm[1]); + if ($$tm[3] != $$gm[3]) { + # account for case where one date wraps to the first of the next month + $$gm[3] = $$tm[3] - ($$tm[3]==1 ? 1 : -1) if abs($$tm[3]-$$gm[3]) != 1; + # adjust for the +/- one day difference + $min += ($$tm[3] - $$gm[3]) * 24 * 60; + } + # MirBSD patch to round to the nearest 30 minutes because + # it includes leap seconds in localtime but not gmtime + $min = int($min / 30 + ($min > 0 ? 0.5 : -0.5)) * 30 if $^O eq 'mirbsd'; + return $min; +} + +#------------------------------------------------------------------------------ +# Get time zone string +# Inputs: 0) time zone offset in minutes +# or 0) localtime array ref, 1) corresponding time value +# Returns: time zone string ("+/-HH:MM") +sub TimeZoneString($;$) +{ + my $min = shift; + if (ref $min) { + my @gm = gmtime(shift); + $min = GetTimeZone($min, \@gm); + } + my $sign = '+'; + $min < 0 and $sign = '-', $min = -$min; + $min = int($min + 0.5); # round off to nearest minute + my $h = int($min / 60); + return sprintf('%s%.2d:%.2d', $sign, $h, $min - $h * 60); +} + +#------------------------------------------------------------------------------ +# Convert Unix time to EXIF date/time string +# Inputs: 0) Unix time value, 1) non-zero to convert to local time, 2) number of decimal digits +# Returns: EXIF date/time string (with timezone for local times) +# Notes: fractional seconds are ignored +sub ConvertUnixTime($;$$) +{ + my ($time, $toLocal, $dec) = @_; + return '0000:00:00 00:00:00' if $time == 0; + my (@tm, $tz); + if ($dec) { + my $frac = $time - int($time); + $time = int($time); + $frac < 0 and $frac += 1, $time -= 1; + $dec = sprintf('%.*f', $dec, $frac); + # remove number before decimal and increment integer time if it was rounded up + $dec =~ s/^(\d)// and $1 eq '1' and $time += 1; + } else { + $time = int($time + 1e-6) if $time != int($time); # avoid round-off errors + $dec = ''; + } + if ($toLocal) { + @tm = localtime($time); + $tz = TimeZoneString(\@tm, $time); + } else { + @tm = gmtime($time); + $tz = ''; + } + my $str = sprintf("%4d:%.2d:%.2d %.2d:%.2d:%.2d$dec%s", + $tm[5]+1900, $tm[4]+1, $tm[3], $tm[2], $tm[1], $tm[0], $tz); + return $str; +} + +#------------------------------------------------------------------------------ +# Get Unix time from EXIF-formatted date/time string with optional timezone +# Inputs: 0) EXIF date/time string, 1) non-zero if time is local +# Returns: Unix time (seconds since 0:00 GMT Jan 1, 1970) or undefined on error +sub GetUnixTime($;$) +{ + my ($timeStr, $isLocal) = @_; + return 0 if $timeStr eq '0000:00:00 00:00:00'; + my @tm = ($timeStr =~ /^(\d+):(\d+):(\d+)\s+(\d+):(\d+):(\d+)(.*)/); + return undef unless @tm == 7 and eval { require Time::Local }; + my ($tzStr, $tzSec) = (pop(@tm), 0); + # use specified timezone offset (if given) instead of local system time + # if we are converting a local time value + if ($isLocal and $tzStr =~ /(?:Z|([-+])(\d+):(\d+))/i) { + # use specified timezone if one exists + $tzSec = ($2 * 60 + $3) * ($1 eq '-' ? -60 : 60) if $1; + undef $isLocal; # convert using GMT corrected for specified timezone + } + $tm[0] -= 1900; # convert year + $tm[1] -= 1; # convert month + @tm = reverse @tm; # change to order required by timelocal() + return $isLocal ? TimeLocal(@tm) : Time::Local::timegm(@tm) - $tzSec; +} + +#------------------------------------------------------------------------------ +# Print conversion for file size +# Inputs: 0) file size in bytes +# Returns: converted file size +sub ConvertFileSize($) +{ + my $val = shift; + $val < 2048 and return "$val bytes"; + $val < 10240 and return sprintf('%.1f kB', $val / 1024); + $val < 2097152 and return sprintf('%.0f kB', $val / 1024); + $val < 10485760 and return sprintf('%.1f MB', $val / 1048576); + $val < 2147483648 and return sprintf('%.0f MB', $val / 1048576); + $val < 10737418240 and return sprintf('%.1f GB', $val / 1073741824); + return sprintf('%.0f GB', $val / 1073741824); +} + +#------------------------------------------------------------------------------ +# Convert seconds to duration string (handles negative durations) +# Inputs: 0) floating point seconds +# Returns: duration string in form "S.SS s", "MM:SS" or "H:MM:SS" +sub ConvertDuration($) +{ + my $time = shift; + return $time unless IsFloat($time); + return '0 s' if $time == 0; + my $sign = ($time > 0 ? '' : (($time = -$time), '-')); + return sprintf("$sign%.2f s", $time) if $time < 30; + $time += 0.5; # to round off to nearest second + my $h = int($time / 3600); + $time -= $h * 3600; + my $m = int($time / 60); + $time -= $m * 60; + if ($h > 24) { + my $d = int($h / 24); + $h -= $d * 24; + $sign = "$sign$d days "; + } + return sprintf("$sign%d:%.2d:%.2d", $h, $m, int($time)); +} + +#------------------------------------------------------------------------------ +# Print conversion for bitrate values +# Inputs: 0) bitrate in bits per second +# Returns: human-readable bitrate string +# Notes: returns input value without formatting if it isn't numerical +sub ConvertBitrate($) +{ + my $bitrate = shift; + IsFloat($bitrate) or return $bitrate; + my @units = ('bps', 'kbps', 'Mbps', 'Gbps'); + for (;;) { + my $units = shift @units; + $bitrate >= 1000 and @units and $bitrate /= 1000, next; + my $fmt = $bitrate < 100 ? '%.3g' : '%.0f'; + return sprintf("$fmt $units", $bitrate); + } +} + +#------------------------------------------------------------------------------ +# Convert file name for printing +# Inputs: 0) ExifTool ref, 1) file name in CharsetFileName character set +# Returns: converted file name in external character set +sub ConvertFileName($$) +{ + my ($self, $val) = @_; + my $enc = $$self{OPTIONS}{CharsetFileName}; + $val = $self->Decode($val, $enc) if $enc; + return $val; +} + +#------------------------------------------------------------------------------ +# Inverse conversion for file name (encode in CharsetFileName) +# Inputs: 0) ExifTool ref, 1) file name in external character set +# Returns: file name in CharsetFileName character set +sub InverseFileName($$) +{ + my ($self, $val) = @_; + my $enc = $$self{OPTIONS}{CharsetFileName}; + $val = $self->Encode($val, $enc) if $enc; + $val =~ tr/\\/\//; # make sure we are using forward slashes + return $val; +} + +#------------------------------------------------------------------------------ +# Save information for HTML dump +# Inputs: 0) ExifTool hash ref, 1) start offset, 2) data size +# 3) comment string, 4) tool tip (or SAME), 5) flags, 6) IFD name +sub HDump($$$$;$$$) +{ + my $self = shift; + $$self{HTML_DUMP} or return; + my ($pos, $len, $com, $tip, $flg, $ifd) = @_; + $pos += $$self{BASE} if $$self{BASE}; + # skip structural data blocks which have been removed from the middle of this dump + # (SkipData list contains ordered [start,end+1] offsets to skip) + if ($$self{SkipData}) { + my $end = $pos + $len; + my $skip; + foreach $skip (@{$$self{SkipData}}) { + $end <= $$skip[0] and last; + $pos >= $$skip[1] and $pos += $$skip[1] - $$skip[0], next; + if ($pos != $$skip[0]) { + $$self{HTML_DUMP}->Add($pos, $$skip[0]-$pos, $com, $tip, $flg, $ifd); + $len -= $$skip[0] - $pos; + $tip = 'SAME'; + } + $pos = $$skip[1]; + } + } + $$self{HTML_DUMP}->Add($pos, $len, $com, $tip, $flg, $ifd); +} + +#------------------------------------------------------------------------------ +# Identify trailer ending at specified offset from end of file +# Inputs: 0) RAF reference, 1) offset from end of file (0 by default) +# Returns: Trailer info hash (with RAF and DirName set), +# or undef if no recognized trailer was found +# Notes: leaves file position unchanged +sub IdentifyTrailer($;$) +{ + my $raf = shift; + my $offset = shift || 0; + my $pos = $raf->Tell(); + my ($buff, $type, $len); + while ($raf->Seek(-$offset, 2) and ($len = $raf->Tell()) > 0) { + # read up to 64 bytes before specified offset from end of file + $len = 64 if $len > 64; + $raf->Seek(-$len, 1) and $raf->Read($buff, $len) == $len or last; + if ($buff =~ /AXS(!|\*).{8}$/s) { + $type = 'AFCP'; + } elsif ($buff =~ /\xa1\xb2\xc3\xd4$/) { + $type = 'FotoStation'; + } elsif ($buff =~ /cbipcbbl$/) { + $type = 'PhotoMechanic'; + } elsif ($buff =~ /^CANON OPTIONAL DATA\0/) { + $type = 'CanonVRD'; + } elsif ($buff =~ /~\0\x04\0zmie~\0\0\x06.{4}[\x10\x18]\x04$/s or + $buff =~ /~\0\x04\0zmie~\0\0\x0a.{8}[\x10\x18]\x08$/s) + { + $type = 'MIE'; + } elsif ($buff =~ /\0\0(QDIOBS|SEFT)$/) { + $type = 'Samsung'; + } + last; + } + $raf->Seek($pos, 0); # restore original file position + return $type ? { RAF => $raf, DirName => $type } : undef; +} + +#------------------------------------------------------------------------------ +# Read/rewrite trailer information (including multiple trailers) +# Inputs: 0) ExifTool object ref, 1) DirInfo ref: +# - requires RAF and DirName +# - OutFile is a scalar reference for writing +# - scans from current file position if ScanForAFCP is set +# Returns: 1 if trailer was processed or couldn't be processed (or written OK) +# 0 if trailer was recognized but offsets need fixing (or write error) +# - DirName, DirLen, DataPos, Offset, Fixup and OutFile are updated +# - preserves current file position and byte order +sub ProcessTrailers($$) +{ + my ($self, $dirInfo) = @_; + my $dirName = $$dirInfo{DirName}; + my $outfile = $$dirInfo{OutFile}; + my $offset = $$dirInfo{Offset} || 0; + my $fixup = $$dirInfo{Fixup}; + my $raf = $$dirInfo{RAF}; + my $pos = $raf->Tell(); + my $byteOrder = GetByteOrder(); + my $success = 1; + my $path = $$self{PATH}; + + for (;;) { # loop through all trailers + require "Image/ExifTool/$dirName.pm"; + my $proc = "Image::ExifTool::${dirName}::Process$dirName"; + my $outBuff; + if ($outfile) { + # write to local buffer so we can add trailer in proper order later + $$outfile and $$dirInfo{OutFile} = \$outBuff, $outBuff = ''; + # must generate new fixup if necessary so we can shift + # the old fixup separately after we prepend this trailer + delete $$dirInfo{Fixup}; + } + delete $$dirInfo{DirLen}; # reset trailer length + $$dirInfo{Offset} = $offset; # set offset from end of file + $$dirInfo{Trailer} = 1; # set Trailer flag in case proc cares + # add trailer and DirName to SubDirectory PATH + push @$path, 'Trailer', $dirName; + + # read or write this trailer + # (proc takes Offset as offset from end of trailer to end of file, + # and returns DataPos and DirLen, and Fixup if applicable) + no strict 'refs'; + my $result = &$proc($self, $dirInfo); + use strict 'refs'; + + # restore PATH (pop last 2 items) + splice @$path, -2; + + # check result + if ($outfile) { + if ($result > 0) { + if ($outBuff) { + # write trailers to OutFile in original order + $$outfile = $outBuff . $$outfile; + # must adjust old fixup start if it exists + $$fixup{Start} += length($outBuff) if $fixup; + $outBuff = ''; # free memory + } + if ($$dirInfo{Fixup}) { + if ($fixup) { + # add fixup for subsequent trailers to the fixup for this trailer + # (but first we must adjust for the new start position) + $$fixup{Shift} += $$dirInfo{Fixup}{Start}; + $$fixup{Start} -= $$dirInfo{Fixup}{Start}; + $$dirInfo{Fixup}->AddFixup($fixup); + } + $fixup = $$dirInfo{Fixup}; # save fixup + } + } else { + $success = 0 if $self->Error("Error rewriting $dirName trailer", 2); + last; + } + } elsif ($result < 0) { + # can't continue if we must scan for this trailer + $success = 0; + last; + } + last unless $result > 0 and $$dirInfo{DirLen}; + # look for next trailer + $offset += $$dirInfo{DirLen}; + my $nextTrail = IdentifyTrailer($raf, $offset) or last; + $dirName = $$dirInfo{DirName} = $$nextTrail{DirName}; + $raf->Seek($pos, 0); + } + SetByteOrder($byteOrder); # restore original byte order + $raf->Seek($pos, 0); # restore original file position + $$dirInfo{OutFile} = $outfile; # restore original outfile + $$dirInfo{Offset} = $offset; # return offset from EOF to start of first trailer + $$dirInfo{Fixup} = $fixup; # return fixup information + return $success; +} + +#------------------------------------------------------------------------------ +# JPEG constants + +# JPEG marker names +%jpegMarker = ( + 0x00 => 'NULL', + 0x01 => 'TEM', + 0xc0 => 'SOF0', # to SOF15, with a few exceptions below + 0xc4 => 'DHT', + 0xc8 => 'JPGA', + 0xcc => 'DAC', + 0xd0 => 'RST0', # to RST7 + 0xd8 => 'SOI', + 0xd9 => 'EOI', + 0xda => 'SOS', + 0xdb => 'DQT', + 0xdc => 'DNL', + 0xdd => 'DRI', + 0xde => 'DHP', + 0xdf => 'EXP', + 0xe0 => 'APP0', # to APP15 + 0xf0 => 'JPG0', + 0xfe => 'COM', +); + +# lookup for size of JPEG marker length word +# (2 bytes assumed unless specified here) +my %markerLenBytes = ( + 0x00 => 0, 0x01 => 0, + 0xd0 => 0, 0xd1 => 0, 0xd2 => 0, 0xd3 => 0, 0xd4 => 0, 0xd5 => 0, 0xd6 => 0, 0xd7 => 0, + 0xd8 => 0, 0xd9 => 0, 0xda => 0, + # J2C + 0x30 => 0, 0x31 => 0, 0x32 => 0, 0x33 => 0, 0x34 => 0, 0x35 => 0, 0x36 => 0, 0x37 => 0, + 0x38 => 0, 0x39 => 0, 0x3a => 0, 0x3b => 0, 0x3c => 0, 0x3d => 0, 0x3e => 0, 0x3f => 0, + 0x4f => 0, + 0x92 => 0, 0x93 => 0, + # J2C extensions + 0x74 => 4, 0x75 => 4, 0x77 => 4, +); + +#------------------------------------------------------------------------------ +# Get JPEG marker name +# Inputs: 0) Jpeg number +# Returns: marker name +sub JpegMarkerName($) +{ + my $marker = shift; + my $markerName = $jpegMarker{$marker}; + unless ($markerName) { + $markerName = $jpegMarker{$marker & 0xf0}; + if ($markerName and $markerName =~ /^([A-Z]+)\d+$/) { + $markerName = $1 . ($marker & 0x0f); + } else { + $markerName = sprintf("marker 0x%.2x", $marker); + } + } + return $markerName; +} + +#------------------------------------------------------------------------------ +# Adjust directory start position +# Inputs: 0) dirInfo ref, 1) start offset +# 2) Base for offsets (relative to DataPos, defaults to absolute Base of 0) +sub DirStart($$;$) +{ + my ($dirInfo, $start, $base) = @_; + $$dirInfo{DirStart} = $start; + $$dirInfo{DirLen} -= $start; + if (defined $base) { + $$dirInfo{Base} = $$dirInfo{DataPos} + $base; + $$dirInfo{DataPos} = -$base; # (relative to Base!) + } +} + +#------------------------------------------------------------------------------ +# Extract metadata from a jpg image +# Inputs: 0) ExifTool object reference, 1) dirInfo ref with RAF set +# Returns: 1 on success, 0 if this wasn't a valid JPEG file +sub ProcessJPEG($$) +{ + local $_; + my ($self, $dirInfo) = @_; + my ($ch, $s, $length); + my $options = $$self{OPTIONS}; + my $verbose = $$options{Verbose}; + my $out = $$options{TextOut}; + my $fast = $$options{FastScan}; + my $raf = $$dirInfo{RAF}; + my $htmlDump = $$self{HTML_DUMP}; + my %dumpParms = ( Out => $out ); + my ($success, $wantTrailer, $trailInfo, $foundSOS); + my (@iccChunk, $iccChunkCount, $iccChunksTotal, @flirChunk, $flirCount, $flirTotal); + my ($preview, $scalado, @dqt, $subSampling, $dumpEnd, %extendedXMP); + + # check to be sure this is a valid JPG (or J2C, or EXV) file + return 0 unless $raf->Read($s, 2) == 2 and $s =~ /^\xff[\xd8\x4f\x01]/; + if ($s eq "\xff\x01") { + return 0 unless $raf->Read($s, 5) == 5 and $s eq 'Exiv2'; + $$self{FILE_TYPE} = 'EXV'; + } + if (not $$self{VALUE}{FileType} or ($$self{DOC_NUM} and $$options{ExtractEmbedded})) { + $self->SetFileType(); # set FileType tag + return 1 if $fast and $fast == 3; # don't process file when FastScan == 3 + $$self{LOW_PRIORITY_DIR}{IFD1} = 1; # lower priority of IFD1 tags + } + $$raf{NoBuffer} = 1 if $self->Options('FastScan'); # disable buffering in FastScan mode + + $dumpParms{MaxLen} = 128 if $verbose < 4; + if ($htmlDump) { + $dumpEnd = $raf->Tell(); + my ($n, $t, $m) = $s eq 'Exiv2' ? (7,'EXV','TEM') : (2,'JPEG','SOI'); + my $pos = $dumpEnd - $n; + $self->HDump(0, $pos, '[unknown header]') if $pos; + $self->HDump($pos, $n, "$t header", "$m Marker"); + } + my $path = $$self{PATH}; + my $pn = scalar @$path; + + # set input record separator to 0xff (the JPEG marker) to make reading quicker + local $/ = "\xff"; + + my ($nextMarker, $nextSegDataPt, $nextSegPos, $combinedSegData, $firstSegPos, @skipData); + + # read file until we reach an end of image (EOI) or start of scan (SOS) + Marker: for (;;) { + # set marker and data pointer for current segment + my $marker = $nextMarker; + my $segDataPt = $nextSegDataPt; + my $segPos = $nextSegPos; + undef $nextMarker; + undef $nextSegDataPt; +# +# read ahead to the next segment unless we have reached EOI, SOS or SOD +# + unless ($marker and ($marker==0xd9 or ($marker==0xda and not $wantTrailer) or $marker==0x93)) { + # read up to next marker (JPEG markers begin with 0xff) + my $buff; + $raf->ReadLine($buff) or last; + # JPEG markers can be padded with unlimited 0xff's + for (;;) { + $raf->Read($ch, 1) or last Marker; + $nextMarker = ord($ch); + last unless $nextMarker == 0xff; + } + # read segment data if it exists + if (not defined $markerLenBytes{$nextMarker}) { + # read record length word + last unless $raf->Read($s, 2) == 2; + my $len = unpack('n',$s); # get data length + last unless defined($len) and $len >= 2; + $nextSegPos = $raf->Tell(); + $len -= 2; # subtract size of length word + last unless $raf->Read($buff, $len) == $len; + $nextSegDataPt = \$buff; # set pointer to our next data + } elsif ($markerLenBytes{$nextMarker} == 4) { + # handle J2C extensions with 4-byte length word + last unless $raf->Read($s, 4) == 4; + my $len = unpack('N',$s); # get data length + last unless defined($len) and $len >= 4; + $nextSegPos = $raf->Tell(); + $len -= 4; # subtract size of length word + last unless $raf->Seek($len, 1); + } + # read second segment too if this was the first + next unless defined $marker; + } + # set some useful variables for the current segment + my $markerName = JpegMarkerName($marker); + $$path[$pn] = $markerName; +# +# parse the current segment +# + # handle SOF markers: SOF0-SOF15, except DHT(0xc4), JPGA(0xc8) and DAC(0xcc) + if (($marker & 0xf0) == 0xc0 and ($marker == 0xc0 or $marker & 0x03)) { + $length = length $$segDataPt; + if ($verbose) { + print $out "JPEG $markerName ($length bytes):\n"; + HexDump($segDataPt, undef, %dumpParms, Addr=>$segPos) if $verbose>2; + } elsif ($htmlDump) { + $self->HDump($segPos-4, $length+4, "[JPEG $markerName]", undef, 0x08); + $dumpEnd = $segPos + $length; + } + next unless $length >= 6; + # extract some useful information + my ($p, $h, $w, $n) = unpack('Cn2C', $$segDataPt); + my $sof = GetTagTable('Image::ExifTool::JPEG::SOF'); + $self->HandleTag($sof, 'ImageWidth', $w); + $self->HandleTag($sof, 'ImageHeight', $h); + $self->HandleTag($sof, 'EncodingProcess', $marker - 0xc0); + $self->HandleTag($sof, 'BitsPerSample', $p); + $self->HandleTag($sof, 'ColorComponents', $n); + next unless $n == 3 and $length >= 15; + my ($i, $hmin, $hmax, $vmin, $vmax); + # loop through all components to determine sampling frequency + $subSampling = ''; + for ($i=0; $i<$n; ++$i) { + my $sf = Get8u($segDataPt, 7 + 3 * $i); + $subSampling .= sprintf('%.2x', $sf); + # isolate horizontal and vertical components + my ($hf, $vf) = ($sf >> 4, $sf & 0x0f); + unless ($i) { + $hmin = $hmax = $hf; + $vmin = $vmax = $vf; + next; + } + # determine min/max frequencies + $hmin = $hf if $hf < $hmin; + $hmax = $hf if $hf > $hmax; + $vmin = $vf if $vf < $vmin; + $vmax = $vf if $vf > $vmax; + } + if ($hmin and $vmin) { + my ($hs, $vs) = ($hmax / $hmin, $vmax / $vmin); + $self->FoundTag($$sof{YCbCrSubSampling}, "$hs $vs"); + } + next; + } elsif ($marker == 0xd9) { # EOI + pop @$path; + $verbose and print $out "JPEG EOI\n"; + my $pos = $raf->Tell(); + if ($htmlDump and $dumpEnd) { + $self->HDump($dumpEnd, $pos-2-$dumpEnd, '[JPEG Image Data]', undef, 0x08); + $self->HDump($pos-2, 2, 'JPEG EOI', undef); + $dumpEnd = 0; + } + if ($foundSOS or $$self{FILE_TYPE} eq 'EXV') { + $success = 1; + } else { + $self->Warn('Missing JPEG SOS'); + } + # we are here because we are looking for trailer information + if ($wantTrailer) { + my $start = $$self{PreviewImageStart}; + if ($start) { + my $buff; + # most previews start right after the JPEG EOI, but the Olympus E-20 + # preview is 508 bytes into the trailer, the K-M Maxxum 7D preview is + # 979 bytes in, and Sony previews can start up to 32 kB into the trailer. + # (and Minolta and Sony previews can have a random first byte...) + my $scanLen = $$self{Make} =~ /Sony/i ? 65536 : 1024; + if ($raf->Read($buff, $scanLen) and ($buff =~ /\xff\xd8\xff./g or + ($$self{Make} =~ /(Minolta|Sony)/i and $buff =~ /.\xd8\xff\xdb/g))) + { + # adjust PreviewImageStart to this location + my $actual = $pos + pos($buff) - 4; + if ($start ne $actual and $verbose > 1) { + print $out "(Fixed PreviewImage location: $start -> $actual)\n"; + } + # update preview image offsets + $$self{VALUE}{PreviewImageStart} = $actual if $$self{VALUE}{PreviewImageStart}; + $$self{PreviewImageStart} = $actual; + # load preview now if we tried and failed earlier + if ($$self{PreviewError} and $$self{PreviewImageLength}) { + if ($raf->Seek($actual, 0) and $raf->Read($buff, $$self{PreviewImageLength})) { + $self->FoundTag('PreviewImage', $buff); + delete $$self{PreviewError}; + } + } + } + $raf->Seek($pos, 0); + } + } + # process trailer now or finish processing trailers + # and scan for AFCP if necessary + my $fromEnd = 0; + if ($trailInfo) { + $$trailInfo{ScanForAFCP} = 1; # scan now if necessary + $self->ProcessTrailers($trailInfo); + # save offset from end of file to start of first trailer + $fromEnd = $$trailInfo{Offset}; + undef $trailInfo; + } + if ($$self{LeicaTrailer}) { + $raf->Seek(0, 2); + $$self{LeicaTrailer}{TrailPos} = $pos; + $$self{LeicaTrailer}{TrailLen} = $raf->Tell() - $pos - $fromEnd; + Image::ExifTool::Panasonic::ProcessLeicaTrailer($self); + } + # finally, dump remaining information in JPEG trailer + if ($verbose or $htmlDump) { + my $endPos = $$self{LeicaTrailerPos}; + unless ($endPos) { + $raf->Seek(0, 2); + $endPos = $raf->Tell() - $fromEnd; + } + $self->DumpUnknownTrailer({ + RAF => $raf, + DataPos => $pos, + DirLen => $endPos - $pos + }) if $endPos > $pos; + } + last; # all done parsing file + } elsif ($marker == 0xda) { # SOS + pop @$path; + $foundSOS = 1; + # all done with meta information unless we have a trailer + $verbose and print $out "JPEG SOS\n"; + unless ($fast) { + $trailInfo = IdentifyTrailer($raf); + # process trailer now unless we are doing verbose dump + if ($trailInfo and $verbose < 3 and not $htmlDump) { + # process trailers (keep trailInfo to finish processing later + # only if we can't finish without scanning from end of file) + $self->ProcessTrailers($trailInfo) and undef $trailInfo; + } + if ($wantTrailer) { + # seek ahead and validate preview image + my $buff; + my $curPos = $raf->Tell(); + if ($raf->Seek($$self{PreviewImageStart}, 0) and + $raf->Read($buff, 4) == 4 and + $buff =~ /^.\xd8\xff[\xc4\xdb\xe0-\xef]/) + { + undef $wantTrailer; + } + $raf->Seek($curPos, 0) or last; + } + # seek ahead and process Leica trailer + if ($$self{LeicaTrailer}) { + require Image::ExifTool::Panasonic; + Image::ExifTool::Panasonic::ProcessLeicaTrailer($self); + $wantTrailer = 1 if $$self{LeicaTrailer}; + } + next if $trailInfo or $wantTrailer or $verbose > 2 or $htmlDump; + } + next if $$options{Validate}; # (validate to EOI) + # nothing interesting to parse after start of scan (SOS) + $success = 1; + last; # all done parsing file + } elsif ($marker == 0x93) { + pop @$path; + $verbose and print $out "JPEG SOD\n"; + $success = 1; + next if $verbose > 2 or $htmlDump; + last; # all done parsing file + } elsif (defined $markerLenBytes{$marker}) { + # handle other stand-alone markers and segments we skipped over + $verbose and $marker and print $out "JPEG $markerName\n"; + next; + } elsif ($marker == 0xdb and length($$segDataPt) and # DQT + # save the DQT data only if JPEGDigest has been requested + # (Note: since we aren't checking the RequestAll API option here, the application + # must use the RequestTags option to generate these tags if they have not been + # specifically requested. The reason is that there is too much overhead involved + # in the calculation of this tag to make this worth the CPU time.) + ($$self{REQ_TAG_LOOKUP}{jpegdigest} or $$self{REQ_TAG_LOOKUP}{jpegqualityestimate} + or ($$options{RequestAll} and $$options{RequestAll} > 2))) + { + my $num = unpack('C',$$segDataPt) & 0x0f; # get table index + $dqt[$num] = $$segDataPt if $num < 4; # save for MD5 calculation + } + # handle all other markers + my $dumpType = ''; + my ($desc, $tip, $xtra); + $length = length $$segDataPt; + if ($verbose) { + print $out "JPEG $markerName ($length bytes):\n"; + if ($verbose > 2) { + my %extraParms = ( Addr => $segPos ); + $extraParms{MaxLen} = 128 if $verbose == 4; + HexDump($segDataPt, undef, %dumpParms, %extraParms); + } + } + # prepare dirInfo hash for processing this information + my %dirInfo = ( + Parent => $markerName, + DataPt => $segDataPt, + DataPos => $segPos, + DataLen => $length, + DirStart => 0, + DirLen => $length, + Base => 0, + ); + if ($marker == 0xe0) { # APP0 (JFIF, JFXX, CIFF, AVI1, Ocad) + if ($$segDataPt =~ /^JFIF\0/) { + $dumpType = 'JFIF'; + DirStart(\%dirInfo, 5); # start at byte 5 + SetByteOrder('MM'); + my $tagTablePtr = GetTagTable('Image::ExifTool::JFIF::Main'); + $self->ProcessDirectory(\%dirInfo, $tagTablePtr); + } elsif ($$segDataPt =~ /^JFXX\0(\x10|\x11|\x13)/) { + my $tag = ord $1; + $dumpType = 'JFXX'; + my $tagTablePtr = GetTagTable('Image::ExifTool::JFIF::Extension'); + my $tagInfo = $self->GetTagInfo($tagTablePtr, $tag); + $self->FoundTag($tagInfo, substr($$segDataPt, 6)); + } elsif ($$segDataPt =~ /^(II|MM).{4}HEAPJPGM/s) { + next if $fast and $fast > 1; # skip processing for very fast + $dumpType = 'CIFF'; + my %dirInfo = ( RAF => new File::RandomAccess($segDataPt) ); + $$self{SET_GROUP1} = 'CIFF'; + push @{$$self{PATH}}, 'CIFF'; + require Image::ExifTool::CanonRaw; + Image::ExifTool::CanonRaw::ProcessCRW($self, \%dirInfo); + pop @{$$self{PATH}}; + delete $$self{SET_GROUP1}; + } elsif ($$segDataPt =~ /^(AVI1|Ocad)/) { + $dumpType = $1; + SetByteOrder('MM'); + my $tagTablePtr = GetTagTable("Image::ExifTool::JPEG::$dumpType"); + DirStart(\%dirInfo, 4); + $self->ProcessDirectory(\%dirInfo, $tagTablePtr); + } + } elsif ($marker == 0xe1) { # APP1 (EXIF, XMP, QVCI) + # (some Kodak cameras don't put a second "\0", and I have seen an + # example where there was a second 4-byte APP1 segment header) + if ($$segDataPt =~ /^(.{0,4})Exif\0/is) { + undef $dumpType; # (will be dumped here) + # this is EXIF data -- + # get the data block (into a common variable) + my $hdrLen = length($exifAPP1hdr); + if (length $1) { + $hdrLen += length $1; + $self->Warn('Unknown garbage at start of EXIF segment',1); + } elsif ($$segDataPt !~ /^Exif\0/) { + $self->Warn('Incorrect EXIF segment identifier',1); + } + if ($htmlDump) { + $self->HDump($segPos-4, 4, 'APP1 header', "Data size: $length bytes"); + $self->HDump($segPos, $hdrLen, 'Exif header', 'APP1 data type: Exif'); + $dumpEnd = $segPos + $length; + } + my $dataPt = $segDataPt; + if (defined $combinedSegData) { + push @skipData, [ $segPos-4, $segPos+$hdrLen ]; + $combinedSegData .= substr($$segDataPt,$hdrLen); + undef $$segDataPt; + $dataPt = \$combinedSegData; + $segPos = $firstSegPos; + } + # peek ahead to see if the next segment is extended EXIF + if ($nextMarker == $marker and + $$nextSegDataPt =~ /^$exifAPP1hdr(?!(MM\0\x2a|II\x2a\0))/) + { + # initialize combined data if necessary + unless (defined $combinedSegData) { + $combinedSegData = $$segDataPt; + undef $$segDataPt; + $firstSegPos = $segPos; + $self->Warn('File contains multi-segment EXIF',1); + $$self{ExtendedEXIF} = 1; + } + next; + } + $dirInfo{DataPt} = $dataPt; + $dirInfo{DataPos} = $segPos; + $dirInfo{DataLen} = $dirInfo{DirLen} = length $$dataPt; + DirStart(\%dirInfo, $hdrLen, $hdrLen); + $$self{SkipData} = \@skipData if @skipData; + # extract the EXIF information (it is in standard TIFF format) + $self->ProcessTIFF(\%dirInfo) or $self->Warn('Malformed APP1 EXIF segment'); + # avoid looking for preview unless necessary because it really slows + # us down -- only look for it if we found pointer, and preview is + # outside EXIF, and PreviewImage is specifically requested + my $start = $self->GetValue('PreviewImageStart', 'ValueConv'); + my $plen = $self->GetValue('PreviewImageLength', 'ValueConv'); + if (not $start or not $plen and $$self{PreviewError}) { + $start = $$self{PreviewImageStart}; + $plen = $$self{PreviewImageLength}; + } + if ($start and $plen and IsInt($start) and IsInt($plen) and + $start + $plen > $$self{EXIF_POS} + length($$self{EXIF_DATA}) and + ($$self{REQ_TAG_LOOKUP}{previewimage} or + # (extracted normally, so check Binary option) + ($$options{Binary} and not $$self{EXCL_TAG_LOOKUP}{previewimage}))) + { + $$self{PreviewImageStart} = $start; + $$self{PreviewImageLength} = $plen; + $wantTrailer = 1; + } + if (@skipData) { + undef @skipData; + delete $$self{SkipData}; + } + undef $$dataPt; + next; + } elsif ($$segDataPt =~ /^$xmpExtAPP1hdr/) { + # off len -- extended XMP header (75 bytes total): + # 0 35 bytes - signature + # 35 32 bytes - GUID (MD5 hash of full extended XMP data in ASCII) + # 67 4 bytes - total size of extended XMP data + # 71 4 bytes - offset for this XMP data portion + $dumpType = 'Extended XMP'; + if ($length > 75) { + my ($size, $off) = unpack('x67N2', $$segDataPt); + my $guid = substr($$segDataPt, 35, 32); + if ($guid =~ /[^A-Za-z0-9]/) { # (technically, should be uppercase) + $self->WarnOnce($tip = 'Invalid extended XMP GUID'); + } else { + my $extXMP = $extendedXMP{$guid}; + if (not $extXMP) { + $extXMP = $extendedXMP{$guid} = { }; + } elsif ($size != $$extXMP{Size}) { + $self->WarnOnce('Inconsistent extended XMP size'); + } + $$extXMP{Size} = $size; + $$extXMP{$off} = substr($$segDataPt, 75); + $tip = "Full length: $size\nChunk offset: $off\nChunk length: " . + ($length - 75) . "\nGUID: $guid"; + # (delay processing extended XMP until after reading all segments) + } + } else { + $self->WarnOnce($tip = 'Invalid extended XMP segment'); + } + } elsif ($$segDataPt =~ /^QVCI\0/) { + $dumpType = 'QVCI'; + my $tagTablePtr = GetTagTable('Image::ExifTool::Casio::QVCI'); + $self->ProcessDirectory(\%dirInfo, $tagTablePtr); + } elsif ($$segDataPt =~ /^FLIR\0/ and $length >= 8) { + $dumpType = 'FLIR'; + # must concatenate FLIR chunks (note: handle the case where + # some software erroneously writes zeros for the chunk counts) + my $chunkNum = Get8u($segDataPt, 6); + my $chunksTot = Get8u($segDataPt, 7) + 1; # (note the "+ 1"!) + $verbose and printf $out "$$self{INDENT}FLIR chunk %d of %d\n", + $chunkNum + 1, $chunksTot; + if (defined $flirTotal) { + # abort parsing FLIR if the total chunk count is inconsistent + undef $flirCount if $chunksTot != $flirTotal; + } else { + $flirCount = 0; + $flirTotal = $chunksTot; + } + if (defined $flirCount) { + if (defined $flirChunk[$chunkNum]) { + $self->WarnOnce('Duplicate FLIR chunk number(s)'); + $flirChunk[$chunkNum] .= substr($$segDataPt, 8); + } else { + $flirChunk[$chunkNum] = substr($$segDataPt, 8); + } + # process the FLIR information if we have all of the chunks + if (++$flirCount >= $flirTotal) { + my $flir = ''; + defined $_ and $flir .= $_ foreach @flirChunk; + undef @flirChunk; # free memory + my $tagTablePtr = GetTagTable('Image::ExifTool::FLIR::FFF'); + my %dirInfo = ( + DataPt => \$flir, + Parent => $markerName, + DirName => 'FLIR', + ); + $self->ProcessDirectory(\%dirInfo, $tagTablePtr); + undef $flirCount; # prevent reprocessing + } + } else { + $self->WarnOnce('Invalid or extraneous FLIR chunk(s)'); + } + } else { + # Hmmm. Could be XMP, let's see + my $processed; + if ($$segDataPt =~ /^(http|XMP\0)/ or $$segDataPt =~ /<(exif:|\?xpacket)/) { + $dumpType = 'XMP'; + # also try to parse XMP with a non-standard header + # (note: this non-standard XMP is ignored when writing) + my $start = ($$segDataPt =~ /^$xmpAPP1hdr/) ? length($xmpAPP1hdr) : 0; + my $tagTablePtr = GetTagTable('Image::ExifTool::XMP::Main'); + DirStart(\%dirInfo, $start); + $dirInfo{DirName} = $start ? 'XMP' : 'XML', + $processed = $self->ProcessDirectory(\%dirInfo, $tagTablePtr); + if ($processed and not $start) { + $self->Warn('Non-standard header for APP1 XMP segment'); + } + } + if ($verbose and not $processed) { + $self->Warn("Ignored APP1 segment length $length (unknown header)"); + } + } + } elsif ($marker == 0xe2) { # APP2 (ICC Profile, FPXR, MPF, PreviewImage) + if ($$segDataPt =~ /^ICC_PROFILE\0/ and $length >= 14) { + $dumpType = 'ICC_Profile'; + # must concatenate profile chunks (note: handle the case where + # some software erroneously writes zeros for the chunk counts) + my $chunkNum = Get8u($segDataPt, 12); + my $chunksTot = Get8u($segDataPt, 13); + $verbose and print $out "$$self{INDENT}ICC_Profile chunk $chunkNum of $chunksTot\n"; + if (defined $iccChunksTotal) { + # abort parsing ICC_Profile if the total chunk count is inconsistent + undef $iccChunkCount if $chunksTot != $iccChunksTotal; + } else { + $iccChunkCount = 0; + $iccChunksTotal = $chunksTot; + $self->Warn('ICC_Profile chunk count is zero') if !$chunksTot; + } + if (defined $iccChunkCount) { + if (defined $iccChunk[$chunkNum]) { + $self->WarnOnce('Duplicate ICC_Profile chunk number(s)'); + $iccChunk[$chunkNum] .= substr($$segDataPt, 14); + } else { + $iccChunk[$chunkNum] = substr($$segDataPt, 14); + } + # process profile if we have all of the chunks + if (++$iccChunkCount >= $iccChunksTotal) { + my $icc_profile = ''; + defined $_ and $icc_profile .= $_ foreach @iccChunk; + undef @iccChunk; # free memory + my $tagTablePtr = GetTagTable('Image::ExifTool::ICC_Profile::Main'); + my %dirInfo = ( + DataPt => \$icc_profile, + DataPos => $segPos + 14, + DataLen => length($icc_profile), + DirStart => 0, + DirLen => length($icc_profile), + Parent => $markerName, + ); + $self->ProcessDirectory(\%dirInfo, $tagTablePtr); + undef $iccChunkCount; # prevent reprocessing + } + } else { + $self->WarnOnce('Invalid or extraneous ICC_Profile chunk(s)'); + } + } elsif ($$segDataPt =~ /^FPXR\0/) { + next if $fast and $fast > 1; # skip processing for very fast + $dumpType = 'FPXR'; + my $tagTablePtr = GetTagTable('Image::ExifTool::FlashPix::Main'); + # set flag if this is the last FPXR segment + $dirInfo{LastFPXR} = not ($nextMarker==$marker and $$nextSegDataPt=~/^FPXR\0/), + $self->ProcessDirectory(\%dirInfo, $tagTablePtr); + } elsif ($$segDataPt =~ /^MPF\0/) { + undef $dumpType; # (will be dumped here) + DirStart(\%dirInfo, 4, 4); + $dirInfo{Multi} = 1; # the MP Attribute IFD will be MPF1 + if ($htmlDump) { + $self->HDump($segPos-4, 4, 'APP2 header', "Data size: $length bytes"); + $self->HDump($segPos, 4, 'MPF header', 'APP2 data type: MPF'); + $dumpEnd = $segPos + $length; + } + # extract the MPF information (it is in standard TIFF format) + my $tagTablePtr = GetTagTable('Image::ExifTool::MPF::Main'); + $self->ProcessTIFF(\%dirInfo, $tagTablePtr); + } elsif ($$segDataPt =~ /^(|QVGA\0|BGTH)\xff\xd8\xff[\xdb\xe0\xe1]/) { + # Samsung/GE/GoPro="", BenQ DC C1220/Pentacon/Polaroid="QVGA\0", + # Digilife DDC-690/Rollei="BGTH" + $dumpType = 'Preview Image'; + $preview = substr($$segDataPt, length($1)); + } elsif ($preview) { + $dumpType = 'Preview Image'; + $preview .= $$segDataPt; + } + if ($preview and $nextMarker ne $marker) { + $self->FoundTag('PreviewImage', $preview); + undef $preview; + } + } elsif ($marker == 0xe3) { # APP3 (Kodak "Meta", Stim) + if ($$segDataPt =~ /^(Meta|META|Exif)\0\0/) { + undef $dumpType; # (will be dumped here) + DirStart(\%dirInfo, 6, 6); + if ($htmlDump) { + $self->HDump($segPos-4, 10, 'APP3 Meta header'); + $dumpEnd = $segPos + $length; + } + my $tagTablePtr = GetTagTable('Image::ExifTool::Kodak::Meta'); + $self->ProcessTIFF(\%dirInfo, $tagTablePtr); + } elsif ($$segDataPt =~ /^Stim\0/) { + undef $dumpType; # (will be dumped here) + DirStart(\%dirInfo, 6, 6); + if ($htmlDump) { + $self->HDump($segPos-4, 4, 'APP3 header', "Data size: $length bytes"); + $self->HDump($segPos, 5, 'Stim header', 'APP3 data type: Stim'); + $dumpEnd = $segPos + $length; + } + # extract the Stim information (it is in standard TIFF format) + my $tagTablePtr = GetTagTable('Image::ExifTool::Stim::Main'); + $self->ProcessTIFF(\%dirInfo, $tagTablePtr); + } elsif ($$segDataPt =~ /^\xff\xd8\xff\xdb/) { + $dumpType = 'PreviewImage'; # (Samsung, HP, BenQ) + $preview = $$segDataPt; + } + if ($preview and $nextMarker ne 0xe4) { # this preview continues in APP4 + $self->FoundTag('PreviewImage', $preview); + undef $preview; + } + } elsif ($marker == 0xe4) { # APP4 ("SCALADO", FPXR, PreviewImage) + if ($$segDataPt =~ /^SCALADO\0/ and $length >= 16) { + $dumpType = 'SCALADO'; + my ($num, $idx, $len) = unpack('x8n2N', $$segDataPt); + # assume that the segments are in order and just concatinate them + $scalado = '' unless defined $scalado; + $scalado .= substr($$segDataPt, 16); + if ($idx == $num - 1) { + if ($len != length $scalado) { + $self->Warn('Possibly corrupted APP4 SCALADO data', 1); + } + my %dirInfo = ( + Parent => $markerName, + DataPt => \$scalado, + ); + my $tagTablePtr = GetTagTable('Image::ExifTool::Scalado::Main'); + $self->ProcessDirectory(\%dirInfo, $tagTablePtr); + undef $scalado; + } + } elsif ($$segDataPt =~ /^FPXR\0/) { + next if $fast and $fast > 1; # skip processing for very fast + $dumpType = 'FPXR'; + my $tagTablePtr = GetTagTable('Image::ExifTool::FlashPix::Main'); + # set flag if this is the last FPXR segment + $dirInfo{LastFPXR} = not ($nextMarker==$marker and $$nextSegDataPt=~/^FPXR\0/), + $self->ProcessDirectory(\%dirInfo, $tagTablePtr); + } elsif ($preview) { + # continued Samsung S1060 preview from APP3 + $dumpType = 'PreviewImage'; + $preview .= $$segDataPt; + } + # (also seen "QTI Debug Metadata\0" segment in some newer Samsung images) + # BenQ DC E1050 continues preview in APP5 + if ($preview and $nextMarker ne 0xe5) { + $self->FoundTag('PreviewImage', $preview); + undef $preview; + } + } elsif ($marker == 0xe5) { # APP5 (Ricoh "RMETA") + if ($$segDataPt =~ /^RMETA\0/) { + # (NOTE: apparently these may span multiple segments, but I haven't seen + # a sample like this, so multi-segment support hasn't yet been implemented) + $dumpType = 'Ricoh RMETA'; + DirStart(\%dirInfo, 6, 6); + my $tagTablePtr = GetTagTable('Image::ExifTool::Ricoh::RMETA'); + $self->ProcessDirectory(\%dirInfo, $tagTablePtr); + } elsif ($$segDataPt =~ /^ssuniqueid\0/) { + my $tagTablePtr = GetTagTable('Image::ExifTool::Samsung::APP5'); + $self->HandleTag($tagTablePtr, 'ssuniqueid', substr($$segDataPt, 11)); + } elsif ($preview) { + $dumpType = 'PreviewImage'; + $preview .= $$segDataPt; + $self->FoundTag('PreviewImage', $preview); + undef $preview; + } + } elsif ($marker == 0xe6) { # APP6 (Toshiba EPPIM, NITF, HP_TDHD) + if ($$segDataPt =~ /^EPPIM\0/) { + undef $dumpType; # (will be dumped here) + DirStart(\%dirInfo, 6, 6); + if ($htmlDump) { + $self->HDump($segPos-4, 10, 'APP6 EPPIM header'); + $dumpEnd = $segPos + $length; + } + my $tagTablePtr = GetTagTable('Image::ExifTool::JPEG::EPPIM'); + $self->ProcessTIFF(\%dirInfo, $tagTablePtr); + } elsif ($$segDataPt =~ /^NITF\0/) { + $dumpType = 'NITF'; + SetByteOrder('MM'); + my $tagTablePtr = GetTagTable('Image::ExifTool::JPEG::NITF'); + DirStart(\%dirInfo, 5); + $self->ProcessDirectory(\%dirInfo, $tagTablePtr); + } elsif ($$segDataPt =~ /^TDHD\x01\0\0\0/ and $length > 12) { + # HP Photosmart R837 APP6 "TDHD" segment + $dumpType = 'TDHD'; + my $tagTablePtr = GetTagTable('Image::ExifTool::HP::TDHD'); + # (ignore first TDHD element because size includes 12-byte tag header) + DirStart(\%dirInfo, 12); + $self->ProcessDirectory(\%dirInfo, $tagTablePtr); + } elsif ($$segDataPt =~ /^GoPro\0/) { + # GoPro segment + $dumpType = 'GoPro'; + my $tagTablePtr = GetTagTable('Image::ExifTool::GoPro::GPMF'); + DirStart(\%dirInfo, 6); + $self->ProcessDirectory(\%dirInfo, $tagTablePtr); + } + } elsif ($marker == 0xe7) { # APP7 (Pentax, Qualcomm) + if ($$segDataPt =~ /^PENTAX \0(II|MM)/) { + # found in K-3 images (is this multi-segment??) + SetByteOrder($1); + undef $dumpType; # (dump this ourself) + my $hdrLen = 10; + my $tagTablePtr = GetTagTable('Image::ExifTool::Pentax::Main'); + DirStart(\%dirInfo, $hdrLen, 0); + $dirInfo{DirName} = 'Pentax APP7'; + if ($htmlDump) { + $self->HDump($segPos-4, 4, 'APP7 header', "Data size: $length bytes"); + $self->HDump($segPos, $hdrLen, 'Pentax header', 'APP7 data type: Pentax'); + $dumpEnd = $segPos + $length; + } + $self->ProcessDirectory(\%dirInfo, $tagTablePtr); + } elsif ($$segDataPt =~ /^\x1aQualcomm Camera Attributes/) { + # found in HP iPAQ_VoiceMessenger + $dumpType = 'Qualcomm'; + my $tagTablePtr = GetTagTable('Image::ExifTool::Qualcomm::Main'); + DirStart(\%dirInfo, 27); + $dirInfo{DirName} = 'Qualcomm'; + $self->ProcessDirectory(\%dirInfo, $tagTablePtr); + } + } elsif ($marker == 0xe8) { # APP8 (SPIFF) + # my sample SPIFF has 32 bytes of data, but spec states 30 + if ($$segDataPt =~ /^SPIFF\0/ and $length == 32) { + $dumpType = 'SPIFF'; + DirStart(\%dirInfo, 6); + my $tagTablePtr = GetTagTable('Image::ExifTool::JPEG::SPIFF'); + $self->ProcessDirectory(\%dirInfo, $tagTablePtr); + } + } elsif ($marker == 0xe9) { # APP9 (Media Jukebox) + if ($$segDataPt =~ /^Media Jukebox\0/ and $length > 22) { + $dumpType = 'MediaJukebox'; + # (start parsing after the "") + DirStart(\%dirInfo, 22); + $dirInfo{DirName} = 'MediaJukebox'; + require Image::ExifTool::XMP; + my $tagTablePtr = GetTagTable('Image::ExifTool::JPEG::MediaJukebox'); + $self->ProcessDirectory(\%dirInfo, $tagTablePtr, \&Image::ExifTool::XMP::ProcessXMP); + } + } elsif ($marker == 0xea) { # APP10 (PhotoStudio Unicode comments) + if ($$segDataPt =~ /^UNICODE\0/) { + $dumpType = 'PhotoStudio'; + my $comment = $self->Decode(substr($$segDataPt,8), 'UCS2', 'MM'); + $self->FoundTag('Comment', $comment); + } elsif ($$segDataPt =~ /^AROT\0/ and $length > 10) { + # iPhone "AROT" segment containing integrated intensity per 16 scan lines + # (with number of elements N = ImageHeight / 16 - 1, ref PH/NealKrawetz) + $xtra = 'segment (N=' . unpack('x6N', $$segDataPt) . ')'; + } + } elsif ($marker == 0xeb) { # APP11 (JPEG-HDR) + if ($$segDataPt =~ /^HDR_RI /) { + $dumpType = 'JPEG-HDR'; + my $dataPt = $segDataPt; + if (defined $combinedSegData) { + if ($$segDataPt =~ /~\0/g) { + $combinedSegData .= substr($$segDataPt,pos($$segDataPt)); + } else { + $self->Warn('Invalid format for JPEG-HDR extended segment'); + } + $dataPt = \$combinedSegData; + } + if ($nextMarker == $marker and $$nextSegDataPt =~ /^HDR_RI /) { + $combinedSegData = $$segDataPt unless defined $combinedSegData; + } else { + my $tagTablePtr = GetTagTable('Image::ExifTool::JPEG::HDR'); + my %dirInfo = ( DataPt => $dataPt ); + $self->ProcessDirectory(\%dirInfo, $tagTablePtr); + undef $combinedSegData; + } + } + } elsif ($marker == 0xec) { # APP12 (Ducky, Picture Info) + if ($$segDataPt =~ /^Ducky/) { + $dumpType = 'Ducky'; + DirStart(\%dirInfo, 5); + my $tagTablePtr = GetTagTable('Image::ExifTool::APP12::Ducky'); + $self->ProcessDirectory(\%dirInfo, $tagTablePtr); + } else { + my $tagTablePtr = GetTagTable('Image::ExifTool::APP12::PictureInfo'); + $self->ProcessDirectory(\%dirInfo, $tagTablePtr) and $dumpType = 'Picture Info'; + } + } elsif ($marker == 0xed) { # APP13 (Photoshop, Adobe_CM) + my $isOld; + if ($$segDataPt =~ /^$psAPP13hdr/ or ($$segDataPt =~ /^$psAPP13old/ and $isOld=1)) { + $dumpType = 'Photoshop'; + # add this data to the combined data if it exists + my $dataPt = $segDataPt; + if (defined $combinedSegData) { + $combinedSegData .= substr($$segDataPt,length($psAPP13hdr)); + $dataPt = \$combinedSegData; + } + # peek ahead to see if the next segment is photoshop data too + if ($nextMarker == $marker and $$nextSegDataPt =~ /^$psAPP13hdr/) { + # initialize combined data if necessary + $combinedSegData = $$segDataPt unless defined $combinedSegData; + # (will handle the Photoshop data the next time around) + } else { + my $hdrLen = $isOld ? 27 : 14; + # process APP13 Photoshop record + my $tagTablePtr = GetTagTable('Image::ExifTool::Photoshop::Main'); + my %dirInfo = ( + DataPt => $dataPt, + DataPos => $segPos, + DataLen => length $$dataPt, + DirStart => $hdrLen, # directory starts after identifier + DirLen => length($$dataPt) - $hdrLen, + Parent => $markerName, + ); + $self->ProcessDirectory(\%dirInfo, $tagTablePtr); + undef $combinedSegData; + } + } elsif ($$segDataPt =~ /^Adobe_CM/) { + $dumpType = 'Adobe_CM'; + SetByteOrder('MM'); + my $tagTablePtr = GetTagTable('Image::ExifTool::JPEG::AdobeCM'); + DirStart(\%dirInfo, 8); + $self->ProcessDirectory(\%dirInfo, $tagTablePtr); + } + } elsif ($marker == 0xee) { # APP14 (Adobe) + if ($$segDataPt =~ /^Adobe/) { + # extract as a block if requested, or if copying tags from file + if ($$self{REQ_TAG_LOOKUP}{adobe} or + # (not extracted normally, so check TAGS_FROM_FILE) + ($$self{TAGS_FROM_FILE} and not $$self{EXCL_TAG_LOOKUP}{adobe})) + { + $self->FoundTag('Adobe', $$segDataPt); + } + $dumpType = 'Adobe'; + SetByteOrder('MM'); + my $tagTablePtr = GetTagTable('Image::ExifTool::JPEG::Adobe'); + DirStart(\%dirInfo, 5); + $self->ProcessDirectory(\%dirInfo, $tagTablePtr); + } + } elsif ($marker == 0xef) { # APP15 (GraphicConverter) + if ($$segDataPt =~ /^Q\s*(\d+)/ and $length == 4) { + $dumpType = 'GraphicConverter'; + my $tagTablePtr = GetTagTable('Image::ExifTool::JPEG::GraphConv'); + $self->HandleTag($tagTablePtr, 'Q', $1); + } + } elsif ($marker == 0xfe) { # COM (JPEG comment) + $dumpType = 'Comment'; + $$segDataPt =~ s/\0+$//; # some dumb softwares add null terminators + $self->FoundTag('Comment', $$segDataPt); + } elsif ($marker == 0x64) { # CME (J2C comment and extension) + $dumpType = 'Comment'; + if ($length > 2) { + my $reg = unpack('n', $$segDataPt); # get registration value + my $val = substr($$segDataPt, 2); + $val = $self->Decode($val, 'Latin') if $reg == 1; + # (actually an extension for $reg==65535, but store as binary comment) + $self->FoundTag('Comment', ($reg==0 or $reg==65535) ? \$val : $val); + } + } elsif ($marker == 0x51) { # SIZ (J2C) + my ($w, $h) = unpack('x2N2', $$segDataPt); + $self->FoundTag('ImageWidth', $w); + $self->FoundTag('ImageHeight', $h); + } elsif (($marker & 0xf0) != 0xe0) { + $dumpType = "$markerName segment"; + $desc = "[JPEG $markerName]"; # (other known JPEG segments) + } + if (defined $dumpType) { + if (not $dumpType and ($$options{Unknown} or $$options{Validate})) { + my $str = ($$segDataPt =~ /^([\x20-\x7e]{1,20})\0/) ? " '$1'" : ''; + $xtra = 'segment' unless $xtra; + $self->Warn("Unknown $markerName$str $xtra", 1); + } + if ($htmlDump) { + $desc or $desc = $markerName . ($dumpType ? " $dumpType" : '') . ' segment'; + $self->HDump($segPos-4, $length+4, $desc, $tip, 0x08); + $dumpEnd = $segPos + $length; + } + } + undef $$segDataPt; + } + # process extended XMP now if it existed + if (%extendedXMP) { + my $guid; + # GUID indicated by the last main XMP segment + my $goodGuid = $$self{VALUE}{HasExtendedXMP} || ''; + # GUID of the extended XMP that we will process ('2' for all) + my $readGuid = $$options{ExtendedXMP} || 0; + $readGuid = $goodGuid if $readGuid eq '1'; + foreach $guid (sort keys %extendedXMP) { + next unless length $guid == 32; # ignore other (internal) keys + my $extXMP = $extendedXMP{$guid}; + my ($off, @offsets, $warn); + # make sure we have all chunks, and create a list of sorted offsets + for ($off=0; $off<$$extXMP{Size}; ) { + last unless defined $$extXMP{$off}; + push @offsets, $off; + $off += length $$extXMP{$off}; + } + unless ($off == $$extXMP{Size}) { + $self->Warn("Incomplete extended XMP (GUID $guid)"); + next; + } + if ($guid eq $readGuid or $readGuid eq '2') { + $warn = 'Reading non-' if $guid ne $goodGuid; + my $buff = ''; + # assemble XMP all together + $buff .= $$extXMP{$_} foreach @offsets; + my $tagTablePtr = GetTagTable('Image::ExifTool::XMP::Main'); + my %dirInfo = ( + DataPt => \$buff, + Parent => 'APP1', + IsExtended => 1, + ); + $$path[$pn] = 'APP1'; + $self->ProcessDirectory(\%dirInfo, $tagTablePtr); + pop @$path; + } else { + $warn = 'Ignored '; + $warn .= 'non-' if $guid ne $goodGuid; + } + $self->Warn("${warn}standard extended XMP (GUID $guid)") if $warn; + delete $extendedXMP{$guid}; + } + } + # calculate JPEGDigest if requested + if (@dqt) { + require Image::ExifTool::JPEGDigest; + Image::ExifTool::JPEGDigest::Calculate($self, \@dqt, $subSampling); + } + # issue necessary warnings + $self->Warn('Incomplete ICC_Profile record', 1) if defined $iccChunkCount; + $self->Warn('Incomplete FLIR record', 1) if defined $flirCount; + $self->Warn('Error reading PreviewImage', 1) if $$self{PreviewError}; + $success or $self->Warn('JPEG format error'); + pop @$path if @$path > $pn; + return 1; +} + +#------------------------------------------------------------------------------ +# Extract metadata from an Exiv2 EXV file +# Inputs: 0) ExifTool object reference, 1) dirInfo ref with RAF set +# Returns: 1 on success, 0 if this wasn't a valid JPEG file +sub ProcessEXV($$) +{ + my ($self, $dirInfo) = @_; + return $self->ProcessJPEG($dirInfo); +} + +#------------------------------------------------------------------------------ +# Process EXIF file +# Inputs/Returns: same as ProcessTIFF +sub ProcessEXIF($$;$) +{ + my ($self, $dirInfo, $tagTablePtr) = @_; + return $self->ProcessTIFF($dirInfo, $tagTablePtr); +} + +#------------------------------------------------------------------------------ +# Process TIFF data (wrapper for DoProcessTIFF to allow re-entry) +# Inputs: 0) ExifTool object ref, 1) dirInfo ref, 2) optional tag table ref +# Returns: 1 if this looked like a valid EXIF block, 0 otherwise, or -1 on write error +sub ProcessTIFF($$;$) +{ + my ($self, $dirInfo, $tagTablePtr) = @_; + my $exifData = $$self{EXIF_DATA}; + my $exifPos = $$self{EXIF_POS}; + my $rtnVal = $self->DoProcessTIFF($dirInfo, $tagTablePtr); + # restore original EXIF information (in case ProcessTIFF is nested) + if (defined $exifData) { + $$self{EXIF_DATA} = $exifData; + $$self{EXIF_POS} = $exifPos; + } + return $rtnVal; +} + +#------------------------------------------------------------------------------ +# Process TIFF data +# Inputs: 0) ExifTool object ref, 1) dirInfo ref, 2) optional tag table ref +# Returns: 1 if this looked like a valid EXIF block, 0 otherwise, or -1 on write error +sub DoProcessTIFF($$;$) +{ + my ($self, $dirInfo, $tagTablePtr) = @_; + my $dataPt = $$dirInfo{DataPt}; + my $fileType = $$dirInfo{Parent} || ''; + my $raf = $$dirInfo{RAF}; + my $base = $$dirInfo{Base} || 0; + my $outfile = $$dirInfo{OutFile}; + my ($err, $sig, $canonSig, $otherSig); + + # attempt to read TIFF header + $$self{EXIF_DATA} = ''; + if ($raf) { + if ($outfile) { + $raf->Seek(0, 0) or return 0; + if ($base) { + $raf->Read($$dataPt, $base) == $base or return 0; + Write($outfile, $$dataPt) or $err = 1; + } + } else { + $raf->Seek($base, 0) or return 0; + } + # extract full EXIF block (for block copy) from EXIF file + my $amount = $fileType eq 'EXIF' ? 65536 * 8 : 8; + my $n = $raf->Read($$self{EXIF_DATA}, $amount); + if ($n < 8) { + return 0 if $n or not $outfile or $fileType ne 'EXIF'; + # create EXIF file from scratch + delete $$self{EXIF_DATA}; + undef $raf; + } + if ($n > 8) { + $raf->Seek(8, 0); + if ($n == $amount) { + $$self{EXIF_DATA} = substr($$self{EXIF_DATA}, 0, 8); + $self->Warn('EXIF too large to extract as a block'); #(shouldn't happen) + } + } + } elsif ($dataPt and length $$dataPt) { + # save a copy of the EXIF data + my $dirStart = $$dirInfo{DirStart} || 0; + my $dirLen = $$dirInfo{DirLen} || (length($$dataPt) - $dirStart); + $$self{EXIF_DATA} = substr($$dataPt, $dirStart, $dirLen); + $self->VerboseDir('TIFF') if $$self{OPTIONS}{Verbose} and length($$self{INDENT}) > 2; + } elsif ($outfile) { + delete $$self{EXIF_DATA}; # create from scratch + } else { + $$self{EXIF_DATA} = ''; + } + unless (defined $$self{EXIF_DATA}) { + # create TIFF information from scratch + if ($self->SetPreferredByteOrder() eq 'MM') { + $$self{EXIF_DATA} = "MM\0\x2a\0\0\0\x08"; + } else { + $$self{EXIF_DATA} = "II\x2a\0\x08\0\0\0"; + } + } + $$self{FIRST_EXIF_POS} = $base + $$self{BASE} unless defined $$self{FIRST_EXIF_POS}; + $$self{EXIF_POS} = $base + $$self{BASE}; + $dataPt = \$$self{EXIF_DATA}; + + # set byte ordering + my $byteOrder = substr($$dataPt,0,2); + SetByteOrder($byteOrder) or return 0; + + # verify the byte ordering + my $identifier = Get16u($dataPt, 2); + # identifier is 0x2a for TIFF (but 0x4f52, 0x5352 or ?? for ORF) + # no longer do this because various files use different values + # (TIFF=0x2a, RW2/RWL=0x55, HDP=0xbc, BTF=0x2b, ORF=0x4f52/0x5352/0x????) + # return 0 unless $identifier == 0x2a; + + # get offset to IFD0 + return 0 if length $$dataPt < 8; + my $offset = Get32u($dataPt, 4); + $offset >= 8 or return 0; + + if ($raf) { + # check for canon or EXIF signature + # (Canon CR2 images should have an offset of 16, but it may be + # greater if edited by PhotoMechanic) + if ($identifier == 0x2a and $offset >= 16) { + $raf->Read($sig, 8) == 8 or return 0; + $$dataPt .= $sig; + if ($sig =~ /^(CR\x02\0|\xba\xb0\xac\xbb|ExifMeta)/) { + if ($sig eq 'ExifMeta') { + $self->SetFileType($fileType = 'EXIF'); + $otherSig = $sig; + } else { + $fileType = $sig =~ /^CR/ ? 'CR2' : 'Canon 1D RAW'; + $canonSig = $sig; + } + $self->HDump($base+8, 8, "[$fileType header]") if $$self{HTML_DUMP}; + } + } elsif ($identifier == 0x55 and $fileType =~ /^(RAW|RW2|RWL|TIFF)$/) { + # panasonic RAW, RW2 or RWL file + my $magic; + # test for RW2/RWL magic number + if ($offset >= 0x18 and $raf->Read($magic, 16) and + $magic eq "\x88\xe7\x74\xd8\xf8\x25\x1d\x4d\x94\x7a\x6e\x77\x82\x2b\x5d\x6a") + { + $fileType = 'RW2' unless $fileType eq 'RWL'; + $self->HDump($base + 8, 16, '[RW2/RWL header]') if $$self{HTML_DUMP}; + $otherSig = $magic; # save signature for writing + } else { + $fileType = 'RAW'; + } + $tagTablePtr = GetTagTable('Image::ExifTool::PanasonicRaw::Main'); + } elsif ($fileType eq 'TIFF') { + if ($identifier == 0x2b) { + # this looks like a BigTIFF image + $raf->Seek(0); + require Image::ExifTool::BigTIFF; + return 1 if Image::ExifTool::BigTIFF::ProcessBTF($self, $dirInfo); + } elsif ($identifier == 0x4f52 or $identifier == 0x5352) { + # Olympus ORF image (set FileType now because base type is 'ORF') + $self->SetFileType($fileType = 'ORF'); + } elsif ($identifier == 0x4352) { + $fileType = 'DCP'; + } elsif ($byteOrder eq 'II' and ($identifier & 0xff) == 0xbc) { + $fileType = 'HDP'; # Windows HD Photo file + # check version number + my $ver = Get8u($dataPt, 3); + if ($ver > 1) { + $self->Error("Windows HD Photo version $ver files not yet supported"); + return 1; + } + } + } + # we have a valid TIFF (or whatever) file + if ($fileType and not $$self{VALUE}{FileType}) { + my $lookup = $fileTypeLookup{$fileType}; + $lookup = $fileTypeLookup{$lookup} unless ref $lookup or not $lookup; + # use file extension to pre-determine type if extension is TIFF-based or type is RAW + my $baseType = $lookup ? (ref $$lookup[0] ? $$lookup[0][0] : $$lookup[0]) : ''; + my $t = ($baseType eq 'TIFF' or $fileType =~ /RAW/) ? $fileType : undef; + $self->SetFileType($t); + } + # don't process file if FastScan == 3 + return 1 if not $outfile and $$self{OPTIONS}{FastScan} and $$self{OPTIONS}{FastScan} == 3; + } + # (accomodate CR3 images which have a TIFF directory with ExifIFD at the top level) + my $ifdName = ($$dirInfo{DirName} and $$dirInfo{DirName} =~ /^(ExifIFD|GPS)$/) ? $1 : 'IFD0'; + if (not $tagTablePtr or $$tagTablePtr{GROUPS}{0} eq 'EXIF') { + $self->FoundTag('ExifByteOrder', $byteOrder) unless $outfile; + } else { + $ifdName = $$tagTablePtr{GROUPS}{1}; + } + if ($$self{HTML_DUMP}) { + my $tip = sprintf("Byte order: %s endian\nIdentifier: 0x%.4x\n$ifdName offset: 0x%.4x", + ($byteOrder eq 'II') ? 'Little' : 'Big', $identifier, $offset); + $self->HDump($base, 8, 'TIFF header', $tip, 0); + } + # remember where we found the TIFF data (APP1, APP3, TIFF, NEF, etc...) + $$self{TIFF_TYPE} = $fileType; + + # get reference to the main EXIF table + $tagTablePtr or $tagTablePtr = GetTagTable('Image::ExifTool::Exif::Main'); + + # build directory information hash + my %dirInfo = ( + Base => $base, + DataPt => $dataPt, + DataLen => length $$dataPt, + DataPos => 0, + DirStart => $offset, + DirLen => length($$dataPt) - $offset, + RAF => $raf, + DirName => $ifdName, + Parent => $fileType, + ImageData=> 'Main', # set flag to get information to copy main image data later + Multi => $$dirInfo{Multi}, + ); + + # extract information from the image + unless ($outfile) { + # process the directory + $self->ProcessDirectory(\%dirInfo, $tagTablePtr); + # process GeoTiff information if available + if ($$self{VALUE}{GeoTiffDirectory}) { + require Image::ExifTool::GeoTiff; + Image::ExifTool::GeoTiff::ProcessGeoTiff($self); + } + # process information in recognized trailers + if ($raf) { + my $trailInfo = IdentifyTrailer($raf); + if ($trailInfo) { + $$trailInfo{ScanForAFCP} = 1; # scan to find AFCP if necessary + $self->ProcessTrailers($trailInfo); + } + # dump any other known trailer (eg. A100 RAW Data) + if ($$self{HTML_DUMP} and $$self{KnownTrailer}) { + my $known = $$self{KnownTrailer}; + $raf->Seek(0, 2); + my $len = $raf->Tell() - $$known{Start}; + $len -= $$trailInfo{Offset} if $trailInfo; # account for other trailers + $self->HDump($$known{Start}, $len, "[$$known{Name}]") if $len > 0; + } + } + # update FileType if necessary now that we know more about the file + if ($$self{DNGVersion} and $$self{VALUE}{FileType} !~ /^(DNG|GPR)$/) { + # override whatever FileType we set since we now know it is DNG + $self->OverrideFileType($$self{TIFF_TYPE} = 'DNG'); + } + return 1; + } +# +# rewrite the image +# + if ($$dirInfo{NoTiffEnd}) { + delete $$self{TIFF_END}; + } else { + # initialize TIFF_END so it will be updated by WriteExif() + $$self{TIFF_END} = 0; + } + if ($canonSig) { + # write Canon CR2 specially because it has a header we want to preserve, + # and possibly trailers added by the Canon utilities and/or PhotoMechanic + $dirInfo{OutFile} = $outfile; + require Image::ExifTool::CanonRaw; + Image::ExifTool::CanonRaw::WriteCR2($self, \%dirInfo, $tagTablePtr) or $err = 1; + } else { + # write TIFF header (8 bytes [plus optional signature] followed by IFD) + if ($fileType eq 'EXIF') { + $otherSig = 'ExifMeta'; # force this signature for all EXIF files + } elsif (not defined $otherSig) { + $otherSig = ''; + } + my $offset = 8 + length($otherSig); + # construct tiff header + my $header = substr($$dataPt, 0, 4) . Set32u($offset) . $otherSig; + $dirInfo{NewDataPos} = $offset; + $dirInfo{HeaderPtr} = \$header; + # preserve padding between image data blocks in ORF images + # (otherwise dcraw has problems because it assumes fixed block spacing) + $dirInfo{PreserveImagePadding} = 1 if $fileType eq 'ORF' or $identifier != 0x2a; + my $newData = $self->WriteDirectory(\%dirInfo, $tagTablePtr); + if (not defined $newData) { + $err = 1; + } elsif (length($newData)) { + # update header length in case more was added + my $hdrLen = length $header; + if ($hdrLen != 8) { + Set32u($hdrLen, \$header, 4); + # also update preview fixup if necessary + my $pi = $$self{PREVIEW_INFO}; + $$pi{Fixup}{Start} += $hdrLen - 8 if $pi and $$pi{Fixup}; + } + if ($$self{TIFF_TYPE} eq 'ARW' and not $err) { + # write any required ARW trailer and patch other ARW quirks + require Image::ExifTool::Sony; + my $errStr = Image::ExifTool::Sony::FinishARW($self, $dirInfo, \$newData, + $dirInfo{ImageData}); + $errStr and $self->Error($errStr); + delete $dirInfo{ImageData}; # (was copied by FinishARW) + } else { + Write($outfile, $header, $newData) or $err = 1; + } + undef $newData; # free memory + } + # copy over image data now if necessary + if (ref $dirInfo{ImageData} and not $err) { + $self->CopyImageData($dirInfo{ImageData}, $outfile) or $err = 1; + delete $dirInfo{ImageData}; + } + } + # make local copy of TIFF_END now (it may be reset when processing trailers) + my $tiffEnd = $$self{TIFF_END}; + delete $$self{TIFF_END}; + + # rewrite trailers if they exist + if ($raf and $tiffEnd and not $err) { + my ($buf, $trailInfo); + $raf->Seek(0, 2) or $err = 1; + my $extra = $raf->Tell() - $tiffEnd; + # check for trailer and process if possible + for (;;) { + last unless $extra > 12; + $raf->Seek($tiffEnd); # seek back to end of image + $trailInfo = IdentifyTrailer($raf); + last unless $trailInfo; + my $tbuf = ''; + $$trailInfo{OutFile} = \$tbuf; # rewrite trailer(s) + $$trailInfo{ScanForAFCP} = 1; # scan for AFCP if necessary + # rewrite all trailers to buffer + unless ($self->ProcessTrailers($trailInfo)) { + undef $trailInfo; + $err = 1; + last; + } + # calculate unused bytes before trailer + $extra = $$trailInfo{DataPos} - $tiffEnd; + last; # yes, the 'for' loop was just a cheap 'goto' + } + # ignore a single zero byte if used for padding + if ($extra > 0 and $tiffEnd & 0x01) { + $raf->Seek($tiffEnd, 0) or $err = 1; + $raf->Read($buf, 1) or $err = 1; + defined $buf and $buf eq "\0" and --$extra, ++$tiffEnd; + } + if ($extra > 0) { + my $known = $$self{KnownTrailer}; + if ($$self{DEL_GROUP}{Trailer} and not $known) { + $self->VPrint(0, " Deleting unknown trailer ($extra bytes)\n"); + ++$$self{CHANGED}; + } elsif ($known) { + $self->VPrint(0, " Copying $$known{Name} ($extra bytes)\n"); + $raf->Seek($tiffEnd, 0) or $err = 1; + CopyBlock($raf, $outfile, $extra) or $err = 1; + } else { + $raf->Seek($tiffEnd, 0) or $err = 1; + # preserve unknown trailer only if it contains non-null data + # (Photoshop CS adds a trailer with 2 null bytes) + my $size = $extra; + for (;;) { + my $n = $size > 65536 ? 65536 : $size; + $raf->Read($buf, $n) == $n or $err = 1, last; + if ($buf =~ /[^\0]/) { + $self->VPrint(0, " Preserving unknown trailer ($extra bytes)\n"); + # copy the trailer since it contains non-null data + Write($outfile, "\0"x($extra-$size)) or $err = 1, last if $size != $extra; + Write($outfile, $buf) or $err = 1, last; + CopyBlock($raf, $outfile, $size-$n) or $err = 1 if $size > $n; + last; + } + $size -= $n; + next if $size > 0; + $self->VPrint(0, " Deleting blank trailer ($extra bytes)\n"); + last; + } + } + } + # write trailer buffer if necessary + $self->WriteTrailerBuffer($trailInfo, $outfile) or $err = 1 if $trailInfo; + # add any new trailers we are creating + my $trailPt = $self->AddNewTrailers(); + Write($outfile, $$trailPt) or $err = 1 if $trailPt; + } + # check DNG version + if ($$self{DNGVersion}) { + my $ver = $$self{DNGVersion}; + # currently support up to DNG version 1.4 + unless ($ver =~ /^(\d+) (\d+)/ and "$1.$2" <= 1.4) { + $ver =~ tr/ /./; + $self->Error("DNG Version $ver not yet tested", 1); + } + } + return $err ? -1 : 1; +} + +#------------------------------------------------------------------------------ +# Return list of tag table keys (ignoring special keys) +# Inputs: 0) reference to tag table +# Returns: List of table keys (unsorted) +sub TagTableKeys($) +{ + local $_; + my $tagTablePtr = shift; + my @keyList; + foreach (keys %$tagTablePtr) { + push(@keyList, $_) unless $specialTags{$_}; + } + return @keyList; +} + +#------------------------------------------------------------------------------ +# GetTagTable +# Inputs: 0) table name +# Returns: tag table reference, or undefined if not found +# Notes: Always use this function instead of requiring module and using table +# directly since this function also does the following the first time the table +# is loaded: +# - requires new module if necessary +# - generates default GROUPS hash and Group 0 name from module name +# - registers Composite tags if Composite table found +# - saves descriptions for tags in specified table +# - generates default TAG_PREFIX to be used for unknown tags +sub GetTagTable($) +{ + my $tableName = shift or return undef; + my $table = $allTables{$tableName}; + + unless ($table) { + no strict 'refs'; + unless (%$tableName) { + # try to load module for this table + if ($tableName =~ /(.*)::/) { + my $module = $1; + if (eval "require $module") { + # load additional modules if required + if (not %$tableName) { + if ($module eq 'Image::ExifTool::XMP') { + require 'Image/ExifTool/XMP2.pl'; + } elsif ($tableName eq 'Image::ExifTool::QuickTime::Stream') { + require 'Image/ExifTool/QuickTimeStream.pl'; + } + } + } else { + $@ and warn $@; + } + } + unless (%$tableName) { + warn "Can't find table $tableName\n"; + return undef; + } + } + no strict 'refs'; + $table = \%$tableName; + use strict 'refs'; + $$table{TABLE_NAME} = $tableName; # set table name + ($$table{SHORT_NAME} = $tableName) =~ s/^Image::ExifTool:://; + # set default group 0 and 1 from module name unless already specified + my $defaultGroups = $$table{GROUPS}; + $defaultGroups or $defaultGroups = $$table{GROUPS} = { }; + unless ($$defaultGroups{0} and $$defaultGroups{1}) { + if ($tableName =~ /Image::.*?::([^:]*)/) { + $$defaultGroups{0} = $1 unless $$defaultGroups{0}; + $$defaultGroups{1} = $1 unless $$defaultGroups{1}; + } else { + $$defaultGroups{0} = $tableName unless $$defaultGroups{0}; + $$defaultGroups{1} = $tableName unless $$defaultGroups{1}; + } + } + $$defaultGroups{2} = 'Other' unless $$defaultGroups{2}; + if ($$defaultGroups{0} eq 'XMP' or $$table{NAMESPACE}) { + # initialize some XMP table defaults + require Image::ExifTool::XMP; + Image::ExifTool::XMP::RegisterNamespace($table); # register all table namespaces + # set default write/check procs + $$table{WRITE_PROC} = \&Image::ExifTool::XMP::WriteXMP unless $$table{WRITE_PROC}; + $$table{CHECK_PROC} = \&Image::ExifTool::XMP::CheckXMP unless $$table{CHECK_PROC}; + $$table{LANG_INFO} = \&Image::ExifTool::XMP::GetLangInfo unless $$table{LANG_INFO}; + } + # generate a tag prefix for unknown tags if necessary + unless (defined $$table{TAG_PREFIX}) { + my $tagPrefix; + if ($tableName =~ /Image::.*?::(.*)::Main/ || $tableName =~ /Image::.*?::(.*)/) { + ($tagPrefix = $1) =~ s/::/_/g; + } else { + $tagPrefix = $tableName; + } + $$table{TAG_PREFIX} = $tagPrefix; + } + # set up the new table + SetupTagTable($table); + # add any user-defined tags (except Composite tags, which are handled specially) + if (%UserDefined and $UserDefined{$tableName} and $table ne \%Image::ExifTool::Composite) { + my $tagID; + foreach $tagID (TagTableKeys($UserDefined{$tableName})) { + next if $specialTags{$tagID}; + delete $$table{$tagID}; # replace any existing entry + AddTagToTable($table, $tagID, $UserDefined{$tableName}{$tagID}, 1); + } + } + # remember order we loaded the tables in + push @tableOrder, $tableName; + # insert newly loaded table into list + $allTables{$tableName} = $table; + } + # must check each time to add UserDefined Composite tags because the Composite table + # may be loaded before the UserDefined tags are available + if ($table eq \%Image::ExifTool::Composite and not $$table{VARS}{LOADED_USERDEFINED} and + %UserDefined and $UserDefined{$tableName}) + { + my $userComp = $UserDefined{$tableName}; + delete $UserDefined{$tableName}; # (must delete first to avoid infinite recursion) + AddCompositeTags($userComp, 1); + $UserDefined{$tableName} = $userComp; # (add back again for adding writable tags later) + $$table{VARS}{LOADED_USERDEFINED} = 1; # set flag to avoid doing this again + } + return $table; +} + +#------------------------------------------------------------------------------ +# Process an image directory +# Inputs: 0) ExifTool object reference, 1) directory information reference +# 2) tag table reference, 3) optional reference to processing procedure +# Returns: Result from processing (1=success) +sub ProcessDirectory($$$;$) +{ + my ($self, $dirInfo, $tagTablePtr, $proc) = @_; + + return 0 unless $tagTablePtr and $dirInfo; + # use default proc from tag table or EXIF proc as fallback if no proc specified + $proc or $proc = $$tagTablePtr{PROCESS_PROC} || \&Image::ExifTool::Exif::ProcessExif; + # set directory name from default group0 name if not done already + my $dirName = $$dirInfo{DirName}; + unless ($dirName) { + $dirName = $$tagTablePtr{GROUPS}{0}; + $dirName = $$tagTablePtr{GROUPS}{1} if $dirName =~ /^APP\d+$/; # (use specific APP name) + $$dirInfo{DirName} = $dirName; + } + + # guard against cyclical recursion into the same directory + if (defined $$dirInfo{DirStart} and defined $$dirInfo{DataPos} and + # directories don't overlap if the length is zero + ($$dirInfo{DirLen} or not defined $$dirInfo{DirLen})) + { + my $addr = $$dirInfo{DirStart} + $$dirInfo{DataPos} + ($$dirInfo{Base}||0) + $$self{BASE}; + if ($$self{PROCESSED}{$addr}) { + $self->Warn("$dirName pointer references previous $$self{PROCESSED}{$addr} directory"); + # patch for bug in Windows phone 7.5 O/S that writes incorrect InteropIFD pointer + return 0 unless $dirName eq 'GPS' and $$self{PROCESSED}{$addr} eq 'InteropIFD'; + } + $$self{PROCESSED}{$addr} = $dirName; + } + my $oldOrder = GetByteOrder(); + my @save = @$self{'INDENT','DIR_NAME','Compression','SubfileType'}; + $$self{LIST_TAGS} = { }; # don't build lists across different directories + $$self{INDENT} .= '| '; + $$self{DIR_NAME} = $dirName; + push @{$$self{PATH}}, $dirName; + $$self{FOUND_DIR}{$dirName} = 1; + + # process the directory + my $rtnVal = &$proc($self, $dirInfo, $tagTablePtr); + + pop @{$$self{PATH}}; + @$self{'INDENT','DIR_NAME','Compression','SubfileType'} = @save; + SetByteOrder($oldOrder); + return $rtnVal; +} + +#------------------------------------------------------------------------------ +# Get Metadata path +# Inputs: 0) Exiftool object ref +# Return: Metadata path string +sub MetadataPath($) +{ + my $self = shift; + return join '-', @{$$self{PATH}} +} + +#------------------------------------------------------------------------------ +# Get standardized file extension +# Inputs: 0) file name +# Returns: standardized extension (all uppercase), or undefined if no extension +sub GetFileExtension($) +{ + my $filename = shift; + my $fileExt; + if ($filename and $filename =~ /^.*\.([^.]+)$/s) { + $fileExt = uc($1); # change extension to upper case + # convert TIF extension to TIFF because we use the + # extension for the file type tag of TIFF images + $fileExt eq 'TIF' and $fileExt = 'TIFF'; + } + return $fileExt; +} + +#------------------------------------------------------------------------------ +# Get list of tag information hashes for given tag ID +# Inputs: 0) Tag table reference, 1) tag ID +# Returns: Array of tag information references +# Notes: Generates tagInfo hash if necessary +sub GetTagInfoList($$) +{ + my ($tagTablePtr, $tagID) = @_; + my $tagInfo = $$tagTablePtr{$tagID}; + + if ($specialTags{$tagID}) { + # (hopefully this won't happen) + warn "Tag $tagID conflicts with internal ExifTool variable in $$tagTablePtr{TABLE_NAME}\n"; + } elsif (ref $tagInfo eq 'HASH') { + return ($tagInfo); + } elsif (ref $tagInfo eq 'ARRAY') { + return @$tagInfo; + } elsif ($tagInfo) { + # create hash with name + $tagInfo = $$tagTablePtr{$tagID} = { Name => $tagInfo }; + return ($tagInfo); + } + return (); +} + +#------------------------------------------------------------------------------ +# Find tag information, processing conditional tags +# Inputs: 0) ExifTool object reference, 1) tagTable pointer, 2) tag ID +# 3) optional value reference, 4) optional format type, 5) optional value count +# Returns: pointer to tagInfo hash, undefined if none found, or '' if $valPt needed +# Notes: You should always call this routine to find a tag in a table because +# this routine will evaluate conditional tags. +# Arguments 3-5 are only required if the information type allows $valPt, $format and/or +# $count in a Condition, and if not given when needed this routine returns ''. +sub GetTagInfo($$$;$$$) +{ + my ($self, $tagTablePtr, $tagID) = @_; + my ($valPt, $format, $count); + + my @infoArray = GetTagInfoList($tagTablePtr, $tagID); + # evaluate condition + my $tagInfo; + foreach $tagInfo (@infoArray) { + my $condition = $$tagInfo{Condition}; + if ($condition) { + ($valPt, $format, $count) = splice(@_, 3) if @_ > 3; + return '' if $condition =~ /\$(valPt|format|count)\b/ and not defined $valPt; + # set old value for use in condition if needed + local $SIG{'__WARN__'} = \&SetWarning; + undef $evalWarning; + #### eval Condition ($self, [$valPt, $format, $count]) + unless (eval $condition) { + $@ and $evalWarning = $@; + $self->Warn("Condition $$tagInfo{Name}: " . CleanWarning()) if $evalWarning; + next; + } + } + if ($$tagInfo{Unknown} and not $$self{OPTIONS}{Unknown} and not $$self{OPTIONS}{Verbose}) { + # don't return Unknown tags unless that option is set + return undef; + } + # return the tag information we found + return $tagInfo; + } + # generate information for unknown tags (numerical only) if required + if (not $tagInfo and ($$self{OPTIONS}{Unknown} or $$self{OPTIONS}{Verbose}) and + $tagID =~ /^\d+$/ and not $$self{NO_UNKNOWN}) + { + my $printConv; + if (defined $$tagTablePtr{PRINT_CONV}) { + $printConv = $$tagTablePtr{PRINT_CONV}; + } else { + # limit length of printout (can be very long) + $printConv = 'length($val) > 60 ? substr($val,0,55) . "[...]" : $val'; + } + my $hex = sprintf("0x%.4x", $tagID); + my $prefix = $$tagTablePtr{TAG_PREFIX}; + $tagInfo = { + Name => "${prefix}_$hex", + Description => MakeDescription($prefix, $hex), + Unknown => 1, + Writable => 0, # can't write unknown tags + PrintConv => $printConv, + }; + # add tag information to table + AddTagToTable($tagTablePtr, $tagID, $tagInfo); + } else { + undef $tagInfo; + } + return $tagInfo; +} + +#------------------------------------------------------------------------------ +# Add new tag to table (must use this routine to add new tags to a table) +# Inputs: 0) reference to tag table, 1) tag ID +# 2) [optional] tag name or reference to tag information hash +# 3) [optional] flag to avoid adding prefix when generating tag name +# Notes: - will not override existing entry in table +# - info need contain no entries when this routine is called +# - tag name is made valid if necessary +sub AddTagToTable($$;$$) +{ + my ($tagTablePtr, $tagID, $tagInfo, $noPrefix) = @_; + + # generate tag info hash if necessary + $tagInfo = $tagInfo ? { Name => $tagInfo } : { } unless ref $tagInfo eq 'HASH'; + + # define necessary entries in information hash + if ($$tagInfo{Groups}) { + # fill in default groups from table GROUPS + foreach (keys %{$$tagTablePtr{GROUPS}}) { + next if $$tagInfo{Groups}{$_}; + $$tagInfo{Groups}{$_} = $$tagTablePtr{GROUPS}{$_}; + } + } else { + $$tagInfo{Groups} = { %{$$tagTablePtr{GROUPS}} }; + } + $$tagInfo{Flags} and ExpandFlags($tagInfo); + $$tagInfo{GotGroups} = 1, + $$tagInfo{Table} = $tagTablePtr; + $$tagInfo{TagID} = $tagID; + + my $name = $$tagInfo{Name}; + $name = $tagID unless defined $name; + $name =~ tr/-_a-zA-Z0-9//dc; # remove illegal characters + $name = ucfirst $name; # capitalize first letter + # add tag-name prefix if specified and tag name not provided + unless (defined $$tagInfo{Name} or $noPrefix or not $$tagTablePtr{TAG_PREFIX}) { + # make description to prevent tagID from getting mangled by MakeDescription() + $$tagInfo{Description} = MakeDescription($$tagTablePtr{TAG_PREFIX}, $name); + $name = "$$tagTablePtr{TAG_PREFIX}_$name"; + } + # tag names must be at least 2 characters long and prefer them to start with a letter + $name = "Tag$name" if length($name) < 2 or $name !~ /^[A-Z]/i; + $$tagInfo{Name} = $name; + # add tag to table, but never override existing entries (could potentially happen + # if someone thinks there isn't any tagInfo because a condition wasn't satisfied) + unless (defined $$tagTablePtr{$tagID} or $specialTags{$tagID}) { + $$tagTablePtr{$tagID} = $tagInfo; + } +} + +#------------------------------------------------------------------------------ +# Handle simple extraction of new tag information +# Inputs: 0) ExifTool object ref, 1) tag table reference, 2) tagID, 3) value, +# 4-N) parameters hash: Index, DataPt, DataPos, Base, Start, Size, Parent, +# TagInfo, ProcessProc, RAF, Format +# Returns: tag key or undef if tag not found +# Notes: if value is not defined, it is extracted from DataPt using TagInfo +# Format and Count if provided +sub HandleTag($$$$;%) +{ + my ($self, $tagTablePtr, $tag, $val, %parms) = @_; + my $verbose = $$self{OPTIONS}{Verbose}; + my $pfmt = $parms{Format}; + my $tagInfo = $parms{TagInfo} || $self->GetTagInfo($tagTablePtr, $tag, \$val, $pfmt, $parms{Count}); + my $dataPt = $parms{DataPt}; + my ($subdir, $format, $noTagInfo, $rational); + + if ($tagInfo) { + $subdir = $$tagInfo{SubDirectory} + } else { + return undef unless $verbose; + $tagInfo = { Name => "tag $tag" }; # create temporary tagInfo hash + $noTagInfo = 1; + } + # read value if not done already (not necessary for subdir) + unless (defined $val or ($subdir and not $$tagInfo{Writable} and not $$tagInfo{RawConv})) { + my $start = $parms{Start} || 0; + my $dLen = $dataPt ? length($$dataPt) : -1; + my $size = $parms{Size}; + $size = $dLen unless defined $size; + # read from data in memory if possible + if ($start >= 0 and $start + $size <= $dLen) { + $format = $$tagInfo{Format} || $$tagTablePtr{FORMAT}; + $format = $pfmt if not $format and $pfmt and $formatSize{$pfmt}; + if ($format) { + $val = ReadValue($dataPt, $start, $format, $$tagInfo{Count}, $size, \$rational); + } else { + $val = substr($$dataPt, $start, $size); + } + } else { + $self->Warn("Error extracting value for $$tagInfo{Name}"); + return undef; + } + } + # do verbose print if necessary + if ($verbose) { + undef $tagInfo if $noTagInfo; + $parms{Value} = $val; + $parms{Value} .= " ($rational)" if defined $rational; + $parms{Table} = $tagTablePtr; + if ($format) { + my $count = int(($parms{Size} || 0) / ($formatSize{$format} || 1)); + $parms{Format} = $format . "[$count]"; + } + $self->VerboseInfo($tag, $tagInfo, %parms); + } + if ($tagInfo) { + if ($subdir) { + my $subdirStart = $parms{Start}; + my $subdirLen = $parms{Size}; + if ($$tagInfo{RawConv} and not $$tagInfo{Writable}) { + my $conv = $$tagInfo{RawConv}; + local $SIG{'__WARN__'} = \&SetWarning; + undef $evalWarning; + if (ref $conv eq 'CODE') { + $val = &$conv($val, $self); + } else { + my ($priority, @grps); + # NOTE: RawConv is evaluated in Writer.pl and twice in ExifTool.pm + #### eval RawConv ($self, $val, $tag, $tagInfo, $priority, @grps) + $val = eval $conv; + $@ and $evalWarning = $@; + } + $self->Warn("RawConv $tag: " . CleanWarning()) if $evalWarning; + return undef unless defined $val; + $val = $$val if ref $val eq 'SCALAR'; + $dataPt = \$val; + $subdirStart = 0; + $subdirLen = length $val; + } + if ($$subdir{Start}) { + my $valuePtr = 0; + #### eval Start ($valuePtr) + my $off = eval $$subdir{Start}; + $subdirStart += $off; + $subdirLen -= $off; + } + $dataPt or $dataPt = \$val; + # process subdirectory information + my %dirInfo = ( + DirName => $$subdir{DirName} || $$tagInfo{Name}, + DataPt => $dataPt, + DataLen => length $$dataPt, + DataPos => $parms{DataPos}, + DirStart => $subdirStart, + DirLen => $subdirLen, + Parent => $parms{Parent}, + Base => $parms{Base}, + Multi => $$subdir{Multi}, + TagInfo => $tagInfo, + RAF => $parms{RAF}, + ); + my $oldOrder = GetByteOrder(); + if ($$subdir{ByteOrder}) { + if ($$subdir{ByteOrder} eq 'Unknown') { + if ($subdirStart + 2 <= $subdirLen) { + # attempt to determine the byte ordering of an IFD-style subdirectory + my $num = Get16u($dataPt, $subdirStart); + ToggleByteOrder if $num & 0xff00 and ($num>>8) > ($num&0xff); + } + } else { + SetByteOrder($$subdir{ByteOrder}); + } + } + my $subTablePtr = GetTagTable($$subdir{TagTable}) || $tagTablePtr; + $self->ProcessDirectory(\%dirInfo, $subTablePtr, $$subdir{ProcessProc} || $parms{ProcessProc}); + SetByteOrder($oldOrder); + # return now unless directory is writable as a block + return undef unless $$tagInfo{Writable}; + } + my $key = $self->FoundTag($tagInfo, $val); + # save original components of rational numbers + $$self{RATIONAL}{$key} = $rational if defined $rational and defined $key; + return $key; + } + return undef; +} + +#------------------------------------------------------------------------------ +# Add tag to hash of extracted information +# Inputs: 0) ExifTool object reference +# 1) reference to tagInfo hash or tag name +# 2) data value (or reference to require hash if Composite) +# 3) optional family 0 group, 4) optional family 1 group +# Returns: tag key or undef if no value +sub FoundTag($$$;@) +{ + local $_; + my ($self, $tagInfo, $value, @grps) = @_; + my ($tag, $noListDel); + my $options = $$self{OPTIONS}; + + if (ref $tagInfo eq 'HASH') { + $tag = $$tagInfo{Name} or warn("No tag name\n"), return undef; + } else { + $tag = $tagInfo; + # look for tag in Extra + $tagInfo = $self->GetTagInfo(GetTagTable('Image::ExifTool::Extra'), $tag); + # make temporary hash if tag doesn't exist in Extra + # (not advised to do this since the tag won't show in list) + $tagInfo or $tagInfo = { Name => $tag, Groups => \%allGroupsExifTool }; + $$options{Verbose} and $self->VerboseInfo(undef, $tagInfo, Value => $value); + } + # get tag priority + my $priority = $$tagInfo{Priority}; + unless (defined $priority) { + $priority = $$tagInfo{Table}{PRIORITY}; + $priority = 0 if not defined $priority and $$tagInfo{Avoid}; + } + $grps[0] or $grps[0] = $$self{SET_GROUP0}; + $grps[1] or $grps[1] = $$self{SET_GROUP1}; + my $valueHash = $$self{VALUE}; + + if ($$tagInfo{RawConv}) { + # initialize @val for use in Composite RawConv expressions + my @val; + if (ref $value eq 'HASH' and $$tagInfo{IsComposite}) { + foreach (keys %$value) { $val[$_] = $$valueHash{$$value{$_}}; } + } + my $conv = $$tagInfo{RawConv}; + local $SIG{'__WARN__'} = \&SetWarning; + undef $evalWarning; + if (ref $conv eq 'CODE') { + $value = &$conv($value, $self); + $$self{grps} and @grps = @{$$self{grps}}, delete $$self{grps}; + } else { + my $val = $value; # do this so eval can use $val + # NOTE: RawConv is also evaluated in Writer.pl + #### eval RawConv ($self, $val, $tag, $tagInfo, $priority, @grps) + $value = eval $conv; + $@ and $evalWarning = $@; + } + $self->Warn("RawConv $tag: " . CleanWarning()) if $evalWarning; + return undef unless defined $value; + } + # handle duplicate tag names + if (defined $$valueHash{$tag}) { + # add to list if there is an active list for this tag + if ($$self{LIST_TAGS}{$tagInfo}) { + $tag = $$self{LIST_TAGS}{$tagInfo}; # use key from previous list tag + if (defined $$self{NO_LIST}) { + # accumulate list in TAG_EXTRA "NoList" element + if (defined $$self{TAG_EXTRA}{$tag}{NoList}) { + push @{$$self{TAG_EXTRA}{$tag}{NoList}}, $value; + } else { + $$self{TAG_EXTRA}{$tag}{NoList} = [ $$valueHash{$tag}, $value ]; + } + $noListDel = 1; # set flag to delete this tag if re-listed + } else { + if (ref $$valueHash{$tag} ne 'ARRAY') { + $$valueHash{$tag} = [ $$valueHash{$tag} ]; + } + push @{$$valueHash{$tag}}, $value; + return $tag; # return without creating a new entry + } + } + # get next available tag key + my $nextInd = $$self{DUPL_TAG}{$tag} = ($$self{DUPL_TAG}{$tag} || 0) + 1; + my $nextTag = "$tag ($nextInd)"; +# +# take tag with highest priority +# + # promote existing 0-priority tag so it takes precedence over a new 0-tag + # (unless old tag was a sub-document and new tag isn't. Also, never override + # a Warning tag because they may be added by ValueConv, which could be confusing) + my $oldPriority = $$self{PRIORITY}{$tag}; + unless ($oldPriority) { + if ($$self{DOC_NUM} or not $$self{TAG_EXTRA}{$tag} or $tag eq 'Warning' or + not $$self{TAG_EXTRA}{$tag}{G3}) + { + $oldPriority = 1; + } else { + $oldPriority = 0; # don't promote sub-document tag over main document + } + } + # set priority for this tag + if (defined $priority) { + # increase 0-priority tags if this is the priority directory + $priority = 1 if not $priority and $$self{DIR_NAME} and + $$self{DIR_NAME} eq $$self{PRIORITY_DIR}; + } elsif ($$self{LOW_PRIORITY_DIR}{'*'} or + ($$self{DIR_NAME} and $$self{LOW_PRIORITY_DIR}{$$self{DIR_NAME}})) + { + $priority = 0; # default is 0 for a LOW_PRIORITY_DIR + } else { + $priority = 1; # the normal default + } + if ($priority >= $oldPriority and not $$self{DOC_NUM} and not $noListDel) { + # move existing tag out of the way since this tag is higher priority + # (NOTE: any new members added here must also be added to DeleteTag()) + $$self{MOVED_KEY} = $nextTag; # used in BuildCompositeTags() + $$self{PRIORITY}{$nextTag} = $$self{PRIORITY}{$tag}; + $$valueHash{$nextTag} = $$valueHash{$tag}; + $$self{FILE_ORDER}{$nextTag} = $$self{FILE_ORDER}{$tag}; + my $oldInfo = $$self{TAG_INFO}{$nextTag} = $$self{TAG_INFO}{$tag}; + foreach ('TAG_EXTRA','RATIONAL') { + if ($$self{$_}{$tag}) { + $$self{$_}{$nextTag} = $$self{$_}{$tag}; + delete $$self{$_}{$tag}; + } + } + delete $$self{BOTH}{$tag}; + # update tag key for list if necessary + $$self{LIST_TAGS}{$oldInfo} = $nextTag if $$self{LIST_TAGS}{$oldInfo}; + } else { + $tag = $nextTag; # don't override the existing tag + } + $$self{PRIORITY}{$tag} = $priority; + $$self{TAG_EXTRA}{$tag}{NoListDel} = 1 if $noListDel; + } elsif ($priority) { + # set tag priority (only if exists and is non-zero) + $$self{PRIORITY}{$tag} = $priority; + } + + # save the raw value, file order, tagInfo ref, group1 name, + # and tag key for lists if necessary + $$valueHash{$tag} = $value; + $$self{FILE_ORDER}{$tag} = ++$$self{NUM_FOUND}; + $$self{TAG_INFO}{$tag} = $tagInfo; + # set dynamic groups 0, 1 and 3 if necessary + $$self{TAG_EXTRA}{$tag}{G0} = $grps[0] if $grps[0]; + $$self{TAG_EXTRA}{$tag}{G1} = $grps[1] if $grps[1]; + if ($$self{DOC_NUM}) { + $$self{TAG_EXTRA}{$tag}{G3} = $$self{DOC_NUM}; + if ($$self{DOC_NUM} =~ /^(\d+)/) { + # keep track of maximum 1st-level sub-document number + $$self{DOC_COUNT} = $1 unless $$self{DOC_COUNT} >= $1; + } + } + # save path if requested + $$self{TAG_EXTRA}{$tag}{G5} = $self->MetadataPath() if $$options{SavePath}; + + # remember this tagInfo if we will be accumulating values in a list + # (but don't override earlier list if this may be deleted by NoListDel flag) + if ($$tagInfo{List} and not $$self{NO_LIST} and not $noListDel) { + $$self{LIST_TAGS}{$tagInfo} = $tag; + } + + # validate tag if requested (but only for simple values -- could result + # in infinite recursion if called for a Composite tag (HASH ref value) + # because FoundTag is called in the middle of building Composite tags + if ($$options{Validate} and not ref $value) { + Image::ExifTool::Validate::ValidateRaw($self, $tag, $value); + } + + return $tag; +} + +#------------------------------------------------------------------------------ +# Make current directory the priority directory if not set already +# Inputs: 0) ExifTool object reference +sub SetPriorityDir($) +{ + my $self = shift; + $$self{PRIORITY_DIR} = $$self{DIR_NAME} unless $$self{PRIORITY_DIR}; +} + +#------------------------------------------------------------------------------ +# Set family 0 or 1 group name specific to this tag instance +# Inputs: 0) ExifTool ref, 1) tag key, 2) group name, 3) family (default 1) +sub SetGroup($$$;$) +{ + my ($self, $tagKey, $extra, $fam) = @_; + $$self{TAG_EXTRA}{$tagKey}{defined $fam ? "G$fam" : 'G1'} = $extra; +} + +#------------------------------------------------------------------------------ +# Delete specified tag +# Inputs: 0) ExifTool object ref, 1) tag key +sub DeleteTag($$) +{ + my ($self, $tag) = @_; + delete $$self{VALUE}{$tag}; + delete $$self{FILE_ORDER}{$tag}; + delete $$self{TAG_INFO}{$tag}; + delete $$self{TAG_EXTRA}{$tag}; + delete $$self{PRIORITY}{$tag}; + delete $$self{RATIONAL}{$tag}; + delete $$self{BOTH}{$tag}; +} + +#------------------------------------------------------------------------------ +# Escape all elements of a value +# Inputs: 0) value, 1) escape proc +sub DoEscape($$) +{ + my ($val, $key); + if (not ref $_[0]) { + $_[0] = &{$_[1]}($_[0]); + } elsif (ref $_[0] eq 'ARRAY') { + foreach $val (@{$_[0]}) { + DoEscape($val, $_[1]); + } + } elsif (ref $_[0] eq 'HASH') { + foreach $key (keys %{$_[0]}) { + DoEscape($_[0]{$key}, $_[1]); + } + } +} + +#------------------------------------------------------------------------------ +# Set the FileType and MIMEType tags +# Inputs: 0) ExifTool object reference +# 1) Optional file type (uses FILE_TYPE if not specified) +# 2) Optional MIME type (uses our lookup if not specified) +# 3) Optional recommended extension (converted to lower case; uses FileType if undef) +# Notes: Will NOT set file type twice (subsequent calls ignored) +sub SetFileType($;$$$) +{ + my ($self, $fileType, $mimeType, $normExt) = @_; + unless ($$self{VALUE}{FileType} and not $$self{DOC_NUM}) { + my $baseType = $$self{FILE_TYPE}; + my $ext = $$self{FILE_EXT}; + $fileType or $fileType = $baseType; + # handle sub-types which are identified by extension + if (defined $ext and $ext ne $fileType and not $$self{DOC_NUM}) { + my ($f,$e) = @fileTypeLookup{$fileType,$ext}; + if (ref $f eq 'ARRAY' and ref $e eq 'ARRAY' and $$f[0] eq $$e[0]) { + # make sure $fileType was a root type and not another sub-type + $fileType = $ext if $$f[0] eq $fileType or not $fileTypeLookup{$$f[0]}; + } + } + $mimeType or $mimeType = $mimeType{$fileType}; + # use base file type if necessary (except if 'TIFF', which is a special case) + $mimeType = $mimeType{$baseType} unless $mimeType or $baseType eq 'TIFF'; + unless (defined $normExt) { + $normExt = $fileTypeExt{$fileType}; + $normExt = $fileType unless defined $normExt; + } + $self->FoundTag('FileType', $fileType); + $self->FoundTag('FileTypeExtension', uc $normExt); + $self->FoundTag('MIMEType', $mimeType || 'application/unknown'); + } +} + +#------------------------------------------------------------------------------ +# Override the FileType and MIMEType tags +# Inputs: 0) ExifTool object ref, 1) file type, 2) MIME type, 3) normal extension +# Notes: does nothing if FileType was not previously defined (ie. when writing) +sub OverrideFileType($$;$$) +{ + my ($self, $fileType, $mimeType, $normExt) = @_; + if (defined $$self{VALUE}{FileType} and $fileType ne $$self{VALUE}{FileType}) { + $$self{VALUE}{FileType} = $fileType; + unless (defined $normExt) { + $normExt = $fileTypeExt{$fileType}; + $normExt = $fileType unless defined $normExt; + } + $$self{VALUE}{FileTypeExtension} = uc $normExt; + $mimeType or $mimeType = $mimeType{$fileType}; + $$self{VALUE}{MIMEType} = $mimeType if $mimeType; + if ($$self{OPTIONS}{Verbose}) { + $self->VPrint(0,"$$self{INDENT}FileType [override] = $fileType\n"); + $self->VPrint(0,"$$self{INDENT}FileTypeExtension [override] = $$self{VALUE}{FileTypeExtension}\n"); + $self->VPrint(0,"$$self{INDENT}MIMEType [override] = $mimeType\n") if $mimeType; + } + } +} + +#------------------------------------------------------------------------------ +# Modify the value of the MIMEType tag +# Inputs: 0) ExifTool object reference, 1) file or MIME type +# Notes: combines existing type with new type: ie) a/b + c/d => c/b-d +sub ModifyMimeType($;$) +{ + my ($self, $mime) = @_; + $mime =~ m{/} or $mime = $mimeType{$mime} or return; + my $old = $$self{VALUE}{MIMEType}; + if (defined $old) { + my ($a, $b) = split '/', $old; + my ($c, $d) = split '/', $mime; + $d =~ s/^x-//; + $$self{VALUE}{MIMEType} = "$c/$b-$d"; + $self->VPrint(0, " Modified MIMEType = $c/$b-$d\n"); + } else { + $self->FoundTag('MIMEType', $mime); + } +} + +#------------------------------------------------------------------------------ +# Print verbose output +# Inputs: 0) ExifTool ref, 1) verbose level (prints if level > this), 2-N) print args +sub VPrint($$@) +{ + my $self = shift; + my $level = shift; + if ($$self{OPTIONS}{Verbose} and $$self{OPTIONS}{Verbose} > $level) { + my $out = $$self{OPTIONS}{TextOut}; + print $out @_; + print $out "\n" unless $_[-1] =~ /\n$/; + } +} + +#------------------------------------------------------------------------------ +# Print verbose directory information +# Inputs: 0) ExifTool object reference, 1) directory name or dirInfo ref +# 2) number of entries in directory (or 0 if unknown) +# 3) optional size of directory in bytes +sub VerboseDir($$;$$) +{ + my ($self, $name, $entries, $size) = @_; + return unless $$self{OPTIONS}{Verbose}; + if (ref $name eq 'HASH') { + $size = $$name{DirLen} unless $size; + $name = $$name{Name} || $$name{DirName}; + } + my $indent = substr($$self{INDENT}, 0, -2); + my $out = $$self{OPTIONS}{TextOut}; + my $str = $entries ? " with $entries entries" : ''; + $str .= ", $size bytes" if $size; + print $out "$indent+ [$name directory$str]\n"; +} + +#------------------------------------------------------------------------------ +# Verbose dump +# Inputs: 0) ExifTool ref, 1) data ref, 2-N) HexDump options +sub VerboseDump($$;%) +{ + my $self = shift; + my $dataPt = shift; + my $verbose = $$self{OPTIONS}{Verbose}; + if ($verbose and $verbose > 2) { + my %parms = ( + Prefix => $$self{INDENT}, + Out => $$self{OPTIONS}{TextOut}, + MaxLen => $verbose < 4 ? 96 : $verbose < 5 ? 2048 : undef, + ); + HexDump($dataPt, undef, %parms, @_); + } +} + +#------------------------------------------------------------------------------ +# Print data in hex +# Inputs: 0) data +# Returns: hex string +# (this is a convenience function for use in debugging PrintConv statements) +sub PrintHex($) +{ + my $val = shift; + return join(' ', unpack('H2' x length($val), $val)); +} + +#------------------------------------------------------------------------------ +# Extract binary data from file +# 0) ExifTool object reference, 1) offset, 2) length, 3) tag name if conditional +# Returns: binary data, or undef on error +# Notes: Returns "Binary data #### bytes" instead of data unless tag is +# specifically requested or the Binary option is set +sub ExtractBinary($$$;$) +{ + my ($self, $offset, $length, $tag) = @_; + my ($isPreview, $buff); + + if ($tag) { + if ($tag eq 'PreviewImage') { + # save PreviewImage start/length in case we want to dump trailer + $$self{PreviewImageStart} = $offset; + $$self{PreviewImageLength} = $length; + $isPreview = 1; + } + my $lcTag = lc $tag; + if ((not $$self{OPTIONS}{Binary} or $$self{EXCL_TAG_LOOKUP}{$lcTag}) and + not $$self{OPTIONS}{Verbose} and not $$self{REQ_TAG_LOOKUP}{$lcTag}) + { + return "Binary data $length bytes"; + } + } + unless ($$self{RAF}->Seek($offset,0) + and $$self{RAF}->Read($buff, $length) == $length) + { + $tag or $tag = 'binary data'; + if ($isPreview and not $$self{BuildingComposite}) { + $$self{PreviewError} = 1; + } else { + $self->Warn("Error reading $tag from file", $isPreview); + } + return undef; + } + return $buff; +} + +#------------------------------------------------------------------------------ +# Process binary data +# Inputs: 0) ExifTool object ref, 1) directory information ref, 2) tag table ref +# Returns: 1 on success +# Notes: dirInfo may contain VarFormatData (reference to empty list) to return +# details about any variable-length-format tags in the table (used when writing) +sub ProcessBinaryData($$$) +{ + my ($self, $dirInfo, $tagTablePtr) = @_; + my $dataPt = $$dirInfo{DataPt}; + my $offset = $$dirInfo{DirStart} || 0; + my $size = $$dirInfo{DirLen} || (length($$dataPt) - $offset); + my $base = $$dirInfo{Base} || 0; + my $verbose = $$self{OPTIONS}{Verbose}; + my $unknown = $$self{OPTIONS}{Unknown}; + my $dataPos = $$dirInfo{DataPos} || 0; + + # get default format ('int8u' unless specified) + my $defaultFormat = $$tagTablePtr{FORMAT} || 'int8u'; + my $increment = $formatSize{$defaultFormat}; + unless ($increment) { + warn "Unknown format $defaultFormat\n"; + $defaultFormat = 'int8u'; + $increment = $formatSize{$defaultFormat}; + } + # prepare list of tag numbers to extract + my (@tags, $topIndex); + if ($unknown > 1 and defined $$tagTablePtr{FIRST_ENTRY}) { + # don't create a stupid number of tags if data is huge + my $sizeLimit = $size < 65536 ? $size : 65536; + # scan through entire binary table + $topIndex = int($sizeLimit/$increment); + @tags = ($$tagTablePtr{FIRST_ENTRY}..($topIndex - 1)); + # add in floating point tag ID's if they exist + my @ftags = grep /\./, TagTableKeys($tagTablePtr); + @tags = sort { $a <=> $b } @tags, @ftags if @ftags; + } elsif ($$dirInfo{DataMember}) { + @tags = @{$$dirInfo{DataMember}}; + $verbose = 0; # no verbose output of extracted values when writing + } elsif ($$dirInfo{MixedTags}) { + # process sorted integer-ID tags only + @tags = sort { $a <=> $b } grep /^\d+$/, TagTableKeys($tagTablePtr); + } else { + # extract known tags in numerical order + @tags = sort { ($a < 0 ? $a + 1e9 : $a) <=> ($b < 0 ? $b + 1e9 : $b) } TagTableKeys($tagTablePtr); + } + $self->VerboseDir('BinaryData', undef, $size) if $verbose; + # avoid creating unknown tags for tags that fail condition if Unknown is 1 + $$self{NO_UNKNOWN} = 1 if $unknown < 2; + my ($index, %val); + my $nextIndex = 0; + my $varSize = 0; + foreach $index (@tags) { + my ($tagInfo, $val, $saveNextIndex, $len, $mask, $wasVar, $rational); + if ($$tagTablePtr{$index}) { + $tagInfo = $self->GetTagInfo($tagTablePtr, $index); + unless ($tagInfo) { + next unless defined $tagInfo; + my $entry = int($index) * $increment + $varSize; + if ($entry < 0) { + $entry += $size; + next if $entry < 0; + } + next if $entry >= $size; + my $more = $size - $entry; + $more = 128 if $more > 128; + my $v = substr($$dataPt, $entry+$offset, $more); + $tagInfo = $self->GetTagInfo($tagTablePtr, $index, \$v); + next unless $tagInfo; + } + next if $$tagInfo{Unknown} and + ($$tagInfo{Unknown} > $unknown or $index < $nextIndex); + } elsif ($topIndex and $$tagTablePtr{$index - $topIndex}) { + $tagInfo = $self->GetTagInfo($tagTablePtr, $index - $topIndex) or next; + } else { + # don't generate unknown tags in binary tables unless Unknown > 1 + next unless $unknown > 1; + next if $index < $nextIndex; # skip if data already used + $tagInfo = $self->GetTagInfo($tagTablePtr, $index) or next; + $$tagInfo{Unknown} = 2; # set unknown to 2 for binary unknowns + } + # get relative offset of this entry + my $entry = int($index) * $increment + $varSize; + # allow negative indices to represent bytes from end + if ($entry < 0) { + $entry += $size; + next if $entry < 0; + } + my $more = $size - $entry; + last if $more <= 0; # all done if we have reached the end of data + my $count = 1; + my $format = $$tagInfo{Format}; + if (not $format) { + $format = $defaultFormat; + } elsif ($format eq 'string') { + # string with no specified count runs to end of block + $count = $more; + } elsif ($format eq 'pstring') { + $format = 'string'; + $count = Get8u($dataPt, ($entry++)+$offset); + --$more; + } elsif (not $formatSize{$format}) { + if ($format =~ /(.*)\[(.*)\]/) { + # handle format count field + $format = $1; + $count = $2; + # evaluate count to allow count to be based on previous values + #### eval Format size (%val, $size, $self) + $count = eval $count; + $@ and warn("Format $$tagInfo{Name}: $@"), next; + next if $count < 0; + # allow a variable-length value of any format + # (note: the next incremental index points to data immediately after + # this value, regardless of the size of this value, even if it is zero) + if ($format =~ s/^var_//) { + $varSize += $count * ($formatSize{$format} || 1) - $increment; + $wasVar = 1; + # save variable size data if required for writing + if ($$dirInfo{VarFormatData}) { + push @{$$dirInfo{VarFormatData}}, [ $index, $varSize, $format ]; + } + # don't extract value if large and we wanted it just to get + # the variable-format information when writing + next if $$tagInfo{LargeTag} and $$dirInfo{VarFormatData}; + } + } elsif ($format =~ /^var_/) { + # handle variable-length string formats + $format = substr($format, 4); + pos($$dataPt) = $entry + $offset; + undef $count; + if ($format eq 'ustring') { + $count = pos($$dataPt) - ($entry+$offset) if $$dataPt =~ /\G(..)*?\0\0/sg; + $varSize -= 2; # ($count includes base size of 2 bytes) + } elsif ($format eq 'pstring') { + $count = Get8u($dataPt, ($entry++)+$offset); + --$more; + } elsif ($format eq 'pstr32' or $format eq 'ustr32') { + last if $more < 4; + $count = Get32u($dataPt, $entry + $offset); + $count *= 2 if $format eq 'ustr32'; + $entry += 4; + $more -= 4; + $nextIndex += 4 / $increment; # (increment next index for int32u) + } elsif ($format eq 'int16u') { + # int16u size of binary data to follow + last if $more < 2; + $count = Get16u($dataPt, $entry + $offset) + 2; + $varSize -= 2; # ($count includes size word) + $format = 'undef'; + } elsif ($format eq 'ue7') { + require Image::ExifTool::BPG; + ($val, $count) = Image::ExifTool::BPG::Get_ue7($dataPt, $entry + $offset); + last unless defined $val; + --$varSize; # ($count includes base size of 1 byte) + } elsif ($$dataPt =~ /\0/g) { + $count = pos($$dataPt) - ($entry+$offset); + --$varSize; # ($count includes base size of 1 byte) + } + $count = $more if not defined $count or $count > $more; + $varSize += $count; # shift subsequent indices + unless (defined $val) { + $val = substr($$dataPt, $entry+$offset, $count); + $val = $self->Decode($val, 'UCS2') if $format eq 'ustring' or $format eq 'ustr32'; + $val =~ s/\0.*//s unless $format eq 'undef'; # truncate at null + } + $wasVar = 1; + # save variable size data if required for writing + if ($$dirInfo{VarFormatData}) { + push @{$$dirInfo{VarFormatData}}, [ $index, $varSize, $format ]; + } + } + } + # hook to allow format, etc to be set dynamically + if (defined $$tagInfo{Hook}) { + my $oldVarSize = $varSize; + #### eval Hook ($format, $varSize, $size) + eval $$tagInfo{Hook}; + # save variable size data if required for writing (in case changed by Hook) + if ($$dirInfo{VarFormatData}) { + $#{$$dirInfo{VarFormatData}} -= 1 if $wasVar; # remove previous entry for this tag + push @{$$dirInfo{VarFormatData}}, [ $index, $varSize, $format ]; + } elsif ($varSize != $oldVarSize and $verbose > 2) { + my ($tmp, $sign) = ($varSize, '+'); + $tmp < 0 and $tmp = -$tmp, $sign = '-'; + $self->VPrint(2, sprintf("$$self{INDENT}\[offsets adjusted by ${sign}0x%.4x after 0x%.4x $$tagInfo{Name}]\n", $tmp, $index)); + } + } + if ($unknown > 1) { + # calculate next valid index for unknown tag + my $ni = int $index; + $ni += (($formatSize{$format} || 1) * $count) / $increment unless $wasVar; + $saveNextIndex = $nextIndex; + $nextIndex = $ni unless $nextIndex > $ni; + } + # allow large tags to be excluded from extraction + # (provides a work-around for some tight memory situations) + next if $$tagInfo{LargeTag} and $$self{EXCL_TAG_LOOKUP}{lc $$tagInfo{Name}}; + # read value now if necessary + unless (defined $val and not $$tagInfo{SubDirectory}) { + $val = ReadValue($dataPt, $entry+$offset, $format, $count, $more, \$rational); + $mask = $$tagInfo{Mask}; + $val = ($val & $mask) >> $$tagInfo{BitShift} if $mask; + } + if ($verbose and not $$tagInfo{Hidden}) { + if (not $$tagInfo{SubDirectory} or $$tagInfo{Format}) { + $len = $count * ($formatSize{$format} || 1); + $len = $more if $len > $more; + } else { + $len = $more; + } + $self->VerboseInfo($index, $tagInfo, + Table => $tagTablePtr, + Value => $val, + DataPt => $dataPt, + Size => $len, + Start => $entry+$offset, + Addr => $entry+$offset+$base+$dataPos, + Format => $format, + Count => $count, + Extra => $mask ? sprintf(', mask 0x%.2x',$mask) : undef, + ); + } + # parse nested BinaryData directories + if ($$tagInfo{SubDirectory}) { + my $subdir = $$tagInfo{SubDirectory}; + my $subTablePtr = GetTagTable($$subdir{TagTable}); + # use specified subdirectory length if given + if ($$tagInfo{Format} and $formatSize{$format}) { + $len = $count * $formatSize{$format}; + $len = $more if $len > $more; + } else { + $len = $more; # directory size is all of remaining data + if ($$subTablePtr{PROCESS_PROC} and + $$subTablePtr{PROCESS_PROC} eq \&ProcessBinaryData) + { + # the rest of the data will be printed in the subdirectory + $nextIndex = $size / $increment; + } + } + my $subdirBase = $base; + if (defined $$subdir{Base}) { + #### eval Base ($start,$base) + my $start = $entry + $offset + $dataPos; + $subdirBase = eval($$subdir{Base}) + $base; + } + my $start = $$subdir{Start} || 0; + my %subdirInfo = ( + DataPt => $dataPt, + DataPos => $dataPos, + DataLen => length $$dataPt, + DirStart => $entry + $offset + $start, + DirLen => $len - $start, + Base => $subdirBase, + ); + delete $$self{NO_UNKNOWN}; + $self->ProcessDirectory(\%subdirInfo, $subTablePtr, $$subdir{ProcessProc}); + $$self{NO_UNKNOWN} = 1 if $unknown < 2; + next; + } + if ($$tagInfo{IsOffset} and $$tagInfo{IsOffset} ne '3') { + my $et = $self; + #### eval IsOffset ($val, $et) + $val += $base + $$self{BASE} if eval $$tagInfo{IsOffset}; + } + $val{$index} = $val; + my $oldBase; + if ($$tagInfo{SetBase}) { + $oldBase = $$self{BASE}; + $$self{BASE} += $base; + } + my $key = $self->FoundTag($tagInfo,$val); + $$self{BASE} = $oldBase if defined $oldBase; + if ($key) { + $$self{RATIONAL}{$key} = $rational if defined $rational; + } else { + # don't increment nextIndex if we didn't extract a tag + $nextIndex = $saveNextIndex if defined $saveNextIndex; + } + } + delete $$self{NO_UNKNOWN}; + return 1; +} + +#.............................................................................. +# Load .ExifTool_config file from user's home directory +# (use of noConfig is now deprecated, use configFile = '' instead) +until ($Image::ExifTool::noConfig) { + my $config = $Image::ExifTool::configFile; + my $file; + if (not defined $config) { + $config = '.ExifTool_config'; + # get our home directory (HOMEDRIVE and HOMEPATH are used in Windows cmd shell) + my $home = $ENV{EXIFTOOL_HOME} || $ENV{HOME} || + ($ENV{HOMEDRIVE} || '') . ($ENV{HOMEPATH} || '') || '.'; + # look for the config file in 1) the home directory, 2) the program dir + $file = "$home/$config"; + } else { + length $config or last; # filename of "" disables configuration + $file = $config; + } + # also check executable directory unless path is absolute + -r $file or $config =~ /^\// or $file = ($0 =~ /(.*[\\\/])/ ? $1 : './') . $config; + unless (-r $file) { + warn("Config file not found\n") if defined $Image::ExifTool::configFile; + last; + } + unshift @INC, '.'; # look in current directory first + eval { require $file }; # load the config file + shift @INC; + # print warning (minus "Compilation failed" part) + $@ and $_=$@, s/Compilation failed.*//s, warn $_; + last; +} +# read user-defined lenses (may have been defined by script instead of config file) +if (@Image::ExifTool::UserDefined::Lenses) { + foreach (@Image::ExifTool::UserDefined::Lenses) { + $Image::ExifTool::userLens{$_} = 1; + } +} +# add user-defined file types +if (%Image::ExifTool::UserDefined::FileTypes) { + foreach (sort keys %Image::ExifTool::UserDefined::FileTypes) { + my $fileInfo = $Image::ExifTool::UserDefined::FileTypes{$_}; + my $type = uc $_; + ref $fileInfo eq 'HASH' or $fileTypeLookup{$type} = $fileInfo, next; + my $baseType = $$fileInfo{BaseType}; + if ($baseType) { + if ($$fileInfo{Description}) { + $fileTypeLookup{$type} = [ $baseType, $$fileInfo{Description} ]; + } else { + $fileTypeLookup{$type} = $baseType; + } + if (defined $$fileInfo{Writable} and not $$fileInfo{Writable}) { + # first make sure we are using an actual base type and not a derived type + $baseType = $fileTypeLookup{$baseType} while $baseType and not ref $fileTypeLookup{$baseType}; + # mark this type as not writable + $noWriteFile{$baseType} or $noWriteFile{$baseType} = [ ]; + push @{$noWriteFile{$baseType}}, $type; + } + } else { + $fileTypeLookup{$type} = [ $type, $$fileInfo{Description} || $type ]; + $moduleName{$type} = 0; # not supported + if ($$fileInfo{Magic}) { + $magicNumber{$type} = $$fileInfo{Magic}; + push @fileTypes, $type unless grep /^$type$/, @fileTypes; + } + } + $mimeType{$type} = $$fileInfo{MIMEType} if defined $$fileInfo{MIMEType}; + } +} + +#------------------------------------------------------------------------------ +1; # end diff --git a/lib/Image/ExifTool.pod b/lib/Image/ExifTool.pod new file mode 100644 index 0000000..9941d5f --- /dev/null +++ b/lib/Image/ExifTool.pod @@ -0,0 +1,2646 @@ +#------------------------------------------------------------------------------ +# File: ExifTool.pod - Documentation for File::ExifTool +# +# Description: Read and write meta information +# +# URL: http://owl.phy.queensu.ca/~phil/exiftool/ +# +# Legal: Copyright (c) 2003-2019, Phil Harvey (phil at owl.phy.queensu.ca) +# This library is free software; you can redistribute it and/or +# modify it under the same terms as Perl itself. +#------------------------------------------------------------------------------ + +=head1 NAME + +Image::ExifTool - Read and write meta information + +=head1 SYNOPSIS + + use Image::ExifTool qw(:Public); + + # ---- Simple procedural usage ---- + + # Get hash of meta information tag names/values from an image + $info = ImageInfo('a.jpg'); + + # ---- Object-oriented usage ---- + + # Create a new Image::ExifTool object + $exifTool = new Image::ExifTool; + + # Extract meta information from an image + $exifTool->ExtractInfo($file, \%options); + + # Get list of tags in the order they were found in the file + @tagList = $exifTool->GetFoundTags('File'); + + # Get the value of a specified tag + $value = $exifTool->GetValue($tag, $type); + + # Get a tag description + $description = $exifTool->GetDescription($tag); + + # Get the group name associated with this tag + $group = $exifTool->GetGroup($tag, $family); + + # Set a new value for a tag + $exifTool->SetNewValue($tag, $newValue); + + # Write new meta information to a file + $success = $exifTool->WriteInfo($srcfile, $dstfile); + + # ...plus a host of other useful methods... + +=head1 DESCRIPTION + +Reads and writes meta information in a wide variety of files, including the +maker notes of many digital cameras by various manufacturers such as Canon, +Casio, DJI, FLIR, FujiFilm, GE, GoPro, HP, JVC/Victor, Kodak, Leaf, +Minolta/Konica-Minolta, Nikon, Nintendo, Olympus/Epson, Panasonic/Leica, +Pentax/Asahi, Phase One, Reconyx, Ricoh, Samsung, Sanyo, Sigma/Foveon and +Sony. + +Below is a list of file types and meta information formats currently +supported by ExifTool (r = read, w = write, c = create): + + File Types + ------------+-------------+-------------+-------------+------------ + 3FR r | DSS r | JNG r/w | ODS r | RIFF r + 3G2 r/w | DV r | JP2 r/w | ODT r | RSRC r + 3GP r/w | DVB r/w | JPEG r/w | OFR r | RTF r + A r | DVR-MS r | JSON r | OGG r | RW2 r/w + AA r | DYLIB r | K25 r | OGV r | RWL r/w + AAE r | EIP r | KDC r | OPUS r | RWZ r + AAX r/w | EPS r/w | KEY r | ORF r/w | RM r + ACR r | EPUB r | LA r | OTF r | SEQ r + AFM r | ERF r/w | LFP r | PAC r | SKETCH r + AI r/w | EXE r | LNK r | PAGES r | SO r + AIFF r | EXIF r/w/c | LRV r/w | PBM r/w | SR2 r/w + APE r | EXR r | M2TS r | PCD r | SRF r + ARQ r/w | EXV r/w/c | M4A/V r/w | PCX r | SRW r/w + ARW r/w | F4A/V r/w | MAX r | PDB r | SVG r + ASF r | FFF r/w | MEF r/w | PDF r/w | SWF r + AVI r | FLA r | MIE r/w/c | PEF r/w | THM r/w + AZW r | FLAC r | MIFF r | PFA r | TIFF r/w + BMP r | FLIF r/w | MKA r | PFB r | TORRENT r + BPG r | FLV r | MKS r | PFM r | TTC r + BTF r | FPF r | MKV r | PGF r | TTF r + CHM r | FPX r | MNG r/w | PGM r/w | VCF r + COS r | GIF r/w | MOBI r | PLIST r | VRD r/w/c + CR2 r/w | GPR r/w | MODD r | PICT r | VSD r + CR3 r/w | GZ r | MOI r | PMP r | WAV r + CRM r/w | HDP r/w | MOS r/w | PNG r/w | WDP r/w + CRW r/w | HDR r | MOV r/w | PPM r/w | WEBP r + CS1 r/w | HEIC r | MP3 r | PPT r | WEBM r + DCM r | HEIF r | MP4 r/w | PPTX r | WMA r + DCP r/w | HTML r | MPC r | PS r/w | WMV r + DCR r | ICC r/w/c | MPG r | PSB r/w | WTV r + DFONT r | ICS r | MPO r/w | PSD r/w | WV r + DIVX r | IDML r | MQV r/w | PSP r | X3F r/w + DJVU r | IIQ r/w | MRW r/w | QTIF r/w | XCF r + DLL r | IND r/w | MXF r | R3D r | XLS r + DNG r/w | INSV r | NEF r/w | RA r | XLSX r + DOC r | INX r | NRW r/w | RAF r/w | XMP r/w/c + DOCX r | ISO r | NUMBERS r | RAM r | ZIP r + DPX r | ITC r | O r | RAR r | + DR4 r/w/c | J2C r | ODP r | RAW r/w | + + Meta Information + ----------------------+----------------------+--------------------- + EXIF r/w/c | CIFF r/w | Ricoh RMETA r + GPS r/w/c | AFCP r/w | Picture Info r + IPTC r/w/c | Kodak Meta r/w | Adobe APP14 r + XMP r/w/c | FotoStation r/w | MPF r + MakerNotes r/w/c | PhotoMechanic r/w | Stim r + Photoshop IRB r/w/c | JPEG 2000 r | DPX r + ICC Profile r/w/c | DICOM r | APE r + MIE r/w/c | Flash r | Vorbis r + JFIF r/w/c | FlashPix r | SPIFF r + Ducky APP12 r/w/c | QuickTime r | DjVu r + PDF r/w/c | Matroska r | M2TS r + PNG r/w/c | MXF r | PE/COFF r + Canon VRD r/w/c | PrintIM r | AVCHD r + Nikon Capture r/w/c | FLAC r | ZIP r + GeoTIFF r/w/c | ID3 r | (and more) + +=head1 CONFIGURATION + +User-defined tags can be added via the ExifTool configuration file, or by +defining the %Image::ExifTool::UserDefined hash before calling any ExifTool +methods. See "ExifTool_config" in the ExifTool distribution for more +details. + +By default ExifTool looks for a configuration file named ".ExifTool_config" +first in your home directory, then in the directory of the application +script, but a different directory may be specified by setting the +EXIFTOOL_HOME environment variable, or a different file may be specified by +setting the ExifTool C variable before using Image::ExifTool. +For example: + + BEGIN { $Image::ExifTool::configFile = '/Users/phil/myconfig.cfg' } + use Image::ExifTool; + +The configuration feature may also be disabled by setting C to +an empty string: + + BEGIN { $Image::ExifTool::configFile = '' } + use Image::ExifTool; + +=head1 EXPORTS + +Exports nothing by default, but L and all static methods may be +exported with the C<:Public> export list. + +=head1 METHODS + +All ExifTool features are accessed through the methods of the public +interface listed below. Other Image::ExifTool methods and modules should +not be accessed directly because their interface may change with future +versions. + +None of these methods should ever die or issue warnings to STDERR if called +with the proper arguments (with the exception of L which may +send an error message to STDERR, but only when called in scalar context). +Error and warning messages that occur during processing are stored in the +values of the Error and Warning tags, and are accessible via the +L method to retrieve a single Error or Warning message, or +L to retrieve any number of them. + +The ExifTool methods are not thread safe. + +=head2 new + +Creates a new ExifTool object. + + $exifTool = new Image::ExifTool; + +Note that ExifTool uses AUTOLOAD to load non-member methods, so any class +using Image::ExifTool as a base class must define an AUTOLOAD which calls +Image::ExifTool::DoAutoLoad(). eg) + + sub AUTOLOAD + { + Image::ExifTool::DoAutoLoad($AUTOLOAD, @_); + } + +=head2 ImageInfo + +Read image file and return meta information. This is the one step function +for retrieving meta information from an image. Internally, L +calls L to extract the information, L to generate +the information hash, and L for the returned tag list. + + # return meta information for 2 tags only (procedural) + $info = ImageInfo($filename, $tag1, $tag2); + + # return information about an open image file (object-oriented) + $info = $exifTool->ImageInfo(\*FILE); + + # return information from image data in memory for specified tags + %options = (PrintConv => 0); + @tagList = qw(filename imagesize xmp:creator exif:* -ifd1:*); + $info = ImageInfo(\$imageData, \@tagList, \%options); + + # extract information from an embedded thumbnail image + $info = ImageInfo('image.jpg', 'thumbnailimage'); + $thumbInfo = ImageInfo($$info{ThumbnailImage}); + +=over 4 + +=item Inputs: + +L is very flexible about the input arguments, and interprets +them based on their type. It may be called with one or more arguments. +The one required argument is either a SCALAR (the image file name), a file +reference (a reference to the image file) or a SCALAR reference (a +reference to the image in memory). Other arguments are optional. The +order of the arguments is not significant, except that the first SCALAR is +taken to be the file name unless a file reference or scalar reference comes +earlier in the argument list. + +Below is an explanation of how the L function arguments are +interpreted: + +=over 4 + +=item ExifTool ref + +L may be called with an ExifTool object if desired. Advantages +of using the object-oriented form are that options may be set before calling +L, and the object may be used afterward to access member +functions. Must be the first argument if used. + +=item SCALAR + +The first scalar argument is taken to be the file name unless an earlier +argument specified the image data via a file reference (file ref) or data +reference (SCALAR ref). The remaining scalar arguments are names of tags +for requested information. All tags are returned if no tags are specified. + +Tag names are case-insensitive and may be prefixed by optional group names +separated by colons. A group name may begin with a family number (eg. +'1IPTC:Keywords'), to restrict matches to a specific family. In the tag +name, a '?' matches any single character and a '*' matches zero or more +characters. Thus 'GROUP:*' represents all tags in a specific group. +Wildcards may not be used in group names, with the exception that a group +name of '*' may be used to extract all available instances of a tag +regardless of the L setting (eg. '*:WhiteBalance'). Multiple +groups may be specified (eg. 'EXIF:Time:*' extracts all EXIF Time tags). And +finally, a leading '-' indicates a tag to be excluded (eg. '-IFD1:*'), or a +trailing '#' causes the ValueConv value to be returned for this tag. + +Note that keys in the returned information hash and elements of the returned +tag list are not necessarily the same as these tag names because group names +are removed, the case may be changed, and an instance number may be added. +For this reason it is best to use either the keys of the returned hash or +the elements of the returned tag list when accessing the tag values. + +See L for a complete +list of ExifTool tag names. + +=item File ref + +A reference to an open image file. If you use this method (or a SCALAR +reference) to access information in an image, the FileName and Directory +tags will not be returned. (Also, a number of the File System tags will not +be returned unless it is a plain file.) Image processing begins at the +current file position, and on return the file position is unspecified. May +be either a standard filehandle, or a reference to a +L object. Note that the file remains +open and must be closed by the caller after L returns. + +[Advanced: To allow a non-rewindable stream (eg. a network socket) to be +re-read after processing with ExifTool, first wrap the file reference in a +L object, then pass this object to +L. The L object will +buffer the file if necessary, and may be used to re-read the file after +L returns.] + +=item SCALAR ref + +A reference to image data in memory. + +=item ARRAY ref + +Reference to a list of tag names. On entry, any elements in the list are +added to the list of requested tags. Tags with names beginning with '-' are +excluded. On return, this list is updated to contain an ordered list of tag +keys for the returned information. + +There will be 1:1 correspondence between the requested tags and the returned +tag keys only if the L option is 0 and L is 'Input'. +(With L enabled, there may be more entries in the returned list +of tag keys, and with other L settings the entries may not be in the +same order as requested.) If a requested tag doesn't exist, a tag key is +still generated, but the tag value is undefined. + +=item HASH ref + +Reference to a hash containing the options settings valid for this call +only. See L documentation below for a list of available options. +Options specified as arguments to L take precedence over +L settings. + +=back + +=item Return Values: + +L returns a reference to a hash of tag key/value pairs. The tag +keys are identifiers -- essentially case-sensitive tag names with an +appended instance number if multiple tags with the same name were extracted +from the image. Many of the ExifTool functions require a tag key as an +argument. Use L to get the tag name for a given tag +key. Note that the case of the tag names may not be the same as requested. +Here is a simple example to print out the information returned by +L: + + foreach (sort keys %$info) { + print "$_ => $$info{$_}\n"; + } + +Values of the returned hash are usually simple scalars, but a scalar +reference is used to indicate binary data and an array reference may be used +to indicate a list. Also, a hash reference may be returned if the L +option is used. Lists of values are joined by commas into a single +string only if the PrintConv option is enabled and the ListJoin option is +enabled (which are the defaults). Note that binary values are not +necessarily extracted unless specifically requested, or the Binary option is +enabled and the tag is not specifically excluded. If not extracted the +value is a reference to a string of the form "Binary data ##### bytes". + +The code below gives an example of how to handle these return values, as +well as illustrating the use of other ExifTool functions: + + use Image::ExifTool; + my $exifTool = new Image::ExifTool; + $exifTool->Options(Unknown => 1); + my $info = $exifTool->ImageInfo('a.jpg'); + my $group = ''; + my $tag; + foreach $tag ($exifTool->GetFoundTags('Group0')) { + if ($group ne $exifTool->GetGroup($tag)) { + $group = $exifTool->GetGroup($tag); + print "---- $group ----\n"; + } + my $val = $info->{$tag}; + if (ref $val eq 'SCALAR') { + if ($$val =~ /^Binary data/) { + $val = "($$val)"; + } else { + my $len = length($$val); + $val = "(Binary data $len bytes)"; + } + } + printf("%-32s : %s\n", $exifTool->GetDescription($tag), $val); + } + +=item Notes: + +ExifTool returns all values as byte strings of encoded characters. Perl +wide characters are not used. See L for details about +the encodings. By default, most returned values are encoded in UTF-8. For +these, Encode::decode_utf8() may be used to convert to a sequence of logical +Perl characters. + +As well as tags representing information extracted from the image, the +following L generated by +ExifTool may be returned: + + ExifToolVersion - The ExifTool version number. + + Error - An error message if the image could not be processed. + + Warning - A warning message if problems were encountered while + processing the image. + +=back + +=head2 Options + +Get/set ExifTool options. This function can be called to set the default +options for an ExifTool object. Options set this way are in effect for +all function calls but may be overridden by options passed as arguments +to some functions. Option names are not case sensitive. + +The default option values may be changed by defining a +%Image::ExifTool::UserDefined::Options hash. See the ExifTool_config file +in the full ExifTool distribution for examples. + + # exclude the 'OwnerName' tag from returned information + $exifTool->Options(Exclude => 'OwnerName'); + + # only get information in EXIF or MakerNotes groups + $exifTool->Options(Group0 => ['EXIF', 'MakerNotes']); + + # ignore information from IFD1 + $exifTool->Options(Group1 => '-IFD1'); + + # sort by groups in family 2, and extract unknown tags + $exifTool->Options(Sort => 'Group2', Unknown => 1); + + # reset DateFormat option + $exifTool->Options(DateFormat => undef); + + # do not extract duplicate tag names + $oldSetting = $exifTool->Options(Duplicates => 0); + + # get current Verbose setting + $isVerbose = $exifTool->Options('Verbose'); + + # set a user parameter + $exifTool->Options(UserParam => 'MyParam=some value'); + +=over 4 + +=item Inputs: + +0) ExifTool object reference + +1) Option parameter name (case-insensitive) + +2) [optional] Option parameter value (may be undef to clear option) + +3-N) [optional] Additional parameter/value pairs + +=item Option Parameters: + +=over 4 + +=item Binary + +Flag to extract the value data for all binary tags. Tag values representing +large binary data blocks (eg. ThumbnailImage) are not necessarily extracted +unless this option is set or the tag is specifically requested by name. +Default is undef. + +=item ByteOrder + +The byte order for newly created EXIF segments when writing. Note that if +EXIF information already exists, the existing order is maintained. Valid +values are 'MM', 'II' and undef. If ByteOrder is not defined (the default), +then the maker note byte order is used (if they are being copied), otherwise +big-endian ('MM') order is assumed. This can also be set via the +L, but the ByteOrder +option takes precedence if both are set. + +=item Charset + +Character set for encoding character tag values passed to/from ExifTool with +code points above U+007F. Default is 'UTF8'. Valid values are listed +below, case is not significant: + + Value Alias(es) Description + ----------- --------------- ---------------------------------- + UTF8 cp65001, UTF-8 UTF-8 characters + Latin cp1252, Latin1 Windows Latin1 (West European) + Latin2 cp1250 Windows Latin2 (Central European) + Cyrillic cp1251, Russian Windows Cyrillic + Greek cp1253 Windows Greek + Turkish cp1254 Windows Turkish + Hebrew cp1255 Windows Hebrew + Arabic cp1256 Windows Arabic + Baltic cp1257 Windows Baltic + Vietnam cp1258 Windows Vietnamese + Thai cp874 Windows Thai + DOSLatinUS cp437 DOS Latin US + DOSLatin1 cp850 DOS Latin1 + MacRoman cp10000, Roman Macintosh Roman + MacLatin2 cp10029 Macintosh Latin2 (Central Europe) + MacCyrillic cp10007 Macintosh Cyrillic + MacGreek cp10006 Macintosh Greek + MacTurkish cp10081 Macintosh Turkish + MacRomanian cp10010 Macintosh Romanian + MacIceland cp10079 Macintosh Icelandic + MacCroatian cp10082 Macintosh Croatian + +Note that this option affects some types of information when reading/writing +the file and other types when getting/setting tag values, so it must be +defined for both types of access. See the L section +for more information about the handling of special characters. + +=item CharsetEXIF + +Internal encoding to use for stored EXIF "ASCII" string values. May also be +set to undef to pass through EXIF "ASCII" values without recoding. Set to +"UTF8" to conform with the MWG recommendation. Default is undef. + +=item CharsetFileName + +External character set used for file names passed to ExifTool functions. +When set in Windows, this triggers use of Windows wide-character i/o library +routines (requires Win32API::File). Default is undef. May also be set to +an empty string to avoid "encoding not specified" warnings on Windows. + +=item CharsetID3 + +Internal encoding to assume for ID3v1 strings. By the specification ID3v1 +strings should be encoded in ISO 8859-1 (essentially Latin), but some +applications may use local encoding instead. Default is 'Latin'. + +=item CharsetIPTC + +Fallback internal IPTC character set to assume if IPTC information contains +no CodedCharacterSet tag. Possible values are the same as the L +option. Default is 'Latin'. + +Note that this option affects some types of information when reading/writing +the file and other types when getting/setting tag values, so it must be +defined for both types of access. + +=item CharsetPhotoshop + +Internal encoding to assume for Photoshop IRB resource names. Default is +'Latin'. + +=item CharsetQuickTime + +Internal encoding to assume for QuickTime strings stored with an unspecified +encoding. Default is 'MacRoman'. + +=item CharsetRIFF + +Internal encoding to assume for strings in RIFF metadata (eg. AVI and WAV +files). The default value of 0 assumes "Latin" encoding unless otherwise +specified by the RIFF CSET chunk. Set to undef to pass through strings +without recoding. Default is 0. + +=item Compact + +Option to write compact XMP output. The XMP specification suggests that the +data be padded with blanks to allow in-place editing. With this flag set to +1, the 2 kB of padding is not written. Note that this only effects embedded +XMP since padding is never written for stand-alone XMP files. When set to +2, spaces to indent XMP for readability are also dropped. Default is undef. +Also see the XMPShorthand option for reducing the size of XMP. + +=item Composite + +Flag to generate Composite tags when extracting information. Default is 1. + +=item Compress + +Flag to write new values in compressed format if possible. Has no effect +unless Compress::Zlib is installed. Default is undef. + +=item CoordFormat + +Format for printing GPS coordinates. This is a printf format string with +specifiers for degrees, minutes and seconds in that order, however minutes +and seconds may be omitted. If the hemisphere is known, a reference +direction (N, S, E or W) is appended to each printed coordinate, but adding +a C<+> to the first format specifier (eg. C<%+.6f>) prints a signed +coordinate instead. For example, the following table gives the output for +the same coordinate using various formats: + + CoordFormat Example Output + ------------------- ------------------ + q{%d deg %d' %.2f"} 54 deg 59' 22.80" (default for reading) + q{%d %d %.8f} 54 59 22.80000000 (default for copying) + q{%d deg %.4f min} 54 deg 59.3800 min + q{%.6f degrees} 54.989667 degrees + +Note: To avoid loss of precision, the default coordinate format is +different when copying tags with L. + +=item DateFormat + +Format for printing date/time values. See C in the L +package for details about the format string. If date can not be converted, +value is left unchanged unless the StrictDate option is set. Timezones are +ignored. The inverse conversion (ie. when calling L) is +performed only if POSIX::strptime or Time::Piece is installed. The default +setting of undef causes date/time values to remain in standard EXIF format +(similar to a DateFormat of "%Y:%m:%d %H:%M:%S"). + +=item Duplicates + +Flag to return values from tags with duplicate names when extracting +information. Default is 1. + +=item Escape + +Escape special characters in extracted values for HTML or XML. Also +unescapes HTML or XML character entities in input values passed to +L. Valid settings are 'HTML', 'XML' or undef. Default is +undef. + +=item Exclude + +Exclude specified tags from tags extracted from an image. The option value +is either a tag name or reference to a list of tag names to exclude. The +case of tag names is not significant. This option is ignored for +specifically requested tags. Tags may also be excluded by preceding their +name with a '-' in the arguments to L. + +=item ExtendedXMP + +This setting affects the reading and editing of extended XMP in JPEG images. +According to the XMP specification, extended XMP is only valid if it has the +GUID specified by the HasExtendedXMP tag, so by default ExifTool will ignore +other extended XMP, but this option allows full control over the extended +XMP to be extracted. + + 0 - ignore all extended XMP + 1 - read extended XMP with valid GUID only (default) + 2 - read extended XMP with any GUID + - read extended XMP with a specific GUID + +=item ExtractEmbedded + +Flag to extract information from embedded documents in EPS files, embedded +EPS information and JPEG and Jpeg2000 images in PDF files, embedded MPF +images in JPEG and MPO files, streaming metadata in AVCHD videos, and the +resource fork of Mac OS files. Default is undef. + +=item FastScan + +Flag to increase speed of extracting information from JPEG images. With +this option set to 1, ExifTool will not scan to the end of a JPEG image to +check for an AFCP, CanonVRD, FotoStation, PhotoMechanic, MIE or PreviewImage +trailer. This also stops the parsing after the first comment in GIF images, +and at the audio/video data with RIFF-format files (AVI, WAV, etc), so any +trailing metadata (eg. XMP written by some utilities) may be missed. Also +disables input buffering for some types of files to reduce memory usage when +reading from a non-seekable stream. When combined with the ScanForXMP +option, prevents scanning for XMP in recognized file types. With a value of +2, ExifTool will also avoid extracting any EXIF MakerNote information. When +set to 3 or 4, only pseudo system tags and FileType are generated. For 3, +the file header is read to provide an educated guess at FileType. For 4, +the file is not read at all and FileType is determined based on the file's +extension. Default is undef. + +=item Filter + +Perl expression used to filter values for all tags. The expression acts on +the value of the Perl default variable ($_), and changes the value of this +variable as required. The value is not changed if $_ is set to undef. List +items are filtered individually. Applies to all returned values unless +PrintConv option is disabled. + +=item FixBase + +Fix maker notes base offset. A common problem with image editing software +is that offsets in the maker notes are not adjusted properly when the file +is modified. This may cause the wrong values to be extracted for some maker +note entries when reading the edited file. FixBase specifies an integer +value to be added to the maker notes base offset. It may also be set to the +empty string ('') for ExifTool will take its best guess at the correct base, +or undef (the default) for no base adjustment. + +=item GeoMaxIntSecs + +Maximum interpolation time in seconds for geotagging. Geotagging is treated +as an extrapolation if the Geotime value lies between two fixes in the same +track which are separated by a number of seconds greater than this. +Otherwise, the coordinates are calculated as a linear interpolation between +the nearest fixes on either side of the Geotime value. Set to 0 to disable +interpolation and use the coordinates of the nearest fix instead (provided +it is within GeoMaxExtSecs, otherwise geotagging fails). Default is 1800. + +=item GeoMaxExtSecs + +Maximum extrapolation time in seconds for geotagging. Geotagging fails if +the Geotime value lies outside a GPS track by a number of seconds greater +than this. Otherwise, the coordinates of the nearest fix are taken. +Default is 1800. + +=item GeoMaxHDOP + +Maximum Horizontal (2D) Dilution Of Precision for geotagging. GPS fixes are +ignored if the HDOP is greater than this. Default is undef. + +=item GeoMaxPDOP + +Maximum Position (3D) Dilution Of Precision for geotagging. GPS fixes are +ignored if the PDOP is greater than this. Default is undef. + +=item GeoMinSats + +Minimum number of satellites for geotagging. GPS fixes are ignored if the +number of acquired satellites is less than this. Default is undef. + +=item GeoSpeedRef + +Reference units for writing GPSSpeed when geotagging: + + 'K', 'k' or 'km/h' - km/h + 'M', 'm' or 'mph' - mph + - knots (default undef) + +=item GlobalTimeShift + +Time shift to apply to all extracted date/time PrintConv values. Does not +affect ValueConv values. Value is a date/time shift string (see +L), with a leading +'-' for negative shifts. Default is undef. + +=item Group# + +Extract tags only for specified groups in family # (Group0 assumed if # +not given). The option value may be a single group name or a reference +to a list of groups. Case is significant in group names. Specify a group +to be excluded by preceding group name with a '-'. See L for a +description of group families, and L for lists of +group names. + +=item HtmlDump + +Dump information in hex to dynamic HTML web page. The value may be 0-3 for +increasingly larger limits on the maximum block size. Default is 0. Output +goes to the file specified by the TextOut option (\*STDOUT by default). + +=item HtmlDumpBase + +Base for HTML dump offsets. If not defined, the EXIF/TIFF base offset is +used. Set to 0 for absolute offsets. Default is undef. + +=item IgnoreMinorErrors + +Flag to ignore minor errors. Causes minor errors to be downgraded to +warnings, and minor warnings to be ignored. This option is provided mainly +to allow writing of files when minor errors occur, but by ignoring some +minor warnings the behaviour of ExifTool may be changed to allow some +questionable operations to proceed (such as extracting thumbnail and preview +images even if they don't have a recognizable header). Minor errors and +warnings are denoted by "[minor]" at the start of the message, or "[Minor]" +(with a capital "M") for warnings that affect processing when ignored. + +=item Lang + +Localized language for exiftool tag descriptions, etc. Available languages +are given by the Image::ExifTool::Lang module names (eg. 'fr', 'zh_cn'). If +the specified language isn't available, the option is not changed. May be +set to undef to select the built-in default language. Default is 'en'. + +=item LargeFileSupport + +Flag to indicate that 64-bit file offsets are supported on this system. +Default is undef. + +=item ListItem + +Return only a specific item from list-type values. A value of 0 returns the +first item in the list, 1 return the second item, etc. Negative indices may +also be used, with -1 representing the last item in the list. Applies only +to the top-level list of nested lists. Default is undef to return all items +in the list. + +=item ListJoin + +Separator used to join the PrintConv value of multi-item List-type tags into +a single string. If not defined, multi-item lists are returned as a list +reference. Does not affect ValueConv values. Default is ', '. + +=item ListSplit + +Regular expression used to split values of list-type tags into individual +items when writing. (eg. use ',\\s*' to split a comma-separated list.) +Split when writing either PrintConv or ValueConv values. Default is undef. + +=item MakerNotes + +Option to extract MakerNotes and other writable subdirectories (such as +PrintIM) as a data block. Normally when the MakerNotes are extracted they +are rebuilt to include data outside the boundaries of the original maker +note data block, but a value of 2 disables this feature. Possible values +are: + + 0 - Do not extract writable subdirectories (same as default of undef) + 1 - Extract and rebuild maker notes into self-contained block + 2 - Extract without rebuilding maker notes + +=item MDItemTags + +Flag to extract the OS X metadata item tags (see the "mdls" man page and +L for more information). + +=item MissingTagValue + +Value for missing tags in tag name expressions (or tags where the advanced +formatting expression returns undef). If not set, a minor error is issued +for missing values, or the value is set to '' if L is +set. Default is undef. + +=item NoPDFList + +Flag to avoid splitting PDF list-type tag values into separate items. +Default is undef. + +=item Password + +Password for reading/writing password-protected PDF documents. Ignored if a +password is not required. Character encoding of the password is determined +by the value of the Charset option at processing time. Default is undef. + +=item PNGEarlyXMP + +Flag to write XMP in PNG images before the IDAT (image data) chunk. By +default, ExifTool adds new XMP to the end of a PNG file (just before IEND). +This is allowed by the PNG and XMP specifications, but some utilities seem +to ignore XMP if it comes after the image data. The PNGEarlyXMP option +causes ExifTool to instead add new XMP before the PNG IDAT chunk. However, +since ExifTool uses a single-pass writing algorithm, it has no way to tell +if XMP already exists later in the file before writing the new XMP in this +location. If this happens, a minor error is issued when the extra XMP is +encountered, and the file is not written. Adding the L +option causes the XMP after IDAT to be deleted, thus resolving the conflict +(at the expense of possible metadata loss), and allowing the file to be +written. The PNGEarlyXMP option is applied automatically when deleting all +XMP and writing new XMP back in one step. When reading, this option causes +a warning to be issued if standard XMP is found after the IDAT chunk. + +=item PrintConv + +Flag to enable automatic print conversion. Also enables inverse +print conversion for writing. Default is 1. + +=item QuickTimeUTC + +Flag set to assume that QuickTime date/time values are stored as UTC, +causing conversion to local time when they are extracted and from local time +when written. According to the QuickTime specification date/time values +should be UTC, but many digital cameras store local time instead (presumably +because they don't know the time zone), so the default is to not convert +these times. This option also disables the autodetection of incorrect +time-zero offsets in QuickTime date/time values, and enforces a time zero of +1904 as per the QuickTime specification. + +=item RequestAll + +Flag to request all tags to be extracted. This causes some tags to be +generated which normally would not be unless specifically requested (by +passing the tag name to L or L). May be set to 2 +or 3 to enable generation of some additional tags as mentioned in the tag +name documentation. Default is undef. + +=item RequestTags + +List of additional tag and/or group names to request in the next call to +L. This option is useful only for tags/groups which aren't +extracted unless specifically requested. Value may be a list reference, a +delimited string of names (any delimiter is allowed), or undef to clear the +current RequestTags list. Groups are requested by adding a colon after the +name (eg. "MacOS:"). Names are converted to lower case as they are added to +the list. Default is undef. + +=item ScanForXMP + +Flag to scan all files (even unrecognized formats) for XMP information +unless XMP was already found in the file. When combined with the FastScan +option, only unrecognized file types are scanned for XMP. Default is undef. + +=item Sort + +Specifies order to sort tags in returned list: + + Input - Sort in same order as input tag arguments (default) + File - Sort in order that tags were found in the file + Tag - Sort alphabetically by tag name + Descr - Sort by tag description (for current Lang setting) + Group# - Sort by tag group, where # is zero or more family + numbers separated by colons. If # is not specified, + Group0 is assumed. See GetGroup for a description + of group families. + +=item Sort2 + +Secondary sort order used for tags within each group when Sort is 'Group': + + File - Sort in order tags were found in the file (default) + Tag - Sort alphabetically by tag name + Descr - Sort by tag description (for current Lang setting) + +=item StrictDate + +Flag to return undefined value for any date which can't be converted when +the DateFormat option is used. Default is undef. + + undef - Same as 0 for reading/writing, or 1 for copying + 0 - Return date/time value unchanged if it can't be converted + 1 - Return undef if date/time value can't be converted + +When set to 1 while writing a PrintConv date/time value with the DateFormat +option set, the value is written only if POSIX::strptime or Time::Piece is +available and can successfully convert the value. + +For PNG CreationTime, a setting of 1 has the additional effect of causing +the date/time to be reformatted according to PNG 1.2 recommendation +(RFC-1123) when writing, and a warning to be issued for any non-standard +value when reading (but note that Windows may not recognize PNG date/time +values in standard format). + +=item Struct + +Flag to return XMP structures as hash references instead of flattening into +individual tags. Has no effect when writing since both flattened and +structured tags may always be written. Possible values are: + + undef - (default) Same as 0 for reading, 2 for copying + 0 - Read/copy flattened tags + 1 - Read/copy structured tags + 2 - Read/copy both flattened and structured tags, but flag + flattened tags as 'unsafe' for copying + +=item SystemTags + +Flag to extract the following additional File System tags: FileAttributes, +FileDeviceNumber, FileInodeNumber, FileHardLinks, FileUserID, FileGroupID, +FileDeviceID, FileBlockSize and FileBlockCount. + +=item TextOut + +Output file reference for Verbose and HtmlDump options. Default is +\*STDOUT. + +=item TimeZone + +Time zone for local date/time values. May be set to any valid TZ string. +Uses the system time zone if not specified. Default is undef. (Requires +POSIX::tzset, which may not be available in Windows. A work-around in +Windows is to CzoneE> before running ExifTool.) + +=item Unknown + +Flag to get the values of unknown tags. If set to 1, unknown tags are +extracted from EXIF (or other tagged-format) directories. If set to 2, +unknown tags are also extracted from binary data blocks. Default is 0. + +=item UserParam + +Special option to set/get user-defined parameters. Useful to allow external +input into tag name expressions and ValueConv logic. Valid UserParam values +are: + + PARAM - Get parameter + PARAM= - Clear parameter + PARAM^= - Set parameter to empty string + PARAM=VALUE - Set parameter + - Set entire UserParam hash lookup + undef - Clear all user parameters + +Where I is the user-defined parameter name (case insensitive). + +User-defined parameters may be accessed in tag name expressions by prefixing +the parameter name with a dollar sign just like normal tags, or via the API +by calling C. If called without no additional +arguments, C returns a reference to the hash of all +user parameters (with lower-case names). + +=item Validate + +Flag to perform extra validation checks when reading, causing extra warnings +to be generated if problems are found. Default is undef. + +=item Verbose + +Print verbose messages to file specified by TextOut option. Value may be +from 0 to 5 for increasingly verbose messages. Default is 0. With the +verbose option set, messages are printed to the console as the file is +parsed. Level 1 prints the tag names and raw values. Level 2 adds more +details about the tags. Level 3 adds a hex dump of the tag data, but with +limits on the number of bytes dumped. Levels 4 and 5 remove the dump limit +on tag values and JPEG segment data respectively. + +=item WriteMode + +Set tag write/create mode. Value is a string of one or more characters from +list below. Default is 'wcg'. + + w - Write existing tags + c - Create new tags + g - create new Groups as necessary + +The level of the group differs for different types of metadata. For XMP or +IPTC this is the full XMP/IPTC block (the family 0 group), but for EXIF this +is the individual IFD (the family 1 group). + +=item XAttrTags + +Flag to extract the OS X extended attribute tags (see the "xattr" man page +and L for more information). + +=item XMPAutoConv + +Flag to enable automatic conversion for unknown XMP tags with values that +look like rational numbers or dates. Default is 1. + +=item XMPShorthand + +Flag set to write xmp in shorthand format. Default is undef. + +=back + +=item Return Values: + +The original value of the last specified parameter. + +=back + +=head2 ClearOptions + +Reset all options to their default values. Loads user-defined default +option values from the %Image::ExifTool::UserDefined::Options hash in the +.ExifTool_config file if it exists. + + $exifTool->ClearOptions(); + +=over 4 + +=item Inputs: + +0) ExifTool object reference + +=item Return Values: + +(none) + +=back + +=head2 ExtractInfo + +Extract all meta information from an image. + + $success = $exifTool->ExtractInfo('image.jpg', \%options); + +=over 4 + +=item Inputs: + +L takes exactly the same arguments as L. The only +difference is that a list of tag keys is not returned if an ARRAY reference +is given. The following options are effective in the call to +L: + +Binary, Charset, CharsetEXIF, CharsetFileName, CharsetID3, CharsetIPTC, +CharsetPhotoshop, CharsetQuickTime, CharsetRIFF, Composite, ExtendedXMP, +ExtractEmbedded, FastScan, FixBase, HtmlDump, HtmlDumpBase, +IgnoreMinorErrors, Lang, LargeFileSupport, MakerNotes, MDItemTags, +NoPDFList, Password, PNGEarlyXMP, QuickTimeUTC (enforced 1904 time zero), +RequestAll, RequestTags, ScanForXMP, Struct, TextOut, Unknown, Verbose, +XAttrTags and XMPAutoConv. + +=item Return Value: + +1 if this was a recognized file format, 0 otherwise (and 'Error' tag set). + +=back + +=head2 GetInfo + +L is called to return meta information after it has been extracted +from the image by a previous call to L or L. This +function may be called repeatedly after a single call to L or +L. + + # get image width and height only + $info = $exifTool->GetInfo('ImageWidth', 'ImageHeight'); + + # get all Error and Warning messages + $info = $exifTool->GetInfo('Error', 'Warning'); + + # get information for all tags in list (list updated with tags found) + $info = $exifTool->GetInfo(\@ioTagList); + + # get all information in Author or Location groups + $info = $exifTool->GetInfo({Group2 => ['Author', 'Location']}); + +=over 4 + +=item Inputs: + +Inputs are the same as L and L except that an +image can not be specified. Options in effect are: + +Charset, CoordFormat, DateFormat, Duplicates, Escape, Exclude, Filter, +Group#, GlobalTimeShift, Lang, ListItem, ListJoin, PrintConv, Sort (if a tag +list reference is given) and StrictDate. + +=item Return Value: + +Reference to information hash, the same as with L. + +=back + +The following options are effective in the call to L: + +Charset, CoordFormat, DateFormat, Duplicates, Escape, Exclude, Filter, +Group#, GlobalTimeShift, Lang, ListItem, ListJoin, PrintConv, QuickTimeUTC +(conversion to local time), Sort (if a tag list reference is given) and +StrictDate. + +=head2 WriteInfo + +Write meta information to a file. The specified source file is rewritten to +the same-type destination file with new information as specified by previous +calls to L. The necessary segments and/or directories are +created in the destination file as required to store the specified +information. May be called repeatedly to write the same information to +additional files without the need to call L again. + +Note that it is NOT necessary to call L or L +before L. L changes only metadata specified by +previous calls to L. + + + # add information to a source file, writing output to new file + $exifTool->WriteInfo($srcfile, $dstfile); + + # create XMP data file from scratch + $exifTool->WriteInfo(undef, $dstfile, 'XMP'); + + # overwrite file (you do have backups, right?) + $exifTool->WriteInfo($srcfile); + +=over 4 + +=item Inputs: + +0) ExifTool object reference + +1) Source file name, file reference, scalar reference, or undef to create a +file from scratch. A reference to a +L object is also allowed as a source, +but in this case the destination is not optional. + +2) [optional] Destination file name, file reference, scalar reference, or +undef to overwrite the original file. May be '-' to write to stdout. + +3) [optional] Destination file type. Ignored if a source is defined. + +=item Return Value: + +1 if file was written OK, 2 if file was written but no changes made, 0 on +file write error. + +If an error code is returned, an Error tag is set and GetValue('Error') can +be called to obtain the error description. A Warning tag may be set even if +this routine is successful. Calling WriteInfo clears any pre-existing Error +and Warning tags. + + $errorMessage = $exifTool->GetValue('Error'); + $warningMessage = $exifTool->GetValue('Warning'); + +=item Notes: + +The source file name may be undefined to create a file from scratch +(currently only XMP, MIE, ICC, VRD, DR4, EXV and EXIF files can be created +in this way -- see L for details). If undefined, the +destination file type is required unless the type can be determined from the +extension of the destination file name. + +If a destination file name is given, the specified file must not exist +because an existing destination file will not be overwritten. Any new +values for FileName, Directory or HardLink are ignored when a destination +file name is specified. + +The destination file name may be undefined to overwrite the original file +(make sure you have backups!). In this case, if a source file name is +provided, a temporary file is created and renamed to replace the source file +if no errors occurred while writing. Otherwise, if a source file reference +or scalar reference is used, the image is first written to memory then +copied back to replace the original if there were no errors. + +On Mac OS systems, the file resource fork is preserved if this routine is +called with a source file name. + +=back + +The following ExifTool options are effective in the call to L: + +ByteOrder, Charset, CharsetEXIF, CharsetFileName, CharsetIPTC, Compact, +Compress, FixBase, IgnoreMinorErrors, Password, PNGEarlyXMP, Verbose and +XMPShorthand. + +=head2 GetTagList + +Get a sorted list of tags from the specified information hash or tag list. + + @tags = $exifTool->GetTagList($info, 'Group0'); + +=over 4 + +=item Inputs: + +0) ExifTool object reference + +1) [optional] Information hash reference or tag list reference + +2) [optional] Sort order ('Input', 'File', 'Tag', 'Descr' or 'Group#') + +3) [optional] Secondary sort order ('File', 'Tag' or 'Descr') + +If the information hash or tag list reference is not provided, then the list +of found tags from the last call to L, L or +L is used instead, and the result is the same as if +L was called. If sort order is not specified, the sort order +is taken from the current options settings. + +=item Return Values: + +A list of tag keys in the specified order. + +=back + +=head2 GetFoundTags + +Get list of found tags in specified sort order. The found tags are the tags +for the information obtained from the most recent call to L, +L or L for this object. + + @tags = $exifTool->GetFoundTags('File'); + +=over 4 + +=item Inputs: + +0) ExifTool object reference + +1) [optional] Sort order ('Input', 'File', 'Tag', 'Descr' or 'Group#') + +2) [optional] Secondary sort order ('File', 'Tag' or 'Descr') + +If sort order is not specified, the sort order from the ExifTool options is +used. + +=item Return Values: + +A list of tag keys in the specified order. + +=back + +=head2 GetRequestedTags + +Get list of requested tags. These are the tags that were specified in the +arguments of the most recent call to L, L or +L, including tags specified via a tag list reference. Shortcut +tags are expanded in the list. + + @tags = $exifTool->GetRequestedTags(); + +=over 4 + +=item Inputs: + +(none) + +=item Return Values: + +List of requested tag keys in the same order that the tags were specified. +Note that this list will be empty if tags were not specifically requested +(ie. If extracting all tags). + +=back + +=head2 GetValue + +Get the value of a specified tag. The returned value is either the +human-readable (PrintConv) value, the converted machine-readable (ValueConv) +value, the original raw (Raw) value, or the original rational (Rational) +value for rational formats. If the value type is not specified, the +PrintConv value is returned if the PrintConv option is set, otherwise the +ValueConv value is returned. The PrintConv values are same as the values +returned by L and L in the tag/value hash unless the +PrintConv option is disabled. + +Tags which represent lists of multiple values (as may happen with 'Keywords' +for example) are handled specially. In scalar context, the returned +PrintConv value for these tags is either a string of values or a list +reference (depending on the ListJoin option setting), and the ValueConv +value is always a list reference. But in list context, L always +returns the list itself. + +Note that L requires a case-sensitive tag key as an argument. To +retrieve tag information based on a case-insensitive tag name (with an +optional group specifier), use L instead. + + # PrintConv example + my $val = $exifTool->GetValue($tag); + if (ref $val eq 'SCALAR') { + print "$tag = (unprintable value)\n"; + } else { + print "$tag = $val\n"; + } + + # ValueConv examples + my $val = $exifTool->GetValue($tag, 'ValueConv'); + if (ref $val eq 'ARRAY') { + print "$tag is a list of values\n"; + } elsif (ref $val eq 'SCALAR') { + print "$tag represents binary data\n"; + } else { + print "$tag is a simple scalar\n"; + } + + my @keywords = $exifTool->GetValue('Keywords', 'ValueConv'); + +The following options are in effect when L is called: + +Charset, CoordFormat, DateFormat, Escape, Filter, GlobalTimeShift, Lang, +ListItem, ListJoin, PrintConv, QuickTimeUTC (conversion to local time), +StrictDate and TimeZone. + +=over 4 + +=item Inputs: + +0) ExifTool object reference + +1) Tag key, or case-sensitive tag name with optional group prefix(es) + +2) [optional] Value type: 'PrintConv', 'ValueConv', 'Both', 'Raw' or +'Rational' + +The default value type is 'PrintConv' if the PrintConv option is set, +otherwise the default is 'ValueConv'. A value type of 'Both' returns both +ValueConv and PrintConv values as a list. 'Rational' returns the raw +rational value as a string fraction for rational types, or undef for other +types. + +=item Return Values: + +The value of the specified tag. If the tag represents a list of multiple +values and the ListJoin option is enabled then PrintConv returns a string of +values, otherwise a reference to the list is returned in scalar context. The +list itself is returned in list context. (Unless 'Both' values are +requested, in which case two list references are returned, regardless of +context.) Values may also be scalar references to binary data, or hash +references if the L option is set. + +Note: It is possible for L to return an undefined ValueConv or +PrintConv value (or an empty list in list context) even if the tag exists, +since it is possible for these conversions to yield undefined values. And +the Rational value will be undefined for any non-rational tag. The Raw +value should always exist if the tag exists. + +=back + +=head2 SetNewValue + +Set the new value for a tag. The routine may be called multiple times to +set the values of many tags before using L to write the new +values to an image. + +For list-type tags (like Keywords), either call repeatedly with the same tag +name for each value, or call with a reference to the list of values. + + # set a new value for a tag (errors go to STDERR) + $success = $exifTool->SetNewValue($tag, $value); + + # set a new value and capture any error message + ($success, $errStr) = $exifTool->SetNewValue($tag, $value); + + # delete information for specified tag if it exists in image + # (also resets AddValue and DelValue options for this tag) + $exifTool->SetNewValue($tag); + + # reset all values from previous calls to SetNewValue() + $exifTool->SetNewValue(); + + # delete a specific keyword + $exifTool->SetNewValue('Keywords', $word, DelValue => 1); + + # set keywords (a list-type tag) with two new values + $exifTool->SetNewValue(Keywords => 'word1'); + $exifTool->SetNewValue(Keywords => 'word2'); + # equivalent, but set both in one call using an array reference + $exifTool->SetNewValue(Keywords => ['word1','word2']); + + # add a keyword without replacing existing keywords in the file + $exifTool->SetNewValue(Keywords => $word, AddValue => 1); + + # conditionally add a tag if it didn't exist before, + # or replace it if it had a specified value ("old value") + $exifTool->SetNewValue(Description => '', DelValue => 1); + $exifTool->SetNewValue(Description => 'old value', DelValue => 1); + $exifTool->SetNewValue(Description => 'new value'); + + # set a tag in a specific group + $exifTool->SetNewValue(Headline => $val, Group => 'XMP'); + $exifTool->SetNewValue('XMP:Headline' => $val); # (equivalent) + + # shift original date/time back by 2.5 hours + $exifTool->SetNewValue(DateTimeOriginal => '2:30', Shift => -1); + + # write a tag only if it had a specific value + # (the order of the following calls is not significant) + $exifTool->SetNewValue(Title => $oldVal, DelValue => 1); + $exifTool->SetNewValue(Title => $newVal); + + # write tag by numerical value + $exifTool->SetNewValue(Orientation => 6, Type => 'ValueConv'); + $exifTool->SetNewValue('Orientation#' => 6); # (equivalent) + + # delete all but EXIF tags + $exifTool->SetNewValue('*'); # delete all... + $exifTool->SetNewValue('EXIF:*', undef, Replace => 2); # ...but EXIF + + # write structured information as a HASH reference + $exifTool->SetNewValue('XMP:Flash' => { + mode => 'on', + fired => 'true', + return => 'not' + }); + + # write structured information as a serialized string + $exifTool->SetNewValue('XMP:Flash'=>'{mode=on,fired=true,return=not}'); + +(See L for +a description of the structure serialization technique.) + +=over 4 + +=item Inputs: + +0) ExifTool object reference + +1) [optional] Tag key or tag name, or undef to clear all new values. The +tag name may be prefixed by one or more family 0, 1 or 2 group names with +optional leading family numbers, separated by colons (eg. 'EXIF:Artist', +'XMP:Time:*'), which is equivalent to using a Group option argument. Also, +a '#' may be appended to the tag name (eg. 'EXIF:Orientation#'), with the +same effect as setting Type to 'ValueConv'. Wildcards ('*' and '?') may be +used in the tag name to assign multiple tags simultaneously. A tag name of +'*' is special when deleting information, and will delete an entire group +even if some individual tags in the group are not writable, but only if a +single family 0 or 1 group is specified (otherwise the tags are deleted +individually). Use L to get a list of deletable group +names, and see L for a +complete list of tag names. + +2) [optional] New value for tag. Undefined to delete tag from file. May be +a scalar, scalar reference, list reference to set a list of values, or hash +reference for a structure. Integer values may be specified as a hexadecimal +string (with a leading '0x'), and simple rational values may be specified in +fractional form (eg. '4/10'). Structure tags may be specified either as a +hash reference or a serialized string (see the last two examples above). + +3-N) [optional] SetNewValue option/value pairs (see below). + +=item SetNewValue Options: + +=over 4 + +=item AddValue + +Specifies that the value be added to an existing list in a file rather than +overwriting. Valid settings are 0 (overwrite any existing tag value), 1 +(add to an existing list and warn for non-list tags) or 2 (add to existing +list and overwrite non-list tags). Default is 0. + +=item DelValue + +Delete existing tag from a file if it has the specified value. For +list-type tags this deletes a specified item from the list. For non-list +tags this may be used to conditionally replace a tag by providing a new +value in a separate call to L (see examples above). For +structured tags, the entire structure is deleted/replaced only if all of the +specified fields match the existing structure. Option values are 0 or 1. +Default is 0. + +=item EditGroup + +Create tags in existing groups only. Don't create new group. Valid values +are 0 and 1. Effectively removes the 'g' from the ExifTool WriteMode option +for this tag only. Default is 0. + +=item EditOnly + +Edit tag only if it already exists. Don't create new tag. Valid values are +0 and 1. Effectively removes the 'c' from the ExifTool WriteMode option for +this tag only. Default is 0. + +=item Group + +Specifies group name where tag should be written. This option is superseded +by any group specified in the tag name. If not specified, tag is written to +highest priority group as specified by L. May be one or more +family 0, 1 or 2 groups with optional leading family number, separated by +colons. Case is not significant. + +=item NoFlat + +Treat flattened tags as 'unsafe'. + +=item NoShortcut + +Disables default behaviour of looking up tag in shortcuts if not found +otherwise. + +=item Protected + +Bit mask for tag protection levels to write. Bit 0x01 allows writing of +'unsafe' tags (ie. tags not copied automatically via +L). Bit 0x02 allows writing of 'protected' tags, and +should only be used internally by ExifTool. See +L, for a list of tag +names indicating 'unsafe' and 'protected' tags. Default is 0. + +=item ProtectSaved + +Avoid setting new values which were saved after the Nth call to +L. Has no effect on unsaved values, or values saved before +Nth call. Option value is N. Default is undef. + +=item Replace + +Flag to replace the previous new values for this tag (ie. replace the values +set in previous calls to L). This option is most commonly +used to replace previously-set new values for list-type tags. Valid values +are 0 (set new value normally -- adds to new values for list-type tags), 1 +(reset previous new values for this tag and replace with the specified new +value) or 2 (reset previous new values only). + +=item Shift + +Shift the tag by the specified value. Currently only date/time tags and +tags with numerical values may be shifted. Undefined for no shift, 1 for a +positive shift, or -1 for a negative shift. A value of 0 causes a positive +shift to be applied if the tag is shiftable and AddValue is set, or a +negative shift for date/time tags only if DelValue is set. Default is undef. +See L for more +information. + +=item Type + +The type of value being set. Valid values are PrintConv, ValueConv or Raw. +Default is PrintConv if the L Option is set, otherwise +ValueConv. + +=back + +=item Return Values: + +In scalar context, returns the number of tags set and error messages are +printed to STDERR. In list context, returns the number of tags set, and the +error string (which is undefined if there was no error). + +=item Notes: + +When deleting groups of tags, the Replace option may be used to exclude +specific groups from a mass delete. However, this technique may not be used +to exclude individual tags from a group delete (unless a family 2 group was +specified in the delete). Instead, use L to recover +the values of individual tags after deleting a group. + +When deleting all tags from a JPEG image, the APP14 "Adobe" information is +not deleted by default because doing so may affect the appearance of the +image. However, this information may be deleted by specifying it +explicitly, either by group (with 'Adobe:*') or as a block (with 'Adobe'). + +=back + +The following ExifTool options are effective in the call to L: + +Charset, DateFormat, Escape, IgnoreMinorErrors, Lang, ListJoin, ListSplit, +PrintConv, QuickTimeUTC, StrictDate, TimeZone, Verbose and WriteMode. + +=head2 GetNewValue + +Get the new Raw value for a tag. This is the value set by L +this is queued to be written to file. List-type tags may return multiple +values in list context. + + $rawVal = $exifTool->GetNewValue($tag); + + @rawVals = $exifTool->GetNewValue($tag); + +=over 4 + +=item Inputs: + +0) ExifTool object reference + +1) Tag name (case sensitive, may be prefixed by family 0 or 1 group name) + +=item Return Values: + +List of new Raw tag values, or first value in list when called in scalar +context. The list may be empty either if the tag isn't being written, or if +it is being deleted (ie. if L was called without a value). + +=back + +=head2 SetNewValuesFromFile + +A very powerful routine that sets new values for tags from information found +in a specified file. + + # set new values from all information in a file... + my $info = $exifTool->SetNewValuesFromFile($srcFile); + # ...then write these values to another image + my $result = $exifTool->WriteInfo($file2, $outFile); + + # set all new values, preserving original groups + $exifTool->SetNewValuesFromFile($srcFile, '*:*'); + + # set specific information + $exifTool->SetNewValuesFromFile($srcFile, @tags); + + # set new value from a different tag in specific group + $exifTool->SetNewValuesFromFile($fp, 'XMP-dc:SubjectSetNewValuesFromFile($fp, 'XMP-dc:Subject+SetNewValuesFromFile($file, + 'CommentSetNewValuesFromFile($file, { Replace => 0 }, + 'keywordsSetNewValuesFromFile($file, '*:*SetNewValuesFromFile($file, 'gps*'); + + # set FileName from Model, translating questionable characters + $exifTool->SetNewValuesFromFile($file, + 'filename<${model; tr(/\\\\?*:|"><)(_) }.jpg'); + +=over 4 + +=item Inputs: + +0) ExifTool object reference + +1) File name, file reference, or scalar reference + +2-N) [optional] List of tag names to set or options hash references. All +writable tags are set if none are specified. The tag names are not case +sensitive, and may be prefixed by one or more family 0, 1 or 2 group names +with optional leading family numbers, separated by colons (eg. 'exif:iso'). +A leading '-' indicates tags to be excluded (eg. '-comment'), or a trailing +'#' causes the ValueConv value to be copied (same as setting the Type option +to 'ValueConv' for this tag only). Wildcards ('*' and '?') may be used in +the tag name. A tag name of '*' is commonly used when a group is specified +to copy all tags in the group (eg. 'XMP:*'). A special feature allows tag +names of the form 'DSTTAGESRCTAG' (or 'SRCTAGEDSTTAG') to be +specified to copy information to a tag with a different name or a specified +group. Both 'SRCTAG' and 'DSTTAG' may contain wildcards and/or be prefixed +by a group name (eg. 'fileModifyDateEmodifyDate' or 'xmp:*E*'), +and/or suffixed by a '#' to disable print conversion. Copied tags may also +be added or deleted from a list with arguments of the form +'DSTTAG+ESRCTAG' or 'DSTTAG-ESRCTAG'. Tags are evaluated in order, +so exclusions apply only to tags included earlier in the list. An extension +of this feature allows the tag value to be set from a string containing tag +names with leading '$' symbols (eg. 'CommentEthe file is $filename'). +Braces '{}' may be used around the tag name to separate it from subsequent +text, and a '$$' is used to to represent a '$' symbol. The behaviour for +missing tags in expressions is defined by the L option. +The tag value may be modified via changes to the default input variable ($_) +in a Perl expression placed inside the braces and after a semicolon +following the tag name (see the last example above). A '@' may be added +after the tag name (before the semicolon) to make the expression act on +individual list items instead of the concatenated string for list-type tags. +Braces within the expression must be balanced. Multiple options hash +references may be passed to set different options for different tags. +Options apply to subsequent tags in the argument list. + +By default, this routine will commute information between same-named tags in +different groups, allowing information to be translated between images with +different formats. This behaviour may be modified by specifying a group +name for extracted tags (even if '*' is used as a group name), in which case +the information is written to the original group, unless redirected to a +different group. When '*' is used for a group name, by default the family 1 +group of the original tag is preserved, but a different family may be +specified with a leading family number. (For example, specifying '*:*' +copies all information while preserving the original family 1 groups, while +'0*:*' preserves the family 0 group.) + +=item SetNewValuesFromFile Options: + +The options are the same was for L, and are passed directly +to L internally, with a few exceptions: + +- The Replace option defaults to 1 instead of 0 as with L. + +- The AddValue or DelValue option is set for individual tags if '+>' or '->' +(or '+E' or '-E') are used. + +- The Group option is set for tags where a group name is given. + +- The Protected flag is set to 1 for individually specified tags. + +- The Type option also applies to extracted tags. + +=item Return Values: + +A hash of information that was set successfully. May include Warning or +Error entries if there were problems reading the input file. + +=item Notes: + +The PrintConv option applies to this routine, but it normally should be left +on to provide more reliable transfer of information between groups. + +If a preview image exists, it is not copied. The preview image must be +transferred separately if desired, in a separate call to L + +When simply copying all information between files of the same type, it is +usually desirable to preserve the original groups by specifying '*:*' for +the tags to set. + +The L option is always in effect for tags extracted from the +source file using this routine. + +The L option is enabled by default for tags extracted by this +routine. This allows the hierarchy of complex structures to be preserved +when copying, but the Struct option may be set to 0 to override this +behaviour and copy as flattened tags instead. + +=back + +=head2 CountNewValues + +Return the total number of new values set. + + $numSet = $exifTool->CountNewValues(); + ($numSet, $numPseudo) = $exifTool->CountNewValues(); + +=over 4 + +=item Inputs: + +0) ExifTool object reference + +=item Return Values: + +In scalar context, returns the total number of tags with new values set. In +list context, also returns the number of "pseudo" tag values which have been +set. "Pseudo" tags are tags like FileName and FileModifyDate which are not +contained within the file and can be changed without rewriting the file. + +=back + +=head2 SaveNewValues + +Save state of new values to be later restored by L. + + $exifTool->SaveNewValues(); # save state of new values + $exifTool->SetNewValue(ISO => 100); # set new value for ISO + $exifTool->WriteInfo($src, $dst1); # write ISO + previous new values + $exifTool->RestoreNewValues(); # restore previous new values + $exifTool->WriteInfo($src, $dst2); # write previous new values only + +=over 4 + +=item Inputs: + +0) ExifTool object reference + +=item Return Value: + +Count of the number of times this routine has been called (N) since the last +time the new values were reset. + +=back + +=head2 RestoreNewValues + +Restore new values to the settings that existed when L was +last called. May be called repeatedly after a single call to +L. See L above for an example. + +=over 4 + +=item Inputs: + +0) ExifTool object reference + +=item Return Value: + +None. + +=back + +=head2 SetFileModifyDate + +Write the filesystem modification or creation time from the new value of the +FileModifyDate or FileCreateDate tag. + + $exifTool->SetNewValue(FileModifyDate => '2000:01:02 03:04:05-05:00', + Protected => 1); + $result = $exifTool->SetFileModifyDate($file); + +=over 4 + +=item Inputs: + +0) ExifTool object reference + +1) File name + +2) [optional] Base time if applying shift (days before $^T) + +3) [optional] Tag to write: 'FileModifyDate' (default), or 'FileCreateDate' + +=item Return Value: + +1 if the time was changed, 0 if nothing was done, or -1 if there was an +error setting the time. + +=item Notes: + +Equivalent to, but more efficient than calling L when only the +FileModifyDate or FileCreateDate tag has been set. If a timezone is not +specified, local time is assumed. When shifting, the time of the original +file is used unless the optional base time is specified. + +The ability to write FileCreateDate is currently restricted to Windows +systems only. + +=back + +=head2 SetFileName + +Set the file name and directory, or create a hard link. If not specified, +the new file name is derived from the new values of the FileName and +Directory tags, or from the HardLink tag if creating a link. If the +FileName tag contains a '/', then the file is renamed into a new directory. +If FileName ends with '/', then it is taken as a directory name and the file +is moved into the new directory. The new value for the Directory tag takes +precedence over any directory specified in FileName. + + $result = $exifTool->SetFileName($file); + $result = $exifTool->SetFileName($file, $newName); + +=over 4 + +=item Inputs: + +0) ExifTool object reference + +1) Current file name + +2) [optional] New file name + +3) [optional] 'Link' to create a hard link instead of renaming the file, or +'Test' to test renaming feature by printing the old and new names instead of +changing anything. + +=item Return Value: + +1 if the file name or directory was changed, 0 if nothing was done, or -1 if +there was an error renaming the file. + +=item Notes: + +Will not overwrite existing files. New directories are created as necessary. + +=back + +=head2 SetNewGroups + +Set the order of the preferred groups when adding new information. In +subsequent calls to L, new information will be created in the +first valid group of this list. This has an impact only if the group is not +specified when calling L and if the tag name exists in more +than one group. The default order is EXIF, IPTC then XMP. Any family 0 +group name may be used. Case is not significant. + + $exifTool->SetNewGroups('XMP','EXIF','IPTC'); + +=over 4 + +=item Inputs: + +0) ExifTool object reference + +1-N) Groups in order of priority. If no groups are specified, the priorities +are reset to the defaults. + +=item Return Value: + +None. + +=back + +=head2 GetNewGroups + +Get current group priority list. + + @groups = $exifTool->GetNewGroups(); + +=over 4 + +=item Inputs: + +0) ExifTool object reference + +=item Return Values: + +List of group names in order of write priority. Highest priority first. + +=back + +=head2 GetTagID + +Get the ID for the specified tag. The ID is the IFD tag number in EXIF +information, the property name in XMP information, or the data offset in a +binary data block. For some tags, such as Composite tags where there is no +ID, an empty string is returned. In list context, also returns a language +code for the tag if available and different from the default language (eg. +with alternate language entries for XMP "lang-alt" tags). + + $id = $exifTool->GetTagID($tag); + ($id, $lang) = $exifTool->GetTagID($tag); + +=over 4 + +=item Inputs: + +0) ExifTool object reference + +1) Tag key + +=item Return Values: + +In scalar context, returns the tag ID or '' if there is no ID for this tag. +In list context, returns the tag ID (or '') and the language code (or +undef). + +=back + +=head2 GetDescription + +Get description for specified tag. This function will always return a +defined value. In the case where the description doesn't exist, one is +generated from the tag name. + +=over 4 + +=item Inputs: + +0) ExifTool object reference + +1) Tag key + +=item Return Values: + +A description for the specified tag. + +=back + +=head2 GetGroup + +Get group name(s) for a specified tag. + + # return family 0 group name (eg. 'EXIF'); + $group = $exifTool->GetGroup($tag, 0); + + # return all groups (eg. qw{EXIF IFD0 Author Main}) + @groups = $exifTool->GetGroup($tag); + + # return groups as a string (eg. 'Main:IFD0:Author') + $group = $exifTool->GetGroup($tag, ':3:1:2'); + + # return groups as a simplified string (eg. 'IFD0:Author') + $group = $exifTool->GetGroup($tag, '3:1:2'); + +=over 4 + +=item Inputs: + +0) ExifTool object reference + +1) Tag key + +2) [optional] Group family number, or string of numbers separated by colons + +=item Return Values: + +Group name (or '' if tag has no group). If no group family is specified, +L returns the name of the group in family 0 when called in scalar +context, or the names of groups for all families in list context. Returns a +string of group names separated by colons if the input group family contains +a colon. The string is simplified to remove a leading 'Main:' and adjacent +identical group names unless the family string begins with a colon. + +=item Notes: + +The group family numbers are currently available: + + 0) Information Type (eg. EXIF, XMP, IPTC) + 1) Specific Location (eg. IFD0, XMP-dc) + 2) Category (eg. Author, Time) + 3) Document Number (eg. Main, Doc1, Doc3-2) + 4) Instance Number (eg. Copy1, Copy2, Copy3...) + +Families 0 and 1 are based on the file structure, and are similar except +that family 1 is more specific and sub-divides some groups to give more +detail about the specific location where the information was found. For +example, the EXIF group is split up based on the specific IFD (Image File +Directory), the MakerNotes group is divided into groups for each +manufacturer, and the XMP group is separated based on the XMP namespace +prefix. Note that only common XMP namespaces are listed in the +L, but additional +namespaces may be present in some XMP data. Also note that the 'XMP-xmp...' +group names may appear in the older form 'XMP-xap...' since these names +evolved as the XMP standard was developed. The ICC_Profile group is broken +down to give information about the specific ICC_Profile tag from which +multiple values were extracted. As well, information extracted from the +ICC_Profile header is separated into the ICC-header group. + +Family 2 classifies information based on the logical category to which the +information refers. + +Family 3 gives the document number for tags extracted from embedded +documents, or 'Main' for tags from the main document. (See the +L option for extracting tags from embedded documents.) +Nested sub-documents (if they exist) are indicated by numbers separated with +dashes in the group name, to an arbitrary depth. (eg. 'Doc2-3-1' is the 1st +sub-sub-document of the 3rd sub-document of the 2nd embedded document of the +main file.) + +Family 4 provides a method for differentiating tags when multiple tags exist +with the same name in the same location. The primary instance of a tag (the +tag extracted when the Duplicates option is disabled and no group is +specified) has no family 4 group name, but additional instances have have +family 4 group names of 'Copy1', 'Copy2', 'Copy3', etc. + +See L for complete lists of group names. + +=back + +=head2 GetGroups + +Get list of group names that exist in the specified information. + + @groups = $exifTool->GetGroups($info, 2); + @groups = $exifTool->GetGroups('3:1'); + +=over 4 + +=item Inputs: + +0) ExifTool object reference + +1) [optional] Info hash ref (default is all extracted info) + +2) [optional] Group family number, or string of numbers (default 0) + +=item Return Values: + +List of group names in alphabetical order. If information hash is not +specified, the group names are returned for all extracted information. See +L for an description of family numbers and family number strings. + +=back + +=head2 BuildCompositeTags + +Builds composite tags from required tags. The composite tags are +convenience tags which are derived from the values of other tags. This +routine is called automatically by L and L if the +Composite option is set. + +=over 4 + +=item Inputs: + +0) ExifTool object reference + +=item Return Values: + +(none) + +=item Notes: + +Tag values are calculated in alphabetical order unless a tag Require's or +Desire's another composite tag, in which case the calculation is deferred +until after the other tag is calculated. + +Composite tags may need to read data from the image for their value to be +determined, and for these L must be called while the +image is available. This is only a problem if L is called with +a filename (as opposed to a file reference or scalar reference) since in +this case the file is closed before L returns. Here the +Composite option may be used so that L is called from +within L, before the file is closed. + +=back + +=head2 GetTagName [static] + +Get name of tag from tag key. This is a convenience function that +strips the embedded instance number, if it exists, from the tag key. + +Note: "static" in the heading above indicates that the function does not +require an ExifTool object reference as the first argument. All functions +documented below are also static. + + $tagName = Image::ExifTool::GetTagName($tag); + +=over 4 + +=item Inputs: + +0) Tag key + +=item Return Value: + +Tag name. This is the same as the tag key but has the instance number +removed. + +=back + +=head2 GetShortcuts [static] + +Get a list of shortcut tags. + +=over 4 + +=item Inputs: + +(none) + +=item Return Values: + +List of shortcut tags (as defined in Image::ExifTool::Shortcuts). + +=back + +=head2 GetAllTags [static] + +Get list of all available tag names. + + @tagList = Image::ExifTool::GetAllTags($group); + +=over 4 + +=item Inputs: + +0) [optional] Group name, or string of group names separated by colons + +=item Return Values: + +A list of all available tags in alphabetical order, or all tags in a +specified group or intersection of groups. The group name is case +insensitive, and any group in families 0-2 may be used except for EXIF +family 1 groups (ie. the specific IFD). + +=back + +=head2 GetWritableTags [static] + +Get list of all writable tag names. + + @tagList = Image::ExifTool::GetWritableTags($group); + +=over 4 + +=item Inputs: + +0) [optional] Group name, or string of group names separated by colons + +=item Return Values: + +A list of all writable tags in alphabetical order. These are the tags for +which values may be set through L. If a group name is given, +returns only writable tags in specified group(s). The group name is case +insensitive, and any group in families 0-2 may be used except for EXIF +family 1 groups (ie. the specific IFD). + +=back + +=head2 GetAllGroups [static] + +Get list of all group names in specified family. + + @groupList = Image::ExifTool::GetAllGroups($family); + +=over 4 + +=item Inputs: + +0) Group family number (0-4) + +=item Return Values: + +A list of all groups in the specified family in alphabetical order. + +=back + +Here is a complete list of groups for each of these families: + +=over 4 + +=item Family 0 (Information Type): + +AFCP, AIFF, APE, APP0, APP1, APP11, APP12, APP13, APP14, APP15, APP4, APP5, +APP6, APP8, ASF, Audible, CanonVRD, Composite, DICOM, DNG, DV, DjVu, Ducky, +EXE, EXIF, ExifTool, FLAC, FLIR, File, Flash, FlashPix, Font, FotoStation, +GIF, GIMP, GeoTiff, GoPro, H264, HTML, ICC_Profile, ID3, IPTC, ISO, ITC, +JFIF, JPEG, JSON, Jpeg2000, LNK, Leaf, Lytro, M2TS, MIE, MIFF, MNG, MOI, +MPC, MPEG, MPF, MXF, MakerNotes, Matroska, Meta, Ogg, OpenEXR, Opus, PDF, +PICT, PLIST, PNG, PSP, Palm, PanasonicRaw, PhotoCD, PhotoMechanic, +Photoshop, PostScript, PrintIM, QuickTime, RAF, RIFF, RSRC, RTF, Radiance, +Rawzor, Real, Red, SVG, SigmaRaw, Stim, Theora, Torrent, VCard, Vorbis, WTV, +XML, XMP, ZIP + +=item Family 1 (Specific Location): + +AC3, AFCP, AIFF, APE, ASF, AVI1, Adobe, AdobeCM, AdobeDNG, Apple, Audible, +CIFF, CameraIFD, Canon, CanonCustom, CanonRaw, CanonVRD, Casio, Chapter#, +Composite, DICOM, DJI, DNG, DV, DjVu, DjVu-Meta, Ducky, EPPIM, EXE, EXIF, +ExifIFD, ExifTool, FLAC, FLIR, File, Flash, FlashPix, Font, FotoStation, +FujiFilm, FujiIFD, GE, GIF, GIMP, GPS, GeoTiff, GlobParamIFD, GoPro, +GraphConv, H264, HP, HTC, HTML, HTML-dc, HTML-ncc, HTML-office, HTML-prod, +HTML-vw96, HTTP-equiv, ICC-chrm, ICC-clrt, ICC-header, ICC-meas, ICC-meta, +ICC-view, ICC_Profile, ICC_Profile#, ID3, ID3v1, ID3v1_Enh, ID3v2_2, +ID3v2_3, ID3v2_4, IFD0, IFD1, IPTC, IPTC#, ISO, ITC, InteropIFD, JFIF, JFXX, +JPEG, JPEG-HDR, JSON, JVC, Jpeg2000, KDC_IFD, Kodak, KodakBordersIFD, +KodakEffectsIFD, KodakIFD, KyoceraRaw, LNK, Leaf, LeafSubIFD, Leica, Lytro, +M2TS, MAC, MIE-Audio, MIE-Camera, MIE-Canon, MIE-Doc, MIE-Extender, +MIE-Flash, MIE-GPS, MIE-Geo, MIE-Image, MIE-Lens, MIE-Main, MIE-MakerNotes, +MIE-Meta, MIE-Orient, MIE-Preview, MIE-Thumbnail, MIE-UTM, MIE-Unknown, +MIE-Video, MIFF, MNG, MOBI, MOI, MPC, MPEG, MPF0, MPImage, MS-DOC, MXF, +MacOS, MakerNotes, MakerUnknown, Matroska, MediaJukebox, MetaIFD, Microsoft, +Minolta, MinoltaRaw, Motorola, NITF, Nikon, NikonCapture, NikonCustom, +NikonScan, Nintendo, Ocad, Ogg, Olympus, OpenEXR, Opus, PDF, PICT, PNG, +PNG-pHYs, PSP, Palm, Panasonic, PanasonicRaw, Pentax, PhaseOne, PhotoCD, +PhotoMechanic, Photoshop, PictureInfo, PostScript, PreviewIFD, PrintIM, +ProfileIFD, Qualcomm, QuickTime, RAF, RAF2, RIFF, RMETA, RSRC, RTF, +Radiance, Rawzor, Real, Real-CONT, Real-MDPR, Real-PROP, Real-RA3, Real-RA4, +Real-RA5, Real-RJMD, Reconyx, Red, Ricoh, SPIFF, SR2, SR2DataIFD, SR2SubIFD, +SRF#, SVG, Samsung, Sanyo, Scalado, Sigma, SigmaRaw, Sony, SonyIDC, Stim, +SubIFD, System, Theora, Torrent, Track#, VCalendar, VCard, Version0, Vorbis, +WTV, XML, XMP, XMP-DICOM, XMP-GAudio, XMP-GImage, XMP-GPano, XMP-GSpherical, +XMP-MP, XMP-MP1, XMP-PixelLive, XMP-aas, XMP-acdsee, XMP-album, +XMP-apple-fi, XMP-aux, XMP-cc, XMP-cell, XMP-creatorAtom, XMP-crs, XMP-dc, +XMP-dex, XMP-digiKam, XMP-drone-dji, XMP-dwc, XMP-exif, XMP-exifEX, +XMP-expressionmedia, XMP-extensis, XMP-fpv, XMP-getty, XMP-ics, +XMP-iptcCore, XMP-iptcExt, XMP-lr, XMP-mediapro, XMP-microsoft, +XMP-mwg-coll, XMP-mwg-kw, XMP-mwg-rs, XMP-pdf, XMP-pdfx, XMP-photomech, +XMP-photoshop, XMP-plus, XMP-pmi, XMP-prism, XMP-prl, XMP-prm, XMP-pur, +XMP-rdf, XMP-swf, XMP-tiff, XMP-x, XMP-xmp, XMP-xmpBJ, XMP-xmpDM, XMP-xmpMM, +XMP-xmpNote, XMP-xmpPLUS, XMP-xmpRights, XMP-xmpTPg, ZIP + +=item Family 2 (Category): + +Audio, Author, Camera, Document, ExifTool, Image, Location, Other, Preview, +Printing, Time, Unknown, Video + +=item Family 3 (Document Number): + +Doc#, Main + +=item Family 4 (Instance Number): + +Copy# + +=back + +=head2 GetDeleteGroups [static] + +Get list of all deletable group names. + + @delGroups = Image::ExifTool::GetDeleteGroups(); + +=over 4 + +=item Inputs: + +None. + +=item Return Values: + +A list of deletable group names in alphabetical order. The current list of +deletable group names is: + +AFCP, APP0, APP1, APP10, APP11, APP12, APP13, APP14, APP15, APP2, APP3, +APP4, APP5, APP6, APP7, APP8, APP9, Adobe, Audio, Author, CIFF, Camera, +CanonVRD, Document, Ducky, EXIF, ExifIFD, ExifTool, File, FlashPix, +FotoStation, GPS, GlobParamIFD, ICC_Profile, IFD0, IFD1, IPTC, Image, +InteropIFD, JFIF, Jpeg2000, Location, MIE, MPF, MakerNotes, Meta, MetaIFD, +NikonCapture, Other, PDF, PDF-update, PNG, PNG-pHYs, PhotoMechanic, +Photoshop, Preview, PrintIM, Printing, RMETA, RSRC, SubIFD, Time, Trailer, +Video, XML, XML-*, XMP, XMP-* + +To schedule a group for deletion, call L with a tag name like +'EXIF:*' and an undefined tag value. + +Deleting a family 0 or 1 group will delete the entire corresponding block of +metadata, but deleting a family 2 group (eg. Audio, Author, Camera, etc.) +deletes the individual tags belonging to that category. + +The 'Trailer' group allows all trailers in JPEG and TIFF-format images to be +deleted at once, including unknown trailers. Note that the JPEG "APP" +groups are special, and are used only to delete application segments which +are not associated with another deletable group. For example, deleting +'APP14:*' will delete other APP14 segments, but not the APP14 "Adobe" +segment. + +=back + +=head2 GetFileType [static] + +Get type of file given file name. + + my $type = Image::ExifTool::GetFileType($filename); + my $desc = Image::ExifTool::GetFileType($filename, 1); + +=over 4 + +=item Inputs: + +0) [optional] File name (or just an extension) + +1) [optional] Flag to return a description instead of a type. Default is +undef. Set to 0 to also return types of recognized but unsupported files +(otherwise the return value for unsupported files is undef), or 1 to return +descriptions. + +=item Return Value: + +A string, based on the file extension, which indicates the basic format of +the file. Note that some files may be based on other formats (like many RAW +image formats are based on TIFF). In list context, may return more than one +file type if the file may be based on different formats. Returns undef if +files with this extension are not yet supported by ExifTool. Returns a list +of extensions for all supported file types if no input extension is +specified (or all recognized file types if the description flag is set to +0). Returns a more detailed description of the specific file format when the +description flag is set. + +=back + +=head2 CanWrite [static] + +Can the specified file be written? + + my $writable = Image::ExifTool::CanWrite($filename); + +=over 4 + +=item Inputs: + +0) File name or extension + +=item Return Value: + +True if ExifTool supports writing files of this type (based on the file +extension). + +=back + +=head2 CanCreate [static] + +Can the specified file be created? + + my $creatable = Image::ExifTool::CanCreate($filename); + +=over 4 + +=item Inputs: + +0) File name or extension + +=item Return Value: + +True if ExifTool can create files with this extension from scratch. +Currently, this can only be done with XMP, MIE, ICC, VRD, DR4, EXV and EXIF +files. + +=back + +=head2 AddUserDefinedTags [static] + +Add user-defined tags to an existing tag table at run time. This differs +from the usual technique of creating user-defined tags via the +%Image::ExifTool::UserDefined hash (see the ExifTool_config file in the +Image::ExifTool distribution) because it allows tags to be added after a tag +table has been initialized. + + use Image::ExifTool ':Public'; + my %tags = ( + TestTagID1 => { Name => 'TestTagName1' }, + TestTagID2 => { Name => 'TestTagName2' }, + ); + my $num = AddUserDefinedTags('Image::ExifTool::PDF::Info', %tags); + +=over 4 + +=item Inputs: + +0) Destination tag table name + +1-N) Pairs of tag ID / tag information hash references for the new tags + +=item Return Value: + +The number of tags added. + +=item Notes + +Pre-existing tags with the same ID will be replaced in the destination +table. See lib/Image/ExifTool/README in the full distribution for full +details on the elements of the tag information hash. + +=back + +=head1 CHARACTER ENCODINGS + +Certain meta information formats allow coded character sets other than plain +ASCII. When reading, most known encodings are converted to the external +character set according to the L option, or to UTF-8 by default. +When writing, the inverse conversions are performed. Alternatively, special +characters may be converted to/from HTML character entities with the +L HTML option. + +A distinction is made between the external character set visible via the +ExifTool API, and the internal character used to store text in the metadata +of a file. These character sets may be specified separately as follows: + +=over 4 + +=item External Character Sets: + +The encoding for tag values passed to/from ExifTool API functions is set via +the L option, which is 'UTF8' by default. + +The encoding of file names is specified via the L option. +By default, L is not defined, and file names passed to +ExifTool are used directly in calls to the system i/o routines (which expect +UTF-8 strings on Mac/Linux, but default to the system code page on Windows). +In this mode on Windows a warning is issued if a file name contains special +characters, but this warning may be avoided by setting L +to an empty string. Setting L to any other value causes +file names to be converted from the specified encoding to one appropriate +for the system. In Windows this also has the effect of activating Unicode +filename support via the special Windows wide-character i/o routines if +Win32API::File is available. + +=item Internal Character Sets: + +The encodings used to store strings in the various metadata formats. These +encodings may be changed for certain types of metadata via the +L, L, L, L, +L and L options. + +=back + +Values are returned as byte strings of encoded characters. Perl wide +characters are not used. By default, most returned strings are encoded in +UTF-8. For these, Encode::decode_utf8() may be used to convert to a +sequence of logical Perl characters. Note that some settings of the +PERL_UNICODE environment variable may be incompatible with ExifTool's +character handling. + +More specific details are given below about how character coding is handled +for EXIF, IPTC, XMP, PNG, ID3, PDF, Photoshop, QuickTime, AIFF, MIE and +Vorbis information: + +=head2 EXIF + +Most textual information in EXIF is stored in ASCII format (called "string" +in the L). By +default ExifTool does not convert these strings. However, it is not +uncommon for applications to write UTF-8 or other encodings where ASCII is +expected. To deal with these, ExifTool allows the internal EXIF string +encoding to be specified with L, which causes EXIF string +values to be converted from the specified character set when reading, and +stored with this character set when writing. (The MWG recommends using +UTF-8 encoding for EXIF strings, and in keeping with this the +L module sets the default internal EXIF string +encoding to UTF-8, but note that this will have no effect unless the +external encoding is also set to something other than the default of UTF-8.) + +A few EXIF tags (UserComment, GPSProcessingMethod and GPSAreaInformation) +support a designated internal text encoding, with values stored as ASCII, +Unicode (UCS-2) or JIS. When reading these tags, ExifTool converts Unicode +and JIS to the external character set specified by the L +option, or to UTF-8 by default. ASCII text is not converted. When writing, +text is stored as ASCII unless the string contains special characters, in +which case it is converted from the external character set (UTF-8 by +default), and stored as Unicode. ExifTool writes Unicode in native EXIF byte +ordering by default, but the byte order may be specified by setting the +ExifUnicodeByteOrder tag (see the +L). + +The EXIF "XP" tags (XPTitle, XPComment, etc) are always stored as +little-endian Unicode (UCS-2), and are read and written using the specified +character set. + +=head2 IPTC + +The value of the IPTC:CodedCharacterSet tag determines how the internal IPTC +string values are interpreted. If CodedCharacterSet exists and has a value +of 'UTF8' (or 'ESC % G') then string values are assumed to be stored as +UTF-8, otherwise Windows Latin1 (cp1252, 'Latin') coding is assumed by +default, but this can be changed with the L option. When +reading, these strings are converted to the character set specified by the +L option. When writing, the inverse conversions are performed. +No conversion is done if the internal (IPTC) and external (ExifTool) +character sets are the same. Note that ISO 2022 character set shifting is +not supported. Instead, a warning is issued and the string is not converted +if an ISO 2022 shift code is encountered. See L +for the official IPTC specification. + +ExifTool may be used to convert IPTC values to a different internal +encoding. To do this, all IPTC tags must be rewritten along with the +desired value of CodedCharacterSet. For example, the following command +changes the internal IPTC encoding to UTF-8 (from Windows Latin1 unless +CodedCharacterSet was already 'UTF8'): + + exiftool -tagsfromfile @ -iptc:all -codedcharacterset=utf8 a.jpg + +or from Windows Latin2 (cp1250) to UTF-8: + + exiftool -tagsfromfile @ -iptc:all -codedcharacterset=utf8 \ + -charset iptc=latin2 a.jpg + +and this command changes it back from UTF-8 to Windows Latin1 (cp1252): + + exiftool -tagsfromfile @ -iptc:all -codedcharacterset= a.jpg + +or to Windows Latin2: + + exiftool -tagsfromfile @ -iptc:all -codedcharacterset= \ + -charset iptc=latin2 a.jpg + +Unless CodedCharacterSet is 'UTF8', applications have no reliable way to +determine the IPTC character encoding. For this reason, it is recommended +that CodedCharacterSet be set to 'UTF8' when creating new IPTC. + +(Note: Here, "IPTC" Refers to the older IPTC IIM format. The more recent +IPTC Core and Extension specifications actually use the XMP format.) + +=head2 XMP + +Exiftool reads XMP encoded as UTF-8, UTF-16 or UTF-32, and converts them all +to UTF-8 internally. Also, all XML character entity references and numeric +character references are converted. When writing, ExifTool always encodes +XMP as UTF-8, converting the following 5 characters to XML character +references: E E E E<39> E. By default no further +conversion is performed, however if the L option is other than +'UTF8' then text is converted to/from a specified character set when +reading/writing. + +=head2 PNG + +L are +stored as tEXt, zTXt and iTXt chunks in PNG images. The tEXt and zTXt +chunks use ISO 8859-1 encoding, while iTXt uses UTF-8. When reading, +ExifTool converts all PNG textual data to the character set specified by the +L option. When writing, ExifTool generates a tEXt chunk (or zTXt +with the L option) if the text doesn't contain special characters +or if Latin encoding is specified; otherwise an iTXt chunk is used and the +text is converted from the specified character set and stored as UTF-8. + +=head2 JPEG Comment + +The encoding for the JPEG Comment (COM segment) is not specified, so +ExifTool reads/writes this text without conversion. + +=head2 ID3 + +The ID3v1 specification officially supports only ISO 8859-1 encoding (a +subset of Windows Latin1), although some applications may incorrectly use +other character sets. By default ExifTool converts ID3v1 text from Latin to +the character set specified by the L option. However, the +internal ID3v1 charset may be specified with the L option. The +encoding for ID3v2 information is stored in the file, so ExifTool converts +ID3v2 text from this encoding to the character set specified by the +L option. ExifTool does not currently write ID3 information. + +=head2 PDF + +PDF text strings are stored in either PDFDocEncoding (similar to Windows +Latin1) or Unicode (UCS-2). When reading, ExifTool converts to the +character set specified by the L option. When writing, ExifTool +encodes input text from the specified character set as Unicode only if the +string contains special characters, otherwise PDFDocEncoding is used. + +=head2 Photoshop + +Some Photoshop resource names are stored as Pascal strings with unknown +encoding. By default, ExifTool assumes MacRoman encoding and converts this +to UTF-8, but the internal and external character sets may be specified with +the L and L options respectively. + +=head2 QuickTime + +QuickTime text strings may be stored in a variety of poorly document +formats. ExifTool does its best to decode these according to the L +option setting. For some QuickTime strings, ExifTool assumes a default +encoding of MacRoman, but this may be changed with the L +option. + +=head2 AIFF + +AIFF strings are assumed to be stored in MacRoman, and are converted +according to the L option when reading. + +=head2 RIFF + +The internal encoding of RIFF strings (eg. in AVI and WAV files) is assumed +to be Latin unless otherwise specified by the RIFF CSET chunk or the +L option. + +=head2 MIE + +MIE strings are stored as either UTF-8 or ISO 8859-1. When reading, UTF-8 +strings are converted according to the L option, and ISO 8859-1 +strings are never converted. When writing, input strings are converted from +the specified character set to UTF-8. The resulting strings are stored as +UTF-8 if they contain multi-byte UTF-8 character sequences, otherwise they +are stored as ISO 8859-1. + +=head2 Vorbis + +Vorbis comments are stored as UTF-8, and are converted to the character set +specified by the L option. + +=head1 AUTHOR + +Copyright 2003-2019, Phil Harvey + +This library is free software; you can redistribute it and/or modify it +under the same terms as Perl itself. + +=head1 ACKNOWLEDGEMENTS + +Many people have helped in the development of ExifTool through their bug +reports, comments and suggestions, and/or additions to the code. See the +ACKNOWLEDGEMENTS in the individual Image::ExifTool modules and in +html/index.html of the Image::ExifTool distribution package for a list of +people who have contributed to this project. + +=head1 SEE ALSO + +L, +L, +L, +L, +L, +L + +=cut + +# end diff --git a/lib/Image/ExifTool/AES.pm b/lib/Image/ExifTool/AES.pm new file mode 100644 index 0000000..50050f8 --- /dev/null +++ b/lib/Image/ExifTool/AES.pm @@ -0,0 +1,501 @@ +#------------------------------------------------------------------------------ +# File: AES.pm +# +# Description: AES encryption with cipher-block chaining +# +# Revisions: 2010/10/14 - P. Harvey Created +# +# References: 1) http://www.hoozi.com/Articles/AESEncryption.htm +# 2) http://www.csrc.nist.gov/publications/fips/fips197/fips-197.pdf +# 3) http://www.faqs.org/rfcs/rfc3602.html +#------------------------------------------------------------------------------ + +package Image::ExifTool::AES; + +use strict; +use vars qw($VERSION @ISA @EXPORT_OK); +require Exporter; + +$VERSION = '1.01'; +@ISA = qw(Exporter); +@EXPORT_OK = qw(Crypt); + +my $seeded; # flag set if we already seeded random number generator +my $nr; # number of rounds in AES cipher +my @cbc; # cipher-block chaining bytes + +# arrays (all unsigned character) to hold intermediate results during encryption +my @state = ([],[],[],[]); # the 2-dimensional state array +my @RoundKey; # round keys + +my @sbox = ( + 0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5, 0x30, 0x01, 0x67, 0x2b, 0xfe, 0xd7, 0xab, 0x76, + 0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0, 0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0, + 0xb7, 0xfd, 0x93, 0x26, 0x36, 0x3f, 0xf7, 0xcc, 0x34, 0xa5, 0xe5, 0xf1, 0x71, 0xd8, 0x31, 0x15, + 0x04, 0xc7, 0x23, 0xc3, 0x18, 0x96, 0x05, 0x9a, 0x07, 0x12, 0x80, 0xe2, 0xeb, 0x27, 0xb2, 0x75, + 0x09, 0x83, 0x2c, 0x1a, 0x1b, 0x6e, 0x5a, 0xa0, 0x52, 0x3b, 0xd6, 0xb3, 0x29, 0xe3, 0x2f, 0x84, + 0x53, 0xd1, 0x00, 0xed, 0x20, 0xfc, 0xb1, 0x5b, 0x6a, 0xcb, 0xbe, 0x39, 0x4a, 0x4c, 0x58, 0xcf, + 0xd0, 0xef, 0xaa, 0xfb, 0x43, 0x4d, 0x33, 0x85, 0x45, 0xf9, 0x02, 0x7f, 0x50, 0x3c, 0x9f, 0xa8, + 0x51, 0xa3, 0x40, 0x8f, 0x92, 0x9d, 0x38, 0xf5, 0xbc, 0xb6, 0xda, 0x21, 0x10, 0xff, 0xf3, 0xd2, + 0xcd, 0x0c, 0x13, 0xec, 0x5f, 0x97, 0x44, 0x17, 0xc4, 0xa7, 0x7e, 0x3d, 0x64, 0x5d, 0x19, 0x73, + 0x60, 0x81, 0x4f, 0xdc, 0x22, 0x2a, 0x90, 0x88, 0x46, 0xee, 0xb8, 0x14, 0xde, 0x5e, 0x0b, 0xdb, + 0xe0, 0x32, 0x3a, 0x0a, 0x49, 0x06, 0x24, 0x5c, 0xc2, 0xd3, 0xac, 0x62, 0x91, 0x95, 0xe4, 0x79, + 0xe7, 0xc8, 0x37, 0x6d, 0x8d, 0xd5, 0x4e, 0xa9, 0x6c, 0x56, 0xf4, 0xea, 0x65, 0x7a, 0xae, 0x08, + 0xba, 0x78, 0x25, 0x2e, 0x1c, 0xa6, 0xb4, 0xc6, 0xe8, 0xdd, 0x74, 0x1f, 0x4b, 0xbd, 0x8b, 0x8a, + 0x70, 0x3e, 0xb5, 0x66, 0x48, 0x03, 0xf6, 0x0e, 0x61, 0x35, 0x57, 0xb9, 0x86, 0xc1, 0x1d, 0x9e, + 0xe1, 0xf8, 0x98, 0x11, 0x69, 0xd9, 0x8e, 0x94, 0x9b, 0x1e, 0x87, 0xe9, 0xce, 0x55, 0x28, 0xdf, + 0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68, 0x41, 0x99, 0x2d, 0x0f, 0xb0, 0x54, 0xbb, 0x16, +); + +# reverse sbox +my @rsbox = ( + 0x52, 0x09, 0x6a, 0xd5, 0x30, 0x36, 0xa5, 0x38, 0xbf, 0x40, 0xa3, 0x9e, 0x81, 0xf3, 0xd7, 0xfb, + 0x7c, 0xe3, 0x39, 0x82, 0x9b, 0x2f, 0xff, 0x87, 0x34, 0x8e, 0x43, 0x44, 0xc4, 0xde, 0xe9, 0xcb, + 0x54, 0x7b, 0x94, 0x32, 0xa6, 0xc2, 0x23, 0x3d, 0xee, 0x4c, 0x95, 0x0b, 0x42, 0xfa, 0xc3, 0x4e, + 0x08, 0x2e, 0xa1, 0x66, 0x28, 0xd9, 0x24, 0xb2, 0x76, 0x5b, 0xa2, 0x49, 0x6d, 0x8b, 0xd1, 0x25, + 0x72, 0xf8, 0xf6, 0x64, 0x86, 0x68, 0x98, 0x16, 0xd4, 0xa4, 0x5c, 0xcc, 0x5d, 0x65, 0xb6, 0x92, + 0x6c, 0x70, 0x48, 0x50, 0xfd, 0xed, 0xb9, 0xda, 0x5e, 0x15, 0x46, 0x57, 0xa7, 0x8d, 0x9d, 0x84, + 0x90, 0xd8, 0xab, 0x00, 0x8c, 0xbc, 0xd3, 0x0a, 0xf7, 0xe4, 0x58, 0x05, 0xb8, 0xb3, 0x45, 0x06, + 0xd0, 0x2c, 0x1e, 0x8f, 0xca, 0x3f, 0x0f, 0x02, 0xc1, 0xaf, 0xbd, 0x03, 0x01, 0x13, 0x8a, 0x6b, + 0x3a, 0x91, 0x11, 0x41, 0x4f, 0x67, 0xdc, 0xea, 0x97, 0xf2, 0xcf, 0xce, 0xf0, 0xb4, 0xe6, 0x73, + 0x96, 0xac, 0x74, 0x22, 0xe7, 0xad, 0x35, 0x85, 0xe2, 0xf9, 0x37, 0xe8, 0x1c, 0x75, 0xdf, 0x6e, + 0x47, 0xf1, 0x1a, 0x71, 0x1d, 0x29, 0xc5, 0x89, 0x6f, 0xb7, 0x62, 0x0e, 0xaa, 0x18, 0xbe, 0x1b, + 0xfc, 0x56, 0x3e, 0x4b, 0xc6, 0xd2, 0x79, 0x20, 0x9a, 0xdb, 0xc0, 0xfe, 0x78, 0xcd, 0x5a, 0xf4, + 0x1f, 0xdd, 0xa8, 0x33, 0x88, 0x07, 0xc7, 0x31, 0xb1, 0x12, 0x10, 0x59, 0x27, 0x80, 0xec, 0x5f, + 0x60, 0x51, 0x7f, 0xa9, 0x19, 0xb5, 0x4a, 0x0d, 0x2d, 0xe5, 0x7a, 0x9f, 0x93, 0xc9, 0x9c, 0xef, + 0xa0, 0xe0, 0x3b, 0x4d, 0xae, 0x2a, 0xf5, 0xb0, 0xc8, 0xeb, 0xbb, 0x3c, 0x83, 0x53, 0x99, 0x61, + 0x17, 0x2b, 0x04, 0x7e, 0xba, 0x77, 0xd6, 0x26, 0xe1, 0x69, 0x14, 0x63, 0x55, 0x21, 0x0c, 0x7d, +); + +# the round constant word array, $rcon[i], contains the values given by +# x to the power (i-1) being powers of x (x is denoted as {02}) in the field GF(2^8) +# Note that i starts at 1, not 0). +my @rcon = ( + 0x8d, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36, 0x6c, 0xd8, 0xab, 0x4d, 0x9a, + 0x2f, 0x5e, 0xbc, 0x63, 0xc6, 0x97, 0x35, 0x6a, 0xd4, 0xb3, 0x7d, 0xfa, 0xef, 0xc5, 0x91, 0x39, + 0x72, 0xe4, 0xd3, 0xbd, 0x61, 0xc2, 0x9f, 0x25, 0x4a, 0x94, 0x33, 0x66, 0xcc, 0x83, 0x1d, 0x3a, + 0x74, 0xe8, 0xcb, 0x8d, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36, 0x6c, 0xd8, + 0xab, 0x4d, 0x9a, 0x2f, 0x5e, 0xbc, 0x63, 0xc6, 0x97, 0x35, 0x6a, 0xd4, 0xb3, 0x7d, 0xfa, 0xef, + 0xc5, 0x91, 0x39, 0x72, 0xe4, 0xd3, 0xbd, 0x61, 0xc2, 0x9f, 0x25, 0x4a, 0x94, 0x33, 0x66, 0xcc, + 0x83, 0x1d, 0x3a, 0x74, 0xe8, 0xcb, 0x8d, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, + 0x36, 0x6c, 0xd8, 0xab, 0x4d, 0x9a, 0x2f, 0x5e, 0xbc, 0x63, 0xc6, 0x97, 0x35, 0x6a, 0xd4, 0xb3, + 0x7d, 0xfa, 0xef, 0xc5, 0x91, 0x39, 0x72, 0xe4, 0xd3, 0xbd, 0x61, 0xc2, 0x9f, 0x25, 0x4a, 0x94, + 0x33, 0x66, 0xcc, 0x83, 0x1d, 0x3a, 0x74, 0xe8, 0xcb, 0x8d, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, + 0x40, 0x80, 0x1b, 0x36, 0x6c, 0xd8, 0xab, 0x4d, 0x9a, 0x2f, 0x5e, 0xbc, 0x63, 0xc6, 0x97, 0x35, + 0x6a, 0xd4, 0xb3, 0x7d, 0xfa, 0xef, 0xc5, 0x91, 0x39, 0x72, 0xe4, 0xd3, 0xbd, 0x61, 0xc2, 0x9f, + 0x25, 0x4a, 0x94, 0x33, 0x66, 0xcc, 0x83, 0x1d, 0x3a, 0x74, 0xe8, 0xcb, 0x8d, 0x01, 0x02, 0x04, + 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36, 0x6c, 0xd8, 0xab, 0x4d, 0x9a, 0x2f, 0x5e, 0xbc, 0x63, + 0xc6, 0x97, 0x35, 0x6a, 0xd4, 0xb3, 0x7d, 0xfa, 0xef, 0xc5, 0x91, 0x39, 0x72, 0xe4, 0xd3, 0xbd, + 0x61, 0xc2, 0x9f, 0x25, 0x4a, 0x94, 0x33, 0x66, 0xcc, 0x83, 0x1d, 0x3a, 0x74, 0xe8, 0xcb, +); + +#------------------------------------------------------------------------------ +# This function produces 4*($nr+1) round keys. +# The round keys are used in each round to encrypt the states. +# Inputs: 0) key string (must be 16, 24 or 32 bytes long) +sub KeyExpansion($) +{ + my $key = shift; + my @key = unpack 'C*', $key; # convert the key into a byte array + my $nk = int(length($key) / 4); # number of 32-bit words in the key + $nr = $nk + 6; # number of rounds + + # temporary variables (all unsigned characters) + my ($i,@temp); + + # The first round key is the key itself. + for ($i=0; $i<$nk; ++$i) { + @RoundKey[$i*4..$i*4+3] = @key[$i*4..$i*4+3]; + } + # All other round keys are found from the previous round keys. + while ($i < (4 * ($nr+1))) { + + @temp[0..3] = @RoundKey[($i-1)*4..($i-1)*4+3]; + + if ($i % $nk == 0) { + # rotate the 4 bytes in a word to the left once + # [a0,a1,a2,a3] becomes [a1,a2,a3,a0] + @temp[0..3] = @temp[1,2,3,0]; + + # take a four-byte input word and apply the S-box + # to each of the four bytes to produce an output word. + @temp[0..3] = @sbox[@temp[0..3]]; + + $temp[0] = $temp[0] ^ $rcon[$i/$nk]; + + } elsif ($nk > 6 && $i % $nk == 4) { + + @temp[0..3] = @sbox[@temp[0..3]]; + } + $RoundKey[$i*4+0] = $RoundKey[($i-$nk)*4+0] ^ $temp[0]; + $RoundKey[$i*4+1] = $RoundKey[($i-$nk)*4+1] ^ $temp[1]; + $RoundKey[$i*4+2] = $RoundKey[($i-$nk)*4+2] ^ $temp[2]; + $RoundKey[$i*4+3] = $RoundKey[($i-$nk)*4+3] ^ $temp[3]; + ++$i; + } +} + +#------------------------------------------------------------------------------ +# This function adds the round key to state. +# The round key is added to the state by an XOR function. +sub AddRoundKey($) +{ + my $round = shift; + my ($i,$j); + for ($i=0; $i<4; ++$i) { + my $k = $round*16 + $i*4; + for ($j=0; $j<4; ++$j) { + $state[$j][$i] ^= $RoundKey[$k + $j]; + } + } +} + +#------------------------------------------------------------------------------ +# Substitute the values in the state matrix with values in an S-box +sub SubBytes() +{ + my $i; + for ($i=0; $i<4; ++$i) { + @{$state[$i]}[0..3] = @sbox[@{$state[$i]}[0..3]]; + } +} + +sub InvSubBytes() +{ + my $i; + for ($i=0; $i<4; ++$i) { + @{$state[$i]}[0..3] = @rsbox[@{$state[$i]}[0..3]]; + } +} + +#------------------------------------------------------------------------------ +# Shift the rows in the state to the left. +# Each row is shifted with different offset. +# Offset = Row number. So the first row is not shifted. +sub ShiftRows() +{ + # rotate first row 1 columns to left + @{$state[1]}[0,1,2,3] = @{$state[1]}[1,2,3,0]; + + # rotate second row 2 columns to left + @{$state[2]}[0,1,2,3] = @{$state[2]}[2,3,0,1]; + + # rotate third row 3 columns to left + @{$state[3]}[0,1,2,3] = @{$state[3]}[3,0,1,2]; +} + +sub InvShiftRows() +{ + # rotate first row 1 columns to right + @{$state[1]}[0,1,2,3] = @{$state[1]}[3,0,1,2]; + + # rotate second row 2 columns to right + @{$state[2]}[0,1,2,3] = @{$state[2]}[2,3,0,1]; + + # rotate third row 3 columns to right + @{$state[3]}[0,1,2,3] = @{$state[3]}[1,2,3,0]; +} + +#------------------------------------------------------------------------------ +# Find the product of {02} and the argument to xtime modulo 0x1b +# Note: returns an integer which may need to be trimmed to 8 bits +sub xtime($) +{ + return ($_[0]<<1) ^ ((($_[0]>>7) & 1) * 0x1b); +} + +#------------------------------------------------------------------------------ +# Multiply numbers in the field GF(2^8) +sub Mult($$) +{ + my ($x, $y) = @_; + return (($y & 1) * $x) ^ + (($y>>1 & 1) * xtime($x)) ^ + (($y>>2 & 1) * xtime(xtime($x))) ^ + (($y>>3 & 1) * xtime(xtime(xtime($x)))) ^ + (($y>>4 & 1) * xtime(xtime(xtime(xtime($x))))); +} + +#------------------------------------------------------------------------------ +# Mix the columns of the state matrix +sub MixColumns() +{ + my ($i,$t0,$t1,$t2); + for ($i=0; $i<4; ++$i) { + $t0 = $state[0][$i]; + $t2 = $state[0][$i] ^ $state[1][$i] ^ $state[2][$i] ^ $state[3][$i]; + $t1 = $state[0][$i] ^ $state[1][$i] ; $t1 = xtime($t1) & 0xff; $state[0][$i] ^= $t1 ^ $t2 ; + $t1 = $state[1][$i] ^ $state[2][$i] ; $t1 = xtime($t1) & 0xff; $state[1][$i] ^= $t1 ^ $t2 ; + $t1 = $state[2][$i] ^ $state[3][$i] ; $t1 = xtime($t1) & 0xff; $state[2][$i] ^= $t1 ^ $t2 ; + $t1 = $state[3][$i] ^ $t0 ; $t1 = xtime($t1) & 0xff; $state[3][$i] ^= $t1 ^ $t2 ; + } +} + +sub InvMixColumns() +{ + my $i; + for ($i=0; $i<4; ++$i) { + my $a = $state[0][$i]; + my $b = $state[1][$i]; + my $c = $state[2][$i]; + my $d = $state[3][$i]; + $state[0][$i] = (Mult($a,0x0e) ^ Mult($b,0x0b) ^ Mult($c,0x0d) ^ Mult($d,0x09)) & 0xff; + $state[1][$i] = (Mult($a,0x09) ^ Mult($b,0x0e) ^ Mult($c,0x0b) ^ Mult($d,0x0d)) & 0xff; + $state[2][$i] = (Mult($a,0x0d) ^ Mult($b,0x09) ^ Mult($c,0x0e) ^ Mult($d,0x0b)) & 0xff; + $state[3][$i] = (Mult($a,0x0b) ^ Mult($b,0x0d) ^ Mult($c,0x09) ^ Mult($d,0x0e)) & 0xff; + } +} + +#------------------------------------------------------------------------------ +# Encrypt (Cipher) or decrypt (InvCipher) a block of data with CBC +# Inputs: 0) string to cipher (must be 16 bytes long) +# Returns: cipher'd string +sub Cipher($) +{ + my @in = unpack 'C*', $_[0]; # unpack input plaintext + my ($i, $j, $round); + + # copy the input PlainText to state array and apply the CBC + for ($i=0; $i<4; ++$i) { + for ($j=0; $j<4; ++$j) { + my $k = $i*4 + $j; + $state[$j][$i] = $in[$k] ^ $cbc[$k]; + } + } + + # add the First round key to the state before starting the rounds + AddRoundKey(0); + + # there will be $nr rounds; the first $nr-1 rounds are identical + for ($round=1; ; ++$round) { + SubBytes(); + ShiftRows(); + if ($round < $nr) { + MixColumns(); + AddRoundKey($round); + } else { + # MixColumns() is not used in the last round + AddRoundKey($nr); + last; + } + } + + # the encryption process is over + # copy the state array to output array (and save for CBC) + for ($i=0; $i<4; ++$i) { + for ($j=0; $j<4; ++$j) { + $cbc[$i*4+$j] = $state[$j][$i]; + } + } + return pack 'C*', @cbc; # return packed ciphertext +} + +sub InvCipher($) +{ + my @in = unpack 'C*', $_[0]; # unpack input ciphertext + my (@out, $i, $j, $round); + + # copy the input CipherText to state array + for ($i=0; $i<4; ++$i) { + for ($j=0; $j<4; ++$j) { + $state[$j][$i] = $in[$i*4 + $j]; + } + } + + # add the First round key to the state before starting the rounds + AddRoundKey($nr); + + # there will be $nr rounds; the first $nr-1 rounds are identical + for ($round=$nr-1; ; --$round) { + InvShiftRows(); + InvSubBytes(); + AddRoundKey($round); + # InvMixColumns() is not used in the last round + last if $round <= 0; + InvMixColumns(); + } + + # copy the state array to output array and reverse the CBC + for ($i=0; $i<4; ++$i) { + for ($j=0; $j<4; ++$j) { + my $k = $i*4 + $j; + $out[$k] = $state[$j][$i] ^ $cbc[$k]; + } + } + @cbc = @in; # update CBC for next block + return pack 'C*', @out; # return packed plaintext +} + +#------------------------------------------------------------------------------ +# Encrypt/Decrypt using AES-CBC algorithm (with fixed 16-byte blocks) +# Inputs: 0) data reference (with leading 16-byte initialization vector when decrypting) +# 1) encryption key (16, 24 or 32 bytes for AES-128, AES-192 or AES-256) +# 2) encrypt flag (false for decryption, true with length 16 bytes to +# encrypt using this as the CBC IV, or true with other length to +# encrypt with a randomly-generated IV) +# 3) flag to disable padding +# Returns: error string, or undef on success +# Notes: encrypts/decrypts data in place (encrypted data returned with leading IV) +sub Crypt($$;$$) +{ + my ($dataPt, $key, $encrypt, $noPad) = @_; + + # validate key length + my $keyLen = length $key; + unless ($keyLen == 16 or $keyLen == 24 or $keyLen == 32) { + return "Invalid AES key length ($keyLen)"; + } + my $partLen = length($$dataPt) % 16; + my ($pos, $i); + if ($encrypt) { + if (length($encrypt) == 16) { + @cbc = unpack 'C*', $encrypt; + } else { + # generate a random 16-byte CBC initialization vector + unless ($seeded) { + srand(time() & ($$ + ($$<<15))); + $seeded = 1; + } + for ($i=0; $i<16; ++$i) { + $cbc[$i] = int(rand(256)); + } + $encrypt = pack 'C*', @cbc; + } + $$dataPt = $encrypt . $$dataPt; # add IV to the start of the data + # add required padding so we can recover the + # original string length after decryption + # (padding bytes have value set to padding length) + my $padLen = 16 - $partLen; + $$dataPt .= (chr($padLen)) x $padLen unless $padLen == 16 and $noPad; + $pos = 16; # start encrypting at byte 16 (after the IV) + } elsif ($partLen) { + return 'Invalid AES ciphertext length'; + } elsif (length $$dataPt >= 32) { + # take the CBC initialization vector from the start of the data + @cbc = unpack 'C16', $$dataPt; + $$dataPt = substr($$dataPt, 16); + $pos = 0; # start decrypting from byte 0 (now that IV is removed) + } else { + $$dataPt = ''; # empty text + return undef; + } + # the KeyExpansion routine must be called before encryption + KeyExpansion($key); + + # loop through the data and convert in blocks + my $dataLen = length $$dataPt; + my $last = $dataLen - 16; + my $func = $encrypt ? \&Cipher : \&InvCipher; + while ($pos <= $last) { + # cipher this block + substr($$dataPt, $pos, 16) = &$func(substr($$dataPt, $pos, 16)); + $pos += 16; + } + unless ($encrypt or $noPad) { + # remove padding if necessary (padding byte value gives length of padding) + my $padLen = ord(substr($$dataPt, -1, 1)); + return 'AES decryption error (invalid pad byte)' if $padLen > 16; + $$dataPt = substr($$dataPt, 0, $dataLen - $padLen); + } + return undef; +} + +1; # end + + +__END__ + +=head1 NAME + +Image::ExifTool::AES - AES encryption with cipher-block chaining + +=head1 SYNOPSIS + + use Image::ExifTool::AES qw(Crypt); + + $err = Crypt(\$plaintext, $key, 1); # encryption + + $err = Crypt(\$ciphertext, $key); # decryption + +=head1 DESCRIPTION + +This module contains an implementation of the AES encryption/decryption +algorithms with cipher-block chaining (CBC) and RFC 2898 PKCS #5 padding. +This is the AESV2 and AESV3 encryption mode used in PDF documents. + +=head1 EXPORTS + +Exports nothing by default, but L may be exported. + +=head1 METHODS + +=head2 Crypt + +Implement AES encryption/decryption with cipher-block chaining. + +=over 4 + +=item Inputs: + +0) Scalar reference for data to encrypt/decrypt. + +1) Encryption key string (must have length 16, 24 or 32). + +2) [optional] Encrypt flag (false to decrypt). + +3) [optional] Flag to avoid removing padding after decrypting, or to avoid +adding 16 bytes of padding before encrypting when data length is already a +multiple of 16 bytes. + +=item Returns: + +On success, the return value is undefined and the data is encrypted or +decrypted as specified. Otherwise returns an error string and the data is +left in an indeterminate state. + +=item Notes: + +The length of the encryption key dictates the AES mode, with lengths of 16, +24 and 32 bytes resulting in AES-128, AES-192 and AES-256. + +When encrypting, the input data may be any length and will be padded to an +even 16-byte block size using the specified padding technique. If the +encrypt flag has length 16, it is used as the initialization vector for +the cipher-block chaining, otherwise a random IV is generated. Upon +successful return the data will be encrypted, with the first 16 bytes of +the data being the CBC IV. + +When decrypting, the input data begins with the 16-byte CBC initialization +vector. + +=back + +=head1 BUGS + +This code is blindingly slow. But in truth, slowing down processing is the +main purpose of encryption, so this really can't be considered a bug. + +=head1 AUTHOR + +Copyright 2003-2019, Phil Harvey (phil at owl.phy.queensu.ca) + +This library is free software; you can redistribute it and/or modify it +under the same terms as Perl itself. + +=head1 REFERENCES + +=over 4 + +=item L + +=item L + +=item L + +=back + +=head1 SEE ALSO + +L + +=cut diff --git a/lib/Image/ExifTool/AFCP.pm b/lib/Image/ExifTool/AFCP.pm new file mode 100644 index 0000000..9c961c2 --- /dev/null +++ b/lib/Image/ExifTool/AFCP.pm @@ -0,0 +1,281 @@ +#------------------------------------------------------------------------------ +# File: AFCP.pm +# +# Description: Read/write AFCP trailer +# +# Revisions: 12/26/2005 - P. Harvey Created +# +# References: 1) http://web.archive.org/web/20080828211305/http://www.tocarte.com/media/axs_afcp_spec.pdf +#------------------------------------------------------------------------------ + +package Image::ExifTool::AFCP; + +use strict; +use vars qw($VERSION); +use Image::ExifTool qw(:DataAccess :Utils); + +$VERSION = '1.08'; + +sub ProcessAFCP($$); + +%Image::ExifTool::AFCP::Main = ( + PROCESS_PROC => \&ProcessAFCP, + NOTES => q{ +AFCP stands for AXS File Concatenation Protocol, and is a poorly designed +protocol for appending information to the end of files. This can be used as +an auxiliary technique to store IPTC information in images, but is +incompatible with some file formats. + +ExifTool will read and write (but not create) AFCP IPTC information in JPEG +and TIFF images. + +See +L +for the AFCP specification. + }, + IPTC => { SubDirectory => { TagTable => 'Image::ExifTool::IPTC::Main' } }, + TEXT => 'Text', + Nail => { + Name => 'ThumbnailImage', + Groups => { 2 => 'Preview' }, + # (the specification allows for a variable amount of padding before + # the image after a 10-byte header, so look for the JPEG SOI marker, + # otherwise assume a fixed 8 bytes of padding) + RawConv => q{ + pos($val) = 10; + my $start = ($val =~ /\xff\xd8\xff/g) ? pos($val) - 3 : 18; + my $img = substr($val, $start); + return $self->ValidateImage(\$img, $tag); + }, + }, + PrVw => { + Name => 'PreviewImage', + Groups => { 2 => 'Preview' }, + RawConv => q{ + pos($val) = 10; + my $start = ($val =~ /\xff\xd8\xff/g) ? pos($val) - 3 : 18; + my $img = substr($val, $start); + return $self->ValidateImage(\$img, $tag); + }, + }, +); + +#------------------------------------------------------------------------------ +# Read/write AFCP information in a file +# Inputs: 0) ExifTool object reference, 1) dirInfo reference +# (Set 'ScanForAFCP' member in dirInfo to scan from current position for AFCP) +# Returns: 1 on success, 0 if this file didn't contain AFCP information +# -1 on write error or if the offsets were incorrect on reading +# - updates DataPos to point to actual AFCP start if ScanForAFCP is set +# - updates DirLen to trailer length +# - returns Fixup reference in dirInfo hash when writing +sub ProcessAFCP($$) +{ + my ($et, $dirInfo) = @_; + my $raf = $$dirInfo{RAF}; + my $curPos = $raf->Tell(); + my $offset = $$dirInfo{Offset} || 0; # offset from end of file + my $rtnVal = 0; + +NoAFCP: for (;;) { + my ($buff, $fix, $dirBuff, $valBuff, $fixup, $vers); + # look for AXS trailer + last unless $raf->Seek(-12-$offset, 2) and + $raf->Read($buff, 12) == 12 and + $buff =~ /^(AXS(!|\*))/; + my $endPos = $raf->Tell(); + my $hdr = $1; + SetByteOrder($2 eq '!' ? 'MM' : 'II'); + my $startPos = Get32u(\$buff, 4); + if ($raf->Seek($startPos, 0) and $raf->Read($buff, 12) == 12 and $buff =~ /^$hdr/) { + $fix = 0; + } else { + $rtnVal = -1; + # look for start of AXS trailer if 'ScanForAFCP' + last unless $$dirInfo{ScanForAFCP} and $raf->Seek($curPos, 0); + my $actualPos = $curPos; + # first look for header right at current position + for (;;) { + last if $raf->Read($buff, 12) == 12 and $buff =~ /^$hdr/; + last NoAFCP if $actualPos != $curPos; + # scan for AXS header (could be after preview image) + for (;;) { + my $buf2; + $raf->Read($buf2, 65536) or last NoAFCP; + $buff .= $buf2; + if ($buff =~ /$hdr/g) { + $actualPos += pos($buff) - length($hdr); + last; # ok, now go back and re-read header + } + $buf2 = substr($buf2, -3); # only need last 3 bytes for next test + $actualPos += length($buff) - length($buf2); + $buff = $buf2; + } + last unless $raf->Seek($actualPos, 0); # seek to start of AFCP + } + # calculate shift for fixing AFCP offsets + $fix = $actualPos - $startPos; + } + # set variables returned in dirInfo hash + $$dirInfo{DataPos} = $startPos + $fix; # actual start position + $$dirInfo{DirLen} = $endPos - ($startPos + $fix); + + $rtnVal = 1; + my $verbose = $et->Options('Verbose'); + my $out = $et->Options('TextOut'); + my $outfile = $$dirInfo{OutFile}; + if ($outfile) { + # allow all AFCP information to be deleted + if ($$et{DEL_GROUP}{AFCP}) { + $verbose and print $out " Deleting AFCP\n"; + ++$$et{CHANGED}; + last; + } + $dirBuff = $valBuff = ''; + require Image::ExifTool::Fixup; + $fixup = $$dirInfo{Fixup}; + $fixup or $fixup = $$dirInfo{Fixup} = new Image::ExifTool::Fixup; + $vers = substr($buff, 4, 2); # get version number + } else { + $et->DumpTrailer($dirInfo) if $verbose or $$et{HTML_DUMP}; + } + # read AFCP directory data + my $numEntries = Get16u(\$buff, 6); + my $dir; + unless ($raf->Read($dir, 12 * $numEntries) == 12 * $numEntries) { + $et->Error('Error reading AFCP directory', 1); + last; + } + if ($verbose > 2 and not $outfile) { + my $dat = $buff . $dir; + print $out " AFCP Directory:\n"; + $et->VerboseDump(\$dat, Addr => $$dirInfo{DataPos}, Width => 12); + } + $fix and $et->Warn("Adjusted AFCP offsets by $fix", 1); +# +# process AFCP directory +# + my $tagTablePtr = GetTagTable('Image::ExifTool::AFCP::Main'); + my ($index, $entry); + for ($index=0; $index<$numEntries; ++$index) { + my $entry = 12 * $index; + my $tag = substr($dir, $entry, 4); + my $size = Get32u(\$dir, $entry + 4); + my $offset = Get32u(\$dir, $entry + 8); + if ($size < 0x80000000 and + $raf->Seek($offset+$fix, 0) and + $raf->Read($buff, $size) == $size) + { + if ($outfile) { + # rewrite this information + my $tagInfo = $et->GetTagInfo($tagTablePtr, $tag); + if ($tagInfo and $$tagInfo{SubDirectory}) { + my %subdirInfo = ( + DataPt => \$buff, + DirStart => 0, + DirLen => $size, + DataPos => $offset + $fix, + Parent => 'AFCP', + ); + my $subTable = GetTagTable($tagInfo->{SubDirectory}->{TagTable}); + my $newDir = $et->WriteDirectory(\%subdirInfo, $subTable); + if (defined $newDir) { + $size = length $newDir; + $buff = $newDir; + } + } + $fixup->AddFixup(length($dirBuff) + 8); + $dirBuff .= $tag . Set32u($size) . Set32u(length $valBuff); + $valBuff .= $buff; + } else { + # extract information + $et->HandleTag($tagTablePtr, $tag, $buff, + DataPt => \$buff, + Size => $size, + Index => $index, + DataPos => $offset + $fix, + ); + } + } else { + $et->Warn("Bad AFCP directory"); + $rtnVal = -1 if $outfile; + last; + } + } + if ($outfile and length($dirBuff)) { + my $outPos = Tell($outfile); # get current outfile position + # apply fixup to directory pointers + my $valPos = $outPos + 12; # start of value data + $fixup->{Shift} += $valPos + length($dirBuff); + $fixup->ApplyFixup(\$dirBuff); + # write the AFCP header, directory, value data and EOF record (with zero checksums) + Write($outfile, $hdr, $vers, Set16u(length($dirBuff)/12), Set32u(0), + $dirBuff, $valBuff, $hdr, Set32u($outPos), Set32u(0)) or $rtnVal = -1; + # complete fixup so the calling routine can apply further shifts + $fixup->AddFixup(length($dirBuff) + length($valBuff) + 4); + $fixup->{Start} += $valPos; + $fixup->{Shift} -= $valPos; + } + last; + } + return $rtnVal; +} + +1; # end + +__END__ + +=head1 NAME + +Image::ExifTool::AFCP - Read/write AFCP trailer + +=head1 SYNOPSIS + +This module is used by Image::ExifTool + +=head1 DESCRIPTION + +This module contains definitions required by Image::ExifTool to extract +information from the AFCP trailer. Although the AFCP specification is +compatible with various file formats, ExifTool currently only processes AFCP +in JPEG images. + +=head1 NOTES + +AFCP is a specification which allows meta information (including IPTC) to be +appended to the end of a file. + +It is a poorly designed protocol because (like TIFF) it uses absolute +offsets to specify data locations. This is a huge blunder because it makes +the AFCP information dependent on the file length, so it is easily +invalidated by image editing software which doesn't recognize the AFCP +trailer to fix up these offsets when the file length changes. ExifTool will +attempt to fix these invalid offsets if possible. + +Scanning for AFCP information may be time consuming, especially when reading +from a sequential device, since the information is at the end of the file. +In these instances, the ExifTool FastScan option may be used to disable +scanning for AFCP information. + +=head1 AUTHOR + +Copyright 2003-2019, Phil Harvey (phil at owl.phy.queensu.ca) + +This library is free software; you can redistribute it and/or modify it +under the same terms as Perl itself. + +=head1 REFERENCES + +=over 4 + +=item L + +=back + +=head1 SEE ALSO + +L, +L + +=cut + diff --git a/lib/Image/ExifTool/AIFF.pm b/lib/Image/ExifTool/AIFF.pm new file mode 100644 index 0000000..2fd82fb --- /dev/null +++ b/lib/Image/ExifTool/AIFF.pm @@ -0,0 +1,297 @@ +#------------------------------------------------------------------------------ +# File: AIFF.pm +# +# Description: Read AIFF meta information +# +# Revisions: 01/06/2006 - P. Harvey Created +# 09/22/2008 - PH Added DjVu support +# +# References: 1) http://developer.apple.com/documentation/QuickTime/INMAC/SOUND/imsoundmgr.30.htm#pgfId=3190 +# 2) http://astronomy.swin.edu.au/~pbourke/dataformats/aiff/ +# 3) http://www.mactech.com/articles/mactech/Vol.06/06.01/SANENormalized/ +#------------------------------------------------------------------------------ + +package Image::ExifTool::AIFF; + +use strict; +use vars qw($VERSION); +use Image::ExifTool qw(:DataAccess :Utils); +use Image::ExifTool::ID3; + +$VERSION = '1.09'; + +# information for time/date-based tags (time zero is Jan 1, 1904) +my %timeInfo = ( + Groups => { 2 => 'Time' }, + ValueConv => 'ConvertUnixTime($val - ((66 * 365 + 17) * 24 * 3600))', + PrintConv => '$self->ConvertDateTime($val)', +); + +# AIFF info +%Image::ExifTool::AIFF::Main = ( + GROUPS => { 2 => 'Audio' }, + NOTES => q{ + Tags extracted from Audio Interchange File Format (AIFF) files. See + L for + the AIFF specification. + }, +# FORM => 'Format', + FVER => { + Name => 'FormatVersion', + SubDirectory => { TagTable => 'Image::ExifTool::AIFF::FormatVers' }, + }, + COMM => { + Name => 'Common', + SubDirectory => { TagTable => 'Image::ExifTool::AIFF::Common' }, + }, + COMT => { + Name => 'Comment', + SubDirectory => { TagTable => 'Image::ExifTool::AIFF::Comment' }, + }, + NAME => { + Name => 'Name', + ValueConv => '$self->Decode($val, "MacRoman")', + }, + AUTH => { + Name => 'Author', + Groups => { 2 => 'Author' }, + ValueConv => '$self->Decode($val, "MacRoman")', + }, + '(c) ' => { + Name => 'Copyright', + Groups => { 2 => 'Author' }, + ValueConv => '$self->Decode($val, "MacRoman")', + }, + ANNO => { + Name => 'Annotation', + ValueConv => '$self->Decode($val, "MacRoman")', + }, + 'ID3 ' => { + Name => 'ID3', + SubDirectory => { + TagTable => 'Image::ExifTool::ID3::Main', + ProcessProc => \&Image::ExifTool::ID3::ProcessID3, + }, + }, +# SSND => 'SoundData', +# MARK => 'Marker', +# INST => 'Instrument', +# MIDI => 'MidiData', +# AESD => 'AudioRecording', +# APPL => 'ApplicationSpecific', +); + +%Image::ExifTool::AIFF::Common = ( + PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData, + GROUPS => { 2 => 'Audio' }, + FORMAT => 'int16u', + 0 => 'NumChannels', + 1 => { Name => 'NumSampleFrames', Format => 'int32u' }, + 3 => 'SampleSize', + 4 => { Name => 'SampleRate', Format => 'extended' }, #3 + 9 => { + Name => 'CompressionType', + Format => 'string[4]', + PrintConv => { + NONE => 'None', + ACE2 => 'ACE 2-to-1', + ACE8 => 'ACE 8-to-3', + MAC3 => 'MAC 3-to-1', + MAC6 => 'MAC 6-to-1', + sowt => 'Little-endian, no compression', + alaw => 'a-law', + ALAW => 'A-law', + ulaw => 'mu-law', + ULAW => 'Mu-law', + 'GSM '=> 'GSM', + G722 => 'G722', + G726 => 'G726', + G728 => 'G728', + }, + }, + 11 => { #PH + Name => 'CompressorName', + Format => 'pstring', + ValueConv => '$self->Decode($val, "MacRoman")', + }, +); + +%Image::ExifTool::AIFF::FormatVers = ( + PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData, + FORMAT => 'int32u', + 0 => { Name => 'FormatVersionTime', %timeInfo }, +); + +%Image::ExifTool::AIFF::Comment = ( + PROCESS_PROC => \&Image::ExifTool::AIFF::ProcessComment, + GROUPS => { 2 => 'Audio' }, + 0 => { Name => 'CommentTime', %timeInfo }, + 1 => 'MarkerID', + 2 => { + Name => 'Comment', + ValueConv => '$self->Decode($val, "MacRoman")', + }, +); + +%Image::ExifTool::AIFF::Composite = ( + Duration => { + Require => { + 0 => 'AIFF:SampleRate', + 1 => 'AIFF:NumSampleFrames', + }, + RawConv => '($val[0] and $val[1]) ? $val[1] / $val[0] : undef', + PrintConv => 'ConvertDuration($val)', + }, +); + +# add our composite tags +Image::ExifTool::AddCompositeTags('Image::ExifTool::AIFF'); + + +#------------------------------------------------------------------------------ +# Process AIFF Comment chunk +# Inputs: 0) ExifTool object reference, 1) DirInfo reference, 2) tag table ref +# Returns: 1 on success +sub ProcessComment($$$) +{ + my ($et, $dirInfo, $tagTablePtr) = @_; + my $dataPt = $$dirInfo{DataPt}; + my $dirLen = $$dirInfo{DirLen}; + my $verbose = $et->Options('Verbose'); + return 0 unless $dirLen > 2; + my $numComments = unpack('n',$$dataPt); + my $pos = 2; + my $i; + $verbose and $et->VerboseDir('Comment', $numComments); + for ($i=0; $i<$numComments; ++$i) { + last if $pos + 8 > $dirLen; + my ($time, $markerID, $size) = unpack("x${pos}Nnn", $$dataPt); + $et->HandleTag($tagTablePtr, 0, $time); + $et->HandleTag($tagTablePtr, 1, $markerID) if $markerID; + $pos += 8; + last if $pos + $size > $dirLen; + my $val = substr($$dataPt, $pos, $size); + $et->HandleTag($tagTablePtr, 2, $val); + ++$size if $size & 0x01; # account for padding byte if necessary + $pos += $size; + } +} + +#------------------------------------------------------------------------------ +# Extract information from a AIFF file +# Inputs: 0) ExifTool object reference, 1) DirInfo reference +# Returns: 1 on success, 0 if this wasn't a valid AIFF file +sub ProcessAIFF($$) +{ + my ($et, $dirInfo) = @_; + my $raf = $$dirInfo{RAF}; + my ($buff, $err, $tagTablePtr, $page, $type); + + # verify this is a valid AIFF file + return 0 unless $raf->Read($buff, 12) == 12; + my $fast3 = $$et{OPTIONS}{FastScan} && $$et{OPTIONS}{FastScan} == 3; + my $pos = 12; + # check for DjVu image + if ($buff =~ /^AT&TFORM/) { + # http://www.djvu.org/ + # http://djvu.sourceforge.net/specs/djvu3changes.txt + my $buf2; + return 0 unless $raf->Read($buf2, 4) == 4 and $buf2 =~ /^(DJVU|DJVM)/; + $pos += 4; + $buff = substr($buff, 4) . $buf2; + $et->SetFileType('DJVU'); + return 1 if $fast3; + $tagTablePtr = GetTagTable('Image::ExifTool::DjVu::Main'); + # modifiy FileType to indicate a multi-page document + $$et{VALUE}{FileType} .= " (multi-page)" if $buf2 eq 'DJVM'; + $type = 'DjVu'; + } else { + return 0 unless $buff =~ /^FORM....(AIF(F|C))/s; + $et->SetFileType($1); + return 1 if $fast3; + $tagTablePtr = GetTagTable('Image::ExifTool::AIFF::Main'); + $type = 'AIFF'; + } + SetByteOrder('MM'); + my $verbose = $et->Options('Verbose'); +# +# Read through the IFF chunks +# + for (;;) { + $raf->Read($buff, 8) == 8 or last; + $pos += 8; + my ($tag, $len) = unpack('a4N', $buff); + my $tagInfo = $et->GetTagInfo($tagTablePtr, $tag); + $et->VPrint(0, "AIFF '${tag}' chunk ($len bytes of data):\n"); + # AIFF chunks are padded to an even number of bytes + my $len2 = $len + ($len & 0x01); + if ($tagInfo) { + if ($$tagInfo{TypeOnly}) { + $len = $len2 = 4; + $page = ($page || 0) + 1; + $et->VPrint(0, $$et{INDENT} . "Page $page:\n"); + } + $raf->Read($buff, $len2) >= $len or $err=1, last; + unless ($$tagInfo{SubDirectory} or $$tagInfo{Binary}) { + $buff =~ s/\0+$//; # remove trailing nulls + } + $et->HandleTag($tagTablePtr, $tag, $buff, + DataPt => \$buff, + DataPos => $pos, + Start => 0, + Size => $len, + ); + } elsif ($verbose > 2 and $len2 < 1024000) { + $raf->Read($buff, $len2) == $len2 or $err = 1, last; + $et->VerboseDump(\$buff); + } else { + $raf->Seek($len2, 1) or $err=1, last; + } + $pos += $len2; + } + $err and $et->Warn("Error reading $type file (corrupted?)"); + return 1; +} + +1; # end + +__END__ + +=head1 NAME + +Image::ExifTool::AIFF - Read AIFF meta information + +=head1 SYNOPSIS + +This module is used by Image::ExifTool + +=head1 DESCRIPTION + +This module contains routines required by Image::ExifTool to extract +information from AIFF (Audio Interchange File Format) audio files. + +=head1 AUTHOR + +Copyright 2003-2019, Phil Harvey (phil at owl.phy.queensu.ca) + +This library is free software; you can redistribute it and/or modify it +under the same terms as Perl itself. + +=head1 REFERENCES + +=over 4 + +=item L + +=item L + +=item L + +=back + +=head1 SEE ALSO + +L, +L + +=cut diff --git a/lib/Image/ExifTool/APE.pm b/lib/Image/ExifTool/APE.pm new file mode 100644 index 0000000..736fb81 --- /dev/null +++ b/lib/Image/ExifTool/APE.pm @@ -0,0 +1,287 @@ +#------------------------------------------------------------------------------ +# File: APE.pm +# +# Description: Read Monkey's Audio meta information +# +# Revisions: 11/13/2006 - P. Harvey Created +# +# References: 1) http://www.monkeysaudio.com/ +# 2) http://www.personal.uni-jena.de/~pfk/mpp/sv8/apetag.html +#------------------------------------------------------------------------------ + +package Image::ExifTool::APE; + +use strict; +use vars qw($VERSION); +use Image::ExifTool qw(:DataAccess :Utils); + +$VERSION = '1.05'; + +# APE metadata blocks +%Image::ExifTool::APE::Main = ( + GROUPS => { 2 => 'Audio' }, + NOTES => q{ + Tags found in Monkey's Audio (APE) information. Only a few common tags are + listed below, but ExifTool will extract any tag found. ExifTool supports + APEv1 and APEv2 tags, as well as ID3 information in APE files, and will also + read APE metadata from MP3 and MPC files. + }, + Album => { }, + Artist => { }, + Genre => { }, + Title => { }, + Track => { }, + Year => { }, + DURATION => { + Name => 'Duration', + ValueConv => '$val += 4294967296 if $val < 0 and $val >= -2147483648; $val * 1e-7', + PrintConv => 'ConvertDuration($val)', + }, + 'Tool Version' => { Name => 'ToolVersion' }, + 'Tool Name' => { Name => 'ToolName' }, +); + +# APE MAC header version 3.97 or earlier +%Image::ExifTool::APE::OldHeader = ( + PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData, + GROUPS => { 1 => 'MAC', 2 => 'Audio' }, + FORMAT => 'int16u', + NOTES => 'APE MAC audio header for version 3.97 or earlier.', + 0 => { + Name => 'APEVersion', + ValueConv => '$val / 1000', + }, + 1 => 'CompressionLevel', + # 2 => 'FormatFlags', + 3 => 'Channels', + 4 => { Name => 'SampleRate', Format => 'int32u' }, + # 6 => { Name => 'HeaderBytes', Format => 'int32u' }, # WAV header bytes + # 8 => { Name => 'TerminatingBytes', Format => 'int32u' }, + 10 => { Name => 'TotalFrames', Format => 'int32u' }, + 12 => { Name => 'FinalFrameBlocks', Format => 'int32u' }, +); + +# APE MAC header version 3.98 or later +%Image::ExifTool::APE::NewHeader = ( + PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData, + GROUPS => { 1 => 'MAC', 2 => 'Audio' }, + FORMAT => 'int16u', + NOTES => 'APE MAC audio header for version 3.98 or later.', + 0 => 'CompressionLevel', + # 1 => 'FormatFlags', + 2 => { Name => 'BlocksPerFrame', Format => 'int32u' }, + 4 => { Name => 'FinalFrameBlocks', Format => 'int32u' }, + 6 => { Name => 'TotalFrames', Format => 'int32u' }, + 8 => 'BitsPerSample', + 9 => 'Channels', + 10 => { Name => 'SampleRate', Format => 'int32u' }, +); + +# APE Composite tags +%Image::ExifTool::APE::Composite = ( + GROUPS => { 2 => 'Audio' }, + Duration => { + Require => { + 0 => 'APE:SampleRate', + 1 => 'APE:TotalFrames', + 2 => 'APE:BlocksPerFrame', + 3 => 'APE:FinalFrameBlocks', + }, + RawConv => '($val[0] && $val[1]) ? (($val[1] - 1) * $val[2] + $val[3]) / $val[0]: undef', + PrintConv => 'ConvertDuration($val)', + }, +); + +# add our composite tags +Image::ExifTool::AddCompositeTags('Image::ExifTool::APE'); + +#------------------------------------------------------------------------------ +# Make tag info hash for specified tag +# Inputs: 0) tag name, 1) tag table ref +# - must only call if tag doesn't exist +sub MakeTag($$) +{ + my ($tag, $tagTablePtr) = @_; + my $name = ucfirst(lc($tag)); + # remove invalid characters in tag name and capitalize following letters + $name =~ s/[^\w-]+(.?)/\U$1/sg; + $name =~ s/([a-z0-9])_([a-z])/$1\U$2/g; + my %tagInfo = ( Name => $name ); + $tagInfo{Groups} = { 2 => 'Preview' } if $tag =~ /^Cover Art/ and $tag !~ /Desc$/; + AddTagToTable($tagTablePtr, $tag, \%tagInfo); +} + +#------------------------------------------------------------------------------ +# Extract information from an APE file +# Inputs: 0) ExifTool object reference, 1) dirInfo reference +# - Just looks for APE trailer if FileType is already set +# Returns: 1 on success, 0 if this wasn't a valid APE file +sub ProcessAPE($$) +{ + my ($et, $dirInfo) = @_; + + # must first check for leading/trailing ID3 information + unless ($$et{DoneID3}) { + require Image::ExifTool::ID3; + Image::ExifTool::ID3::ProcessID3($et, $dirInfo) and return 1; + } + my $raf = $$dirInfo{RAF}; + my $verbose = $et->Options('Verbose'); + my ($buff, $i, $header, $tagTablePtr, $dataPos, $oldIndent); + + $$et{DoneAPE} = 1; + + # check APE signature and process audio information + # unless this is some other type of file + unless ($$et{VALUE}{FileType}) { + $raf->Read($buff, 32) == 32 or return 0; + $buff =~ /^(MAC |APETAGEX)/ or return 0; + $et->SetFileType(); + SetByteOrder('II'); + + if ($buff =~ /^APETAGEX/) { + # we already read the APE header + $header = 1; + } else { + # process the MAC header + my $vers = Get16u(\$buff, 4); + my $table; + if ($vers <= 3970) { + $buff = substr($buff, 4); + $table = GetTagTable('Image::ExifTool::APE::OldHeader'); + } else { + my $dlen = Get32u(\$buff, 8); + my $hlen = Get32u(\$buff, 12); + unless ($dlen & 0x80000000 or $hlen & 0x80000000) { + if ($raf->Seek($dlen, 0) and $raf->Read($buff, $hlen) == $hlen) { + $table = GetTagTable('Image::ExifTool::APE::NewHeader'); + } + } + } + $et->ProcessDirectory( { DataPt => \$buff }, $table) if $table; + } + } + # look for APE trailer unless we already found an APE header + unless ($header) { + # look for the APE trailer footer... + my $footPos = -32; + # (...but before the ID3v1 trailer if it exists) + $footPos -= 128 if $$et{DoneID3} == 2; + $raf->Seek($footPos, 2) or return 1; + $raf->Read($buff, 32) == 32 or return 1; + $buff =~ /^APETAGEX/ or return 1; + SetByteOrder('II'); + } +# +# Read the APE data (we have just read the APE header or footer into $buff) +# + my ($version, $size, $count, $flags) = unpack('x8V4', $buff); + $version /= 1000; + $size -= 32; # get size of data only + if (($size & 0x80000000) == 0 and + ($header or $raf->Seek(-$size-32, 1)) and + $raf->Read($buff, $size) == $size) + { + if ($verbose) { + $oldIndent = $$et{INDENT}; + $$et{INDENT} .= '| '; + $et->VerboseDir("APEv$version", $count, $size); + $et->VerboseDump(\$buff, DataPos => $raf->Tell() - $size); + } + $tagTablePtr = GetTagTable('Image::ExifTool::APE::Main'); + $dataPos = $raf->Tell() - $size; + } else { + $count = -1; + } +# +# Process the APE tags +# + my $pos = 0; + for ($i=0; $i<$count; ++$i) { + # read next APE tag + last if $pos + 8 > $size; + my $len = Get32u(\$buff, $pos); + my $flags = Get32u(\$buff, $pos + 4); + pos($buff) = $pos + 8; + last unless $buff =~ /\G(.*?)\0/sg; + my $tag = $1; + # avoid conflicts with our special table entries + $tag .= '.' if $Image::ExifTool::specialTags{$tag}; + $pos = pos($buff); + last if $pos + $len > $size; + my $val = substr($buff, $pos, $len); + MakeTag($tag, $tagTablePtr) unless $$tagTablePtr{$tag}; + # handle binary-value tags + if (($flags & 0x06) == 0x02) { + my $buf2 = $val; + $val = \$buf2; + # extract cover art description separately (hackitty hack) + if ($tag =~ /^Cover Art/) { + $buf2 =~ s/^([\x20-\x7f]*)\0//; + if ($1) { + my $t = "$tag Desc"; + my $v = $1; + MakeTag($t, $tagTablePtr) unless $$tagTablePtr{$t}; + $et->HandleTag($tagTablePtr, $t, $v); + } + } + } + $et->HandleTag($tagTablePtr, $tag, $val, + Index => $i, + DataPt => \$buff, + DataPos => $dataPos, + Start => $pos, + Size => $len, + ); + $pos += $len; + } + $i == $count or $et->Warn('Bad APE trailer'); + $$et{INDENT} = $oldIndent if defined $oldIndent; + return 1; +} + +1; # end + +__END__ + +=head1 NAME + +Image::ExifTool::APE - Read Monkey's Audio meta information + +=head1 SYNOPSIS + +This module is used by Image::ExifTool + +=head1 DESCRIPTION + +This module contains definitions required by Image::ExifTool to extract meta +information from Monkey's Audio (APE) audio files. + +=head1 BUGS + +Currently doesn't parse MAC header unless it is at the start of the file. + +=head1 AUTHOR + +Copyright 2003-2019, Phil Harvey (phil at owl.phy.queensu.ca) + +This library is free software; you can redistribute it and/or modify it +under the same terms as Perl itself. + +=head1 REFERENCES + +=over 4 + +=item L + +=item L + +=back + +=head1 SEE ALSO + +L, +L + +=cut + diff --git a/lib/Image/ExifTool/APP12.pm b/lib/Image/ExifTool/APP12.pm new file mode 100644 index 0000000..4ecd5f0 --- /dev/null +++ b/lib/Image/ExifTool/APP12.pm @@ -0,0 +1,322 @@ +#------------------------------------------------------------------------------ +# File: APP12.pm +# +# Description: Read APP12 meta information +# +# Revisions: 10/18/2005 - P. Harvey Created +# +# References: 1) Heinrich Giesen private communication +#------------------------------------------------------------------------------ + +package Image::ExifTool::APP12; + +use strict; +use vars qw($VERSION); +use Image::ExifTool qw(:DataAccess :Utils); + +$VERSION = '1.13'; + +sub ProcessAPP12($$$); +sub ProcessDucky($$$); +sub WriteDucky($$$); + +# APP12 tags (ref PH) +%Image::ExifTool::APP12::PictureInfo = ( + PROCESS_PROC => \&ProcessAPP12, + GROUPS => { 0 => 'APP12', 1 => 'PictureInfo', 2 => 'Image' }, + PRIORITY => 0, + NOTES => q{ + The JPEG APP12 "Picture Info" segment was used by some older cameras, and + contains ASCII-based meta information. Below are some tags which have been + observed Agfa and Polaroid images, however ExifTool will extract information + from any tags found in this segment. + }, + FNumber => { + ValueConv => '$val=~s/^[A-Za-z ]*//;$val', # Agfa leads with an 'F' + PrintConv => 'sprintf("%.1f",$val)', + }, + Aperture => { + PrintConv => 'sprintf("%.1f",$val)', + }, + TimeDate => { + Name => 'DateTimeOriginal', + Description => 'Date/Time Original', + Groups => { 2 => 'Time' }, + ValueConv => '$val=~/^\d+$/ ? ConvertUnixTime($val) : $val', + PrintConv => '$self->ConvertDateTime($val)', + }, + Shutter => { + Name => 'ExposureTime', + ValueConv => '$val * 1e-6', + PrintConv => 'Image::ExifTool::Exif::PrintExposureTime($val)', + }, + shtr => { + Name => 'ExposureTime', + ValueConv => '$val * 1e-6', + PrintConv => 'Image::ExifTool::Exif::PrintExposureTime($val)', + }, + 'Serial#' => { + Name => 'SerialNumber', + Groups => { 2 => 'Camera' }, + }, + Flash => { PrintConv => { 0 => 'Off', 1 => 'On' } }, + Macro => { PrintConv => { 0 => 'Off', 1 => 'On' } }, + StrobeTime => { }, + Ytarget => { Name => 'YTarget' }, + ylevel => { Name => 'YLevel' }, + FocusPos => { }, + FocusMode => { }, + Quality => { }, + ExpBias => 'ExposureCompensation', + FWare => 'FirmwareVersion', + StrobeTime => { }, + Resolution => { }, + Protect => { }, + ConTake => { }, + ImageSize => { PrintConv => '$val=~tr/-/x/;$val' }, + ColorMode => { }, + Zoom => { }, + ZoomPos => { }, + LightS => { }, + Type => { + Name => 'CameraType', + Groups => { 2 => 'Camera' }, + DataMember => 'CameraType', + RawConv => '$self->{CameraType} = $val', + }, + Version => { Groups => { 2 => 'Camera' } }, + ID => { Groups => { 2 => 'Camera' } }, +); + +# APP12 segment written in Photoshop "Save For Web" images +# (from tests with Photoshop 7 files - PH/1) +%Image::ExifTool::APP12::Ducky = ( + PROCESS_PROC => \&ProcessDucky, + WRITE_PROC => \&WriteDucky, + GROUPS => { 0 => 'Ducky', 1 => 'Ducky', 2 => 'Image' }, + WRITABLE => 'string', + NOTES => q{ + Photoshop uses the JPEG APP12 "Ducky" segment to store some information in + "Save for Web" images. + }, + 1 => { #PH + Name => 'Quality', + Priority => 0, + Avoid => 1, + Writable => 'int32u', + ValueConv => 'unpack("N",$val)', # 4-byte integer + ValueConvInv => 'pack("N",$val)', + PrintConv => '"$val%"', + PrintConvInv => '$val=~/(\d+)/ ? $1 : undef', + }, + 2 => { #1 + Name => 'Comment', + Priority => 0, + Avoid => 1, + # (ignore 4-byte character count at start of value) + ValueConv => '$self->Decode(substr($val,4),"UCS2","MM")', + ValueConvInv => 'pack("N",length $val) . $self->Encode($val,"UCS2","MM")', + }, + 3 => { #PH + Name => 'Copyright', + Priority => 0, + Avoid => 1, + Groups => { 2 => 'Author' }, + # (ignore 4-byte character count at start of value) + ValueConv => '$self->Decode(substr($val,4),"UCS2","MM")', + ValueConvInv => 'pack("N",length $val) . $self->Encode($val,"UCS2","MM")', + }, +); + +#------------------------------------------------------------------------------ +# Write APP12 Ducky segment +# Inputs: 0) ExifTool object ref, 1) dirInfo ref, 2) tag table ref +# Returns: New directory data or undefined on error +sub WriteDucky($$$) +{ + my ($et, $dirInfo, $tagTablePtr) = @_; + $et or return 1; # allow dummy access to autoload this package + my $dataPt = $$dirInfo{DataPt}; + my $pos = $$dirInfo{DirStart}; + my $newTags = $et->GetNewTagInfoHash($tagTablePtr); + my @addTags = sort { $a <=> $b } keys(%$newTags); + my ($dirEnd, %doneTags); + if ($dataPt) { + $dirEnd = $pos + $$dirInfo{DirLen}; + } else { + my $tmp = ''; + $dataPt = \$tmp; + $pos = $dirEnd = 0; + } + my $newData = ''; + SetByteOrder('MM'); + # process all data blocks in Ducky segment + for (;;) { + my ($tag, $len, $val); + if ($pos + 4 <= $dirEnd) { + $tag = Get16u($dataPt, $pos); + $len = Get16u($dataPt, $pos + 2); + $pos += 4; + if ($pos + $len > $dirEnd) { + $et->Warn('Invalid Ducky block length'); + return undef; + } + $val = substr($$dataPt, $pos, $len); + $pos += $len; + } else { + last unless @addTags; + $tag = pop @addTags; + next if $doneTags{$tag}; + } + $doneTags{$tag} = 1; + my $tagInfo = $$newTags{$tag}; + if ($tagInfo) { + my $nvHash = $et->GetNewValueHash($tagInfo); + my $isNew; + if (defined $val) { + if ($et->IsOverwriting($nvHash, $val)) { + $et->VerboseValue("- Ducky:$$tagInfo{Name}", $val); + $isNew = 1; + } + } else { + next unless $$nvHash{IsCreating}; + $isNew = 1; + } + if ($isNew) { + $val = $et->GetNewValue($nvHash); + ++$$et{CHANGED}; + next unless defined $val; # next if tag is being deleted + $et->VerboseValue("+ Ducky:$$tagInfo{Name}", $val); + } + } + $newData .= pack('nn', $tag, length $val) . $val; + } + $newData .= "\0\0" if length $newData; + return $newData; +} + +#------------------------------------------------------------------------------ +# Process APP12 Ducky segment (ref PH) +# Inputs: 0) ExifTool object reference, 1) Directory information ref, 2) tag table ref +# Returns: 1 on success, 0 if this wasn't a recognized Ducky segment +# Notes: This segment has the following format: +# 1) 5 bytes: "Ducky" +# 2) multiple data blocks (all integers are big endian): +# a) 2 bytes: block type (0=end, 1=Quality, 2=Comment, 3=Copyright) +# b) 2 bytes: block length (N) +# c) N bytes: block data +sub ProcessDucky($$$) +{ + my ($et, $dirInfo, $tagTablePtr) = @_; + my $dataPt = $$dirInfo{DataPt}; + my $pos = $$dirInfo{DirStart}; + my $dirEnd = $pos + $$dirInfo{DirLen}; + SetByteOrder('MM'); + # process all data blocks in Ducky segment + for (;;) { + last if $pos + 4 > $dirEnd; + my $tag = Get16u($dataPt, $pos); + my $len = Get16u($dataPt, $pos + 2); + $pos += 4; + if ($pos + $len > $dirEnd) { + $et->Warn('Invalid Ducky block length'); + last; + } + my $val = substr($$dataPt, $pos, $len); + $et->HandleTag($tagTablePtr, $tag, $val, + DataPt => $dataPt, + DataPos => $$dirInfo{DataPos}, + Start => $pos, + Size => $len, + ); + $pos += $len; + } + return 1; +} + +#------------------------------------------------------------------------------ +# Process APP12 Picture Info segment (ref PH) +# Inputs: 0) ExifTool object reference, 1) Directory information ref, 2) tag table ref +# Returns: 1 on success, 0 if this wasn't a recognized APP12 +sub ProcessAPP12($$$) +{ + my ($et, $dirInfo, $tagTablePtr) = @_; + my $dataPt = $$dirInfo{DataPt}; + my $dirStart = $$dirInfo{DirStart} || 0; + my $dirLen = $$dirInfo{DirLen} || (length($$dataPt) - $dirStart); + if ($dirLen != $dirStart + length($$dataPt)) { + my $buff = substr($$dataPt, $dirStart, $dirLen); + $dataPt = \$buff; + } else { + pos($$dataPt) = $$dirInfo{DirStart}; + } + my $verbose = $et->Options('Verbose'); + my $success = 0; + my $section = ''; + pos($$dataPt) = 0; + + # this regular expression is a bit complex, but basically we are looking for + # section headers (eg. "[Camera Info]") and tag/value pairs (eg. "tag=value", + # where "value" may contain white space), separated by spaces or CR/LF. + # (APP12 uses CR/LF, but Olympus TextualInfo is similar and uses spaces) + while ($$dataPt =~ /(\[.*?\]|[\w#-]+=[\x20-\x7e]+?(?=\s*([\n\r\0]|[\w#-]+=|\[|$)))/g) { + my $token = $1; + # was this a section name? + if ($token =~ /^\[(.*)\]/) { + $et->VerboseDir($1) if $verbose; + $section = ($token =~ /\[(\S+) ?Info\]/i) ? $1 : ''; + $success = 1; + next; + } + $et->VerboseDir($$dirInfo{DirName}) if $verbose and not $success; + $success = 1; + my ($tag, $val) = ($token =~ /(\S+)=(.+)/); + my $tagInfo = $et->GetTagInfo($tagTablePtr, $tag); + $verbose and $et->VerboseInfo($tag, $tagInfo, Value => $val); + unless ($tagInfo) { + # add new tag to table + $tagInfo = { Name => ucfirst $tag }; + # put in Camera group if information in "Camera" section + $$tagInfo{Groups} = { 2 => 'Camera' } if $section =~ /camera/i; + AddTagToTable($tagTablePtr, $tag, $tagInfo); + } + $et->FoundTag($tagInfo, $val); + } + return $success; +} + + +1; #end + +__END__ + +=head1 NAME + +Image::ExifTool::APP12 - Read APP12 meta information + +=head1 SYNOPSIS + +This module is loaded automatically by Image::ExifTool when required. + +=head1 DESCRIPTION + +This module contains definitions required by Image::ExifTool to interpret +APP12 meta information. + +=head1 AUTHOR + +Copyright 2003-2019, Phil Harvey (phil at owl.phy.queensu.ca) + +This library is free software; you can redistribute it and/or modify it +under the same terms as Perl itself. + +=head1 ACKNOWLEDGEMENTS + +Thanks to Heinrich Giesen for his help decoding APP12 "Ducky" information. + +=head1 SEE ALSO + +L, +L + +=cut diff --git a/lib/Image/ExifTool/ASF.pm b/lib/Image/ExifTool/ASF.pm new file mode 100644 index 0000000..dacf95f --- /dev/null +++ b/lib/Image/ExifTool/ASF.pm @@ -0,0 +1,898 @@ +#------------------------------------------------------------------------------ +# File: ASF.pm +# +# Description: Read ASF/WMA/WMV meta information +# +# Revisions: 12/23/2005 - P. Harvey Created +# +# References: 1) http://www.microsoft.com/windows/windowsmedia/format/asfspec.aspx +# 2) http://www.adobe.com/devnet/xmp/pdfs/XMPSpecificationPart3.pdf (Oct 2008) +#------------------------------------------------------------------------------ + +package Image::ExifTool::ASF; + +use strict; +use vars qw($VERSION); +use Image::ExifTool qw(:DataAccess :Utils); +use Image::ExifTool::Exif; +use Image::ExifTool::RIFF; + +$VERSION = '1.25'; + +sub ProcessASF($$;$); +sub ProcessContentDescription($$$); +sub ProcessExtendedContentDescription($$$); +sub ProcessMetadata($$$); +sub ProcessPicture($$$); +sub ProcessCodecList($$$); + +# GUID definitions +my %errorCorrection = ( + '20FB5700-5B55-11CF-A8FD-00805F5C442B' => 'No Error Correction', + 'BFC3CD50-618F-11CF-8BB2-00AA00B4E220' => 'Audio Spread', +); + +my %streamType = ( + 'F8699E40-5B4D-11CF-A8FD-00805F5C442B' => 'Audio', + 'BC19EFC0-5B4D-11CF-A8FD-00805F5C442B' => 'Video', + '59DACFC0-59E6-11D0-A3AC-00A0C90348F6' => 'Command', + 'B61BE100-5B4E-11CF-A8FD-00805F5C442B' => 'JFIF', + '35907DE0-E415-11CF-A917-00805F5C442B' => 'Degradable JPEG', + '91BD222C-F21C-497A-8B6D-5AA86BFC0185' => 'File Transfer', + '3AFB65E2-47EF-40F2-AC2C-70A90D71D343' => 'Binary', +); + +my %mutex = ( + 'D6E22A00-35DA-11D1-9034-00A0C90349BE' => 'MutexLanguage', + 'D6E22A01-35DA-11D1-9034-00A0C90349BE' => 'MutexBitrate', + 'D6E22A02-35DA-11D1-9034-00A0C90349BE' => 'MutexUnknown', +); + +my %bandwidthSharing = ( + 'AF6060AA-5197-11D2-B6AF-00C04FD908E9' => 'SharingExclusive', + 'AF6060AB-5197-11D2-B6AF-00C04FD908E9' => 'SharingPartial', +); + +my %typeSpecific = ( + '776257D4-C627-41CB-8F81-7AC7FF1C40CC' => 'WebStreamMediaSubtype', + 'DA1E6B13-8359-4050-B398-388E965BF00C' => 'WebStreamFormat', +); + +my %advancedContentEncryption = ( + '7A079BB6-DAA4-4e12-A5CA-91D38DC11A8D' => 'DRMNetworkDevices', +); + +# ASF top level objects +%Image::ExifTool::ASF::Main = ( + PROCESS_PROC => \&ProcessASF, + NOTES => q{ + The ASF format is used by Windows WMA and WMV files, and DIVX videos. Tag + ID's aren't listed because they are huge 128-bit GUID's that would ruin the + formatting of this table. + }, + '75B22630-668E-11CF-A6D9-00AA0062CE6C' => { + Name => 'Header', + SubDirectory => { TagTable => 'Image::ExifTool::ASF::Header', Size => 6 }, + }, + '75B22636-668E-11CF-A6D9-00AA0062CE6C' => 'Data', + '33000890-E5B1-11CF-89F4-00A0C90349CB' => 'SimpleIndex', + 'D6E229D3-35DA-11D1-9034-00A0C90349BE' => 'Index', + 'FEB103F8-12AD-4C64-840F-2A1D2F7AD48C' => 'MediaIndex', + '3CB73FD0-0C4A-4803-953D-EDF7B6228F0C' => 'TimecodeIndex', + 'BE7ACFCB-97A9-42E8-9C71-999491E3AFAC' => { #2 + Name => 'XMP', + SubDirectory => { TagTable => 'Image::ExifTool::XMP::Main' }, + }, +); + +# ASF header objects +%Image::ExifTool::ASF::Header = ( + PROCESS_PROC => \&ProcessASF, + '8CABDCA1-A947-11CF-8EE4-00C00C205365' => { + Name => 'FileProperties', + SubDirectory => { TagTable => 'Image::ExifTool::ASF::FileProperties' }, + }, + 'B7DC0791-A9B7-11CF-8EE6-00C00C205365' => { + Name => 'StreamProperties', + SubDirectory => { TagTable => 'Image::ExifTool::ASF::StreamProperties' }, + }, + '5FBF03B5-A92E-11CF-8EE3-00C00C205365' => { + Name => 'HeaderExtension', + SubDirectory => { TagTable => 'Image::ExifTool::ASF::HeaderExtension', Size => 22 }, + }, + '86D15240-311D-11D0-A3A4-00A0C90348F6' => { + Name => 'CodecList', + SubDirectory => { TagTable => 'Image::ExifTool::ASF::CodecList' }, + }, + '1EFB1A30-0B62-11D0-A39B-00A0C90348F6' => 'ScriptCommand', + 'F487CD01-A951-11CF-8EE6-00C00C205365' => 'Marker', + 'D6E229DC-35DA-11D1-9034-00A0C90349BE' => 'BitrateMutualExclusion', + '75B22635-668E-11CF-A6D9-00AA0062CE6C' => 'ErrorCorrection', + '75B22633-668E-11CF-A6D9-00AA0062CE6C' => { + Name => 'ContentDescription', + SubDirectory => { TagTable => 'Image::ExifTool::ASF::ContentDescr' }, + }, + '2211B3FA-BD23-11D2-B4B7-00A0C955FC6E' => { + Name => 'ContentBranding', + SubDirectory => { TagTable => 'Image::ExifTool::ASF::ContentBranding' }, + }, + 'D2D0A440-E307-11D2-97F0-00A0C95EA850' => { + Name => 'ExtendedContentDescr', + SubDirectory => { TagTable => 'Image::ExifTool::ASF::ExtendedDescr' }, + }, + '7BF875CE-468D-11D1-8D82-006097C9A2B2' => 'StreamBitrateProps', + '2211B3FB-BD23-11D2-B4B7-00A0C955FC6E' => 'ContentEncryption', + '298AE614-2622-4C17-B935-DAE07EE9289C' => 'ExtendedContentEncryption', + '2211B3FC-BD23-11D2-B4B7-00A0C955FC6E' => 'DigitalSignature', + '1806D474-CADF-4509-A4BA-9AABCB96AAE8' => 'Padding', +); + +%Image::ExifTool::ASF::ContentDescr = ( + PROCESS_PROC => \&ProcessContentDescription, + GROUPS => { 2 => 'Video' }, + 0 => 'Title', + 1 => { Name => 'Author', Groups => { 2 => 'Author' } }, + 2 => { Name => 'Copyright', Groups => { 2 => 'Author' } }, + 3 => 'Description', + 4 => 'Rating', +); + +%Image::ExifTool::ASF::ContentBranding = ( + PROCESS_PROC => \&ProcessContentBranding, + GROUPS => { 2 => 'Author' }, + 0 => { + Name => 'BannerImageType', + PrintConv => { + 0 => 'None', + 1 => 'Bitmap', + 2 => 'JPEG', + 3 => 'GIF', + }, + }, + 1 => { Name => 'BannerImage', Groups => { 2 => 'Preview' }, Binary => 1 }, + 2 => 'BannerImageURL', + 3 => 'CopyrightURL', +); + +# Note: Many of these tags are similar to those in Image::ExifTool::Microsoft::Xtra +# and Image::ExifTool::WTV::Metadata +# (tags in this table may have a leading "WM/" removed) +%Image::ExifTool::ASF::ExtendedDescr = ( + PROCESS_PROC => \&ProcessExtendedContentDescription, + GROUPS => { 2 => 'Video' }, + ASFLeakyBucketPairs => { Binary => 1 }, + AspectRatioX => {}, + AspectRatioY => {}, + Author => { Groups => { 2 => 'Author' } }, + AverageLevel => {}, + BannerImageData => {}, + BannerImageType => {}, + BannerImageURL => {}, + Bitrate => { PrintConv => 'ConvertBitrate($val)' }, + Broadcast => {}, + BufferAverage => {}, + Can_Skip_Backward => {}, + Can_Skip_Forward => {}, + Copyright => { Groups => { 2 => 'Author' } }, + CopyrightURL => { Groups => { 2 => 'Author' } }, + CurrentBitrate => { PrintConv => 'ConvertBitrate($val)' }, + Description => {}, + DRM_ContentID => {}, + DRM_DRMHeader_ContentDistributor => {}, + DRM_DRMHeader_ContentID => {}, + DRM_DRMHeader_IndividualizedVersion => {}, + DRM_DRMHeader_KeyID => {}, + DRM_DRMHeader_LicenseAcqURL => {}, + DRM_DRMHeader_SubscriptionContentID => {}, + DRM_DRMHeader => {}, + DRM_IndividualizedVersion => {}, + DRM_KeyID => {}, + DRM_LASignatureCert => {}, + DRM_LASignatureLicSrvCert => {}, + DRM_LASignaturePrivKey => {}, + DRM_LASignatureRootCert => {}, + DRM_LicenseAcqURL => {}, + DRM_V1LicenseAcqURL => {}, + Duration => { PrintConv => 'ConvertDuration($val)' }, + FileSize => {}, + HasArbitraryDataStream => {}, + HasAttachedImages => {}, + HasAudio => {}, + HasFileTransferStream => {}, + HasImage => {}, + HasScript => {}, + HasVideo => {}, + Is_Protected => {}, + Is_Trusted => {}, + IsVBR => {}, + NSC_Address => {}, + NSC_Description => {}, + NSC_Email => {}, + NSC_Name => {}, + NSC_Phone => {}, + NumberOfFrames => {}, + OptimalBitrate => { PrintConv => 'ConvertBitrate($val)' }, + PeakValue => {}, + Rating => {}, + Seekable => {}, + Signature_Name => {}, + Stridable => {}, + Title => {}, + VBRPeak => {}, + # "WM/" tags... + AlbumArtist => {}, + AlbumCoverURL => {}, + AlbumTitle => {}, + ASFPacketCount => {}, + ASFSecurityObjectsSize => {}, + AudioFileURL => {}, + AudioSourceURL => {}, + AuthorURL => { Groups => { 2 => 'Author' } }, + BeatsPerMinute => {}, + Category => {}, + Codec => {}, + Composer => {}, + Conductor => {}, + ContainerFormat => {}, + ContentDistributor => {}, + ContentGroupDescription => {}, + Director => {}, + DRM => {}, + DVDID => {}, + EncodedBy => {}, + EncodingSettings => {}, + EncodingTime => { Groups => { 2 => 'Time' }, PrintConv => '$self->ConvertDateTime($val)' }, + Genre => {}, + GenreID => {}, + InitialKey => {}, + ISRC => {}, + Language => {}, + Lyrics => {}, + Lyrics_Synchronised => {}, + MCDI => {}, + MediaClassPrimaryID => { ValueConv => 'Image::ExifTool::ASF::GetGUID($val)' }, + MediaClassSecondaryID => { ValueConv => 'Image::ExifTool::ASF::GetGUID($val)' }, + MediaCredits => {}, + MediaIsDelay => {}, + MediaIsFinale => {}, + MediaIsLive => {}, + MediaIsPremiere => {}, + MediaIsRepeat => {}, + MediaIsSAP => {}, + MediaIsStereo => {}, + MediaIsSubtitled => {}, + MediaIsTape => {}, + MediaNetworkAffiliation => {}, + MediaOriginalBroadcastDateTime => { + Groups => { 2 => 'Time' }, + ValueConv => '$val=~tr/-T/: /; $val', + PrintConv => '$self->ConvertDateTime($val)', + }, + MediaOriginalChannel => {}, + MediaStationCallSign => {}, + MediaStationName => {}, + ModifiedBy => {}, + Mood => {}, + OriginalAlbumTitle => {}, + OriginalArtist => {}, + OriginalFilename => 'OriginalFileName', + OriginalLyricist => {}, + OriginalReleaseTime => { + Groups => { 2 => 'Time' }, + ValueConv => '$val=~tr/-T/: /; $val', + PrintConv => '$self->ConvertDateTime($val)', + }, + OriginalReleaseYear => { Groups => { 2 => 'Time' } }, + ParentalRating => {}, + ParentalRatingReason => {}, + PartOfSet => {}, + PeakBitrate => { PrintConv => 'ConvertBitrate($val)' }, + Period => {}, + Picture => { + SubDirectory => { + TagTable => 'Image::ExifTool::ASF::Picture', + }, + }, + PlaylistDelay => {}, + Producer => {}, + PromotionURL => {}, + ProtectionType => {}, + Provider => {}, + ProviderCopyright => {}, + ProviderRating => {}, + ProviderStyle => {}, + Publisher => {}, + RadioStationName => {}, + RadioStationOwner => {}, + SharedUserRating => {}, + StreamTypeInfo => {}, + SubscriptionContentID => {}, + SubTitle => 'Subtitle', + SubTitleDescription => 'SubtitleDescription', + Text => {}, + ToolName => {}, + ToolVersion => {}, + Track => {}, + TrackNumber => {}, + UniqueFileIdentifier => {}, + UserWebURL => {}, + VideoClosedCaptioning => {}, + VideoFrameRate => {}, + VideoHeight => {}, + VideoWidth => {}, + WMADRCAverageReference => {}, + WMADRCAverageTarget => {}, + WMADRCPeakReference => {}, + WMADRCPeakTarget => {}, + WMCollectionGroupID => {}, + WMCollectionID => {}, + WMContentID => {}, + Writer => { Groups => { 2 => 'Author' } }, + Year => { Groups => { 2 => 'Time' } }, +); + +%Image::ExifTool::ASF::Picture = ( + PROCESS_PROC => \&ProcessPicture, + GROUPS => { 2 => 'Image' }, + 0 => { + Name => 'PictureType', + PrintConv => { # (Note: Duplicated in ID3, ASF and FLAC modules!) + 0 => 'Other', + 1 => '32x32 PNG Icon', + 2 => 'Other Icon', + 3 => 'Front Cover', + 4 => 'Back Cover', + 5 => 'Leaflet', + 6 => 'Media', + 7 => 'Lead Artist', + 8 => 'Artist', + 9 => 'Conductor', + 10 => 'Band', + 11 => 'Composer', + 12 => 'Lyricist', + 13 => 'Recording Studio or Location', + 14 => 'Recording Session', + 15 => 'Performance', + 16 => 'Capture from Movie or Video', + 17 => 'Bright(ly) Colored Fish', + 18 => 'Illustration', + 19 => 'Band Logo', + 20 => 'Publisher Logo', + }, + }, + 1 => 'PictureMIMEType', + 2 => 'PictureDescription', + 3 => { + Name => 'Picture', + Groups => { 2 => 'Preview' }, + Binary => 1, + }, +); + +%Image::ExifTool::ASF::FileProperties = ( + PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData, + GROUPS => { 2 => 'Video' }, + 0 => { + Name => 'FileID', + Format => 'binary[16]', + ValueConv => 'Image::ExifTool::ASF::GetGUID($val)', + }, + 16 => { Name => 'FileLength', Format => 'int64u' }, + 24 => { + Name => 'CreationDate', + Format => 'int64u', + Groups => { 2 => 'Time' }, + # time is in 100 ns intervals since 0:00 UTC Jan 1, 1601 + ValueConv => q{ # (89 leap years between 1601 and 1970) + my $t = $val / 1e7 - (((1970-1601)*365+89)*24*3600); + return Image::ExifTool::ConvertUnixTime($t) . 'Z'; + }, + PrintConv => '$self->ConvertDateTime($val)', + }, + 32 => { Name => 'DataPackets', Format => 'int64u' }, + 40 => { + Name => 'Duration', + Format => 'int64u', + Notes => 'called PlayDuration by the ASF spec', + Priority => 0, + ValueConv => '$val / 1e7', + PrintConv => 'ConvertDuration($val)', + }, + 48 => { + Name => 'SendDuration', + Format => 'int64u', + ValueConv => '$val / 1e7', + PrintConv => 'ConvertDuration($val)', + }, + 56 => { Name => 'Preroll', Format => 'int64u' }, + 64 => { Name => 'Flags', Format => 'int32u' }, + 68 => { Name => 'MinPacketSize',Format => 'int32u' }, + 72 => { Name => 'MaxPacketSize',Format => 'int32u' }, + 76 => { Name => 'MaxBitrate', Format => 'int32u', PrintConv => 'ConvertBitrate($val)' }, +); + +%Image::ExifTool::ASF::StreamProperties = ( + PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData, + GROUPS => { 2 => 'Video' }, + NOTES => 'Tags with index 54 and greater are conditional based on the StreamType.', + 0 => { + Name => 'StreamType', + Format => 'binary[16]', + RawConv => sub { # set ASF_STREAM_TYPE for use in conditional tags + my ($val, $et) = @_; + $$et{ASF_STREAM_TYPE} = $streamType{GetGUID($val)} || ''; + return $val; + }, + ValueConv => 'Image::ExifTool::ASF::GetGUID($val)', + PrintConv => \%streamType, + }, + 16 => { + Name => 'ErrorCorrectionType', + Format => 'binary[16]', + ValueConv => 'Image::ExifTool::ASF::GetGUID($val)', + PrintConv => \%errorCorrection, + }, + 32 => { + Name => 'TimeOffset', + Format => 'int64u', + ValueConv => '$val / 1e7', + PrintConv => '"$val s"', + }, + 48 => { + Name => 'StreamNumber', + Format => 'int16u', + PrintConv => '($val & 0x7f) . ($val & 0x8000 ? " (encrypted)" : "")', + }, + 54 => [ + { + Condition => '$self->{ASF_STREAM_TYPE} eq "Audio"', + Name => 'AudioCodecID', + Format => 'int16u', + PrintHex => 1, + SeparateTable => 'RIFF AudioEncoding', + PrintConv => \%Image::ExifTool::RIFF::audioEncoding, + }, + { + Condition => '$self->{ASF_STREAM_TYPE} =~ /^(Video|JFIF|Degradable JPEG)$/', + Name => 'ImageWidth', + Format => 'int32u', + }, + ], + 56 => { + Condition => '$self->{ASF_STREAM_TYPE} eq "Audio"', + Name => 'AudioChannels', + Format => 'int16u', + }, + 58 => [ + { + Condition => '$self->{ASF_STREAM_TYPE} eq "Audio"', + Name => 'AudioSampleRate', + Format => 'int32u', + }, + { + Condition => '$self->{ASF_STREAM_TYPE} =~ /^(Video|JFIF|Degradable JPEG)$/', + Name => 'ImageHeight', + Format => 'int32u', + }, + ], +); + +%Image::ExifTool::ASF::HeaderExtension = ( + PROCESS_PROC => \&ProcessASF, + '14E6A5CB-C672-4332-8399-A96952065B5A' => 'ExtendedStreamProps', + 'A08649CF-4775-4670-8A16-6E35357566CD' => 'AdvancedMutualExcl', + 'D1465A40-5A79-4338-B71B-E36B8FD6C249' => 'GroupMutualExclusion', + 'D4FED15B-88D3-454F-81F0-ED5C45999E24' => 'StreamPrioritization', + 'A69609E6-517B-11D2-B6AF-00C04FD908E9' => 'BandwidthSharing', + '7C4346A9-EFE0-4BFC-B229-393EDE415C85' => 'LanguageList', + 'C5F8CBEA-5BAF-4877-8467-AA8C44FA4CCA' => { + Name => 'Metadata', + SubDirectory => { + # have seen some tags same as ExtendedDescr, so use this table - PH + TagTable => 'Image::ExifTool::ASF::ExtendedDescr', + ProcessProc => \&ProcessMetadata, + }, + }, + '44231C94-9498-49D1-A141-1D134E457054' => { + Name => 'MetadataLibrary', + SubDirectory => { + # have seen some tags same as ExtendedDescr, so use this table - PH + TagTable => 'Image::ExifTool::ASF::ExtendedDescr', + ProcessProc => \&ProcessMetadata, + }, + }, + 'D6E229DF-35DA-11D1-9034-00A0C90349BE' => 'IndexParameters', + '6B203BAD-3F11-48E4-ACA8-D7613DE2CFA7' => 'TimecodeIndexParms', + '75B22630-668E-11CF-A6D9-00AA0062CE6C' => 'Compatibility', + '43058533-6981-49E6-9B74-AD12CB86D58C' => 'AdvancedContentEncryption', + 'ABD3D211-A9BA-11cf-8EE6-00C00C205365' => 'Reserved1', +); + +%Image::ExifTool::ASF::CodecList = ( + PROCESS_PROC => \&ProcessCodecList, + VideoCodecName => {}, + VideoCodecDescription => {}, + AudioCodecName => {}, + AudioCodecDescription => {}, + OtherCodecName => {}, + OtherCodecDescription => {}, +); + +#------------------------------------------------------------------------------ +# Generate GUID from 16 bytes of binary data +# Inputs: 0) data +# Returns: GUID +sub GetGUID($) +{ + # must do some byte swapping + my $val = shift; + return $val unless length($val) == 16; + my $buff = unpack('H*',pack('NnnNN',unpack('VvvNN',$val))); + $buff =~ s/(.{8})(.{4})(.{4})(.{4})/$1-$2-$3-$4-/; + return uc($buff); +} + +#------------------------------------------------------------------------------ +# Process ASF content description +# Inputs: 0) ExifTool object reference, 1) dirInfo ref, 2) tag table reference +# Returns: 1 on success +sub ProcessContentDescription($$$) +{ + my ($et, $dirInfo, $tagTablePtr) = @_; + my $dataPt = $$dirInfo{DataPt}; + my $dirLen = $$dirInfo{DirLen}; + return 0 if $dirLen < 10; + my @len = unpack('v5', $$dataPt); + my $pos = 10; + my $tag; + foreach $tag (0..4) { + my $len = shift @len; + next unless $len; + return 0 if $pos + $len > $dirLen; + my $val = $et->Decode(substr($$dataPt,$pos,$len),'UCS2','II'); + $et->HandleTag($tagTablePtr, $tag, $val); + $pos += $len; + } + return 1; +} + +#------------------------------------------------------------------------------ +# Process ASF content branding +# Inputs: 0) ExifTool object reference, 1) dirInfo ref, 2) tag table reference +# Returns: 1 on success +sub ProcessContentBranding($$$) +{ + my ($et, $dirInfo, $tagTablePtr) = @_; + my $dataPt = $$dirInfo{DataPt}; + my $dirLen = $$dirInfo{DirLen}; + return 0 if $dirLen < 40; + # decode banner image type + $et->HandleTag($tagTablePtr, 0, unpack('V', $$dataPt)); + # decode banner image, banner URL and copyright URL + my $pos = 4; + my $tag; + foreach $tag (1..3) { + return 0 if $pos + 4 > $dirLen; + my $size = unpack("x${pos}V", $$dataPt); + $pos += 4; + next unless $size; + return 0 if $pos + $size > $dirLen; + my $val = substr($$dataPt, $pos, $size); + $et->HandleTag($tagTablePtr, $tag, $val); + $pos += $size; + } + return 1; +} + +#------------------------------------------------------------------------------ +# Read ASF value +# Inputs: 0) ExifTool object ref, 1) data reference, 2) value offset, +# 3) format number, 4) size +# Returns: converted value +sub ReadASF($$$$$) +{ + my ($et, $dataPt, $pos, $format, $size) = @_; + my @vals; + if ($format == 0) { # unicode string + $vals[0] = $et->Decode(substr($$dataPt,$pos,$size),'UCS2','II'); + } elsif ($format == 2) { # 4-byte boolean + @vals = ReadValue($dataPt, $pos, 'int32u', undef, $size); + foreach (@vals) { + $_ = $_ ? 'True' : 'False'; + } + } elsif ($format == 3) { # int32u + @vals = ReadValue($dataPt, $pos, 'int32u', undef, $size); + } elsif ($format == 4) { # int64u + @vals = ReadValue($dataPt, $pos, 'int64u', undef, $size); + } elsif ($format == 5) { # int16u + @vals = ReadValue($dataPt, $pos, 'int16u', undef, $size); + } else { # any other format (including 1, byte array): return raw data + $vals[0] = substr($$dataPt,$pos,$size); + } + return join ' ', @vals; +} + +#------------------------------------------------------------------------------ +# Process extended content description +# Inputs: 0) ExifTool object reference, 1) dirInfo ref, 2) tag table reference +# Returns: 1 on success +sub ProcessExtendedContentDescription($$$) +{ + my ($et, $dirInfo, $tagTablePtr) = @_; + my $dataPt = $$dirInfo{DataPt}; + my $dirLen = $$dirInfo{DirLen}; + return 0 if $dirLen < 2; + my $count = Get16u($dataPt, 0); + $et->VerboseDir($dirInfo, $count); + my $pos = 2; + my $i; + for ($i=0; $i<$count; ++$i) { + return 0 if $pos + 6 > $dirLen; + my $nameLen = unpack("x${pos}v", $$dataPt); + $pos += 2; + return 0 if $pos + $nameLen + 4 > $dirLen; + my $tag = Image::ExifTool::Decode(undef,substr($$dataPt,$pos,$nameLen),'UCS2','II','Latin'); + $tag =~ s/^WM\///; # remove leading "WM/" + $pos += $nameLen; + my ($dType, $dLen) = unpack("x${pos}v2", $$dataPt); + $pos += 4; + return 0 if $pos + $dLen > $dirLen; + my $val = ReadASF($et,$dataPt,$pos,$dType,$dLen); + $et->HandleTag($tagTablePtr, $tag, $val, + DataPt => $dataPt, + Start => $pos, + Size => $dLen, + ); + $pos += $dLen; + } + return 1; +} + +#------------------------------------------------------------------------------ +# Process ASF metadata library (similar to ProcessExtendedContentDescription above) +# Inputs: 0) ExifTool object reference, 1) dirInfo ref, 2) tag table reference +# Returns: 1 on success +sub ProcessMetadata($$$) +{ + my ($et, $dirInfo, $tagTablePtr) = @_; + my $dataPt = $$dirInfo{DataPt}; + my $dirLen = $$dirInfo{DirLen}; + return 0 if $dirLen < 2; + my $count = Get16u($dataPt, 0); + $et->VerboseDir($dirInfo, $count); + my $pos = 2; + my $i; + for ($i=0; $i<$count; ++$i) { + return 0 if $pos + 12 > $dirLen; + my ($index, $stream, $nameLen, $dType, $dLen) = unpack("x${pos}v4V", $$dataPt); + $pos += 12; + return 0 if $pos + $nameLen + $dLen > $dirLen; + my $tag = Image::ExifTool::Decode(undef,substr($$dataPt,$pos,$nameLen),'UCS2','II','Latin'); + $tag =~ s/^WM\///; # remove leading "WM/" + $pos += $nameLen; + my $val = ReadASF($et,$dataPt,$pos,$dType,$dLen); + $et->HandleTag($tagTablePtr, $tag, $val, + DataPt => $dataPt, + Start => $pos, + Size => $dLen, + ); + $pos += $dLen; + } + return 1; +} + +#------------------------------------------------------------------------------ +# Process WM/Picture preview +# Inputs: 0) ExifTool object reference, 1) dirInfo ref, 2) tag table reference +# Returns: 1 on success +sub ProcessPicture($$$) +{ + my ($et, $dirInfo, $tagTablePtr) = @_; + my $dataPt = $$dirInfo{DataPt}; + my $dirStart = $$dirInfo{DirStart}; + my $dirLen = $$dirInfo{DirLen}; + return 0 unless $dirLen > 9; + # extract picture type and length + my ($type, $picLen) = unpack("x${dirStart}CV", $$dataPt); + $et->VerboseDir('Picture'); + $et->HandleTag($tagTablePtr, 0, $type); + # extract mime type and description strings (null-terminated unicode strings) + my $n = $dirLen - 5 - $picLen; + return 0 if $n & 0x01 or $n < 4; + my $str = substr($$dataPt, $dirStart+5, $n); + if ($str =~ /^((?:..)*?)\0\0((?:..)*?)\0\0/s) { + my ($mime, $desc) = ($1, $2); + $et->HandleTag($tagTablePtr, 1, $et->Decode($mime,'UCS2','II')); + $et->HandleTag($tagTablePtr, 2, $et->Decode($desc,'UCS2','II')) if length $desc; + } + $et->HandleTag($tagTablePtr, 3, substr($$dataPt, $dirStart+5+$n, $picLen)); + return 1; +} + +#------------------------------------------------------------------------------ +# Process codec list +# Inputs: 0) ExifTool object reference, 1) dirInfo ref, 2) tag table reference +# Returns: 1 on success +sub ProcessCodecList($$$) +{ + my ($et, $dirInfo, $tagTablePtr) = @_; + my $dataPt = $$dirInfo{DataPt}; + my $dirLen = $$dirInfo{DirLen}; + return 0 if $dirLen < 20; + my $count = Get32u($dataPt, 16); + $et->VerboseDir($dirInfo, $count); + my $pos = 20; + my $i; + my %codecType = ( 1 => 'Video', 2 => 'Audio' ); + for ($i=0; $i<$count; ++$i) { + return 0 if $pos + 8 > $dirLen; + my $type = ($codecType{Get16u($dataPt, $pos)} || 'Other') . 'Codec'; + # stupid Windows programmers: these lengths are in characters (others are in bytes) + my $nameLen = Get16u($dataPt, $pos + 2) * 2; + $pos += 4; + return 0 if $pos + $nameLen + 2 > $dirLen; + my $name = $et->Decode(substr($$dataPt,$pos,$nameLen),'UCS2','II'); + $et->HandleTag($tagTablePtr, "${type}Name", $name); + my $descLen = Get16u($dataPt, $pos + $nameLen) * 2; + $pos += $nameLen + 2; + return 0 if $pos + $descLen + 2 > $dirLen; + my $desc = $et->Decode(substr($$dataPt,$pos,$descLen),'UCS2','II'); + $et->HandleTag($tagTablePtr, "${type}Description", $desc); + my $infoLen = Get16u($dataPt, $pos + $descLen); + $pos += $descLen + 2 + $infoLen; + } + return 1; +} + +#------------------------------------------------------------------------------ +# Extract information from a ASF file +# Inputs: 0) ExifTool object reference, 1) dirInfo reference, 2) tag table ref +# Returns: 1 on success, 0 if this wasn't a valid ASF file +sub ProcessASF($$;$) +{ + my ($et, $dirInfo, $tagTablePtr) = @_; + my $raf = $$dirInfo{RAF}; + my $verbose = $et->Options('Verbose'); + my $rtnVal = 0; + my $pos = 0; + my ($buff, $err, @parentTable, @childEnd); + + for (;;) { + last unless $raf->Read($buff, 24) == 24; + $pos += 24; + my $tag = GetGUID(substr($buff,0,16)); + unless ($tagTablePtr) { + # verify this is a valid ASF file + last unless $tag eq '75B22630-668E-11CF-A6D9-00AA0062CE6C'; + my $fileType = $$et{FILE_EXT}; + $fileType = 'ASF' unless $fileType and $fileType =~ /^(ASF|WMV|WMA|DIVX)$/; + $et->SetFileType($fileType); + SetByteOrder('II'); + $tagTablePtr = GetTagTable('Image::ExifTool::ASF::Main'); + $rtnVal = 1; + } + my $size = Image::ExifTool::Get64u(\$buff, 16) - 24; + if ($size < 0) { + $err = 'Invalid ASF object size'; + last; + } + if ($size > 0x7fffffff) { + if ($size > 0x7fffffff * 4294967296) { + $err = 'Invalid ASF object size'; + } elsif ($et->Options('LargeFileSupport')) { + if ($raf->Seek($size, 1)) { + $et->VPrint(0, " Skipped large ASF object ($size bytes)\n"); + $pos += $size; + next; + } + $err = 'Error seeking past large ASF object'; + } else { + $err = 'Large ASF objects not supported (LargeFileSupport not set)'; + } + last; + } + # go back to parent tag table if done with previous children + if (@childEnd and $pos >= $childEnd[-1]) { + pop @childEnd; + $tagTablePtr = pop @parentTable; + $$et{INDENT} = substr($$et{INDENT},0,-2); + } + my $tagInfo = $et->GetTagInfo($tagTablePtr, $tag); + $verbose and $et->VerboseInfo($tag, $tagInfo); + if ($tagInfo) { + my $subdir = $$tagInfo{SubDirectory}; + if ($subdir) { + my $subTable = GetTagTable($$subdir{TagTable}); + if ($$subTable{PROCESS_PROC} eq \&ProcessASF) { + if (defined $$subdir{Size}) { + my $s = $$subdir{Size}; + if ($verbose > 2) { + $raf->Read($buff, $s) == $s or $err = 'Truncated file', last; + $et->VerboseDump(\$buff); + } elsif (not $raf->Seek($s, 1)) { + $err = 'Seek error'; + last; + } + # continue processing linearly using subTable + push @parentTable, $tagTablePtr; + push @childEnd, $pos + $size; + $tagTablePtr = $subTable; + $pos += $$subdir{Size}; + if ($verbose) { + $$et{INDENT} .= '| '; + $et->VerboseDir($$tagInfo{Name}); + } + next; + } + } elsif ($raf->Read($buff, $size) == $size) { + my %subdirInfo = ( + DataPt => \$buff, + DirStart => 0, + DirLen => $size, + DirName => $$tagInfo{Name}, + ); + $et->VerboseDump(\$buff) if $verbose > 2; + unless ($et->ProcessDirectory(\%subdirInfo, $subTable, $$subdir{ProcessProc})) { + $et->Warn("Error processing $$tagInfo{Name} directory"); + } + $pos += $size; + next; + } else { + $err = 'Unexpected end of file'; + last; + } + } + } + if ($verbose > 2) { + $raf->Read($buff, $size) == $size or $err = 'Truncated file', last; + $et->VerboseDump(\$buff); + } elsif (not $raf->Seek($size, 1)) { # skip the block + $err = 'Seek error'; + last; + } + $pos += $size; + } + $err and $et->Warn($err); + return $rtnVal; +} + +1; # end + +__END__ + +=head1 NAME + +Image::ExifTool::ASF - Read ASF/WMA/WMV meta information + +=head1 SYNOPSIS + +This module is used by Image::ExifTool + +=head1 DESCRIPTION + +This module contains routines required by Image::ExifTool to extract +information from Microsoft Advanced Systems Format (ASF) files, including +Windows Media Audio (WMA) and Windows Media Video (WMV) files. + +=head1 AUTHOR + +Copyright 2003-2019, Phil Harvey (phil at owl.phy.queensu.ca) + +This library is free software; you can redistribute it and/or modify it +under the same terms as Perl itself. + +=head1 REFERENCES + +=over 4 + +=item L + +=back + +=head1 SEE ALSO + +L, +L + +=cut + diff --git a/lib/Image/ExifTool/Apple.pm b/lib/Image/ExifTool/Apple.pm new file mode 100644 index 0000000..a3208dd --- /dev/null +++ b/lib/Image/ExifTool/Apple.pm @@ -0,0 +1,161 @@ +#------------------------------------------------------------------------------ +# File: Apple.pm +# +# Description: Apple EXIF maker notes tags +# +# Revisions: 2013-09-13 - P. Harvey Created +# +# References: 1) http://www.photoinvestigator.co/blog/the-mystery-of-maker-apple-metadata/ +#------------------------------------------------------------------------------ + +package Image::ExifTool::Apple; + +use strict; +use vars qw($VERSION); +use Image::ExifTool::Exif; +use Image::ExifTool::PLIST; + +$VERSION = '1.04'; + +# Apple iPhone metadata (ref PH) +%Image::ExifTool::Apple::Main = ( + WRITE_PROC => \&Image::ExifTool::Exif::WriteExif, + CHECK_PROC => \&Image::ExifTool::Exif::CheckExif, + WRITABLE => 1, + GROUPS => { 0 => 'MakerNotes', 2 => 'Image' }, + NOTES => 'Tags extracted from the maker notes of iPhone images.', + # 0x0001 - int32s: seen 0,1,2,3,4,9 + # 0x0002 - binary plist with a single data object of size 512 bytes (iPhone5s) + 0x0003 => { + Name => 'RunTime', # (includes time plugged in, but not when suspended, ref 1) + SubDirectory => { TagTable => 'Image::ExifTool::Apple::RunTime' }, + }, + # 0x0004 - int32s: normally 1, but 0 for low-light images + # 0x0005 - int32s: seen values 113-247, and 100 for blank images + # 0x0006 - int32s: seen values 27-258, and 20 for blank images + # 0x0007 - int32s: seen 1 + 0x0008 => { #1 + Name => 'AccelerationVector', + Groups => { 2 => 'Camera' }, + Writable => 'rational64s', + Count => 3, + # Note: the directions are contrary to the Apple documentation (which have the + # signs of all axes reversed -- apparently the Apple geeks aren't very good + # with basic physics, and don't understand the concept of acceleration. See + # http://nscookbook.com/2013/03/ios-programming-recipe-19-using-core-motion-to-access-gyro-and-accelerometer/ + # for one of the few correct descriptions of this). Note that this leads to + # a left-handed coordinate system for acceleration. + Notes => q{ + XYZ coordinates of the acceleration vector in units of g. As viewed from + the front of the phone, positive X is toward the left side, positive Y is + toward the bottom, and positive Z points into the face of the phone + }, + }, + # 0x0009 - int32s: seen 19,275,531,4371 + 0x000a => { + Name => 'HDRImageType', + Writable => 'int32s', + PrintConv => { + # 2 => ? (iPad mini 2) + 3 => 'HDR Image', + 4 => 'Original Image', + }, + }, + 0x000b => { + Name => 'BurstUUID', + Writable => 'string', + Notes => 'unique ID for all images in a burst', + }, + # 0x000c - rational64s[2]: eg) "0.1640625 0.19921875" + # 0x000d - int32s: 0,1,6,20,24,32,40 + # 0x000e - int32s: 0,1,4,12 (Orienation? 0=landscape? 4=portrait? ref 1) + # 0x000f - int32s: 2,3 + # 0x0010 - int32s: 1 + 0x0011 => { + Name => 'ContentIdentifier', #forum8750 + Writable => 'string', + }, + # 0x0014 - int32s: 1,2,3,4,5 (iPhone 6s, iOS 6.1) + 0x0015 => { + Name => 'ImageUniqueID', + Writable => 'string', + }, + # 0x0016 - string[29]: "AXZ6pMTOh2L+acSh4Kg630XCScoO\0" + # 0x0017 - int32s: 0,8192 + # 0x0019 - int32s: 0,2,128 + # 0x001a - string[6]: "q825s\0" + # 0x001f - int32s: 0 +); + +# PLIST-format CMTime structure (ref PH) +# (CMTime ref https://developer.apple.com/library/ios/documentation/CoreMedia/Reference/CMTime/Reference/reference.html) +%Image::ExifTool::Apple::RunTime = ( + PROCESS_PROC => \&Image::ExifTool::PLIST::ProcessBinaryPLIST, + GROUPS => { 0 => 'MakerNotes', 2 => 'Image' }, + NOTES => q{ + This PLIST-format information contains the elements of a CMTime structure + representing the amount of time the phone has been running since the last + boot, not including standby time. + }, + timescale => { Name => 'RunTimeScale' }, # (seen 1000000000 --> ns) + epoch => { Name => 'RunTimeEpoch' }, # (seen 0) + value => { Name => 'RunTimeValue' }, # (should divide by RunTimeScale to get seconds) + flags => { + Name => 'RunTimeFlags', + PrintConv => { BITMASK => { + 0 => 'Valid', + 1 => 'Has been rounded', + 2 => 'Positive infinity', + 3 => 'Negative infinity', + 4 => 'Indefinite', + }}, + }, +); + +# Apple composite tags +%Image::ExifTool::Apple::Composite = ( + GROUPS => { 2 => 'Camera' }, + RunTimeSincePowerUp => { + Require => { + 0 => 'Apple:RunTimeValue', + 1 => 'Apple:RunTimeScale', + }, + ValueConv => '$val[1] ? $val[0] / $val[1] : undef', + PrintConv => 'ConvertDuration($val)', + }, +); + +# add our composite tags +Image::ExifTool::AddCompositeTags('Image::ExifTool::Apple'); + + +1; # end + +__END__ + +=head1 NAME + +Image::ExifTool::Apple - Apple EXIF maker notes tags + +=head1 SYNOPSIS + +This module is loaded automatically by Image::ExifTool when required. + +=head1 DESCRIPTION + +This module contains definitions required by Image::ExifTool to interpret +Apple maker notes in EXIF information. + +=head1 AUTHOR + +Copyright 2003-2019, Phil Harvey (phil at owl.phy.queensu.ca) + +This library is free software; you can redistribute it and/or modify it +under the same terms as Perl itself. + +=head1 SEE ALSO + +L, +L + +=cut diff --git a/lib/Image/ExifTool/Audible.pm b/lib/Image/ExifTool/Audible.pm new file mode 100644 index 0000000..13aa627 --- /dev/null +++ b/lib/Image/ExifTool/Audible.pm @@ -0,0 +1,317 @@ +#------------------------------------------------------------------------------ +# File: Audible.pm +# +# Description: Read metadata from Audible audio books +# +# Revisions: 2015/04/05 - P. Harvey Created +# +# References: 1) https://github.com/jteeuwen/audible +# 2) https://code.google.com/p/pyaudibletags/ +# 3) http://wiki.multimedia.cx/index.php?title=Audible_Audio +#------------------------------------------------------------------------------ + +package Image::ExifTool::Audible; + +use strict; +use vars qw($VERSION); +use Image::ExifTool qw(:DataAccess :Utils); + +$VERSION = '1.02'; + +sub ProcessAudible_meta($$$); +sub ProcessAudible_cvrx($$$); + +%Image::ExifTool::Audible::Main = ( + GROUPS => { 2 => 'Audio' }, + NOTES => q{ + ExifTool will extract any information found in the metadata dictionary of + Audible .AA files, even if not listed in the table below. + }, + # tags found in the metadata dictionary (chunk 2) + pubdate => { Name => 'PublishDate', Groups => { 2 => 'Time' } }, + pub_date_start => { Name => 'PublishDateStart', Groups => { 2 => 'Time' } }, + author => { Name => 'Author', Groups => { 2 => 'Author' } }, + copyright => { Name => 'Copyright', Groups => { 2 => 'Author' } }, + # also seen (ref PH): + # product_id, parent_id, title, provider, narrator, price, description, + # long_description, short_title, is_aggregation, title_id, codec, HeaderSeed, + # EncryptedBlocks, HeaderKey, license_list, CPUType, license_count, <12 hex digits>, + # parent_short_title, parent_title, aggregation_id, short_description, user_alias + + # information extracted from other chunks + _chapter_count => { Name => 'ChapterCount' }, # from chunk 6 + _cover_art => { # from chunk 11 + Name => 'CoverArt', + Groups => { 2 => 'Preview' }, + Binary => 1, + }, +); + +# 'tags' atoms observed in Audible .m4b audio books (ref PH) +%Image::ExifTool::Audible::tags = ( + GROUPS => { 0 => 'QuickTime', 2 => 'Audio' }, + NOTES => 'Information found in "tags" atom of Audible M4B audio books.', + meta => { + Name => 'Audible_meta', + SubDirectory => { TagTable => 'Image::ExifTool::Audible::meta' }, + }, + cvrx => { + Name => 'Audible_cvrx', + SubDirectory => { TagTable => 'Image::ExifTool::Audible::cvrx' }, + }, + tseg => { + Name => 'Audible_tseg', + SubDirectory => { TagTable => 'Image::ExifTool::Audible::tseg' }, + }, +); + +# 'meta' information observed in Audible .m4b audio books (ref PH) +%Image::ExifTool::Audible::meta = ( + PROCESS_PROC => \&ProcessAudible_meta, + GROUPS => { 0 => 'QuickTime', 2 => 'Audio' }, + NOTES => 'Information found in Audible M4B "meta" atom.', + Album => 'Album', + ALBUMARTIST => { Name => 'AlbumArtist', Groups => { 2 => 'Author' } }, + Artist => { Name => 'Artist', Groups => { 2 => 'Author' } }, + Comment => 'Comment', + Genre => 'Genre', + itunesmediatype => { Name => 'iTunesMediaType', Description => 'iTunes Media Type' }, + SUBTITLE => 'Subtitle', + Title => 'Title', + TOOL => 'CreatorTool', + Year => { Name => 'Year', Groups => { 2 => 'Time' } }, + track => 'ChapterName', # (found in 'meta' of 'tseg' atom) +); + +# 'cvrx' information observed in Audible .m4b audio books (ref PH) +%Image::ExifTool::Audible::cvrx = ( + PROCESS_PROC => \&ProcessAudible_cvrx, + GROUPS => { 0 => 'QuickTime', 2 => 'Audio' }, + NOTES => 'Audible cover art information in M4B audio books.', + VARS => { NO_ID => 1 }, + CoverArtType => 'CoverArtType', + CoverArt => { + Name => 'CoverArt', + Groups => { 2 => 'Preview' }, + Binary => 1, + }, +); + +# 'tseg' information observed in Audible .m4b audio books (ref PH) +%Image::ExifTool::Audible::tseg = ( + GROUPS => { 0 => 'QuickTime', 2 => 'Audio' }, + tshd => { + Name => 'ChapterNumber', + Format => 'int32u', + ValueConv => '$val + 1', # start counting from 1 + }, + meta => { + Name => 'Audible_meta2', + SubDirectory => { TagTable => 'Image::ExifTool::Audible::meta' }, + }, +); + +#------------------------------------------------------------------------------ +# Process Audible 'meta' tags from M4B files (ref PH) +# Inputs: 0) ExifTool object ref, 1) dirInfo ref, 2) tag table ref +# Returns: 1 on success +sub ProcessAudible_meta($$$) +{ + my ($et, $dirInfo, $tagTablePtr) = @_; + my $dataPt = $$dirInfo{DataPt}; + my $dataPos = $$dirInfo{DataPos}; + my $dirLen = length $$dataPt; + return 0 if $dirLen < 4; + my $num = Get32u($dataPt, 0); + $et->VerboseDir('Audible_meta', $num); + my $pos = 4; + my $index; + for ($index=0; $index<$num; ++$index) { + last if $pos + 3 > $dirLen; + my $unk = Get8u($dataPt, $pos); # ? (0x80 or 0x00) + last unless $unk eq 0x80 or $unk eq 0x00; + my $len = Get16u($dataPt, $pos + 1); # tag length + $pos += 3; + last if $pos + $len + 6 > $dirLen or not $len; + my $tag = substr($$dataPt, $pos, $len); # tag ID + my $ver = Get16u($dataPt, $pos + $len); # version? + last unless $ver eq 0x0001; + my $size = Get32u($dataPt, $pos + $len + 2);# data size + $pos += $len + 6; + last if $pos + $size > $dirLen; + my $val = $et->Decode(substr($$dataPt, $pos, $size), 'UTF8'); + unless ($$tagTablePtr{$tag}) { + my $name = Image::ExifTool::MakeTagName(($tag =~ /[a-z]/) ? $tag : lc($tag)); + AddTagToTable($tagTablePtr, $tag, { Name => $name }); + } + $et->HandleTag($tagTablePtr, $tag, $val, + DataPt => $dataPt, + DataPos => $dataPos, + Start => $pos, + Size => $size, + Index => $index, + ); + $pos += $size; + } + return 1; +} + +#------------------------------------------------------------------------------ +# Process Audible 'cvrx' cover art atom from M4B files (ref PH) +# Inputs: 0) ExifTool object ref, 1) dirInfo ref, 2) tag table ref +# Returns: 1 on success +sub ProcessAudible_cvrx($$$) +{ + my ($et, $dirInfo, $tagTablePtr) = @_; + my $dataPt = $$dirInfo{DataPt}; + my $dataPos = $$dirInfo{DataPos}; + my $dirLen = length $$dataPt; + return 0 if 0x0a > $dirLen; + my $len = Get16u($dataPt, 0x08); + return 0 if 0x0a + $len + 6 > $dirLen; + my $size = Get32u($dataPt, 0x0a + $len + 2); + return 0 if 0x0a + $len + 6 + $size > $dirLen; + $et->VerboseDir('Audible_cvrx', undef, $dirLen); + $et->HandleTag($tagTablePtr, 'CoverArtType', undef, + DataPt => $dataPt, + DataPos => $dataPos, + Start => 0x0a, + Size => $len, + ); + $et->HandleTag($tagTablePtr, 'CoverArt', undef, + DataPt => $dataPt, + DataPos => $dataPos, + Start => 0x0a + $len + 6, + Size => $size, + ); + return 1; +} + +#------------------------------------------------------------------------------ +# Read information from an Audible .AA file +# Inputs: 0) ExifTool ref, 1) dirInfo ref +# Returns: 1 on success, 0 if this wasn't a valid AA file +sub ProcessAA($$) +{ + my ($et, $dirInfo) = @_; + my $raf = $$dirInfo{RAF}; + my ($buff, $toc, $entry, $i); + + # check magic number + return 0 unless $raf->Read($buff, 16) == 16 and $buff=~/^.{4}\x57\x90\x75\x36/s; + # check file size + if (defined $$et{VALUE}{FileSize}) { + # first 4 bytes of the file should be the filesize + unpack('N', $buff) == $$et{VALUE}{FileSize} or return 0; + } + $et->SetFileType(); + SetByteOrder('MM'); + my $bytes = 12 * Get32u(\$buff, 8); # table of contents size in bytes + $bytes > 0xc00 and $et->Warn('Invalid TOC'), return 1; + # read the table of contents + $raf->Read($toc, $bytes) == $bytes or $et->Warn('Truncated TOC'), return 1; + my $tagTablePtr = GetTagTable('Image::ExifTool::Audible::Main'); + # parse table of contents (in $toc) + for ($entry=0; $entry<$bytes; $entry+=12) { + my $type = Get32u(\$toc, $entry); + next unless $type == 2 or $type == 6 or $type == 11; + my $offset = Get32u(\$toc, $entry + 4); + my $length = Get32u(\$toc, $entry + 8) or next; + $raf->Seek($offset, 0) or $et->Warn("Chunk $type seek error"), last; + if ($type == 6) { # offset table + next if $length < 4 or $raf->Read($buff, 4) != 4; # only read the chapter count + $et->HandleTag($tagTablePtr, '_chapter_count', Get32u(\$buff, 0)); + next; + } + # read the chunk + $length > 100000000 and $et->Warn("Chunk $type too big"), next; + $raf->Read($buff, $length) == $length or $et->Warn("Chunk $type read error"), last; + if ($type == 11) { # cover art + next if $length < 8; + my $len = Get32u(\$buff, 0); + my $off = Get32u(\$buff, 4); + next if $off < $offset + 8 or $off - $offset + $len > $length; + $et->HandleTag($tagTablePtr, '_cover_art', substr($buff, $off-$offset, $len)); + next; + } + # parse metadata dictionary (in $buff) + $length < 4 and $et->Warn('Bad dictionary'), next; + my $num = Get32u(\$buff, 0); + $num > 0x200 and $et->Warn('Bad dictionary count'), next; + my $pos = 4; # dictionary starts immediately after count + require Image::ExifTool::HTML; # (for UnescapeHTML) + $et->VerboseDir('Audible Metadata', $num); + for ($i=0; $i<$num; ++$i) { + my $tagPos = $pos + 9; # position of tag string + $tagPos > $length and $et->Warn('Truncated dictionary'), last; + # (1 unknown byte ignored at start of each dictionary entry) + my $tagLen = Get32u(\$buff, $pos + 1); # tag string length + my $valLen = Get32u(\$buff, $pos + 5); # value string length + my $valPos = $tagPos + $tagLen; # position of value string + my $nxtPos = $valPos + $valLen; # position of next entry + $nxtPos > $length and $et->Warn('Bad dictionary entry'), last; + my $tag = substr($buff, $tagPos, $tagLen); + my $val = substr($buff, $valPos, $valLen); + unless ($$tagTablePtr{$tag}) { + my $name = Image::ExifTool::MakeTagName($tag); + $name =~ s/_(.)/\U$1/g; # change from underscore-separated to mixed case + AddTagToTable($tagTablePtr, $tag, { Name => $name }); + } + # unescape HTML character references and convert from UTF-8 + $val = $et->Decode(Image::ExifTool::HTML::UnescapeHTML($val), 'UTF8'); + $et->HandleTag($tagTablePtr, $tag, $val, + DataPos => $offset, + DataPt => \$buff, + Start => $valPos, + Size => $valLen, + Index => $i, + ); + $pos = $nxtPos; # step to next dictionary entry + } + } + return 1; +} + +1; # end + +__END__ + +=head1 NAME + +Image::ExifTool::Audible - Read meta information from Audible audio books + +=head1 SYNOPSIS + +This module is used by Image::ExifTool + +=head1 DESCRIPTION + +This module contains definitions required by Image::ExifTool to read meta +information from Audible audio books. + +=head1 AUTHOR + +Copyright 2003-2019, Phil Harvey (phil at owl.phy.queensu.ca) + +This library is free software; you can redistribute it and/or modify it +under the same terms as Perl itself. + +=head1 REFERENCES + +=over 4 + +=item L + +=item L + +=item L + +=back + +=head1 SEE ALSO + +L, +L + +=cut + diff --git a/lib/Image/ExifTool/BMP.pm b/lib/Image/ExifTool/BMP.pm new file mode 100644 index 0000000..a6b183a --- /dev/null +++ b/lib/Image/ExifTool/BMP.pm @@ -0,0 +1,361 @@ +#------------------------------------------------------------------------------ +# File: BMP.pm +# +# Description: Read BMP meta information +# +# Revisions: 07/16/2005 - P. Harvey Created +# +# References: 1) http://www.fortunecity.com/skyscraper/windows/364/bmpffrmt.html +# 2) http://www.fourcc.org/rgb.php +# 3) https://msdn.microsoft.com/en-us/library/dd183381(v=vs.85).aspx +#------------------------------------------------------------------------------ + +package Image::ExifTool::BMP; + +use strict; +use vars qw($VERSION); +use Image::ExifTool qw(:DataAccess :Utils); + +$VERSION = '1.09'; + +# conversions for fixed-point 2.30 format values +my %fixed2_30 = ( + ValueConv => q{ + my @a = split ' ', $val; + $_ /= 0x40000000 foreach @a; + "@a"; + }, + PrintConv => q{ + my @a = split ' ', $val; + $_ = sprintf('%.6f', $_) foreach @a; + "@a"; + }, +); + +# BMP chunks +%Image::ExifTool::BMP::Main = ( + PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData, + GROUPS => { 0 => 'File', 1 => 'File', 2 => 'Image' }, + NOTES => q{ + There really isn't much meta information in a BMP file as such, just a bit + of image related information. + }, + 0 => { + Name => 'BMPVersion', + Format => 'int32u', + Notes => q{ + this is actually the size of the BMP header, but used to determine the BMP + version + }, + RawConv => '$$self{BMPVersion} = $val', + PrintConv => { + 40 => 'Windows V3', + 68 => 'AVI BMP structure?', #PH (seen in AVI movies from some Casio and Nikon cameras) + 108 => 'Windows V4', + 124 => 'Windows V5', + }, + }, + 4 => { + Name => 'ImageWidth', + Format => 'int32u', + }, + 8 => { + Name => 'ImageHeight', + Format => 'int32s', # (negative when stored in top-to-bottom order) + ValueConv => 'abs($val)', + }, + 12 => { + Name => 'Planes', + Format => 'int16u', + # values: 0,1,4,8,16,24,32 + }, + 14 => { + Name => 'BitDepth', + Format => 'int16u', + }, + 16 => { + Name => 'Compression', + Format => 'int32u', + RawConv => '$$self{BMPCompression} = $val', + # (formatted as string[4] for some values in AVI images) + ValueConv => '$val > 256 ? unpack("A4",pack("V",$val)) : $val', + PrintConv => { + 0 => 'None', + 1 => '8-Bit RLE', + 2 => '4-Bit RLE', + 3 => 'Bitfields', + 4 => 'JPEG', #2 + 5 => 'PNG', #2 + # pass through ASCII video compression codec ID's + OTHER => sub { + my $val = shift; + # convert non-ascii characters + $val =~ s/([\0-\x1f\x7f-\xff])/sprintf('\\x%.2x',ord $1)/eg; + return $val; + }, + }, + }, + 20 => { + Name => 'ImageLength', + Format => 'int32u', + RawConv => '$$self{BMPImageLength} = $val', + }, + 24 => { + Name => 'PixelsPerMeterX', + Format => 'int32u', + }, + 28 => { + Name => 'PixelsPerMeterY', + Format => 'int32u', + }, + 32 => { + Name => 'NumColors', + Format => 'int32u', + PrintConv => '$val ? $val : "Use BitDepth"', + }, + 36 => { + Name => 'NumImportantColors', + Format => 'int32u', + Hook => '$varSize += $size if $$self{BMPVersion} == 68', # (the rest is invalid for AVI BMP's) + PrintConv => '$val ? $val : "All"', + }, + 40 => { + Name => 'RedMask', + Format => 'int32u', + PrintConv => 'sprintf("0x%.8x",$val)', + }, + 44 => { + Name => 'GreenMask', + Format => 'int32u', + PrintConv => 'sprintf("0x%.8x",$val)', + }, + 48 => { + Name => 'BlueMask', + Format => 'int32u', + PrintConv => 'sprintf("0x%.8x",$val)', + }, + 52 => { + Name => 'AlphaMask', + Format => 'int32u', + PrintConv => 'sprintf("0x%.8x",$val)', + }, + 56 => { + Name => 'ColorSpace', + Format => 'undef[4]', + RawConv => '$$self{BMPColorSpace} = $val =~ /\0/ ? Get32u(\$val, 0) : pack("N",unpack("V",$val))', + PrintConv => { + 0 => 'Calibrated RGB', + 1 => 'Device RGB', + 2 => 'Device CMYK', + LINK => 'Linked Color Profile', + MBED => 'Embedded Color Profile', + sRGB => 'sRGB', + 'Win ' => 'Windows Color Space', + }, + }, + 60 => { + Name => 'RedEndpoint', + Condition => '$$self{BMPColorSpace} eq "0"', + Format => 'int32u[3]', + %fixed2_30, + }, + 72 => { + Name => 'GreenEndpoint', + Condition => '$$self{BMPColorSpace} eq "0"', + Format => 'int32u[3]', + %fixed2_30, + }, + 84 => { + Name => 'BlueEndpoint', + Condition => '$$self{BMPColorSpace} eq "0"', + Format => 'int32u[3]', + %fixed2_30, + }, + 96 => { + Name => 'GammaRed', + Condition => '$$self{BMPColorSpace} eq "0"', + Format => 'fixed32u', + }, + 100 => { + Name => 'GammaGreen', + Condition => '$$self{BMPColorSpace} eq "0"', + Format => 'fixed32u', + }, + 104 => { + Name => 'GammaBlue', + Condition => '$$self{BMPColorSpace} eq "0"', + Format => 'fixed32u', + }, + 108 => { + Name => 'RenderingIntent', + Format => 'int32u', + PrintConv => { + 1 => 'Graphic (LCS_GM_BUSINESS)', + 2 => 'Proof (LCS_GM_GRAPHICS)', + 4 => 'Picture (LCS_GM_IMAGES)', + 8 => 'Absolute Colorimetric (LCS_GM_ABS_COLORIMETRIC)', + }, + }, + 112 => { + Name => 'ProfileDataOffset', + Condition => '$$self{BMPColorSpace} eq "LINK" or $$self{BMPColorSpace} eq "MBED"', + Format => 'int32u', + RawConv => '$$self{BMPProfileOffset} = $val', + }, + 116 => { + Name => 'ProfileSize', + Condition => '$$self{BMPColorSpace} eq "LINK" or $$self{BMPColorSpace} eq "MBED"', + Format => 'int32u', + RawConv => '$$self{BMPProfileSize} = $val', + }, + # 120 - reserved +); + +# OS/2 12-byte bitmap header (ref http://www.fileformat.info/format/bmp/egff.htm) +%Image::ExifTool::BMP::OS2 = ( + PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData, + GROUPS => { 0 => 'File', 1 => 'File', 2 => 'Image' }, + NOTES => 'Information extracted from OS/2-format BMP images.', + 0 => { + Name => 'BMPVersion', + Format => 'int32u', + Notes => 'again, the header size is used to determine the BMP version', + PrintConv => { + 12 => 'OS/2 V1', + 64 => 'OS/2 V2', + }, + }, + 4 => { Name => 'ImageWidth', Format => 'int16u' }, + 6 => { Name => 'ImageHeight', Format => 'int16u' }, + 8 => { Name => 'Planes', Format => 'int16u' }, + 10 => { Name => 'BitDepth', Format => 'int16u' }, +); + +%Image::ExifTool::BMP::Extra = ( + GROUPS => { 0 => 'File', 1 => 'File', 2 => 'Image' }, + NOTES => 'Extra information extracted from some BMP images.', + VARS => { NO_ID => 1 }, + LinkedProfileName => { }, + ICC_Profile => { SubDirectory => { TagTable => 'Image::ExifTool::ICC_Profile::Main' } }, + EmbeddedJPG => { + Groups => { 2 => 'Preview' }, + Binary => 1, + }, + EmbeddedPNG => { + Groups => { 2 => 'Preview' }, + Binary => 1, + }, +); + +#------------------------------------------------------------------------------ +# Extract EXIF information from a BMP image +# Inputs: 0) ExifTool object reference, 1) dirInfo reference +# Returns: 1 on success, 0 if this wasn't a valid BMP file +sub ProcessBMP($$) +{ + my ($et, $dirInfo) = @_; + my $raf = $$dirInfo{RAF}; + my ($buff, $tagTablePtr); + + # verify this is a valid BMP file + return 0 unless $raf->Read($buff, 18) == 18; + return 0 unless $buff =~ /^BM/; + SetByteOrder('II'); + my $len = Get32u(\$buff, 14); + # len = v1:12, v4:108, v5:124 + return 0 unless $len == 12 or $len == 16 or ($len >= 40 and $len < 1000000); + return 0 unless $raf->Seek(-4, 1) and $raf->Read($buff, $len) == $len; + $et->SetFileType(); # set the FileType tag +# +# process the BMP header +# + my %dirInfo = ( + DataPt => \$buff, + DirStart => 0, + DirLen => length($buff), + ); + if ($len == 12 or $len == 16 or $len == 64) { # old OS/2 format BMP + $tagTablePtr = GetTagTable('Image::ExifTool::BMP::OS2'); + } else { + $tagTablePtr = GetTagTable('Image::ExifTool::BMP::Main'); + } + $et->ProcessDirectory(\%dirInfo, $tagTablePtr); +# +# extract any embedded images +# + my $extraTable = GetTagTable('Image::ExifTool::BMP::Extra'); + if ($$et{BMPCompression} and $$et{BMPImageLength} and + ($$et{BMPCompression} == 4 or $$et{BMPCompression} == 5)) + { + my $tag = $$et{BMPCompression} == 4 ? 'EmbeddedJPG' : 'EmbeddedPNG'; + my $val = $et->ExtractBinary($raf->Tell(), $$et{BMPImageLength}, $tag); + if ($val) { + $et->HandleTag($extraTable, $tag, $val); + } + } +# +# process profile data if it exists (v5 header only) +# + if ($len == 124 and $$et{BMPProfileOffset}) { + my $pos = $$et{BMPProfileOffset} + 14; # (note the 14-byte shift!) + my $size = $$et{BMPProfileSize}; + if ($raf->Seek($pos, 0) and $raf->Read($buff, $size) == $size) { + my $tag; + if ($$et{BMPColorSpace} eq 'LINK') { + $buff =~ s/\0+$//; # remove null terminator(s) + $buff = $et->Decode($buff, 'Latin'); # convert from Latin + $tag = 'LinkedProfileName'; + } else { + $tag = 'ICC_Profile'; + } + $et->HandleTag($extraTable, $tag => $buff, Size => $size, DataPos => $pos); + } else { + $et->Warn('Error loading profile data', 1); + } + } + return 1; +} + +1; # end + +__END__ + +=head1 NAME + +Image::ExifTool::BMP - Read BMP meta information + +=head1 SYNOPSIS + +This module is used by Image::ExifTool + +=head1 DESCRIPTION + +This module contains definitions required by Image::ExifTool to read BMP +(Windows Bitmap) images. + +=head1 AUTHOR + +Copyright 2003-2019, Phil Harvey (phil at owl.phy.queensu.ca) + +This library is free software; you can redistribute it and/or modify it +under the same terms as Perl itself. + +=head1 REFERENCES + +=over 4 + +=item L + +=item L + +=item L + +=back + +=head1 SEE ALSO + +L, +L + +=cut + diff --git a/lib/Image/ExifTool/BPG.pm b/lib/Image/ExifTool/BPG.pm new file mode 100644 index 0000000..b879e7e --- /dev/null +++ b/lib/Image/ExifTool/BPG.pm @@ -0,0 +1,253 @@ +#------------------------------------------------------------------------------ +# File: BPG.pm +# +# Description: Read BPG meta information +# +# Revisions: 2016-07-05 - P. Harvey Created +# +# References: 1) http://bellard.org/bpg/ +#------------------------------------------------------------------------------ + +package Image::ExifTool::BPG; + +use strict; +use vars qw($VERSION); +use Image::ExifTool qw(:DataAccess :Utils); + +$VERSION = '1.01'; + +# BPG information +%Image::ExifTool::BPG::Main = ( + PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData, + GROUPS => { 0 => 'File', 1 => 'File', 2 => 'Image' }, + NOTES => q{ + The information listed below is extracted from BPG (Better Portable + Graphics) images. See L for the specification. + }, + 4 => { + Name => 'PixelFormat', + Format => 'int16u', + Mask => 0xe000, + PrintConv => { + 0 => 'Grayscale', + 1 => '4:2:0 (chroma at 0.5, 0.5)', + 2 => '4:2:2 (chroma at 0.5, 0)', + 3 => '4:4:4', + 4 => '4:2:0 (chroma at 0, 0.5)', + 5 => '4:2:2 (chroma at 0, 0)', + }, + }, + 4.1 => { + Name => 'Alpha', + Format => 'int16u', + Mask => 0x1004, + BitShift => 0, + PrintHex => 1, + PrintConv => { + 0x0000 => 'No Alpha Plane', + 0x1000 => 'Alpha Exists (color not premultiplied)', + 0x1004 => 'Alpha Exists (color premultiplied)', + 0x0004 => 'Alpha Exists (W color component)', + }, + }, + 4.2 => { + Name => 'BitDepth', + Format => 'int16u', + Mask => 0x0f00, + ValueConv => '$val + 8', + }, + 4.3 => { + Name => 'ColorSpace', + Format => 'int16u', + Mask => 0x00f0, + PrintConv => { + 0 => 'YCbCr (BT 601)', + 1 => 'RGB', + 2 => 'YCgCo', + 3 => 'YCbCr (BT 709)', + 4 => 'YCbCr (BT 2020)', + 5 => 'BT 2020 Constant Luminance', + }, + }, + 4.4 => { + Name => 'Flags', + Format => 'int16u', + Mask => 0x000b, + PrintConv => { BITMASK => { + 0 => 'Animation', + 1 => 'Limited Range', + 3 => 'Extension Present', + }}, + }, + 6 => { Name => 'ImageWidth', Format => 'var_ue7' }, + 7 => { Name => 'ImageHeight', Format => 'var_ue7' }, + # length of image data or 0 to EOF + # (must be decoded so we know where the extension data starts) + 8 => { Name => 'ImageLength', Format => 'var_ue7' }, +); + +%Image::ExifTool::BPG::Extensions = ( + GROUPS => { 0 => 'File', 1 => 'File', 2 => 'Image' }, + VARS => { ALPHA_FIRST => 1 }, + 1 => { + Name => 'EXIF', + SubDirectory => { + TagTable => 'Image::ExifTool::Exif::Main', + ProcessProc => \&Image::ExifTool::ProcessTIFF, + }, + }, + 2 => { + Name => 'ICC_Profile', + SubDirectory => { TagTable => 'Image::ExifTool::ICC_Profile::Main' }, + }, + 3 => { + Name => 'XMP', + SubDirectory => { TagTable => 'Image::ExifTool::XMP::Main' }, + }, + 4 => { + Name => 'ThumbnailBPG', + Binary => 1, + }, + 5 => { + Name => 'AnimationControl', + Binary => 1, + Unknown => 1, + }, +); + +#------------------------------------------------------------------------------ +# Get ue7 integer from binary data (max 32 bits) +# Inputs: 0) data ref, 1) location in data (undef for 0) +# Returns: 0) ue7 as integer or undef on error, 1) length of ue7 in bytes +sub Get_ue7($;$) +{ + my $dataPt = shift; + my $pos = shift || 0; + my $size = length $$dataPt; + my $val = 0; + my $i; + for ($i=0; ; ) { + return() if $pos+$i >= $size or $i >= 5; + my $byte = Get8u($dataPt, $pos + $i); + $val = ($val << 7) | ($byte & 0x7f); + unless ($byte & 0x80) { + return() if $i == 4 and $byte & 0x70; # error if bits 32-34 are set + last; # this was the last byte + } + return() if $i == 0 and $byte == 0x80; # error if first byte is 0x80 + ++$i; # step to the next byte + } + return($val, $i+1); +} + +#------------------------------------------------------------------------------ +# Extract EXIF information from a BPG image +# Inputs: 0) ExifTool object reference, 1) dirInfo reference +# Returns: 1 on success, 0 if this wasn't a valid BPG file +sub ProcessBPG($$) +{ + local $_; + my ($et, $dirInfo) = @_; + my $raf = $$dirInfo{RAF}; + my ($buff, $size, $n, $len, $pos); + + # verify this is a valid BPG file + return 0 unless $raf->Read($buff, 21) == 21; # (21 bytes is maximum header length) + return 0 unless $buff =~ /^BPG\xfb/; + $et->SetFileType(); # set the FileType tag + + SetByteOrder('MM'); + my %dirInfo = ( + DataPt => \$buff, + DirStart => 0, + DirLen => length($buff), + VarFormatData => [ ], + ); + $et->ProcessDirectory(\%dirInfo, GetTagTable('Image::ExifTool::BPG::Main')); + + return 1 unless $$et{VALUE}{Flags} & 0x0008; # all done unless extension flag is set + + # add varSize from last entry in VarFormatData to determine + # the current read position in the file + my $dataPos = 9 + $dirInfo{VarFormatData}[-1][1]; + # read extension length + unless ($raf->Seek($dataPos, 0) and $raf->Read($buff, 5) == 5) { + $et->Warn('Missing BPG extension data'); + return 1; + } + ($size, $n) = Get_ue7(\$buff); + defined $size or $et->Warn('Corrupted BPG extension length'), return 1; + $dataPos += $n; + $size > 10000000 and $et->Warn('BPG extension is too large'), return 1; + unless ($raf->Seek($dataPos, 0) and $raf->Read($buff, $size) == $size) { + $et->Warn('Truncated BPG extension'); + return 1; + } + my $tagTablePtr = GetTagTable('Image::ExifTool::BPG::Extensions'); + # loop through the individual extensions + for ($pos=0; $pos<$size; $pos+=$len) { + my $type = Get8u(\$buff, $pos); + # get length of this extension + ($len, $n) = Get_ue7(\$buff, ++$pos); + defined $len or $et->Warn('Corrupted BPG extension'), last; + $pos += $n; # point to start of data for this extension + $pos + $len > $size and $et->Warn('Invalid BPG extension size'), last; + $$tagTablePtr{$type} or $et->Warn("Unrecognized BPG extension $type ($len bytes)", 1), next; + # libbpg (in my opinion) incorrectly copies the padding byte after the + # "EXIF\0" APP1 header to the start of the BPG EXIF extension, so issue a + # minor warning and ignore the padding if we find it before the TIFF header + if ($type == 1 and $len > 3 and substr($buff,$pos,3)=~/^.(II|MM)/s) { + $et->Warn("Ignored extra byte at start of EXIF extension", 1); + ++$pos; + --$len; + } + $et->HandleTag($tagTablePtr, $type, undef, + DataPt => \$buff, + DataPos => $dataPos, + Start => $pos, + Size => $len, + Parent => 'BPG', + ); + } + return 1; +} + +1; # end + +__END__ + +=head1 NAME + +Image::ExifTool::BPG - Read BPG meta information + +=head1 SYNOPSIS + +This module is used by Image::ExifTool + +=head1 DESCRIPTION + +This module contains definitions required by Image::ExifTool to read BPG +(Better Portable Graphics) images. + +=head1 AUTHOR + +Copyright 2003-2019, Phil Harvey (phil at owl.phy.queensu.ca) + +This library is free software; you can redistribute it and/or modify it +under the same terms as Perl itself. + +=head1 REFERENCES + +=over 4 + +=item L + +=back + +=head1 SEE ALSO + +L, +L + +=cut + diff --git a/lib/Image/ExifTool/BZZ.pm b/lib/Image/ExifTool/BZZ.pm new file mode 100644 index 0000000..a876e76 --- /dev/null +++ b/lib/Image/ExifTool/BZZ.pm @@ -0,0 +1,472 @@ +#------------------------------------------------------------------------------ +# File: BZZ.pm +# +# Description: Utility to decode BZZ compressed data +# +# Revisions: 09/22/2008 - P. Harvey Created +# +# References: 1) http://djvu.sourceforge.net/ +# 2) http://www.djvu.org/ +# +# Notes: This code based on ZPCodec and BSByteStream of DjVuLibre 3.5.21 +# (see NOTES documentation below for license/copyright details) +#------------------------------------------------------------------------------ + +package Image::ExifTool::BZZ; + +use strict; +use integer; # IMPORTANT!! use integer arithmetic throughout +require Exporter; +use vars qw($VERSION @ISA @EXPORT_OK); + +$VERSION = '1.00'; +@ISA = qw(Exporter); +@EXPORT_OK = qw(Decode); + +# constants +sub FREQMAX { 4 } +sub CTXIDS { 3 } +sub MAXBLOCK { 4096 } + +# This table has been designed for the ZPCoder +# by running the following command in file 'zptable.sn': +# (fast-crude (steady-mat 0.0035 0.0002) 260))) +my @default_ztable_p = ( + 0x8000, 0x8000, 0x8000, 0x6bbd, 0x6bbd, 0x5d45, 0x5d45, 0x51b9, 0x51b9, 0x4813, + 0x4813, 0x3fd5, 0x3fd5, 0x38b1, 0x38b1, 0x3275, 0x3275, 0x2cfd, 0x2cfd, 0x2825, + 0x2825, 0x23ab, 0x23ab, 0x1f87, 0x1f87, 0x1bbb, 0x1bbb, 0x1845, 0x1845, 0x1523, + 0x1523, 0x1253, 0x1253, 0x0fcf, 0x0fcf, 0x0d95, 0x0d95, 0x0b9d, 0x0b9d, 0x09e3, + 0x09e3, 0x0861, 0x0861, 0x0711, 0x0711, 0x05f1, 0x05f1, 0x04f9, 0x04f9, 0x0425, + 0x0425, 0x0371, 0x0371, 0x02d9, 0x02d9, 0x0259, 0x0259, 0x01ed, 0x01ed, 0x0193, + 0x0193, 0x0149, 0x0149, 0x010b, 0x010b, 0x00d5, 0x00d5, 0x00a5, 0x00a5, 0x007b, + 0x007b, 0x0057, 0x0057, 0x003b, 0x003b, 0x0023, 0x0023, 0x0013, 0x0013, 0x0007, + 0x0007, 0x0001, 0x0001, 0x5695, 0x24ee, 0x8000, 0x0d30, 0x481a, 0x0481, 0x3579, + 0x017a, 0x24ef, 0x007b, 0x1978, 0x0028, 0x10ca, 0x000d, 0x0b5d, 0x0034, 0x078a, + 0x00a0, 0x050f, 0x0117, 0x0358, 0x01ea, 0x0234, 0x0144, 0x0173, 0x0234, 0x00f5, + 0x0353, 0x00a1, 0x05c5, 0x011a, 0x03cf, 0x01aa, 0x0285, 0x0286, 0x01ab, 0x03d3, + 0x011a, 0x05c5, 0x00ba, 0x08ad, 0x007a, 0x0ccc, 0x01eb, 0x1302, 0x02e6, 0x1b81, + 0x045e, 0x24ef, 0x0690, 0x2865, 0x09de, 0x3987, 0x0dc8, 0x2c99, 0x10ca, 0x3b5f, + 0x0b5d, 0x5695, 0x078a, 0x8000, 0x050f, 0x24ee, 0x0358, 0x0d30, 0x0234, 0x0481, + 0x0173, 0x017a, 0x00f5, 0x007b, 0x00a1, 0x0028, 0x011a, 0x000d, 0x01aa, 0x0034, + 0x0286, 0x00a0, 0x03d3, 0x0117, 0x05c5, 0x01ea, 0x08ad, 0x0144, 0x0ccc, 0x0234, + 0x1302, 0x0353, 0x1b81, 0x05c5, 0x24ef, 0x03cf, 0x2b74, 0x0285, 0x201d, 0x01ab, + 0x1715, 0x011a, 0x0fb7, 0x00ba, 0x0a67, 0x01eb, 0x06e7, 0x02e6, 0x0496, 0x045e, + 0x030d, 0x0690, 0x0206, 0x09de, 0x0155, 0x0dc8, 0x00e1, 0x2b74, 0x0094, 0x201d, + 0x0188, 0x1715, 0x0252, 0x0fb7, 0x0383, 0x0a67, 0x0547, 0x06e7, 0x07e2, 0x0496, + 0x0bc0, 0x030d, 0x1178, 0x0206, 0x19da, 0x0155, 0x24ef, 0x00e1, 0x320e, 0x0094, + 0x432a, 0x0188, 0x447d, 0x0252, 0x5ece, 0x0383, 0x8000, 0x0547, 0x481a, 0x07e2, + 0x3579, 0x0bc0, 0x24ef, 0x1178, 0x1978, 0x19da, 0x2865, 0x24ef, 0x3987, 0x320e, + 0x2c99, 0x432a, 0x3b5f, 0x447d, 0x5695, 0x5ece, 0x8000, 0x8000, 0x5695, 0x481a, + 0x481a, 0, 0, 0, 0, 0 +); +my @default_ztable_m = ( + 0x0000, 0x0000, 0x0000, 0x10a5, 0x10a5, 0x1f28, 0x1f28, 0x2bd3, 0x2bd3, 0x36e3, + 0x36e3, 0x408c, 0x408c, 0x48fd, 0x48fd, 0x505d, 0x505d, 0x56d0, 0x56d0, 0x5c71, + 0x5c71, 0x615b, 0x615b, 0x65a5, 0x65a5, 0x6962, 0x6962, 0x6ca2, 0x6ca2, 0x6f74, + 0x6f74, 0x71e6, 0x71e6, 0x7404, 0x7404, 0x75d6, 0x75d6, 0x7768, 0x7768, 0x78c2, + 0x78c2, 0x79ea, 0x79ea, 0x7ae7, 0x7ae7, 0x7bbe, 0x7bbe, 0x7c75, 0x7c75, 0x7d0f, + 0x7d0f, 0x7d91, 0x7d91, 0x7dfe, 0x7dfe, 0x7e5a, 0x7e5a, 0x7ea6, 0x7ea6, 0x7ee6, + 0x7ee6, 0x7f1a, 0x7f1a, 0x7f45, 0x7f45, 0x7f6b, 0x7f6b, 0x7f8d, 0x7f8d, 0x7faa, + 0x7faa, 0x7fc3, 0x7fc3, 0x7fd7, 0x7fd7, 0x7fe7, 0x7fe7, 0x7ff2, 0x7ff2, 0x7ffa, + 0x7ffa, 0x7fff, 0x7fff, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +); +my @default_ztable_up = ( + 84, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, + 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, + 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, + 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, + 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, + 82, 81, 82, 9, 86, 5, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, + 82, 99, 76, 101, 70, 103, 66, 105, 106, 107, 66, 109, 60, 111, 56, 69, + 114, 65, 116, 61, 118, 57, 120, 53, 122, 49, 124, 43, 72, 39, 60, 33, + 56, 29, 52, 23, 48, 23, 42, 137, 38, 21, 140, 15, 142, 9, 144, 141, + 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 70, 157, 66, 81, 62, 75, + 58, 69, 54, 65, 50, 167, 44, 65, 40, 59, 34, 55, 30, 175, 24, 177, + 178, 179, 180, 181, 182, 183, 184, 69, 186, 59, 188, 55, 190, 51, 192, 47, + 194, 41, 196, 37, 198, 199, 72, 201, 62, 203, 58, 205, 54, 207, 50, 209, + 46, 211, 40, 213, 36, 215, 30, 217, 26, 219, 20, 71, 14, 61, 14, 57, + 8, 53, 228, 49, 230, 45, 232, 39, 234, 35, 138, 29, 24, 25, 240, 19, + 22, 13, 16, 13, 10, 7, 244, 249, 10, 89, 230, 0, 0, 0, 0, 0 +); +my @default_ztable_dn = ( + 145, 4, 3, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, + 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, + 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, + 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, + 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, + 78, 79, 80, 85, 226, 6, 176, 143, 138, 141, 112, 135, 104, 133, 100, 129, + 98, 127, 72, 125, 102, 123, 60, 121, 110, 119, 108, 117, 54, 115, 48, 113, + 134, 59, 132, 55, 130, 51, 128, 47, 126, 41, 62, 37, 66, 31, 54, 25, + 50, 131, 46, 17, 40, 15, 136, 7, 32, 139, 172, 9, 170, 85, 168, 248, + 166, 247, 164, 197, 162, 95, 160, 173, 158, 165, 156, 161, 60, 159, 56, 71, + 52, 163, 48, 59, 42, 171, 38, 169, 32, 53, 26, 47, 174, 193, 18, 191, + 222, 189, 218, 187, 216, 185, 214, 61, 212, 53, 210, 49, 208, 45, 206, 39, + 204, 195, 202, 31, 200, 243, 64, 239, 56, 237, 52, 235, 48, 233, 44, 231, + 38, 229, 34, 227, 28, 225, 22, 223, 16, 221, 220, 63, 8, 55, 224, 51, + 2, 47, 87, 43, 246, 37, 244, 33, 238, 27, 236, 21, 16, 15, 8, 241, + 242, 7, 10, 245, 2, 1, 83, 250, 2, 143, 246, 0, 0, 0, 0, 0 +); + +#------------------------------------------------------------------------------ +# New - create new BZZ object +# Inputs: 0) reference to BZZ object or BZZ class name +# Returns: blessed BZZ object ref +sub new +{ + local $_; + my $that = shift; + my $class = ref($that) || $that || 'Image::ExifTool::BZZ'; + return bless {}, $class; +} + +#------------------------------------------------------------------------------ +# Initialize BZZ object +# Inputs: 0) BZZ object ref, 1) data ref, 2) true for DjVu compatibility +sub Init($$) +{ + my ($self, $dataPt, $djvucompat) = @_; + # Create machine independent ffz table + my $ffzt = $$self{ffzt} = [ ]; + my ($i, $j); + for ($i=0; $i<256; $i++) { + $$ffzt[$i] = 0; + for ($j=$i; $j&0x80; $j<<=1) { + $$ffzt[$i] += 1; + } + } + # Initialize table + $$self{p} = [ @default_ztable_p ]; + $$self{'m'} = [ @default_ztable_m ]; + $$self{up} = [ @default_ztable_up ]; + $$self{dn} = [ @default_ztable_dn ]; + # Patch table (and lose DjVu compatibility) + unless ($djvucompat) { + my ($p, $m, $dn) = ($$self{p}, $$self{'m'}, $$self{dn}); + for ($j=0; $j<256; $j++) { + my $a = (0x10000 - $$p[$j]) & 0xffff; + while ($a >= 0x8000) { $a = ($a<<1) & 0xffff } + if ($$m[$j]>0 && $a+$$p[$j]>=0x8000 && $a>=$$m[$j]) { + $$dn[$j] = $default_ztable_dn[$default_ztable_dn[$j]]; + } + } + } + $$self{ctx} = [ (0) x 300 ]; + $$self{DataPt} = $dataPt; + $$self{Pos} = 0; + $$self{DataLen} = length $$dataPt; + $$self{a} = 0; + $$self{buffer} = 0; + $$self{fence} = 0; + $$self{blocksize} = 0; + # Read first 16 bits of code + if (length($$dataPt) >= 2) { + $$self{code} = unpack('n', $$dataPt); + $$self{Pos} += 2; + } elsif (length($$dataPt) >= 1) { + $$self{code} = (unpack('C', $$dataPt) << 8) | 0xff; + $$self{Pos}++; + } else { + $$self{code} = 0xffff; + } + $$self{byte} = $$self{code} & 0xff; + # Preload buffer + $$self{delay} = 25; + $$self{scount} = 0; + # Compute initial fence + $$self{fence} = $$self{code} >= 0x8000 ? 0x7fff : $$self{code}; +} + +#------------------------------------------------------------------------------ +# Decode data block +# Inputs: 0) optional BZZ object ref, 1) optional data ref +# Returns: decoded data or undefined on error +# Notes: If called without a data ref, an input BZZ object ref must be given and +# the BZZ object must have been initialized by a previous call to Init() +sub Decode($;$) +{ + # Decode input stream + local $_; + my $self; + if (ref $_[0] and UNIVERSAL::isa($_[0],'Image::ExifTool::BZZ')) { + $self = shift; + } else { + $self = new Image::ExifTool::BZZ; + } + my $dataPt = shift; + if ($dataPt) { + $self->Init($dataPt, 1); + } else { + $dataPt = $$self{DataPt} or return undef; + } + # Decode block size + my $n = 1; + my $m = (1 << 24); + while ($n < $m) { + my $b = $self->decode_sub(0x8000 + ($$self{a}>>1)); + $n = ($n<<1) | $b; + } + $$self{size} = $n - $m; + + return '' unless $$self{size}; + return undef if $$self{size} > MAXBLOCK()*1024; + # Allocate + if ($$self{blocksize} < $$self{size}) { + $$self{blocksize} = $$self{size}; + } + # Decode Estimation Speed + my $fshift = 0; + if ($self->decode_sub(0x8000 + ($$self{a}>>1))) { + $fshift += 1; + $fshift += 1 if $self->decode_sub(0x8000 + ($$self{a}>>1)); + } + # Prepare Quasi MTF + my @mtf = (0..255); + my @freq = (0) x FREQMAX(); + my $fadd = 4; + # Decode + my $mtfno = 3; + my $markerpos = -1; + my $cx = $$self{ctx}; + my ($i, @dat); +byte: for ($i=0; $i<$$self{size}; $i++) { + # dummy loop avoids use of "goto" statement +dummy: for (;;) { + my $ctxid = CTXIDS() - 1; + $ctxid = $mtfno if $ctxid > $mtfno; + my $cp = 0; + my ($imtf, $bits); + for ($imtf=0; $imtf<2; ++$imtf) { + if ($self->decoder($$cx[$cp+$ctxid])) { + $mtfno = $imtf; + $dat[$i] = $mtf[$mtfno]; + # (a "goto" here could give a segfault due to a Perl bug) + last dummy; # do rotation + } + $cp += CTXIDS(); + } + for ($bits=1; $bits<8; ++$bits, $imtf<<=1) { + if ($self->decoder($$cx[$cp])) { + my $n = 1; + my $m = (1 << $bits); + while ($n < $m) { + my $b = $self->decoder($$cx[$cp+$n]); + $n = ($n<<1) | $b; + } + $mtfno = $imtf + $n - $m; + $dat[$i] = $mtf[$mtfno]; + last dummy; # do rotation + } + $cp += $imtf; + } + $mtfno=256; + $dat[$i] = 0; + $markerpos=$i; + next byte; # no rotation necessary + } + # Rotate mtf according to empirical frequencies (new!) + # Adjust frequencies for overflow + $fadd = $fadd + ($fadd >> $fshift); + if ($fadd > 0x10000000) { + $fadd >>= 24; + $_ >>= 24 foreach @freq; + } + # Relocate new char according to new freq + my $fc = $fadd; + $fc += $freq[$mtfno] if $mtfno < FREQMAX(); + my $k; + for ($k=$mtfno; $k>=FREQMAX(); $k--) { + $mtf[$k] = $mtf[$k-1]; + } + for (; $k>0 && $fc>=$freq[$k-1]; $k--) { + $mtf[$k] = $mtf[$k-1]; + $freq[$k] = $freq[$k-1]; + } + $mtf[$k] = $dat[$i]; + $freq[$k] = $fc; + # when "goto" was used, Perl 5.8.6 could segfault here + # unless "next" was explicitly stated + } +# +# Reconstruct the string +# + return undef if $markerpos<1 || $markerpos>=$$self{size}; + # Allocate pointers + # Prepare count buffer + my @count = (0) x 256; + my @posn; + # Fill count buffer + no integer; + for ($i=0; $i<$markerpos; $i++) { + my $c = $dat[$i]; + $posn[$i] = ($c<<24) | ($count[$c]++ & 0xffffff); + } + $posn[$i++] = 0; # (initialize marker entry just to be safe) + for ( ; $i<$$self{size}; $i++) { + my $c = $dat[$i]; + $posn[$i] = ($c<<24) | ($count[$c]++ & 0xffffff); + } + use integer; + # Compute sorted char positions + my $last = 1; + for ($i=0; $i<256; $i++) { + my $tmp = $count[$i]; + $count[$i] = $last; + $last += $tmp; + } + # Undo the sort transform + $i = 0; + $last = $$self{size}-1; + while ($last > 0) { + my $n = $posn[$i]; + no integer; + my $c = $n >> 24; + use integer; + $dat[--$last] = $c; + $i = $count[$c] + ($n & 0xffffff); + } + # Final check and return decoded data + return undef if $i != $markerpos; + pop @dat; # (last byte isn't real) + return pack 'C*', @dat; +} + +#------------------------------------------------------------------------------ +# Inputs: 0) BZZ object ref, 1) ctx +# Returns: decoded bit +sub decoder($$) +{ + my ($self, $ctx) = @_; + my $z = $$self{a} + $self->{p}[$ctx]; + if ($z <= $$self{fence}) { + $$self{a} = $z; + return ($ctx & 1); + } + # must pass $_[1] so subroutine can modify value (darned C++ pass-by-reference!) + return $self->decode_sub($z, $_[1]); +} + +#------------------------------------------------------------------------------ +# Inputs: 0) BZZ object ref, 1) z, 2) ctx (or undef) +# Returns: decoded bit +sub decode_sub($$;$) +{ + my ($self, $z, $ctx) = @_; + + # ensure that we have at least 16 bits of encoded data available + if ($$self{scount} < 16) { + # preload byte by byte until we have at least 24 bits + while ($$self{scount} <= 24) { + if ($$self{Pos} < $$self{DataLen}) { + $$self{byte} = ord(substr(${$$self{DataPt}}, $$self{Pos}, 1)); + ++$$self{Pos}; + } else { + $$self{byte} = 0xff; + if (--$$self{delay} < 1) { + # setting size to zero forces error return from Decode() + $$self{size} = 0; + return 0; + } + } + $$self{buffer} = ($$self{buffer}<<8) | $$self{byte}; + $$self{scount} += 8; + } + } + # Save bit + my $a = $$self{a}; + my ($bit, $code); + if (defined $ctx) { + $bit = ($ctx & 1); + # Avoid interval reversion + my $d = 0x6000 + (($z+$a)>>2); + $z = $d if $z > $d; + } else { + $bit = 0; + } + # Test MPS/LPS + if ($z > ($code = $$self{code})) { + $bit ^= 1; + # LPS branch + $z = 0x10000 - $z; + $a += $z; + $code += $z; + # LPS adaptation + $_[2] = $self->{dn}[$ctx] if defined $ctx; + # LPS renormalization + my $sft = $a>=0xff00 ? $self->{ffzt}[$a&0xff] + 8 : $self->{ffzt}[($a>>8)&0xff]; + $$self{scount} -= $sft; + $$self{a} = ($a<<$sft) & 0xffff; + $code = (($code<<$sft) & 0xffff) | (($$self{buffer}>>$$self{scount}) & ((1<<$sft)-1)); + } else { + # MPS adaptation + $_[2] = $self->{up}[$ctx] if defined $ctx and $a >= $self->{'m'}[$ctx]; + # MPS renormalization + $$self{scount} -= 1; + $$self{a} = ($z<<1) & 0xffff; + $code = (($code<<1) & 0xffff) | (($$self{buffer}>>$$self{scount}) & 1); + } + # Adjust fence and save new code + $$self{fence} = $code >= 0x8000 ? 0x7fff : $code; + $$self{code} = $code; + return $bit; +} + +1; # end + +__END__ + +=head1 NAME + +Image::ExifTool::BZZ - Utility to decode BZZ compressed data + +=head1 SYNOPSIS + +This module is used by Image::ExifTool + +=head1 DESCRIPTION + +This module contains definitions required by Image::ExifTool to decode BZZ +compressed data in DjVu images. + +=head1 NOTES + +This code is based on ZPCodec and BSByteStream of DjVuLibre 3.5.21 (see +additional copyrights and the first reference below), which are covered +under the GNU GPL license. + +This is implemented as Image::ExifTool::BZZ instead of Compress::BZZ because +I am hoping that someone else will write a proper Compress::BZZ module (with +compression ability). + +=head1 AUTHOR + +Copyright 2003-2019, Phil Harvey (phil at owl.phy.queensu.ca) +Copyright 2002, Leon Bottou and Yann Le Cun +Copyright 2001, AT&T +Copyright 1999-2001, LizardTech Inc. + +This library is free software; you can redistribute it and/or modify it +under the same terms as Perl itself. + +=head1 REFERENCES + +=over 4 + +=item L + +=item L + +=back + +=head1 SEE ALSO + +L, +L + +=cut + diff --git a/lib/Image/ExifTool/BigTIFF.pm b/lib/Image/ExifTool/BigTIFF.pm new file mode 100644 index 0000000..cad97db --- /dev/null +++ b/lib/Image/ExifTool/BigTIFF.pm @@ -0,0 +1,297 @@ +#------------------------------------------------------------------------------ +# File: BigTIFF.pm +# +# Description: Read Big TIFF meta information +# +# Revisions: 07/03/2007 - P. Harvey Created +# +# References: 1) http://www.awaresystems.be/imaging/tiff/bigtiff.html +#------------------------------------------------------------------------------ + +package Image::ExifTool::BigTIFF; + +use strict; +use vars qw($VERSION); +use Image::ExifTool qw(:DataAccess :Utils); +use Image::ExifTool::Exif; + +$VERSION = '1.07'; + +my $maxOffset = 0x7fffffff; # currently supported maximum data offset/size + +#------------------------------------------------------------------------------ +# Process Big IFD directory +# Inputs: 0) ExifTool object ref, 1) dirInfo ref, 2) tag table ref +# Returns: 1 on success, otherwise returns 0 and sets a Warning +sub ProcessBigIFD($$$) +{ + my ($et, $dirInfo, $tagTablePtr) = @_; + my $raf = $$dirInfo{RAF}; + my $verbose = $$et{OPTIONS}{Verbose}; + my $htmlDump = $$et{HTML_DUMP}; + my $dirName = $$dirInfo{DirName}; + my $dirStart = $$dirInfo{DirStart}; + my ($offName, $nextOffName); + + if ($htmlDump) { + $verbose = -1; # mix htmlDump into verbose so we can test for both at once + $offName = $$dirInfo{OffsetName}; + } + + # loop through IFD chain + for (;;) { + if ($dirStart > $maxOffset and not $et->Options('LargeFileSupport')) { + $et->Warn('Huge offsets not supported (LargeFileSupport not set)'); + last; + } + unless ($raf->Seek($dirStart, 0)) { + $et->Warn("Bad $dirName offset"); + return 0; + } + my ($dirBuff, $index); + unless ($raf->Read($dirBuff, 8) == 8) { + $et->Warn("Truncated $dirName count"); + return 0; + } + my $numEntries = Image::ExifTool::Get64u(\$dirBuff, 0); + $verbose > 0 and $et->VerboseDir($dirName, $numEntries); + my $bsize = $numEntries * 20; + if ($bsize > $maxOffset) { + $et->Warn('Huge directory counts not yet supported'); + last; + } + my $bufPos = $raf->Tell(); + unless ($raf->Read($dirBuff, $bsize) == $bsize) { + $et->Warn("Truncated $dirName directory"); + return 0; + } + my $nextIFD; + $raf->Read($nextIFD, 8) == 8 or undef $nextIFD; # try to read next IFD pointer + if ($htmlDump) { + $et->HDump($bufPos-8, 8, "$dirName entries", "Entry count: $numEntries", undef, $offName); + if (defined $nextIFD) { + my $off = Image::ExifTool::Get64u(\$nextIFD, 0); + my $tip = sprintf("Offset: 0x%.8x", $off); + my $id = $offName; + ($nextOffName, $id) = Image::ExifTool::Exif::NextOffsetName($et, $id) if $off; + $et->HDump($bufPos + 20 * $numEntries, 8, "Next IFD", $tip, 0, $id); + } + } + # loop through all entries in this BigTIFF IFD + for ($index=0; $index<$numEntries; ++$index) { + my $entry = 20 * $index; + my $tagID = Get16u(\$dirBuff, $entry); + my $format = Get16u(\$dirBuff, $entry+2); + my $count = Image::ExifTool::Get64u(\$dirBuff, $entry+4); + my $formatSize = $Image::ExifTool::Exif::formatSize[$format]; + unless (defined $formatSize) { + $et->HDump($bufPos+$entry,20,"[invalid IFD entry]", + "Bad format value: $format", 1, $offName); + # warn unless the IFD was just padded with zeros + $et->Warn(sprintf("Unknown format ($format) for $dirName tag 0x%x",$tagID)); + return 0; # assume corrupted IFD + } + my $formatStr = $Image::ExifTool::Exif::formatName[$format]; + my $size = $count * $formatSize; + my $tagInfo = $et->GetTagInfo($tagTablePtr, $tagID); + next unless defined $tagInfo or $verbose; + my $valuePtr = $entry + 12; + my ($valBuff, $valBase, $rational, $subOffName); + if ($size > 8) { + if ($size > $maxOffset) { + $et->Warn("Can't handle $dirName entry $index (huge size)"); + next; + } + $valuePtr = Image::ExifTool::Get64u(\$dirBuff, $valuePtr); + if ($valuePtr > $maxOffset and not $et->Options('LargeFileSupport')) { + $et->Warn("Can't handle $dirName entry $index (LargeFileSupport not set)"); + next; + } + unless ($raf->Seek($valuePtr, 0) and $raf->Read($valBuff, $size) == $size) { + $et->Warn("Error reading $dirName entry $index"); + next; + } + $valBase = 0; + } else { + $valBuff = substr($dirBuff, $valuePtr, $size); + $valBase = $bufPos; + } + if (defined $tagInfo and not $tagInfo) { + # GetTagInfo() required the value for a Condition + $tagInfo = $et->GetTagInfo($tagTablePtr, $tagID, \$valBuff); + } + my $val = ReadValue(\$valBuff, 0, $formatStr, $count, $size, \$rational); + if ($htmlDump) { + my $tval = $val; + # show numerator/denominator separately for rational numbers + $tval .= " ($rational)" if defined $rational; + my ($tagName, $colName); + if ($tagID == 0x927c and $dirName eq 'ExifIFD') { + $tagName = 'MakerNotes'; + } elsif ($tagInfo) { + $tagName = $$tagInfo{Name}; + } else { + $tagName = sprintf("Tag 0x%.4x",$tagID); + } + my $dname = sprintf("$dirName-%.2d", $index); + # build our tool tip + my $tip = sprintf("Tag ID: 0x%.4x\n", $tagID) . + "Format: $formatStr\[$count]\nSize: $size bytes\n"; + if ($size > 8) { + $tip .= sprintf("Value offset: 0x%.8x\n", $valuePtr); + $colName = "$tagName"; + } else { + $colName = $tagName; + } + $tval = substr($tval,0,28) . '[...]' if length($tval) > 32; + if ($formatStr =~ /^(string|undef|binary)/) { + # translate non-printable characters + $tval =~ tr/\x00-\x1f\x7f-\xff/./; + } elsif ($tagInfo and Image::ExifTool::IsInt($tval)) { + if ($$tagInfo{IsOffset}) { + $tval = sprintf('0x%.4x', $tval); + } elsif ($$tagInfo{PrintHex}) { + $tval = sprintf('0x%x', $tval); + } + } + $tip .= "Value: $tval"; + my ($id, $sid); + if ($tagInfo and $$tagInfo{SubIFD}) { + ($subOffName, $id, $sid) = Image::ExifTool::Exif::NextOffsetName($et, $offName); + } else { + $id = $offName; + } + $et->HDump($entry+$bufPos, 20, "$dname $colName", $tip, 1, $id); + if ($size > 8) { + # add value data block + my $flg = ($tagInfo and $$tagInfo{SubDirectory} and $$tagInfo{MakerNotes}) ? 4 : 0; + $et->HDump($valuePtr,$size,"$tagName value",'SAME', $flg, $sid); + } + } + if ($tagInfo and $$tagInfo{SubIFD}) { + # process all SubIFD's as BigTIFF + $verbose > 0 and $et->VerboseInfo($tagID, $tagInfo, + Table => $tagTablePtr, + Index => $index, + Value => $val, + DataPt => \$valBuff, + DataPos => $valBase + $valuePtr, + Start => 0, + Size => $size, + Format => $formatStr, + Count => $count, + ); + my @offsets = split ' ', $val; + my $i; + for ($i=0; $i $raf, + DataPos => 0, + DirStart => $offsets[$i], + DirName => $subdirName, + Parent => $dirName, + OffsetName => $subOffName, + ); + $et->ProcessDirectory(\%subdirInfo, $tagTablePtr, \&ProcessBigIFD); + } + } else { + my $tagKey = $et->HandleTag($tagTablePtr, $tagID, $val, + Index => $index, + DataPt => \$valBuff, + DataPos => $valBase + $valuePtr, + Start => 0, + Size => $size, + Format => $formatStr, + TagInfo => $tagInfo, + RAF => $raf, + ); + $tagKey and $et->SetGroup($tagKey, $dirName); + } + } + last unless $dirName =~ /^(IFD|SubIFD)(\d*)$/; + $dirName = $1 . (($2 || 0) + 1); + defined $nextIFD or $et->Warn("Bad $dirName pointer"), return 0; + $dirStart = Image::ExifTool::Get64u(\$nextIFD, 0); + $dirStart or last; + $offName = $nextOffName; + } + return 1; +} + +#------------------------------------------------------------------------------ +# Extract meta information from a BigTIFF image +# Inputs: 0) ExifTool object reference, 1) dirInfo reference +# Returns: 1 on success, 0 if this wasn't a valid BigTIFF image +sub ProcessBTF($$) +{ + my ($et, $dirInfo) = @_; + my $raf = $$dirInfo{RAF}; + my $buff; + + return 0 unless $raf->Read($buff, 16) == 16; + return 0 unless $buff =~ /^(MM\0\x2b\0\x08\0\0|II\x2b\0\x08\0\0\0)/; + if ($$dirInfo{OutFile}) { + $et->Error('ExifTool does not support writing of BigTIFF images'); + return 1; + } + $et->SetFileType('BTF'); # set the FileType tag + SetByteOrder(substr($buff, 0, 2)); + my $offset = Image::ExifTool::Get64u(\$buff, 8); + if ($$et{HTML_DUMP}) { + my $o = (GetByteOrder() eq 'II') ? 'Little' : 'Big'; + $et->HDump(0, 8, "BigTIFF header", "Byte order: $o endian", 0); + $et->HDump(8, 8, "IFD0 pointer", sprintf("Offset: 0x%.8x",$offset), 0); + } + my %dirInfo = ( + RAF => $raf, + DataPos => 0, + DirStart => $offset, + DirName => 'IFD0', + Parent => 'BigTIFF', + ); + my $tagTablePtr = GetTagTable('Image::ExifTool::Exif::Main'); + $et->ProcessDirectory(\%dirInfo, $tagTablePtr, \&ProcessBigIFD); + return 1; +} + +1; # end + +__END__ + +=head1 NAME + +Image::ExifTool::BigTIFF - Read Big TIFF meta information + +=head1 SYNOPSIS + +This module is used by Image::ExifTool + +=head1 DESCRIPTION + +This module contains routines required by Image::ExifTool to read meta +information in BigTIFF images. + +=head1 AUTHOR + +Copyright 2003-2019, Phil Harvey (phil at owl.phy.queensu.ca) + +This library is free software; you can redistribute it and/or modify it +under the same terms as Perl itself. + +=head1 REFERENCES + +=over 4 + +=item L + +=back + +=head1 SEE ALSO + +L, +L + +=cut + diff --git a/lib/Image/ExifTool/BuildTagLookup.pm b/lib/Image/ExifTool/BuildTagLookup.pm new file mode 100644 index 0000000..f495a32 --- /dev/null +++ b/lib/Image/ExifTool/BuildTagLookup.pm @@ -0,0 +1,2631 @@ +#------------------------------------------------------------------------------ +# File: BuildTagLookup.pm +# +# Description: Utility to build tag lookup tables in Image::ExifTool::TagLookup.pm +# +# Revisions: 12/31/2004 - P. Harvey Created +# 02/15/2005 - PH Added ability to generate TagNames documentation +# +# Notes: Documentation for the tag tables may either be placed in the +# %docs hash below or in a NOTES entry in the table itself, and +# individual tags may have their own Notes entry. +#------------------------------------------------------------------------------ + +package Image::ExifTool::BuildTagLookup; + +use strict; +require Exporter; + +BEGIN { + # prevent ExifTool from loading the user config file + $Image::ExifTool::configFile = ''; + $Image::ExifTool::debug = 1; # enabled debug messages +} + +use vars qw($VERSION @ISA); +use Image::ExifTool qw(:Utils :Vars); +use Image::ExifTool::Exif; +use Image::ExifTool::Shortcuts; +use Image::ExifTool::HTML qw(EscapeHTML); +use Image::ExifTool::IPTC; +use Image::ExifTool::XMP; +use Image::ExifTool::Canon; +use Image::ExifTool::Nikon; +use Image::ExifTool::Validate; +use Image::ExifTool::MacOS; + +$VERSION = '3.19'; +@ISA = qw(Exporter); + +sub NumbersFirst($$); +sub SortedTagTablekeys($); + +# global variables to control sorting order of table entries +my $numbersFirst = 1; # set to -1 to sort numbers last, or 2 to put negative numbers last +my $caseInsensitive; # flag to ignore case when sorting tag names + +# list of all tables in plug-in modules +my @pluginTables = ('Image::ExifTool::MWG::Composite'); + +# colors for html pages +my $noteFont = ""; +my $noteFontSmall = ""; + +my $docType = q{ +}; + +my $homePage = 'http://owl.phy.queensu.ca/~phil/exiftool'; + +# tweak the ordering of tables in the documentation +my %tweakOrder = ( + # this => comes after this + # ------- ----------------- + JPEG => '-', # JPEG comes first + IPTC => 'Exif', # put IPTC after EXIF, + GPS => 'XMP', # etc... + Composite => 'Extra', + GeoTiff => 'GPS', + CanonVRD=> 'CanonCustom', + FLIR => 'Casio', + FujiFilm => 'FLIR', + Kodak => 'JVC', + Leaf => 'Kodak', + Minolta => 'Leaf', + Motorola => 'Minolta', + Nikon => 'Motorola', + NikonCustom => 'Nikon', + NikonCapture => 'NikonCustom', + Nintendo => 'NikonCapture', + Pentax => 'Panasonic', + SonyIDC => 'Sony', + Unknown => 'SonyIDC', + DNG => 'Unknown', + PrintIM => 'ICC_Profile', + Vorbis => 'Ogg', + ID3 => 'PostScript', + MinoltaRaw => 'KyoceraRaw', + KyoceraRaw => 'CanonRaw', + SigmaRaw => 'PanasonicRaw', + Lytro => 'SigmaRaw', + PhotoMechanic => 'FotoStation', + Microsoft => 'PhotoMechanic', + 'Microsoft::MP'=> 'Microsoft::MP1', + GIMP => 'Microsoft', + 'Nikon::CameraSettingsD300' => 'Nikon::ShotInfoD300b', + 'Pentax::LensData' => 'Pentax::LensInfo2', + 'Sony::SRF2' => 'Sony::SRF', + DarwinCore => 'AFCP', + 'MWG::Regions' => 'MWG::Composite', + 'MWG::Keywords' => 'MWG::Regions', + 'MWG::Collections' => 'MWG::Keywords', + 'GoPro::fdsc' => 'GoPro::KBAT', +); + +# list of all recognized Format strings +# (not a complete list, but this is all we use so far) +# (also, formats like "var_X[num]" are allowed for any valid X) +my %formatOK = ( + %Image::ExifTool::Exif::formatNumber, + 0 => 1, + 1 => 1, + real => 1, + integer => 1, + date => 1, + boolean => 1, + rational => 1, + 'lang-alt' => 1, + fixed16u => 1, + fixed16s => 1, + fixed32u => 1, + fixed32s => 1, + extended => 1, + resize => 1, + digits => 1, + int16uRev => 1, + int32uRev => 1, + rational32u => 1, + rational32s => 1, + pstring => 1, + var_string => 1, + var_int16u => 1, + var_pstr32 => 1, + var_ustr32 => 1, + var_ue7 => 1, # (BPG) + # Matroska + signed => 1, + unsigned => 1, + utf8 => 1, +); + +# Descriptions for the TagNames documentation +# (descriptions may also be defined in tag table NOTES) +# Note: POD headers in these descriptions start with '~' instead of '=' to keep +# from confusing POD parsers which apparently parse inside quoted strings. +my %docs = ( + PodHeader => q{ +~head1 NAME + +Image::ExifTool::TagNames - ExifTool tag name documentation + +~head1 DESCRIPTION + +This document contains a complete list of ExifTool tag names, organized into +tables based on information type. Tag names are used to reference specific +meta information extracted from or written to a file. + +~head1 TAG TABLES +}, + ExifTool => q{ +The tables listed below give the names of all tags recognized by ExifTool. +}, + ExifTool2 => q{ +B, B or B is given in the first column of each +table. A B is the computer-readable equivalent of a tag name, and +is the identifier that is actually stored in the file. B refers to +the offset of a value when found at a fixed position within a data block +(B<#> is the multiplier for calculating a byte offset: B<1>, B<2>, B<4> or +B<8>). These offsets may have a decimal part which is used only to +differentiate tags with values stored at the same position. B +gives the order of values for a serial data stream. + +A B is the handle by which the information is accessed in +ExifTool. In some instances, more than one name may correspond to a single +tag ID. In these cases, the actual name used depends on the context in +which the information is found. Case is not significant for tag names. A +question mark (C) after a tag name indicates that the information is +either not understood, not verified, or not very useful -- these tags are +not extracted by ExifTool unless the Unknown (-u) option is enabled. Be +aware that some tag names are different than the descriptions printed out by +default when extracting information with exiftool. To see the tag names +instead of the descriptions, use C. + +The B column indicates whether the tag is writable by ExifTool. +Anything but a C in this column means the tag is writable. A C +indicates writable information that is either unformatted or written using +the existing format. Other expressions give details about the information +format, and vary depending on the general type of information. The format +name may be followed by a number in square brackets to indicate the number +of values written, or the number of characters in a fixed-length string +(including a null terminator which is added if required). + +A plus sign (C<+>) after an entry in the B column indicates a +I tag which supports multiple values and allows individual values to +be added and deleted. A slash (C) indicates a tag that ExifTool will +I when writing. These tags are not created when writing if another +same-named tag may be created instead. To write these tags, the group +should be specified. A tilde (C<~>) indicates a tag this is writable only +when the print conversion is disabled (by setting PrintConv to 0, using the +-n option, or suffixing the tag name with a C<#> character). An exclamation +point (C) indicates a tag that is considered I to write under +normal circumstances. These tags are not written unless specified +explicitly (ie. not when wildcards or "all" are used), and care should be +taken when editing them manually since they may affect the way an image is +rendered. An asterisk (C<*>) indicates a I tag which is not +writable directly, but is written automatically by ExifTool (often when a +corresponding L or +L tag is written). A colon +(C<:>) indicates a I tag which may be added automatically when +writing. + +The HTML version of these tables also lists possible B for +discrete-valued tags, as well as B for some tags. The B are +listed as the computer-readable and human-readable values on the left and +right hand side of an equals sign (C<=>) respectively. The human-readable +values are used by default when reading and writing, but the +computer-readable values may be accessed by disabling the value conversion +with the -n option on the command line, by setting the ValueConv option to 0 +in the API, or or on a per-tag basis by adding a hash (C<#>) after the tag +name. + +B: If you are familiar with common meta-information tag names, you may +find that some ExifTool tag names are different than expected. The usual +reason for this is to make the tag names more consistent across different +types of meta information. To determine a tag name, either consult this +documentation or run C on a file containing the information in +question. + +I<(This documentation is the result of years of research, testing and +reverse engineering, and is the most complete metadata tag list available +anywhere on the internet. It is provided not only for ExifTool users, but +more importantly as a public service to help augment the collective +knowledge, and is often used as a primary source of information in the +development of other metadata software. Please help keep this documentation +as accurate and complete as possible, and feed any new discoveries back to +ExifTool. A big thanks to everyone who has helped with this so far!)> +}, + EXIF => q{ +EXIF stands for "Exchangeable Image File Format". This type of information +is formatted according to the TIFF specification, and may be found in JPG, +TIFF, PNG, JP2, PGF, MIFF, HDP, PSP and XCF images, as well as many +TIFF-based RAW images, and even some AVI and MOV videos. + +The EXIF meta information is organized into different Image File Directories +(IFD's) within an image. The names of these IFD's correspond to the +ExifTool family 1 group names. When writing EXIF information, the default +B listed below is used unless another group is specified. + +Mandatory tags (indicated by a colon after the B type) may be +added automatically with default values when creating a new IFD, and the IFD +is removed automatically when deleting tags if only default-valued mandatory +tags remain. + +The table below lists all EXIF tags. Also listed are TIFF, DNG, HDP and +other tags which are not part of the EXIF specification, but may co-exist +with EXIF tags in some images. Tags which are part of the EXIF 2.31 +specification have an underlined B in the HTML version of this +documentation. See +L for the +official EXIF 2.31 specification. +}, + GPS => q{ +These GPS tags are part of the EXIF standard, and are stored in a separate +IFD within the EXIF information. + +ExifTool is very flexible about the input format when writing lat/long +coordinates, and will accept from 1 to 3 floating point numbers (for decimal +degrees, degrees and minutes, or degrees, minutes and seconds) separated by +just about anything, and will format them properly according to the EXIF +specification. + +Some GPS tags have values which are fixed-length strings. For these, the +indicated string lengths include a null terminator which is added +automatically by ExifTool. Remember that the descriptive values are used +when writing (eg. 'Above Sea Level', not '0') unless the print conversion is +disabled (with '-n' on the command line or the PrintConv option in the API, +or by suffixing the tag name with a C<#> character). + +When adding GPS information to an image, it is important to set all of the +following tags: GPSLatitude, GPSLatitudeRef, GPSLongitude, GPSLongitudeRef, +and GPSAltitude and GPSAltitudeRef if the altitude is known. ExifTool will +write the required GPSVersionID tag automatically if new a GPS IFD is added +to an image. +}, + XMP => q{ +XMP stands for "Extensible Metadata Platform", an XML/RDF-based metadata +format which is being pushed by Adobe. Information in this format can be +embedded in many different image file types including JPG, JP2, TIFF, GIF, +EPS, PDF, PSD, IND, INX, PNG, DJVU, SVG, PGF, MIFF, XCF, CRW, DNG and a +variety of proprietary TIFF-based RAW images, as well as MOV, AVI, ASF, WMV, +FLV, SWF and MP4 videos, and WMA and audio formats supporting ID3v2 +information. + +The XMP B's aren't listed because in most cases they are identical +to the B (aside from differences in case). Tags with different +ID's are mentioned in the B column of the HTML version of this +document. + +All XMP information is stored as character strings. The B column +specifies the information format: C is an unformatted string, +C is a string of digits (possibly beginning with a '+' or '-'), +C is a floating point number, C is entered as a floating +point number but stored as two C strings separated by a '/' +character, C is a date/time string entered in the format "YYYY:mm:dd +HH:MM:SS[.ss][+/-HH:MM]", C is either "True" or "False", C +indicates a structured tag, and C is a tag that supports alternate +languages. + +When reading, C tags are extracted only if the Struct (-struct) +option is used. Otherwise the corresponding I tags, indicated by +an underline (C<_>) after the B type, are extracted. When +copying, by default both structured and flattened tags are available, but +the flattened tags are considered "unsafe" so they they aren't copied unless +specified explicitly. The Struct option may be disabled by setting Struct +to 0 via the API or with --struct on the command line to copy only flattened +tags, or enabled by setting Struct to 1 via the API or with -struct on the +command line to copy only as structures. When writing, the Struct option +has no effect, and both structured and flattened tags may be written. See +L for more details. + +Individual languages for C tags are accessed by suffixing the tag +name with a '-', followed by an RFC 3066 language code (eg. "XMP:Title-fr", +or "Rights-en-US"). (See L for the RFC +3066 specification.) A C tag with no language code accesses the +"x-default" language, but causes other languages for this tag to be deleted +when writing. The "x-default" language code may be specified when writing +to preserve other existing languages (eg. "XMP-dc:Description-x-default"). +When reading, "x-default" is not specified. + +The XMP tags are organized according to schema B in the following +tables. The ExifTool family 1 group names are derived from the namespace +prefixes by adding a leading "XMP-" (eg. "XMP-dc"). A few of the longer +prefixes have been shortened (as mentioned in the documentation below) to +avoid excessively long ExifTool group names. The tags of any namespace may +be deleted as a group by specifying the family 1 group name (eg. +"-XMP-dc:all=" on the command line). This includes namespaces which are not +pre-defined by ExifTool. + +In cases where a tag name exists in more than one namespace, less common +namespaces are avoided when writing. However, a specific namespace may be +written by providing a family 1 group name for the tag (eg. XMP-crs:Contrast +or XMP-exif:Contrast). When deciding on which tags to add to an image, +using standard schemas such as L, L, +L and L is +recommended if possible. + +For structures, the heading of the first column is B. Field +names are very similar to tag names, except they are used to identify fields +inside structures instead of stand-alone tags. See +L for more +details. + +ExifTool will extract XMP information even if it is not listed in these +tables, but other tags are not writable unless added as user-defined tags in +the L. For example, the C namespace doesn't have a +predefined set of tag names because it is used to store application-defined +PDF information, so although this information will be extracted, it is only +writable if the corresponding user-defined tags have been created. + +The tables below list tags from the official XMP specification (with an +underlined B in the HTML version of this documentation), as well +as extensions from various other sources. See +L for the official XMP specification. +}, + IPTC => q{ +The tags listed below are part of the International Press Telecommunications +Council (IPTC) and the Newspaper Association of America (NAA) Information +Interchange Model (IIM). This is an older meta information format, slowly +being phased out in favor of XMP -- the newer IPTCCore specification uses +XMP format. IPTC information may be found in JPG, TIFF, PNG, MIFF, PS, PDF, +PSD, XCF and DNG images. + +IPTC information is separated into different records, each of which has its +own set of tags. See +L for the +official IPTC IIM specification. + +This specification dictates a length for ASCII (C or C) and +binary (C) values. These lengths are given in square brackets after +the B format name. For tags where a range of lengths is allowed, +the minimum and maximum lengths are separated by a comma within the +brackets. When writing, ExifTool issues a minor warning and truncates the +value if it is longer than allowed by the IPTC specification. Minor errors +may be ignored with the IgnoreMinorErrors (-m) option, allowing longer +values to be written, but beware that values like this may cause problems +for some other IPTC readers. ExifTool will happily read IPTC values of any +length. + +Separate IPTC date and time tags may be written with a combined date/time +value and ExifTool automagically takes the appropriate part of the date/time +string depending on whether a date or time tag is being written. This is +very useful when copying date/time values to IPTC from other metadata +formats. + +IPTC time values include a timezone offset. If written with a value which +doesn't include a timezone then the current local timezone offset is used +(unless written with a combined date/time, in which case the local timezone +offset at the specified date/time is used, which may be different due to +changes in daylight savings time). + +Note that it is not uncommon for IPTC to be found in non-standard locations +in JPEG and TIFF-based images. When reading, the family 1 group name has a +number added for non-standard IPTC ("IPTC2", "IPTC3", etc), but when writing +only "IPTC" may be specified as the group. To keep the IPTC consistent, +ExifTool updates tags in all existing IPTC locations, but will create a new +IPTC group only in the standard location. +}, + Photoshop => q{ +Photoshop tags are found in PSD and PSB files, as well as inside embedded +Photoshop information in many other file types (JPEG, TIFF, PDF, PNG to name +a few). + +Many Photoshop tags are marked as Unknown (indicated by a question mark +after the tag name) because the information they provide is not very useful +under normal circumstances. These unknown tags are not extracted unless the +Unknown (-u) option is used. See +L for the +official specification + +Photoshop path tags (Tag ID's 0x7d0 to 0xbb5) are not defined by default, +but a config file included in the full ExifTool distribution +(config_files/photoshop_paths.config) contains the tag definitions to allow +access to this information. +}, + PrintIM => q{ +The format of the PrintIM information is known, however no PrintIM tags have +been decoded. Use the Unknown (-u) option to extract PrintIM information. +}, + GeoTiff => q{ +ExifTool extracts the following tags from GeoTIFF images. See +L for the +complete GeoTIFF specification. Also included in the table below are +ChartTIFF tags (see L). GeoTIFF +tags are not writable individually, but they may be copied en mass via the +block tags GeoTiffDirectory, GeoTiffDoubleParams and GeoTiffAsciiParams. +}, + JFIF => q{ +The following information is extracted from the JPEG JFIF header. See +L for the JFIF 1.02 +specification. +}, + Kodak => q{ +Many Kodak models don't store the maker notes in standard IFD format, and +these formats vary with different models. Some information has been +decoded, but much of the Kodak information remains unknown. +}, + 'Kodak SpecialEffects' => q{ +The Kodak SpecialEffects and Borders tags are found in sub-IFD's within the +Kodak JPEG APP3 "Meta" segment. +}, + Minolta => q{ +These tags are used by Minolta, Konica/Minolta as well as some Sony cameras. +Minolta doesn't make things easy for decoders because the meaning of some +tags and the location where some information is stored is different for +different camera models. (Take MinoltaQuality for example, which may be +located in 5 different places.) +}, + Olympus => q{ +Tags 0x0000 through 0x0103 are used by some older Olympus cameras, and are +the same as Konica/Minolta tags. These tags are also used for some models +from other brands such as Acer, BenQ, Epson, Hitachi, HP, Maginon, Minolta, +Pentax, Ricoh, Samsung, Sanyo, SeaLife, Sony, Supra and Vivitar. +}, + Panasonic => q{ +These tags are used in Panasonic/Leica cameras. +}, + Pentax => q{ +These tags are used in Pentax/Asahi cameras. +}, + CanonRaw => q{ +These tags apply to CRW-format Canon RAW files and information in the APP0 +"CIFF" segment of JPEG images. When writing CanonRaw/CIFF information, the +length of the information is preserved (and the new information is truncated +or padded as required) unless B is C. Currently, only +JpgFromRaw and ThumbnailImage are allowed to change size. + +CRW images also support the addition of a CanonVRD trailer, which in turn +supports XMP. This trailer is created automatically if necessary when +ExifTool is used to write XMP to a CRW image. +}, + NikonCustom => q{ +Unfortunately, the NikonCustom settings are stored in a binary data block +which changes from model to model. This means that significant effort must +be spent in decoding these for each model, usually requiring hundreds of +test images from a dedicated Nikon owner. For this reason, the NikonCustom +settings have not been decoded for all models. The tables below list the +custom settings for the currently supported models. +}, + Unknown => q{ +The following tags are decoded in unsupported maker notes. Use the Unknown +(-u) option to display other unknown tags. +}, + PDF => q{ +The tags listed in the PDF tables below are those which are used by ExifTool +to extract meta information, but they are only a small fraction of the total +number of available PDF tags. See +L for the official PDF +specification. + +ExifTool supports reading and writing PDF documents up to version 1.7 +extension level 3, including support for RC4, AES-128 and AES-256 +encryption. A Password option is provided to allow processing of +password-protected PDF files. + +ExifTool may be used to write native PDF and XMP metadata to PDF files. It +uses an incremental update technique that has the advantages of being both +fast and reversible. If ExifTool was used to modify a PDF file, the +original may be recovered by deleting the C pseudo-group (with +C<-PDF-update:all=> on the command line). However, there are two main +disadvantages to this technique: + +1) A linearized PDF file is no longer linearized after the update, so it +must be subsequently re-linearized if this is required. + +2) All metadata edits are reversible. While this would normally be +considered an advantage, it is a potential security problem because old +information is never actually deleted from the file. (However, after +running ExifTool the old information may be removed permanently using the +"qpdf" utility with this command: "qpdf --linearize in.pdf out.pdf".) +}, + DNG => q{ +The main DNG tags are found in the EXIF table. The tables below define only +information found within structures of these main DNG tag values. See +L for the official DNG specification. +}, + MPEG => q{ +The MPEG format doesn't specify any file-level meta information. In lieu of +this, information is extracted from the first audio and video frame headers +in the file. +}, + Real => q{ +ExifTool recognizes three basic types of Real audio/video files: 1) +RealMedia (RM, RV and RMVB), 2) RealAudio (RA), and 3) Real Metafile (RAM +and RPM). +}, + Extra => q{ +The extra tags provide extra features or extra information extracted or +generated by ExifTool that is not directly associated with another tag +group. The B column lists the family 1 group name when reading. +Tags with a "-" in this column are write-only. + +Tags in the family 1 "System" group are referred to as "pseudo" tags because +they don't represent real metadata in the file. Instead, this information +is stored in the directory structure of the filesystem. The B +System "pseudo" tags in this table may be written without modifying the file +itself. The TestName tag is used for dry-run testing before writing +FileName. +}, + Composite => q{ +The values of the composite tags are B the values of other +tags. These are convenience tags which are calculated after all other +information is extracted. Only a few of these tags are writable directly, +the others are changed by writing the corresponding B tags. +User-defined Composite tags, also useful for custom-formatting of tag +values, may created via the L. +}, + Shortcuts => q{ +Shortcut tags are convenience tags that represent one or more other tag +names. They are used like regular tags to read and write the information +for a specified set of tags. + +The shortcut tags below have been pre-defined, but user-defined shortcuts +may be added via the %Image::ExifTool::UserDefined::Shortcuts lookup in the +~/.ExifTool_config file. See the Image::ExifTool::Shortcuts documentation +for more details. +}, + MWG => q{ +The Metadata Working Group (MWG) recommends techniques to allow certain +overlapping EXIF, IPTC and XMP tags to be reconciled when reading, and +synchronized when writing. The MWG Composite tags below are designed to aid +in the implementation of these recommendations. As well, the MWG defines +new XMP tags which are listed in the subsequent tables below. See +L for the official MWG specification. +}, + MacOS => q{ +On MacOS systems, there are a number of additional tags with names beginning +with "MDItem" and "XAttr" that may be extracted. These tags are not +extracted by default -- they must be specifically requested or enabled via +an API option. + +The tables below list some of the tags that may be extracted, but ExifTool +will extract all available information even for tags not listed. + +Tags in these tables are referred to as "pseudo" tags because their +information is not stored in the file itself. As such, B tags in +these tables may be changed without having to rewrite the file. +}, + PodTrailer => q{ +~head1 NOTES + +This document generated automatically by +L. + +~head1 AUTHOR + +Copyright 2003-2019, Phil Harvey (phil at owl.phy.queensu.ca) + +This library is free software; you can redistribute it and/or modify it +under the same terms as Perl itself. + +~head1 SEE ALSO + +L + +~cut +}, +); + +# notes for Shortcuts tags +my %shortcutNotes = ( + AllDates => q{ + contrary to the shortcut name, this represents only the common EXIF + date/time tags. To access all date/time tags, use Time:All instead + }, + MakerNotes => q{ + useful when copying tags between files to either copy the maker notes as a + block or prevent it from being copied + }, + ColorSpaceTags => q{ + standard tags which carry color space information. Useful for preserving + color space when deleting all other metadata + }, + CommonIFD0 => q{ + common metadata tags found in IFD0 of TIFF-format images. Used to simpify + deletion of all metadata from these images. See + L for details + }, + Unsafe => q{ + I tags in JPEG images which are normally not copied. Defined here + as a shortcut to use when rebuilding JPEG EXIF from scratch. See + L for more information + }, + LargeTags => q{ + large binary data tags which may be excluded to reduce memory usage if + memory limitations are a problem + }, +); + + +# same thing for RIFF INFO tags found in the EXIF spec +my %riffSpec = ( + IARL => 1, ICRD => 1, IGNR => 1, IPLT => 1, ISRC => 1, + IART => 1, ICRP => 1, IKEY => 1, IPRD => 1, ISRF => 1, + ICMS => 1, IDIM => 1, ILGT => 1, ISBJ => 1, ITCH => 1, + ICMT => 1, IDPI => 1, IMED => 1, ISFT => 1, + ICOP => 1, IENG => 1, INAM => 1, ISHP => 1, +); +# same thing for XMP namespaces +my %xmpSpec = ( + aux => 1, 'x' => 1, + crs => 1, xmp => 1, + dc => 1, xmpBJ => 1, + exif => 1, xmpDM => 1, + pdf => 1, xmpMM => 1, + pdfx => 1, xmpNote => 1, + photoshop => 1, xmpRights => 1, + tiff => 1, xmpTPg => 1, +); + +#------------------------------------------------------------------------------ +# New - create new BuildTagLookup object +# Inputs: 0) reference to BuildTagLookup object or BuildTagLookup class name +sub new +{ + local $_; + my $that = shift; + my $class = ref($that) || $that || 'Image::ExifTool::BuildTagLookup'; + my $self = bless {}, $class; + my (%subdirs, %isShortcut, %allStructs); + my %count = ( + 'unique tag names' => 0, + 'total tags' => 0, + ); +# +# loop through all tables, accumulating TagLookup and TagName information +# + my (%tagNameInfo, %id, %longID, %longName, %shortName, %tableNum, + %tagLookup, %tagExists, %noLookup, %tableWritable, %sepTable, %case, + %structs, %compositeModules, %isPlugin, %flattened, %structLookup, + @writePseudo); + $self->{TAG_NAME_INFO} = \%tagNameInfo; + $self->{ID_LOOKUP} = \%id; + $self->{LONG_ID} = \%longID; + $self->{LONG_NAME} = \%longName; + $self->{SHORT_NAME} = \%shortName; + $self->{TABLE_NUM} = \%tableNum; + $self->{TAG_LOOKUP} = \%tagLookup; + $self->{TAG_EXISTS} = \%tagExists; + $self->{FLATTENED} = \%flattened; + $self->{TABLE_WRITABLE} = \%tableWritable; + $self->{SEPARATE_TABLE} = \%sepTable; + $self->{STRUCTURES} = \%structs; + $self->{STRUCT_LOOKUP} = \%structLookup; # lookup for Struct hash ref based on Struct name + $self->{COMPOSITE_MODULES} = \%compositeModules; + $self->{COUNT} = \%count; + $self->{WRITE_PSEUDO} = \@writePseudo; + + Image::ExifTool::LoadAllTables(); + my @tableNames = sort keys %allTables; + # add Shortcuts after other tables + push @tableNames, 'Image::ExifTool::Shortcuts::Main'; + # add plug-in modules last + foreach (@pluginTables) { + push @tableNames, $_; + $isPlugin{$_} = 1; + } + + my $tableNum = 0; + my $et = new Image::ExifTool; + my ($tableName, $tag); + # create lookup for short table names + foreach $tableName (@tableNames) { + my $short = $tableName; + $short =~ s/^Image::ExifTool:://; + $short =~ s/::Main$//; + $short =~ s/::/ /; + $short =~ s/^(.+)Tags$/\u$1/ unless $short eq 'Nikon AVITags'; + $short =~ s/^Exif\b/EXIF/; + # change underlines to dashes in XMP-mwg group names + # (we used underlines just because Perl variables can't contain dashes) + $short =~ s/^XMP mwg_/XMP mwg-/; + $shortName{$tableName} = $short; # remember short name + $tableNum{$tableName} = $tableNum++; + } + # validate DICOM UID values + foreach (values %Image::ExifTool::DICOM::uid) { + next unless /[\0-\x1f\x7f-\xff]/; + warn "Warning: Special characters in DICOM UID value ($_)\n"; + } + # make lookup table to check for shortcut tags + foreach $tag (keys %Image::ExifTool::Shortcuts::Main) { + my $entry = $Image::ExifTool::Shortcuts::Main{$tag}; + # ignore if shortcut tag name includes itself + next if ref $entry eq 'ARRAY' and grep /^$tag$/, @$entry; + $isShortcut{lc($tag)} = 1; + } + foreach $tableName (@tableNames) { + # create short table name + my $short = $shortName{$tableName}; + my $info = $tagNameInfo{$tableName} = [ ]; + my $isPlugin = $isPlugin{$tableName}; + my ($table, $shortcut, %isOffset, %datamember, %hasSubdir); + if ($short eq 'Shortcuts') { + # can't use GetTagTable() for Shortcuts (not a normal table) + $table = \%Image::ExifTool::Shortcuts::Main; + $shortcut = 1; + } elsif ($isPlugin) { + $table = GetTagTable($tableName); + # don't add to allTables list because this messes our table order + delete $allTables{$tableName}; + pop @tableOrder; + } else { + $table = GetTagTable($tableName); + } + my $tableNum = $tableNum{$tableName}; + my $writeProc = $$table{WRITE_PROC}; + my $vars = $$table{VARS} || { }; + $longID{$tableName} = 0; + $longName{$tableName} = 0; + # save all tag names + my ($tagID, $binaryTable, $noID, $hexID, $isIPTC, $isXMP); + $isIPTC = 1 if $writeProc and $writeProc eq \&Image::ExifTool::IPTC::WriteIPTC; + # generate flattened tag names for structure fields if this is an XMP table + if ($$table{GROUPS} and $$table{GROUPS}{0} eq 'XMP') { + Image::ExifTool::XMP::AddFlattenedTags($table); + $isXMP = 1; + } + $noID = 1 if $isXMP or $short =~ /^(Shortcuts|ASF.*)$/ or $$vars{NO_ID}; + $hexID = $$vars{HEX_ID}; + my $processBinaryData = ($$table{PROCESS_PROC} and ( + $$table{PROCESS_PROC} eq \&Image::ExifTool::ProcessBinaryData or + $$table{PROCESS_PROC} eq \&Image::ExifTool::Nikon::ProcessNikonEncrypted)); + if ($$vars{ID_LABEL} or $processBinaryData) { + my $s = $$table{FORMAT} ? Image::ExifTool::FormatSize($$table{FORMAT}) || 1 : 1; + $binaryTable = 1; + $id{$tableName} = $$vars{ID_LABEL} || "Index$s"; + } elsif ($isIPTC and $$table{PROCESS_PROC}) { #only the main IPTC table has a PROCESS_PROC + $id{$tableName} = 'Record'; + } elsif (not $noID) { + $id{$tableName} = 'Tag ID'; + } + $caseInsensitive = $isXMP; + $numbersFirst = 2; + $numbersFirst = -1 if $$table{VARS} and $$table{VARS}{ALPHA_FIRST}; + my @keys = SortedTagTableKeys($table); + $numbersFirst = 1; + my $defFormat = $table->{FORMAT}; + # use default format for binary data tables + $defFormat = 'int8u' if not $defFormat and $binaryTable; + +TagID: foreach $tagID (@keys) { + my ($tagInfo, @tagNames, $subdir, @values); + my (@infoArray, @require, @writeGroup, @writable); + if ($shortcut) { + # must build a dummy tagInfo list since Shortcuts is not a normal table + $tagInfo = { + Name => $tagID, + Notes => $shortcutNotes{$tagID}, + Writable => 1, + Require => { }, + }; + my $i; + for ($i=0; $i<@{$$table{$tagID}}; ++$i) { + $tagInfo->{Require}->{$i} = $table->{$tagID}->[$i]; + } + @infoArray = ( $tagInfo ); + } else { + @infoArray = GetTagInfoList($table,$tagID); + } + foreach $tagInfo (@infoArray) { + my $name = $$tagInfo{Name}; + if ($$tagInfo{WritePseudo}) { + push @writePseudo, $name; + warn "Writable pseudo tag $name is not protected!\n" unless $$tagInfo{Protected}; + } + unless ($$tagInfo{SubDirectory} or $$tagInfo{Struct}) { + my $lc = lc $name; + warn "Different case for $tableName $name $case{$lc}\n" if $case{$lc} and $case{$lc} ne $name; + $case{$lc} = $name; + } + my $format = $$tagInfo{Format}; + # validate Name (must not start with a digit or else XML output will not be valid; + # must not start with a dash or exiftool command line may get confused) + if ($name !~ /^[_A-Za-z][-\w]+$/ and + # single-character subdirectory names are allowed + (not $$tagInfo{SubDirectory} or $name !~ /^[_A-Za-z]$/)) + { + warn "Warning: Invalid tag name $short '${name}'\n"; + } + # validate list type + if ($$tagInfo{List} and $$tagInfo{List} !~ /^(1|Alt|Bag|Seq|array|string)$/) { + warn "Warning: Unknown List type ($$tagInfo{List}) for $name in $tableName\n"; + } + # accumulate information for consistency check of BinaryData tables + if ($processBinaryData and $$table{WRITABLE}) { + # can't currently write tag if Condition accesses $valPt + if ($$tagInfo{Condition} and not $$tagInfo{SubDirectory} and + $$tagInfo{Condition} =~ /\$valPt/ and + ($$tagInfo{Writable} or not defined $$tagInfo{Writable})) + { + warn "Warning: Tag not writable due to Condition - $short $name\n"; + } + $isOffset{$tagID} = $name if $$tagInfo{IsOffset}; + $hasSubdir{$tagID} = $name if $$tagInfo{SubDirectory}; + # require DATAMEMBER for writable var-format tags, Hook and DataMember tags + if ($format and $format =~ /^var_/) { + $datamember{$tagID} = $name; + unless (defined $$tagInfo{Writable} and not $$tagInfo{Writable}) { + warn "Warning: Var-format tag is writable - $short $name\n" + } + # also need DATAMEMBER for tags used in length of var-sized value + while ($format =~ /\$val\{(.*?)\}/g) { + my $id = $1; + $id = hex($id) if $id =~ /^0x/; # convert from hex if necessary + $datamember{$id} = $$table{$id}{Name} if ref $$table{$id} eq 'HASH'; + unless ($datamember{$id}) { + warn "Warning: Unknown ID ($id) used in Format - $short $name\n"; + } + } + } elsif ($$tagInfo{Hook} or ($$tagInfo{RawConv} and + $$tagInfo{RawConv} =~ /\$self(->)?\{\w+\}\s*=(?!~)/)) + { + $datamember{$tagID} = $name; + } + if ($format and $format =~ /\$val\{/ and + ($$tagInfo{Writable} or not defined $$tagInfo{Writable})) + { + warn "Warning: \$var{} used in Format of writable tag - $short $name\n" + } + } + if ($$tagInfo{Hidden}) { + if ($tagInfo == $infoArray[0]) { + next TagID; # hide all tags with this ID if first tag in list is hidden + } else { + next; # only hide this tag + } + } + my $writable; + if (defined $$tagInfo{Writable}) { + $writable = $$tagInfo{Writable}; + # validate Writable + unless ($formatOK{$writable} or ($writable =~ /(.*)\[/ and $formatOK{$1})) { + warn "Warning: Unknown Writable ($writable) - $short $name\n", + } + } elsif (not $$tagInfo{SubDirectory}) { + $writable = $$table{WRITABLE}; + } + # validate some characteristics of obvious date/time tags + my @g = $et->GetGroup($tagInfo); + if ($$tagInfo{List} and $g[2] eq 'Time' and $writable and not $$tagInfo{Protected} and + not $$tagInfo{PrintConvInv}) + { + # (this is a problem because shifting Time:All would create a new list entry) + warn "Writable List-type Time tag $g[1]:$name has no PrintConvInv and is not Protected!\n"; + } + if ($$tagInfo{PrintConv} and $$tagInfo{PrintConv} eq '$self->ConvertDateTime($val)') { + warn "$short $name should be in 'Time' group!\n" unless $g[2] eq 'Time'; + if ($writable and not defined $$tagInfo{Shift} and $short ne 'PostScript') { + warn "$short $name is not shiftable!\n"; + } + if ($writable and (not $$tagInfo{PrintConvInv} or + $$tagInfo{PrintConvInv} !~ /InverseDateTime/)) + { + warn "$short $name missing InverseDateTime PrintConvInv\n"; + } + } elsif ($name =~ /DateTime(?!Stamp)/ and (not $$tagInfo{Groups}{2} or + $$tagInfo{Groups}{2} ne 'Time') and $short ne 'DICOM') { + warn "$short $name should be in 'Time' group!\n"; + } + # validate Description (can't contain special characters) + if ($$tagInfo{Description} and + $$tagInfo{Description} ne EscapeHTML($$tagInfo{Description})) + { + # this is a problem because the Escape option currently only + # escapes descriptions if the default Lang option isn't default + warn "$name description contains special characters!\n"; + } + # generate structure lookup + my $struct = $$tagInfo{Struct}; + my $strTable; + if (ref $struct) { + $strTable = $struct; + $struct = $$strTable{STRUCT_NAME}; + if ($struct) { + my $oldTable = $structLookup{$struct}; + if ($oldTable and $oldTable ne $strTable) { + warn "Duplicate XMP structure with name $struct\n"; + } else { + $structLookup{$struct} = $strTable; + } + } else { + warn "Missing STRUCT_NAME for structure in $$tagInfo{Name}\n"; + undef $strTable; + } + } elsif ($struct) { + $strTable = $structLookup{$struct}; + unless ($strTable) { + $struct = "XMP $struct" unless $struct =~ / /; + warn "Missing $struct structure!\n"; + undef $struct; + } + } + # validate SubIFD flag + my $subdir = $$tagInfo{SubDirectory}; + my $isSub = ($subdir and $$subdir{Start} and $$subdir{Start} =~ /\$val\b/); + if ($$tagInfo{SubIFD}) { + warn "Warning: Wrong SubDirectory Start for SubIFD tag - $short $name\n" unless $isSub; + } else { + warn "Warning: SubIFD flag not set for $short $name\n" if $isSub; + } + if ($$tagInfo{Notes}) { + my $note = $$tagInfo{Notes}; + # remove leading/trailing blank lines + $note =~ s/^\s+//; $note =~ s/\s+$//; + # remove leading/trailing spaces on each line + $note =~ s/(^[ \t]+|[ \t]+$)//mg; + push @values, "($note)"; + } + if ($isXMP and lc $tagID ne lc $name) { + # add note about different XMP Tag ID + my $note = $$tagInfo{RootTagInfo} ? $tagID : "called $tagID by the spec"; + if ($$tagInfo{Notes}) { + $values[-1] =~ s/^\(/($note; /; + } else { + push @values, "($note)"; + } + } + my $writeGroup; + if ($short eq 'Extra') { + $writeGroup = $$tagInfo{WriteOnly} ? '-' : $g[1]; + } else { + $writeGroup = $$tagInfo{WriteGroup}; + } + unless ($writeGroup) { + $writeGroup = $$table{WRITE_GROUP} if $writable; + $writeGroup = '-' unless $writeGroup; + } + if (defined $format) { + # validate Format + unless ($formatOK{$format} or $short eq 'PICT' or + ($format =~ /^(var_)?(.*)\[/ and $formatOK{$2})) + { + warn "Warning: Unknown Format ($format) for $short $name\n"; + } + } else { + $format = $defFormat; + } + if ($subdir) { + my $subTable = $$subdir{TagTable} || $tableName; + push @values, $shortName{$subTable} + } elsif ($struct) { + push @values, $struct; + $structs{$struct} = 1; + } + my $type; + foreach $type ('Require','Desire') { + my $require = $$tagInfo{$type}; + if (ref $require) { + foreach (sort { $a <=> $b } keys %$require) { + push @require, $$require{$_}; + } + } elsif ($require) { + push @require, $require; + } + } + my $printConv = $$tagInfo{PrintConv}; + if ($$tagInfo{Mask}) { + my $val = $$tagInfo{Mask}; + my $bsh = $$tagInfo{BitShift}; + if ($bsh) { + push @values, sprintf('[val >> %d & 0x%x]',$bsh,$val>>$bsh); + } else { + push @values, sprintf('[val & 0x%x]',$val); + } + # verify that all values are within the mask + if (ref $printConv eq 'HASH') { + $val >>= $$tagInfo{BitShift}; + foreach (keys %$printConv) { + next if $_ !~ /^\d+$/ or ($_ & $val) == $_; + my $hex = sprintf '0x%.2x', $_; + warn "$short $name PrintConv value $hex is not in Mask!\n"; + } + } + } + if (ref($printConv) =~ /^(HASH|ARRAY)$/) { + my (@printConvList, @indexList, $index, $valueConvHash); + if (ref $printConv eq 'ARRAY') { + for ($index=0; $index<@$printConv; ++$index) { + if (ref $$printConv[$index] eq 'HASH') { + next unless %{$$printConv[$index]}; + push @printConvList, $$printConv[$index]; + push @indexList, $index; + } elsif ($$printConv[$index] and $$printConv[$index] eq 'REPEAT' and $index) { + push @printConvList, $$printConv[$index-1]; + push @indexList, 'N'; + } else { + next; + } + # collapse values with identical PrintConv's + if (@printConvList >= 2 and $printConvList[-1] eq $printConvList[-2]) { + if (ref $indexList[-2]) { + push @{$indexList[-2]}, $indexList[-1]; + } else { + $indexList[-2] = [ $indexList[-2], $indexList[-1] ]; + } + pop @printConvList; + pop @indexList; + } + } + $printConv = shift @printConvList; + $index = shift @indexList; + } else { + $valueConvHash = $$tagInfo{ValueConv} if ref $$tagInfo{ValueConv} eq 'HASH'; + } + while (defined $printConv) { + if (defined $index) { + # (print indices of original values if reorganized) + my $s = ''; + my $idx = $$tagInfo{Relist} ? $tagInfo->{Relist}->[$index] : $index; + if (ref $idx) { + $s = 's' if @$idx > 1; + # collapse consecutive number ranges + my ($i, @i, $rngStart); + for ($i=0; $i<@$idx; ++$i) { + if ($i < @$idx - 1 and ($$idx[$i+1] eq 'N' or $$idx[$i+1] == $$idx[$i] + 1)) { + $rngStart = $$idx[$i] unless defined $rngStart; + next; + } + push @i, (defined($rngStart) ? "$rngStart-" : '') . $$idx[$i]; + } + ($idx = join ', ', @i) =~ s/(.*),/$1 and/; + } elsif (not $$tagInfo{Relist}) { + while (@printConvList and $printConv eq $printConvList[0]) { + shift @printConvList; + $index = shift @indexList; + } + if ($idx != $index) { + $idx = "$idx-$index"; + $s = 's'; + } + } + push @values, "[Value$s $idx]"; + } + if ($$tagInfo{SeparateTable}) { + $subdir = 1; + my $s = $$tagInfo{SeparateTable}; + $s = $name if $s eq '1'; + # add module name if not specified + $s =~ / / or ($short =~ /^(\w+)/ and $s = "$1 $s"); + push @values, $s; + $sepTable{$s} = $printConv; + # add PrintHex flag to PrintConv so we can check it later + $$printConv{PrintHex} = 1 if $$tagInfo{PrintHex}; + $$printConv{PrintString} = 1 if $$tagInfo{PrintString}; + } else { + $caseInsensitive = 0; + my @pk; + if ($$tagInfo{PrintSort}) { + @pk = sort { NumbersFirst($$printConv{$a},$$printConv{$b}) } keys %$printConv; + } else { + @pk = sort { NumbersFirst($a,$b) } keys %$printConv; + } + my $n = scalar @values; + my ($bits, $i, $v); + foreach (@pk) { + next if $_ eq ''; + $_ eq 'BITMASK' and $bits = $$printConv{$_}, next; + $_ eq 'OTHER' and next; + my $index; + if (($$tagInfo{PrintHex} or $$printConv{BITMASK}) and /^-?\d+$/) { + my $dig = $$tagInfo{PrintHex} || 1; + if ($_ >= 0) { + $index = sprintf('0x%.*x', $dig, $_); + } elsif ($format and $format =~ /int(16|32)/) { + # mask off unused bits of signed integer hex value + my $mask = { 16 => 0xffff, 32 => 0xffffffff }->{$1}; + $index = sprintf('0x%.*x', $dig, $_ & $mask); + } else { + $index = $_; + } + } elsif (/^[+-]?(?=\d|\.\d)\d*(\.\d*)?$/ and not $$tagInfo{PrintString}) { + $index = $_; + } else { + $index = $_; + # translate unprintable values + if ($index =~ s/([\x00-\x1f\x80-\xff])/sprintf("\\x%.2x",ord $1)/eg) { + $index = qq{"$index"}; + } else { + $index = qq{'${index}'}; + } + } + push @values, "$index = " . $$printConv{$_}; + if ($valueConvHash) { + foreach $v (keys %$valueConvHash) { + next unless $$valueConvHash{$v} eq $_; + $values[-1] = "$v => " . $values[-1]; + last; + } + } + # validate all PrintConv values + if ($$printConv{$_} =~ /[\0-\x1f\x7f-\xff]/) { + warn "Warning: Special characters in $short $name PrintConv ($$printConv{$_})\n"; + } + } + if ($bits) { + my @pk = sort { NumbersFirst($a,$b) } keys %$bits; + foreach (@pk) { + push @values, "Bit $_ = " . $$bits{$_}; + } + } + # organize values into columns if specified + my $cols = $$tagInfo{PrintConvColumns}; + if (not $cols and scalar(@values) - $n >= 6) { + # do columns if more than 6 short entries + my $maxLen = 0; + for ($i=$n; $i<@values; ++$i) { + next unless $maxLen < length $values[$i]; + $maxLen = length $values[$i]; + } + my $num = scalar(@values) - $n; + $cols = int(50 / ($maxLen + 2)); # (50 chars max width) + # have 3 rows minimum + --$cols while $cols and $num / $cols < 3; + } + if ($cols) { + my @new = splice @values, $n; + my $v = '[!HTML]'; + my $rows = int((scalar(@new) + $cols - 1) / $cols); + for ($n=0; ;) { + $v .= "\n '; + last if ($n += $rows) >= @new; + $v .= ''; # add spaces between columns + } + push @values, $v . "
"; + for ($i=0; $i<$rows and $n+$i<@new; ++$i) { + $v .= "\n
" if $i; + $v .= EscapeHTML($new[$n+$i]); + } + $v .= '
  
\n"; + } + } + last unless @printConvList; + $printConv = shift @printConvList; + $index = shift @indexList; + } + } elsif ($printConv and $printConv =~ /DecodeBits\(\$val,\s*(\{.*\})\s*\)/s) { + $$self{Model} = ''; # needed for Nikon ShootingMode + my $bits = eval $1; + delete $$self{Model}; + if ($@) { + warn $@; + } else { + my @pk = sort { NumbersFirst($a,$b) } keys %$bits; + foreach (@pk) { + push @values, "Bit $_ = " . $$bits{$_}; + } + } + } + if ($subdir and not $$tagInfo{SeparateTable}) { + # subdirectories are only writable if specified explicitly + my $tw = $$tagInfo{Writable}; + $writable = 'yes' if $tw and $writable eq '1'; + $writable = '-' . ($tw ? $writable : ''); + $writable .= '!' if $tw and ($$tagInfo{Protected} || 0) & 0x01; + $writable .= '+' if $$tagInfo{List}; + } else { + # not writable if we can't do the inverse conversions + my $noPrintConvInv; + if ($writable) { + foreach ('PrintConv','ValueConv') { + next unless $$tagInfo{$_}; + next if $$tagInfo{$_ . 'Inv'}; + next if ref($$tagInfo{$_}) =~ /^(HASH|ARRAY)$/; + next if $$tagInfo{WriteAlso}; + if ($_ eq 'ValueConv') { + undef $writable; + } else { + $noPrintConvInv = 1; + } + } + } + if (not $writable) { + $writable = 'no'; + } else { + $writable eq '1' and $writable = $format ? $format : 'yes'; + my $count = $$tagInfo{Count} || 1; + # adjust count to Writable size if different than Format + if ($writable and $format and $writable ne $format and + $Image::ExifTool::Exif::formatNumber{$writable} and + $Image::ExifTool::Exif::formatNumber{$format}) + { + my $n1 = $Image::ExifTool::Exif::formatNumber{$format}; + my $n2 = $Image::ExifTool::Exif::formatNumber{$writable}; + $count *= $Image::ExifTool::Exif::formatSize[$n1] / + $Image::ExifTool::Exif::formatSize[$n2]; + } + if ($count != 1) { + $count = 'n' if $count < 0; + $writable .= "[$count]"; + } + $writable .= '~' if $noPrintConvInv; + # add a '*' if this tag is protected or a '!' for unsafe tags + if ($$tagInfo{Protected}) { + $writable .= '*' if $$tagInfo{Protected} & 0x02; + $writable .= '!' if $$tagInfo{Protected} & 0x01; + } + $writable .= '/' if $$tagInfo{Avoid}; + } + $writable = "=struct" if $struct; + $writable .= '_' if defined $$tagInfo{Flat}; + $writable .= '+' if $$tagInfo{List}; + $writable .= ':' if $$tagInfo{Mandatory}; + # separate tables link like subdirectories (flagged with leading '-') + $writable = "-$writable" if $subdir; + } + # don't duplicate a tag name unless an entry is different + my $lcName = lc($name); + # check for conflicts with shortcut names + if ($isShortcut{$lcName} and $short ne 'Shortcuts' and + ($$tagInfo{Writable} or not $$tagInfo{SubDirectory})) + { + warn "WARNING: $short $name is a shortcut tag!\n"; + } + $name .= '?' if $$tagInfo{Unknown}; + unless (@tagNames and $tagNames[-1] eq $name and + $writeGroup[-1] eq $writeGroup and $writable[-1] eq $writable) + { + push @tagNames, $name; + push @writeGroup, $writeGroup; + push @writable, $writable; + } +# +# add this tag to the tag lookup unless NO_LOOKUP is set or shortcut or plug-in tag +# + next if $shortcut or $isPlugin; + # count tags + if ($$tagInfo{SubDirectory}) { + next if $$vars{NO_LOOKUP}; + $subdirs{$lcName} or $subdirs{$lcName} = 0; + ++$subdirs{$lcName}; + } else { + ++$count{'total tags'}; + unless ($tagExists{$lcName} and + (not $subdirs{$lcName} or $subdirs{$lcName} == $tagExists{$lcName})) + { + ++$count{'unique tag names'} unless $noLookup{$lcName}; + } + # don't add to tag lookup if specified + $$vars{NO_LOOKUP} and $noLookup{$lcName} = 1, next; + } + $tagExists{$lcName} or $tagExists{$lcName} = 0; + ++$tagExists{$lcName}; + # only add writable tags to lookup table (for speed) + my $wflag = $$tagInfo{Writable}; + next unless $writeProc and ($wflag or ($$table{WRITABLE} and + not defined $wflag and not $$tagInfo{SubDirectory})); + $tagLookup{$lcName} or $tagLookup{$lcName} = { }; + # add to lookup for flattened tags if necessary + if ($$tagInfo{RootTagInfo}) { + $flattened{$lcName} or $flattened{$lcName} = { }; + $flattened{$lcName}{$tableNum} = $$tagInfo{RootTagInfo}{TagID}; + } + # remember number for this table + my $tagIDs = $tagLookup{$lcName}->{$tableNum}; + # must allow for duplicate tags with the same name in a single table! + if ($tagIDs) { + if (ref $tagIDs eq 'HASH') { + $$tagIDs{$tagID} = 1; + next; + } elsif ($tagID eq $tagIDs) { + next; + } else { + $tagIDs = { $tagIDs => 1, $tagID => 1 }; + } + } else { + $tagIDs = $tagID; + } + $tableWritable{$tableName} = 1; + $tagLookup{$lcName}->{$tableNum} = $tagIDs; + # keep track of extra modules needed for Composite tags + $compositeModules{$lcName} = $$tagInfo{Module} if $$tagInfo{Module}; + } +# +# save TagName information +# + my $tagIDstr; + if ($tagID =~ /^(-)?\d+(\.\d+)?$/) { + if ($1) { + $tagIDstr = $tagID; + } elsif (defined $hexID) { + $tagIDstr = $hexID ? sprintf('0x%.4x',$tagID) : $tagID; + } elsif (not $2 and not $binaryTable and not $isIPTC and + not ($short =~ /^CanonCustom/ and $tagID < 256)) + { + $tagIDstr = sprintf('0x%.4x',$tagID); + } elsif ($tagID < 0x10000) { + $tagIDstr = $tagID; + } else { + $tagIDstr = sprintf('0x%.8x',$tagID); + } + } elsif ($short eq 'DICOM') { + ($tagIDstr = $tagID) =~ s/_/,/; + } elsif ($tagID =~ /^0x([0-9a-f]+)\.(\d+)$/) { # DR4 tags like '0x20500.0' + $tagIDstr = $tagID; + } else { + # convert non-printable characters to hex escape sequences + if ($tagID =~ s/([\x00-\x1f\x7f-\xff])/'\x'.unpack('H*',$1)/eg) { + $tagID =~ s/\\x00/\\0/g; + next if $tagID eq 'jP\x1a\x1a'; # ignore abnormal JP2 signature tag + $tagIDstr = qq{"$tagID"}; + } else { + $tagIDstr = "'${tagID}'"; + } + } + my $len = length $tagIDstr; + $longID{$tableName} = $len if $longID{$tableName} < $len; + foreach (@tagNames) { + $len = length $_; + $longName{$tableName} = $len if $longName{$tableName} < $len; + } + push @$info, [ $tagIDstr, \@tagNames, \@writable, \@values, \@require, \@writeGroup ]; + } + # do consistency check of writable BinaryData tables + if ($processBinaryData and $$table{WRITABLE}) { + my %lookup = ( + IS_OFFSET => \%isOffset, + IS_SUBDIR => \%hasSubdir, + DATAMEMBER => \%datamember, + ); + my ($var, $tagID); + foreach $var (sort keys %lookup) { + my $hash = $lookup{$var}; + if ($$table{$var}) { + foreach $tagID (@{$$table{$var}}) { + $$hash{$tagID} and delete($$hash{$tagID}), next; + warn "Warning: Extra $var for $short tag $tagID\n"; + } + } + foreach $tagID (sort keys %$hash) { + warn "Warning: Missing $var for $short $$hash{$tagID}\n"; + } + } + } + } + # save information about structures + my $strName; + foreach $strName (keys %structs) { + my $struct = $structLookup{$strName}; + my $fullName = ($strName =~ / / ? '' : 'XMP ') . "$strName Struct"; + my $info = $tagNameInfo{$fullName} = [ ]; + my $tag; + foreach $tag (sort keys %$struct) { + my $tagInfo = $$struct{$tag}; + next unless ref $tagInfo eq 'HASH'; + my $writable = $$tagInfo{Writable}; + my @vals; + unless ($writable) { + $writable = $$tagInfo{Struct}; + ref $writable and $writable = $$writable{STRUCT_NAME}; + if ($writable) { + push @vals, $writable; + $structs{$writable} = 1; + $writable = "=$writable"; + } else { + $writable = 'string'; + } + } + $writable .= '+' if $$tagInfo{List}; + push @vals, "($$tagInfo{Notes})" if $$tagInfo{Notes}; + # handle PrintConv lookups in Structure elements + my $printConv = $$tagInfo{PrintConv}; + if (ref $printConv eq 'HASH') { + foreach (sort keys %$printConv) { + next if /^(OTHER|BITMASK)$/; + push @vals, "$_ = $$printConv{$_}"; + } + } + push @$info, [ + $tag, + [ $$tagInfo{Name} || ucfirst($tag) ], + [ $writable ], + \@vals, + [], [] + ]; + } + } + return $self; +} + +#------------------------------------------------------------------------------ +# Rewrite this file to build the lookup tables +# Inputs: 0) BuildTagLookup object reference +# 1) output tag lookup module name (eg. 'lib/Image/ExifTool/TagLookup.pm') +# Returns: true on success +sub WriteTagLookup($$) +{ + local ($_, *INFILE, *OUTFILE); + my ($self, $file) = @_; + my $tagLookup = $self->{TAG_LOOKUP}; + my $tagExists = $self->{TAG_EXISTS}; + my $flattened = $self->{FLATTENED}; + my $tableWritable = $self->{TABLE_WRITABLE}; +# +# open/create necessary files and transfer file headers +# + my $tmpFile = "${file}_tmp"; + open(INFILE, $file) or warn("Can't open $file\n"), return 0; + unless (open(OUTFILE, ">$tmpFile")) { + warn "Can't create temporary file $tmpFile\n"; + close(INFILE); + return 0; + } + my $success; + while () { + print OUTFILE $_ or last; + if (/^#\+{4} Begin/) { + $success = 1; + last; + } + } + print OUTFILE "\n# list of tables containing writable tags\n"; + print OUTFILE "my \@tableList = (\n"; + +# +# write table list +# + my @tableNames = sort keys %allTables; + my $tableName; + my %wrNum; # translate from allTables index to writable tables index + my $count = 0; + my $num = 0; + foreach $tableName (@tableNames) { + if ($$tableWritable{$tableName}) { + print OUTFILE "\t'${tableName}',\n"; + $wrNum{$count} = $num++; + } + $count++; + } +# +# write the tag lookup table +# + my $tag; + # verify that certain critical tag names aren't duplicated + foreach $tag (qw{filename directory}) { + next unless $$tagLookup{$tag}; + my $n = scalar keys %{$$tagLookup{$tag}}; + warn "Warning: $n writable '${tag}' tags!\n" if $n > 1; + } + print OUTFILE ");\n\n# lookup for all writable tags\nmy \%tagLookup = (\n"; + foreach $tag (sort keys %$tagLookup) { + print OUTFILE "\t'${tag}' => { "; + my @tableNums = sort { $a <=> $b } keys %{$$tagLookup{$tag}}; + my (@entries, $tableNum); + foreach $tableNum (@tableNums) { + my $tagID = $$tagLookup{$tag}{$tableNum}; + my $rootID = $$flattened{$tag}{$tableNum}; + my $entry; + if (ref $tagID eq 'HASH' or $rootID) { + $tagID = { $tagID => 1 } unless ref $tagID eq 'HASH'; + my @tagIDs = sort keys %$tagID; + foreach (@tagIDs) { + if (/^\d+$/) { + $_ = sprintf('0x%x',$_); + } else { + my $quot = "'"; + # escape non-printable characters in tag ID if necessary + $quot = '"' if s/[\x00-\x1f,\x7f-\xff]/sprintf('\\x%.2x',ord($&))/ge; + $_ = $quot . $_ . $quot; + } + } + # reference to root structure ID must come first in lookup + # (so we can generate the flattened tags just before we need them) + unshift @tagIDs, "\\'${rootID}'" if $rootID; + $entry = '[' . join(',', @tagIDs) . ']'; + } elsif ($tagID =~ /^\d+$/) { + $entry = sprintf('0x%x',$tagID); + } else { + $entry = "'${tagID}'"; + } + my $wrNum = $wrNum{$tableNum}; + push @entries, "$wrNum => $entry"; + } + print OUTFILE join(', ', @entries); + print OUTFILE " },\n"; + } +# +# write tag exists lookup +# + print OUTFILE ");\n\n# lookup for non-writable tags to check if the name exists\n"; + print OUTFILE "my \%tagExists = (\n"; + foreach $tag (sort keys %$tagExists) { + next if $$tagLookup{$tag}; + print OUTFILE "\t'${tag}' => 1,\n"; + } +# +# write module lookup for writable composite tags +# + my $compositeModules = $self->{COMPOSITE_MODULES}; + print OUTFILE ");\n\n# module names for writable Composite tags\n"; + print OUTFILE "my \%compositeModules = (\n"; + foreach (sort keys %$compositeModules) { + print OUTFILE "\t'${_}' => '$$compositeModules{$_}',\n"; + } + print OUTFILE ");\n\n"; +# +# finish writing TagLookup.pm and clean up +# + if ($success) { + $success = 0; + while () { + $success or /^#\+{4} End/ or next; + print OUTFILE $_; + $success = 1; + } + } + close(INFILE); + close(OUTFILE) or $success = 0; +# +# return success code +# + if ($success) { + local (*ORG, *TMP); + # only rename the file if something changed + open ORG, $file or return 0; + open TMP, $tmpFile or return 0; + my ($buff, $buf2, $changed); + for (;;) { + my $n1 = read ORG, $buff, 65536; + my $n2 = read TMP, $buf2, 65536; + $n1 eq $n2 or $changed = 1, last; + last unless $n1; + $buff eq $buf2 or $changed = 1, last; + } + close ORG; + close TMP; + if ($changed) { + rename($tmpFile, $file) or warn("Error renaming $tmpFile\n"), $success = 0; + } else { + unlink($tmpFile); + } + } else { + unlink($tmpFile); + warn "Error rewriting file\n"; + } + return $success; +} + +#------------------------------------------------------------------------------ +# Sort numbers first numerically, then strings alphabetically (case insensitive) +# - two global variables are used to change the sort algorithm: +# $numbersFirst: -1 = put numbers after other strings +# 1 = put numbers before other strings +# 2 = put numbers first, but negative numbers last +# $caseInsensitive: flag set for case-insensitive sorting +sub NumbersFirst($$) +{ + my ($a, $b) = @_; + my $rtnVal; + my ($bNum, $bDec); + ($bNum, $bDec) = ($1, $3) if $b =~ /^(-?[0-9]+)(\.(\d*))?$/; + if ($a =~ /^(-?[0-9]+)(\.(\d*))?$/) { + if (defined $bNum) { + $bNum += 1e9 if $numbersFirst == 2 and $bNum < 0; + my $aInt = $1; + $aInt += 1e9 if $numbersFirst == 2 and $aInt < 0; + # compare integer part as a number + $rtnVal = $aInt <=> $bNum; + unless ($rtnVal) { + my $aDec = $3 || 0; + $bDec or $bDec = 0; + # compare decimal part as an integer too + # (so that "1.10" comes after "1.9") + $rtnVal = $aDec <=> $bDec; + } + } else { + $rtnVal = -$numbersFirst; + } + } elsif (defined $bNum) { + $rtnVal = $numbersFirst; + } else { + my ($a2, $b2) = ($a, $b); + # expand numbers to 3 digits (with restrictions to avoid messing up ascii-hex tags) + $a2 =~ s/(\d+)/sprintf("%.3d",$1)/eg if $a2 =~ /^(APP|DMC-\w+ )?[.0-9 ]*$/ and length($a2)<16; + $b2 =~ s/(\d+)/sprintf("%.3d",$1)/eg if $b2 =~ /^(APP|DMC-\w+ )?[.0-9 ]*$/ and length($b2)<16; + $caseInsensitive and $rtnVal = (lc($a2) cmp lc($b2)); + $rtnVal or $rtnVal = ($a2 cmp $b2); + } + return $rtnVal; +} + +#------------------------------------------------------------------------------ +# Convert our pod-like documentation to pod +# (funny, I know, but the pod headings must be hidden to prevent confusing +# the pod parser) +# Inputs: 0-N) documentation strings +sub Doc2Pod($;@) +{ + my $doc = shift; + local $_; + $doc .= shift while @_; + $doc =~ s/\n~/\n=/g; + $doc =~ s/L<[^>]+?\|(http[^>]+)>/L<$1>/g; # POD doesn't support text for http links + $doc =~ s/L<([^>]+?)\|[^>]+\.html(#\w+)?>/$1/g; # remove relative HTML links + return $doc; +} + +#------------------------------------------------------------------------------ +# Convert our pod-like documentation to html +# Inputs: 0) string +sub Doc2Html($) +{ + my $doc = EscapeHTML(shift); + $doc =~ s/\n\n/<\/p>\n\n

/g; + $doc =~ s/B<(.*?)>/$1<\/b>/sg; + $doc =~ s/C<(.*?)>/$1<\/code>/sg; + $doc =~ s/I<(.*?)>/$1<\/i>/sg; + # L --> some text + $doc =~ s{L<([^&]+?)\|\Q$homePage\E/(.*?)>}{$1<\/a>}sg; + # L --> http://owl.phy.queensu.ca/~phil/exiftool/struct.html + $doc =~ s{L<\Q$homePage\E/(.*?)>}{$1<\/a>}sg; + # L

--> <a href="XMP.html#DICOM">XMP DICOM Tags</a> + # (specify "Image::ExifTool::TagNames" to link to another html file) + $doc =~ s{L&lt;([^&]+?)\|Image::ExifTool::TagNames/(\w+) ([^/&|]+) Tags&gt;}{<a href="$2.html#$3">$1</a>}sg; + # L<DICOM Tags|Image::ExifTool::TagNames/DICOM Tags> --> <a href="DICOM.html">DICOM Tags</a> + $doc =~ s{L&lt;([^&]+?)\|Image::ExifTool::TagNames/(\w+) Tags&gt;}{<a href="$2.html">$1</a>}sg; + # L<dc|/XMP dc Tags> --> <a href="#dc">dc</a> + # (a relative POD link turns into a relative HTML link) + $doc =~ s{L&lt;([^&]+?)\|/\w+ ([^/&|]+) Tags&gt;}{<a href="#$2">$1</a>}sg; + # L<sample config file|../config.html> --> <a href="../config.html">sample config file</a> + $doc =~ s/L&lt;([^&]+?)\|(.+?)&gt;/<a href="$2">$1<\/a>/sg; + # L<http://some.web.site/> --> <a href="http://some.web.site">http://some.web.site</a> + $doc =~ s/L&lt;(http.*?)&gt;/<a href="$1">$1<\/a>/sg; + return $doc; +} + +#------------------------------------------------------------------------------ +# Tweak order of tables +# Inputs: 0) table list ref, 1) reference to tweak hash +sub TweakOrder($$) +{ + local $_; + my ($sortedTables, $tweakOrder) = @_; + my @tweak = sort keys %$tweakOrder; + my (%addedMain, @sorted); + # flag files which have a "Main" table + foreach (@$sortedTables) { + $addedMain{$1} = 0 if /^Image::ExifTool::(\w+)::(\w+)/ and $2 eq 'Main'; + } + # make sure that the main table always comes first in each file + foreach (@$sortedTables) { + if (/^Image::ExifTool::(\w+)::(\w+)/) { + if ($addedMain{$1}) { + next if $2 eq 'Main'; # don't add again + } elsif (defined $addedMain{$1}) { + push @sorted, "Image::ExifTool::${1}::Main" if $2 ne 'Main'; + $addedMain{$1} = 1; + } + } + push @sorted, $_; + } + @$sortedTables = @sorted; + # apply manual tweaks + while (@tweak) { + my $table = shift @tweak; + my $first = $$tweakOrder{$table}; + if ($$tweakOrder{$first}) { + push @tweak, $table; # must defer this till later + next; + } + delete $$tweakOrder{$table}; # because the table won't move again + my @moving = grep /^Image::ExifTool::$table\b/, @$sortedTables; + my @notMoving = grep !/^Image::ExifTool::$table\b/, @$sortedTables; + my @after; + while (@notMoving) { + last if $notMoving[-1] =~ /^Image::ExifTool::$first\b/; + unshift @after, pop @notMoving; + } + @$sortedTables = (@notMoving, @moving, @after); + } +} + +#------------------------------------------------------------------------------ +# Get a list of sorted tag ID's from a table +# Inputs: 0) tag table ref +# Returns: list of sorted keys +sub SortedTagTableKeys($) +{ + my $table = shift; + my $vars = $$table{VARS} || { }; + my @keys = TagTableKeys($table); + if ($$vars{NO_ID}) { + # sort by tag name if ID not shown + my ($key, %name); + foreach $key (@keys) { + my ($tagInfo) = GetTagInfoList($table, $key); + $name{$key} = $$tagInfo{Name}; + } + return sort { $name{$a} cmp $name{$b} or $a cmp $b } @keys; + } else { + my $sortProc = $$vars{SORT_PROC} || \&NumbersFirst; + return sort { &$sortProc($a,$b) } @keys; + } +} + +#------------------------------------------------------------------------------ +# Get the order that we want to print the tables in the documentation +# Inputs: 0-N) Extra tables to add at end +# Returns: tables in the order we want +sub GetTableOrder(@) +{ + my %gotTable; + my @tableNames = @tableOrder; + my (@orderedTables, %mainTables, @outOfOrder); + my $lastTable = ''; + + while (@tableNames) { + my $tableName = shift @tableNames; + next if $gotTable{$tableName}; + if ($tableName =~ /^Image::ExifTool::(\w+)::Main/) { + $mainTables{$1} = 1; + } elsif ($lastTable and not $tableName =~ /^${lastTable}::/) { + push @outOfOrder, $tableName; + } + ($lastTable) = ($tableName =~ /^(Image::ExifTool::\w+)/); + push @orderedTables, $tableName; + $gotTable{$tableName} = 1; + my $table = GetTagTable($tableName); + # recursively scan through tables in subdirectories + my @moreTables; + $caseInsensitive = ($$table{GROUPS} and $$table{GROUPS}{0} eq 'XMP'); + $numbersFirst = -1 if $$table{VARS} and $$table{VARS}{ALPHA_FIRST}; + my @keys = SortedTagTableKeys($table); + $numbersFirst = 1; + foreach (@keys) { + my @infoArray = GetTagInfoList($table,$_); + my $tagInfo; + foreach $tagInfo (@infoArray) { + my $subdir = $$tagInfo{SubDirectory} or next; + $tableName = $$subdir{TagTable} or next; + next if $gotTable{$tableName}; # next if table already loaded + push @moreTables, $tableName; # must scan this one too + } + } + unshift @tableNames, @moreTables; + } + # clean up the order for tables which are out of order + # (groups all Canon and Kodak tables together) + my %fixOrder; + foreach (@outOfOrder) { + next unless /^Image::ExifTool::(\w+)/; + # only re-order tables which have a corresponding main table + next unless $mainTables{$1}; + $fixOrder{$1} = []; # fix the order of these tables + } + my (@sortedTables, %fixPos, $pos); + foreach (@orderedTables) { + if (/^Image::ExifTool::(\w+)/ and $fixOrder{$1}) { + my $fix = $fixOrder{$1}; + unless (@$fix) { + $pos = @sortedTables; + $fixPos{$pos} or $fixPos{$pos} = []; + push @{$fixPos{$pos}}, $1; + } + push @{$fix}, $_; + } else { + push @sortedTables, $_; + } + } + # insert back in better order + foreach $pos (sort { $b <=> $a } keys %fixPos) { # (reverse sort) + my $fix = $fixPos{$pos}; + foreach (@$fix) { + splice(@sortedTables, $pos, 0, @{$fixOrder{$_}}); + } + } + # add the extra tables + push @sortedTables, @_; + # tweak the table order + TweakOrder(\@sortedTables, \%tweakOrder); + + return @sortedTables; +} + +#------------------------------------------------------------------------------ +# Open HTMLFILE and print header and description +# Inputs: 0) Filename, 1) optional category +# Returns: True on success +my %createdFiles; +sub OpenHtmlFile($;$$) +{ + my ($htmldir, $category, $sepTable) = @_; + my ($htmlFile, $head, $title, $url, $class); + my $top = ''; + + if ($category) { + my @names = split ' ', $category; + $class = shift @names; + $htmlFile = "$htmldir/TagNames/$class.html"; + $head = $category; + if ($head =~ /^\S+ .+ Struct$/) { + pop @names; + } else { + $head .= ($sepTable ? ' Values' : ' Tags'); + } + ($title = $head) =~ s/ .* / /; + @names and $url = join '_', @names; + } else { + $htmlFile = "$htmldir/TagNames/index.html"; + $category = $class = 'ExifTool'; + $head = $title = 'ExifTool Tag Names'; + } + if ($createdFiles{$htmlFile}) { + open(HTMLFILE, ">>${htmlFile}_tmp") or return 0; + } else { + open(HTMLFILE, ">${htmlFile}_tmp") or return 0; + print HTMLFILE "$docType<html>\n<head>\n<title>$title</title>\n"; + print HTMLFILE "<link rel=stylesheet type='text/css' href='style.css' title='Style'>\n"; + print HTMLFILE "</head>\n<body>\n"; + if ($category ne $class and $docs{$class}) { + print HTMLFILE "<h2 class=top>$class Tags</h2>\n" or return 0; + print HTMLFILE '<p>',Doc2Html($docs{$class}),"</p>\n" or return 0; + } else { + $top = " class=top"; + } + } + $head = "<a name='${url}'>$head</a>" if $url; + print HTMLFILE "<h2$top>$head</h2>\n" or return 0; + print HTMLFILE '<p>',Doc2Html($docs{$category}),"</p>\n" if $docs{$category}; + $createdFiles{$htmlFile} = 1; + return 1; +} + +#------------------------------------------------------------------------------ +# Close all html files and write trailers +# Returns: true on success +# Inputs: 0) BuildTagLookup object reference +sub CloseHtmlFiles($) +{ + my $self = shift; + my $preserveDate = $$self{PRESERVE_DATE}; + my $success = 1; + # get the date + my ($sec,$min,$hr,$day,$mon,$yr) = localtime; + my @month = qw(Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec); + $yr += 1900; + my $date = "$month[$mon] $day, $yr"; + my $htmlFile; + my $countNewFiles = 0; + my $countSameFiles = 0; + foreach $htmlFile (keys %createdFiles) { + my $tmpFile = $htmlFile . '_tmp'; + my $fileDate = $date; + if ($preserveDate) { + my @lines = `grep '<i>Last revised' $htmlFile`; + $fileDate = $1 if @lines and $lines[-1] =~ m{<i>Last revised (.*)</i>}; + } + open(HTMLFILE, ">>$tmpFile") or $success = 0, next; + # write the trailers + print HTMLFILE "<hr>\n"; + print HTMLFILE "(This document generated automatically by Image::ExifTool::BuildTagLookup)\n"; + print HTMLFILE "<br><i>Last revised $fileDate</i>\n"; + print HTMLFILE "<p class=lf><a href="; + if ($htmlFile =~ /index\.html$/) { + print HTMLFILE "'../index.html'>&lt;-- Back to ExifTool home page</a></p>\n"; + } else { + print HTMLFILE "'index.html'>&lt;-- ExifTool Tag Names</a></p>\n" + } + print HTMLFILE "</body>\n</html>\n" or $success = 0; + close HTMLFILE or $success = 0; + # check for differences and only use new file if it was changed + # (so the date only gets updated if changes were really made) + my $useNewFile; + if ($success) { + open (TEMPFILE, $tmpFile) or $success = 0, last; + if (open (HTMLFILE, $htmlFile)) { + while (<HTMLFILE>) { + my $newLine = <TEMPFILE>; + if (defined $newLine) { + next if /^<br><i>Last revised/; + next if $_ eq $newLine; + } + # files are different -- use the new file + $useNewFile = 1; + last; + } + $useNewFile = 1 if <TEMPFILE>; + close HTMLFILE; + } else { + $useNewFile = 1; + } + close TEMPFILE; + if ($useNewFile) { + ++$countNewFiles; + rename $tmpFile, $htmlFile or warn("Error renaming temporary file\n"), $success = 0; + } else { + ++$countSameFiles; + unlink $tmpFile; # erase new file and use existing file + } + } + last unless $success; + } + # save number of files processed so we can check the results later + $self->{COUNT}->{'HTML files changed'} = $countNewFiles; + $self->{COUNT}->{'HTML files unchanged'} = $countSameFiles; + return $success; +} + +#------------------------------------------------------------------------------ +# Get bitmask for POD documentation +# Inputs: mask string from HTML docs +# Returns: mask string for POD, or '' +sub PodMask($) +{ + my $mask = shift; + return '' unless $mask =~ /^\[val( >> (\d+))? \& (0x[\da-f]+)\]/; + return sprintf(' & 0x%.2x', hex($3) << ($2 || 0)); +} + +#------------------------------------------------------------------------------ +# Write the TagName HTML and POD documentation +# Inputs: 0) BuildTagLookup object reference +# 1) output pod file (eg. 'lib/Image/ExifTool/TagNames.pod') +# 2) output html directory (eg. 'html') +# Returns: true on success +# Notes: My apologies for the patchwork code, but this is only used to generate the docs. +sub WriteTagNames($$) +{ + my ($self, $podFile, $htmldir) = @_; + my ($tableName, $short, $url, @sepTables, @structs); + my $tagNameInfo = $self->{TAG_NAME_INFO} or return 0; + my $idLabel = $self->{ID_LOOKUP}; + my $shortName = $self->{SHORT_NAME}; + my $sepTable = $self->{SEPARATE_TABLE}; + my $structs = $self->{STRUCTURES}; + my $structLookup = $self->{STRUCT_LOOKUP}; + my $success = 1; + my $columns = 6; # number of columns in html index + my $percent = int(100 / $columns); + + # open the file and write the header + open(PODFILE, ">$podFile") or return 0; + print PODFILE Doc2Pod($docs{PodHeader}, $docs{ExifTool}, $docs{ExifTool2}); + mkdir "$htmldir/TagNames", 0777; + OpenHtmlFile($htmldir) or return 0; + print HTMLFILE "<blockquote>\n"; + print HTMLFILE "<table width='100%' class=frame><tr><td>\n"; + print HTMLFILE "<table width='100%' class=inner cellspacing=1><tr class=h>\n"; + print HTMLFILE "<th colspan=$columns><span class=l>Tag Table Index</span></th></tr>\n"; + print HTMLFILE "<tr class=b><td width='$percent%'>\n"; + + # get the full table list, adding shortcuts and plug-in tables to the end + my @tableNames = GetTableOrder('Image::ExifTool::Shortcuts::Main', @pluginTables); + + # get list of headings and add any missing ones + my $heading = 'xxx'; + my (@tableIndexNames, @headings); + foreach $tableName (@tableNames) { + $short = $$shortName{$tableName}; + my @names = split ' ', $short; + my $class = shift @names; + if (@names) { + # add heading for tables without a Main + unless ($heading eq $class) { + $heading = $class; + push @tableIndexNames, $heading; + push @headings, $heading; + } + } else { + $heading = $short; + push @headings, $heading; + } + push @tableIndexNames, $tableName; + } + @tableNames = @tableIndexNames; + # print html index of headings only + my $count = 0; + my $lines = int((scalar(@headings) + $columns - 1) / $columns); + foreach $tableName (@headings) { + if ($count) { + if ($count % $lines) { + print HTMLFILE "<br>\n"; + } else { + print HTMLFILE "</td><td width='$percent%'>\n"; + } + } + $short = $$shortName{$tableName}; + $short = $tableName unless $short; + $url = "$short.html"; + print HTMLFILE "<a href='${url}'>$short</a>"; + ++$count; + } + print HTMLFILE "\n</td></tr></table></td></tr></table></blockquote>\n"; + print HTMLFILE '<p>',Doc2Html($docs{ExifTool2}),"</p>\n"; + + # write all the tag tables + while (@tableNames or @sepTables or @structs) { + while (@sepTables) { + $tableName = shift @sepTables; + my $printConv = $$sepTable{$tableName}; + next unless ref $printConv eq 'HASH'; + $$sepTable{$tableName} = 1; + my $notes = $$printConv{Notes}; + if ($notes) { + # remove unnecessary whitespace + $notes =~ s/^\s+//; $notes =~ s/\s+$//; + $notes =~ s/(^[ \t]+|[ \t]+$)//mg; + } + my $head = $tableName; + $head =~ s/^.* //s; + close HTMLFILE; + if (OpenHtmlFile($htmldir, $tableName, 1)) { + print HTMLFILE '<p>', Doc2Html($notes), "</p>\n" if $notes; + print HTMLFILE "<blockquote>\n"; + print HTMLFILE "<table class=frame><tr><td>\n"; + print HTMLFILE "<table class='inner sep' cellspacing=1>\n"; + my $align = ' class=r'; + my $wid = 0; + my @keys; + foreach (sort { NumbersFirst($a,$b) } keys %$printConv) { + next if /^(Notes|PrintHex|PrintString|OTHER)$/; + $align = '' if $align and /[^\d]/; + my $w = length($_) + length($$printConv{$_}); + $wid = $w if $wid < $w; + push @keys, $_; + } + $wid = length($tableName)+7 if $wid < length($tableName)+7; + # print in multiple columns if there is room + my $cols = int(110 / ($wid + 4)); + $cols = 1 if $cols < 1 or $cols > @keys or @keys < 4; + my $rows = int((scalar(@keys) + $cols - 1) / $cols); + my ($r, $c); + print HTMLFILE '<tr class=h>'; + for ($c=0; $c<$cols; ++$c) { + print HTMLFILE "<th>Value</th><th>$head</th>"; + } + print HTMLFILE "</tr>\n"; + for ($r=0; $r<$rows; ++$r) { + print HTMLFILE '<tr>'; + for ($c=0; $c<$cols; ++$c) { + my $key = $keys[$r + $c*$rows]; + my ($index, $prt); + if (defined $key) { + $index = $key; + $prt = '= ' . EscapeHTML($$printConv{$key}); + if ($$printConv{PrintHex}) { + $index =~ s/(\.\d+)$//; # remove decimal + $index = sprintf('0x%x',$index); + $index .= $1 if $1; # add back decimal + } elsif ($$printConv{PrintString} or + $index !~ /^[+-]?(?=\d|\.\d)\d*(\.\d*)?$/) + { + $index = "'" . EscapeHTML($index) . "'"; + } + } else { + $index = $prt = '&nbsp;'; + } + my ($ic, $pc); + if ($c & 0x01) { + $pc = ' class=b'; + $ic = $align ? " class='r b'" : $pc; + } else { + $ic = $align; + $pc = ''; + } + print HTMLFILE "<td$ic>$index</td><td$pc>$prt</td>\n"; + } + print HTMLFILE '</tr>'; + } + print HTMLFILE "</table></td></tr></table></blockquote>\n\n"; + } + } + last unless @tableNames or @structs; + my $isStruct; + if (@structs) { + $tableName = shift @structs; + next if $$structs{$tableName} == 2; # only list each structure once + $$structs{$tableName} = 2; + $isStruct = $$structLookup{$tableName}; + $isStruct or warn("Missing structure $tableName\n"), next; + $tableName = "XMP $tableName" unless $tableName =~ / /; + $short = $tableName = "$tableName Struct"; + my $maxLen = 0; + $maxLen < length and $maxLen = length foreach keys %$isStruct; + $$self{LONG_ID}{$tableName} = $maxLen; + } else { + $tableName = shift @tableNames; + $short = $$shortName{$tableName}; + unless ($short) { + # this is just an index heading + print PODFILE "\n=head2 $tableName Tags\n"; + print PODFILE Doc2Pod($docs{$tableName}) if $docs{$tableName}; + next; + } + } + my $isExif = ($tableName eq 'Image::ExifTool::Exif::Main'); + my $isRiff = ($tableName eq 'Image::ExifTool::RIFF::Info'); + my $isXmpMain = ($tableName eq 'Image::ExifTool::XMP::Main'); + my $info = $$tagNameInfo{$tableName}; + my $id = $$idLabel{$tableName}; + my ($hid, $showGrp); + # widths of the different columns in the POD documentation + my ($wID,$wTag,$wReq,$wGrp) = (8,36,24,10); + my ($composite, $derived, $notes, $longTags, $wasLong, $prefix); + if ($short eq 'Shortcuts') { + $derived = '<th>Refers To</th>'; + $composite = 2; + } elsif ($isStruct) { + $derived = ''; + $notes = $$isStruct{NOTES}; + } else { + my $table = GetTagTable($tableName); + $notes = $$table{NOTES}; + if ($$table{NAMESPACE}) { + my $ns = $Image::ExifTool::XMP::stdXlatNS{$$table{NAMESPACE}} || $$table{NAMESPACE}; + my $msg = "These tags belong to the ExifTool XMP-$ns family 1 group."; + if ($notes) { + $notes =~ s/\s+$//; + $notes .= "\n\n" . $msg; + } else { + $notes = $msg; + } + } + $longTags = $$table{VARS}{LONG_TAGS} if $$table{VARS}; + if ($$table{GROUPS}{0} eq 'Composite') { + $composite = 1; + $derived = '<th>Derived From</th>'; + } else { + $composite = 0; + $derived = ''; + } + } + my $podIdLen = $self->{LONG_ID}->{$tableName}; + if ($notes) { + # remove unnecessary whitespace + $notes =~ s/^\s+//; $notes =~ s/\s+$//; + $notes =~ s/(^[ \t]+|[ \t]+$)//mg; + if ($notes =~ /leading '(.*?_)' which/) { + $prefix = $1; + $podIdLen -= length $prefix; + } + } + if ($podIdLen <= $wID) { + $podIdLen = $wID; + } elsif ($short eq 'DICOM') { + $podIdLen = 10; + } else { + # align tag names in secondary columns if possible + my $col = ($podIdLen <= 10) ? 12 : 20; + $podIdLen = $col if $podIdLen < $col; + } + if ($id) { + ($hid = "<th>$id</th>") =~ s/ /&nbsp;/g; + $wTag -= $podIdLen - $wID; + $wID = $podIdLen; + my $longTag = $self->{LONG_NAME}->{$tableName}; + if ($wTag < $longTag) { + if ($wID - $longTag + $wTag >= 6) { # don't let ID column get too narrow + $wID -= $longTag - $wTag; + $wTag = $longTag; + } + $wasLong = 1 if $wID <= $self->{LONG_ID}->{$tableName}; + } + } elsif ($composite) { + $wTag += $wID - $wReq; + $hid = ''; + } else { + $wTag += 9; + $hid = ''; + } + if ($short eq 'EXIF' or $short eq 'Extra') { + $derived = '<th>Group</th>'; + $showGrp = 1; + $wGrp += 8 if $short eq 'Extra'; # tweak Group column width for "Extra" tags + $wTag -= $wGrp + 1; + } + my $head = ($short =~ / /) ? 'head3' : 'head2'; + my $str = $isStruct ? '' : ' Tags'; + print PODFILE "\n=$head $short$str\n"; + print PODFILE Doc2Pod($docs{$short}) if $docs{$short}; + print PODFILE "\n", Doc2Pod($notes), "\n" if $notes; + my $line = "\n"; + if ($id) { + # shift over 'Index' heading by one character for a bit more balance + $id = " $id" if $id eq 'Index'; + $line .= sprintf " %-${wID}s", $id; + } else { + $line .= ' '; + } + my $tagNameHeading = ($short eq 'XMP') ? 'Namespace' : ($isStruct?'Field':'Tag').' Name'; + $line .= sprintf " %-${wTag}s", $tagNameHeading; + $line .= sprintf " %-${wReq}s", $composite == 2 ? 'Refers To' : 'Derived From' if $composite; + $line .= sprintf " %-${wGrp}s", 'Group' if $showGrp; + $line .= ' Writable'; + print PODFILE $line; + $line =~ s/^(\s*\w.{6}\w) /$1\t/; # change space to tab after long ID label (eg. "Sequence") + $line =~ s/\S/-/g; + $line =~ s/- -/---/g; + $line =~ tr/\t/ /; # change tab back to space + print PODFILE $line,"\n"; + close HTMLFILE; + OpenHtmlFile($htmldir, $short) or $success = 0; + print HTMLFILE '<p>',Doc2Html($notes), "</p>\n" if $notes; + print HTMLFILE "<blockquote>\n"; + print HTMLFILE "<table class=frame><tr><td>\n"; + print HTMLFILE "<table class=inner cellspacing=1>\n"; + print HTMLFILE "<tr class=h>$hid<th>$tagNameHeading</th>\n"; + print HTMLFILE "<th>Writable</th>$derived<th>Values / ${noteFont}Notes</span></th></tr>\n"; + my $rowClass = 1; + my $infoCount = 0; + my $infoList; + foreach $infoList (@$info) { + ++$infoCount; + my ($tagIDstr, $tagNames, $writable, $values, $require, $writeGroup) = @$infoList; + my ($align, $idStr, $w, $tip); + my $wTag2 = $wTag; + if (not $id) { + $idStr = ' '; + } elsif ($tagIDstr =~ /^-?\d+(\.\d+)?$/) { + $w = $wID - 3; + $idStr = sprintf " %${w}g ", $tagIDstr; + my $tooLong = length($idStr) - 6 - $w; + if ($tooLong) { + $tooLong = 3 if $tooLong > 3; + $idStr = substr($idStr, 0, -$tooLong); + } + $align = " class=r"; + } else { + $tagIDstr =~ s/^'$prefix/'/ if $prefix; + $w = $wID; + my $over = length($tagIDstr) - $w; + if ($over > 0) { + # shift over tag name if there is room + if ($over <= $wTag - length($$tagNames[0])) { + $wTag2 -= $over; + $w += $over; + } else { + # put tag name on next line if ID is too long + $idStr = " $tagIDstr\n " . (' ' x $w); + if ($longTags) { + --$longTags; + } else { + warn "Notice: Split $$tagNames[0] line\n"; + } + } + } + $idStr = sprintf " %-${w}s ", $tagIDstr unless defined $idStr; + $align = ''; + } + my @reqs; + my @tags = @$tagNames; + my @wGrp = @$writeGroup; + my @vals = @$writable; + my $wrStr = shift @vals; + my $subdir; + my @masks = grep /^\[val( >> \d+)? \& 0x[\da-f]+\]/, @$values; + my $tag = shift @tags; + # if this is a subdirectory or structure, print subdir name (from values) instead of writable + if ($wrStr =~ /^[-=]/) { + $subdir = 1; + if (@masks) { + # combine any mask into the format string + $wrStr .= PodMask($masks[0]); + shift @masks; + @vals = grep !/^\[val( >> \d+)? \& 0x[\da-f]+\]/, @$values; + } else { + @vals = @$values; + } + # remove Notes if subdir has Notes as well + shift @vals if $vals[0] =~ /^\(/ and @vals >= @$writable; + foreach (@vals) { /^\(/ and $_ = '-' } + my $i; # fill in any missing entries from non-directory tags + for ($i=0; $i<@$writable; ++$i) { + $vals[$i] = $$writable[$i] unless defined $vals[$i]; + if (@masks) { + $vals[$i] .= PodMask($masks[0]); + shift @masks; + } + } + if ($$sepTable{$vals[0]}) { + $wrStr =~ s/^[-=]//; + $wrStr = 'no' unless $wrStr; + } elsif ($$structs{$vals[0]}) { + my $flags = $wrStr =~ /([+_]+)$/ ? $1 : ''; + $wrStr = "$vals[0] Struct$flags"; + } else { + $wrStr = $vals[0]; + } + shift @vals; + } elsif ($wrStr and $wrStr ne 'no' and @masks) { + # fill in missing entries if masks are different + my $mask = shift @masks; + while (@masks > @vals) { + last if $masks[@vals] eq $mask; + push @vals, $wrStr; + push @tags, $tag if @tags < @vals; + } + # add Mask to Writable column in POD doc + $wrStr .= PodMask($mask); + } + my $pod = sprintf "%s%-${wTag2}s", $idStr, $tag; + my $tGrp = $wGrp; + if ($id and length($tag) > $wTag2) { + my $madeRoom; + if ($showGrp) { + my $wGrp0 = length($wGrp[0] || '-'); + if (not $composite and $wGrp > $wGrp0) { + $tGrp = $wGrp - (length($tag) - $wTag2); + if ($tGrp < length $wGrp0) { + $tGrp = length $wGrp0; + } else { + $madeRoom = 1; + } + } + } + warn "Warning: Pushed $tag\n" unless $madeRoom; + } + $pod .= sprintf " %-${tGrp}s", shift(@wGrp) || '-' if $showGrp; + if ($composite) { + @reqs = @$require; + $w = $wReq; # Keep writable column in line + length($tag) > $wTag2 and $w -= length($tag) - $wTag2; + $pod .= sprintf " %-${w}s", shift(@reqs) || ''; + } + $pod .= " $wrStr"; + # limit line length to 82 characters (even if it means messing up column alignment) + if (length $pod > 82 and $pod !~ /\n/) { + my $remove = length($pod) - 82; + $pod =~ s/(\w)\s{$remove}/$1/; + } + print PODFILE $pod, "\n"; + my $numTags = scalar @$tagNames; + my $n = 0; + while (@tags or @reqs or @vals) { + my $more = (@tags or @reqs); + $line = ' '; + $line .= ' 'x($wID+1) if $id; + $line .= sprintf("%-${wTag2}s", shift(@tags) || ''); + $line .= sprintf(" %-${wReq}s", shift(@reqs) || '') if $composite; + $line .= sprintf(" %-${wGrp}s", shift(@wGrp) || '-') if $showGrp; + ++$n; + if (@vals) { + my $val = shift @vals; + # use writable if this is a note + my $wrStr = $$writable[$n]; + if ($subdir and ($val =~ /^\(/ or $val =~ /=/ or ($wrStr and $wrStr !~ /^[-=]/))) { + $val = $wrStr; + if (defined $val) { + $val =~ s/^[-=]//; + } else { + # done with tag if nothing else to print + last unless $more; + } + } + if (defined $val) { + $line .= " $val"; + if (@masks) { + $line .= PodMask($masks[0]); + shift @masks; + } + } + } + $line =~ s/\s+$//; # trim trailing white space + print PODFILE "$line\n"; + } + my @htmlTags; + foreach (@$tagNames) { + push @htmlTags, EscapeHTML($_); + } + if (($isExif and $Image::ExifTool::Validate::exifSpec{hex $tagIDstr}) or + ($isRiff and $tagIDstr=~/(\w+)/ and $riffSpec{$1}) or + ($isXmpMain and $tagIDstr=~/([-\w]+)/ and $xmpSpec{$1})) + { + # underline "unknown" makernote tags only + my $n = $tagIDstr eq '0x927c' ? -1 : 0; + $htmlTags[$n] = "<u>$htmlTags[$n]</u>"; + } + $rowClass = $rowClass ? '' : " class=b"; + my $isSubdir; + if ($$writable[0] =~ /^[-=]/) { + $isSubdir = 1; + s/^[-=](.+)/$1/ foreach @$writable; + } + # add tooltip for hex conversion of Tag ID + if ($tagIDstr =~ /^(0x[0-9a-f]+)(\.\d+)?$/i) { + $tip = sprintf(" title='$tagIDstr = %u%s'", hex($1), $2||''); + } elsif ($tagIDstr =~ /^(\d+)(\.\d*)?$/) { + $tip = sprintf(" title='%u = 0x%x'", $1, $1); + } else { + $tip = ''; + # use copyright symbol in QuickTime UserData tags + $tagIDstr =~ s/^"\\xa9/"&copy;/; + } + # add tooltip for special writable attributes + my $wtip = ''; + my %wattr = ( + '_' => 'Flattened', + '+' => 'List', + '/' => 'Avoid', + '~' => 'Writable only with -n', + '!' => 'Unsafe', + '*' => 'Protected', + ':' => 'Mandatory', + ); + my ($wstr, %hasAttr, @hasAttr); + foreach $wstr (@$writable) { + next unless $wstr =~ m{([+/~!*:_]+)$}; + my @a = split //, $1; + foreach (@a) { + next if $hasAttr{$_}; + push @hasAttr, $_; + $hasAttr{$_} = 1; + } + } + if (@hasAttr) { + $wtip = " title='"; + my $n = 0; + foreach (@hasAttr) { + $wtip .= "\n" if $n; + $wtip .= " $_ = $wattr{$_}"; + ++$n; + } + $wtip .= "'"; + } + # print this row in the tag table + print HTMLFILE "<tr$rowClass>\n"; + print HTMLFILE "<td$align$tip>$tagIDstr</td>\n" if $id; + print HTMLFILE "<td>", join("\n <br>",@htmlTags), "</td>\n"; + print HTMLFILE "<td class=c$wtip>",join('<br>',@$writable),"</td>\n"; + print HTMLFILE '<td class=n>',join("\n <br>",@$require),"</td>\n" if $composite; + print HTMLFILE "<td class=c>",join('<br>',@$writeGroup),"</td>\n" if $showGrp; + print HTMLFILE "<td>"; + if (@$values) { + if ($isSubdir) { + my ($smallNote, @values); + foreach (@$values) { + if (/^\(/) { + # set the note font + $smallNote = 1 if $numTags < 2; + push @values, ($smallNote ? $noteFontSmall : $noteFont) . "$_</span>"; + next; + } + # make text in square brackets small + if (/^\[/) { + if (s/^\[!HTML\]//) { + push @values, $_; + } else { + push @values, "<span class=s>$_</span>"; + } + next; + } + /=/ and push(@values, $_), next; + my @names = split; + my $suffix = ' Tags'; + if ($$sepTable{$_}) { + push @sepTables, $_; + $suffix = ' Values'; + } + # handle structures specially + if ($$structs{$_}) { + # assume XMP module for this struct unless otherwise specified + unshift @names, 'XMP' unless / /; + push @structs, $_; # list this later + # hack to put Area Struct in with XMP tags, + # even though it is only used by the MWG module + push @structs, 'Area' if $_ eq 'Dimensions'; + $suffix = ' Struct'; + } + $url = (shift @names) . '.html'; + @names and $url .= '#' . join '_', @names; + push @values, "--&gt; <a href='${url}'>$_$suffix</a>"; + } + # put small note last + $smallNote and push @values, shift @values; + print HTMLFILE join("\n <br>",@values); + } else { + my ($close, $br) = ('', ''); + foreach (@$values) { + if (s/^\[!HTML\]//) { + print HTMLFILE $close if $close; + print HTMLFILE $_; + $close = $br = ''; + } else { + if (/^\(/) { + # notes can use POD syntax + $_ = $noteFont . Doc2Html($_) . "</span>"; + } else { + $_ = EscapeHTML($_); + } + $close or $_ = "<span class=s>$_", $close = '</span>'; + print HTMLFILE $br, $_; + $br = "\n <br>"; + } + } + print HTMLFILE $close if $close; + } + } else { + print HTMLFILE '&nbsp;'; + } + print HTMLFILE "</td></tr>\n"; + } + warn "$longTags unaccounted-for long tags in $tableName\n" if $longTags; + if ($wasLong and not defined $longTags) { + warn "Notice: Long tags in $tableName table\n"; + } + unless ($infoCount) { + print PODFILE " [no tags known]\n"; + my $cols = 3; + ++$cols if $hid; + ++$cols if $derived; + print HTMLFILE "<tr><td colspan=$cols class=c><i>[no tags known]</i></td></tr>\n"; + } + print HTMLFILE "</table></td></tr></table></blockquote>\n\n"; + } + close(HTMLFILE) or $success = 0; + CloseHtmlFiles($self) or $success = 0; + print PODFILE Doc2Pod($docs{PodTrailer}) or $success = 0; + close(PODFILE) or $success = 0; + return $success; +} + +1; # end + + +__END__ + +=head1 NAME + +Image::ExifTool::BuildTagLookup - Build ExifTool tag lookup tables + +=head1 DESCRIPTION + +This module is used to generate the tag lookup tables in +Image::ExifTool::TagLookup.pm and tag name documentation in +Image::ExifTool::TagNames.pod, as well as HTML tag name documentation. It +is used before each new ExifTool release to update the lookup tables and +documentation, but it is not used otherwise. It also performs some +validation and consistency checks on the tag tables. + +=head1 SYNOPSIS + + use Image::ExifTool::BuildTagLookup; + + $builder = new Image::ExifTool::BuildTagLookup; + + # update Image::ExifTool::TagLookup + $ok = $builder->WriteTagLookup('lib/Image/ExifTool/TagLookup.pm'); + + # update the tag name documentation + $ok = $builder->WriteTagNames('lib/Image/ExifTool/TagNames.pod','html'); + + # print some statistics + my $count = $$builder{COUNT}; + foreach (sort keys %$count) { + printf "%5d %s\n", $$count{$_}, $_; + } + +=head1 MEMBER VARIABLES + +=over 4 + +=item PRESERVE_DATE + +Flag to preserve "Last revised" date in HTML files. Set before calling +WriteTagNames(). + +=item COUNT + +Reference to hash containing counting statistics. Keys are the +descriptions, and values are the numerical counts. Valid after +BuildTagLookup object is created, but additional statistics are added by +WriteTagNames(). + +=item WRITE_PSEUDO + +List of writable pseudo tags. + +=back + +=head1 AUTHOR + +Copyright 2003-2019, Phil Harvey (phil at owl.phy.queensu.ca) + +This library is free software; you can redistribute it and/or modify it +under the same terms as Perl itself. + +=head1 SEE ALSO + +L<Image::ExifTool(3pm)|Image::ExifTool>, +L<Image::ExifTool::TagLookup(3pm)|Image::ExifTool::TagLookup>, +L<Image::ExifTool::TagNames(3pm)|Image::ExifTool::TagNames> + +=cut diff --git a/lib/Image/ExifTool/Canon.pm b/lib/Image/ExifTool/Canon.pm new file mode 100644 index 0000000..d10055b --- /dev/null +++ b/lib/Image/ExifTool/Canon.pm @@ -0,0 +1,9513 @@ +#------------------------------------------------------------------------------ +# File: Canon.pm +# +# Description: Canon EXIF maker notes tags +# +# Revisions: 11/25/2003 - P. Harvey Created +# 12/03/2003 - P. Harvey Decode lots more tags and add CanonAFInfo +# 02/17/2004 - Michael Rommel Added IxusAFPoint +# 01/27/2005 - P. Harvey Disable validation of CanonAFInfo +# 01/30/2005 - P. Harvey Added a few more tags (ref 4) +# 02/10/2006 - P. Harvey Decode a lot of new tags (ref 12) +# [ongoing] - P. Harvey Constantly decoding new information +# +# Notes: Must check FocalPlaneX/YResolution values for each new model! +# +# References: 1) http://park2.wakwak.com/~tsuruzoh/Computer/Digicams/exif-e.html +# 2) Michael Rommel private communication (Digital Ixus) +# 3) Daniel Pittman private communication (PowerShot S70) +# 4) http://www.wonderland.org/crw/ +# 5) Juha Eskelinen private communication (20D) +# 6) Richard S. Smith private communication (20D) +# 7) Denny Priebe private communication (1DmkII) +# 8) Irwin Poche private communication +# 9) Michael Tiemann private communication (1DmkII) +# 10) Volker Gering private communication (1DmkII) +# 11) "cip" private communication +# 12) Rainer Honle private communication (5D) +# 13) http://www.cybercom.net/~dcoffin/dcraw/ +# 14) (bozi) http://www.cpanforum.com/threads/2476 and /2563 +# 15) http://homepage3.nifty.com/kamisaka/makernote/makernote_canon.htm (2007/11/19) +# + http://homepage3.nifty.com/kamisaka/makernote/CanonLens.htm (2007/11/19) +# 16) Emil Sit private communication (30D) +# 17) http://www.asahi-net.or.jp/~xp8t-ymzk/s10exif.htm +# 18) Samson Tai private communication (G7) +# 19) Warren Stockton private communication +# 20) Bogdan private communication +# 21) Heiko Hinrichs private communication +# 22) Dave Nicholson private communication (PowerShot S30) +# 23) Magne Nilsen private communication (400D) +# 24) Wolfgang Hoffmann private communication (40D) +# 25) Laurent Clevy private communication +# 26) Steve Balcombe private communication +# 27) Chris Huebsch private communication (40D) +# 28) Hal Williamson private communication (XTi) +# 29) Ger Vermeulen private communication +# 30) David Pitcher private communication (1DmkIII) +# 31) Darryl Zurn private communication (A590IS) +# 32) Rich Taylor private communication (5D) +# 33) D.J. Cristi private communication +# 34) Andreas Huggel and Pascal de Bruijn private communication +# 35) Jan Boelsma private communication +# 36) Karl-Heinz Klotz private communication (http://www.dslr-forum.de/showthread.php?t=430900) +# 37) Vesa Kivisto private communication (30D) +# 38) Kurt Garloff private communication (5DmkII) +# 39) Irwin Poche private communication (5DmkII) +# 40) Jose Oliver-Didier private communication +# 41) http://www.cpanforum.com/threads/10730 +# 42) Norbert Wasser private communication +# 43) Karsten Sote private communication +# 44) Hugh Griffiths private communication (5DmkII) +# 45) Mark Berger private communication (5DmkII) +# 46) Dieter Steiner private communication (7D) +# 47) http://www.exiv2.org/ +# 48) Tomasz A. Kawecki private communication (550D, firmware 1.0.6, 1.0.8) +# 49) http://www.listware.net/201101/digikam-users/49795-digikam-users-re-lens-recognition.html +# 50) http://u88.n24.queensu.ca/exiftool/forum/index.php/topic,3833.0.html +# 51) http://u88.n24.queensu.ca/exiftool/forum/index.php/topic,4110.0.html +# 52) Kai Harrekilde-Petersen private communication +# 53) Anton Reiser private communication +# IB) Iliah Borg private communication (LibRaw) +# JD) Jens Duttke private communication +# JR) Jos Roost private communication +# NJ) Niels Kristian Bech Jensen private communication +#------------------------------------------------------------------------------ + +package Image::ExifTool::Canon; + +use strict; +use vars qw($VERSION %canonModelID %canonLensTypes); +use Image::ExifTool qw(:DataAccess :Utils); +use Image::ExifTool::Exif; + +sub WriteCanon($$$); +sub ProcessSerialData($$$); +sub ProcessFilters($$$); +sub ProcessCTMD($$$); +sub ProcessExifInfo($$$); +sub SwapWords($); + +$VERSION = '4.07'; + +# Note: Removed 'USM' from 'L' lenses since it is redundant - PH +# (or is it? Ref 32 shows 5 non-USM L-type lenses) +# --> have relaxed this for new lenses because Canon has been +# consistent about keeping "USM" in the model name +%canonLensTypes = ( #4 + Notes => q{ + Decimal values have been added to differentiate lenses which would otherwise + have the same LensType, and are used by the Composite LensID tag when + attempting to identify the specific lens model. + }, + -1 => 'n/a', + 1 => 'Canon EF 50mm f/1.8', + 2 => 'Canon EF 28mm f/2.8 or Sigma Lens', + 2.1 => 'Sigma 24mm f/2.8 Super Wide II', #ClaudeJolicoeur + # (3 removed in current Kamisaka list) + 3 => 'Canon EF 135mm f/2.8 Soft', #15/32 + 4 => 'Canon EF 35-105mm f/3.5-4.5 or Sigma Lens', #28 + 4.1 => 'Sigma UC Zoom 35-135mm f/4-5.6', + 5 => 'Canon EF 35-70mm f/3.5-4.5', #32 + 6 => 'Canon EF 28-70mm f/3.5-4.5 or Sigma or Tokina Lens', #32 + 6.1 => 'Sigma 18-50mm f/3.5-5.6 DC', #23 + 6.2 => 'Sigma 18-125mm f/3.5-5.6 DC IF ASP', + 6.3 => 'Tokina AF 193-2 19-35mm f/3.5-4.5', + 6.4 => 'Sigma 28-80mm f/3.5-5.6 II Macro', #47 + 6.5 => 'Sigma 28-300mm f/3.5-6.3 DG Macro', #IB + 7 => 'Canon EF 100-300mm f/5.6L', #15 + 8 => 'Canon EF 100-300mm f/5.6 or Sigma or Tokina Lens', #32 + 8.1 => 'Sigma 70-300mm f/4-5.6 [APO] DG Macro', #15 (both APO and non-APO, ref forum2947) + 8.2 => 'Tokina AT-X 242 AF 24-200mm f/3.5-5.6', #15 + 9 => 'Canon EF 70-210mm f/4', #32 + 9.1 => 'Sigma 55-200mm f/4-5.6 DC', #34 + 10 => 'Canon EF 50mm f/2.5 Macro or Sigma Lens', #10 (+ LSC Life Size Converter --> 70mm - PH) + 10.1 => 'Sigma 50mm f/2.8 EX', #4 + 10.2 => 'Sigma 28mm f/1.8', + 10.3 => 'Sigma 105mm f/2.8 Macro EX', #15 + 10.4 => 'Sigma 70mm f/2.8 EX DG Macro EF', #Jean-Michel Dubois + 11 => 'Canon EF 35mm f/2', #9 + 13 => 'Canon EF 15mm f/2.8 Fisheye', #9 + 14 => 'Canon EF 50-200mm f/3.5-4.5L', #32 + 15 => 'Canon EF 50-200mm f/3.5-4.5', #32 + 16 => 'Canon EF 35-135mm f/3.5-4.5', #32 + 17 => 'Canon EF 35-70mm f/3.5-4.5A', #32 + 18 => 'Canon EF 28-70mm f/3.5-4.5', #32 + 20 => 'Canon EF 100-200mm f/4.5A', #32 + 21 => 'Canon EF 80-200mm f/2.8L', + 22 => 'Canon EF 20-35mm f/2.8L or Tokina Lens', #32 + 22.1 => 'Tokina AT-X 280 AF Pro 28-80mm f/2.8 Aspherical', #15 + 23 => 'Canon EF 35-105mm f/3.5-4.5', #32 + 24 => 'Canon EF 35-80mm f/4-5.6 Power Zoom', #32 + 25 => 'Canon EF 35-80mm f/4-5.6 Power Zoom', #32 + 26 => 'Canon EF 100mm f/2.8 Macro or Other Lens', + 26.1 => 'Cosina 100mm f/3.5 Macro AF', + 26.2 => 'Tamron SP AF 90mm f/2.8 Di Macro', #15 + 26.3 => 'Tamron SP AF 180mm f/3.5 Di Macro', #15 + 26.4 => 'Carl Zeiss Planar T* 50mm f/1.4', #PH + 27 => 'Canon EF 35-80mm f/4-5.6', #32 + # 27 => 'Carl Zeiss Distagon T* 28mm f/2 ZF', #PH (must be with an adapter, because the ZF version is a Nikon mount) + # 27 => 'EMF adapter for Canon EOS digital cameras', #50 (reports MaxFocalLength of 65535) + # 27 => optix adapter + # 27 => Venus Optics Laowa 12mm f2.8 Zero-D or 105mm f2 (T3.2) Smooth Trans Focus (ref IB) + 28 => 'Canon EF 80-200mm f/4.5-5.6 or Tamron Lens', #32 + 28.1 => 'Tamron SP AF 28-105mm f/2.8 LD Aspherical IF', #15 + 28.2 => 'Tamron SP AF 28-75mm f/2.8 XR Di LD Aspherical [IF] Macro', #4 + # 28.3 => 'Tamron AF 70-300mm f/4.5-5.6 Di LD 1:2 Macro Zoom', #11 + 28.3 => 'Tamron AF 70-300mm f/4-5.6 Di LD 1:2 Macro', #47 + 28.4 => 'Tamron AF Aspherical 28-200mm f/3.8-5.6', #14 + 29 => 'Canon EF 50mm f/1.8 II', + 30 => 'Canon EF 35-105mm f/4.5-5.6', #32 + 31 => 'Canon EF 75-300mm f/4-5.6 or Tamron Lens', #32 + 31.1 => 'Tamron SP AF 300mm f/2.8 LD IF', #15 + 32 => 'Canon EF 24mm f/2.8 or Sigma Lens', #10 + 32.1 => 'Sigma 15mm f/2.8 EX Fisheye', #11 + 33 => 'Voigtlander or Carl Zeiss Lens', + 33.1 => 'Voigtlander Ultron 40mm f/2 SLII Aspherical', #45 + 33.2 => 'Voigtlander Color Skopar 20mm f/3.5 SLII Aspherical', #50 + 33.3 => 'Voigtlander APO-Lanthar 90mm f/3.5 SLII Close Focus', #50 + 33.4 => 'Carl Zeiss Distagon T* 15mm f/2.8 ZE', #PH + 33.5 => 'Carl Zeiss Distagon T* 18mm f/3.5 ZE', #PH + 33.6 => 'Carl Zeiss Distagon T* 21mm f/2.8 ZE', #PH + 33.7 => 'Carl Zeiss Distagon T* 25mm f/2 ZE', #IB + 33.8 => 'Carl Zeiss Distagon T* 28mm f/2 ZE', #PH + 33.9 => 'Carl Zeiss Distagon T* 35mm f/2 ZE', #PH + '33.10' => 'Carl Zeiss Distagon T* 35mm f/1.4 ZE', #IB + '33.11' => 'Carl Zeiss Planar T* 50mm f/1.4 ZE', #IB + '33.12' => 'Carl Zeiss Makro-Planar T* 50mm f/2 ZE', #IB + '33.13' => 'Carl Zeiss Makro-Planar T* 100mm f/2 ZE', #IB + '33.14' => 'Carl Zeiss Apo-Sonnar T* 135mm f/2 ZE', #JR + 35 => 'Canon EF 35-80mm f/4-5.6', #32 + 36 => 'Canon EF 38-76mm f/4.5-5.6', #32 + 37 => 'Canon EF 35-80mm f/4-5.6 or Tamron Lens', #32 + 37.1 => 'Tamron 70-200mm f/2.8 Di LD IF Macro', #PH + 37.2 => 'Tamron AF 28-300mm f/3.5-6.3 XR Di VC LD Aspherical [IF] Macro Model A20', #38 + 37.3 => 'Tamron SP AF 17-50mm f/2.8 XR Di II VC LD Aspherical [IF]', #34 + 37.4 => 'Tamron AF 18-270mm f/3.5-6.3 Di II VC LD Aspherical [IF] Macro', #forum2937 + 38 => 'Canon EF 80-200mm f/4.5-5.6', #32 + 39 => 'Canon EF 75-300mm f/4-5.6', + 40 => 'Canon EF 28-80mm f/3.5-5.6', + 41 => 'Canon EF 28-90mm f/4-5.6', #32 + 42 => 'Canon EF 28-200mm f/3.5-5.6 or Tamron Lens', #32 + 42.1 => 'Tamron AF 28-300mm f/3.5-6.3 XR Di VC LD Aspherical [IF] Macro Model A20', #15 + 43 => 'Canon EF 28-105mm f/4-5.6', #10 + 44 => 'Canon EF 90-300mm f/4.5-5.6', #32 + 45 => 'Canon EF-S 18-55mm f/3.5-5.6 [II]', #PH (same ID for version II, ref 20) + 46 => 'Canon EF 28-90mm f/4-5.6', #32 + 47 => 'Zeiss Milvus 35mm f/2 or 50mm f/2', #IB + 47.1 => 'Zeiss Milvus 50mm f/2 Makro', #IB + 48 => 'Canon EF-S 18-55mm f/3.5-5.6 IS', #20 + 49 => 'Canon EF-S 55-250mm f/4-5.6 IS', #23 + 50 => 'Canon EF-S 18-200mm f/3.5-5.6 IS', + 51 => 'Canon EF-S 18-135mm f/3.5-5.6 IS', #PH + 52 => 'Canon EF-S 18-55mm f/3.5-5.6 IS II', #PH + 53 => 'Canon EF-S 18-55mm f/3.5-5.6 III', #Jon Charnas + 54 => 'Canon EF-S 55-250mm f/4-5.6 IS II', #47 + 60 => 'Irix 11mm f/4', #50 + 80 => 'Canon TS-E 50mm f/2.8L Macro', #42 + 81 => 'Canon TS-E 90mm f/2.8L Macro', #42 + 82 => 'Canon TS-E 135mm f/4L Macro', #42 + 94 => 'Canon TS-E 17mm f/4L', #42 + 95 => 'Canon TS-E 24mm f/3.5L II', #43 + 103 => 'Samyang AF 14mm f/2.8 EF or Rokinon Lens', #IB + 103.1 => 'Rokinon SP 14mm f/2.4', #IB + 103.2 => 'Rokinon AF 14mm f/2.8 EF', #IB + 124 => 'Canon MP-E 65mm f/2.8 1-5x Macro Photo', #9 + 125 => 'Canon TS-E 24mm f/3.5L', + 126 => 'Canon TS-E 45mm f/2.8', #15 + 127 => 'Canon TS-E 90mm f/2.8', #15 + 129 => 'Canon EF 300mm f/2.8L USM', #32 + 130 => 'Canon EF 50mm f/1.0L USM', #10/15 + 131 => 'Canon EF 28-80mm f/2.8-4L USM or Sigma Lens', #32 + 131.1 => 'Sigma 8mm f/3.5 EX DG Circular Fisheye', #15 + 131.2 => 'Sigma 17-35mm f/2.8-4 EX DG Aspherical HSM', #15 + 131.3 => 'Sigma 17-70mm f/2.8-4.5 DC Macro', #PH (NC) + 131.4 => 'Sigma APO 50-150mm f/2.8 [II] EX DC HSM', #15 ([II] ref PH) + 131.5 => 'Sigma APO 120-300mm f/2.8 EX DG HSM', #15 + # 'Sigma APO 120-300mm f/2.8 EX DG HSM + 1.4x', #15 + # 'Sigma APO 120-300mm f/2.8 EX DG HSM + 2x', #15 + 131.6 => 'Sigma 4.5mm f/2.8 EX DC HSM Circular Fisheye', #PH + 131.7 => 'Sigma 70-200mm f/2.8 APO EX HSM', #PH (http://www.lensrentals.com/blog/2012/08/canon-illumination-correction-and-third-party-lenses) + 132 => 'Canon EF 1200mm f/5.6L USM', #32 + 134 => 'Canon EF 600mm f/4L IS USM', #15 + 135 => 'Canon EF 200mm f/1.8L USM', + 136 => 'Canon EF 300mm f/2.8L USM', + 137 => 'Canon EF 85mm f/1.2L USM or Sigma or Tamron Lens', #10 + 137.1 => 'Sigma 18-50mm f/2.8-4.5 DC OS HSM', #PH + 137.2 => 'Sigma 50-200mm f/4-5.6 DC OS HSM', #PH + 137.3 => 'Sigma 18-250mm f/3.5-6.3 DC OS HSM', #PH (also Sigma 18-250mm f/3.5-6.3 DC Macro OS HSM) + 137.4 => 'Sigma 24-70mm f/2.8 IF EX DG HSM', #PH + 137.5 => 'Sigma 18-125mm f/3.8-5.6 DC OS HSM', #PH + 137.6 => 'Sigma 17-70mm f/2.8-4 DC Macro OS HSM | C', #forum2819 (Contemporary version has this ID - PH) + 137.7 => 'Sigma 17-50mm f/2.8 OS HSM', #47 + 137.8 => 'Sigma 18-200mm f/3.5-6.3 DC OS HSM [II]', #PH + 137.9 => 'Tamron AF 18-270mm f/3.5-6.3 Di II VC PZD', #(model B008)forum3090 + '137.10' => 'Sigma 8-16mm f/4.5-5.6 DC HSM', #50-Zwielicht + '137.11' => 'Tamron SP 17-50mm f/2.8 XR Di II VC', #50 (model B005) + '137.12' => 'Tamron SP 60mm f/2 Macro Di II', #50 (model G005) + '137.13' => 'Sigma 10-20mm f/3.5 EX DC HSM', #Gerald Erdmann + '137.14' => 'Tamron SP 24-70mm f/2.8 Di VC USD', #PH + '137.15' => 'Sigma 18-35mm f/1.8 DC HSM', #David Monro + '137.16' => 'Sigma 12-24mm f/4.5-5.6 DG HSM II', #IB + 138 => 'Canon EF 28-80mm f/2.8-4L', #32 + 139 => 'Canon EF 400mm f/2.8L USM', + 140 => 'Canon EF 500mm f/4.5L USM', #32 + 141 => 'Canon EF 500mm f/4.5L USM', + 142 => 'Canon EF 300mm f/2.8L IS USM', #15 + 143 => 'Canon EF 500mm f/4L IS USM or Sigma Lens', #15 + 143.1 => 'Sigma 17-70mm f/2.8-4 DC Macro OS HSM', #NJ (Exiv2 #1167) + 144 => 'Canon EF 35-135mm f/4-5.6 USM', #26 + 145 => 'Canon EF 100-300mm f/4.5-5.6 USM', #32 + 146 => 'Canon EF 70-210mm f/3.5-4.5 USM', #32 + 147 => 'Canon EF 35-135mm f/4-5.6 USM', #32 + 148 => 'Canon EF 28-80mm f/3.5-5.6 USM', #32 + 149 => 'Canon EF 100mm f/2 USM', #9 + 150 => 'Canon EF 14mm f/2.8L USM or Sigma Lens', #10 + 150.1 => 'Sigma 20mm EX f/1.8', #4 + 150.2 => 'Sigma 30mm f/1.4 DC HSM', #15 + 150.3 => 'Sigma 24mm f/1.8 DG Macro EX', #15 + 150.4 => 'Sigma 28mm f/1.8 DG Macro EX', #IB + 151 => 'Canon EF 200mm f/2.8L USM', + 152 => 'Canon EF 300mm f/4L IS USM or Sigma Lens', #15 + 152.1 => 'Sigma 12-24mm f/4.5-5.6 EX DG ASPHERICAL HSM', #15 + 152.2 => 'Sigma 14mm f/2.8 EX Aspherical HSM', #15 + 152.3 => 'Sigma 10-20mm f/4-5.6', #14 + 152.4 => 'Sigma 100-300mm f/4', # (ref Bozi) + 153 => 'Canon EF 35-350mm f/3.5-5.6L USM or Sigma or Tamron Lens', #PH + 153.1 => 'Sigma 50-500mm f/4-6.3 APO HSM EX', #15 + 153.2 => 'Tamron AF 28-300mm f/3.5-6.3 XR LD Aspherical [IF] Macro', + 153.3 => 'Tamron AF 18-200mm f/3.5-6.3 XR Di II LD Aspherical [IF] Macro Model A14', #15 + 153.4 => 'Tamron 18-250mm f/3.5-6.3 Di II LD Aspherical [IF] Macro', #PH + 154 => 'Canon EF 20mm f/2.8 USM or Zeiss Lens', #15 + 154.1 => 'Zeiss Milvus 21mm f/2.8', #IB + 155 => 'Canon EF 85mm f/1.8 USM', + 156 => 'Canon EF 28-105mm f/3.5-4.5 USM or Tamron Lens', + 156.1 => 'Tamron SP 70-300mm f/4-5.6 Di VC USD', #PH (model A005) + 156.2 => 'Tamron SP AF 28-105mm f/2.8 LD Aspherical IF', #JR (Model 176D) + 160 => 'Canon EF 20-35mm f/3.5-4.5 USM or Tamron or Tokina Lens', + 160.1 => 'Tamron AF 19-35mm f/3.5-4.5', #44 + 160.2 => 'Tokina AT-X 124 AF Pro DX 12-24mm f/4', #49 + 160.3 => 'Tokina AT-X 107 AF DX 10-17mm f/3.5-4.5 Fisheye', #PH (http://osdir.com/ml/digikam-devel/2011-04/msg00275.html) + 160.4 => 'Tokina AT-X 116 AF Pro DX 11-16mm f/2.8', #forum3967 + 160.5 => 'Tokina AT-X 11-20 F2.8 PRO DX Aspherical 11-20mm f/2.8', #NJ (Exiv2 #1166) + 161 => 'Canon EF 28-70mm f/2.8L USM or Other Lens', + 161.1 => 'Sigma 24-70mm f/2.8 EX', + 161.2 => 'Sigma 28-70mm f/2.8 EX', #PH (http://www.breezesys.com/forum/showthread.php?t=3718) + 161.3 => 'Sigma 24-60mm f/2.8 EX DG', #PH (http://www.lensrentals.com/blog/2012/08/canon-illumination-correction-and-third-party-lenses) + 161.4 => 'Tamron AF 17-50mm f/2.8 Di-II LD Aspherical', #40 + 161.5 => 'Tamron 90mm f/2.8', + 161.6 => 'Tamron SP AF 17-35mm f/2.8-4 Di LD Aspherical IF', #IB (A05) + 161.7 => 'Tamron SP AF 28-75mm f/2.8 XR Di LD Aspherical [IF] Macro', #IB/NJ + 161.8 => 'Tokina AT-X 24-70mm f/2.8 PRO FX (IF)', #IB + 162 => 'Canon EF 200mm f/2.8L USM', #32 + 163 => 'Canon EF 300mm f/4L', #32 + 164 => 'Canon EF 400mm f/5.6L', #32 + 165 => 'Canon EF 70-200mm f/2.8L USM', + 166 => 'Canon EF 70-200mm f/2.8L USM + 1.4x', + 167 => 'Canon EF 70-200mm f/2.8L USM + 2x', + 168 => 'Canon EF 28mm f/1.8 USM or Sigma Lens', #15 + 168.1 => 'Sigma 50-100mm f/1.8 DC HSM | A', #IB + 169 => 'Canon EF 17-35mm f/2.8L USM or Sigma Lens', #15 + 169.1 => 'Sigma 18-200mm f/3.5-6.3 DC OS', #23 + 169.2 => 'Sigma 15-30mm f/3.5-4.5 EX DG Aspherical', #4 + 169.3 => 'Sigma 18-50mm f/2.8 Macro', #26 + 169.4 => 'Sigma 50mm f/1.4 EX DG HSM', #PH + 169.5 => 'Sigma 85mm f/1.4 EX DG HSM', #Rolando Ruzic + 169.6 => 'Sigma 30mm f/1.4 EX DC HSM', #Rodolfo Borges + 169.7 => 'Sigma 35mm f/1.4 DG HSM', #PH (also "| A" version, ref 50) + 169.8 => 'Sigma 35mm f/1.5 FF High-Speed Prime | 017', #IB + 170 => 'Canon EF 200mm f/2.8L II USM', #9 + 171 => 'Canon EF 300mm f/4L USM', #15 + 172 => 'Canon EF 400mm f/5.6L USM or Sigma Lens', #32 + 172.1 =>'Sigma 150-600mm f/5-6.3 DG OS HSM | S', #50 + 173 => 'Canon EF 180mm Macro f/3.5L USM or Sigma Lens', #9 + 173.1 => 'Sigma 180mm EX HSM Macro f/3.5', #14 + 173.2 => 'Sigma APO Macro 150mm f/2.8 EX DG HSM', #14 + 174 => 'Canon EF 135mm f/2L USM or Other Lens', #9 + 174.1 => 'Sigma 70-200mm f/2.8 EX DG APO OS HSM', #PH (probably version II of this lens) + 174.2 => 'Sigma 50-500mm f/4.5-6.3 APO DG OS HSM', #forum4031 + 174.3 => 'Sigma 150-500mm f/5-6.3 APO DG OS HSM', #47 + 174.4 => 'Zeiss Milvus 100mm f/2 Makro', #IB + 175 => 'Canon EF 400mm f/2.8L USM', #32 + 176 => 'Canon EF 24-85mm f/3.5-4.5 USM', + 177 => 'Canon EF 300mm f/4L IS USM', #9 + 178 => 'Canon EF 28-135mm f/3.5-5.6 IS', + 179 => 'Canon EF 24mm f/1.4L USM', #20 + 180 => 'Canon EF 35mm f/1.4L USM or Other Lens', #9 + 180.1 => 'Sigma 50mm f/1.4 DG HSM | A', #50 + 180.2 => 'Sigma 24mm f/1.4 DG HSM | A', #NJ + 180.3 => 'Zeiss Milvus 50mm f/1.4', #IB + 180.4 => 'Zeiss Milvus 85mm f/1.4', #IB + 180.5 => 'Zeiss Otus 28mm f/1.4 ZE', #PH + 180.6 => 'Sigma 24mm f/1.5 FF High-Speed Prime | 017', #IB + 180.7 => 'Sigma 50mm f/1.5 FF High-Speed Prime | 017', #IB + 180.8 => 'Sigma 85mm f/1.5 FF High-Speed Prime | 017', #IB + 181 => 'Canon EF 100-400mm f/4.5-5.6L IS USM + 1.4x or Sigma Lens', #15 + 181.1 => 'Sigma 150-600mm f/5-6.3 DG OS HSM | S + 1.4x', #50 + 182 => 'Canon EF 100-400mm f/4.5-5.6L IS USM + 2x or Sigma Lens', + 182.1 => 'Sigma 150-600mm f/5-6.3 DG OS HSM | S + 2x', #PH (NC) + 183 => 'Canon EF 100-400mm f/4.5-5.6L IS USM or Sigma Lens', + 183.1 => 'Sigma 150mm f/2.8 EX DG OS HSM APO Macro', #50 + 183.2 => 'Sigma 105mm f/2.8 EX DG OS HSM Macro', #50 + 183.3 => 'Sigma 180mm f/2.8 EX DG OS HSM APO Macro', #IB + 183.4 => 'Sigma 150-600mm f/5-6.3 DG OS HSM | C', #47 + 183.5 => 'Sigma 150-600mm f/5-6.3 DG OS HSM | S', #forum7109 (Sports 014) + 183.6 => 'Sigma 100-400mm f/5-6.3 DG OS HSM', #PH ("| C" ?) + 183.7 => 'Sigma 180mm f/3.5 APO Macro EX DG IF HSM', #IB + 184 => 'Canon EF 400mm f/2.8L USM + 2x', #15 + 185 => 'Canon EF 600mm f/4L IS USM', #32 + 186 => 'Canon EF 70-200mm f/4L USM', #9 + 187 => 'Canon EF 70-200mm f/4L USM + 1.4x', #26 + 188 => 'Canon EF 70-200mm f/4L USM + 2x', #PH + 189 => 'Canon EF 70-200mm f/4L USM + 2.8x', #32 + 190 => 'Canon EF 100mm f/2.8 Macro USM', # (+USM ref 42) + 191 => 'Canon EF 400mm f/4 DO IS or Sigma Lens', #9 + 191.1 => 'Sigma 500mm f/4 DG OS HSM', #AndrewSheih + 193 => 'Canon EF 35-80mm f/4-5.6 USM', #32 + 194 => 'Canon EF 80-200mm f/4.5-5.6 USM', #32 + 195 => 'Canon EF 35-105mm f/4.5-5.6 USM', #32 + 196 => 'Canon EF 75-300mm f/4-5.6 USM', #15/32 + 197 => 'Canon EF 75-300mm f/4-5.6 IS USM or Sigma Lens', + 197.1 => 'Sigma 18-300mm f/3.5-6.3 DC Macro OS HS', #50 + 198 => 'Canon EF 50mm f/1.4 USM or Zeiss Lens', + 198.1 => 'Zeiss Otus 55mm f/1.4 ZE', #JR (seen only on Sony camera) + 198.2 => 'Zeiss Otus 85mm f/1.4 ZE', #JR (NC) + 198.3 => 'Zeiss Milvus 25mm f/1.4', #IB + 199 => 'Canon EF 28-80mm f/3.5-5.6 USM', #32 + 200 => 'Canon EF 75-300mm f/4-5.6 USM', #32 + 201 => 'Canon EF 28-80mm f/3.5-5.6 USM', #32 + 202 => 'Canon EF 28-80mm f/3.5-5.6 USM IV', + 208 => 'Canon EF 22-55mm f/4-5.6 USM', #32 + 209 => 'Canon EF 55-200mm f/4.5-5.6', #32 + 210 => 'Canon EF 28-90mm f/4-5.6 USM', #32 + 211 => 'Canon EF 28-200mm f/3.5-5.6 USM', #15 + 212 => 'Canon EF 28-105mm f/4-5.6 USM', #15 + 213 => 'Canon EF 90-300mm f/4.5-5.6 USM or Tamron Lens', + 213.1 => 'Tamron SP 150-600mm f/5-6.3 Di VC USD', #topic5565 (model A011) + 213.2 => 'Tamron 16-300mm f/3.5-6.3 Di II VC PZD Macro', #PH (model B016) + 213.3 => 'Tamron SP 35mm f/1.8 Di VC USD', #PH (model F012) + 213.4 => 'Tamron SP 45mm f/1.8 Di VC USD', #PH (model F013) + 214 => 'Canon EF-S 18-55mm f/3.5-5.6 USM', #PH/34 + 215 => 'Canon EF 55-200mm f/4.5-5.6 II USM', + 217 => 'Tamron AF 18-270mm f/3.5-6.3 Di II VC PZD', #47 + 224 => 'Canon EF 70-200mm f/2.8L IS USM', #11 + 225 => 'Canon EF 70-200mm f/2.8L IS USM + 1.4x', #11 + 226 => 'Canon EF 70-200mm f/2.8L IS USM + 2x', #14 + 227 => 'Canon EF 70-200mm f/2.8L IS USM + 2.8x', #32 + 228 => 'Canon EF 28-105mm f/3.5-4.5 USM', #32 + 229 => 'Canon EF 16-35mm f/2.8L USM', #PH + 230 => 'Canon EF 24-70mm f/2.8L USM', #9 + 231 => 'Canon EF 17-40mm f/4L USM', + 232 => 'Canon EF 70-300mm f/4.5-5.6 DO IS USM', #15 + 233 => 'Canon EF 28-300mm f/3.5-5.6L IS USM', #PH + 234 => 'Canon EF-S 17-85mm f/4-5.6 IS USM or Tokina Lens', #19 + 234.1 => 'Tokina AT-X 12-28 PRO DX 12-28mm f/4', #50/NJ + 235 => 'Canon EF-S 10-22mm f/3.5-4.5 USM', #15 + 236 => 'Canon EF-S 60mm f/2.8 Macro USM', #15 + 237 => 'Canon EF 24-105mm f/4L IS USM', #15 + 238 => 'Canon EF 70-300mm f/4-5.6 IS USM', #15 (and version II? ref 42) + 239 => 'Canon EF 85mm f/1.2L II USM or Rokinon Lens', #15 + 239.1 => 'Rokinon SP 85mm f/1.2', #IB + 240 => 'Canon EF-S 17-55mm f/2.8 IS USM or Sigma Lens', #15 + 240.1 => 'Sigma 17-50mm f/2.8 EX DC OS HSM', #https://github.com/Exiv2/exiv2/issues/397 + 241 => 'Canon EF 50mm f/1.2L USM', #15 + 242 => 'Canon EF 70-200mm f/4L IS USM', #PH + 243 => 'Canon EF 70-200mm f/4L IS USM + 1.4x', #15 + 244 => 'Canon EF 70-200mm f/4L IS USM + 2x', #PH + 245 => 'Canon EF 70-200mm f/4L IS USM + 2.8x', #32 + 246 => 'Canon EF 16-35mm f/2.8L II USM', #PH + 247 => 'Canon EF 14mm f/2.8L II USM', #32 + 248 => 'Canon EF 200mm f/2L IS USM or Sigma Lens', #42 + 248.1 => 'Sigma 24-35mm f/2 DG HSM | A', #JR + 248.2 => 'Sigma 135mm f/2 FF High-Speed Prime | 017', #IB + 248.3 => 'Sigma 24-35mm f/2.2 FF Zoom | 017', #IB + 249 => 'Canon EF 800mm f/5.6L IS USM', #35 + 250 => 'Canon EF 24mm f/1.4L II USM or Sigma Lens', #41 + 250.1 => 'Sigma 20mm f/1.4 DG HSM | A', #IB + 250.2 => 'Sigma 20mm f/1.5 FF High-Speed Prime | 017', #IB + 251 => 'Canon EF 70-200mm f/2.8L IS II USM', + 252 => 'Canon EF 70-200mm f/2.8L IS II USM + 1.4x', #50 (1.4x Mk II) + 253 => 'Canon EF 70-200mm f/2.8L IS II USM + 2x', #PH (NC) + # 253.1 => 'Tamron SP 70-200mm f/2.8 Di VC USD G2 (A025) + 2x', #forum9367 + 254 => 'Canon EF 100mm f/2.8L Macro IS USM', #42 + 255 => 'Sigma 24-105mm f/4 DG OS HSM | A or Other Sigma Lens', #50 + 255.1 => 'Sigma 180mm f/2.8 EX DG OS HSM APO Macro', #50 + 368 => 'Sigma 14-24mm f/2.8 DG HSM | A or other Sigma Lens', #IB (A018) + 368.1 => 'Sigma 20mm f/1.4 DG HSM | A', #50 (newer firmware) + 368.2 => 'Sigma 50mm f/1.4 DG HSM | A', #50 + 368.3 => 'Sigma 40mm f/1.4 DG HSM | A', #IB (018) + 368.4 => 'Sigma 60-600mm f/4.5-6.3 DG OS HSM | S', #IB (018) + 368.5 => 'Sigma 28mm f/1.4 DG HSM | A', #IB (A019) + # Note: LensType 488 (0x1e8) is reported as 232 (0xe8) in 7D CameraSettings + 488 => 'Canon EF-S 15-85mm f/3.5-5.6 IS USM', #PH + 489 => 'Canon EF 70-300mm f/4-5.6L IS USM', #Gerald Kapounek + 490 => 'Canon EF 8-15mm f/4L Fisheye USM', #Klaus Reinfeld (PH added "Fisheye") + 491 => 'Canon EF 300mm f/2.8L IS II USM or Tamron Lens', #42 + 491.1 => 'Tamron SP 70-200mm f/2.8 Di VC USD G2 (A025)', #IB + 491.2 => 'Tamron 18-400mm f/3.5-6.3 Di II VC HLD (B028)', #IB + 491.3 => 'Tamron 100-400mm f/4.5-6.3 Di VC USD (A035)', #IB + 491.4 => 'Tamron 70-210mm f/4 Di VC USD (A034)', #IB + 491.5 => 'Tamron 70-210mm f/4 Di VC USD (A034) + 1.4x', #IB + 491.6 => 'Tamron SP 24-70mm f/2.8 Di VC USD G2 (A032)', + 492 => 'Canon EF 400mm f/2.8L IS II USM', #PH + 493 => 'Canon EF 500mm f/4L IS II USM or EF 24-105mm f4L IS USM', #PH + 493.1 => 'Canon EF 24-105mm f/4L IS USM', #PH (should recheck this) + 494 => 'Canon EF 600mm f/4L IS II USM', #PH + 495 => 'Canon EF 24-70mm f/2.8L II USM or Sigma Lens', #PH + 495.1 => 'Sigma 24-70mm F2.8 DG OS HSM | A', #IB (017) + 496 => 'Canon EF 200-400mm f/4L IS USM', #PH + 499 => 'Canon EF 200-400mm f/4L IS USM + 1.4x', #50 + 502 => 'Canon EF 28mm f/2.8 IS USM or Tamron Lens', #PH + 502.1 => 'Tamron 35mm f/1.8 Di VC USD (F012)', #forum9757 + 503 => 'Canon EF 24mm f/2.8 IS USM', #PH + 504 => 'Canon EF 24-70mm f/4L IS USM', #PH + 505 => 'Canon EF 35mm f/2 IS USM', #PH + 506 => 'Canon EF 400mm f/4 DO IS II USM', #42 + 507 => 'Canon EF 16-35mm f/4L IS USM', #42 + 508 => 'Canon EF 11-24mm f/4L USM or Tamron Lens', #PH + 508.1 => 'Tamron 10-24mm f/3.5-4.5 Di II VC HLD', #PH (B023) + 747 => 'Canon EF 100-400mm f/4.5-5.6L IS II USM or Tamron Lens', #JR + 747.1 => 'Tamron SP 150-600mm f/5-6.3 Di VC USD G2', #50 + 748 => 'Canon EF 100-400mm f/4.5-5.6L IS II USM + 1.4x or Tamron Lens', #JR (1.4x Mk III) + 748.1 => 'Tamron 100-400mm f/4.5-6.3 Di VC USD A035E + 1.4x', #IB + 748.2 => 'Tamron 70-210mm f/4 Di VC USD (A034) + 2x', #IB + 749 => 'Tamron 100-400mm f/4.5-6.3 Di VC USD A035E + 2x', #IB + 750 => 'Canon EF 35mm f/1.4L II USM', #42 + 751 => 'Canon EF 16-35mm f/2.8L III USM', #42 + 752 => 'Canon EF 24-105mm f/4L IS II USM', #42 + 753 => 'Canon EF 85mm f/1.4L IS USM', #42 + 754 => 'Canon EF 70-200mm f/4L IS II USM', #IB + 757 => 'Canon EF 400mm f/2.8L IS III USM', #IB + 758 => 'Canon EF 600mm f/4L IS III USM', #IB + + 1136 => 'Sigma 24-70mm f/2.8 DG OS HSM | Art 017', #IB + # (STM lenses - 0x10xx) + 4142 => 'Canon EF-S 18-135mm f/3.5-5.6 IS STM', + 4143 => 'Canon EF-M 18-55mm f/3.5-5.6 IS STM or Tamron Lens', + 4143.1 => 'Tamron 18-200mm f/3.5-6.3 Di III VC', #42 + 4144 => 'Canon EF 40mm f/2.8 STM', #50 + 4145 => 'Canon EF-M 22mm f/2 STM', #34 + 4146 => 'Canon EF-S 18-55mm f/3.5-5.6 IS STM', #PH + 4147 => 'Canon EF-M 11-22mm f/4-5.6 IS STM', #42 + 4148 => 'Canon EF-S 55-250mm f/4-5.6 IS STM', #42 + 4149 => 'Canon EF-M 55-200mm f/4.5-6.3 IS STM', #42 + 4150 => 'Canon EF-S 10-18mm f/4.5-5.6 IS STM', #42 + 4152 => 'Canon EF 24-105mm f/3.5-5.6 IS STM', #42 + 4153 => 'Canon EF-M 15-45mm f/3.5-6.3 IS STM', #PH + 4154 => 'Canon EF-S 24mm f/2.8 STM', #IB + 4155 => 'Canon EF-M 28mm f/3.5 Macro IS STM', #42 + 4156 => 'Canon EF 50mm f/1.8 STM', #42 + 4157 => 'Canon EF-M 18-150mm 1:3.5-6.3 IS STM', #42 + 4158 => 'Canon EF-S 18-55mm f/4-5.6 IS STM', #PH + 4159 => 'Canon EF-M 32mm f/1.4 STM', #42 + 4160 => 'Canon EF-S 35mm f/2.8 Macro IS STM', #42 + # (Nano USM lenses - 0x90xx) + 36910 => 'Canon EF 70-300mm f/4-5.6 IS II USM', #42 + 36912 => 'Canon EF-S 18-135mm f/3.5-5.6 IS USM', #42 + # (CN-E lenses - 0xf0xx) + 61491 => 'Canon CN-E 14mm T3.1 L F', #PH + 61492 => 'Canon CN-E 24mm T1.5 L F', #PH + # 61493 - missing CN-E 50mm T1.3 L F ? + 61494 => 'Canon CN-E 85mm T1.3 L F', #PH + 61495 => 'Canon CN-E 135mm T2.2 L F', #PH + 61496 => 'Canon CN-E 35mm T1.5 L F', #PH + 61182 => 'Canon RF 35mm F1.8 Macro IS STM or other Canon RF Lens', #IB + 61182.1 => 'Canon RF 50mm F1.2 L USM', #IB + 61182.2 => 'Canon RF 24-105mm F4 L IS USM', #IB + 61182.3 => 'Canon RF 28-70mm F2 L USM', #IB + 65535 => 'n/a', +); + +# Canon model ID numbers (PH) +%canonModelID = ( + 0x1010000 => 'PowerShot A30', + 0x1040000 => 'PowerShot S300 / Digital IXUS 300 / IXY Digital 300', + 0x1060000 => 'PowerShot A20', + 0x1080000 => 'PowerShot A10', + 0x1090000 => 'PowerShot S110 / Digital IXUS v / IXY Digital 200', + 0x1100000 => 'PowerShot G2', + 0x1110000 => 'PowerShot S40', + 0x1120000 => 'PowerShot S30', + 0x1130000 => 'PowerShot A40', + 0x1140000 => 'EOS D30', + 0x1150000 => 'PowerShot A100', + 0x1160000 => 'PowerShot S200 / Digital IXUS v2 / IXY Digital 200a', + 0x1170000 => 'PowerShot A200', + 0x1180000 => 'PowerShot S330 / Digital IXUS 330 / IXY Digital 300a', + 0x1190000 => 'PowerShot G3', + 0x1210000 => 'PowerShot S45', + 0x1230000 => 'PowerShot SD100 / Digital IXUS II / IXY Digital 30', + 0x1240000 => 'PowerShot S230 / Digital IXUS v3 / IXY Digital 320', + 0x1250000 => 'PowerShot A70', + 0x1260000 => 'PowerShot A60', + 0x1270000 => 'PowerShot S400 / Digital IXUS 400 / IXY Digital 400', + 0x1290000 => 'PowerShot G5', + 0x1300000 => 'PowerShot A300', + 0x1310000 => 'PowerShot S50', + 0x1340000 => 'PowerShot A80', + 0x1350000 => 'PowerShot SD10 / Digital IXUS i / IXY Digital L', + 0x1360000 => 'PowerShot S1 IS', + 0x1370000 => 'PowerShot Pro1', + 0x1380000 => 'PowerShot S70', + 0x1390000 => 'PowerShot S60', + 0x1400000 => 'PowerShot G6', + 0x1410000 => 'PowerShot S500 / Digital IXUS 500 / IXY Digital 500', + 0x1420000 => 'PowerShot A75', + 0x1440000 => 'PowerShot SD110 / Digital IXUS IIs / IXY Digital 30a', + 0x1450000 => 'PowerShot A400', + 0x1470000 => 'PowerShot A310', + 0x1490000 => 'PowerShot A85', + 0x1520000 => 'PowerShot S410 / Digital IXUS 430 / IXY Digital 450', + 0x1530000 => 'PowerShot A95', + 0x1540000 => 'PowerShot SD300 / Digital IXUS 40 / IXY Digital 50', + 0x1550000 => 'PowerShot SD200 / Digital IXUS 30 / IXY Digital 40', + 0x1560000 => 'PowerShot A520', + 0x1570000 => 'PowerShot A510', + 0x1590000 => 'PowerShot SD20 / Digital IXUS i5 / IXY Digital L2', + 0x1640000 => 'PowerShot S2 IS', + 0x1650000 => 'PowerShot SD430 / Digital IXUS Wireless / IXY Digital Wireless', + 0x1660000 => 'PowerShot SD500 / Digital IXUS 700 / IXY Digital 600', + 0x1668000 => 'EOS D60', + 0x1700000 => 'PowerShot SD30 / Digital IXUS i Zoom / IXY Digital L3', + 0x1740000 => 'PowerShot A430', + 0x1750000 => 'PowerShot A410', + 0x1760000 => 'PowerShot S80', + 0x1780000 => 'PowerShot A620', + 0x1790000 => 'PowerShot A610', + 0x1800000 => 'PowerShot SD630 / Digital IXUS 65 / IXY Digital 80', + 0x1810000 => 'PowerShot SD450 / Digital IXUS 55 / IXY Digital 60', + 0x1820000 => 'PowerShot TX1', + 0x1870000 => 'PowerShot SD400 / Digital IXUS 50 / IXY Digital 55', + 0x1880000 => 'PowerShot A420', + 0x1890000 => 'PowerShot SD900 / Digital IXUS 900 Ti / IXY Digital 1000', + 0x1900000 => 'PowerShot SD550 / Digital IXUS 750 / IXY Digital 700', + 0x1920000 => 'PowerShot A700', + 0x1940000 => 'PowerShot SD700 IS / Digital IXUS 800 IS / IXY Digital 800 IS', + 0x1950000 => 'PowerShot S3 IS', + 0x1960000 => 'PowerShot A540', + 0x1970000 => 'PowerShot SD600 / Digital IXUS 60 / IXY Digital 70', + 0x1980000 => 'PowerShot G7', + 0x1990000 => 'PowerShot A530', + 0x2000000 => 'PowerShot SD800 IS / Digital IXUS 850 IS / IXY Digital 900 IS', + 0x2010000 => 'PowerShot SD40 / Digital IXUS i7 / IXY Digital L4', + 0x2020000 => 'PowerShot A710 IS', + 0x2030000 => 'PowerShot A640', + 0x2040000 => 'PowerShot A630', + 0x2090000 => 'PowerShot S5 IS', + 0x2100000 => 'PowerShot A460', + 0x2120000 => 'PowerShot SD850 IS / Digital IXUS 950 IS / IXY Digital 810 IS', + 0x2130000 => 'PowerShot A570 IS', + 0x2140000 => 'PowerShot A560', + 0x2150000 => 'PowerShot SD750 / Digital IXUS 75 / IXY Digital 90', + 0x2160000 => 'PowerShot SD1000 / Digital IXUS 70 / IXY Digital 10', + 0x2180000 => 'PowerShot A550', + 0x2190000 => 'PowerShot A450', + 0x2230000 => 'PowerShot G9', + 0x2240000 => 'PowerShot A650 IS', + 0x2260000 => 'PowerShot A720 IS', + 0x2290000 => 'PowerShot SX100 IS', + 0x2300000 => 'PowerShot SD950 IS / Digital IXUS 960 IS / IXY Digital 2000 IS', + 0x2310000 => 'PowerShot SD870 IS / Digital IXUS 860 IS / IXY Digital 910 IS', + 0x2320000 => 'PowerShot SD890 IS / Digital IXUS 970 IS / IXY Digital 820 IS', + 0x2360000 => 'PowerShot SD790 IS / Digital IXUS 90 IS / IXY Digital 95 IS', + 0x2370000 => 'PowerShot SD770 IS / Digital IXUS 85 IS / IXY Digital 25 IS', + 0x2380000 => 'PowerShot A590 IS', + 0x2390000 => 'PowerShot A580', + 0x2420000 => 'PowerShot A470', + 0x2430000 => 'PowerShot SD1100 IS / Digital IXUS 80 IS / IXY Digital 20 IS', + 0x2460000 => 'PowerShot SX1 IS', + 0x2470000 => 'PowerShot SX10 IS', + 0x2480000 => 'PowerShot A1000 IS', + 0x2490000 => 'PowerShot G10', + 0x2510000 => 'PowerShot A2000 IS', + 0x2520000 => 'PowerShot SX110 IS', + 0x2530000 => 'PowerShot SD990 IS / Digital IXUS 980 IS / IXY Digital 3000 IS', + 0x2540000 => 'PowerShot SD880 IS / Digital IXUS 870 IS / IXY Digital 920 IS', + 0x2550000 => 'PowerShot E1', + 0x2560000 => 'PowerShot D10', + 0x2570000 => 'PowerShot SD960 IS / Digital IXUS 110 IS / IXY Digital 510 IS', + 0x2580000 => 'PowerShot A2100 IS', + 0x2590000 => 'PowerShot A480', + 0x2600000 => 'PowerShot SX200 IS', + 0x2610000 => 'PowerShot SD970 IS / Digital IXUS 990 IS / IXY Digital 830 IS', + 0x2620000 => 'PowerShot SD780 IS / Digital IXUS 100 IS / IXY Digital 210 IS', + 0x2630000 => 'PowerShot A1100 IS', + 0x2640000 => 'PowerShot SD1200 IS / Digital IXUS 95 IS / IXY Digital 110 IS', + 0x2700000 => 'PowerShot G11', + 0x2710000 => 'PowerShot SX120 IS', + 0x2720000 => 'PowerShot S90', + 0x2750000 => 'PowerShot SX20 IS', + 0x2760000 => 'PowerShot SD980 IS / Digital IXUS 200 IS / IXY Digital 930 IS', + 0x2770000 => 'PowerShot SD940 IS / Digital IXUS 120 IS / IXY Digital 220 IS', + 0x2800000 => 'PowerShot A495', + 0x2810000 => 'PowerShot A490', + 0x2820000 => 'PowerShot A3100/A3150 IS', # (different cameras, same ID) + 0x2830000 => 'PowerShot A3000 IS', + 0x2840000 => 'PowerShot SD1400 IS / IXUS 130 / IXY 400F', + 0x2850000 => 'PowerShot SD1300 IS / IXUS 105 / IXY 200F', + 0x2860000 => 'PowerShot SD3500 IS / IXUS 210 / IXY 10S', + 0x2870000 => 'PowerShot SX210 IS', + 0x2880000 => 'PowerShot SD4000 IS / IXUS 300 HS / IXY 30S', + 0x2890000 => 'PowerShot SD4500 IS / IXUS 1000 HS / IXY 50S', + 0x2920000 => 'PowerShot G12', + 0x2930000 => 'PowerShot SX30 IS', + 0x2940000 => 'PowerShot SX130 IS', + 0x2950000 => 'PowerShot S95', + 0x2980000 => 'PowerShot A3300 IS', + 0x2990000 => 'PowerShot A3200 IS', + 0x3000000 => 'PowerShot ELPH 500 HS / IXUS 310 HS / IXY 31S', + 0x3010000 => 'PowerShot Pro90 IS', + 0x3010001 => 'PowerShot A800', + 0x3020000 => 'PowerShot ELPH 100 HS / IXUS 115 HS / IXY 210F', + 0x3030000 => 'PowerShot SX230 HS', + 0x3040000 => 'PowerShot ELPH 300 HS / IXUS 220 HS / IXY 410F', + 0x3050000 => 'PowerShot A2200', + 0x3060000 => 'PowerShot A1200', + 0x3070000 => 'PowerShot SX220 HS', + 0x3080000 => 'PowerShot G1 X', + 0x3090000 => 'PowerShot SX150 IS', + 0x3100000 => 'PowerShot ELPH 510 HS / IXUS 1100 HS / IXY 51S', + 0x3110000 => 'PowerShot S100 (new)', + 0x3130000 => 'PowerShot SX40 HS', + 0x3120000 => 'PowerShot ELPH 310 HS / IXUS 230 HS / IXY 600F', + # the Canon page lists the IXY 32S as "Japan only", but many other + # sites list the ELPH 500 HS and IXUS 320 HS as being the same model. + # I haven't been able to find an IXUS 320 sample, and the ELPH 500 HS + # is already associated with other IXUS and IXY models - PH + 0x3140000 => 'IXY 32S', # (PowerShot ELPH 500 HS / IXUS 320 HS ??) + 0x3160000 => 'PowerShot A1300', + 0x3170000 => 'PowerShot A810', + 0x3180000 => 'PowerShot ELPH 320 HS / IXUS 240 HS / IXY 420F', + 0x3190000 => 'PowerShot ELPH 110 HS / IXUS 125 HS / IXY 220F', + 0x3200000 => 'PowerShot D20', + 0x3210000 => 'PowerShot A4000 IS', + 0x3220000 => 'PowerShot SX260 HS', + 0x3230000 => 'PowerShot SX240 HS', + 0x3240000 => 'PowerShot ELPH 530 HS / IXUS 510 HS / IXY 1', + 0x3250000 => 'PowerShot ELPH 520 HS / IXUS 500 HS / IXY 3', + 0x3260000 => 'PowerShot A3400 IS', + 0x3270000 => 'PowerShot A2400 IS', + 0x3280000 => 'PowerShot A2300', + 0x3330000 => 'PowerShot G15', #25 + 0x3340000 => 'PowerShot SX50 HS', #25/forum8196 + 0x3350000 => 'PowerShot SX160 IS', + 0x3360000 => 'PowerShot S110 (new)', + 0x3370000 => 'PowerShot SX500 IS', + 0x3380000 => 'PowerShot N', + 0x3390000 => 'IXUS 245 HS / IXY 430F', # (no PowerShot) + 0x3400000 => 'PowerShot SX280 HS', + 0x3410000 => 'PowerShot SX270 HS', + 0x3420000 => 'PowerShot A3500 IS', + 0x3430000 => 'PowerShot A2600', + 0x3440000 => 'PowerShot SX275 HS', #forum8199 + 0x3450000 => 'PowerShot A1400', + 0x3460000 => 'PowerShot ELPH 130 IS / IXUS 140 / IXY 110F', + 0x3470000 => 'PowerShot ELPH 115/120 IS / IXUS 132/135 / IXY 90F/100F', + 0x3490000 => 'PowerShot ELPH 330 HS / IXUS 255 HS / IXY 610F', + 0x3510000 => 'PowerShot A2500', + 0x3540000 => 'PowerShot G16', + 0x3550000 => 'PowerShot S120', + 0x3560000 => 'PowerShot SX170 IS', + 0x3580000 => 'PowerShot SX510 HS', + 0x3590000 => 'PowerShot S200 (new)', + 0x3600000 => 'IXY 620F', # (no PowerShot or IXUS?) + 0x3610000 => 'PowerShot N100', + 0x3640000 => 'PowerShot G1 X Mark II', + 0x3650000 => 'PowerShot D30', + 0x3660000 => 'PowerShot SX700 HS', + 0x3670000 => 'PowerShot SX600 HS', + 0x3680000 => 'PowerShot ELPH 140 IS / IXUS 150 / IXY 130', + 0x3690000 => 'PowerShot ELPH 135 / IXUS 145 / IXY 120', + 0x3700000 => 'PowerShot ELPH 340 HS / IXUS 265 HS / IXY 630', + 0x3710000 => 'PowerShot ELPH 150 IS / IXUS 155 / IXY 140', + 0x3740000 => 'EOS M3', #IB + 0x3750000 => 'PowerShot SX60 HS', #IB/NJ + 0x3760000 => 'PowerShot SX520 HS', #IB + 0x3770000 => 'PowerShot SX400 IS', + 0x3780000 => 'PowerShot G7 X', #IB + 0x3790000 => 'PowerShot N2', + 0x3800000 => 'PowerShot SX530 HS', + 0x3820000 => 'PowerShot SX710 HS', + 0x3830000 => 'PowerShot SX610 HS', + 0x3840000 => 'EOS M10', + 0x3850000 => 'PowerShot G3 X', + 0x3860000 => 'PowerShot ELPH 165 HS / IXUS 165 / IXY 160', + 0x3870000 => 'PowerShot ELPH 160 / IXUS 160', + 0x3880000 => 'PowerShot ELPH 350 HS / IXUS 275 HS / IXY 640', + 0x3890000 => 'PowerShot ELPH 170 IS / IXUS 170', + 0x3910000 => 'PowerShot SX410 IS', + 0x3930000 => 'PowerShot G9 X', + 0x3940000 => 'EOS M5', #IB + 0x3950000 => 'PowerShot G5 X', + 0x3970000 => 'PowerShot G7 X Mark II', + 0x3980000 => 'EOS M100', #42 + 0x3990000 => 'PowerShot ELPH 360 HS / IXUS 285 HS / IXY 650', + 0x4010000 => 'PowerShot SX540 HS', + 0x4020000 => 'PowerShot SX420 IS', + 0x4030000 => 'PowerShot ELPH 190 IS / IXUS 180 / IXY 190', + 0x4040000 => 'PowerShot G1', + 0x4040001 => 'IXY 180', # ?? (from Canon sample) + 0x4050000 => 'PowerShot SX720 HS', + 0x4060000 => 'PowerShot SX620 HS', + 0x4070000 => 'EOS M6', + 0x4100000 => 'PowerShot G9 X Mark II', + 0x412 => 'EOS M50 / Kiss M', # (yes, no "0000") + 0x4150000 => 'PowerShot ELPH 185 / IXUS 185 / IXY 200', + 0x4160000 => 'PowerShot SX430 IS', + 0x4170000 => 'PowerShot SX730 HS', + 0x4180000 => 'PowerShot G1 X Mark III', #IB + 0x6040000 => 'PowerShot S100 / Digital IXUS / IXY Digital', + 0x801 => 'PowerShot SX740 HS', + 0x805 => 'PowerShot SX70 HS', + +# (see http://cweb.canon.jp/e-support/faq/answer/digitalcamera/10447-1.html for PowerShot/IXUS/IXY names) + + 0x4007d673 => 'DC19/DC21/DC22', + 0x4007d674 => 'XH A1', + 0x4007d675 => 'HV10', + 0x4007d676 => 'MD130/MD140/MD150/MD160/ZR850', + 0x4007d777 => 'DC50', # (iVIS) + 0x4007d778 => 'HV20', # (iVIS) + 0x4007d779 => 'DC211', #29 + 0x4007d77a => 'HG10', + 0x4007d77b => 'HR10', #29 (iVIS) + 0x4007d77d => 'MD255/ZR950', + 0x4007d81c => 'HF11', + 0x4007d878 => 'HV30', + 0x4007d87c => 'XH A1S', + 0x4007d87e => 'DC301/DC310/DC311/DC320/DC330', + 0x4007d87f => 'FS100', + 0x4007d880 => 'HF10', #29 (iVIS/VIXIA) + 0x4007d882 => 'HG20/HG21', # (VIXIA) + 0x4007d925 => 'HF21', # (LEGRIA) + 0x4007d926 => 'HF S11', # (LEGRIA) + 0x4007d978 => 'HV40', # (LEGRIA) + 0x4007d987 => 'DC410/DC411/DC420', + 0x4007d988 => 'FS19/FS20/FS21/FS22/FS200', # (LEGRIA) + 0x4007d989 => 'HF20/HF200', # (LEGRIA) + 0x4007d98a => 'HF S10/S100', # (LEGRIA/VIXIA) + 0x4007da8e => 'HF R10/R16/R17/R18/R100/R106', # (LEGRIA/VIXIA) + 0x4007da8f => 'HF M30/M31/M36/M300/M306', # (LEGRIA/VIXIA) + 0x4007da90 => 'HF S20/S21/S200', # (LEGRIA/VIXIA) + 0x4007da92 => 'FS31/FS36/FS37/FS300/FS305/FS306/FS307', + 0x4007dca0 => 'EOS C300', + 0x4007dda9 => 'HF G25', # (LEGRIA) + 0x4007dfb4 => 'XC10', + 0x4007e1c3 => 'EOS C200', + + # NOTE: some pre-production models may have a model name of + # "Canon EOS Kxxx", where "xxx" is the last 3 digits of the model ID below. + # This has been observed for the 1DSmkIII/K215 and 400D/K236. + 0x80000001 => 'EOS-1D', + 0x80000167 => 'EOS-1DS', + 0x80000168 => 'EOS 10D', + 0x80000169 => 'EOS-1D Mark III', + 0x80000170 => 'EOS Digital Rebel / 300D / Kiss Digital', + 0x80000174 => 'EOS-1D Mark II', + 0x80000175 => 'EOS 20D', + 0x80000176 => 'EOS Digital Rebel XSi / 450D / Kiss X2', + 0x80000188 => 'EOS-1Ds Mark II', + 0x80000189 => 'EOS Digital Rebel XT / 350D / Kiss Digital N', + 0x80000190 => 'EOS 40D', + 0x80000213 => 'EOS 5D', + 0x80000215 => 'EOS-1Ds Mark III', + 0x80000218 => 'EOS 5D Mark II', + 0x80000219 => 'WFT-E1', + 0x80000232 => 'EOS-1D Mark II N', + 0x80000234 => 'EOS 30D', + 0x80000236 => 'EOS Digital Rebel XTi / 400D / Kiss Digital X', + 0x80000241 => 'WFT-E2', + 0x80000246 => 'WFT-E3', + 0x80000250 => 'EOS 7D', + 0x80000252 => 'EOS Rebel T1i / 500D / Kiss X3', + 0x80000254 => 'EOS Rebel XS / 1000D / Kiss F', + 0x80000261 => 'EOS 50D', + 0x80000269 => 'EOS-1D X', + 0x80000270 => 'EOS Rebel T2i / 550D / Kiss X4', + 0x80000271 => 'WFT-E4', + 0x80000273 => 'WFT-E5', + 0x80000281 => 'EOS-1D Mark IV', + 0x80000285 => 'EOS 5D Mark III', + 0x80000286 => 'EOS Rebel T3i / 600D / Kiss X5', + 0x80000287 => 'EOS 60D', + 0x80000288 => 'EOS Rebel T3 / 1100D / Kiss X50', + 0x80000289 => 'EOS 7D Mark II', #IB + 0x80000297 => 'WFT-E2 II', + 0x80000298 => 'WFT-E4 II', + 0x80000301 => 'EOS Rebel T4i / 650D / Kiss X6i', + 0x80000302 => 'EOS 6D', #25 + 0x80000324 => 'EOS-1D C', #(NC) + 0x80000325 => 'EOS 70D', + 0x80000326 => 'EOS Rebel T5i / 700D / Kiss X7i', + 0x80000327 => 'EOS Rebel T5 / 1200D / Kiss X70 / Hi', + 0x80000328 => 'EOS-1D X MARK II', #42 + 0x80000331 => 'EOS M', + 0x80000350 => 'EOS 80D', #42 + 0x80000355 => 'EOS M2', + 0x80000346 => 'EOS Rebel SL1 / 100D / Kiss X7', + 0x80000347 => 'EOS Rebel T6s / 760D / 8000D', + 0x80000349 => 'EOS 5D Mark IV', #42 + 0x80000382 => 'EOS 5DS', + 0x80000393 => 'EOS Rebel T6i / 750D / Kiss X8i', + 0x80000401 => 'EOS 5DS R', + 0x80000404 => 'EOS Rebel T6 / 1300D / Kiss X80', + 0x80000405 => 'EOS Rebel T7i / 800D / Kiss X9i', + 0x80000406 => 'EOS 6D Mark II', #IB/42 + 0x80000408 => 'EOS 77D / 9000D', + 0x80000417 => 'EOS Rebel SL2 / 200D / Kiss X9', #IB/42 + 0x80000422 => 'EOS Rebel T100 / 4000D / 3000D', #IB (3000D in China; Kiss? - PH) + 0x80000424 => 'EOR R', #IB + 0x80000432 => 'EOS Rebel T7 / 2000D / 1500D / Kiss X90', #IB + 0x80000433 => 'EOS RP', +); + +my %canonQuality = ( + -1 => 'n/a', # (PH, EOS M MOV video) + 1 => 'Economy', + 2 => 'Normal', + 3 => 'Fine', + 4 => 'RAW', + 5 => 'Superfine', + 7 => 'CRAW', #42 + 130 => 'Normal Movie', #22 + 131 => 'Movie (2)', #PH (7DmkII 1920x1080) +); +my %canonImageSize = ( + -1 => 'n/a', + 0 => 'Large', + 1 => 'Medium', + 2 => 'Small', + 5 => 'Medium 1', #PH + 6 => 'Medium 2', #PH + 7 => 'Medium 3', #PH + 8 => 'Postcard', #PH (SD200 1600x1200 with DateStamp option) + 9 => 'Widescreen', #PH (SD900 3648x2048), 22 (HFS200 3264x1840) + 10 => 'Medium Widescreen', #22 (HFS200 1920x1080) + 14 => 'Small 1', #PH + 15 => 'Small 2', #PH + 16 => 'Small 3', #PH + 128 => '640x480 Movie', #PH (7D 60fps) + 129 => 'Medium Movie', #22 + 130 => 'Small Movie', #22 + 137 => '1280x720 Movie', #PH (S95 24fps; D60 50fps) + 142 => '1920x1080 Movie', #PH (D60 25fps) + 143 => '4096x2160 Movie', #PH (C200) +); +my %canonWhiteBalance = ( + # -1='Click", -2='Pasted' ?? - PH + 0 => 'Auto', + 1 => 'Daylight', + 2 => 'Cloudy', + 3 => 'Tungsten', + 4 => 'Fluorescent', + 5 => 'Flash', + 6 => 'Custom', + 7 => 'Black & White', + 8 => 'Shade', + 9 => 'Manual Temperature (Kelvin)', + 10 => 'PC Set1', #PH + 11 => 'PC Set2', #PH + 12 => 'PC Set3', #PH + 14 => 'Daylight Fluorescent', #3 + 15 => 'Custom 1', #PH + 16 => 'Custom 2', #PH + 17 => 'Underwater', #3 + 18 => 'Custom 3', #PH + 19 => 'Custom 4', #PH + 20 => 'PC Set4', #PH + 21 => 'PC Set5', #PH + # 22 - Custom 2? + 23 => 'Auto (ambience priority)', #PH (5DS) + # 30 - Click White Balance? + # 31 - Shot Settings? + # 137 - Tungsten? + # 138 - White Fluorescent? + # 139 - Fluorescent H? + # 140 - Manual? +); + +# picture styles used by the 5D +# (styles 0x4X may be downloaded from Canon) +# (called "ColorMatrix" in 1D owner manual) +my %pictureStyles = ( #12 + 0x00 => 'None', #PH + 0x01 => 'Standard', #15 + 0x02 => 'Portrait', #15 + 0x03 => 'High Saturation', #15 + 0x04 => 'Adobe RGB', #15 + 0x05 => 'Low Saturation', #15 + 0x06 => 'CM Set 1', #PH + 0x07 => 'CM Set 2', #PH + # "ColorMatrix" values end here + 0x21 => 'User Def. 1', + 0x22 => 'User Def. 2', + 0x23 => 'User Def. 3', + # "External" styles currently available from Canon are Nostalgia, Clear, + # Twilight and Emerald. The "User Def" styles change to these "External" + # codes when these styles are installed in the camera + 0x41 => 'PC 1', #PH + 0x42 => 'PC 2', #PH + 0x43 => 'PC 3', #PH + 0x81 => 'Standard', + 0x82 => 'Portrait', + 0x83 => 'Landscape', + 0x84 => 'Neutral', + 0x85 => 'Faithful', + 0x86 => 'Monochrome', + 0x87 => 'Auto', #PH + 0x88 => 'Fine Detail', #PH + 0xff => 'n/a', #PH (guess) + 0xffff => 'n/a', #PH (guess) +); +my %userDefStyles = ( #12/48 + Notes => q{ + Base style for user-defined picture styles. PC values represent external + picture styles which may be downloaded from Canon and installed in the + camera. + }, + 0x41 => 'PC 1', + 0x42 => 'PC 2', + 0x43 => 'PC 3', + 0x81 => 'Standard', + 0x82 => 'Portrait', + 0x83 => 'Landscape', + 0x84 => 'Neutral', + 0x85 => 'Faithful', + 0x86 => 'Monochrome', + 0x87 => 'Auto', #PH +); + +# picture style tag information for CameraInfo550D +my %psConv = ( + -559038737 => 'n/a', # = 0xdeadbeef ! LOL + OTHER => sub { shift }, +); +my %psInfo = ( + Format => 'int32s', + PrintHex => 1, + PrintConv => \%psConv, +); + +# ValueConv that makes long values binary type +my %longBin = ( + ValueConv => 'length($val) > 64 ? \$val : $val', + ValueConvInv => '$val', +); + +# conversions, etc for CameraColorCalibration tags +my %cameraColorCalibration = ( + Format => 'int16s[4]', + Unknown => 1, + PrintConv => 'sprintf("%4d %4d %4d (%dK)", split(" ",$val))', + PrintConvInv => '$val=~s/\s+/ /g; $val=~tr/()K//d; $val', +); + +# conversions, etc for PowerShot CameraColorCalibration tags +my %cameraColorCalibration2 = ( + Format => 'int16s[5]', + Unknown => 1, + PrintConv => 'sprintf("%4d %4d %4d %4d (%dK)", split(" ",$val))', + PrintConvInv => '$val=~s/\s+/ /g; $val=~tr/()K//d; $val', +); +# conversions, etc for byte-swapped FocusDistance tags +my %focusDistanceByteSwap = ( + # this is very odd (little-endian number on odd boundary), + # but it does seem to work better with my sample images - PH + Format => 'int16uRev', + ValueConv => '$val / 100', + ValueConvInv => '$val * 100', + PrintConv => '$val > 655.345 ? "inf" : "$val m"', + PrintConvInv => '$val =~ s/ ?m$//; IsFloat($val) ? $val : 655.35', +); + +# common attributes for writable BinaryData directories +my %binaryDataAttrs = ( + PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData, + WRITE_PROC => \&Image::ExifTool::WriteBinaryData, + CHECK_PROC => \&Image::ExifTool::CheckBinaryData, + WRITABLE => 1, +); + +my %offOn = ( 0 => 'Off', 1 => 'On' ); + +#------------------------------------------------------------------------------ +# Canon EXIF Maker Notes +%Image::ExifTool::Canon::Main = ( + WRITE_PROC => \&WriteCanon, + CHECK_PROC => \&Image::ExifTool::Exif::CheckExif, + GROUPS => { 0 => 'MakerNotes', 2 => 'Camera' }, + 0x1 => { + Name => 'CanonCameraSettings', + SubDirectory => { + Validate => 'Image::ExifTool::Canon::Validate($dirData,$subdirStart,$size)', + TagTable => 'Image::ExifTool::Canon::CameraSettings', + }, + }, + 0x2 => { + Name => 'CanonFocalLength', + SubDirectory => { TagTable => 'Image::ExifTool::Canon::FocalLength' }, + }, + 0x3 => { + Name => 'CanonFlashInfo', + Unknown => 1, + }, + 0x4 => { + Name => 'CanonShotInfo', + SubDirectory => { + Validate => 'Image::ExifTool::Canon::Validate($dirData,$subdirStart,$size)', + TagTable => 'Image::ExifTool::Canon::ShotInfo', + }, + }, + 0x5 => { + Name => 'CanonPanorama', + SubDirectory => { TagTable => 'Image::ExifTool::Canon::Panorama' }, + }, + 0x6 => { + Name => 'CanonImageType', + Writable => 'string', + Groups => { 2 => 'Image' }, + }, + 0x7 => { + Name => 'CanonFirmwareVersion', + Writable => 'string', + }, + 0x8 => { + Name => 'FileNumber', + Writable => 'int32u', + Groups => { 2 => 'Image' }, + PrintConv => '$_=$val,s/(\d+)(\d{4})/$1-$2/,$_', + PrintConvInv => '$val=~s/-//g;$val', + }, + 0x9 => { + Name => 'OwnerName', + Writable => 'string', + # pad to 32 bytes (including null terminator which will be added) + # to avoid bug which crashes DPP if length is 4 bytes + ValueConvInv => '$val .= "\0" x (31 - length $val) if length $val < 31; $val', + }, + 0xa => { + Name => 'UnknownD30', + SubDirectory => { + Validate => 'Image::ExifTool::Canon::Validate($dirData,$subdirStart,$size)', + TagTable => 'Image::ExifTool::Canon::UnknownD30', + }, + }, + 0xc => [ # square brackets for a conditional list + { + # D30 + Name => 'SerialNumber', + Condition => '$$self{Model} =~ /EOS D30\b/', + Writable => 'int32u', + PrintConv => 'sprintf("%.4x%.5d",$val>>16,$val&0xffff)', + PrintConvInv => '$val=~/(.*)-?(\d{5})$/ ? (hex($1)<<16)+$2 : undef', + }, + { + # serial number of 1D/1Ds/1D Mark II/1Ds Mark II is usually + # displayed w/o leeding zeros (ref 7) (1D uses 6 digits - PH) + Name => 'SerialNumber', + Condition => '$$self{Model} =~ /EOS-1D/', + Writable => 'int32u', + PrintConv => 'sprintf("%.6u",$val)', + PrintConvInv => '$val', + }, + { + # all other models (D60,300D,350D,REBEL,10D,20D,etc) + Name => 'SerialNumber', + Writable => 'int32u', + PrintConv => 'sprintf("%.10u",$val)', + PrintConvInv => '$val', + }, + ], + 0xd => [ + { + Name => 'CanonCameraInfo1D', + # (save size of this record as "CameraInfoCount" for later tests) + Condition => '($$self{CameraInfoCount} = $count) and $$self{Model} =~ /\b1DS?$/', + SubDirectory => { TagTable => 'Image::ExifTool::Canon::CameraInfo1D' }, + }, + { + Name => 'CanonCameraInfo1DmkII', + Condition => '$$self{Model} =~ /\b1Ds? Mark II$/', + SubDirectory => { TagTable => 'Image::ExifTool::Canon::CameraInfo1DmkII' }, + }, + { + Name => 'CanonCameraInfo1DmkIIN', + Condition => '$$self{Model} =~ /\b1Ds? Mark II N$/', + SubDirectory => { TagTable => 'Image::ExifTool::Canon::CameraInfo1DmkIIN' }, + }, + { + Name => 'CanonCameraInfo1DmkIII', + Condition => '$$self{Model} =~ /\b1Ds? Mark III$/', + SubDirectory => { TagTable => 'Image::ExifTool::Canon::CameraInfo1DmkIII' }, + }, + { + Name => 'CanonCameraInfo1DmkIV', + Condition => '$$self{Model} =~ /\b1D Mark IV$/', + SubDirectory => { TagTable => 'Image::ExifTool::Canon::CameraInfo1DmkIV' }, + }, + { + Name => 'CanonCameraInfo1DX', + Condition => '$$self{Model} =~ /EOS-1D X$/', + SubDirectory => { TagTable => 'Image::ExifTool::Canon::CameraInfo1DX' }, + }, + { + Name => 'CanonCameraInfo5D', + Condition => '$$self{Model} =~ /EOS 5D$/', + SubDirectory => { TagTable => 'Image::ExifTool::Canon::CameraInfo5D' }, + }, + { + Name => 'CanonCameraInfo5DmkII', + Condition => '$$self{Model} =~ /EOS 5D Mark II$/', + SubDirectory => { TagTable => 'Image::ExifTool::Canon::CameraInfo5DmkII' }, + }, + { + Name => 'CanonCameraInfo5DmkIII', + Condition => '$$self{Model} =~ /EOS 5D Mark III$/', + SubDirectory => { TagTable => 'Image::ExifTool::Canon::CameraInfo5DmkIII' }, + }, + { + Name => 'CanonCameraInfo6D', + Condition => '$$self{Model} =~ /EOS 6D$/', + SubDirectory => { TagTable => 'Image::ExifTool::Canon::CameraInfo6D' }, + }, + { + Name => 'CanonCameraInfo7D', + Condition => '$$self{Model} =~ /EOS 7D$/', + SubDirectory => { TagTable => 'Image::ExifTool::Canon::CameraInfo7D' }, + }, + { + Name => 'CanonCameraInfo40D', + Condition => '$$self{Model} =~ /EOS 40D$/', + SubDirectory => { TagTable => 'Image::ExifTool::Canon::CameraInfo40D' }, + }, + { + Name => 'CanonCameraInfo50D', + Condition => '$$self{Model} =~ /EOS 50D$/', + SubDirectory => { TagTable => 'Image::ExifTool::Canon::CameraInfo50D' }, + }, + { + Name => 'CanonCameraInfo60D', + Condition => '$$self{Model} =~ /EOS 60D$/', + SubDirectory => { TagTable => 'Image::ExifTool::Canon::CameraInfo60D' }, + }, + { + Name => 'CanonCameraInfo70D', + Condition => '$$self{Model} =~ /EOS 70D$/', + SubDirectory => { TagTable => 'Image::ExifTool::Canon::CameraInfo70D' }, + }, + { + Name => 'CanonCameraInfo80D', + Condition => '$$self{Model} =~ /EOS 80D$/', + SubDirectory => { TagTable => 'Image::ExifTool::Canon::CameraInfo80D' }, + }, + { + Name => 'CanonCameraInfo450D', + Condition => '$$self{Model} =~ /\b(450D|REBEL XSi|Kiss X2)\b/', + SubDirectory => { TagTable => 'Image::ExifTool::Canon::CameraInfo450D' }, + }, + { + Name => 'CanonCameraInfo500D', + Condition => '$$self{Model} =~ /\b(500D|REBEL T1i|Kiss X3)\b/', + SubDirectory => { TagTable => 'Image::ExifTool::Canon::CameraInfo500D' }, + }, + { + Name => 'CanonCameraInfo550D', + Condition => '$$self{Model} =~ /\b(550D|REBEL T2i|Kiss X4)\b/', + SubDirectory => { TagTable => 'Image::ExifTool::Canon::CameraInfo550D' }, + }, + { + Name => 'CanonCameraInfo600D', + Condition => '$$self{Model} =~ /\b(600D|REBEL T3i|Kiss X5)\b/', + SubDirectory => { TagTable => 'Image::ExifTool::Canon::CameraInfo600D' }, + }, + { + Name => 'CanonCameraInfo650D', + Condition => '$$self{Model} =~ /\b(650D|REBEL T4i|Kiss X6i)\b/', + SubDirectory => { TagTable => 'Image::ExifTool::Canon::CameraInfo650D' }, + }, + { + Name => 'CanonCameraInfo700D', + Condition => '$$self{Model} =~ /\b(700D|REBEL T5i|Kiss X7i)\b/', + SubDirectory => { TagTable => 'Image::ExifTool::Canon::CameraInfo650D' }, + }, + { + Name => 'CanonCameraInfo750D', + Condition => '$$self{Model} =~ /\b(750D|Rebel T6i|Kiss X8i)\b/', + SubDirectory => { TagTable => 'Image::ExifTool::Canon::CameraInfo750D' }, + }, + { + Name => 'CanonCameraInfo760D', + Condition => '$$self{Model} =~ /\b(760D|Rebel T6s|8000D)\b/', + SubDirectory => { TagTable => 'Image::ExifTool::Canon::CameraInfo750D' }, + }, + { + Name => 'CanonCameraInfo1000D', + Condition => '$$self{Model} =~ /\b(1000D|REBEL XS|Kiss F)\b/', + SubDirectory => { TagTable => 'Image::ExifTool::Canon::CameraInfo1000D' }, + }, + { + Name => 'CanonCameraInfo1100D', + Condition => '$$self{Model} =~ /\b(1100D|REBEL T3|Kiss X50)\b/', + SubDirectory => { TagTable => 'Image::ExifTool::Canon::CameraInfo600D' }, + }, + { + Name => 'CanonCameraInfo1200D', + Condition => '$$self{Model} =~ /\b(1200D|REBEL T5|Kiss X70)\b/', + SubDirectory => { TagTable => 'Image::ExifTool::Canon::CameraInfo60D' }, + }, + { + Name => 'CanonCameraInfoPowerShot', + # valid if format is int32u[138] or int32u[148] + Condition => '$format eq "int32u" and ($count == 138 or $count == 148)', + SubDirectory => { TagTable => 'Image::ExifTool::Canon::CameraInfoPowerShot' }, + }, + { + Name => 'CanonCameraInfoPowerShot2', + # valid if format is int32u[162], int32u[167], int32u[171] or int32u[264] + Condition => q{ + $format eq "int32u" and ($count == 156 or $count == 162 or + $count == 167 or $count == 171 or $count == 264) + }, + SubDirectory => { TagTable => 'Image::ExifTool::Canon::CameraInfoPowerShot2' }, + }, + { + Name => 'CanonCameraInfoUnknown32', + Condition => '$format =~ /^int32/', + # (counts of 72, 85, 86, 93, 94, 96, 104) - PH + SubDirectory => { TagTable => 'Image::ExifTool::Canon::CameraInfoUnknown32' }, + }, + { + Name => 'CanonCameraInfoUnknown16', + Condition => '$format =~ /^int16/', + SubDirectory => { TagTable => 'Image::ExifTool::Canon::CameraInfoUnknown16' }, + }, + { + Name => 'CanonCameraInfoUnknown', + SubDirectory => { TagTable => 'Image::ExifTool::Canon::CameraInfoUnknown' }, + }, + ], + 0xe => { + Name => 'CanonFileLength', + Writable => 'int32u', + Groups => { 2 => 'Image' }, + }, + 0xf => [ + { # used by 1DmkII, 1DSmkII and 1DmkIIN + Name => 'CustomFunctions1D', + Condition => '$$self{Model} =~ /EOS-1D/', + SubDirectory => { + Validate => 'Image::ExifTool::Canon::Validate($dirData,$subdirStart,$size)', + TagTable => 'Image::ExifTool::CanonCustom::Functions1D', + }, + }, + { + Name => 'CustomFunctions5D', + Condition => '$$self{Model} =~ /EOS 5D/', + SubDirectory => { + Validate => 'Image::ExifTool::Canon::Validate($dirData,$subdirStart,$size)', + TagTable => 'Image::ExifTool::CanonCustom::Functions5D', + }, + }, + { + Name => 'CustomFunctions10D', + Condition => '$$self{Model} =~ /EOS 10D/', + SubDirectory => { + Validate => 'Image::ExifTool::Canon::Validate($dirData,$subdirStart,$size)', + TagTable => 'Image::ExifTool::CanonCustom::Functions10D', + }, + }, + { + Name => 'CustomFunctions20D', + Condition => '$$self{Model} =~ /EOS 20D/', + SubDirectory => { + Validate => 'Image::ExifTool::Canon::Validate($dirData,$subdirStart,$size)', + TagTable => 'Image::ExifTool::CanonCustom::Functions20D', + }, + }, + { + Name => 'CustomFunctions30D', + Condition => '$$self{Model} =~ /EOS 30D/', + SubDirectory => { + Validate => 'Image::ExifTool::Canon::Validate($dirData,$subdirStart,$size)', + TagTable => 'Image::ExifTool::CanonCustom::Functions30D', + }, + }, + { + Name => 'CustomFunctions350D', + Condition => '$$self{Model} =~ /\b(350D|REBEL XT|Kiss Digital N)\b/', + SubDirectory => { + Validate => 'Image::ExifTool::Canon::Validate($dirData,$subdirStart,$size)', + TagTable => 'Image::ExifTool::CanonCustom::Functions350D', + }, + }, + { + Name => 'CustomFunctions400D', + Condition => '$$self{Model} =~ /\b(400D|REBEL XTi|Kiss Digital X|K236)\b/', + SubDirectory => { + Validate => 'Image::ExifTool::Canon::Validate($dirData,$subdirStart,$size)', + TagTable => 'Image::ExifTool::CanonCustom::Functions400D', + }, + }, + { + Name => 'CustomFunctionsD30', + Condition => '$$self{Model} =~ /EOS D30\b/', + SubDirectory => { + Validate => 'Image::ExifTool::Canon::Validate($dirData,$subdirStart,$size)', + TagTable => 'Image::ExifTool::CanonCustom::FunctionsD30', + }, + }, + { + Name => 'CustomFunctionsD60', + Condition => '$$self{Model} =~ /EOS D60\b/', + SubDirectory => { + # the stored size in the D60 apparently doesn't include the size word: + Validate => 'Image::ExifTool::Canon::Validate($dirData,$subdirStart,$size-2,$size)', + # (D60 custom functions are basically the same as D30) + TagTable => 'Image::ExifTool::CanonCustom::FunctionsD30', + }, + }, + { + Name => 'CustomFunctionsUnknown', + SubDirectory => { + Validate => 'Image::ExifTool::Canon::Validate($dirData,$subdirStart,$size)', + TagTable => 'Image::ExifTool::CanonCustom::FuncsUnknown', + }, + }, + ], + 0x10 => { #PH + Name => 'CanonModelID', + Writable => 'int32u', + PrintHex => 1, + SeparateTable => 1, + PrintConv => \%canonModelID, + }, + 0x11 => { #PH + Name => 'MovieInfo', + SubDirectory => { + Validate => 'Image::ExifTool::Canon::Validate($dirData,$subdirStart,$size)', + TagTable => 'Image::ExifTool::Canon::MovieInfo', + }, + }, + 0x12 => { + Name => 'CanonAFInfo', + # not really a condition -- just need to store the count for later + Condition => '$$self{AFInfoCount} = $count', + SubDirectory => { + # this record does not begin with a length word, so it + # has to be validated differently + Validate => 'Image::ExifTool::Canon::ValidateAFInfo($dirData,$subdirStart,$size)', + TagTable => 'Image::ExifTool::Canon::AFInfo', + }, + }, + 0x13 => { #PH + Name => 'ThumbnailImageValidArea', + # left,right,top,bottom edges of image in thumbnail, or all zeros for full frame + Notes => 'all zeros for full frame', + Writable => 'int16u', + Count => 4, + }, + 0x15 => { #PH + # display format for serial number + Name => 'SerialNumberFormat', + Writable => 'int32u', + PrintHex => 1, + PrintConv => { + 0x90000000 => 'Format 1', + 0xa0000000 => 'Format 2', + }, + }, + 0x1a => { #15 + Name => 'SuperMacro', + Writable => 'int16u', + PrintConv => { + 0 => 'Off', + 1 => 'On (1)', + 2 => 'On (2)', + }, + }, + 0x1c => { #PH (A570IS) + Name => 'DateStampMode', + Writable => 'int16u', + Notes => 'used only in postcard mode', + PrintConv => { + 0 => 'Off', + 1 => 'Date', + 2 => 'Date & Time', + }, + }, + 0x1d => { #PH + Name => 'MyColors', + SubDirectory => { + Validate => 'Image::ExifTool::Canon::Validate($dirData,$subdirStart,$size)', + TagTable => 'Image::ExifTool::Canon::MyColors', + }, + }, + 0x1e => { #PH + Name => 'FirmwareRevision', + Writable => 'int32u', + # as a hex number: 0xAVVVRR00, where (a bit of guessing here...) + # A = 'a' for alpha, 'b' for beta? + # V = version? (100,101 for normal releases, 100,110,120,130,170 for alpha/beta) + # R = revision? (01-07, except 00 for alpha/beta releases) + PrintConv => q{ + my $rev = sprintf("%.8x", $val); + my ($rel, $v1, $v2, $r1, $r2) = ($rev =~ /^(.)(.)(..)0?(.+)(..)$/); + my %r = ( a => 'Alpha ', b => 'Beta ', '0' => '' ); + $rel = defined $r{$rel} ? $r{$rel} : "Unknown($rel) "; + return "$rel$v1.$v2 rev $r1.$r2", + }, + PrintConvInv => q{ + $_=$val; s/Alpha ?/a/i; s/Beta ?/b/i; + s/Unknown ?\((.)\)/$1/i; s/ ?rev ?(.)\./0$1/; s/ ?rev ?//; + tr/a-fA-F0-9//dc; return hex $_; + }, + }, + # 0x1f - used for red-eye-corrected images - PH (A570IS) + # 0x22 - values 1 and 2 are 2 and 1 for flash pics, 0 otherwise - PH (A570IS) + 0x23 => { #31 + Name => 'Categories', + Writable => 'int32u', + Format => 'int32u', # (necessary to perform conversion for Condition) + Notes => '2 values: 1. always 8, 2. Categories', + Count => '2', + Condition => '$$valPt =~ /^\x08\0\0\0/', + ValueConv => '$val =~ s/^8 //; $val', + ValueConvInv => '"8 $val"', + PrintConvColumns => 2, + PrintConv => { + 0 => '(none)', + BITMASK => { + 0 => 'People', + 1 => 'Scenery', + 2 => 'Events', + 3 => 'User 1', + 4 => 'User 2', + 5 => 'User 3', + 6 => 'To Do', + }, + }, + }, + 0x24 => { #PH + Name => 'FaceDetect1', + SubDirectory => { + Validate => 'Image::ExifTool::Canon::Validate($dirData,$subdirStart,$size)', + TagTable => 'Image::ExifTool::Canon::FaceDetect1', + }, + }, + 0x25 => { #PH + Name => 'FaceDetect2', + SubDirectory => { + TagTable => 'Image::ExifTool::Canon::FaceDetect2', + # (can't validate because this record uses a 1-byte count instead of a 2-byte count) + }, + }, + 0x26 => { #PH (A570IS,1DmkIII) + Name => 'CanonAFInfo2', + Condition => '$$valPt !~ /^\0\0\0\0/', # (data may be all zeros in thumbnail of 60D MOV video) + SubDirectory => { + Validate => 'Image::ExifTool::Canon::Validate($dirData,$subdirStart,$size)', + TagTable => 'Image::ExifTool::Canon::AFInfo2', + }, + }, + 0x27 => { #PH + Name => 'ContrastInfo', + Condition => '$$valPt =~ /^\x0a\0/', # (seems to be various versions of this information) + SubDirectory => { TagTable => 'Image::ExifTool::Canon::ContrastInfo' }, + }, + # 0x27 - value 1 is 1 for high ISO pictures, 0 otherwise + # value 4 is 9 for Flexizone and FaceDetect AF, 1 for Centre AF, 0 otherwise (SX10IS) + 0x28 => { #JD + # bytes 0-1=sequence number (encrypted), 2-5=date/time (encrypted) (ref JD) + Name => 'ImageUniqueID', + Format => 'undef', + Writable => 'int8u', + Groups => { 2 => 'Image' }, + RawConv => '$val eq "\0" x 16 ? undef : $val', + ValueConv => 'unpack("H*", $val)', + ValueConvInv => 'pack("H*", $val)', + }, + # 0x29 - WBInfo (ref IB, offset 0x6 is int32u[4] WB_GRBGLevels as shot for PowerShot G9) + # 0x2d - changes with categories (ref 31) + 0x2f => { #PH (G12) + Name => 'FaceDetect3', + SubDirectory => { + Validate => 'Image::ExifTool::Canon::Validate($dirData,$subdirStart,$size)', + TagTable => 'Image::ExifTool::Canon::FaceDetect3', + }, + }, + 0x35 => { #PH + Name => 'TimeInfo', + SubDirectory => { + Validate => 'Image::ExifTool::Canon::Validate($dirData,$subdirStart,$size)', + TagTable => 'Image::ExifTool::Canon::TimeInfo', + }, + }, + 0x38 => { #PH + Name => 'BatteryType', + Writable => 'undef', + Condition => '$count == 76', + RawConv => '$val=~/^.{4}([^\0]+)/s ? $1 : undef', + RawConvInv => 'substr("\x4c\0\0\0".$val.("\0"x72), 0, 76)', + }, + 0x3c => { #PH (G1XmkII) + Name => 'AFInfo3', + Condition => '$$self{AFInfo3} = 1', + SubDirectory => { + Validate => 'Image::ExifTool::Canon::Validate($dirData,$subdirStart,$size)', + TagTable => 'Image::ExifTool::Canon::AFInfo2', + }, + }, + # 0x44 (ShootInfo) + # 0x62 (UserSetting) + 0x81 => { #13 + Name => 'RawDataOffset', + # (can't yet write 1D raw files) + # Writable => 'int32u', + # Protected => 2, + }, + 0x83 => { #PH + Name => 'OriginalDecisionDataOffset', + Writable => 'int32u', + OffsetPair => 1, # (just used as a flag, since this tag has no pair) + # this is an offset to the original decision data block + # (offset relative to start of file in JPEG images, but NOT DNG images!) + IsOffset => '$val and $$et{FILE_TYPE} ne "JPEG"', + Protected => 2, + DataTag => 'OriginalDecisionData', + }, + 0x90 => { # used by 1D and 1Ds + Name => 'CustomFunctions1D', + SubDirectory => { + Validate => 'Image::ExifTool::Canon::Validate($dirData,$subdirStart,$size)', + TagTable => 'Image::ExifTool::CanonCustom::Functions1D', + }, + }, + 0x91 => { #PH + Name => 'PersonalFunctions', + SubDirectory => { + Validate => 'Image::ExifTool::Canon::Validate($dirData,$subdirStart,$size)', + TagTable => 'Image::ExifTool::CanonCustom::PersonalFuncs', + }, + }, + 0x92 => { #PH + Name => 'PersonalFunctionValues', + SubDirectory => { + Validate => 'Image::ExifTool::Canon::Validate($dirData,$subdirStart,$size)', + TagTable => 'Image::ExifTool::CanonCustom::PersonalFuncValues', + }, + }, + 0x93 => { + Name => 'CanonFileInfo', # (ShootInfoEx) + SubDirectory => { + Validate => 'Image::ExifTool::Canon::Validate($dirData,$subdirStart,$size)', + TagTable => 'Image::ExifTool::Canon::FileInfo', + }, + }, + 0x94 => { #PH + # AF points for 1D (45 points in 5 rows) + Name => 'AFPointsInFocus1D', + Notes => 'EOS 1D -- 5 rows: A1-7, B1-10, C1-11, D1-10, E1-7, center point is C6', + PrintConv => 'Image::ExifTool::Canon::PrintAFPoints1D($val)', + }, + 0x95 => { #PH (observed in 5D sample image) + Name => 'LensModel', # (LensName) + Writable => 'string', + }, + 0x96 => [ #PH (CMOSNumber) + { + Name => 'SerialInfo', + Condition => '$$self{Model} =~ /EOS 5D/', + SubDirectory => { TagTable => 'Image::ExifTool::Canon::SerialInfo' }, + }, + { + Name => 'InternalSerialNumber', + Writable => 'string', + # remove trailing 0xff's if they exist (Kiss X3) + ValueConv => '$val=~s/\xff+$//; $val', + ValueConvInv => '$val', + }, + ], + 0x97 => { #PH (also see http://www.freepatentsonline.com/7657116.html) + Name => 'DustRemovalData', # (DustDeleteData) + Writable => 'undef', + Flags => [ 'Binary', 'Protected' ], + # 0x00: int8u - Version (0 or 1) + # 0x01: int8u - LensInfo ? (1) + # 0x02: int8u - AVValue ? (int8u for version 0, int16u for version 1) + # 0x03: int8u - POValue ? (int8u for version 0, int16u for version 1) + # 0x04: int16u - DustCount + # 0x06: int16u - FocalLength ? + # 0x08: int16u - LensID ? + # 0x0a: int16u - Width + # 0x0c: int16u - Height + # 0x0e: int16u - RAW_Width + # 0x10: int16u - RAW_Height + # 0x12: int16u - PixelPitch [um * 1000] + # 0x14: int16u - LpfDistance [mm * 1000] + # 0x16: int8u - TopOffset + # 0x17: int8u - BottomOffset + # 0x18: int8u - LeftOffset + # 0x19: int8u - RightOffset + # 0x1a: int8u - Year [-1900] + # 0x1b: int8u - Month + # 0x1c: int8u - Day + # 0x1d: int8u - Hour + # 0x1e: int8u - Minutes + # 0x1f: int8u - BrightDiff + # Table with DustCount entries: + # 0x22: int16u - DustX + # 0x24: int16u - DustY + # 0x26: int16u - DustSize + }, + 0x98 => { #PH + Name => 'CropInfo', # (ImageSizeOffset) + SubDirectory => { TagTable => 'Image::ExifTool::Canon::CropInfo' }, + }, + 0x99 => { #PH (EOS 1D Mark III, 40D, etc) + Name => 'CustomFunctions2', # (CustomFunEx) + SubDirectory => { + Validate => 'Image::ExifTool::Canon::Validate($dirData,$subdirStart,$size)', + TagTable => 'Image::ExifTool::CanonCustom::Functions2', + }, + }, + 0x9a => { #PH + Name => 'AspectInfo', # (AspectRatioInfo) + SubDirectory => { TagTable => 'Image::ExifTool::Canon::AspectInfo' }, + }, + 0xa0 => { + Name => 'ProcessingInfo', # (DevelopParam) + SubDirectory => { + Validate => 'Image::ExifTool::Canon::Validate($dirData,$subdirStart,$size)', + TagTable => 'Image::ExifTool::Canon::Processing', + }, + }, + 0xa1 => { Name => 'ToneCurveTable', %longBin }, #PH + 0xa2 => { Name => 'SharpnessTable', %longBin }, #PH + 0xa3 => { Name => 'SharpnessFreqTable', %longBin }, #PH + 0xa4 => { Name => 'WhiteBalanceTable', %longBin }, #PH + 0xa9 => { + Name => 'ColorBalance', + SubDirectory => { + Validate => 'Image::ExifTool::Canon::Validate($dirData,$subdirStart,$size)', + TagTable => 'Image::ExifTool::Canon::ColorBalance', + }, + }, + 0xaa => { + Name => 'MeasuredColor', # (PresetWBDS) + SubDirectory => { + Validate => 'Image::ExifTool::Canon::Validate($dirData,$subdirStart,$size)', + TagTable => 'Image::ExifTool::Canon::MeasuredColor', + }, + }, + 0xae => { + Name => 'ColorTemperature', + Writable => 'int16u', + }, + 0xb0 => { #PH + Name => 'CanonFlags', + SubDirectory => { + Validate => 'Image::ExifTool::Canon::Validate($dirData,$subdirStart,$size)', + TagTable => 'Image::ExifTool::Canon::Flags', + }, + }, + 0xb1 => { #PH + Name => 'ModifiedInfo', + SubDirectory => { + Validate => 'Image::ExifTool::Canon::Validate($dirData,$subdirStart,$size)', + TagTable => 'Image::ExifTool::Canon::ModifiedInfo', + }, + }, + 0xb2 => { Name => 'ToneCurveMatching', %longBin }, #PH + 0xb3 => { Name => 'WhiteBalanceMatching', %longBin }, #PH + 0xb4 => { #PH + Name => 'ColorSpace', + Writable => 'int16u', + PrintConv => { + 1 => 'sRGB', + 2 => 'Adobe RGB', + }, + }, + 0xb6 => { + Name => 'PreviewImageInfo', + SubDirectory => { + # Note: the first word of this block gives the correct block size in bytes, but + # the size is wrong by a factor of 2 in the IFD, so we must account for this + Validate => 'Image::ExifTool::Canon::Validate($dirData,$subdirStart,$size/2)', + TagTable => 'Image::ExifTool::Canon::PreviewImageInfo', + }, + }, + 0xd0 => { #PH + Name => 'VRDOffset', + Writable => 'int32u', + OffsetPair => 1, # (just used as a flag, since this tag has no pair) + Protected => 2, + DataTag => 'CanonVRD', + Notes => 'offset of VRD "recipe data" if it exists', + }, + 0xe0 => { #12 + Name => 'SensorInfo', # (ImageAreaDesc) + SubDirectory => { + Validate => 'Image::ExifTool::Canon::Validate($dirData,$subdirStart,$size)', + TagTable => 'Image::ExifTool::Canon::SensorInfo', + }, + }, + 0x4001 => [ #13 (WBPacket) + { # (int16u[582]) - 20D and 350D + Condition => '$count == 582', + Name => 'ColorData1', + SubDirectory => { TagTable => 'Image::ExifTool::Canon::ColorData1' }, + }, + { # (int16u[653]) - 1DmkII and 1DSmkII + Condition => '$count == 653', + Name => 'ColorData2', + SubDirectory => { TagTable => 'Image::ExifTool::Canon::ColorData2' }, + }, + { # (int16u[796]) - 1DmkIIN, 5D, 30D, 400D + Condition => '$count == 796', + Name => 'ColorData3', + SubDirectory => { TagTable => 'Image::ExifTool::Canon::ColorData3' }, + }, + { # (int16u[692|674|702|1227|1250|1251|1337]) + # 40D (692), 1DmkIII (674), 1DSmkIII (702), 450D/1000D (1227) + # 50D/5DmkII (1250), 500D/7D_pre-prod/1DmkIV_pre-prod (1251), + # 1DmkIV/7D/550D_pre-prod (1337), 550D (1338), 60D/1100D (1346) + Condition => q{ + $count == 692 or $count == 674 or $count == 702 or + $count == 1227 or $count == 1250 or $count == 1251 or + $count == 1337 or $count == 1338 or $count == 1346 + }, + Name => 'ColorData4', + SubDirectory => { TagTable => 'Image::ExifTool::Canon::ColorData4' }, + }, + { # (int16u[5120]) - G10, G7X + Condition => '$count == 5120', + Name => 'ColorData5', + SubDirectory => { TagTable => 'Image::ExifTool::Canon::ColorData5' }, + }, + { # (int16u[1273|1275]) - 600D (1273), 1200D (1275) + Condition => '$count == 1273 or $count == 1275', + Name => 'ColorData6', + SubDirectory => { TagTable => 'Image::ExifTool::Canon::ColorData6' }, + }, + { # (int16u[1312|1313|1316]) + # 1DX/5DmkIII/650D/700D/M (1312), 6D/70D/100D (1313), + # 1DX firmware 1.x (1316), 7DmkII (1506) + Condition => '$count == 1312 or $count == 1313 or $count == 1316 or + $count == 1506', + Name => 'ColorData7', + SubDirectory => { TagTable => 'Image::ExifTool::Canon::ColorData7' }, + }, + { # (int16u[1560|1592]) - 5DS/5DSR (1560), 80D (1592), 1300D (1353) ref IB + Condition => '$count == 1560 or $count == 1592 or $count == 1353 or $count == 1602', + Name => 'ColorData8', + SubDirectory => { TagTable => 'Image::ExifTool::Canon::ColorData8' }, + }, + { # (int16u[1816|1820|1824]) - M50 (1820) ref PH, EOS R (1824), EOS RP, SX70 (1816) ref IB + Condition => '$count == 1816 or $count == 1820 or $count == 1824', + Name => 'ColorData9', + SubDirectory => { TagTable => 'Image::ExifTool::Canon::ColorData9' }, + }, + { + Name => 'ColorDataUnknown', + SubDirectory => { TagTable => 'Image::ExifTool::Canon::ColorDataUnknown' }, + }, + ], + 0x4002 => { #PH + # unknown data block in some JPEG and CR2 images + # (5kB for most models, but 22kb for 5D and 30D, and 43kB for 5DmkII so Drop it) + Name => 'CRWParam', + Format => 'undef', + Flags => [ 'Unknown', 'Binary', 'Drop' ], + }, + 0x4003 => { #PH + Name => 'ColorInfo', + SubDirectory => { TagTable => 'Image::ExifTool::Canon::ColorInfo' }, + }, + 0x4005 => { #PH + Name => 'Flavor', + Notes => 'unknown 49kB block, not copied to JPEG images', + # 'Drop' because not found in JPEG images (too large for APP1 anyway) + Flags => [ 'Unknown', 'Binary', 'Drop' ], + }, + 0x4008 => { #53 + Name => 'PictureStyleUserDef', # (BasePictStyleOfUser) + Format => 'int16u', + Count => 3, # UserDef1, UserDef2, UserDef3 + PrintHex => 1, + SeparateTable => 'PictureStyle', + PrintConv => [\%pictureStyles,\%pictureStyles,\%pictureStyles], + }, + 0x4009 => { #53 + Name => 'PictureStylePC', # (BasePictStyleOfUser) + Format => 'int16u', + Count => 3, # PC1, PC2, PC3 + PrintHex => 1, + SeparateTable => 'PictureStyle', + PrintConv => [\%pictureStyles,\%pictureStyles,\%pictureStyles], + }, + 0x4010 => { #forum2933 + Name => 'CustomPictureStyleFileName', # (PictStyleCaption) + Writable => 'string', + }, + # 0x4011 (PictStyleAppendInfo) + # 0x4012 (CustomWBCaption) + 0x4013 => { #PH + Name => 'AFMicroAdj', # (AFMicroAdjust) + SubDirectory => { + # Canon DPP 3.13 is known to truncate this data to 0x14 bytes (from 0x2c), + # so specifically check for 0x2c to avoid giving a warning in this case + Validate => 'Image::ExifTool::Canon::Validate($dirData,$subdirStart,$size,0x2c)', + TagTable => 'Image::ExifTool::Canon::AFMicroAdj', + }, + }, + # 0x4014 (similar to 0x83?) + 0x4015 => [{ + Name => 'VignettingCorr', # (LensPacket) + Condition => '$$valPt =~ /^\0/ and $$valPt !~ /^\0\0\0\0/', # (data may be all zeros for 60D) + SubDirectory => { + # (the size word is at byte 2 in this structure) + Validate => 'Image::ExifTool::Canon::Validate($dirData,$subdirStart+2,$size)', + TagTable => 'Image::ExifTool::Canon::VignettingCorr', + }, + },{ + Name => 'VignettingCorrUnknown1', + Condition => '$$valPt =~ /^[\x01\x02\x10\x20]/ and $$valPt !~ /^\0\0\0\0/', + SubDirectory => { + # (the size word is at byte 2 in this structure) + Validate => 'Image::ExifTool::Canon::Validate($dirData,$subdirStart+2,$size)', + TagTable => 'Image::ExifTool::Canon::VignettingCorrUnknown', + }, + },{ + Name => 'VignettingCorrUnknown2', + Condition => '$$valPt !~ /^\0\0\0\0/', + SubDirectory => { + # (the size word is at byte 4 for version 3 of this structure, but not always!) + # Validate => 'Image::ExifTool::Canon::Validate($dirData,$subdirStart+4,$size)', + TagTable => 'Image::ExifTool::Canon::VignettingCorrUnknown', + }, + }], + 0x4016 => { + Name => 'VignettingCorr2', # (ImageCorrectActual) + SubDirectory => { + # (the size word is actually 4 bytes, but it doesn't matter if little-endian) + Validate => 'Image::ExifTool::Canon::Validate($dirData,$subdirStart,$size)', + TagTable => 'Image::ExifTool::Canon::VignettingCorr2', + }, + }, + 0x4018 => { #PH + Name => 'LightingOpt', # (ImageCorrect) + SubDirectory => { + Validate => 'Image::ExifTool::Canon::Validate($dirData,$subdirStart,$size)', + TagTable => 'Image::ExifTool::Canon::LightingOpt', + } + }, + 0x4019 => { #20 + Name => 'LensInfo', # (LensInfoForService) + SubDirectory => { + TagTable => 'Image::ExifTool::Canon::LensInfo', + } + }, + 0x4020 => { #PH + Name => 'AmbienceInfo', + Condition => '$$valPt !~ /^\0\0\0\0/', # (data may be all zeros for 60D) + SubDirectory => { + Validate => 'Image::ExifTool::Canon::Validate($dirData,$subdirStart,$size)', + TagTable => 'Image::ExifTool::Canon::Ambience', + } + }, + 0x4021 => { #PH + Name => 'MultiExp', # (ExifDSTagMultipleExposure) + SubDirectory => { + Validate => 'Image::ExifTool::Canon::Validate($dirData,$subdirStart,$size)', + TagTable => 'Image::ExifTool::Canon::MultiExp', + } + }, + 0x4024 => { #PH + Name => 'FilterInfo', + SubDirectory => { + Validate => 'Image::ExifTool::Canon::Validate($dirData,$subdirStart,$size)', + TagTable => 'Image::ExifTool::Canon::FilterInfo', + } + }, + 0x4025 => { #PH + Name => 'HDRInfo', # (HighDynamicRange) + SubDirectory => { + Validate => 'Image::ExifTool::Canon::Validate($dirData,$subdirStart,$size)', + TagTable => 'Image::ExifTool::Canon::HDRInfo', + } + }, + 0x4028 => { #PH + Name => 'AFConfig', # (AFTabInfo) + SubDirectory => { + Validate => 'Image::ExifTool::Canon::Validate($dirData,$subdirStart,$size)', + TagTable => 'Image::ExifTool::Canon::AFConfig', + } + }, +); + +#.............................................................................. +# Canon camera settings (MakerNotes tag 0x01) +# BinaryData (keys are indices into the int16s array) +%Image::ExifTool::Canon::CameraSettings = ( + %binaryDataAttrs, + FORMAT => 'int16s', + FIRST_ENTRY => 1, + DATAMEMBER => [ 22, 25 ], # necessary for writing + GROUPS => { 0 => 'MakerNotes', 2 => 'Camera' }, + 1 => { + Name => 'MacroMode', + PrintConv => { + 1 => 'Macro', + 2 => 'Normal', + }, + }, + 2 => { + Name => 'SelfTimer', + # Custom timer mode if bit 0x4000 is set - PH (A570IS) + PrintConv => q{ + return 'Off' unless $val; + return (($val&0xfff) / 10) . ' s' . ($val & 0x4000 ? ', Custom' : ''); + }, + PrintConvInv => q{ + return 0 if $val =~ /^Off/i; + $val =~ s/\s*s(ec)?\b//i; + $val =~ s/,?\s*Custom$//i ? ($val*10) | 0x4000 : $val*10; + }, + }, + 3 => { + Name => 'Quality', + PrintConv => \%canonQuality, + }, + 4 => { + Name => 'CanonFlashMode', + PrintConv => { + -1 => "n/a", # (PH, EOS M MOV video) + 0 => 'Off', + 1 => 'Auto', + 2 => 'On', + 3 => 'Red-eye reduction', + 4 => 'Slow-sync', + 5 => 'Red-eye reduction (Auto)', + 6 => 'Red-eye reduction (On)', + 16 => 'External flash', # not set in D30 or 300D + }, + }, + 5 => { + Name => 'ContinuousDrive', + PrintConv => { + 0 => 'Single', + 1 => 'Continuous', + 2 => 'Movie', #PH + 3 => 'Continuous, Speed Priority', #PH + 4 => 'Continuous, Low', #PH + 5 => 'Continuous, High', #PH + 6 => 'Silent Single', #PH + # ref A: http://u88.n24.queensu.ca/exiftool/forum/index.php/topic,5701.msg27843.html#msg27843 + 9 => 'Single, Silent', #A + 10 => 'Continuous, Silent', #A + # 11 - seen for SX260 + # 32-34 - Self-timer? + }, + }, + 7 => { + Name => 'FocusMode', + PrintConv => { + 0 => 'One-shot AF', + 1 => 'AI Servo AF', + 2 => 'AI Focus AF', + 3 => 'Manual Focus (3)', + 4 => 'Single', + 5 => 'Continuous', + 6 => 'Manual Focus (6)', + 16 => 'Pan Focus', #PH + # 137 - Single? + 256 => 'AF + MF', #PH (NC, EOS M) + 512 => 'Movie Snap Focus', #48 + 519 => 'Movie Servo AF', #PH (NC, EOS M) + }, + }, + 9 => { #PH + Name => 'RecordMode', + RawConv => '$val==-1 ? undef : $val', #22 + PrintConv => { + 1 => 'JPEG', + 2 => 'CRW+THM', # (300D,etc) + 3 => 'AVI+THM', # (30D) + 4 => 'TIF', # +THM? (1Ds) (unconfirmed) + 5 => 'TIF+JPEG', # (1D) (unconfirmed) + 6 => 'CR2', # +THM? (1D,30D,350D) + 7 => 'CR2+JPEG', # (S30) + 9 => 'MOV', # (S95 MOV) + 10 => 'MP4', # (SX280 MP4) + 11 => 'CRM', #PH (C200 CRM) + 12 => 'CR3', #PH (EOS R) + 13 => 'CR3+JPEG', #PH (EOS R) + }, + }, + 10 => { + Name => 'CanonImageSize', + PrintConvColumns => 2, + PrintConv => \%canonImageSize, + }, + 11 => { + Name => 'EasyMode', + PrintConvColumns => 3, + PrintConv => { + # references: + # A = http://homepage3.nifty.com/kamisaka/makernote/makernote_canon.htm + # B = http://www.burren.cx/david/canon.html + # C = DPP 3.11.26 + 0 => 'Full auto', + 1 => 'Manual', + 2 => 'Landscape', + 3 => 'Fast shutter', + 4 => 'Slow shutter', + 5 => 'Night', # (C='Night Scene') + 6 => 'Gray Scale', #PH (A/B/C='Black & White') + 7 => 'Sepia', + 8 => 'Portrait', + 9 => 'Sports', + 10 => 'Macro', + 11 => 'Black & White', #PH (A='Black & White', B/C='Pan focus') + 12 => 'Pan focus', # (A='Pan focus', C='Vivid') + 13 => 'Vivid', #PH (A='Vivid', C='Neutral') + 14 => 'Neutral', #PH (A='Natural', C='Black & White') + 15 => 'Flash Off', #8 (C=<none>) + 16 => 'Long Shutter', #PH + 17 => 'Super Macro', #PH (C='Macro') + 18 => 'Foliage', #PH + 19 => 'Indoor', #PH + 20 => 'Fireworks', #PH + 21 => 'Beach', #PH + 22 => 'Underwater', #PH + 23 => 'Snow', #PH + 24 => 'Kids & Pets', #PH + 25 => 'Night Snapshot', #PH + 26 => 'Digital Macro', #PH + 27 => 'My Colors', #PH + 28 => 'Movie Snap', #PH + 29 => 'Super Macro 2', #PH + 30 => 'Color Accent', #18 + 31 => 'Color Swap', #18 + 32 => 'Aquarium', #18 + 33 => 'ISO 3200', #18 + 34 => 'ISO 6400', #PH + 35 => 'Creative Light Effect', #PH + 36 => 'Easy', #PH + 37 => 'Quick Shot', #PH + 38 => 'Creative Auto', #39 + 39 => 'Zoom Blur', #PH + 40 => 'Low Light', #PH + 41 => 'Nostalgic', #PH + 42 => 'Super Vivid', #PH (SD4500) + 43 => 'Poster Effect', #PH (SD4500) + 44 => 'Face Self-timer', #PH + 45 => 'Smile', #PH + 46 => 'Wink Self-timer', #PH + 47 => 'Fisheye Effect', #PH (SX30IS,IXUS240) + 48 => 'Miniature Effect', #PH (SD4500) + 49 => 'High-speed Burst', #PH + 50 => 'Best Image Selection', #PH + 51 => 'High Dynamic Range', #PH (S95) + 52 => 'Handheld Night Scene', #PH + 53 => 'Movie Digest', #PH + 54 => 'Live View Control', #PH + 55 => 'Discreet', #PH + 56 => 'Blur Reduction', #PH + 57 => 'Monochrome', #PH (SX260 B&W,Sepia,Blue tone) + 58 => 'Toy Camera Effect', #51 + 59 => 'Scene Intelligent Auto', #PH (T3i) (C='High-speed Burst HQ' !!) + 60 => 'High-speed Burst HQ', #PH (C='High-speed Burst HQ', same as 59) + 61 => 'Smooth Skin', #51 + 62 => 'Soft Focus', #PH (SX260,IXUS240) + # 83 - seen for EOS M3 night shot (PH) + 257 => 'Spotlight', #PH + 258 => 'Night 2', #PH + 259 => 'Night+', + 260 => 'Super Night', #PH + 261 => 'Sunset', #PH (SX10IS) + 263 => 'Night Scene', #PH + 264 => 'Surface', #PH + 265 => 'Low Light 2', #PH + }, + }, + 12 => { + Name => 'DigitalZoom', + PrintConv => { + 0 => 'None', + 1 => '2x', + 2 => '4x', + 3 => 'Other', # value obtained from 2*$val[37]/$val[36] + }, + }, + 13 => { + Name => 'Contrast', + RawConv => '$val == 0x7fff ? undef : $val', + %Image::ExifTool::Exif::printParameter, + }, + 14 => { + Name => 'Saturation', + RawConv => '$val == 0x7fff ? undef : $val', + %Image::ExifTool::Exif::printParameter, + }, + 15 => { + Name => 'Sharpness', + RawConv => '$val == 0x7fff ? undef : $val', + Notes => q{ + some models use a range of -2 to +2 where 0 is normal sharpening, and + others use a range of 0 to 7 where 0 is no sharpening + }, + PrintConv => '$val > 0 ? "+$val" : $val', + PrintConvInv => '$val', + }, + 16 => { + Name => 'CameraISO', + RawConv => '$val == 0x7fff ? undef : $val', + ValueConv => 'Image::ExifTool::Canon::CameraISO($val)', + ValueConvInv => 'Image::ExifTool::Canon::CameraISO($val,1)', + }, + 17 => { + Name => 'MeteringMode', + PrintConv => { + 0 => 'Default', # older Ixus + 1 => 'Spot', + 2 => 'Average', #PH + 3 => 'Evaluative', + 4 => 'Partial', + 5 => 'Center-weighted average', + }, + }, + 18 => { + # this is always 2 for the 300D - PH + Name => 'FocusRange', + PrintConv => { + 0 => 'Manual', + 1 => 'Auto', + 2 => 'Not Known', + 3 => 'Macro', + 4 => 'Very Close', #PH + 5 => 'Close', #PH + 6 => 'Middle Range', #PH + 7 => 'Far Range', + 8 => 'Pan Focus', + 9 => 'Super Macro', #PH + 10=> 'Infinity', #PH + }, + }, + 19 => { + Name => 'AFPoint', + Flags => 'PrintHex', + RawConv => '$val==0 ? undef : $val', + PrintConv => { + 0x2005 => 'Manual AF point selection', + 0x3000 => 'None (MF)', + 0x3001 => 'Auto AF point selection', + 0x3002 => 'Right', + 0x3003 => 'Center', + 0x3004 => 'Left', + 0x4001 => 'Auto AF point selection', + 0x4006 => 'Face Detect', #PH (A570IS) + }, + }, + 20 => { + Name => 'CanonExposureMode', + PrintConv => { + 0 => 'Easy', + 1 => 'Program AE', + 2 => 'Shutter speed priority AE', + 3 => 'Aperture-priority AE', + 4 => 'Manual', + 5 => 'Depth-of-field AE', + 6 => 'M-Dep', #PH + 7 => 'Bulb', #30 + }, + }, + 22 => { #4 + Name => 'LensType', + Format => 'int16u', + RawConv => '$val ? $$self{LensType}=$val : undef', # don't use if value is zero + Notes => 'this value is incorrect for EOS 7D images with lenses of type 256 or greater', + SeparateTable => 1, + DataMember => 'LensType', + ValueConvInv => 'int($val)', # (must truncate decimal part) + PrintConv => \%canonLensTypes, + }, + 23 => { + Name => 'MaxFocalLength', + Format => 'int16u', + # this is a bit tricky, but we need the FocalUnits to convert this to mm + RawConvInv => '$val * ($$self{FocalUnits} || 1)', + ValueConv => '$val / ($$self{FocalUnits} || 1)', + ValueConvInv => '$val', + PrintConv => '"$val mm"', + PrintConvInv => '$val=~s/\s*mm//;$val', + }, + 24 => { + Name => 'MinFocalLength', + Format => 'int16u', + RawConvInv => '$val * ($$self{FocalUnits} || 1)', + ValueConv => '$val / ($$self{FocalUnits} || 1)', + ValueConvInv => '$val', + PrintConv => '"$val mm"', + PrintConvInv => '$val=~s/\s*mm//;$val', + }, + 25 => { + Name => 'FocalUnits', + # conversion from raw focal length values to mm + DataMember => 'FocalUnits', + RawConv => '$$self{FocalUnits} = $val', + PrintConv => '"$val/mm"', + PrintConvInv => '$val=~s/\s*\/?\s*mm//;$val', + }, + 26 => { #9 + Name => 'MaxAperture', + RawConv => '$val > 0 ? $val : undef', + ValueConv => 'exp(Image::ExifTool::Canon::CanonEv($val)*log(2)/2)', + ValueConvInv => 'Image::ExifTool::Canon::CanonEvInv(log($val)*2/log(2))', + PrintConv => 'sprintf("%.2g",$val)', + PrintConvInv => '$val', + }, + 27 => { #PH + Name => 'MinAperture', + RawConv => '$val > 0 ? $val : undef', + ValueConv => 'exp(Image::ExifTool::Canon::CanonEv($val)*log(2)/2)', + ValueConvInv => 'Image::ExifTool::Canon::CanonEvInv(log($val)*2/log(2))', + PrintConv => 'sprintf("%.2g",$val)', + PrintConvInv => '$val', + }, + 28 => { + Name => 'FlashActivity', + RawConv => '$val==-1 ? undef : $val', + }, + 29 => { + Name => 'FlashBits', + PrintConvColumns => 2, + PrintConv => { + 0 => '(none)', + BITMASK => { + 0 => 'Manual', #PH + 1 => 'TTL', #PH + 2 => 'A-TTL', #PH + 3 => 'E-TTL', #PH + 4 => 'FP sync enabled', + 7 => '2nd-curtain sync used', + 11 => 'FP sync used', + 13 => 'Built-in', + 14 => 'External', #(may not be set in manual mode - ref 37) + }, + }, + }, + 32 => { + Name => 'FocusContinuous', + RawConv => '$val==-1 ? undef : $val', + PrintConv => { + 0 => 'Single', + 1 => 'Continuous', + 8 => 'Manual', #22 + }, + }, + 33 => { #PH + Name => 'AESetting', + RawConv => '$val==-1 ? undef : $val', + PrintConv => { + 0 => 'Normal AE', + 1 => 'Exposure Compensation', + 2 => 'AE Lock', + 3 => 'AE Lock + Exposure Comp.', + 4 => 'No AE', + }, + }, + 34 => { #PH + Name => 'ImageStabilization', + RawConv => '$val==-1 ? undef : $val', + PrintConv => { + 0 => 'Off', + 1 => 'On', + 2 => 'Shoot Only', #15 + 3 => 'Panning', # (A570IS) + 4 => 'Dynamic', # (SX30IS) (was 'On, Video') + # (don't know what bit 0x100 indicates) + 256 => 'Off (2)', + 257 => 'On (2)', + 258 => 'Shoot Only (2)', + 259 => 'Panning (2)', + 260 => 'Dynamic (2)', + }, + }, + 35 => { #PH + Name => 'DisplayAperture', + RawConv => '$val ? $val : undef', + ValueConv => '$val / 10', + ValueConvInv => '$val * 10', + }, + 36 => 'ZoomSourceWidth', #PH + 37 => 'ZoomTargetWidth', #PH + 39 => { #22 + Name => 'SpotMeteringMode', + RawConv => '$val==-1 ? undef : $val', + PrintConv => { + 0 => 'Center', + 1 => 'AF Point', + }, + }, + 40 => { #PH + Name => 'PhotoEffect', + RawConv => '$val==-1 ? undef : $val', + PrintConvColumns => 2, + PrintConv => { + 0 => 'Off', + 1 => 'Vivid', + 2 => 'Neutral', + 3 => 'Smooth', + 4 => 'Sepia', + 5 => 'B&W', + 6 => 'Custom', + 100 => 'My Color Data', + }, + }, + 41 => { #PH (A570IS) + Name => 'ManualFlashOutput', + PrintHex => 1, + PrintConv => { + 0 => 'n/a', + 0x500 => 'Full', + 0x502 => 'Medium', + 0x504 => 'Low', + 0x7fff => 'n/a', # (EOS models) + }, + }, + # 41 => non-zero for manual flash intensity - PH (A570IS) + 42 => { + Name => 'ColorTone', + RawConv => '$val == 0x7fff ? undef : $val', + %Image::ExifTool::Exif::printParameter, + }, + 46 => { #PH + Name => 'SRAWQuality', + RawConv => '$val==-1 ? undef : $val', + PrintConv => { + 0 => 'n/a', + 1 => 'sRAW1 (mRAW)', + 2 => 'sRAW2 (sRAW)', + }, + }, + # 47 - related to aspect ratio: 100=4:3,70=1:1/16:9,90=3:2,60=4:5 (PH G12) + # (roughly image area in percent - 4:3=100%,1:1/16:9=75%,3:2=89%,4:5=60%) +); + +# focal length information (MakerNotes tag 0x02) +%Image::ExifTool::Canon::FocalLength = ( + %binaryDataAttrs, + FORMAT => 'int16u', + FIRST_ENTRY => 0, + GROUPS => { 0 => 'MakerNotes', 2 => 'Image' }, + 0 => { #9 + Name => 'FocalType', + RawConv => '$val ? $val : undef', # don't use if value is zero + PrintConv => { + 1 => 'Fixed', + 2 => 'Zoom', + }, + }, + 1 => { + Name => 'FocalLength', + # the EXIF FocalLength is more reliable, so set this priority to zero + Priority => 0, + RawConv => '$val ? $val : undef', # don't use if value is zero + RawConvInv => q{ + my $focalUnits = $$self{FocalUnits}; + unless ($focalUnits) { + $focalUnits = 1; + # (this happens when writing FocalLength to CRW images) + $self->Warn("FocalUnits not available for FocalLength conversion (1 assumed)"); + } + return $val * $focalUnits; + }, + ValueConv => '$val / ($$self{FocalUnits} || 1)', + ValueConvInv => '$val', + PrintConv => '"$val mm"', + PrintConvInv => '$val=~s/\s*mm//;$val', + }, + 2 => [ #4 + { + Name => 'FocalPlaneXSize', + Notes => q{ + these focal plane sizes are only valid for some models, and are affected by + digital zoom if applied + }, + # this conversion is valid only for PowerShot models and these EOS models: + # D30, D60, 1D, 1DS, 5D, 10D, 20D, 30D, 300D, 350D, and 400D + Condition => q{ + $$self{Model} !~ /EOS/ or + $$self{Model} =~ /\b(1DS?|5D|D30|D60|10D|20D|30D|K236)$/ or + $$self{Model} =~ /\b((300D|350D|400D) DIGITAL|REBEL( XTi?)?|Kiss Digital( [NX])?)$/ + }, + # focal plane image dimensions in 1/1000 inch -- convert to mm + RawConv => '$val < 40 ? undef : $val', # must be reasonable + ValueConv => '$val * 25.4 / 1000', + ValueConvInv => 'int($val * 1000 / 25.4 + 0.5)', + PrintConv => 'sprintf("%.2f mm",$val)', + PrintConvInv => '$val=~s/\s*mm$//;$val', + },{ + Name => 'FocalPlaneXUnknown', + Unknown => 1, + }, + ], + 3 => [ #4 + { + Name => 'FocalPlaneYSize', + Condition => q{ + $$self{Model} !~ /EOS/ or + $$self{Model} =~ /\b(1DS?|5D|D30|D60|10D|20D|30D|K236)$/ or + $$self{Model} =~ /\b((300D|350D|400D) DIGITAL|REBEL( XTi?)?|Kiss Digital( [NX])?)$/ + }, + RawConv => '$val < 40 ? undef : $val', # must be reasonable + ValueConv => '$val * 25.4 / 1000', + ValueConvInv => 'int($val * 1000 / 25.4 + 0.5)', + PrintConv => 'sprintf("%.2f mm",$val)', + PrintConvInv => '$val=~s/\s*mm$//;$val', + },{ + Name => 'FocalPlaneYUnknown', + Unknown => 1, + }, + ], +); + +# Canon shot information (MakerNotes tag 0x04) +# BinaryData (keys are indices into the int16s array) +%Image::ExifTool::Canon::ShotInfo = ( + %binaryDataAttrs, + FORMAT => 'int16s', + FIRST_ENTRY => 1, + DATAMEMBER => [ 19 ], + GROUPS => { 0 => 'MakerNotes', 2 => 'Image' }, + 1 => { #PH + Name => 'AutoISO', + Notes => 'actual ISO used = BaseISO * AutoISO / 100', + ValueConv => 'exp($val/32*log(2))*100', + ValueConvInv => '32*log($val/100)/log(2)', + PrintConv => 'sprintf("%.0f",$val)', + PrintConvInv => '$val', + }, + 2 => { + Name => 'BaseISO', + Priority => 0, + RawConv => '$val ? $val : undef', + ValueConv => 'exp($val/32*log(2))*100/32', + ValueConvInv => '32*log($val*32/100)/log(2)', + PrintConv => 'sprintf("%.0f",$val)', + PrintConvInv => '$val', + }, + 3 => { #9/PH + Name => 'MeasuredEV', + Notes => q{ + this is the Canon name for what could better be called MeasuredLV, and + should be close to the calculated LightValue for a proper exposure with most + models + }, + # empirical offset of +5 seems to be good for EOS models, but maybe + # the offset should be less by up to 1 EV for some PowerShot models + ValueConv => '$val / 32 + 5', + ValueConvInv => '($val - 5) * 32', + PrintConv => 'sprintf("%.2f",$val)', + PrintConvInv => '$val', + }, + 4 => { #2, 9 + Name => 'TargetAperture', + RawConv => '$val > 0 ? $val : undef', + ValueConv => 'exp(Image::ExifTool::Canon::CanonEv($val)*log(2)/2)', + ValueConvInv => 'Image::ExifTool::Canon::CanonEvInv(log($val)*2/log(2))', + PrintConv => 'sprintf("%.2g",$val)', + PrintConvInv => '$val', + }, + 5 => { #2 + Name => 'TargetExposureTime', + # ignore obviously bad values (also, -32768 may be used for n/a) + # (note that a few models always write 0: DC211, and video models) + RawConv => '($val > -1000 and ($val or $$self{Model}=~/(EOS|PowerShot|IXUS|IXY)/))? $val : undef', + ValueConv => 'exp(-Image::ExifTool::Canon::CanonEv($val)*log(2))', + ValueConvInv => 'Image::ExifTool::Canon::CanonEvInv(-log($val)/log(2))', + PrintConv => 'Image::ExifTool::Exif::PrintExposureTime($val)', + PrintConvInv => 'Image::ExifTool::Exif::ConvertFraction($val)', + }, + 6 => { + Name => 'ExposureCompensation', + ValueConv => 'Image::ExifTool::Canon::CanonEv($val)', + ValueConvInv => 'Image::ExifTool::Canon::CanonEvInv($val)', + PrintConv => 'Image::ExifTool::Exif::PrintFraction($val)', + PrintConvInv => 'Image::ExifTool::Exif::ConvertFraction($val)', + }, + 7 => { + Name => 'WhiteBalance', + PrintConv => \%canonWhiteBalance, + SeparateTable => 1, + }, + 8 => { #PH + Name => 'SlowShutter', + PrintConv => { + -1 => 'n/a', + 0 => 'Off', + 1 => 'Night Scene', + 2 => 'On', + 3 => 'None', + }, + }, + 9 => { + Name => 'SequenceNumber', + Description => 'Shot Number In Continuous Burst', + Notes => 'valid only for some models', #PH (eg. not the 5DmkIII) + }, + 10 => { #PH/17 + Name => 'OpticalZoomCode', + Groups => { 2 => 'Camera' }, + Notes => 'for many PowerShot models, a this is 0-6 for wide-tele zoom', + # (for many models, 0-6 represent 0-100% zoom, but it is always 8 for + # EOS models, and I have seen values of 16,20,28,32 and 39 too...) + # - set to 8 for "n/a" by Canon software (ref 22) + PrintConv => '$val == 8 ? "n/a" : $val', + PrintConvInv => '$val =~ /[a-z]/i ? 8 : $val', + }, + # 11 - (8 for all EOS samples, [0,8] for other models - PH) + 12 => { #37 + Name => 'CameraTemperature', + Condition => '$$self{Model} =~ /EOS/ and $$self{Model} !~ /EOS-1DS?$/', + Groups => { 2 => 'Camera' }, + Notes => 'newer EOS models only', + # usually zero if not valid for an EOS model (exceptions: 1D, 1DS) + RawConv => '$val ? $val : undef', + ValueConv => '$val - 128', + ValueConvInv => '$val + 128', + PrintConv => '"$val C"', + PrintConvInv => '$val=~s/ ?C//; $val', + }, + 13 => { #PH + Name => 'FlashGuideNumber', + RawConv => '$val==-1 ? undef : $val', + ValueConv => '$val / 32', + ValueConvInv => '$val * 32', + }, + # AF points for Ixus and IxusV cameras - 02/17/04 M. Rommel (also D30/D60 - PH) + 14 => { #2 + Name => 'AFPointsInFocus', + Notes => 'used by D30, D60 and some PowerShot/Ixus models', + Groups => { 2 => 'Camera' }, + Flags => 'PrintHex', + RawConv => '$val==0 ? undef : $val', + PrintConvColumns => 2, + PrintConv => { + 0x3000 => 'None (MF)', + 0x3001 => 'Right', + 0x3002 => 'Center', + 0x3003 => 'Center+Right', + 0x3004 => 'Left', + 0x3005 => 'Left+Right', + 0x3006 => 'Left+Center', + 0x3007 => 'All', + }, + }, + 15 => { + Name => 'FlashExposureComp', + Description => 'Flash Exposure Compensation', + ValueConv => 'Image::ExifTool::Canon::CanonEv($val)', + ValueConvInv => 'Image::ExifTool::Canon::CanonEvInv($val)', + PrintConv => 'Image::ExifTool::Exif::PrintFraction($val)', + PrintConvInv => 'Image::ExifTool::Exif::ConvertFraction($val)', + }, + 16 => { + Name => 'AutoExposureBracketing', + PrintConv => { + -1 => 'On', + 0 => 'Off', + 1 => 'On (shot 1)', + 2 => 'On (shot 2)', + 3 => 'On (shot 3)', + }, + }, + 17 => { + Name => 'AEBBracketValue', + ValueConv => 'Image::ExifTool::Canon::CanonEv($val)', + ValueConvInv => 'Image::ExifTool::Canon::CanonEvInv($val)', + PrintConv => 'Image::ExifTool::Exif::PrintFraction($val)', + PrintConvInv => 'Image::ExifTool::Exif::ConvertFraction($val)', + }, + 18 => { #22 + Name => 'ControlMode', + PrintConv => { + 0 => 'n/a', + 1 => 'Camera Local Control', + # 2 - have seen this for EOS M studio picture + 3 => 'Computer Remote Control', + }, + }, + 19 => { + Name => 'FocusDistanceUpper', + DataMember => 'FocusDistanceUpper', + Format => 'int16u', + Notes => 'FocusDistance tags are only extracted if FocusDistanceUpper is non-zero', + RawConv => '($$self{FocusDistanceUpper} = $val) || undef', + ValueConv => '$val / 100', + ValueConvInv => '$val * 100', + PrintConv => '$val > 655.345 ? "inf" : "$val m"', + PrintConvInv => '$val =~ s/ ?m$//; IsFloat($val) ? $val : 655.35', + }, + 20 => { + Name => 'FocusDistanceLower', # (seems to be the upper distance for the 400D) + Condition => '$$self{FocusDistanceUpper}', + Format => 'int16u', + ValueConv => '$val / 100', + ValueConvInv => '$val * 100', + PrintConv => '$val > 655.345 ? "inf" : "$val m"', + PrintConvInv => '$val =~ s/ ?m$//; IsFloat($val) ? $val : 655.35', + }, + 21 => { + Name => 'FNumber', + Priority => 0, + RawConv => '$val ? $val : undef', + # approximate big translation table by simple calculation - PH + ValueConv => 'exp(Image::ExifTool::Canon::CanonEv($val)*log(2)/2)', + ValueConvInv => 'Image::ExifTool::Canon::CanonEvInv(log($val)*2/log(2))', + PrintConv => 'sprintf("%.2g",$val)', + PrintConvInv => '$val', + }, + 22 => [ + { + Name => 'ExposureTime', + # encoding is different for 20D and 350D (darn!) + # (but note that encoding is the same for TargetExposureTime - PH) + Condition => '$$self{Model} =~ /\b(20D|350D|REBEL XT|Kiss Digital N)\b/', + Priority => 0, + # many models write 0 here in JPEG images (even though 0 is the + # value for an exposure time of 1 sec), but apparently a value of 0 + # is valid in a CRW image (=1s, D60 sample) + RawConv => '($val or $$self{FILE_TYPE} eq "CRW") ? $val : undef', + # approximate big translation table by simple calculation - PH + ValueConv => 'exp(-Image::ExifTool::Canon::CanonEv($val)*log(2))*1000/32', + ValueConvInv => 'Image::ExifTool::Canon::CanonEvInv(-log($val*32/1000)/log(2))', + PrintConv => 'Image::ExifTool::Exif::PrintExposureTime($val)', + PrintConvInv => 'Image::ExifTool::Exif::ConvertFraction($val)', + }, + { + Name => 'ExposureTime', + Priority => 0, + # many models write 0 here in JPEG images (even though 0 is the + # value for an exposure time of 1 sec), but apparently a value of 0 + # is valid in a CRW image (=1s, D60 sample) + RawConv => '($val or $$self{FILE_TYPE} eq "CRW") ? $val : undef', + # approximate big translation table by simple calculation - PH + ValueConv => 'exp(-Image::ExifTool::Canon::CanonEv($val)*log(2))', + ValueConvInv => 'Image::ExifTool::Canon::CanonEvInv(-log($val)/log(2))', + PrintConv => 'Image::ExifTool::Exif::PrintExposureTime($val)', + PrintConvInv => 'Image::ExifTool::Exif::ConvertFraction($val)', + }, + ], + 23 => { #37 + Name => 'MeasuredEV2', + Description => 'Measured EV 2', + RawConv => '$val ? $val : undef', + ValueConv => '$val / 8 - 6', + ValueConvInv => 'int(($val + 6) * 8 + 0.5)', + }, + 24 => { + Name => 'BulbDuration', + ValueConv => '$val / 10', + ValueConvInv => '$val * 10', + }, + # 25 - (usually 0, but 1 for 2s timer?, 19 for small AVI, 14 for large + # AVI, and -6 and -10 for shots 1 and 2 with stitch assist - PH) + 26 => { #15 + Name => 'CameraType', + Groups => { 2 => 'Camera' }, + PrintConv => { + 0 => 'n/a', + 248 => 'EOS High-end', + 250 => 'Compact', + 252 => 'EOS Mid-range', + 255 => 'DV Camera', #PH + }, + }, + 27 => { + Name => 'AutoRotate', + RawConv => '$val >= 0 ? $val : undef', + PrintConv => { + -1 => 'n/a', # (set to -1 when rotated by Canon software) + 0 => 'None', + 1 => 'Rotate 90 CW', + 2 => 'Rotate 180', + 3 => 'Rotate 270 CW', + }, + }, + 28 => { #15 + Name => 'NDFilter', + PrintConv => { -1 => 'n/a', 0 => 'Off', 1 => 'On' }, + }, + 29 => { + Name => 'SelfTimer2', + RawConv => '$val >= 0 ? $val : undef', + ValueConv => '$val / 10', + ValueConvInv => '$val * 10', + }, + 33 => { #PH (A570IS) + Name => 'FlashOutput', + RawConv => '($$self{Model}=~/(PowerShot|IXUS|IXY)/ or $val) ? $val : undef', + Notes => q{ + used only for PowerShot models, this has a maximum value of 500 for models + like the A570IS + }, + }, +); + +# Canon panorama information (MakerNotes tag 0x05) +%Image::ExifTool::Canon::Panorama = ( + %binaryDataAttrs, + FORMAT => 'int16s', + FIRST_ENTRY => 0, + GROUPS => { 0 => 'MakerNotes', 2 => 'Image' }, + # 0 - values: always 1 + # 1 - values: 0,256,512(3 sequential L->R images); 0,-256(2 R->L images) + 2 => 'PanoramaFrameNumber', #(some models this is always 0) + # 3 - values: 160(SX10IS,A570IS); 871(S30) + # 4 - values: always 0 + 5 => { + Name => 'PanoramaDirection', + PrintConv => { + 0 => 'Left to Right', + 1 => 'Right to Left', + 2 => 'Bottom to Top', + 3 => 'Top to Bottom', + 4 => '2x2 Matrix (Clockwise)', + }, + }, +); + +# D30 color information (MakerNotes tag 0x0a) +%Image::ExifTool::Canon::UnknownD30 = ( + %binaryDataAttrs, + FORMAT => 'int16s', + FIRST_ENTRY => 1, + GROUPS => { 0 => 'MakerNotes', 2 => 'Camera' }, +); + +#.............................................................................. +# common CameraInfo tag definitions +my %ciFNumber = ( + Name => 'FNumber', + Format => 'int8u', + Groups => { 2 => 'Image' }, + RawConv => '$val ? $val : undef', + ValueConv => 'exp(($val-8)/16*log(2))', + ValueConvInv => 'log($val)*16/log(2)+8', + PrintConv => 'sprintf("%.2g",$val)', + PrintConvInv => '$val', +); +my %ciExposureTime = ( + Name => 'ExposureTime', + Format => 'int8u', + Groups => { 2 => 'Image' }, + RawConv => '$val ? $val : undef', + ValueConv => 'exp(4*log(2)*(1-Image::ExifTool::Canon::CanonEv($val-24)))', + ValueConvInv => 'Image::ExifTool::Canon::CanonEvInv(1-log($val)/(4*log(2)))+24', + PrintConv => 'Image::ExifTool::Exif::PrintExposureTime($val)', + PrintConvInv => 'Image::ExifTool::Exif::ConvertFraction($val)', +); +my %ciISO = ( + Name => 'ISO', + Format => 'int8u', + Groups => { 2 => 'Image' }, + ValueConv => '100*exp(($val/8-9)*log(2))', + ValueConvInv => '(log($val/100)/log(2)+9)*8', + PrintConv => 'sprintf("%.0f",$val)', + PrintConvInv => '$val', +); +my %ciCameraTemperature = ( + Name => 'CameraTemperature', + Format => 'int8u', + ValueConv => '$val - 128', + ValueConvInv => '$val + 128', + PrintConv => '"$val C"', + PrintConvInv => '$val=~s/ ?C//; $val', +); +my %ciMacroMagnification = ( + Name => 'MacroMagnification', + Notes => 'currently decoded only for the MP-E 65mm f/2.8 1-5x Macro Photo', + Condition => '$$self{LensType} and $$self{LensType} == 124', + # 75=1x, 44=5x, log relationship + ValueConv => 'exp((75-$val) * log(2) * 3 / 40)', + ValueConvInv => '$val > 0 ? 75 - log($val) / log(2) * 40 / 3 : undef', + PrintConv => 'sprintf("%.1fx",$val)', + PrintConvInv => '$val=~s/\s*x//; $val', +); +my %ciFocalLength = ( + Name => 'FocalLength', + Format => 'int16uRev', # (just to make things confusing, the focal lengths are big-endian) + # ignore if zero + RawConv => '$val ? $val : undef', + PrintConv => '"$val mm"', + PrintConvInv => '$val=~s/\s*mm//;$val', +); +my %ciMinFocal = ( + Name => 'MinFocalLength', + Format => 'int16uRev', # byte order is big-endian + PrintConv => '"$val mm"', + PrintConvInv => '$val=~s/\s*mm//;$val', +); +my %ciMaxFocal = ( + Name => 'MaxFocalLength', + Format => 'int16uRev', # byte order is big-endian + PrintConv => '"$val mm"', + PrintConvInv => '$val=~s/\s*mm//;$val', +); + +#.............................................................................. +# Camera information for 1D and 1DS (MakerNotes tag 0x0d) +# (ref 15 unless otherwise noted) +%Image::ExifTool::Canon::CameraInfo1D = ( + %binaryDataAttrs, + FORMAT => 'int8u', + FIRST_ENTRY => 0, + PRIORITY => 0, # these tags are not reliable since they change with firmware version + GROUPS => { 0 => 'MakerNotes', 2 => 'Camera' }, + NOTES => q{ + Information in the "CameraInfo" records is tricky to decode because the + encodings are very different than in other Canon records (even sometimes + switching endianness between values within a single camera), plus there is + considerable variation in format from model to model. The first table below + lists CameraInfo tags for the 1D and 1DS. + }, + 0x04 => { %ciExposureTime }, #9 + 0x0a => { + Name => 'FocalLength', + Format => 'int16u', + # ignore if zero + RawConv => '$val ? $val : undef', + PrintConv => '"$val mm"', + PrintConvInv => '$val=~s/\s*mm//;$val', + }, + 0x0d => { #9 + Name => 'LensType', + Format => 'int16uRev', # value is little-endian + SeparateTable => 1, + RawConv => '$val ? $val : undef', # don't use if value is zero + ValueConvInv => 'int($val)', # (must truncate decimal part) + PrintConv => \%canonLensTypes, + }, + 0x0e => { + Name => 'MinFocalLength', + Format => 'int16u', + PrintConv => '"$val mm"', + PrintConvInv => '$val=~s/\s*mm//;$val', + }, + 0x10 => { + Name => 'MaxFocalLength', + Format => 'int16u', + PrintConv => '"$val mm"', + PrintConvInv => '$val=~s/\s*mm//;$val', + }, + 0x41 => { + Name => 'SharpnessFrequency', # PatternSharpness? + Condition => '$$self{Model} =~ /\b1D$/', + Notes => '1D only', + PrintConvColumns => 2, + PrintConv => { + 0 => 'n/a', + 1 => 'Lowest', + 2 => 'Low', + 3 => 'Standard', + 4 => 'High', + 5 => 'Highest', + }, + }, + 0x42 => { + Name => 'Sharpness', + Format => 'int8s', + Condition => '$$self{Model} =~ /\b1D$/', + Notes => '1D only', + }, + 0x44 => { + Name => 'WhiteBalance', + Condition => '$$self{Model} =~ /\b1D$/', + Notes => '1D only', + SeparateTable => 1, + PrintConv => \%canonWhiteBalance, + }, + 0x47 => { + Name => 'SharpnessFrequency', # PatternSharpness? + Condition => '$$self{Model} =~ /\b1DS$/', + Notes => '1DS only', + PrintConvColumns => 2, + PrintConv => { + 0 => 'n/a', + 1 => 'Lowest', + 2 => 'Low', + 3 => 'Standard', + 4 => 'High', + 5 => 'Highest', + }, + }, + 0x48 => [ + { + Name => 'ColorTemperature', + Format => 'int16u', + Condition => '$$self{Model} =~ /\b1D$/', + Notes => '1D only', + }, + { + Name => 'Sharpness', + Format => 'int8s', + Condition => '$$self{Model} =~ /\b1DS$/', + Notes => '1DS only', + }, + ], + 0x4a => { + Name => 'WhiteBalance', + Condition => '$$self{Model} =~ /\b1DS$/', + Notes => '1DS only', + SeparateTable => 1, + PrintConv => \%canonWhiteBalance, + }, + 0x4b => { + Name => 'PictureStyle', + Condition => '$$self{Model} =~ /\b1D$/', + Notes => "1D only, called 'Color Matrix' in owner's manual", + Flags => ['PrintHex','SeparateTable'], + PrintConv => \%pictureStyles, + }, + 0x4e => { + Name => 'ColorTemperature', + Format => 'int16u', + Condition => '$$self{Model} =~ /\b1DS$/', + Notes => '1DS only', + }, + 0x51 => { + Name => 'PictureStyle', + Condition => '$$self{Model} =~ /\b1DS$/', + Notes => '1DS only', + Flags => ['PrintHex','SeparateTable'], + PrintConv => \%pictureStyles, + }, +); + +# Camera information for 1DmkII and 1DSmkII (MakerNotes tag 0x0d) +# (ref 15 unless otherwise noted) +%Image::ExifTool::Canon::CameraInfo1DmkII = ( + %binaryDataAttrs, + FORMAT => 'int8u', + FIRST_ENTRY => 0, + PRIORITY => 0, + GROUPS => { 0 => 'MakerNotes', 2 => 'Camera' }, + NOTES => 'CameraInfo tags for the 1DmkII and 1DSmkII.', + 0x04 => { %ciExposureTime }, #9 + 0x09 => { %ciFocalLength }, #9 + 0x0c => { #9 + Name => 'LensType', + Format => 'int16uRev', # value is big-endian + SeparateTable => 1, + RawConv => '$val ? $val : undef', # don't use if value is zero + ValueConvInv => 'int($val)', # (must truncate decimal part) + PrintConv => \%canonLensTypes, + }, + 0x11 => { %ciMinFocal }, #9 + 0x13 => { %ciMaxFocal }, #9 + 0x2d => { #9 + Name => 'FocalType', + PrintConv => { + 0 => 'Fixed', + 2 => 'Zoom', + }, + }, + 0x36 => { + Name => 'WhiteBalance', + SeparateTable => 1, + PrintConv => \%canonWhiteBalance, + }, + 0x37 => { + Name => 'ColorTemperature', + Format => 'int16uRev', + }, + 0x39 => { + Name => 'CanonImageSize', + Format => 'int16u', + PrintConvColumns => 2, + PrintConv => \%canonImageSize, + }, + 0x66 => { + Name => 'JPEGQuality', + Notes => 'a number from 1 to 10', + }, + 0x6c => { #12 + Name => 'PictureStyle', + Flags => ['PrintHex','SeparateTable'], + PrintConv => \%pictureStyles, + }, + 0x6e => { + Name => 'Saturation', + Format => 'int8s', + %Image::ExifTool::Exif::printParameter, + }, + 0x6f => { + Name => 'ColorTone', + Format => 'int8s', + %Image::ExifTool::Exif::printParameter, + }, + 0x72 => { + Name => 'Sharpness', + Format => 'int8s', + }, + 0x73 => { + Name => 'Contrast', + Format => 'int8s', + %Image::ExifTool::Exif::printParameter, + }, + 0x75 => { + Name => 'ISO', + Format => 'string[5]', + }, +); + +# Camera information for the 1DmkIIN (MakerNotes tag 0x0d) +# (ref 9 unless otherwise noted) +%Image::ExifTool::Canon::CameraInfo1DmkIIN = ( + %binaryDataAttrs, + FORMAT => 'int8u', + FIRST_ENTRY => 0, + PRIORITY => 0, + GROUPS => { 0 => 'MakerNotes', 2 => 'Camera' }, + NOTES => 'CameraInfo tags for the 1DmkIIN.', + 0x04 => { %ciExposureTime }, + 0x09 => { %ciFocalLength }, + 0x0c => { + Name => 'LensType', + Format => 'int16uRev', # value is big-endian + SeparateTable => 1, + RawConv => '$val ? $val : undef', # don't use if value is zero + ValueConvInv => 'int($val)', # (must truncate decimal part) + PrintConv => \%canonLensTypes, + }, + 0x11 => { %ciMinFocal }, + 0x13 => { %ciMaxFocal }, + 0x36 => { #15 + Name => 'WhiteBalance', + SeparateTable => 1, + PrintConv => \%canonWhiteBalance, + }, + 0x37 => { #15 + Name => 'ColorTemperature', + Format => 'int16uRev', + }, + 0x73 => { #15 + Name => 'PictureStyle', + Flags => ['PrintHex','SeparateTable'], + PrintConv => \%pictureStyles, + }, + 0x74 => { #15 + Name => 'Sharpness', + Format => 'int8s', + }, + 0x75 => { #15 + Name => 'Contrast', + Format => 'int8s', + %Image::ExifTool::Exif::printParameter, + }, + 0x76 => { #15 + Name => 'Saturation', + Format => 'int8s', + %Image::ExifTool::Exif::printParameter, + }, + 0x77 => { #15 + Name => 'ColorTone', + Format => 'int8s', + %Image::ExifTool::Exif::printParameter, + }, + 0x79 => { #15 + Name => 'ISO', + Format => 'string[5]', + }, +); + +# Canon camera information for 1DmkIII and 1DSmkIII (MakerNotes tag 0x0d) (ref PH) +%Image::ExifTool::Canon::CameraInfo1DmkIII = ( + %binaryDataAttrs, + FORMAT => 'int8u', + FIRST_ENTRY => 0, + PRIORITY => 0, + IS_SUBDIR => [ 0x2aa ], + GROUPS => { 0 => 'MakerNotes', 2 => 'Camera' }, + NOTES => 'CameraInfo tags for the 1DmkIII and 1DSmkIII.', + 0x03 => { %ciFNumber }, + 0x04 => { %ciExposureTime }, #9 + 0x06 => { %ciISO }, + 0x18 => { %ciCameraTemperature }, #36 + 0x1b => { %ciMacroMagnification }, #(NC) + 0x1d => { %ciFocalLength }, + 0x30 => { # <-- (follows pattern /\xbb\xbb(.{64})?\x01\x01\0\0.{4}/s for all models - Dave Coffin) + Name => 'CameraOrientation', + PrintConv => { + 0 => 'Horizontal (normal)', + 1 => 'Rotate 90 CW', + 2 => 'Rotate 270 CW', + }, + }, + 0x43 => { #21/24 + Name => 'FocusDistanceUpper', + # (it looks like the focus distances are also odd-byte big-endian) + %focusDistanceByteSwap, + }, + 0x45 => { #21/24 + Name => 'FocusDistanceLower', + %focusDistanceByteSwap, + }, + 0x5e => { #15 + Name => 'WhiteBalance', + Format => 'int16u', + PrintConv => \%canonWhiteBalance, + SeparateTable => 1, + }, + 0x62 => { #15 + Name => 'ColorTemperature', + Format => 'int16u', + }, + 0x86 => { + Name => 'PictureStyle', + Flags => ['PrintHex','SeparateTable'], + PrintConv => \%pictureStyles, + }, + 0x111 => { #15 + Name => 'LensType', + Format => 'int16uRev', # value is big-endian + SeparateTable => 1, + ValueConvInv => 'int($val)', # (must truncate decimal part) + PrintConv => \%canonLensTypes, + }, + 0x113 => { %ciMinFocal }, + 0x115 => { %ciMaxFocal }, + 0x136 => { #15 + Name => 'FirmwareVersion', + Format => 'string[6]', + }, + 0x172 => { + Name => 'FileIndex', + Groups => { 2 => 'Image' }, + Format => 'int32u', + ValueConv => '$val + 1', + ValueConvInv => '$val - 1', + }, + 0x176 => { + Name => 'ShutterCount', + Notes => 'may be valid only for some 1DmkIII copies, even running the same firmware', + Format => 'int32u', + ValueConv => '$val + 1', + ValueConvInv => '$val - 1', + }, + 0x17e => { #(NC) + Name => 'DirectoryIndex', + Groups => { 2 => 'Image' }, + Format => 'int32u', + ValueConv => '$val - 1', + ValueConvInv => '$val + 1', + }, + 0x2aa => { #48 + Name => 'PictureStyleInfo', + SubDirectory => { TagTable => 'Image::ExifTool::Canon::PSInfo' }, + }, + 0x45a => { #29 + Name => 'TimeStamp1', + Condition => '$$self{Model} =~ /\b1D Mark III$/', + Format => 'int32u', + Groups => { 2 => 'Time' }, + # observed in 1DmkIII firmware 5.3.1 (pre-production), 1.0.3, 1.0.8 + Notes => 'only valid for some versions of the 1DmkIII firmware', + Shift => 'Time', + RawConv => '$val ? $val : undef', + ValueConv => 'ConvertUnixTime($val)', + ValueConvInv => 'GetUnixTime($val)', + PrintConv => '$self->ConvertDateTime($val)', + PrintConvInv => '$self->InverseDateTime($val)', + }, + 0x45e => { + Name => 'TimeStamp', + Format => 'int32u', + Groups => { 2 => 'Time' }, + # observed in 1DmkIII firmware 1.1.0, 1.1.3 and + # 1DSmkIII firmware 1.0.0, 1.0.4, 2.1.2, 2.7.1 + Notes => 'valid for the 1DSmkIII and some versions of the 1DmkIII firmware', + Shift => 'Time', + RawConv => '$val ? $val : undef', + ValueConv => 'ConvertUnixTime($val)', + ValueConvInv => 'GetUnixTime($val)', + PrintConv => '$self->ConvertDateTime($val)', + PrintConvInv => '$self->InverseDateTime($val)', + }, +); + +# Canon camera information for 1DmkIV (MakerNotes tag 0x0d) (ref PH) +%Image::ExifTool::Canon::CameraInfo1DmkIV = ( + %binaryDataAttrs, + FIRST_ENTRY => 0, + PRIORITY => 0, + DATAMEMBER => [ 0x00, 0x56, 0x153 ], + IS_SUBDIR => [ 0x368 ], + GROUPS => { 0 => 'MakerNotes', 2 => 'Camera' }, + NOTES => q{ + CameraInfo tags for the EOS 1D Mark IV. Indices shown are for firmware + versions 1.0.x, but they may be different for other firmware versions. + }, + 0x00 => { + Name => 'FirmwareVersionLookAhead', + Hidden => 1, + # look ahead to check location of FirmwareVersion string + Format => 'undef[0x1fd]', + RawConv => q{ + my $t = substr($val, 0x1e8, 6); # 1 = firmware 4.2.1 + $t =~ /^\d+\.\d+\.\d+/ and $$self{CanonFirm} = 1, return undef; + $t = substr($val, 0x1ed, 6); # 2 = firmware 1.0.4 + $t =~ /^\d+\.\d+\.\d+/ and $$self{CanonFirm} = 2, return undef; + $self->Warn('Unrecognized CameraInfo1DmkIV firmware version'); + $$self{CanonFirm} = 0; + return undef; # not a real tag + }, + }, + 0x03 => { %ciFNumber }, + 0x04 => { %ciExposureTime }, + 0x06 => { %ciISO }, + 0x07 => { + Name => 'HighlightTonePriority', + PrintConv => \%offOn, + }, + 0x08 => { + Name => 'MeasuredEV2', + Description => 'Measured EV 2', + RawConv => '$val ? $val : undef', + ValueConv => '$val / 8 - 6', + ValueConvInv => 'int(($val + 6) * 8 + 0.5)', + }, + 0x09 => { + Name => 'MeasuredEV3', + Description => 'Measured EV 3', + RawConv => '$val ? $val : undef', + ValueConv => '$val / 8 - 6', + ValueConvInv => 'int(($val + 6) * 8 + 0.5)', + }, + 0x15 => { + Name => 'FlashMeteringMode', + PrintConv => { + 0 => 'E-TTL', + 3 => 'TTL', + 4 => 'External Auto', + 5 => 'External Manual', + 6 => 'Off', + }, + }, + 0x19 => { %ciCameraTemperature }, + 0x1e => { %ciFocalLength }, + 0x35 => { + Name => 'CameraOrientation', + PrintConv => { + 0 => 'Horizontal (normal)', + 1 => 'Rotate 90 CW', + 2 => 'Rotate 270 CW', + }, + }, + 0x54 => { + Name => 'FocusDistanceUpper', + %focusDistanceByteSwap, + }, + 0x56 => { + Name => 'FocusDistanceLower', + %focusDistanceByteSwap, + Hook => '$varSize += ($$self{CanonFirm} ? -1 : 0x10000) if $$self{CanonFirm} < 2', + }, + 0x78 => { + Name => 'WhiteBalance', + Format => 'int16u', + SeparateTable => 1, + PrintConv => \%canonWhiteBalance, + }, + 0x7c => { + Name => 'ColorTemperature', + Format => 'int16u', + }, + 0x14f => { + Name => 'LensType', + Format => 'int16uRev', # value is big-endian + SeparateTable => 1, + ValueConvInv => 'int($val)', # (must truncate decimal part) + PrintConv => \%canonLensTypes, + }, + 0x151 => { %ciMinFocal }, + 0x153 => { %ciMaxFocal, + Hook => '$varSize -= 4 if $$self{CanonFirm} < 2', + }, + 0x1ed => { + Name => 'FirmwareVersion', + Format => 'string[6]', + Writable => 0, + }, + 0x22c => { #(NC) + Name => 'FileIndex', + Groups => { 2 => 'Image' }, + Format => 'int32u', + ValueConv => '$val + 1', + ValueConvInv => '$val - 1', + }, + 0x238 => { #(NC) + Name => 'DirectoryIndex', + Groups => { 2 => 'Image' }, + Format => 'int32u', + ValueConv => '$val - 1', + ValueConvInv => '$val + 1', + }, + 0x368 => { + Name => 'PictureStyleInfo', + SubDirectory => { TagTable => 'Image::ExifTool::Canon::PSInfo' }, + }, +); + +# Camera information for 1D X (MakerNotes tag 0x0d) (ref PH) +%Image::ExifTool::Canon::CameraInfo1DX = ( + %binaryDataAttrs, + FORMAT => 'int8u', + FIRST_ENTRY => 0, + PRIORITY => 0, + DATAMEMBER => [ 0x00, 0x1b, 0x8e, 0x1ab ], + IS_SUBDIR => [ 0x3f4 ], + GROUPS => { 0 => 'MakerNotes', 2 => 'Camera' }, + NOTES => q{ + CameraInfo tags for the EOS 1D X. Indices shown are for firmware version + 1.0.2, but they may be different for other firmware versions. + }, + 0x00 => { + Name => 'FirmwareVersionLookAhead', + Hidden => 1, + # look ahead to check location of FirmwareVersion string + Format => 'undef[0x28b]', + RawConv => q{ + my $t = substr($val, 0x271, 6); # 1 = firmware 5.7.1 + $t =~ /^\d+\.\d+\.\d+/ and $$self{CanonFirm} = 1, return undef; + $t = substr($val, 0x279, 6); # 2 = firmware 6.5.1 + $t =~ /^\d+\.\d+\.\d+/ and $$self{CanonFirm} = 2, return undef; + $t = substr($val, 0x280, 6); # 3 = firmware 0.0.8/1.0.2/1.1.1 + $t =~ /^\d+\.\d+\.\d+/ and $$self{CanonFirm} = 3, return undef; + $t = substr($val, 0x285, 6); # 4 = firmware 2.1.0 + $t =~ /^\d+\.\d+\.\d+/ and $$self{CanonFirm} = 4, return undef; + $self->Warn('Unrecognized CameraInfo1DX firmware version'); + $$self{CanonFirm} = 0; + return undef; # not a real tag + }, + }, + 0x03 => { %ciFNumber }, + 0x04 => { %ciExposureTime }, + 0x06 => { %ciISO }, + 0x1b => { %ciCameraTemperature, + Hook => '$varSize -= 3 if $$self{CanonFirm} < 3', + }, + 0x23 => { %ciFocalLength }, + 0x7d => { + Name => 'CameraOrientation', + PrintConv => { + 0 => 'Horizontal (normal)', + 1 => 'Rotate 90 CW', + 2 => 'Rotate 270 CW', + }, + }, + 0x8c => { + Name => 'FocusDistanceUpper', + %focusDistanceByteSwap, + }, + 0x8e => { + Name => 'FocusDistanceLower', + %focusDistanceByteSwap, + Hook => '$varSize -= 4 if $$self{CanonFirm} < 3; $varSize += 5 if $$self{CanonFirm} == 4', + }, + 0xbc => { + Name => 'WhiteBalance', + Format => 'int16u', + SeparateTable => 1, + PrintConv => \%canonWhiteBalance, + }, + 0xc0 => { + Name => 'ColorTemperature', + Format => 'int16u', + }, + 0xf4 => { + Name => 'PictureStyle', + Format => 'int8u', + Flags => ['PrintHex','SeparateTable'], + PrintConv => \%pictureStyles, + }, + 0x1a7 => { + Name => 'LensType', + Format => 'int16uRev', # value is big-endian + SeparateTable => 1, + ValueConvInv => 'int($val)', # (must truncate decimal part) + PrintConv => \%canonLensTypes, + }, + 0x1a9 => { %ciMinFocal }, + 0x1ab => { %ciMaxFocal, + # add another offset of -8 for firmware 5.7.1, and a large offset + # to effectively abort processing for unknown firmware + Hook => '$varSize += ($$self{CanonFirm} ? -8 : 0x10000) if $$self{CanonFirm} < 2', + }, + 0x280 => { + Name => 'FirmwareVersion', + Format => 'string[6]', + Writable => 0, + }, + 0x2d0 => { # (doesn't seem to work for firmware 2.0.3 - PH) + Name => 'FileIndex', + Groups => { 2 => 'Image' }, + Format => 'int32u', + ValueConv => '$val + 1', + ValueConvInv => '$val - 1', + }, + 0x2dc => { #(NC) + Name => 'DirectoryIndex', + Groups => { 2 => 'Image' }, + Format => 'int32u', + ValueConv => '$val - 1', + ValueConvInv => '$val + 1', + }, + 0x3f4 => { + Name => 'PictureStyleInfo', + SubDirectory => { TagTable => 'Image::ExifTool::Canon::PSInfo2' }, + }, +); + +# Camera information for 5D (MakerNotes tag 0x0d) +# (ref 12 unless otherwise noted) +%Image::ExifTool::Canon::CameraInfo5D = ( + %binaryDataAttrs, + FORMAT => 'int8s', + FIRST_ENTRY => 0, + PRIORITY => 0, + GROUPS => { 0 => 'MakerNotes', 2 => 'Camera' }, + NOTES => 'CameraInfo tags for the EOS 5D.', + 0x03 => { %ciFNumber }, #PH + 0x04 => { %ciExposureTime }, #9 + 0x06 => { %ciISO }, #PH + 0x0c => { #9 + Name => 'LensType', + Format => 'int16uRev', # value is big-endian + SeparateTable => 1, + RawConv => '$val ? $val : undef', # don't use if value is zero + ValueConvInv => 'int($val)', # (must truncate decimal part) + PrintConv => \%canonLensTypes, + }, + 0x17 => { %ciCameraTemperature }, #PH + 0x1b => { %ciMacroMagnification }, #PH + 0x27 => { #PH + Name => 'CameraOrientation', + PrintConv => { + 0 => 'Horizontal (normal)', + 1 => 'Rotate 90 CW', + 2 => 'Rotate 270 CW', + }, + }, + 0x28 => { %ciFocalLength }, #15 + 0x38 => { + Name => 'AFPointsInFocus5D', + Format => 'int16uRev', + PrintConvColumns => 2, + PrintConv => { 0 => '(none)', + BITMASK => { + 0 => 'Center', + 1 => 'Top', + 2 => 'Bottom', + 3 => 'Upper-left', + 4 => 'Upper-right', + 5 => 'Lower-left', + 6 => 'Lower-right', + 7 => 'Left', + 8 => 'Right', + 9 => 'AI Servo1', + 10 => 'AI Servo2', + 11 => 'AI Servo3', + 12 => 'AI Servo4', + 13 => 'AI Servo5', + 14 => 'AI Servo6', + }, + }, + }, + 0x54 => { #15 + Name => 'WhiteBalance', + Format => 'int16u', + SeparateTable => 1, + PrintConv => \%canonWhiteBalance, + }, + 0x58 => { #15 + Name => 'ColorTemperature', + Format => 'int16u', + }, + 0x6c => { + Name => 'PictureStyle', + Format => 'int8u', + Flags => ['PrintHex','SeparateTable'], + PrintConv => \%pictureStyles, + }, + 0x93 => { %ciMinFocal }, #15 + 0x95 => { %ciMaxFocal }, #15 + 0x97 => { #15 + Name => 'LensType', + Format => 'int16uRev', # value is big-endian + SeparateTable => 1, + ValueConvInv => 'int($val)', # (must truncate decimal part) + PrintConv => \%canonLensTypes, + }, + 0xa4 => { #PH + Name => 'FirmwareRevision', + Format => 'string[8]', + }, + 0xac => { #PH + Name => 'ShortOwnerName', + Format => 'string[16]', + }, + 0xcc => { #PH (NC) + Name => 'DirectoryIndex', + Groups => { 2 => 'Image' }, + Format => 'int32u', + }, + 0xd0 => { + Name => 'FileIndex', + Format => 'int16u', + Groups => { 2 => 'Image' }, + ValueConv => '$val + 1', + ValueConvInv => '$val - 1', + }, + 0xe8 => 'ContrastStandard', + 0xe9 => 'ContrastPortrait', + 0xea => 'ContrastLandscape', + 0xeb => 'ContrastNeutral', + 0xec => 'ContrastFaithful', + 0xed => 'ContrastMonochrome', + 0xee => 'ContrastUserDef1', + 0xef => 'ContrastUserDef2', + 0xf0 => 'ContrastUserDef3', + # sharpness values are 0-7 + 0xf1 => 'SharpnessStandard', + 0xf2 => 'SharpnessPortrait', + 0xf3 => 'SharpnessLandscape', + 0xf4 => 'SharpnessNeutral', + 0xf5 => 'SharpnessFaithful', + 0xf6 => 'SharpnessMonochrome', + 0xf7 => 'SharpnessUserDef1', + 0xf8 => 'SharpnessUserDef2', + 0xf9 => 'SharpnessUserDef3', + 0xfa => 'SaturationStandard', + 0xfb => 'SaturationPortrait', + 0xfc => 'SaturationLandscape', + 0xfd => 'SaturationNeutral', + 0xfe => 'SaturationFaithful', + 0xff => { + Name => 'FilterEffectMonochrome', + PrintConv => { + 0 => 'None', + 1 => 'Yellow', + 2 => 'Orange', + 3 => 'Red', + 4 => 'Green', + -559038737 => 'n/a', # (0xdeadbeef) + }, + }, + 0x100 => 'SaturationUserDef1', + 0x101 => 'SaturationUserDef2', + 0x102 => 'SaturationUserDef3', + 0x103 => 'ColorToneStandard', + 0x104 => 'ColorTonePortrait', + 0x105 => 'ColorToneLandscape', + 0x106 => 'ColorToneNeutral', + 0x107 => 'ColorToneFaithful', + 0x108 => { + Name => 'ToningEffectMonochrome', + PrintConv => { + 0 => 'None', + 1 => 'Sepia', + 2 => 'Blue', + 3 => 'Purple', + 4 => 'Green', + -559038737 => 'n/a', # (0xdeadbeef) + }, + }, + 0x109 => 'ColorToneUserDef1', + 0x10a => 'ColorToneUserDef2', + 0x10b => 'ColorToneUserDef3', + 0x10c => { + Name => 'UserDef1PictureStyle', + Format => 'int16u', + PrintHex => 1, # (only needed for one tag) + SeparateTable => 'UserDefStyle', + PrintConv => \%userDefStyles, + }, + 0x10e => { + Name => 'UserDef2PictureStyle', + Format => 'int16u', + SeparateTable => 'UserDefStyle', + PrintConv => \%userDefStyles, + }, + 0x110 => { + Name => 'UserDef3PictureStyle', + Format => 'int16u', + SeparateTable => 'UserDefStyle', + PrintConv => \%userDefStyles, + }, + 0x11c => { + Name => 'TimeStamp', + Format => 'int32u', + Groups => { 2 => 'Time' }, + Shift => 'Time', + RawConv => '$val ? $val : undef', + ValueConv => 'ConvertUnixTime($val)', + ValueConvInv => 'GetUnixTime($val)', + PrintConv => '$self->ConvertDateTime($val)', + PrintConvInv => '$self->InverseDateTime($val)', + }, +); + +# Camera information for 5D Mark II (MakerNotes tag 0x0d) (ref PH) +%Image::ExifTool::Canon::CameraInfo5DmkII = ( + %binaryDataAttrs, + FORMAT => 'int8u', + FIRST_ENTRY => 0, + PRIORITY => 0, + DATAMEMBER => [ 0x00, 0xea ], + IS_SUBDIR => [ 0x2f7 ], + GROUPS => { 0 => 'MakerNotes', 2 => 'Camera' }, + NOTES => q{ + CameraInfo tags for the EOS 5D Mark II. Indices shown are for firmware + version 1.0.6, but they may be different for other firmware versions. + }, + 0x00 => { + Name => 'FirmwareVersionLookAhead', + Hidden => 1, + # look ahead to check location of FirmwareVersion string + Format => 'undef[0x184]', + RawConv => q{ + my $t = substr($val, 0x15a, 6); # 1 = firmware 3.4.6/3.6.1 + $t =~ /^\d+\.\d+\.\d+/ and $$self{CanonFirm} = 1, return undef; + $t = substr($val, 0x17e, 6); # 2 = firmware 4.1.1/1.0.6 + $t =~ /^\d+\.\d+\.\d+/ and $$self{CanonFirm} = 2, return undef; + $self->Warn('Unrecognized CameraInfo5DmkII firmware version'); + $$self{CanonFirm} = 0; + return undef; # not a real tag + }, + }, + 0x03 => { %ciFNumber }, + 0x04 => { %ciExposureTime }, + 0x06 => { %ciISO }, + 0x07 => { + Name => 'HighlightTonePriority', + PrintConv => \%offOn, + }, + 0x1b => { %ciMacroMagnification }, #PH + 0x15 => { #PH (580 EX II) + Name => 'FlashMeteringMode', + PrintConv => { + 0 => 'E-TTL', + 3 => 'TTL', + 4 => 'External Auto', + 5 => 'External Manual', + 6 => 'Off', + }, + }, + 0x19 => { %ciCameraTemperature }, #36 + # 0x1b, 0x1c, 0x1d - same as FileInfo 0x10 - PH + 0x1e => { %ciFocalLength }, + 0x31 => { + Name => 'CameraOrientation', + PrintConv => { + 0 => 'Horizontal (normal)', + 1 => 'Rotate 90 CW', + 2 => 'Rotate 270 CW', + }, + }, + 0x50 => { + Name => 'FocusDistanceUpper', + %focusDistanceByteSwap, + }, + 0x52 => { + Name => 'FocusDistanceLower', + %focusDistanceByteSwap, + }, + 0x6f => { + Name => 'WhiteBalance', + Format => 'int16u', + SeparateTable => 1, + PrintConv => \%canonWhiteBalance, + }, + 0x73 => { + Name => 'ColorTemperature', + Format => 'int16u', + }, + 0xa7 => { + Name => 'PictureStyle', + Format => 'int8u', + Flags => ['PrintHex','SeparateTable'], + PrintConv => \%pictureStyles, + }, + 0xbd => { + Name => 'HighISONoiseReduction', + PrintConv => { + 0 => 'Standard', + 1 => 'Low', + 2 => 'Strong', + 3 => 'Off', + }, + }, + 0xbf => { + Name => 'AutoLightingOptimizer', + PrintConv => { + 0 => 'Standard', + 1 => 'Low', + 2 => 'Strong', + 3 => 'Off', + }, + }, + 0xe6 => { + Name => 'LensType', + Format => 'int16uRev', # value is big-endian + SeparateTable => 1, + ValueConvInv => 'int($val)', # (must truncate decimal part) + PrintConv => \%canonLensTypes, + }, + 0xe8 => { %ciMinFocal }, + 0xea => { %ciMaxFocal, + # offset changes after this for different firmware versions + Hook => '$varSize += ($$self{CanonFirm} ? -36 : 0x10000) if $$self{CanonFirm} < 2', + }, + 0x17e => { + Name => 'FirmwareVersion', + Format => 'string[6]', + Writable => 0, # not writable for logic reasons + # some firmwares have a null instead of a space after the version number + RawConv => '$val=~/^\d+\.\d+\.\d+\s*$/ ? $val : undef', + }, + 0x1bb => { + Name => 'FileIndex', + Groups => { 2 => 'Image' }, + Format => 'int32u', + ValueConv => '$val + 1', + ValueConvInv => '$val - 1', + }, + 0x1c7 => { #(NC) + Name => 'DirectoryIndex', + Groups => { 2 => 'Image' }, + Format => 'int32u', + ValueConv => '$val - 1', + ValueConvInv => '$val + 1', + }, + 0x2f7 => { #48 + Name => 'PictureStyleInfo', + SubDirectory => { TagTable => 'Image::ExifTool::Canon::PSInfo' }, + }, +); + +# Camera information for 5D Mark III (MakerNotes tag 0x0d) (ref PH) +%Image::ExifTool::Canon::CameraInfo5DmkIII = ( + %binaryDataAttrs, + FORMAT => 'int8u', + FIRST_ENTRY => 0, + PRIORITY => 0, + DATAMEMBER => [ 0x00, 0x1b, 0x23, 0x8e, 0x157 ], + IS_SUBDIR => [ 0x3b0 ], + GROUPS => { 0 => 'MakerNotes', 2 => 'Camera' }, + NOTES => q{ + CameraInfo tags for the EOS 5D Mark III. Indices shown are for firmware + versions 1.0.x, but they may be different for other firmware versions. + }, + 0x00 => { + Name => 'FirmwareVersionLookAhead', + Hidden => 1, + # look ahead to check location of FirmwareVersion string + Format => 'undef[0x24d]', + RawConv => q{ + my $t = substr($val, 0x22c, 6); # 1 = firmware 4.5.4/4.5.6 + $t =~ /^\d+\.\d+\.\d+/ and $$self{CanonFirm} = 1, return undef; + $t = substr($val, 0x22d, 6); # 2 = firmware 5.2.2/5.3.1/5.4.2 + $t =~ /^\d+\.\d+\.\d+/ and $$self{CanonFirm} = 2, return undef; + $t = substr($val, 0x23c, 6); # 3 = firmware 1.0.3/1.0.7 + $t =~ /^\d+\.\d+\.\d+/ and $$self{CanonFirm} = 3, return undef; + $t = substr($val, 0x242, 6); # 4 = firmware 1.2.1 + $t =~ /^\d+\.\d+\.\d+/ and $$self{CanonFirm} = 4, return undef; + $t = substr($val, 0x247, 6); # 5 = firmware 1.3.5 + $t =~ /^\d+\.\d+\.\d+/ and $$self{CanonFirm} = 5, return undef; + $self->Warn('Unrecognized CameraInfo5DmkIII firmware version'); + $$self{CanonFirm} = 0; + return undef; # not a real tag + }, + }, + 0x03 => { %ciFNumber }, + 0x04 => { %ciExposureTime }, + 0x06 => { %ciISO }, + 0x1b => { %ciCameraTemperature, + # decrement $varSize for missing byte after this tag with firmware 5.x and earlier + # (and add large offset to effectively abort processing if unknown firmware) + Hook => '$varSize += ($$self{CanonFirm} ? -1 : 0x10000) if $$self{CanonFirm} < 3', + }, + 0x23 => { %ciFocalLength, + Hook => q{ + $varSize -= 3 if $$self{CanonFirm} == 1; + $varSize -= 2 if $$self{CanonFirm} == 2; + $varSize += 6 if $$self{CanonFirm} >= 4; + }, + }, + 0x7d => { + Name => 'CameraOrientation', + PrintConv => { + 0 => 'Horizontal (normal)', + 1 => 'Rotate 90 CW', + 2 => 'Rotate 270 CW', + }, + }, + 0x8c => { + Name => 'FocusDistanceUpper', + %focusDistanceByteSwap, + }, + 0x8e => { + Name => 'FocusDistanceLower', + %focusDistanceByteSwap, + Hook => q{ + $varSize -= 4 if $$self{CanonFirm} < 3; + $varSize += 5 if $$self{CanonFirm} > 4; + }, + }, + 0xbc => { + Name => 'WhiteBalance', + Format => 'int16u', + SeparateTable => 1, + PrintConv => \%canonWhiteBalance, + }, + 0xc0 => { + Name => 'ColorTemperature', + Format => 'int16u', + }, + 0xf4 => { + Name => 'PictureStyle', + Format => 'int8u', + Flags => ['PrintHex','SeparateTable'], + PrintConv => \%pictureStyles, + }, + 0x153 => { + Name => 'LensType', + Format => 'int16uRev', # value is big-endian + SeparateTable => 1, + ValueConvInv => 'int($val)', # (must truncate decimal part) + PrintConv => \%canonLensTypes, + }, + 0x155 => { %ciMinFocal }, + 0x157 => { %ciMaxFocal, + Hook => '$varSize -= 8 if $$self{CanonFirm} < 3', + }, + 0x164 => { + Name => 'LensSerialNumber', + Format => 'undef[5]', + Priority => 0, + ValueConv => 'unpack("H*",$val)', + ValueConvInv => 'length($val) < 10 and $val = 0 x (10-length($val)) . $val; pack("H*",$val)', + }, + 0x23c => { + Name => 'FirmwareVersion', + Format => 'string[6]', + Writable => 0, + }, + # the 5DmkIII has "User setting1" and "User setting2" file naming options: + # - with "User setting1" 4 characters are selectable + # - with "User setting2", 3 characters are selectable, and the 4th character + # - in the file name corresponds to the image size: + # L=large, M=medium, S=small1, T=small2, U=small3, _=movie + # - as shipped, the first 4 characters of the file name are unique to the camera + 0x28c => { # used for file names like IMG_xxxx.JPG + Name => 'FileIndex', + Groups => { 2 => 'Image' }, + Format => 'int32u', + ValueConv => '$val + 1', + ValueConvInv => '$val - 1', + }, + 0x290 => { # used for file names like 2F0Axxxx.JPG and 6T3Cxxxx.JPG + Name => 'FileIndex2', + Groups => { 2 => 'Image' }, + Format => 'int32u', + ValueConv => '$val + 1', + ValueConvInv => '$val - 1', + }, + 0x298 => { #(NC) + Name => 'DirectoryIndex', + Groups => { 2 => 'Image' }, + Format => 'int32u', + ValueConv => '$val - 1', + ValueConvInv => '$val + 1', + }, + 0x29c => { #(NC) + Name => 'DirectoryIndex2', + Groups => { 2 => 'Image' }, + Format => 'int32u', + ValueConv => '$val - 1', + ValueConvInv => '$val + 1', + }, + 0x3b0 => { + Name => 'PictureStyleInfo', + SubDirectory => { TagTable => 'Image::ExifTool::Canon::PSInfo2' }, + }, +); + +# Camera information for 6D (MakerNotes tag 0x0d) (ref PH) +%Image::ExifTool::Canon::CameraInfo6D = ( + %binaryDataAttrs, + FORMAT => 'int8u', + FIRST_ENTRY => 0, + PRIORITY => 0, + IS_SUBDIR => [ 0x3c6 ], + GROUPS => { 0 => 'MakerNotes', 2 => 'Camera' }, + NOTES => 'CameraInfo tags for the EOS 6D.', + 0x03 => { %ciFNumber }, + 0x04 => { %ciExposureTime }, + 0x06 => { %ciISO }, + 0x1b => { %ciCameraTemperature }, + 0x23 => { %ciFocalLength }, + 0x83 => { # (5DmkIII + 6) + Name => 'CameraOrientation', + PrintConv => { + 0 => 'Horizontal (normal)', + 1 => 'Rotate 90 CW', + 2 => 'Rotate 270 CW', + }, + }, + 0x92 => { # (5DmkIII + 6) + Name => 'FocusDistanceUpper', + %focusDistanceByteSwap, + }, + 0x94 => { # (5DmkIII + 6) + Name => 'FocusDistanceLower', + %focusDistanceByteSwap, + }, + 0xc2 => { # (5DmkIII + 6) + Name => 'WhiteBalance', + Format => 'int16u', + SeparateTable => 1, + PrintConv => \%canonWhiteBalance, + }, + 0xc6 => { # (5DmkIII + 6) + Name => 'ColorTemperature', + Format => 'int16u', + }, + 0xfa => { # (5DmkIII + 6) + Name => 'PictureStyle', + Format => 'int8u', + Flags => ['PrintHex','SeparateTable'], + PrintConv => \%pictureStyles, + }, + 0x161 => { # (5DmkIII + 0x0e) + Name => 'LensType', + Format => 'int16uRev', # value is big-endian + SeparateTable => 1, + ValueConvInv => 'int($val)', # (must truncate decimal part) + PrintConv => \%canonLensTypes, + }, + 0x163 => { %ciMinFocal }, # (5DmkIII + 0x0e) + 0x165 => { %ciMaxFocal }, # (5DmkIII + 0x0e) + 0x256 => { # (5DmkIII + 0x1a) + Name => 'FirmwareVersion', + Format => 'string[6]', + Writable => 0, + }, + 0x2aa => { # (5DmkIII + 0x16 or 0x1e) + Name => 'FileIndex', + Groups => { 2 => 'Image' }, + Format => 'int32u', + ValueConv => '$val + 1', + ValueConvInv => '$val - 1', + }, + 0x2b6 => { #(NC) (5DmkIII + 0x16 or 0x1e) + Name => 'DirectoryIndex', + Groups => { 2 => 'Image' }, + Format => 'int32u', + ValueConv => '$val - 1', + ValueConvInv => '$val + 1', + }, + 0x3c6 => { # (5DmkIII + 0x16) + Name => 'PictureStyleInfo', + SubDirectory => { TagTable => 'Image::ExifTool::Canon::PSInfo2' }, + }, +); + +# Camera information for 7D (MakerNotes tag 0x0d) (ref PH) +%Image::ExifTool::Canon::CameraInfo7D = ( + %binaryDataAttrs, + FORMAT => 'int8u', + FIRST_ENTRY => 0, + PRIORITY => 0, + DATAMEMBER => [ 0x00, 0x1e ], + IS_SUBDIR => [ 0x327 ], + GROUPS => { 0 => 'MakerNotes', 2 => 'Camera' }, + NOTES => q{ + CameraInfo tags for the EOS 7D. Indices shown are for firmware versions + 1.0.x, but they may be different for other firmware versions. + }, + 0x00 => { + Name => 'FirmwareVersionLookAhead', + Hidden => 1, + # look ahead to check location of FirmwareVersion string + Format => 'undef[0x1b2]', + RawConv => q{ + my $t = substr($val, 0x1a8, 6); # 1 = firmware 3.7.5 + $t =~ /^\d+\.\d+\.\d+/ and $$self{CanonFirm} = 1, return undef; + $t = substr($val, 0x1ac, 6); # 2 = firmware 1.0.7/1.0.8/1.1.0/1.2.1/1.2.2 + $t =~ /^\d+\.\d+\.\d+/ and $$self{CanonFirm} = 2, return undef; + $self->Warn('Unrecognized CameraInfo7D firmware version'); + $$self{CanonFirm} = 0; + return undef; # not a real tag + }, + }, + 0x03 => { %ciFNumber }, + 0x04 => { %ciExposureTime }, + 0x06 => { %ciISO }, + 0x07 => { + Name => 'HighlightTonePriority', + PrintConv => \%offOn, + }, + 0x08 => { #37 + Name => 'MeasuredEV2', + Description => 'Measured EV 2', + RawConv => '$val ? $val : undef', + ValueConv => '$val / 8 - 6', + ValueConvInv => 'int(($val + 6) * 8 + 0.5)', + }, + 0x09 => { #37 + Name => 'MeasuredEV', + Description => 'Measured EV', + RawConv => '$val ? $val : undef', + ValueConv => '$val / 8 - 6', + ValueConvInv => 'int(($val + 6) * 8 + 0.5)', + }, + 0x15 => { #PH (580 EX II) + Name => 'FlashMeteringMode', + PrintConv => { + 0 => 'E-TTL', + 3 => 'TTL', + 4 => 'External Auto', + 5 => 'External Manual', + 6 => 'Off', + }, + }, + 0x19 => { %ciCameraTemperature }, + 0x1e => { %ciFocalLength, + Hook => '$varSize += ($$self{CanonFirm} ? -4 : 0x10000) if $$self{CanonFirm} < 2', + }, + 0x35 => { + Name => 'CameraOrientation', + PrintConv => { + 0 => 'Horizontal (normal)', + 1 => 'Rotate 90 CW', + 2 => 'Rotate 270 CW', + }, + }, + 0x54 => { + Name => 'FocusDistanceUpper', + %focusDistanceByteSwap, + }, + 0x56 => { + Name => 'FocusDistanceLower', + %focusDistanceByteSwap, + }, + 0x77 => { + Name => 'WhiteBalance', + Format => 'int16u', + SeparateTable => 1, + PrintConv => \%canonWhiteBalance, + }, + 0x7b => { + Name => 'ColorTemperature', + Format => 'int16u', + }, + 0xaf => { + Name => 'CameraPictureStyle', + PrintHex => 1, + PrintConv => { + 0x81 => 'Standard', + 0x82 => 'Portrait', + 0x83 => 'Landscape', + 0x84 => 'Neutral', + 0x85 => 'Faithful', + 0x86 => 'Monochrome', + 0x21 => 'User Defined 1', + 0x22 => 'User Defined 2', + 0x23 => 'User Defined 3', + }, + }, + 0xc9 => { + Name => 'HighISONoiseReduction', + PrintConv => { + 0 => 'Standard', + 1 => 'Low', + 2 => 'Strong', + 3 => 'Off', + }, + }, + 0x112 => { + Name => 'LensType', + Format => 'int16uRev', # value is big-endian + SeparateTable => 1, + ValueConvInv => 'int($val)', # (must truncate decimal part) + PrintConv => \%canonLensTypes, + }, + 0x114 => { %ciMinFocal }, + 0x116 => { %ciMaxFocal }, + 0x1ac => { + Name => 'FirmwareVersion', + Format => 'string[6]', + Writable => 0, # not writable for logic reasons + # some firmwares have a null instead of a space after the version number + RawConv => '$val=~/^\d+\.\d+\.\d+\s*$/ ? $val : undef', + }, + 0x1eb => { + Name => 'FileIndex', + Groups => { 2 => 'Image' }, + Format => 'int32u', + ValueConv => '$val + 1', + ValueConvInv => '$val - 1', + }, + 0x1f7 => { #(NC) + Name => 'DirectoryIndex', + Groups => { 2 => 'Image' }, + Format => 'int32u', + ValueConv => '$val - 1', + ValueConvInv => '$val + 1', + }, + 0x327 => { #48 + Name => 'PictureStyleInfo', + SubDirectory => { TagTable => 'Image::ExifTool::Canon::PSInfo' }, + }, +); + +# Canon camera information for 40D (MakerNotes tag 0x0d) (ref PH) +%Image::ExifTool::Canon::CameraInfo40D = ( + %binaryDataAttrs, + FORMAT => 'int8u', + FIRST_ENTRY => 0, + PRIORITY => 0, + IS_SUBDIR => [ 0x25b ], + GROUPS => { 0 => 'MakerNotes', 2 => 'Camera' }, + NOTES => 'CameraInfo tags for the EOS 40D.', + 0x03 => { %ciFNumber }, #PH + 0x04 => { %ciExposureTime }, #PH + 0x06 => { %ciISO }, #PH + 0x15 => { #PH (580 EX II) + Name => 'FlashMeteringMode', + PrintConv => { + 0 => 'E-TTL', + 3 => 'TTL', + 4 => 'External Auto', + 5 => 'External Manual', + 6 => 'Off', + }, + }, + 0x18 => { %ciCameraTemperature }, #36 + 0x1b => { %ciMacroMagnification }, #PH + 0x1d => { %ciFocalLength }, #PH + 0x30 => { #20 + Name => 'CameraOrientation', + PrintConv => { + 0 => 'Horizontal (normal)', + 1 => 'Rotate 90 CW', + 2 => 'Rotate 270 CW', + }, + }, + 0x43 => { #21/24 + Name => 'FocusDistanceUpper', + # this is very odd (little-endian number on odd boundary), + # but it does seem to work better with my sample images - PH + %focusDistanceByteSwap, + }, + 0x45 => { #21/24 + Name => 'FocusDistanceLower', + %focusDistanceByteSwap, + }, + 0x6f => { #15 + Name => 'WhiteBalance', + Format => 'int16u', + PrintConv => \%canonWhiteBalance, + SeparateTable => 1, + }, + 0x73 => { #15 + Name => 'ColorTemperature', + Format => 'int16u', + }, + 0xd6 => { #15 + Name => 'LensType', + Format => 'int16uRev', # value is big-endian + SeparateTable => 1, + ValueConvInv => 'int($val)', # (must truncate decimal part) + PrintConv => \%canonLensTypes, + }, + 0xd8 => { %ciMinFocal }, #15 + 0xda => { %ciMaxFocal }, #15 + 0xff => { #15 + Name => 'FirmwareVersion', + Format => 'string[6]', + }, + 0x133 => { #27 + Name => 'FileIndex', + Groups => { 2 => 'Image' }, + Format => 'int32u', + Notes => 'combined with DirectoryIndex to give the Composite FileNumber tag', + ValueConv => '$val + 1', + ValueConvInv => '$val - 1', + }, + 0x13f => { #27 + Name => 'DirectoryIndex', + Groups => { 2 => 'Image' }, + Format => 'int32u', + ValueConv => '$val - 1', # yes, minus (opposite to FileIndex) + ValueConvInv => '$val + 1', + }, + 0x25b => { + Name => 'PictureStyleInfo', + SubDirectory => { TagTable => 'Image::ExifTool::Canon::PSInfo' }, + }, + 0x92b => { #33 + Name => 'LensModel', + Format => 'string[64]', + }, +); + +# Canon camera information for 50D (MakerNotes tag 0x0d) (ref PH) +%Image::ExifTool::Canon::CameraInfo50D = ( + %binaryDataAttrs, + FORMAT => 'int8u', + FIRST_ENTRY => 0, + PRIORITY => 0, + DATAMEMBER => [ 0x00, 0xee ], + IS_SUBDIR => [ 0x2d7 ], + GROUPS => { 0 => 'MakerNotes', 2 => 'Camera' }, + NOTES => q{ + CameraInfo tags for the EOS 50D. Indices shown are for firmware versions + 1.0.x, but they may be different for other firmware versions. + }, + 0x00 => { + Name => 'FirmwareVersionLookAhead', + Hidden => 1, + # look ahead to check location of FirmwareVersion string + Format => 'undef[0x164]', + RawConv => q{ + my $t = substr($val, 0x15a, 6); # 1 = firmware 2.6.1 + $t =~ /^\d+\.\d+\.\d+/ and $$self{CanonFirm} = 1, return undef; + $t = substr($val, 0x15e, 6); # 2 = firmware 2.9.1/3.1.1/1.0.2/1.0.3 + $t =~ /^\d+\.\d+\.\d+/ and $$self{CanonFirm} = 2, return undef; + $self->Warn('Unrecognized CameraInfo50D firmware version'); + $$self{CanonFirm} = 0; + return undef; # not a real tag + }, + }, + 0x03 => { %ciFNumber }, + 0x04 => { %ciExposureTime }, + 0x06 => { %ciISO }, + 0x07 => { + Name => 'HighlightTonePriority', + PrintConv => \%offOn, + }, + 0x15 => { #PH (580 EX II) + Name => 'FlashMeteringMode', + PrintConv => { + 0 => 'E-TTL', + 3 => 'TTL', + 4 => 'External Auto', + 5 => 'External Manual', + 6 => 'Off', + }, + }, + 0x19 => { %ciCameraTemperature }, #36 + 0x1e => { %ciFocalLength }, + 0x31 => { + Name => 'CameraOrientation', + PrintConv => { + 0 => 'Horizontal (normal)', + 1 => 'Rotate 90 CW', + 2 => 'Rotate 270 CW', + }, + }, + 0x50 => { #33 + Name => 'FocusDistanceUpper', + %focusDistanceByteSwap, + }, + 0x52 => { #33 + Name => 'FocusDistanceLower', + %focusDistanceByteSwap, + }, + 0x6f => { + Name => 'WhiteBalance', + Format => 'int16u', + SeparateTable => 1, + PrintConv => \%canonWhiteBalance, + }, + 0x73 => { #33 + Name => 'ColorTemperature', + Format => 'int16u', + }, + 0xa7 => { + Name => 'PictureStyle', + Format => 'int8u', + Flags => ['PrintHex','SeparateTable'], + PrintConv => \%pictureStyles, + }, + 0xbd => { + Name => 'HighISONoiseReduction', + PrintConv => { + 0 => 'Standard', + 1 => 'Low', + 2 => 'Strong', + 3 => 'Off', + }, + }, + 0xbf => { + Name => 'AutoLightingOptimizer', + PrintConv => { + 0 => 'Standard', + 1 => 'Low', + 2 => 'Strong', + 3 => 'Off', + }, + }, + 0xea => { #33 + Name => 'LensType', + Format => 'int16uRev', # value is big-endian + SeparateTable => 1, + ValueConvInv => 'int($val)', # (must truncate decimal part) + PrintConv => \%canonLensTypes, + }, + 0xec => { %ciMinFocal }, + 0xee => { %ciMaxFocal, + Hook => '$varSize += ($$self{CanonFirm} ? -4 : 0x10000) if $$self{CanonFirm} < 2', + }, + 0x15e => { #33 + Name => 'FirmwareVersion', + Format => 'string[6]', + Writable => 0, + }, + 0x19b => { + Name => 'FileIndex', + Groups => { 2 => 'Image' }, + Format => 'int32u', + ValueConv => '$val + 1', + ValueConvInv => '$val - 1', + }, + 0x1a7 => { #(NC) + Name => 'DirectoryIndex', + Groups => { 2 => 'Image' }, + Format => 'int32u', + ValueConv => '$val - 1', + ValueConvInv => '$val + 1', + }, + 0x2d7 => { + Name => 'PictureStyleInfo', + SubDirectory => { TagTable => 'Image::ExifTool::Canon::PSInfo' }, + }, +); + +# Canon camera information for 60D/1200D (MakerNotes tag 0x0d) (ref PH) +# NOTE: Can probably borrow more 50D tags here, possibly with an offset +%Image::ExifTool::Canon::CameraInfo60D = ( + %binaryDataAttrs, + FORMAT => 'int8u', + FIRST_ENTRY => 0, + PRIORITY => 0, + IS_SUBDIR => [ 0x2f9, 0x321 ], + GROUPS => { 0 => 'MakerNotes', 2 => 'Camera' }, + NOTES => 'CameraInfo tags for the EOS 60D and 1200D.', + 0x03 => { %ciFNumber }, + 0x04 => { %ciExposureTime }, + 0x06 => { %ciISO }, + 0x19 => { %ciCameraTemperature }, + 0x1e => { %ciFocalLength }, + 0x36 => { + Name => 'CameraOrientation', + Condition => '$$self{Model} =~ /EOS 60D$/', #(NC) + Notes => '60D only', + PrintConv => { + 0 => 'Horizontal (normal)', + 1 => 'Rotate 90 CW', + 2 => 'Rotate 270 CW', + }, + }, + 0x55 => { + Name => 'FocusDistanceUpper', + Condition => '$$self{Model} =~ /EOS 60D$/', + Notes => '60D only', + %focusDistanceByteSwap, + }, + 0x57 => { + Name => 'FocusDistanceLower', + Condition => '$$self{Model} =~ /EOS 60D$/', + Notes => '60D only', + %focusDistanceByteSwap, + }, + 0x7d => { + Name => 'ColorTemperature', + Condition => '$$self{Model} =~ /EOS 60D$/', + Notes => '60D only', + Format => 'int16u', + }, + 0xe8 => { + Name => 'LensType', + Format => 'int16uRev', # value is big-endian + SeparateTable => 1, + ValueConvInv => 'int($val)', # (must truncate decimal part) + PrintConv => \%canonLensTypes, + }, + 0xea => { %ciMinFocal }, + 0xec => { %ciMaxFocal }, + 0x199 => { # (at this location for 60D firmware 2.8.1/1.0.5, and 1200D 3.3.1/1.0.0) + Name => 'FirmwareVersion', + Format => 'string[6]', + Writable => 0, + }, + 0x1d9 => { + Name => 'FileIndex', + Condition => '$$self{Model} =~ /EOS 60D$/', + Notes => '60D only', + Groups => { 2 => 'Image' }, + Format => 'int32u', + ValueConv => '$val + 1', + ValueConvInv => '$val - 1', + }, + 0x1e5 => { #(NC) + Name => 'DirectoryIndex', + Condition => '$$self{Model} =~ /EOS 60D$/', + Notes => '60D only', + Groups => { 2 => 'Image' }, + Format => 'int32u', + ValueConv => '$val - 1', + ValueConvInv => '$val + 1', + }, + 0x2f9 => { + Name => 'PictureStyleInfo', + Condition => '$$self{Model} =~ /\b(1200D|REBEL T5|Kiss X70)\b/', + Notes => '1200D', + SubDirectory => { TagTable => 'Image::ExifTool::Canon::PSInfo2' }, + }, + 0x321 => { + Name => 'PictureStyleInfo', + Condition => '$$self{Model} =~ /EOS 60D$/', + Notes => '60D', + SubDirectory => { TagTable => 'Image::ExifTool::Canon::PSInfo2' }, + }, +); + +# Canon camera information for 70D (MakerNotes tag 0x0d) (ref PH) +%Image::ExifTool::Canon::CameraInfo70D = ( + %binaryDataAttrs, + FORMAT => 'int8u', + FIRST_ENTRY => 0, + PRIORITY => 0, + IS_SUBDIR => [ 0x3cf ], + GROUPS => { 0 => 'MakerNotes', 2 => 'Camera' }, + NOTES => 'CameraInfo tags for the EOS 70D.', + 0x03 => { %ciFNumber }, + 0x04 => { %ciExposureTime }, + 0x06 => { %ciISO }, + 0x1b => { %ciCameraTemperature }, + 0x23 => { %ciFocalLength }, + # 0x36 - focal length again? + 0x84 => { + Name => 'CameraOrientation', + PrintConv => { + 0 => 'Horizontal (normal)', + 1 => 'Rotate 90 CW', + 2 => 'Rotate 270 CW', + }, + }, + 0x93 => { + Name => 'FocusDistanceUpper', + %focusDistanceByteSwap, + }, + 0x95 => { + Name => 'FocusDistanceLower', + %focusDistanceByteSwap, + }, + 0xc7 => { + Name => 'ColorTemperature', + Format => 'int16u', + }, + 0x166 => { + Name => 'LensType', + Format => 'int16uRev', # value is big-endian + SeparateTable => 1, + ValueConvInv => 'int($val)', # (must truncate decimal part) + PrintConv => \%canonLensTypes, + }, + 0x168 => { %ciMinFocal }, + 0x16a => { %ciMaxFocal }, + 0x25e => { # (at this location for firmware 6.1.2, 1.0.4 and 1.1.1) + Name => 'FirmwareVersion', + Format => 'string[6]', + Writable => 0, + }, + 0x2b3 => { + Name => 'FileIndex', + Groups => { 2 => 'Image' }, + Format => 'int32u', + ValueConv => '$val + 1', + ValueConvInv => '$val - 1', + }, + 0x2bf => { #(NC) + Name => 'DirectoryIndex', + Groups => { 2 => 'Image' }, + Format => 'int32u', + ValueConv => '$val - 1', + ValueConvInv => '$val + 1', + }, + 0x3cf => { #48 + Name => 'PictureStyleInfo', + SubDirectory => { TagTable => 'Image::ExifTool::Canon::PSInfo2' }, + }, +); + +# Canon camera information for 80D (MakerNotes tag 0x0d) (ref PH) +%Image::ExifTool::Canon::CameraInfo80D = ( + %binaryDataAttrs, + FORMAT => 'int8u', + FIRST_ENTRY => 0, + PRIORITY => 0, + GROUPS => { 0 => 'MakerNotes', 2 => 'Camera' }, + NOTES => 'CameraInfo tags for the EOS 70D.', + 0x03 => { %ciFNumber }, + 0x04 => { %ciExposureTime }, + 0x06 => { %ciISO }, + 0x1b => { %ciCameraTemperature }, + 0x23 => { %ciFocalLength }, + 0x96 => { + Name => 'CameraOrientation', + PrintConv => { + 0 => 'Horizontal (normal)', + 1 => 'Rotate 90 CW', + 2 => 'Rotate 270 CW', + }, + }, + 0xa5 => { + Name => 'FocusDistanceUpper', + %focusDistanceByteSwap, + }, + 0xa7 => { + Name => 'FocusDistanceLower', + %focusDistanceByteSwap, + }, + 0x13a => { + Name => 'ColorTemperature', + Format => 'int16u', + }, + 0x189 => { + Name => 'LensType', + Format => 'int16uRev', # value is big-endian + SeparateTable => 1, + ValueConvInv => 'int($val)', # (must truncate decimal part) + PrintConv => \%canonLensTypes, + }, + 0x18b => { %ciMinFocal }, + 0x18d => { %ciMaxFocal }, + 0x45a => { # (at this location for firmware 1.0.1) + Name => 'FirmwareVersion', + Format => 'string[6]', + Writable => 0, + }, + 0x4ae => { + Name => 'FileIndex', + Groups => { 2 => 'Image' }, + Format => 'int32u', + ValueConv => '$val + 1', + ValueConvInv => '$val - 1', + }, + 0x4ba => { #(NC) + Name => 'DirectoryIndex', + Groups => { 2 => 'Image' }, + Format => 'int32u', + ValueConv => '$val - 1', + ValueConvInv => '$val + 1', + }, +); + +# Canon camera information for 450D (MakerNotes tag 0x0d) (ref PH) +%Image::ExifTool::Canon::CameraInfo450D = ( + %binaryDataAttrs, + FORMAT => 'int8u', + FIRST_ENTRY => 0, + PRIORITY => 0, + IS_SUBDIR => [ 0x263 ], + GROUPS => { 0 => 'MakerNotes', 2 => 'Camera' }, + NOTES => 'CameraInfo tags for the EOS 450D.', + 0x03 => { %ciFNumber }, #PH + 0x04 => { %ciExposureTime }, #PH + 0x06 => { %ciISO }, #PH + 0x15 => { #PH (580 EX II) + Name => 'FlashMeteringMode', + PrintConv => { + 0 => 'E-TTL', + 3 => 'TTL', + 4 => 'External Auto', + 5 => 'External Manual', + 6 => 'Off', + }, + }, + 0x18 => { %ciCameraTemperature }, #36 + 0x1b => { %ciMacroMagnification }, #PH + 0x1d => { %ciFocalLength }, #PH + 0x30 => { #20 + Name => 'CameraOrientation', + PrintConv => { + 0 => 'Horizontal (normal)', + 1 => 'Rotate 90 CW', + 2 => 'Rotate 270 CW', + }, + }, + 0x43 => { #20 + Name => 'FocusDistanceUpper', + # this is very odd (little-endian number on odd boundary), + # but it does seem to work better with my sample images - PH + %focusDistanceByteSwap, + }, + 0x45 => { #20 + Name => 'FocusDistanceLower', + %focusDistanceByteSwap, + }, + 0x6f => { #PH + Name => 'WhiteBalance', + Format => 'int16u', + PrintConv => \%canonWhiteBalance, + SeparateTable => 1, + }, + 0x73 => { #PH + Name => 'ColorTemperature', + Format => 'int16u', + }, + 0xde => { #33 + Name => 'LensType', + Format => 'int16uRev', # value is big-endian + SeparateTable => 1, + ValueConvInv => 'int($val)', # (must truncate decimal part) + PrintConv => \%canonLensTypes, + }, + 0x107 => { #PH + Name => 'FirmwareVersion', + Format => 'string[6]', + }, + 0x10f => { #20 + Name => 'OwnerName', + Format => 'string[32]', + }, + 0x133 => { #20 + Name => 'DirectoryIndex', + Groups => { 2 => 'Image' }, + Format => 'int32u', + }, + 0x13f => { #20 + Name => 'FileIndex', + Groups => { 2 => 'Image' }, + Format => 'int32u', + ValueConv => '$val + 1', + ValueConvInv => '$val - 1', + }, + 0x263 => { #PH + Name => 'PictureStyleInfo', + SubDirectory => { TagTable => 'Image::ExifTool::Canon::PSInfo' }, + }, + 0x933 => { #33 + Name => 'LensModel', + Format => 'string[64]', + }, +); + +# Canon camera information for 500D (MakerNotes tag 0x0d) (ref PH) +%Image::ExifTool::Canon::CameraInfo500D = ( + %binaryDataAttrs, + FORMAT => 'int8u', + FIRST_ENTRY => 0, + PRIORITY => 0, + IS_SUBDIR => [ 0x30b ], + GROUPS => { 0 => 'MakerNotes', 2 => 'Camera' }, + NOTES => 'CameraInfo tags for the EOS 500D.', + 0x03 => { %ciFNumber }, + 0x04 => { %ciExposureTime }, + 0x06 => { %ciISO }, + 0x07 => { + Name => 'HighlightTonePriority', + PrintConv => \%offOn, + }, + 0x15 => { #PH (580 EX II) + Name => 'FlashMeteringMode', + PrintConv => { + 0 => 'E-TTL', + 3 => 'TTL', + 4 => 'External Auto', + 5 => 'External Manual', + 6 => 'Off', + }, + }, + 0x19 => { %ciCameraTemperature }, + 0x1e => { %ciFocalLength }, + 0x31 => { + Name => 'CameraOrientation', + PrintConv => { + 0 => 'Horizontal (normal)', + 1 => 'Rotate 90 CW', + 2 => 'Rotate 270 CW', + }, + }, + 0x50 => { + Name => 'FocusDistanceUpper', + %focusDistanceByteSwap, + }, + 0x52 => { + Name => 'FocusDistanceLower', + %focusDistanceByteSwap, + }, + 0x73 => { # (50D + 4) + Name => 'WhiteBalance', + Format => 'int16u', + SeparateTable => 1, + PrintConv => \%canonWhiteBalance, + }, + 0x77 => { # (50D + 4) + Name => 'ColorTemperature', + Format => 'int16u', + }, + 0xab => { # (50D + 4) + Name => 'PictureStyle', + Format => 'int8u', + Flags => ['PrintHex','SeparateTable'], + PrintConv => \%pictureStyles, + }, + 0xbc => { + Name => 'HighISONoiseReduction', + PrintConv => { + 0 => 'Standard', + 1 => 'Low', + 2 => 'Strong', + 3 => 'Off', + }, + }, + 0xbe => { + Name => 'AutoLightingOptimizer', + PrintConv => { + 0 => 'Standard', + 1 => 'Low', + 2 => 'Strong', + 3 => 'Off', + }, + }, + 0xf6 => { + Name => 'LensType', + Format => 'int16uRev', # value is big-endian + SeparateTable => 1, + ValueConvInv => 'int($val)', # (must truncate decimal part) + PrintConv => \%canonLensTypes, + }, + 0xf8 => { %ciMinFocal }, + 0xfa => { %ciMaxFocal }, + 0x190 => { + Name => 'FirmwareVersion', + Format => 'string[6]', + Writable => 0, + RawConv => '$val=~/^\d+\.\d+\.\d+\s*$/ ? $val : undef', + }, + 0x1d3 => { + Name => 'FileIndex', + Groups => { 2 => 'Image' }, + Format => 'int32u', + ValueConv => '$val + 1', + ValueConvInv => '$val - 1', + }, + 0x1df => { #(NC) + Name => 'DirectoryIndex', + Groups => { 2 => 'Image' }, + Format => 'int32u', + ValueConv => '$val - 1', + ValueConvInv => '$val + 1', + }, + 0x30b => { + Name => 'PictureStyleInfo', + SubDirectory => { TagTable => 'Image::ExifTool::Canon::PSInfo' }, + }, +); + +# Canon camera information for 550D (MakerNotes tag 0x0d) (ref PH) +%Image::ExifTool::Canon::CameraInfo550D = ( + %binaryDataAttrs, + FORMAT => 'int8u', + FIRST_ENTRY => 0, + PRIORITY => 0, + IS_SUBDIR => [ 0x31c ], + GROUPS => { 0 => 'MakerNotes', 2 => 'Camera' }, + NOTES => 'CameraInfo tags for the EOS 550D.', + 0x03 => { %ciFNumber }, + 0x04 => { %ciExposureTime }, + 0x06 => { %ciISO }, + 0x07 => { #(NC) + Name => 'HighlightTonePriority', + PrintConv => \%offOn, + }, + 0x15 => { #(NC) + Name => 'FlashMeteringMode', + PrintConv => { + 0 => 'E-TTL', + 3 => 'TTL', + 4 => 'External Auto', + 5 => 'External Manual', + 6 => 'Off', + }, + }, + 0x19 => { %ciCameraTemperature }, # (500D + 0) + 0x1e => { %ciFocalLength }, # (500D + 0) + 0x35 => { # (500D + 4) + Name => 'CameraOrientation', + PrintConv => { + 0 => 'Horizontal (normal)', + 1 => 'Rotate 90 CW', + 2 => 'Rotate 270 CW', + }, + }, + 0x54 => { # (500D + 4) + Name => 'FocusDistanceUpper', + %focusDistanceByteSwap, + }, + 0x56 => { # (500D + 4) + Name => 'FocusDistanceLower', + %focusDistanceByteSwap, + }, + 0x78 => { # (500D + 5) (NC) + Name => 'WhiteBalance', + Format => 'int16u', + SeparateTable => 1, + PrintConv => \%canonWhiteBalance, + }, + 0x7c => { # (500D + 5) + Name => 'ColorTemperature', + Format => 'int16u', + }, + 0xb0 => { # (500D + 5) + Name => 'PictureStyle', + Format => 'int8u', + Flags => ['PrintHex','SeparateTable'], + PrintConv => \%pictureStyles, + }, + 0xff => { # (500D + 9) + Name => 'LensType', + Format => 'int16uRev', # value is big-endian + SeparateTable => 1, + ValueConvInv => 'int($val)', # (must truncate decimal part) + PrintConv => \%canonLensTypes, + }, + 0x101 => { %ciMinFocal }, # (500D + 9) + 0x103 => { %ciMaxFocal }, # (500D + 9) + 0x1a4 => { # (500D + 0x11) + Name => 'FirmwareVersion', + Format => 'string[6]', + Writable => 0, + RawConv => '$val=~/^\d+\.\d+\.\d+\s*$/ ? $val : undef', + }, + 0x1e4 => { # (500D + 0x11) + Name => 'FileIndex', + Groups => { 2 => 'Image' }, + Format => 'int32u', + ValueConv => '$val + 1', + ValueConvInv => '$val - 1', + }, + 0x1f0 => { # (500D + 0x11) (NC) + Name => 'DirectoryIndex', + Groups => { 2 => 'Image' }, + Format => 'int32u', + ValueConv => '$val - 1', + ValueConvInv => '$val + 1', + }, + 0x31c => { #48 + Name => 'PictureStyleInfo', + SubDirectory => { TagTable => 'Image::ExifTool::Canon::PSInfo' }, + }, +); + +# Canon camera information for 600D and 1100D (MakerNotes tag 0x0d) (ref PH) +%Image::ExifTool::Canon::CameraInfo600D = ( + %binaryDataAttrs, + FORMAT => 'int8u', + FIRST_ENTRY => 0, + PRIORITY => 0, + IS_SUBDIR => [ 0x2fb ], + GROUPS => { 0 => 'MakerNotes', 2 => 'Camera' }, + NOTES => 'CameraInfo tags for the EOS 600D and 1100D.', + 0x03 => { %ciFNumber }, + 0x04 => { %ciExposureTime }, + 0x06 => { %ciISO }, + 0x07 => { #(NC) + Name => 'HighlightTonePriority', + PrintConv => \%offOn, + }, + 0x15 => { #(NC) + Name => 'FlashMeteringMode', + PrintConv => { + 0 => 'E-TTL', + 3 => 'TTL', + 4 => 'External Auto', + 5 => 'External Manual', + 6 => 'Off', + }, + }, + 0x19 => { %ciCameraTemperature }, # (60D + 0) + 0x1e => { %ciFocalLength }, # (60D + 0) + 0x38 => { # (60D + 2) + Name => 'CameraOrientation', + PrintConv => { + 0 => 'Horizontal (normal)', + 1 => 'Rotate 90 CW', + 2 => 'Rotate 270 CW', + }, + }, + 0x57 => { # (60D + 2, 550D + 3) + Name => 'FocusDistanceUpper', + %focusDistanceByteSwap, + }, + 0x59 => { # (60D + 2, 550D + 3) + Name => 'FocusDistanceLower', + %focusDistanceByteSwap, + }, + 0x7b => { # (550D + 3) + Name => 'WhiteBalance', + Format => 'int16u', + SeparateTable => 1, + PrintConv => \%canonWhiteBalance, + }, + 0x7f => { # (60D + 2, 550D + 3) + Name => 'ColorTemperature', + Format => 'int16u', + }, + 0xb3 => { # (550D + 3) + Name => 'PictureStyle', + Format => 'int8u', + Flags => ['PrintHex','SeparateTable'], + PrintConv => \%pictureStyles, + }, + 0xea => { # (60D + 2, 550D + 3) + Name => 'LensType', + Format => 'int16uRev', # value is big-endian + SeparateTable => 1, + ValueConvInv => 'int($val)', # (must truncate decimal part) + PrintConv => \%canonLensTypes, + }, + 0xec => { %ciMinFocal }, # (60D + 2) + 0xee => { %ciMaxFocal }, # (60D + 2) + 0x19b => { # (60D + 2) + Name => 'FirmwareVersion', + Format => 'string[6]', + Writable => 0, + RawConv => '$val=~/^\d+\.\d+\.\d+\s*$/ ? $val : undef', + }, + 0x1db => { # (60D + 2) (NC) + Name => 'FileIndex', + Groups => { 2 => 'Image' }, + Format => 'int32u', + ValueConv => '$val + 1', + ValueConvInv => '$val - 1', + }, + 0x1e7 => { # (60D + 2) (NC) + Name => 'DirectoryIndex', + Groups => { 2 => 'Image' }, + Format => 'int32u', + ValueConv => '$val - 1', + ValueConvInv => '$val + 1', + }, + 0x2fb => { + Name => 'PictureStyleInfo', + SubDirectory => { TagTable => 'Image::ExifTool::Canon::PSInfo2' }, + }, +); + +# Canon camera information for 650D/700D (MakerNotes tag 0x0d) (ref PH) +%Image::ExifTool::Canon::CameraInfo650D = ( + %binaryDataAttrs, + FORMAT => 'int8u', + FIRST_ENTRY => 0, + PRIORITY => 0, + IS_SUBDIR => [ 0x390 ], + GROUPS => { 0 => 'MakerNotes', 2 => 'Camera' }, + NOTES => 'CameraInfo tags for the EOS 650D and 700D.', + 0x03 => { %ciFNumber }, + 0x04 => { %ciExposureTime }, + 0x06 => { %ciISO }, + 0x1b => { %ciCameraTemperature }, # (1DX/5DmkIII + 0) + 0x23 => { %ciFocalLength }, # (1DX/5DmkIII + 3) + # 0x35 - seems to be the same as 0x54 + 0x7d => { # (1DX/5DmkIII + 3) + Name => 'CameraOrientation', + PrintConv => { + 0 => 'Horizontal (normal)', + 1 => 'Rotate 90 CW', + 2 => 'Rotate 270 CW', + }, + }, + 0x8c => { # (1DX + 3) + Name => 'FocusDistanceUpper', + %focusDistanceByteSwap, + }, + 0x8e => { # (1DX + 3) + Name => 'FocusDistanceLower', + %focusDistanceByteSwap, + }, + 0xbc => { # (1DX + 7) + Name => 'WhiteBalance', + Format => 'int16u', + SeparateTable => 1, + PrintConv => \%canonWhiteBalance, + }, + 0xc0 => { # (1DX + 7) + Name => 'ColorTemperature', + Format => 'int16u', + }, + 0xf4 => { # (1DX + 7) + Name => 'PictureStyle', + Format => 'int8u', + Flags => ['PrintHex','SeparateTable'], + PrintConv => \%pictureStyles, + }, + 0x127 => { + Name => 'LensType', + Format => 'int16uRev', # value is big-endian + SeparateTable => 1, + ValueConvInv => 'int($val)', # (must truncate decimal part) + PrintConv => \%canonLensTypes, + }, + 0x129 => { %ciMinFocal }, + 0x12b => { %ciMaxFocal }, + 0x21b => { # (650D version 1.0.1) + Name => 'FirmwareVersion', + Condition => '$$self{Model} =~ /(650D|REBEL T4i|Kiss X6i)\b/', + Notes => '650D', + Format => 'string[6]', + Writable => 0, + RawConv => '$val=~/^\d+\.\d+\.\d+\s*$/ ? $val : undef', + }, + 0x220 => { # (700D version 1.1.1/2.1.1) + Name => 'FirmwareVersion', + Condition => '$$self{Model} =~ /(700D|REBEL T5i|Kiss X7i)\b/', + Notes => '700D', + Format => 'string[6]', + Writable => 0, + RawConv => '$val=~/^\d+\.\d+\.\d+\s*$/ ? $val : undef', + }, + 0x270 => { #(NC) + Name => 'FileIndex', + Condition => '$$self{Model} =~ /(650D|REBEL T4i|Kiss X6i)\b/', + Notes => '650D', + Groups => { 2 => 'Image' }, + Format => 'int32u', + ValueConv => '$val + 1', + ValueConvInv => '$val - 1', + }, + 0x274 => { #(NC) + Name => 'FileIndex', + Condition => '$$self{Model} =~ /(700D|REBEL T5i|Kiss X7i)\b/', + Notes => '700D', + Groups => { 2 => 'Image' }, + Format => 'int32u', + ValueConv => '$val + 1', + ValueConvInv => '$val - 1', + }, + 0x27c => { #(NC) + Name => 'DirectoryIndex', + Condition => '$$self{Model} =~ /(650D|REBEL T4i|Kiss X6i)\b/', + Notes => '650D', + Groups => { 2 => 'Image' }, + Format => 'int32u', + ValueConv => '$val - 1', + ValueConvInv => '$val + 1', + }, + 0x280 => { #(NC) + Name => 'DirectoryIndex', + Condition => '$$self{Model} =~ /(700D|REBEL T5i|Kiss X7i)\b/', + Notes => '700D', + Groups => { 2 => 'Image' }, + Format => 'int32u', + ValueConv => '$val - 1', + ValueConvInv => '$val + 1', + }, + 0x390 => { + Name => 'PictureStyleInfo', + SubDirectory => { TagTable => 'Image::ExifTool::Canon::PSInfo2' }, + }, +); + +# Canon camera information for 750D/760D (MakerNotes tag 0x0d) (ref PH) +%Image::ExifTool::Canon::CameraInfo750D = ( + %binaryDataAttrs, + FORMAT => 'int8u', + FIRST_ENTRY => 0, + PRIORITY => 0, + GROUPS => { 0 => 'MakerNotes', 2 => 'Camera' }, + NOTES => 'CameraInfo tags for the EOS 750D and 760D.', + 0x03 => { %ciFNumber }, + 0x04 => { %ciExposureTime }, + 0x06 => { %ciISO }, + 0x1b => { %ciCameraTemperature }, # (700D + 0) + 0x23 => { %ciFocalLength }, # (700D + 0) + 0xa5 => { # (700D + 0x19) + Name => 'FocusDistanceUpper', + %focusDistanceByteSwap, + }, + 0xa7 => { # (700D + 0x19) + Name => 'FocusDistanceLower', + %focusDistanceByteSwap, + }, + 0x131 => { # (700D + 0x19) + Name => 'WhiteBalance', + Format => 'int16u', + SeparateTable => 1, + PrintConv => \%canonWhiteBalance, + }, + 0x135 => { + Name => 'ColorTemperature', + Format => 'int16u', + }, + 0x169 => { + Name => 'PictureStyle', + Format => 'int8u', + Flags => ['PrintHex','SeparateTable'], + PrintConv => \%pictureStyles, + }, + 0x184 => { + Name => 'LensType', + Format => 'int16uRev', # value is big-endian + SeparateTable => 1, + ValueConvInv => 'int($val)', # (must truncate decimal part) + PrintConv => \%canonLensTypes, + }, + 0x186 => { %ciMinFocal }, + 0x188 => { %ciMaxFocal }, + 0x43d => { # (750D/760D firmware 6.7.2) + Name => 'FirmwareVersion', + Format => 'string[6]', + Writable => 0, + RawConv => '$val=~/^\d+\.\d+\.\d+\s*$/ ? $val : undef', + }, + 0x449 => { # (750D/760D firmware 1.0.0) + Name => 'FirmwareVersion', + Format => 'string[6]', + Writable => 0, + RawConv => '$val=~/^\d+\.\d+\.\d+\s*$/ ? $val : undef', + }, +); + +# Canon camera information for 1000D (MakerNotes tag 0x0d) (ref PH) +%Image::ExifTool::Canon::CameraInfo1000D = ( + %binaryDataAttrs, + FORMAT => 'int8u', + FIRST_ENTRY => 0, + PRIORITY => 0, + IS_SUBDIR => [ 0x267 ], + GROUPS => { 0 => 'MakerNotes', 2 => 'Camera' }, + NOTES => 'CameraInfo tags for the EOS 1000D.', + 0x03 => { %ciFNumber }, #PH + 0x04 => { %ciExposureTime }, #PH + 0x06 => { %ciISO }, #PH + 0x15 => { #PH (580 EX II) + Name => 'FlashMeteringMode', + PrintConv => { + 0 => 'E-TTL', + 3 => 'TTL', + 4 => 'External Auto', + 5 => 'External Manual', + 6 => 'Off', + }, + }, + 0x18 => { %ciCameraTemperature }, #36 + 0x1b => { %ciMacroMagnification }, #PH (NC) + 0x1d => { %ciFocalLength }, #PH + 0x30 => { #20 + Name => 'CameraOrientation', + PrintConv => { + 0 => 'Horizontal (normal)', + 1 => 'Rotate 90 CW', + 2 => 'Rotate 270 CW', + }, + }, + 0x43 => { #20 + Name => 'FocusDistanceUpper', + %focusDistanceByteSwap, + }, + 0x45 => { #20 + Name => 'FocusDistanceLower', + %focusDistanceByteSwap, + }, + 0x6f => { #PH + Name => 'WhiteBalance', + Format => 'int16u', + PrintConv => \%canonWhiteBalance, + SeparateTable => 1, + }, + 0x73 => { #PH + Name => 'ColorTemperature', + Format => 'int16u', + }, + 0xe2 => { #PH + Name => 'LensType', + Format => 'int16uRev', # value is big-endian + SeparateTable => 1, + ValueConvInv => 'int($val)', # (must truncate decimal part) + PrintConv => \%canonLensTypes, + }, + 0xe4 => { %ciMinFocal }, #PH + 0xe6 => { %ciMaxFocal }, #PH + 0x10b => { #PH + Name => 'FirmwareVersion', + Format => 'string[6]', + }, + 0x137 => { #PH (NC) + Name => 'DirectoryIndex', + Groups => { 2 => 'Image' }, + Format => 'int32u', + }, + 0x143 => { #PH + Name => 'FileIndex', + Groups => { 2 => 'Image' }, + Format => 'int32u', + ValueConv => '$val + 1', + ValueConvInv => '$val - 1', + }, + 0x267 => { #PH + Name => 'PictureStyleInfo', + SubDirectory => { TagTable => 'Image::ExifTool::Canon::PSInfo' }, + }, + 0x937 => { #PH + Name => 'LensModel', + Format => 'string[64]', + }, +); + +# Canon camera information for PowerShot models (MakerNotes tag 0x0d) - PH +%Image::ExifTool::Canon::CameraInfoPowerShot = ( + %binaryDataAttrs, + FORMAT => 'int32s', + FIRST_ENTRY => 0, + PRIORITY => 0, + GROUPS => { 0 => 'MakerNotes', 2 => 'Camera' }, + NOTES => q{ + CameraInfo tags for PowerShot models such as the A450, A460, A550, A560, + A570, A630, A640, A650, A710, A720, G7, G9, S5, SD40, SD750, SD800, SD850, + SD870, SD900, SD950, SD1000, SX100 and TX1. + }, + 0x00 => { + Name => 'ISO', + Groups => { 2 => 'Image' }, + ValueConv => '100*exp((($val-411)/96)*log(2))', + ValueConvInv => 'log($val/100)/log(2)*96+411', + PrintConv => 'sprintf("%.0f",$val)', + PrintConvInv => '$val', + }, + 0x05 => { + Name => 'FNumber', + Groups => { 2 => 'Image' }, + ValueConv => 'exp($val/192*log(2))', + ValueConvInv => 'log($val)*192/log(2)', + PrintConv => 'sprintf("%.2g",$val)', + PrintConvInv => '$val', + }, + 0x06 => { + Name => 'ExposureTime', + Groups => { 2 => 'Image' }, + ValueConv => 'exp(-$val/96*log(2))', + ValueConvInv => '-log($val)*96/log(2)', + PrintConv => 'Image::ExifTool::Exif::PrintExposureTime($val)', + PrintConvInv => 'Image::ExifTool::Exif::ConvertFraction($val)', + }, + 0x17 => 'Rotation', # usually the same as Orientation (but not always! why?) + # 0x25 - flash fired/not fired (ref 37) + # 0x26 - related to flash mode? (ref 37) + # 0x37 - related to flash strength (ref 37) + # 0x38 - pre-flash fired/no fired or flash data collection (ref 37) + 135 => { # [-3] <-- index relative to CameraInfoCount + Name => 'CameraTemperature', + Condition => '$$self{CameraInfoCount} == 138', + Notes => 'A450, A460, A550, A630, A640 and A710', + PrintConv => '"$val C"', + PrintConvInv => '$val=~s/ ?C//; $val', + }, + 145 => { #37 [-3] + Name => 'CameraTemperature', + Condition => '$$self{CameraInfoCount} == 148', + Notes => q{ + A560, A570, A650, A720, G7, G9, S5, SD40, SD750, SD800, SD850, SD870, SD900, + SD950, SD1000, SX100 and TX1 + }, + PrintConv => '"$val C"', + PrintConvInv => '$val=~s/ ?C//; $val', + }, +); + +# Canon camera information for some PowerShot models (MakerNotes tag 0x0d) - PH +%Image::ExifTool::Canon::CameraInfoPowerShot2 = ( + %binaryDataAttrs, + FORMAT => 'int32s', + FIRST_ENTRY => 0, + PRIORITY => 0, + GROUPS => { 0 => 'MakerNotes', 2 => 'Camera' }, + NOTES => q{ + CameraInfo tags for PowerShot models such as the A470, A480, A490, A495, + A580, A590, A1000, A1100, A2000, A2100, A3000, A3100, D10, E1, G10, G11, + S90, S95, SD770, SD780, SD790, SD880, SD890, SD940, SD960, SD970, SD980, + SD990, SD1100, SD1200, SD1300, SD1400, SD3500, SD4000, SD4500, SX1, SX10, + SX20, SX110, SX120, SX130, SX200 and SX210. + }, + 0x01 => { + Name => 'ISO', + Groups => { 2 => 'Image' }, + ValueConv => '100*exp((($val-411)/96)*log(2))', + ValueConvInv => 'log($val/100)/log(2)*96+411', + PrintConv => 'sprintf("%.0f",$val)', + PrintConvInv => '$val', + }, + 0x06 => { + Name => 'FNumber', + Groups => { 2 => 'Image' }, + ValueConv => 'exp($val/192*log(2))', + ValueConvInv => 'log($val)*192/log(2)', + PrintConv => 'sprintf("%.2g",$val)', + PrintConvInv => '$val', + }, + 0x07 => { + Name => 'ExposureTime', + Groups => { 2 => 'Image' }, + ValueConv => 'exp(-$val/96*log(2))', + ValueConvInv => '-log($val)*96/log(2)', + PrintConv => 'Image::ExifTool::Exif::PrintExposureTime($val)', + PrintConvInv => 'Image::ExifTool::Exif::ConvertFraction($val)', + }, + 0x18 => 'Rotation', + 153 => { # [-3] <-- index relative to CameraInfoCount + Name => 'CameraTemperature', + Condition => '$$self{CameraInfoCount} == 156', + Notes => 'A470, A580, A590, SD770, SD790, SD890 and SD1100', + PrintConv => '"$val C"', + PrintConvInv => '$val=~s/ ?C//; $val', + }, + 159 => { # [-3] + Name => 'CameraTemperature', + Condition => '$$self{CameraInfoCount} == 162', + Notes => 'A1000, A2000, E1, G10, SD880, SD990, SX1, SX10 and SX110', + PrintConv => '"$val C"', + PrintConvInv => '$val=~s/ ?C//; $val', + }, + 164 => { # [-3] + Name => 'CameraTemperature', + Condition => '$$self{CameraInfoCount} == 167', + Notes => 'A480, A1100, A2100, D10, SD780, SD960, SD970, SD1200 and SX200', + PrintConv => '"$val C"', + PrintConvInv => '$val=~s/ ?C//; $val', + }, + 168 => { # [-3] + Name => 'CameraTemperature', + Condition => '$$self{CameraInfoCount} == 171', + Notes => q{ + A490, A495, A3000, A3100, G11, S90, SD940, SD980, SD1300, SD1400, SD3500, + SD4000, SX20, SX120 and SX210 + }, + PrintConv => '"$val C"', + PrintConvInv => '$val=~s/ ?C//; $val', + }, + 261 => { # [-3] + Name => 'CameraTemperature', + Condition => '$$self{CameraInfoCount} == 264', + Notes => 'S95, SD4500 and SX130', + PrintConv => '"$val C"', + PrintConvInv => '$val=~s/ ?C//; $val', + }, +); + +# unknown Canon camera information (MakerNotes tag 0x0d) - PH +%Image::ExifTool::Canon::CameraInfoUnknown32 = ( + %binaryDataAttrs, + FORMAT => 'int32s', + FIRST_ENTRY => 0, + PRIORITY => 0, + GROUPS => { 0 => 'MakerNotes', 2 => 'Camera' }, + NOTES => 'Unknown CameraInfo tags are divided into 3 tables based on format size.', + # This tag may be uncommented, and is useful for generating + # lists of models in the "Notes" below... + # 0 => { + # Name => 'CameraInfoCount', + # ValueConv => '$$self{CameraInfoCount}', + # }, + 71 => { # [-1] <-- index relative to CameraInfoCount + Name => 'CameraTemperature', + Condition => '$$self{CameraInfoCount} == 72', + Notes => 'S1', + PrintConv => '"$val C"', + PrintConvInv => '$val=~s/ ?C//; $val', + }, + 83 => { # [-2] + Name => 'CameraTemperature', + Condition => '$$self{CameraInfoCount} == 85', + Notes => 'S2', + PrintConv => '"$val C"', + PrintConvInv => '$val=~s/ ?C//; $val', + }, + 91 => { # [-2 or -3] + Name => 'CameraTemperature', + Condition => '$$self{CameraInfoCount} == 93 or $$self{CameraInfoCount} == 94', + Notes => 'A410, A610, A620, S80, SD30, SD400, SD430, SD450, SD500 and SD550', + PrintConv => '"$val C"', + PrintConvInv => '$val=~s/ ?C//; $val', + }, + 92 => { # [-4] + Name => 'CameraTemperature', + Condition => '$$self{CameraInfoCount} == 96', + Notes => 'S3', + PrintConv => '"$val C"', + PrintConvInv => '$val=~s/ ?C//; $val', + }, + 100 => { # [-4] + Name => 'CameraTemperature', + Condition => '$$self{CameraInfoCount} == 104', + Notes => 'A420, A430, A530, A540, A700, SD600, SD630 and SD700', + PrintConv => '"$val C"', + PrintConvInv => '$val=~s/ ?C//; $val', + }, + -3 => { + Name => 'CameraTemperature', + Condition => '$$self{CameraInfoCount} > 400', + Notes => '3 entries from end of record for most newer camera models', + PrintConv => '"$val C"', + PrintConvInv => '$val=~s/ ?C//; $val', + }, +# 466 => { # [-3] +# Name => 'CameraTemperature', +# Condition => '$$self{CameraInfoCount} == 469', +# Notes => '100HS, 300HS, 500HS, A1200, A2200, A3200 and A3300', +# PrintConv => '"$val C"', +# PrintConvInv => '$val=~s/ ?C//; $val', +# }, +# 503 => { # [-3] +# Name => 'CameraTemperature', +# Condition => '$$self{CameraInfoCount} == 506', +# Notes => 'A800', +# PrintConv => '"$val C"', +# PrintConvInv => '$val=~s/ ?C//; $val', +# }, +# 506 => { # [-3] +# Name => 'CameraTemperature', +# Condition => '$$self{CameraInfoCount} == 509', +# Notes => 'SX230HS', +# PrintConv => '"$val C"', +# PrintConvInv => '$val=~s/ ?C//; $val', +# }, +# 520 => { # [-3] +# Name => 'CameraTemperature', +# Condition => '$$self{CameraInfoCount} == 523', +# Notes => '310HS, 510HS, G1X, S100 (new), SX40HS and SX150', +# PrintConv => '"$val C"', +# PrintConvInv => '$val=~s/ ?C//; $val', +# }, +# 524 => { # [-3] +# Name => 'CameraTemperature', +# Condition => '$$self{CameraInfoCount} == 527', +# Notes => '110HS, 520HS, A2300, A2400, A3400, A4000, D20 and SX260HS', +# PrintConv => '"$val C"', +# PrintConvInv => '$val=~s/ ?C//; $val', +# }, +# 532 => { # [-3] +# Name => 'CameraTemperature', +# Condition => '$$self{CameraInfoCount} == 535', +# Notes => 'S110 (new), G15, SX50, SX160IS and SX500IS', +# PrintConv => '"$val C"', +# PrintConvInv => '$val=~s/ ?C//; $val', +# }, +# 547 => { # [-3] +# Name => 'CameraTemperature', +# Condition => '$$self{CameraInfoCount} == 550', +# Notes => '130IS, A1400, A2500 and A2600', +# PrintConv => '"$val C"', +# PrintConvInv => '$val=~s/ ?C//; $val', +# }, +# 549 => { # [-3] +# Name => 'CameraTemperature', +# Condition => '$$self{CameraInfoCount} == 552', +# Notes => '115IS, 130IS, SX270, SX280, 330HS and A3500', +# PrintConv => '"$val C"', +# PrintConvInv => '$val=~s/ ?C//; $val', +# }, +# 552 => { # [-3] +# Name => 'CameraTemperature', +# Condition => '$$self{CameraInfoCount} == 555', +# Notes => 'S200 (new)', +# PrintConv => '"$val C"', +# PrintConvInv => '$val=~s/ ?C//; $val', +# }, +# 850 => { # [-3] +# Name => 'CameraTemperature', +# Condition => '$$self{CameraInfoCount} == 853', +# Notes => 'N', +# PrintConv => '"$val C"', +# PrintConvInv => '$val=~s/ ?C//; $val', +# }, +# 895 => { # [-3] +# Name => 'CameraTemperature', +# Condition => '$$self{CameraInfoCount} == 898', +# Notes => 'G1XmkII, N100, SX600HS and SX700HS', +# PrintConv => '"$val C"', +# PrintConvInv => '$val=~s/ ?C//; $val', +# }, +); + +# unknown Canon camera information (MakerNotes tag 0x0d) - PH +%Image::ExifTool::Canon::CameraInfoUnknown16 = ( + %binaryDataAttrs, + FORMAT => 'int16s', + FIRST_ENTRY => 0, + PRIORITY => 0, + GROUPS => { 0 => 'MakerNotes', 2 => 'Camera' }, +); + +# unknown Canon camera information (MakerNotes tag 0x0d) - PH +%Image::ExifTool::Canon::CameraInfoUnknown = ( + %binaryDataAttrs, + FORMAT => 'int8s', + FIRST_ENTRY => 0, + PRIORITY => 0, + GROUPS => { 0 => 'MakerNotes', 2 => 'Camera' }, + 0x16b => { + Name => 'LensSerialNumber', + Condition => '$$self{Model} =~ /^Canon EOS 5DS/', # (good for 5DS and 5DSR) + Format => 'undef[5]', + Priority => 0, + ValueConv => 'unpack("H*",$val)', + ValueConvInv => 'length($val) < 10 and $val = 0 x (10-length($val)) . $val; pack("H*",$val)', + }, +); + +# Picture Style information for various cameras (ref 48) +%Image::ExifTool::Canon::PSInfo = ( + %binaryDataAttrs, + FIRST_ENTRY => 0, + PRIORITY => 0, + GROUPS => { 0 => 'MakerNotes', 2 => 'Camera' }, + NOTES => 'Custom picture style information for various models.', + # (values expected to be "n/a" are flagged as Unknown) + 0x00 => { Name => 'ContrastStandard', %psInfo }, + 0x04 => { Name => 'SharpnessStandard', %psInfo }, + 0x08 => { Name => 'SaturationStandard', %psInfo }, + 0x0c => { Name => 'ColorToneStandard', %psInfo }, + 0x10 => { Name => 'FilterEffectStandard', %psInfo, Unknown => 1 }, + 0x14 => { Name => 'ToningEffectStandard', %psInfo, Unknown => 1 }, + 0x18 => { Name => 'ContrastPortrait', %psInfo }, + 0x1c => { Name => 'SharpnessPortrait', %psInfo }, + 0x20 => { Name => 'SaturationPortrait', %psInfo }, + 0x24 => { Name => 'ColorTonePortrait', %psInfo }, + 0x28 => { Name => 'FilterEffectPortrait', %psInfo, Unknown => 1 }, + 0x2c => { Name => 'ToningEffectPortrait', %psInfo, Unknown => 1 }, + 0x30 => { Name => 'ContrastLandscape', %psInfo }, + 0x34 => { Name => 'SharpnessLandscape', %psInfo }, + 0x38 => { Name => 'SaturationLandscape', %psInfo }, + 0x3c => { Name => 'ColorToneLandscape', %psInfo }, + 0x40 => { Name => 'FilterEffectLandscape', %psInfo, Unknown => 1 }, + 0x44 => { Name => 'ToningEffectLandscape', %psInfo, Unknown => 1 }, + 0x48 => { Name => 'ContrastNeutral', %psInfo }, + 0x4c => { Name => 'SharpnessNeutral', %psInfo }, + 0x50 => { Name => 'SaturationNeutral', %psInfo }, + 0x54 => { Name => 'ColorToneNeutral', %psInfo }, + 0x58 => { Name => 'FilterEffectNeutral', %psInfo, Unknown => 1 }, + 0x5c => { Name => 'ToningEffectNeutral', %psInfo, Unknown => 1 }, + 0x60 => { Name => 'ContrastFaithful', %psInfo }, + 0x64 => { Name => 'SharpnessFaithful', %psInfo }, + 0x68 => { Name => 'SaturationFaithful', %psInfo }, + 0x6c => { Name => 'ColorToneFaithful', %psInfo }, + 0x70 => { Name => 'FilterEffectFaithful', %psInfo, Unknown => 1 }, + 0x74 => { Name => 'ToningEffectFaithful', %psInfo, Unknown => 1 }, + 0x78 => { Name => 'ContrastMonochrome', %psInfo }, + 0x7c => { Name => 'SharpnessMonochrome', %psInfo }, + 0x80 => { Name => 'SaturationMonochrome', %psInfo, Unknown => 1 }, + 0x84 => { Name => 'ColorToneMonochrome', %psInfo, Unknown => 1 }, + 0x88 => { Name => 'FilterEffectMonochrome',%psInfo, + PrintConv => { + 0 => 'None', + 1 => 'Yellow', + 2 => 'Orange', + 3 => 'Red', + 4 => 'Green', + -559038737 => 'n/a', # (0xdeadbeef) + }, + }, + 0x8c => { Name => 'ToningEffectMonochrome',%psInfo, + PrintConv => { + 0 => 'None', + 1 => 'Sepia', + 2 => 'Blue', + 3 => 'Purple', + 4 => 'Green', + -559038737 => 'n/a', # (0xdeadbeef) + }, + }, + 0x90 => { Name => 'ContrastUserDef1', %psInfo }, + 0x94 => { Name => 'SharpnessUserDef1', %psInfo }, + 0x98 => { Name => 'SaturationUserDef1', %psInfo }, + 0x9c => { Name => 'ColorToneUserDef1', %psInfo }, + 0xa0 => { Name => 'FilterEffectUserDef1', %psInfo, + PrintConv => { + 0 => 'None', + 1 => 'Yellow', + 2 => 'Orange', + 3 => 'Red', + 4 => 'Green', + -559038737 => 'n/a', # (0xdeadbeef) + }, + }, + 0xa4 => { Name => 'ToningEffectUserDef1', %psInfo, + PrintConv => { + 0 => 'None', + 1 => 'Sepia', + 2 => 'Blue', + 3 => 'Purple', + 4 => 'Green', + -559038737 => 'n/a', # (0xdeadbeef) + }, + }, + 0xa8 => { Name => 'ContrastUserDef2', %psInfo }, + 0xac => { Name => 'SharpnessUserDef2', %psInfo }, + 0xb0 => { Name => 'SaturationUserDef2', %psInfo }, + 0xb4 => { Name => 'ColorToneUserDef2', %psInfo }, + 0xb8 => { Name => 'FilterEffectUserDef2', %psInfo, + PrintConv => { + 0 => 'None', + 1 => 'Yellow', + 2 => 'Orange', + 3 => 'Red', + 4 => 'Green', + -559038737 => 'n/a', # (0xdeadbeef) + }, + }, + 0xbc => { Name => 'ToningEffectUserDef2', %psInfo, + PrintConv => { + 0 => 'None', + 1 => 'Sepia', + 2 => 'Blue', + 3 => 'Purple', + 4 => 'Green', + -559038737 => 'n/a', # (0xdeadbeef) + }, + }, + 0xc0 => { Name => 'ContrastUserDef3', %psInfo }, + 0xc4 => { Name => 'SharpnessUserDef3', %psInfo }, + 0xc8 => { Name => 'SaturationUserDef3', %psInfo }, + 0xcc => { Name => 'ColorToneUserDef3', %psInfo }, + 0xd0 => { Name => 'FilterEffectUserDef3', %psInfo, + PrintConv => { + 0 => 'None', + 1 => 'Yellow', + 2 => 'Orange', + 3 => 'Red', + 4 => 'Green', + -559038737 => 'n/a', # (0xdeadbeef) + }, + }, + 0xd4 => { Name => 'ToningEffectUserDef3', %psInfo, + PrintConv => { + 0 => 'None', + 1 => 'Sepia', + 2 => 'Blue', + 3 => 'Purple', + 4 => 'Green', + -559038737 => 'n/a', # (0xdeadbeef) + }, + }, + # base picture style names: + 0xd8 => { + Name => 'UserDef1PictureStyle', + Format => 'int16u', + SeparateTable => 'UserDefStyle', + PrintConv => \%userDefStyles, + }, + 0xda => { + Name => 'UserDef2PictureStyle', + Format => 'int16u', + SeparateTable => 'UserDefStyle', + PrintConv => \%userDefStyles, + }, + 0xdc => { + Name => 'UserDef3PictureStyle', + Format => 'int16u', + SeparateTable => 'UserDefStyle', + PrintConv => \%userDefStyles, + }, +); + +# Picture Style information for the 60D, etc (ref 48) +%Image::ExifTool::Canon::PSInfo2 = ( + %binaryDataAttrs, + FIRST_ENTRY => 0, + PRIORITY => 0, + GROUPS => { 0 => 'MakerNotes', 2 => 'Camera' }, + NOTES => 'Custom picture style information for the EOS 5DmkIII, 60D, 600D and 1100D.', + # (values expected to be "n/a" are flagged as Unknown) + 0x00 => { Name => 'ContrastStandard', %psInfo }, + 0x04 => { Name => 'SharpnessStandard', %psInfo }, + 0x08 => { Name => 'SaturationStandard', %psInfo }, + 0x0c => { Name => 'ColorToneStandard', %psInfo }, + 0x10 => { Name => 'FilterEffectStandard', %psInfo, Unknown => 1 }, + 0x14 => { Name => 'ToningEffectStandard', %psInfo, Unknown => 1 }, + 0x18 => { Name => 'ContrastPortrait', %psInfo }, + 0x1c => { Name => 'SharpnessPortrait', %psInfo }, + 0x20 => { Name => 'SaturationPortrait', %psInfo }, + 0x24 => { Name => 'ColorTonePortrait', %psInfo }, + 0x28 => { Name => 'FilterEffectPortrait', %psInfo, Unknown => 1 }, + 0x2c => { Name => 'ToningEffectPortrait', %psInfo, Unknown => 1 }, + 0x30 => { Name => 'ContrastLandscape', %psInfo }, + 0x34 => { Name => 'SharpnessLandscape', %psInfo }, + 0x38 => { Name => 'SaturationLandscape', %psInfo }, + 0x3c => { Name => 'ColorToneLandscape', %psInfo }, + 0x40 => { Name => 'FilterEffectLandscape', %psInfo, Unknown => 1 }, + 0x44 => { Name => 'ToningEffectLandscape', %psInfo, Unknown => 1 }, + 0x48 => { Name => 'ContrastNeutral', %psInfo }, + 0x4c => { Name => 'SharpnessNeutral', %psInfo }, + 0x50 => { Name => 'SaturationNeutral', %psInfo }, + 0x54 => { Name => 'ColorToneNeutral', %psInfo }, + 0x58 => { Name => 'FilterEffectNeutral', %psInfo, Unknown => 1 }, + 0x5c => { Name => 'ToningEffectNeutral', %psInfo, Unknown => 1 }, + 0x60 => { Name => 'ContrastFaithful', %psInfo }, + 0x64 => { Name => 'SharpnessFaithful', %psInfo }, + 0x68 => { Name => 'SaturationFaithful', %psInfo }, + 0x6c => { Name => 'ColorToneFaithful', %psInfo }, + 0x70 => { Name => 'FilterEffectFaithful', %psInfo, Unknown => 1 }, + 0x74 => { Name => 'ToningEffectFaithful', %psInfo, Unknown => 1 }, + 0x78 => { Name => 'ContrastMonochrome', %psInfo }, + 0x7c => { Name => 'SharpnessMonochrome', %psInfo }, + 0x80 => { Name => 'SaturationMonochrome', %psInfo, Unknown => 1 }, + 0x84 => { Name => 'ColorToneMonochrome', %psInfo, Unknown => 1 }, + 0x88 => { Name => 'FilterEffectMonochrome',%psInfo, + PrintConv => { + 0 => 'None', + 1 => 'Yellow', + 2 => 'Orange', + 3 => 'Red', + 4 => 'Green', + -559038737 => 'n/a', # (0xdeadbeef) + }, + }, + 0x8c => { Name => 'ToningEffectMonochrome',%psInfo, + PrintConv => { + 0 => 'None', + 1 => 'Sepia', + 2 => 'Blue', + 3 => 'Purple', + 4 => 'Green', + -559038737 => 'n/a', # (0xdeadbeef) + }, + }, + 0x90 => { Name => 'ContrastAuto', %psInfo }, + 0x94 => { Name => 'SharpnessAuto', %psInfo }, + 0x98 => { Name => 'SaturationAuto', %psInfo }, + 0x9c => { Name => 'ColorToneAuto', %psInfo }, + 0xa0 => { Name => 'FilterEffectAuto', %psInfo, + PrintConv => { + 0 => 'None', + 1 => 'Yellow', + 2 => 'Orange', + 3 => 'Red', + 4 => 'Green', + -559038737 => 'n/a', # (0xdeadbeef) + }, + }, + 0xa4 => { Name => 'ToningEffectAuto', %psInfo, + PrintConv => { + 0 => 'None', + 1 => 'Sepia', + 2 => 'Blue', + 3 => 'Purple', + 4 => 'Green', + -559038737 => 'n/a', # (0xdeadbeef) + }, + }, + 0xa8 => { Name => 'ContrastUserDef1', %psInfo }, + 0xac => { Name => 'SharpnessUserDef1', %psInfo }, + 0xb0 => { Name => 'SaturationUserDef1', %psInfo }, + 0xb4 => { Name => 'ColorToneUserDef1', %psInfo }, + 0xb8 => { Name => 'FilterEffectUserDef1', %psInfo, + PrintConv => { + 0 => 'None', + 1 => 'Yellow', + 2 => 'Orange', + 3 => 'Red', + 4 => 'Green', + -559038737 => 'n/a', # (0xdeadbeef) + }, + }, + 0xbc => { Name => 'ToningEffectUserDef1', %psInfo, + PrintConv => { + 0 => 'None', + 1 => 'Sepia', + 2 => 'Blue', + 3 => 'Purple', + 4 => 'Green', + -559038737 => 'n/a', # (0xdeadbeef) + }, + }, + 0xc0 => { Name => 'ContrastUserDef2', %psInfo }, + 0xc4 => { Name => 'SharpnessUserDef2', %psInfo }, + 0xc8 => { Name => 'SaturationUserDef2', %psInfo }, + 0xcc => { Name => 'ColorToneUserDef2', %psInfo }, + 0xd0 => { Name => 'FilterEffectUserDef2', %psInfo, + PrintConv => { + 0 => 'None', + 1 => 'Yellow', + 2 => 'Orange', + 3 => 'Red', + 4 => 'Green', + -559038737 => 'n/a', # (0xdeadbeef) + }, + }, + 0xd4 => { Name => 'ToningEffectUserDef2', %psInfo, + PrintConv => { + 0 => 'None', + 1 => 'Sepia', + 2 => 'Blue', + 3 => 'Purple', + 4 => 'Green', + -559038737 => 'n/a', # (0xdeadbeef) + }, + }, + 0xd8 => { Name => 'ContrastUserDef3', %psInfo }, + 0xdc => { Name => 'SharpnessUserDef3', %psInfo }, + 0xe0 => { Name => 'SaturationUserDef3', %psInfo }, + 0xe4 => { Name => 'ColorToneUserDef3', %psInfo }, + 0xe8 => { Name => 'FilterEffectUserDef3', %psInfo, + PrintConv => { + 0 => 'None', + 1 => 'Yellow', + 2 => 'Orange', + 3 => 'Red', + 4 => 'Green', + -559038737 => 'n/a', # (0xdeadbeef) + }, + }, + 0xec => { Name => 'ToningEffectUserDef3', %psInfo, + PrintConv => { + 0 => 'None', + 1 => 'Sepia', + 2 => 'Blue', + 3 => 'Purple', + 4 => 'Green', + -559038737 => 'n/a', # (0xdeadbeef) + }, + }, + # base picture style names: + 0xf0 => { + Name => 'UserDef1PictureStyle', + Format => 'int16u', + SeparateTable => 'UserDefStyle', + PrintConv => \%userDefStyles, + }, + 0xf2 => { + Name => 'UserDef2PictureStyle', + Format => 'int16u', + SeparateTable => 'UserDefStyle', + PrintConv => \%userDefStyles, + }, + 0xf4 => { + Name => 'UserDef3PictureStyle', + Format => 'int16u', + SeparateTable => 'UserDefStyle', + PrintConv => \%userDefStyles, + }, +); + +# Movie information (MakerNotes tag 0x11) (ref PH) +%Image::ExifTool::Canon::MovieInfo = ( + %binaryDataAttrs, + FORMAT => 'int16u', + FIRST_ENTRY => 1, + GROUPS => { 0 => 'MakerNotes', 2 => 'Video' }, + NOTES => 'Tags written by some Canon cameras when recording video.', + 1 => { # (older PowerShot AVI) + Name => 'FrameRate', + RawConv => '$val == 65535 ? undef: $val', + ValueConvInv => '$val > 65535 ? 65535 : $val', + }, + 2 => { # (older PowerShot AVI) + Name => 'FrameCount', + RawConv => '$val == 65535 ? undef: $val', + ValueConvInv => '$val > 65535 ? 65535 : $val', + }, + # 3 - values: 0x0001 (older PowerShot AVI), 0x4004, 0x4005 + 4 => { + Name => 'FrameCount', + Format => 'int32u', + }, + 6 => { + Name => 'FrameRate', + Format => 'rational32u', + PrintConv => 'int($val * 1000 + 0.5) / 1000', + PrintConvInv => '$val', + }, + # 9/10 - same as 6/7 (FrameRate) + 106 => { + Name => 'Duration', + Format => 'int32u', + ValueConv => '$val / 1000', + ValueConvInv => '$val * 1000', + PrintConv => 'ConvertDuration($val)', + PrintConvInv => q{ + my @a = ($val =~ /\d+(?:\.\d*)?/g); + $val = pop(@a) || 0; # seconds + $val += pop(@a) * 60 if @a; # minutes + $val += pop(@a) * 3600 if @a; # hours + return $val; + }, + }, + 108 => { + Name => 'AudioBitrate', + Groups => { 2 => 'Audio' }, + Format => 'int32u', + PrintConv => 'ConvertBitrate($val)', + PrintConvInv => q{ + $val =~ /^(\d+(?:\.\d*)?) ?([kMG]?bps)?$/ or return undef; + return $1 * {bps=>1,kbps=>1000,Mbps=>1000000,Gbps=>1000000000}->{$2 || 'bps'}; + }, + }, + 110 => { + Name => 'AudioSampleRate', + Groups => { 2 => 'Audio' }, + Format => 'int32u', + }, + 112 => { # (guess) + Name => 'AudioChannels', + Groups => { 2 => 'Audio' }, + Format => 'int32u', + }, + # 114 - values: 0 (60D), 1 (S95) + 116 => { + Name => 'VideoCodec', + Format => 'undef[4]', + # swap bytes if little endian + RawConv => 'GetByteOrder() eq "MM" ? $val : pack("N",unpack("V",$val))', + RawConvInv => 'GetByteOrder() eq "MM" ? $val : pack("N",unpack("V",$val))', + }, + # 125 - same as 10 +); + +# AF information (MakerNotes tag 0x12) - PH +%Image::ExifTool::Canon::AFInfo = ( + PROCESS_PROC => \&ProcessSerialData, + VARS => { ID_LABEL => 'Sequence' }, + FORMAT => 'int16u', + GROUPS => { 0 => 'MakerNotes', 2 => 'Camera' }, + NOTES => q{ + Auto-focus information used by many older Canon models. The values in this + record are sequential, and some have variable sizes based on the value of + NumAFPoints (which may be 1,5,7,9,15,45 or 53). The AFArea coordinates are + given in a system where the image has dimensions given by AFImageWidth and + AFImageHeight, and 0,0 is the image center. The direction of the Y axis + depends on the camera model, with positive Y upwards for EOS models, but + apparently downwards for PowerShot models. + }, + 0 => { + Name => 'NumAFPoints', + }, + 1 => { + Name => 'ValidAFPoints', + Notes => 'number of AF points valid in the following information', + }, + 2 => { + Name => 'CanonImageWidth', + Groups => { 2 => 'Image' }, + }, + 3 => { + Name => 'CanonImageHeight', + Groups => { 2 => 'Image' }, + }, + 4 => { + Name => 'AFImageWidth', + Notes => 'size of image in AF coordinates', + }, + 5 => 'AFImageHeight', + 6 => 'AFAreaWidth', + 7 => 'AFAreaHeight', + 8 => { + Name => 'AFAreaXPositions', + Format => 'int16s[$val{0}]', + }, + 9 => { + Name => 'AFAreaYPositions', + Format => 'int16s[$val{0}]', + }, + 10 => { + Name => 'AFPointsInFocus', + Format => 'int16s[int(($val{0}+15)/16)]', + PrintConv => 'Image::ExifTool::DecodeBits($val, undef, 16)', + }, + 11 => [ + { + Name => 'PrimaryAFPoint', + Condition => q{ + $$self{Model} !~ /EOS/ and + (not $$self{AFInfoCount} or $$self{AFInfoCount} != 36) + }, + }, + { + # (some PowerShot 9-point systems put PrimaryAFPoint after 8 unknown values) + Name => 'Canon_AFInfo_0x000b', + Condition => '$$self{Model} !~ /EOS/', + Format => 'int16u[8]', + Unknown => 1, + }, + # (serial processing stops here for EOS cameras) + ], + 12 => 'PrimaryAFPoint', +); + +# newer AF information (MakerNotes tag 0x26 and 0x32) - PH (A570IS,1DmkIII,40D and G1XmkII) +# (Note: this tag is out of sequence in A570IS maker notes) +%Image::ExifTool::Canon::AFInfo2 = ( + PROCESS_PROC => \&ProcessSerialData, + VARS => { ID_LABEL => 'Sequence' }, + FORMAT => 'int16u', + GROUPS => { 0 => 'MakerNotes', 2 => 'Camera' }, + NOTES => q{ + Newer version of the AFInfo record containing much of the same information + (and coordinate confusion) as the older version. In this record, NumAFPoints + may be 7, 9, 11, 19, 31, 45 or 61, depending on the camera model. + }, + 0 => { + Name => 'AFInfoSize', + Unknown => 1, # normally don't print this out + }, + 1 => { + Name => 'AFAreaMode', + PrintConv => { + 0 => 'Off (Manual Focus)', + 1 => 'AF Point Expansion (surround)', #PH + 2 => 'Single-point AF', + # 3 - n/a + 4 => 'Auto', #forum6237 (AiAF on A570IS) + 5 => 'Face Detect AF', + 6 => 'Face + Tracking', #PH (NC, EOS M, live view) + 7 => 'Zone AF', #46 + 8 => 'AF Point Expansion (4 point)', #46/PH/forum6237 + 9 => 'Spot AF', #46 + 10 => 'AF Point Expansion (8 point)', #forum6237 + 11 => 'Flexizone Multi', #PH (NC, EOS M, live view) + # 12 - also "Flexizone Multi"? (PH) + 13 => 'Flexizone Single', #PH (EOS M default, live view) + 14 => 'Large Zone AF', #PH/forum6237 (7DmkII) + }, + }, + 2 => { + Name => 'NumAFPoints', + RawConv => '$$self{NumAFPoints} = $val', # save for later + }, + 3 => { + Name => 'ValidAFPoints', + Notes => 'number of AF points valid in the following information', + }, + 4 => { + Name => 'CanonImageWidth', + Groups => { 2 => 'Image' }, + }, + 5 => { + Name => 'CanonImageHeight', + Groups => { 2 => 'Image' }, + }, + 6 => { + Name => 'AFImageWidth', + Notes => 'size of image in AF coordinates', + }, + 7 => 'AFImageHeight', + 8 => { + Name => 'AFAreaWidths', + Format => 'int16s[$val{2}]', + }, + 9 => { + Name => 'AFAreaHeights', + Format => 'int16s[$val{2}]', + }, + 10 => { + Name => 'AFAreaXPositions', + Format => 'int16s[$val{2}]', + }, + 11 => { + Name => 'AFAreaYPositions', + Format => 'int16s[$val{2}]', + }, + 12 => { + Name => 'AFPointsInFocus', + Format => 'int16s[int(($val{2}+15)/16)]', + PrintConv => 'Image::ExifTool::DecodeBits($val, undef, 16)', + }, + 13 => [ + { + Name => 'AFPointsSelected', + Condition => '$$self{Model} =~ /EOS/', + Format => 'int16s[int(($val{2}+15)/16)]', + PrintConv => 'Image::ExifTool::DecodeBits($val, undef, 16)', + }, + { + Name => 'Canon_AFInfo2_0x000d', + Format => 'int16s[int(($val{2}+15)/16)+1]', + Unknown => 1, + }, + ], + 14 => { + # usually, but not always, the lowest number AF point in focus + Name => 'PrimaryAFPoint', + Condition => '$$self{Model} !~ /EOS/ and not $$self{AFInfo3}', # (not valid for G1XmkII) + }, +); + +# contrast information (MakerNotes tag 0x27) - PH +%Image::ExifTool::Canon::ContrastInfo = ( + %binaryDataAttrs, + FORMAT => 'int16u', + GROUPS => { 0 => 'MakerNotes', 2 => 'Camera' }, + 4 => { + Name => 'IntelligentContrast', + PrintHex => 1, + PrintConv => { + 0x00 => 'Off', + 0x08 => 'On', + 0xffff => 'n/a', + OTHER => sub { + # DPP shows "On" for any value except 0xffff when bit 0x08 is set + my ($val, $inv) = @_; + if ($inv) { + $val =~ /(0x[0-9a-f]+)/i or $val =~ /(\d+)/; + return $1; + } else { + return sprintf("On (0x%.2x)",$val) if $val & 0x08; + return sprintf("Off (0x%.2x)",$val); + } + }, + }, + }, + # 6 - 0=normal, 257=i-Contrast On +); + +# time information (MakerNotes tag 0x35) - PH (1DX, 5DmkIII) +%Image::ExifTool::Canon::TimeInfo = ( + %binaryDataAttrs, + FORMAT => 'int32s', + FIRST_ENTRY => 1, + GROUPS => { 0 => 'MakerNotes', 2 => 'Time' }, + # 0 - size (16 bytes) + 1 => { + Name => 'TimeZone', + PrintConv => 'Image::ExifTool::TimeZoneString($val)', + PrintConvInv => sub { + my $val = shift; + $val =~ /^([-+]?)(\d{1,2}):?(\d{2})$/ or return undef; + return(($1 eq '-' ? -1 : 1) * ($2 * 60 + $3)); + }, + }, + 2 => { + Name => 'TimeZoneCity', + PrintConvColumns => 3, + PrintConv => { + # [square brackets] = actual time zone for each city + # (round brackets) = observed time zone values from sample images + # --> unobserved entries have not been confirmed! + 0 => 'n/a', # (PowerShot models) + 1 => 'Chatham Islands', # [+12:45] + 2 => 'Wellington', # [+12] (+12:00,DST+0) + 3 => 'Solomon Islands', # [+11] + 4 => 'Sydney', # [+10] (+11:00,DST+1) + 5 => 'Adelaide', # [+9:30] + 6 => 'Tokyo', # [+9] (+09:00,DST+0) + 7 => 'Hong Kong', # [+8] (+08:00,DST+0) + 8 => 'Bangkok', # [+7] (+08:00,DST+1) + 9 => 'Yangon', # [+6:30] + 10 => 'Dhaka', # [+6] (Canon uses old "Dacca" spelling) + 11 => 'Kathmandu', # [+5:45] + 12 => 'Delhi', # [+5:30] + 13 => 'Karachi', # [+5] + 14 => 'Kabul', # [+4:30] + 15 => 'Dubai', # [+4] + 16 => 'Tehran', # [+3:30] + 17 => 'Moscow', # [+4] (+03:00,DST+0) (! changed to +4 permanent DST in 2011) + 18 => 'Cairo', # [+2] + 19 => 'Paris', # [+1] (+01:10,DST+0; +02:00,DST+1) + 20 => 'London', # [0] (+00:00,DST+0) + 21 => 'Azores', # [-1] + 22 => 'Fernando de Noronha', # [-2] + 23 => 'Sao Paulo', # [-3] + 24 => 'Newfoundland', # [-3:30] + 25 => 'Santiago', # [-4] + 26 => 'Caracas', # [-4:30] + 27 => 'New York', # [-5] (-05:00,DST+0; -04:00,DST+1) + 28 => 'Chicago', # [-6] + 29 => 'Denver', # [-7] + 30 => 'Los Angeles', # [-8] (-08:00,DST+0; -07:00,DST+1) + 31 => 'Anchorage', # [-9] + 32 => 'Honolulu', # [-10] + 33 => 'Samoa', # [+13] + 32766 => '(not set)', #(NC) + }, + }, + 3 => { + Name => 'DaylightSavings', + PrintConv => { + 0 => 'Off', + 60 => 'On', + }, + }, +); + +# my color mode information (MakerNotes tag 0x1d) - PH (A570IS) +%Image::ExifTool::Canon::MyColors = ( + %binaryDataAttrs, + FORMAT => 'int16u', + FIRST_ENTRY => 0, + GROUPS => { 0 => 'MakerNotes', 2 => 'Image' }, + 0x02 => { + Name => 'MyColorMode', + PrintConvColumns => 2, + PrintConv => { + 0 => 'Off', + 1 => 'Positive Film', #15 (SD600) + 2 => 'Light Skin Tone', #15 + 3 => 'Dark Skin Tone', #15 + 4 => 'Vivid Blue', #15 + 5 => 'Vivid Green', #15 + 6 => 'Vivid Red', #15 + 7 => 'Color Accent', #15 (A610) (NC) + 8 => 'Color Swap', #15 (A610) + 9 => 'Custom', + 12 => 'Vivid', + 13 => 'Neutral', + 14 => 'Sepia', + 15 => 'B&W', + }, + }, +); + +# face detect information (MakerNotes tag 0x24) - PH (A570IS) +%Image::ExifTool::Canon::FaceDetect1 = ( + %binaryDataAttrs, + FORMAT => 'int16u', + FIRST_ENTRY => 0, + DATAMEMBER => [ 0x02 ], + GROUPS => { 0 => 'MakerNotes', 2 => 'Image' }, + 0x02 => { + Name => 'FacesDetected', + DataMember => 'FacesDetected', + RawConv => '$$self{FacesDetected} = $val', + }, + 0x03 => { + Name => 'FaceDetectFrameSize', + Format => 'int16u[2]', + }, + 0x08 => { + Name => 'Face1Position', + Format => 'int16s[2]', + RawConv => '$$self{FacesDetected} < 1 ? undef: $val', + Notes => q{ + X-Y coordinates for the center of each face in the Face Detect frame at the + time of focus lock. "0 0" is the center, and positive X and Y are to the + right and downwards respectively + }, + }, + 0x0a => { + Name => 'Face2Position', + Format => 'int16s[2]', + RawConv => '$$self{FacesDetected} < 2 ? undef : $val', + }, + 0x0c => { + Name => 'Face3Position', + Format => 'int16s[2]', + RawConv => '$$self{FacesDetected} < 3 ? undef : $val', + }, + 0x0e => { + Name => 'Face4Position', + Format => 'int16s[2]', + RawConv => '$$self{FacesDetected} < 4 ? undef : $val', + }, + 0x10 => { + Name => 'Face5Position', + Format => 'int16s[2]', + RawConv => '$$self{FacesDetected} < 5 ? undef : $val', + }, + 0x12 => { + Name => 'Face6Position', + Format => 'int16s[2]', + RawConv => '$$self{FacesDetected} < 6 ? undef : $val', + }, + 0x14 => { + Name => 'Face7Position', + Format => 'int16s[2]', + RawConv => '$$self{FacesDetected} < 7 ? undef : $val', + }, + 0x16 => { + Name => 'Face8Position', + Format => 'int16s[2]', + RawConv => '$$self{FacesDetected} < 8 ? undef : $val', + }, + 0x18 => { + Name => 'Face9Position', + Format => 'int16s[2]', + RawConv => '$$self{FacesDetected} < 9 ? undef : $val', + }, +); + +# more face detect information (MakerNotes tag 0x25) - PH (A570IS) +%Image::ExifTool::Canon::FaceDetect2 = ( + %binaryDataAttrs, + FORMAT => 'int8u', + FIRST_ENTRY => 0, + GROUPS => { 0 => 'MakerNotes', 2 => 'Image' }, + 0x01 => 'FaceWidth', + 0x02 => 'FacesDetected', +); + +# yet more face detect information (MakerNotes tag 0x2f) - PH (G12) +%Image::ExifTool::Canon::FaceDetect3 = ( + %binaryDataAttrs, + FORMAT => 'int16u', + FIRST_ENTRY => 1, + GROUPS => { 0 => 'MakerNotes', 2 => 'Image' }, + # 0 - size (34 bytes) + # 1 - 1=4:3/16:9,2=1:1/3:2/4:5 + # 2 - normally 1 if faces detected, but sometimes 0 (maybe if face wasn't in captured image?) + 3 => 'FacesDetected', + # 4 - 240=4:3/4:5/1:1,180=16:9,212=3:2 +); + +# File number information (MakerNotes tag 0x93) +%Image::ExifTool::Canon::FileInfo = ( + %binaryDataAttrs, + FORMAT => 'int16s', + FIRST_ENTRY => 1, + GROUPS => { 0 => 'MakerNotes', 2 => 'Image' }, + DATAMEMBER => [ 20 ], + 1 => [ + { #5 + Name => 'FileNumber', + Condition => '$$self{Model} =~ /\b(20D|350D|REBEL XT|Kiss Digital N)\b/', + Format => 'int32u', + # Thanks to Juha Eskelinen for figuring this out: + # [this is an odd bit mapping -- it looks like the file number exists as + # a 16-bit integer containing the high bits, followed by an 8-bit integer + # with the low bits. But it is more convenient to have this in a single + # word, so some bit manipulations are necessary... - PH] + # The bit pattern of the 32-bit word is: + # 31....24 23....16 15.....8 7......0 + # 00000000 ffffffff DDDDDDDD ddFFFFFF + # 0 = zero bits (not part of the file number?) + # f/F = low/high bits of file number + # d/D = low/high bits of directory number + # The directory and file number are then converted into decimal + # and separated by a '-' to give the file number used in the 20D + ValueConv => '(($val&0xffc0)>>6)*10000+(($val>>16)&0xff)+(($val&0x3f)<<8)', + ValueConvInv => q{ + my $d = int($val/10000); + my $f = $val - $d * 10000; + return (($d<<6) & 0xffc0) + (($f & 0xff)<<16) + (($f>>8) & 0x3f); + }, + PrintConv => '$_=$val,s/(\d+)(\d{4})/$1-$2/,$_', + PrintConvInv => '$val=~s/-//g;$val', + }, + { #16 + Name => 'FileNumber', + Condition => '$$self{Model} =~ /\b(30D|400D|REBEL XTi|Kiss Digital X|K236)\b/', + Format => 'int32u', + Notes => q{ + the location of the upper 4 bits of the directory number is a mystery for + the EOS 30D, so the reported directory number will be incorrect for original + images with a directory number of 164 or greater + }, + # Thanks to Emil Sit for figuring this out: + # [more insane bit maniplations like the 20D/350D above, but this time we + # appear to have lost the upper 4 bits of the directory number (this was + # verified through tests with directory numbers 100, 222, 801 and 999) - PH] + # The bit pattern for the 30D is: (see 20D notes above for more information) + # 31....24 23....16 15.....8 7......0 + # 00000000 ffff0000 ddddddFF FFFFFFFF + # [NOTE: the 4 high order directory bits don't appear in this record, but + # I have chosen to write them into bits 16-19 since these 4 zero bits look + # very suspicious, and are a convenient place to store this information - PH] + ValueConv => q{ + my $d = ($val & 0xffc00) >> 10; + # we know there are missing bits if directory number is < 100 + $d += 0x40 while $d < 100; # (repair the damage as best we can) + return $d*10000 + (($val&0x3ff)<<4) + (($val>>20)&0x0f); + }, + ValueConvInv => q{ + my $d = int($val/10000); + my $f = $val - $d * 10000; + return ($d << 10) + (($f>>4)&0x3ff) + (($f&0x0f)<<20); + }, + PrintConv => '$_=$val,s/(\d+)(\d{4})/$1-$2/,$_', + PrintConvInv => '$val=~s/-//g;$val', + }, + { #7 (1D, 1Ds) + Name => 'ShutterCount', + Condition => 'GetByteOrder() eq "MM"', + Format => 'int32u', + }, + { #7 (1DmkII, 1DSmkII, 1DSmkIIN) + Name => 'ShutterCount', + # ref http://www.luminous-landscape.com/forum/index.php?topic=36469 : + Notes => q{ + there are reports that the ShutterCount changed when loading a settings file + on the 1DSmkII + }, + Condition => '$$self{Model} =~ /\b1Ds? Mark II\b/', + Format => 'int32u', + ValueConv => '($val>>16)|(($val&0xffff)<<16)', + ValueConvInv => '($val>>16)|(($val&0xffff)<<16)', + }, + # 5D gives a single byte value (unknown) + # 40D stores all zeros + ], + 3 => { #PH + Name => 'BracketMode', + PrintConv => { + 0 => 'Off', + 1 => 'AEB', + 2 => 'FEB', + 3 => 'ISO', + 4 => 'WB', + }, + }, + 4 => 'BracketValue', #PH + 5 => 'BracketShotNumber', #PH + 6 => { #PH + Name => 'RawJpgQuality', + RawConv => '$val<=0 ? undef : $val', + PrintConv => \%canonQuality, + }, + 7 => { #PH + Name => 'RawJpgSize', + RawConv => '$val<0 ? undef : $val', + PrintConv => \%canonImageSize, + }, + 8 => { #PH + Name => 'LongExposureNoiseReduction2', + Notes => q{ + for some modules this gives the long exposure noise reduction applied to the + image, but for other models this just reflects the setting independent of + whether or not it was applied + }, + RawConv => '$val<0 ? undef : $val', + PrintConv => { + 0 => 'Off', + 1 => 'On (1D)', + 3 => 'On', + 4 => 'Auto', + }, + }, + 9 => { #PH + Name => 'WBBracketMode', + PrintConv => { + 0 => 'Off', + 1 => 'On (shift AB)', + 2 => 'On (shift GM)', + }, + }, + 12 => 'WBBracketValueAB', #PH + 13 => 'WBBracketValueGM', #PH + 14 => { #PH + Name => 'FilterEffect', + RawConv => '$val==-1 ? undef : $val', + PrintConv => { + 0 => 'None', + 1 => 'Yellow', + 2 => 'Orange', + 3 => 'Red', + 4 => 'Green', + }, + }, + 15 => { #PH + Name => 'ToningEffect', + RawConv => '$val==-1 ? undef : $val', + PrintConv => { + 0 => 'None', + 1 => 'Sepia', + 2 => 'Blue', + 3 => 'Purple', + 4 => 'Green', + }, + }, + 16 => { #PH + %ciMacroMagnification, + # MP-E 65mm on 5DmkII: 44=5x,52~=3.9x,56~=3.3x,62~=2.6x,75=1x + # ME-E 65mm on 40D/450D: 72 for all samples (not valid) + Condition => q{ + $$self{LensType} and $$self{LensType} == 124 and + $$self{Model} !~ /\b(40D|450D|REBEL XSi|Kiss X2)\b/ + }, + Notes => q{ + currently decoded only for the MP-E 65mm f/2.8 1-5x Macro Photo, and not + valid for all camera models + }, + }, + # 17 - values: 0, 3, 4 + # 18 - same as LiveViewShooting for all my samples (5DmkII, 50D) - PH + 19 => { #PH + # Note: this value is not displayed by Canon ImageBrowser for the following + # models with the live view feature: 1DmkIII, 1DSmkIII, 40D, 450D, 1000D + # (this tag could be valid only for some firmware versions: + # http://www.breezesys.com/forum/showthread.php?p=16980) + Name => 'LiveViewShooting', + PrintConv => \%offOn, + }, + 20 => { #47 + Name => 'FocusDistanceUpper', + DataMember => 'FocusDistanceUpper2', + Format => 'int16u', + RawConv => '($$self{FocusDistanceUpper2} = $val) || undef', + ValueConv => '$val / 100', + ValueConvInv => '$val * 100', + PrintConv => '$val > 655.345 ? "inf" : "$val m"', + PrintConvInv => '$val =~ s/ ?m$//; IsFloat($val) ? $val : 655.35', + }, + 21 => { #47 + Name => 'FocusDistanceLower', + Condition => '$$self{FocusDistanceUpper2}', + Format => 'int16u', + ValueConv => '$val / 100', + ValueConvInv => '$val * 100', + PrintConv => '$val > 655.345 ? "inf" : "$val m"', + PrintConvInv => '$val =~ s/ ?m$//; IsFloat($val) ? $val : 655.35', + }, + # 22 - values: 0, 1 + # 23 - values: 0, 21, 22 + 25 => { #PH + Name => 'FlashExposureLock', + PrintConv => \%offOn, + }, +); + +# Internal serial number information (MakerNotes tag 0x96) (ref PH) +%Image::ExifTool::Canon::SerialInfo = ( + %binaryDataAttrs, + FIRST_ENTRY => 0, + GROUPS => { 0 => 'MakerNotes', 2 => 'Camera' }, + 9 => { + Name => 'InternalSerialNumber', + Format => 'string', + }, +); + +# Cropping information (MakerNotes tag 0x98) (ref PH) +%Image::ExifTool::Canon::CropInfo = ( + %binaryDataAttrs, + FORMAT => 'int16u', + FIRST_ENTRY => 0, + GROUPS => { 0 => 'MakerNotes', 2 => 'Camera' }, + 0 => 'CropLeftMargin', # (NC, may be right) + 1 => 'CropRightMargin', + 2 => 'CropTopMargin', # (NC, may be bottom) + 3 => 'CropBottomMargin', +); + +# Aspect ratio information (MakerNotes tag 0x9a) (ref PH) +%Image::ExifTool::Canon::AspectInfo = ( + %binaryDataAttrs, + FORMAT => 'int32u', + FIRST_ENTRY => 0, + GROUPS => { 0 => 'MakerNotes', 2 => 'Camera' }, + 0 => { + Name => 'AspectRatio', + PrintConv => { + 0 => '3:2', + 1 => '1:1', + 2 => '4:3', + 7 => '16:9', + 8 => '4:5', + }, + }, + # (could use better names for these, or the Crop tags above, or both) + 1 => 'CroppedImageWidth', + 2 => 'CroppedImageHeight', + 3 => 'CroppedImageLeft', #forum4138 + 4 => 'CroppedImageTop', #ditto +); + +# Color information (MakerNotes tag 0xa0) +%Image::ExifTool::Canon::Processing = ( + %binaryDataAttrs, + FORMAT => 'int16s', + FIRST_ENTRY => 1, + GROUPS => { 0 => 'MakerNotes', 2 => 'Image' }, + 1 => { #PH + Name => 'ToneCurve', + PrintConv => { + 0 => 'Standard', + 1 => 'Manual', + 2 => 'Custom', + }, + }, + 2 => { #12 + Name => 'Sharpness', + Notes => 'all models except the 20D and 350D', + Condition => '$$self{Model} !~ /\b(20D|350D|REBEL XT|Kiss Digital N)\b/', + Priority => 0, # (maybe not as reliable as other sharpness values) + }, + 3 => { #PH + Name => 'SharpnessFrequency', # PatternSharpness? + PrintConvColumns => 2, + PrintConv => { + 0 => 'n/a', + 1 => 'Lowest', + 2 => 'Low', + 3 => 'Standard', + 4 => 'High', + 5 => 'Highest', + }, + }, + 4 => 'SensorRedLevel', #PH + 5 => 'SensorBlueLevel', #PH + 6 => 'WhiteBalanceRed', #PH + 7 => 'WhiteBalanceBlue', #PH + 8 => { #PH + Name => 'WhiteBalance', + RawConv => '$val < 0 ? undef : $val', + PrintConv => \%canonWhiteBalance, + SeparateTable => 1, + }, + 9 => 'ColorTemperature', #6 + 10 => { #12 + Name => 'PictureStyle', + Flags => ['PrintHex','SeparateTable'], + PrintConv => \%pictureStyles, + }, + 11 => { #PH + Name => 'DigitalGain', + ValueConv => '$val / 10', + ValueConvInv => '$val * 10', + }, + 12 => { #PH + Name => 'WBShiftAB', + Notes => 'positive is a shift toward amber', + }, + 13 => { #PH + Name => 'WBShiftGM', + Notes => 'positive is a shift toward green', + }, +); + +# Color balance information (MakerNotes tag 0xa9) (ref PH) +%Image::ExifTool::Canon::ColorBalance = ( + %binaryDataAttrs, + NOTES => 'These tags are used by the 10D and 300D.', + FORMAT => 'int16s', + FIRST_ENTRY => 0, + GROUPS => { 0 => 'MakerNotes', 2 => 'Camera' }, + # red,green1,green2,blue (ref 2) + 1 => { Name => 'WB_RGGBLevelsAuto', Format => 'int16s[4]' }, + 5 => { Name => 'WB_RGGBLevelsDaylight', Format => 'int16s[4]' }, + 9 => { Name => 'WB_RGGBLevelsShade', Format => 'int16s[4]' }, + 13 => { Name => 'WB_RGGBLevelsCloudy', Format => 'int16s[4]' }, + 17 => { Name => 'WB_RGGBLevelsTungsten', Format => 'int16s[4]' }, + 21 => { Name => 'WB_RGGBLevelsFluorescent',Format => 'int16s[4]' }, + 25 => { Name => 'WB_RGGBLevelsFlash', Format => 'int16s[4]' }, + 29 => { Name => 'WB_RGGBLevelsCustom', Format => 'int16s[4]' }, # (actually black levels for D60, ref IB) + 33 => { Name => 'WB_RGGBLevelsKelvin', Format => 'int16s[4]' }, + 37 => { Name => 'WB_RGGBBlackLevels', Format => 'int16s[4]' }, #IB +); + +# Measured color levels (MakerNotes tag 0xaa) (ref 37) +%Image::ExifTool::Canon::MeasuredColor = ( + %binaryDataAttrs, + FORMAT => 'int16u', + FIRST_ENTRY => 1, + GROUPS => { 0 => 'MakerNotes', 2 => 'Camera' }, + 1 => { + # this is basically the inverse of WB_RGGBLevelsMeasured (ref 37) + Name => 'MeasuredRGGB', + Format => 'int16u[4]', + }, + # 5 - observed values: 0, 1 - PH +); + +# Flags information (MakerNotes tag 0xb0) (ref PH) +%Image::ExifTool::Canon::Flags = ( + %binaryDataAttrs, + FORMAT => 'int16s', + FIRST_ENTRY => 1, + GROUPS => { 0 => 'MakerNotes', 2 => 'Camera' }, + 1 => 'ModifiedParamFlag', +); + +# Modified information (MakerNotes tag 0xb1) (ref PH) +%Image::ExifTool::Canon::ModifiedInfo = ( + %binaryDataAttrs, + FORMAT => 'int16s', + FIRST_ENTRY => 1, + GROUPS => { 0 => 'MakerNotes', 2 => 'Camera' }, + 1 => { + Name => 'ModifiedToneCurve', + PrintConv => { + 0 => 'Standard', + 1 => 'Manual', + 2 => 'Custom', + }, + }, + 2 => { + Name => 'ModifiedSharpness', + Notes => '1D and 5D only', + Condition => '$$self{Model} =~ /\b(1D|5D)/', + }, + 3 => { + Name => 'ModifiedSharpnessFreq', # ModifiedPatternSharpness? + PrintConv => { + 0 => 'n/a', + 1 => 'Lowest', + 2 => 'Low', + 3 => 'Standard', + 4 => 'High', + 5 => 'Highest', + }, + }, + 4 => 'ModifiedSensorRedLevel', + 5 => 'ModifiedSensorBlueLevel', + 6 => 'ModifiedWhiteBalanceRed', + 7 => 'ModifiedWhiteBalanceBlue', + 8 => { + Name => 'ModifiedWhiteBalance', + PrintConv => \%canonWhiteBalance, + SeparateTable => 'WhiteBalance', + }, + 9 => 'ModifiedColorTemp', + 10 => { + Name => 'ModifiedPictureStyle', + PrintHex => 1, + SeparateTable => 'PictureStyle', + PrintConv => \%pictureStyles, + }, + 11 => { + Name => 'ModifiedDigitalGain', + ValueConv => '$val / 10', + ValueConvInv => '$val * 10', + }, +); + +# Preview image information (MakerNotes tag 0xb6) +# - The 300D writes a 1536x1024 preview image that is accessed +# through this information - decoded by PH 12/14/03 +%Image::ExifTool::Canon::PreviewImageInfo = ( + %binaryDataAttrs, + FORMAT => 'int32u', + FIRST_ENTRY => 1, + IS_OFFSET => [ 5 ], # tag 5 is 'IsOffset' + GROUPS => { 0 => 'MakerNotes', 2 => 'Image' }, +# the size of the preview block in 2-byte increments +# 0 => { +# Name => 'PreviewImageInfoWords', +# }, + 1 => { + Name => 'PreviewQuality', + PrintConv => \%canonQuality, + }, + 2 => { + Name => 'PreviewImageLength', + OffsetPair => 5, # point to associated offset + DataTag => 'PreviewImage', + WriteGroup => 'MakerNotes', + Protected => 2, + }, + 3 => 'PreviewImageWidth', + 4 => 'PreviewImageHeight', + 5 => { + Name => 'PreviewImageStart', + Flags => 'IsOffset', + OffsetPair => 2, # associated byte count tagID + DataTag => 'PreviewImage', + WriteGroup => 'MakerNotes', + Protected => 2, + }, + # NOTE: The size of the PreviewImageInfo structure is incorrectly + # written as 48 bytes (Count=12, Format=int32u), but only the first + # 6 int32u values actually exist +); + +# Sensor information (MakerNotes tag 0xe0) (ref 12) +%Image::ExifTool::Canon::SensorInfo = ( + PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData, + FORMAT => 'int16s', + FIRST_ENTRY => 1, + GROUPS => { 0 => 'MakerNotes', 2 => 'Image' }, + # Note: Don't make these writable because it confuses Canon decoding software + # if these are changed + 1 => 'SensorWidth', + 2 => 'SensorHeight', + 5 => 'SensorLeftBorder', #2 + 6 => 'SensorTopBorder', #2 + 7 => 'SensorRightBorder', #2 + 8 => 'SensorBottomBorder', #2 + 9 => { #22 + Name => 'BlackMaskLeftBorder', + Notes => q{ + coordinates for the area to the left or right of the image used to calculate + the average black level + }, + }, + 10 => 'BlackMaskTopBorder', #22 + 11 => 'BlackMaskRightBorder', #22 + 12 => 'BlackMaskBottomBorder', #22 +); + +# Color data (MakerNotes tag 0x4001, count=582) (ref 12) +%Image::ExifTool::Canon::ColorData1 = ( + %binaryDataAttrs, + NOTES => 'These tags are used by the 20D and 350D.', + FORMAT => 'int16s', + FIRST_ENTRY => 0, + GROUPS => { 0 => 'MakerNotes', 2 => 'Camera' }, + IS_SUBDIR => [ 0x4b ], + # 0x00: size of record in bytes - PH + # (dcraw 8.81 uses index 0x19 for WB) + 0x19 => { Name => 'WB_RGGBLevelsAsShot', Format => 'int16s[4]' }, + 0x1d => 'ColorTempAsShot', + 0x1e => { Name => 'WB_RGGBLevelsAuto', Format => 'int16s[4]' }, + 0x22 => 'ColorTempAuto', + 0x23 => { Name => 'WB_RGGBLevelsDaylight', Format => 'int16s[4]' }, + 0x27 => 'ColorTempDaylight', + 0x28 => { Name => 'WB_RGGBLevelsShade', Format => 'int16s[4]' }, + 0x2c => 'ColorTempShade', + 0x2d => { Name => 'WB_RGGBLevelsCloudy', Format => 'int16s[4]' }, + 0x31 => 'ColorTempCloudy', + 0x32 => { Name => 'WB_RGGBLevelsTungsten', Format => 'int16s[4]' }, + 0x36 => 'ColorTempTungsten', + 0x37 => { Name => 'WB_RGGBLevelsFluorescent', Format => 'int16s[4]' }, + 0x3b => 'ColorTempFluorescent', + 0x3c => { Name => 'WB_RGGBLevelsFlash', Format => 'int16s[4]' }, + 0x40 => 'ColorTempFlash', + 0x41 => { Name => 'WB_RGGBLevelsCustom1', Format => 'int16s[4]' }, + 0x45 => 'ColorTempCustom1', + 0x46 => { Name => 'WB_RGGBLevelsCustom2', Format => 'int16s[4]' }, + 0x4a => 'ColorTempCustom2', + 0x4b => { #PH + Name => 'ColorCalib', + Format => 'undef[120]', + Unknown => 1, # (all tags are unknown, so we can avoid processing entire directory) + Notes => 'A, B, C, Temperature', + SubDirectory => { TagTable => 'Image::ExifTool::Canon::ColorCalib' } + }, +); + +# Color data (MakerNotes tag 0x4001, count=653) (ref 12) +%Image::ExifTool::Canon::ColorData2 = ( + %binaryDataAttrs, + NOTES => 'These tags are used by the 1DmkII and 1DSmkII.', + FORMAT => 'int16s', + FIRST_ENTRY => 0, + GROUPS => { 0 => 'MakerNotes', 2 => 'Camera' }, + IS_SUBDIR => [ 0xa4 ], + 0x18 => { Name => 'WB_RGGBLevelsAuto', Format => 'int16s[4]' }, + 0x1c => 'ColorTempAuto', + 0x1d => { Name => 'WB_RGGBLevelsUnknown', Format => 'int16s[4]', Unknown => 1 }, + 0x21 => { Name => 'ColorTempUnknown', Unknown => 1 }, + # (dcraw 8.81 uses index 0x22 for WB) + 0x22 => { Name => 'WB_RGGBLevelsAsShot', Format => 'int16s[4]' }, + 0x26 => 'ColorTempAsShot', + 0x27 => { Name => 'WB_RGGBLevelsDaylight', Format => 'int16s[4]' }, + 0x2b => 'ColorTempDaylight', + 0x2c => { Name => 'WB_RGGBLevelsShade', Format => 'int16s[4]' }, + 0x30 => 'ColorTempShade', + 0x31 => { Name => 'WB_RGGBLevelsCloudy', Format => 'int16s[4]' }, + 0x35 => 'ColorTempCloudy', + 0x36 => { Name => 'WB_RGGBLevelsTungsten', Format => 'int16s[4]' }, + 0x3a => 'ColorTempTungsten', + 0x3b => { Name => 'WB_RGGBLevelsFluorescent',Format => 'int16s[4]' }, + 0x3f => 'ColorTempFluorescent', + 0x40 => { Name => 'WB_RGGBLevelsKelvin', Format => 'int16s[4]' }, + 0x44 => 'ColorTempKelvin', + 0x45 => { Name => 'WB_RGGBLevelsFlash', Format => 'int16s[4]' }, + 0x49 => 'ColorTempFlash', + 0x4a => { Name => 'WB_RGGBLevelsUnknown2', Format => 'int16s[4]', Unknown => 1 }, + 0x4e => { Name => 'ColorTempUnknown2', Unknown => 1 }, + 0x4f => { Name => 'WB_RGGBLevelsUnknown3', Format => 'int16s[4]', Unknown => 1 }, + 0x53 => { Name => 'ColorTempUnknown3', Unknown => 1 }, + 0x54 => { Name => 'WB_RGGBLevelsUnknown4', Format => 'int16s[4]', Unknown => 1 }, + 0x58 => { Name => 'ColorTempUnknown4', Unknown => 1 }, + 0x59 => { Name => 'WB_RGGBLevelsUnknown5', Format => 'int16s[4]', Unknown => 1 }, + 0x5d => { Name => 'ColorTempUnknown5', Unknown => 1 }, + 0x5e => { Name => 'WB_RGGBLevelsUnknown6', Format => 'int16s[4]', Unknown => 1 }, + 0x62 => { Name => 'ColorTempUnknown6', Unknown => 1 }, + 0x63 => { Name => 'WB_RGGBLevelsUnknown7', Format => 'int16s[4]', Unknown => 1 }, + 0x67 => { Name => 'ColorTempUnknown7', Unknown => 1 }, + 0x68 => { Name => 'WB_RGGBLevelsUnknown8', Format => 'int16s[4]', Unknown => 1 }, + 0x6c => { Name => 'ColorTempUnknown8', Unknown => 1 }, + 0x6d => { Name => 'WB_RGGBLevelsUnknown9', Format => 'int16s[4]', Unknown => 1 }, + 0x71 => { Name => 'ColorTempUnknown9', Unknown => 1 }, + 0x72 => { Name => 'WB_RGGBLevelsUnknown10', Format => 'int16s[4]', Unknown => 1 }, + 0x76 => { Name => 'ColorTempUnknown10', Unknown => 1 }, + 0x77 => { Name => 'WB_RGGBLevelsUnknown11', Format => 'int16s[4]', Unknown => 1 }, + 0x7b => { Name => 'ColorTempUnknown11', Unknown => 1 }, + 0x7c => { Name => 'WB_RGGBLevelsUnknown12', Format => 'int16s[4]', Unknown => 1 }, + 0x80 => { Name => 'ColorTempUnknown12', Unknown => 1 }, + 0x81 => { Name => 'WB_RGGBLevelsUnknown13', Format => 'int16s[4]', Unknown => 1 }, + 0x85 => { Name => 'ColorTempUnknown13', Unknown => 1 }, + 0x86 => { Name => 'WB_RGGBLevelsUnknown14', Format => 'int16s[4]', Unknown => 1 }, + 0x8a => { Name => 'ColorTempUnknown14', Unknown => 1 }, + 0x8b => { Name => 'WB_RGGBLevelsUnknown15', Format => 'int16s[4]', Unknown => 1 }, + 0x8f => { Name => 'ColorTempUnknown15', Unknown => 1 }, + 0x90 => { Name => 'WB_RGGBLevelsPC1', Format => 'int16s[4]' }, + 0x94 => 'ColorTempPC1', + 0x95 => { Name => 'WB_RGGBLevelsPC2', Format => 'int16s[4]' }, + 0x99 => 'ColorTempPC2', + 0x9a => { Name => 'WB_RGGBLevelsPC3', Format => 'int16s[4]' }, + 0x9e => 'ColorTempPC3', + 0x9f => { Name => 'WB_RGGBLevelsUnknown16', Format => 'int16s[4]', Unknown => 1 }, + 0xa3 => { Name => 'ColorTempUnknown16', Unknown => 1 }, + 0xa4 => { #PH + Name => 'ColorCalib', + Format => 'undef[120]', + Unknown => 1, + Notes => 'A, B, C, Temperature', + SubDirectory => { TagTable => 'Image::ExifTool::Canon::ColorCalib' } + }, + 0x26a => { #PH + Name => 'RawMeasuredRGGB', + Format => 'int32u[4]', + Notes => 'raw MeasuredRGGB values, before normalization', + # swap words because the word ordering is big-endian, opposite to the byte ordering + ValueConv => \&SwapWords, + ValueConvInv => \&SwapWords, + }, +); + +# Color data (MakerNotes tag 0x4001, count=796) (ref 12) +%Image::ExifTool::Canon::ColorData3 = ( + %binaryDataAttrs, + NOTES => 'These tags are used by the 1DmkIIN, 5D, 30D and 400D.', + FORMAT => 'int16s', + FIRST_ENTRY => 0, + GROUPS => { 0 => 'MakerNotes', 2 => 'Camera' }, + IS_SUBDIR => [ 0x85 ], + 0x00 => { #PH + Name => 'ColorDataVersion', + PrintConv => { + 1 => '1 (1DmkIIN/5D/30D/400D)', + }, + }, + # 0x01-0x3e: RGGB coefficients, apparently specific to the + # individual camera and possibly used for color calibration (ref 37) + # (dcraw 8.81 uses index 0x3f for WB) + 0x3f => { Name => 'WB_RGGBLevelsAsShot', Format => 'int16s[4]' }, + 0x43 => 'ColorTempAsShot', + 0x44 => { Name => 'WB_RGGBLevelsAuto', Format => 'int16s[4]' }, + 0x48 => 'ColorTempAuto', + # not sure exactly what 'Measured' values mean... + 0x49 => { Name => 'WB_RGGBLevelsMeasured', Format => 'int16s[4]' }, + 0x4d => 'ColorTempMeasured', + 0x4e => { Name => 'WB_RGGBLevelsDaylight', Format => 'int16s[4]' }, + 0x52 => 'ColorTempDaylight', + 0x53 => { Name => 'WB_RGGBLevelsShade', Format => 'int16s[4]' }, + 0x57 => 'ColorTempShade', + 0x58 => { Name => 'WB_RGGBLevelsCloudy', Format => 'int16s[4]' }, + 0x5c => 'ColorTempCloudy', + 0x5d => { Name => 'WB_RGGBLevelsTungsten', Format => 'int16s[4]' }, + 0x61 => 'ColorTempTungsten', + 0x62 => { Name => 'WB_RGGBLevelsFluorescent', Format => 'int16s[4]' }, + 0x66 => 'ColorTempFluorescent', + 0x67 => { Name => 'WB_RGGBLevelsKelvin', Format => 'int16s[4]' }, + 0x6b => 'ColorTempKelvin', + 0x6c => { Name => 'WB_RGGBLevelsFlash', Format => 'int16s[4]' }, + 0x70 => 'ColorTempFlash', + 0x71 => { Name => 'WB_RGGBLevelsPC1', Format => 'int16s[4]' }, + 0x75 => 'ColorTempPC1', + 0x76 => { Name => 'WB_RGGBLevelsPC2', Format => 'int16s[4]' }, + 0x7a => 'ColorTempPC2', + 0x7b => { Name => 'WB_RGGBLevelsPC3', Format => 'int16s[4]' }, + 0x7f => 'ColorTempPC3', + 0x80 => { Name => 'WB_RGGBLevelsCustom', Format => 'int16s[4]' }, + 0x84 => 'ColorTempCustom', + 0x85 => { #37 + Name => 'ColorCalib', + Format => 'undef[120]', + Unknown => 1, + Notes => 'B, C, A, Temperature', + SubDirectory => { TagTable => 'Image::ExifTool::Canon::ColorCalib' } + }, + 0xc4 => { #IB + Name => 'PerChannelBlackLevel', + Format => 'int16u[4]', + }, + # 0xc8-0x1c7: some sort of color table (ref 37) + 0x248 => { #37 + Name => 'FlashOutput', + ValueConv => '$val >= 255 ? 255 : exp(($val-200)/16*log(2))', + ValueConvInv => '$val == 255 ? 255 : 200 + log($val)*16/log(2)', + PrintConv => '$val == 255 ? "Strobe or Misfire" : sprintf("%.0f%%", $val * 100)', + PrintConvInv => '$val =~ /^(\d(\.?\d*))/ ? $1 / 100 : 255', + }, + 0x249 => { #37 + Name => 'FlashBatteryLevel', + # calibration points for external flash: 144=3.76V (almost empty), 192=5.24V (full) + # - have seen a value of 201 with internal flash + PrintConv => '$val ? sprintf("%.2fV", $val * 5 / 186) : "n/a"', + PrintConvInv => '$val=~/^(\d+\.\d+)\s*V?$/i ? int($val*186/5+0.5) : 0', + }, + 0x24a => { #37 + Name => 'ColorTempFlashData', + # 0 for no external flash, 35980 for 'Strobe or Misfire' + # (lower than ColorTempFlash by up to 200 degrees) + RawConv => '($val < 2000 or $val > 12000) ? undef : $val', + }, + # 0x24b: inverse relationship with flash power (ref 37) + # 0x286: has value 256 for correct exposure, less for under exposure (seen 96 minimum) (ref 37) + 0x287 => { #37 + Name => 'MeasuredRGGBData', + Format => 'int32u[4]', + Notes => 'MeasuredRGGB may be derived from these data values', + # swap words because the word ordering is big-endian, opposite to the byte ordering + ValueConv => \&SwapWords, + ValueConvInv => \&SwapWords, + }, + # 0x297: ranges from -10 to 30, higher for high ISO (ref 37) +); + +# Color data (MakerNotes tag 0x4001, count=674|692|702|1227|1250|1251|1337|1338|1346) (ref PH) +%Image::ExifTool::Canon::ColorData4 = ( + %binaryDataAttrs, + NOTES => q{ + These tags are used by the 1DmkIII, 1DSmkIII, 1DmkIV, 5DmkII, 7D, 40D, 50D, + 60D, 450D, 500D, 550D, 1000D and 1100D. + }, + FORMAT => 'int16s', + FIRST_ENTRY => 0, + GROUPS => { 0 => 'MakerNotes', 2 => 'Camera' }, + IS_SUBDIR => [ 0x3f, 0xa8 ], + DATAMEMBER => [ 0x00 ], + 0x00 => { + Name => 'ColorDataVersion', + DataMember => 'ColorDataVersion', + RawConv => '$$self{ColorDataVersion} = $val', + PrintConv => { + 2 => '2 (1DmkIII)', + 3 => '3 (40D)', + 4 => '4 (1DSmkIII)', + 5 => '5 (450D/1000D)', + 6 => '6 (50D/5DmkII)', + 7 => '7 (500D/550D/7D/1DmkIV)', + 9 => '9 (60D/1100D)', + }, + }, + # 0x01-0x18: unknown RGGB coefficients (int16s[4]) (50D) + # (dcraw 8.81 uses index 0x3f for WB) + 0x3f => { + Name => 'ColorCoefs', + Format => 'undef[210]', # ColorTempUnknown11 is last entry + SubDirectory => { TagTable => 'Image::ExifTool::Canon::ColorCoefs' } + }, + 0xa8 => { + Name => 'ColorCalib', + Format => 'undef[120]', + Unknown => 1, + Notes => 'B, C, A, Temperature', + SubDirectory => { TagTable => 'Image::ExifTool::Canon::ColorCalib' } + }, + 0x0e7 => { Name => 'AverageBlackLevel', Format => 'int16u[4]' }, #IB + 0x280 => { #PH + Name => 'RawMeasuredRGGB', + Format => 'int32u[4]', + Notes => 'raw MeasuredRGGB values, before normalization', + # swap words because the word ordering is big-endian, opposite to the byte ordering + ValueConv => \&SwapWords, + ValueConvInv => \&SwapWords, + }, + 0x2b4 => { #IB + Name => 'PerChannelBlackLevel', + Condition => '$$self{ColorDataVersion} == 4 or $$self{ColorDataVersion} == 5', + Format => 'int16u[4]', + }, + 0x2b8 => { #IB + Name => 'NormalWhiteLevel', + Condition => '$$self{ColorDataVersion} == 4 or $$self{ColorDataVersion} == 5', + Format => 'int16u', + RawConv => '$val || undef', + }, + 0x2b9 => { #IB + Name => 'SpecularWhiteLevel', + Condition => '$$self{ColorDataVersion} == 4 or $$self{ColorDataVersion} == 5', + Format => 'int16u', + }, + 0x2ba => { #IB + Name => 'LinearityUpperMargin', + Condition => '$$self{ColorDataVersion} == 4 or $$self{ColorDataVersion} == 5', + Format => 'int16u', + }, + 0x2cb => { #IB + Name => 'PerChannelBlackLevel', + Condition => '$$self{ColorDataVersion} == 6 or $$self{ColorDataVersion} == 7', + Format => 'int16u[4]', + }, + 0x2cf => [{ #IB + Name => 'NormalWhiteLevel', + Condition => '$$self{ColorDataVersion} == 6 or $$self{ColorDataVersion} == 7', + Format => 'int16u', + RawConv => '$val || undef', + },{ + Name => 'PerChannelBlackLevel', + Condition => '$$self{ColorDataVersion} == 9', + Format => 'int16u[4]', + }], + 0x2d0 => { #IB + Name => 'SpecularWhiteLevel', + Condition => '$$self{ColorDataVersion} == 6 or $$self{ColorDataVersion} == 7', + Format => 'int16u', + }, + 0x2d1 => { #IB + Name => 'LinearityUpperMargin', + Condition => '$$self{ColorDataVersion} == 6 or $$self{ColorDataVersion} == 7', + Format => 'int16u', + }, + 0x2d3 => { #IB + Name => 'NormalWhiteLevel', + Condition => '$$self{ColorDataVersion} == 9', + Format => 'int16u', + RawConv => '$val || undef', + }, + 0x2d4 => { #IB + Name => 'SpecularWhiteLevel', + Condition => '$$self{ColorDataVersion} == 9', + Format => 'int16u', + }, + 0x2d5 => { #IB + Name => 'LinearityUpperMargin', + Condition => '$$self{ColorDataVersion} == 9', + Format => 'int16u', + }, +); + +# color coefficients (ref PH) +%Image::ExifTool::Canon::ColorCoefs = ( + %binaryDataAttrs, + FORMAT => 'int16s', + FIRST_ENTRY => 0, + GROUPS => { 0 => 'MakerNotes', 2 => 'Camera' }, + 0x00 => { Name => 'WB_RGGBLevelsAsShot', Format => 'int16s[4]' }, + 0x04 => 'ColorTempAsShot', + 0x05 => { Name => 'WB_RGGBLevelsAuto', Format => 'int16s[4]' }, + 0x09 => 'ColorTempAuto', + 0x0a => { Name => 'WB_RGGBLevelsMeasured', Format => 'int16s[4]' }, + 0x0e => 'ColorTempMeasured', + # the following Unknown values are set for the 50D and 5DmkII, and the + # SRAW images of the 40D, and affect thumbnail display for the 50D/5DmkII + # and conversion for all modes of the 40D + 0x0f => { Name => 'WB_RGGBLevelsUnknown', Format => 'int16s[4]', Unknown => 1 }, + 0x13 => { Name => 'ColorTempUnknown', Unknown => 1 }, + 0x14 => { Name => 'WB_RGGBLevelsDaylight', Format => 'int16s[4]' }, + 0x18 => 'ColorTempDaylight', + 0x19 => { Name => 'WB_RGGBLevelsShade', Format => 'int16s[4]' }, + 0x1d => 'ColorTempShade', + 0x1e => { Name => 'WB_RGGBLevelsCloudy', Format => 'int16s[4]' }, + 0x22 => 'ColorTempCloudy', + 0x23 => { Name => 'WB_RGGBLevelsTungsten', Format => 'int16s[4]' }, + 0x27 => 'ColorTempTungsten', + 0x28 => { Name => 'WB_RGGBLevelsFluorescent',Format => 'int16s[4]' }, + 0x2c => 'ColorTempFluorescent', + # (changing the Kelvin values has no effect on image in DPP... why not?) + 0x2d => { Name => 'WB_RGGBLevelsKelvin', Format => 'int16s[4]' }, + 0x31 => 'ColorTempKelvin', + 0x32 => { Name => 'WB_RGGBLevelsFlash', Format => 'int16s[4]' }, + 0x36 => 'ColorTempFlash', + 0x37 => { Name => 'WB_RGGBLevelsUnknown2', Format => 'int16s[4]', Unknown => 1 }, + 0x3b => { Name => 'ColorTempUnknown2', Unknown => 1 }, + 0x3c => { Name => 'WB_RGGBLevelsUnknown3', Format => 'int16s[4]', Unknown => 1 }, + 0x40 => { Name => 'ColorTempUnknown3', Unknown => 1 }, + 0x41 => { Name => 'WB_RGGBLevelsUnknown4', Format => 'int16s[4]', Unknown => 1 }, + 0x45 => { Name => 'ColorTempUnknown4', Unknown => 1 }, + 0x46 => { Name => 'WB_RGGBLevelsUnknown5', Format => 'int16s[4]', Unknown => 1 }, + 0x4a => { Name => 'ColorTempUnknown5', Unknown => 1 }, + 0x4b => { Name => 'WB_RGGBLevelsUnknown6', Format => 'int16s[4]', Unknown => 1 }, + 0x4f => { Name => 'ColorTempUnknown6', Unknown => 1 }, + 0x50 => { Name => 'WB_RGGBLevelsUnknown7', Format => 'int16s[4]', Unknown => 1 }, + 0x54 => { Name => 'ColorTempUnknown7', Unknown => 1 }, + 0x55 => { Name => 'WB_RGGBLevelsUnknown8', Format => 'int16s[4]', Unknown => 1 }, + 0x59 => { Name => 'ColorTempUnknown8', Unknown => 1 }, + 0x5a => { Name => 'WB_RGGBLevelsUnknown9', Format => 'int16s[4]', Unknown => 1 }, + 0x5e => { Name => 'ColorTempUnknown9', Unknown => 1 }, + 0x5f => { Name => 'WB_RGGBLevelsUnknown10', Format => 'int16s[4]', Unknown => 1 }, + 0x63 => { Name => 'ColorTempUnknown10', Unknown => 1 }, + 0x64 => { Name => 'WB_RGGBLevelsUnknown11', Format => 'int16s[4]', Unknown => 1 }, + 0x68 => { Name => 'ColorTempUnknown11', Unknown => 1 }, + 0x69 => { Name => 'WB_RGGBLevelsUnknown12', Format => 'int16s[4]', Unknown => 1 }, + 0x6d => { Name => 'ColorTempUnknown12', Unknown => 1 }, + 0x6e => { Name => 'WB_RGGBLevelsUnknown13', Format => 'int16s[4]', Unknown => 1 }, + 0x72 => { Name => 'ColorTempUnknown13', Unknown => 1 }, +); + +# color coefficients (ref PH/IB) +%Image::ExifTool::Canon::ColorCoefs2 = ( + %binaryDataAttrs, + FORMAT => 'int16s', + FIRST_ENTRY => 0, + GROUPS => { 0 => 'MakerNotes', 2 => 'Camera' }, + 0x00 => { Name => 'WB_RGGBLevelsAsShot', Format => 'int16s[4]' }, + 0x07 => 'ColorTempAsShot', + 0x08 => { Name => 'WB_RGGBLevelsAuto', Format => 'int16s[4]' }, + 0x0f => 'ColorTempAuto', + 0x10 => { Name => 'WB_RGGBLevelsMeasured', Format => 'int16s[4]' }, + 0x17 => 'ColorTempMeasured', + 0x18 => { Name => 'WB_RGGBLevelsUnknown', Format => 'int16s[4]', Unknown => 1 }, + 0x1f => { Name => 'ColorTempUnknown', Unknown => 1 }, + 0x20 => { Name => 'WB_RGGBLevelsDaylight', Format => 'int16s[4]' }, + 0x27 => 'ColorTempDaylight', + 0x28 => { Name => 'WB_RGGBLevelsShade', Format => 'int16s[4]' }, + 0x2f => 'ColorTempShade', + 0x30 => { Name => 'WB_RGGBLevelsCloudy', Format => 'int16s[4]' }, + 0x37 => 'ColorTempCloudy', + 0x38 => { Name => 'WB_RGGBLevelsTungsten', Format => 'int16s[4]' }, + 0x3f => 'ColorTempTungsten', + 0x40 => { Name => 'WB_RGGBLevelsFluorescent',Format => 'int16s[4]' }, + 0x47 => 'ColorTempFluorescent', + 0x48 => { Name => 'WB_RGGBLevelsKelvin', Format => 'int16s[4]' }, + 0x4f => 'ColorTempKelvin', + 0x50 => { Name => 'WB_RGGBLevelsFlash', Format => 'int16s[4]' }, + 0x57 => 'ColorTempFlash', + 0x58 => { Name => 'WB_RGGBLevelsUnknown2', Format => 'int16s[4]', Unknown => 1 }, + 0x5f => { Name => 'ColorTempUnknown2', Unknown => 1 }, + 0x60 => { Name => 'WB_RGGBLevelsUnknown3', Format => 'int16s[4]', Unknown => 1 }, + 0x67 => { Name => 'ColorTempUnknown3', Unknown => 1 }, + 0x68 => { Name => 'WB_RGGBLevelsUnknown4', Format => 'int16s[4]', Unknown => 1 }, + 0x6f => { Name => 'ColorTempUnknown4', Unknown => 1 }, + 0x70 => { Name => 'WB_RGGBLevelsUnknown5', Format => 'int16s[4]', Unknown => 1 }, + 0x77 => { Name => 'ColorTempUnknown5', Unknown => 1 }, + 0x78 => { Name => 'WB_RGGBLevelsUnknown6', Format => 'int16s[4]', Unknown => 1 }, + 0x7f => { Name => 'ColorTempUnknown6', Unknown => 1 }, + 0x80 => { Name => 'WB_RGGBLevelsUnknown7', Format => 'int16s[4]', Unknown => 1 }, + 0x87 => { Name => 'ColorTempUnknown7', Unknown => 1 }, + 0x88 => { Name => 'WB_RGGBLevelsUnknown8', Format => 'int16s[4]', Unknown => 1 }, + 0x8f => { Name => 'ColorTempUnknown8', Unknown => 1 }, + 0x90 => { Name => 'WB_RGGBLevelsUnknown9', Format => 'int16s[4]', Unknown => 1 }, + 0x97 => { Name => 'ColorTempUnknown9', Unknown => 1 }, + 0x98 => { Name => 'WB_RGGBLevelsUnknown10', Format => 'int16s[4]', Unknown => 1 }, + 0x9f => { Name => 'ColorTempUnknown10', Unknown => 1 }, + 0xa0 => { Name => 'WB_RGGBLevelsUnknown11', Format => 'int16s[4]', Unknown => 1 }, + 0xa7 => { Name => 'ColorTempUnknown11', Unknown => 1 }, + 0xa8 => { Name => 'WB_RGGBLevelsUnknown12', Format => 'int16s[4]', Unknown => 1 }, + 0xaf => { Name => 'ColorTempUnknown12', Unknown => 1 }, + 0xb0 => { Name => 'WB_RGGBLevelsUnknown13', Format => 'int16s[4]', Unknown => 1 }, + 0xb7 => { Name => 'ColorTempUnknown13', Unknown => 1 }, +); + +# color calibration (ref 37) +%Image::ExifTool::Canon::ColorCalib = ( + %binaryDataAttrs, + FORMAT => 'int16s', + FIRST_ENTRY => 0, + GROUPS => { 0 => 'MakerNotes', 2 => 'Camera' }, + # these coefficients are in a different order compared to older + # models (A,B,C in ColorData1/2 vs. C,A,B in ColorData3/4) - PH + # Coefficient A most closely matches the blue curvature, and + # coefficient B most closely matches the red curvature, but the match + # is not perfect, and I don't know what coefficient C is for (certainly + # not a green coefficient) - PH + NOTES => q{ + Camera color calibration data. For the 20D, 350D, 1DmkII and 1DSmkII the + order of the coefficients is A, B, C, Temperature, but for newer models it + is B, C, A, Temperature. These tags are extracted only when the Unknown + option is used. + }, + 0x00 => { Name => 'CameraColorCalibration01', %cameraColorCalibration }, + 0x04 => { Name => 'CameraColorCalibration02', %cameraColorCalibration }, + 0x08 => { Name => 'CameraColorCalibration03', %cameraColorCalibration }, + 0x0c => { Name => 'CameraColorCalibration04', %cameraColorCalibration }, + 0x10 => { Name => 'CameraColorCalibration05', %cameraColorCalibration }, + 0x14 => { Name => 'CameraColorCalibration06', %cameraColorCalibration }, + 0x18 => { Name => 'CameraColorCalibration07', %cameraColorCalibration }, + 0x1c => { Name => 'CameraColorCalibration08', %cameraColorCalibration }, + 0x20 => { Name => 'CameraColorCalibration09', %cameraColorCalibration }, + 0x24 => { Name => 'CameraColorCalibration10', %cameraColorCalibration }, + 0x28 => { Name => 'CameraColorCalibration11', %cameraColorCalibration }, + 0x2c => { Name => 'CameraColorCalibration12', %cameraColorCalibration }, + 0x30 => { Name => 'CameraColorCalibration13', %cameraColorCalibration }, + 0x34 => { Name => 'CameraColorCalibration14', %cameraColorCalibration }, + 0x38 => { Name => 'CameraColorCalibration15', %cameraColorCalibration }, +); + +# color calibration2 +%Image::ExifTool::Canon::ColorCalib2 = ( + %binaryDataAttrs, + FORMAT => 'int16s', + FIRST_ENTRY => 0, + GROUPS => { 0 => 'MakerNotes', 2 => 'Camera' }, + NOTES => 'B, C, A, D, Temperature.', + 0x00 => { Name => 'CameraColorCalibration01', %cameraColorCalibration2 }, + 0x05 => { Name => 'CameraColorCalibration02', %cameraColorCalibration2 }, + 0x0a => { Name => 'CameraColorCalibration03', %cameraColorCalibration2 }, + 0x0f => { Name => 'CameraColorCalibration04', %cameraColorCalibration2 }, + 0x14 => { Name => 'CameraColorCalibration05', %cameraColorCalibration2 }, + 0x19 => { Name => 'CameraColorCalibration06', %cameraColorCalibration2 }, + 0x1e => { Name => 'CameraColorCalibration07', %cameraColorCalibration2 }, + 0x23 => { Name => 'CameraColorCalibration08', %cameraColorCalibration2 }, + 0x28 => { Name => 'CameraColorCalibration09', %cameraColorCalibration2 }, + 0x2d => { Name => 'CameraColorCalibration10', %cameraColorCalibration2 }, + 0x32 => { Name => 'CameraColorCalibration11', %cameraColorCalibration2 }, + 0x37 => { Name => 'CameraColorCalibration12', %cameraColorCalibration2 }, + 0x3c => { Name => 'CameraColorCalibration13', %cameraColorCalibration2 }, + 0x41 => { Name => 'CameraColorCalibration14', %cameraColorCalibration2 }, + 0x46 => { Name => 'CameraColorCalibration15', %cameraColorCalibration2 }, +); + +# Color data (MakerNotes tag 0x4001, count=5120) (ref PH) +%Image::ExifTool::Canon::ColorData5 = ( + %binaryDataAttrs, + NOTES => 'These tags are used by many EOS M and PowerShot models.', + FORMAT => 'int16s', + FIRST_ENTRY => 0, + GROUPS => { 0 => 'MakerNotes', 2 => 'Camera' }, + DATAMEMBER => [ 0x00 ], + IS_SUBDIR => [ 0x47, 0xba, 0xff ], + 0x00 => { + Name => 'ColorDataVersion', + DataMember => 'ColorDataVersion', + RawConv => '$$self{ColorDataVersion} = $val', + PrintConv => { + -3 => '-3 (M10/M3)', # (and PowerShot G1X/G1XmkII/G10/G11/G12/G15/G16/G3X/G5X/G7X/G9X/S100/S110/S120/S90/S95/SX1IS/SX50HS/SX60HS) + -4 => '-4 (M100/M5/M6)', # (and PowerShot G1XmkIII/G7XmkII/G9XmkII) + }, + }, + 0x47 => [{ + Name => 'ColorCoefs', + Condition => '$$self{ColorDataVersion} == -3', + Format => 'undef[230]', # ColorTempUnknown13 is last entry + SubDirectory => { TagTable => 'Image::ExifTool::Canon::ColorCoefs' } + },{ + Name => 'ColorCoefs2', + Condition => '$$self{ColorDataVersion} == -4', + Format => 'undef[368]', + SubDirectory => { TagTable => 'Image::ExifTool::Canon::ColorCoefs2' } + }], + 0xba => { + Name => 'ColorCalib2', + Condition => '$$self{ColorDataVersion} == -3', + Format => 'undef[150]', + Unknown => 1, + SubDirectory => { TagTable => 'Image::ExifTool::Canon::ColorCalib2' } + }, + 0xff => { + Name => 'ColorCalib2', + Condition => '$$self{ColorDataVersion} == -4', + Format => 'undef[150]', + Unknown => 1, + SubDirectory => { TagTable => 'Image::ExifTool::Canon::ColorCalib2' } + }, + 0x108=> { #IB + Name => 'PerChannelBlackLevel', + Condition => '$$self{ColorDataVersion} == -3', + Format => 'int16s[4]', + }, + 0x14d=> { #IB + Name => 'PerChannelBlackLevel', + Condition => '$$self{ColorDataVersion} == -4', + Format => 'int16s[4]', + }, +); + +# Color data (MakerNotes tag 0x4001, count=1273|1275) (ref PH) +%Image::ExifTool::Canon::ColorData6 = ( + %binaryDataAttrs, + NOTES => 'These tags are used by the EOS 600D and 1200D.', + FORMAT => 'int16s', + FIRST_ENTRY => 0, + GROUPS => { 0 => 'MakerNotes', 2 => 'Camera' }, + IS_SUBDIR => [ 0xbc ], + 0x00 => { + Name => 'ColorDataVersion', + PrintConv => { + 10 => '10 (600D/1200D)', + }, + }, + 0x3f => { Name => 'WB_RGGBLevelsAsShot', Format => 'int16s[4]' }, + 0x43 => 'ColorTempAsShot', + 0x44 => { Name => 'WB_RGGBLevelsAuto', Format => 'int16s[4]' }, + 0x48 => 'ColorTempAuto', + 0x49 => { Name => 'WB_RGGBLevelsMeasured', Format => 'int16s[4]' }, + 0x4d => 'ColorTempMeasured', + 0x4e => { Name => 'WB_RGGBLevelsUnknown', Format => 'int16s[4]', Unknown => 1 }, + 0x52 => { Name => 'ColorTempUnknown', Unknown => 1 }, + 0x53 => { Name => 'WB_RGGBLevelsUnknown2', Format => 'int16s[4]', Unknown => 1 }, + 0x57 => { Name => 'ColorTempUnknown2', Unknown => 1 }, + 0x58 => { Name => 'WB_RGGBLevelsUnknown3', Format => 'int16s[4]', Unknown => 1 }, + 0x5c => { Name => 'ColorTempUnknown3', Unknown => 1 }, + 0x5d => { Name => 'WB_RGGBLevelsUnknown4', Format => 'int16s[4]', Unknown => 1 }, + 0x61 => { Name => 'ColorTempUnknown4', Unknown => 1 }, + 0x62 => { Name => 'WB_RGGBLevelsUnknown5', Format => 'int16s[4]', Unknown => 1 }, + 0x66 => { Name => 'ColorTempUnknown5', Unknown => 1 }, + 0x67 => { Name => 'WB_RGGBLevelsDaylight', Format => 'int16s[4]' }, + 0x6b => 'ColorTempDaylight', + 0x6c => { Name => 'WB_RGGBLevelsShade', Format => 'int16s[4]' }, + 0x70 => 'ColorTempShade', + 0x71 => { Name => 'WB_RGGBLevelsCloudy', Format => 'int16s[4]' }, + 0x75 => 'ColorTempCloudy', + 0x76 => { Name => 'WB_RGGBLevelsTungsten', Format => 'int16s[4]' }, + 0x7a => 'ColorTempTungsten', + 0x7b => { Name => 'WB_RGGBLevelsFluorescent',Format => 'int16s[4]' }, + 0x7f => 'ColorTempFluorescent', + 0x80 => { Name => 'WB_RGGBLevelsKelvin', Format => 'int16s[4]' }, + 0x84 => 'ColorTempKelvin', + 0x85 => { Name => 'WB_RGGBLevelsFlash', Format => 'int16s[4]' }, + 0x89 => 'ColorTempFlash', + 0x8a => { Name => 'WB_RGGBLevelsUnknown6', Format => 'int16s[4]', Unknown => 1 }, + 0x8e => { Name => 'ColorTempUnknown6', Unknown => 1 }, + 0x8f => { Name => 'WB_RGGBLevelsUnknown7', Format => 'int16s[4]', Unknown => 1 }, + 0x93 => { Name => 'ColorTempUnknown7', Unknown => 1 }, + 0x94 => { Name => 'WB_RGGBLevelsUnknown8', Format => 'int16s[4]', Unknown => 1 }, + 0x98 => { Name => 'ColorTempUnknown8', Unknown => 1 }, + 0x99 => { Name => 'WB_RGGBLevelsUnknown9', Format => 'int16s[4]', Unknown => 1 }, + 0x9d => { Name => 'ColorTempUnknown9', Unknown => 1 }, + 0x9e => { Name => 'WB_RGGBLevelsUnknown10', Format => 'int16s[4]', Unknown => 1 }, + 0xa2 => { Name => 'ColorTempUnknown10', Unknown => 1 }, + 0xa3 => { Name => 'WB_RGGBLevelsUnknown11', Format => 'int16s[4]', Unknown => 1 }, + 0xa7 => { Name => 'ColorTempUnknown11', Unknown => 1 }, + 0xa8 => { Name => 'WB_RGGBLevelsUnknown12', Format => 'int16s[4]', Unknown => 1 }, + 0xac => { Name => 'ColorTempUnknown12', Unknown => 1 }, + 0xad => { Name => 'WB_RGGBLevelsUnknown13', Format => 'int16s[4]', Unknown => 1 }, + 0xb1 => { Name => 'ColorTempUnknown13', Unknown => 1 }, + 0xb2 => { Name => 'WB_RGGBLevelsUnknown14', Format => 'int16s[4]', Unknown => 1 }, + 0xb6 => { Name => 'ColorTempUnknown14', Unknown => 1 }, + 0xb7 => { Name => 'WB_RGGBLevelsUnknown15', Format => 'int16s[4]', Unknown => 1 }, + 0xbb => { Name => 'ColorTempUnknown15', Unknown => 1 }, + 0xbc => { + Name => 'ColorCalib', + Format => 'undef[120]', + Unknown => 1, + Notes => 'B, C, A, Temperature', + SubDirectory => { TagTable => 'Image::ExifTool::Canon::ColorCalib' } + }, + 0x0fb => { Name => 'AverageBlackLevel', Format => 'int16u[4]' }, #IB + 0x194 => { #PH + Name => 'RawMeasuredRGGB', + Format => 'int32u[4]', + Notes => 'raw MeasuredRGGB values, before normalization', + # swap words because the word ordering is big-endian, opposite to the byte ordering + ValueConv => \&SwapWords, + ValueConvInv => \&SwapWords, + }, + 0x1df => { Name => 'PerChannelBlackLevel', Format => 'int16u[4]' }, #IB + 0x1e3 => { Name => 'NormalWhiteLevel', Format => 'int16u', RawConv => '$val || undef' }, #IB + 0x1e4 => { Name => 'SpecularWhiteLevel', Format => 'int16u' }, #IB + 0x1e5 => { Name => 'LinearityUpperMargin', Format => 'int16u' }, #IB +); + +# Color data (MakerNotes tag 0x4001, count=1312,1313,1316) (ref PH) +%Image::ExifTool::Canon::ColorData7 = ( + %binaryDataAttrs, + NOTES => 'These tags are used by the EOS 1DX, 5DmkIII, 6D, 100D, 650D, 700D, M and 7DmkII.', + FORMAT => 'int16s', + FIRST_ENTRY => 0, + GROUPS => { 0 => 'MakerNotes', 2 => 'Camera' }, + DATAMEMBER => [ 0x00 ], + IS_SUBDIR => [ 0xd5 ], + 0x00 => { + Name => 'ColorDataVersion', + DataMember => 'ColorDataVersion', + RawConv => '$$self{ColorDataVersion} = $val', + PrintConv => { + 10 => '10 (1DX/5DmkIII/6D/70D/100D/650D/700D/M)', + 11 => '11 (7DmkII/750D/760D)', + }, + }, + # not really sure about the AsShot, Auto and Measured values any more - PH + 0x3f => { Name => 'WB_RGGBLevelsAsShot', Format => 'int16s[4]' }, + 0x43 => 'ColorTempAsShot', + 0x44 => { Name => 'WB_RGGBLevelsAuto', Format => 'int16s[4]' }, + 0x48 => 'ColorTempAuto', + 0x49 => { Name => 'WB_RGGBLevelsMeasured', Format => 'int16s[4]' }, + 0x4d => 'ColorTempMeasured', + 0x4e => { Name => 'WB_RGGBLevelsUnknown', Format => 'int16s[4]', Unknown => 1 }, + 0x52 => { Name => 'ColorTempUnknown', Unknown => 1 }, + 0x53 => { Name => 'WB_RGGBLevelsUnknown2', Format => 'int16s[4]', Unknown => 1 }, + 0x57 => { Name => 'ColorTempUnknown2', Unknown => 1 }, + 0x58 => { Name => 'WB_RGGBLevelsUnknown3', Format => 'int16s[4]', Unknown => 1 }, + 0x5c => { Name => 'ColorTempUnknown3', Unknown => 1 }, + 0x5d => { Name => 'WB_RGGBLevelsUnknown4', Format => 'int16s[4]', Unknown => 1 }, + 0x61 => { Name => 'ColorTempUnknown4', Unknown => 1 }, + 0x62 => { Name => 'WB_RGGBLevelsUnknown5', Format => 'int16s[4]', Unknown => 1 }, + 0x66 => { Name => 'ColorTempUnknown5', Unknown => 1 }, + 0x67 => { Name => 'WB_RGGBLevelsUnknown6', Format => 'int16s[4]', Unknown => 1 }, + 0x6b => { Name => 'ColorTempUnknown6', Unknown => 1 }, + 0x6c => { Name => 'WB_RGGBLevelsUnknown7', Format => 'int16s[4]', Unknown => 1 }, + 0x70 => { Name => 'ColorTempUnknown7', Unknown => 1 }, + 0x71 => { Name => 'WB_RGGBLevelsUnknown8', Format => 'int16s[4]', Unknown => 1 }, + 0x75 => { Name => 'ColorTempUnknown8', Unknown => 1 }, + 0x76 => { Name => 'WB_RGGBLevelsUnknown9', Format => 'int16s[4]', Unknown => 1 }, + 0x7a => { Name => 'ColorTempUnknown9', Unknown => 1 }, + 0x7b => { Name => 'WB_RGGBLevelsUnknown10', Format => 'int16s[4]', Unknown => 1 }, + 0x7f => { Name => 'ColorTempUnknown10', Unknown => 1 }, + 0x80 => { Name => 'WB_RGGBLevelsDaylight', Format => 'int16s[4]' }, + 0x84 => 'ColorTempDaylight', + 0x85 => { Name => 'WB_RGGBLevelsShade', Format => 'int16s[4]' }, + 0x89 => 'ColorTempShade', + 0x8a => { Name => 'WB_RGGBLevelsCloudy', Format => 'int16s[4]' }, + 0x8e => 'ColorTempCloudy', + 0x8f => { Name => 'WB_RGGBLevelsTungsten', Format => 'int16s[4]' }, + 0x93 => 'ColorTempTungsten', + 0x94 => { Name => 'WB_RGGBLevelsFluorescent',Format => 'int16s[4]' }, + 0x98 => 'ColorTempFluorescent', + 0x99 => { Name => 'WB_RGGBLevelsKelvin', Format => 'int16s[4]' }, + 0x9d => 'ColorTempKelvin', + 0x9e => { Name => 'WB_RGGBLevelsFlash', Format => 'int16s[4]' }, + 0xa2 => 'ColorTempFlash', + 0xa3 => { Name => 'WB_RGGBLevelsUnknown11', Format => 'int16s[4]', Unknown => 1 }, + 0xa7 => { Name => 'ColorTempUnknown11', Unknown => 1 }, + 0xa8 => { Name => 'WB_RGGBLevelsUnknown12', Format => 'int16s[4]', Unknown => 1 }, + 0xac => { Name => 'ColorTempUnknown12', Unknown => 1 }, + 0xad => { Name => 'WB_RGGBLevelsUnknown13', Format => 'int16s[4]', Unknown => 1 }, + 0xb1 => { Name => 'ColorTempUnknown13', Unknown => 1 }, + 0xb2 => { Name => 'WB_RGGBLevelsUnknown14', Format => 'int16s[4]', Unknown => 1 }, + 0xb6 => { Name => 'ColorTempUnknown14', Unknown => 1 }, + 0xb7 => { Name => 'WB_RGGBLevelsUnknown15', Format => 'int16s[4]', Unknown => 1 }, + 0xbb => { Name => 'ColorTempUnknown15', Unknown => 1 }, + 0xbc => { Name => 'WB_RGGBLevelsUnknown16', Format => 'int16s[4]', Unknown => 1 }, + 0xc0 => { Name => 'ColorTempUnknown16', Unknown => 1 }, + 0xc1 => { Name => 'WB_RGGBLevelsUnknown17', Format => 'int16s[4]', Unknown => 1 }, + 0xc5 => { Name => 'ColorTempUnknown17', Unknown => 1 }, + 0xc6 => { Name => 'WB_RGGBLevelsUnknown18', Format => 'int16s[4]', Unknown => 1 }, + 0xca => { Name => 'ColorTempUnknown18', Unknown => 1 }, + 0xcb => { Name => 'WB_RGGBLevelsUnknown19', Format => 'int16s[4]', Unknown => 1 }, + 0xcf => { Name => 'ColorTempUnknown19', Unknown => 1 }, + 0xd0 => { Name => 'WB_RGGBLevelsUnknown20', Format => 'int16s[4]', Unknown => 1 }, + 0xd4 => { Name => 'ColorTempUnknown20', Unknown => 1 }, + 0xd5 => { + Name => 'ColorCalib', + Format => 'undef[120]', + Unknown => 1, + Notes => 'B, C, A, Temperature', + SubDirectory => { TagTable => 'Image::ExifTool::Canon::ColorCalib' } + }, + 0x114 => { Name => 'AverageBlackLevel', Format => 'int16u[4]' }, #IB + 0x1ad => { + Name => 'RawMeasuredRGGB', + Condition => '$$self{ColorDataVersion} == 10', + Format => 'int32u[4]', + Notes => 'raw MeasuredRGGB values, before normalization', + # swap words because the word ordering is big-endian, opposite to the byte ordering + ValueConv => \&SwapWords, + ValueConvInv => \&SwapWords, + }, + 0x1f8 => { #IB + Name => 'PerChannelBlackLevel', + Condition => '$$self{ColorDataVersion} == 10', + Format => 'int16u[4]', + }, + 0x1fc => { #IB + Name => 'NormalWhiteLevel', + Condition => '$$self{ColorDataVersion} == 10', + Format => 'int16u', + RawConv => '$val || undef', + }, + 0x1fd => { #IB + Name => 'SpecularWhiteLevel', + Condition => '$$self{ColorDataVersion} == 10', + Format => 'int16u', + }, + 0x1fe => { #IB + Name => 'LinearityUpperMargin', + Condition => '$$self{ColorDataVersion} == 10', + Format => 'int16u', + }, + 0x26b => { + Name => 'RawMeasuredRGGB', + Condition => '$$self{ColorDataVersion} == 11', + Format => 'int32u[4]', + ValueConv => \&SwapWords, + ValueConvInv => \&SwapWords, + }, + 0x2d8 => { + Name => 'PerChannelBlackLevel', + Condition => '$$self{ColorDataVersion} == 11', + Format => 'int16u[4]', + }, + 0x2dc => { + Name => 'NormalWhiteLevel', + Condition => '$$self{ColorDataVersion} == 11', + Format => 'int16u', + RawConv => '$val || undef', + }, + 0x2dd => { + Name => 'SpecularWhiteLevel', + Condition => '$$self{ColorDataVersion} == 11', + Format => 'int16u', + }, + 0x2de => { + Name => 'LinearityUpperMargin', + Condition => '$$self{ColorDataVersion} == 11', + Format => 'int16u', + }, +); + +# Color data (MakerNotes tag 0x4001, count=1560,etc) (ref IB) +%Image::ExifTool::Canon::ColorData8 = ( + %binaryDataAttrs, + FORMAT => 'int16s', + FIRST_ENTRY => 0, + GROUPS => { 0 => 'MakerNotes', 2 => 'Camera' }, + DATAMEMBER => [ 0 ], + IS_SUBDIR => [ 0x107 ], + 0x00 => { + Name => 'ColorDataVersion', + DataMember => 'ColorDataVersion', + RawConv => '$$self{ColorDataVersion} = $val', + PrintConv => { + 12 => '12 (5DS/5DSR)', + 13 => '13 (80D)', #PH + 14 => '14 (1300D/2000D/4000D)', #IB + 15 => '15 (6DmkII/77D/200D/800D)', #IB + }, + }, + 0x3f => { Name => 'WB_RGGBLevelsAsShot', Format => 'int16s[4]' }, + 0x43 => 'ColorTempAsShot', + 0x44 => { Name => 'WB_RGGBLevelsAuto', Format => 'int16s[4]' }, + 0x48 => 'ColorTempAuto', + 0x49 => { Name => 'WB_RGGBLevelsMeasured', Format => 'int16s[4]' }, + 0x4d => 'ColorTempMeasured', + 0x4e => { Name => 'WB_RGGBLevelsUnknown', Format => 'int16s[4]', Unknown => 1 }, + 0x52 => { Name => 'ColorTempUnknown', Unknown => 1 }, + 0x53 => { Name => 'WB_RGGBLevelsUnknown2', Format => 'int16s[4]', Unknown => 1 }, + 0x57 => { Name => 'ColorTempUnknown2', Unknown => 1 }, + 0x58 => { Name => 'WB_RGGBLevelsUnknown3', Format => 'int16s[4]', Unknown => 1 }, + 0x5c => { Name => 'ColorTempUnknown3', Unknown => 1 }, + 0x5d => { Name => 'WB_RGGBLevelsUnknown4', Format => 'int16s[4]', Unknown => 1 }, + 0x61 => { Name => 'ColorTempUnknown4', Unknown => 1 }, + 0x62 => { Name => 'WB_RGGBLevelsUnknown5', Format => 'int16s[4]', Unknown => 1 }, + 0x66 => { Name => 'ColorTempUnknown5', Unknown => 1 }, + 0x67 => { Name => 'WB_RGGBLevelsUnknown6', Format => 'int16s[4]', Unknown => 1 }, + 0x6b => { Name => 'ColorTempUnknown6', Unknown => 1 }, + 0x6c => { Name => 'WB_RGGBLevelsUnknown7', Format => 'int16s[4]', Unknown => 1 }, + 0x70 => { Name => 'ColorTempUnknown7', Unknown => 1 }, + 0x71 => { Name => 'WB_RGGBLevelsUnknown8', Format => 'int16s[4]', Unknown => 1 }, + 0x75 => { Name => 'ColorTempUnknown8', Unknown => 1 }, + 0x76 => { Name => 'WB_RGGBLevelsUnknown9', Format => 'int16s[4]', Unknown => 1 }, + 0x7a => { Name => 'ColorTempUnknown9', Unknown => 1 }, + 0x7b => { Name => 'WB_RGGBLevelsUnknown10', Format => 'int16s[4]', Unknown => 1 }, + 0x7f => { Name => 'ColorTempUnknown10', Unknown => 1 }, + 0x80 => { Name => 'WB_RGGBLevelsUnknown11', Format => 'int16s[4]', Unknown => 1 }, + 0x84 => { Name => 'ColorTempUnknown11', Unknown => 1 }, + 0x85 => { Name => 'WB_RGGBLevelsDaylight', Format => 'int16s[4]' }, + 0x89 => 'ColorTempDaylight', + 0x8a => { Name => 'WB_RGGBLevelsShade', Format => 'int16s[4]' }, + 0x8e => 'ColorTempShade', + 0x8f => { Name => 'WB_RGGBLevelsCloudy', Format => 'int16s[4]' }, + 0x93 => 'ColorTempCloudy', + 0x94 => { Name => 'WB_RGGBLevelsTungsten', Format => 'int16s[4]' }, + 0x98 => 'ColorTempTungsten', + 0x99 => { Name => 'WB_RGGBLevelsFluorescent',Format => 'int16s[4]' }, + 0x9d => 'ColorTempFluorescent', + 0x9e => { Name => 'WB_RGGBLevelsKelvin', Format => 'int16s[4]' }, + 0xa2 => 'ColorTempKelvin', + 0xa3 => { Name => 'WB_RGGBLevelsFlash', Format => 'int16s[4]' }, + 0xa7 => 'ColorTempFlash', + 0xa8 => { Name => 'WB_RGGBLevelsUnknown12', Format => 'int16s[4]', Unknown => 1 }, + 0xac => { Name => 'ColorTempUnknown12', Unknown => 1 }, + 0xad => { Name => 'WB_RGGBLevelsUnknown13', Format => 'int16s[4]', Unknown => 1 }, + 0xb1 => { Name => 'ColorTempUnknown13', Unknown => 1 }, + 0xb2 => { Name => 'WB_RGGBLevelsUnknown14', Format => 'int16s[4]', Unknown => 1 }, + 0xb6 => { Name => 'ColorTempUnknown14', Unknown => 1 }, + 0xb7 => { Name => 'WB_RGGBLevelsUnknown15', Format => 'int16s[4]', Unknown => 1 }, + 0xbb => { Name => 'ColorTempUnknown15', Unknown => 1 }, + 0xbc => { Name => 'WB_RGGBLevelsUnknown16', Format => 'int16s[4]', Unknown => 1 }, + 0xc0 => { Name => 'ColorTempUnknown16', Unknown => 1 }, + 0xc1 => { Name => 'WB_RGGBLevelsUnknown17', Format => 'int16s[4]', Unknown => 1 }, + 0xc5 => { Name => 'ColorTempUnknown17', Unknown => 1 }, + 0xc6 => { Name => 'WB_RGGBLevelsUnknown18', Format => 'int16s[4]', Unknown => 1 }, + 0xca => { Name => 'ColorTempUnknown18', Unknown => 1 }, + 0xcb => { Name => 'WB_RGGBLevelsUnknown19', Format => 'int16s[4]', Unknown => 1 }, + 0xcf => { Name => 'ColorTempUnknown19', Unknown => 1 }, + 0xd0 => { Name => 'WB_RGGBLevelsUnknown20', Format => 'int16s[4]', Unknown => 1 }, + 0xd4 => { Name => 'ColorTempUnknown20', Unknown => 1 }, + 0xd5 => { Name => 'WB_RGGBLevelsUnknown21', Format => 'int16s[4]', Unknown => 1 }, + 0xd9 => { Name => 'ColorTempUnknown21', Unknown => 1 }, + 0xda => { Name => 'WB_RGGBLevelsUnknown22', Format => 'int16s[4]', Unknown => 1 }, + 0xde => { Name => 'ColorTempUnknown22', Unknown => 1 }, + 0xdf => { Name => 'WB_RGGBLevelsUnknown23', Format => 'int16s[4]', Unknown => 1 }, + 0xe3 => { Name => 'ColorTempUnknown23', Unknown => 1 }, + 0xe4 => { Name => 'WB_RGGBLevelsUnknown24', Format => 'int16s[4]', Unknown => 1 }, + 0xe8 => { Name => 'ColorTempUnknown24', Unknown => 1 }, + 0xe9 => { Name => 'WB_RGGBLevelsUnknown25', Format => 'int16s[4]', Unknown => 1 }, + 0xed => { Name => 'ColorTempUnknown25', Unknown => 1 }, + 0xee => { Name => 'WB_RGGBLevelsUnknown26', Format => 'int16s[4]', Unknown => 1 }, + 0xf2 => { Name => 'ColorTempUnknown26', Unknown => 1 }, + 0xf3 => { Name => 'WB_RGGBLevelsUnknown27', Format => 'int16s[4]', Unknown => 1 }, + 0xf7 => { Name => 'ColorTempUnknown27', Unknown => 1 }, + 0xf8 => { Name => 'WB_RGGBLevelsUnknown28', Format => 'int16s[4]', Unknown => 1 }, + 0xfc => { Name => 'ColorTempUnknown28', Unknown => 1 }, + 0xfd => { Name => 'WB_RGGBLevelsUnknown29', Format => 'int16s[4]', Unknown => 1 }, + 0x101 => { Name => 'ColorTempUnknown29', Unknown => 1 }, + 0x102 => { Name => 'WB_RGGBLevelsUnknown30', Format => 'int16s[4]', Unknown => 1 }, + 0x106 => { Name => 'ColorTempUnknown30', Unknown => 1 }, + + 0x107 => { + Name => 'ColorCalib', + Format => 'undef[120]', + Unknown => 1, + Notes => 'B, C, A, Temperature', + SubDirectory => { TagTable => 'Image::ExifTool::Canon::ColorCalib' } + }, + 0x146 => { Name => 'AverageBlackLevel', Format => 'int16u[4]' }, + 0x22c => { + Name => 'PerChannelBlackLevel', + Condition => '$$self{ColorDataVersion} == 14', + Format => 'int16u[4]', + Notes => '1300D', + }, + 0x230 => { + Name => 'NormalWhiteLevel', + Condition => '$$self{ColorDataVersion} == 14', + Format => 'int16u', + Notes => '1300D', + RawConv => '$val || undef', + }, + 0x231 => { + Name => 'SpecularWhiteLevel', + Condition => '$$self{ColorDataVersion} == 14', + Format => 'int16u', + Notes => '1300D', + }, + 0x232 => { + Name => 'LinearityUpperMargin', + Condition => '$$self{ColorDataVersion} == 14', + Format => 'int16u', + Notes => '1300D', + }, + 0x30a => { + Name => 'PerChannelBlackLevel', + Condition => '$$self{ColorDataVersion} < 14 or $$self{ColorDataVersion} == 15', + Format => 'int16u[4]', + Notes => '5DS, 5DS R, 77D, 80D and 800D', + }, + 0x30e => { + Name => 'NormalWhiteLevel', + Condition => '$$self{ColorDataVersion} < 14 or $$self{ColorDataVersion} == 15', + Format => 'int16u', + Notes => '5DS, 5DS R, 77D, 80D and 800D', + RawConv => '$val || undef', + }, + 0x30f => { + Name => 'SpecularWhiteLevel', + Condition => '$$self{ColorDataVersion} < 14 or $$self{ColorDataVersion} == 15', + Format => 'int16u', + Notes => '5DS, 5DS R, 77D, 80D and 800D', + }, + 0x310 => { + Name => 'LinearityUpperMargin', + Condition => '$$self{ColorDataVersion} < 14 or $$self{ColorDataVersion} == 15', + Format => 'int16u', + Notes => '5DS, 5DS R, 77D, 80D and 800D', + }, +); + +# Color data (MakerNotes tag 0x4001, count=1820,etc) (ref PH) +%Image::ExifTool::Canon::ColorData9 = ( + %binaryDataAttrs, + FORMAT => 'int16s', + FIRST_ENTRY => 0, + GROUPS => { 0 => 'MakerNotes', 2 => 'Camera' }, + DATAMEMBER => [ 0 ], + IS_SUBDIR => [ 0x10a ], + 0x00 => { + Name => 'ColorDataVersion', + DataMember => 'ColorDataVersion', + RawConv => '$$self{ColorDataVersion} = $val', + PrintConv => { + 16 => '16 (M50)', + 17 => '17 (EOS R)', # (and PowerShot SX740HS) + 18 => '18 (EOS RP)', # (and PowerShot SX70HS) + }, + }, + 0x47 => { Name => 'WB_RGGBLevelsAsShot', Format => 'int16s[4]' }, + 0x4b => 'ColorTempAsShot', + 0x4c => { Name => 'WB_RGGBLevelsAuto', Format => 'int16s[4]' }, + 0x50 => 'ColorTempAuto', + 0x51 => { Name => 'WB_RGGBLevelsMeasured', Format => 'int16s[4]' }, + 0x55 => 'ColorTempMeasured', + 0x56 => { Name => 'WB_RGGBLevelsUnknown', Format => 'int16s[4]', Unknown => 1 }, + 0x5a => { Name => 'ColorTempUnknown', Unknown => 1 }, + 0x5b => { Name => 'WB_RGGBLevelsUnknown2', Format => 'int16s[4]', Unknown => 1 }, + 0x5f => { Name => 'ColorTempUnknown2', Unknown => 1 }, + 0x60 => { Name => 'WB_RGGBLevelsUnknown3', Format => 'int16s[4]', Unknown => 1 }, + 0x64 => { Name => 'ColorTempUnknown3', Unknown => 1 }, + 0x65 => { Name => 'WB_RGGBLevelsUnknown4', Format => 'int16s[4]', Unknown => 1 }, + 0x69 => { Name => 'ColorTempUnknown4', Unknown => 1 }, + 0x6a => { Name => 'WB_RGGBLevelsUnknown5', Format => 'int16s[4]', Unknown => 1 }, + 0x6e => { Name => 'ColorTempUnknown5', Unknown => 1 }, + 0x6f => { Name => 'WB_RGGBLevelsUnknown6', Format => 'int16s[4]', Unknown => 1 }, + 0x73 => { Name => 'ColorTempUnknown6', Unknown => 1 }, + 0x74 => { Name => 'WB_RGGBLevelsUnknown7', Format => 'int16s[4]', Unknown => 1 }, + 0x78 => { Name => 'ColorTempUnknown7', Unknown => 1 }, + 0x79 => { Name => 'WB_RGGBLevelsUnknown8', Format => 'int16s[4]', Unknown => 1 }, + 0x7d => { Name => 'ColorTempUnknown8', Unknown => 1 }, + 0x7e => { Name => 'WB_RGGBLevelsUnknown9', Format => 'int16s[4]', Unknown => 1 }, + 0x82 => { Name => 'ColorTempUnknown9', Unknown => 1 }, + 0x83 => { Name => 'WB_RGGBLevelsUnknown10', Format => 'int16s[4]', Unknown => 1 }, + 0x87 => { Name => 'ColorTempUnknown10', Unknown => 1 }, + 0x88 => { Name => 'WB_RGGBLevelsDaylight', Format => 'int16s[4]' }, + 0x8c => 'ColorTempDaylight', + 0x8d => { Name => 'WB_RGGBLevelsShade', Format => 'int16s[4]' }, + 0x91 => 'ColorTempShade', + 0x92 => { Name => 'WB_RGGBLevelsCloudy', Format => 'int16s[4]' }, + 0x96 => 'ColorTempCloudy', + 0x97 => { Name => 'WB_RGGBLevelsTungsten', Format => 'int16s[4]' }, + 0x9b => 'ColorTempTungsten', + 0x9c => { Name => 'WB_RGGBLevelsFluorescent',Format => 'int16s[4]' }, + 0xa0 => 'ColorTempFluorescent', + 0xa1 => { Name => 'WB_RGGBLevelsKelvin', Format => 'int16s[4]' }, + 0xa5 => 'ColorTempKelvin', + 0xa6 => { Name => 'WB_RGGBLevelsFlash', Format => 'int16s[4]' }, + 0xaa => 'ColorTempFlash', + 0xab => { Name => 'WB_RGGBLevelsUnknown11', Format => 'int16s[4]', Unknown => 1 }, + 0xaf => { Name => 'ColorTempUnknown11', Unknown => 1 }, + 0xb0 => { Name => 'WB_RGGBLevelsUnknown12', Format => 'int16s[4]', Unknown => 1 }, + 0xb4 => { Name => 'ColorTempUnknown12', Unknown => 1 }, + 0xb5 => { Name => 'WB_RGGBLevelsUnknown13', Format => 'int16s[4]', Unknown => 1 }, + 0xb9 => { Name => 'ColorTempUnknown13', Unknown => 1 }, + 0xba => { Name => 'WB_RGGBLevelsUnknown14', Format => 'int16s[4]', Unknown => 1 }, + 0xbe => { Name => 'ColorTempUnknown14', Unknown => 1 }, + 0xbf => { Name => 'WB_RGGBLevelsUnknown15', Format => 'int16s[4]', Unknown => 1 }, + 0xc3 => { Name => 'ColorTempUnknown15', Unknown => 1 }, + 0xc4 => { Name => 'WB_RGGBLevelsUnknown16', Format => 'int16s[4]', Unknown => 1 }, + 0xc8 => { Name => 'ColorTempUnknown16', Unknown => 1 }, + 0xc9 => { Name => 'WB_RGGBLevelsUnknown17', Format => 'int16s[4]', Unknown => 1 }, + 0xcd => { Name => 'ColorTempUnknown17', Unknown => 1 }, + 0xce => { Name => 'WB_RGGBLevelsUnknown18', Format => 'int16s[4]', Unknown => 1 }, + 0xd2 => { Name => 'ColorTempUnknown18', Unknown => 1 }, + 0xd3 => { Name => 'WB_RGGBLevelsUnknown19', Format => 'int16s[4]', Unknown => 1 }, + 0xd7 => { Name => 'ColorTempUnknown19', Unknown => 1 }, + 0xd8 => { Name => 'WB_RGGBLevelsUnknown20', Format => 'int16s[4]', Unknown => 1 }, + 0xdc => { Name => 'ColorTempUnknown20', Unknown => 1 }, + 0xdd => { Name => 'WB_RGGBLevelsUnknown21', Format => 'int16s[4]', Unknown => 1 }, + 0xe1 => { Name => 'ColorTempUnknown21', Unknown => 1 }, + 0xe2 => { Name => 'WB_RGGBLevelsUnknown22', Format => 'int16s[4]', Unknown => 1 }, + 0xe6 => { Name => 'ColorTempUnknown22', Unknown => 1 }, + 0xe7 => { Name => 'WB_RGGBLevelsUnknown23', Format => 'int16s[4]', Unknown => 1 }, + 0xeb => { Name => 'ColorTempUnknown23', Unknown => 1 }, + 0xec => { Name => 'WB_RGGBLevelsUnknown24', Format => 'int16s[4]', Unknown => 1 }, + 0xf0 => { Name => 'ColorTempUnknown24', Unknown => 1 }, + 0xf1 => { Name => 'WB_RGGBLevelsUnknown25', Format => 'int16s[4]', Unknown => 1 }, + 0xf5 => { Name => 'ColorTempUnknown25', Unknown => 1 }, + 0xf6 => { Name => 'WB_RGGBLevelsUnknown26', Format => 'int16s[4]', Unknown => 1 }, + 0xfa => { Name => 'ColorTempUnknown26', Unknown => 1 }, + 0xfb => { Name => 'WB_RGGBLevelsUnknown27', Format => 'int16s[4]', Unknown => 1 }, + 0xff => { Name => 'ColorTempUnknown27', Unknown => 1 }, + 0x100=> { Name => 'WB_RGGBLevelsUnknown28', Format => 'int16s[4]', Unknown => 1 }, + 0x104=> { Name => 'ColorTempUnknown28', Unknown => 1 }, + 0x105=> { Name => 'WB_RGGBLevelsUnknown29', Format => 'int16s[4]', Unknown => 1 }, + 0x109=> { Name => 'ColorTempUnknown29', Unknown => 1 }, + 0x10a => { #IB + Name => 'ColorCalib', + Format => 'undef[120]', + Unknown => 1, + SubDirectory => { TagTable => 'Image::ExifTool::Canon::ColorCalib' } + }, + 0x149 => { #IB + Name => 'PerChannelBlackLevel', + Format => 'int16u[4]', + Notes => '1300D', + }, + # 0x318 - PerChannelBlackLevel again (ref IB) + 0x31c => { #IB + Name => 'NormalWhiteLevel', + Format => 'int16u', + RawConv => '$val || undef', + }, + 0x31d => { #IB + Name => 'SpecularWhiteLevel', + Format => 'int16u', + }, + 0x31e => { #IB + Name => 'LinearityUpperMargin', + Format => 'int16u', + }, +); + +# Unknown color data (MakerNotes tag 0x4001) +%Image::ExifTool::Canon::ColorDataUnknown = ( + PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData, + FORMAT => 'int16s', + FIRST_ENTRY => 0, + GROUPS => { 0 => 'MakerNotes', 2 => 'Camera' }, + 0x00 => 'ColorDataVersion', +); + +# Color information (MakerNotes tag 0x4003) (ref PH) +%Image::ExifTool::Canon::ColorInfo = ( + %binaryDataAttrs, + FORMAT => 'int16s', + FIRST_ENTRY => 1, + GROUPS => { 0 => 'MakerNotes', 2 => 'Camera' }, + 1 => { + Condition => '$$self{Model} =~ /EOS-1D/', + Name => 'Saturation', + %Image::ExifTool::Exif::printParameter, + }, + 2 => { + Name => 'ColorTone', + %Image::ExifTool::Exif::printParameter, + }, + 3 => { + Name => 'ColorSpace', + RawConv => '$val ? $val : undef', # ignore tag if zero + PrintConv => { + 1 => 'sRGB', + 2 => 'Adobe RGB', + }, + }, +); + +# AF micro-adjustment information (MakerNotes tag 0x4013) (ref PH) +%Image::ExifTool::Canon::AFMicroAdj = ( + %binaryDataAttrs, + FORMAT => 'int32s', + FIRST_ENTRY => 1, + GROUPS => { 0 => 'MakerNotes', 2 => 'Camera' }, + 1 => { + Name => 'AFMicroAdjMode', + PrintConv => { + 0 => 'Disable', + 1 => 'Adjust all by the same amount', + 2 => 'Adjust by lens', + # 3 - seen this for EOS 77D, which doesn't have an AF Micro Adjust feature - PH + }, + }, + 2 => { + Name => 'AFMicroAdjValue', + Format => 'rational64s', + }, +); + +# Vignetting correction information (MakerNotes tag 0x4015) +%Image::ExifTool::Canon::VignettingCorr = ( + %binaryDataAttrs, + FORMAT => 'int16s', + FIRST_ENTRY => 1, + GROUPS => { 0 => 'MakerNotes', 2 => 'Camera' }, + NOTES => 'This information is found in images from newer EOS models.', + 0 => { + Name => 'VignettingCorrVersion', + Format => 'int8u', + Writable => 0, + }, + 2 => { + Name => 'PeripheralLighting', + PrintConv => \%offOn, + }, + 4 => { + Name => 'ChromaticAberrationCorr', + PrintConv => \%offOn, + }, + 5 => { + Name => 'ChromaticAberrationCorr', + PrintConv => \%offOn, + }, + 6 => 'PeripheralLightingValue', + # 10 - flags? + 11 => { + Name => 'OriginalImageWidth', + Notes => 'full size of original image before being rotated or scaled in camera', + }, + 12 => 'OriginalImageHeight', +); + +%Image::ExifTool::Canon::VignettingCorrUnknown = ( + %binaryDataAttrs, + FORMAT => 'int16s', + FIRST_ENTRY => 1, + GROUPS => { 0 => 'MakerNotes', 2 => 'Camera' }, + NOTES => 'Vignetting correction from PowerShot models.', + 0 => { + Name => 'VignettingCorrVersion', + Format => 'int8u', + Writable => 0, + }, +); + +# More Vignetting correction information (MakerNotes tag 0x4016) +%Image::ExifTool::Canon::VignettingCorr2 = ( + %binaryDataAttrs, + FORMAT => 'int32s', + FIRST_ENTRY => 1, + GROUPS => { 0 => 'MakerNotes', 2 => 'Camera' }, + 5 => { + Name => 'PeripheralLightingSetting', + PrintConv => \%offOn, + }, + 6 => { + Name => 'ChromaticAberrationSetting', + PrintConv => \%offOn, + }, +); + +# Auto Lighting Optimizater information (MakerNotes tag 0x4018) (ref PH) +%Image::ExifTool::Canon::LightingOpt = ( + %binaryDataAttrs, + FORMAT => 'int32s', + FIRST_ENTRY => 1, + GROUPS => { 0 => 'MakerNotes', 2 => 'Camera' }, + NOTES => 'This information is new in images from the EOS 7D.', + 1 => { + Name => 'PeripheralIlluminationCorr', + PrintConv => \%offOn, + }, + 2 => { + Name => 'AutoLightingOptimizer', + PrintConv => { + 0 => 'Standard', + 1 => 'Low', + 2 => 'Strong', + 3 => 'Off', + }, + }, + 3 => { + Name => 'HighlightTonePriority', + PrintConv => \%offOn, + }, + 4 => { + Name => 'LongExposureNoiseReduction', + PrintConv => { + 0 => 'Off', + 1 => 'Auto', + 2 => 'On', + }, + }, + 5 => { + Name => 'HighISONoiseReduction', + PrintConv => { + 0 => 'Standard', + 1 => 'Low', + 2 => 'Strong', + 3 => 'Off', + }, + }, + # 6 - related to ChromaticAberrationCorr + # 7 - related to DistortionCorrection + # 8 - related to PeripheralIlluminationCorr and ChromaticAberrationCorr +); + +# Lens information (MakerNotes tag 0x4019) (ref 20) +%Image::ExifTool::Canon::LensInfo = ( + %binaryDataAttrs, + FIRST_ENTRY => 0, + GROUPS => { 0 => 'MakerNotes', 2 => 'Camera' }, + 0 => { # this doesn't seem to be valid for some models (eg. 550D, 7D?, 1DmkIV?) + Name => 'LensSerialNumber', + Notes => q{ + apparently this is an internal serial number because it doesn't correspond + to the one printed on the lens + }, + Format => 'undef[5]', + Priority => 0, + RawConv => '$val=~/^\0\0\0\0/ ? undef : $val', # (rules out 550D and older lenses) + ValueConv => 'unpack("H*", $val)', + ValueConvInv => 'length($val) < 10 and $val = 0 x (10-length($val)) . $val; pack("H*",$val)', + }, +); + +# Subject mode ambience information (MakerNotes tag 0x4020) (ref PH) +%Image::ExifTool::Canon::Ambience = ( + %binaryDataAttrs, + FORMAT => 'int32s', + FIRST_ENTRY => 1, + GROUPS => { 0 => 'MakerNotes', 2 => 'Camera' }, + 1 => { + Name => 'AmbienceSelection', + PrintConv => { + 0 => 'Standard', + 1 => 'Vivid', + 2 => 'Warm', + 3 => 'Soft', + 4 => 'Cool', + 5 => 'Intense', + 6 => 'Brighter', + 7 => 'Darker', + 8 => 'Monochrome', + }, + }, +); + +# Multi-exposure information (MakerNotes tag 0x4021) (ref PH) +%Image::ExifTool::Canon::MultiExp = ( + %binaryDataAttrs, + FORMAT => 'int32s', + FIRST_ENTRY => 1, + GROUPS => { 0 => 'MakerNotes', 2 => 'Image' }, + 1 => { + Name => 'MultiExposure', + PrintConv => { + 0 => 'Off', + 1 => 'On', + 2 => 'On (RAW)', #IB + }, + }, + 2 => { + Name => 'MultiExposureControl', + PrintConv => { + 0 => 'Additive', + 1 => 'Average', + 2 => 'Bright (comparative)', + 3 => 'Dark (comparative)', + }, + }, + 3 => 'MultiExposureShots', +); + +my %filterConv = ( + PrintConv => { + -1 => 'Off', + OTHER => sub { my $val=shift; return "On ($val)" }, + }, +); +# Creative filter information (MakerNotes tag 0x4024) (ref PH) +%Image::ExifTool::Canon::FilterInfo = ( + PROCESS_PROC => \&ProcessFilters, + GROUPS => { 0 => 'MakerNotes', 2 => 'Camera' }, + NOTES => 'Information about creative filter settings.', + 0x101 => { + Name => 'GrainyBWFilter', + Description => 'Grainy B/W Filter', + %filterConv, + }, + 0x201 => { Name => 'SoftFocusFilter', %filterConv }, + 0x301 => { Name => 'ToyCameraFilter', %filterConv }, + 0x401 => { Name => 'MiniatureFilter', %filterConv }, + 0x402 => { + Name => 'MiniatureFilterOrientation', + PrintConv => { + 0 => 'Horizontal', + 1 => 'Vertical', + }, + }, + 0x403 => 'MiniatureFilterPosition', + 0x404 => 'MiniatureFilterParameter', # but what is the meaning? + 0x501 => { Name => 'FisheyeFilter', %filterConv }, # (M2) + 0x601 => { Name => 'PaintingFilter', %filterConv }, # (M2) + 0x701 => { Name => 'WatercolorFilter', %filterConv }, # (M2) +); + +# HDR information (MakerNotes tag 0x4025) (ref PH) +%Image::ExifTool::Canon::HDRInfo = ( + %binaryDataAttrs, + FORMAT => 'int32s', + FIRST_ENTRY => 1, + GROUPS => { 0 => 'MakerNotes', 2 => 'Image' }, + 1 => { + Name => 'HDR', + PrintConv => { + 0 => 'Off', + 1 => 'Auto', + 2 => 'On', + }, + }, + 2 => { + Name => 'HDREffect', + PrintConv => { + 0 => 'Natural', + 1 => 'Art (standard)', + 2 => 'Art (vivid)', + 3 => 'Art (bold)', + 4 => 'Art (embossed)', + }, + }, + # 3 - maybe related to AutoImageAlign? +); + +# AF configuration info (MakerNotes tag 0x4028) (ref PH) +%Image::ExifTool::Canon::AFConfig = ( + %binaryDataAttrs, + GROUPS => { 0 => 'MakerNotes', 2 => 'Camera' }, + FORMAT => 'int32s', + FIRST_ENTRY => 1, + 1 => { + Name => 'AFConfigTool', + ValueConv => '$val + 1', + ValueConvInv => '$val - 1', + PrintConv => '"Case $val"', + PrintConvInv => '$val=~/(\d+)/ ? $1 : undef', + }, + 2 => 'AFTrackingSensitivity', + 3 => { + Name => 'AFAccelDecelTracking', + Description => 'AF Accel/Decel Tracking', + }, + 4 => 'AFPointSwitching', + 5 => { #52 + Name => 'AIServoFirstImage', + PrintConv => { + 0 => 'Equal Priority', + 1 => 'Release Priority', + 2 => 'Focus Priority', + }, + }, + 6 => { #52 + Name => 'AIServoSecondImage', + PrintConv => { + 0 => 'Equal Priority', + 1 => 'Release Priority', + 2 => 'Focus Priority', + 3 => 'Release High Priority', + 4 => 'Focus High Priority', + }, + }, + 7 => { #52 + Name => 'USMLensElectronicMF', + PrintConv => { + 0 => 'Enable After AF', + 1 => 'Disable After AF', + 2 => 'Disable in AF Mode', + }, + }, + 8 => { #52 + Name => 'AFAssistBeam', + PrintConv => { + 0 => 'Enable', + 1 => 'Disable', + 2 => 'IR AF Assist Beam Only', + }, + }, + 9 => { #52 + Name => 'OneShotAFRelease', + PrintConv => { + 0 => 'Focus Priority', + 1 => 'Release Priority', + }, + }, + 10 => { #52 + Name => 'AutoAFPointSelEOSiTRAF', + Description => 'Auto AF Point Sel EOS iTR AF', + # valid for: 1DX, 1DXmkII, 7DmkII, 5DS, 5DSR + # not valid for: 5DmkIII + Notes => 'only valid for some models', + Condition => '$$self{Model} !~ /5D /', + PrintConv => { + 0 => 'Enable', + 1 => 'Disable', + }, + }, + 11 => { #52 + Name => 'LensDriveWhenAFImpossible', + PrintConv => { + 0 => 'Continue Focus Search', + 1 => 'Stop Focus Search', + }, + }, + 12 => { #52 + Name => 'SelectAFAreaSelectionMode', + PrintConv => { BITMASK => { + 0 => 'Single-point AF', + 1 => 'Auto', # (61 point) + 2 => 'Zone AF', + 3 => 'AF Point Expansion (4 point)', + 4 => 'Spot AF', + 5 => 'AF Point Expansion (8 point)', + }}, + }, + 13 => { #52 + Name => 'AFAreaSelectionMethod', + PrintConv => { + 0 => 'M-Fn Button', + 1 => 'Main Dial', + }, + }, + 14 => { #52 + Name => 'OrientationLinkedAF', + PrintConv => { # Covers both 1Dx (0-2) and 5D3 (0-1) + 0 => 'Same for Vert/Horiz Points', + 1 => 'Separate Vert/Horiz Points', + 2 => 'Separate Area+Points', + }, + }, + 15 => { #52 + Name => 'ManualAFPointSelPattern', + PrintConv => { + 0 => 'Stops at AF Area Edges', + 1 => 'Continuous', + }, + }, + 16 => { #52 + Name => 'AFPointDisplayDuringFocus', + PrintConv => { + 0 => 'Selected (constant)', + 1 => 'All (constant)', + 2 => 'Selected (pre-AF, focused)', + 3 => 'Selected (focused)', + 4 => 'Disabled', + }, + }, + 17 => { #52 + Name => 'VFDisplayIllumination', + PrintConv => { + 0 => 'Auto', + 1 => 'Enable', + 2 => 'Disable', + }, + }, + 18 => { #52 + Name => 'AFStatusViewfinder', + Condition => '$$self{Model} =~ /1D X/', + Notes => '1D X only', + PrintConv => { + 0 => 'Show in Field of View', + 1 => 'Show Outside View', + }, + }, + 19 => { #52 + Name => 'InitialAFPointInServo', + Condition => '$$self{Model} =~ /1D X/', + Notes => '1D X only', + PrintConv => { + 0 => 'Initial AF Point Selected', + 1 => 'Manual AF Point', + 2 => 'Auto', #PH (1DXmkII) + }, + }, +); + +# Canon UUID atoms (ref PH, SX280) +%Image::ExifTool::Canon::uuid = ( + GROUPS => { 0 => 'MakerNotes', 1 => 'Canon', 2 => 'Video' }, + NOTES => q{ + Tags extracted from the uuid atom of MP4 videos from cameras such as the + SX280, and CR3 images from cameras such as the EOS M50. + }, + CNCV => { + Name => 'CompressorVersion', + # use this to recognize the specific type of Canon RAW (CR3 or CRM) + RawConv => '$self->OverrideFileType($1) if $val =~ /^Canon(\w{3})/i; $val', + }, + # CNDM - 4 bytes - 0xff,0xd8,0xff,0xd9 + CNTH => { + Name => 'CanonCNTH', + SubDirectory => { TagTable => 'Image::ExifTool::Canon::CNTH' }, + }, + CCTP => { # (CR3 files) + Name => 'CanonCCTP', + SubDirectory => { + TagTable => 'Image::ExifTool::Canon::CCTP', + Start => '12', + }, + }, + # CTBO - (CR3 files) int32u entry count N, N x (int32u index, int64u offset, int64u size) + # index 1=XMP, 2=PRVW, 3=mdat + CMT1 => { # (CR3 files) + Name => 'IFD0', + SubDirectory => { + TagTable => 'Image::ExifTool::Exif::Main', + ProcessProc => \&Image::ExifTool::ProcessTIFF, + }, + }, + CMT2 => { # (CR3 files) + Name => 'ExifIFD', + SubDirectory => { + TagTable => 'Image::ExifTool::Exif::Main', + ProcessProc => \&Image::ExifTool::ProcessTIFF, + }, + }, + CMT3 => { # (CR3 files) + Name => 'MakerNoteCanon', + SubDirectory => { + TagTable => 'Image::ExifTool::Canon::Main', + ProcessProc => \&Image::ExifTool::ProcessTIFF, + }, + }, + CMT4 => { # (CR3 files) + Name => 'GPSInfo', + SubDirectory => { + TagTable => 'Image::ExifTool::GPS::Main', + ProcessProc => \&Image::ExifTool::ProcessTIFF, + DirName => 'GPS', + }, + }, + THMB => { + Name => 'ThumbnailImage', + Groups => { 2 => 'Preview' }, + RawConv => 'substr($val, 16)', + Binary => 1, + }, + CNOP => { #PH (M50) + Name => 'CanonCNOP', + SubDirectory => { TagTable => 'Image::ExifTool::Canon::CNOP' }, + }, +); + +%Image::ExifTool::Canon::UnknownIFD = ( + GROUPS => { 0 => 'MakerNotes', 2 => 'Camera' }, +); + +# Canon CCTP atoms (ref PH, CR3 files) +%Image::ExifTool::Canon::CCTP = ( + GROUPS => { 0 => 'MakerNotes', 1 => 'Canon', 2 => 'Video' }, + # CCDT - int32u[3]: 0. 0, 1. decoder type?, 2. 0, 3. index +); + +# 'CDI1' atom information (ref PH, CR3 files) +%Image::ExifTool::Canon::CDI1 = ( + GROUPS => { 0 => 'QuickTime', 1 => 'Canon', 2 => 'Image' }, + # IAD1 - 32/48 bytes +); + +# Canon Timed MetaData (ref PH, CR3 files) +%Image::ExifTool::Canon::CTMD = ( + GROUPS => { 0 => 'MakerNotes', 1 => 'Canon', 2 => 'Image' }, + PROCESS_PROC => \&ProcessCTMD, + NOTES => q{ + Canon Timed MetaData tags found in CR3 images. The ExtractEmbedded option + is automatically applied when reading CR3 files to be able to extract this + information. + }, + 1 => { + Name => 'TimeStamp', + Groups => { 2 => 'Time' }, + RawConv => q{ + my $fmt = GetByteOrder() eq 'MM' ? 'x2nCCCCCC' : 'x2vCCCCCC'; + sprintf('%.4d:%.2d:%.2d %.2d:%.2d:%.2d.%.2d', unpack($fmt, $val)); + }, + PrintConv => '$self->ConvertDateTime($val)', + }, + # 3 - 4 bytes, seen: ff ff ff ff + 4 => { + Name => 'FocalInfo', + SubDirectory => { TagTable => 'Image::ExifTool::Canon::FocalInfo' }, + }, + 5 => { + Name => 'ExposureInfo', + SubDirectory => { TagTable => 'Image::ExifTool::Canon::ExposureInfo' }, + }, + 7 => { + Name => 'ExifInfo7', + SubDirectory => { TagTable => 'Image::ExifTool::Canon::ExifInfo' }, + }, + 8 => { + Name => 'ExifInfo8', + SubDirectory => { TagTable => 'Image::ExifTool::Canon::ExifInfo' }, + }, + 9 => { + Name => 'ExifInfo9', + SubDirectory => { TagTable => 'Image::ExifTool::Canon::ExifInfo' }, + }, + # 10 - 60 bytes: all zeros with a pair of 0xff's at offset 0x02 (C200 CRM) + # 11 - 612 bytes: all zero with pairs of 0xff's at offset 0x6e and 0x116 (C200 CRM) +); + +# Canon Timed MetaData (ref PH, CR3 files) +%Image::ExifTool::Canon::ExifInfo = ( + GROUPS => { 0 => 'MakerNotes', 1 => 'Canon', 2 => 'Image' }, + PROCESS_PROC => \&ProcessExifInfo, + 0x8769 => { + Name => 'ExifIFD', + SubDirectory => { + TagTable => 'Image::ExifTool::Exif::Main', + ProcessProc => \&Image::ExifTool::ProcessTIFF, + }, + }, + 0x927c => { + Name => 'MakerNoteCanon', + SubDirectory => { + TagTable => 'Image::ExifTool::Canon::Main', + ProcessProc => \&Image::ExifTool::ProcessTIFF, + }, + }, +); + +# timed focal length information (ref PH, CR3 files) +%Image::ExifTool::Canon::FocalInfo = ( + PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData, + GROUPS => { 0 => 'MakerNotes', 1 => 'Canon', 2 => 'Image' }, + FORMAT => 'int32u', + FIRST_ENTRY => 0, + 0 => { + Name => 'FocalLength', + Format => 'rational32u', + PrintConv => 'sprintf("%.1f mm",$val)', + }, +); + +# timed exposure information (ref PH, CR3 files) +%Image::ExifTool::Canon::ExposureInfo = ( + PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData, + GROUPS => { 0 => 'MakerNotes', 1 => 'Canon', 2 => 'Image' }, + FORMAT => 'int32u', + FIRST_ENTRY => 0, + 0 => { + Name => 'FNumber', + Format => 'rational32u', + PrintConv => 'Image::ExifTool::Exif::PrintFNumber($val)', + }, + 1 => { + Name => 'ExposureTime', + Format => 'rational32u', + PrintConv => 'Image::ExifTool::Exif::PrintExposureTime($val)', + }, + 2 => { + Name => 'ISO', + Format => 'int32u', + ValueConv => '$val & 0x7fffffff', # (not sure what high bit indicates) + }, +); + +%Image::ExifTool::Canon::CNTH = ( + GROUPS => { 0 => 'MakerNotes', 1 => 'Canon', 2 => 'Video' }, + NOTES => q{ + Canon-specific QuickTime tags found in the CNTH atom of MOV videos from some + cameras such as the PowerShot S95. + }, + CNDA => { + Name => 'ThumbnailImage', + Groups => { 2 => 'Preview' }, + Format => 'undef', + Notes => 'the full THM image, embedded metadata is extracted as the first sub-document', + SetBase => 1, + RawConv => q{ + $$self{DOC_NUM} = ++$$self{DOC_COUNT}; + $self->ExtractInfo(\$val, { ReEntry => 1 }); + $$self{DOC_NUM} = 0; + return \$val; + }, + }, +); + +# Canon CNOP atoms (ref PH) +%Image::ExifTool::Canon::CNOP = ( + GROUPS => { 0 => 'MakerNotes', 1 => 'Canon', 2 => 'Video' }, + # CNFB - 52 bytes (7DmkII,M50,C200) + # CNMI - 4 bytes: "0x20000001" (C200) + # CNCM - 48 bytes: original file name in bytes 24-31 (C200) +); + +# 'skip' atom of Canon MOV videos (ref PH) +%Image::ExifTool::Canon::Skip = ( + GROUPS => { 0 => 'MakerNotes', 1 => 'Canon', 2 => 'Video' }, + NOTES => 'Information found in the "skip" atom of Canon MOV videos.', + CNDB => { Name => 'Unknown_CNDB', Unknown => 1, Binary => 1 }, +); + +# Canon composite tags +%Image::ExifTool::Canon::Composite = ( + GROUPS => { 2 => 'Camera' }, + DriveMode => { + Require => { + 0 => 'ContinuousDrive', + 1 => 'SelfTimer', + }, + ValueConv => '$val[0] ? 0 : ($val[1] ? 1 : 2)', + PrintConv => { + 0 => 'Continuous Shooting', + 1 => 'Self-timer Operation', + 2 => 'Single-frame Shooting', + }, + }, + Lens => { + Require => { + 0 => 'Canon:MinFocalLength', + 1 => 'Canon:MaxFocalLength', + }, + ValueConv => '$val[0]', + PrintConv => 'Image::ExifTool::Canon::PrintFocalRange(@val)', + }, + Lens35efl => { + Description => 'Lens', + Require => { + 0 => 'Canon:MinFocalLength', + 1 => 'Canon:MaxFocalLength', + 3 => 'Lens', + }, + Desire => { + 2 => 'ScaleFactor35efl', + }, + ValueConv => '$val[3] * ($val[2] ? $val[2] : 1)', + PrintConv => '$prt[3] . ($val[2] ? sprintf(" (35 mm equivalent: %s)",Image::ExifTool::Canon::PrintFocalRange(@val)) : "")', + }, + ShootingMode => { + Require => { + 0 => 'CanonExposureMode', + 1 => 'EasyMode', + }, + Desire => { + 2 => 'BulbDuration', + }, + # most Canon models set CanonExposureMode to Manual (4) for Bulb shots, + # but the 1DmkIII uses a value of 7 for Bulb, so use this for other + # models too (Note that Canon DPP reports "Manual Exposure" here) + ValueConv => '$val[0] ? (($val[0] eq "4" and $val[2]) ? 7 : $val[0]) : $val[1] + 10', + PrintConv => '$val eq "7" ? "Bulb" : ($val[0] ? $prt[0] : $prt[1])', + }, + FlashType => { + Notes => q{ + may report "Built-in Flash" for some Canon cameras with external flash in + manual mode + }, + Require => { + 0 => 'FlashBits', + }, + RawConv => '$val[0] ? $val : undef', + ValueConv => '$val[0]&(1<<14)? 1 : 0', + PrintConv => { + 0 => 'Built-In Flash', + 1 => 'External', + }, + }, + RedEyeReduction => { + Require => { + 0 => 'CanonFlashMode', + 1 => 'FlashBits', + }, + RawConv => '$val[1] ? $val : undef', + ValueConv => '($val[0]==3 or $val[0]==4 or $val[0]==6) ? 1 : 0', + PrintConv => { + 0 => 'Off', + 1 => 'On', + }, + }, + # same as FlashExposureComp, but undefined if no flash + ConditionalFEC => { + Description => 'Flash Exposure Compensation', + Require => { + 0 => 'FlashExposureComp', + 1 => 'FlashBits', + }, + RawConv => '$val[1] ? $val : undef', + ValueConv => '$val[0]', + PrintConv => '$prt[0]', + }, + # hack to assume 1st curtain unless we see otherwise + ShutterCurtainHack => { + Description => 'Shutter Curtain Sync', + Desire => { + 0 => 'ShutterCurtainSync', + }, + Require => { + 1 => 'FlashBits', + }, + RawConv => '$val[1] ? $val : undef', + ValueConv => 'defined($val[0]) ? $val[0] : 0', + PrintConv => { + 0 => '1st-curtain sync', + 1 => '2nd-curtain sync', + }, + }, + WB_RGGBLevels => { + Require => { + 0 => 'Canon:WhiteBalance', + }, + Desire => { + 1 => 'WB_RGGBLevelsAsShot', + # indices of the following entries correspond to Canon:WhiteBalance + 2 + 2 => 'WB_RGGBLevelsAuto', + 3 => 'WB_RGGBLevelsDaylight', + 4 => 'WB_RGGBLevelsCloudy', + 5 => 'WB_RGGBLevelsTungsten', + 6 => 'WB_RGGBLevelsFluorescent', + 7 => 'WB_RGGBLevelsFlash', + 8 => 'WB_RGGBLevelsCustom', + 10 => 'WB_RGGBLevelsShade', + 11 => 'WB_RGGBLevelsKelvin', + }, + ValueConv => '$val[1] ? $val[1] : $val[($val[0] || 0) + 2]', + }, + ISO => { + Priority => 0, # let EXIF:ISO take priority + Desire => { + 0 => 'Canon:CameraISO', + 1 => 'Canon:BaseISO', + 2 => 'Canon:AutoISO', + }, + Notes => 'use CameraISO if numerical, otherwise calculate as BaseISO * AutoISO / 100', + ValueConv => q{ + return $val[0] if $val[0] and $val[0] =~ /^\d+$/; + return undef unless $val[1] and $val[2]; + return $val[1] * $val[2] / 100; + }, + PrintConv => 'sprintf("%.0f",$val)', + }, + DigitalZoom => { + Require => { + 0 => 'Canon:ZoomSourceWidth', + 1 => 'Canon:ZoomTargetWidth', + 2 => 'Canon:DigitalZoom', + }, + RawConv => q{ + ToFloat(@val); + return undef unless $val[2] and $val[2] == 3 and $val[0] and $val[1]; + return $val[1] / $val[0]; + }, + PrintConv => 'sprintf("%.2fx",$val)', + }, + OriginalDecisionData => { + Flags => ['Writable','Protected'], + WriteGroup => 'MakerNotes', + Require => 'OriginalDecisionDataOffset', + RawConv => 'Image::ExifTool::Canon::ReadODD($self,$val[0])', + }, + FileNumber => { + Groups => { 2 => 'Image' }, + Writable => 1, + WriteCheck => '$val=~/\d+-\d+/ ? undef : "Invalid format"', + DelCheck => '"Can\'t delete"', + Require => { + 0 => 'DirectoryIndex', + 1 => 'FileIndex', + }, + WriteAlso => { + DirectoryIndex => '$val=~/(\d+)-(\d+)/; $1', + FileIndex => '$val=~/(\d+)-(\d+)/; $2', + }, + ValueConv => q{ + # fix the funny things that these numbers do when they wrap over 9999 + # (it seems that FileIndex and DirectoryIndex actually store the + # numbers from the previous image, so we need special logic + # to handle the FileIndex wrap properly) + $val[1] == 10000 and $val[1] = 1, ++$val[0]; + return sprintf("%.3d-%.4d",@val); + }, + }, +); + +# add our composite tags +Image::ExifTool::AddCompositeTags('Image::ExifTool::Canon'); + +#------------------------------------------------------------------------------ +# Return lens name with teleconverter if applicable +# Inputs: 0) lens name string, 1) short focal length +# Returns: lens string with tc if appropriate +sub LensWithTC($$) +{ + my ($lens, $shortFocal) = @_; + + # add teleconverter multiplication factor if applicable + # (and if the LensType doesn't already include one) + if (not $lens =~ /x$/ and $lens =~ /(\d+)/) { + my $sf = $1; # short focal length + my $tc; + foreach $tc (1, 1.4, 2, 2.8) { + next if abs($shortFocal - $sf * $tc) > 0.9; + $lens .= " + ${tc}x" if $tc > 1; + last; + } + } + return $lens; +} + +#------------------------------------------------------------------------------ +# Attempt to calculate sensor size for Canon cameras +# Inputs: 0/1) rational values for FocalPlaneX/YResolution +# Returns: Sensor diagonal size in mm, or undef +# Notes: This algorithm is fairly reliable, but has been found to give incorrect +# values for some firmware versions of the EOS 20D, A310, SD40 and IXUS 65 +# (ref http://wyw.dcweb.cn/download.asp?path=&file=jhead-2.96-ccdwidth_hack.zip) +sub CalcSensorDiag($$) +{ + my ($xres, $yres) = @_; + # most Canon cameras store the sensor size in the denominator + if ($xres and $yres) { + # assumptions: 1) numerators are image width/height * 1000 + # 2) denominators are sensor width/height in inches * 1000 + my @xres = split /[ \/]/, $xres; + my @yres = split /[ \/]/, $yres; + # verify assumptions as best we can: + # numerators are always divisible by 1000 + if ($xres[0] % 1000 == 0 and $yres[0] % 1000 == 0 and + # at least 640x480 pixels (DC models - PH) + $xres[0] >= 640000 and $yres[0] >= 480000 and + # ... but not too big! + $xres[0] < 10000000 and $yres[0] < 10000000 and + # minimum sensor size is 0.061 inches (DC models - PH) + $xres[1] >= 61 and $xres[1] < 1500 and + $yres[1] >= 61 and $yres[1] < 1000 and + # sensor isn't square (may happen if rationals have been reduced) + $xres[1] != $yres[1]) + { + return sqrt($xres[1]*$xres[1] + $yres[1]*$yres[1]) * 0.0254; + } + } + return undef; +} + +#------------------------------------------------------------------------------ +# Attempt to identify the specific lens if multiple lenses have the same LensType +# Inputs: 0) PrintConv hash ref, 1) LensType, 2) MinFocalLength, 3) MaxFocalLength +# 4) MaxAperture, 5) LensModel +# Notes: PrintConv, LensType, MinFocalLength and MaxFocalLength must be defined. +# Other inputs are optional. +sub PrintLensID(@) +{ + my ($printConv, $lensType, $shortFocal, $longFocal, $maxAperture, $lensModel) = @_; + my $lens; + $lens = $$printConv{$lensType} unless $lensType eq '-1' or $lensType eq '65535'; + if ($lens) { + # return this lens unless other lenses have the same LensType + return LensWithTC($lens, $shortFocal) unless $$printConv{"$lensType.1"}; + $lens =~ s/ or .*//s; # remove everything after "or" + # make list of all possible matching lenses + my @lenses = ( $lens ); + my $i; + for ($i=1; $$printConv{"$lensType.$i"}; ++$i) { + push @lenses, $$printConv{"$lensType.$i"}; + } + my ($tc, @user, @maybe, @likely, @matches); + # look for lens in user-defined lenses + foreach $lens (@lenses) { + push @user, $lens if $Image::ExifTool::userLens{$lens}; + } + # attempt to determine actual lens + foreach $tc (1, 1.4, 2, 2.8) { # loop through teleconverter scaling factors + foreach $lens (@lenses) { + next unless $lens =~ /(\d+)(?:-(\d+))?mm.*?(?:[fF]\/?)(\d+(?:\.\d+)?)(?:-(\d+(?:\.\d+)?))?/; + # ($1=short focal, $2=long focal, $3=max aperture wide, $4=max aperture tele) + my ($sf, $lf, $sa, $la) = ($1, $2, $3, $4); + # see if we can rule out this lens by focal length or aperture + $lf = $sf if $sf and not $lf; + $la = $sa if $sa and not $la; + # account for converter-specific LensType's (ie. end with " + #.#x") + if ($lens =~ / \+ (\d+(\.\d+)?)x$/) { + $sf *= $1; $lf *= $1; + $sa *= $1; $la *= $1; + } + next if abs($shortFocal - $sf * $tc) > 0.9; + my $tclens = $lens; + $tclens .= " + ${tc}x" if $tc > 1; + push @maybe, $tclens; + next if abs($longFocal - $lf * $tc) > 0.9; + push @likely, $tclens; + if ($maxAperture) { + # (not 100% sure that TC affects MaxAperture, but it should!) + next if $maxAperture < $sa * $tc - 0.15; + next if $maxAperture > $la * $tc + 0.15; + } + push @matches, $tclens; + } + last if @maybe; + } + if (@user) { + # choose the best match if we have more than one + if (@user > 1) { + my ($try, @good); + foreach $try (\@matches, \@likely, \@maybe) { + foreach (@$try) { + $Image::ExifTool::userLens{$_} and push(@good, $_), next; + # check for match with TC string removed + next unless /^(.*) \+ \d+(\.\d+)?x$/; + $Image::ExifTool::userLens{$1} and push(@good, $_); + } + return join(' or ', @good) if @good; + } + } + # default to returning the first user-defined lens + return LensWithTC($user[0], $shortFocal); + } + # differentiate Sigma Art/Contemporary/Sports models + if (@matches > 1 and $lensModel and $lensModel =~ /(\| [ACS])/) { + my $type = $1; + my @best; + foreach $lens (@matches) { + push @best, $lens if $lens =~ /\Q$type/; + } + @matches = @best if @best; + } + return join(' or ', @matches) if @matches; + return join(' or ', @likely) if @likely; + return join(' or ', @maybe) if @maybe; + } elsif ($lensModel and $lensModel =~ /\d/) { + # use lens model as written by the camera + if ($printConv eq \%canonLensTypes) { + # add "Canon" to the start since the Canon cameras only understand Canon lenses + return "Canon $lensModel"; + } else { + return $lensModel; + } + } + my $str = ''; + if ($shortFocal) { + $str .= sprintf(' %d', $shortFocal); + $str .= sprintf('-%d', $longFocal) if $longFocal and $longFocal != $shortFocal; + $str .= 'mm'; + } + # (careful because Sigma LensType's may not be integer, so use string comparison) + return "Unknown$str" if $lensType eq '-1' or $lensType eq '65535'; + return "Unknown ($lensType)$str"; +} + +#------------------------------------------------------------------------------ +# Swap 16-bit words in 32-bit integers +# Inputs: 0) string of integers +# Returns: string of word-swapped integers +sub SwapWords($) +{ + my @a = split(' ', shift); + $_ = (($_ >> 16) | ($_ << 16)) & 0xffffffff foreach @a; + return "@a"; +} + +#------------------------------------------------------------------------------ +# Validate first word of Canon binary data +# Inputs: 0) data pointer, 1) offset, 2-N) list of valid values +# Returns: true if data value is the same +sub Validate($$@) +{ + my ($dataPt, $offset, @vals) = @_; + # the first 16-bit value is the length of the data in bytes + my $dataVal = Image::ExifTool::Get16u($dataPt, $offset); + my $val; + foreach $val (@vals) { + return 1 if $val == $dataVal; + } + return undef; +} + +#------------------------------------------------------------------------------ +# Validate CanonAFInfo +# Inputs: 0) data pointer, 1) offset, 2) size +# Returns: true if data appears valid +sub ValidateAFInfo($$$) +{ + my ($dataPt, $offset, $size) = @_; + return 0 if $size < 24; # must be at least 24 bytes long (PowerShot Pro1) + my $af = Get16u($dataPt, $offset); + return 0 if $af !~ /^(1|5|7|9|15|45|53)$/; # check NumAFPoints + my $w1 = Get16u($dataPt, $offset + 4); + my $h1 = Get16u($dataPt, $offset + 6); + return 0 unless $h1 and $w1; + my $f1 = $w1 / $h1; + # check for normal aspect ratio + return 1 if abs($f1 - 1.33) < 0.01 or abs($f1 - 1.67) < 0.01; + # ZoomBrowser can modify this for rotated images (ref Joshua Bixby) + return 1 if abs($f1 - 0.75) < 0.01 or abs($f1 - 0.60) < 0.01; + my $w2 = Get16u($dataPt, $offset + 8); + my $h2 = Get16u($dataPt, $offset + 10); + return 0 unless $h2 and $w2; + # compare aspect ratio with AF image size + # (but the Powershot AFImageHeight is odd, hence the test above) + return 0 if $w1 eq $h1; + my $f2 = $w2 / $h2; + return 1 if abs(1-$f1/$f2) < 0.01; + return 1 if abs(1-$f1*$f2) < 0.01; + return 0; +} + +#------------------------------------------------------------------------------ +# Read original decision data from file (variable length) +# Inputs: 0) ExifTool object ref, 1) offset in file +# Returns: reference to original decision data (or undef if no data) +sub ReadODD($$) +{ + my ($et, $offset) = @_; + return undef unless $offset; + my ($raf, $buff, $buf2, $i, $warn); + return undef unless defined($raf = $$et{RAF}); + # the data block is a variable length and starts with 0xffffffff + # followed a 4-byte (int32u) version number + my $pos = $raf->Tell(); + if ($raf->Seek($offset, 0) and $raf->Read($buff, 8)==8 and $buff=~/^\xff{4}.\0\0/s) { + my $err = 1; + # must set byte order in case it is different than current byte order + # (we could be reading this after byte order was changed) + my $oldOrder = GetByteOrder(); + my $version = Get32u(\$buff, 4); + if ($version > 20) { + ToggleByteOrder(); + $version = unpack('N',pack('V',$version)); + } + if ($version == 1 or # 1Ds (big endian) + $version == 2) # 5D/20D (little endian) + { + # this data is structured as follows: + # 4 bytes: all 0xff + # 4 bytes: version number (=1 or 2) + # 20 bytes: sha1 + # 4 bytes: record count + # for each record: + # | 4 bytes: record number (beginning at 0) + # | 4 bytes: block offset + # | 4 bytes: block length + # | 20 bytes: block sha1 + if ($raf->Read($buf2, 24) == 24) { + $buff .= $buf2; + my $count = Get32u(\$buf2, 20); + # read all records if the count is reasonable + if ($count and $count < 20 and + $raf->Read($buf2, $count * 32) == $count * 32) + { + $buff .= $buf2; + undef $err; + } + } + } elsif ($version == 3) { # newer models (little endian) + # this data is structured as follows: + # 4 bytes: all 0xff + # 4 bytes: version number (=3) + # 24 bytes: sha1 A length (=20) + sha1 A + # 24 bytes: sha1 B length (=20) + sha1 B + # 4 bytes: length of remaining data (including this length word!) + # 8 bytes: salt length (=4) + salt ? + # 4 bytes: unknown (=3) + # 4 bytes: size of file + # 4 bytes: unknown (=1 for most models, 2 for 5DmkII) + # 4 bytes: unknown (=1) + # 4 bytes: unknown (always the same for a given firmware version) + # 4 bytes: unknown (random) + # 4 bytes: record count + # for each record: + # | 4 bytes: record number (beginning at 1) + # | 8 bytes: salt length (=4) + salt ? + # | 24 bytes: sha1 length (=20) + sha1 + # | 4 bytes: block count + # | for each block: + # | | 4 bytes: block offset + # | | 4 bytes: block length + # followed by zero padding to end of ODD data (~72 bytes) + for ($i=0; ; ++$i) { + $i == 3 and undef $err, last; # success! + $raf->Read($buf2, 4) == 4 or last; + $buff .= $buf2; + my $len = Get32u(\$buf2, 0); + # (the data length includes the length word itself - doh!) + $len -= 4 if $i == 2 and $len >= 4; + # make sure records are a reasonable size (<= 64kB) + $len <= 0x10000 and $raf->Read($buf2, $len) == $len or last; + $buff .= $buf2; + } + } else { + $warn = "Unsupported original decision data version $version"; + } + SetByteOrder($oldOrder); + unless ($err) { + if ($et->Options('HtmlDump')) { + $et->HDump($offset, length $buff, '[OriginalDecisionData]', undef); + } + $raf->Seek($pos, 0); # restore original file position + return \$buff; + } + } + $et->Warn($warn || 'Invalid original decision data'); + $raf->Seek($pos, 0); # restore original file position + return undef; +} + +#------------------------------------------------------------------------------ +# Convert the CameraISO value +# Inputs: 0) value, 1) set for inverse conversion +sub CameraISO($;$) +{ + my ($val, $inv) = @_; + my $rtnVal; + my %isoLookup = ( + 0 => 'n/a', + 14 => 'Auto High', #PH (S3IS) + 15 => 'Auto', + 16 => 50, + 17 => 100, + 18 => 200, + 19 => 400, + 20 => 800, #PH + ); + if ($inv) { + $rtnVal = Image::ExifTool::ReverseLookup($val, \%isoLookup); + if (not defined $rtnVal and Image::ExifTool::IsInt($val)) { + $rtnVal = ($val & 0x3fff) | 0x4000; + } + } elsif ($val != 0x7fff) { + if ($val & 0x4000) { + $rtnVal = $val & 0x3fff; + } else { + $rtnVal = $isoLookup{$val} || "Unknown ($val)"; + } + } + return $rtnVal; +} + +#------------------------------------------------------------------------------ +# Print range of focal lengths +# Inputs: 0) short focal, 1) long focal, 2) optional scaling factor +sub PrintFocalRange(@) +{ + my ($short, $long, $scale) = @_; + + $scale or $scale = 1; + if ($short == $long) { + return sprintf("%.1f mm", $short * $scale); + } else { + return sprintf("%.1f - %.1f mm", $short * $scale, $long * $scale); + } +} + +#------------------------------------------------------------------------------ +# Process a serial stream of binary data +# Inputs: 0) ExifTool object ref, 1) dirInfo ref, 2) tag table ref +# Returns: 1 on success +# Notes: The tagID's for serial stream tags are consecutive indices beginning +# at 0, and the corresponding values must be contiguous in memory. +# "Unknown" tags must be used to skip padding or unknown values. +# (does not yet extract Rational values) +sub ProcessSerialData($$$) +{ + my ($et, $dirInfo, $tagTablePtr) = @_; + my $dataPt = $$dirInfo{DataPt}; + my $offset = $$dirInfo{DirStart}; + my $size = $$dirInfo{DirLen}; + my $base = $$dirInfo{Base} || 0; + my $verbose = $et->Options('Verbose'); + my $dataPos = $$dirInfo{DataPos} || 0; + + # temporarily set Unknown option so GetTagInfo() will return existing unknown tags + # (require to maintain serial data synchronization) + my $unknown = $et->Options(Unknown => 1); + # but disable unknown tag generation (because processing ends when we run out of tags) + $$et{NO_UNKNOWN} = 1; + + $verbose and $et->VerboseDir('SerialData', undef, $size); + + # get default format ('int8u' unless specified) + my $defaultFormat = $$tagTablePtr{FORMAT} || 'int8u'; + + my ($index, %val); + my $pos = 0; + for ($index=0; $$tagTablePtr{$index} and $pos <= $size; ++$index) { + my $tagInfo = $et->GetTagInfo($tagTablePtr, $index) or last; + my $format = $$tagInfo{Format}; + my $count = 1; + if ($format) { + if ($format =~ /(.*)\[(.*)\]/) { + $format = $1; + $count = $2; + # evaluate count to allow count to be based on previous values + #### eval Format (%val, $size) + $count = eval $count; + $@ and warn("Format $$tagInfo{Name}: $@"), last; + } elsif ($format eq 'string') { + # allow string with no specified count to run to end of block + $count = ($size > $pos) ? $size - $pos : 0; + } + } else { + $format = $defaultFormat; + } + my $len = (Image::ExifTool::FormatSize($format) || 1) * $count; + last if $pos + $len > $size; + my $val = ReadValue($dataPt, $pos+$offset, $format, $count, $size-$pos); + last unless defined $val; + if ($verbose) { + $et->VerboseInfo($index, $tagInfo, + Index => $index, + Table => $tagTablePtr, + Value => $val, + DataPt => $dataPt, + Size => $len, + Start => $pos+$offset, + Addr => $pos+$offset+$base+$dataPos, + Format => $format, + Count => $count, + ); + } + $val{$index} = $val; + if ($$tagInfo{SubDirectory}) { + my $subTablePtr = GetTagTable($$tagInfo{SubDirectory}{TagTable}); + my %dirInfo = ( + DataPt => \$val, + DataPos => $dataPos + $pos, + DirStart => 0, + DirLen => length($val), + ); + $et->ProcessDirectory(\%dirInfo, $subTablePtr); + } elsif (not $$tagInfo{Unknown} or $unknown) { + # don't extract zero-length information + $et->FoundTag($tagInfo, $val) if $count; + } + $pos += $len; + } + $et->Options(Unknown => $unknown); # restore Unknown option + delete $$et{NO_UNKNOWN}; + return 1; +} + +#------------------------------------------------------------------------------ +# Print 1D AF points +# Inputs: 0) value to convert +# Focus point pattern: +# A1 A2 A3 A4 A5 A6 A7 +# B1 B2 B3 B4 B5 B6 B7 B8 B9 B10 +# C1 C2 C3 C4 C5 C6 C7 C9 C9 C10 C11 +# D1 D2 D3 D4 D5 D6 D7 D8 D9 D10 +# E1 E2 E3 E4 E5 E6 E7 +sub PrintAFPoints1D($) +{ + my $val = shift; + return 'Unknown' unless length $val == 8; + # list of focus point values for decoding the first byte of the 8-byte record. + # they are the x/y positions of each bit in the AF point mask + # (y is upper 3 bits / x is lower 5 bits) + my @focusPts = (0,0, + 0x04,0x06,0x08,0x0a,0x0c,0x0e,0x10, 0,0, + 0x21,0x23,0x25,0x27,0x29,0x2b,0x2d,0x2f,0x31,0x33, + 0x40,0x42,0x44,0x46,0x48,0x4a,0x4c,0x4d,0x50,0x52,0x54, + 0x61,0x63,0x65,0x67,0x69,0x6b,0x6d,0x6f,0x71,0x73, 0,0, + 0x84,0x86,0x88,0x8a,0x8c,0x8e,0x90, 0,0,0,0,0 + ); + my $focus = unpack('C',$val); + my @bits = split //, unpack('b*',substr($val,1)); + my @rows = split //, ' AAAAAAA BBBBBBBBBBCCCCCCCCCCCDDDDDDDDDD EEEEEEE '; + my ($focusing, $focusPt, @points); + my $lastRow = ''; + my $col = 0; + foreach $focusPt (@focusPts) { + my $row = shift @rows; + $col = ($row eq $lastRow) ? $col + 1 : 1; + $lastRow = $row; + $focusing = "$row$col" if $focus eq $focusPt; + push @points, "$row$col" if shift @bits; + } + $focusing or $focusing = ($focus eq 0xff) ? 'Auto' : sprintf('Unknown (0x%.2x)',$focus); + return "$focusing (" . join(',',@points) . ')'; +} + +#------------------------------------------------------------------------------ +# Convert Canon hex-based EV (modulo 0x20) to real number +# Inputs: 0) value to convert +# eg) 0x00 -> 0 +# 0x0c -> 0.33333 +# 0x10 -> 0.5 +# 0x14 -> 0.66666 +# 0x20 -> 1 ... etc +sub CanonEv($) +{ + my $val = shift; + my $sign; + # temporarily make the number positive + if ($val < 0) { + $val = -$val; + $sign = -1; + } else { + $sign = 1; + } + my $frac = $val & 0x1f; + $val -= $frac; # remove fraction + # Convert 1/3 and 2/3 codes + if ($frac == 0x0c) { + $frac = 0x20 / 3; + } elsif ($frac == 0x14) { + $frac = 0x40 / 3; + } + return $sign * ($val + $frac) / 0x20; +} + +#------------------------------------------------------------------------------ +# Convert number to Canon hex-based EV (modulo 0x20) +# Inputs: 0) number +# Returns: Canon EV code +sub CanonEvInv($) +{ + my $num = shift; + my $sign; + # temporarily make the number positive + if ($num < 0) { + $num = -$num; + $sign = -1; + } else { + $sign = 1; + } + my $val = int($num); + my $frac = $num - $val; + if (abs($frac - 0.33) < 0.05) { + $frac = 0x0c + } elsif (abs($frac - 0.67) < 0.05) { + $frac = 0x14; + } else { + $frac = int($frac * 0x20 + 0.5); + } + return $sign * ($val * 0x20 + $frac); +} + +#------------------------------------------------------------------------------ +# Process CTMD EXIF information +# Inputs: 0) ExifTool object ref, 1) dirInfo ref, 2) tag table ref +# Returns: 1 on success +sub ProcessExifInfo($$$) +{ + my ($et, $dirInfo, $tagTablePtr) = @_; + my $dataPt = $$dirInfo{DataPt}; + my $start = $$dirInfo{DirStart} || 0; + my $dirLen = $$dirInfo{DirLen} || (length($$dataPt) - $start); + my $dirEnd = $start + $dirLen; + # loop through TIFF-format EXIF/MakerNote records + my ($pos, $len, $tag); + for ($pos = $start; $pos + 8 < $dirEnd; $pos += $len) { + $len = Get32u($dataPt, $pos); + $tag = Get32u($dataPt, $pos + 4); + # test size/tag for valid ExifInfo (not EXIF in CRM files) + last if $len < 8 or $pos + $len > $dirEnd or not $$tagTablePtr{$tag}; + $et->VerboseDir('ExifInfo', undef, $dirLen) if $pos == $start; + $et->HandleTag($tagTablePtr, $tag, undef, + DataPt => $dataPt, + Base => $$dirInfo{Base} + $pos + 8, # base for TIFF pointers + DataPos => -($pos + 8), # (relative to Base) + Start => $pos + 8, + Size => $len - 8, + ); + } + return 1; +} + +#------------------------------------------------------------------------------ +# Process Canon Timed MetaData (ref PH) +# Inputs: 0) ExifTool object ref, 1) dirInfo ref, 2) tag table ref +# Returns: 1 on success +sub ProcessCTMD($$$) +{ + my ($et, $dirInfo, $tagTablePtr) = @_; + my $dataPt = $$dirInfo{DataPt}; + my $verbose = $et->Options('Verbose'); + my $dirLen = length $$dataPt; + my $pos = 0; + SetByteOrder('II'); + while ($pos + 6 < $dirLen) { + my $size = Get32u($dataPt, $pos); + my $type = Get16u($dataPt, $pos + 4); + # what is the meaning of the 6-byte header of these records?: + # type 1 - 00 00 00 01 zz zz - TimeStamp(CR3/CRM); zz=00(CR3),ff(CRM) + # type 3 - 00 00 00 01 zz zz - ? "ff ff ff ff"; zz=00(CR3),ff(CRM) + # type 4 - 00 00 00 01 ff ff - FocalInfo(CR3/CRM) + # type 5 - 00 00 00 01 ff ff - ExposureInfo(CR3/CRM) + # type 6 - 00 04 00 01 ff ff - ? "03 04 00 80 e0 15 ff ff"(CRM) [0x15e0 = ColorTemperature?] + # type 7 - xx yy 00 01 ff ff - ExifIFD + MakerNotes(CR3), ?(CRM); xxyy=0101(CR3),0004(CRM) + # type 8 - 01 yy 00 01 ff ff - MakerNotes(CR3), ?(CRM); yy=01(CR3),04(CRM) + # type 9 - 01 yy 00 01 ff ff - MakerNotes(CR3), ?(CRM); yy=01(CR3),00(CRM) + # type 10- 01 00 00 01 ff ff - ? (CRM) + # type 11- 01 00 00 01 ff ff - ? (CRM) + # --> maybe yy == 01 for ExifInfo? + $size < 12 and $et->Warn('Short CTMD record'), last; + $pos + $size > $dirLen and $et->Warn('Truncated CTMD record'), last; + $et->VerboseDir("CTMD type $type", undef, $size - 6); + HexDump($dataPt, 6, # dump 6-byte header + Start => $pos + 6, + Addr => $$dirInfo{Base} + $pos + 6, + Prefix => $$et{INDENT}, + ) if $verbose > 2; + if ($$tagTablePtr{$type}) { + $et->HandleTag($tagTablePtr, $type, undef, + DataPt => $dataPt, + Base => $$dirInfo{Base}, + Start => $pos + 12, + Size => $size - 12, + ); + } elsif ($verbose) { + $et->VerboseDump($dataPt, Len=>$size-12, Start=>$pos+12, DataPos=>$$dirInfo{Base}); + } + $pos += $size; + } + $et->Warn('Error parsing Canon CTMD data', 1) if $pos != $dirLen; + return 1; +} + +#------------------------------------------------------------------------------ +# Process a creative filter data +# Inputs: 0) ExifTool object ref, 1) dirInfo ref, 2) tag table ref +# Returns: 1 on success +sub ProcessFilters($$$) +{ + my ($et, $dirInfo, $tagTablePtr) = @_; + my $dataPt = $$dirInfo{DataPt}; + my $pos = $$dirInfo{DirStart}; + my $dirLen = $$dirInfo{DirLen}; + my $dataPos = $$dirInfo{DataPos} || 0; + my $end = $pos + $dirLen; + my $verbose = $et->Options('Verbose'); + + return 0 if $dirLen < 8; + my $numFilters = Get32u($dataPt, $pos + 4); + $verbose and $et->VerboseDir('Creative Filter', $numFilters); + $pos += 8; + my ($i, $j, $err); + for ($i=0; $i<$numFilters; ++$i) { + # read filter structure: + # 4 bytes - filter number + # 4 bytes - filter data length + # 4 bytes - number of parameters: + # | 4 bytes - parameter ID + # | 4 bytes - parameter value count + # | 4 bytes * count - parameter values (NC) + $pos + 12 > $end and $err = "Truncated data for filter $i", last; + my $fnum = Get32u($dataPt, $pos); # (is this an index or an ID?) + my $size = Get32u($dataPt, $pos + 4); + my $nparm = Get32u($dataPt, $pos + 8); + my $nxt = $pos + 4 + $size; + $nxt > $end and $err = "Invalid size ($size) for filter $i", last; + $verbose and $et->VerboseDir("Filter $fnum", $nparm, $size); + $pos += 12; + for ($j=0; $j<$nparm; ++$j) { + $pos + 12 > $end and $err = "Truncated data for filter $i param $j", last; + my $tag = Get32u($dataPt, $pos); + my $count = Get32u($dataPt, $pos + 4); + $pos += 8; + $pos + 4 * $count > $end and $err = "Truncated value for filter $i param $j", last; + my $val = ReadValue($dataPt, $pos, 'int32s', $count, 4 * $count); + $et->HandleTag($tagTablePtr, $tag, $val, + DataPt => $dataPt, + DataPos => $dataPos, + Start => $pos, + Size => 4 * $count, + ); + $pos += 4 * $count; + } + $pos = $nxt; # step to next filter + } + $err and $et->Warn($err, 1); + return 1; +} + +#------------------------------------------------------------------------------ +# Write Canon maker notes +# Inputs: 0) ExifTool object reference, 1) dirInfo ref, 2) tag table ref +# Returns: data block (may be empty if no Exif data) or undef on error +sub WriteCanon($$$) +{ + my ($et, $dirInfo, $tagTablePtr) = @_; + $et or return 1; # allow dummy access to autoload this package + my $dirData = Image::ExifTool::Exif::WriteExif($et, $dirInfo, $tagTablePtr); + # add footer which is written by some Canon models (format of a TIFF header) + if (defined $dirData and length $dirData and $$dirInfo{Fixup}) { + $dirData .= GetByteOrder() . Set16u(42) . Set32u(0); + $$dirInfo{Fixup}->AddFixup(length($dirData) - 4); + } + return $dirData; +} + +#------------------------------------------------------------------------------ +1; # end + +__END__ + +=head1 NAME + +Image::ExifTool::Canon - Canon EXIF maker notes tags + +=head1 SYNOPSIS + +This module is loaded automatically by Image::ExifTool when required. + +=head1 DESCRIPTION + +This module contains definitions required by Image::ExifTool to interpret +Canon maker notes in EXIF information. + +=head1 AUTHOR + +Copyright 2003-2019, Phil Harvey (phil at owl.phy.queensu.ca) + +This library is free software; you can redistribute it and/or modify it +under the same terms as Perl itself. + +=head1 REFERENCES + +=over 4 + +=item L<http://park2.wakwak.com/~tsuruzoh/Computer/Digicams/exif-e.html> + +=item L<http://www.wonderland.org/crw/> + +=item L<http://www.cybercom.net/~dcoffin/dcraw/> + +=item L<http://homepage3.nifty.com/kamisaka/makernote/makernote_canon.htm> + +=item (...plus lots of testing with my 300D, A570IS and G12!) + +=back + +=head1 ACKNOWLEDGEMENTS + +Thanks Michael Rommel and Daniel Pittman for information they provided about +the Digital Ixus and PowerShot S70 cameras, Juha Eskelinen and Emil Sit for +figuring out the 20D and 30D FileNumber, Denny Priebe for figuring out a +couple of 1D tags, and Michael Tiemann, Rainer Honle, Dave Nicholson, Chris +Huebsch, Ger Vermeulen, Darryl Zurn, D.J. Cristi, Bogdan, Vesa Kivisto and +Kai Harrekilde-Petersen for decoding a number of new tags. Also thanks to +everyone who made contributions to the LensType lookup list or the meanings +of other tag values. + +=head1 SEE ALSO + +L<Image::ExifTool::TagNames/Canon Tags>, +L<Image::ExifTool(3pm)|Image::ExifTool> + +=cut diff --git a/lib/Image/ExifTool/CanonCustom.pm b/lib/Image/ExifTool/CanonCustom.pm new file mode 100644 index 0000000..80e3c10 --- /dev/null +++ b/lib/Image/ExifTool/CanonCustom.pm @@ -0,0 +1,2780 @@ +#------------------------------------------------------------------------------ +# File: CanonCustom.pm +# +# Description: Read and write Canon Custom functions +# +# Revisions: 11/25/2003 - P. Harvey Created +# +# References: 1) http://park2.wakwak.com/~tsuruzoh/Computer/Digicams/exif-e.html +# 2) Christian Koller private communication (20D) +# 3) Rainer Honle private communication (5D) +# 4) David Pitcher private communication (1DmkIII firmware upgrade) +#------------------------------------------------------------------------------ + +package Image::ExifTool::CanonCustom; + +use strict; +use vars qw($VERSION); +use Image::ExifTool qw(:DataAccess); +use Image::ExifTool::Canon; +use Image::ExifTool::Exif; + +$VERSION = '1.55'; + +sub ProcessCanonCustom($$$); +sub ProcessCanonCustom2($$$); +sub WriteCanonCustom($$$); +sub WriteCanonCustom2($$$); +sub CheckCanonCustom($$$); +sub ConvertPFn($); +sub ConvertPFnInv($); + +my %onOff = ( 0 => 'On', 1 => 'Off' ); +my %offOn = ( 0 => 'Off', 1 => 'On' ); +my %disableEnable = ( 0 => 'Disable', 1 => 'Enable' ); +my %enableDisable = ( 0 => 'Enable', 1 => 'Disable' ); +my %convPFn = ( PrintConv => \&ConvertPfn, PrintConvInv => \&ConvertPfnInv ); + +#------------------------------------------------------------------------------ +# Custom functions for the 1D +# CanonCustom (keys are custom function number) +%Image::ExifTool::CanonCustom::Functions1D = ( + GROUPS => { 0 => 'MakerNotes', 2 => 'Camera' }, + PROCESS_PROC => \&ProcessCanonCustom, + WRITE_PROC => \&WriteCanonCustom, + CHECK_PROC => \&CheckCanonCustom, + WRITABLE => 'int8u', + NOTES => q{ + These custom functions are used by all 1D models up to but not including the + Mark III. + }, + 0 => { + Name => 'FocusingScreen', + PrintConv => { + 0 => 'Ec-N, R', + 1 => 'Ec-A,B,C,CII,CIII,D,H,I,L', + }, + }, + 1 => { + Name => 'FinderDisplayDuringExposure', + PrintConv => \%offOn, + }, + 2 => { + Name => 'ShutterReleaseNoCFCard', + Description => 'Shutter Release W/O CF Card', + PrintConv => { + 0 => 'Yes', + 1 => 'No', + }, + }, + 3 => { + Name => 'ISOSpeedExpansion', + Description => 'ISO Speed Expansion', + PrintConv => { + 0 => 'No', + 1 => 'Yes', + }, + }, + 4 => { + Name => 'ShutterAELButton', + Description => 'Shutter Button/AEL Button', + PrintConv => { + 0 => 'AF/AE lock stop', + 1 => 'AE lock/AF', + 2 => 'AF/AF lock, No AE lock', + 3 => 'AE/AF, No AE lock', + }, + }, + 5 => { + Name => 'ManualTv', + Description => 'Manual Tv/Av For M', + PrintConv => { + 0 => 'Tv=Main/Av=Control', + 1 => 'Tv=Control/Av=Main', + 2 => 'Tv=Main/Av=Main w/o lens', + 3 => 'Tv=Control/Av=Main w/o lens', + }, + }, + 6 => { + Name => 'ExposureLevelIncrements', + PrintConv => { + 0 => '1/3-stop set, 1/3-stop comp.', + 1 => '1-stop set, 1/3-stop comp.', + 2 => '1/2-stop set, 1/2-stop comp.', + }, + }, + 7 => { + Name => 'USMLensElectronicMF', + PrintConv => { + 0 => 'Turns on after one-shot AF', + 1 => 'Turns off after one-shot AF', + 2 => 'Always turned off', + }, + }, + 8 => { + Name => 'LCDPanels', + Description => 'Top/Back LCD Panels', + PrintConv => { + 0 => 'Remain. shots/File no.', + 1 => 'ISO/Remain. shots', + 2 => 'ISO/File no.', + 3 => 'Shots in folder/Remain. shots', + }, + }, + 9 => { + Name => 'AEBSequenceAutoCancel', + Description => 'AEB Sequence/Auto Cancel', + PrintConv => { + 0 => '0,-,+/Enabled', + 1 => '0,-,+/Disabled', + 2 => '-,0,+/Enabled', + 3 => '-,0,+/Disabled', + }, + }, + 10 => { + Name => 'AFPointIllumination', + PrintConv => { + 0 => 'On', + 1 => 'Off', + 2 => 'On without dimming', + 3 => 'Brighter', + }, + }, + 11 => { + Name => 'AFPointSelection', + PrintConv => { + 0 => 'H=AF+Main/V=AF+Command', + 1 => 'H=Comp+Main/V=Comp+Command', + 2 => 'H=Command only/V=Assist+Main', + 3 => 'H=FEL+Main/V=FEL+Command', + }, + }, + 12 => { + Name => 'MirrorLockup', + PrintConv => \%disableEnable, + }, + 13 => { + Name => 'AFPointSpotMetering', + Description => 'No. AF Points/Spot Metering', + PrintConv => { + 0 => '45/Center AF point', + 1 => '11/Active AF point', + 2 => '11/Center AF point', + 3 => '9/Active AF point', + }, + }, + 14 => { + Name => 'FillFlashAutoReduction', + PrintConv => \%enableDisable, + }, + 15 => { + Name => 'ShutterCurtainSync', + PrintConv => { + 0 => '1st-curtain sync', + 1 => '2nd-curtain sync', + }, + }, + 16 => { + Name => 'SafetyShiftInAvOrTv', + PrintConv => \%disableEnable, + }, + 17 => { + Name => 'AFPointActivationArea', + PrintConv => { + 0 => 'Single AF point', + 1 => 'Expanded (TTL. of 7 AF points)', + 2 => 'Automatic expanded (max. 13)', + }, + }, + 18 => { + Name => 'SwitchToRegisteredAFPoint', + PrintConv => { + 0 => 'Assist + AF', + 1 => 'Assist', + 2 => 'Only while pressing assist', + }, + }, + 19 => { + Name => 'LensAFStopButton', + PrintConv => { + 0 => 'AF stop', + 1 => 'AF start', + 2 => 'AE lock while metering', + 3 => 'AF point: M -> Auto / Auto -> Ctr.', + 4 => 'AF mode: ONE SHOT <-> AI SERVO', + 5 => 'IS start', + }, + }, + 20 => { + Name => 'AIServoTrackingSensitivity', + PrintConv => { + 0 => 'Standard', + 1 => 'Slow', + 2 => 'Moderately slow', + 3 => 'Moderately fast', + 4 => 'Fast', + }, + }, + 21 => { + Name => 'AIServoContinuousShooting', + PrintConv => { + 0 => 'Shooting not possible without focus', + 1 => 'Shooting possible without focus', + }, + }, +); + +# Custom functions for the 5D (ref 3) +%Image::ExifTool::CanonCustom::Functions5D = ( + GROUPS => { 0 => 'MakerNotes', 2 => 'Camera' }, + PROCESS_PROC => \&ProcessCanonCustom, + WRITE_PROC => \&WriteCanonCustom, + CHECK_PROC => \&CheckCanonCustom, + WRITABLE => 'int8u', + 0 => { + Name => 'FocusingScreen', + PrintConv => { + 0 => 'Ee-A', + 1 => 'Ee-D', + 2 => 'Ee-S', + }, + }, + 1 => { + Name => 'SetFunctionWhenShooting', + PrintConv => { + 0 => 'Default (no function)', + 1 => 'Change quality', + 2 => 'Change Parameters', + 3 => 'Menu display', + 4 => 'Image replay', + }, + }, + 2 => { + Name => 'LongExposureNoiseReduction', + PrintConv => { + 0 => 'Off', + 1 => 'Auto', + 2 => 'On', + }, + }, + 3 => { + Name => 'FlashSyncSpeedAv', + PrintConv => { + 0 => 'Auto', + 1 => '1/200 Fixed', + }, + }, + 4 => { + Name => 'Shutter-AELock', + PrintConv => { + 0 => 'AF/AE lock', + 1 => 'AE lock/AF', + 2 => 'AF/AF lock, No AE lock', + 3 => 'AE/AF, No AE lock', + }, + }, + 5 => { + Name => 'AFAssistBeam', + PrintConv => { + 0 => 'Emits', + 1 => 'Does not emit', + }, + }, + 6 => { + Name => 'ExposureLevelIncrements', + PrintConv => { + 0 => '1/3 Stop', + 1 => '1/2 Stop', + }, + }, + 7 => { + Name => 'FlashFiring', + PrintConv => { + 0 => 'Fires', + 1 => 'Does not fire', + }, + }, + 8 => { + Name => 'ISOExpansion', + PrintConv => \%offOn, + }, + 9 => { + Name => 'AEBSequenceAutoCancel', + Description => 'AEB Sequence/Auto Cancel', + PrintConv => { + 0 => '0,-,+/Enabled', + 1 => '0,-,+/Disabled', + 2 => '-,0,+/Enabled', + 3 => '-,0,+/Disabled', + }, + }, + 10 => { + Name => 'SuperimposedDisplay', + PrintConv => \%onOff, + }, + 11 => { + Name => 'MenuButtonDisplayPosition', + PrintConv => { + 0 => 'Previous (top if power off)', + 1 => 'Previous', + 2 => 'Top', + }, + }, + 12 => { + Name => 'MirrorLockup', + PrintConv => \%disableEnable, + }, + 13 => { + Name => 'AFPointSelectionMethod', + PrintConv => { + 0 => 'Normal', + 1 => 'Multi-controller direct', + 2 => 'Quick Control Dial direct', + }, + }, + 14 => { + Name => 'ETTLII', + Description => 'E-TTL II', + PrintConv => { + 0 => 'Evaluative', + 1 => 'Average', + }, + }, + 15 => { + Name => 'ShutterCurtainSync', + PrintConv => { + 0 => '1st-curtain sync', + 1 => '2nd-curtain sync', + }, + }, + 16 => { + Name => 'SafetyShiftInAvOrTv', + PrintConv => \%disableEnable, + }, + 17 => { + Name => 'AFPointActivationArea', + PrintConv => { + 0 => 'Standard', + 1 => 'Expanded', + }, + }, + 18 => { + Name => 'LCDDisplayReturnToShoot', + PrintConv => { + 0 => 'With Shutter Button only', + 1 => 'Also with * etc.', + }, + }, + 19 => { + Name => 'LensAFStopButton', + PrintConv => { + 0 => 'AF stop', + 1 => 'AF start', + 2 => 'AE lock while metering', + 3 => 'AF point: M -> Auto / Auto -> Ctr.', + 4 => 'ONE SHOT <-> AI SERVO', + 5 => 'IS start', + }, + }, + 20 => { + Name => 'AddOriginalDecisionData', + PrintConv => \%offOn, + }, +); + +# Custom functions for 10D +%Image::ExifTool::CanonCustom::Functions10D = ( + GROUPS => { 0 => 'MakerNotes', 2 => 'Camera' }, + PROCESS_PROC => \&ProcessCanonCustom, + WRITE_PROC => \&WriteCanonCustom, + CHECK_PROC => \&CheckCanonCustom, + WRITABLE => 'int8u', + 1 => { + Name => 'SetButtonWhenShooting', + PrintConv => { + 0 => 'Normal (disabled)', + 1 => 'Image quality', + 2 => 'Change parameters', + 3 => 'Menu display', + 4 => 'Image playback', + }, + }, + 2 => { + Name => 'ShutterReleaseNoCFCard', + Description => 'Shutter Release W/O CF Card', + PrintConv => { + 0 => 'Yes', + 1 => 'No', + }, + }, + 3 => { + Name => 'FlashSyncSpeedAv', + PrintConv => { + 0 => 'Auto', + 1 => '1/200 Fixed', + }, + }, + 4 => { + Name => 'Shutter-AELock', + PrintConv => { + 0 => 'AF/AE lock', + 1 => 'AE lock/AF', + 2 => 'AF/AF lock, No AE lock', + 3 => 'AE/AF, No AE lock', + }, + }, + 5 => { + Name => 'AFAssist', + Description => 'AF Assist/Flash Firing', + PrintConv => { + 0 => 'Emits/Fires', + 1 => 'Does not emit/Fires', + 2 => 'Only ext. flash emits/Fires', + 3 => 'Emits/Does not fire', + }, + }, + 6 => { + Name => 'ExposureLevelIncrements', + PrintConv => { + 0 => '1/2 Stop', + 1 => '1/3 Stop', + }, + }, + 7 => { + Name => 'AFPointRegistration', + PrintConv => { + 0 => 'Center', + 1 => 'Bottom', + 2 => 'Right', + 3 => 'Extreme Right', + 4 => 'Automatic', + 5 => 'Extreme Left', + 6 => 'Left', + 7 => 'Top', + }, + }, + 8 => { + Name => 'RawAndJpgRecording', + PrintConv => { + 0 => 'RAW+Small/Normal', + 1 => 'RAW+Small/Fine', + 2 => 'RAW+Medium/Normal', + 3 => 'RAW+Medium/Fine', + 4 => 'RAW+Large/Normal', + 5 => 'RAW+Large/Fine', + }, + }, + 9 => { + Name => 'AEBSequenceAutoCancel', + Description => 'AEB Sequence/Auto Cancel', + PrintConv => { + 0 => '0,-,+/Enabled', + 1 => '0,-,+/Disabled', + 2 => '-,0,+/Enabled', + 3 => '-,0,+/Disabled', + }, + }, + 10 => { + Name => 'SuperimposedDisplay', + PrintConv => \%onOff, + }, + 11 => { + Name => 'MenuButtonDisplayPosition', + PrintConv => { + 0 => 'Previous (top if power off)', + 1 => 'Previous', + 2 => 'Top', + }, + }, + 12 => { + Name => 'MirrorLockup', + PrintConv => \%disableEnable, + }, + 13 => { + Name => 'AssistButtonFunction', + PrintConv => { + 0 => 'Normal', + 1 => 'Select Home Position', + 2 => 'Select HP (while pressing)', + 3 => 'Av+/- (AF point by QCD)', + 4 => 'FE lock', + }, + }, + 14 => { + Name => 'FillFlashAutoReduction', + PrintConv => \%enableDisable, + }, + 15 => { + Name => 'ShutterCurtainSync', + PrintConv => { + 0 => '1st-curtain sync', + 1 => '2nd-curtain sync', + }, + }, + 16 => { + Name => 'SafetyShiftInAvOrTv', + PrintConv => \%disableEnable, + }, + 17 => { + Name => 'LensAFStopButton', + PrintConv => { + 0 => 'AF stop', + 1 => 'AF start', + 2 => 'AE lock while metering', + 3 => 'AF point: M->Auto/Auto->ctr', + 4 => 'One Shot <-> AI servo', + 5 => 'IS start', + }, + }, +); + +# Custom functions for the 20D (ref 2) +%Image::ExifTool::CanonCustom::Functions20D = ( + GROUPS => { 0 => 'MakerNotes', 2 => 'Camera' }, + PROCESS_PROC => \&ProcessCanonCustom, + WRITE_PROC => \&WriteCanonCustom, + CHECK_PROC => \&CheckCanonCustom, + WRITABLE => 'int8u', + 0 => { + Name => 'SetFunctionWhenShooting', + PrintConv => { + 0 => 'Default (no function)', + 1 => 'Change quality', + 2 => 'Change Parameters', + 3 => 'Menu display', + 4 => 'Image replay', + }, + }, + 1 => { + Name => 'LongExposureNoiseReduction', + PrintConv => \%offOn, + }, + 2 => { + Name => 'FlashSyncSpeedAv', + PrintConv => { + 0 => 'Auto', + 1 => '1/250 Fixed', + }, + }, + 3 => { + Name => 'Shutter-AELock', + PrintConv => { + 0 => 'AF/AE lock', + 1 => 'AE lock/AF', + 2 => 'AF/AF lock, No AE lock', + 3 => 'AE/AF, No AE lock', + }, + }, + 4 => { + Name => 'AFAssistBeam', + PrintConv => { + 0 => 'Emits', + 1 => 'Does not emit', + 2 => 'Only ext. flash emits', + }, + }, + 5 => { + Name => 'ExposureLevelIncrements', + PrintConv => { + 0 => '1/3 Stop', + 1 => '1/2 Stop', + }, + }, + 6 => { + Name => 'FlashFiring', + PrintConv => { + 0 => 'Fires', + 1 => 'Does not fire', + }, + }, + 7 => { + Name => 'ISOExpansion', + PrintConv => \%offOn, + }, + 8 => { + Name => 'AEBSequenceAutoCancel', + Description => 'AEB Sequence/Auto Cancel', + PrintConv => { + 0 => '0,-,+/Enabled', + 1 => '0,-,+/Disabled', + 2 => '-,0,+/Enabled', + 3 => '-,0,+/Disabled', + }, + }, + 9 => { + Name => 'SuperimposedDisplay', + PrintConv => \%onOff, + }, + 10 => { + Name => 'MenuButtonDisplayPosition', + PrintConv => { + 0 => 'Previous (top if power off)', + 1 => 'Previous', + 2 => 'Top', + }, + }, + 11 => { + Name => 'MirrorLockup', + PrintConv => \%disableEnable, + }, + 12 => { + Name => 'AFPointSelectionMethod', + PrintConv => { + 0 => 'Normal', + 1 => 'Multi-controller direct', + 2 => 'Quick Control Dial direct', + }, + }, + 13 => { + Name => 'ETTLII', + Description => 'E-TTL II', + PrintConv => { + 0 => 'Evaluative', + 1 => 'Average', + }, + }, + 14 => { + Name => 'ShutterCurtainSync', + PrintConv => { + 0 => '1st-curtain sync', + 1 => '2nd-curtain sync', + }, + }, + 15 => { + Name => 'SafetyShiftInAvOrTv', + PrintConv => \%disableEnable, + }, + 16 => { + Name => 'LensAFStopButton', + PrintConv => { + 0 => 'AF stop', + 1 => 'AF start', + 2 => 'AE lock while metering', + 3 => 'AF point: M -> Auto / Auto -> Ctr.', + 4 => 'ONE SHOT <-> AI SERVO', + 5 => 'IS start', + }, + }, + 17 => { + Name => 'AddOriginalDecisionData', + PrintConv => \%offOn, + }, +); + +# Custom functions for the 30D (PH) +%Image::ExifTool::CanonCustom::Functions30D = ( + GROUPS => { 0 => 'MakerNotes', 2 => 'Camera' }, + PROCESS_PROC => \&ProcessCanonCustom, + WRITE_PROC => \&WriteCanonCustom, + CHECK_PROC => \&CheckCanonCustom, + WRITABLE => 'int8u', + 1 => { + Name => 'SetFunctionWhenShooting', + PrintConv => { + 0 => 'Default (no function)', + 1 => 'Change quality', + 2 => 'Change Picture Style', + 3 => 'Menu display', + 4 => 'Image replay', + }, + }, + 2 => { + Name => 'LongExposureNoiseReduction', + PrintConv => { + 0 => 'Off', + 1 => 'Auto', + 2 => 'On', + }, + }, + 3 => { + Name => 'FlashSyncSpeedAv', + PrintConv => { + 0 => 'Auto', + 1 => '1/250 Fixed', + }, + }, + 4 => { + Name => 'Shutter-AELock', + PrintConv => { + 0 => 'AF/AE lock', + 1 => 'AE lock/AF', + 2 => 'AF/AF lock, No AE lock', + 3 => 'AE/AF, No AE lock', + }, + }, + 5 => { + Name => 'AFAssistBeam', + PrintConv => { + 0 => 'Emits', + 1 => 'Does not emit', + 2 => 'Only ext. flash emits', + }, + }, + 6 => { + Name => 'ExposureLevelIncrements', + PrintConv => { + 0 => '1/3 Stop', + 1 => '1/2 Stop', + }, + }, + 7 => { + Name => 'FlashFiring', + PrintConv => { + 0 => 'Fires', + 1 => 'Does not fire', + }, + }, + 8 => { + Name => 'ISOExpansion', + PrintConv => \%offOn, + }, + 9 => { + Name => 'AEBSequenceAutoCancel', + Description => 'AEB Sequence/Auto Cancel', + PrintConv => { + 0 => '0,-,+/Enabled', + 1 => '0,-,+/Disabled', + 2 => '-,0,+/Enabled', + 3 => '-,0,+/Disabled', + }, + }, + 10 => { + Name => 'SuperimposedDisplay', + PrintConv => \%onOff, + }, + 11 => { + Name => 'MenuButtonDisplayPosition', + PrintConv => { + 0 => 'Previous (top if power off)', + 1 => 'Previous', + 2 => 'Top', + }, + }, + 12 => { + Name => 'MirrorLockup', + PrintConv => \%disableEnable, + }, + 13 => { + Name => 'AFPointSelectionMethod', + PrintConv => { + 0 => 'Normal', + 1 => 'Multi-controller direct', + 2 => 'Quick Control Dial direct', + }, + }, + 14 => { + Name => 'ETTLII', + Description => 'E-TTL II', + PrintConv => { + 0 => 'Evaluative', + 1 => 'Average', + }, + }, + 15 => { + Name => 'ShutterCurtainSync', + PrintConv => { + 0 => '1st-curtain sync', + 1 => '2nd-curtain sync', + }, + }, + 16 => { + Name => 'SafetyShiftInAvOrTv', + PrintConv => \%disableEnable, + }, + 17 => { + Name => 'MagnifiedView', + PrintConv => { + 0 => 'Image playback only', + 1 => 'Image review and playback', + }, + }, + 18 => { + Name => 'LensAFStopButton', + PrintConv => { + 0 => 'AF stop', + 1 => 'AF start', + 2 => 'AE lock while metering', + 3 => 'AF point: M -> Auto / Auto -> Ctr.', + 4 => 'ONE SHOT <-> AI SERVO', + 5 => 'IS start', + }, + }, + 19 => { + Name => 'AddOriginalDecisionData', + PrintConv => \%offOn, + }, +); + +# Custom functions for the 350D (PH) +%Image::ExifTool::CanonCustom::Functions350D = ( + GROUPS => { 0 => 'MakerNotes', 2 => 'Camera' }, + PROCESS_PROC => \&ProcessCanonCustom, + WRITE_PROC => \&WriteCanonCustom, + CHECK_PROC => \&CheckCanonCustom, + WRITABLE => 'int8u', + 0 => { + Name => 'SetButtonCrossKeysFunc', + PrintConv => { + 0 => 'Normal', + 1 => 'Set: Quality', + 2 => 'Set: Parameter', + 3 => 'Set: Playback', + 4 => 'Cross keys: AF point select', + }, + }, + 1 => { + Name => 'LongExposureNoiseReduction', + PrintConv => \%offOn, + }, + 2 => { + Name => 'FlashSyncSpeedAv', + PrintConv => { + 0 => 'Auto', + 1 => '1/200 Fixed', + }, + }, + 3 => { + Name => 'Shutter-AELock', + PrintConv => { + 0 => 'AF/AE lock', + 1 => 'AE lock/AF', + 2 => 'AF/AF lock, No AE lock', + 3 => 'AE/AF, No AE lock', + }, + }, + 4 => { + Name => 'AFAssistBeam', + PrintConv => { + 0 => 'Emits', + 1 => 'Does not emit', + 2 => 'Only ext. flash emits', + }, + }, + 5 => { + Name => 'ExposureLevelIncrements', + PrintConv => { + 0 => '1/3 Stop', + 1 => '1/2 Stop', + }, + }, + 6 => { + Name => 'MirrorLockup', + PrintConv => \%disableEnable, + }, + 7 => { + Name => 'ETTLII', + Description => 'E-TTL II', + PrintConv => { + 0 => 'Evaluative', + 1 => 'Average', + }, + }, + 8 => { + Name => 'ShutterCurtainSync', + PrintConv => { + 0 => '1st-curtain sync', + 1 => '2nd-curtain sync', + }, + }, +); + +# Custom functions for the 400D (PH) +%Image::ExifTool::CanonCustom::Functions400D = ( + GROUPS => { 0 => 'MakerNotes', 2 => 'Camera' }, + PROCESS_PROC => \&ProcessCanonCustom, + WRITE_PROC => \&WriteCanonCustom, + CHECK_PROC => \&CheckCanonCustom, + WRITABLE => 'int8u', + 0 => { + Name => 'SetButtonCrossKeysFunc', + PrintConv => { + 0 => 'Set: Picture Style', + 1 => 'Set: Quality', + 2 => 'Set: Flash Exposure Comp', + 3 => 'Set: Playback', + 4 => 'Cross keys: AF point select', + }, + }, + 1 => { + Name => 'LongExposureNoiseReduction', + PrintConv => { + 0 => 'Off', + 1 => 'Auto', + 2 => 'On', + }, + }, + 2 => { + Name => 'FlashSyncSpeedAv', + PrintConv => { + 0 => 'Auto', + 1 => '1/200 Fixed', + }, + }, + 3 => { + Name => 'Shutter-AELock', + PrintConv => { + 0 => 'AF/AE lock', + 1 => 'AE lock/AF', + 2 => 'AF/AF lock, No AE lock', + 3 => 'AE/AF, No AE lock', + }, + }, + 4 => { + Name => 'AFAssistBeam', + PrintConv => { + 0 => 'Emits', + 1 => 'Does not emit', + 2 => 'Only ext. flash emits', + }, + }, + 5 => { + Name => 'ExposureLevelIncrements', + PrintConv => { + 0 => '1/3 Stop', + 1 => '1/2 Stop', + }, + }, + 6 => { + Name => 'MirrorLockup', + PrintConv => \%disableEnable, + }, + 7 => { + Name => 'ETTLII', + Description => 'E-TTL II', + PrintConv => { + 0 => 'Evaluative', + 1 => 'Average', + }, + }, + 8 => { + Name => 'ShutterCurtainSync', + PrintConv => { + 0 => '1st-curtain sync', + 1 => '2nd-curtain sync', + }, + }, + 9 => { + Name => 'MagnifiedView', + PrintConv => { + 0 => 'Image playback only', + 1 => 'Image review and playback', + }, + }, + 10 => { + Name => 'LCDDisplayAtPowerOn', + PrintConv => { + 0 => 'Display', + 1 => 'Retain power off status', + }, + }, +); + +# Custom functions for the D30/D60 +%Image::ExifTool::CanonCustom::FunctionsD30 = ( + GROUPS => { 0 => 'MakerNotes', 2 => 'Camera' }, + PROCESS_PROC => \&ProcessCanonCustom, + WRITE_PROC => \&WriteCanonCustom, + CHECK_PROC => \&CheckCanonCustom, + NOTES => 'Custom functions for the EOS D30 and D60.', + WRITABLE => 'int8u', + 1 => { + Name => 'LongExposureNoiseReduction', + PrintConv => \%offOn, + }, + 2 => { + Name => 'Shutter-AELock', + PrintConv => { + 0 => 'AF/AE lock', + 1 => 'AE lock/AF', + 2 => 'AF/AF lock', + 3 => 'AE+release/AE+AF', + }, + }, + 3 => { + Name => 'MirrorLockup', + PrintConv => \%disableEnable, + }, + 4 => { + Name => 'ExposureLevelIncrements', + PrintConv => { + 0 => '1/2 Stop', + 1 => '1/3 Stop', + }, + }, + 5 => { + Name => 'AFAssist', + PrintConv => { + 0 => 'Emits/Fires', + 1 => 'Does not emit/Fires', + 2 => 'Only ext. flash emits/Fires', + 3 => 'Emits/Does not fire', + }, + }, + 6 => { + Name => 'FlashSyncSpeedAv', + PrintConv => { + 0 => 'Auto', + 1 => '1/200 Fixed', + }, + }, + 7 => { + Name => 'AEBSequenceAutoCancel', + Description => 'AEB Sequence/Auto Cancel', + PrintConv => { + 0 => '0,-,+/Enabled', + 1 => '0,-,+/Disabled', + 2 => '-,0,+/Enabled', + 3 => '-,0,+/Disabled', + }, + }, + 8 => { + Name => 'ShutterCurtainSync', + PrintConv => { + 0 => '1st-curtain sync', + 1 => '2nd-curtain sync', + }, + }, + 9 => { + Name => 'LensAFStopButton', + PrintConv => { + 0 => 'AF Stop', + 1 => 'Operate AF', + 2 => 'Lock AE and start timer', + }, + }, + 10 => { + Name => 'FillFlashAutoReduction', + PrintConv => \%enableDisable, + }, + 11 => { + Name => 'MenuButtonReturn', + PrintConv => { + 0 => 'Top', + 1 => 'Previous (volatile)', + 2 => 'Previous', + }, + }, + 12 => { + Name => 'SetButtonWhenShooting', + PrintConv => { + 0 => 'Default (no function)', + 1 => 'Image quality', + 2 => 'Change ISO speed', + 3 => 'Change parameters', + }, + }, + 13 => { + Name => 'SensorCleaning', + PrintConv => \%disableEnable, + }, + 14 => { + Name => 'SuperimposedDisplay', + PrintConv => \%onOff, + }, + 15 => { + Name => 'ShutterReleaseNoCFCard', + Description => 'Shutter Release W/O CF Card', + PrintConv => { + 0 => 'Yes', + 1 => 'No', + }, + }, +); + +# Custom functions for unknown cameras +%Image::ExifTool::CanonCustom::FuncsUnknown = ( + GROUPS => { 0 => 'MakerNotes', 2 => 'Camera' }, + PROCESS_PROC => \&ProcessCanonCustom, +); + +# 1D personal function settings (ref PH) +%Image::ExifTool::CanonCustom::PersonalFuncs = ( + GROUPS => { 0 => 'MakerNotes', 2 => 'Camera' }, + PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData, + WRITE_PROC => \&Image::ExifTool::WriteBinaryData, + CHECK_PROC => \&Image::ExifTool::CheckBinaryData, + WRITABLE => 1, + NOTES => 'Personal function settings for the EOS-1D.', + FORMAT => 'int16u', + FIRST_ENTRY => 1, + 1 => { Name => 'PF0CustomFuncRegistration', %convPFn }, + 2 => { Name => 'PF1DisableShootingModes', %convPFn }, + 3 => { Name => 'PF2DisableMeteringModes', %convPFn }, + 4 => { Name => 'PF3ManualExposureMetering', %convPFn }, + 5 => { Name => 'PF4ExposureTimeLimits', %convPFn }, + 6 => { Name => 'PF5ApertureLimits', %convPFn }, + 7 => { Name => 'PF6PresetShootingModes', %convPFn }, + 8 => { Name => 'PF7BracketContinuousShoot', %convPFn }, + 9 => { Name => 'PF8SetBracketShots', %convPFn }, + 10 => { Name => 'PF9ChangeBracketSequence', %convPFn }, + 11 => { Name => 'PF10RetainProgramShift', %convPFn }, + #12 => { Name => 'PF11Unused', %convPFn }, + #13 => { Name => 'PF12Unused', %convPFn }, + 14 => { Name => 'PF13DrivePriority', %convPFn }, + 15 => { Name => 'PF14DisableFocusSearch', %convPFn }, + 16 => { Name => 'PF15DisableAFAssistBeam', %convPFn }, + 17 => { Name => 'PF16AutoFocusPointShoot', %convPFn }, + 18 => { Name => 'PF17DisableAFPointSel', %convPFn }, + 19 => { Name => 'PF18EnableAutoAFPointSel', %convPFn }, + 20 => { Name => 'PF19ContinuousShootSpeed', %convPFn }, + 21 => { Name => 'PF20LimitContinousShots', %convPFn }, + 22 => { Name => 'PF21EnableQuietOperation', %convPFn }, + #23 => { Name => 'PF22Unused', %convPFn }, + 24 => { Name => 'PF23SetTimerLengths', %convPFn }, + 25 => { Name => 'PF24LightLCDDuringBulb', %convPFn }, + 26 => { Name => 'PF25DefaultClearSettings', %convPFn }, + 27 => { Name => 'PF26ShortenReleaseLag', %convPFn }, + 28 => { Name => 'PF27ReverseDialRotation', %convPFn }, + 29 => { Name => 'PF28NoQuickDialExpComp', %convPFn }, + 30 => { Name => 'PF29QuickDialSwitchOff', %convPFn }, + 31 => { Name => 'PF30EnlargementMode', %convPFn }, + 32 => { Name => 'PF31OriginalDecisionData', %convPFn }, +); + +# 1D personal function values (ref PH) +%Image::ExifTool::CanonCustom::PersonalFuncValues = ( + GROUPS => { 0 => 'MakerNotes', 2 => 'Camera' }, + PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData, + WRITE_PROC => \&Image::ExifTool::WriteBinaryData, + CHECK_PROC => \&Image::ExifTool::CheckBinaryData, + WRITABLE => 1, + FORMAT => 'int16u', + FIRST_ENTRY => 1, + 1 => 'PF1Value', + 2 => 'PF2Value', + 3 => 'PF3Value', + 4 => { + Name => 'PF4ExposureTimeMin', + RawConv => '$val > 0 ? $val : 0', + ValueConv => 'exp(-Image::ExifTool::Canon::CanonEv($val*4)*log(2))*1000/8', + ValueConvInv => 'Image::ExifTool::Canon::CanonEvInv(-log($val*8/1000)/log(2))/4', + PrintConv => 'Image::ExifTool::Exif::PrintExposureTime($val)', + PrintConvInv => 'Image::ExifTool::Exif::ConvertFraction($val)', + }, + 5 => { + Name => 'PF4ExposureTimeMax', + RawConv => '$val > 0 ? $val : 0', + ValueConv => 'exp(-Image::ExifTool::Canon::CanonEv($val*4)*log(2))*1000/8', + ValueConvInv => 'Image::ExifTool::Canon::CanonEvInv(-log($val*8/1000)/log(2))/4', + PrintConv => 'Image::ExifTool::Exif::PrintExposureTime($val)', + PrintConvInv => 'Image::ExifTool::Exif::ConvertFraction($val)', + }, + 6 => { + Name => 'PF5ApertureMin', + RawConv => '$val > 0 ? $val : 0', + ValueConv => 'exp(Image::ExifTool::Canon::CanonEv($val*4-32)*log(2)/2)', + ValueConvInv => '(Image::ExifTool::Canon::CanonEvInv(log($val)*2/log(2))+32)/4', + PrintConv => 'sprintf("%.2g",$val)', + PrintConvInv => '$val', + }, + 7 => { + Name => 'PF5ApertureMax', + RawConv => '$val > 0 ? $val : 0', + ValueConv => 'exp(Image::ExifTool::Canon::CanonEv($val*4-32)*log(2)/2)', + ValueConvInv => '(Image::ExifTool::Canon::CanonEvInv(log($val)*2/log(2))+32)/4', + PrintConv => 'sprintf("%.2g",$val)', + PrintConvInv => '$val', + }, + 8 => 'PF8BracketShots', + 9 => 'PF19ShootingSpeedLow', + 10 => 'PF19ShootingSpeedHigh', + 11 => 'PF20MaxContinousShots', + 12 => 'PF23ShutterButtonTime', + 13 => 'PF23FELockTime', + 14 => 'PF23PostReleaseTime', + 15 => 'PF25AEMode', + 16 => 'PF25MeteringMode', + 17 => 'PF25DriveMode', + 18 => 'PF25AFMode', + 19 => 'PF25AFPointSel', + 20 => 'PF25ImageSize', + 21 => 'PF25WBMode', + 22 => 'PF25Parameters', + 23 => 'PF25ColorMatrix', + 24 => 'PF27Value', +); + +# Custom functions used by the 1D Mark III and later models (ref PH) +%Image::ExifTool::CanonCustom::Functions2 = ( + GROUPS => { 0 => 'MakerNotes', 2 => 'Camera' }, + PROCESS_PROC => \&ProcessCanonCustom2, + CHECK_PROC => \&Image::ExifTool::Exif::CheckExif, + WRITE_PROC => \&WriteCanonCustom2, + WRITABLE => 'int32s', + NOTES => q{ + Beginning with the EOS 1D Mark III, Canon finally created a set of custom + function tags which are (reasonably) consistent across models. The EOS 1D + Mark III has 57 custom function tags divided into four main groups: 1. + Exposure (0x0101-0x010f), 2. Image (0x0201-0x0203), Flash Exposure + (0x0304-0x0306) and Display (0x0407-0x0409), 3. Auto Focus (0x0501-0x050e) + and Drive (0x060f-0x0611), and 4. Operation (0x0701-0x070a) and Others + (0x080b-0x0810). The table below lists tags used by the EOS 1D Mark III, as + well as newer tags and values added by later models. + }, + # grouped in 4 groups: + # 1) Exposure + 0x0101 => [ + { + Name => 'ExposureLevelIncrements', + Condition => '$$self{Model} =~ /\b1Ds?\b/', + Notes => '1DmkIII and 1DmkIV', + PrintConv => { + 0 => '1/3-stop set, 1/3-stop comp.', + 1 => '1-stop set, 1/3-stop comp.', + 2 => '1/2-stop set, 1/2-stop comp.', + }, + }, + { + Name => 'ExposureLevelIncrements', + Notes => 'other models', + PrintConv => { + 0 => '1/3 Stop', + 1 => '1/2 Stop', + }, + }, + ], + 0x0102 => { + Name => 'ISOSpeedIncrements', + PrintConv => { + 0 => '1/3 Stop', + 1 => '1 Stop', + }, + }, + 0x0103 => [ + { + Name => 'ISOSpeedRange', + Condition => '$$self{Model} =~ /\b1D/', + Notes => '1DmkIII and 1DmkIV', + Count => 3, + # (this decoding may not be valid for CR2 images?) + ValueConv => [ + undef, + # this may also be set to "H" (Hi6400) -- is this the -1 value I see? - PH + '$val < 2 ? $val : ($val < 1000 ? exp(($val/8-9)*log(2))*100 : 0)', # (educated guess) + # this may also be set to "L" (Lo50) -- is this the 1 value I see? - PH + '$val < 2 ? $val : ($val < 1000 ? exp(($val/8-9)*log(2))*100 : 0)', # (educated guess) + ], + ValueConvInv => [ + undef, + '$val < 2 ? $val : int(8*(log($val/100)/log(2)+9) + 0.5)', + '$val < 2 ? $val : int(8*(log($val/100)/log(2)+9) + 0.5)', + ], + PrintConv => [ + \%disableEnable, + 'sprintf("Max %.0f",$val)', + 'sprintf("Min %.0f",$val)', + ], + PrintConvInv => [ + undef, + '$val=~/(-?[\d.]+)/ ? $1 : 0', + '$val=~/(-?[\d.]+)/ ? $1 : 0', + ], + }, + { + Name => 'ISOExpansion', + Notes => 'other models', + PrintConv => \%offOn, + }, + ], + 0x0104 => { + Name => 'AEBAutoCancel', + PrintConv => \%onOff, + }, + 0x0105 => { + Name => 'AEBSequence', + Notes => 'value of 2 not used by 40D, 50D, 60D, 5DmkII and 7D', + PrintConv => { + 0 => '0,-,+', + 1 => '-,0,+', + 2 => '+,0,-', + }, + }, + 0x0106 => [{ + Name => 'AEBShotCount', + Condition => '$count == 1', + Notes => 'one value for some models...', + PrintConv => { + 0 => '3 shots', + 1 => '2 shots', + 2 => '5 shots', + 3 => '7 shots', + }, + },{ + Name => 'AEBShotCount', + Count => 2, + Notes => 'two values for others', + PrintConv => { + '3 0' => '3 shots', + '2 1' => '2 shots', + '5 2' => '5 shots', + '7 3' => '7 shots', + }, + }], + 0x0107 => { + Name => 'SpotMeterLinkToAFPoint', + PrintConv => { + 0 => 'Disable (use center AF point)', + 1 => 'Enable (use active AF point)', + }, + }, + 0x0108 => { + Name => 'SafetyShift', + Notes => 'value of 2 not used by 40D, 50D, 60D, 5DmkII and 7D', + PrintConv => { + 0 => 'Disable', + 1 => 'Enable (Tv/Av)', + 2 => 'Enable (ISO speed)', + }, + }, + 0x0109 => { + Name => 'UsableShootingModes', + Count => 2, + PrintConv => [ + \%disableEnable, + 'sprintf("Flags 0x%x",$val)', # (M, Tv, Av, P, Bulb) + ], + PrintConvInv => [ + undef, + '$val=~/0x([\dA-F]+)/i ? hex($1) : undef', + ], + }, + 0x010a => { + Name => 'UsableMeteringModes', + Count => 2, + PrintConv => [ + \%disableEnable, + 'sprintf("Flags 0x%x",$val)', # (evaluative,partial,spot,center-weighted average) + ], + PrintConvInv => [ + undef, + '$val=~/0x([\dA-F]+)/i ? hex($1) : undef', + ], + }, + 0x010b => { + Name => 'ExposureModeInManual', + PrintConv => { + 0 => 'Specified metering mode', + 1 => 'Evaluative metering', + 2 => 'Partial metering', + 3 => 'Spot metering', + 4 => 'Center-weighted average', + }, + }, + 0x010c => [{ + Name => 'ShutterSpeedRange', + Condition => '$count == 3', + Count => 3, + ValueConv => [ + undef, + 'exp(-($val/8-7)*log(2))', + 'exp(-($val/8-7)*log(2))', + ], + ValueConvInv => [ + undef, + 'int(-8*(log($val)/log(2)-7) + 0.5)', + 'int(-8*(log($val)/log(2)-7) + 0.5)', + ], + PrintConv => [ + \%disableEnable, + '"Hi " . Image::ExifTool::Exif::PrintExposureTime($val)', + '"Lo " . Image::ExifTool::Exif::PrintExposureTime($val)', + ], + PrintConvInv => [ + undef, + '$val=~m{([\d./]+)} ? eval $1 : 0', + '$val=~m{([\d./]+)} ? eval $1 : 0', + ], + },{ # (EOS R) + Name => 'ShutterSpeedRange', + Condition => '$count == 4', + Count => 4, + ValueConv => [ # (NC) + 'exp(-$val/(1600*log(2)))', + 'exp(-$val/(1600*log(2)))', + 'exp(-$val/(1600*log(2)))', + 'exp(-$val/(1600*log(2)))', + ], + ValueConvInv => [ + 'int(-log($val)*1600*log(2) + 0.5)', + 'int(-log($val)*1600*log(2) + 0.5)', + 'int(-log($val)*1600*log(2) + 0.5)', + 'int(-log($val)*1600*log(2) + 0.5)', + ], + PrintConv => [ # (NC) + '"Manual: Hi " . Image::ExifTool::Exif::PrintExposureTime($val)', + '"Lo " . Image::ExifTool::Exif::PrintExposureTime($val)', + '"Auto: Hi " . Image::ExifTool::Exif::PrintExposureTime($val)', + '"Lo " . Image::ExifTool::Exif::PrintExposureTime($val)', + ], + PrintConvInv => [ + '$val=~m{([\d./]+)} ? eval $1 : 0', + '$val=~m{([\d./]+)} ? eval $1 : 0', + '$val=~m{([\d./]+)} ? eval $1 : 0', + '$val=~m{([\d./]+)} ? eval $1 : 0', + ], + }], + 0x010d => [{ + Name => 'ApertureRange', + Condition => '$count == 3', + Count => 3, + ValueConv => [ + undef, + 'exp(($val/8-1)*log(2)/2)', + 'exp(($val/8-1)*log(2)/2)', + ], + ValueConvInv => [ + undef, + 'int(8*(log($val)*2/log(2)+1) + 0.5)', + 'int(8*(log($val)*2/log(2)+1) + 0.5)', + ], + PrintConv => [ + \%disableEnable, + 'sprintf("Closed %.2g",$val)', + 'sprintf("Open %.2g",$val)', + ], + PrintConvInv => [ + undef, + '$val=~/([\d.]+)/ ? $1 : 0', + '$val=~/([\d.]+)/ ? $1 : 0', + ], + },{ # (EOS R) + Name => 'ApertureRange', + Condition => '$count == 4', + Count => 4, + ValueConv => [ # (NC) + 'exp($val/2400)', + 'exp($val/2400)', + 'exp($val/2400)', + 'exp($val/2400)', + ], + ValueConvInv => [ + 'int(log($val)*2400) + 0.5)', + 'int(log($val)*2400) + 0.5)', + 'int(log($val)*2400) + 0.5)', + 'int(log($val)*2400) + 0.5)', + ], + PrintConv => [ # (NC) + 'sprintf("Manual: Closed %.2g",$val)', + 'sprintf("Open %.2g",$val)', + 'sprintf("Auto: Closed %.2g",$val)', + 'sprintf("Open %.2g",$val)', + ], + PrintConvInv => [ + '$val=~/([\d.]+)/ ? $1 : 0', + '$val=~/([\d.]+)/ ? $1 : 0', + '$val=~/([\d.]+)/ ? $1 : 0', + '$val=~/([\d.]+)/ ? $1 : 0', + ], + }], + 0x010e => { + Name => 'ApplyShootingMeteringMode', + Count => 8, + PrintConv => [ \%disableEnable ], + }, + 0x010f => [ + { + Name => 'FlashSyncSpeedAv', + Condition => '$$self{Model} =~ /\b(40D|1Ds Mark III)\b/', + Notes => '40D and 1Ds Mark III', + PrintConv => { + 0 => 'Auto', + 1 => '1/250 Fixed', + }, + }, + { + Name => 'FlashSyncSpeedAv', + Condition => '$$self{Model} =~ /\b(50D|60D|7D)\b/', + Notes => '50D, 60D and 7D', + PrintConv => { + 0 => 'Auto', + 1 => '1/250-1/60 Auto', + 2 => '1/250 Fixed', + }, + }, + { + Name => 'FlashSyncSpeedAv', + Condition => '$$self{Model} =~ /\b(450D|XSi|Kiss X2|1000D|XS|Kiss F)\b/', + Notes => '450D and 1000D', + PrintConv => { + 0 => 'Auto', + 1 => '1/200 Fixed', + }, + }, + { + Name => 'FlashSyncSpeedAv', + Condition => '$$self{Model} =~ /\bEOS-1Ds? Mark III\b/', + Notes => '1D Mark III and 1Ds Mark III', + PrintConv => { + 0 => 'Auto', + 1 => '1/300 Fixed', + }, + }, + { + Name => 'FlashSyncSpeedAv', + Condition => '$$self{Model} =~ /\bEOS-1D Mark IV\b/', + Notes => '1D Mark IV', + PrintConv => { + 0 => 'Auto', + 1 => '1/300-1/60 Auto', + 2 => '1/300 Fixed', + }, + }, + { + Name => 'FlashSyncSpeedAv', + Notes => '5D Mark II, 5D Mark III, 500D, 550D, 600D and 1100D', + PrintConv => { + 0 => 'Auto', + 1 => '1/200-1/60 Auto', + 2 => '1/200 Fixed', + }, + }, + ], + 0x0110 => { # new for 1DmkIV + Name => 'AEMicroadjustment', + Count => 3, + PrintConv => [ \%disableEnable ], + }, + 0x0111 => { # new for 1DmkIV + Name => 'FEMicroadjustment', + Count => 3, + PrintConv => [ \%disableEnable ], + }, + 0x0112 => [{ # (5DS) + Name => 'SameExposureForNewAperture', + PrintConv => { + 0 => 'Disable', + 1 => 'ISO Speed', + 2 => 'Shutter Speed', + }, + },{ # (EOS R) + Name => 'SameExposureForNewAperture', + Notes => 'EOS R', + PrintConv => { + 0 => 'Disable', + 1 => 'ISO Speed', + 2 => 'ISO Speed/Shutter Speed', + 3 => 'Shutter Speed', + }, + }], + 0x0113 => { # (200D) + Name => 'ExposureCompAutoCancel', + PrintConv => \%enableDisable, + }, + 0x0114 => { # (R) + Name => 'AELockMeterModeAfterFocus', + # metering modes where AE lock after focus applies: + PrintConv => { BITMASK => { # (NC) + 0 => 'Evaluative', + 1 => 'Partial', + 2 => 'Spot', + 3 => 'Center-weighted', + }}, + }, + #### 2a) Image + 0x0201 => { + Name => 'LongExposureNoiseReduction', + PrintConv => { + 0 => 'Off', + 1 => 'Auto', + 2 => 'On', + }, + }, + 0x0202 => [ + { + Name => 'HighISONoiseReduction', + Condition => q{ + $$self{Model} =~ /\b(50D|60D|5D Mark II|7D|500D|T1i|Kiss X3|550D|T2i|Kiss X4)\b/ or + $$self{Model} =~ /\b(600D|T3i|Kiss X5|1100D|T3|Kiss X50)\b/ + }, + Notes => '50D, 60D, 500D, 550D, 600D, 1100D, 5DmkII and 7D', + PrintConv => { + 0 => 'Standard', + 1 => 'Low', + 2 => 'Strong', + 3 => 'Off', + }, + }, + { + Name => 'HighISONoiseReduction', + Notes => 'other models', + PrintConv => \%offOn, + }, + ], + 0x0203 => { + Name => 'HighlightTonePriority', + PrintConv => \%disableEnable + }, + 0x0204 => [ + { + Name => 'AutoLightingOptimizer', + Condition => '$$self{Model} =~ /\b(50D|5D Mark II|500D|T1i|Kiss X3|1D Mark IV)\b/', + Notes => '50D, 500D, 5DmkII and 1DmkIV', + PrintConv => { + 0 => 'Standard', + 1 => 'Low', + 2 => 'Strong', + 3 => 'Disable', + }, + }, + { + Name => 'AutoLightingOptimizer', + Notes => 'other models', + PrintConv => \%enableDisable, + }, + ], + # 0x0205 - Added in 5DmkII firmware update + #### 2b) Flash exposure + 0x0304 => { + Name => 'ETTLII', + Description => 'E-TTL II', + PrintConv => { + 0 => 'Evaluative', + 1 => 'Average', + }, + }, + 0x0305 => { + Name => 'ShutterCurtainSync', + PrintConv => { + 0 => '1st-curtain sync', + 1 => '2nd-curtain sync', + }, + }, + 0x0306 => { + Name => 'FlashFiring', + PrintConv => { + 0 => 'Fires', + 1 => 'Does not fire', + }, + }, + #### 2c) Display + 0x0407 => { + Name => 'ViewInfoDuringExposure', + PrintConv => \%disableEnable, + }, + 0x0408 => { + Name => 'LCDIlluminationDuringBulb', + PrintConv => \%offOn, + }, + 0x0409 => [ + { + Name => 'InfoButtonWhenShooting', + Condition => '$$self{Model} =~ /\b1Ds? Mark III\b/', + Notes => '1D Mark III', + PrintConv => { + 0 => 'Displays camera settings', + 1 => 'Displays shooting functions', + }, + }, + { + Name => 'InfoButtonWhenShooting', + Notes => '1D Mark IV', + PrintConv => { + # reversed from earlier models. grr... + 0 => 'Displays shooting functions', + 1 => 'Displays camera settings', + }, + }, + ], + 0x040a => { # new for 5DmkIII + Name => 'ViewfinderWarnings', + PrintConv => { BITMASK => { #(NC) + 0 => 'Monochrome', # (have seen for: 5DmkII, 6D) + 1 => 'WB corrected', # (have seen for: 5DmkII, 6D) + 2 => 'One-touch image quality', # (have seen for: 5DmkII; doesn't exist for 6D) + 3 => 'ISO expansion', # (have seen for: 5DmkII) + 4 => 'Spot metering', # (have seen for: 5DmkII, 6D) + }}, + }, + 0x040b => { # new for 5DmkIII + Name => 'LVShootingAreaDisplay', + PrintConv => { + 0 => 'Masked', + 1 => 'Outlined', + }, + }, + 0x040c => { # (7DmkII) + Name => 'LVShootingAreaDisplay', + PrintConv => { + 0 => 'Masked', + 1 => 'Outlined', + }, + }, + #### 3a) Auto focus + 0x0501 => { + Name => 'USMLensElectronicMF', + PrintConv => { + 0 => 'Enable after one-shot AF', + 1 => 'Disable after one-shot AF', + 2 => 'Disable in AF mode', + }, + }, + 0x0502 => { + Name => 'AIServoTrackingSensitivity', + PrintConv => { + -2 => 'Slow', # (Locked on -2 for 6D) + -1 => 'Medium Slow', # (Locked on -1 for 6D) + 0 => 'Standard', + 1 => 'Medium Fast', # (Responsive +1 for 6D) + 2 => 'Fast', # (Responsive +2 for 6D) + }, + }, + 0x0503 => { + Name => 'AIServoImagePriority', + PrintConv => { + 0 => '1: AF, 2: Tracking', + 1 => '1: AF, 2: Drive speed', + 2 => '1: Release, 2: Drive speed', + 3 => '1: Release, 2: Tracking', # 7D/1DmkIV + }, + }, + 0x0504 => { + Name => 'AIServoTrackingMethod', + PrintConv => { + 0 => 'Main focus point priority', + 1 => 'Continuous AF track priority', + }, + }, + 0x0505 => { + Name => 'LensDriveNoAF', + PrintConv => { + 0 => 'Focus search on', + 1 => 'Focus search off', + }, + }, + 0x0506 => { + Name => 'LensAFStopButton', + Notes => 'value of 6 not used by 40D, 50D and 5DmkII', + PrintConv => { + 0 => 'AF stop', + 1 => 'AF start', + 2 => 'AE lock', + 3 => 'AF point: M->Auto/Auto->ctr', + 4 => 'One Shot <-> AI servo', + 5 => 'IS start', + 6 => 'Switch to registered AF point', + 7 => 'Spot AF', # 1DmkIV + }, + }, + 0x0507 => { + Name => 'AFMicroadjustment', + Count => 5, + PrintConv => [ + { + 0 => 'Disable', + 1 => 'Adjust all by same amount', + 2 => 'Adjust by lens', + }, + # DECODE OTHER VALUES + ], + }, + 0x0508 => [ + { + Name => 'AFPointAreaExpansion', + Condition => '$$self{Model} =~ /\b5D Mark II\b/', + Notes => '5D Mark II', + PrintConv => { + 0 => 'Disable', + 1 => 'Enable', + }, + }, + { + Name => 'AFPointAreaExpansion', + Condition => '$$self{Model} =~ /\b1Ds Mark III\b/', + Notes => '1Ds Mark III', + PrintConv => { + 0 => 'Disable', + 1 => 'Enable (left/right Assist AF points)', + 2 => 'Enable (surrounding Assist AF points)', + }, + }, + { + Name => 'AFPointAreaExpansion', + Notes => 'other models', + PrintConv => { + 0 => 'Disable', + 1 => 'Left/right AF points', + 2 => 'Surrounding AF points', + 3 => 'All 45 points area', # 1DmkIV + }, + }, + ], + 0x0509 => [ + { + Name => 'SelectableAFPoint', + Condition => '$$self{Model} =~ /\b1D Mark IV\b/', + Notes => '1D Mark IV', + PrintConv => { + 0 => '45 points', + 1 => '19 points', + 2 => '11 points', + 3 => 'Inner 9 points', + 4 => 'Outer 9 points', + }, + }, + { + Name => 'SelectableAFPoint', + Notes => 'other models', + PrintConv => { + 0 => '19 points', + 1 => 'Inner 9 points', + 2 => 'Outer 9 points', + 3 => '19 Points, Multi-controller selectable', #4 + 4 => 'Inner 9 Points, Multi-controller selectable', #4 + 5 => 'Outer 9 Points, Multi-controller selectable', #4 + }, + }, + ], + 0x050a => [ + { + Name => 'SwitchToRegisteredAFPoint', + Condition => '$$self{Model} =~ /\b1D Mark IV\b/', + Notes => '1D Mark IV', + PrintConv => { + 0 => 'Disable', + 1 => 'Switch with multi-controller', + 2 => 'Only while AEL is pressed', + }, + }, + { + Name => 'SwitchToRegisteredAFPoint', + Notes => 'other models', + PrintConv => \%disableEnable, + }, + ], + 0x050b => { + Name => 'AFPointAutoSelection', + PrintConv => { + 0 => 'Control-direct:disable/Main:enable', + 1 => 'Control-direct:disable/Main:disable', + 2 => 'Control-direct:enable/Main:enable', + }, + }, + 0x050c => [ + { + Name => 'AFPointDisplayDuringFocus', + Condition => '$$self{Model} =~ /\b1D\b/', + Notes => '1D models', + PrintConv => { + 0 => 'On', + 1 => 'Off', + 2 => 'On (when focus achieved)', + }, + }, + { + Name => 'AFPointDisplayDuringFocus', + Notes => 'other models', # (7D, 70D, 750D, 760D) + PrintConv => { + 0 => 'Selected (constant)', + 1 => 'All (constant)', + 2 => 'Selected (pre-AF, focused)', + 3 => 'Selected (focused)', + 4 => 'Disable display', + }, + }, + ], + 0x050d => { + Name => 'AFPointBrightness', + PrintConv => { + 0 => 'Normal', + 1 => 'Brighter', + }, + }, + 0x050e => [ + { + Name => 'AFAssistBeam', + Condition => '$$self{Model} =~ /\b(1D Mark IV|6D)\b/', + Notes => '1D Mark IV and 6D', + PrintConv => { + 0 => 'Emits', + 1 => 'Does not emit', + 2 => 'IR AF assist beam only', + }, + }, + { + Name => 'AFAssistBeam', + Notes => 'other models; values 2-3 not used by 1DmkIII or 5DmkII, value 3 new for 7D', + PrintConv => { + 0 => 'Emits', + 1 => 'Does not emit', + 2 => 'Only ext. flash emits', + 3 => 'IR AF assist beam only', # new for 7D + }, + }, + ], + 0x050f => [ # new for 40D + { + Name => 'AFPointSelectionMethod', + Condition => '$$self{Model} !~ /\b60D\b/', + Notes => '40D, 50D and 5DmkII', + PrintConv => { + 0 => 'Normal', + 1 => 'Multi-controller direct', + 2 => 'Quick Control Dial direct', + }, + }, + { + Name => 'AFPointSelectionMethod', + Notes => '60D', + PrintConv => { + 0 => 'AF point button: Activate AF Sel; Rear dial: Select AF points', + 1 => 'AF point button: Auto selection; Rear dial: Manual selection', + }, + }, + ], + 0x0510 => [ # new for 40D + { + Name => 'VFDisplayIllumination', # (7D quirk, or decoded incorrectly?) + Condition => '$$self{Model} =~ /\b7D\b/', + Notes => '7D', + PrintConv => { + 0 => 'Auto', + 1 => 'Enable', + 2 => 'Disable', + }, + }, + { + Name => 'SuperimposedDisplay', + Notes => 'other models', + PrintConv => \%onOff, + }, + ], + 0x0511 => [ # new for 40D + { + Name => 'AFDuringLiveView', + Condition => '$$self{Model} =~ /\b40D\b/', + Notes => '40D', + PrintConv => \%disableEnable, + }, + { + Name => 'AFDuringLiveView', + Notes => '450D and 1000D', + PrintConv => { + 0 => 'Disable', + 1 => 'Quick mode', + 2 => 'Live mode', + }, + }, + ], + 0x0512 => { # new for 7D + Name => 'SelectAFAreaSelectMode', + PrintConv => [ + { + 0 => 'Disable', + 1 => 'Enable', + 2 => 'Register', + 3 => 'Select AF-modes', + }, + 'sprintf("Flags 0x%x",$val)', # (70D=Manual 1pt,Manual zone,Auto 19pt) + ], + PrintConvInv => [ + undef, + '$val=~/0x([\dA-F]+)/i ? hex($1) : undef', + ], + }, + 0x0513 => { # new for 7D + Name => 'ManualAFPointSelectPattern', + PrintConv => { + 0 => 'Stops at AF area edges', + 1 => 'Continuous', + }, + }, + 0x0514 => { # new for 7D + Name => 'DisplayAllAFPoints', + PrintConv => \%enableDisable, + }, + 0x0515 => { # new for 7D + Name => 'FocusDisplayAIServoAndMF', + PrintConv => \%enableDisable, + }, + 0x0516 => { # new for 7D and 1DmkIV + Name => 'OrientationLinkedAFPoint', + PrintConv => { + 0 => 'Same for vertical and horizontal', + 1 => 'Select different AF points', + }, + }, + 0x0517 => { # new for 1DmkIV + Name => 'MultiControllerWhileMetering', + PrintConv => { + 0 => 'Off', + 1 => 'AF point selection', + }, + }, + 0x0518 => { # new for 6D + Name => 'AccelerationTracking', + }, + 0x0519 => { # new for 6D + Name => 'AIServoFirstImagePriority', + PrintConv => { #(NC) + -1 => 'Release priority', + 0 => 'Equal priority', + 1 => 'Focus priority', + }, + }, + 0x051a => { # new for 6D + Name => 'AIServoSecondImagePriority', + PrintConv => { #(NC) + -1 => 'Shooting speed priority', + 0 => 'Equal priority', + 1 => 'Focus priority', + }, + }, + 0x051b => { # (70D) + Name => 'AFAreaSelectMethod', + PrintConv => { + 0 => 'AF area selection button', + 1 => 'Main dial', + }, + }, + 0x051c => { # (750D) + Name => 'AutoAFPointColorTracking', + PrintConv => { + 0 => 'On-Shot AF only', + 1 => 'Disable', + }, + }, + 0x051d => { # (750D/760D) + Name => 'VFDisplayIllumination', + PrintConv => [{ + 0 => 'Auto', + 1 => 'Enable', + 2 => 'Disable', + },{ + 0 => 'Non-illuminated', #(NC) + 1 => 'Illuminated', #(NC) + }], + }, + 0x051e => { # (80D) + Name => 'InitialAFPointAIServoAF', + PrintConv => { + 0 => 'Auto', + 1 => 'Initial AF point selected', + 2 => 'Manual AF point', + }, + }, + #### 3b) Drive + 0x060f => { + Name => 'MirrorLockup', + Notes => 'value of 2 not used by some models', + PrintConv => { + 0 => 'Disable', + 1 => 'Enable', + 2 => 'Enable: Down with Set', + }, + }, + 0x0610 => { + Name => 'ContinuousShootingSpeed', + Count => 3, + PrintConv => [ + \%disableEnable, + '"Hi $val"', + '"Lo $val"', + ], + PrintConvInv => [ + undef, + '$val=~/(\d+)/ ? $1 : 0', + '$val=~/(\d+)/ ? $1 : 0', + ], + }, + 0x0611 => { + Name => 'ContinuousShotLimit', + Count => 2, + PrintConv => [ + \%disableEnable, + '"$val shots"', + ], + PrintConvInv => [ + undef, + '$val=~/(\d+)/ ? $1 : 0', + ], + }, + 0x0612 => { # (1DX) + Name => 'RestrictDriveModes', + Count => 2, + PrintConv => [ + \%disableEnable, + 'sprintf("Flags 0x%x",$val)', # (Single,Cont Hi,Cont Lo,Timer 10,Timer 2,Silent,Super Hi) + ], + PrintConvInv => [ + undef, + '$val=~/0x([\dA-F]+)/i ? hex($1) : undef', + ], + }, + #### 4a) Operation + 0x0701 => [ + { + Name => 'Shutter-AELock', + Condition => q{ + $$self{Model} =~ /\b(1000D|XS|Kiss F|500D|T1i|Kiss X3|550D|T2i|Kiss X4)\b/ or + $$self{Model} =~ /\b(600D|T3i|Kiss X5|1100D|T3|Kiss X50)\b/ + }, + Notes => '500D, 550D, 600D, 1000D and 1100D', + PrintConv => { + 0 => 'AF/AE lock', + 1 => 'AE lock/AF', + 2 => 'AF/AF lock, No AE lock', + 3 => 'AE/AF, No AE lock', + }, + }, + { + Name => 'AFAndMeteringButtons', + Condition => '$$self{Model} =~ /\b60D\b/', + Notes => '60D', + PrintConv => { + 0 => 'Metering start', + 1 => 'Metering + AF start', + 2 => 'AE lock', + 3 => 'AF stop', + 4 => 'No function', + }, + }, + { + Name => 'ShutterButtonAFOnButton', + Notes => 'other models', + PrintConv => { + 0 => 'Metering + AF start', + 1 => 'Metering + AF start/AF stop', + 2 => 'Metering start/Meter + AF start', + 3 => 'AE lock/Metering + AF start', + 4 => 'Metering + AF start/disable', + }, + }, + ], + 0x0702 => { + Name => 'AFOnAELockButtonSwitch', + PrintConv => \%disableEnable, + }, + 0x0703 => { + Name => 'QuickControlDialInMeter', + PrintConv => { + 0 => 'Exposure comp/Aperture', + 1 => 'AF point selection', + 2 => 'ISO speed', + 3 => 'AF point selection swapped with Exposure comp', #4 + 4 => 'ISO speed swapped with Exposure comp', #4 + }, + }, + 0x0704 => [ + { + Name => 'SetButtonWhenShooting', + Condition => '$$self{Model} =~ /\b(40D|50D|5D Mark II)\b/', + Notes => '40D, 50D and 5DmkII; value of 5 is new for 50D, and 6 is new for 5DmkII', + PrintConv => { + 0 => 'Normal (disabled)', + 1 => 'Image quality', + 2 => 'Picture style', + 3 => 'Menu display', + 4 => 'Image playback', + 5 => 'Quick control screen', #50D + 6 => 'Record movie (Live View)', #5DmkII + }, + }, + { + Name => 'SetButtonWhenShooting', + Condition => '$$self{Model} =~ /\b60D\b/', + Notes => '60D', + PrintConv => { + 0 => 'Normal (disabled)', + 1 => 'Image quality', + 2 => 'Picture style', + 3 => 'White balance', + 4 => 'Flash exposure compensation', + 5 => 'Viewfinder leveling gauge', + }, + }, + { + Name => 'SetButtonWhenShooting', + Condition => '$$self{Model} =~ /\b(450D|XSi|Kiss X2|550D|T2i|Kiss X4|600D|T3i|Kiss X5)\b/', + Notes => '450D, 550D and 600D; value of 5 is new for 550D', + PrintConv => { + 0 => 'Normal (disabled)', + 1 => 'Image quality', + 2 => 'Flash exposure compensation', + 3 => 'LCD monitor On/Off', + 4 => 'Menu display', + 5 => 'ISO speed', + }, + }, + { + Name => 'SetButtonWhenShooting', + Condition => '$$self{Model} =~ /\b(1100D|T3|Kiss X50)\b/', + Notes => '1100D', + PrintConv => { + 0 => 'Normal (disabled)', + 1 => 'Image quality', + 2 => 'Flash exposure compensation', + 3 => 'LCD monitor On/Off', + 4 => 'Menu display', + 5 => 'Depth-of-field preview', + }, + }, + { + Name => 'SetButtonWhenShooting', + Condition => '$$self{Model} =~ /\b(1000D|XS|Kiss F)\b/', + Notes => '1000D', + PrintConv => { + 0 => 'LCD monitor On/Off', + 1 => 'Image quality', + 2 => 'Flash exposure compensation', + 3 => 'Menu display', + 4 => 'Disabled', + }, + }, + { + Name => 'SetButtonWhenShooting', + Condition => '$$self{Model} =~ /\b(500D|T1i|Kiss X3)\b/', + Notes => '500D', + PrintConv => { + 0 => 'Quick control screen', + 1 => 'Image quality', + 2 => 'Flash exposure compensation', + 3 => 'LCD monitor On/Off', + 4 => 'Menu display', + 5 => 'Disabled', + }, + }, + { + Name => 'SetButtonWhenShooting', + Notes => '1DmkIII and 1DmkIV', + PrintConv => { + 0 => 'Normal (disabled)', + 1 => 'White balance', + 2 => 'Image size', + 3 => 'ISO speed', + 4 => 'Picture style', + 5 => 'Record func. + media/folder', + 6 => 'Menu display', + 7 => 'Image playback', + }, + }, + ], + 0x0705 => { + Name => 'ManualTv', + Description => 'Manual Tv/Av For M', + PrintConv => { + 0 => 'Tv=Main/Av=Control', + 1 => 'Tv=Control/Av=Main', + }, + }, + 0x0706 => { + Name => 'DialDirectionTvAv', + PrintConv => { + 0 => 'Normal', + 1 => 'Reversed', + }, + }, + 0x0707 => { + Name => 'AvSettingWithoutLens', + PrintConv => \%disableEnable, + }, + 0x0708 => { + Name => 'WBMediaImageSizeSetting', + PrintConv => { + 0 => 'Rear LCD panel', + 1 => 'LCD monitor', + 2 => 'Off (disable button)', # (1DX) + }, + }, + 0x0709 => { + Name => 'LockMicrophoneButton', + PrintConv => [{ + # called "sound" in 1DmkIII manual, and "memo" in 1DmkIV manual + 0 => 'Protect (hold:record memo)', + 1 => 'Record memo (protect:disable)', + 2 => 'Play memo (hold:record memo)', # new with 1DmkIV + 3 => 'Rating (protect/memo:disable)', # new with 1DX + }], + # (not sure what the 2nd number is -- new for 1DX. Seen a value of 31. + # Memo quality may be set to 48kHz or 8kHz through another option that + # doesn't seem to be stored separately -- is this it?) + }, + 0x070a => { + Name => 'ButtonFunctionControlOff', + PrintConv => { + 0 => 'Normal (enable)', + 1 => 'Disable main, Control, Multi-control', + }, + }, + 0x070b => { # 50D (also, 5DmkII writes this but it isn't in user guide) + Name => 'AssignFuncButton', + PrintConv => { + 0 => 'LCD brightness', + 1 => 'Image quality', + 2 => 'Exposure comp./AEB setting', + 3 => 'Image jump with main dial', + 4 => 'Live view function settings', + }, + }, + 0x070c => { # new for 7D + Name => 'CustomControls', + # (too much stuff to decode) + }, + 0x070d => { # new for 1DmkIV + Name => 'StartMovieShooting', + PrintConv => { + 0 => 'Default (from LV)', + 1 => 'Quick start (FEL button)', + }, + }, + 0x070e => { # new for 1100D + Name => 'FlashButtonFunction', + PrintConv => { + 0 => 'Raise built-in flash', + 1 => 'ISO speed', + }, + }, + 0x070f => { # new for 5DmkIII + Name => 'MultiFunctionLock', + PrintConv => [ + { #(NC) + 0 => 'Off', + 1 => 'On', # "On (main dial)" for 750D/760D? + 2 => 'On (quick control dial)', #(NC) + 3 => 'On (main dial and quick control dial)', #(NC) + }, + { BITMASK => { #(NC) + 0 => 'Main dial', + 1 => 'Quick control dial', + 2 => 'Multi-controller', + }}, + ], + }, + 0x0710 => { # (M) + Name => 'TrashButtonFunction', + PrintConv => { + 0 => 'Normal (set center AF point)', + 1 => 'Depth-of-field preview', + }, + }, + 0x0711 => { # (M) + Name => 'ShutterReleaseWithoutLens', + PrintConv => \%disableEnable, + }, + 0x0712 => { # (R) + Name => 'ControlRingRotation', + PrintConv => { + 0 => 'Normal', + 1 => 'Reversed', + }, + }, + 0x0713 => { # (R) + Name => 'FocusRingRotation', + PrintConv => { + 0 => 'Normal', + 1 => 'Reversed', + }, + }, + 0x0714 => { # (R) + Name => 'RFLensMFFocusRingSensitivity', + PrintConv => { + 0 => 'Varies With Rotation Speed', + 1 => 'Linked To Rotation Angle', + }, + }, + 0x0715 => { # (R) + Name => 'CustomizeDials', # (NC, may be CustomizeM-FnBar) + # (too much stuff to decode) + }, + #### 4b) Others + 0x080b => [ + { + Name => 'FocusingScreen', + Condition => '$$self{Model} =~ /\b(40D|50D|60D)\b/', + Notes => '40D, 50D and 60D', + PrintConv => { + 0 => 'Ef-A', + 1 => 'Ef-D', + 2 => 'Ef-S', + }, + }, + { + Name => 'FocusingScreen', + Condition => '$$self{Model} =~ /\b5D Mark II\b/', + Notes => '5D Mark II', + PrintConv => { + 0 => 'Eg-A', + 1 => 'Eg-D', + 2 => 'Eg-S', + }, + }, + { + Name => 'FocusingScreen', + Condition => '$$self{Model} =~ /\b6D\b/', + Notes => '6D', + PrintConv => { + 0 => 'Eg-A II', + 1 => 'Eg-D', + 2 => 'Eg-S', + }, + }, + { + Name => 'FocusingScreen', + Condition => '$$self{Model} =~ /\b7D Mark II\b/', + Notes => '7D Mark II', + PrintConv => { + 0 => 'Eh-A', + 1 => 'Eh-S', + }, + }, + { + Name => 'FocusingScreen', + Condition => '$$self{Model} =~ /\b1D X\b/', + Notes => '1DX', + PrintConv => { + 0 => 'Ec-CV', + 1 => 'Ec-A,B,D,H,I,L', + }, + }, + { + Name => 'FocusingScreen', + Notes => '1DmkIII, 1DSmkIII and 1DmkIV', + PrintConv => { + 0 => 'Ec-CIV', + 1 => 'Ec-A,B,C,CII,CIII,D,H,I,L', + 2 => 'Ec-S', + 3 => 'Ec-N,R', + }, + }, + ], + 0x080c => { + Name => 'TimerLength', + Count => 4, + PrintConv => [ + \%disableEnable, + '"6 s: $val"', + '"16 s: $val"', + '"After release: $val"', + ], + PrintConvInv => [ + undef, + '$val=~/(\d+)$/ ? $1 : 0', + '$val=~/(\d+)$/ ? $1 : 0', + '$val=~/(\d+)$/ ? $1 : 0', + ], + }, + 0x080d => { + Name => 'ShortReleaseTimeLag', + PrintConv => \%disableEnable, + }, + 0x080e => { + Name => 'AddAspectRatioInfo', + PrintConv => { + 0 => 'Off', + 1 => '6:6', + 2 => '3:4', + 3 => '4:5', + 4 => '6:7', + 5 => '10:12', + 6 => '5:7', + }, + }, + 0x080f => { + Name => 'AddOriginalDecisionData', # called ("image verification" in 1DmkIV manual) + PrintConv => \%offOn, + }, + 0x0810 => { + Name => 'LiveViewExposureSimulation', + PrintConv => { + 0 => 'Disable (LCD auto adjust)', + 1 => 'Enable (simulates exposure)', + }, + }, + 0x0811 => { + Name => 'LCDDisplayAtPowerOn', + PrintConv => { + 0 => 'Display', + 1 => 'Retain power off status', + }, + }, + 0x0812 => { # (1DX) + Name => 'MemoAudioQuality', + PrintConv => { + 0 => 'High (48 kHz)', + 1 => 'Low (8 kHz)', + }, + }, + 0x0813 => { # (5DmkIII) + Name => 'DefaultEraseOption', + PrintConv => { + 0 => 'Cancel selected', + 1 => 'Erase selected', + }, + }, + 0x0814 => { # (5DS) + Name => 'RetractLensOnPowerOff', + PrintConv => \%enableDisable, + }, + 0x0815 => { # (R) + Name => 'AddIPTCInformation', + PrintConv => \%disableEnable, + }, +); + +#------------------------------------------------------------------------------ +# Conversion routines +# Inputs: 0) value to convert +sub ConvertPfn($) +{ + my $val = shift; + return $val ? ($val==1 ? 'On' : "On ($val)") : "Off"; +} +sub ConvertPfnInv($) +{ + my $val = shift; + return $1 if $val =~ /(\d+)/; + return 1 if $val =~ /on/i; + return 0 if $val =~ /off/i; + return undef; +} + +#------------------------------------------------------------------------------ +# Read/Write Canon custom 2 directory (new for 1D Mark III) +# Inputs: 0) ExifTool object ref, 1) dirInfo ref, 2) tag table ref +# Returns: 1 on success +sub ProcessCanonCustom2($$$) +{ + my ($et, $dirInfo, $tagTablePtr) = @_; + my $dataPt = $$dirInfo{DataPt}; + my $offset = $$dirInfo{DirStart}; + my $size = $$dirInfo{DirLen}; + my $write = $$dirInfo{Write}; + my $verbose = $et->Options('Verbose'); + my $newTags; + + return 0 if $size < 2; + # first entry in array must be the size + my $len = Get16u($dataPt, $offset); + unless ($len == $size and $len >= 8) { + $et->Warn('Invalid CanonCustom2 data'); + return 0; + } + # get group count + my $count = Get32u($dataPt, $offset + 4); + if ($write) { + $newTags = $et->GetNewTagInfoHash($tagTablePtr); + $et->VPrint(0, " Rewriting CanonCustom2\n"); + } elsif ($verbose) { + $et->VerboseDir('CanonCustom2', $count, $len); + } + my $pos = $offset + 8; + my $end = $offset + $size; + # loop through group records + for (; $pos<$end; ) { + last if $pos + 12 > $end; + my $recNum = Get32u($dataPt, $pos); + my $recLen = Get32u($dataPt, $pos + 4); + my $recCount = Get32u($dataPt, $pos + 8); + last if $recLen < 8; # must be at least 8 bytes for recNum and recLen + $pos += 12; + my $recPos = $pos; + my $recEnd = $pos + $recLen - 8; + if ($recEnd > $end) { + $et->Warn('Corrupted CanonCustom2 group'); + return 0; + } + if ($verbose and not $write) { + $et->VerboseDir("CanonCustom2 group $recNum", $recCount, $recLen); + } + my ($i, $num, $tag); + for ($i=0; $recPos + 8 < $recEnd; ++$i, $recPos+=4*$num) { + $tag = Get32u($dataPt, $recPos); + $num = Get32u($dataPt, $recPos + 4); + $recPos += 8; + last if $recPos + $num * 4 > $recEnd; + my $val = ReadValue($dataPt, $recPos, 'int32s', $num, $num * 4); + if ($write) { + # write new value + my $tagInfo = $$newTags{$tag}; + next unless $$newTags{$tag}; + $tagInfo = $et->GetTagInfo($tagTablePtr, $tag, \$val, undef, $num) or next; + my $nvHash = $et->GetNewValueHash($tagInfo) or next; + next unless $et->IsOverwriting($nvHash, $val); + my $newVal = $et->GetNewValue($nvHash); + next unless defined $newVal; # can't delete from a custom table + WriteValue($newVal, 'int32s', $num, $dataPt, $recPos); + $et->VerboseValue("- CanonCustom:$$tagInfo{Name}", $val); + $et->VerboseValue("+ CanonCustom:$$tagInfo{Name}", $newVal); + ++$$et{CHANGED}; + } else { + # save extracted tag + my $oldInfo = $$tagTablePtr{$tag}; + $et->HandleTag($tagTablePtr, $tag, $val, + Index => $i, + Format => 'int32u', + Count => $num, + Size => $num * 4, + ); + my $tagInfo = $$tagTablePtr{$tag}; + # generate properly formatted description if we just added the tag + if ($tagInfo and not $oldInfo) { + ($$tagInfo{Description} = $$tagInfo{Name}) =~ tr/_/ /; + $$tagInfo{Description} =~ s/CanonCustom Functions/Canon Custom Functions /; + } + } + } + $pos = $recEnd; + } + if ($pos != $end) { + # Note: a firmware bug in the EOS M5 and M6 stores an incorrect + # size for the 2nd CanonCustom2 record, so this message is expected + # for these models... + $et->Warn('Possibly corrupted CanonCustom2 data'); + return 0; + } + return 1; +} + +#------------------------------------------------------------------------------ +# Write Canon custom 2 data +# Inputs: 0) ExifTool object reference, 1) dirInfo hash ref, 2) tag table ref +# Returns: New custom data block or undefined on error +sub WriteCanonCustom2($$$) +{ + my ($et, $dirInfo, $tagTablePtr) = @_; + $et or return 1; # allow dummy access to autoload this package + my $dataPt = $$dirInfo{DataPt}; + # edit a copy of the custom function 2 data + my $buff = substr($$dataPt, $$dirInfo{DirStart}, $$dirInfo{DirLen}); + my %dirInfo = ( + DataPt => \$buff, + DirStart => 0, + DirLen => $$dirInfo{DirLen}, + Write => 1, + ); + ProcessCanonCustom2($et, \%dirInfo, $tagTablePtr) or return undef; + return $buff; +} + +#------------------------------------------------------------------------------ +# Process Canon custom directory +# Inputs: 0) ExifTool object ref, 1) dirInfo ref, 2) tag table ref +# Returns: 1 on success +sub ProcessCanonCustom($$$) +{ + my ($et, $dirInfo, $tagTablePtr) = @_; + my $dataPt = $$dirInfo{DataPt}; + my $offset = $$dirInfo{DirStart}; + my $size = $$dirInfo{DirLen}; + my $verbose = $et->Options('Verbose'); + + # first entry in array must be the size + my $len = Get16u($dataPt,$offset); + unless ($len == $size or ($$et{Model}=~/\bD60\b/ and $len+2 == $size)) { + $et->Warn("Invalid CanonCustom data"); + return 0; + } + $verbose and $et->VerboseDir('CanonCustom', $size/2-1); + my $pos; + for ($pos=2; $pos<$size; $pos+=2) { + # ($pos is position within custom directory) + my $val = Get16u($dataPt,$offset+$pos); + my $tag = ($val >> 8); + $val = ($val & 0xff); + $et->HandleTag($tagTablePtr, $tag, $val, + Index => $pos/2-1, + Format => 'int8u', + Count => 1, + Size => 1, + ); + } + return 1; +} + +#------------------------------------------------------------------------------ +# Check new value for Canon custom data block +# Inputs: 0) ExifTool object reference, 1) tagInfo hash ref, 2) raw value ref +# Returns: error string or undef (and may modify value) on success +sub CheckCanonCustom($$$) +{ + my ($et, $tagInfo, $valPtr) = @_; + return Image::ExifTool::CheckValue($valPtr, 'int8u'); +} + +#------------------------------------------------------------------------------ +# Write Canon custom data +# Inputs: 0) ExifTool object reference, 1) dirInfo hash ref, 2) tag table ref +# Returns: New custom data block or undefined on error +sub WriteCanonCustom($$$) +{ + my ($et, $dirInfo, $tagTablePtr) = @_; + $et or return 1; # allow dummy access to autoload this package + my $dataPt = $$dirInfo{DataPt}; + my $dirStart = $$dirInfo{DirStart} || 0; + my $dirLen = $$dirInfo{DirLen} || length($$dataPt) - $dirStart; + my $dirName = $$dirInfo{DirName}; + my $newData = substr($$dataPt, $dirStart, $dirLen) or return undef; + $dataPt = \$newData; + + # first entry in array must be the size + my $len = Get16u($dataPt, 0); + unless ($len == $dirLen or ($$et{Model}=~/\bD60\b/ and $len+2 == $dirLen)) { + $et->Warn("Invalid CanonCustom data"); + return undef; + } + my $newTags = $et->GetNewTagInfoHash($tagTablePtr); + my $pos; + for ($pos=2; $pos<$dirLen; $pos+=2) { + my $val = Get16u($dataPt, $pos); + my $tag = ($val >> 8); + my $tagInfo = $$newTags{$tag}; + next unless $tagInfo; + my $nvHash = $et->GetNewValueHash($tagInfo); + $val = ($val & 0xff); + next unless $et->IsOverwriting($nvHash, $val); + my $newVal = $et->GetNewValue($nvHash); + next unless defined $newVal; # can't delete from a custom table + Set16u(($newVal & 0xff) + ($tag << 8), $dataPt, $pos); + $et->VerboseValue("- $dirName:$$tagInfo{Name}", $val); + $et->VerboseValue("+ $dirName:$$tagInfo{Name}", $newVal); + ++$$et{CHANGED}; + } + return $newData; +} + + +1; # end + +__END__ + +=head1 NAME + +Image::ExifTool::CanonCustom - Read and Write Canon custom functions + +=head1 SYNOPSIS + +This module is loaded automatically by Image::ExifTool when required. + +=head1 DESCRIPTION + +The Canon custom functions meta information is very specific to the +camera model, and is found in both the EXIF maker notes and in the +Canon RAW files. This module contains the definitions necessary for +Image::ExifTool to read this information. + +=head1 AUTHOR + +Copyright 2003-2019, Phil Harvey (phil at owl.phy.queensu.ca) + +This library is free software; you can redistribute it and/or modify it +under the same terms as Perl itself. + +=head1 REFERENCES + +=over 4 + +=item L<http://park2.wakwak.com/~tsuruzoh/Computer/Digicams/exif-e.html> + +=back + +=head1 ACKNOWLEDGEMENTS + +Thanks to Christian Koller for his work in decoding the 20D custom +functions, Rainer Honle for decoding the 5D custom functions and David +Pitcher for adding a few undocumented 1DmkIII settings. + +=head1 SEE ALSO + +L<Image::ExifTool::TagNames/Canon Tags>, +L<Image::ExifTool(3pm)|Image::ExifTool> + +=cut diff --git a/lib/Image/ExifTool/CanonRaw.pm b/lib/Image/ExifTool/CanonRaw.pm new file mode 100644 index 0000000..576f6ee --- /dev/null +++ b/lib/Image/ExifTool/CanonRaw.pm @@ -0,0 +1,910 @@ +#------------------------------------------------------------------------------ +# File: CanonRaw.pm +# +# Description: Read Canon RAW (CRW) meta information +# +# Revisions: 11/25/2003 - P. Harvey Created +# 12/02/2003 - P. Harvey Completely reworked and figured out many +# more tags +# +# References: 1) http://www.cybercom.net/~dcoffin/dcraw/ +# 2) http://www.wonderland.org/crw/ +# 3) http://xyrion.org/ciff/CIFFspecV1R04.pdf +# 4) Dave Nicholson private communication (PowerShot S30) +#------------------------------------------------------------------------------ + +package Image::ExifTool::CanonRaw; + +use strict; +use vars qw($VERSION $AUTOLOAD %crwTagFormat); +use Image::ExifTool qw(:DataAccess :Utils); +use Image::ExifTool::Exif; +use Image::ExifTool::Canon; + +$VERSION = '1.58'; + +sub WriteCRW($$); +sub ProcessCanonRaw($$$); +sub WriteCanonRaw($$$); +sub CheckCanonRaw($$$); +sub InitMakerNotes($); +sub SaveMakerNotes($); +sub BuildMakerNotes($$$$$$); + +# formats for CRW tag types (($tag >> 8) & 0x38) +# Note: don't define format for undefined types +%crwTagFormat = ( + 0x00 => 'int8u', + 0x08 => 'string', + 0x10 => 'int16u', + 0x18 => 'int32u', + # 0x20 => 'undef', + # 0x28 => 'undef', + # 0x30 => 'undef', +); + +# Canon raw file tag table +# Note: Tag ID's have upper 2 bits set to zero, since these 2 bits +# just specify the location of the information +%Image::ExifTool::CanonRaw::Main = ( + GROUPS => { 0 => 'MakerNotes', 2 => 'Camera' }, + PROCESS_PROC => \&ProcessCanonRaw, + WRITE_PROC => \&WriteCanonRaw, + CHECK_PROC => \&CheckCanonRaw, + WRITABLE => 1, + 0x0000 => { Name => 'NullRecord', Writable => 'undef' }, #3 + 0x0001 => { #3 + Name => 'FreeBytes', + Format => 'undef', + Binary => 1, + }, + 0x0032 => { Name => 'CanonColorInfo1', Writable => 0 }, + 0x0805 => [ + # this tag is found in more than one directory... + { + Condition => '$self->{DIR_NAME} eq "ImageDescription"', + Name => 'CanonFileDescription', + Writable => 'string[32]', + }, + { + Name => 'UserComment', + Writable => 'string[256]', + }, + ], + 0x080a => { + Name => 'CanonRawMakeModel', + Writable => 0, + SubDirectory => { TagTable => 'Image::ExifTool::CanonRaw::MakeModel' }, + }, + 0x080b => { Name => 'CanonFirmwareVersion', Writable => 'string[32]' }, + 0x080c => { Name => 'ComponentVersion', Writable => 'string' }, #3 + 0x080d => { Name => 'ROMOperationMode', Writable => 'string[8]' }, #3 + 0x0810 => { Name => 'OwnerName', Writable => 'string[32]' }, + 0x0815 => { Name => 'CanonImageType', Writable => 'string[32]' }, + 0x0816 => { Name => 'OriginalFileName', Writable => 'string[32]' }, + 0x0817 => { Name => 'ThumbnailFileName', Writable => 'string[32]' }, + 0x100a => { #3 + Name => 'TargetImageType', + Writable => 'int16u', + PrintConv => { + 0 => 'Real-world Subject', + 1 => 'Written Document', + }, + }, + 0x1010 => { #3 + Name => 'ShutterReleaseMethod', + Writable => 'int16u', + PrintConv => { + 0 => 'Single Shot', + 2 => 'Continuous Shooting', + }, + }, + 0x1011 => { #3 + Name => 'ShutterReleaseTiming', + Writable => 'int16u', + PrintConv => { + 0 => 'Priority on shutter', + 1 => 'Priority on focus', + }, + }, + 0x1016 => { Name => 'ReleaseSetting', Writable => 'int16u' }, #3 + 0x101c => { Name => 'BaseISO', Writable => 'int16u' }, #3 + 0x1028=> { #PH + Name => 'CanonFlashInfo', + Writable => 'int16u', + Count => 4, + Unknown => 1, + }, + 0x1029 => { + Name => 'CanonFocalLength', + Writable => 0, + SubDirectory => { TagTable => 'Image::ExifTool::Canon::FocalLength' }, + }, + 0x102a => { + Name => 'CanonShotInfo', + Writable => 0, + SubDirectory => { TagTable => 'Image::ExifTool::Canon::ShotInfo' }, + }, + 0x102c => { + Name => 'CanonColorInfo2', + Writable => 0, + # for the S30, the following information has been decoded: (ref 4) + # offset 66: int32u - shutter half press time in ms + # offset 70: int32u - image capture time in ms + # offset 74: int16u - custom white balance flag (0=Off, 512=On) + }, + 0x102d => { + Name => 'CanonCameraSettings', + Writable => 0, + SubDirectory => { TagTable => 'Image::ExifTool::Canon::CameraSettings' }, + }, + 0x1030 => { #4 + Name => 'WhiteSample', + Writable => 0, + SubDirectory => { + Validate => 'Image::ExifTool::Canon::Validate($dirData,$subdirStart,$size)', + TagTable => 'Image::ExifTool::CanonRaw::WhiteSample', + }, + }, + 0x1031 => { + Name => 'SensorInfo', + Writable => 0, + SubDirectory => { TagTable => 'Image::ExifTool::Canon::SensorInfo' }, + }, + # this tag has only be verified for the 10D in CRW files, but the D30 and D60 + # also produce CRW images and have CustomFunction information in their JPEG's + 0x1033 => [ + { + Name => 'CustomFunctions10D', + Condition => '$self->{Model} =~ /EOS 10D/', + SubDirectory => { + Validate => 'Image::ExifTool::Canon::Validate($dirData,$subdirStart,$size)', + TagTable => 'Image::ExifTool::CanonCustom::Functions10D', + }, + }, + { + Name => 'CustomFunctionsD30', + Condition => '$self->{Model} =~ /EOS D30\b/', + SubDirectory => { + Validate => 'Image::ExifTool::Canon::Validate($dirData,$subdirStart,$size)', + TagTable => 'Image::ExifTool::CanonCustom::FunctionsD30', + }, + }, + { + Name => 'CustomFunctionsD60', + Condition => '$self->{Model} =~ /EOS D60\b/', + SubDirectory => { + # the stored size in the D60 apparently doesn't include the size word: + Validate => 'Image::ExifTool::Canon::Validate($dirData,$subdirStart,$size-2,$size)', + # (D60 custom functions are basically the same as D30) + TagTable => 'Image::ExifTool::CanonCustom::FunctionsD30', + }, + }, + { + Name => 'CustomFunctionsUnknown', + SubDirectory => { + Validate => 'Image::ExifTool::Canon::Validate($dirData,$subdirStart,$size)', + TagTable => 'Image::ExifTool::CanonCustom::FuncsUnknown', + }, + }, + ], + 0x1038 => { + Name => 'CanonAFInfo', + Writable => 0, + SubDirectory => { TagTable => 'Image::ExifTool::Canon::AFInfo' }, + }, + 0x1093 => { + Name => 'CanonFileInfo', + SubDirectory => { + Validate => 'Image::ExifTool::Canon::Validate($dirData,$subdirStart,$size)', + TagTable => 'Image::ExifTool::Canon::FileInfo', + }, + }, + 0x10a9 => { + Name => 'ColorBalance', + Writable => 0, + SubDirectory => { TagTable => 'Image::ExifTool::Canon::ColorBalance' }, + }, + 0x10b5 => { #PH + Name => 'RawJpgInfo', + SubDirectory => { + Validate => 'Image::ExifTool::Canon::Validate($dirData,$subdirStart,$size)', + TagTable => 'Image::ExifTool::CanonRaw::RawJpgInfo', + }, + }, + 0x10ae => { + Name => 'ColorTemperature', + Writable => 'int16u', + }, + 0x10b4 => { + Name => 'ColorSpace', + Writable => 'int16u', + PrintConv => { + 1 => 'sRGB', + 2 => 'Adobe RGB', + 0xffff => 'Uncalibrated', + }, + }, + 0x1803 => { #3 + Name => 'ImageFormat', + Writable => 0, + SubDirectory => { TagTable => 'Image::ExifTool::CanonRaw::ImageFormat' }, + }, + 0x1804 => { Name => 'RecordID', Writable => 'int32u' }, #3 + 0x1806 => { #3 + Name => 'SelfTimerTime', + Writable => 'int32u', + ValueConv => '$val / 1000', + ValueConvInv => '$val * 1000', + PrintConv => '"$val s"', + PrintConvInv => '$val=~s/\s*s.*//;$val', + }, + 0x1807 => { + Name => 'TargetDistanceSetting', + Format => 'float', + PrintConv => '"$val mm"', + PrintConvInv => '$val=~s/\s*mm$//;$val', + }, + 0x180b => [ + { + # D30 + Name => 'SerialNumber', + Condition => '$$self{Model} =~ /EOS D30\b/', + Writable => 'int32u', + PrintConv => 'sprintf("%x-%.5d",$val>>16,$val&0xffff)', + PrintConvInv => '$val=~/(.*)-(\d+)/ ? (hex($1)<<16)+$2 : undef', + }, + { + # all EOS models (D30, 10D, 300D) + Name => 'SerialNumber', + Condition => '$$self{Model} =~ /EOS/', + Writable => 'int32u', + PrintConv => 'sprintf("%.10d",$val)', + PrintConvInv => '$val', + }, + { + # this is not SerialNumber for PowerShot models (but what is it?) - PH + Name => 'UnknownNumber', + Unknown => 1, + }, + ], + 0x180e => { + Name => 'TimeStamp', + Writable => 0, + SubDirectory => { + TagTable => 'Image::ExifTool::CanonRaw::TimeStamp', + }, + }, + 0x1810 => { + Name => 'ImageInfo', + Writable => 0, + SubDirectory => { + TagTable => 'Image::ExifTool::CanonRaw::ImageInfo', + }, + }, + 0x1813 => { #3 + Name => 'FlashInfo', + Writable => 0, + SubDirectory => { + TagTable => 'Image::ExifTool::CanonRaw::FlashInfo', + }, + }, + 0x1814 => { #3 + Name => 'MeasuredEV', + Notes => q{ + this is the Canon name for what could better be called MeasuredLV, and + should be close to the calculated LightValue for a proper exposure with most + models + }, + Format => 'float', + ValueConv => '$val + 5', + ValueConvInv => '$val - 5', + }, + 0x1817 => { + Name => 'FileNumber', + Writable => 'int32u', + Groups => { 2 => 'Image' }, + PrintConv => '$_=$val;s/(\d+)(\d{4})/$1-$2/;$_', + PrintConvInv => '$_=$val;s/-//;$_', + }, + 0x1818 => { #3 + Name => 'ExposureInfo', + Groups => { 1 => 'CIFF' }, # (only so CIFF shows up in group lists) + Writable => 0, + SubDirectory => { TagTable => 'Image::ExifTool::CanonRaw::ExposureInfo' }, + }, + 0x1834 => { #PH + Name => 'CanonModelID', + Writable => 'int32u', + PrintHex => 1, + Notes => q{ + this is the complete list of model ID numbers, but note that many of these + models do not produce CRW images + }, + SeparateTable => 'Canon CanonModelID', + PrintConv => \%Image::ExifTool::Canon::canonModelID, + }, + 0x1835 => { + Name => 'DecoderTable', + Writable => 0, + SubDirectory => { TagTable => 'Image::ExifTool::CanonRaw::DecoderTable' }, + }, + 0x183b => { #PH + # display format for serial number + Name => 'SerialNumberFormat', + Writable => 'int32u', + PrintHex => 1, + PrintConv => { + 0x90000000 => 'Format 1', + 0xa0000000 => 'Format 2', + }, + }, + 0x2005 => { + Name => 'RawData', + Writable => 0, + Binary => 1, + }, + 0x2007 => { + Name => 'JpgFromRaw', + Groups => { 2 => 'Preview' }, + Writable => 'resize', # 'resize' allows this value to change size + Permanent => 0, + RawConv => '$self->ValidateImage(\$val,$tag)', + }, + 0x2008 => { + Name => 'ThumbnailImage', + Groups => { 2 => 'Preview' }, + Writable => 'resize', # 'resize' allows this value to change size + WriteCheck => '$self->CheckImage(\$val)', + Permanent => 0, + RawConv => '$self->ValidateImage(\$val,$tag)', + }, + # the following entries are subdirectories + # (any 0x28 and 0x30 tag types are handled automatically by the decoding logic) + 0x2804 => { + Name => 'ImageDescription', + SubDirectory => { }, + Writable => 0, + }, + 0x2807 => { #3 + Name => 'CameraObject', + SubDirectory => { }, + Writable => 0, + }, + 0x3002 => { #3 + Name => 'ShootingRecord', + SubDirectory => { }, + Writable => 0, + }, + 0x3003 => { #3 + Name => 'MeasuredInfo', + SubDirectory => { }, + Writable => 0, + }, + 0x3004 => { #3 + Name => 'CameraSpecification', + SubDirectory => { }, + Writable => 0, + }, + 0x300a => { #3 + Name => 'ImageProps', + SubDirectory => { }, + Writable => 0, + }, + 0x300b => { + Name => 'ExifInformation', + SubDirectory => { }, + Writable => 0, + }, +); + +# Canon binary data blocks +%Image::ExifTool::CanonRaw::MakeModel = ( + PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData, + WRITE_PROC => \&Image::ExifTool::WriteBinaryData, + CHECK_PROC => \&Image::ExifTool::CheckBinaryData, + DATAMEMBER => [ 0, 6 ], # indices of data members to extract when writing + WRITABLE => 1, + FORMAT => 'string', + GROUPS => { 0 => 'MakerNotes', 2 => 'Camera' }, + # (can't specify a first entry because this isn't + # a simple binary table with fixed offsets) + 0 => { + Name => 'Make', + Format => 'string[6]', # "Canon\0" + DataMember => 'Make', + RawConv => '$self->{Make} = $val', + }, + 6 => { + Name => 'Model', + Format => 'string', # no size = to the end of the data + Description => 'Camera Model Name', + DataMember => 'Model', + RawConv => '$self->{Model} = $val', + }, +); + +%Image::ExifTool::CanonRaw::TimeStamp = ( + PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData, + WRITE_PROC => \&Image::ExifTool::WriteBinaryData, + CHECK_PROC => \&Image::ExifTool::CheckBinaryData, + WRITABLE => 1, + FORMAT => 'int32u', + FIRST_ENTRY => 0, + GROUPS => { 0 => 'MakerNotes', 2 => 'Time' }, + 0 => { + Name => 'DateTimeOriginal', + Description => 'Date/Time Original', + Shift => 'Time', + ValueConv => 'ConvertUnixTime($val)', + ValueConvInv => 'GetUnixTime($val)', + PrintConv => '$self->ConvertDateTime($val)', + PrintConvInv => '$self->InverseDateTime($val)', + }, + 1 => { #3 + Name => 'TimeZoneCode', + Format => 'int32s', + ValueConv => '$val / 3600', + ValueConvInv => '$val * 3600', + }, + 2 => { #3 + Name => 'TimeZoneInfo', + Notes => 'set to 0x80000000 if TimeZoneCode is valid', + }, +); + +%Image::ExifTool::CanonRaw::ImageFormat = ( + PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData, + WRITE_PROC => \&Image::ExifTool::WriteBinaryData, + CHECK_PROC => \&Image::ExifTool::CheckBinaryData, + WRITABLE => 1, + FORMAT => 'int32u', + FIRST_ENTRY => 0, + GROUPS => { 0 => 'MakerNotes', 2 => 'Image' }, + 0 => { + Name => 'FileFormat', + Flags => 'PrintHex', + PrintConv => { + 0x00010000 => 'JPEG (lossy)', + 0x00010002 => 'JPEG (non-quantization)', + 0x00010003 => 'JPEG (lossy/non-quantization toggled)', + 0x00020001 => 'CRW', + }, + }, + 1 => { + Name => 'TargetCompressionRatio', + Format => 'float', + }, +); + +%Image::ExifTool::CanonRaw::RawJpgInfo = ( + PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData, + WRITE_PROC => \&Image::ExifTool::WriteBinaryData, + CHECK_PROC => \&Image::ExifTool::CheckBinaryData, + WRITABLE => 1, + FORMAT => 'int16u', + FIRST_ENTRY => 1, + GROUPS => { 0 => 'MakerNotes', 2 => 'Image' }, +# 0 => 'RawJpgInfoSize', + 1 => { #PH + Name => 'RawJpgQuality', + PrintConv => { + 1 => 'Economy', + 2 => 'Normal', + 3 => 'Fine', + 5 => 'Superfine', + }, + }, + 2 => { #PH + Name => 'RawJpgSize', + PrintConv => { + 0 => 'Large', + 1 => 'Medium', + 2 => 'Small', + }, + }, + 3 => 'RawJpgWidth', #PH + 4 => 'RawJpgHeight', #PH +); + +%Image::ExifTool::CanonRaw::FlashInfo = ( + PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData, + WRITE_PROC => \&Image::ExifTool::WriteBinaryData, + CHECK_PROC => \&Image::ExifTool::CheckBinaryData, + WRITABLE => 1, + FORMAT => 'float', + FIRST_ENTRY => 0, + GROUPS => { 0 => 'MakerNotes', 2 => 'Image' }, + 0 => 'FlashGuideNumber', + 1 => 'FlashThreshold', +); + +%Image::ExifTool::CanonRaw::ExposureInfo = ( + PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData, + WRITE_PROC => \&Image::ExifTool::WriteBinaryData, + CHECK_PROC => \&Image::ExifTool::CheckBinaryData, + WRITABLE => 1, + FORMAT => 'float', + FIRST_ENTRY => 0, + GROUPS => { 0 => 'MakerNotes', 2 => 'Image' }, + 0 => 'ExposureCompensation', + 1 => { + Name => 'ShutterSpeedValue', + ValueConv => 'abs($val)<100 ? 1/(2**$val) : 0', + ValueConvInv => '$val>0 ? -log($val)/log(2) : -100', + PrintConv => 'Image::ExifTool::Exif::PrintExposureTime($val)', + PrintConvInv => 'Image::ExifTool::Exif::ConvertFraction($val)', + }, + 2 => { + Name => 'ApertureValue', + ValueConv => '2 ** ($val / 2)', + ValueConvInv => '$val>0 ? 2*log($val)/log(2) : 0', + PrintConv => 'sprintf("%.1f",$val)', + PrintConvInv => '$val', + }, +); + +%Image::ExifTool::CanonRaw::ImageInfo = ( + PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData, + WRITE_PROC => \&Image::ExifTool::WriteBinaryData, + CHECK_PROC => \&Image::ExifTool::CheckBinaryData, + FORMAT => 'int32u', + FIRST_ENTRY => 0, + GROUPS => { 0 => 'MakerNotes', 2 => 'Image' }, + # Note: Don't make these writable (except rotation) because it confuses + # Canon decoding software if the are changed + 0 => 'ImageWidth', #3 + 1 => 'ImageHeight', #3 + 2 => { #3 + Name => 'PixelAspectRatio', + Format => 'float', + }, + 3 => { + Name => 'Rotation', + Format => 'int32s', + Writable => 'int32s', + }, + 4 => 'ComponentBitDepth', #3 + 5 => 'ColorBitDepth', #3 + 6 => 'ColorBW', #3 +); + +# ref 4 +%Image::ExifTool::CanonRaw::DecoderTable = ( + PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData, + WRITE_PROC => \&Image::ExifTool::WriteBinaryData, + CHECK_PROC => \&Image::ExifTool::CheckBinaryData, + GROUPS => { 0 => 'MakerNotes', 2 => 'Camera' }, + FORMAT => 'int32u', + FIRST_ENTRY => 0, + 0 => 'DecoderTableNumber', + 2 => 'CompressedDataOffset', + 3 => 'CompressedDataLength', +); + +# ref 1/4 +%Image::ExifTool::CanonRaw::WhiteSample = ( + PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData, + WRITE_PROC => \&Image::ExifTool::WriteBinaryData, + CHECK_PROC => \&Image::ExifTool::CheckBinaryData, + GROUPS => { 0 => 'MakerNotes', 2 => 'Camera' }, + FORMAT => 'int16u', + FIRST_ENTRY => 1, + 1 => 'WhiteSampleWidth', + 2 => 'WhiteSampleHeight', + 3 => 'WhiteSampleLeftBorder', + 4 => 'WhiteSampleTopBorder', + 5 => 'WhiteSampleBits', + # this is followed by the encrypted white sample values (ref 1) +); + +#------------------------------------------------------------------------------ +# AutoLoad our writer routines when necessary +# +sub AUTOLOAD +{ + return Image::ExifTool::DoAutoLoad($AUTOLOAD, @_); +} + +#------------------------------------------------------------------------------ +# Process Raw file directory +# Inputs: 0) ExifTool object reference +# 1) directory information reference, 2) tag table reference +# Returns: 1 on success +sub ProcessCanonRaw($$$) +{ + my ($et, $dirInfo, $rawTagTable) = @_; + my $blockStart = $$dirInfo{DirStart}; + my $blockSize = $$dirInfo{DirLen}; + my $raf = $$dirInfo{RAF} or return 0; + my $buff; + my $verbose = $et->Options('Verbose'); + my $buildMakerNotes = $et->Options('MakerNotes'); + + # 4 bytes at end of block give directory position within block + $raf->Seek($blockStart+$blockSize-4, 0) or return 0; + $raf->Read($buff, 4) == 4 or return 0; + my $dirOffset = Get32u(\$buff,0) + $blockStart; + $raf->Seek($dirOffset, 0) or return 0; + $raf->Read($buff, 2) == 2 or return 0; + my $entries = Get16u(\$buff,0); # get number of entries in directory + # read the directory (10 bytes per entry) + $raf->Read($buff, 10 * $entries) == 10 * $entries or return 0; + + $verbose and $et->VerboseDir('CIFF', $entries); + my $index; + for ($index=0; $index<$entries; ++$index) { + my $pt = 10 * $index; + my $tag = Get16u(\$buff, $pt); + my $size = Get32u(\$buff, $pt+2); + my $valuePtr = Get32u(\$buff, $pt+6); + my $ptr = $valuePtr + $blockStart; # all pointers relative to block start + if ($tag & 0x8000) { + $et->Warn('Bad CRW directory entry'); + return 1; + } + my $tagID = $tag & 0x3fff; # get tag ID + my $tagType = ($tag >> 8) & 0x38; # get tag type + my $valueInDir = ($tag & 0x4000); # flag for value in directory + my $tagInfo = $et->GetTagInfo($rawTagTable, $tagID); + if (($tagType==0x28 or $tagType==0x30) and not $valueInDir) { + # this type of tag specifies a raw subdirectory + my $name; + $tagInfo and $name = $$tagInfo{Name}; + $name or $name = sprintf("CanonRaw_0x%.4x", $tag); + my %subdirInfo = ( + DirName => $name, + DataLen => 0, + DirStart => $ptr, + DirLen => $size, + Nesting => $$dirInfo{Nesting} + 1, + RAF => $raf, + Parent => $$dirInfo{DirName}, + ); + if ($verbose) { + my $fakeInfo = { Name => $name, SubDirectory => { } }; + $et->VerboseInfo($tagID, $fakeInfo, + 'Index' => $index, + 'Size' => $size, + 'Start' => $ptr, + ); + } + $et->ProcessDirectory(\%subdirInfo, $rawTagTable); + next; + } + my ($valueDataPos, $count, $subdir); + my $format = $crwTagFormat{$tagType}; + if ($tagInfo) { + $subdir = $$tagInfo{SubDirectory}; + $format = $$tagInfo{Format} if $$tagInfo{Format}; + $count = $$tagInfo{Count}; + } + # get value data + my ($value, $delRawConv); + if ($valueInDir) { # is the value data in the directory? + # this type of tag stores the value in the 'size' and 'ptr' fields + $valueDataPos = $dirOffset + $pt + 4; + $size = 8; + $value = substr($buff, $pt+2, $size); + # set count to 1 by default for normal values in directory + $count = 1 if not defined $count and $format and + $format ne 'string' and not $subdir; + } else { + $valueDataPos = $ptr; + if ($size <= 512 or ($verbose > 2 and $size <= 65536) + or ($tagInfo and ($$tagInfo{SubDirectory} + or grep(/^$$tagInfo{Name}$/i, $et->GetRequestedTags()) ))) + { + # read value if size is small or specifically requested + # or if this is a SubDirectory + unless ($raf->Seek($ptr, 0) and $raf->Read($value, $size) == $size) { + $et->Warn(sprintf("Error reading %d bytes from 0x%x",$size,$ptr)); + next; + } + } else { + $value = "Binary data $size bytes"; + if ($tagInfo) { + if ($et->Options('Binary') or $verbose) { + # read the value anyway + unless ($raf->Seek($ptr, 0) and $raf->Read($value, $size) == $size) { + $et->Warn(sprintf("Error reading %d bytes from 0x%x",$size,$ptr)); + next; + } + } + # force this to be a binary (scalar reference) + $$tagInfo{RawConv} = '\$val'; + $delRawConv = 1; + } + $size = length $value; + undef $format; + } + } + # set count from tagInfo count if necessary + if ($format and not $count) { + # set count according to format and size + my $fnum = $Image::ExifTool::Exif::formatNumber{$format}; + my $fsiz = $Image::ExifTool::Exif::formatSize[$fnum]; + $count = int($size / $fsiz); + } + if ($verbose) { + my $val = $value; + $format and $val = ReadValue(\$val, 0, $format, $count, $size); + $et->VerboseInfo($tagID, $tagInfo, + Table => $rawTagTable, + Index => $index, + Value => $val, + DataPt => \$value, + DataPos => $valueDataPos, + Size => $size, + Format => $format, + Count => $count, + ); + } + if ($buildMakerNotes) { + # build maker notes information if requested + BuildMakerNotes($et, $tagID, $tagInfo, \$value, $format, $count); + } + next unless defined $tagInfo; + + if ($subdir) { + my $name = $$tagInfo{Name}; + my $newTagTable; + if ($$subdir{TagTable}) { + $newTagTable = GetTagTable($$subdir{TagTable}); + unless ($newTagTable) { + warn "Unknown tag table $$subdir{TagTable}\n"; + next; + } + } else { + warn "Must specify TagTable for SubDirectory $name\n"; + next; + } + my $subdirStart = 0; + #### eval Start () + $subdirStart = eval $$subdir{Start} if $$subdir{Start}; + my $dirData = \$value; + my %subdirInfo = ( + Name => $name, + DataPt => $dirData, + DataLen => $size, + DataPos => $valueDataPos, + DirStart => $subdirStart, + DirLen => $size - $subdirStart, + Nesting => $$dirInfo{Nesting} + 1, + RAF => $raf, + DirName => $name, + Parent => $$dirInfo{DirName}, + ); + #### eval Validate ($dirData, $subdirStart, $size) + if (defined $$subdir{Validate} and not eval $$subdir{Validate}) { + $et->Warn("Invalid $name data"); + } else { + $et->ProcessDirectory(\%subdirInfo, $newTagTable, $$subdir{ProcessProc}); + } + } else { + # convert to specified format if necessary + $format and $value = ReadValue(\$value, 0, $format, $count, $size); + # save the information + $et->FoundTag($tagInfo, $value); + delete $$tagInfo{RawConv} if $delRawConv; + } + } + return 1; +} + +#------------------------------------------------------------------------------ +# get information from raw file +# Inputs: 0) ExifTool object reference, 1) dirInfo reference +# Returns: 1 if this was a valid Canon RAW file +sub ProcessCRW($$) +{ + my ($et, $dirInfo) = @_; + my ($buff, $sig); + my $raf = $$dirInfo{RAF}; + my $buildMakerNotes = $et->Options('MakerNotes'); + + $raf->Read($buff,2) == 2 or return 0; + SetByteOrder($buff) or return 0; + $raf->Read($buff,4) == 4 or return 0; + $raf->Read($sig,8) == 8 or return 0; # get file signature + $sig =~ /^HEAP(CCDR|JPGM)/ or return 0; # validate signature + my $hlen = Get32u(\$buff, 0); + + $raf->Seek(0, 2) or return 0; # seek to end of file + my $filesize = $raf->Tell() or return 0; + + # initialize maker note data if building maker notes + $buildMakerNotes and InitMakerNotes($et); + + # set the FileType tag unless already done (eg. APP0 CIFF record in JPEG image) + $et->SetFileType(); + + # build directory information for main raw directory + my %dirInfo = ( + DataLen => 0, + DirStart => $hlen, + DirLen => $filesize - $hlen, + Nesting => 0, + RAF => $raf, + Parent => 'CRW', + ); + + # process the raw directory + my $rawTagTable = GetTagTable('Image::ExifTool::CanonRaw::Main'); + my $oldIndent = $$et{INDENT}; + $$et{INDENT} .= '| '; + unless (ProcessCanonRaw($et, \%dirInfo, $rawTagTable)) { + $et->Warn('CRW file format error'); + } + $$et{INDENT} = $oldIndent; + + # finish building maker notes if necessary + $buildMakerNotes and SaveMakerNotes($et); + + # process trailers if they exist in CRW file (not in CIFF information!) + if ($$et{FILE_TYPE} eq 'CRW') { + my $trailInfo = Image::ExifTool::IdentifyTrailer($raf); + $et->ProcessTrailers($trailInfo) if $trailInfo; + } + + return 1; +} + +1; # end + +__END__ + +=head1 NAME + +Image::ExifTool::CanonRaw - Read Canon RAW (CRW) meta information + +=head1 SYNOPSIS + +This module is loaded automatically by Image::ExifTool when required. + +=head1 DESCRIPTION + +This module contains definitions required by Image::ExifTool to interpret +meta information from Canon CRW raw files. These files are written directly +by some Canon cameras, and contain meta information similar to that found in +the EXIF Canon maker notes. + +=head1 NOTES + +The CR2 format written by some Canon cameras is very different the CRW +format processed by this module. (CR2 is TIFF-based and uses standard EXIF +tags.) + +=head1 AUTHOR + +Copyright 2003-2019, Phil Harvey (phil at owl.phy.queensu.ca) + +This library is free software; you can redistribute it and/or modify it +under the same terms as Perl itself. + +=head1 REFERENCES + +=over 4 + +=item L<http://www.cybercom.net/~dcoffin/dcraw/> + +=item L<http://www.wonderland.org/crw/> + +=item L<http://xyrion.org/ciff/> + +=item L<http://owl.phy.queensu.ca/~phil/exiftool/canon_raw.html> + +=back + +=head1 ACKNOWLEDGEMENTS + +Thanks to Dave Nicholson for decoding a number of new tags. + +=head1 SEE ALSO + +L<Image::ExifTool::TagNames/CanonRaw Tags>, +L<Image::ExifTool::Canon(3pm)|Image::ExifTool::Canon>, +L<Image::ExifTool(3pm)|Image::ExifTool> + +=cut + diff --git a/lib/Image/ExifTool/CanonVRD.pm b/lib/Image/ExifTool/CanonVRD.pm new file mode 100644 index 0000000..2ba2f64 --- /dev/null +++ b/lib/Image/ExifTool/CanonVRD.pm @@ -0,0 +1,2260 @@ +#------------------------------------------------------------------------------ +# File: CanonVRD.pm +# +# Description: Read/write Canon VRD and DR4 information +# +# Revisions: 2006/10/30 - P. Harvey Created +# 2007/10/23 - PH Added new VRD 3.0 tags +# 2008/08/29 - PH Added new VRD 3.4 tags +# 2008/12/02 - PH Added new VRD 3.5 tags +# 2010/06/18 - PH Support variable-length CustomPictureStyle data +# 2010/09/14 - PH Added r/w support for XMP in VRD +# 2015/05/16 - PH Added DR4 support (DPP 4.1.50.0) +# 2018/03/13 - PH Update to DPP 4.8.20 +# +# References: 1) Bogdan private communication (Canon DPP v3.4.1.1) +# 2) Gert Kello private communiation (DPP 3.8) +#------------------------------------------------------------------------------ + +package Image::ExifTool::CanonVRD; + +use strict; +use vars qw($VERSION); +use Image::ExifTool qw(:DataAccess :Utils); +use Image::ExifTool::Canon; + +$VERSION = '1.32'; + +sub ProcessCanonVRD($$;$); +sub WriteCanonVRD($$;$); +sub ProcessEditData($$$); +sub ProcessIHL($$$); +sub ProcessIHLExif($$$); +sub ProcessDR4($$;$); +sub SortDR4($$); + +# map for adding directories to VRD +my %vrdMap = ( + XMP => 'CanonVRD', + CanonVRD => 'VRD', +); + +my %noYes = ( + PrintConvColumns => 2, + PrintConv => { 0 => 'No', 1 => 'Yes' }, +); + +# DR4 format codes +my %vrdFormat = ( + 1 => 'int32u', + 2 => 'string', + 8 => 'int32u', + 9 => 'int32s', + 13 => 'double', + 33 => 'int32u', # (array) + 38 => 'double', # (array) + # 254 => 'undef', ? + 255 => 'undef', +); + +# empty VRD header/footer for creating VRD from scratch +my $blankHeader = "CANON OPTIONAL DATA\0\0\x01\0\0\0\0\0\0"; +my $blankFooter = "CANON OPTIONAL DATA\0" . ("\0" x 42) . "\xff\xd9"; + +# main tag table blocks in CanonVRD trailer (ref PH) +%Image::ExifTool::CanonVRD::Main = ( + WRITE_PROC => \&WriteCanonVRD, + PROCESS_PROC => \&ProcessCanonVRD, + NOTES => q{ + Canon Digital Photo Professional writes VRD (Recipe Data) information as a + trailer record to JPEG, TIFF, CRW and CR2 images, or as stand-alone VRD or + DR4 files. The tags listed below represent information found in these + records. The complete VRD/DR4 data record may be accessed as a block using + the Extra 'CanonVRD' or 'CanonDR4' tag, but this tag is not extracted or + copied unless specified explicitly. + }, + 0xffff00f4 => { + Name => 'EditData', + SubDirectory => { TagTable => 'Image::ExifTool::CanonVRD::Edit' }, + }, + 0xffff00f5 => { + Name => 'IHLData', + SubDirectory => { TagTable => 'Image::ExifTool::CanonVRD::IHL' }, + }, + 0xffff00f6 => { + Name => 'XMP', + Flags => [ 'Binary', 'Protected' ], + Writable => 'undef', # allow writing/deleting as a block + SubDirectory => { + DirName => 'XMP', + TagTable => 'Image::ExifTool::XMP::Main', + }, + }, + 0xffff00f7 => { + Name => 'Edit4Data', + SubDirectory => { TagTable => 'Image::ExifTool::CanonVRD::Edit4' }, + }, +); + +# the VRD edit information is divided into sections +%Image::ExifTool::CanonVRD::Edit = ( + WRITE_PROC => \&ProcessEditData, + PROCESS_PROC => \&ProcessEditData, + VARS => { ID_LABEL => 'Index' }, # change TagID label in documentation + NOTES => 'Canon VRD edit information.', + 0 => { + Name => 'VRD1', + Size => 0x272, # size of version 1.0 edit information in bytes + SubDirectory => { TagTable => 'Image::ExifTool::CanonVRD::Ver1' }, + }, + 1 => { + Name => 'VRDStampTool', + Size => 0, # size is variable, and obtained from int32u at directory start + SubDirectory => { TagTable => 'Image::ExifTool::CanonVRD::StampTool' }, + }, + 2 => { + Name => 'VRD2', + Size => undef, # size is the remaining edit data + SubDirectory => { TagTable => 'Image::ExifTool::CanonVRD::Ver2' }, + }, +); + +# Canon DPP version 4 edit information +%Image::ExifTool::CanonVRD::Edit4 = ( + WRITE_PROC => \&ProcessEditData, + PROCESS_PROC => \&ProcessEditData, + VARS => { ID_LABEL => 'Index' }, # change TagID label in documentation + NOTES => 'Canon DPP version 4 edit information.', + 0 => { + Name => 'DR4', + Size => undef, # size is the remaining edit data + SubDirectory => { TagTable => 'Image::ExifTool::CanonVRD::DR4' }, + }, +); + +# "IHL Created Optional Item Data" tags (not yet writable) +%Image::ExifTool::CanonVRD::IHL = ( + PROCESS_PROC => \&ProcessIHL, + TAG_PREFIX => 'VRD_IHL', + GROUPS => { 2 => 'Image' }, + 1 => [ + # this contains edited TIFF-format data, with an original IFD at 0x0008 + # and an edited IFD with offset given in the TIFF header. + { + Name => 'IHL_EXIF', + Condition => '$self->Options("ExtractEmbedded")', + SubDirectory => { + TagTable => 'Image::ExifTool::Exif::Main', + ProcessProc => \&ProcessIHLExif, + }, + },{ + Name => 'IHL_EXIF', + Notes => q{ + extracted as a block if the Unknown option is used, or processed as the + first sub-document with the ExtractEmbedded option + }, + Binary => 1, + Unknown => 1, + }, + ], + # 2 - written by DPP 3.0.2.6, and it looks something like edit data, + # but I haven't decoded it yet - PH + 3 => { + # (same size as the PreviewImage with DPP 3.0.2.6) + Name => 'ThumbnailImage', + Groups => { 2 => 'Preview' }, + Binary => 1, + }, + 4 => { + Name => 'PreviewImage', + Groups => { 2 => 'Preview' }, + Binary => 1, + }, + 5 => { + Name => 'RawCodecVersion', + ValueConv => '$val =~ s/\0.*//s; $val', # truncate string at null + }, + 6 => { + Name => 'CRCDevelParams', + Binary => 1, + Unknown => 1, + }, +); + +# VRD version 1 tags (ref PH) +%Image::ExifTool::CanonVRD::Ver1 = ( + PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData, + WRITE_PROC => \&Image::ExifTool::WriteBinaryData, + CHECK_PROC => \&Image::ExifTool::CheckBinaryData, + WRITABLE => 1, + FIRST_ENTRY => 0, + GROUPS => { 2 => 'Image' }, + DATAMEMBER => [ 0x002 ], # necessary for writing +# +# RAW image adjustment +# + 0x002 => { + Name => 'VRDVersion', + Format => 'int16u', + Writable => 0, + DataMember => 'VRDVersion', + RawConv => '$$self{VRDVersion} = $val', + PrintConv => '$val =~ s/^(\d)(\d*)(\d)$/$1.$2.$3/; $val', + }, + 0x006 => { + Name => 'WBAdjRGGBLevels', + Format => 'int16u[4]', + }, + 0x018 => { + Name => 'WhiteBalanceAdj', + Format => 'int16u', + PrintConvColumns => 2, + PrintConv => { + 0 => 'Auto', + 1 => 'Daylight', + 2 => 'Cloudy', + 3 => 'Tungsten', + 4 => 'Fluorescent', + 5 => 'Flash', + 8 => 'Shade', + 9 => 'Kelvin', + 30 => 'Manual (Click)', + 31 => 'Shot Settings', + }, + }, + 0x01a => { + Name => 'WBAdjColorTemp', + Format => 'int16u', + }, + # 0x01c similar to 0x006 + 0x024 => { + Name => 'WBFineTuneActive', + Format => 'int16u', + %noYes, + }, + 0x028 => { + Name => 'WBFineTuneSaturation', + Format => 'int16u', + }, + 0x02c => { + Name => 'WBFineTuneTone', + Format => 'int16u', + }, + 0x02e => { + Name => 'RawColorAdj', + Format => 'int16u', + PrintConv => { + 0 => 'Shot Settings', + 1 => 'Faithful', + 2 => 'Custom', + }, + }, + 0x030 => { + Name => 'RawCustomSaturation', + Format => 'int32s', + }, + 0x034 => { + Name => 'RawCustomTone', + Format => 'int32s', + }, + 0x038 => { + Name => 'RawBrightnessAdj', + Format => 'int32s', + ValueConv => '$val / 6000', + ValueConvInv => 'int($val * 6000 + ($val < 0 ? -0.5 : 0.5))', + PrintConv => 'sprintf("%.2f",$val)', + PrintConvInv => '$val', + }, + 0x03c => { + Name => 'ToneCurveProperty', + Format => 'int16u', + PrintConvColumns => 2, + PrintConv => { + 0 => 'Shot Settings', + 1 => 'Linear', + 2 => 'Custom 1', + 3 => 'Custom 2', + 4 => 'Custom 3', + 5 => 'Custom 4', + 6 => 'Custom 5', + }, + }, + # 0x040 usually "10 9 2" + 0x07a => { + Name => 'DynamicRangeMin', + Format => 'int16u', + }, + 0x07c => { + Name => 'DynamicRangeMax', + Format => 'int16u', + }, + # 0x0c6 usually "10 9 2" +# +# RGB image adjustment +# + 0x110 => { + Name => 'ToneCurveActive', + Format => 'int16u', + %noYes, + }, + 0x113 => { + Name => 'ToneCurveMode', + PrintConv => { 0 => 'RGB', 1 => 'Luminance' }, + }, + 0x114 => { + Name => 'BrightnessAdj', + Format => 'int8s', + }, + 0x115 => { + Name => 'ContrastAdj', + Format => 'int8s', + }, + 0x116 => { + Name => 'SaturationAdj', + Format => 'int16s', + }, + 0x11e => { + Name => 'ColorToneAdj', + Notes => 'in degrees, so -1 is the same as 359', + Format => 'int32s', + }, + 0x126 => { + Name => 'LuminanceCurvePoints', + Format => 'int16u[21]', + PrintConv => 'Image::ExifTool::CanonVRD::ToneCurvePrint($val)', + PrintConvInv => 'Image::ExifTool::CanonVRD::ToneCurvePrintInv($val)', + }, + 0x150 => { + Name => 'LuminanceCurveLimits', + Notes => '4 numbers: input and output highlight and shadow points', + Format => 'int16u[4]', + }, + 0x159 => { + Name => 'ToneCurveInterpolation', + PrintConv => { 0 => 'Curve', 1 => 'Straight' }, + }, + 0x160 => { + Name => 'RedCurvePoints', + Format => 'int16u[21]', + PrintConv => 'Image::ExifTool::CanonVRD::ToneCurvePrint($val)', + PrintConvInv => 'Image::ExifTool::CanonVRD::ToneCurvePrintInv($val)', + }, + # 0x193 same as 0x159 + 0x19a => { + Name => 'GreenCurvePoints', + Format => 'int16u[21]', + PrintConv => 'Image::ExifTool::CanonVRD::ToneCurvePrint($val)', + PrintConvInv => 'Image::ExifTool::CanonVRD::ToneCurvePrintInv($val)', + }, + # 0x1cd same as 0x159 + 0x1d4 => { + Name => 'BlueCurvePoints', + Format => 'int16u[21]', + PrintConv => 'Image::ExifTool::CanonVRD::ToneCurvePrint($val)', + PrintConvInv => 'Image::ExifTool::CanonVRD::ToneCurvePrintInv($val)', + }, + 0x18a => { + Name => 'RedCurveLimits', + Format => 'int16u[4]', + }, + 0x1c4 => { + Name => 'GreenCurveLimits', + Format => 'int16u[4]', + }, + 0x1fe => { + Name => 'BlueCurveLimits', + Format => 'int16u[4]', + }, + # 0x207 same as 0x159 + 0x20e => { + Name => 'RGBCurvePoints', + Format => 'int16u[21]', + PrintConv => 'Image::ExifTool::CanonVRD::ToneCurvePrint($val)', + PrintConvInv => 'Image::ExifTool::CanonVRD::ToneCurvePrintInv($val)', + }, + 0x238 => { + Name => 'RGBCurveLimits', + Format => 'int16u[4]', + }, + # 0x241 same as 0x159 + 0x244 => { + Name => 'CropActive', + Format => 'int16u', + %noYes, + }, + 0x246 => { + Name => 'CropLeft', + Notes => 'crop coordinates in original unrotated image', + Format => 'int16u', + }, + 0x248 => { + Name => 'CropTop', + Format => 'int16u', + }, + 0x24a => { + Name => 'CropWidth', + Format => 'int16u', + }, + 0x24c => { + Name => 'CropHeight', + Format => 'int16u', + }, + 0x25a => { + Name => 'SharpnessAdj', + Format => 'int16u', + }, + 0x260 => { + Name => 'CropAspectRatio', + Format => 'int16u', + PrintConv => { + 0 => 'Free', + 1 => '3:2', + 2 => '2:3', + 3 => '4:3', + 4 => '3:4', + 5 => 'A-size Landscape', + 6 => 'A-size Portrait', + 7 => 'Letter-size Landscape', + 8 => 'Letter-size Portrait', + 9 => '4:5', + 10 => '5:4', + 11 => '1:1', + 12 => 'Circle', + 65535 => 'Custom', + }, + }, + 0x262 => { + Name => 'ConstrainedCropWidth', + Format => 'float', + PrintConv => 'sprintf("%.7g",$val)', + PrintConvInv => '$val', + }, + 0x266 => { + Name => 'ConstrainedCropHeight', + Format => 'float', + PrintConv => 'sprintf("%.7g",$val)', + PrintConvInv => '$val', + }, + 0x26a => { + Name => 'CheckMark', + Format => 'int16u', + PrintConv => { + 0 => 'Clear', + 1 => 1, + 2 => 2, + 3 => 3, + }, + }, + 0x26e => { + Name => 'Rotation', + Format => 'int16u', + PrintConv => { + 0 => 0, + 1 => 90, + 2 => 180, + 3 => 270, + }, + }, + 0x270 => { + Name => 'WorkColorSpace', + Format => 'int16u', + PrintConv => { + 0 => 'sRGB', + 1 => 'Adobe RGB', + 2 => 'Wide Gamut RGB', + 3 => 'Apple RGB', + 4 => 'ColorMatch RGB', + }, + }, + # (VRD 1.0.0 edit data ends here -- 0x272 bytes) +); + +# VRD Stamp Tool tags (ref PH) +%Image::ExifTool::CanonVRD::StampTool = ( + PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData, + GROUPS => { 2 => 'Image' }, + 0x00 => { + Name => 'StampToolCount', + Format => 'int32u', + }, +); + +# VRD version 2 and 3 tags (ref PH) +%Image::ExifTool::CanonVRD::Ver2 = ( + PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData, + WRITE_PROC => \&Image::ExifTool::WriteBinaryData, + CHECK_PROC => \&Image::ExifTool::CheckBinaryData, + WRITABLE => 1, + FIRST_ENTRY => 0, + FORMAT => 'int16s', + DATAMEMBER => [ 0x58, 0xdc, 0xdf, 0xe0 ], # (required for DataMember and var-format tags) + IS_SUBDIR => [ 0xe0 ], + GROUPS => { 2 => 'Image' }, + NOTES => 'Tags added in DPP version 2.0 and later.', + 0x02 => { + Name => 'PictureStyle', + PrintConvColumns => 2, + PrintConv => { + 0 => 'Standard', + 1 => 'Portrait', + 2 => 'Landscape', + 3 => 'Neutral', + 4 => 'Faithful', + 5 => 'Monochrome', + 6 => 'Unknown?', # PH (maybe in-camera custom picture style?) + 7 => 'Custom', + }, + }, + 0x03 => { Name => 'IsCustomPictureStyle', %noYes }, + # 0x08: 3 + # 0x09: 4095 + # 0x0a: 0 + # 0x0b: 4095 + # 0x0c: 0 + 0x0d => 'StandardRawColorTone', + 0x0e => 'StandardRawSaturation', + 0x0f => 'StandardRawContrast', + 0x10 => { Name => 'StandardRawLinear', %noYes }, + 0x11 => 'StandardRawSharpness', + 0x12 => 'StandardRawHighlightPoint', + 0x13 => 'StandardRawShadowPoint', + 0x14 => 'StandardOutputHighlightPoint', #2 + 0x15 => 'StandardOutputShadowPoint', #2 + 0x16 => 'PortraitRawColorTone', + 0x17 => 'PortraitRawSaturation', + 0x18 => 'PortraitRawContrast', + 0x19 => { Name => 'PortraitRawLinear', %noYes }, + 0x1a => 'PortraitRawSharpness', + 0x1b => 'PortraitRawHighlightPoint', + 0x1c => 'PortraitRawShadowPoint', + 0x1d => 'PortraitOutputHighlightPoint', + 0x1e => 'PortraitOutputShadowPoint', + 0x1f => 'LandscapeRawColorTone', + 0x20 => 'LandscapeRawSaturation', + 0x21 => 'LandscapeRawContrast', + 0x22 => { Name => 'LandscapeRawLinear', %noYes }, + 0x23 => 'LandscapeRawSharpness', + 0x24 => 'LandscapeRawHighlightPoint', + 0x25 => 'LandscapeRawShadowPoint', + 0x26 => 'LandscapeOutputHighlightPoint', + 0x27 => 'LandscapeOutputShadowPoint', + 0x28 => 'NeutralRawColorTone', + 0x29 => 'NeutralRawSaturation', + 0x2a => 'NeutralRawContrast', + 0x2b => { Name => 'NeutralRawLinear', %noYes }, + 0x2c => 'NeutralRawSharpness', + 0x2d => 'NeutralRawHighlightPoint', + 0x2e => 'NeutralRawShadowPoint', + 0x2f => 'NeutralOutputHighlightPoint', + 0x30 => 'NeutralOutputShadowPoint', + 0x31 => 'FaithfulRawColorTone', + 0x32 => 'FaithfulRawSaturation', + 0x33 => 'FaithfulRawContrast', + 0x34 => { Name => 'FaithfulRawLinear', %noYes }, + 0x35 => 'FaithfulRawSharpness', + 0x36 => 'FaithfulRawHighlightPoint', + 0x37 => 'FaithfulRawShadowPoint', + 0x38 => 'FaithfulOutputHighlightPoint', + 0x39 => 'FaithfulOutputShadowPoint', + 0x3a => { + Name => 'MonochromeFilterEffect', + PrintConv => { + -2 => 'None', + -1 => 'Yellow', + 0 => 'Orange', + 1 => 'Red', + 2 => 'Green', + }, + }, + 0x3b => { + Name => 'MonochromeToningEffect', + PrintConv => { + -2 => 'None', + -1 => 'Sepia', + 0 => 'Blue', + 1 => 'Purple', + 2 => 'Green', + }, + }, + 0x3c => 'MonochromeContrast', + 0x3d => { Name => 'MonochromeLinear', %noYes }, + 0x3e => 'MonochromeSharpness', + 0x3f => 'MonochromeRawHighlightPoint', + 0x40 => 'MonochromeRawShadowPoint', + 0x41 => 'MonochromeOutputHighlightPoint', + 0x42 => 'MonochromeOutputShadowPoint', + 0x45 => { Name => 'UnknownContrast', Unknown => 1 }, + 0x46 => { Name => 'UnknownLinear', %noYes, Unknown => 1 }, + 0x47 => { Name => 'UnknownSharpness', Unknown => 1 }, + 0x48 => { Name => 'UnknownRawHighlightPoint', Unknown => 1 }, + 0x49 => { Name => 'UnknownRawShadowPoint', Unknown => 1 }, + 0x4a => { Name => 'UnknownOutputHighlightPoint',Unknown => 1 }, + 0x4b => { Name => 'UnknownOutputShadowPoint', Unknown => 1 }, + 0x4c => 'CustomColorTone', + 0x4d => 'CustomSaturation', + 0x4e => 'CustomContrast', + 0x4f => { Name => 'CustomLinear', %noYes }, + 0x50 => 'CustomSharpness', + 0x51 => 'CustomRawHighlightPoint', + 0x52 => 'CustomRawShadowPoint', + 0x53 => 'CustomOutputHighlightPoint', + 0x54 => 'CustomOutputShadowPoint', + 0x58 => { + Name => 'CustomPictureStyleData', + Format => 'var_int16u', + Binary => 1, + Notes => 'variable-length data structure', + Writable => 0, + RawConv => 'length($val) == 2 ? undef : $val', # ignore if no data + }, + # (VRD 2.0.0 edit data ends here: 178 bytes, index 0x59) + 0x5e => [{ + Name => 'ChrominanceNoiseReduction', + Condition => '$$self{VRDVersion} < 330', + Notes => 'VRDVersion prior to 3.3.0', + PrintConv => { + 0 => 'Off', + 58 => 'Low', + 100 => 'High', + }, + },{ #1 + Name => 'ChrominanceNoiseReduction', + Notes => 'VRDVersion 3.3.0 or later', + PrintHex => 1, + PrintConvColumns => 4, + PrintConv => { + 0x00 => 0, + 0x10 => 1, + 0x21 => 2, + 0x32 => 3, + 0x42 => 4, + 0x53 => 5, + 0x64 => 6, + 0x74 => 7, + 0x85 => 8, + 0x96 => 9, + 0xa6 => 10, + 0xa7 => 11, + 0xa8 => 12, + 0xa9 => 13, + 0xaa => 14, + 0xab => 15, + 0xac => 16, + 0xad => 17, + 0xae => 18, + 0xaf => 19, + 0xb0 => 20, + }, + }], + 0x5f => [{ + Name => 'LuminanceNoiseReduction', + Condition => '$$self{VRDVersion} < 330', + Notes => 'VRDVersion prior to 3.3.0', + PrintConv => { + 0 => 'Off', + 65 => 'Low', + 100 => 'High', + }, + },{ #1 + Name => 'LuminanceNoiseReduction', + Notes => 'VRDVersion 3.3.0 or later', + PrintHex => 1, + PrintConvColumns => 4, + PrintConv => { + 0x00 => 0, + 0x41 => 1, + 0x64 => 2, + 0x6e => 3, + 0x78 => 4, + 0x82 => 5, + 0x8c => 6, + 0x96 => 7, + 0xa0 => 8, + 0xaa => 9, + 0xb4 => 10, + 0xb5 => 11, + 0xb6 => 12, + 0xb7 => 13, + 0xb8 => 14, + 0xb9 => 15, + 0xba => 16, + 0xbb => 17, + 0xbc => 18, + 0xbd => 19, + 0xbe => 20, + }, + }], + 0x60 => [{ + Name => 'ChrominanceNR_TIFF_JPEG', + Condition => '$$self{VRDVersion} < 330', + Notes => 'VRDVersion prior to 3.3.0', + PrintConv => { + 0 => 'Off', + 33 => 'Low', + 100 => 'High', + }, + },{ #1 + Name => 'ChrominanceNR_TIFF_JPEG', + Notes => 'VRDVersion 3.3.0 or later', + PrintHex => 1, + PrintConvColumns => 4, + PrintConv => { + 0x00 => 0, + 0x10 => 1, + 0x21 => 2, + 0x32 => 3, + 0x42 => 4, + 0x53 => 5, + 0x64 => 6, + 0x74 => 7, + 0x85 => 8, + 0x96 => 9, + 0xa6 => 10, + 0xa7 => 11, + 0xa8 => 12, + 0xa9 => 13, + 0xaa => 14, + 0xab => 15, + 0xac => 16, + 0xad => 17, + 0xae => 18, + 0xaf => 19, + 0xb0 => 20, + }, + }], + # 0x61: 1 + # (VRD 3.0.0 edit data ends here: 196 bytes, index 0x62) + 0x62 => { Name => 'ChromaticAberrationOn', %noYes }, + 0x63 => { Name => 'DistortionCorrectionOn', %noYes }, + 0x64 => { Name => 'PeripheralIlluminationOn', %noYes }, + 0x65 => { Name => 'ColorBlur', %noYes }, + 0x66 => { + Name => 'ChromaticAberration', + ValueConv => '$val / 0x400', + ValueConvInv => 'int($val * 0x400 + 0.5)', + PrintConv => 'sprintf("%.0f%%", $val * 100)', + PrintConvInv => 'ToFloat($val) / 100', + }, + 0x67 => { + Name => 'DistortionCorrection', + ValueConv => '$val / 0x400', + ValueConvInv => 'int($val * 0x400 + 0.5)', + PrintConv => 'sprintf("%.0f%%", $val * 100)', + PrintConvInv => 'ToFloat($val) / 100', + }, + 0x68 => { + Name => 'PeripheralIllumination', + ValueConv => '$val / 0x400', + ValueConvInv => 'int($val * 0x400 + 0.5)', + PrintConv => 'sprintf("%.0f%%", $val * 100)', + PrintConvInv => 'ToFloat($val) / 100', + }, + 0x69 => { + Name => 'AberrationCorrectionDistance', + Notes => '100% = infinity', + RawConv => '$val == 0x7fff ? undef : $val', + ValueConv => '1 - $val / 0x400', + ValueConvInv => 'int((1 - $val) * 0x400 + 0.5)', + PrintConv => 'sprintf("%.0f%%", $val * 100)', + PrintConvInv => 'ToFloat($val) / 100', + }, + 0x6a => 'ChromaticAberrationRed', + 0x6b => 'ChromaticAberrationBlue', + 0x6d => { #1 + Name => 'LuminanceNR_TIFF_JPEG', + Notes => 'val = raw / 10', + ValueConv => '$val / 10', + ValueConvInv => 'int($val * 10 + 0.5)', + }, + # (VRD 3.4.0 edit data ends here: 220 bytes, index 0x6e) + 0x6e => { Name => 'AutoLightingOptimizerOn', %noYes }, + 0x6f => { + Name => 'AutoLightingOptimizer', + PrintConv => { + 100 => 'Low', + 200 => 'Standard', + 300 => 'Strong', + 0x7fff => 'n/a', #1 + }, + }, + # 0x71: 200 + # 0x73: 100 + # (VRD 3.5.0 edit data ends here: 232 bytes, index 0x74) + 0x75 => { + Name => 'StandardRawHighlight', + ValueConv => '$val / 10', + ValueConvInv => '$val * 10', + }, + 0x76 => { + Name => 'PortraitRawHighlight', + ValueConv => '$val / 10', + ValueConvInv => '$val * 10', + }, + 0x77 => { + Name => 'LandscapeRawHighlight', + ValueConv => '$val / 10', + ValueConvInv => '$val * 10', + }, + 0x78 => { + Name => 'NeutralRawHighlight', + ValueConv => '$val / 10', + ValueConvInv => '$val * 10', + }, + 0x79 => { + Name => 'FaithfulRawHighlight', + ValueConv => '$val / 10', + ValueConvInv => '$val * 10', + }, + 0x7a => { + Name => 'MonochromeRawHighlight', + ValueConv => '$val / 10', + ValueConvInv => '$val * 10', + }, + 0x7b => { + Name => 'UnknownRawHighlight', + Unknown => 1, + ValueConv => '$val / 10', + ValueConvInv => '$val * 10', + }, + 0x7c => { + Name => 'CustomRawHighlight', + ValueConv => '$val / 10', + ValueConvInv => '$val * 10', + }, + 0x7e => { + Name => 'StandardRawShadow', + ValueConv => '$val / 10', + ValueConvInv => '$val * 10', + }, + 0x7f => { + Name => 'PortraitRawShadow', + ValueConv => '$val / 10', + ValueConvInv => '$val * 10', + }, + 0x80 => { + Name => 'LandscapeRawShadow', + ValueConv => '$val / 10', + ValueConvInv => '$val * 10', + }, + 0x81 => { + Name => 'NeutralRawShadow', + ValueConv => '$val / 10', + ValueConvInv => '$val * 10', + }, + 0x82 => { + Name => 'FaithfulRawShadow', + ValueConv => '$val / 10', + ValueConvInv => '$val * 10', + }, + 0x83 => { + Name => 'MonochromeRawShadow', + ValueConv => '$val / 10', + ValueConvInv => '$val * 10', + }, + 0x84 => { + Name => 'UnknownRawShadow', + Unknown => 1, + ValueConv => '$val / 10', + ValueConvInv => '$val * 10', + }, + 0x85 => { + Name => 'CustomRawShadow', + ValueConv => '$val / 10', + ValueConvInv => '$val * 10', + }, + 0x8b => { #2 + Name => 'AngleAdj', + Format => 'int32s', + ValueConv => '$val / 100', + ValueConvInv => '$val * 100', + }, + 0x8e => { + Name => 'CheckMark2', + Format => 'int16u', + PrintConvColumns => 2, + PrintConv => { + 0 => 'Clear', + 1 => 1, + 2 => 2, + 3 => 3, + 4 => 4, + 5 => 5, + }, + }, + # (VRD 3.8.0 edit data ends here: 286 bytes, index 0x8f) + 0x90 => { + Name => 'UnsharpMask', + PrintConv => { 0 => 'Off', 1 => 'On' }, + }, + 0x92 => 'StandardUnsharpMaskStrength', + 0x94 => 'StandardUnsharpMaskFineness', + 0x96 => 'StandardUnsharpMaskThreshold', + 0x98 => 'PortraitUnsharpMaskStrength', + 0x9a => 'PortraitUnsharpMaskFineness', + 0x9c => 'PortraitUnsharpMaskThreshold', + 0x9e => 'LandscapeUnsharpMaskStrength', + 0xa0 => 'LandscapeUnsharpMaskFineness', + 0xa2 => 'LandscapeUnsharpMaskThreshold', + 0xa4 => 'NeutraUnsharpMaskStrength', + 0xa6 => 'NeutralUnsharpMaskFineness', + 0xa8 => 'NeutralUnsharpMaskThreshold', + 0xaa => 'FaithfulUnsharpMaskStrength', + 0xac => 'FaithfulUnsharpMaskFineness', + 0xae => 'FaithfulUnsharpMaskThreshold', + 0xb0 => 'MonochromeUnsharpMaskStrength', + 0xb2 => 'MonochromeUnsharpMaskFineness', + 0xb4 => 'MonochromeUnsharpMaskThreshold', + 0xb6 => 'CustomUnsharpMaskStrength', + 0xb8 => 'CustomUnsharpMaskFineness', + 0xba => 'CustomUnsharpMaskThreshold', + 0xbc => 'CustomDefaultUnsharpStrength', + 0xbe => 'CustomDefaultUnsharpFineness', + 0xc0 => 'CustomDefaultUnsharpThreshold', + # (VRD 3.9.1 edit data ends here: 392 bytes, index 0xc4) + # 0xc9: 3 - some RawSharpness + # 0xca: 4095 - some RawHighlightPoint + # 0xcb: 0 - some RawShadowPoint + # 0xcc: 4095 - some OutputHighlightPoint + # 0xcd: 0 - some OutputShadowPoint + # 0xd1: 3 - some UnsharpMaskStrength + # 0xd3: 7 - some UnsharpMaskFineness + # 0xd5: 3,4 - some UnsharpMaskThreshold + 0xd6 => { Name => 'CropCircleActive', %noYes }, + 0xd7 => 'CropCircleX', + 0xd8 => 'CropCircleY', + 0xd9 => 'CropCircleRadius', + # 0xda: 0, 1 + # 0xdb: 100 + 0xdc => { + Name => 'DLOOn', + DataMember => 'DLOOn', + RawConv => '$$self{DLOOn} = $val', + %noYes, + }, + 0xdd => 'DLOSetting', + # (VRD 3.11.0 edit data ends here: 444 bytes, index 0xde) + 0xde => { + Name => 'DLOShootingDistance', + Notes => '100% = infinity', + RawConv => '$val == 0x7fff ? undef : $val', + ValueConv => '1 - $val / 0x400', + ValueConvInv => 'int((1 - $val) * 0x400 + 0.5)', + PrintConv => 'sprintf("%.0f%%", $val * 100)', + PrintConvInv => 'ToFloat($val) / 100', + }, + 0xdf => { + Name => 'DLODataLength', + DataMember => 'DLODataLength', + Format => 'int32u', + Writable => 0, + RawConv => '$$self{DLODataLength} = $val', + }, + 0xe0 => { # (yes, this overlaps DLODataLength) + Name => 'DLOInfo', + # - have seen DLODataLengths of 65536,64869 when DLO is Off, so must test DLOOn flag + Condition => '$$self{DLOOn}', + SubDirectory => { TagTable => 'Image::ExifTool::CanonVRD::DLOInfo' }, + Hook => '$varSize += $$self{DLODataLength} + 0x16', + }, + 0xe1 => 'CameraRawColorTone', + # (VRD 3.11.2 edit data ends here: 452 bytes, index 0xe2, unless DLO is on) + 0xe2 => 'CameraRawSaturation', + 0xe3 => 'CameraRawContrast', + 0xe4 => { Name => 'CameraRawLinear', %noYes }, + 0xe5 => 'CameraRawSharpness', + 0xe6 => 'CameraRawHighlightPoint', + 0xe7 => 'CameraRawShadowPoint', + 0xe8 => 'CameraRawOutputHighlightPoint', + 0xe9 => 'CameraRawOutputShadowPoint', +); + +# DLO tags (ref PH) +%Image::ExifTool::CanonVRD::DLOInfo = ( + PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData, + WRITE_PROC => \&Image::ExifTool::WriteBinaryData, + CHECK_PROC => \&Image::ExifTool::CheckBinaryData, + WRITABLE => 1, + FIRST_ENTRY => 1, + FORMAT => 'int16s', + GROUPS => { 2 => 'Image' }, + NOTES => 'Tags added when DLO (Digital Lens Optimizer) is on.', + # 0x01 - seen 3112,3140 + 0x04 => 'DLOSettingApplied', + 0x05 => { + Name => 'DLOVersion', #(NC) + Format => 'string[10]', + }, + 0x0a => { + Name => 'DLOData', + LargeTag => 1, # large tag, so avoid storing unnecessarily + Notes => 'variable-length Digital Lens Optimizer data, stored in JPEG-like format', + Format => 'undef[$$self{DLODataLength}]', + Writable => 0, + Binary => 1, + }, +); + +# VRD version 4 tags (ref PH) +%Image::ExifTool::CanonVRD::DR4 = ( + PROCESS_PROC => \&ProcessDR4, + WRITE_PROC => \&ProcessDR4, + WRITABLE => 1, + GROUPS => { 2 => 'Image' }, + VARS => { HEX_ID => 1, SORT_PROC => \&SortDR4 }, + NOTES => q{ + Tags written by Canon DPP version 4 in CanonVRD trailers and DR4 files. Each + tag has three associated flag words which are stored with the directory + entry, some of which are extracted as a separate tag, indicated in the table + below by a decimal appended to the tag ID (.0, .1 or .2). + }, + header => { + Name => 'DR4Header', + SubDirectory => { TagTable => 'Image::ExifTool::CanonVRD::DR4Header' }, + }, + 0x10002 => 'Rotation', # left/right rotation 90,180,270 + 0x10003 => 'AngleAdj', # crop angle + # 0x10018 - fmt=8: 0 + # 0x10020 - fmt=2: '' + 0x10021 => 'CustomPictureStyle', # (string) + 0x10101 => { + Name => 'CheckMark', + PrintConv => { + 0 => 'Clear', + 1 => 1, + 2 => 2, + 3 => 3, + 4 => 4, + 5 => 5, + }, + }, + 0x10200 => { + Name => 'WorkColorSpace', + PrintConv => { + 1 => 'sRGB', + 2 => 'Adobe RGB', + 3 => 'Wide Gamut RGB', + 4 => 'Apple RGB', + 5 => 'ColorMatch RGB', + }, + }, + # 0x10201 - fmt=9: 0 + # 0x10f20 - fmt=9: 350 + 0x20001 => 'RawBrightnessAdj', + 0x20101 => { + Name => 'WhiteBalanceAdj', + PrintConvColumns => 2, + PrintConv => { + -1 => 'Manual (Click)', + 0 => 'Auto', + 1 => 'Daylight', + 2 => 'Cloudy', + 3 => 'Tungsten', + 4 => 'Fluorescent', + 5 => 'Flash', + 8 => 'Shade', + 9 => 'Kelvin', + 255 => 'Shot Settings', + }, + }, + 0x20102 => 'WBAdjColorTemp', + 0x20105 => 'WBAdjMagentaGreen', + 0x20106 => 'WBAdjBlueAmber', + 0x20125 => { + Name => 'WBAdjRGGBLevels', + PrintConv => '$val =~ s/^\d+ //; $val', # remove first integer (14: what is this for?) + PrintConvInv => '"14 $val"', + }, + 0x20200 => { Name => 'GammaLinear', %noYes }, + 0x20301 => { + Name => 'PictureStyle', + PrintHex => 1, + PrintConv => { + 0x81 => 'Standard', + 0x82 => 'Portrait', + 0x83 => 'Landscape', + 0x84 => 'Neutral', + 0x85 => 'Faithful', + 0x86 => 'Monochrome', + 0x87 => 'Auto', + 0x88 => 'Fine Detail', + 0xf0 => 'Shot Settings', + 0xff => 'Custom', + }, + }, + # 0x20302 - Gamma curve data + 0x20303 => 'ContrastAdj', + 0x20304 => 'ColorToneAdj', + 0x20305 => 'ColorSaturationAdj', + 0x20306 => { + Name => 'MonochromeToningEffect', + PrintConv => { + 0 => 'None', + 1 => 'Sepia', + 2 => 'Blue', + 3 => 'Purple', + 4 => 'Green', + }, + }, + 0x20307 => { + Name => 'MonochromeFilterEffect', + PrintConv => { + 0 => 'None', + 1 => 'Yellow', + 2 => 'Orange', + 3 => 'Red', + 4 => 'Green', + }, + }, + 0x20308 => 'UnsharpMaskStrength', + 0x20309 => 'UnsharpMaskFineness', + 0x2030a => 'UnsharpMaskThreshold', + 0x2030b => 'ShadowAdj', + 0x2030c => 'HighlightAdj', + 0x20310 => { + Name => 'SharpnessAdj', + PrintConv => { + 0 => 'Sharpness', + 1 => 'Unsharp Mask', + }, + }, + '0x20310.0' => { Name => 'SharpnessAdjOn', %noYes }, + 0x20311 => 'SharpnessStrength', + 0x20400 => { + Name => 'ToneCurve', + SubDirectory => { TagTable => 'Image::ExifTool::CanonVRD::ToneCurve' }, + }, + '0x20400.1' => { Name => 'ToneCurveOriginal', %noYes }, + # 0x20401 - fmt=33 (312 bytes) + 0x20410 => 'ToneCurveBrightness', + 0x20411 => 'ToneCurveContrast', + 0x20500 => { + Name => 'AutoLightingOptimizer', + PrintConv => { + 0 => 'Low', + 1 => 'Standard', + 2 => 'Strong', + }, + }, + '0x20500.0' => { + Name => 'AutoLightingOptimizerOn', + Notes => 'ignored if gamma is linear', + %noYes, + }, + # 0x20501 - fmt=13: 0 + # 0x20502 - fmt=13: 0 + 0x20600 => 'LuminanceNoiseReduction', + 0x20601 => 'ChrominanceNoiseReduction', + # 0x20650 - fmt=9: 0 (JPG images) + 0x20670 => 'ColorMoireReduction', + '0x20670.0' => { Name => 'ColorMoireReductionOn', %noYes }, + 0x20701 => { + Name => 'ShootingDistance', + Notes => '100% = infinity', + ValueConv => '$val / 10', + ValueConvInv => '$val * 10', + PrintConv => 'sprintf("%.0f%%", $val * 100)', + PrintConvInv => 'ToFloat($val) / 100', + }, + 0x20702 => { + Name => 'PeripheralIllumination', + PrintConv => 'sprintf "%g", $val', + PrintConvInv => '$val', + }, + '0x20702.0' => { Name => 'PeripheralIlluminationOn', %noYes }, + 0x20703 => { + Name => 'ChromaticAberration', + PrintConv => 'sprintf "%g", $val', + PrintConvInv => '$val', + }, + '0x20703.0' => { Name => 'ChromaticAberrationOn', %noYes }, + 0x20704 => { Name => 'ColorBlurOn', %noYes }, + 0x20705 => { + Name => 'DistortionCorrection', + PrintConv => 'sprintf "%g", $val', + PrintConvInv => '$val', + }, + '0x20705.0' => { Name => 'DistortionCorrectionOn', %noYes }, + 0x20706 => 'DLOSetting', + '0x20706.0' => { Name => 'DLOOn', %noYes }, + 0x20707 => { + Name => 'ChromaticAberrationRed', + PrintConv => 'sprintf "%g", $val', + PrintConvInv => '$val', + }, + 0x20708 => { + Name => 'ChromaticAberrationBlue', + PrintConv => 'sprintf "%g", $val', + PrintConvInv => '$val', + }, + 0x20709 => { + Name => 'DistortionEffect', + PrintConv => { + 0 => 'Shot Settings', + 1 => 'Emphasize Linearity', + 2 => 'Emphasize Distance', + 3 => 'Emphasize Periphery', + 4 => 'Emphasize Center', + }, + }, + # 0x20800 - fmt=1: 0 + # 0x20801 - fmt=1: 0 + 0x2070b => { Name => 'DiffractionCorrectionOn', %noYes }, + 0x20900 => 'ColorHue', + 0x20901 => 'SaturationAdj', + 0x20910 => 'RedHSL', + 0x20911 => 'OrangeHSL', + 0x20912 => 'YellowHSL', + 0x20913 => 'GreenHSL', + 0x20914 => 'AquaHSL', + 0x20915 => 'BlueHSL', + 0x20916 => 'PurpleHSL', + 0x20917 => 'MagentaHSL', + 0x20a00 => { + Name => 'GammaInfo', + SubDirectory => { TagTable => 'Image::ExifTool::CanonVRD::GammaInfo' }, + }, + # 0x20a01 - Auto picture style settings + # 0x20a02 - Standard picture style settings + # 0x20a03 - Portrait picture style settings + # 0x20a04 - Landscape picture style settings + # 0x20a05 - Neutral picture style settings + # 0x20a06 - Faithful picture style settings + # 0x20a07 - Monochrome picture style settings + # 0x20a08 - (unknown picture style settings) + # 0x20a09 - Custom picture style settings + # 0x20a20 - Fine Detail picture style settings + 0x30101 => { + Name => 'CropAspectRatio', + PrintConv => { + 0 => 'Free', + 1 => 'Custom', + 2 => '1:1', + 3 => '3:2', + 4 => '2:3', + 5 => '4:3', + 6 => '3:4', + 7 => '5:4', + 8 => '4:5', + 9 => '16:9', + 10 => '9:16', + }, + }, + 0x30102 => 'CropAspectRatioCustom', + # 0x30103 - fmt=33: "0 0 8" + 0xf0100 => { + Name => 'CropInfo', + SubDirectory => { TagTable => 'Image::ExifTool::CanonVRD::CropInfo' }, + }, + 0xf0500 => { + Name => 'CustomPictureStyleData', + Binary => 1, + }, + 0xf0510 => { + Name => 'StampInfo', + SubDirectory => { TagTable => 'Image::ExifTool::CanonVRD::StampInfo' }, + }, + 0xf0511 => { + Name => 'DustInfo', + SubDirectory => { TagTable => 'Image::ExifTool::CanonVRD::DustInfo' }, + }, + 0xf0512 => 'LensFocalLength', + # 0xf0521 - DLO data + # 0xf0520 - DLO data + # 0xf0530 - created when dust delete data applied (4 bytes, all zero) + # 0xf0600 - fmt=253 (2308 bytes, JPG images) + # 0xf0601 - fmt=253 (2308 bytes, JPG images) + # 0x1ff52c - values: 129,130,132 (related to custom picture style somehow) + # to do: + # - find 8-15mm CR2 sample and decode linear distortion effect fine-tune +); + +# Version 4 header information (ref PH) +%Image::ExifTool::CanonVRD::DR4Header = ( + PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData, + WRITE_PROC => \&Image::ExifTool::WriteBinaryData, + CHECK_PROC => \&Image::ExifTool::CheckBinaryData, + WRITABLE => 1, + FIRST_ENTRY => 0, + FORMAT => 'int32u', + GROUPS => { 2 => 'Image' }, + # 0 - value: 'IIII' (presumably byte order) + # 1 - value: 0x00040004 (currently use this for magic number) + # 2 - value: 6 + 3 => { + Name => 'DR4CameraModel', + Writable => 'int32u', + PrintHex => 1, + SeparateTable => 'Canon CanonModelID', + PrintConv => \%Image::ExifTool::Canon::canonModelID, + }, + # 4 - value: 3 + # 5 - value: 4 + # 6 - value: 5 + # 7 - DR4 directory entry count +); + +# Version 4 RGB tone curve information (ref PH) +%Image::ExifTool::CanonVRD::ToneCurve = ( + PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData, + WRITE_PROC => \&Image::ExifTool::WriteBinaryData, + CHECK_PROC => \&Image::ExifTool::CheckBinaryData, + WRITABLE => 1, + FIRST_ENTRY => 0, + FORMAT => 'int32u', + GROUPS => { 2 => 'Image' }, + 0x00 => { + Name => 'ToneCurveColorSpace', + PrintConv => { + 0 => 'RGB', + 1 => 'Luminance', + }, + }, + 0x01 => { + Name => 'ToneCurveShape', + PrintConv => { + 0 => 'Curve', + 1 => 'Straight', + }, + }, + 0x03 => { Name => 'ToneCurveInputRange', Format => 'int32u[2]', Notes => '255 max' }, + 0x05 => { Name => 'ToneCurveOutputRange', Format => 'int32u[2]', Notes => '255 max' }, + 0x07 => { + Name => 'RGBCurvePoints', + Format => 'int32u[21]', + PrintConv => 'Image::ExifTool::CanonVRD::ToneCurvePrint($val)', + PrintConvInv => 'Image::ExifTool::CanonVRD::ToneCurvePrintInv($val)', + }, + 0x0a => 'ToneCurveX', + 0x0b => 'ToneCurveY', + 0x2d => { + Name => 'RedCurvePoints', + Format => 'int32u[21]', + PrintConv => 'Image::ExifTool::CanonVRD::ToneCurvePrint($val)', + PrintConvInv => 'Image::ExifTool::CanonVRD::ToneCurvePrintInv($val)', + }, + 0x53 => { + Name => 'GreenCurvePoints', + Format => 'int32u[21]', + PrintConv => 'Image::ExifTool::CanonVRD::ToneCurvePrint($val)', + PrintConvInv => 'Image::ExifTool::CanonVRD::ToneCurvePrintInv($val)', + }, + 0x79 => { + Name => 'BlueCurvePoints', + Format => 'int32u[21]', + PrintConv => 'Image::ExifTool::CanonVRD::ToneCurvePrint($val)', + PrintConvInv => 'Image::ExifTool::CanonVRD::ToneCurvePrintInv($val)', + }, +); + +# Version 4 gamma curve information (ref PH) +%Image::ExifTool::CanonVRD::GammaInfo = ( + PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData, + WRITE_PROC => \&Image::ExifTool::WriteBinaryData, + CHECK_PROC => \&Image::ExifTool::CheckBinaryData, + WRITABLE => 1, + FIRST_ENTRY => 0, + FORMAT => 'double', + GROUPS => { 2 => 'Image' }, + 0x02 => 'GammaContrast', + 0x03 => 'GammaColorTone', + 0x04 => 'GammaSaturation', + 0x05 => 'GammaUnsharpMaskStrength', + 0x06 => 'GammaUnsharpMaskFineness', + 0x07 => 'GammaUnsharpMaskThreshold', + 0x08 => 'GammaSharpnessStrength', + 0x09 => 'GammaShadow', + 0x0a => 'GammaHighlight', + # 0x0b-0x10 are the same as first 6 doubles of tag DR4_0x20302 + # 0x0b - value: 14 + 0x0c => { + Name => 'GammaBlackPoint', + ValueConv => q{ + return 0 if $val <= 0; + $val = log($val / 4.6875) / log(2) + 1; + return abs($val) > 1e-10 ? $val : 0; + }, + ValueConvInv => '$val ? exp(($val - 1) * log(2)) * 4.6876 : 0', + PrintConv => 'sprintf("%+.3f", $val)', + PrintConvInv => '$val', + }, + 0x0d => { + Name => 'GammaWhitePoint', + ValueConv => q{ + return $val if $val <= 0; + $val = log($val / 4.6875) / log(2) - 11.77109325169954; + return abs($val) > 1e-10 ? $val : 0; + }, + ValueConvInv => '$val ? exp(($val + 11.77109325169954) * log(2)) * 4.6875 : 0', + PrintConv => 'sprintf("%+.3f", $val)', + PrintConvInv => '$val', + }, + 0x0e => { + Name => 'GammaMidPoint', + ValueConv => q{ + return $val if $val <= 0; + $val = log($val / 4.6875) / log(2) - 8; + return abs($val) > 1e-10 ? $val : 0; + }, + ValueConvInv => '$val ? exp(($val + 8) * log(2)) * 4.6876 : 0', + PrintConv => 'sprintf("%+.3f", $val)', + PrintConvInv => '$val', + }, + 0x0f => { Name => 'GammaCurveOutputRange', Format => 'double[2]', Notes => '16383 max' }, +); + +# Version 4 crop information (ref PH) +%Image::ExifTool::CanonVRD::CropInfo = ( + PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData, + WRITE_PROC => \&Image::ExifTool::WriteBinaryData, + CHECK_PROC => \&Image::ExifTool::CheckBinaryData, + WRITABLE => 1, + FIRST_ENTRY => 0, + FORMAT => 'int32s', + GROUPS => { 2 => 'Image' }, + 0 => { Name => 'CropActive', %noYes }, + 1 => 'CropRotatedOriginalWidth', + 2 => 'CropRotatedOriginalHeight', + 3 => 'CropX', + 4 => 'CropY', + 5 => 'CropWidth', + 6 => 'CropHeight', + 8 => { + Name => 'CropRotation', + Format => 'double', + PrintConv => 'sprintf("%.7g",$val)', + PrintConvInv => '$val', + }, + 0x0a => 'CropOriginalWidth', + 0x0b => 'CropOriginalHeight', + # 0x0c double - value: 100 +); + +# DR4 Stamp Tool tags (ref PH) +%Image::ExifTool::CanonVRD::StampInfo = ( + PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData, + GROUPS => { 2 => 'Image' }, + FORMAT => 'int32u', + FIRST_ENTRY => 0, + 0x02 => 'StampToolCount', +); + +# DR4 dust delete information (ref PH) +%Image::ExifTool::CanonVRD::DustInfo = ( + PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData, + GROUPS => { 2 => 'Image' }, + FORMAT => 'int32u', + FIRST_ENTRY => 0, + 0x02 => { Name => 'DustDeleteApplied', %noYes }, +); + +#------------------------------------------------------------------------------ +# sort DR4 tag ID's for the documentation +sub SortDR4($$) +{ + my ($a, $b) = @_; + my ($aHex, $aDec, $bHex, $bDec); + ($aHex, $aDec) = ($1, $2) if $a =~ /^(0x[0-9a-f]+)?\.?(\d*?)$/; + ($bHex, $bDec) = ($1, $2) if $b =~ /^(0x[0-9a-f]+)?\.?(\d*?)$/; + if ($aHex) { + return 1 unless defined $bDec; # $b is 'header'; + return hex($aHex) <=> hex($bHex) || $aDec <=> $bDec if $bHex; + return hex($aHex) <=> $bDec || 1; + } elsif ($bHex) { + return -1 unless defined $aDec; + return $aDec <=> hex($bHex) || -1; + } else { + return 1 unless defined $bDec; + return -1 unless defined $aDec; + return $aDec <=> $bDec; + } +} + +#------------------------------------------------------------------------------ +# Tone curve print conversion +sub ToneCurvePrint($) +{ + my $val = shift; + my @vals = split ' ', $val; + return $val unless @vals == 21; + my $n = shift @vals; + return $val unless $n >= 2 and $n <= 10; + $val = ''; + while ($n--) { + $val and $val .= ' '; + $val .= '(' . shift(@vals) . ',' . shift(@vals) . ')'; + } + return $val; +} + +#------------------------------------------------------------------------------ +# Inverse print conversion for tone curve +sub ToneCurvePrintInv($) +{ + my $val = shift; + my @vals = ($val =~ /\((\d+),(\d+)\)/g); + return undef unless @vals >= 4 and @vals <= 20 and not @vals & 0x01; + unshift @vals, scalar(@vals) / 2; + while (@vals < 21) { push @vals, 0 } + return join(' ',@vals); +} + +#------------------------------------------------------------------------------ +# Read/Write VRD edit data +# Inputs: 0) ExifTool object ref, 1) dirInfo ref, 2) tag table ref +# Returns: Reading: 1 on success; Writing: modified edit data, or undef if nothing changed +sub ProcessEditData($$$) +{ + my ($et, $dirInfo, $tagTablePtr) = @_; + $et or return 1; # allow dummy access + my $dataPt = $$dirInfo{DataPt}; + my $pos = $$dirInfo{DirStart}; + my $dataPos = $$dirInfo{DataPos}; + my $outfile = $$dirInfo{OutFile}; + my $dirLen = $$dirInfo{DirLen}; + my $verbose = $et->Options('Verbose'); + my $out = $et->Options('TextOut'); + my $oldChanged = $$et{CHANGED}; + + $et->VerboseDir('VRD Edit Data', 0, $dirLen) unless $outfile; + + if ($outfile) { + # make a copy for editing in place + my $buff = substr($$dataPt, $pos, $dirLen); + $dataPt = $$dirInfo{DataPt} = \$buff; + $dataPos += $pos; + $pos = $$dirInfo{DirStart} = 0; + } + my $dirEnd = $pos + $dirLen; + + # loop through all records in the edit data + my ($recNum, $recLen, $err); + for ($recNum=0;; ++$recNum, $pos+=$recLen) { + if ($pos + 4 > $dirEnd) { + last if $pos == $dirEnd; # all done if we arrived at end + $recLen = 0; # just reset record size (will exit loop on test below) + } else { + $recLen = Get32u($dataPt, $pos); + # (DR4 has a null terminator) + last if $recLen == 0 and $pos + 4 == $dirEnd; + } + $pos += 4; # move to start of record + if ($pos + $recLen > $dirEnd) { + $et->Warn('Possibly corrupt CanonVRD Edit record'); + $err = 1; + last; + } + my $saveRecLen = $recLen; + if ($verbose > 1 and not $outfile) { + printf $out "$$et{INDENT}CanonVRD Edit record ($recLen bytes at offset 0x%x)\n", + $pos + $dataPos; + $et->VerboseDump($dataPt, Len => $recLen, Start => $pos, Addr => $pos + $dataPos) if $recNum; + } + + # our edit information is the 0th record, so don't process the others + next if $recNum; + + # process VRD edit information + my $subTablePtr = $tagTablePtr; + my $index; + my %subdirInfo = ( + DataPt => $dataPt, + DataPos => $dataPos, + DirStart => $pos, + DirLen => $recLen, + OutFile => $outfile, + ); + my $subStart = 0; + # loop through various sections of the VRD edit data + for ($index=0; ; ++$index) { + my $tagInfo = $$subTablePtr{$index} or last; + my $subLen; + my $maxLen = $recLen - $subStart; + if ($$tagInfo{Size}) { + $subLen = $$tagInfo{Size}; + } elsif (defined $$tagInfo{Size}) { + # get size from int32u at $subStart + last unless $subStart + 4 <= $recLen; + $subLen = Get32u($dataPt, $subStart + $pos); + $subStart += 4; # skip the length word + } else { + $subLen = $maxLen; + } + $subLen > $maxLen and $subLen = $maxLen; + if ($subLen) { + my $subTable = GetTagTable($$tagInfo{SubDirectory}{TagTable}); + my $subName = $$tagInfo{Name}; + $subdirInfo{DirStart} = $subStart + $pos; + $subdirInfo{DirLen} = $subLen; + $subdirInfo{DirName} = $subName; + if ($outfile) { + # rewrite this section of the VRD edit information + $verbose and print $out " Rewriting Canon $subName\n"; + my $newVal = $et->WriteDirectory(\%subdirInfo, $subTable); + if ($newVal) { + my $sizeDiff = length($newVal) - $subLen; + substr($$dataPt, $pos+$subStart, $subLen) = $newVal; + if ($sizeDiff) { + $subLen = length $newVal; + $recLen += $sizeDiff; + $dirEnd += $sizeDiff; + $dirLen += $sizeDiff; + } + } + } else { + $et->VPrint(0, "$$et{INDENT}$subName (SubDirectory) -->\n"); + $et->VerboseDump($dataPt, + Start => $pos + $subStart, + Addr => $dataPos + $pos + $subStart, + Len => $subLen, + ); + # extract tags from this section of the VRD edit information + $et->ProcessDirectory(\%subdirInfo, $subTable); + } + } + # next section starts at the end of this one + $subStart += $subLen; + } + if ($outfile and $saveRecLen ne $recLen) { + # update record length if necessary + Set32u($recLen, $dataPt, $pos - 4) + } + } + if ($outfile) { + return undef if $oldChanged == $$et{CHANGED}; + return substr($$dataPt, $$dirInfo{DirStart}, $dirLen); + } + return $err ? 0 : 1; +} + +#------------------------------------------------------------------------------ +# Process VRD IHL data +# Inputs: 0) ExifTool object ref, 1) dirInfo ref, 2) tag table ref +# Returns: 1 on success +sub ProcessIHL($$$) +{ + my ($et, $dirInfo, $tagTablePtr) = @_; + my $dataPt = $$dirInfo{DataPt}; + my $dataPos = $$dirInfo{DataPos}; + my $pos = $$dirInfo{DirStart}; + my $dirLen = $$dirInfo{DirLen}; + my $dirEnd = $pos + $dirLen; + + $et->VerboseDir('VRD IHL', 0, $dirLen); + + SetByteOrder('II'); # (make up your mind, Canon!) + while ($pos + 48 <= $dirEnd) { + my $hdr = substr($$dataPt, $pos, 48); + unless ($hdr =~ /^IHL Created Optional Item Data\0\0/) { + $et->Warn('Possibly corrupted VRD IHL data'); + last; + } + my $tag = Get32u($dataPt, $pos + 36); + my $size = Get32u($dataPt, $pos + 40); # size of data in IHL record + my $next = Get32u($dataPt, $pos + 44); # size of complete IHL record + if ($size > $next or $pos + 48 + $next > $dirEnd) { + $et->Warn(sprintf('Bad size for VRD IHL tag 0x%.4x', $tag)); + last; + } + $pos += 48; + $et->HandleTag($tagTablePtr, $tag, substr($$dataPt, $pos, $size), + DataPt => $dataPt, + DataPos => $dataPos, + Start => $pos, + Size => $size + ); + $pos += $next; + } + return 1; +} + +#------------------------------------------------------------------------------ +# Process VRD IHL EXIF data +# Inputs: 0) ExifTool object ref, 1) dirInfo ref, 2) tag table ref +# Returns: 1 on success +sub ProcessIHLExif($$$) +{ + my ($et, $dirInfo, $tagTablePtr) = @_; + $$et{DOC_NUM} = 1; + # the IHL-edited maker notes may look messed up, but the offsets should be OK + my $oldFix = $et->Options(FixBase => 0); + my $rtnVal = $et->ProcessTIFF($dirInfo, $tagTablePtr); + $et->Options(FixBase => $oldFix); + delete $$et{DOC_NUM}; + return $rtnVal; +} + +#------------------------------------------------------------------------------ +# Wrap DR4 data with the VRD header/footer and edit record +# Inputs: 0) DR4 record +# Returns: VRD[Edit[DR4]] data +sub WrapDR4($) +{ + my $val = shift; + my $n = length $val; + my $oldOrder = GetByteOrder(); + SetByteOrder('MM'); + $val = $blankHeader . "\xff\xff\0\xf7" . Set32u($n+8) . Set32u($n) . + $val . "\0\0\0\0" . $blankFooter; + # update the new VRD length in the header/footer + Set32u($n + 16, \$val, 0x18); # (extra 16 bytes for the edit record wrapper) + Set32u($n + 16, \$val, length($val) - 0x2c); + SetByteOrder($oldOrder); + return $val; +} + +#------------------------------------------------------------------------------ +# Read/Write DPP version 4 edit data or DR4 file +# Inputs: 0) ExifTool object ref, 1) dirInfo ref, 2) tag table ref +# Returns: +# Reading from memory (not RAF and not IsWriting): 1 on success +# Editing from memory (not RAF and IsWriting): modified edit data, or undef if nothing changed +# Reading file (RAF and not OutFile): 1 if a valid DR4 file, 0 if not +# Writing file (RAF and OutFile): 1 if valid DR4 file, 0 if not, -1 on write error +# (serves me right for not having a consistent interface for the various modes of operation) +sub ProcessDR4($$;$) +{ + my ($et, $dirInfo, $tagTablePtr) = @_; + $et or return 1; # allow dummy access + my $dataPt = $$dirInfo{DataPt}; + my $raf = $$dirInfo{RAF}; + my $outfile = $$dirInfo{OutFile}; + my $isWriting = $outfile || $$dirInfo{IsWriting}; + my $dataPos = $$dirInfo{DataPos} || 0; + my $verbose = $et->Options('Verbose'); + my $unknown = $et->Options('Unknown'); + my ($pos, $dirLen, $numEntries, $err, $newTags); + + # write CanonDR4 as a block if specified + if ($isWriting) { + my $nvHash; + my $newVal = $et->GetNewValue('CanonDR4', \$nvHash); + if ($newVal) { + $et->VPrint(0, " Writing CanonDR4 as a block\n"); + $$et{DidCanonVRD} = 1; # set flag so we don't add this twice + ++$$et{CHANGED}; + if ($outfile) { + Write($$dirInfo{OutFile}, $newVal) or return -1; + return 1; + } else { + return $newVal; + } + } elsif (not $dataPt and ($nvHash or $$et{DEL_GROUP}{CanonVRD})) { + $et->Error("Can't delete all CanonDR4 information from a DR4 file"); + return 1; + } + } + if ($dataPt) { + $pos = $$dirInfo{DirStart} || 0; + $dirLen = $$dirInfo{DirLen} || length($$dataPt) - $pos; + } else { + # load DR4 file into memory + my $buff; + $raf->Read($buff, 8) == 8 and $buff eq "IIII\x04\0\x04\0" or return 0; + $et->SetFileType(); + $raf->Seek(0, 2) or return $err = 1; + $dirLen = $raf->Tell(); + $raf->Seek(0, 0) or return $err = 1; + $raf->Read($buff, $dirLen) == $dirLen or $err = 1; + $err and $et->Warn('Error reading DR4 file'), return 1; + $tagTablePtr = GetTagTable('Image::ExifTool::CanonVRD::DR4'); + $dataPt = \$buff; + $pos = 0; + } + my $dirEnd = $pos + $dirLen; + + if (($$et{TAGS_FROM_FILE} and + not $$et{EXCL_TAG_LOOKUP}{canondr4}) or $$et{REQ_TAG_LOOKUP}{canondr4}) + { + # extract CanonDR4 block if copying tags, or if requested + $et->FoundTag('CanonDR4', substr($$dataPt, $pos, $dirLen)); + } + + # version 4 header is 32 bytes (int32u[8]) + if ($dirLen < 32) { + $err = 1; + } else { + SetByteOrder(substr($$dataPt, $pos, 2)) or $err = 1; + # process the DR4 header + my %hdrInfo = ( + DataPt => $dataPt, + DirStart => $pos, + DirLen => 32, + DirName => 'DR4Header', + ); + my $hdrTable = GetTagTable('Image::ExifTool::CanonVRD::DR4Header'); + if ($outfile) { + my $hdr = $et->WriteDirectory(\%hdrInfo, $hdrTable); + substr($$dataPt, $pos, 32) = $hdr if $hdr and length $hdr == 32; + } else { + $et->VerboseDir('DR4Header', undef, 32); + $et->ProcessDirectory(\%hdrInfo, $hdrTable); + } + # number of entries in the DR4 directory + $numEntries = Get32u($dataPt, $pos + 28); + $err = 1 if $dirLen < 36 + 28 * $numEntries; + } + $err and $et->Warn('Invalid DR4 directory'), return $outfile ? undef : 0; + + if ($outfile) { + $newTags = $et->GetNewTagInfoHash($tagTablePtr); + } else { + $et->VerboseDir('DR4', $numEntries, $dirLen); + } + + my $index; + for ($index=0; $index<$numEntries; ++$index) { + my ($val, @flg, $i); + my $entry = $pos + 36 + 28 * $index; + last if $entry + 28 > $dirEnd; + my $tag = Get32u($dataPt, $entry); + my $fmt = Get32u($dataPt, $entry + 4); + $flg[0] = Get32u($dataPt, $entry + 8); + $flg[1] = Get32u($dataPt, $entry + 12); + $flg[2] = Get32u($dataPt, $entry + 16); + my $off = Get32u($dataPt, $entry + 20) + $pos; + my $len = Get32u($dataPt, $entry + 24); + next if $off + $len >= $dirEnd; + my $format = $vrdFormat{$fmt}; + if (not $format) { + $val = unpack 'H*', substr($$dataPt, $off, $len); + $format = 'undef'; + } elsif ($format eq 'double' and $len eq 8) { + # avoid teeny weeny values + $val = ReadValue($dataPt, $off, $format, undef, $len); + $val = 0 if abs($val) < 1e-100; + } + if ($outfile) { + # write (binary data) subdirectory if it exists + my $tagInfo = $et->GetTagInfo($tagTablePtr, $tag); + if ($tagInfo and $$tagInfo{SubDirectory}) { + my %subdirInfo = ( + DataPt => $dataPt, + DirStart => $off, + DirLen => $len, + DirName => $$tagInfo{Name}, + ); + my $subTablePtr = GetTagTable($$tagInfo{SubDirectory}{TagTable}); + my $saveChanged = $$et{CHANGED}; + my $dat = $et->WriteDirectory(\%subdirInfo, $subTablePtr); + if (defined $dat and length($dat) == $len) { + substr($$dataPt, $off, $len) = $dat; + } else { + $$et{CHANGED} = $saveChanged; # didn't change anything after all + } + } else { + # loop through main tag and flags (don't yet consider flag 2) + for ($i=-1; $i<2; ++$i) { + $tagInfo = $$newTags{$i>=0 ? sprintf('0x%x.%d',$tag,$i) : $tag}; + next unless $tagInfo; + if ($i >= 0) { + $off = $entry + 8 + 4 * $i; + $format = 'int32u'; + $len = 4; + undef $val; + } + $val = ReadValue($dataPt, $off, $format, undef, $len) unless defined $val; + my $nvHash; + my $newVal = $et->GetNewValue($tagInfo, \$nvHash); + if ($et->IsOverwriting($nvHash, $val) and defined $newVal) { + my $count = int($len / Image::ExifTool::FormatSize($format)); + my $rtnVal = WriteValue($newVal, $format, $count, $dataPt, $off); + if (defined $rtnVal) { + $et->VerboseValue("- CanonVRD:$$tagInfo{Name}", $val); + $et->VerboseValue("+ CanonVRD:$$tagInfo{Name}", $newVal); + ++$$et{CHANGED}; + } + } + } + } + next; + } + $et->HandleTag($tagTablePtr, $tag, $val, + DataPt => $dataPt, + DataPos => $dataPos, + Start => $off, + Size => $len, + Index => $index, + Format => $format, + # $flg[0] is on/off flag + # $flg[1] "is default" flag? + # $flg[2] changed to 0 when some unsharp mask settings were changed + Extra => ", fmt=$fmt flags=" . join(',', @flg), + ); + foreach $i (0..2) { + my $flagID = sprintf('0x%x.%d', $tag, $i); + $et->HandleTag($tagTablePtr, $flagID, $flg[$i]) if $$tagTablePtr{$flagID}; + } + } + return 1 unless $isWriting; + return substr($$dataPt, $pos, $dirLen) unless $raf; + return 1 if Write($outfile, substr($$dataPt, $pos, $dirLen)); + return -1; +} + +#------------------------------------------------------------------------------ +# Read/write Canon VRD file +# Inputs: 0) ExifTool object reference, 1) dirInfo reference +# Returns: 1 if this was a Canon VRD file, 0 otherwise, -1 on write error +sub ProcessVRD($$) +{ + my ($et, $dirInfo) = @_; + my $raf = $$dirInfo{RAF}; + my $buff; + my $num = $raf->Read($buff, 0x1c); + + # initialize write directories if necessary + $et->InitWriteDirs(\%vrdMap, 'XMP') if $$dirInfo{OutFile}; + + if (not $num and $$dirInfo{OutFile}) { + # create new VRD file from scratch + my $newVal = $et->GetNewValue('CanonVRD'); + if ($newVal) { + $et->VPrint(0, " Writing CanonVRD as a block\n"); + Write($$dirInfo{OutFile}, $newVal) or return -1; + $$et{DidCanonVRD} = 1; + ++$$et{CHANGED}; + } else { + # allow VRD to be created from individual tags + if ($$et{ADD_DIRS}{CanonVRD}) { + my $newVal = ''; + if (ProcessCanonVRD($et, { OutFile => \$newVal }) > 0) { + Write($$dirInfo{OutFile}, $newVal) or return -1; + ++$$et{CHANGED}; + return 1; + } + } + $et->Error('No CanonVRD information to write'); + } + } else { + $num == 0x1c or return 0; + $buff =~ /^CANON OPTIONAL DATA\0/ or return 0; + $et->SetFileType(); + $$dirInfo{DirName} = 'CanonVRD'; # set directory name for verbose output + my $result = ProcessCanonVRD($et, $dirInfo); + return $result if $result < 0; + $result or $et->Warn('Format error in VRD file'); + } + return 1; +} + +#------------------------------------------------------------------------------ +# Write VRD data record as a block +# Inputs: 0) ExifTool object ref, 1) dirInfo ref, 2) tag table ref +# Returns: VRD data block (may be empty if no VRD data) +# Notes: Increments ExifTool CHANGED flag if changed +sub WriteCanonVRD($$;$) +{ + my ($et, $dirInfo, $tagTablePtr) = @_; + $et or return 1; # allow dummy access + my $nvHash = $et->GetNewValueHash($Image::ExifTool::Extra{CanonVRD}); + my $val = $et->GetNewValue($nvHash); + $val = '' unless defined $val; + return undef unless $et->IsOverwriting($nvHash, $val); + ++$$et{CHANGED}; + return $val; +} + +#------------------------------------------------------------------------------ +# Read/write CanonVRD information (from VRD file or VRD trailer) +# Inputs: 0) ExifTool object reference, 1) dirInfo reference +# Returns: 1 on success, 0 not valid VRD, or -1 error writing +# - updates DataPos to point to start of CanonVRD information +# - updates DirLen to existing trailer length +sub ProcessCanonVRD($$;$) +{ + my ($et, $dirInfo, $tagTablePtr) = @_; + my $raf = $$dirInfo{RAF}; + my $offset = $$dirInfo{Offset} || 0; + my $outfile = $$dirInfo{OutFile}; + my $dataPt = $$dirInfo{DataPt}; + my $verbose = $et->Options('Verbose'); + my $out = $et->Options('TextOut'); + my ($buff, $created, $err, $blockLen, $blockType, %didDir, $fromFile); +# +# The CanonVRD trailer has a 0x1c-byte header and a 0x40-byte footer, +# each beginning with "CANON OPTIONAL DATA\0" and containing an int32u +# giving the size of the contained data (at byte 0x18 and 0x14 respectively) +# + if ($raf) { + $fromFile = 1; + } else { + unless ($dataPt) { + return 1 unless $outfile; + # create blank VRD data from scratch + my $blank = $blankHeader . $blankFooter; + $dataPt = \$blank; + $verbose and print $out " Creating CanonVRD trailer\n"; + $created = 1; + } + $raf = new File::RandomAccess($dataPt); + } + # read and validate the footer + $raf->Seek(-0x40-$offset, 2) or return 0; + $raf->Read($buff, 0x40) == 0x40 or return 0; + $buff =~ /^CANON OPTIONAL DATA\0(.{4})/s or return 0; + my $dirLen = unpack('N', $1) + 0x5c; # size including header+footer + + # read and validate the header + unless ($dirLen < 0x80000000 and + $raf->Seek(-$dirLen, 1) and + $raf->Read($buff, 0x1c) == 0x1c and + $buff =~ /^CANON OPTIONAL DATA\0/ and + $raf->Seek(-0x1c, 1)) + { + $et->Warn('Bad CanonVRD trailer'); + return 0; + } + # set variables returned in dirInfo hash + $$dirInfo{DataPos} = $raf->Tell(); + $$dirInfo{DirLen} = $dirLen; + + if ($outfile and ref $outfile eq 'SCALAR' and not length $$outfile) { + # write directly to outfile to avoid duplicating data in memory + $$outfile = $$dataPt unless $fromFile; + # TRICKY! -- copy to outfile memory buffer and edit in place + # (so we must disable all Write() calls for this case) + $dataPt = $outfile; + } + if ($fromFile) { + $dataPt = \$buff unless $dataPt; + # read VRD data into memory if necessary + unless ($raf->Read($$dataPt, $dirLen) == $dirLen) { + $$dataPt = '' if $outfile and $outfile eq $dataPt; + $et->Warn('Error reading CanonVRD data'); + return 0; + } + } + # exit quickly if writing and no CanonVRD tags are being edited + if ($outfile and not exists $$et{EDIT_DIRS}{CanonVRD}) { + print $out "$$et{INDENT} [nothing changed]\n" if $verbose; + return 1 if $outfile eq $dataPt; + return Write($outfile, $$dataPt) ? 1 : -1; + } + + my $vrdType = 'VRD'; + + if ($outfile) { + $verbose and not $created and print $out " Rewriting CanonVRD trailer\n"; + # delete CanonVRD information if specified + my $doDel = $$et{DEL_GROUP}{CanonVRD}; + unless ($doDel) { + $doDel = 1 if $$et{DEL_GROUP}{Trailer} and $$et{FILE_TYPE} ne 'VRD'; + unless ($doDel) { + # also delete if writing as a block (will get added back again later) + if ($$et{NEW_VALUE}{$Image::ExifTool::Extra{CanonVRD}}) { + # delete if this isn't version 4 + $doDel = 1 unless $$dataPt =~ /^.{28}\xff\xff\0\xf7/s; + } + if ($$et{NEW_VALUE}{$Image::ExifTool::Extra{CanonDR4}} and not $doDel) { + # delete if this is version 4 + $doDel = 1 if $$dataPt =~ /^.{28}\xff\xff\0\xf7/s; + } + } + } + if ($doDel) { + if ($$et{FILE_TYPE} eq 'VRD') { + my $newVal = $et->GetNewValue('CanonVRD'); + if ($newVal) { + $verbose and print $out " Writing CanonVRD as a block\n"; + if ($outfile eq $dataPt) { + $$outfile = $newVal; + } else { + Write($outfile, $newVal) or return -1; + } + $$et{DidCanonVRD} = 1; + ++$$et{CHANGED}; + } else { + $et->Error("Can't delete all CanonVRD information from a VRD file"); + } + } else { + $verbose and print $out " Deleting CanonVRD trailer\n"; + $$outfile = '' if $outfile eq $dataPt; + ++$$et{CHANGED}; + } + return 1; + } + # write now and return if CanonVRD was set as a block + my $val = $et->GetNewValue('CanonVRD'); + unless ($val) { + $val = $et->GetNewValue('CanonDR4'); + $vrdType = 'DR4' if $val; + } + if ($val) { + $verbose and print $out " Writing Canon$vrdType as a block\n"; + # must wrap DR4 data with the VRD header/footer and edit record + $val = WrapDR4($val) if $vrdType eq 'DR4'; + if ($outfile eq $dataPt) { + $$outfile = $val; + } else { + Write($outfile, $val) or return -1; + } + $$et{DidCanonVRD} = 1; + ++$$et{CHANGED}; + return 1; + } + } elsif ($verbose or $$et{HTML_DUMP}) { + $et->DumpTrailer($dirInfo) if $$dirInfo{RAF}; + } + + $tagTablePtr = GetTagTable('Image::ExifTool::CanonVRD::Main'); + + # validate VRD trailer and get position and length of edit record + SetByteOrder('MM'); # VRD header/footer is big-endian + my $pos = 0x1c; # start at end of header + + # loop through the VRD blocks + for (;;) { + my $end = $dirLen - 0x40; # end of last VRD block (and start of footer) + if ($pos + 8 > $end) { + last if $pos == $end; + $blockLen = $end; # mark as invalid + } else { + $blockType = Get32u($dataPt, $pos); + $blockLen = Get32u($dataPt, $pos + 4); + } + $vrdType = 'DR4' if $blockType eq 0xffff00f7; + $pos += 8; # move to start of block + if ($pos + $blockLen > $end) { + $et->Warn('Possibly corrupt CanonVRD block'); + last; + } + if ($verbose > 1 and not $outfile) { + printf $out " CanonVRD block 0x%.8x ($blockLen bytes at offset 0x%x)\n", + $blockType, $pos + $$dirInfo{DataPos}; + $et->VerboseDump($dataPt, Len => $blockLen, Start => $pos, Addr => $pos + $$dirInfo{DataPos}); + } + my $tagInfo = $$tagTablePtr{$blockType}; + unless ($tagInfo) { + unless ($et->Options('Unknown')) { + $pos += $blockLen; # step to next block + next; + } + my $name = sprintf('CanonVRD_0x%.8x', $blockType); + my $desc = $name; + $desc =~ tr/_/ /; + $tagInfo = { + Name => $name, + Description => $desc, + Binary => 1, + }; + AddTagToTable($tagTablePtr, $blockType, $tagInfo); + } + if ($$tagInfo{SubDirectory}) { + my $subTablePtr = GetTagTable($$tagInfo{SubDirectory}{TagTable}); + my %subdirInfo = ( + DataPt => $dataPt, + DataLen => length $$dataPt, + DataPos => $$dirInfo{DataPos}, + DirStart => $pos, + DirLen => $blockLen, + DirName => $$tagInfo{Name}, + Parent => 'CanonVRD', + OutFile => $outfile, + ); + if ($outfile) { + # set flag indicating we did this directory + $didDir{$$tagInfo{Name}} = 1; + my ($dat, $diff); + if ($$et{NEW_VALUE}{$tagInfo}) { + # write as a block + $et->VPrint(0, "Writing $$tagInfo{Name} as a block\n"); + $dat = $et->GetNewValue($tagInfo); + $dat = '' unless defined $dat; + ++$$et{CHANGED}; + } else { + $dat = $et->WriteDirectory(\%subdirInfo, $subTablePtr); + } + # update data with new directory + if (defined $dat) { + if (length $dat or $$et{FILE_TYPE} !~ /^(CRW|VRD)$/) { + # replace with new block (updating the block length word) + substr($$dataPt, $pos-4, $blockLen+4) = Set32u(length $dat) . $dat; + } else { + # remove block totally (CRW/VRD files only) + substr($$dataPt, $pos-8, $blockLen+8) = ''; + } + # make necessary adjustments if block changes length + if (($diff = length($$dataPt) - $dirLen) != 0) { + $pos += $diff; + $dirLen += $diff; + # update the new VRD length in the header/footer + Set32u($dirLen - 0x5c, $dataPt, 0x18); + Set32u($dirLen - 0x5c, $dataPt, $dirLen - 0x2c); + } + } + } else { + # extract as a block if requested + $et->ProcessDirectory(\%subdirInfo, $subTablePtr); + } + } else { + $et->HandleTag($tagTablePtr, $blockType, substr($$dataPt, $pos, $blockLen)); + } + $pos += $blockLen; # step to next block + } + if ($outfile) { + # create XMP block if necessary (CRW/VRD files only) + if ($$et{ADD_DIRS}{CanonVRD} and not $didDir{XMP}) { + my $subTablePtr = GetTagTable('Image::ExifTool::XMP::Main'); + my $dat = $et->WriteDirectory({ Parent => 'CanonVRD' }, $subTablePtr); + if ($dat) { + my $blockLen = length $dat; + substr($$dataPt, -0x40, 0) = Set32u(0xffff00f6) . Set32u(length $dat) . $dat; + $dirLen = length $$dataPt; + # update the new VRD length in the header/footer + Set32u($dirLen - 0x5c, $dataPt, 0x18); + Set32u($dirLen - 0x5c, $dataPt, $dirLen - 0x2c); + } + } + # write CanonVRD trailer unless it is empty + if (length $$dataPt) { + Write($outfile, $$dataPt) or $err = 1 unless $outfile eq $dataPt; + } else { + $verbose and print $out " Deleting CanonVRD trailer\n"; + } + } elsif ($vrdType eq 'VRD' and (($$et{TAGS_FROM_FILE} and + not $$et{EXCL_TAG_LOOKUP}{canonvrd}) or $$et{REQ_TAG_LOOKUP}{canonvrd})) + { + # extract CanonVRD block if copying tags, or if requested (and not DR4 info) + $et->FoundTag('CanonVRD', $buff); + } + undef $buff; + return $err ? -1 : 1; +} + +1; # end + +__END__ + +=head1 NAME + +Image::ExifTool::CanonVRD - Read/write Canon VRD and DR4 information + +=head1 SYNOPSIS + +This module is used by Image::ExifTool + +=head1 DESCRIPTION + +This module contains definitions required by Image::ExifTool to read and +write VRD and DR4 Recipe Data information as written by the Canon Digital +Photo Professional software. This information is written to VRD and DR4 +files, and as a trailer in JPEG, CRW, CR2 and TIFF images. + +=head1 AUTHOR + +Copyright 2003-2019, Phil Harvey (phil at owl.phy.queensu.ca) + +This library is free software; you can redistribute it and/or modify it +under the same terms as Perl itself. + +=head1 ACKNOWLEDGEMENTS + +Thanks to Bogdan and Gert Kello for decoding some tags. + +=head1 SEE ALSO + +L<Image::ExifTool::TagNames/CanonVRD Tags>, +L<Image::ExifTool(3pm)|Image::ExifTool> + +=cut + diff --git a/lib/Image/ExifTool/CaptureOne.pm b/lib/Image/ExifTool/CaptureOne.pm new file mode 100644 index 0000000..576dbd7 --- /dev/null +++ b/lib/Image/ExifTool/CaptureOne.pm @@ -0,0 +1,235 @@ +#------------------------------------------------------------------------------ +# File: CaptureOne.pm +# +# Description: Read Capture One EIP and COS files +# +# Revisions: 2009/11/01 - P. Harvey Created +# +# Notes: The EIP format is a ZIP file containing an image (IIQ or TIFF) +# and some settings files (COS). COS files are XML based. +#------------------------------------------------------------------------------ + +package Image::ExifTool::CaptureOne; + +use strict; +use vars qw($VERSION); +use Image::ExifTool qw(:DataAccess :Utils); +use Image::ExifTool::XMP; +use Image::ExifTool::ZIP; + +$VERSION = '1.04'; + +# CaptureOne COS XML tags +# - tags are added dynamically when encountered +# - this table is not listed in tag name docs +%Image::ExifTool::CaptureOne::Main = ( + GROUPS => { 0 => 'XML', 1 => 'XML', 2 => 'Image' }, + PROCESS_PROC => \&Image::ExifTool::XMP::ProcessXMP, + VARS => { NO_ID => 1 }, + ColorCorrections => { ValueConv => '\$val' }, # (long list of floating point numbers) +); + +#------------------------------------------------------------------------------ +# We found an XMP property name/value +# Inputs: 0) attribute list ref, 1) attr hash ref, +# 2) property name ref, 3) property value ref +# Returns: true if value was changed +sub HandleCOSAttrs($$$$) +{ + my ($attrList, $attrs, $prop, $valPt) = @_; + my $changed; + if (not length $$valPt and defined $$attrs{K} and defined $$attrs{V}) { + $$prop = $$attrs{K}; + $$valPt = $$attrs{V}; + # remove these attributes from the list + my @attrs = @$attrList; + @$attrList = ( ); + my $a; + foreach $a (@attrs) { + if ($a eq 'K' or $a eq 'V') { + delete $$attrs{$a}; + } else { + push @$attrList, $a; + } + } + $changed = 1; + } + return $changed; +} + +#------------------------------------------------------------------------------ +# We found a COS property name/value +# Inputs: 0) ExifTool object ref, 1) tag table ref +# 2) reference to array of XMP property names (last is current property) +# 3) property value, 4) attribute hash ref (not used here) +# Returns: 1 if valid tag was found +sub FoundCOS($$$$;$) +{ + my ($et, $tagTablePtr, $props, $val, $attrs) = @_; + + my $tag = $$props[-1]; + unless ($$tagTablePtr{$tag}) { + $et->VPrint(0, " | [adding $tag]\n"); + my $name = ucfirst $tag; + $name =~ tr/-_a-zA-Z0-9//dc; + return 0 unless length $tag; + my %tagInfo = ( Name => $tag ); + # try formatting any tag with "Date" in the name as a date + # (shouldn't affect non-date tags) + if ($name =~ /Date(?![a-z])/) { + $tagInfo{Groups} = { 2 => 'Time' }; + $tagInfo{ValueConv} = 'Image::ExifTool::XMP::ConvertXMPDate($val,1)'; + $tagInfo{PrintConv} = '$self->ConvertDateTime($val)'; + } + AddTagToTable($tagTablePtr, $tag, \%tagInfo); + } + # convert from UTF8 to ExifTool Charset + $val = $et->Decode($val, "UTF8"); + # un-escape XML character entities + $val = Image::ExifTool::XMP::UnescapeXML($val); + $et->HandleTag($tagTablePtr, $tag, $val); + return 0; +} + +#------------------------------------------------------------------------------ +# Extract information from a COS file +# Inputs: 0) ExifTool object reference, 1) dirInfo reference +# Returns: 1 on success, 0 if this wasn't a valid XML file +sub ProcessCOS($$) +{ + my ($et, $dirInfo) = @_; + + # process using XMP module, but override handling of attributes and tags + $$dirInfo{XMPParseOpts} = { + AttrProc => \&HandleCOSAttrs, + FoundProc => \&FoundCOS, + }; + my $tagTablePtr = GetTagTable('Image::ExifTool::CaptureOne::Main'); + my $success = $et->ProcessDirectory($dirInfo, $tagTablePtr); + delete $$dirInfo{XMLParseArgs}; + return $success; +} + +#------------------------------------------------------------------------------ +# Extract information from a CaptureOne EIP file +# Inputs: 0) ExifTool object reference, 1) dirInfo reference +# Returns: 1 +# Notes: Upon entry to this routine, the file type has already been verified +# and the dirInfo hash contains a ZIP element unique to this process proc: +# ZIP - reference to Archive::Zip object for this file +sub ProcessEIP($$) +{ + my ($et, $dirInfo) = @_; + my $zip = $$dirInfo{ZIP}; + my ($file, $buff, $status, $member, %parseFile); + + $et->SetFileType('EIP'); + + # must catch all Archive::Zip warnings + local $SIG{'__WARN__'} = \&Image::ExifTool::ZIP::WarnProc; + # find all manifest files + my @members = $zip->membersMatching('^manifest\d*.xml$'); + # and choose the one with the highest version number (any better ideas?) + while (@members) { + my $m = shift @members; + my $f = $m->fileName(); + next if $file and $file gt $f; + $member = $m; + $file = $f; + } + # get file names from our chosen manifest file + if ($member) { + ($buff, $status) = $zip->contents($member); + if (not $status) { + my $foundImage; + while ($buff =~ m{<(RawPath|SettingsPath)>(.*?)</\1>}sg) { + $file = $2; + next unless $file =~ /\.(cos|iiq|jpe?g|tiff?)$/i; + $parseFile{$file} = 1; # set flag to parse this file + $foundImage = 1 unless $file =~ /\.cos$/i; + } + # ignore manifest unless it contained a valid image + undef %parseFile unless $foundImage; + } + } + # extract meta information from embedded files + my $docNum = 0; + @members = $zip->members(); # get all members + foreach $member (@members) { + # get filename of this ZIP member + $file = $member->fileName(); + next unless defined $file; + $et->VPrint(0, "File: $file\n"); + # set the document number and extract ZIP tags + $$et{DOC_NUM} = ++$docNum; + Image::ExifTool::ZIP::HandleMember($et, $member); + if (%parseFile) { + next unless $parseFile{$file}; + } else { + # reading the manifest didn't work, so look for image files in the + # root directory and .cos files in the CaptureOne directory + next unless $file =~ m{^([^/]+\.(iiq|jpe?g|tiff?)|CaptureOne/.*\.cos)$}i; + } + # extract the contents of the file + # Note: this could use a LOT of memory here for RAW images... + ($buff, $status) = $zip->contents($member); + $status and $et->Warn("Error extracting $file"), next; + if ($file =~ /\.cos$/i) { + # process Capture One Settings files + my %dirInfo = ( + DataPt => \$buff, + DirLen => length $buff, + DataLen => length $buff, + ); + ProcessCOS($et, \%dirInfo); + } else { + # set HtmlDump error if necessary because it doesn't work with embedded files + if ($$et{HTML_DUMP}) { + $$et{HTML_DUMP}{Error} = "Sorry, can't dump images embedded in ZIP files"; + } + # process IIQ, JPEG and TIFF images + $et->ExtractInfo(\$buff, { ReEntry => 1 }); + } + undef $buff; # (free memory now) + } + delete $$et{DOC_NUM}; + return 1; +} + +1; # end + +__END__ + +=head1 NAME + +Image::ExifTool::CaptureOne - Read Capture One EIP and COS files + +=head1 SYNOPSIS + +This module is used by Image::ExifTool + +=head1 DESCRIPTION + +This module contains definitions required by Image::ExifTool to extract meta +information from Capture One EIP (Enhanced Image Package) and COS (Capture +One Settings) files. + +=head1 NOTES + +The EIP format is a ZIP file containing an image (IIQ or TIFF) and some +settings files (COS). + +=head1 AUTHOR + +Copyright 2003-2019, Phil Harvey (phil at owl.phy.queensu.ca) + +This library is free software; you can redistribute it and/or modify it +under the same terms as Perl itself. + +=head1 SEE ALSO + +L<Image::ExifTool::TagNames/ZIP Tags>, +L<Image::ExifTool(3pm)|Image::ExifTool> + +=cut + diff --git a/lib/Image/ExifTool/Casio.pm b/lib/Image/ExifTool/Casio.pm new file mode 100644 index 0000000..4fbad47 --- /dev/null +++ b/lib/Image/ExifTool/Casio.pm @@ -0,0 +1,2060 @@ +#------------------------------------------------------------------------------ +# File: Casio.pm +# +# Description: Casio EXIF maker notes tags +# +# Revisions: 12/09/2003 - P. Harvey Created +# 09/10/2004 - P. Harvey Added MakerNote2 (thanks to Joachim Loehr) +# +# References: 1) http://park2.wakwak.com/~tsuruzoh/Computer/Digicams/exif-e.html +# 2) Joachim Loehr private communication +# 3) http://homepage3.nifty.com/kamisaka/makernote/makernote_casio.htm +# 4) http://gvsoft.homedns.org/exif/makernote-casio-type1.html +# 5) Robert Chi private communication (EX-F1) +# 6) http://u88.n24.queensu.ca/exiftool/forum/index.php/topic,3701.html +# JD) Jens Duttke private communication +#------------------------------------------------------------------------------ + +package Image::ExifTool::Casio; + +use strict; +use vars qw($VERSION); +use Image::ExifTool::Exif; + +$VERSION = '1.38'; + +# older Casio maker notes (ref 1) +%Image::ExifTool::Casio::Main = ( + WRITE_PROC => \&Image::ExifTool::Exif::WriteExif, + CHECK_PROC => \&Image::ExifTool::Exif::CheckExif, + WRITABLE => 1, + GROUPS => { 0 => 'MakerNotes', 2 => 'Camera' }, + 0x0001 => { + Name => 'RecordingMode' , + Writable => 'int16u', + PrintConv => { + 1 => 'Single Shutter', + 2 => 'Panorama', + 3 => 'Night Scene', + 4 => 'Portrait', + 5 => 'Landscape', + 7 => 'Panorama', #4 + 10 => 'Night Scene', #4 + 15 => 'Portrait', #4 + 16 => 'Landscape', #4 + }, + }, + 0x0002 => { + Name => 'Quality', + Writable => 'int16u', + PrintConv => { 1 => 'Economy', 2 => 'Normal', 3 => 'Fine' }, + }, + 0x0003 => { + Name => 'FocusMode', + Writable => 'int16u', + PrintConv => { + 2 => 'Macro', + 3 => 'Auto', + 4 => 'Manual', + 5 => 'Infinity', + 7 => 'Spot AF', #4 + }, + }, + 0x0004 => [ + { + Name => 'FlashMode', + Condition => '$self->{Model} =~ /^QV-(3500EX|8000SX)/', + Writable => 'int16u', + PrintConv => { + 1 => 'Auto', + 2 => 'On', + 3 => 'Off', + 4 => 'Off', #4 + 5 => 'Red-eye Reduction', #4 + }, + }, + { + Name => 'FlashMode', + Writable => 'int16u', + PrintConv => { + 1 => 'Auto', + 2 => 'On', + 3 => 'Off', + 4 => 'Red-eye Reduction', + }, + }, + ], + 0x0005 => { + Name => 'FlashIntensity', + Writable => 'int16u', + PrintConv => { + 11 => 'Weak', + 12 => 'Low', #4 + 13 => 'Normal', + 14 => 'High', #4 + 15 => 'Strong', + }, + }, + 0x0006 => { + Name => 'ObjectDistance', + Writable => 'int32u', + ValueConv => '$val / 1000', #4 + ValueConvInv => '$val * 1000', + PrintConv => '"$val m"', + PrintConvInv => '$val=~s/\s*m$//;$val', + }, + 0x0007 => { + Name => 'WhiteBalance', + Writable => 'int16u', + PrintConv => { + 1 => 'Auto', + 2 => 'Tungsten', + 3 => 'Daylight', + 4 => 'Fluorescent', + 5 => 'Shade', + 129 => 'Manual', + }, + }, + # 0x0009 Bulb? (ref unknown) + 0x000a => { + Name => 'DigitalZoom', + Writable => 'int32u', + PrintHex => 1, + PrintConv => { + 0x10000 => 'Off', + 0x10001 => '2x', + 0x19999 => '1.6x', #4 + 0x20000 => '2x', #4 + 0x33333 => '3.2x', #4 + 0x40000 => '4x', #4 + }, + }, + 0x000b => { + Name => 'Sharpness', + Writable => 'int16u', + PrintConv => { + 0 => 'Normal', + 1 => 'Soft', + 2 => 'Hard', + 16 => 'Normal', #4 + 17 => '+1', #4 + 18 => '-1', #4 + }, + }, + 0x000c => { + Name => 'Contrast', + Writable => 'int16u', + PrintConv => { + 0 => 'Normal', + 1 => 'Low', + 2 => 'High', + 16 => 'Normal', #4 + 17 => '+1', #4 + 18 => '-1', #4 + }, + }, + 0x000d => { + Name => 'Saturation', + Writable => 'int16u', + PrintConv => { + 0 => 'Normal', + 1 => 'Low', + 2 => 'High', + 16 => 'Normal', #4 + 17 => '+1', #4 + 18 => '-1', #4 + }, + }, + 0x0014 => { + Name => 'ISO', + Writable => 'int16u', + Priority => 0, + }, + 0x0015 => { #JD (Similar to Type2 0x2001) + Name => 'FirmwareDate', + Writable => 'string', + Format => 'undef', # the 'string' contains nulls + Count => 18, + PrintConv => q{ + $_ = $val; + if (/^(\d{2})(\d{2})\0\0(\d{2})(\d{2})\0\0(\d{2})(.{2})\0{2}$/) { + my $yr = $1 + ($1 < 70 ? 2000 : 1900); + my $sec = $6; + $val = "$yr:$2:$3 $4:$5"; + $val .= ":$sec" if $sec=~/^\d{2}$/; + return $val; + } + tr/\0/./; s/\.+$//; + return "Unknown ($_)"; + }, + PrintConvInv => q{ + $_ = $val; + if (/^(19|20)(\d{2}):(\d{2}):(\d{2}) (\d{2}):(\d{2})$/) { + return "$2$3\0\0$4$5\0\0$6\0\0\0\0"; + } elsif (/^Unknown\s*\((.*)\)$/i) { + $_ = $1; tr/./\0/; + return $_; + } else { + return undef; + } + }, + }, + 0x0016 => { #4 + Name => 'Enhancement', + Writable => 'int16u', + PrintConv => { + 1 => 'Off', + 2 => 'Red', + 3 => 'Green', + 4 => 'Blue', + 5 => 'Flesh Tones', + }, + }, + 0x0017 => { #4 + Name => 'ColorFilter', + Writable => 'int16u', + PrintConv => { + 1 => 'Off', + 2 => 'Black & White', + 3 => 'Sepia', + 4 => 'Red', + 5 => 'Green', + 6 => 'Blue', + 7 => 'Yellow', + 8 => 'Pink', + 9 => 'Purple', + }, + }, + 0x0018 => { #4 + Name => 'AFPoint', + Writable => 'int16u', + Notes => 'may not be valid for all models', #JD + PrintConv => { + 1 => 'Center', + 2 => 'Upper Left', + 3 => 'Upper Right', + 4 => 'Near Left/Right of Center', + 5 => 'Far Left/Right of Center', + 6 => 'Far Left/Right of Center/Bottom', + 7 => 'Top Near-left', + 8 => 'Near Upper/Left', + 9 => 'Top Near-right', + 10 => 'Top Left', + 11 => 'Top Center', + 12 => 'Top Right', + 13 => 'Center Left', + 14 => 'Center Right', + 15 => 'Bottom Left', + 16 => 'Bottom Center', + 17 => 'Bottom Right', + }, + }, + 0x0019 => { #4 + Name => 'FlashIntensity', + Writable => 'int16u', + PrintConv => { + 1 => 'Normal', + 2 => 'Weak', + 3 => 'Strong', + }, + }, + 0x0e00 => { + Name => 'PrintIM', + Description => 'Print Image Matching', + # crazy I know, but the offset for this value is entry-based + # (QV-2100, QV-2900UX, QV-3500EX and QV-4000) even though the + # offsets for other values isn't + EntryBased => 1, + SubDirectory => { + TagTable => 'Image::ExifTool::PrintIM::Main', + }, + }, +); + +# ref 2: +%Image::ExifTool::Casio::Type2 = ( + WRITE_PROC => \&Image::ExifTool::Exif::WriteExif, + CHECK_PROC => \&Image::ExifTool::Exif::CheckExif, + WRITABLE => 1, + GROUPS => { 0 => 'MakerNotes', 2 => 'Camera' }, + 0x0002 => { + Name => 'PreviewImageSize', + Groups => { 2 => 'Image' }, + Writable => 'int16u', + Count => 2, + PrintConv => '$val =~ tr/ /x/; $val', + PrintConvInv => '$val =~ tr/x/ /; $val', + }, + 0x0003 => { + Name => 'PreviewImageLength', + Groups => { 2 => 'Image' }, + OffsetPair => 0x0004, # point to associated offset + DataTag => 'PreviewImage', + Writable => 'int32u', + WriteGroup => 'MakerNotes', + Protected => 2, + }, + 0x0004 => { + Name => 'PreviewImageStart', + Groups => { 2 => 'Image' }, + Flags => 'IsOffset', + OffsetPair => 0x0003, # point to associated byte count + DataTag => 'PreviewImage', + Writable => 'int32u', + WriteGroup => 'MakerNotes', + Protected => 2, + }, + 0x0008 => { + Name => 'QualityMode', + Writable => 'int16u', + PrintConv => { + 0 => 'Economy', + 1 => 'Normal', + 2 => 'Fine', + }, + }, + 0x0009 => { + Name => 'CasioImageSize', + Groups => { 2 => 'Image' }, + Writable => 'int16u', + PrintConv => { + 0 => '640x480', + 4 => '1600x1200', + 5 => '2048x1536', + 20 => '2288x1712', + 21 => '2592x1944', + 22 => '2304x1728', + 36 => '3008x2008', + }, + }, + 0x000d => { + Name => 'FocusMode', + Writable => 'int16u', + PrintConv => { + 0 => 'Normal', + 1 => 'Macro', + }, + }, + 0x0014 => { + Name => 'ISO', + Writable => 'int16u', + Priority => 0, + PrintConv => { + 3 => 50, + 4 => 64, + 6 => 100, + 9 => 200, + }, + }, + 0x0019 => { + Name => 'WhiteBalance', + Writable => 'int16u', + PrintConv => { + 0 => 'Auto', + 1 => 'Daylight', + 2 => 'Shade', + 3 => 'Tungsten', + 4 => 'Fluorescent', + 5 => 'Manual', + }, + }, + 0x001d => { + Name => 'FocalLength', + Writable => 'rational64u', + PrintConv => 'sprintf("%.1f mm",$val)', + PrintConvInv => '$val=~s/\s*mm$//;$val', + }, + 0x001f => { + Name => 'Saturation', + Writable => 'int16u', + PrintConv => { + 0 => 'Low', + 1 => 'Normal', + 2 => 'High', + }, + }, + 0x0020 => { + Name => 'Contrast', + Writable => 'int16u', + PrintConv => { + 0 => 'Low', + 1 => 'Normal', + 2 => 'High', + }, + }, + 0x0021 => { + Name => 'Sharpness', + Writable => 'int16u', + PrintConv => { + 0 => 'Soft', + 1 => 'Normal', + 2 => 'Hard', + }, + }, + 0x0e00 => { + Name => 'PrintIM', + Description => 'Print Image Matching', + Writable => 0, + SubDirectory => { + TagTable => 'Image::ExifTool::PrintIM::Main', + }, + }, + 0x2000 => { + # this image data is also referenced by tags 3 and 4 + # (nasty that they double-reference the image!) + %Image::ExifTool::previewImageTagInfo, + Groups => { 2 => 'Preview' }, + }, + 0x2001 => { #PH + # I downloaded images from 12 different EX-Z50 cameras, and they showed + # only 3 distinct dates here (2004:08:31 18:55, 2004:09:13 14:14, and + # 2004:11:26 17:07), so I'm guessing this is a firmware version date - PH + Name => 'FirmwareDate', + Writable => 'string', + Format => 'undef', # the 'string' contains nulls + Count => 18, + PrintConv => q{ + $_ = $val; + if (/^(\d{2})(\d{2})\0\0(\d{2})(\d{2})\0\0(\d{2})\0{4}$/) { + my $yr = $1 + ($1 < 70 ? 2000 : 1900); + return "$yr:$2:$3 $4:$5"; + } + tr/\0/./; s/\.+$//; + return "Unknown ($_)"; + }, + PrintConvInv => q{ + $_ = $val; + if (/^(19|20)(\d{2}):(\d{2}):(\d{2}) (\d{2}):(\d{2})$/) { + return "$2$3\0\0$4$5\0\0$6\0\0\0\0"; + } elsif (/^Unknown\s*\((.*)\)$/i) { + $_ = $1; tr/./\0/; + return $_; + } else { + return undef; + } + }, + }, + 0x2011 => { + Name => 'WhiteBalanceBias', + Writable => 'int16u', + Count => 2, + }, + 0x2012 => { + Name => 'WhiteBalance', + Writable => 'int16u', + PrintConv => { + 0 => 'Manual', + 1 => 'Daylight', #3 + 2 => 'Cloudy', #PH (EX-ZR20, NC) + 3 => 'Shade', #3 + 4 => 'Flash?', + 6 => 'Fluorescent', #3 + 9 => 'Tungsten?', #PH (EX-Z77) + 10 => 'Tungsten', #3 + 12 => 'Flash', + }, + }, + 0x2021 => { #JD (guess) + Name => 'AFPointPosition', + Writable => 'int16u', + Count => 4, + PrintConv => q{ + my @v = split ' ', $val; + return 'n/a' if $v[0] == 65535 or not $v[1] or not $v[3]; + sprintf "%.2g %.2g", $v[0]/$v[1], $v[2]/$v[3]; + }, + }, + 0x2022 => { + Name => 'ObjectDistance', + Writable => 'int32u', + ValueConv => '$val >= 0x20000000 ? "inf" : $val / 1000', + ValueConvInv => '$val eq "inf" ? 0x20000000 : $val * 1000', + PrintConv => '$val eq "inf" ? $val : "$val m"', + PrintConvInv => '$val=~s/\s*m$//;$val', + }, + # 0x2023 looks interesting (values 0,1,2,3,5 in samples) - PH + # - 1 for makeup mode shots (portrait?) (EX-Z450) + 0x2034 => { + Name => 'FlashDistance', + Writable => 'int16u', + }, + # 0x203e - normally 62000, but 62001 for anti-shake mode - PH + 0x2076 => { #PH (EX-Z450) + # ("Enhancement" was taken already, so call this "SpecialEffect" for lack of a better name) + Name => 'SpecialEffectMode', + Writable => 'int8u', + Count => 3, + PrintConv => { + '0 0 0' => 'Off', + '1 0 0' => 'Makeup', + '2 0 0' => 'Mist Removal', + '3 0 0' => 'Vivid Landscape', + # have also seen '1 1 1', '2 2 4', '4 3 3', '4 4 4' + # '0 0 14' and '0 0 42' - premium auto night shot (EX-Z2300) + # and '0 0 2' for Art HDR + }, + }, + 0x2089 => [ #PH + { + Name => 'FaceInfo1', + Condition => '$$valPt =~ /^(\0\0|.\x02\x80\x01\xe0)/s', # (EX-H5) + SubDirectory => { + TagTable => 'Image::ExifTool::Casio::FaceInfo1', + ByteOrder => 'BigEndian', + }, + },{ + Name => 'FaceInfo2', + Condition => '$$valPt =~ /^\x02\x01/', # (EX-H20G,EX-ZR100) + SubDirectory => { + TagTable => 'Image::ExifTool::Casio::FaceInfo2', + ByteOrder => 'LittleEndian', + }, + },{ + Name => 'FaceInfoUnknown', + Unknown => 1, + }, + ], + # 0x208a - also some sort of face detection information - PH + 0x211c => { #PH + Name => 'FacesDetected', + Format => 'int8u', + }, + 0x3000 => { + Name => 'RecordMode', + Writable => 'int16u', + PrintConv => { + 2 => 'Program AE', #3 + 3 => 'Shutter Priority', #3 + 4 => 'Aperture Priority', #3 + 5 => 'Manual', #3 + 6 => 'Best Shot', #3 + 17 => 'Movie', #PH (UHQ?) + 19 => 'Movie (19)', #PH (HQ?, EX-P505) + 20 => 'YouTube Movie', #PH + '2 0' => 'Program AE', #PH (NC) + '3 0' => 'Shutter Priority', #PH (NC) + '4 0' => 'Aperture Priority', #PH (NC) + '5 0' => 'Manual', #PH (NC) + '6 0' => 'Best Shot', #PH (NC) + }, + }, + 0x3001 => { #3 + Name => 'ReleaseMode', + Writable => 'int16u', + PrintConv => { + 1 => 'Normal', + 3 => 'AE Bracketing', + 11 => 'WB Bracketing', + 13 => 'Contrast Bracketing', #(not sure about translation - PH) + 19 => 'High Speed Burst', #PH (EX-FH25, 40fps) + # have also seen: 2, 7(common), 14, 18 - PH + }, + }, + 0x3002 => { + Name => 'Quality', + Writable => 'int16u', + PrintConv => { + 1 => 'Economy', + 2 => 'Normal', + 3 => 'Fine', + }, + }, + 0x3003 => { + Name => 'FocusMode', + Writable => 'int16u', + PrintConv => { + 0 => 'Manual', #(guess at translation) + 1 => 'Focus Lock', #(guess at translation) + 2 => 'Macro', #3 + 3 => 'Single-Area Auto Focus', + 5 => 'Infinity', #PH + 6 => 'Multi-Area Auto Focus', + 8 => 'Super Macro', #PH (EX-Z2300) + }, + }, + 0x3006 => { + Name => 'HometownCity', + Writable => 'string', + }, + # unfortunately the BestShotMode numbers are model-dependent - PH + #http://search.casio-intl.com/search?q=BEST+SHOT+sets+up+the+camera+CASIO+EX+ZR100+BEST+SHOT&btnG=Search&output=xml_no_dtd&oe=UTF-8&ie=UTF-8&site=casio-intl_com&client=search_casio-intl_com&proxystylesheet=search_casio-intl_com + # NOTE: BestShotMode is not used unless RecordMode is "Best Shot" + 0x3007 => [{ + Name => 'BestShotMode', + Writable => 'int16u', + Condition => '$$self{Model} eq "EX-FC100"', + Notes => 'EX-FC100', + PrintConvColumns => 2, + PrintConv => { + 0 => 'Off', + 1 => 'Auto', + 2 => 'Portrait', + 3 => 'Scenery', + 4 => 'Portrait with Scenery', + 5 => 'Children', + 6 => 'Sports', + 7 => 'Pet', + 8 => 'Flower', + 9 => 'Natural Green', + 10 => 'Autumn Leaves', + 11 => 'Sundown', + 12 => 'High Speed Night Scene', + 13 => 'Night Scene Portrait', + 14 => 'Fireworks', + 15 => 'High Speed Anti Shake', + 16 => 'Multi-motion Image', + 17 => 'High Speed Best Selection', + 18 => 'Move Out CS', + 19 => 'Move In CS', + 20 => 'Pre-record Movie', + 21 => 'For YouTube', + }, + },{ + Name => 'BestShotMode', + Writable => 'int16u', + Condition => '$$self{Model} eq "EX-FC150"', + Notes => 'EX-FC150', + PrintConvColumns => 2, + PrintConv => { + 0 => 'Off', + 1 => 'Auto', + 2 => 'Expression CS', + 3 => 'Baby CS', + 4 => 'Child CS', + 5 => 'Pet CS', + 6 => 'Sports CS', + 7 => 'Child High Speed Movie', + 8 => 'Pet High Speed Movie', + 9 => 'Sports High Speed Movie', + 10 => 'Lag Correction', + 11 => 'High Speed Lighting', + 12 => 'High Speed Night Scene', + 13 => 'High Speed Night Scene and Portrait', + 14 => 'High Speed Anti Shake', + 15 => 'High Speed Best Selection', + 16 => 'Portrait', + 17 => 'Scenery', + 18 => 'Portrait With Scenery', + 19 => 'Flower', + 20 => 'Natural Green', + 21 => 'Autumn Leaves', + 22 => 'Sundown', + 23 => 'Fireworks', + 24 => 'Multi-motion Image', + 25 => 'Move Out CS', + 26 => 'Move In CS', + 27 => 'Pre-record Movie', + 28 => 'For YouTube', + }, + },{ + Name => 'BestShotMode', + Writable => 'int16u', + Condition => '$$self{Model} eq "EX-FC200S"', + Notes => 'EX-FC200S', + PrintConvColumns => 2, + PrintConv => { + 0 => 'Off', + 1 => 'Slow Motion Swing (behind)', + 2 => 'Slow Motion Swing (front)', + 3 => 'Self Slow Motion (behind)', + 4 => 'Self Slow Motion (front)', + 5 => 'Swing Burst', + 6 => 'HDR', + 7 => 'HDR Art', + 8 => 'High Speed Night Scene', + 9 => 'High Speed Night Scene and Portrait', + 10 => 'High Speed Anti Shake', + 11 => 'Multi SR Zoom', + 12 => 'Blurred Background', + 13 => 'Wide Shot', + 14 => 'Slide Panorama', + 15 => 'High Speed Best Selection', + 16 => 'Lag Correction', + 17 => 'High Speed CS', + 18 => 'Child CS', + 19 => 'Pet CS', + 20 => 'Sports CS', + 21 => 'Child High Speed Movie', + 22 => 'Pet High Speed Movie', + 23 => 'Sports High Speed Movie', + 24 => 'Portrait', + 25 => 'Scenery', + 26 => 'Portrait with Scenery', + 27 => 'Children', + 28 => 'Sports', + 29 => 'Candlelight Portrait', + 30 => 'Party', + 31 => 'Pet', + 32 => 'Flower', + 33 => 'Natural Green', + 34 => 'Autumn Leaves', + 35 => 'Soft Flowing Water', + 36 => 'Splashing Water', + 37 => 'Sundown', + 38 => 'Fireworks', + 39 => 'Food', + 40 => 'Text', + 41 => 'Collection', + 42 => 'Auction', + 43 => 'Pre-record Movie', + 44 => 'For YouTube', + }, + },{ + Name => 'BestShotMode', + Writable => 'int16u', + Condition => '$$self{Model} eq "EX-FH100"', + Notes => 'EX-FH100', + PrintConvColumns => 2, + PrintConv => { + 0 => 'Off', + 1 => 'Expression CS', + 2 => 'Baby CS', + 3 => 'Child CS', + 4 => 'Pet CS', + 5 => 'Sports CS', + 6 => 'Child High Speed Movie', + 7 => 'Pet High Speed Movie', + 8 => 'Sports High Speed Movie', + 9 => 'Lag Correction', + 10 => 'High Speed Lighting', + 11 => 'High Speed Night Scene', + 12 => 'High Speed Night Scene and Portrait', + 13 => 'High Speed Anti Shake', + 14 => 'High Speed Best Selection', + 15 => 'Portrait', + 16 => 'Scenery', + 17 => 'Portrait With Scenery', + 18 => 'Flower', + 19 => 'Natural Green', + 20 => 'Autumn Leaves', + 21 => 'Sundown', + 22 => 'Fireworks', + 23 => 'Multi-motion Image', + 24 => 'Move Out CS', + 25 => 'Move In CS', + 26 => 'Pre-record Movie', + 27 => 'For YouTube', + }, + },{ + Name => 'BestShotMode', + Writable => 'int16u', + Condition => '$$self{Model} eq "EX-G1"', + Notes => 'EX-G1', + PrintConvColumns => 3, + PrintConv => { + 0 => 'Off', + 1 => 'Auto', + 2 => 'Auto Best Shot', + 3 => 'Dynamic Photo', + 4 => 'Interval Snapshot', + 5 => 'Interval Movie', + 6 => 'Portrait', + 7 => 'Scenery', + 8 => 'Portrait with Scenery', + 9 => 'Underwater', + 10 => 'Beach', + 11 => 'Snow', + 12 => 'Children', + 13 => 'Sports', + 14 => 'Pet', + 15 => 'Flower', + 16 => 'Sundown', + 17 => 'Night Scene', + 18 => 'Night Scene Portrait', + 19 => 'Fireworks', + 20 => 'Food', + 21 => 'For eBay', + 22 => 'Multi-motion Image', + 23 => 'Pre-record Movie', + 24 => 'For YouTube', + 25 => 'Voice Recording', + }, + },{ + Name => 'BestShotMode', + Writable => 'int16u', + Condition => '$$self{Model} eq "EX-S10"', + Notes => 'EX-S10', + PrintConvColumns => 3, + PrintConv => { + 0 => 'Off', + 1 => 'Auto', + 2 => 'Portrait', + 3 => 'Scenery', + 4 => 'Portrait with Scenery', + 5 => 'Self-portrait (1 person)', + 6 => 'Self-portrait (2 people)', + 7 => 'Children', + 8 => 'Sports', + 9 => 'Candlelight Portrait', + 10 => 'Party', + 11 => 'Pet', + 12 => 'Flower', + 13 => 'Natural Green', + 14 => 'Autumn Leaves', + 15 => 'Soft Flowing Water', + 16 => 'Splashing Water', + 17 => 'Sundown', + 18 => 'Night Scene', + 19 => 'Night Scene Portrait', + 20 => 'Fireworks', + 21 => 'Food', + 22 => 'Text', + 23 => 'Collection', + 24 => 'Auction', + 25 => 'Backlight', + 26 => 'Anti Shake', + 27 => 'High Sensitivity', + 28 => 'Underwater', + 29 => 'Monochrome', + 30 => 'Retro', + 31 => 'Business Cards', + 32 => 'White Board', + 33 => 'Silent', + 34 => 'Pre-record Movie', + 35 => 'For YouTube', + 36 => 'Voice Recording', + }, + },{ + Name => 'BestShotMode', + Writable => 'int16u', + Condition => '$$self{Model} eq "EX-S880"', + Notes => 'EX-S880', + PrintConvColumns => 3, + PrintConv => { + 0 => 'Off', + 1 => 'Auto', + 2 => 'Portrait', + 3 => 'Scenery', + 4 => 'Portrait with Scenery', + 5 => 'Children', + 6 => 'Sports', + 7 => 'Candlelight Portrait', + 8 => 'Party', + 9 => 'Pet', + 10 => 'Flower', + 11 => 'Natural Green', + 12 => 'Autumn Leaves', + 13 => 'Soft Flowing Water', # (wrong in documentation) + 14 => 'Splashing Water', + 15 => 'Sundown', + 16 => 'Night Scene', + 17 => 'Night Scene Portrait', + 18 => 'Fireworks', + 19 => 'Food', + 20 => 'Text', + 21 => 'Collection', + 22 => 'Auction', + 23 => 'Backlight', + 24 => 'Anti Shake', + 25 => 'High Sensitivity', + 26 => 'Monochrome', + 27 => 'Retro', + 28 => 'Twilight', + 29 => 'Layout (2 images)', + 30 => 'Layout (3 images)', + 31 => 'Auto Framing', + 32 => 'Old Photo', + 33 => 'Business Cards', + 34 => 'White Board', + 35 => 'Silent', + 36 => 'Short Movie', + 37 => 'Past Movie', + 38 => 'For YouTube', + 39 => 'Voice Recording', + }, + },{ + Name => 'BestShotMode', + Writable => 'int16u', + Condition => '$$self{Model} eq "EX-Z16"', + Notes => 'EX-Z16', + PrintConvColumns => 3, + PrintConv => { + 0 => 'Off', + 1 => 'Auto', + 2 => 'Portrait', + 3 => 'Scenery', + 4 => 'Portrait with Scenery', + 5 => 'Children', + 6 => 'Sports', + 7 => 'Candlelight Portrait', + 8 => 'Party', + 9 => 'Pet', + 10 => 'Flower', + 11 => 'Soft Flowing Water', + 12 => 'Sundown', + 13 => 'Night Scene', + 14 => 'Night Scene Portrait', + 15 => 'Fireworks', + 16 => 'Food', + 17 => 'Text', + 18 => 'For eBay', + 19 => 'Backlight', + 20 => 'Anti Shake', + 21 => 'High Sensitivity', + 22 => 'For YouTube', + 23 => 'Voice Recording', + }, + },{ + Name => 'BestShotMode', + Writable => 'int16u', + Condition => '$$self{Model} eq "EX-Z9"', + Notes => 'EX-Z9', + PrintConvColumns => 3, + PrintConv => { + 0 => 'Off', + 1 => 'Auto', + 2 => 'Movie', + 3 => 'Portrait', + 4 => 'Scenery', + 5 => 'Children', + 6 => 'Sports', + 7 => 'Candlelight Portrait', + 8 => 'Party', + 9 => 'Pet', + 10 => 'Flower', + 11 => 'Soft Flowing Water', + 12 => 'Sundown', + 13 => 'Night Scene', + 14 => 'Night Scene Portrait', + 15 => 'Fireworks', + 16 => 'Food', + 17 => 'Text', + 18 => 'Auction', + 19 => 'Backlight', + 20 => 'Anti Shake', + 21 => 'High Sensitivity', + 22 => 'For YouTube', + 23 => 'Voice Recording', + }, + },{ + Name => 'BestShotMode', + Writable => 'int16u', + Condition => '$$self{Model} eq "EX-Z80"', + Notes => 'EX-Z80', + PrintConvColumns => 3, + PrintConv => { + 0 => 'Off', + 1 => 'Auto', + 2 => 'Portrait', + 3 => 'Scenery', + 4 => 'Portrait with Scenery', + 5 => 'Pet', + 6 => 'Self-portrait (1 person)', + 7 => 'Self-portrait (2 people)', + 8 => 'Flower', + 9 => 'Food', + 10 => 'Fashion Accessories', + 11 => 'Magazine', + 12 => 'Monochrome', + 13 => 'Retro', + 14 => 'Cross Filter', + 15 => 'Pastel', + 16 => 'Night Scene', + 17 => 'Night Scene Portrait', + 18 => 'Party', + 19 => 'Sports', + 20 => 'Children', + 21 => 'Sundown', + 22 => 'Fireworks', + 23 => 'Underwater', + 24 => 'Backlight', + 25 => 'High Sensitivity', + 26 => 'Auction', + 27 => 'White Board', + 28 => 'Pre-record Movie', + 29 => 'For YouTube', + 30 => 'Voice Recording', + }, + },{ + Name => 'BestShotMode', + Writable => 'int16u', + Condition => '$$self{Model} =~ /^EX-Z(100|200)$/', + Notes => 'EX-Z100 and EX-Z200', + PrintConvColumns => 3, + PrintConv => { + 0 => 'Off', + 1 => 'Auto', + 2 => 'Auto Best Shot', + 3 => 'Portrait', + 4 => 'Scenery', + 5 => 'Portrait with Scenery', + 6 => 'Self-portrait (1 person)', + 7 => 'Self-portrait (2 people)', + 8 => 'Children', + 9 => 'Sports', + 10 => 'Candlelight Portrait', + 11 => 'Party', + 12 => 'Pet', + 13 => 'Flower', + 14 => 'Natural Green', + 15 => 'Autumn Leaves', + 16 => 'Soft Flowing Water', + 17 => 'Splashing Water', + 18 => 'Sundown', + 19 => 'Night Scene', + 20 => 'Night Scene Portrait', + 21 => 'Fireworks', + 22 => 'Food', + 23 => 'Text', + 24 => 'Collection', + 25 => 'Auction', + 26 => 'Backlight', + 27 => 'Anti Shake', + 28 => 'High Sensitivity', + 29 => 'Underwater', + 30 => 'Monochrome', + 31 => 'Retro', + 32 => 'Twilight', + 33 => 'ID Photo', + 34 => 'Business Cards', + 35 => 'White Board', + 36 => 'Silent', + 37 => 'Pre-record Movie', + 38 => 'For YouTube', + 39 => 'Voice Recording', + }, + },{ + Name => 'BestShotMode', + Writable => 'int16u', + # (Movies have different BestShot numbers for this camera) + Condition => '$$self{Model} eq "EX-Z750" and $$self{FILE_TYPE} eq "JPEG"', + Notes => 'EX-Z750 JPEG images', + PrintConvColumns => 3, + PrintConv => { + 0 => 'Off', + 1 => 'Portrait', + 2 => 'Scenery', + 3 => 'Portrait with Scenery', + 4 => 'Children', + 5 => 'Sports', + 6 => 'Candlelight Portrait', + 7 => 'Party', + 8 => 'Pet', + 9 => 'Flower', + 10 => 'Natural Green', + 11 => 'Soft Flowing Water', + 12 => 'Splashing Water', + 13 => 'Sundown', + 14 => 'Night Scene', + 15 => 'Night Scene Portrait', + 16 => 'Fireworks', + 17 => 'Food', + 18 => 'Text', + 19 => 'Collection', + 20 => 'Backlight', + 21 => 'Anti Shake', + 22 => 'Pastel', + 23 => 'Illustration', + 24 => 'Cross Filter', + 25 => 'Monochrome', + 26 => 'Retro', + 27 => 'Twilight', + 28 => 'Old Photo', + 29 => 'ID Photo', + 30 => 'Business Cards', + 31 => 'White Board', + }, + },{ + Name => 'BestShotMode', + Writable => 'int16u', + # (Movies have different BestShot numbers for this camera) + Condition => '$$self{Model} eq "EX-Z750" and $$self{FILE_TYPE} =~ /^(MOV|AVI)$/', + Notes => 'EX-Z750 movies', + PrintConvColumns => 3, + PrintConv => { + 0 => 'Off', + 1 => 'Portrait', + 2 => 'Scenery', + 3 => 'Night Scene', + 4 => 'Fireworks', + 5 => 'Backlight', + 6 => 'Silent', + }, + },{ + Name => 'BestShotMode', + Writable => 'int16u', + # (Movies have different BestShot numbers for this camera) + Condition => '$$self{Model} eq "EX-Z850" and $$self{FILE_TYPE} eq "JPEG"', + Notes => 'EX-Z850 JPEG images', + PrintConvColumns => 3, + PrintConv => { + 0 => 'Off', + 1 => 'Portrait', + 2 => 'Scenery', + 3 => 'Portrait with Scenery', + 4 => 'Children', + 5 => 'Sports', + 6 => 'Candlelight Portrait', + 7 => 'Party', + 8 => 'Pet', + 9 => 'Flower', + 10 => 'Natural Green', + 11 => 'Autumn Leaves', + 12 => 'Soft Flowing Water', + 13 => 'Splashing Water', + 14 => 'Sundown', + 15 => 'Night Scene', + 16 => 'Night Scene Portrait', + 17 => 'Fireworks', + 18 => 'Food', + 19 => 'Text', + 20 => 'Collection', + 21 => 'For eBay', + 22 => 'Backlight', + 23 => 'Anti Shake', + 24 => 'High Sensitivity', + 25 => 'Pastel', + 26 => 'Illustration', + 27 => 'Cross Filter', + 28 => 'Monochrome', + 29 => 'Retro', + 30 => 'Twilight', + 31 => 'ID Photo', + 32 => 'Old Photo', + 33 => 'Business Cards', + 34 => 'White Board', + }, + },{ + Name => 'BestShotMode', + Writable => 'int16u', + # (Movies have different BestShot numbers for this camera) + Condition => '$$self{Model} eq "EX-Z850" and $$self{FILE_TYPE} =~ /^(MOV|AVI)$/', + Notes => 'EX-Z850 movies', + PrintConvColumns => 3, + PrintConv => { + 0 => 'Off', + 1 => 'Portrait', + 2 => 'Scenery', + 3 => 'Night Scene', + 4 => 'Fireworks', + 5 => 'Backlight', + 6 => 'High Sensitivity', + 7 => 'Silent', + 8 => 'Short Movie', + 9 => 'Past Movie', + }, + },{ + Name => 'BestShotMode', + Writable => 'int16u', + # (Movies have different BestShot numbers for this camera) + Condition => '$$self{Model} eq "EX-Z1050"', + Notes => 'EX-Z1050', + PrintConvColumns => 3, + PrintConv => { + 0 => 'Off', + 1 => 'Auto', + 2 => 'Movie', + 3 => 'Portrait', + 4 => 'Scenery', + 5 => 'Portrait with Scenery', + 6 => 'Children', + 7 => 'Sports', + 8 => 'Candlelight Portrait', + 9 => 'Party', + 10 => 'Pet', + 11 => 'Flower', + 12 => 'Natural Green', + 13 => 'Autumn Leaves', + 14 => 'Soft Flowing Water', + 15 => 'Splashing Water', + 16 => 'Sundown', + 17 => 'Night Scene', + 18 => 'Night Scene Portrait', + 19 => 'Fireworks', + 20 => 'Food', + 21 => 'Text', + 22 => 'Collection', + 23 => 'For eBay', + 24 => 'Backlight', + 25 => 'Anti Shake', + 26 => 'High Sensitivity', + 27 => 'Underwater', + 28 => 'Monochrome', + 29 => 'Retro', + 30 => 'Twilight', + 31 => 'Layout (2 images)', + 32 => 'Layout (3 images)', + 33 => 'Auto Framing', + 34 => 'ID Photo', + 35 => 'Old Photo', + 36 => 'Business Cards', + 37 => 'White Board', + 38 => 'Voice Recording', + }, + },{ + Name => 'BestShotMode', + Writable => 'int16u', + # (Movies have different BestShot numbers for this camera) + Condition => '$$self{Model} eq "EX-Z1080"', + Notes => 'EX-Z1080', + PrintConvColumns => 3, + PrintConv => { + 0 => 'Off', + 1 => 'Auto', + 2 => 'Movie', + 3 => 'Portrait', + 4 => 'Scenery', + 5 => 'Portrait with Scenery', + 6 => 'Children', + 7 => 'Sports', + 8 => 'Candlelight Portrait', + 9 => 'Party', + 10 => 'Pet', + 11 => 'Flower', + 12 => 'Natural Green', + 13 => 'Autumn Leaves', + 14 => 'Soft Flowing Water', + 15 => 'Splashing Water', + 16 => 'Sundown', + 17 => 'Night Scene', + 18 => 'Night Scene Portrait', + 19 => 'Fireworks', + 20 => 'Food', + 21 => 'Text', + 22 => 'Collection', + 23 => 'For eBay', + 24 => 'Backlight', + 25 => 'Anti Shake', + 26 => 'High Sensitivity', + 27 => 'Underwater', + 28 => 'Monochrome', + 29 => 'Retro', + 30 => 'Twilight', + 31 => 'Layout (2 images)', + 32 => 'Layout (3 images)', + 33 => 'Auto Framing', + 34 => 'ID Photo', + 35 => 'Old Photo', + 36 => 'Business Cards', + 37 => 'White Board', + 38 => 'Short Movie', + 39 => 'Past Movie', + 40 => 'For YouTube', + 41 => 'Voice Recording', + }, + },{ + Name => 'BestShotMode', + Writable => 'int16u', + # (Movies have different BestShot numbers for this camera) + Condition => '$$self{Model} eq "EX-Z1200" and $$self{FILE_TYPE} eq "JPEG"', + Notes => 'EX-Z1200 JPEG images', + PrintConvColumns => 3, + PrintConv => { + 0 => 'Off', + 1 => 'Portrait', + 2 => 'Scenery', + 3 => 'Portrait with Scenery', + 4 => 'Children', + 5 => 'Sports', + 6 => 'Candlelight Portrait', + 7 => 'Party', + 8 => 'Pet', + 9 => 'Flower', + 10 => 'Natural Green', + 11 => 'Autumn Leaves', + 12 => 'Soft Flowing Water', + 13 => 'Splashing Water', + 14 => 'Sundown', + 15 => 'Night Scene', + 16 => 'Night Scene Portrait', + 17 => 'Fireworks', + 18 => 'Food', + 19 => 'Text', + 20 => 'Collection', + 21 => 'Auction', + 22 => 'Backlight', + 23 => 'High Sensitivity', + 24 => 'Underwater', + 25 => 'Monochrome', + 26 => 'Retro', + 27 => 'Twilight', + 28 => 'Layout (2 images)', + 29 => 'Layout (3 images)', + 30 => 'Auto Framing', + 31 => 'ID Photo', + 32 => 'Old Photo', + 33 => 'Business Cards', + 34 => 'White Board', + }, + },{ + Name => 'BestShotMode', + Writable => 'int16u', + # (Movies have different BestShot numbers for this camera) + Condition => '$$self{Model} eq "EX-Z1200" and $$self{FILE_TYPE} =~ /^(MOV|AVI)$/', + Notes => 'EX-Z1200 movies', + PrintConvColumns => 3, + PrintConv => { + 0 => 'Off', + 1 => 'Portrait', + 2 => 'Scenery', + 3 => 'Night Scene', + 4 => 'Fireworks', + 5 => 'Backlight', + 6 => 'High Sensitivity', + 7 => 'Silent', + 8 => 'Short Movie', + 9 => 'Past Movie', + }, + }, + # (the following weren't numbered in the documentation: + # G1, Z300, Z250, Z85, Z19, Z150, F1, FH20) + { + Name => 'BestShotMode', + Writable => 'int16u', + Condition => '$$self{Model} eq "EX-Z2000"', + Notes => 'EX-Z2000', + PrintConvColumns => 3, + #http://support.casio.com/download_files/001/faq_pdf/Z2000/EXZ2000_BS_US_a.pdf + PrintConv => { + 0 => 'Off', + 1 => 'Auto', + 2 => 'Premium Auto', + 3 => 'Dynamic Photo', + 4 => 'Portrait', + 5 => 'Scenery', + 6 => 'Portrait with Scenery', + 7 => 'Children', + 8 => 'Sports', + 9 => 'Candlelight Portrait', + 10 => 'Party', + 11 => 'Pet', + 12 => 'Flower', + 13 => 'Natural Green', + 14 => 'Autumn Leaves', + 15 => 'Soft Flowing Water', + 16 => 'Splashing Water', + 17 => 'Sundown', + 18 => 'Night Scene', + 19 => 'Night Scene Portrait', + 20 => 'Fireworks', + 21 => 'Food', + 22 => 'Text', + 23 => 'Collection', + 24 => 'For eBay', + 25 => 'Backlight', + 26 => 'High Sensitivity', + 27 => 'Oil Painting', + 28 => 'Crayon', + 29 => 'Water Color', + 30 => 'Monochrome', + 31 => 'Retro', + 32 => 'Twilight', + 33 => 'Multi-motion Image', + 34 => 'ID Photo', + 35 => 'Business Cards', + 36 => 'White Board', + 37 => 'Silent', + 38 => 'Pre-record Movie', + 39 => 'For YouTube', + 40 => 'Voice Recording', + }, + },{ + Name => 'BestShotMode', + Writable => 'int16u', + # (Movies have different BestShot numbers for this camera) + Condition => '$$self{Model} eq "EX-Z2300"', + Notes => 'EX-Z2300', + PrintConvColumns => 3, + PrintConv => { + 0 => 'Off', + 1 => 'Auto', + 2 => 'Premium Auto', + 3 => 'Dynamic Photo', + 4 => 'Portrait', + 5 => 'Scenery', + 6 => 'Portrait with Scenery', + 7 => 'Children', + 8 => 'Sports', + 9 => 'Candlelight Portrait', + 10 => 'Party', + 11 => 'Pet', + 12 => 'Flower', + 13 => 'Natural Green', + 14 => 'Autumn Leaves', + 15 => 'Soft Flowing Water', + 16 => 'Splashing Water', + 17 => 'Sundown', + 18 => 'Night Scene', + 19 => 'Night Scene Portrait', + 20 => 'Fireworks', + 21 => 'Food', + 22 => 'Text', + 23 => 'Collection', + 24 => 'Auction', + 25 => 'Backlight', + 26 => 'High Sensitivity', + 27 => 'Oil Painting', + 28 => 'Crayon', + 29 => 'Water Color', + 30 => 'Monochrome', + 31 => 'Retro', + 32 => 'Twilight', + 33 => 'Multi-motion Image', + 34 => 'ID Photo', + 35 => 'Business Cards', + 36 => 'White Board', + 37 => 'Silent', + 38 => 'Pre-record Movie', + 39 => 'For YouTube', + 40 => 'Voice Recording', + }, + },{ + Name => 'BestShotMode', + Writable => 'int16u', + Condition => '$$self{Model} eq "EX-Z3000"', + Notes => 'EX-Z3000', + PrintConvColumns => 3, + PrintConv => { + 0 => 'Off', + 1 => 'Portrait', + 2 => 'Scenery', + 3 => 'Portrait With Scenery', + 4 => 'Children', + 5 => 'Sports', + 6 => 'Night Scene', + }, + },{ + Name => 'BestShotMode', + Writable => 'int16u', + Condition => '$$self{Model} eq "EX-ZR100"', + Notes => 'EX-ZR100', + PrintConvColumns => 2, + PrintConv => { + 0 => 'Off', + 1 => 'Child CS', + 2 => 'Pet CS', + 3 => 'Sports CS', + 4 => 'Child High Speed Movie', + 5 => 'Pet High Speed Movie', + 6 => 'Sports High Speed Movie', + 7 => 'Multi SR Zoom', + 8 => 'Lag Correction', + 9 => 'High Speed Night Scene', + 10 => 'High Speed Night Scene and Portrait', + 11 => 'High Speed Anti Shake', + 12 => 'Portrait', + 13 => 'Scenery', + 14 => 'Portrait with Scenery', + 15 => 'Children', + 16 => 'Sports', + 17 => 'Candlelight Portrait', + 18 => 'Party', + 19 => 'Pet', + 20 => 'Flower', + 21 => 'Natural Green', + 22 => 'Autumn Leaves', + 23 => 'Soft Flowing Water', + 24 => 'Splashing Water', + 25 => 'Sundown', + 26 => 'Fireworks', + 27 => 'Food', + 28 => 'Text', + 29 => 'Collection', + 30 => 'For eBay', + 31 => 'Pre-record Movie', + 32 => 'For YouTube', + }, + },{ + Name => 'BestShotMode', + Writable => 'int16u', + Condition => '$$self{Model} eq "EX-ZR200"', + Notes => 'EX-ZR200', + PrintConvColumns => 2, + PrintConv => { + 0 => 'Off', + 1 => 'High Speed Night Scene', + 2 => 'High Speed Night Scene and Portrait', + 3 => 'High Speed Anti Shake', + 4 => 'Blurred Background', + 5 => 'Wide Shot', + 6 => 'High Speed Best Selection', + 7 => 'Lag Correction', + 8 => 'Child CS', + 9 => 'Pet CS', + 10 => 'Sports CS', + 11 => 'Child High Speed Movie', + 12 => 'Pet High Speed Movie', + 13 => 'Sports High Speed Movie', + 14 => 'Portrait', + 15 => 'Scenery', + 16 => 'Portrait with Scenery', + 17 => 'Children', + 18 => 'Sports', + 19 => 'Candlelight Portrait', + 20 => 'Party', + 21 => 'Pet', + 22 => 'Flower', + 23 => 'Natural Green', + 24 => 'Autumn Leaves', + 25 => 'Soft Flowing Water', + 26 => 'Splashing Water', + 27 => 'Sundown', + 28 => 'Fireworks', + 29 => 'Food', + 30 => 'Text', + 31 => 'Collection', + 32 => 'Auction', + 33 => 'Pre-record Movie', + 34 => 'For YouTube', + }, + },{ #http://ftp.casio.co.jp/pub/world_manual/qv/en/qv_4000/BS.pdf + Name => 'BestShotMode', + Writable => 'int16u', + Condition => '$$self{Model} eq "QV-4000"', + Notes => 'QV-4000', + PrintConvColumns => 3, + PrintConv => { + 0 => 'Off', + 1 => 'People', + 2 => 'Scenery', + 3 => 'Flower', + 4 => 'Night Scene', + 5 => 'Soft Focus', + # this camera also supports 100 modes that you can apparently load + # from a CD-ROM, but I don't know how these map into these numbers + }, + },{ #Manfred, email + Name => 'BestShotMode', + Writable => 'int16u', + Condition => '$$self{Model} eq "EX-ZR300"', + Notes => 'EX-ZR300', + PrintConvColumns => 2, + PrintConv => { + 1 => 'High Speed Night Shot', + 2 => 'Blurred Background', + 3 => 'Toy Camera', + 4 => 'Soft Focus', + 5 => 'Light Tone', + 6 => 'Pop', + 7 => 'Sepia', + 8 => 'Monochrome', + 9 => 'Miniature', + 10 => 'Wide Shot', + 11 => 'High Speed Best Selection', + 12 => 'Lag Correction', + 13 => 'High Speed Night Scene', + 14 => 'High Speed Night Scene and Portrait', + 15 => 'High Speed Anti Shake', + 16 => 'Portrait', + 17 => 'Scenery', + 18 => 'Portrait with Scenery', + 19 => 'Children', + 20 => 'Sports', + 21 => 'Candlelight Portrait', + 22 => 'Party', + 23 => 'Pet', + 24 => 'Flower', + 25 => 'Natural Green', + 26 => 'Autumn Leaves', + 27 => 'Soft Flowing Water', + 28 => 'Splashing Water', + 29 => 'Sundown', + 30 => 'Fireworks', + 31 => 'Food', + 32 => 'Text', + 33 => 'Collection', + 34 => 'Auction', + 35 => 'Prerecord (Movie)', + 36 => 'For YouTube', + }, + },{ + Name => 'BestShotMode', + Writable => 'int16u', + Notes => 'other models not yet decoded', + # so we can't use a lookup as usual - PH + PrintConv => '$val ? $val : "Off"', + PrintConvInv => '$val=~/(\d+)/ ? $1 : 0', + }], + 0x3008 => { #3 + Name => 'AutoISO', + Writable => 'int16u', + PrintConv => { + 1 => 'On', + 2 => 'Off', + 7 => 'On (high sensitivity)', #PH + 8 => 'On (anti-shake)', #PH + 10 => 'High Speed', #PH (EX-FC150) + }, + }, + 0x3009 => { #6 + Name => 'AFMode', + Writable => 'int16u', + PrintConv => { + 0 => 'Off', + 1 => 'Spot', + 2 => 'Multi', + 3 => 'Face Detection', + 4 => 'Tracking', # (but saw this for "Family First" mode with EX-Z77 - PH) + 5 => 'Intelligent', + }, + }, + 0x3011 => { #3 + Name => 'Sharpness', + Format => 'int16s', + Writable => 'undef', + }, + 0x3012 => { #3 + Name => 'Contrast', + Format => 'int16s', + Writable => 'undef', + }, + 0x3013 => { #3 + Name => 'Saturation', + Format => 'int16s', + Writable => 'undef', + }, + 0x3014 => { + Name => 'ISO', + Writable => 'int16u', + Priority => 0, + }, + 0x3015 => { + Name => 'ColorMode', + Writable => 'int16u', + PrintConv => { + 0 => 'Off', + 2 => 'Black & White', #PH (EX-Z400,FH20) + 3 => 'Sepia', #PH (EX-Z400) + }, + }, + 0x3016 => { + Name => 'Enhancement', + Writable => 'int16u', + PrintConv => { + 0 => 'Off', + 1 => 'Scenery', #PH (NC) (EX-Z77) + 3 => 'Green', #PH (EX-Z77) + 5 => 'Underwater', #PH (NC) (EX-Z77) + 9 => 'Flesh Tones', #PH (EX-Z77) + }, + }, + 0x3017 => { + Name => 'ColorFilter', + Writable => 'int16u', + PrintConv => { + 0 => 'Off', + 1 => 'Blue', #PH (FH20,Z400) + 3 => 'Green', #PH (FH20) + 4 => 'Yellow', #PH (FH20) + 5 => 'Red', #PH (FH20,Z77) + 6 => 'Purple', #PH (FH20,Z77,Z400) + 7 => 'Pink', #PH (FH20) + }, + }, + 0x301b => { #PH + Name => 'ArtMode', + Writable => 'int16u', + PrintConv => { + 0 => 'Normal', + 8 => 'Silent Movie', + 39 => 'HDR', # (EX-ZR10) + 45 => 'Premium Auto', # (EX-2300) + 47 => 'Painting', # (EX-2300) + 49 => 'Crayon Drawing', # (EX-2300) + 51 => 'Panorama', # (EX-ZR10) + 52 => 'Art HDR', # (EX-ZR10,EX-Z3000) + 62 => 'High Speed Night Shot', # (EX-ZR20) + 64 => 'Monochrome', # (EX-ZR20) + 67 => 'Toy Camera', # (EX-ZR20) + 68 => 'Pop Art', # (EX-ZR20) + 69 => 'Light Tone', # (EX-ZR20) + }, + }, + 0x301c => { #3 + Name => 'SequenceNumber', # for continuous shooting + Writable => 'int16u', + }, + 0x301d => { #3 + Name => 'BracketSequence', + Writable => 'int16u', + Count => 2, + }, + # 0x301e - MultiBracket ? (ref 3) + 0x3020 => { #3 + Name => 'ImageStabilization', + Writable => 'int16u', + PrintConv => { + 0 => 'Off', + 1 => 'On', + 2 => 'Best Shot', + 3 => 'Movie Anti-Shake', # (EX-V7, EX-TR100) + # (newer models write 2 numbers here - PH) + '0 0' => 'Off', #PH + '16 0' => 'Slow Shutter', #PH (EX-Z77) + '18 0' => 'Anti-Shake', #PH (EX-Z77) + '20 0' => 'High Sensitivity', #PH (EX-Z77) + # EX-Z2000 in 'Auto' mode gives '0 3' or '2 3' (ref 6) + '0 1' => 'Off (1)', #6 + '0 3' => 'CCD Shift', #PH/6 ("Camera AS" in EX-Z2000 manual) + '2 1' => 'High Sensitivity', #6 + '2 3' => 'CCD Shift + High Sensitivity', #PH (EX-FC150) + # have also seen: + # '2 0' - EX-Z15 1/60s ISO 200, EX-Z77 1/1000s ISO 50 + # '16 1' - EX-Z2300 1/125s ISO 50 + }, + }, + 0x302a => { #PH (EX-Z450) + Name => 'LightingMode', #(just guessing here) + Writable => 'int16u', + PrintConv => { + 0 => 'Off', + 1 => 'High Dynamic Range', # (EX-Z77 anti-blur shot) + 5 => 'Shadow Enhance Low', #(NC) + 6 => 'Shadow Enhance High', #(NC) + }, + }, + 0x302b => { #PH (EX-Z77) + Name => 'PortraitRefiner', + Writable => 'int16u', + PrintConv => { + 0 => 'Off', + 1 => '+1', + 2 => '+2', + }, + }, + 0x3030 => { #PH (EX-Z450) + Name => 'SpecialEffectLevel', + Writable => 'int16u', + }, + 0x3031 => { #PH (EX-Z450) + Name => 'SpecialEffectSetting', + Writable => 'int16u', + PrintConv => { + 0 => 'Off', + 1 => 'Makeup', + 2 => 'Mist Removal', + 3 => 'Vivid Landscape', + 16 => 'Art Shot', # (EX-Z2300) + }, + }, + 0x3103 => { #5 + Name => 'DriveMode', + Writable => 'int16u', + PrintConvColumns => 2, + PrintConv => { + OTHER => sub { + # handle new values of future models + my ($val, $inv) = @_; + return $val =~ /(\d+)/ ? $1 : undef if $inv; + return "Continuous ($val fps)"; + }, + 0 => 'Single Shot', #PH (NC) + 1 => 'Continuous Shooting', # (1 fps for the EX-F1) + 2 => 'Continuous (2 fps)', + 3 => 'Continuous (3 fps)', + 4 => 'Continuous (4 fps)', + 5 => 'Continuous (5 fps)', + 6 => 'Continuous (6 fps)', + 7 => 'Continuous (7 fps)', + 10 => 'Continuous (10 fps)', + 12 => 'Continuous (12 fps)', + 15 => 'Continuous (15 fps)', + 20 => 'Continuous (20 fps)', + 30 => 'Continuous (30 fps)', + 40 => 'Continuous (40 fps)', #PH (EX-FH25) + 60 => 'Continuous (60 fps)', + 240 => 'Auto-N', + }, + }, + 0x310b => { #PH (NC) + Name => 'ArtModeParameters', + Writable => 'int8u', + Count => 3, + # "0 1 0" = Toy camera 1 + # "0 2 0" = Toy camera 1 + # "0 3 0" = Toy camera 1 + # Have also seen "0 0 0" and "2 0 0" + }, + 0x4001 => { #PH (AVI videos) + Name => 'CaptureFrameRate', + Writable => 'int16u', + Count => -1, + ValueConv => q{ + my @v=split(" ",$val); + return $val / 1000 if @v == 1; + return $v[1] ? "$v[1]-$v[0]" : ($v[0] > 10000 ? $v[0] / 1000 : $v[0]); + }, + ValueConvInv => '$val <= 60 ? $val * 1000 : int($val) . " 0"', + }, + # 0x4002 - AVI videos, related to video quality or size - PH + 0x4003 => { #PH (AVI and MOV videos) + Name => 'VideoQuality', + Writable => 'int16u', + PrintConv => { + 1 => 'Standard', + # 2 - could this be LP? + 3 => 'HD (720p)', + 4 => 'Full HD (1080p)', # (EX-ZR10, 30fps 1920x1080) + 5 => 'Low', # used in High Speed modes + }, + }, +); + +# face detection information (ref PH) (EX-H5) +%Image::ExifTool::Casio::FaceInfo1 = ( + PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData, + WRITE_PROC => \&Image::ExifTool::WriteBinaryData, + CHECK_PROC => \&Image::ExifTool::CheckBinaryData, + GROUPS => { 0 => 'MakerNotes', 2 => 'Image' }, + WRITABLE => 1, + FIRST_ENTRY => 0, + DATAMEMBER => [ 0 ], + NOTES => 'Face-detect tags extracted from models such as the EX-H5.', + 0x00 => { # (NC) + Name => 'FacesDetected', + DataMember => 'FacesDetected', + RawConv => '$$self{FacesDetected} = $val', + }, + 0x01 => { + Name => 'FaceDetectFrameSize', + Condition => '$$self{FacesDetected} >= 1', # (otherwise zeros) + Format => 'int16u[2]', + }, + 0x0d => { + Name => 'Face1Position', + Condition => '$$self{FacesDetected} >= 1', + Format => 'int16u[4]', + Notes => q{ + left, top, right and bottom of detected face in coordinates of + FaceDetectFrameSize, with increasing Y downwards + }, + }, + # decoding NOT CONFIRMED (NC) for faces 2-10! + 0x7c => { + Name => 'Face2Position', + Condition => '$$self{FacesDetected} >= 2', + Format => 'int16u[4]', + }, + 0xeb => { + Name => 'Face3Position', + Condition => '$$self{FacesDetected} >= 3', + Format => 'int16u[4]', + }, + 0x15a => { + Name => 'Face4Position', + Condition => '$$self{FacesDetected} >= 4', + Format => 'int16u[4]', + }, + 0x1c9 => { + Name => 'Face5Position', + Condition => '$$self{FacesDetected} >= 5', + Format => 'int16u[4]', + }, + 0x238 => { + Name => 'Face6Position', + Condition => '$$self{FacesDetected} >= 6', + Format => 'int16u[4]', + }, + 0x2a7 => { + Name => 'Face7Position', + Condition => '$$self{FacesDetected} >= 7', + Format => 'int16u[4]', + }, + 0x316 => { + Name => 'Face8Position', + Condition => '$$self{FacesDetected} >= 8', + Format => 'int16u[4]', + }, + 0x385 => { + Name => 'Face9Position', + Condition => '$$self{FacesDetected} >= 9', + Format => 'int16u[4]', + }, + 0x3f4 => { + Name => 'Face10Position', + Condition => '$$self{FacesDetected} >= 10', + Format => 'int16u[4]', + }, +); + +# face detection information (ref PH) (EX-ZR100) +%Image::ExifTool::Casio::FaceInfo2 = ( + PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData, + WRITE_PROC => \&Image::ExifTool::WriteBinaryData, + CHECK_PROC => \&Image::ExifTool::CheckBinaryData, + GROUPS => { 0 => 'MakerNotes', 2 => 'Image' }, + WRITABLE => 1, + FIRST_ENTRY => 0, + DATAMEMBER => [ 2 ], + NOTES => 'Face-detect tags extracted from models such as the EX-H20G and EX-ZR100.', + 0x02 => { + Name => 'FacesDetected', + DataMember => 'FacesDetected', + RawConv => '$$self{FacesDetected} = $val', + }, + 0x04 => { + Name => 'FaceDetectFrameSize', + Condition => '$$self{FacesDetected} >= 1', + Format => 'int16u[2]', + }, + 0x08 => { + Name => 'FaceOrientation', + Condition => '$$self{FacesDetected} >= 1', + PrintConv => { + 0 => 'Horizontal (normal)', + 1 => 'Rotate 90 CW', + 2 => 'Rotate 270 CW', + 3 => 'Rotate 180', # (NC) + # (have seen 64 here, but image had no face) + }, + Notes => 'orientation of face relative to unrotated image', + }, + # 0x0a - FaceDetectFrameSize again + # 0x11 - Face1Detected flag (1=detected) + 0x18 => { + Name => 'Face1Position', + Condition => '$$self{FacesDetected} >= 1', + Format => 'int16u[4]', + Notes => q{ + left, top, right and bottom of detected face in coordinates of + FaceDetectFrameSize, with increasing Y downwards + }, + }, + # 0x45 - Face2Detected, etc... + 0x4c => { + Name => 'Face2Position', + Condition => '$$self{FacesDetected} >= 2', + Format => 'int16u[4]', + }, + 0x80 => { + Name => 'Face3Position', + Condition => '$$self{FacesDetected} >= 3', + Format => 'int16u[4]', + }, + 0xb4 => { + Name => 'Face4Position', + Condition => '$$self{FacesDetected} >= 4', + Format => 'int16u[4]', + }, + 0xe8 => { + Name => 'Face5Position', + Condition => '$$self{FacesDetected} >= 5', + Format => 'int16u[4]', + }, + 0x11c => { + Name => 'Face6Position', + Condition => '$$self{FacesDetected} >= 6', + Format => 'int16u[4]', + }, + 0x150 => { + Name => 'Face7Position', + Condition => '$$self{FacesDetected} >= 7', + Format => 'int16u[4]', + }, + 0x184 => { + Name => 'Face8Position', + Condition => '$$self{FacesDetected} >= 8', + Format => 'int16u[4]', + }, + 0x1b8 => { + Name => 'Face9Position', + Condition => '$$self{FacesDetected} >= 9', + Format => 'int16u[4]', + }, + 0x1ec => { + Name => 'Face10Position', + Condition => '$$self{FacesDetected} >= 10', + Format => 'int16u[4]', + }, +); + +# Casio APP1 QVCI segment found in QV-7000SX images (ref PH) +%Image::ExifTool::Casio::QVCI = ( + PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData, + GROUPS => { 0 => 'MakerNotes', 2 => 'Camera' }, + FIRST_ENTRY => 0, + NOTES => q{ + This information is found in the APP1 QVCI segment of JPEG images from the + Casio QV-7000SX. + }, + 0x2c => { + Name => 'CasioQuality', + PrintConv => { + 1 => 'Economy', + 2 => 'Normal', + 3 => 'Fine', + 4 => 'Super Fine', + }, + }, + 0x37 => { + Name => 'FocalRange', + Unknown => 1, + }, + 0x4d => { + Name => 'DateTimeOriginal', + Description => 'Date/Time Original', + Format => 'string[20]', + Groups => { 2 => 'Time' }, + ValueConv => '$val=~tr/./:/; $val=~s/(\d+:\d+:\d+):/$1 /; $val', + PrintConv => '$self->ConvertDateTime($val)', + }, + 0x62 => { + Name => 'ModelType', + Format => 'string[7]', + }, + 0x72 => { # could be serial number or manufacture date in form YYMMDDxx ? + Name => 'ManufactureIndex', + Format => 'string[9]', + }, + 0x7c => { + Name => 'ManufactureCode', + Format => 'string[9]', + }, +); + +# tags in Casio AVI videos (ref PH) +%Image::ExifTool::Casio::AVI = ( + PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData, + GROUPS => { 0 => 'MakerNotes', 2 => 'Camera' }, + FIRST_ENTRY => 0, + NOTES => 'This information is found in Casio GV-10 AVI videos.', + 0 => { + Name => 'Software', # (equivalent to RIFF Software tag) + Format => 'string', + }, +); + + +1; # end + +__END__ + +=head1 NAME + +Image::ExifTool::Casio - Casio EXIF maker notes tags + +=head1 SYNOPSIS + +This module is loaded automatically by Image::ExifTool when required. + +=head1 DESCRIPTION + +This module contains definitions required by Image::ExifTool to interpret +Casio maker notes in EXIF information. + +=head1 AUTHOR + +Copyright 2003-2019, Phil Harvey (phil at owl.phy.queensu.ca) + +This library is free software; you can redistribute it and/or modify it +under the same terms as Perl itself. + +=head1 REFERENCES + +=over 4 + +=item L<http://park2.wakwak.com/~tsuruzoh/Computer/Digicams/exif-e.html> + +=back + +=head1 ACKNOWLEDGEMENTS + +Thanks to Joachim Loehr for adding support for the type 2 maker notes, and +Jens Duttke and Robert Chi for decoding some tags. + +=head1 SEE ALSO + +L<Image::ExifTool::TagNames/Casio Tags>, +L<Image::ExifTool(3pm)|Image::ExifTool> + +=cut diff --git a/lib/Image/ExifTool/Charset.pm b/lib/Image/ExifTool/Charset.pm new file mode 100644 index 0000000..d27d0fa --- /dev/null +++ b/lib/Image/ExifTool/Charset.pm @@ -0,0 +1,431 @@ +#------------------------------------------------------------------------------ +# File: Charset.pm +# +# Description: ExifTool character encoding routines +# +# Revisions: 2009/08/28 - P. Harvey created +# 2010/01/20 - P. Harvey complete re-write +# 2010/07/16 - P. Harvey added UTF-16 support +#------------------------------------------------------------------------------ + +package Image::ExifTool::Charset; + +use strict; +use vars qw($VERSION %csType); +use Image::ExifTool qw(:DataAccess :Utils); + +$VERSION = '1.11'; + +my %charsetTable; # character set tables we've loaded + +# lookup for converting Unicode to 1-byte character sets +my %unicode2byte = ( + Latin => { # pre-load Latin (cp1252) for speed + 0x20ac => 0x80, 0x0160 => 0x8a, 0x2013 => 0x96, + 0x201a => 0x82, 0x2039 => 0x8b, 0x2014 => 0x97, + 0x0192 => 0x83, 0x0152 => 0x8c, 0x02dc => 0x98, + 0x201e => 0x84, 0x017d => 0x8e, 0x2122 => 0x99, + 0x2026 => 0x85, 0x2018 => 0x91, 0x0161 => 0x9a, + 0x2020 => 0x86, 0x2019 => 0x92, 0x203a => 0x9b, + 0x2021 => 0x87, 0x201c => 0x93, 0x0153 => 0x9c, + 0x02c6 => 0x88, 0x201d => 0x94, 0x017e => 0x9e, + 0x2030 => 0x89, 0x2022 => 0x95, 0x0178 => 0x9f, + }, +); + +# bit flags for all supported character sets +# (this number must be correct because it dictates the decoding algorithm!) +# 0x001 = character set requires a translation module +# 0x002 = inverse conversion not yet supported by Recompose() +# 0x080 = some characters with codepoints in the range 0x00-0x7f are remapped +# 0x100 = 1-byte fixed-width characters +# 0x200 = 2-byte fixed-width characters +# 0x400 = 4-byte fixed-width characters +# 0x800 = 1- and 2-byte variable-width characters, or 1-byte +# fixed-width characters that map into multiple codepoints +# Note: In its public interface, ExifTool can currently only support type 0x101 +# and lower character sets because strings are only converted if they +# contain characters above 0x7f and there is no provision for specifying +# the byte order for input/output values +%csType = ( + UTF8 => 0x100, + ASCII => 0x100, # (treated like UTF8) + Arabic => 0x101, + Baltic => 0x101, + Cyrillic => 0x101, + Greek => 0x101, + Hebrew => 0x101, + Latin => 0x101, + Latin2 => 0x101, + DOSLatinUS => 0x101, + DOSLatin1 => 0x101, + MacCroatian => 0x101, + MacCyrillic => 0x101, + MacGreek => 0x101, + MacIceland => 0x101, + MacLatin2 => 0x101, + MacRoman => 0x101, + MacRomanian => 0x101, + MacTurkish => 0x101, + Thai => 0x101, + Turkish => 0x101, + Vietnam => 0x101, + MacArabic => 0x103, # (directional characters not supported) + PDFDoc => 0x181, + Unicode => 0x200, # (UCS2) + UCS2 => 0x200, + UTF16 => 0x200, + Symbol => 0x201, + JIS => 0x201, + UCS4 => 0x400, + MacChineseCN => 0x803, + MacChineseTW => 0x803, + MacHebrew => 0x803, # (directional characters not supported) + MacKorean => 0x803, + MacRSymbol => 0x803, + MacThai => 0x803, + MacJapanese => 0x883, + ShiftJIS => 0x883, +); + +#------------------------------------------------------------------------------ +# Load character set module +# Inputs: 0) Module name +# Returns: Reference to lookup hash, or undef on error +sub LoadCharset($) +{ + my $charset = shift; + my $conv = $charsetTable{$charset}; + unless ($conv) { + # load translation module + my $module = "Image::ExifTool::Charset::$charset"; + no strict 'refs'; + if (%$module or eval "require $module") { + $conv = $charsetTable{$charset} = \%$module; + } + } + return $conv; +} + +#------------------------------------------------------------------------------ +# Does an array contain valid UTF-16 characters? +# Inputs: 0) array reference to list of UCS-2 values +# Returns: 0=invalid UTF-16, 1=valid UTF-16 with no surrogates, 2=valid UTF-16 with surrogates +sub IsUTF16($) +{ + local $_; + my $uni = shift; + my $surrogate; + foreach (@$uni) { + my $hiBits = ($_ & 0xfc00); + if ($hiBits == 0xfc00) { + # check for invalid values in UTF-16 + return 0 if $_ == 0xffff or $_ == 0xfffe or ($_ >= 0xfdd0 and $_ <= 0xfdef); + } elsif ($surrogate) { + return 0 if $hiBits != 0xdc00; + $surrogate = 0; + } else { + return 0 if $hiBits == 0xdc00; + $surrogate = 1 if $hiBits == 0xd800; + } + } + return 1 if not defined $surrogate; + return 2 unless $surrogate; + return 0; +} + +#------------------------------------------------------------------------------ +# Decompose string with specified encoding into an array of integer code points +# Inputs: 0) ExifTool object ref (or undef), 1) string, 2) character set name, +# 3) optional byte order ('II','MM','Unknown' or undef to use ExifTool ordering) +# Returns: Reference to array of Unicode values +# Notes: Accepts any type of character set +# - byte order only used for fixed-width 2-byte and 4-byte character sets +# - byte order mark observed and then removed with UCS2 and UCS4 +# - no warnings are issued if ExifTool object is not provided +# - sets ExifTool WrongByteOrder flag if byte order is Unknown and current order is wrong +sub Decompose($$$;$) +{ + local $_; + my ($et, $val, $charset) = @_; # ($byteOrder assigned later if required) + my $type = $csType{$charset}; + my (@uni, $conv); + + if ($type & 0x001) { + $conv = LoadCharset($charset); + unless ($conv) { + # (shouldn't happen) + $et->Warn("Invalid character set $charset") if $et; + return \@uni; # error! + } + } elsif ($type == 0x100) { + # convert ASCII and UTF8 (treat ASCII as UTF8) + if ($] < 5.006001) { + # do it ourself + @uni = Image::ExifTool::UnpackUTF8($val); + } else { + # handle warnings from malformed UTF-8 + undef $Image::ExifTool::evalWarning; + local $SIG{'__WARN__'} = \&Image::ExifTool::SetWarning; + # (somehow the meaning of "U0" was reversed in Perl 5.10.0!) + @uni = unpack($] < 5.010000 ? 'U0U*' : 'C0U*', $val); + # issue warning if we had errors + if ($Image::ExifTool::evalWarning and $et and not $$et{WarnBadUTF8}) { + $et->Warn('Malformed UTF-8 character(s)'); + $$et{WarnBadUTF8} = 1; + } + } + return \@uni; # all done! + } + if ($type & 0x100) { # 1-byte fixed-width characters + @uni = unpack('C*', $val); + foreach (@uni) { + $_ = $$conv{$_} if defined $$conv{$_}; + } + } elsif ($type & 0x600) { # 2-byte or 4-byte fixed-width characters + my $unknown; + my $byteOrder = $_[3]; + if (not $byteOrder) { + $byteOrder = GetByteOrder(); + } elsif ($byteOrder eq 'Unknown') { + $byteOrder = GetByteOrder(); + $unknown = 1; + } + my $fmt = $byteOrder eq 'MM' ? 'n*' : 'v*'; + if ($type & 0x400) { # 4-byte + $fmt = uc $fmt; # unpack as 'N*' or 'V*' + # honour BOM if it exists + $val =~ s/^(\0\0\xfe\xff|\xff\xfe\0\0)// and $fmt = $1 eq "\0\0\xfe\xff" ? 'N*' : 'V*'; + undef $unknown; # (byte order logic applies to 2-byte only) + } elsif ($val =~ s/^(\xfe\xff|\xff\xfe)//) { + $fmt = $1 eq "\xfe\xff" ? 'n*' : 'v*'; + undef $unknown; + } + # convert from UCS2 or UCS4 + @uni = unpack($fmt, $val); + + if (not $conv) { + # no translation necessary + if ($unknown) { + # check the byte order + my (%bh, %bl); + my ($zh, $zl) = (0, 0); + foreach (@uni) { + $bh{$_ >> 8} = 1; + $bl{$_ & 0xff} = 1; + ++$zh unless $_ & 0xff00; + ++$zl unless $_ & 0x00ff; + } + # count the number of unique values in the hi and lo bytes + my ($bh, $bl) = (scalar(keys %bh), scalar(keys %bl)); + # the byte with the greater number of unique values should be + # the low-order byte, otherwise the byte which is zero more + # often is likely the high-order byte + if ($bh > $bl or ($bh == $bl and $zl > $zh)) { + # we guessed wrong, so decode using the other byte order + $fmt =~ tr/nvNV/vnVN/; + @uni = unpack($fmt, $val); + $$et{WrongByteOrder} = 1; + } + } + # handle surrogate pairs of UTF-16 + if ($charset eq 'UTF16') { + my $i; + for ($i=0; $i<$#uni; ++$i) { + next unless ($uni[$i] & 0xfc00) == 0xd800 and + ($uni[$i+1] & 0xfc00) == 0xdc00; + my $cp = 0x10000 + (($uni[$i] & 0x3ff) << 10) + ($uni[$i+1] & 0x3ff); + splice(@uni, $i, 2, $cp); + } + } + } elsif ($unknown) { + # count encoding errors as we do the translation + my $e1 = 0; + foreach (@uni) { + defined $$conv{$_} and $_ = $$conv{$_}, next; + ++$e1; + } + # try the other byte order if we had any errors + if ($e1) { + $fmt = $byteOrder eq 'MM' ? 'v*' : 'n*'; #(reversed) + my @try = unpack($fmt, $val); + my $e2 = 0; + foreach (@try) { + defined $$conv{$_} and $_ = $$conv{$_}, next; + ++$e2; + } + # use this byte order if there are fewer errors + if ($e2 < $e1) { + $$et{WrongByteOrder} = 1; + return \@try; + } + } + } else { + # translate any characters found in the lookup + foreach (@uni) { + $_ = $$conv{$_} if defined $$conv{$_}; + } + } + } else { # variable-width characters + # unpack into bytes + my @bytes = unpack('C*', $val); + while (@bytes) { + my $ch = shift @bytes; + my $cv = $$conv{$ch}; + # pass straight through if no translation + $cv or push(@uni, $ch), next; + # byte translates into single Unicode character + ref $cv or push(@uni, $cv), next; + # byte maps into multiple Unicode characters + ref $cv eq 'ARRAY' and push(@uni, @$cv), next; + # handle 2-byte character codes + $ch = shift @bytes; + if (defined $ch) { + if ($$cv{$ch}) { + $cv = $$cv{$ch}; + ref $cv or push(@uni, $cv), next; + push @uni, @$cv; # multiple Unicode characters + } else { + push @uni, ord('?'); # encoding error + unshift @bytes, $ch; + } + } else { + push @uni, ord('?'); # encoding error + } + } + } + return \@uni; +} + +#------------------------------------------------------------------------------ +# Convert array of code point integers into a string with specified encoding +# Inputs: 0) ExifTool ref (or undef), 1) unicode character array ref, +# 2) character set (note: not all types are supported) +# 3) byte order ('MM' or 'II', multi-byte sets only, defaults to current byte order) +# Returns: converted string (truncated at null character if it exists), empty on error +# Notes: converts elements of input character array to new code points +# - ExifTool ref may be undef provided $charset is defined +sub Recompose($$;$$) +{ + local $_; + my ($et, $uni, $charset) = @_; # ($byteOrder assigned later if required) + my ($outVal, $conv, $inv); + $charset or $charset = $$et{OPTIONS}{Charset}; + my $csType = $csType{$charset}; + if ($csType == 0x100) { # UTF8 (also treat ASCII as UTF8) + if ($] >= 5.006001) { + # let Perl do it + $outVal = pack('C0U*', @$uni); + } else { + # do it ourself + $outVal = Image::ExifTool::PackUTF8(@$uni); + } + $outVal =~ s/\0.*//s; # truncate at null terminator + return $outVal; + } + # get references to forward and inverse lookup tables + if ($csType & 0x801) { + $conv = LoadCharset($charset); + unless ($conv) { + $et->Warn("Missing charset $charset") if $et; + return ''; + } + $inv = $unicode2byte{$charset}; + # generate inverse lookup if necessary + unless ($inv) { + if (not $csType or $csType & 0x802) { + $et->Warn("Invalid destination charset $charset") if $et; + return ''; + } + # prepare table to convert from Unicode to 1-byte characters + my ($char, %inv); + foreach $char (keys %$conv) { + $inv{$$conv{$char}} = $char; + } + $inv = $unicode2byte{$charset} = \%inv; + } + } + if ($csType & 0x100) { # 1-byte fixed-width + # convert to specified character set + foreach (@$uni) { + next if $_ < 0x80; + $$inv{$_} and $_ = $$inv{$_}, next; + # our tables omit 1-byte characters with the same values as Unicode, + # so pass them straight through after making sure there isn't a + # different character with this byte value + next if $_ < 0x100 and not $$conv{$_}; + $_ = ord('?'); # set invalid characters to '?' + if ($et and not $$et{EncodingError}) { + $et->Warn("Some character(s) could not be encoded in $charset"); + $$et{EncodingError} = 1; + } + } + # repack as an 8-bit string and truncate at null + $outVal = pack('C*', @$uni); + $outVal =~ s/\0.*//s; + } else { # 2-byte and 4-byte fixed-width + # convert if required + if ($inv) { + $$inv{$_} and $_ = $$inv{$_} foreach @$uni; + } + # generate surrogate pairs of UTF-16 + if ($charset eq 'UTF16') { + my $i; + for ($i=0; $i<@$uni; ++$i) { + next unless $$uni[$i] >= 0x10000 and $$uni[$i] < 0x10ffff; + my $t = $$uni[$i] - 0x10000; + my $w1 = 0xd800 + (($t >> 10) & 0x3ff); + my $w2 = 0xdc00 + ($t & 0x3ff); + splice(@$uni, $i, 1, $w1, $w2); + ++$i; # skip surrogate pair + } + } + # pack as 2- or 4-byte integer in specified byte order + my $byteOrder = $_[3] || GetByteOrder(); + my $fmt = $byteOrder eq 'MM' ? 'n*' : 'v*'; + $fmt = uc($fmt) if $csType & 0x400; + $outVal = pack($fmt, @$uni); + } + return $outVal; +} + +1; # end + +__END__ + +=head1 NAME + +Image::ExifTool::Charset - ExifTool character encoding routines + +=head1 SYNOPSIS + +This module is required by Image::ExifTool. + +=head1 DESCRIPTION + +This module contains routines used by ExifTool to translate special +character sets. Currently, the following character sets are supported: + + UTF8, UTF16, UCS2, UCS4, Arabic, Baltic, Cyrillic, Greek, Hebrew, JIS, + Latin, Latin2, DOSLatinUS, DOSLatin1, MacArabic, MacChineseCN, + MacChineseTW, MacCroatian, MacCyrillic, MacGreek, MacHebrew, MacIceland, + MacJapanese, MacKorean, MacLatin2, MacRSymbol, MacRoman, MacRomanian, + MacThai, MacTurkish, PDFDoc, RSymbol, ShiftJIS, Symbol, Thai, Turkish, + Vietnam + +However, only some of these character sets are available to the user via +ExifTool options -- the multi-byte character sets are used only internally +when decoding certain types of information. + +=head1 AUTHOR + +Copyright 2003-2019, Phil Harvey (phil at owl.phy.queensu.ca) + +This library is free software; you can redistribute it and/or modify it +under the same terms as Perl itself. + +=head1 SEE ALSO + +L<Image::ExifTool(3pm)|Image::ExifTool> + +=cut diff --git a/lib/Image/ExifTool/Charset/Arabic.pm b/lib/Image/ExifTool/Charset/Arabic.pm new file mode 100644 index 0000000..513492f --- /dev/null +++ b/lib/Image/ExifTool/Charset/Arabic.pm @@ -0,0 +1,39 @@ +#------------------------------------------------------------------------------ +# File: Arabic.pm +# +# Description: cp1256 to Unicode +# +# Revisions: 2010/01/20 - P. Harvey created +# +# References: 1) http://unicode.org/Public/MAPPINGS/VENDORS/MICSFT/WINDOWS/CP1256.TXT +# +# Notes: The table omits 1-byte characters with the same values as Unicode +#------------------------------------------------------------------------------ +use strict; + +%Image::ExifTool::Charset::Arabic = ( + 0x80 => 0x20ac, 0x81 => 0x067e, 0x82 => 0x201a, 0x83 => 0x0192, + 0x84 => 0x201e, 0x85 => 0x2026, 0x86 => 0x2020, 0x87 => 0x2021, + 0x88 => 0x02c6, 0x89 => 0x2030, 0x8a => 0x0679, 0x8b => 0x2039, + 0x8c => 0x0152, 0x8d => 0x0686, 0x8e => 0x0698, 0x8f => 0x0688, + 0x90 => 0x06af, 0x91 => 0x2018, 0x92 => 0x2019, 0x93 => 0x201c, + 0x94 => 0x201d, 0x95 => 0x2022, 0x96 => 0x2013, 0x97 => 0x2014, + 0x98 => 0x06a9, 0x99 => 0x2122, 0x9a => 0x0691, 0x9b => 0x203a, + 0x9c => 0x0153, 0x9d => 0x200c, 0x9e => 0x200d, 0x9f => 0x06ba, + 0xa1 => 0x060c, 0xaa => 0x06be, 0xba => 0x061b, 0xbf => 0x061f, + 0xc0 => 0x06c1, 0xc1 => 0x0621, 0xc2 => 0x0622, 0xc3 => 0x0623, + 0xc4 => 0x0624, 0xc5 => 0x0625, 0xc6 => 0x0626, 0xc7 => 0x0627, + 0xc8 => 0x0628, 0xc9 => 0x0629, 0xca => 0x062a, 0xcb => 0x062b, + 0xcc => 0x062c, 0xcd => 0x062d, 0xce => 0x062e, 0xcf => 0x062f, + 0xd0 => 0x0630, 0xd1 => 0x0631, 0xd2 => 0x0632, 0xd3 => 0x0633, + 0xd4 => 0x0634, 0xd5 => 0x0635, 0xd6 => 0x0636, 0xd8 => 0x0637, + 0xd9 => 0x0638, 0xda => 0x0639, 0xdb => 0x063a, 0xdc => 0x0640, + 0xdd => 0x0641, 0xde => 0x0642, 0xdf => 0x0643, 0xe1 => 0x0644, + 0xe3 => 0x0645, 0xe4 => 0x0646, 0xe5 => 0x0647, 0xe6 => 0x0648, + 0xec => 0x0649, 0xed => 0x064a, 0xf0 => 0x064b, 0xf1 => 0x064c, + 0xf2 => 0x064d, 0xf3 => 0x064e, 0xf5 => 0x064f, 0xf6 => 0x0650, + 0xf8 => 0x0651, 0xfa => 0x0652, 0xfd => 0x200e, 0xfe => 0x200f, + 0xff => 0x06d2, +); + +1; # end diff --git a/lib/Image/ExifTool/Charset/Baltic.pm b/lib/Image/ExifTool/Charset/Baltic.pm new file mode 100644 index 0000000..4ed0a10 --- /dev/null +++ b/lib/Image/ExifTool/Charset/Baltic.pm @@ -0,0 +1,35 @@ +#------------------------------------------------------------------------------ +# File: Baltic.pm +# +# Description: cp1257 to Unicode +# +# Revisions: 2010/01/20 - P. Harvey created +# +# References: 1) http://unicode.org/Public/MAPPINGS/VENDORS/MICSFT/WINDOWS/CP1257.TXT +# +# Notes: The table omits 1-byte characters with the same values as Unicode +#------------------------------------------------------------------------------ +use strict; + +%Image::ExifTool::Charset::Baltic = ( + 0x80 => 0x20ac, 0x82 => 0x201a, 0x84 => 0x201e, 0x85 => 0x2026, + 0x86 => 0x2020, 0x87 => 0x2021, 0x89 => 0x2030, 0x8b => 0x2039, 0x8d => 0xa8, + 0x8e => 0x02c7, 0x8f => 0xb8, 0x91 => 0x2018, 0x92 => 0x2019, 0x93 => 0x201c, + 0x94 => 0x201d, 0x95 => 0x2022, 0x96 => 0x2013, 0x97 => 0x2014, + 0x99 => 0x2122, 0x9b => 0x203a, 0x9d => 0xaf, 0x9e => 0x02db, 0xa8 => 0xd8, + 0xaa => 0x0156, 0xaf => 0xc6, 0xb8 => 0xf8, 0xba => 0x0157, 0xbf => 0xe6, + 0xc0 => 0x0104, 0xc1 => 0x012e, 0xc2 => 0x0100, 0xc3 => 0x0106, + 0xc6 => 0x0118, 0xc7 => 0x0112, 0xc8 => 0x010c, 0xca => 0x0179, + 0xcb => 0x0116, 0xcc => 0x0122, 0xcd => 0x0136, 0xce => 0x012a, + 0xcf => 0x013b, 0xd0 => 0x0160, 0xd1 => 0x0143, 0xd2 => 0x0145, + 0xd4 => 0x014c, 0xd8 => 0x0172, 0xd9 => 0x0141, 0xda => 0x015a, + 0xdb => 0x016a, 0xdd => 0x017b, 0xde => 0x017d, 0xe0 => 0x0105, + 0xe1 => 0x012f, 0xe2 => 0x0101, 0xe3 => 0x0107, 0xe6 => 0x0119, + 0xe7 => 0x0113, 0xe8 => 0x010d, 0xea => 0x017a, 0xeb => 0x0117, + 0xec => 0x0123, 0xed => 0x0137, 0xee => 0x012b, 0xef => 0x013c, + 0xf0 => 0x0161, 0xf1 => 0x0144, 0xf2 => 0x0146, 0xf4 => 0x014d, + 0xf8 => 0x0173, 0xf9 => 0x0142, 0xfa => 0x015b, 0xfb => 0x016b, + 0xfd => 0x017c, 0xfe => 0x017e, 0xff => 0x02d9, +); + +1; # end diff --git a/lib/Image/ExifTool/Charset/Cyrillic.pm b/lib/Image/ExifTool/Charset/Cyrillic.pm new file mode 100644 index 0000000..f7972d6 --- /dev/null +++ b/lib/Image/ExifTool/Charset/Cyrillic.pm @@ -0,0 +1,45 @@ +#------------------------------------------------------------------------------ +# File: Cyrillic.pm +# +# Description: cp1251 to Unicode +# +# Revisions: 2010/01/20 - P. Harvey created +# +# References: 1) http://unicode.org/Public/MAPPINGS/VENDORS/MICSFT/WINDOWS/CP1251.TXT +# +# Notes: The table omits 1-byte characters with the same values as Unicode +#------------------------------------------------------------------------------ +use strict; + +%Image::ExifTool::Charset::Cyrillic = ( + 0x80 => 0x0402, 0x81 => 0x0403, 0x82 => 0x201a, 0x83 => 0x0453, + 0x84 => 0x201e, 0x85 => 0x2026, 0x86 => 0x2020, 0x87 => 0x2021, + 0x88 => 0x20ac, 0x89 => 0x2030, 0x8a => 0x0409, 0x8b => 0x2039, + 0x8c => 0x040a, 0x8d => 0x040c, 0x8e => 0x040b, 0x8f => 0x040f, + 0x90 => 0x0452, 0x91 => 0x2018, 0x92 => 0x2019, 0x93 => 0x201c, + 0x94 => 0x201d, 0x95 => 0x2022, 0x96 => 0x2013, 0x97 => 0x2014, + 0x99 => 0x2122, 0x9a => 0x0459, 0x9b => 0x203a, 0x9c => 0x045a, + 0x9d => 0x045c, 0x9e => 0x045b, 0x9f => 0x045f, 0xa1 => 0x040e, + 0xa2 => 0x045e, 0xa3 => 0x0408, 0xa5 => 0x0490, 0xa8 => 0x0401, + 0xaa => 0x0404, 0xaf => 0x0407, 0xb2 => 0x0406, 0xb3 => 0x0456, + 0xb4 => 0x0491, 0xb8 => 0x0451, 0xb9 => 0x2116, 0xba => 0x0454, + 0xbc => 0x0458, 0xbd => 0x0405, 0xbe => 0x0455, 0xbf => 0x0457, + 0xc0 => 0x0410, 0xc1 => 0x0411, 0xc2 => 0x0412, 0xc3 => 0x0413, + 0xc4 => 0x0414, 0xc5 => 0x0415, 0xc6 => 0x0416, 0xc7 => 0x0417, + 0xc8 => 0x0418, 0xc9 => 0x0419, 0xca => 0x041a, 0xcb => 0x041b, + 0xcc => 0x041c, 0xcd => 0x041d, 0xce => 0x041e, 0xcf => 0x041f, + 0xd0 => 0x0420, 0xd1 => 0x0421, 0xd2 => 0x0422, 0xd3 => 0x0423, + 0xd4 => 0x0424, 0xd5 => 0x0425, 0xd6 => 0x0426, 0xd7 => 0x0427, + 0xd8 => 0x0428, 0xd9 => 0x0429, 0xda => 0x042a, 0xdb => 0x042b, + 0xdc => 0x042c, 0xdd => 0x042d, 0xde => 0x042e, 0xdf => 0x042f, + 0xe0 => 0x0430, 0xe1 => 0x0431, 0xe2 => 0x0432, 0xe3 => 0x0433, + 0xe4 => 0x0434, 0xe5 => 0x0435, 0xe6 => 0x0436, 0xe7 => 0x0437, + 0xe8 => 0x0438, 0xe9 => 0x0439, 0xea => 0x043a, 0xeb => 0x043b, + 0xec => 0x043c, 0xed => 0x043d, 0xee => 0x043e, 0xef => 0x043f, + 0xf0 => 0x0440, 0xf1 => 0x0441, 0xf2 => 0x0442, 0xf3 => 0x0443, + 0xf4 => 0x0444, 0xf5 => 0x0445, 0xf6 => 0x0446, 0xf7 => 0x0447, + 0xf8 => 0x0448, 0xf9 => 0x0449, 0xfa => 0x044a, 0xfb => 0x044b, + 0xfc => 0x044c, 0xfd => 0x044d, 0xfe => 0x044e, 0xff => 0x044f, +); + +1; # end diff --git a/lib/Image/ExifTool/Charset/DOSLatin1.pm b/lib/Image/ExifTool/Charset/DOSLatin1.pm new file mode 100644 index 0000000..2e3fd15 --- /dev/null +++ b/lib/Image/ExifTool/Charset/DOSLatin1.pm @@ -0,0 +1,49 @@ +#------------------------------------------------------------------------------ +# File: DOSLatin1.pm +# +# Description: cp850 to Unicode +# +# Revisions: 2017/10/31- P. Harvey created +# +# References: 1) http://unicode.org/Public/MAPPINGS/VENDORS/MICSFT/PC/CP850.TXT +# +# Notes: The table omits 1-byte characters with the same values as Unicode +#------------------------------------------------------------------------------ +use strict; + +%Image::ExifTool::Charset::DOSLatin1 = ( + 0x80 => 0x00c7, 0x81 => 0x00fc, 0x82 => 0x00e9, 0x83 => 0x00e2, + 0x84 => 0x00e4, 0x85 => 0x00e0, 0x86 => 0x00e5, 0x87 => 0x00e7, + 0x88 => 0x00ea, 0x89 => 0x00eb, 0x8a => 0x00e8, 0x8b => 0x00ef, + 0x8c => 0x00ee, 0x8d => 0x00ec, 0x8e => 0x00c4, 0x8f => 0x00c5, + 0x90 => 0x00c9, 0x91 => 0x00e6, 0x92 => 0x00c6, 0x93 => 0x00f4, + 0x94 => 0x00f6, 0x95 => 0x00f2, 0x96 => 0x00fb, 0x97 => 0x00f9, + 0x98 => 0x00ff, 0x99 => 0x00d6, 0x9a => 0x00dc, 0x9b => 0x00f8, + 0x9c => 0x00a3, 0x9d => 0x00d8, 0x9e => 0x00d7, 0x9f => 0x0192, + 0xa0 => 0x00e1, 0xa1 => 0x00ed, 0xa2 => 0x00f3, 0xa3 => 0x00fa, + 0xa4 => 0x00f1, 0xa5 => 0x00d1, 0xa6 => 0x00aa, 0xa7 => 0x00ba, + 0xa8 => 0x00bf, 0xa9 => 0x00ae, 0xaa => 0x00ac, 0xab => 0x00bd, + 0xac => 0x00bc, 0xad => 0x00a1, 0xae => 0x00ab, 0xaf => 0x00bb, + 0xb0 => 0x2591, 0xb1 => 0x2592, 0xb2 => 0x2593, 0xb3 => 0x2502, + 0xb4 => 0x2524, 0xb5 => 0x00c1, 0xb6 => 0x00c2, 0xb7 => 0x00c0, + 0xb8 => 0x00a9, 0xb9 => 0x2563, 0xba => 0x2551, 0xbb => 0x2557, + 0xbc => 0x255d, 0xbd => 0x00a2, 0xbe => 0x00a5, 0xbf => 0x2510, + 0xc0 => 0x2514, 0xc1 => 0x2534, 0xc2 => 0x252c, 0xc3 => 0x251c, + 0xc4 => 0x2500, 0xc5 => 0x253c, 0xc6 => 0x00e3, 0xc7 => 0x00c3, + 0xc8 => 0x255a, 0xc9 => 0x2554, 0xca => 0x2569, 0xcb => 0x2566, + 0xcc => 0x2560, 0xcd => 0x2550, 0xce => 0x256c, 0xcf => 0x00a4, + 0xd0 => 0x00f0, 0xd1 => 0x00d0, 0xd2 => 0x00ca, 0xd3 => 0x00cb, + 0xd4 => 0x00c8, 0xd5 => 0x0131, 0xd6 => 0x00cd, 0xd7 => 0x00ce, + 0xd8 => 0x00cf, 0xd9 => 0x2518, 0xda => 0x250c, 0xdb => 0x2588, + 0xdc => 0x2584, 0xdd => 0x00a6, 0xde => 0x00cc, 0xdf => 0x2580, + 0xe0 => 0x00d3, 0xe1 => 0x00df, 0xe2 => 0x00d4, 0xe3 => 0x00d2, + 0xe4 => 0x00f5, 0xe5 => 0x00d5, 0xe6 => 0x00b5, 0xe7 => 0x00fe, + 0xe8 => 0x00de, 0xe9 => 0x00da, 0xea => 0x00db, 0xeb => 0x00d9, + 0xec => 0x00fd, 0xed => 0x00dd, 0xee => 0x00af, 0xef => 0x00b4, + 0xf0 => 0x00ad, 0xf1 => 0x00b1, 0xf2 => 0x2017, 0xf3 => 0x00be, + 0xf4 => 0x00b6, 0xf5 => 0x00a7, 0xf6 => 0x00f7, 0xf7 => 0x00b8, + 0xf8 => 0x00b0, 0xf9 => 0x00a8, 0xfa => 0x00b7, 0xfb => 0x00b9, + 0xfc => 0x00b3, 0xfd => 0x00b2, 0xfe => 0x25a0, 0xff => 0x00a0, +); + +1; # end diff --git a/lib/Image/ExifTool/Charset/DOSLatinUS.pm b/lib/Image/ExifTool/Charset/DOSLatinUS.pm new file mode 100644 index 0000000..7f76823 --- /dev/null +++ b/lib/Image/ExifTool/Charset/DOSLatinUS.pm @@ -0,0 +1,49 @@ +#------------------------------------------------------------------------------ +# File: DOSLatinUS.pm +# +# Description: cp437 to Unicode +# +# Revisions: 2017/10/31- P. Harvey created +# +# References: 1) http://unicode.org/Public/MAPPINGS/VENDORS/MICSFT/PC/CP437.TXT +# +# Notes: The table omits 1-byte characters with the same values as Unicode +#------------------------------------------------------------------------------ +use strict; + +%Image::ExifTool::Charset::DOSLatinUS = ( + 0x80 => 0x00c7, 0x81 => 0x00fc, 0x82 => 0x00e9, 0x83 => 0x00e2, + 0x84 => 0x00e4, 0x85 => 0x00e0, 0x86 => 0x00e5, 0x87 => 0x00e7, + 0x88 => 0x00ea, 0x89 => 0x00eb, 0x8a => 0x00e8, 0x8b => 0x00ef, + 0x8c => 0x00ee, 0x8d => 0x00ec, 0x8e => 0x00c4, 0x8f => 0x00c5, + 0x90 => 0x00c9, 0x91 => 0x00e6, 0x92 => 0x00c6, 0x93 => 0x00f4, + 0x94 => 0x00f6, 0x95 => 0x00f2, 0x96 => 0x00fb, 0x97 => 0x00f9, + 0x98 => 0x00ff, 0x99 => 0x00d6, 0x9a => 0x00dc, 0x9b => 0x00a2, + 0x9c => 0x00a3, 0x9d => 0x00a5, 0x9e => 0x20a7, 0x9f => 0x0192, + 0xa0 => 0x00e1, 0xa1 => 0x00ed, 0xa2 => 0x00f3, 0xa3 => 0x00fa, + 0xa4 => 0x00f1, 0xa5 => 0x00d1, 0xa6 => 0x00aa, 0xa7 => 0x00ba, + 0xa8 => 0x00bf, 0xa9 => 0x2310, 0xaa => 0x00ac, 0xab => 0x00bd, + 0xac => 0x00bc, 0xad => 0x00a1, 0xae => 0x00ab, 0xaf => 0x00bb, + 0xb0 => 0x2591, 0xb1 => 0x2592, 0xb2 => 0x2593, 0xb3 => 0x2502, + 0xb4 => 0x2524, 0xb5 => 0x2561, 0xb6 => 0x2562, 0xb7 => 0x2556, + 0xb8 => 0x2555, 0xb9 => 0x2563, 0xba => 0x2551, 0xbb => 0x2557, + 0xbc => 0x255d, 0xbd => 0x255c, 0xbe => 0x255b, 0xbf => 0x2510, + 0xc0 => 0x2514, 0xc1 => 0x2534, 0xc2 => 0x252c, 0xc3 => 0x251c, + 0xc4 => 0x2500, 0xc5 => 0x253c, 0xc6 => 0x255e, 0xc7 => 0x255f, + 0xc8 => 0x255a, 0xc9 => 0x2554, 0xca => 0x2569, 0xcb => 0x2566, + 0xcc => 0x2560, 0xcd => 0x2550, 0xce => 0x256c, 0xcf => 0x2567, + 0xd0 => 0x2568, 0xd1 => 0x2564, 0xd2 => 0x2565, 0xd3 => 0x2559, + 0xd4 => 0x2558, 0xd5 => 0x2552, 0xd6 => 0x2553, 0xd7 => 0x256b, + 0xd8 => 0x256a, 0xd9 => 0x2518, 0xda => 0x250c, 0xdb => 0x2588, + 0xdc => 0x2584, 0xdd => 0x258c, 0xde => 0x2590, 0xdf => 0x2580, + 0xe0 => 0x03b1, 0xe1 => 0x00df, 0xe2 => 0x0393, 0xe3 => 0x03c0, + 0xe4 => 0x03a3, 0xe5 => 0x03c3, 0xe6 => 0x00b5, 0xe7 => 0x03c4, + 0xe8 => 0x03a6, 0xe9 => 0x0398, 0xea => 0x03a9, 0xeb => 0x03b4, + 0xec => 0x221e, 0xed => 0x03c6, 0xee => 0x03b5, 0xef => 0x2229, + 0xf0 => 0x2261, 0xf1 => 0x00b1, 0xf2 => 0x2265, 0xf3 => 0x2264, + 0xf4 => 0x2320, 0xf5 => 0x2321, 0xf6 => 0x00f7, 0xf7 => 0x2248, + 0xf8 => 0x00b0, 0xf9 => 0x2219, 0xfa => 0x00b7, 0xfb => 0x221a, + 0xfc => 0x207f, 0xfd => 0x00b2, 0xfe => 0x25a0, 0xff => 0x00a0, +); + +1; # end diff --git a/lib/Image/ExifTool/Charset/Greek.pm b/lib/Image/ExifTool/Charset/Greek.pm new file mode 100644 index 0000000..a1bcb8e --- /dev/null +++ b/lib/Image/ExifTool/Charset/Greek.pm @@ -0,0 +1,40 @@ +#------------------------------------------------------------------------------ +# File: Greek.pm +# +# Description: cp1253 to Unicode +# +# Revisions: 2010/01/20 - P. Harvey created +# +# References: 1) http://unicode.org/Public/MAPPINGS/VENDORS/MICSFT/WINDOWS/CP1253.TXT +# +# Notes: The table omits 1-byte characters with the same values as Unicode +#------------------------------------------------------------------------------ +use strict; + +%Image::ExifTool::Charset::Greek = ( + 0x80 => 0x20ac, 0x82 => 0x201a, 0x83 => 0x0192, 0x84 => 0x201e, + 0x85 => 0x2026, 0x86 => 0x2020, 0x87 => 0x2021, 0x89 => 0x2030, + 0x8b => 0x2039, 0x91 => 0x2018, 0x92 => 0x2019, 0x93 => 0x201c, + 0x94 => 0x201d, 0x95 => 0x2022, 0x96 => 0x2013, 0x97 => 0x2014, + 0x99 => 0x2122, 0x9b => 0x203a, 0xa1 => 0x0385, 0xa2 => 0x0386, + 0xaf => 0x2015, 0xb4 => 0x0384, 0xb8 => 0x0388, 0xb9 => 0x0389, + 0xba => 0x038a, 0xbc => 0x038c, 0xbe => 0x038e, 0xbf => 0x038f, + 0xc0 => 0x0390, 0xc1 => 0x0391, 0xc2 => 0x0392, 0xc3 => 0x0393, + 0xc4 => 0x0394, 0xc5 => 0x0395, 0xc6 => 0x0396, 0xc7 => 0x0397, + 0xc8 => 0x0398, 0xc9 => 0x0399, 0xca => 0x039a, 0xcb => 0x039b, + 0xcc => 0x039c, 0xcd => 0x039d, 0xce => 0x039e, 0xcf => 0x039f, + 0xd0 => 0x03a0, 0xd1 => 0x03a1, 0xd3 => 0x03a3, 0xd4 => 0x03a4, + 0xd5 => 0x03a5, 0xd6 => 0x03a6, 0xd7 => 0x03a7, 0xd8 => 0x03a8, + 0xd9 => 0x03a9, 0xda => 0x03aa, 0xdb => 0x03ab, 0xdc => 0x03ac, + 0xdd => 0x03ad, 0xde => 0x03ae, 0xdf => 0x03af, 0xe0 => 0x03b0, + 0xe1 => 0x03b1, 0xe2 => 0x03b2, 0xe3 => 0x03b3, 0xe4 => 0x03b4, + 0xe5 => 0x03b5, 0xe6 => 0x03b6, 0xe7 => 0x03b7, 0xe8 => 0x03b8, + 0xe9 => 0x03b9, 0xea => 0x03ba, 0xeb => 0x03bb, 0xec => 0x03bc, + 0xed => 0x03bd, 0xee => 0x03be, 0xef => 0x03bf, 0xf0 => 0x03c0, + 0xf1 => 0x03c1, 0xf2 => 0x03c2, 0xf3 => 0x03c3, 0xf4 => 0x03c4, + 0xf5 => 0x03c5, 0xf6 => 0x03c6, 0xf7 => 0x03c7, 0xf8 => 0x03c8, + 0xf9 => 0x03c9, 0xfa => 0x03ca, 0xfb => 0x03cb, 0xfc => 0x03cc, + 0xfd => 0x03cd, 0xfe => 0x03ce, +); + +1; # end diff --git a/lib/Image/ExifTool/Charset/Hebrew.pm b/lib/Image/ExifTool/Charset/Hebrew.pm new file mode 100644 index 0000000..6cebced --- /dev/null +++ b/lib/Image/ExifTool/Charset/Hebrew.pm @@ -0,0 +1,36 @@ +#------------------------------------------------------------------------------ +# File: Hebrew.pm +# +# Description: cp1255 to Unicode +# +# Revisions: 2010/01/20 - P. Harvey created +# +# References: 1) http://unicode.org/Public/MAPPINGS/VENDORS/MICSFT/WINDOWS/CP1255.TXT +# +# Notes: The table omits 1-byte characters with the same values as Unicode +#------------------------------------------------------------------------------ +use strict; + +%Image::ExifTool::Charset::Hebrew = ( + 0x80 => 0x20ac, 0x82 => 0x201a, 0x83 => 0x0192, 0x84 => 0x201e, + 0x85 => 0x2026, 0x86 => 0x2020, 0x87 => 0x2021, 0x88 => 0x02c6, + 0x89 => 0x2030, 0x8b => 0x2039, 0x91 => 0x2018, 0x92 => 0x2019, + 0x93 => 0x201c, 0x94 => 0x201d, 0x95 => 0x2022, 0x96 => 0x2013, + 0x97 => 0x2014, 0x98 => 0x02dc, 0x99 => 0x2122, 0x9b => 0x203a, + 0xa4 => 0x20aa, 0xaa => 0xd7, 0xba => 0xf7, 0xc0 => 0x05b0, 0xc1 => 0x05b1, + 0xc2 => 0x05b2, 0xc3 => 0x05b3, 0xc4 => 0x05b4, 0xc5 => 0x05b5, + 0xc6 => 0x05b6, 0xc7 => 0x05b7, 0xc8 => 0x05b8, 0xc9 => 0x05b9, + 0xcb => 0x05bb, 0xcc => 0x05bc, 0xcd => 0x05bd, 0xce => 0x05be, + 0xcf => 0x05bf, 0xd0 => 0x05c0, 0xd1 => 0x05c1, 0xd2 => 0x05c2, + 0xd3 => 0x05c3, 0xd4 => 0x05f0, 0xd5 => 0x05f1, 0xd6 => 0x05f2, + 0xd7 => 0x05f3, 0xd8 => 0x05f4, 0xe0 => 0x05d0, 0xe1 => 0x05d1, + 0xe2 => 0x05d2, 0xe3 => 0x05d3, 0xe4 => 0x05d4, 0xe5 => 0x05d5, + 0xe6 => 0x05d6, 0xe7 => 0x05d7, 0xe8 => 0x05d8, 0xe9 => 0x05d9, + 0xea => 0x05da, 0xeb => 0x05db, 0xec => 0x05dc, 0xed => 0x05dd, + 0xee => 0x05de, 0xef => 0x05df, 0xf0 => 0x05e0, 0xf1 => 0x05e1, + 0xf2 => 0x05e2, 0xf3 => 0x05e3, 0xf4 => 0x05e4, 0xf5 => 0x05e5, + 0xf6 => 0x05e6, 0xf7 => 0x05e7, 0xf8 => 0x05e8, 0xf9 => 0x05e9, + 0xfa => 0x05ea, 0xfd => 0x200e, 0xfe => 0x200f, +); + +1; # end diff --git a/lib/Image/ExifTool/Charset/JIS.pm b/lib/Image/ExifTool/Charset/JIS.pm new file mode 100644 index 0000000..d4411cb --- /dev/null +++ b/lib/Image/ExifTool/Charset/JIS.pm @@ -0,0 +1,1735 @@ +#------------------------------------------------------------------------------ +# File: JIS.pm +# +# Description: JIS X 0208 (1990) to Unicode +# +# Revisions: 2010/01/20 - P. Harvey created +# +# References: 1) http://unicode.org/Public/MAPPINGS/OBSOLETE/EASTASIA/JIS/JIS0208.TXT +#------------------------------------------------------------------------------ +use strict; + +%Image::ExifTool::Charset::JIS = ( + 0x2121 => 0x3000, 0x2122 => 0x3001, 0x2123 => 0x3002, 0x2124 => 0xff0c, + 0x2125 => 0xff0e, 0x2126 => 0x30fb, 0x2127 => 0xff1a, 0x2128 => 0xff1b, + 0x2129 => 0xff1f, 0x212a => 0xff01, 0x212b => 0x309b, 0x212c => 0x309c, + 0x212d => 0x00b4, 0x212e => 0xff40, 0x212f => 0x00a8, 0x2130 => 0xff3e, + 0x2131 => 0xffe3, 0x2132 => 0xff3f, 0x2133 => 0x30fd, 0x2134 => 0x30fe, + 0x2135 => 0x309d, 0x2136 => 0x309e, 0x2137 => 0x3003, 0x2138 => 0x4edd, + 0x2139 => 0x3005, 0x213a => 0x3006, 0x213b => 0x3007, 0x213c => 0x30fc, + 0x213d => 0x2015, 0x213e => 0x2010, 0x213f => 0xff0f, 0x2140 => 0x005c, + 0x2141 => 0x301c, 0x2142 => 0x2016, 0x2143 => 0xff5c, 0x2144 => 0x2026, + 0x2145 => 0x2025, 0x2146 => 0x2018, 0x2147 => 0x2019, 0x2148 => 0x201c, + 0x2149 => 0x201d, 0x214a => 0xff08, 0x214b => 0xff09, 0x214c => 0x3014, + 0x214d => 0x3015, 0x214e => 0xff3b, 0x214f => 0xff3d, 0x2150 => 0xff5b, + 0x2151 => 0xff5d, 0x2152 => 0x3008, 0x2153 => 0x3009, 0x2154 => 0x300a, + 0x2155 => 0x300b, 0x2156 => 0x300c, 0x2157 => 0x300d, 0x2158 => 0x300e, + 0x2159 => 0x300f, 0x215a => 0x3010, 0x215b => 0x3011, 0x215c => 0xff0b, + 0x215d => 0x2212, 0x215e => 0x00b1, 0x215f => 0x00d7, 0x2160 => 0x00f7, + 0x2161 => 0xff1d, 0x2162 => 0x2260, 0x2163 => 0xff1c, 0x2164 => 0xff1e, + 0x2165 => 0x2266, 0x2166 => 0x2267, 0x2167 => 0x221e, 0x2168 => 0x2234, + 0x2169 => 0x2642, 0x216a => 0x2640, 0x216b => 0x00b0, 0x216c => 0x2032, + 0x216d => 0x2033, 0x216e => 0x2103, 0x216f => 0xffe5, 0x2170 => 0xff04, + 0x2171 => 0x00a2, 0x2172 => 0x00a3, 0x2173 => 0xff05, 0x2174 => 0xff03, + 0x2175 => 0xff06, 0x2176 => 0xff0a, 0x2177 => 0xff20, 0x2178 => 0x00a7, + 0x2179 => 0x2606, 0x217a => 0x2605, 0x217b => 0x25cb, 0x217c => 0x25cf, + 0x217d => 0x25ce, 0x217e => 0x25c7, 0x2221 => 0x25c6, 0x2222 => 0x25a1, + 0x2223 => 0x25a0, 0x2224 => 0x25b3, 0x2225 => 0x25b2, 0x2226 => 0x25bd, + 0x2227 => 0x25bc, 0x2228 => 0x203b, 0x2229 => 0x3012, 0x222a => 0x2192, + 0x222b => 0x2190, 0x222c => 0x2191, 0x222d => 0x2193, 0x222e => 0x3013, + 0x223a => 0x2208, 0x223b => 0x220b, 0x223c => 0x2286, 0x223d => 0x2287, + 0x223e => 0x2282, 0x223f => 0x2283, 0x2240 => 0x222a, 0x2241 => 0x2229, + 0x224a => 0x2227, 0x224b => 0x2228, 0x224c => 0x00ac, 0x224d => 0x21d2, + 0x224e => 0x21d4, 0x224f => 0x2200, 0x2250 => 0x2203, 0x225c => 0x2220, + 0x225d => 0x22a5, 0x225e => 0x2312, 0x225f => 0x2202, 0x2260 => 0x2207, + 0x2261 => 0x2261, 0x2262 => 0x2252, 0x2263 => 0x226a, 0x2264 => 0x226b, + 0x2265 => 0x221a, 0x2266 => 0x223d, 0x2267 => 0x221d, 0x2268 => 0x2235, + 0x2269 => 0x222b, 0x226a => 0x222c, 0x2272 => 0x212b, 0x2273 => 0x2030, + 0x2274 => 0x266f, 0x2275 => 0x266d, 0x2276 => 0x266a, 0x2277 => 0x2020, + 0x2278 => 0x2021, 0x2279 => 0x00b6, 0x227e => 0x25ef, 0x2330 => 0xff10, + 0x2331 => 0xff11, 0x2332 => 0xff12, 0x2333 => 0xff13, 0x2334 => 0xff14, + 0x2335 => 0xff15, 0x2336 => 0xff16, 0x2337 => 0xff17, 0x2338 => 0xff18, + 0x2339 => 0xff19, 0x2341 => 0xff21, 0x2342 => 0xff22, 0x2343 => 0xff23, + 0x2344 => 0xff24, 0x2345 => 0xff25, 0x2346 => 0xff26, 0x2347 => 0xff27, + 0x2348 => 0xff28, 0x2349 => 0xff29, 0x234a => 0xff2a, 0x234b => 0xff2b, + 0x234c => 0xff2c, 0x234d => 0xff2d, 0x234e => 0xff2e, 0x234f => 0xff2f, + 0x2350 => 0xff30, 0x2351 => 0xff31, 0x2352 => 0xff32, 0x2353 => 0xff33, + 0x2354 => 0xff34, 0x2355 => 0xff35, 0x2356 => 0xff36, 0x2357 => 0xff37, + 0x2358 => 0xff38, 0x2359 => 0xff39, 0x235a => 0xff3a, 0x2361 => 0xff41, + 0x2362 => 0xff42, 0x2363 => 0xff43, 0x2364 => 0xff44, 0x2365 => 0xff45, + 0x2366 => 0xff46, 0x2367 => 0xff47, 0x2368 => 0xff48, 0x2369 => 0xff49, + 0x236a => 0xff4a, 0x236b => 0xff4b, 0x236c => 0xff4c, 0x236d => 0xff4d, + 0x236e => 0xff4e, 0x236f => 0xff4f, 0x2370 => 0xff50, 0x2371 => 0xff51, + 0x2372 => 0xff52, 0x2373 => 0xff53, 0x2374 => 0xff54, 0x2375 => 0xff55, + 0x2376 => 0xff56, 0x2377 => 0xff57, 0x2378 => 0xff58, 0x2379 => 0xff59, + 0x237a => 0xff5a, 0x2421 => 0x3041, 0x2422 => 0x3042, 0x2423 => 0x3043, + 0x2424 => 0x3044, 0x2425 => 0x3045, 0x2426 => 0x3046, 0x2427 => 0x3047, + 0x2428 => 0x3048, 0x2429 => 0x3049, 0x242a => 0x304a, 0x242b => 0x304b, + 0x242c => 0x304c, 0x242d => 0x304d, 0x242e => 0x304e, 0x242f => 0x304f, + 0x2430 => 0x3050, 0x2431 => 0x3051, 0x2432 => 0x3052, 0x2433 => 0x3053, + 0x2434 => 0x3054, 0x2435 => 0x3055, 0x2436 => 0x3056, 0x2437 => 0x3057, + 0x2438 => 0x3058, 0x2439 => 0x3059, 0x243a => 0x305a, 0x243b => 0x305b, + 0x243c => 0x305c, 0x243d => 0x305d, 0x243e => 0x305e, 0x243f => 0x305f, + 0x2440 => 0x3060, 0x2441 => 0x3061, 0x2442 => 0x3062, 0x2443 => 0x3063, + 0x2444 => 0x3064, 0x2445 => 0x3065, 0x2446 => 0x3066, 0x2447 => 0x3067, + 0x2448 => 0x3068, 0x2449 => 0x3069, 0x244a => 0x306a, 0x244b => 0x306b, + 0x244c => 0x306c, 0x244d => 0x306d, 0x244e => 0x306e, 0x244f => 0x306f, + 0x2450 => 0x3070, 0x2451 => 0x3071, 0x2452 => 0x3072, 0x2453 => 0x3073, + 0x2454 => 0x3074, 0x2455 => 0x3075, 0x2456 => 0x3076, 0x2457 => 0x3077, + 0x2458 => 0x3078, 0x2459 => 0x3079, 0x245a => 0x307a, 0x245b => 0x307b, + 0x245c => 0x307c, 0x245d => 0x307d, 0x245e => 0x307e, 0x245f => 0x307f, + 0x2460 => 0x3080, 0x2461 => 0x3081, 0x2462 => 0x3082, 0x2463 => 0x3083, + 0x2464 => 0x3084, 0x2465 => 0x3085, 0x2466 => 0x3086, 0x2467 => 0x3087, + 0x2468 => 0x3088, 0x2469 => 0x3089, 0x246a => 0x308a, 0x246b => 0x308b, + 0x246c => 0x308c, 0x246d => 0x308d, 0x246e => 0x308e, 0x246f => 0x308f, + 0x2470 => 0x3090, 0x2471 => 0x3091, 0x2472 => 0x3092, 0x2473 => 0x3093, + 0x2521 => 0x30a1, 0x2522 => 0x30a2, 0x2523 => 0x30a3, 0x2524 => 0x30a4, + 0x2525 => 0x30a5, 0x2526 => 0x30a6, 0x2527 => 0x30a7, 0x2528 => 0x30a8, + 0x2529 => 0x30a9, 0x252a => 0x30aa, 0x252b => 0x30ab, 0x252c => 0x30ac, + 0x252d => 0x30ad, 0x252e => 0x30ae, 0x252f => 0x30af, 0x2530 => 0x30b0, + 0x2531 => 0x30b1, 0x2532 => 0x30b2, 0x2533 => 0x30b3, 0x2534 => 0x30b4, + 0x2535 => 0x30b5, 0x2536 => 0x30b6, 0x2537 => 0x30b7, 0x2538 => 0x30b8, + 0x2539 => 0x30b9, 0x253a => 0x30ba, 0x253b => 0x30bb, 0x253c => 0x30bc, + 0x253d => 0x30bd, 0x253e => 0x30be, 0x253f => 0x30bf, 0x2540 => 0x30c0, + 0x2541 => 0x30c1, 0x2542 => 0x30c2, 0x2543 => 0x30c3, 0x2544 => 0x30c4, + 0x2545 => 0x30c5, 0x2546 => 0x30c6, 0x2547 => 0x30c7, 0x2548 => 0x30c8, + 0x2549 => 0x30c9, 0x254a => 0x30ca, 0x254b => 0x30cb, 0x254c => 0x30cc, + 0x254d => 0x30cd, 0x254e => 0x30ce, 0x254f => 0x30cf, 0x2550 => 0x30d0, + 0x2551 => 0x30d1, 0x2552 => 0x30d2, 0x2553 => 0x30d3, 0x2554 => 0x30d4, + 0x2555 => 0x30d5, 0x2556 => 0x30d6, 0x2557 => 0x30d7, 0x2558 => 0x30d8, + 0x2559 => 0x30d9, 0x255a => 0x30da, 0x255b => 0x30db, 0x255c => 0x30dc, + 0x255d => 0x30dd, 0x255e => 0x30de, 0x255f => 0x30df, 0x2560 => 0x30e0, + 0x2561 => 0x30e1, 0x2562 => 0x30e2, 0x2563 => 0x30e3, 0x2564 => 0x30e4, + 0x2565 => 0x30e5, 0x2566 => 0x30e6, 0x2567 => 0x30e7, 0x2568 => 0x30e8, + 0x2569 => 0x30e9, 0x256a => 0x30ea, 0x256b => 0x30eb, 0x256c => 0x30ec, + 0x256d => 0x30ed, 0x256e => 0x30ee, 0x256f => 0x30ef, 0x2570 => 0x30f0, + 0x2571 => 0x30f1, 0x2572 => 0x30f2, 0x2573 => 0x30f3, 0x2574 => 0x30f4, + 0x2575 => 0x30f5, 0x2576 => 0x30f6, 0x2621 => 0x0391, 0x2622 => 0x0392, + 0x2623 => 0x0393, 0x2624 => 0x0394, 0x2625 => 0x0395, 0x2626 => 0x0396, + 0x2627 => 0x0397, 0x2628 => 0x0398, 0x2629 => 0x0399, 0x262a => 0x039a, + 0x262b => 0x039b, 0x262c => 0x039c, 0x262d => 0x039d, 0x262e => 0x039e, + 0x262f => 0x039f, 0x2630 => 0x03a0, 0x2631 => 0x03a1, 0x2632 => 0x03a3, + 0x2633 => 0x03a4, 0x2634 => 0x03a5, 0x2635 => 0x03a6, 0x2636 => 0x03a7, + 0x2637 => 0x03a8, 0x2638 => 0x03a9, 0x2641 => 0x03b1, 0x2642 => 0x03b2, + 0x2643 => 0x03b3, 0x2644 => 0x03b4, 0x2645 => 0x03b5, 0x2646 => 0x03b6, + 0x2647 => 0x03b7, 0x2648 => 0x03b8, 0x2649 => 0x03b9, 0x264a => 0x03ba, + 0x264b => 0x03bb, 0x264c => 0x03bc, 0x264d => 0x03bd, 0x264e => 0x03be, + 0x264f => 0x03bf, 0x2650 => 0x03c0, 0x2651 => 0x03c1, 0x2652 => 0x03c3, + 0x2653 => 0x03c4, 0x2654 => 0x03c5, 0x2655 => 0x03c6, 0x2656 => 0x03c7, + 0x2657 => 0x03c8, 0x2658 => 0x03c9, 0x2721 => 0x0410, 0x2722 => 0x0411, + 0x2723 => 0x0412, 0x2724 => 0x0413, 0x2725 => 0x0414, 0x2726 => 0x0415, + 0x2727 => 0x0401, 0x2728 => 0x0416, 0x2729 => 0x0417, 0x272a => 0x0418, + 0x272b => 0x0419, 0x272c => 0x041a, 0x272d => 0x041b, 0x272e => 0x041c, + 0x272f => 0x041d, 0x2730 => 0x041e, 0x2731 => 0x041f, 0x2732 => 0x0420, + 0x2733 => 0x0421, 0x2734 => 0x0422, 0x2735 => 0x0423, 0x2736 => 0x0424, + 0x2737 => 0x0425, 0x2738 => 0x0426, 0x2739 => 0x0427, 0x273a => 0x0428, + 0x273b => 0x0429, 0x273c => 0x042a, 0x273d => 0x042b, 0x273e => 0x042c, + 0x273f => 0x042d, 0x2740 => 0x042e, 0x2741 => 0x042f, 0x2751 => 0x0430, + 0x2752 => 0x0431, 0x2753 => 0x0432, 0x2754 => 0x0433, 0x2755 => 0x0434, + 0x2756 => 0x0435, 0x2757 => 0x0451, 0x2758 => 0x0436, 0x2759 => 0x0437, + 0x275a => 0x0438, 0x275b => 0x0439, 0x275c => 0x043a, 0x275d => 0x043b, + 0x275e => 0x043c, 0x275f => 0x043d, 0x2760 => 0x043e, 0x2761 => 0x043f, + 0x2762 => 0x0440, 0x2763 => 0x0441, 0x2764 => 0x0442, 0x2765 => 0x0443, + 0x2766 => 0x0444, 0x2767 => 0x0445, 0x2768 => 0x0446, 0x2769 => 0x0447, + 0x276a => 0x0448, 0x276b => 0x0449, 0x276c => 0x044a, 0x276d => 0x044b, + 0x276e => 0x044c, 0x276f => 0x044d, 0x2770 => 0x044e, 0x2771 => 0x044f, + 0x2821 => 0x2500, 0x2822 => 0x2502, 0x2823 => 0x250c, 0x2824 => 0x2510, + 0x2825 => 0x2518, 0x2826 => 0x2514, 0x2827 => 0x251c, 0x2828 => 0x252c, + 0x2829 => 0x2524, 0x282a => 0x2534, 0x282b => 0x253c, 0x282c => 0x2501, + 0x282d => 0x2503, 0x282e => 0x250f, 0x282f => 0x2513, 0x2830 => 0x251b, + 0x2831 => 0x2517, 0x2832 => 0x2523, 0x2833 => 0x2533, 0x2834 => 0x252b, + 0x2835 => 0x253b, 0x2836 => 0x254b, 0x2837 => 0x2520, 0x2838 => 0x252f, + 0x2839 => 0x2528, 0x283a => 0x2537, 0x283b => 0x253f, 0x283c => 0x251d, + 0x283d => 0x2530, 0x283e => 0x2525, 0x283f => 0x2538, 0x2840 => 0x2542, + 0x3021 => 0x4e9c, 0x3022 => 0x5516, 0x3023 => 0x5a03, 0x3024 => 0x963f, + 0x3025 => 0x54c0, 0x3026 => 0x611b, 0x3027 => 0x6328, 0x3028 => 0x59f6, + 0x3029 => 0x9022, 0x302a => 0x8475, 0x302b => 0x831c, 0x302c => 0x7a50, + 0x302d => 0x60aa, 0x302e => 0x63e1, 0x302f => 0x6e25, 0x3030 => 0x65ed, + 0x3031 => 0x8466, 0x3032 => 0x82a6, 0x3033 => 0x9bf5, 0x3034 => 0x6893, + 0x3035 => 0x5727, 0x3036 => 0x65a1, 0x3037 => 0x6271, 0x3038 => 0x5b9b, + 0x3039 => 0x59d0, 0x303a => 0x867b, 0x303b => 0x98f4, 0x303c => 0x7d62, + 0x303d => 0x7dbe, 0x303e => 0x9b8e, 0x303f => 0x6216, 0x3040 => 0x7c9f, + 0x3041 => 0x88b7, 0x3042 => 0x5b89, 0x3043 => 0x5eb5, 0x3044 => 0x6309, + 0x3045 => 0x6697, 0x3046 => 0x6848, 0x3047 => 0x95c7, 0x3048 => 0x978d, + 0x3049 => 0x674f, 0x304a => 0x4ee5, 0x304b => 0x4f0a, 0x304c => 0x4f4d, + 0x304d => 0x4f9d, 0x304e => 0x5049, 0x304f => 0x56f2, 0x3050 => 0x5937, + 0x3051 => 0x59d4, 0x3052 => 0x5a01, 0x3053 => 0x5c09, 0x3054 => 0x60df, + 0x3055 => 0x610f, 0x3056 => 0x6170, 0x3057 => 0x6613, 0x3058 => 0x6905, + 0x3059 => 0x70ba, 0x305a => 0x754f, 0x305b => 0x7570, 0x305c => 0x79fb, + 0x305d => 0x7dad, 0x305e => 0x7def, 0x305f => 0x80c3, 0x3060 => 0x840e, + 0x3061 => 0x8863, 0x3062 => 0x8b02, 0x3063 => 0x9055, 0x3064 => 0x907a, + 0x3065 => 0x533b, 0x3066 => 0x4e95, 0x3067 => 0x4ea5, 0x3068 => 0x57df, + 0x3069 => 0x80b2, 0x306a => 0x90c1, 0x306b => 0x78ef, 0x306c => 0x4e00, + 0x306d => 0x58f1, 0x306e => 0x6ea2, 0x306f => 0x9038, 0x3070 => 0x7a32, + 0x3071 => 0x8328, 0x3072 => 0x828b, 0x3073 => 0x9c2f, 0x3074 => 0x5141, + 0x3075 => 0x5370, 0x3076 => 0x54bd, 0x3077 => 0x54e1, 0x3078 => 0x56e0, + 0x3079 => 0x59fb, 0x307a => 0x5f15, 0x307b => 0x98f2, 0x307c => 0x6deb, + 0x307d => 0x80e4, 0x307e => 0x852d, 0x3121 => 0x9662, 0x3122 => 0x9670, + 0x3123 => 0x96a0, 0x3124 => 0x97fb, 0x3125 => 0x540b, 0x3126 => 0x53f3, + 0x3127 => 0x5b87, 0x3128 => 0x70cf, 0x3129 => 0x7fbd, 0x312a => 0x8fc2, + 0x312b => 0x96e8, 0x312c => 0x536f, 0x312d => 0x9d5c, 0x312e => 0x7aba, + 0x312f => 0x4e11, 0x3130 => 0x7893, 0x3131 => 0x81fc, 0x3132 => 0x6e26, + 0x3133 => 0x5618, 0x3134 => 0x5504, 0x3135 => 0x6b1d, 0x3136 => 0x851a, + 0x3137 => 0x9c3b, 0x3138 => 0x59e5, 0x3139 => 0x53a9, 0x313a => 0x6d66, + 0x313b => 0x74dc, 0x313c => 0x958f, 0x313d => 0x5642, 0x313e => 0x4e91, + 0x313f => 0x904b, 0x3140 => 0x96f2, 0x3141 => 0x834f, 0x3142 => 0x990c, + 0x3143 => 0x53e1, 0x3144 => 0x55b6, 0x3145 => 0x5b30, 0x3146 => 0x5f71, + 0x3147 => 0x6620, 0x3148 => 0x66f3, 0x3149 => 0x6804, 0x314a => 0x6c38, + 0x314b => 0x6cf3, 0x314c => 0x6d29, 0x314d => 0x745b, 0x314e => 0x76c8, + 0x314f => 0x7a4e, 0x3150 => 0x9834, 0x3151 => 0x82f1, 0x3152 => 0x885b, + 0x3153 => 0x8a60, 0x3154 => 0x92ed, 0x3155 => 0x6db2, 0x3156 => 0x75ab, + 0x3157 => 0x76ca, 0x3158 => 0x99c5, 0x3159 => 0x60a6, 0x315a => 0x8b01, + 0x315b => 0x8d8a, 0x315c => 0x95b2, 0x315d => 0x698e, 0x315e => 0x53ad, + 0x315f => 0x5186, 0x3160 => 0x5712, 0x3161 => 0x5830, 0x3162 => 0x5944, + 0x3163 => 0x5bb4, 0x3164 => 0x5ef6, 0x3165 => 0x6028, 0x3166 => 0x63a9, + 0x3167 => 0x63f4, 0x3168 => 0x6cbf, 0x3169 => 0x6f14, 0x316a => 0x708e, + 0x316b => 0x7114, 0x316c => 0x7159, 0x316d => 0x71d5, 0x316e => 0x733f, + 0x316f => 0x7e01, 0x3170 => 0x8276, 0x3171 => 0x82d1, 0x3172 => 0x8597, + 0x3173 => 0x9060, 0x3174 => 0x925b, 0x3175 => 0x9d1b, 0x3176 => 0x5869, + 0x3177 => 0x65bc, 0x3178 => 0x6c5a, 0x3179 => 0x7525, 0x317a => 0x51f9, + 0x317b => 0x592e, 0x317c => 0x5965, 0x317d => 0x5f80, 0x317e => 0x5fdc, + 0x3221 => 0x62bc, 0x3222 => 0x65fa, 0x3223 => 0x6a2a, 0x3224 => 0x6b27, + 0x3225 => 0x6bb4, 0x3226 => 0x738b, 0x3227 => 0x7fc1, 0x3228 => 0x8956, + 0x3229 => 0x9d2c, 0x322a => 0x9d0e, 0x322b => 0x9ec4, 0x322c => 0x5ca1, + 0x322d => 0x6c96, 0x322e => 0x837b, 0x322f => 0x5104, 0x3230 => 0x5c4b, + 0x3231 => 0x61b6, 0x3232 => 0x81c6, 0x3233 => 0x6876, 0x3234 => 0x7261, + 0x3235 => 0x4e59, 0x3236 => 0x4ffa, 0x3237 => 0x5378, 0x3238 => 0x6069, + 0x3239 => 0x6e29, 0x323a => 0x7a4f, 0x323b => 0x97f3, 0x323c => 0x4e0b, + 0x323d => 0x5316, 0x323e => 0x4eee, 0x323f => 0x4f55, 0x3240 => 0x4f3d, + 0x3241 => 0x4fa1, 0x3242 => 0x4f73, 0x3243 => 0x52a0, 0x3244 => 0x53ef, + 0x3245 => 0x5609, 0x3246 => 0x590f, 0x3247 => 0x5ac1, 0x3248 => 0x5bb6, + 0x3249 => 0x5be1, 0x324a => 0x79d1, 0x324b => 0x6687, 0x324c => 0x679c, + 0x324d => 0x67b6, 0x324e => 0x6b4c, 0x324f => 0x6cb3, 0x3250 => 0x706b, + 0x3251 => 0x73c2, 0x3252 => 0x798d, 0x3253 => 0x79be, 0x3254 => 0x7a3c, + 0x3255 => 0x7b87, 0x3256 => 0x82b1, 0x3257 => 0x82db, 0x3258 => 0x8304, + 0x3259 => 0x8377, 0x325a => 0x83ef, 0x325b => 0x83d3, 0x325c => 0x8766, + 0x325d => 0x8ab2, 0x325e => 0x5629, 0x325f => 0x8ca8, 0x3260 => 0x8fe6, + 0x3261 => 0x904e, 0x3262 => 0x971e, 0x3263 => 0x868a, 0x3264 => 0x4fc4, + 0x3265 => 0x5ce8, 0x3266 => 0x6211, 0x3267 => 0x7259, 0x3268 => 0x753b, + 0x3269 => 0x81e5, 0x326a => 0x82bd, 0x326b => 0x86fe, 0x326c => 0x8cc0, + 0x326d => 0x96c5, 0x326e => 0x9913, 0x326f => 0x99d5, 0x3270 => 0x4ecb, + 0x3271 => 0x4f1a, 0x3272 => 0x89e3, 0x3273 => 0x56de, 0x3274 => 0x584a, + 0x3275 => 0x58ca, 0x3276 => 0x5efb, 0x3277 => 0x5feb, 0x3278 => 0x602a, + 0x3279 => 0x6094, 0x327a => 0x6062, 0x327b => 0x61d0, 0x327c => 0x6212, + 0x327d => 0x62d0, 0x327e => 0x6539, 0x3321 => 0x9b41, 0x3322 => 0x6666, + 0x3323 => 0x68b0, 0x3324 => 0x6d77, 0x3325 => 0x7070, 0x3326 => 0x754c, + 0x3327 => 0x7686, 0x3328 => 0x7d75, 0x3329 => 0x82a5, 0x332a => 0x87f9, + 0x332b => 0x958b, 0x332c => 0x968e, 0x332d => 0x8c9d, 0x332e => 0x51f1, + 0x332f => 0x52be, 0x3330 => 0x5916, 0x3331 => 0x54b3, 0x3332 => 0x5bb3, + 0x3333 => 0x5d16, 0x3334 => 0x6168, 0x3335 => 0x6982, 0x3336 => 0x6daf, + 0x3337 => 0x788d, 0x3338 => 0x84cb, 0x3339 => 0x8857, 0x333a => 0x8a72, + 0x333b => 0x93a7, 0x333c => 0x9ab8, 0x333d => 0x6d6c, 0x333e => 0x99a8, + 0x333f => 0x86d9, 0x3340 => 0x57a3, 0x3341 => 0x67ff, 0x3342 => 0x86ce, + 0x3343 => 0x920e, 0x3344 => 0x5283, 0x3345 => 0x5687, 0x3346 => 0x5404, + 0x3347 => 0x5ed3, 0x3348 => 0x62e1, 0x3349 => 0x64b9, 0x334a => 0x683c, + 0x334b => 0x6838, 0x334c => 0x6bbb, 0x334d => 0x7372, 0x334e => 0x78ba, + 0x334f => 0x7a6b, 0x3350 => 0x899a, 0x3351 => 0x89d2, 0x3352 => 0x8d6b, + 0x3353 => 0x8f03, 0x3354 => 0x90ed, 0x3355 => 0x95a3, 0x3356 => 0x9694, + 0x3357 => 0x9769, 0x3358 => 0x5b66, 0x3359 => 0x5cb3, 0x335a => 0x697d, + 0x335b => 0x984d, 0x335c => 0x984e, 0x335d => 0x639b, 0x335e => 0x7b20, + 0x335f => 0x6a2b, 0x3360 => 0x6a7f, 0x3361 => 0x68b6, 0x3362 => 0x9c0d, + 0x3363 => 0x6f5f, 0x3364 => 0x5272, 0x3365 => 0x559d, 0x3366 => 0x6070, + 0x3367 => 0x62ec, 0x3368 => 0x6d3b, 0x3369 => 0x6e07, 0x336a => 0x6ed1, + 0x336b => 0x845b, 0x336c => 0x8910, 0x336d => 0x8f44, 0x336e => 0x4e14, + 0x336f => 0x9c39, 0x3370 => 0x53f6, 0x3371 => 0x691b, 0x3372 => 0x6a3a, + 0x3373 => 0x9784, 0x3374 => 0x682a, 0x3375 => 0x515c, 0x3376 => 0x7ac3, + 0x3377 => 0x84b2, 0x3378 => 0x91dc, 0x3379 => 0x938c, 0x337a => 0x565b, + 0x337b => 0x9d28, 0x337c => 0x6822, 0x337d => 0x8305, 0x337e => 0x8431, + 0x3421 => 0x7ca5, 0x3422 => 0x5208, 0x3423 => 0x82c5, 0x3424 => 0x74e6, + 0x3425 => 0x4e7e, 0x3426 => 0x4f83, 0x3427 => 0x51a0, 0x3428 => 0x5bd2, + 0x3429 => 0x520a, 0x342a => 0x52d8, 0x342b => 0x52e7, 0x342c => 0x5dfb, + 0x342d => 0x559a, 0x342e => 0x582a, 0x342f => 0x59e6, 0x3430 => 0x5b8c, + 0x3431 => 0x5b98, 0x3432 => 0x5bdb, 0x3433 => 0x5e72, 0x3434 => 0x5e79, + 0x3435 => 0x60a3, 0x3436 => 0x611f, 0x3437 => 0x6163, 0x3438 => 0x61be, + 0x3439 => 0x63db, 0x343a => 0x6562, 0x343b => 0x67d1, 0x343c => 0x6853, + 0x343d => 0x68fa, 0x343e => 0x6b3e, 0x343f => 0x6b53, 0x3440 => 0x6c57, + 0x3441 => 0x6f22, 0x3442 => 0x6f97, 0x3443 => 0x6f45, 0x3444 => 0x74b0, + 0x3445 => 0x7518, 0x3446 => 0x76e3, 0x3447 => 0x770b, 0x3448 => 0x7aff, + 0x3449 => 0x7ba1, 0x344a => 0x7c21, 0x344b => 0x7de9, 0x344c => 0x7f36, + 0x344d => 0x7ff0, 0x344e => 0x809d, 0x344f => 0x8266, 0x3450 => 0x839e, + 0x3451 => 0x89b3, 0x3452 => 0x8acc, 0x3453 => 0x8cab, 0x3454 => 0x9084, + 0x3455 => 0x9451, 0x3456 => 0x9593, 0x3457 => 0x9591, 0x3458 => 0x95a2, + 0x3459 => 0x9665, 0x345a => 0x97d3, 0x345b => 0x9928, 0x345c => 0x8218, + 0x345d => 0x4e38, 0x345e => 0x542b, 0x345f => 0x5cb8, 0x3460 => 0x5dcc, + 0x3461 => 0x73a9, 0x3462 => 0x764c, 0x3463 => 0x773c, 0x3464 => 0x5ca9, + 0x3465 => 0x7feb, 0x3466 => 0x8d0b, 0x3467 => 0x96c1, 0x3468 => 0x9811, + 0x3469 => 0x9854, 0x346a => 0x9858, 0x346b => 0x4f01, 0x346c => 0x4f0e, + 0x346d => 0x5371, 0x346e => 0x559c, 0x346f => 0x5668, 0x3470 => 0x57fa, + 0x3471 => 0x5947, 0x3472 => 0x5b09, 0x3473 => 0x5bc4, 0x3474 => 0x5c90, + 0x3475 => 0x5e0c, 0x3476 => 0x5e7e, 0x3477 => 0x5fcc, 0x3478 => 0x63ee, + 0x3479 => 0x673a, 0x347a => 0x65d7, 0x347b => 0x65e2, 0x347c => 0x671f, + 0x347d => 0x68cb, 0x347e => 0x68c4, 0x3521 => 0x6a5f, 0x3522 => 0x5e30, + 0x3523 => 0x6bc5, 0x3524 => 0x6c17, 0x3525 => 0x6c7d, 0x3526 => 0x757f, + 0x3527 => 0x7948, 0x3528 => 0x5b63, 0x3529 => 0x7a00, 0x352a => 0x7d00, + 0x352b => 0x5fbd, 0x352c => 0x898f, 0x352d => 0x8a18, 0x352e => 0x8cb4, + 0x352f => 0x8d77, 0x3530 => 0x8ecc, 0x3531 => 0x8f1d, 0x3532 => 0x98e2, + 0x3533 => 0x9a0e, 0x3534 => 0x9b3c, 0x3535 => 0x4e80, 0x3536 => 0x507d, + 0x3537 => 0x5100, 0x3538 => 0x5993, 0x3539 => 0x5b9c, 0x353a => 0x622f, + 0x353b => 0x6280, 0x353c => 0x64ec, 0x353d => 0x6b3a, 0x353e => 0x72a0, + 0x353f => 0x7591, 0x3540 => 0x7947, 0x3541 => 0x7fa9, 0x3542 => 0x87fb, + 0x3543 => 0x8abc, 0x3544 => 0x8b70, 0x3545 => 0x63ac, 0x3546 => 0x83ca, + 0x3547 => 0x97a0, 0x3548 => 0x5409, 0x3549 => 0x5403, 0x354a => 0x55ab, + 0x354b => 0x6854, 0x354c => 0x6a58, 0x354d => 0x8a70, 0x354e => 0x7827, + 0x354f => 0x6775, 0x3550 => 0x9ecd, 0x3551 => 0x5374, 0x3552 => 0x5ba2, + 0x3553 => 0x811a, 0x3554 => 0x8650, 0x3555 => 0x9006, 0x3556 => 0x4e18, + 0x3557 => 0x4e45, 0x3558 => 0x4ec7, 0x3559 => 0x4f11, 0x355a => 0x53ca, + 0x355b => 0x5438, 0x355c => 0x5bae, 0x355d => 0x5f13, 0x355e => 0x6025, + 0x355f => 0x6551, 0x3560 => 0x673d, 0x3561 => 0x6c42, 0x3562 => 0x6c72, + 0x3563 => 0x6ce3, 0x3564 => 0x7078, 0x3565 => 0x7403, 0x3566 => 0x7a76, + 0x3567 => 0x7aae, 0x3568 => 0x7b08, 0x3569 => 0x7d1a, 0x356a => 0x7cfe, + 0x356b => 0x7d66, 0x356c => 0x65e7, 0x356d => 0x725b, 0x356e => 0x53bb, + 0x356f => 0x5c45, 0x3570 => 0x5de8, 0x3571 => 0x62d2, 0x3572 => 0x62e0, + 0x3573 => 0x6319, 0x3574 => 0x6e20, 0x3575 => 0x865a, 0x3576 => 0x8a31, + 0x3577 => 0x8ddd, 0x3578 => 0x92f8, 0x3579 => 0x6f01, 0x357a => 0x79a6, + 0x357b => 0x9b5a, 0x357c => 0x4ea8, 0x357d => 0x4eab, 0x357e => 0x4eac, + 0x3621 => 0x4f9b, 0x3622 => 0x4fa0, 0x3623 => 0x50d1, 0x3624 => 0x5147, + 0x3625 => 0x7af6, 0x3626 => 0x5171, 0x3627 => 0x51f6, 0x3628 => 0x5354, + 0x3629 => 0x5321, 0x362a => 0x537f, 0x362b => 0x53eb, 0x362c => 0x55ac, + 0x362d => 0x5883, 0x362e => 0x5ce1, 0x362f => 0x5f37, 0x3630 => 0x5f4a, + 0x3631 => 0x602f, 0x3632 => 0x6050, 0x3633 => 0x606d, 0x3634 => 0x631f, + 0x3635 => 0x6559, 0x3636 => 0x6a4b, 0x3637 => 0x6cc1, 0x3638 => 0x72c2, + 0x3639 => 0x72ed, 0x363a => 0x77ef, 0x363b => 0x80f8, 0x363c => 0x8105, + 0x363d => 0x8208, 0x363e => 0x854e, 0x363f => 0x90f7, 0x3640 => 0x93e1, + 0x3641 => 0x97ff, 0x3642 => 0x9957, 0x3643 => 0x9a5a, 0x3644 => 0x4ef0, + 0x3645 => 0x51dd, 0x3646 => 0x5c2d, 0x3647 => 0x6681, 0x3648 => 0x696d, + 0x3649 => 0x5c40, 0x364a => 0x66f2, 0x364b => 0x6975, 0x364c => 0x7389, + 0x364d => 0x6850, 0x364e => 0x7c81, 0x364f => 0x50c5, 0x3650 => 0x52e4, + 0x3651 => 0x5747, 0x3652 => 0x5dfe, 0x3653 => 0x9326, 0x3654 => 0x65a4, + 0x3655 => 0x6b23, 0x3656 => 0x6b3d, 0x3657 => 0x7434, 0x3658 => 0x7981, + 0x3659 => 0x79bd, 0x365a => 0x7b4b, 0x365b => 0x7dca, 0x365c => 0x82b9, + 0x365d => 0x83cc, 0x365e => 0x887f, 0x365f => 0x895f, 0x3660 => 0x8b39, + 0x3661 => 0x8fd1, 0x3662 => 0x91d1, 0x3663 => 0x541f, 0x3664 => 0x9280, + 0x3665 => 0x4e5d, 0x3666 => 0x5036, 0x3667 => 0x53e5, 0x3668 => 0x533a, + 0x3669 => 0x72d7, 0x366a => 0x7396, 0x366b => 0x77e9, 0x366c => 0x82e6, + 0x366d => 0x8eaf, 0x366e => 0x99c6, 0x366f => 0x99c8, 0x3670 => 0x99d2, + 0x3671 => 0x5177, 0x3672 => 0x611a, 0x3673 => 0x865e, 0x3674 => 0x55b0, + 0x3675 => 0x7a7a, 0x3676 => 0x5076, 0x3677 => 0x5bd3, 0x3678 => 0x9047, + 0x3679 => 0x9685, 0x367a => 0x4e32, 0x367b => 0x6adb, 0x367c => 0x91e7, + 0x367d => 0x5c51, 0x367e => 0x5c48, 0x3721 => 0x6398, 0x3722 => 0x7a9f, + 0x3723 => 0x6c93, 0x3724 => 0x9774, 0x3725 => 0x8f61, 0x3726 => 0x7aaa, + 0x3727 => 0x718a, 0x3728 => 0x9688, 0x3729 => 0x7c82, 0x372a => 0x6817, + 0x372b => 0x7e70, 0x372c => 0x6851, 0x372d => 0x936c, 0x372e => 0x52f2, + 0x372f => 0x541b, 0x3730 => 0x85ab, 0x3731 => 0x8a13, 0x3732 => 0x7fa4, + 0x3733 => 0x8ecd, 0x3734 => 0x90e1, 0x3735 => 0x5366, 0x3736 => 0x8888, + 0x3737 => 0x7941, 0x3738 => 0x4fc2, 0x3739 => 0x50be, 0x373a => 0x5211, + 0x373b => 0x5144, 0x373c => 0x5553, 0x373d => 0x572d, 0x373e => 0x73ea, + 0x373f => 0x578b, 0x3740 => 0x5951, 0x3741 => 0x5f62, 0x3742 => 0x5f84, + 0x3743 => 0x6075, 0x3744 => 0x6176, 0x3745 => 0x6167, 0x3746 => 0x61a9, + 0x3747 => 0x63b2, 0x3748 => 0x643a, 0x3749 => 0x656c, 0x374a => 0x666f, + 0x374b => 0x6842, 0x374c => 0x6e13, 0x374d => 0x7566, 0x374e => 0x7a3d, + 0x374f => 0x7cfb, 0x3750 => 0x7d4c, 0x3751 => 0x7d99, 0x3752 => 0x7e4b, + 0x3753 => 0x7f6b, 0x3754 => 0x830e, 0x3755 => 0x834a, 0x3756 => 0x86cd, + 0x3757 => 0x8a08, 0x3758 => 0x8a63, 0x3759 => 0x8b66, 0x375a => 0x8efd, + 0x375b => 0x981a, 0x375c => 0x9d8f, 0x375d => 0x82b8, 0x375e => 0x8fce, + 0x375f => 0x9be8, 0x3760 => 0x5287, 0x3761 => 0x621f, 0x3762 => 0x6483, + 0x3763 => 0x6fc0, 0x3764 => 0x9699, 0x3765 => 0x6841, 0x3766 => 0x5091, + 0x3767 => 0x6b20, 0x3768 => 0x6c7a, 0x3769 => 0x6f54, 0x376a => 0x7a74, + 0x376b => 0x7d50, 0x376c => 0x8840, 0x376d => 0x8a23, 0x376e => 0x6708, + 0x376f => 0x4ef6, 0x3770 => 0x5039, 0x3771 => 0x5026, 0x3772 => 0x5065, + 0x3773 => 0x517c, 0x3774 => 0x5238, 0x3775 => 0x5263, 0x3776 => 0x55a7, + 0x3777 => 0x570f, 0x3778 => 0x5805, 0x3779 => 0x5acc, 0x377a => 0x5efa, + 0x377b => 0x61b2, 0x377c => 0x61f8, 0x377d => 0x62f3, 0x377e => 0x6372, + 0x3821 => 0x691c, 0x3822 => 0x6a29, 0x3823 => 0x727d, 0x3824 => 0x72ac, + 0x3825 => 0x732e, 0x3826 => 0x7814, 0x3827 => 0x786f, 0x3828 => 0x7d79, + 0x3829 => 0x770c, 0x382a => 0x80a9, 0x382b => 0x898b, 0x382c => 0x8b19, + 0x382d => 0x8ce2, 0x382e => 0x8ed2, 0x382f => 0x9063, 0x3830 => 0x9375, + 0x3831 => 0x967a, 0x3832 => 0x9855, 0x3833 => 0x9a13, 0x3834 => 0x9e78, + 0x3835 => 0x5143, 0x3836 => 0x539f, 0x3837 => 0x53b3, 0x3838 => 0x5e7b, + 0x3839 => 0x5f26, 0x383a => 0x6e1b, 0x383b => 0x6e90, 0x383c => 0x7384, + 0x383d => 0x73fe, 0x383e => 0x7d43, 0x383f => 0x8237, 0x3840 => 0x8a00, + 0x3841 => 0x8afa, 0x3842 => 0x9650, 0x3843 => 0x4e4e, 0x3844 => 0x500b, + 0x3845 => 0x53e4, 0x3846 => 0x547c, 0x3847 => 0x56fa, 0x3848 => 0x59d1, + 0x3849 => 0x5b64, 0x384a => 0x5df1, 0x384b => 0x5eab, 0x384c => 0x5f27, + 0x384d => 0x6238, 0x384e => 0x6545, 0x384f => 0x67af, 0x3850 => 0x6e56, + 0x3851 => 0x72d0, 0x3852 => 0x7cca, 0x3853 => 0x88b4, 0x3854 => 0x80a1, + 0x3855 => 0x80e1, 0x3856 => 0x83f0, 0x3857 => 0x864e, 0x3858 => 0x8a87, + 0x3859 => 0x8de8, 0x385a => 0x9237, 0x385b => 0x96c7, 0x385c => 0x9867, + 0x385d => 0x9f13, 0x385e => 0x4e94, 0x385f => 0x4e92, 0x3860 => 0x4f0d, + 0x3861 => 0x5348, 0x3862 => 0x5449, 0x3863 => 0x543e, 0x3864 => 0x5a2f, + 0x3865 => 0x5f8c, 0x3866 => 0x5fa1, 0x3867 => 0x609f, 0x3868 => 0x68a7, + 0x3869 => 0x6a8e, 0x386a => 0x745a, 0x386b => 0x7881, 0x386c => 0x8a9e, + 0x386d => 0x8aa4, 0x386e => 0x8b77, 0x386f => 0x9190, 0x3870 => 0x4e5e, + 0x3871 => 0x9bc9, 0x3872 => 0x4ea4, 0x3873 => 0x4f7c, 0x3874 => 0x4faf, + 0x3875 => 0x5019, 0x3876 => 0x5016, 0x3877 => 0x5149, 0x3878 => 0x516c, + 0x3879 => 0x529f, 0x387a => 0x52b9, 0x387b => 0x52fe, 0x387c => 0x539a, + 0x387d => 0x53e3, 0x387e => 0x5411, 0x3921 => 0x540e, 0x3922 => 0x5589, + 0x3923 => 0x5751, 0x3924 => 0x57a2, 0x3925 => 0x597d, 0x3926 => 0x5b54, + 0x3927 => 0x5b5d, 0x3928 => 0x5b8f, 0x3929 => 0x5de5, 0x392a => 0x5de7, + 0x392b => 0x5df7, 0x392c => 0x5e78, 0x392d => 0x5e83, 0x392e => 0x5e9a, + 0x392f => 0x5eb7, 0x3930 => 0x5f18, 0x3931 => 0x6052, 0x3932 => 0x614c, + 0x3933 => 0x6297, 0x3934 => 0x62d8, 0x3935 => 0x63a7, 0x3936 => 0x653b, + 0x3937 => 0x6602, 0x3938 => 0x6643, 0x3939 => 0x66f4, 0x393a => 0x676d, + 0x393b => 0x6821, 0x393c => 0x6897, 0x393d => 0x69cb, 0x393e => 0x6c5f, + 0x393f => 0x6d2a, 0x3940 => 0x6d69, 0x3941 => 0x6e2f, 0x3942 => 0x6e9d, + 0x3943 => 0x7532, 0x3944 => 0x7687, 0x3945 => 0x786c, 0x3946 => 0x7a3f, + 0x3947 => 0x7ce0, 0x3948 => 0x7d05, 0x3949 => 0x7d18, 0x394a => 0x7d5e, + 0x394b => 0x7db1, 0x394c => 0x8015, 0x394d => 0x8003, 0x394e => 0x80af, + 0x394f => 0x80b1, 0x3950 => 0x8154, 0x3951 => 0x818f, 0x3952 => 0x822a, + 0x3953 => 0x8352, 0x3954 => 0x884c, 0x3955 => 0x8861, 0x3956 => 0x8b1b, + 0x3957 => 0x8ca2, 0x3958 => 0x8cfc, 0x3959 => 0x90ca, 0x395a => 0x9175, + 0x395b => 0x9271, 0x395c => 0x783f, 0x395d => 0x92fc, 0x395e => 0x95a4, + 0x395f => 0x964d, 0x3960 => 0x9805, 0x3961 => 0x9999, 0x3962 => 0x9ad8, + 0x3963 => 0x9d3b, 0x3964 => 0x525b, 0x3965 => 0x52ab, 0x3966 => 0x53f7, + 0x3967 => 0x5408, 0x3968 => 0x58d5, 0x3969 => 0x62f7, 0x396a => 0x6fe0, + 0x396b => 0x8c6a, 0x396c => 0x8f5f, 0x396d => 0x9eb9, 0x396e => 0x514b, + 0x396f => 0x523b, 0x3970 => 0x544a, 0x3971 => 0x56fd, 0x3972 => 0x7a40, + 0x3973 => 0x9177, 0x3974 => 0x9d60, 0x3975 => 0x9ed2, 0x3976 => 0x7344, + 0x3977 => 0x6f09, 0x3978 => 0x8170, 0x3979 => 0x7511, 0x397a => 0x5ffd, + 0x397b => 0x60da, 0x397c => 0x9aa8, 0x397d => 0x72db, 0x397e => 0x8fbc, + 0x3a21 => 0x6b64, 0x3a22 => 0x9803, 0x3a23 => 0x4eca, 0x3a24 => 0x56f0, + 0x3a25 => 0x5764, 0x3a26 => 0x58be, 0x3a27 => 0x5a5a, 0x3a28 => 0x6068, + 0x3a29 => 0x61c7, 0x3a2a => 0x660f, 0x3a2b => 0x6606, 0x3a2c => 0x6839, + 0x3a2d => 0x68b1, 0x3a2e => 0x6df7, 0x3a2f => 0x75d5, 0x3a30 => 0x7d3a, + 0x3a31 => 0x826e, 0x3a32 => 0x9b42, 0x3a33 => 0x4e9b, 0x3a34 => 0x4f50, + 0x3a35 => 0x53c9, 0x3a36 => 0x5506, 0x3a37 => 0x5d6f, 0x3a38 => 0x5de6, + 0x3a39 => 0x5dee, 0x3a3a => 0x67fb, 0x3a3b => 0x6c99, 0x3a3c => 0x7473, + 0x3a3d => 0x7802, 0x3a3e => 0x8a50, 0x3a3f => 0x9396, 0x3a40 => 0x88df, + 0x3a41 => 0x5750, 0x3a42 => 0x5ea7, 0x3a43 => 0x632b, 0x3a44 => 0x50b5, + 0x3a45 => 0x50ac, 0x3a46 => 0x518d, 0x3a47 => 0x6700, 0x3a48 => 0x54c9, + 0x3a49 => 0x585e, 0x3a4a => 0x59bb, 0x3a4b => 0x5bb0, 0x3a4c => 0x5f69, + 0x3a4d => 0x624d, 0x3a4e => 0x63a1, 0x3a4f => 0x683d, 0x3a50 => 0x6b73, + 0x3a51 => 0x6e08, 0x3a52 => 0x707d, 0x3a53 => 0x91c7, 0x3a54 => 0x7280, + 0x3a55 => 0x7815, 0x3a56 => 0x7826, 0x3a57 => 0x796d, 0x3a58 => 0x658e, + 0x3a59 => 0x7d30, 0x3a5a => 0x83dc, 0x3a5b => 0x88c1, 0x3a5c => 0x8f09, + 0x3a5d => 0x969b, 0x3a5e => 0x5264, 0x3a5f => 0x5728, 0x3a60 => 0x6750, + 0x3a61 => 0x7f6a, 0x3a62 => 0x8ca1, 0x3a63 => 0x51b4, 0x3a64 => 0x5742, + 0x3a65 => 0x962a, 0x3a66 => 0x583a, 0x3a67 => 0x698a, 0x3a68 => 0x80b4, + 0x3a69 => 0x54b2, 0x3a6a => 0x5d0e, 0x3a6b => 0x57fc, 0x3a6c => 0x7895, + 0x3a6d => 0x9dfa, 0x3a6e => 0x4f5c, 0x3a6f => 0x524a, 0x3a70 => 0x548b, + 0x3a71 => 0x643e, 0x3a72 => 0x6628, 0x3a73 => 0x6714, 0x3a74 => 0x67f5, + 0x3a75 => 0x7a84, 0x3a76 => 0x7b56, 0x3a77 => 0x7d22, 0x3a78 => 0x932f, + 0x3a79 => 0x685c, 0x3a7a => 0x9bad, 0x3a7b => 0x7b39, 0x3a7c => 0x5319, + 0x3a7d => 0x518a, 0x3a7e => 0x5237, 0x3b21 => 0x5bdf, 0x3b22 => 0x62f6, + 0x3b23 => 0x64ae, 0x3b24 => 0x64e6, 0x3b25 => 0x672d, 0x3b26 => 0x6bba, + 0x3b27 => 0x85a9, 0x3b28 => 0x96d1, 0x3b29 => 0x7690, 0x3b2a => 0x9bd6, + 0x3b2b => 0x634c, 0x3b2c => 0x9306, 0x3b2d => 0x9bab, 0x3b2e => 0x76bf, + 0x3b2f => 0x6652, 0x3b30 => 0x4e09, 0x3b31 => 0x5098, 0x3b32 => 0x53c2, + 0x3b33 => 0x5c71, 0x3b34 => 0x60e8, 0x3b35 => 0x6492, 0x3b36 => 0x6563, + 0x3b37 => 0x685f, 0x3b38 => 0x71e6, 0x3b39 => 0x73ca, 0x3b3a => 0x7523, + 0x3b3b => 0x7b97, 0x3b3c => 0x7e82, 0x3b3d => 0x8695, 0x3b3e => 0x8b83, + 0x3b3f => 0x8cdb, 0x3b40 => 0x9178, 0x3b41 => 0x9910, 0x3b42 => 0x65ac, + 0x3b43 => 0x66ab, 0x3b44 => 0x6b8b, 0x3b45 => 0x4ed5, 0x3b46 => 0x4ed4, + 0x3b47 => 0x4f3a, 0x3b48 => 0x4f7f, 0x3b49 => 0x523a, 0x3b4a => 0x53f8, + 0x3b4b => 0x53f2, 0x3b4c => 0x55e3, 0x3b4d => 0x56db, 0x3b4e => 0x58eb, + 0x3b4f => 0x59cb, 0x3b50 => 0x59c9, 0x3b51 => 0x59ff, 0x3b52 => 0x5b50, + 0x3b53 => 0x5c4d, 0x3b54 => 0x5e02, 0x3b55 => 0x5e2b, 0x3b56 => 0x5fd7, + 0x3b57 => 0x601d, 0x3b58 => 0x6307, 0x3b59 => 0x652f, 0x3b5a => 0x5b5c, + 0x3b5b => 0x65af, 0x3b5c => 0x65bd, 0x3b5d => 0x65e8, 0x3b5e => 0x679d, + 0x3b5f => 0x6b62, 0x3b60 => 0x6b7b, 0x3b61 => 0x6c0f, 0x3b62 => 0x7345, + 0x3b63 => 0x7949, 0x3b64 => 0x79c1, 0x3b65 => 0x7cf8, 0x3b66 => 0x7d19, + 0x3b67 => 0x7d2b, 0x3b68 => 0x80a2, 0x3b69 => 0x8102, 0x3b6a => 0x81f3, + 0x3b6b => 0x8996, 0x3b6c => 0x8a5e, 0x3b6d => 0x8a69, 0x3b6e => 0x8a66, + 0x3b6f => 0x8a8c, 0x3b70 => 0x8aee, 0x3b71 => 0x8cc7, 0x3b72 => 0x8cdc, + 0x3b73 => 0x96cc, 0x3b74 => 0x98fc, 0x3b75 => 0x6b6f, 0x3b76 => 0x4e8b, + 0x3b77 => 0x4f3c, 0x3b78 => 0x4f8d, 0x3b79 => 0x5150, 0x3b7a => 0x5b57, + 0x3b7b => 0x5bfa, 0x3b7c => 0x6148, 0x3b7d => 0x6301, 0x3b7e => 0x6642, + 0x3c21 => 0x6b21, 0x3c22 => 0x6ecb, 0x3c23 => 0x6cbb, 0x3c24 => 0x723e, + 0x3c25 => 0x74bd, 0x3c26 => 0x75d4, 0x3c27 => 0x78c1, 0x3c28 => 0x793a, + 0x3c29 => 0x800c, 0x3c2a => 0x8033, 0x3c2b => 0x81ea, 0x3c2c => 0x8494, + 0x3c2d => 0x8f9e, 0x3c2e => 0x6c50, 0x3c2f => 0x9e7f, 0x3c30 => 0x5f0f, + 0x3c31 => 0x8b58, 0x3c32 => 0x9d2b, 0x3c33 => 0x7afa, 0x3c34 => 0x8ef8, + 0x3c35 => 0x5b8d, 0x3c36 => 0x96eb, 0x3c37 => 0x4e03, 0x3c38 => 0x53f1, + 0x3c39 => 0x57f7, 0x3c3a => 0x5931, 0x3c3b => 0x5ac9, 0x3c3c => 0x5ba4, + 0x3c3d => 0x6089, 0x3c3e => 0x6e7f, 0x3c3f => 0x6f06, 0x3c40 => 0x75be, + 0x3c41 => 0x8cea, 0x3c42 => 0x5b9f, 0x3c43 => 0x8500, 0x3c44 => 0x7be0, + 0x3c45 => 0x5072, 0x3c46 => 0x67f4, 0x3c47 => 0x829d, 0x3c48 => 0x5c61, + 0x3c49 => 0x854a, 0x3c4a => 0x7e1e, 0x3c4b => 0x820e, 0x3c4c => 0x5199, + 0x3c4d => 0x5c04, 0x3c4e => 0x6368, 0x3c4f => 0x8d66, 0x3c50 => 0x659c, + 0x3c51 => 0x716e, 0x3c52 => 0x793e, 0x3c53 => 0x7d17, 0x3c54 => 0x8005, + 0x3c55 => 0x8b1d, 0x3c56 => 0x8eca, 0x3c57 => 0x906e, 0x3c58 => 0x86c7, + 0x3c59 => 0x90aa, 0x3c5a => 0x501f, 0x3c5b => 0x52fa, 0x3c5c => 0x5c3a, + 0x3c5d => 0x6753, 0x3c5e => 0x707c, 0x3c5f => 0x7235, 0x3c60 => 0x914c, + 0x3c61 => 0x91c8, 0x3c62 => 0x932b, 0x3c63 => 0x82e5, 0x3c64 => 0x5bc2, + 0x3c65 => 0x5f31, 0x3c66 => 0x60f9, 0x3c67 => 0x4e3b, 0x3c68 => 0x53d6, + 0x3c69 => 0x5b88, 0x3c6a => 0x624b, 0x3c6b => 0x6731, 0x3c6c => 0x6b8a, + 0x3c6d => 0x72e9, 0x3c6e => 0x73e0, 0x3c6f => 0x7a2e, 0x3c70 => 0x816b, + 0x3c71 => 0x8da3, 0x3c72 => 0x9152, 0x3c73 => 0x9996, 0x3c74 => 0x5112, + 0x3c75 => 0x53d7, 0x3c76 => 0x546a, 0x3c77 => 0x5bff, 0x3c78 => 0x6388, + 0x3c79 => 0x6a39, 0x3c7a => 0x7dac, 0x3c7b => 0x9700, 0x3c7c => 0x56da, + 0x3c7d => 0x53ce, 0x3c7e => 0x5468, 0x3d21 => 0x5b97, 0x3d22 => 0x5c31, + 0x3d23 => 0x5dde, 0x3d24 => 0x4fee, 0x3d25 => 0x6101, 0x3d26 => 0x62fe, + 0x3d27 => 0x6d32, 0x3d28 => 0x79c0, 0x3d29 => 0x79cb, 0x3d2a => 0x7d42, + 0x3d2b => 0x7e4d, 0x3d2c => 0x7fd2, 0x3d2d => 0x81ed, 0x3d2e => 0x821f, + 0x3d2f => 0x8490, 0x3d30 => 0x8846, 0x3d31 => 0x8972, 0x3d32 => 0x8b90, + 0x3d33 => 0x8e74, 0x3d34 => 0x8f2f, 0x3d35 => 0x9031, 0x3d36 => 0x914b, + 0x3d37 => 0x916c, 0x3d38 => 0x96c6, 0x3d39 => 0x919c, 0x3d3a => 0x4ec0, + 0x3d3b => 0x4f4f, 0x3d3c => 0x5145, 0x3d3d => 0x5341, 0x3d3e => 0x5f93, + 0x3d3f => 0x620e, 0x3d40 => 0x67d4, 0x3d41 => 0x6c41, 0x3d42 => 0x6e0b, + 0x3d43 => 0x7363, 0x3d44 => 0x7e26, 0x3d45 => 0x91cd, 0x3d46 => 0x9283, + 0x3d47 => 0x53d4, 0x3d48 => 0x5919, 0x3d49 => 0x5bbf, 0x3d4a => 0x6dd1, + 0x3d4b => 0x795d, 0x3d4c => 0x7e2e, 0x3d4d => 0x7c9b, 0x3d4e => 0x587e, + 0x3d4f => 0x719f, 0x3d50 => 0x51fa, 0x3d51 => 0x8853, 0x3d52 => 0x8ff0, + 0x3d53 => 0x4fca, 0x3d54 => 0x5cfb, 0x3d55 => 0x6625, 0x3d56 => 0x77ac, + 0x3d57 => 0x7ae3, 0x3d58 => 0x821c, 0x3d59 => 0x99ff, 0x3d5a => 0x51c6, + 0x3d5b => 0x5faa, 0x3d5c => 0x65ec, 0x3d5d => 0x696f, 0x3d5e => 0x6b89, + 0x3d5f => 0x6df3, 0x3d60 => 0x6e96, 0x3d61 => 0x6f64, 0x3d62 => 0x76fe, + 0x3d63 => 0x7d14, 0x3d64 => 0x5de1, 0x3d65 => 0x9075, 0x3d66 => 0x9187, + 0x3d67 => 0x9806, 0x3d68 => 0x51e6, 0x3d69 => 0x521d, 0x3d6a => 0x6240, + 0x3d6b => 0x6691, 0x3d6c => 0x66d9, 0x3d6d => 0x6e1a, 0x3d6e => 0x5eb6, + 0x3d6f => 0x7dd2, 0x3d70 => 0x7f72, 0x3d71 => 0x66f8, 0x3d72 => 0x85af, + 0x3d73 => 0x85f7, 0x3d74 => 0x8af8, 0x3d75 => 0x52a9, 0x3d76 => 0x53d9, + 0x3d77 => 0x5973, 0x3d78 => 0x5e8f, 0x3d79 => 0x5f90, 0x3d7a => 0x6055, + 0x3d7b => 0x92e4, 0x3d7c => 0x9664, 0x3d7d => 0x50b7, 0x3d7e => 0x511f, + 0x3e21 => 0x52dd, 0x3e22 => 0x5320, 0x3e23 => 0x5347, 0x3e24 => 0x53ec, + 0x3e25 => 0x54e8, 0x3e26 => 0x5546, 0x3e27 => 0x5531, 0x3e28 => 0x5617, + 0x3e29 => 0x5968, 0x3e2a => 0x59be, 0x3e2b => 0x5a3c, 0x3e2c => 0x5bb5, + 0x3e2d => 0x5c06, 0x3e2e => 0x5c0f, 0x3e2f => 0x5c11, 0x3e30 => 0x5c1a, + 0x3e31 => 0x5e84, 0x3e32 => 0x5e8a, 0x3e33 => 0x5ee0, 0x3e34 => 0x5f70, + 0x3e35 => 0x627f, 0x3e36 => 0x6284, 0x3e37 => 0x62db, 0x3e38 => 0x638c, + 0x3e39 => 0x6377, 0x3e3a => 0x6607, 0x3e3b => 0x660c, 0x3e3c => 0x662d, + 0x3e3d => 0x6676, 0x3e3e => 0x677e, 0x3e3f => 0x68a2, 0x3e40 => 0x6a1f, + 0x3e41 => 0x6a35, 0x3e42 => 0x6cbc, 0x3e43 => 0x6d88, 0x3e44 => 0x6e09, + 0x3e45 => 0x6e58, 0x3e46 => 0x713c, 0x3e47 => 0x7126, 0x3e48 => 0x7167, + 0x3e49 => 0x75c7, 0x3e4a => 0x7701, 0x3e4b => 0x785d, 0x3e4c => 0x7901, + 0x3e4d => 0x7965, 0x3e4e => 0x79f0, 0x3e4f => 0x7ae0, 0x3e50 => 0x7b11, + 0x3e51 => 0x7ca7, 0x3e52 => 0x7d39, 0x3e53 => 0x8096, 0x3e54 => 0x83d6, + 0x3e55 => 0x848b, 0x3e56 => 0x8549, 0x3e57 => 0x885d, 0x3e58 => 0x88f3, + 0x3e59 => 0x8a1f, 0x3e5a => 0x8a3c, 0x3e5b => 0x8a54, 0x3e5c => 0x8a73, + 0x3e5d => 0x8c61, 0x3e5e => 0x8cde, 0x3e5f => 0x91a4, 0x3e60 => 0x9266, + 0x3e61 => 0x937e, 0x3e62 => 0x9418, 0x3e63 => 0x969c, 0x3e64 => 0x9798, + 0x3e65 => 0x4e0a, 0x3e66 => 0x4e08, 0x3e67 => 0x4e1e, 0x3e68 => 0x4e57, + 0x3e69 => 0x5197, 0x3e6a => 0x5270, 0x3e6b => 0x57ce, 0x3e6c => 0x5834, + 0x3e6d => 0x58cc, 0x3e6e => 0x5b22, 0x3e6f => 0x5e38, 0x3e70 => 0x60c5, + 0x3e71 => 0x64fe, 0x3e72 => 0x6761, 0x3e73 => 0x6756, 0x3e74 => 0x6d44, + 0x3e75 => 0x72b6, 0x3e76 => 0x7573, 0x3e77 => 0x7a63, 0x3e78 => 0x84b8, + 0x3e79 => 0x8b72, 0x3e7a => 0x91b8, 0x3e7b => 0x9320, 0x3e7c => 0x5631, + 0x3e7d => 0x57f4, 0x3e7e => 0x98fe, 0x3f21 => 0x62ed, 0x3f22 => 0x690d, + 0x3f23 => 0x6b96, 0x3f24 => 0x71ed, 0x3f25 => 0x7e54, 0x3f26 => 0x8077, + 0x3f27 => 0x8272, 0x3f28 => 0x89e6, 0x3f29 => 0x98df, 0x3f2a => 0x8755, + 0x3f2b => 0x8fb1, 0x3f2c => 0x5c3b, 0x3f2d => 0x4f38, 0x3f2e => 0x4fe1, + 0x3f2f => 0x4fb5, 0x3f30 => 0x5507, 0x3f31 => 0x5a20, 0x3f32 => 0x5bdd, + 0x3f33 => 0x5be9, 0x3f34 => 0x5fc3, 0x3f35 => 0x614e, 0x3f36 => 0x632f, + 0x3f37 => 0x65b0, 0x3f38 => 0x664b, 0x3f39 => 0x68ee, 0x3f3a => 0x699b, + 0x3f3b => 0x6d78, 0x3f3c => 0x6df1, 0x3f3d => 0x7533, 0x3f3e => 0x75b9, + 0x3f3f => 0x771f, 0x3f40 => 0x795e, 0x3f41 => 0x79e6, 0x3f42 => 0x7d33, + 0x3f43 => 0x81e3, 0x3f44 => 0x82af, 0x3f45 => 0x85aa, 0x3f46 => 0x89aa, + 0x3f47 => 0x8a3a, 0x3f48 => 0x8eab, 0x3f49 => 0x8f9b, 0x3f4a => 0x9032, + 0x3f4b => 0x91dd, 0x3f4c => 0x9707, 0x3f4d => 0x4eba, 0x3f4e => 0x4ec1, + 0x3f4f => 0x5203, 0x3f50 => 0x5875, 0x3f51 => 0x58ec, 0x3f52 => 0x5c0b, + 0x3f53 => 0x751a, 0x3f54 => 0x5c3d, 0x3f55 => 0x814e, 0x3f56 => 0x8a0a, + 0x3f57 => 0x8fc5, 0x3f58 => 0x9663, 0x3f59 => 0x976d, 0x3f5a => 0x7b25, + 0x3f5b => 0x8acf, 0x3f5c => 0x9808, 0x3f5d => 0x9162, 0x3f5e => 0x56f3, + 0x3f5f => 0x53a8, 0x3f60 => 0x9017, 0x3f61 => 0x5439, 0x3f62 => 0x5782, + 0x3f63 => 0x5e25, 0x3f64 => 0x63a8, 0x3f65 => 0x6c34, 0x3f66 => 0x708a, + 0x3f67 => 0x7761, 0x3f68 => 0x7c8b, 0x3f69 => 0x7fe0, 0x3f6a => 0x8870, + 0x3f6b => 0x9042, 0x3f6c => 0x9154, 0x3f6d => 0x9310, 0x3f6e => 0x9318, + 0x3f6f => 0x968f, 0x3f70 => 0x745e, 0x3f71 => 0x9ac4, 0x3f72 => 0x5d07, + 0x3f73 => 0x5d69, 0x3f74 => 0x6570, 0x3f75 => 0x67a2, 0x3f76 => 0x8da8, + 0x3f77 => 0x96db, 0x3f78 => 0x636e, 0x3f79 => 0x6749, 0x3f7a => 0x6919, + 0x3f7b => 0x83c5, 0x3f7c => 0x9817, 0x3f7d => 0x96c0, 0x3f7e => 0x88fe, + 0x4021 => 0x6f84, 0x4022 => 0x647a, 0x4023 => 0x5bf8, 0x4024 => 0x4e16, + 0x4025 => 0x702c, 0x4026 => 0x755d, 0x4027 => 0x662f, 0x4028 => 0x51c4, + 0x4029 => 0x5236, 0x402a => 0x52e2, 0x402b => 0x59d3, 0x402c => 0x5f81, + 0x402d => 0x6027, 0x402e => 0x6210, 0x402f => 0x653f, 0x4030 => 0x6574, + 0x4031 => 0x661f, 0x4032 => 0x6674, 0x4033 => 0x68f2, 0x4034 => 0x6816, + 0x4035 => 0x6b63, 0x4036 => 0x6e05, 0x4037 => 0x7272, 0x4038 => 0x751f, + 0x4039 => 0x76db, 0x403a => 0x7cbe, 0x403b => 0x8056, 0x403c => 0x58f0, + 0x403d => 0x88fd, 0x403e => 0x897f, 0x403f => 0x8aa0, 0x4040 => 0x8a93, + 0x4041 => 0x8acb, 0x4042 => 0x901d, 0x4043 => 0x9192, 0x4044 => 0x9752, + 0x4045 => 0x9759, 0x4046 => 0x6589, 0x4047 => 0x7a0e, 0x4048 => 0x8106, + 0x4049 => 0x96bb, 0x404a => 0x5e2d, 0x404b => 0x60dc, 0x404c => 0x621a, + 0x404d => 0x65a5, 0x404e => 0x6614, 0x404f => 0x6790, 0x4050 => 0x77f3, + 0x4051 => 0x7a4d, 0x4052 => 0x7c4d, 0x4053 => 0x7e3e, 0x4054 => 0x810a, + 0x4055 => 0x8cac, 0x4056 => 0x8d64, 0x4057 => 0x8de1, 0x4058 => 0x8e5f, + 0x4059 => 0x78a9, 0x405a => 0x5207, 0x405b => 0x62d9, 0x405c => 0x63a5, + 0x405d => 0x6442, 0x405e => 0x6298, 0x405f => 0x8a2d, 0x4060 => 0x7a83, + 0x4061 => 0x7bc0, 0x4062 => 0x8aac, 0x4063 => 0x96ea, 0x4064 => 0x7d76, + 0x4065 => 0x820c, 0x4066 => 0x8749, 0x4067 => 0x4ed9, 0x4068 => 0x5148, + 0x4069 => 0x5343, 0x406a => 0x5360, 0x406b => 0x5ba3, 0x406c => 0x5c02, + 0x406d => 0x5c16, 0x406e => 0x5ddd, 0x406f => 0x6226, 0x4070 => 0x6247, + 0x4071 => 0x64b0, 0x4072 => 0x6813, 0x4073 => 0x6834, 0x4074 => 0x6cc9, + 0x4075 => 0x6d45, 0x4076 => 0x6d17, 0x4077 => 0x67d3, 0x4078 => 0x6f5c, + 0x4079 => 0x714e, 0x407a => 0x717d, 0x407b => 0x65cb, 0x407c => 0x7a7f, + 0x407d => 0x7bad, 0x407e => 0x7dda, 0x4121 => 0x7e4a, 0x4122 => 0x7fa8, + 0x4123 => 0x817a, 0x4124 => 0x821b, 0x4125 => 0x8239, 0x4126 => 0x85a6, + 0x4127 => 0x8a6e, 0x4128 => 0x8cce, 0x4129 => 0x8df5, 0x412a => 0x9078, + 0x412b => 0x9077, 0x412c => 0x92ad, 0x412d => 0x9291, 0x412e => 0x9583, + 0x412f => 0x9bae, 0x4130 => 0x524d, 0x4131 => 0x5584, 0x4132 => 0x6f38, + 0x4133 => 0x7136, 0x4134 => 0x5168, 0x4135 => 0x7985, 0x4136 => 0x7e55, + 0x4137 => 0x81b3, 0x4138 => 0x7cce, 0x4139 => 0x564c, 0x413a => 0x5851, + 0x413b => 0x5ca8, 0x413c => 0x63aa, 0x413d => 0x66fe, 0x413e => 0x66fd, + 0x413f => 0x695a, 0x4140 => 0x72d9, 0x4141 => 0x758f, 0x4142 => 0x758e, + 0x4143 => 0x790e, 0x4144 => 0x7956, 0x4145 => 0x79df, 0x4146 => 0x7c97, + 0x4147 => 0x7d20, 0x4148 => 0x7d44, 0x4149 => 0x8607, 0x414a => 0x8a34, + 0x414b => 0x963b, 0x414c => 0x9061, 0x414d => 0x9f20, 0x414e => 0x50e7, + 0x414f => 0x5275, 0x4150 => 0x53cc, 0x4151 => 0x53e2, 0x4152 => 0x5009, + 0x4153 => 0x55aa, 0x4154 => 0x58ee, 0x4155 => 0x594f, 0x4156 => 0x723d, + 0x4157 => 0x5b8b, 0x4158 => 0x5c64, 0x4159 => 0x531d, 0x415a => 0x60e3, + 0x415b => 0x60f3, 0x415c => 0x635c, 0x415d => 0x6383, 0x415e => 0x633f, + 0x415f => 0x63bb, 0x4160 => 0x64cd, 0x4161 => 0x65e9, 0x4162 => 0x66f9, + 0x4163 => 0x5de3, 0x4164 => 0x69cd, 0x4165 => 0x69fd, 0x4166 => 0x6f15, + 0x4167 => 0x71e5, 0x4168 => 0x4e89, 0x4169 => 0x75e9, 0x416a => 0x76f8, + 0x416b => 0x7a93, 0x416c => 0x7cdf, 0x416d => 0x7dcf, 0x416e => 0x7d9c, + 0x416f => 0x8061, 0x4170 => 0x8349, 0x4171 => 0x8358, 0x4172 => 0x846c, + 0x4173 => 0x84bc, 0x4174 => 0x85fb, 0x4175 => 0x88c5, 0x4176 => 0x8d70, + 0x4177 => 0x9001, 0x4178 => 0x906d, 0x4179 => 0x9397, 0x417a => 0x971c, + 0x417b => 0x9a12, 0x417c => 0x50cf, 0x417d => 0x5897, 0x417e => 0x618e, + 0x4221 => 0x81d3, 0x4222 => 0x8535, 0x4223 => 0x8d08, 0x4224 => 0x9020, + 0x4225 => 0x4fc3, 0x4226 => 0x5074, 0x4227 => 0x5247, 0x4228 => 0x5373, + 0x4229 => 0x606f, 0x422a => 0x6349, 0x422b => 0x675f, 0x422c => 0x6e2c, + 0x422d => 0x8db3, 0x422e => 0x901f, 0x422f => 0x4fd7, 0x4230 => 0x5c5e, + 0x4231 => 0x8cca, 0x4232 => 0x65cf, 0x4233 => 0x7d9a, 0x4234 => 0x5352, + 0x4235 => 0x8896, 0x4236 => 0x5176, 0x4237 => 0x63c3, 0x4238 => 0x5b58, + 0x4239 => 0x5b6b, 0x423a => 0x5c0a, 0x423b => 0x640d, 0x423c => 0x6751, + 0x423d => 0x905c, 0x423e => 0x4ed6, 0x423f => 0x591a, 0x4240 => 0x592a, + 0x4241 => 0x6c70, 0x4242 => 0x8a51, 0x4243 => 0x553e, 0x4244 => 0x5815, + 0x4245 => 0x59a5, 0x4246 => 0x60f0, 0x4247 => 0x6253, 0x4248 => 0x67c1, + 0x4249 => 0x8235, 0x424a => 0x6955, 0x424b => 0x9640, 0x424c => 0x99c4, + 0x424d => 0x9a28, 0x424e => 0x4f53, 0x424f => 0x5806, 0x4250 => 0x5bfe, + 0x4251 => 0x8010, 0x4252 => 0x5cb1, 0x4253 => 0x5e2f, 0x4254 => 0x5f85, + 0x4255 => 0x6020, 0x4256 => 0x614b, 0x4257 => 0x6234, 0x4258 => 0x66ff, + 0x4259 => 0x6cf0, 0x425a => 0x6ede, 0x425b => 0x80ce, 0x425c => 0x817f, + 0x425d => 0x82d4, 0x425e => 0x888b, 0x425f => 0x8cb8, 0x4260 => 0x9000, + 0x4261 => 0x902e, 0x4262 => 0x968a, 0x4263 => 0x9edb, 0x4264 => 0x9bdb, + 0x4265 => 0x4ee3, 0x4266 => 0x53f0, 0x4267 => 0x5927, 0x4268 => 0x7b2c, + 0x4269 => 0x918d, 0x426a => 0x984c, 0x426b => 0x9df9, 0x426c => 0x6edd, + 0x426d => 0x7027, 0x426e => 0x5353, 0x426f => 0x5544, 0x4270 => 0x5b85, + 0x4271 => 0x6258, 0x4272 => 0x629e, 0x4273 => 0x62d3, 0x4274 => 0x6ca2, + 0x4275 => 0x6fef, 0x4276 => 0x7422, 0x4277 => 0x8a17, 0x4278 => 0x9438, + 0x4279 => 0x6fc1, 0x427a => 0x8afe, 0x427b => 0x8338, 0x427c => 0x51e7, + 0x427d => 0x86f8, 0x427e => 0x53ea, 0x4321 => 0x53e9, 0x4322 => 0x4f46, + 0x4323 => 0x9054, 0x4324 => 0x8fb0, 0x4325 => 0x596a, 0x4326 => 0x8131, + 0x4327 => 0x5dfd, 0x4328 => 0x7aea, 0x4329 => 0x8fbf, 0x432a => 0x68da, + 0x432b => 0x8c37, 0x432c => 0x72f8, 0x432d => 0x9c48, 0x432e => 0x6a3d, + 0x432f => 0x8ab0, 0x4330 => 0x4e39, 0x4331 => 0x5358, 0x4332 => 0x5606, + 0x4333 => 0x5766, 0x4334 => 0x62c5, 0x4335 => 0x63a2, 0x4336 => 0x65e6, + 0x4337 => 0x6b4e, 0x4338 => 0x6de1, 0x4339 => 0x6e5b, 0x433a => 0x70ad, + 0x433b => 0x77ed, 0x433c => 0x7aef, 0x433d => 0x7baa, 0x433e => 0x7dbb, + 0x433f => 0x803d, 0x4340 => 0x80c6, 0x4341 => 0x86cb, 0x4342 => 0x8a95, + 0x4343 => 0x935b, 0x4344 => 0x56e3, 0x4345 => 0x58c7, 0x4346 => 0x5f3e, + 0x4347 => 0x65ad, 0x4348 => 0x6696, 0x4349 => 0x6a80, 0x434a => 0x6bb5, + 0x434b => 0x7537, 0x434c => 0x8ac7, 0x434d => 0x5024, 0x434e => 0x77e5, + 0x434f => 0x5730, 0x4350 => 0x5f1b, 0x4351 => 0x6065, 0x4352 => 0x667a, + 0x4353 => 0x6c60, 0x4354 => 0x75f4, 0x4355 => 0x7a1a, 0x4356 => 0x7f6e, + 0x4357 => 0x81f4, 0x4358 => 0x8718, 0x4359 => 0x9045, 0x435a => 0x99b3, + 0x435b => 0x7bc9, 0x435c => 0x755c, 0x435d => 0x7af9, 0x435e => 0x7b51, + 0x435f => 0x84c4, 0x4360 => 0x9010, 0x4361 => 0x79e9, 0x4362 => 0x7a92, + 0x4363 => 0x8336, 0x4364 => 0x5ae1, 0x4365 => 0x7740, 0x4366 => 0x4e2d, + 0x4367 => 0x4ef2, 0x4368 => 0x5b99, 0x4369 => 0x5fe0, 0x436a => 0x62bd, + 0x436b => 0x663c, 0x436c => 0x67f1, 0x436d => 0x6ce8, 0x436e => 0x866b, + 0x436f => 0x8877, 0x4370 => 0x8a3b, 0x4371 => 0x914e, 0x4372 => 0x92f3, + 0x4373 => 0x99d0, 0x4374 => 0x6a17, 0x4375 => 0x7026, 0x4376 => 0x732a, + 0x4377 => 0x82e7, 0x4378 => 0x8457, 0x4379 => 0x8caf, 0x437a => 0x4e01, + 0x437b => 0x5146, 0x437c => 0x51cb, 0x437d => 0x558b, 0x437e => 0x5bf5, + 0x4421 => 0x5e16, 0x4422 => 0x5e33, 0x4423 => 0x5e81, 0x4424 => 0x5f14, + 0x4425 => 0x5f35, 0x4426 => 0x5f6b, 0x4427 => 0x5fb4, 0x4428 => 0x61f2, + 0x4429 => 0x6311, 0x442a => 0x66a2, 0x442b => 0x671d, 0x442c => 0x6f6e, + 0x442d => 0x7252, 0x442e => 0x753a, 0x442f => 0x773a, 0x4430 => 0x8074, + 0x4431 => 0x8139, 0x4432 => 0x8178, 0x4433 => 0x8776, 0x4434 => 0x8abf, + 0x4435 => 0x8adc, 0x4436 => 0x8d85, 0x4437 => 0x8df3, 0x4438 => 0x929a, + 0x4439 => 0x9577, 0x443a => 0x9802, 0x443b => 0x9ce5, 0x443c => 0x52c5, + 0x443d => 0x6357, 0x443e => 0x76f4, 0x443f => 0x6715, 0x4440 => 0x6c88, + 0x4441 => 0x73cd, 0x4442 => 0x8cc3, 0x4443 => 0x93ae, 0x4444 => 0x9673, + 0x4445 => 0x6d25, 0x4446 => 0x589c, 0x4447 => 0x690e, 0x4448 => 0x69cc, + 0x4449 => 0x8ffd, 0x444a => 0x939a, 0x444b => 0x75db, 0x444c => 0x901a, + 0x444d => 0x585a, 0x444e => 0x6802, 0x444f => 0x63b4, 0x4450 => 0x69fb, + 0x4451 => 0x4f43, 0x4452 => 0x6f2c, 0x4453 => 0x67d8, 0x4454 => 0x8fbb, + 0x4455 => 0x8526, 0x4456 => 0x7db4, 0x4457 => 0x9354, 0x4458 => 0x693f, + 0x4459 => 0x6f70, 0x445a => 0x576a, 0x445b => 0x58f7, 0x445c => 0x5b2c, + 0x445d => 0x7d2c, 0x445e => 0x722a, 0x445f => 0x540a, 0x4460 => 0x91e3, + 0x4461 => 0x9db4, 0x4462 => 0x4ead, 0x4463 => 0x4f4e, 0x4464 => 0x505c, + 0x4465 => 0x5075, 0x4466 => 0x5243, 0x4467 => 0x8c9e, 0x4468 => 0x5448, + 0x4469 => 0x5824, 0x446a => 0x5b9a, 0x446b => 0x5e1d, 0x446c => 0x5e95, + 0x446d => 0x5ead, 0x446e => 0x5ef7, 0x446f => 0x5f1f, 0x4470 => 0x608c, + 0x4471 => 0x62b5, 0x4472 => 0x633a, 0x4473 => 0x63d0, 0x4474 => 0x68af, + 0x4475 => 0x6c40, 0x4476 => 0x7887, 0x4477 => 0x798e, 0x4478 => 0x7a0b, + 0x4479 => 0x7de0, 0x447a => 0x8247, 0x447b => 0x8a02, 0x447c => 0x8ae6, + 0x447d => 0x8e44, 0x447e => 0x9013, 0x4521 => 0x90b8, 0x4522 => 0x912d, + 0x4523 => 0x91d8, 0x4524 => 0x9f0e, 0x4525 => 0x6ce5, 0x4526 => 0x6458, + 0x4527 => 0x64e2, 0x4528 => 0x6575, 0x4529 => 0x6ef4, 0x452a => 0x7684, + 0x452b => 0x7b1b, 0x452c => 0x9069, 0x452d => 0x93d1, 0x452e => 0x6eba, + 0x452f => 0x54f2, 0x4530 => 0x5fb9, 0x4531 => 0x64a4, 0x4532 => 0x8f4d, + 0x4533 => 0x8fed, 0x4534 => 0x9244, 0x4535 => 0x5178, 0x4536 => 0x586b, + 0x4537 => 0x5929, 0x4538 => 0x5c55, 0x4539 => 0x5e97, 0x453a => 0x6dfb, + 0x453b => 0x7e8f, 0x453c => 0x751c, 0x453d => 0x8cbc, 0x453e => 0x8ee2, + 0x453f => 0x985b, 0x4540 => 0x70b9, 0x4541 => 0x4f1d, 0x4542 => 0x6bbf, + 0x4543 => 0x6fb1, 0x4544 => 0x7530, 0x4545 => 0x96fb, 0x4546 => 0x514e, + 0x4547 => 0x5410, 0x4548 => 0x5835, 0x4549 => 0x5857, 0x454a => 0x59ac, + 0x454b => 0x5c60, 0x454c => 0x5f92, 0x454d => 0x6597, 0x454e => 0x675c, + 0x454f => 0x6e21, 0x4550 => 0x767b, 0x4551 => 0x83df, 0x4552 => 0x8ced, + 0x4553 => 0x9014, 0x4554 => 0x90fd, 0x4555 => 0x934d, 0x4556 => 0x7825, + 0x4557 => 0x783a, 0x4558 => 0x52aa, 0x4559 => 0x5ea6, 0x455a => 0x571f, + 0x455b => 0x5974, 0x455c => 0x6012, 0x455d => 0x5012, 0x455e => 0x515a, + 0x455f => 0x51ac, 0x4560 => 0x51cd, 0x4561 => 0x5200, 0x4562 => 0x5510, + 0x4563 => 0x5854, 0x4564 => 0x5858, 0x4565 => 0x5957, 0x4566 => 0x5b95, + 0x4567 => 0x5cf6, 0x4568 => 0x5d8b, 0x4569 => 0x60bc, 0x456a => 0x6295, + 0x456b => 0x642d, 0x456c => 0x6771, 0x456d => 0x6843, 0x456e => 0x68bc, + 0x456f => 0x68df, 0x4570 => 0x76d7, 0x4571 => 0x6dd8, 0x4572 => 0x6e6f, + 0x4573 => 0x6d9b, 0x4574 => 0x706f, 0x4575 => 0x71c8, 0x4576 => 0x5f53, + 0x4577 => 0x75d8, 0x4578 => 0x7977, 0x4579 => 0x7b49, 0x457a => 0x7b54, + 0x457b => 0x7b52, 0x457c => 0x7cd6, 0x457d => 0x7d71, 0x457e => 0x5230, + 0x4621 => 0x8463, 0x4622 => 0x8569, 0x4623 => 0x85e4, 0x4624 => 0x8a0e, + 0x4625 => 0x8b04, 0x4626 => 0x8c46, 0x4627 => 0x8e0f, 0x4628 => 0x9003, + 0x4629 => 0x900f, 0x462a => 0x9419, 0x462b => 0x9676, 0x462c => 0x982d, + 0x462d => 0x9a30, 0x462e => 0x95d8, 0x462f => 0x50cd, 0x4630 => 0x52d5, + 0x4631 => 0x540c, 0x4632 => 0x5802, 0x4633 => 0x5c0e, 0x4634 => 0x61a7, + 0x4635 => 0x649e, 0x4636 => 0x6d1e, 0x4637 => 0x77b3, 0x4638 => 0x7ae5, + 0x4639 => 0x80f4, 0x463a => 0x8404, 0x463b => 0x9053, 0x463c => 0x9285, + 0x463d => 0x5ce0, 0x463e => 0x9d07, 0x463f => 0x533f, 0x4640 => 0x5f97, + 0x4641 => 0x5fb3, 0x4642 => 0x6d9c, 0x4643 => 0x7279, 0x4644 => 0x7763, + 0x4645 => 0x79bf, 0x4646 => 0x7be4, 0x4647 => 0x6bd2, 0x4648 => 0x72ec, + 0x4649 => 0x8aad, 0x464a => 0x6803, 0x464b => 0x6a61, 0x464c => 0x51f8, + 0x464d => 0x7a81, 0x464e => 0x6934, 0x464f => 0x5c4a, 0x4650 => 0x9cf6, + 0x4651 => 0x82eb, 0x4652 => 0x5bc5, 0x4653 => 0x9149, 0x4654 => 0x701e, + 0x4655 => 0x5678, 0x4656 => 0x5c6f, 0x4657 => 0x60c7, 0x4658 => 0x6566, + 0x4659 => 0x6c8c, 0x465a => 0x8c5a, 0x465b => 0x9041, 0x465c => 0x9813, + 0x465d => 0x5451, 0x465e => 0x66c7, 0x465f => 0x920d, 0x4660 => 0x5948, + 0x4661 => 0x90a3, 0x4662 => 0x5185, 0x4663 => 0x4e4d, 0x4664 => 0x51ea, + 0x4665 => 0x8599, 0x4666 => 0x8b0e, 0x4667 => 0x7058, 0x4668 => 0x637a, + 0x4669 => 0x934b, 0x466a => 0x6962, 0x466b => 0x99b4, 0x466c => 0x7e04, + 0x466d => 0x7577, 0x466e => 0x5357, 0x466f => 0x6960, 0x4670 => 0x8edf, + 0x4671 => 0x96e3, 0x4672 => 0x6c5d, 0x4673 => 0x4e8c, 0x4674 => 0x5c3c, + 0x4675 => 0x5f10, 0x4676 => 0x8fe9, 0x4677 => 0x5302, 0x4678 => 0x8cd1, + 0x4679 => 0x8089, 0x467a => 0x8679, 0x467b => 0x5eff, 0x467c => 0x65e5, + 0x467d => 0x4e73, 0x467e => 0x5165, 0x4721 => 0x5982, 0x4722 => 0x5c3f, + 0x4723 => 0x97ee, 0x4724 => 0x4efb, 0x4725 => 0x598a, 0x4726 => 0x5fcd, + 0x4727 => 0x8a8d, 0x4728 => 0x6fe1, 0x4729 => 0x79b0, 0x472a => 0x7962, + 0x472b => 0x5be7, 0x472c => 0x8471, 0x472d => 0x732b, 0x472e => 0x71b1, + 0x472f => 0x5e74, 0x4730 => 0x5ff5, 0x4731 => 0x637b, 0x4732 => 0x649a, + 0x4733 => 0x71c3, 0x4734 => 0x7c98, 0x4735 => 0x4e43, 0x4736 => 0x5efc, + 0x4737 => 0x4e4b, 0x4738 => 0x57dc, 0x4739 => 0x56a2, 0x473a => 0x60a9, + 0x473b => 0x6fc3, 0x473c => 0x7d0d, 0x473d => 0x80fd, 0x473e => 0x8133, + 0x473f => 0x81bf, 0x4740 => 0x8fb2, 0x4741 => 0x8997, 0x4742 => 0x86a4, + 0x4743 => 0x5df4, 0x4744 => 0x628a, 0x4745 => 0x64ad, 0x4746 => 0x8987, + 0x4747 => 0x6777, 0x4748 => 0x6ce2, 0x4749 => 0x6d3e, 0x474a => 0x7436, + 0x474b => 0x7834, 0x474c => 0x5a46, 0x474d => 0x7f75, 0x474e => 0x82ad, + 0x474f => 0x99ac, 0x4750 => 0x4ff3, 0x4751 => 0x5ec3, 0x4752 => 0x62dd, + 0x4753 => 0x6392, 0x4754 => 0x6557, 0x4755 => 0x676f, 0x4756 => 0x76c3, + 0x4757 => 0x724c, 0x4758 => 0x80cc, 0x4759 => 0x80ba, 0x475a => 0x8f29, + 0x475b => 0x914d, 0x475c => 0x500d, 0x475d => 0x57f9, 0x475e => 0x5a92, + 0x475f => 0x6885, 0x4760 => 0x6973, 0x4761 => 0x7164, 0x4762 => 0x72fd, + 0x4763 => 0x8cb7, 0x4764 => 0x58f2, 0x4765 => 0x8ce0, 0x4766 => 0x966a, + 0x4767 => 0x9019, 0x4768 => 0x877f, 0x4769 => 0x79e4, 0x476a => 0x77e7, + 0x476b => 0x8429, 0x476c => 0x4f2f, 0x476d => 0x5265, 0x476e => 0x535a, + 0x476f => 0x62cd, 0x4770 => 0x67cf, 0x4771 => 0x6cca, 0x4772 => 0x767d, + 0x4773 => 0x7b94, 0x4774 => 0x7c95, 0x4775 => 0x8236, 0x4776 => 0x8584, + 0x4777 => 0x8feb, 0x4778 => 0x66dd, 0x4779 => 0x6f20, 0x477a => 0x7206, + 0x477b => 0x7e1b, 0x477c => 0x83ab, 0x477d => 0x99c1, 0x477e => 0x9ea6, + 0x4821 => 0x51fd, 0x4822 => 0x7bb1, 0x4823 => 0x7872, 0x4824 => 0x7bb8, + 0x4825 => 0x8087, 0x4826 => 0x7b48, 0x4827 => 0x6ae8, 0x4828 => 0x5e61, + 0x4829 => 0x808c, 0x482a => 0x7551, 0x482b => 0x7560, 0x482c => 0x516b, + 0x482d => 0x9262, 0x482e => 0x6e8c, 0x482f => 0x767a, 0x4830 => 0x9197, + 0x4831 => 0x9aea, 0x4832 => 0x4f10, 0x4833 => 0x7f70, 0x4834 => 0x629c, + 0x4835 => 0x7b4f, 0x4836 => 0x95a5, 0x4837 => 0x9ce9, 0x4838 => 0x567a, + 0x4839 => 0x5859, 0x483a => 0x86e4, 0x483b => 0x96bc, 0x483c => 0x4f34, + 0x483d => 0x5224, 0x483e => 0x534a, 0x483f => 0x53cd, 0x4840 => 0x53db, + 0x4841 => 0x5e06, 0x4842 => 0x642c, 0x4843 => 0x6591, 0x4844 => 0x677f, + 0x4845 => 0x6c3e, 0x4846 => 0x6c4e, 0x4847 => 0x7248, 0x4848 => 0x72af, + 0x4849 => 0x73ed, 0x484a => 0x7554, 0x484b => 0x7e41, 0x484c => 0x822c, + 0x484d => 0x85e9, 0x484e => 0x8ca9, 0x484f => 0x7bc4, 0x4850 => 0x91c6, + 0x4851 => 0x7169, 0x4852 => 0x9812, 0x4853 => 0x98ef, 0x4854 => 0x633d, + 0x4855 => 0x6669, 0x4856 => 0x756a, 0x4857 => 0x76e4, 0x4858 => 0x78d0, + 0x4859 => 0x8543, 0x485a => 0x86ee, 0x485b => 0x532a, 0x485c => 0x5351, + 0x485d => 0x5426, 0x485e => 0x5983, 0x485f => 0x5e87, 0x4860 => 0x5f7c, + 0x4861 => 0x60b2, 0x4862 => 0x6249, 0x4863 => 0x6279, 0x4864 => 0x62ab, + 0x4865 => 0x6590, 0x4866 => 0x6bd4, 0x4867 => 0x6ccc, 0x4868 => 0x75b2, + 0x4869 => 0x76ae, 0x486a => 0x7891, 0x486b => 0x79d8, 0x486c => 0x7dcb, + 0x486d => 0x7f77, 0x486e => 0x80a5, 0x486f => 0x88ab, 0x4870 => 0x8ab9, + 0x4871 => 0x8cbb, 0x4872 => 0x907f, 0x4873 => 0x975e, 0x4874 => 0x98db, + 0x4875 => 0x6a0b, 0x4876 => 0x7c38, 0x4877 => 0x5099, 0x4878 => 0x5c3e, + 0x4879 => 0x5fae, 0x487a => 0x6787, 0x487b => 0x6bd8, 0x487c => 0x7435, + 0x487d => 0x7709, 0x487e => 0x7f8e, 0x4921 => 0x9f3b, 0x4922 => 0x67ca, + 0x4923 => 0x7a17, 0x4924 => 0x5339, 0x4925 => 0x758b, 0x4926 => 0x9aed, + 0x4927 => 0x5f66, 0x4928 => 0x819d, 0x4929 => 0x83f1, 0x492a => 0x8098, + 0x492b => 0x5f3c, 0x492c => 0x5fc5, 0x492d => 0x7562, 0x492e => 0x7b46, + 0x492f => 0x903c, 0x4930 => 0x6867, 0x4931 => 0x59eb, 0x4932 => 0x5a9b, + 0x4933 => 0x7d10, 0x4934 => 0x767e, 0x4935 => 0x8b2c, 0x4936 => 0x4ff5, + 0x4937 => 0x5f6a, 0x4938 => 0x6a19, 0x4939 => 0x6c37, 0x493a => 0x6f02, + 0x493b => 0x74e2, 0x493c => 0x7968, 0x493d => 0x8868, 0x493e => 0x8a55, + 0x493f => 0x8c79, 0x4940 => 0x5edf, 0x4941 => 0x63cf, 0x4942 => 0x75c5, + 0x4943 => 0x79d2, 0x4944 => 0x82d7, 0x4945 => 0x9328, 0x4946 => 0x92f2, + 0x4947 => 0x849c, 0x4948 => 0x86ed, 0x4949 => 0x9c2d, 0x494a => 0x54c1, + 0x494b => 0x5f6c, 0x494c => 0x658c, 0x494d => 0x6d5c, 0x494e => 0x7015, + 0x494f => 0x8ca7, 0x4950 => 0x8cd3, 0x4951 => 0x983b, 0x4952 => 0x654f, + 0x4953 => 0x74f6, 0x4954 => 0x4e0d, 0x4955 => 0x4ed8, 0x4956 => 0x57e0, + 0x4957 => 0x592b, 0x4958 => 0x5a66, 0x4959 => 0x5bcc, 0x495a => 0x51a8, + 0x495b => 0x5e03, 0x495c => 0x5e9c, 0x495d => 0x6016, 0x495e => 0x6276, + 0x495f => 0x6577, 0x4960 => 0x65a7, 0x4961 => 0x666e, 0x4962 => 0x6d6e, + 0x4963 => 0x7236, 0x4964 => 0x7b26, 0x4965 => 0x8150, 0x4966 => 0x819a, + 0x4967 => 0x8299, 0x4968 => 0x8b5c, 0x4969 => 0x8ca0, 0x496a => 0x8ce6, + 0x496b => 0x8d74, 0x496c => 0x961c, 0x496d => 0x9644, 0x496e => 0x4fae, + 0x496f => 0x64ab, 0x4970 => 0x6b66, 0x4971 => 0x821e, 0x4972 => 0x8461, + 0x4973 => 0x856a, 0x4974 => 0x90e8, 0x4975 => 0x5c01, 0x4976 => 0x6953, + 0x4977 => 0x98a8, 0x4978 => 0x847a, 0x4979 => 0x8557, 0x497a => 0x4f0f, + 0x497b => 0x526f, 0x497c => 0x5fa9, 0x497d => 0x5e45, 0x497e => 0x670d, + 0x4a21 => 0x798f, 0x4a22 => 0x8179, 0x4a23 => 0x8907, 0x4a24 => 0x8986, + 0x4a25 => 0x6df5, 0x4a26 => 0x5f17, 0x4a27 => 0x6255, 0x4a28 => 0x6cb8, + 0x4a29 => 0x4ecf, 0x4a2a => 0x7269, 0x4a2b => 0x9b92, 0x4a2c => 0x5206, + 0x4a2d => 0x543b, 0x4a2e => 0x5674, 0x4a2f => 0x58b3, 0x4a30 => 0x61a4, + 0x4a31 => 0x626e, 0x4a32 => 0x711a, 0x4a33 => 0x596e, 0x4a34 => 0x7c89, + 0x4a35 => 0x7cde, 0x4a36 => 0x7d1b, 0x4a37 => 0x96f0, 0x4a38 => 0x6587, + 0x4a39 => 0x805e, 0x4a3a => 0x4e19, 0x4a3b => 0x4f75, 0x4a3c => 0x5175, + 0x4a3d => 0x5840, 0x4a3e => 0x5e63, 0x4a3f => 0x5e73, 0x4a40 => 0x5f0a, + 0x4a41 => 0x67c4, 0x4a42 => 0x4e26, 0x4a43 => 0x853d, 0x4a44 => 0x9589, + 0x4a45 => 0x965b, 0x4a46 => 0x7c73, 0x4a47 => 0x9801, 0x4a48 => 0x50fb, + 0x4a49 => 0x58c1, 0x4a4a => 0x7656, 0x4a4b => 0x78a7, 0x4a4c => 0x5225, + 0x4a4d => 0x77a5, 0x4a4e => 0x8511, 0x4a4f => 0x7b86, 0x4a50 => 0x504f, + 0x4a51 => 0x5909, 0x4a52 => 0x7247, 0x4a53 => 0x7bc7, 0x4a54 => 0x7de8, + 0x4a55 => 0x8fba, 0x4a56 => 0x8fd4, 0x4a57 => 0x904d, 0x4a58 => 0x4fbf, + 0x4a59 => 0x52c9, 0x4a5a => 0x5a29, 0x4a5b => 0x5f01, 0x4a5c => 0x97ad, + 0x4a5d => 0x4fdd, 0x4a5e => 0x8217, 0x4a5f => 0x92ea, 0x4a60 => 0x5703, + 0x4a61 => 0x6355, 0x4a62 => 0x6b69, 0x4a63 => 0x752b, 0x4a64 => 0x88dc, + 0x4a65 => 0x8f14, 0x4a66 => 0x7a42, 0x4a67 => 0x52df, 0x4a68 => 0x5893, + 0x4a69 => 0x6155, 0x4a6a => 0x620a, 0x4a6b => 0x66ae, 0x4a6c => 0x6bcd, + 0x4a6d => 0x7c3f, 0x4a6e => 0x83e9, 0x4a6f => 0x5023, 0x4a70 => 0x4ff8, + 0x4a71 => 0x5305, 0x4a72 => 0x5446, 0x4a73 => 0x5831, 0x4a74 => 0x5949, + 0x4a75 => 0x5b9d, 0x4a76 => 0x5cf0, 0x4a77 => 0x5cef, 0x4a78 => 0x5d29, + 0x4a79 => 0x5e96, 0x4a7a => 0x62b1, 0x4a7b => 0x6367, 0x4a7c => 0x653e, + 0x4a7d => 0x65b9, 0x4a7e => 0x670b, 0x4b21 => 0x6cd5, 0x4b22 => 0x6ce1, + 0x4b23 => 0x70f9, 0x4b24 => 0x7832, 0x4b25 => 0x7e2b, 0x4b26 => 0x80de, + 0x4b27 => 0x82b3, 0x4b28 => 0x840c, 0x4b29 => 0x84ec, 0x4b2a => 0x8702, + 0x4b2b => 0x8912, 0x4b2c => 0x8a2a, 0x4b2d => 0x8c4a, 0x4b2e => 0x90a6, + 0x4b2f => 0x92d2, 0x4b30 => 0x98fd, 0x4b31 => 0x9cf3, 0x4b32 => 0x9d6c, + 0x4b33 => 0x4e4f, 0x4b34 => 0x4ea1, 0x4b35 => 0x508d, 0x4b36 => 0x5256, + 0x4b37 => 0x574a, 0x4b38 => 0x59a8, 0x4b39 => 0x5e3d, 0x4b3a => 0x5fd8, + 0x4b3b => 0x5fd9, 0x4b3c => 0x623f, 0x4b3d => 0x66b4, 0x4b3e => 0x671b, + 0x4b3f => 0x67d0, 0x4b40 => 0x68d2, 0x4b41 => 0x5192, 0x4b42 => 0x7d21, + 0x4b43 => 0x80aa, 0x4b44 => 0x81a8, 0x4b45 => 0x8b00, 0x4b46 => 0x8c8c, + 0x4b47 => 0x8cbf, 0x4b48 => 0x927e, 0x4b49 => 0x9632, 0x4b4a => 0x5420, + 0x4b4b => 0x982c, 0x4b4c => 0x5317, 0x4b4d => 0x50d5, 0x4b4e => 0x535c, + 0x4b4f => 0x58a8, 0x4b50 => 0x64b2, 0x4b51 => 0x6734, 0x4b52 => 0x7267, + 0x4b53 => 0x7766, 0x4b54 => 0x7a46, 0x4b55 => 0x91e6, 0x4b56 => 0x52c3, + 0x4b57 => 0x6ca1, 0x4b58 => 0x6b86, 0x4b59 => 0x5800, 0x4b5a => 0x5e4c, + 0x4b5b => 0x5954, 0x4b5c => 0x672c, 0x4b5d => 0x7ffb, 0x4b5e => 0x51e1, + 0x4b5f => 0x76c6, 0x4b60 => 0x6469, 0x4b61 => 0x78e8, 0x4b62 => 0x9b54, + 0x4b63 => 0x9ebb, 0x4b64 => 0x57cb, 0x4b65 => 0x59b9, 0x4b66 => 0x6627, + 0x4b67 => 0x679a, 0x4b68 => 0x6bce, 0x4b69 => 0x54e9, 0x4b6a => 0x69d9, + 0x4b6b => 0x5e55, 0x4b6c => 0x819c, 0x4b6d => 0x6795, 0x4b6e => 0x9baa, + 0x4b6f => 0x67fe, 0x4b70 => 0x9c52, 0x4b71 => 0x685d, 0x4b72 => 0x4ea6, + 0x4b73 => 0x4fe3, 0x4b74 => 0x53c8, 0x4b75 => 0x62b9, 0x4b76 => 0x672b, + 0x4b77 => 0x6cab, 0x4b78 => 0x8fc4, 0x4b79 => 0x4fad, 0x4b7a => 0x7e6d, + 0x4b7b => 0x9ebf, 0x4b7c => 0x4e07, 0x4b7d => 0x6162, 0x4b7e => 0x6e80, + 0x4c21 => 0x6f2b, 0x4c22 => 0x8513, 0x4c23 => 0x5473, 0x4c24 => 0x672a, + 0x4c25 => 0x9b45, 0x4c26 => 0x5df3, 0x4c27 => 0x7b95, 0x4c28 => 0x5cac, + 0x4c29 => 0x5bc6, 0x4c2a => 0x871c, 0x4c2b => 0x6e4a, 0x4c2c => 0x84d1, + 0x4c2d => 0x7a14, 0x4c2e => 0x8108, 0x4c2f => 0x5999, 0x4c30 => 0x7c8d, + 0x4c31 => 0x6c11, 0x4c32 => 0x7720, 0x4c33 => 0x52d9, 0x4c34 => 0x5922, + 0x4c35 => 0x7121, 0x4c36 => 0x725f, 0x4c37 => 0x77db, 0x4c38 => 0x9727, + 0x4c39 => 0x9d61, 0x4c3a => 0x690b, 0x4c3b => 0x5a7f, 0x4c3c => 0x5a18, + 0x4c3d => 0x51a5, 0x4c3e => 0x540d, 0x4c3f => 0x547d, 0x4c40 => 0x660e, + 0x4c41 => 0x76df, 0x4c42 => 0x8ff7, 0x4c43 => 0x9298, 0x4c44 => 0x9cf4, + 0x4c45 => 0x59ea, 0x4c46 => 0x725d, 0x4c47 => 0x6ec5, 0x4c48 => 0x514d, + 0x4c49 => 0x68c9, 0x4c4a => 0x7dbf, 0x4c4b => 0x7dec, 0x4c4c => 0x9762, + 0x4c4d => 0x9eba, 0x4c4e => 0x6478, 0x4c4f => 0x6a21, 0x4c50 => 0x8302, + 0x4c51 => 0x5984, 0x4c52 => 0x5b5f, 0x4c53 => 0x6bdb, 0x4c54 => 0x731b, + 0x4c55 => 0x76f2, 0x4c56 => 0x7db2, 0x4c57 => 0x8017, 0x4c58 => 0x8499, + 0x4c59 => 0x5132, 0x4c5a => 0x6728, 0x4c5b => 0x9ed9, 0x4c5c => 0x76ee, + 0x4c5d => 0x6762, 0x4c5e => 0x52ff, 0x4c5f => 0x9905, 0x4c60 => 0x5c24, + 0x4c61 => 0x623b, 0x4c62 => 0x7c7e, 0x4c63 => 0x8cb0, 0x4c64 => 0x554f, + 0x4c65 => 0x60b6, 0x4c66 => 0x7d0b, 0x4c67 => 0x9580, 0x4c68 => 0x5301, + 0x4c69 => 0x4e5f, 0x4c6a => 0x51b6, 0x4c6b => 0x591c, 0x4c6c => 0x723a, + 0x4c6d => 0x8036, 0x4c6e => 0x91ce, 0x4c6f => 0x5f25, 0x4c70 => 0x77e2, + 0x4c71 => 0x5384, 0x4c72 => 0x5f79, 0x4c73 => 0x7d04, 0x4c74 => 0x85ac, + 0x4c75 => 0x8a33, 0x4c76 => 0x8e8d, 0x4c77 => 0x9756, 0x4c78 => 0x67f3, + 0x4c79 => 0x85ae, 0x4c7a => 0x9453, 0x4c7b => 0x6109, 0x4c7c => 0x6108, + 0x4c7d => 0x6cb9, 0x4c7e => 0x7652, 0x4d21 => 0x8aed, 0x4d22 => 0x8f38, + 0x4d23 => 0x552f, 0x4d24 => 0x4f51, 0x4d25 => 0x512a, 0x4d26 => 0x52c7, + 0x4d27 => 0x53cb, 0x4d28 => 0x5ba5, 0x4d29 => 0x5e7d, 0x4d2a => 0x60a0, + 0x4d2b => 0x6182, 0x4d2c => 0x63d6, 0x4d2d => 0x6709, 0x4d2e => 0x67da, + 0x4d2f => 0x6e67, 0x4d30 => 0x6d8c, 0x4d31 => 0x7336, 0x4d32 => 0x7337, + 0x4d33 => 0x7531, 0x4d34 => 0x7950, 0x4d35 => 0x88d5, 0x4d36 => 0x8a98, + 0x4d37 => 0x904a, 0x4d38 => 0x9091, 0x4d39 => 0x90f5, 0x4d3a => 0x96c4, + 0x4d3b => 0x878d, 0x4d3c => 0x5915, 0x4d3d => 0x4e88, 0x4d3e => 0x4f59, + 0x4d3f => 0x4e0e, 0x4d40 => 0x8a89, 0x4d41 => 0x8f3f, 0x4d42 => 0x9810, + 0x4d43 => 0x50ad, 0x4d44 => 0x5e7c, 0x4d45 => 0x5996, 0x4d46 => 0x5bb9, + 0x4d47 => 0x5eb8, 0x4d48 => 0x63da, 0x4d49 => 0x63fa, 0x4d4a => 0x64c1, + 0x4d4b => 0x66dc, 0x4d4c => 0x694a, 0x4d4d => 0x69d8, 0x4d4e => 0x6d0b, + 0x4d4f => 0x6eb6, 0x4d50 => 0x7194, 0x4d51 => 0x7528, 0x4d52 => 0x7aaf, + 0x4d53 => 0x7f8a, 0x4d54 => 0x8000, 0x4d55 => 0x8449, 0x4d56 => 0x84c9, + 0x4d57 => 0x8981, 0x4d58 => 0x8b21, 0x4d59 => 0x8e0a, 0x4d5a => 0x9065, + 0x4d5b => 0x967d, 0x4d5c => 0x990a, 0x4d5d => 0x617e, 0x4d5e => 0x6291, + 0x4d5f => 0x6b32, 0x4d60 => 0x6c83, 0x4d61 => 0x6d74, 0x4d62 => 0x7fcc, + 0x4d63 => 0x7ffc, 0x4d64 => 0x6dc0, 0x4d65 => 0x7f85, 0x4d66 => 0x87ba, + 0x4d67 => 0x88f8, 0x4d68 => 0x6765, 0x4d69 => 0x83b1, 0x4d6a => 0x983c, + 0x4d6b => 0x96f7, 0x4d6c => 0x6d1b, 0x4d6d => 0x7d61, 0x4d6e => 0x843d, + 0x4d6f => 0x916a, 0x4d70 => 0x4e71, 0x4d71 => 0x5375, 0x4d72 => 0x5d50, + 0x4d73 => 0x6b04, 0x4d74 => 0x6feb, 0x4d75 => 0x85cd, 0x4d76 => 0x862d, + 0x4d77 => 0x89a7, 0x4d78 => 0x5229, 0x4d79 => 0x540f, 0x4d7a => 0x5c65, + 0x4d7b => 0x674e, 0x4d7c => 0x68a8, 0x4d7d => 0x7406, 0x4d7e => 0x7483, + 0x4e21 => 0x75e2, 0x4e22 => 0x88cf, 0x4e23 => 0x88e1, 0x4e24 => 0x91cc, + 0x4e25 => 0x96e2, 0x4e26 => 0x9678, 0x4e27 => 0x5f8b, 0x4e28 => 0x7387, + 0x4e29 => 0x7acb, 0x4e2a => 0x844e, 0x4e2b => 0x63a0, 0x4e2c => 0x7565, + 0x4e2d => 0x5289, 0x4e2e => 0x6d41, 0x4e2f => 0x6e9c, 0x4e30 => 0x7409, + 0x4e31 => 0x7559, 0x4e32 => 0x786b, 0x4e33 => 0x7c92, 0x4e34 => 0x9686, + 0x4e35 => 0x7adc, 0x4e36 => 0x9f8d, 0x4e37 => 0x4fb6, 0x4e38 => 0x616e, + 0x4e39 => 0x65c5, 0x4e3a => 0x865c, 0x4e3b => 0x4e86, 0x4e3c => 0x4eae, + 0x4e3d => 0x50da, 0x4e3e => 0x4e21, 0x4e3f => 0x51cc, 0x4e40 => 0x5bee, + 0x4e41 => 0x6599, 0x4e42 => 0x6881, 0x4e43 => 0x6dbc, 0x4e44 => 0x731f, + 0x4e45 => 0x7642, 0x4e46 => 0x77ad, 0x4e47 => 0x7a1c, 0x4e48 => 0x7ce7, + 0x4e49 => 0x826f, 0x4e4a => 0x8ad2, 0x4e4b => 0x907c, 0x4e4c => 0x91cf, + 0x4e4d => 0x9675, 0x4e4e => 0x9818, 0x4e4f => 0x529b, 0x4e50 => 0x7dd1, + 0x4e51 => 0x502b, 0x4e52 => 0x5398, 0x4e53 => 0x6797, 0x4e54 => 0x6dcb, + 0x4e55 => 0x71d0, 0x4e56 => 0x7433, 0x4e57 => 0x81e8, 0x4e58 => 0x8f2a, + 0x4e59 => 0x96a3, 0x4e5a => 0x9c57, 0x4e5b => 0x9e9f, 0x4e5c => 0x7460, + 0x4e5d => 0x5841, 0x4e5e => 0x6d99, 0x4e5f => 0x7d2f, 0x4e60 => 0x985e, + 0x4e61 => 0x4ee4, 0x4e62 => 0x4f36, 0x4e63 => 0x4f8b, 0x4e64 => 0x51b7, + 0x4e65 => 0x52b1, 0x4e66 => 0x5dba, 0x4e67 => 0x601c, 0x4e68 => 0x73b2, + 0x4e69 => 0x793c, 0x4e6a => 0x82d3, 0x4e6b => 0x9234, 0x4e6c => 0x96b7, + 0x4e6d => 0x96f6, 0x4e6e => 0x970a, 0x4e6f => 0x9e97, 0x4e70 => 0x9f62, + 0x4e71 => 0x66a6, 0x4e72 => 0x6b74, 0x4e73 => 0x5217, 0x4e74 => 0x52a3, + 0x4e75 => 0x70c8, 0x4e76 => 0x88c2, 0x4e77 => 0x5ec9, 0x4e78 => 0x604b, + 0x4e79 => 0x6190, 0x4e7a => 0x6f23, 0x4e7b => 0x7149, 0x4e7c => 0x7c3e, + 0x4e7d => 0x7df4, 0x4e7e => 0x806f, 0x4f21 => 0x84ee, 0x4f22 => 0x9023, + 0x4f23 => 0x932c, 0x4f24 => 0x5442, 0x4f25 => 0x9b6f, 0x4f26 => 0x6ad3, + 0x4f27 => 0x7089, 0x4f28 => 0x8cc2, 0x4f29 => 0x8def, 0x4f2a => 0x9732, + 0x4f2b => 0x52b4, 0x4f2c => 0x5a41, 0x4f2d => 0x5eca, 0x4f2e => 0x5f04, + 0x4f2f => 0x6717, 0x4f30 => 0x697c, 0x4f31 => 0x6994, 0x4f32 => 0x6d6a, + 0x4f33 => 0x6f0f, 0x4f34 => 0x7262, 0x4f35 => 0x72fc, 0x4f36 => 0x7bed, + 0x4f37 => 0x8001, 0x4f38 => 0x807e, 0x4f39 => 0x874b, 0x4f3a => 0x90ce, + 0x4f3b => 0x516d, 0x4f3c => 0x9e93, 0x4f3d => 0x7984, 0x4f3e => 0x808b, + 0x4f3f => 0x9332, 0x4f40 => 0x8ad6, 0x4f41 => 0x502d, 0x4f42 => 0x548c, + 0x4f43 => 0x8a71, 0x4f44 => 0x6b6a, 0x4f45 => 0x8cc4, 0x4f46 => 0x8107, + 0x4f47 => 0x60d1, 0x4f48 => 0x67a0, 0x4f49 => 0x9df2, 0x4f4a => 0x4e99, + 0x4f4b => 0x4e98, 0x4f4c => 0x9c10, 0x4f4d => 0x8a6b, 0x4f4e => 0x85c1, + 0x4f4f => 0x8568, 0x4f50 => 0x6900, 0x4f51 => 0x6e7e, 0x4f52 => 0x7897, + 0x4f53 => 0x8155, 0x5021 => 0x5f0c, 0x5022 => 0x4e10, 0x5023 => 0x4e15, + 0x5024 => 0x4e2a, 0x5025 => 0x4e31, 0x5026 => 0x4e36, 0x5027 => 0x4e3c, + 0x5028 => 0x4e3f, 0x5029 => 0x4e42, 0x502a => 0x4e56, 0x502b => 0x4e58, + 0x502c => 0x4e82, 0x502d => 0x4e85, 0x502e => 0x8c6b, 0x502f => 0x4e8a, + 0x5030 => 0x8212, 0x5031 => 0x5f0d, 0x5032 => 0x4e8e, 0x5033 => 0x4e9e, + 0x5034 => 0x4e9f, 0x5035 => 0x4ea0, 0x5036 => 0x4ea2, 0x5037 => 0x4eb0, + 0x5038 => 0x4eb3, 0x5039 => 0x4eb6, 0x503a => 0x4ece, 0x503b => 0x4ecd, + 0x503c => 0x4ec4, 0x503d => 0x4ec6, 0x503e => 0x4ec2, 0x503f => 0x4ed7, + 0x5040 => 0x4ede, 0x5041 => 0x4eed, 0x5042 => 0x4edf, 0x5043 => 0x4ef7, + 0x5044 => 0x4f09, 0x5045 => 0x4f5a, 0x5046 => 0x4f30, 0x5047 => 0x4f5b, + 0x5048 => 0x4f5d, 0x5049 => 0x4f57, 0x504a => 0x4f47, 0x504b => 0x4f76, + 0x504c => 0x4f88, 0x504d => 0x4f8f, 0x504e => 0x4f98, 0x504f => 0x4f7b, + 0x5050 => 0x4f69, 0x5051 => 0x4f70, 0x5052 => 0x4f91, 0x5053 => 0x4f6f, + 0x5054 => 0x4f86, 0x5055 => 0x4f96, 0x5056 => 0x5118, 0x5057 => 0x4fd4, + 0x5058 => 0x4fdf, 0x5059 => 0x4fce, 0x505a => 0x4fd8, 0x505b => 0x4fdb, + 0x505c => 0x4fd1, 0x505d => 0x4fda, 0x505e => 0x4fd0, 0x505f => 0x4fe4, + 0x5060 => 0x4fe5, 0x5061 => 0x501a, 0x5062 => 0x5028, 0x5063 => 0x5014, + 0x5064 => 0x502a, 0x5065 => 0x5025, 0x5066 => 0x5005, 0x5067 => 0x4f1c, + 0x5068 => 0x4ff6, 0x5069 => 0x5021, 0x506a => 0x5029, 0x506b => 0x502c, + 0x506c => 0x4ffe, 0x506d => 0x4fef, 0x506e => 0x5011, 0x506f => 0x5006, + 0x5070 => 0x5043, 0x5071 => 0x5047, 0x5072 => 0x6703, 0x5073 => 0x5055, + 0x5074 => 0x5050, 0x5075 => 0x5048, 0x5076 => 0x505a, 0x5077 => 0x5056, + 0x5078 => 0x506c, 0x5079 => 0x5078, 0x507a => 0x5080, 0x507b => 0x509a, + 0x507c => 0x5085, 0x507d => 0x50b4, 0x507e => 0x50b2, 0x5121 => 0x50c9, + 0x5122 => 0x50ca, 0x5123 => 0x50b3, 0x5124 => 0x50c2, 0x5125 => 0x50d6, + 0x5126 => 0x50de, 0x5127 => 0x50e5, 0x5128 => 0x50ed, 0x5129 => 0x50e3, + 0x512a => 0x50ee, 0x512b => 0x50f9, 0x512c => 0x50f5, 0x512d => 0x5109, + 0x512e => 0x5101, 0x512f => 0x5102, 0x5130 => 0x5116, 0x5131 => 0x5115, + 0x5132 => 0x5114, 0x5133 => 0x511a, 0x5134 => 0x5121, 0x5135 => 0x513a, + 0x5136 => 0x5137, 0x5137 => 0x513c, 0x5138 => 0x513b, 0x5139 => 0x513f, + 0x513a => 0x5140, 0x513b => 0x5152, 0x513c => 0x514c, 0x513d => 0x5154, + 0x513e => 0x5162, 0x513f => 0x7af8, 0x5140 => 0x5169, 0x5141 => 0x516a, + 0x5142 => 0x516e, 0x5143 => 0x5180, 0x5144 => 0x5182, 0x5145 => 0x56d8, + 0x5146 => 0x518c, 0x5147 => 0x5189, 0x5148 => 0x518f, 0x5149 => 0x5191, + 0x514a => 0x5193, 0x514b => 0x5195, 0x514c => 0x5196, 0x514d => 0x51a4, + 0x514e => 0x51a6, 0x514f => 0x51a2, 0x5150 => 0x51a9, 0x5151 => 0x51aa, + 0x5152 => 0x51ab, 0x5153 => 0x51b3, 0x5154 => 0x51b1, 0x5155 => 0x51b2, + 0x5156 => 0x51b0, 0x5157 => 0x51b5, 0x5158 => 0x51bd, 0x5159 => 0x51c5, + 0x515a => 0x51c9, 0x515b => 0x51db, 0x515c => 0x51e0, 0x515d => 0x8655, + 0x515e => 0x51e9, 0x515f => 0x51ed, 0x5160 => 0x51f0, 0x5161 => 0x51f5, + 0x5162 => 0x51fe, 0x5163 => 0x5204, 0x5164 => 0x520b, 0x5165 => 0x5214, + 0x5166 => 0x520e, 0x5167 => 0x5227, 0x5168 => 0x522a, 0x5169 => 0x522e, + 0x516a => 0x5233, 0x516b => 0x5239, 0x516c => 0x524f, 0x516d => 0x5244, + 0x516e => 0x524b, 0x516f => 0x524c, 0x5170 => 0x525e, 0x5171 => 0x5254, + 0x5172 => 0x526a, 0x5173 => 0x5274, 0x5174 => 0x5269, 0x5175 => 0x5273, + 0x5176 => 0x527f, 0x5177 => 0x527d, 0x5178 => 0x528d, 0x5179 => 0x5294, + 0x517a => 0x5292, 0x517b => 0x5271, 0x517c => 0x5288, 0x517d => 0x5291, + 0x517e => 0x8fa8, 0x5221 => 0x8fa7, 0x5222 => 0x52ac, 0x5223 => 0x52ad, + 0x5224 => 0x52bc, 0x5225 => 0x52b5, 0x5226 => 0x52c1, 0x5227 => 0x52cd, + 0x5228 => 0x52d7, 0x5229 => 0x52de, 0x522a => 0x52e3, 0x522b => 0x52e6, + 0x522c => 0x98ed, 0x522d => 0x52e0, 0x522e => 0x52f3, 0x522f => 0x52f5, + 0x5230 => 0x52f8, 0x5231 => 0x52f9, 0x5232 => 0x5306, 0x5233 => 0x5308, + 0x5234 => 0x7538, 0x5235 => 0x530d, 0x5236 => 0x5310, 0x5237 => 0x530f, + 0x5238 => 0x5315, 0x5239 => 0x531a, 0x523a => 0x5323, 0x523b => 0x532f, + 0x523c => 0x5331, 0x523d => 0x5333, 0x523e => 0x5338, 0x523f => 0x5340, + 0x5240 => 0x5346, 0x5241 => 0x5345, 0x5242 => 0x4e17, 0x5243 => 0x5349, + 0x5244 => 0x534d, 0x5245 => 0x51d6, 0x5246 => 0x535e, 0x5247 => 0x5369, + 0x5248 => 0x536e, 0x5249 => 0x5918, 0x524a => 0x537b, 0x524b => 0x5377, + 0x524c => 0x5382, 0x524d => 0x5396, 0x524e => 0x53a0, 0x524f => 0x53a6, + 0x5250 => 0x53a5, 0x5251 => 0x53ae, 0x5252 => 0x53b0, 0x5253 => 0x53b6, + 0x5254 => 0x53c3, 0x5255 => 0x7c12, 0x5256 => 0x96d9, 0x5257 => 0x53df, + 0x5258 => 0x66fc, 0x5259 => 0x71ee, 0x525a => 0x53ee, 0x525b => 0x53e8, + 0x525c => 0x53ed, 0x525d => 0x53fa, 0x525e => 0x5401, 0x525f => 0x543d, + 0x5260 => 0x5440, 0x5261 => 0x542c, 0x5262 => 0x542d, 0x5263 => 0x543c, + 0x5264 => 0x542e, 0x5265 => 0x5436, 0x5266 => 0x5429, 0x5267 => 0x541d, + 0x5268 => 0x544e, 0x5269 => 0x548f, 0x526a => 0x5475, 0x526b => 0x548e, + 0x526c => 0x545f, 0x526d => 0x5471, 0x526e => 0x5477, 0x526f => 0x5470, + 0x5270 => 0x5492, 0x5271 => 0x547b, 0x5272 => 0x5480, 0x5273 => 0x5476, + 0x5274 => 0x5484, 0x5275 => 0x5490, 0x5276 => 0x5486, 0x5277 => 0x54c7, + 0x5278 => 0x54a2, 0x5279 => 0x54b8, 0x527a => 0x54a5, 0x527b => 0x54ac, + 0x527c => 0x54c4, 0x527d => 0x54c8, 0x527e => 0x54a8, 0x5321 => 0x54ab, + 0x5322 => 0x54c2, 0x5323 => 0x54a4, 0x5324 => 0x54be, 0x5325 => 0x54bc, + 0x5326 => 0x54d8, 0x5327 => 0x54e5, 0x5328 => 0x54e6, 0x5329 => 0x550f, + 0x532a => 0x5514, 0x532b => 0x54fd, 0x532c => 0x54ee, 0x532d => 0x54ed, + 0x532e => 0x54fa, 0x532f => 0x54e2, 0x5330 => 0x5539, 0x5331 => 0x5540, + 0x5332 => 0x5563, 0x5333 => 0x554c, 0x5334 => 0x552e, 0x5335 => 0x555c, + 0x5336 => 0x5545, 0x5337 => 0x5556, 0x5338 => 0x5557, 0x5339 => 0x5538, + 0x533a => 0x5533, 0x533b => 0x555d, 0x533c => 0x5599, 0x533d => 0x5580, + 0x533e => 0x54af, 0x533f => 0x558a, 0x5340 => 0x559f, 0x5341 => 0x557b, + 0x5342 => 0x557e, 0x5343 => 0x5598, 0x5344 => 0x559e, 0x5345 => 0x55ae, + 0x5346 => 0x557c, 0x5347 => 0x5583, 0x5348 => 0x55a9, 0x5349 => 0x5587, + 0x534a => 0x55a8, 0x534b => 0x55da, 0x534c => 0x55c5, 0x534d => 0x55df, + 0x534e => 0x55c4, 0x534f => 0x55dc, 0x5350 => 0x55e4, 0x5351 => 0x55d4, + 0x5352 => 0x5614, 0x5353 => 0x55f7, 0x5354 => 0x5616, 0x5355 => 0x55fe, + 0x5356 => 0x55fd, 0x5357 => 0x561b, 0x5358 => 0x55f9, 0x5359 => 0x564e, + 0x535a => 0x5650, 0x535b => 0x71df, 0x535c => 0x5634, 0x535d => 0x5636, + 0x535e => 0x5632, 0x535f => 0x5638, 0x5360 => 0x566b, 0x5361 => 0x5664, + 0x5362 => 0x562f, 0x5363 => 0x566c, 0x5364 => 0x566a, 0x5365 => 0x5686, + 0x5366 => 0x5680, 0x5367 => 0x568a, 0x5368 => 0x56a0, 0x5369 => 0x5694, + 0x536a => 0x568f, 0x536b => 0x56a5, 0x536c => 0x56ae, 0x536d => 0x56b6, + 0x536e => 0x56b4, 0x536f => 0x56c2, 0x5370 => 0x56bc, 0x5371 => 0x56c1, + 0x5372 => 0x56c3, 0x5373 => 0x56c0, 0x5374 => 0x56c8, 0x5375 => 0x56ce, + 0x5376 => 0x56d1, 0x5377 => 0x56d3, 0x5378 => 0x56d7, 0x5379 => 0x56ee, + 0x537a => 0x56f9, 0x537b => 0x5700, 0x537c => 0x56ff, 0x537d => 0x5704, + 0x537e => 0x5709, 0x5421 => 0x5708, 0x5422 => 0x570b, 0x5423 => 0x570d, + 0x5424 => 0x5713, 0x5425 => 0x5718, 0x5426 => 0x5716, 0x5427 => 0x55c7, + 0x5428 => 0x571c, 0x5429 => 0x5726, 0x542a => 0x5737, 0x542b => 0x5738, + 0x542c => 0x574e, 0x542d => 0x573b, 0x542e => 0x5740, 0x542f => 0x574f, + 0x5430 => 0x5769, 0x5431 => 0x57c0, 0x5432 => 0x5788, 0x5433 => 0x5761, + 0x5434 => 0x577f, 0x5435 => 0x5789, 0x5436 => 0x5793, 0x5437 => 0x57a0, + 0x5438 => 0x57b3, 0x5439 => 0x57a4, 0x543a => 0x57aa, 0x543b => 0x57b0, + 0x543c => 0x57c3, 0x543d => 0x57c6, 0x543e => 0x57d4, 0x543f => 0x57d2, + 0x5440 => 0x57d3, 0x5441 => 0x580a, 0x5442 => 0x57d6, 0x5443 => 0x57e3, + 0x5444 => 0x580b, 0x5445 => 0x5819, 0x5446 => 0x581d, 0x5447 => 0x5872, + 0x5448 => 0x5821, 0x5449 => 0x5862, 0x544a => 0x584b, 0x544b => 0x5870, + 0x544c => 0x6bc0, 0x544d => 0x5852, 0x544e => 0x583d, 0x544f => 0x5879, + 0x5450 => 0x5885, 0x5451 => 0x58b9, 0x5452 => 0x589f, 0x5453 => 0x58ab, + 0x5454 => 0x58ba, 0x5455 => 0x58de, 0x5456 => 0x58bb, 0x5457 => 0x58b8, + 0x5458 => 0x58ae, 0x5459 => 0x58c5, 0x545a => 0x58d3, 0x545b => 0x58d1, + 0x545c => 0x58d7, 0x545d => 0x58d9, 0x545e => 0x58d8, 0x545f => 0x58e5, + 0x5460 => 0x58dc, 0x5461 => 0x58e4, 0x5462 => 0x58df, 0x5463 => 0x58ef, + 0x5464 => 0x58fa, 0x5465 => 0x58f9, 0x5466 => 0x58fb, 0x5467 => 0x58fc, + 0x5468 => 0x58fd, 0x5469 => 0x5902, 0x546a => 0x590a, 0x546b => 0x5910, + 0x546c => 0x591b, 0x546d => 0x68a6, 0x546e => 0x5925, 0x546f => 0x592c, + 0x5470 => 0x592d, 0x5471 => 0x5932, 0x5472 => 0x5938, 0x5473 => 0x593e, + 0x5474 => 0x7ad2, 0x5475 => 0x5955, 0x5476 => 0x5950, 0x5477 => 0x594e, + 0x5478 => 0x595a, 0x5479 => 0x5958, 0x547a => 0x5962, 0x547b => 0x5960, + 0x547c => 0x5967, 0x547d => 0x596c, 0x547e => 0x5969, 0x5521 => 0x5978, + 0x5522 => 0x5981, 0x5523 => 0x599d, 0x5524 => 0x4f5e, 0x5525 => 0x4fab, + 0x5526 => 0x59a3, 0x5527 => 0x59b2, 0x5528 => 0x59c6, 0x5529 => 0x59e8, + 0x552a => 0x59dc, 0x552b => 0x598d, 0x552c => 0x59d9, 0x552d => 0x59da, + 0x552e => 0x5a25, 0x552f => 0x5a1f, 0x5530 => 0x5a11, 0x5531 => 0x5a1c, + 0x5532 => 0x5a09, 0x5533 => 0x5a1a, 0x5534 => 0x5a40, 0x5535 => 0x5a6c, + 0x5536 => 0x5a49, 0x5537 => 0x5a35, 0x5538 => 0x5a36, 0x5539 => 0x5a62, + 0x553a => 0x5a6a, 0x553b => 0x5a9a, 0x553c => 0x5abc, 0x553d => 0x5abe, + 0x553e => 0x5acb, 0x553f => 0x5ac2, 0x5540 => 0x5abd, 0x5541 => 0x5ae3, + 0x5542 => 0x5ad7, 0x5543 => 0x5ae6, 0x5544 => 0x5ae9, 0x5545 => 0x5ad6, + 0x5546 => 0x5afa, 0x5547 => 0x5afb, 0x5548 => 0x5b0c, 0x5549 => 0x5b0b, + 0x554a => 0x5b16, 0x554b => 0x5b32, 0x554c => 0x5ad0, 0x554d => 0x5b2a, + 0x554e => 0x5b36, 0x554f => 0x5b3e, 0x5550 => 0x5b43, 0x5551 => 0x5b45, + 0x5552 => 0x5b40, 0x5553 => 0x5b51, 0x5554 => 0x5b55, 0x5555 => 0x5b5a, + 0x5556 => 0x5b5b, 0x5557 => 0x5b65, 0x5558 => 0x5b69, 0x5559 => 0x5b70, + 0x555a => 0x5b73, 0x555b => 0x5b75, 0x555c => 0x5b78, 0x555d => 0x6588, + 0x555e => 0x5b7a, 0x555f => 0x5b80, 0x5560 => 0x5b83, 0x5561 => 0x5ba6, + 0x5562 => 0x5bb8, 0x5563 => 0x5bc3, 0x5564 => 0x5bc7, 0x5565 => 0x5bc9, + 0x5566 => 0x5bd4, 0x5567 => 0x5bd0, 0x5568 => 0x5be4, 0x5569 => 0x5be6, + 0x556a => 0x5be2, 0x556b => 0x5bde, 0x556c => 0x5be5, 0x556d => 0x5beb, + 0x556e => 0x5bf0, 0x556f => 0x5bf6, 0x5570 => 0x5bf3, 0x5571 => 0x5c05, + 0x5572 => 0x5c07, 0x5573 => 0x5c08, 0x5574 => 0x5c0d, 0x5575 => 0x5c13, + 0x5576 => 0x5c20, 0x5577 => 0x5c22, 0x5578 => 0x5c28, 0x5579 => 0x5c38, + 0x557a => 0x5c39, 0x557b => 0x5c41, 0x557c => 0x5c46, 0x557d => 0x5c4e, + 0x557e => 0x5c53, 0x5621 => 0x5c50, 0x5622 => 0x5c4f, 0x5623 => 0x5b71, + 0x5624 => 0x5c6c, 0x5625 => 0x5c6e, 0x5626 => 0x4e62, 0x5627 => 0x5c76, + 0x5628 => 0x5c79, 0x5629 => 0x5c8c, 0x562a => 0x5c91, 0x562b => 0x5c94, + 0x562c => 0x599b, 0x562d => 0x5cab, 0x562e => 0x5cbb, 0x562f => 0x5cb6, + 0x5630 => 0x5cbc, 0x5631 => 0x5cb7, 0x5632 => 0x5cc5, 0x5633 => 0x5cbe, + 0x5634 => 0x5cc7, 0x5635 => 0x5cd9, 0x5636 => 0x5ce9, 0x5637 => 0x5cfd, + 0x5638 => 0x5cfa, 0x5639 => 0x5ced, 0x563a => 0x5d8c, 0x563b => 0x5cea, + 0x563c => 0x5d0b, 0x563d => 0x5d15, 0x563e => 0x5d17, 0x563f => 0x5d5c, + 0x5640 => 0x5d1f, 0x5641 => 0x5d1b, 0x5642 => 0x5d11, 0x5643 => 0x5d14, + 0x5644 => 0x5d22, 0x5645 => 0x5d1a, 0x5646 => 0x5d19, 0x5647 => 0x5d18, + 0x5648 => 0x5d4c, 0x5649 => 0x5d52, 0x564a => 0x5d4e, 0x564b => 0x5d4b, + 0x564c => 0x5d6c, 0x564d => 0x5d73, 0x564e => 0x5d76, 0x564f => 0x5d87, + 0x5650 => 0x5d84, 0x5651 => 0x5d82, 0x5652 => 0x5da2, 0x5653 => 0x5d9d, + 0x5654 => 0x5dac, 0x5655 => 0x5dae, 0x5656 => 0x5dbd, 0x5657 => 0x5d90, + 0x5658 => 0x5db7, 0x5659 => 0x5dbc, 0x565a => 0x5dc9, 0x565b => 0x5dcd, + 0x565c => 0x5dd3, 0x565d => 0x5dd2, 0x565e => 0x5dd6, 0x565f => 0x5ddb, + 0x5660 => 0x5deb, 0x5661 => 0x5df2, 0x5662 => 0x5df5, 0x5663 => 0x5e0b, + 0x5664 => 0x5e1a, 0x5665 => 0x5e19, 0x5666 => 0x5e11, 0x5667 => 0x5e1b, + 0x5668 => 0x5e36, 0x5669 => 0x5e37, 0x566a => 0x5e44, 0x566b => 0x5e43, + 0x566c => 0x5e40, 0x566d => 0x5e4e, 0x566e => 0x5e57, 0x566f => 0x5e54, + 0x5670 => 0x5e5f, 0x5671 => 0x5e62, 0x5672 => 0x5e64, 0x5673 => 0x5e47, + 0x5674 => 0x5e75, 0x5675 => 0x5e76, 0x5676 => 0x5e7a, 0x5677 => 0x9ebc, + 0x5678 => 0x5e7f, 0x5679 => 0x5ea0, 0x567a => 0x5ec1, 0x567b => 0x5ec2, + 0x567c => 0x5ec8, 0x567d => 0x5ed0, 0x567e => 0x5ecf, 0x5721 => 0x5ed6, + 0x5722 => 0x5ee3, 0x5723 => 0x5edd, 0x5724 => 0x5eda, 0x5725 => 0x5edb, + 0x5726 => 0x5ee2, 0x5727 => 0x5ee1, 0x5728 => 0x5ee8, 0x5729 => 0x5ee9, + 0x572a => 0x5eec, 0x572b => 0x5ef1, 0x572c => 0x5ef3, 0x572d => 0x5ef0, + 0x572e => 0x5ef4, 0x572f => 0x5ef8, 0x5730 => 0x5efe, 0x5731 => 0x5f03, + 0x5732 => 0x5f09, 0x5733 => 0x5f5d, 0x5734 => 0x5f5c, 0x5735 => 0x5f0b, + 0x5736 => 0x5f11, 0x5737 => 0x5f16, 0x5738 => 0x5f29, 0x5739 => 0x5f2d, + 0x573a => 0x5f38, 0x573b => 0x5f41, 0x573c => 0x5f48, 0x573d => 0x5f4c, + 0x573e => 0x5f4e, 0x573f => 0x5f2f, 0x5740 => 0x5f51, 0x5741 => 0x5f56, + 0x5742 => 0x5f57, 0x5743 => 0x5f59, 0x5744 => 0x5f61, 0x5745 => 0x5f6d, + 0x5746 => 0x5f73, 0x5747 => 0x5f77, 0x5748 => 0x5f83, 0x5749 => 0x5f82, + 0x574a => 0x5f7f, 0x574b => 0x5f8a, 0x574c => 0x5f88, 0x574d => 0x5f91, + 0x574e => 0x5f87, 0x574f => 0x5f9e, 0x5750 => 0x5f99, 0x5751 => 0x5f98, + 0x5752 => 0x5fa0, 0x5753 => 0x5fa8, 0x5754 => 0x5fad, 0x5755 => 0x5fbc, + 0x5756 => 0x5fd6, 0x5757 => 0x5ffb, 0x5758 => 0x5fe4, 0x5759 => 0x5ff8, + 0x575a => 0x5ff1, 0x575b => 0x5fdd, 0x575c => 0x60b3, 0x575d => 0x5fff, + 0x575e => 0x6021, 0x575f => 0x6060, 0x5760 => 0x6019, 0x5761 => 0x6010, + 0x5762 => 0x6029, 0x5763 => 0x600e, 0x5764 => 0x6031, 0x5765 => 0x601b, + 0x5766 => 0x6015, 0x5767 => 0x602b, 0x5768 => 0x6026, 0x5769 => 0x600f, + 0x576a => 0x603a, 0x576b => 0x605a, 0x576c => 0x6041, 0x576d => 0x606a, + 0x576e => 0x6077, 0x576f => 0x605f, 0x5770 => 0x604a, 0x5771 => 0x6046, + 0x5772 => 0x604d, 0x5773 => 0x6063, 0x5774 => 0x6043, 0x5775 => 0x6064, + 0x5776 => 0x6042, 0x5777 => 0x606c, 0x5778 => 0x606b, 0x5779 => 0x6059, + 0x577a => 0x6081, 0x577b => 0x608d, 0x577c => 0x60e7, 0x577d => 0x6083, + 0x577e => 0x609a, 0x5821 => 0x6084, 0x5822 => 0x609b, 0x5823 => 0x6096, + 0x5824 => 0x6097, 0x5825 => 0x6092, 0x5826 => 0x60a7, 0x5827 => 0x608b, + 0x5828 => 0x60e1, 0x5829 => 0x60b8, 0x582a => 0x60e0, 0x582b => 0x60d3, + 0x582c => 0x60b4, 0x582d => 0x5ff0, 0x582e => 0x60bd, 0x582f => 0x60c6, + 0x5830 => 0x60b5, 0x5831 => 0x60d8, 0x5832 => 0x614d, 0x5833 => 0x6115, + 0x5834 => 0x6106, 0x5835 => 0x60f6, 0x5836 => 0x60f7, 0x5837 => 0x6100, + 0x5838 => 0x60f4, 0x5839 => 0x60fa, 0x583a => 0x6103, 0x583b => 0x6121, + 0x583c => 0x60fb, 0x583d => 0x60f1, 0x583e => 0x610d, 0x583f => 0x610e, + 0x5840 => 0x6147, 0x5841 => 0x613e, 0x5842 => 0x6128, 0x5843 => 0x6127, + 0x5844 => 0x614a, 0x5845 => 0x613f, 0x5846 => 0x613c, 0x5847 => 0x612c, + 0x5848 => 0x6134, 0x5849 => 0x613d, 0x584a => 0x6142, 0x584b => 0x6144, + 0x584c => 0x6173, 0x584d => 0x6177, 0x584e => 0x6158, 0x584f => 0x6159, + 0x5850 => 0x615a, 0x5851 => 0x616b, 0x5852 => 0x6174, 0x5853 => 0x616f, + 0x5854 => 0x6165, 0x5855 => 0x6171, 0x5856 => 0x615f, 0x5857 => 0x615d, + 0x5858 => 0x6153, 0x5859 => 0x6175, 0x585a => 0x6199, 0x585b => 0x6196, + 0x585c => 0x6187, 0x585d => 0x61ac, 0x585e => 0x6194, 0x585f => 0x619a, + 0x5860 => 0x618a, 0x5861 => 0x6191, 0x5862 => 0x61ab, 0x5863 => 0x61ae, + 0x5864 => 0x61cc, 0x5865 => 0x61ca, 0x5866 => 0x61c9, 0x5867 => 0x61f7, + 0x5868 => 0x61c8, 0x5869 => 0x61c3, 0x586a => 0x61c6, 0x586b => 0x61ba, + 0x586c => 0x61cb, 0x586d => 0x7f79, 0x586e => 0x61cd, 0x586f => 0x61e6, + 0x5870 => 0x61e3, 0x5871 => 0x61f6, 0x5872 => 0x61fa, 0x5873 => 0x61f4, + 0x5874 => 0x61ff, 0x5875 => 0x61fd, 0x5876 => 0x61fc, 0x5877 => 0x61fe, + 0x5878 => 0x6200, 0x5879 => 0x6208, 0x587a => 0x6209, 0x587b => 0x620d, + 0x587c => 0x620c, 0x587d => 0x6214, 0x587e => 0x621b, 0x5921 => 0x621e, + 0x5922 => 0x6221, 0x5923 => 0x622a, 0x5924 => 0x622e, 0x5925 => 0x6230, + 0x5926 => 0x6232, 0x5927 => 0x6233, 0x5928 => 0x6241, 0x5929 => 0x624e, + 0x592a => 0x625e, 0x592b => 0x6263, 0x592c => 0x625b, 0x592d => 0x6260, + 0x592e => 0x6268, 0x592f => 0x627c, 0x5930 => 0x6282, 0x5931 => 0x6289, + 0x5932 => 0x627e, 0x5933 => 0x6292, 0x5934 => 0x6293, 0x5935 => 0x6296, + 0x5936 => 0x62d4, 0x5937 => 0x6283, 0x5938 => 0x6294, 0x5939 => 0x62d7, + 0x593a => 0x62d1, 0x593b => 0x62bb, 0x593c => 0x62cf, 0x593d => 0x62ff, + 0x593e => 0x62c6, 0x593f => 0x64d4, 0x5940 => 0x62c8, 0x5941 => 0x62dc, + 0x5942 => 0x62cc, 0x5943 => 0x62ca, 0x5944 => 0x62c2, 0x5945 => 0x62c7, + 0x5946 => 0x629b, 0x5947 => 0x62c9, 0x5948 => 0x630c, 0x5949 => 0x62ee, + 0x594a => 0x62f1, 0x594b => 0x6327, 0x594c => 0x6302, 0x594d => 0x6308, + 0x594e => 0x62ef, 0x594f => 0x62f5, 0x5950 => 0x6350, 0x5951 => 0x633e, + 0x5952 => 0x634d, 0x5953 => 0x641c, 0x5954 => 0x634f, 0x5955 => 0x6396, + 0x5956 => 0x638e, 0x5957 => 0x6380, 0x5958 => 0x63ab, 0x5959 => 0x6376, + 0x595a => 0x63a3, 0x595b => 0x638f, 0x595c => 0x6389, 0x595d => 0x639f, + 0x595e => 0x63b5, 0x595f => 0x636b, 0x5960 => 0x6369, 0x5961 => 0x63be, + 0x5962 => 0x63e9, 0x5963 => 0x63c0, 0x5964 => 0x63c6, 0x5965 => 0x63e3, + 0x5966 => 0x63c9, 0x5967 => 0x63d2, 0x5968 => 0x63f6, 0x5969 => 0x63c4, + 0x596a => 0x6416, 0x596b => 0x6434, 0x596c => 0x6406, 0x596d => 0x6413, + 0x596e => 0x6426, 0x596f => 0x6436, 0x5970 => 0x651d, 0x5971 => 0x6417, + 0x5972 => 0x6428, 0x5973 => 0x640f, 0x5974 => 0x6467, 0x5975 => 0x646f, + 0x5976 => 0x6476, 0x5977 => 0x644e, 0x5978 => 0x652a, 0x5979 => 0x6495, + 0x597a => 0x6493, 0x597b => 0x64a5, 0x597c => 0x64a9, 0x597d => 0x6488, + 0x597e => 0x64bc, 0x5a21 => 0x64da, 0x5a22 => 0x64d2, 0x5a23 => 0x64c5, + 0x5a24 => 0x64c7, 0x5a25 => 0x64bb, 0x5a26 => 0x64d8, 0x5a27 => 0x64c2, + 0x5a28 => 0x64f1, 0x5a29 => 0x64e7, 0x5a2a => 0x8209, 0x5a2b => 0x64e0, + 0x5a2c => 0x64e1, 0x5a2d => 0x62ac, 0x5a2e => 0x64e3, 0x5a2f => 0x64ef, + 0x5a30 => 0x652c, 0x5a31 => 0x64f6, 0x5a32 => 0x64f4, 0x5a33 => 0x64f2, + 0x5a34 => 0x64fa, 0x5a35 => 0x6500, 0x5a36 => 0x64fd, 0x5a37 => 0x6518, + 0x5a38 => 0x651c, 0x5a39 => 0x6505, 0x5a3a => 0x6524, 0x5a3b => 0x6523, + 0x5a3c => 0x652b, 0x5a3d => 0x6534, 0x5a3e => 0x6535, 0x5a3f => 0x6537, + 0x5a40 => 0x6536, 0x5a41 => 0x6538, 0x5a42 => 0x754b, 0x5a43 => 0x6548, + 0x5a44 => 0x6556, 0x5a45 => 0x6555, 0x5a46 => 0x654d, 0x5a47 => 0x6558, + 0x5a48 => 0x655e, 0x5a49 => 0x655d, 0x5a4a => 0x6572, 0x5a4b => 0x6578, + 0x5a4c => 0x6582, 0x5a4d => 0x6583, 0x5a4e => 0x8b8a, 0x5a4f => 0x659b, + 0x5a50 => 0x659f, 0x5a51 => 0x65ab, 0x5a52 => 0x65b7, 0x5a53 => 0x65c3, + 0x5a54 => 0x65c6, 0x5a55 => 0x65c1, 0x5a56 => 0x65c4, 0x5a57 => 0x65cc, + 0x5a58 => 0x65d2, 0x5a59 => 0x65db, 0x5a5a => 0x65d9, 0x5a5b => 0x65e0, + 0x5a5c => 0x65e1, 0x5a5d => 0x65f1, 0x5a5e => 0x6772, 0x5a5f => 0x660a, + 0x5a60 => 0x6603, 0x5a61 => 0x65fb, 0x5a62 => 0x6773, 0x5a63 => 0x6635, + 0x5a64 => 0x6636, 0x5a65 => 0x6634, 0x5a66 => 0x661c, 0x5a67 => 0x664f, + 0x5a68 => 0x6644, 0x5a69 => 0x6649, 0x5a6a => 0x6641, 0x5a6b => 0x665e, + 0x5a6c => 0x665d, 0x5a6d => 0x6664, 0x5a6e => 0x6667, 0x5a6f => 0x6668, + 0x5a70 => 0x665f, 0x5a71 => 0x6662, 0x5a72 => 0x6670, 0x5a73 => 0x6683, + 0x5a74 => 0x6688, 0x5a75 => 0x668e, 0x5a76 => 0x6689, 0x5a77 => 0x6684, + 0x5a78 => 0x6698, 0x5a79 => 0x669d, 0x5a7a => 0x66c1, 0x5a7b => 0x66b9, + 0x5a7c => 0x66c9, 0x5a7d => 0x66be, 0x5a7e => 0x66bc, 0x5b21 => 0x66c4, + 0x5b22 => 0x66b8, 0x5b23 => 0x66d6, 0x5b24 => 0x66da, 0x5b25 => 0x66e0, + 0x5b26 => 0x663f, 0x5b27 => 0x66e6, 0x5b28 => 0x66e9, 0x5b29 => 0x66f0, + 0x5b2a => 0x66f5, 0x5b2b => 0x66f7, 0x5b2c => 0x670f, 0x5b2d => 0x6716, + 0x5b2e => 0x671e, 0x5b2f => 0x6726, 0x5b30 => 0x6727, 0x5b31 => 0x9738, + 0x5b32 => 0x672e, 0x5b33 => 0x673f, 0x5b34 => 0x6736, 0x5b35 => 0x6741, + 0x5b36 => 0x6738, 0x5b37 => 0x6737, 0x5b38 => 0x6746, 0x5b39 => 0x675e, + 0x5b3a => 0x6760, 0x5b3b => 0x6759, 0x5b3c => 0x6763, 0x5b3d => 0x6764, + 0x5b3e => 0x6789, 0x5b3f => 0x6770, 0x5b40 => 0x67a9, 0x5b41 => 0x677c, + 0x5b42 => 0x676a, 0x5b43 => 0x678c, 0x5b44 => 0x678b, 0x5b45 => 0x67a6, + 0x5b46 => 0x67a1, 0x5b47 => 0x6785, 0x5b48 => 0x67b7, 0x5b49 => 0x67ef, + 0x5b4a => 0x67b4, 0x5b4b => 0x67ec, 0x5b4c => 0x67b3, 0x5b4d => 0x67e9, + 0x5b4e => 0x67b8, 0x5b4f => 0x67e4, 0x5b50 => 0x67de, 0x5b51 => 0x67dd, + 0x5b52 => 0x67e2, 0x5b53 => 0x67ee, 0x5b54 => 0x67b9, 0x5b55 => 0x67ce, + 0x5b56 => 0x67c6, 0x5b57 => 0x67e7, 0x5b58 => 0x6a9c, 0x5b59 => 0x681e, + 0x5b5a => 0x6846, 0x5b5b => 0x6829, 0x5b5c => 0x6840, 0x5b5d => 0x684d, + 0x5b5e => 0x6832, 0x5b5f => 0x684e, 0x5b60 => 0x68b3, 0x5b61 => 0x682b, + 0x5b62 => 0x6859, 0x5b63 => 0x6863, 0x5b64 => 0x6877, 0x5b65 => 0x687f, + 0x5b66 => 0x689f, 0x5b67 => 0x688f, 0x5b68 => 0x68ad, 0x5b69 => 0x6894, + 0x5b6a => 0x689d, 0x5b6b => 0x689b, 0x5b6c => 0x6883, 0x5b6d => 0x6aae, + 0x5b6e => 0x68b9, 0x5b6f => 0x6874, 0x5b70 => 0x68b5, 0x5b71 => 0x68a0, + 0x5b72 => 0x68ba, 0x5b73 => 0x690f, 0x5b74 => 0x688d, 0x5b75 => 0x687e, + 0x5b76 => 0x6901, 0x5b77 => 0x68ca, 0x5b78 => 0x6908, 0x5b79 => 0x68d8, + 0x5b7a => 0x6922, 0x5b7b => 0x6926, 0x5b7c => 0x68e1, 0x5b7d => 0x690c, + 0x5b7e => 0x68cd, 0x5c21 => 0x68d4, 0x5c22 => 0x68e7, 0x5c23 => 0x68d5, + 0x5c24 => 0x6936, 0x5c25 => 0x6912, 0x5c26 => 0x6904, 0x5c27 => 0x68d7, + 0x5c28 => 0x68e3, 0x5c29 => 0x6925, 0x5c2a => 0x68f9, 0x5c2b => 0x68e0, + 0x5c2c => 0x68ef, 0x5c2d => 0x6928, 0x5c2e => 0x692a, 0x5c2f => 0x691a, + 0x5c30 => 0x6923, 0x5c31 => 0x6921, 0x5c32 => 0x68c6, 0x5c33 => 0x6979, + 0x5c34 => 0x6977, 0x5c35 => 0x695c, 0x5c36 => 0x6978, 0x5c37 => 0x696b, + 0x5c38 => 0x6954, 0x5c39 => 0x697e, 0x5c3a => 0x696e, 0x5c3b => 0x6939, + 0x5c3c => 0x6974, 0x5c3d => 0x693d, 0x5c3e => 0x6959, 0x5c3f => 0x6930, + 0x5c40 => 0x6961, 0x5c41 => 0x695e, 0x5c42 => 0x695d, 0x5c43 => 0x6981, + 0x5c44 => 0x696a, 0x5c45 => 0x69b2, 0x5c46 => 0x69ae, 0x5c47 => 0x69d0, + 0x5c48 => 0x69bf, 0x5c49 => 0x69c1, 0x5c4a => 0x69d3, 0x5c4b => 0x69be, + 0x5c4c => 0x69ce, 0x5c4d => 0x5be8, 0x5c4e => 0x69ca, 0x5c4f => 0x69dd, + 0x5c50 => 0x69bb, 0x5c51 => 0x69c3, 0x5c52 => 0x69a7, 0x5c53 => 0x6a2e, + 0x5c54 => 0x6991, 0x5c55 => 0x69a0, 0x5c56 => 0x699c, 0x5c57 => 0x6995, + 0x5c58 => 0x69b4, 0x5c59 => 0x69de, 0x5c5a => 0x69e8, 0x5c5b => 0x6a02, + 0x5c5c => 0x6a1b, 0x5c5d => 0x69ff, 0x5c5e => 0x6b0a, 0x5c5f => 0x69f9, + 0x5c60 => 0x69f2, 0x5c61 => 0x69e7, 0x5c62 => 0x6a05, 0x5c63 => 0x69b1, + 0x5c64 => 0x6a1e, 0x5c65 => 0x69ed, 0x5c66 => 0x6a14, 0x5c67 => 0x69eb, + 0x5c68 => 0x6a0a, 0x5c69 => 0x6a12, 0x5c6a => 0x6ac1, 0x5c6b => 0x6a23, + 0x5c6c => 0x6a13, 0x5c6d => 0x6a44, 0x5c6e => 0x6a0c, 0x5c6f => 0x6a72, + 0x5c70 => 0x6a36, 0x5c71 => 0x6a78, 0x5c72 => 0x6a47, 0x5c73 => 0x6a62, + 0x5c74 => 0x6a59, 0x5c75 => 0x6a66, 0x5c76 => 0x6a48, 0x5c77 => 0x6a38, + 0x5c78 => 0x6a22, 0x5c79 => 0x6a90, 0x5c7a => 0x6a8d, 0x5c7b => 0x6aa0, + 0x5c7c => 0x6a84, 0x5c7d => 0x6aa2, 0x5c7e => 0x6aa3, 0x5d21 => 0x6a97, + 0x5d22 => 0x8617, 0x5d23 => 0x6abb, 0x5d24 => 0x6ac3, 0x5d25 => 0x6ac2, + 0x5d26 => 0x6ab8, 0x5d27 => 0x6ab3, 0x5d28 => 0x6aac, 0x5d29 => 0x6ade, + 0x5d2a => 0x6ad1, 0x5d2b => 0x6adf, 0x5d2c => 0x6aaa, 0x5d2d => 0x6ada, + 0x5d2e => 0x6aea, 0x5d2f => 0x6afb, 0x5d30 => 0x6b05, 0x5d31 => 0x8616, + 0x5d32 => 0x6afa, 0x5d33 => 0x6b12, 0x5d34 => 0x6b16, 0x5d35 => 0x9b31, + 0x5d36 => 0x6b1f, 0x5d37 => 0x6b38, 0x5d38 => 0x6b37, 0x5d39 => 0x76dc, + 0x5d3a => 0x6b39, 0x5d3b => 0x98ee, 0x5d3c => 0x6b47, 0x5d3d => 0x6b43, + 0x5d3e => 0x6b49, 0x5d3f => 0x6b50, 0x5d40 => 0x6b59, 0x5d41 => 0x6b54, + 0x5d42 => 0x6b5b, 0x5d43 => 0x6b5f, 0x5d44 => 0x6b61, 0x5d45 => 0x6b78, + 0x5d46 => 0x6b79, 0x5d47 => 0x6b7f, 0x5d48 => 0x6b80, 0x5d49 => 0x6b84, + 0x5d4a => 0x6b83, 0x5d4b => 0x6b8d, 0x5d4c => 0x6b98, 0x5d4d => 0x6b95, + 0x5d4e => 0x6b9e, 0x5d4f => 0x6ba4, 0x5d50 => 0x6baa, 0x5d51 => 0x6bab, + 0x5d52 => 0x6baf, 0x5d53 => 0x6bb2, 0x5d54 => 0x6bb1, 0x5d55 => 0x6bb3, + 0x5d56 => 0x6bb7, 0x5d57 => 0x6bbc, 0x5d58 => 0x6bc6, 0x5d59 => 0x6bcb, + 0x5d5a => 0x6bd3, 0x5d5b => 0x6bdf, 0x5d5c => 0x6bec, 0x5d5d => 0x6beb, + 0x5d5e => 0x6bf3, 0x5d5f => 0x6bef, 0x5d60 => 0x9ebe, 0x5d61 => 0x6c08, + 0x5d62 => 0x6c13, 0x5d63 => 0x6c14, 0x5d64 => 0x6c1b, 0x5d65 => 0x6c24, + 0x5d66 => 0x6c23, 0x5d67 => 0x6c5e, 0x5d68 => 0x6c55, 0x5d69 => 0x6c62, + 0x5d6a => 0x6c6a, 0x5d6b => 0x6c82, 0x5d6c => 0x6c8d, 0x5d6d => 0x6c9a, + 0x5d6e => 0x6c81, 0x5d6f => 0x6c9b, 0x5d70 => 0x6c7e, 0x5d71 => 0x6c68, + 0x5d72 => 0x6c73, 0x5d73 => 0x6c92, 0x5d74 => 0x6c90, 0x5d75 => 0x6cc4, + 0x5d76 => 0x6cf1, 0x5d77 => 0x6cd3, 0x5d78 => 0x6cbd, 0x5d79 => 0x6cd7, + 0x5d7a => 0x6cc5, 0x5d7b => 0x6cdd, 0x5d7c => 0x6cae, 0x5d7d => 0x6cb1, + 0x5d7e => 0x6cbe, 0x5e21 => 0x6cba, 0x5e22 => 0x6cdb, 0x5e23 => 0x6cef, + 0x5e24 => 0x6cd9, 0x5e25 => 0x6cea, 0x5e26 => 0x6d1f, 0x5e27 => 0x884d, + 0x5e28 => 0x6d36, 0x5e29 => 0x6d2b, 0x5e2a => 0x6d3d, 0x5e2b => 0x6d38, + 0x5e2c => 0x6d19, 0x5e2d => 0x6d35, 0x5e2e => 0x6d33, 0x5e2f => 0x6d12, + 0x5e30 => 0x6d0c, 0x5e31 => 0x6d63, 0x5e32 => 0x6d93, 0x5e33 => 0x6d64, + 0x5e34 => 0x6d5a, 0x5e35 => 0x6d79, 0x5e36 => 0x6d59, 0x5e37 => 0x6d8e, + 0x5e38 => 0x6d95, 0x5e39 => 0x6fe4, 0x5e3a => 0x6d85, 0x5e3b => 0x6df9, + 0x5e3c => 0x6e15, 0x5e3d => 0x6e0a, 0x5e3e => 0x6db5, 0x5e3f => 0x6dc7, + 0x5e40 => 0x6de6, 0x5e41 => 0x6db8, 0x5e42 => 0x6dc6, 0x5e43 => 0x6dec, + 0x5e44 => 0x6dde, 0x5e45 => 0x6dcc, 0x5e46 => 0x6de8, 0x5e47 => 0x6dd2, + 0x5e48 => 0x6dc5, 0x5e49 => 0x6dfa, 0x5e4a => 0x6dd9, 0x5e4b => 0x6de4, + 0x5e4c => 0x6dd5, 0x5e4d => 0x6dea, 0x5e4e => 0x6dee, 0x5e4f => 0x6e2d, + 0x5e50 => 0x6e6e, 0x5e51 => 0x6e2e, 0x5e52 => 0x6e19, 0x5e53 => 0x6e72, + 0x5e54 => 0x6e5f, 0x5e55 => 0x6e3e, 0x5e56 => 0x6e23, 0x5e57 => 0x6e6b, + 0x5e58 => 0x6e2b, 0x5e59 => 0x6e76, 0x5e5a => 0x6e4d, 0x5e5b => 0x6e1f, + 0x5e5c => 0x6e43, 0x5e5d => 0x6e3a, 0x5e5e => 0x6e4e, 0x5e5f => 0x6e24, + 0x5e60 => 0x6eff, 0x5e61 => 0x6e1d, 0x5e62 => 0x6e38, 0x5e63 => 0x6e82, + 0x5e64 => 0x6eaa, 0x5e65 => 0x6e98, 0x5e66 => 0x6ec9, 0x5e67 => 0x6eb7, + 0x5e68 => 0x6ed3, 0x5e69 => 0x6ebd, 0x5e6a => 0x6eaf, 0x5e6b => 0x6ec4, + 0x5e6c => 0x6eb2, 0x5e6d => 0x6ed4, 0x5e6e => 0x6ed5, 0x5e6f => 0x6e8f, + 0x5e70 => 0x6ea5, 0x5e71 => 0x6ec2, 0x5e72 => 0x6e9f, 0x5e73 => 0x6f41, + 0x5e74 => 0x6f11, 0x5e75 => 0x704c, 0x5e76 => 0x6eec, 0x5e77 => 0x6ef8, + 0x5e78 => 0x6efe, 0x5e79 => 0x6f3f, 0x5e7a => 0x6ef2, 0x5e7b => 0x6f31, + 0x5e7c => 0x6eef, 0x5e7d => 0x6f32, 0x5e7e => 0x6ecc, 0x5f21 => 0x6f3e, + 0x5f22 => 0x6f13, 0x5f23 => 0x6ef7, 0x5f24 => 0x6f86, 0x5f25 => 0x6f7a, + 0x5f26 => 0x6f78, 0x5f27 => 0x6f81, 0x5f28 => 0x6f80, 0x5f29 => 0x6f6f, + 0x5f2a => 0x6f5b, 0x5f2b => 0x6ff3, 0x5f2c => 0x6f6d, 0x5f2d => 0x6f82, + 0x5f2e => 0x6f7c, 0x5f2f => 0x6f58, 0x5f30 => 0x6f8e, 0x5f31 => 0x6f91, + 0x5f32 => 0x6fc2, 0x5f33 => 0x6f66, 0x5f34 => 0x6fb3, 0x5f35 => 0x6fa3, + 0x5f36 => 0x6fa1, 0x5f37 => 0x6fa4, 0x5f38 => 0x6fb9, 0x5f39 => 0x6fc6, + 0x5f3a => 0x6faa, 0x5f3b => 0x6fdf, 0x5f3c => 0x6fd5, 0x5f3d => 0x6fec, + 0x5f3e => 0x6fd4, 0x5f3f => 0x6fd8, 0x5f40 => 0x6ff1, 0x5f41 => 0x6fee, + 0x5f42 => 0x6fdb, 0x5f43 => 0x7009, 0x5f44 => 0x700b, 0x5f45 => 0x6ffa, + 0x5f46 => 0x7011, 0x5f47 => 0x7001, 0x5f48 => 0x700f, 0x5f49 => 0x6ffe, + 0x5f4a => 0x701b, 0x5f4b => 0x701a, 0x5f4c => 0x6f74, 0x5f4d => 0x701d, + 0x5f4e => 0x7018, 0x5f4f => 0x701f, 0x5f50 => 0x7030, 0x5f51 => 0x703e, + 0x5f52 => 0x7032, 0x5f53 => 0x7051, 0x5f54 => 0x7063, 0x5f55 => 0x7099, + 0x5f56 => 0x7092, 0x5f57 => 0x70af, 0x5f58 => 0x70f1, 0x5f59 => 0x70ac, + 0x5f5a => 0x70b8, 0x5f5b => 0x70b3, 0x5f5c => 0x70ae, 0x5f5d => 0x70df, + 0x5f5e => 0x70cb, 0x5f5f => 0x70dd, 0x5f60 => 0x70d9, 0x5f61 => 0x7109, + 0x5f62 => 0x70fd, 0x5f63 => 0x711c, 0x5f64 => 0x7119, 0x5f65 => 0x7165, + 0x5f66 => 0x7155, 0x5f67 => 0x7188, 0x5f68 => 0x7166, 0x5f69 => 0x7162, + 0x5f6a => 0x714c, 0x5f6b => 0x7156, 0x5f6c => 0x716c, 0x5f6d => 0x718f, + 0x5f6e => 0x71fb, 0x5f6f => 0x7184, 0x5f70 => 0x7195, 0x5f71 => 0x71a8, + 0x5f72 => 0x71ac, 0x5f73 => 0x71d7, 0x5f74 => 0x71b9, 0x5f75 => 0x71be, + 0x5f76 => 0x71d2, 0x5f77 => 0x71c9, 0x5f78 => 0x71d4, 0x5f79 => 0x71ce, + 0x5f7a => 0x71e0, 0x5f7b => 0x71ec, 0x5f7c => 0x71e7, 0x5f7d => 0x71f5, + 0x5f7e => 0x71fc, 0x6021 => 0x71f9, 0x6022 => 0x71ff, 0x6023 => 0x720d, + 0x6024 => 0x7210, 0x6025 => 0x721b, 0x6026 => 0x7228, 0x6027 => 0x722d, + 0x6028 => 0x722c, 0x6029 => 0x7230, 0x602a => 0x7232, 0x602b => 0x723b, + 0x602c => 0x723c, 0x602d => 0x723f, 0x602e => 0x7240, 0x602f => 0x7246, + 0x6030 => 0x724b, 0x6031 => 0x7258, 0x6032 => 0x7274, 0x6033 => 0x727e, + 0x6034 => 0x7282, 0x6035 => 0x7281, 0x6036 => 0x7287, 0x6037 => 0x7292, + 0x6038 => 0x7296, 0x6039 => 0x72a2, 0x603a => 0x72a7, 0x603b => 0x72b9, + 0x603c => 0x72b2, 0x603d => 0x72c3, 0x603e => 0x72c6, 0x603f => 0x72c4, + 0x6040 => 0x72ce, 0x6041 => 0x72d2, 0x6042 => 0x72e2, 0x6043 => 0x72e0, + 0x6044 => 0x72e1, 0x6045 => 0x72f9, 0x6046 => 0x72f7, 0x6047 => 0x500f, + 0x6048 => 0x7317, 0x6049 => 0x730a, 0x604a => 0x731c, 0x604b => 0x7316, + 0x604c => 0x731d, 0x604d => 0x7334, 0x604e => 0x732f, 0x604f => 0x7329, + 0x6050 => 0x7325, 0x6051 => 0x733e, 0x6052 => 0x734e, 0x6053 => 0x734f, + 0x6054 => 0x9ed8, 0x6055 => 0x7357, 0x6056 => 0x736a, 0x6057 => 0x7368, + 0x6058 => 0x7370, 0x6059 => 0x7378, 0x605a => 0x7375, 0x605b => 0x737b, + 0x605c => 0x737a, 0x605d => 0x73c8, 0x605e => 0x73b3, 0x605f => 0x73ce, + 0x6060 => 0x73bb, 0x6061 => 0x73c0, 0x6062 => 0x73e5, 0x6063 => 0x73ee, + 0x6064 => 0x73de, 0x6065 => 0x74a2, 0x6066 => 0x7405, 0x6067 => 0x746f, + 0x6068 => 0x7425, 0x6069 => 0x73f8, 0x606a => 0x7432, 0x606b => 0x743a, + 0x606c => 0x7455, 0x606d => 0x743f, 0x606e => 0x745f, 0x606f => 0x7459, + 0x6070 => 0x7441, 0x6071 => 0x745c, 0x6072 => 0x7469, 0x6073 => 0x7470, + 0x6074 => 0x7463, 0x6075 => 0x746a, 0x6076 => 0x7476, 0x6077 => 0x747e, + 0x6078 => 0x748b, 0x6079 => 0x749e, 0x607a => 0x74a7, 0x607b => 0x74ca, + 0x607c => 0x74cf, 0x607d => 0x74d4, 0x607e => 0x73f1, 0x6121 => 0x74e0, + 0x6122 => 0x74e3, 0x6123 => 0x74e7, 0x6124 => 0x74e9, 0x6125 => 0x74ee, + 0x6126 => 0x74f2, 0x6127 => 0x74f0, 0x6128 => 0x74f1, 0x6129 => 0x74f8, + 0x612a => 0x74f7, 0x612b => 0x7504, 0x612c => 0x7503, 0x612d => 0x7505, + 0x612e => 0x750c, 0x612f => 0x750e, 0x6130 => 0x750d, 0x6131 => 0x7515, + 0x6132 => 0x7513, 0x6133 => 0x751e, 0x6134 => 0x7526, 0x6135 => 0x752c, + 0x6136 => 0x753c, 0x6137 => 0x7544, 0x6138 => 0x754d, 0x6139 => 0x754a, + 0x613a => 0x7549, 0x613b => 0x755b, 0x613c => 0x7546, 0x613d => 0x755a, + 0x613e => 0x7569, 0x613f => 0x7564, 0x6140 => 0x7567, 0x6141 => 0x756b, + 0x6142 => 0x756d, 0x6143 => 0x7578, 0x6144 => 0x7576, 0x6145 => 0x7586, + 0x6146 => 0x7587, 0x6147 => 0x7574, 0x6148 => 0x758a, 0x6149 => 0x7589, + 0x614a => 0x7582, 0x614b => 0x7594, 0x614c => 0x759a, 0x614d => 0x759d, + 0x614e => 0x75a5, 0x614f => 0x75a3, 0x6150 => 0x75c2, 0x6151 => 0x75b3, + 0x6152 => 0x75c3, 0x6153 => 0x75b5, 0x6154 => 0x75bd, 0x6155 => 0x75b8, + 0x6156 => 0x75bc, 0x6157 => 0x75b1, 0x6158 => 0x75cd, 0x6159 => 0x75ca, + 0x615a => 0x75d2, 0x615b => 0x75d9, 0x615c => 0x75e3, 0x615d => 0x75de, + 0x615e => 0x75fe, 0x615f => 0x75ff, 0x6160 => 0x75fc, 0x6161 => 0x7601, + 0x6162 => 0x75f0, 0x6163 => 0x75fa, 0x6164 => 0x75f2, 0x6165 => 0x75f3, + 0x6166 => 0x760b, 0x6167 => 0x760d, 0x6168 => 0x7609, 0x6169 => 0x761f, + 0x616a => 0x7627, 0x616b => 0x7620, 0x616c => 0x7621, 0x616d => 0x7622, + 0x616e => 0x7624, 0x616f => 0x7634, 0x6170 => 0x7630, 0x6171 => 0x763b, + 0x6172 => 0x7647, 0x6173 => 0x7648, 0x6174 => 0x7646, 0x6175 => 0x765c, + 0x6176 => 0x7658, 0x6177 => 0x7661, 0x6178 => 0x7662, 0x6179 => 0x7668, + 0x617a => 0x7669, 0x617b => 0x766a, 0x617c => 0x7667, 0x617d => 0x766c, + 0x617e => 0x7670, 0x6221 => 0x7672, 0x6222 => 0x7676, 0x6223 => 0x7678, + 0x6224 => 0x767c, 0x6225 => 0x7680, 0x6226 => 0x7683, 0x6227 => 0x7688, + 0x6228 => 0x768b, 0x6229 => 0x768e, 0x622a => 0x7696, 0x622b => 0x7693, + 0x622c => 0x7699, 0x622d => 0x769a, 0x622e => 0x76b0, 0x622f => 0x76b4, + 0x6230 => 0x76b8, 0x6231 => 0x76b9, 0x6232 => 0x76ba, 0x6233 => 0x76c2, + 0x6234 => 0x76cd, 0x6235 => 0x76d6, 0x6236 => 0x76d2, 0x6237 => 0x76de, + 0x6238 => 0x76e1, 0x6239 => 0x76e5, 0x623a => 0x76e7, 0x623b => 0x76ea, + 0x623c => 0x862f, 0x623d => 0x76fb, 0x623e => 0x7708, 0x623f => 0x7707, + 0x6240 => 0x7704, 0x6241 => 0x7729, 0x6242 => 0x7724, 0x6243 => 0x771e, + 0x6244 => 0x7725, 0x6245 => 0x7726, 0x6246 => 0x771b, 0x6247 => 0x7737, + 0x6248 => 0x7738, 0x6249 => 0x7747, 0x624a => 0x775a, 0x624b => 0x7768, + 0x624c => 0x776b, 0x624d => 0x775b, 0x624e => 0x7765, 0x624f => 0x777f, + 0x6250 => 0x777e, 0x6251 => 0x7779, 0x6252 => 0x778e, 0x6253 => 0x778b, + 0x6254 => 0x7791, 0x6255 => 0x77a0, 0x6256 => 0x779e, 0x6257 => 0x77b0, + 0x6258 => 0x77b6, 0x6259 => 0x77b9, 0x625a => 0x77bf, 0x625b => 0x77bc, + 0x625c => 0x77bd, 0x625d => 0x77bb, 0x625e => 0x77c7, 0x625f => 0x77cd, + 0x6260 => 0x77d7, 0x6261 => 0x77da, 0x6262 => 0x77dc, 0x6263 => 0x77e3, + 0x6264 => 0x77ee, 0x6265 => 0x77fc, 0x6266 => 0x780c, 0x6267 => 0x7812, + 0x6268 => 0x7926, 0x6269 => 0x7820, 0x626a => 0x792a, 0x626b => 0x7845, + 0x626c => 0x788e, 0x626d => 0x7874, 0x626e => 0x7886, 0x626f => 0x787c, + 0x6270 => 0x789a, 0x6271 => 0x788c, 0x6272 => 0x78a3, 0x6273 => 0x78b5, + 0x6274 => 0x78aa, 0x6275 => 0x78af, 0x6276 => 0x78d1, 0x6277 => 0x78c6, + 0x6278 => 0x78cb, 0x6279 => 0x78d4, 0x627a => 0x78be, 0x627b => 0x78bc, + 0x627c => 0x78c5, 0x627d => 0x78ca, 0x627e => 0x78ec, 0x6321 => 0x78e7, + 0x6322 => 0x78da, 0x6323 => 0x78fd, 0x6324 => 0x78f4, 0x6325 => 0x7907, + 0x6326 => 0x7912, 0x6327 => 0x7911, 0x6328 => 0x7919, 0x6329 => 0x792c, + 0x632a => 0x792b, 0x632b => 0x7940, 0x632c => 0x7960, 0x632d => 0x7957, + 0x632e => 0x795f, 0x632f => 0x795a, 0x6330 => 0x7955, 0x6331 => 0x7953, + 0x6332 => 0x797a, 0x6333 => 0x797f, 0x6334 => 0x798a, 0x6335 => 0x799d, + 0x6336 => 0x79a7, 0x6337 => 0x9f4b, 0x6338 => 0x79aa, 0x6339 => 0x79ae, + 0x633a => 0x79b3, 0x633b => 0x79b9, 0x633c => 0x79ba, 0x633d => 0x79c9, + 0x633e => 0x79d5, 0x633f => 0x79e7, 0x6340 => 0x79ec, 0x6341 => 0x79e1, + 0x6342 => 0x79e3, 0x6343 => 0x7a08, 0x6344 => 0x7a0d, 0x6345 => 0x7a18, + 0x6346 => 0x7a19, 0x6347 => 0x7a20, 0x6348 => 0x7a1f, 0x6349 => 0x7980, + 0x634a => 0x7a31, 0x634b => 0x7a3b, 0x634c => 0x7a3e, 0x634d => 0x7a37, + 0x634e => 0x7a43, 0x634f => 0x7a57, 0x6350 => 0x7a49, 0x6351 => 0x7a61, + 0x6352 => 0x7a62, 0x6353 => 0x7a69, 0x6354 => 0x9f9d, 0x6355 => 0x7a70, + 0x6356 => 0x7a79, 0x6357 => 0x7a7d, 0x6358 => 0x7a88, 0x6359 => 0x7a97, + 0x635a => 0x7a95, 0x635b => 0x7a98, 0x635c => 0x7a96, 0x635d => 0x7aa9, + 0x635e => 0x7ac8, 0x635f => 0x7ab0, 0x6360 => 0x7ab6, 0x6361 => 0x7ac5, + 0x6362 => 0x7ac4, 0x6363 => 0x7abf, 0x6364 => 0x9083, 0x6365 => 0x7ac7, + 0x6366 => 0x7aca, 0x6367 => 0x7acd, 0x6368 => 0x7acf, 0x6369 => 0x7ad5, + 0x636a => 0x7ad3, 0x636b => 0x7ad9, 0x636c => 0x7ada, 0x636d => 0x7add, + 0x636e => 0x7ae1, 0x636f => 0x7ae2, 0x6370 => 0x7ae6, 0x6371 => 0x7aed, + 0x6372 => 0x7af0, 0x6373 => 0x7b02, 0x6374 => 0x7b0f, 0x6375 => 0x7b0a, + 0x6376 => 0x7b06, 0x6377 => 0x7b33, 0x6378 => 0x7b18, 0x6379 => 0x7b19, + 0x637a => 0x7b1e, 0x637b => 0x7b35, 0x637c => 0x7b28, 0x637d => 0x7b36, + 0x637e => 0x7b50, 0x6421 => 0x7b7a, 0x6422 => 0x7b04, 0x6423 => 0x7b4d, + 0x6424 => 0x7b0b, 0x6425 => 0x7b4c, 0x6426 => 0x7b45, 0x6427 => 0x7b75, + 0x6428 => 0x7b65, 0x6429 => 0x7b74, 0x642a => 0x7b67, 0x642b => 0x7b70, + 0x642c => 0x7b71, 0x642d => 0x7b6c, 0x642e => 0x7b6e, 0x642f => 0x7b9d, + 0x6430 => 0x7b98, 0x6431 => 0x7b9f, 0x6432 => 0x7b8d, 0x6433 => 0x7b9c, + 0x6434 => 0x7b9a, 0x6435 => 0x7b8b, 0x6436 => 0x7b92, 0x6437 => 0x7b8f, + 0x6438 => 0x7b5d, 0x6439 => 0x7b99, 0x643a => 0x7bcb, 0x643b => 0x7bc1, + 0x643c => 0x7bcc, 0x643d => 0x7bcf, 0x643e => 0x7bb4, 0x643f => 0x7bc6, + 0x6440 => 0x7bdd, 0x6441 => 0x7be9, 0x6442 => 0x7c11, 0x6443 => 0x7c14, + 0x6444 => 0x7be6, 0x6445 => 0x7be5, 0x6446 => 0x7c60, 0x6447 => 0x7c00, + 0x6448 => 0x7c07, 0x6449 => 0x7c13, 0x644a => 0x7bf3, 0x644b => 0x7bf7, + 0x644c => 0x7c17, 0x644d => 0x7c0d, 0x644e => 0x7bf6, 0x644f => 0x7c23, + 0x6450 => 0x7c27, 0x6451 => 0x7c2a, 0x6452 => 0x7c1f, 0x6453 => 0x7c37, + 0x6454 => 0x7c2b, 0x6455 => 0x7c3d, 0x6456 => 0x7c4c, 0x6457 => 0x7c43, + 0x6458 => 0x7c54, 0x6459 => 0x7c4f, 0x645a => 0x7c40, 0x645b => 0x7c50, + 0x645c => 0x7c58, 0x645d => 0x7c5f, 0x645e => 0x7c64, 0x645f => 0x7c56, + 0x6460 => 0x7c65, 0x6461 => 0x7c6c, 0x6462 => 0x7c75, 0x6463 => 0x7c83, + 0x6464 => 0x7c90, 0x6465 => 0x7ca4, 0x6466 => 0x7cad, 0x6467 => 0x7ca2, + 0x6468 => 0x7cab, 0x6469 => 0x7ca1, 0x646a => 0x7ca8, 0x646b => 0x7cb3, + 0x646c => 0x7cb2, 0x646d => 0x7cb1, 0x646e => 0x7cae, 0x646f => 0x7cb9, + 0x6470 => 0x7cbd, 0x6471 => 0x7cc0, 0x6472 => 0x7cc5, 0x6473 => 0x7cc2, + 0x6474 => 0x7cd8, 0x6475 => 0x7cd2, 0x6476 => 0x7cdc, 0x6477 => 0x7ce2, + 0x6478 => 0x9b3b, 0x6479 => 0x7cef, 0x647a => 0x7cf2, 0x647b => 0x7cf4, + 0x647c => 0x7cf6, 0x647d => 0x7cfa, 0x647e => 0x7d06, 0x6521 => 0x7d02, + 0x6522 => 0x7d1c, 0x6523 => 0x7d15, 0x6524 => 0x7d0a, 0x6525 => 0x7d45, + 0x6526 => 0x7d4b, 0x6527 => 0x7d2e, 0x6528 => 0x7d32, 0x6529 => 0x7d3f, + 0x652a => 0x7d35, 0x652b => 0x7d46, 0x652c => 0x7d73, 0x652d => 0x7d56, + 0x652e => 0x7d4e, 0x652f => 0x7d72, 0x6530 => 0x7d68, 0x6531 => 0x7d6e, + 0x6532 => 0x7d4f, 0x6533 => 0x7d63, 0x6534 => 0x7d93, 0x6535 => 0x7d89, + 0x6536 => 0x7d5b, 0x6537 => 0x7d8f, 0x6538 => 0x7d7d, 0x6539 => 0x7d9b, + 0x653a => 0x7dba, 0x653b => 0x7dae, 0x653c => 0x7da3, 0x653d => 0x7db5, + 0x653e => 0x7dc7, 0x653f => 0x7dbd, 0x6540 => 0x7dab, 0x6541 => 0x7e3d, + 0x6542 => 0x7da2, 0x6543 => 0x7daf, 0x6544 => 0x7ddc, 0x6545 => 0x7db8, + 0x6546 => 0x7d9f, 0x6547 => 0x7db0, 0x6548 => 0x7dd8, 0x6549 => 0x7ddd, + 0x654a => 0x7de4, 0x654b => 0x7dde, 0x654c => 0x7dfb, 0x654d => 0x7df2, + 0x654e => 0x7de1, 0x654f => 0x7e05, 0x6550 => 0x7e0a, 0x6551 => 0x7e23, + 0x6552 => 0x7e21, 0x6553 => 0x7e12, 0x6554 => 0x7e31, 0x6555 => 0x7e1f, + 0x6556 => 0x7e09, 0x6557 => 0x7e0b, 0x6558 => 0x7e22, 0x6559 => 0x7e46, + 0x655a => 0x7e66, 0x655b => 0x7e3b, 0x655c => 0x7e35, 0x655d => 0x7e39, + 0x655e => 0x7e43, 0x655f => 0x7e37, 0x6560 => 0x7e32, 0x6561 => 0x7e3a, + 0x6562 => 0x7e67, 0x6563 => 0x7e5d, 0x6564 => 0x7e56, 0x6565 => 0x7e5e, + 0x6566 => 0x7e59, 0x6567 => 0x7e5a, 0x6568 => 0x7e79, 0x6569 => 0x7e6a, + 0x656a => 0x7e69, 0x656b => 0x7e7c, 0x656c => 0x7e7b, 0x656d => 0x7e83, + 0x656e => 0x7dd5, 0x656f => 0x7e7d, 0x6570 => 0x8fae, 0x6571 => 0x7e7f, + 0x6572 => 0x7e88, 0x6573 => 0x7e89, 0x6574 => 0x7e8c, 0x6575 => 0x7e92, + 0x6576 => 0x7e90, 0x6577 => 0x7e93, 0x6578 => 0x7e94, 0x6579 => 0x7e96, + 0x657a => 0x7e8e, 0x657b => 0x7e9b, 0x657c => 0x7e9c, 0x657d => 0x7f38, + 0x657e => 0x7f3a, 0x6621 => 0x7f45, 0x6622 => 0x7f4c, 0x6623 => 0x7f4d, + 0x6624 => 0x7f4e, 0x6625 => 0x7f50, 0x6626 => 0x7f51, 0x6627 => 0x7f55, + 0x6628 => 0x7f54, 0x6629 => 0x7f58, 0x662a => 0x7f5f, 0x662b => 0x7f60, + 0x662c => 0x7f68, 0x662d => 0x7f69, 0x662e => 0x7f67, 0x662f => 0x7f78, + 0x6630 => 0x7f82, 0x6631 => 0x7f86, 0x6632 => 0x7f83, 0x6633 => 0x7f88, + 0x6634 => 0x7f87, 0x6635 => 0x7f8c, 0x6636 => 0x7f94, 0x6637 => 0x7f9e, + 0x6638 => 0x7f9d, 0x6639 => 0x7f9a, 0x663a => 0x7fa3, 0x663b => 0x7faf, + 0x663c => 0x7fb2, 0x663d => 0x7fb9, 0x663e => 0x7fae, 0x663f => 0x7fb6, + 0x6640 => 0x7fb8, 0x6641 => 0x8b71, 0x6642 => 0x7fc5, 0x6643 => 0x7fc6, + 0x6644 => 0x7fca, 0x6645 => 0x7fd5, 0x6646 => 0x7fd4, 0x6647 => 0x7fe1, + 0x6648 => 0x7fe6, 0x6649 => 0x7fe9, 0x664a => 0x7ff3, 0x664b => 0x7ff9, + 0x664c => 0x98dc, 0x664d => 0x8006, 0x664e => 0x8004, 0x664f => 0x800b, + 0x6650 => 0x8012, 0x6651 => 0x8018, 0x6652 => 0x8019, 0x6653 => 0x801c, + 0x6654 => 0x8021, 0x6655 => 0x8028, 0x6656 => 0x803f, 0x6657 => 0x803b, + 0x6658 => 0x804a, 0x6659 => 0x8046, 0x665a => 0x8052, 0x665b => 0x8058, + 0x665c => 0x805a, 0x665d => 0x805f, 0x665e => 0x8062, 0x665f => 0x8068, + 0x6660 => 0x8073, 0x6661 => 0x8072, 0x6662 => 0x8070, 0x6663 => 0x8076, + 0x6664 => 0x8079, 0x6665 => 0x807d, 0x6666 => 0x807f, 0x6667 => 0x8084, + 0x6668 => 0x8086, 0x6669 => 0x8085, 0x666a => 0x809b, 0x666b => 0x8093, + 0x666c => 0x809a, 0x666d => 0x80ad, 0x666e => 0x5190, 0x666f => 0x80ac, + 0x6670 => 0x80db, 0x6671 => 0x80e5, 0x6672 => 0x80d9, 0x6673 => 0x80dd, + 0x6674 => 0x80c4, 0x6675 => 0x80da, 0x6676 => 0x80d6, 0x6677 => 0x8109, + 0x6678 => 0x80ef, 0x6679 => 0x80f1, 0x667a => 0x811b, 0x667b => 0x8129, + 0x667c => 0x8123, 0x667d => 0x812f, 0x667e => 0x814b, 0x6721 => 0x968b, + 0x6722 => 0x8146, 0x6723 => 0x813e, 0x6724 => 0x8153, 0x6725 => 0x8151, + 0x6726 => 0x80fc, 0x6727 => 0x8171, 0x6728 => 0x816e, 0x6729 => 0x8165, + 0x672a => 0x8166, 0x672b => 0x8174, 0x672c => 0x8183, 0x672d => 0x8188, + 0x672e => 0x818a, 0x672f => 0x8180, 0x6730 => 0x8182, 0x6731 => 0x81a0, + 0x6732 => 0x8195, 0x6733 => 0x81a4, 0x6734 => 0x81a3, 0x6735 => 0x815f, + 0x6736 => 0x8193, 0x6737 => 0x81a9, 0x6738 => 0x81b0, 0x6739 => 0x81b5, + 0x673a => 0x81be, 0x673b => 0x81b8, 0x673c => 0x81bd, 0x673d => 0x81c0, + 0x673e => 0x81c2, 0x673f => 0x81ba, 0x6740 => 0x81c9, 0x6741 => 0x81cd, + 0x6742 => 0x81d1, 0x6743 => 0x81d9, 0x6744 => 0x81d8, 0x6745 => 0x81c8, + 0x6746 => 0x81da, 0x6747 => 0x81df, 0x6748 => 0x81e0, 0x6749 => 0x81e7, + 0x674a => 0x81fa, 0x674b => 0x81fb, 0x674c => 0x81fe, 0x674d => 0x8201, + 0x674e => 0x8202, 0x674f => 0x8205, 0x6750 => 0x8207, 0x6751 => 0x820a, + 0x6752 => 0x820d, 0x6753 => 0x8210, 0x6754 => 0x8216, 0x6755 => 0x8229, + 0x6756 => 0x822b, 0x6757 => 0x8238, 0x6758 => 0x8233, 0x6759 => 0x8240, + 0x675a => 0x8259, 0x675b => 0x8258, 0x675c => 0x825d, 0x675d => 0x825a, + 0x675e => 0x825f, 0x675f => 0x8264, 0x6760 => 0x8262, 0x6761 => 0x8268, + 0x6762 => 0x826a, 0x6763 => 0x826b, 0x6764 => 0x822e, 0x6765 => 0x8271, + 0x6766 => 0x8277, 0x6767 => 0x8278, 0x6768 => 0x827e, 0x6769 => 0x828d, + 0x676a => 0x8292, 0x676b => 0x82ab, 0x676c => 0x829f, 0x676d => 0x82bb, + 0x676e => 0x82ac, 0x676f => 0x82e1, 0x6770 => 0x82e3, 0x6771 => 0x82df, + 0x6772 => 0x82d2, 0x6773 => 0x82f4, 0x6774 => 0x82f3, 0x6775 => 0x82fa, + 0x6776 => 0x8393, 0x6777 => 0x8303, 0x6778 => 0x82fb, 0x6779 => 0x82f9, + 0x677a => 0x82de, 0x677b => 0x8306, 0x677c => 0x82dc, 0x677d => 0x8309, + 0x677e => 0x82d9, 0x6821 => 0x8335, 0x6822 => 0x8334, 0x6823 => 0x8316, + 0x6824 => 0x8332, 0x6825 => 0x8331, 0x6826 => 0x8340, 0x6827 => 0x8339, + 0x6828 => 0x8350, 0x6829 => 0x8345, 0x682a => 0x832f, 0x682b => 0x832b, + 0x682c => 0x8317, 0x682d => 0x8318, 0x682e => 0x8385, 0x682f => 0x839a, + 0x6830 => 0x83aa, 0x6831 => 0x839f, 0x6832 => 0x83a2, 0x6833 => 0x8396, + 0x6834 => 0x8323, 0x6835 => 0x838e, 0x6836 => 0x8387, 0x6837 => 0x838a, + 0x6838 => 0x837c, 0x6839 => 0x83b5, 0x683a => 0x8373, 0x683b => 0x8375, + 0x683c => 0x83a0, 0x683d => 0x8389, 0x683e => 0x83a8, 0x683f => 0x83f4, + 0x6840 => 0x8413, 0x6841 => 0x83eb, 0x6842 => 0x83ce, 0x6843 => 0x83fd, + 0x6844 => 0x8403, 0x6845 => 0x83d8, 0x6846 => 0x840b, 0x6847 => 0x83c1, + 0x6848 => 0x83f7, 0x6849 => 0x8407, 0x684a => 0x83e0, 0x684b => 0x83f2, + 0x684c => 0x840d, 0x684d => 0x8422, 0x684e => 0x8420, 0x684f => 0x83bd, + 0x6850 => 0x8438, 0x6851 => 0x8506, 0x6852 => 0x83fb, 0x6853 => 0x846d, + 0x6854 => 0x842a, 0x6855 => 0x843c, 0x6856 => 0x855a, 0x6857 => 0x8484, + 0x6858 => 0x8477, 0x6859 => 0x846b, 0x685a => 0x84ad, 0x685b => 0x846e, + 0x685c => 0x8482, 0x685d => 0x8469, 0x685e => 0x8446, 0x685f => 0x842c, + 0x6860 => 0x846f, 0x6861 => 0x8479, 0x6862 => 0x8435, 0x6863 => 0x84ca, + 0x6864 => 0x8462, 0x6865 => 0x84b9, 0x6866 => 0x84bf, 0x6867 => 0x849f, + 0x6868 => 0x84d9, 0x6869 => 0x84cd, 0x686a => 0x84bb, 0x686b => 0x84da, + 0x686c => 0x84d0, 0x686d => 0x84c1, 0x686e => 0x84c6, 0x686f => 0x84d6, + 0x6870 => 0x84a1, 0x6871 => 0x8521, 0x6872 => 0x84ff, 0x6873 => 0x84f4, + 0x6874 => 0x8517, 0x6875 => 0x8518, 0x6876 => 0x852c, 0x6877 => 0x851f, + 0x6878 => 0x8515, 0x6879 => 0x8514, 0x687a => 0x84fc, 0x687b => 0x8540, + 0x687c => 0x8563, 0x687d => 0x8558, 0x687e => 0x8548, 0x6921 => 0x8541, + 0x6922 => 0x8602, 0x6923 => 0x854b, 0x6924 => 0x8555, 0x6925 => 0x8580, + 0x6926 => 0x85a4, 0x6927 => 0x8588, 0x6928 => 0x8591, 0x6929 => 0x858a, + 0x692a => 0x85a8, 0x692b => 0x856d, 0x692c => 0x8594, 0x692d => 0x859b, + 0x692e => 0x85ea, 0x692f => 0x8587, 0x6930 => 0x859c, 0x6931 => 0x8577, + 0x6932 => 0x857e, 0x6933 => 0x8590, 0x6934 => 0x85c9, 0x6935 => 0x85ba, + 0x6936 => 0x85cf, 0x6937 => 0x85b9, 0x6938 => 0x85d0, 0x6939 => 0x85d5, + 0x693a => 0x85dd, 0x693b => 0x85e5, 0x693c => 0x85dc, 0x693d => 0x85f9, + 0x693e => 0x860a, 0x693f => 0x8613, 0x6940 => 0x860b, 0x6941 => 0x85fe, + 0x6942 => 0x85fa, 0x6943 => 0x8606, 0x6944 => 0x8622, 0x6945 => 0x861a, + 0x6946 => 0x8630, 0x6947 => 0x863f, 0x6948 => 0x864d, 0x6949 => 0x4e55, + 0x694a => 0x8654, 0x694b => 0x865f, 0x694c => 0x8667, 0x694d => 0x8671, + 0x694e => 0x8693, 0x694f => 0x86a3, 0x6950 => 0x86a9, 0x6951 => 0x86aa, + 0x6952 => 0x868b, 0x6953 => 0x868c, 0x6954 => 0x86b6, 0x6955 => 0x86af, + 0x6956 => 0x86c4, 0x6957 => 0x86c6, 0x6958 => 0x86b0, 0x6959 => 0x86c9, + 0x695a => 0x8823, 0x695b => 0x86ab, 0x695c => 0x86d4, 0x695d => 0x86de, + 0x695e => 0x86e9, 0x695f => 0x86ec, 0x6960 => 0x86df, 0x6961 => 0x86db, + 0x6962 => 0x86ef, 0x6963 => 0x8712, 0x6964 => 0x8706, 0x6965 => 0x8708, + 0x6966 => 0x8700, 0x6967 => 0x8703, 0x6968 => 0x86fb, 0x6969 => 0x8711, + 0x696a => 0x8709, 0x696b => 0x870d, 0x696c => 0x86f9, 0x696d => 0x870a, + 0x696e => 0x8734, 0x696f => 0x873f, 0x6970 => 0x8737, 0x6971 => 0x873b, + 0x6972 => 0x8725, 0x6973 => 0x8729, 0x6974 => 0x871a, 0x6975 => 0x8760, + 0x6976 => 0x875f, 0x6977 => 0x8778, 0x6978 => 0x874c, 0x6979 => 0x874e, + 0x697a => 0x8774, 0x697b => 0x8757, 0x697c => 0x8768, 0x697d => 0x876e, + 0x697e => 0x8759, 0x6a21 => 0x8753, 0x6a22 => 0x8763, 0x6a23 => 0x876a, + 0x6a24 => 0x8805, 0x6a25 => 0x87a2, 0x6a26 => 0x879f, 0x6a27 => 0x8782, + 0x6a28 => 0x87af, 0x6a29 => 0x87cb, 0x6a2a => 0x87bd, 0x6a2b => 0x87c0, + 0x6a2c => 0x87d0, 0x6a2d => 0x96d6, 0x6a2e => 0x87ab, 0x6a2f => 0x87c4, + 0x6a30 => 0x87b3, 0x6a31 => 0x87c7, 0x6a32 => 0x87c6, 0x6a33 => 0x87bb, + 0x6a34 => 0x87ef, 0x6a35 => 0x87f2, 0x6a36 => 0x87e0, 0x6a37 => 0x880f, + 0x6a38 => 0x880d, 0x6a39 => 0x87fe, 0x6a3a => 0x87f6, 0x6a3b => 0x87f7, + 0x6a3c => 0x880e, 0x6a3d => 0x87d2, 0x6a3e => 0x8811, 0x6a3f => 0x8816, + 0x6a40 => 0x8815, 0x6a41 => 0x8822, 0x6a42 => 0x8821, 0x6a43 => 0x8831, + 0x6a44 => 0x8836, 0x6a45 => 0x8839, 0x6a46 => 0x8827, 0x6a47 => 0x883b, + 0x6a48 => 0x8844, 0x6a49 => 0x8842, 0x6a4a => 0x8852, 0x6a4b => 0x8859, + 0x6a4c => 0x885e, 0x6a4d => 0x8862, 0x6a4e => 0x886b, 0x6a4f => 0x8881, + 0x6a50 => 0x887e, 0x6a51 => 0x889e, 0x6a52 => 0x8875, 0x6a53 => 0x887d, + 0x6a54 => 0x88b5, 0x6a55 => 0x8872, 0x6a56 => 0x8882, 0x6a57 => 0x8897, + 0x6a58 => 0x8892, 0x6a59 => 0x88ae, 0x6a5a => 0x8899, 0x6a5b => 0x88a2, + 0x6a5c => 0x888d, 0x6a5d => 0x88a4, 0x6a5e => 0x88b0, 0x6a5f => 0x88bf, + 0x6a60 => 0x88b1, 0x6a61 => 0x88c3, 0x6a62 => 0x88c4, 0x6a63 => 0x88d4, + 0x6a64 => 0x88d8, 0x6a65 => 0x88d9, 0x6a66 => 0x88dd, 0x6a67 => 0x88f9, + 0x6a68 => 0x8902, 0x6a69 => 0x88fc, 0x6a6a => 0x88f4, 0x6a6b => 0x88e8, + 0x6a6c => 0x88f2, 0x6a6d => 0x8904, 0x6a6e => 0x890c, 0x6a6f => 0x890a, + 0x6a70 => 0x8913, 0x6a71 => 0x8943, 0x6a72 => 0x891e, 0x6a73 => 0x8925, + 0x6a74 => 0x892a, 0x6a75 => 0x892b, 0x6a76 => 0x8941, 0x6a77 => 0x8944, + 0x6a78 => 0x893b, 0x6a79 => 0x8936, 0x6a7a => 0x8938, 0x6a7b => 0x894c, + 0x6a7c => 0x891d, 0x6a7d => 0x8960, 0x6a7e => 0x895e, 0x6b21 => 0x8966, + 0x6b22 => 0x8964, 0x6b23 => 0x896d, 0x6b24 => 0x896a, 0x6b25 => 0x896f, + 0x6b26 => 0x8974, 0x6b27 => 0x8977, 0x6b28 => 0x897e, 0x6b29 => 0x8983, + 0x6b2a => 0x8988, 0x6b2b => 0x898a, 0x6b2c => 0x8993, 0x6b2d => 0x8998, + 0x6b2e => 0x89a1, 0x6b2f => 0x89a9, 0x6b30 => 0x89a6, 0x6b31 => 0x89ac, + 0x6b32 => 0x89af, 0x6b33 => 0x89b2, 0x6b34 => 0x89ba, 0x6b35 => 0x89bd, + 0x6b36 => 0x89bf, 0x6b37 => 0x89c0, 0x6b38 => 0x89da, 0x6b39 => 0x89dc, + 0x6b3a => 0x89dd, 0x6b3b => 0x89e7, 0x6b3c => 0x89f4, 0x6b3d => 0x89f8, + 0x6b3e => 0x8a03, 0x6b3f => 0x8a16, 0x6b40 => 0x8a10, 0x6b41 => 0x8a0c, + 0x6b42 => 0x8a1b, 0x6b43 => 0x8a1d, 0x6b44 => 0x8a25, 0x6b45 => 0x8a36, + 0x6b46 => 0x8a41, 0x6b47 => 0x8a5b, 0x6b48 => 0x8a52, 0x6b49 => 0x8a46, + 0x6b4a => 0x8a48, 0x6b4b => 0x8a7c, 0x6b4c => 0x8a6d, 0x6b4d => 0x8a6c, + 0x6b4e => 0x8a62, 0x6b4f => 0x8a85, 0x6b50 => 0x8a82, 0x6b51 => 0x8a84, + 0x6b52 => 0x8aa8, 0x6b53 => 0x8aa1, 0x6b54 => 0x8a91, 0x6b55 => 0x8aa5, + 0x6b56 => 0x8aa6, 0x6b57 => 0x8a9a, 0x6b58 => 0x8aa3, 0x6b59 => 0x8ac4, + 0x6b5a => 0x8acd, 0x6b5b => 0x8ac2, 0x6b5c => 0x8ada, 0x6b5d => 0x8aeb, + 0x6b5e => 0x8af3, 0x6b5f => 0x8ae7, 0x6b60 => 0x8ae4, 0x6b61 => 0x8af1, + 0x6b62 => 0x8b14, 0x6b63 => 0x8ae0, 0x6b64 => 0x8ae2, 0x6b65 => 0x8af7, + 0x6b66 => 0x8ade, 0x6b67 => 0x8adb, 0x6b68 => 0x8b0c, 0x6b69 => 0x8b07, + 0x6b6a => 0x8b1a, 0x6b6b => 0x8ae1, 0x6b6c => 0x8b16, 0x6b6d => 0x8b10, + 0x6b6e => 0x8b17, 0x6b6f => 0x8b20, 0x6b70 => 0x8b33, 0x6b71 => 0x97ab, + 0x6b72 => 0x8b26, 0x6b73 => 0x8b2b, 0x6b74 => 0x8b3e, 0x6b75 => 0x8b28, + 0x6b76 => 0x8b41, 0x6b77 => 0x8b4c, 0x6b78 => 0x8b4f, 0x6b79 => 0x8b4e, + 0x6b7a => 0x8b49, 0x6b7b => 0x8b56, 0x6b7c => 0x8b5b, 0x6b7d => 0x8b5a, + 0x6b7e => 0x8b6b, 0x6c21 => 0x8b5f, 0x6c22 => 0x8b6c, 0x6c23 => 0x8b6f, + 0x6c24 => 0x8b74, 0x6c25 => 0x8b7d, 0x6c26 => 0x8b80, 0x6c27 => 0x8b8c, + 0x6c28 => 0x8b8e, 0x6c29 => 0x8b92, 0x6c2a => 0x8b93, 0x6c2b => 0x8b96, + 0x6c2c => 0x8b99, 0x6c2d => 0x8b9a, 0x6c2e => 0x8c3a, 0x6c2f => 0x8c41, + 0x6c30 => 0x8c3f, 0x6c31 => 0x8c48, 0x6c32 => 0x8c4c, 0x6c33 => 0x8c4e, + 0x6c34 => 0x8c50, 0x6c35 => 0x8c55, 0x6c36 => 0x8c62, 0x6c37 => 0x8c6c, + 0x6c38 => 0x8c78, 0x6c39 => 0x8c7a, 0x6c3a => 0x8c82, 0x6c3b => 0x8c89, + 0x6c3c => 0x8c85, 0x6c3d => 0x8c8a, 0x6c3e => 0x8c8d, 0x6c3f => 0x8c8e, + 0x6c40 => 0x8c94, 0x6c41 => 0x8c7c, 0x6c42 => 0x8c98, 0x6c43 => 0x621d, + 0x6c44 => 0x8cad, 0x6c45 => 0x8caa, 0x6c46 => 0x8cbd, 0x6c47 => 0x8cb2, + 0x6c48 => 0x8cb3, 0x6c49 => 0x8cae, 0x6c4a => 0x8cb6, 0x6c4b => 0x8cc8, + 0x6c4c => 0x8cc1, 0x6c4d => 0x8ce4, 0x6c4e => 0x8ce3, 0x6c4f => 0x8cda, + 0x6c50 => 0x8cfd, 0x6c51 => 0x8cfa, 0x6c52 => 0x8cfb, 0x6c53 => 0x8d04, + 0x6c54 => 0x8d05, 0x6c55 => 0x8d0a, 0x6c56 => 0x8d07, 0x6c57 => 0x8d0f, + 0x6c58 => 0x8d0d, 0x6c59 => 0x8d10, 0x6c5a => 0x9f4e, 0x6c5b => 0x8d13, + 0x6c5c => 0x8ccd, 0x6c5d => 0x8d14, 0x6c5e => 0x8d16, 0x6c5f => 0x8d67, + 0x6c60 => 0x8d6d, 0x6c61 => 0x8d71, 0x6c62 => 0x8d73, 0x6c63 => 0x8d81, + 0x6c64 => 0x8d99, 0x6c65 => 0x8dc2, 0x6c66 => 0x8dbe, 0x6c67 => 0x8dba, + 0x6c68 => 0x8dcf, 0x6c69 => 0x8dda, 0x6c6a => 0x8dd6, 0x6c6b => 0x8dcc, + 0x6c6c => 0x8ddb, 0x6c6d => 0x8dcb, 0x6c6e => 0x8dea, 0x6c6f => 0x8deb, + 0x6c70 => 0x8ddf, 0x6c71 => 0x8de3, 0x6c72 => 0x8dfc, 0x6c73 => 0x8e08, + 0x6c74 => 0x8e09, 0x6c75 => 0x8dff, 0x6c76 => 0x8e1d, 0x6c77 => 0x8e1e, + 0x6c78 => 0x8e10, 0x6c79 => 0x8e1f, 0x6c7a => 0x8e42, 0x6c7b => 0x8e35, + 0x6c7c => 0x8e30, 0x6c7d => 0x8e34, 0x6c7e => 0x8e4a, 0x6d21 => 0x8e47, + 0x6d22 => 0x8e49, 0x6d23 => 0x8e4c, 0x6d24 => 0x8e50, 0x6d25 => 0x8e48, + 0x6d26 => 0x8e59, 0x6d27 => 0x8e64, 0x6d28 => 0x8e60, 0x6d29 => 0x8e2a, + 0x6d2a => 0x8e63, 0x6d2b => 0x8e55, 0x6d2c => 0x8e76, 0x6d2d => 0x8e72, + 0x6d2e => 0x8e7c, 0x6d2f => 0x8e81, 0x6d30 => 0x8e87, 0x6d31 => 0x8e85, + 0x6d32 => 0x8e84, 0x6d33 => 0x8e8b, 0x6d34 => 0x8e8a, 0x6d35 => 0x8e93, + 0x6d36 => 0x8e91, 0x6d37 => 0x8e94, 0x6d38 => 0x8e99, 0x6d39 => 0x8eaa, + 0x6d3a => 0x8ea1, 0x6d3b => 0x8eac, 0x6d3c => 0x8eb0, 0x6d3d => 0x8ec6, + 0x6d3e => 0x8eb1, 0x6d3f => 0x8ebe, 0x6d40 => 0x8ec5, 0x6d41 => 0x8ec8, + 0x6d42 => 0x8ecb, 0x6d43 => 0x8edb, 0x6d44 => 0x8ee3, 0x6d45 => 0x8efc, + 0x6d46 => 0x8efb, 0x6d47 => 0x8eeb, 0x6d48 => 0x8efe, 0x6d49 => 0x8f0a, + 0x6d4a => 0x8f05, 0x6d4b => 0x8f15, 0x6d4c => 0x8f12, 0x6d4d => 0x8f19, + 0x6d4e => 0x8f13, 0x6d4f => 0x8f1c, 0x6d50 => 0x8f1f, 0x6d51 => 0x8f1b, + 0x6d52 => 0x8f0c, 0x6d53 => 0x8f26, 0x6d54 => 0x8f33, 0x6d55 => 0x8f3b, + 0x6d56 => 0x8f39, 0x6d57 => 0x8f45, 0x6d58 => 0x8f42, 0x6d59 => 0x8f3e, + 0x6d5a => 0x8f4c, 0x6d5b => 0x8f49, 0x6d5c => 0x8f46, 0x6d5d => 0x8f4e, + 0x6d5e => 0x8f57, 0x6d5f => 0x8f5c, 0x6d60 => 0x8f62, 0x6d61 => 0x8f63, + 0x6d62 => 0x8f64, 0x6d63 => 0x8f9c, 0x6d64 => 0x8f9f, 0x6d65 => 0x8fa3, + 0x6d66 => 0x8fad, 0x6d67 => 0x8faf, 0x6d68 => 0x8fb7, 0x6d69 => 0x8fda, + 0x6d6a => 0x8fe5, 0x6d6b => 0x8fe2, 0x6d6c => 0x8fea, 0x6d6d => 0x8fef, + 0x6d6e => 0x9087, 0x6d6f => 0x8ff4, 0x6d70 => 0x9005, 0x6d71 => 0x8ff9, + 0x6d72 => 0x8ffa, 0x6d73 => 0x9011, 0x6d74 => 0x9015, 0x6d75 => 0x9021, + 0x6d76 => 0x900d, 0x6d77 => 0x901e, 0x6d78 => 0x9016, 0x6d79 => 0x900b, + 0x6d7a => 0x9027, 0x6d7b => 0x9036, 0x6d7c => 0x9035, 0x6d7d => 0x9039, + 0x6d7e => 0x8ff8, 0x6e21 => 0x904f, 0x6e22 => 0x9050, 0x6e23 => 0x9051, + 0x6e24 => 0x9052, 0x6e25 => 0x900e, 0x6e26 => 0x9049, 0x6e27 => 0x903e, + 0x6e28 => 0x9056, 0x6e29 => 0x9058, 0x6e2a => 0x905e, 0x6e2b => 0x9068, + 0x6e2c => 0x906f, 0x6e2d => 0x9076, 0x6e2e => 0x96a8, 0x6e2f => 0x9072, + 0x6e30 => 0x9082, 0x6e31 => 0x907d, 0x6e32 => 0x9081, 0x6e33 => 0x9080, + 0x6e34 => 0x908a, 0x6e35 => 0x9089, 0x6e36 => 0x908f, 0x6e37 => 0x90a8, + 0x6e38 => 0x90af, 0x6e39 => 0x90b1, 0x6e3a => 0x90b5, 0x6e3b => 0x90e2, + 0x6e3c => 0x90e4, 0x6e3d => 0x6248, 0x6e3e => 0x90db, 0x6e3f => 0x9102, + 0x6e40 => 0x9112, 0x6e41 => 0x9119, 0x6e42 => 0x9132, 0x6e43 => 0x9130, + 0x6e44 => 0x914a, 0x6e45 => 0x9156, 0x6e46 => 0x9158, 0x6e47 => 0x9163, + 0x6e48 => 0x9165, 0x6e49 => 0x9169, 0x6e4a => 0x9173, 0x6e4b => 0x9172, + 0x6e4c => 0x918b, 0x6e4d => 0x9189, 0x6e4e => 0x9182, 0x6e4f => 0x91a2, + 0x6e50 => 0x91ab, 0x6e51 => 0x91af, 0x6e52 => 0x91aa, 0x6e53 => 0x91b5, + 0x6e54 => 0x91b4, 0x6e55 => 0x91ba, 0x6e56 => 0x91c0, 0x6e57 => 0x91c1, + 0x6e58 => 0x91c9, 0x6e59 => 0x91cb, 0x6e5a => 0x91d0, 0x6e5b => 0x91d6, + 0x6e5c => 0x91df, 0x6e5d => 0x91e1, 0x6e5e => 0x91db, 0x6e5f => 0x91fc, + 0x6e60 => 0x91f5, 0x6e61 => 0x91f6, 0x6e62 => 0x921e, 0x6e63 => 0x91ff, + 0x6e64 => 0x9214, 0x6e65 => 0x922c, 0x6e66 => 0x9215, 0x6e67 => 0x9211, + 0x6e68 => 0x925e, 0x6e69 => 0x9257, 0x6e6a => 0x9245, 0x6e6b => 0x9249, + 0x6e6c => 0x9264, 0x6e6d => 0x9248, 0x6e6e => 0x9295, 0x6e6f => 0x923f, + 0x6e70 => 0x924b, 0x6e71 => 0x9250, 0x6e72 => 0x929c, 0x6e73 => 0x9296, + 0x6e74 => 0x9293, 0x6e75 => 0x929b, 0x6e76 => 0x925a, 0x6e77 => 0x92cf, + 0x6e78 => 0x92b9, 0x6e79 => 0x92b7, 0x6e7a => 0x92e9, 0x6e7b => 0x930f, + 0x6e7c => 0x92fa, 0x6e7d => 0x9344, 0x6e7e => 0x932e, 0x6f21 => 0x9319, + 0x6f22 => 0x9322, 0x6f23 => 0x931a, 0x6f24 => 0x9323, 0x6f25 => 0x933a, + 0x6f26 => 0x9335, 0x6f27 => 0x933b, 0x6f28 => 0x935c, 0x6f29 => 0x9360, + 0x6f2a => 0x937c, 0x6f2b => 0x936e, 0x6f2c => 0x9356, 0x6f2d => 0x93b0, + 0x6f2e => 0x93ac, 0x6f2f => 0x93ad, 0x6f30 => 0x9394, 0x6f31 => 0x93b9, + 0x6f32 => 0x93d6, 0x6f33 => 0x93d7, 0x6f34 => 0x93e8, 0x6f35 => 0x93e5, + 0x6f36 => 0x93d8, 0x6f37 => 0x93c3, 0x6f38 => 0x93dd, 0x6f39 => 0x93d0, + 0x6f3a => 0x93c8, 0x6f3b => 0x93e4, 0x6f3c => 0x941a, 0x6f3d => 0x9414, + 0x6f3e => 0x9413, 0x6f3f => 0x9403, 0x6f40 => 0x9407, 0x6f41 => 0x9410, + 0x6f42 => 0x9436, 0x6f43 => 0x942b, 0x6f44 => 0x9435, 0x6f45 => 0x9421, + 0x6f46 => 0x943a, 0x6f47 => 0x9441, 0x6f48 => 0x9452, 0x6f49 => 0x9444, + 0x6f4a => 0x945b, 0x6f4b => 0x9460, 0x6f4c => 0x9462, 0x6f4d => 0x945e, + 0x6f4e => 0x946a, 0x6f4f => 0x9229, 0x6f50 => 0x9470, 0x6f51 => 0x9475, + 0x6f52 => 0x9477, 0x6f53 => 0x947d, 0x6f54 => 0x945a, 0x6f55 => 0x947c, + 0x6f56 => 0x947e, 0x6f57 => 0x9481, 0x6f58 => 0x947f, 0x6f59 => 0x9582, + 0x6f5a => 0x9587, 0x6f5b => 0x958a, 0x6f5c => 0x9594, 0x6f5d => 0x9596, + 0x6f5e => 0x9598, 0x6f5f => 0x9599, 0x6f60 => 0x95a0, 0x6f61 => 0x95a8, + 0x6f62 => 0x95a7, 0x6f63 => 0x95ad, 0x6f64 => 0x95bc, 0x6f65 => 0x95bb, + 0x6f66 => 0x95b9, 0x6f67 => 0x95be, 0x6f68 => 0x95ca, 0x6f69 => 0x6ff6, + 0x6f6a => 0x95c3, 0x6f6b => 0x95cd, 0x6f6c => 0x95cc, 0x6f6d => 0x95d5, + 0x6f6e => 0x95d4, 0x6f6f => 0x95d6, 0x6f70 => 0x95dc, 0x6f71 => 0x95e1, + 0x6f72 => 0x95e5, 0x6f73 => 0x95e2, 0x6f74 => 0x9621, 0x6f75 => 0x9628, + 0x6f76 => 0x962e, 0x6f77 => 0x962f, 0x6f78 => 0x9642, 0x6f79 => 0x964c, + 0x6f7a => 0x964f, 0x6f7b => 0x964b, 0x6f7c => 0x9677, 0x6f7d => 0x965c, + 0x6f7e => 0x965e, 0x7021 => 0x965d, 0x7022 => 0x965f, 0x7023 => 0x9666, + 0x7024 => 0x9672, 0x7025 => 0x966c, 0x7026 => 0x968d, 0x7027 => 0x9698, + 0x7028 => 0x9695, 0x7029 => 0x9697, 0x702a => 0x96aa, 0x702b => 0x96a7, + 0x702c => 0x96b1, 0x702d => 0x96b2, 0x702e => 0x96b0, 0x702f => 0x96b4, + 0x7030 => 0x96b6, 0x7031 => 0x96b8, 0x7032 => 0x96b9, 0x7033 => 0x96ce, + 0x7034 => 0x96cb, 0x7035 => 0x96c9, 0x7036 => 0x96cd, 0x7037 => 0x894d, + 0x7038 => 0x96dc, 0x7039 => 0x970d, 0x703a => 0x96d5, 0x703b => 0x96f9, + 0x703c => 0x9704, 0x703d => 0x9706, 0x703e => 0x9708, 0x703f => 0x9713, + 0x7040 => 0x970e, 0x7041 => 0x9711, 0x7042 => 0x970f, 0x7043 => 0x9716, + 0x7044 => 0x9719, 0x7045 => 0x9724, 0x7046 => 0x972a, 0x7047 => 0x9730, + 0x7048 => 0x9739, 0x7049 => 0x973d, 0x704a => 0x973e, 0x704b => 0x9744, + 0x704c => 0x9746, 0x704d => 0x9748, 0x704e => 0x9742, 0x704f => 0x9749, + 0x7050 => 0x975c, 0x7051 => 0x9760, 0x7052 => 0x9764, 0x7053 => 0x9766, + 0x7054 => 0x9768, 0x7055 => 0x52d2, 0x7056 => 0x976b, 0x7057 => 0x9771, + 0x7058 => 0x9779, 0x7059 => 0x9785, 0x705a => 0x977c, 0x705b => 0x9781, + 0x705c => 0x977a, 0x705d => 0x9786, 0x705e => 0x978b, 0x705f => 0x978f, + 0x7060 => 0x9790, 0x7061 => 0x979c, 0x7062 => 0x97a8, 0x7063 => 0x97a6, + 0x7064 => 0x97a3, 0x7065 => 0x97b3, 0x7066 => 0x97b4, 0x7067 => 0x97c3, + 0x7068 => 0x97c6, 0x7069 => 0x97c8, 0x706a => 0x97cb, 0x706b => 0x97dc, + 0x706c => 0x97ed, 0x706d => 0x9f4f, 0x706e => 0x97f2, 0x706f => 0x7adf, + 0x7070 => 0x97f6, 0x7071 => 0x97f5, 0x7072 => 0x980f, 0x7073 => 0x980c, + 0x7074 => 0x9838, 0x7075 => 0x9824, 0x7076 => 0x9821, 0x7077 => 0x9837, + 0x7078 => 0x983d, 0x7079 => 0x9846, 0x707a => 0x984f, 0x707b => 0x984b, + 0x707c => 0x986b, 0x707d => 0x986f, 0x707e => 0x9870, 0x7121 => 0x9871, + 0x7122 => 0x9874, 0x7123 => 0x9873, 0x7124 => 0x98aa, 0x7125 => 0x98af, + 0x7126 => 0x98b1, 0x7127 => 0x98b6, 0x7128 => 0x98c4, 0x7129 => 0x98c3, + 0x712a => 0x98c6, 0x712b => 0x98e9, 0x712c => 0x98eb, 0x712d => 0x9903, + 0x712e => 0x9909, 0x712f => 0x9912, 0x7130 => 0x9914, 0x7131 => 0x9918, + 0x7132 => 0x9921, 0x7133 => 0x991d, 0x7134 => 0x991e, 0x7135 => 0x9924, + 0x7136 => 0x9920, 0x7137 => 0x992c, 0x7138 => 0x992e, 0x7139 => 0x993d, + 0x713a => 0x993e, 0x713b => 0x9942, 0x713c => 0x9949, 0x713d => 0x9945, + 0x713e => 0x9950, 0x713f => 0x994b, 0x7140 => 0x9951, 0x7141 => 0x9952, + 0x7142 => 0x994c, 0x7143 => 0x9955, 0x7144 => 0x9997, 0x7145 => 0x9998, + 0x7146 => 0x99a5, 0x7147 => 0x99ad, 0x7148 => 0x99ae, 0x7149 => 0x99bc, + 0x714a => 0x99df, 0x714b => 0x99db, 0x714c => 0x99dd, 0x714d => 0x99d8, + 0x714e => 0x99d1, 0x714f => 0x99ed, 0x7150 => 0x99ee, 0x7151 => 0x99f1, + 0x7152 => 0x99f2, 0x7153 => 0x99fb, 0x7154 => 0x99f8, 0x7155 => 0x9a01, + 0x7156 => 0x9a0f, 0x7157 => 0x9a05, 0x7158 => 0x99e2, 0x7159 => 0x9a19, + 0x715a => 0x9a2b, 0x715b => 0x9a37, 0x715c => 0x9a45, 0x715d => 0x9a42, + 0x715e => 0x9a40, 0x715f => 0x9a43, 0x7160 => 0x9a3e, 0x7161 => 0x9a55, + 0x7162 => 0x9a4d, 0x7163 => 0x9a5b, 0x7164 => 0x9a57, 0x7165 => 0x9a5f, + 0x7166 => 0x9a62, 0x7167 => 0x9a65, 0x7168 => 0x9a64, 0x7169 => 0x9a69, + 0x716a => 0x9a6b, 0x716b => 0x9a6a, 0x716c => 0x9aad, 0x716d => 0x9ab0, + 0x716e => 0x9abc, 0x716f => 0x9ac0, 0x7170 => 0x9acf, 0x7171 => 0x9ad1, + 0x7172 => 0x9ad3, 0x7173 => 0x9ad4, 0x7174 => 0x9ade, 0x7175 => 0x9adf, + 0x7176 => 0x9ae2, 0x7177 => 0x9ae3, 0x7178 => 0x9ae6, 0x7179 => 0x9aef, + 0x717a => 0x9aeb, 0x717b => 0x9aee, 0x717c => 0x9af4, 0x717d => 0x9af1, + 0x717e => 0x9af7, 0x7221 => 0x9afb, 0x7222 => 0x9b06, 0x7223 => 0x9b18, + 0x7224 => 0x9b1a, 0x7225 => 0x9b1f, 0x7226 => 0x9b22, 0x7227 => 0x9b23, + 0x7228 => 0x9b25, 0x7229 => 0x9b27, 0x722a => 0x9b28, 0x722b => 0x9b29, + 0x722c => 0x9b2a, 0x722d => 0x9b2e, 0x722e => 0x9b2f, 0x722f => 0x9b32, + 0x7230 => 0x9b44, 0x7231 => 0x9b43, 0x7232 => 0x9b4f, 0x7233 => 0x9b4d, + 0x7234 => 0x9b4e, 0x7235 => 0x9b51, 0x7236 => 0x9b58, 0x7237 => 0x9b74, + 0x7238 => 0x9b93, 0x7239 => 0x9b83, 0x723a => 0x9b91, 0x723b => 0x9b96, + 0x723c => 0x9b97, 0x723d => 0x9b9f, 0x723e => 0x9ba0, 0x723f => 0x9ba8, + 0x7240 => 0x9bb4, 0x7241 => 0x9bc0, 0x7242 => 0x9bca, 0x7243 => 0x9bb9, + 0x7244 => 0x9bc6, 0x7245 => 0x9bcf, 0x7246 => 0x9bd1, 0x7247 => 0x9bd2, + 0x7248 => 0x9be3, 0x7249 => 0x9be2, 0x724a => 0x9be4, 0x724b => 0x9bd4, + 0x724c => 0x9be1, 0x724d => 0x9c3a, 0x724e => 0x9bf2, 0x724f => 0x9bf1, + 0x7250 => 0x9bf0, 0x7251 => 0x9c15, 0x7252 => 0x9c14, 0x7253 => 0x9c09, + 0x7254 => 0x9c13, 0x7255 => 0x9c0c, 0x7256 => 0x9c06, 0x7257 => 0x9c08, + 0x7258 => 0x9c12, 0x7259 => 0x9c0a, 0x725a => 0x9c04, 0x725b => 0x9c2e, + 0x725c => 0x9c1b, 0x725d => 0x9c25, 0x725e => 0x9c24, 0x725f => 0x9c21, + 0x7260 => 0x9c30, 0x7261 => 0x9c47, 0x7262 => 0x9c32, 0x7263 => 0x9c46, + 0x7264 => 0x9c3e, 0x7265 => 0x9c5a, 0x7266 => 0x9c60, 0x7267 => 0x9c67, + 0x7268 => 0x9c76, 0x7269 => 0x9c78, 0x726a => 0x9ce7, 0x726b => 0x9cec, + 0x726c => 0x9cf0, 0x726d => 0x9d09, 0x726e => 0x9d08, 0x726f => 0x9ceb, + 0x7270 => 0x9d03, 0x7271 => 0x9d06, 0x7272 => 0x9d2a, 0x7273 => 0x9d26, + 0x7274 => 0x9daf, 0x7275 => 0x9d23, 0x7276 => 0x9d1f, 0x7277 => 0x9d44, + 0x7278 => 0x9d15, 0x7279 => 0x9d12, 0x727a => 0x9d41, 0x727b => 0x9d3f, + 0x727c => 0x9d3e, 0x727d => 0x9d46, 0x727e => 0x9d48, 0x7321 => 0x9d5d, + 0x7322 => 0x9d5e, 0x7323 => 0x9d64, 0x7324 => 0x9d51, 0x7325 => 0x9d50, + 0x7326 => 0x9d59, 0x7327 => 0x9d72, 0x7328 => 0x9d89, 0x7329 => 0x9d87, + 0x732a => 0x9dab, 0x732b => 0x9d6f, 0x732c => 0x9d7a, 0x732d => 0x9d9a, + 0x732e => 0x9da4, 0x732f => 0x9da9, 0x7330 => 0x9db2, 0x7331 => 0x9dc4, + 0x7332 => 0x9dc1, 0x7333 => 0x9dbb, 0x7334 => 0x9db8, 0x7335 => 0x9dba, + 0x7336 => 0x9dc6, 0x7337 => 0x9dcf, 0x7338 => 0x9dc2, 0x7339 => 0x9dd9, + 0x733a => 0x9dd3, 0x733b => 0x9df8, 0x733c => 0x9de6, 0x733d => 0x9ded, + 0x733e => 0x9def, 0x733f => 0x9dfd, 0x7340 => 0x9e1a, 0x7341 => 0x9e1b, + 0x7342 => 0x9e1e, 0x7343 => 0x9e75, 0x7344 => 0x9e79, 0x7345 => 0x9e7d, + 0x7346 => 0x9e81, 0x7347 => 0x9e88, 0x7348 => 0x9e8b, 0x7349 => 0x9e8c, + 0x734a => 0x9e92, 0x734b => 0x9e95, 0x734c => 0x9e91, 0x734d => 0x9e9d, + 0x734e => 0x9ea5, 0x734f => 0x9ea9, 0x7350 => 0x9eb8, 0x7351 => 0x9eaa, + 0x7352 => 0x9ead, 0x7353 => 0x9761, 0x7354 => 0x9ecc, 0x7355 => 0x9ece, + 0x7356 => 0x9ecf, 0x7357 => 0x9ed0, 0x7358 => 0x9ed4, 0x7359 => 0x9edc, + 0x735a => 0x9ede, 0x735b => 0x9edd, 0x735c => 0x9ee0, 0x735d => 0x9ee5, + 0x735e => 0x9ee8, 0x735f => 0x9eef, 0x7360 => 0x9ef4, 0x7361 => 0x9ef6, + 0x7362 => 0x9ef7, 0x7363 => 0x9ef9, 0x7364 => 0x9efb, 0x7365 => 0x9efc, + 0x7366 => 0x9efd, 0x7367 => 0x9f07, 0x7368 => 0x9f08, 0x7369 => 0x76b7, + 0x736a => 0x9f15, 0x736b => 0x9f21, 0x736c => 0x9f2c, 0x736d => 0x9f3e, + 0x736e => 0x9f4a, 0x736f => 0x9f52, 0x7370 => 0x9f54, 0x7371 => 0x9f63, + 0x7372 => 0x9f5f, 0x7373 => 0x9f60, 0x7374 => 0x9f61, 0x7375 => 0x9f66, + 0x7376 => 0x9f67, 0x7377 => 0x9f6c, 0x7378 => 0x9f6a, 0x7379 => 0x9f77, + 0x737a => 0x9f72, 0x737b => 0x9f76, 0x737c => 0x9f95, 0x737d => 0x9f9c, + 0x737e => 0x9fa0, 0x7421 => 0x582f, 0x7422 => 0x69c7, 0x7423 => 0x9059, + 0x7424 => 0x7464, 0x7425 => 0x51dc, 0x7426 => 0x7199, +); + +1; # end diff --git a/lib/Image/ExifTool/Charset/Latin.pm b/lib/Image/ExifTool/Charset/Latin.pm new file mode 100644 index 0000000..13cad9f --- /dev/null +++ b/lib/Image/ExifTool/Charset/Latin.pm @@ -0,0 +1,24 @@ +#------------------------------------------------------------------------------ +# File: Latin.pm +# +# Description: cp1252 to Unicode +# +# Revisions: 2010/01/20 - P. Harvey created +# +# References: 1) http://unicode.org/Public/MAPPINGS/VENDORS/MICSFT/WINDOWS/CP1252.TXT +# +# Notes: The table omits 1-byte characters with the same values as Unicode +#------------------------------------------------------------------------------ +use strict; + +%Image::ExifTool::Charset::Latin = ( + 0x80 => 0x20ac, 0x82 => 0x201a, 0x83 => 0x0192, 0x84 => 0x201e, + 0x85 => 0x2026, 0x86 => 0x2020, 0x87 => 0x2021, 0x88 => 0x02c6, + 0x89 => 0x2030, 0x8a => 0x0160, 0x8b => 0x2039, 0x8c => 0x0152, + 0x8e => 0x017d, 0x91 => 0x2018, 0x92 => 0x2019, 0x93 => 0x201c, + 0x94 => 0x201d, 0x95 => 0x2022, 0x96 => 0x2013, 0x97 => 0x2014, + 0x98 => 0x02dc, 0x99 => 0x2122, 0x9a => 0x0161, 0x9b => 0x203a, + 0x9c => 0x0153, 0x9e => 0x017e, 0x9f => 0x0178, +); + +1; # end diff --git a/lib/Image/ExifTool/Charset/Latin2.pm b/lib/Image/ExifTool/Charset/Latin2.pm new file mode 100644 index 0000000..1f8432e --- /dev/null +++ b/lib/Image/ExifTool/Charset/Latin2.pm @@ -0,0 +1,36 @@ +#------------------------------------------------------------------------------ +# File: Latin2.pm +# +# Description: cp1250 to Unicode +# +# Revisions: 2010/01/20 - P. Harvey created +# +# References: 1) http://unicode.org/Public/MAPPINGS/VENDORS/MICSFT/WINDOWS/CP1250.TXT +# +# Notes: The table omits 1-byte characters with the same values as Unicode +#------------------------------------------------------------------------------ +use strict; + +%Image::ExifTool::Charset::Latin2 = ( + 0x80 => 0x20ac, 0x82 => 0x201a, 0x84 => 0x201e, 0x85 => 0x2026, + 0x86 => 0x2020, 0x87 => 0x2021, 0x89 => 0x2030, 0x8a => 0x0160, + 0x8b => 0x2039, 0x8c => 0x015a, 0x8d => 0x0164, 0x8e => 0x017d, + 0x8f => 0x0179, 0x91 => 0x2018, 0x92 => 0x2019, 0x93 => 0x201c, + 0x94 => 0x201d, 0x95 => 0x2022, 0x96 => 0x2013, 0x97 => 0x2014, + 0x99 => 0x2122, 0x9a => 0x0161, 0x9b => 0x203a, 0x9c => 0x015b, + 0x9d => 0x0165, 0x9e => 0x017e, 0x9f => 0x017a, 0xa1 => 0x02c7, + 0xa2 => 0x02d8, 0xa3 => 0x0141, 0xa5 => 0x0104, 0xaa => 0x015e, + 0xaf => 0x017b, 0xb2 => 0x02db, 0xb3 => 0x0142, 0xb9 => 0x0105, + 0xba => 0x015f, 0xbc => 0x013d, 0xbd => 0x02dd, 0xbe => 0x013e, + 0xbf => 0x017c, 0xc0 => 0x0154, 0xc3 => 0x0102, 0xc5 => 0x0139, + 0xc6 => 0x0106, 0xc8 => 0x010c, 0xca => 0x0118, 0xcc => 0x011a, + 0xcf => 0x010e, 0xd0 => 0x0110, 0xd1 => 0x0143, 0xd2 => 0x0147, + 0xd5 => 0x0150, 0xd8 => 0x0158, 0xd9 => 0x016e, 0xdb => 0x0170, + 0xde => 0x0162, 0xe0 => 0x0155, 0xe3 => 0x0103, 0xe5 => 0x013a, + 0xe6 => 0x0107, 0xe8 => 0x010d, 0xea => 0x0119, 0xec => 0x011b, + 0xef => 0x010f, 0xf0 => 0x0111, 0xf1 => 0x0144, 0xf2 => 0x0148, + 0xf5 => 0x0151, 0xf8 => 0x0159, 0xf9 => 0x016f, 0xfb => 0x0171, + 0xfe => 0x0163, 0xff => 0x02d9, +); + +1; # end diff --git a/lib/Image/ExifTool/Charset/MacArabic.pm b/lib/Image/ExifTool/Charset/MacArabic.pm new file mode 100644 index 0000000..05c22c3 --- /dev/null +++ b/lib/Image/ExifTool/Charset/MacArabic.pm @@ -0,0 +1,47 @@ +#------------------------------------------------------------------------------ +# File: MacArabic.pm +# +# Description: Mac Arabic to Unicode +# +# Revisions: 2010/01/20 - P. Harvey created +# +# References: 1) http://unicode.org/Public/MAPPINGS/VENDORS/APPLE/ARABIC.TXT +# +# Notes: The table omits 1-byte characters with the same values as Unicode +# and directional characters are ignored +#------------------------------------------------------------------------------ +use strict; + +%Image::ExifTool::Charset::MacArabic = ( + 0x80 => 0xc4, 0x81 => 0xa0, 0x82 => 0xc7, 0x83 => 0xc9, 0x84 => 0xd1, + 0x85 => 0xd6, 0x86 => 0xdc, 0x87 => 0xe1, 0x88 => 0xe0, 0x89 => 0xe2, + 0x8a => 0xe4, 0x8b => 0x06ba, 0x8c => 0xab, 0x8d => 0xe7, 0x8e => 0xe9, + 0x8f => 0xe8, 0x90 => 0xea, 0x91 => 0xeb, 0x92 => 0xed, 0x93 => 0x2026, + 0x94 => 0xee, 0x95 => 0xef, 0x96 => 0xf1, 0x97 => 0xf3, 0x98 => 0xbb, + 0x99 => 0xf4, 0x9a => 0xf6, 0x9b => 0xf7, 0x9c => 0xfa, 0x9d => 0xf9, + 0x9e => 0xfb, 0x9f => 0xfc, 0xa0 => 0x20, 0xa1 => 0x21, 0xa2 => 0x22, + 0xa3 => 0x23, 0xa4 => 0x24, 0xa5 => 0x066a, 0xa6 => 0x26, 0xa7 => 0x27, + 0xa8 => 0x28, 0xa9 => 0x29, 0xaa => 0x2a, 0xab => 0x2b, 0xac => 0x060c, + 0xad => 0x2d, 0xae => 0x2e, 0xaf => 0x2f, 0xb0 => 0x0660, 0xb1 => 0x0661, + 0xb2 => 0x0662, 0xb3 => 0x0663, 0xb4 => 0x0664, 0xb5 => 0x0665, + 0xb6 => 0x0666, 0xb7 => 0x0667, 0xb8 => 0x0668, 0xb9 => 0x0669, 0xba => 0x3a, + 0xbb => 0x061b, 0xbc => 0x3c, 0xbd => 0x3d, 0xbe => 0x3e, 0xbf => 0x061f, + 0xc0 => 0x274a, 0xc1 => 0x0621, 0xc2 => 0x0622, 0xc3 => 0x0623, + 0xc4 => 0x0624, 0xc5 => 0x0625, 0xc6 => 0x0626, 0xc7 => 0x0627, + 0xc8 => 0x0628, 0xc9 => 0x0629, 0xca => 0x062a, 0xcb => 0x062b, + 0xcc => 0x062c, 0xcd => 0x062d, 0xce => 0x062e, 0xcf => 0x062f, + 0xd0 => 0x0630, 0xd1 => 0x0631, 0xd2 => 0x0632, 0xd3 => 0x0633, + 0xd4 => 0x0634, 0xd5 => 0x0635, 0xd6 => 0x0636, 0xd7 => 0x0637, + 0xd8 => 0x0638, 0xd9 => 0x0639, 0xda => 0x063a, 0xdb => 0x5b, 0xdc => 0x5c, + 0xdd => 0x5d, 0xde => 0x5e, 0xdf => 0x5f, 0xe0 => 0x0640, 0xe1 => 0x0641, + 0xe2 => 0x0642, 0xe3 => 0x0643, 0xe4 => 0x0644, 0xe5 => 0x0645, + 0xe6 => 0x0646, 0xe7 => 0x0647, 0xe8 => 0x0648, 0xe9 => 0x0649, + 0xea => 0x064a, 0xeb => 0x064b, 0xec => 0x064c, 0xed => 0x064d, + 0xee => 0x064e, 0xef => 0x064f, 0xf0 => 0x0650, 0xf1 => 0x0651, + 0xf2 => 0x0652, 0xf3 => 0x067e, 0xf4 => 0x0679, 0xf5 => 0x0686, + 0xf6 => 0x06d5, 0xf7 => 0x06a4, 0xf8 => 0x06af, 0xf9 => 0x0688, + 0xfa => 0x0691, 0xfb => 0x7b, 0xfc => 0x7c, 0xfd => 0x7d, 0xfe => 0x0698, + 0xff => 0x06d2, +); + +1; # end diff --git a/lib/Image/ExifTool/Charset/MacChineseCN.pm b/lib/Image/ExifTool/Charset/MacChineseCN.pm new file mode 100644 index 0000000..5c70e0e --- /dev/null +++ b/lib/Image/ExifTool/Charset/MacChineseCN.pm @@ -0,0 +1,2088 @@ +#------------------------------------------------------------------------------ +# File: MacChineseCN.pm +# +# Description: Mac Chinese Simplified to Unicode +# +# Revisions: 2010/01/20 - P. Harvey created +# +# References: 1) http://unicode.org/Public/MAPPINGS/VENDORS/APPLE/CHINSIMP.TXT +# +# Notes: The table omits 1-byte characters with the same values as Unicode +#------------------------------------------------------------------------------ +use strict; + +%Image::ExifTool::Charset::MacChineseCN = ( + 0x80 => [0xfc,0xf87f], 0x81 => 0xf880, 0x82 => 0xf881, 0xfd => 0xa9, + 0xfe => 0x2122, 0xff => 0x2026, + 0xa1 => { + 0xa1 => 0x3000, 0xa2 => 0x3001, 0xa3 => 0x3002, 0xa4 => 0xb7, + 0xa5 => 0x02c9, 0xa6 => 0x02c7, 0xa7 => 0xa8, 0xa8 => 0x3003, + 0xa9 => 0x3005, 0xaa => 0x2014, 0xab => 0x301c, 0xac => 0x2016, + 0xad => 0x22ef, 0xae => 0x2018, 0xaf => 0x2019, 0xb0 => 0x201c, + 0xb1 => 0x201d, 0xb2 => 0x3014, 0xb3 => 0x3015, 0xb4 => 0x3008, + 0xb5 => 0x3009, 0xb6 => 0x300a, 0xb7 => 0x300b, 0xb8 => 0x300c, + 0xb9 => 0x300d, 0xba => 0x300e, 0xbb => 0x300f, 0xbc => 0x3016, + 0xbd => 0x3017, 0xbe => 0x3010, 0xbf => 0x3011, 0xc0 => 0xb1, 0xc1 => 0xd7, + 0xc2 => 0xf7, 0xc3 => 0x2236, 0xc4 => 0x2227, 0xc5 => 0x2228, + 0xc6 => 0x2211, 0xc7 => 0x220f, 0xc8 => 0x222a, 0xc9 => 0x2229, + 0xca => 0x2208, 0xcb => 0x2237, 0xcc => 0x221a, 0xcd => 0x22a5, + 0xce => 0x2225, 0xcf => 0x2220, 0xd0 => 0x2312, 0xd1 => 0x2299, + 0xd2 => 0x222b, 0xd3 => 0x222e, 0xd4 => 0x2261, 0xd5 => 0x224c, + 0xd6 => 0x2248, 0xd7 => 0x223d, 0xd8 => 0x221d, 0xd9 => 0x2260, + 0xda => 0x226e, 0xdb => 0x226f, 0xdc => 0x2264, 0xdd => 0x2265, + 0xde => 0x221e, 0xdf => 0x2235, 0xe0 => 0x2234, 0xe1 => 0x2642, + 0xe2 => 0x2640, 0xe3 => 0xb0, 0xe4 => 0x2032, 0xe5 => 0x2033, + 0xe6 => 0x2103, 0xe7 => 0xff04, 0xe8 => 0xa4, 0xe9 => 0xa2, 0xea => 0xa3, + 0xeb => 0x2030, 0xec => 0xa7, 0xed => 0x2116, 0xee => 0x2606, + 0xef => 0x2605, 0xf0 => 0x25cb, 0xf1 => 0x25cf, 0xf2 => 0x25ce, + 0xf3 => 0x25c7, 0xf4 => 0x25c6, 0xf5 => 0x25a1, 0xf6 => 0x25a0, + 0xf7 => 0x25b3, 0xf8 => 0x25b2, 0xf9 => 0x203b, 0xfa => 0x2192, + 0xfb => 0x2190, 0xfc => 0x2191, 0xfd => 0x2193, 0xfe => 0x3013, + }, + 0xa2 => { + 0xb1 => 0x2488, 0xb2 => 0x2489, 0xb3 => 0x248a, 0xb4 => 0x248b, + 0xb5 => 0x248c, 0xb6 => 0x248d, 0xb7 => 0x248e, 0xb8 => 0x248f, + 0xb9 => 0x2490, 0xba => 0x2491, 0xbb => 0x2492, 0xbc => 0x2493, + 0xbd => 0x2494, 0xbe => 0x2495, 0xbf => 0x2496, 0xc0 => 0x2497, + 0xc1 => 0x2498, 0xc2 => 0x2499, 0xc3 => 0x249a, 0xc4 => 0x249b, + 0xc5 => 0x2474, 0xc6 => 0x2475, 0xc7 => 0x2476, 0xc8 => 0x2477, + 0xc9 => 0x2478, 0xca => 0x2479, 0xcb => 0x247a, 0xcc => 0x247b, + 0xcd => 0x247c, 0xce => 0x247d, 0xcf => 0x247e, 0xd0 => 0x247f, + 0xd1 => 0x2480, 0xd2 => 0x2481, 0xd3 => 0x2482, 0xd4 => 0x2483, + 0xd5 => 0x2484, 0xd6 => 0x2485, 0xd7 => 0x2486, 0xd8 => 0x2487, + 0xd9 => 0x2460, 0xda => 0x2461, 0xdb => 0x2462, 0xdc => 0x2463, + 0xdd => 0x2464, 0xde => 0x2465, 0xdf => 0x2466, 0xe0 => 0x2467, + 0xe1 => 0x2468, 0xe2 => 0x2469, 0xe5 => 0x3220, 0xe6 => 0x3221, + 0xe7 => 0x3222, 0xe8 => 0x3223, 0xe9 => 0x3224, 0xea => 0x3225, + 0xeb => 0x3226, 0xec => 0x3227, 0xed => 0x3228, 0xee => 0x3229, + 0xf1 => 0x2160, 0xf2 => 0x2161, 0xf3 => 0x2162, 0xf4 => 0x2163, + 0xf5 => 0x2164, 0xf6 => 0x2165, 0xf7 => 0x2166, 0xf8 => 0x2167, + 0xf9 => 0x2168, 0xfa => 0x2169, 0xfb => 0x216a, 0xfc => 0x216b, + }, + 0xa3 => { + 0xa1 => 0xff01, 0xa2 => 0xff02, 0xa3 => 0xff03, 0xa4 => 0xa5, + 0xa5 => 0xff05, 0xa6 => 0xff06, 0xa7 => 0xff07, 0xa8 => 0xff08, + 0xa9 => 0xff09, 0xaa => 0xff0a, 0xab => 0xff0b, 0xac => 0xff0c, + 0xad => 0xff0d, 0xae => 0xff0e, 0xaf => 0xff0f, 0xb0 => 0xff10, + 0xb1 => 0xff11, 0xb2 => 0xff12, 0xb3 => 0xff13, 0xb4 => 0xff14, + 0xb5 => 0xff15, 0xb6 => 0xff16, 0xb7 => 0xff17, 0xb8 => 0xff18, + 0xb9 => 0xff19, 0xba => 0xff1a, 0xbb => 0xff1b, 0xbc => 0xff1c, + 0xbd => 0xff1d, 0xbe => 0xff1e, 0xbf => 0xff1f, 0xc0 => 0xff20, + 0xc1 => 0xff21, 0xc2 => 0xff22, 0xc3 => 0xff23, 0xc4 => 0xff24, + 0xc5 => 0xff25, 0xc6 => 0xff26, 0xc7 => 0xff27, 0xc8 => 0xff28, + 0xc9 => 0xff29, 0xca => 0xff2a, 0xcb => 0xff2b, 0xcc => 0xff2c, + 0xcd => 0xff2d, 0xce => 0xff2e, 0xcf => 0xff2f, 0xd0 => 0xff30, + 0xd1 => 0xff31, 0xd2 => 0xff32, 0xd3 => 0xff33, 0xd4 => 0xff34, + 0xd5 => 0xff35, 0xd6 => 0xff36, 0xd7 => 0xff37, 0xd8 => 0xff38, + 0xd9 => 0xff39, 0xda => 0xff3a, 0xdb => 0xff3b, 0xdc => 0xff3c, + 0xdd => 0xff3d, 0xde => 0xff3e, 0xdf => 0xff3f, 0xe0 => 0xff40, + 0xe1 => 0xff41, 0xe2 => 0xff42, 0xe3 => 0xff43, 0xe4 => 0xff44, + 0xe5 => 0xff45, 0xe6 => 0xff46, 0xe7 => 0xff47, 0xe8 => 0xff48, + 0xe9 => 0xff49, 0xea => 0xff4a, 0xeb => 0xff4b, 0xec => 0xff4c, + 0xed => 0xff4d, 0xee => 0xff4e, 0xef => 0xff4f, 0xf0 => 0xff50, + 0xf1 => 0xff51, 0xf2 => 0xff52, 0xf3 => 0xff53, 0xf4 => 0xff54, + 0xf5 => 0xff55, 0xf6 => 0xff56, 0xf7 => 0xff57, 0xf8 => 0xff58, + 0xf9 => 0xff59, 0xfa => 0xff5a, 0xfb => 0xff5b, 0xfc => 0xff5c, + 0xfd => 0xff5d, 0xfe => 0x203e, + }, + 0xa4 => { + 0xa1 => 0x3041, 0xa2 => 0x3042, 0xa3 => 0x3043, 0xa4 => 0x3044, + 0xa5 => 0x3045, 0xa6 => 0x3046, 0xa7 => 0x3047, 0xa8 => 0x3048, + 0xa9 => 0x3049, 0xaa => 0x304a, 0xab => 0x304b, 0xac => 0x304c, + 0xad => 0x304d, 0xae => 0x304e, 0xaf => 0x304f, 0xb0 => 0x3050, + 0xb1 => 0x3051, 0xb2 => 0x3052, 0xb3 => 0x3053, 0xb4 => 0x3054, + 0xb5 => 0x3055, 0xb6 => 0x3056, 0xb7 => 0x3057, 0xb8 => 0x3058, + 0xb9 => 0x3059, 0xba => 0x305a, 0xbb => 0x305b, 0xbc => 0x305c, + 0xbd => 0x305d, 0xbe => 0x305e, 0xbf => 0x305f, 0xc0 => 0x3060, + 0xc1 => 0x3061, 0xc2 => 0x3062, 0xc3 => 0x3063, 0xc4 => 0x3064, + 0xc5 => 0x3065, 0xc6 => 0x3066, 0xc7 => 0x3067, 0xc8 => 0x3068, + 0xc9 => 0x3069, 0xca => 0x306a, 0xcb => 0x306b, 0xcc => 0x306c, + 0xcd => 0x306d, 0xce => 0x306e, 0xcf => 0x306f, 0xd0 => 0x3070, + 0xd1 => 0x3071, 0xd2 => 0x3072, 0xd3 => 0x3073, 0xd4 => 0x3074, + 0xd5 => 0x3075, 0xd6 => 0x3076, 0xd7 => 0x3077, 0xd8 => 0x3078, + 0xd9 => 0x3079, 0xda => 0x307a, 0xdb => 0x307b, 0xdc => 0x307c, + 0xdd => 0x307d, 0xde => 0x307e, 0xdf => 0x307f, 0xe0 => 0x3080, + 0xe1 => 0x3081, 0xe2 => 0x3082, 0xe3 => 0x3083, 0xe4 => 0x3084, + 0xe5 => 0x3085, 0xe6 => 0x3086, 0xe7 => 0x3087, 0xe8 => 0x3088, + 0xe9 => 0x3089, 0xea => 0x308a, 0xeb => 0x308b, 0xec => 0x308c, + 0xed => 0x308d, 0xee => 0x308e, 0xef => 0x308f, 0xf0 => 0x3090, + 0xf1 => 0x3091, 0xf2 => 0x3092, 0xf3 => 0x3093, + }, + 0xa5 => { + 0xa1 => 0x30a1, 0xa2 => 0x30a2, 0xa3 => 0x30a3, 0xa4 => 0x30a4, + 0xa5 => 0x30a5, 0xa6 => 0x30a6, 0xa7 => 0x30a7, 0xa8 => 0x30a8, + 0xa9 => 0x30a9, 0xaa => 0x30aa, 0xab => 0x30ab, 0xac => 0x30ac, + 0xad => 0x30ad, 0xae => 0x30ae, 0xaf => 0x30af, 0xb0 => 0x30b0, + 0xb1 => 0x30b1, 0xb2 => 0x30b2, 0xb3 => 0x30b3, 0xb4 => 0x30b4, + 0xb5 => 0x30b5, 0xb6 => 0x30b6, 0xb7 => 0x30b7, 0xb8 => 0x30b8, + 0xb9 => 0x30b9, 0xba => 0x30ba, 0xbb => 0x30bb, 0xbc => 0x30bc, + 0xbd => 0x30bd, 0xbe => 0x30be, 0xbf => 0x30bf, 0xc0 => 0x30c0, + 0xc1 => 0x30c1, 0xc2 => 0x30c2, 0xc3 => 0x30c3, 0xc4 => 0x30c4, + 0xc5 => 0x30c5, 0xc6 => 0x30c6, 0xc7 => 0x30c7, 0xc8 => 0x30c8, + 0xc9 => 0x30c9, 0xca => 0x30ca, 0xcb => 0x30cb, 0xcc => 0x30cc, + 0xcd => 0x30cd, 0xce => 0x30ce, 0xcf => 0x30cf, 0xd0 => 0x30d0, + 0xd1 => 0x30d1, 0xd2 => 0x30d2, 0xd3 => 0x30d3, 0xd4 => 0x30d4, + 0xd5 => 0x30d5, 0xd6 => 0x30d6, 0xd7 => 0x30d7, 0xd8 => 0x30d8, + 0xd9 => 0x30d9, 0xda => 0x30da, 0xdb => 0x30db, 0xdc => 0x30dc, + 0xdd => 0x30dd, 0xde => 0x30de, 0xdf => 0x30df, 0xe0 => 0x30e0, + 0xe1 => 0x30e1, 0xe2 => 0x30e2, 0xe3 => 0x30e3, 0xe4 => 0x30e4, + 0xe5 => 0x30e5, 0xe6 => 0x30e6, 0xe7 => 0x30e7, 0xe8 => 0x30e8, + 0xe9 => 0x30e9, 0xea => 0x30ea, 0xeb => 0x30eb, 0xec => 0x30ec, + 0xed => 0x30ed, 0xee => 0x30ee, 0xef => 0x30ef, 0xf0 => 0x30f0, + 0xf1 => 0x30f1, 0xf2 => 0x30f2, 0xf3 => 0x30f3, 0xf4 => 0x30f4, + 0xf5 => 0x30f5, 0xf6 => 0x30f6, + }, + 0xa6 => { + 0xa1 => 0x0391, 0xa2 => 0x0392, 0xa3 => 0x0393, 0xa4 => 0x0394, + 0xa5 => 0x0395, 0xa6 => 0x0396, 0xa7 => 0x0397, 0xa8 => 0x0398, + 0xa9 => 0x0399, 0xaa => 0x039a, 0xab => 0x039b, 0xac => 0x039c, + 0xad => 0x039d, 0xae => 0x039e, 0xaf => 0x039f, 0xb0 => 0x03a0, + 0xb1 => 0x03a1, 0xb2 => 0x03a3, 0xb3 => 0x03a4, 0xb4 => 0x03a5, + 0xb5 => 0x03a6, 0xb6 => 0x03a7, 0xb7 => 0x03a8, 0xb8 => 0x03a9, + 0xc1 => 0x03b1, 0xc2 => 0x03b2, 0xc3 => 0x03b3, 0xc4 => 0x03b4, + 0xc5 => 0x03b5, 0xc6 => 0x03b6, 0xc7 => 0x03b7, 0xc8 => 0x03b8, + 0xc9 => 0x03b9, 0xca => 0x03ba, 0xcb => 0x03bb, 0xcc => 0x03bc, + 0xcd => 0x03bd, 0xce => 0x03be, 0xcf => 0x03bf, 0xd0 => 0x03c0, + 0xd1 => 0x03c1, 0xd2 => 0x03c3, 0xd3 => 0x03c4, 0xd4 => 0x03c5, + 0xd5 => 0x03c6, 0xd6 => 0x03c7, 0xd7 => 0x03c8, 0xd8 => 0x03c9, + 0xd9 => [0xff0c,0xf87e], 0xda => [0x3002,0xf87e], 0xdb => [0x3001,0xf87e], + 0xdc => [0xff1a,0xf87e], 0xdd => [0xff1b,0xf87e], 0xde => [0xff01,0xf87e], + 0xdf => [0xff1f,0xf87e], 0xe0 => 0xfe35, 0xe1 => 0xfe36, 0xe2 => 0xfe39, + 0xe3 => 0xfe3a, 0xe4 => 0xfe3f, 0xe5 => 0xfe40, 0xe6 => 0xfe3d, + 0xe7 => 0xfe3e, 0xe8 => 0xfe41, 0xe9 => 0xfe42, 0xea => 0xfe43, + 0xeb => 0xfe44, 0xec => [0x3016,0xf87e], 0xed => [0x3017,0xf87e], + 0xee => 0xfe3b, 0xef => 0xfe3c, 0xf0 => 0xfe37, 0xf1 => 0xfe38, + 0xf2 => 0xfe31, 0xf3 => [0x22ef,0xf87e], 0xf4 => 0xfe33, 0xf5 => 0xfe34, + }, + 0xa7 => { + 0xa1 => 0x0410, 0xa2 => 0x0411, 0xa3 => 0x0412, 0xa4 => 0x0413, + 0xa5 => 0x0414, 0xa6 => 0x0415, 0xa7 => 0x0401, 0xa8 => 0x0416, + 0xa9 => 0x0417, 0xaa => 0x0418, 0xab => 0x0419, 0xac => 0x041a, + 0xad => 0x041b, 0xae => 0x041c, 0xaf => 0x041d, 0xb0 => 0x041e, + 0xb1 => 0x041f, 0xb2 => 0x0420, 0xb3 => 0x0421, 0xb4 => 0x0422, + 0xb5 => 0x0423, 0xb6 => 0x0424, 0xb7 => 0x0425, 0xb8 => 0x0426, + 0xb9 => 0x0427, 0xba => 0x0428, 0xbb => 0x0429, 0xbc => 0x042a, + 0xbd => 0x042b, 0xbe => 0x042c, 0xbf => 0x042d, 0xc0 => 0x042e, + 0xc1 => 0x042f, 0xd1 => 0x0430, 0xd2 => 0x0431, 0xd3 => 0x0432, + 0xd4 => 0x0433, 0xd5 => 0x0434, 0xd6 => 0x0435, 0xd7 => 0x0451, + 0xd8 => 0x0436, 0xd9 => 0x0437, 0xda => 0x0438, 0xdb => 0x0439, + 0xdc => 0x043a, 0xdd => 0x043b, 0xde => 0x043c, 0xdf => 0x043d, + 0xe0 => 0x043e, 0xe1 => 0x043f, 0xe2 => 0x0440, 0xe3 => 0x0441, + 0xe4 => 0x0442, 0xe5 => 0x0443, 0xe6 => 0x0444, 0xe7 => 0x0445, + 0xe8 => 0x0446, 0xe9 => 0x0447, 0xea => 0x0448, 0xeb => 0x0449, + 0xec => 0x044a, 0xed => 0x044b, 0xee => 0x044c, 0xef => 0x044d, + 0xf0 => 0x044e, 0xf1 => 0x044f, + }, + 0xa8 => { + 0xa1 => 0x0101, 0xa2 => 0xe1, 0xa3 => 0x01ce, 0xa4 => 0xe0, 0xa5 => 0x0113, + 0xa6 => 0xe9, 0xa7 => 0x011b, 0xa8 => 0xe8, 0xa9 => 0x012b, 0xaa => 0xed, + 0xab => 0x01d0, 0xac => 0xec, 0xad => 0x014d, 0xae => 0xf3, 0xaf => 0x01d2, + 0xb0 => 0xf2, 0xb1 => 0x016b, 0xb2 => 0xfa, 0xb3 => 0x01d4, 0xb4 => 0xf9, + 0xb5 => 0x01d6, 0xb6 => 0x01d8, 0xb7 => 0x01da, 0xb8 => 0x01dc, + 0xb9 => 0xfc, 0xba => 0xea, 0xbb => 0x0251, 0xbc => 0x1e3f, 0xbd => 0x0144, + 0xbe => 0x0148, 0xbf => 0x01f9, 0xc0 => 0x0261, 0xc5 => 0x3105, + 0xc6 => 0x3106, 0xc7 => 0x3107, 0xc8 => 0x3108, 0xc9 => 0x3109, + 0xca => 0x310a, 0xcb => 0x310b, 0xcc => 0x310c, 0xcd => 0x310d, + 0xce => 0x310e, 0xcf => 0x310f, 0xd0 => 0x3110, 0xd1 => 0x3111, + 0xd2 => 0x3112, 0xd3 => 0x3113, 0xd4 => 0x3114, 0xd5 => 0x3115, + 0xd6 => 0x3116, 0xd7 => 0x3117, 0xd8 => 0x3118, 0xd9 => 0x3119, + 0xda => 0x311a, 0xdb => 0x311b, 0xdc => 0x311c, 0xdd => 0x311d, + 0xde => 0x311e, 0xdf => 0x311f, 0xe0 => 0x3120, 0xe1 => 0x3121, + 0xe2 => 0x3122, 0xe3 => 0x3123, 0xe4 => 0x3124, 0xe5 => 0x3125, + 0xe6 => 0x3126, 0xe7 => 0x3127, 0xe8 => 0x3128, 0xe9 => 0x3129, + }, + 0xa9 => { + 0xa4 => 0x2500, 0xa5 => 0x2501, 0xa6 => 0x2502, 0xa7 => 0x2503, + 0xa8 => 0x2504, 0xa9 => 0x2505, 0xaa => 0x2506, 0xab => 0x2507, + 0xac => 0x2508, 0xad => 0x2509, 0xae => 0x250a, 0xaf => 0x250b, + 0xb0 => 0x250c, 0xb1 => 0x250d, 0xb2 => 0x250e, 0xb3 => 0x250f, + 0xb4 => 0x2510, 0xb5 => 0x2511, 0xb6 => 0x2512, 0xb7 => 0x2513, + 0xb8 => 0x2514, 0xb9 => 0x2515, 0xba => 0x2516, 0xbb => 0x2517, + 0xbc => 0x2518, 0xbd => 0x2519, 0xbe => 0x251a, 0xbf => 0x251b, + 0xc0 => 0x251c, 0xc1 => 0x251d, 0xc2 => 0x251e, 0xc3 => 0x251f, + 0xc4 => 0x2520, 0xc5 => 0x2521, 0xc6 => 0x2522, 0xc7 => 0x2523, + 0xc8 => 0x2524, 0xc9 => 0x2525, 0xca => 0x2526, 0xcb => 0x2527, + 0xcc => 0x2528, 0xcd => 0x2529, 0xce => 0x252a, 0xcf => 0x252b, + 0xd0 => 0x252c, 0xd1 => 0x252d, 0xd2 => 0x252e, 0xd3 => 0x252f, + 0xd4 => 0x2530, 0xd5 => 0x2531, 0xd6 => 0x2532, 0xd7 => 0x2533, + 0xd8 => 0x2534, 0xd9 => 0x2535, 0xda => 0x2536, 0xdb => 0x2537, + 0xdc => 0x2538, 0xdd => 0x2539, 0xde => 0x253a, 0xdf => 0x253b, + 0xe0 => 0x253c, 0xe1 => 0x253d, 0xe2 => 0x253e, 0xe3 => 0x253f, + 0xe4 => 0x2540, 0xe5 => 0x2541, 0xe6 => 0x2542, 0xe7 => 0x2543, + 0xe8 => 0x2544, 0xe9 => 0x2545, 0xea => 0x2546, 0xeb => 0x2547, + 0xec => 0x2548, 0xed => 0x2549, 0xee => 0x254a, 0xef => 0x254b, + }, + 0xb0 => { + 0xa1 => 0x554a, 0xa2 => 0x963f, 0xa3 => 0x57c3, 0xa4 => 0x6328, + 0xa5 => 0x54ce, 0xa6 => 0x5509, 0xa7 => 0x54c0, 0xa8 => 0x7691, + 0xa9 => 0x764c, 0xaa => 0x853c, 0xab => 0x77ee, 0xac => 0x827e, + 0xad => 0x788d, 0xae => 0x7231, 0xaf => 0x9698, 0xb0 => 0x978d, + 0xb1 => 0x6c28, 0xb2 => 0x5b89, 0xb3 => 0x4ffa, 0xb4 => 0x6309, + 0xb5 => 0x6697, 0xb6 => 0x5cb8, 0xb7 => 0x80fa, 0xb8 => 0x6848, + 0xb9 => 0x80ae, 0xba => 0x6602, 0xbb => 0x76ce, 0xbc => 0x51f9, + 0xbd => 0x6556, 0xbe => 0x71ac, 0xbf => 0x7ff1, 0xc0 => 0x8884, + 0xc1 => 0x50b2, 0xc2 => 0x5965, 0xc3 => 0x61ca, 0xc4 => 0x6fb3, + 0xc5 => 0x82ad, 0xc6 => 0x634c, 0xc7 => 0x6252, 0xc8 => 0x53ed, + 0xc9 => 0x5427, 0xca => 0x7b06, 0xcb => 0x516b, 0xcc => 0x75a4, + 0xcd => 0x5df4, 0xce => 0x62d4, 0xcf => 0x8dcb, 0xd0 => 0x9776, + 0xd1 => 0x628a, 0xd2 => 0x8019, 0xd3 => 0x575d, 0xd4 => 0x9738, + 0xd5 => 0x7f62, 0xd6 => 0x7238, 0xd7 => 0x767d, 0xd8 => 0x67cf, + 0xd9 => 0x767e, 0xda => 0x6446, 0xdb => 0x4f70, 0xdc => 0x8d25, + 0xdd => 0x62dc, 0xde => 0x7a17, 0xdf => 0x6591, 0xe0 => 0x73ed, + 0xe1 => 0x642c, 0xe2 => 0x6273, 0xe3 => 0x822c, 0xe4 => 0x9881, + 0xe5 => 0x677f, 0xe6 => 0x7248, 0xe7 => 0x626e, 0xe8 => 0x62cc, + 0xe9 => 0x4f34, 0xea => 0x74e3, 0xeb => 0x534a, 0xec => 0x529e, + 0xed => 0x7eca, 0xee => 0x90a6, 0xef => 0x5e2e, 0xf0 => 0x6886, + 0xf1 => 0x699c, 0xf2 => 0x8180, 0xf3 => 0x7ed1, 0xf4 => 0x68d2, + 0xf5 => 0x78c5, 0xf6 => 0x868c, 0xf7 => 0x9551, 0xf8 => 0x508d, + 0xf9 => 0x8c24, 0xfa => 0x82de, 0xfb => 0x80de, 0xfc => 0x5305, + 0xfd => 0x8912, 0xfe => 0x5265, + }, + 0xb1 => { + 0xa1 => 0x8584, 0xa2 => 0x96f9, 0xa3 => 0x4fdd, 0xa4 => 0x5821, + 0xa5 => 0x9971, 0xa6 => 0x5b9d, 0xa7 => 0x62b1, 0xa8 => 0x62a5, + 0xa9 => 0x66b4, 0xaa => 0x8c79, 0xab => 0x9c8d, 0xac => 0x7206, + 0xad => 0x676f, 0xae => 0x7891, 0xaf => 0x60b2, 0xb0 => 0x5351, + 0xb1 => 0x5317, 0xb2 => 0x8f88, 0xb3 => 0x80cc, 0xb4 => 0x8d1d, + 0xb5 => 0x94a1, 0xb6 => 0x500d, 0xb7 => 0x72c8, 0xb8 => 0x5907, + 0xb9 => 0x60eb, 0xba => 0x7119, 0xbb => 0x88ab, 0xbc => 0x5954, + 0xbd => 0x82ef, 0xbe => 0x672c, 0xbf => 0x7b28, 0xc0 => 0x5d29, + 0xc1 => 0x7ef7, 0xc2 => 0x752d, 0xc3 => 0x6cf5, 0xc4 => 0x8e66, + 0xc5 => 0x8ff8, 0xc6 => 0x903c, 0xc7 => 0x9f3b, 0xc8 => 0x6bd4, + 0xc9 => 0x9119, 0xca => 0x7b14, 0xcb => 0x5f7c, 0xcc => 0x78a7, + 0xcd => 0x84d6, 0xce => 0x853d, 0xcf => 0x6bd5, 0xd0 => 0x6bd9, + 0xd1 => 0x6bd6, 0xd2 => 0x5e01, 0xd3 => 0x5e87, 0xd4 => 0x75f9, + 0xd5 => 0x95ed, 0xd6 => 0x655d, 0xd7 => 0x5f0a, 0xd8 => 0x5fc5, + 0xd9 => 0x8f9f, 0xda => 0x58c1, 0xdb => 0x81c2, 0xdc => 0x907f, + 0xdd => 0x965b, 0xde => 0x97ad, 0xdf => 0x8fb9, 0xe0 => 0x7f16, + 0xe1 => 0x8d2c, 0xe2 => 0x6241, 0xe3 => 0x4fbf, 0xe4 => 0x53d8, + 0xe5 => 0x535e, 0xe6 => 0x8fa8, 0xe7 => 0x8fa9, 0xe8 => 0x8fab, + 0xe9 => 0x904d, 0xea => 0x6807, 0xeb => 0x5f6a, 0xec => 0x8198, + 0xed => 0x8868, 0xee => 0x9cd6, 0xef => 0x618b, 0xf0 => 0x522b, + 0xf1 => 0x762a, 0xf2 => 0x5f6c, 0xf3 => 0x658c, 0xf4 => 0x6fd2, + 0xf5 => 0x6ee8, 0xf6 => 0x5bbe, 0xf7 => 0x6448, 0xf8 => 0x5175, + 0xf9 => 0x51b0, 0xfa => 0x67c4, 0xfb => 0x4e19, 0xfc => 0x79c9, + 0xfd => 0x997c, 0xfe => 0x70b3, + }, + 0xb2 => { + 0xa1 => 0x75c5, 0xa2 => 0x5e76, 0xa3 => 0x73bb, 0xa4 => 0x83e0, + 0xa5 => 0x64ad, 0xa6 => 0x62e8, 0xa7 => 0x94b5, 0xa8 => 0x6ce2, + 0xa9 => 0x535a, 0xaa => 0x52c3, 0xab => 0x640f, 0xac => 0x94c2, + 0xad => 0x7b94, 0xae => 0x4f2f, 0xaf => 0x5e1b, 0xb0 => 0x8236, + 0xb1 => 0x8116, 0xb2 => 0x818a, 0xb3 => 0x6e24, 0xb4 => 0x6cca, + 0xb5 => 0x9a73, 0xb6 => 0x6355, 0xb7 => 0x535c, 0xb8 => 0x54fa, + 0xb9 => 0x8865, 0xba => 0x57e0, 0xbb => 0x4e0d, 0xbc => 0x5e03, + 0xbd => 0x6b65, 0xbe => 0x7c3f, 0xbf => 0x90e8, 0xc0 => 0x6016, + 0xc1 => 0x64e6, 0xc2 => 0x731c, 0xc3 => 0x88c1, 0xc4 => 0x6750, + 0xc5 => 0x624d, 0xc6 => 0x8d22, 0xc7 => 0x776c, 0xc8 => 0x8e29, + 0xc9 => 0x91c7, 0xca => 0x5f69, 0xcb => 0x83dc, 0xcc => 0x8521, + 0xcd => 0x9910, 0xce => 0x53c2, 0xcf => 0x8695, 0xd0 => 0x6b8b, + 0xd1 => 0x60ed, 0xd2 => 0x60e8, 0xd3 => 0x707f, 0xd4 => 0x82cd, + 0xd5 => 0x8231, 0xd6 => 0x4ed3, 0xd7 => 0x6ca7, 0xd8 => 0x85cf, + 0xd9 => 0x64cd, 0xda => 0x7cd9, 0xdb => 0x69fd, 0xdc => 0x66f9, + 0xdd => 0x8349, 0xde => 0x5395, 0xdf => 0x7b56, 0xe0 => 0x4fa7, + 0xe1 => 0x518c, 0xe2 => 0x6d4b, 0xe3 => 0x5c42, 0xe4 => 0x8e6d, + 0xe5 => 0x63d2, 0xe6 => 0x53c9, 0xe7 => 0x832c, 0xe8 => 0x8336, + 0xe9 => 0x67e5, 0xea => 0x78b4, 0xeb => 0x643d, 0xec => 0x5bdf, + 0xed => 0x5c94, 0xee => 0x5dee, 0xef => 0x8be7, 0xf0 => 0x62c6, + 0xf1 => 0x67f4, 0xf2 => 0x8c7a, 0xf3 => 0x6400, 0xf4 => 0x63ba, + 0xf5 => 0x8749, 0xf6 => 0x998b, 0xf7 => 0x8c17, 0xf8 => 0x7f20, + 0xf9 => 0x94f2, 0xfa => 0x4ea7, 0xfb => 0x9610, 0xfc => 0x98a4, + 0xfd => 0x660c, 0xfe => 0x7316, + }, + 0xb3 => { + 0xa1 => 0x573a, 0xa2 => 0x5c1d, 0xa3 => 0x5e38, 0xa4 => 0x957f, + 0xa5 => 0x507f, 0xa6 => 0x80a0, 0xa7 => 0x5382, 0xa8 => 0x655e, + 0xa9 => 0x7545, 0xaa => 0x5531, 0xab => 0x5021, 0xac => 0x8d85, + 0xad => 0x6284, 0xae => 0x949e, 0xaf => 0x671d, 0xb0 => 0x5632, + 0xb1 => 0x6f6e, 0xb2 => 0x5de2, 0xb3 => 0x5435, 0xb4 => 0x7092, + 0xb5 => 0x8f66, 0xb6 => 0x626f, 0xb7 => 0x64a4, 0xb8 => 0x63a3, + 0xb9 => 0x5f7b, 0xba => 0x6f88, 0xbb => 0x90f4, 0xbc => 0x81e3, + 0xbd => 0x8fb0, 0xbe => 0x5c18, 0xbf => 0x6668, 0xc0 => 0x5ff1, + 0xc1 => 0x6c89, 0xc2 => 0x9648, 0xc3 => 0x8d81, 0xc4 => 0x886c, + 0xc5 => 0x6491, 0xc6 => 0x79f0, 0xc7 => 0x57ce, 0xc8 => 0x6a59, + 0xc9 => 0x6210, 0xca => 0x5448, 0xcb => 0x4e58, 0xcc => 0x7a0b, + 0xcd => 0x60e9, 0xce => 0x6f84, 0xcf => 0x8bda, 0xd0 => 0x627f, + 0xd1 => 0x901e, 0xd2 => 0x9a8b, 0xd3 => 0x79e4, 0xd4 => 0x5403, + 0xd5 => 0x75f4, 0xd6 => 0x6301, 0xd7 => 0x5319, 0xd8 => 0x6c60, + 0xd9 => 0x8fdf, 0xda => 0x5f1b, 0xdb => 0x9a70, 0xdc => 0x803b, + 0xdd => 0x9f7f, 0xde => 0x4f88, 0xdf => 0x5c3a, 0xe0 => 0x8d64, + 0xe1 => 0x7fc5, 0xe2 => 0x65a5, 0xe3 => 0x70bd, 0xe4 => 0x5145, + 0xe5 => 0x51b2, 0xe6 => 0x866b, 0xe7 => 0x5d07, 0xe8 => 0x5ba0, + 0xe9 => 0x62bd, 0xea => 0x916c, 0xeb => 0x7574, 0xec => 0x8e0c, + 0xed => 0x7a20, 0xee => 0x6101, 0xef => 0x7b79, 0xf0 => 0x4ec7, + 0xf1 => 0x7ef8, 0xf2 => 0x7785, 0xf3 => 0x4e11, 0xf4 => 0x81ed, + 0xf5 => 0x521d, 0xf6 => 0x51fa, 0xf7 => 0x6a71, 0xf8 => 0x53a8, + 0xf9 => 0x8e87, 0xfa => 0x9504, 0xfb => 0x96cf, 0xfc => 0x6ec1, + 0xfd => 0x9664, 0xfe => 0x695a, + }, + 0xb4 => { + 0xa1 => 0x7840, 0xa2 => 0x50a8, 0xa3 => 0x77d7, 0xa4 => 0x6410, + 0xa5 => 0x89e6, 0xa6 => 0x5904, 0xa7 => 0x63e3, 0xa8 => 0x5ddd, + 0xa9 => 0x7a7f, 0xaa => 0x693d, 0xab => 0x4f20, 0xac => 0x8239, + 0xad => 0x5598, 0xae => 0x4e32, 0xaf => 0x75ae, 0xb0 => 0x7a97, + 0xb1 => 0x5e62, 0xb2 => 0x5e8a, 0xb3 => 0x95ef, 0xb4 => 0x521b, + 0xb5 => 0x5439, 0xb6 => 0x708a, 0xb7 => 0x6376, 0xb8 => 0x9524, + 0xb9 => 0x5782, 0xba => 0x6625, 0xbb => 0x693f, 0xbc => 0x9187, + 0xbd => 0x5507, 0xbe => 0x6df3, 0xbf => 0x7eaf, 0xc0 => 0x8822, + 0xc1 => 0x6233, 0xc2 => 0x7ef0, 0xc3 => 0x75b5, 0xc4 => 0x8328, + 0xc5 => 0x78c1, 0xc6 => 0x96cc, 0xc7 => 0x8f9e, 0xc8 => 0x6148, + 0xc9 => 0x74f7, 0xca => 0x8bcd, 0xcb => 0x6b64, 0xcc => 0x523a, + 0xcd => 0x8d50, 0xce => 0x6b21, 0xcf => 0x806a, 0xd0 => 0x8471, + 0xd1 => 0x56f1, 0xd2 => 0x5306, 0xd3 => 0x4ece, 0xd4 => 0x4e1b, + 0xd5 => 0x51d1, 0xd6 => 0x7c97, 0xd7 => 0x918b, 0xd8 => 0x7c07, + 0xd9 => 0x4fc3, 0xda => 0x8e7f, 0xdb => 0x7be1, 0xdc => 0x7a9c, + 0xdd => 0x6467, 0xde => 0x5d14, 0xdf => 0x50ac, 0xe0 => 0x8106, + 0xe1 => 0x7601, 0xe2 => 0x7cb9, 0xe3 => 0x6dec, 0xe4 => 0x7fe0, + 0xe5 => 0x6751, 0xe6 => 0x5b58, 0xe7 => 0x5bf8, 0xe8 => 0x78cb, + 0xe9 => 0x64ae, 0xea => 0x6413, 0xeb => 0x63aa, 0xec => 0x632b, + 0xed => 0x9519, 0xee => 0x642d, 0xef => 0x8fbe, 0xf0 => 0x7b54, + 0xf1 => 0x7629, 0xf2 => 0x6253, 0xf3 => 0x5927, 0xf4 => 0x5446, + 0xf5 => 0x6b79, 0xf6 => 0x50a3, 0xf7 => 0x6234, 0xf8 => 0x5e26, + 0xf9 => 0x6b86, 0xfa => 0x4ee3, 0xfb => 0x8d37, 0xfc => 0x888b, + 0xfd => 0x5f85, 0xfe => 0x902e, + }, + 0xb5 => { + 0xa1 => 0x6020, 0xa2 => 0x803d, 0xa3 => 0x62c5, 0xa4 => 0x4e39, + 0xa5 => 0x5355, 0xa6 => 0x90f8, 0xa7 => 0x63b8, 0xa8 => 0x80c6, + 0xa9 => 0x65e6, 0xaa => 0x6c2e, 0xab => 0x4f46, 0xac => 0x60ee, + 0xad => 0x6de1, 0xae => 0x8bde, 0xaf => 0x5f39, 0xb0 => 0x86cb, + 0xb1 => 0x5f53, 0xb2 => 0x6321, 0xb3 => 0x515a, 0xb4 => 0x8361, + 0xb5 => 0x6863, 0xb6 => 0x5200, 0xb7 => 0x6363, 0xb8 => 0x8e48, + 0xb9 => 0x5012, 0xba => 0x5c9b, 0xbb => 0x7977, 0xbc => 0x5bfc, + 0xbd => 0x5230, 0xbe => 0x7a3b, 0xbf => 0x60bc, 0xc0 => 0x9053, + 0xc1 => 0x76d7, 0xc2 => 0x5fb7, 0xc3 => 0x5f97, 0xc4 => 0x7684, + 0xc5 => 0x8e6c, 0xc6 => 0x706f, 0xc7 => 0x767b, 0xc8 => 0x7b49, + 0xc9 => 0x77aa, 0xca => 0x51f3, 0xcb => 0x9093, 0xcc => 0x5824, + 0xcd => 0x4f4e, 0xce => 0x6ef4, 0xcf => 0x8fea, 0xd0 => 0x654c, + 0xd1 => 0x7b1b, 0xd2 => 0x72c4, 0xd3 => 0x6da4, 0xd4 => 0x7fdf, + 0xd5 => 0x5ae1, 0xd6 => 0x62b5, 0xd7 => 0x5e95, 0xd8 => 0x5730, + 0xd9 => 0x8482, 0xda => 0x7b2c, 0xdb => 0x5e1d, 0xdc => 0x5f1f, + 0xdd => 0x9012, 0xde => 0x7f14, 0xdf => 0x98a0, 0xe0 => 0x6382, + 0xe1 => 0x6ec7, 0xe2 => 0x7898, 0xe3 => 0x70b9, 0xe4 => 0x5178, + 0xe5 => 0x975b, 0xe6 => 0x57ab, 0xe7 => 0x7535, 0xe8 => 0x4f43, + 0xe9 => 0x7538, 0xea => 0x5e97, 0xeb => 0x60e6, 0xec => 0x5960, + 0xed => 0x6dc0, 0xee => 0x6bbf, 0xef => 0x7889, 0xf0 => 0x53fc, + 0xf1 => 0x96d5, 0xf2 => 0x51cb, 0xf3 => 0x5201, 0xf4 => 0x6389, + 0xf5 => 0x540a, 0xf6 => 0x9493, 0xf7 => 0x8c03, 0xf8 => 0x8dcc, + 0xf9 => 0x7239, 0xfa => 0x789f, 0xfb => 0x8776, 0xfc => 0x8fed, + 0xfd => 0x8c0d, 0xfe => 0x53e0, + }, + 0xb6 => { + 0xa1 => 0x4e01, 0xa2 => 0x76ef, 0xa3 => 0x53ee, 0xa4 => 0x9489, + 0xa5 => 0x9876, 0xa6 => 0x9f0e, 0xa7 => 0x952d, 0xa8 => 0x5b9a, + 0xa9 => 0x8ba2, 0xaa => 0x4e22, 0xab => 0x4e1c, 0xac => 0x51ac, + 0xad => 0x8463, 0xae => 0x61c2, 0xaf => 0x52a8, 0xb0 => 0x680b, + 0xb1 => 0x4f97, 0xb2 => 0x606b, 0xb3 => 0x51bb, 0xb4 => 0x6d1e, + 0xb5 => 0x515c, 0xb6 => 0x6296, 0xb7 => 0x6597, 0xb8 => 0x9661, + 0xb9 => 0x8c46, 0xba => 0x9017, 0xbb => 0x75d8, 0xbc => 0x90fd, + 0xbd => 0x7763, 0xbe => 0x6bd2, 0xbf => 0x728a, 0xc0 => 0x72ec, + 0xc1 => 0x8bfb, 0xc2 => 0x5835, 0xc3 => 0x7779, 0xc4 => 0x8d4c, + 0xc5 => 0x675c, 0xc6 => 0x9540, 0xc7 => 0x809a, 0xc8 => 0x5ea6, + 0xc9 => 0x6e21, 0xca => 0x5992, 0xcb => 0x7aef, 0xcc => 0x77ed, + 0xcd => 0x953b, 0xce => 0x6bb5, 0xcf => 0x65ad, 0xd0 => 0x7f0e, + 0xd1 => 0x5806, 0xd2 => 0x5151, 0xd3 => 0x961f, 0xd4 => 0x5bf9, + 0xd5 => 0x58a9, 0xd6 => 0x5428, 0xd7 => 0x8e72, 0xd8 => 0x6566, + 0xd9 => 0x987f, 0xda => 0x56e4, 0xdb => 0x949d, 0xdc => 0x76fe, + 0xdd => 0x9041, 0xde => 0x6387, 0xdf => 0x54c6, 0xe0 => 0x591a, + 0xe1 => 0x593a, 0xe2 => 0x579b, 0xe3 => 0x8eb2, 0xe4 => 0x6735, + 0xe5 => 0x8dfa, 0xe6 => 0x8235, 0xe7 => 0x5241, 0xe8 => 0x60f0, + 0xe9 => 0x5815, 0xea => 0x86fe, 0xeb => 0x5ce8, 0xec => 0x9e45, + 0xed => 0x4fc4, 0xee => 0x989d, 0xef => 0x8bb9, 0xf0 => 0x5a25, + 0xf1 => 0x6076, 0xf2 => 0x5384, 0xf3 => 0x627c, 0xf4 => 0x904f, + 0xf5 => 0x9102, 0xf6 => 0x997f, 0xf7 => 0x6069, 0xf8 => 0x800c, + 0xf9 => 0x513f, 0xfa => 0x8033, 0xfb => 0x5c14, 0xfc => 0x9975, + 0xfd => 0x6d31, 0xfe => 0x4e8c, + }, + 0xb7 => { + 0xa1 => 0x8d30, 0xa2 => 0x53d1, 0xa3 => 0x7f5a, 0xa4 => 0x7b4f, + 0xa5 => 0x4f10, 0xa6 => 0x4e4f, 0xa7 => 0x9600, 0xa8 => 0x6cd5, + 0xa9 => 0x73d0, 0xaa => 0x85e9, 0xab => 0x5e06, 0xac => 0x756a, + 0xad => 0x7ffb, 0xae => 0x6a0a, 0xaf => 0x77fe, 0xb0 => 0x9492, + 0xb1 => 0x7e41, 0xb2 => 0x51e1, 0xb3 => 0x70e6, 0xb4 => 0x53cd, + 0xb5 => 0x8fd4, 0xb6 => 0x8303, 0xb7 => 0x8d29, 0xb8 => 0x72af, + 0xb9 => 0x996d, 0xba => 0x6cdb, 0xbb => 0x574a, 0xbc => 0x82b3, + 0xbd => 0x65b9, 0xbe => 0x80aa, 0xbf => 0x623f, 0xc0 => 0x9632, + 0xc1 => 0x59a8, 0xc2 => 0x4eff, 0xc3 => 0x8bbf, 0xc4 => 0x7eba, + 0xc5 => 0x653e, 0xc6 => 0x83f2, 0xc7 => 0x975e, 0xc8 => 0x5561, + 0xc9 => 0x98de, 0xca => 0x80a5, 0xcb => 0x532a, 0xcc => 0x8bfd, + 0xcd => 0x5420, 0xce => 0x80ba, 0xcf => 0x5e9f, 0xd0 => 0x6cb8, + 0xd1 => 0x8d39, 0xd2 => 0x82ac, 0xd3 => 0x915a, 0xd4 => 0x5429, + 0xd5 => 0x6c1b, 0xd6 => 0x5206, 0xd7 => 0x7eb7, 0xd8 => 0x575f, + 0xd9 => 0x711a, 0xda => 0x6c7e, 0xdb => 0x7c89, 0xdc => 0x594b, + 0xdd => 0x4efd, 0xde => 0x5fff, 0xdf => 0x6124, 0xe0 => 0x7caa, + 0xe1 => 0x4e30, 0xe2 => 0x5c01, 0xe3 => 0x67ab, 0xe4 => 0x8702, + 0xe5 => 0x5cf0, 0xe6 => 0x950b, 0xe7 => 0x98ce, 0xe8 => 0x75af, + 0xe9 => 0x70fd, 0xea => 0x9022, 0xeb => 0x51af, 0xec => 0x7f1d, + 0xed => 0x8bbd, 0xee => 0x5949, 0xef => 0x51e4, 0xf0 => 0x4f5b, + 0xf1 => 0x5426, 0xf2 => 0x592b, 0xf3 => 0x6577, 0xf4 => 0x80a4, + 0xf5 => 0x5b75, 0xf6 => 0x6276, 0xf7 => 0x62c2, 0xf8 => 0x8f90, + 0xf9 => 0x5e45, 0xfa => 0x6c1f, 0xfb => 0x7b26, 0xfc => 0x4f0f, + 0xfd => 0x4fd8, 0xfe => 0x670d, + }, + 0xb8 => { + 0xa1 => 0x6d6e, 0xa2 => 0x6daa, 0xa3 => 0x798f, 0xa4 => 0x88b1, + 0xa5 => 0x5f17, 0xa6 => 0x752b, 0xa7 => 0x629a, 0xa8 => 0x8f85, + 0xa9 => 0x4fef, 0xaa => 0x91dc, 0xab => 0x65a7, 0xac => 0x812f, + 0xad => 0x8151, 0xae => 0x5e9c, 0xaf => 0x8150, 0xb0 => 0x8d74, + 0xb1 => 0x526f, 0xb2 => 0x8986, 0xb3 => 0x8d4b, 0xb4 => 0x590d, + 0xb5 => 0x5085, 0xb6 => 0x4ed8, 0xb7 => 0x961c, 0xb8 => 0x7236, + 0xb9 => 0x8179, 0xba => 0x8d1f, 0xbb => 0x5bcc, 0xbc => 0x8ba3, + 0xbd => 0x9644, 0xbe => 0x5987, 0xbf => 0x7f1a, 0xc0 => 0x5490, + 0xc1 => 0x5676, 0xc2 => 0x560e, 0xc3 => 0x8be5, 0xc4 => 0x6539, + 0xc5 => 0x6982, 0xc6 => 0x9499, 0xc7 => 0x76d6, 0xc8 => 0x6e89, + 0xc9 => 0x5e72, 0xca => 0x7518, 0xcb => 0x6746, 0xcc => 0x67d1, + 0xcd => 0x7aff, 0xce => 0x809d, 0xcf => 0x8d76, 0xd0 => 0x611f, + 0xd1 => 0x79c6, 0xd2 => 0x6562, 0xd3 => 0x8d63, 0xd4 => 0x5188, + 0xd5 => 0x521a, 0xd6 => 0x94a2, 0xd7 => 0x7f38, 0xd8 => 0x809b, + 0xd9 => 0x7eb2, 0xda => 0x5c97, 0xdb => 0x6e2f, 0xdc => 0x6760, + 0xdd => 0x7bd9, 0xde => 0x768b, 0xdf => 0x9ad8, 0xe0 => 0x818f, + 0xe1 => 0x7f94, 0xe2 => 0x7cd5, 0xe3 => 0x641e, 0xe4 => 0x9550, + 0xe5 => 0x7a3f, 0xe6 => 0x544a, 0xe7 => 0x54e5, 0xe8 => 0x6b4c, + 0xe9 => 0x6401, 0xea => 0x6208, 0xeb => 0x9e3d, 0xec => 0x80f3, + 0xed => 0x7599, 0xee => 0x5272, 0xef => 0x9769, 0xf0 => 0x845b, + 0xf1 => 0x683c, 0xf2 => 0x86e4, 0xf3 => 0x9601, 0xf4 => 0x9694, + 0xf5 => 0x94ec, 0xf6 => 0x4e2a, 0xf7 => 0x5404, 0xf8 => 0x7ed9, + 0xf9 => 0x6839, 0xfa => 0x8ddf, 0xfb => 0x8015, 0xfc => 0x66f4, + 0xfd => 0x5e9a, 0xfe => 0x7fb9, + }, + 0xb9 => { + 0xa1 => 0x57c2, 0xa2 => 0x803f, 0xa3 => 0x6897, 0xa4 => 0x5de5, + 0xa5 => 0x653b, 0xa6 => 0x529f, 0xa7 => 0x606d, 0xa8 => 0x9f9a, + 0xa9 => 0x4f9b, 0xaa => 0x8eac, 0xab => 0x516c, 0xac => 0x5bab, + 0xad => 0x5f13, 0xae => 0x5de9, 0xaf => 0x6c5e, 0xb0 => 0x62f1, + 0xb1 => 0x8d21, 0xb2 => 0x5171, 0xb3 => 0x94a9, 0xb4 => 0x52fe, + 0xb5 => 0x6c9f, 0xb6 => 0x82df, 0xb7 => 0x72d7, 0xb8 => 0x57a2, + 0xb9 => 0x6784, 0xba => 0x8d2d, 0xbb => 0x591f, 0xbc => 0x8f9c, + 0xbd => 0x83c7, 0xbe => 0x5495, 0xbf => 0x7b8d, 0xc0 => 0x4f30, + 0xc1 => 0x6cbd, 0xc2 => 0x5b64, 0xc3 => 0x59d1, 0xc4 => 0x9f13, + 0xc5 => 0x53e4, 0xc6 => 0x86ca, 0xc7 => 0x9aa8, 0xc8 => 0x8c37, + 0xc9 => 0x80a1, 0xca => 0x6545, 0xcb => 0x987e, 0xcc => 0x56fa, + 0xcd => 0x96c7, 0xce => 0x522e, 0xcf => 0x74dc, 0xd0 => 0x5250, + 0xd1 => 0x5be1, 0xd2 => 0x6302, 0xd3 => 0x8902, 0xd4 => 0x4e56, + 0xd5 => 0x62d0, 0xd6 => 0x602a, 0xd7 => 0x68fa, 0xd8 => 0x5173, + 0xd9 => 0x5b98, 0xda => 0x51a0, 0xdb => 0x89c2, 0xdc => 0x7ba1, + 0xdd => 0x9986, 0xde => 0x7f50, 0xdf => 0x60ef, 0xe0 => 0x704c, + 0xe1 => 0x8d2f, 0xe2 => 0x5149, 0xe3 => 0x5e7f, 0xe4 => 0x901b, + 0xe5 => 0x7470, 0xe6 => 0x89c4, 0xe7 => 0x572d, 0xe8 => 0x7845, + 0xe9 => 0x5f52, 0xea => 0x9f9f, 0xeb => 0x95fa, 0xec => 0x8f68, + 0xed => 0x9b3c, 0xee => 0x8be1, 0xef => 0x7678, 0xf0 => 0x6842, + 0xf1 => 0x67dc, 0xf2 => 0x8dea, 0xf3 => 0x8d35, 0xf4 => 0x523d, + 0xf5 => 0x8f8a, 0xf6 => 0x6eda, 0xf7 => 0x68cd, 0xf8 => 0x9505, + 0xf9 => 0x90ed, 0xfa => 0x56fd, 0xfb => 0x679c, 0xfc => 0x88f9, + 0xfd => 0x8fc7, 0xfe => 0x54c8, + }, + 0xba => { + 0xa1 => 0x9ab8, 0xa2 => 0x5b69, 0xa3 => 0x6d77, 0xa4 => 0x6c26, + 0xa5 => 0x4ea5, 0xa6 => 0x5bb3, 0xa7 => 0x9a87, 0xa8 => 0x9163, + 0xa9 => 0x61a8, 0xaa => 0x90af, 0xab => 0x97e9, 0xac => 0x542b, + 0xad => 0x6db5, 0xae => 0x5bd2, 0xaf => 0x51fd, 0xb0 => 0x558a, + 0xb1 => 0x7f55, 0xb2 => 0x7ff0, 0xb3 => 0x64bc, 0xb4 => 0x634d, + 0xb5 => 0x65f1, 0xb6 => 0x61be, 0xb7 => 0x608d, 0xb8 => 0x710a, + 0xb9 => 0x6c57, 0xba => 0x6c49, 0xbb => 0x592f, 0xbc => 0x676d, + 0xbd => 0x822a, 0xbe => 0x58d5, 0xbf => 0x568e, 0xc0 => 0x8c6a, + 0xc1 => 0x6beb, 0xc2 => 0x90dd, 0xc3 => 0x597d, 0xc4 => 0x8017, + 0xc5 => 0x53f7, 0xc6 => 0x6d69, 0xc7 => 0x5475, 0xc8 => 0x559d, + 0xc9 => 0x8377, 0xca => 0x83cf, 0xcb => 0x6838, 0xcc => 0x79be, + 0xcd => 0x548c, 0xce => 0x4f55, 0xcf => 0x5408, 0xd0 => 0x76d2, + 0xd1 => 0x8c89, 0xd2 => 0x9602, 0xd3 => 0x6cb3, 0xd4 => 0x6db8, + 0xd5 => 0x8d6b, 0xd6 => 0x8910, 0xd7 => 0x9e64, 0xd8 => 0x8d3a, + 0xd9 => 0x563f, 0xda => 0x9ed1, 0xdb => 0x75d5, 0xdc => 0x5f88, + 0xdd => 0x72e0, 0xde => 0x6068, 0xdf => 0x54fc, 0xe0 => 0x4ea8, + 0xe1 => 0x6a2a, 0xe2 => 0x8861, 0xe3 => 0x6052, 0xe4 => 0x8f70, + 0xe5 => 0x54c4, 0xe6 => 0x70d8, 0xe7 => 0x8679, 0xe8 => 0x9e3f, + 0xe9 => 0x6d2a, 0xea => 0x5b8f, 0xeb => 0x5f18, 0xec => 0x7ea2, + 0xed => 0x5589, 0xee => 0x4faf, 0xef => 0x7334, 0xf0 => 0x543c, + 0xf1 => 0x539a, 0xf2 => 0x5019, 0xf3 => 0x540e, 0xf4 => 0x547c, + 0xf5 => 0x4e4e, 0xf6 => 0x5ffd, 0xf7 => 0x745a, 0xf8 => 0x58f6, + 0xf9 => 0x846b, 0xfa => 0x80e1, 0xfb => 0x8774, 0xfc => 0x72d0, + 0xfd => 0x7cca, 0xfe => 0x6e56, + }, + 0xbb => { + 0xa1 => 0x5f27, 0xa2 => 0x864e, 0xa3 => 0x552c, 0xa4 => 0x62a4, + 0xa5 => 0x4e92, 0xa6 => 0x6caa, 0xa7 => 0x6237, 0xa8 => 0x82b1, + 0xa9 => 0x54d7, 0xaa => 0x534e, 0xab => 0x733e, 0xac => 0x6ed1, + 0xad => 0x753b, 0xae => 0x5212, 0xaf => 0x5316, 0xb0 => 0x8bdd, + 0xb1 => 0x69d0, 0xb2 => 0x5f8a, 0xb3 => 0x6000, 0xb4 => 0x6dee, + 0xb5 => 0x574f, 0xb6 => 0x6b22, 0xb7 => 0x73af, 0xb8 => 0x6853, + 0xb9 => 0x8fd8, 0xba => 0x7f13, 0xbb => 0x6362, 0xbc => 0x60a3, + 0xbd => 0x5524, 0xbe => 0x75ea, 0xbf => 0x8c62, 0xc0 => 0x7115, + 0xc1 => 0x6da3, 0xc2 => 0x5ba6, 0xc3 => 0x5e7b, 0xc4 => 0x8352, + 0xc5 => 0x614c, 0xc6 => 0x9ec4, 0xc7 => 0x78fa, 0xc8 => 0x8757, + 0xc9 => 0x7c27, 0xca => 0x7687, 0xcb => 0x51f0, 0xcc => 0x60f6, + 0xcd => 0x714c, 0xce => 0x6643, 0xcf => 0x5e4c, 0xd0 => 0x604d, + 0xd1 => 0x8c0e, 0xd2 => 0x7070, 0xd3 => 0x6325, 0xd4 => 0x8f89, + 0xd5 => 0x5fbd, 0xd6 => 0x6062, 0xd7 => 0x86d4, 0xd8 => 0x56de, + 0xd9 => 0x6bc1, 0xda => 0x6094, 0xdb => 0x6167, 0xdc => 0x5349, + 0xdd => 0x60e0, 0xde => 0x6666, 0xdf => 0x8d3f, 0xe0 => 0x79fd, + 0xe1 => 0x4f1a, 0xe2 => 0x70e9, 0xe3 => 0x6c47, 0xe4 => 0x8bb3, + 0xe5 => 0x8bf2, 0xe6 => 0x7ed8, 0xe7 => 0x8364, 0xe8 => 0x660f, + 0xe9 => 0x5a5a, 0xea => 0x9b42, 0xeb => 0x6d51, 0xec => 0x6df7, + 0xed => 0x8c41, 0xee => 0x6d3b, 0xef => 0x4f19, 0xf0 => 0x706b, + 0xf1 => 0x83b7, 0xf2 => 0x6216, 0xf3 => 0x60d1, 0xf4 => 0x970d, + 0xf5 => 0x8d27, 0xf6 => 0x7978, 0xf7 => 0x51fb, 0xf8 => 0x573e, + 0xf9 => 0x57fa, 0xfa => 0x673a, 0xfb => 0x7578, 0xfc => 0x7a3d, + 0xfd => 0x79ef, 0xfe => 0x7b95, + }, + 0xbc => { + 0xa1 => 0x808c, 0xa2 => 0x9965, 0xa3 => 0x8ff9, 0xa4 => 0x6fc0, + 0xa5 => 0x8ba5, 0xa6 => 0x9e21, 0xa7 => 0x59ec, 0xa8 => 0x7ee9, + 0xa9 => 0x7f09, 0xaa => 0x5409, 0xab => 0x6781, 0xac => 0x68d8, + 0xad => 0x8f91, 0xae => 0x7c4d, 0xaf => 0x96c6, 0xb0 => 0x53ca, + 0xb1 => 0x6025, 0xb2 => 0x75be, 0xb3 => 0x6c72, 0xb4 => 0x5373, + 0xb5 => 0x5ac9, 0xb6 => 0x7ea7, 0xb7 => 0x6324, 0xb8 => 0x51e0, + 0xb9 => 0x810a, 0xba => 0x5df1, 0xbb => 0x84df, 0xbc => 0x6280, + 0xbd => 0x5180, 0xbe => 0x5b63, 0xbf => 0x4f0e, 0xc0 => 0x796d, + 0xc1 => 0x5242, 0xc2 => 0x60b8, 0xc3 => 0x6d4e, 0xc4 => 0x5bc4, + 0xc5 => 0x5bc2, 0xc6 => 0x8ba1, 0xc7 => 0x8bb0, 0xc8 => 0x65e2, + 0xc9 => 0x5fcc, 0xca => 0x9645, 0xcb => 0x5993, 0xcc => 0x7ee7, + 0xcd => 0x7eaa, 0xce => 0x5609, 0xcf => 0x67b7, 0xd0 => 0x5939, + 0xd1 => 0x4f73, 0xd2 => 0x5bb6, 0xd3 => 0x52a0, 0xd4 => 0x835a, + 0xd5 => 0x988a, 0xd6 => 0x8d3e, 0xd7 => 0x7532, 0xd8 => 0x94be, + 0xd9 => 0x5047, 0xda => 0x7a3c, 0xdb => 0x4ef7, 0xdc => 0x67b6, + 0xdd => 0x9a7e, 0xde => 0x5ac1, 0xdf => 0x6b7c, 0xe0 => 0x76d1, + 0xe1 => 0x575a, 0xe2 => 0x5c16, 0xe3 => 0x7b3a, 0xe4 => 0x95f4, + 0xe5 => 0x714e, 0xe6 => 0x517c, 0xe7 => 0x80a9, 0xe8 => 0x8270, + 0xe9 => 0x5978, 0xea => 0x7f04, 0xeb => 0x8327, 0xec => 0x68c0, + 0xed => 0x67ec, 0xee => 0x78b1, 0xef => 0x7877, 0xf0 => 0x62e3, + 0xf1 => 0x6361, 0xf2 => 0x7b80, 0xf3 => 0x4fed, 0xf4 => 0x526a, + 0xf5 => 0x51cf, 0xf6 => 0x8350, 0xf7 => 0x69db, 0xf8 => 0x9274, + 0xf9 => 0x8df5, 0xfa => 0x8d31, 0xfb => 0x89c1, 0xfc => 0x952e, + 0xfd => 0x7bad, 0xfe => 0x4ef6, + }, + 0xbd => { + 0xa1 => 0x5065, 0xa2 => 0x8230, 0xa3 => 0x5251, 0xa4 => 0x996f, + 0xa5 => 0x6e10, 0xa6 => 0x6e85, 0xa7 => 0x6da7, 0xa8 => 0x5efa, + 0xa9 => 0x50f5, 0xaa => 0x59dc, 0xab => 0x5c06, 0xac => 0x6d46, + 0xad => 0x6c5f, 0xae => 0x7586, 0xaf => 0x848b, 0xb0 => 0x6868, + 0xb1 => 0x5956, 0xb2 => 0x8bb2, 0xb3 => 0x5320, 0xb4 => 0x9171, + 0xb5 => 0x964d, 0xb6 => 0x8549, 0xb7 => 0x6912, 0xb8 => 0x7901, + 0xb9 => 0x7126, 0xba => 0x80f6, 0xbb => 0x4ea4, 0xbc => 0x90ca, + 0xbd => 0x6d47, 0xbe => 0x9a84, 0xbf => 0x5a07, 0xc0 => 0x56bc, + 0xc1 => 0x6405, 0xc2 => 0x94f0, 0xc3 => 0x77eb, 0xc4 => 0x4fa5, + 0xc5 => 0x811a, 0xc6 => 0x72e1, 0xc7 => 0x89d2, 0xc8 => 0x997a, + 0xc9 => 0x7f34, 0xca => 0x7ede, 0xcb => 0x527f, 0xcc => 0x6559, + 0xcd => 0x9175, 0xce => 0x8f7f, 0xcf => 0x8f83, 0xd0 => 0x53eb, + 0xd1 => 0x7a96, 0xd2 => 0x63ed, 0xd3 => 0x63a5, 0xd4 => 0x7686, + 0xd5 => 0x79f8, 0xd6 => 0x8857, 0xd7 => 0x9636, 0xd8 => 0x622a, + 0xd9 => 0x52ab, 0xda => 0x8282, 0xdb => 0x6854, 0xdc => 0x6770, + 0xdd => 0x6377, 0xde => 0x776b, 0xdf => 0x7aed, 0xe0 => 0x6d01, + 0xe1 => 0x7ed3, 0xe2 => 0x89e3, 0xe3 => 0x59d0, 0xe4 => 0x6212, + 0xe5 => 0x85c9, 0xe6 => 0x82a5, 0xe7 => 0x754c, 0xe8 => 0x501f, + 0xe9 => 0x4ecb, 0xea => 0x75a5, 0xeb => 0x8beb, 0xec => 0x5c4a, + 0xed => 0x5dfe, 0xee => 0x7b4b, 0xef => 0x65a4, 0xf0 => 0x91d1, + 0xf1 => 0x4eca, 0xf2 => 0x6d25, 0xf3 => 0x895f, 0xf4 => 0x7d27, + 0xf5 => 0x9526, 0xf6 => 0x4ec5, 0xf7 => 0x8c28, 0xf8 => 0x8fdb, + 0xf9 => 0x9773, 0xfa => 0x664b, 0xfb => 0x7981, 0xfc => 0x8fd1, + 0xfd => 0x70ec, 0xfe => 0x6d78, + }, + 0xbe => { + 0xa1 => 0x5c3d, 0xa2 => 0x52b2, 0xa3 => 0x8346, 0xa4 => 0x5162, + 0xa5 => 0x830e, 0xa6 => 0x775b, 0xa7 => 0x6676, 0xa8 => 0x9cb8, + 0xa9 => 0x4eac, 0xaa => 0x60ca, 0xab => 0x7cbe, 0xac => 0x7cb3, + 0xad => 0x7ecf, 0xae => 0x4e95, 0xaf => 0x8b66, 0xb0 => 0x666f, + 0xb1 => 0x9888, 0xb2 => 0x9759, 0xb3 => 0x5883, 0xb4 => 0x656c, + 0xb5 => 0x955c, 0xb6 => 0x5f84, 0xb7 => 0x75c9, 0xb8 => 0x9756, + 0xb9 => 0x7adf, 0xba => 0x7ade, 0xbb => 0x51c0, 0xbc => 0x70af, + 0xbd => 0x7a98, 0xbe => 0x63ea, 0xbf => 0x7a76, 0xc0 => 0x7ea0, + 0xc1 => 0x7396, 0xc2 => 0x97ed, 0xc3 => 0x4e45, 0xc4 => 0x7078, + 0xc5 => 0x4e5d, 0xc6 => 0x9152, 0xc7 => 0x53a9, 0xc8 => 0x6551, + 0xc9 => 0x65e7, 0xca => 0x81fc, 0xcb => 0x8205, 0xcc => 0x548e, + 0xcd => 0x5c31, 0xce => 0x759a, 0xcf => 0x97a0, 0xd0 => 0x62d8, + 0xd1 => 0x72d9, 0xd2 => 0x75bd, 0xd3 => 0x5c45, 0xd4 => 0x9a79, + 0xd5 => 0x83ca, 0xd6 => 0x5c40, 0xd7 => 0x5480, 0xd8 => 0x77e9, + 0xd9 => 0x4e3e, 0xda => 0x6cae, 0xdb => 0x805a, 0xdc => 0x62d2, + 0xdd => 0x636e, 0xde => 0x5de8, 0xdf => 0x5177, 0xe0 => 0x8ddd, + 0xe1 => 0x8e1e, 0xe2 => 0x952f, 0xe3 => 0x4ff1, 0xe4 => 0x53e5, + 0xe5 => 0x60e7, 0xe6 => 0x70ac, 0xe7 => 0x5267, 0xe8 => 0x6350, + 0xe9 => 0x9e43, 0xea => 0x5a1f, 0xeb => 0x5026, 0xec => 0x7737, + 0xed => 0x5377, 0xee => 0x7ee2, 0xef => 0x6485, 0xf0 => 0x652b, + 0xf1 => 0x6289, 0xf2 => 0x6398, 0xf3 => 0x5014, 0xf4 => 0x7235, + 0xf5 => 0x89c9, 0xf6 => 0x51b3, 0xf7 => 0x8bc0, 0xf8 => 0x7edd, + 0xf9 => 0x5747, 0xfa => 0x83cc, 0xfb => 0x94a7, 0xfc => 0x519b, + 0xfd => 0x541b, 0xfe => 0x5cfb, + }, + 0xbf => { + 0xa1 => 0x4fca, 0xa2 => 0x7ae3, 0xa3 => 0x6d5a, 0xa4 => 0x90e1, + 0xa5 => 0x9a8f, 0xa6 => 0x5580, 0xa7 => 0x5496, 0xa8 => 0x5361, + 0xa9 => 0x54af, 0xaa => 0x5f00, 0xab => 0x63e9, 0xac => 0x6977, + 0xad => 0x51ef, 0xae => 0x6168, 0xaf => 0x520a, 0xb0 => 0x582a, + 0xb1 => 0x52d8, 0xb2 => 0x574e, 0xb3 => 0x780d, 0xb4 => 0x770b, + 0xb5 => 0x5eb7, 0xb6 => 0x6177, 0xb7 => 0x7ce0, 0xb8 => 0x625b, + 0xb9 => 0x6297, 0xba => 0x4ea2, 0xbb => 0x7095, 0xbc => 0x8003, + 0xbd => 0x62f7, 0xbe => 0x70e4, 0xbf => 0x9760, 0xc0 => 0x5777, + 0xc1 => 0x82db, 0xc2 => 0x67ef, 0xc3 => 0x68f5, 0xc4 => 0x78d5, + 0xc5 => 0x9897, 0xc6 => 0x79d1, 0xc7 => 0x58f3, 0xc8 => 0x54b3, + 0xc9 => 0x53ef, 0xca => 0x6e34, 0xcb => 0x514b, 0xcc => 0x523b, + 0xcd => 0x5ba2, 0xce => 0x8bfe, 0xcf => 0x80af, 0xd0 => 0x5543, + 0xd1 => 0x57a6, 0xd2 => 0x6073, 0xd3 => 0x5751, 0xd4 => 0x542d, + 0xd5 => 0x7a7a, 0xd6 => 0x6050, 0xd7 => 0x5b54, 0xd8 => 0x63a7, + 0xd9 => 0x62a0, 0xda => 0x53e3, 0xdb => 0x6263, 0xdc => 0x5bc7, + 0xdd => 0x67af, 0xde => 0x54ed, 0xdf => 0x7a9f, 0xe0 => 0x82e6, + 0xe1 => 0x9177, 0xe2 => 0x5e93, 0xe3 => 0x88e4, 0xe4 => 0x5938, + 0xe5 => 0x57ae, 0xe6 => 0x630e, 0xe7 => 0x8de8, 0xe8 => 0x80ef, + 0xe9 => 0x5757, 0xea => 0x7b77, 0xeb => 0x4fa9, 0xec => 0x5feb, + 0xed => 0x5bbd, 0xee => 0x6b3e, 0xef => 0x5321, 0xf0 => 0x7b50, + 0xf1 => 0x72c2, 0xf2 => 0x6846, 0xf3 => 0x77ff, 0xf4 => 0x7736, + 0xf5 => 0x65f7, 0xf6 => 0x51b5, 0xf7 => 0x4e8f, 0xf8 => 0x76d4, + 0xf9 => 0x5cbf, 0xfa => 0x7aa5, 0xfb => 0x8475, 0xfc => 0x594e, + 0xfd => 0x9b41, 0xfe => 0x5080, + }, + 0xc0 => { + 0xa1 => 0x9988, 0xa2 => 0x6127, 0xa3 => 0x6e83, 0xa4 => 0x5764, + 0xa5 => 0x6606, 0xa6 => 0x6346, 0xa7 => 0x56f0, 0xa8 => 0x62ec, + 0xa9 => 0x6269, 0xaa => 0x5ed3, 0xab => 0x9614, 0xac => 0x5783, + 0xad => 0x62c9, 0xae => 0x5587, 0xaf => 0x8721, 0xb0 => 0x814a, + 0xb1 => 0x8fa3, 0xb2 => 0x5566, 0xb3 => 0x83b1, 0xb4 => 0x6765, + 0xb5 => 0x8d56, 0xb6 => 0x84dd, 0xb7 => 0x5a6a, 0xb8 => 0x680f, + 0xb9 => 0x62e6, 0xba => 0x7bee, 0xbb => 0x9611, 0xbc => 0x5170, + 0xbd => 0x6f9c, 0xbe => 0x8c30, 0xbf => 0x63fd, 0xc0 => 0x89c8, + 0xc1 => 0x61d2, 0xc2 => 0x7f06, 0xc3 => 0x70c2, 0xc4 => 0x6ee5, + 0xc5 => 0x7405, 0xc6 => 0x6994, 0xc7 => 0x72fc, 0xc8 => 0x5eca, + 0xc9 => 0x90ce, 0xca => 0x6717, 0xcb => 0x6d6a, 0xcc => 0x635e, + 0xcd => 0x52b3, 0xce => 0x7262, 0xcf => 0x8001, 0xd0 => 0x4f6c, + 0xd1 => 0x59e5, 0xd2 => 0x916a, 0xd3 => 0x70d9, 0xd4 => 0x6d9d, + 0xd5 => 0x52d2, 0xd6 => 0x4e50, 0xd7 => 0x96f7, 0xd8 => 0x956d, + 0xd9 => 0x857e, 0xda => 0x78ca, 0xdb => 0x7d2f, 0xdc => 0x5121, + 0xdd => 0x5792, 0xde => 0x64c2, 0xdf => 0x808b, 0xe0 => 0x7c7b, + 0xe1 => 0x6cea, 0xe2 => 0x68f1, 0xe3 => 0x695e, 0xe4 => 0x51b7, + 0xe5 => 0x5398, 0xe6 => 0x68a8, 0xe7 => 0x7281, 0xe8 => 0x9ece, + 0xe9 => 0x7bf1, 0xea => 0x72f8, 0xeb => 0x79bb, 0xec => 0x6f13, + 0xed => 0x7406, 0xee => 0x674e, 0xef => 0x91cc, 0xf0 => 0x9ca4, + 0xf1 => 0x793c, 0xf2 => 0x8389, 0xf3 => 0x8354, 0xf4 => 0x540f, + 0xf5 => 0x6817, 0xf6 => 0x4e3d, 0xf7 => 0x5389, 0xf8 => 0x52b1, + 0xf9 => 0x783e, 0xfa => 0x5386, 0xfb => 0x5229, 0xfc => 0x5088, + 0xfd => 0x4f8b, 0xfe => 0x4fd0, + }, + 0xc1 => { + 0xa1 => 0x75e2, 0xa2 => 0x7acb, 0xa3 => 0x7c92, 0xa4 => 0x6ca5, + 0xa5 => 0x96b6, 0xa6 => 0x529b, 0xa7 => 0x7483, 0xa8 => 0x54e9, + 0xa9 => 0x4fe9, 0xaa => 0x8054, 0xab => 0x83b2, 0xac => 0x8fde, + 0xad => 0x9570, 0xae => 0x5ec9, 0xaf => 0x601c, 0xb0 => 0x6d9f, + 0xb1 => 0x5e18, 0xb2 => 0x655b, 0xb3 => 0x8138, 0xb4 => 0x94fe, + 0xb5 => 0x604b, 0xb6 => 0x70bc, 0xb7 => 0x7ec3, 0xb8 => 0x7cae, + 0xb9 => 0x51c9, 0xba => 0x6881, 0xbb => 0x7cb1, 0xbc => 0x826f, + 0xbd => 0x4e24, 0xbe => 0x8f86, 0xbf => 0x91cf, 0xc0 => 0x667e, + 0xc1 => 0x4eae, 0xc2 => 0x8c05, 0xc3 => 0x64a9, 0xc4 => 0x804a, + 0xc5 => 0x50da, 0xc6 => 0x7597, 0xc7 => 0x71ce, 0xc8 => 0x5be5, + 0xc9 => 0x8fbd, 0xca => 0x6f66, 0xcb => 0x4e86, 0xcc => 0x6482, + 0xcd => 0x9563, 0xce => 0x5ed6, 0xcf => 0x6599, 0xd0 => 0x5217, + 0xd1 => 0x88c2, 0xd2 => 0x70c8, 0xd3 => 0x52a3, 0xd4 => 0x730e, + 0xd5 => 0x7433, 0xd6 => 0x6797, 0xd7 => 0x78f7, 0xd8 => 0x9716, + 0xd9 => 0x4e34, 0xda => 0x90bb, 0xdb => 0x9cde, 0xdc => 0x6dcb, + 0xdd => 0x51db, 0xde => 0x8d41, 0xdf => 0x541d, 0xe0 => 0x62ce, + 0xe1 => 0x73b2, 0xe2 => 0x83f1, 0xe3 => 0x96f6, 0xe4 => 0x9f84, + 0xe5 => 0x94c3, 0xe6 => 0x4f36, 0xe7 => 0x7f9a, 0xe8 => 0x51cc, + 0xe9 => 0x7075, 0xea => 0x9675, 0xeb => 0x5cad, 0xec => 0x9886, + 0xed => 0x53e6, 0xee => 0x4ee4, 0xef => 0x6e9c, 0xf0 => 0x7409, + 0xf1 => 0x69b4, 0xf2 => 0x786b, 0xf3 => 0x998f, 0xf4 => 0x7559, + 0xf5 => 0x5218, 0xf6 => 0x7624, 0xf7 => 0x6d41, 0xf8 => 0x67f3, + 0xf9 => 0x516d, 0xfa => 0x9f99, 0xfb => 0x804b, 0xfc => 0x5499, + 0xfd => 0x7b3c, 0xfe => 0x7abf, + }, + 0xc2 => { + 0xa1 => 0x9686, 0xa2 => 0x5784, 0xa3 => 0x62e2, 0xa4 => 0x9647, + 0xa5 => 0x697c, 0xa6 => 0x5a04, 0xa7 => 0x6402, 0xa8 => 0x7bd3, + 0xa9 => 0x6f0f, 0xaa => 0x964b, 0xab => 0x82a6, 0xac => 0x5362, + 0xad => 0x9885, 0xae => 0x5e90, 0xaf => 0x7089, 0xb0 => 0x63b3, + 0xb1 => 0x5364, 0xb2 => 0x864f, 0xb3 => 0x9c81, 0xb4 => 0x9e93, + 0xb5 => 0x788c, 0xb6 => 0x9732, 0xb7 => 0x8def, 0xb8 => 0x8d42, + 0xb9 => 0x9e7f, 0xba => 0x6f5e, 0xbb => 0x7984, 0xbc => 0x5f55, + 0xbd => 0x9646, 0xbe => 0x622e, 0xbf => 0x9a74, 0xc0 => 0x5415, + 0xc1 => 0x94dd, 0xc2 => 0x4fa3, 0xc3 => 0x65c5, 0xc4 => 0x5c65, + 0xc5 => 0x5c61, 0xc6 => 0x7f15, 0xc7 => 0x8651, 0xc8 => 0x6c2f, + 0xc9 => 0x5f8b, 0xca => 0x7387, 0xcb => 0x6ee4, 0xcc => 0x7eff, + 0xcd => 0x5ce6, 0xce => 0x631b, 0xcf => 0x5b6a, 0xd0 => 0x6ee6, + 0xd1 => 0x5375, 0xd2 => 0x4e71, 0xd3 => 0x63a0, 0xd4 => 0x7565, + 0xd5 => 0x62a1, 0xd6 => 0x8f6e, 0xd7 => 0x4f26, 0xd8 => 0x4ed1, + 0xd9 => 0x6ca6, 0xda => 0x7eb6, 0xdb => 0x8bba, 0xdc => 0x841d, + 0xdd => 0x87ba, 0xde => 0x7f57, 0xdf => 0x903b, 0xe0 => 0x9523, + 0xe1 => 0x7ba9, 0xe2 => 0x9aa1, 0xe3 => 0x88f8, 0xe4 => 0x843d, + 0xe5 => 0x6d1b, 0xe6 => 0x9a86, 0xe7 => 0x7edc, 0xe8 => 0x5988, + 0xe9 => 0x9ebb, 0xea => 0x739b, 0xeb => 0x7801, 0xec => 0x8682, + 0xed => 0x9a6c, 0xee => 0x9a82, 0xef => 0x561b, 0xf0 => 0x5417, + 0xf1 => 0x57cb, 0xf2 => 0x4e70, 0xf3 => 0x9ea6, 0xf4 => 0x5356, + 0xf5 => 0x8fc8, 0xf6 => 0x8109, 0xf7 => 0x7792, 0xf8 => 0x9992, + 0xf9 => 0x86ee, 0xfa => 0x6ee1, 0xfb => 0x8513, 0xfc => 0x66fc, + 0xfd => 0x6162, 0xfe => 0x6f2b, + }, + 0xc3 => { + 0xa1 => 0x8c29, 0xa2 => 0x8292, 0xa3 => 0x832b, 0xa4 => 0x76f2, + 0xa5 => 0x6c13, 0xa6 => 0x5fd9, 0xa7 => 0x83bd, 0xa8 => 0x732b, + 0xa9 => 0x8305, 0xaa => 0x951a, 0xab => 0x6bdb, 0xac => 0x77db, + 0xad => 0x94c6, 0xae => 0x536f, 0xaf => 0x8302, 0xb0 => 0x5192, + 0xb1 => 0x5e3d, 0xb2 => 0x8c8c, 0xb3 => 0x8d38, 0xb4 => 0x4e48, + 0xb5 => 0x73ab, 0xb6 => 0x679a, 0xb7 => 0x6885, 0xb8 => 0x9176, + 0xb9 => 0x9709, 0xba => 0x7164, 0xbb => 0x6ca1, 0xbc => 0x7709, + 0xbd => 0x5a92, 0xbe => 0x9541, 0xbf => 0x6bcf, 0xc0 => 0x7f8e, + 0xc1 => 0x6627, 0xc2 => 0x5bd0, 0xc3 => 0x59b9, 0xc4 => 0x5a9a, + 0xc5 => 0x95e8, 0xc6 => 0x95f7, 0xc7 => 0x4eec, 0xc8 => 0x840c, + 0xc9 => 0x8499, 0xca => 0x6aac, 0xcb => 0x76df, 0xcc => 0x9530, + 0xcd => 0x731b, 0xce => 0x68a6, 0xcf => 0x5b5f, 0xd0 => 0x772f, + 0xd1 => 0x919a, 0xd2 => 0x9761, 0xd3 => 0x7cdc, 0xd4 => 0x8ff7, + 0xd5 => 0x8c1c, 0xd6 => 0x5f25, 0xd7 => 0x7c73, 0xd8 => 0x79d8, + 0xd9 => 0x89c5, 0xda => 0x6ccc, 0xdb => 0x871c, 0xdc => 0x5bc6, + 0xdd => 0x5e42, 0xde => 0x68c9, 0xdf => 0x7720, 0xe0 => 0x7ef5, + 0xe1 => 0x5195, 0xe2 => 0x514d, 0xe3 => 0x52c9, 0xe4 => 0x5a29, + 0xe5 => 0x7f05, 0xe6 => 0x9762, 0xe7 => 0x82d7, 0xe8 => 0x63cf, + 0xe9 => 0x7784, 0xea => 0x85d0, 0xeb => 0x79d2, 0xec => 0x6e3a, + 0xed => 0x5e99, 0xee => 0x5999, 0xef => 0x8511, 0xf0 => 0x706d, + 0xf1 => 0x6c11, 0xf2 => 0x62bf, 0xf3 => 0x76bf, 0xf4 => 0x654f, + 0xf5 => 0x60af, 0xf6 => 0x95fd, 0xf7 => 0x660e, 0xf8 => 0x879f, + 0xf9 => 0x9e23, 0xfa => 0x94ed, 0xfb => 0x540d, 0xfc => 0x547d, + 0xfd => 0x8c2c, 0xfe => 0x6478, + }, + 0xc4 => { + 0xa1 => 0x6479, 0xa2 => 0x8611, 0xa3 => 0x6a21, 0xa4 => 0x819c, + 0xa5 => 0x78e8, 0xa6 => 0x6469, 0xa7 => 0x9b54, 0xa8 => 0x62b9, + 0xa9 => 0x672b, 0xaa => 0x83ab, 0xab => 0x58a8, 0xac => 0x9ed8, + 0xad => 0x6cab, 0xae => 0x6f20, 0xaf => 0x5bde, 0xb0 => 0x964c, + 0xb1 => 0x8c0b, 0xb2 => 0x725f, 0xb3 => 0x67d0, 0xb4 => 0x62c7, + 0xb5 => 0x7261, 0xb6 => 0x4ea9, 0xb7 => 0x59c6, 0xb8 => 0x6bcd, + 0xb9 => 0x5893, 0xba => 0x66ae, 0xbb => 0x5e55, 0xbc => 0x52df, + 0xbd => 0x6155, 0xbe => 0x6728, 0xbf => 0x76ee, 0xc0 => 0x7766, + 0xc1 => 0x7267, 0xc2 => 0x7a46, 0xc3 => 0x62ff, 0xc4 => 0x54ea, + 0xc5 => 0x5450, 0xc6 => 0x94a0, 0xc7 => 0x90a3, 0xc8 => 0x5a1c, + 0xc9 => 0x7eb3, 0xca => 0x6c16, 0xcb => 0x4e43, 0xcc => 0x5976, + 0xcd => 0x8010, 0xce => 0x5948, 0xcf => 0x5357, 0xd0 => 0x7537, + 0xd1 => 0x96be, 0xd2 => 0x56ca, 0xd3 => 0x6320, 0xd4 => 0x8111, + 0xd5 => 0x607c, 0xd6 => 0x95f9, 0xd7 => 0x6dd6, 0xd8 => 0x5462, + 0xd9 => 0x9981, 0xda => 0x5185, 0xdb => 0x5ae9, 0xdc => 0x80fd, + 0xdd => 0x59ae, 0xde => 0x9713, 0xdf => 0x502a, 0xe0 => 0x6ce5, + 0xe1 => 0x5c3c, 0xe2 => 0x62df, 0xe3 => 0x4f60, 0xe4 => 0x533f, + 0xe5 => 0x817b, 0xe6 => 0x9006, 0xe7 => 0x6eba, 0xe8 => 0x852b, + 0xe9 => 0x62c8, 0xea => 0x5e74, 0xeb => 0x78be, 0xec => 0x64b5, + 0xed => 0x637b, 0xee => 0x5ff5, 0xef => 0x5a18, 0xf0 => 0x917f, + 0xf1 => 0x9e1f, 0xf2 => 0x5c3f, 0xf3 => 0x634f, 0xf4 => 0x8042, + 0xf5 => 0x5b7d, 0xf6 => 0x556e, 0xf7 => 0x954a, 0xf8 => 0x954d, + 0xf9 => 0x6d85, 0xfa => 0x60a8, 0xfb => 0x67e0, 0xfc => 0x72de, + 0xfd => 0x51dd, 0xfe => 0x5b81, + }, + 0xc5 => { + 0xa1 => 0x62e7, 0xa2 => 0x6cde, 0xa3 => 0x725b, 0xa4 => 0x626d, + 0xa5 => 0x94ae, 0xa6 => 0x7ebd, 0xa7 => 0x8113, 0xa8 => 0x6d53, + 0xa9 => 0x519c, 0xaa => 0x5f04, 0xab => 0x5974, 0xac => 0x52aa, + 0xad => 0x6012, 0xae => 0x5973, 0xaf => 0x6696, 0xb0 => 0x8650, + 0xb1 => 0x759f, 0xb2 => 0x632a, 0xb3 => 0x61e6, 0xb4 => 0x7cef, + 0xb5 => 0x8bfa, 0xb6 => 0x54e6, 0xb7 => 0x6b27, 0xb8 => 0x9e25, + 0xb9 => 0x6bb4, 0xba => 0x85d5, 0xbb => 0x5455, 0xbc => 0x5076, + 0xbd => 0x6ca4, 0xbe => 0x556a, 0xbf => 0x8db4, 0xc0 => 0x722c, + 0xc1 => 0x5e15, 0xc2 => 0x6015, 0xc3 => 0x7436, 0xc4 => 0x62cd, + 0xc5 => 0x6392, 0xc6 => 0x724c, 0xc7 => 0x5f98, 0xc8 => 0x6e43, + 0xc9 => 0x6d3e, 0xca => 0x6500, 0xcb => 0x6f58, 0xcc => 0x76d8, + 0xcd => 0x78d0, 0xce => 0x76fc, 0xcf => 0x7554, 0xd0 => 0x5224, + 0xd1 => 0x53db, 0xd2 => 0x4e53, 0xd3 => 0x5e9e, 0xd4 => 0x65c1, + 0xd5 => 0x802a, 0xd6 => 0x80d6, 0xd7 => 0x629b, 0xd8 => 0x5486, + 0xd9 => 0x5228, 0xda => 0x70ae, 0xdb => 0x888d, 0xdc => 0x8dd1, + 0xdd => 0x6ce1, 0xde => 0x5478, 0xdf => 0x80da, 0xe0 => 0x57f9, + 0xe1 => 0x88f4, 0xe2 => 0x8d54, 0xe3 => 0x966a, 0xe4 => 0x914d, + 0xe5 => 0x4f69, 0xe6 => 0x6c9b, 0xe7 => 0x55b7, 0xe8 => 0x76c6, + 0xe9 => 0x7830, 0xea => 0x62a8, 0xeb => 0x70f9, 0xec => 0x6f8e, + 0xed => 0x5f6d, 0xee => 0x84ec, 0xef => 0x68da, 0xf0 => 0x787c, + 0xf1 => 0x7bf7, 0xf2 => 0x81a8, 0xf3 => 0x670b, 0xf4 => 0x9e4f, + 0xf5 => 0x6367, 0xf6 => 0x78b0, 0xf7 => 0x576f, 0xf8 => 0x7812, + 0xf9 => 0x9739, 0xfa => 0x6279, 0xfb => 0x62ab, 0xfc => 0x5288, + 0xfd => 0x7435, 0xfe => 0x6bd7, + }, + 0xc6 => { + 0xa1 => 0x5564, 0xa2 => 0x813e, 0xa3 => 0x75b2, 0xa4 => 0x76ae, + 0xa5 => 0x5339, 0xa6 => 0x75de, 0xa7 => 0x50fb, 0xa8 => 0x5c41, + 0xa9 => 0x8b6c, 0xaa => 0x7bc7, 0xab => 0x504f, 0xac => 0x7247, + 0xad => 0x9a97, 0xae => 0x98d8, 0xaf => 0x6f02, 0xb0 => 0x74e2, + 0xb1 => 0x7968, 0xb2 => 0x6487, 0xb3 => 0x77a5, 0xb4 => 0x62fc, + 0xb5 => 0x9891, 0xb6 => 0x8d2b, 0xb7 => 0x54c1, 0xb8 => 0x8058, + 0xb9 => 0x4e52, 0xba => 0x576a, 0xbb => 0x82f9, 0xbc => 0x840d, + 0xbd => 0x5e73, 0xbe => 0x51ed, 0xbf => 0x74f6, 0xc0 => 0x8bc4, + 0xc1 => 0x5c4f, 0xc2 => 0x5761, 0xc3 => 0x6cfc, 0xc4 => 0x9887, + 0xc5 => 0x5a46, 0xc6 => 0x7834, 0xc7 => 0x9b44, 0xc8 => 0x8feb, + 0xc9 => 0x7c95, 0xca => 0x5256, 0xcb => 0x6251, 0xcc => 0x94fa, + 0xcd => 0x4ec6, 0xce => 0x8386, 0xcf => 0x8461, 0xd0 => 0x83e9, + 0xd1 => 0x84b2, 0xd2 => 0x57d4, 0xd3 => 0x6734, 0xd4 => 0x5703, + 0xd5 => 0x666e, 0xd6 => 0x6d66, 0xd7 => 0x8c31, 0xd8 => 0x66dd, + 0xd9 => 0x7011, 0xda => 0x671f, 0xdb => 0x6b3a, 0xdc => 0x6816, + 0xdd => 0x621a, 0xde => 0x59bb, 0xdf => 0x4e03, 0xe0 => 0x51c4, + 0xe1 => 0x6f06, 0xe2 => 0x67d2, 0xe3 => 0x6c8f, 0xe4 => 0x5176, + 0xe5 => 0x68cb, 0xe6 => 0x5947, 0xe7 => 0x6b67, 0xe8 => 0x7566, + 0xe9 => 0x5d0e, 0xea => 0x8110, 0xeb => 0x9f50, 0xec => 0x65d7, + 0xed => 0x7948, 0xee => 0x7941, 0xef => 0x9a91, 0xf0 => 0x8d77, + 0xf1 => 0x5c82, 0xf2 => 0x4e5e, 0xf3 => 0x4f01, 0xf4 => 0x542f, + 0xf5 => 0x5951, 0xf6 => 0x780c, 0xf7 => 0x5668, 0xf8 => 0x6c14, + 0xf9 => 0x8fc4, 0xfa => 0x5f03, 0xfb => 0x6c7d, 0xfc => 0x6ce3, + 0xfd => 0x8bab, 0xfe => 0x6390, + }, + 0xc7 => { + 0xa1 => 0x6070, 0xa2 => 0x6d3d, 0xa3 => 0x7275, 0xa4 => 0x6266, + 0xa5 => 0x948e, 0xa6 => 0x94c5, 0xa7 => 0x5343, 0xa8 => 0x8fc1, + 0xa9 => 0x7b7e, 0xaa => 0x4edf, 0xab => 0x8c26, 0xac => 0x4e7e, + 0xad => 0x9ed4, 0xae => 0x94b1, 0xaf => 0x94b3, 0xb0 => 0x524d, + 0xb1 => 0x6f5c, 0xb2 => 0x9063, 0xb3 => 0x6d45, 0xb4 => 0x8c34, + 0xb5 => 0x5811, 0xb6 => 0x5d4c, 0xb7 => 0x6b20, 0xb8 => 0x6b49, + 0xb9 => 0x67aa, 0xba => 0x545b, 0xbb => 0x8154, 0xbc => 0x7f8c, + 0xbd => 0x5899, 0xbe => 0x8537, 0xbf => 0x5f3a, 0xc0 => 0x62a2, + 0xc1 => 0x6a47, 0xc2 => 0x9539, 0xc3 => 0x6572, 0xc4 => 0x6084, + 0xc5 => 0x6865, 0xc6 => 0x77a7, 0xc7 => 0x4e54, 0xc8 => 0x4fa8, + 0xc9 => 0x5de7, 0xca => 0x9798, 0xcb => 0x64ac, 0xcc => 0x7fd8, + 0xcd => 0x5ced, 0xce => 0x4fcf, 0xcf => 0x7a8d, 0xd0 => 0x5207, + 0xd1 => 0x8304, 0xd2 => 0x4e14, 0xd3 => 0x602f, 0xd4 => 0x7a83, + 0xd5 => 0x94a6, 0xd6 => 0x4fb5, 0xd7 => 0x4eb2, 0xd8 => 0x79e6, + 0xd9 => 0x7434, 0xda => 0x52e4, 0xdb => 0x82b9, 0xdc => 0x64d2, + 0xdd => 0x79bd, 0xde => 0x5bdd, 0xdf => 0x6c81, 0xe0 => 0x9752, + 0xe1 => 0x8f7b, 0xe2 => 0x6c22, 0xe3 => 0x503e, 0xe4 => 0x537f, + 0xe5 => 0x6e05, 0xe6 => 0x64ce, 0xe7 => 0x6674, 0xe8 => 0x6c30, + 0xe9 => 0x60c5, 0xea => 0x9877, 0xeb => 0x8bf7, 0xec => 0x5e86, + 0xed => 0x743c, 0xee => 0x7a77, 0xef => 0x79cb, 0xf0 => 0x4e18, + 0xf1 => 0x90b1, 0xf2 => 0x7403, 0xf3 => 0x6c42, 0xf4 => 0x56da, + 0xf5 => 0x914b, 0xf6 => 0x6cc5, 0xf7 => 0x8d8b, 0xf8 => 0x533a, + 0xf9 => 0x86c6, 0xfa => 0x66f2, 0xfb => 0x8eaf, 0xfc => 0x5c48, + 0xfd => 0x9a71, 0xfe => 0x6e20, + }, + 0xc8 => { + 0xa1 => 0x53d6, 0xa2 => 0x5a36, 0xa3 => 0x9f8b, 0xa4 => 0x8da3, + 0xa5 => 0x53bb, 0xa6 => 0x5708, 0xa7 => 0x98a7, 0xa8 => 0x6743, + 0xa9 => 0x919b, 0xaa => 0x6cc9, 0xab => 0x5168, 0xac => 0x75ca, + 0xad => 0x62f3, 0xae => 0x72ac, 0xaf => 0x5238, 0xb0 => 0x529d, + 0xb1 => 0x7f3a, 0xb2 => 0x7094, 0xb3 => 0x7638, 0xb4 => 0x5374, + 0xb5 => 0x9e4a, 0xb6 => 0x69b7, 0xb7 => 0x786e, 0xb8 => 0x96c0, + 0xb9 => 0x88d9, 0xba => 0x7fa4, 0xbb => 0x7136, 0xbc => 0x71c3, + 0xbd => 0x5189, 0xbe => 0x67d3, 0xbf => 0x74e4, 0xc0 => 0x58e4, + 0xc1 => 0x6518, 0xc2 => 0x56b7, 0xc3 => 0x8ba9, 0xc4 => 0x9976, + 0xc5 => 0x6270, 0xc6 => 0x7ed5, 0xc7 => 0x60f9, 0xc8 => 0x70ed, + 0xc9 => 0x58ec, 0xca => 0x4ec1, 0xcb => 0x4eba, 0xcc => 0x5fcd, + 0xcd => 0x97e7, 0xce => 0x4efb, 0xcf => 0x8ba4, 0xd0 => 0x5203, + 0xd1 => 0x598a, 0xd2 => 0x7eab, 0xd3 => 0x6254, 0xd4 => 0x4ecd, + 0xd5 => 0x65e5, 0xd6 => 0x620e, 0xd7 => 0x8338, 0xd8 => 0x84c9, + 0xd9 => 0x8363, 0xda => 0x878d, 0xdb => 0x7194, 0xdc => 0x6eb6, + 0xdd => 0x5bb9, 0xde => 0x7ed2, 0xdf => 0x5197, 0xe0 => 0x63c9, + 0xe1 => 0x67d4, 0xe2 => 0x8089, 0xe3 => 0x8339, 0xe4 => 0x8815, + 0xe5 => 0x5112, 0xe6 => 0x5b7a, 0xe7 => 0x5982, 0xe8 => 0x8fb1, + 0xe9 => 0x4e73, 0xea => 0x6c5d, 0xeb => 0x5165, 0xec => 0x8925, + 0xed => 0x8f6f, 0xee => 0x962e, 0xef => 0x854a, 0xf0 => 0x745e, + 0xf1 => 0x9510, 0xf2 => 0x95f0, 0xf3 => 0x6da6, 0xf4 => 0x82e5, + 0xf5 => 0x5f31, 0xf6 => 0x6492, 0xf7 => 0x6d12, 0xf8 => 0x8428, + 0xf9 => 0x816e, 0xfa => 0x9cc3, 0xfb => 0x585e, 0xfc => 0x8d5b, + 0xfd => 0x4e09, 0xfe => 0x53c1, + }, + 0xc9 => { + 0xa1 => 0x4f1e, 0xa2 => 0x6563, 0xa3 => 0x6851, 0xa4 => 0x55d3, + 0xa5 => 0x4e27, 0xa6 => 0x6414, 0xa7 => 0x9a9a, 0xa8 => 0x626b, + 0xa9 => 0x5ac2, 0xaa => 0x745f, 0xab => 0x8272, 0xac => 0x6da9, + 0xad => 0x68ee, 0xae => 0x50e7, 0xaf => 0x838e, 0xb0 => 0x7802, + 0xb1 => 0x6740, 0xb2 => 0x5239, 0xb3 => 0x6c99, 0xb4 => 0x7eb1, + 0xb5 => 0x50bb, 0xb6 => 0x5565, 0xb7 => 0x715e, 0xb8 => 0x7b5b, + 0xb9 => 0x6652, 0xba => 0x73ca, 0xbb => 0x82eb, 0xbc => 0x6749, + 0xbd => 0x5c71, 0xbe => 0x5220, 0xbf => 0x717d, 0xc0 => 0x886b, + 0xc1 => 0x95ea, 0xc2 => 0x9655, 0xc3 => 0x64c5, 0xc4 => 0x8d61, + 0xc5 => 0x81b3, 0xc6 => 0x5584, 0xc7 => 0x6c55, 0xc8 => 0x6247, + 0xc9 => 0x7f2e, 0xca => 0x5892, 0xcb => 0x4f24, 0xcc => 0x5546, + 0xcd => 0x8d4f, 0xce => 0x664c, 0xcf => 0x4e0a, 0xd0 => 0x5c1a, + 0xd1 => 0x88f3, 0xd2 => 0x68a2, 0xd3 => 0x634e, 0xd4 => 0x7a0d, + 0xd5 => 0x70e7, 0xd6 => 0x828d, 0xd7 => 0x52fa, 0xd8 => 0x97f6, + 0xd9 => 0x5c11, 0xda => 0x54e8, 0xdb => 0x90b5, 0xdc => 0x7ecd, + 0xdd => 0x5962, 0xde => 0x8d4a, 0xdf => 0x86c7, 0xe0 => 0x820c, + 0xe1 => 0x820d, 0xe2 => 0x8d66, 0xe3 => 0x6444, 0xe4 => 0x5c04, + 0xe5 => 0x6151, 0xe6 => 0x6d89, 0xe7 => 0x793e, 0xe8 => 0x8bbe, + 0xe9 => 0x7837, 0xea => 0x7533, 0xeb => 0x547b, 0xec => 0x4f38, + 0xed => 0x8eab, 0xee => 0x6df1, 0xef => 0x5a20, 0xf0 => 0x7ec5, + 0xf1 => 0x795e, 0xf2 => 0x6c88, 0xf3 => 0x5ba1, 0xf4 => 0x5a76, + 0xf5 => 0x751a, 0xf6 => 0x80be, 0xf7 => 0x614e, 0xf8 => 0x6e17, + 0xf9 => 0x58f0, 0xfa => 0x751f, 0xfb => 0x7525, 0xfc => 0x7272, + 0xfd => 0x5347, 0xfe => 0x7ef3, + }, + 0xca => { + 0xa1 => 0x7701, 0xa2 => 0x76db, 0xa3 => 0x5269, 0xa4 => 0x80dc, + 0xa5 => 0x5723, 0xa6 => 0x5e08, 0xa7 => 0x5931, 0xa8 => 0x72ee, + 0xa9 => 0x65bd, 0xaa => 0x6e7f, 0xab => 0x8bd7, 0xac => 0x5c38, + 0xad => 0x8671, 0xae => 0x5341, 0xaf => 0x77f3, 0xb0 => 0x62fe, + 0xb1 => 0x65f6, 0xb2 => 0x4ec0, 0xb3 => 0x98df, 0xb4 => 0x8680, + 0xb5 => 0x5b9e, 0xb6 => 0x8bc6, 0xb7 => 0x53f2, 0xb8 => 0x77e2, + 0xb9 => 0x4f7f, 0xba => 0x5c4e, 0xbb => 0x9a76, 0xbc => 0x59cb, + 0xbd => 0x5f0f, 0xbe => 0x793a, 0xbf => 0x58eb, 0xc0 => 0x4e16, + 0xc1 => 0x67ff, 0xc2 => 0x4e8b, 0xc3 => 0x62ed, 0xc4 => 0x8a93, + 0xc5 => 0x901d, 0xc6 => 0x52bf, 0xc7 => 0x662f, 0xc8 => 0x55dc, + 0xc9 => 0x566c, 0xca => 0x9002, 0xcb => 0x4ed5, 0xcc => 0x4f8d, + 0xcd => 0x91ca, 0xce => 0x9970, 0xcf => 0x6c0f, 0xd0 => 0x5e02, + 0xd1 => 0x6043, 0xd2 => 0x5ba4, 0xd3 => 0x89c6, 0xd4 => 0x8bd5, + 0xd5 => 0x6536, 0xd6 => 0x624b, 0xd7 => 0x9996, 0xd8 => 0x5b88, + 0xd9 => 0x5bff, 0xda => 0x6388, 0xdb => 0x552e, 0xdc => 0x53d7, + 0xdd => 0x7626, 0xde => 0x517d, 0xdf => 0x852c, 0xe0 => 0x67a2, + 0xe1 => 0x68b3, 0xe2 => 0x6b8a, 0xe3 => 0x6292, 0xe4 => 0x8f93, + 0xe5 => 0x53d4, 0xe6 => 0x8212, 0xe7 => 0x6dd1, 0xe8 => 0x758f, + 0xe9 => 0x4e66, 0xea => 0x8d4e, 0xeb => 0x5b70, 0xec => 0x719f, + 0xed => 0x85af, 0xee => 0x6691, 0xef => 0x66d9, 0xf0 => 0x7f72, + 0xf1 => 0x8700, 0xf2 => 0x9ecd, 0xf3 => 0x9f20, 0xf4 => 0x5c5e, + 0xf5 => 0x672f, 0xf6 => 0x8ff0, 0xf7 => 0x6811, 0xf8 => 0x675f, + 0xf9 => 0x620d, 0xfa => 0x7ad6, 0xfb => 0x5885, 0xfc => 0x5eb6, + 0xfd => 0x6570, 0xfe => 0x6f31, + }, + 0xcb => { + 0xa1 => 0x6055, 0xa2 => 0x5237, 0xa3 => 0x800d, 0xa4 => 0x6454, + 0xa5 => 0x8870, 0xa6 => 0x7529, 0xa7 => 0x5e05, 0xa8 => 0x6813, + 0xa9 => 0x62f4, 0xaa => 0x971c, 0xab => 0x53cc, 0xac => 0x723d, + 0xad => 0x8c01, 0xae => 0x6c34, 0xaf => 0x7761, 0xb0 => 0x7a0e, + 0xb1 => 0x542e, 0xb2 => 0x77ac, 0xb3 => 0x987a, 0xb4 => 0x821c, + 0xb5 => 0x8bf4, 0xb6 => 0x7855, 0xb7 => 0x6714, 0xb8 => 0x70c1, + 0xb9 => 0x65af, 0xba => 0x6495, 0xbb => 0x5636, 0xbc => 0x601d, + 0xbd => 0x79c1, 0xbe => 0x53f8, 0xbf => 0x4e1d, 0xc0 => 0x6b7b, + 0xc1 => 0x8086, 0xc2 => 0x5bfa, 0xc3 => 0x55e3, 0xc4 => 0x56db, + 0xc5 => 0x4f3a, 0xc6 => 0x4f3c, 0xc7 => 0x9972, 0xc8 => 0x5df3, + 0xc9 => 0x677e, 0xca => 0x8038, 0xcb => 0x6002, 0xcc => 0x9882, + 0xcd => 0x9001, 0xce => 0x5b8b, 0xcf => 0x8bbc, 0xd0 => 0x8bf5, + 0xd1 => 0x641c, 0xd2 => 0x8258, 0xd3 => 0x64de, 0xd4 => 0x55fd, + 0xd5 => 0x82cf, 0xd6 => 0x9165, 0xd7 => 0x4fd7, 0xd8 => 0x7d20, + 0xd9 => 0x901f, 0xda => 0x7c9f, 0xdb => 0x50f3, 0xdc => 0x5851, + 0xdd => 0x6eaf, 0xde => 0x5bbf, 0xdf => 0x8bc9, 0xe0 => 0x8083, + 0xe1 => 0x9178, 0xe2 => 0x849c, 0xe3 => 0x7b97, 0xe4 => 0x867d, + 0xe5 => 0x968b, 0xe6 => 0x968f, 0xe7 => 0x7ee5, 0xe8 => 0x9ad3, + 0xe9 => 0x788e, 0xea => 0x5c81, 0xeb => 0x7a57, 0xec => 0x9042, + 0xed => 0x96a7, 0xee => 0x795f, 0xef => 0x5b59, 0xf0 => 0x635f, + 0xf1 => 0x7b0b, 0xf2 => 0x84d1, 0xf3 => 0x68ad, 0xf4 => 0x5506, + 0xf5 => 0x7f29, 0xf6 => 0x7410, 0xf7 => 0x7d22, 0xf8 => 0x9501, + 0xf9 => 0x6240, 0xfa => 0x584c, 0xfb => 0x4ed6, 0xfc => 0x5b83, + 0xfd => 0x5979, 0xfe => 0x5854, + }, + 0xcc => { + 0xa1 => 0x736d, 0xa2 => 0x631e, 0xa3 => 0x8e4b, 0xa4 => 0x8e0f, + 0xa5 => 0x80ce, 0xa6 => 0x82d4, 0xa7 => 0x62ac, 0xa8 => 0x53f0, + 0xa9 => 0x6cf0, 0xaa => 0x915e, 0xab => 0x592a, 0xac => 0x6001, + 0xad => 0x6c70, 0xae => 0x574d, 0xaf => 0x644a, 0xb0 => 0x8d2a, + 0xb1 => 0x762b, 0xb2 => 0x6ee9, 0xb3 => 0x575b, 0xb4 => 0x6a80, + 0xb5 => 0x75f0, 0xb6 => 0x6f6d, 0xb7 => 0x8c2d, 0xb8 => 0x8c08, + 0xb9 => 0x5766, 0xba => 0x6bef, 0xbb => 0x8892, 0xbc => 0x78b3, + 0xbd => 0x63a2, 0xbe => 0x53f9, 0xbf => 0x70ad, 0xc0 => 0x6c64, + 0xc1 => 0x5858, 0xc2 => 0x642a, 0xc3 => 0x5802, 0xc4 => 0x68e0, + 0xc5 => 0x819b, 0xc6 => 0x5510, 0xc7 => 0x7cd6, 0xc8 => 0x5018, + 0xc9 => 0x8eba, 0xca => 0x6dcc, 0xcb => 0x8d9f, 0xcc => 0x70eb, + 0xcd => 0x638f, 0xce => 0x6d9b, 0xcf => 0x6ed4, 0xd0 => 0x7ee6, + 0xd1 => 0x8404, 0xd2 => 0x6843, 0xd3 => 0x9003, 0xd4 => 0x6dd8, + 0xd5 => 0x9676, 0xd6 => 0x8ba8, 0xd7 => 0x5957, 0xd8 => 0x7279, + 0xd9 => 0x85e4, 0xda => 0x817e, 0xdb => 0x75bc, 0xdc => 0x8a8a, + 0xdd => 0x68af, 0xde => 0x5254, 0xdf => 0x8e22, 0xe0 => 0x9511, + 0xe1 => 0x63d0, 0xe2 => 0x9898, 0xe3 => 0x8e44, 0xe4 => 0x557c, + 0xe5 => 0x4f53, 0xe6 => 0x66ff, 0xe7 => 0x568f, 0xe8 => 0x60d5, + 0xe9 => 0x6d95, 0xea => 0x5243, 0xeb => 0x5c49, 0xec => 0x5929, + 0xed => 0x6dfb, 0xee => 0x586b, 0xef => 0x7530, 0xf0 => 0x751c, + 0xf1 => 0x606c, 0xf2 => 0x8214, 0xf3 => 0x8146, 0xf4 => 0x6311, + 0xf5 => 0x6761, 0xf6 => 0x8fe2, 0xf7 => 0x773a, 0xf8 => 0x8df3, + 0xf9 => 0x8d34, 0xfa => 0x94c1, 0xfb => 0x5e16, 0xfc => 0x5385, + 0xfd => 0x542c, 0xfe => 0x70c3, + }, + 0xcd => { + 0xa1 => 0x6c40, 0xa2 => 0x5ef7, 0xa3 => 0x505c, 0xa4 => 0x4ead, + 0xa5 => 0x5ead, 0xa6 => 0x633a, 0xa7 => 0x8247, 0xa8 => 0x901a, + 0xa9 => 0x6850, 0xaa => 0x916e, 0xab => 0x77b3, 0xac => 0x540c, + 0xad => 0x94dc, 0xae => 0x5f64, 0xaf => 0x7ae5, 0xb0 => 0x6876, + 0xb1 => 0x6345, 0xb2 => 0x7b52, 0xb3 => 0x7edf, 0xb4 => 0x75db, + 0xb5 => 0x5077, 0xb6 => 0x6295, 0xb7 => 0x5934, 0xb8 => 0x900f, + 0xb9 => 0x51f8, 0xba => 0x79c3, 0xbb => 0x7a81, 0xbc => 0x56fe, + 0xbd => 0x5f92, 0xbe => 0x9014, 0xbf => 0x6d82, 0xc0 => 0x5c60, + 0xc1 => 0x571f, 0xc2 => 0x5410, 0xc3 => 0x5154, 0xc4 => 0x6e4d, + 0xc5 => 0x56e2, 0xc6 => 0x63a8, 0xc7 => 0x9893, 0xc8 => 0x817f, + 0xc9 => 0x8715, 0xca => 0x892a, 0xcb => 0x9000, 0xcc => 0x541e, + 0xcd => 0x5c6f, 0xce => 0x81c0, 0xcf => 0x62d6, 0xd0 => 0x6258, + 0xd1 => 0x8131, 0xd2 => 0x9e35, 0xd3 => 0x9640, 0xd4 => 0x9a6e, + 0xd5 => 0x9a7c, 0xd6 => 0x692d, 0xd7 => 0x59a5, 0xd8 => 0x62d3, + 0xd9 => 0x553e, 0xda => 0x6316, 0xdb => 0x54c7, 0xdc => 0x86d9, + 0xdd => 0x6d3c, 0xde => 0x5a03, 0xdf => 0x74e6, 0xe0 => 0x889c, + 0xe1 => 0x6b6a, 0xe2 => 0x5916, 0xe3 => 0x8c4c, 0xe4 => 0x5f2f, + 0xe5 => 0x6e7e, 0xe6 => 0x73a9, 0xe7 => 0x987d, 0xe8 => 0x4e38, + 0xe9 => 0x70f7, 0xea => 0x5b8c, 0xeb => 0x7897, 0xec => 0x633d, + 0xed => 0x665a, 0xee => 0x7696, 0xef => 0x60cb, 0xf0 => 0x5b9b, + 0xf1 => 0x5a49, 0xf2 => 0x4e07, 0xf3 => 0x8155, 0xf4 => 0x6c6a, + 0xf5 => 0x738b, 0xf6 => 0x4ea1, 0xf7 => 0x6789, 0xf8 => 0x7f51, + 0xf9 => 0x5f80, 0xfa => 0x65fa, 0xfb => 0x671b, 0xfc => 0x5fd8, + 0xfd => 0x5984, 0xfe => 0x5a01, + }, + 0xce => { + 0xa1 => 0x5dcd, 0xa2 => 0x5fae, 0xa3 => 0x5371, 0xa4 => 0x97e6, + 0xa5 => 0x8fdd, 0xa6 => 0x6845, 0xa7 => 0x56f4, 0xa8 => 0x552f, + 0xa9 => 0x60df, 0xaa => 0x4e3a, 0xab => 0x6f4d, 0xac => 0x7ef4, + 0xad => 0x82c7, 0xae => 0x840e, 0xaf => 0x59d4, 0xb0 => 0x4f1f, + 0xb1 => 0x4f2a, 0xb2 => 0x5c3e, 0xb3 => 0x7eac, 0xb4 => 0x672a, + 0xb5 => 0x851a, 0xb6 => 0x5473, 0xb7 => 0x754f, 0xb8 => 0x80c3, + 0xb9 => 0x5582, 0xba => 0x9b4f, 0xbb => 0x4f4d, 0xbc => 0x6e2d, + 0xbd => 0x8c13, 0xbe => 0x5c09, 0xbf => 0x6170, 0xc0 => 0x536b, + 0xc1 => 0x761f, 0xc2 => 0x6e29, 0xc3 => 0x868a, 0xc4 => 0x6587, + 0xc5 => 0x95fb, 0xc6 => 0x7eb9, 0xc7 => 0x543b, 0xc8 => 0x7a33, + 0xc9 => 0x7d0a, 0xca => 0x95ee, 0xcb => 0x55e1, 0xcc => 0x7fc1, + 0xcd => 0x74ee, 0xce => 0x631d, 0xcf => 0x8717, 0xd0 => 0x6da1, + 0xd1 => 0x7a9d, 0xd2 => 0x6211, 0xd3 => 0x65a1, 0xd4 => 0x5367, + 0xd5 => 0x63e1, 0xd6 => 0x6c83, 0xd7 => 0x5deb, 0xd8 => 0x545c, + 0xd9 => 0x94a8, 0xda => 0x4e4c, 0xdb => 0x6c61, 0xdc => 0x8bec, + 0xdd => 0x5c4b, 0xde => 0x65e0, 0xdf => 0x829c, 0xe0 => 0x68a7, + 0xe1 => 0x543e, 0xe2 => 0x5434, 0xe3 => 0x6bcb, 0xe4 => 0x6b66, + 0xe5 => 0x4e94, 0xe6 => 0x6342, 0xe7 => 0x5348, 0xe8 => 0x821e, + 0xe9 => 0x4f0d, 0xea => 0x4fae, 0xeb => 0x575e, 0xec => 0x620a, + 0xed => 0x96fe, 0xee => 0x6664, 0xef => 0x7269, 0xf0 => 0x52ff, + 0xf1 => 0x52a1, 0xf2 => 0x609f, 0xf3 => 0x8bef, 0xf4 => 0x6614, + 0xf5 => 0x7199, 0xf6 => 0x6790, 0xf7 => 0x897f, 0xf8 => 0x7852, + 0xf9 => 0x77fd, 0xfa => 0x6670, 0xfb => 0x563b, 0xfc => 0x5438, + 0xfd => 0x9521, 0xfe => 0x727a, + }, + 0xcf => { + 0xa1 => 0x7a00, 0xa2 => 0x606f, 0xa3 => 0x5e0c, 0xa4 => 0x6089, + 0xa5 => 0x819d, 0xa6 => 0x5915, 0xa7 => 0x60dc, 0xa8 => 0x7184, + 0xa9 => 0x70ef, 0xaa => 0x6eaa, 0xab => 0x6c50, 0xac => 0x7280, + 0xad => 0x6a84, 0xae => 0x88ad, 0xaf => 0x5e2d, 0xb0 => 0x4e60, + 0xb1 => 0x5ab3, 0xb2 => 0x559c, 0xb3 => 0x94e3, 0xb4 => 0x6d17, + 0xb5 => 0x7cfb, 0xb6 => 0x9699, 0xb7 => 0x620f, 0xb8 => 0x7ec6, + 0xb9 => 0x778e, 0xba => 0x867e, 0xbb => 0x5323, 0xbc => 0x971e, + 0xbd => 0x8f96, 0xbe => 0x6687, 0xbf => 0x5ce1, 0xc0 => 0x4fa0, + 0xc1 => 0x72ed, 0xc2 => 0x4e0b, 0xc3 => 0x53a6, 0xc4 => 0x590f, + 0xc5 => 0x5413, 0xc6 => 0x6380, 0xc7 => 0x9528, 0xc8 => 0x5148, + 0xc9 => 0x4ed9, 0xca => 0x9c9c, 0xcb => 0x7ea4, 0xcc => 0x54b8, + 0xcd => 0x8d24, 0xce => 0x8854, 0xcf => 0x8237, 0xd0 => 0x95f2, + 0xd1 => 0x6d8e, 0xd2 => 0x5f26, 0xd3 => 0x5acc, 0xd4 => 0x663e, + 0xd5 => 0x9669, 0xd6 => 0x73b0, 0xd7 => 0x732e, 0xd8 => 0x53bf, + 0xd9 => 0x817a, 0xda => 0x9985, 0xdb => 0x7fa1, 0xdc => 0x5baa, + 0xdd => 0x9677, 0xde => 0x9650, 0xdf => 0x7ebf, 0xe0 => 0x76f8, + 0xe1 => 0x53a2, 0xe2 => 0x9576, 0xe3 => 0x9999, 0xe4 => 0x7bb1, + 0xe5 => 0x8944, 0xe6 => 0x6e58, 0xe7 => 0x4e61, 0xe8 => 0x7fd4, + 0xe9 => 0x7965, 0xea => 0x8be6, 0xeb => 0x60f3, 0xec => 0x54cd, + 0xed => 0x4eab, 0xee => 0x9879, 0xef => 0x5df7, 0xf0 => 0x6a61, + 0xf1 => 0x50cf, 0xf2 => 0x5411, 0xf3 => 0x8c61, 0xf4 => 0x8427, + 0xf5 => 0x785d, 0xf6 => 0x9704, 0xf7 => 0x524a, 0xf8 => 0x54ee, + 0xf9 => 0x56a3, 0xfa => 0x9500, 0xfb => 0x6d88, 0xfc => 0x5bb5, + 0xfd => 0x6dc6, 0xfe => 0x6653, + }, + 0xd0 => { + 0xa1 => 0x5c0f, 0xa2 => 0x5b5d, 0xa3 => 0x6821, 0xa4 => 0x8096, + 0xa5 => 0x5578, 0xa6 => 0x7b11, 0xa7 => 0x6548, 0xa8 => 0x6954, + 0xa9 => 0x4e9b, 0xaa => 0x6b47, 0xab => 0x874e, 0xac => 0x978b, + 0xad => 0x534f, 0xae => 0x631f, 0xaf => 0x643a, 0xb0 => 0x90aa, + 0xb1 => 0x659c, 0xb2 => 0x80c1, 0xb3 => 0x8c10, 0xb4 => 0x5199, + 0xb5 => 0x68b0, 0xb6 => 0x5378, 0xb7 => 0x87f9, 0xb8 => 0x61c8, + 0xb9 => 0x6cc4, 0xba => 0x6cfb, 0xbb => 0x8c22, 0xbc => 0x5c51, + 0xbd => 0x85aa, 0xbe => 0x82af, 0xbf => 0x950c, 0xc0 => 0x6b23, + 0xc1 => 0x8f9b, 0xc2 => 0x65b0, 0xc3 => 0x5ffb, 0xc4 => 0x5fc3, + 0xc5 => 0x4fe1, 0xc6 => 0x8845, 0xc7 => 0x661f, 0xc8 => 0x8165, + 0xc9 => 0x7329, 0xca => 0x60fa, 0xcb => 0x5174, 0xcc => 0x5211, + 0xcd => 0x578b, 0xce => 0x5f62, 0xcf => 0x90a2, 0xd0 => 0x884c, + 0xd1 => 0x9192, 0xd2 => 0x5e78, 0xd3 => 0x674f, 0xd4 => 0x6027, + 0xd5 => 0x59d3, 0xd6 => 0x5144, 0xd7 => 0x51f6, 0xd8 => 0x80f8, + 0xd9 => 0x5308, 0xda => 0x6c79, 0xdb => 0x96c4, 0xdc => 0x718a, + 0xdd => 0x4f11, 0xde => 0x4fee, 0xdf => 0x7f9e, 0xe0 => 0x673d, + 0xe1 => 0x55c5, 0xe2 => 0x9508, 0xe3 => 0x79c0, 0xe4 => 0x8896, + 0xe5 => 0x7ee3, 0xe6 => 0x589f, 0xe7 => 0x620c, 0xe8 => 0x9700, + 0xe9 => 0x865a, 0xea => 0x5618, 0xeb => 0x987b, 0xec => 0x5f90, + 0xed => 0x8bb8, 0xee => 0x84c4, 0xef => 0x9157, 0xf0 => 0x53d9, + 0xf1 => 0x65ed, 0xf2 => 0x5e8f, 0xf3 => 0x755c, 0xf4 => 0x6064, + 0xf5 => 0x7d6e, 0xf6 => 0x5a7f, 0xf7 => 0x7eea, 0xf8 => 0x7eed, + 0xf9 => 0x8f69, 0xfa => 0x55a7, 0xfb => 0x5ba3, 0xfc => 0x60ac, + 0xfd => 0x65cb, 0xfe => 0x7384, + }, + 0xd1 => { + 0xa1 => 0x9009, 0xa2 => 0x7663, 0xa3 => 0x7729, 0xa4 => 0x7eda, + 0xa5 => 0x9774, 0xa6 => 0x859b, 0xa7 => 0x5b66, 0xa8 => 0x7a74, + 0xa9 => 0x96ea, 0xaa => 0x8840, 0xab => 0x52cb, 0xac => 0x718f, + 0xad => 0x5faa, 0xae => 0x65ec, 0xaf => 0x8be2, 0xb0 => 0x5bfb, + 0xb1 => 0x9a6f, 0xb2 => 0x5de1, 0xb3 => 0x6b89, 0xb4 => 0x6c5b, + 0xb5 => 0x8bad, 0xb6 => 0x8baf, 0xb7 => 0x900a, 0xb8 => 0x8fc5, + 0xb9 => 0x538b, 0xba => 0x62bc, 0xbb => 0x9e26, 0xbc => 0x9e2d, + 0xbd => 0x5440, 0xbe => 0x4e2b, 0xbf => 0x82bd, 0xc0 => 0x7259, + 0xc1 => 0x869c, 0xc2 => 0x5d16, 0xc3 => 0x8859, 0xc4 => 0x6daf, + 0xc5 => 0x96c5, 0xc6 => 0x54d1, 0xc7 => 0x4e9a, 0xc8 => 0x8bb6, + 0xc9 => 0x7109, 0xca => 0x54bd, 0xcb => 0x9609, 0xcc => 0x70df, + 0xcd => 0x6df9, 0xce => 0x76d0, 0xcf => 0x4e25, 0xd0 => 0x7814, + 0xd1 => 0x8712, 0xd2 => 0x5ca9, 0xd3 => 0x5ef6, 0xd4 => 0x8a00, + 0xd5 => 0x989c, 0xd6 => 0x960e, 0xd7 => 0x708e, 0xd8 => 0x6cbf, + 0xd9 => 0x5944, 0xda => 0x63a9, 0xdb => 0x773c, 0xdc => 0x884d, + 0xdd => 0x6f14, 0xde => 0x8273, 0xdf => 0x5830, 0xe0 => 0x71d5, + 0xe1 => 0x538c, 0xe2 => 0x781a, 0xe3 => 0x96c1, 0xe4 => 0x5501, + 0xe5 => 0x5f66, 0xe6 => 0x7130, 0xe7 => 0x5bb4, 0xe8 => 0x8c1a, + 0xe9 => 0x9a8c, 0xea => 0x6b83, 0xeb => 0x592e, 0xec => 0x9e2f, + 0xed => 0x79e7, 0xee => 0x6768, 0xef => 0x626c, 0xf0 => 0x4f6f, + 0xf1 => 0x75a1, 0xf2 => 0x7f8a, 0xf3 => 0x6d0b, 0xf4 => 0x9633, + 0xf5 => 0x6c27, 0xf6 => 0x4ef0, 0xf7 => 0x75d2, 0xf8 => 0x517b, + 0xf9 => 0x6837, 0xfa => 0x6f3e, 0xfb => 0x9080, 0xfc => 0x8170, + 0xfd => 0x5996, 0xfe => 0x7476, + }, + 0xd2 => { + 0xa1 => 0x6447, 0xa2 => 0x5c27, 0xa3 => 0x9065, 0xa4 => 0x7a91, + 0xa5 => 0x8c23, 0xa6 => 0x59da, 0xa7 => 0x54ac, 0xa8 => 0x8200, + 0xa9 => 0x836f, 0xaa => 0x8981, 0xab => 0x8000, 0xac => 0x6930, + 0xad => 0x564e, 0xae => 0x8036, 0xaf => 0x7237, 0xb0 => 0x91ce, + 0xb1 => 0x51b6, 0xb2 => 0x4e5f, 0xb3 => 0x9875, 0xb4 => 0x6396, + 0xb5 => 0x4e1a, 0xb6 => 0x53f6, 0xb7 => 0x66f3, 0xb8 => 0x814b, + 0xb9 => 0x591c, 0xba => 0x6db2, 0xbb => 0x4e00, 0xbc => 0x58f9, + 0xbd => 0x533b, 0xbe => 0x63d6, 0xbf => 0x94f1, 0xc0 => 0x4f9d, + 0xc1 => 0x4f0a, 0xc2 => 0x8863, 0xc3 => 0x9890, 0xc4 => 0x5937, + 0xc5 => 0x9057, 0xc6 => 0x79fb, 0xc7 => 0x4eea, 0xc8 => 0x80f0, + 0xc9 => 0x7591, 0xca => 0x6c82, 0xcb => 0x5b9c, 0xcc => 0x59e8, + 0xcd => 0x5f5d, 0xce => 0x6905, 0xcf => 0x8681, 0xd0 => 0x501a, + 0xd1 => 0x5df2, 0xd2 => 0x4e59, 0xd3 => 0x77e3, 0xd4 => 0x4ee5, + 0xd5 => 0x827a, 0xd6 => 0x6291, 0xd7 => 0x6613, 0xd8 => 0x9091, + 0xd9 => 0x5c79, 0xda => 0x4ebf, 0xdb => 0x5f79, 0xdc => 0x81c6, + 0xdd => 0x9038, 0xde => 0x8084, 0xdf => 0x75ab, 0xe0 => 0x4ea6, + 0xe1 => 0x88d4, 0xe2 => 0x610f, 0xe3 => 0x6bc5, 0xe4 => 0x5fc6, + 0xe5 => 0x4e49, 0xe6 => 0x76ca, 0xe7 => 0x6ea2, 0xe8 => 0x8be3, + 0xe9 => 0x8bae, 0xea => 0x8c0a, 0xeb => 0x8bd1, 0xec => 0x5f02, + 0xed => 0x7ffc, 0xee => 0x7fcc, 0xef => 0x7ece, 0xf0 => 0x8335, + 0xf1 => 0x836b, 0xf2 => 0x56e0, 0xf3 => 0x6bb7, 0xf4 => 0x97f3, + 0xf5 => 0x9634, 0xf6 => 0x59fb, 0xf7 => 0x541f, 0xf8 => 0x94f6, + 0xf9 => 0x6deb, 0xfa => 0x5bc5, 0xfb => 0x996e, 0xfc => 0x5c39, + 0xfd => 0x5f15, 0xfe => 0x9690, + }, + 0xd3 => { + 0xa1 => 0x5370, 0xa2 => 0x82f1, 0xa3 => 0x6a31, 0xa4 => 0x5a74, + 0xa5 => 0x9e70, 0xa6 => 0x5e94, 0xa7 => 0x7f28, 0xa8 => 0x83b9, + 0xa9 => 0x8424, 0xaa => 0x8425, 0xab => 0x8367, 0xac => 0x8747, + 0xad => 0x8fce, 0xae => 0x8d62, 0xaf => 0x76c8, 0xb0 => 0x5f71, + 0xb1 => 0x9896, 0xb2 => 0x786c, 0xb3 => 0x6620, 0xb4 => 0x54df, + 0xb5 => 0x62e5, 0xb6 => 0x4f63, 0xb7 => 0x81c3, 0xb8 => 0x75c8, + 0xb9 => 0x5eb8, 0xba => 0x96cd, 0xbb => 0x8e0a, 0xbc => 0x86f9, + 0xbd => 0x548f, 0xbe => 0x6cf3, 0xbf => 0x6d8c, 0xc0 => 0x6c38, + 0xc1 => 0x607f, 0xc2 => 0x52c7, 0xc3 => 0x7528, 0xc4 => 0x5e7d, + 0xc5 => 0x4f18, 0xc6 => 0x60a0, 0xc7 => 0x5fe7, 0xc8 => 0x5c24, + 0xc9 => 0x7531, 0xca => 0x90ae, 0xcb => 0x94c0, 0xcc => 0x72b9, + 0xcd => 0x6cb9, 0xce => 0x6e38, 0xcf => 0x9149, 0xd0 => 0x6709, + 0xd1 => 0x53cb, 0xd2 => 0x53f3, 0xd3 => 0x4f51, 0xd4 => 0x91c9, + 0xd5 => 0x8bf1, 0xd6 => 0x53c8, 0xd7 => 0x5e7c, 0xd8 => 0x8fc2, + 0xd9 => 0x6de4, 0xda => 0x4e8e, 0xdb => 0x76c2, 0xdc => 0x6986, + 0xdd => 0x865e, 0xde => 0x611a, 0xdf => 0x8206, 0xe0 => 0x4f59, + 0xe1 => 0x4fde, 0xe2 => 0x903e, 0xe3 => 0x9c7c, 0xe4 => 0x6109, + 0xe5 => 0x6e1d, 0xe6 => 0x6e14, 0xe7 => 0x9685, 0xe8 => 0x4e88, + 0xe9 => 0x5a31, 0xea => 0x96e8, 0xeb => 0x4e0e, 0xec => 0x5c7f, + 0xed => 0x79b9, 0xee => 0x5b87, 0xef => 0x8bed, 0xf0 => 0x7fbd, + 0xf1 => 0x7389, 0xf2 => 0x57df, 0xf3 => 0x828b, 0xf4 => 0x90c1, + 0xf5 => 0x5401, 0xf6 => 0x9047, 0xf7 => 0x55bb, 0xf8 => 0x5cea, + 0xf9 => 0x5fa1, 0xfa => 0x6108, 0xfb => 0x6b32, 0xfc => 0x72f1, + 0xfd => 0x80b2, 0xfe => 0x8a89, + }, + 0xd4 => { + 0xa1 => 0x6d74, 0xa2 => 0x5bd3, 0xa3 => 0x88d5, 0xa4 => 0x9884, + 0xa5 => 0x8c6b, 0xa6 => 0x9a6d, 0xa7 => 0x9e33, 0xa8 => 0x6e0a, + 0xa9 => 0x51a4, 0xaa => 0x5143, 0xab => 0x57a3, 0xac => 0x8881, + 0xad => 0x539f, 0xae => 0x63f4, 0xaf => 0x8f95, 0xb0 => 0x56ed, + 0xb1 => 0x5458, 0xb2 => 0x5706, 0xb3 => 0x733f, 0xb4 => 0x6e90, + 0xb5 => 0x7f18, 0xb6 => 0x8fdc, 0xb7 => 0x82d1, 0xb8 => 0x613f, + 0xb9 => 0x6028, 0xba => 0x9662, 0xbb => 0x66f0, 0xbc => 0x7ea6, + 0xbd => 0x8d8a, 0xbe => 0x8dc3, 0xbf => 0x94a5, 0xc0 => 0x5cb3, + 0xc1 => 0x7ca4, 0xc2 => 0x6708, 0xc3 => 0x60a6, 0xc4 => 0x9605, + 0xc5 => 0x8018, 0xc6 => 0x4e91, 0xc7 => 0x90e7, 0xc8 => 0x5300, + 0xc9 => 0x9668, 0xca => 0x5141, 0xcb => 0x8fd0, 0xcc => 0x8574, + 0xcd => 0x915d, 0xce => 0x6655, 0xcf => 0x97f5, 0xd0 => 0x5b55, + 0xd1 => 0x531d, 0xd2 => 0x7838, 0xd3 => 0x6742, 0xd4 => 0x683d, + 0xd5 => 0x54c9, 0xd6 => 0x707e, 0xd7 => 0x5bb0, 0xd8 => 0x8f7d, + 0xd9 => 0x518d, 0xda => 0x5728, 0xdb => 0x54b1, 0xdc => 0x6512, + 0xdd => 0x6682, 0xde => 0x8d5e, 0xdf => 0x8d43, 0xe0 => 0x810f, + 0xe1 => 0x846c, 0xe2 => 0x906d, 0xe3 => 0x7cdf, 0xe4 => 0x51ff, + 0xe5 => 0x85fb, 0xe6 => 0x67a3, 0xe7 => 0x65e9, 0xe8 => 0x6fa1, + 0xe9 => 0x86a4, 0xea => 0x8e81, 0xeb => 0x566a, 0xec => 0x9020, + 0xed => 0x7682, 0xee => 0x7076, 0xef => 0x71e5, 0xf0 => 0x8d23, + 0xf1 => 0x62e9, 0xf2 => 0x5219, 0xf3 => 0x6cfd, 0xf4 => 0x8d3c, + 0xf5 => 0x600e, 0xf6 => 0x589e, 0xf7 => 0x618e, 0xf8 => 0x66fe, + 0xf9 => 0x8d60, 0xfa => 0x624e, 0xfb => 0x55b3, 0xfc => 0x6e23, + 0xfd => 0x672d, 0xfe => 0x8f67, + }, + 0xd5 => { + 0xa1 => 0x94e1, 0xa2 => 0x95f8, 0xa3 => 0x7728, 0xa4 => 0x6805, + 0xa5 => 0x69a8, 0xa6 => 0x548b, 0xa7 => 0x4e4d, 0xa8 => 0x70b8, + 0xa9 => 0x8bc8, 0xaa => 0x6458, 0xab => 0x658b, 0xac => 0x5b85, + 0xad => 0x7a84, 0xae => 0x503a, 0xaf => 0x5be8, 0xb0 => 0x77bb, + 0xb1 => 0x6be1, 0xb2 => 0x8a79, 0xb3 => 0x7c98, 0xb4 => 0x6cbe, + 0xb5 => 0x76cf, 0xb6 => 0x65a9, 0xb7 => 0x8f97, 0xb8 => 0x5d2d, + 0xb9 => 0x5c55, 0xba => 0x8638, 0xbb => 0x6808, 0xbc => 0x5360, + 0xbd => 0x6218, 0xbe => 0x7ad9, 0xbf => 0x6e5b, 0xc0 => 0x7efd, + 0xc1 => 0x6a1f, 0xc2 => 0x7ae0, 0xc3 => 0x5f70, 0xc4 => 0x6f33, + 0xc5 => 0x5f20, 0xc6 => 0x638c, 0xc7 => 0x6da8, 0xc8 => 0x6756, + 0xc9 => 0x4e08, 0xca => 0x5e10, 0xcb => 0x8d26, 0xcc => 0x4ed7, + 0xcd => 0x80c0, 0xce => 0x7634, 0xcf => 0x969c, 0xd0 => 0x62db, + 0xd1 => 0x662d, 0xd2 => 0x627e, 0xd3 => 0x6cbc, 0xd4 => 0x8d75, + 0xd5 => 0x7167, 0xd6 => 0x7f69, 0xd7 => 0x5146, 0xd8 => 0x8087, + 0xd9 => 0x53ec, 0xda => 0x906e, 0xdb => 0x6298, 0xdc => 0x54f2, + 0xdd => 0x86f0, 0xde => 0x8f99, 0xdf => 0x8005, 0xe0 => 0x9517, + 0xe1 => 0x8517, 0xe2 => 0x8fd9, 0xe3 => 0x6d59, 0xe4 => 0x73cd, + 0xe5 => 0x659f, 0xe6 => 0x771f, 0xe7 => 0x7504, 0xe8 => 0x7827, + 0xe9 => 0x81fb, 0xea => 0x8d1e, 0xeb => 0x9488, 0xec => 0x4fa6, + 0xed => 0x6795, 0xee => 0x75b9, 0xef => 0x8bca, 0xf0 => 0x9707, + 0xf1 => 0x632f, 0xf2 => 0x9547, 0xf3 => 0x9635, 0xf4 => 0x84b8, + 0xf5 => 0x6323, 0xf6 => 0x7741, 0xf7 => 0x5f81, 0xf8 => 0x72f0, + 0xf9 => 0x4e89, 0xfa => 0x6014, 0xfb => 0x6574, 0xfc => 0x62ef, + 0xfd => 0x6b63, 0xfe => 0x653f, + }, + 0xd6 => { + 0xa1 => 0x5e27, 0xa2 => 0x75c7, 0xa3 => 0x90d1, 0xa4 => 0x8bc1, + 0xa5 => 0x829d, 0xa6 => 0x679d, 0xa7 => 0x652f, 0xa8 => 0x5431, + 0xa9 => 0x8718, 0xaa => 0x77e5, 0xab => 0x80a2, 0xac => 0x8102, + 0xad => 0x6c41, 0xae => 0x4e4b, 0xaf => 0x7ec7, 0xb0 => 0x804c, + 0xb1 => 0x76f4, 0xb2 => 0x690d, 0xb3 => 0x6b96, 0xb4 => 0x6267, + 0xb5 => 0x503c, 0xb6 => 0x4f84, 0xb7 => 0x5740, 0xb8 => 0x6307, + 0xb9 => 0x6b62, 0xba => 0x8dbe, 0xbb => 0x53ea, 0xbc => 0x65e8, + 0xbd => 0x7eb8, 0xbe => 0x5fd7, 0xbf => 0x631a, 0xc0 => 0x63b7, + 0xc1 => 0x81f3, 0xc2 => 0x81f4, 0xc3 => 0x7f6e, 0xc4 => 0x5e1c, + 0xc5 => 0x5cd9, 0xc6 => 0x5236, 0xc7 => 0x667a, 0xc8 => 0x79e9, + 0xc9 => 0x7a1a, 0xca => 0x8d28, 0xcb => 0x7099, 0xcc => 0x75d4, + 0xcd => 0x6ede, 0xce => 0x6cbb, 0xcf => 0x7a92, 0xd0 => 0x4e2d, + 0xd1 => 0x76c5, 0xd2 => 0x5fe0, 0xd3 => 0x949f, 0xd4 => 0x8877, + 0xd5 => 0x7ec8, 0xd6 => 0x79cd, 0xd7 => 0x80bf, 0xd8 => 0x91cd, + 0xd9 => 0x4ef2, 0xda => 0x4f17, 0xdb => 0x821f, 0xdc => 0x5468, + 0xdd => 0x5dde, 0xde => 0x6d32, 0xdf => 0x8bcc, 0xe0 => 0x7ca5, + 0xe1 => 0x8f74, 0xe2 => 0x8098, 0xe3 => 0x5e1a, 0xe4 => 0x5492, + 0xe5 => 0x76b1, 0xe6 => 0x5b99, 0xe7 => 0x663c, 0xe8 => 0x9aa4, + 0xe9 => 0x73e0, 0xea => 0x682a, 0xeb => 0x86db, 0xec => 0x6731, + 0xed => 0x732a, 0xee => 0x8bf8, 0xef => 0x8bdb, 0xf0 => 0x9010, + 0xf1 => 0x7af9, 0xf2 => 0x70db, 0xf3 => 0x716e, 0xf4 => 0x62c4, + 0xf5 => 0x77a9, 0xf6 => 0x5631, 0xf7 => 0x4e3b, 0xf8 => 0x8457, + 0xf9 => 0x67f1, 0xfa => 0x52a9, 0xfb => 0x86c0, 0xfc => 0x8d2e, + 0xfd => 0x94f8, 0xfe => 0x7b51, + }, + 0xd7 => { + 0xa1 => 0x4f4f, 0xa2 => 0x6ce8, 0xa3 => 0x795d, 0xa4 => 0x9a7b, + 0xa5 => 0x6293, 0xa6 => 0x722a, 0xa7 => 0x62fd, 0xa8 => 0x4e13, + 0xa9 => 0x7816, 0xaa => 0x8f6c, 0xab => 0x64b0, 0xac => 0x8d5a, + 0xad => 0x7bc6, 0xae => 0x6869, 0xaf => 0x5e84, 0xb0 => 0x88c5, + 0xb1 => 0x5986, 0xb2 => 0x649e, 0xb3 => 0x58ee, 0xb4 => 0x72b6, + 0xb5 => 0x690e, 0xb6 => 0x9525, 0xb7 => 0x8ffd, 0xb8 => 0x8d58, + 0xb9 => 0x5760, 0xba => 0x7f00, 0xbb => 0x8c06, 0xbc => 0x51c6, + 0xbd => 0x6349, 0xbe => 0x62d9, 0xbf => 0x5353, 0xc0 => 0x684c, + 0xc1 => 0x7422, 0xc2 => 0x8301, 0xc3 => 0x914c, 0xc4 => 0x5544, + 0xc5 => 0x7740, 0xc6 => 0x707c, 0xc7 => 0x6d4a, 0xc8 => 0x5179, + 0xc9 => 0x54a8, 0xca => 0x8d44, 0xcb => 0x59ff, 0xcc => 0x6ecb, + 0xcd => 0x6dc4, 0xce => 0x5b5c, 0xcf => 0x7d2b, 0xd0 => 0x4ed4, + 0xd1 => 0x7c7d, 0xd2 => 0x6ed3, 0xd3 => 0x5b50, 0xd4 => 0x81ea, + 0xd5 => 0x6e0d, 0xd6 => 0x5b57, 0xd7 => 0x9b03, 0xd8 => 0x68d5, + 0xd9 => 0x8e2a, 0xda => 0x5b97, 0xdb => 0x7efc, 0xdc => 0x603b, + 0xdd => 0x7eb5, 0xde => 0x90b9, 0xdf => 0x8d70, 0xe0 => 0x594f, + 0xe1 => 0x63cd, 0xe2 => 0x79df, 0xe3 => 0x8db3, 0xe4 => 0x5352, + 0xe5 => 0x65cf, 0xe6 => 0x7956, 0xe7 => 0x8bc5, 0xe8 => 0x963b, + 0xe9 => 0x7ec4, 0xea => 0x94bb, 0xeb => 0x7e82, 0xec => 0x5634, + 0xed => 0x9189, 0xee => 0x6700, 0xef => 0x7f6a, 0xf0 => 0x5c0a, + 0xf1 => 0x9075, 0xf2 => 0x6628, 0xf3 => 0x5de6, 0xf4 => 0x4f50, + 0xf5 => 0x67de, 0xf6 => 0x505a, 0xf7 => 0x4f5c, 0xf8 => 0x5750, + 0xf9 => 0x5ea7, + }, + 0xd8 => { + 0xa1 => 0x4e8d, 0xa2 => 0x4e0c, 0xa3 => 0x5140, 0xa4 => 0x4e10, + 0xa5 => 0x5eff, 0xa6 => 0x5345, 0xa7 => 0x4e15, 0xa8 => 0x4e98, + 0xa9 => 0x4e1e, 0xaa => 0x9b32, 0xab => 0x5b6c, 0xac => 0x5669, + 0xad => 0x4e28, 0xae => 0x79ba, 0xaf => 0x4e3f, 0xb0 => 0x5315, + 0xb1 => 0x4e47, 0xb2 => 0x592d, 0xb3 => 0x723b, 0xb4 => 0x536e, + 0xb5 => 0x6c10, 0xb6 => 0x56df, 0xb7 => 0x80e4, 0xb8 => 0x9997, + 0xb9 => 0x6bd3, 0xba => 0x777e, 0xbb => 0x9f17, 0xbc => 0x4e36, + 0xbd => 0x4e9f, 0xbe => 0x9f10, 0xbf => 0x4e5c, 0xc0 => 0x4e69, + 0xc1 => 0x4e93, 0xc2 => 0x8288, 0xc3 => 0x5b5b, 0xc4 => 0x556c, + 0xc5 => 0x560f, 0xc6 => 0x4ec4, 0xc7 => 0x538d, 0xc8 => 0x539d, + 0xc9 => 0x53a3, 0xca => 0x53a5, 0xcb => 0x53ae, 0xcc => 0x9765, + 0xcd => 0x8d5d, 0xce => 0x531a, 0xcf => 0x53f5, 0xd0 => 0x5326, + 0xd1 => 0x532e, 0xd2 => 0x533e, 0xd3 => 0x8d5c, 0xd4 => 0x5366, + 0xd5 => 0x5363, 0xd6 => 0x5202, 0xd7 => 0x5208, 0xd8 => 0x520e, + 0xd9 => 0x522d, 0xda => 0x5233, 0xdb => 0x523f, 0xdc => 0x5240, + 0xdd => 0x524c, 0xde => 0x525e, 0xdf => 0x5261, 0xe0 => 0x525c, + 0xe1 => 0x84af, 0xe2 => 0x527d, 0xe3 => 0x5282, 0xe4 => 0x5281, + 0xe5 => 0x5290, 0xe6 => 0x5293, 0xe7 => 0x5182, 0xe8 => 0x7f54, + 0xe9 => 0x4ebb, 0xea => 0x4ec3, 0xeb => 0x4ec9, 0xec => 0x4ec2, + 0xed => 0x4ee8, 0xee => 0x4ee1, 0xef => 0x4eeb, 0xf0 => 0x4ede, + 0xf1 => 0x4f1b, 0xf2 => 0x4ef3, 0xf3 => 0x4f22, 0xf4 => 0x4f64, + 0xf5 => 0x4ef5, 0xf6 => 0x4f25, 0xf7 => 0x4f27, 0xf8 => 0x4f09, + 0xf9 => 0x4f2b, 0xfa => 0x4f5e, 0xfb => 0x4f67, 0xfc => 0x6538, + 0xfd => 0x4f5a, 0xfe => 0x4f5d, + }, + 0xd9 => { + 0xa1 => 0x4f5f, 0xa2 => 0x4f57, 0xa3 => 0x4f32, 0xa4 => 0x4f3d, + 0xa5 => 0x4f76, 0xa6 => 0x4f74, 0xa7 => 0x4f91, 0xa8 => 0x4f89, + 0xa9 => 0x4f83, 0xaa => 0x4f8f, 0xab => 0x4f7e, 0xac => 0x4f7b, + 0xad => 0x4faa, 0xae => 0x4f7c, 0xaf => 0x4fac, 0xb0 => 0x4f94, + 0xb1 => 0x4fe6, 0xb2 => 0x4fe8, 0xb3 => 0x4fea, 0xb4 => 0x4fc5, + 0xb5 => 0x4fda, 0xb6 => 0x4fe3, 0xb7 => 0x4fdc, 0xb8 => 0x4fd1, + 0xb9 => 0x4fdf, 0xba => 0x4ff8, 0xbb => 0x5029, 0xbc => 0x504c, + 0xbd => 0x4ff3, 0xbe => 0x502c, 0xbf => 0x500f, 0xc0 => 0x502e, + 0xc1 => 0x502d, 0xc2 => 0x4ffe, 0xc3 => 0x501c, 0xc4 => 0x500c, + 0xc5 => 0x5025, 0xc6 => 0x5028, 0xc7 => 0x507e, 0xc8 => 0x5043, + 0xc9 => 0x5055, 0xca => 0x5048, 0xcb => 0x504e, 0xcc => 0x506c, + 0xcd => 0x507b, 0xce => 0x50a5, 0xcf => 0x50a7, 0xd0 => 0x50a9, + 0xd1 => 0x50ba, 0xd2 => 0x50d6, 0xd3 => 0x5106, 0xd4 => 0x50ed, + 0xd5 => 0x50ec, 0xd6 => 0x50e6, 0xd7 => 0x50ee, 0xd8 => 0x5107, + 0xd9 => 0x510b, 0xda => 0x4edd, 0xdb => 0x6c3d, 0xdc => 0x4f58, + 0xdd => 0x4f65, 0xde => 0x4fce, 0xdf => 0x9fa0, 0xe0 => 0x6c46, + 0xe1 => 0x7c74, 0xe2 => 0x516e, 0xe3 => 0x5dfd, 0xe4 => 0x9ec9, + 0xe5 => 0x9998, 0xe6 => 0x5181, 0xe7 => 0x5914, 0xe8 => 0x52f9, + 0xe9 => 0x530d, 0xea => 0x8a07, 0xeb => 0x5310, 0xec => 0x51eb, + 0xed => 0x5919, 0xee => 0x5155, 0xef => 0x4ea0, 0xf0 => 0x5156, + 0xf1 => 0x4eb3, 0xf2 => 0x886e, 0xf3 => 0x88a4, 0xf4 => 0x4eb5, + 0xf5 => 0x8114, 0xf6 => 0x88d2, 0xf7 => 0x7980, 0xf8 => 0x5b34, + 0xf9 => 0x8803, 0xfa => 0x7fb8, 0xfb => 0x51ab, 0xfc => 0x51b1, + 0xfd => 0x51bd, 0xfe => 0x51bc, + }, + 0xda => { + 0xa1 => 0x51c7, 0xa2 => 0x5196, 0xa3 => 0x51a2, 0xa4 => 0x51a5, + 0xa5 => 0x8ba0, 0xa6 => 0x8ba6, 0xa7 => 0x8ba7, 0xa8 => 0x8baa, + 0xa9 => 0x8bb4, 0xaa => 0x8bb5, 0xab => 0x8bb7, 0xac => 0x8bc2, + 0xad => 0x8bc3, 0xae => 0x8bcb, 0xaf => 0x8bcf, 0xb0 => 0x8bce, + 0xb1 => 0x8bd2, 0xb2 => 0x8bd3, 0xb3 => 0x8bd4, 0xb4 => 0x8bd6, + 0xb5 => 0x8bd8, 0xb6 => 0x8bd9, 0xb7 => 0x8bdc, 0xb8 => 0x8bdf, + 0xb9 => 0x8be0, 0xba => 0x8be4, 0xbb => 0x8be8, 0xbc => 0x8be9, + 0xbd => 0x8bee, 0xbe => 0x8bf0, 0xbf => 0x8bf3, 0xc0 => 0x8bf6, + 0xc1 => 0x8bf9, 0xc2 => 0x8bfc, 0xc3 => 0x8bff, 0xc4 => 0x8c00, + 0xc5 => 0x8c02, 0xc6 => 0x8c04, 0xc7 => 0x8c07, 0xc8 => 0x8c0c, + 0xc9 => 0x8c0f, 0xca => 0x8c11, 0xcb => 0x8c12, 0xcc => 0x8c14, + 0xcd => 0x8c15, 0xce => 0x8c16, 0xcf => 0x8c19, 0xd0 => 0x8c1b, + 0xd1 => 0x8c18, 0xd2 => 0x8c1d, 0xd3 => 0x8c1f, 0xd4 => 0x8c20, + 0xd5 => 0x8c21, 0xd6 => 0x8c25, 0xd7 => 0x8c27, 0xd8 => 0x8c2a, + 0xd9 => 0x8c2b, 0xda => 0x8c2e, 0xdb => 0x8c2f, 0xdc => 0x8c32, + 0xdd => 0x8c33, 0xde => 0x8c35, 0xdf => 0x8c36, 0xe0 => 0x5369, + 0xe1 => 0x537a, 0xe2 => 0x961d, 0xe3 => 0x9622, 0xe4 => 0x9621, + 0xe5 => 0x9631, 0xe6 => 0x962a, 0xe7 => 0x963d, 0xe8 => 0x963c, + 0xe9 => 0x9642, 0xea => 0x9649, 0xeb => 0x9654, 0xec => 0x965f, + 0xed => 0x9667, 0xee => 0x966c, 0xef => 0x9672, 0xf0 => 0x9674, + 0xf1 => 0x9688, 0xf2 => 0x968d, 0xf3 => 0x9697, 0xf4 => 0x96b0, + 0xf5 => 0x9097, 0xf6 => 0x909b, 0xf7 => 0x909d, 0xf8 => 0x9099, + 0xf9 => 0x90ac, 0xfa => 0x90a1, 0xfb => 0x90b4, 0xfc => 0x90b3, + 0xfd => 0x90b6, 0xfe => 0x90ba, + }, + 0xdb => { + 0xa1 => 0x90b8, 0xa2 => 0x90b0, 0xa3 => 0x90cf, 0xa4 => 0x90c5, + 0xa5 => 0x90be, 0xa6 => 0x90d0, 0xa7 => 0x90c4, 0xa8 => 0x90c7, + 0xa9 => 0x90d3, 0xaa => 0x90e6, 0xab => 0x90e2, 0xac => 0x90dc, + 0xad => 0x90d7, 0xae => 0x90db, 0xaf => 0x90eb, 0xb0 => 0x90ef, + 0xb1 => 0x90fe, 0xb2 => 0x9104, 0xb3 => 0x9122, 0xb4 => 0x911e, + 0xb5 => 0x9123, 0xb6 => 0x9131, 0xb7 => 0x912f, 0xb8 => 0x9139, + 0xb9 => 0x9143, 0xba => 0x9146, 0xbb => 0x520d, 0xbc => 0x5942, + 0xbd => 0x52a2, 0xbe => 0x52ac, 0xbf => 0x52ad, 0xc0 => 0x52be, + 0xc1 => 0x54ff, 0xc2 => 0x52d0, 0xc3 => 0x52d6, 0xc4 => 0x52f0, + 0xc5 => 0x53df, 0xc6 => 0x71ee, 0xc7 => 0x77cd, 0xc8 => 0x5ef4, + 0xc9 => 0x51f5, 0xca => 0x51fc, 0xcb => 0x9b2f, 0xcc => 0x53b6, + 0xcd => 0x5f01, 0xce => 0x755a, 0xcf => 0x5def, 0xd0 => 0x574c, + 0xd1 => 0x57a9, 0xd2 => 0x57a1, 0xd3 => 0x587e, 0xd4 => 0x58bc, + 0xd5 => 0x58c5, 0xd6 => 0x58d1, 0xd7 => 0x5729, 0xd8 => 0x572c, + 0xd9 => 0x572a, 0xda => 0x5733, 0xdb => 0x5739, 0xdc => 0x572e, + 0xdd => 0x572f, 0xde => 0x575c, 0xdf => 0x573b, 0xe0 => 0x5742, + 0xe1 => 0x5769, 0xe2 => 0x5785, 0xe3 => 0x576b, 0xe4 => 0x5786, + 0xe5 => 0x577c, 0xe6 => 0x577b, 0xe7 => 0x5768, 0xe8 => 0x576d, + 0xe9 => 0x5776, 0xea => 0x5773, 0xeb => 0x57ad, 0xec => 0x57a4, + 0xed => 0x578c, 0xee => 0x57b2, 0xef => 0x57cf, 0xf0 => 0x57a7, + 0xf1 => 0x57b4, 0xf2 => 0x5793, 0xf3 => 0x57a0, 0xf4 => 0x57d5, + 0xf5 => 0x57d8, 0xf6 => 0x57da, 0xf7 => 0x57d9, 0xf8 => 0x57d2, + 0xf9 => 0x57b8, 0xfa => 0x57f4, 0xfb => 0x57ef, 0xfc => 0x57f8, + 0xfd => 0x57e4, 0xfe => 0x57dd, + }, + 0xdc => { + 0xa1 => 0x580b, 0xa2 => 0x580d, 0xa3 => 0x57fd, 0xa4 => 0x57ed, + 0xa5 => 0x5800, 0xa6 => 0x581e, 0xa7 => 0x5819, 0xa8 => 0x5844, + 0xa9 => 0x5820, 0xaa => 0x5865, 0xab => 0x586c, 0xac => 0x5881, + 0xad => 0x5889, 0xae => 0x589a, 0xaf => 0x5880, 0xb0 => 0x99a8, + 0xb1 => 0x9f19, 0xb2 => 0x61ff, 0xb3 => 0x8279, 0xb4 => 0x827d, + 0xb5 => 0x827f, 0xb6 => 0x828f, 0xb7 => 0x828a, 0xb8 => 0x82a8, + 0xb9 => 0x8284, 0xba => 0x828e, 0xbb => 0x8291, 0xbc => 0x8297, + 0xbd => 0x8299, 0xbe => 0x82ab, 0xbf => 0x82b8, 0xc0 => 0x82be, + 0xc1 => 0x82b0, 0xc2 => 0x82c8, 0xc3 => 0x82ca, 0xc4 => 0x82e3, + 0xc5 => 0x8298, 0xc6 => 0x82b7, 0xc7 => 0x82ae, 0xc8 => 0x82cb, + 0xc9 => 0x82cc, 0xca => 0x82c1, 0xcb => 0x82a9, 0xcc => 0x82b4, + 0xcd => 0x82a1, 0xce => 0x82aa, 0xcf => 0x829f, 0xd0 => 0x82c4, + 0xd1 => 0x82ce, 0xd2 => 0x82a4, 0xd3 => 0x82e1, 0xd4 => 0x8309, + 0xd5 => 0x82f7, 0xd6 => 0x82e4, 0xd7 => 0x830f, 0xd8 => 0x8307, + 0xd9 => 0x82dc, 0xda => 0x82f4, 0xdb => 0x82d2, 0xdc => 0x82d8, + 0xdd => 0x830c, 0xde => 0x82fb, 0xdf => 0x82d3, 0xe0 => 0x8311, + 0xe1 => 0x831a, 0xe2 => 0x8306, 0xe3 => 0x8314, 0xe4 => 0x8315, + 0xe5 => 0x82e0, 0xe6 => 0x82d5, 0xe7 => 0x831c, 0xe8 => 0x8351, + 0xe9 => 0x835b, 0xea => 0x835c, 0xeb => 0x8308, 0xec => 0x8392, + 0xed => 0x833c, 0xee => 0x8334, 0xef => 0x8331, 0xf0 => 0x839b, + 0xf1 => 0x835e, 0xf2 => 0x832f, 0xf3 => 0x834f, 0xf4 => 0x8347, + 0xf5 => 0x8343, 0xf6 => 0x835f, 0xf7 => 0x8340, 0xf8 => 0x8317, + 0xf9 => 0x8360, 0xfa => 0x832d, 0xfb => 0x833a, 0xfc => 0x8333, + 0xfd => 0x8366, 0xfe => 0x8365, + }, + 0xdd => { + 0xa1 => 0x8368, 0xa2 => 0x831b, 0xa3 => 0x8369, 0xa4 => 0x836c, + 0xa5 => 0x836a, 0xa6 => 0x836d, 0xa7 => 0x836e, 0xa8 => 0x83b0, + 0xa9 => 0x8378, 0xaa => 0x83b3, 0xab => 0x83b4, 0xac => 0x83a0, + 0xad => 0x83aa, 0xae => 0x8393, 0xaf => 0x839c, 0xb0 => 0x8385, + 0xb1 => 0x837c, 0xb2 => 0x83b6, 0xb3 => 0x83a9, 0xb4 => 0x837d, + 0xb5 => 0x83b8, 0xb6 => 0x837b, 0xb7 => 0x8398, 0xb8 => 0x839e, + 0xb9 => 0x83a8, 0xba => 0x83ba, 0xbb => 0x83bc, 0xbc => 0x83c1, + 0xbd => 0x8401, 0xbe => 0x83e5, 0xbf => 0x83d8, 0xc0 => 0x5807, + 0xc1 => 0x8418, 0xc2 => 0x840b, 0xc3 => 0x83dd, 0xc4 => 0x83fd, + 0xc5 => 0x83d6, 0xc6 => 0x841c, 0xc7 => 0x8438, 0xc8 => 0x8411, + 0xc9 => 0x8406, 0xca => 0x83d4, 0xcb => 0x83df, 0xcc => 0x840f, + 0xcd => 0x8403, 0xce => 0x83f8, 0xcf => 0x83f9, 0xd0 => 0x83ea, + 0xd1 => 0x83c5, 0xd2 => 0x83c0, 0xd3 => 0x8426, 0xd4 => 0x83f0, + 0xd5 => 0x83e1, 0xd6 => 0x845c, 0xd7 => 0x8451, 0xd8 => 0x845a, + 0xd9 => 0x8459, 0xda => 0x8473, 0xdb => 0x8487, 0xdc => 0x8488, + 0xdd => 0x847a, 0xde => 0x8489, 0xdf => 0x8478, 0xe0 => 0x843c, + 0xe1 => 0x8446, 0xe2 => 0x8469, 0xe3 => 0x8476, 0xe4 => 0x848c, + 0xe5 => 0x848e, 0xe6 => 0x8431, 0xe7 => 0x846d, 0xe8 => 0x84c1, + 0xe9 => 0x84cd, 0xea => 0x84d0, 0xeb => 0x84e6, 0xec => 0x84bd, + 0xed => 0x84d3, 0xee => 0x84ca, 0xef => 0x84bf, 0xf0 => 0x84ba, + 0xf1 => 0x84e0, 0xf2 => 0x84a1, 0xf3 => 0x84b9, 0xf4 => 0x84b4, + 0xf5 => 0x8497, 0xf6 => 0x84e5, 0xf7 => 0x84e3, 0xf8 => 0x850c, + 0xf9 => 0x750d, 0xfa => 0x8538, 0xfb => 0x84f0, 0xfc => 0x8539, + 0xfd => 0x851f, 0xfe => 0x853a, + }, + 0xde => { + 0xa1 => 0x8556, 0xa2 => 0x853b, 0xa3 => 0x84ff, 0xa4 => 0x84fc, + 0xa5 => 0x8559, 0xa6 => 0x8548, 0xa7 => 0x8568, 0xa8 => 0x8564, + 0xa9 => 0x855e, 0xaa => 0x857a, 0xab => 0x77a2, 0xac => 0x8543, + 0xad => 0x8572, 0xae => 0x857b, 0xaf => 0x85a4, 0xb0 => 0x85a8, + 0xb1 => 0x8587, 0xb2 => 0x858f, 0xb3 => 0x8579, 0xb4 => 0x85ae, + 0xb5 => 0x859c, 0xb6 => 0x8585, 0xb7 => 0x85b9, 0xb8 => 0x85b7, + 0xb9 => 0x85b0, 0xba => 0x85d3, 0xbb => 0x85c1, 0xbc => 0x85dc, + 0xbd => 0x85ff, 0xbe => 0x8627, 0xbf => 0x8605, 0xc0 => 0x8629, + 0xc1 => 0x8616, 0xc2 => 0x863c, 0xc3 => 0x5efe, 0xc4 => 0x5f08, + 0xc5 => 0x593c, 0xc6 => 0x5941, 0xc7 => 0x8037, 0xc8 => 0x5955, + 0xc9 => 0x595a, 0xca => 0x5958, 0xcb => 0x530f, 0xcc => 0x5c22, + 0xcd => 0x5c25, 0xce => 0x5c2c, 0xcf => 0x5c34, 0xd0 => 0x624c, + 0xd1 => 0x626a, 0xd2 => 0x629f, 0xd3 => 0x62bb, 0xd4 => 0x62ca, + 0xd5 => 0x62da, 0xd6 => 0x62d7, 0xd7 => 0x62ee, 0xd8 => 0x6322, + 0xd9 => 0x62f6, 0xda => 0x6339, 0xdb => 0x634b, 0xdc => 0x6343, + 0xdd => 0x63ad, 0xde => 0x63f6, 0xdf => 0x6371, 0xe0 => 0x637a, + 0xe1 => 0x638e, 0xe2 => 0x63b4, 0xe3 => 0x636d, 0xe4 => 0x63ac, + 0xe5 => 0x638a, 0xe6 => 0x6369, 0xe7 => 0x63ae, 0xe8 => 0x63bc, + 0xe9 => 0x63f2, 0xea => 0x63f8, 0xeb => 0x63e0, 0xec => 0x63ff, + 0xed => 0x63c4, 0xee => 0x63de, 0xef => 0x63ce, 0xf0 => 0x6452, + 0xf1 => 0x63c6, 0xf2 => 0x63be, 0xf3 => 0x6445, 0xf4 => 0x6441, + 0xf5 => 0x640b, 0xf6 => 0x641b, 0xf7 => 0x6420, 0xf8 => 0x640c, + 0xf9 => 0x6426, 0xfa => 0x6421, 0xfb => 0x645e, 0xfc => 0x6484, + 0xfd => 0x646d, 0xfe => 0x6496, + }, + 0xdf => { + 0xa1 => 0x647a, 0xa2 => 0x64b7, 0xa3 => 0x64b8, 0xa4 => 0x6499, + 0xa5 => 0x64ba, 0xa6 => 0x64c0, 0xa7 => 0x64d0, 0xa8 => 0x64d7, + 0xa9 => 0x64e4, 0xaa => 0x64e2, 0xab => 0x6509, 0xac => 0x6525, + 0xad => 0x652e, 0xae => 0x5f0b, 0xaf => 0x5fd2, 0xb0 => 0x7519, + 0xb1 => 0x5f11, 0xb2 => 0x535f, 0xb3 => 0x53f1, 0xb4 => 0x53fd, + 0xb5 => 0x53e9, 0xb6 => 0x53e8, 0xb7 => 0x53fb, 0xb8 => 0x5412, + 0xb9 => 0x5416, 0xba => 0x5406, 0xbb => 0x544b, 0xbc => 0x5452, + 0xbd => 0x5453, 0xbe => 0x5454, 0xbf => 0x5456, 0xc0 => 0x5443, + 0xc1 => 0x5421, 0xc2 => 0x5457, 0xc3 => 0x5459, 0xc4 => 0x5423, + 0xc5 => 0x5432, 0xc6 => 0x5482, 0xc7 => 0x5494, 0xc8 => 0x5477, + 0xc9 => 0x5471, 0xca => 0x5464, 0xcb => 0x549a, 0xcc => 0x549b, + 0xcd => 0x5484, 0xce => 0x5476, 0xcf => 0x5466, 0xd0 => 0x549d, + 0xd1 => 0x54d0, 0xd2 => 0x54ad, 0xd3 => 0x54c2, 0xd4 => 0x54b4, + 0xd5 => 0x54d2, 0xd6 => 0x54a7, 0xd7 => 0x54a6, 0xd8 => 0x54d3, + 0xd9 => 0x54d4, 0xda => 0x5472, 0xdb => 0x54a3, 0xdc => 0x54d5, + 0xdd => 0x54bb, 0xde => 0x54bf, 0xdf => 0x54cc, 0xe0 => 0x54d9, + 0xe1 => 0x54da, 0xe2 => 0x54dc, 0xe3 => 0x54a9, 0xe4 => 0x54aa, + 0xe5 => 0x54a4, 0xe6 => 0x54dd, 0xe7 => 0x54cf, 0xe8 => 0x54de, + 0xe9 => 0x551b, 0xea => 0x54e7, 0xeb => 0x5520, 0xec => 0x54fd, + 0xed => 0x5514, 0xee => 0x54f3, 0xef => 0x5522, 0xf0 => 0x5523, + 0xf1 => 0x550f, 0xf2 => 0x5511, 0xf3 => 0x5527, 0xf4 => 0x552a, + 0xf5 => 0x5567, 0xf6 => 0x558f, 0xf7 => 0x55b5, 0xf8 => 0x5549, + 0xf9 => 0x556d, 0xfa => 0x5541, 0xfb => 0x5555, 0xfc => 0x553f, + 0xfd => 0x5550, 0xfe => 0x553c, + }, + 0xe0 => { + 0xa1 => 0x5537, 0xa2 => 0x5556, 0xa3 => 0x5575, 0xa4 => 0x5576, + 0xa5 => 0x5577, 0xa6 => 0x5533, 0xa7 => 0x5530, 0xa8 => 0x555c, + 0xa9 => 0x558b, 0xaa => 0x55d2, 0xab => 0x5583, 0xac => 0x55b1, + 0xad => 0x55b9, 0xae => 0x5588, 0xaf => 0x5581, 0xb0 => 0x559f, + 0xb1 => 0x557e, 0xb2 => 0x55d6, 0xb3 => 0x5591, 0xb4 => 0x557b, + 0xb5 => 0x55df, 0xb6 => 0x55bd, 0xb7 => 0x55be, 0xb8 => 0x5594, + 0xb9 => 0x5599, 0xba => 0x55ea, 0xbb => 0x55f7, 0xbc => 0x55c9, + 0xbd => 0x561f, 0xbe => 0x55d1, 0xbf => 0x55eb, 0xc0 => 0x55ec, + 0xc1 => 0x55d4, 0xc2 => 0x55e6, 0xc3 => 0x55dd, 0xc4 => 0x55c4, + 0xc5 => 0x55ef, 0xc6 => 0x55e5, 0xc7 => 0x55f2, 0xc8 => 0x55f3, + 0xc9 => 0x55cc, 0xca => 0x55cd, 0xcb => 0x55e8, 0xcc => 0x55f5, + 0xcd => 0x55e4, 0xce => 0x8f94, 0xcf => 0x561e, 0xd0 => 0x5608, + 0xd1 => 0x560c, 0xd2 => 0x5601, 0xd3 => 0x5624, 0xd4 => 0x5623, + 0xd5 => 0x55fe, 0xd6 => 0x5600, 0xd7 => 0x5627, 0xd8 => 0x562d, + 0xd9 => 0x5658, 0xda => 0x5639, 0xdb => 0x5657, 0xdc => 0x562c, + 0xdd => 0x564d, 0xde => 0x5662, 0xdf => 0x5659, 0xe0 => 0x565c, + 0xe1 => 0x564c, 0xe2 => 0x5654, 0xe3 => 0x5686, 0xe4 => 0x5664, + 0xe5 => 0x5671, 0xe6 => 0x566b, 0xe7 => 0x567b, 0xe8 => 0x567c, + 0xe9 => 0x5685, 0xea => 0x5693, 0xeb => 0x56af, 0xec => 0x56d4, + 0xed => 0x56d7, 0xee => 0x56dd, 0xef => 0x56e1, 0xf0 => 0x56f5, + 0xf1 => 0x56eb, 0xf2 => 0x56f9, 0xf3 => 0x56ff, 0xf4 => 0x5704, + 0xf5 => 0x570a, 0xf6 => 0x5709, 0xf7 => 0x571c, 0xf8 => 0x5e0f, + 0xf9 => 0x5e19, 0xfa => 0x5e14, 0xfb => 0x5e11, 0xfc => 0x5e31, + 0xfd => 0x5e3b, 0xfe => 0x5e3c, + }, + 0xe1 => { + 0xa1 => 0x5e37, 0xa2 => 0x5e44, 0xa3 => 0x5e54, 0xa4 => 0x5e5b, + 0xa5 => 0x5e5e, 0xa6 => 0x5e61, 0xa7 => 0x5c8c, 0xa8 => 0x5c7a, + 0xa9 => 0x5c8d, 0xaa => 0x5c90, 0xab => 0x5c96, 0xac => 0x5c88, + 0xad => 0x5c98, 0xae => 0x5c99, 0xaf => 0x5c91, 0xb0 => 0x5c9a, + 0xb1 => 0x5c9c, 0xb2 => 0x5cb5, 0xb3 => 0x5ca2, 0xb4 => 0x5cbd, + 0xb5 => 0x5cac, 0xb6 => 0x5cab, 0xb7 => 0x5cb1, 0xb8 => 0x5ca3, + 0xb9 => 0x5cc1, 0xba => 0x5cb7, 0xbb => 0x5cc4, 0xbc => 0x5cd2, + 0xbd => 0x5ce4, 0xbe => 0x5ccb, 0xbf => 0x5ce5, 0xc0 => 0x5d02, + 0xc1 => 0x5d03, 0xc2 => 0x5d27, 0xc3 => 0x5d26, 0xc4 => 0x5d2e, + 0xc5 => 0x5d24, 0xc6 => 0x5d1e, 0xc7 => 0x5d06, 0xc8 => 0x5d1b, + 0xc9 => 0x5d58, 0xca => 0x5d3e, 0xcb => 0x5d34, 0xcc => 0x5d3d, + 0xcd => 0x5d6c, 0xce => 0x5d5b, 0xcf => 0x5d6f, 0xd0 => 0x5d5d, + 0xd1 => 0x5d6b, 0xd2 => 0x5d4b, 0xd3 => 0x5d4a, 0xd4 => 0x5d69, + 0xd5 => 0x5d74, 0xd6 => 0x5d82, 0xd7 => 0x5d99, 0xd8 => 0x5d9d, + 0xd9 => 0x8c73, 0xda => 0x5db7, 0xdb => 0x5dc5, 0xdc => 0x5f73, + 0xdd => 0x5f77, 0xde => 0x5f82, 0xdf => 0x5f87, 0xe0 => 0x5f89, + 0xe1 => 0x5f8c, 0xe2 => 0x5f95, 0xe3 => 0x5f99, 0xe4 => 0x5f9c, + 0xe5 => 0x5fa8, 0xe6 => 0x5fad, 0xe7 => 0x5fb5, 0xe8 => 0x5fbc, + 0xe9 => 0x8862, 0xea => 0x5f61, 0xeb => 0x72ad, 0xec => 0x72b0, + 0xed => 0x72b4, 0xee => 0x72b7, 0xef => 0x72b8, 0xf0 => 0x72c3, + 0xf1 => 0x72c1, 0xf2 => 0x72ce, 0xf3 => 0x72cd, 0xf4 => 0x72d2, + 0xf5 => 0x72e8, 0xf6 => 0x72ef, 0xf7 => 0x72e9, 0xf8 => 0x72f2, + 0xf9 => 0x72f4, 0xfa => 0x72f7, 0xfb => 0x7301, 0xfc => 0x72f3, + 0xfd => 0x7303, 0xfe => 0x72fa, + }, + 0xe2 => { + 0xa1 => 0x72fb, 0xa2 => 0x7317, 0xa3 => 0x7313, 0xa4 => 0x7321, + 0xa5 => 0x730a, 0xa6 => 0x731e, 0xa7 => 0x731d, 0xa8 => 0x7315, + 0xa9 => 0x7322, 0xaa => 0x7339, 0xab => 0x7325, 0xac => 0x732c, + 0xad => 0x7338, 0xae => 0x7331, 0xaf => 0x7350, 0xb0 => 0x734d, + 0xb1 => 0x7357, 0xb2 => 0x7360, 0xb3 => 0x736c, 0xb4 => 0x736f, + 0xb5 => 0x737e, 0xb6 => 0x821b, 0xb7 => 0x5925, 0xb8 => 0x98e7, + 0xb9 => 0x5924, 0xba => 0x5902, 0xbb => 0x9963, 0xbc => 0x9967, + 0xbd => 0x9968, 0xbe => 0x9969, 0xbf => 0x996a, 0xc0 => 0x996b, + 0xc1 => 0x996c, 0xc2 => 0x9974, 0xc3 => 0x9977, 0xc4 => 0x997d, + 0xc5 => 0x9980, 0xc6 => 0x9984, 0xc7 => 0x9987, 0xc8 => 0x998a, + 0xc9 => 0x998d, 0xca => 0x9990, 0xcb => 0x9991, 0xcc => 0x9993, + 0xcd => 0x9994, 0xce => 0x9995, 0xcf => 0x5e80, 0xd0 => 0x5e91, + 0xd1 => 0x5e8b, 0xd2 => 0x5e96, 0xd3 => 0x5ea5, 0xd4 => 0x5ea0, + 0xd5 => 0x5eb9, 0xd6 => 0x5eb5, 0xd7 => 0x5ebe, 0xd8 => 0x5eb3, + 0xd9 => 0x8d53, 0xda => 0x5ed2, 0xdb => 0x5ed1, 0xdc => 0x5edb, + 0xdd => 0x5ee8, 0xde => 0x5eea, 0xdf => 0x81ba, 0xe0 => 0x5fc4, + 0xe1 => 0x5fc9, 0xe2 => 0x5fd6, 0xe3 => 0x5fcf, 0xe4 => 0x6003, + 0xe5 => 0x5fee, 0xe6 => 0x6004, 0xe7 => 0x5fe1, 0xe8 => 0x5fe4, + 0xe9 => 0x5ffe, 0xea => 0x6005, 0xeb => 0x6006, 0xec => 0x5fea, + 0xed => 0x5fed, 0xee => 0x5ff8, 0xef => 0x6019, 0xf0 => 0x6035, + 0xf1 => 0x6026, 0xf2 => 0x601b, 0xf3 => 0x600f, 0xf4 => 0x600d, + 0xf5 => 0x6029, 0xf6 => 0x602b, 0xf7 => 0x600a, 0xf8 => 0x603f, + 0xf9 => 0x6021, 0xfa => 0x6078, 0xfb => 0x6079, 0xfc => 0x607b, + 0xfd => 0x607a, 0xfe => 0x6042, + }, + 0xe3 => { + 0xa1 => 0x606a, 0xa2 => 0x607d, 0xa3 => 0x6096, 0xa4 => 0x609a, + 0xa5 => 0x60ad, 0xa6 => 0x609d, 0xa7 => 0x6083, 0xa8 => 0x6092, + 0xa9 => 0x608c, 0xaa => 0x609b, 0xab => 0x60ec, 0xac => 0x60bb, + 0xad => 0x60b1, 0xae => 0x60dd, 0xaf => 0x60d8, 0xb0 => 0x60c6, + 0xb1 => 0x60da, 0xb2 => 0x60b4, 0xb3 => 0x6120, 0xb4 => 0x6126, + 0xb5 => 0x6115, 0xb6 => 0x6123, 0xb7 => 0x60f4, 0xb8 => 0x6100, + 0xb9 => 0x610e, 0xba => 0x612b, 0xbb => 0x614a, 0xbc => 0x6175, + 0xbd => 0x61ac, 0xbe => 0x6194, 0xbf => 0x61a7, 0xc0 => 0x61b7, + 0xc1 => 0x61d4, 0xc2 => 0x61f5, 0xc3 => 0x5fdd, 0xc4 => 0x96b3, + 0xc5 => 0x95e9, 0xc6 => 0x95eb, 0xc7 => 0x95f1, 0xc8 => 0x95f3, + 0xc9 => 0x95f5, 0xca => 0x95f6, 0xcb => 0x95fc, 0xcc => 0x95fe, + 0xcd => 0x9603, 0xce => 0x9604, 0xcf => 0x9606, 0xd0 => 0x9608, + 0xd1 => 0x960a, 0xd2 => 0x960b, 0xd3 => 0x960c, 0xd4 => 0x960d, + 0xd5 => 0x960f, 0xd6 => 0x9612, 0xd7 => 0x9615, 0xd8 => 0x9616, + 0xd9 => 0x9617, 0xda => 0x9619, 0xdb => 0x961a, 0xdc => 0x4e2c, + 0xdd => 0x723f, 0xde => 0x6215, 0xdf => 0x6c35, 0xe0 => 0x6c54, + 0xe1 => 0x6c5c, 0xe2 => 0x6c4a, 0xe3 => 0x6ca3, 0xe4 => 0x6c85, + 0xe5 => 0x6c90, 0xe6 => 0x6c94, 0xe7 => 0x6c8c, 0xe8 => 0x6c68, + 0xe9 => 0x6c69, 0xea => 0x6c74, 0xeb => 0x6c76, 0xec => 0x6c86, + 0xed => 0x6ca9, 0xee => 0x6cd0, 0xef => 0x6cd4, 0xf0 => 0x6cad, + 0xf1 => 0x6cf7, 0xf2 => 0x6cf8, 0xf3 => 0x6cf1, 0xf4 => 0x6cd7, + 0xf5 => 0x6cb2, 0xf6 => 0x6ce0, 0xf7 => 0x6cd6, 0xf8 => 0x6cfa, + 0xf9 => 0x6ceb, 0xfa => 0x6cee, 0xfb => 0x6cb1, 0xfc => 0x6cd3, + 0xfd => 0x6cef, 0xfe => 0x6cfe, + }, + 0xe4 => { + 0xa1 => 0x6d39, 0xa2 => 0x6d27, 0xa3 => 0x6d0c, 0xa4 => 0x6d43, + 0xa5 => 0x6d48, 0xa6 => 0x6d07, 0xa7 => 0x6d04, 0xa8 => 0x6d19, + 0xa9 => 0x6d0e, 0xaa => 0x6d2b, 0xab => 0x6d4d, 0xac => 0x6d2e, + 0xad => 0x6d35, 0xae => 0x6d1a, 0xaf => 0x6d4f, 0xb0 => 0x6d52, + 0xb1 => 0x6d54, 0xb2 => 0x6d33, 0xb3 => 0x6d91, 0xb4 => 0x6d6f, + 0xb5 => 0x6d9e, 0xb6 => 0x6da0, 0xb7 => 0x6d5e, 0xb8 => 0x6d93, + 0xb9 => 0x6d94, 0xba => 0x6d5c, 0xbb => 0x6d60, 0xbc => 0x6d7c, + 0xbd => 0x6d63, 0xbe => 0x6e1a, 0xbf => 0x6dc7, 0xc0 => 0x6dc5, + 0xc1 => 0x6dde, 0xc2 => 0x6e0e, 0xc3 => 0x6dbf, 0xc4 => 0x6de0, + 0xc5 => 0x6e11, 0xc6 => 0x6de6, 0xc7 => 0x6ddd, 0xc8 => 0x6dd9, + 0xc9 => 0x6e16, 0xca => 0x6dab, 0xcb => 0x6e0c, 0xcc => 0x6dae, + 0xcd => 0x6e2b, 0xce => 0x6e6e, 0xcf => 0x6e4e, 0xd0 => 0x6e6b, + 0xd1 => 0x6eb2, 0xd2 => 0x6e5f, 0xd3 => 0x6e86, 0xd4 => 0x6e53, + 0xd5 => 0x6e54, 0xd6 => 0x6e32, 0xd7 => 0x6e25, 0xd8 => 0x6e44, + 0xd9 => 0x6edf, 0xda => 0x6eb1, 0xdb => 0x6e98, 0xdc => 0x6ee0, + 0xdd => 0x6f2d, 0xde => 0x6ee2, 0xdf => 0x6ea5, 0xe0 => 0x6ea7, + 0xe1 => 0x6ebd, 0xe2 => 0x6ebb, 0xe3 => 0x6eb7, 0xe4 => 0x6ed7, + 0xe5 => 0x6eb4, 0xe6 => 0x6ecf, 0xe7 => 0x6e8f, 0xe8 => 0x6ec2, + 0xe9 => 0x6e9f, 0xea => 0x6f62, 0xeb => 0x6f46, 0xec => 0x6f47, + 0xed => 0x6f24, 0xee => 0x6f15, 0xef => 0x6ef9, 0xf0 => 0x6f2f, + 0xf1 => 0x6f36, 0xf2 => 0x6f4b, 0xf3 => 0x6f74, 0xf4 => 0x6f2a, + 0xf5 => 0x6f09, 0xf6 => 0x6f29, 0xf7 => 0x6f89, 0xf8 => 0x6f8d, + 0xf9 => 0x6f8c, 0xfa => 0x6f78, 0xfb => 0x6f72, 0xfc => 0x6f7c, + 0xfd => 0x6f7a, 0xfe => 0x6fd1, + }, + 0xe5 => { + 0xa1 => 0x6fc9, 0xa2 => 0x6fa7, 0xa3 => 0x6fb9, 0xa4 => 0x6fb6, + 0xa5 => 0x6fc2, 0xa6 => 0x6fe1, 0xa7 => 0x6fee, 0xa8 => 0x6fde, + 0xa9 => 0x6fe0, 0xaa => 0x6fef, 0xab => 0x701a, 0xac => 0x7023, + 0xad => 0x701b, 0xae => 0x7039, 0xaf => 0x7035, 0xb0 => 0x704f, + 0xb1 => 0x705e, 0xb2 => 0x5b80, 0xb3 => 0x5b84, 0xb4 => 0x5b95, + 0xb5 => 0x5b93, 0xb6 => 0x5ba5, 0xb7 => 0x5bb8, 0xb8 => 0x752f, + 0xb9 => 0x9a9e, 0xba => 0x6434, 0xbb => 0x5be4, 0xbc => 0x5bee, + 0xbd => 0x8930, 0xbe => 0x5bf0, 0xbf => 0x8e47, 0xc0 => 0x8b07, + 0xc1 => 0x8fb6, 0xc2 => 0x8fd3, 0xc3 => 0x8fd5, 0xc4 => 0x8fe5, + 0xc5 => 0x8fee, 0xc6 => 0x8fe4, 0xc7 => 0x8fe9, 0xc8 => 0x8fe6, + 0xc9 => 0x8ff3, 0xca => 0x8fe8, 0xcb => 0x9005, 0xcc => 0x9004, + 0xcd => 0x900b, 0xce => 0x9026, 0xcf => 0x9011, 0xd0 => 0x900d, + 0xd1 => 0x9016, 0xd2 => 0x9021, 0xd3 => 0x9035, 0xd4 => 0x9036, + 0xd5 => 0x902d, 0xd6 => 0x902f, 0xd7 => 0x9044, 0xd8 => 0x9051, + 0xd9 => 0x9052, 0xda => 0x9050, 0xdb => 0x9068, 0xdc => 0x9058, + 0xdd => 0x9062, 0xde => 0x905b, 0xdf => 0x66b9, 0xe0 => 0x9074, + 0xe1 => 0x907d, 0xe2 => 0x9082, 0xe3 => 0x9088, 0xe4 => 0x9083, + 0xe5 => 0x908b, 0xe6 => 0x5f50, 0xe7 => 0x5f57, 0xe8 => 0x5f56, + 0xe9 => 0x5f58, 0xea => 0x5c3b, 0xeb => 0x54ab, 0xec => 0x5c50, + 0xed => 0x5c59, 0xee => 0x5b71, 0xef => 0x5c63, 0xf0 => 0x5c66, + 0xf1 => 0x7fbc, 0xf2 => 0x5f2a, 0xf3 => 0x5f29, 0xf4 => 0x5f2d, + 0xf5 => 0x8274, 0xf6 => 0x5f3c, 0xf7 => 0x9b3b, 0xf8 => 0x5c6e, + 0xf9 => 0x5981, 0xfa => 0x5983, 0xfb => 0x598d, 0xfc => 0x59a9, + 0xfd => 0x59aa, 0xfe => 0x59a3, + }, + 0xe6 => { + 0xa1 => 0x5997, 0xa2 => 0x59ca, 0xa3 => 0x59ab, 0xa4 => 0x599e, + 0xa5 => 0x59a4, 0xa6 => 0x59d2, 0xa7 => 0x59b2, 0xa8 => 0x59af, + 0xa9 => 0x59d7, 0xaa => 0x59be, 0xab => 0x5a05, 0xac => 0x5a06, + 0xad => 0x59dd, 0xae => 0x5a08, 0xaf => 0x59e3, 0xb0 => 0x59d8, + 0xb1 => 0x59f9, 0xb2 => 0x5a0c, 0xb3 => 0x5a09, 0xb4 => 0x5a32, + 0xb5 => 0x5a34, 0xb6 => 0x5a11, 0xb7 => 0x5a23, 0xb8 => 0x5a13, + 0xb9 => 0x5a40, 0xba => 0x5a67, 0xbb => 0x5a4a, 0xbc => 0x5a55, + 0xbd => 0x5a3c, 0xbe => 0x5a62, 0xbf => 0x5a75, 0xc0 => 0x80ec, + 0xc1 => 0x5aaa, 0xc2 => 0x5a9b, 0xc3 => 0x5a77, 0xc4 => 0x5a7a, + 0xc5 => 0x5abe, 0xc6 => 0x5aeb, 0xc7 => 0x5ab2, 0xc8 => 0x5ad2, + 0xc9 => 0x5ad4, 0xca => 0x5ab8, 0xcb => 0x5ae0, 0xcc => 0x5ae3, + 0xcd => 0x5af1, 0xce => 0x5ad6, 0xcf => 0x5ae6, 0xd0 => 0x5ad8, + 0xd1 => 0x5adc, 0xd2 => 0x5b09, 0xd3 => 0x5b17, 0xd4 => 0x5b16, + 0xd5 => 0x5b32, 0xd6 => 0x5b37, 0xd7 => 0x5b40, 0xd8 => 0x5c15, + 0xd9 => 0x5c1c, 0xda => 0x5b5a, 0xdb => 0x5b65, 0xdc => 0x5b73, + 0xdd => 0x5b51, 0xde => 0x5b53, 0xdf => 0x5b62, 0xe0 => 0x9a75, + 0xe1 => 0x9a77, 0xe2 => 0x9a78, 0xe3 => 0x9a7a, 0xe4 => 0x9a7f, + 0xe5 => 0x9a7d, 0xe6 => 0x9a80, 0xe7 => 0x9a81, 0xe8 => 0x9a85, + 0xe9 => 0x9a88, 0xea => 0x9a8a, 0xeb => 0x9a90, 0xec => 0x9a92, + 0xed => 0x9a93, 0xee => 0x9a96, 0xef => 0x9a98, 0xf0 => 0x9a9b, + 0xf1 => 0x9a9c, 0xf2 => 0x9a9d, 0xf3 => 0x9a9f, 0xf4 => 0x9aa0, + 0xf5 => 0x9aa2, 0xf6 => 0x9aa3, 0xf7 => 0x9aa5, 0xf8 => 0x9aa7, + 0xf9 => 0x7e9f, 0xfa => 0x7ea1, 0xfb => 0x7ea3, 0xfc => 0x7ea5, + 0xfd => 0x7ea8, 0xfe => 0x7ea9, + }, + 0xe7 => { + 0xa1 => 0x7ead, 0xa2 => 0x7eb0, 0xa3 => 0x7ebe, 0xa4 => 0x7ec0, + 0xa5 => 0x7ec1, 0xa6 => 0x7ec2, 0xa7 => 0x7ec9, 0xa8 => 0x7ecb, + 0xa9 => 0x7ecc, 0xaa => 0x7ed0, 0xab => 0x7ed4, 0xac => 0x7ed7, + 0xad => 0x7edb, 0xae => 0x7ee0, 0xaf => 0x7ee1, 0xb0 => 0x7ee8, + 0xb1 => 0x7eeb, 0xb2 => 0x7eee, 0xb3 => 0x7eef, 0xb4 => 0x7ef1, + 0xb5 => 0x7ef2, 0xb6 => 0x7f0d, 0xb7 => 0x7ef6, 0xb8 => 0x7efa, + 0xb9 => 0x7efb, 0xba => 0x7efe, 0xbb => 0x7f01, 0xbc => 0x7f02, + 0xbd => 0x7f03, 0xbe => 0x7f07, 0xbf => 0x7f08, 0xc0 => 0x7f0b, + 0xc1 => 0x7f0c, 0xc2 => 0x7f0f, 0xc3 => 0x7f11, 0xc4 => 0x7f12, + 0xc5 => 0x7f17, 0xc6 => 0x7f19, 0xc7 => 0x7f1c, 0xc8 => 0x7f1b, + 0xc9 => 0x7f1f, 0xca => 0x7f21, 0xcb => 0x7f22, 0xcc => 0x7f23, + 0xcd => 0x7f24, 0xce => 0x7f25, 0xcf => 0x7f26, 0xd0 => 0x7f27, + 0xd1 => 0x7f2a, 0xd2 => 0x7f2b, 0xd3 => 0x7f2c, 0xd4 => 0x7f2d, + 0xd5 => 0x7f2f, 0xd6 => 0x7f30, 0xd7 => 0x7f31, 0xd8 => 0x7f32, + 0xd9 => 0x7f33, 0xda => 0x7f35, 0xdb => 0x5e7a, 0xdc => 0x757f, + 0xdd => 0x5ddb, 0xde => 0x753e, 0xdf => 0x9095, 0xe0 => 0x738e, + 0xe1 => 0x7391, 0xe2 => 0x73ae, 0xe3 => 0x73a2, 0xe4 => 0x739f, + 0xe5 => 0x73cf, 0xe6 => 0x73c2, 0xe7 => 0x73d1, 0xe8 => 0x73b7, + 0xe9 => 0x73b3, 0xea => 0x73c0, 0xeb => 0x73c9, 0xec => 0x73c8, + 0xed => 0x73e5, 0xee => 0x73d9, 0xef => 0x987c, 0xf0 => 0x740a, + 0xf1 => 0x73e9, 0xf2 => 0x73e7, 0xf3 => 0x73de, 0xf4 => 0x73ba, + 0xf5 => 0x73f2, 0xf6 => 0x740f, 0xf7 => 0x742a, 0xf8 => 0x745b, + 0xf9 => 0x7426, 0xfa => 0x7425, 0xfb => 0x7428, 0xfc => 0x7430, + 0xfd => 0x742e, 0xfe => 0x742c, + }, + 0xe8 => { + 0xa1 => 0x741b, 0xa2 => 0x741a, 0xa3 => 0x7441, 0xa4 => 0x745c, + 0xa5 => 0x7457, 0xa6 => 0x7455, 0xa7 => 0x7459, 0xa8 => 0x7477, + 0xa9 => 0x746d, 0xaa => 0x747e, 0xab => 0x749c, 0xac => 0x748e, + 0xad => 0x7480, 0xae => 0x7481, 0xaf => 0x7487, 0xb0 => 0x748b, + 0xb1 => 0x749e, 0xb2 => 0x74a8, 0xb3 => 0x74a9, 0xb4 => 0x7490, + 0xb5 => 0x74a7, 0xb6 => 0x74d2, 0xb7 => 0x74ba, 0xb8 => 0x97ea, + 0xb9 => 0x97eb, 0xba => 0x97ec, 0xbb => 0x674c, 0xbc => 0x6753, + 0xbd => 0x675e, 0xbe => 0x6748, 0xbf => 0x6769, 0xc0 => 0x67a5, + 0xc1 => 0x6787, 0xc2 => 0x676a, 0xc3 => 0x6773, 0xc4 => 0x6798, + 0xc5 => 0x67a7, 0xc6 => 0x6775, 0xc7 => 0x67a8, 0xc8 => 0x679e, + 0xc9 => 0x67ad, 0xca => 0x678b, 0xcb => 0x6777, 0xcc => 0x677c, + 0xcd => 0x67f0, 0xce => 0x6809, 0xcf => 0x67d8, 0xd0 => 0x680a, + 0xd1 => 0x67e9, 0xd2 => 0x67b0, 0xd3 => 0x680c, 0xd4 => 0x67d9, + 0xd5 => 0x67b5, 0xd6 => 0x67da, 0xd7 => 0x67b3, 0xd8 => 0x67dd, + 0xd9 => 0x6800, 0xda => 0x67c3, 0xdb => 0x67b8, 0xdc => 0x67e2, + 0xdd => 0x680e, 0xde => 0x67c1, 0xdf => 0x67fd, 0xe0 => 0x6832, + 0xe1 => 0x6833, 0xe2 => 0x6860, 0xe3 => 0x6861, 0xe4 => 0x684e, + 0xe5 => 0x6862, 0xe6 => 0x6844, 0xe7 => 0x6864, 0xe8 => 0x6883, + 0xe9 => 0x681d, 0xea => 0x6855, 0xeb => 0x6866, 0xec => 0x6841, + 0xed => 0x6867, 0xee => 0x6840, 0xef => 0x683e, 0xf0 => 0x684a, + 0xf1 => 0x6849, 0xf2 => 0x6829, 0xf3 => 0x68b5, 0xf4 => 0x688f, + 0xf5 => 0x6874, 0xf6 => 0x6877, 0xf7 => 0x6893, 0xf8 => 0x686b, + 0xf9 => 0x68c2, 0xfa => 0x696e, 0xfb => 0x68fc, 0xfc => 0x691f, + 0xfd => 0x6920, 0xfe => 0x68f9, + }, + 0xe9 => { + 0xa1 => 0x6924, 0xa2 => 0x68f0, 0xa3 => 0x690b, 0xa4 => 0x6901, + 0xa5 => 0x6957, 0xa6 => 0x68e3, 0xa7 => 0x6910, 0xa8 => 0x6971, + 0xa9 => 0x6939, 0xaa => 0x6960, 0xab => 0x6942, 0xac => 0x695d, + 0xad => 0x6984, 0xae => 0x696b, 0xaf => 0x6980, 0xb0 => 0x6998, + 0xb1 => 0x6978, 0xb2 => 0x6934, 0xb3 => 0x69cc, 0xb4 => 0x6987, + 0xb5 => 0x6988, 0xb6 => 0x69ce, 0xb7 => 0x6989, 0xb8 => 0x6966, + 0xb9 => 0x6963, 0xba => 0x6979, 0xbb => 0x699b, 0xbc => 0x69a7, + 0xbd => 0x69bb, 0xbe => 0x69ab, 0xbf => 0x69ad, 0xc0 => 0x69d4, + 0xc1 => 0x69b1, 0xc2 => 0x69c1, 0xc3 => 0x69ca, 0xc4 => 0x69df, + 0xc5 => 0x6995, 0xc6 => 0x69e0, 0xc7 => 0x698d, 0xc8 => 0x69ff, + 0xc9 => 0x6a2f, 0xca => 0x69ed, 0xcb => 0x6a17, 0xcc => 0x6a18, + 0xcd => 0x6a65, 0xce => 0x69f2, 0xcf => 0x6a44, 0xd0 => 0x6a3e, + 0xd1 => 0x6aa0, 0xd2 => 0x6a50, 0xd3 => 0x6a5b, 0xd4 => 0x6a35, + 0xd5 => 0x6a8e, 0xd6 => 0x6a79, 0xd7 => 0x6a3d, 0xd8 => 0x6a28, + 0xd9 => 0x6a58, 0xda => 0x6a7c, 0xdb => 0x6a91, 0xdc => 0x6a90, + 0xdd => 0x6aa9, 0xde => 0x6a97, 0xdf => 0x6aab, 0xe0 => 0x7337, + 0xe1 => 0x7352, 0xe2 => 0x6b81, 0xe3 => 0x6b82, 0xe4 => 0x6b87, + 0xe5 => 0x6b84, 0xe6 => 0x6b92, 0xe7 => 0x6b93, 0xe8 => 0x6b8d, + 0xe9 => 0x6b9a, 0xea => 0x6b9b, 0xeb => 0x6ba1, 0xec => 0x6baa, + 0xed => 0x8f6b, 0xee => 0x8f6d, 0xef => 0x8f71, 0xf0 => 0x8f72, + 0xf1 => 0x8f73, 0xf2 => 0x8f75, 0xf3 => 0x8f76, 0xf4 => 0x8f78, + 0xf5 => 0x8f77, 0xf6 => 0x8f79, 0xf7 => 0x8f7a, 0xf8 => 0x8f7c, + 0xf9 => 0x8f7e, 0xfa => 0x8f81, 0xfb => 0x8f82, 0xfc => 0x8f84, + 0xfd => 0x8f87, 0xfe => 0x8f8b, + }, + 0xea => { + 0xa1 => 0x8f8d, 0xa2 => 0x8f8e, 0xa3 => 0x8f8f, 0xa4 => 0x8f98, + 0xa5 => 0x8f9a, 0xa6 => 0x8ece, 0xa7 => 0x620b, 0xa8 => 0x6217, + 0xa9 => 0x621b, 0xaa => 0x621f, 0xab => 0x6222, 0xac => 0x6221, + 0xad => 0x6225, 0xae => 0x6224, 0xaf => 0x622c, 0xb0 => 0x81e7, + 0xb1 => 0x74ef, 0xb2 => 0x74f4, 0xb3 => 0x74ff, 0xb4 => 0x750f, + 0xb5 => 0x7511, 0xb6 => 0x7513, 0xb7 => 0x6534, 0xb8 => 0x65ee, + 0xb9 => 0x65ef, 0xba => 0x65f0, 0xbb => 0x660a, 0xbc => 0x6619, + 0xbd => 0x6772, 0xbe => 0x6603, 0xbf => 0x6615, 0xc0 => 0x6600, + 0xc1 => 0x7085, 0xc2 => 0x66f7, 0xc3 => 0x661d, 0xc4 => 0x6634, + 0xc5 => 0x6631, 0xc6 => 0x6636, 0xc7 => 0x6635, 0xc8 => 0x8006, + 0xc9 => 0x665f, 0xca => 0x6654, 0xcb => 0x6641, 0xcc => 0x664f, + 0xcd => 0x6656, 0xce => 0x6661, 0xcf => 0x6657, 0xd0 => 0x6677, + 0xd1 => 0x6684, 0xd2 => 0x668c, 0xd3 => 0x66a7, 0xd4 => 0x669d, + 0xd5 => 0x66be, 0xd6 => 0x66db, 0xd7 => 0x66dc, 0xd8 => 0x66e6, + 0xd9 => 0x66e9, 0xda => 0x8d32, 0xdb => 0x8d33, 0xdc => 0x8d36, + 0xdd => 0x8d3b, 0xde => 0x8d3d, 0xdf => 0x8d40, 0xe0 => 0x8d45, + 0xe1 => 0x8d46, 0xe2 => 0x8d48, 0xe3 => 0x8d49, 0xe4 => 0x8d47, + 0xe5 => 0x8d4d, 0xe6 => 0x8d55, 0xe7 => 0x8d59, 0xe8 => 0x89c7, + 0xe9 => 0x89ca, 0xea => 0x89cb, 0xeb => 0x89cc, 0xec => 0x89ce, + 0xed => 0x89cf, 0xee => 0x89d0, 0xef => 0x89d1, 0xf0 => 0x726e, + 0xf1 => 0x729f, 0xf2 => 0x725d, 0xf3 => 0x7266, 0xf4 => 0x726f, + 0xf5 => 0x727e, 0xf6 => 0x727f, 0xf7 => 0x7284, 0xf8 => 0x728b, + 0xf9 => 0x728d, 0xfa => 0x728f, 0xfb => 0x7292, 0xfc => 0x6308, + 0xfd => 0x6332, 0xfe => 0x63b0, + }, + 0xeb => { + 0xa1 => 0x643f, 0xa2 => 0x64d8, 0xa3 => 0x8004, 0xa4 => 0x6bea, + 0xa5 => 0x6bf3, 0xa6 => 0x6bfd, 0xa7 => 0x6bf5, 0xa8 => 0x6bf9, + 0xa9 => 0x6c05, 0xaa => 0x6c07, 0xab => 0x6c06, 0xac => 0x6c0d, + 0xad => 0x6c15, 0xae => 0x6c18, 0xaf => 0x6c19, 0xb0 => 0x6c1a, + 0xb1 => 0x6c21, 0xb2 => 0x6c29, 0xb3 => 0x6c24, 0xb4 => 0x6c2a, + 0xb5 => 0x6c32, 0xb6 => 0x6535, 0xb7 => 0x6555, 0xb8 => 0x656b, + 0xb9 => 0x724d, 0xba => 0x7252, 0xbb => 0x7256, 0xbc => 0x7230, + 0xbd => 0x8662, 0xbe => 0x5216, 0xbf => 0x809f, 0xc0 => 0x809c, + 0xc1 => 0x8093, 0xc2 => 0x80bc, 0xc3 => 0x670a, 0xc4 => 0x80bd, + 0xc5 => 0x80b1, 0xc6 => 0x80ab, 0xc7 => 0x80ad, 0xc8 => 0x80b4, + 0xc9 => 0x80b7, 0xca => 0x80e7, 0xcb => 0x80e8, 0xcc => 0x80e9, + 0xcd => 0x80ea, 0xce => 0x80db, 0xcf => 0x80c2, 0xd0 => 0x80c4, + 0xd1 => 0x80d9, 0xd2 => 0x80cd, 0xd3 => 0x80d7, 0xd4 => 0x6710, + 0xd5 => 0x80dd, 0xd6 => 0x80eb, 0xd7 => 0x80f1, 0xd8 => 0x80f4, + 0xd9 => 0x80ed, 0xda => 0x810d, 0xdb => 0x810e, 0xdc => 0x80f2, + 0xdd => 0x80fc, 0xde => 0x6715, 0xdf => 0x8112, 0xe0 => 0x8c5a, + 0xe1 => 0x8136, 0xe2 => 0x811e, 0xe3 => 0x812c, 0xe4 => 0x8118, + 0xe5 => 0x8132, 0xe6 => 0x8148, 0xe7 => 0x814c, 0xe8 => 0x8153, + 0xe9 => 0x8174, 0xea => 0x8159, 0xeb => 0x815a, 0xec => 0x8171, + 0xed => 0x8160, 0xee => 0x8169, 0xef => 0x817c, 0xf0 => 0x817d, + 0xf1 => 0x816d, 0xf2 => 0x8167, 0xf3 => 0x584d, 0xf4 => 0x5ab5, + 0xf5 => 0x8188, 0xf6 => 0x8182, 0xf7 => 0x8191, 0xf8 => 0x6ed5, + 0xf9 => 0x81a3, 0xfa => 0x81aa, 0xfb => 0x81cc, 0xfc => 0x6726, + 0xfd => 0x81ca, 0xfe => 0x81bb, + }, + 0xec => { + 0xa1 => 0x81c1, 0xa2 => 0x81a6, 0xa3 => 0x6b24, 0xa4 => 0x6b37, + 0xa5 => 0x6b39, 0xa6 => 0x6b43, 0xa7 => 0x6b46, 0xa8 => 0x6b59, + 0xa9 => 0x98d1, 0xaa => 0x98d2, 0xab => 0x98d3, 0xac => 0x98d5, + 0xad => 0x98d9, 0xae => 0x98da, 0xaf => 0x6bb3, 0xb0 => 0x5f40, + 0xb1 => 0x6bc2, 0xb2 => 0x89f3, 0xb3 => 0x6590, 0xb4 => 0x9f51, + 0xb5 => 0x6593, 0xb6 => 0x65bc, 0xb7 => 0x65c6, 0xb8 => 0x65c4, + 0xb9 => 0x65c3, 0xba => 0x65cc, 0xbb => 0x65ce, 0xbc => 0x65d2, + 0xbd => 0x65d6, 0xbe => 0x7080, 0xbf => 0x709c, 0xc0 => 0x7096, + 0xc1 => 0x709d, 0xc2 => 0x70bb, 0xc3 => 0x70c0, 0xc4 => 0x70b7, + 0xc5 => 0x70ab, 0xc6 => 0x70b1, 0xc7 => 0x70e8, 0xc8 => 0x70ca, + 0xc9 => 0x7110, 0xca => 0x7113, 0xcb => 0x7116, 0xcc => 0x712f, + 0xcd => 0x7131, 0xce => 0x7173, 0xcf => 0x715c, 0xd0 => 0x7168, + 0xd1 => 0x7145, 0xd2 => 0x7172, 0xd3 => 0x714a, 0xd4 => 0x7178, + 0xd5 => 0x717a, 0xd6 => 0x7198, 0xd7 => 0x71b3, 0xd8 => 0x71b5, + 0xd9 => 0x71a8, 0xda => 0x71a0, 0xdb => 0x71e0, 0xdc => 0x71d4, + 0xdd => 0x71e7, 0xde => 0x71f9, 0xdf => 0x721d, 0xe0 => 0x7228, + 0xe1 => 0x706c, 0xe2 => 0x7118, 0xe3 => 0x7166, 0xe4 => 0x71b9, + 0xe5 => 0x623e, 0xe6 => 0x623d, 0xe7 => 0x6243, 0xe8 => 0x6248, + 0xe9 => 0x6249, 0xea => 0x793b, 0xeb => 0x7940, 0xec => 0x7946, + 0xed => 0x7949, 0xee => 0x795b, 0xef => 0x795c, 0xf0 => 0x7953, + 0xf1 => 0x795a, 0xf2 => 0x7962, 0xf3 => 0x7957, 0xf4 => 0x7960, + 0xf5 => 0x796f, 0xf6 => 0x7967, 0xf7 => 0x797a, 0xf8 => 0x7985, + 0xf9 => 0x798a, 0xfa => 0x799a, 0xfb => 0x79a7, 0xfc => 0x79b3, + 0xfd => 0x5fd1, 0xfe => 0x5fd0, + }, + 0xed => { + 0xa1 => 0x603c, 0xa2 => 0x605d, 0xa3 => 0x605a, 0xa4 => 0x6067, + 0xa5 => 0x6041, 0xa6 => 0x6059, 0xa7 => 0x6063, 0xa8 => 0x60ab, + 0xa9 => 0x6106, 0xaa => 0x610d, 0xab => 0x615d, 0xac => 0x61a9, + 0xad => 0x619d, 0xae => 0x61cb, 0xaf => 0x61d1, 0xb0 => 0x6206, + 0xb1 => 0x8080, 0xb2 => 0x807f, 0xb3 => 0x6c93, 0xb4 => 0x6cf6, + 0xb5 => 0x6dfc, 0xb6 => 0x77f6, 0xb7 => 0x77f8, 0xb8 => 0x7800, + 0xb9 => 0x7809, 0xba => 0x7817, 0xbb => 0x7818, 0xbc => 0x7811, + 0xbd => 0x65ab, 0xbe => 0x782d, 0xbf => 0x781c, 0xc0 => 0x781d, + 0xc1 => 0x7839, 0xc2 => 0x783a, 0xc3 => 0x783b, 0xc4 => 0x781f, + 0xc5 => 0x783c, 0xc6 => 0x7825, 0xc7 => 0x782c, 0xc8 => 0x7823, + 0xc9 => 0x7829, 0xca => 0x784e, 0xcb => 0x786d, 0xcc => 0x7856, + 0xcd => 0x7857, 0xce => 0x7826, 0xcf => 0x7850, 0xd0 => 0x7847, + 0xd1 => 0x784c, 0xd2 => 0x786a, 0xd3 => 0x789b, 0xd4 => 0x7893, + 0xd5 => 0x789a, 0xd6 => 0x7887, 0xd7 => 0x789c, 0xd8 => 0x78a1, + 0xd9 => 0x78a3, 0xda => 0x78b2, 0xdb => 0x78b9, 0xdc => 0x78a5, + 0xdd => 0x78d4, 0xde => 0x78d9, 0xdf => 0x78c9, 0xe0 => 0x78ec, + 0xe1 => 0x78f2, 0xe2 => 0x7905, 0xe3 => 0x78f4, 0xe4 => 0x7913, + 0xe5 => 0x7924, 0xe6 => 0x791e, 0xe7 => 0x7934, 0xe8 => 0x9f9b, + 0xe9 => 0x9ef9, 0xea => 0x9efb, 0xeb => 0x9efc, 0xec => 0x76f1, + 0xed => 0x7704, 0xee => 0x770d, 0xef => 0x76f9, 0xf0 => 0x7707, + 0xf1 => 0x7708, 0xf2 => 0x771a, 0xf3 => 0x7722, 0xf4 => 0x7719, + 0xf5 => 0x772d, 0xf6 => 0x7726, 0xf7 => 0x7735, 0xf8 => 0x7738, + 0xf9 => 0x7750, 0xfa => 0x7751, 0xfb => 0x7747, 0xfc => 0x7743, + 0xfd => 0x775a, 0xfe => 0x7768, + }, + 0xee => { + 0xa1 => 0x7762, 0xa2 => 0x7765, 0xa3 => 0x777f, 0xa4 => 0x778d, + 0xa5 => 0x777d, 0xa6 => 0x7780, 0xa7 => 0x778c, 0xa8 => 0x7791, + 0xa9 => 0x779f, 0xaa => 0x77a0, 0xab => 0x77b0, 0xac => 0x77b5, + 0xad => 0x77bd, 0xae => 0x753a, 0xaf => 0x7540, 0xb0 => 0x754e, + 0xb1 => 0x754b, 0xb2 => 0x7548, 0xb3 => 0x755b, 0xb4 => 0x7572, + 0xb5 => 0x7579, 0xb6 => 0x7583, 0xb7 => 0x7f58, 0xb8 => 0x7f61, + 0xb9 => 0x7f5f, 0xba => 0x8a48, 0xbb => 0x7f68, 0xbc => 0x7f74, + 0xbd => 0x7f71, 0xbe => 0x7f79, 0xbf => 0x7f81, 0xc0 => 0x7f7e, + 0xc1 => 0x76cd, 0xc2 => 0x76e5, 0xc3 => 0x8832, 0xc4 => 0x9485, + 0xc5 => 0x9486, 0xc6 => 0x9487, 0xc7 => 0x948b, 0xc8 => 0x948a, + 0xc9 => 0x948c, 0xca => 0x948d, 0xcb => 0x948f, 0xcc => 0x9490, + 0xcd => 0x9494, 0xce => 0x9497, 0xcf => 0x9495, 0xd0 => 0x949a, + 0xd1 => 0x949b, 0xd2 => 0x949c, 0xd3 => 0x94a3, 0xd4 => 0x94a4, + 0xd5 => 0x94ab, 0xd6 => 0x94aa, 0xd7 => 0x94ad, 0xd8 => 0x94ac, + 0xd9 => 0x94af, 0xda => 0x94b0, 0xdb => 0x94b2, 0xdc => 0x94b4, + 0xdd => 0x94b6, 0xde => 0x94b7, 0xdf => 0x94b8, 0xe0 => 0x94b9, + 0xe1 => 0x94ba, 0xe2 => 0x94bc, 0xe3 => 0x94bd, 0xe4 => 0x94bf, + 0xe5 => 0x94c4, 0xe6 => 0x94c8, 0xe7 => 0x94c9, 0xe8 => 0x94ca, + 0xe9 => 0x94cb, 0xea => 0x94cc, 0xeb => 0x94cd, 0xec => 0x94ce, + 0xed => 0x94d0, 0xee => 0x94d1, 0xef => 0x94d2, 0xf0 => 0x94d5, + 0xf1 => 0x94d6, 0xf2 => 0x94d7, 0xf3 => 0x94d9, 0xf4 => 0x94d8, + 0xf5 => 0x94db, 0xf6 => 0x94de, 0xf7 => 0x94df, 0xf8 => 0x94e0, + 0xf9 => 0x94e2, 0xfa => 0x94e4, 0xfb => 0x94e5, 0xfc => 0x94e7, + 0xfd => 0x94e8, 0xfe => 0x94ea, + }, + 0xef => { + 0xa1 => 0x94e9, 0xa2 => 0x94eb, 0xa3 => 0x94ee, 0xa4 => 0x94ef, + 0xa5 => 0x94f3, 0xa6 => 0x94f4, 0xa7 => 0x94f5, 0xa8 => 0x94f7, + 0xa9 => 0x94f9, 0xaa => 0x94fc, 0xab => 0x94fd, 0xac => 0x94ff, + 0xad => 0x9503, 0xae => 0x9502, 0xaf => 0x9506, 0xb0 => 0x9507, + 0xb1 => 0x9509, 0xb2 => 0x950a, 0xb3 => 0x950d, 0xb4 => 0x950e, + 0xb5 => 0x950f, 0xb6 => 0x9512, 0xb7 => 0x9513, 0xb8 => 0x9514, + 0xb9 => 0x9515, 0xba => 0x9516, 0xbb => 0x9518, 0xbc => 0x951b, + 0xbd => 0x951d, 0xbe => 0x951e, 0xbf => 0x951f, 0xc0 => 0x9522, + 0xc1 => 0x952a, 0xc2 => 0x952b, 0xc3 => 0x9529, 0xc4 => 0x952c, + 0xc5 => 0x9531, 0xc6 => 0x9532, 0xc7 => 0x9534, 0xc8 => 0x9536, + 0xc9 => 0x9537, 0xca => 0x9538, 0xcb => 0x953c, 0xcc => 0x953e, + 0xcd => 0x953f, 0xce => 0x9542, 0xcf => 0x9535, 0xd0 => 0x9544, + 0xd1 => 0x9545, 0xd2 => 0x9546, 0xd3 => 0x9549, 0xd4 => 0x954c, + 0xd5 => 0x954e, 0xd6 => 0x954f, 0xd7 => 0x9552, 0xd8 => 0x9553, + 0xd9 => 0x9554, 0xda => 0x9556, 0xdb => 0x9557, 0xdc => 0x9558, + 0xdd => 0x9559, 0xde => 0x955b, 0xdf => 0x955e, 0xe0 => 0x955f, + 0xe1 => 0x955d, 0xe2 => 0x9561, 0xe3 => 0x9562, 0xe4 => 0x9564, + 0xe5 => 0x9565, 0xe6 => 0x9566, 0xe7 => 0x9567, 0xe8 => 0x9568, + 0xe9 => 0x9569, 0xea => 0x956a, 0xeb => 0x956b, 0xec => 0x956c, + 0xed => 0x956f, 0xee => 0x9571, 0xef => 0x9572, 0xf0 => 0x9573, + 0xf1 => 0x953a, 0xf2 => 0x77e7, 0xf3 => 0x77ec, 0xf4 => 0x96c9, + 0xf5 => 0x79d5, 0xf6 => 0x79ed, 0xf7 => 0x79e3, 0xf8 => 0x79eb, + 0xf9 => 0x7a06, 0xfa => 0x5d47, 0xfb => 0x7a03, 0xfc => 0x7a02, + 0xfd => 0x7a1e, 0xfe => 0x7a14, + }, + 0xf0 => { + 0xa1 => 0x7a39, 0xa2 => 0x7a37, 0xa3 => 0x7a51, 0xa4 => 0x9ecf, + 0xa5 => 0x99a5, 0xa6 => 0x7a70, 0xa7 => 0x7688, 0xa8 => 0x768e, + 0xa9 => 0x7693, 0xaa => 0x7699, 0xab => 0x76a4, 0xac => 0x74de, + 0xad => 0x74e0, 0xae => 0x752c, 0xaf => 0x9e20, 0xb0 => 0x9e22, + 0xb1 => 0x9e28, 0xb2 => 0x9e29, 0xb3 => 0x9e2a, 0xb4 => 0x9e2b, + 0xb5 => 0x9e2c, 0xb6 => 0x9e32, 0xb7 => 0x9e31, 0xb8 => 0x9e36, + 0xb9 => 0x9e38, 0xba => 0x9e37, 0xbb => 0x9e39, 0xbc => 0x9e3a, + 0xbd => 0x9e3e, 0xbe => 0x9e41, 0xbf => 0x9e42, 0xc0 => 0x9e44, + 0xc1 => 0x9e46, 0xc2 => 0x9e47, 0xc3 => 0x9e48, 0xc4 => 0x9e49, + 0xc5 => 0x9e4b, 0xc6 => 0x9e4c, 0xc7 => 0x9e4e, 0xc8 => 0x9e51, + 0xc9 => 0x9e55, 0xca => 0x9e57, 0xcb => 0x9e5a, 0xcc => 0x9e5b, + 0xcd => 0x9e5c, 0xce => 0x9e5e, 0xcf => 0x9e63, 0xd0 => 0x9e66, + 0xd1 => 0x9e67, 0xd2 => 0x9e68, 0xd3 => 0x9e69, 0xd4 => 0x9e6a, + 0xd5 => 0x9e6b, 0xd6 => 0x9e6c, 0xd7 => 0x9e71, 0xd8 => 0x9e6d, + 0xd9 => 0x9e73, 0xda => 0x7592, 0xdb => 0x7594, 0xdc => 0x7596, + 0xdd => 0x75a0, 0xde => 0x759d, 0xdf => 0x75ac, 0xe0 => 0x75a3, + 0xe1 => 0x75b3, 0xe2 => 0x75b4, 0xe3 => 0x75b8, 0xe4 => 0x75c4, + 0xe5 => 0x75b1, 0xe6 => 0x75b0, 0xe7 => 0x75c3, 0xe8 => 0x75c2, + 0xe9 => 0x75d6, 0xea => 0x75cd, 0xeb => 0x75e3, 0xec => 0x75e8, + 0xed => 0x75e6, 0xee => 0x75e4, 0xef => 0x75eb, 0xf0 => 0x75e7, + 0xf1 => 0x7603, 0xf2 => 0x75f1, 0xf3 => 0x75fc, 0xf4 => 0x75ff, + 0xf5 => 0x7610, 0xf6 => 0x7600, 0xf7 => 0x7605, 0xf8 => 0x760c, + 0xf9 => 0x7617, 0xfa => 0x760a, 0xfb => 0x7625, 0xfc => 0x7618, + 0xfd => 0x7615, 0xfe => 0x7619, + }, + 0xf1 => { + 0xa1 => 0x761b, 0xa2 => 0x763c, 0xa3 => 0x7622, 0xa4 => 0x7620, + 0xa5 => 0x7640, 0xa6 => 0x762d, 0xa7 => 0x7630, 0xa8 => 0x763f, + 0xa9 => 0x7635, 0xaa => 0x7643, 0xab => 0x763e, 0xac => 0x7633, + 0xad => 0x764d, 0xae => 0x765e, 0xaf => 0x7654, 0xb0 => 0x765c, + 0xb1 => 0x7656, 0xb2 => 0x766b, 0xb3 => 0x766f, 0xb4 => 0x7fca, + 0xb5 => 0x7ae6, 0xb6 => 0x7a78, 0xb7 => 0x7a79, 0xb8 => 0x7a80, + 0xb9 => 0x7a86, 0xba => 0x7a88, 0xbb => 0x7a95, 0xbc => 0x7aa6, + 0xbd => 0x7aa0, 0xbe => 0x7aac, 0xbf => 0x7aa8, 0xc0 => 0x7aad, + 0xc1 => 0x7ab3, 0xc2 => 0x8864, 0xc3 => 0x8869, 0xc4 => 0x8872, + 0xc5 => 0x887d, 0xc6 => 0x887f, 0xc7 => 0x8882, 0xc8 => 0x88a2, + 0xc9 => 0x88c6, 0xca => 0x88b7, 0xcb => 0x88bc, 0xcc => 0x88c9, + 0xcd => 0x88e2, 0xce => 0x88ce, 0xcf => 0x88e3, 0xd0 => 0x88e5, + 0xd1 => 0x88f1, 0xd2 => 0x891a, 0xd3 => 0x88fc, 0xd4 => 0x88e8, + 0xd5 => 0x88fe, 0xd6 => 0x88f0, 0xd7 => 0x8921, 0xd8 => 0x8919, + 0xd9 => 0x8913, 0xda => 0x891b, 0xdb => 0x890a, 0xdc => 0x8934, + 0xdd => 0x892b, 0xde => 0x8936, 0xdf => 0x8941, 0xe0 => 0x8966, + 0xe1 => 0x897b, 0xe2 => 0x758b, 0xe3 => 0x80e5, 0xe4 => 0x76b2, + 0xe5 => 0x76b4, 0xe6 => 0x77dc, 0xe7 => 0x8012, 0xe8 => 0x8014, + 0xe9 => 0x8016, 0xea => 0x801c, 0xeb => 0x8020, 0xec => 0x8022, + 0xed => 0x8025, 0xee => 0x8026, 0xef => 0x8027, 0xf0 => 0x8029, + 0xf1 => 0x8028, 0xf2 => 0x8031, 0xf3 => 0x800b, 0xf4 => 0x8035, + 0xf5 => 0x8043, 0xf6 => 0x8046, 0xf7 => 0x804d, 0xf8 => 0x8052, + 0xf9 => 0x8069, 0xfa => 0x8071, 0xfb => 0x8983, 0xfc => 0x9878, + 0xfd => 0x9880, 0xfe => 0x9883, + }, + 0xf2 => { + 0xa1 => 0x9889, 0xa2 => 0x988c, 0xa3 => 0x988d, 0xa4 => 0x988f, + 0xa5 => 0x9894, 0xa6 => 0x989a, 0xa7 => 0x989b, 0xa8 => 0x989e, + 0xa9 => 0x989f, 0xaa => 0x98a1, 0xab => 0x98a2, 0xac => 0x98a5, + 0xad => 0x98a6, 0xae => 0x864d, 0xaf => 0x8654, 0xb0 => 0x866c, + 0xb1 => 0x866e, 0xb2 => 0x867f, 0xb3 => 0x867a, 0xb4 => 0x867c, + 0xb5 => 0x867b, 0xb6 => 0x86a8, 0xb7 => 0x868d, 0xb8 => 0x868b, + 0xb9 => 0x86ac, 0xba => 0x869d, 0xbb => 0x86a7, 0xbc => 0x86a3, + 0xbd => 0x86aa, 0xbe => 0x8693, 0xbf => 0x86a9, 0xc0 => 0x86b6, + 0xc1 => 0x86c4, 0xc2 => 0x86b5, 0xc3 => 0x86ce, 0xc4 => 0x86b0, + 0xc5 => 0x86ba, 0xc6 => 0x86b1, 0xc7 => 0x86af, 0xc8 => 0x86c9, + 0xc9 => 0x86cf, 0xca => 0x86b4, 0xcb => 0x86e9, 0xcc => 0x86f1, + 0xcd => 0x86f2, 0xce => 0x86ed, 0xcf => 0x86f3, 0xd0 => 0x86d0, + 0xd1 => 0x8713, 0xd2 => 0x86de, 0xd3 => 0x86f4, 0xd4 => 0x86df, + 0xd5 => 0x86d8, 0xd6 => 0x86d1, 0xd7 => 0x8703, 0xd8 => 0x8707, + 0xd9 => 0x86f8, 0xda => 0x8708, 0xdb => 0x870a, 0xdc => 0x870d, + 0xdd => 0x8709, 0xde => 0x8723, 0xdf => 0x873b, 0xe0 => 0x871e, + 0xe1 => 0x8725, 0xe2 => 0x872e, 0xe3 => 0x871a, 0xe4 => 0x873e, + 0xe5 => 0x8748, 0xe6 => 0x8734, 0xe7 => 0x8731, 0xe8 => 0x8729, + 0xe9 => 0x8737, 0xea => 0x873f, 0xeb => 0x8782, 0xec => 0x8722, + 0xed => 0x877d, 0xee => 0x877e, 0xef => 0x877b, 0xf0 => 0x8760, + 0xf1 => 0x8770, 0xf2 => 0x874c, 0xf3 => 0x876e, 0xf4 => 0x878b, + 0xf5 => 0x8753, 0xf6 => 0x8763, 0xf7 => 0x877c, 0xf8 => 0x8764, + 0xf9 => 0x8759, 0xfa => 0x8765, 0xfb => 0x8793, 0xfc => 0x87af, + 0xfd => 0x87a8, 0xfe => 0x87d2, + }, + 0xf3 => { + 0xa1 => 0x87c6, 0xa2 => 0x8788, 0xa3 => 0x8785, 0xa4 => 0x87ad, + 0xa5 => 0x8797, 0xa6 => 0x8783, 0xa7 => 0x87ab, 0xa8 => 0x87e5, + 0xa9 => 0x87ac, 0xaa => 0x87b5, 0xab => 0x87b3, 0xac => 0x87cb, + 0xad => 0x87d3, 0xae => 0x87bd, 0xaf => 0x87d1, 0xb0 => 0x87c0, + 0xb1 => 0x87ca, 0xb2 => 0x87db, 0xb3 => 0x87ea, 0xb4 => 0x87e0, + 0xb5 => 0x87ee, 0xb6 => 0x8816, 0xb7 => 0x8813, 0xb8 => 0x87fe, + 0xb9 => 0x880a, 0xba => 0x881b, 0xbb => 0x8821, 0xbc => 0x8839, + 0xbd => 0x883c, 0xbe => 0x7f36, 0xbf => 0x7f42, 0xc0 => 0x7f44, + 0xc1 => 0x7f45, 0xc2 => 0x8210, 0xc3 => 0x7afa, 0xc4 => 0x7afd, + 0xc5 => 0x7b08, 0xc6 => 0x7b03, 0xc7 => 0x7b04, 0xc8 => 0x7b15, + 0xc9 => 0x7b0a, 0xca => 0x7b2b, 0xcb => 0x7b0f, 0xcc => 0x7b47, + 0xcd => 0x7b38, 0xce => 0x7b2a, 0xcf => 0x7b19, 0xd0 => 0x7b2e, + 0xd1 => 0x7b31, 0xd2 => 0x7b20, 0xd3 => 0x7b25, 0xd4 => 0x7b24, + 0xd5 => 0x7b33, 0xd6 => 0x7b3e, 0xd7 => 0x7b1e, 0xd8 => 0x7b58, + 0xd9 => 0x7b5a, 0xda => 0x7b45, 0xdb => 0x7b75, 0xdc => 0x7b4c, + 0xdd => 0x7b5d, 0xde => 0x7b60, 0xdf => 0x7b6e, 0xe0 => 0x7b7b, + 0xe1 => 0x7b62, 0xe2 => 0x7b72, 0xe3 => 0x7b71, 0xe4 => 0x7b90, + 0xe5 => 0x7ba6, 0xe6 => 0x7ba7, 0xe7 => 0x7bb8, 0xe8 => 0x7bac, + 0xe9 => 0x7b9d, 0xea => 0x7ba8, 0xeb => 0x7b85, 0xec => 0x7baa, + 0xed => 0x7b9c, 0xee => 0x7ba2, 0xef => 0x7bab, 0xf0 => 0x7bb4, + 0xf1 => 0x7bd1, 0xf2 => 0x7bc1, 0xf3 => 0x7bcc, 0xf4 => 0x7bdd, + 0xf5 => 0x7bda, 0xf6 => 0x7be5, 0xf7 => 0x7be6, 0xf8 => 0x7bea, + 0xf9 => 0x7c0c, 0xfa => 0x7bfe, 0xfb => 0x7bfc, 0xfc => 0x7c0f, + 0xfd => 0x7c16, 0xfe => 0x7c0b, + }, + 0xf4 => { + 0xa1 => 0x7c1f, 0xa2 => 0x7c2a, 0xa3 => 0x7c26, 0xa4 => 0x7c38, + 0xa5 => 0x7c41, 0xa6 => 0x7c40, 0xa7 => 0x81fe, 0xa8 => 0x8201, + 0xa9 => 0x8202, 0xaa => 0x8204, 0xab => 0x81ec, 0xac => 0x8844, + 0xad => 0x8221, 0xae => 0x8222, 0xaf => 0x8223, 0xb0 => 0x822d, + 0xb1 => 0x822f, 0xb2 => 0x8228, 0xb3 => 0x822b, 0xb4 => 0x8238, + 0xb5 => 0x823b, 0xb6 => 0x8233, 0xb7 => 0x8234, 0xb8 => 0x823e, + 0xb9 => 0x8244, 0xba => 0x8249, 0xbb => 0x824b, 0xbc => 0x824f, + 0xbd => 0x825a, 0xbe => 0x825f, 0xbf => 0x8268, 0xc0 => 0x887e, + 0xc1 => 0x8885, 0xc2 => 0x8888, 0xc3 => 0x88d8, 0xc4 => 0x88df, + 0xc5 => 0x895e, 0xc6 => 0x7f9d, 0xc7 => 0x7f9f, 0xc8 => 0x7fa7, + 0xc9 => 0x7faf, 0xca => 0x7fb0, 0xcb => 0x7fb2, 0xcc => 0x7c7c, + 0xcd => 0x6549, 0xce => 0x7c91, 0xcf => 0x7c9d, 0xd0 => 0x7c9c, + 0xd1 => 0x7c9e, 0xd2 => 0x7ca2, 0xd3 => 0x7cb2, 0xd4 => 0x7cbc, + 0xd5 => 0x7cbd, 0xd6 => 0x7cc1, 0xd7 => 0x7cc7, 0xd8 => 0x7ccc, + 0xd9 => 0x7ccd, 0xda => 0x7cc8, 0xdb => 0x7cc5, 0xdc => 0x7cd7, + 0xdd => 0x7ce8, 0xde => 0x826e, 0xdf => 0x66a8, 0xe0 => 0x7fbf, + 0xe1 => 0x7fce, 0xe2 => 0x7fd5, 0xe3 => 0x7fe5, 0xe4 => 0x7fe1, + 0xe5 => 0x7fe6, 0xe6 => 0x7fe9, 0xe7 => 0x7fee, 0xe8 => 0x7ff3, + 0xe9 => 0x7cf8, 0xea => 0x7d77, 0xeb => 0x7da6, 0xec => 0x7dae, + 0xed => 0x7e47, 0xee => 0x7e9b, 0xef => 0x9eb8, 0xf0 => 0x9eb4, + 0xf1 => 0x8d73, 0xf2 => 0x8d84, 0xf3 => 0x8d94, 0xf4 => 0x8d91, + 0xf5 => 0x8db1, 0xf6 => 0x8d67, 0xf7 => 0x8d6d, 0xf8 => 0x8c47, + 0xf9 => 0x8c49, 0xfa => 0x914a, 0xfb => 0x9150, 0xfc => 0x914e, + 0xfd => 0x914f, 0xfe => 0x9164, + }, + 0xf5 => { + 0xa1 => 0x9162, 0xa2 => 0x9161, 0xa3 => 0x9170, 0xa4 => 0x9169, + 0xa5 => 0x916f, 0xa6 => 0x917d, 0xa7 => 0x917e, 0xa8 => 0x9172, + 0xa9 => 0x9174, 0xaa => 0x9179, 0xab => 0x918c, 0xac => 0x9185, + 0xad => 0x9190, 0xae => 0x918d, 0xaf => 0x9191, 0xb0 => 0x91a2, + 0xb1 => 0x91a3, 0xb2 => 0x91aa, 0xb3 => 0x91ad, 0xb4 => 0x91ae, + 0xb5 => 0x91af, 0xb6 => 0x91b5, 0xb7 => 0x91b4, 0xb8 => 0x91ba, + 0xb9 => 0x8c55, 0xba => 0x9e7e, 0xbb => 0x8db8, 0xbc => 0x8deb, + 0xbd => 0x8e05, 0xbe => 0x8e59, 0xbf => 0x8e69, 0xc0 => 0x8db5, + 0xc1 => 0x8dbf, 0xc2 => 0x8dbc, 0xc3 => 0x8dba, 0xc4 => 0x8dc4, + 0xc5 => 0x8dd6, 0xc6 => 0x8dd7, 0xc7 => 0x8dda, 0xc8 => 0x8dde, + 0xc9 => 0x8dce, 0xca => 0x8dcf, 0xcb => 0x8ddb, 0xcc => 0x8dc6, + 0xcd => 0x8dec, 0xce => 0x8df7, 0xcf => 0x8df8, 0xd0 => 0x8de3, + 0xd1 => 0x8df9, 0xd2 => 0x8dfb, 0xd3 => 0x8de4, 0xd4 => 0x8e09, + 0xd5 => 0x8dfd, 0xd6 => 0x8e14, 0xd7 => 0x8e1d, 0xd8 => 0x8e1f, + 0xd9 => 0x8e2c, 0xda => 0x8e2e, 0xdb => 0x8e23, 0xdc => 0x8e2f, + 0xdd => 0x8e3a, 0xde => 0x8e40, 0xdf => 0x8e39, 0xe0 => 0x8e35, + 0xe1 => 0x8e3d, 0xe2 => 0x8e31, 0xe3 => 0x8e49, 0xe4 => 0x8e41, + 0xe5 => 0x8e42, 0xe6 => 0x8e51, 0xe7 => 0x8e52, 0xe8 => 0x8e4a, + 0xe9 => 0x8e70, 0xea => 0x8e76, 0xeb => 0x8e7c, 0xec => 0x8e6f, + 0xed => 0x8e74, 0xee => 0x8e85, 0xef => 0x8e8f, 0xf0 => 0x8e94, + 0xf1 => 0x8e90, 0xf2 => 0x8e9c, 0xf3 => 0x8e9e, 0xf4 => 0x8c78, + 0xf5 => 0x8c82, 0xf6 => 0x8c8a, 0xf7 => 0x8c85, 0xf8 => 0x8c98, + 0xf9 => 0x8c94, 0xfa => 0x659b, 0xfb => 0x89d6, 0xfc => 0x89de, + 0xfd => 0x89da, 0xfe => 0x89dc, + }, + 0xf6 => { + 0xa1 => 0x89e5, 0xa2 => 0x89eb, 0xa3 => 0x89ef, 0xa4 => 0x8a3e, + 0xa5 => 0x8b26, 0xa6 => 0x9753, 0xa7 => 0x96e9, 0xa8 => 0x96f3, + 0xa9 => 0x96ef, 0xaa => 0x9706, 0xab => 0x9701, 0xac => 0x9708, + 0xad => 0x970f, 0xae => 0x970e, 0xaf => 0x972a, 0xb0 => 0x972d, + 0xb1 => 0x9730, 0xb2 => 0x973e, 0xb3 => 0x9f80, 0xb4 => 0x9f83, + 0xb5 => 0x9f85, 0xb6 => 0x9f86, 0xb7 => 0x9f87, 0xb8 => 0x9f88, + 0xb9 => 0x9f89, 0xba => 0x9f8a, 0xbb => 0x9f8c, 0xbc => 0x9efe, + 0xbd => 0x9f0b, 0xbe => 0x9f0d, 0xbf => 0x96b9, 0xc0 => 0x96bc, + 0xc1 => 0x96bd, 0xc2 => 0x96ce, 0xc3 => 0x96d2, 0xc4 => 0x77bf, + 0xc5 => 0x96e0, 0xc6 => 0x928e, 0xc7 => 0x92ae, 0xc8 => 0x92c8, + 0xc9 => 0x933e, 0xca => 0x936a, 0xcb => 0x93ca, 0xcc => 0x938f, + 0xcd => 0x943e, 0xce => 0x946b, 0xcf => 0x9c7f, 0xd0 => 0x9c82, + 0xd1 => 0x9c85, 0xd2 => 0x9c86, 0xd3 => 0x9c87, 0xd4 => 0x9c88, + 0xd5 => 0x7a23, 0xd6 => 0x9c8b, 0xd7 => 0x9c8e, 0xd8 => 0x9c90, + 0xd9 => 0x9c91, 0xda => 0x9c92, 0xdb => 0x9c94, 0xdc => 0x9c95, + 0xdd => 0x9c9a, 0xde => 0x9c9b, 0xdf => 0x9c9e, 0xe0 => 0x9c9f, + 0xe1 => 0x9ca0, 0xe2 => 0x9ca1, 0xe3 => 0x9ca2, 0xe4 => 0x9ca3, + 0xe5 => 0x9ca5, 0xe6 => 0x9ca6, 0xe7 => 0x9ca7, 0xe8 => 0x9ca8, + 0xe9 => 0x9ca9, 0xea => 0x9cab, 0xeb => 0x9cad, 0xec => 0x9cae, + 0xed => 0x9cb0, 0xee => 0x9cb1, 0xef => 0x9cb2, 0xf0 => 0x9cb3, + 0xf1 => 0x9cb4, 0xf2 => 0x9cb5, 0xf3 => 0x9cb6, 0xf4 => 0x9cb7, + 0xf5 => 0x9cba, 0xf6 => 0x9cbb, 0xf7 => 0x9cbc, 0xf8 => 0x9cbd, + 0xf9 => 0x9cc4, 0xfa => 0x9cc5, 0xfb => 0x9cc6, 0xfc => 0x9cc7, + 0xfd => 0x9cca, 0xfe => 0x9ccb, + }, + 0xf7 => { + 0xa1 => 0x9ccc, 0xa2 => 0x9ccd, 0xa3 => 0x9cce, 0xa4 => 0x9ccf, + 0xa5 => 0x9cd0, 0xa6 => 0x9cd3, 0xa7 => 0x9cd4, 0xa8 => 0x9cd5, + 0xa9 => 0x9cd7, 0xaa => 0x9cd8, 0xab => 0x9cd9, 0xac => 0x9cdc, + 0xad => 0x9cdd, 0xae => 0x9cdf, 0xaf => 0x9ce2, 0xb0 => 0x977c, + 0xb1 => 0x9785, 0xb2 => 0x9791, 0xb3 => 0x9792, 0xb4 => 0x9794, + 0xb5 => 0x97af, 0xb6 => 0x97ab, 0xb7 => 0x97a3, 0xb8 => 0x97b2, + 0xb9 => 0x97b4, 0xba => 0x9ab1, 0xbb => 0x9ab0, 0xbc => 0x9ab7, + 0xbd => 0x9e58, 0xbe => 0x9ab6, 0xbf => 0x9aba, 0xc0 => 0x9abc, + 0xc1 => 0x9ac1, 0xc2 => 0x9ac0, 0xc3 => 0x9ac5, 0xc4 => 0x9ac2, + 0xc5 => 0x9acb, 0xc6 => 0x9acc, 0xc7 => 0x9ad1, 0xc8 => 0x9b45, + 0xc9 => 0x9b43, 0xca => 0x9b47, 0xcb => 0x9b49, 0xcc => 0x9b48, + 0xcd => 0x9b4d, 0xce => 0x9b51, 0xcf => 0x98e8, 0xd0 => 0x990d, + 0xd1 => 0x992e, 0xd2 => 0x9955, 0xd3 => 0x9954, 0xd4 => 0x9adf, + 0xd5 => 0x9ae1, 0xd6 => 0x9ae6, 0xd7 => 0x9aef, 0xd8 => 0x9aeb, + 0xd9 => 0x9afb, 0xda => 0x9aed, 0xdb => 0x9af9, 0xdc => 0x9b08, + 0xdd => 0x9b0f, 0xde => 0x9b13, 0xdf => 0x9b1f, 0xe0 => 0x9b23, + 0xe1 => 0x9ebd, 0xe2 => 0x9ebe, 0xe3 => 0x7e3b, 0xe4 => 0x9e82, + 0xe5 => 0x9e87, 0xe6 => 0x9e88, 0xe7 => 0x9e8b, 0xe8 => 0x9e92, + 0xe9 => 0x93d6, 0xea => 0x9e9d, 0xeb => 0x9e9f, 0xec => 0x9edb, + 0xed => 0x9edc, 0xee => 0x9edd, 0xef => 0x9ee0, 0xf0 => 0x9edf, + 0xf1 => 0x9ee2, 0xf2 => 0x9ee9, 0xf3 => 0x9ee7, 0xf4 => 0x9ee5, + 0xf5 => 0x9eea, 0xf6 => 0x9eef, 0xf7 => 0x9f22, 0xf8 => 0x9f2c, + 0xf9 => 0x9f2f, 0xfa => 0x9f39, 0xfb => 0x9f37, 0xfc => 0x9f3d, + 0xfd => 0x9f3e, 0xfe => 0x9f44, + }, +); + +1; # end diff --git a/lib/Image/ExifTool/Charset/MacChineseTW.pm b/lib/Image/ExifTool/Charset/MacChineseTW.pm new file mode 100644 index 0000000..a7bb96e --- /dev/null +++ b/lib/Image/ExifTool/Charset/MacChineseTW.pm @@ -0,0 +1,3623 @@ +#------------------------------------------------------------------------------ +# File: MacChineseTW.pm +# +# Description: Mac Chinese Traditional to Unicode +# +# Revisions: 2010/01/20 - P. Harvey created +# +# References: 1) http://unicode.org/Public/MAPPINGS/VENDORS/APPLE/CHINTRAD.TXT +# +# Notes: The table omits 1-byte characters with the same values as Unicode +#------------------------------------------------------------------------------ +use strict; + +%Image::ExifTool::Charset::MacChineseTW = ( + 0x80 => [0x5c,0xf87f], 0x81 => 0xf880, 0x82 => 0xf881, 0xfd => 0xa9, + 0xfe => 0x2122, 0xff => 0x2026, + 0xa1 => { + 0x40 => 0x3000, 0x41 => 0xff0c, 0x42 => 0x3001, 0x43 => 0x3002, + 0x44 => 0xff0e, 0x45 => 0xb7, 0x46 => 0xff1b, 0x47 => 0xff1a, + 0x48 => 0xff1f, 0x49 => 0xff01, 0x4a => 0xfe30, 0x4b => 0x22ef, + 0x4c => 0x2025, 0x4d => [0xff0c,0xf87d], 0x4e => [0x3001,0xf87d], + 0x4f => [0xff0e,0xf87d], 0x50 => [0xff0e,0xf87e], 0x51 => [0xff1b,0xf87d], + 0x52 => [0xff1a,0xf87d], 0x53 => [0xff1f,0xf87d], 0x54 => [0xff01,0xf87d], + 0x55 => 0xff5c, 0x56 => 0x2013, 0x57 => 0xfe31, 0x58 => 0x2014, + 0x59 => 0xfe33, 0x5a => [0xff3f,0xf87f], 0x5b => 0xfe34, 0x5c => 0xfe4f, + 0x5d => 0xff08, 0x5e => 0xff09, 0x5f => 0xfe35, 0x60 => 0xfe36, + 0x61 => 0xff5b, 0x62 => 0xff5d, 0x63 => 0xfe37, 0x64 => 0xfe38, + 0x65 => 0x3014, 0x66 => 0x3015, 0x67 => 0xfe39, 0x68 => 0xfe3a, + 0x69 => 0x3010, 0x6a => 0x3011, 0x6b => 0xfe3b, 0x6c => 0xfe3c, + 0x6d => 0x300a, 0x6e => 0x300b, 0x6f => 0xfe3d, 0x70 => 0xfe3e, + 0x71 => 0x3008, 0x72 => 0x3009, 0x73 => 0xfe3f, 0x74 => 0xfe40, + 0x75 => 0x300c, 0x76 => 0x300d, 0x77 => 0xfe41, 0x78 => 0xfe42, + 0x79 => 0x300e, 0x7a => 0x300f, 0x7b => 0xfe43, 0x7c => 0xfe44, + 0x7d => [0xff08,0xf87f], 0x7e => [0xff09,0xf87f], 0xa1 => [0xff5b,0xf87f], + 0xa2 => [0xff5d,0xf87f], 0xa3 => [0x3014,0xf87f], 0xa4 => [0x3015,0xf87f], + 0xa5 => 0x2018, 0xa6 => 0x2019, 0xa7 => 0x201c, 0xa8 => 0x201d, + 0xa9 => 0x301d, 0xaa => 0x301e, 0xab => 0x2035, 0xac => 0x2032, + 0xad => 0xff03, 0xae => 0xff06, 0xaf => 0xff0a, 0xb0 => 0x203b, + 0xb1 => 0xa7, 0xb2 => 0x3003, 0xb3 => 0x25cb, 0xb4 => 0x25cf, + 0xb5 => 0x25b3, 0xb6 => 0x25b2, 0xb7 => 0x25ce, 0xb8 => 0x2606, + 0xb9 => 0x2605, 0xba => 0x25c7, 0xbb => 0x25c6, 0xbc => 0x25a1, + 0xbd => 0x25a0, 0xbe => 0x25bd, 0xbf => 0x25bc, 0xc0 => 0x32a3, + 0xc1 => 0x2105, 0xc2 => 0x203e, 0xc3 => [0x203e,0xf87c], 0xc4 => 0xff3f, + 0xc5 => [0xff3f,0xf87c], 0xc6 => 0xfe49, 0xc7 => 0xfe4a, 0xc8 => 0xfe4d, + 0xc9 => 0xfe4e, 0xca => 0xfe4b, 0xcb => [0xfe4b,0xf87c], 0xcc => 0xfe5f, + 0xcd => 0xfe60, 0xce => 0xfe61, 0xcf => 0xff0b, 0xd0 => 0xff0d, + 0xd1 => 0xd7, 0xd2 => 0xf7, 0xd3 => 0xb1, 0xd4 => 0x221a, 0xd5 => 0xff1c, + 0xd6 => 0xff1e, 0xd7 => 0xff1d, 0xd8 => 0x2266, 0xd9 => 0x2267, + 0xda => 0x2260, 0xdb => 0x221e, 0xdc => 0x2252, 0xdd => 0x2261, + 0xde => 0xfe62, 0xdf => 0xfe63, 0xe0 => 0xfe64, 0xe1 => 0xfe65, + 0xe2 => 0xfe66, 0xe3 => 0x223c, 0xe4 => 0x2229, 0xe5 => 0x222a, + 0xe6 => 0x22a5, 0xe7 => 0x2220, 0xe8 => 0x221f, 0xe9 => 0x22bf, + 0xea => 0x33d2, 0xeb => 0x33d1, 0xec => 0x222b, 0xed => 0x222e, + 0xee => 0x2235, 0xef => 0x2234, 0xf0 => 0x2640, 0xf1 => 0x2642, + 0xf2 => 0x2295, 0xf3 => 0x2609, 0xf4 => 0x2191, 0xf5 => 0x2193, + 0xf6 => 0x2190, 0xf7 => 0x2192, 0xf8 => 0x2196, 0xf9 => 0x2197, + 0xfa => 0x2199, 0xfb => 0x2198, 0xfc => 0x2225, 0xfd => 0x2223, + 0xfe => [0xff0f,0xf87f], + }, + 0xa2 => { + 0x40 => [0xff3c,0xf87f], 0x41 => 0xff0f, 0x42 => 0xff3c, 0x43 => 0xff04, + 0x44 => 0xa5, 0x45 => 0x3012, 0x46 => 0xa2, 0x47 => 0xa3, 0x48 => 0xff05, + 0x49 => 0xff20, 0x4a => 0x2103, 0x4b => 0x2109, 0x4c => 0xfe69, + 0x4d => 0xfe6a, 0x4e => 0xfe6b, 0x4f => 0x33d5, 0x50 => 0x339c, + 0x51 => 0x339d, 0x52 => 0x339e, 0x53 => 0x33ce, 0x54 => 0x33a1, + 0x55 => 0x338e, 0x56 => 0x338f, 0x57 => 0x33c4, 0x58 => 0xb0, + 0x59 => 0x5159, 0x5a => 0x515b, 0x5b => 0x515e, 0x5c => 0x515d, + 0x5d => 0x5161, 0x5e => 0x5163, 0x5f => 0x55e7, 0x60 => 0x74e9, + 0x61 => 0x7cce, 0x62 => 0x2581, 0x63 => 0x2582, 0x64 => 0x2583, + 0x65 => 0x2584, 0x66 => 0x2585, 0x67 => 0x2586, 0x68 => 0x2587, + 0x69 => 0x2588, 0x6a => 0x258f, 0x6b => 0x258e, 0x6c => 0x258d, + 0x6d => 0x258c, 0x6e => 0x258b, 0x6f => 0x258a, 0x70 => 0x2589, + 0x71 => 0x253c, 0x72 => 0x2534, 0x73 => 0x252c, 0x74 => 0x2524, + 0x75 => 0x251c, 0x76 => 0x2594, 0x77 => 0x2500, 0x78 => 0x2502, + 0x79 => [0x2502,0xf87f], 0x7a => 0x250c, 0x7b => 0x2510, 0x7c => 0x2514, + 0x7d => 0x2518, 0x7e => 0x256d, 0xa1 => 0x256e, 0xa2 => 0x2570, + 0xa3 => 0x256f, 0xa4 => 0x2550, 0xa5 => 0x255e, 0xa6 => 0x256a, + 0xa7 => 0x2561, 0xa8 => 0x25e2, 0xa9 => 0x25e3, 0xaa => 0x25e5, + 0xab => 0x25e4, 0xac => 0x2571, 0xad => 0x2572, 0xae => 0x2573, + 0xaf => 0xff10, 0xb0 => 0xff11, 0xb1 => 0xff12, 0xb2 => 0xff13, + 0xb3 => 0xff14, 0xb4 => 0xff15, 0xb5 => 0xff16, 0xb6 => 0xff17, + 0xb7 => 0xff18, 0xb8 => 0xff19, 0xb9 => 0x2160, 0xba => 0x2161, + 0xbb => 0x2162, 0xbc => 0x2163, 0xbd => 0x2164, 0xbe => 0x2165, + 0xbf => 0x2166, 0xc0 => 0x2167, 0xc1 => 0x2168, 0xc2 => 0x2169, + 0xc3 => 0x3021, 0xc4 => 0x3022, 0xc5 => 0x3023, 0xc6 => 0x3024, + 0xc7 => 0x3025, 0xc8 => 0x3026, 0xc9 => 0x3027, 0xca => 0x3028, + 0xcb => 0x3029, 0xcc => [0x5341,0xf87f], 0xcd => 0x5344, + 0xce => [0x5345,0xf87f], 0xcf => 0xff21, 0xd0 => 0xff22, 0xd1 => 0xff23, + 0xd2 => 0xff24, 0xd3 => 0xff25, 0xd4 => 0xff26, 0xd5 => 0xff27, + 0xd6 => 0xff28, 0xd7 => 0xff29, 0xd8 => 0xff2a, 0xd9 => 0xff2b, + 0xda => 0xff2c, 0xdb => 0xff2d, 0xdc => 0xff2e, 0xdd => 0xff2f, + 0xde => 0xff30, 0xdf => 0xff31, 0xe0 => 0xff32, 0xe1 => 0xff33, + 0xe2 => 0xff34, 0xe3 => 0xff35, 0xe4 => 0xff36, 0xe5 => 0xff37, + 0xe6 => 0xff38, 0xe7 => 0xff39, 0xe8 => 0xff3a, 0xe9 => 0xff41, + 0xea => 0xff42, 0xeb => 0xff43, 0xec => 0xff44, 0xed => 0xff45, + 0xee => 0xff46, 0xef => 0xff47, 0xf0 => 0xff48, 0xf1 => 0xff49, + 0xf2 => 0xff4a, 0xf3 => 0xff4b, 0xf4 => 0xff4c, 0xf5 => 0xff4d, + 0xf6 => 0xff4e, 0xf7 => 0xff4f, 0xf8 => 0xff50, 0xf9 => 0xff51, + 0xfa => 0xff52, 0xfb => 0xff53, 0xfc => 0xff54, 0xfd => 0xff55, + 0xfe => 0xff56, + }, + 0xa3 => { + 0x40 => 0xff57, 0x41 => 0xff58, 0x42 => 0xff59, 0x43 => 0xff5a, + 0x44 => 0x0391, 0x45 => 0x0392, 0x46 => 0x0393, 0x47 => 0x0394, + 0x48 => 0x0395, 0x49 => 0x0396, 0x4a => 0x0397, 0x4b => 0x0398, + 0x4c => 0x0399, 0x4d => 0x039a, 0x4e => 0x039b, 0x4f => 0x039c, + 0x50 => 0x039d, 0x51 => 0x039e, 0x52 => 0x039f, 0x53 => 0x03a0, + 0x54 => 0x03a1, 0x55 => 0x03a3, 0x56 => 0x03a4, 0x57 => 0x03a5, + 0x58 => 0x03a6, 0x59 => 0x03a7, 0x5a => 0x03a8, 0x5b => 0x03a9, + 0x5c => 0x03b1, 0x5d => 0x03b2, 0x5e => 0x03b3, 0x5f => 0x03b4, + 0x60 => 0x03b5, 0x61 => 0x03b6, 0x62 => 0x03b7, 0x63 => 0x03b8, + 0x64 => 0x03b9, 0x65 => 0x03ba, 0x66 => 0x03bb, 0x67 => 0x03bc, + 0x68 => 0x03bd, 0x69 => 0x03be, 0x6a => 0x03bf, 0x6b => 0x03c0, + 0x6c => 0x03c1, 0x6d => 0x03c3, 0x6e => 0x03c4, 0x6f => 0x03c5, + 0x70 => 0x03c6, 0x71 => 0x03c7, 0x72 => 0x03c8, 0x73 => 0x03c9, + 0x74 => 0x3105, 0x75 => 0x3106, 0x76 => 0x3107, 0x77 => 0x3108, + 0x78 => 0x3109, 0x79 => 0x310a, 0x7a => 0x310b, 0x7b => 0x310c, + 0x7c => 0x310d, 0x7d => 0x310e, 0x7e => 0x310f, 0xa1 => 0x3110, + 0xa2 => 0x3111, 0xa3 => 0x3112, 0xa4 => 0x3113, 0xa5 => 0x3114, + 0xa6 => 0x3115, 0xa7 => 0x3116, 0xa8 => 0x3117, 0xa9 => 0x3118, + 0xaa => 0x3119, 0xab => 0x311a, 0xac => 0x311b, 0xad => 0x311c, + 0xae => 0x311d, 0xaf => 0x311e, 0xb0 => 0x311f, 0xb1 => 0x3120, + 0xb2 => 0x3121, 0xb3 => 0x3122, 0xb4 => 0x3123, 0xb5 => 0x3124, + 0xb6 => 0x3125, 0xb7 => 0x3126, 0xb8 => 0x3127, 0xb9 => 0x3128, + 0xba => 0x3129, 0xbb => 0x02d9, 0xbc => 0x02c9, 0xbd => 0x02ca, + 0xbe => 0x02c7, 0xbf => 0x02cb, + }, + 0xa4 => { + 0x40 => 0x4e00, 0x41 => 0x4e59, 0x42 => 0x4e01, 0x43 => 0x4e03, + 0x44 => 0x4e43, 0x45 => 0x4e5d, 0x46 => 0x4e86, 0x47 => 0x4e8c, + 0x48 => 0x4eba, 0x49 => 0x513f, 0x4a => 0x5165, 0x4b => 0x516b, + 0x4c => 0x51e0, 0x4d => 0x5200, 0x4e => 0x5201, 0x4f => 0x529b, + 0x50 => 0x5315, 0x51 => 0x5341, 0x52 => 0x535c, 0x53 => 0x53c8, + 0x54 => 0x4e09, 0x55 => 0x4e0b, 0x56 => 0x4e08, 0x57 => 0x4e0a, + 0x58 => 0x4e2b, 0x59 => 0x4e38, 0x5a => 0x51e1, 0x5b => 0x4e45, + 0x5c => 0x4e48, 0x5d => 0x4e5f, 0x5e => 0x4e5e, 0x5f => 0x4e8e, + 0x60 => 0x4ea1, 0x61 => 0x5140, 0x62 => 0x5203, 0x63 => 0x52fa, + 0x64 => 0x5343, 0x65 => 0x53c9, 0x66 => 0x53e3, 0x67 => 0x571f, + 0x68 => 0x58eb, 0x69 => 0x5915, 0x6a => 0x5927, 0x6b => 0x5973, + 0x6c => 0x5b50, 0x6d => 0x5b51, 0x6e => 0x5b53, 0x6f => 0x5bf8, + 0x70 => 0x5c0f, 0x71 => 0x5c22, 0x72 => 0x5c38, 0x73 => 0x5c71, + 0x74 => 0x5ddd, 0x75 => 0x5de5, 0x76 => 0x5df1, 0x77 => 0x5df2, + 0x78 => 0x5df3, 0x79 => 0x5dfe, 0x7a => 0x5e72, 0x7b => 0x5efe, + 0x7c => 0x5f0b, 0x7d => 0x5f13, 0x7e => 0x624d, 0xa1 => 0x4e11, + 0xa2 => 0x4e10, 0xa3 => 0x4e0d, 0xa4 => 0x4e2d, 0xa5 => 0x4e30, + 0xa6 => 0x4e39, 0xa7 => 0x4e4b, 0xa8 => 0x5c39, 0xa9 => 0x4e88, + 0xaa => 0x4e91, 0xab => 0x4e95, 0xac => 0x4e92, 0xad => 0x4e94, + 0xae => 0x4ea2, 0xaf => 0x4ec1, 0xb0 => 0x4ec0, 0xb1 => 0x4ec3, + 0xb2 => 0x4ec6, 0xb3 => 0x4ec7, 0xb4 => 0x4ecd, 0xb5 => 0x4eca, + 0xb6 => 0x4ecb, 0xb7 => 0x4ec4, 0xb8 => 0x5143, 0xb9 => 0x5141, + 0xba => 0x5167, 0xbb => 0x516d, 0xbc => 0x516e, 0xbd => 0x516c, + 0xbe => 0x5197, 0xbf => 0x51f6, 0xc0 => 0x5206, 0xc1 => 0x5207, + 0xc2 => 0x5208, 0xc3 => 0x52fb, 0xc4 => 0x52fe, 0xc5 => 0x52ff, + 0xc6 => 0x5316, 0xc7 => 0x5339, 0xc8 => 0x5348, 0xc9 => 0x5347, + 0xca => 0x5345, 0xcb => 0x535e, 0xcc => 0x5384, 0xcd => 0x53cb, + 0xce => 0x53ca, 0xcf => 0x53cd, 0xd0 => 0x58ec, 0xd1 => 0x5929, + 0xd2 => 0x592b, 0xd3 => 0x592a, 0xd4 => 0x592d, 0xd5 => 0x5b54, + 0xd6 => 0x5c11, 0xd7 => 0x5c24, 0xd8 => 0x5c3a, 0xd9 => 0x5c6f, + 0xda => 0x5df4, 0xdb => 0x5e7b, 0xdc => 0x5eff, 0xdd => 0x5f14, + 0xde => 0x5f15, 0xdf => 0x5fc3, 0xe0 => 0x6208, 0xe1 => 0x6236, + 0xe2 => 0x624b, 0xe3 => 0x624e, 0xe4 => 0x652f, 0xe5 => 0x6587, + 0xe6 => 0x6597, 0xe7 => 0x65a4, 0xe8 => 0x65b9, 0xe9 => 0x65e5, + 0xea => 0x66f0, 0xeb => 0x6708, 0xec => 0x6728, 0xed => 0x6b20, + 0xee => 0x6b62, 0xef => 0x6b79, 0xf0 => 0x6bcb, 0xf1 => 0x6bd4, + 0xf2 => 0x6bdb, 0xf3 => 0x6c0f, 0xf4 => 0x6c34, 0xf5 => 0x706b, + 0xf6 => 0x722a, 0xf7 => 0x7236, 0xf8 => 0x723b, 0xf9 => 0x7247, + 0xfa => 0x7259, 0xfb => 0x725b, 0xfc => 0x72ac, 0xfd => 0x738b, + 0xfe => 0x4e19, + }, + 0xa5 => { + 0x40 => 0x4e16, 0x41 => 0x4e15, 0x42 => 0x4e14, 0x43 => 0x4e18, + 0x44 => 0x4e3b, 0x45 => 0x4e4d, 0x46 => 0x4e4f, 0x47 => 0x4e4e, + 0x48 => 0x4ee5, 0x49 => 0x4ed8, 0x4a => 0x4ed4, 0x4b => 0x4ed5, + 0x4c => 0x4ed6, 0x4d => 0x4ed7, 0x4e => 0x4ee3, 0x4f => 0x4ee4, + 0x50 => 0x4ed9, 0x51 => 0x4ede, 0x52 => 0x5145, 0x53 => 0x5144, + 0x54 => 0x5189, 0x55 => 0x518a, 0x56 => 0x51ac, 0x57 => 0x51f9, + 0x58 => 0x51fa, 0x59 => 0x51f8, 0x5a => 0x520a, 0x5b => 0x52a0, + 0x5c => 0x529f, 0x5d => 0x5305, 0x5e => 0x5306, 0x5f => 0x5317, + 0x60 => 0x531d, 0x61 => 0x4edf, 0x62 => 0x534a, 0x63 => 0x5349, + 0x64 => 0x5361, 0x65 => 0x5360, 0x66 => 0x536f, 0x67 => 0x536e, + 0x68 => 0x53bb, 0x69 => 0x53ef, 0x6a => 0x53e4, 0x6b => 0x53f3, + 0x6c => 0x53ec, 0x6d => 0x53ee, 0x6e => 0x53e9, 0x6f => 0x53e8, + 0x70 => 0x53fc, 0x71 => 0x53f8, 0x72 => 0x53f5, 0x73 => 0x53eb, + 0x74 => 0x53e6, 0x75 => 0x53ea, 0x76 => 0x53f2, 0x77 => 0x53f1, + 0x78 => 0x53f0, 0x79 => 0x53e5, 0x7a => 0x53ed, 0x7b => 0x53fb, + 0x7c => 0x56db, 0x7d => 0x56da, 0x7e => 0x5916, 0xa1 => 0x592e, + 0xa2 => 0x5931, 0xa3 => 0x5974, 0xa4 => 0x5976, 0xa5 => 0x5b55, + 0xa6 => 0x5b83, 0xa7 => 0x5c3c, 0xa8 => 0x5de8, 0xa9 => 0x5de7, + 0xaa => 0x5de6, 0xab => 0x5e02, 0xac => 0x5e03, 0xad => 0x5e73, + 0xae => 0x5e7c, 0xaf => 0x5f01, 0xb0 => 0x5f18, 0xb1 => 0x5f17, + 0xb2 => 0x5fc5, 0xb3 => 0x620a, 0xb4 => 0x6253, 0xb5 => 0x6254, + 0xb6 => 0x6252, 0xb7 => 0x6251, 0xb8 => 0x65a5, 0xb9 => 0x65e6, + 0xba => 0x672e, 0xbb => 0x672c, 0xbc => 0x672a, 0xbd => 0x672b, + 0xbe => 0x672d, 0xbf => 0x6b63, 0xc0 => 0x6bcd, 0xc1 => 0x6c11, + 0xc2 => 0x6c10, 0xc3 => 0x6c38, 0xc4 => 0x6c41, 0xc5 => 0x6c40, + 0xc6 => 0x6c3e, 0xc7 => 0x72af, 0xc8 => 0x7384, 0xc9 => 0x7389, + 0xca => 0x74dc, 0xcb => 0x74e6, 0xcc => 0x7518, 0xcd => 0x751f, + 0xce => 0x7528, 0xcf => 0x7529, 0xd0 => 0x7530, 0xd1 => 0x7531, + 0xd2 => 0x7532, 0xd3 => 0x7533, 0xd4 => 0x758b, 0xd5 => 0x767d, + 0xd6 => 0x76ae, 0xd7 => 0x76bf, 0xd8 => 0x76ee, 0xd9 => 0x77db, + 0xda => 0x77e2, 0xdb => 0x77f3, 0xdc => 0x793a, 0xdd => 0x79be, + 0xde => 0x7a74, 0xdf => 0x7acb, 0xe0 => 0x4e1e, 0xe1 => 0x4e1f, + 0xe2 => 0x4e52, 0xe3 => 0x4e53, 0xe4 => 0x4e69, 0xe5 => 0x4e99, + 0xe6 => 0x4ea4, 0xe7 => 0x4ea6, 0xe8 => 0x4ea5, 0xe9 => 0x4eff, + 0xea => 0x4f09, 0xeb => 0x4f19, 0xec => 0x4f0a, 0xed => 0x4f15, + 0xee => 0x4f0d, 0xef => 0x4f10, 0xf0 => 0x4f11, 0xf1 => 0x4f0f, + 0xf2 => 0x4ef2, 0xf3 => 0x4ef6, 0xf4 => 0x4efb, 0xf5 => 0x4ef0, + 0xf6 => 0x4ef3, 0xf7 => 0x4efd, 0xf8 => 0x4f01, 0xf9 => 0x4f0b, + 0xfa => 0x5149, 0xfb => 0x5147, 0xfc => 0x5146, 0xfd => 0x5148, + 0xfe => 0x5168, + }, + 0xa6 => { + 0x40 => 0x5171, 0x41 => 0x518d, 0x42 => 0x51b0, 0x43 => 0x5217, + 0x44 => 0x5211, 0x45 => 0x5212, 0x46 => 0x520e, 0x47 => 0x5216, + 0x48 => 0x52a3, 0x49 => 0x5308, 0x4a => 0x5321, 0x4b => 0x5320, + 0x4c => 0x5370, 0x4d => 0x5371, 0x4e => 0x5409, 0x4f => 0x540f, + 0x50 => 0x540c, 0x51 => 0x540a, 0x52 => 0x5410, 0x53 => 0x5401, + 0x54 => 0x540b, 0x55 => 0x5404, 0x56 => 0x5411, 0x57 => 0x540d, + 0x58 => 0x5408, 0x59 => 0x5403, 0x5a => 0x540e, 0x5b => 0x5406, + 0x5c => 0x5412, 0x5d => 0x56e0, 0x5e => 0x56de, 0x5f => 0x56dd, + 0x60 => 0x5733, 0x61 => 0x5730, 0x62 => 0x5728, 0x63 => 0x572d, + 0x64 => 0x572c, 0x65 => 0x572f, 0x66 => 0x5729, 0x67 => 0x5919, + 0x68 => 0x591a, 0x69 => 0x5937, 0x6a => 0x5938, 0x6b => 0x5984, + 0x6c => 0x5978, 0x6d => 0x5983, 0x6e => 0x597d, 0x6f => 0x5979, + 0x70 => 0x5982, 0x71 => 0x5981, 0x72 => 0x5b57, 0x73 => 0x5b58, + 0x74 => 0x5b87, 0x75 => 0x5b88, 0x76 => 0x5b85, 0x77 => 0x5b89, + 0x78 => 0x5bfa, 0x79 => 0x5c16, 0x7a => 0x5c79, 0x7b => 0x5dde, + 0x7c => 0x5e06, 0x7d => 0x5e76, 0x7e => 0x5e74, 0xa1 => 0x5f0f, + 0xa2 => 0x5f1b, 0xa3 => 0x5fd9, 0xa4 => 0x5fd6, 0xa5 => 0x620e, + 0xa6 => 0x620c, 0xa7 => 0x620d, 0xa8 => 0x6210, 0xa9 => 0x6263, + 0xaa => 0x625b, 0xab => 0x6258, 0xac => 0x6536, 0xad => 0x65e9, + 0xae => 0x65e8, 0xaf => 0x65ec, 0xb0 => 0x65ed, 0xb1 => 0x66f2, + 0xb2 => 0x66f3, 0xb3 => 0x6709, 0xb4 => 0x673d, 0xb5 => 0x6734, + 0xb6 => 0x6731, 0xb7 => 0x6735, 0xb8 => 0x6b21, 0xb9 => 0x6b64, + 0xba => 0x6b7b, 0xbb => 0x6c16, 0xbc => 0x6c5d, 0xbd => 0x6c57, + 0xbe => 0x6c59, 0xbf => 0x6c5f, 0xc0 => 0x6c60, 0xc1 => 0x6c50, + 0xc2 => 0x6c55, 0xc3 => 0x6c61, 0xc4 => 0x6c5b, 0xc5 => 0x6c4d, + 0xc6 => 0x6c4e, 0xc7 => 0x7070, 0xc8 => 0x725f, 0xc9 => 0x725d, + 0xca => 0x767e, 0xcb => 0x7af9, 0xcc => 0x7c73, 0xcd => 0x7cf8, + 0xce => 0x7f36, 0xcf => 0x7f8a, 0xd0 => 0x7fbd, 0xd1 => 0x8001, + 0xd2 => 0x8003, 0xd3 => 0x800c, 0xd4 => 0x8012, 0xd5 => 0x8033, + 0xd6 => 0x807f, 0xd7 => 0x8089, 0xd8 => 0x808b, 0xd9 => 0x808c, + 0xda => 0x81e3, 0xdb => 0x81ea, 0xdc => 0x81f3, 0xdd => 0x81fc, + 0xde => 0x820c, 0xdf => 0x821b, 0xe0 => 0x821f, 0xe1 => 0x826e, + 0xe2 => 0x8272, 0xe3 => 0x827e, 0xe4 => 0x866b, 0xe5 => 0x8840, + 0xe6 => 0x884c, 0xe7 => 0x8863, 0xe8 => 0x897f, 0xe9 => 0x9621, + 0xea => 0x4e32, 0xeb => 0x4ea8, 0xec => 0x4f4d, 0xed => 0x4f4f, + 0xee => 0x4f47, 0xef => 0x4f57, 0xf0 => 0x4f5e, 0xf1 => 0x4f34, + 0xf2 => 0x4f5b, 0xf3 => 0x4f55, 0xf4 => 0x4f30, 0xf5 => 0x4f50, + 0xf6 => 0x4f51, 0xf7 => 0x4f3d, 0xf8 => 0x4f3a, 0xf9 => 0x4f38, + 0xfa => 0x4f43, 0xfb => 0x4f54, 0xfc => 0x4f3c, 0xfd => 0x4f46, + 0xfe => 0x4f63, + }, + 0xa7 => { + 0x40 => 0x4f5c, 0x41 => 0x4f60, 0x42 => 0x4f2f, 0x43 => 0x4f4e, + 0x44 => 0x4f36, 0x45 => 0x4f59, 0x46 => 0x4f5d, 0x47 => 0x4f48, + 0x48 => 0x4f5a, 0x49 => 0x514c, 0x4a => 0x514b, 0x4b => 0x514d, + 0x4c => 0x5175, 0x4d => 0x51b6, 0x4e => 0x51b7, 0x4f => 0x5225, + 0x50 => 0x5224, 0x51 => 0x5229, 0x52 => 0x522a, 0x53 => 0x5228, + 0x54 => 0x52ab, 0x55 => 0x52a9, 0x56 => 0x52aa, 0x57 => 0x52ac, + 0x58 => 0x5323, 0x59 => 0x5373, 0x5a => 0x5375, 0x5b => 0x541d, + 0x5c => 0x542d, 0x5d => 0x541e, 0x5e => 0x543e, 0x5f => 0x5426, + 0x60 => 0x544e, 0x61 => 0x5427, 0x62 => 0x5446, 0x63 => 0x5443, + 0x64 => 0x5433, 0x65 => 0x5448, 0x66 => 0x5442, 0x67 => 0x541b, + 0x68 => 0x5429, 0x69 => 0x544a, 0x6a => 0x5439, 0x6b => 0x543b, + 0x6c => 0x5438, 0x6d => 0x542e, 0x6e => 0x5435, 0x6f => 0x5436, + 0x70 => 0x5420, 0x71 => 0x543c, 0x72 => 0x5440, 0x73 => 0x5431, + 0x74 => 0x542b, 0x75 => 0x541f, 0x76 => 0x542c, 0x77 => 0x56ea, + 0x78 => 0x56f0, 0x79 => 0x56e4, 0x7a => 0x56eb, 0x7b => 0x574a, + 0x7c => 0x5751, 0x7d => 0x5740, 0x7e => 0x574d, 0xa1 => 0x5747, + 0xa2 => 0x574e, 0xa3 => 0x573e, 0xa4 => 0x5750, 0xa5 => 0x574f, + 0xa6 => 0x573b, 0xa7 => 0x58ef, 0xa8 => 0x593e, 0xa9 => 0x599d, + 0xaa => 0x5992, 0xab => 0x59a8, 0xac => 0x599e, 0xad => 0x59a3, + 0xae => 0x5999, 0xaf => 0x5996, 0xb0 => 0x598d, 0xb1 => 0x59a4, + 0xb2 => 0x5993, 0xb3 => 0x598a, 0xb4 => 0x59a5, 0xb5 => 0x5b5d, + 0xb6 => 0x5b5c, 0xb7 => 0x5b5a, 0xb8 => 0x5b5b, 0xb9 => 0x5b8c, + 0xba => 0x5b8b, 0xbb => 0x5b8f, 0xbc => 0x5c2c, 0xbd => 0x5c40, + 0xbe => 0x5c41, 0xbf => 0x5c3f, 0xc0 => 0x5c3e, 0xc1 => 0x5c90, + 0xc2 => 0x5c91, 0xc3 => 0x5c94, 0xc4 => 0x5c8c, 0xc5 => 0x5deb, + 0xc6 => 0x5e0c, 0xc7 => 0x5e8f, 0xc8 => 0x5e87, 0xc9 => 0x5e8a, + 0xca => 0x5ef7, 0xcb => 0x5f04, 0xcc => 0x5f1f, 0xcd => 0x5f64, + 0xce => 0x5f62, 0xcf => 0x5f77, 0xd0 => 0x5f79, 0xd1 => 0x5fd8, + 0xd2 => 0x5fcc, 0xd3 => 0x5fd7, 0xd4 => 0x5fcd, 0xd5 => 0x5ff1, + 0xd6 => 0x5feb, 0xd7 => 0x5ff8, 0xd8 => 0x5fea, 0xd9 => 0x6212, + 0xda => 0x6211, 0xdb => 0x6284, 0xdc => 0x6297, 0xdd => 0x6296, + 0xde => 0x6280, 0xdf => 0x6276, 0xe0 => 0x6289, 0xe1 => 0x626d, + 0xe2 => 0x628a, 0xe3 => 0x627c, 0xe4 => 0x627e, 0xe5 => 0x6279, + 0xe6 => 0x6273, 0xe7 => 0x6292, 0xe8 => 0x626f, 0xe9 => 0x6298, + 0xea => 0x626e, 0xeb => 0x6295, 0xec => 0x6293, 0xed => 0x6291, + 0xee => 0x6286, 0xef => 0x6539, 0xf0 => 0x653b, 0xf1 => 0x6538, + 0xf2 => 0x65f1, 0xf3 => 0x66f4, 0xf4 => 0x675f, 0xf5 => 0x674e, + 0xf6 => 0x674f, 0xf7 => 0x6750, 0xf8 => 0x6751, 0xf9 => 0x675c, + 0xfa => 0x6756, 0xfb => 0x675e, 0xfc => 0x6749, 0xfd => 0x6746, + 0xfe => 0x6760, + }, + 0xa8 => { + 0x40 => 0x6753, 0x41 => 0x6757, 0x42 => 0x6b65, 0x43 => 0x6bcf, + 0x44 => 0x6c42, 0x45 => 0x6c5e, 0x46 => 0x6c99, 0x47 => 0x6c81, + 0x48 => 0x6c88, 0x49 => 0x6c89, 0x4a => 0x6c85, 0x4b => 0x6c9b, + 0x4c => 0x6c6a, 0x4d => 0x6c7a, 0x4e => 0x6c90, 0x4f => 0x6c70, + 0x50 => 0x6c8c, 0x51 => 0x6c68, 0x52 => 0x6c96, 0x53 => 0x6c92, + 0x54 => 0x6c7d, 0x55 => 0x6c83, 0x56 => 0x6c72, 0x57 => 0x6c7e, + 0x58 => 0x6c74, 0x59 => 0x6c86, 0x5a => 0x6c76, 0x5b => 0x6c8d, + 0x5c => 0x6c94, 0x5d => 0x6c98, 0x5e => 0x6c82, 0x5f => 0x7076, + 0x60 => 0x707c, 0x61 => 0x707d, 0x62 => 0x7078, 0x63 => 0x7262, + 0x64 => 0x7261, 0x65 => 0x7260, 0x66 => 0x72c4, 0x67 => 0x72c2, + 0x68 => 0x7396, 0x69 => 0x752c, 0x6a => 0x752b, 0x6b => 0x7537, + 0x6c => 0x7538, 0x6d => 0x7682, 0x6e => 0x76ef, 0x6f => 0x77e3, + 0x70 => 0x79c1, 0x71 => 0x79c0, 0x72 => 0x79bf, 0x73 => 0x7a76, + 0x74 => 0x7cfb, 0x75 => 0x7f55, 0x76 => 0x8096, 0x77 => 0x8093, + 0x78 => 0x809d, 0x79 => 0x8098, 0x7a => 0x809b, 0x7b => 0x809a, + 0x7c => 0x80b2, 0x7d => 0x826f, 0x7e => 0x8292, 0xa1 => 0x828b, + 0xa2 => 0x828d, 0xa3 => 0x898b, 0xa4 => 0x89d2, 0xa5 => 0x8a00, + 0xa6 => 0x8c37, 0xa7 => 0x8c46, 0xa8 => 0x8c55, 0xa9 => 0x8c9d, + 0xaa => 0x8d64, 0xab => 0x8d70, 0xac => 0x8db3, 0xad => 0x8eab, + 0xae => 0x8eca, 0xaf => 0x8f9b, 0xb0 => 0x8fb0, 0xb1 => 0x8fc2, + 0xb2 => 0x8fc6, 0xb3 => 0x8fc5, 0xb4 => 0x8fc4, 0xb5 => 0x5de1, + 0xb6 => 0x9091, 0xb7 => 0x90a2, 0xb8 => 0x90aa, 0xb9 => 0x90a6, + 0xba => 0x90a3, 0xbb => 0x9149, 0xbc => 0x91c6, 0xbd => 0x91cc, + 0xbe => 0x9632, 0xbf => 0x962e, 0xc0 => 0x9631, 0xc1 => 0x962a, + 0xc2 => 0x962c, 0xc3 => 0x4e26, 0xc4 => 0x4e56, 0xc5 => 0x4e73, + 0xc6 => 0x4e8b, 0xc7 => 0x4e9b, 0xc8 => 0x4e9e, 0xc9 => 0x4eab, + 0xca => 0x4eac, 0xcb => 0x4f6f, 0xcc => 0x4f9d, 0xcd => 0x4f8d, + 0xce => 0x4f73, 0xcf => 0x4f7f, 0xd0 => 0x4f6c, 0xd1 => 0x4f9b, + 0xd2 => 0x4f8b, 0xd3 => 0x4f86, 0xd4 => 0x4f83, 0xd5 => 0x4f70, + 0xd6 => 0x4f75, 0xd7 => 0x4f88, 0xd8 => 0x4f69, 0xd9 => 0x4f7b, + 0xda => 0x4f96, 0xdb => 0x4f7e, 0xdc => 0x4f8f, 0xdd => 0x4f91, + 0xde => 0x4f7a, 0xdf => 0x5154, 0xe0 => 0x5152, 0xe1 => 0x5155, + 0xe2 => 0x5169, 0xe3 => 0x5177, 0xe4 => 0x5176, 0xe5 => 0x5178, + 0xe6 => 0x51bd, 0xe7 => 0x51fd, 0xe8 => 0x523b, 0xe9 => 0x5238, + 0xea => 0x5237, 0xeb => 0x523a, 0xec => 0x5230, 0xed => 0x522e, + 0xee => 0x5236, 0xef => 0x5241, 0xf0 => 0x52be, 0xf1 => 0x52bb, + 0xf2 => 0x5352, 0xf3 => 0x5354, 0xf4 => 0x5353, 0xf5 => 0x5351, + 0xf6 => 0x5366, 0xf7 => 0x5377, 0xf8 => 0x5378, 0xf9 => 0x5379, + 0xfa => 0x53d6, 0xfb => 0x53d4, 0xfc => 0x53d7, 0xfd => 0x5473, + 0xfe => 0x5475, + }, + 0xa9 => { + 0x40 => 0x5496, 0x41 => 0x5478, 0x42 => 0x5495, 0x43 => 0x5480, + 0x44 => 0x547b, 0x45 => 0x5477, 0x46 => 0x5484, 0x47 => 0x5492, + 0x48 => 0x5486, 0x49 => 0x547c, 0x4a => 0x5490, 0x4b => 0x5471, + 0x4c => 0x5476, 0x4d => 0x548c, 0x4e => 0x549a, 0x4f => 0x5462, + 0x50 => 0x5468, 0x51 => 0x548b, 0x52 => 0x547d, 0x53 => 0x548e, + 0x54 => 0x56fa, 0x55 => 0x5783, 0x56 => 0x5777, 0x57 => 0x576a, + 0x58 => 0x5769, 0x59 => 0x5761, 0x5a => 0x5766, 0x5b => 0x5764, + 0x5c => 0x577c, 0x5d => 0x591c, 0x5e => 0x5949, 0x5f => 0x5947, + 0x60 => 0x5948, 0x61 => 0x5944, 0x62 => 0x5954, 0x63 => 0x59be, + 0x64 => 0x59bb, 0x65 => 0x59d4, 0x66 => 0x59b9, 0x67 => 0x59ae, + 0x68 => 0x59d1, 0x69 => 0x59c6, 0x6a => 0x59d0, 0x6b => 0x59cd, + 0x6c => 0x59cb, 0x6d => 0x59d3, 0x6e => 0x59ca, 0x6f => 0x59af, + 0x70 => 0x59b3, 0x71 => 0x59d2, 0x72 => 0x59c5, 0x73 => 0x5b5f, + 0x74 => 0x5b64, 0x75 => 0x5b63, 0x76 => 0x5b97, 0x77 => 0x5b9a, + 0x78 => 0x5b98, 0x79 => 0x5b9c, 0x7a => 0x5b99, 0x7b => 0x5b9b, + 0x7c => 0x5c1a, 0x7d => 0x5c48, 0x7e => 0x5c45, 0xa1 => 0x5c46, + 0xa2 => 0x5cb7, 0xa3 => 0x5ca1, 0xa4 => 0x5cb8, 0xa5 => 0x5ca9, + 0xa6 => 0x5cab, 0xa7 => 0x5cb1, 0xa8 => 0x5cb3, 0xa9 => 0x5e18, + 0xaa => 0x5e1a, 0xab => 0x5e16, 0xac => 0x5e15, 0xad => 0x5e1b, + 0xae => 0x5e11, 0xaf => 0x5e78, 0xb0 => 0x5e9a, 0xb1 => 0x5e97, + 0xb2 => 0x5e9c, 0xb3 => 0x5e95, 0xb4 => 0x5e96, 0xb5 => 0x5ef6, + 0xb6 => 0x5f26, 0xb7 => 0x5f27, 0xb8 => 0x5f29, 0xb9 => 0x5f80, + 0xba => 0x5f81, 0xbb => 0x5f7f, 0xbc => 0x5f7c, 0xbd => 0x5fdd, + 0xbe => 0x5fe0, 0xbf => 0x5ffd, 0xc0 => 0x5ff5, 0xc1 => 0x5fff, + 0xc2 => 0x600f, 0xc3 => 0x6014, 0xc4 => 0x602f, 0xc5 => 0x6035, + 0xc6 => 0x6016, 0xc7 => 0x602a, 0xc8 => 0x6015, 0xc9 => 0x6021, + 0xca => 0x6027, 0xcb => 0x6029, 0xcc => 0x602b, 0xcd => 0x601b, + 0xce => 0x6216, 0xcf => 0x6215, 0xd0 => 0x623f, 0xd1 => 0x623e, + 0xd2 => 0x6240, 0xd3 => 0x627f, 0xd4 => 0x62c9, 0xd5 => 0x62cc, + 0xd6 => 0x62c4, 0xd7 => 0x62bf, 0xd8 => 0x62c2, 0xd9 => 0x62b9, + 0xda => 0x62d2, 0xdb => 0x62db, 0xdc => 0x62ab, 0xdd => 0x62d3, + 0xde => 0x62d4, 0xdf => 0x62cb, 0xe0 => 0x62c8, 0xe1 => 0x62a8, + 0xe2 => 0x62bd, 0xe3 => 0x62bc, 0xe4 => 0x62d0, 0xe5 => 0x62d9, + 0xe6 => 0x62c7, 0xe7 => 0x62cd, 0xe8 => 0x62b5, 0xe9 => 0x62da, + 0xea => 0x62b1, 0xeb => 0x62d8, 0xec => 0x62d6, 0xed => 0x62d7, + 0xee => 0x62c6, 0xef => 0x62ac, 0xf0 => 0x62ce, 0xf1 => 0x653e, + 0xf2 => 0x65a7, 0xf3 => 0x65bc, 0xf4 => 0x65fa, 0xf5 => 0x6614, + 0xf6 => 0x6613, 0xf7 => 0x660c, 0xf8 => 0x6606, 0xf9 => 0x6602, + 0xfa => 0x660e, 0xfb => 0x6600, 0xfc => 0x660f, 0xfd => 0x6615, + 0xfe => 0x660a, + }, + 0xaa => { + 0x40 => 0x6607, 0x41 => 0x670d, 0x42 => 0x670b, 0x43 => 0x676d, + 0x44 => 0x678b, 0x45 => 0x6795, 0x46 => 0x6771, 0x47 => 0x679c, + 0x48 => 0x6773, 0x49 => 0x6777, 0x4a => 0x6787, 0x4b => 0x679d, + 0x4c => 0x6797, 0x4d => 0x676f, 0x4e => 0x6770, 0x4f => 0x677f, + 0x50 => 0x6789, 0x51 => 0x677e, 0x52 => 0x6790, 0x53 => 0x6775, + 0x54 => 0x679a, 0x55 => 0x6793, 0x56 => 0x677c, 0x57 => 0x676a, + 0x58 => 0x6772, 0x59 => 0x6b23, 0x5a => 0x6b66, 0x5b => 0x6b67, + 0x5c => 0x6b7f, 0x5d => 0x6c13, 0x5e => 0x6c1b, 0x5f => 0x6ce3, + 0x60 => 0x6ce8, 0x61 => 0x6cf3, 0x62 => 0x6cb1, 0x63 => 0x6ccc, + 0x64 => 0x6ce5, 0x65 => 0x6cb3, 0x66 => 0x6cbd, 0x67 => 0x6cbe, + 0x68 => 0x6cbc, 0x69 => 0x6ce2, 0x6a => 0x6cab, 0x6b => 0x6cd5, + 0x6c => 0x6cd3, 0x6d => 0x6cb8, 0x6e => 0x6cc4, 0x6f => 0x6cb9, + 0x70 => 0x6cc1, 0x71 => 0x6cae, 0x72 => 0x6cd7, 0x73 => 0x6cc5, + 0x74 => 0x6cf1, 0x75 => 0x6cbf, 0x76 => 0x6cbb, 0x77 => 0x6ce1, + 0x78 => 0x6cdb, 0x79 => 0x6cca, 0x7a => 0x6cac, 0x7b => 0x6cef, + 0x7c => 0x6cdc, 0x7d => 0x6cd6, 0x7e => 0x6ce0, 0xa1 => 0x7095, + 0xa2 => 0x708e, 0xa3 => 0x7092, 0xa4 => 0x708a, 0xa5 => 0x7099, + 0xa6 => 0x722c, 0xa7 => 0x722d, 0xa8 => 0x7238, 0xa9 => 0x7248, + 0xaa => 0x7267, 0xab => 0x7269, 0xac => 0x72c0, 0xad => 0x72ce, + 0xae => 0x72d9, 0xaf => 0x72d7, 0xb0 => 0x72d0, 0xb1 => 0x73a9, + 0xb2 => 0x73a8, 0xb3 => 0x739f, 0xb4 => 0x73ab, 0xb5 => 0x73a5, + 0xb6 => 0x753d, 0xb7 => 0x759d, 0xb8 => 0x7599, 0xb9 => 0x759a, + 0xba => 0x7684, 0xbb => 0x76c2, 0xbc => 0x76f2, 0xbd => 0x76f4, + 0xbe => 0x77e5, 0xbf => 0x77fd, 0xc0 => 0x793e, 0xc1 => 0x7940, + 0xc2 => 0x7941, 0xc3 => 0x79c9, 0xc4 => 0x79c8, 0xc5 => 0x7a7a, + 0xc6 => 0x7a79, 0xc7 => 0x7afa, 0xc8 => 0x7cfe, 0xc9 => 0x7f54, + 0xca => 0x7f8c, 0xcb => 0x7f8b, 0xcc => 0x8005, 0xcd => 0x80ba, + 0xce => 0x80a5, 0xcf => 0x80a2, 0xd0 => 0x80b1, 0xd1 => 0x80a1, + 0xd2 => 0x80ab, 0xd3 => 0x80a9, 0xd4 => 0x80b4, 0xd5 => 0x80aa, + 0xd6 => 0x80af, 0xd7 => 0x81e5, 0xd8 => 0x81fe, 0xd9 => 0x820d, + 0xda => 0x82b3, 0xdb => 0x829d, 0xdc => 0x8299, 0xdd => 0x82ad, + 0xde => 0x82bd, 0xdf => 0x829f, 0xe0 => 0x82b9, 0xe1 => 0x82b1, + 0xe2 => 0x82ac, 0xe3 => 0x82a5, 0xe4 => 0x82af, 0xe5 => 0x82b8, + 0xe6 => 0x82a3, 0xe7 => 0x82b0, 0xe8 => 0x82be, 0xe9 => 0x82b7, + 0xea => 0x864e, 0xeb => 0x8671, 0xec => 0x521d, 0xed => 0x8868, + 0xee => 0x8ecb, 0xef => 0x8fce, 0xf0 => 0x8fd4, 0xf1 => 0x8fd1, + 0xf2 => 0x90b5, 0xf3 => 0x90b8, 0xf4 => 0x90b1, 0xf5 => 0x90b6, + 0xf6 => 0x91c7, 0xf7 => 0x91d1, 0xf8 => 0x9577, 0xf9 => 0x9580, + 0xfa => 0x961c, 0xfb => 0x9640, 0xfc => 0x963f, 0xfd => 0x963b, + 0xfe => 0x9644, + }, + 0xab => { + 0x40 => 0x9642, 0x41 => 0x96b9, 0x42 => 0x96e8, 0x43 => 0x9752, + 0x44 => 0x975e, 0x45 => 0x4e9f, 0x46 => 0x4ead, 0x47 => 0x4eae, + 0x48 => 0x4fe1, 0x49 => 0x4fb5, 0x4a => 0x4faf, 0x4b => 0x4fbf, + 0x4c => 0x4fe0, 0x4d => 0x4fd1, 0x4e => 0x4fcf, 0x4f => 0x4fdd, + 0x50 => 0x4fc3, 0x51 => 0x4fb6, 0x52 => 0x4fd8, 0x53 => 0x4fdf, + 0x54 => 0x4fca, 0x55 => 0x4fd7, 0x56 => 0x4fae, 0x57 => 0x4fd0, + 0x58 => 0x4fc4, 0x59 => 0x4fc2, 0x5a => 0x4fda, 0x5b => 0x4fce, + 0x5c => 0x4fde, 0x5d => 0x4fb7, 0x5e => 0x5157, 0x5f => 0x5192, + 0x60 => 0x5191, 0x61 => 0x51a0, 0x62 => 0x524e, 0x63 => 0x5243, + 0x64 => 0x524a, 0x65 => 0x524d, 0x66 => 0x524c, 0x67 => 0x524b, + 0x68 => 0x5247, 0x69 => 0x52c7, 0x6a => 0x52c9, 0x6b => 0x52c3, + 0x6c => 0x52c1, 0x6d => 0x530d, 0x6e => 0x5357, 0x6f => 0x537b, + 0x70 => 0x539a, 0x71 => 0x53db, 0x72 => 0x54ac, 0x73 => 0x54c0, + 0x74 => 0x54a8, 0x75 => 0x54ce, 0x76 => 0x54c9, 0x77 => 0x54b8, + 0x78 => 0x54a6, 0x79 => 0x54b3, 0x7a => 0x54c7, 0x7b => 0x54c2, + 0x7c => 0x54bd, 0x7d => 0x54aa, 0x7e => 0x54c1, 0xa1 => 0x54c4, + 0xa2 => 0x54c8, 0xa3 => 0x54af, 0xa4 => 0x54ab, 0xa5 => 0x54b1, + 0xa6 => 0x54bb, 0xa7 => 0x54a9, 0xa8 => 0x54a7, 0xa9 => 0x54bf, + 0xaa => 0x56ff, 0xab => 0x5782, 0xac => 0x578b, 0xad => 0x57a0, + 0xae => 0x57a3, 0xaf => 0x57a2, 0xb0 => 0x57ce, 0xb1 => 0x57ae, + 0xb2 => 0x5793, 0xb3 => 0x5955, 0xb4 => 0x5951, 0xb5 => 0x594f, + 0xb6 => 0x594e, 0xb7 => 0x5950, 0xb8 => 0x59dc, 0xb9 => 0x59d8, + 0xba => 0x59ff, 0xbb => 0x59e3, 0xbc => 0x59e8, 0xbd => 0x5a03, + 0xbe => 0x59e5, 0xbf => 0x59ea, 0xc0 => 0x59da, 0xc1 => 0x59e6, + 0xc2 => 0x5a01, 0xc3 => 0x59fb, 0xc4 => 0x5b69, 0xc5 => 0x5ba3, + 0xc6 => 0x5ba6, 0xc7 => 0x5ba4, 0xc8 => 0x5ba2, 0xc9 => 0x5ba5, + 0xca => 0x5c01, 0xcb => 0x5c4e, 0xcc => 0x5c4f, 0xcd => 0x5c4d, + 0xce => 0x5c4b, 0xcf => 0x5cd9, 0xd0 => 0x5cd2, 0xd1 => 0x5df7, + 0xd2 => 0x5e1d, 0xd3 => 0x5e25, 0xd4 => 0x5e1f, 0xd5 => 0x5e7d, + 0xd6 => 0x5ea0, 0xd7 => 0x5ea6, 0xd8 => 0x5efa, 0xd9 => 0x5f08, + 0xda => 0x5f2d, 0xdb => 0x5f65, 0xdc => 0x5f88, 0xdd => 0x5f85, + 0xde => 0x5f8a, 0xdf => 0x5f8b, 0xe0 => 0x5f87, 0xe1 => 0x5f8c, + 0xe2 => 0x5f89, 0xe3 => 0x6012, 0xe4 => 0x601d, 0xe5 => 0x6020, + 0xe6 => 0x6025, 0xe7 => 0x600e, 0xe8 => 0x6028, 0xe9 => 0x604d, + 0xea => 0x6070, 0xeb => 0x6068, 0xec => 0x6062, 0xed => 0x6046, + 0xee => 0x6043, 0xef => 0x606c, 0xf0 => 0x606b, 0xf1 => 0x606a, + 0xf2 => 0x6064, 0xf3 => 0x6241, 0xf4 => 0x62dc, 0xf5 => 0x6316, + 0xf6 => 0x6309, 0xf7 => 0x62fc, 0xf8 => 0x62ed, 0xf9 => 0x6301, + 0xfa => 0x62ee, 0xfb => 0x62fd, 0xfc => 0x6307, 0xfd => 0x62f1, + 0xfe => 0x62f7, + }, + 0xac => { + 0x40 => 0x62ef, 0x41 => 0x62ec, 0x42 => 0x62fe, 0x43 => 0x62f4, + 0x44 => 0x6311, 0x45 => 0x6302, 0x46 => 0x653f, 0x47 => 0x6545, + 0x48 => 0x65ab, 0x49 => 0x65bd, 0x4a => 0x65e2, 0x4b => 0x6625, + 0x4c => 0x662d, 0x4d => 0x6620, 0x4e => 0x6627, 0x4f => 0x662f, + 0x50 => 0x661f, 0x51 => 0x6628, 0x52 => 0x6631, 0x53 => 0x6624, + 0x54 => 0x66f7, 0x55 => 0x67ff, 0x56 => 0x67d3, 0x57 => 0x67f1, + 0x58 => 0x67d4, 0x59 => 0x67d0, 0x5a => 0x67ec, 0x5b => 0x67b6, + 0x5c => 0x67af, 0x5d => 0x67f5, 0x5e => 0x67e9, 0x5f => 0x67ef, + 0x60 => 0x67c4, 0x61 => 0x67d1, 0x62 => 0x67b4, 0x63 => 0x67da, + 0x64 => 0x67e5, 0x65 => 0x67b8, 0x66 => 0x67cf, 0x67 => 0x67de, + 0x68 => 0x67f3, 0x69 => 0x67b0, 0x6a => 0x67d9, 0x6b => 0x67e2, + 0x6c => 0x67dd, 0x6d => 0x67d2, 0x6e => 0x6b6a, 0x6f => 0x6b83, + 0x70 => 0x6b86, 0x71 => 0x6bb5, 0x72 => 0x6bd2, 0x73 => 0x6bd7, + 0x74 => 0x6c1f, 0x75 => 0x6cc9, 0x76 => 0x6d0b, 0x77 => 0x6d32, + 0x78 => 0x6d2a, 0x79 => 0x6d41, 0x7a => 0x6d25, 0x7b => 0x6d0c, + 0x7c => 0x6d31, 0x7d => 0x6d1e, 0x7e => 0x6d17, 0xa1 => 0x6d3b, + 0xa2 => 0x6d3d, 0xa3 => 0x6d3e, 0xa4 => 0x6d36, 0xa5 => 0x6d1b, + 0xa6 => 0x6cf5, 0xa7 => 0x6d39, 0xa8 => 0x6d27, 0xa9 => 0x6d38, + 0xaa => 0x6d29, 0xab => 0x6d2e, 0xac => 0x6d35, 0xad => 0x6d0e, + 0xae => 0x6d2b, 0xaf => 0x70ab, 0xb0 => 0x70ba, 0xb1 => 0x70b3, + 0xb2 => 0x70ac, 0xb3 => 0x70af, 0xb4 => 0x70ad, 0xb5 => 0x70b8, + 0xb6 => 0x70ae, 0xb7 => 0x70a4, 0xb8 => 0x7230, 0xb9 => 0x7272, + 0xba => 0x726f, 0xbb => 0x7274, 0xbc => 0x72e9, 0xbd => 0x72e0, + 0xbe => 0x72e1, 0xbf => 0x73b7, 0xc0 => 0x73ca, 0xc1 => 0x73bb, + 0xc2 => 0x73b2, 0xc3 => 0x73cd, 0xc4 => 0x73c0, 0xc5 => 0x73b3, + 0xc6 => 0x751a, 0xc7 => 0x752d, 0xc8 => 0x754f, 0xc9 => 0x754c, + 0xca => 0x754e, 0xcb => 0x754b, 0xcc => 0x75ab, 0xcd => 0x75a4, + 0xce => 0x75a5, 0xcf => 0x75a2, 0xd0 => 0x75a3, 0xd1 => 0x7678, + 0xd2 => 0x7686, 0xd3 => 0x7687, 0xd4 => 0x7688, 0xd5 => 0x76c8, + 0xd6 => 0x76c6, 0xd7 => 0x76c3, 0xd8 => 0x76c5, 0xd9 => 0x7701, + 0xda => 0x76f9, 0xdb => 0x76f8, 0xdc => 0x7709, 0xdd => 0x770b, + 0xde => 0x76fe, 0xdf => 0x76fc, 0xe0 => 0x7707, 0xe1 => 0x77dc, + 0xe2 => 0x7802, 0xe3 => 0x7814, 0xe4 => 0x780c, 0xe5 => 0x780d, + 0xe6 => 0x7946, 0xe7 => 0x7949, 0xe8 => 0x7948, 0xe9 => 0x7947, + 0xea => 0x79b9, 0xeb => 0x79ba, 0xec => 0x79d1, 0xed => 0x79d2, + 0xee => 0x79cb, 0xef => 0x7a7f, 0xf0 => 0x7a81, 0xf1 => 0x7aff, + 0xf2 => 0x7afd, 0xf3 => 0x7c7d, 0xf4 => 0x7d02, 0xf5 => 0x7d05, + 0xf6 => 0x7d00, 0xf7 => 0x7d09, 0xf8 => 0x7d07, 0xf9 => 0x7d04, + 0xfa => 0x7d06, 0xfb => 0x7f38, 0xfc => 0x7f8e, 0xfd => 0x7fbf, + 0xfe => 0x8004, + }, + 0xad => { + 0x40 => 0x8010, 0x41 => 0x800d, 0x42 => 0x8011, 0x43 => 0x8036, + 0x44 => 0x80d6, 0x45 => 0x80e5, 0x46 => 0x80da, 0x47 => 0x80c3, + 0x48 => 0x80c4, 0x49 => 0x80cc, 0x4a => 0x80e1, 0x4b => 0x80db, + 0x4c => 0x80ce, 0x4d => 0x80de, 0x4e => 0x80e4, 0x4f => 0x80dd, + 0x50 => 0x81f4, 0x51 => 0x8222, 0x52 => 0x82e7, 0x53 => 0x8303, + 0x54 => 0x8305, 0x55 => 0x82e3, 0x56 => 0x82db, 0x57 => 0x82e6, + 0x58 => 0x8304, 0x59 => 0x82e5, 0x5a => 0x8302, 0x5b => 0x8309, + 0x5c => 0x82d2, 0x5d => 0x82d7, 0x5e => 0x82f1, 0x5f => 0x8301, + 0x60 => 0x82dc, 0x61 => 0x82d4, 0x62 => 0x82d1, 0x63 => 0x82de, + 0x64 => 0x82d3, 0x65 => 0x82df, 0x66 => 0x82ef, 0x67 => 0x8306, + 0x68 => 0x8650, 0x69 => 0x8679, 0x6a => 0x867b, 0x6b => 0x867a, + 0x6c => 0x884d, 0x6d => 0x886b, 0x6e => 0x8981, 0x6f => 0x89d4, + 0x70 => 0x8a08, 0x71 => 0x8a02, 0x72 => 0x8a03, 0x73 => 0x8c9e, + 0x74 => 0x8ca0, 0x75 => 0x8d74, 0x76 => 0x8d73, 0x77 => 0x8db4, + 0x78 => 0x8ecd, 0x79 => 0x8ecc, 0x7a => 0x8ff0, 0x7b => 0x8fe6, + 0x7c => 0x8fe2, 0x7d => 0x8fea, 0x7e => 0x8fe5, 0xa1 => 0x8fed, + 0xa2 => 0x8feb, 0xa3 => 0x8fe4, 0xa4 => 0x8fe8, 0xa5 => 0x90ca, + 0xa6 => 0x90ce, 0xa7 => 0x90c1, 0xa8 => 0x90c3, 0xa9 => 0x914b, + 0xaa => 0x914a, 0xab => 0x91cd, 0xac => 0x9582, 0xad => 0x9650, + 0xae => 0x964b, 0xaf => 0x964c, 0xb0 => 0x964d, 0xb1 => 0x9762, + 0xb2 => 0x9769, 0xb3 => 0x97cb, 0xb4 => 0x97ed, 0xb5 => 0x97f3, + 0xb6 => 0x9801, 0xb7 => 0x98a8, 0xb8 => 0x98db, 0xb9 => 0x98df, + 0xba => 0x9996, 0xbb => 0x9999, 0xbc => 0x4e58, 0xbd => 0x4eb3, + 0xbe => 0x500c, 0xbf => 0x500d, 0xc0 => 0x5023, 0xc1 => 0x4fef, + 0xc2 => 0x5026, 0xc3 => 0x5025, 0xc4 => 0x4ff8, 0xc5 => 0x5029, + 0xc6 => 0x5016, 0xc7 => 0x5006, 0xc8 => 0x503c, 0xc9 => 0x501f, + 0xca => 0x501a, 0xcb => 0x5012, 0xcc => 0x5011, 0xcd => 0x4ffa, + 0xce => 0x5000, 0xcf => 0x5014, 0xd0 => 0x5028, 0xd1 => 0x4ff1, + 0xd2 => 0x5021, 0xd3 => 0x500b, 0xd4 => 0x5019, 0xd5 => 0x5018, + 0xd6 => 0x4ff3, 0xd7 => 0x4fee, 0xd8 => 0x502d, 0xd9 => 0x502a, + 0xda => 0x4ffe, 0xdb => 0x502b, 0xdc => 0x5009, 0xdd => 0x517c, + 0xde => 0x51a4, 0xdf => 0x51a5, 0xe0 => 0x51a2, 0xe1 => 0x51cd, + 0xe2 => 0x51cc, 0xe3 => 0x51c6, 0xe4 => 0x51cb, 0xe5 => 0x5256, + 0xe6 => 0x525c, 0xe7 => 0x5254, 0xe8 => 0x525b, 0xe9 => 0x525d, + 0xea => 0x532a, 0xeb => 0x537f, 0xec => 0x539f, 0xed => 0x539d, + 0xee => 0x53df, 0xef => 0x54e8, 0xf0 => 0x5510, 0xf1 => 0x5501, + 0xf2 => 0x5537, 0xf3 => 0x54fc, 0xf4 => 0x54e5, 0xf5 => 0x54f2, + 0xf6 => 0x5506, 0xf7 => 0x54fa, 0xf8 => 0x5514, 0xf9 => 0x54e9, + 0xfa => 0x54ed, 0xfb => 0x54e1, 0xfc => 0x5509, 0xfd => 0x54ee, + 0xfe => 0x54ea, + }, + 0xae => { + 0x40 => 0x54e6, 0x41 => 0x5527, 0x42 => 0x5507, 0x43 => 0x54fd, + 0x44 => 0x550f, 0x45 => 0x5703, 0x46 => 0x5704, 0x47 => 0x57c2, + 0x48 => 0x57d4, 0x49 => 0x57cb, 0x4a => 0x57c3, 0x4b => 0x5809, + 0x4c => 0x590f, 0x4d => 0x5957, 0x4e => 0x5958, 0x4f => 0x595a, + 0x50 => 0x5a11, 0x51 => 0x5a18, 0x52 => 0x5a1c, 0x53 => 0x5a1f, + 0x54 => 0x5a1b, 0x55 => 0x5a13, 0x56 => 0x59ec, 0x57 => 0x5a20, + 0x58 => 0x5a23, 0x59 => 0x5a29, 0x5a => 0x5a25, 0x5b => 0x5a0c, + 0x5c => 0x5a09, 0x5d => 0x5b6b, 0x5e => 0x5c58, 0x5f => 0x5bb0, + 0x60 => 0x5bb3, 0x61 => 0x5bb6, 0x62 => 0x5bb4, 0x63 => 0x5bae, + 0x64 => 0x5bb5, 0x65 => 0x5bb9, 0x66 => 0x5bb8, 0x67 => 0x5c04, + 0x68 => 0x5c51, 0x69 => 0x5c55, 0x6a => 0x5c50, 0x6b => 0x5ced, + 0x6c => 0x5cfd, 0x6d => 0x5cfb, 0x6e => 0x5cea, 0x6f => 0x5ce8, + 0x70 => 0x5cf0, 0x71 => 0x5cf6, 0x72 => 0x5d01, 0x73 => 0x5cf4, + 0x74 => 0x5dee, 0x75 => 0x5e2d, 0x76 => 0x5e2b, 0x77 => 0x5eab, + 0x78 => 0x5ead, 0x79 => 0x5ea7, 0x7a => 0x5f31, 0x7b => 0x5f92, + 0x7c => 0x5f91, 0x7d => 0x5f90, 0x7e => 0x6059, 0xa1 => 0x6063, + 0xa2 => 0x6065, 0xa3 => 0x6050, 0xa4 => 0x6055, 0xa5 => 0x606d, + 0xa6 => 0x6069, 0xa7 => 0x606f, 0xa8 => 0x6084, 0xa9 => 0x609f, + 0xaa => 0x609a, 0xab => 0x608d, 0xac => 0x6094, 0xad => 0x608c, + 0xae => 0x6085, 0xaf => 0x6096, 0xb0 => 0x6247, 0xb1 => 0x62f3, + 0xb2 => 0x6308, 0xb3 => 0x62ff, 0xb4 => 0x634e, 0xb5 => 0x633e, + 0xb6 => 0x632f, 0xb7 => 0x6355, 0xb8 => 0x6342, 0xb9 => 0x6346, + 0xba => 0x634f, 0xbb => 0x6349, 0xbc => 0x633a, 0xbd => 0x6350, + 0xbe => 0x633d, 0xbf => 0x632a, 0xc0 => 0x632b, 0xc1 => 0x6328, + 0xc2 => 0x634d, 0xc3 => 0x634c, 0xc4 => 0x6548, 0xc5 => 0x6549, + 0xc6 => 0x6599, 0xc7 => 0x65c1, 0xc8 => 0x65c5, 0xc9 => 0x6642, + 0xca => 0x6649, 0xcb => 0x664f, 0xcc => 0x6643, 0xcd => 0x6652, + 0xce => 0x664c, 0xcf => 0x6645, 0xd0 => 0x6641, 0xd1 => 0x66f8, + 0xd2 => 0x6714, 0xd3 => 0x6715, 0xd4 => 0x6717, 0xd5 => 0x6821, + 0xd6 => 0x6838, 0xd7 => 0x6848, 0xd8 => 0x6846, 0xd9 => 0x6853, + 0xda => 0x6839, 0xdb => 0x6842, 0xdc => 0x6854, 0xdd => 0x6829, + 0xde => 0x68b3, 0xdf => 0x6817, 0xe0 => 0x684c, 0xe1 => 0x6851, + 0xe2 => 0x683d, 0xe3 => 0x67f4, 0xe4 => 0x6850, 0xe5 => 0x6840, + 0xe6 => 0x683c, 0xe7 => 0x6843, 0xe8 => 0x682a, 0xe9 => 0x6845, + 0xea => 0x6813, 0xeb => 0x6818, 0xec => 0x6841, 0xed => 0x6b8a, + 0xee => 0x6b89, 0xef => 0x6bb7, 0xf0 => 0x6c23, 0xf1 => 0x6c27, + 0xf2 => 0x6c28, 0xf3 => 0x6c26, 0xf4 => 0x6c24, 0xf5 => 0x6cf0, + 0xf6 => 0x6d6a, 0xf7 => 0x6d95, 0xf8 => 0x6d88, 0xf9 => 0x6d87, + 0xfa => 0x6d66, 0xfb => 0x6d78, 0xfc => 0x6d77, 0xfd => 0x6d59, + 0xfe => 0x6d93, + }, + 0xaf => { + 0x40 => 0x6d6c, 0x41 => 0x6d89, 0x42 => 0x6d6e, 0x43 => 0x6d5a, + 0x44 => 0x6d74, 0x45 => 0x6d69, 0x46 => 0x6d8c, 0x47 => 0x6d8a, + 0x48 => 0x6d79, 0x49 => 0x6d85, 0x4a => 0x6d65, 0x4b => 0x6d94, + 0x4c => 0x70ca, 0x4d => 0x70d8, 0x4e => 0x70e4, 0x4f => 0x70d9, + 0x50 => 0x70c8, 0x51 => 0x70cf, 0x52 => 0x7239, 0x53 => 0x7279, + 0x54 => 0x72fc, 0x55 => 0x72f9, 0x56 => 0x72fd, 0x57 => 0x72f8, + 0x58 => 0x72f7, 0x59 => 0x7386, 0x5a => 0x73ed, 0x5b => 0x7409, + 0x5c => 0x73ee, 0x5d => 0x73e0, 0x5e => 0x73ea, 0x5f => 0x73de, + 0x60 => 0x7554, 0x61 => 0x755d, 0x62 => 0x755c, 0x63 => 0x755a, + 0x64 => 0x7559, 0x65 => 0x75be, 0x66 => 0x75c5, 0x67 => 0x75c7, + 0x68 => 0x75b2, 0x69 => 0x75b3, 0x6a => 0x75bd, 0x6b => 0x75bc, + 0x6c => 0x75b9, 0x6d => 0x75c2, 0x6e => 0x75b8, 0x6f => 0x768b, + 0x70 => 0x76b0, 0x71 => 0x76ca, 0x72 => 0x76cd, 0x73 => 0x76ce, + 0x74 => 0x7729, 0x75 => 0x771f, 0x76 => 0x7720, 0x77 => 0x7728, + 0x78 => 0x77e9, 0x79 => 0x7830, 0x7a => 0x7827, 0x7b => 0x7838, + 0x7c => 0x781d, 0x7d => 0x7834, 0x7e => 0x7837, 0xa1 => 0x7825, + 0xa2 => 0x782d, 0xa3 => 0x7820, 0xa4 => 0x781f, 0xa5 => 0x7832, + 0xa6 => 0x7955, 0xa7 => 0x7950, 0xa8 => 0x7960, 0xa9 => 0x795f, + 0xaa => 0x7956, 0xab => 0x795e, 0xac => 0x795d, 0xad => 0x7957, + 0xae => 0x795a, 0xaf => 0x79e4, 0xb0 => 0x79e3, 0xb1 => 0x79e7, + 0xb2 => 0x79df, 0xb3 => 0x79e6, 0xb4 => 0x79e9, 0xb5 => 0x79d8, + 0xb6 => 0x7a84, 0xb7 => 0x7a88, 0xb8 => 0x7ad9, 0xb9 => 0x7b06, + 0xba => 0x7b11, 0xbb => 0x7c89, 0xbc => 0x7d21, 0xbd => 0x7d17, + 0xbe => 0x7d0b, 0xbf => 0x7d0a, 0xc0 => 0x7d20, 0xc1 => 0x7d22, + 0xc2 => 0x7d14, 0xc3 => 0x7d10, 0xc4 => 0x7d15, 0xc5 => 0x7d1a, + 0xc6 => 0x7d1c, 0xc7 => 0x7d0d, 0xc8 => 0x7d19, 0xc9 => 0x7d1b, + 0xca => 0x7f3a, 0xcb => 0x7f5f, 0xcc => 0x7f94, 0xcd => 0x7fc5, + 0xce => 0x7fc1, 0xcf => 0x8006, 0xd0 => 0x8018, 0xd1 => 0x8015, + 0xd2 => 0x8019, 0xd3 => 0x8017, 0xd4 => 0x803d, 0xd5 => 0x803f, + 0xd6 => 0x80f1, 0xd7 => 0x8102, 0xd8 => 0x80f0, 0xd9 => 0x8105, + 0xda => 0x80ed, 0xdb => 0x80f4, 0xdc => 0x8106, 0xdd => 0x80f8, + 0xde => 0x80f3, 0xdf => 0x8108, 0xe0 => 0x80fd, 0xe1 => 0x810a, + 0xe2 => 0x80fc, 0xe3 => 0x80ef, 0xe4 => 0x81ed, 0xe5 => 0x81ec, + 0xe6 => 0x8200, 0xe7 => 0x8210, 0xe8 => 0x822a, 0xe9 => 0x822b, + 0xea => 0x8228, 0xeb => 0x822c, 0xec => 0x82bb, 0xed => 0x832b, + 0xee => 0x8352, 0xef => 0x8354, 0xf0 => 0x834a, 0xf1 => 0x8338, + 0xf2 => 0x8350, 0xf3 => 0x8349, 0xf4 => 0x8335, 0xf5 => 0x8334, + 0xf6 => 0x834f, 0xf7 => 0x8332, 0xf8 => 0x8339, 0xf9 => 0x8336, + 0xfa => 0x8317, 0xfb => 0x8340, 0xfc => 0x8331, 0xfd => 0x8328, + 0xfe => 0x8343, + }, + 0xb0 => { + 0x40 => 0x8654, 0x41 => 0x868a, 0x42 => 0x86aa, 0x43 => 0x8693, + 0x44 => 0x86a4, 0x45 => 0x86a9, 0x46 => 0x868c, 0x47 => 0x86a3, + 0x48 => 0x869c, 0x49 => 0x8870, 0x4a => 0x8877, 0x4b => 0x8881, + 0x4c => 0x8882, 0x4d => 0x887d, 0x4e => 0x8879, 0x4f => 0x8a18, + 0x50 => 0x8a10, 0x51 => 0x8a0e, 0x52 => 0x8a0c, 0x53 => 0x8a15, + 0x54 => 0x8a0a, 0x55 => 0x8a17, 0x56 => 0x8a13, 0x57 => 0x8a16, + 0x58 => 0x8a0f, 0x59 => 0x8a11, 0x5a => 0x8c48, 0x5b => 0x8c7a, + 0x5c => 0x8c79, 0x5d => 0x8ca1, 0x5e => 0x8ca2, 0x5f => 0x8d77, + 0x60 => 0x8eac, 0x61 => 0x8ed2, 0x62 => 0x8ed4, 0x63 => 0x8ecf, + 0x64 => 0x8fb1, 0x65 => 0x9001, 0x66 => 0x9006, 0x67 => 0x8ff7, + 0x68 => 0x9000, 0x69 => 0x8ffa, 0x6a => 0x8ff4, 0x6b => 0x9003, + 0x6c => 0x8ffd, 0x6d => 0x9005, 0x6e => 0x8ff8, 0x6f => 0x9095, + 0x70 => 0x90e1, 0x71 => 0x90dd, 0x72 => 0x90e2, 0x73 => 0x9152, + 0x74 => 0x914d, 0x75 => 0x914c, 0x76 => 0x91d8, 0x77 => 0x91dd, + 0x78 => 0x91d7, 0x79 => 0x91dc, 0x7a => 0x91d9, 0x7b => 0x9583, + 0x7c => 0x9662, 0x7d => 0x9663, 0x7e => 0x9661, 0xa1 => 0x965b, + 0xa2 => 0x965d, 0xa3 => 0x9664, 0xa4 => 0x9658, 0xa5 => 0x965e, + 0xa6 => 0x96bb, 0xa7 => 0x98e2, 0xa8 => 0x99ac, 0xa9 => 0x9aa8, + 0xaa => 0x9ad8, 0xab => 0x9b25, 0xac => 0x9b32, 0xad => 0x9b3c, + 0xae => 0x4e7e, 0xaf => 0x507a, 0xb0 => 0x507d, 0xb1 => 0x505c, + 0xb2 => 0x5047, 0xb3 => 0x5043, 0xb4 => 0x504c, 0xb5 => 0x505a, + 0xb6 => 0x5049, 0xb7 => 0x5065, 0xb8 => 0x5076, 0xb9 => 0x504e, + 0xba => 0x5055, 0xbb => 0x5075, 0xbc => 0x5074, 0xbd => 0x5077, + 0xbe => 0x504f, 0xbf => 0x500f, 0xc0 => 0x506f, 0xc1 => 0x506d, + 0xc2 => 0x515c, 0xc3 => 0x5195, 0xc4 => 0x51f0, 0xc5 => 0x526a, + 0xc6 => 0x526f, 0xc7 => 0x52d2, 0xc8 => 0x52d9, 0xc9 => 0x52d8, + 0xca => 0x52d5, 0xcb => 0x5310, 0xcc => 0x530f, 0xcd => 0x5319, + 0xce => 0x533f, 0xcf => 0x5340, 0xd0 => 0x533e, 0xd1 => 0x53c3, + 0xd2 => 0x66fc, 0xd3 => 0x5546, 0xd4 => 0x556a, 0xd5 => 0x5566, + 0xd6 => 0x5544, 0xd7 => 0x555e, 0xd8 => 0x5561, 0xd9 => 0x5543, + 0xda => 0x554a, 0xdb => 0x5531, 0xdc => 0x5556, 0xdd => 0x554f, + 0xde => 0x5555, 0xdf => 0x552f, 0xe0 => 0x5564, 0xe1 => 0x5538, + 0xe2 => 0x552e, 0xe3 => 0x555c, 0xe4 => 0x552c, 0xe5 => 0x5563, + 0xe6 => 0x5533, 0xe7 => 0x5541, 0xe8 => 0x5557, 0xe9 => 0x5708, + 0xea => 0x570b, 0xeb => 0x5709, 0xec => 0x57df, 0xed => 0x5805, + 0xee => 0x580a, 0xef => 0x5806, 0xf0 => 0x57e0, 0xf1 => 0x57e4, + 0xf2 => 0x57fa, 0xf3 => 0x5802, 0xf4 => 0x5835, 0xf5 => 0x57f7, + 0xf6 => 0x57f9, 0xf7 => 0x5920, 0xf8 => 0x5962, 0xf9 => 0x5a36, + 0xfa => 0x5a41, 0xfb => 0x5a49, 0xfc => 0x5a66, 0xfd => 0x5a6a, + 0xfe => 0x5a40, + }, + 0xb1 => { + 0x40 => 0x5a3c, 0x41 => 0x5a62, 0x42 => 0x5a5a, 0x43 => 0x5a46, + 0x44 => 0x5a4a, 0x45 => 0x5b70, 0x46 => 0x5bc7, 0x47 => 0x5bc5, + 0x48 => 0x5bc4, 0x49 => 0x5bc2, 0x4a => 0x5bbf, 0x4b => 0x5bc6, + 0x4c => 0x5c09, 0x4d => 0x5c08, 0x4e => 0x5c07, 0x4f => 0x5c60, + 0x50 => 0x5c5c, 0x51 => 0x5c5d, 0x52 => 0x5d07, 0x53 => 0x5d06, + 0x54 => 0x5d0e, 0x55 => 0x5d1b, 0x56 => 0x5d16, 0x57 => 0x5d22, + 0x58 => 0x5d11, 0x59 => 0x5d29, 0x5a => 0x5d14, 0x5b => 0x5d19, + 0x5c => 0x5d24, 0x5d => 0x5d27, 0x5e => 0x5d17, 0x5f => 0x5de2, + 0x60 => 0x5e38, 0x61 => 0x5e36, 0x62 => 0x5e33, 0x63 => 0x5e37, + 0x64 => 0x5eb7, 0x65 => 0x5eb8, 0x66 => 0x5eb6, 0x67 => 0x5eb5, + 0x68 => 0x5ebe, 0x69 => 0x5f35, 0x6a => 0x5f37, 0x6b => 0x5f57, + 0x6c => 0x5f6c, 0x6d => 0x5f69, 0x6e => 0x5f6b, 0x6f => 0x5f97, + 0x70 => 0x5f99, 0x71 => 0x5f9e, 0x72 => 0x5f98, 0x73 => 0x5fa1, + 0x74 => 0x5fa0, 0x75 => 0x5f9c, 0x76 => 0x607f, 0x77 => 0x60a3, + 0x78 => 0x6089, 0x79 => 0x60a0, 0x7a => 0x60a8, 0x7b => 0x60cb, + 0x7c => 0x60b4, 0x7d => 0x60e6, 0x7e => 0x60bd, 0xa1 => 0x60c5, + 0xa2 => 0x60bb, 0xa3 => 0x60b5, 0xa4 => 0x60dc, 0xa5 => 0x60bc, + 0xa6 => 0x60d8, 0xa7 => 0x60d5, 0xa8 => 0x60c6, 0xa9 => 0x60df, + 0xaa => 0x60b8, 0xab => 0x60da, 0xac => 0x60c7, 0xad => 0x621a, + 0xae => 0x621b, 0xaf => 0x6248, 0xb0 => 0x63a0, 0xb1 => 0x63a7, + 0xb2 => 0x6372, 0xb3 => 0x6396, 0xb4 => 0x63a2, 0xb5 => 0x63a5, + 0xb6 => 0x6377, 0xb7 => 0x6367, 0xb8 => 0x6398, 0xb9 => 0x63aa, + 0xba => 0x6371, 0xbb => 0x63a9, 0xbc => 0x6389, 0xbd => 0x6383, + 0xbe => 0x639b, 0xbf => 0x636b, 0xc0 => 0x63a8, 0xc1 => 0x6384, + 0xc2 => 0x6388, 0xc3 => 0x6399, 0xc4 => 0x63a1, 0xc5 => 0x63ac, + 0xc6 => 0x6392, 0xc7 => 0x638f, 0xc8 => 0x6380, 0xc9 => 0x637b, + 0xca => 0x6369, 0xcb => 0x6368, 0xcc => 0x637a, 0xcd => 0x655d, + 0xce => 0x6556, 0xcf => 0x6551, 0xd0 => 0x6559, 0xd1 => 0x6557, + 0xd2 => 0x555f, 0xd3 => 0x654f, 0xd4 => 0x6558, 0xd5 => 0x6555, + 0xd6 => 0x6554, 0xd7 => 0x659c, 0xd8 => 0x659b, 0xd9 => 0x65ac, + 0xda => 0x65cf, 0xdb => 0x65cb, 0xdc => 0x65cc, 0xdd => 0x65ce, + 0xde => 0x665d, 0xdf => 0x665a, 0xe0 => 0x6664, 0xe1 => 0x6668, + 0xe2 => 0x6666, 0xe3 => 0x665e, 0xe4 => 0x66f9, 0xe5 => 0x52d7, + 0xe6 => 0x671b, 0xe7 => 0x6881, 0xe8 => 0x68af, 0xe9 => 0x68a2, + 0xea => 0x6893, 0xeb => 0x68b5, 0xec => 0x687f, 0xed => 0x6876, + 0xee => 0x68b1, 0xef => 0x68a7, 0xf0 => 0x6897, 0xf1 => 0x68b0, + 0xf2 => 0x6883, 0xf3 => 0x68c4, 0xf4 => 0x68ad, 0xf5 => 0x6886, + 0xf6 => 0x6885, 0xf7 => 0x6894, 0xf8 => 0x689d, 0xf9 => 0x68a8, + 0xfa => 0x689f, 0xfb => 0x68a1, 0xfc => 0x6882, 0xfd => 0x6b32, + 0xfe => 0x6bba, + }, + 0xb2 => { + 0x40 => 0x6beb, 0x41 => 0x6bec, 0x42 => 0x6c2b, 0x43 => 0x6d8e, + 0x44 => 0x6dbc, 0x45 => 0x6df3, 0x46 => 0x6dd9, 0x47 => 0x6db2, + 0x48 => 0x6de1, 0x49 => 0x6dcc, 0x4a => 0x6de4, 0x4b => 0x6dfb, + 0x4c => 0x6dfa, 0x4d => 0x6e05, 0x4e => 0x6dc7, 0x4f => 0x6dcb, + 0x50 => 0x6daf, 0x51 => 0x6dd1, 0x52 => 0x6dae, 0x53 => 0x6dde, + 0x54 => 0x6df9, 0x55 => 0x6db8, 0x56 => 0x6df7, 0x57 => 0x6df5, + 0x58 => 0x6dc5, 0x59 => 0x6dd2, 0x5a => 0x6e1a, 0x5b => 0x6db5, + 0x5c => 0x6dda, 0x5d => 0x6deb, 0x5e => 0x6dd8, 0x5f => 0x6dea, + 0x60 => 0x6df1, 0x61 => 0x6dee, 0x62 => 0x6de8, 0x63 => 0x6dc6, + 0x64 => 0x6dc4, 0x65 => 0x6daa, 0x66 => 0x6dec, 0x67 => 0x6dbf, + 0x68 => 0x6de6, 0x69 => 0x70f9, 0x6a => 0x7109, 0x6b => 0x710a, + 0x6c => 0x70fd, 0x6d => 0x70ef, 0x6e => 0x723d, 0x6f => 0x727d, + 0x70 => 0x7281, 0x71 => 0x731c, 0x72 => 0x731b, 0x73 => 0x7316, + 0x74 => 0x7313, 0x75 => 0x7319, 0x76 => 0x7387, 0x77 => 0x7405, + 0x78 => 0x740a, 0x79 => 0x7403, 0x7a => 0x7406, 0x7b => 0x73fe, + 0x7c => 0x740d, 0x7d => 0x74e0, 0x7e => 0x74f6, 0xa1 => 0x74f7, + 0xa2 => 0x751c, 0xa3 => 0x7522, 0xa4 => 0x7565, 0xa5 => 0x7566, + 0xa6 => 0x7562, 0xa7 => 0x7570, 0xa8 => 0x758f, 0xa9 => 0x75d4, + 0xaa => 0x75d5, 0xab => 0x75b5, 0xac => 0x75ca, 0xad => 0x75cd, + 0xae => 0x768e, 0xaf => 0x76d4, 0xb0 => 0x76d2, 0xb1 => 0x76db, + 0xb2 => 0x7737, 0xb3 => 0x773e, 0xb4 => 0x773c, 0xb5 => 0x7736, + 0xb6 => 0x7738, 0xb7 => 0x773a, 0xb8 => 0x786b, 0xb9 => 0x7843, + 0xba => 0x784e, 0xbb => 0x7965, 0xbc => 0x7968, 0xbd => 0x796d, + 0xbe => 0x79fb, 0xbf => 0x7a92, 0xc0 => 0x7a95, 0xc1 => 0x7b20, + 0xc2 => 0x7b28, 0xc3 => 0x7b1b, 0xc4 => 0x7b2c, 0xc5 => 0x7b26, + 0xc6 => 0x7b19, 0xc7 => 0x7b1e, 0xc8 => 0x7b2e, 0xc9 => 0x7c92, + 0xca => 0x7c97, 0xcb => 0x7c95, 0xcc => 0x7d46, 0xcd => 0x7d43, + 0xce => 0x7d71, 0xcf => 0x7d2e, 0xd0 => 0x7d39, 0xd1 => 0x7d3c, + 0xd2 => 0x7d40, 0xd3 => 0x7d30, 0xd4 => 0x7d33, 0xd5 => 0x7d44, + 0xd6 => 0x7d2f, 0xd7 => 0x7d42, 0xd8 => 0x7d32, 0xd9 => 0x7d31, + 0xda => 0x7f3d, 0xdb => 0x7f9e, 0xdc => 0x7f9a, 0xdd => 0x7fcc, + 0xde => 0x7fce, 0xdf => 0x7fd2, 0xe0 => 0x801c, 0xe1 => 0x804a, + 0xe2 => 0x8046, 0xe3 => 0x812f, 0xe4 => 0x8116, 0xe5 => 0x8123, + 0xe6 => 0x812b, 0xe7 => 0x8129, 0xe8 => 0x8130, 0xe9 => 0x8124, + 0xea => 0x8202, 0xeb => 0x8235, 0xec => 0x8237, 0xed => 0x8236, + 0xee => 0x8239, 0xef => 0x838e, 0xf0 => 0x839e, 0xf1 => 0x8398, + 0xf2 => 0x8378, 0xf3 => 0x83a2, 0xf4 => 0x8396, 0xf5 => 0x83bd, + 0xf6 => 0x83ab, 0xf7 => 0x8392, 0xf8 => 0x838a, 0xf9 => 0x8393, + 0xfa => 0x8389, 0xfb => 0x83a0, 0xfc => 0x8377, 0xfd => 0x837b, + 0xfe => 0x837c, + }, + 0xb3 => { + 0x40 => 0x8386, 0x41 => 0x83a7, 0x42 => 0x8655, 0x43 => 0x5f6a, + 0x44 => 0x86c7, 0x45 => 0x86c0, 0x46 => 0x86b6, 0x47 => 0x86c4, + 0x48 => 0x86b5, 0x49 => 0x86c6, 0x4a => 0x86cb, 0x4b => 0x86b1, + 0x4c => 0x86af, 0x4d => 0x86c9, 0x4e => 0x8853, 0x4f => 0x889e, + 0x50 => 0x8888, 0x51 => 0x88ab, 0x52 => 0x8892, 0x53 => 0x8896, + 0x54 => 0x888d, 0x55 => 0x888b, 0x56 => 0x8993, 0x57 => 0x898f, + 0x58 => 0x8a2a, 0x59 => 0x8a1d, 0x5a => 0x8a23, 0x5b => 0x8a25, + 0x5c => 0x8a31, 0x5d => 0x8a2d, 0x5e => 0x8a1f, 0x5f => 0x8a1b, + 0x60 => 0x8a22, 0x61 => 0x8c49, 0x62 => 0x8c5a, 0x63 => 0x8ca9, + 0x64 => 0x8cac, 0x65 => 0x8cab, 0x66 => 0x8ca8, 0x67 => 0x8caa, + 0x68 => 0x8ca7, 0x69 => 0x8d67, 0x6a => 0x8d66, 0x6b => 0x8dbe, + 0x6c => 0x8dba, 0x6d => 0x8edb, 0x6e => 0x8edf, 0x6f => 0x9019, + 0x70 => 0x900d, 0x71 => 0x901a, 0x72 => 0x9017, 0x73 => 0x9023, + 0x74 => 0x901f, 0x75 => 0x901d, 0x76 => 0x9010, 0x77 => 0x9015, + 0x78 => 0x901e, 0x79 => 0x9020, 0x7a => 0x900f, 0x7b => 0x9022, + 0x7c => 0x9016, 0x7d => 0x901b, 0x7e => 0x9014, 0xa1 => 0x90e8, + 0xa2 => 0x90ed, 0xa3 => 0x90fd, 0xa4 => 0x9157, 0xa5 => 0x91ce, + 0xa6 => 0x91f5, 0xa7 => 0x91e6, 0xa8 => 0x91e3, 0xa9 => 0x91e7, + 0xaa => 0x91ed, 0xab => 0x91e9, 0xac => 0x9589, 0xad => 0x966a, + 0xae => 0x9675, 0xaf => 0x9673, 0xb0 => 0x9678, 0xb1 => 0x9670, + 0xb2 => 0x9674, 0xb3 => 0x9676, 0xb4 => 0x9677, 0xb5 => 0x966c, + 0xb6 => 0x96c0, 0xb7 => 0x96ea, 0xb8 => 0x96e9, 0xb9 => 0x7ae0, + 0xba => 0x7adf, 0xbb => 0x9802, 0xbc => 0x9803, 0xbd => 0x9b5a, + 0xbe => 0x9ce5, 0xbf => 0x9e75, 0xc0 => 0x9e7f, 0xc1 => 0x9ea5, + 0xc2 => 0x9ebb, 0xc3 => 0x50a2, 0xc4 => 0x508d, 0xc5 => 0x5085, + 0xc6 => 0x5099, 0xc7 => 0x5091, 0xc8 => 0x5080, 0xc9 => 0x5096, + 0xca => 0x5098, 0xcb => 0x509a, 0xcc => 0x6700, 0xcd => 0x51f1, + 0xce => 0x5272, 0xcf => 0x5274, 0xd0 => 0x5275, 0xd1 => 0x5269, + 0xd2 => 0x52de, 0xd3 => 0x52dd, 0xd4 => 0x52db, 0xd5 => 0x535a, + 0xd6 => 0x53a5, 0xd7 => 0x557b, 0xd8 => 0x5580, 0xd9 => 0x55a7, + 0xda => 0x557c, 0xdb => 0x558a, 0xdc => 0x559d, 0xdd => 0x5598, + 0xde => 0x5582, 0xdf => 0x559c, 0xe0 => 0x55aa, 0xe1 => 0x5594, + 0xe2 => 0x5587, 0xe3 => 0x558b, 0xe4 => 0x5583, 0xe5 => 0x55b3, + 0xe6 => 0x55ae, 0xe7 => 0x559f, 0xe8 => 0x553e, 0xe9 => 0x55b2, + 0xea => 0x559a, 0xeb => 0x55bb, 0xec => 0x55ac, 0xed => 0x55b1, + 0xee => 0x557e, 0xef => 0x5589, 0xf0 => 0x55ab, 0xf1 => 0x5599, + 0xf2 => 0x570d, 0xf3 => 0x582f, 0xf4 => 0x582a, 0xf5 => 0x5834, + 0xf6 => 0x5824, 0xf7 => 0x5830, 0xf8 => 0x5831, 0xf9 => 0x5821, + 0xfa => 0x581d, 0xfb => 0x5820, 0xfc => 0x58f9, 0xfd => 0x58fa, + 0xfe => 0x5960, + }, + 0xb4 => { + 0x40 => 0x5a77, 0x41 => 0x5a9a, 0x42 => 0x5a7f, 0x43 => 0x5a92, + 0x44 => 0x5a9b, 0x45 => 0x5aa7, 0x46 => 0x5b73, 0x47 => 0x5b71, + 0x48 => 0x5bd2, 0x49 => 0x5bcc, 0x4a => 0x5bd3, 0x4b => 0x5bd0, + 0x4c => 0x5c0a, 0x4d => 0x5c0b, 0x4e => 0x5c31, 0x4f => 0x5d4c, + 0x50 => 0x5d50, 0x51 => 0x5d34, 0x52 => 0x5d47, 0x53 => 0x5dfd, + 0x54 => 0x5e45, 0x55 => 0x5e3d, 0x56 => 0x5e40, 0x57 => 0x5e43, + 0x58 => 0x5e7e, 0x59 => 0x5eca, 0x5a => 0x5ec1, 0x5b => 0x5ec2, + 0x5c => 0x5ec4, 0x5d => 0x5f3c, 0x5e => 0x5f6d, 0x5f => 0x5fa9, + 0x60 => 0x5faa, 0x61 => 0x5fa8, 0x62 => 0x60d1, 0x63 => 0x60e1, + 0x64 => 0x60b2, 0x65 => 0x60b6, 0x66 => 0x60e0, 0x67 => 0x611c, + 0x68 => 0x6123, 0x69 => 0x60fa, 0x6a => 0x6115, 0x6b => 0x60f0, + 0x6c => 0x60fb, 0x6d => 0x60f4, 0x6e => 0x6168, 0x6f => 0x60f1, + 0x70 => 0x610e, 0x71 => 0x60f6, 0x72 => 0x6109, 0x73 => 0x6100, + 0x74 => 0x6112, 0x75 => 0x621f, 0x76 => 0x6249, 0x77 => 0x63a3, + 0x78 => 0x638c, 0x79 => 0x63cf, 0x7a => 0x63c0, 0x7b => 0x63e9, + 0x7c => 0x63c9, 0x7d => 0x63c6, 0x7e => 0x63cd, 0xa1 => 0x63d2, + 0xa2 => 0x63e3, 0xa3 => 0x63d0, 0xa4 => 0x63e1, 0xa5 => 0x63d6, + 0xa6 => 0x63ed, 0xa7 => 0x63ee, 0xa8 => 0x6376, 0xa9 => 0x63f4, + 0xaa => 0x63ea, 0xab => 0x63db, 0xac => 0x6452, 0xad => 0x63da, + 0xae => 0x63f9, 0xaf => 0x655e, 0xb0 => 0x6566, 0xb1 => 0x6562, + 0xb2 => 0x6563, 0xb3 => 0x6591, 0xb4 => 0x6590, 0xb5 => 0x65af, + 0xb6 => 0x666e, 0xb7 => 0x6670, 0xb8 => 0x6674, 0xb9 => 0x6676, + 0xba => 0x666f, 0xbb => 0x6691, 0xbc => 0x667a, 0xbd => 0x667e, + 0xbe => 0x6677, 0xbf => 0x66fe, 0xc0 => 0x66ff, 0xc1 => 0x671f, + 0xc2 => 0x671d, 0xc3 => 0x68fa, 0xc4 => 0x68d5, 0xc5 => 0x68e0, + 0xc6 => 0x68d8, 0xc7 => 0x68d7, 0xc8 => 0x6905, 0xc9 => 0x68df, + 0xca => 0x68f5, 0xcb => 0x68ee, 0xcc => 0x68e7, 0xcd => 0x68f9, + 0xce => 0x68d2, 0xcf => 0x68f2, 0xd0 => 0x68e3, 0xd1 => 0x68cb, + 0xd2 => 0x68cd, 0xd3 => 0x690d, 0xd4 => 0x6912, 0xd5 => 0x690e, + 0xd6 => 0x68c9, 0xd7 => 0x68da, 0xd8 => 0x696e, 0xd9 => 0x68fb, + 0xda => 0x6b3e, 0xdb => 0x6b3a, 0xdc => 0x6b3d, 0xdd => 0x6b98, + 0xde => 0x6b96, 0xdf => 0x6bbc, 0xe0 => 0x6bef, 0xe1 => 0x6c2e, + 0xe2 => 0x6c2f, 0xe3 => 0x6c2c, 0xe4 => 0x6e2f, 0xe5 => 0x6e38, + 0xe6 => 0x6e54, 0xe7 => 0x6e21, 0xe8 => 0x6e32, 0xe9 => 0x6e67, + 0xea => 0x6e4a, 0xeb => 0x6e20, 0xec => 0x6e25, 0xed => 0x6e23, + 0xee => 0x6e1b, 0xef => 0x6e5b, 0xf0 => 0x6e58, 0xf1 => 0x6e24, + 0xf2 => 0x6e56, 0xf3 => 0x6e6e, 0xf4 => 0x6e2d, 0xf5 => 0x6e26, + 0xf6 => 0x6e6f, 0xf7 => 0x6e34, 0xf8 => 0x6e4d, 0xf9 => 0x6e3a, + 0xfa => 0x6e2c, 0xfb => 0x6e43, 0xfc => 0x6e1d, 0xfd => 0x6e3e, + 0xfe => 0x6ecb, + }, + 0xb5 => { + 0x40 => 0x6e89, 0x41 => 0x6e19, 0x42 => 0x6e4e, 0x43 => 0x6e63, + 0x44 => 0x6e44, 0x45 => 0x6e72, 0x46 => 0x6e69, 0x47 => 0x6e5f, + 0x48 => 0x7119, 0x49 => 0x711a, 0x4a => 0x7126, 0x4b => 0x7130, + 0x4c => 0x7121, 0x4d => 0x7136, 0x4e => 0x716e, 0x4f => 0x711c, + 0x50 => 0x724c, 0x51 => 0x7284, 0x52 => 0x7280, 0x53 => 0x7336, + 0x54 => 0x7325, 0x55 => 0x7334, 0x56 => 0x7329, 0x57 => 0x743a, + 0x58 => 0x742a, 0x59 => 0x7433, 0x5a => 0x7422, 0x5b => 0x7425, + 0x5c => 0x7435, 0x5d => 0x7436, 0x5e => 0x7434, 0x5f => 0x742f, + 0x60 => 0x741b, 0x61 => 0x7426, 0x62 => 0x7428, 0x63 => 0x7525, + 0x64 => 0x7526, 0x65 => 0x756b, 0x66 => 0x756a, 0x67 => 0x75e2, + 0x68 => 0x75db, 0x69 => 0x75e3, 0x6a => 0x75d9, 0x6b => 0x75d8, + 0x6c => 0x75de, 0x6d => 0x75e0, 0x6e => 0x767b, 0x6f => 0x767c, + 0x70 => 0x7696, 0x71 => 0x7693, 0x72 => 0x76b4, 0x73 => 0x76dc, + 0x74 => 0x774f, 0x75 => 0x77ed, 0x76 => 0x785d, 0x77 => 0x786c, + 0x78 => 0x786f, 0x79 => 0x7a0d, 0x7a => 0x7a08, 0x7b => 0x7a0b, + 0x7c => 0x7a05, 0x7d => 0x7a00, 0x7e => 0x7a98, 0xa1 => 0x7a97, + 0xa2 => 0x7a96, 0xa3 => 0x7ae5, 0xa4 => 0x7ae3, 0xa5 => 0x7b49, + 0xa6 => 0x7b56, 0xa7 => 0x7b46, 0xa8 => 0x7b50, 0xa9 => 0x7b52, + 0xaa => 0x7b54, 0xab => 0x7b4d, 0xac => 0x7b4b, 0xad => 0x7b4f, + 0xae => 0x7b51, 0xaf => 0x7c9f, 0xb0 => 0x7ca5, 0xb1 => 0x7d5e, + 0xb2 => 0x7d50, 0xb3 => 0x7d68, 0xb4 => 0x7d55, 0xb5 => 0x7d2b, + 0xb6 => 0x7d6e, 0xb7 => 0x7d72, 0xb8 => 0x7d61, 0xb9 => 0x7d66, + 0xba => 0x7d62, 0xbb => 0x7d70, 0xbc => 0x7d73, 0xbd => 0x5584, + 0xbe => 0x7fd4, 0xbf => 0x7fd5, 0xc0 => 0x800b, 0xc1 => 0x8052, + 0xc2 => 0x8085, 0xc3 => 0x8155, 0xc4 => 0x8154, 0xc5 => 0x814b, + 0xc6 => 0x8151, 0xc7 => 0x814e, 0xc8 => 0x8139, 0xc9 => 0x8146, + 0xca => 0x813e, 0xcb => 0x814c, 0xcc => 0x8153, 0xcd => 0x8174, + 0xce => 0x8212, 0xcf => 0x821c, 0xd0 => 0x83e9, 0xd1 => 0x8403, + 0xd2 => 0x83f8, 0xd3 => 0x840d, 0xd4 => 0x83e0, 0xd5 => 0x83c5, + 0xd6 => 0x840b, 0xd7 => 0x83c1, 0xd8 => 0x83ef, 0xd9 => 0x83f1, + 0xda => 0x83f4, 0xdb => 0x8457, 0xdc => 0x840a, 0xdd => 0x83f0, + 0xde => 0x840c, 0xdf => 0x83cc, 0xe0 => 0x83fd, 0xe1 => 0x83f2, + 0xe2 => 0x83ca, 0xe3 => 0x8438, 0xe4 => 0x840e, 0xe5 => 0x8404, + 0xe6 => 0x83dc, 0xe7 => 0x8407, 0xe8 => 0x83d4, 0xe9 => 0x83df, + 0xea => 0x865b, 0xeb => 0x86df, 0xec => 0x86d9, 0xed => 0x86ed, + 0xee => 0x86d4, 0xef => 0x86db, 0xf0 => 0x86e4, 0xf1 => 0x86d0, + 0xf2 => 0x86de, 0xf3 => 0x8857, 0xf4 => 0x88c1, 0xf5 => 0x88c2, + 0xf6 => 0x88b1, 0xf7 => 0x8983, 0xf8 => 0x8996, 0xf9 => 0x8a3b, + 0xfa => 0x8a60, 0xfb => 0x8a55, 0xfc => 0x8a5e, 0xfd => 0x8a3c, + 0xfe => 0x8a41, + }, + 0xb6 => { + 0x40 => 0x8a54, 0x41 => 0x8a5b, 0x42 => 0x8a50, 0x43 => 0x8a46, + 0x44 => 0x8a34, 0x45 => 0x8a3a, 0x46 => 0x8a36, 0x47 => 0x8a56, + 0x48 => 0x8c61, 0x49 => 0x8c82, 0x4a => 0x8caf, 0x4b => 0x8cbc, + 0x4c => 0x8cb3, 0x4d => 0x8cbd, 0x4e => 0x8cc1, 0x4f => 0x8cbb, + 0x50 => 0x8cc0, 0x51 => 0x8cb4, 0x52 => 0x8cb7, 0x53 => 0x8cb6, + 0x54 => 0x8cbf, 0x55 => 0x8cb8, 0x56 => 0x8d8a, 0x57 => 0x8d85, + 0x58 => 0x8d81, 0x59 => 0x8dce, 0x5a => 0x8ddd, 0x5b => 0x8dcb, + 0x5c => 0x8dda, 0x5d => 0x8dd1, 0x5e => 0x8dcc, 0x5f => 0x8ddb, + 0x60 => 0x8dc6, 0x61 => 0x8efb, 0x62 => 0x8ef8, 0x63 => 0x8efc, + 0x64 => 0x8f9c, 0x65 => 0x902e, 0x66 => 0x9035, 0x67 => 0x9031, + 0x68 => 0x9038, 0x69 => 0x9032, 0x6a => 0x9036, 0x6b => 0x9102, + 0x6c => 0x90f5, 0x6d => 0x9109, 0x6e => 0x90fe, 0x6f => 0x9163, + 0x70 => 0x9165, 0x71 => 0x91cf, 0x72 => 0x9214, 0x73 => 0x9215, + 0x74 => 0x9223, 0x75 => 0x9209, 0x76 => 0x921e, 0x77 => 0x920d, + 0x78 => 0x9210, 0x79 => 0x9207, 0x7a => 0x9211, 0x7b => 0x9594, + 0x7c => 0x958f, 0x7d => 0x958b, 0x7e => 0x9591, 0xa1 => 0x9593, + 0xa2 => 0x9592, 0xa3 => 0x958e, 0xa4 => 0x968a, 0xa5 => 0x968e, + 0xa6 => 0x968b, 0xa7 => 0x967d, 0xa8 => 0x9685, 0xa9 => 0x9686, + 0xaa => 0x968d, 0xab => 0x9672, 0xac => 0x9684, 0xad => 0x96c1, + 0xae => 0x96c5, 0xaf => 0x96c4, 0xb0 => 0x96c6, 0xb1 => 0x96c7, + 0xb2 => 0x96ef, 0xb3 => 0x96f2, 0xb4 => 0x97cc, 0xb5 => 0x9805, + 0xb6 => 0x9806, 0xb7 => 0x9808, 0xb8 => 0x98e7, 0xb9 => 0x98ea, + 0xba => 0x98ef, 0xbb => 0x98e9, 0xbc => 0x98f2, 0xbd => 0x98ed, + 0xbe => 0x99ae, 0xbf => 0x99ad, 0xc0 => 0x9ec3, 0xc1 => 0x9ecd, + 0xc2 => 0x9ed1, 0xc3 => 0x4e82, 0xc4 => 0x50ad, 0xc5 => 0x50b5, + 0xc6 => 0x50b2, 0xc7 => 0x50b3, 0xc8 => 0x50c5, 0xc9 => 0x50be, + 0xca => 0x50ac, 0xcb => 0x50b7, 0xcc => 0x50bb, 0xcd => 0x50af, + 0xce => 0x50c7, 0xcf => 0x527f, 0xd0 => 0x5277, 0xd1 => 0x527d, + 0xd2 => 0x52df, 0xd3 => 0x52e6, 0xd4 => 0x52e4, 0xd5 => 0x52e2, + 0xd6 => 0x52e3, 0xd7 => 0x532f, 0xd8 => 0x55df, 0xd9 => 0x55e8, + 0xda => 0x55d3, 0xdb => 0x55e6, 0xdc => 0x55ce, 0xdd => 0x55dc, + 0xde => 0x55c7, 0xdf => 0x55d1, 0xe0 => 0x55e3, 0xe1 => 0x55e4, + 0xe2 => 0x55ef, 0xe3 => 0x55da, 0xe4 => 0x55e1, 0xe5 => 0x55c5, + 0xe6 => 0x55c6, 0xe7 => 0x55e5, 0xe8 => 0x55c9, 0xe9 => 0x5712, + 0xea => 0x5713, 0xeb => 0x585e, 0xec => 0x5851, 0xed => 0x5858, + 0xee => 0x5857, 0xef => 0x585a, 0xf0 => 0x5854, 0xf1 => 0x586b, + 0xf2 => 0x584c, 0xf3 => 0x586d, 0xf4 => 0x584a, 0xf5 => 0x5862, + 0xf6 => 0x5852, 0xf7 => 0x584b, 0xf8 => 0x5967, 0xf9 => 0x5ac1, + 0xfa => 0x5ac9, 0xfb => 0x5acc, 0xfc => 0x5abe, 0xfd => 0x5abd, + 0xfe => 0x5abc, + }, + 0xb7 => { + 0x40 => 0x5ab3, 0x41 => 0x5ac2, 0x42 => 0x5ab2, 0x43 => 0x5d69, + 0x44 => 0x5d6f, 0x45 => 0x5e4c, 0x46 => 0x5e79, 0x47 => 0x5ec9, + 0x48 => 0x5ec8, 0x49 => 0x5f12, 0x4a => 0x5f59, 0x4b => 0x5fac, + 0x4c => 0x5fae, 0x4d => 0x611a, 0x4e => 0x610f, 0x4f => 0x6148, + 0x50 => 0x611f, 0x51 => 0x60f3, 0x52 => 0x611b, 0x53 => 0x60f9, + 0x54 => 0x6101, 0x55 => 0x6108, 0x56 => 0x614e, 0x57 => 0x614c, + 0x58 => 0x6144, 0x59 => 0x614d, 0x5a => 0x613e, 0x5b => 0x6134, + 0x5c => 0x6127, 0x5d => 0x610d, 0x5e => 0x6106, 0x5f => 0x6137, + 0x60 => 0x6221, 0x61 => 0x6222, 0x62 => 0x6413, 0x63 => 0x643e, + 0x64 => 0x641e, 0x65 => 0x642a, 0x66 => 0x642d, 0x67 => 0x643d, + 0x68 => 0x642c, 0x69 => 0x640f, 0x6a => 0x641c, 0x6b => 0x6414, + 0x6c => 0x640d, 0x6d => 0x6436, 0x6e => 0x6416, 0x6f => 0x6417, + 0x70 => 0x6406, 0x71 => 0x656c, 0x72 => 0x659f, 0x73 => 0x65b0, + 0x74 => 0x6697, 0x75 => 0x6689, 0x76 => 0x6687, 0x77 => 0x6688, + 0x78 => 0x6696, 0x79 => 0x6684, 0x7a => 0x6698, 0x7b => 0x668d, + 0x7c => 0x6703, 0x7d => 0x6994, 0x7e => 0x696d, 0xa1 => 0x695a, + 0xa2 => 0x6977, 0xa3 => 0x6960, 0xa4 => 0x6954, 0xa5 => 0x6975, + 0xa6 => 0x6930, 0xa7 => 0x6982, 0xa8 => 0x694a, 0xa9 => 0x6968, + 0xaa => 0x696b, 0xab => 0x695e, 0xac => 0x6953, 0xad => 0x6979, + 0xae => 0x6986, 0xaf => 0x695d, 0xb0 => 0x6963, 0xb1 => 0x695b, + 0xb2 => 0x6b47, 0xb3 => 0x6b72, 0xb4 => 0x6bc0, 0xb5 => 0x6bbf, + 0xb6 => 0x6bd3, 0xb7 => 0x6bfd, 0xb8 => 0x6ea2, 0xb9 => 0x6eaf, + 0xba => 0x6ed3, 0xbb => 0x6eb6, 0xbc => 0x6ec2, 0xbd => 0x6e90, + 0xbe => 0x6e9d, 0xbf => 0x6ec7, 0xc0 => 0x6ec5, 0xc1 => 0x6ea5, + 0xc2 => 0x6e98, 0xc3 => 0x6ebc, 0xc4 => 0x6eba, 0xc5 => 0x6eab, + 0xc6 => 0x6ed1, 0xc7 => 0x6e96, 0xc8 => 0x6e9c, 0xc9 => 0x6ec4, + 0xca => 0x6ed4, 0xcb => 0x6eaa, 0xcc => 0x6ea7, 0xcd => 0x6eb4, + 0xce => 0x714e, 0xcf => 0x7159, 0xd0 => 0x7169, 0xd1 => 0x7164, + 0xd2 => 0x7149, 0xd3 => 0x7167, 0xd4 => 0x715c, 0xd5 => 0x716c, + 0xd6 => 0x7166, 0xd7 => 0x714c, 0xd8 => 0x7165, 0xd9 => 0x715e, + 0xda => 0x7146, 0xdb => 0x7168, 0xdc => 0x7156, 0xdd => 0x723a, + 0xde => 0x7252, 0xdf => 0x7337, 0xe0 => 0x7345, 0xe1 => 0x733f, + 0xe2 => 0x733e, 0xe3 => 0x746f, 0xe4 => 0x745a, 0xe5 => 0x7455, + 0xe6 => 0x745f, 0xe7 => 0x745e, 0xe8 => 0x7441, 0xe9 => 0x743f, + 0xea => 0x7459, 0xeb => 0x745b, 0xec => 0x745c, 0xed => 0x7576, + 0xee => 0x7578, 0xef => 0x7600, 0xf0 => 0x75f0, 0xf1 => 0x7601, + 0xf2 => 0x75f2, 0xf3 => 0x75f1, 0xf4 => 0x75fa, 0xf5 => 0x75ff, + 0xf6 => 0x75f4, 0xf7 => 0x75f3, 0xf8 => 0x76de, 0xf9 => 0x76df, + 0xfa => 0x775b, 0xfb => 0x776b, 0xfc => 0x7766, 0xfd => 0x775e, + 0xfe => 0x7763, + }, + 0xb8 => { + 0x40 => 0x7779, 0x41 => 0x776a, 0x42 => 0x776c, 0x43 => 0x775c, + 0x44 => 0x7765, 0x45 => 0x7768, 0x46 => 0x7762, 0x47 => 0x77ee, + 0x48 => 0x788e, 0x49 => 0x78b0, 0x4a => 0x7897, 0x4b => 0x7898, + 0x4c => 0x788c, 0x4d => 0x7889, 0x4e => 0x787c, 0x4f => 0x7891, + 0x50 => 0x7893, 0x51 => 0x787f, 0x52 => 0x797a, 0x53 => 0x797f, + 0x54 => 0x7981, 0x55 => 0x842c, 0x56 => 0x79bd, 0x57 => 0x7a1c, + 0x58 => 0x7a1a, 0x59 => 0x7a20, 0x5a => 0x7a14, 0x5b => 0x7a1f, + 0x5c => 0x7a1e, 0x5d => 0x7a9f, 0x5e => 0x7aa0, 0x5f => 0x7b77, + 0x60 => 0x7bc0, 0x61 => 0x7b60, 0x62 => 0x7b6e, 0x63 => 0x7b67, + 0x64 => 0x7cb1, 0x65 => 0x7cb3, 0x66 => 0x7cb5, 0x67 => 0x7d93, + 0x68 => 0x7d79, 0x69 => 0x7d91, 0x6a => 0x7d81, 0x6b => 0x7d8f, + 0x6c => 0x7d5b, 0x6d => 0x7f6e, 0x6e => 0x7f69, 0x6f => 0x7f6a, + 0x70 => 0x7f72, 0x71 => 0x7fa9, 0x72 => 0x7fa8, 0x73 => 0x7fa4, + 0x74 => 0x8056, 0x75 => 0x8058, 0x76 => 0x8086, 0x77 => 0x8084, + 0x78 => 0x8171, 0x79 => 0x8170, 0x7a => 0x8178, 0x7b => 0x8165, + 0x7c => 0x816e, 0x7d => 0x8173, 0x7e => 0x816b, 0xa1 => 0x8179, + 0xa2 => 0x817a, 0xa3 => 0x8166, 0xa4 => 0x8205, 0xa5 => 0x8247, + 0xa6 => 0x8482, 0xa7 => 0x8477, 0xa8 => 0x843d, 0xa9 => 0x8431, + 0xaa => 0x8475, 0xab => 0x8466, 0xac => 0x846b, 0xad => 0x8449, + 0xae => 0x846c, 0xaf => 0x845b, 0xb0 => 0x843c, 0xb1 => 0x8435, + 0xb2 => 0x8461, 0xb3 => 0x8463, 0xb4 => 0x8469, 0xb5 => 0x846d, + 0xb6 => 0x8446, 0xb7 => 0x865e, 0xb8 => 0x865c, 0xb9 => 0x865f, + 0xba => 0x86f9, 0xbb => 0x8713, 0xbc => 0x8708, 0xbd => 0x8707, + 0xbe => 0x8700, 0xbf => 0x86fe, 0xc0 => 0x86fb, 0xc1 => 0x8702, + 0xc2 => 0x8703, 0xc3 => 0x8706, 0xc4 => 0x870a, 0xc5 => 0x8859, + 0xc6 => 0x88df, 0xc7 => 0x88d4, 0xc8 => 0x88d9, 0xc9 => 0x88dc, + 0xca => 0x88d8, 0xcb => 0x88dd, 0xcc => 0x88e1, 0xcd => 0x88ca, + 0xce => 0x88d5, 0xcf => 0x88d2, 0xd0 => 0x899c, 0xd1 => 0x89e3, + 0xd2 => 0x8a6b, 0xd3 => 0x8a72, 0xd4 => 0x8a73, 0xd5 => 0x8a66, + 0xd6 => 0x8a69, 0xd7 => 0x8a70, 0xd8 => 0x8a87, 0xd9 => 0x8a7c, + 0xda => 0x8a63, 0xdb => 0x8aa0, 0xdc => 0x8a71, 0xdd => 0x8a85, + 0xde => 0x8a6d, 0xdf => 0x8a62, 0xe0 => 0x8a6e, 0xe1 => 0x8a6c, + 0xe2 => 0x8a79, 0xe3 => 0x8a7b, 0xe4 => 0x8a3e, 0xe5 => 0x8a68, + 0xe6 => 0x8c62, 0xe7 => 0x8c8a, 0xe8 => 0x8c89, 0xe9 => 0x8cca, + 0xea => 0x8cc7, 0xeb => 0x8cc8, 0xec => 0x8cc4, 0xed => 0x8cb2, + 0xee => 0x8cc3, 0xef => 0x8cc2, 0xf0 => 0x8cc5, 0xf1 => 0x8de1, + 0xf2 => 0x8ddf, 0xf3 => 0x8de8, 0xf4 => 0x8def, 0xf5 => 0x8df3, + 0xf6 => 0x8dfa, 0xf7 => 0x8dea, 0xf8 => 0x8de4, 0xf9 => 0x8de6, + 0xfa => 0x8eb2, 0xfb => 0x8f03, 0xfc => 0x8f09, 0xfd => 0x8efe, + 0xfe => 0x8f0a, + }, + 0xb9 => { + 0x40 => 0x8f9f, 0x41 => 0x8fb2, 0x42 => 0x904b, 0x43 => 0x904a, + 0x44 => 0x9053, 0x45 => 0x9042, 0x46 => 0x9054, 0x47 => 0x903c, + 0x48 => 0x9055, 0x49 => 0x9050, 0x4a => 0x9047, 0x4b => 0x904f, + 0x4c => 0x904e, 0x4d => 0x904d, 0x4e => 0x9051, 0x4f => 0x903e, + 0x50 => 0x9041, 0x51 => 0x9112, 0x52 => 0x9117, 0x53 => 0x916c, + 0x54 => 0x916a, 0x55 => 0x9169, 0x56 => 0x91c9, 0x57 => 0x9237, + 0x58 => 0x9257, 0x59 => 0x9238, 0x5a => 0x923d, 0x5b => 0x9240, + 0x5c => 0x923e, 0x5d => 0x925b, 0x5e => 0x924b, 0x5f => 0x9264, + 0x60 => 0x9251, 0x61 => 0x9234, 0x62 => 0x9249, 0x63 => 0x924d, + 0x64 => 0x9245, 0x65 => 0x9239, 0x66 => 0x923f, 0x67 => 0x925a, + 0x68 => 0x9598, 0x69 => 0x9698, 0x6a => 0x9694, 0x6b => 0x9695, + 0x6c => 0x96cd, 0x6d => 0x96cb, 0x6e => 0x96c9, 0x6f => 0x96ca, + 0x70 => 0x96f7, 0x71 => 0x96fb, 0x72 => 0x96f9, 0x73 => 0x96f6, + 0x74 => 0x9756, 0x75 => 0x9774, 0x76 => 0x9776, 0x77 => 0x9810, + 0x78 => 0x9811, 0x79 => 0x9813, 0x7a => 0x980a, 0x7b => 0x9812, + 0x7c => 0x980c, 0x7d => 0x98fc, 0x7e => 0x98f4, 0xa1 => 0x98fd, + 0xa2 => 0x98fe, 0xa3 => 0x99b3, 0xa4 => 0x99b1, 0xa5 => 0x99b4, + 0xa6 => 0x9ae1, 0xa7 => 0x9ce9, 0xa8 => 0x9e82, 0xa9 => 0x9f0e, + 0xaa => 0x9f13, 0xab => 0x9f20, 0xac => 0x50e7, 0xad => 0x50ee, + 0xae => 0x50e5, 0xaf => 0x50d6, 0xb0 => 0x50ed, 0xb1 => 0x50da, + 0xb2 => 0x50d5, 0xb3 => 0x50cf, 0xb4 => 0x50d1, 0xb5 => 0x50f1, + 0xb6 => 0x50ce, 0xb7 => 0x50e9, 0xb8 => 0x5162, 0xb9 => 0x51f3, + 0xba => 0x5283, 0xbb => 0x5282, 0xbc => 0x5331, 0xbd => 0x53ad, + 0xbe => 0x55fe, 0xbf => 0x5600, 0xc0 => 0x561b, 0xc1 => 0x5617, + 0xc2 => 0x55fd, 0xc3 => 0x5614, 0xc4 => 0x5606, 0xc5 => 0x5609, + 0xc6 => 0x560d, 0xc7 => 0x560e, 0xc8 => 0x55f7, 0xc9 => 0x5616, + 0xca => 0x561f, 0xcb => 0x5608, 0xcc => 0x5610, 0xcd => 0x55f6, + 0xce => 0x5718, 0xcf => 0x5716, 0xd0 => 0x5875, 0xd1 => 0x587e, + 0xd2 => 0x5883, 0xd3 => 0x5893, 0xd4 => 0x588a, 0xd5 => 0x5879, + 0xd6 => 0x5885, 0xd7 => 0x587d, 0xd8 => 0x58fd, 0xd9 => 0x5925, + 0xda => 0x5922, 0xdb => 0x5924, 0xdc => 0x596a, 0xdd => 0x5969, + 0xde => 0x5ae1, 0xdf => 0x5ae6, 0xe0 => 0x5ae9, 0xe1 => 0x5ad7, + 0xe2 => 0x5ad6, 0xe3 => 0x5ad8, 0xe4 => 0x5ae3, 0xe5 => 0x5b75, + 0xe6 => 0x5bde, 0xe7 => 0x5be7, 0xe8 => 0x5be1, 0xe9 => 0x5be5, + 0xea => 0x5be6, 0xeb => 0x5be8, 0xec => 0x5be2, 0xed => 0x5be4, + 0xee => 0x5bdf, 0xef => 0x5c0d, 0xf0 => 0x5c62, 0xf1 => 0x5d84, + 0xf2 => 0x5d87, 0xf3 => 0x5e5b, 0xf4 => 0x5e63, 0xf5 => 0x5e55, + 0xf6 => 0x5e57, 0xf7 => 0x5e54, 0xf8 => 0x5ed3, 0xf9 => 0x5ed6, + 0xfa => 0x5f0a, 0xfb => 0x5f46, 0xfc => 0x5f70, 0xfd => 0x5fb9, + 0xfe => 0x6147, + }, + 0xba => { + 0x40 => 0x613f, 0x41 => 0x614b, 0x42 => 0x6177, 0x43 => 0x6162, + 0x44 => 0x6163, 0x45 => 0x615f, 0x46 => 0x615a, 0x47 => 0x6158, + 0x48 => 0x6175, 0x49 => 0x622a, 0x4a => 0x6487, 0x4b => 0x6458, + 0x4c => 0x6454, 0x4d => 0x64a4, 0x4e => 0x6478, 0x4f => 0x645f, + 0x50 => 0x647a, 0x51 => 0x6451, 0x52 => 0x6467, 0x53 => 0x6434, + 0x54 => 0x646d, 0x55 => 0x647b, 0x56 => 0x6572, 0x57 => 0x65a1, + 0x58 => 0x65d7, 0x59 => 0x65d6, 0x5a => 0x66a2, 0x5b => 0x66a8, + 0x5c => 0x669d, 0x5d => 0x699c, 0x5e => 0x69a8, 0x5f => 0x6995, + 0x60 => 0x69c1, 0x61 => 0x69ae, 0x62 => 0x69d3, 0x63 => 0x69cb, + 0x64 => 0x699b, 0x65 => 0x69b7, 0x66 => 0x69bb, 0x67 => 0x69ab, + 0x68 => 0x69b4, 0x69 => 0x69d0, 0x6a => 0x69cd, 0x6b => 0x69ad, + 0x6c => 0x69cc, 0x6d => 0x69a6, 0x6e => 0x69c3, 0x6f => 0x69a3, + 0x70 => 0x6b49, 0x71 => 0x6b4c, 0x72 => 0x6c33, 0x73 => 0x6f33, + 0x74 => 0x6f14, 0x75 => 0x6efe, 0x76 => 0x6f13, 0x77 => 0x6ef4, + 0x78 => 0x6f29, 0x79 => 0x6f3e, 0x7a => 0x6f20, 0x7b => 0x6f2c, + 0x7c => 0x6f0f, 0x7d => 0x6f02, 0x7e => 0x6f22, 0xa1 => 0x6eff, + 0xa2 => 0x6eef, 0xa3 => 0x6f06, 0xa4 => 0x6f31, 0xa5 => 0x6f38, + 0xa6 => 0x6f32, 0xa7 => 0x6f23, 0xa8 => 0x6f15, 0xa9 => 0x6f2b, + 0xaa => 0x6f2f, 0xab => 0x6f88, 0xac => 0x6f2a, 0xad => 0x6eec, + 0xae => 0x6f01, 0xaf => 0x6ef2, 0xb0 => 0x6ecc, 0xb1 => 0x6ef7, + 0xb2 => 0x7194, 0xb3 => 0x7199, 0xb4 => 0x717d, 0xb5 => 0x718a, + 0xb6 => 0x7184, 0xb7 => 0x7192, 0xb8 => 0x723e, 0xb9 => 0x7292, + 0xba => 0x7296, 0xbb => 0x7344, 0xbc => 0x7350, 0xbd => 0x7464, + 0xbe => 0x7463, 0xbf => 0x746a, 0xc0 => 0x7470, 0xc1 => 0x746d, + 0xc2 => 0x7504, 0xc3 => 0x7591, 0xc4 => 0x7627, 0xc5 => 0x760d, + 0xc6 => 0x760b, 0xc7 => 0x7609, 0xc8 => 0x7613, 0xc9 => 0x76e1, + 0xca => 0x76e3, 0xcb => 0x7784, 0xcc => 0x777d, 0xcd => 0x777f, + 0xce => 0x7761, 0xcf => 0x78c1, 0xd0 => 0x789f, 0xd1 => 0x78a7, + 0xd2 => 0x78b3, 0xd3 => 0x78a9, 0xd4 => 0x78a3, 0xd5 => 0x798e, + 0xd6 => 0x798f, 0xd7 => 0x798d, 0xd8 => 0x7a2e, 0xd9 => 0x7a31, + 0xda => 0x7aaa, 0xdb => 0x7aa9, 0xdc => 0x7aed, 0xdd => 0x7aef, + 0xde => 0x7ba1, 0xdf => 0x7b95, 0xe0 => 0x7b8b, 0xe1 => 0x7b75, + 0xe2 => 0x7b97, 0xe3 => 0x7b9d, 0xe4 => 0x7b94, 0xe5 => 0x7b8f, + 0xe6 => 0x7bb8, 0xe7 => 0x7b87, 0xe8 => 0x7b84, 0xe9 => 0x7cb9, + 0xea => 0x7cbd, 0xeb => 0x7cbe, 0xec => 0x7dbb, 0xed => 0x7db0, + 0xee => 0x7d9c, 0xef => 0x7dbd, 0xf0 => 0x7dbe, 0xf1 => 0x7da0, + 0xf2 => 0x7dca, 0xf3 => 0x7db4, 0xf4 => 0x7db2, 0xf5 => 0x7db1, + 0xf6 => 0x7dba, 0xf7 => 0x7da2, 0xf8 => 0x7dbf, 0xf9 => 0x7db5, + 0xfa => 0x7db8, 0xfb => 0x7dad, 0xfc => 0x7dd2, 0xfd => 0x7dc7, + 0xfe => 0x7dac, + }, + 0xbb => { + 0x40 => 0x7f70, 0x41 => 0x7fe0, 0x42 => 0x7fe1, 0x43 => 0x7fdf, + 0x44 => 0x805e, 0x45 => 0x805a, 0x46 => 0x8087, 0x47 => 0x8150, + 0x48 => 0x8180, 0x49 => 0x818f, 0x4a => 0x8188, 0x4b => 0x818a, + 0x4c => 0x817f, 0x4d => 0x8182, 0x4e => 0x81e7, 0x4f => 0x81fa, + 0x50 => 0x8207, 0x51 => 0x8214, 0x52 => 0x821e, 0x53 => 0x824b, + 0x54 => 0x84c9, 0x55 => 0x84bf, 0x56 => 0x84c6, 0x57 => 0x84c4, + 0x58 => 0x8499, 0x59 => 0x849e, 0x5a => 0x84b2, 0x5b => 0x849c, + 0x5c => 0x84cb, 0x5d => 0x84b8, 0x5e => 0x84c0, 0x5f => 0x84d3, + 0x60 => 0x8490, 0x61 => 0x84bc, 0x62 => 0x84d1, 0x63 => 0x84ca, + 0x64 => 0x873f, 0x65 => 0x871c, 0x66 => 0x873b, 0x67 => 0x8722, + 0x68 => 0x8725, 0x69 => 0x8734, 0x6a => 0x8718, 0x6b => 0x8755, + 0x6c => 0x8737, 0x6d => 0x8729, 0x6e => 0x88f3, 0x6f => 0x8902, + 0x70 => 0x88f4, 0x71 => 0x88f9, 0x72 => 0x88f8, 0x73 => 0x88fd, + 0x74 => 0x88e8, 0x75 => 0x891a, 0x76 => 0x88ef, 0x77 => 0x8aa6, + 0x78 => 0x8a8c, 0x79 => 0x8a9e, 0x7a => 0x8aa3, 0x7b => 0x8a8d, + 0x7c => 0x8aa1, 0x7d => 0x8a93, 0x7e => 0x8aa4, 0xa1 => 0x8aaa, + 0xa2 => 0x8aa5, 0xa3 => 0x8aa8, 0xa4 => 0x8a98, 0xa5 => 0x8a91, + 0xa6 => 0x8a9a, 0xa7 => 0x8aa7, 0xa8 => 0x8c6a, 0xa9 => 0x8c8d, + 0xaa => 0x8c8c, 0xab => 0x8cd3, 0xac => 0x8cd1, 0xad => 0x8cd2, + 0xae => 0x8d6b, 0xaf => 0x8d99, 0xb0 => 0x8d95, 0xb1 => 0x8dfc, + 0xb2 => 0x8f14, 0xb3 => 0x8f12, 0xb4 => 0x8f15, 0xb5 => 0x8f13, + 0xb6 => 0x8fa3, 0xb7 => 0x9060, 0xb8 => 0x9058, 0xb9 => 0x905c, + 0xba => 0x9063, 0xbb => 0x9059, 0xbc => 0x905e, 0xbd => 0x9062, + 0xbe => 0x905d, 0xbf => 0x905b, 0xc0 => 0x9119, 0xc1 => 0x9118, + 0xc2 => 0x911e, 0xc3 => 0x9175, 0xc4 => 0x9178, 0xc5 => 0x9177, + 0xc6 => 0x9174, 0xc7 => 0x9278, 0xc8 => 0x9280, 0xc9 => 0x9285, + 0xca => 0x9298, 0xcb => 0x9296, 0xcc => 0x927b, 0xcd => 0x9293, + 0xce => 0x929c, 0xcf => 0x92a8, 0xd0 => 0x927c, 0xd1 => 0x9291, + 0xd2 => 0x95a1, 0xd3 => 0x95a8, 0xd4 => 0x95a9, 0xd5 => 0x95a3, + 0xd6 => 0x95a5, 0xd7 => 0x95a4, 0xd8 => 0x9699, 0xd9 => 0x969c, + 0xda => 0x969b, 0xdb => 0x96cc, 0xdc => 0x96d2, 0xdd => 0x9700, + 0xde => 0x977c, 0xdf => 0x9785, 0xe0 => 0x97f6, 0xe1 => 0x9817, + 0xe2 => 0x9818, 0xe3 => 0x98af, 0xe4 => 0x98b1, 0xe5 => 0x9903, + 0xe6 => 0x9905, 0xe7 => 0x990c, 0xe8 => 0x9909, 0xe9 => 0x99c1, + 0xea => 0x9aaf, 0xeb => 0x9ab0, 0xec => 0x9ae6, 0xed => 0x9b41, + 0xee => 0x9b42, 0xef => 0x9cf4, 0xf0 => 0x9cf6, 0xf1 => 0x9cf3, + 0xf2 => 0x9ebc, 0xf3 => 0x9f3b, 0xf4 => 0x9f4a, 0xf5 => 0x5104, + 0xf6 => 0x5100, 0xf7 => 0x50fb, 0xf8 => 0x50f5, 0xf9 => 0x50f9, + 0xfa => 0x5102, 0xfb => 0x5108, 0xfc => 0x5109, 0xfd => 0x5105, + 0xfe => 0x51dc, + }, + 0xbc => { + 0x40 => 0x5287, 0x41 => 0x5288, 0x42 => 0x5289, 0x43 => 0x528d, + 0x44 => 0x528a, 0x45 => 0x52f0, 0x46 => 0x53b2, 0x47 => 0x562e, + 0x48 => 0x563b, 0x49 => 0x5639, 0x4a => 0x5632, 0x4b => 0x563f, + 0x4c => 0x5634, 0x4d => 0x5629, 0x4e => 0x5653, 0x4f => 0x564e, + 0x50 => 0x5657, 0x51 => 0x5674, 0x52 => 0x5636, 0x53 => 0x562f, + 0x54 => 0x5630, 0x55 => 0x5880, 0x56 => 0x589f, 0x57 => 0x589e, + 0x58 => 0x58b3, 0x59 => 0x589c, 0x5a => 0x58ae, 0x5b => 0x58a9, + 0x5c => 0x58a6, 0x5d => 0x596d, 0x5e => 0x5b09, 0x5f => 0x5afb, + 0x60 => 0x5b0b, 0x61 => 0x5af5, 0x62 => 0x5b0c, 0x63 => 0x5b08, + 0x64 => 0x5bee, 0x65 => 0x5bec, 0x66 => 0x5be9, 0x67 => 0x5beb, + 0x68 => 0x5c64, 0x69 => 0x5c65, 0x6a => 0x5d9d, 0x6b => 0x5d94, + 0x6c => 0x5e62, 0x6d => 0x5e5f, 0x6e => 0x5e61, 0x6f => 0x5ee2, + 0x70 => 0x5eda, 0x71 => 0x5edf, 0x72 => 0x5edd, 0x73 => 0x5ee3, + 0x74 => 0x5ee0, 0x75 => 0x5f48, 0x76 => 0x5f71, 0x77 => 0x5fb7, + 0x78 => 0x5fb5, 0x79 => 0x6176, 0x7a => 0x6167, 0x7b => 0x616e, + 0x7c => 0x615d, 0x7d => 0x6155, 0x7e => 0x6182, 0xa1 => 0x617c, + 0xa2 => 0x6170, 0xa3 => 0x616b, 0xa4 => 0x617e, 0xa5 => 0x61a7, + 0xa6 => 0x6190, 0xa7 => 0x61ab, 0xa8 => 0x618e, 0xa9 => 0x61ac, + 0xaa => 0x619a, 0xab => 0x61a4, 0xac => 0x6194, 0xad => 0x61ae, + 0xae => 0x622e, 0xaf => 0x6469, 0xb0 => 0x646f, 0xb1 => 0x6479, + 0xb2 => 0x649e, 0xb3 => 0x64b2, 0xb4 => 0x6488, 0xb5 => 0x6490, + 0xb6 => 0x64b0, 0xb7 => 0x64a5, 0xb8 => 0x6493, 0xb9 => 0x6495, + 0xba => 0x64a9, 0xbb => 0x6492, 0xbc => 0x64ae, 0xbd => 0x64ad, + 0xbe => 0x64ab, 0xbf => 0x649a, 0xc0 => 0x64ac, 0xc1 => 0x6499, + 0xc2 => 0x64a2, 0xc3 => 0x64b3, 0xc4 => 0x6575, 0xc5 => 0x6577, + 0xc6 => 0x6578, 0xc7 => 0x66ae, 0xc8 => 0x66ab, 0xc9 => 0x66b4, + 0xca => 0x66b1, 0xcb => 0x6a23, 0xcc => 0x6a1f, 0xcd => 0x69e8, + 0xce => 0x6a01, 0xcf => 0x6a1e, 0xd0 => 0x6a19, 0xd1 => 0x69fd, + 0xd2 => 0x6a21, 0xd3 => 0x6a13, 0xd4 => 0x6a0a, 0xd5 => 0x69f3, + 0xd6 => 0x6a02, 0xd7 => 0x6a05, 0xd8 => 0x69ed, 0xd9 => 0x6a11, + 0xda => 0x6b50, 0xdb => 0x6b4e, 0xdc => 0x6ba4, 0xdd => 0x6bc5, + 0xde => 0x6bc6, 0xdf => 0x6f3f, 0xe0 => 0x6f7c, 0xe1 => 0x6f84, + 0xe2 => 0x6f51, 0xe3 => 0x6f66, 0xe4 => 0x6f54, 0xe5 => 0x6f86, + 0xe6 => 0x6f6d, 0xe7 => 0x6f5b, 0xe8 => 0x6f78, 0xe9 => 0x6f6e, + 0xea => 0x6f8e, 0xeb => 0x6f7a, 0xec => 0x6f70, 0xed => 0x6f64, + 0xee => 0x6f97, 0xef => 0x6f58, 0xf0 => 0x6ed5, 0xf1 => 0x6f6f, + 0xf2 => 0x6f60, 0xf3 => 0x6f5f, 0xf4 => 0x719f, 0xf5 => 0x71ac, + 0xf6 => 0x71b1, 0xf7 => 0x71a8, 0xf8 => 0x7256, 0xf9 => 0x729b, + 0xfa => 0x734e, 0xfb => 0x7357, 0xfc => 0x7469, 0xfd => 0x748b, + 0xfe => 0x7483, + }, + 0xbd => { + 0x40 => 0x747e, 0x41 => 0x7480, 0x42 => 0x757f, 0x43 => 0x7620, + 0x44 => 0x7629, 0x45 => 0x761f, 0x46 => 0x7624, 0x47 => 0x7626, + 0x48 => 0x7621, 0x49 => 0x7622, 0x4a => 0x769a, 0x4b => 0x76ba, + 0x4c => 0x76e4, 0x4d => 0x778e, 0x4e => 0x7787, 0x4f => 0x778c, + 0x50 => 0x7791, 0x51 => 0x778b, 0x52 => 0x78cb, 0x53 => 0x78c5, + 0x54 => 0x78ba, 0x55 => 0x78ca, 0x56 => 0x78be, 0x57 => 0x78d5, + 0x58 => 0x78bc, 0x59 => 0x78d0, 0x5a => 0x7a3f, 0x5b => 0x7a3c, + 0x5c => 0x7a40, 0x5d => 0x7a3d, 0x5e => 0x7a37, 0x5f => 0x7a3b, + 0x60 => 0x7aaf, 0x61 => 0x7aae, 0x62 => 0x7bad, 0x63 => 0x7bb1, + 0x64 => 0x7bc4, 0x65 => 0x7bb4, 0x66 => 0x7bc6, 0x67 => 0x7bc7, + 0x68 => 0x7bc1, 0x69 => 0x7ba0, 0x6a => 0x7bcc, 0x6b => 0x7cca, + 0x6c => 0x7de0, 0x6d => 0x7df4, 0x6e => 0x7def, 0x6f => 0x7dfb, + 0x70 => 0x7dd8, 0x71 => 0x7dec, 0x72 => 0x7ddd, 0x73 => 0x7de8, + 0x74 => 0x7de3, 0x75 => 0x7dda, 0x76 => 0x7dde, 0x77 => 0x7de9, + 0x78 => 0x7d9e, 0x79 => 0x7dd9, 0x7a => 0x7df2, 0x7b => 0x7df9, + 0x7c => 0x7f75, 0x7d => 0x7f77, 0x7e => 0x7faf, 0xa1 => 0x7fe9, + 0xa2 => 0x8026, 0xa3 => 0x819b, 0xa4 => 0x819c, 0xa5 => 0x819d, + 0xa6 => 0x81a0, 0xa7 => 0x819a, 0xa8 => 0x8198, 0xa9 => 0x8517, + 0xaa => 0x853d, 0xab => 0x851a, 0xac => 0x84ee, 0xad => 0x852c, + 0xae => 0x852d, 0xaf => 0x8513, 0xb0 => 0x8511, 0xb1 => 0x8523, + 0xb2 => 0x8521, 0xb3 => 0x8514, 0xb4 => 0x84ec, 0xb5 => 0x8525, + 0xb6 => 0x84ff, 0xb7 => 0x8506, 0xb8 => 0x8782, 0xb9 => 0x8774, + 0xba => 0x8776, 0xbb => 0x8760, 0xbc => 0x8766, 0xbd => 0x8778, + 0xbe => 0x8768, 0xbf => 0x8759, 0xc0 => 0x8757, 0xc1 => 0x874c, + 0xc2 => 0x8753, 0xc3 => 0x885b, 0xc4 => 0x885d, 0xc5 => 0x8910, + 0xc6 => 0x8907, 0xc7 => 0x8912, 0xc8 => 0x8913, 0xc9 => 0x8915, + 0xca => 0x890a, 0xcb => 0x8abc, 0xcc => 0x8ad2, 0xcd => 0x8ac7, + 0xce => 0x8ac4, 0xcf => 0x8a95, 0xd0 => 0x8acb, 0xd1 => 0x8af8, + 0xd2 => 0x8ab2, 0xd3 => 0x8ac9, 0xd4 => 0x8ac2, 0xd5 => 0x8abf, + 0xd6 => 0x8ab0, 0xd7 => 0x8ad6, 0xd8 => 0x8acd, 0xd9 => 0x8ab6, + 0xda => 0x8ab9, 0xdb => 0x8adb, 0xdc => 0x8c4c, 0xdd => 0x8c4e, + 0xde => 0x8c6c, 0xdf => 0x8ce0, 0xe0 => 0x8cde, 0xe1 => 0x8ce6, + 0xe2 => 0x8ce4, 0xe3 => 0x8cec, 0xe4 => 0x8ced, 0xe5 => 0x8ce2, + 0xe6 => 0x8ce3, 0xe7 => 0x8cdc, 0xe8 => 0x8cea, 0xe9 => 0x8ce1, + 0xea => 0x8d6d, 0xeb => 0x8d9f, 0xec => 0x8da3, 0xed => 0x8e2b, + 0xee => 0x8e10, 0xef => 0x8e1d, 0xf0 => 0x8e22, 0xf1 => 0x8e0f, + 0xf2 => 0x8e29, 0xf3 => 0x8e1f, 0xf4 => 0x8e21, 0xf5 => 0x8e1e, + 0xf6 => 0x8eba, 0xf7 => 0x8f1d, 0xf8 => 0x8f1b, 0xf9 => 0x8f1f, + 0xfa => 0x8f29, 0xfb => 0x8f26, 0xfc => 0x8f2a, 0xfd => 0x8f1c, + 0xfe => 0x8f1e, + }, + 0xbe => { + 0x40 => 0x8f25, 0x41 => 0x9069, 0x42 => 0x906e, 0x43 => 0x9068, + 0x44 => 0x906d, 0x45 => 0x9077, 0x46 => 0x9130, 0x47 => 0x912d, + 0x48 => 0x9127, 0x49 => 0x9131, 0x4a => 0x9187, 0x4b => 0x9189, + 0x4c => 0x918b, 0x4d => 0x9183, 0x4e => 0x92c5, 0x4f => 0x92bb, + 0x50 => 0x92b7, 0x51 => 0x92ea, 0x52 => 0x92ac, 0x53 => 0x92e4, + 0x54 => 0x92c1, 0x55 => 0x92b3, 0x56 => 0x92bc, 0x57 => 0x92d2, + 0x58 => 0x92c7, 0x59 => 0x92f0, 0x5a => 0x92b2, 0x5b => 0x95ad, + 0x5c => 0x95b1, 0x5d => 0x9704, 0x5e => 0x9706, 0x5f => 0x9707, + 0x60 => 0x9709, 0x61 => 0x9760, 0x62 => 0x978d, 0x63 => 0x978b, + 0x64 => 0x978f, 0x65 => 0x9821, 0x66 => 0x982b, 0x67 => 0x981c, + 0x68 => 0x98b3, 0x69 => 0x990a, 0x6a => 0x9913, 0x6b => 0x9912, + 0x6c => 0x9918, 0x6d => 0x99dd, 0x6e => 0x99d0, 0x6f => 0x99df, + 0x70 => 0x99db, 0x71 => 0x99d1, 0x72 => 0x99d5, 0x73 => 0x99d2, + 0x74 => 0x99d9, 0x75 => 0x9ab7, 0x76 => 0x9aee, 0x77 => 0x9aef, + 0x78 => 0x9b27, 0x79 => 0x9b45, 0x7a => 0x9b44, 0x7b => 0x9b77, + 0x7c => 0x9b6f, 0x7d => 0x9d06, 0x7e => 0x9d09, 0xa1 => 0x9d03, + 0xa2 => 0x9ea9, 0xa3 => 0x9ebe, 0xa4 => 0x9ece, 0xa5 => 0x58a8, + 0xa6 => 0x9f52, 0xa7 => 0x5112, 0xa8 => 0x5118, 0xa9 => 0x5114, + 0xaa => 0x5110, 0xab => 0x5115, 0xac => 0x5180, 0xad => 0x51aa, + 0xae => 0x51dd, 0xaf => 0x5291, 0xb0 => 0x5293, 0xb1 => 0x52f3, + 0xb2 => 0x5659, 0xb3 => 0x566b, 0xb4 => 0x5679, 0xb5 => 0x5669, + 0xb6 => 0x5664, 0xb7 => 0x5678, 0xb8 => 0x566a, 0xb9 => 0x5668, + 0xba => 0x5665, 0xbb => 0x5671, 0xbc => 0x566f, 0xbd => 0x566c, + 0xbe => 0x5662, 0xbf => 0x5676, 0xc0 => 0x58c1, 0xc1 => 0x58be, + 0xc2 => 0x58c7, 0xc3 => 0x58c5, 0xc4 => 0x596e, 0xc5 => 0x5b1d, + 0xc6 => 0x5b34, 0xc7 => 0x5b78, 0xc8 => 0x5bf0, 0xc9 => 0x5c0e, + 0xca => 0x5f4a, 0xcb => 0x61b2, 0xcc => 0x6191, 0xcd => 0x61a9, + 0xce => 0x618a, 0xcf => 0x61cd, 0xd0 => 0x61b6, 0xd1 => 0x61be, + 0xd2 => 0x61ca, 0xd3 => 0x61c8, 0xd4 => 0x6230, 0xd5 => 0x64c5, + 0xd6 => 0x64c1, 0xd7 => 0x64cb, 0xd8 => 0x64bb, 0xd9 => 0x64bc, + 0xda => 0x64da, 0xdb => 0x64c4, 0xdc => 0x64c7, 0xdd => 0x64c2, + 0xde => 0x64cd, 0xdf => 0x64bf, 0xe0 => 0x64d2, 0xe1 => 0x64d4, + 0xe2 => 0x64be, 0xe3 => 0x6574, 0xe4 => 0x66c6, 0xe5 => 0x66c9, + 0xe6 => 0x66b9, 0xe7 => 0x66c4, 0xe8 => 0x66c7, 0xe9 => 0x66b8, + 0xea => 0x6a3d, 0xeb => 0x6a38, 0xec => 0x6a3a, 0xed => 0x6a59, + 0xee => 0x6a6b, 0xef => 0x6a58, 0xf0 => 0x6a39, 0xf1 => 0x6a44, + 0xf2 => 0x6a62, 0xf3 => 0x6a61, 0xf4 => 0x6a4b, 0xf5 => 0x6a47, + 0xf6 => 0x6a35, 0xf7 => 0x6a5f, 0xf8 => 0x6a48, 0xf9 => 0x6b59, + 0xfa => 0x6b77, 0xfb => 0x6c05, 0xfc => 0x6fc2, 0xfd => 0x6fb1, + 0xfe => 0x6fa1, + }, + 0xbf => { + 0x40 => 0x6fc3, 0x41 => 0x6fa4, 0x42 => 0x6fc1, 0x43 => 0x6fa7, + 0x44 => 0x6fb3, 0x45 => 0x6fc0, 0x46 => 0x6fb9, 0x47 => 0x6fb6, + 0x48 => 0x6fa6, 0x49 => 0x6fa0, 0x4a => 0x6fb4, 0x4b => 0x71be, + 0x4c => 0x71c9, 0x4d => 0x71d0, 0x4e => 0x71d2, 0x4f => 0x71c8, + 0x50 => 0x71d5, 0x51 => 0x71b9, 0x52 => 0x71ce, 0x53 => 0x71d9, + 0x54 => 0x71dc, 0x55 => 0x71c3, 0x56 => 0x71c4, 0x57 => 0x7368, + 0x58 => 0x749c, 0x59 => 0x74a3, 0x5a => 0x7498, 0x5b => 0x749f, + 0x5c => 0x749e, 0x5d => 0x74e2, 0x5e => 0x750c, 0x5f => 0x750d, + 0x60 => 0x7634, 0x61 => 0x7638, 0x62 => 0x763a, 0x63 => 0x76e7, + 0x64 => 0x76e5, 0x65 => 0x77a0, 0x66 => 0x779e, 0x67 => 0x779f, + 0x68 => 0x77a5, 0x69 => 0x78e8, 0x6a => 0x78da, 0x6b => 0x78ec, + 0x6c => 0x78e7, 0x6d => 0x79a6, 0x6e => 0x7a4d, 0x6f => 0x7a4e, + 0x70 => 0x7a46, 0x71 => 0x7a4c, 0x72 => 0x7a4b, 0x73 => 0x7aba, + 0x74 => 0x7bd9, 0x75 => 0x7c11, 0x76 => 0x7bc9, 0x77 => 0x7be4, + 0x78 => 0x7bdb, 0x79 => 0x7be1, 0x7a => 0x7be9, 0x7b => 0x7be6, + 0x7c => 0x7cd5, 0x7d => 0x7cd6, 0x7e => 0x7e0a, 0xa1 => 0x7e11, + 0xa2 => 0x7e08, 0xa3 => 0x7e1b, 0xa4 => 0x7e23, 0xa5 => 0x7e1e, + 0xa6 => 0x7e1d, 0xa7 => 0x7e09, 0xa8 => 0x7e10, 0xa9 => 0x7f79, + 0xaa => 0x7fb2, 0xab => 0x7ff0, 0xac => 0x7ff1, 0xad => 0x7fee, + 0xae => 0x8028, 0xaf => 0x81b3, 0xb0 => 0x81a9, 0xb1 => 0x81a8, + 0xb2 => 0x81fb, 0xb3 => 0x8208, 0xb4 => 0x8258, 0xb5 => 0x8259, + 0xb6 => 0x854a, 0xb7 => 0x8559, 0xb8 => 0x8548, 0xb9 => 0x8568, + 0xba => 0x8569, 0xbb => 0x8543, 0xbc => 0x8549, 0xbd => 0x856d, + 0xbe => 0x856a, 0xbf => 0x855e, 0xc0 => 0x8783, 0xc1 => 0x879f, + 0xc2 => 0x879e, 0xc3 => 0x87a2, 0xc4 => 0x878d, 0xc5 => 0x8861, + 0xc6 => 0x892a, 0xc7 => 0x8932, 0xc8 => 0x8925, 0xc9 => 0x892b, + 0xca => 0x8921, 0xcb => 0x89aa, 0xcc => 0x89a6, 0xcd => 0x8ae6, + 0xce => 0x8afa, 0xcf => 0x8aeb, 0xd0 => 0x8af1, 0xd1 => 0x8b00, + 0xd2 => 0x8adc, 0xd3 => 0x8ae7, 0xd4 => 0x8aee, 0xd5 => 0x8afe, + 0xd6 => 0x8b01, 0xd7 => 0x8b02, 0xd8 => 0x8af7, 0xd9 => 0x8aed, + 0xda => 0x8af3, 0xdb => 0x8af6, 0xdc => 0x8afc, 0xdd => 0x8c6b, + 0xde => 0x8c6d, 0xdf => 0x8c93, 0xe0 => 0x8cf4, 0xe1 => 0x8e44, + 0xe2 => 0x8e31, 0xe3 => 0x8e34, 0xe4 => 0x8e42, 0xe5 => 0x8e39, + 0xe6 => 0x8e35, 0xe7 => 0x8f3b, 0xe8 => 0x8f2f, 0xe9 => 0x8f38, + 0xea => 0x8f33, 0xeb => 0x8fa8, 0xec => 0x8fa6, 0xed => 0x9075, + 0xee => 0x9074, 0xef => 0x9078, 0xf0 => 0x9072, 0xf1 => 0x907c, + 0xf2 => 0x907a, 0xf3 => 0x9134, 0xf4 => 0x9192, 0xf5 => 0x9320, + 0xf6 => 0x9336, 0xf7 => 0x92f8, 0xf8 => 0x9333, 0xf9 => 0x932f, + 0xfa => 0x9322, 0xfb => 0x92fc, 0xfc => 0x932b, 0xfd => 0x9304, + 0xfe => 0x931a, + }, + 0xc0 => { + 0x40 => 0x9310, 0x41 => 0x9326, 0x42 => 0x9321, 0x43 => 0x9315, + 0x44 => 0x932e, 0x45 => 0x9319, 0x46 => 0x95bb, 0x47 => 0x96a7, + 0x48 => 0x96a8, 0x49 => 0x96aa, 0x4a => 0x96d5, 0x4b => 0x970e, + 0x4c => 0x9711, 0x4d => 0x9716, 0x4e => 0x970d, 0x4f => 0x9713, + 0x50 => 0x970f, 0x51 => 0x975b, 0x52 => 0x975c, 0x53 => 0x9766, + 0x54 => 0x9798, 0x55 => 0x9830, 0x56 => 0x9838, 0x57 => 0x983b, + 0x58 => 0x9837, 0x59 => 0x982d, 0x5a => 0x9839, 0x5b => 0x9824, + 0x5c => 0x9910, 0x5d => 0x9928, 0x5e => 0x991e, 0x5f => 0x991b, + 0x60 => 0x9921, 0x61 => 0x991a, 0x62 => 0x99ed, 0x63 => 0x99e2, + 0x64 => 0x99f1, 0x65 => 0x9ab8, 0x66 => 0x9abc, 0x67 => 0x9afb, + 0x68 => 0x9aed, 0x69 => 0x9b28, 0x6a => 0x9b91, 0x6b => 0x9d15, + 0x6c => 0x9d23, 0x6d => 0x9d26, 0x6e => 0x9d28, 0x6f => 0x9d12, + 0x70 => 0x9d1b, 0x71 => 0x9ed8, 0x72 => 0x9ed4, 0x73 => 0x9f8d, + 0x74 => 0x9f9c, 0x75 => 0x512a, 0x76 => 0x511f, 0x77 => 0x5121, + 0x78 => 0x5132, 0x79 => 0x52f5, 0x7a => 0x568e, 0x7b => 0x5680, + 0x7c => 0x5690, 0x7d => 0x5685, 0x7e => 0x5687, 0xa1 => 0x568f, + 0xa2 => 0x58d5, 0xa3 => 0x58d3, 0xa4 => 0x58d1, 0xa5 => 0x58ce, + 0xa6 => 0x5b30, 0xa7 => 0x5b2a, 0xa8 => 0x5b24, 0xa9 => 0x5b7a, + 0xaa => 0x5c37, 0xab => 0x5c68, 0xac => 0x5dbc, 0xad => 0x5dba, + 0xae => 0x5dbd, 0xaf => 0x5db8, 0xb0 => 0x5e6b, 0xb1 => 0x5f4c, + 0xb2 => 0x5fbd, 0xb3 => 0x61c9, 0xb4 => 0x61c2, 0xb5 => 0x61c7, + 0xb6 => 0x61e6, 0xb7 => 0x61cb, 0xb8 => 0x6232, 0xb9 => 0x6234, + 0xba => 0x64ce, 0xbb => 0x64ca, 0xbc => 0x64d8, 0xbd => 0x64e0, + 0xbe => 0x64f0, 0xbf => 0x64e6, 0xc0 => 0x64ec, 0xc1 => 0x64f1, + 0xc2 => 0x64e2, 0xc3 => 0x64ed, 0xc4 => 0x6582, 0xc5 => 0x6583, + 0xc6 => 0x66d9, 0xc7 => 0x66d6, 0xc8 => 0x6a80, 0xc9 => 0x6a94, + 0xca => 0x6a84, 0xcb => 0x6aa2, 0xcc => 0x6a9c, 0xcd => 0x6adb, + 0xce => 0x6aa3, 0xcf => 0x6a7e, 0xd0 => 0x6a97, 0xd1 => 0x6a90, + 0xd2 => 0x6aa0, 0xd3 => 0x6b5c, 0xd4 => 0x6bae, 0xd5 => 0x6bda, + 0xd6 => 0x6c08, 0xd7 => 0x6fd8, 0xd8 => 0x6ff1, 0xd9 => 0x6fdf, + 0xda => 0x6fe0, 0xdb => 0x6fdb, 0xdc => 0x6fe4, 0xdd => 0x6feb, + 0xde => 0x6fef, 0xdf => 0x6f80, 0xe0 => 0x6fec, 0xe1 => 0x6fe1, + 0xe2 => 0x6fe9, 0xe3 => 0x6fd5, 0xe4 => 0x6fee, 0xe5 => 0x6ff0, + 0xe6 => 0x71e7, 0xe7 => 0x71df, 0xe8 => 0x71ee, 0xe9 => 0x71e6, + 0xea => 0x71e5, 0xeb => 0x71ed, 0xec => 0x71ec, 0xed => 0x71f4, + 0xee => 0x71e0, 0xef => 0x7235, 0xf0 => 0x7246, 0xf1 => 0x7370, + 0xf2 => 0x7372, 0xf3 => 0x74a9, 0xf4 => 0x74b0, 0xf5 => 0x74a6, + 0xf6 => 0x74a8, 0xf7 => 0x7646, 0xf8 => 0x7642, 0xf9 => 0x764c, + 0xfa => 0x76ea, 0xfb => 0x77b3, 0xfc => 0x77aa, 0xfd => 0x77b0, + 0xfe => 0x77ac, + }, + 0xc1 => { + 0x40 => 0x77a7, 0x41 => 0x77ad, 0x42 => 0x77ef, 0x43 => 0x78f7, + 0x44 => 0x78fa, 0x45 => 0x78f4, 0x46 => 0x78ef, 0x47 => 0x7901, + 0x48 => 0x79a7, 0x49 => 0x79aa, 0x4a => 0x7a57, 0x4b => 0x7abf, + 0x4c => 0x7c07, 0x4d => 0x7c0d, 0x4e => 0x7bfe, 0x4f => 0x7bf7, + 0x50 => 0x7c0c, 0x51 => 0x7be0, 0x52 => 0x7ce0, 0x53 => 0x7cdc, + 0x54 => 0x7cde, 0x55 => 0x7ce2, 0x56 => 0x7cdf, 0x57 => 0x7cd9, + 0x58 => 0x7cdd, 0x59 => 0x7e2e, 0x5a => 0x7e3e, 0x5b => 0x7e46, + 0x5c => 0x7e37, 0x5d => 0x7e32, 0x5e => 0x7e43, 0x5f => 0x7e2b, + 0x60 => 0x7e3d, 0x61 => 0x7e31, 0x62 => 0x7e45, 0x63 => 0x7e41, + 0x64 => 0x7e34, 0x65 => 0x7e39, 0x66 => 0x7e48, 0x67 => 0x7e35, + 0x68 => 0x7e3f, 0x69 => 0x7e2f, 0x6a => 0x7f44, 0x6b => 0x7ff3, + 0x6c => 0x7ffc, 0x6d => 0x8071, 0x6e => 0x8072, 0x6f => 0x8070, + 0x70 => 0x806f, 0x71 => 0x8073, 0x72 => 0x81c6, 0x73 => 0x81c3, + 0x74 => 0x81ba, 0x75 => 0x81c2, 0x76 => 0x81c0, 0x77 => 0x81bf, + 0x78 => 0x81bd, 0x79 => 0x81c9, 0x7a => 0x81be, 0x7b => 0x81e8, + 0x7c => 0x8209, 0x7d => 0x8271, 0x7e => 0x85aa, 0xa1 => 0x8584, + 0xa2 => 0x857e, 0xa3 => 0x859c, 0xa4 => 0x8591, 0xa5 => 0x8594, + 0xa6 => 0x85af, 0xa7 => 0x859b, 0xa8 => 0x8587, 0xa9 => 0x85a8, + 0xaa => 0x858a, 0xab => 0x8667, 0xac => 0x87c0, 0xad => 0x87d1, + 0xae => 0x87b3, 0xaf => 0x87d2, 0xb0 => 0x87c6, 0xb1 => 0x87ab, + 0xb2 => 0x87bb, 0xb3 => 0x87ba, 0xb4 => 0x87c8, 0xb5 => 0x87cb, + 0xb6 => 0x893b, 0xb7 => 0x8936, 0xb8 => 0x8944, 0xb9 => 0x8938, + 0xba => 0x893d, 0xbb => 0x89ac, 0xbc => 0x8b0e, 0xbd => 0x8b17, + 0xbe => 0x8b19, 0xbf => 0x8b1b, 0xc0 => 0x8b0a, 0xc1 => 0x8b20, + 0xc2 => 0x8b1d, 0xc3 => 0x8b04, 0xc4 => 0x8b10, 0xc5 => 0x8c41, + 0xc6 => 0x8c3f, 0xc7 => 0x8c73, 0xc8 => 0x8cfa, 0xc9 => 0x8cfd, + 0xca => 0x8cfc, 0xcb => 0x8cf8, 0xcc => 0x8cfb, 0xcd => 0x8da8, + 0xce => 0x8e49, 0xcf => 0x8e4b, 0xd0 => 0x8e48, 0xd1 => 0x8e4a, + 0xd2 => 0x8f44, 0xd3 => 0x8f3e, 0xd4 => 0x8f42, 0xd5 => 0x8f45, + 0xd6 => 0x8f3f, 0xd7 => 0x907f, 0xd8 => 0x907d, 0xd9 => 0x9084, + 0xda => 0x9081, 0xdb => 0x9082, 0xdc => 0x9080, 0xdd => 0x9139, + 0xde => 0x91a3, 0xdf => 0x919e, 0xe0 => 0x919c, 0xe1 => 0x934d, + 0xe2 => 0x9382, 0xe3 => 0x9328, 0xe4 => 0x9375, 0xe5 => 0x934a, + 0xe6 => 0x9365, 0xe7 => 0x934b, 0xe8 => 0x9318, 0xe9 => 0x937e, + 0xea => 0x936c, 0xeb => 0x935b, 0xec => 0x9370, 0xed => 0x935a, + 0xee => 0x9354, 0xef => 0x95ca, 0xf0 => 0x95cb, 0xf1 => 0x95cc, + 0xf2 => 0x95c8, 0xf3 => 0x95c6, 0xf4 => 0x96b1, 0xf5 => 0x96b8, + 0xf6 => 0x96d6, 0xf7 => 0x971c, 0xf8 => 0x971e, 0xf9 => 0x97a0, + 0xfa => 0x97d3, 0xfb => 0x9846, 0xfc => 0x98b6, 0xfd => 0x9935, + 0xfe => 0x9a01, + }, + 0xc2 => { + 0x40 => 0x99ff, 0x41 => 0x9bae, 0x42 => 0x9bab, 0x43 => 0x9baa, + 0x44 => 0x9bad, 0x45 => 0x9d3b, 0x46 => 0x9d3f, 0x47 => 0x9e8b, + 0x48 => 0x9ecf, 0x49 => 0x9ede, 0x4a => 0x9edc, 0x4b => 0x9edd, + 0x4c => 0x9edb, 0x4d => 0x9f3e, 0x4e => 0x9f4b, 0x4f => 0x53e2, + 0x50 => 0x5695, 0x51 => 0x56ae, 0x52 => 0x58d9, 0x53 => 0x58d8, + 0x54 => 0x5b38, 0x55 => 0x5f5d, 0x56 => 0x61e3, 0x57 => 0x6233, + 0x58 => 0x64f4, 0x59 => 0x64f2, 0x5a => 0x64fe, 0x5b => 0x6506, + 0x5c => 0x64fa, 0x5d => 0x64fb, 0x5e => 0x64f7, 0x5f => 0x65b7, + 0x60 => 0x66dc, 0x61 => 0x6726, 0x62 => 0x6ab3, 0x63 => 0x6aac, + 0x64 => 0x6ac3, 0x65 => 0x6abb, 0x66 => 0x6ab8, 0x67 => 0x6ac2, + 0x68 => 0x6aae, 0x69 => 0x6aaf, 0x6a => 0x6b5f, 0x6b => 0x6b78, + 0x6c => 0x6baf, 0x6d => 0x7009, 0x6e => 0x700b, 0x6f => 0x6ffe, + 0x70 => 0x7006, 0x71 => 0x6ffa, 0x72 => 0x7011, 0x73 => 0x700f, + 0x74 => 0x71fb, 0x75 => 0x71fc, 0x76 => 0x71fe, 0x77 => 0x71f8, + 0x78 => 0x7377, 0x79 => 0x7375, 0x7a => 0x74a7, 0x7b => 0x74bf, + 0x7c => 0x7515, 0x7d => 0x7656, 0x7e => 0x7658, 0xa1 => 0x7652, + 0xa2 => 0x77bd, 0xa3 => 0x77bf, 0xa4 => 0x77bb, 0xa5 => 0x77bc, + 0xa6 => 0x790e, 0xa7 => 0x79ae, 0xa8 => 0x7a61, 0xa9 => 0x7a62, + 0xaa => 0x7a60, 0xab => 0x7ac4, 0xac => 0x7ac5, 0xad => 0x7c2b, + 0xae => 0x7c27, 0xaf => 0x7c2a, 0xb0 => 0x7c1e, 0xb1 => 0x7c23, + 0xb2 => 0x7c21, 0xb3 => 0x7ce7, 0xb4 => 0x7e54, 0xb5 => 0x7e55, + 0xb6 => 0x7e5e, 0xb7 => 0x7e5a, 0xb8 => 0x7e61, 0xb9 => 0x7e52, + 0xba => 0x7e59, 0xbb => 0x7f48, 0xbc => 0x7ff9, 0xbd => 0x7ffb, + 0xbe => 0x8077, 0xbf => 0x8076, 0xc0 => 0x81cd, 0xc1 => 0x81cf, + 0xc2 => 0x820a, 0xc3 => 0x85cf, 0xc4 => 0x85a9, 0xc5 => 0x85cd, + 0xc6 => 0x85d0, 0xc7 => 0x85c9, 0xc8 => 0x85b0, 0xc9 => 0x85ba, + 0xca => 0x85b9, 0xcb => 0x85a6, 0xcc => 0x87ef, 0xcd => 0x87ec, + 0xce => 0x87f2, 0xcf => 0x87e0, 0xd0 => 0x8986, 0xd1 => 0x89b2, + 0xd2 => 0x89f4, 0xd3 => 0x8b28, 0xd4 => 0x8b39, 0xd5 => 0x8b2c, + 0xd6 => 0x8b2b, 0xd7 => 0x8c50, 0xd8 => 0x8d05, 0xd9 => 0x8e59, + 0xda => 0x8e63, 0xdb => 0x8e66, 0xdc => 0x8e64, 0xdd => 0x8e5f, + 0xde => 0x8e55, 0xdf => 0x8ec0, 0xe0 => 0x8f49, 0xe1 => 0x8f4d, + 0xe2 => 0x9087, 0xe3 => 0x9083, 0xe4 => 0x9088, 0xe5 => 0x91ab, + 0xe6 => 0x91ac, 0xe7 => 0x91d0, 0xe8 => 0x9394, 0xe9 => 0x938a, + 0xea => 0x9396, 0xeb => 0x93a2, 0xec => 0x93b3, 0xed => 0x93ae, + 0xee => 0x93ac, 0xef => 0x93b0, 0xf0 => 0x9398, 0xf1 => 0x939a, + 0xf2 => 0x9397, 0xf3 => 0x95d4, 0xf4 => 0x95d6, 0xf5 => 0x95d0, + 0xf6 => 0x95d5, 0xf7 => 0x96e2, 0xf8 => 0x96dc, 0xf9 => 0x96d9, + 0xfa => 0x96db, 0xfb => 0x96de, 0xfc => 0x9724, 0xfd => 0x97a3, + 0xfe => 0x97a6, + }, + 0xc3 => { + 0x40 => 0x97ad, 0x41 => 0x97f9, 0x42 => 0x984d, 0x43 => 0x984f, + 0x44 => 0x984c, 0x45 => 0x984e, 0x46 => 0x9853, 0x47 => 0x98ba, + 0x48 => 0x993e, 0x49 => 0x993f, 0x4a => 0x993d, 0x4b => 0x992e, + 0x4c => 0x99a5, 0x4d => 0x9a0e, 0x4e => 0x9ac1, 0x4f => 0x9b03, + 0x50 => 0x9b06, 0x51 => 0x9b4f, 0x52 => 0x9b4e, 0x53 => 0x9b4d, + 0x54 => 0x9bca, 0x55 => 0x9bc9, 0x56 => 0x9bfd, 0x57 => 0x9bc8, + 0x58 => 0x9bc0, 0x59 => 0x9d51, 0x5a => 0x9d5d, 0x5b => 0x9d60, + 0x5c => 0x9ee0, 0x5d => 0x9f15, 0x5e => 0x9f2c, 0x5f => 0x5133, + 0x60 => 0x56a5, 0x61 => 0x58de, 0x62 => 0x58df, 0x63 => 0x58e2, + 0x64 => 0x5bf5, 0x65 => 0x9f90, 0x66 => 0x5eec, 0x67 => 0x61f2, + 0x68 => 0x61f7, 0x69 => 0x61f6, 0x6a => 0x61f5, 0x6b => 0x6500, + 0x6c => 0x650f, 0x6d => 0x66e0, 0x6e => 0x66dd, 0x6f => 0x6ae5, + 0x70 => 0x6add, 0x71 => 0x6ada, 0x72 => 0x6ad3, 0x73 => 0x701b, + 0x74 => 0x701f, 0x75 => 0x7028, 0x76 => 0x701a, 0x77 => 0x701d, + 0x78 => 0x7015, 0x79 => 0x7018, 0x7a => 0x7206, 0x7b => 0x720d, + 0x7c => 0x7258, 0x7d => 0x72a2, 0x7e => 0x7378, 0xa1 => 0x737a, + 0xa2 => 0x74bd, 0xa3 => 0x74ca, 0xa4 => 0x74e3, 0xa5 => 0x7587, + 0xa6 => 0x7586, 0xa7 => 0x765f, 0xa8 => 0x7661, 0xa9 => 0x77c7, + 0xaa => 0x7919, 0xab => 0x79b1, 0xac => 0x7a6b, 0xad => 0x7a69, + 0xae => 0x7c3e, 0xaf => 0x7c3f, 0xb0 => 0x7c38, 0xb1 => 0x7c3d, + 0xb2 => 0x7c37, 0xb3 => 0x7c40, 0xb4 => 0x7e6b, 0xb5 => 0x7e6d, + 0xb6 => 0x7e79, 0xb7 => 0x7e69, 0xb8 => 0x7e6a, 0xb9 => 0x7f85, + 0xba => 0x7e73, 0xbb => 0x7fb6, 0xbc => 0x7fb9, 0xbd => 0x7fb8, + 0xbe => 0x81d8, 0xbf => 0x85e9, 0xc0 => 0x85dd, 0xc1 => 0x85ea, + 0xc2 => 0x85d5, 0xc3 => 0x85e4, 0xc4 => 0x85e5, 0xc5 => 0x85f7, + 0xc6 => 0x87fb, 0xc7 => 0x8805, 0xc8 => 0x880d, 0xc9 => 0x87f9, + 0xca => 0x87fe, 0xcb => 0x8960, 0xcc => 0x895f, 0xcd => 0x8956, + 0xce => 0x895e, 0xcf => 0x8b41, 0xd0 => 0x8b5c, 0xd1 => 0x8b58, + 0xd2 => 0x8b49, 0xd3 => 0x8b5a, 0xd4 => 0x8b4e, 0xd5 => 0x8b4f, + 0xd6 => 0x8b46, 0xd7 => 0x8b59, 0xd8 => 0x8d08, 0xd9 => 0x8d0a, + 0xda => 0x8e7c, 0xdb => 0x8e72, 0xdc => 0x8e87, 0xdd => 0x8e76, + 0xde => 0x8e6c, 0xdf => 0x8e7a, 0xe0 => 0x8e74, 0xe1 => 0x8f54, + 0xe2 => 0x8f4e, 0xe3 => 0x8fad, 0xe4 => 0x908a, 0xe5 => 0x908b, + 0xe6 => 0x91b1, 0xe7 => 0x91ae, 0xe8 => 0x93e1, 0xe9 => 0x93d1, + 0xea => 0x93df, 0xeb => 0x93c3, 0xec => 0x93c8, 0xed => 0x93dc, + 0xee => 0x93dd, 0xef => 0x93d6, 0xf0 => 0x93e2, 0xf1 => 0x93cd, + 0xf2 => 0x93d8, 0xf3 => 0x93e4, 0xf4 => 0x93d7, 0xf5 => 0x93e8, + 0xf6 => 0x95dc, 0xf7 => 0x96b4, 0xf8 => 0x96e3, 0xf9 => 0x972a, + 0xfa => 0x9727, 0xfb => 0x9761, 0xfc => 0x97dc, 0xfd => 0x97fb, + 0xfe => 0x985e, + }, + 0xc4 => { + 0x40 => 0x9858, 0x41 => 0x985b, 0x42 => 0x98bc, 0x43 => 0x9945, + 0x44 => 0x9949, 0x45 => 0x9a16, 0x46 => 0x9a19, 0x47 => 0x9b0d, + 0x48 => 0x9be8, 0x49 => 0x9be7, 0x4a => 0x9bd6, 0x4b => 0x9bdb, + 0x4c => 0x9d89, 0x4d => 0x9d61, 0x4e => 0x9d72, 0x4f => 0x9d6a, + 0x50 => 0x9d6c, 0x51 => 0x9e92, 0x52 => 0x9e97, 0x53 => 0x9e93, + 0x54 => 0x9eb4, 0x55 => 0x52f8, 0x56 => 0x56a8, 0x57 => 0x56b7, + 0x58 => 0x56b6, 0x59 => 0x56b4, 0x5a => 0x56bc, 0x5b => 0x58e4, + 0x5c => 0x5b40, 0x5d => 0x5b43, 0x5e => 0x5b7d, 0x5f => 0x5bf6, + 0x60 => 0x5dc9, 0x61 => 0x61f8, 0x62 => 0x61fa, 0x63 => 0x6518, + 0x64 => 0x6514, 0x65 => 0x6519, 0x66 => 0x66e6, 0x67 => 0x6727, + 0x68 => 0x6aec, 0x69 => 0x703e, 0x6a => 0x7030, 0x6b => 0x7032, + 0x6c => 0x7210, 0x6d => 0x737b, 0x6e => 0x74cf, 0x6f => 0x7662, + 0x70 => 0x7665, 0x71 => 0x7926, 0x72 => 0x792a, 0x73 => 0x792c, + 0x74 => 0x792b, 0x75 => 0x7ac7, 0x76 => 0x7af6, 0x77 => 0x7c4c, + 0x78 => 0x7c43, 0x79 => 0x7c4d, 0x7a => 0x7cef, 0x7b => 0x7cf0, + 0x7c => 0x8fae, 0x7d => 0x7e7d, 0x7e => 0x7e7c, 0xa1 => 0x7e82, + 0xa2 => 0x7f4c, 0xa3 => 0x8000, 0xa4 => 0x81da, 0xa5 => 0x8266, + 0xa6 => 0x85fb, 0xa7 => 0x85f9, 0xa8 => 0x8611, 0xa9 => 0x85fa, + 0xaa => 0x8606, 0xab => 0x860b, 0xac => 0x8607, 0xad => 0x860a, + 0xae => 0x8814, 0xaf => 0x8815, 0xb0 => 0x8964, 0xb1 => 0x89ba, + 0xb2 => 0x89f8, 0xb3 => 0x8b70, 0xb4 => 0x8b6c, 0xb5 => 0x8b66, + 0xb6 => 0x8b6f, 0xb7 => 0x8b5f, 0xb8 => 0x8b6b, 0xb9 => 0x8d0f, + 0xba => 0x8d0d, 0xbb => 0x8e89, 0xbc => 0x8e81, 0xbd => 0x8e85, + 0xbe => 0x8e82, 0xbf => 0x91b4, 0xc0 => 0x91cb, 0xc1 => 0x9418, + 0xc2 => 0x9403, 0xc3 => 0x93fd, 0xc4 => 0x95e1, 0xc5 => 0x9730, + 0xc6 => 0x98c4, 0xc7 => 0x9952, 0xc8 => 0x9951, 0xc9 => 0x99a8, + 0xca => 0x9a2b, 0xcb => 0x9a30, 0xcc => 0x9a37, 0xcd => 0x9a35, + 0xce => 0x9c13, 0xcf => 0x9c0d, 0xd0 => 0x9e79, 0xd1 => 0x9eb5, + 0xd2 => 0x9ee8, 0xd3 => 0x9f2f, 0xd4 => 0x9f5f, 0xd5 => 0x9f63, + 0xd6 => 0x9f61, 0xd7 => 0x5137, 0xd8 => 0x5138, 0xd9 => 0x56c1, + 0xda => 0x56c0, 0xdb => 0x56c2, 0xdc => 0x5914, 0xdd => 0x5c6c, + 0xde => 0x5dcd, 0xdf => 0x61fc, 0xe0 => 0x61fe, 0xe1 => 0x651d, + 0xe2 => 0x651c, 0xe3 => 0x6595, 0xe4 => 0x66e9, 0xe5 => 0x6afb, + 0xe6 => 0x6b04, 0xe7 => 0x6afa, 0xe8 => 0x6bb2, 0xe9 => 0x704c, + 0xea => 0x721b, 0xeb => 0x72a7, 0xec => 0x74d6, 0xed => 0x74d4, + 0xee => 0x7669, 0xef => 0x77d3, 0xf0 => 0x7c50, 0xf1 => 0x7e8f, + 0xf2 => 0x7e8c, 0xf3 => 0x7fbc, 0xf4 => 0x8617, 0xf5 => 0x862d, + 0xf6 => 0x861a, 0xf7 => 0x8823, 0xf8 => 0x8822, 0xf9 => 0x8821, + 0xfa => 0x881f, 0xfb => 0x896a, 0xfc => 0x896c, 0xfd => 0x89bd, + 0xfe => 0x8b74, + }, + 0xc5 => { + 0x40 => 0x8b77, 0x41 => 0x8b7d, 0x42 => 0x8d13, 0x43 => 0x8e8a, + 0x44 => 0x8e8d, 0x45 => 0x8e8b, 0x46 => 0x8f5f, 0x47 => 0x8faf, + 0x48 => 0x91ba, 0x49 => 0x942e, 0x4a => 0x9433, 0x4b => 0x9435, + 0x4c => 0x943a, 0x4d => 0x9438, 0x4e => 0x9432, 0x4f => 0x942b, + 0x50 => 0x95e2, 0x51 => 0x9738, 0x52 => 0x9739, 0x53 => 0x9732, + 0x54 => 0x97ff, 0x55 => 0x9867, 0x56 => 0x9865, 0x57 => 0x9957, + 0x58 => 0x9a45, 0x59 => 0x9a43, 0x5a => 0x9a40, 0x5b => 0x9a3e, + 0x5c => 0x9acf, 0x5d => 0x9b54, 0x5e => 0x9b51, 0x5f => 0x9c2d, + 0x60 => 0x9c25, 0x61 => 0x9daf, 0x62 => 0x9db4, 0x63 => 0x9dc2, + 0x64 => 0x9db8, 0x65 => 0x9e9d, 0x66 => 0x9eef, 0x67 => 0x9f19, + 0x68 => 0x9f5c, 0x69 => 0x9f66, 0x6a => 0x9f67, 0x6b => 0x513c, + 0x6c => 0x513b, 0x6d => 0x56c8, 0x6e => 0x56ca, 0x6f => 0x56c9, + 0x70 => 0x5b7f, 0x71 => 0x5dd4, 0x72 => 0x5dd2, 0x73 => 0x5f4e, + 0x74 => 0x61ff, 0x75 => 0x6524, 0x76 => 0x6b0a, 0x77 => 0x6b61, + 0x78 => 0x7051, 0x79 => 0x7058, 0x7a => 0x7380, 0x7b => 0x74e4, + 0x7c => 0x758a, 0x7d => 0x766e, 0x7e => 0x766c, 0xa1 => 0x79b3, + 0xa2 => 0x7c60, 0xa3 => 0x7c5f, 0xa4 => 0x807e, 0xa5 => 0x807d, + 0xa6 => 0x81df, 0xa7 => 0x8972, 0xa8 => 0x896f, 0xa9 => 0x89fc, + 0xaa => 0x8b80, 0xab => 0x8d16, 0xac => 0x8d17, 0xad => 0x8e91, + 0xae => 0x8e93, 0xaf => 0x8f61, 0xb0 => 0x9148, 0xb1 => 0x9444, + 0xb2 => 0x9451, 0xb3 => 0x9452, 0xb4 => 0x973d, 0xb5 => 0x973e, + 0xb6 => 0x97c3, 0xb7 => 0x97c1, 0xb8 => 0x986b, 0xb9 => 0x9955, + 0xba => 0x9a55, 0xbb => 0x9a4d, 0xbc => 0x9ad2, 0xbd => 0x9b1a, + 0xbe => 0x9c49, 0xbf => 0x9c31, 0xc0 => 0x9c3e, 0xc1 => 0x9c3b, + 0xc2 => 0x9dd3, 0xc3 => 0x9dd7, 0xc4 => 0x9f34, 0xc5 => 0x9f6c, + 0xc6 => 0x9f6a, 0xc7 => 0x9f94, 0xc8 => 0x56cc, 0xc9 => 0x5dd6, + 0xca => 0x6200, 0xcb => 0x6523, 0xcc => 0x652b, 0xcd => 0x652a, + 0xce => 0x66ec, 0xcf => 0x6b10, 0xd0 => 0x74da, 0xd1 => 0x7aca, + 0xd2 => 0x7c64, 0xd3 => 0x7c63, 0xd4 => 0x7c65, 0xd5 => 0x7e93, + 0xd6 => 0x7e96, 0xd7 => 0x7e94, 0xd8 => 0x81e2, 0xd9 => 0x8638, + 0xda => 0x863f, 0xdb => 0x8831, 0xdc => 0x8b8a, 0xdd => 0x9090, + 0xde => 0x908f, 0xdf => 0x9463, 0xe0 => 0x9460, 0xe1 => 0x9464, + 0xe2 => 0x9768, 0xe3 => 0x986f, 0xe4 => 0x995c, 0xe5 => 0x9a5a, + 0xe6 => 0x9a5b, 0xe7 => 0x9a57, 0xe8 => 0x9ad3, 0xe9 => 0x9ad4, + 0xea => 0x9ad1, 0xeb => 0x9c54, 0xec => 0x9c57, 0xed => 0x9c56, + 0xee => 0x9de5, 0xef => 0x9e9f, 0xf0 => 0x9ef4, 0xf1 => 0x56d1, + 0xf2 => 0x58e9, 0xf3 => 0x652c, 0xf4 => 0x705e, 0xf5 => 0x7671, + 0xf6 => 0x7672, 0xf7 => 0x77d7, 0xf8 => 0x7f50, 0xf9 => 0x7f88, + 0xfa => 0x8836, 0xfb => 0x8839, 0xfc => 0x8862, 0xfd => 0x8b93, + 0xfe => 0x8b92, + }, + 0xc6 => { + 0x40 => 0x8b96, 0x41 => 0x8277, 0x42 => 0x8d1b, 0x43 => 0x91c0, + 0x44 => 0x946a, 0x45 => 0x9742, 0x46 => 0x9748, 0x47 => 0x9744, + 0x48 => 0x97c6, 0x49 => 0x9870, 0x4a => 0x9a5f, 0x4b => 0x9b22, + 0x4c => 0x9b58, 0x4d => 0x9c5f, 0x4e => 0x9df9, 0x4f => 0x9dfa, + 0x50 => 0x9e7c, 0x51 => 0x9e7d, 0x52 => 0x9f07, 0x53 => 0x9f77, + 0x54 => 0x9f72, 0x55 => 0x5ef3, 0x56 => 0x6b16, 0x57 => 0x7063, + 0x58 => 0x7c6c, 0x59 => 0x7c6e, 0x5a => 0x883b, 0x5b => 0x89c0, + 0x5c => 0x8ea1, 0x5d => 0x91c1, 0x5e => 0x9472, 0x5f => 0x9470, + 0x60 => 0x9871, 0x61 => 0x995e, 0x62 => 0x9ad6, 0x63 => 0x9b23, + 0x64 => 0x9ecc, 0x65 => 0x7064, 0x66 => 0x77da, 0x67 => 0x8b9a, + 0x68 => 0x9477, 0x69 => 0x97c9, 0x6a => 0x9a62, 0x6b => 0x9a65, + 0x6c => 0x7e9c, 0x6d => 0x8b9c, 0x6e => 0x8eaa, 0x6f => 0x91c5, + 0x70 => 0x947d, 0x71 => 0x947e, 0x72 => 0x947c, 0x73 => 0x9c77, + 0x74 => 0x9c78, 0x75 => 0x9ef7, 0x76 => 0x8c54, 0x77 => 0x947f, + 0x78 => 0x9e1a, 0x79 => 0x7228, 0x7a => 0x9a6a, 0x7b => 0x9b31, + 0x7c => 0x9e1b, 0x7d => 0x9e1e, 0x7e => 0x7c72, + }, + 0xc9 => { + 0x40 => 0x4e42, 0x41 => 0x4e5c, 0x42 => 0x51f5, 0x43 => 0x531a, + 0x44 => 0x5382, 0x45 => 0x4e07, 0x46 => 0x4e0c, 0x47 => 0x4e47, + 0x48 => 0x4e8d, 0x49 => 0x56d7, 0x4a => 0xfa0c, 0x4b => 0x5c6e, + 0x4c => 0x5f73, 0x4d => 0x4e0f, 0x4e => 0x5187, 0x4f => 0x4e0e, + 0x50 => 0x4e2e, 0x51 => 0x4e93, 0x52 => 0x4ec2, 0x53 => 0x4ec9, + 0x54 => 0x4ec8, 0x55 => 0x5198, 0x56 => 0x52fc, 0x57 => 0x536c, + 0x58 => 0x53b9, 0x59 => 0x5720, 0x5a => 0x5903, 0x5b => 0x592c, + 0x5c => 0x5c10, 0x5d => 0x5dff, 0x5e => 0x65e1, 0x5f => 0x6bb3, + 0x60 => 0x6bcc, 0x61 => 0x6c14, 0x62 => 0x723f, 0x63 => 0x4e31, + 0x64 => 0x4e3c, 0x65 => 0x4ee8, 0x66 => 0x4edc, 0x67 => 0x4ee9, + 0x68 => 0x4ee1, 0x69 => 0x4edd, 0x6a => 0x4eda, 0x6b => 0x520c, + 0x6c => 0x531c, 0x6d => 0x534c, 0x6e => 0x5722, 0x6f => 0x5723, + 0x70 => 0x5917, 0x71 => 0x592f, 0x72 => 0x5b81, 0x73 => 0x5b84, + 0x74 => 0x5c12, 0x75 => 0x5c3b, 0x76 => 0x5c74, 0x77 => 0x5c73, + 0x78 => 0x5e04, 0x79 => 0x5e80, 0x7a => 0x5e82, 0x7b => 0x5fc9, + 0x7c => 0x6209, 0x7d => 0x6250, 0x7e => 0x6c15, 0xa1 => 0x6c36, + 0xa2 => 0x6c43, 0xa3 => 0x6c3f, 0xa4 => 0x6c3b, 0xa5 => 0x72ae, + 0xa6 => 0x72b0, 0xa7 => 0x738a, 0xa8 => 0x79b8, 0xa9 => 0x808a, + 0xaa => 0x961e, 0xab => 0x4f0e, 0xac => 0x4f18, 0xad => 0x4f2c, + 0xae => 0x4ef5, 0xaf => 0x4f14, 0xb0 => 0x4ef1, 0xb1 => 0x4f00, + 0xb2 => 0x4ef7, 0xb3 => 0x4f08, 0xb4 => 0x4f1d, 0xb5 => 0x4f02, + 0xb6 => 0x4f05, 0xb7 => 0x4f22, 0xb8 => 0x4f13, 0xb9 => 0x4f04, + 0xba => 0x4ef4, 0xbb => 0x4f12, 0xbc => 0x51b1, 0xbd => 0x5213, + 0xbe => 0x5209, 0xbf => 0x5210, 0xc0 => 0x52a6, 0xc1 => 0x5322, + 0xc2 => 0x531f, 0xc3 => 0x534d, 0xc4 => 0x538a, 0xc5 => 0x5407, + 0xc6 => 0x56e1, 0xc7 => 0x56df, 0xc8 => 0x572e, 0xc9 => 0x572a, + 0xca => 0x5734, 0xcb => 0x593c, 0xcc => 0x5980, 0xcd => 0x597c, + 0xce => 0x5985, 0xcf => 0x597b, 0xd0 => 0x597e, 0xd1 => 0x5977, + 0xd2 => 0x597f, 0xd3 => 0x5b56, 0xd4 => 0x5c15, 0xd5 => 0x5c25, + 0xd6 => 0x5c7c, 0xd7 => 0x5c7a, 0xd8 => 0x5c7b, 0xd9 => 0x5c7e, + 0xda => 0x5ddf, 0xdb => 0x5e75, 0xdc => 0x5e84, 0xdd => 0x5f02, + 0xde => 0x5f1a, 0xdf => 0x5f74, 0xe0 => 0x5fd5, 0xe1 => 0x5fd4, + 0xe2 => 0x5fcf, 0xe3 => 0x625c, 0xe4 => 0x625e, 0xe5 => 0x6264, + 0xe6 => 0x6261, 0xe7 => 0x6266, 0xe8 => 0x6262, 0xe9 => 0x6259, + 0xea => 0x6260, 0xeb => 0x625a, 0xec => 0x6265, 0xed => 0x65ef, + 0xee => 0x65ee, 0xef => 0x673e, 0xf0 => 0x6739, 0xf1 => 0x6738, + 0xf2 => 0x673b, 0xf3 => 0x673a, 0xf4 => 0x673f, 0xf5 => 0x673c, + 0xf6 => 0x6733, 0xf7 => 0x6c18, 0xf8 => 0x6c46, 0xf9 => 0x6c52, + 0xfa => 0x6c5c, 0xfb => 0x6c4f, 0xfc => 0x6c4a, 0xfd => 0x6c54, + 0xfe => 0x6c4b, + }, + 0xca => { + 0x40 => 0x6c4c, 0x41 => 0x7071, 0x42 => 0x725e, 0x43 => 0x72b4, + 0x44 => 0x72b5, 0x45 => 0x738e, 0x46 => 0x752a, 0x47 => 0x767f, + 0x48 => 0x7a75, 0x49 => 0x7f51, 0x4a => 0x8278, 0x4b => 0x827c, + 0x4c => 0x8280, 0x4d => 0x827d, 0x4e => 0x827f, 0x4f => 0x864d, + 0x50 => 0x897e, 0x51 => 0x9099, 0x52 => 0x9097, 0x53 => 0x9098, + 0x54 => 0x909b, 0x55 => 0x9094, 0x56 => 0x9622, 0x57 => 0x9624, + 0x58 => 0x9620, 0x59 => 0x9623, 0x5a => 0x4f56, 0x5b => 0x4f3b, + 0x5c => 0x4f62, 0x5d => 0x4f49, 0x5e => 0x4f53, 0x5f => 0x4f64, + 0x60 => 0x4f3e, 0x61 => 0x4f67, 0x62 => 0x4f52, 0x63 => 0x4f5f, + 0x64 => 0x4f41, 0x65 => 0x4f58, 0x66 => 0x4f2d, 0x67 => 0x4f33, + 0x68 => 0x4f3f, 0x69 => 0x4f61, 0x6a => 0x518f, 0x6b => 0x51b9, + 0x6c => 0x521c, 0x6d => 0x521e, 0x6e => 0x5221, 0x6f => 0x52ad, + 0x70 => 0x52ae, 0x71 => 0x5309, 0x72 => 0x5363, 0x73 => 0x5372, + 0x74 => 0x538e, 0x75 => 0x538f, 0x76 => 0x5430, 0x77 => 0x5437, + 0x78 => 0x542a, 0x79 => 0x5454, 0x7a => 0x5445, 0x7b => 0x5419, + 0x7c => 0x541c, 0x7d => 0x5425, 0x7e => 0x5418, 0xa1 => 0x543d, + 0xa2 => 0x544f, 0xa3 => 0x5441, 0xa4 => 0x5428, 0xa5 => 0x5424, + 0xa6 => 0x5447, 0xa7 => 0x56ee, 0xa8 => 0x56e7, 0xa9 => 0x56e5, + 0xaa => 0x5741, 0xab => 0x5745, 0xac => 0x574c, 0xad => 0x5749, + 0xae => 0x574b, 0xaf => 0x5752, 0xb0 => 0x5906, 0xb1 => 0x5940, + 0xb2 => 0x59a6, 0xb3 => 0x5998, 0xb4 => 0x59a0, 0xb5 => 0x5997, + 0xb6 => 0x598e, 0xb7 => 0x59a2, 0xb8 => 0x5990, 0xb9 => 0x598f, + 0xba => 0x59a7, 0xbb => 0x59a1, 0xbc => 0x5b8e, 0xbd => 0x5b92, + 0xbe => 0x5c28, 0xbf => 0x5c2a, 0xc0 => 0x5c8d, 0xc1 => 0x5c8f, + 0xc2 => 0x5c88, 0xc3 => 0x5c8b, 0xc4 => 0x5c89, 0xc5 => 0x5c92, + 0xc6 => 0x5c8a, 0xc7 => 0x5c86, 0xc8 => 0x5c93, 0xc9 => 0x5c95, + 0xca => 0x5de0, 0xcb => 0x5e0a, 0xcc => 0x5e0e, 0xcd => 0x5e8b, + 0xce => 0x5e89, 0xcf => 0x5e8c, 0xd0 => 0x5e88, 0xd1 => 0x5e8d, + 0xd2 => 0x5f05, 0xd3 => 0x5f1d, 0xd4 => 0x5f78, 0xd5 => 0x5f76, + 0xd6 => 0x5fd2, 0xd7 => 0x5fd1, 0xd8 => 0x5fd0, 0xd9 => 0x5fed, + 0xda => 0x5fe8, 0xdb => 0x5fee, 0xdc => 0x5ff3, 0xdd => 0x5fe1, + 0xde => 0x5fe4, 0xdf => 0x5fe3, 0xe0 => 0x5ffa, 0xe1 => 0x5fef, + 0xe2 => 0x5ff7, 0xe3 => 0x5ffb, 0xe4 => 0x6000, 0xe5 => 0x5ff4, + 0xe6 => 0x623a, 0xe7 => 0x6283, 0xe8 => 0x628c, 0xe9 => 0x628e, + 0xea => 0x628f, 0xeb => 0x6294, 0xec => 0x6287, 0xed => 0x6271, + 0xee => 0x627b, 0xef => 0x627a, 0xf0 => 0x6270, 0xf1 => 0x6281, + 0xf2 => 0x6288, 0xf3 => 0x6277, 0xf4 => 0x627d, 0xf5 => 0x6272, + 0xf6 => 0x6274, 0xf7 => 0x6537, 0xf8 => 0x65f0, 0xf9 => 0x65f4, + 0xfa => 0x65f3, 0xfb => 0x65f2, 0xfc => 0x65f5, 0xfd => 0x6745, + 0xfe => 0x6747, + }, + 0xcb => { + 0x40 => 0x6759, 0x41 => 0x6755, 0x42 => 0x674c, 0x43 => 0x6748, + 0x44 => 0x675d, 0x45 => 0x674d, 0x46 => 0x675a, 0x47 => 0x674b, + 0x48 => 0x6bd0, 0x49 => 0x6c19, 0x4a => 0x6c1a, 0x4b => 0x6c78, + 0x4c => 0x6c67, 0x4d => 0x6c6b, 0x4e => 0x6c84, 0x4f => 0x6c8b, + 0x50 => 0x6c8f, 0x51 => 0x6c71, 0x52 => 0x6c6f, 0x53 => 0x6c69, + 0x54 => 0x6c9a, 0x55 => 0x6c6d, 0x56 => 0x6c87, 0x57 => 0x6c95, + 0x58 => 0x6c9c, 0x59 => 0x6c66, 0x5a => 0x6c73, 0x5b => 0x6c65, + 0x5c => 0x6c7b, 0x5d => 0x6c8e, 0x5e => 0x7074, 0x5f => 0x707a, + 0x60 => 0x7263, 0x61 => 0x72bf, 0x62 => 0x72bd, 0x63 => 0x72c3, + 0x64 => 0x72c6, 0x65 => 0x72c1, 0x66 => 0x72ba, 0x67 => 0x72c5, + 0x68 => 0x7395, 0x69 => 0x7397, 0x6a => 0x7393, 0x6b => 0x7394, + 0x6c => 0x7392, 0x6d => 0x753a, 0x6e => 0x7539, 0x6f => 0x7594, + 0x70 => 0x7595, 0x71 => 0x7681, 0x72 => 0x793d, 0x73 => 0x8034, + 0x74 => 0x8095, 0x75 => 0x8099, 0x76 => 0x8090, 0x77 => 0x8092, + 0x78 => 0x809c, 0x79 => 0x8290, 0x7a => 0x828f, 0x7b => 0x8285, + 0x7c => 0x828e, 0x7d => 0x8291, 0x7e => 0x8293, 0xa1 => 0x828a, + 0xa2 => 0x8283, 0xa3 => 0x8284, 0xa4 => 0x8c78, 0xa5 => 0x8fc9, + 0xa6 => 0x8fbf, 0xa7 => 0x909f, 0xa8 => 0x90a1, 0xa9 => 0x90a5, + 0xaa => 0x909e, 0xab => 0x90a7, 0xac => 0x90a0, 0xad => 0x9630, + 0xae => 0x9628, 0xaf => 0x962f, 0xb0 => 0x962d, 0xb1 => 0x4e33, + 0xb2 => 0x4f98, 0xb3 => 0x4f7c, 0xb4 => 0x4f85, 0xb5 => 0x4f7d, + 0xb6 => 0x4f80, 0xb7 => 0x4f87, 0xb8 => 0x4f76, 0xb9 => 0x4f74, + 0xba => 0x4f89, 0xbb => 0x4f84, 0xbc => 0x4f77, 0xbd => 0x4f4c, + 0xbe => 0x4f97, 0xbf => 0x4f6a, 0xc0 => 0x4f9a, 0xc1 => 0x4f79, + 0xc2 => 0x4f81, 0xc3 => 0x4f78, 0xc4 => 0x4f90, 0xc5 => 0x4f9c, + 0xc6 => 0x4f94, 0xc7 => 0x4f9e, 0xc8 => 0x4f92, 0xc9 => 0x4f82, + 0xca => 0x4f95, 0xcb => 0x4f6b, 0xcc => 0x4f6e, 0xcd => 0x519e, + 0xce => 0x51bc, 0xcf => 0x51be, 0xd0 => 0x5235, 0xd1 => 0x5232, + 0xd2 => 0x5233, 0xd3 => 0x5246, 0xd4 => 0x5231, 0xd5 => 0x52bc, + 0xd6 => 0x530a, 0xd7 => 0x530b, 0xd8 => 0x533c, 0xd9 => 0x5392, + 0xda => 0x5394, 0xdb => 0x5487, 0xdc => 0x547f, 0xdd => 0x5481, + 0xde => 0x5491, 0xdf => 0x5482, 0xe0 => 0x5488, 0xe1 => 0x546b, + 0xe2 => 0x547a, 0xe3 => 0x547e, 0xe4 => 0x5465, 0xe5 => 0x546c, + 0xe6 => 0x5474, 0xe7 => 0x5466, 0xe8 => 0x548d, 0xe9 => 0x546f, + 0xea => 0x5461, 0xeb => 0x5460, 0xec => 0x5498, 0xed => 0x5463, + 0xee => 0x5467, 0xef => 0x5464, 0xf0 => 0x56f7, 0xf1 => 0x56f9, + 0xf2 => 0x576f, 0xf3 => 0x5772, 0xf4 => 0x576d, 0xf5 => 0x576b, + 0xf6 => 0x5771, 0xf7 => 0x5770, 0xf8 => 0x5776, 0xf9 => 0x5780, + 0xfa => 0x5775, 0xfb => 0x577b, 0xfc => 0x5773, 0xfd => 0x5774, + 0xfe => 0x5762, + }, + 0xcc => { + 0x40 => 0x5768, 0x41 => 0x577d, 0x42 => 0x590c, 0x43 => 0x5945, + 0x44 => 0x59b5, 0x45 => 0x59ba, 0x46 => 0x59cf, 0x47 => 0x59ce, + 0x48 => 0x59b2, 0x49 => 0x59cc, 0x4a => 0x59c1, 0x4b => 0x59b6, + 0x4c => 0x59bc, 0x4d => 0x59c3, 0x4e => 0x59d6, 0x4f => 0x59b1, + 0x50 => 0x59bd, 0x51 => 0x59c0, 0x52 => 0x59c8, 0x53 => 0x59b4, + 0x54 => 0x59c7, 0x55 => 0x5b62, 0x56 => 0x5b65, 0x57 => 0x5b93, + 0x58 => 0x5b95, 0x59 => 0x5c44, 0x5a => 0x5c47, 0x5b => 0x5cae, + 0x5c => 0x5ca4, 0x5d => 0x5ca0, 0x5e => 0x5cb5, 0x5f => 0x5caf, + 0x60 => 0x5ca8, 0x61 => 0x5cac, 0x62 => 0x5c9f, 0x63 => 0x5ca3, + 0x64 => 0x5cad, 0x65 => 0x5ca2, 0x66 => 0x5caa, 0x67 => 0x5ca7, + 0x68 => 0x5c9d, 0x69 => 0x5ca5, 0x6a => 0x5cb6, 0x6b => 0x5cb0, + 0x6c => 0x5ca6, 0x6d => 0x5e17, 0x6e => 0x5e14, 0x6f => 0x5e19, + 0x70 => 0x5f28, 0x71 => 0x5f22, 0x72 => 0x5f23, 0x73 => 0x5f24, + 0x74 => 0x5f54, 0x75 => 0x5f82, 0x76 => 0x5f7e, 0x77 => 0x5f7d, + 0x78 => 0x5fde, 0x79 => 0x5fe5, 0x7a => 0x602d, 0x7b => 0x6026, + 0x7c => 0x6019, 0x7d => 0x6032, 0x7e => 0x600b, 0xa1 => 0x6034, + 0xa2 => 0x600a, 0xa3 => 0x6017, 0xa4 => 0x6033, 0xa5 => 0x601a, + 0xa6 => 0x601e, 0xa7 => 0x602c, 0xa8 => 0x6022, 0xa9 => 0x600d, + 0xaa => 0x6010, 0xab => 0x602e, 0xac => 0x6013, 0xad => 0x6011, + 0xae => 0x600c, 0xaf => 0x6009, 0xb0 => 0x601c, 0xb1 => 0x6214, + 0xb2 => 0x623d, 0xb3 => 0x62ad, 0xb4 => 0x62b4, 0xb5 => 0x62d1, + 0xb6 => 0x62be, 0xb7 => 0x62aa, 0xb8 => 0x62b6, 0xb9 => 0x62ca, + 0xba => 0x62ae, 0xbb => 0x62b3, 0xbc => 0x62af, 0xbd => 0x62bb, + 0xbe => 0x62a9, 0xbf => 0x62b0, 0xc0 => 0x62b8, 0xc1 => 0x653d, + 0xc2 => 0x65a8, 0xc3 => 0x65bb, 0xc4 => 0x6609, 0xc5 => 0x65fc, + 0xc6 => 0x6604, 0xc7 => 0x6612, 0xc8 => 0x6608, 0xc9 => 0x65fb, + 0xca => 0x6603, 0xcb => 0x660b, 0xcc => 0x660d, 0xcd => 0x6605, + 0xce => 0x65fd, 0xcf => 0x6611, 0xd0 => 0x6610, 0xd1 => 0x66f6, + 0xd2 => 0x670a, 0xd3 => 0x6785, 0xd4 => 0x676c, 0xd5 => 0x678e, + 0xd6 => 0x6792, 0xd7 => 0x6776, 0xd8 => 0x677b, 0xd9 => 0x6798, + 0xda => 0x6786, 0xdb => 0x6784, 0xdc => 0x6774, 0xdd => 0x678d, + 0xde => 0x678c, 0xdf => 0x677a, 0xe0 => 0x679f, 0xe1 => 0x6791, + 0xe2 => 0x6799, 0xe3 => 0x6783, 0xe4 => 0x677d, 0xe5 => 0x6781, + 0xe6 => 0x6778, 0xe7 => 0x6779, 0xe8 => 0x6794, 0xe9 => 0x6b25, + 0xea => 0x6b80, 0xeb => 0x6b7e, 0xec => 0x6bde, 0xed => 0x6c1d, + 0xee => 0x6c93, 0xef => 0x6cec, 0xf0 => 0x6ceb, 0xf1 => 0x6cee, + 0xf2 => 0x6cd9, 0xf3 => 0x6cb6, 0xf4 => 0x6cd4, 0xf5 => 0x6cad, + 0xf6 => 0x6ce7, 0xf7 => 0x6cb7, 0xf8 => 0x6cd0, 0xf9 => 0x6cc2, + 0xfa => 0x6cba, 0xfb => 0x6cc3, 0xfc => 0x6cc6, 0xfd => 0x6ced, + 0xfe => 0x6cf2, + }, + 0xcd => { + 0x40 => 0x6cd2, 0x41 => 0x6cdd, 0x42 => 0x6cb4, 0x43 => 0x6c8a, + 0x44 => 0x6c9d, 0x45 => 0x6c80, 0x46 => 0x6cde, 0x47 => 0x6cc0, + 0x48 => 0x6d30, 0x49 => 0x6ccd, 0x4a => 0x6cc7, 0x4b => 0x6cb0, + 0x4c => 0x6cf9, 0x4d => 0x6ccf, 0x4e => 0x6ce9, 0x4f => 0x6cd1, + 0x50 => 0x7094, 0x51 => 0x7098, 0x52 => 0x7085, 0x53 => 0x7093, + 0x54 => 0x7086, 0x55 => 0x7084, 0x56 => 0x7091, 0x57 => 0x7096, + 0x58 => 0x7082, 0x59 => 0x709a, 0x5a => 0x7083, 0x5b => 0x726a, + 0x5c => 0x72d6, 0x5d => 0x72cb, 0x5e => 0x72d8, 0x5f => 0x72c9, + 0x60 => 0x72dc, 0x61 => 0x72d2, 0x62 => 0x72d4, 0x63 => 0x72da, + 0x64 => 0x72cc, 0x65 => 0x72d1, 0x66 => 0x73a4, 0x67 => 0x73a1, + 0x68 => 0x73ad, 0x69 => 0x73a6, 0x6a => 0x73a2, 0x6b => 0x73a0, + 0x6c => 0x73ac, 0x6d => 0x739d, 0x6e => 0x74dd, 0x6f => 0x74e8, + 0x70 => 0x753f, 0x71 => 0x7540, 0x72 => 0x753e, 0x73 => 0x758c, + 0x74 => 0x7598, 0x75 => 0x76af, 0x76 => 0x76f3, 0x77 => 0x76f1, + 0x78 => 0x76f0, 0x79 => 0x76f5, 0x7a => 0x77f8, 0x7b => 0x77fc, + 0x7c => 0x77f9, 0x7d => 0x77fb, 0x7e => 0x77fa, 0xa1 => 0x77f7, + 0xa2 => 0x7942, 0xa3 => 0x793f, 0xa4 => 0x79c5, 0xa5 => 0x7a78, + 0xa6 => 0x7a7b, 0xa7 => 0x7afb, 0xa8 => 0x7c75, 0xa9 => 0x7cfd, + 0xaa => 0x8035, 0xab => 0x808f, 0xac => 0x80ae, 0xad => 0x80a3, + 0xae => 0x80b8, 0xaf => 0x80b5, 0xb0 => 0x80ad, 0xb1 => 0x8220, + 0xb2 => 0x82a0, 0xb3 => 0x82c0, 0xb4 => 0x82ab, 0xb5 => 0x829a, + 0xb6 => 0x8298, 0xb7 => 0x829b, 0xb8 => 0x82b5, 0xb9 => 0x82a7, + 0xba => 0x82ae, 0xbb => 0x82bc, 0xbc => 0x829e, 0xbd => 0x82ba, + 0xbe => 0x82b4, 0xbf => 0x82a8, 0xc0 => 0x82a1, 0xc1 => 0x82a9, + 0xc2 => 0x82c2, 0xc3 => 0x82a4, 0xc4 => 0x82c3, 0xc5 => 0x82b6, + 0xc6 => 0x82a2, 0xc7 => 0x8670, 0xc8 => 0x866f, 0xc9 => 0x866d, + 0xca => 0x866e, 0xcb => 0x8c56, 0xcc => 0x8fd2, 0xcd => 0x8fcb, + 0xce => 0x8fd3, 0xcf => 0x8fcd, 0xd0 => 0x8fd6, 0xd1 => 0x8fd5, + 0xd2 => 0x8fd7, 0xd3 => 0x90b2, 0xd4 => 0x90b4, 0xd5 => 0x90af, + 0xd6 => 0x90b3, 0xd7 => 0x90b0, 0xd8 => 0x9639, 0xd9 => 0x963d, + 0xda => 0x963c, 0xdb => 0x963a, 0xdc => 0x9643, 0xdd => 0x4fcd, + 0xde => 0x4fc5, 0xdf => 0x4fd3, 0xe0 => 0x4fb2, 0xe1 => 0x4fc9, + 0xe2 => 0x4fcb, 0xe3 => 0x4fc1, 0xe4 => 0x4fd4, 0xe5 => 0x4fdc, + 0xe6 => 0x4fd9, 0xe7 => 0x4fbb, 0xe8 => 0x4fb3, 0xe9 => 0x4fdb, + 0xea => 0x4fc7, 0xeb => 0x4fd6, 0xec => 0x4fba, 0xed => 0x4fc0, + 0xee => 0x4fb9, 0xef => 0x4fec, 0xf0 => 0x5244, 0xf1 => 0x5249, + 0xf2 => 0x52c0, 0xf3 => 0x52c2, 0xf4 => 0x533d, 0xf5 => 0x537c, + 0xf6 => 0x5397, 0xf7 => 0x5396, 0xf8 => 0x5399, 0xf9 => 0x5398, + 0xfa => 0x54ba, 0xfb => 0x54a1, 0xfc => 0x54ad, 0xfd => 0x54a5, + 0xfe => 0x54cf, + }, + 0xce => { + 0x40 => 0x54c3, 0x41 => 0x830d, 0x42 => 0x54b7, 0x43 => 0x54ae, + 0x44 => 0x54d6, 0x45 => 0x54b6, 0x46 => 0x54c5, 0x47 => 0x54c6, + 0x48 => 0x54a0, 0x49 => 0x5470, 0x4a => 0x54bc, 0x4b => 0x54a2, + 0x4c => 0x54be, 0x4d => 0x5472, 0x4e => 0x54de, 0x4f => 0x54b0, + 0x50 => 0x57b5, 0x51 => 0x579e, 0x52 => 0x579f, 0x53 => 0x57a4, + 0x54 => 0x578c, 0x55 => 0x5797, 0x56 => 0x579d, 0x57 => 0x579b, + 0x58 => 0x5794, 0x59 => 0x5798, 0x5a => 0x578f, 0x5b => 0x5799, + 0x5c => 0x57a5, 0x5d => 0x579a, 0x5e => 0x5795, 0x5f => 0x58f4, + 0x60 => 0x590d, 0x61 => 0x5953, 0x62 => 0x59e1, 0x63 => 0x59de, + 0x64 => 0x59ee, 0x65 => 0x5a00, 0x66 => 0x59f1, 0x67 => 0x59dd, + 0x68 => 0x59fa, 0x69 => 0x59fd, 0x6a => 0x59fc, 0x6b => 0x59f6, + 0x6c => 0x59e4, 0x6d => 0x59f2, 0x6e => 0x59f7, 0x6f => 0x59db, + 0x70 => 0x59e9, 0x71 => 0x59f3, 0x72 => 0x59f5, 0x73 => 0x59e0, + 0x74 => 0x59fe, 0x75 => 0x59f4, 0x76 => 0x59ed, 0x77 => 0x5ba8, + 0x78 => 0x5c4c, 0x79 => 0x5cd0, 0x7a => 0x5cd8, 0x7b => 0x5ccc, + 0x7c => 0x5cd7, 0x7d => 0x5ccb, 0x7e => 0x5cdb, 0xa1 => 0x5cde, + 0xa2 => 0x5cda, 0xa3 => 0x5cc9, 0xa4 => 0x5cc7, 0xa5 => 0x5cca, + 0xa6 => 0x5cd6, 0xa7 => 0x5cd3, 0xa8 => 0x5cd4, 0xa9 => 0x5ccf, + 0xaa => 0x5cc8, 0xab => 0x5cc6, 0xac => 0x5cce, 0xad => 0x5cdf, + 0xae => 0x5cf8, 0xaf => 0x5df9, 0xb0 => 0x5e21, 0xb1 => 0x5e22, + 0xb2 => 0x5e23, 0xb3 => 0x5e20, 0xb4 => 0x5e24, 0xb5 => 0x5eb0, + 0xb6 => 0x5ea4, 0xb7 => 0x5ea2, 0xb8 => 0x5e9b, 0xb9 => 0x5ea3, + 0xba => 0x5ea5, 0xbb => 0x5f07, 0xbc => 0x5f2e, 0xbd => 0x5f56, + 0xbe => 0x5f86, 0xbf => 0x6037, 0xc0 => 0x6039, 0xc1 => 0x6054, + 0xc2 => 0x6072, 0xc3 => 0x605e, 0xc4 => 0x6045, 0xc5 => 0x6053, + 0xc6 => 0x6047, 0xc7 => 0x6049, 0xc8 => 0x605b, 0xc9 => 0x604c, + 0xca => 0x6040, 0xcb => 0x6042, 0xcc => 0x605f, 0xcd => 0x6024, + 0xce => 0x6044, 0xcf => 0x6058, 0xd0 => 0x6066, 0xd1 => 0x606e, + 0xd2 => 0x6242, 0xd3 => 0x6243, 0xd4 => 0x62cf, 0xd5 => 0x630d, + 0xd6 => 0x630b, 0xd7 => 0x62f5, 0xd8 => 0x630e, 0xd9 => 0x6303, + 0xda => 0x62eb, 0xdb => 0x62f9, 0xdc => 0x630f, 0xdd => 0x630c, + 0xde => 0x62f8, 0xdf => 0x62f6, 0xe0 => 0x6300, 0xe1 => 0x6313, + 0xe2 => 0x6314, 0xe3 => 0x62fa, 0xe4 => 0x6315, 0xe5 => 0x62fb, + 0xe6 => 0x62f0, 0xe7 => 0x6541, 0xe8 => 0x6543, 0xe9 => 0x65aa, + 0xea => 0x65bf, 0xeb => 0x6636, 0xec => 0x6621, 0xed => 0x6632, + 0xee => 0x6635, 0xef => 0x661c, 0xf0 => 0x6626, 0xf1 => 0x6622, + 0xf2 => 0x6633, 0xf3 => 0x662b, 0xf4 => 0x663a, 0xf5 => 0x661d, + 0xf6 => 0x6634, 0xf7 => 0x6639, 0xf8 => 0x662e, 0xf9 => 0x670f, + 0xfa => 0x6710, 0xfb => 0x67c1, 0xfc => 0x67f2, 0xfd => 0x67c8, + 0xfe => 0x67ba, + }, + 0xcf => { + 0x40 => 0x67dc, 0x41 => 0x67bb, 0x42 => 0x67f8, 0x43 => 0x67d8, + 0x44 => 0x67c0, 0x45 => 0x67b7, 0x46 => 0x67c5, 0x47 => 0x67eb, + 0x48 => 0x67e4, 0x49 => 0x67df, 0x4a => 0x67b5, 0x4b => 0x67cd, + 0x4c => 0x67b3, 0x4d => 0x67f7, 0x4e => 0x67f6, 0x4f => 0x67ee, + 0x50 => 0x67e3, 0x51 => 0x67c2, 0x52 => 0x67b9, 0x53 => 0x67ce, + 0x54 => 0x67e7, 0x55 => 0x67f0, 0x56 => 0x67b2, 0x57 => 0x67fc, + 0x58 => 0x67c6, 0x59 => 0x67ed, 0x5a => 0x67cc, 0x5b => 0x67ae, + 0x5c => 0x67e6, 0x5d => 0x67db, 0x5e => 0x67fa, 0x5f => 0x67c9, + 0x60 => 0x67ca, 0x61 => 0x67c3, 0x62 => 0x67ea, 0x63 => 0x67cb, + 0x64 => 0x6b28, 0x65 => 0x6b82, 0x66 => 0x6b84, 0x67 => 0x6bb6, + 0x68 => 0x6bd6, 0x69 => 0x6bd8, 0x6a => 0x6be0, 0x6b => 0x6c20, + 0x6c => 0x6c21, 0x6d => 0x6d28, 0x6e => 0x6d34, 0x6f => 0x6d2d, + 0x70 => 0x6d1f, 0x71 => 0x6d3c, 0x72 => 0x6d3f, 0x73 => 0x6d12, + 0x74 => 0x6d0a, 0x75 => 0x6cda, 0x76 => 0x6d33, 0x77 => 0x6d04, + 0x78 => 0x6d19, 0x79 => 0x6d3a, 0x7a => 0x6d1a, 0x7b => 0x6d11, + 0x7c => 0x6d00, 0x7d => 0x6d1d, 0x7e => 0x6d42, 0xa1 => 0x6d01, + 0xa2 => 0x6d18, 0xa3 => 0x6d37, 0xa4 => 0x6d03, 0xa5 => 0x6d0f, + 0xa6 => 0x6d40, 0xa7 => 0x6d07, 0xa8 => 0x6d20, 0xa9 => 0x6d2c, + 0xaa => 0x6d08, 0xab => 0x6d22, 0xac => 0x6d09, 0xad => 0x6d10, + 0xae => 0x70b7, 0xaf => 0x709f, 0xb0 => 0x70be, 0xb1 => 0x70b1, + 0xb2 => 0x70b0, 0xb3 => 0x70a1, 0xb4 => 0x70b4, 0xb5 => 0x70b5, + 0xb6 => 0x70a9, 0xb7 => 0x7241, 0xb8 => 0x7249, 0xb9 => 0x724a, + 0xba => 0x726c, 0xbb => 0x7270, 0xbc => 0x7273, 0xbd => 0x726e, + 0xbe => 0x72ca, 0xbf => 0x72e4, 0xc0 => 0x72e8, 0xc1 => 0x72eb, + 0xc2 => 0x72df, 0xc3 => 0x72ea, 0xc4 => 0x72e6, 0xc5 => 0x72e3, + 0xc6 => 0x7385, 0xc7 => 0x73cc, 0xc8 => 0x73c2, 0xc9 => 0x73c8, + 0xca => 0x73c5, 0xcb => 0x73b9, 0xcc => 0x73b6, 0xcd => 0x73b5, + 0xce => 0x73b4, 0xcf => 0x73eb, 0xd0 => 0x73bf, 0xd1 => 0x73c7, + 0xd2 => 0x73be, 0xd3 => 0x73c3, 0xd4 => 0x73c6, 0xd5 => 0x73b8, + 0xd6 => 0x73cb, 0xd7 => 0x74ec, 0xd8 => 0x74ee, 0xd9 => 0x752e, + 0xda => 0x7547, 0xdb => 0x7548, 0xdc => 0x75a7, 0xdd => 0x75aa, + 0xde => 0x7679, 0xdf => 0x76c4, 0xe0 => 0x7708, 0xe1 => 0x7703, + 0xe2 => 0x7704, 0xe3 => 0x7705, 0xe4 => 0x770a, 0xe5 => 0x76f7, + 0xe6 => 0x76fb, 0xe7 => 0x76fa, 0xe8 => 0x77e7, 0xe9 => 0x77e8, + 0xea => 0x7806, 0xeb => 0x7811, 0xec => 0x7812, 0xed => 0x7805, + 0xee => 0x7810, 0xef => 0x780f, 0xf0 => 0x780e, 0xf1 => 0x7809, + 0xf2 => 0x7803, 0xf3 => 0x7813, 0xf4 => 0x794a, 0xf5 => 0x794c, + 0xf6 => 0x794b, 0xf7 => 0x7945, 0xf8 => 0x7944, 0xf9 => 0x79d5, + 0xfa => 0x79cd, 0xfb => 0x79cf, 0xfc => 0x79d6, 0xfd => 0x79ce, + 0xfe => 0x7a80, + }, + 0xd0 => { + 0x40 => 0x7a7e, 0x41 => 0x7ad1, 0x42 => 0x7b00, 0x43 => 0x7b01, + 0x44 => 0x7c7a, 0x45 => 0x7c78, 0x46 => 0x7c79, 0x47 => 0x7c7f, + 0x48 => 0x7c80, 0x49 => 0x7c81, 0x4a => 0x7d03, 0x4b => 0x7d08, + 0x4c => 0x7d01, 0x4d => 0x7f58, 0x4e => 0x7f91, 0x4f => 0x7f8d, + 0x50 => 0x7fbe, 0x51 => 0x8007, 0x52 => 0x800e, 0x53 => 0x800f, + 0x54 => 0x8014, 0x55 => 0x8037, 0x56 => 0x80d8, 0x57 => 0x80c7, + 0x58 => 0x80e0, 0x59 => 0x80d1, 0x5a => 0x80c8, 0x5b => 0x80c2, + 0x5c => 0x80d0, 0x5d => 0x80c5, 0x5e => 0x80e3, 0x5f => 0x80d9, + 0x60 => 0x80dc, 0x61 => 0x80ca, 0x62 => 0x80d5, 0x63 => 0x80c9, + 0x64 => 0x80cf, 0x65 => 0x80d7, 0x66 => 0x80e6, 0x67 => 0x80cd, + 0x68 => 0x81ff, 0x69 => 0x8221, 0x6a => 0x8294, 0x6b => 0x82d9, + 0x6c => 0x82fe, 0x6d => 0x82f9, 0x6e => 0x8307, 0x6f => 0x82e8, + 0x70 => 0x8300, 0x71 => 0x82d5, 0x72 => 0x833a, 0x73 => 0x82eb, + 0x74 => 0x82d6, 0x75 => 0x82f4, 0x76 => 0x82ec, 0x77 => 0x82e1, + 0x78 => 0x82f2, 0x79 => 0x82f5, 0x7a => 0x830c, 0x7b => 0x82fb, + 0x7c => 0x82f6, 0x7d => 0x82f0, 0x7e => 0x82ea, 0xa1 => 0x82e4, + 0xa2 => 0x82e0, 0xa3 => 0x82fa, 0xa4 => 0x82f3, 0xa5 => 0x82ed, + 0xa6 => 0x8677, 0xa7 => 0x8674, 0xa8 => 0x867c, 0xa9 => 0x8673, + 0xaa => 0x8841, 0xab => 0x884e, 0xac => 0x8867, 0xad => 0x886a, + 0xae => 0x8869, 0xaf => 0x89d3, 0xb0 => 0x8a04, 0xb1 => 0x8a07, + 0xb2 => 0x8d72, 0xb3 => 0x8fe3, 0xb4 => 0x8fe1, 0xb5 => 0x8fee, + 0xb6 => 0x8fe0, 0xb7 => 0x90f1, 0xb8 => 0x90bd, 0xb9 => 0x90bf, + 0xba => 0x90d5, 0xbb => 0x90c5, 0xbc => 0x90be, 0xbd => 0x90c7, + 0xbe => 0x90cb, 0xbf => 0x90c8, 0xc0 => 0x91d4, 0xc1 => 0x91d3, + 0xc2 => 0x9654, 0xc3 => 0x964f, 0xc4 => 0x9651, 0xc5 => 0x9653, + 0xc6 => 0x964a, 0xc7 => 0x964e, 0xc8 => 0x501e, 0xc9 => 0x5005, + 0xca => 0x5007, 0xcb => 0x5013, 0xcc => 0x5022, 0xcd => 0x5030, + 0xce => 0x501b, 0xcf => 0x4ff5, 0xd0 => 0x4ff4, 0xd1 => 0x5033, + 0xd2 => 0x5037, 0xd3 => 0x502c, 0xd4 => 0x4ff6, 0xd5 => 0x4ff7, + 0xd6 => 0x5017, 0xd7 => 0x501c, 0xd8 => 0x5020, 0xd9 => 0x5027, + 0xda => 0x5035, 0xdb => 0x502f, 0xdc => 0x5031, 0xdd => 0x500e, + 0xde => 0x515a, 0xdf => 0x5194, 0xe0 => 0x5193, 0xe1 => 0x51ca, + 0xe2 => 0x51c4, 0xe3 => 0x51c5, 0xe4 => 0x51c8, 0xe5 => 0x51ce, + 0xe6 => 0x5261, 0xe7 => 0x525a, 0xe8 => 0x5252, 0xe9 => 0x525e, + 0xea => 0x525f, 0xeb => 0x5255, 0xec => 0x5262, 0xed => 0x52cd, + 0xee => 0x530e, 0xef => 0x539e, 0xf0 => 0x5526, 0xf1 => 0x54e2, + 0xf2 => 0x5517, 0xf3 => 0x5512, 0xf4 => 0x54e7, 0xf5 => 0x54f3, + 0xf6 => 0x54e4, 0xf7 => 0x551a, 0xf8 => 0x54ff, 0xf9 => 0x5504, + 0xfa => 0x5508, 0xfb => 0x54eb, 0xfc => 0x5511, 0xfd => 0x5505, + 0xfe => 0x54f1, + }, + 0xd1 => { + 0x40 => 0x550a, 0x41 => 0x54fb, 0x42 => 0x54f7, 0x43 => 0x54f8, + 0x44 => 0x54e0, 0x45 => 0x550e, 0x46 => 0x5503, 0x47 => 0x550b, + 0x48 => 0x5701, 0x49 => 0x5702, 0x4a => 0x57cc, 0x4b => 0x5832, + 0x4c => 0x57d5, 0x4d => 0x57d2, 0x4e => 0x57ba, 0x4f => 0x57c6, + 0x50 => 0x57bd, 0x51 => 0x57bc, 0x52 => 0x57b8, 0x53 => 0x57b6, + 0x54 => 0x57bf, 0x55 => 0x57c7, 0x56 => 0x57d0, 0x57 => 0x57b9, + 0x58 => 0x57c1, 0x59 => 0x590e, 0x5a => 0x594a, 0x5b => 0x5a19, + 0x5c => 0x5a16, 0x5d => 0x5a2d, 0x5e => 0x5a2e, 0x5f => 0x5a15, + 0x60 => 0x5a0f, 0x61 => 0x5a17, 0x62 => 0x5a0a, 0x63 => 0x5a1e, + 0x64 => 0x5a33, 0x65 => 0x5b6c, 0x66 => 0x5ba7, 0x67 => 0x5bad, + 0x68 => 0x5bac, 0x69 => 0x5c03, 0x6a => 0x5c56, 0x6b => 0x5c54, + 0x6c => 0x5cec, 0x6d => 0x5cff, 0x6e => 0x5cee, 0x6f => 0x5cf1, + 0x70 => 0x5cf7, 0x71 => 0x5d00, 0x72 => 0x5cf9, 0x73 => 0x5e29, + 0x74 => 0x5e28, 0x75 => 0x5ea8, 0x76 => 0x5eae, 0x77 => 0x5eaa, + 0x78 => 0x5eac, 0x79 => 0x5f33, 0x7a => 0x5f30, 0x7b => 0x5f67, + 0x7c => 0x605d, 0x7d => 0x605a, 0x7e => 0x6067, 0xa1 => 0x6041, + 0xa2 => 0x60a2, 0xa3 => 0x6088, 0xa4 => 0x6080, 0xa5 => 0x6092, + 0xa6 => 0x6081, 0xa7 => 0x609d, 0xa8 => 0x6083, 0xa9 => 0x6095, + 0xaa => 0x609b, 0xab => 0x6097, 0xac => 0x6087, 0xad => 0x609c, + 0xae => 0x608e, 0xaf => 0x6219, 0xb0 => 0x6246, 0xb1 => 0x62f2, + 0xb2 => 0x6310, 0xb3 => 0x6356, 0xb4 => 0x632c, 0xb5 => 0x6344, + 0xb6 => 0x6345, 0xb7 => 0x6336, 0xb8 => 0x6343, 0xb9 => 0x63e4, + 0xba => 0x6339, 0xbb => 0x634b, 0xbc => 0x634a, 0xbd => 0x633c, + 0xbe => 0x6329, 0xbf => 0x6341, 0xc0 => 0x6334, 0xc1 => 0x6358, + 0xc2 => 0x6354, 0xc3 => 0x6359, 0xc4 => 0x632d, 0xc5 => 0x6347, + 0xc6 => 0x6333, 0xc7 => 0x635a, 0xc8 => 0x6351, 0xc9 => 0x6338, + 0xca => 0x6357, 0xcb => 0x6340, 0xcc => 0x6348, 0xcd => 0x654a, + 0xce => 0x6546, 0xcf => 0x65c6, 0xd0 => 0x65c3, 0xd1 => 0x65c4, + 0xd2 => 0x65c2, 0xd3 => 0x664a, 0xd4 => 0x665f, 0xd5 => 0x6647, + 0xd6 => 0x6651, 0xd7 => 0x6712, 0xd8 => 0x6713, 0xd9 => 0x681f, + 0xda => 0x681a, 0xdb => 0x6849, 0xdc => 0x6832, 0xdd => 0x6833, + 0xde => 0x683b, 0xdf => 0x684b, 0xe0 => 0x684f, 0xe1 => 0x6816, + 0xe2 => 0x6831, 0xe3 => 0x681c, 0xe4 => 0x6835, 0xe5 => 0x682b, + 0xe6 => 0x682d, 0xe7 => 0x682f, 0xe8 => 0x684e, 0xe9 => 0x6844, + 0xea => 0x6834, 0xeb => 0x681d, 0xec => 0x6812, 0xed => 0x6814, + 0xee => 0x6826, 0xef => 0x6828, 0xf0 => 0x682e, 0xf1 => 0x684d, + 0xf2 => 0x683a, 0xf3 => 0x6825, 0xf4 => 0x6820, 0xf5 => 0x6b2c, + 0xf6 => 0x6b2f, 0xf7 => 0x6b2d, 0xf8 => 0x6b31, 0xf9 => 0x6b34, + 0xfa => 0x6b6d, 0xfb => 0x8082, 0xfc => 0x6b88, 0xfd => 0x6be6, + 0xfe => 0x6be4, + }, + 0xd2 => { + 0x40 => 0x6be8, 0x41 => 0x6be3, 0x42 => 0x6be2, 0x43 => 0x6be7, + 0x44 => 0x6c25, 0x45 => 0x6d7a, 0x46 => 0x6d63, 0x47 => 0x6d64, + 0x48 => 0x6d76, 0x49 => 0x6d0d, 0x4a => 0x6d61, 0x4b => 0x6d92, + 0x4c => 0x6d58, 0x4d => 0x6d62, 0x4e => 0x6d6d, 0x4f => 0x6d6f, + 0x50 => 0x6d91, 0x51 => 0x6d8d, 0x52 => 0x6def, 0x53 => 0x6d7f, + 0x54 => 0x6d86, 0x55 => 0x6d5e, 0x56 => 0x6d67, 0x57 => 0x6d60, + 0x58 => 0x6d97, 0x59 => 0x6d70, 0x5a => 0x6d7c, 0x5b => 0x6d5f, + 0x5c => 0x6d82, 0x5d => 0x6d98, 0x5e => 0x6d2f, 0x5f => 0x6d68, + 0x60 => 0x6d8b, 0x61 => 0x6d7e, 0x62 => 0x6d80, 0x63 => 0x6d84, + 0x64 => 0x6d16, 0x65 => 0x6d83, 0x66 => 0x6d7b, 0x67 => 0x6d7d, + 0x68 => 0x6d75, 0x69 => 0x6d90, 0x6a => 0x70dc, 0x6b => 0x70d3, + 0x6c => 0x70d1, 0x6d => 0x70dd, 0x6e => 0x70cb, 0x6f => 0x7f39, + 0x70 => 0x70e2, 0x71 => 0x70d7, 0x72 => 0x70d2, 0x73 => 0x70de, + 0x74 => 0x70e0, 0x75 => 0x70d4, 0x76 => 0x70cd, 0x77 => 0x70c5, + 0x78 => 0x70c6, 0x79 => 0x70c7, 0x7a => 0x70da, 0x7b => 0x70ce, + 0x7c => 0x70e1, 0x7d => 0x7242, 0x7e => 0x7278, 0xa1 => 0x7277, + 0xa2 => 0x7276, 0xa3 => 0x7300, 0xa4 => 0x72fa, 0xa5 => 0x72f4, + 0xa6 => 0x72fe, 0xa7 => 0x72f6, 0xa8 => 0x72f3, 0xa9 => 0x72fb, + 0xaa => 0x7301, 0xab => 0x73d3, 0xac => 0x73d9, 0xad => 0x73e5, + 0xae => 0x73d6, 0xaf => 0x73bc, 0xb0 => 0x73e7, 0xb1 => 0x73e3, + 0xb2 => 0x73e9, 0xb3 => 0x73dc, 0xb4 => 0x73d2, 0xb5 => 0x73db, + 0xb6 => 0x73d4, 0xb7 => 0x73dd, 0xb8 => 0x73da, 0xb9 => 0x73d7, + 0xba => 0x73d8, 0xbb => 0x73e8, 0xbc => 0x74de, 0xbd => 0x74df, + 0xbe => 0x74f4, 0xbf => 0x74f5, 0xc0 => 0x7521, 0xc1 => 0x755b, + 0xc2 => 0x755f, 0xc3 => 0x75b0, 0xc4 => 0x75c1, 0xc5 => 0x75bb, + 0xc6 => 0x75c4, 0xc7 => 0x75c0, 0xc8 => 0x75bf, 0xc9 => 0x75b6, + 0xca => 0x75ba, 0xcb => 0x768a, 0xcc => 0x76c9, 0xcd => 0x771d, + 0xce => 0x771b, 0xcf => 0x7710, 0xd0 => 0x7713, 0xd1 => 0x7712, + 0xd2 => 0x7723, 0xd3 => 0x7711, 0xd4 => 0x7715, 0xd5 => 0x7719, + 0xd6 => 0x771a, 0xd7 => 0x7722, 0xd8 => 0x7727, 0xd9 => 0x7823, + 0xda => 0x782c, 0xdb => 0x7822, 0xdc => 0x7835, 0xdd => 0x782f, + 0xde => 0x7828, 0xdf => 0x782e, 0xe0 => 0x782b, 0xe1 => 0x7821, + 0xe2 => 0x7829, 0xe3 => 0x7833, 0xe4 => 0x782a, 0xe5 => 0x7831, + 0xe6 => 0x7954, 0xe7 => 0x795b, 0xe8 => 0x794f, 0xe9 => 0x795c, + 0xea => 0x7953, 0xeb => 0x7952, 0xec => 0x7951, 0xed => 0x79eb, + 0xee => 0x79ec, 0xef => 0x79e0, 0xf0 => 0x79ee, 0xf1 => 0x79ed, + 0xf2 => 0x79ea, 0xf3 => 0x79dc, 0xf4 => 0x79de, 0xf5 => 0x79dd, + 0xf6 => 0x7a86, 0xf7 => 0x7a89, 0xf8 => 0x7a85, 0xf9 => 0x7a8b, + 0xfa => 0x7a8c, 0xfb => 0x7a8a, 0xfc => 0x7a87, 0xfd => 0x7ad8, + 0xfe => 0x7b10, + }, + 0xd3 => { + 0x40 => 0x7b04, 0x41 => 0x7b13, 0x42 => 0x7b05, 0x43 => 0x7b0f, + 0x44 => 0x7b08, 0x45 => 0x7b0a, 0x46 => 0x7b0e, 0x47 => 0x7b09, + 0x48 => 0x7b12, 0x49 => 0x7c84, 0x4a => 0x7c91, 0x4b => 0x7c8a, + 0x4c => 0x7c8c, 0x4d => 0x7c88, 0x4e => 0x7c8d, 0x4f => 0x7c85, + 0x50 => 0x7d1e, 0x51 => 0x7d1d, 0x52 => 0x7d11, 0x53 => 0x7d0e, + 0x54 => 0x7d18, 0x55 => 0x7d16, 0x56 => 0x7d13, 0x57 => 0x7d1f, + 0x58 => 0x7d12, 0x59 => 0x7d0f, 0x5a => 0x7d0c, 0x5b => 0x7f5c, + 0x5c => 0x7f61, 0x5d => 0x7f5e, 0x5e => 0x7f60, 0x5f => 0x7f5d, + 0x60 => 0x7f5b, 0x61 => 0x7f96, 0x62 => 0x7f92, 0x63 => 0x7fc3, + 0x64 => 0x7fc2, 0x65 => 0x7fc0, 0x66 => 0x8016, 0x67 => 0x803e, + 0x68 => 0x8039, 0x69 => 0x80fa, 0x6a => 0x80f2, 0x6b => 0x80f9, + 0x6c => 0x80f5, 0x6d => 0x8101, 0x6e => 0x80fb, 0x6f => 0x8100, + 0x70 => 0x8201, 0x71 => 0x822f, 0x72 => 0x8225, 0x73 => 0x8333, + 0x74 => 0x832d, 0x75 => 0x8344, 0x76 => 0x8319, 0x77 => 0x8351, + 0x78 => 0x8325, 0x79 => 0x8356, 0x7a => 0x833f, 0x7b => 0x8341, + 0x7c => 0x8326, 0x7d => 0x831c, 0x7e => 0x8322, 0xa1 => 0x8342, + 0xa2 => 0x834e, 0xa3 => 0x831b, 0xa4 => 0x832a, 0xa5 => 0x8308, + 0xa6 => 0x833c, 0xa7 => 0x834d, 0xa8 => 0x8316, 0xa9 => 0x8324, + 0xaa => 0x8320, 0xab => 0x8337, 0xac => 0x832f, 0xad => 0x8329, + 0xae => 0x8347, 0xaf => 0x8345, 0xb0 => 0x834c, 0xb1 => 0x8353, + 0xb2 => 0x831e, 0xb3 => 0x832c, 0xb4 => 0x834b, 0xb5 => 0x8327, + 0xb6 => 0x8348, 0xb7 => 0x8653, 0xb8 => 0x8652, 0xb9 => 0x86a2, + 0xba => 0x86a8, 0xbb => 0x8696, 0xbc => 0x868d, 0xbd => 0x8691, + 0xbe => 0x869e, 0xbf => 0x8687, 0xc0 => 0x8697, 0xc1 => 0x8686, + 0xc2 => 0x868b, 0xc3 => 0x869a, 0xc4 => 0x8685, 0xc5 => 0x86a5, + 0xc6 => 0x8699, 0xc7 => 0x86a1, 0xc8 => 0x86a7, 0xc9 => 0x8695, + 0xca => 0x8698, 0xcb => 0x868e, 0xcc => 0x869d, 0xcd => 0x8690, + 0xce => 0x8694, 0xcf => 0x8843, 0xd0 => 0x8844, 0xd1 => 0x886d, + 0xd2 => 0x8875, 0xd3 => 0x8876, 0xd4 => 0x8872, 0xd5 => 0x8880, + 0xd6 => 0x8871, 0xd7 => 0x887f, 0xd8 => 0x886f, 0xd9 => 0x8883, + 0xda => 0x887e, 0xdb => 0x8874, 0xdc => 0x887c, 0xdd => 0x8a12, + 0xde => 0x8c47, 0xdf => 0x8c57, 0xe0 => 0x8c7b, 0xe1 => 0x8ca4, + 0xe2 => 0x8ca3, 0xe3 => 0x8d76, 0xe4 => 0x8d78, 0xe5 => 0x8db5, + 0xe6 => 0x8db7, 0xe7 => 0x8db6, 0xe8 => 0x8ed1, 0xe9 => 0x8ed3, + 0xea => 0x8ffe, 0xeb => 0x8ff5, 0xec => 0x9002, 0xed => 0x8fff, + 0xee => 0x8ffb, 0xef => 0x9004, 0xf0 => 0x8ffc, 0xf1 => 0x8ff6, + 0xf2 => 0x90d6, 0xf3 => 0x90e0, 0xf4 => 0x90d9, 0xf5 => 0x90da, + 0xf6 => 0x90e3, 0xf7 => 0x90df, 0xf8 => 0x90e5, 0xf9 => 0x90d8, + 0xfa => 0x90db, 0xfb => 0x90d7, 0xfc => 0x90dc, 0xfd => 0x90e4, + 0xfe => 0x9150, + }, + 0xd4 => { + 0x40 => 0x914e, 0x41 => 0x914f, 0x42 => 0x91d5, 0x43 => 0x91e2, + 0x44 => 0x91da, 0x45 => 0x965c, 0x46 => 0x965f, 0x47 => 0x96bc, + 0x48 => 0x98e3, 0x49 => 0x9adf, 0x4a => 0x9b2f, 0x4b => 0x4e7f, + 0x4c => 0x5070, 0x4d => 0x506a, 0x4e => 0x5061, 0x4f => 0x505e, + 0x50 => 0x5060, 0x51 => 0x5053, 0x52 => 0x504b, 0x53 => 0x505d, + 0x54 => 0x5072, 0x55 => 0x5048, 0x56 => 0x504d, 0x57 => 0x5041, + 0x58 => 0x505b, 0x59 => 0x504a, 0x5a => 0x5062, 0x5b => 0x5015, + 0x5c => 0x5045, 0x5d => 0x505f, 0x5e => 0x5069, 0x5f => 0x506b, + 0x60 => 0x5063, 0x61 => 0x5064, 0x62 => 0x5046, 0x63 => 0x5040, + 0x64 => 0x506e, 0x65 => 0x5073, 0x66 => 0x5057, 0x67 => 0x5051, + 0x68 => 0x51d0, 0x69 => 0x526b, 0x6a => 0x526d, 0x6b => 0x526c, + 0x6c => 0x526e, 0x6d => 0x52d6, 0x6e => 0x52d3, 0x6f => 0x532d, + 0x70 => 0x539c, 0x71 => 0x5575, 0x72 => 0x5576, 0x73 => 0x553c, + 0x74 => 0x554d, 0x75 => 0x5550, 0x76 => 0x5534, 0x77 => 0x552a, + 0x78 => 0x5551, 0x79 => 0x5562, 0x7a => 0x5536, 0x7b => 0x5535, + 0x7c => 0x5530, 0x7d => 0x5552, 0x7e => 0x5545, 0xa1 => 0x550c, + 0xa2 => 0x5532, 0xa3 => 0x5565, 0xa4 => 0x554e, 0xa5 => 0x5539, + 0xa6 => 0x5548, 0xa7 => 0x552d, 0xa8 => 0x553b, 0xa9 => 0x5540, + 0xaa => 0x554b, 0xab => 0x570a, 0xac => 0x5707, 0xad => 0x57fb, + 0xae => 0x5814, 0xaf => 0x57e2, 0xb0 => 0x57f6, 0xb1 => 0x57dc, + 0xb2 => 0x57f4, 0xb3 => 0x5800, 0xb4 => 0x57ed, 0xb5 => 0x57fd, + 0xb6 => 0x5808, 0xb7 => 0x57f8, 0xb8 => 0x580b, 0xb9 => 0x57f3, + 0xba => 0x57cf, 0xbb => 0x5807, 0xbc => 0x57ee, 0xbd => 0x57e3, + 0xbe => 0x57f2, 0xbf => 0x57e5, 0xc0 => 0x57ec, 0xc1 => 0x57e1, + 0xc2 => 0x580e, 0xc3 => 0x57fc, 0xc4 => 0x5810, 0xc5 => 0x57e7, + 0xc6 => 0x5801, 0xc7 => 0x580c, 0xc8 => 0x57f1, 0xc9 => 0x57e9, + 0xca => 0x57f0, 0xcb => 0x580d, 0xcc => 0x5804, 0xcd => 0x595c, + 0xce => 0x5a60, 0xcf => 0x5a58, 0xd0 => 0x5a55, 0xd1 => 0x5a67, + 0xd2 => 0x5a5e, 0xd3 => 0x5a38, 0xd4 => 0x5a35, 0xd5 => 0x5a6d, + 0xd6 => 0x5a50, 0xd7 => 0x5a5f, 0xd8 => 0x5a65, 0xd9 => 0x5a6c, + 0xda => 0x5a53, 0xdb => 0x5a64, 0xdc => 0x5a57, 0xdd => 0x5a43, + 0xde => 0x5a5d, 0xdf => 0x5a52, 0xe0 => 0x5a44, 0xe1 => 0x5a5b, + 0xe2 => 0x5a48, 0xe3 => 0x5a8e, 0xe4 => 0x5a3e, 0xe5 => 0x5a4d, + 0xe6 => 0x5a39, 0xe7 => 0x5a4c, 0xe8 => 0x5a70, 0xe9 => 0x5a69, + 0xea => 0x5a47, 0xeb => 0x5a51, 0xec => 0x5a56, 0xed => 0x5a42, + 0xee => 0x5a5c, 0xef => 0x5b72, 0xf0 => 0x5b6e, 0xf1 => 0x5bc1, + 0xf2 => 0x5bc0, 0xf3 => 0x5c59, 0xf4 => 0x5d1e, 0xf5 => 0x5d0b, + 0xf6 => 0x5d1d, 0xf7 => 0x5d1a, 0xf8 => 0x5d20, 0xf9 => 0x5d0c, + 0xfa => 0x5d28, 0xfb => 0x5d0d, 0xfc => 0x5d26, 0xfd => 0x5d25, + 0xfe => 0x5d0f, + }, + 0xd5 => { + 0x40 => 0x5d30, 0x41 => 0x5d12, 0x42 => 0x5d23, 0x43 => 0x5d1f, + 0x44 => 0x5d2e, 0x45 => 0x5e3e, 0x46 => 0x5e34, 0x47 => 0x5eb1, + 0x48 => 0x5eb4, 0x49 => 0x5eb9, 0x4a => 0x5eb2, 0x4b => 0x5eb3, + 0x4c => 0x5f36, 0x4d => 0x5f38, 0x4e => 0x5f9b, 0x4f => 0x5f96, + 0x50 => 0x5f9f, 0x51 => 0x608a, 0x52 => 0x6090, 0x53 => 0x6086, + 0x54 => 0x60be, 0x55 => 0x60b0, 0x56 => 0x60ba, 0x57 => 0x60d3, + 0x58 => 0x60d4, 0x59 => 0x60cf, 0x5a => 0x60e4, 0x5b => 0x60d9, + 0x5c => 0x60dd, 0x5d => 0x60c8, 0x5e => 0x60b1, 0x5f => 0x60db, + 0x60 => 0x60b7, 0x61 => 0x60ca, 0x62 => 0x60bf, 0x63 => 0x60c3, + 0x64 => 0x60cd, 0x65 => 0x60c0, 0x66 => 0x6332, 0x67 => 0x6365, + 0x68 => 0x638a, 0x69 => 0x6382, 0x6a => 0x637d, 0x6b => 0x63bd, + 0x6c => 0x639e, 0x6d => 0x63ad, 0x6e => 0x639d, 0x6f => 0x6397, + 0x70 => 0x63ab, 0x71 => 0x638e, 0x72 => 0x636f, 0x73 => 0x6387, + 0x74 => 0x6390, 0x75 => 0x636e, 0x76 => 0x63af, 0x77 => 0x6375, + 0x78 => 0x639c, 0x79 => 0x636d, 0x7a => 0x63ae, 0x7b => 0x637c, + 0x7c => 0x63a4, 0x7d => 0x633b, 0x7e => 0x639f, 0xa1 => 0x6378, + 0xa2 => 0x6385, 0xa3 => 0x6381, 0xa4 => 0x6391, 0xa5 => 0x638d, + 0xa6 => 0x6370, 0xa7 => 0x6553, 0xa8 => 0x65cd, 0xa9 => 0x6665, + 0xaa => 0x6661, 0xab => 0x665b, 0xac => 0x6659, 0xad => 0x665c, + 0xae => 0x6662, 0xaf => 0x6718, 0xb0 => 0x6879, 0xb1 => 0x6887, + 0xb2 => 0x6890, 0xb3 => 0x689c, 0xb4 => 0x686d, 0xb5 => 0x686e, + 0xb6 => 0x68ae, 0xb7 => 0x68ab, 0xb8 => 0x6956, 0xb9 => 0x686f, + 0xba => 0x68a3, 0xbb => 0x68ac, 0xbc => 0x68a9, 0xbd => 0x6875, + 0xbe => 0x6874, 0xbf => 0x68b2, 0xc0 => 0x688f, 0xc1 => 0x6877, + 0xc2 => 0x6892, 0xc3 => 0x687c, 0xc4 => 0x686b, 0xc5 => 0x6872, + 0xc6 => 0x68aa, 0xc7 => 0x6880, 0xc8 => 0x6871, 0xc9 => 0x687e, + 0xca => 0x689b, 0xcb => 0x6896, 0xcc => 0x688b, 0xcd => 0x68a0, + 0xce => 0x6889, 0xcf => 0x68a4, 0xd0 => 0x6878, 0xd1 => 0x687b, + 0xd2 => 0x6891, 0xd3 => 0x688c, 0xd4 => 0x688a, 0xd5 => 0x687d, + 0xd6 => 0x6b36, 0xd7 => 0x6b33, 0xd8 => 0x6b37, 0xd9 => 0x6b38, + 0xda => 0x6b91, 0xdb => 0x6b8f, 0xdc => 0x6b8d, 0xdd => 0x6b8e, + 0xde => 0x6b8c, 0xdf => 0x6c2a, 0xe0 => 0x6dc0, 0xe1 => 0x6dab, + 0xe2 => 0x6db4, 0xe3 => 0x6db3, 0xe4 => 0x6e74, 0xe5 => 0x6dac, + 0xe6 => 0x6de9, 0xe7 => 0x6de2, 0xe8 => 0x6db7, 0xe9 => 0x6df6, + 0xea => 0x6dd4, 0xeb => 0x6e00, 0xec => 0x6dc8, 0xed => 0x6de0, + 0xee => 0x6ddf, 0xef => 0x6dd6, 0xf0 => 0x6dbe, 0xf1 => 0x6de5, + 0xf2 => 0x6ddc, 0xf3 => 0x6ddd, 0xf4 => 0x6ddb, 0xf5 => 0x6df4, + 0xf6 => 0x6dca, 0xf7 => 0x6dbd, 0xf8 => 0x6ded, 0xf9 => 0x6df0, + 0xfa => 0x6dba, 0xfb => 0x6dd5, 0xfc => 0x6dc2, 0xfd => 0x6dcf, + 0xfe => 0x6dc9, + }, + 0xd6 => { + 0x40 => 0x6dd0, 0x41 => 0x6df2, 0x42 => 0x6dd3, 0x43 => 0x6dfd, + 0x44 => 0x6dd7, 0x45 => 0x6dcd, 0x46 => 0x6de3, 0x47 => 0x6dbb, + 0x48 => 0x70fa, 0x49 => 0x710d, 0x4a => 0x70f7, 0x4b => 0x7117, + 0x4c => 0x70f4, 0x4d => 0x710c, 0x4e => 0x70f0, 0x4f => 0x7104, + 0x50 => 0x70f3, 0x51 => 0x7110, 0x52 => 0x70fc, 0x53 => 0x70ff, + 0x54 => 0x7106, 0x55 => 0x7113, 0x56 => 0x7100, 0x57 => 0x70f8, + 0x58 => 0x70f6, 0x59 => 0x710b, 0x5a => 0x7102, 0x5b => 0x710e, + 0x5c => 0x727e, 0x5d => 0x727b, 0x5e => 0x727c, 0x5f => 0x727f, + 0x60 => 0x731d, 0x61 => 0x7317, 0x62 => 0x7307, 0x63 => 0x7311, + 0x64 => 0x7318, 0x65 => 0x730a, 0x66 => 0x7308, 0x67 => 0x72ff, + 0x68 => 0x730f, 0x69 => 0x731e, 0x6a => 0x7388, 0x6b => 0x73f6, + 0x6c => 0x73f8, 0x6d => 0x73f5, 0x6e => 0x7404, 0x6f => 0x7401, + 0x70 => 0x73fd, 0x71 => 0x7407, 0x72 => 0x7400, 0x73 => 0x73fa, + 0x74 => 0x73fc, 0x75 => 0x73ff, 0x76 => 0x740c, 0x77 => 0x740b, + 0x78 => 0x73f4, 0x79 => 0x7408, 0x7a => 0x7564, 0x7b => 0x7563, + 0x7c => 0x75ce, 0x7d => 0x75d2, 0x7e => 0x75cf, 0xa1 => 0x75cb, + 0xa2 => 0x75cc, 0xa3 => 0x75d1, 0xa4 => 0x75d0, 0xa5 => 0x768f, + 0xa6 => 0x7689, 0xa7 => 0x76d3, 0xa8 => 0x7739, 0xa9 => 0x772f, + 0xaa => 0x772d, 0xab => 0x7731, 0xac => 0x7732, 0xad => 0x7734, + 0xae => 0x7733, 0xaf => 0x773d, 0xb0 => 0x7725, 0xb1 => 0x773b, + 0xb2 => 0x7735, 0xb3 => 0x7848, 0xb4 => 0x7852, 0xb5 => 0x7849, + 0xb6 => 0x784d, 0xb7 => 0x784a, 0xb8 => 0x784c, 0xb9 => 0x7826, + 0xba => 0x7845, 0xbb => 0x7850, 0xbc => 0x7964, 0xbd => 0x7967, + 0xbe => 0x7969, 0xbf => 0x796a, 0xc0 => 0x7963, 0xc1 => 0x796b, + 0xc2 => 0x7961, 0xc3 => 0x79bb, 0xc4 => 0x79fa, 0xc5 => 0x79f8, + 0xc6 => 0x79f6, 0xc7 => 0x79f7, 0xc8 => 0x7a8f, 0xc9 => 0x7a94, + 0xca => 0x7a90, 0xcb => 0x7b35, 0xcc => 0x7b47, 0xcd => 0x7b34, + 0xce => 0x7b25, 0xcf => 0x7b30, 0xd0 => 0x7b22, 0xd1 => 0x7b24, + 0xd2 => 0x7b33, 0xd3 => 0x7b18, 0xd4 => 0x7b2a, 0xd5 => 0x7b1d, + 0xd6 => 0x7b31, 0xd7 => 0x7b2b, 0xd8 => 0x7b2d, 0xd9 => 0x7b2f, + 0xda => 0x7b32, 0xdb => 0x7b38, 0xdc => 0x7b1a, 0xdd => 0x7b23, + 0xde => 0x7c94, 0xdf => 0x7c98, 0xe0 => 0x7c96, 0xe1 => 0x7ca3, + 0xe2 => 0x7d35, 0xe3 => 0x7d3d, 0xe4 => 0x7d38, 0xe5 => 0x7d36, + 0xe6 => 0x7d3a, 0xe7 => 0x7d45, 0xe8 => 0x7d2c, 0xe9 => 0x7d29, + 0xea => 0x7d41, 0xeb => 0x7d47, 0xec => 0x7d3e, 0xed => 0x7d3f, + 0xee => 0x7d4a, 0xef => 0x7d3b, 0xf0 => 0x7d28, 0xf1 => 0x7f63, + 0xf2 => 0x7f95, 0xf3 => 0x7f9c, 0xf4 => 0x7f9d, 0xf5 => 0x7f9b, + 0xf6 => 0x7fca, 0xf7 => 0x7fcb, 0xf8 => 0x7fcd, 0xf9 => 0x7fd0, + 0xfa => 0x7fd1, 0xfb => 0x7fc7, 0xfc => 0x7fcf, 0xfd => 0x7fc9, + 0xfe => 0x801f, + }, + 0xd7 => { + 0x40 => 0x801e, 0x41 => 0x801b, 0x42 => 0x8047, 0x43 => 0x8043, + 0x44 => 0x8048, 0x45 => 0x8118, 0x46 => 0x8125, 0x47 => 0x8119, + 0x48 => 0x811b, 0x49 => 0x812d, 0x4a => 0x811f, 0x4b => 0x812c, + 0x4c => 0x811e, 0x4d => 0x8121, 0x4e => 0x8115, 0x4f => 0x8127, + 0x50 => 0x811d, 0x51 => 0x8122, 0x52 => 0x8211, 0x53 => 0x8238, + 0x54 => 0x8233, 0x55 => 0x823a, 0x56 => 0x8234, 0x57 => 0x8232, + 0x58 => 0x8274, 0x59 => 0x8390, 0x5a => 0x83a3, 0x5b => 0x83a8, + 0x5c => 0x838d, 0x5d => 0x837a, 0x5e => 0x8373, 0x5f => 0x83a4, + 0x60 => 0x8374, 0x61 => 0x838f, 0x62 => 0x8381, 0x63 => 0x8395, + 0x64 => 0x8399, 0x65 => 0x8375, 0x66 => 0x8394, 0x67 => 0x83a9, + 0x68 => 0x837d, 0x69 => 0x8383, 0x6a => 0x838c, 0x6b => 0x839d, + 0x6c => 0x839b, 0x6d => 0x83aa, 0x6e => 0x838b, 0x6f => 0x837e, + 0x70 => 0x83a5, 0x71 => 0x83af, 0x72 => 0x8388, 0x73 => 0x8397, + 0x74 => 0x83b0, 0x75 => 0x837f, 0x76 => 0x83a6, 0x77 => 0x8387, + 0x78 => 0x83ae, 0x79 => 0x8376, 0x7a => 0x839a, 0x7b => 0x8659, + 0x7c => 0x8656, 0x7d => 0x86bf, 0x7e => 0x86b7, 0xa1 => 0x86c2, + 0xa2 => 0x86c1, 0xa3 => 0x86c5, 0xa4 => 0x86ba, 0xa5 => 0x86b0, + 0xa6 => 0x86c8, 0xa7 => 0x86b9, 0xa8 => 0x86b3, 0xa9 => 0x86b8, + 0xaa => 0x86cc, 0xab => 0x86b4, 0xac => 0x86bb, 0xad => 0x86bc, + 0xae => 0x86c3, 0xaf => 0x86bd, 0xb0 => 0x86be, 0xb1 => 0x8852, + 0xb2 => 0x8889, 0xb3 => 0x8895, 0xb4 => 0x88a8, 0xb5 => 0x88a2, + 0xb6 => 0x88aa, 0xb7 => 0x889a, 0xb8 => 0x8891, 0xb9 => 0x88a1, + 0xba => 0x889f, 0xbb => 0x8898, 0xbc => 0x88a7, 0xbd => 0x8899, + 0xbe => 0x889b, 0xbf => 0x8897, 0xc0 => 0x88a4, 0xc1 => 0x88ac, + 0xc2 => 0x888c, 0xc3 => 0x8893, 0xc4 => 0x888e, 0xc5 => 0x8982, + 0xc6 => 0x89d6, 0xc7 => 0x89d9, 0xc8 => 0x89d5, 0xc9 => 0x8a30, + 0xca => 0x8a27, 0xcb => 0x8a2c, 0xcc => 0x8a1e, 0xcd => 0x8c39, + 0xce => 0x8c3b, 0xcf => 0x8c5c, 0xd0 => 0x8c5d, 0xd1 => 0x8c7d, + 0xd2 => 0x8ca5, 0xd3 => 0x8d7d, 0xd4 => 0x8d7b, 0xd5 => 0x8d79, + 0xd6 => 0x8dbc, 0xd7 => 0x8dc2, 0xd8 => 0x8db9, 0xd9 => 0x8dbf, + 0xda => 0x8dc1, 0xdb => 0x8ed8, 0xdc => 0x8ede, 0xdd => 0x8edd, + 0xde => 0x8edc, 0xdf => 0x8ed7, 0xe0 => 0x8ee0, 0xe1 => 0x8ee1, + 0xe2 => 0x9024, 0xe3 => 0x900b, 0xe4 => 0x9011, 0xe5 => 0x901c, + 0xe6 => 0x900c, 0xe7 => 0x9021, 0xe8 => 0x90ef, 0xe9 => 0x90ea, + 0xea => 0x90f0, 0xeb => 0x90f4, 0xec => 0x90f2, 0xed => 0x90f3, + 0xee => 0x90d4, 0xef => 0x90eb, 0xf0 => 0x90ec, 0xf1 => 0x90e9, + 0xf2 => 0x9156, 0xf3 => 0x9158, 0xf4 => 0x915a, 0xf5 => 0x9153, + 0xf6 => 0x9155, 0xf7 => 0x91ec, 0xf8 => 0x91f4, 0xf9 => 0x91f1, + 0xfa => 0x91f3, 0xfb => 0x91f8, 0xfc => 0x91e4, 0xfd => 0x91f9, + 0xfe => 0x91ea, + }, + 0xd8 => { + 0x40 => 0x91eb, 0x41 => 0x91f7, 0x42 => 0x91e8, 0x43 => 0x91ee, + 0x44 => 0x957a, 0x45 => 0x9586, 0x46 => 0x9588, 0x47 => 0x967c, + 0x48 => 0x966d, 0x49 => 0x966b, 0x4a => 0x9671, 0x4b => 0x966f, + 0x4c => 0x96bf, 0x4d => 0x976a, 0x4e => 0x9804, 0x4f => 0x98e5, + 0x50 => 0x9997, 0x51 => 0x509b, 0x52 => 0x5095, 0x53 => 0x5094, + 0x54 => 0x509e, 0x55 => 0x508b, 0x56 => 0x50a3, 0x57 => 0x5083, + 0x58 => 0x508c, 0x59 => 0x508e, 0x5a => 0x509d, 0x5b => 0x5068, + 0x5c => 0x509c, 0x5d => 0x5092, 0x5e => 0x5082, 0x5f => 0x5087, + 0x60 => 0x515f, 0x61 => 0x51d4, 0x62 => 0x5312, 0x63 => 0x5311, + 0x64 => 0x53a4, 0x65 => 0x53a7, 0x66 => 0x5591, 0x67 => 0x55a8, + 0x68 => 0x55a5, 0x69 => 0x55ad, 0x6a => 0x5577, 0x6b => 0x5645, + 0x6c => 0x55a2, 0x6d => 0x5593, 0x6e => 0x5588, 0x6f => 0x558f, + 0x70 => 0x55b5, 0x71 => 0x5581, 0x72 => 0x55a3, 0x73 => 0x5592, + 0x74 => 0x55a4, 0x75 => 0x557d, 0x76 => 0x558c, 0x77 => 0x55a6, + 0x78 => 0x557f, 0x79 => 0x5595, 0x7a => 0x55a1, 0x7b => 0x558e, + 0x7c => 0x570c, 0x7d => 0x5829, 0x7e => 0x5837, 0xa1 => 0x5819, + 0xa2 => 0x581e, 0xa3 => 0x5827, 0xa4 => 0x5823, 0xa5 => 0x5828, + 0xa6 => 0x57f5, 0xa7 => 0x5848, 0xa8 => 0x5825, 0xa9 => 0x581c, + 0xaa => 0x581b, 0xab => 0x5833, 0xac => 0x583f, 0xad => 0x5836, + 0xae => 0x582e, 0xaf => 0x5839, 0xb0 => 0x5838, 0xb1 => 0x582d, + 0xb2 => 0x582c, 0xb3 => 0x583b, 0xb4 => 0x5961, 0xb5 => 0x5aaf, + 0xb6 => 0x5a94, 0xb7 => 0x5a9f, 0xb8 => 0x5a7a, 0xb9 => 0x5aa2, + 0xba => 0x5a9e, 0xbb => 0x5a78, 0xbc => 0x5aa6, 0xbd => 0x5a7c, + 0xbe => 0x5aa5, 0xbf => 0x5aac, 0xc0 => 0x5a95, 0xc1 => 0x5aae, + 0xc2 => 0x5a37, 0xc3 => 0x5a84, 0xc4 => 0x5a8a, 0xc5 => 0x5a97, + 0xc6 => 0x5a83, 0xc7 => 0x5a8b, 0xc8 => 0x5aa9, 0xc9 => 0x5a7b, + 0xca => 0x5a7d, 0xcb => 0x5a8c, 0xcc => 0x5a9c, 0xcd => 0x5a8f, + 0xce => 0x5a93, 0xcf => 0x5a9d, 0xd0 => 0x5bea, 0xd1 => 0x5bcd, + 0xd2 => 0x5bcb, 0xd3 => 0x5bd4, 0xd4 => 0x5bd1, 0xd5 => 0x5bca, + 0xd6 => 0x5bce, 0xd7 => 0x5c0c, 0xd8 => 0x5c30, 0xd9 => 0x5d37, + 0xda => 0x5d43, 0xdb => 0x5d6b, 0xdc => 0x5d41, 0xdd => 0x5d4b, + 0xde => 0x5d3f, 0xdf => 0x5d35, 0xe0 => 0x5d51, 0xe1 => 0x5d4e, + 0xe2 => 0x5d55, 0xe3 => 0x5d33, 0xe4 => 0x5d3a, 0xe5 => 0x5d52, + 0xe6 => 0x5d3d, 0xe7 => 0x5d31, 0xe8 => 0x5d59, 0xe9 => 0x5d42, + 0xea => 0x5d39, 0xeb => 0x5d49, 0xec => 0x5d38, 0xed => 0x5d3c, + 0xee => 0x5d32, 0xef => 0x5d36, 0xf0 => 0x5d40, 0xf1 => 0x5d45, + 0xf2 => 0x5e44, 0xf3 => 0x5e41, 0xf4 => 0x5f58, 0xf5 => 0x5fa6, + 0xf6 => 0x5fa5, 0xf7 => 0x5fab, 0xf8 => 0x60c9, 0xf9 => 0x60b9, + 0xfa => 0x60cc, 0xfb => 0x60e2, 0xfc => 0x60ce, 0xfd => 0x60c4, + 0xfe => 0x6114, + }, + 0xd9 => { + 0x40 => 0x60f2, 0x41 => 0x610a, 0x42 => 0x6116, 0x43 => 0x6105, + 0x44 => 0x60f5, 0x45 => 0x6113, 0x46 => 0x60f8, 0x47 => 0x60fc, + 0x48 => 0x60fe, 0x49 => 0x60c1, 0x4a => 0x6103, 0x4b => 0x6118, + 0x4c => 0x611d, 0x4d => 0x6110, 0x4e => 0x60ff, 0x4f => 0x6104, + 0x50 => 0x610b, 0x51 => 0x624a, 0x52 => 0x6394, 0x53 => 0x63b1, + 0x54 => 0x63b0, 0x55 => 0x63ce, 0x56 => 0x63e5, 0x57 => 0x63e8, + 0x58 => 0x63ef, 0x59 => 0x63c3, 0x5a => 0x649d, 0x5b => 0x63f3, + 0x5c => 0x63ca, 0x5d => 0x63e0, 0x5e => 0x63f6, 0x5f => 0x63d5, + 0x60 => 0x63f2, 0x61 => 0x63f5, 0x62 => 0x6461, 0x63 => 0x63df, + 0x64 => 0x63be, 0x65 => 0x63dd, 0x66 => 0x63dc, 0x67 => 0x63c4, + 0x68 => 0x63d8, 0x69 => 0x63d3, 0x6a => 0x63c2, 0x6b => 0x63c7, + 0x6c => 0x63cc, 0x6d => 0x63cb, 0x6e => 0x63c8, 0x6f => 0x63f0, + 0x70 => 0x63d7, 0x71 => 0x63d9, 0x72 => 0x6532, 0x73 => 0x6567, + 0x74 => 0x656a, 0x75 => 0x6564, 0x76 => 0x655c, 0x77 => 0x6568, + 0x78 => 0x6565, 0x79 => 0x658c, 0x7a => 0x659d, 0x7b => 0x659e, + 0x7c => 0x65ae, 0x7d => 0x65d0, 0x7e => 0x65d2, 0xa1 => 0x667c, + 0xa2 => 0x666c, 0xa3 => 0x667b, 0xa4 => 0x6680, 0xa5 => 0x6671, + 0xa6 => 0x6679, 0xa7 => 0x666a, 0xa8 => 0x6672, 0xa9 => 0x6701, + 0xaa => 0x690c, 0xab => 0x68d3, 0xac => 0x6904, 0xad => 0x68dc, + 0xae => 0x692a, 0xaf => 0x68ec, 0xb0 => 0x68ea, 0xb1 => 0x68f1, + 0xb2 => 0x690f, 0xb3 => 0x68d6, 0xb4 => 0x68f7, 0xb5 => 0x68eb, + 0xb6 => 0x68e4, 0xb7 => 0x68f6, 0xb8 => 0x6913, 0xb9 => 0x6910, + 0xba => 0x68f3, 0xbb => 0x68e1, 0xbc => 0x6907, 0xbd => 0x68cc, + 0xbe => 0x6908, 0xbf => 0x6970, 0xc0 => 0x68b4, 0xc1 => 0x6911, + 0xc2 => 0x68ef, 0xc3 => 0x68c6, 0xc4 => 0x6914, 0xc5 => 0x68f8, + 0xc6 => 0x68d0, 0xc7 => 0x68fd, 0xc8 => 0x68fc, 0xc9 => 0x68e8, + 0xca => 0x690b, 0xcb => 0x690a, 0xcc => 0x6917, 0xcd => 0x68ce, + 0xce => 0x68c8, 0xcf => 0x68dd, 0xd0 => 0x68de, 0xd1 => 0x68e6, + 0xd2 => 0x68f4, 0xd3 => 0x68d1, 0xd4 => 0x6906, 0xd5 => 0x68d4, + 0xd6 => 0x68e9, 0xd7 => 0x6915, 0xd8 => 0x6925, 0xd9 => 0x68c7, + 0xda => 0x6b39, 0xdb => 0x6b3b, 0xdc => 0x6b3f, 0xdd => 0x6b3c, + 0xde => 0x6b94, 0xdf => 0x6b97, 0xe0 => 0x6b99, 0xe1 => 0x6b95, + 0xe2 => 0x6bbd, 0xe3 => 0x6bf0, 0xe4 => 0x6bf2, 0xe5 => 0x6bf3, + 0xe6 => 0x6c30, 0xe7 => 0x6dfc, 0xe8 => 0x6e46, 0xe9 => 0x6e47, + 0xea => 0x6e1f, 0xeb => 0x6e49, 0xec => 0x6e88, 0xed => 0x6e3c, + 0xee => 0x6e3d, 0xef => 0x6e45, 0xf0 => 0x6e62, 0xf1 => 0x6e2b, + 0xf2 => 0x6e3f, 0xf3 => 0x6e41, 0xf4 => 0x6e5d, 0xf5 => 0x6e73, + 0xf6 => 0x6e1c, 0xf7 => 0x6e33, 0xf8 => 0x6e4b, 0xf9 => 0x6e40, + 0xfa => 0x6e51, 0xfb => 0x6e3b, 0xfc => 0x6e03, 0xfd => 0x6e2e, + 0xfe => 0x6e5e, + }, + 0xda => { + 0x40 => 0x6e68, 0x41 => 0x6e5c, 0x42 => 0x6e61, 0x43 => 0x6e31, + 0x44 => 0x6e28, 0x45 => 0x6e60, 0x46 => 0x6e71, 0x47 => 0x6e6b, + 0x48 => 0x6e39, 0x49 => 0x6e22, 0x4a => 0x6e30, 0x4b => 0x6e53, + 0x4c => 0x6e65, 0x4d => 0x6e27, 0x4e => 0x6e78, 0x4f => 0x6e64, + 0x50 => 0x6e77, 0x51 => 0x6e55, 0x52 => 0x6e79, 0x53 => 0x6e52, + 0x54 => 0x6e66, 0x55 => 0x6e35, 0x56 => 0x6e36, 0x57 => 0x6e5a, + 0x58 => 0x7120, 0x59 => 0x711e, 0x5a => 0x712f, 0x5b => 0x70fb, + 0x5c => 0x712e, 0x5d => 0x7131, 0x5e => 0x7123, 0x5f => 0x7125, + 0x60 => 0x7122, 0x61 => 0x7132, 0x62 => 0x711f, 0x63 => 0x7128, + 0x64 => 0x713a, 0x65 => 0x711b, 0x66 => 0x724b, 0x67 => 0x725a, + 0x68 => 0x7288, 0x69 => 0x7289, 0x6a => 0x7286, 0x6b => 0x7285, + 0x6c => 0x728b, 0x6d => 0x7312, 0x6e => 0x730b, 0x6f => 0x7330, + 0x70 => 0x7322, 0x71 => 0x7331, 0x72 => 0x7333, 0x73 => 0x7327, + 0x74 => 0x7332, 0x75 => 0x732d, 0x76 => 0x7326, 0x77 => 0x7323, + 0x78 => 0x7335, 0x79 => 0x730c, 0x7a => 0x742e, 0x7b => 0x742c, + 0x7c => 0x7430, 0x7d => 0x742b, 0x7e => 0x7416, 0xa1 => 0x741a, + 0xa2 => 0x7421, 0xa3 => 0x742d, 0xa4 => 0x7431, 0xa5 => 0x7424, + 0xa6 => 0x7423, 0xa7 => 0x741d, 0xa8 => 0x7429, 0xa9 => 0x7420, + 0xaa => 0x7432, 0xab => 0x74fb, 0xac => 0x752f, 0xad => 0x756f, + 0xae => 0x756c, 0xaf => 0x75e7, 0xb0 => 0x75da, 0xb1 => 0x75e1, + 0xb2 => 0x75e6, 0xb3 => 0x75dd, 0xb4 => 0x75df, 0xb5 => 0x75e4, + 0xb6 => 0x75d7, 0xb7 => 0x7695, 0xb8 => 0x7692, 0xb9 => 0x76da, + 0xba => 0x7746, 0xbb => 0x7747, 0xbc => 0x7744, 0xbd => 0x774d, + 0xbe => 0x7745, 0xbf => 0x774a, 0xc0 => 0x774e, 0xc1 => 0x774b, + 0xc2 => 0x774c, 0xc3 => 0x77de, 0xc4 => 0x77ec, 0xc5 => 0x7860, + 0xc6 => 0x7864, 0xc7 => 0x7865, 0xc8 => 0x785c, 0xc9 => 0x786d, + 0xca => 0x7871, 0xcb => 0x786a, 0xcc => 0x786e, 0xcd => 0x7870, + 0xce => 0x7869, 0xcf => 0x7868, 0xd0 => 0x785e, 0xd1 => 0x7862, + 0xd2 => 0x7974, 0xd3 => 0x7973, 0xd4 => 0x7972, 0xd5 => 0x7970, + 0xd6 => 0x7a02, 0xd7 => 0x7a0a, 0xd8 => 0x7a03, 0xd9 => 0x7a0c, + 0xda => 0x7a04, 0xdb => 0x7a99, 0xdc => 0x7ae6, 0xdd => 0x7ae4, + 0xde => 0x7b4a, 0xdf => 0x7b3b, 0xe0 => 0x7b44, 0xe1 => 0x7b48, + 0xe2 => 0x7b4c, 0xe3 => 0x7b4e, 0xe4 => 0x7b40, 0xe5 => 0x7b58, + 0xe6 => 0x7b45, 0xe7 => 0x7ca2, 0xe8 => 0x7c9e, 0xe9 => 0x7ca8, + 0xea => 0x7ca1, 0xeb => 0x7d58, 0xec => 0x7d6f, 0xed => 0x7d63, + 0xee => 0x7d53, 0xef => 0x7d56, 0xf0 => 0x7d67, 0xf1 => 0x7d6a, + 0xf2 => 0x7d4f, 0xf3 => 0x7d6d, 0xf4 => 0x7d5c, 0xf5 => 0x7d6b, + 0xf6 => 0x7d52, 0xf7 => 0x7d54, 0xf8 => 0x7d69, 0xf9 => 0x7d51, + 0xfa => 0x7d5f, 0xfb => 0x7d4e, 0xfc => 0x7f3e, 0xfd => 0x7f3f, + 0xfe => 0x7f65, + }, + 0xdb => { + 0x40 => 0x7f66, 0x41 => 0x7fa2, 0x42 => 0x7fa0, 0x43 => 0x7fa1, + 0x44 => 0x7fd7, 0x45 => 0x8051, 0x46 => 0x804f, 0x47 => 0x8050, + 0x48 => 0x80fe, 0x49 => 0x80d4, 0x4a => 0x8143, 0x4b => 0x814a, + 0x4c => 0x8152, 0x4d => 0x814f, 0x4e => 0x8147, 0x4f => 0x813d, + 0x50 => 0x814d, 0x51 => 0x813a, 0x52 => 0x81e6, 0x53 => 0x81ee, + 0x54 => 0x81f7, 0x55 => 0x81f8, 0x56 => 0x81f9, 0x57 => 0x8204, + 0x58 => 0x823c, 0x59 => 0x823d, 0x5a => 0x823f, 0x5b => 0x8275, + 0x5c => 0x833b, 0x5d => 0x83cf, 0x5e => 0x83f9, 0x5f => 0x8423, + 0x60 => 0x83c0, 0x61 => 0x83e8, 0x62 => 0x8412, 0x63 => 0x83e7, + 0x64 => 0x83e4, 0x65 => 0x83fc, 0x66 => 0x83f6, 0x67 => 0x8410, + 0x68 => 0x83c6, 0x69 => 0x83c8, 0x6a => 0x83eb, 0x6b => 0x83e3, + 0x6c => 0x83bf, 0x6d => 0x8401, 0x6e => 0x83dd, 0x6f => 0x83e5, + 0x70 => 0x83d8, 0x71 => 0x83ff, 0x72 => 0x83e1, 0x73 => 0x83cb, + 0x74 => 0x83ce, 0x75 => 0x83d6, 0x76 => 0x83f5, 0x77 => 0x83c9, + 0x78 => 0x8409, 0x79 => 0x840f, 0x7a => 0x83de, 0x7b => 0x8411, + 0x7c => 0x8406, 0x7d => 0x83c2, 0x7e => 0x83f3, 0xa1 => 0x83d5, + 0xa2 => 0x83fa, 0xa3 => 0x83c7, 0xa4 => 0x83d1, 0xa5 => 0x83ea, + 0xa6 => 0x8413, 0xa7 => 0x83c3, 0xa8 => 0x83ec, 0xa9 => 0x83ee, + 0xaa => 0x83c4, 0xab => 0x83fb, 0xac => 0x83d7, 0xad => 0x83e2, + 0xae => 0x841b, 0xaf => 0x83db, 0xb0 => 0x83fe, 0xb1 => 0x86d8, + 0xb2 => 0x86e2, 0xb3 => 0x86e6, 0xb4 => 0x86d3, 0xb5 => 0x86e3, + 0xb6 => 0x86da, 0xb7 => 0x86ea, 0xb8 => 0x86dd, 0xb9 => 0x86eb, + 0xba => 0x86dc, 0xbb => 0x86ec, 0xbc => 0x86e9, 0xbd => 0x86d7, + 0xbe => 0x86e8, 0xbf => 0x86d1, 0xc0 => 0x8848, 0xc1 => 0x8856, + 0xc2 => 0x8855, 0xc3 => 0x88ba, 0xc4 => 0x88d7, 0xc5 => 0x88b9, + 0xc6 => 0x88b8, 0xc7 => 0x88c0, 0xc8 => 0x88be, 0xc9 => 0x88b6, + 0xca => 0x88bc, 0xcb => 0x88b7, 0xcc => 0x88bd, 0xcd => 0x88b2, + 0xce => 0x8901, 0xcf => 0x88c9, 0xd0 => 0x8995, 0xd1 => 0x8998, + 0xd2 => 0x8997, 0xd3 => 0x89dd, 0xd4 => 0x89da, 0xd5 => 0x89db, + 0xd6 => 0x8a4e, 0xd7 => 0x8a4d, 0xd8 => 0x8a39, 0xd9 => 0x8a59, + 0xda => 0x8a40, 0xdb => 0x8a57, 0xdc => 0x8a58, 0xdd => 0x8a44, + 0xde => 0x8a45, 0xdf => 0x8a52, 0xe0 => 0x8a48, 0xe1 => 0x8a51, + 0xe2 => 0x8a4a, 0xe3 => 0x8a4c, 0xe4 => 0x8a4f, 0xe5 => 0x8c5f, + 0xe6 => 0x8c81, 0xe7 => 0x8c80, 0xe8 => 0x8cba, 0xe9 => 0x8cbe, + 0xea => 0x8cb0, 0xeb => 0x8cb9, 0xec => 0x8cb5, 0xed => 0x8d84, + 0xee => 0x8d80, 0xef => 0x8d89, 0xf0 => 0x8dd8, 0xf1 => 0x8dd3, + 0xf2 => 0x8dcd, 0xf3 => 0x8dc7, 0xf4 => 0x8dd6, 0xf5 => 0x8ddc, + 0xf6 => 0x8dcf, 0xf7 => 0x8dd5, 0xf8 => 0x8dd9, 0xf9 => 0x8dc8, + 0xfa => 0x8dd7, 0xfb => 0x8dc5, 0xfc => 0x8eef, 0xfd => 0x8ef7, + 0xfe => 0x8efa, + }, + 0xdc => { + 0x40 => 0x8ef9, 0x41 => 0x8ee6, 0x42 => 0x8eee, 0x43 => 0x8ee5, + 0x44 => 0x8ef5, 0x45 => 0x8ee7, 0x46 => 0x8ee8, 0x47 => 0x8ef6, + 0x48 => 0x8eeb, 0x49 => 0x8ef1, 0x4a => 0x8eec, 0x4b => 0x8ef4, + 0x4c => 0x8ee9, 0x4d => 0x902d, 0x4e => 0x9034, 0x4f => 0x902f, + 0x50 => 0x9106, 0x51 => 0x912c, 0x52 => 0x9104, 0x53 => 0x90ff, + 0x54 => 0x90fc, 0x55 => 0x9108, 0x56 => 0x90f9, 0x57 => 0x90fb, + 0x58 => 0x9101, 0x59 => 0x9100, 0x5a => 0x9107, 0x5b => 0x9105, + 0x5c => 0x9103, 0x5d => 0x9161, 0x5e => 0x9164, 0x5f => 0x915f, + 0x60 => 0x9162, 0x61 => 0x9160, 0x62 => 0x9201, 0x63 => 0x920a, + 0x64 => 0x9225, 0x65 => 0x9203, 0x66 => 0x921a, 0x67 => 0x9226, + 0x68 => 0x920f, 0x69 => 0x920c, 0x6a => 0x9200, 0x6b => 0x9212, + 0x6c => 0x91ff, 0x6d => 0x91fd, 0x6e => 0x9206, 0x6f => 0x9204, + 0x70 => 0x9227, 0x71 => 0x9202, 0x72 => 0x921c, 0x73 => 0x9224, + 0x74 => 0x9219, 0x75 => 0x9217, 0x76 => 0x9205, 0x77 => 0x9216, + 0x78 => 0x957b, 0x79 => 0x958d, 0x7a => 0x958c, 0x7b => 0x9590, + 0x7c => 0x9687, 0x7d => 0x967e, 0x7e => 0x9688, 0xa1 => 0x9689, + 0xa2 => 0x9683, 0xa3 => 0x9680, 0xa4 => 0x96c2, 0xa5 => 0x96c8, + 0xa6 => 0x96c3, 0xa7 => 0x96f1, 0xa8 => 0x96f0, 0xa9 => 0x976c, + 0xaa => 0x9770, 0xab => 0x976e, 0xac => 0x9807, 0xad => 0x98a9, + 0xae => 0x98eb, 0xaf => 0x9ce6, 0xb0 => 0x9ef9, 0xb1 => 0x4e83, + 0xb2 => 0x4e84, 0xb3 => 0x4eb6, 0xb4 => 0x50bd, 0xb5 => 0x50bf, + 0xb6 => 0x50c6, 0xb7 => 0x50ae, 0xb8 => 0x50c4, 0xb9 => 0x50ca, + 0xba => 0x50b4, 0xbb => 0x50c8, 0xbc => 0x50c2, 0xbd => 0x50b0, + 0xbe => 0x50c1, 0xbf => 0x50ba, 0xc0 => 0x50b1, 0xc1 => 0x50cb, + 0xc2 => 0x50c9, 0xc3 => 0x50b6, 0xc4 => 0x50b8, 0xc5 => 0x51d7, + 0xc6 => 0x527a, 0xc7 => 0x5278, 0xc8 => 0x527b, 0xc9 => 0x527c, + 0xca => 0x55c3, 0xcb => 0x55db, 0xcc => 0x55cc, 0xcd => 0x55d0, + 0xce => 0x55cb, 0xcf => 0x55ca, 0xd0 => 0x55dd, 0xd1 => 0x55c0, + 0xd2 => 0x55d4, 0xd3 => 0x55c4, 0xd4 => 0x55e9, 0xd5 => 0x55bf, + 0xd6 => 0x55d2, 0xd7 => 0x558d, 0xd8 => 0x55cf, 0xd9 => 0x55d5, + 0xda => 0x55e2, 0xdb => 0x55d6, 0xdc => 0x55c8, 0xdd => 0x55f2, + 0xde => 0x55cd, 0xdf => 0x55d9, 0xe0 => 0x55c2, 0xe1 => 0x5714, + 0xe2 => 0x5853, 0xe3 => 0x5868, 0xe4 => 0x5864, 0xe5 => 0x584f, + 0xe6 => 0x584d, 0xe7 => 0x5849, 0xe8 => 0x586f, 0xe9 => 0x5855, + 0xea => 0x584e, 0xeb => 0x585d, 0xec => 0x5859, 0xed => 0x5865, + 0xee => 0x585b, 0xef => 0x583d, 0xf0 => 0x5863, 0xf1 => 0x5871, + 0xf2 => 0x58fc, 0xf3 => 0x5ac7, 0xf4 => 0x5ac4, 0xf5 => 0x5acb, + 0xf6 => 0x5aba, 0xf7 => 0x5ab8, 0xf8 => 0x5ab1, 0xf9 => 0x5ab5, + 0xfa => 0x5ab0, 0xfb => 0x5abf, 0xfc => 0x5ac8, 0xfd => 0x5abb, + 0xfe => 0x5ac6, + }, + 0xdd => { + 0x40 => 0x5ab7, 0x41 => 0x5ac0, 0x42 => 0x5aca, 0x43 => 0x5ab4, + 0x44 => 0x5ab6, 0x45 => 0x5acd, 0x46 => 0x5ab9, 0x47 => 0x5a90, + 0x48 => 0x5bd6, 0x49 => 0x5bd8, 0x4a => 0x5bd9, 0x4b => 0x5c1f, + 0x4c => 0x5c33, 0x4d => 0x5d71, 0x4e => 0x5d63, 0x4f => 0x5d4a, + 0x50 => 0x5d65, 0x51 => 0x5d72, 0x52 => 0x5d6c, 0x53 => 0x5d5e, + 0x54 => 0x5d68, 0x55 => 0x5d67, 0x56 => 0x5d62, 0x57 => 0x5df0, + 0x58 => 0x5e4f, 0x59 => 0x5e4e, 0x5a => 0x5e4a, 0x5b => 0x5e4d, + 0x5c => 0x5e4b, 0x5d => 0x5ec5, 0x5e => 0x5ecc, 0x5f => 0x5ec6, + 0x60 => 0x5ecb, 0x61 => 0x5ec7, 0x62 => 0x5f40, 0x63 => 0x5faf, + 0x64 => 0x5fad, 0x65 => 0x60f7, 0x66 => 0x6149, 0x67 => 0x614a, + 0x68 => 0x612b, 0x69 => 0x6145, 0x6a => 0x6136, 0x6b => 0x6132, + 0x6c => 0x612e, 0x6d => 0x6146, 0x6e => 0x612f, 0x6f => 0x614f, + 0x70 => 0x6129, 0x71 => 0x6140, 0x72 => 0x6220, 0x73 => 0x9168, + 0x74 => 0x6223, 0x75 => 0x6225, 0x76 => 0x6224, 0x77 => 0x63c5, + 0x78 => 0x63f1, 0x79 => 0x63eb, 0x7a => 0x6410, 0x7b => 0x6412, + 0x7c => 0x6409, 0x7d => 0x6420, 0x7e => 0x6424, 0xa1 => 0x6433, + 0xa2 => 0x6443, 0xa3 => 0x641f, 0xa4 => 0x6415, 0xa5 => 0x6418, + 0xa6 => 0x6439, 0xa7 => 0x6437, 0xa8 => 0x6422, 0xa9 => 0x6423, + 0xaa => 0x640c, 0xab => 0x6426, 0xac => 0x6430, 0xad => 0x6428, + 0xae => 0x6441, 0xaf => 0x6435, 0xb0 => 0x642f, 0xb1 => 0x640a, + 0xb2 => 0x641a, 0xb3 => 0x6440, 0xb4 => 0x6425, 0xb5 => 0x6427, + 0xb6 => 0x640b, 0xb7 => 0x63e7, 0xb8 => 0x641b, 0xb9 => 0x642e, + 0xba => 0x6421, 0xbb => 0x640e, 0xbc => 0x656f, 0xbd => 0x6592, + 0xbe => 0x65d3, 0xbf => 0x6686, 0xc0 => 0x668c, 0xc1 => 0x6695, + 0xc2 => 0x6690, 0xc3 => 0x668b, 0xc4 => 0x668a, 0xc5 => 0x6699, + 0xc6 => 0x6694, 0xc7 => 0x6678, 0xc8 => 0x6720, 0xc9 => 0x6966, + 0xca => 0x695f, 0xcb => 0x6938, 0xcc => 0x694e, 0xcd => 0x6962, + 0xce => 0x6971, 0xcf => 0x693f, 0xd0 => 0x6945, 0xd1 => 0x696a, + 0xd2 => 0x6939, 0xd3 => 0x6942, 0xd4 => 0x6957, 0xd5 => 0x6959, + 0xd6 => 0x697a, 0xd7 => 0x6948, 0xd8 => 0x6949, 0xd9 => 0x6935, + 0xda => 0x696c, 0xdb => 0x6933, 0xdc => 0x693d, 0xdd => 0x6965, + 0xde => 0x68f0, 0xdf => 0x6978, 0xe0 => 0x6934, 0xe1 => 0x6969, + 0xe2 => 0x6940, 0xe3 => 0x696f, 0xe4 => 0x6944, 0xe5 => 0x6976, + 0xe6 => 0x6958, 0xe7 => 0x6941, 0xe8 => 0x6974, 0xe9 => 0x694c, + 0xea => 0x693b, 0xeb => 0x694b, 0xec => 0x6937, 0xed => 0x695c, + 0xee => 0x694f, 0xef => 0x6951, 0xf0 => 0x6932, 0xf1 => 0x6952, + 0xf2 => 0x692f, 0xf3 => 0x697b, 0xf4 => 0x693c, 0xf5 => 0x6b46, + 0xf6 => 0x6b45, 0xf7 => 0x6b43, 0xf8 => 0x6b42, 0xf9 => 0x6b48, + 0xfa => 0x6b41, 0xfb => 0x6b9b, 0xfc => 0xfa0d, 0xfd => 0x6bfb, + 0xfe => 0x6bfc, + }, + 0xde => { + 0x40 => 0x6bf9, 0x41 => 0x6bf7, 0x42 => 0x6bf8, 0x43 => 0x6e9b, + 0x44 => 0x6ed6, 0x45 => 0x6ec8, 0x46 => 0x6e8f, 0x47 => 0x6ec0, + 0x48 => 0x6e9f, 0x49 => 0x6e93, 0x4a => 0x6e94, 0x4b => 0x6ea0, + 0x4c => 0x6eb1, 0x4d => 0x6eb9, 0x4e => 0x6ec6, 0x4f => 0x6ed2, + 0x50 => 0x6ebd, 0x51 => 0x6ec1, 0x52 => 0x6e9e, 0x53 => 0x6ec9, + 0x54 => 0x6eb7, 0x55 => 0x6eb0, 0x56 => 0x6ecd, 0x57 => 0x6ea6, + 0x58 => 0x6ecf, 0x59 => 0x6eb2, 0x5a => 0x6ebe, 0x5b => 0x6ec3, + 0x5c => 0x6edc, 0x5d => 0x6ed8, 0x5e => 0x6e99, 0x5f => 0x6e92, + 0x60 => 0x6e8e, 0x61 => 0x6e8d, 0x62 => 0x6ea4, 0x63 => 0x6ea1, + 0x64 => 0x6ebf, 0x65 => 0x6eb3, 0x66 => 0x6ed0, 0x67 => 0x6eca, + 0x68 => 0x6e97, 0x69 => 0x6eae, 0x6a => 0x6ea3, 0x6b => 0x7147, + 0x6c => 0x7154, 0x6d => 0x7152, 0x6e => 0x7163, 0x6f => 0x7160, + 0x70 => 0x7141, 0x71 => 0x715d, 0x72 => 0x7162, 0x73 => 0x7172, + 0x74 => 0x7178, 0x75 => 0x716a, 0x76 => 0x7161, 0x77 => 0x7142, + 0x78 => 0x7158, 0x79 => 0x7143, 0x7a => 0x714b, 0x7b => 0x7170, + 0x7c => 0x715f, 0x7d => 0x7150, 0x7e => 0x7153, 0xa1 => 0x7144, + 0xa2 => 0x714d, 0xa3 => 0x715a, 0xa4 => 0x724f, 0xa5 => 0x728d, + 0xa6 => 0x728c, 0xa7 => 0x7291, 0xa8 => 0x7290, 0xa9 => 0x728e, + 0xaa => 0x733c, 0xab => 0x7342, 0xac => 0x733b, 0xad => 0x733a, + 0xae => 0x7340, 0xaf => 0x734a, 0xb0 => 0x7349, 0xb1 => 0x7444, + 0xb2 => 0x744a, 0xb3 => 0x744b, 0xb4 => 0x7452, 0xb5 => 0x7451, + 0xb6 => 0x7457, 0xb7 => 0x7440, 0xb8 => 0x744f, 0xb9 => 0x7450, + 0xba => 0x744e, 0xbb => 0x7442, 0xbc => 0x7446, 0xbd => 0x744d, + 0xbe => 0x7454, 0xbf => 0x74e1, 0xc0 => 0x74ff, 0xc1 => 0x74fe, + 0xc2 => 0x74fd, 0xc3 => 0x751d, 0xc4 => 0x7579, 0xc5 => 0x7577, + 0xc6 => 0x6983, 0xc7 => 0x75ef, 0xc8 => 0x760f, 0xc9 => 0x7603, + 0xca => 0x75f7, 0xcb => 0x75fe, 0xcc => 0x75fc, 0xcd => 0x75f9, + 0xce => 0x75f8, 0xcf => 0x7610, 0xd0 => 0x75fb, 0xd1 => 0x75f6, + 0xd2 => 0x75ed, 0xd3 => 0x75f5, 0xd4 => 0x75fd, 0xd5 => 0x7699, + 0xd6 => 0x76b5, 0xd7 => 0x76dd, 0xd8 => 0x7755, 0xd9 => 0x775f, + 0xda => 0x7760, 0xdb => 0x7752, 0xdc => 0x7756, 0xdd => 0x775a, + 0xde => 0x7769, 0xdf => 0x7767, 0xe0 => 0x7754, 0xe1 => 0x7759, + 0xe2 => 0x776d, 0xe3 => 0x77e0, 0xe4 => 0x7887, 0xe5 => 0x789a, + 0xe6 => 0x7894, 0xe7 => 0x788f, 0xe8 => 0x7884, 0xe9 => 0x7895, + 0xea => 0x7885, 0xeb => 0x7886, 0xec => 0x78a1, 0xed => 0x7883, + 0xee => 0x7879, 0xef => 0x7899, 0xf0 => 0x7880, 0xf1 => 0x7896, + 0xf2 => 0x787b, 0xf3 => 0x797c, 0xf4 => 0x7982, 0xf5 => 0x797d, + 0xf6 => 0x7979, 0xf7 => 0x7a11, 0xf8 => 0x7a18, 0xf9 => 0x7a19, + 0xfa => 0x7a12, 0xfb => 0x7a17, 0xfc => 0x7a15, 0xfd => 0x7a22, + 0xfe => 0x7a13, + }, + 0xdf => { + 0x40 => 0x7a1b, 0x41 => 0x7a10, 0x42 => 0x7aa3, 0x43 => 0x7aa2, + 0x44 => 0x7a9e, 0x45 => 0x7aeb, 0x46 => 0x7b66, 0x47 => 0x7b64, + 0x48 => 0x7b6d, 0x49 => 0x7b74, 0x4a => 0x7b69, 0x4b => 0x7b72, + 0x4c => 0x7b65, 0x4d => 0x7b73, 0x4e => 0x7b71, 0x4f => 0x7b70, + 0x50 => 0x7b61, 0x51 => 0x7b78, 0x52 => 0x7b76, 0x53 => 0x7b63, + 0x54 => 0x7cb2, 0x55 => 0x7cb4, 0x56 => 0x7caf, 0x57 => 0x7d88, + 0x58 => 0x7d86, 0x59 => 0x7d80, 0x5a => 0x7d8d, 0x5b => 0x7d7f, + 0x5c => 0x7d85, 0x5d => 0x7d7a, 0x5e => 0x7d8e, 0x5f => 0x7d7b, + 0x60 => 0x7d83, 0x61 => 0x7d7c, 0x62 => 0x7d8c, 0x63 => 0x7d94, + 0x64 => 0x7d84, 0x65 => 0x7d7d, 0x66 => 0x7d92, 0x67 => 0x7f6d, + 0x68 => 0x7f6b, 0x69 => 0x7f67, 0x6a => 0x7f68, 0x6b => 0x7f6c, + 0x6c => 0x7fa6, 0x6d => 0x7fa5, 0x6e => 0x7fa7, 0x6f => 0x7fdb, + 0x70 => 0x7fdc, 0x71 => 0x8021, 0x72 => 0x8164, 0x73 => 0x8160, + 0x74 => 0x8177, 0x75 => 0x815c, 0x76 => 0x8169, 0x77 => 0x815b, + 0x78 => 0x8162, 0x79 => 0x8172, 0x7a => 0x6721, 0x7b => 0x815e, + 0x7c => 0x8176, 0x7d => 0x8167, 0x7e => 0x816f, 0xa1 => 0x8144, + 0xa2 => 0x8161, 0xa3 => 0x821d, 0xa4 => 0x8249, 0xa5 => 0x8244, + 0xa6 => 0x8240, 0xa7 => 0x8242, 0xa8 => 0x8245, 0xa9 => 0x84f1, + 0xaa => 0x843f, 0xab => 0x8456, 0xac => 0x8476, 0xad => 0x8479, + 0xae => 0x848f, 0xaf => 0x848d, 0xb0 => 0x8465, 0xb1 => 0x8451, + 0xb2 => 0x8440, 0xb3 => 0x8486, 0xb4 => 0x8467, 0xb5 => 0x8430, + 0xb6 => 0x844d, 0xb7 => 0x847d, 0xb8 => 0x845a, 0xb9 => 0x8459, + 0xba => 0x8474, 0xbb => 0x8473, 0xbc => 0x845d, 0xbd => 0x8507, + 0xbe => 0x845e, 0xbf => 0x8437, 0xc0 => 0x843a, 0xc1 => 0x8434, + 0xc2 => 0x847a, 0xc3 => 0x8443, 0xc4 => 0x8478, 0xc5 => 0x8432, + 0xc6 => 0x8445, 0xc7 => 0x8429, 0xc8 => 0x83d9, 0xc9 => 0x844b, + 0xca => 0x842f, 0xcb => 0x8442, 0xcc => 0x842d, 0xcd => 0x845f, + 0xce => 0x8470, 0xcf => 0x8439, 0xd0 => 0x844e, 0xd1 => 0x844c, + 0xd2 => 0x8452, 0xd3 => 0x846f, 0xd4 => 0x84c5, 0xd5 => 0x848e, + 0xd6 => 0x843b, 0xd7 => 0x8447, 0xd8 => 0x8436, 0xd9 => 0x8433, + 0xda => 0x8468, 0xdb => 0x847e, 0xdc => 0x8444, 0xdd => 0x842b, + 0xde => 0x8460, 0xdf => 0x8454, 0xe0 => 0x846e, 0xe1 => 0x8450, + 0xe2 => 0x870b, 0xe3 => 0x8704, 0xe4 => 0x86f7, 0xe5 => 0x870c, + 0xe6 => 0x86fa, 0xe7 => 0x86d6, 0xe8 => 0x86f5, 0xe9 => 0x874d, + 0xea => 0x86f8, 0xeb => 0x870e, 0xec => 0x8709, 0xed => 0x8701, + 0xee => 0x86f6, 0xef => 0x870d, 0xf0 => 0x8705, 0xf1 => 0x88d6, + 0xf2 => 0x88cb, 0xf3 => 0x88cd, 0xf4 => 0x88ce, 0xf5 => 0x88de, + 0xf6 => 0x88db, 0xf7 => 0x88da, 0xf8 => 0x88cc, 0xf9 => 0x88d0, + 0xfa => 0x8985, 0xfb => 0x899b, 0xfc => 0x89df, 0xfd => 0x89e5, + 0xfe => 0x89e4, + }, + 0xe0 => { + 0x40 => 0x89e1, 0x41 => 0x89e0, 0x42 => 0x89e2, 0x43 => 0x89dc, + 0x44 => 0x89e6, 0x45 => 0x8a76, 0x46 => 0x8a86, 0x47 => 0x8a7f, + 0x48 => 0x8a61, 0x49 => 0x8a3f, 0x4a => 0x8a77, 0x4b => 0x8a82, + 0x4c => 0x8a84, 0x4d => 0x8a75, 0x4e => 0x8a83, 0x4f => 0x8a81, + 0x50 => 0x8a74, 0x51 => 0x8a7a, 0x52 => 0x8c3c, 0x53 => 0x8c4b, + 0x54 => 0x8c4a, 0x55 => 0x8c65, 0x56 => 0x8c64, 0x57 => 0x8c66, + 0x58 => 0x8c86, 0x59 => 0x8c84, 0x5a => 0x8c85, 0x5b => 0x8ccc, + 0x5c => 0x8d68, 0x5d => 0x8d69, 0x5e => 0x8d91, 0x5f => 0x8d8c, + 0x60 => 0x8d8e, 0x61 => 0x8d8f, 0x62 => 0x8d8d, 0x63 => 0x8d93, + 0x64 => 0x8d94, 0x65 => 0x8d90, 0x66 => 0x8d92, 0x67 => 0x8df0, + 0x68 => 0x8de0, 0x69 => 0x8dec, 0x6a => 0x8df1, 0x6b => 0x8dee, + 0x6c => 0x8dd0, 0x6d => 0x8de9, 0x6e => 0x8de3, 0x6f => 0x8de2, + 0x70 => 0x8de7, 0x71 => 0x8df2, 0x72 => 0x8deb, 0x73 => 0x8df4, + 0x74 => 0x8f06, 0x75 => 0x8eff, 0x76 => 0x8f01, 0x77 => 0x8f00, + 0x78 => 0x8f05, 0x79 => 0x8f07, 0x7a => 0x8f08, 0x7b => 0x8f02, + 0x7c => 0x8f0b, 0x7d => 0x9052, 0x7e => 0x903f, 0xa1 => 0x9044, + 0xa2 => 0x9049, 0xa3 => 0x903d, 0xa4 => 0x9110, 0xa5 => 0x910d, + 0xa6 => 0x910f, 0xa7 => 0x9111, 0xa8 => 0x9116, 0xa9 => 0x9114, + 0xaa => 0x910b, 0xab => 0x910e, 0xac => 0x916e, 0xad => 0x916f, + 0xae => 0x9248, 0xaf => 0x9252, 0xb0 => 0x9230, 0xb1 => 0x923a, + 0xb2 => 0x9266, 0xb3 => 0x9233, 0xb4 => 0x9265, 0xb5 => 0x925e, + 0xb6 => 0x9283, 0xb7 => 0x922e, 0xb8 => 0x924a, 0xb9 => 0x9246, + 0xba => 0x926d, 0xbb => 0x926c, 0xbc => 0x924f, 0xbd => 0x9260, + 0xbe => 0x9267, 0xbf => 0x926f, 0xc0 => 0x9236, 0xc1 => 0x9261, + 0xc2 => 0x9270, 0xc3 => 0x9231, 0xc4 => 0x9254, 0xc5 => 0x9263, + 0xc6 => 0x9250, 0xc7 => 0x9272, 0xc8 => 0x924e, 0xc9 => 0x9253, + 0xca => 0x924c, 0xcb => 0x9256, 0xcc => 0x9232, 0xcd => 0x959f, + 0xce => 0x959c, 0xcf => 0x959e, 0xd0 => 0x959b, 0xd1 => 0x9692, + 0xd2 => 0x9693, 0xd3 => 0x9691, 0xd4 => 0x9697, 0xd5 => 0x96ce, + 0xd6 => 0x96fa, 0xd7 => 0x96fd, 0xd8 => 0x96f8, 0xd9 => 0x96f5, + 0xda => 0x9773, 0xdb => 0x9777, 0xdc => 0x9778, 0xdd => 0x9772, + 0xde => 0x980f, 0xdf => 0x980d, 0xe0 => 0x980e, 0xe1 => 0x98ac, + 0xe2 => 0x98f6, 0xe3 => 0x98f9, 0xe4 => 0x99af, 0xe5 => 0x99b2, + 0xe6 => 0x99b0, 0xe7 => 0x99b5, 0xe8 => 0x9aad, 0xe9 => 0x9aab, + 0xea => 0x9b5b, 0xeb => 0x9cea, 0xec => 0x9ced, 0xed => 0x9ce7, + 0xee => 0x9e80, 0xef => 0x9efd, 0xf0 => 0x50e6, 0xf1 => 0x50d4, + 0xf2 => 0x50d7, 0xf3 => 0x50e8, 0xf4 => 0x50f3, 0xf5 => 0x50db, + 0xf6 => 0x50ea, 0xf7 => 0x50dd, 0xf8 => 0x50e4, 0xf9 => 0x50d3, + 0xfa => 0x50ec, 0xfb => 0x50f0, 0xfc => 0x50ef, 0xfd => 0x50e3, + 0xfe => 0x50e0, + }, + 0xe1 => { + 0x40 => 0x51d8, 0x41 => 0x5280, 0x42 => 0x5281, 0x43 => 0x52e9, + 0x44 => 0x52eb, 0x45 => 0x5330, 0x46 => 0x53ac, 0x47 => 0x5627, + 0x48 => 0x5615, 0x49 => 0x560c, 0x4a => 0x5612, 0x4b => 0x55fc, + 0x4c => 0x560f, 0x4d => 0x561c, 0x4e => 0x5601, 0x4f => 0x5613, + 0x50 => 0x5602, 0x51 => 0x55fa, 0x52 => 0x561d, 0x53 => 0x5604, + 0x54 => 0x55ff, 0x55 => 0x55f9, 0x56 => 0x5889, 0x57 => 0x587c, + 0x58 => 0x5890, 0x59 => 0x5898, 0x5a => 0x5886, 0x5b => 0x5881, + 0x5c => 0x587f, 0x5d => 0x5874, 0x5e => 0x588b, 0x5f => 0x587a, + 0x60 => 0x5887, 0x61 => 0x5891, 0x62 => 0x588e, 0x63 => 0x5876, + 0x64 => 0x5882, 0x65 => 0x5888, 0x66 => 0x587b, 0x67 => 0x5894, + 0x68 => 0x588f, 0x69 => 0x58fe, 0x6a => 0x596b, 0x6b => 0x5adc, + 0x6c => 0x5aee, 0x6d => 0x5ae5, 0x6e => 0x5ad5, 0x6f => 0x5aea, + 0x70 => 0x5ada, 0x71 => 0x5aed, 0x72 => 0x5aeb, 0x73 => 0x5af3, + 0x74 => 0x5ae2, 0x75 => 0x5ae0, 0x76 => 0x5adb, 0x77 => 0x5aec, + 0x78 => 0x5ade, 0x79 => 0x5add, 0x7a => 0x5ad9, 0x7b => 0x5ae8, + 0x7c => 0x5adf, 0x7d => 0x5b77, 0x7e => 0x5be0, 0xa1 => 0x5be3, + 0xa2 => 0x5c63, 0xa3 => 0x5d82, 0xa4 => 0x5d80, 0xa5 => 0x5d7d, + 0xa6 => 0x5d86, 0xa7 => 0x5d7a, 0xa8 => 0x5d81, 0xa9 => 0x5d77, + 0xaa => 0x5d8a, 0xab => 0x5d89, 0xac => 0x5d88, 0xad => 0x5d7e, + 0xae => 0x5d7c, 0xaf => 0x5d8d, 0xb0 => 0x5d79, 0xb1 => 0x5d7f, + 0xb2 => 0x5e58, 0xb3 => 0x5e59, 0xb4 => 0x5e53, 0xb5 => 0x5ed8, + 0xb6 => 0x5ed1, 0xb7 => 0x5ed7, 0xb8 => 0x5ece, 0xb9 => 0x5edc, + 0xba => 0x5ed5, 0xbb => 0x5ed9, 0xbc => 0x5ed2, 0xbd => 0x5ed4, + 0xbe => 0x5f44, 0xbf => 0x5f43, 0xc0 => 0x5f6f, 0xc1 => 0x5fb6, + 0xc2 => 0x612c, 0xc3 => 0x6128, 0xc4 => 0x6141, 0xc5 => 0x615e, + 0xc6 => 0x6171, 0xc7 => 0x6173, 0xc8 => 0x6152, 0xc9 => 0x6153, + 0xca => 0x6172, 0xcb => 0x616c, 0xcc => 0x6180, 0xcd => 0x6174, + 0xce => 0x6154, 0xcf => 0x617a, 0xd0 => 0x615b, 0xd1 => 0x6165, + 0xd2 => 0x613b, 0xd3 => 0x616a, 0xd4 => 0x6161, 0xd5 => 0x6156, + 0xd6 => 0x6229, 0xd7 => 0x6227, 0xd8 => 0x622b, 0xd9 => 0x642b, + 0xda => 0x644d, 0xdb => 0x645b, 0xdc => 0x645d, 0xdd => 0x6474, + 0xde => 0x6476, 0xdf => 0x6472, 0xe0 => 0x6473, 0xe1 => 0x647d, + 0xe2 => 0x6475, 0xe3 => 0x6466, 0xe4 => 0x64a6, 0xe5 => 0x644e, + 0xe6 => 0x6482, 0xe7 => 0x645e, 0xe8 => 0x645c, 0xe9 => 0x644b, + 0xea => 0x6453, 0xeb => 0x6460, 0xec => 0x6450, 0xed => 0x647f, + 0xee => 0x643f, 0xef => 0x646c, 0xf0 => 0x646b, 0xf1 => 0x6459, + 0xf2 => 0x6465, 0xf3 => 0x6477, 0xf4 => 0x6573, 0xf5 => 0x65a0, + 0xf6 => 0x66a1, 0xf7 => 0x66a0, 0xf8 => 0x669f, 0xf9 => 0x6705, + 0xfa => 0x6704, 0xfb => 0x6722, 0xfc => 0x69b1, 0xfd => 0x69b6, + 0xfe => 0x69c9, + }, + 0xe2 => { + 0x40 => 0x69a0, 0x41 => 0x69ce, 0x42 => 0x6996, 0x43 => 0x69b0, + 0x44 => 0x69ac, 0x45 => 0x69bc, 0x46 => 0x6991, 0x47 => 0x6999, + 0x48 => 0x698e, 0x49 => 0x69a7, 0x4a => 0x698d, 0x4b => 0x69a9, + 0x4c => 0x69be, 0x4d => 0x69af, 0x4e => 0x69bf, 0x4f => 0x69c4, + 0x50 => 0x69bd, 0x51 => 0x69a4, 0x52 => 0x69d4, 0x53 => 0x69b9, + 0x54 => 0x69ca, 0x55 => 0x699a, 0x56 => 0x69cf, 0x57 => 0x69b3, + 0x58 => 0x6993, 0x59 => 0x69aa, 0x5a => 0x69a1, 0x5b => 0x699e, + 0x5c => 0x69d9, 0x5d => 0x6997, 0x5e => 0x6990, 0x5f => 0x69c2, + 0x60 => 0x69b5, 0x61 => 0x69a5, 0x62 => 0x69c6, 0x63 => 0x6b4a, + 0x64 => 0x6b4d, 0x65 => 0x6b4b, 0x66 => 0x6b9e, 0x67 => 0x6b9f, + 0x68 => 0x6ba0, 0x69 => 0x6bc3, 0x6a => 0x6bc4, 0x6b => 0x6bfe, + 0x6c => 0x6ece, 0x6d => 0x6ef5, 0x6e => 0x6ef1, 0x6f => 0x6f03, + 0x70 => 0x6f25, 0x71 => 0x6ef8, 0x72 => 0x6f37, 0x73 => 0x6efb, + 0x74 => 0x6f2e, 0x75 => 0x6f09, 0x76 => 0x6f4e, 0x77 => 0x6f19, + 0x78 => 0x6f1a, 0x79 => 0x6f27, 0x7a => 0x6f18, 0x7b => 0x6f3b, + 0x7c => 0x6f12, 0x7d => 0x6eed, 0x7e => 0x6f0a, 0xa1 => 0x6f36, + 0xa2 => 0x6f73, 0xa3 => 0x6ef9, 0xa4 => 0x6eee, 0xa5 => 0x6f2d, + 0xa6 => 0x6f40, 0xa7 => 0x6f30, 0xa8 => 0x6f3c, 0xa9 => 0x6f35, + 0xaa => 0x6eeb, 0xab => 0x6f07, 0xac => 0x6f0e, 0xad => 0x6f43, + 0xae => 0x6f05, 0xaf => 0x6efd, 0xb0 => 0x6ef6, 0xb1 => 0x6f39, + 0xb2 => 0x6f1c, 0xb3 => 0x6efc, 0xb4 => 0x6f3a, 0xb5 => 0x6f1f, + 0xb6 => 0x6f0d, 0xb7 => 0x6f1e, 0xb8 => 0x6f08, 0xb9 => 0x6f21, + 0xba => 0x7187, 0xbb => 0x7190, 0xbc => 0x7189, 0xbd => 0x7180, + 0xbe => 0x7185, 0xbf => 0x7182, 0xc0 => 0x718f, 0xc1 => 0x717b, + 0xc2 => 0x7186, 0xc3 => 0x7181, 0xc4 => 0x7197, 0xc5 => 0x7244, + 0xc6 => 0x7253, 0xc7 => 0x7297, 0xc8 => 0x7295, 0xc9 => 0x7293, + 0xca => 0x7343, 0xcb => 0x734d, 0xcc => 0x7351, 0xcd => 0x734c, + 0xce => 0x7462, 0xcf => 0x7473, 0xd0 => 0x7471, 0xd1 => 0x7475, + 0xd2 => 0x7472, 0xd3 => 0x7467, 0xd4 => 0x746e, 0xd5 => 0x7500, + 0xd6 => 0x7502, 0xd7 => 0x7503, 0xd8 => 0x757d, 0xd9 => 0x7590, + 0xda => 0x7616, 0xdb => 0x7608, 0xdc => 0x760c, 0xdd => 0x7615, + 0xde => 0x7611, 0xdf => 0x760a, 0xe0 => 0x7614, 0xe1 => 0x76b8, + 0xe2 => 0x7781, 0xe3 => 0x777c, 0xe4 => 0x7785, 0xe5 => 0x7782, + 0xe6 => 0x776e, 0xe7 => 0x7780, 0xe8 => 0x776f, 0xe9 => 0x777e, + 0xea => 0x7783, 0xeb => 0x78b2, 0xec => 0x78aa, 0xed => 0x78b4, + 0xee => 0x78ad, 0xef => 0x78a8, 0xf0 => 0x787e, 0xf1 => 0x78ab, + 0xf2 => 0x789e, 0xf3 => 0x78a5, 0xf4 => 0x78a0, 0xf5 => 0x78ac, + 0xf6 => 0x78a2, 0xf7 => 0x78a4, 0xf8 => 0x7998, 0xf9 => 0x798a, + 0xfa => 0x798b, 0xfb => 0x7996, 0xfc => 0x7995, 0xfd => 0x7994, + 0xfe => 0x7993, + }, + 0xe3 => { + 0x40 => 0x7997, 0x41 => 0x7988, 0x42 => 0x7992, 0x43 => 0x7990, + 0x44 => 0x7a2b, 0x45 => 0x7a4a, 0x46 => 0x7a30, 0x47 => 0x7a2f, + 0x48 => 0x7a28, 0x49 => 0x7a26, 0x4a => 0x7aa8, 0x4b => 0x7aab, + 0x4c => 0x7aac, 0x4d => 0x7aee, 0x4e => 0x7b88, 0x4f => 0x7b9c, + 0x50 => 0x7b8a, 0x51 => 0x7b91, 0x52 => 0x7b90, 0x53 => 0x7b96, + 0x54 => 0x7b8d, 0x55 => 0x7b8c, 0x56 => 0x7b9b, 0x57 => 0x7b8e, + 0x58 => 0x7b85, 0x59 => 0x7b98, 0x5a => 0x5284, 0x5b => 0x7b99, + 0x5c => 0x7ba4, 0x5d => 0x7b82, 0x5e => 0x7cbb, 0x5f => 0x7cbf, + 0x60 => 0x7cbc, 0x61 => 0x7cba, 0x62 => 0x7da7, 0x63 => 0x7db7, + 0x64 => 0x7dc2, 0x65 => 0x7da3, 0x66 => 0x7daa, 0x67 => 0x7dc1, + 0x68 => 0x7dc0, 0x69 => 0x7dc5, 0x6a => 0x7d9d, 0x6b => 0x7dce, + 0x6c => 0x7dc4, 0x6d => 0x7dc6, 0x6e => 0x7dcb, 0x6f => 0x7dcc, + 0x70 => 0x7daf, 0x71 => 0x7db9, 0x72 => 0x7d96, 0x73 => 0x7dbc, + 0x74 => 0x7d9f, 0x75 => 0x7da6, 0x76 => 0x7dae, 0x77 => 0x7da9, + 0x78 => 0x7da1, 0x79 => 0x7dc9, 0x7a => 0x7f73, 0x7b => 0x7fe2, + 0x7c => 0x7fe3, 0x7d => 0x7fe5, 0x7e => 0x7fde, 0xa1 => 0x8024, + 0xa2 => 0x805d, 0xa3 => 0x805c, 0xa4 => 0x8189, 0xa5 => 0x8186, + 0xa6 => 0x8183, 0xa7 => 0x8187, 0xa8 => 0x818d, 0xa9 => 0x818c, + 0xaa => 0x818b, 0xab => 0x8215, 0xac => 0x8497, 0xad => 0x84a4, + 0xae => 0x84a1, 0xaf => 0x849f, 0xb0 => 0x84ba, 0xb1 => 0x84ce, + 0xb2 => 0x84c2, 0xb3 => 0x84ac, 0xb4 => 0x84ae, 0xb5 => 0x84ab, + 0xb6 => 0x84b9, 0xb7 => 0x84b4, 0xb8 => 0x84c1, 0xb9 => 0x84cd, + 0xba => 0x84aa, 0xbb => 0x849a, 0xbc => 0x84b1, 0xbd => 0x84d0, + 0xbe => 0x849d, 0xbf => 0x84a7, 0xc0 => 0x84bb, 0xc1 => 0x84a2, + 0xc2 => 0x8494, 0xc3 => 0x84c7, 0xc4 => 0x84cc, 0xc5 => 0x849b, + 0xc6 => 0x84a9, 0xc7 => 0x84af, 0xc8 => 0x84a8, 0xc9 => 0x84d6, + 0xca => 0x8498, 0xcb => 0x84b6, 0xcc => 0x84cf, 0xcd => 0x84a0, + 0xce => 0x84d7, 0xcf => 0x84d4, 0xd0 => 0x84d2, 0xd1 => 0x84db, + 0xd2 => 0x84b0, 0xd3 => 0x8491, 0xd4 => 0x8661, 0xd5 => 0x8733, + 0xd6 => 0x8723, 0xd7 => 0x8728, 0xd8 => 0x876b, 0xd9 => 0x8740, + 0xda => 0x872e, 0xdb => 0x871e, 0xdc => 0x8721, 0xdd => 0x8719, + 0xde => 0x871b, 0xdf => 0x8743, 0xe0 => 0x872c, 0xe1 => 0x8741, + 0xe2 => 0x873e, 0xe3 => 0x8746, 0xe4 => 0x8720, 0xe5 => 0x8732, + 0xe6 => 0x872a, 0xe7 => 0x872d, 0xe8 => 0x873c, 0xe9 => 0x8712, + 0xea => 0x873a, 0xeb => 0x8731, 0xec => 0x8735, 0xed => 0x8742, + 0xee => 0x8726, 0xef => 0x8727, 0xf0 => 0x8738, 0xf1 => 0x8724, + 0xf2 => 0x871a, 0xf3 => 0x8730, 0xf4 => 0x8711, 0xf5 => 0x88f7, + 0xf6 => 0x88e7, 0xf7 => 0x88f1, 0xf8 => 0x88f2, 0xf9 => 0x88fa, + 0xfa => 0x88fe, 0xfb => 0x88ee, 0xfc => 0x88fc, 0xfd => 0x88f6, + 0xfe => 0x88fb, + }, + 0xe4 => { + 0x40 => 0x88f0, 0x41 => 0x88ec, 0x42 => 0x88eb, 0x43 => 0x899d, + 0x44 => 0x89a1, 0x45 => 0x899f, 0x46 => 0x899e, 0x47 => 0x89e9, + 0x48 => 0x89eb, 0x49 => 0x89e8, 0x4a => 0x8aab, 0x4b => 0x8a99, + 0x4c => 0x8a8b, 0x4d => 0x8a92, 0x4e => 0x8a8f, 0x4f => 0x8a96, + 0x50 => 0x8c3d, 0x51 => 0x8c68, 0x52 => 0x8c69, 0x53 => 0x8cd5, + 0x54 => 0x8ccf, 0x55 => 0x8cd7, 0x56 => 0x8d96, 0x57 => 0x8e09, + 0x58 => 0x8e02, 0x59 => 0x8dff, 0x5a => 0x8e0d, 0x5b => 0x8dfd, + 0x5c => 0x8e0a, 0x5d => 0x8e03, 0x5e => 0x8e07, 0x5f => 0x8e06, + 0x60 => 0x8e05, 0x61 => 0x8dfe, 0x62 => 0x8e00, 0x63 => 0x8e04, + 0x64 => 0x8f10, 0x65 => 0x8f11, 0x66 => 0x8f0e, 0x67 => 0x8f0d, + 0x68 => 0x9123, 0x69 => 0x911c, 0x6a => 0x9120, 0x6b => 0x9122, + 0x6c => 0x911f, 0x6d => 0x911d, 0x6e => 0x911a, 0x6f => 0x9124, + 0x70 => 0x9121, 0x71 => 0x911b, 0x72 => 0x917a, 0x73 => 0x9172, + 0x74 => 0x9179, 0x75 => 0x9173, 0x76 => 0x92a5, 0x77 => 0x92a4, + 0x78 => 0x9276, 0x79 => 0x929b, 0x7a => 0x927a, 0x7b => 0x92a0, + 0x7c => 0x9294, 0x7d => 0x92aa, 0x7e => 0x928d, 0xa1 => 0x92a6, + 0xa2 => 0x929a, 0xa3 => 0x92ab, 0xa4 => 0x9279, 0xa5 => 0x9297, + 0xa6 => 0x927f, 0xa7 => 0x92a3, 0xa8 => 0x92ee, 0xa9 => 0x928e, + 0xaa => 0x9282, 0xab => 0x9295, 0xac => 0x92a2, 0xad => 0x927d, + 0xae => 0x9288, 0xaf => 0x92a1, 0xb0 => 0x928a, 0xb1 => 0x9286, + 0xb2 => 0x928c, 0xb3 => 0x9299, 0xb4 => 0x92a7, 0xb5 => 0x927e, + 0xb6 => 0x9287, 0xb7 => 0x92a9, 0xb8 => 0x929d, 0xb9 => 0x928b, + 0xba => 0x922d, 0xbb => 0x969e, 0xbc => 0x96a1, 0xbd => 0x96ff, + 0xbe => 0x9758, 0xbf => 0x977d, 0xc0 => 0x977a, 0xc1 => 0x977e, + 0xc2 => 0x9783, 0xc3 => 0x9780, 0xc4 => 0x9782, 0xc5 => 0x977b, + 0xc6 => 0x9784, 0xc7 => 0x9781, 0xc8 => 0x977f, 0xc9 => 0x97ce, + 0xca => 0x97cd, 0xcb => 0x9816, 0xcc => 0x98ad, 0xcd => 0x98ae, + 0xce => 0x9902, 0xcf => 0x9900, 0xd0 => 0x9907, 0xd1 => 0x999d, + 0xd2 => 0x999c, 0xd3 => 0x99c3, 0xd4 => 0x99b9, 0xd5 => 0x99bb, + 0xd6 => 0x99ba, 0xd7 => 0x99c2, 0xd8 => 0x99bd, 0xd9 => 0x99c7, + 0xda => 0x9ab1, 0xdb => 0x9ae3, 0xdc => 0x9ae7, 0xdd => 0x9b3e, + 0xde => 0x9b3f, 0xdf => 0x9b60, 0xe0 => 0x9b61, 0xe1 => 0x9b5f, + 0xe2 => 0x9cf1, 0xe3 => 0x9cf2, 0xe4 => 0x9cf5, 0xe5 => 0x9ea7, + 0xe6 => 0x50ff, 0xe7 => 0x5103, 0xe8 => 0x5130, 0xe9 => 0x50f8, + 0xea => 0x5106, 0xeb => 0x5107, 0xec => 0x50f6, 0xed => 0x50fe, + 0xee => 0x510b, 0xef => 0x510c, 0xf0 => 0x50fd, 0xf1 => 0x510a, + 0xf2 => 0x528b, 0xf3 => 0x528c, 0xf4 => 0x52f1, 0xf5 => 0x52ef, + 0xf6 => 0x5648, 0xf7 => 0x5642, 0xf8 => 0x564c, 0xf9 => 0x5635, + 0xfa => 0x5641, 0xfb => 0x564a, 0xfc => 0x5649, 0xfd => 0x5646, + 0xfe => 0x5658, + }, + 0xe5 => { + 0x40 => 0x565a, 0x41 => 0x5640, 0x42 => 0x5633, 0x43 => 0x563d, + 0x44 => 0x562c, 0x45 => 0x563e, 0x46 => 0x5638, 0x47 => 0x562a, + 0x48 => 0x563a, 0x49 => 0x571a, 0x4a => 0x58ab, 0x4b => 0x589d, + 0x4c => 0x58b1, 0x4d => 0x58a0, 0x4e => 0x58a3, 0x4f => 0x58af, + 0x50 => 0x58ac, 0x51 => 0x58a5, 0x52 => 0x58a1, 0x53 => 0x58ff, + 0x54 => 0x5aff, 0x55 => 0x5af4, 0x56 => 0x5afd, 0x57 => 0x5af7, + 0x58 => 0x5af6, 0x59 => 0x5b03, 0x5a => 0x5af8, 0x5b => 0x5b02, + 0x5c => 0x5af9, 0x5d => 0x5b01, 0x5e => 0x5b07, 0x5f => 0x5b05, + 0x60 => 0x5b0f, 0x61 => 0x5c67, 0x62 => 0x5d99, 0x63 => 0x5d97, + 0x64 => 0x5d9f, 0x65 => 0x5d92, 0x66 => 0x5da2, 0x67 => 0x5d93, + 0x68 => 0x5d95, 0x69 => 0x5da0, 0x6a => 0x5d9c, 0x6b => 0x5da1, + 0x6c => 0x5d9a, 0x6d => 0x5d9e, 0x6e => 0x5e69, 0x6f => 0x5e5d, + 0x70 => 0x5e60, 0x71 => 0x5e5c, 0x72 => 0x7df3, 0x73 => 0x5edb, + 0x74 => 0x5ede, 0x75 => 0x5ee1, 0x76 => 0x5f49, 0x77 => 0x5fb2, + 0x78 => 0x618b, 0x79 => 0x6183, 0x7a => 0x6179, 0x7b => 0x61b1, + 0x7c => 0x61b0, 0x7d => 0x61a2, 0x7e => 0x6189, 0xa1 => 0x619b, + 0xa2 => 0x6193, 0xa3 => 0x61af, 0xa4 => 0x61ad, 0xa5 => 0x619f, + 0xa6 => 0x6192, 0xa7 => 0x61aa, 0xa8 => 0x61a1, 0xa9 => 0x618d, + 0xaa => 0x6166, 0xab => 0x61b3, 0xac => 0x622d, 0xad => 0x646e, + 0xae => 0x6470, 0xaf => 0x6496, 0xb0 => 0x64a0, 0xb1 => 0x6485, + 0xb2 => 0x6497, 0xb3 => 0x649c, 0xb4 => 0x648f, 0xb5 => 0x648b, + 0xb6 => 0x648a, 0xb7 => 0x648c, 0xb8 => 0x64a3, 0xb9 => 0x649f, + 0xba => 0x6468, 0xbb => 0x64b1, 0xbc => 0x6498, 0xbd => 0x6576, + 0xbe => 0x657a, 0xbf => 0x6579, 0xc0 => 0x657b, 0xc1 => 0x65b2, + 0xc2 => 0x65b3, 0xc3 => 0x66b5, 0xc4 => 0x66b0, 0xc5 => 0x66a9, + 0xc6 => 0x66b2, 0xc7 => 0x66b7, 0xc8 => 0x66aa, 0xc9 => 0x66af, + 0xca => 0x6a00, 0xcb => 0x6a06, 0xcc => 0x6a17, 0xcd => 0x69e5, + 0xce => 0x69f8, 0xcf => 0x6a15, 0xd0 => 0x69f1, 0xd1 => 0x69e4, + 0xd2 => 0x6a20, 0xd3 => 0x69ff, 0xd4 => 0x69ec, 0xd5 => 0x69e2, + 0xd6 => 0x6a1b, 0xd7 => 0x6a1d, 0xd8 => 0x69fe, 0xd9 => 0x6a27, + 0xda => 0x69f2, 0xdb => 0x69ee, 0xdc => 0x6a14, 0xdd => 0x69f7, + 0xde => 0x69e7, 0xdf => 0x6a40, 0xe0 => 0x6a08, 0xe1 => 0x69e6, + 0xe2 => 0x69fb, 0xe3 => 0x6a0d, 0xe4 => 0x69fc, 0xe5 => 0x69eb, + 0xe6 => 0x6a09, 0xe7 => 0x6a04, 0xe8 => 0x6a18, 0xe9 => 0x6a25, + 0xea => 0x6a0f, 0xeb => 0x69f6, 0xec => 0x6a26, 0xed => 0x6a07, + 0xee => 0x69f4, 0xef => 0x6a16, 0xf0 => 0x6b51, 0xf1 => 0x6ba5, + 0xf2 => 0x6ba3, 0xf3 => 0x6ba2, 0xf4 => 0x6ba6, 0xf5 => 0x6c01, + 0xf6 => 0x6c00, 0xf7 => 0x6bff, 0xf8 => 0x6c02, 0xf9 => 0x6f41, + 0xfa => 0x6f26, 0xfb => 0x6f7e, 0xfc => 0x6f87, 0xfd => 0x6fc6, + 0xfe => 0x6f92, + }, + 0xe6 => { + 0x40 => 0x6f8d, 0x41 => 0x6f89, 0x42 => 0x6f8c, 0x43 => 0x6f62, + 0x44 => 0x6f4f, 0x45 => 0x6f85, 0x46 => 0x6f5a, 0x47 => 0x6f96, + 0x48 => 0x6f76, 0x49 => 0x6f6c, 0x4a => 0x6f82, 0x4b => 0x6f55, + 0x4c => 0x6f72, 0x4d => 0x6f52, 0x4e => 0x6f50, 0x4f => 0x6f57, + 0x50 => 0x6f94, 0x51 => 0x6f93, 0x52 => 0x6f5d, 0x53 => 0x6f00, + 0x54 => 0x6f61, 0x55 => 0x6f6b, 0x56 => 0x6f7d, 0x57 => 0x6f67, + 0x58 => 0x6f90, 0x59 => 0x6f53, 0x5a => 0x6f8b, 0x5b => 0x6f69, + 0x5c => 0x6f7f, 0x5d => 0x6f95, 0x5e => 0x6f63, 0x5f => 0x6f77, + 0x60 => 0x6f6a, 0x61 => 0x6f7b, 0x62 => 0x71b2, 0x63 => 0x71af, + 0x64 => 0x719b, 0x65 => 0x71b0, 0x66 => 0x71a0, 0x67 => 0x719a, + 0x68 => 0x71a9, 0x69 => 0x71b5, 0x6a => 0x719d, 0x6b => 0x71a5, + 0x6c => 0x719e, 0x6d => 0x71a4, 0x6e => 0x71a1, 0x6f => 0x71aa, + 0x70 => 0x719c, 0x71 => 0x71a7, 0x72 => 0x71b3, 0x73 => 0x7298, + 0x74 => 0x729a, 0x75 => 0x7358, 0x76 => 0x7352, 0x77 => 0x735e, + 0x78 => 0x735f, 0x79 => 0x7360, 0x7a => 0x735d, 0x7b => 0x735b, + 0x7c => 0x7361, 0x7d => 0x735a, 0x7e => 0x7359, 0xa1 => 0x7362, + 0xa2 => 0x7487, 0xa3 => 0x7489, 0xa4 => 0x748a, 0xa5 => 0x7486, + 0xa6 => 0x7481, 0xa7 => 0x747d, 0xa8 => 0x7485, 0xa9 => 0x7488, + 0xaa => 0x747c, 0xab => 0x7479, 0xac => 0x7508, 0xad => 0x7507, + 0xae => 0x757e, 0xaf => 0x7625, 0xb0 => 0x761e, 0xb1 => 0x7619, + 0xb2 => 0x761d, 0xb3 => 0x761c, 0xb4 => 0x7623, 0xb5 => 0x761a, + 0xb6 => 0x7628, 0xb7 => 0x761b, 0xb8 => 0x769c, 0xb9 => 0x769d, + 0xba => 0x769e, 0xbb => 0x769b, 0xbc => 0x778d, 0xbd => 0x778f, + 0xbe => 0x7789, 0xbf => 0x7788, 0xc0 => 0x78cd, 0xc1 => 0x78bb, + 0xc2 => 0x78cf, 0xc3 => 0x78cc, 0xc4 => 0x78d1, 0xc5 => 0x78ce, + 0xc6 => 0x78d4, 0xc7 => 0x78c8, 0xc8 => 0x78c3, 0xc9 => 0x78c4, + 0xca => 0x78c9, 0xcb => 0x799a, 0xcc => 0x79a1, 0xcd => 0x79a0, + 0xce => 0x799c, 0xcf => 0x79a2, 0xd0 => 0x799b, 0xd1 => 0x6b76, + 0xd2 => 0x7a39, 0xd3 => 0x7ab2, 0xd4 => 0x7ab4, 0xd5 => 0x7ab3, + 0xd6 => 0x7bb7, 0xd7 => 0x7bcb, 0xd8 => 0x7bbe, 0xd9 => 0x7bac, + 0xda => 0x7bce, 0xdb => 0x7baf, 0xdc => 0x7bb9, 0xdd => 0x7bca, + 0xde => 0x7bb5, 0xdf => 0x7cc5, 0xe0 => 0x7cc8, 0xe1 => 0x7ccc, + 0xe2 => 0x7ccb, 0xe3 => 0x7df7, 0xe4 => 0x7ddb, 0xe5 => 0x7dea, + 0xe6 => 0x7de7, 0xe7 => 0x7dd7, 0xe8 => 0x7de1, 0xe9 => 0x7e03, + 0xea => 0x7dfa, 0xeb => 0x7de6, 0xec => 0x7df6, 0xed => 0x7df1, + 0xee => 0x7df0, 0xef => 0x7dee, 0xf0 => 0x7ddf, 0xf1 => 0x7f76, + 0xf2 => 0x7fac, 0xf3 => 0x7fb0, 0xf4 => 0x7fad, 0xf5 => 0x7fed, + 0xf6 => 0x7feb, 0xf7 => 0x7fea, 0xf8 => 0x7fec, 0xf9 => 0x7fe6, + 0xfa => 0x7fe8, 0xfb => 0x8064, 0xfc => 0x8067, 0xfd => 0x81a3, + 0xfe => 0x819f, + }, + 0xe7 => { + 0x40 => 0x819e, 0x41 => 0x8195, 0x42 => 0x81a2, 0x43 => 0x8199, + 0x44 => 0x8197, 0x45 => 0x8216, 0x46 => 0x824f, 0x47 => 0x8253, + 0x48 => 0x8252, 0x49 => 0x8250, 0x4a => 0x824e, 0x4b => 0x8251, + 0x4c => 0x8524, 0x4d => 0x853b, 0x4e => 0x850f, 0x4f => 0x8500, + 0x50 => 0x8529, 0x51 => 0x850e, 0x52 => 0x8509, 0x53 => 0x850d, + 0x54 => 0x851f, 0x55 => 0x850a, 0x56 => 0x8527, 0x57 => 0x851c, + 0x58 => 0x84fb, 0x59 => 0x852b, 0x5a => 0x84fa, 0x5b => 0x8508, + 0x5c => 0x850c, 0x5d => 0x84f4, 0x5e => 0x852a, 0x5f => 0x84f2, + 0x60 => 0x8515, 0x61 => 0x84f7, 0x62 => 0x84eb, 0x63 => 0x84f3, + 0x64 => 0x84fc, 0x65 => 0x8512, 0x66 => 0x84ea, 0x67 => 0x84e9, + 0x68 => 0x8516, 0x69 => 0x84fe, 0x6a => 0x8528, 0x6b => 0x851d, + 0x6c => 0x852e, 0x6d => 0x8502, 0x6e => 0x84fd, 0x6f => 0x851e, + 0x70 => 0x84f6, 0x71 => 0x8531, 0x72 => 0x8526, 0x73 => 0x84e7, + 0x74 => 0x84e8, 0x75 => 0x84f0, 0x76 => 0x84ef, 0x77 => 0x84f9, + 0x78 => 0x8518, 0x79 => 0x8520, 0x7a => 0x8530, 0x7b => 0x850b, + 0x7c => 0x8519, 0x7d => 0x852f, 0x7e => 0x8662, 0xa1 => 0x8756, + 0xa2 => 0x8763, 0xa3 => 0x8764, 0xa4 => 0x8777, 0xa5 => 0x87e1, + 0xa6 => 0x8773, 0xa7 => 0x8758, 0xa8 => 0x8754, 0xa9 => 0x875b, + 0xaa => 0x8752, 0xab => 0x8761, 0xac => 0x875a, 0xad => 0x8751, + 0xae => 0x875e, 0xaf => 0x876d, 0xb0 => 0x876a, 0xb1 => 0x8750, + 0xb2 => 0x874e, 0xb3 => 0x875f, 0xb4 => 0x875d, 0xb5 => 0x876f, + 0xb6 => 0x876c, 0xb7 => 0x877a, 0xb8 => 0x876e, 0xb9 => 0x875c, + 0xba => 0x8765, 0xbb => 0x874f, 0xbc => 0x877b, 0xbd => 0x8775, + 0xbe => 0x8762, 0xbf => 0x8767, 0xc0 => 0x8769, 0xc1 => 0x885a, + 0xc2 => 0x8905, 0xc3 => 0x890c, 0xc4 => 0x8914, 0xc5 => 0x890b, + 0xc6 => 0x8917, 0xc7 => 0x8918, 0xc8 => 0x8919, 0xc9 => 0x8906, + 0xca => 0x8916, 0xcb => 0x8911, 0xcc => 0x890e, 0xcd => 0x8909, + 0xce => 0x89a2, 0xcf => 0x89a4, 0xd0 => 0x89a3, 0xd1 => 0x89ed, + 0xd2 => 0x89f0, 0xd3 => 0x89ec, 0xd4 => 0x8acf, 0xd5 => 0x8ac6, + 0xd6 => 0x8ab8, 0xd7 => 0x8ad3, 0xd8 => 0x8ad1, 0xd9 => 0x8ad4, + 0xda => 0x8ad5, 0xdb => 0x8abb, 0xdc => 0x8ad7, 0xdd => 0x8abe, + 0xde => 0x8ac0, 0xdf => 0x8ac5, 0xe0 => 0x8ad8, 0xe1 => 0x8ac3, + 0xe2 => 0x8aba, 0xe3 => 0x8abd, 0xe4 => 0x8ad9, 0xe5 => 0x8c3e, + 0xe6 => 0x8c4d, 0xe7 => 0x8c8f, 0xe8 => 0x8ce5, 0xe9 => 0x8cdf, + 0xea => 0x8cd9, 0xeb => 0x8ce8, 0xec => 0x8cda, 0xed => 0x8cdd, + 0xee => 0x8ce7, 0xef => 0x8da0, 0xf0 => 0x8d9c, 0xf1 => 0x8da1, + 0xf2 => 0x8d9b, 0xf3 => 0x8e20, 0xf4 => 0x8e23, 0xf5 => 0x8e25, + 0xf6 => 0x8e24, 0xf7 => 0x8e2e, 0xf8 => 0x8e15, 0xf9 => 0x8e1b, + 0xfa => 0x8e16, 0xfb => 0x8e11, 0xfc => 0x8e19, 0xfd => 0x8e26, + 0xfe => 0x8e27, + }, + 0xe8 => { + 0x40 => 0x8e14, 0x41 => 0x8e12, 0x42 => 0x8e18, 0x43 => 0x8e13, + 0x44 => 0x8e1c, 0x45 => 0x8e17, 0x46 => 0x8e1a, 0x47 => 0x8f2c, + 0x48 => 0x8f24, 0x49 => 0x8f18, 0x4a => 0x8f1a, 0x4b => 0x8f20, + 0x4c => 0x8f23, 0x4d => 0x8f16, 0x4e => 0x8f17, 0x4f => 0x9073, + 0x50 => 0x9070, 0x51 => 0x906f, 0x52 => 0x9067, 0x53 => 0x906b, + 0x54 => 0x912f, 0x55 => 0x912b, 0x56 => 0x9129, 0x57 => 0x912a, + 0x58 => 0x9132, 0x59 => 0x9126, 0x5a => 0x912e, 0x5b => 0x9185, + 0x5c => 0x9186, 0x5d => 0x918a, 0x5e => 0x9181, 0x5f => 0x9182, + 0x60 => 0x9184, 0x61 => 0x9180, 0x62 => 0x92d0, 0x63 => 0x92c3, + 0x64 => 0x92c4, 0x65 => 0x92c0, 0x66 => 0x92d9, 0x67 => 0x92b6, + 0x68 => 0x92cf, 0x69 => 0x92f1, 0x6a => 0x92df, 0x6b => 0x92d8, + 0x6c => 0x92e9, 0x6d => 0x92d7, 0x6e => 0x92dd, 0x6f => 0x92cc, + 0x70 => 0x92ef, 0x71 => 0x92c2, 0x72 => 0x92e8, 0x73 => 0x92ca, + 0x74 => 0x92c8, 0x75 => 0x92ce, 0x76 => 0x92e6, 0x77 => 0x92cd, + 0x78 => 0x92d5, 0x79 => 0x92c9, 0x7a => 0x92e0, 0x7b => 0x92de, + 0x7c => 0x92e7, 0x7d => 0x92d1, 0x7e => 0x92d3, 0xa1 => 0x92b5, + 0xa2 => 0x92e1, 0xa3 => 0x92c6, 0xa4 => 0x92b4, 0xa5 => 0x957c, + 0xa6 => 0x95ac, 0xa7 => 0x95ab, 0xa8 => 0x95ae, 0xa9 => 0x95b0, + 0xaa => 0x96a4, 0xab => 0x96a2, 0xac => 0x96d3, 0xad => 0x9705, + 0xae => 0x9708, 0xaf => 0x9702, 0xb0 => 0x975a, 0xb1 => 0x978a, + 0xb2 => 0x978e, 0xb3 => 0x9788, 0xb4 => 0x97d0, 0xb5 => 0x97cf, + 0xb6 => 0x981e, 0xb7 => 0x981d, 0xb8 => 0x9826, 0xb9 => 0x9829, + 0xba => 0x9828, 0xbb => 0x9820, 0xbc => 0x981b, 0xbd => 0x9827, + 0xbe => 0x98b2, 0xbf => 0x9908, 0xc0 => 0x98fa, 0xc1 => 0x9911, + 0xc2 => 0x9914, 0xc3 => 0x9916, 0xc4 => 0x9917, 0xc5 => 0x9915, + 0xc6 => 0x99dc, 0xc7 => 0x99cd, 0xc8 => 0x99cf, 0xc9 => 0x99d3, + 0xca => 0x99d4, 0xcb => 0x99ce, 0xcc => 0x99c9, 0xcd => 0x99d6, + 0xce => 0x99d8, 0xcf => 0x99cb, 0xd0 => 0x99d7, 0xd1 => 0x99cc, + 0xd2 => 0x9ab3, 0xd3 => 0x9aec, 0xd4 => 0x9aeb, 0xd5 => 0x9af3, + 0xd6 => 0x9af2, 0xd7 => 0x9af1, 0xd8 => 0x9b46, 0xd9 => 0x9b43, + 0xda => 0x9b67, 0xdb => 0x9b74, 0xdc => 0x9b71, 0xdd => 0x9b66, + 0xde => 0x9b76, 0xdf => 0x9b75, 0xe0 => 0x9b70, 0xe1 => 0x9b68, + 0xe2 => 0x9b64, 0xe3 => 0x9b6c, 0xe4 => 0x9cfc, 0xe5 => 0x9cfa, + 0xe6 => 0x9cfd, 0xe7 => 0x9cff, 0xe8 => 0x9cf7, 0xe9 => 0x9d07, + 0xea => 0x9d00, 0xeb => 0x9cf9, 0xec => 0x9cfb, 0xed => 0x9d08, + 0xee => 0x9d05, 0xef => 0x9d04, 0xf0 => 0x9e83, 0xf1 => 0x9ed3, + 0xf2 => 0x9f0f, 0xf3 => 0x9f10, 0xf4 => 0x511c, 0xf5 => 0x5113, + 0xf6 => 0x5117, 0xf7 => 0x511a, 0xf8 => 0x5111, 0xf9 => 0x51de, + 0xfa => 0x5334, 0xfb => 0x53e1, 0xfc => 0x5670, 0xfd => 0x5660, + 0xfe => 0x566e, + }, + 0xe9 => { + 0x40 => 0x5673, 0x41 => 0x5666, 0x42 => 0x5663, 0x43 => 0x566d, + 0x44 => 0x5672, 0x45 => 0x565e, 0x46 => 0x5677, 0x47 => 0x571c, + 0x48 => 0x571b, 0x49 => 0x58c8, 0x4a => 0x58bd, 0x4b => 0x58c9, + 0x4c => 0x58bf, 0x4d => 0x58ba, 0x4e => 0x58c2, 0x4f => 0x58bc, + 0x50 => 0x58c6, 0x51 => 0x5b17, 0x52 => 0x5b19, 0x53 => 0x5b1b, + 0x54 => 0x5b21, 0x55 => 0x5b14, 0x56 => 0x5b13, 0x57 => 0x5b10, + 0x58 => 0x5b16, 0x59 => 0x5b28, 0x5a => 0x5b1a, 0x5b => 0x5b20, + 0x5c => 0x5b1e, 0x5d => 0x5bef, 0x5e => 0x5dac, 0x5f => 0x5db1, + 0x60 => 0x5da9, 0x61 => 0x5da7, 0x62 => 0x5db5, 0x63 => 0x5db0, + 0x64 => 0x5dae, 0x65 => 0x5daa, 0x66 => 0x5da8, 0x67 => 0x5db2, + 0x68 => 0x5dad, 0x69 => 0x5daf, 0x6a => 0x5db4, 0x6b => 0x5e67, + 0x6c => 0x5e68, 0x6d => 0x5e66, 0x6e => 0x5e6f, 0x6f => 0x5ee9, + 0x70 => 0x5ee7, 0x71 => 0x5ee6, 0x72 => 0x5ee8, 0x73 => 0x5ee5, + 0x74 => 0x5f4b, 0x75 => 0x5fbc, 0x76 => 0x619d, 0x77 => 0x61a8, + 0x78 => 0x6196, 0x79 => 0x61c5, 0x7a => 0x61b4, 0x7b => 0x61c6, + 0x7c => 0x61c1, 0x7d => 0x61cc, 0x7e => 0x61ba, 0xa1 => 0x61bf, + 0xa2 => 0x61b8, 0xa3 => 0x618c, 0xa4 => 0x64d7, 0xa5 => 0x64d6, + 0xa6 => 0x64d0, 0xa7 => 0x64cf, 0xa8 => 0x64c9, 0xa9 => 0x64bd, + 0xaa => 0x6489, 0xab => 0x64c3, 0xac => 0x64db, 0xad => 0x64f3, + 0xae => 0x64d9, 0xaf => 0x6533, 0xb0 => 0x657f, 0xb1 => 0x657c, + 0xb2 => 0x65a2, 0xb3 => 0x66c8, 0xb4 => 0x66be, 0xb5 => 0x66c0, + 0xb6 => 0x66ca, 0xb7 => 0x66cb, 0xb8 => 0x66cf, 0xb9 => 0x66bd, + 0xba => 0x66bb, 0xbb => 0x66ba, 0xbc => 0x66cc, 0xbd => 0x6723, + 0xbe => 0x6a34, 0xbf => 0x6a66, 0xc0 => 0x6a49, 0xc1 => 0x6a67, + 0xc2 => 0x6a32, 0xc3 => 0x6a68, 0xc4 => 0x6a3e, 0xc5 => 0x6a5d, + 0xc6 => 0x6a6d, 0xc7 => 0x6a76, 0xc8 => 0x6a5b, 0xc9 => 0x6a51, + 0xca => 0x6a28, 0xcb => 0x6a5a, 0xcc => 0x6a3b, 0xcd => 0x6a3f, + 0xce => 0x6a41, 0xcf => 0x6a6a, 0xd0 => 0x6a64, 0xd1 => 0x6a50, + 0xd2 => 0x6a4f, 0xd3 => 0x6a54, 0xd4 => 0x6a6f, 0xd5 => 0x6a69, + 0xd6 => 0x6a60, 0xd7 => 0x6a3c, 0xd8 => 0x6a5e, 0xd9 => 0x6a56, + 0xda => 0x6a55, 0xdb => 0x6a4d, 0xdc => 0x6a4e, 0xdd => 0x6a46, + 0xde => 0x6b55, 0xdf => 0x6b54, 0xe0 => 0x6b56, 0xe1 => 0x6ba7, + 0xe2 => 0x6baa, 0xe3 => 0x6bab, 0xe4 => 0x6bc8, 0xe5 => 0x6bc7, + 0xe6 => 0x6c04, 0xe7 => 0x6c03, 0xe8 => 0x6c06, 0xe9 => 0x6fad, + 0xea => 0x6fcb, 0xeb => 0x6fa3, 0xec => 0x6fc7, 0xed => 0x6fbc, + 0xee => 0x6fce, 0xef => 0x6fc8, 0xf0 => 0x6f5e, 0xf1 => 0x6fc4, + 0xf2 => 0x6fbd, 0xf3 => 0x6f9e, 0xf4 => 0x6fca, 0xf5 => 0x6fa8, + 0xf6 => 0x7004, 0xf7 => 0x6fa5, 0xf8 => 0x6fae, 0xf9 => 0x6fba, + 0xfa => 0x6fac, 0xfb => 0x6faa, 0xfc => 0x6fcf, 0xfd => 0x6fbf, + 0xfe => 0x6fb8, + }, + 0xea => { + 0x40 => 0x6fa2, 0x41 => 0x6fc9, 0x42 => 0x6fab, 0x43 => 0x6fcd, + 0x44 => 0x6faf, 0x45 => 0x6fb2, 0x46 => 0x6fb0, 0x47 => 0x71c5, + 0x48 => 0x71c2, 0x49 => 0x71bf, 0x4a => 0x71b8, 0x4b => 0x71d6, + 0x4c => 0x71c0, 0x4d => 0x71c1, 0x4e => 0x71cb, 0x4f => 0x71d4, + 0x50 => 0x71ca, 0x51 => 0x71c7, 0x52 => 0x71cf, 0x53 => 0x71bd, + 0x54 => 0x71d8, 0x55 => 0x71bc, 0x56 => 0x71c6, 0x57 => 0x71da, + 0x58 => 0x71db, 0x59 => 0x729d, 0x5a => 0x729e, 0x5b => 0x7369, + 0x5c => 0x7366, 0x5d => 0x7367, 0x5e => 0x736c, 0x5f => 0x7365, + 0x60 => 0x736b, 0x61 => 0x736a, 0x62 => 0x747f, 0x63 => 0x749a, + 0x64 => 0x74a0, 0x65 => 0x7494, 0x66 => 0x7492, 0x67 => 0x7495, + 0x68 => 0x74a1, 0x69 => 0x750b, 0x6a => 0x7580, 0x6b => 0x762f, + 0x6c => 0x762d, 0x6d => 0x7631, 0x6e => 0x763d, 0x6f => 0x7633, + 0x70 => 0x763c, 0x71 => 0x7635, 0x72 => 0x7632, 0x73 => 0x7630, + 0x74 => 0x76bb, 0x75 => 0x76e6, 0x76 => 0x779a, 0x77 => 0x779d, + 0x78 => 0x77a1, 0x79 => 0x779c, 0x7a => 0x779b, 0x7b => 0x77a2, + 0x7c => 0x77a3, 0x7d => 0x7795, 0x7e => 0x7799, 0xa1 => 0x7797, + 0xa2 => 0x78dd, 0xa3 => 0x78e9, 0xa4 => 0x78e5, 0xa5 => 0x78ea, + 0xa6 => 0x78de, 0xa7 => 0x78e3, 0xa8 => 0x78db, 0xa9 => 0x78e1, + 0xaa => 0x78e2, 0xab => 0x78ed, 0xac => 0x78df, 0xad => 0x78e0, + 0xae => 0x79a4, 0xaf => 0x7a44, 0xb0 => 0x7a48, 0xb1 => 0x7a47, + 0xb2 => 0x7ab6, 0xb3 => 0x7ab8, 0xb4 => 0x7ab5, 0xb5 => 0x7ab1, + 0xb6 => 0x7ab7, 0xb7 => 0x7bde, 0xb8 => 0x7be3, 0xb9 => 0x7be7, + 0xba => 0x7bdd, 0xbb => 0x7bd5, 0xbc => 0x7be5, 0xbd => 0x7bda, + 0xbe => 0x7be8, 0xbf => 0x7bf9, 0xc0 => 0x7bd4, 0xc1 => 0x7bea, + 0xc2 => 0x7be2, 0xc3 => 0x7bdc, 0xc4 => 0x7beb, 0xc5 => 0x7bd8, + 0xc6 => 0x7bdf, 0xc7 => 0x7cd2, 0xc8 => 0x7cd4, 0xc9 => 0x7cd7, + 0xca => 0x7cd0, 0xcb => 0x7cd1, 0xcc => 0x7e12, 0xcd => 0x7e21, + 0xce => 0x7e17, 0xcf => 0x7e0c, 0xd0 => 0x7e1f, 0xd1 => 0x7e20, + 0xd2 => 0x7e13, 0xd3 => 0x7e0e, 0xd4 => 0x7e1c, 0xd5 => 0x7e15, + 0xd6 => 0x7e1a, 0xd7 => 0x7e22, 0xd8 => 0x7e0b, 0xd9 => 0x7e0f, + 0xda => 0x7e16, 0xdb => 0x7e0d, 0xdc => 0x7e14, 0xdd => 0x7e25, + 0xde => 0x7e24, 0xdf => 0x7f43, 0xe0 => 0x7f7b, 0xe1 => 0x7f7c, + 0xe2 => 0x7f7a, 0xe3 => 0x7fb1, 0xe4 => 0x7fef, 0xe5 => 0x802a, + 0xe6 => 0x8029, 0xe7 => 0x806c, 0xe8 => 0x81b1, 0xe9 => 0x81a6, + 0xea => 0x81ae, 0xeb => 0x81b9, 0xec => 0x81b5, 0xed => 0x81ab, + 0xee => 0x81b0, 0xef => 0x81ac, 0xf0 => 0x81b4, 0xf1 => 0x81b2, + 0xf2 => 0x81b7, 0xf3 => 0x81a7, 0xf4 => 0x81f2, 0xf5 => 0x8255, + 0xf6 => 0x8256, 0xf7 => 0x8257, 0xf8 => 0x8556, 0xf9 => 0x8545, + 0xfa => 0x856b, 0xfb => 0x854d, 0xfc => 0x8553, 0xfd => 0x8561, + 0xfe => 0x8558, + }, + 0xeb => { + 0x40 => 0x8540, 0x41 => 0x8546, 0x42 => 0x8564, 0x43 => 0x8541, + 0x44 => 0x8562, 0x45 => 0x8544, 0x46 => 0x8551, 0x47 => 0x8547, + 0x48 => 0x8563, 0x49 => 0x853e, 0x4a => 0x855b, 0x4b => 0x8571, + 0x4c => 0x854e, 0x4d => 0x856e, 0x4e => 0x8575, 0x4f => 0x8555, + 0x50 => 0x8567, 0x51 => 0x8560, 0x52 => 0x858c, 0x53 => 0x8566, + 0x54 => 0x855d, 0x55 => 0x8554, 0x56 => 0x8565, 0x57 => 0x856c, + 0x58 => 0x8663, 0x59 => 0x8665, 0x5a => 0x8664, 0x5b => 0x879b, + 0x5c => 0x878f, 0x5d => 0x8797, 0x5e => 0x8793, 0x5f => 0x8792, + 0x60 => 0x8788, 0x61 => 0x8781, 0x62 => 0x8796, 0x63 => 0x8798, + 0x64 => 0x8779, 0x65 => 0x8787, 0x66 => 0x87a3, 0x67 => 0x8785, + 0x68 => 0x8790, 0x69 => 0x8791, 0x6a => 0x879d, 0x6b => 0x8784, + 0x6c => 0x8794, 0x6d => 0x879c, 0x6e => 0x879a, 0x6f => 0x8789, + 0x70 => 0x891e, 0x71 => 0x8926, 0x72 => 0x8930, 0x73 => 0x892d, + 0x74 => 0x892e, 0x75 => 0x8927, 0x76 => 0x8931, 0x77 => 0x8922, + 0x78 => 0x8929, 0x79 => 0x8923, 0x7a => 0x892f, 0x7b => 0x892c, + 0x7c => 0x891f, 0x7d => 0x89f1, 0x7e => 0x8ae0, 0xa1 => 0x8ae2, + 0xa2 => 0x8af2, 0xa3 => 0x8af4, 0xa4 => 0x8af5, 0xa5 => 0x8add, + 0xa6 => 0x8b14, 0xa7 => 0x8ae4, 0xa8 => 0x8adf, 0xa9 => 0x8af0, + 0xaa => 0x8ac8, 0xab => 0x8ade, 0xac => 0x8ae1, 0xad => 0x8ae8, + 0xae => 0x8aff, 0xaf => 0x8aef, 0xb0 => 0x8afb, 0xb1 => 0x8c91, + 0xb2 => 0x8c92, 0xb3 => 0x8c90, 0xb4 => 0x8cf5, 0xb5 => 0x8cee, + 0xb6 => 0x8cf1, 0xb7 => 0x8cf0, 0xb8 => 0x8cf3, 0xb9 => 0x8d6c, + 0xba => 0x8d6e, 0xbb => 0x8da5, 0xbc => 0x8da7, 0xbd => 0x8e33, + 0xbe => 0x8e3e, 0xbf => 0x8e38, 0xc0 => 0x8e40, 0xc1 => 0x8e45, + 0xc2 => 0x8e36, 0xc3 => 0x8e3c, 0xc4 => 0x8e3d, 0xc5 => 0x8e41, + 0xc6 => 0x8e30, 0xc7 => 0x8e3f, 0xc8 => 0x8ebd, 0xc9 => 0x8f36, + 0xca => 0x8f2e, 0xcb => 0x8f35, 0xcc => 0x8f32, 0xcd => 0x8f39, + 0xce => 0x8f37, 0xcf => 0x8f34, 0xd0 => 0x9076, 0xd1 => 0x9079, + 0xd2 => 0x907b, 0xd3 => 0x9086, 0xd4 => 0x90fa, 0xd5 => 0x9133, + 0xd6 => 0x9135, 0xd7 => 0x9136, 0xd8 => 0x9193, 0xd9 => 0x9190, + 0xda => 0x9191, 0xdb => 0x918d, 0xdc => 0x918f, 0xdd => 0x9327, + 0xde => 0x931e, 0xdf => 0x9308, 0xe0 => 0x931f, 0xe1 => 0x9306, + 0xe2 => 0x930f, 0xe3 => 0x937a, 0xe4 => 0x9338, 0xe5 => 0x933c, + 0xe6 => 0x931b, 0xe7 => 0x9323, 0xe8 => 0x9312, 0xe9 => 0x9301, + 0xea => 0x9346, 0xeb => 0x932d, 0xec => 0x930e, 0xed => 0x930d, + 0xee => 0x92cb, 0xef => 0x931d, 0xf0 => 0x92fa, 0xf1 => 0x9325, + 0xf2 => 0x9313, 0xf3 => 0x92f9, 0xf4 => 0x92f7, 0xf5 => 0x9334, + 0xf6 => 0x9302, 0xf7 => 0x9324, 0xf8 => 0x92ff, 0xf9 => 0x9329, + 0xfa => 0x9339, 0xfb => 0x9335, 0xfc => 0x932a, 0xfd => 0x9314, + 0xfe => 0x930c, + }, + 0xec => { + 0x40 => 0x930b, 0x41 => 0x92fe, 0x42 => 0x9309, 0x43 => 0x9300, + 0x44 => 0x92fb, 0x45 => 0x9316, 0x46 => 0x95bc, 0x47 => 0x95cd, + 0x48 => 0x95be, 0x49 => 0x95b9, 0x4a => 0x95ba, 0x4b => 0x95b6, + 0x4c => 0x95bf, 0x4d => 0x95b5, 0x4e => 0x95bd, 0x4f => 0x96a9, + 0x50 => 0x96d4, 0x51 => 0x970b, 0x52 => 0x9712, 0x53 => 0x9710, + 0x54 => 0x9799, 0x55 => 0x9797, 0x56 => 0x9794, 0x57 => 0x97f0, + 0x58 => 0x97f8, 0x59 => 0x9835, 0x5a => 0x982f, 0x5b => 0x9832, + 0x5c => 0x9924, 0x5d => 0x991f, 0x5e => 0x9927, 0x5f => 0x9929, + 0x60 => 0x999e, 0x61 => 0x99ee, 0x62 => 0x99ec, 0x63 => 0x99e5, + 0x64 => 0x99e4, 0x65 => 0x99f0, 0x66 => 0x99e3, 0x67 => 0x99ea, + 0x68 => 0x99e9, 0x69 => 0x99e7, 0x6a => 0x9ab9, 0x6b => 0x9abf, + 0x6c => 0x9ab4, 0x6d => 0x9abb, 0x6e => 0x9af6, 0x6f => 0x9afa, + 0x70 => 0x9af9, 0x71 => 0x9af7, 0x72 => 0x9b33, 0x73 => 0x9b80, + 0x74 => 0x9b85, 0x75 => 0x9b87, 0x76 => 0x9b7c, 0x77 => 0x9b7e, + 0x78 => 0x9b7b, 0x79 => 0x9b82, 0x7a => 0x9b93, 0x7b => 0x9b92, + 0x7c => 0x9b90, 0x7d => 0x9b7a, 0x7e => 0x9b95, 0xa1 => 0x9b7d, + 0xa2 => 0x9b88, 0xa3 => 0x9d25, 0xa4 => 0x9d17, 0xa5 => 0x9d20, + 0xa6 => 0x9d1e, 0xa7 => 0x9d14, 0xa8 => 0x9d29, 0xa9 => 0x9d1d, + 0xaa => 0x9d18, 0xab => 0x9d22, 0xac => 0x9d10, 0xad => 0x9d19, + 0xae => 0x9d1f, 0xaf => 0x9e88, 0xb0 => 0x9e86, 0xb1 => 0x9e87, + 0xb2 => 0x9eae, 0xb3 => 0x9ead, 0xb4 => 0x9ed5, 0xb5 => 0x9ed6, + 0xb6 => 0x9efa, 0xb7 => 0x9f12, 0xb8 => 0x9f3d, 0xb9 => 0x5126, + 0xba => 0x5125, 0xbb => 0x5122, 0xbc => 0x5124, 0xbd => 0x5120, + 0xbe => 0x5129, 0xbf => 0x52f4, 0xc0 => 0x5693, 0xc1 => 0x568c, + 0xc2 => 0x568d, 0xc3 => 0x5686, 0xc4 => 0x5684, 0xc5 => 0x5683, + 0xc6 => 0x567e, 0xc7 => 0x5682, 0xc8 => 0x567f, 0xc9 => 0x5681, + 0xca => 0x58d6, 0xcb => 0x58d4, 0xcc => 0x58cf, 0xcd => 0x58d2, + 0xce => 0x5b2d, 0xcf => 0x5b25, 0xd0 => 0x5b32, 0xd1 => 0x5b23, + 0xd2 => 0x5b2c, 0xd3 => 0x5b27, 0xd4 => 0x5b26, 0xd5 => 0x5b2f, + 0xd6 => 0x5b2e, 0xd7 => 0x5b7b, 0xd8 => 0x5bf1, 0xd9 => 0x5bf2, + 0xda => 0x5db7, 0xdb => 0x5e6c, 0xdc => 0x5e6a, 0xdd => 0x5fbe, + 0xde => 0x5fbb, 0xdf => 0x61c3, 0xe0 => 0x61b5, 0xe1 => 0x61bc, + 0xe2 => 0x61e7, 0xe3 => 0x61e0, 0xe4 => 0x61e5, 0xe5 => 0x61e4, + 0xe6 => 0x61e8, 0xe7 => 0x61de, 0xe8 => 0x64ef, 0xe9 => 0x64e9, + 0xea => 0x64e3, 0xeb => 0x64eb, 0xec => 0x64e4, 0xed => 0x64e8, + 0xee => 0x6581, 0xef => 0x6580, 0xf0 => 0x65b6, 0xf1 => 0x65da, + 0xf2 => 0x66d2, 0xf3 => 0x6a8d, 0xf4 => 0x6a96, 0xf5 => 0x6a81, + 0xf6 => 0x6aa5, 0xf7 => 0x6a89, 0xf8 => 0x6a9f, 0xf9 => 0x6a9b, + 0xfa => 0x6aa1, 0xfb => 0x6a9e, 0xfc => 0x6a87, 0xfd => 0x6a93, + 0xfe => 0x6a8e, + }, + 0xed => { + 0x40 => 0x6a95, 0x41 => 0x6a83, 0x42 => 0x6aa8, 0x43 => 0x6aa4, + 0x44 => 0x6a91, 0x45 => 0x6a7f, 0x46 => 0x6aa6, 0x47 => 0x6a9a, + 0x48 => 0x6a85, 0x49 => 0x6a8c, 0x4a => 0x6a92, 0x4b => 0x6b5b, + 0x4c => 0x6bad, 0x4d => 0x6c09, 0x4e => 0x6fcc, 0x4f => 0x6fa9, + 0x50 => 0x6ff4, 0x51 => 0x6fd4, 0x52 => 0x6fe3, 0x53 => 0x6fdc, + 0x54 => 0x6fed, 0x55 => 0x6fe7, 0x56 => 0x6fe6, 0x57 => 0x6fde, + 0x58 => 0x6ff2, 0x59 => 0x6fdd, 0x5a => 0x6fe2, 0x5b => 0x6fe8, + 0x5c => 0x71e1, 0x5d => 0x71f1, 0x5e => 0x71e8, 0x5f => 0x71f2, + 0x60 => 0x71e4, 0x61 => 0x71f0, 0x62 => 0x71e2, 0x63 => 0x7373, + 0x64 => 0x736e, 0x65 => 0x736f, 0x66 => 0x7497, 0x67 => 0x74b2, + 0x68 => 0x74ab, 0x69 => 0x7490, 0x6a => 0x74aa, 0x6b => 0x74ad, + 0x6c => 0x74b1, 0x6d => 0x74a5, 0x6e => 0x74af, 0x6f => 0x7510, + 0x70 => 0x7511, 0x71 => 0x7512, 0x72 => 0x750f, 0x73 => 0x7584, + 0x74 => 0x7643, 0x75 => 0x7648, 0x76 => 0x7649, 0x77 => 0x7647, + 0x78 => 0x76a4, 0x79 => 0x76e9, 0x7a => 0x77b5, 0x7b => 0x77ab, + 0x7c => 0x77b2, 0x7d => 0x77b7, 0x7e => 0x77b6, 0xa1 => 0x77b4, + 0xa2 => 0x77b1, 0xa3 => 0x77a8, 0xa4 => 0x77f0, 0xa5 => 0x78f3, + 0xa6 => 0x78fd, 0xa7 => 0x7902, 0xa8 => 0x78fb, 0xa9 => 0x78fc, + 0xaa => 0x78f2, 0xab => 0x7905, 0xac => 0x78f9, 0xad => 0x78fe, + 0xae => 0x7904, 0xaf => 0x79ab, 0xb0 => 0x79a8, 0xb1 => 0x7a5c, + 0xb2 => 0x7a5b, 0xb3 => 0x7a56, 0xb4 => 0x7a58, 0xb5 => 0x7a54, + 0xb6 => 0x7a5a, 0xb7 => 0x7abe, 0xb8 => 0x7ac0, 0xb9 => 0x7ac1, + 0xba => 0x7c05, 0xbb => 0x7c0f, 0xbc => 0x7bf2, 0xbd => 0x7c00, + 0xbe => 0x7bff, 0xbf => 0x7bfb, 0xc0 => 0x7c0e, 0xc1 => 0x7bf4, + 0xc2 => 0x7c0b, 0xc3 => 0x7bf3, 0xc4 => 0x7c02, 0xc5 => 0x7c09, + 0xc6 => 0x7c03, 0xc7 => 0x7c01, 0xc8 => 0x7bf8, 0xc9 => 0x7bfd, + 0xca => 0x7c06, 0xcb => 0x7bf0, 0xcc => 0x7bf1, 0xcd => 0x7c10, + 0xce => 0x7c0a, 0xcf => 0x7ce8, 0xd0 => 0x7e2d, 0xd1 => 0x7e3c, + 0xd2 => 0x7e42, 0xd3 => 0x7e33, 0xd4 => 0x9848, 0xd5 => 0x7e38, + 0xd6 => 0x7e2a, 0xd7 => 0x7e49, 0xd8 => 0x7e40, 0xd9 => 0x7e47, + 0xda => 0x7e29, 0xdb => 0x7e4c, 0xdc => 0x7e30, 0xdd => 0x7e3b, + 0xde => 0x7e36, 0xdf => 0x7e44, 0xe0 => 0x7e3a, 0xe1 => 0x7f45, + 0xe2 => 0x7f7f, 0xe3 => 0x7f7e, 0xe4 => 0x7f7d, 0xe5 => 0x7ff4, + 0xe6 => 0x7ff2, 0xe7 => 0x802c, 0xe8 => 0x81bb, 0xe9 => 0x81c4, + 0xea => 0x81cc, 0xeb => 0x81ca, 0xec => 0x81c5, 0xed => 0x81c7, + 0xee => 0x81bc, 0xef => 0x81e9, 0xf0 => 0x825b, 0xf1 => 0x825a, + 0xf2 => 0x825c, 0xf3 => 0x8583, 0xf4 => 0x8580, 0xf5 => 0x858f, + 0xf6 => 0x85a7, 0xf7 => 0x8595, 0xf8 => 0x85a0, 0xf9 => 0x858b, + 0xfa => 0x85a3, 0xfb => 0x857b, 0xfc => 0x85a4, 0xfd => 0x859a, + 0xfe => 0x859e, + }, + 0xee => { + 0x40 => 0x8577, 0x41 => 0x857c, 0x42 => 0x8589, 0x43 => 0x85a1, + 0x44 => 0x857a, 0x45 => 0x8578, 0x46 => 0x8557, 0x47 => 0x858e, + 0x48 => 0x8596, 0x49 => 0x8586, 0x4a => 0x858d, 0x4b => 0x8599, + 0x4c => 0x859d, 0x4d => 0x8581, 0x4e => 0x85a2, 0x4f => 0x8582, + 0x50 => 0x8588, 0x51 => 0x8585, 0x52 => 0x8579, 0x53 => 0x8576, + 0x54 => 0x8598, 0x55 => 0x8590, 0x56 => 0x859f, 0x57 => 0x8668, + 0x58 => 0x87be, 0x59 => 0x87aa, 0x5a => 0x87ad, 0x5b => 0x87c5, + 0x5c => 0x87b0, 0x5d => 0x87ac, 0x5e => 0x87b9, 0x5f => 0x87b5, + 0x60 => 0x87bc, 0x61 => 0x87ae, 0x62 => 0x87c9, 0x63 => 0x87c3, + 0x64 => 0x87c2, 0x65 => 0x87cc, 0x66 => 0x87b7, 0x67 => 0x87af, + 0x68 => 0x87c4, 0x69 => 0x87ca, 0x6a => 0x87b4, 0x6b => 0x87b6, + 0x6c => 0x87bf, 0x6d => 0x87b8, 0x6e => 0x87bd, 0x6f => 0x87de, + 0x70 => 0x87b2, 0x71 => 0x8935, 0x72 => 0x8933, 0x73 => 0x893c, + 0x74 => 0x893e, 0x75 => 0x8941, 0x76 => 0x8952, 0x77 => 0x8937, + 0x78 => 0x8942, 0x79 => 0x89ad, 0x7a => 0x89af, 0x7b => 0x89ae, + 0x7c => 0x89f2, 0x7d => 0x89f3, 0x7e => 0x8b1e, 0xa1 => 0x8b18, + 0xa2 => 0x8b16, 0xa3 => 0x8b11, 0xa4 => 0x8b05, 0xa5 => 0x8b0b, + 0xa6 => 0x8b22, 0xa7 => 0x8b0f, 0xa8 => 0x8b12, 0xa9 => 0x8b15, + 0xaa => 0x8b07, 0xab => 0x8b0d, 0xac => 0x8b08, 0xad => 0x8b06, + 0xae => 0x8b1c, 0xaf => 0x8b13, 0xb0 => 0x8b1a, 0xb1 => 0x8c4f, + 0xb2 => 0x8c70, 0xb3 => 0x8c72, 0xb4 => 0x8c71, 0xb5 => 0x8c6f, + 0xb6 => 0x8c95, 0xb7 => 0x8c94, 0xb8 => 0x8cf9, 0xb9 => 0x8d6f, + 0xba => 0x8e4e, 0xbb => 0x8e4d, 0xbc => 0x8e53, 0xbd => 0x8e50, + 0xbe => 0x8e4c, 0xbf => 0x8e47, 0xc0 => 0x8f43, 0xc1 => 0x8f40, + 0xc2 => 0x9085, 0xc3 => 0x907e, 0xc4 => 0x9138, 0xc5 => 0x919a, + 0xc6 => 0x91a2, 0xc7 => 0x919b, 0xc8 => 0x9199, 0xc9 => 0x919f, + 0xca => 0x91a1, 0xcb => 0x919d, 0xcc => 0x91a0, 0xcd => 0x93a1, + 0xce => 0x9383, 0xcf => 0x93af, 0xd0 => 0x9364, 0xd1 => 0x9356, + 0xd2 => 0x9347, 0xd3 => 0x937c, 0xd4 => 0x9358, 0xd5 => 0x935c, + 0xd6 => 0x9376, 0xd7 => 0x9349, 0xd8 => 0x9350, 0xd9 => 0x9351, + 0xda => 0x9360, 0xdb => 0x936d, 0xdc => 0x938f, 0xdd => 0x934c, + 0xde => 0x936a, 0xdf => 0x9379, 0xe0 => 0x9357, 0xe1 => 0x9355, + 0xe2 => 0x9352, 0xe3 => 0x934f, 0xe4 => 0x9371, 0xe5 => 0x9377, + 0xe6 => 0x937b, 0xe7 => 0x9361, 0xe8 => 0x935e, 0xe9 => 0x9363, + 0xea => 0x9367, 0xeb => 0x9380, 0xec => 0x934e, 0xed => 0x9359, + 0xee => 0x95c7, 0xef => 0x95c0, 0xf0 => 0x95c9, 0xf1 => 0x95c3, + 0xf2 => 0x95c5, 0xf3 => 0x95b7, 0xf4 => 0x96ae, 0xf5 => 0x96b0, + 0xf6 => 0x96ac, 0xf7 => 0x9720, 0xf8 => 0x971f, 0xf9 => 0x9718, + 0xfa => 0x971d, 0xfb => 0x9719, 0xfc => 0x979a, 0xfd => 0x97a1, + 0xfe => 0x979c, + }, + 0xef => { + 0x40 => 0x979e, 0x41 => 0x979d, 0x42 => 0x97d5, 0x43 => 0x97d4, + 0x44 => 0x97f1, 0x45 => 0x9841, 0x46 => 0x9844, 0x47 => 0x984a, + 0x48 => 0x9849, 0x49 => 0x9845, 0x4a => 0x9843, 0x4b => 0x9925, + 0x4c => 0x992b, 0x4d => 0x992c, 0x4e => 0x992a, 0x4f => 0x9933, + 0x50 => 0x9932, 0x51 => 0x992f, 0x52 => 0x992d, 0x53 => 0x9931, + 0x54 => 0x9930, 0x55 => 0x9998, 0x56 => 0x99a3, 0x57 => 0x99a1, + 0x58 => 0x9a02, 0x59 => 0x99fa, 0x5a => 0x99f4, 0x5b => 0x99f7, + 0x5c => 0x99f9, 0x5d => 0x99f8, 0x5e => 0x99f6, 0x5f => 0x99fb, + 0x60 => 0x99fd, 0x61 => 0x99fe, 0x62 => 0x99fc, 0x63 => 0x9a03, + 0x64 => 0x9abe, 0x65 => 0x9afe, 0x66 => 0x9afd, 0x67 => 0x9b01, + 0x68 => 0x9afc, 0x69 => 0x9b48, 0x6a => 0x9b9a, 0x6b => 0x9ba8, + 0x6c => 0x9b9e, 0x6d => 0x9b9b, 0x6e => 0x9ba6, 0x6f => 0x9ba1, + 0x70 => 0x9ba5, 0x71 => 0x9ba4, 0x72 => 0x9b86, 0x73 => 0x9ba2, + 0x74 => 0x9ba0, 0x75 => 0x9baf, 0x76 => 0x9d33, 0x77 => 0x9d41, + 0x78 => 0x9d67, 0x79 => 0x9d36, 0x7a => 0x9d2e, 0x7b => 0x9d2f, + 0x7c => 0x9d31, 0x7d => 0x9d38, 0x7e => 0x9d30, 0xa1 => 0x9d45, + 0xa2 => 0x9d42, 0xa3 => 0x9d43, 0xa4 => 0x9d3e, 0xa5 => 0x9d37, + 0xa6 => 0x9d40, 0xa7 => 0x9d3d, 0xa8 => 0x7ff5, 0xa9 => 0x9d2d, + 0xaa => 0x9e8a, 0xab => 0x9e89, 0xac => 0x9e8d, 0xad => 0x9eb0, + 0xae => 0x9ec8, 0xaf => 0x9eda, 0xb0 => 0x9efb, 0xb1 => 0x9eff, + 0xb2 => 0x9f24, 0xb3 => 0x9f23, 0xb4 => 0x9f22, 0xb5 => 0x9f54, + 0xb6 => 0x9fa0, 0xb7 => 0x5131, 0xb8 => 0x512d, 0xb9 => 0x512e, + 0xba => 0x5698, 0xbb => 0x569c, 0xbc => 0x5697, 0xbd => 0x569a, + 0xbe => 0x569d, 0xbf => 0x5699, 0xc0 => 0x5970, 0xc1 => 0x5b3c, + 0xc2 => 0x5c69, 0xc3 => 0x5c6a, 0xc4 => 0x5dc0, 0xc5 => 0x5e6d, + 0xc6 => 0x5e6e, 0xc7 => 0x61d8, 0xc8 => 0x61df, 0xc9 => 0x61ed, + 0xca => 0x61ee, 0xcb => 0x61f1, 0xcc => 0x61ea, 0xcd => 0x61f0, + 0xce => 0x61eb, 0xcf => 0x61d6, 0xd0 => 0x61e9, 0xd1 => 0x64ff, + 0xd2 => 0x6504, 0xd3 => 0x64fd, 0xd4 => 0x64f8, 0xd5 => 0x6501, + 0xd6 => 0x6503, 0xd7 => 0x64fc, 0xd8 => 0x6594, 0xd9 => 0x65db, + 0xda => 0x66da, 0xdb => 0x66db, 0xdc => 0x66d8, 0xdd => 0x6ac5, + 0xde => 0x6ab9, 0xdf => 0x6abd, 0xe0 => 0x6ae1, 0xe1 => 0x6ac6, + 0xe2 => 0x6aba, 0xe3 => 0x6ab6, 0xe4 => 0x6ab7, 0xe5 => 0x6ac7, + 0xe6 => 0x6ab4, 0xe7 => 0x6aad, 0xe8 => 0x6b5e, 0xe9 => 0x6bc9, + 0xea => 0x6c0b, 0xeb => 0x7007, 0xec => 0x700c, 0xed => 0x700d, + 0xee => 0x7001, 0xef => 0x7005, 0xf0 => 0x7014, 0xf1 => 0x700e, + 0xf2 => 0x6fff, 0xf3 => 0x7000, 0xf4 => 0x6ffb, 0xf5 => 0x7026, + 0xf6 => 0x6ffc, 0xf7 => 0x6ff7, 0xf8 => 0x700a, 0xf9 => 0x7201, + 0xfa => 0x71ff, 0xfb => 0x71f9, 0xfc => 0x7203, 0xfd => 0x71fd, + 0xfe => 0x7376, + }, + 0xf0 => { + 0x40 => 0x74b8, 0x41 => 0x74c0, 0x42 => 0x74b5, 0x43 => 0x74c1, + 0x44 => 0x74be, 0x45 => 0x74b6, 0x46 => 0x74bb, 0x47 => 0x74c2, + 0x48 => 0x7514, 0x49 => 0x7513, 0x4a => 0x765c, 0x4b => 0x7664, + 0x4c => 0x7659, 0x4d => 0x7650, 0x4e => 0x7653, 0x4f => 0x7657, + 0x50 => 0x765a, 0x51 => 0x76a6, 0x52 => 0x76bd, 0x53 => 0x76ec, + 0x54 => 0x77c2, 0x55 => 0x77ba, 0x56 => 0x78ff, 0x57 => 0x790c, + 0x58 => 0x7913, 0x59 => 0x7914, 0x5a => 0x7909, 0x5b => 0x7910, + 0x5c => 0x7912, 0x5d => 0x7911, 0x5e => 0x79ad, 0x5f => 0x79ac, + 0x60 => 0x7a5f, 0x61 => 0x7c1c, 0x62 => 0x7c29, 0x63 => 0x7c19, + 0x64 => 0x7c20, 0x65 => 0x7c1f, 0x66 => 0x7c2d, 0x67 => 0x7c1d, + 0x68 => 0x7c26, 0x69 => 0x7c28, 0x6a => 0x7c22, 0x6b => 0x7c25, + 0x6c => 0x7c30, 0x6d => 0x7e5c, 0x6e => 0x7e50, 0x6f => 0x7e56, + 0x70 => 0x7e63, 0x71 => 0x7e58, 0x72 => 0x7e62, 0x73 => 0x7e5f, + 0x74 => 0x7e51, 0x75 => 0x7e60, 0x76 => 0x7e57, 0x77 => 0x7e53, + 0x78 => 0x7fb5, 0x79 => 0x7fb3, 0x7a => 0x7ff7, 0x7b => 0x7ff8, + 0x7c => 0x8075, 0x7d => 0x81d1, 0x7e => 0x81d2, 0xa1 => 0x81d0, + 0xa2 => 0x825f, 0xa3 => 0x825e, 0xa4 => 0x85b4, 0xa5 => 0x85c6, + 0xa6 => 0x85c0, 0xa7 => 0x85c3, 0xa8 => 0x85c2, 0xa9 => 0x85b3, + 0xaa => 0x85b5, 0xab => 0x85bd, 0xac => 0x85c7, 0xad => 0x85c4, + 0xae => 0x85bf, 0xaf => 0x85cb, 0xb0 => 0x85ce, 0xb1 => 0x85c8, + 0xb2 => 0x85c5, 0xb3 => 0x85b1, 0xb4 => 0x85b6, 0xb5 => 0x85d2, + 0xb6 => 0x8624, 0xb7 => 0x85b8, 0xb8 => 0x85b7, 0xb9 => 0x85be, + 0xba => 0x8669, 0xbb => 0x87e7, 0xbc => 0x87e6, 0xbd => 0x87e2, + 0xbe => 0x87db, 0xbf => 0x87eb, 0xc0 => 0x87ea, 0xc1 => 0x87e5, + 0xc2 => 0x87df, 0xc3 => 0x87f3, 0xc4 => 0x87e4, 0xc5 => 0x87d4, + 0xc6 => 0x87dc, 0xc7 => 0x87d3, 0xc8 => 0x87ed, 0xc9 => 0x87d8, + 0xca => 0x87e3, 0xcb => 0x87a4, 0xcc => 0x87d7, 0xcd => 0x87d9, + 0xce => 0x8801, 0xcf => 0x87f4, 0xd0 => 0x87e8, 0xd1 => 0x87dd, + 0xd2 => 0x8953, 0xd3 => 0x894b, 0xd4 => 0x894f, 0xd5 => 0x894c, + 0xd6 => 0x8946, 0xd7 => 0x8950, 0xd8 => 0x8951, 0xd9 => 0x8949, + 0xda => 0x8b2a, 0xdb => 0x8b27, 0xdc => 0x8b23, 0xdd => 0x8b33, + 0xde => 0x8b30, 0xdf => 0x8b35, 0xe0 => 0x8b47, 0xe1 => 0x8b2f, + 0xe2 => 0x8b3c, 0xe3 => 0x8b3e, 0xe4 => 0x8b31, 0xe5 => 0x8b25, + 0xe6 => 0x8b37, 0xe7 => 0x8b26, 0xe8 => 0x8b36, 0xe9 => 0x8b2e, + 0xea => 0x8b24, 0xeb => 0x8b3b, 0xec => 0x8b3d, 0xed => 0x8b3a, + 0xee => 0x8c42, 0xef => 0x8c75, 0xf0 => 0x8c99, 0xf1 => 0x8c98, + 0xf2 => 0x8c97, 0xf3 => 0x8cfe, 0xf4 => 0x8d04, 0xf5 => 0x8d02, + 0xf6 => 0x8d00, 0xf7 => 0x8e5c, 0xf8 => 0x8e62, 0xf9 => 0x8e60, + 0xfa => 0x8e57, 0xfb => 0x8e56, 0xfc => 0x8e5e, 0xfd => 0x8e65, + 0xfe => 0x8e67, + }, + 0xf1 => { + 0x40 => 0x8e5b, 0x41 => 0x8e5a, 0x42 => 0x8e61, 0x43 => 0x8e5d, + 0x44 => 0x8e69, 0x45 => 0x8e54, 0x46 => 0x8f46, 0x47 => 0x8f47, + 0x48 => 0x8f48, 0x49 => 0x8f4b, 0x4a => 0x9128, 0x4b => 0x913a, + 0x4c => 0x913b, 0x4d => 0x913e, 0x4e => 0x91a8, 0x4f => 0x91a5, + 0x50 => 0x91a7, 0x51 => 0x91af, 0x52 => 0x91aa, 0x53 => 0x93b5, + 0x54 => 0x938c, 0x55 => 0x9392, 0x56 => 0x93b7, 0x57 => 0x939b, + 0x58 => 0x939d, 0x59 => 0x9389, 0x5a => 0x93a7, 0x5b => 0x938e, + 0x5c => 0x93aa, 0x5d => 0x939e, 0x5e => 0x93a6, 0x5f => 0x9395, + 0x60 => 0x9388, 0x61 => 0x9399, 0x62 => 0x939f, 0x63 => 0x938d, + 0x64 => 0x93b1, 0x65 => 0x9391, 0x66 => 0x93b2, 0x67 => 0x93a4, + 0x68 => 0x93a8, 0x69 => 0x93b4, 0x6a => 0x93a3, 0x6b => 0x93a5, + 0x6c => 0x95d2, 0x6d => 0x95d3, 0x6e => 0x95d1, 0x6f => 0x96b3, + 0x70 => 0x96d7, 0x71 => 0x96da, 0x72 => 0x5dc2, 0x73 => 0x96df, + 0x74 => 0x96d8, 0x75 => 0x96dd, 0x76 => 0x9723, 0x77 => 0x9722, + 0x78 => 0x9725, 0x79 => 0x97ac, 0x7a => 0x97ae, 0x7b => 0x97a8, + 0x7c => 0x97ab, 0x7d => 0x97a4, 0x7e => 0x97aa, 0xa1 => 0x97a2, + 0xa2 => 0x97a5, 0xa3 => 0x97d7, 0xa4 => 0x97d9, 0xa5 => 0x97d6, + 0xa6 => 0x97d8, 0xa7 => 0x97fa, 0xa8 => 0x9850, 0xa9 => 0x9851, + 0xaa => 0x9852, 0xab => 0x98b8, 0xac => 0x9941, 0xad => 0x993c, + 0xae => 0x993a, 0xaf => 0x9a0f, 0xb0 => 0x9a0b, 0xb1 => 0x9a09, + 0xb2 => 0x9a0d, 0xb3 => 0x9a04, 0xb4 => 0x9a11, 0xb5 => 0x9a0a, + 0xb6 => 0x9a05, 0xb7 => 0x9a07, 0xb8 => 0x9a06, 0xb9 => 0x9ac0, + 0xba => 0x9adc, 0xbb => 0x9b08, 0xbc => 0x9b04, 0xbd => 0x9b05, + 0xbe => 0x9b29, 0xbf => 0x9b35, 0xc0 => 0x9b4a, 0xc1 => 0x9b4c, + 0xc2 => 0x9b4b, 0xc3 => 0x9bc7, 0xc4 => 0x9bc6, 0xc5 => 0x9bc3, + 0xc6 => 0x9bbf, 0xc7 => 0x9bc1, 0xc8 => 0x9bb5, 0xc9 => 0x9bb8, + 0xca => 0x9bd3, 0xcb => 0x9bb6, 0xcc => 0x9bc4, 0xcd => 0x9bb9, + 0xce => 0x9bbd, 0xcf => 0x9d5c, 0xd0 => 0x9d53, 0xd1 => 0x9d4f, + 0xd2 => 0x9d4a, 0xd3 => 0x9d5b, 0xd4 => 0x9d4b, 0xd5 => 0x9d59, + 0xd6 => 0x9d56, 0xd7 => 0x9d4c, 0xd8 => 0x9d57, 0xd9 => 0x9d52, + 0xda => 0x9d54, 0xdb => 0x9d5f, 0xdc => 0x9d58, 0xdd => 0x9d5a, + 0xde => 0x9e8e, 0xdf => 0x9e8c, 0xe0 => 0x9edf, 0xe1 => 0x9f01, + 0xe2 => 0x9f00, 0xe3 => 0x9f16, 0xe4 => 0x9f25, 0xe5 => 0x9f2b, + 0xe6 => 0x9f2a, 0xe7 => 0x9f29, 0xe8 => 0x9f28, 0xe9 => 0x9f4c, + 0xea => 0x9f55, 0xeb => 0x5134, 0xec => 0x5135, 0xed => 0x5296, + 0xee => 0x52f7, 0xef => 0x53b4, 0xf0 => 0x56ab, 0xf1 => 0x56ad, + 0xf2 => 0x56a6, 0xf3 => 0x56a7, 0xf4 => 0x56aa, 0xf5 => 0x56ac, + 0xf6 => 0x58da, 0xf7 => 0x58dd, 0xf8 => 0x58db, 0xf9 => 0x5912, + 0xfa => 0x5b3d, 0xfb => 0x5b3e, 0xfc => 0x5b3f, 0xfd => 0x5dc3, + 0xfe => 0x5e70, + }, + 0xf2 => { + 0x40 => 0x5fbf, 0x41 => 0x61fb, 0x42 => 0x6507, 0x43 => 0x6510, + 0x44 => 0x650d, 0x45 => 0x6509, 0x46 => 0x650c, 0x47 => 0x650e, + 0x48 => 0x6584, 0x49 => 0x65de, 0x4a => 0x65dd, 0x4b => 0x66de, + 0x4c => 0x6ae7, 0x4d => 0x6ae0, 0x4e => 0x6acc, 0x4f => 0x6ad1, + 0x50 => 0x6ad9, 0x51 => 0x6acb, 0x52 => 0x6adf, 0x53 => 0x6adc, + 0x54 => 0x6ad0, 0x55 => 0x6aeb, 0x56 => 0x6acf, 0x57 => 0x6acd, + 0x58 => 0x6ade, 0x59 => 0x6b60, 0x5a => 0x6bb0, 0x5b => 0x6c0c, + 0x5c => 0x7019, 0x5d => 0x7027, 0x5e => 0x7020, 0x5f => 0x7016, + 0x60 => 0x702b, 0x61 => 0x7021, 0x62 => 0x7022, 0x63 => 0x7023, + 0x64 => 0x7029, 0x65 => 0x7017, 0x66 => 0x7024, 0x67 => 0x701c, + 0x68 => 0x702a, 0x69 => 0x720c, 0x6a => 0x720a, 0x6b => 0x7207, + 0x6c => 0x7202, 0x6d => 0x7205, 0x6e => 0x72a5, 0x6f => 0x72a6, + 0x70 => 0x72a4, 0x71 => 0x72a3, 0x72 => 0x72a1, 0x73 => 0x74cb, + 0x74 => 0x74c5, 0x75 => 0x74b7, 0x76 => 0x74c3, 0x77 => 0x7516, + 0x78 => 0x7660, 0x79 => 0x77c9, 0x7a => 0x77ca, 0x7b => 0x77c4, + 0x7c => 0x77f1, 0x7d => 0x791d, 0x7e => 0x791b, 0xa1 => 0x7921, + 0xa2 => 0x791c, 0xa3 => 0x7917, 0xa4 => 0x791e, 0xa5 => 0x79b0, + 0xa6 => 0x7a67, 0xa7 => 0x7a68, 0xa8 => 0x7c33, 0xa9 => 0x7c3c, + 0xaa => 0x7c39, 0xab => 0x7c2c, 0xac => 0x7c3b, 0xad => 0x7cec, + 0xae => 0x7cea, 0xaf => 0x7e76, 0xb0 => 0x7e75, 0xb1 => 0x7e78, + 0xb2 => 0x7e70, 0xb3 => 0x7e77, 0xb4 => 0x7e6f, 0xb5 => 0x7e7a, + 0xb6 => 0x7e72, 0xb7 => 0x7e74, 0xb8 => 0x7e68, 0xb9 => 0x7f4b, + 0xba => 0x7f4a, 0xbb => 0x7f83, 0xbc => 0x7f86, 0xbd => 0x7fb7, + 0xbe => 0x7ffd, 0xbf => 0x7ffe, 0xc0 => 0x8078, 0xc1 => 0x81d7, + 0xc2 => 0x81d5, 0xc3 => 0x8264, 0xc4 => 0x8261, 0xc5 => 0x8263, + 0xc6 => 0x85eb, 0xc7 => 0x85f1, 0xc8 => 0x85ed, 0xc9 => 0x85d9, + 0xca => 0x85e1, 0xcb => 0x85e8, 0xcc => 0x85da, 0xcd => 0x85d7, + 0xce => 0x85ec, 0xcf => 0x85f2, 0xd0 => 0x85f8, 0xd1 => 0x85d8, + 0xd2 => 0x85df, 0xd3 => 0x85e3, 0xd4 => 0x85dc, 0xd5 => 0x85d1, + 0xd6 => 0x85f0, 0xd7 => 0x85e6, 0xd8 => 0x85ef, 0xd9 => 0x85de, + 0xda => 0x85e2, 0xdb => 0x8800, 0xdc => 0x87fa, 0xdd => 0x8803, + 0xde => 0x87f6, 0xdf => 0x87f7, 0xe0 => 0x8809, 0xe1 => 0x880c, + 0xe2 => 0x880b, 0xe3 => 0x8806, 0xe4 => 0x87fc, 0xe5 => 0x8808, + 0xe6 => 0x87ff, 0xe7 => 0x880a, 0xe8 => 0x8802, 0xe9 => 0x8962, + 0xea => 0x895a, 0xeb => 0x895b, 0xec => 0x8957, 0xed => 0x8961, + 0xee => 0x895c, 0xef => 0x8958, 0xf0 => 0x895d, 0xf1 => 0x8959, + 0xf2 => 0x8988, 0xf3 => 0x89b7, 0xf4 => 0x89b6, 0xf5 => 0x89f6, + 0xf6 => 0x8b50, 0xf7 => 0x8b48, 0xf8 => 0x8b4a, 0xf9 => 0x8b40, + 0xfa => 0x8b53, 0xfb => 0x8b56, 0xfc => 0x8b54, 0xfd => 0x8b4b, + 0xfe => 0x8b55, + }, + 0xf3 => { + 0x40 => 0x8b51, 0x41 => 0x8b42, 0x42 => 0x8b52, 0x43 => 0x8b57, + 0x44 => 0x8c43, 0x45 => 0x8c77, 0x46 => 0x8c76, 0x47 => 0x8c9a, + 0x48 => 0x8d06, 0x49 => 0x8d07, 0x4a => 0x8d09, 0x4b => 0x8dac, + 0x4c => 0x8daa, 0x4d => 0x8dad, 0x4e => 0x8dab, 0x4f => 0x8e6d, + 0x50 => 0x8e78, 0x51 => 0x8e73, 0x52 => 0x8e6a, 0x53 => 0x8e6f, + 0x54 => 0x8e7b, 0x55 => 0x8ec2, 0x56 => 0x8f52, 0x57 => 0x8f51, + 0x58 => 0x8f4f, 0x59 => 0x8f50, 0x5a => 0x8f53, 0x5b => 0x8fb4, + 0x5c => 0x9140, 0x5d => 0x913f, 0x5e => 0x91b0, 0x5f => 0x91ad, + 0x60 => 0x93de, 0x61 => 0x93c7, 0x62 => 0x93cf, 0x63 => 0x93c2, + 0x64 => 0x93da, 0x65 => 0x93d0, 0x66 => 0x93f9, 0x67 => 0x93ec, + 0x68 => 0x93cc, 0x69 => 0x93d9, 0x6a => 0x93a9, 0x6b => 0x93e6, + 0x6c => 0x93ca, 0x6d => 0x93d4, 0x6e => 0x93ee, 0x6f => 0x93e3, + 0x70 => 0x93d5, 0x71 => 0x93c4, 0x72 => 0x93ce, 0x73 => 0x93c0, + 0x74 => 0x93d2, 0x75 => 0x93e7, 0x76 => 0x957d, 0x77 => 0x95da, + 0x78 => 0x95db, 0x79 => 0x96e1, 0x7a => 0x9729, 0x7b => 0x972b, + 0x7c => 0x972c, 0x7d => 0x9728, 0x7e => 0x9726, 0xa1 => 0x97b3, + 0xa2 => 0x97b7, 0xa3 => 0x97b6, 0xa4 => 0x97dd, 0xa5 => 0x97de, + 0xa6 => 0x97df, 0xa7 => 0x985c, 0xa8 => 0x9859, 0xa9 => 0x985d, + 0xaa => 0x9857, 0xab => 0x98bf, 0xac => 0x98bd, 0xad => 0x98bb, + 0xae => 0x98be, 0xaf => 0x9948, 0xb0 => 0x9947, 0xb1 => 0x9943, + 0xb2 => 0x99a6, 0xb3 => 0x99a7, 0xb4 => 0x9a1a, 0xb5 => 0x9a15, + 0xb6 => 0x9a25, 0xb7 => 0x9a1d, 0xb8 => 0x9a24, 0xb9 => 0x9a1b, + 0xba => 0x9a22, 0xbb => 0x9a20, 0xbc => 0x9a27, 0xbd => 0x9a23, + 0xbe => 0x9a1e, 0xbf => 0x9a1c, 0xc0 => 0x9a14, 0xc1 => 0x9ac2, + 0xc2 => 0x9b0b, 0xc3 => 0x9b0a, 0xc4 => 0x9b0e, 0xc5 => 0x9b0c, + 0xc6 => 0x9b37, 0xc7 => 0x9bea, 0xc8 => 0x9beb, 0xc9 => 0x9be0, + 0xca => 0x9bde, 0xcb => 0x9be4, 0xcc => 0x9be6, 0xcd => 0x9be2, + 0xce => 0x9bf0, 0xcf => 0x9bd4, 0xd0 => 0x9bd7, 0xd1 => 0x9bec, + 0xd2 => 0x9bdc, 0xd3 => 0x9bd9, 0xd4 => 0x9be5, 0xd5 => 0x9bd5, + 0xd6 => 0x9be1, 0xd7 => 0x9bda, 0xd8 => 0x9d77, 0xd9 => 0x9d81, + 0xda => 0x9d8a, 0xdb => 0x9d84, 0xdc => 0x9d88, 0xdd => 0x9d71, + 0xde => 0x9d80, 0xdf => 0x9d78, 0xe0 => 0x9d86, 0xe1 => 0x9d8b, + 0xe2 => 0x9d8c, 0xe3 => 0x9d7d, 0xe4 => 0x9d6b, 0xe5 => 0x9d74, + 0xe6 => 0x9d75, 0xe7 => 0x9d70, 0xe8 => 0x9d69, 0xe9 => 0x9d85, + 0xea => 0x9d73, 0xeb => 0x9d7b, 0xec => 0x9d82, 0xed => 0x9d6f, + 0xee => 0x9d79, 0xef => 0x9d7f, 0xf0 => 0x9d87, 0xf1 => 0x9d68, + 0xf2 => 0x9e94, 0xf3 => 0x9e91, 0xf4 => 0x9ec0, 0xf5 => 0x9efc, + 0xf6 => 0x9f2d, 0xf7 => 0x9f40, 0xf8 => 0x9f41, 0xf9 => 0x9f4d, + 0xfa => 0x9f56, 0xfb => 0x9f57, 0xfc => 0x9f58, 0xfd => 0x5337, + 0xfe => 0x56b2, + }, + 0xf4 => { + 0x40 => 0x56b5, 0x41 => 0x56b3, 0x42 => 0x58e3, 0x43 => 0x5b45, + 0x44 => 0x5dc6, 0x45 => 0x5dc7, 0x46 => 0x5eee, 0x47 => 0x5eef, + 0x48 => 0x5fc0, 0x49 => 0x5fc1, 0x4a => 0x61f9, 0x4b => 0x6517, + 0x4c => 0x6516, 0x4d => 0x6515, 0x4e => 0x6513, 0x4f => 0x65df, + 0x50 => 0x66e8, 0x51 => 0x66e3, 0x52 => 0x66e4, 0x53 => 0x6af3, + 0x54 => 0x6af0, 0x55 => 0x6aea, 0x56 => 0x6ae8, 0x57 => 0x6af9, + 0x58 => 0x6af1, 0x59 => 0x6aee, 0x5a => 0x6aef, 0x5b => 0x703c, + 0x5c => 0x7035, 0x5d => 0x702f, 0x5e => 0x7037, 0x5f => 0x7034, + 0x60 => 0x7031, 0x61 => 0x7042, 0x62 => 0x7038, 0x63 => 0x703f, + 0x64 => 0x703a, 0x65 => 0x7039, 0x66 => 0x7040, 0x67 => 0x703b, + 0x68 => 0x7033, 0x69 => 0x7041, 0x6a => 0x7213, 0x6b => 0x7214, + 0x6c => 0x72a8, 0x6d => 0x737d, 0x6e => 0x737c, 0x6f => 0x74ba, + 0x70 => 0x76ab, 0x71 => 0x76aa, 0x72 => 0x76be, 0x73 => 0x76ed, + 0x74 => 0x77cc, 0x75 => 0x77ce, 0x76 => 0x77cf, 0x77 => 0x77cd, + 0x78 => 0x77f2, 0x79 => 0x7925, 0x7a => 0x7923, 0x7b => 0x7927, + 0x7c => 0x7928, 0x7d => 0x7924, 0x7e => 0x7929, 0xa1 => 0x79b2, + 0xa2 => 0x7a6e, 0xa3 => 0x7a6c, 0xa4 => 0x7a6d, 0xa5 => 0x7af7, + 0xa6 => 0x7c49, 0xa7 => 0x7c48, 0xa8 => 0x7c4a, 0xa9 => 0x7c47, + 0xaa => 0x7c45, 0xab => 0x7cee, 0xac => 0x7e7b, 0xad => 0x7e7e, + 0xae => 0x7e81, 0xaf => 0x7e80, 0xb0 => 0x7fba, 0xb1 => 0x7fff, + 0xb2 => 0x8079, 0xb3 => 0x81db, 0xb4 => 0x81d9, 0xb5 => 0x820b, + 0xb6 => 0x8268, 0xb7 => 0x8269, 0xb8 => 0x8622, 0xb9 => 0x85ff, + 0xba => 0x8601, 0xbb => 0x85fe, 0xbc => 0x861b, 0xbd => 0x8600, + 0xbe => 0x85f6, 0xbf => 0x8604, 0xc0 => 0x8609, 0xc1 => 0x8605, + 0xc2 => 0x860c, 0xc3 => 0x85fd, 0xc4 => 0x8819, 0xc5 => 0x8810, + 0xc6 => 0x8811, 0xc7 => 0x8817, 0xc8 => 0x8813, 0xc9 => 0x8816, + 0xca => 0x8963, 0xcb => 0x8966, 0xcc => 0x89b9, 0xcd => 0x89f7, + 0xce => 0x8b60, 0xcf => 0x8b6a, 0xd0 => 0x8b5d, 0xd1 => 0x8b68, + 0xd2 => 0x8b63, 0xd3 => 0x8b65, 0xd4 => 0x8b67, 0xd5 => 0x8b6d, + 0xd6 => 0x8dae, 0xd7 => 0x8e86, 0xd8 => 0x8e88, 0xd9 => 0x8e84, + 0xda => 0x8f59, 0xdb => 0x8f56, 0xdc => 0x8f57, 0xdd => 0x8f55, + 0xde => 0x8f58, 0xdf => 0x8f5a, 0xe0 => 0x908d, 0xe1 => 0x9143, + 0xe2 => 0x9141, 0xe3 => 0x91b7, 0xe4 => 0x91b5, 0xe5 => 0x91b2, + 0xe6 => 0x91b3, 0xe7 => 0x940b, 0xe8 => 0x9413, 0xe9 => 0x93fb, + 0xea => 0x9420, 0xeb => 0x940f, 0xec => 0x9414, 0xed => 0x93fe, + 0xee => 0x9415, 0xef => 0x9410, 0xf0 => 0x9428, 0xf1 => 0x9419, + 0xf2 => 0x940d, 0xf3 => 0x93f5, 0xf4 => 0x9400, 0xf5 => 0x93f7, + 0xf6 => 0x9407, 0xf7 => 0x940e, 0xf8 => 0x9416, 0xf9 => 0x9412, + 0xfa => 0x93fa, 0xfb => 0x9409, 0xfc => 0x93f8, 0xfd => 0x940a, + 0xfe => 0x93ff, + }, + 0xf5 => { + 0x40 => 0x93fc, 0x41 => 0x940c, 0x42 => 0x93f6, 0x43 => 0x9411, + 0x44 => 0x9406, 0x45 => 0x95de, 0x46 => 0x95e0, 0x47 => 0x95df, + 0x48 => 0x972e, 0x49 => 0x972f, 0x4a => 0x97b9, 0x4b => 0x97bb, + 0x4c => 0x97fd, 0x4d => 0x97fe, 0x4e => 0x9860, 0x4f => 0x9862, + 0x50 => 0x9863, 0x51 => 0x985f, 0x52 => 0x98c1, 0x53 => 0x98c2, + 0x54 => 0x9950, 0x55 => 0x994e, 0x56 => 0x9959, 0x57 => 0x994c, + 0x58 => 0x994b, 0x59 => 0x9953, 0x5a => 0x9a32, 0x5b => 0x9a34, + 0x5c => 0x9a31, 0x5d => 0x9a2c, 0x5e => 0x9a2a, 0x5f => 0x9a36, + 0x60 => 0x9a29, 0x61 => 0x9a2e, 0x62 => 0x9a38, 0x63 => 0x9a2d, + 0x64 => 0x9ac7, 0x65 => 0x9aca, 0x66 => 0x9ac6, 0x67 => 0x9b10, + 0x68 => 0x9b12, 0x69 => 0x9b11, 0x6a => 0x9c0b, 0x6b => 0x9c08, + 0x6c => 0x9bf7, 0x6d => 0x9c05, 0x6e => 0x9c12, 0x6f => 0x9bf8, + 0x70 => 0x9c40, 0x71 => 0x9c07, 0x72 => 0x9c0e, 0x73 => 0x9c06, + 0x74 => 0x9c17, 0x75 => 0x9c14, 0x76 => 0x9c09, 0x77 => 0x9d9f, + 0x78 => 0x9d99, 0x79 => 0x9da4, 0x7a => 0x9d9d, 0x7b => 0x9d92, + 0x7c => 0x9d98, 0x7d => 0x9d90, 0x7e => 0x9d9b, 0xa1 => 0x9da0, + 0xa2 => 0x9d94, 0xa3 => 0x9d9c, 0xa4 => 0x9daa, 0xa5 => 0x9d97, + 0xa6 => 0x9da1, 0xa7 => 0x9d9a, 0xa8 => 0x9da2, 0xa9 => 0x9da8, + 0xaa => 0x9d9e, 0xab => 0x9da3, 0xac => 0x9dbf, 0xad => 0x9da9, + 0xae => 0x9d96, 0xaf => 0x9da6, 0xb0 => 0x9da7, 0xb1 => 0x9e99, + 0xb2 => 0x9e9b, 0xb3 => 0x9e9a, 0xb4 => 0x9ee5, 0xb5 => 0x9ee4, + 0xb6 => 0x9ee7, 0xb7 => 0x9ee6, 0xb8 => 0x9f30, 0xb9 => 0x9f2e, + 0xba => 0x9f5b, 0xbb => 0x9f60, 0xbc => 0x9f5e, 0xbd => 0x9f5d, + 0xbe => 0x9f59, 0xbf => 0x9f91, 0xc0 => 0x513a, 0xc1 => 0x5139, + 0xc2 => 0x5298, 0xc3 => 0x5297, 0xc4 => 0x56c3, 0xc5 => 0x56bd, + 0xc6 => 0x56be, 0xc7 => 0x5b48, 0xc8 => 0x5b47, 0xc9 => 0x5dcb, + 0xca => 0x5dcf, 0xcb => 0x5ef1, 0xcc => 0x61fd, 0xcd => 0x651b, + 0xce => 0x6b02, 0xcf => 0x6afc, 0xd0 => 0x6b03, 0xd1 => 0x6af8, + 0xd2 => 0x6b00, 0xd3 => 0x7043, 0xd4 => 0x7044, 0xd5 => 0x704a, + 0xd6 => 0x7048, 0xd7 => 0x7049, 0xd8 => 0x7045, 0xd9 => 0x7046, + 0xda => 0x721d, 0xdb => 0x721a, 0xdc => 0x7219, 0xdd => 0x737e, + 0xde => 0x7517, 0xdf => 0x766a, 0xe0 => 0x77d0, 0xe1 => 0x792d, + 0xe2 => 0x7931, 0xe3 => 0x792f, 0xe4 => 0x7c54, 0xe5 => 0x7c53, + 0xe6 => 0x7cf2, 0xe7 => 0x7e8a, 0xe8 => 0x7e87, 0xe9 => 0x7e88, + 0xea => 0x7e8b, 0xeb => 0x7e86, 0xec => 0x7e8d, 0xed => 0x7f4d, + 0xee => 0x7fbb, 0xef => 0x8030, 0xf0 => 0x81dd, 0xf1 => 0x8618, + 0xf2 => 0x862a, 0xf3 => 0x8626, 0xf4 => 0x861f, 0xf5 => 0x8623, + 0xf6 => 0x861c, 0xf7 => 0x8619, 0xf8 => 0x8627, 0xf9 => 0x862e, + 0xfa => 0x8621, 0xfb => 0x8620, 0xfc => 0x8629, 0xfd => 0x861e, + 0xfe => 0x8625, + }, + 0xf6 => { + 0x40 => 0x8829, 0x41 => 0x881d, 0x42 => 0x881b, 0x43 => 0x8820, + 0x44 => 0x8824, 0x45 => 0x881c, 0x46 => 0x882b, 0x47 => 0x884a, + 0x48 => 0x896d, 0x49 => 0x8969, 0x4a => 0x896e, 0x4b => 0x896b, + 0x4c => 0x89fa, 0x4d => 0x8b79, 0x4e => 0x8b78, 0x4f => 0x8b45, + 0x50 => 0x8b7a, 0x51 => 0x8b7b, 0x52 => 0x8d10, 0x53 => 0x8d14, + 0x54 => 0x8daf, 0x55 => 0x8e8e, 0x56 => 0x8e8c, 0x57 => 0x8f5e, + 0x58 => 0x8f5b, 0x59 => 0x8f5d, 0x5a => 0x9146, 0x5b => 0x9144, + 0x5c => 0x9145, 0x5d => 0x91b9, 0x5e => 0x943f, 0x5f => 0x943b, + 0x60 => 0x9436, 0x61 => 0x9429, 0x62 => 0x943d, 0x63 => 0x943c, + 0x64 => 0x9430, 0x65 => 0x9439, 0x66 => 0x942a, 0x67 => 0x9437, + 0x68 => 0x942c, 0x69 => 0x9440, 0x6a => 0x9431, 0x6b => 0x95e5, + 0x6c => 0x95e4, 0x6d => 0x95e3, 0x6e => 0x9735, 0x6f => 0x973a, + 0x70 => 0x97bf, 0x71 => 0x97e1, 0x72 => 0x9864, 0x73 => 0x98c9, + 0x74 => 0x98c6, 0x75 => 0x98c0, 0x76 => 0x9958, 0x77 => 0x9956, + 0x78 => 0x9a39, 0x79 => 0x9a3d, 0x7a => 0x9a46, 0x7b => 0x9a44, + 0x7c => 0x9a42, 0x7d => 0x9a41, 0x7e => 0x9a3a, 0xa1 => 0x9a3f, + 0xa2 => 0x9acd, 0xa3 => 0x9b15, 0xa4 => 0x9b17, 0xa5 => 0x9b18, + 0xa6 => 0x9b16, 0xa7 => 0x9b3a, 0xa8 => 0x9b52, 0xa9 => 0x9c2b, + 0xaa => 0x9c1d, 0xab => 0x9c1c, 0xac => 0x9c2c, 0xad => 0x9c23, + 0xae => 0x9c28, 0xaf => 0x9c29, 0xb0 => 0x9c24, 0xb1 => 0x9c21, + 0xb2 => 0x9db7, 0xb3 => 0x9db6, 0xb4 => 0x9dbc, 0xb5 => 0x9dc1, + 0xb6 => 0x9dc7, 0xb7 => 0x9dca, 0xb8 => 0x9dcf, 0xb9 => 0x9dbe, + 0xba => 0x9dc5, 0xbb => 0x9dc3, 0xbc => 0x9dbb, 0xbd => 0x9db5, + 0xbe => 0x9dce, 0xbf => 0x9db9, 0xc0 => 0x9dba, 0xc1 => 0x9dac, + 0xc2 => 0x9dc8, 0xc3 => 0x9db1, 0xc4 => 0x9dad, 0xc5 => 0x9dcc, + 0xc6 => 0x9db3, 0xc7 => 0x9dcd, 0xc8 => 0x9db2, 0xc9 => 0x9e7a, + 0xca => 0x9e9c, 0xcb => 0x9eeb, 0xcc => 0x9eee, 0xcd => 0x9eed, + 0xce => 0x9f1b, 0xcf => 0x9f18, 0xd0 => 0x9f1a, 0xd1 => 0x9f31, + 0xd2 => 0x9f4e, 0xd3 => 0x9f65, 0xd4 => 0x9f64, 0xd5 => 0x9f92, + 0xd6 => 0x4eb9, 0xd7 => 0x56c6, 0xd8 => 0x56c5, 0xd9 => 0x56cb, + 0xda => 0x5971, 0xdb => 0x5b4b, 0xdc => 0x5b4c, 0xdd => 0x5dd5, + 0xde => 0x5dd1, 0xdf => 0x5ef2, 0xe0 => 0x6521, 0xe1 => 0x6520, + 0xe2 => 0x6526, 0xe3 => 0x6522, 0xe4 => 0x6b0b, 0xe5 => 0x6b08, + 0xe6 => 0x6b09, 0xe7 => 0x6c0d, 0xe8 => 0x7055, 0xe9 => 0x7056, + 0xea => 0x7057, 0xeb => 0x7052, 0xec => 0x721e, 0xed => 0x721f, + 0xee => 0x72a9, 0xef => 0x737f, 0xf0 => 0x74d8, 0xf1 => 0x74d5, + 0xf2 => 0x74d9, 0xf3 => 0x74d7, 0xf4 => 0x766d, 0xf5 => 0x76ad, + 0xf6 => 0x7935, 0xf7 => 0x79b4, 0xf8 => 0x7a70, 0xf9 => 0x7a71, + 0xfa => 0x7c57, 0xfb => 0x7c5c, 0xfc => 0x7c59, 0xfd => 0x7c5b, + 0xfe => 0x7c5a, + }, + 0xf7 => { + 0x40 => 0x7cf4, 0x41 => 0x7cf1, 0x42 => 0x7e91, 0x43 => 0x7f4f, + 0x44 => 0x7f87, 0x45 => 0x81de, 0x46 => 0x826b, 0x47 => 0x8634, + 0x48 => 0x8635, 0x49 => 0x8633, 0x4a => 0x862c, 0x4b => 0x8632, + 0x4c => 0x8636, 0x4d => 0x882c, 0x4e => 0x8828, 0x4f => 0x8826, + 0x50 => 0x882a, 0x51 => 0x8825, 0x52 => 0x8971, 0x53 => 0x89bf, + 0x54 => 0x89be, 0x55 => 0x89fb, 0x56 => 0x8b7e, 0x57 => 0x8b84, + 0x58 => 0x8b82, 0x59 => 0x8b86, 0x5a => 0x8b85, 0x5b => 0x8b7f, + 0x5c => 0x8d15, 0x5d => 0x8e95, 0x5e => 0x8e94, 0x5f => 0x8e9a, + 0x60 => 0x8e92, 0x61 => 0x8e90, 0x62 => 0x8e96, 0x63 => 0x8e97, + 0x64 => 0x8f60, 0x65 => 0x8f62, 0x66 => 0x9147, 0x67 => 0x944c, + 0x68 => 0x9450, 0x69 => 0x944a, 0x6a => 0x944b, 0x6b => 0x944f, + 0x6c => 0x9447, 0x6d => 0x9445, 0x6e => 0x9448, 0x6f => 0x9449, + 0x70 => 0x9446, 0x71 => 0x973f, 0x72 => 0x97e3, 0x73 => 0x986a, + 0x74 => 0x9869, 0x75 => 0x98cb, 0x76 => 0x9954, 0x77 => 0x995b, + 0x78 => 0x9a4e, 0x79 => 0x9a53, 0x7a => 0x9a54, 0x7b => 0x9a4c, + 0x7c => 0x9a4f, 0x7d => 0x9a48, 0x7e => 0x9a4a, 0xa1 => 0x9a49, + 0xa2 => 0x9a52, 0xa3 => 0x9a50, 0xa4 => 0x9ad0, 0xa5 => 0x9b19, + 0xa6 => 0x9b2b, 0xa7 => 0x9b3b, 0xa8 => 0x9b56, 0xa9 => 0x9b55, + 0xaa => 0x9c46, 0xab => 0x9c48, 0xac => 0x9c3f, 0xad => 0x9c44, + 0xae => 0x9c39, 0xaf => 0x9c33, 0xb0 => 0x9c41, 0xb1 => 0x9c3c, + 0xb2 => 0x9c37, 0xb3 => 0x9c34, 0xb4 => 0x9c32, 0xb5 => 0x9c3d, + 0xb6 => 0x9c36, 0xb7 => 0x9ddb, 0xb8 => 0x9dd2, 0xb9 => 0x9dde, + 0xba => 0x9dda, 0xbb => 0x9dcb, 0xbc => 0x9dd0, 0xbd => 0x9ddc, + 0xbe => 0x9dd1, 0xbf => 0x9ddf, 0xc0 => 0x9de9, 0xc1 => 0x9dd9, + 0xc2 => 0x9dd8, 0xc3 => 0x9dd6, 0xc4 => 0x9df5, 0xc5 => 0x9dd5, + 0xc6 => 0x9ddd, 0xc7 => 0x9eb6, 0xc8 => 0x9ef0, 0xc9 => 0x9f35, + 0xca => 0x9f33, 0xcb => 0x9f32, 0xcc => 0x9f42, 0xcd => 0x9f6b, + 0xce => 0x9f95, 0xcf => 0x9fa2, 0xd0 => 0x513d, 0xd1 => 0x5299, + 0xd2 => 0x58e8, 0xd3 => 0x58e7, 0xd4 => 0x5972, 0xd5 => 0x5b4d, + 0xd6 => 0x5dd8, 0xd7 => 0x882f, 0xd8 => 0x5f4f, 0xd9 => 0x6201, + 0xda => 0x6203, 0xdb => 0x6204, 0xdc => 0x6529, 0xdd => 0x6525, + 0xde => 0x6596, 0xdf => 0x66eb, 0xe0 => 0x6b11, 0xe1 => 0x6b12, + 0xe2 => 0x6b0f, 0xe3 => 0x6bca, 0xe4 => 0x705b, 0xe5 => 0x705a, + 0xe6 => 0x7222, 0xe7 => 0x7382, 0xe8 => 0x7381, 0xe9 => 0x7383, + 0xea => 0x7670, 0xeb => 0x77d4, 0xec => 0x7c67, 0xed => 0x7c66, + 0xee => 0x7e95, 0xef => 0x826c, 0xf0 => 0x863a, 0xf1 => 0x8640, + 0xf2 => 0x8639, 0xf3 => 0x863c, 0xf4 => 0x8631, 0xf5 => 0x863b, + 0xf6 => 0x863e, 0xf7 => 0x8830, 0xf8 => 0x8832, 0xf9 => 0x882e, + 0xfa => 0x8833, 0xfb => 0x8976, 0xfc => 0x8974, 0xfd => 0x8973, + 0xfe => 0x89fe, + }, + 0xf8 => { + 0x40 => 0x8b8c, 0x41 => 0x8b8e, 0x42 => 0x8b8b, 0x43 => 0x8b88, + 0x44 => 0x8c45, 0x45 => 0x8d19, 0x46 => 0x8e98, 0x47 => 0x8f64, + 0x48 => 0x8f63, 0x49 => 0x91bc, 0x4a => 0x9462, 0x4b => 0x9455, + 0x4c => 0x945d, 0x4d => 0x9457, 0x4e => 0x945e, 0x4f => 0x97c4, + 0x50 => 0x97c5, 0x51 => 0x9800, 0x52 => 0x9a56, 0x53 => 0x9a59, + 0x54 => 0x9b1e, 0x55 => 0x9b1f, 0x56 => 0x9b20, 0x57 => 0x9c52, + 0x58 => 0x9c58, 0x59 => 0x9c50, 0x5a => 0x9c4a, 0x5b => 0x9c4d, + 0x5c => 0x9c4b, 0x5d => 0x9c55, 0x5e => 0x9c59, 0x5f => 0x9c4c, + 0x60 => 0x9c4e, 0x61 => 0x9dfb, 0x62 => 0x9df7, 0x63 => 0x9def, + 0x64 => 0x9de3, 0x65 => 0x9deb, 0x66 => 0x9df8, 0x67 => 0x9de4, + 0x68 => 0x9df6, 0x69 => 0x9de1, 0x6a => 0x9dee, 0x6b => 0x9de6, + 0x6c => 0x9df2, 0x6d => 0x9df0, 0x6e => 0x9de2, 0x6f => 0x9dec, + 0x70 => 0x9df4, 0x71 => 0x9df3, 0x72 => 0x9de8, 0x73 => 0x9ded, + 0x74 => 0x9ec2, 0x75 => 0x9ed0, 0x76 => 0x9ef2, 0x77 => 0x9ef3, + 0x78 => 0x9f06, 0x79 => 0x9f1c, 0x7a => 0x9f38, 0x7b => 0x9f37, + 0x7c => 0x9f36, 0x7d => 0x9f43, 0x7e => 0x9f4f, 0xa1 => 0x9f71, + 0xa2 => 0x9f70, 0xa3 => 0x9f6e, 0xa4 => 0x9f6f, 0xa5 => 0x56d3, + 0xa6 => 0x56cd, 0xa7 => 0x5b4e, 0xa8 => 0x5c6d, 0xa9 => 0x652d, + 0xaa => 0x66ed, 0xab => 0x66ee, 0xac => 0x6b13, 0xad => 0x705f, + 0xae => 0x7061, 0xaf => 0x705d, 0xb0 => 0x7060, 0xb1 => 0x7223, + 0xb2 => 0x74db, 0xb3 => 0x74e5, 0xb4 => 0x77d5, 0xb5 => 0x7938, + 0xb6 => 0x79b7, 0xb7 => 0x79b6, 0xb8 => 0x7c6a, 0xb9 => 0x7e97, + 0xba => 0x7f89, 0xbb => 0x826d, 0xbc => 0x8643, 0xbd => 0x8838, + 0xbe => 0x8837, 0xbf => 0x8835, 0xc0 => 0x884b, 0xc1 => 0x8b94, + 0xc2 => 0x8b95, 0xc3 => 0x8e9e, 0xc4 => 0x8e9f, 0xc5 => 0x8ea0, + 0xc6 => 0x8e9d, 0xc7 => 0x91be, 0xc8 => 0x91bd, 0xc9 => 0x91c2, + 0xca => 0x946b, 0xcb => 0x9468, 0xcc => 0x9469, 0xcd => 0x96e5, + 0xce => 0x9746, 0xcf => 0x9743, 0xd0 => 0x9747, 0xd1 => 0x97c7, + 0xd2 => 0x97e5, 0xd3 => 0x9a5e, 0xd4 => 0x9ad5, 0xd5 => 0x9b59, + 0xd6 => 0x9c63, 0xd7 => 0x9c67, 0xd8 => 0x9c66, 0xd9 => 0x9c62, + 0xda => 0x9c5e, 0xdb => 0x9c60, 0xdc => 0x9e02, 0xdd => 0x9dfe, + 0xde => 0x9e07, 0xdf => 0x9e03, 0xe0 => 0x9e06, 0xe1 => 0x9e05, + 0xe2 => 0x9e00, 0xe3 => 0x9e01, 0xe4 => 0x9e09, 0xe5 => 0x9dff, + 0xe6 => 0x9dfd, 0xe7 => 0x9e04, 0xe8 => 0x9ea0, 0xe9 => 0x9f1e, + 0xea => 0x9f46, 0xeb => 0x9f74, 0xec => 0x9f75, 0xed => 0x9f76, + 0xee => 0x56d4, 0xef => 0x652e, 0xf0 => 0x65b8, 0xf1 => 0x6b18, + 0xf2 => 0x6b19, 0xf3 => 0x6b17, 0xf4 => 0x6b1a, 0xf5 => 0x7062, + 0xf6 => 0x7226, 0xf7 => 0x72aa, 0xf8 => 0x77d8, 0xf9 => 0x77d9, + 0xfa => 0x7939, 0xfb => 0x7c69, 0xfc => 0x7c6b, 0xfd => 0x7cf6, + 0xfe => 0x7e9a, + }, + 0xf9 => { + 0x40 => 0x7e98, 0x41 => 0x7e9b, 0x42 => 0x7e99, 0x43 => 0x81e0, + 0x44 => 0x81e1, 0x45 => 0x8646, 0x46 => 0x8647, 0x47 => 0x8648, + 0x48 => 0x8979, 0x49 => 0x897a, 0x4a => 0x897c, 0x4b => 0x897b, + 0x4c => 0x89ff, 0x4d => 0x8b98, 0x4e => 0x8b99, 0x4f => 0x8ea5, + 0x50 => 0x8ea4, 0x51 => 0x8ea3, 0x52 => 0x946e, 0x53 => 0x946d, + 0x54 => 0x946f, 0x55 => 0x9471, 0x56 => 0x9473, 0x57 => 0x9749, + 0x58 => 0x9872, 0x59 => 0x995f, 0x5a => 0x9c68, 0x5b => 0x9c6e, + 0x5c => 0x9c6d, 0x5d => 0x9e0b, 0x5e => 0x9e0d, 0x5f => 0x9e10, + 0x60 => 0x9e0f, 0x61 => 0x9e12, 0x62 => 0x9e11, 0x63 => 0x9ea1, + 0x64 => 0x9ef5, 0x65 => 0x9f09, 0x66 => 0x9f47, 0x67 => 0x9f78, + 0x68 => 0x9f7b, 0x69 => 0x9f7a, 0x6a => 0x9f79, 0x6b => 0x571e, + 0x6c => 0x7066, 0x6d => 0x7c6f, 0x6e => 0x883c, 0x6f => 0x8db2, + 0x70 => 0x8ea6, 0x71 => 0x91c3, 0x72 => 0x9474, 0x73 => 0x9478, + 0x74 => 0x9476, 0x75 => 0x9475, 0x76 => 0x9a60, 0x77 => 0x9c74, + 0x78 => 0x9c73, 0x79 => 0x9c71, 0x7a => 0x9c75, 0x7b => 0x9e14, + 0x7c => 0x9e13, 0x7d => 0x9ef6, 0x7e => 0x9f0a, 0xa1 => 0x9fa4, + 0xa2 => 0x7068, 0xa3 => 0x7065, 0xa4 => 0x7cf7, 0xa5 => 0x866a, + 0xa6 => 0x883e, 0xa7 => 0x883d, 0xa8 => 0x883f, 0xa9 => 0x8b9e, + 0xaa => 0x8c9c, 0xab => 0x8ea9, 0xac => 0x8ec9, 0xad => 0x974b, + 0xae => 0x9873, 0xaf => 0x9874, 0xb0 => 0x98cc, 0xb1 => 0x9961, + 0xb2 => 0x99ab, 0xb3 => 0x9a64, 0xb4 => 0x9a66, 0xb5 => 0x9a67, + 0xb6 => 0x9b24, 0xb7 => 0x9e15, 0xb8 => 0x9e17, 0xb9 => 0x9f48, + 0xba => 0x6207, 0xbb => 0x6b1e, 0xbc => 0x7227, 0xbd => 0x864c, + 0xbe => 0x8ea8, 0xbf => 0x9482, 0xc0 => 0x9480, 0xc1 => 0x9481, + 0xc2 => 0x9a69, 0xc3 => 0x9a68, 0xc4 => 0x9b2e, 0xc5 => 0x9e19, + 0xc6 => 0x7229, 0xc7 => 0x864b, 0xc8 => 0x8b9f, 0xc9 => 0x9483, + 0xca => 0x9c79, 0xcb => 0x9eb7, 0xcc => 0x7675, 0xcd => 0x9a6b, + 0xce => 0x9c7a, 0xcf => 0x9e1d, 0xd0 => 0x7069, 0xd1 => 0x706a, + 0xd2 => 0x9ea4, 0xd3 => 0x9f7e, 0xd4 => 0x9f49, 0xd5 => 0x9f98, + }, +); + +1; # end diff --git a/lib/Image/ExifTool/Charset/MacCroatian.pm b/lib/Image/ExifTool/Charset/MacCroatian.pm new file mode 100644 index 0000000..f99d066 --- /dev/null +++ b/lib/Image/ExifTool/Charset/MacCroatian.pm @@ -0,0 +1,43 @@ +#------------------------------------------------------------------------------ +# File: MacCroatian.pm +# +# Description: Mac Croatian to Unicode +# +# Revisions: 2010/01/20 - P. Harvey created +# +# References: 1) http://unicode.org/Public/MAPPINGS/VENDORS/APPLE/CROATIAN.TXT +# +# Notes: The table omits 1-byte characters with the same values as Unicode +#------------------------------------------------------------------------------ +use strict; + +%Image::ExifTool::Charset::MacCroatian = ( + 0x80 => 0xc4, 0x81 => 0xc5, 0x82 => 0xc7, 0x83 => 0xc9, 0x84 => 0xd1, + 0x85 => 0xd6, 0x86 => 0xdc, 0x87 => 0xe1, 0x88 => 0xe0, 0x89 => 0xe2, + 0x8a => 0xe4, 0x8b => 0xe3, 0x8c => 0xe5, 0x8d => 0xe7, 0x8e => 0xe9, + 0x8f => 0xe8, 0x90 => 0xea, 0x91 => 0xeb, 0x92 => 0xed, 0x93 => 0xec, + 0x94 => 0xee, 0x95 => 0xef, 0x96 => 0xf1, 0x97 => 0xf3, 0x98 => 0xf2, + 0x99 => 0xf4, 0x9a => 0xf6, 0x9b => 0xf5, 0x9c => 0xfa, 0x9d => 0xf9, + 0x9e => 0xfb, 0x9f => 0xfc, 0xa0 => 0x2020, 0xa1 => 0xb0, 0xa4 => 0xa7, + 0xa5 => 0x2022, 0xa6 => 0xb6, 0xa7 => 0xdf, 0xa8 => 0xae, 0xa9 => 0x0160, + 0xaa => 0x2122, 0xab => 0xb4, 0xac => 0xa8, 0xad => 0x2260, 0xae => 0x017d, + 0xaf => 0xd8, 0xb0 => 0x221e, 0xb2 => 0x2264, 0xb3 => 0x2265, 0xb4 => 0x2206, + 0xb6 => 0x2202, 0xb7 => 0x2211, 0xb8 => 0x220f, 0xb9 => 0x0161, + 0xba => 0x222b, 0xbb => 0xaa, 0xbc => 0xba, 0xbd => 0x03a9, 0xbe => 0x017e, + 0xbf => 0xf8, 0xc0 => 0xbf, 0xc1 => 0xa1, 0xc2 => 0xac, 0xc3 => 0x221a, + 0xc4 => 0x0192, 0xc5 => 0x2248, 0xc6 => 0x0106, 0xc7 => 0xab, 0xc8 => 0x010c, + 0xc9 => 0x2026, 0xca => 0xa0, 0xcb => 0xc0, 0xcc => 0xc3, 0xcd => 0xd5, + 0xce => 0x0152, 0xcf => 0x0153, 0xd0 => 0x0110, 0xd1 => 0x2014, + 0xd2 => 0x201c, 0xd3 => 0x201d, 0xd4 => 0x2018, 0xd5 => 0x2019, 0xd6 => 0xf7, + 0xd7 => 0x25ca, 0xd8 => 0xf8ff, 0xd9 => 0xa9, 0xda => 0x2044, 0xdb => 0x20ac, + 0xdc => 0x2039, 0xdd => 0x203a, 0xde => 0xc6, 0xdf => 0xbb, 0xe0 => 0x2013, + 0xe1 => 0xb7, 0xe2 => 0x201a, 0xe3 => 0x201e, 0xe4 => 0x2030, 0xe5 => 0xc2, + 0xe6 => 0x0107, 0xe7 => 0xc1, 0xe8 => 0x010d, 0xe9 => 0xc8, 0xea => 0xcd, + 0xeb => 0xce, 0xec => 0xcf, 0xed => 0xcc, 0xee => 0xd3, 0xef => 0xd4, + 0xf0 => 0x0111, 0xf1 => 0xd2, 0xf2 => 0xda, 0xf3 => 0xdb, 0xf4 => 0xd9, + 0xf5 => 0x0131, 0xf6 => 0x02c6, 0xf7 => 0x02dc, 0xf8 => 0xaf, 0xf9 => 0x03c0, + 0xfa => 0xcb, 0xfb => 0x02da, 0xfc => 0xb8, 0xfd => 0xca, 0xfe => 0xe6, + 0xff => 0x02c7, +); + +1; # end diff --git a/lib/Image/ExifTool/Charset/MacCyrillic.pm b/lib/Image/ExifTool/Charset/MacCyrillic.pm new file mode 100644 index 0000000..7d5ea75 --- /dev/null +++ b/lib/Image/ExifTool/Charset/MacCyrillic.pm @@ -0,0 +1,47 @@ +#------------------------------------------------------------------------------ +# File: MacCyrillic.pm +# +# Description: Mac Cyrillic to Unicode +# +# Revisions: 2010/01/20 - P. Harvey created +# +# References: 1) http://unicode.org/Public/MAPPINGS/VENDORS/APPLE/CYRILLIC.TXT +# +# Notes: The table omits 1-byte characters with the same values as Unicode +#------------------------------------------------------------------------------ +use strict; + +%Image::ExifTool::Charset::MacCyrillic = ( + 0x80 => 0x0410, 0x81 => 0x0411, 0x82 => 0x0412, 0x83 => 0x0413, + 0x84 => 0x0414, 0x85 => 0x0415, 0x86 => 0x0416, 0x87 => 0x0417, + 0x88 => 0x0418, 0x89 => 0x0419, 0x8a => 0x041a, 0x8b => 0x041b, + 0x8c => 0x041c, 0x8d => 0x041d, 0x8e => 0x041e, 0x8f => 0x041f, + 0x90 => 0x0420, 0x91 => 0x0421, 0x92 => 0x0422, 0x93 => 0x0423, + 0x94 => 0x0424, 0x95 => 0x0425, 0x96 => 0x0426, 0x97 => 0x0427, + 0x98 => 0x0428, 0x99 => 0x0429, 0x9a => 0x042a, 0x9b => 0x042b, + 0x9c => 0x042c, 0x9d => 0x042d, 0x9e => 0x042e, 0x9f => 0x042f, + 0xa0 => 0x2020, 0xa1 => 0xb0, 0xa2 => 0x0490, 0xa4 => 0xa7, 0xa5 => 0x2022, + 0xa6 => 0xb6, 0xa7 => 0x0406, 0xa8 => 0xae, 0xaa => 0x2122, 0xab => 0x0402, + 0xac => 0x0452, 0xad => 0x2260, 0xae => 0x0403, 0xaf => 0x0453, + 0xb0 => 0x221e, 0xb2 => 0x2264, 0xb3 => 0x2265, 0xb4 => 0x0456, + 0xb6 => 0x0491, 0xb7 => 0x0408, 0xb8 => 0x0404, 0xb9 => 0x0454, + 0xba => 0x0407, 0xbb => 0x0457, 0xbc => 0x0409, 0xbd => 0x0459, + 0xbe => 0x040a, 0xbf => 0x045a, 0xc0 => 0x0458, 0xc1 => 0x0405, 0xc2 => 0xac, + 0xc3 => 0x221a, 0xc4 => 0x0192, 0xc5 => 0x2248, 0xc6 => 0x2206, 0xc7 => 0xab, + 0xc8 => 0xbb, 0xc9 => 0x2026, 0xca => 0xa0, 0xcb => 0x040b, 0xcc => 0x045b, + 0xcd => 0x040c, 0xce => 0x045c, 0xcf => 0x0455, 0xd0 => 0x2013, + 0xd1 => 0x2014, 0xd2 => 0x201c, 0xd3 => 0x201d, 0xd4 => 0x2018, + 0xd5 => 0x2019, 0xd6 => 0xf7, 0xd7 => 0x201e, 0xd8 => 0x040e, 0xd9 => 0x045e, + 0xda => 0x040f, 0xdb => 0x045f, 0xdc => 0x2116, 0xdd => 0x0401, + 0xde => 0x0451, 0xdf => 0x044f, 0xe0 => 0x0430, 0xe1 => 0x0431, + 0xe2 => 0x0432, 0xe3 => 0x0433, 0xe4 => 0x0434, 0xe5 => 0x0435, + 0xe6 => 0x0436, 0xe7 => 0x0437, 0xe8 => 0x0438, 0xe9 => 0x0439, + 0xea => 0x043a, 0xeb => 0x043b, 0xec => 0x043c, 0xed => 0x043d, + 0xee => 0x043e, 0xef => 0x043f, 0xf0 => 0x0440, 0xf1 => 0x0441, + 0xf2 => 0x0442, 0xf3 => 0x0443, 0xf4 => 0x0444, 0xf5 => 0x0445, + 0xf6 => 0x0446, 0xf7 => 0x0447, 0xf8 => 0x0448, 0xf9 => 0x0449, + 0xfa => 0x044a, 0xfb => 0x044b, 0xfc => 0x044c, 0xfd => 0x044d, + 0xfe => 0x044e, 0xff => 0x20ac, +); + +1; # end diff --git a/lib/Image/ExifTool/Charset/MacGreek.pm b/lib/Image/ExifTool/Charset/MacGreek.pm new file mode 100644 index 0000000..43b2595 --- /dev/null +++ b/lib/Image/ExifTool/Charset/MacGreek.pm @@ -0,0 +1,45 @@ +#------------------------------------------------------------------------------ +# File: MacGreek.pm +# +# Description: Mac Greek to Unicode +# +# Revisions: 2010/01/20 - P. Harvey created +# +# References: 1) http://unicode.org/Public/MAPPINGS/VENDORS/APPLE/GREEK.TXT +# +# Notes: The table omits 1-byte characters with the same values as Unicode +#------------------------------------------------------------------------------ +use strict; + +%Image::ExifTool::Charset::MacGreek = ( + 0x80 => 0xc4, 0x81 => 0xb9, 0x82 => 0xb2, 0x83 => 0xc9, 0x84 => 0xb3, + 0x85 => 0xd6, 0x86 => 0xdc, 0x87 => 0x0385, 0x88 => 0xe0, 0x89 => 0xe2, + 0x8a => 0xe4, 0x8b => 0x0384, 0x8c => 0xa8, 0x8d => 0xe7, 0x8e => 0xe9, + 0x8f => 0xe8, 0x90 => 0xea, 0x91 => 0xeb, 0x92 => 0xa3, 0x93 => 0x2122, + 0x94 => 0xee, 0x95 => 0xef, 0x96 => 0x2022, 0x97 => 0xbd, 0x98 => 0x2030, + 0x99 => 0xf4, 0x9a => 0xf6, 0x9b => 0xa6, 0x9c => 0x20ac, 0x9d => 0xf9, + 0x9e => 0xfb, 0x9f => 0xfc, 0xa0 => 0x2020, 0xa1 => 0x0393, 0xa2 => 0x0394, + 0xa3 => 0x0398, 0xa4 => 0x039b, 0xa5 => 0x039e, 0xa6 => 0x03a0, 0xa7 => 0xdf, + 0xa8 => 0xae, 0xaa => 0x03a3, 0xab => 0x03aa, 0xac => 0xa7, 0xad => 0x2260, + 0xae => 0xb0, 0xaf => 0xb7, 0xb0 => 0x0391, 0xb2 => 0x2264, 0xb3 => 0x2265, + 0xb4 => 0xa5, 0xb5 => 0x0392, 0xb6 => 0x0395, 0xb7 => 0x0396, 0xb8 => 0x0397, + 0xb9 => 0x0399, 0xba => 0x039a, 0xbb => 0x039c, 0xbc => 0x03a6, + 0xbd => 0x03ab, 0xbe => 0x03a8, 0xbf => 0x03a9, 0xc0 => 0x03ac, + 0xc1 => 0x039d, 0xc2 => 0xac, 0xc3 => 0x039f, 0xc4 => 0x03a1, 0xc5 => 0x2248, + 0xc6 => 0x03a4, 0xc7 => 0xab, 0xc8 => 0xbb, 0xc9 => 0x2026, 0xca => 0xa0, + 0xcb => 0x03a5, 0xcc => 0x03a7, 0xcd => 0x0386, 0xce => 0x0388, + 0xcf => 0x0153, 0xd0 => 0x2013, 0xd1 => 0x2015, 0xd2 => 0x201c, + 0xd3 => 0x201d, 0xd4 => 0x2018, 0xd5 => 0x2019, 0xd6 => 0xf7, 0xd7 => 0x0389, + 0xd8 => 0x038a, 0xd9 => 0x038c, 0xda => 0x038e, 0xdb => 0x03ad, + 0xdc => 0x03ae, 0xdd => 0x03af, 0xde => 0x03cc, 0xdf => 0x038f, + 0xe0 => 0x03cd, 0xe1 => 0x03b1, 0xe2 => 0x03b2, 0xe3 => 0x03c8, + 0xe4 => 0x03b4, 0xe5 => 0x03b5, 0xe6 => 0x03c6, 0xe7 => 0x03b3, + 0xe8 => 0x03b7, 0xe9 => 0x03b9, 0xea => 0x03be, 0xeb => 0x03ba, + 0xec => 0x03bb, 0xed => 0x03bc, 0xee => 0x03bd, 0xef => 0x03bf, + 0xf0 => 0x03c0, 0xf1 => 0x03ce, 0xf2 => 0x03c1, 0xf3 => 0x03c3, + 0xf4 => 0x03c4, 0xf5 => 0x03b8, 0xf6 => 0x03c9, 0xf7 => 0x03c2, + 0xf8 => 0x03c7, 0xf9 => 0x03c5, 0xfa => 0x03b6, 0xfb => 0x03ca, + 0xfc => 0x03cb, 0xfd => 0x0390, 0xfe => 0x03b0, 0xff => 0xad, +); + +1; # end diff --git a/lib/Image/ExifTool/Charset/MacHebrew.pm b/lib/Image/ExifTool/Charset/MacHebrew.pm new file mode 100644 index 0000000..86f8f08 --- /dev/null +++ b/lib/Image/ExifTool/Charset/MacHebrew.pm @@ -0,0 +1,47 @@ +#------------------------------------------------------------------------------ +# File: MacHebrew.pm +# +# Description: Mac Hebrew to Unicode +# +# Revisions: 2010/01/20 - P. Harvey created +# +# References: 1) http://unicode.org/Public/MAPPINGS/VENDORS/APPLE/HEBREW.TXT +# +# Notes: The table omits 1-byte characters with the same values as Unicode +# and directional characters are ignored +#------------------------------------------------------------------------------ +use strict; + +%Image::ExifTool::Charset::MacHebrew = ( + 0x80 => 0xc4, 0x81 => [0x05f2,0x05b7], 0x82 => 0xc7, 0x83 => 0xc9, + 0x84 => 0xd1, 0x85 => 0xd6, 0x86 => 0xdc, 0x87 => 0xe1, 0x88 => 0xe0, + 0x89 => 0xe2, 0x8a => 0xe4, 0x8b => 0xe3, 0x8c => 0xe5, 0x8d => 0xe7, + 0x8e => 0xe9, 0x8f => 0xe8, 0x90 => 0xea, 0x91 => 0xeb, 0x92 => 0xed, + 0x93 => 0xec, 0x94 => 0xee, 0x95 => 0xef, 0x96 => 0xf1, 0x97 => 0xf3, + 0x98 => 0xf2, 0x99 => 0xf4, 0x9a => 0xf6, 0x9b => 0xf5, 0x9c => 0xfa, + 0x9d => 0xf9, 0x9e => 0xfb, 0x9f => 0xfc, 0xa0 => 0x20, 0xa1 => 0x21, + 0xa2 => 0x22, 0xa3 => 0x23, 0xa4 => 0x24, 0xa5 => 0x25, 0xa6 => 0x20aa, + 0xa7 => 0x27, 0xa8 => 0x29, 0xa9 => 0x28, 0xaa => 0x2a, 0xab => 0x2b, + 0xac => 0x2c, 0xad => 0x2d, 0xae => 0x2e, 0xaf => 0x2f, 0xb0 => 0x30, + 0xb1 => 0x31, 0xb2 => 0x32, 0xb3 => 0x33, 0xb4 => 0x34, 0xb5 => 0x35, + 0xb6 => 0x36, 0xb7 => 0x37, 0xb8 => 0x38, 0xb9 => 0x39, 0xba => 0x3a, + 0xbb => 0x3b, 0xbc => 0x3c, 0xbd => 0x3d, 0xbe => 0x3e, 0xbf => 0x3f, + 0xc0 => [0xf86a,0x05dc,0x05b9], 0xc1 => 0x201e, 0xc2 => 0xf89b, + 0xc3 => 0xf89c, 0xc4 => 0xf89d, 0xc5 => 0xf89e, 0xc6 => 0x05bc, + 0xc7 => 0xfb4b, 0xc8 => 0xfb35, 0xc9 => 0x2026, 0xca => 0xa0, 0xcb => 0x05b8, + 0xcc => 0x05b7, 0xcd => 0x05b5, 0xce => 0x05b6, 0xcf => 0x05b4, + 0xd0 => 0x2013, 0xd1 => 0x2014, 0xd2 => 0x201c, 0xd3 => 0x201d, + 0xd4 => 0x2018, 0xd5 => 0x2019, 0xd6 => 0xfb2a, 0xd7 => 0xfb2b, + 0xd8 => 0x05bf, 0xd9 => 0x05b0, 0xda => 0x05b2, 0xdb => 0x05b1, + 0xdc => 0x05bb, 0xdd => 0x05b9, 0xde => [0x05b8,0xf87f], 0xdf => 0x05b3, + 0xe0 => 0x05d0, 0xe1 => 0x05d1, 0xe2 => 0x05d2, 0xe3 => 0x05d3, + 0xe4 => 0x05d4, 0xe5 => 0x05d5, 0xe6 => 0x05d6, 0xe7 => 0x05d7, + 0xe8 => 0x05d8, 0xe9 => 0x05d9, 0xea => 0x05da, 0xeb => 0x05db, + 0xec => 0x05dc, 0xed => 0x05dd, 0xee => 0x05de, 0xef => 0x05df, + 0xf0 => 0x05e0, 0xf1 => 0x05e1, 0xf2 => 0x05e2, 0xf3 => 0x05e3, + 0xf4 => 0x05e4, 0xf5 => 0x05e5, 0xf6 => 0x05e6, 0xf7 => 0x05e7, + 0xf8 => 0x05e8, 0xf9 => 0x05e9, 0xfa => 0x05ea, 0xfb => 0x7d, 0xfc => 0x5d, + 0xfd => 0x7b, 0xfe => 0x5b, 0xff => 0x7c, +); + +1; # end diff --git a/lib/Image/ExifTool/Charset/MacIceland.pm b/lib/Image/ExifTool/Charset/MacIceland.pm new file mode 100644 index 0000000..ad4d0c4 --- /dev/null +++ b/lib/Image/ExifTool/Charset/MacIceland.pm @@ -0,0 +1,42 @@ +#------------------------------------------------------------------------------ +# File: MacIceland.pm +# +# Description: Mac Icelandic to Unicode +# +# Revisions: 2010/01/20 - P. Harvey created +# +# References: 1) http://unicode.org/Public/MAPPINGS/VENDORS/APPLE/ICELAND.TXT +# +# Notes: The table omits 1-byte characters with the same values as Unicode +#------------------------------------------------------------------------------ +use strict; + +%Image::ExifTool::Charset::MacIceland = ( + 0x80 => 0xc4, 0x81 => 0xc5, 0x82 => 0xc7, 0x83 => 0xc9, 0x84 => 0xd1, + 0x85 => 0xd6, 0x86 => 0xdc, 0x87 => 0xe1, 0x88 => 0xe0, 0x89 => 0xe2, + 0x8a => 0xe4, 0x8b => 0xe3, 0x8c => 0xe5, 0x8d => 0xe7, 0x8e => 0xe9, + 0x8f => 0xe8, 0x90 => 0xea, 0x91 => 0xeb, 0x92 => 0xed, 0x93 => 0xec, + 0x94 => 0xee, 0x95 => 0xef, 0x96 => 0xf1, 0x97 => 0xf3, 0x98 => 0xf2, + 0x99 => 0xf4, 0x9a => 0xf6, 0x9b => 0xf5, 0x9c => 0xfa, 0x9d => 0xf9, + 0x9e => 0xfb, 0x9f => 0xfc, 0xa0 => 0xdd, 0xa1 => 0xb0, 0xa4 => 0xa7, + 0xa5 => 0x2022, 0xa6 => 0xb6, 0xa7 => 0xdf, 0xa8 => 0xae, 0xaa => 0x2122, + 0xab => 0xb4, 0xac => 0xa8, 0xad => 0x2260, 0xae => 0xc6, 0xaf => 0xd8, + 0xb0 => 0x221e, 0xb2 => 0x2264, 0xb3 => 0x2265, 0xb4 => 0xa5, 0xb6 => 0x2202, + 0xb7 => 0x2211, 0xb8 => 0x220f, 0xb9 => 0x03c0, 0xba => 0x222b, 0xbb => 0xaa, + 0xbc => 0xba, 0xbd => 0x03a9, 0xbe => 0xe6, 0xbf => 0xf8, 0xc0 => 0xbf, + 0xc1 => 0xa1, 0xc2 => 0xac, 0xc3 => 0x221a, 0xc4 => 0x0192, 0xc5 => 0x2248, + 0xc6 => 0x2206, 0xc7 => 0xab, 0xc8 => 0xbb, 0xc9 => 0x2026, 0xca => 0xa0, + 0xcb => 0xc0, 0xcc => 0xc3, 0xcd => 0xd5, 0xce => 0x0152, 0xcf => 0x0153, + 0xd0 => 0x2013, 0xd1 => 0x2014, 0xd2 => 0x201c, 0xd3 => 0x201d, + 0xd4 => 0x2018, 0xd5 => 0x2019, 0xd6 => 0xf7, 0xd7 => 0x25ca, 0xd8 => 0xff, + 0xd9 => 0x0178, 0xda => 0x2044, 0xdb => 0x20ac, 0xdc => 0xd0, 0xdd => 0xf0, + 0xdf => 0xfe, 0xe0 => 0xfd, 0xe1 => 0xb7, 0xe2 => 0x201a, 0xe3 => 0x201e, + 0xe4 => 0x2030, 0xe5 => 0xc2, 0xe6 => 0xca, 0xe7 => 0xc1, 0xe8 => 0xcb, + 0xe9 => 0xc8, 0xea => 0xcd, 0xeb => 0xce, 0xec => 0xcf, 0xed => 0xcc, + 0xee => 0xd3, 0xef => 0xd4, 0xf0 => 0xf8ff, 0xf1 => 0xd2, 0xf2 => 0xda, + 0xf3 => 0xdb, 0xf4 => 0xd9, 0xf5 => 0x0131, 0xf6 => 0x02c6, 0xf7 => 0x02dc, + 0xf8 => 0xaf, 0xf9 => 0x02d8, 0xfa => 0x02d9, 0xfb => 0x02da, 0xfc => 0xb8, + 0xfd => 0x02dd, 0xfe => 0x02db, 0xff => 0x02c7, +); + +1; # end diff --git a/lib/Image/ExifTool/Charset/MacJapanese.pm b/lib/Image/ExifTool/Charset/MacJapanese.pm new file mode 100644 index 0000000..79afe55 --- /dev/null +++ b/lib/Image/ExifTool/Charset/MacJapanese.pm @@ -0,0 +1,1933 @@ +#------------------------------------------------------------------------------ +# File: MacJapanese.pm +# +# Description: Mac Japanese to Unicode +# +# Revisions: 2010/01/20 - P. Harvey created +# +# References: 1) http://unicode.org/Public/MAPPINGS/VENDORS/APPLE/JAPANESE.TXT +# +# Notes: The table omits 1-byte characters with the same values as Unicode +# This set re-maps characters with codepoints less than 0x80 +#------------------------------------------------------------------------------ +use strict; + +%Image::ExifTool::Charset::MacJapanese = ( + 0x5c => 0xa5, 0x80 => 0x5c, 0xa1 => 0xff61, 0xa2 => 0xff62, 0xa3 => 0xff63, + 0xa4 => 0xff64, 0xa5 => 0xff65, 0xa6 => 0xff66, 0xa7 => 0xff67, + 0xa8 => 0xff68, 0xa9 => 0xff69, 0xaa => 0xff6a, 0xab => 0xff6b, + 0xac => 0xff6c, 0xad => 0xff6d, 0xae => 0xff6e, 0xaf => 0xff6f, + 0xb0 => 0xff70, 0xb1 => 0xff71, 0xb2 => 0xff72, 0xb3 => 0xff73, + 0xb4 => 0xff74, 0xb5 => 0xff75, 0xb6 => 0xff76, 0xb7 => 0xff77, + 0xb8 => 0xff78, 0xb9 => 0xff79, 0xba => 0xff7a, 0xbb => 0xff7b, + 0xbc => 0xff7c, 0xbd => 0xff7d, 0xbe => 0xff7e, 0xbf => 0xff7f, + 0xc0 => 0xff80, 0xc1 => 0xff81, 0xc2 => 0xff82, 0xc3 => 0xff83, + 0xc4 => 0xff84, 0xc5 => 0xff85, 0xc6 => 0xff86, 0xc7 => 0xff87, + 0xc8 => 0xff88, 0xc9 => 0xff89, 0xca => 0xff8a, 0xcb => 0xff8b, + 0xcc => 0xff8c, 0xcd => 0xff8d, 0xce => 0xff8e, 0xcf => 0xff8f, + 0xd0 => 0xff90, 0xd1 => 0xff91, 0xd2 => 0xff92, 0xd3 => 0xff93, + 0xd4 => 0xff94, 0xd5 => 0xff95, 0xd6 => 0xff96, 0xd7 => 0xff97, + 0xd8 => 0xff98, 0xd9 => 0xff99, 0xda => 0xff9a, 0xdb => 0xff9b, + 0xdc => 0xff9c, 0xdd => 0xff9d, 0xde => 0xff9e, 0xdf => 0xff9f, 0xfd => 0xa9, + 0xfe => 0x2122, 0xff => [0x2026,0xf87f], + 0x81 => { + 0x40 => 0x3000, 0x41 => 0x3001, 0x42 => 0x3002, 0x43 => 0xff0c, + 0x44 => 0xff0e, 0x45 => 0x30fb, 0x46 => 0xff1a, 0x47 => 0xff1b, + 0x48 => 0xff1f, 0x49 => 0xff01, 0x4a => 0x309b, 0x4b => 0x309c, + 0x4c => 0xb4, 0x4d => 0xff40, 0x4e => 0xa8, 0x4f => 0xff3e, 0x50 => 0xffe3, + 0x51 => 0xff3f, 0x52 => 0x30fd, 0x53 => 0x30fe, 0x54 => 0x309d, + 0x55 => 0x309e, 0x56 => 0x3003, 0x57 => 0x4edd, 0x58 => 0x3005, + 0x59 => 0x3006, 0x5a => 0x3007, 0x5b => 0x30fc, 0x5c => 0x2014, + 0x5d => 0x2010, 0x5e => 0xff0f, 0x5f => 0xff3c, 0x60 => 0x301c, + 0x61 => 0x2016, 0x62 => 0xff5c, 0x63 => 0x2026, 0x64 => 0x2025, + 0x65 => 0x2018, 0x66 => 0x2019, 0x67 => 0x201c, 0x68 => 0x201d, + 0x69 => 0xff08, 0x6a => 0xff09, 0x6b => 0x3014, 0x6c => 0x3015, + 0x6d => 0xff3b, 0x6e => 0xff3d, 0x6f => 0xff5b, 0x70 => 0xff5d, + 0x71 => 0x3008, 0x72 => 0x3009, 0x73 => 0x300a, 0x74 => 0x300b, + 0x75 => 0x300c, 0x76 => 0x300d, 0x77 => 0x300e, 0x78 => 0x300f, + 0x79 => 0x3010, 0x7a => 0x3011, 0x7b => 0xff0b, 0x7c => 0x2212, + 0x7d => 0xb1, 0x7e => 0xd7, 0x80 => 0xf7, 0x81 => 0xff1d, 0x82 => 0x2260, + 0x83 => 0xff1c, 0x84 => 0xff1e, 0x85 => 0x2266, 0x86 => 0x2267, + 0x87 => 0x221e, 0x88 => 0x2234, 0x89 => 0x2642, 0x8a => 0x2640, + 0x8b => 0xb0, 0x8c => 0x2032, 0x8d => 0x2033, 0x8e => 0x2103, + 0x8f => 0xffe5, 0x90 => 0xff04, 0x91 => 0xa2, 0x92 => 0xa3, 0x93 => 0xff05, + 0x94 => 0xff03, 0x95 => 0xff06, 0x96 => 0xff0a, 0x97 => 0xff20, + 0x98 => 0xa7, 0x99 => 0x2606, 0x9a => 0x2605, 0x9b => 0x25cb, + 0x9c => 0x25cf, 0x9d => 0x25ce, 0x9e => 0x25c7, 0x9f => 0x25c6, + 0xa0 => 0x25a1, 0xa1 => 0x25a0, 0xa2 => 0x25b3, 0xa3 => 0x25b2, + 0xa4 => 0x25bd, 0xa5 => 0x25bc, 0xa6 => 0x203b, 0xa7 => 0x3012, + 0xa8 => 0x2192, 0xa9 => 0x2190, 0xaa => 0x2191, 0xab => 0x2193, + 0xac => 0x3013, 0xb8 => 0x2208, 0xb9 => 0x220b, 0xba => 0x2286, + 0xbb => 0x2287, 0xbc => 0x2282, 0xbd => 0x2283, 0xbe => 0x222a, + 0xbf => 0x2229, 0xc8 => 0x2227, 0xc9 => 0x2228, 0xca => 0xac, + 0xcb => 0x21d2, 0xcc => 0x21d4, 0xcd => 0x2200, 0xce => 0x2203, + 0xda => 0x2220, 0xdb => 0x22a5, 0xdc => 0x2312, 0xdd => 0x2202, + 0xde => 0x2207, 0xdf => 0x2261, 0xe0 => 0x2252, 0xe1 => 0x226a, + 0xe2 => 0x226b, 0xe3 => 0x221a, 0xe4 => 0x223d, 0xe5 => 0x221d, + 0xe6 => 0x2235, 0xe7 => 0x222b, 0xe8 => 0x222c, 0xf0 => 0x212b, + 0xf1 => 0x2030, 0xf2 => 0x266f, 0xf3 => 0x266d, 0xf4 => 0x266a, + 0xf5 => 0x2020, 0xf6 => 0x2021, 0xf7 => 0xb6, 0xfc => 0x25ef, + }, + 0x82 => { + 0x4f => 0xff10, 0x50 => 0xff11, 0x51 => 0xff12, 0x52 => 0xff13, + 0x53 => 0xff14, 0x54 => 0xff15, 0x55 => 0xff16, 0x56 => 0xff17, + 0x57 => 0xff18, 0x58 => 0xff19, 0x60 => 0xff21, 0x61 => 0xff22, + 0x62 => 0xff23, 0x63 => 0xff24, 0x64 => 0xff25, 0x65 => 0xff26, + 0x66 => 0xff27, 0x67 => 0xff28, 0x68 => 0xff29, 0x69 => 0xff2a, + 0x6a => 0xff2b, 0x6b => 0xff2c, 0x6c => 0xff2d, 0x6d => 0xff2e, + 0x6e => 0xff2f, 0x6f => 0xff30, 0x70 => 0xff31, 0x71 => 0xff32, + 0x72 => 0xff33, 0x73 => 0xff34, 0x74 => 0xff35, 0x75 => 0xff36, + 0x76 => 0xff37, 0x77 => 0xff38, 0x78 => 0xff39, 0x79 => 0xff3a, + 0x81 => 0xff41, 0x82 => 0xff42, 0x83 => 0xff43, 0x84 => 0xff44, + 0x85 => 0xff45, 0x86 => 0xff46, 0x87 => 0xff47, 0x88 => 0xff48, + 0x89 => 0xff49, 0x8a => 0xff4a, 0x8b => 0xff4b, 0x8c => 0xff4c, + 0x8d => 0xff4d, 0x8e => 0xff4e, 0x8f => 0xff4f, 0x90 => 0xff50, + 0x91 => 0xff51, 0x92 => 0xff52, 0x93 => 0xff53, 0x94 => 0xff54, + 0x95 => 0xff55, 0x96 => 0xff56, 0x97 => 0xff57, 0x98 => 0xff58, + 0x99 => 0xff59, 0x9a => 0xff5a, 0x9f => 0x3041, 0xa0 => 0x3042, + 0xa1 => 0x3043, 0xa2 => 0x3044, 0xa3 => 0x3045, 0xa4 => 0x3046, + 0xa5 => 0x3047, 0xa6 => 0x3048, 0xa7 => 0x3049, 0xa8 => 0x304a, + 0xa9 => 0x304b, 0xaa => 0x304c, 0xab => 0x304d, 0xac => 0x304e, + 0xad => 0x304f, 0xae => 0x3050, 0xaf => 0x3051, 0xb0 => 0x3052, + 0xb1 => 0x3053, 0xb2 => 0x3054, 0xb3 => 0x3055, 0xb4 => 0x3056, + 0xb5 => 0x3057, 0xb6 => 0x3058, 0xb7 => 0x3059, 0xb8 => 0x305a, + 0xb9 => 0x305b, 0xba => 0x305c, 0xbb => 0x305d, 0xbc => 0x305e, + 0xbd => 0x305f, 0xbe => 0x3060, 0xbf => 0x3061, 0xc0 => 0x3062, + 0xc1 => 0x3063, 0xc2 => 0x3064, 0xc3 => 0x3065, 0xc4 => 0x3066, + 0xc5 => 0x3067, 0xc6 => 0x3068, 0xc7 => 0x3069, 0xc8 => 0x306a, + 0xc9 => 0x306b, 0xca => 0x306c, 0xcb => 0x306d, 0xcc => 0x306e, + 0xcd => 0x306f, 0xce => 0x3070, 0xcf => 0x3071, 0xd0 => 0x3072, + 0xd1 => 0x3073, 0xd2 => 0x3074, 0xd3 => 0x3075, 0xd4 => 0x3076, + 0xd5 => 0x3077, 0xd6 => 0x3078, 0xd7 => 0x3079, 0xd8 => 0x307a, + 0xd9 => 0x307b, 0xda => 0x307c, 0xdb => 0x307d, 0xdc => 0x307e, + 0xdd => 0x307f, 0xde => 0x3080, 0xdf => 0x3081, 0xe0 => 0x3082, + 0xe1 => 0x3083, 0xe2 => 0x3084, 0xe3 => 0x3085, 0xe4 => 0x3086, + 0xe5 => 0x3087, 0xe6 => 0x3088, 0xe7 => 0x3089, 0xe8 => 0x308a, + 0xe9 => 0x308b, 0xea => 0x308c, 0xeb => 0x308d, 0xec => 0x308e, + 0xed => 0x308f, 0xee => 0x3090, 0xef => 0x3091, 0xf0 => 0x3092, + 0xf1 => 0x3093, + }, + 0x83 => { + 0x40 => 0x30a1, 0x41 => 0x30a2, 0x42 => 0x30a3, 0x43 => 0x30a4, + 0x44 => 0x30a5, 0x45 => 0x30a6, 0x46 => 0x30a7, 0x47 => 0x30a8, + 0x48 => 0x30a9, 0x49 => 0x30aa, 0x4a => 0x30ab, 0x4b => 0x30ac, + 0x4c => 0x30ad, 0x4d => 0x30ae, 0x4e => 0x30af, 0x4f => 0x30b0, + 0x50 => 0x30b1, 0x51 => 0x30b2, 0x52 => 0x30b3, 0x53 => 0x30b4, + 0x54 => 0x30b5, 0x55 => 0x30b6, 0x56 => 0x30b7, 0x57 => 0x30b8, + 0x58 => 0x30b9, 0x59 => 0x30ba, 0x5a => 0x30bb, 0x5b => 0x30bc, + 0x5c => 0x30bd, 0x5d => 0x30be, 0x5e => 0x30bf, 0x5f => 0x30c0, + 0x60 => 0x30c1, 0x61 => 0x30c2, 0x62 => 0x30c3, 0x63 => 0x30c4, + 0x64 => 0x30c5, 0x65 => 0x30c6, 0x66 => 0x30c7, 0x67 => 0x30c8, + 0x68 => 0x30c9, 0x69 => 0x30ca, 0x6a => 0x30cb, 0x6b => 0x30cc, + 0x6c => 0x30cd, 0x6d => 0x30ce, 0x6e => 0x30cf, 0x6f => 0x30d0, + 0x70 => 0x30d1, 0x71 => 0x30d2, 0x72 => 0x30d3, 0x73 => 0x30d4, + 0x74 => 0x30d5, 0x75 => 0x30d6, 0x76 => 0x30d7, 0x77 => 0x30d8, + 0x78 => 0x30d9, 0x79 => 0x30da, 0x7a => 0x30db, 0x7b => 0x30dc, + 0x7c => 0x30dd, 0x7d => 0x30de, 0x7e => 0x30df, 0x80 => 0x30e0, + 0x81 => 0x30e1, 0x82 => 0x30e2, 0x83 => 0x30e3, 0x84 => 0x30e4, + 0x85 => 0x30e5, 0x86 => 0x30e6, 0x87 => 0x30e7, 0x88 => 0x30e8, + 0x89 => 0x30e9, 0x8a => 0x30ea, 0x8b => 0x30eb, 0x8c => 0x30ec, + 0x8d => 0x30ed, 0x8e => 0x30ee, 0x8f => 0x30ef, 0x90 => 0x30f0, + 0x91 => 0x30f1, 0x92 => 0x30f2, 0x93 => 0x30f3, 0x94 => 0x30f4, + 0x95 => 0x30f5, 0x96 => 0x30f6, 0x9f => 0x0391, 0xa0 => 0x0392, + 0xa1 => 0x0393, 0xa2 => 0x0394, 0xa3 => 0x0395, 0xa4 => 0x0396, + 0xa5 => 0x0397, 0xa6 => 0x0398, 0xa7 => 0x0399, 0xa8 => 0x039a, + 0xa9 => 0x039b, 0xaa => 0x039c, 0xab => 0x039d, 0xac => 0x039e, + 0xad => 0x039f, 0xae => 0x03a0, 0xaf => 0x03a1, 0xb0 => 0x03a3, + 0xb1 => 0x03a4, 0xb2 => 0x03a5, 0xb3 => 0x03a6, 0xb4 => 0x03a7, + 0xb5 => 0x03a8, 0xb6 => 0x03a9, 0xbf => 0x03b1, 0xc0 => 0x03b2, + 0xc1 => 0x03b3, 0xc2 => 0x03b4, 0xc3 => 0x03b5, 0xc4 => 0x03b6, + 0xc5 => 0x03b7, 0xc6 => 0x03b8, 0xc7 => 0x03b9, 0xc8 => 0x03ba, + 0xc9 => 0x03bb, 0xca => 0x03bc, 0xcb => 0x03bd, 0xcc => 0x03be, + 0xcd => 0x03bf, 0xce => 0x03c0, 0xcf => 0x03c1, 0xd0 => 0x03c3, + 0xd1 => 0x03c4, 0xd2 => 0x03c5, 0xd3 => 0x03c6, 0xd4 => 0x03c7, + 0xd5 => 0x03c8, 0xd6 => 0x03c9, + }, + 0x84 => { + 0x40 => 0x0410, 0x41 => 0x0411, 0x42 => 0x0412, 0x43 => 0x0413, + 0x44 => 0x0414, 0x45 => 0x0415, 0x46 => 0x0401, 0x47 => 0x0416, + 0x48 => 0x0417, 0x49 => 0x0418, 0x4a => 0x0419, 0x4b => 0x041a, + 0x4c => 0x041b, 0x4d => 0x041c, 0x4e => 0x041d, 0x4f => 0x041e, + 0x50 => 0x041f, 0x51 => 0x0420, 0x52 => 0x0421, 0x53 => 0x0422, + 0x54 => 0x0423, 0x55 => 0x0424, 0x56 => 0x0425, 0x57 => 0x0426, + 0x58 => 0x0427, 0x59 => 0x0428, 0x5a => 0x0429, 0x5b => 0x042a, + 0x5c => 0x042b, 0x5d => 0x042c, 0x5e => 0x042d, 0x5f => 0x042e, + 0x60 => 0x042f, 0x70 => 0x0430, 0x71 => 0x0431, 0x72 => 0x0432, + 0x73 => 0x0433, 0x74 => 0x0434, 0x75 => 0x0435, 0x76 => 0x0451, + 0x77 => 0x0436, 0x78 => 0x0437, 0x79 => 0x0438, 0x7a => 0x0439, + 0x7b => 0x043a, 0x7c => 0x043b, 0x7d => 0x043c, 0x7e => 0x043d, + 0x80 => 0x043e, 0x81 => 0x043f, 0x82 => 0x0440, 0x83 => 0x0441, + 0x84 => 0x0442, 0x85 => 0x0443, 0x86 => 0x0444, 0x87 => 0x0445, + 0x88 => 0x0446, 0x89 => 0x0447, 0x8a => 0x0448, 0x8b => 0x0449, + 0x8c => 0x044a, 0x8d => 0x044b, 0x8e => 0x044c, 0x8f => 0x044d, + 0x90 => 0x044e, 0x91 => 0x044f, 0x9f => 0x2500, 0xa0 => 0x2502, + 0xa1 => 0x250c, 0xa2 => 0x2510, 0xa3 => 0x2518, 0xa4 => 0x2514, + 0xa5 => 0x251c, 0xa6 => 0x252c, 0xa7 => 0x2524, 0xa8 => 0x2534, + 0xa9 => 0x253c, 0xaa => 0x2501, 0xab => 0x2503, 0xac => 0x250f, + 0xad => 0x2513, 0xae => 0x251b, 0xaf => 0x2517, 0xb0 => 0x2523, + 0xb1 => 0x2533, 0xb2 => 0x252b, 0xb3 => 0x253b, 0xb4 => 0x254b, + 0xb5 => 0x2520, 0xb6 => 0x252f, 0xb7 => 0x2528, 0xb8 => 0x2537, + 0xb9 => 0x253f, 0xba => 0x251d, 0xbb => 0x2530, 0xbc => 0x2525, + 0xbd => 0x2538, 0xbe => 0x2542, + }, + 0x85 => { + 0x40 => 0x2460, 0x41 => 0x2461, 0x42 => 0x2462, 0x43 => 0x2463, + 0x44 => 0x2464, 0x45 => 0x2465, 0x46 => 0x2466, 0x47 => 0x2467, + 0x48 => 0x2468, 0x49 => 0x2469, 0x4a => 0x246a, 0x4b => 0x246b, + 0x4c => 0x246c, 0x4d => 0x246d, 0x4e => 0x246e, 0x4f => 0x246f, + 0x50 => 0x2470, 0x51 => 0x2471, 0x52 => 0x2472, 0x53 => 0x2473, + 0x5e => 0x2474, 0x5f => 0x2475, 0x60 => 0x2476, 0x61 => 0x2477, + 0x62 => 0x2478, 0x63 => 0x2479, 0x64 => 0x247a, 0x65 => 0x247b, + 0x66 => 0x247c, 0x67 => 0x247d, 0x68 => 0x247e, 0x69 => 0x247f, + 0x6a => 0x2480, 0x6b => 0x2481, 0x6c => 0x2482, 0x6d => 0x2483, + 0x6e => 0x2484, 0x6f => 0x2485, 0x70 => 0x2486, 0x71 => 0x2487, + 0x7c => 0x2776, 0x7d => 0x2777, 0x7e => 0x2778, 0x80 => 0x2779, + 0x81 => 0x277a, 0x82 => 0x277b, 0x83 => 0x277c, 0x84 => 0x277d, + 0x85 => 0x277e, 0x91 => [0xf860,0x30,0x2e], 0x92 => 0x2488, 0x93 => 0x2489, + 0x94 => 0x248a, 0x95 => 0x248b, 0x96 => 0x248c, 0x97 => 0x248d, + 0x98 => 0x248e, 0x99 => 0x248f, 0x9a => 0x2490, 0x9f => 0x2160, + 0xa0 => 0x2161, 0xa1 => 0x2162, 0xa2 => 0x2163, 0xa3 => 0x2164, + 0xa4 => 0x2165, 0xa5 => 0x2166, 0xa6 => 0x2167, 0xa7 => 0x2168, + 0xa8 => 0x2169, 0xa9 => 0x216a, 0xaa => 0x216b, + 0xab => [0xf862,0x58,0x49,0x49,0x49], 0xac => [0xf861,0x58,0x49,0x56], + 0xad => [0xf860,0x58,0x56], 0xb3 => 0x2170, 0xb4 => 0x2171, 0xb5 => 0x2172, + 0xb6 => 0x2173, 0xb7 => 0x2174, 0xb8 => 0x2175, 0xb9 => 0x2176, + 0xba => 0x2177, 0xbb => 0x2178, 0xbc => 0x2179, 0xbd => 0x217a, + 0xbe => 0x217b, 0xbf => [0xf862,0x78,0x69,0x69,0x69], + 0xc0 => [0xf861,0x78,0x69,0x76], 0xc1 => [0xf860,0x78,0x76], 0xdb => 0x249c, + 0xdc => 0x249d, 0xdd => 0x249e, 0xde => 0x249f, 0xdf => 0x24a0, + 0xe0 => 0x24a1, 0xe1 => 0x24a2, 0xe2 => 0x24a3, 0xe3 => 0x24a4, + 0xe4 => 0x24a5, 0xe5 => 0x24a6, 0xe6 => 0x24a7, 0xe7 => 0x24a8, + 0xe8 => 0x24a9, 0xe9 => 0x24aa, 0xea => 0x24ab, 0xeb => 0x24ac, + 0xec => 0x24ad, 0xed => 0x24ae, 0xee => 0x24af, 0xef => 0x24b0, + 0xf0 => 0x24b1, 0xf1 => 0x24b2, 0xf2 => 0x24b3, 0xf3 => 0x24b4, + 0xf4 => 0x24b5, + }, + 0x86 => { + 0x40 => 0x339c, 0x41 => 0x339f, 0x42 => 0x339d, 0x43 => 0x33a0, + 0x44 => 0x33a4, 0x45 => [0xff4d,0xf87f], 0x46 => 0x33a1, 0x47 => 0x33a5, + 0x48 => 0x339e, 0x49 => 0x33a2, 0x4a => 0x338e, 0x4b => [0xff47,0xf87f], + 0x4c => 0x338f, 0x4d => 0x33c4, 0x4e => 0x3396, 0x4f => 0x3397, + 0x50 => 0x2113, 0x51 => 0x3398, 0x52 => 0x33b3, 0x53 => 0x33b2, + 0x54 => 0x33b1, 0x55 => 0x33b0, 0x56 => 0x2109, 0x57 => 0x33d4, + 0x58 => 0x33cb, 0x59 => 0x3390, 0x5a => 0x3385, 0x5b => 0x3386, + 0x5c => 0x3387, 0x5d => [0xf860,0x54,0x42], 0x9b => 0x2116, 0x9c => 0x33cd, + 0x9d => 0x2121, 0x9e => [0xf861,0x46,0x41,0x58], 0x9f => 0x2664, + 0xa0 => 0x2667, 0xa1 => 0x2661, 0xa2 => 0x2662, 0xa3 => 0x2660, + 0xa4 => 0x2663, 0xa5 => 0x2665, 0xa6 => 0x2666, 0xb3 => 0x3020, + 0xb4 => 0x260e, 0xb5 => 0x3004, 0xc7 => 0x261e, 0xc8 => 0x261c, + 0xc9 => 0x261d, 0xca => 0x261f, 0xcb => 0x21c6, 0xcc => 0x21c4, + 0xcd => 0x21c5, 0xce => [0xf860,0x2193,0x2191], 0xcf => 0x21e8, + 0xd0 => 0x21e6, 0xd1 => 0x21e7, 0xd2 => 0x21e9, 0xd3 => [0x21e8,0xf87a], + 0xd4 => [0x21e6,0xf87a], 0xd5 => [0x21e7,0xf87a], 0xd6 => [0x21e9,0xf87a], + }, + 0x87 => { + 0x40 => 0x3230, 0x41 => 0x322a, 0x42 => 0x322b, 0x43 => 0x322c, + 0x44 => 0x322d, 0x45 => 0x322e, 0x46 => 0x322f, 0x47 => 0x3240, + 0x48 => 0x3237, 0x49 => 0x3242, 0x4a => 0x3243, 0x4b => 0x3239, + 0x4c => 0x323a, 0x4d => 0x3231, 0x4e => 0x323e, 0x4f => 0x3234, + 0x50 => 0x3232, 0x51 => 0x323b, 0x52 => 0x3236, 0x53 => 0x3233, + 0x54 => 0x3235, 0x55 => 0x323c, 0x56 => 0x323d, 0x57 => 0x323f, + 0x58 => 0x3238, 0x91 => [0x5927,0x20dd], 0x92 => [0x5c0f,0x20dd], + 0x93 => 0x32a4, 0x94 => 0x32a5, 0x95 => 0x32a6, 0x96 => 0x32a7, + 0x97 => 0x32a8, 0x98 => 0x32a9, 0x99 => 0x3296, 0x9a => 0x329d, + 0x9b => 0x3298, 0x9c => 0x329e, 0x9d => [0x63a7,0x20dd], 0x9e => 0x3299, + 0x9f => 0x3349, 0xa0 => 0x3322, 0xa1 => 0x334d, 0xa2 => 0x3314, + 0xa3 => 0x3316, 0xa4 => 0x3305, 0xa5 => 0x3333, 0xa6 => 0x334e, + 0xa7 => 0x3303, 0xa8 => 0x3336, 0xa9 => 0x3318, 0xaa => 0x3315, + 0xab => 0x3327, 0xac => 0x3351, 0xad => 0x334a, 0xae => 0x3339, + 0xaf => 0x3357, 0xb0 => 0x330d, 0xb1 => 0x3342, 0xb2 => 0x3323, + 0xb3 => 0x3326, 0xb4 => 0x333b, 0xb5 => 0x332b, 0xbd => 0x3300, + 0xbe => 0x331e, 0xbf => 0x332a, 0xc0 => 0x3331, 0xc1 => 0x3347, + 0xe5 => 0x337e, 0xe6 => 0x337d, 0xe7 => 0x337c, 0xe8 => 0x337b, + 0xfa => 0x337f, 0xfb => [0xf862,0x6709,0x9650,0x4f1a,0x793e], + 0xfc => [0xf862,0x8ca1,0x56e3,0x6cd5,0x4eba], + }, + 0x88 => { + 0x40 => 0x222e, 0x41 => 0x221f, 0x42 => 0x22bf, 0x54 => 0x301d, + 0x55 => 0x301f, 0x68 => 0x3094, 0x6a => 0x30f7, 0x6b => 0x30f8, + 0x6c => 0x30f9, 0x6d => 0x30fa, 0x9f => 0x4e9c, 0xa0 => 0x5516, + 0xa1 => 0x5a03, 0xa2 => 0x963f, 0xa3 => 0x54c0, 0xa4 => 0x611b, + 0xa5 => 0x6328, 0xa6 => 0x59f6, 0xa7 => 0x9022, 0xa8 => 0x8475, + 0xa9 => 0x831c, 0xaa => 0x7a50, 0xab => 0x60aa, 0xac => 0x63e1, + 0xad => 0x6e25, 0xae => 0x65ed, 0xaf => 0x8466, 0xb0 => 0x82a6, + 0xb1 => 0x9bf5, 0xb2 => 0x6893, 0xb3 => 0x5727, 0xb4 => 0x65a1, + 0xb5 => 0x6271, 0xb6 => 0x5b9b, 0xb7 => 0x59d0, 0xb8 => 0x867b, + 0xb9 => 0x98f4, 0xba => 0x7d62, 0xbb => 0x7dbe, 0xbc => 0x9b8e, + 0xbd => 0x6216, 0xbe => 0x7c9f, 0xbf => 0x88b7, 0xc0 => 0x5b89, + 0xc1 => 0x5eb5, 0xc2 => 0x6309, 0xc3 => 0x6697, 0xc4 => 0x6848, + 0xc5 => 0x95c7, 0xc6 => 0x978d, 0xc7 => 0x674f, 0xc8 => 0x4ee5, + 0xc9 => 0x4f0a, 0xca => 0x4f4d, 0xcb => 0x4f9d, 0xcc => 0x5049, + 0xcd => 0x56f2, 0xce => 0x5937, 0xcf => 0x59d4, 0xd0 => 0x5a01, + 0xd1 => 0x5c09, 0xd2 => 0x60df, 0xd3 => 0x610f, 0xd4 => 0x6170, + 0xd5 => 0x6613, 0xd6 => 0x6905, 0xd7 => 0x70ba, 0xd8 => 0x754f, + 0xd9 => 0x7570, 0xda => 0x79fb, 0xdb => 0x7dad, 0xdc => 0x7def, + 0xdd => 0x80c3, 0xde => 0x840e, 0xdf => 0x8863, 0xe0 => 0x8b02, + 0xe1 => 0x9055, 0xe2 => 0x907a, 0xe3 => 0x533b, 0xe4 => 0x4e95, + 0xe5 => 0x4ea5, 0xe6 => 0x57df, 0xe7 => 0x80b2, 0xe8 => 0x90c1, + 0xe9 => 0x78ef, 0xea => 0x4e00, 0xeb => 0x58f1, 0xec => 0x6ea2, + 0xed => 0x9038, 0xee => 0x7a32, 0xef => 0x8328, 0xf0 => 0x828b, + 0xf1 => 0x9c2f, 0xf2 => 0x5141, 0xf3 => 0x5370, 0xf4 => 0x54bd, + 0xf5 => 0x54e1, 0xf6 => 0x56e0, 0xf7 => 0x59fb, 0xf8 => 0x5f15, + 0xf9 => 0x98f2, 0xfa => 0x6deb, 0xfb => 0x80e4, 0xfc => 0x852d, + }, + 0x89 => { + 0x40 => 0x9662, 0x41 => 0x9670, 0x42 => 0x96a0, 0x43 => 0x97fb, + 0x44 => 0x540b, 0x45 => 0x53f3, 0x46 => 0x5b87, 0x47 => 0x70cf, + 0x48 => 0x7fbd, 0x49 => 0x8fc2, 0x4a => 0x96e8, 0x4b => 0x536f, + 0x4c => 0x9d5c, 0x4d => 0x7aba, 0x4e => 0x4e11, 0x4f => 0x7893, + 0x50 => 0x81fc, 0x51 => 0x6e26, 0x52 => 0x5618, 0x53 => 0x5504, + 0x54 => 0x6b1d, 0x55 => 0x851a, 0x56 => 0x9c3b, 0x57 => 0x59e5, + 0x58 => 0x53a9, 0x59 => 0x6d66, 0x5a => 0x74dc, 0x5b => 0x958f, + 0x5c => 0x5642, 0x5d => 0x4e91, 0x5e => 0x904b, 0x5f => 0x96f2, + 0x60 => 0x834f, 0x61 => 0x990c, 0x62 => 0x53e1, 0x63 => 0x55b6, + 0x64 => 0x5b30, 0x65 => 0x5f71, 0x66 => 0x6620, 0x67 => 0x66f3, + 0x68 => 0x6804, 0x69 => 0x6c38, 0x6a => 0x6cf3, 0x6b => 0x6d29, + 0x6c => 0x745b, 0x6d => 0x76c8, 0x6e => 0x7a4e, 0x6f => 0x9834, + 0x70 => 0x82f1, 0x71 => 0x885b, 0x72 => 0x8a60, 0x73 => 0x92ed, + 0x74 => 0x6db2, 0x75 => 0x75ab, 0x76 => 0x76ca, 0x77 => 0x99c5, + 0x78 => 0x60a6, 0x79 => 0x8b01, 0x7a => 0x8d8a, 0x7b => 0x95b2, + 0x7c => 0x698e, 0x7d => 0x53ad, 0x7e => 0x5186, 0x80 => 0x5712, + 0x81 => 0x5830, 0x82 => 0x5944, 0x83 => 0x5bb4, 0x84 => 0x5ef6, + 0x85 => 0x6028, 0x86 => 0x63a9, 0x87 => 0x63f4, 0x88 => 0x6cbf, + 0x89 => 0x6f14, 0x8a => 0x708e, 0x8b => 0x7114, 0x8c => 0x7159, + 0x8d => 0x71d5, 0x8e => 0x733f, 0x8f => 0x7e01, 0x90 => 0x8276, + 0x91 => 0x82d1, 0x92 => 0x8597, 0x93 => 0x9060, 0x94 => 0x925b, + 0x95 => 0x9d1b, 0x96 => 0x5869, 0x97 => 0x65bc, 0x98 => 0x6c5a, + 0x99 => 0x7525, 0x9a => 0x51f9, 0x9b => 0x592e, 0x9c => 0x5965, + 0x9d => 0x5f80, 0x9e => 0x5fdc, 0x9f => 0x62bc, 0xa0 => 0x65fa, + 0xa1 => 0x6a2a, 0xa2 => 0x6b27, 0xa3 => 0x6bb4, 0xa4 => 0x738b, + 0xa5 => 0x7fc1, 0xa6 => 0x8956, 0xa7 => 0x9d2c, 0xa8 => 0x9d0e, + 0xa9 => 0x9ec4, 0xaa => 0x5ca1, 0xab => 0x6c96, 0xac => 0x837b, + 0xad => 0x5104, 0xae => 0x5c4b, 0xaf => 0x61b6, 0xb0 => 0x81c6, + 0xb1 => 0x6876, 0xb2 => 0x7261, 0xb3 => 0x4e59, 0xb4 => 0x4ffa, + 0xb5 => 0x5378, 0xb6 => 0x6069, 0xb7 => 0x6e29, 0xb8 => 0x7a4f, + 0xb9 => 0x97f3, 0xba => 0x4e0b, 0xbb => 0x5316, 0xbc => 0x4eee, + 0xbd => 0x4f55, 0xbe => 0x4f3d, 0xbf => 0x4fa1, 0xc0 => 0x4f73, + 0xc1 => 0x52a0, 0xc2 => 0x53ef, 0xc3 => 0x5609, 0xc4 => 0x590f, + 0xc5 => 0x5ac1, 0xc6 => 0x5bb6, 0xc7 => 0x5be1, 0xc8 => 0x79d1, + 0xc9 => 0x6687, 0xca => 0x679c, 0xcb => 0x67b6, 0xcc => 0x6b4c, + 0xcd => 0x6cb3, 0xce => 0x706b, 0xcf => 0x73c2, 0xd0 => 0x798d, + 0xd1 => 0x79be, 0xd2 => 0x7a3c, 0xd3 => 0x7b87, 0xd4 => 0x82b1, + 0xd5 => 0x82db, 0xd6 => 0x8304, 0xd7 => 0x8377, 0xd8 => 0x83ef, + 0xd9 => 0x83d3, 0xda => 0x8766, 0xdb => 0x8ab2, 0xdc => 0x5629, + 0xdd => 0x8ca8, 0xde => 0x8fe6, 0xdf => 0x904e, 0xe0 => 0x971e, + 0xe1 => 0x868a, 0xe2 => 0x4fc4, 0xe3 => 0x5ce8, 0xe4 => 0x6211, + 0xe5 => 0x7259, 0xe6 => 0x753b, 0xe7 => 0x81e5, 0xe8 => 0x82bd, + 0xe9 => 0x86fe, 0xea => 0x8cc0, 0xeb => 0x96c5, 0xec => 0x9913, + 0xed => 0x99d5, 0xee => 0x4ecb, 0xef => 0x4f1a, 0xf0 => 0x89e3, + 0xf1 => 0x56de, 0xf2 => 0x584a, 0xf3 => 0x58ca, 0xf4 => 0x5efb, + 0xf5 => 0x5feb, 0xf6 => 0x602a, 0xf7 => 0x6094, 0xf8 => 0x6062, + 0xf9 => 0x61d0, 0xfa => 0x6212, 0xfb => 0x62d0, 0xfc => 0x6539, + }, + 0x8a => { + 0x40 => 0x9b41, 0x41 => 0x6666, 0x42 => 0x68b0, 0x43 => 0x6d77, + 0x44 => 0x7070, 0x45 => 0x754c, 0x46 => 0x7686, 0x47 => 0x7d75, + 0x48 => 0x82a5, 0x49 => 0x87f9, 0x4a => 0x958b, 0x4b => 0x968e, + 0x4c => 0x8c9d, 0x4d => 0x51f1, 0x4e => 0x52be, 0x4f => 0x5916, + 0x50 => 0x54b3, 0x51 => 0x5bb3, 0x52 => 0x5d16, 0x53 => 0x6168, + 0x54 => 0x6982, 0x55 => 0x6daf, 0x56 => 0x788d, 0x57 => 0x84cb, + 0x58 => 0x8857, 0x59 => 0x8a72, 0x5a => 0x93a7, 0x5b => 0x9ab8, + 0x5c => 0x6d6c, 0x5d => 0x99a8, 0x5e => 0x86d9, 0x5f => 0x57a3, + 0x60 => 0x67ff, 0x61 => 0x86ce, 0x62 => 0x920e, 0x63 => 0x5283, + 0x64 => 0x5687, 0x65 => 0x5404, 0x66 => 0x5ed3, 0x67 => 0x62e1, + 0x68 => 0x64b9, 0x69 => 0x683c, 0x6a => 0x6838, 0x6b => 0x6bbb, + 0x6c => 0x7372, 0x6d => 0x78ba, 0x6e => 0x7a6b, 0x6f => 0x899a, + 0x70 => 0x89d2, 0x71 => 0x8d6b, 0x72 => 0x8f03, 0x73 => 0x90ed, + 0x74 => 0x95a3, 0x75 => 0x9694, 0x76 => 0x9769, 0x77 => 0x5b66, + 0x78 => 0x5cb3, 0x79 => 0x697d, 0x7a => 0x984d, 0x7b => 0x984e, + 0x7c => 0x639b, 0x7d => 0x7b20, 0x7e => 0x6a2b, 0x80 => 0x6a7f, + 0x81 => 0x68b6, 0x82 => 0x9c0d, 0x83 => 0x6f5f, 0x84 => 0x5272, + 0x85 => 0x559d, 0x86 => 0x6070, 0x87 => 0x62ec, 0x88 => 0x6d3b, + 0x89 => 0x6e07, 0x8a => 0x6ed1, 0x8b => 0x845b, 0x8c => 0x8910, + 0x8d => 0x8f44, 0x8e => 0x4e14, 0x8f => 0x9c39, 0x90 => 0x53f6, + 0x91 => 0x691b, 0x92 => 0x6a3a, 0x93 => 0x9784, 0x94 => 0x682a, + 0x95 => 0x515c, 0x96 => 0x7ac3, 0x97 => 0x84b2, 0x98 => 0x91dc, + 0x99 => 0x938c, 0x9a => 0x565b, 0x9b => 0x9d28, 0x9c => 0x6822, + 0x9d => 0x8305, 0x9e => 0x8431, 0x9f => 0x7ca5, 0xa0 => 0x5208, + 0xa1 => 0x82c5, 0xa2 => 0x74e6, 0xa3 => 0x4e7e, 0xa4 => 0x4f83, + 0xa5 => 0x51a0, 0xa6 => 0x5bd2, 0xa7 => 0x520a, 0xa8 => 0x52d8, + 0xa9 => 0x52e7, 0xaa => 0x5dfb, 0xab => 0x559a, 0xac => 0x582a, + 0xad => 0x59e6, 0xae => 0x5b8c, 0xaf => 0x5b98, 0xb0 => 0x5bdb, + 0xb1 => 0x5e72, 0xb2 => 0x5e79, 0xb3 => 0x60a3, 0xb4 => 0x611f, + 0xb5 => 0x6163, 0xb6 => 0x61be, 0xb7 => 0x63db, 0xb8 => 0x6562, + 0xb9 => 0x67d1, 0xba => 0x6853, 0xbb => 0x68fa, 0xbc => 0x6b3e, + 0xbd => 0x6b53, 0xbe => 0x6c57, 0xbf => 0x6f22, 0xc0 => 0x6f97, + 0xc1 => 0x6f45, 0xc2 => 0x74b0, 0xc3 => 0x7518, 0xc4 => 0x76e3, + 0xc5 => 0x770b, 0xc6 => 0x7aff, 0xc7 => 0x7ba1, 0xc8 => 0x7c21, + 0xc9 => 0x7de9, 0xca => 0x7f36, 0xcb => 0x7ff0, 0xcc => 0x809d, + 0xcd => 0x8266, 0xce => 0x839e, 0xcf => 0x89b3, 0xd0 => 0x8acc, + 0xd1 => 0x8cab, 0xd2 => 0x9084, 0xd3 => 0x9451, 0xd4 => 0x9593, + 0xd5 => 0x9591, 0xd6 => 0x95a2, 0xd7 => 0x9665, 0xd8 => 0x97d3, + 0xd9 => 0x9928, 0xda => 0x8218, 0xdb => 0x4e38, 0xdc => 0x542b, + 0xdd => 0x5cb8, 0xde => 0x5dcc, 0xdf => 0x73a9, 0xe0 => 0x764c, + 0xe1 => 0x773c, 0xe2 => 0x5ca9, 0xe3 => 0x7feb, 0xe4 => 0x8d0b, + 0xe5 => 0x96c1, 0xe6 => 0x9811, 0xe7 => 0x9854, 0xe8 => 0x9858, + 0xe9 => 0x4f01, 0xea => 0x4f0e, 0xeb => 0x5371, 0xec => 0x559c, + 0xed => 0x5668, 0xee => 0x57fa, 0xef => 0x5947, 0xf0 => 0x5b09, + 0xf1 => 0x5bc4, 0xf2 => 0x5c90, 0xf3 => 0x5e0c, 0xf4 => 0x5e7e, + 0xf5 => 0x5fcc, 0xf6 => 0x63ee, 0xf7 => 0x673a, 0xf8 => 0x65d7, + 0xf9 => 0x65e2, 0xfa => 0x671f, 0xfb => 0x68cb, 0xfc => 0x68c4, + }, + 0x8b => { + 0x40 => 0x6a5f, 0x41 => 0x5e30, 0x42 => 0x6bc5, 0x43 => 0x6c17, + 0x44 => 0x6c7d, 0x45 => 0x757f, 0x46 => 0x7948, 0x47 => 0x5b63, + 0x48 => 0x7a00, 0x49 => 0x7d00, 0x4a => 0x5fbd, 0x4b => 0x898f, + 0x4c => 0x8a18, 0x4d => 0x8cb4, 0x4e => 0x8d77, 0x4f => 0x8ecc, + 0x50 => 0x8f1d, 0x51 => 0x98e2, 0x52 => 0x9a0e, 0x53 => 0x9b3c, + 0x54 => 0x4e80, 0x55 => 0x507d, 0x56 => 0x5100, 0x57 => 0x5993, + 0x58 => 0x5b9c, 0x59 => 0x622f, 0x5a => 0x6280, 0x5b => 0x64ec, + 0x5c => 0x6b3a, 0x5d => 0x72a0, 0x5e => 0x7591, 0x5f => 0x7947, + 0x60 => 0x7fa9, 0x61 => 0x87fb, 0x62 => 0x8abc, 0x63 => 0x8b70, + 0x64 => 0x63ac, 0x65 => 0x83ca, 0x66 => 0x97a0, 0x67 => 0x5409, + 0x68 => 0x5403, 0x69 => 0x55ab, 0x6a => 0x6854, 0x6b => 0x6a58, + 0x6c => 0x8a70, 0x6d => 0x7827, 0x6e => 0x6775, 0x6f => 0x9ecd, + 0x70 => 0x5374, 0x71 => 0x5ba2, 0x72 => 0x811a, 0x73 => 0x8650, + 0x74 => 0x9006, 0x75 => 0x4e18, 0x76 => 0x4e45, 0x77 => 0x4ec7, + 0x78 => 0x4f11, 0x79 => 0x53ca, 0x7a => 0x5438, 0x7b => 0x5bae, + 0x7c => 0x5f13, 0x7d => 0x6025, 0x7e => 0x6551, 0x80 => 0x673d, + 0x81 => 0x6c42, 0x82 => 0x6c72, 0x83 => 0x6ce3, 0x84 => 0x7078, + 0x85 => 0x7403, 0x86 => 0x7a76, 0x87 => 0x7aae, 0x88 => 0x7b08, + 0x89 => 0x7d1a, 0x8a => 0x7cfe, 0x8b => 0x7d66, 0x8c => 0x65e7, + 0x8d => 0x725b, 0x8e => 0x53bb, 0x8f => 0x5c45, 0x90 => 0x5de8, + 0x91 => 0x62d2, 0x92 => 0x62e0, 0x93 => 0x6319, 0x94 => 0x6e20, + 0x95 => 0x865a, 0x96 => 0x8a31, 0x97 => 0x8ddd, 0x98 => 0x92f8, + 0x99 => 0x6f01, 0x9a => 0x79a6, 0x9b => 0x9b5a, 0x9c => 0x4ea8, + 0x9d => 0x4eab, 0x9e => 0x4eac, 0x9f => 0x4f9b, 0xa0 => 0x4fa0, + 0xa1 => 0x50d1, 0xa2 => 0x5147, 0xa3 => 0x7af6, 0xa4 => 0x5171, + 0xa5 => 0x51f6, 0xa6 => 0x5354, 0xa7 => 0x5321, 0xa8 => 0x537f, + 0xa9 => 0x53eb, 0xaa => 0x55ac, 0xab => 0x5883, 0xac => 0x5ce1, + 0xad => 0x5f37, 0xae => 0x5f4a, 0xaf => 0x602f, 0xb0 => 0x6050, + 0xb1 => 0x606d, 0xb2 => 0x631f, 0xb3 => 0x6559, 0xb4 => 0x6a4b, + 0xb5 => 0x6cc1, 0xb6 => 0x72c2, 0xb7 => 0x72ed, 0xb8 => 0x77ef, + 0xb9 => 0x80f8, 0xba => 0x8105, 0xbb => 0x8208, 0xbc => 0x854e, + 0xbd => 0x90f7, 0xbe => 0x93e1, 0xbf => 0x97ff, 0xc0 => 0x9957, + 0xc1 => 0x9a5a, 0xc2 => 0x4ef0, 0xc3 => 0x51dd, 0xc4 => 0x5c2d, + 0xc5 => 0x6681, 0xc6 => 0x696d, 0xc7 => 0x5c40, 0xc8 => 0x66f2, + 0xc9 => 0x6975, 0xca => 0x7389, 0xcb => 0x6850, 0xcc => 0x7c81, + 0xcd => 0x50c5, 0xce => 0x52e4, 0xcf => 0x5747, 0xd0 => 0x5dfe, + 0xd1 => 0x9326, 0xd2 => 0x65a4, 0xd3 => 0x6b23, 0xd4 => 0x6b3d, + 0xd5 => 0x7434, 0xd6 => 0x7981, 0xd7 => 0x79bd, 0xd8 => 0x7b4b, + 0xd9 => 0x7dca, 0xda => 0x82b9, 0xdb => 0x83cc, 0xdc => 0x887f, + 0xdd => 0x895f, 0xde => 0x8b39, 0xdf => 0x8fd1, 0xe0 => 0x91d1, + 0xe1 => 0x541f, 0xe2 => 0x9280, 0xe3 => 0x4e5d, 0xe4 => 0x5036, + 0xe5 => 0x53e5, 0xe6 => 0x533a, 0xe7 => 0x72d7, 0xe8 => 0x7396, + 0xe9 => 0x77e9, 0xea => 0x82e6, 0xeb => 0x8eaf, 0xec => 0x99c6, + 0xed => 0x99c8, 0xee => 0x99d2, 0xef => 0x5177, 0xf0 => 0x611a, + 0xf1 => 0x865e, 0xf2 => 0x55b0, 0xf3 => 0x7a7a, 0xf4 => 0x5076, + 0xf5 => 0x5bd3, 0xf6 => 0x9047, 0xf7 => 0x9685, 0xf8 => 0x4e32, + 0xf9 => 0x6adb, 0xfa => 0x91e7, 0xfb => 0x5c51, 0xfc => 0x5c48, + }, + 0x8c => { + 0x40 => 0x6398, 0x41 => 0x7a9f, 0x42 => 0x6c93, 0x43 => 0x9774, + 0x44 => 0x8f61, 0x45 => 0x7aaa, 0x46 => 0x718a, 0x47 => 0x9688, + 0x48 => 0x7c82, 0x49 => 0x6817, 0x4a => 0x7e70, 0x4b => 0x6851, + 0x4c => 0x936c, 0x4d => 0x52f2, 0x4e => 0x541b, 0x4f => 0x85ab, + 0x50 => 0x8a13, 0x51 => 0x7fa4, 0x52 => 0x8ecd, 0x53 => 0x90e1, + 0x54 => 0x5366, 0x55 => 0x8888, 0x56 => 0x7941, 0x57 => 0x4fc2, + 0x58 => 0x50be, 0x59 => 0x5211, 0x5a => 0x5144, 0x5b => 0x5553, + 0x5c => 0x572d, 0x5d => 0x73ea, 0x5e => 0x578b, 0x5f => 0x5951, + 0x60 => 0x5f62, 0x61 => 0x5f84, 0x62 => 0x6075, 0x63 => 0x6176, + 0x64 => 0x6167, 0x65 => 0x61a9, 0x66 => 0x63b2, 0x67 => 0x643a, + 0x68 => 0x656c, 0x69 => 0x666f, 0x6a => 0x6842, 0x6b => 0x6e13, + 0x6c => 0x7566, 0x6d => 0x7a3d, 0x6e => 0x7cfb, 0x6f => 0x7d4c, + 0x70 => 0x7d99, 0x71 => 0x7e4b, 0x72 => 0x7f6b, 0x73 => 0x830e, + 0x74 => 0x834a, 0x75 => 0x86cd, 0x76 => 0x8a08, 0x77 => 0x8a63, + 0x78 => 0x8b66, 0x79 => 0x8efd, 0x7a => 0x981a, 0x7b => 0x9d8f, + 0x7c => 0x82b8, 0x7d => 0x8fce, 0x7e => 0x9be8, 0x80 => 0x5287, + 0x81 => 0x621f, 0x82 => 0x6483, 0x83 => 0x6fc0, 0x84 => 0x9699, + 0x85 => 0x6841, 0x86 => 0x5091, 0x87 => 0x6b20, 0x88 => 0x6c7a, + 0x89 => 0x6f54, 0x8a => 0x7a74, 0x8b => 0x7d50, 0x8c => 0x8840, + 0x8d => 0x8a23, 0x8e => 0x6708, 0x8f => 0x4ef6, 0x90 => 0x5039, + 0x91 => 0x5026, 0x92 => 0x5065, 0x93 => 0x517c, 0x94 => 0x5238, + 0x95 => 0x5263, 0x96 => 0x55a7, 0x97 => 0x570f, 0x98 => 0x5805, + 0x99 => 0x5acc, 0x9a => 0x5efa, 0x9b => 0x61b2, 0x9c => 0x61f8, + 0x9d => 0x62f3, 0x9e => 0x6372, 0x9f => 0x691c, 0xa0 => 0x6a29, + 0xa1 => 0x727d, 0xa2 => 0x72ac, 0xa3 => 0x732e, 0xa4 => 0x7814, + 0xa5 => 0x786f, 0xa6 => 0x7d79, 0xa7 => 0x770c, 0xa8 => 0x80a9, + 0xa9 => 0x898b, 0xaa => 0x8b19, 0xab => 0x8ce2, 0xac => 0x8ed2, + 0xad => 0x9063, 0xae => 0x9375, 0xaf => 0x967a, 0xb0 => 0x9855, + 0xb1 => 0x9a13, 0xb2 => 0x9e78, 0xb3 => 0x5143, 0xb4 => 0x539f, + 0xb5 => 0x53b3, 0xb6 => 0x5e7b, 0xb7 => 0x5f26, 0xb8 => 0x6e1b, + 0xb9 => 0x6e90, 0xba => 0x7384, 0xbb => 0x73fe, 0xbc => 0x7d43, + 0xbd => 0x8237, 0xbe => 0x8a00, 0xbf => 0x8afa, 0xc0 => 0x9650, + 0xc1 => 0x4e4e, 0xc2 => 0x500b, 0xc3 => 0x53e4, 0xc4 => 0x547c, + 0xc5 => 0x56fa, 0xc6 => 0x59d1, 0xc7 => 0x5b64, 0xc8 => 0x5df1, + 0xc9 => 0x5eab, 0xca => 0x5f27, 0xcb => 0x6238, 0xcc => 0x6545, + 0xcd => 0x67af, 0xce => 0x6e56, 0xcf => 0x72d0, 0xd0 => 0x7cca, + 0xd1 => 0x88b4, 0xd2 => 0x80a1, 0xd3 => 0x80e1, 0xd4 => 0x83f0, + 0xd5 => 0x864e, 0xd6 => 0x8a87, 0xd7 => 0x8de8, 0xd8 => 0x9237, + 0xd9 => 0x96c7, 0xda => 0x9867, 0xdb => 0x9f13, 0xdc => 0x4e94, + 0xdd => 0x4e92, 0xde => 0x4f0d, 0xdf => 0x5348, 0xe0 => 0x5449, + 0xe1 => 0x543e, 0xe2 => 0x5a2f, 0xe3 => 0x5f8c, 0xe4 => 0x5fa1, + 0xe5 => 0x609f, 0xe6 => 0x68a7, 0xe7 => 0x6a8e, 0xe8 => 0x745a, + 0xe9 => 0x7881, 0xea => 0x8a9e, 0xeb => 0x8aa4, 0xec => 0x8b77, + 0xed => 0x9190, 0xee => 0x4e5e, 0xef => 0x9bc9, 0xf0 => 0x4ea4, + 0xf1 => 0x4f7c, 0xf2 => 0x4faf, 0xf3 => 0x5019, 0xf4 => 0x5016, + 0xf5 => 0x5149, 0xf6 => 0x516c, 0xf7 => 0x529f, 0xf8 => 0x52b9, + 0xf9 => 0x52fe, 0xfa => 0x539a, 0xfb => 0x53e3, 0xfc => 0x5411, + }, + 0x8d => { + 0x40 => 0x540e, 0x41 => 0x5589, 0x42 => 0x5751, 0x43 => 0x57a2, + 0x44 => 0x597d, 0x45 => 0x5b54, 0x46 => 0x5b5d, 0x47 => 0x5b8f, + 0x48 => 0x5de5, 0x49 => 0x5de7, 0x4a => 0x5df7, 0x4b => 0x5e78, + 0x4c => 0x5e83, 0x4d => 0x5e9a, 0x4e => 0x5eb7, 0x4f => 0x5f18, + 0x50 => 0x6052, 0x51 => 0x614c, 0x52 => 0x6297, 0x53 => 0x62d8, + 0x54 => 0x63a7, 0x55 => 0x653b, 0x56 => 0x6602, 0x57 => 0x6643, + 0x58 => 0x66f4, 0x59 => 0x676d, 0x5a => 0x6821, 0x5b => 0x6897, + 0x5c => 0x69cb, 0x5d => 0x6c5f, 0x5e => 0x6d2a, 0x5f => 0x6d69, + 0x60 => 0x6e2f, 0x61 => 0x6e9d, 0x62 => 0x7532, 0x63 => 0x7687, + 0x64 => 0x786c, 0x65 => 0x7a3f, 0x66 => 0x7ce0, 0x67 => 0x7d05, + 0x68 => 0x7d18, 0x69 => 0x7d5e, 0x6a => 0x7db1, 0x6b => 0x8015, + 0x6c => 0x8003, 0x6d => 0x80af, 0x6e => 0x80b1, 0x6f => 0x8154, + 0x70 => 0x818f, 0x71 => 0x822a, 0x72 => 0x8352, 0x73 => 0x884c, + 0x74 => 0x8861, 0x75 => 0x8b1b, 0x76 => 0x8ca2, 0x77 => 0x8cfc, + 0x78 => 0x90ca, 0x79 => 0x9175, 0x7a => 0x9271, 0x7b => 0x783f, + 0x7c => 0x92fc, 0x7d => 0x95a4, 0x7e => 0x964d, 0x80 => 0x9805, + 0x81 => 0x9999, 0x82 => 0x9ad8, 0x83 => 0x9d3b, 0x84 => 0x525b, + 0x85 => 0x52ab, 0x86 => 0x53f7, 0x87 => 0x5408, 0x88 => 0x58d5, + 0x89 => 0x62f7, 0x8a => 0x6fe0, 0x8b => 0x8c6a, 0x8c => 0x8f5f, + 0x8d => 0x9eb9, 0x8e => 0x514b, 0x8f => 0x523b, 0x90 => 0x544a, + 0x91 => 0x56fd, 0x92 => 0x7a40, 0x93 => 0x9177, 0x94 => 0x9d60, + 0x95 => 0x9ed2, 0x96 => 0x7344, 0x97 => 0x6f09, 0x98 => 0x8170, + 0x99 => 0x7511, 0x9a => 0x5ffd, 0x9b => 0x60da, 0x9c => 0x9aa8, + 0x9d => 0x72db, 0x9e => 0x8fbc, 0x9f => 0x6b64, 0xa0 => 0x9803, + 0xa1 => 0x4eca, 0xa2 => 0x56f0, 0xa3 => 0x5764, 0xa4 => 0x58be, + 0xa5 => 0x5a5a, 0xa6 => 0x6068, 0xa7 => 0x61c7, 0xa8 => 0x660f, + 0xa9 => 0x6606, 0xaa => 0x6839, 0xab => 0x68b1, 0xac => 0x6df7, + 0xad => 0x75d5, 0xae => 0x7d3a, 0xaf => 0x826e, 0xb0 => 0x9b42, + 0xb1 => 0x4e9b, 0xb2 => 0x4f50, 0xb3 => 0x53c9, 0xb4 => 0x5506, + 0xb5 => 0x5d6f, 0xb6 => 0x5de6, 0xb7 => 0x5dee, 0xb8 => 0x67fb, + 0xb9 => 0x6c99, 0xba => 0x7473, 0xbb => 0x7802, 0xbc => 0x8a50, + 0xbd => 0x9396, 0xbe => 0x88df, 0xbf => 0x5750, 0xc0 => 0x5ea7, + 0xc1 => 0x632b, 0xc2 => 0x50b5, 0xc3 => 0x50ac, 0xc4 => 0x518d, + 0xc5 => 0x6700, 0xc6 => 0x54c9, 0xc7 => 0x585e, 0xc8 => 0x59bb, + 0xc9 => 0x5bb0, 0xca => 0x5f69, 0xcb => 0x624d, 0xcc => 0x63a1, + 0xcd => 0x683d, 0xce => 0x6b73, 0xcf => 0x6e08, 0xd0 => 0x707d, + 0xd1 => 0x91c7, 0xd2 => 0x7280, 0xd3 => 0x7815, 0xd4 => 0x7826, + 0xd5 => 0x796d, 0xd6 => 0x658e, 0xd7 => 0x7d30, 0xd8 => 0x83dc, + 0xd9 => 0x88c1, 0xda => 0x8f09, 0xdb => 0x969b, 0xdc => 0x5264, + 0xdd => 0x5728, 0xde => 0x6750, 0xdf => 0x7f6a, 0xe0 => 0x8ca1, + 0xe1 => 0x51b4, 0xe2 => 0x5742, 0xe3 => 0x962a, 0xe4 => 0x583a, + 0xe5 => 0x698a, 0xe6 => 0x80b4, 0xe7 => 0x54b2, 0xe8 => 0x5d0e, + 0xe9 => 0x57fc, 0xea => 0x7895, 0xeb => 0x9dfa, 0xec => 0x4f5c, + 0xed => 0x524a, 0xee => 0x548b, 0xef => 0x643e, 0xf0 => 0x6628, + 0xf1 => 0x6714, 0xf2 => 0x67f5, 0xf3 => 0x7a84, 0xf4 => 0x7b56, + 0xf5 => 0x7d22, 0xf6 => 0x932f, 0xf7 => 0x685c, 0xf8 => 0x9bad, + 0xf9 => 0x7b39, 0xfa => 0x5319, 0xfb => 0x518a, 0xfc => 0x5237, + }, + 0x8e => { + 0x40 => 0x5bdf, 0x41 => 0x62f6, 0x42 => 0x64ae, 0x43 => 0x64e6, + 0x44 => 0x672d, 0x45 => 0x6bba, 0x46 => 0x85a9, 0x47 => 0x96d1, + 0x48 => 0x7690, 0x49 => 0x9bd6, 0x4a => 0x634c, 0x4b => 0x9306, + 0x4c => 0x9bab, 0x4d => 0x76bf, 0x4e => 0x6652, 0x4f => 0x4e09, + 0x50 => 0x5098, 0x51 => 0x53c2, 0x52 => 0x5c71, 0x53 => 0x60e8, + 0x54 => 0x6492, 0x55 => 0x6563, 0x56 => 0x685f, 0x57 => 0x71e6, + 0x58 => 0x73ca, 0x59 => 0x7523, 0x5a => 0x7b97, 0x5b => 0x7e82, + 0x5c => 0x8695, 0x5d => 0x8b83, 0x5e => 0x8cdb, 0x5f => 0x9178, + 0x60 => 0x9910, 0x61 => 0x65ac, 0x62 => 0x66ab, 0x63 => 0x6b8b, + 0x64 => 0x4ed5, 0x65 => 0x4ed4, 0x66 => 0x4f3a, 0x67 => 0x4f7f, + 0x68 => 0x523a, 0x69 => 0x53f8, 0x6a => 0x53f2, 0x6b => 0x55e3, + 0x6c => 0x56db, 0x6d => 0x58eb, 0x6e => 0x59cb, 0x6f => 0x59c9, + 0x70 => 0x59ff, 0x71 => 0x5b50, 0x72 => 0x5c4d, 0x73 => 0x5e02, + 0x74 => 0x5e2b, 0x75 => 0x5fd7, 0x76 => 0x601d, 0x77 => 0x6307, + 0x78 => 0x652f, 0x79 => 0x5b5c, 0x7a => 0x65af, 0x7b => 0x65bd, + 0x7c => 0x65e8, 0x7d => 0x679d, 0x7e => 0x6b62, 0x80 => 0x6b7b, + 0x81 => 0x6c0f, 0x82 => 0x7345, 0x83 => 0x7949, 0x84 => 0x79c1, + 0x85 => 0x7cf8, 0x86 => 0x7d19, 0x87 => 0x7d2b, 0x88 => 0x80a2, + 0x89 => 0x8102, 0x8a => 0x81f3, 0x8b => 0x8996, 0x8c => 0x8a5e, + 0x8d => 0x8a69, 0x8e => 0x8a66, 0x8f => 0x8a8c, 0x90 => 0x8aee, + 0x91 => 0x8cc7, 0x92 => 0x8cdc, 0x93 => 0x96cc, 0x94 => 0x98fc, + 0x95 => 0x6b6f, 0x96 => 0x4e8b, 0x97 => 0x4f3c, 0x98 => 0x4f8d, + 0x99 => 0x5150, 0x9a => 0x5b57, 0x9b => 0x5bfa, 0x9c => 0x6148, + 0x9d => 0x6301, 0x9e => 0x6642, 0x9f => 0x6b21, 0xa0 => 0x6ecb, + 0xa1 => 0x6cbb, 0xa2 => 0x723e, 0xa3 => 0x74bd, 0xa4 => 0x75d4, + 0xa5 => 0x78c1, 0xa6 => 0x793a, 0xa7 => 0x800c, 0xa8 => 0x8033, + 0xa9 => 0x81ea, 0xaa => 0x8494, 0xab => 0x8f9e, 0xac => 0x6c50, + 0xad => 0x9e7f, 0xae => 0x5f0f, 0xaf => 0x8b58, 0xb0 => 0x9d2b, + 0xb1 => 0x7afa, 0xb2 => 0x8ef8, 0xb3 => 0x5b8d, 0xb4 => 0x96eb, + 0xb5 => 0x4e03, 0xb6 => 0x53f1, 0xb7 => 0x57f7, 0xb8 => 0x5931, + 0xb9 => 0x5ac9, 0xba => 0x5ba4, 0xbb => 0x6089, 0xbc => 0x6e7f, + 0xbd => 0x6f06, 0xbe => 0x75be, 0xbf => 0x8cea, 0xc0 => 0x5b9f, + 0xc1 => 0x8500, 0xc2 => 0x7be0, 0xc3 => 0x5072, 0xc4 => 0x67f4, + 0xc5 => 0x829d, 0xc6 => 0x5c61, 0xc7 => 0x854a, 0xc8 => 0x7e1e, + 0xc9 => 0x820e, 0xca => 0x5199, 0xcb => 0x5c04, 0xcc => 0x6368, + 0xcd => 0x8d66, 0xce => 0x659c, 0xcf => 0x716e, 0xd0 => 0x793e, + 0xd1 => 0x7d17, 0xd2 => 0x8005, 0xd3 => 0x8b1d, 0xd4 => 0x8eca, + 0xd5 => 0x906e, 0xd6 => 0x86c7, 0xd7 => 0x90aa, 0xd8 => 0x501f, + 0xd9 => 0x52fa, 0xda => 0x5c3a, 0xdb => 0x6753, 0xdc => 0x707c, + 0xdd => 0x7235, 0xde => 0x914c, 0xdf => 0x91c8, 0xe0 => 0x932b, + 0xe1 => 0x82e5, 0xe2 => 0x5bc2, 0xe3 => 0x5f31, 0xe4 => 0x60f9, + 0xe5 => 0x4e3b, 0xe6 => 0x53d6, 0xe7 => 0x5b88, 0xe8 => 0x624b, + 0xe9 => 0x6731, 0xea => 0x6b8a, 0xeb => 0x72e9, 0xec => 0x73e0, + 0xed => 0x7a2e, 0xee => 0x816b, 0xef => 0x8da3, 0xf0 => 0x9152, + 0xf1 => 0x9996, 0xf2 => 0x5112, 0xf3 => 0x53d7, 0xf4 => 0x546a, + 0xf5 => 0x5bff, 0xf6 => 0x6388, 0xf7 => 0x6a39, 0xf8 => 0x7dac, + 0xf9 => 0x9700, 0xfa => 0x56da, 0xfb => 0x53ce, 0xfc => 0x5468, + }, + 0x8f => { + 0x40 => 0x5b97, 0x41 => 0x5c31, 0x42 => 0x5dde, 0x43 => 0x4fee, + 0x44 => 0x6101, 0x45 => 0x62fe, 0x46 => 0x6d32, 0x47 => 0x79c0, + 0x48 => 0x79cb, 0x49 => 0x7d42, 0x4a => 0x7e4d, 0x4b => 0x7fd2, + 0x4c => 0x81ed, 0x4d => 0x821f, 0x4e => 0x8490, 0x4f => 0x8846, + 0x50 => 0x8972, 0x51 => 0x8b90, 0x52 => 0x8e74, 0x53 => 0x8f2f, + 0x54 => 0x9031, 0x55 => 0x914b, 0x56 => 0x916c, 0x57 => 0x96c6, + 0x58 => 0x919c, 0x59 => 0x4ec0, 0x5a => 0x4f4f, 0x5b => 0x5145, + 0x5c => 0x5341, 0x5d => 0x5f93, 0x5e => 0x620e, 0x5f => 0x67d4, + 0x60 => 0x6c41, 0x61 => 0x6e0b, 0x62 => 0x7363, 0x63 => 0x7e26, + 0x64 => 0x91cd, 0x65 => 0x9283, 0x66 => 0x53d4, 0x67 => 0x5919, + 0x68 => 0x5bbf, 0x69 => 0x6dd1, 0x6a => 0x795d, 0x6b => 0x7e2e, + 0x6c => 0x7c9b, 0x6d => 0x587e, 0x6e => 0x719f, 0x6f => 0x51fa, + 0x70 => 0x8853, 0x71 => 0x8ff0, 0x72 => 0x4fca, 0x73 => 0x5cfb, + 0x74 => 0x6625, 0x75 => 0x77ac, 0x76 => 0x7ae3, 0x77 => 0x821c, + 0x78 => 0x99ff, 0x79 => 0x51c6, 0x7a => 0x5faa, 0x7b => 0x65ec, + 0x7c => 0x696f, 0x7d => 0x6b89, 0x7e => 0x6df3, 0x80 => 0x6e96, + 0x81 => 0x6f64, 0x82 => 0x76fe, 0x83 => 0x7d14, 0x84 => 0x5de1, + 0x85 => 0x9075, 0x86 => 0x9187, 0x87 => 0x9806, 0x88 => 0x51e6, + 0x89 => 0x521d, 0x8a => 0x6240, 0x8b => 0x6691, 0x8c => 0x66d9, + 0x8d => 0x6e1a, 0x8e => 0x5eb6, 0x8f => 0x7dd2, 0x90 => 0x7f72, + 0x91 => 0x66f8, 0x92 => 0x85af, 0x93 => 0x85f7, 0x94 => 0x8af8, + 0x95 => 0x52a9, 0x96 => 0x53d9, 0x97 => 0x5973, 0x98 => 0x5e8f, + 0x99 => 0x5f90, 0x9a => 0x6055, 0x9b => 0x92e4, 0x9c => 0x9664, + 0x9d => 0x50b7, 0x9e => 0x511f, 0x9f => 0x52dd, 0xa0 => 0x5320, + 0xa1 => 0x5347, 0xa2 => 0x53ec, 0xa3 => 0x54e8, 0xa4 => 0x5546, + 0xa5 => 0x5531, 0xa6 => 0x5617, 0xa7 => 0x5968, 0xa8 => 0x59be, + 0xa9 => 0x5a3c, 0xaa => 0x5bb5, 0xab => 0x5c06, 0xac => 0x5c0f, + 0xad => 0x5c11, 0xae => 0x5c1a, 0xaf => 0x5e84, 0xb0 => 0x5e8a, + 0xb1 => 0x5ee0, 0xb2 => 0x5f70, 0xb3 => 0x627f, 0xb4 => 0x6284, + 0xb5 => 0x62db, 0xb6 => 0x638c, 0xb7 => 0x6377, 0xb8 => 0x6607, + 0xb9 => 0x660c, 0xba => 0x662d, 0xbb => 0x6676, 0xbc => 0x677e, + 0xbd => 0x68a2, 0xbe => 0x6a1f, 0xbf => 0x6a35, 0xc0 => 0x6cbc, + 0xc1 => 0x6d88, 0xc2 => 0x6e09, 0xc3 => 0x6e58, 0xc4 => 0x713c, + 0xc5 => 0x7126, 0xc6 => 0x7167, 0xc7 => 0x75c7, 0xc8 => 0x7701, + 0xc9 => 0x785d, 0xca => 0x7901, 0xcb => 0x7965, 0xcc => 0x79f0, + 0xcd => 0x7ae0, 0xce => 0x7b11, 0xcf => 0x7ca7, 0xd0 => 0x7d39, + 0xd1 => 0x8096, 0xd2 => 0x83d6, 0xd3 => 0x848b, 0xd4 => 0x8549, + 0xd5 => 0x885d, 0xd6 => 0x88f3, 0xd7 => 0x8a1f, 0xd8 => 0x8a3c, + 0xd9 => 0x8a54, 0xda => 0x8a73, 0xdb => 0x8c61, 0xdc => 0x8cde, + 0xdd => 0x91a4, 0xde => 0x9266, 0xdf => 0x937e, 0xe0 => 0x9418, + 0xe1 => 0x969c, 0xe2 => 0x9798, 0xe3 => 0x4e0a, 0xe4 => 0x4e08, + 0xe5 => 0x4e1e, 0xe6 => 0x4e57, 0xe7 => 0x5197, 0xe8 => 0x5270, + 0xe9 => 0x57ce, 0xea => 0x5834, 0xeb => 0x58cc, 0xec => 0x5b22, + 0xed => 0x5e38, 0xee => 0x60c5, 0xef => 0x64fe, 0xf0 => 0x6761, + 0xf1 => 0x6756, 0xf2 => 0x6d44, 0xf3 => 0x72b6, 0xf4 => 0x7573, + 0xf5 => 0x7a63, 0xf6 => 0x84b8, 0xf7 => 0x8b72, 0xf8 => 0x91b8, + 0xf9 => 0x9320, 0xfa => 0x5631, 0xfb => 0x57f4, 0xfc => 0x98fe, + }, + 0x90 => { + 0x40 => 0x62ed, 0x41 => 0x690d, 0x42 => 0x6b96, 0x43 => 0x71ed, + 0x44 => 0x7e54, 0x45 => 0x8077, 0x46 => 0x8272, 0x47 => 0x89e6, + 0x48 => 0x98df, 0x49 => 0x8755, 0x4a => 0x8fb1, 0x4b => 0x5c3b, + 0x4c => 0x4f38, 0x4d => 0x4fe1, 0x4e => 0x4fb5, 0x4f => 0x5507, + 0x50 => 0x5a20, 0x51 => 0x5bdd, 0x52 => 0x5be9, 0x53 => 0x5fc3, + 0x54 => 0x614e, 0x55 => 0x632f, 0x56 => 0x65b0, 0x57 => 0x664b, + 0x58 => 0x68ee, 0x59 => 0x699b, 0x5a => 0x6d78, 0x5b => 0x6df1, + 0x5c => 0x7533, 0x5d => 0x75b9, 0x5e => 0x771f, 0x5f => 0x795e, + 0x60 => 0x79e6, 0x61 => 0x7d33, 0x62 => 0x81e3, 0x63 => 0x82af, + 0x64 => 0x85aa, 0x65 => 0x89aa, 0x66 => 0x8a3a, 0x67 => 0x8eab, + 0x68 => 0x8f9b, 0x69 => 0x9032, 0x6a => 0x91dd, 0x6b => 0x9707, + 0x6c => 0x4eba, 0x6d => 0x4ec1, 0x6e => 0x5203, 0x6f => 0x5875, + 0x70 => 0x58ec, 0x71 => 0x5c0b, 0x72 => 0x751a, 0x73 => 0x5c3d, + 0x74 => 0x814e, 0x75 => 0x8a0a, 0x76 => 0x8fc5, 0x77 => 0x9663, + 0x78 => 0x976d, 0x79 => 0x7b25, 0x7a => 0x8acf, 0x7b => 0x9808, + 0x7c => 0x9162, 0x7d => 0x56f3, 0x7e => 0x53a8, 0x80 => 0x9017, + 0x81 => 0x5439, 0x82 => 0x5782, 0x83 => 0x5e25, 0x84 => 0x63a8, + 0x85 => 0x6c34, 0x86 => 0x708a, 0x87 => 0x7761, 0x88 => 0x7c8b, + 0x89 => 0x7fe0, 0x8a => 0x8870, 0x8b => 0x9042, 0x8c => 0x9154, + 0x8d => 0x9310, 0x8e => 0x9318, 0x8f => 0x968f, 0x90 => 0x745e, + 0x91 => 0x9ac4, 0x92 => 0x5d07, 0x93 => 0x5d69, 0x94 => 0x6570, + 0x95 => 0x67a2, 0x96 => 0x8da8, 0x97 => 0x96db, 0x98 => 0x636e, + 0x99 => 0x6749, 0x9a => 0x6919, 0x9b => 0x83c5, 0x9c => 0x9817, + 0x9d => 0x96c0, 0x9e => 0x88fe, 0x9f => 0x6f84, 0xa0 => 0x647a, + 0xa1 => 0x5bf8, 0xa2 => 0x4e16, 0xa3 => 0x702c, 0xa4 => 0x755d, + 0xa5 => 0x662f, 0xa6 => 0x51c4, 0xa7 => 0x5236, 0xa8 => 0x52e2, + 0xa9 => 0x59d3, 0xaa => 0x5f81, 0xab => 0x6027, 0xac => 0x6210, + 0xad => 0x653f, 0xae => 0x6574, 0xaf => 0x661f, 0xb0 => 0x6674, + 0xb1 => 0x68f2, 0xb2 => 0x6816, 0xb3 => 0x6b63, 0xb4 => 0x6e05, + 0xb5 => 0x7272, 0xb6 => 0x751f, 0xb7 => 0x76db, 0xb8 => 0x7cbe, + 0xb9 => 0x8056, 0xba => 0x58f0, 0xbb => 0x88fd, 0xbc => 0x897f, + 0xbd => 0x8aa0, 0xbe => 0x8a93, 0xbf => 0x8acb, 0xc0 => 0x901d, + 0xc1 => 0x9192, 0xc2 => 0x9752, 0xc3 => 0x9759, 0xc4 => 0x6589, + 0xc5 => 0x7a0e, 0xc6 => 0x8106, 0xc7 => 0x96bb, 0xc8 => 0x5e2d, + 0xc9 => 0x60dc, 0xca => 0x621a, 0xcb => 0x65a5, 0xcc => 0x6614, + 0xcd => 0x6790, 0xce => 0x77f3, 0xcf => 0x7a4d, 0xd0 => 0x7c4d, + 0xd1 => 0x7e3e, 0xd2 => 0x810a, 0xd3 => 0x8cac, 0xd4 => 0x8d64, + 0xd5 => 0x8de1, 0xd6 => 0x8e5f, 0xd7 => 0x78a9, 0xd8 => 0x5207, + 0xd9 => 0x62d9, 0xda => 0x63a5, 0xdb => 0x6442, 0xdc => 0x6298, + 0xdd => 0x8a2d, 0xde => 0x7a83, 0xdf => 0x7bc0, 0xe0 => 0x8aac, + 0xe1 => 0x96ea, 0xe2 => 0x7d76, 0xe3 => 0x820c, 0xe4 => 0x8749, + 0xe5 => 0x4ed9, 0xe6 => 0x5148, 0xe7 => 0x5343, 0xe8 => 0x5360, + 0xe9 => 0x5ba3, 0xea => 0x5c02, 0xeb => 0x5c16, 0xec => 0x5ddd, + 0xed => 0x6226, 0xee => 0x6247, 0xef => 0x64b0, 0xf0 => 0x6813, + 0xf1 => 0x6834, 0xf2 => 0x6cc9, 0xf3 => 0x6d45, 0xf4 => 0x6d17, + 0xf5 => 0x67d3, 0xf6 => 0x6f5c, 0xf7 => 0x714e, 0xf8 => 0x717d, + 0xf9 => 0x65cb, 0xfa => 0x7a7f, 0xfb => 0x7bad, 0xfc => 0x7dda, + }, + 0x91 => { + 0x40 => 0x7e4a, 0x41 => 0x7fa8, 0x42 => 0x817a, 0x43 => 0x821b, + 0x44 => 0x8239, 0x45 => 0x85a6, 0x46 => 0x8a6e, 0x47 => 0x8cce, + 0x48 => 0x8df5, 0x49 => 0x9078, 0x4a => 0x9077, 0x4b => 0x92ad, + 0x4c => 0x9291, 0x4d => 0x9583, 0x4e => 0x9bae, 0x4f => 0x524d, + 0x50 => 0x5584, 0x51 => 0x6f38, 0x52 => 0x7136, 0x53 => 0x5168, + 0x54 => 0x7985, 0x55 => 0x7e55, 0x56 => 0x81b3, 0x57 => 0x7cce, + 0x58 => 0x564c, 0x59 => 0x5851, 0x5a => 0x5ca8, 0x5b => 0x63aa, + 0x5c => 0x66fe, 0x5d => 0x66fd, 0x5e => 0x695a, 0x5f => 0x72d9, + 0x60 => 0x758f, 0x61 => 0x758e, 0x62 => 0x790e, 0x63 => 0x7956, + 0x64 => 0x79df, 0x65 => 0x7c97, 0x66 => 0x7d20, 0x67 => 0x7d44, + 0x68 => 0x8607, 0x69 => 0x8a34, 0x6a => 0x963b, 0x6b => 0x9061, + 0x6c => 0x9f20, 0x6d => 0x50e7, 0x6e => 0x5275, 0x6f => 0x53cc, + 0x70 => 0x53e2, 0x71 => 0x5009, 0x72 => 0x55aa, 0x73 => 0x58ee, + 0x74 => 0x594f, 0x75 => 0x723d, 0x76 => 0x5b8b, 0x77 => 0x5c64, + 0x78 => 0x531d, 0x79 => 0x60e3, 0x7a => 0x60f3, 0x7b => 0x635c, + 0x7c => 0x6383, 0x7d => 0x633f, 0x7e => 0x63bb, 0x80 => 0x64cd, + 0x81 => 0x65e9, 0x82 => 0x66f9, 0x83 => 0x5de3, 0x84 => 0x69cd, + 0x85 => 0x69fd, 0x86 => 0x6f15, 0x87 => 0x71e5, 0x88 => 0x4e89, + 0x89 => 0x75e9, 0x8a => 0x76f8, 0x8b => 0x7a93, 0x8c => 0x7cdf, + 0x8d => 0x7dcf, 0x8e => 0x7d9c, 0x8f => 0x8061, 0x90 => 0x8349, + 0x91 => 0x8358, 0x92 => 0x846c, 0x93 => 0x84bc, 0x94 => 0x85fb, + 0x95 => 0x88c5, 0x96 => 0x8d70, 0x97 => 0x9001, 0x98 => 0x906d, + 0x99 => 0x9397, 0x9a => 0x971c, 0x9b => 0x9a12, 0x9c => 0x50cf, + 0x9d => 0x5897, 0x9e => 0x618e, 0x9f => 0x81d3, 0xa0 => 0x8535, + 0xa1 => 0x8d08, 0xa2 => 0x9020, 0xa3 => 0x4fc3, 0xa4 => 0x5074, + 0xa5 => 0x5247, 0xa6 => 0x5373, 0xa7 => 0x606f, 0xa8 => 0x6349, + 0xa9 => 0x675f, 0xaa => 0x6e2c, 0xab => 0x8db3, 0xac => 0x901f, + 0xad => 0x4fd7, 0xae => 0x5c5e, 0xaf => 0x8cca, 0xb0 => 0x65cf, + 0xb1 => 0x7d9a, 0xb2 => 0x5352, 0xb3 => 0x8896, 0xb4 => 0x5176, + 0xb5 => 0x63c3, 0xb6 => 0x5b58, 0xb7 => 0x5b6b, 0xb8 => 0x5c0a, + 0xb9 => 0x640d, 0xba => 0x6751, 0xbb => 0x905c, 0xbc => 0x4ed6, + 0xbd => 0x591a, 0xbe => 0x592a, 0xbf => 0x6c70, 0xc0 => 0x8a51, + 0xc1 => 0x553e, 0xc2 => 0x5815, 0xc3 => 0x59a5, 0xc4 => 0x60f0, + 0xc5 => 0x6253, 0xc6 => 0x67c1, 0xc7 => 0x8235, 0xc8 => 0x6955, + 0xc9 => 0x9640, 0xca => 0x99c4, 0xcb => 0x9a28, 0xcc => 0x4f53, + 0xcd => 0x5806, 0xce => 0x5bfe, 0xcf => 0x8010, 0xd0 => 0x5cb1, + 0xd1 => 0x5e2f, 0xd2 => 0x5f85, 0xd3 => 0x6020, 0xd4 => 0x614b, + 0xd5 => 0x6234, 0xd6 => 0x66ff, 0xd7 => 0x6cf0, 0xd8 => 0x6ede, + 0xd9 => 0x80ce, 0xda => 0x817f, 0xdb => 0x82d4, 0xdc => 0x888b, + 0xdd => 0x8cb8, 0xde => 0x9000, 0xdf => 0x902e, 0xe0 => 0x968a, + 0xe1 => 0x9edb, 0xe2 => 0x9bdb, 0xe3 => 0x4ee3, 0xe4 => 0x53f0, + 0xe5 => 0x5927, 0xe6 => 0x7b2c, 0xe7 => 0x918d, 0xe8 => 0x984c, + 0xe9 => 0x9df9, 0xea => 0x6edd, 0xeb => 0x7027, 0xec => 0x5353, + 0xed => 0x5544, 0xee => 0x5b85, 0xef => 0x6258, 0xf0 => 0x629e, + 0xf1 => 0x62d3, 0xf2 => 0x6ca2, 0xf3 => 0x6fef, 0xf4 => 0x7422, + 0xf5 => 0x8a17, 0xf6 => 0x9438, 0xf7 => 0x6fc1, 0xf8 => 0x8afe, + 0xf9 => 0x8338, 0xfa => 0x51e7, 0xfb => 0x86f8, 0xfc => 0x53ea, + }, + 0x92 => { + 0x40 => 0x53e9, 0x41 => 0x4f46, 0x42 => 0x9054, 0x43 => 0x8fb0, + 0x44 => 0x596a, 0x45 => 0x8131, 0x46 => 0x5dfd, 0x47 => 0x7aea, + 0x48 => 0x8fbf, 0x49 => 0x68da, 0x4a => 0x8c37, 0x4b => 0x72f8, + 0x4c => 0x9c48, 0x4d => 0x6a3d, 0x4e => 0x8ab0, 0x4f => 0x4e39, + 0x50 => 0x5358, 0x51 => 0x5606, 0x52 => 0x5766, 0x53 => 0x62c5, + 0x54 => 0x63a2, 0x55 => 0x65e6, 0x56 => 0x6b4e, 0x57 => 0x6de1, + 0x58 => 0x6e5b, 0x59 => 0x70ad, 0x5a => 0x77ed, 0x5b => 0x7aef, + 0x5c => 0x7baa, 0x5d => 0x7dbb, 0x5e => 0x803d, 0x5f => 0x80c6, + 0x60 => 0x86cb, 0x61 => 0x8a95, 0x62 => 0x935b, 0x63 => 0x56e3, + 0x64 => 0x58c7, 0x65 => 0x5f3e, 0x66 => 0x65ad, 0x67 => 0x6696, + 0x68 => 0x6a80, 0x69 => 0x6bb5, 0x6a => 0x7537, 0x6b => 0x8ac7, + 0x6c => 0x5024, 0x6d => 0x77e5, 0x6e => 0x5730, 0x6f => 0x5f1b, + 0x70 => 0x6065, 0x71 => 0x667a, 0x72 => 0x6c60, 0x73 => 0x75f4, + 0x74 => 0x7a1a, 0x75 => 0x7f6e, 0x76 => 0x81f4, 0x77 => 0x8718, + 0x78 => 0x9045, 0x79 => 0x99b3, 0x7a => 0x7bc9, 0x7b => 0x755c, + 0x7c => 0x7af9, 0x7d => 0x7b51, 0x7e => 0x84c4, 0x80 => 0x9010, + 0x81 => 0x79e9, 0x82 => 0x7a92, 0x83 => 0x8336, 0x84 => 0x5ae1, + 0x85 => 0x7740, 0x86 => 0x4e2d, 0x87 => 0x4ef2, 0x88 => 0x5b99, + 0x89 => 0x5fe0, 0x8a => 0x62bd, 0x8b => 0x663c, 0x8c => 0x67f1, + 0x8d => 0x6ce8, 0x8e => 0x866b, 0x8f => 0x8877, 0x90 => 0x8a3b, + 0x91 => 0x914e, 0x92 => 0x92f3, 0x93 => 0x99d0, 0x94 => 0x6a17, + 0x95 => 0x7026, 0x96 => 0x732a, 0x97 => 0x82e7, 0x98 => 0x8457, + 0x99 => 0x8caf, 0x9a => 0x4e01, 0x9b => 0x5146, 0x9c => 0x51cb, + 0x9d => 0x558b, 0x9e => 0x5bf5, 0x9f => 0x5e16, 0xa0 => 0x5e33, + 0xa1 => 0x5e81, 0xa2 => 0x5f14, 0xa3 => 0x5f35, 0xa4 => 0x5f6b, + 0xa5 => 0x5fb4, 0xa6 => 0x61f2, 0xa7 => 0x6311, 0xa8 => 0x66a2, + 0xa9 => 0x671d, 0xaa => 0x6f6e, 0xab => 0x7252, 0xac => 0x753a, + 0xad => 0x773a, 0xae => 0x8074, 0xaf => 0x8139, 0xb0 => 0x8178, + 0xb1 => 0x8776, 0xb2 => 0x8abf, 0xb3 => 0x8adc, 0xb4 => 0x8d85, + 0xb5 => 0x8df3, 0xb6 => 0x929a, 0xb7 => 0x9577, 0xb8 => 0x9802, + 0xb9 => 0x9ce5, 0xba => 0x52c5, 0xbb => 0x6357, 0xbc => 0x76f4, + 0xbd => 0x6715, 0xbe => 0x6c88, 0xbf => 0x73cd, 0xc0 => 0x8cc3, + 0xc1 => 0x93ae, 0xc2 => 0x9673, 0xc3 => 0x6d25, 0xc4 => 0x589c, + 0xc5 => 0x690e, 0xc6 => 0x69cc, 0xc7 => 0x8ffd, 0xc8 => 0x939a, + 0xc9 => 0x75db, 0xca => 0x901a, 0xcb => 0x585a, 0xcc => 0x6802, + 0xcd => 0x63b4, 0xce => 0x69fb, 0xcf => 0x4f43, 0xd0 => 0x6f2c, + 0xd1 => 0x67d8, 0xd2 => 0x8fbb, 0xd3 => 0x8526, 0xd4 => 0x7db4, + 0xd5 => 0x9354, 0xd6 => 0x693f, 0xd7 => 0x6f70, 0xd8 => 0x576a, + 0xd9 => 0x58f7, 0xda => 0x5b2c, 0xdb => 0x7d2c, 0xdc => 0x722a, + 0xdd => 0x540a, 0xde => 0x91e3, 0xdf => 0x9db4, 0xe0 => 0x4ead, + 0xe1 => 0x4f4e, 0xe2 => 0x505c, 0xe3 => 0x5075, 0xe4 => 0x5243, + 0xe5 => 0x8c9e, 0xe6 => 0x5448, 0xe7 => 0x5824, 0xe8 => 0x5b9a, + 0xe9 => 0x5e1d, 0xea => 0x5e95, 0xeb => 0x5ead, 0xec => 0x5ef7, + 0xed => 0x5f1f, 0xee => 0x608c, 0xef => 0x62b5, 0xf0 => 0x633a, + 0xf1 => 0x63d0, 0xf2 => 0x68af, 0xf3 => 0x6c40, 0xf4 => 0x7887, + 0xf5 => 0x798e, 0xf6 => 0x7a0b, 0xf7 => 0x7de0, 0xf8 => 0x8247, + 0xf9 => 0x8a02, 0xfa => 0x8ae6, 0xfb => 0x8e44, 0xfc => 0x9013, + }, + 0x93 => { + 0x40 => 0x90b8, 0x41 => 0x912d, 0x42 => 0x91d8, 0x43 => 0x9f0e, + 0x44 => 0x6ce5, 0x45 => 0x6458, 0x46 => 0x64e2, 0x47 => 0x6575, + 0x48 => 0x6ef4, 0x49 => 0x7684, 0x4a => 0x7b1b, 0x4b => 0x9069, + 0x4c => 0x93d1, 0x4d => 0x6eba, 0x4e => 0x54f2, 0x4f => 0x5fb9, + 0x50 => 0x64a4, 0x51 => 0x8f4d, 0x52 => 0x8fed, 0x53 => 0x9244, + 0x54 => 0x5178, 0x55 => 0x586b, 0x56 => 0x5929, 0x57 => 0x5c55, + 0x58 => 0x5e97, 0x59 => 0x6dfb, 0x5a => 0x7e8f, 0x5b => 0x751c, + 0x5c => 0x8cbc, 0x5d => 0x8ee2, 0x5e => 0x985b, 0x5f => 0x70b9, + 0x60 => 0x4f1d, 0x61 => 0x6bbf, 0x62 => 0x6fb1, 0x63 => 0x7530, + 0x64 => 0x96fb, 0x65 => 0x514e, 0x66 => 0x5410, 0x67 => 0x5835, + 0x68 => 0x5857, 0x69 => 0x59ac, 0x6a => 0x5c60, 0x6b => 0x5f92, + 0x6c => 0x6597, 0x6d => 0x675c, 0x6e => 0x6e21, 0x6f => 0x767b, + 0x70 => 0x83df, 0x71 => 0x8ced, 0x72 => 0x9014, 0x73 => 0x90fd, + 0x74 => 0x934d, 0x75 => 0x7825, 0x76 => 0x783a, 0x77 => 0x52aa, + 0x78 => 0x5ea6, 0x79 => 0x571f, 0x7a => 0x5974, 0x7b => 0x6012, + 0x7c => 0x5012, 0x7d => 0x515a, 0x7e => 0x51ac, 0x80 => 0x51cd, + 0x81 => 0x5200, 0x82 => 0x5510, 0x83 => 0x5854, 0x84 => 0x5858, + 0x85 => 0x5957, 0x86 => 0x5b95, 0x87 => 0x5cf6, 0x88 => 0x5d8b, + 0x89 => 0x60bc, 0x8a => 0x6295, 0x8b => 0x642d, 0x8c => 0x6771, + 0x8d => 0x6843, 0x8e => 0x68bc, 0x8f => 0x68df, 0x90 => 0x76d7, + 0x91 => 0x6dd8, 0x92 => 0x6e6f, 0x93 => 0x6d9b, 0x94 => 0x706f, + 0x95 => 0x71c8, 0x96 => 0x5f53, 0x97 => 0x75d8, 0x98 => 0x7977, + 0x99 => 0x7b49, 0x9a => 0x7b54, 0x9b => 0x7b52, 0x9c => 0x7cd6, + 0x9d => 0x7d71, 0x9e => 0x5230, 0x9f => 0x8463, 0xa0 => 0x8569, + 0xa1 => 0x85e4, 0xa2 => 0x8a0e, 0xa3 => 0x8b04, 0xa4 => 0x8c46, + 0xa5 => 0x8e0f, 0xa6 => 0x9003, 0xa7 => 0x900f, 0xa8 => 0x9419, + 0xa9 => 0x9676, 0xaa => 0x982d, 0xab => 0x9a30, 0xac => 0x95d8, + 0xad => 0x50cd, 0xae => 0x52d5, 0xaf => 0x540c, 0xb0 => 0x5802, + 0xb1 => 0x5c0e, 0xb2 => 0x61a7, 0xb3 => 0x649e, 0xb4 => 0x6d1e, + 0xb5 => 0x77b3, 0xb6 => 0x7ae5, 0xb7 => 0x80f4, 0xb8 => 0x8404, + 0xb9 => 0x9053, 0xba => 0x9285, 0xbb => 0x5ce0, 0xbc => 0x9d07, + 0xbd => 0x533f, 0xbe => 0x5f97, 0xbf => 0x5fb3, 0xc0 => 0x6d9c, + 0xc1 => 0x7279, 0xc2 => 0x7763, 0xc3 => 0x79bf, 0xc4 => 0x7be4, + 0xc5 => 0x6bd2, 0xc6 => 0x72ec, 0xc7 => 0x8aad, 0xc8 => 0x6803, + 0xc9 => 0x6a61, 0xca => 0x51f8, 0xcb => 0x7a81, 0xcc => 0x6934, + 0xcd => 0x5c4a, 0xce => 0x9cf6, 0xcf => 0x82eb, 0xd0 => 0x5bc5, + 0xd1 => 0x9149, 0xd2 => 0x701e, 0xd3 => 0x5678, 0xd4 => 0x5c6f, + 0xd5 => 0x60c7, 0xd6 => 0x6566, 0xd7 => 0x6c8c, 0xd8 => 0x8c5a, + 0xd9 => 0x9041, 0xda => 0x9813, 0xdb => 0x5451, 0xdc => 0x66c7, + 0xdd => 0x920d, 0xde => 0x5948, 0xdf => 0x90a3, 0xe0 => 0x5185, + 0xe1 => 0x4e4d, 0xe2 => 0x51ea, 0xe3 => 0x8599, 0xe4 => 0x8b0e, + 0xe5 => 0x7058, 0xe6 => 0x637a, 0xe7 => 0x934b, 0xe8 => 0x6962, + 0xe9 => 0x99b4, 0xea => 0x7e04, 0xeb => 0x7577, 0xec => 0x5357, + 0xed => 0x6960, 0xee => 0x8edf, 0xef => 0x96e3, 0xf0 => 0x6c5d, + 0xf1 => 0x4e8c, 0xf2 => 0x5c3c, 0xf3 => 0x5f10, 0xf4 => 0x8fe9, + 0xf5 => 0x5302, 0xf6 => 0x8cd1, 0xf7 => 0x8089, 0xf8 => 0x8679, + 0xf9 => 0x5eff, 0xfa => 0x65e5, 0xfb => 0x4e73, 0xfc => 0x5165, + }, + 0x94 => { + 0x40 => 0x5982, 0x41 => 0x5c3f, 0x42 => 0x97ee, 0x43 => 0x4efb, + 0x44 => 0x598a, 0x45 => 0x5fcd, 0x46 => 0x8a8d, 0x47 => 0x6fe1, + 0x48 => 0x79b0, 0x49 => 0x7962, 0x4a => 0x5be7, 0x4b => 0x8471, + 0x4c => 0x732b, 0x4d => 0x71b1, 0x4e => 0x5e74, 0x4f => 0x5ff5, + 0x50 => 0x637b, 0x51 => 0x649a, 0x52 => 0x71c3, 0x53 => 0x7c98, + 0x54 => 0x4e43, 0x55 => 0x5efc, 0x56 => 0x4e4b, 0x57 => 0x57dc, + 0x58 => 0x56a2, 0x59 => 0x60a9, 0x5a => 0x6fc3, 0x5b => 0x7d0d, + 0x5c => 0x80fd, 0x5d => 0x8133, 0x5e => 0x81bf, 0x5f => 0x8fb2, + 0x60 => 0x8997, 0x61 => 0x86a4, 0x62 => 0x5df4, 0x63 => 0x628a, + 0x64 => 0x64ad, 0x65 => 0x8987, 0x66 => 0x6777, 0x67 => 0x6ce2, + 0x68 => 0x6d3e, 0x69 => 0x7436, 0x6a => 0x7834, 0x6b => 0x5a46, + 0x6c => 0x7f75, 0x6d => 0x82ad, 0x6e => 0x99ac, 0x6f => 0x4ff3, + 0x70 => 0x5ec3, 0x71 => 0x62dd, 0x72 => 0x6392, 0x73 => 0x6557, + 0x74 => 0x676f, 0x75 => 0x76c3, 0x76 => 0x724c, 0x77 => 0x80cc, + 0x78 => 0x80ba, 0x79 => 0x8f29, 0x7a => 0x914d, 0x7b => 0x500d, + 0x7c => 0x57f9, 0x7d => 0x5a92, 0x7e => 0x6885, 0x80 => 0x6973, + 0x81 => 0x7164, 0x82 => 0x72fd, 0x83 => 0x8cb7, 0x84 => 0x58f2, + 0x85 => 0x8ce0, 0x86 => 0x966a, 0x87 => 0x9019, 0x88 => 0x877f, + 0x89 => 0x79e4, 0x8a => 0x77e7, 0x8b => 0x8429, 0x8c => 0x4f2f, + 0x8d => 0x5265, 0x8e => 0x535a, 0x8f => 0x62cd, 0x90 => 0x67cf, + 0x91 => 0x6cca, 0x92 => 0x767d, 0x93 => 0x7b94, 0x94 => 0x7c95, + 0x95 => 0x8236, 0x96 => 0x8584, 0x97 => 0x8feb, 0x98 => 0x66dd, + 0x99 => 0x6f20, 0x9a => 0x7206, 0x9b => 0x7e1b, 0x9c => 0x83ab, + 0x9d => 0x99c1, 0x9e => 0x9ea6, 0x9f => 0x51fd, 0xa0 => 0x7bb1, + 0xa1 => 0x7872, 0xa2 => 0x7bb8, 0xa3 => 0x8087, 0xa4 => 0x7b48, + 0xa5 => 0x6ae8, 0xa6 => 0x5e61, 0xa7 => 0x808c, 0xa8 => 0x7551, + 0xa9 => 0x7560, 0xaa => 0x516b, 0xab => 0x9262, 0xac => 0x6e8c, + 0xad => 0x767a, 0xae => 0x9197, 0xaf => 0x9aea, 0xb0 => 0x4f10, + 0xb1 => 0x7f70, 0xb2 => 0x629c, 0xb3 => 0x7b4f, 0xb4 => 0x95a5, + 0xb5 => 0x9ce9, 0xb6 => 0x567a, 0xb7 => 0x5859, 0xb8 => 0x86e4, + 0xb9 => 0x96bc, 0xba => 0x4f34, 0xbb => 0x5224, 0xbc => 0x534a, + 0xbd => 0x53cd, 0xbe => 0x53db, 0xbf => 0x5e06, 0xc0 => 0x642c, + 0xc1 => 0x6591, 0xc2 => 0x677f, 0xc3 => 0x6c3e, 0xc4 => 0x6c4e, + 0xc5 => 0x7248, 0xc6 => 0x72af, 0xc7 => 0x73ed, 0xc8 => 0x7554, + 0xc9 => 0x7e41, 0xca => 0x822c, 0xcb => 0x85e9, 0xcc => 0x8ca9, + 0xcd => 0x7bc4, 0xce => 0x91c6, 0xcf => 0x7169, 0xd0 => 0x9812, + 0xd1 => 0x98ef, 0xd2 => 0x633d, 0xd3 => 0x6669, 0xd4 => 0x756a, + 0xd5 => 0x76e4, 0xd6 => 0x78d0, 0xd7 => 0x8543, 0xd8 => 0x86ee, + 0xd9 => 0x532a, 0xda => 0x5351, 0xdb => 0x5426, 0xdc => 0x5983, + 0xdd => 0x5e87, 0xde => 0x5f7c, 0xdf => 0x60b2, 0xe0 => 0x6249, + 0xe1 => 0x6279, 0xe2 => 0x62ab, 0xe3 => 0x6590, 0xe4 => 0x6bd4, + 0xe5 => 0x6ccc, 0xe6 => 0x75b2, 0xe7 => 0x76ae, 0xe8 => 0x7891, + 0xe9 => 0x79d8, 0xea => 0x7dcb, 0xeb => 0x7f77, 0xec => 0x80a5, + 0xed => 0x88ab, 0xee => 0x8ab9, 0xef => 0x8cbb, 0xf0 => 0x907f, + 0xf1 => 0x975e, 0xf2 => 0x98db, 0xf3 => 0x6a0b, 0xf4 => 0x7c38, + 0xf5 => 0x5099, 0xf6 => 0x5c3e, 0xf7 => 0x5fae, 0xf8 => 0x6787, + 0xf9 => 0x6bd8, 0xfa => 0x7435, 0xfb => 0x7709, 0xfc => 0x7f8e, + }, + 0x95 => { + 0x40 => 0x9f3b, 0x41 => 0x67ca, 0x42 => 0x7a17, 0x43 => 0x5339, + 0x44 => 0x758b, 0x45 => 0x9aed, 0x46 => 0x5f66, 0x47 => 0x819d, + 0x48 => 0x83f1, 0x49 => 0x8098, 0x4a => 0x5f3c, 0x4b => 0x5fc5, + 0x4c => 0x7562, 0x4d => 0x7b46, 0x4e => 0x903c, 0x4f => 0x6867, + 0x50 => 0x59eb, 0x51 => 0x5a9b, 0x52 => 0x7d10, 0x53 => 0x767e, + 0x54 => 0x8b2c, 0x55 => 0x4ff5, 0x56 => 0x5f6a, 0x57 => 0x6a19, + 0x58 => 0x6c37, 0x59 => 0x6f02, 0x5a => 0x74e2, 0x5b => 0x7968, + 0x5c => 0x8868, 0x5d => 0x8a55, 0x5e => 0x8c79, 0x5f => 0x5edf, + 0x60 => 0x63cf, 0x61 => 0x75c5, 0x62 => 0x79d2, 0x63 => 0x82d7, + 0x64 => 0x9328, 0x65 => 0x92f2, 0x66 => 0x849c, 0x67 => 0x86ed, + 0x68 => 0x9c2d, 0x69 => 0x54c1, 0x6a => 0x5f6c, 0x6b => 0x658c, + 0x6c => 0x6d5c, 0x6d => 0x7015, 0x6e => 0x8ca7, 0x6f => 0x8cd3, + 0x70 => 0x983b, 0x71 => 0x654f, 0x72 => 0x74f6, 0x73 => 0x4e0d, + 0x74 => 0x4ed8, 0x75 => 0x57e0, 0x76 => 0x592b, 0x77 => 0x5a66, + 0x78 => 0x5bcc, 0x79 => 0x51a8, 0x7a => 0x5e03, 0x7b => 0x5e9c, + 0x7c => 0x6016, 0x7d => 0x6276, 0x7e => 0x6577, 0x80 => 0x65a7, + 0x81 => 0x666e, 0x82 => 0x6d6e, 0x83 => 0x7236, 0x84 => 0x7b26, + 0x85 => 0x8150, 0x86 => 0x819a, 0x87 => 0x8299, 0x88 => 0x8b5c, + 0x89 => 0x8ca0, 0x8a => 0x8ce6, 0x8b => 0x8d74, 0x8c => 0x961c, + 0x8d => 0x9644, 0x8e => 0x4fae, 0x8f => 0x64ab, 0x90 => 0x6b66, + 0x91 => 0x821e, 0x92 => 0x8461, 0x93 => 0x856a, 0x94 => 0x90e8, + 0x95 => 0x5c01, 0x96 => 0x6953, 0x97 => 0x98a8, 0x98 => 0x847a, + 0x99 => 0x8557, 0x9a => 0x4f0f, 0x9b => 0x526f, 0x9c => 0x5fa9, + 0x9d => 0x5e45, 0x9e => 0x670d, 0x9f => 0x798f, 0xa0 => 0x8179, + 0xa1 => 0x8907, 0xa2 => 0x8986, 0xa3 => 0x6df5, 0xa4 => 0x5f17, + 0xa5 => 0x6255, 0xa6 => 0x6cb8, 0xa7 => 0x4ecf, 0xa8 => 0x7269, + 0xa9 => 0x9b92, 0xaa => 0x5206, 0xab => 0x543b, 0xac => 0x5674, + 0xad => 0x58b3, 0xae => 0x61a4, 0xaf => 0x626e, 0xb0 => 0x711a, + 0xb1 => 0x596e, 0xb2 => 0x7c89, 0xb3 => 0x7cde, 0xb4 => 0x7d1b, + 0xb5 => 0x96f0, 0xb6 => 0x6587, 0xb7 => 0x805e, 0xb8 => 0x4e19, + 0xb9 => 0x4f75, 0xba => 0x5175, 0xbb => 0x5840, 0xbc => 0x5e63, + 0xbd => 0x5e73, 0xbe => 0x5f0a, 0xbf => 0x67c4, 0xc0 => 0x4e26, + 0xc1 => 0x853d, 0xc2 => 0x9589, 0xc3 => 0x965b, 0xc4 => 0x7c73, + 0xc5 => 0x9801, 0xc6 => 0x50fb, 0xc7 => 0x58c1, 0xc8 => 0x7656, + 0xc9 => 0x78a7, 0xca => 0x5225, 0xcb => 0x77a5, 0xcc => 0x8511, + 0xcd => 0x7b86, 0xce => 0x504f, 0xcf => 0x5909, 0xd0 => 0x7247, + 0xd1 => 0x7bc7, 0xd2 => 0x7de8, 0xd3 => 0x8fba, 0xd4 => 0x8fd4, + 0xd5 => 0x904d, 0xd6 => 0x4fbf, 0xd7 => 0x52c9, 0xd8 => 0x5a29, + 0xd9 => 0x5f01, 0xda => 0x97ad, 0xdb => 0x4fdd, 0xdc => 0x8217, + 0xdd => 0x92ea, 0xde => 0x5703, 0xdf => 0x6355, 0xe0 => 0x6b69, + 0xe1 => 0x752b, 0xe2 => 0x88dc, 0xe3 => 0x8f14, 0xe4 => 0x7a42, + 0xe5 => 0x52df, 0xe6 => 0x5893, 0xe7 => 0x6155, 0xe8 => 0x620a, + 0xe9 => 0x66ae, 0xea => 0x6bcd, 0xeb => 0x7c3f, 0xec => 0x83e9, + 0xed => 0x5023, 0xee => 0x4ff8, 0xef => 0x5305, 0xf0 => 0x5446, + 0xf1 => 0x5831, 0xf2 => 0x5949, 0xf3 => 0x5b9d, 0xf4 => 0x5cf0, + 0xf5 => 0x5cef, 0xf6 => 0x5d29, 0xf7 => 0x5e96, 0xf8 => 0x62b1, + 0xf9 => 0x6367, 0xfa => 0x653e, 0xfb => 0x65b9, 0xfc => 0x670b, + }, + 0x96 => { + 0x40 => 0x6cd5, 0x41 => 0x6ce1, 0x42 => 0x70f9, 0x43 => 0x7832, + 0x44 => 0x7e2b, 0x45 => 0x80de, 0x46 => 0x82b3, 0x47 => 0x840c, + 0x48 => 0x84ec, 0x49 => 0x8702, 0x4a => 0x8912, 0x4b => 0x8a2a, + 0x4c => 0x8c4a, 0x4d => 0x90a6, 0x4e => 0x92d2, 0x4f => 0x98fd, + 0x50 => 0x9cf3, 0x51 => 0x9d6c, 0x52 => 0x4e4f, 0x53 => 0x4ea1, + 0x54 => 0x508d, 0x55 => 0x5256, 0x56 => 0x574a, 0x57 => 0x59a8, + 0x58 => 0x5e3d, 0x59 => 0x5fd8, 0x5a => 0x5fd9, 0x5b => 0x623f, + 0x5c => 0x66b4, 0x5d => 0x671b, 0x5e => 0x67d0, 0x5f => 0x68d2, + 0x60 => 0x5192, 0x61 => 0x7d21, 0x62 => 0x80aa, 0x63 => 0x81a8, + 0x64 => 0x8b00, 0x65 => 0x8c8c, 0x66 => 0x8cbf, 0x67 => 0x927e, + 0x68 => 0x9632, 0x69 => 0x5420, 0x6a => 0x982c, 0x6b => 0x5317, + 0x6c => 0x50d5, 0x6d => 0x535c, 0x6e => 0x58a8, 0x6f => 0x64b2, + 0x70 => 0x6734, 0x71 => 0x7267, 0x72 => 0x7766, 0x73 => 0x7a46, + 0x74 => 0x91e6, 0x75 => 0x52c3, 0x76 => 0x6ca1, 0x77 => 0x6b86, + 0x78 => 0x5800, 0x79 => 0x5e4c, 0x7a => 0x5954, 0x7b => 0x672c, + 0x7c => 0x7ffb, 0x7d => 0x51e1, 0x7e => 0x76c6, 0x80 => 0x6469, + 0x81 => 0x78e8, 0x82 => 0x9b54, 0x83 => 0x9ebb, 0x84 => 0x57cb, + 0x85 => 0x59b9, 0x86 => 0x6627, 0x87 => 0x679a, 0x88 => 0x6bce, + 0x89 => 0x54e9, 0x8a => 0x69d9, 0x8b => 0x5e55, 0x8c => 0x819c, + 0x8d => 0x6795, 0x8e => 0x9baa, 0x8f => 0x67fe, 0x90 => 0x9c52, + 0x91 => 0x685d, 0x92 => 0x4ea6, 0x93 => 0x4fe3, 0x94 => 0x53c8, + 0x95 => 0x62b9, 0x96 => 0x672b, 0x97 => 0x6cab, 0x98 => 0x8fc4, + 0x99 => 0x4fad, 0x9a => 0x7e6d, 0x9b => 0x9ebf, 0x9c => 0x4e07, + 0x9d => 0x6162, 0x9e => 0x6e80, 0x9f => 0x6f2b, 0xa0 => 0x8513, + 0xa1 => 0x5473, 0xa2 => 0x672a, 0xa3 => 0x9b45, 0xa4 => 0x5df3, + 0xa5 => 0x7b95, 0xa6 => 0x5cac, 0xa7 => 0x5bc6, 0xa8 => 0x871c, + 0xa9 => 0x6e4a, 0xaa => 0x84d1, 0xab => 0x7a14, 0xac => 0x8108, + 0xad => 0x5999, 0xae => 0x7c8d, 0xaf => 0x6c11, 0xb0 => 0x7720, + 0xb1 => 0x52d9, 0xb2 => 0x5922, 0xb3 => 0x7121, 0xb4 => 0x725f, + 0xb5 => 0x77db, 0xb6 => 0x9727, 0xb7 => 0x9d61, 0xb8 => 0x690b, + 0xb9 => 0x5a7f, 0xba => 0x5a18, 0xbb => 0x51a5, 0xbc => 0x540d, + 0xbd => 0x547d, 0xbe => 0x660e, 0xbf => 0x76df, 0xc0 => 0x8ff7, + 0xc1 => 0x9298, 0xc2 => 0x9cf4, 0xc3 => 0x59ea, 0xc4 => 0x725d, + 0xc5 => 0x6ec5, 0xc6 => 0x514d, 0xc7 => 0x68c9, 0xc8 => 0x7dbf, + 0xc9 => 0x7dec, 0xca => 0x9762, 0xcb => 0x9eba, 0xcc => 0x6478, + 0xcd => 0x6a21, 0xce => 0x8302, 0xcf => 0x5984, 0xd0 => 0x5b5f, + 0xd1 => 0x6bdb, 0xd2 => 0x731b, 0xd3 => 0x76f2, 0xd4 => 0x7db2, + 0xd5 => 0x8017, 0xd6 => 0x8499, 0xd7 => 0x5132, 0xd8 => 0x6728, + 0xd9 => 0x9ed9, 0xda => 0x76ee, 0xdb => 0x6762, 0xdc => 0x52ff, + 0xdd => 0x9905, 0xde => 0x5c24, 0xdf => 0x623b, 0xe0 => 0x7c7e, + 0xe1 => 0x8cb0, 0xe2 => 0x554f, 0xe3 => 0x60b6, 0xe4 => 0x7d0b, + 0xe5 => 0x9580, 0xe6 => 0x5301, 0xe7 => 0x4e5f, 0xe8 => 0x51b6, + 0xe9 => 0x591c, 0xea => 0x723a, 0xeb => 0x8036, 0xec => 0x91ce, + 0xed => 0x5f25, 0xee => 0x77e2, 0xef => 0x5384, 0xf0 => 0x5f79, + 0xf1 => 0x7d04, 0xf2 => 0x85ac, 0xf3 => 0x8a33, 0xf4 => 0x8e8d, + 0xf5 => 0x9756, 0xf6 => 0x67f3, 0xf7 => 0x85ae, 0xf8 => 0x9453, + 0xf9 => 0x6109, 0xfa => 0x6108, 0xfb => 0x6cb9, 0xfc => 0x7652, + }, + 0x97 => { + 0x40 => 0x8aed, 0x41 => 0x8f38, 0x42 => 0x552f, 0x43 => 0x4f51, + 0x44 => 0x512a, 0x45 => 0x52c7, 0x46 => 0x53cb, 0x47 => 0x5ba5, + 0x48 => 0x5e7d, 0x49 => 0x60a0, 0x4a => 0x6182, 0x4b => 0x63d6, + 0x4c => 0x6709, 0x4d => 0x67da, 0x4e => 0x6e67, 0x4f => 0x6d8c, + 0x50 => 0x7336, 0x51 => 0x7337, 0x52 => 0x7531, 0x53 => 0x7950, + 0x54 => 0x88d5, 0x55 => 0x8a98, 0x56 => 0x904a, 0x57 => 0x9091, + 0x58 => 0x90f5, 0x59 => 0x96c4, 0x5a => 0x878d, 0x5b => 0x5915, + 0x5c => 0x4e88, 0x5d => 0x4f59, 0x5e => 0x4e0e, 0x5f => 0x8a89, + 0x60 => 0x8f3f, 0x61 => 0x9810, 0x62 => 0x50ad, 0x63 => 0x5e7c, + 0x64 => 0x5996, 0x65 => 0x5bb9, 0x66 => 0x5eb8, 0x67 => 0x63da, + 0x68 => 0x63fa, 0x69 => 0x64c1, 0x6a => 0x66dc, 0x6b => 0x694a, + 0x6c => 0x69d8, 0x6d => 0x6d0b, 0x6e => 0x6eb6, 0x6f => 0x7194, + 0x70 => 0x7528, 0x71 => 0x7aaf, 0x72 => 0x7f8a, 0x73 => 0x8000, + 0x74 => 0x8449, 0x75 => 0x84c9, 0x76 => 0x8981, 0x77 => 0x8b21, + 0x78 => 0x8e0a, 0x79 => 0x9065, 0x7a => 0x967d, 0x7b => 0x990a, + 0x7c => 0x617e, 0x7d => 0x6291, 0x7e => 0x6b32, 0x80 => 0x6c83, + 0x81 => 0x6d74, 0x82 => 0x7fcc, 0x83 => 0x7ffc, 0x84 => 0x6dc0, + 0x85 => 0x7f85, 0x86 => 0x87ba, 0x87 => 0x88f8, 0x88 => 0x6765, + 0x89 => 0x83b1, 0x8a => 0x983c, 0x8b => 0x96f7, 0x8c => 0x6d1b, + 0x8d => 0x7d61, 0x8e => 0x843d, 0x8f => 0x916a, 0x90 => 0x4e71, + 0x91 => 0x5375, 0x92 => 0x5d50, 0x93 => 0x6b04, 0x94 => 0x6feb, + 0x95 => 0x85cd, 0x96 => 0x862d, 0x97 => 0x89a7, 0x98 => 0x5229, + 0x99 => 0x540f, 0x9a => 0x5c65, 0x9b => 0x674e, 0x9c => 0x68a8, + 0x9d => 0x7406, 0x9e => 0x7483, 0x9f => 0x75e2, 0xa0 => 0x88cf, + 0xa1 => 0x88e1, 0xa2 => 0x91cc, 0xa3 => 0x96e2, 0xa4 => 0x9678, + 0xa5 => 0x5f8b, 0xa6 => 0x7387, 0xa7 => 0x7acb, 0xa8 => 0x844e, + 0xa9 => 0x63a0, 0xaa => 0x7565, 0xab => 0x5289, 0xac => 0x6d41, + 0xad => 0x6e9c, 0xae => 0x7409, 0xaf => 0x7559, 0xb0 => 0x786b, + 0xb1 => 0x7c92, 0xb2 => 0x9686, 0xb3 => 0x7adc, 0xb4 => 0x9f8d, + 0xb5 => 0x4fb6, 0xb6 => 0x616e, 0xb7 => 0x65c5, 0xb8 => 0x865c, + 0xb9 => 0x4e86, 0xba => 0x4eae, 0xbb => 0x50da, 0xbc => 0x4e21, + 0xbd => 0x51cc, 0xbe => 0x5bee, 0xbf => 0x6599, 0xc0 => 0x6881, + 0xc1 => 0x6dbc, 0xc2 => 0x731f, 0xc3 => 0x7642, 0xc4 => 0x77ad, + 0xc5 => 0x7a1c, 0xc6 => 0x7ce7, 0xc7 => 0x826f, 0xc8 => 0x8ad2, + 0xc9 => 0x907c, 0xca => 0x91cf, 0xcb => 0x9675, 0xcc => 0x9818, + 0xcd => 0x529b, 0xce => 0x7dd1, 0xcf => 0x502b, 0xd0 => 0x5398, + 0xd1 => 0x6797, 0xd2 => 0x6dcb, 0xd3 => 0x71d0, 0xd4 => 0x7433, + 0xd5 => 0x81e8, 0xd6 => 0x8f2a, 0xd7 => 0x96a3, 0xd8 => 0x9c57, + 0xd9 => 0x9e9f, 0xda => 0x7460, 0xdb => 0x5841, 0xdc => 0x6d99, + 0xdd => 0x7d2f, 0xde => 0x985e, 0xdf => 0x4ee4, 0xe0 => 0x4f36, + 0xe1 => 0x4f8b, 0xe2 => 0x51b7, 0xe3 => 0x52b1, 0xe4 => 0x5dba, + 0xe5 => 0x601c, 0xe6 => 0x73b2, 0xe7 => 0x793c, 0xe8 => 0x82d3, + 0xe9 => 0x9234, 0xea => 0x96b7, 0xeb => 0x96f6, 0xec => 0x970a, + 0xed => 0x9e97, 0xee => 0x9f62, 0xef => 0x66a6, 0xf0 => 0x6b74, + 0xf1 => 0x5217, 0xf2 => 0x52a3, 0xf3 => 0x70c8, 0xf4 => 0x88c2, + 0xf5 => 0x5ec9, 0xf6 => 0x604b, 0xf7 => 0x6190, 0xf8 => 0x6f23, + 0xf9 => 0x7149, 0xfa => 0x7c3e, 0xfb => 0x7df4, 0xfc => 0x806f, + }, + 0x98 => { + 0x40 => 0x84ee, 0x41 => 0x9023, 0x42 => 0x932c, 0x43 => 0x5442, + 0x44 => 0x9b6f, 0x45 => 0x6ad3, 0x46 => 0x7089, 0x47 => 0x8cc2, + 0x48 => 0x8def, 0x49 => 0x9732, 0x4a => 0x52b4, 0x4b => 0x5a41, + 0x4c => 0x5eca, 0x4d => 0x5f04, 0x4e => 0x6717, 0x4f => 0x697c, + 0x50 => 0x6994, 0x51 => 0x6d6a, 0x52 => 0x6f0f, 0x53 => 0x7262, + 0x54 => 0x72fc, 0x55 => 0x7bed, 0x56 => 0x8001, 0x57 => 0x807e, + 0x58 => 0x874b, 0x59 => 0x90ce, 0x5a => 0x516d, 0x5b => 0x9e93, + 0x5c => 0x7984, 0x5d => 0x808b, 0x5e => 0x9332, 0x5f => 0x8ad6, + 0x60 => 0x502d, 0x61 => 0x548c, 0x62 => 0x8a71, 0x63 => 0x6b6a, + 0x64 => 0x8cc4, 0x65 => 0x8107, 0x66 => 0x60d1, 0x67 => 0x67a0, + 0x68 => 0x9df2, 0x69 => 0x4e99, 0x6a => 0x4e98, 0x6b => 0x9c10, + 0x6c => 0x8a6b, 0x6d => 0x85c1, 0x6e => 0x8568, 0x6f => 0x6900, + 0x70 => 0x6e7e, 0x71 => 0x7897, 0x72 => 0x8155, 0x9f => 0x5f0c, + 0xa0 => 0x4e10, 0xa1 => 0x4e15, 0xa2 => 0x4e2a, 0xa3 => 0x4e31, + 0xa4 => 0x4e36, 0xa5 => 0x4e3c, 0xa6 => 0x4e3f, 0xa7 => 0x4e42, + 0xa8 => 0x4e56, 0xa9 => 0x4e58, 0xaa => 0x4e82, 0xab => 0x4e85, + 0xac => 0x8c6b, 0xad => 0x4e8a, 0xae => 0x8212, 0xaf => 0x5f0d, + 0xb0 => 0x4e8e, 0xb1 => 0x4e9e, 0xb2 => 0x4e9f, 0xb3 => 0x4ea0, + 0xb4 => 0x4ea2, 0xb5 => 0x4eb0, 0xb6 => 0x4eb3, 0xb7 => 0x4eb6, + 0xb8 => 0x4ece, 0xb9 => 0x4ecd, 0xba => 0x4ec4, 0xbb => 0x4ec6, + 0xbc => 0x4ec2, 0xbd => 0x4ed7, 0xbe => 0x4ede, 0xbf => 0x4eed, + 0xc0 => 0x4edf, 0xc1 => 0x4ef7, 0xc2 => 0x4f09, 0xc3 => 0x4f5a, + 0xc4 => 0x4f30, 0xc5 => 0x4f5b, 0xc6 => 0x4f5d, 0xc7 => 0x4f57, + 0xc8 => 0x4f47, 0xc9 => 0x4f76, 0xca => 0x4f88, 0xcb => 0x4f8f, + 0xcc => 0x4f98, 0xcd => 0x4f7b, 0xce => 0x4f69, 0xcf => 0x4f70, + 0xd0 => 0x4f91, 0xd1 => 0x4f6f, 0xd2 => 0x4f86, 0xd3 => 0x4f96, + 0xd4 => 0x5118, 0xd5 => 0x4fd4, 0xd6 => 0x4fdf, 0xd7 => 0x4fce, + 0xd8 => 0x4fd8, 0xd9 => 0x4fdb, 0xda => 0x4fd1, 0xdb => 0x4fda, + 0xdc => 0x4fd0, 0xdd => 0x4fe4, 0xde => 0x4fe5, 0xdf => 0x501a, + 0xe0 => 0x5028, 0xe1 => 0x5014, 0xe2 => 0x502a, 0xe3 => 0x5025, + 0xe4 => 0x5005, 0xe5 => 0x4f1c, 0xe6 => 0x4ff6, 0xe7 => 0x5021, + 0xe8 => 0x5029, 0xe9 => 0x502c, 0xea => 0x4ffe, 0xeb => 0x4fef, + 0xec => 0x5011, 0xed => 0x5006, 0xee => 0x5043, 0xef => 0x5047, + 0xf0 => 0x6703, 0xf1 => 0x5055, 0xf2 => 0x5050, 0xf3 => 0x5048, + 0xf4 => 0x505a, 0xf5 => 0x5056, 0xf6 => 0x506c, 0xf7 => 0x5078, + 0xf8 => 0x5080, 0xf9 => 0x509a, 0xfa => 0x5085, 0xfb => 0x50b4, + 0xfc => 0x50b2, + }, + 0x99 => { + 0x40 => 0x50c9, 0x41 => 0x50ca, 0x42 => 0x50b3, 0x43 => 0x50c2, + 0x44 => 0x50d6, 0x45 => 0x50de, 0x46 => 0x50e5, 0x47 => 0x50ed, + 0x48 => 0x50e3, 0x49 => 0x50ee, 0x4a => 0x50f9, 0x4b => 0x50f5, + 0x4c => 0x5109, 0x4d => 0x5101, 0x4e => 0x5102, 0x4f => 0x5116, + 0x50 => 0x5115, 0x51 => 0x5114, 0x52 => 0x511a, 0x53 => 0x5121, + 0x54 => 0x513a, 0x55 => 0x5137, 0x56 => 0x513c, 0x57 => 0x513b, + 0x58 => 0x513f, 0x59 => 0x5140, 0x5a => 0x5152, 0x5b => 0x514c, + 0x5c => 0x5154, 0x5d => 0x5162, 0x5e => 0x7af8, 0x5f => 0x5169, + 0x60 => 0x516a, 0x61 => 0x516e, 0x62 => 0x5180, 0x63 => 0x5182, + 0x64 => 0x56d8, 0x65 => 0x518c, 0x66 => 0x5189, 0x67 => 0x518f, + 0x68 => 0x5191, 0x69 => 0x5193, 0x6a => 0x5195, 0x6b => 0x5196, + 0x6c => 0x51a4, 0x6d => 0x51a6, 0x6e => 0x51a2, 0x6f => 0x51a9, + 0x70 => 0x51aa, 0x71 => 0x51ab, 0x72 => 0x51b3, 0x73 => 0x51b1, + 0x74 => 0x51b2, 0x75 => 0x51b0, 0x76 => 0x51b5, 0x77 => 0x51bd, + 0x78 => 0x51c5, 0x79 => 0x51c9, 0x7a => 0x51db, 0x7b => 0x51e0, + 0x7c => 0x8655, 0x7d => 0x51e9, 0x7e => 0x51ed, 0x80 => 0x51f0, + 0x81 => 0x51f5, 0x82 => 0x51fe, 0x83 => 0x5204, 0x84 => 0x520b, + 0x85 => 0x5214, 0x86 => 0x520e, 0x87 => 0x5227, 0x88 => 0x522a, + 0x89 => 0x522e, 0x8a => 0x5233, 0x8b => 0x5239, 0x8c => 0x524f, + 0x8d => 0x5244, 0x8e => 0x524b, 0x8f => 0x524c, 0x90 => 0x525e, + 0x91 => 0x5254, 0x92 => 0x526a, 0x93 => 0x5274, 0x94 => 0x5269, + 0x95 => 0x5273, 0x96 => 0x527f, 0x97 => 0x527d, 0x98 => 0x528d, + 0x99 => 0x5294, 0x9a => 0x5292, 0x9b => 0x5271, 0x9c => 0x5288, + 0x9d => 0x5291, 0x9e => 0x8fa8, 0x9f => 0x8fa7, 0xa0 => 0x52ac, + 0xa1 => 0x52ad, 0xa2 => 0x52bc, 0xa3 => 0x52b5, 0xa4 => 0x52c1, + 0xa5 => 0x52cd, 0xa6 => 0x52d7, 0xa7 => 0x52de, 0xa8 => 0x52e3, + 0xa9 => 0x52e6, 0xaa => 0x98ed, 0xab => 0x52e0, 0xac => 0x52f3, + 0xad => 0x52f5, 0xae => 0x52f8, 0xaf => 0x52f9, 0xb0 => 0x5306, + 0xb1 => 0x5308, 0xb2 => 0x7538, 0xb3 => 0x530d, 0xb4 => 0x5310, + 0xb5 => 0x530f, 0xb6 => 0x5315, 0xb7 => 0x531a, 0xb8 => 0x5323, + 0xb9 => 0x532f, 0xba => 0x5331, 0xbb => 0x5333, 0xbc => 0x5338, + 0xbd => 0x5340, 0xbe => 0x5346, 0xbf => 0x5345, 0xc0 => 0x4e17, + 0xc1 => 0x5349, 0xc2 => 0x534d, 0xc3 => 0x51d6, 0xc4 => 0x535e, + 0xc5 => 0x5369, 0xc6 => 0x536e, 0xc7 => 0x5918, 0xc8 => 0x537b, + 0xc9 => 0x5377, 0xca => 0x5382, 0xcb => 0x5396, 0xcc => 0x53a0, + 0xcd => 0x53a6, 0xce => 0x53a5, 0xcf => 0x53ae, 0xd0 => 0x53b0, + 0xd1 => 0x53b6, 0xd2 => 0x53c3, 0xd3 => 0x7c12, 0xd4 => 0x96d9, + 0xd5 => 0x53df, 0xd6 => 0x66fc, 0xd7 => 0x71ee, 0xd8 => 0x53ee, + 0xd9 => 0x53e8, 0xda => 0x53ed, 0xdb => 0x53fa, 0xdc => 0x5401, + 0xdd => 0x543d, 0xde => 0x5440, 0xdf => 0x542c, 0xe0 => 0x542d, + 0xe1 => 0x543c, 0xe2 => 0x542e, 0xe3 => 0x5436, 0xe4 => 0x5429, + 0xe5 => 0x541d, 0xe6 => 0x544e, 0xe7 => 0x548f, 0xe8 => 0x5475, + 0xe9 => 0x548e, 0xea => 0x545f, 0xeb => 0x5471, 0xec => 0x5477, + 0xed => 0x5470, 0xee => 0x5492, 0xef => 0x547b, 0xf0 => 0x5480, + 0xf1 => 0x5476, 0xf2 => 0x5484, 0xf3 => 0x5490, 0xf4 => 0x5486, + 0xf5 => 0x54c7, 0xf6 => 0x54a2, 0xf7 => 0x54b8, 0xf8 => 0x54a5, + 0xf9 => 0x54ac, 0xfa => 0x54c4, 0xfb => 0x54c8, 0xfc => 0x54a8, + }, + 0x9a => { + 0x40 => 0x54ab, 0x41 => 0x54c2, 0x42 => 0x54a4, 0x43 => 0x54be, + 0x44 => 0x54bc, 0x45 => 0x54d8, 0x46 => 0x54e5, 0x47 => 0x54e6, + 0x48 => 0x550f, 0x49 => 0x5514, 0x4a => 0x54fd, 0x4b => 0x54ee, + 0x4c => 0x54ed, 0x4d => 0x54fa, 0x4e => 0x54e2, 0x4f => 0x5539, + 0x50 => 0x5540, 0x51 => 0x5563, 0x52 => 0x554c, 0x53 => 0x552e, + 0x54 => 0x555c, 0x55 => 0x5545, 0x56 => 0x5556, 0x57 => 0x5557, + 0x58 => 0x5538, 0x59 => 0x5533, 0x5a => 0x555d, 0x5b => 0x5599, + 0x5c => 0x5580, 0x5d => 0x54af, 0x5e => 0x558a, 0x5f => 0x559f, + 0x60 => 0x557b, 0x61 => 0x557e, 0x62 => 0x5598, 0x63 => 0x559e, + 0x64 => 0x55ae, 0x65 => 0x557c, 0x66 => 0x5583, 0x67 => 0x55a9, + 0x68 => 0x5587, 0x69 => 0x55a8, 0x6a => 0x55da, 0x6b => 0x55c5, + 0x6c => 0x55df, 0x6d => 0x55c4, 0x6e => 0x55dc, 0x6f => 0x55e4, + 0x70 => 0x55d4, 0x71 => 0x5614, 0x72 => 0x55f7, 0x73 => 0x5616, + 0x74 => 0x55fe, 0x75 => 0x55fd, 0x76 => 0x561b, 0x77 => 0x55f9, + 0x78 => 0x564e, 0x79 => 0x5650, 0x7a => 0x71df, 0x7b => 0x5634, + 0x7c => 0x5636, 0x7d => 0x5632, 0x7e => 0x5638, 0x80 => 0x566b, + 0x81 => 0x5664, 0x82 => 0x562f, 0x83 => 0x566c, 0x84 => 0x566a, + 0x85 => 0x5686, 0x86 => 0x5680, 0x87 => 0x568a, 0x88 => 0x56a0, + 0x89 => 0x5694, 0x8a => 0x568f, 0x8b => 0x56a5, 0x8c => 0x56ae, + 0x8d => 0x56b6, 0x8e => 0x56b4, 0x8f => 0x56c2, 0x90 => 0x56bc, + 0x91 => 0x56c1, 0x92 => 0x56c3, 0x93 => 0x56c0, 0x94 => 0x56c8, + 0x95 => 0x56ce, 0x96 => 0x56d1, 0x97 => 0x56d3, 0x98 => 0x56d7, + 0x99 => 0x56ee, 0x9a => 0x56f9, 0x9b => 0x5700, 0x9c => 0x56ff, + 0x9d => 0x5704, 0x9e => 0x5709, 0x9f => 0x5708, 0xa0 => 0x570b, + 0xa1 => 0x570d, 0xa2 => 0x5713, 0xa3 => 0x5718, 0xa4 => 0x5716, + 0xa5 => 0x55c7, 0xa6 => 0x571c, 0xa7 => 0x5726, 0xa8 => 0x5737, + 0xa9 => 0x5738, 0xaa => 0x574e, 0xab => 0x573b, 0xac => 0x5740, + 0xad => 0x574f, 0xae => 0x5769, 0xaf => 0x57c0, 0xb0 => 0x5788, + 0xb1 => 0x5761, 0xb2 => 0x577f, 0xb3 => 0x5789, 0xb4 => 0x5793, + 0xb5 => 0x57a0, 0xb6 => 0x57b3, 0xb7 => 0x57a4, 0xb8 => 0x57aa, + 0xb9 => 0x57b0, 0xba => 0x57c3, 0xbb => 0x57c6, 0xbc => 0x57d4, + 0xbd => 0x57d2, 0xbe => 0x57d3, 0xbf => 0x580a, 0xc0 => 0x57d6, + 0xc1 => 0x57e3, 0xc2 => 0x580b, 0xc3 => 0x5819, 0xc4 => 0x581d, + 0xc5 => 0x5872, 0xc6 => 0x5821, 0xc7 => 0x5862, 0xc8 => 0x584b, + 0xc9 => 0x5870, 0xca => 0x6bc0, 0xcb => 0x5852, 0xcc => 0x583d, + 0xcd => 0x5879, 0xce => 0x5885, 0xcf => 0x58b9, 0xd0 => 0x589f, + 0xd1 => 0x58ab, 0xd2 => 0x58ba, 0xd3 => 0x58de, 0xd4 => 0x58bb, + 0xd5 => 0x58b8, 0xd6 => 0x58ae, 0xd7 => 0x58c5, 0xd8 => 0x58d3, + 0xd9 => 0x58d1, 0xda => 0x58d7, 0xdb => 0x58d9, 0xdc => 0x58d8, + 0xdd => 0x58e5, 0xde => 0x58dc, 0xdf => 0x58e4, 0xe0 => 0x58df, + 0xe1 => 0x58ef, 0xe2 => 0x58fa, 0xe3 => 0x58f9, 0xe4 => 0x58fb, + 0xe5 => 0x58fc, 0xe6 => 0x58fd, 0xe7 => 0x5902, 0xe8 => 0x590a, + 0xe9 => 0x5910, 0xea => 0x591b, 0xeb => 0x68a6, 0xec => 0x5925, + 0xed => 0x592c, 0xee => 0x592d, 0xef => 0x5932, 0xf0 => 0x5938, + 0xf1 => 0x593e, 0xf2 => 0x7ad2, 0xf3 => 0x5955, 0xf4 => 0x5950, + 0xf5 => 0x594e, 0xf6 => 0x595a, 0xf7 => 0x5958, 0xf8 => 0x5962, + 0xf9 => 0x5960, 0xfa => 0x5967, 0xfb => 0x596c, 0xfc => 0x5969, + }, + 0x9b => { + 0x40 => 0x5978, 0x41 => 0x5981, 0x42 => 0x599d, 0x43 => 0x4f5e, + 0x44 => 0x4fab, 0x45 => 0x59a3, 0x46 => 0x59b2, 0x47 => 0x59c6, + 0x48 => 0x59e8, 0x49 => 0x59dc, 0x4a => 0x598d, 0x4b => 0x59d9, + 0x4c => 0x59da, 0x4d => 0x5a25, 0x4e => 0x5a1f, 0x4f => 0x5a11, + 0x50 => 0x5a1c, 0x51 => 0x5a09, 0x52 => 0x5a1a, 0x53 => 0x5a40, + 0x54 => 0x5a6c, 0x55 => 0x5a49, 0x56 => 0x5a35, 0x57 => 0x5a36, + 0x58 => 0x5a62, 0x59 => 0x5a6a, 0x5a => 0x5a9a, 0x5b => 0x5abc, + 0x5c => 0x5abe, 0x5d => 0x5acb, 0x5e => 0x5ac2, 0x5f => 0x5abd, + 0x60 => 0x5ae3, 0x61 => 0x5ad7, 0x62 => 0x5ae6, 0x63 => 0x5ae9, + 0x64 => 0x5ad6, 0x65 => 0x5afa, 0x66 => 0x5afb, 0x67 => 0x5b0c, + 0x68 => 0x5b0b, 0x69 => 0x5b16, 0x6a => 0x5b32, 0x6b => 0x5ad0, + 0x6c => 0x5b2a, 0x6d => 0x5b36, 0x6e => 0x5b3e, 0x6f => 0x5b43, + 0x70 => 0x5b45, 0x71 => 0x5b40, 0x72 => 0x5b51, 0x73 => 0x5b55, + 0x74 => 0x5b5a, 0x75 => 0x5b5b, 0x76 => 0x5b65, 0x77 => 0x5b69, + 0x78 => 0x5b70, 0x79 => 0x5b73, 0x7a => 0x5b75, 0x7b => 0x5b78, + 0x7c => 0x6588, 0x7d => 0x5b7a, 0x7e => 0x5b80, 0x80 => 0x5b83, + 0x81 => 0x5ba6, 0x82 => 0x5bb8, 0x83 => 0x5bc3, 0x84 => 0x5bc7, + 0x85 => 0x5bc9, 0x86 => 0x5bd4, 0x87 => 0x5bd0, 0x88 => 0x5be4, + 0x89 => 0x5be6, 0x8a => 0x5be2, 0x8b => 0x5bde, 0x8c => 0x5be5, + 0x8d => 0x5beb, 0x8e => 0x5bf0, 0x8f => 0x5bf6, 0x90 => 0x5bf3, + 0x91 => 0x5c05, 0x92 => 0x5c07, 0x93 => 0x5c08, 0x94 => 0x5c0d, + 0x95 => 0x5c13, 0x96 => 0x5c20, 0x97 => 0x5c22, 0x98 => 0x5c28, + 0x99 => 0x5c38, 0x9a => 0x5c39, 0x9b => 0x5c41, 0x9c => 0x5c46, + 0x9d => 0x5c4e, 0x9e => 0x5c53, 0x9f => 0x5c50, 0xa0 => 0x5c4f, + 0xa1 => 0x5b71, 0xa2 => 0x5c6c, 0xa3 => 0x5c6e, 0xa4 => 0x4e62, + 0xa5 => 0x5c76, 0xa6 => 0x5c79, 0xa7 => 0x5c8c, 0xa8 => 0x5c91, + 0xa9 => 0x5c94, 0xaa => 0x599b, 0xab => 0x5cab, 0xac => 0x5cbb, + 0xad => 0x5cb6, 0xae => 0x5cbc, 0xaf => 0x5cb7, 0xb0 => 0x5cc5, + 0xb1 => 0x5cbe, 0xb2 => 0x5cc7, 0xb3 => 0x5cd9, 0xb4 => 0x5ce9, + 0xb5 => 0x5cfd, 0xb6 => 0x5cfa, 0xb7 => 0x5ced, 0xb8 => 0x5d8c, + 0xb9 => 0x5cea, 0xba => 0x5d0b, 0xbb => 0x5d15, 0xbc => 0x5d17, + 0xbd => 0x5d5c, 0xbe => 0x5d1f, 0xbf => 0x5d1b, 0xc0 => 0x5d11, + 0xc1 => 0x5d14, 0xc2 => 0x5d22, 0xc3 => 0x5d1a, 0xc4 => 0x5d19, + 0xc5 => 0x5d18, 0xc6 => 0x5d4c, 0xc7 => 0x5d52, 0xc8 => 0x5d4e, + 0xc9 => 0x5d4b, 0xca => 0x5d6c, 0xcb => 0x5d73, 0xcc => 0x5d76, + 0xcd => 0x5d87, 0xce => 0x5d84, 0xcf => 0x5d82, 0xd0 => 0x5da2, + 0xd1 => 0x5d9d, 0xd2 => 0x5dac, 0xd3 => 0x5dae, 0xd4 => 0x5dbd, + 0xd5 => 0x5d90, 0xd6 => 0x5db7, 0xd7 => 0x5dbc, 0xd8 => 0x5dc9, + 0xd9 => 0x5dcd, 0xda => 0x5dd3, 0xdb => 0x5dd2, 0xdc => 0x5dd6, + 0xdd => 0x5ddb, 0xde => 0x5deb, 0xdf => 0x5df2, 0xe0 => 0x5df5, + 0xe1 => 0x5e0b, 0xe2 => 0x5e1a, 0xe3 => 0x5e19, 0xe4 => 0x5e11, + 0xe5 => 0x5e1b, 0xe6 => 0x5e36, 0xe7 => 0x5e37, 0xe8 => 0x5e44, + 0xe9 => 0x5e43, 0xea => 0x5e40, 0xeb => 0x5e4e, 0xec => 0x5e57, + 0xed => 0x5e54, 0xee => 0x5e5f, 0xef => 0x5e62, 0xf0 => 0x5e64, + 0xf1 => 0x5e47, 0xf2 => 0x5e75, 0xf3 => 0x5e76, 0xf4 => 0x5e7a, + 0xf5 => 0x9ebc, 0xf6 => 0x5e7f, 0xf7 => 0x5ea0, 0xf8 => 0x5ec1, + 0xf9 => 0x5ec2, 0xfa => 0x5ec8, 0xfb => 0x5ed0, 0xfc => 0x5ecf, + }, + 0x9c => { + 0x40 => 0x5ed6, 0x41 => 0x5ee3, 0x42 => 0x5edd, 0x43 => 0x5eda, + 0x44 => 0x5edb, 0x45 => 0x5ee2, 0x46 => 0x5ee1, 0x47 => 0x5ee8, + 0x48 => 0x5ee9, 0x49 => 0x5eec, 0x4a => 0x5ef1, 0x4b => 0x5ef3, + 0x4c => 0x5ef0, 0x4d => 0x5ef4, 0x4e => 0x5ef8, 0x4f => 0x5efe, + 0x50 => 0x5f03, 0x51 => 0x5f09, 0x52 => 0x5f5d, 0x53 => 0x5f5c, + 0x54 => 0x5f0b, 0x55 => 0x5f11, 0x56 => 0x5f16, 0x57 => 0x5f29, + 0x58 => 0x5f2d, 0x59 => 0x5f38, 0x5a => 0x5f41, 0x5b => 0x5f48, + 0x5c => 0x5f4c, 0x5d => 0x5f4e, 0x5e => 0x5f2f, 0x5f => 0x5f51, + 0x60 => 0x5f56, 0x61 => 0x5f57, 0x62 => 0x5f59, 0x63 => 0x5f61, + 0x64 => 0x5f6d, 0x65 => 0x5f73, 0x66 => 0x5f77, 0x67 => 0x5f83, + 0x68 => 0x5f82, 0x69 => 0x5f7f, 0x6a => 0x5f8a, 0x6b => 0x5f88, + 0x6c => 0x5f91, 0x6d => 0x5f87, 0x6e => 0x5f9e, 0x6f => 0x5f99, + 0x70 => 0x5f98, 0x71 => 0x5fa0, 0x72 => 0x5fa8, 0x73 => 0x5fad, + 0x74 => 0x5fbc, 0x75 => 0x5fd6, 0x76 => 0x5ffb, 0x77 => 0x5fe4, + 0x78 => 0x5ff8, 0x79 => 0x5ff1, 0x7a => 0x5fdd, 0x7b => 0x60b3, + 0x7c => 0x5fff, 0x7d => 0x6021, 0x7e => 0x6060, 0x80 => 0x6019, + 0x81 => 0x6010, 0x82 => 0x6029, 0x83 => 0x600e, 0x84 => 0x6031, + 0x85 => 0x601b, 0x86 => 0x6015, 0x87 => 0x602b, 0x88 => 0x6026, + 0x89 => 0x600f, 0x8a => 0x603a, 0x8b => 0x605a, 0x8c => 0x6041, + 0x8d => 0x606a, 0x8e => 0x6077, 0x8f => 0x605f, 0x90 => 0x604a, + 0x91 => 0x6046, 0x92 => 0x604d, 0x93 => 0x6063, 0x94 => 0x6043, + 0x95 => 0x6064, 0x96 => 0x6042, 0x97 => 0x606c, 0x98 => 0x606b, + 0x99 => 0x6059, 0x9a => 0x6081, 0x9b => 0x608d, 0x9c => 0x60e7, + 0x9d => 0x6083, 0x9e => 0x609a, 0x9f => 0x6084, 0xa0 => 0x609b, + 0xa1 => 0x6096, 0xa2 => 0x6097, 0xa3 => 0x6092, 0xa4 => 0x60a7, + 0xa5 => 0x608b, 0xa6 => 0x60e1, 0xa7 => 0x60b8, 0xa8 => 0x60e0, + 0xa9 => 0x60d3, 0xaa => 0x60b4, 0xab => 0x5ff0, 0xac => 0x60bd, + 0xad => 0x60c6, 0xae => 0x60b5, 0xaf => 0x60d8, 0xb0 => 0x614d, + 0xb1 => 0x6115, 0xb2 => 0x6106, 0xb3 => 0x60f6, 0xb4 => 0x60f7, + 0xb5 => 0x6100, 0xb6 => 0x60f4, 0xb7 => 0x60fa, 0xb8 => 0x6103, + 0xb9 => 0x6121, 0xba => 0x60fb, 0xbb => 0x60f1, 0xbc => 0x610d, + 0xbd => 0x610e, 0xbe => 0x6147, 0xbf => 0x613e, 0xc0 => 0x6128, + 0xc1 => 0x6127, 0xc2 => 0x614a, 0xc3 => 0x613f, 0xc4 => 0x613c, + 0xc5 => 0x612c, 0xc6 => 0x6134, 0xc7 => 0x613d, 0xc8 => 0x6142, + 0xc9 => 0x6144, 0xca => 0x6173, 0xcb => 0x6177, 0xcc => 0x6158, + 0xcd => 0x6159, 0xce => 0x615a, 0xcf => 0x616b, 0xd0 => 0x6174, + 0xd1 => 0x616f, 0xd2 => 0x6165, 0xd3 => 0x6171, 0xd4 => 0x615f, + 0xd5 => 0x615d, 0xd6 => 0x6153, 0xd7 => 0x6175, 0xd8 => 0x6199, + 0xd9 => 0x6196, 0xda => 0x6187, 0xdb => 0x61ac, 0xdc => 0x6194, + 0xdd => 0x619a, 0xde => 0x618a, 0xdf => 0x6191, 0xe0 => 0x61ab, + 0xe1 => 0x61ae, 0xe2 => 0x61cc, 0xe3 => 0x61ca, 0xe4 => 0x61c9, + 0xe5 => 0x61f7, 0xe6 => 0x61c8, 0xe7 => 0x61c3, 0xe8 => 0x61c6, + 0xe9 => 0x61ba, 0xea => 0x61cb, 0xeb => 0x7f79, 0xec => 0x61cd, + 0xed => 0x61e6, 0xee => 0x61e3, 0xef => 0x61f6, 0xf0 => 0x61fa, + 0xf1 => 0x61f4, 0xf2 => 0x61ff, 0xf3 => 0x61fd, 0xf4 => 0x61fc, + 0xf5 => 0x61fe, 0xf6 => 0x6200, 0xf7 => 0x6208, 0xf8 => 0x6209, + 0xf9 => 0x620d, 0xfa => 0x620c, 0xfb => 0x6214, 0xfc => 0x621b, + }, + 0x9d => { + 0x40 => 0x621e, 0x41 => 0x6221, 0x42 => 0x622a, 0x43 => 0x622e, + 0x44 => 0x6230, 0x45 => 0x6232, 0x46 => 0x6233, 0x47 => 0x6241, + 0x48 => 0x624e, 0x49 => 0x625e, 0x4a => 0x6263, 0x4b => 0x625b, + 0x4c => 0x6260, 0x4d => 0x6268, 0x4e => 0x627c, 0x4f => 0x6282, + 0x50 => 0x6289, 0x51 => 0x627e, 0x52 => 0x6292, 0x53 => 0x6293, + 0x54 => 0x6296, 0x55 => 0x62d4, 0x56 => 0x6283, 0x57 => 0x6294, + 0x58 => 0x62d7, 0x59 => 0x62d1, 0x5a => 0x62bb, 0x5b => 0x62cf, + 0x5c => 0x62ff, 0x5d => 0x62c6, 0x5e => 0x64d4, 0x5f => 0x62c8, + 0x60 => 0x62dc, 0x61 => 0x62cc, 0x62 => 0x62ca, 0x63 => 0x62c2, + 0x64 => 0x62c7, 0x65 => 0x629b, 0x66 => 0x62c9, 0x67 => 0x630c, + 0x68 => 0x62ee, 0x69 => 0x62f1, 0x6a => 0x6327, 0x6b => 0x6302, + 0x6c => 0x6308, 0x6d => 0x62ef, 0x6e => 0x62f5, 0x6f => 0x6350, + 0x70 => 0x633e, 0x71 => 0x634d, 0x72 => 0x641c, 0x73 => 0x634f, + 0x74 => 0x6396, 0x75 => 0x638e, 0x76 => 0x6380, 0x77 => 0x63ab, + 0x78 => 0x6376, 0x79 => 0x63a3, 0x7a => 0x638f, 0x7b => 0x6389, + 0x7c => 0x639f, 0x7d => 0x63b5, 0x7e => 0x636b, 0x80 => 0x6369, + 0x81 => 0x63be, 0x82 => 0x63e9, 0x83 => 0x63c0, 0x84 => 0x63c6, + 0x85 => 0x63e3, 0x86 => 0x63c9, 0x87 => 0x63d2, 0x88 => 0x63f6, + 0x89 => 0x63c4, 0x8a => 0x6416, 0x8b => 0x6434, 0x8c => 0x6406, + 0x8d => 0x6413, 0x8e => 0x6426, 0x8f => 0x6436, 0x90 => 0x651d, + 0x91 => 0x6417, 0x92 => 0x6428, 0x93 => 0x640f, 0x94 => 0x6467, + 0x95 => 0x646f, 0x96 => 0x6476, 0x97 => 0x644e, 0x98 => 0x652a, + 0x99 => 0x6495, 0x9a => 0x6493, 0x9b => 0x64a5, 0x9c => 0x64a9, + 0x9d => 0x6488, 0x9e => 0x64bc, 0x9f => 0x64da, 0xa0 => 0x64d2, + 0xa1 => 0x64c5, 0xa2 => 0x64c7, 0xa3 => 0x64bb, 0xa4 => 0x64d8, + 0xa5 => 0x64c2, 0xa6 => 0x64f1, 0xa7 => 0x64e7, 0xa8 => 0x8209, + 0xa9 => 0x64e0, 0xaa => 0x64e1, 0xab => 0x62ac, 0xac => 0x64e3, + 0xad => 0x64ef, 0xae => 0x652c, 0xaf => 0x64f6, 0xb0 => 0x64f4, + 0xb1 => 0x64f2, 0xb2 => 0x64fa, 0xb3 => 0x6500, 0xb4 => 0x64fd, + 0xb5 => 0x6518, 0xb6 => 0x651c, 0xb7 => 0x6505, 0xb8 => 0x6524, + 0xb9 => 0x6523, 0xba => 0x652b, 0xbb => 0x6534, 0xbc => 0x6535, + 0xbd => 0x6537, 0xbe => 0x6536, 0xbf => 0x6538, 0xc0 => 0x754b, + 0xc1 => 0x6548, 0xc2 => 0x6556, 0xc3 => 0x6555, 0xc4 => 0x654d, + 0xc5 => 0x6558, 0xc6 => 0x655e, 0xc7 => 0x655d, 0xc8 => 0x6572, + 0xc9 => 0x6578, 0xca => 0x6582, 0xcb => 0x6583, 0xcc => 0x8b8a, + 0xcd => 0x659b, 0xce => 0x659f, 0xcf => 0x65ab, 0xd0 => 0x65b7, + 0xd1 => 0x65c3, 0xd2 => 0x65c6, 0xd3 => 0x65c1, 0xd4 => 0x65c4, + 0xd5 => 0x65cc, 0xd6 => 0x65d2, 0xd7 => 0x65db, 0xd8 => 0x65d9, + 0xd9 => 0x65e0, 0xda => 0x65e1, 0xdb => 0x65f1, 0xdc => 0x6772, + 0xdd => 0x660a, 0xde => 0x6603, 0xdf => 0x65fb, 0xe0 => 0x6773, + 0xe1 => 0x6635, 0xe2 => 0x6636, 0xe3 => 0x6634, 0xe4 => 0x661c, + 0xe5 => 0x664f, 0xe6 => 0x6644, 0xe7 => 0x6649, 0xe8 => 0x6641, + 0xe9 => 0x665e, 0xea => 0x665d, 0xeb => 0x6664, 0xec => 0x6667, + 0xed => 0x6668, 0xee => 0x665f, 0xef => 0x6662, 0xf0 => 0x6670, + 0xf1 => 0x6683, 0xf2 => 0x6688, 0xf3 => 0x668e, 0xf4 => 0x6689, + 0xf5 => 0x6684, 0xf6 => 0x6698, 0xf7 => 0x669d, 0xf8 => 0x66c1, + 0xf9 => 0x66b9, 0xfa => 0x66c9, 0xfb => 0x66be, 0xfc => 0x66bc, + }, + 0x9e => { + 0x40 => 0x66c4, 0x41 => 0x66b8, 0x42 => 0x66d6, 0x43 => 0x66da, + 0x44 => 0x66e0, 0x45 => 0x663f, 0x46 => 0x66e6, 0x47 => 0x66e9, + 0x48 => 0x66f0, 0x49 => 0x66f5, 0x4a => 0x66f7, 0x4b => 0x670f, + 0x4c => 0x6716, 0x4d => 0x671e, 0x4e => 0x6726, 0x4f => 0x6727, + 0x50 => 0x9738, 0x51 => 0x672e, 0x52 => 0x673f, 0x53 => 0x6736, + 0x54 => 0x6741, 0x55 => 0x6738, 0x56 => 0x6737, 0x57 => 0x6746, + 0x58 => 0x675e, 0x59 => 0x6760, 0x5a => 0x6759, 0x5b => 0x6763, + 0x5c => 0x6764, 0x5d => 0x6789, 0x5e => 0x6770, 0x5f => 0x67a9, + 0x60 => 0x677c, 0x61 => 0x676a, 0x62 => 0x678c, 0x63 => 0x678b, + 0x64 => 0x67a6, 0x65 => 0x67a1, 0x66 => 0x6785, 0x67 => 0x67b7, + 0x68 => 0x67ef, 0x69 => 0x67b4, 0x6a => 0x67ec, 0x6b => 0x67b3, + 0x6c => 0x67e9, 0x6d => 0x67b8, 0x6e => 0x67e4, 0x6f => 0x67de, + 0x70 => 0x67dd, 0x71 => 0x67e2, 0x72 => 0x67ee, 0x73 => 0x67b9, + 0x74 => 0x67ce, 0x75 => 0x67c6, 0x76 => 0x67e7, 0x77 => 0x6a9c, + 0x78 => 0x681e, 0x79 => 0x6846, 0x7a => 0x6829, 0x7b => 0x6840, + 0x7c => 0x684d, 0x7d => 0x6832, 0x7e => 0x684e, 0x80 => 0x68b3, + 0x81 => 0x682b, 0x82 => 0x6859, 0x83 => 0x6863, 0x84 => 0x6877, + 0x85 => 0x687f, 0x86 => 0x689f, 0x87 => 0x688f, 0x88 => 0x68ad, + 0x89 => 0x6894, 0x8a => 0x689d, 0x8b => 0x689b, 0x8c => 0x6883, + 0x8d => 0x6aae, 0x8e => 0x68b9, 0x8f => 0x6874, 0x90 => 0x68b5, + 0x91 => 0x68a0, 0x92 => 0x68ba, 0x93 => 0x690f, 0x94 => 0x688d, + 0x95 => 0x687e, 0x96 => 0x6901, 0x97 => 0x68ca, 0x98 => 0x6908, + 0x99 => 0x68d8, 0x9a => 0x6922, 0x9b => 0x6926, 0x9c => 0x68e1, + 0x9d => 0x690c, 0x9e => 0x68cd, 0x9f => 0x68d4, 0xa0 => 0x68e7, + 0xa1 => 0x68d5, 0xa2 => 0x6936, 0xa3 => 0x6912, 0xa4 => 0x6904, + 0xa5 => 0x68d7, 0xa6 => 0x68e3, 0xa7 => 0x6925, 0xa8 => 0x68f9, + 0xa9 => 0x68e0, 0xaa => 0x68ef, 0xab => 0x6928, 0xac => 0x692a, + 0xad => 0x691a, 0xae => 0x6923, 0xaf => 0x6921, 0xb0 => 0x68c6, + 0xb1 => 0x6979, 0xb2 => 0x6977, 0xb3 => 0x695c, 0xb4 => 0x6978, + 0xb5 => 0x696b, 0xb6 => 0x6954, 0xb7 => 0x697e, 0xb8 => 0x696e, + 0xb9 => 0x6939, 0xba => 0x6974, 0xbb => 0x693d, 0xbc => 0x6959, + 0xbd => 0x6930, 0xbe => 0x6961, 0xbf => 0x695e, 0xc0 => 0x695d, + 0xc1 => 0x6981, 0xc2 => 0x696a, 0xc3 => 0x69b2, 0xc4 => 0x69ae, + 0xc5 => 0x69d0, 0xc6 => 0x69bf, 0xc7 => 0x69c1, 0xc8 => 0x69d3, + 0xc9 => 0x69be, 0xca => 0x69ce, 0xcb => 0x5be8, 0xcc => 0x69ca, + 0xcd => 0x69dd, 0xce => 0x69bb, 0xcf => 0x69c3, 0xd0 => 0x69a7, + 0xd1 => 0x6a2e, 0xd2 => 0x6991, 0xd3 => 0x69a0, 0xd4 => 0x699c, + 0xd5 => 0x6995, 0xd6 => 0x69b4, 0xd7 => 0x69de, 0xd8 => 0x69e8, + 0xd9 => 0x6a02, 0xda => 0x6a1b, 0xdb => 0x69ff, 0xdc => 0x6b0a, + 0xdd => 0x69f9, 0xde => 0x69f2, 0xdf => 0x69e7, 0xe0 => 0x6a05, + 0xe1 => 0x69b1, 0xe2 => 0x6a1e, 0xe3 => 0x69ed, 0xe4 => 0x6a14, + 0xe5 => 0x69eb, 0xe6 => 0x6a0a, 0xe7 => 0x6a12, 0xe8 => 0x6ac1, + 0xe9 => 0x6a23, 0xea => 0x6a13, 0xeb => 0x6a44, 0xec => 0x6a0c, + 0xed => 0x6a72, 0xee => 0x6a36, 0xef => 0x6a78, 0xf0 => 0x6a47, + 0xf1 => 0x6a62, 0xf2 => 0x6a59, 0xf3 => 0x6a66, 0xf4 => 0x6a48, + 0xf5 => 0x6a38, 0xf6 => 0x6a22, 0xf7 => 0x6a90, 0xf8 => 0x6a8d, + 0xf9 => 0x6aa0, 0xfa => 0x6a84, 0xfb => 0x6aa2, 0xfc => 0x6aa3, + }, + 0x9f => { + 0x40 => 0x6a97, 0x41 => 0x8617, 0x42 => 0x6abb, 0x43 => 0x6ac3, + 0x44 => 0x6ac2, 0x45 => 0x6ab8, 0x46 => 0x6ab3, 0x47 => 0x6aac, + 0x48 => 0x6ade, 0x49 => 0x6ad1, 0x4a => 0x6adf, 0x4b => 0x6aaa, + 0x4c => 0x6ada, 0x4d => 0x6aea, 0x4e => 0x6afb, 0x4f => 0x6b05, + 0x50 => 0x8616, 0x51 => 0x6afa, 0x52 => 0x6b12, 0x53 => 0x6b16, + 0x54 => 0x9b31, 0x55 => 0x6b1f, 0x56 => 0x6b38, 0x57 => 0x6b37, + 0x58 => 0x76dc, 0x59 => 0x6b39, 0x5a => 0x98ee, 0x5b => 0x6b47, + 0x5c => 0x6b43, 0x5d => 0x6b49, 0x5e => 0x6b50, 0x5f => 0x6b59, + 0x60 => 0x6b54, 0x61 => 0x6b5b, 0x62 => 0x6b5f, 0x63 => 0x6b61, + 0x64 => 0x6b78, 0x65 => 0x6b79, 0x66 => 0x6b7f, 0x67 => 0x6b80, + 0x68 => 0x6b84, 0x69 => 0x6b83, 0x6a => 0x6b8d, 0x6b => 0x6b98, + 0x6c => 0x6b95, 0x6d => 0x6b9e, 0x6e => 0x6ba4, 0x6f => 0x6baa, + 0x70 => 0x6bab, 0x71 => 0x6baf, 0x72 => 0x6bb2, 0x73 => 0x6bb1, + 0x74 => 0x6bb3, 0x75 => 0x6bb7, 0x76 => 0x6bbc, 0x77 => 0x6bc6, + 0x78 => 0x6bcb, 0x79 => 0x6bd3, 0x7a => 0x6bdf, 0x7b => 0x6bec, + 0x7c => 0x6beb, 0x7d => 0x6bf3, 0x7e => 0x6bef, 0x80 => 0x9ebe, + 0x81 => 0x6c08, 0x82 => 0x6c13, 0x83 => 0x6c14, 0x84 => 0x6c1b, + 0x85 => 0x6c24, 0x86 => 0x6c23, 0x87 => 0x6c5e, 0x88 => 0x6c55, + 0x89 => 0x6c62, 0x8a => 0x6c6a, 0x8b => 0x6c82, 0x8c => 0x6c8d, + 0x8d => 0x6c9a, 0x8e => 0x6c81, 0x8f => 0x6c9b, 0x90 => 0x6c7e, + 0x91 => 0x6c68, 0x92 => 0x6c73, 0x93 => 0x6c92, 0x94 => 0x6c90, + 0x95 => 0x6cc4, 0x96 => 0x6cf1, 0x97 => 0x6cd3, 0x98 => 0x6cbd, + 0x99 => 0x6cd7, 0x9a => 0x6cc5, 0x9b => 0x6cdd, 0x9c => 0x6cae, + 0x9d => 0x6cb1, 0x9e => 0x6cbe, 0x9f => 0x6cba, 0xa0 => 0x6cdb, + 0xa1 => 0x6cef, 0xa2 => 0x6cd9, 0xa3 => 0x6cea, 0xa4 => 0x6d1f, + 0xa5 => 0x884d, 0xa6 => 0x6d36, 0xa7 => 0x6d2b, 0xa8 => 0x6d3d, + 0xa9 => 0x6d38, 0xaa => 0x6d19, 0xab => 0x6d35, 0xac => 0x6d33, + 0xad => 0x6d12, 0xae => 0x6d0c, 0xaf => 0x6d63, 0xb0 => 0x6d93, + 0xb1 => 0x6d64, 0xb2 => 0x6d5a, 0xb3 => 0x6d79, 0xb4 => 0x6d59, + 0xb5 => 0x6d8e, 0xb6 => 0x6d95, 0xb7 => 0x6fe4, 0xb8 => 0x6d85, + 0xb9 => 0x6df9, 0xba => 0x6e15, 0xbb => 0x6e0a, 0xbc => 0x6db5, + 0xbd => 0x6dc7, 0xbe => 0x6de6, 0xbf => 0x6db8, 0xc0 => 0x6dc6, + 0xc1 => 0x6dec, 0xc2 => 0x6dde, 0xc3 => 0x6dcc, 0xc4 => 0x6de8, + 0xc5 => 0x6dd2, 0xc6 => 0x6dc5, 0xc7 => 0x6dfa, 0xc8 => 0x6dd9, + 0xc9 => 0x6de4, 0xca => 0x6dd5, 0xcb => 0x6dea, 0xcc => 0x6dee, + 0xcd => 0x6e2d, 0xce => 0x6e6e, 0xcf => 0x6e2e, 0xd0 => 0x6e19, + 0xd1 => 0x6e72, 0xd2 => 0x6e5f, 0xd3 => 0x6e3e, 0xd4 => 0x6e23, + 0xd5 => 0x6e6b, 0xd6 => 0x6e2b, 0xd7 => 0x6e76, 0xd8 => 0x6e4d, + 0xd9 => 0x6e1f, 0xda => 0x6e43, 0xdb => 0x6e3a, 0xdc => 0x6e4e, + 0xdd => 0x6e24, 0xde => 0x6eff, 0xdf => 0x6e1d, 0xe0 => 0x6e38, + 0xe1 => 0x6e82, 0xe2 => 0x6eaa, 0xe3 => 0x6e98, 0xe4 => 0x6ec9, + 0xe5 => 0x6eb7, 0xe6 => 0x6ed3, 0xe7 => 0x6ebd, 0xe8 => 0x6eaf, + 0xe9 => 0x6ec4, 0xea => 0x6eb2, 0xeb => 0x6ed4, 0xec => 0x6ed5, + 0xed => 0x6e8f, 0xee => 0x6ea5, 0xef => 0x6ec2, 0xf0 => 0x6e9f, + 0xf1 => 0x6f41, 0xf2 => 0x6f11, 0xf3 => 0x704c, 0xf4 => 0x6eec, + 0xf5 => 0x6ef8, 0xf6 => 0x6efe, 0xf7 => 0x6f3f, 0xf8 => 0x6ef2, + 0xf9 => 0x6f31, 0xfa => 0x6eef, 0xfb => 0x6f32, 0xfc => 0x6ecc, + }, + 0xe0 => { + 0x40 => 0x6f3e, 0x41 => 0x6f13, 0x42 => 0x6ef7, 0x43 => 0x6f86, + 0x44 => 0x6f7a, 0x45 => 0x6f78, 0x46 => 0x6f81, 0x47 => 0x6f80, + 0x48 => 0x6f6f, 0x49 => 0x6f5b, 0x4a => 0x6ff3, 0x4b => 0x6f6d, + 0x4c => 0x6f82, 0x4d => 0x6f7c, 0x4e => 0x6f58, 0x4f => 0x6f8e, + 0x50 => 0x6f91, 0x51 => 0x6fc2, 0x52 => 0x6f66, 0x53 => 0x6fb3, + 0x54 => 0x6fa3, 0x55 => 0x6fa1, 0x56 => 0x6fa4, 0x57 => 0x6fb9, + 0x58 => 0x6fc6, 0x59 => 0x6faa, 0x5a => 0x6fdf, 0x5b => 0x6fd5, + 0x5c => 0x6fec, 0x5d => 0x6fd4, 0x5e => 0x6fd8, 0x5f => 0x6ff1, + 0x60 => 0x6fee, 0x61 => 0x6fdb, 0x62 => 0x7009, 0x63 => 0x700b, + 0x64 => 0x6ffa, 0x65 => 0x7011, 0x66 => 0x7001, 0x67 => 0x700f, + 0x68 => 0x6ffe, 0x69 => 0x701b, 0x6a => 0x701a, 0x6b => 0x6f74, + 0x6c => 0x701d, 0x6d => 0x7018, 0x6e => 0x701f, 0x6f => 0x7030, + 0x70 => 0x703e, 0x71 => 0x7032, 0x72 => 0x7051, 0x73 => 0x7063, + 0x74 => 0x7099, 0x75 => 0x7092, 0x76 => 0x70af, 0x77 => 0x70f1, + 0x78 => 0x70ac, 0x79 => 0x70b8, 0x7a => 0x70b3, 0x7b => 0x70ae, + 0x7c => 0x70df, 0x7d => 0x70cb, 0x7e => 0x70dd, 0x80 => 0x70d9, + 0x81 => 0x7109, 0x82 => 0x70fd, 0x83 => 0x711c, 0x84 => 0x7119, + 0x85 => 0x7165, 0x86 => 0x7155, 0x87 => 0x7188, 0x88 => 0x7166, + 0x89 => 0x7162, 0x8a => 0x714c, 0x8b => 0x7156, 0x8c => 0x716c, + 0x8d => 0x718f, 0x8e => 0x71fb, 0x8f => 0x7184, 0x90 => 0x7195, + 0x91 => 0x71a8, 0x92 => 0x71ac, 0x93 => 0x71d7, 0x94 => 0x71b9, + 0x95 => 0x71be, 0x96 => 0x71d2, 0x97 => 0x71c9, 0x98 => 0x71d4, + 0x99 => 0x71ce, 0x9a => 0x71e0, 0x9b => 0x71ec, 0x9c => 0x71e7, + 0x9d => 0x71f5, 0x9e => 0x71fc, 0x9f => 0x71f9, 0xa0 => 0x71ff, + 0xa1 => 0x720d, 0xa2 => 0x7210, 0xa3 => 0x721b, 0xa4 => 0x7228, + 0xa5 => 0x722d, 0xa6 => 0x722c, 0xa7 => 0x7230, 0xa8 => 0x7232, + 0xa9 => 0x723b, 0xaa => 0x723c, 0xab => 0x723f, 0xac => 0x7240, + 0xad => 0x7246, 0xae => 0x724b, 0xaf => 0x7258, 0xb0 => 0x7274, + 0xb1 => 0x727e, 0xb2 => 0x7282, 0xb3 => 0x7281, 0xb4 => 0x7287, + 0xb5 => 0x7292, 0xb6 => 0x7296, 0xb7 => 0x72a2, 0xb8 => 0x72a7, + 0xb9 => 0x72b9, 0xba => 0x72b2, 0xbb => 0x72c3, 0xbc => 0x72c6, + 0xbd => 0x72c4, 0xbe => 0x72ce, 0xbf => 0x72d2, 0xc0 => 0x72e2, + 0xc1 => 0x72e0, 0xc2 => 0x72e1, 0xc3 => 0x72f9, 0xc4 => 0x72f7, + 0xc5 => 0x500f, 0xc6 => 0x7317, 0xc7 => 0x730a, 0xc8 => 0x731c, + 0xc9 => 0x7316, 0xca => 0x731d, 0xcb => 0x7334, 0xcc => 0x732f, + 0xcd => 0x7329, 0xce => 0x7325, 0xcf => 0x733e, 0xd0 => 0x734e, + 0xd1 => 0x734f, 0xd2 => 0x9ed8, 0xd3 => 0x7357, 0xd4 => 0x736a, + 0xd5 => 0x7368, 0xd6 => 0x7370, 0xd7 => 0x7378, 0xd8 => 0x7375, + 0xd9 => 0x737b, 0xda => 0x737a, 0xdb => 0x73c8, 0xdc => 0x73b3, + 0xdd => 0x73ce, 0xde => 0x73bb, 0xdf => 0x73c0, 0xe0 => 0x73e5, + 0xe1 => 0x73ee, 0xe2 => 0x73de, 0xe3 => 0x74a2, 0xe4 => 0x7405, + 0xe5 => 0x746f, 0xe6 => 0x7425, 0xe7 => 0x73f8, 0xe8 => 0x7432, + 0xe9 => 0x743a, 0xea => 0x7455, 0xeb => 0x743f, 0xec => 0x745f, + 0xed => 0x7459, 0xee => 0x7441, 0xef => 0x745c, 0xf0 => 0x7469, + 0xf1 => 0x7470, 0xf2 => 0x7463, 0xf3 => 0x746a, 0xf4 => 0x7476, + 0xf5 => 0x747e, 0xf6 => 0x748b, 0xf7 => 0x749e, 0xf8 => 0x74a7, + 0xf9 => 0x74ca, 0xfa => 0x74cf, 0xfb => 0x74d4, 0xfc => 0x73f1, + }, + 0xe1 => { + 0x40 => 0x74e0, 0x41 => 0x74e3, 0x42 => 0x74e7, 0x43 => 0x74e9, + 0x44 => 0x74ee, 0x45 => 0x74f2, 0x46 => 0x74f0, 0x47 => 0x74f1, + 0x48 => 0x74f8, 0x49 => 0x74f7, 0x4a => 0x7504, 0x4b => 0x7503, + 0x4c => 0x7505, 0x4d => 0x750c, 0x4e => 0x750e, 0x4f => 0x750d, + 0x50 => 0x7515, 0x51 => 0x7513, 0x52 => 0x751e, 0x53 => 0x7526, + 0x54 => 0x752c, 0x55 => 0x753c, 0x56 => 0x7544, 0x57 => 0x754d, + 0x58 => 0x754a, 0x59 => 0x7549, 0x5a => 0x755b, 0x5b => 0x7546, + 0x5c => 0x755a, 0x5d => 0x7569, 0x5e => 0x7564, 0x5f => 0x7567, + 0x60 => 0x756b, 0x61 => 0x756d, 0x62 => 0x7578, 0x63 => 0x7576, + 0x64 => 0x7586, 0x65 => 0x7587, 0x66 => 0x7574, 0x67 => 0x758a, + 0x68 => 0x7589, 0x69 => 0x7582, 0x6a => 0x7594, 0x6b => 0x759a, + 0x6c => 0x759d, 0x6d => 0x75a5, 0x6e => 0x75a3, 0x6f => 0x75c2, + 0x70 => 0x75b3, 0x71 => 0x75c3, 0x72 => 0x75b5, 0x73 => 0x75bd, + 0x74 => 0x75b8, 0x75 => 0x75bc, 0x76 => 0x75b1, 0x77 => 0x75cd, + 0x78 => 0x75ca, 0x79 => 0x75d2, 0x7a => 0x75d9, 0x7b => 0x75e3, + 0x7c => 0x75de, 0x7d => 0x75fe, 0x7e => 0x75ff, 0x80 => 0x75fc, + 0x81 => 0x7601, 0x82 => 0x75f0, 0x83 => 0x75fa, 0x84 => 0x75f2, + 0x85 => 0x75f3, 0x86 => 0x760b, 0x87 => 0x760d, 0x88 => 0x7609, + 0x89 => 0x761f, 0x8a => 0x7627, 0x8b => 0x7620, 0x8c => 0x7621, + 0x8d => 0x7622, 0x8e => 0x7624, 0x8f => 0x7634, 0x90 => 0x7630, + 0x91 => 0x763b, 0x92 => 0x7647, 0x93 => 0x7648, 0x94 => 0x7646, + 0x95 => 0x765c, 0x96 => 0x7658, 0x97 => 0x7661, 0x98 => 0x7662, + 0x99 => 0x7668, 0x9a => 0x7669, 0x9b => 0x766a, 0x9c => 0x7667, + 0x9d => 0x766c, 0x9e => 0x7670, 0x9f => 0x7672, 0xa0 => 0x7676, + 0xa1 => 0x7678, 0xa2 => 0x767c, 0xa3 => 0x7680, 0xa4 => 0x7683, + 0xa5 => 0x7688, 0xa6 => 0x768b, 0xa7 => 0x768e, 0xa8 => 0x7696, + 0xa9 => 0x7693, 0xaa => 0x7699, 0xab => 0x769a, 0xac => 0x76b0, + 0xad => 0x76b4, 0xae => 0x76b8, 0xaf => 0x76b9, 0xb0 => 0x76ba, + 0xb1 => 0x76c2, 0xb2 => 0x76cd, 0xb3 => 0x76d6, 0xb4 => 0x76d2, + 0xb5 => 0x76de, 0xb6 => 0x76e1, 0xb7 => 0x76e5, 0xb8 => 0x76e7, + 0xb9 => 0x76ea, 0xba => 0x862f, 0xbb => 0x76fb, 0xbc => 0x7708, + 0xbd => 0x7707, 0xbe => 0x7704, 0xbf => 0x7729, 0xc0 => 0x7724, + 0xc1 => 0x771e, 0xc2 => 0x7725, 0xc3 => 0x7726, 0xc4 => 0x771b, + 0xc5 => 0x7737, 0xc6 => 0x7738, 0xc7 => 0x7747, 0xc8 => 0x775a, + 0xc9 => 0x7768, 0xca => 0x776b, 0xcb => 0x775b, 0xcc => 0x7765, + 0xcd => 0x777f, 0xce => 0x777e, 0xcf => 0x7779, 0xd0 => 0x778e, + 0xd1 => 0x778b, 0xd2 => 0x7791, 0xd3 => 0x77a0, 0xd4 => 0x779e, + 0xd5 => 0x77b0, 0xd6 => 0x77b6, 0xd7 => 0x77b9, 0xd8 => 0x77bf, + 0xd9 => 0x77bc, 0xda => 0x77bd, 0xdb => 0x77bb, 0xdc => 0x77c7, + 0xdd => 0x77cd, 0xde => 0x77d7, 0xdf => 0x77da, 0xe0 => 0x77dc, + 0xe1 => 0x77e3, 0xe2 => 0x77ee, 0xe3 => 0x77fc, 0xe4 => 0x780c, + 0xe5 => 0x7812, 0xe6 => 0x7926, 0xe7 => 0x7820, 0xe8 => 0x792a, + 0xe9 => 0x7845, 0xea => 0x788e, 0xeb => 0x7874, 0xec => 0x7886, + 0xed => 0x787c, 0xee => 0x789a, 0xef => 0x788c, 0xf0 => 0x78a3, + 0xf1 => 0x78b5, 0xf2 => 0x78aa, 0xf3 => 0x78af, 0xf4 => 0x78d1, + 0xf5 => 0x78c6, 0xf6 => 0x78cb, 0xf7 => 0x78d4, 0xf8 => 0x78be, + 0xf9 => 0x78bc, 0xfa => 0x78c5, 0xfb => 0x78ca, 0xfc => 0x78ec, + }, + 0xe2 => { + 0x40 => 0x78e7, 0x41 => 0x78da, 0x42 => 0x78fd, 0x43 => 0x78f4, + 0x44 => 0x7907, 0x45 => 0x7912, 0x46 => 0x7911, 0x47 => 0x7919, + 0x48 => 0x792c, 0x49 => 0x792b, 0x4a => 0x7940, 0x4b => 0x7960, + 0x4c => 0x7957, 0x4d => 0x795f, 0x4e => 0x795a, 0x4f => 0x7955, + 0x50 => 0x7953, 0x51 => 0x797a, 0x52 => 0x797f, 0x53 => 0x798a, + 0x54 => 0x799d, 0x55 => 0x79a7, 0x56 => 0x9f4b, 0x57 => 0x79aa, + 0x58 => 0x79ae, 0x59 => 0x79b3, 0x5a => 0x79b9, 0x5b => 0x79ba, + 0x5c => 0x79c9, 0x5d => 0x79d5, 0x5e => 0x79e7, 0x5f => 0x79ec, + 0x60 => 0x79e1, 0x61 => 0x79e3, 0x62 => 0x7a08, 0x63 => 0x7a0d, + 0x64 => 0x7a18, 0x65 => 0x7a19, 0x66 => 0x7a20, 0x67 => 0x7a1f, + 0x68 => 0x7980, 0x69 => 0x7a31, 0x6a => 0x7a3b, 0x6b => 0x7a3e, + 0x6c => 0x7a37, 0x6d => 0x7a43, 0x6e => 0x7a57, 0x6f => 0x7a49, + 0x70 => 0x7a61, 0x71 => 0x7a62, 0x72 => 0x7a69, 0x73 => 0x9f9d, + 0x74 => 0x7a70, 0x75 => 0x7a79, 0x76 => 0x7a7d, 0x77 => 0x7a88, + 0x78 => 0x7a97, 0x79 => 0x7a95, 0x7a => 0x7a98, 0x7b => 0x7a96, + 0x7c => 0x7aa9, 0x7d => 0x7ac8, 0x7e => 0x7ab0, 0x80 => 0x7ab6, + 0x81 => 0x7ac5, 0x82 => 0x7ac4, 0x83 => 0x7abf, 0x84 => 0x9083, + 0x85 => 0x7ac7, 0x86 => 0x7aca, 0x87 => 0x7acd, 0x88 => 0x7acf, + 0x89 => 0x7ad5, 0x8a => 0x7ad3, 0x8b => 0x7ad9, 0x8c => 0x7ada, + 0x8d => 0x7add, 0x8e => 0x7ae1, 0x8f => 0x7ae2, 0x90 => 0x7ae6, + 0x91 => 0x7aed, 0x92 => 0x7af0, 0x93 => 0x7b02, 0x94 => 0x7b0f, + 0x95 => 0x7b0a, 0x96 => 0x7b06, 0x97 => 0x7b33, 0x98 => 0x7b18, + 0x99 => 0x7b19, 0x9a => 0x7b1e, 0x9b => 0x7b35, 0x9c => 0x7b28, + 0x9d => 0x7b36, 0x9e => 0x7b50, 0x9f => 0x7b7a, 0xa0 => 0x7b04, + 0xa1 => 0x7b4d, 0xa2 => 0x7b0b, 0xa3 => 0x7b4c, 0xa4 => 0x7b45, + 0xa5 => 0x7b75, 0xa6 => 0x7b65, 0xa7 => 0x7b74, 0xa8 => 0x7b67, + 0xa9 => 0x7b70, 0xaa => 0x7b71, 0xab => 0x7b6c, 0xac => 0x7b6e, + 0xad => 0x7b9d, 0xae => 0x7b98, 0xaf => 0x7b9f, 0xb0 => 0x7b8d, + 0xb1 => 0x7b9c, 0xb2 => 0x7b9a, 0xb3 => 0x7b8b, 0xb4 => 0x7b92, + 0xb5 => 0x7b8f, 0xb6 => 0x7b5d, 0xb7 => 0x7b99, 0xb8 => 0x7bcb, + 0xb9 => 0x7bc1, 0xba => 0x7bcc, 0xbb => 0x7bcf, 0xbc => 0x7bb4, + 0xbd => 0x7bc6, 0xbe => 0x7bdd, 0xbf => 0x7be9, 0xc0 => 0x7c11, + 0xc1 => 0x7c14, 0xc2 => 0x7be6, 0xc3 => 0x7be5, 0xc4 => 0x7c60, + 0xc5 => 0x7c00, 0xc6 => 0x7c07, 0xc7 => 0x7c13, 0xc8 => 0x7bf3, + 0xc9 => 0x7bf7, 0xca => 0x7c17, 0xcb => 0x7c0d, 0xcc => 0x7bf6, + 0xcd => 0x7c23, 0xce => 0x7c27, 0xcf => 0x7c2a, 0xd0 => 0x7c1f, + 0xd1 => 0x7c37, 0xd2 => 0x7c2b, 0xd3 => 0x7c3d, 0xd4 => 0x7c4c, + 0xd5 => 0x7c43, 0xd6 => 0x7c54, 0xd7 => 0x7c4f, 0xd8 => 0x7c40, + 0xd9 => 0x7c50, 0xda => 0x7c58, 0xdb => 0x7c5f, 0xdc => 0x7c64, + 0xdd => 0x7c56, 0xde => 0x7c65, 0xdf => 0x7c6c, 0xe0 => 0x7c75, + 0xe1 => 0x7c83, 0xe2 => 0x7c90, 0xe3 => 0x7ca4, 0xe4 => 0x7cad, + 0xe5 => 0x7ca2, 0xe6 => 0x7cab, 0xe7 => 0x7ca1, 0xe8 => 0x7ca8, + 0xe9 => 0x7cb3, 0xea => 0x7cb2, 0xeb => 0x7cb1, 0xec => 0x7cae, + 0xed => 0x7cb9, 0xee => 0x7cbd, 0xef => 0x7cc0, 0xf0 => 0x7cc5, + 0xf1 => 0x7cc2, 0xf2 => 0x7cd8, 0xf3 => 0x7cd2, 0xf4 => 0x7cdc, + 0xf5 => 0x7ce2, 0xf6 => 0x9b3b, 0xf7 => 0x7cef, 0xf8 => 0x7cf2, + 0xf9 => 0x7cf4, 0xfa => 0x7cf6, 0xfb => 0x7cfa, 0xfc => 0x7d06, + }, + 0xe3 => { + 0x40 => 0x7d02, 0x41 => 0x7d1c, 0x42 => 0x7d15, 0x43 => 0x7d0a, + 0x44 => 0x7d45, 0x45 => 0x7d4b, 0x46 => 0x7d2e, 0x47 => 0x7d32, + 0x48 => 0x7d3f, 0x49 => 0x7d35, 0x4a => 0x7d46, 0x4b => 0x7d73, + 0x4c => 0x7d56, 0x4d => 0x7d4e, 0x4e => 0x7d72, 0x4f => 0x7d68, + 0x50 => 0x7d6e, 0x51 => 0x7d4f, 0x52 => 0x7d63, 0x53 => 0x7d93, + 0x54 => 0x7d89, 0x55 => 0x7d5b, 0x56 => 0x7d8f, 0x57 => 0x7d7d, + 0x58 => 0x7d9b, 0x59 => 0x7dba, 0x5a => 0x7dae, 0x5b => 0x7da3, + 0x5c => 0x7db5, 0x5d => 0x7dc7, 0x5e => 0x7dbd, 0x5f => 0x7dab, + 0x60 => 0x7e3d, 0x61 => 0x7da2, 0x62 => 0x7daf, 0x63 => 0x7ddc, + 0x64 => 0x7db8, 0x65 => 0x7d9f, 0x66 => 0x7db0, 0x67 => 0x7dd8, + 0x68 => 0x7ddd, 0x69 => 0x7de4, 0x6a => 0x7dde, 0x6b => 0x7dfb, + 0x6c => 0x7df2, 0x6d => 0x7de1, 0x6e => 0x7e05, 0x6f => 0x7e0a, + 0x70 => 0x7e23, 0x71 => 0x7e21, 0x72 => 0x7e12, 0x73 => 0x7e31, + 0x74 => 0x7e1f, 0x75 => 0x7e09, 0x76 => 0x7e0b, 0x77 => 0x7e22, + 0x78 => 0x7e46, 0x79 => 0x7e66, 0x7a => 0x7e3b, 0x7b => 0x7e35, + 0x7c => 0x7e39, 0x7d => 0x7e43, 0x7e => 0x7e37, 0x80 => 0x7e32, + 0x81 => 0x7e3a, 0x82 => 0x7e67, 0x83 => 0x7e5d, 0x84 => 0x7e56, + 0x85 => 0x7e5e, 0x86 => 0x7e59, 0x87 => 0x7e5a, 0x88 => 0x7e79, + 0x89 => 0x7e6a, 0x8a => 0x7e69, 0x8b => 0x7e7c, 0x8c => 0x7e7b, + 0x8d => 0x7e83, 0x8e => 0x7dd5, 0x8f => 0x7e7d, 0x90 => 0x8fae, + 0x91 => 0x7e7f, 0x92 => 0x7e88, 0x93 => 0x7e89, 0x94 => 0x7e8c, + 0x95 => 0x7e92, 0x96 => 0x7e90, 0x97 => 0x7e93, 0x98 => 0x7e94, + 0x99 => 0x7e96, 0x9a => 0x7e8e, 0x9b => 0x7e9b, 0x9c => 0x7e9c, + 0x9d => 0x7f38, 0x9e => 0x7f3a, 0x9f => 0x7f45, 0xa0 => 0x7f4c, + 0xa1 => 0x7f4d, 0xa2 => 0x7f4e, 0xa3 => 0x7f50, 0xa4 => 0x7f51, + 0xa5 => 0x7f55, 0xa6 => 0x7f54, 0xa7 => 0x7f58, 0xa8 => 0x7f5f, + 0xa9 => 0x7f60, 0xaa => 0x7f68, 0xab => 0x7f69, 0xac => 0x7f67, + 0xad => 0x7f78, 0xae => 0x7f82, 0xaf => 0x7f86, 0xb0 => 0x7f83, + 0xb1 => 0x7f88, 0xb2 => 0x7f87, 0xb3 => 0x7f8c, 0xb4 => 0x7f94, + 0xb5 => 0x7f9e, 0xb6 => 0x7f9d, 0xb7 => 0x7f9a, 0xb8 => 0x7fa3, + 0xb9 => 0x7faf, 0xba => 0x7fb2, 0xbb => 0x7fb9, 0xbc => 0x7fae, + 0xbd => 0x7fb6, 0xbe => 0x7fb8, 0xbf => 0x8b71, 0xc0 => 0x7fc5, + 0xc1 => 0x7fc6, 0xc2 => 0x7fca, 0xc3 => 0x7fd5, 0xc4 => 0x7fd4, + 0xc5 => 0x7fe1, 0xc6 => 0x7fe6, 0xc7 => 0x7fe9, 0xc8 => 0x7ff3, + 0xc9 => 0x7ff9, 0xca => 0x98dc, 0xcb => 0x8006, 0xcc => 0x8004, + 0xcd => 0x800b, 0xce => 0x8012, 0xcf => 0x8018, 0xd0 => 0x8019, + 0xd1 => 0x801c, 0xd2 => 0x8021, 0xd3 => 0x8028, 0xd4 => 0x803f, + 0xd5 => 0x803b, 0xd6 => 0x804a, 0xd7 => 0x8046, 0xd8 => 0x8052, + 0xd9 => 0x8058, 0xda => 0x805a, 0xdb => 0x805f, 0xdc => 0x8062, + 0xdd => 0x8068, 0xde => 0x8073, 0xdf => 0x8072, 0xe0 => 0x8070, + 0xe1 => 0x8076, 0xe2 => 0x8079, 0xe3 => 0x807d, 0xe4 => 0x807f, + 0xe5 => 0x8084, 0xe6 => 0x8086, 0xe7 => 0x8085, 0xe8 => 0x809b, + 0xe9 => 0x8093, 0xea => 0x809a, 0xeb => 0x80ad, 0xec => 0x5190, + 0xed => 0x80ac, 0xee => 0x80db, 0xef => 0x80e5, 0xf0 => 0x80d9, + 0xf1 => 0x80dd, 0xf2 => 0x80c4, 0xf3 => 0x80da, 0xf4 => 0x80d6, + 0xf5 => 0x8109, 0xf6 => 0x80ef, 0xf7 => 0x80f1, 0xf8 => 0x811b, + 0xf9 => 0x8129, 0xfa => 0x8123, 0xfb => 0x812f, 0xfc => 0x814b, + }, + 0xe4 => { + 0x40 => 0x968b, 0x41 => 0x8146, 0x42 => 0x813e, 0x43 => 0x8153, + 0x44 => 0x8151, 0x45 => 0x80fc, 0x46 => 0x8171, 0x47 => 0x816e, + 0x48 => 0x8165, 0x49 => 0x8166, 0x4a => 0x8174, 0x4b => 0x8183, + 0x4c => 0x8188, 0x4d => 0x818a, 0x4e => 0x8180, 0x4f => 0x8182, + 0x50 => 0x81a0, 0x51 => 0x8195, 0x52 => 0x81a4, 0x53 => 0x81a3, + 0x54 => 0x815f, 0x55 => 0x8193, 0x56 => 0x81a9, 0x57 => 0x81b0, + 0x58 => 0x81b5, 0x59 => 0x81be, 0x5a => 0x81b8, 0x5b => 0x81bd, + 0x5c => 0x81c0, 0x5d => 0x81c2, 0x5e => 0x81ba, 0x5f => 0x81c9, + 0x60 => 0x81cd, 0x61 => 0x81d1, 0x62 => 0x81d9, 0x63 => 0x81d8, + 0x64 => 0x81c8, 0x65 => 0x81da, 0x66 => 0x81df, 0x67 => 0x81e0, + 0x68 => 0x81e7, 0x69 => 0x81fa, 0x6a => 0x81fb, 0x6b => 0x81fe, + 0x6c => 0x8201, 0x6d => 0x8202, 0x6e => 0x8205, 0x6f => 0x8207, + 0x70 => 0x820a, 0x71 => 0x820d, 0x72 => 0x8210, 0x73 => 0x8216, + 0x74 => 0x8229, 0x75 => 0x822b, 0x76 => 0x8238, 0x77 => 0x8233, + 0x78 => 0x8240, 0x79 => 0x8259, 0x7a => 0x8258, 0x7b => 0x825d, + 0x7c => 0x825a, 0x7d => 0x825f, 0x7e => 0x8264, 0x80 => 0x8262, + 0x81 => 0x8268, 0x82 => 0x826a, 0x83 => 0x826b, 0x84 => 0x822e, + 0x85 => 0x8271, 0x86 => 0x8277, 0x87 => 0x8278, 0x88 => 0x827e, + 0x89 => 0x828d, 0x8a => 0x8292, 0x8b => 0x82ab, 0x8c => 0x829f, + 0x8d => 0x82bb, 0x8e => 0x82ac, 0x8f => 0x82e1, 0x90 => 0x82e3, + 0x91 => 0x82df, 0x92 => 0x82d2, 0x93 => 0x82f4, 0x94 => 0x82f3, + 0x95 => 0x82fa, 0x96 => 0x8393, 0x97 => 0x8303, 0x98 => 0x82fb, + 0x99 => 0x82f9, 0x9a => 0x82de, 0x9b => 0x8306, 0x9c => 0x82dc, + 0x9d => 0x8309, 0x9e => 0x82d9, 0x9f => 0x8335, 0xa0 => 0x8334, + 0xa1 => 0x8316, 0xa2 => 0x8332, 0xa3 => 0x8331, 0xa4 => 0x8340, + 0xa5 => 0x8339, 0xa6 => 0x8350, 0xa7 => 0x8345, 0xa8 => 0x832f, + 0xa9 => 0x832b, 0xaa => 0x8317, 0xab => 0x8318, 0xac => 0x8385, + 0xad => 0x839a, 0xae => 0x83aa, 0xaf => 0x839f, 0xb0 => 0x83a2, + 0xb1 => 0x8396, 0xb2 => 0x8323, 0xb3 => 0x838e, 0xb4 => 0x8387, + 0xb5 => 0x838a, 0xb6 => 0x837c, 0xb7 => 0x83b5, 0xb8 => 0x8373, + 0xb9 => 0x8375, 0xba => 0x83a0, 0xbb => 0x8389, 0xbc => 0x83a8, + 0xbd => 0x83f4, 0xbe => 0x8413, 0xbf => 0x83eb, 0xc0 => 0x83ce, + 0xc1 => 0x83fd, 0xc2 => 0x8403, 0xc3 => 0x83d8, 0xc4 => 0x840b, + 0xc5 => 0x83c1, 0xc6 => 0x83f7, 0xc7 => 0x8407, 0xc8 => 0x83e0, + 0xc9 => 0x83f2, 0xca => 0x840d, 0xcb => 0x8422, 0xcc => 0x8420, + 0xcd => 0x83bd, 0xce => 0x8438, 0xcf => 0x8506, 0xd0 => 0x83fb, + 0xd1 => 0x846d, 0xd2 => 0x842a, 0xd3 => 0x843c, 0xd4 => 0x855a, + 0xd5 => 0x8484, 0xd6 => 0x8477, 0xd7 => 0x846b, 0xd8 => 0x84ad, + 0xd9 => 0x846e, 0xda => 0x8482, 0xdb => 0x8469, 0xdc => 0x8446, + 0xdd => 0x842c, 0xde => 0x846f, 0xdf => 0x8479, 0xe0 => 0x8435, + 0xe1 => 0x84ca, 0xe2 => 0x8462, 0xe3 => 0x84b9, 0xe4 => 0x84bf, + 0xe5 => 0x849f, 0xe6 => 0x84d9, 0xe7 => 0x84cd, 0xe8 => 0x84bb, + 0xe9 => 0x84da, 0xea => 0x84d0, 0xeb => 0x84c1, 0xec => 0x84c6, + 0xed => 0x84d6, 0xee => 0x84a1, 0xef => 0x8521, 0xf0 => 0x84ff, + 0xf1 => 0x84f4, 0xf2 => 0x8517, 0xf3 => 0x8518, 0xf4 => 0x852c, + 0xf5 => 0x851f, 0xf6 => 0x8515, 0xf7 => 0x8514, 0xf8 => 0x84fc, + 0xf9 => 0x8540, 0xfa => 0x8563, 0xfb => 0x8558, 0xfc => 0x8548, + }, + 0xe5 => { + 0x40 => 0x8541, 0x41 => 0x8602, 0x42 => 0x854b, 0x43 => 0x8555, + 0x44 => 0x8580, 0x45 => 0x85a4, 0x46 => 0x8588, 0x47 => 0x8591, + 0x48 => 0x858a, 0x49 => 0x85a8, 0x4a => 0x856d, 0x4b => 0x8594, + 0x4c => 0x859b, 0x4d => 0x85ea, 0x4e => 0x8587, 0x4f => 0x859c, + 0x50 => 0x8577, 0x51 => 0x857e, 0x52 => 0x8590, 0x53 => 0x85c9, + 0x54 => 0x85ba, 0x55 => 0x85cf, 0x56 => 0x85b9, 0x57 => 0x85d0, + 0x58 => 0x85d5, 0x59 => 0x85dd, 0x5a => 0x85e5, 0x5b => 0x85dc, + 0x5c => 0x85f9, 0x5d => 0x860a, 0x5e => 0x8613, 0x5f => 0x860b, + 0x60 => 0x85fe, 0x61 => 0x85fa, 0x62 => 0x8606, 0x63 => 0x8622, + 0x64 => 0x861a, 0x65 => 0x8630, 0x66 => 0x863f, 0x67 => 0x864d, + 0x68 => 0x4e55, 0x69 => 0x8654, 0x6a => 0x865f, 0x6b => 0x8667, + 0x6c => 0x8671, 0x6d => 0x8693, 0x6e => 0x86a3, 0x6f => 0x86a9, + 0x70 => 0x86aa, 0x71 => 0x868b, 0x72 => 0x868c, 0x73 => 0x86b6, + 0x74 => 0x86af, 0x75 => 0x86c4, 0x76 => 0x86c6, 0x77 => 0x86b0, + 0x78 => 0x86c9, 0x79 => 0x8823, 0x7a => 0x86ab, 0x7b => 0x86d4, + 0x7c => 0x86de, 0x7d => 0x86e9, 0x7e => 0x86ec, 0x80 => 0x86df, + 0x81 => 0x86db, 0x82 => 0x86ef, 0x83 => 0x8712, 0x84 => 0x8706, + 0x85 => 0x8708, 0x86 => 0x8700, 0x87 => 0x8703, 0x88 => 0x86fb, + 0x89 => 0x8711, 0x8a => 0x8709, 0x8b => 0x870d, 0x8c => 0x86f9, + 0x8d => 0x870a, 0x8e => 0x8734, 0x8f => 0x873f, 0x90 => 0x8737, + 0x91 => 0x873b, 0x92 => 0x8725, 0x93 => 0x8729, 0x94 => 0x871a, + 0x95 => 0x8760, 0x96 => 0x875f, 0x97 => 0x8778, 0x98 => 0x874c, + 0x99 => 0x874e, 0x9a => 0x8774, 0x9b => 0x8757, 0x9c => 0x8768, + 0x9d => 0x876e, 0x9e => 0x8759, 0x9f => 0x8753, 0xa0 => 0x8763, + 0xa1 => 0x876a, 0xa2 => 0x8805, 0xa3 => 0x87a2, 0xa4 => 0x879f, + 0xa5 => 0x8782, 0xa6 => 0x87af, 0xa7 => 0x87cb, 0xa8 => 0x87bd, + 0xa9 => 0x87c0, 0xaa => 0x87d0, 0xab => 0x96d6, 0xac => 0x87ab, + 0xad => 0x87c4, 0xae => 0x87b3, 0xaf => 0x87c7, 0xb0 => 0x87c6, + 0xb1 => 0x87bb, 0xb2 => 0x87ef, 0xb3 => 0x87f2, 0xb4 => 0x87e0, + 0xb5 => 0x880f, 0xb6 => 0x880d, 0xb7 => 0x87fe, 0xb8 => 0x87f6, + 0xb9 => 0x87f7, 0xba => 0x880e, 0xbb => 0x87d2, 0xbc => 0x8811, + 0xbd => 0x8816, 0xbe => 0x8815, 0xbf => 0x8822, 0xc0 => 0x8821, + 0xc1 => 0x8831, 0xc2 => 0x8836, 0xc3 => 0x8839, 0xc4 => 0x8827, + 0xc5 => 0x883b, 0xc6 => 0x8844, 0xc7 => 0x8842, 0xc8 => 0x8852, + 0xc9 => 0x8859, 0xca => 0x885e, 0xcb => 0x8862, 0xcc => 0x886b, + 0xcd => 0x8881, 0xce => 0x887e, 0xcf => 0x889e, 0xd0 => 0x8875, + 0xd1 => 0x887d, 0xd2 => 0x88b5, 0xd3 => 0x8872, 0xd4 => 0x8882, + 0xd5 => 0x8897, 0xd6 => 0x8892, 0xd7 => 0x88ae, 0xd8 => 0x8899, + 0xd9 => 0x88a2, 0xda => 0x888d, 0xdb => 0x88a4, 0xdc => 0x88b0, + 0xdd => 0x88bf, 0xde => 0x88b1, 0xdf => 0x88c3, 0xe0 => 0x88c4, + 0xe1 => 0x88d4, 0xe2 => 0x88d8, 0xe3 => 0x88d9, 0xe4 => 0x88dd, + 0xe5 => 0x88f9, 0xe6 => 0x8902, 0xe7 => 0x88fc, 0xe8 => 0x88f4, + 0xe9 => 0x88e8, 0xea => 0x88f2, 0xeb => 0x8904, 0xec => 0x890c, + 0xed => 0x890a, 0xee => 0x8913, 0xef => 0x8943, 0xf0 => 0x891e, + 0xf1 => 0x8925, 0xf2 => 0x892a, 0xf3 => 0x892b, 0xf4 => 0x8941, + 0xf5 => 0x8944, 0xf6 => 0x893b, 0xf7 => 0x8936, 0xf8 => 0x8938, + 0xf9 => 0x894c, 0xfa => 0x891d, 0xfb => 0x8960, 0xfc => 0x895e, + }, + 0xe6 => { + 0x40 => 0x8966, 0x41 => 0x8964, 0x42 => 0x896d, 0x43 => 0x896a, + 0x44 => 0x896f, 0x45 => 0x8974, 0x46 => 0x8977, 0x47 => 0x897e, + 0x48 => 0x8983, 0x49 => 0x8988, 0x4a => 0x898a, 0x4b => 0x8993, + 0x4c => 0x8998, 0x4d => 0x89a1, 0x4e => 0x89a9, 0x4f => 0x89a6, + 0x50 => 0x89ac, 0x51 => 0x89af, 0x52 => 0x89b2, 0x53 => 0x89ba, + 0x54 => 0x89bd, 0x55 => 0x89bf, 0x56 => 0x89c0, 0x57 => 0x89da, + 0x58 => 0x89dc, 0x59 => 0x89dd, 0x5a => 0x89e7, 0x5b => 0x89f4, + 0x5c => 0x89f8, 0x5d => 0x8a03, 0x5e => 0x8a16, 0x5f => 0x8a10, + 0x60 => 0x8a0c, 0x61 => 0x8a1b, 0x62 => 0x8a1d, 0x63 => 0x8a25, + 0x64 => 0x8a36, 0x65 => 0x8a41, 0x66 => 0x8a5b, 0x67 => 0x8a52, + 0x68 => 0x8a46, 0x69 => 0x8a48, 0x6a => 0x8a7c, 0x6b => 0x8a6d, + 0x6c => 0x8a6c, 0x6d => 0x8a62, 0x6e => 0x8a85, 0x6f => 0x8a82, + 0x70 => 0x8a84, 0x71 => 0x8aa8, 0x72 => 0x8aa1, 0x73 => 0x8a91, + 0x74 => 0x8aa5, 0x75 => 0x8aa6, 0x76 => 0x8a9a, 0x77 => 0x8aa3, + 0x78 => 0x8ac4, 0x79 => 0x8acd, 0x7a => 0x8ac2, 0x7b => 0x8ada, + 0x7c => 0x8aeb, 0x7d => 0x8af3, 0x7e => 0x8ae7, 0x80 => 0x8ae4, + 0x81 => 0x8af1, 0x82 => 0x8b14, 0x83 => 0x8ae0, 0x84 => 0x8ae2, + 0x85 => 0x8af7, 0x86 => 0x8ade, 0x87 => 0x8adb, 0x88 => 0x8b0c, + 0x89 => 0x8b07, 0x8a => 0x8b1a, 0x8b => 0x8ae1, 0x8c => 0x8b16, + 0x8d => 0x8b10, 0x8e => 0x8b17, 0x8f => 0x8b20, 0x90 => 0x8b33, + 0x91 => 0x97ab, 0x92 => 0x8b26, 0x93 => 0x8b2b, 0x94 => 0x8b3e, + 0x95 => 0x8b28, 0x96 => 0x8b41, 0x97 => 0x8b4c, 0x98 => 0x8b4f, + 0x99 => 0x8b4e, 0x9a => 0x8b49, 0x9b => 0x8b56, 0x9c => 0x8b5b, + 0x9d => 0x8b5a, 0x9e => 0x8b6b, 0x9f => 0x8b5f, 0xa0 => 0x8b6c, + 0xa1 => 0x8b6f, 0xa2 => 0x8b74, 0xa3 => 0x8b7d, 0xa4 => 0x8b80, + 0xa5 => 0x8b8c, 0xa6 => 0x8b8e, 0xa7 => 0x8b92, 0xa8 => 0x8b93, + 0xa9 => 0x8b96, 0xaa => 0x8b99, 0xab => 0x8b9a, 0xac => 0x8c3a, + 0xad => 0x8c41, 0xae => 0x8c3f, 0xaf => 0x8c48, 0xb0 => 0x8c4c, + 0xb1 => 0x8c4e, 0xb2 => 0x8c50, 0xb3 => 0x8c55, 0xb4 => 0x8c62, + 0xb5 => 0x8c6c, 0xb6 => 0x8c78, 0xb7 => 0x8c7a, 0xb8 => 0x8c82, + 0xb9 => 0x8c89, 0xba => 0x8c85, 0xbb => 0x8c8a, 0xbc => 0x8c8d, + 0xbd => 0x8c8e, 0xbe => 0x8c94, 0xbf => 0x8c7c, 0xc0 => 0x8c98, + 0xc1 => 0x621d, 0xc2 => 0x8cad, 0xc3 => 0x8caa, 0xc4 => 0x8cbd, + 0xc5 => 0x8cb2, 0xc6 => 0x8cb3, 0xc7 => 0x8cae, 0xc8 => 0x8cb6, + 0xc9 => 0x8cc8, 0xca => 0x8cc1, 0xcb => 0x8ce4, 0xcc => 0x8ce3, + 0xcd => 0x8cda, 0xce => 0x8cfd, 0xcf => 0x8cfa, 0xd0 => 0x8cfb, + 0xd1 => 0x8d04, 0xd2 => 0x8d05, 0xd3 => 0x8d0a, 0xd4 => 0x8d07, + 0xd5 => 0x8d0f, 0xd6 => 0x8d0d, 0xd7 => 0x8d10, 0xd8 => 0x9f4e, + 0xd9 => 0x8d13, 0xda => 0x8ccd, 0xdb => 0x8d14, 0xdc => 0x8d16, + 0xdd => 0x8d67, 0xde => 0x8d6d, 0xdf => 0x8d71, 0xe0 => 0x8d73, + 0xe1 => 0x8d81, 0xe2 => 0x8d99, 0xe3 => 0x8dc2, 0xe4 => 0x8dbe, + 0xe5 => 0x8dba, 0xe6 => 0x8dcf, 0xe7 => 0x8dda, 0xe8 => 0x8dd6, + 0xe9 => 0x8dcc, 0xea => 0x8ddb, 0xeb => 0x8dcb, 0xec => 0x8dea, + 0xed => 0x8deb, 0xee => 0x8ddf, 0xef => 0x8de3, 0xf0 => 0x8dfc, + 0xf1 => 0x8e08, 0xf2 => 0x8e09, 0xf3 => 0x8dff, 0xf4 => 0x8e1d, + 0xf5 => 0x8e1e, 0xf6 => 0x8e10, 0xf7 => 0x8e1f, 0xf8 => 0x8e42, + 0xf9 => 0x8e35, 0xfa => 0x8e30, 0xfb => 0x8e34, 0xfc => 0x8e4a, + }, + 0xe7 => { + 0x40 => 0x8e47, 0x41 => 0x8e49, 0x42 => 0x8e4c, 0x43 => 0x8e50, + 0x44 => 0x8e48, 0x45 => 0x8e59, 0x46 => 0x8e64, 0x47 => 0x8e60, + 0x48 => 0x8e2a, 0x49 => 0x8e63, 0x4a => 0x8e55, 0x4b => 0x8e76, + 0x4c => 0x8e72, 0x4d => 0x8e7c, 0x4e => 0x8e81, 0x4f => 0x8e87, + 0x50 => 0x8e85, 0x51 => 0x8e84, 0x52 => 0x8e8b, 0x53 => 0x8e8a, + 0x54 => 0x8e93, 0x55 => 0x8e91, 0x56 => 0x8e94, 0x57 => 0x8e99, + 0x58 => 0x8eaa, 0x59 => 0x8ea1, 0x5a => 0x8eac, 0x5b => 0x8eb0, + 0x5c => 0x8ec6, 0x5d => 0x8eb1, 0x5e => 0x8ebe, 0x5f => 0x8ec5, + 0x60 => 0x8ec8, 0x61 => 0x8ecb, 0x62 => 0x8edb, 0x63 => 0x8ee3, + 0x64 => 0x8efc, 0x65 => 0x8efb, 0x66 => 0x8eeb, 0x67 => 0x8efe, + 0x68 => 0x8f0a, 0x69 => 0x8f05, 0x6a => 0x8f15, 0x6b => 0x8f12, + 0x6c => 0x8f19, 0x6d => 0x8f13, 0x6e => 0x8f1c, 0x6f => 0x8f1f, + 0x70 => 0x8f1b, 0x71 => 0x8f0c, 0x72 => 0x8f26, 0x73 => 0x8f33, + 0x74 => 0x8f3b, 0x75 => 0x8f39, 0x76 => 0x8f45, 0x77 => 0x8f42, + 0x78 => 0x8f3e, 0x79 => 0x8f4c, 0x7a => 0x8f49, 0x7b => 0x8f46, + 0x7c => 0x8f4e, 0x7d => 0x8f57, 0x7e => 0x8f5c, 0x80 => 0x8f62, + 0x81 => 0x8f63, 0x82 => 0x8f64, 0x83 => 0x8f9c, 0x84 => 0x8f9f, + 0x85 => 0x8fa3, 0x86 => 0x8fad, 0x87 => 0x8faf, 0x88 => 0x8fb7, + 0x89 => 0x8fda, 0x8a => 0x8fe5, 0x8b => 0x8fe2, 0x8c => 0x8fea, + 0x8d => 0x8fef, 0x8e => 0x9087, 0x8f => 0x8ff4, 0x90 => 0x9005, + 0x91 => 0x8ff9, 0x92 => 0x8ffa, 0x93 => 0x9011, 0x94 => 0x9015, + 0x95 => 0x9021, 0x96 => 0x900d, 0x97 => 0x901e, 0x98 => 0x9016, + 0x99 => 0x900b, 0x9a => 0x9027, 0x9b => 0x9036, 0x9c => 0x9035, + 0x9d => 0x9039, 0x9e => 0x8ff8, 0x9f => 0x904f, 0xa0 => 0x9050, + 0xa1 => 0x9051, 0xa2 => 0x9052, 0xa3 => 0x900e, 0xa4 => 0x9049, + 0xa5 => 0x903e, 0xa6 => 0x9056, 0xa7 => 0x9058, 0xa8 => 0x905e, + 0xa9 => 0x9068, 0xaa => 0x906f, 0xab => 0x9076, 0xac => 0x96a8, + 0xad => 0x9072, 0xae => 0x9082, 0xaf => 0x907d, 0xb0 => 0x9081, + 0xb1 => 0x9080, 0xb2 => 0x908a, 0xb3 => 0x9089, 0xb4 => 0x908f, + 0xb5 => 0x90a8, 0xb6 => 0x90af, 0xb7 => 0x90b1, 0xb8 => 0x90b5, + 0xb9 => 0x90e2, 0xba => 0x90e4, 0xbb => 0x6248, 0xbc => 0x90db, + 0xbd => 0x9102, 0xbe => 0x9112, 0xbf => 0x9119, 0xc0 => 0x9132, + 0xc1 => 0x9130, 0xc2 => 0x914a, 0xc3 => 0x9156, 0xc4 => 0x9158, + 0xc5 => 0x9163, 0xc6 => 0x9165, 0xc7 => 0x9169, 0xc8 => 0x9173, + 0xc9 => 0x9172, 0xca => 0x918b, 0xcb => 0x9189, 0xcc => 0x9182, + 0xcd => 0x91a2, 0xce => 0x91ab, 0xcf => 0x91af, 0xd0 => 0x91aa, + 0xd1 => 0x91b5, 0xd2 => 0x91b4, 0xd3 => 0x91ba, 0xd4 => 0x91c0, + 0xd5 => 0x91c1, 0xd6 => 0x91c9, 0xd7 => 0x91cb, 0xd8 => 0x91d0, + 0xd9 => 0x91d6, 0xda => 0x91df, 0xdb => 0x91e1, 0xdc => 0x91db, + 0xdd => 0x91fc, 0xde => 0x91f5, 0xdf => 0x91f6, 0xe0 => 0x921e, + 0xe1 => 0x91ff, 0xe2 => 0x9214, 0xe3 => 0x922c, 0xe4 => 0x9215, + 0xe5 => 0x9211, 0xe6 => 0x925e, 0xe7 => 0x9257, 0xe8 => 0x9245, + 0xe9 => 0x9249, 0xea => 0x9264, 0xeb => 0x9248, 0xec => 0x9295, + 0xed => 0x923f, 0xee => 0x924b, 0xef => 0x9250, 0xf0 => 0x929c, + 0xf1 => 0x9296, 0xf2 => 0x9293, 0xf3 => 0x929b, 0xf4 => 0x925a, + 0xf5 => 0x92cf, 0xf6 => 0x92b9, 0xf7 => 0x92b7, 0xf8 => 0x92e9, + 0xf9 => 0x930f, 0xfa => 0x92fa, 0xfb => 0x9344, 0xfc => 0x932e, + }, + 0xe8 => { + 0x40 => 0x9319, 0x41 => 0x9322, 0x42 => 0x931a, 0x43 => 0x9323, + 0x44 => 0x933a, 0x45 => 0x9335, 0x46 => 0x933b, 0x47 => 0x935c, + 0x48 => 0x9360, 0x49 => 0x937c, 0x4a => 0x936e, 0x4b => 0x9356, + 0x4c => 0x93b0, 0x4d => 0x93ac, 0x4e => 0x93ad, 0x4f => 0x9394, + 0x50 => 0x93b9, 0x51 => 0x93d6, 0x52 => 0x93d7, 0x53 => 0x93e8, + 0x54 => 0x93e5, 0x55 => 0x93d8, 0x56 => 0x93c3, 0x57 => 0x93dd, + 0x58 => 0x93d0, 0x59 => 0x93c8, 0x5a => 0x93e4, 0x5b => 0x941a, + 0x5c => 0x9414, 0x5d => 0x9413, 0x5e => 0x9403, 0x5f => 0x9407, + 0x60 => 0x9410, 0x61 => 0x9436, 0x62 => 0x942b, 0x63 => 0x9435, + 0x64 => 0x9421, 0x65 => 0x943a, 0x66 => 0x9441, 0x67 => 0x9452, + 0x68 => 0x9444, 0x69 => 0x945b, 0x6a => 0x9460, 0x6b => 0x9462, + 0x6c => 0x945e, 0x6d => 0x946a, 0x6e => 0x9229, 0x6f => 0x9470, + 0x70 => 0x9475, 0x71 => 0x9477, 0x72 => 0x947d, 0x73 => 0x945a, + 0x74 => 0x947c, 0x75 => 0x947e, 0x76 => 0x9481, 0x77 => 0x947f, + 0x78 => 0x9582, 0x79 => 0x9587, 0x7a => 0x958a, 0x7b => 0x9594, + 0x7c => 0x9596, 0x7d => 0x9598, 0x7e => 0x9599, 0x80 => 0x95a0, + 0x81 => 0x95a8, 0x82 => 0x95a7, 0x83 => 0x95ad, 0x84 => 0x95bc, + 0x85 => 0x95bb, 0x86 => 0x95b9, 0x87 => 0x95be, 0x88 => 0x95ca, + 0x89 => 0x6ff6, 0x8a => 0x95c3, 0x8b => 0x95cd, 0x8c => 0x95cc, + 0x8d => 0x95d5, 0x8e => 0x95d4, 0x8f => 0x95d6, 0x90 => 0x95dc, + 0x91 => 0x95e1, 0x92 => 0x95e5, 0x93 => 0x95e2, 0x94 => 0x9621, + 0x95 => 0x9628, 0x96 => 0x962e, 0x97 => 0x962f, 0x98 => 0x9642, + 0x99 => 0x964c, 0x9a => 0x964f, 0x9b => 0x964b, 0x9c => 0x9677, + 0x9d => 0x965c, 0x9e => 0x965e, 0x9f => 0x965d, 0xa0 => 0x965f, + 0xa1 => 0x9666, 0xa2 => 0x9672, 0xa3 => 0x966c, 0xa4 => 0x968d, + 0xa5 => 0x9698, 0xa6 => 0x9695, 0xa7 => 0x9697, 0xa8 => 0x96aa, + 0xa9 => 0x96a7, 0xaa => 0x96b1, 0xab => 0x96b2, 0xac => 0x96b0, + 0xad => 0x96b4, 0xae => 0x96b6, 0xaf => 0x96b8, 0xb0 => 0x96b9, + 0xb1 => 0x96ce, 0xb2 => 0x96cb, 0xb3 => 0x96c9, 0xb4 => 0x96cd, + 0xb5 => 0x894d, 0xb6 => 0x96dc, 0xb7 => 0x970d, 0xb8 => 0x96d5, + 0xb9 => 0x96f9, 0xba => 0x9704, 0xbb => 0x9706, 0xbc => 0x9708, + 0xbd => 0x9713, 0xbe => 0x970e, 0xbf => 0x9711, 0xc0 => 0x970f, + 0xc1 => 0x9716, 0xc2 => 0x9719, 0xc3 => 0x9724, 0xc4 => 0x972a, + 0xc5 => 0x9730, 0xc6 => 0x9739, 0xc7 => 0x973d, 0xc8 => 0x973e, + 0xc9 => 0x9744, 0xca => 0x9746, 0xcb => 0x9748, 0xcc => 0x9742, + 0xcd => 0x9749, 0xce => 0x975c, 0xcf => 0x9760, 0xd0 => 0x9764, + 0xd1 => 0x9766, 0xd2 => 0x9768, 0xd3 => 0x52d2, 0xd4 => 0x976b, + 0xd5 => 0x9771, 0xd6 => 0x9779, 0xd7 => 0x9785, 0xd8 => 0x977c, + 0xd9 => 0x9781, 0xda => 0x977a, 0xdb => 0x9786, 0xdc => 0x978b, + 0xdd => 0x978f, 0xde => 0x9790, 0xdf => 0x979c, 0xe0 => 0x97a8, + 0xe1 => 0x97a6, 0xe2 => 0x97a3, 0xe3 => 0x97b3, 0xe4 => 0x97b4, + 0xe5 => 0x97c3, 0xe6 => 0x97c6, 0xe7 => 0x97c8, 0xe8 => 0x97cb, + 0xe9 => 0x97dc, 0xea => 0x97ed, 0xeb => 0x9f4f, 0xec => 0x97f2, + 0xed => 0x7adf, 0xee => 0x97f6, 0xef => 0x97f5, 0xf0 => 0x980f, + 0xf1 => 0x980c, 0xf2 => 0x9838, 0xf3 => 0x9824, 0xf4 => 0x9821, + 0xf5 => 0x9837, 0xf6 => 0x983d, 0xf7 => 0x9846, 0xf8 => 0x984f, + 0xf9 => 0x984b, 0xfa => 0x986b, 0xfb => 0x986f, 0xfc => 0x9870, + }, + 0xe9 => { + 0x40 => 0x9871, 0x41 => 0x9874, 0x42 => 0x9873, 0x43 => 0x98aa, + 0x44 => 0x98af, 0x45 => 0x98b1, 0x46 => 0x98b6, 0x47 => 0x98c4, + 0x48 => 0x98c3, 0x49 => 0x98c6, 0x4a => 0x98e9, 0x4b => 0x98eb, + 0x4c => 0x9903, 0x4d => 0x9909, 0x4e => 0x9912, 0x4f => 0x9914, + 0x50 => 0x9918, 0x51 => 0x9921, 0x52 => 0x991d, 0x53 => 0x991e, + 0x54 => 0x9924, 0x55 => 0x9920, 0x56 => 0x992c, 0x57 => 0x992e, + 0x58 => 0x993d, 0x59 => 0x993e, 0x5a => 0x9942, 0x5b => 0x9949, + 0x5c => 0x9945, 0x5d => 0x9950, 0x5e => 0x994b, 0x5f => 0x9951, + 0x60 => 0x9952, 0x61 => 0x994c, 0x62 => 0x9955, 0x63 => 0x9997, + 0x64 => 0x9998, 0x65 => 0x99a5, 0x66 => 0x99ad, 0x67 => 0x99ae, + 0x68 => 0x99bc, 0x69 => 0x99df, 0x6a => 0x99db, 0x6b => 0x99dd, + 0x6c => 0x99d8, 0x6d => 0x99d1, 0x6e => 0x99ed, 0x6f => 0x99ee, + 0x70 => 0x99f1, 0x71 => 0x99f2, 0x72 => 0x99fb, 0x73 => 0x99f8, + 0x74 => 0x9a01, 0x75 => 0x9a0f, 0x76 => 0x9a05, 0x77 => 0x99e2, + 0x78 => 0x9a19, 0x79 => 0x9a2b, 0x7a => 0x9a37, 0x7b => 0x9a45, + 0x7c => 0x9a42, 0x7d => 0x9a40, 0x7e => 0x9a43, 0x80 => 0x9a3e, + 0x81 => 0x9a55, 0x82 => 0x9a4d, 0x83 => 0x9a5b, 0x84 => 0x9a57, + 0x85 => 0x9a5f, 0x86 => 0x9a62, 0x87 => 0x9a65, 0x88 => 0x9a64, + 0x89 => 0x9a69, 0x8a => 0x9a6b, 0x8b => 0x9a6a, 0x8c => 0x9aad, + 0x8d => 0x9ab0, 0x8e => 0x9abc, 0x8f => 0x9ac0, 0x90 => 0x9acf, + 0x91 => 0x9ad1, 0x92 => 0x9ad3, 0x93 => 0x9ad4, 0x94 => 0x9ade, + 0x95 => 0x9adf, 0x96 => 0x9ae2, 0x97 => 0x9ae3, 0x98 => 0x9ae6, + 0x99 => 0x9aef, 0x9a => 0x9aeb, 0x9b => 0x9aee, 0x9c => 0x9af4, + 0x9d => 0x9af1, 0x9e => 0x9af7, 0x9f => 0x9afb, 0xa0 => 0x9b06, + 0xa1 => 0x9b18, 0xa2 => 0x9b1a, 0xa3 => 0x9b1f, 0xa4 => 0x9b22, + 0xa5 => 0x9b23, 0xa6 => 0x9b25, 0xa7 => 0x9b27, 0xa8 => 0x9b28, + 0xa9 => 0x9b29, 0xaa => 0x9b2a, 0xab => 0x9b2e, 0xac => 0x9b2f, + 0xad => 0x9b32, 0xae => 0x9b44, 0xaf => 0x9b43, 0xb0 => 0x9b4f, + 0xb1 => 0x9b4d, 0xb2 => 0x9b4e, 0xb3 => 0x9b51, 0xb4 => 0x9b58, + 0xb5 => 0x9b74, 0xb6 => 0x9b93, 0xb7 => 0x9b83, 0xb8 => 0x9b91, + 0xb9 => 0x9b96, 0xba => 0x9b97, 0xbb => 0x9b9f, 0xbc => 0x9ba0, + 0xbd => 0x9ba8, 0xbe => 0x9bb4, 0xbf => 0x9bc0, 0xc0 => 0x9bca, + 0xc1 => 0x9bb9, 0xc2 => 0x9bc6, 0xc3 => 0x9bcf, 0xc4 => 0x9bd1, + 0xc5 => 0x9bd2, 0xc6 => 0x9be3, 0xc7 => 0x9be2, 0xc8 => 0x9be4, + 0xc9 => 0x9bd4, 0xca => 0x9be1, 0xcb => 0x9c3a, 0xcc => 0x9bf2, + 0xcd => 0x9bf1, 0xce => 0x9bf0, 0xcf => 0x9c15, 0xd0 => 0x9c14, + 0xd1 => 0x9c09, 0xd2 => 0x9c13, 0xd3 => 0x9c0c, 0xd4 => 0x9c06, + 0xd5 => 0x9c08, 0xd6 => 0x9c12, 0xd7 => 0x9c0a, 0xd8 => 0x9c04, + 0xd9 => 0x9c2e, 0xda => 0x9c1b, 0xdb => 0x9c25, 0xdc => 0x9c24, + 0xdd => 0x9c21, 0xde => 0x9c30, 0xdf => 0x9c47, 0xe0 => 0x9c32, + 0xe1 => 0x9c46, 0xe2 => 0x9c3e, 0xe3 => 0x9c5a, 0xe4 => 0x9c60, + 0xe5 => 0x9c67, 0xe6 => 0x9c76, 0xe7 => 0x9c78, 0xe8 => 0x9ce7, + 0xe9 => 0x9cec, 0xea => 0x9cf0, 0xeb => 0x9d09, 0xec => 0x9d08, + 0xed => 0x9ceb, 0xee => 0x9d03, 0xef => 0x9d06, 0xf0 => 0x9d2a, + 0xf1 => 0x9d26, 0xf2 => 0x9daf, 0xf3 => 0x9d23, 0xf4 => 0x9d1f, + 0xf5 => 0x9d44, 0xf6 => 0x9d15, 0xf7 => 0x9d12, 0xf8 => 0x9d41, + 0xf9 => 0x9d3f, 0xfa => 0x9d3e, 0xfb => 0x9d46, 0xfc => 0x9d48, + }, + 0xea => { + 0x40 => 0x9d5d, 0x41 => 0x9d5e, 0x42 => 0x9d64, 0x43 => 0x9d51, + 0x44 => 0x9d50, 0x45 => 0x9d59, 0x46 => 0x9d72, 0x47 => 0x9d89, + 0x48 => 0x9d87, 0x49 => 0x9dab, 0x4a => 0x9d6f, 0x4b => 0x9d7a, + 0x4c => 0x9d9a, 0x4d => 0x9da4, 0x4e => 0x9da9, 0x4f => 0x9db2, + 0x50 => 0x9dc4, 0x51 => 0x9dc1, 0x52 => 0x9dbb, 0x53 => 0x9db8, + 0x54 => 0x9dba, 0x55 => 0x9dc6, 0x56 => 0x9dcf, 0x57 => 0x9dc2, + 0x58 => 0x9dd9, 0x59 => 0x9dd3, 0x5a => 0x9df8, 0x5b => 0x9de6, + 0x5c => 0x9ded, 0x5d => 0x9def, 0x5e => 0x9dfd, 0x5f => 0x9e1a, + 0x60 => 0x9e1b, 0x61 => 0x9e1e, 0x62 => 0x9e75, 0x63 => 0x9e79, + 0x64 => 0x9e7d, 0x65 => 0x9e81, 0x66 => 0x9e88, 0x67 => 0x9e8b, + 0x68 => 0x9e8c, 0x69 => 0x9e92, 0x6a => 0x9e95, 0x6b => 0x9e91, + 0x6c => 0x9e9d, 0x6d => 0x9ea5, 0x6e => 0x9ea9, 0x6f => 0x9eb8, + 0x70 => 0x9eaa, 0x71 => 0x9ead, 0x72 => 0x9761, 0x73 => 0x9ecc, + 0x74 => 0x9ece, 0x75 => 0x9ecf, 0x76 => 0x9ed0, 0x77 => 0x9ed4, + 0x78 => 0x9edc, 0x79 => 0x9ede, 0x7a => 0x9edd, 0x7b => 0x9ee0, + 0x7c => 0x9ee5, 0x7d => 0x9ee8, 0x7e => 0x9eef, 0x80 => 0x9ef4, + 0x81 => 0x9ef6, 0x82 => 0x9ef7, 0x83 => 0x9ef9, 0x84 => 0x9efb, + 0x85 => 0x9efc, 0x86 => 0x9efd, 0x87 => 0x9f07, 0x88 => 0x9f08, + 0x89 => 0x76b7, 0x8a => 0x9f15, 0x8b => 0x9f21, 0x8c => 0x9f2c, + 0x8d => 0x9f3e, 0x8e => 0x9f4a, 0x8f => 0x9f52, 0x90 => 0x9f54, + 0x91 => 0x9f63, 0x92 => 0x9f5f, 0x93 => 0x9f60, 0x94 => 0x9f61, + 0x95 => 0x9f66, 0x96 => 0x9f67, 0x97 => 0x9f6c, 0x98 => 0x9f6a, + 0x99 => 0x9f77, 0x9a => 0x9f72, 0x9b => 0x9f76, 0x9c => 0x9f95, + 0x9d => 0x9f9c, 0x9e => 0x9fa0, 0x9f => 0x582f, 0xa0 => 0x69c7, + 0xa1 => 0x9059, 0xa2 => 0x7464, 0xa3 => 0x51dc, 0xa4 => 0x7199, + }, + 0xeb => { + 0x41 => [0x3001,0xf87e], 0x42 => [0x3002,0xf87e], 0x50 => [0xffe3,0xf87e], + 0x51 => 0xfe33, 0x5b => [0x30fc,0xf87e], 0x5c => 0xfe31, + 0x5d => [0x2010,0xf87e], 0x60 => [0x301c,0xf87e], 0x61 => [0x2016,0xf87e], + 0x62 => [0xff5c,0xf87e], 0x63 => [0x2026,0xf87e], 0x64 => 0xfe30, + 0x69 => 0xfe35, 0x6a => 0xfe36, 0x6b => 0xfe39, 0x6c => 0xfe3a, + 0x6d => [0xff3b,0xf87e], 0x6e => [0xff3d,0xf87e], 0x6f => 0xfe37, + 0x70 => 0xfe38, 0x71 => 0xfe3f, 0x72 => 0xfe40, 0x73 => 0xfe3d, + 0x74 => 0xfe3e, 0x75 => 0xfe41, 0x76 => 0xfe42, 0x77 => 0xfe43, + 0x78 => 0xfe44, 0x79 => 0xfe3b, 0x7a => 0xfe3c, 0x81 => [0xff1d,0xf87e], + }, + 0xec => { + 0x9f => [0x3041,0xf87e], 0xa1 => [0x3043,0xf87e], 0xa3 => [0x3045,0xf87e], + 0xa5 => [0x3047,0xf87e], 0xa7 => [0x3049,0xf87e], 0xc1 => [0x3063,0xf87e], + 0xe1 => [0x3083,0xf87e], 0xe3 => [0x3085,0xf87e], 0xe5 => [0x3087,0xf87e], + 0xec => [0x308e,0xf87e], + }, + 0xed => { + 0x40 => [0x30a1,0xf87e], 0x42 => [0x30a3,0xf87e], 0x44 => [0x30a5,0xf87e], + 0x46 => [0x30a7,0xf87e], 0x48 => [0x30a9,0xf87e], 0x62 => [0x30c3,0xf87e], + 0x83 => [0x30e3,0xf87e], 0x85 => [0x30e5,0xf87e], 0x87 => [0x30e7,0xf87e], + 0x8e => [0x30ee,0xf87e], 0x95 => [0x30f5,0xf87e], 0x96 => [0x30f6,0xf87e], + }, +); + +1; # end diff --git a/lib/Image/ExifTool/Charset/MacKorean.pm b/lib/Image/ExifTool/Charset/MacKorean.pm new file mode 100644 index 0000000..c8f6e72 --- /dev/null +++ b/lib/Image/ExifTool/Charset/MacKorean.pm @@ -0,0 +1,2720 @@ +#------------------------------------------------------------------------------ +# File: MacKorean.pm +# +# Description: Mac Korean to Unicode +# +# Revisions: 2010/01/20 - P. Harvey created +# +# References: 1) http://unicode.org/Public/MAPPINGS/VENDORS/APPLE/KOREAN.TXT +# +# Notes: The table omits 1-byte characters with the same values as Unicode +#------------------------------------------------------------------------------ +use strict; + +%Image::ExifTool::Charset::MacKorean = ( + 0x80 => 0xa0, 0x81 => 0x20a9, 0x82 => [0x2013,0xf87f], 0x83 => 0xa9, + 0x84 => [0xff3f,0xf87f], 0xff => [0x2026,0xf87f], + 0xa1 => { + 0x41 => [0x300c,0xf87f], 0x42 => [0x300d,0xf87f], 0x43 => [0x300c,0xf87b], + 0x44 => [0x300d,0xf87b], 0x45 => [0x300c,0xf87c], 0x46 => [0x300d,0xf87c], + 0x47 => [0x300e,0xf87c], 0x48 => [0x300f,0xf87c], 0x49 => [0x300a,0xf878], + 0x4a => [0x300b,0xf878], 0x4b => [0x3008,0xf878], 0x4c => [0x3009,0xf878], + 0x4d => 0xfe59, 0x4e => 0xfe5a, 0x4f => [0xfe59,0xf87f], + 0x50 => [0xfe5a,0xf87f], 0x51 => [0x2985,0xf87f], 0x52 => [0x2986,0xf87f], + 0x53 => [0x2985,0xf879], 0x54 => [0x2986,0xf879], 0x55 => [0x2985,0xf87c], + 0x56 => [0x2986,0xf87c], 0x57 => [0x28,0xf87c], 0x58 => [0x29,0xf87c], + 0x59 => 0x2985, 0x5a => 0x2986, 0x5b => [0x3010,0xf87f], + 0x5c => [0x3011,0xf87f], 0x5d => 0x3016, 0x5e => 0x3017, 0x5f => 0x3018, + 0x60 => 0x3019, 0x61 => [0x5b,0xf87b], 0x62 => [0x5d,0xf87b], + 0x63 => [0x5b,0xf87c], 0x64 => [0x5d,0xf87c], 0x65 => [0x2985,0xf87b], + 0x66 => [0x2986,0xf87b], 0x67 => [0x2020,0xf87f], 0x68 => [0x2021,0xf87f], + 0x69 => [0x2020,0xf87b], 0x6a => [0x2021,0xf87c], 0x6b => [0x2020,0xf877], + 0x6c => [0x2a,0xf877], 0x6d => 0x2051, 0x6e => 0xf840, 0x6f => 0x201f, + 0x70 => 0x201b, 0x71 => 0x207a, 0x72 => 0x207b, 0x73 => [0xd7,0xf877], + 0x74 => [0x221e,0xf877], 0x75 => [0x223d,0xf877], 0x76 => [0xb1,0xf877], + 0x77 => [0x2213,0xf877], 0x78 => [0x3e,0xf877], 0x79 => [0x3c,0xf877], + 0x7a => 0x207c, 0x7b => [0x2260,0xf877], 0x7c => 0x207d, 0x7d => 0x207e, + 0x81 => [0x7b,0xf877], 0x82 => [0x7d,0xf877], 0x83 => [0x5b,0xf877], + 0x84 => [0x5d,0xf877], 0x85 => [0x2229,0xf877], 0x86 => [0x222a,0xf877], + 0x87 => [0x2282,0xf877], 0x88 => [0x2208,0xf877], 0x89 => [0x2211,0xf877], + 0x8a => [0x21,0xf877], 0x8b => [0x3007,0xf876], 0x8c => [0x4e00,0xf876], + 0x8d => [0x4e8c,0xf876], 0x8e => [0x4e09,0xf876], 0x8f => [0x56db,0xf876], + 0x90 => [0x4e94,0xf876], 0x91 => [0x516d,0xf876], 0x92 => [0x4e03,0xf876], + 0x93 => [0x516b,0xf876], 0x94 => [0x4e5d,0xf876], 0x95 => [0x5341,0xf876], + 0x96 => 0x204c, 0x97 => 0x204d, 0x98 => 0x02bc, 0x99 => 0x2997, + 0x9a => 0x2998, 0x9c => [0xff0a,0xf874], 0x9d => [0x2051,0xf87c], + 0x9e => [0xff0a,0xf875], 0x9f => [0xff0a,0xf871], 0xa0 => [0x2051,0xf879], + 0xa1 => 0x3000, 0xa2 => 0x3001, 0xa3 => 0x3002, 0xa4 => 0xb7, + 0xa5 => 0x2025, 0xa6 => 0x2026, 0xa7 => 0xa8, 0xa8 => 0x3003, + 0xa9 => 0x2013, 0xaa => 0x2014, 0xab => 0x2016, 0xac => 0xff3c, + 0xad => 0x301c, 0xae => 0x2018, 0xaf => 0x2019, 0xb0 => 0x201c, + 0xb1 => 0x201d, 0xb2 => 0x3014, 0xb3 => 0x3015, 0xb4 => 0x3008, + 0xb5 => 0x3009, 0xb6 => 0x300a, 0xb7 => 0x300b, 0xb8 => 0x300c, + 0xb9 => 0x300d, 0xba => 0x300e, 0xbb => 0x300f, 0xbc => 0x3010, + 0xbd => 0x3011, 0xbe => 0xb1, 0xbf => 0xd7, 0xc0 => 0xf7, 0xc1 => 0x2260, + 0xc2 => 0x2264, 0xc3 => 0x2265, 0xc4 => 0x221e, 0xc5 => 0x2234, + 0xc6 => 0xb0, 0xc7 => 0x2032, 0xc8 => 0x2033, 0xc9 => 0x2103, + 0xca => 0x212b, 0xcb => 0xa2, 0xcc => 0xa3, 0xcd => 0xa5, 0xce => 0x2642, + 0xcf => 0x2640, 0xd0 => 0x2220, 0xd1 => 0x22a5, 0xd2 => 0x2312, + 0xd3 => 0x2202, 0xd4 => 0x2207, 0xd5 => 0x2261, 0xd6 => 0x2252, + 0xd7 => 0xa7, 0xd8 => 0x203b, 0xd9 => 0x2606, 0xda => 0x2605, + 0xdb => 0x25cb, 0xdc => 0x25cf, 0xdd => 0x25ce, 0xde => 0x25c7, + 0xdf => 0x25c6, 0xe0 => 0x25a1, 0xe1 => 0x25a0, 0xe2 => 0x25b3, + 0xe3 => 0x25b2, 0xe4 => 0x25bd, 0xe5 => 0x25bc, 0xe6 => 0x2192, + 0xe7 => 0x2190, 0xe8 => 0x2191, 0xe9 => 0x2193, 0xea => 0x2194, + 0xeb => 0x3013, 0xec => 0x226a, 0xed => 0x226b, 0xee => 0x221a, + 0xef => 0x223d, 0xf0 => 0x221d, 0xf1 => 0x2235, 0xf2 => 0x222b, + 0xf3 => 0x222c, 0xf4 => 0x2208, 0xf5 => 0x220b, 0xf6 => 0x2286, + 0xf7 => 0x2287, 0xf8 => 0x2282, 0xf9 => 0x2283, 0xfa => 0x222a, + 0xfb => 0x2229, 0xfc => 0x2227, 0xfd => 0x2228, 0xfe => 0xac, + }, + 0xa2 => { + 0x41 => [0x2985,0xf878], 0x42 => [0x2986,0xf878], 0x43 => [0x2985,0xf873], + 0x44 => [0x2986,0xf873], 0x45 => [0xfe59,0xf87c], 0x46 => [0xfe5a,0xf87c], + 0x47 => [0x3016,0xf878], 0x48 => [0x3017,0xf878], 0x49 => [0x3010,0xf878], + 0x4a => [0x3011,0xf878], 0x4b => [0x28,0xf87f], 0x4c => [0x29,0xf87f], + 0xa1 => 0x21d2, 0xa2 => 0x21d4, 0xa3 => 0x2200, 0xa4 => 0x2203, + 0xa5 => 0xb4, 0xa6 => 0x02dc, 0xa7 => 0x02c7, 0xa8 => 0x02d8, + 0xa9 => 0x02dd, 0xaa => 0x02da, 0xab => 0x02d9, 0xac => 0xb8, + 0xad => 0x02db, 0xae => 0xa1, 0xaf => 0xbf, 0xb0 => 0x02d0, 0xb1 => 0x222e, + 0xb2 => 0x2211, 0xb3 => 0x220f, 0xb4 => 0xa4, 0xb5 => 0x2109, + 0xb6 => 0x2030, 0xb7 => 0x25c1, 0xb8 => 0x25c0, 0xb9 => 0x25b7, + 0xba => 0x25b6, 0xbb => 0x2664, 0xbc => 0x2660, 0xbd => 0x2661, + 0xbe => 0x2665, 0xbf => 0x2667, 0xc0 => 0x2663, 0xc1 => 0x25c9, + 0xc2 => 0x25c8, 0xc3 => 0x25a3, 0xc4 => 0x25d0, 0xc5 => 0x25d1, + 0xc6 => 0x2592, 0xc7 => 0x25a4, 0xc8 => 0x25a5, 0xc9 => 0x25a8, + 0xca => 0x25a7, 0xcb => 0x25a6, 0xcc => 0x25a9, 0xcd => 0x2668, + 0xce => 0x260f, 0xcf => 0x260e, 0xd0 => 0x261c, 0xd1 => 0x261e, + 0xd2 => 0xb6, 0xd3 => 0x2020, 0xd4 => 0x2021, 0xd5 => 0x2195, + 0xd6 => 0x2197, 0xd7 => 0x2199, 0xd8 => 0x2196, 0xd9 => 0x2198, + 0xda => 0x266d, 0xdb => 0x2669, 0xdc => 0x266a, 0xdd => 0x266c, + 0xde => 0x327f, 0xdf => 0x321c, 0xe0 => 0x2116, 0xe1 => 0x33c7, + 0xe2 => 0x2122, 0xe3 => 0x33c2, 0xe4 => 0x33d8, 0xe5 => 0x2121, + 0xe6 => [0x31,0x20de,0xf87c], 0xe7 => [0x32,0x20de,0xf87c], + 0xe8 => [0x33,0x20de,0xf87c], 0xe9 => [0x34,0x20de,0xf87c], + 0xea => [0x35,0x20de,0xf87c], 0xeb => [0x36,0x20de,0xf87c], + 0xec => [0x37,0x20de,0xf87c], 0xed => [0x38,0x20de,0xf87c], + 0xee => [0x39,0x20de,0xf87c], 0xef => [0xf863,0x5b,0x31,0x30,0x5d], + 0xf0 => [0xf863,0x5b,0x31,0x31,0x5d], 0xf1 => [0xf863,0x5b,0x31,0x32,0x5d], + 0xf2 => [0xf863,0x5b,0x31,0x33,0x5d], 0xf3 => [0xf863,0x5b,0x31,0x34,0x5d], + 0xf4 => [0xf863,0x5b,0x31,0x35,0x5d], 0xf5 => [0xf863,0x5b,0x31,0x36,0x5d], + 0xf6 => [0xf863,0x5b,0x31,0x37,0x5d], 0xf7 => [0xf863,0x5b,0x31,0x38,0x5d], + 0xf8 => [0xf863,0x5b,0x31,0x39,0x5d], 0xf9 => [0xf863,0x5b,0x32,0x30,0x5d], + 0xfa => [0xb6,0xf87f], 0xfb => [0x2016,0xf87b], 0xfc => [0x2016,0xf87c], + 0xfd => 0x22ee, 0xfe => 0x2237, + }, + 0xa3 => { + 0x41 => [0x31,0x20de,0xf87b], 0x42 => [0x32,0x20de,0xf87b], + 0x43 => [0x33,0x20de,0xf87b], 0x44 => [0x34,0x20de,0xf87b], + 0x45 => [0x35,0x20de,0xf87b], 0x46 => [0x36,0x20de,0xf87b], + 0x47 => [0x37,0x20de,0xf87b], 0x48 => [0x38,0x20de,0xf87b], + 0x49 => [0x39,0x20de,0xf87b], 0x4a => [0xf864,0x5b,0x31,0x30,0x5d], + 0x4b => [0xf864,0x5b,0x31,0x31,0x5d], 0x4c => [0xf864,0x5b,0x31,0x32,0x5d], + 0x4d => [0xf864,0x5b,0x31,0x33,0x5d], 0x4e => [0xf864,0x5b,0x31,0x34,0x5d], + 0x4f => [0xf864,0x5b,0x31,0x35,0x5d], 0x50 => [0xf864,0x5b,0x31,0x36,0x5d], + 0x51 => [0xf864,0x5b,0x31,0x37,0x5d], 0x52 => [0xf864,0x5b,0x31,0x38,0x5d], + 0x53 => [0xf864,0x5b,0x31,0x39,0x5d], 0x54 => [0xf864,0x5b,0x32,0x30,0x5d], + 0x55 => 0x278a, 0x56 => 0x278b, 0x57 => 0x278c, 0x58 => 0x278d, + 0x59 => 0x278e, 0x5a => 0x278f, 0x5b => 0x2790, 0x5c => 0x2791, + 0x5d => 0x2792, 0x5e => 0x2793, 0x5f => [0x24eb,0xf87f], + 0x60 => [0x24ec,0xf87f], 0x61 => [0x24ed,0xf87f], 0x62 => [0x24ee,0xf87f], + 0x63 => [0x24ef,0xf87f], 0x64 => [0x24f0,0xf87f], 0x65 => [0x24f1,0xf87f], + 0x66 => [0x24f2,0xf87f], 0x67 => [0x24f3,0xf87f], 0x68 => [0x24f4,0xf87f], + 0x69 => [0xf861,0x28,0x41,0x29], 0x6a => [0xf861,0x28,0x42,0x29], + 0x6b => [0xf861,0x28,0x43,0x29], 0x6c => [0xf861,0x28,0x44,0x29], + 0x6d => [0xf861,0x28,0x45,0x29], 0x6e => [0xf861,0x28,0x46,0x29], + 0x6f => [0xf861,0x28,0x47,0x29], 0x70 => [0xf861,0x28,0x48,0x29], + 0x71 => [0xf861,0x28,0x49,0x29], 0x72 => [0xf861,0x28,0x4a,0x29], + 0x73 => [0xf861,0x28,0x4b,0x29], 0x74 => [0xf861,0x28,0x4c,0x29], + 0x75 => [0xf861,0x28,0x4d,0x29], 0x76 => [0xf861,0x28,0x4e,0x29], + 0x77 => [0xf861,0x28,0x4f,0x29], 0x78 => [0xf861,0x28,0x50,0x29], + 0x79 => [0xf861,0x28,0x51,0x29], 0x7a => [0xf861,0x28,0x52,0x29], + 0x7b => [0xf861,0x28,0x53,0x29], 0x7c => [0xf861,0x28,0x54,0x29], + 0x7d => [0xf861,0x28,0x55,0x29], 0x81 => [0xf861,0x28,0x56,0x29], + 0x82 => [0xf861,0x28,0x57,0x29], 0x83 => [0xf861,0x28,0x58,0x29], + 0x84 => [0xf861,0x28,0x59,0x29], 0x85 => [0xf861,0x28,0x5a,0x29], + 0x86 => 0x24b6, 0x87 => 0x24b7, 0x88 => 0x24b8, 0x89 => 0x24b9, + 0x8a => 0x24ba, 0x8b => 0x24bb, 0x8c => 0x24bc, 0x8d => 0x24bd, + 0x8e => 0x24be, 0x8f => 0x24bf, 0x90 => 0x24c0, 0x91 => 0x24c1, + 0x92 => 0x24c2, 0x93 => 0x24c3, 0x94 => 0x24c4, 0x95 => 0x24c5, + 0x96 => 0x24c6, 0x97 => 0x24c7, 0x98 => 0x24c8, 0x99 => 0x24c9, + 0x9a => 0x24ca, 0x9b => 0x24cb, 0x9c => 0x24cc, 0x9d => 0x24cd, + 0x9e => 0x24ce, 0x9f => 0x24cf, 0xa1 => 0xff01, 0xa2 => 0xff02, + 0xa3 => 0xff03, 0xa4 => 0xff04, 0xa5 => 0xff05, 0xa6 => 0xff06, + 0xa7 => 0xff07, 0xa8 => 0xff08, 0xa9 => 0xff09, 0xaa => 0xff0a, + 0xab => 0xff0b, 0xac => 0xff0c, 0xad => 0xff0d, 0xae => 0xff0e, + 0xaf => 0xff0f, 0xb0 => 0xff10, 0xb1 => 0xff11, 0xb2 => 0xff12, + 0xb3 => 0xff13, 0xb4 => 0xff14, 0xb5 => 0xff15, 0xb6 => 0xff16, + 0xb7 => 0xff17, 0xb8 => 0xff18, 0xb9 => 0xff19, 0xba => 0xff1a, + 0xbb => 0xff1b, 0xbc => 0xff1c, 0xbd => 0xff1d, 0xbe => 0xff1e, + 0xbf => 0xff1f, 0xc0 => 0xff20, 0xc1 => 0xff21, 0xc2 => 0xff22, + 0xc3 => 0xff23, 0xc4 => 0xff24, 0xc5 => 0xff25, 0xc6 => 0xff26, + 0xc7 => 0xff27, 0xc8 => 0xff28, 0xc9 => 0xff29, 0xca => 0xff2a, + 0xcb => 0xff2b, 0xcc => 0xff2c, 0xcd => 0xff2d, 0xce => 0xff2e, + 0xcf => 0xff2f, 0xd0 => 0xff30, 0xd1 => 0xff31, 0xd2 => 0xff32, + 0xd3 => 0xff33, 0xd4 => 0xff34, 0xd5 => 0xff35, 0xd6 => 0xff36, + 0xd7 => 0xff37, 0xd8 => 0xff38, 0xd9 => 0xff39, 0xda => 0xff3a, + 0xdb => 0xff3b, 0xdc => 0xffe6, 0xdd => 0xff3d, 0xde => 0xff3e, + 0xdf => 0xff3f, 0xe0 => 0xff40, 0xe1 => 0xff41, 0xe2 => 0xff42, + 0xe3 => 0xff43, 0xe4 => 0xff44, 0xe5 => 0xff45, 0xe6 => 0xff46, + 0xe7 => 0xff47, 0xe8 => 0xff48, 0xe9 => 0xff49, 0xea => 0xff4a, + 0xeb => 0xff4b, 0xec => 0xff4c, 0xed => 0xff4d, 0xee => 0xff4e, + 0xef => 0xff4f, 0xf0 => 0xff50, 0xf1 => 0xff51, 0xf2 => 0xff52, + 0xf3 => 0xff53, 0xf4 => 0xff54, 0xf5 => 0xff55, 0xf6 => 0xff56, + 0xf7 => 0xff57, 0xf8 => 0xff58, 0xf9 => 0xff59, 0xfa => 0xff5a, + 0xfb => 0xff5b, 0xfc => 0xff5c, 0xfd => 0xff5d, 0xfe => 0x203e, + }, + 0xa4 => { + 0x41 => [0x31,0x20de,0xf87f], 0x42 => [0x32,0x20de,0xf87f], + 0x43 => [0x33,0x20de,0xf87f], 0x44 => [0x34,0x20de,0xf87f], + 0x45 => [0x35,0x20de,0xf87f], 0x46 => [0x36,0x20de,0xf87f], + 0x47 => [0x37,0x20de,0xf87f], 0x48 => [0x38,0x20de,0xf87f], + 0x49 => [0x39,0x20de,0xf87f], 0x4a => [0xf862,0x5b,0x31,0x30,0x5d], + 0x4b => [0xf862,0x5b,0x31,0x31,0x5d], 0x4c => [0xf862,0x5b,0x31,0x32,0x5d], + 0x4d => [0xf862,0x5b,0x31,0x33,0x5d], 0x4e => [0xf862,0x5b,0x31,0x34,0x5d], + 0x4f => [0xf862,0x5b,0x31,0x35,0x5d], 0x50 => [0xf862,0x5b,0x31,0x36,0x5d], + 0x51 => [0xf862,0x5b,0x31,0x37,0x5d], 0x52 => [0xf862,0x5b,0x31,0x38,0x5d], + 0x53 => [0xf862,0x5b,0x31,0x39,0x5d], 0x54 => [0xf862,0x5b,0x32,0x30,0x5d], + 0x55 => [0x31,0x20de,0xf87a], 0x56 => [0x32,0x20de,0xf87a], + 0x57 => [0x33,0x20de,0xf87a], 0x58 => [0x34,0x20de,0xf87a], + 0x59 => [0x35,0x20de,0xf87a], 0x5a => [0x36,0x20de,0xf87a], + 0x5b => [0x37,0x20de,0xf87a], 0x5c => [0x38,0x20de,0xf87a], + 0x5d => [0x39,0x20de,0xf87a], 0x5e => [0xf865,0x5b,0x31,0x30,0x5d], + 0x5f => [0xf865,0x5b,0x31,0x31,0x5d], 0x60 => [0xf865,0x5b,0x31,0x32,0x5d], + 0x61 => [0xf865,0x5b,0x31,0x33,0x5d], 0x62 => [0xf865,0x5b,0x31,0x34,0x5d], + 0x63 => [0xf865,0x5b,0x31,0x35,0x5d], 0x64 => [0xf865,0x5b,0x31,0x36,0x5d], + 0x65 => [0xf865,0x5b,0x31,0x37,0x5d], 0x66 => [0xf865,0x5b,0x31,0x38,0x5d], + 0x67 => [0xf865,0x5b,0x31,0x39,0x5d], 0x68 => [0xf865,0x5b,0x32,0x30,0x5d], + 0x69 => [0x278a,0xf87f], 0x6a => [0x278b,0xf87f], 0x6b => [0x278c,0xf87f], + 0x6c => [0x278d,0xf87f], 0x6d => [0x278e,0xf87f], 0x6e => [0x278f,0xf87f], + 0x6f => [0x2790,0xf87f], 0x70 => [0x2791,0xf87f], 0x71 => [0x2792,0xf87f], + 0x72 => [0x2793,0xf87f], 0x73 => [0x24eb,0xf878], 0x74 => [0x24ec,0xf878], + 0x75 => [0x24ed,0xf878], 0x76 => [0x24ee,0xf878], 0x77 => [0x24ef,0xf878], + 0x78 => [0x24f0,0xf878], 0x79 => [0x24f1,0xf878], 0x7a => [0x24f2,0xf878], + 0x7b => [0x24f3,0xf878], 0x7c => [0x24f4,0xf878], 0x7d => 0x2a26, + 0x81 => 0x227a, 0x82 => 0x227b, 0x83 => 0x22ce, 0x84 => 0x22cf, + 0x85 => 0x2280, 0x86 => 0x2281, 0x87 => 0x2270, 0x88 => 0x2271, + 0x89 => 0x2272, 0x8a => 0x2273, 0x8b => 0x2ac5, 0x8c => 0x2acb, + 0x8d => 0x2ac6, 0x8e => 0x2acc, 0x8f => 0x2276, 0x90 => 0x2277, + 0x91 => 0x2279, 0x92 => 0x22da, 0x93 => 0x22db, 0x94 => 0x2a8b, + 0x95 => 0x2a8c, 0x96 => 0x2a91, 0x97 => 0x2a92, 0x98 => [0x2222,0xf87f], + 0x99 => 0x2245, 0x9a => 0x2243, 0x9b => 0x2248, 0x9c => 0x29a3, + 0x9d => 0x22a4, 0x9e => [0x2225,0x0347], 0x9f => [0x2afd,0x0347], + 0xa1 => 0x3131, 0xa2 => 0x3132, 0xa3 => 0x3133, 0xa4 => 0x3134, + 0xa5 => 0x3135, 0xa6 => 0x3136, 0xa7 => 0x3137, 0xa8 => 0x3138, + 0xa9 => 0x3139, 0xaa => 0x313a, 0xab => 0x313b, 0xac => 0x313c, + 0xad => 0x313d, 0xae => 0x313e, 0xaf => 0x313f, 0xb0 => 0x3140, + 0xb1 => 0x3141, 0xb2 => 0x3142, 0xb3 => 0x3143, 0xb4 => 0x3144, + 0xb5 => 0x3145, 0xb6 => 0x3146, 0xb7 => 0x3147, 0xb8 => 0x3148, + 0xb9 => 0x3149, 0xba => 0x314a, 0xbb => 0x314b, 0xbc => 0x314c, + 0xbd => 0x314d, 0xbe => 0x314e, 0xbf => 0x314f, 0xc0 => 0x3150, + 0xc1 => 0x3151, 0xc2 => 0x3152, 0xc3 => 0x3153, 0xc4 => 0x3154, + 0xc5 => 0x3155, 0xc6 => 0x3156, 0xc7 => 0x3157, 0xc8 => 0x3158, + 0xc9 => 0x3159, 0xca => 0x315a, 0xcb => 0x315b, 0xcc => 0x315c, + 0xcd => 0x315d, 0xce => 0x315e, 0xcf => 0x315f, 0xd0 => 0x3160, + 0xd1 => 0x3161, 0xd2 => 0x3162, 0xd3 => 0x3163, 0xd4 => 0x3164, + 0xd5 => 0x3165, 0xd6 => 0x3166, 0xd7 => 0x3167, 0xd8 => 0x3168, + 0xd9 => 0x3169, 0xda => 0x316a, 0xdb => 0x316b, 0xdc => 0x316c, + 0xdd => 0x316d, 0xde => 0x316e, 0xdf => 0x316f, 0xe0 => 0x3170, + 0xe1 => 0x3171, 0xe2 => 0x3172, 0xe3 => 0x3173, 0xe4 => 0x3174, + 0xe5 => 0x3175, 0xe6 => 0x3176, 0xe7 => 0x3177, 0xe8 => 0x3178, + 0xe9 => 0x3179, 0xea => 0x317a, 0xeb => 0x317b, 0xec => 0x317c, + 0xed => 0x317d, 0xee => 0x317e, 0xef => 0x317f, 0xf0 => 0x3180, + 0xf1 => 0x3181, 0xf2 => 0x3182, 0xf3 => 0x3183, 0xf4 => 0x3184, + 0xf5 => 0x3185, 0xf6 => 0x3186, 0xf7 => 0x3187, 0xf8 => 0x3188, + 0xf9 => 0x3189, 0xfa => 0x318a, 0xfb => 0x318b, 0xfc => 0x318c, + 0xfd => 0x318d, 0xfe => 0x318e, + }, + 0xa5 => { + 0x41 => [0x30,0x20de], 0x42 => [0x31,0x20de], 0x43 => [0x32,0x20de], + 0x44 => [0x33,0x20de], 0x45 => [0x34,0x20de], 0x46 => [0x35,0x20de], + 0x47 => [0x36,0x20de], 0x48 => [0x37,0x20de], 0x49 => [0x38,0x20de], + 0x4a => [0x39,0x20de], 0x4b => [0x24ea,0xf87f], 0x4c => [0x2460,0xf87f], + 0x4d => [0x2461,0xf87f], 0x4e => [0x2462,0xf87f], 0x4f => [0x2463,0xf87f], + 0x50 => [0x2464,0xf87f], 0x51 => [0x2465,0xf87f], 0x52 => [0x2466,0xf87f], + 0x53 => [0x2467,0xf87f], 0x54 => [0x2468,0xf87f], + 0x55 => [0xf860,0x41,0x29], 0x56 => [0xf860,0x42,0x29], + 0x57 => [0xf860,0x43,0x29], 0x58 => [0xf860,0x44,0x29], + 0x59 => [0xf860,0x45,0x29], 0x5a => [0xf860,0x46,0x29], + 0x5b => [0xf860,0x47,0x29], 0x5c => [0xf860,0x48,0x29], + 0x5d => [0xf860,0x49,0x29], 0x5e => [0xf860,0x4a,0x29], + 0x5f => [0xf860,0x4b,0x29], 0x60 => [0xf860,0x4c,0x29], + 0x61 => [0xf860,0x4d,0x29], 0x62 => [0xf860,0x4e,0x29], + 0x63 => [0xf860,0x4f,0x29], 0x64 => [0xf860,0x50,0x29], + 0x65 => [0xf860,0x51,0x29], 0x66 => [0xf860,0x52,0x29], + 0x67 => [0xf860,0x53,0x29], 0x68 => [0xf860,0x54,0x29], + 0x69 => [0xf860,0x55,0x29], 0x6a => [0xf860,0x56,0x29], + 0x6b => [0xf860,0x57,0x29], 0x6c => [0xf860,0x58,0x29], + 0x6d => [0xf860,0x59,0x29], 0x6e => [0xf860,0x5a,0x29], + 0x6f => [0xf860,0x61,0x29], 0x70 => [0xf860,0x62,0x29], + 0x71 => [0xf860,0x63,0x29], 0x72 => [0xf860,0x64,0x29], + 0x73 => [0xf860,0x65,0x29], 0x74 => [0xf860,0x66,0x29], + 0x75 => [0xf860,0x67,0x29], 0x76 => [0xf860,0x68,0x29], + 0x77 => [0xf860,0x69,0x29], 0x78 => [0xf860,0x6a,0x29], + 0x79 => [0xf860,0x6b,0x29], 0x7a => [0xf860,0x6c,0x29], + 0x7b => [0xf860,0x6d,0x29], 0x7c => [0xf860,0x6e,0x29], + 0x7d => [0xf860,0x6f,0x29], 0x81 => [0xf860,0x70,0x29], + 0x82 => [0xf860,0x71,0x29], 0x83 => [0xf860,0x72,0x29], + 0x84 => [0xf860,0x73,0x29], 0x85 => [0xf860,0x74,0x29], + 0x86 => [0xf860,0x75,0x29], 0x87 => [0xf860,0x76,0x29], + 0x88 => [0xf860,0x77,0x29], 0x89 => [0xf860,0x78,0x29], + 0x8a => [0xf860,0x79,0x29], 0x8b => [0xf860,0x7a,0x29], 0xa1 => 0x2170, + 0xa2 => 0x2171, 0xa3 => 0x2172, 0xa4 => 0x2173, 0xa5 => 0x2174, + 0xa6 => 0x2175, 0xa7 => 0x2176, 0xa8 => 0x2177, 0xa9 => 0x2178, + 0xaa => 0x2179, 0xb0 => 0x2160, 0xb1 => 0x2161, 0xb2 => 0x2162, + 0xb3 => 0x2163, 0xb4 => 0x2164, 0xb5 => 0x2165, 0xb6 => 0x2166, + 0xb7 => 0x2167, 0xb8 => 0x2168, 0xb9 => 0x2169, 0xc1 => 0x0391, + 0xc2 => 0x0392, 0xc3 => 0x0393, 0xc4 => 0x0394, 0xc5 => 0x0395, + 0xc6 => 0x0396, 0xc7 => 0x0397, 0xc8 => 0x0398, 0xc9 => 0x0399, + 0xca => 0x039a, 0xcb => 0x039b, 0xcc => 0x039c, 0xcd => 0x039d, + 0xce => 0x039e, 0xcf => 0x039f, 0xd0 => 0x03a0, 0xd1 => 0x03a1, + 0xd2 => 0x03a3, 0xd3 => 0x03a4, 0xd4 => 0x03a5, 0xd5 => 0x03a6, + 0xd6 => 0x03a7, 0xd7 => 0x03a8, 0xd8 => 0x03a9, 0xda => [0xff01,0xf874], + 0xdb => [0x3002,0xf87d], 0xdc => [0x2032,0xf87f], 0xdd => [0x2033,0xf87f], + 0xde => 0x2034, 0xe1 => 0x03b1, 0xe2 => 0x03b2, 0xe3 => 0x03b3, + 0xe4 => 0x03b4, 0xe5 => 0x03b5, 0xe6 => 0x03b6, 0xe7 => 0x03b7, + 0xe8 => 0x03b8, 0xe9 => 0x03b9, 0xea => 0x03ba, 0xeb => 0x03bb, + 0xec => 0x03bc, 0xed => 0x03bd, 0xee => 0x03be, 0xef => 0x03bf, + 0xf0 => 0x03c0, 0xf1 => 0x03c1, 0xf2 => 0x03c3, 0xf3 => 0x03c4, + 0xf4 => 0x03c5, 0xf5 => 0x03c6, 0xf6 => 0x03c7, 0xf7 => 0x03c8, + 0xf8 => 0x03c9, 0xf9 => [0x3257,0xf87a], 0xfa => [0x3258,0xf87a], + 0xfb => [0x3259,0xf87a], 0xfc => [0x325a,0xf87a], + }, + 0xa6 => { + 0x41 => [0xf83d,0xf87f], 0x42 => 0xf83d, 0x43 => [0x2020,0xf87c], + 0x44 => [0xf860,0x2020,0x2020], 0x45 => [0xf860,0x2021,0x2021], + 0x46 => [0xf861,0x2020,0x2020,0x2020], 0x47 => [0xa7,0xf87c], + 0x48 => 0x266f, 0x49 => [0xff0a,0xf87f], 0x4a => [0xff0a,0xf873], + 0x4b => [0x2051,0xf874], 0x4c => [0xf860,0x2a,0x2a], 0x4d => 0x2042, + 0x4e => 0x204e, 0x4f => [0x2051,0xf871], 0x50 => [0xf867,0x2a,0x2a], + 0x51 => [0x2042,0xf879], 0x52 => 0x273d, 0x53 => 0x2731, 0x54 => 0x2747, + 0x55 => 0x2022, 0x56 => [0x25a0,0x20df], 0x57 => [0x25c7,0x20df], + 0x58 => 0xf805, 0x59 => [0x25a1,0x20df], 0x5a => 0x2039, 0x5b => 0x203a, + 0x5c => 0xab, 0x5d => 0xbb, 0x5e => [0x261c,0xf87f], + 0x5f => [0x261e,0xf87f], 0x60 => [0xf806,0x20df], + 0x61 => [0x25c7,0x20df,0x20df], 0x62 => [0x25c7,0x20de], 0x63 => 0xf806, + 0x64 => 0x29c8, 0x65 => [0x25c6,0x20de], 0x66 => [0xf805,0x20de], + 0x67 => [0x29c8,0x20de], 0x68 => 0x29be, 0x69 => [0x25ce,0x20dd], + 0x6a => [0x25b3,0x20dd], 0x6b => [0x25b2,0x20dd], 0x6c => 0x271a, + 0x6d => 0x2716, 0x6e => 0x29bf, 0x6f => 0x25ef, 0x70 => [0x25ef,0xf87c], + 0x71 => [0x2610,0xf87c], 0x72 => 0x2723, 0x73 => 0x2756, 0x74 => 0xf80a, + 0x75 => 0x25cc, 0x76 => [0x2610,0xf87f], 0x77 => 0x2610, 0x78 => 0x25a2, + 0x79 => [0x2723,0xf87a], 0x7a => [0x2756,0xf87a], 0x7b => [0x273f,0xf87a], + 0x7c => 0x273f, 0x7d => [0x3013,0xf87c], 0x81 => 0xf809, + 0x82 => [0x25c9,0x20dd], 0x83 => 0x274d, 0x84 => 0x25cd, + 0x85 => [0x27e1,0x20dd], 0x86 => [0xf80b,0xf87f], 0x87 => [0x2720,0xf87a], + 0x88 => 0x2720, 0x89 => [0x25c8,0xf87f], 0x8a => [0x25a8,0xf87f], + 0x8d => 0x2741, 0x8e => [0x2756,0xf87f], 0x8f => 0xf808, + 0x90 => [0x20a9,0xf87f], 0x91 => [0xf809,0xf87a], 0x92 => [0x534d,0xf87f], + 0x93 => 0x262f, 0x96 => 0xf80b, 0x97 => [0x262f,0xf87a], + 0x98 => [0x262f,0xf876], 0x99 => 0x2740, 0x9a => 0xf80c, + 0x9b => [0x2748,0x20d8], 0x9e => 0x3020, 0x9f => 0xf807, 0xa1 => 0x2500, + 0xa2 => 0x2502, 0xa3 => 0x250c, 0xa4 => 0x2510, 0xa5 => 0x2518, + 0xa6 => 0x2514, 0xa7 => 0x251c, 0xa8 => 0x252c, 0xa9 => 0x2524, + 0xaa => 0x2534, 0xab => 0x253c, 0xac => 0x2501, 0xad => 0x2503, + 0xae => 0x250f, 0xaf => 0x2513, 0xb0 => 0x251b, 0xb1 => 0x2517, + 0xb2 => 0x2523, 0xb3 => 0x2533, 0xb4 => 0x252b, 0xb5 => 0x253b, + 0xb6 => 0x254b, 0xb7 => 0x2520, 0xb8 => 0x252f, 0xb9 => 0x2528, + 0xba => 0x2537, 0xbb => 0x253f, 0xbc => 0x251d, 0xbd => 0x2530, + 0xbe => 0x2525, 0xbf => 0x2538, 0xc0 => 0x2542, 0xc1 => 0x2512, + 0xc2 => 0x2511, 0xc3 => 0x251a, 0xc4 => 0x2519, 0xc5 => 0x2516, + 0xc6 => 0x2515, 0xc7 => 0x250e, 0xc8 => 0x250d, 0xc9 => 0x251e, + 0xca => 0x251f, 0xcb => 0x2521, 0xcc => 0x2522, 0xcd => 0x2526, + 0xce => 0x2527, 0xcf => 0x2529, 0xd0 => 0x252a, 0xd1 => 0x252d, + 0xd2 => 0x252e, 0xd3 => 0x2531, 0xd4 => 0x2532, 0xd5 => 0x2535, + 0xd6 => 0x2536, 0xd7 => 0x2539, 0xd8 => 0x253a, 0xd9 => 0x253d, + 0xda => 0x253e, 0xdb => 0x2540, 0xdc => 0x2541, 0xdd => 0x2543, + 0xde => 0x2544, 0xdf => 0x2545, 0xe0 => 0x2546, 0xe1 => 0x2547, + 0xe2 => 0x2548, 0xe3 => 0x2549, 0xe4 => 0x254a, 0xe5 => 0x2776, + 0xe6 => 0x2777, 0xe7 => 0x2778, 0xe8 => 0x2779, 0xe9 => 0x277a, + 0xea => 0x277b, 0xeb => 0x277c, 0xec => 0x277d, 0xed => 0x277e, + 0xee => 0x277f, 0xef => 0x24eb, 0xf0 => 0x24ec, 0xf1 => 0x24ed, + 0xf2 => 0x24ee, 0xf3 => 0x24ef, 0xf4 => 0x24f0, 0xf5 => 0x24f1, + 0xf6 => 0x24f2, 0xf7 => 0x24f3, 0xf8 => 0x24f4, 0xf9 => [0x3251,0xf87a], + 0xfa => [0x3252,0xf87a], 0xfb => [0x3253,0xf87a], 0xfc => [0x3254,0xf87a], + 0xfd => [0x3255,0xf87a], 0xfe => [0x3256,0xf87a], + }, + 0xa7 => { + 0x41 => [0x2642,0xf87f], 0x42 => 0x3012, 0x43 => 0x3036, + 0x44 => [0x25cb,0xf87f], 0x45 => [0x25b3,0xf87f], 0x46 => 0x25fb, + 0x47 => 0xf84c, 0x48 => [0x2394,0xf876], 0x49 => [0x25ad,0xf878], + 0x4a => 0x25ad, 0x4b => 0xf84d, 0x4c => 0xf84e, 0x4d => 0xf84f, + 0x4e => [0x25c7,0xf87f], 0x4f => [0x51f9,0xf87f], 0x50 => [0x51f8,0xf87f], + 0x51 => 0x2206, 0x52 => [0x2206,0xf87f], 0x53 => 0x221f, + 0x54 => [0x222a,0xf87f], 0x55 => 0x2225, 0x56 => 0x2226, + 0x57 => [0x2229,0xf87f], 0x58 => 0x2253, 0x59 => 0x2251, 0x5a => 0x2266, + 0x5b => 0x2267, 0x5c => 0x2213, 0x5d => 0x2295, 0x5e => 0x2296, + 0x5f => 0x2297, 0x60 => 0x2a38, 0x61 => 0x2314, 0x62 => [0x3d,0x20e5], + 0x63 => [0x2261,0x20e5], 0x64 => 0x2262, 0x65 => [0x3d,0x20d2], + 0x66 => 0x25b1, 0x67 => [0x2d,0x0308], 0x68 => 0x2222, 0x69 => 0x2250, + 0x6a => 0x03d5, 0x6b => 0x2ae8, 0x6c => 0x22a3, 0x6d => [0x22a5,0x0338], + 0x6e => [0x2261,0x20d2], 0x6f => 0x226e, 0x70 => 0x226f, 0x71 => 0x2285, + 0x72 => 0x2284, 0x73 => 0x2209, 0x74 => 0x220c, 0x75 => 0x22bb, + 0x76 => 0x22bc, 0x77 => 0x225a, 0x78 => 0x2306, 0x79 => [0x223d,0x0336], + 0x7a => [0x2314,0xf87f], 0x7b => 0x2a72, 0x7c => [0x88dc,0x20e4], + 0x7d => [0xf862,0xc8fc,0xc2dd,0xd68c,0xc0ac], + 0x81 => [0xf863,0xc8fc,0xc2dd,0xd68c,0xc0ac], 0x82 => 0x329e, + 0x83 => [0x329e,0xf87f], 0x84 => 0x203c, 0x85 => 0x2049, + 0x86 => [0x203c,0xf87f], 0x87 => 0x2047, 0x88 => [0x25c7,0xf87c], + 0x89 => [0x25c7,0xf879], 0x8a => [0x25c7,0xf87b], 0x8b => [0x25c6,0xf879], + 0x8c => [0x25a1,0xf87c], 0x8d => [0x25a1,0xf879], 0x8e => [0x25a1,0xf87b], + 0x8f => 0x2588, 0x90 => 0x25e6, 0x91 => [0x25cb,0xf879], + 0x92 => [0x25cb,0xf87b], 0x93 => [0x25cf,0xf879], 0x94 => 0x25bf, + 0x95 => 0x25b5, 0x96 => 0x25b9, 0x97 => 0x25c3, 0x98 => 0x2666, + 0x99 => 0x2981, 0x9a => 0x25fc, 0x9b => [0x25b4,0x20e4], 0x9c => 0x25ca, + 0x9d => 0x3231, 0x9e => 0x3239, 0x9f => 0x33cb, 0xa1 => 0x3395, + 0xa2 => 0x3396, 0xa3 => 0x3397, 0xa4 => 0x2113, 0xa5 => 0x3398, + 0xa6 => 0x33c4, 0xa7 => 0x33a3, 0xa8 => 0x33a4, 0xa9 => 0x33a5, + 0xaa => 0x33a6, 0xab => 0x3399, 0xac => 0x339a, 0xad => 0x339b, + 0xae => 0x339c, 0xaf => 0x339d, 0xb0 => 0x339e, 0xb1 => 0x339f, + 0xb2 => 0x33a0, 0xb3 => 0x33a1, 0xb4 => 0x33a2, 0xb5 => 0x33ca, + 0xb6 => 0x338d, 0xb7 => 0x338e, 0xb8 => 0x338f, 0xb9 => 0x33cf, + 0xba => 0x3388, 0xbb => 0x3389, 0xbc => 0x33c8, 0xbd => 0x33a7, + 0xbe => 0x33a8, 0xbf => 0x33b0, 0xc0 => 0x33b1, 0xc1 => 0x33b2, + 0xc2 => 0x33b3, 0xc3 => 0x33b4, 0xc4 => 0x33b5, 0xc5 => 0x33b6, + 0xc6 => 0x33b7, 0xc7 => 0x33b8, 0xc8 => 0x33b9, 0xc9 => 0x3380, + 0xca => 0x3381, 0xcb => 0x3382, 0xcc => 0x3383, 0xcd => 0x3384, + 0xce => 0x33ba, 0xcf => 0x33bb, 0xd0 => 0x33bc, 0xd1 => 0x33bd, + 0xd2 => 0x33be, 0xd3 => 0x33bf, 0xd4 => 0x3390, 0xd5 => 0x3391, + 0xd6 => 0x3392, 0xd7 => 0x3393, 0xd8 => 0x3394, 0xd9 => 0x2126, + 0xda => 0x33c0, 0xdb => 0x33c1, 0xdc => 0x338a, 0xdd => 0x338b, + 0xde => 0x338c, 0xdf => 0x33d6, 0xe0 => 0x33c5, 0xe1 => 0x33ad, + 0xe2 => 0x33ae, 0xe3 => 0x33af, 0xe4 => 0x33db, 0xe5 => 0x33a9, + 0xe6 => 0x33aa, 0xe7 => 0x33ab, 0xe8 => 0x33ac, 0xe9 => 0x33dd, + 0xea => 0x33d0, 0xeb => 0x33d3, 0xec => 0x33c3, 0xed => 0x33c9, + 0xee => 0x33dc, 0xef => 0x33c6, 0xf0 => 0x246f, 0xf1 => 0x2470, + 0xf2 => 0x2471, 0xf3 => 0x2472, 0xf4 => 0x2473, 0xf5 => 0x3251, + 0xf6 => 0x3252, 0xf7 => 0x3253, 0xf8 => 0x3254, 0xf9 => 0x3255, + 0xfa => 0x3256, 0xfb => 0x3257, 0xfc => 0x3258, 0xfd => 0x3259, + 0xfe => 0x325a, + }, + 0xa8 => { + 0x41 => [0x2192,0xf87b], 0x42 => [0x2190,0xf87b], 0x43 => [0x2191,0xf87b], + 0x44 => [0x2193,0xf87b], 0x45 => [0x2196,0xf87b], 0x46 => [0x2197,0xf87b], + 0x47 => [0x2198,0xf87b], 0x48 => [0x2199,0xf87b], 0x49 => 0x21d0, + 0x4a => 0x21cf, 0x4b => 0x21cd, 0x4c => [0x21d4,0xf87f], + 0x4d => [0x2192,0xf87c], 0x4e => [0x2190,0xf87c], 0x4f => [0x2191,0xf87c], + 0x50 => [0x2193,0xf87c], 0x51 => [0x2194,0xf87c], 0x52 => [0x2195,0xf87c], + 0x53 => [0x2190,0xf879], 0x54 => [0x2192,0xf879], 0x55 => [0x2191,0xf879], + 0x56 => [0x2193,0xf879], 0x57 => [0x21e6,0x20de], 0x58 => [0x21e8,0x20de], + 0x59 => [0x21e7,0x20de], 0x5a => [0x21e9,0x20de], 0x5b => [0x21e6,0x20dd], + 0x5c => 0x27b2, 0x5d => [0x21e7,0x20dd], 0x5e => [0x21e9,0x20dd], + 0x5f => [0x2190,0xf87f], 0x60 => 0x279c, 0x61 => [0x2191,0xf87f], + 0x62 => [0x2193,0xf87f], 0x63 => [0x2190,0xf875], 0x64 => [0x2192,0xf875], + 0x65 => [0x2191,0xf875], 0x66 => [0x2193,0xf875], 0x67 => 0xf846, + 0x68 => 0xf847, 0x69 => [0x2190,0xf871], 0x6a => 0x279b, + 0x6b => [0x2190,0xf872], 0x6c => [0x2192,0xf872], 0x6d => [0x2191,0xf872], + 0x6e => [0x2193,0xf872], 0x6f => 0x2962, 0x70 => 0x2964, 0x71 => 0x2963, + 0x72 => 0x2965, 0x73 => [0x21e6,0xf87a], 0x74 => 0x27a1, + 0x75 => [0x21e7,0xf87a], 0x76 => [0x21e9,0xf87a], 0x77 => [0x21e6,0xf87b], + 0x78 => 0x279e, 0x79 => [0x21e7,0xf87b], 0x7a => [0x21e9,0xf87b], + 0x7b => 0x21b2, 0x7c => 0x21b1, 0x7d => [0x21bb,0xf87b], 0x81 => 0x21b4, + 0x82 => 0x21b0, 0x83 => 0x21b3, 0x84 => [0x2939,0xf87f], + 0x85 => [0x2934,0xf87f], 0x86 => 0x2936, 0x87 => [0x21b1,0xf87f], + 0x88 => [0x21bb,0xf87f], 0x89 => 0x2935, 0x8a => [0x21b0,0xf87f], + 0x8b => 0x2937, 0x8c => 0x2939, 0x8d => 0x2934, 0x8e => [0x21e6,0xf879], + 0x8f => [0x21e8,0xf879], 0x90 => [0x21e7,0xf879], 0x91 => [0x21e9,0xf879], + 0x92 => 0x21bc, 0x93 => 0x21c0, 0x94 => 0xf841, 0x95 => [0x21d4,0xf879], + 0x96 => [0x21e8,0xf874], 0x97 => [0x21e6,0xf874], 0x98 => [0x21c0,0xf879], + 0x99 => [0x21bc,0xf879], 0x9a => [0x21d2,0xf87c], 0x9b => [0x21d0,0xf87c], + 0x9c => 0xf849, 0x9d => 0xf848, 0x9e => 0x21c4, 0x9f => 0x21c5, + 0xa1 => 0xc6, 0xa2 => 0xd0, 0xa3 => 0xaa, 0xa4 => 0x0126, 0xa6 => 0x0132, + 0xa8 => 0x013f, 0xa9 => 0x0141, 0xaa => 0xd8, 0xab => 0x0152, 0xac => 0xba, + 0xad => 0xde, 0xae => 0x0166, 0xaf => 0x014a, 0xb1 => 0x3260, + 0xb2 => 0x3261, 0xb3 => 0x3262, 0xb4 => 0x3263, 0xb5 => 0x3264, + 0xb6 => 0x3265, 0xb7 => 0x3266, 0xb8 => 0x3267, 0xb9 => 0x3268, + 0xba => 0x3269, 0xbb => 0x326a, 0xbc => 0x326b, 0xbd => 0x326c, + 0xbe => 0x326d, 0xbf => 0x326e, 0xc0 => 0x326f, 0xc1 => 0x3270, + 0xc2 => 0x3271, 0xc3 => 0x3272, 0xc4 => 0x3273, 0xc5 => 0x3274, + 0xc6 => 0x3275, 0xc7 => 0x3276, 0xc8 => 0x3277, 0xc9 => 0x3278, + 0xca => 0x3279, 0xcb => 0x327a, 0xcc => 0x327b, 0xcd => 0x24d0, + 0xce => 0x24d1, 0xcf => 0x24d2, 0xd0 => 0x24d3, 0xd1 => 0x24d4, + 0xd2 => 0x24d5, 0xd3 => 0x24d6, 0xd4 => 0x24d7, 0xd5 => 0x24d8, + 0xd6 => 0x24d9, 0xd7 => 0x24da, 0xd8 => 0x24db, 0xd9 => 0x24dc, + 0xda => 0x24dd, 0xdb => 0x24de, 0xdc => 0x24df, 0xdd => 0x24e0, + 0xde => 0x24e1, 0xdf => 0x24e2, 0xe0 => 0x24e3, 0xe1 => 0x24e4, + 0xe2 => 0x24e5, 0xe3 => 0x24e6, 0xe4 => 0x24e7, 0xe5 => 0x24e8, + 0xe6 => 0x24e9, 0xe7 => 0x2460, 0xe8 => 0x2461, 0xe9 => 0x2462, + 0xea => 0x2463, 0xeb => 0x2464, 0xec => 0x2465, 0xed => 0x2466, + 0xee => 0x2467, 0xef => 0x2468, 0xf0 => 0x2469, 0xf1 => 0x246a, + 0xf2 => 0x246b, 0xf3 => 0x246c, 0xf4 => 0x246d, 0xf5 => 0x246e, + 0xf6 => 0xbd, 0xf7 => 0x2153, 0xf8 => 0x2154, 0xf9 => 0xbc, 0xfa => 0xbe, + 0xfb => 0x215b, 0xfc => 0x215c, 0xfd => 0x215d, 0xfe => 0x215e, + }, + 0xa9 => { + 0x41 => [0xf860,0x41,0x2e], 0x42 => [0xf860,0x42,0x2e], + 0x43 => [0xf860,0x43,0x2e], 0x44 => [0xf860,0x44,0x2e], + 0x45 => [0xf860,0x45,0x2e], 0x46 => [0xf860,0x46,0x2e], + 0x47 => [0xf860,0x47,0x2e], 0x48 => [0xf860,0x48,0x2e], + 0x49 => [0xf860,0x49,0x2e], 0x4a => [0xf860,0x4a,0x2e], + 0x4b => [0xf860,0x4b,0x2e], 0x4c => [0xf860,0x4c,0x2e], + 0x4d => [0xf860,0x4d,0x2e], 0x4e => [0xf860,0x4e,0x2e], + 0x4f => [0xf860,0x4f,0x2e], 0x50 => [0xf860,0x50,0x2e], + 0x51 => [0xf860,0x51,0x2e], 0x52 => [0xf860,0x52,0x2e], + 0x53 => [0xf860,0x53,0x2e], 0x54 => [0xf860,0x54,0x2e], + 0x55 => [0xf860,0x55,0x2e], 0x56 => [0xf860,0x56,0x2e], + 0x57 => [0xf860,0x57,0x2e], 0x58 => [0xf860,0x58,0x2e], + 0x59 => [0xf860,0x59,0x2e], 0x5a => [0xf860,0x5a,0x2e], + 0x5b => [0xf860,0x61,0x2e], 0x5c => [0xf860,0x62,0x2e], + 0x5d => [0xf860,0x63,0x2e], 0x5e => [0xf860,0x64,0x2e], + 0x5f => [0xf860,0x65,0x2e], 0x60 => [0xf860,0x66,0x2e], + 0x61 => [0xf860,0x67,0x2e], 0x62 => [0xf860,0x68,0x2e], + 0x63 => [0xf860,0x69,0x2e], 0x64 => [0xf860,0x6a,0x2e], + 0x65 => [0xf860,0x6b,0x2e], 0x66 => [0xf860,0x6c,0x2e], + 0x67 => [0xf860,0x6d,0x2e], 0x68 => [0xf860,0x6e,0x2e], + 0x69 => [0xf860,0x6f,0x2e], 0x6a => [0xf860,0x70,0x2e], + 0x6b => [0xf860,0x71,0x2e], 0x6c => [0xf860,0x72,0x2e], + 0x6d => [0xf860,0x73,0x2e], 0x6e => [0xf860,0x74,0x2e], + 0x6f => [0xf860,0x75,0x2e], 0x70 => [0xf860,0x76,0x2e], + 0x71 => [0xf860,0x77,0x2e], 0x72 => [0xf860,0x78,0x2e], + 0x73 => [0xf860,0x79,0x2e], 0x74 => [0xf860,0x7a,0x2e], 0xa1 => 0xe6, + 0xa2 => 0x0111, 0xa3 => 0xf0, 0xa4 => 0x0127, 0xa5 => 0x0131, + 0xa6 => 0x0133, 0xa7 => 0x0138, 0xa8 => 0x0140, 0xa9 => 0x0142, + 0xaa => 0xf8, 0xab => 0x0153, 0xac => 0xdf, 0xad => 0xfe, 0xae => 0x0167, + 0xaf => 0x014b, 0xb0 => 0x0149, 0xb1 => 0x3200, 0xb2 => 0x3201, + 0xb3 => 0x3202, 0xb4 => 0x3203, 0xb5 => 0x3204, 0xb6 => 0x3205, + 0xb7 => 0x3206, 0xb8 => 0x3207, 0xb9 => 0x3208, 0xba => 0x3209, + 0xbb => 0x320a, 0xbc => 0x320b, 0xbd => 0x320c, 0xbe => 0x320d, + 0xbf => 0x320e, 0xc0 => 0x320f, 0xc1 => 0x3210, 0xc2 => 0x3211, + 0xc3 => 0x3212, 0xc4 => 0x3213, 0xc5 => 0x3214, 0xc6 => 0x3215, + 0xc7 => 0x3216, 0xc8 => 0x3217, 0xc9 => 0x3218, 0xca => 0x3219, + 0xcb => 0x321a, 0xcc => 0x321b, 0xcd => 0x249c, 0xce => 0x249d, + 0xcf => 0x249e, 0xd0 => 0x249f, 0xd1 => 0x24a0, 0xd2 => 0x24a1, + 0xd3 => 0x24a2, 0xd4 => 0x24a3, 0xd5 => 0x24a4, 0xd6 => 0x24a5, + 0xd7 => 0x24a6, 0xd8 => 0x24a7, 0xd9 => 0x24a8, 0xda => 0x24a9, + 0xdb => 0x24aa, 0xdc => 0x24ab, 0xdd => 0x24ac, 0xde => 0x24ad, + 0xdf => 0x24ae, 0xe0 => 0x24af, 0xe1 => 0x24b0, 0xe2 => 0x24b1, + 0xe3 => 0x24b2, 0xe4 => 0x24b3, 0xe5 => 0x24b4, 0xe6 => 0x24b5, + 0xe7 => 0x2474, 0xe8 => 0x2475, 0xe9 => 0x2476, 0xea => 0x2477, + 0xeb => 0x2478, 0xec => 0x2479, 0xed => 0x247a, 0xee => 0x247b, + 0xef => 0x247c, 0xf0 => 0x247d, 0xf1 => 0x247e, 0xf2 => 0x247f, + 0xf3 => 0x2480, 0xf4 => 0x2481, 0xf5 => 0x2482, 0xf6 => 0xb9, 0xf7 => 0xb2, + 0xf8 => 0xb3, 0xf9 => 0x2074, 0xfa => 0x207f, 0xfb => 0x2081, + 0xfc => 0x2082, 0xfd => 0x2083, 0xfe => 0x2084, + }, + 0xaa => { + 0x41 => [0xc6b4,0x20de], 0x42 => [0xb2f5,0x20de], 0x43 => [0xc8fc,0x20de], + 0x44 => [0xba85,0x20de], 0x45 => [0xb300,0x20de], 0x46 => [0xd615,0x20de], + 0x47 => [0xbd80,0x20de], 0x48 => [0xc804,0x20de], 0x49 => [0xc811,0x20de], + 0x4a => [0xc218,0x20de], 0x4b => [0xb3d9,0x20de], 0x4c => [0xbe44,0x20de], + 0x4d => [0xbc18,0x20de], 0x4e => [0xc790,0x20de], 0x4f => [0xd0c0,0x20de], + 0x50 => [0xac10,0x20de], 0x51 => [0xc57d,0x20de], 0x52 => [0xc778,0x20de], + 0x53 => [0xb73b,0x20de], 0x54 => [0x5370,0x20de], 0x55 => [0x8a3b,0x20de], + 0x56 => [0xc608,0x20de], 0x57 => [0x611f,0x20de], 0x58 => [0x51a0,0x20de], + 0x59 => [0x7b54,0x20de], 0x5a => [0x4ee3,0x20de], 0x5b => [0x982d,0x20de], + 0x5c => [0x52d5,0x20de], 0x5d => [0x540d,0x20de], 0x5e => [0x76ee,0x20de], + 0x5f => [0x53cd,0x20de], 0x60 => [0x88dc,0x20de], 0x61 => [0x672c,0x20de], + 0x62 => [0x526f,0x20de], 0x63 => [0x5e8f,0x20de], 0x64 => [0x9023,0x20de], + 0x65 => [0x5f71,0x20de], 0x66 => [0x4f8b,0x20de], 0x67 => [0x6e90,0x20de], + 0x68 => [0x5b50,0x20de], 0x69 => [0x524d,0x20de], 0x6a => [0x7bc0,0x20de], + 0x6b => [0x63a5,0x20de], 0x6c => [0x52a9,0x20de], 0x6d => [0x6307,0x20de], + 0x6e => [0x4ed6,0x20de], 0x6f => [0x6d3e,0x20de], 0x70 => [0x5f62,0x20de], + 0x71 => [0xc870,0x20de], 0x72 => [0xbb38,0x20de,0xf87a], + 0x73 => [0xb2f5,0x20de,0xf87a], 0x74 => [0xc8fc,0x20de,0xf87a], + 0x75 => [0xb73b,0x20de,0xf87a], 0x76 => [0x8a3b,0x20de,0xf87a], + 0x77 => [0xad50,0x20de,0xf87a], 0x78 => [0xc5ed,0x20de,0xf87a], + 0x79 => [0xc74c,0x20de,0xf87a], 0x7a => [0xc815,0x20de,0xf87a], + 0x7b => [0xd574,0x20de,0xf87a], 0x7c => [0xc608,0x20de,0xf87a], + 0x7d => [0xc874,0x20dd], 0x81 => [0xb77c,0x20dd], 0x82 => [0xb9c8,0x20dd], + 0x83 => [0xbc14,0x20dd], 0x84 => [0xc0ac,0x20dd], 0x85 => [0xc544,0x20dd], + 0x86 => [0xc790,0x20dd], 0x87 => [0xcc28,0x20dd], 0x88 => [0xce74,0x20dd], + 0x89 => [0xd0c0,0x20dd], 0x8a => [0xd30c,0x20dd], 0x8b => [0xb192,0x20dd], + 0x8c => [0xb0ae,0x20dd], 0x8d => [0xba85,0x20dd], 0x8e => [0xb300,0x20dd], + 0x8f => [0xd615,0x20dd], 0x90 => [0xbd80,0x20dd], 0x91 => [0xc804,0x20dd], + 0x92 => [0xc811,0x20dd], 0x93 => [0xc218,0x20dd], 0x94 => [0xb3d9,0x20dd], + 0x95 => [0xbe44,0x20dd], 0x96 => [0xac8c,0x20dd], 0x97 => [0xbc18,0x20dd], + 0x98 => [0xc18d,0x20dd], 0x99 => [0xc778,0x20dd], 0x9a => [0xbcf8,0x20dd], + 0x9b => [0xc57d,0x20dd], 0x9c => [0xc219,0x20dd], 0x9d => [0xc720,0x20dd], + 0x9e => [0xad00,0x20dd], 0x9f => [0x51a0,0x20dd], 0xa1 => 0x3041, + 0xa2 => 0x3042, 0xa3 => 0x3043, 0xa4 => 0x3044, 0xa5 => 0x3045, + 0xa6 => 0x3046, 0xa7 => 0x3047, 0xa8 => 0x3048, 0xa9 => 0x3049, + 0xaa => 0x304a, 0xab => 0x304b, 0xac => 0x304c, 0xad => 0x304d, + 0xae => 0x304e, 0xaf => 0x304f, 0xb0 => 0x3050, 0xb1 => 0x3051, + 0xb2 => 0x3052, 0xb3 => 0x3053, 0xb4 => 0x3054, 0xb5 => 0x3055, + 0xb6 => 0x3056, 0xb7 => 0x3057, 0xb8 => 0x3058, 0xb9 => 0x3059, + 0xba => 0x305a, 0xbb => 0x305b, 0xbc => 0x305c, 0xbd => 0x305d, + 0xbe => 0x305e, 0xbf => 0x305f, 0xc0 => 0x3060, 0xc1 => 0x3061, + 0xc2 => 0x3062, 0xc3 => 0x3063, 0xc4 => 0x3064, 0xc5 => 0x3065, + 0xc6 => 0x3066, 0xc7 => 0x3067, 0xc8 => 0x3068, 0xc9 => 0x3069, + 0xca => 0x306a, 0xcb => 0x306b, 0xcc => 0x306c, 0xcd => 0x306d, + 0xce => 0x306e, 0xcf => 0x306f, 0xd0 => 0x3070, 0xd1 => 0x3071, + 0xd2 => 0x3072, 0xd3 => 0x3073, 0xd4 => 0x3074, 0xd5 => 0x3075, + 0xd6 => 0x3076, 0xd7 => 0x3077, 0xd8 => 0x3078, 0xd9 => 0x3079, + 0xda => 0x307a, 0xdb => 0x307b, 0xdc => 0x307c, 0xdd => 0x307d, + 0xde => 0x307e, 0xdf => 0x307f, 0xe0 => 0x3080, 0xe1 => 0x3081, + 0xe2 => 0x3082, 0xe3 => 0x3083, 0xe4 => 0x3084, 0xe5 => 0x3085, + 0xe6 => 0x3086, 0xe7 => 0x3087, 0xe8 => 0x3088, 0xe9 => 0x3089, + 0xea => 0x308a, 0xeb => 0x308b, 0xec => 0x308c, 0xed => 0x308d, + 0xee => 0x308e, 0xef => 0x308f, 0xf0 => 0x3090, 0xf1 => 0x3091, + 0xf2 => 0x3092, 0xf3 => 0x3093, 0xf4 => 0x2483, 0xf5 => 0x2484, + 0xf6 => 0x2485, 0xf7 => 0x2486, 0xf8 => 0x2487, + 0xf9 => [0xf862,0x28,0x32,0x31,0x29], 0xfa => [0xf862,0x28,0x32,0x32,0x29], + 0xfb => [0xf862,0x28,0x32,0x33,0x29], 0xfc => [0xf862,0x28,0x32,0x34,0x29], + 0xfd => [0xf862,0x28,0x32,0x35,0x29], 0xfe => [0xf862,0x28,0x32,0x36,0x29], + }, + 0xab => { + 0x41 => [0xc870,0x20dd], 0x42 => [0xad6d,0x20dd], 0x43 => [0xac10,0x20dd], + 0x44 => [0x5370,0x20dd], 0x45 => [0x8863,0x20dd], 0x46 => [0x672b,0x20dd], + 0x47 => [0xac70,0x20dd], 0x48 => [0xb2f5,0x20dd], 0x49 => [0xbcc0,0x20dd], + 0x4a => [0xc0c1,0x20dd], 0x4b => [0xc13c,0x20dd], 0x4c => [0xc2e0,0x20dd], + 0x4d => [0xc5ec,0x20dd], 0x4e => [0xc608,0x20dd], 0x4f => [0xc6d0,0x20dd], + 0x50 => [0xc791,0x20dd], 0x51 => [0xc900,0x20dd], 0x52 => [0xd0b9,0x20dd], + 0x53 => [0xc678,0x20dd], 0x54 => [0xd65c,0x20dd], 0x55 => [0xac04,0x20dd], + 0x56 => [0xac19,0x20dd], 0x57 => [0xc2e4,0x20dd], 0x58 => [0x611f,0x20dd], + 0x59 => [0x6163,0x20dd], 0x5a => [0x4ee3,0x20dd], 0x5b => [0x52d5,0x20dd], + 0x5c => 0x3294, 0x5d => [0x53cd,0x20dd], 0x5e => [0x526f,0x20dd], + 0x5f => [0x81ea,0x20dd], 0x60 => [0x524d,0x20dd], 0x61 => [0x96fb,0x20dd], + 0x62 => [0x63a5,0x20dd], 0x63 => [0x52a9,0x20dd], 0x64 => [0x6ce8,0x20dd], + 0x65 => [0x53c3,0x20dd], 0x66 => [0x672c,0x20dd], 0x67 => [0x65b0,0x20dd], + 0x68 => [0x73fe,0x20dd], 0x69 => [0x5f62,0x20dd], 0x6a => [0x9593,0x20dd], + 0x6b => [0x570b,0x20dd], 0x6c => 0x32a5, 0x6d => [0x4ed6,0x20dd], + 0x6e => [0xbe60,0x20dd], 0x6f => [0xc2dc,0x20dd], 0x70 => [0xc785,0x20dd], + 0x71 => [0xc73c,0x20dd], 0x72 => [0xc74c,0x20dd], 0x73 => [0xc9c1,0x20dd], + 0x74 => [0xd45c,0x20dd], 0x75 => [0xac00,0x20dd], 0x76 => [0xb098,0x20dd], + 0x77 => [0xb2e4,0x20dd], 0x78 => [0xd558,0x20dd], + 0x79 => [0xb9c8,0x20dd,0xf87a], 0x7a => [0xbc14,0x20dd,0xf87a], + 0x7b => [0xc0ac,0x20dd,0xf87a], 0x7c => [0xc544,0x20dd,0xf87a], + 0x7d => [0xc790,0x20dd,0xf87a], 0x81 => [0xcc28,0x20dd,0xf87a], + 0x82 => [0xce74,0x20dd,0xf87a], 0x83 => [0xd0c0,0x20dd,0xf87a], + 0x84 => [0xd30c,0x20dd,0xf87a], 0x85 => [0xd558,0x20dd,0xf87a], + 0x86 => [0xbe44,0x20dd,0xf87a], 0x87 => [0xb2f5,0x20dd,0xf87a], + 0x88 => [0xbe60,0x20dd,0xf87a], 0x89 => [0xbcf8,0x20dd,0xf87a], + 0x8a => [0xb2e8,0x20dd,0xf87a], 0x8b => [0xc13c,0x20dd,0xf87a], + 0x8c => [0xc2dc,0x20dd,0xf87a], 0x8d => [0xc5ec,0x20dd,0xf87a], + 0x8e => [0xc608,0x20dd,0xf87a], 0x8f => [0xc73c,0x20dd,0xf87a], + 0x90 => [0xc74c,0x20dd,0xf87a], 0x91 => [0xc785,0x20dd,0xf87a], + 0x92 => [0xc81c,0x20dd,0xf87a], 0x93 => [0xc874,0x20dd,0xf87a], + 0x94 => [0xc900,0x20dd,0xf87a], 0x95 => [0xd45c,0x20dd,0xf87a], + 0x96 => [0xd574,0x20dd,0xf87a], 0x97 => [0xb290,0x20dd,0xf87a], + 0x98 => [0xb192,0x20dd,0xf87a], 0x99 => [0xb0ae,0x20dd,0xf87a], + 0x9a => [0xbc18,0x20dd,0xf87a], 0x9b => [0xac00,0x20dd,0xf87a], + 0x9c => [0xb098,0x20dd,0xf87a], 0x9d => [0xb2e4,0x20dd,0xf87a], + 0x9e => [0xb77c,0x20dd,0xf87a], 0x9f => [0xc678,0x20dd,0xf87a], + 0xa1 => 0x30a1, 0xa2 => 0x30a2, 0xa3 => 0x30a3, 0xa4 => 0x30a4, + 0xa5 => 0x30a5, 0xa6 => 0x30a6, 0xa7 => 0x30a7, 0xa8 => 0x30a8, + 0xa9 => 0x30a9, 0xaa => 0x30aa, 0xab => 0x30ab, 0xac => 0x30ac, + 0xad => 0x30ad, 0xae => 0x30ae, 0xaf => 0x30af, 0xb0 => 0x30b0, + 0xb1 => 0x30b1, 0xb2 => 0x30b2, 0xb3 => 0x30b3, 0xb4 => 0x30b4, + 0xb5 => 0x30b5, 0xb6 => 0x30b6, 0xb7 => 0x30b7, 0xb8 => 0x30b8, + 0xb9 => 0x30b9, 0xba => 0x30ba, 0xbb => 0x30bb, 0xbc => 0x30bc, + 0xbd => 0x30bd, 0xbe => 0x30be, 0xbf => 0x30bf, 0xc0 => 0x30c0, + 0xc1 => 0x30c1, 0xc2 => 0x30c2, 0xc3 => 0x30c3, 0xc4 => 0x30c4, + 0xc5 => 0x30c5, 0xc6 => 0x30c6, 0xc7 => 0x30c7, 0xc8 => 0x30c8, + 0xc9 => 0x30c9, 0xca => 0x30ca, 0xcb => 0x30cb, 0xcc => 0x30cc, + 0xcd => 0x30cd, 0xce => 0x30ce, 0xcf => 0x30cf, 0xd0 => 0x30d0, + 0xd1 => 0x30d1, 0xd2 => 0x30d2, 0xd3 => 0x30d3, 0xd4 => 0x30d4, + 0xd5 => 0x30d5, 0xd6 => 0x30d6, 0xd7 => 0x30d7, 0xd8 => 0x30d8, + 0xd9 => 0x30d9, 0xda => 0x30da, 0xdb => 0x30db, 0xdc => 0x30dc, + 0xdd => 0x30dd, 0xde => 0x30de, 0xdf => 0x30df, 0xe0 => 0x30e0, + 0xe1 => 0x30e1, 0xe2 => 0x30e2, 0xe3 => 0x30e3, 0xe4 => 0x30e4, + 0xe5 => 0x30e5, 0xe6 => 0x30e6, 0xe7 => 0x30e7, 0xe8 => 0x30e8, + 0xe9 => 0x30e9, 0xea => 0x30ea, 0xeb => 0x30eb, 0xec => 0x30ec, + 0xed => 0x30ed, 0xee => 0x30ee, 0xef => 0x30ef, 0xf0 => 0x30f0, + 0xf1 => 0x30f1, 0xf2 => 0x30f2, 0xf3 => 0x30f3, 0xf4 => 0x30f4, + 0xf5 => 0x30f5, 0xf6 => 0x30f6, 0xf7 => [0xf862,0x28,0x32,0x37,0x29], + 0xf8 => [0xf862,0x28,0x32,0x38,0x29], 0xf9 => [0xf862,0x28,0x32,0x39,0x29], + 0xfa => [0xf862,0x28,0x33,0x30,0x29], + }, + 0xac => { + 0x41 => 0x21f0, 0x42 => 0xf843, 0x43 => 0x27b5, 0x44 => [0x2964,0xf87f], + 0x45 => [0x2962,0xf87f], 0x46 => [0x21e8,0xf870], 0x47 => [0x21e6,0xf870], + 0x48 => 0x27a4, 0x49 => 0xf844, 0x4a => 0xf84b, 0x4b => 0xf84a, + 0x4c => [0x21c0,0xf87f], 0x4d => [0x21bc,0xf87f], 0x4e => [0x21e8,0xf87f], + 0x4f => [0x21e6,0xf87f], 0x50 => 0x21b6, 0x51 => 0x21b7, 0x52 => 0x219d, + 0x53 => 0x219c, 0x54 => 0xf842, 0x55 => [0x2190,0xf87a], + 0x56 => [0x2192,0xf87a], 0x57 => [0x2191,0xf87a], 0x58 => [0x2193,0xf87a], + 0x59 => [0x21e6,0xf87c], 0x5a => [0x21e8,0xf87c], 0x5b => [0x21e7,0xf87c], + 0x5c => [0x21e9,0xf87c], 0x5d => [0x2190,0xf873], 0x5e => 0x2794, + 0x5f => 0xf845, 0x60 => [0x2191,0xf873], 0x61 => [0x2193,0xf873], + 0x62 => [0x2190,0xf878], 0x63 => [0x2192,0xf878], 0x64 => [0x2191,0xf878], + 0x65 => [0x2193,0xf878], 0x66 => [0x2190,0xf874], 0x67 => [0x2192,0xf874], + 0x68 => [0x2191,0xf874], 0x69 => [0x2193,0xf874], 0x6a => 0x21e0, + 0x6b => 0x21e2, 0x6c => 0x21e1, 0x6d => 0x21e3, 0x6e => [0x21e6,0xf875], + 0x6f => [0x21e8,0xf875], 0x70 => [0x21e7,0xf875], 0x71 => [0x21e9,0xf875], + 0x72 => 0x21e6, 0x73 => 0x21e8, 0x74 => 0x21e7, 0x75 => 0x21e9, + 0x76 => [0x2936,0xf87a], 0x77 => [0x21b1,0xf87a], 0x78 => [0x21bb,0xf87a], + 0x79 => [0x2935,0xf87a], 0x7a => [0x21b0,0xf87a], 0x7b => [0x2937,0xf87a], + 0x7c => [0x2939,0xf87a], 0x7d => [0x2934,0xf87a], 0x81 => [0x2936,0xf87c], + 0x82 => [0x21b1,0xf87c], 0x83 => [0x21bb,0xf87c], 0x84 => [0x2935,0xf87c], + 0x85 => [0x21b0,0xf87c], 0x86 => [0x2937,0xf87c], 0x87 => [0x2939,0xf87c], + 0x88 => [0x2934,0xf87c], 0x89 => [0x2190,0xf870], 0x8a => [0x2192,0xf870], + 0x8b => [0x2191,0xf870], 0x8c => [0x2193,0xf870], 0x8d => 0x261d, + 0x8e => 0x261f, 0x8f => [0x261d,0xf87f], 0x90 => [0x261f,0xf87f], + 0x91 => [0xb2e8,0x20dd], 0x92 => [0xcc38,0x20dd], 0x93 => [0xc18c,0x20dd], + 0x94 => [0xc911,0x20dd], 0x95 => [0xc77c,0x20dd], 0x96 => [0xc774,0x20dd], + 0x97 => [0xd734,0x20dd], 0xa1 => 0x0410, 0xa2 => 0x0411, 0xa3 => 0x0412, + 0xa4 => 0x0413, 0xa5 => 0x0414, 0xa6 => 0x0415, 0xa7 => 0x0401, + 0xa8 => 0x0416, 0xa9 => 0x0417, 0xaa => 0x0418, 0xab => 0x0419, + 0xac => 0x041a, 0xad => 0x041b, 0xae => 0x041c, 0xaf => 0x041d, + 0xb0 => 0x041e, 0xb1 => 0x041f, 0xb2 => 0x0420, 0xb3 => 0x0421, + 0xb4 => 0x0422, 0xb5 => 0x0423, 0xb6 => 0x0424, 0xb7 => 0x0425, + 0xb8 => 0x0426, 0xb9 => 0x0427, 0xba => 0x0428, 0xbb => 0x0429, + 0xbc => 0x042a, 0xbd => 0x042b, 0xbe => 0x042c, 0xbf => 0x042d, + 0xc0 => 0x042e, 0xc1 => 0x042f, 0xc2 => [0x31,0x20de,0xf875], + 0xc3 => [0x32,0x20de,0xf875], 0xc4 => [0x33,0x20de,0xf875], + 0xc5 => [0x34,0x20de,0xf875], 0xc6 => [0x35,0x20de,0xf875], + 0xc7 => [0x36,0x20de,0xf875], 0xc8 => [0x37,0x20de,0xf875], + 0xc9 => [0x38,0x20de,0xf875], 0xca => [0x39,0x20de,0xf875], + 0xcb => [0xf866,0x5b,0x31,0x30,0x5d], 0xcc => [0xf866,0x5b,0x31,0x31,0x5d], + 0xcd => [0xf866,0x5b,0x31,0x32,0x5d], 0xce => [0xf866,0x5b,0x31,0x33,0x5d], + 0xcf => [0xf866,0x5b,0x31,0x34,0x5d], 0xd0 => [0xf866,0x5b,0x31,0x35,0x5d], + 0xd1 => 0x0430, 0xd2 => 0x0431, 0xd3 => 0x0432, 0xd4 => 0x0433, + 0xd5 => 0x0434, 0xd6 => 0x0435, 0xd7 => 0x0451, 0xd8 => 0x0436, + 0xd9 => 0x0437, 0xda => 0x0438, 0xdb => 0x0439, 0xdc => 0x043a, + 0xdd => 0x043b, 0xde => 0x043c, 0xdf => 0x043d, 0xe0 => 0x043e, + 0xe1 => 0x043f, 0xe2 => 0x0440, 0xe3 => 0x0441, 0xe4 => 0x0442, + 0xe5 => 0x0443, 0xe6 => 0x0444, 0xe7 => 0x0445, 0xe8 => 0x0446, + 0xe9 => 0x0447, 0xea => 0x0448, 0xeb => 0x0449, 0xec => 0x044a, + 0xed => 0x044b, 0xee => 0x044c, 0xef => 0x044d, 0xf0 => 0x044e, + 0xf1 => 0x044f, 0xf2 => [0xf866,0x5b,0x31,0x36,0x5d], + 0xf3 => [0xf866,0x5b,0x31,0x37,0x5d], 0xf4 => [0xf866,0x5b,0x31,0x38,0x5d], + 0xf5 => [0xf866,0x5b,0x31,0x39,0x5d], 0xf6 => [0xf866,0x5b,0x32,0x30,0x5d], + }, + 0xad => { + 0x41 => [0x4e00,0x20de,0xf87a], 0x42 => [0x4e8c,0x20de,0xf87a], + 0x43 => [0x4e09,0x20de,0xf87a], 0x44 => [0x56db,0x20de,0xf87a], + 0x45 => [0x4e94,0x20de,0xf87a], 0x46 => [0x516d,0x20de,0xf87a], + 0x47 => [0x4e03,0x20de,0xf87a], 0x48 => [0x516b,0x20de,0xf87a], + 0x49 => [0x4e5d,0x20de,0xf87a], 0x4a => [0x5341,0x20de,0xf87a], + 0x4b => [0xf863,0x5b,0x5341,0x4e00,0x5d], + 0x4c => [0xf863,0x5b,0x5341,0x4e8c,0x5d], + 0x4d => [0xf863,0x5b,0x5341,0x4e09,0x5d], + 0x4e => [0xf863,0x5b,0x5341,0x56db,0x5d], + 0x4f => [0xf863,0x5b,0x5341,0x4e94,0x5d], + 0x50 => [0xf863,0x5b,0x5341,0x516d,0x5d], + 0x51 => [0xf863,0x5b,0x5341,0x4e03,0x5d], + 0x52 => [0xf863,0x5b,0x5341,0x516b,0x5d], + 0x53 => [0xf863,0x5b,0x5341,0x4e5d,0x5d], + 0x54 => [0xf863,0x5b,0x4e8c,0x5341,0x5d], 0x55 => [0x4e00,0x20de], + 0x56 => [0x4e8c,0x20de], 0x57 => [0x4e09,0x20de], 0x58 => [0x56db,0x20de], + 0x59 => [0x4e94,0x20de], 0x5a => [0x516d,0x20de], 0x5b => [0x4e03,0x20de], + 0x5c => [0x516b,0x20de], 0x5d => [0x4e5d,0x20de], 0x5e => [0x5341,0x20de], + 0x5f => [0xf862,0x5b,0x5341,0x4e00,0x5d], + 0x60 => [0xf862,0x5b,0x5341,0x4e8c,0x5d], + 0x61 => [0xf862,0x5b,0x5341,0x4e09,0x5d], + 0x62 => [0xf862,0x5b,0x5341,0x56db,0x5d], + 0x63 => [0xf862,0x5b,0x5341,0x4e94,0x5d], + 0x64 => [0xf862,0x5b,0x5341,0x516d,0x5d], + 0x65 => [0xf862,0x5b,0x5341,0x4e03,0x5d], + 0x66 => [0xf862,0x5b,0x5341,0x516b,0x5d], + 0x67 => [0xf862,0x5b,0x5341,0x4e5d,0x5d], + 0x68 => [0xf862,0x5b,0x4e8c,0x5341,0x5d], 0x69 => [0x65e5,0x20de], + 0x6a => [0x6708,0x20de], 0x6b => [0x706b,0x20de], 0x6c => [0x6c34,0x20de], + 0x6d => [0x6728,0x20de], 0x6e => [0x91d1,0x20de], 0x6f => [0x571f,0x20de], + 0x70 => 0x3290, 0x71 => 0x328a, 0x72 => 0x328b, 0x73 => 0x328c, + 0x74 => 0x328d, 0x75 => 0x328e, 0x76 => 0x328f, + 0x77 => [0x65e5,0x20de,0xf87c], 0x78 => [0x6708,0x20de,0xf87c], + 0x79 => [0x706b,0x20de,0xf87c], 0x7a => [0x6c34,0x20de,0xf87c], + 0x7b => [0x6728,0x20de,0xf87c], 0x7c => [0x91d1,0x20de,0xf87c], + 0x7d => [0x571f,0x20de,0xf87c], 0xa1 => [0x300c,0xf879], + 0xa2 => [0x300d,0xf879], 0xa3 => [0x300e,0xf879], 0xa4 => [0x300f,0xf879], + 0xa5 => [0x21e8,0xf878], 0xa6 => [0x21e6,0xf878], 0xa7 => [0x21e7,0xf878], + 0xa8 => [0x21e9,0xf878], 0xa9 => 0x301e, 0xaa => 0x301f, 0xab => 0x2036, + 0xac => [0x2033,0xf873], 0xad => 0x2035, 0xae => [0x2032,0xf873], + 0xaf => [0x21e7,0xf87f], 0xb0 => [0x21,0xf87f], + }, + 0xb0 => { + 0xa1 => 0xac00, 0xa2 => 0xac01, 0xa3 => 0xac04, 0xa4 => 0xac07, + 0xa5 => 0xac08, 0xa6 => 0xac09, 0xa7 => 0xac0a, 0xa8 => 0xac10, + 0xa9 => 0xac11, 0xaa => 0xac12, 0xab => 0xac13, 0xac => 0xac14, + 0xad => 0xac15, 0xae => 0xac16, 0xaf => 0xac17, 0xb0 => 0xac19, + 0xb1 => 0xac1a, 0xb2 => 0xac1b, 0xb3 => 0xac1c, 0xb4 => 0xac1d, + 0xb5 => 0xac20, 0xb6 => 0xac24, 0xb7 => 0xac2c, 0xb8 => 0xac2d, + 0xb9 => 0xac2f, 0xba => 0xac30, 0xbb => 0xac31, 0xbc => 0xac38, + 0xbd => 0xac39, 0xbe => 0xac3c, 0xbf => 0xac40, 0xc0 => 0xac4b, + 0xc1 => 0xac4d, 0xc2 => 0xac54, 0xc3 => 0xac58, 0xc4 => 0xac5c, + 0xc5 => 0xac70, 0xc6 => 0xac71, 0xc7 => 0xac74, 0xc8 => 0xac77, + 0xc9 => 0xac78, 0xca => 0xac7a, 0xcb => 0xac80, 0xcc => 0xac81, + 0xcd => 0xac83, 0xce => 0xac84, 0xcf => 0xac85, 0xd0 => 0xac86, + 0xd1 => 0xac89, 0xd2 => 0xac8a, 0xd3 => 0xac8b, 0xd4 => 0xac8c, + 0xd5 => 0xac90, 0xd6 => 0xac94, 0xd7 => 0xac9c, 0xd8 => 0xac9d, + 0xd9 => 0xac9f, 0xda => 0xaca0, 0xdb => 0xaca1, 0xdc => 0xaca8, + 0xdd => 0xaca9, 0xde => 0xacaa, 0xdf => 0xacac, 0xe0 => 0xacaf, + 0xe1 => 0xacb0, 0xe2 => 0xacb8, 0xe3 => 0xacb9, 0xe4 => 0xacbb, + 0xe5 => 0xacbc, 0xe6 => 0xacbd, 0xe7 => 0xacc1, 0xe8 => 0xacc4, + 0xe9 => 0xacc8, 0xea => 0xaccc, 0xeb => 0xacd5, 0xec => 0xacd7, + 0xed => 0xace0, 0xee => 0xace1, 0xef => 0xace4, 0xf0 => 0xace7, + 0xf1 => 0xace8, 0xf2 => 0xacea, 0xf3 => 0xacec, 0xf4 => 0xacef, + 0xf5 => 0xacf0, 0xf6 => 0xacf1, 0xf7 => 0xacf3, 0xf8 => 0xacf5, + 0xf9 => 0xacf6, 0xfa => 0xacfc, 0xfb => 0xacfd, 0xfc => 0xad00, + 0xfd => 0xad04, 0xfe => 0xad06, + }, + 0xb1 => { + 0xa1 => 0xad0c, 0xa2 => 0xad0d, 0xa3 => 0xad0f, 0xa4 => 0xad11, + 0xa5 => 0xad18, 0xa6 => 0xad1c, 0xa7 => 0xad20, 0xa8 => 0xad29, + 0xa9 => 0xad2c, 0xaa => 0xad2d, 0xab => 0xad34, 0xac => 0xad35, + 0xad => 0xad38, 0xae => 0xad3c, 0xaf => 0xad44, 0xb0 => 0xad45, + 0xb1 => 0xad47, 0xb2 => 0xad49, 0xb3 => 0xad50, 0xb4 => 0xad54, + 0xb5 => 0xad58, 0xb6 => 0xad61, 0xb7 => 0xad63, 0xb8 => 0xad6c, + 0xb9 => 0xad6d, 0xba => 0xad70, 0xbb => 0xad73, 0xbc => 0xad74, + 0xbd => 0xad75, 0xbe => 0xad76, 0xbf => 0xad7b, 0xc0 => 0xad7c, + 0xc1 => 0xad7d, 0xc2 => 0xad7f, 0xc3 => 0xad81, 0xc4 => 0xad82, + 0xc5 => 0xad88, 0xc6 => 0xad89, 0xc7 => 0xad8c, 0xc8 => 0xad90, + 0xc9 => 0xad9c, 0xca => 0xad9d, 0xcb => 0xada4, 0xcc => 0xadb7, + 0xcd => 0xadc0, 0xce => 0xadc1, 0xcf => 0xadc4, 0xd0 => 0xadc8, + 0xd1 => 0xadd0, 0xd2 => 0xadd1, 0xd3 => 0xadd3, 0xd4 => 0xaddc, + 0xd5 => 0xade0, 0xd6 => 0xade4, 0xd7 => 0xadf8, 0xd8 => 0xadf9, + 0xd9 => 0xadfc, 0xda => 0xadff, 0xdb => 0xae00, 0xdc => 0xae01, + 0xdd => 0xae08, 0xde => 0xae09, 0xdf => 0xae0b, 0xe0 => 0xae0d, + 0xe1 => 0xae14, 0xe2 => 0xae30, 0xe3 => 0xae31, 0xe4 => 0xae34, + 0xe5 => 0xae37, 0xe6 => 0xae38, 0xe7 => 0xae3a, 0xe8 => 0xae40, + 0xe9 => 0xae41, 0xea => 0xae43, 0xeb => 0xae45, 0xec => 0xae46, + 0xed => 0xae4a, 0xee => 0xae4c, 0xef => 0xae4d, 0xf0 => 0xae4e, + 0xf1 => 0xae50, 0xf2 => 0xae54, 0xf3 => 0xae56, 0xf4 => 0xae5c, + 0xf5 => 0xae5d, 0xf6 => 0xae5f, 0xf7 => 0xae60, 0xf8 => 0xae61, + 0xf9 => 0xae65, 0xfa => 0xae68, 0xfb => 0xae69, 0xfc => 0xae6c, + 0xfd => 0xae70, 0xfe => 0xae78, + }, + 0xb2 => { + 0xa1 => 0xae79, 0xa2 => 0xae7b, 0xa3 => 0xae7c, 0xa4 => 0xae7d, + 0xa5 => 0xae84, 0xa6 => 0xae85, 0xa7 => 0xae8c, 0xa8 => 0xaebc, + 0xa9 => 0xaebd, 0xaa => 0xaebe, 0xab => 0xaec0, 0xac => 0xaec4, + 0xad => 0xaecc, 0xae => 0xaecd, 0xaf => 0xaecf, 0xb0 => 0xaed0, + 0xb1 => 0xaed1, 0xb2 => 0xaed8, 0xb3 => 0xaed9, 0xb4 => 0xaedc, + 0xb5 => 0xaee8, 0xb6 => 0xaeeb, 0xb7 => 0xaeed, 0xb8 => 0xaef4, + 0xb9 => 0xaef8, 0xba => 0xaefc, 0xbb => 0xaf07, 0xbc => 0xaf08, + 0xbd => 0xaf0d, 0xbe => 0xaf10, 0xbf => 0xaf2c, 0xc0 => 0xaf2d, + 0xc1 => 0xaf30, 0xc2 => 0xaf32, 0xc3 => 0xaf34, 0xc4 => 0xaf3c, + 0xc5 => 0xaf3d, 0xc6 => 0xaf3f, 0xc7 => 0xaf41, 0xc8 => 0xaf42, + 0xc9 => 0xaf43, 0xca => 0xaf48, 0xcb => 0xaf49, 0xcc => 0xaf50, + 0xcd => 0xaf5c, 0xce => 0xaf5d, 0xcf => 0xaf64, 0xd0 => 0xaf65, + 0xd1 => 0xaf79, 0xd2 => 0xaf80, 0xd3 => 0xaf84, 0xd4 => 0xaf88, + 0xd5 => 0xaf90, 0xd6 => 0xaf91, 0xd7 => 0xaf95, 0xd8 => 0xaf9c, + 0xd9 => 0xafb8, 0xda => 0xafb9, 0xdb => 0xafbc, 0xdc => 0xafc0, + 0xdd => 0xafc7, 0xde => 0xafc8, 0xdf => 0xafc9, 0xe0 => 0xafcb, + 0xe1 => 0xafcd, 0xe2 => 0xafce, 0xe3 => 0xafd4, 0xe4 => 0xafdc, + 0xe5 => 0xafe8, 0xe6 => 0xafe9, 0xe7 => 0xaff0, 0xe8 => 0xaff1, + 0xe9 => 0xaff4, 0xea => 0xaff8, 0xeb => 0xb000, 0xec => 0xb001, + 0xed => 0xb004, 0xee => 0xb00c, 0xef => 0xb010, 0xf0 => 0xb014, + 0xf1 => 0xb01c, 0xf2 => 0xb01d, 0xf3 => 0xb028, 0xf4 => 0xb044, + 0xf5 => 0xb045, 0xf6 => 0xb048, 0xf7 => 0xb04a, 0xf8 => 0xb04c, + 0xf9 => 0xb04e, 0xfa => 0xb053, 0xfb => 0xb054, 0xfc => 0xb055, + 0xfd => 0xb057, 0xfe => 0xb059, + }, + 0xb3 => { + 0xa1 => 0xb05d, 0xa2 => 0xb07c, 0xa3 => 0xb07d, 0xa4 => 0xb080, + 0xa5 => 0xb084, 0xa6 => 0xb08c, 0xa7 => 0xb08d, 0xa8 => 0xb08f, + 0xa9 => 0xb091, 0xaa => 0xb098, 0xab => 0xb099, 0xac => 0xb09a, + 0xad => 0xb09c, 0xae => 0xb09f, 0xaf => 0xb0a0, 0xb0 => 0xb0a1, + 0xb1 => 0xb0a2, 0xb2 => 0xb0a8, 0xb3 => 0xb0a9, 0xb4 => 0xb0ab, + 0xb5 => 0xb0ac, 0xb6 => 0xb0ad, 0xb7 => 0xb0ae, 0xb8 => 0xb0af, + 0xb9 => 0xb0b1, 0xba => 0xb0b3, 0xbb => 0xb0b4, 0xbc => 0xb0b5, + 0xbd => 0xb0b8, 0xbe => 0xb0bc, 0xbf => 0xb0c4, 0xc0 => 0xb0c5, + 0xc1 => 0xb0c7, 0xc2 => 0xb0c8, 0xc3 => 0xb0c9, 0xc4 => 0xb0d0, + 0xc5 => 0xb0d1, 0xc6 => 0xb0d4, 0xc7 => 0xb0d8, 0xc8 => 0xb0e0, + 0xc9 => 0xb0e5, 0xca => 0xb108, 0xcb => 0xb109, 0xcc => 0xb10b, + 0xcd => 0xb10c, 0xce => 0xb110, 0xcf => 0xb112, 0xd0 => 0xb113, + 0xd1 => 0xb118, 0xd2 => 0xb119, 0xd3 => 0xb11b, 0xd4 => 0xb11c, + 0xd5 => 0xb11d, 0xd6 => 0xb123, 0xd7 => 0xb124, 0xd8 => 0xb125, + 0xd9 => 0xb128, 0xda => 0xb12c, 0xdb => 0xb134, 0xdc => 0xb135, + 0xdd => 0xb137, 0xde => 0xb138, 0xdf => 0xb139, 0xe0 => 0xb140, + 0xe1 => 0xb141, 0xe2 => 0xb144, 0xe3 => 0xb148, 0xe4 => 0xb150, + 0xe5 => 0xb151, 0xe6 => 0xb154, 0xe7 => 0xb155, 0xe8 => 0xb158, + 0xe9 => 0xb15c, 0xea => 0xb160, 0xeb => 0xb178, 0xec => 0xb179, + 0xed => 0xb17c, 0xee => 0xb180, 0xef => 0xb182, 0xf0 => 0xb188, + 0xf1 => 0xb189, 0xf2 => 0xb18b, 0xf3 => 0xb18d, 0xf4 => 0xb192, + 0xf5 => 0xb193, 0xf6 => 0xb194, 0xf7 => 0xb198, 0xf8 => 0xb19c, + 0xf9 => 0xb1a8, 0xfa => 0xb1cc, 0xfb => 0xb1d0, 0xfc => 0xb1d4, + 0xfd => 0xb1dc, 0xfe => 0xb1dd, + }, + 0xb4 => { + 0xa1 => 0xb1df, 0xa2 => 0xb1e8, 0xa3 => 0xb1e9, 0xa4 => 0xb1ec, + 0xa5 => 0xb1f0, 0xa6 => 0xb1f9, 0xa7 => 0xb1fb, 0xa8 => 0xb1fd, + 0xa9 => 0xb204, 0xaa => 0xb205, 0xab => 0xb208, 0xac => 0xb20b, + 0xad => 0xb20c, 0xae => 0xb214, 0xaf => 0xb215, 0xb0 => 0xb217, + 0xb1 => 0xb219, 0xb2 => 0xb220, 0xb3 => 0xb234, 0xb4 => 0xb23c, + 0xb5 => 0xb258, 0xb6 => 0xb25c, 0xb7 => 0xb260, 0xb8 => 0xb268, + 0xb9 => 0xb269, 0xba => 0xb274, 0xbb => 0xb275, 0xbc => 0xb27c, + 0xbd => 0xb284, 0xbe => 0xb285, 0xbf => 0xb289, 0xc0 => 0xb290, + 0xc1 => 0xb291, 0xc2 => 0xb294, 0xc3 => 0xb298, 0xc4 => 0xb299, + 0xc5 => 0xb29a, 0xc6 => 0xb2a0, 0xc7 => 0xb2a1, 0xc8 => 0xb2a3, + 0xc9 => 0xb2a5, 0xca => 0xb2a6, 0xcb => 0xb2aa, 0xcc => 0xb2ac, + 0xcd => 0xb2b0, 0xce => 0xb2b4, 0xcf => 0xb2c8, 0xd0 => 0xb2c9, + 0xd1 => 0xb2cc, 0xd2 => 0xb2d0, 0xd3 => 0xb2d2, 0xd4 => 0xb2d8, + 0xd5 => 0xb2d9, 0xd6 => 0xb2db, 0xd7 => 0xb2dd, 0xd8 => 0xb2e2, + 0xd9 => 0xb2e4, 0xda => 0xb2e5, 0xdb => 0xb2e6, 0xdc => 0xb2e8, + 0xdd => 0xb2eb, 0xde => 0xb2ec, 0xdf => 0xb2ed, 0xe0 => 0xb2ee, + 0xe1 => 0xb2ef, 0xe2 => 0xb2f3, 0xe3 => 0xb2f4, 0xe4 => 0xb2f5, + 0xe5 => 0xb2f7, 0xe6 => 0xb2f8, 0xe7 => 0xb2f9, 0xe8 => 0xb2fa, + 0xe9 => 0xb2fb, 0xea => 0xb2ff, 0xeb => 0xb300, 0xec => 0xb301, + 0xed => 0xb304, 0xee => 0xb308, 0xef => 0xb310, 0xf0 => 0xb311, + 0xf1 => 0xb313, 0xf2 => 0xb314, 0xf3 => 0xb315, 0xf4 => 0xb31c, + 0xf5 => 0xb354, 0xf6 => 0xb355, 0xf7 => 0xb356, 0xf8 => 0xb358, + 0xf9 => 0xb35b, 0xfa => 0xb35c, 0xfb => 0xb35e, 0xfc => 0xb35f, + 0xfd => 0xb364, 0xfe => 0xb365, + }, + 0xb5 => { + 0xa1 => 0xb367, 0xa2 => 0xb369, 0xa3 => 0xb36b, 0xa4 => 0xb36e, + 0xa5 => 0xb370, 0xa6 => 0xb371, 0xa7 => 0xb374, 0xa8 => 0xb378, + 0xa9 => 0xb380, 0xaa => 0xb381, 0xab => 0xb383, 0xac => 0xb384, + 0xad => 0xb385, 0xae => 0xb38c, 0xaf => 0xb390, 0xb0 => 0xb394, + 0xb1 => 0xb3a0, 0xb2 => 0xb3a1, 0xb3 => 0xb3a8, 0xb4 => 0xb3ac, + 0xb5 => 0xb3c4, 0xb6 => 0xb3c5, 0xb7 => 0xb3c8, 0xb8 => 0xb3cb, + 0xb9 => 0xb3cc, 0xba => 0xb3ce, 0xbb => 0xb3d0, 0xbc => 0xb3d4, + 0xbd => 0xb3d5, 0xbe => 0xb3d7, 0xbf => 0xb3d9, 0xc0 => 0xb3db, + 0xc1 => 0xb3dd, 0xc2 => 0xb3e0, 0xc3 => 0xb3e4, 0xc4 => 0xb3e8, + 0xc5 => 0xb3fc, 0xc6 => 0xb410, 0xc7 => 0xb418, 0xc8 => 0xb41c, + 0xc9 => 0xb420, 0xca => 0xb428, 0xcb => 0xb429, 0xcc => 0xb42b, + 0xcd => 0xb434, 0xce => 0xb450, 0xcf => 0xb451, 0xd0 => 0xb454, + 0xd1 => 0xb458, 0xd2 => 0xb460, 0xd3 => 0xb461, 0xd4 => 0xb463, + 0xd5 => 0xb465, 0xd6 => 0xb46c, 0xd7 => 0xb480, 0xd8 => 0xb488, + 0xd9 => 0xb49d, 0xda => 0xb4a4, 0xdb => 0xb4a8, 0xdc => 0xb4ac, + 0xdd => 0xb4b5, 0xde => 0xb4b7, 0xdf => 0xb4b9, 0xe0 => 0xb4c0, + 0xe1 => 0xb4c4, 0xe2 => 0xb4c8, 0xe3 => 0xb4d0, 0xe4 => 0xb4d5, + 0xe5 => 0xb4dc, 0xe6 => 0xb4dd, 0xe7 => 0xb4e0, 0xe8 => 0xb4e3, + 0xe9 => 0xb4e4, 0xea => 0xb4e6, 0xeb => 0xb4ec, 0xec => 0xb4ed, + 0xed => 0xb4ef, 0xee => 0xb4f1, 0xef => 0xb4f8, 0xf0 => 0xb514, + 0xf1 => 0xb515, 0xf2 => 0xb518, 0xf3 => 0xb51b, 0xf4 => 0xb51c, + 0xf5 => 0xb524, 0xf6 => 0xb525, 0xf7 => 0xb527, 0xf8 => 0xb528, + 0xf9 => 0xb529, 0xfa => 0xb52a, 0xfb => 0xb530, 0xfc => 0xb531, + 0xfd => 0xb534, 0xfe => 0xb538, + }, + 0xb6 => { + 0xa1 => 0xb540, 0xa2 => 0xb541, 0xa3 => 0xb543, 0xa4 => 0xb544, + 0xa5 => 0xb545, 0xa6 => 0xb54b, 0xa7 => 0xb54c, 0xa8 => 0xb54d, + 0xa9 => 0xb550, 0xaa => 0xb554, 0xab => 0xb55c, 0xac => 0xb55d, + 0xad => 0xb55f, 0xae => 0xb560, 0xaf => 0xb561, 0xb0 => 0xb5a0, + 0xb1 => 0xb5a1, 0xb2 => 0xb5a4, 0xb3 => 0xb5a8, 0xb4 => 0xb5aa, + 0xb5 => 0xb5ab, 0xb6 => 0xb5b0, 0xb7 => 0xb5b1, 0xb8 => 0xb5b3, + 0xb9 => 0xb5b4, 0xba => 0xb5b5, 0xbb => 0xb5bb, 0xbc => 0xb5bc, + 0xbd => 0xb5bd, 0xbe => 0xb5c0, 0xbf => 0xb5c4, 0xc0 => 0xb5cc, + 0xc1 => 0xb5cd, 0xc2 => 0xb5cf, 0xc3 => 0xb5d0, 0xc4 => 0xb5d1, + 0xc5 => 0xb5d8, 0xc6 => 0xb5ec, 0xc7 => 0xb610, 0xc8 => 0xb611, + 0xc9 => 0xb614, 0xca => 0xb618, 0xcb => 0xb625, 0xcc => 0xb62c, + 0xcd => 0xb634, 0xce => 0xb648, 0xcf => 0xb664, 0xd0 => 0xb668, + 0xd1 => 0xb69c, 0xd2 => 0xb69d, 0xd3 => 0xb6a0, 0xd4 => 0xb6a4, + 0xd5 => 0xb6ab, 0xd6 => 0xb6ac, 0xd7 => 0xb6b1, 0xd8 => 0xb6d4, + 0xd9 => 0xb6f0, 0xda => 0xb6f4, 0xdb => 0xb6f8, 0xdc => 0xb700, + 0xdd => 0xb701, 0xde => 0xb705, 0xdf => 0xb728, 0xe0 => 0xb729, + 0xe1 => 0xb72c, 0xe2 => 0xb72f, 0xe3 => 0xb730, 0xe4 => 0xb738, + 0xe5 => 0xb739, 0xe6 => 0xb73b, 0xe7 => 0xb744, 0xe8 => 0xb748, + 0xe9 => 0xb74c, 0xea => 0xb754, 0xeb => 0xb755, 0xec => 0xb760, + 0xed => 0xb764, 0xee => 0xb768, 0xef => 0xb770, 0xf0 => 0xb771, + 0xf1 => 0xb773, 0xf2 => 0xb775, 0xf3 => 0xb77c, 0xf4 => 0xb77d, + 0xf5 => 0xb780, 0xf6 => 0xb784, 0xf7 => 0xb78c, 0xf8 => 0xb78d, + 0xf9 => 0xb78f, 0xfa => 0xb790, 0xfb => 0xb791, 0xfc => 0xb792, + 0xfd => 0xb796, 0xfe => 0xb797, + }, + 0xb7 => { + 0xa1 => 0xb798, 0xa2 => 0xb799, 0xa3 => 0xb79c, 0xa4 => 0xb7a0, + 0xa5 => 0xb7a8, 0xa6 => 0xb7a9, 0xa7 => 0xb7ab, 0xa8 => 0xb7ac, + 0xa9 => 0xb7ad, 0xaa => 0xb7b4, 0xab => 0xb7b5, 0xac => 0xb7b8, + 0xad => 0xb7c7, 0xae => 0xb7c9, 0xaf => 0xb7ec, 0xb0 => 0xb7ed, + 0xb1 => 0xb7f0, 0xb2 => 0xb7f4, 0xb3 => 0xb7fc, 0xb4 => 0xb7fd, + 0xb5 => 0xb7ff, 0xb6 => 0xb800, 0xb7 => 0xb801, 0xb8 => 0xb807, + 0xb9 => 0xb808, 0xba => 0xb809, 0xbb => 0xb80c, 0xbc => 0xb810, + 0xbd => 0xb818, 0xbe => 0xb819, 0xbf => 0xb81b, 0xc0 => 0xb81d, + 0xc1 => 0xb824, 0xc2 => 0xb825, 0xc3 => 0xb828, 0xc4 => 0xb82c, + 0xc5 => 0xb834, 0xc6 => 0xb835, 0xc7 => 0xb837, 0xc8 => 0xb838, + 0xc9 => 0xb839, 0xca => 0xb840, 0xcb => 0xb844, 0xcc => 0xb851, + 0xcd => 0xb853, 0xce => 0xb85c, 0xcf => 0xb85d, 0xd0 => 0xb860, + 0xd1 => 0xb864, 0xd2 => 0xb86c, 0xd3 => 0xb86d, 0xd4 => 0xb86f, + 0xd5 => 0xb871, 0xd6 => 0xb878, 0xd7 => 0xb87c, 0xd8 => 0xb88d, + 0xd9 => 0xb8a8, 0xda => 0xb8b0, 0xdb => 0xb8b4, 0xdc => 0xb8b8, + 0xdd => 0xb8c0, 0xde => 0xb8c1, 0xdf => 0xb8c3, 0xe0 => 0xb8c5, + 0xe1 => 0xb8cc, 0xe2 => 0xb8d0, 0xe3 => 0xb8d4, 0xe4 => 0xb8dd, + 0xe5 => 0xb8df, 0xe6 => 0xb8e1, 0xe7 => 0xb8e8, 0xe8 => 0xb8e9, + 0xe9 => 0xb8ec, 0xea => 0xb8f0, 0xeb => 0xb8f8, 0xec => 0xb8f9, + 0xed => 0xb8fb, 0xee => 0xb8fd, 0xef => 0xb904, 0xf0 => 0xb918, + 0xf1 => 0xb920, 0xf2 => 0xb93c, 0xf3 => 0xb93d, 0xf4 => 0xb940, + 0xf5 => 0xb944, 0xf6 => 0xb94c, 0xf7 => 0xb94f, 0xf8 => 0xb951, + 0xf9 => 0xb958, 0xfa => 0xb959, 0xfb => 0xb95c, 0xfc => 0xb960, + 0xfd => 0xb968, 0xfe => 0xb969, + }, + 0xb8 => { + 0xa1 => 0xb96b, 0xa2 => 0xb96d, 0xa3 => 0xb974, 0xa4 => 0xb975, + 0xa5 => 0xb978, 0xa6 => 0xb97c, 0xa7 => 0xb984, 0xa8 => 0xb985, + 0xa9 => 0xb987, 0xaa => 0xb989, 0xab => 0xb98a, 0xac => 0xb98d, + 0xad => 0xb98e, 0xae => 0xb9ac, 0xaf => 0xb9ad, 0xb0 => 0xb9b0, + 0xb1 => 0xb9b4, 0xb2 => 0xb9bc, 0xb3 => 0xb9bd, 0xb4 => 0xb9bf, + 0xb5 => 0xb9c1, 0xb6 => 0xb9c8, 0xb7 => 0xb9c9, 0xb8 => 0xb9cc, + 0xb9 => 0xb9ce, 0xba => 0xb9cf, 0xbb => 0xb9d0, 0xbc => 0xb9d1, + 0xbd => 0xb9d2, 0xbe => 0xb9d8, 0xbf => 0xb9d9, 0xc0 => 0xb9db, + 0xc1 => 0xb9dd, 0xc2 => 0xb9de, 0xc3 => 0xb9e1, 0xc4 => 0xb9e3, + 0xc5 => 0xb9e4, 0xc6 => 0xb9e5, 0xc7 => 0xb9e8, 0xc8 => 0xb9ec, + 0xc9 => 0xb9f4, 0xca => 0xb9f5, 0xcb => 0xb9f7, 0xcc => 0xb9f8, + 0xcd => 0xb9f9, 0xce => 0xb9fa, 0xcf => 0xba00, 0xd0 => 0xba01, + 0xd1 => 0xba08, 0xd2 => 0xba15, 0xd3 => 0xba38, 0xd4 => 0xba39, + 0xd5 => 0xba3c, 0xd6 => 0xba40, 0xd7 => 0xba42, 0xd8 => 0xba48, + 0xd9 => 0xba49, 0xda => 0xba4b, 0xdb => 0xba4d, 0xdc => 0xba4e, + 0xdd => 0xba53, 0xde => 0xba54, 0xdf => 0xba55, 0xe0 => 0xba58, + 0xe1 => 0xba5c, 0xe2 => 0xba64, 0xe3 => 0xba65, 0xe4 => 0xba67, + 0xe5 => 0xba68, 0xe6 => 0xba69, 0xe7 => 0xba70, 0xe8 => 0xba71, + 0xe9 => 0xba74, 0xea => 0xba78, 0xeb => 0xba83, 0xec => 0xba84, + 0xed => 0xba85, 0xee => 0xba87, 0xef => 0xba8c, 0xf0 => 0xbaa8, + 0xf1 => 0xbaa9, 0xf2 => 0xbaab, 0xf3 => 0xbaac, 0xf4 => 0xbab0, + 0xf5 => 0xbab2, 0xf6 => 0xbab8, 0xf7 => 0xbab9, 0xf8 => 0xbabb, + 0xf9 => 0xbabd, 0xfa => 0xbac4, 0xfb => 0xbac8, 0xfc => 0xbad8, + 0xfd => 0xbad9, 0xfe => 0xbafc, + }, + 0xb9 => { + 0xa1 => 0xbb00, 0xa2 => 0xbb04, 0xa3 => 0xbb0d, 0xa4 => 0xbb0f, + 0xa5 => 0xbb11, 0xa6 => 0xbb18, 0xa7 => 0xbb1c, 0xa8 => 0xbb20, + 0xa9 => 0xbb29, 0xaa => 0xbb2b, 0xab => 0xbb34, 0xac => 0xbb35, + 0xad => 0xbb36, 0xae => 0xbb38, 0xaf => 0xbb3b, 0xb0 => 0xbb3c, + 0xb1 => 0xbb3d, 0xb2 => 0xbb3e, 0xb3 => 0xbb44, 0xb4 => 0xbb45, + 0xb5 => 0xbb47, 0xb6 => 0xbb49, 0xb7 => 0xbb4d, 0xb8 => 0xbb4f, + 0xb9 => 0xbb50, 0xba => 0xbb54, 0xbb => 0xbb58, 0xbc => 0xbb61, + 0xbd => 0xbb63, 0xbe => 0xbb6c, 0xbf => 0xbb88, 0xc0 => 0xbb8c, + 0xc1 => 0xbb90, 0xc2 => 0xbba4, 0xc3 => 0xbba8, 0xc4 => 0xbbac, + 0xc5 => 0xbbb4, 0xc6 => 0xbbb7, 0xc7 => 0xbbc0, 0xc8 => 0xbbc4, + 0xc9 => 0xbbc8, 0xca => 0xbbd0, 0xcb => 0xbbd3, 0xcc => 0xbbf8, + 0xcd => 0xbbf9, 0xce => 0xbbfc, 0xcf => 0xbbff, 0xd0 => 0xbc00, + 0xd1 => 0xbc02, 0xd2 => 0xbc08, 0xd3 => 0xbc09, 0xd4 => 0xbc0b, + 0xd5 => 0xbc0c, 0xd6 => 0xbc0d, 0xd7 => 0xbc0f, 0xd8 => 0xbc11, + 0xd9 => 0xbc14, 0xda => 0xbc15, 0xdb => 0xbc16, 0xdc => 0xbc17, + 0xdd => 0xbc18, 0xde => 0xbc1b, 0xdf => 0xbc1c, 0xe0 => 0xbc1d, + 0xe1 => 0xbc1e, 0xe2 => 0xbc1f, 0xe3 => 0xbc24, 0xe4 => 0xbc25, + 0xe5 => 0xbc27, 0xe6 => 0xbc29, 0xe7 => 0xbc2d, 0xe8 => 0xbc30, + 0xe9 => 0xbc31, 0xea => 0xbc34, 0xeb => 0xbc38, 0xec => 0xbc40, + 0xed => 0xbc41, 0xee => 0xbc43, 0xef => 0xbc44, 0xf0 => 0xbc45, + 0xf1 => 0xbc49, 0xf2 => 0xbc4c, 0xf3 => 0xbc4d, 0xf4 => 0xbc50, + 0xf5 => 0xbc5d, 0xf6 => 0xbc84, 0xf7 => 0xbc85, 0xf8 => 0xbc88, + 0xf9 => 0xbc8b, 0xfa => 0xbc8c, 0xfb => 0xbc8e, 0xfc => 0xbc94, + 0xfd => 0xbc95, 0xfe => 0xbc97, + }, + 0xba => { + 0xa1 => 0xbc99, 0xa2 => 0xbc9a, 0xa3 => 0xbca0, 0xa4 => 0xbca1, + 0xa5 => 0xbca4, 0xa6 => 0xbca7, 0xa7 => 0xbca8, 0xa8 => 0xbcb0, + 0xa9 => 0xbcb1, 0xaa => 0xbcb3, 0xab => 0xbcb4, 0xac => 0xbcb5, + 0xad => 0xbcbc, 0xae => 0xbcbd, 0xaf => 0xbcc0, 0xb0 => 0xbcc4, + 0xb1 => 0xbccd, 0xb2 => 0xbccf, 0xb3 => 0xbcd0, 0xb4 => 0xbcd1, + 0xb5 => 0xbcd5, 0xb6 => 0xbcd8, 0xb7 => 0xbcdc, 0xb8 => 0xbcf4, + 0xb9 => 0xbcf5, 0xba => 0xbcf6, 0xbb => 0xbcf8, 0xbc => 0xbcfc, + 0xbd => 0xbd04, 0xbe => 0xbd05, 0xbf => 0xbd07, 0xc0 => 0xbd09, + 0xc1 => 0xbd10, 0xc2 => 0xbd14, 0xc3 => 0xbd24, 0xc4 => 0xbd2c, + 0xc5 => 0xbd40, 0xc6 => 0xbd48, 0xc7 => 0xbd49, 0xc8 => 0xbd4c, + 0xc9 => 0xbd50, 0xca => 0xbd58, 0xcb => 0xbd59, 0xcc => 0xbd64, + 0xcd => 0xbd68, 0xce => 0xbd80, 0xcf => 0xbd81, 0xd0 => 0xbd84, + 0xd1 => 0xbd87, 0xd2 => 0xbd88, 0xd3 => 0xbd89, 0xd4 => 0xbd8a, + 0xd5 => 0xbd90, 0xd6 => 0xbd91, 0xd7 => 0xbd93, 0xd8 => 0xbd95, + 0xd9 => 0xbd99, 0xda => 0xbd9a, 0xdb => 0xbd9c, 0xdc => 0xbda4, + 0xdd => 0xbdb0, 0xde => 0xbdb8, 0xdf => 0xbdd4, 0xe0 => 0xbdd5, + 0xe1 => 0xbdd8, 0xe2 => 0xbddc, 0xe3 => 0xbde9, 0xe4 => 0xbdf0, + 0xe5 => 0xbdf4, 0xe6 => 0xbdf8, 0xe7 => 0xbe00, 0xe8 => 0xbe03, + 0xe9 => 0xbe05, 0xea => 0xbe0c, 0xeb => 0xbe0d, 0xec => 0xbe10, + 0xed => 0xbe14, 0xee => 0xbe1c, 0xef => 0xbe1d, 0xf0 => 0xbe1f, + 0xf1 => 0xbe44, 0xf2 => 0xbe45, 0xf3 => 0xbe48, 0xf4 => 0xbe4c, + 0xf5 => 0xbe4e, 0xf6 => 0xbe54, 0xf7 => 0xbe55, 0xf8 => 0xbe57, + 0xf9 => 0xbe59, 0xfa => 0xbe5a, 0xfb => 0xbe5b, 0xfc => 0xbe60, + 0xfd => 0xbe61, 0xfe => 0xbe64, + }, + 0xbb => { + 0xa1 => 0xbe68, 0xa2 => 0xbe6a, 0xa3 => 0xbe70, 0xa4 => 0xbe71, + 0xa5 => 0xbe73, 0xa6 => 0xbe74, 0xa7 => 0xbe75, 0xa8 => 0xbe7b, + 0xa9 => 0xbe7c, 0xaa => 0xbe7d, 0xab => 0xbe80, 0xac => 0xbe84, + 0xad => 0xbe8c, 0xae => 0xbe8d, 0xaf => 0xbe8f, 0xb0 => 0xbe90, + 0xb1 => 0xbe91, 0xb2 => 0xbe98, 0xb3 => 0xbe99, 0xb4 => 0xbea8, + 0xb5 => 0xbed0, 0xb6 => 0xbed1, 0xb7 => 0xbed4, 0xb8 => 0xbed7, + 0xb9 => 0xbed8, 0xba => 0xbee0, 0xbb => 0xbee3, 0xbc => 0xbee4, + 0xbd => 0xbee5, 0xbe => 0xbeec, 0xbf => 0xbf01, 0xc0 => 0xbf08, + 0xc1 => 0xbf09, 0xc2 => 0xbf18, 0xc3 => 0xbf19, 0xc4 => 0xbf1b, + 0xc5 => 0xbf1c, 0xc6 => 0xbf1d, 0xc7 => 0xbf40, 0xc8 => 0xbf41, + 0xc9 => 0xbf44, 0xca => 0xbf48, 0xcb => 0xbf50, 0xcc => 0xbf51, + 0xcd => 0xbf55, 0xce => 0xbf94, 0xcf => 0xbfb0, 0xd0 => 0xbfc5, + 0xd1 => 0xbfcc, 0xd2 => 0xbfcd, 0xd3 => 0xbfd0, 0xd4 => 0xbfd4, + 0xd5 => 0xbfdc, 0xd6 => 0xbfdf, 0xd7 => 0xbfe1, 0xd8 => 0xc03c, + 0xd9 => 0xc051, 0xda => 0xc058, 0xdb => 0xc05c, 0xdc => 0xc060, + 0xdd => 0xc068, 0xde => 0xc069, 0xdf => 0xc090, 0xe0 => 0xc091, + 0xe1 => 0xc094, 0xe2 => 0xc098, 0xe3 => 0xc0a0, 0xe4 => 0xc0a1, + 0xe5 => 0xc0a3, 0xe6 => 0xc0a5, 0xe7 => 0xc0ac, 0xe8 => 0xc0ad, + 0xe9 => 0xc0af, 0xea => 0xc0b0, 0xeb => 0xc0b3, 0xec => 0xc0b4, + 0xed => 0xc0b5, 0xee => 0xc0b6, 0xef => 0xc0bc, 0xf0 => 0xc0bd, + 0xf1 => 0xc0bf, 0xf2 => 0xc0c0, 0xf3 => 0xc0c1, 0xf4 => 0xc0c5, + 0xf5 => 0xc0c8, 0xf6 => 0xc0c9, 0xf7 => 0xc0cc, 0xf8 => 0xc0d0, + 0xf9 => 0xc0d8, 0xfa => 0xc0d9, 0xfb => 0xc0db, 0xfc => 0xc0dc, + 0xfd => 0xc0dd, 0xfe => 0xc0e4, + }, + 0xbc => { + 0xa1 => 0xc0e5, 0xa2 => 0xc0e8, 0xa3 => 0xc0ec, 0xa4 => 0xc0f4, + 0xa5 => 0xc0f5, 0xa6 => 0xc0f7, 0xa7 => 0xc0f9, 0xa8 => 0xc100, + 0xa9 => 0xc104, 0xaa => 0xc108, 0xab => 0xc110, 0xac => 0xc115, + 0xad => 0xc11c, 0xae => 0xc11d, 0xaf => 0xc11e, 0xb0 => 0xc11f, + 0xb1 => 0xc120, 0xb2 => 0xc123, 0xb3 => 0xc124, 0xb4 => 0xc126, + 0xb5 => 0xc127, 0xb6 => 0xc12c, 0xb7 => 0xc12d, 0xb8 => 0xc12f, + 0xb9 => 0xc130, 0xba => 0xc131, 0xbb => 0xc136, 0xbc => 0xc138, + 0xbd => 0xc139, 0xbe => 0xc13c, 0xbf => 0xc140, 0xc0 => 0xc148, + 0xc1 => 0xc149, 0xc2 => 0xc14b, 0xc3 => 0xc14c, 0xc4 => 0xc14d, + 0xc5 => 0xc154, 0xc6 => 0xc155, 0xc7 => 0xc158, 0xc8 => 0xc15c, + 0xc9 => 0xc164, 0xca => 0xc165, 0xcb => 0xc167, 0xcc => 0xc168, + 0xcd => 0xc169, 0xce => 0xc170, 0xcf => 0xc174, 0xd0 => 0xc178, + 0xd1 => 0xc185, 0xd2 => 0xc18c, 0xd3 => 0xc18d, 0xd4 => 0xc18e, + 0xd5 => 0xc190, 0xd6 => 0xc194, 0xd7 => 0xc196, 0xd8 => 0xc19c, + 0xd9 => 0xc19d, 0xda => 0xc19f, 0xdb => 0xc1a1, 0xdc => 0xc1a5, + 0xdd => 0xc1a8, 0xde => 0xc1a9, 0xdf => 0xc1ac, 0xe0 => 0xc1b0, + 0xe1 => 0xc1bd, 0xe2 => 0xc1c4, 0xe3 => 0xc1c8, 0xe4 => 0xc1cc, + 0xe5 => 0xc1d4, 0xe6 => 0xc1d7, 0xe7 => 0xc1d8, 0xe8 => 0xc1e0, + 0xe9 => 0xc1e4, 0xea => 0xc1e8, 0xeb => 0xc1f0, 0xec => 0xc1f1, + 0xed => 0xc1f3, 0xee => 0xc1fc, 0xef => 0xc1fd, 0xf0 => 0xc200, + 0xf1 => 0xc204, 0xf2 => 0xc20c, 0xf3 => 0xc20d, 0xf4 => 0xc20f, + 0xf5 => 0xc211, 0xf6 => 0xc218, 0xf7 => 0xc219, 0xf8 => 0xc21c, + 0xf9 => 0xc21f, 0xfa => 0xc220, 0xfb => 0xc228, 0xfc => 0xc229, + 0xfd => 0xc22b, 0xfe => 0xc22d, + }, + 0xbd => { + 0xa1 => 0xc22f, 0xa2 => 0xc231, 0xa3 => 0xc232, 0xa4 => 0xc234, + 0xa5 => 0xc248, 0xa6 => 0xc250, 0xa7 => 0xc251, 0xa8 => 0xc254, + 0xa9 => 0xc258, 0xaa => 0xc260, 0xab => 0xc265, 0xac => 0xc26c, + 0xad => 0xc26d, 0xae => 0xc270, 0xaf => 0xc274, 0xb0 => 0xc27c, + 0xb1 => 0xc27d, 0xb2 => 0xc27f, 0xb3 => 0xc281, 0xb4 => 0xc288, + 0xb5 => 0xc289, 0xb6 => 0xc290, 0xb7 => 0xc298, 0xb8 => 0xc29b, + 0xb9 => 0xc29d, 0xba => 0xc2a4, 0xbb => 0xc2a5, 0xbc => 0xc2a8, + 0xbd => 0xc2ac, 0xbe => 0xc2ad, 0xbf => 0xc2b4, 0xc0 => 0xc2b5, + 0xc1 => 0xc2b7, 0xc2 => 0xc2b9, 0xc3 => 0xc2dc, 0xc4 => 0xc2dd, + 0xc5 => 0xc2e0, 0xc6 => 0xc2e3, 0xc7 => 0xc2e4, 0xc8 => 0xc2eb, + 0xc9 => 0xc2ec, 0xca => 0xc2ed, 0xcb => 0xc2ef, 0xcc => 0xc2f1, + 0xcd => 0xc2f6, 0xce => 0xc2f8, 0xcf => 0xc2f9, 0xd0 => 0xc2fb, + 0xd1 => 0xc2fc, 0xd2 => 0xc300, 0xd3 => 0xc308, 0xd4 => 0xc309, + 0xd5 => 0xc30c, 0xd6 => 0xc30d, 0xd7 => 0xc313, 0xd8 => 0xc314, + 0xd9 => 0xc315, 0xda => 0xc318, 0xdb => 0xc31c, 0xdc => 0xc324, + 0xdd => 0xc325, 0xde => 0xc328, 0xdf => 0xc329, 0xe0 => 0xc345, + 0xe1 => 0xc368, 0xe2 => 0xc369, 0xe3 => 0xc36c, 0xe4 => 0xc370, + 0xe5 => 0xc372, 0xe6 => 0xc378, 0xe7 => 0xc379, 0xe8 => 0xc37c, + 0xe9 => 0xc37d, 0xea => 0xc384, 0xeb => 0xc388, 0xec => 0xc38c, + 0xed => 0xc3c0, 0xee => 0xc3d8, 0xef => 0xc3d9, 0xf0 => 0xc3dc, + 0xf1 => 0xc3df, 0xf2 => 0xc3e0, 0xf3 => 0xc3e2, 0xf4 => 0xc3e8, + 0xf5 => 0xc3e9, 0xf6 => 0xc3ed, 0xf7 => 0xc3f4, 0xf8 => 0xc3f5, + 0xf9 => 0xc3f8, 0xfa => 0xc408, 0xfb => 0xc410, 0xfc => 0xc424, + 0xfd => 0xc42c, 0xfe => 0xc430, + }, + 0xbe => { + 0xa1 => 0xc434, 0xa2 => 0xc43c, 0xa3 => 0xc43d, 0xa4 => 0xc448, + 0xa5 => 0xc464, 0xa6 => 0xc465, 0xa7 => 0xc468, 0xa8 => 0xc46c, + 0xa9 => 0xc474, 0xaa => 0xc475, 0xab => 0xc479, 0xac => 0xc480, + 0xad => 0xc494, 0xae => 0xc49c, 0xaf => 0xc4b8, 0xb0 => 0xc4bc, + 0xb1 => 0xc4e9, 0xb2 => 0xc4f0, 0xb3 => 0xc4f1, 0xb4 => 0xc4f4, + 0xb5 => 0xc4f8, 0xb6 => 0xc4fa, 0xb7 => 0xc4ff, 0xb8 => 0xc500, + 0xb9 => 0xc501, 0xba => 0xc50c, 0xbb => 0xc510, 0xbc => 0xc514, + 0xbd => 0xc51c, 0xbe => 0xc528, 0xbf => 0xc529, 0xc0 => 0xc52c, + 0xc1 => 0xc530, 0xc2 => 0xc538, 0xc3 => 0xc539, 0xc4 => 0xc53b, + 0xc5 => 0xc53d, 0xc6 => 0xc544, 0xc7 => 0xc545, 0xc8 => 0xc548, + 0xc9 => 0xc549, 0xca => 0xc54a, 0xcb => 0xc54c, 0xcc => 0xc54d, + 0xcd => 0xc54e, 0xce => 0xc553, 0xcf => 0xc554, 0xd0 => 0xc555, + 0xd1 => 0xc557, 0xd2 => 0xc558, 0xd3 => 0xc559, 0xd4 => 0xc55d, + 0xd5 => 0xc55e, 0xd6 => 0xc560, 0xd7 => 0xc561, 0xd8 => 0xc564, + 0xd9 => 0xc568, 0xda => 0xc570, 0xdb => 0xc571, 0xdc => 0xc573, + 0xdd => 0xc574, 0xde => 0xc575, 0xdf => 0xc57c, 0xe0 => 0xc57d, + 0xe1 => 0xc580, 0xe2 => 0xc584, 0xe3 => 0xc587, 0xe4 => 0xc58c, + 0xe5 => 0xc58d, 0xe6 => 0xc58f, 0xe7 => 0xc591, 0xe8 => 0xc595, + 0xe9 => 0xc597, 0xea => 0xc598, 0xeb => 0xc59c, 0xec => 0xc5a0, + 0xed => 0xc5a9, 0xee => 0xc5b4, 0xef => 0xc5b5, 0xf0 => 0xc5b8, + 0xf1 => 0xc5b9, 0xf2 => 0xc5bb, 0xf3 => 0xc5bc, 0xf4 => 0xc5bd, + 0xf5 => 0xc5be, 0xf6 => 0xc5c4, 0xf7 => 0xc5c5, 0xf8 => 0xc5c6, + 0xf9 => 0xc5c7, 0xfa => 0xc5c8, 0xfb => 0xc5c9, 0xfc => 0xc5ca, + 0xfd => 0xc5cc, 0xfe => 0xc5ce, + }, + 0xbf => { + 0xa1 => 0xc5d0, 0xa2 => 0xc5d1, 0xa3 => 0xc5d4, 0xa4 => 0xc5d8, + 0xa5 => 0xc5e0, 0xa6 => 0xc5e1, 0xa7 => 0xc5e3, 0xa8 => 0xc5e5, + 0xa9 => 0xc5ec, 0xaa => 0xc5ed, 0xab => 0xc5ee, 0xac => 0xc5f0, + 0xad => 0xc5f4, 0xae => 0xc5f6, 0xaf => 0xc5f7, 0xb0 => 0xc5fc, + 0xb1 => 0xc5fd, 0xb2 => 0xc5fe, 0xb3 => 0xc5ff, 0xb4 => 0xc600, + 0xb5 => 0xc601, 0xb6 => 0xc605, 0xb7 => 0xc606, 0xb8 => 0xc607, + 0xb9 => 0xc608, 0xba => 0xc60c, 0xbb => 0xc610, 0xbc => 0xc618, + 0xbd => 0xc619, 0xbe => 0xc61b, 0xbf => 0xc61c, 0xc0 => 0xc624, + 0xc1 => 0xc625, 0xc2 => 0xc628, 0xc3 => 0xc62c, 0xc4 => 0xc62d, + 0xc5 => 0xc62e, 0xc6 => 0xc630, 0xc7 => 0xc633, 0xc8 => 0xc634, + 0xc9 => 0xc635, 0xca => 0xc637, 0xcb => 0xc639, 0xcc => 0xc63b, + 0xcd => 0xc640, 0xce => 0xc641, 0xcf => 0xc644, 0xd0 => 0xc648, + 0xd1 => 0xc650, 0xd2 => 0xc651, 0xd3 => 0xc653, 0xd4 => 0xc654, + 0xd5 => 0xc655, 0xd6 => 0xc65c, 0xd7 => 0xc65d, 0xd8 => 0xc660, + 0xd9 => 0xc66c, 0xda => 0xc66f, 0xdb => 0xc671, 0xdc => 0xc678, + 0xdd => 0xc679, 0xde => 0xc67c, 0xdf => 0xc680, 0xe0 => 0xc688, + 0xe1 => 0xc689, 0xe2 => 0xc68b, 0xe3 => 0xc68d, 0xe4 => 0xc694, + 0xe5 => 0xc695, 0xe6 => 0xc698, 0xe7 => 0xc69c, 0xe8 => 0xc6a4, + 0xe9 => 0xc6a5, 0xea => 0xc6a7, 0xeb => 0xc6a9, 0xec => 0xc6b0, + 0xed => 0xc6b1, 0xee => 0xc6b4, 0xef => 0xc6b8, 0xf0 => 0xc6b9, + 0xf1 => 0xc6ba, 0xf2 => 0xc6c0, 0xf3 => 0xc6c1, 0xf4 => 0xc6c3, + 0xf5 => 0xc6c5, 0xf6 => 0xc6cc, 0xf7 => 0xc6cd, 0xf8 => 0xc6d0, + 0xf9 => 0xc6d4, 0xfa => 0xc6dc, 0xfb => 0xc6dd, 0xfc => 0xc6e0, + 0xfd => 0xc6e1, 0xfe => 0xc6e8, + }, + 0xc0 => { + 0xa1 => 0xc6e9, 0xa2 => 0xc6ec, 0xa3 => 0xc6f0, 0xa4 => 0xc6f8, + 0xa5 => 0xc6f9, 0xa6 => 0xc6fd, 0xa7 => 0xc704, 0xa8 => 0xc705, + 0xa9 => 0xc708, 0xaa => 0xc70c, 0xab => 0xc714, 0xac => 0xc715, + 0xad => 0xc717, 0xae => 0xc719, 0xaf => 0xc720, 0xb0 => 0xc721, + 0xb1 => 0xc724, 0xb2 => 0xc728, 0xb3 => 0xc730, 0xb4 => 0xc731, + 0xb5 => 0xc733, 0xb6 => 0xc735, 0xb7 => 0xc737, 0xb8 => 0xc73c, + 0xb9 => 0xc73d, 0xba => 0xc740, 0xbb => 0xc744, 0xbc => 0xc74a, + 0xbd => 0xc74c, 0xbe => 0xc74d, 0xbf => 0xc74f, 0xc0 => 0xc751, + 0xc1 => 0xc752, 0xc2 => 0xc753, 0xc3 => 0xc754, 0xc4 => 0xc755, + 0xc5 => 0xc756, 0xc6 => 0xc757, 0xc7 => 0xc758, 0xc8 => 0xc75c, + 0xc9 => 0xc760, 0xca => 0xc768, 0xcb => 0xc76b, 0xcc => 0xc774, + 0xcd => 0xc775, 0xce => 0xc778, 0xcf => 0xc77c, 0xd0 => 0xc77d, + 0xd1 => 0xc77e, 0xd2 => 0xc783, 0xd3 => 0xc784, 0xd4 => 0xc785, + 0xd5 => 0xc787, 0xd6 => 0xc788, 0xd7 => 0xc789, 0xd8 => 0xc78a, + 0xd9 => 0xc78e, 0xda => 0xc790, 0xdb => 0xc791, 0xdc => 0xc794, + 0xdd => 0xc796, 0xde => 0xc797, 0xdf => 0xc798, 0xe0 => 0xc79a, + 0xe1 => 0xc7a0, 0xe2 => 0xc7a1, 0xe3 => 0xc7a3, 0xe4 => 0xc7a4, + 0xe5 => 0xc7a5, 0xe6 => 0xc7a6, 0xe7 => 0xc7ac, 0xe8 => 0xc7ad, + 0xe9 => 0xc7b0, 0xea => 0xc7b4, 0xeb => 0xc7bc, 0xec => 0xc7bd, + 0xed => 0xc7bf, 0xee => 0xc7c0, 0xef => 0xc7c1, 0xf0 => 0xc7c8, + 0xf1 => 0xc7c9, 0xf2 => 0xc7cc, 0xf3 => 0xc7ce, 0xf4 => 0xc7d0, + 0xf5 => 0xc7d8, 0xf6 => 0xc7dd, 0xf7 => 0xc7e4, 0xf8 => 0xc7e8, + 0xf9 => 0xc7ec, 0xfa => 0xc800, 0xfb => 0xc801, 0xfc => 0xc804, + 0xfd => 0xc808, 0xfe => 0xc80a, + }, + 0xc1 => { + 0xa1 => 0xc810, 0xa2 => 0xc811, 0xa3 => 0xc813, 0xa4 => 0xc815, + 0xa5 => 0xc816, 0xa6 => 0xc81c, 0xa7 => 0xc81d, 0xa8 => 0xc820, + 0xa9 => 0xc824, 0xaa => 0xc82c, 0xab => 0xc82d, 0xac => 0xc82f, + 0xad => 0xc831, 0xae => 0xc838, 0xaf => 0xc83c, 0xb0 => 0xc840, + 0xb1 => 0xc848, 0xb2 => 0xc849, 0xb3 => 0xc84c, 0xb4 => 0xc84d, + 0xb5 => 0xc854, 0xb6 => 0xc870, 0xb7 => 0xc871, 0xb8 => 0xc874, + 0xb9 => 0xc878, 0xba => 0xc87a, 0xbb => 0xc880, 0xbc => 0xc881, + 0xbd => 0xc883, 0xbe => 0xc885, 0xbf => 0xc886, 0xc0 => 0xc887, + 0xc1 => 0xc88b, 0xc2 => 0xc88c, 0xc3 => 0xc88d, 0xc4 => 0xc894, + 0xc5 => 0xc89d, 0xc6 => 0xc89f, 0xc7 => 0xc8a1, 0xc8 => 0xc8a8, + 0xc9 => 0xc8bc, 0xca => 0xc8bd, 0xcb => 0xc8c4, 0xcc => 0xc8c8, + 0xcd => 0xc8cc, 0xce => 0xc8d4, 0xcf => 0xc8d5, 0xd0 => 0xc8d7, + 0xd1 => 0xc8d9, 0xd2 => 0xc8e0, 0xd3 => 0xc8e1, 0xd4 => 0xc8e4, + 0xd5 => 0xc8f5, 0xd6 => 0xc8fc, 0xd7 => 0xc8fd, 0xd8 => 0xc900, + 0xd9 => 0xc904, 0xda => 0xc905, 0xdb => 0xc906, 0xdc => 0xc90c, + 0xdd => 0xc90d, 0xde => 0xc90f, 0xdf => 0xc911, 0xe0 => 0xc918, + 0xe1 => 0xc92c, 0xe2 => 0xc934, 0xe3 => 0xc950, 0xe4 => 0xc951, + 0xe5 => 0xc954, 0xe6 => 0xc958, 0xe7 => 0xc960, 0xe8 => 0xc961, + 0xe9 => 0xc963, 0xea => 0xc96c, 0xeb => 0xc970, 0xec => 0xc974, + 0xed => 0xc97c, 0xee => 0xc988, 0xef => 0xc989, 0xf0 => 0xc98c, + 0xf1 => 0xc990, 0xf2 => 0xc998, 0xf3 => 0xc999, 0xf4 => 0xc99b, + 0xf5 => 0xc99d, 0xf6 => 0xc9c0, 0xf7 => 0xc9c1, 0xf8 => 0xc9c4, + 0xf9 => 0xc9c7, 0xfa => 0xc9c8, 0xfb => 0xc9ca, 0xfc => 0xc9d0, + 0xfd => 0xc9d1, 0xfe => 0xc9d3, + }, + 0xc2 => { + 0xa1 => 0xc9d5, 0xa2 => 0xc9d6, 0xa3 => 0xc9d9, 0xa4 => 0xc9da, + 0xa5 => 0xc9dc, 0xa6 => 0xc9dd, 0xa7 => 0xc9e0, 0xa8 => 0xc9e2, + 0xa9 => 0xc9e4, 0xaa => 0xc9e7, 0xab => 0xc9ec, 0xac => 0xc9ed, + 0xad => 0xc9ef, 0xae => 0xc9f0, 0xaf => 0xc9f1, 0xb0 => 0xc9f8, + 0xb1 => 0xc9f9, 0xb2 => 0xc9fc, 0xb3 => 0xca00, 0xb4 => 0xca08, + 0xb5 => 0xca09, 0xb6 => 0xca0b, 0xb7 => 0xca0c, 0xb8 => 0xca0d, + 0xb9 => 0xca14, 0xba => 0xca18, 0xbb => 0xca29, 0xbc => 0xca4c, + 0xbd => 0xca4d, 0xbe => 0xca50, 0xbf => 0xca54, 0xc0 => 0xca5c, + 0xc1 => 0xca5d, 0xc2 => 0xca5f, 0xc3 => 0xca60, 0xc4 => 0xca61, + 0xc5 => 0xca68, 0xc6 => 0xca7d, 0xc7 => 0xca84, 0xc8 => 0xca98, + 0xc9 => 0xcabc, 0xca => 0xcabd, 0xcb => 0xcac0, 0xcc => 0xcac4, + 0xcd => 0xcacc, 0xce => 0xcacd, 0xcf => 0xcacf, 0xd0 => 0xcad1, + 0xd1 => 0xcad3, 0xd2 => 0xcad8, 0xd3 => 0xcad9, 0xd4 => 0xcae0, + 0xd5 => 0xcaec, 0xd6 => 0xcaf4, 0xd7 => 0xcb08, 0xd8 => 0xcb10, + 0xd9 => 0xcb14, 0xda => 0xcb18, 0xdb => 0xcb20, 0xdc => 0xcb21, + 0xdd => 0xcb41, 0xde => 0xcb48, 0xdf => 0xcb49, 0xe0 => 0xcb4c, + 0xe1 => 0xcb50, 0xe2 => 0xcb58, 0xe3 => 0xcb59, 0xe4 => 0xcb5d, + 0xe5 => 0xcb64, 0xe6 => 0xcb78, 0xe7 => 0xcb79, 0xe8 => 0xcb9c, + 0xe9 => 0xcbb8, 0xea => 0xcbd4, 0xeb => 0xcbe4, 0xec => 0xcbe7, + 0xed => 0xcbe9, 0xee => 0xcc0c, 0xef => 0xcc0d, 0xf0 => 0xcc10, + 0xf1 => 0xcc14, 0xf2 => 0xcc1c, 0xf3 => 0xcc1d, 0xf4 => 0xcc21, + 0xf5 => 0xcc22, 0xf6 => 0xcc27, 0xf7 => 0xcc28, 0xf8 => 0xcc29, + 0xf9 => 0xcc2c, 0xfa => 0xcc2e, 0xfb => 0xcc30, 0xfc => 0xcc38, + 0xfd => 0xcc39, 0xfe => 0xcc3b, + }, + 0xc3 => { + 0xa1 => 0xcc3c, 0xa2 => 0xcc3d, 0xa3 => 0xcc3e, 0xa4 => 0xcc44, + 0xa5 => 0xcc45, 0xa6 => 0xcc48, 0xa7 => 0xcc4c, 0xa8 => 0xcc54, + 0xa9 => 0xcc55, 0xaa => 0xcc57, 0xab => 0xcc58, 0xac => 0xcc59, + 0xad => 0xcc60, 0xae => 0xcc64, 0xaf => 0xcc66, 0xb0 => 0xcc68, + 0xb1 => 0xcc70, 0xb2 => 0xcc75, 0xb3 => 0xcc98, 0xb4 => 0xcc99, + 0xb5 => 0xcc9c, 0xb6 => 0xcca0, 0xb7 => 0xcca8, 0xb8 => 0xcca9, + 0xb9 => 0xccab, 0xba => 0xccac, 0xbb => 0xccad, 0xbc => 0xccb4, + 0xbd => 0xccb5, 0xbe => 0xccb8, 0xbf => 0xccbc, 0xc0 => 0xccc4, + 0xc1 => 0xccc5, 0xc2 => 0xccc7, 0xc3 => 0xccc9, 0xc4 => 0xccd0, + 0xc5 => 0xccd4, 0xc6 => 0xcce4, 0xc7 => 0xccec, 0xc8 => 0xccf0, + 0xc9 => 0xcd01, 0xca => 0xcd08, 0xcb => 0xcd09, 0xcc => 0xcd0c, + 0xcd => 0xcd10, 0xce => 0xcd18, 0xcf => 0xcd19, 0xd0 => 0xcd1b, + 0xd1 => 0xcd1d, 0xd2 => 0xcd24, 0xd3 => 0xcd28, 0xd4 => 0xcd2c, + 0xd5 => 0xcd39, 0xd6 => 0xcd5c, 0xd7 => 0xcd60, 0xd8 => 0xcd64, + 0xd9 => 0xcd6c, 0xda => 0xcd6d, 0xdb => 0xcd6f, 0xdc => 0xcd71, + 0xdd => 0xcd78, 0xde => 0xcd88, 0xdf => 0xcd94, 0xe0 => 0xcd95, + 0xe1 => 0xcd98, 0xe2 => 0xcd9c, 0xe3 => 0xcda4, 0xe4 => 0xcda5, + 0xe5 => 0xcda7, 0xe6 => 0xcda9, 0xe7 => 0xcdb0, 0xe8 => 0xcdc4, + 0xe9 => 0xcdcc, 0xea => 0xcdd0, 0xeb => 0xcde8, 0xec => 0xcdec, + 0xed => 0xcdf0, 0xee => 0xcdf8, 0xef => 0xcdf9, 0xf0 => 0xcdfb, + 0xf1 => 0xcdfd, 0xf2 => 0xce04, 0xf3 => 0xce08, 0xf4 => 0xce0c, + 0xf5 => 0xce14, 0xf6 => 0xce19, 0xf7 => 0xce20, 0xf8 => 0xce21, + 0xf9 => 0xce24, 0xfa => 0xce28, 0xfb => 0xce30, 0xfc => 0xce31, + 0xfd => 0xce33, 0xfe => 0xce35, + }, + 0xc4 => { + 0xa1 => 0xce58, 0xa2 => 0xce59, 0xa3 => 0xce5c, 0xa4 => 0xce5f, + 0xa5 => 0xce60, 0xa6 => 0xce61, 0xa7 => 0xce68, 0xa8 => 0xce69, + 0xa9 => 0xce6b, 0xaa => 0xce6d, 0xab => 0xce74, 0xac => 0xce75, + 0xad => 0xce78, 0xae => 0xce7c, 0xaf => 0xce84, 0xb0 => 0xce85, + 0xb1 => 0xce87, 0xb2 => 0xce89, 0xb3 => 0xce90, 0xb4 => 0xce91, + 0xb5 => 0xce94, 0xb6 => 0xce98, 0xb7 => 0xcea0, 0xb8 => 0xcea1, + 0xb9 => 0xcea3, 0xba => 0xcea4, 0xbb => 0xcea5, 0xbc => 0xceac, + 0xbd => 0xcead, 0xbe => 0xcec1, 0xbf => 0xcee4, 0xc0 => 0xcee5, + 0xc1 => 0xcee8, 0xc2 => 0xceeb, 0xc3 => 0xceec, 0xc4 => 0xcef4, + 0xc5 => 0xcef5, 0xc6 => 0xcef7, 0xc7 => 0xcef8, 0xc8 => 0xcef9, + 0xc9 => 0xcf00, 0xca => 0xcf01, 0xcb => 0xcf04, 0xcc => 0xcf08, + 0xcd => 0xcf10, 0xce => 0xcf11, 0xcf => 0xcf13, 0xd0 => 0xcf15, + 0xd1 => 0xcf1c, 0xd2 => 0xcf20, 0xd3 => 0xcf24, 0xd4 => 0xcf2c, + 0xd5 => 0xcf2d, 0xd6 => 0xcf2f, 0xd7 => 0xcf30, 0xd8 => 0xcf31, + 0xd9 => 0xcf38, 0xda => 0xcf54, 0xdb => 0xcf55, 0xdc => 0xcf58, + 0xdd => 0xcf5c, 0xde => 0xcf64, 0xdf => 0xcf65, 0xe0 => 0xcf67, + 0xe1 => 0xcf69, 0xe2 => 0xcf70, 0xe3 => 0xcf71, 0xe4 => 0xcf74, + 0xe5 => 0xcf78, 0xe6 => 0xcf80, 0xe7 => 0xcf85, 0xe8 => 0xcf8c, + 0xe9 => 0xcfa1, 0xea => 0xcfa8, 0xeb => 0xcfb0, 0xec => 0xcfc4, + 0xed => 0xcfe0, 0xee => 0xcfe1, 0xef => 0xcfe4, 0xf0 => 0xcfe8, + 0xf1 => 0xcff0, 0xf2 => 0xcff1, 0xf3 => 0xcff3, 0xf4 => 0xcff5, + 0xf5 => 0xcffc, 0xf6 => 0xd000, 0xf7 => 0xd004, 0xf8 => 0xd011, + 0xf9 => 0xd018, 0xfa => 0xd02d, 0xfb => 0xd034, 0xfc => 0xd035, + 0xfd => 0xd038, 0xfe => 0xd03c, + }, + 0xc5 => { + 0xa1 => 0xd044, 0xa2 => 0xd045, 0xa3 => 0xd047, 0xa4 => 0xd049, + 0xa5 => 0xd050, 0xa6 => 0xd054, 0xa7 => 0xd058, 0xa8 => 0xd060, + 0xa9 => 0xd06c, 0xaa => 0xd06d, 0xab => 0xd070, 0xac => 0xd074, + 0xad => 0xd07c, 0xae => 0xd07d, 0xaf => 0xd081, 0xb0 => 0xd0a4, + 0xb1 => 0xd0a5, 0xb2 => 0xd0a8, 0xb3 => 0xd0ac, 0xb4 => 0xd0b4, + 0xb5 => 0xd0b5, 0xb6 => 0xd0b7, 0xb7 => 0xd0b9, 0xb8 => 0xd0c0, + 0xb9 => 0xd0c1, 0xba => 0xd0c4, 0xbb => 0xd0c8, 0xbc => 0xd0c9, + 0xbd => 0xd0d0, 0xbe => 0xd0d1, 0xbf => 0xd0d3, 0xc0 => 0xd0d4, + 0xc1 => 0xd0d5, 0xc2 => 0xd0dc, 0xc3 => 0xd0dd, 0xc4 => 0xd0e0, + 0xc5 => 0xd0e4, 0xc6 => 0xd0ec, 0xc7 => 0xd0ed, 0xc8 => 0xd0ef, + 0xc9 => 0xd0f0, 0xca => 0xd0f1, 0xcb => 0xd0f8, 0xcc => 0xd10d, + 0xcd => 0xd130, 0xce => 0xd131, 0xcf => 0xd134, 0xd0 => 0xd138, + 0xd1 => 0xd13a, 0xd2 => 0xd140, 0xd3 => 0xd141, 0xd4 => 0xd143, + 0xd5 => 0xd144, 0xd6 => 0xd145, 0xd7 => 0xd14c, 0xd8 => 0xd14d, + 0xd9 => 0xd150, 0xda => 0xd154, 0xdb => 0xd15c, 0xdc => 0xd15d, + 0xdd => 0xd15f, 0xde => 0xd161, 0xdf => 0xd168, 0xe0 => 0xd16c, + 0xe1 => 0xd17c, 0xe2 => 0xd184, 0xe3 => 0xd188, 0xe4 => 0xd1a0, + 0xe5 => 0xd1a1, 0xe6 => 0xd1a4, 0xe7 => 0xd1a8, 0xe8 => 0xd1b0, + 0xe9 => 0xd1b1, 0xea => 0xd1b3, 0xeb => 0xd1b5, 0xec => 0xd1ba, + 0xed => 0xd1bc, 0xee => 0xd1c0, 0xef => 0xd1d8, 0xf0 => 0xd1f4, + 0xf1 => 0xd1f8, 0xf2 => 0xd207, 0xf3 => 0xd209, 0xf4 => 0xd210, + 0xf5 => 0xd22c, 0xf6 => 0xd22d, 0xf7 => 0xd230, 0xf8 => 0xd234, + 0xf9 => 0xd23c, 0xfa => 0xd23d, 0xfb => 0xd23f, 0xfc => 0xd241, + 0xfd => 0xd248, 0xfe => 0xd25c, + }, + 0xc6 => { + 0xa1 => 0xd264, 0xa2 => 0xd280, 0xa3 => 0xd281, 0xa4 => 0xd284, + 0xa5 => 0xd288, 0xa6 => 0xd290, 0xa7 => 0xd291, 0xa8 => 0xd295, + 0xa9 => 0xd29c, 0xaa => 0xd2a0, 0xab => 0xd2a4, 0xac => 0xd2ac, + 0xad => 0xd2b1, 0xae => 0xd2b8, 0xaf => 0xd2b9, 0xb0 => 0xd2bc, + 0xb1 => 0xd2bf, 0xb2 => 0xd2c0, 0xb3 => 0xd2c2, 0xb4 => 0xd2c8, + 0xb5 => 0xd2c9, 0xb6 => 0xd2cb, 0xb7 => 0xd2d4, 0xb8 => 0xd2d8, + 0xb9 => 0xd2dc, 0xba => 0xd2e4, 0xbb => 0xd2e5, 0xbc => 0xd2f0, + 0xbd => 0xd2f1, 0xbe => 0xd2f4, 0xbf => 0xd2f8, 0xc0 => 0xd300, + 0xc1 => 0xd301, 0xc2 => 0xd303, 0xc3 => 0xd305, 0xc4 => 0xd30c, + 0xc5 => 0xd30d, 0xc6 => 0xd30e, 0xc7 => 0xd310, 0xc8 => 0xd314, + 0xc9 => 0xd316, 0xca => 0xd31c, 0xcb => 0xd31d, 0xcc => 0xd31f, + 0xcd => 0xd320, 0xce => 0xd321, 0xcf => 0xd325, 0xd0 => 0xd328, + 0xd1 => 0xd329, 0xd2 => 0xd32c, 0xd3 => 0xd330, 0xd4 => 0xd338, + 0xd5 => 0xd339, 0xd6 => 0xd33b, 0xd7 => 0xd33c, 0xd8 => 0xd33d, + 0xd9 => 0xd344, 0xda => 0xd345, 0xdb => 0xd37c, 0xdc => 0xd37d, + 0xdd => 0xd380, 0xde => 0xd384, 0xdf => 0xd38c, 0xe0 => 0xd38d, + 0xe1 => 0xd38f, 0xe2 => 0xd390, 0xe3 => 0xd391, 0xe4 => 0xd398, + 0xe5 => 0xd399, 0xe6 => 0xd39c, 0xe7 => 0xd3a0, 0xe8 => 0xd3a8, + 0xe9 => 0xd3a9, 0xea => 0xd3ab, 0xeb => 0xd3ad, 0xec => 0xd3b4, + 0xed => 0xd3b8, 0xee => 0xd3bc, 0xef => 0xd3c4, 0xf0 => 0xd3c5, + 0xf1 => 0xd3c8, 0xf2 => 0xd3c9, 0xf3 => 0xd3d0, 0xf4 => 0xd3d8, + 0xf5 => 0xd3e1, 0xf6 => 0xd3e3, 0xf7 => 0xd3ec, 0xf8 => 0xd3ed, + 0xf9 => 0xd3f0, 0xfa => 0xd3f4, 0xfb => 0xd3fc, 0xfc => 0xd3fd, + 0xfd => 0xd3ff, 0xfe => 0xd401, + }, + 0xc7 => { + 0xa1 => 0xd408, 0xa2 => 0xd41d, 0xa3 => 0xd440, 0xa4 => 0xd444, + 0xa5 => 0xd45c, 0xa6 => 0xd460, 0xa7 => 0xd464, 0xa8 => 0xd46d, + 0xa9 => 0xd46f, 0xaa => 0xd478, 0xab => 0xd479, 0xac => 0xd47c, + 0xad => 0xd47f, 0xae => 0xd480, 0xaf => 0xd482, 0xb0 => 0xd488, + 0xb1 => 0xd489, 0xb2 => 0xd48b, 0xb3 => 0xd48d, 0xb4 => 0xd494, + 0xb5 => 0xd4a9, 0xb6 => 0xd4cc, 0xb7 => 0xd4d0, 0xb8 => 0xd4d4, + 0xb9 => 0xd4dc, 0xba => 0xd4df, 0xbb => 0xd4e8, 0xbc => 0xd4ec, + 0xbd => 0xd4f0, 0xbe => 0xd4f8, 0xbf => 0xd4fb, 0xc0 => 0xd4fd, + 0xc1 => 0xd504, 0xc2 => 0xd508, 0xc3 => 0xd50c, 0xc4 => 0xd514, + 0xc5 => 0xd515, 0xc6 => 0xd517, 0xc7 => 0xd53c, 0xc8 => 0xd53d, + 0xc9 => 0xd540, 0xca => 0xd544, 0xcb => 0xd54c, 0xcc => 0xd54d, + 0xcd => 0xd54f, 0xce => 0xd551, 0xcf => 0xd558, 0xd0 => 0xd559, + 0xd1 => 0xd55c, 0xd2 => 0xd560, 0xd3 => 0xd565, 0xd4 => 0xd568, + 0xd5 => 0xd569, 0xd6 => 0xd56b, 0xd7 => 0xd56d, 0xd8 => 0xd574, + 0xd9 => 0xd575, 0xda => 0xd578, 0xdb => 0xd57c, 0xdc => 0xd584, + 0xdd => 0xd585, 0xde => 0xd587, 0xdf => 0xd588, 0xe0 => 0xd589, + 0xe1 => 0xd590, 0xe2 => 0xd5a5, 0xe3 => 0xd5c8, 0xe4 => 0xd5c9, + 0xe5 => 0xd5cc, 0xe6 => 0xd5d0, 0xe7 => 0xd5d2, 0xe8 => 0xd5d8, + 0xe9 => 0xd5d9, 0xea => 0xd5db, 0xeb => 0xd5dd, 0xec => 0xd5e4, + 0xed => 0xd5e5, 0xee => 0xd5e8, 0xef => 0xd5ec, 0xf0 => 0xd5f4, + 0xf1 => 0xd5f5, 0xf2 => 0xd5f7, 0xf3 => 0xd5f9, 0xf4 => 0xd600, + 0xf5 => 0xd601, 0xf6 => 0xd604, 0xf7 => 0xd608, 0xf8 => 0xd610, + 0xf9 => 0xd611, 0xfa => 0xd613, 0xfb => 0xd614, 0xfc => 0xd615, + 0xfd => 0xd61c, 0xfe => 0xd620, + }, + 0xc8 => { + 0xa1 => 0xd624, 0xa2 => 0xd62d, 0xa3 => 0xd638, 0xa4 => 0xd639, + 0xa5 => 0xd63c, 0xa6 => 0xd640, 0xa7 => 0xd645, 0xa8 => 0xd648, + 0xa9 => 0xd649, 0xaa => 0xd64b, 0xab => 0xd64d, 0xac => 0xd651, + 0xad => 0xd654, 0xae => 0xd655, 0xaf => 0xd658, 0xb0 => 0xd65c, + 0xb1 => 0xd667, 0xb2 => 0xd669, 0xb3 => 0xd670, 0xb4 => 0xd671, + 0xb5 => 0xd674, 0xb6 => 0xd683, 0xb7 => 0xd685, 0xb8 => 0xd68c, + 0xb9 => 0xd68d, 0xba => 0xd690, 0xbb => 0xd694, 0xbc => 0xd69d, + 0xbd => 0xd69f, 0xbe => 0xd6a1, 0xbf => 0xd6a8, 0xc0 => 0xd6ac, + 0xc1 => 0xd6b0, 0xc2 => 0xd6b9, 0xc3 => 0xd6bb, 0xc4 => 0xd6c4, + 0xc5 => 0xd6c5, 0xc6 => 0xd6c8, 0xc7 => 0xd6cc, 0xc8 => 0xd6d1, + 0xc9 => 0xd6d4, 0xca => 0xd6d7, 0xcb => 0xd6d9, 0xcc => 0xd6e0, + 0xcd => 0xd6e4, 0xce => 0xd6e8, 0xcf => 0xd6f0, 0xd0 => 0xd6f5, + 0xd1 => 0xd6fc, 0xd2 => 0xd6fd, 0xd3 => 0xd700, 0xd4 => 0xd704, + 0xd5 => 0xd711, 0xd6 => 0xd718, 0xd7 => 0xd719, 0xd8 => 0xd71c, + 0xd9 => 0xd720, 0xda => 0xd728, 0xdb => 0xd729, 0xdc => 0xd72b, + 0xdd => 0xd72d, 0xde => 0xd734, 0xdf => 0xd735, 0xe0 => 0xd738, + 0xe1 => 0xd73c, 0xe2 => 0xd744, 0xe3 => 0xd747, 0xe4 => 0xd749, + 0xe5 => 0xd750, 0xe6 => 0xd751, 0xe7 => 0xd754, 0xe8 => 0xd756, + 0xe9 => 0xd757, 0xea => 0xd758, 0xeb => 0xd759, 0xec => 0xd760, + 0xed => 0xd761, 0xee => 0xd763, 0xef => 0xd765, 0xf0 => 0xd769, + 0xf1 => 0xd76c, 0xf2 => 0xd770, 0xf3 => 0xd774, 0xf4 => 0xd77c, + 0xf5 => 0xd77d, 0xf6 => 0xd781, 0xf7 => 0xd788, 0xf8 => 0xd789, + 0xf9 => 0xd78c, 0xfa => 0xd790, 0xfb => 0xd798, 0xfc => 0xd799, + 0xfd => 0xd79b, 0xfe => 0xd79d, + }, + 0xca => { + 0xa1 => 0x4f3d, 0xa2 => 0x4f73, 0xa3 => 0x5047, 0xa4 => 0x50f9, + 0xa5 => 0x52a0, 0xa6 => 0x53ef, 0xa7 => 0x5475, 0xa8 => 0x54e5, + 0xa9 => 0x5609, 0xaa => 0x5ac1, 0xab => 0x5bb6, 0xac => 0x6687, + 0xad => 0x67b6, 0xae => 0x67b7, 0xaf => 0x67ef, 0xb0 => 0x6b4c, + 0xb1 => 0x73c2, 0xb2 => 0x75c2, 0xb3 => 0x7a3c, 0xb4 => 0x82db, + 0xb5 => 0x8304, 0xb6 => 0x8857, 0xb7 => 0x8888, 0xb8 => 0x8a36, + 0xb9 => 0x8cc8, 0xba => 0x8dcf, 0xbb => 0x8efb, 0xbc => 0x8fe6, + 0xbd => 0x99d5, 0xbe => 0x523b, 0xbf => 0x5374, 0xc0 => 0x5404, + 0xc1 => 0x606a, 0xc2 => 0x6164, 0xc3 => 0x6bbc, 0xc4 => 0x73cf, + 0xc5 => 0x811a, 0xc6 => 0x89ba, 0xc7 => 0x89d2, 0xc8 => 0x95a3, + 0xc9 => 0x4f83, 0xca => 0x520a, 0xcb => 0x58be, 0xcc => 0x5978, + 0xcd => 0x59e6, 0xce => 0x5e72, 0xcf => 0x5e79, 0xd0 => 0x61c7, + 0xd1 => 0x63c0, 0xd2 => 0x6746, 0xd3 => 0x67ec, 0xd4 => 0x687f, + 0xd5 => 0x6f97, 0xd6 => 0x764e, 0xd7 => 0x770b, 0xd8 => 0x78f5, + 0xd9 => 0x7a08, 0xda => 0x7aff, 0xdb => 0x7c21, 0xdc => 0x809d, + 0xdd => 0x826e, 0xde => 0x8271, 0xdf => 0x8aeb, 0xe0 => 0x9593, + 0xe1 => 0x4e6b, 0xe2 => 0x559d, 0xe3 => 0x66f7, 0xe4 => 0x6e34, + 0xe5 => 0x78a3, 0xe6 => 0x7aed, 0xe7 => 0x845b, 0xe8 => 0x8910, + 0xe9 => 0x874e, 0xea => 0x97a8, 0xeb => 0x52d8, 0xec => 0x574e, + 0xed => 0x582a, 0xee => 0x5d4c, 0xef => 0x611f, 0xf0 => 0x61be, + 0xf1 => 0x6221, 0xf2 => 0x6562, 0xf3 => 0x67d1, 0xf4 => 0x6a44, + 0xf5 => 0x6e1b, 0xf6 => 0x7518, 0xf7 => 0x75b3, 0xf8 => 0x76e3, + 0xf9 => 0x77b0, 0xfa => 0x7d3a, 0xfb => 0x90af, 0xfc => 0x9451, + 0xfd => 0x9452, 0xfe => 0x9f95, + }, + 0xcb => { + 0xa1 => 0x5323, 0xa2 => 0x5cac, 0xa3 => 0x7532, 0xa4 => 0x80db, + 0xa5 => 0x9240, 0xa6 => 0x9598, 0xa7 => 0x525b, 0xa8 => 0x5808, + 0xa9 => 0x59dc, 0xaa => 0x5ca1, 0xab => 0x5d17, 0xac => 0x5eb7, + 0xad => 0x5f3a, 0xae => 0x5f4a, 0xaf => 0x6177, 0xb0 => 0x6c5f, + 0xb1 => 0x757a, 0xb2 => 0x7586, 0xb3 => 0x7ce0, 0xb4 => 0x7d73, + 0xb5 => 0x7db1, 0xb6 => 0x7f8c, 0xb7 => 0x8154, 0xb8 => 0x8221, + 0xb9 => 0x8591, 0xba => 0x8941, 0xbb => 0x8b1b, 0xbc => 0x92fc, + 0xbd => 0x964d, 0xbe => 0x9c47, 0xbf => 0x4ecb, 0xc0 => 0x4ef7, + 0xc1 => 0x500b, 0xc2 => 0x51f1, 0xc3 => 0x584f, 0xc4 => 0x6137, + 0xc5 => 0x613e, 0xc6 => 0x6168, 0xc7 => 0x6539, 0xc8 => 0x69ea, + 0xc9 => 0x6f11, 0xca => 0x75a5, 0xcb => 0x7686, 0xcc => 0x76d6, + 0xcd => 0x7b87, 0xce => 0x82a5, 0xcf => 0x84cb, 0xd0 => 0xf900, + 0xd1 => 0x93a7, 0xd2 => 0x958b, 0xd3 => 0x5580, 0xd4 => 0x5ba2, + 0xd5 => 0x5751, 0xd6 => 0xf901, 0xd7 => 0x7cb3, 0xd8 => 0x7fb9, + 0xd9 => 0x91b5, 0xda => 0x5028, 0xdb => 0x53bb, 0xdc => 0x5c45, + 0xdd => 0x5de8, 0xde => 0x62d2, 0xdf => 0x636e, 0xe0 => 0x64da, + 0xe1 => 0x64e7, 0xe2 => 0x6e20, 0xe3 => 0x70ac, 0xe4 => 0x795b, + 0xe5 => 0x8ddd, 0xe6 => 0x8e1e, 0xe7 => 0xf902, 0xe8 => 0x907d, + 0xe9 => 0x9245, 0xea => 0x92f8, 0xeb => 0x4e7e, 0xec => 0x4ef6, + 0xed => 0x5065, 0xee => 0x5dfe, 0xef => 0x5efa, 0xf0 => 0x6106, + 0xf1 => 0x6957, 0xf2 => 0x8171, 0xf3 => 0x8654, 0xf4 => 0x8e47, + 0xf5 => 0x9375, 0xf6 => 0x9a2b, 0xf7 => 0x4e5e, 0xf8 => 0x5091, + 0xf9 => 0x6770, 0xfa => 0x6840, 0xfb => 0x5109, 0xfc => 0x528d, + 0xfd => 0x5292, 0xfe => 0x6aa2, + }, + 0xcc => { + 0xa1 => 0x77bc, 0xa2 => 0x9210, 0xa3 => 0x9ed4, 0xa4 => 0x52ab, + 0xa5 => 0x602f, 0xa6 => 0x8ff2, 0xa7 => 0x5048, 0xa8 => 0x61a9, + 0xa9 => 0x63ed, 0xaa => 0x64ca, 0xab => 0x683c, 0xac => 0x6a84, + 0xad => 0x6fc0, 0xae => 0x8188, 0xaf => 0x89a1, 0xb0 => 0x9694, + 0xb1 => 0x5805, 0xb2 => 0x727d, 0xb3 => 0x72ac, 0xb4 => 0x7504, + 0xb5 => 0x7d79, 0xb6 => 0x7e6d, 0xb7 => 0x80a9, 0xb8 => 0x898b, + 0xb9 => 0x8b74, 0xba => 0x9063, 0xbb => 0x9d51, 0xbc => 0x6289, + 0xbd => 0x6c7a, 0xbe => 0x6f54, 0xbf => 0x7d50, 0xc0 => 0x7f3a, + 0xc1 => 0x8a23, 0xc2 => 0x517c, 0xc3 => 0x614a, 0xc4 => 0x7b9d, + 0xc5 => 0x8b19, 0xc6 => 0x9257, 0xc7 => 0x938c, 0xc8 => 0x4eac, + 0xc9 => 0x4fd3, 0xca => 0x501e, 0xcb => 0x50be, 0xcc => 0x5106, + 0xcd => 0x52c1, 0xce => 0x52cd, 0xcf => 0x537f, 0xd0 => 0x5770, + 0xd1 => 0x5883, 0xd2 => 0x5e9a, 0xd3 => 0x5f91, 0xd4 => 0x6176, + 0xd5 => 0x61ac, 0xd6 => 0x64ce, 0xd7 => 0x656c, 0xd8 => 0x666f, + 0xd9 => 0x66bb, 0xda => 0x66f4, 0xdb => 0x6897, 0xdc => 0x6d87, + 0xdd => 0x7085, 0xde => 0x70f1, 0xdf => 0x749f, 0xe0 => 0x74a5, + 0xe1 => 0x74ca, 0xe2 => 0x75d9, 0xe3 => 0x786c, 0xe4 => 0x78ec, + 0xe5 => 0x7adf, 0xe6 => 0x7af6, 0xe7 => 0x7d45, 0xe8 => 0x7d93, + 0xe9 => 0x8015, 0xea => 0x803f, 0xeb => 0x811b, 0xec => 0x8396, + 0xed => 0x8b66, 0xee => 0x8f15, 0xef => 0x9015, 0xf0 => 0x93e1, + 0xf1 => 0x9803, 0xf2 => 0x9838, 0xf3 => 0x9a5a, 0xf4 => 0x9be8, + 0xf5 => 0x4fc2, 0xf6 => 0x5553, 0xf7 => 0x583a, 0xf8 => 0x5951, + 0xf9 => 0x5b63, 0xfa => 0x5c46, 0xfb => 0x60b8, 0xfc => 0x6212, + 0xfd => 0x6842, 0xfe => 0x68b0, + }, + 0xcd => { + 0xa1 => 0x68e8, 0xa2 => 0x6eaa, 0xa3 => 0x754c, 0xa4 => 0x7678, + 0xa5 => 0x78ce, 0xa6 => 0x7a3d, 0xa7 => 0x7cfb, 0xa8 => 0x7e6b, + 0xa9 => 0x7e7c, 0xaa => 0x8a08, 0xab => 0x8aa1, 0xac => 0x8c3f, + 0xad => 0x968e, 0xae => 0x9dc4, 0xaf => 0x53e4, 0xb0 => 0x53e9, + 0xb1 => 0x544a, 0xb2 => 0x5471, 0xb3 => 0x56fa, 0xb4 => 0x59d1, + 0xb5 => 0x5b64, 0xb6 => 0x5c3b, 0xb7 => 0x5eab, 0xb8 => 0x62f7, + 0xb9 => 0x6537, 0xba => 0x6545, 0xbb => 0x6572, 0xbc => 0x66a0, + 0xbd => 0x67af, 0xbe => 0x69c1, 0xbf => 0x6cbd, 0xc0 => 0x75fc, + 0xc1 => 0x7690, 0xc2 => 0x777e, 0xc3 => 0x7a3f, 0xc4 => 0x7f94, + 0xc5 => 0x8003, 0xc6 => 0x80a1, 0xc7 => 0x818f, 0xc8 => 0x82e6, + 0xc9 => 0x82fd, 0xca => 0x83f0, 0xcb => 0x85c1, 0xcc => 0x8831, + 0xcd => 0x88b4, 0xce => 0x8aa5, 0xcf => 0xf903, 0xd0 => 0x8f9c, + 0xd1 => 0x932e, 0xd2 => 0x96c7, 0xd3 => 0x9867, 0xd4 => 0x9ad8, + 0xd5 => 0x9f13, 0xd6 => 0x54ed, 0xd7 => 0x659b, 0xd8 => 0x66f2, + 0xd9 => 0x688f, 0xda => 0x7a40, 0xdb => 0x8c37, 0xdc => 0x9d60, + 0xdd => 0x56f0, 0xde => 0x5764, 0xdf => 0x5d11, 0xe0 => 0x6606, + 0xe1 => 0x68b1, 0xe2 => 0x68cd, 0xe3 => 0x6efe, 0xe4 => 0x7428, + 0xe5 => 0x889e, 0xe6 => 0x9be4, 0xe7 => 0x6c68, 0xe8 => 0xf904, + 0xe9 => 0x9aa8, 0xea => 0x4f9b, 0xeb => 0x516c, 0xec => 0x5171, + 0xed => 0x529f, 0xee => 0x5b54, 0xef => 0x5de5, 0xf0 => 0x6050, + 0xf1 => 0x606d, 0xf2 => 0x62f1, 0xf3 => 0x63a7, 0xf4 => 0x653b, + 0xf5 => 0x73d9, 0xf6 => 0x7a7a, 0xf7 => 0x86a3, 0xf8 => 0x8ca2, + 0xf9 => 0x978f, 0xfa => 0x4e32, 0xfb => 0x5be1, 0xfc => 0x6208, + 0xfd => 0x679c, 0xfe => 0x74dc, + }, + 0xce => { + 0xa1 => 0x79d1, 0xa2 => 0x83d3, 0xa3 => 0x8a87, 0xa4 => 0x8ab2, + 0xa5 => 0x8de8, 0xa6 => 0x904e, 0xa7 => 0x934b, 0xa8 => 0x9846, + 0xa9 => 0x5ed3, 0xaa => 0x69e8, 0xab => 0x85ff, 0xac => 0x90ed, + 0xad => 0xf905, 0xae => 0x51a0, 0xaf => 0x5b98, 0xb0 => 0x5bec, + 0xb1 => 0x6163, 0xb2 => 0x68fa, 0xb3 => 0x6b3e, 0xb4 => 0x704c, + 0xb5 => 0x742f, 0xb6 => 0x74d8, 0xb7 => 0x7ba1, 0xb8 => 0x7f50, + 0xb9 => 0x83c5, 0xba => 0x89c0, 0xbb => 0x8cab, 0xbc => 0x95dc, + 0xbd => 0x9928, 0xbe => 0x522e, 0xbf => 0x605d, 0xc0 => 0x62ec, + 0xc1 => 0x9002, 0xc2 => 0x4f8a, 0xc3 => 0x5149, 0xc4 => 0x5321, + 0xc5 => 0x58d9, 0xc6 => 0x5ee3, 0xc7 => 0x66e0, 0xc8 => 0x6d38, + 0xc9 => 0x709a, 0xca => 0x72c2, 0xcb => 0x73d6, 0xcc => 0x7b50, + 0xcd => 0x80f1, 0xce => 0x945b, 0xcf => 0x5366, 0xd0 => 0x639b, + 0xd1 => 0x7f6b, 0xd2 => 0x4e56, 0xd3 => 0x5080, 0xd4 => 0x584a, + 0xd5 => 0x58de, 0xd6 => 0x602a, 0xd7 => 0x6127, 0xd8 => 0x62d0, + 0xd9 => 0x69d0, 0xda => 0x9b41, 0xdb => 0x5b8f, 0xdc => 0x7d18, + 0xdd => 0x80b1, 0xde => 0x8f5f, 0xdf => 0x4ea4, 0xe0 => 0x50d1, + 0xe1 => 0x54ac, 0xe2 => 0x55ac, 0xe3 => 0x5b0c, 0xe4 => 0x5da0, + 0xe5 => 0x5de7, 0xe6 => 0x652a, 0xe7 => 0x654e, 0xe8 => 0x6821, + 0xe9 => 0x6a4b, 0xea => 0x72e1, 0xeb => 0x768e, 0xec => 0x77ef, + 0xed => 0x7d5e, 0xee => 0x7ff9, 0xef => 0x81a0, 0xf0 => 0x854e, + 0xf1 => 0x86df, 0xf2 => 0x8f03, 0xf3 => 0x8f4e, 0xf4 => 0x90ca, + 0xf5 => 0x9903, 0xf6 => 0x9a55, 0xf7 => 0x9bab, 0xf8 => 0x4e18, + 0xf9 => 0x4e45, 0xfa => 0x4e5d, 0xfb => 0x4ec7, 0xfc => 0x4ff1, + 0xfd => 0x5177, 0xfe => 0x52fe, + }, + 0xcf => { + 0xa1 => 0x5340, 0xa2 => 0x53e3, 0xa3 => 0x53e5, 0xa4 => 0x548e, + 0xa5 => 0x5614, 0xa6 => 0x5775, 0xa7 => 0x57a2, 0xa8 => 0x5bc7, + 0xa9 => 0x5d87, 0xaa => 0x5ed0, 0xab => 0x61fc, 0xac => 0x62d8, + 0xad => 0x6551, 0xae => 0x67b8, 0xaf => 0x67e9, 0xb0 => 0x69cb, + 0xb1 => 0x6b50, 0xb2 => 0x6bc6, 0xb3 => 0x6bec, 0xb4 => 0x6c42, + 0xb5 => 0x6e9d, 0xb6 => 0x7078, 0xb7 => 0x72d7, 0xb8 => 0x7396, + 0xb9 => 0x7403, 0xba => 0x77bf, 0xbb => 0x77e9, 0xbc => 0x7a76, + 0xbd => 0x7d7f, 0xbe => 0x8009, 0xbf => 0x81fc, 0xc0 => 0x8205, + 0xc1 => 0x820a, 0xc2 => 0x82df, 0xc3 => 0x8862, 0xc4 => 0x8b33, + 0xc5 => 0x8cfc, 0xc6 => 0x8ec0, 0xc7 => 0x9011, 0xc8 => 0x90b1, + 0xc9 => 0x9264, 0xca => 0x92b6, 0xcb => 0x99d2, 0xcc => 0x9a45, + 0xcd => 0x9ce9, 0xce => 0x9dd7, 0xcf => 0x9f9c, 0xd0 => 0x570b, + 0xd1 => 0x5c40, 0xd2 => 0x83ca, 0xd3 => 0x97a0, 0xd4 => 0x97ab, + 0xd5 => 0x9eb4, 0xd6 => 0x541b, 0xd7 => 0x7a98, 0xd8 => 0x7fa4, + 0xd9 => 0x88d9, 0xda => 0x8ecd, 0xdb => 0x90e1, 0xdc => 0x5800, + 0xdd => 0x5c48, 0xde => 0x6398, 0xdf => 0x7a9f, 0xe0 => 0x5bae, + 0xe1 => 0x5f13, 0xe2 => 0x7a79, 0xe3 => 0x7aae, 0xe4 => 0x828e, + 0xe5 => 0x8eac, 0xe6 => 0x5026, 0xe7 => 0x5238, 0xe8 => 0x52f8, + 0xe9 => 0x5377, 0xea => 0x5708, 0xeb => 0x62f3, 0xec => 0x6372, + 0xed => 0x6b0a, 0xee => 0x6dc3, 0xef => 0x7737, 0xf0 => 0x53a5, + 0xf1 => 0x7357, 0xf2 => 0x8568, 0xf3 => 0x8e76, 0xf4 => 0x95d5, + 0xf5 => 0x673a, 0xf6 => 0x6ac3, 0xf7 => 0x6f70, 0xf8 => 0x8a6d, + 0xf9 => 0x8ecc, 0xfa => 0x994b, 0xfb => 0xf906, 0xfc => 0x6677, + 0xfd => 0x6b78, 0xfe => 0x8cb4, + }, + 0xd0 => { + 0xa1 => 0x9b3c, 0xa2 => 0xf907, 0xa3 => 0x53eb, 0xa4 => 0x572d, + 0xa5 => 0x594e, 0xa6 => 0x63c6, 0xa7 => 0x69fb, 0xa8 => 0x73ea, + 0xa9 => 0x7845, 0xaa => 0x7aba, 0xab => 0x7ac5, 0xac => 0x7cfe, + 0xad => 0x8475, 0xae => 0x898f, 0xaf => 0x8d73, 0xb0 => 0x9035, + 0xb1 => 0x95a8, 0xb2 => 0x52fb, 0xb3 => 0x5747, 0xb4 => 0x7547, + 0xb5 => 0x7b60, 0xb6 => 0x83cc, 0xb7 => 0x921e, 0xb8 => 0xf908, + 0xb9 => 0x6a58, 0xba => 0x514b, 0xbb => 0x524b, 0xbc => 0x5287, + 0xbd => 0x621f, 0xbe => 0x68d8, 0xbf => 0x6975, 0xc0 => 0x9699, + 0xc1 => 0x50c5, 0xc2 => 0x52a4, 0xc3 => 0x52e4, 0xc4 => 0x61c3, + 0xc5 => 0x65a4, 0xc6 => 0x6839, 0xc7 => 0x69ff, 0xc8 => 0x747e, + 0xc9 => 0x7b4b, 0xca => 0x82b9, 0xcb => 0x83eb, 0xcc => 0x89b2, + 0xcd => 0x8b39, 0xce => 0x8fd1, 0xcf => 0x9949, 0xd0 => 0xf909, + 0xd1 => 0x4eca, 0xd2 => 0x5997, 0xd3 => 0x64d2, 0xd4 => 0x6611, + 0xd5 => 0x6a8e, 0xd6 => 0x7434, 0xd7 => 0x7981, 0xd8 => 0x79bd, + 0xd9 => 0x82a9, 0xda => 0x887e, 0xdb => 0x887f, 0xdc => 0x895f, + 0xdd => 0xf90a, 0xde => 0x9326, 0xdf => 0x4f0b, 0xe0 => 0x53ca, + 0xe1 => 0x6025, 0xe2 => 0x6271, 0xe3 => 0x6c72, 0xe4 => 0x7d1a, + 0xe5 => 0x7d66, 0xe6 => 0x4e98, 0xe7 => 0x5162, 0xe8 => 0x77dc, + 0xe9 => 0x80af, 0xea => 0x4f01, 0xeb => 0x4f0e, 0xec => 0x5176, + 0xed => 0x5180, 0xee => 0x55dc, 0xef => 0x5668, 0xf0 => 0x573b, + 0xf1 => 0x57fa, 0xf2 => 0x57fc, 0xf3 => 0x5914, 0xf4 => 0x5947, + 0xf5 => 0x5993, 0xf6 => 0x5bc4, 0xf7 => 0x5c90, 0xf8 => 0x5d0e, + 0xf9 => 0x5df1, 0xfa => 0x5e7e, 0xfb => 0x5fcc, 0xfc => 0x6280, + 0xfd => 0x65d7, 0xfe => 0x65e3, + }, + 0xd1 => { + 0xa1 => 0x671e, 0xa2 => 0x671f, 0xa3 => 0x675e, 0xa4 => 0x68cb, + 0xa5 => 0x68c4, 0xa6 => 0x6a5f, 0xa7 => 0x6b3a, 0xa8 => 0x6c23, + 0xa9 => 0x6c7d, 0xaa => 0x6c82, 0xab => 0x6dc7, 0xac => 0x7398, + 0xad => 0x7426, 0xae => 0x742a, 0xaf => 0x7482, 0xb0 => 0x74a3, + 0xb1 => 0x7578, 0xb2 => 0x757f, 0xb3 => 0x7881, 0xb4 => 0x78ef, + 0xb5 => 0x7941, 0xb6 => 0x7947, 0xb7 => 0x7948, 0xb8 => 0x797a, + 0xb9 => 0x7b95, 0xba => 0x7d00, 0xbb => 0x7dba, 0xbc => 0x7f88, + 0xbd => 0x8006, 0xbe => 0x802d, 0xbf => 0x808c, 0xc0 => 0x8a18, + 0xc1 => 0x8b4f, 0xc2 => 0x8c48, 0xc3 => 0x8d77, 0xc4 => 0x9321, + 0xc5 => 0x9324, 0xc6 => 0x98e2, 0xc7 => 0x9951, 0xc8 => 0x9a0e, + 0xc9 => 0x9a0f, 0xca => 0x9a65, 0xcb => 0x9e92, 0xcc => 0x7dca, + 0xcd => 0x4f76, 0xce => 0x5409, 0xcf => 0x62ee, 0xd0 => 0x6854, + 0xd1 => 0x91d1, 0xd2 => 0x55ab, 0xd3 => 0x513a, 0xd4 => 0xf90b, + 0xd5 => 0xf90c, 0xd6 => 0x5a1c, 0xd7 => 0x61e6, 0xd8 => 0xf90d, + 0xd9 => 0x62cf, 0xda => 0x62ff, 0xdb => 0xf90e, 0xdc => 0xf90f, + 0xdd => 0xf910, 0xde => 0xf911, 0xdf => 0xf912, 0xe0 => 0xf913, + 0xe1 => 0x90a3, 0xe2 => 0xf914, 0xe3 => 0xf915, 0xe4 => 0xf916, + 0xe5 => 0xf917, 0xe6 => 0xf918, 0xe7 => 0x8afe, 0xe8 => 0xf919, + 0xe9 => 0xf91a, 0xea => 0xf91b, 0xeb => 0xf91c, 0xec => 0x6696, + 0xed => 0xf91d, 0xee => 0x7156, 0xef => 0xf91e, 0xf0 => 0xf91f, + 0xf1 => 0x96e3, 0xf2 => 0xf920, 0xf3 => 0x634f, 0xf4 => 0x637a, + 0xf5 => 0x5357, 0xf6 => 0xf921, 0xf7 => 0x678f, 0xf8 => 0x6960, + 0xf9 => 0x6e73, 0xfa => 0xf922, 0xfb => 0x7537, 0xfc => 0xf923, + 0xfd => 0xf924, 0xfe => 0xf925, + }, + 0xd2 => { + 0xa1 => 0x7d0d, 0xa2 => 0xf926, 0xa3 => 0xf927, 0xa4 => 0x8872, + 0xa5 => 0x56ca, 0xa6 => 0x5a18, 0xa7 => 0xf928, 0xa8 => 0xf929, + 0xa9 => 0xf92a, 0xaa => 0xf92b, 0xab => 0xf92c, 0xac => 0x4e43, + 0xad => 0xf92d, 0xae => 0x5167, 0xaf => 0x5948, 0xb0 => 0x67f0, + 0xb1 => 0x8010, 0xb2 => 0xf92e, 0xb3 => 0x5973, 0xb4 => 0x5e74, + 0xb5 => 0x649a, 0xb6 => 0x79ca, 0xb7 => 0x5ff5, 0xb8 => 0x606c, + 0xb9 => 0x62c8, 0xba => 0x637b, 0xbb => 0x5be7, 0xbc => 0x5bd7, + 0xbd => 0x52aa, 0xbe => 0xf92f, 0xbf => 0x5974, 0xc0 => 0x5f29, + 0xc1 => 0x6012, 0xc2 => 0xf930, 0xc3 => 0xf931, 0xc4 => 0xf932, + 0xc5 => 0x7459, 0xc6 => 0xf933, 0xc7 => 0xf934, 0xc8 => 0xf935, + 0xc9 => 0xf936, 0xca => 0xf937, 0xcb => 0xf938, 0xcc => 0x99d1, + 0xcd => 0xf939, 0xce => 0xf93a, 0xcf => 0xf93b, 0xd0 => 0xf93c, + 0xd1 => 0xf93d, 0xd2 => 0xf93e, 0xd3 => 0xf93f, 0xd4 => 0xf940, + 0xd5 => 0xf941, 0xd6 => 0xf942, 0xd7 => 0xf943, 0xd8 => 0x6fc3, + 0xd9 => 0xf944, 0xda => 0xf945, 0xdb => 0x81bf, 0xdc => 0x8fb2, + 0xdd => 0x60f1, 0xde => 0xf946, 0xdf => 0xf947, 0xe0 => 0x8166, + 0xe1 => 0xf948, 0xe2 => 0xf949, 0xe3 => 0x5c3f, 0xe4 => 0xf94a, + 0xe5 => 0xf94b, 0xe6 => 0xf94c, 0xe7 => 0xf94d, 0xe8 => 0xf94e, + 0xe9 => 0xf94f, 0xea => 0xf950, 0xeb => 0xf951, 0xec => 0x5ae9, + 0xed => 0x8a25, 0xee => 0x677b, 0xef => 0x7d10, 0xf0 => 0xf952, + 0xf1 => 0xf953, 0xf2 => 0xf954, 0xf3 => 0xf955, 0xf4 => 0xf956, + 0xf5 => 0xf957, 0xf6 => 0x80fd, 0xf7 => 0xf958, 0xf8 => 0xf959, + 0xf9 => 0x5c3c, 0xfa => 0x6ce5, 0xfb => 0x533f, 0xfc => 0x6eba, + 0xfd => 0x591a, 0xfe => 0x8336, + }, + 0xd3 => { + 0xa1 => 0x4e39, 0xa2 => 0x4eb6, 0xa3 => 0x4f46, 0xa4 => 0x55ae, + 0xa5 => 0x5718, 0xa6 => 0x58c7, 0xa7 => 0x5f56, 0xa8 => 0x65b7, + 0xa9 => 0x65e6, 0xaa => 0x6a80, 0xab => 0x6bb5, 0xac => 0x6e4d, + 0xad => 0x77ed, 0xae => 0x7aef, 0xaf => 0x7c1e, 0xb0 => 0x7dde, + 0xb1 => 0x86cb, 0xb2 => 0x8892, 0xb3 => 0x9132, 0xb4 => 0x935b, + 0xb5 => 0x64bb, 0xb6 => 0x6fbe, 0xb7 => 0x737a, 0xb8 => 0x75b8, + 0xb9 => 0x9054, 0xba => 0x5556, 0xbb => 0x574d, 0xbc => 0x61ba, + 0xbd => 0x64d4, 0xbe => 0x66c7, 0xbf => 0x6de1, 0xc0 => 0x6e5b, + 0xc1 => 0x6f6d, 0xc2 => 0x6fb9, 0xc3 => 0x75f0, 0xc4 => 0x8043, + 0xc5 => 0x81bd, 0xc6 => 0x8541, 0xc7 => 0x8983, 0xc8 => 0x8ac7, + 0xc9 => 0x8b5a, 0xca => 0x931f, 0xcb => 0x6c93, 0xcc => 0x7553, + 0xcd => 0x7b54, 0xce => 0x8e0f, 0xcf => 0x905d, 0xd0 => 0x5510, + 0xd1 => 0x5802, 0xd2 => 0x5858, 0xd3 => 0x5e62, 0xd4 => 0x6207, + 0xd5 => 0x649e, 0xd6 => 0x68e0, 0xd7 => 0x7576, 0xd8 => 0x7cd6, + 0xd9 => 0x87b3, 0xda => 0x9ee8, 0xdb => 0x4ee3, 0xdc => 0x5788, + 0xdd => 0x576e, 0xde => 0x5927, 0xdf => 0x5c0d, 0xe0 => 0x5cb1, + 0xe1 => 0x5e36, 0xe2 => 0x5f85, 0xe3 => 0x6234, 0xe4 => 0x64e1, + 0xe5 => 0x73b3, 0xe6 => 0x81fa, 0xe7 => 0x888b, 0xe8 => 0x8cb8, + 0xe9 => 0x968a, 0xea => 0x9edb, 0xeb => 0x5b85, 0xec => 0x5fb7, + 0xed => 0x60b3, 0xee => 0x5012, 0xef => 0x5200, 0xf0 => 0x5230, + 0xf1 => 0x5716, 0xf2 => 0x5835, 0xf3 => 0x5857, 0xf4 => 0x5c0e, + 0xf5 => 0x5c60, 0xf6 => 0x5cf6, 0xf7 => 0x5d8b, 0xf8 => 0x5ea6, + 0xf9 => 0x5f92, 0xfa => 0x60bc, 0xfb => 0x6311, 0xfc => 0x6389, + 0xfd => 0x6417, 0xfe => 0x6843, + }, + 0xd4 => { + 0xa1 => 0x68f9, 0xa2 => 0x6ac2, 0xa3 => 0x6dd8, 0xa4 => 0x6e21, + 0xa5 => 0x6ed4, 0xa6 => 0x6fe4, 0xa7 => 0x71fe, 0xa8 => 0x76dc, + 0xa9 => 0x7779, 0xaa => 0x79b1, 0xab => 0x7a3b, 0xac => 0x8404, + 0xad => 0x89a9, 0xae => 0x8ced, 0xaf => 0x8df3, 0xb0 => 0x8e48, + 0xb1 => 0x9003, 0xb2 => 0x9014, 0xb3 => 0x9053, 0xb4 => 0x90fd, + 0xb5 => 0x934d, 0xb6 => 0x9676, 0xb7 => 0x97dc, 0xb8 => 0x6bd2, + 0xb9 => 0x7006, 0xba => 0x7258, 0xbb => 0x72a2, 0xbc => 0x7368, + 0xbd => 0x7763, 0xbe => 0x79bf, 0xbf => 0x7be4, 0xc0 => 0x7e9b, + 0xc1 => 0x8b80, 0xc2 => 0x58a9, 0xc3 => 0x60c7, 0xc4 => 0x6566, + 0xc5 => 0x65fd, 0xc6 => 0x66be, 0xc7 => 0x6c8c, 0xc8 => 0x711e, + 0xc9 => 0x71c9, 0xca => 0x8c5a, 0xcb => 0x9813, 0xcc => 0x4e6d, + 0xcd => 0x7a81, 0xce => 0x4edd, 0xcf => 0x51ac, 0xd0 => 0x51cd, + 0xd1 => 0x52d5, 0xd2 => 0x540c, 0xd3 => 0x61a7, 0xd4 => 0x6771, + 0xd5 => 0x6850, 0xd6 => 0x68df, 0xd7 => 0x6d1e, 0xd8 => 0x6f7c, + 0xd9 => 0x75bc, 0xda => 0x77b3, 0xdb => 0x7ae5, 0xdc => 0x80f4, + 0xdd => 0x8463, 0xde => 0x9285, 0xdf => 0x515c, 0xe0 => 0x6597, + 0xe1 => 0x675c, 0xe2 => 0x6793, 0xe3 => 0x75d8, 0xe4 => 0x7ac7, + 0xe5 => 0x8373, 0xe6 => 0xf95a, 0xe7 => 0x8c46, 0xe8 => 0x9017, + 0xe9 => 0x982d, 0xea => 0x5c6f, 0xeb => 0x81c0, 0xec => 0x829a, + 0xed => 0x9041, 0xee => 0x906f, 0xef => 0x920d, 0xf0 => 0x5f97, + 0xf1 => 0x5d9d, 0xf2 => 0x6a59, 0xf3 => 0x71c8, 0xf4 => 0x767b, + 0xf5 => 0x7b49, 0xf6 => 0x85e4, 0xf7 => 0x8b04, 0xf8 => 0x9127, + 0xf9 => 0x9a30, 0xfa => 0x5587, 0xfb => 0x61f6, 0xfc => 0xf95b, + 0xfd => 0x7669, 0xfe => 0x7f85, + }, + 0xd5 => { + 0xa1 => 0x863f, 0xa2 => 0x87ba, 0xa3 => 0x88f8, 0xa4 => 0x908f, + 0xa5 => 0xf95c, 0xa6 => 0x6d1b, 0xa7 => 0x70d9, 0xa8 => 0x73de, + 0xa9 => 0x7d61, 0xaa => 0x843d, 0xab => 0xf95d, 0xac => 0x916a, + 0xad => 0x99f1, 0xae => 0xf95e, 0xaf => 0x4e82, 0xb0 => 0x5375, + 0xb1 => 0x6b04, 0xb2 => 0x6b12, 0xb3 => 0x703e, 0xb4 => 0x721b, + 0xb5 => 0x862d, 0xb6 => 0x9e1e, 0xb7 => 0x524c, 0xb8 => 0x8fa3, + 0xb9 => 0x5d50, 0xba => 0x64e5, 0xbb => 0x652c, 0xbc => 0x6b16, + 0xbd => 0x6feb, 0xbe => 0x7c43, 0xbf => 0x7e9c, 0xc0 => 0x85cd, + 0xc1 => 0x8964, 0xc2 => 0x89bd, 0xc3 => 0x62c9, 0xc4 => 0x81d8, + 0xc5 => 0x881f, 0xc6 => 0x5eca, 0xc7 => 0x6717, 0xc8 => 0x6d6a, + 0xc9 => 0x72fc, 0xca => 0x7405, 0xcb => 0x746f, 0xcc => 0x8782, + 0xcd => 0x90de, 0xce => 0x4f86, 0xcf => 0x5d0d, 0xd0 => 0x5fa0, + 0xd1 => 0x840a, 0xd2 => 0x51b7, 0xd3 => 0x63a0, 0xd4 => 0x7565, + 0xd5 => 0x4eae, 0xd6 => 0x5006, 0xd7 => 0x5169, 0xd8 => 0x51c9, + 0xd9 => 0x6881, 0xda => 0x6a11, 0xdb => 0x7cae, 0xdc => 0x7cb1, + 0xdd => 0x7ce7, 0xde => 0x826f, 0xdf => 0x8ad2, 0xe0 => 0x8f1b, + 0xe1 => 0x91cf, 0xe2 => 0x4fb6, 0xe3 => 0x5137, 0xe4 => 0x52f5, + 0xe5 => 0x5442, 0xe6 => 0x5eec, 0xe7 => 0x616e, 0xe8 => 0x623e, + 0xe9 => 0x65c5, 0xea => 0x6ada, 0xeb => 0x6ffe, 0xec => 0x792a, + 0xed => 0x85dc, 0xee => 0x8823, 0xef => 0x95ad, 0xf0 => 0x9a62, + 0xf1 => 0x9a6a, 0xf2 => 0x9e97, 0xf3 => 0x9ece, 0xf4 => 0x529b, + 0xf5 => 0x66c6, 0xf6 => 0x6b77, 0xf7 => 0x701d, 0xf8 => 0x792b, + 0xf9 => 0x8f62, 0xfa => 0x9742, 0xfb => 0x6190, 0xfc => 0x6200, + 0xfd => 0x6523, 0xfe => 0x6f23, + }, + 0xd6 => { + 0xa1 => 0x7149, 0xa2 => 0x7489, 0xa3 => 0x7df4, 0xa4 => 0x806f, + 0xa5 => 0x84ee, 0xa6 => 0x8f26, 0xa7 => 0x9023, 0xa8 => 0x934a, + 0xa9 => 0x51bd, 0xaa => 0x5217, 0xab => 0x52a3, 0xac => 0x6d0c, + 0xad => 0x70c8, 0xae => 0x88c2, 0xaf => 0x5ec9, 0xb0 => 0x6582, + 0xb1 => 0x6bae, 0xb2 => 0x6fc2, 0xb3 => 0x7c3e, 0xb4 => 0x7375, + 0xb5 => 0x4ee4, 0xb6 => 0x4f36, 0xb7 => 0x56f9, 0xb8 => 0xf95f, + 0xb9 => 0x5cba, 0xba => 0x5dba, 0xbb => 0x601c, 0xbc => 0x73b2, + 0xbd => 0x7b2d, 0xbe => 0x7f9a, 0xbf => 0x7fce, 0xc0 => 0x8046, + 0xc1 => 0x901e, 0xc2 => 0x9234, 0xc3 => 0x96f6, 0xc4 => 0x9748, + 0xc5 => 0x9818, 0xc6 => 0x9f61, 0xc7 => 0x4f8b, 0xc8 => 0x6fa7, + 0xc9 => 0x79ae, 0xca => 0x91b4, 0xcb => 0x96b7, 0xcc => 0x52de, + 0xcd => 0xf960, 0xce => 0x6488, 0xcf => 0x64c4, 0xd0 => 0x6ad3, + 0xd1 => 0x6f5e, 0xd2 => 0x7018, 0xd3 => 0x7210, 0xd4 => 0x76e7, + 0xd5 => 0x8001, 0xd6 => 0x8606, 0xd7 => 0x865c, 0xd8 => 0x8def, + 0xd9 => 0x8f05, 0xda => 0x9732, 0xdb => 0x9b6f, 0xdc => 0x9dfa, + 0xdd => 0x9e75, 0xde => 0x788c, 0xdf => 0x797f, 0xe0 => 0x7da0, + 0xe1 => 0x83c9, 0xe2 => 0x9304, 0xe3 => 0x9e7f, 0xe4 => 0x9e93, + 0xe5 => 0x8ad6, 0xe6 => 0x58df, 0xe7 => 0x5f04, 0xe8 => 0x6727, + 0xe9 => 0x7027, 0xea => 0x74cf, 0xeb => 0x7c60, 0xec => 0x807e, + 0xed => 0x5121, 0xee => 0x7028, 0xef => 0x7262, 0xf0 => 0x78ca, + 0xf1 => 0x8cc2, 0xf2 => 0x8cda, 0xf3 => 0x8cf4, 0xf4 => 0x96f7, + 0xf5 => 0x4e86, 0xf6 => 0x50da, 0xf7 => 0x5bee, 0xf8 => 0x5ed6, + 0xf9 => 0x6599, 0xfa => 0x71ce, 0xfb => 0x7642, 0xfc => 0x77ad, + 0xfd => 0x804a, 0xfe => 0x84fc, + }, + 0xd7 => { + 0xa1 => 0x907c, 0xa2 => 0x9b27, 0xa3 => 0x9f8d, 0xa4 => 0x58d8, + 0xa5 => 0x5a41, 0xa6 => 0x5c62, 0xa7 => 0x6a13, 0xa8 => 0x6dda, + 0xa9 => 0x6f0f, 0xaa => 0x763b, 0xab => 0x7d2f, 0xac => 0x7e37, + 0xad => 0x851e, 0xae => 0x8938, 0xaf => 0x93e4, 0xb0 => 0x964b, + 0xb1 => 0x5289, 0xb2 => 0x65d2, 0xb3 => 0x67f3, 0xb4 => 0x69b4, + 0xb5 => 0x6d41, 0xb6 => 0x6e9c, 0xb7 => 0x700f, 0xb8 => 0x7409, + 0xb9 => 0x7460, 0xba => 0x7559, 0xbb => 0x7624, 0xbc => 0x786b, + 0xbd => 0x8b2c, 0xbe => 0x985e, 0xbf => 0x516d, 0xc0 => 0x622e, + 0xc1 => 0x9678, 0xc2 => 0x4f96, 0xc3 => 0x502b, 0xc4 => 0x5d19, + 0xc5 => 0x6dea, 0xc6 => 0x7db8, 0xc7 => 0x8f2a, 0xc8 => 0x5f8b, + 0xc9 => 0x6144, 0xca => 0x6817, 0xcb => 0xf961, 0xcc => 0x9686, + 0xcd => 0x52d2, 0xce => 0x808b, 0xcf => 0x51dc, 0xd0 => 0x51cc, + 0xd1 => 0x695e, 0xd2 => 0x7a1c, 0xd3 => 0x7dbe, 0xd4 => 0x83f1, + 0xd5 => 0x9675, 0xd6 => 0x4fda, 0xd7 => 0x5229, 0xd8 => 0x5398, + 0xd9 => 0x540f, 0xda => 0x550e, 0xdb => 0x5c65, 0xdc => 0x60a7, + 0xdd => 0x674e, 0xde => 0x68a8, 0xdf => 0x6d6c, 0xe0 => 0x7281, + 0xe1 => 0x72f8, 0xe2 => 0x7406, 0xe3 => 0x7483, 0xe4 => 0xf962, + 0xe5 => 0x75e2, 0xe6 => 0x7c6c, 0xe7 => 0x7f79, 0xe8 => 0x7fb8, + 0xe9 => 0x8389, 0xea => 0x88cf, 0xeb => 0x88e1, 0xec => 0x91cc, + 0xed => 0x91d0, 0xee => 0x96e2, 0xef => 0x9bc9, 0xf0 => 0x541d, + 0xf1 => 0x6f7e, 0xf2 => 0x71d0, 0xf3 => 0x7498, 0xf4 => 0x85fa, + 0xf5 => 0x8eaa, 0xf6 => 0x96a3, 0xf7 => 0x9c57, 0xf8 => 0x9e9f, + 0xf9 => 0x6797, 0xfa => 0x6dcb, 0xfb => 0x7433, 0xfc => 0x81e8, + 0xfd => 0x9716, 0xfe => 0x782c, + }, + 0xd8 => { + 0xa1 => 0x7acb, 0xa2 => 0x7b20, 0xa3 => 0x7c92, 0xa4 => 0x6469, + 0xa5 => 0x746a, 0xa6 => 0x75f2, 0xa7 => 0x78bc, 0xa8 => 0x78e8, + 0xa9 => 0x99ac, 0xaa => 0x9b54, 0xab => 0x9ebb, 0xac => 0x5bde, + 0xad => 0x5e55, 0xae => 0x6f20, 0xaf => 0x819c, 0xb0 => 0x83ab, + 0xb1 => 0x9088, 0xb2 => 0x4e07, 0xb3 => 0x534d, 0xb4 => 0x5a29, + 0xb5 => 0x5dd2, 0xb6 => 0x5f4e, 0xb7 => 0x6162, 0xb8 => 0x633d, + 0xb9 => 0x6669, 0xba => 0x66fc, 0xbb => 0x6eff, 0xbc => 0x6f2b, + 0xbd => 0x7063, 0xbe => 0x779e, 0xbf => 0x842c, 0xc0 => 0x8513, + 0xc1 => 0x883b, 0xc2 => 0x8f13, 0xc3 => 0x9945, 0xc4 => 0x9c3b, + 0xc5 => 0x551c, 0xc6 => 0x62b9, 0xc7 => 0x672b, 0xc8 => 0x6cab, + 0xc9 => 0x8309, 0xca => 0x896a, 0xcb => 0x977a, 0xcc => 0x4ea1, + 0xcd => 0x5984, 0xce => 0x5fd8, 0xcf => 0x5fd9, 0xd0 => 0x671b, + 0xd1 => 0x7db2, 0xd2 => 0x7f54, 0xd3 => 0x8292, 0xd4 => 0x832b, + 0xd5 => 0x83bd, 0xd6 => 0x8f1e, 0xd7 => 0x9099, 0xd8 => 0x57cb, + 0xd9 => 0x59b9, 0xda => 0x5a92, 0xdb => 0x5bd0, 0xdc => 0x6627, + 0xdd => 0x679a, 0xde => 0x6885, 0xdf => 0x6bcf, 0xe0 => 0x7164, + 0xe1 => 0x7f75, 0xe2 => 0x8cb7, 0xe3 => 0x8ce3, 0xe4 => 0x9081, + 0xe5 => 0x9b45, 0xe6 => 0x8108, 0xe7 => 0x8c8a, 0xe8 => 0x964c, + 0xe9 => 0x9a40, 0xea => 0x9ea5, 0xeb => 0x5b5f, 0xec => 0x6c13, + 0xed => 0x731b, 0xee => 0x76f2, 0xef => 0x76df, 0xf0 => 0x840c, + 0xf1 => 0x51aa, 0xf2 => 0x8993, 0xf3 => 0x514d, 0xf4 => 0x5195, + 0xf5 => 0x52c9, 0xf6 => 0x68c9, 0xf7 => 0x6c94, 0xf8 => 0x7704, + 0xf9 => 0x7720, 0xfa => 0x7dbf, 0xfb => 0x7dec, 0xfc => 0x9762, + 0xfd => 0x9eb5, 0xfe => 0x6ec5, + }, + 0xd9 => { + 0xa1 => 0x8511, 0xa2 => 0x51a5, 0xa3 => 0x540d, 0xa4 => 0x547d, + 0xa5 => 0x660e, 0xa6 => 0x669d, 0xa7 => 0x6927, 0xa8 => 0x6e9f, + 0xa9 => 0x76bf, 0xaa => 0x7791, 0xab => 0x8317, 0xac => 0x84c2, + 0xad => 0x879f, 0xae => 0x9169, 0xaf => 0x9298, 0xb0 => 0x9cf4, + 0xb1 => 0x8882, 0xb2 => 0x4fae, 0xb3 => 0x5192, 0xb4 => 0x52df, + 0xb5 => 0x59c6, 0xb6 => 0x5e3d, 0xb7 => 0x6155, 0xb8 => 0x6478, + 0xb9 => 0x6479, 0xba => 0x66ae, 0xbb => 0x67d0, 0xbc => 0x6a21, + 0xbd => 0x6bcd, 0xbe => 0x6bdb, 0xbf => 0x725f, 0xc0 => 0x7261, + 0xc1 => 0x7441, 0xc2 => 0x7738, 0xc3 => 0x77db, 0xc4 => 0x8017, + 0xc5 => 0x82bc, 0xc6 => 0x8305, 0xc7 => 0x8b00, 0xc8 => 0x8b28, + 0xc9 => 0x8c8c, 0xca => 0x6728, 0xcb => 0x6c90, 0xcc => 0x7267, + 0xcd => 0x76ee, 0xce => 0x7766, 0xcf => 0x7a46, 0xd0 => 0x9da9, + 0xd1 => 0x6b7f, 0xd2 => 0x6c92, 0xd3 => 0x5922, 0xd4 => 0x6726, + 0xd5 => 0x8499, 0xd6 => 0x536f, 0xd7 => 0x5893, 0xd8 => 0x5999, + 0xd9 => 0x5edf, 0xda => 0x63cf, 0xdb => 0x6634, 0xdc => 0x6773, + 0xdd => 0x6e3a, 0xde => 0x732b, 0xdf => 0x7ad7, 0xe0 => 0x82d7, + 0xe1 => 0x9328, 0xe2 => 0x52d9, 0xe3 => 0x5deb, 0xe4 => 0x61ae, + 0xe5 => 0x61cb, 0xe6 => 0x620a, 0xe7 => 0x62c7, 0xe8 => 0x64ab, + 0xe9 => 0x65e0, 0xea => 0x6959, 0xeb => 0x6b66, 0xec => 0x6bcb, + 0xed => 0x7121, 0xee => 0x73f7, 0xef => 0x755d, 0xf0 => 0x7e46, + 0xf1 => 0x821e, 0xf2 => 0x8302, 0xf3 => 0x856a, 0xf4 => 0x8aa3, + 0xf5 => 0x8cbf, 0xf6 => 0x9727, 0xf7 => 0x9d61, 0xf8 => 0x58a8, + 0xf9 => 0x9ed8, 0xfa => 0x5011, 0xfb => 0x520e, 0xfc => 0x543b, + 0xfd => 0x554f, 0xfe => 0x6587, + }, + 0xda => { + 0xa1 => 0x6c76, 0xa2 => 0x7d0a, 0xa3 => 0x7d0b, 0xa4 => 0x805e, + 0xa5 => 0x868a, 0xa6 => 0x9580, 0xa7 => 0x96ef, 0xa8 => 0x52ff, + 0xa9 => 0x6c95, 0xaa => 0x7269, 0xab => 0x5473, 0xac => 0x5a9a, + 0xad => 0x5c3e, 0xae => 0x5d4b, 0xaf => 0x5f4c, 0xb0 => 0x5fae, + 0xb1 => 0x672a, 0xb2 => 0x68b6, 0xb3 => 0x6963, 0xb4 => 0x6e3c, + 0xb5 => 0x6e44, 0xb6 => 0x7709, 0xb7 => 0x7c73, 0xb8 => 0x7f8e, + 0xb9 => 0x8587, 0xba => 0x8b0e, 0xbb => 0x8ff7, 0xbc => 0x9761, + 0xbd => 0x9ef4, 0xbe => 0x5cb7, 0xbf => 0x60b6, 0xc0 => 0x610d, + 0xc1 => 0x61ab, 0xc2 => 0x654f, 0xc3 => 0x65fb, 0xc4 => 0x65fc, + 0xc5 => 0x6c11, 0xc6 => 0x6cef, 0xc7 => 0x739f, 0xc8 => 0x73c9, + 0xc9 => 0x7de1, 0xca => 0x9594, 0xcb => 0x5bc6, 0xcc => 0x871c, + 0xcd => 0x8b10, 0xce => 0x525d, 0xcf => 0x535a, 0xd0 => 0x62cd, + 0xd1 => 0x640f, 0xd2 => 0x64b2, 0xd3 => 0x6734, 0xd4 => 0x6a38, + 0xd5 => 0x6cca, 0xd6 => 0x73c0, 0xd7 => 0x749e, 0xd8 => 0x7b94, + 0xd9 => 0x7c95, 0xda => 0x7e1b, 0xdb => 0x818a, 0xdc => 0x8236, + 0xdd => 0x8584, 0xde => 0x8feb, 0xdf => 0x96f9, 0xe0 => 0x99c1, + 0xe1 => 0x4f34, 0xe2 => 0x534a, 0xe3 => 0x53cd, 0xe4 => 0x53db, + 0xe5 => 0x62cc, 0xe6 => 0x642c, 0xe7 => 0x6500, 0xe8 => 0x6591, + 0xe9 => 0x69c3, 0xea => 0x6cee, 0xeb => 0x6f58, 0xec => 0x73ed, + 0xed => 0x7554, 0xee => 0x7622, 0xef => 0x76e4, 0xf0 => 0x76fc, + 0xf1 => 0x78d0, 0xf2 => 0x78fb, 0xf3 => 0x792c, 0xf4 => 0x7d46, + 0xf5 => 0x822c, 0xf6 => 0x87e0, 0xf7 => 0x8fd4, 0xf8 => 0x9812, + 0xf9 => 0x98ef, 0xfa => 0x52c3, 0xfb => 0x62d4, 0xfc => 0x64a5, + 0xfd => 0x6e24, 0xfe => 0x6f51, + }, + 0xdb => { + 0xa1 => 0x767c, 0xa2 => 0x8dcb, 0xa3 => 0x91b1, 0xa4 => 0x9262, + 0xa5 => 0x9aee, 0xa6 => 0x9b43, 0xa7 => 0x5023, 0xa8 => 0x508d, + 0xa9 => 0x574a, 0xaa => 0x59a8, 0xab => 0x5c28, 0xac => 0x5e47, + 0xad => 0x5f77, 0xae => 0x623f, 0xaf => 0x653e, 0xb0 => 0x65b9, + 0xb1 => 0x65c1, 0xb2 => 0x6609, 0xb3 => 0x678b, 0xb4 => 0x699c, + 0xb5 => 0x6ec2, 0xb6 => 0x78c5, 0xb7 => 0x7d21, 0xb8 => 0x80aa, + 0xb9 => 0x8180, 0xba => 0x822b, 0xbb => 0x82b3, 0xbc => 0x84a1, + 0xbd => 0x868c, 0xbe => 0x8a2a, 0xbf => 0x8b17, 0xc0 => 0x90a6, + 0xc1 => 0x9632, 0xc2 => 0x9f90, 0xc3 => 0x500d, 0xc4 => 0x4ff3, + 0xc5 => 0xf963, 0xc6 => 0x57f9, 0xc7 => 0x5f98, 0xc8 => 0x62dc, + 0xc9 => 0x6392, 0xca => 0x676f, 0xcb => 0x6e43, 0xcc => 0x7119, + 0xcd => 0x76c3, 0xce => 0x80cc, 0xcf => 0x80da, 0xd0 => 0x88f4, + 0xd1 => 0x88f5, 0xd2 => 0x8919, 0xd3 => 0x8ce0, 0xd4 => 0x8f29, + 0xd5 => 0x914d, 0xd6 => 0x966a, 0xd7 => 0x4f2f, 0xd8 => 0x4f70, + 0xd9 => 0x5e1b, 0xda => 0x67cf, 0xdb => 0x6822, 0xdc => 0x767d, + 0xdd => 0x767e, 0xde => 0x9b44, 0xdf => 0x5e61, 0xe0 => 0x6a0a, + 0xe1 => 0x7169, 0xe2 => 0x71d4, 0xe3 => 0x756a, 0xe4 => 0xf964, + 0xe5 => 0x7e41, 0xe6 => 0x8543, 0xe7 => 0x85e9, 0xe8 => 0x98dc, + 0xe9 => 0x4f10, 0xea => 0x7b4f, 0xeb => 0x7f70, 0xec => 0x95a5, + 0xed => 0x51e1, 0xee => 0x5e06, 0xef => 0x68b5, 0xf0 => 0x6c3e, + 0xf1 => 0x6c4e, 0xf2 => 0x6cdb, 0xf3 => 0x72af, 0xf4 => 0x7bc4, + 0xf5 => 0x8303, 0xf6 => 0x6cd5, 0xf7 => 0x743a, 0xf8 => 0x50fb, + 0xf9 => 0x5288, 0xfa => 0x58c1, 0xfb => 0x64d8, 0xfc => 0x6a97, + 0xfd => 0x74a7, 0xfe => 0x7656, + }, + 0xdc => { + 0xa1 => 0x78a7, 0xa2 => 0x8617, 0xa3 => 0x95e2, 0xa4 => 0x9739, + 0xa5 => 0xf965, 0xa6 => 0x535e, 0xa7 => 0x5f01, 0xa8 => 0x8b8a, + 0xa9 => 0x8fa8, 0xaa => 0x8faf, 0xab => 0x908a, 0xac => 0x5225, + 0xad => 0x77a5, 0xae => 0x9c49, 0xaf => 0x9f08, 0xb0 => 0x4e19, + 0xb1 => 0x5002, 0xb2 => 0x5175, 0xb3 => 0x5c5b, 0xb4 => 0x5e77, + 0xb5 => 0x661e, 0xb6 => 0x663a, 0xb7 => 0x67c4, 0xb8 => 0x68c5, + 0xb9 => 0x70b3, 0xba => 0x7501, 0xbb => 0x75c5, 0xbc => 0x79c9, + 0xbd => 0x7add, 0xbe => 0x8f27, 0xbf => 0x9920, 0xc0 => 0x9a08, + 0xc1 => 0x4fdd, 0xc2 => 0x5821, 0xc3 => 0x5831, 0xc4 => 0x5bf6, + 0xc5 => 0x666e, 0xc6 => 0x6b65, 0xc7 => 0x6d11, 0xc8 => 0x6e7a, + 0xc9 => 0x6f7d, 0xca => 0x73e4, 0xcb => 0x752b, 0xcc => 0x83e9, + 0xcd => 0x88dc, 0xce => 0x8913, 0xcf => 0x8b5c, 0xd0 => 0x8f14, + 0xd1 => 0x4f0f, 0xd2 => 0x50d5, 0xd3 => 0x5310, 0xd4 => 0x535c, + 0xd5 => 0x5b93, 0xd6 => 0x5fa9, 0xd7 => 0x670d, 0xd8 => 0x798f, + 0xd9 => 0x8179, 0xda => 0x832f, 0xdb => 0x8514, 0xdc => 0x8907, + 0xdd => 0x8986, 0xde => 0x8f39, 0xdf => 0x8f3b, 0xe0 => 0x99a5, + 0xe1 => 0x9c12, 0xe2 => 0x672c, 0xe3 => 0x4e76, 0xe4 => 0x4ff8, + 0xe5 => 0x5949, 0xe6 => 0x5c01, 0xe7 => 0x5cef, 0xe8 => 0x5cf0, + 0xe9 => 0x6367, 0xea => 0x68d2, 0xeb => 0x70fd, 0xec => 0x71a2, + 0xed => 0x742b, 0xee => 0x7e2b, 0xef => 0x84ec, 0xf0 => 0x8702, + 0xf1 => 0x9022, 0xf2 => 0x92d2, 0xf3 => 0x9cf3, 0xf4 => 0x4e0d, + 0xf5 => 0x4ed8, 0xf6 => 0x4fef, 0xf7 => 0x5085, 0xf8 => 0x5256, + 0xf9 => 0x526f, 0xfa => 0x5426, 0xfb => 0x5490, 0xfc => 0x57e0, + 0xfd => 0x592b, 0xfe => 0x5a66, + }, + 0xdd => { + 0xa1 => 0x5b5a, 0xa2 => 0x5b75, 0xa3 => 0x5bcc, 0xa4 => 0x5e9c, + 0xa5 => 0xf966, 0xa6 => 0x6276, 0xa7 => 0x6577, 0xa8 => 0x65a7, + 0xa9 => 0x6d6e, 0xaa => 0x6ea5, 0xab => 0x7236, 0xac => 0x7b26, + 0xad => 0x7c3f, 0xae => 0x7f36, 0xaf => 0x8150, 0xb0 => 0x8151, + 0xb1 => 0x819a, 0xb2 => 0x8240, 0xb3 => 0x8299, 0xb4 => 0x83a9, + 0xb5 => 0x8a03, 0xb6 => 0x8ca0, 0xb7 => 0x8ce6, 0xb8 => 0x8cfb, + 0xb9 => 0x8d74, 0xba => 0x8dba, 0xbb => 0x90e8, 0xbc => 0x91dc, + 0xbd => 0x961c, 0xbe => 0x9644, 0xbf => 0x99d9, 0xc0 => 0x9ce7, + 0xc1 => 0x5317, 0xc2 => 0x5206, 0xc3 => 0x5429, 0xc4 => 0x5674, + 0xc5 => 0x58b3, 0xc6 => 0x5954, 0xc7 => 0x596e, 0xc8 => 0x5fff, + 0xc9 => 0x61a4, 0xca => 0x626e, 0xcb => 0x6610, 0xcc => 0x6c7e, + 0xcd => 0x711a, 0xce => 0x76c6, 0xcf => 0x7c89, 0xd0 => 0x7cde, + 0xd1 => 0x7d1b, 0xd2 => 0x82ac, 0xd3 => 0x8cc1, 0xd4 => 0x96f0, + 0xd5 => 0xf967, 0xd6 => 0x4f5b, 0xd7 => 0x5f17, 0xd8 => 0x5f7f, + 0xd9 => 0x62c2, 0xda => 0x5d29, 0xdb => 0x670b, 0xdc => 0x68da, + 0xdd => 0x787c, 0xde => 0x7e43, 0xdf => 0x9d6c, 0xe0 => 0x4e15, + 0xe1 => 0x5099, 0xe2 => 0x5315, 0xe3 => 0x532a, 0xe4 => 0x5351, + 0xe5 => 0x5983, 0xe6 => 0x5a62, 0xe7 => 0x5e87, 0xe8 => 0x60b2, + 0xe9 => 0x618a, 0xea => 0x6249, 0xeb => 0x6279, 0xec => 0x6590, + 0xed => 0x6787, 0xee => 0x69a7, 0xef => 0x6bd4, 0xf0 => 0x6bd6, + 0xf1 => 0x6bd7, 0xf2 => 0x6bd8, 0xf3 => 0x6cb8, 0xf4 => 0xf968, + 0xf5 => 0x7435, 0xf6 => 0x75fa, 0xf7 => 0x7812, 0xf8 => 0x7891, + 0xf9 => 0x79d5, 0xfa => 0x79d8, 0xfb => 0x7c83, 0xfc => 0x7dcb, + 0xfd => 0x7fe1, 0xfe => 0x80a5, + }, + 0xde => { + 0xa1 => 0x813e, 0xa2 => 0x81c2, 0xa3 => 0x83f2, 0xa4 => 0x871a, + 0xa5 => 0x88e8, 0xa6 => 0x8ab9, 0xa7 => 0x8b6c, 0xa8 => 0x8cbb, + 0xa9 => 0x9119, 0xaa => 0x975e, 0xab => 0x98db, 0xac => 0x9f3b, + 0xad => 0x56ac, 0xae => 0x5b2a, 0xaf => 0x5f6c, 0xb0 => 0x658c, + 0xb1 => 0x6ab3, 0xb2 => 0x6baf, 0xb3 => 0x6d5c, 0xb4 => 0x6ff1, + 0xb5 => 0x7015, 0xb6 => 0x725d, 0xb7 => 0x73ad, 0xb8 => 0x8ca7, + 0xb9 => 0x8cd3, 0xba => 0x983b, 0xbb => 0x6191, 0xbc => 0x6c37, + 0xbd => 0x8058, 0xbe => 0x9a01, 0xbf => 0x4e4d, 0xc0 => 0x4e8b, + 0xc1 => 0x4e9b, 0xc2 => 0x4ed5, 0xc3 => 0x4f3a, 0xc4 => 0x4f3c, + 0xc5 => 0x4f7f, 0xc6 => 0x4fdf, 0xc7 => 0x50ff, 0xc8 => 0x53f2, + 0xc9 => 0x53f8, 0xca => 0x5506, 0xcb => 0x55e3, 0xcc => 0x56db, + 0xcd => 0x58eb, 0xce => 0x5962, 0xcf => 0x5a11, 0xd0 => 0x5beb, + 0xd1 => 0x5bfa, 0xd2 => 0x5c04, 0xd3 => 0x5df3, 0xd4 => 0x5e2b, + 0xd5 => 0x5f99, 0xd6 => 0x601d, 0xd7 => 0x6368, 0xd8 => 0x659c, + 0xd9 => 0x65af, 0xda => 0x67f6, 0xdb => 0x67fb, 0xdc => 0x68ad, + 0xdd => 0x6b7b, 0xde => 0x6c99, 0xdf => 0x6cd7, 0xe0 => 0x6e23, + 0xe1 => 0x7009, 0xe2 => 0x7345, 0xe3 => 0x7802, 0xe4 => 0x793e, + 0xe5 => 0x7940, 0xe6 => 0x7960, 0xe7 => 0x79c1, 0xe8 => 0x7be9, + 0xe9 => 0x7d17, 0xea => 0x7d72, 0xeb => 0x8086, 0xec => 0x820d, + 0xed => 0x838e, 0xee => 0x84d1, 0xef => 0x86c7, 0xf0 => 0x88df, + 0xf1 => 0x8a50, 0xf2 => 0x8a5e, 0xf3 => 0x8b1d, 0xf4 => 0x8cdc, + 0xf5 => 0x8d66, 0xf6 => 0x8fad, 0xf7 => 0x90aa, 0xf8 => 0x98fc, + 0xf9 => 0x99df, 0xfa => 0x9e9d, 0xfb => 0x524a, 0xfc => 0xf969, + 0xfd => 0x6714, 0xfe => 0xf96a, + }, + 0xdf => { + 0xa1 => 0x5098, 0xa2 => 0x522a, 0xa3 => 0x5c71, 0xa4 => 0x6563, + 0xa5 => 0x6c55, 0xa6 => 0x73ca, 0xa7 => 0x7523, 0xa8 => 0x759d, + 0xa9 => 0x7b97, 0xaa => 0x849c, 0xab => 0x9178, 0xac => 0x9730, + 0xad => 0x4e77, 0xae => 0x6492, 0xaf => 0x6bba, 0xb0 => 0x715e, + 0xb1 => 0x85a9, 0xb2 => 0x4e09, 0xb3 => 0xf96b, 0xb4 => 0x6749, + 0xb5 => 0x68ee, 0xb6 => 0x6e17, 0xb7 => 0x829f, 0xb8 => 0x8518, + 0xb9 => 0x886b, 0xba => 0x63f7, 0xbb => 0x6f81, 0xbc => 0x9212, + 0xbd => 0x98af, 0xbe => 0x4e0a, 0xbf => 0x50b7, 0xc0 => 0x50cf, + 0xc1 => 0x511f, 0xc2 => 0x5546, 0xc3 => 0x55aa, 0xc4 => 0x5617, + 0xc5 => 0x5b40, 0xc6 => 0x5c19, 0xc7 => 0x5ce0, 0xc8 => 0x5e38, + 0xc9 => 0x5e8a, 0xca => 0x5ea0, 0xcb => 0x5ec2, 0xcc => 0x60f3, + 0xcd => 0x6851, 0xce => 0x6a61, 0xcf => 0x6e58, 0xd0 => 0x723d, + 0xd1 => 0x7240, 0xd2 => 0x72c0, 0xd3 => 0x76f8, 0xd4 => 0x7965, + 0xd5 => 0x7bb1, 0xd6 => 0x7fd4, 0xd7 => 0x88f3, 0xd8 => 0x89f4, + 0xd9 => 0x8a73, 0xda => 0x8c61, 0xdb => 0x8cde, 0xdc => 0x971c, + 0xdd => 0x585e, 0xde => 0x74bd, 0xdf => 0x8cfd, 0xe0 => 0x55c7, + 0xe1 => 0xf96c, 0xe2 => 0x7a61, 0xe3 => 0x7d22, 0xe4 => 0x8272, + 0xe5 => 0x7272, 0xe6 => 0x751f, 0xe7 => 0x7525, 0xe8 => 0xf96d, + 0xe9 => 0x7b19, 0xea => 0x5885, 0xeb => 0x58fb, 0xec => 0x5dbc, + 0xed => 0x5e8f, 0xee => 0x5eb6, 0xef => 0x5f90, 0xf0 => 0x6055, + 0xf1 => 0x6292, 0xf2 => 0x637f, 0xf3 => 0x654d, 0xf4 => 0x6691, + 0xf5 => 0x66d9, 0xf6 => 0x66f8, 0xf7 => 0x6816, 0xf8 => 0x68f2, + 0xf9 => 0x7280, 0xfa => 0x745e, 0xfb => 0x7b6e, 0xfc => 0x7d6e, + 0xfd => 0x7dd6, 0xfe => 0x7f72, + }, + 0xe0 => { + 0xa1 => 0x80e5, 0xa2 => 0x8212, 0xa3 => 0x85af, 0xa4 => 0x897f, + 0xa5 => 0x8a93, 0xa6 => 0x901d, 0xa7 => 0x92e4, 0xa8 => 0x9ecd, + 0xa9 => 0x9f20, 0xaa => 0x5915, 0xab => 0x596d, 0xac => 0x5e2d, + 0xad => 0x60dc, 0xae => 0x6614, 0xaf => 0x6673, 0xb0 => 0x6790, + 0xb1 => 0x6c50, 0xb2 => 0x6dc5, 0xb3 => 0x6f5f, 0xb4 => 0x77f3, + 0xb5 => 0x78a9, 0xb6 => 0x84c6, 0xb7 => 0x91cb, 0xb8 => 0x932b, + 0xb9 => 0x4ed9, 0xba => 0x50ca, 0xbb => 0x5148, 0xbc => 0x5584, + 0xbd => 0x5b0b, 0xbe => 0x5ba3, 0xbf => 0x6247, 0xc0 => 0x657e, + 0xc1 => 0x65cb, 0xc2 => 0x6e32, 0xc3 => 0x717d, 0xc4 => 0x7401, + 0xc5 => 0x7444, 0xc6 => 0x7487, 0xc7 => 0x74bf, 0xc8 => 0x766c, + 0xc9 => 0x79aa, 0xca => 0x7dda, 0xcb => 0x7e55, 0xcc => 0x7fa8, + 0xcd => 0x817a, 0xce => 0x81b3, 0xcf => 0x8239, 0xd0 => 0x861a, + 0xd1 => 0x87ec, 0xd2 => 0x8a75, 0xd3 => 0x8de3, 0xd4 => 0x9078, + 0xd5 => 0x9291, 0xd6 => 0x9425, 0xd7 => 0x994d, 0xd8 => 0x9bae, + 0xd9 => 0x5368, 0xda => 0x5c51, 0xdb => 0x6954, 0xdc => 0x6cc4, + 0xdd => 0x6d29, 0xde => 0x6e2b, 0xdf => 0x820c, 0xe0 => 0x859b, + 0xe1 => 0x893b, 0xe2 => 0x8a2d, 0xe3 => 0x8aaa, 0xe4 => 0x96ea, + 0xe5 => 0x9f67, 0xe6 => 0x5261, 0xe7 => 0x66b9, 0xe8 => 0x6bb2, + 0xe9 => 0x7e96, 0xea => 0x87fe, 0xeb => 0x8d0d, 0xec => 0x9583, + 0xed => 0x965d, 0xee => 0x651d, 0xef => 0x6d89, 0xf0 => 0x71ee, + 0xf1 => 0xf96e, 0xf2 => 0x57ce, 0xf3 => 0x59d3, 0xf4 => 0x5bac, + 0xf5 => 0x6027, 0xf6 => 0x60fa, 0xf7 => 0x6210, 0xf8 => 0x661f, + 0xf9 => 0x665f, 0xfa => 0x7329, 0xfb => 0x73f9, 0xfc => 0x76db, + 0xfd => 0x7701, 0xfe => 0x7b6c, + }, + 0xe1 => { + 0xa1 => 0x8056, 0xa2 => 0x8072, 0xa3 => 0x8165, 0xa4 => 0x8aa0, + 0xa5 => 0x9192, 0xa6 => 0x4e16, 0xa7 => 0x52e2, 0xa8 => 0x6b72, + 0xa9 => 0x6d17, 0xaa => 0x7a05, 0xab => 0x7b39, 0xac => 0x7d30, + 0xad => 0xf96f, 0xae => 0x8cb0, 0xaf => 0x53ec, 0xb0 => 0x562f, + 0xb1 => 0x5851, 0xb2 => 0x5bb5, 0xb3 => 0x5c0f, 0xb4 => 0x5c11, + 0xb5 => 0x5de2, 0xb6 => 0x6240, 0xb7 => 0x6383, 0xb8 => 0x6414, + 0xb9 => 0x662d, 0xba => 0x68b3, 0xbb => 0x6cbc, 0xbc => 0x6d88, + 0xbd => 0x6eaf, 0xbe => 0x701f, 0xbf => 0x70a4, 0xc0 => 0x71d2, + 0xc1 => 0x7526, 0xc2 => 0x758f, 0xc3 => 0x758e, 0xc4 => 0x7619, + 0xc5 => 0x7b11, 0xc6 => 0x7be0, 0xc7 => 0x7c2b, 0xc8 => 0x7d20, + 0xc9 => 0x7d39, 0xca => 0x852c, 0xcb => 0x856d, 0xcc => 0x8607, + 0xcd => 0x8a34, 0xce => 0x900d, 0xcf => 0x9061, 0xd0 => 0x90b5, + 0xd1 => 0x92b7, 0xd2 => 0x97f6, 0xd3 => 0x9a37, 0xd4 => 0x4fd7, + 0xd5 => 0x5c6c, 0xd6 => 0x675f, 0xd7 => 0x6d91, 0xd8 => 0x7c9f, + 0xd9 => 0x7e8c, 0xda => 0x8b16, 0xdb => 0x8d16, 0xdc => 0x901f, + 0xdd => 0x5b6b, 0xde => 0x5dfd, 0xdf => 0x640d, 0xe0 => 0x84c0, + 0xe1 => 0x905c, 0xe2 => 0x98e1, 0xe3 => 0x7387, 0xe4 => 0x5b8b, + 0xe5 => 0x609a, 0xe6 => 0x677e, 0xe7 => 0x6dde, 0xe8 => 0x8a1f, + 0xe9 => 0x8aa6, 0xea => 0x9001, 0xeb => 0x980c, 0xec => 0x5237, + 0xed => 0xf970, 0xee => 0x7051, 0xef => 0x788e, 0xf0 => 0x9396, + 0xf1 => 0x8870, 0xf2 => 0x91d7, 0xf3 => 0x4fee, 0xf4 => 0x53d7, + 0xf5 => 0x55fd, 0xf6 => 0x56da, 0xf7 => 0x5782, 0xf8 => 0x58fd, + 0xf9 => 0x5ac2, 0xfa => 0x5b88, 0xfb => 0x5cab, 0xfc => 0x5cc0, + 0xfd => 0x5e25, 0xfe => 0x6101, + }, + 0xe2 => { + 0xa1 => 0x620d, 0xa2 => 0x624b, 0xa3 => 0x6388, 0xa4 => 0x641c, + 0xa5 => 0x6536, 0xa6 => 0x6578, 0xa7 => 0x6a39, 0xa8 => 0x6b8a, + 0xa9 => 0x6c34, 0xaa => 0x6d19, 0xab => 0x6f31, 0xac => 0x71e7, + 0xad => 0x72e9, 0xae => 0x7378, 0xaf => 0x7407, 0xb0 => 0x74b2, + 0xb1 => 0x7626, 0xb2 => 0x7761, 0xb3 => 0x79c0, 0xb4 => 0x7a57, + 0xb5 => 0x7aea, 0xb6 => 0x7cb9, 0xb7 => 0x7d8f, 0xb8 => 0x7dac, + 0xb9 => 0x7e61, 0xba => 0x7f9e, 0xbb => 0x8129, 0xbc => 0x8331, + 0xbd => 0x8490, 0xbe => 0x84da, 0xbf => 0x85ea, 0xc0 => 0x8896, + 0xc1 => 0x8ab0, 0xc2 => 0x8b90, 0xc3 => 0x8f38, 0xc4 => 0x9042, + 0xc5 => 0x9083, 0xc6 => 0x916c, 0xc7 => 0x9296, 0xc8 => 0x92b9, + 0xc9 => 0x968b, 0xca => 0x96a7, 0xcb => 0x96a8, 0xcc => 0x96d6, + 0xcd => 0x9700, 0xce => 0x9808, 0xcf => 0x9996, 0xd0 => 0x9ad3, + 0xd1 => 0x9b1a, 0xd2 => 0x53d4, 0xd3 => 0x587e, 0xd4 => 0x5919, + 0xd5 => 0x5b70, 0xd6 => 0x5bbf, 0xd7 => 0x6dd1, 0xd8 => 0x6f5a, + 0xd9 => 0x719f, 0xda => 0x7421, 0xdb => 0x74b9, 0xdc => 0x8085, + 0xdd => 0x83fd, 0xde => 0x5de1, 0xdf => 0x5f87, 0xe0 => 0x5faa, + 0xe1 => 0x6042, 0xe2 => 0x65ec, 0xe3 => 0x6812, 0xe4 => 0x696f, + 0xe5 => 0x6a53, 0xe6 => 0x6b89, 0xe7 => 0x6d35, 0xe8 => 0x6df3, + 0xe9 => 0x73e3, 0xea => 0x76fe, 0xeb => 0x77ac, 0xec => 0x7b4d, + 0xed => 0x7d14, 0xee => 0x8123, 0xef => 0x821c, 0xf0 => 0x8340, + 0xf1 => 0x84f4, 0xf2 => 0x8563, 0xf3 => 0x8a62, 0xf4 => 0x8ac4, + 0xf5 => 0x9187, 0xf6 => 0x931e, 0xf7 => 0x9806, 0xf8 => 0x99b4, + 0xf9 => 0x620c, 0xfa => 0x8853, 0xfb => 0x8ff0, 0xfc => 0x9265, + 0xfd => 0x5d07, 0xfe => 0x5d27, + }, + 0xe3 => { + 0xa1 => 0x5d69, 0xa2 => 0x745f, 0xa3 => 0x819d, 0xa4 => 0x8768, + 0xa5 => 0x6fd5, 0xa6 => 0x62fe, 0xa7 => 0x7fd2, 0xa8 => 0x8936, + 0xa9 => 0x8972, 0xaa => 0x4e1e, 0xab => 0x4e58, 0xac => 0x50e7, + 0xad => 0x52dd, 0xae => 0x5347, 0xaf => 0x627f, 0xb0 => 0x6607, + 0xb1 => 0x7e69, 0xb2 => 0x8805, 0xb3 => 0x965e, 0xb4 => 0x4f8d, + 0xb5 => 0x5319, 0xb6 => 0x5636, 0xb7 => 0x59cb, 0xb8 => 0x5aa4, + 0xb9 => 0x5c38, 0xba => 0x5c4e, 0xbb => 0x5c4d, 0xbc => 0x5e02, + 0xbd => 0x5f11, 0xbe => 0x6043, 0xbf => 0x65bd, 0xc0 => 0x662f, + 0xc1 => 0x6642, 0xc2 => 0x67be, 0xc3 => 0x67f4, 0xc4 => 0x731c, + 0xc5 => 0x77e2, 0xc6 => 0x793a, 0xc7 => 0x7fc5, 0xc8 => 0x8494, + 0xc9 => 0x84cd, 0xca => 0x8996, 0xcb => 0x8a66, 0xcc => 0x8a69, + 0xcd => 0x8ae1, 0xce => 0x8c55, 0xcf => 0x8c7a, 0xd0 => 0x57f4, + 0xd1 => 0x5bd4, 0xd2 => 0x5f0f, 0xd3 => 0x606f, 0xd4 => 0x62ed, + 0xd5 => 0x690d, 0xd6 => 0x6b96, 0xd7 => 0x6e5c, 0xd8 => 0x7184, + 0xd9 => 0x7bd2, 0xda => 0x8755, 0xdb => 0x8b58, 0xdc => 0x8efe, + 0xdd => 0x98df, 0xde => 0x98fe, 0xdf => 0x4f38, 0xe0 => 0x4f81, + 0xe1 => 0x4fe1, 0xe2 => 0x547b, 0xe3 => 0x5a20, 0xe4 => 0x5bb8, + 0xe5 => 0x613c, 0xe6 => 0x65b0, 0xe7 => 0x6668, 0xe8 => 0x71fc, + 0xe9 => 0x7533, 0xea => 0x795e, 0xeb => 0x7d33, 0xec => 0x814e, + 0xed => 0x81e3, 0xee => 0x8398, 0xef => 0x85aa, 0xf0 => 0x85ce, + 0xf1 => 0x8703, 0xf2 => 0x8a0a, 0xf3 => 0x8eab, 0xf4 => 0x8f9b, + 0xf5 => 0xf971, 0xf6 => 0x8fc5, 0xf7 => 0x5931, 0xf8 => 0x5ba4, + 0xf9 => 0x5be6, 0xfa => 0x6089, 0xfb => 0x5be9, 0xfc => 0x5c0b, + 0xfd => 0x5fc3, 0xfe => 0x6c81, + }, + 0xe4 => { + 0xa1 => 0xf972, 0xa2 => 0x6df1, 0xa3 => 0x700b, 0xa4 => 0x751a, + 0xa5 => 0x82af, 0xa6 => 0x8af6, 0xa7 => 0x4ec0, 0xa8 => 0x5341, + 0xa9 => 0xf973, 0xaa => 0x96d9, 0xab => 0x6c0f, 0xac => 0x4e9e, + 0xad => 0x4fc4, 0xae => 0x5152, 0xaf => 0x555e, 0xb0 => 0x5a25, + 0xb1 => 0x5ce8, 0xb2 => 0x6211, 0xb3 => 0x7259, 0xb4 => 0x82bd, + 0xb5 => 0x83aa, 0xb6 => 0x86fe, 0xb7 => 0x8859, 0xb8 => 0x8a1d, + 0xb9 => 0x963f, 0xba => 0x96c5, 0xbb => 0x9913, 0xbc => 0x9d09, + 0xbd => 0x9d5d, 0xbe => 0x580a, 0xbf => 0x5cb3, 0xc0 => 0x5dbd, + 0xc1 => 0x5e44, 0xc2 => 0x60e1, 0xc3 => 0x6115, 0xc4 => 0x63e1, + 0xc5 => 0x6a02, 0xc6 => 0x6e25, 0xc7 => 0x9102, 0xc8 => 0x9354, + 0xc9 => 0x984e, 0xca => 0x9c10, 0xcb => 0x9f77, 0xcc => 0x5b89, + 0xcd => 0x5cb8, 0xce => 0x6309, 0xcf => 0x664f, 0xd0 => 0x6848, + 0xd1 => 0x773c, 0xd2 => 0x96c1, 0xd3 => 0x978d, 0xd4 => 0x9854, + 0xd5 => 0x9b9f, 0xd6 => 0x65a1, 0xd7 => 0x8b01, 0xd8 => 0x8ecb, + 0xd9 => 0x95bc, 0xda => 0x5535, 0xdb => 0x5ca9, 0xdc => 0x5dd6, + 0xdd => 0x5eb5, 0xde => 0x6697, 0xdf => 0x764c, 0xe0 => 0x83f4, + 0xe1 => 0x95c7, 0xe2 => 0x58d3, 0xe3 => 0x62bc, 0xe4 => 0x72ce, + 0xe5 => 0x9d28, 0xe6 => 0x4ef0, 0xe7 => 0x592e, 0xe8 => 0x600f, + 0xe9 => 0x663b, 0xea => 0x6b83, 0xeb => 0x79e7, 0xec => 0x9d26, + 0xed => 0x5393, 0xee => 0x54c0, 0xef => 0x57c3, 0xf0 => 0x5d16, + 0xf1 => 0x611b, 0xf2 => 0x66d6, 0xf3 => 0x6daf, 0xf4 => 0x788d, + 0xf5 => 0x827e, 0xf6 => 0x9698, 0xf7 => 0x9744, 0xf8 => 0x5384, + 0xf9 => 0x627c, 0xfa => 0x6396, 0xfb => 0x6db2, 0xfc => 0x7e0a, + 0xfd => 0x814b, 0xfe => 0x984d, + }, + 0xe5 => { + 0xa1 => 0x6afb, 0xa2 => 0x7f4c, 0xa3 => 0x9daf, 0xa4 => 0x9e1a, + 0xa5 => 0x4e5f, 0xa6 => 0x503b, 0xa7 => 0x51b6, 0xa8 => 0x591c, + 0xa9 => 0x60f9, 0xaa => 0x63f6, 0xab => 0x6930, 0xac => 0x723a, + 0xad => 0x8036, 0xae => 0xf974, 0xaf => 0x91ce, 0xb0 => 0x5f31, + 0xb1 => 0xf975, 0xb2 => 0xf976, 0xb3 => 0x7d04, 0xb4 => 0x82e5, + 0xb5 => 0x846f, 0xb6 => 0x84bb, 0xb7 => 0x85e5, 0xb8 => 0x8e8d, + 0xb9 => 0xf977, 0xba => 0x4f6f, 0xbb => 0xf978, 0xbc => 0xf979, + 0xbd => 0x58e4, 0xbe => 0x5b43, 0xbf => 0x6059, 0xc0 => 0x63da, + 0xc1 => 0x6518, 0xc2 => 0x656d, 0xc3 => 0x6698, 0xc4 => 0xf97a, + 0xc5 => 0x694a, 0xc6 => 0x6a23, 0xc7 => 0x6d0b, 0xc8 => 0x7001, + 0xc9 => 0x716c, 0xca => 0x75d2, 0xcb => 0x760d, 0xcc => 0x79b3, + 0xcd => 0x7a70, 0xce => 0xf97b, 0xcf => 0x7f8a, 0xd0 => 0xf97c, + 0xd1 => 0x8944, 0xd2 => 0xf97d, 0xd3 => 0x8b93, 0xd4 => 0x91c0, + 0xd5 => 0x967d, 0xd6 => 0xf97e, 0xd7 => 0x990a, 0xd8 => 0x5704, + 0xd9 => 0x5fa1, 0xda => 0x65bc, 0xdb => 0x6f01, 0xdc => 0x7600, + 0xdd => 0x79a6, 0xde => 0x8a9e, 0xdf => 0x99ad, 0xe0 => 0x9b5a, + 0xe1 => 0x9f6c, 0xe2 => 0x5104, 0xe3 => 0x61b6, 0xe4 => 0x6291, + 0xe5 => 0x6a8d, 0xe6 => 0x81c6, 0xe7 => 0x5043, 0xe8 => 0x5830, + 0xe9 => 0x5f66, 0xea => 0x7109, 0xeb => 0x8a00, 0xec => 0x8afa, + 0xed => 0x5b7c, 0xee => 0x8616, 0xef => 0x4ffa, 0xf0 => 0x513c, + 0xf1 => 0x56b4, 0xf2 => 0x5944, 0xf3 => 0x63a9, 0xf4 => 0x6df9, + 0xf5 => 0x5daa, 0xf6 => 0x696d, 0xf7 => 0x5186, 0xf8 => 0x4e88, + 0xf9 => 0x4f59, 0xfa => 0xf97f, 0xfb => 0xf980, 0xfc => 0xf981, + 0xfd => 0x5982, 0xfe => 0xf982, + }, + 0xe6 => { + 0xa1 => 0xf983, 0xa2 => 0x6b5f, 0xa3 => 0x6c5d, 0xa4 => 0xf984, + 0xa5 => 0x74b5, 0xa6 => 0x7916, 0xa7 => 0xf985, 0xa8 => 0x8207, + 0xa9 => 0x8245, 0xaa => 0x8339, 0xab => 0x8f3f, 0xac => 0x8f5d, + 0xad => 0xf986, 0xae => 0x9918, 0xaf => 0xf987, 0xb0 => 0xf988, + 0xb1 => 0xf989, 0xb2 => 0x4ea6, 0xb3 => 0xf98a, 0xb4 => 0x57df, + 0xb5 => 0x5f79, 0xb6 => 0x6613, 0xb7 => 0xf98b, 0xb8 => 0xf98c, + 0xb9 => 0x75ab, 0xba => 0x7e79, 0xbb => 0x8b6f, 0xbc => 0xf98d, + 0xbd => 0x9006, 0xbe => 0x9a5b, 0xbf => 0x56a5, 0xc0 => 0x5827, + 0xc1 => 0x59f8, 0xc2 => 0x5a1f, 0xc3 => 0x5bb4, 0xc4 => 0xf98e, + 0xc5 => 0x5ef6, 0xc6 => 0xf98f, 0xc7 => 0xf990, 0xc8 => 0x6350, + 0xc9 => 0x633b, 0xca => 0xf991, 0xcb => 0x693d, 0xcc => 0x6c87, + 0xcd => 0x6cbf, 0xce => 0x6d8e, 0xcf => 0x6d93, 0xd0 => 0x6df5, + 0xd1 => 0x6f14, 0xd2 => 0xf992, 0xd3 => 0x70df, 0xd4 => 0x7136, + 0xd5 => 0x7159, 0xd6 => 0xf993, 0xd7 => 0x71c3, 0xd8 => 0x71d5, + 0xd9 => 0xf994, 0xda => 0x784f, 0xdb => 0x786f, 0xdc => 0xf995, + 0xdd => 0x7b75, 0xde => 0x7de3, 0xdf => 0xf996, 0xe0 => 0x7e2f, + 0xe1 => 0xf997, 0xe2 => 0x884d, 0xe3 => 0x8edf, 0xe4 => 0xf998, + 0xe5 => 0xf999, 0xe6 => 0xf99a, 0xe7 => 0x925b, 0xe8 => 0xf99b, + 0xe9 => 0x9cf6, 0xea => 0xf99c, 0xeb => 0xf99d, 0xec => 0xf99e, + 0xed => 0x6085, 0xee => 0x6d85, 0xef => 0xf99f, 0xf0 => 0x71b1, + 0xf1 => 0xf9a0, 0xf2 => 0xf9a1, 0xf3 => 0x95b1, 0xf4 => 0x53ad, + 0xf5 => 0xf9a2, 0xf6 => 0xf9a3, 0xf7 => 0xf9a4, 0xf8 => 0x67d3, + 0xf9 => 0xf9a5, 0xfa => 0x708e, 0xfb => 0x7130, 0xfc => 0x7430, + 0xfd => 0x8276, 0xfe => 0x82d2, + }, + 0xe7 => { + 0xa1 => 0xf9a6, 0xa2 => 0x95bb, 0xa3 => 0x9ae5, 0xa4 => 0x9e7d, + 0xa5 => 0x66c4, 0xa6 => 0xf9a7, 0xa7 => 0x71c1, 0xa8 => 0x8449, + 0xa9 => 0xf9a8, 0xaa => 0xf9a9, 0xab => 0x584b, 0xac => 0xf9aa, + 0xad => 0xf9ab, 0xae => 0x5db8, 0xaf => 0x5f71, 0xb0 => 0xf9ac, + 0xb1 => 0x6620, 0xb2 => 0x668e, 0xb3 => 0x6979, 0xb4 => 0x69ae, + 0xb5 => 0x6c38, 0xb6 => 0x6cf3, 0xb7 => 0x6e36, 0xb8 => 0x6f41, + 0xb9 => 0x6fda, 0xba => 0x701b, 0xbb => 0x702f, 0xbc => 0x7150, + 0xbd => 0x71df, 0xbe => 0x7370, 0xbf => 0xf9ad, 0xc0 => 0x745b, + 0xc1 => 0xf9ae, 0xc2 => 0x74d4, 0xc3 => 0x76c8, 0xc4 => 0x7a4e, + 0xc5 => 0x7e93, 0xc6 => 0xf9af, 0xc7 => 0xf9b0, 0xc8 => 0x82f1, + 0xc9 => 0x8a60, 0xca => 0x8fce, 0xcb => 0xf9b1, 0xcc => 0x9348, + 0xcd => 0xf9b2, 0xce => 0x9719, 0xcf => 0xf9b3, 0xd0 => 0xf9b4, + 0xd1 => 0x4e42, 0xd2 => 0x502a, 0xd3 => 0xf9b5, 0xd4 => 0x5208, + 0xd5 => 0x53e1, 0xd6 => 0x66f3, 0xd7 => 0x6c6d, 0xd8 => 0x6fca, + 0xd9 => 0x730a, 0xda => 0x777f, 0xdb => 0x7a62, 0xdc => 0x82ae, + 0xdd => 0x85dd, 0xde => 0x8602, 0xdf => 0xf9b6, 0xe0 => 0x88d4, + 0xe1 => 0x8a63, 0xe2 => 0x8b7d, 0xe3 => 0x8c6b, 0xe4 => 0xf9b7, + 0xe5 => 0x92b3, 0xe6 => 0xf9b8, 0xe7 => 0x9713, 0xe8 => 0x9810, + 0xe9 => 0x4e94, 0xea => 0x4f0d, 0xeb => 0x4fc9, 0xec => 0x50b2, + 0xed => 0x5348, 0xee => 0x543e, 0xef => 0x5433, 0xf0 => 0x55da, + 0xf1 => 0x5862, 0xf2 => 0x58ba, 0xf3 => 0x5967, 0xf4 => 0x5a1b, + 0xf5 => 0x5be4, 0xf6 => 0x609f, 0xf7 => 0xf9b9, 0xf8 => 0x61ca, + 0xf9 => 0x6556, 0xfa => 0x65ff, 0xfb => 0x6664, 0xfc => 0x68a7, + 0xfd => 0x6c5a, 0xfe => 0x6fb3, + }, + 0xe8 => { + 0xa1 => 0x70cf, 0xa2 => 0x71ac, 0xa3 => 0x7352, 0xa4 => 0x7b7d, + 0xa5 => 0x8708, 0xa6 => 0x8aa4, 0xa7 => 0x9c32, 0xa8 => 0x9f07, + 0xa9 => 0x5c4b, 0xaa => 0x6c83, 0xab => 0x7344, 0xac => 0x7389, + 0xad => 0x923a, 0xae => 0x6eab, 0xaf => 0x7465, 0xb0 => 0x761f, + 0xb1 => 0x7a69, 0xb2 => 0x7e15, 0xb3 => 0x860a, 0xb4 => 0x5140, + 0xb5 => 0x58c5, 0xb6 => 0x64c1, 0xb7 => 0x74ee, 0xb8 => 0x7515, + 0xb9 => 0x7670, 0xba => 0x7fc1, 0xbb => 0x9095, 0xbc => 0x96cd, + 0xbd => 0x9954, 0xbe => 0x6e26, 0xbf => 0x74e6, 0xc0 => 0x7aa9, + 0xc1 => 0x7aaa, 0xc2 => 0x81e5, 0xc3 => 0x86d9, 0xc4 => 0x8778, + 0xc5 => 0x8a1b, 0xc6 => 0x5a49, 0xc7 => 0x5b8c, 0xc8 => 0x5b9b, + 0xc9 => 0x68a1, 0xca => 0x6900, 0xcb => 0x6d63, 0xcc => 0x73a9, + 0xcd => 0x7413, 0xce => 0x742c, 0xcf => 0x7897, 0xd0 => 0x7de9, + 0xd1 => 0x7feb, 0xd2 => 0x8118, 0xd3 => 0x8155, 0xd4 => 0x839e, + 0xd5 => 0x8c4c, 0xd6 => 0x962e, 0xd7 => 0x9811, 0xd8 => 0x66f0, + 0xd9 => 0x5f80, 0xda => 0x65fa, 0xdb => 0x6789, 0xdc => 0x6c6a, + 0xdd => 0x738b, 0xde => 0x502d, 0xdf => 0x5a03, 0xe0 => 0x6b6a, + 0xe1 => 0x77ee, 0xe2 => 0x5916, 0xe3 => 0x5d6c, 0xe4 => 0x5dcd, + 0xe5 => 0x7325, 0xe6 => 0x754f, 0xe7 => 0xf9ba, 0xe8 => 0xf9bb, + 0xe9 => 0x50e5, 0xea => 0x51f9, 0xeb => 0x582f, 0xec => 0x592d, + 0xed => 0x5996, 0xee => 0x59da, 0xef => 0x5be5, 0xf0 => 0xf9bc, + 0xf1 => 0xf9bd, 0xf2 => 0x5da2, 0xf3 => 0x62d7, 0xf4 => 0x6416, + 0xf5 => 0x6493, 0xf6 => 0x64fe, 0xf7 => 0xf9be, 0xf8 => 0x66dc, + 0xf9 => 0xf9bf, 0xfa => 0x6a48, 0xfb => 0xf9c0, 0xfc => 0x71ff, + 0xfd => 0x7464, 0xfe => 0xf9c1, + }, + 0xe9 => { + 0xa1 => 0x7a88, 0xa2 => 0x7aaf, 0xa3 => 0x7e47, 0xa4 => 0x7e5e, + 0xa5 => 0x8000, 0xa6 => 0x8170, 0xa7 => 0xf9c2, 0xa8 => 0x87ef, + 0xa9 => 0x8981, 0xaa => 0x8b20, 0xab => 0x9059, 0xac => 0xf9c3, + 0xad => 0x9080, 0xae => 0x9952, 0xaf => 0x617e, 0xb0 => 0x6b32, + 0xb1 => 0x6d74, 0xb2 => 0x7e1f, 0xb3 => 0x8925, 0xb4 => 0x8fb1, + 0xb5 => 0x4fd1, 0xb6 => 0x50ad, 0xb7 => 0x5197, 0xb8 => 0x52c7, + 0xb9 => 0x57c7, 0xba => 0x5889, 0xbb => 0x5bb9, 0xbc => 0x5eb8, + 0xbd => 0x6142, 0xbe => 0x6995, 0xbf => 0x6d8c, 0xc0 => 0x6e67, + 0xc1 => 0x6eb6, 0xc2 => 0x7194, 0xc3 => 0x7462, 0xc4 => 0x7528, + 0xc5 => 0x752c, 0xc6 => 0x8073, 0xc7 => 0x8338, 0xc8 => 0x84c9, + 0xc9 => 0x8e0a, 0xca => 0x9394, 0xcb => 0x93de, 0xcc => 0xf9c4, + 0xcd => 0x4e8e, 0xce => 0x4f51, 0xcf => 0x5076, 0xd0 => 0x512a, + 0xd1 => 0x53c8, 0xd2 => 0x53cb, 0xd3 => 0x53f3, 0xd4 => 0x5b87, + 0xd5 => 0x5bd3, 0xd6 => 0x5c24, 0xd7 => 0x611a, 0xd8 => 0x6182, + 0xd9 => 0x65f4, 0xda => 0x725b, 0xdb => 0x7397, 0xdc => 0x7440, + 0xdd => 0x76c2, 0xde => 0x7950, 0xdf => 0x7991, 0xe0 => 0x79b9, + 0xe1 => 0x7d06, 0xe2 => 0x7fbd, 0xe3 => 0x828b, 0xe4 => 0x85d5, + 0xe5 => 0x865e, 0xe6 => 0x8fc2, 0xe7 => 0x9047, 0xe8 => 0x90f5, + 0xe9 => 0x91ea, 0xea => 0x9685, 0xeb => 0x96e8, 0xec => 0x96e9, + 0xed => 0x52d6, 0xee => 0x5f67, 0xef => 0x65ed, 0xf0 => 0x6631, + 0xf1 => 0x682f, 0xf2 => 0x715c, 0xf3 => 0x7a36, 0xf4 => 0x90c1, + 0xf5 => 0x980a, 0xf6 => 0x4e91, 0xf7 => 0xf9c5, 0xf8 => 0x6a52, + 0xf9 => 0x6b9e, 0xfa => 0x6f90, 0xfb => 0x7189, 0xfc => 0x8018, + 0xfd => 0x82b8, 0xfe => 0x8553, + }, + 0xea => { + 0xa1 => 0x904b, 0xa2 => 0x9695, 0xa3 => 0x96f2, 0xa4 => 0x97fb, + 0xa5 => 0x851a, 0xa6 => 0x9b31, 0xa7 => 0x4e90, 0xa8 => 0x718a, + 0xa9 => 0x96c4, 0xaa => 0x5143, 0xab => 0x539f, 0xac => 0x54e1, + 0xad => 0x5713, 0xae => 0x5712, 0xaf => 0x57a3, 0xb0 => 0x5a9b, + 0xb1 => 0x5ac4, 0xb2 => 0x5bc3, 0xb3 => 0x6028, 0xb4 => 0x613f, + 0xb5 => 0x63f4, 0xb6 => 0x6c85, 0xb7 => 0x6d39, 0xb8 => 0x6e72, + 0xb9 => 0x6e90, 0xba => 0x7230, 0xbb => 0x733f, 0xbc => 0x7457, + 0xbd => 0x82d1, 0xbe => 0x8881, 0xbf => 0x8f45, 0xc0 => 0x9060, + 0xc1 => 0xf9c6, 0xc2 => 0x9662, 0xc3 => 0x9858, 0xc4 => 0x9d1b, + 0xc5 => 0x6708, 0xc6 => 0x8d8a, 0xc7 => 0x925e, 0xc8 => 0x4f4d, + 0xc9 => 0x5049, 0xca => 0x50de, 0xcb => 0x5371, 0xcc => 0x570d, + 0xcd => 0x59d4, 0xce => 0x5a01, 0xcf => 0x5c09, 0xd0 => 0x6170, + 0xd1 => 0x6690, 0xd2 => 0x6e2d, 0xd3 => 0x7232, 0xd4 => 0x744b, + 0xd5 => 0x7def, 0xd6 => 0x80c3, 0xd7 => 0x840e, 0xd8 => 0x8466, + 0xd9 => 0x853f, 0xda => 0x875f, 0xdb => 0x885b, 0xdc => 0x8918, + 0xdd => 0x8b02, 0xde => 0x9055, 0xdf => 0x97cb, 0xe0 => 0x9b4f, + 0xe1 => 0x4e73, 0xe2 => 0x4f91, 0xe3 => 0x5112, 0xe4 => 0x516a, + 0xe5 => 0xf9c7, 0xe6 => 0x552f, 0xe7 => 0x55a9, 0xe8 => 0x5b7a, + 0xe9 => 0x5ba5, 0xea => 0x5e7c, 0xeb => 0x5e7d, 0xec => 0x5ebe, + 0xed => 0x60a0, 0xee => 0x60df, 0xef => 0x6108, 0xf0 => 0x6109, + 0xf1 => 0x63c4, 0xf2 => 0x6538, 0xf3 => 0x6709, 0xf4 => 0xf9c8, + 0xf5 => 0x67d4, 0xf6 => 0x67da, 0xf7 => 0xf9c9, 0xf8 => 0x6961, + 0xf9 => 0x6962, 0xfa => 0x6cb9, 0xfb => 0x6d27, 0xfc => 0xf9ca, + 0xfd => 0x6e38, 0xfe => 0xf9cb, + }, + 0xeb => { + 0xa1 => 0x6fe1, 0xa2 => 0x7336, 0xa3 => 0x7337, 0xa4 => 0xf9cc, + 0xa5 => 0x745c, 0xa6 => 0x7531, 0xa7 => 0xf9cd, 0xa8 => 0x7652, + 0xa9 => 0xf9ce, 0xaa => 0xf9cf, 0xab => 0x7dad, 0xac => 0x81fe, + 0xad => 0x8438, 0xae => 0x88d5, 0xaf => 0x8a98, 0xb0 => 0x8adb, + 0xb1 => 0x8aed, 0xb2 => 0x8e30, 0xb3 => 0x8e42, 0xb4 => 0x904a, + 0xb5 => 0x903e, 0xb6 => 0x907a, 0xb7 => 0x9149, 0xb8 => 0x91c9, + 0xb9 => 0x936e, 0xba => 0xf9d0, 0xbb => 0xf9d1, 0xbc => 0x5809, + 0xbd => 0xf9d2, 0xbe => 0x6bd3, 0xbf => 0x8089, 0xc0 => 0x80b2, + 0xc1 => 0xf9d3, 0xc2 => 0xf9d4, 0xc3 => 0x5141, 0xc4 => 0x596b, + 0xc5 => 0x5c39, 0xc6 => 0xf9d5, 0xc7 => 0xf9d6, 0xc8 => 0x6f64, + 0xc9 => 0x73a7, 0xca => 0x80e4, 0xcb => 0x8d07, 0xcc => 0xf9d7, + 0xcd => 0x9217, 0xce => 0x958f, 0xcf => 0xf9d8, 0xd0 => 0xf9d9, + 0xd1 => 0xf9da, 0xd2 => 0xf9db, 0xd3 => 0x807f, 0xd4 => 0x620e, + 0xd5 => 0x701c, 0xd6 => 0x7d68, 0xd7 => 0x878d, 0xd8 => 0xf9dc, + 0xd9 => 0x57a0, 0xda => 0x6069, 0xdb => 0x6147, 0xdc => 0x6bb7, + 0xdd => 0x8abe, 0xde => 0x9280, 0xdf => 0x96b1, 0xe0 => 0x4e59, + 0xe1 => 0x541f, 0xe2 => 0x6deb, 0xe3 => 0x852d, 0xe4 => 0x9670, + 0xe5 => 0x97f3, 0xe6 => 0x98ee, 0xe7 => 0x63d6, 0xe8 => 0x6ce3, + 0xe9 => 0x9091, 0xea => 0x51dd, 0xeb => 0x61c9, 0xec => 0x81ba, + 0xed => 0x9df9, 0xee => 0x4f9d, 0xef => 0x501a, 0xf0 => 0x5100, + 0xf1 => 0x5b9c, 0xf2 => 0x610f, 0xf3 => 0x61ff, 0xf4 => 0x64ec, + 0xf5 => 0x6905, 0xf6 => 0x6bc5, 0xf7 => 0x7591, 0xf8 => 0x77e3, + 0xf9 => 0x7fa9, 0xfa => 0x8264, 0xfb => 0x858f, 0xfc => 0x87fb, + 0xfd => 0x8863, 0xfe => 0x8abc, + }, + 0xec => { + 0xa1 => 0x8b70, 0xa2 => 0x91ab, 0xa3 => 0x4e8c, 0xa4 => 0x4ee5, + 0xa5 => 0x4f0a, 0xa6 => 0xf9dd, 0xa7 => 0xf9de, 0xa8 => 0x5937, + 0xa9 => 0x59e8, 0xaa => 0xf9df, 0xab => 0x5df2, 0xac => 0x5f1b, + 0xad => 0x5f5b, 0xae => 0x6021, 0xaf => 0xf9e0, 0xb0 => 0xf9e1, + 0xb1 => 0xf9e2, 0xb2 => 0xf9e3, 0xb3 => 0x723e, 0xb4 => 0x73e5, + 0xb5 => 0xf9e4, 0xb6 => 0x7570, 0xb7 => 0x75cd, 0xb8 => 0xf9e5, + 0xb9 => 0x79fb, 0xba => 0xf9e6, 0xbb => 0x800c, 0xbc => 0x8033, + 0xbd => 0x8084, 0xbe => 0x82e1, 0xbf => 0x8351, 0xc0 => 0xf9e7, + 0xc1 => 0xf9e8, 0xc2 => 0x8cbd, 0xc3 => 0x8cb3, 0xc4 => 0x9087, + 0xc5 => 0xf9e9, 0xc6 => 0xf9ea, 0xc7 => 0x98f4, 0xc8 => 0x990c, + 0xc9 => 0xf9eb, 0xca => 0xf9ec, 0xcb => 0x7037, 0xcc => 0x76ca, + 0xcd => 0x7fca, 0xce => 0x7fcc, 0xcf => 0x7ffc, 0xd0 => 0x8b1a, + 0xd1 => 0x4eba, 0xd2 => 0x4ec1, 0xd3 => 0x5203, 0xd4 => 0x5370, + 0xd5 => 0xf9ed, 0xd6 => 0x54bd, 0xd7 => 0x56e0, 0xd8 => 0x59fb, + 0xd9 => 0x5bc5, 0xda => 0x5f15, 0xdb => 0x5fcd, 0xdc => 0x6e6e, + 0xdd => 0xf9ee, 0xde => 0xf9ef, 0xdf => 0x7d6a, 0xe0 => 0x8335, + 0xe1 => 0xf9f0, 0xe2 => 0x8693, 0xe3 => 0x8a8d, 0xe4 => 0xf9f1, + 0xe5 => 0x976d, 0xe6 => 0x9777, 0xe7 => 0xf9f2, 0xe8 => 0xf9f3, + 0xe9 => 0x4e00, 0xea => 0x4f5a, 0xeb => 0x4f7e, 0xec => 0x58f9, + 0xed => 0x65e5, 0xee => 0x6ea2, 0xef => 0x9038, 0xf0 => 0x93b0, + 0xf1 => 0x99b9, 0xf2 => 0x4efb, 0xf3 => 0x58ec, 0xf4 => 0x598a, + 0xf5 => 0x59d9, 0xf6 => 0x6041, 0xf7 => 0xf9f4, 0xf8 => 0xf9f5, + 0xf9 => 0x7a14, 0xfa => 0xf9f6, 0xfb => 0x834f, 0xfc => 0x8cc3, + 0xfd => 0x5165, 0xfe => 0x5344, + }, + 0xed => { + 0xa1 => 0xf9f7, 0xa2 => 0xf9f8, 0xa3 => 0xf9f9, 0xa4 => 0x4ecd, + 0xa5 => 0x5269, 0xa6 => 0x5b55, 0xa7 => 0x82bf, 0xa8 => 0x4ed4, + 0xa9 => 0x523a, 0xaa => 0x54a8, 0xab => 0x59c9, 0xac => 0x59ff, + 0xad => 0x5b50, 0xae => 0x5b57, 0xaf => 0x5b5c, 0xb0 => 0x6063, + 0xb1 => 0x6148, 0xb2 => 0x6ecb, 0xb3 => 0x7099, 0xb4 => 0x716e, + 0xb5 => 0x7386, 0xb6 => 0x74f7, 0xb7 => 0x75b5, 0xb8 => 0x78c1, + 0xb9 => 0x7d2b, 0xba => 0x8005, 0xbb => 0x81ea, 0xbc => 0x8328, + 0xbd => 0x8517, 0xbe => 0x85c9, 0xbf => 0x8aee, 0xc0 => 0x8cc7, + 0xc1 => 0x96cc, 0xc2 => 0x4f5c, 0xc3 => 0x52fa, 0xc4 => 0x56bc, + 0xc5 => 0x65ab, 0xc6 => 0x6628, 0xc7 => 0x707c, 0xc8 => 0x70b8, + 0xc9 => 0x7235, 0xca => 0x7dbd, 0xcb => 0x828d, 0xcc => 0x914c, + 0xcd => 0x96c0, 0xce => 0x9d72, 0xcf => 0x5b71, 0xd0 => 0x68e7, + 0xd1 => 0x6b98, 0xd2 => 0x6f7a, 0xd3 => 0x76de, 0xd4 => 0x5c91, + 0xd5 => 0x66ab, 0xd6 => 0x6f5b, 0xd7 => 0x7bb4, 0xd8 => 0x7c2a, + 0xd9 => 0x8836, 0xda => 0x96dc, 0xdb => 0x4e08, 0xdc => 0x4ed7, + 0xdd => 0x5320, 0xde => 0x5834, 0xdf => 0x58bb, 0xe0 => 0x58ef, + 0xe1 => 0x596c, 0xe2 => 0x5c07, 0xe3 => 0x5e33, 0xe4 => 0x5e84, + 0xe5 => 0x5f35, 0xe6 => 0x638c, 0xe7 => 0x66b2, 0xe8 => 0x6756, + 0xe9 => 0x6a1f, 0xea => 0x6aa3, 0xeb => 0x6b0c, 0xec => 0x6f3f, + 0xed => 0x7246, 0xee => 0xf9fa, 0xef => 0x7350, 0xf0 => 0x748b, + 0xf1 => 0x7ae0, 0xf2 => 0x7ca7, 0xf3 => 0x8178, 0xf4 => 0x81df, + 0xf5 => 0x81e7, 0xf6 => 0x838a, 0xf7 => 0x846c, 0xf8 => 0x8523, + 0xf9 => 0x8594, 0xfa => 0x85cf, 0xfb => 0x88dd, 0xfc => 0x8d13, + 0xfd => 0x91ac, 0xfe => 0x9577, + }, + 0xee => { + 0xa1 => 0x969c, 0xa2 => 0x518d, 0xa3 => 0x54c9, 0xa4 => 0x5728, + 0xa5 => 0x5bb0, 0xa6 => 0x624d, 0xa7 => 0x6750, 0xa8 => 0x683d, + 0xa9 => 0x6893, 0xaa => 0x6e3d, 0xab => 0x6ed3, 0xac => 0x707d, + 0xad => 0x7e21, 0xae => 0x88c1, 0xaf => 0x8ca1, 0xb0 => 0x8f09, + 0xb1 => 0x9f4b, 0xb2 => 0x9f4e, 0xb3 => 0x722d, 0xb4 => 0x7b8f, + 0xb5 => 0x8acd, 0xb6 => 0x931a, 0xb7 => 0x4f47, 0xb8 => 0x4f4e, + 0xb9 => 0x5132, 0xba => 0x5480, 0xbb => 0x59d0, 0xbc => 0x5e95, + 0xbd => 0x62b5, 0xbe => 0x6775, 0xbf => 0x696e, 0xc0 => 0x6a17, + 0xc1 => 0x6cae, 0xc2 => 0x6e1a, 0xc3 => 0x72d9, 0xc4 => 0x732a, + 0xc5 => 0x75bd, 0xc6 => 0x7bb8, 0xc7 => 0x7d35, 0xc8 => 0x82e7, + 0xc9 => 0x83f9, 0xca => 0x8457, 0xcb => 0x85f7, 0xcc => 0x8a5b, + 0xcd => 0x8caf, 0xce => 0x8e87, 0xcf => 0x9019, 0xd0 => 0x90b8, + 0xd1 => 0x96ce, 0xd2 => 0x9f5f, 0xd3 => 0x52e3, 0xd4 => 0x540a, + 0xd5 => 0x5ae1, 0xd6 => 0x5bc2, 0xd7 => 0x6458, 0xd8 => 0x6575, + 0xd9 => 0x6ef4, 0xda => 0x72c4, 0xdb => 0xf9fb, 0xdc => 0x7684, + 0xdd => 0x7a4d, 0xde => 0x7b1b, 0xdf => 0x7c4d, 0xe0 => 0x7e3e, + 0xe1 => 0x7fdf, 0xe2 => 0x837b, 0xe3 => 0x8b2b, 0xe4 => 0x8cca, + 0xe5 => 0x8d64, 0xe6 => 0x8de1, 0xe7 => 0x8e5f, 0xe8 => 0x8fea, + 0xe9 => 0x8ff9, 0xea => 0x9069, 0xeb => 0x93d1, 0xec => 0x4f43, + 0xed => 0x4f7a, 0xee => 0x50b3, 0xef => 0x5168, 0xf0 => 0x5178, + 0xf1 => 0x524d, 0xf2 => 0x526a, 0xf3 => 0x5861, 0xf4 => 0x587c, + 0xf5 => 0x5960, 0xf6 => 0x5c08, 0xf7 => 0x5c55, 0xf8 => 0x5edb, + 0xf9 => 0x609b, 0xfa => 0x6230, 0xfb => 0x6813, 0xfc => 0x6bbf, + 0xfd => 0x6c08, 0xfe => 0x6fb1, + }, + 0xef => { + 0xa1 => 0x714e, 0xa2 => 0x7420, 0xa3 => 0x7530, 0xa4 => 0x7538, + 0xa5 => 0x7551, 0xa6 => 0x7672, 0xa7 => 0x7b4c, 0xa8 => 0x7b8b, + 0xa9 => 0x7bad, 0xaa => 0x7bc6, 0xab => 0x7e8f, 0xac => 0x8a6e, + 0xad => 0x8f3e, 0xae => 0x8f49, 0xaf => 0x923f, 0xb0 => 0x9293, + 0xb1 => 0x9322, 0xb2 => 0x942b, 0xb3 => 0x96fb, 0xb4 => 0x985a, + 0xb5 => 0x986b, 0xb6 => 0x991e, 0xb7 => 0x5207, 0xb8 => 0x622a, + 0xb9 => 0x6298, 0xba => 0x6d59, 0xbb => 0x7664, 0xbc => 0x7aca, + 0xbd => 0x7bc0, 0xbe => 0x7d76, 0xbf => 0x5360, 0xc0 => 0x5cbe, + 0xc1 => 0x5e97, 0xc2 => 0x6f38, 0xc3 => 0x70b9, 0xc4 => 0x7c98, + 0xc5 => 0x9711, 0xc6 => 0x9b8e, 0xc7 => 0x9ede, 0xc8 => 0x63a5, + 0xc9 => 0x647a, 0xca => 0x8776, 0xcb => 0x4e01, 0xcc => 0x4e95, + 0xcd => 0x4ead, 0xce => 0x505c, 0xcf => 0x5075, 0xd0 => 0x5448, + 0xd1 => 0x59c3, 0xd2 => 0x5b9a, 0xd3 => 0x5e40, 0xd4 => 0x5ead, + 0xd5 => 0x5ef7, 0xd6 => 0x5f81, 0xd7 => 0x60c5, 0xd8 => 0x633a, + 0xd9 => 0x653f, 0xda => 0x6574, 0xdb => 0x65cc, 0xdc => 0x6676, + 0xdd => 0x6678, 0xde => 0x67fe, 0xdf => 0x6968, 0xe0 => 0x6a89, + 0xe1 => 0x6b63, 0xe2 => 0x6c40, 0xe3 => 0x6dc0, 0xe4 => 0x6de8, + 0xe5 => 0x6e1f, 0xe6 => 0x6e5e, 0xe7 => 0x701e, 0xe8 => 0x70a1, + 0xe9 => 0x738e, 0xea => 0x73fd, 0xeb => 0x753a, 0xec => 0x775b, + 0xed => 0x7887, 0xee => 0x798e, 0xef => 0x7a0b, 0xf0 => 0x7a7d, + 0xf1 => 0x7cbe, 0xf2 => 0x7d8e, 0xf3 => 0x8247, 0xf4 => 0x8a02, + 0xf5 => 0x8aea, 0xf6 => 0x8c9e, 0xf7 => 0x912d, 0xf8 => 0x914a, + 0xf9 => 0x91d8, 0xfa => 0x9266, 0xfb => 0x92cc, 0xfc => 0x9320, + 0xfd => 0x9706, 0xfe => 0x9756, + }, + 0xf0 => { + 0xa1 => 0x975c, 0xa2 => 0x9802, 0xa3 => 0x9f0e, 0xa4 => 0x5236, + 0xa5 => 0x5291, 0xa6 => 0x557c, 0xa7 => 0x5824, 0xa8 => 0x5e1d, + 0xa9 => 0x5f1f, 0xaa => 0x608c, 0xab => 0x63d0, 0xac => 0x68af, + 0xad => 0x6fdf, 0xae => 0x796d, 0xaf => 0x7b2c, 0xb0 => 0x81cd, + 0xb1 => 0x85ba, 0xb2 => 0x88fd, 0xb3 => 0x8af8, 0xb4 => 0x8e44, + 0xb5 => 0x918d, 0xb6 => 0x9664, 0xb7 => 0x969b, 0xb8 => 0x973d, + 0xb9 => 0x984c, 0xba => 0x9f4a, 0xbb => 0x4fce, 0xbc => 0x5146, + 0xbd => 0x51cb, 0xbe => 0x52a9, 0xbf => 0x5632, 0xc0 => 0x5f14, + 0xc1 => 0x5f6b, 0xc2 => 0x63aa, 0xc3 => 0x64cd, 0xc4 => 0x65e9, + 0xc5 => 0x6641, 0xc6 => 0x66fa, 0xc7 => 0x66f9, 0xc8 => 0x671d, + 0xc9 => 0x689d, 0xca => 0x68d7, 0xcb => 0x69fd, 0xcc => 0x6f15, + 0xcd => 0x6f6e, 0xce => 0x7167, 0xcf => 0x71e5, 0xd0 => 0x722a, + 0xd1 => 0x74aa, 0xd2 => 0x773a, 0xd3 => 0x7956, 0xd4 => 0x795a, + 0xd5 => 0x79df, 0xd6 => 0x7a20, 0xd7 => 0x7a95, 0xd8 => 0x7c97, + 0xd9 => 0x7cdf, 0xda => 0x7d44, 0xdb => 0x7e70, 0xdc => 0x8087, + 0xdd => 0x85fb, 0xde => 0x86a4, 0xdf => 0x8a54, 0xe0 => 0x8abf, + 0xe1 => 0x8d99, 0xe2 => 0x8e81, 0xe3 => 0x9020, 0xe4 => 0x906d, + 0xe5 => 0x91e3, 0xe6 => 0x963b, 0xe7 => 0x96d5, 0xe8 => 0x9ce5, + 0xe9 => 0x65cf, 0xea => 0x7c07, 0xeb => 0x8db3, 0xec => 0x93c3, + 0xed => 0x5b58, 0xee => 0x5c0a, 0xef => 0x5352, 0xf0 => 0x62d9, + 0xf1 => 0x731d, 0xf2 => 0x5027, 0xf3 => 0x5b97, 0xf4 => 0x5f9e, + 0xf5 => 0x60b0, 0xf6 => 0x616b, 0xf7 => 0x68d5, 0xf8 => 0x6dd9, + 0xf9 => 0x742e, 0xfa => 0x7a2e, 0xfb => 0x7d42, 0xfc => 0x7d9c, + 0xfd => 0x7e31, 0xfe => 0x816b, + }, + 0xf1 => { + 0xa1 => 0x8e2a, 0xa2 => 0x8e35, 0xa3 => 0x937e, 0xa4 => 0x9418, + 0xa5 => 0x4f50, 0xa6 => 0x5750, 0xa7 => 0x5de6, 0xa8 => 0x5ea7, + 0xa9 => 0x632b, 0xaa => 0x7f6a, 0xab => 0x4e3b, 0xac => 0x4f4f, + 0xad => 0x4f8f, 0xae => 0x505a, 0xaf => 0x59dd, 0xb0 => 0x80c4, + 0xb1 => 0x546a, 0xb2 => 0x5468, 0xb3 => 0x55fe, 0xb4 => 0x594f, + 0xb5 => 0x5b99, 0xb6 => 0x5dde, 0xb7 => 0x5eda, 0xb8 => 0x665d, + 0xb9 => 0x6731, 0xba => 0x67f1, 0xbb => 0x682a, 0xbc => 0x6ce8, + 0xbd => 0x6d32, 0xbe => 0x6e4a, 0xbf => 0x6f8d, 0xc0 => 0x70b7, + 0xc1 => 0x73e0, 0xc2 => 0x7587, 0xc3 => 0x7c4c, 0xc4 => 0x7d02, + 0xc5 => 0x7d2c, 0xc6 => 0x7da2, 0xc7 => 0x821f, 0xc8 => 0x86db, + 0xc9 => 0x8a3b, 0xca => 0x8a85, 0xcb => 0x8d70, 0xcc => 0x8e8a, + 0xcd => 0x8f33, 0xce => 0x9031, 0xcf => 0x914e, 0xd0 => 0x9152, + 0xd1 => 0x9444, 0xd2 => 0x99d0, 0xd3 => 0x7af9, 0xd4 => 0x7ca5, + 0xd5 => 0x4fca, 0xd6 => 0x5101, 0xd7 => 0x51c6, 0xd8 => 0x57c8, + 0xd9 => 0x5bef, 0xda => 0x5cfb, 0xdb => 0x6659, 0xdc => 0x6a3d, + 0xdd => 0x6d5a, 0xde => 0x6e96, 0xdf => 0x6fec, 0xe0 => 0x710c, + 0xe1 => 0x756f, 0xe2 => 0x7ae3, 0xe3 => 0x8822, 0xe4 => 0x9021, + 0xe5 => 0x9075, 0xe6 => 0x96cb, 0xe7 => 0x99ff, 0xe8 => 0x8301, + 0xe9 => 0x4e2d, 0xea => 0x4ef2, 0xeb => 0x8846, 0xec => 0x91cd, + 0xed => 0x537d, 0xee => 0x6adb, 0xef => 0x696b, 0xf0 => 0x6c41, + 0xf1 => 0x847a, 0xf2 => 0x589e, 0xf3 => 0x618e, 0xf4 => 0x66fe, + 0xf5 => 0x62ef, 0xf6 => 0x70dd, 0xf7 => 0x7511, 0xf8 => 0x75c7, + 0xf9 => 0x7e52, 0xfa => 0x84b8, 0xfb => 0x8b49, 0xfc => 0x8d08, + 0xfd => 0x4e4b, 0xfe => 0x53ea, + }, + 0xf2 => { + 0xa1 => 0x54ab, 0xa2 => 0x5730, 0xa3 => 0x5740, 0xa4 => 0x5fd7, + 0xa5 => 0x6301, 0xa6 => 0x6307, 0xa7 => 0x646f, 0xa8 => 0x652f, + 0xa9 => 0x65e8, 0xaa => 0x667a, 0xab => 0x679d, 0xac => 0x67b3, + 0xad => 0x6b62, 0xae => 0x6c60, 0xaf => 0x6c9a, 0xb0 => 0x6f2c, + 0xb1 => 0x77e5, 0xb2 => 0x7825, 0xb3 => 0x7949, 0xb4 => 0x7957, + 0xb5 => 0x7d19, 0xb6 => 0x80a2, 0xb7 => 0x8102, 0xb8 => 0x81f3, + 0xb9 => 0x829d, 0xba => 0x82b7, 0xbb => 0x8718, 0xbc => 0x8a8c, + 0xbd => 0xf9fc, 0xbe => 0x8d04, 0xbf => 0x8dbe, 0xc0 => 0x9072, + 0xc1 => 0x76f4, 0xc2 => 0x7a19, 0xc3 => 0x7a37, 0xc4 => 0x7e54, + 0xc5 => 0x8077, 0xc6 => 0x5507, 0xc7 => 0x55d4, 0xc8 => 0x5875, + 0xc9 => 0x632f, 0xca => 0x6422, 0xcb => 0x6649, 0xcc => 0x664b, + 0xcd => 0x686d, 0xce => 0x699b, 0xcf => 0x6b84, 0xd0 => 0x6d25, + 0xd1 => 0x6eb1, 0xd2 => 0x73cd, 0xd3 => 0x7468, 0xd4 => 0x74a1, + 0xd5 => 0x755b, 0xd6 => 0x75b9, 0xd7 => 0x76e1, 0xd8 => 0x771e, + 0xd9 => 0x778b, 0xda => 0x79e6, 0xdb => 0x7e09, 0xdc => 0x7e1d, + 0xdd => 0x81fb, 0xde => 0x852f, 0xdf => 0x8897, 0xe0 => 0x8a3a, + 0xe1 => 0x8cd1, 0xe2 => 0x8eeb, 0xe3 => 0x8fb0, 0xe4 => 0x9032, + 0xe5 => 0x93ad, 0xe6 => 0x9663, 0xe7 => 0x9673, 0xe8 => 0x9707, + 0xe9 => 0x4f84, 0xea => 0x53f1, 0xeb => 0x59ea, 0xec => 0x5ac9, + 0xed => 0x5e19, 0xee => 0x684e, 0xef => 0x74c6, 0xf0 => 0x75be, + 0xf1 => 0x79e9, 0xf2 => 0x7a92, 0xf3 => 0x81a3, 0xf4 => 0x86ed, + 0xf5 => 0x8cea, 0xf6 => 0x8dcc, 0xf7 => 0x8fed, 0xf8 => 0x659f, + 0xf9 => 0x6715, 0xfa => 0xf9fd, 0xfb => 0x57f7, 0xfc => 0x6f57, + 0xfd => 0x7ddd, 0xfe => 0x8f2f, + }, + 0xf3 => { + 0xa1 => 0x93f6, 0xa2 => 0x96c6, 0xa3 => 0x5fb5, 0xa4 => 0x61f2, + 0xa5 => 0x6f84, 0xa6 => 0x4e14, 0xa7 => 0x4f98, 0xa8 => 0x501f, + 0xa9 => 0x53c9, 0xaa => 0x55df, 0xab => 0x5d6f, 0xac => 0x5dee, + 0xad => 0x6b21, 0xae => 0x6b64, 0xaf => 0x78cb, 0xb0 => 0x7b9a, + 0xb1 => 0xf9fe, 0xb2 => 0x8e49, 0xb3 => 0x8eca, 0xb4 => 0x906e, + 0xb5 => 0x6349, 0xb6 => 0x643e, 0xb7 => 0x7740, 0xb8 => 0x7a84, + 0xb9 => 0x932f, 0xba => 0x947f, 0xbb => 0x9f6a, 0xbc => 0x64b0, + 0xbd => 0x6faf, 0xbe => 0x71e6, 0xbf => 0x74a8, 0xc0 => 0x74da, + 0xc1 => 0x7ac4, 0xc2 => 0x7c12, 0xc3 => 0x7e82, 0xc4 => 0x7cb2, + 0xc5 => 0x7e98, 0xc6 => 0x8b9a, 0xc7 => 0x8d0a, 0xc8 => 0x947d, + 0xc9 => 0x9910, 0xca => 0x994c, 0xcb => 0x5239, 0xcc => 0x5bdf, + 0xcd => 0x64e6, 0xce => 0x672d, 0xcf => 0x7d2e, 0xd0 => 0x50ed, + 0xd1 => 0x53c3, 0xd2 => 0x5879, 0xd3 => 0x6158, 0xd4 => 0x6159, + 0xd5 => 0x61fa, 0xd6 => 0x65ac, 0xd7 => 0x7ad9, 0xd8 => 0x8b92, + 0xd9 => 0x8b96, 0xda => 0x5009, 0xdb => 0x5021, 0xdc => 0x5275, + 0xdd => 0x5531, 0xde => 0x5a3c, 0xdf => 0x5ee0, 0xe0 => 0x5f70, + 0xe1 => 0x6134, 0xe2 => 0x655e, 0xe3 => 0x660c, 0xe4 => 0x6636, + 0xe5 => 0x66a2, 0xe6 => 0x69cd, 0xe7 => 0x6ec4, 0xe8 => 0x6f32, + 0xe9 => 0x7316, 0xea => 0x7621, 0xeb => 0x7a93, 0xec => 0x8139, + 0xed => 0x8259, 0xee => 0x83d6, 0xef => 0x84bc, 0xf0 => 0x50b5, + 0xf1 => 0x57f0, 0xf2 => 0x5bc0, 0xf3 => 0x5be8, 0xf4 => 0x5f69, + 0xf5 => 0x63a1, 0xf6 => 0x7826, 0xf7 => 0x7db5, 0xf8 => 0x83dc, + 0xf9 => 0x8521, 0xfa => 0x91c7, 0xfb => 0x91f5, 0xfc => 0x518a, + 0xfd => 0x67f5, 0xfe => 0x7b56, + }, + 0xf4 => { + 0xa1 => 0x8cac, 0xa2 => 0x51c4, 0xa3 => 0x59bb, 0xa4 => 0x60bd, + 0xa5 => 0x8655, 0xa6 => 0x501c, 0xa7 => 0xf9ff, 0xa8 => 0x5254, + 0xa9 => 0x5c3a, 0xaa => 0x617d, 0xab => 0x621a, 0xac => 0x62d3, + 0xad => 0x64f2, 0xae => 0x65a5, 0xaf => 0x6ecc, 0xb0 => 0x7620, + 0xb1 => 0x810a, 0xb2 => 0x8e60, 0xb3 => 0x965f, 0xb4 => 0x96bb, + 0xb5 => 0x4edf, 0xb6 => 0x5343, 0xb7 => 0x5598, 0xb8 => 0x5929, + 0xb9 => 0x5ddd, 0xba => 0x64c5, 0xbb => 0x6cc9, 0xbc => 0x6dfa, + 0xbd => 0x7394, 0xbe => 0x7a7f, 0xbf => 0x821b, 0xc0 => 0x85a6, + 0xc1 => 0x8ce4, 0xc2 => 0x8e10, 0xc3 => 0x9077, 0xc4 => 0x91e7, + 0xc5 => 0x95e1, 0xc6 => 0x9621, 0xc7 => 0x97c6, 0xc8 => 0x51f8, + 0xc9 => 0x54f2, 0xca => 0x5586, 0xcb => 0x5fb9, 0xcc => 0x64a4, + 0xcd => 0x6f88, 0xce => 0x7db4, 0xcf => 0x8f1f, 0xd0 => 0x8f4d, + 0xd1 => 0x9435, 0xd2 => 0x50c9, 0xd3 => 0x5c16, 0xd4 => 0x6cbe, + 0xd5 => 0x6dfb, 0xd6 => 0x751b, 0xd7 => 0x77bb, 0xd8 => 0x7c3d, + 0xd9 => 0x7c64, 0xda => 0x8a79, 0xdb => 0x8ac2, 0xdc => 0x581e, + 0xdd => 0x59be, 0xde => 0x5e16, 0xdf => 0x6377, 0xe0 => 0x7252, + 0xe1 => 0x758a, 0xe2 => 0x776b, 0xe3 => 0x8adc, 0xe4 => 0x8cbc, + 0xe5 => 0x8f12, 0xe6 => 0x5ef3, 0xe7 => 0x6674, 0xe8 => 0x6df8, + 0xe9 => 0x807d, 0xea => 0x83c1, 0xeb => 0x8acb, 0xec => 0x9751, + 0xed => 0x9bd6, 0xee => 0xfa00, 0xef => 0x5243, 0xf0 => 0x66ff, + 0xf1 => 0x6d95, 0xf2 => 0x6eef, 0xf3 => 0x7de0, 0xf4 => 0x8ae6, + 0xf5 => 0x902e, 0xf6 => 0x905e, 0xf7 => 0x9ad4, 0xf8 => 0x521d, + 0xf9 => 0x527f, 0xfa => 0x54e8, 0xfb => 0x6194, 0xfc => 0x6284, + 0xfd => 0x62db, 0xfe => 0x68a2, + }, + 0xf5 => { + 0xa1 => 0x6912, 0xa2 => 0x695a, 0xa3 => 0x6a35, 0xa4 => 0x7092, + 0xa5 => 0x7126, 0xa6 => 0x785d, 0xa7 => 0x7901, 0xa8 => 0x790e, + 0xa9 => 0x79d2, 0xaa => 0x7a0d, 0xab => 0x8096, 0xac => 0x8278, + 0xad => 0x82d5, 0xae => 0x8349, 0xaf => 0x8549, 0xb0 => 0x8c82, + 0xb1 => 0x8d85, 0xb2 => 0x9162, 0xb3 => 0x918b, 0xb4 => 0x91ae, + 0xb5 => 0x4fc3, 0xb6 => 0x56d1, 0xb7 => 0x71ed, 0xb8 => 0x77d7, + 0xb9 => 0x8700, 0xba => 0x89f8, 0xbb => 0x5bf8, 0xbc => 0x5fd6, + 0xbd => 0x6751, 0xbe => 0x90a8, 0xbf => 0x53e2, 0xc0 => 0x585a, + 0xc1 => 0x5bf5, 0xc2 => 0x60a4, 0xc3 => 0x6181, 0xc4 => 0x6460, + 0xc5 => 0x7e3d, 0xc6 => 0x8070, 0xc7 => 0x8525, 0xc8 => 0x9283, + 0xc9 => 0x64ae, 0xca => 0x50ac, 0xcb => 0x5d14, 0xcc => 0x6700, + 0xcd => 0x589c, 0xce => 0x62bd, 0xcf => 0x63a8, 0xd0 => 0x690e, + 0xd1 => 0x6978, 0xd2 => 0x6a1e, 0xd3 => 0x6e6b, 0xd4 => 0x76ba, + 0xd5 => 0x79cb, 0xd6 => 0x82bb, 0xd7 => 0x8429, 0xd8 => 0x8acf, + 0xd9 => 0x8da8, 0xda => 0x8ffd, 0xdb => 0x9112, 0xdc => 0x914b, + 0xdd => 0x919c, 0xde => 0x9310, 0xdf => 0x9318, 0xe0 => 0x939a, + 0xe1 => 0x96db, 0xe2 => 0x9a36, 0xe3 => 0x9c0d, 0xe4 => 0x4e11, + 0xe5 => 0x755c, 0xe6 => 0x795d, 0xe7 => 0x7afa, 0xe8 => 0x7b51, + 0xe9 => 0x7bc9, 0xea => 0x7e2e, 0xeb => 0x84c4, 0xec => 0x8e59, + 0xed => 0x8e74, 0xee => 0x8ef8, 0xef => 0x9010, 0xf0 => 0x6625, + 0xf1 => 0x693f, 0xf2 => 0x7443, 0xf3 => 0x51fa, 0xf4 => 0x672e, + 0xf5 => 0x9edc, 0xf6 => 0x5145, 0xf7 => 0x5fe0, 0xf8 => 0x6c96, + 0xf9 => 0x87f2, 0xfa => 0x885d, 0xfb => 0x8877, 0xfc => 0x60b4, + 0xfd => 0x81b5, 0xfe => 0x8403, + }, + 0xf6 => { + 0xa1 => 0x8d05, 0xa2 => 0x53d6, 0xa3 => 0x5439, 0xa4 => 0x5634, + 0xa5 => 0x5a36, 0xa6 => 0x5c31, 0xa7 => 0x708a, 0xa8 => 0x7fe0, + 0xa9 => 0x805a, 0xaa => 0x8106, 0xab => 0x81ed, 0xac => 0x8da3, + 0xad => 0x9189, 0xae => 0x9a5f, 0xaf => 0x9df2, 0xb0 => 0x5074, + 0xb1 => 0x4ec4, 0xb2 => 0x53a0, 0xb3 => 0x60fb, 0xb4 => 0x6e2c, + 0xb5 => 0x5c64, 0xb6 => 0x4f88, 0xb7 => 0x5024, 0xb8 => 0x55e4, + 0xb9 => 0x5cd9, 0xba => 0x5e5f, 0xbb => 0x6065, 0xbc => 0x6894, + 0xbd => 0x6cbb, 0xbe => 0x6dc4, 0xbf => 0x71be, 0xc0 => 0x75d4, + 0xc1 => 0x75f4, 0xc2 => 0x7661, 0xc3 => 0x7a1a, 0xc4 => 0x7a49, + 0xc5 => 0x7dc7, 0xc6 => 0x7dfb, 0xc7 => 0x7f6e, 0xc8 => 0x81f4, + 0xc9 => 0x86a9, 0xca => 0x8f1c, 0xcb => 0x96c9, 0xcc => 0x99b3, + 0xcd => 0x9f52, 0xce => 0x5247, 0xcf => 0x52c5, 0xd0 => 0x98ed, + 0xd1 => 0x89aa, 0xd2 => 0x4e03, 0xd3 => 0x67d2, 0xd4 => 0x6f06, + 0xd5 => 0x4fb5, 0xd6 => 0x5be2, 0xd7 => 0x6795, 0xd8 => 0x6c88, + 0xd9 => 0x6d78, 0xda => 0x741b, 0xdb => 0x7827, 0xdc => 0x91dd, + 0xdd => 0x937c, 0xde => 0x87c4, 0xdf => 0x79e4, 0xe0 => 0x7a31, + 0xe1 => 0x5feb, 0xe2 => 0x4ed6, 0xe3 => 0x54a4, 0xe4 => 0x553e, + 0xe5 => 0x58ae, 0xe6 => 0x59a5, 0xe7 => 0x60f0, 0xe8 => 0x6253, + 0xe9 => 0x62d6, 0xea => 0x6736, 0xeb => 0x6955, 0xec => 0x8235, + 0xed => 0x9640, 0xee => 0x99b1, 0xef => 0x99dd, 0xf0 => 0x502c, + 0xf1 => 0x5353, 0xf2 => 0x5544, 0xf3 => 0x577c, 0xf4 => 0xfa01, + 0xf5 => 0x6258, 0xf6 => 0xfa02, 0xf7 => 0x64e2, 0xf8 => 0x666b, + 0xf9 => 0x67dd, 0xfa => 0x6fc1, 0xfb => 0x6fef, 0xfc => 0x7422, + 0xfd => 0x7438, 0xfe => 0x8a17, + }, + 0xf7 => { + 0xa1 => 0x9438, 0xa2 => 0x5451, 0xa3 => 0x5606, 0xa4 => 0x5766, + 0xa5 => 0x5f48, 0xa6 => 0x619a, 0xa7 => 0x6b4e, 0xa8 => 0x7058, + 0xa9 => 0x70ad, 0xaa => 0x7dbb, 0xab => 0x8a95, 0xac => 0x596a, + 0xad => 0x812b, 0xae => 0x63a2, 0xaf => 0x7708, 0xb0 => 0x803d, + 0xb1 => 0x8caa, 0xb2 => 0x5854, 0xb3 => 0x642d, 0xb4 => 0x69bb, + 0xb5 => 0x5b95, 0xb6 => 0x5e11, 0xb7 => 0x6e6f, 0xb8 => 0xfa03, + 0xb9 => 0x8569, 0xba => 0x514c, 0xbb => 0x53f0, 0xbc => 0x592a, + 0xbd => 0x6020, 0xbe => 0x614b, 0xbf => 0x6b86, 0xc0 => 0x6c70, + 0xc1 => 0x6cf0, 0xc2 => 0x7b1e, 0xc3 => 0x80ce, 0xc4 => 0x82d4, + 0xc5 => 0x8dc6, 0xc6 => 0x90b0, 0xc7 => 0x98b1, 0xc8 => 0xfa04, + 0xc9 => 0x64c7, 0xca => 0x6fa4, 0xcb => 0x6491, 0xcc => 0x6504, + 0xcd => 0x514e, 0xce => 0x5410, 0xcf => 0x571f, 0xd0 => 0x8a0e, + 0xd1 => 0x615f, 0xd2 => 0x6876, 0xd3 => 0xfa05, 0xd4 => 0x75db, + 0xd5 => 0x7b52, 0xd6 => 0x7d71, 0xd7 => 0x901a, 0xd8 => 0x5806, + 0xd9 => 0x69cc, 0xda => 0x817f, 0xdb => 0x892a, 0xdc => 0x9000, + 0xdd => 0x9839, 0xde => 0x5078, 0xdf => 0x5957, 0xe0 => 0x59ac, + 0xe1 => 0x6295, 0xe2 => 0x900f, 0xe3 => 0x9b2a, 0xe4 => 0x615d, + 0xe5 => 0x7279, 0xe6 => 0x95d6, 0xe7 => 0x5761, 0xe8 => 0x5a46, + 0xe9 => 0x5df4, 0xea => 0x628a, 0xeb => 0x64ad, 0xec => 0x64fa, + 0xed => 0x6777, 0xee => 0x6ce2, 0xef => 0x6d3e, 0xf0 => 0x722c, + 0xf1 => 0x7436, 0xf2 => 0x7834, 0xf3 => 0x7f77, 0xf4 => 0x82ad, + 0xf5 => 0x8ddb, 0xf6 => 0x9817, 0xf7 => 0x5224, 0xf8 => 0x5742, + 0xf9 => 0x677f, 0xfa => 0x7248, 0xfb => 0x74e3, 0xfc => 0x8ca9, + 0xfd => 0x8fa6, 0xfe => 0x9211, + }, + 0xf8 => { + 0xa1 => 0x962a, 0xa2 => 0x516b, 0xa3 => 0x53ed, 0xa4 => 0x634c, + 0xa5 => 0x4f69, 0xa6 => 0x5504, 0xa7 => 0x6096, 0xa8 => 0x6557, + 0xa9 => 0x6c9b, 0xaa => 0x6d7f, 0xab => 0x724c, 0xac => 0x72fd, + 0xad => 0x7a17, 0xae => 0x8987, 0xaf => 0x8c9d, 0xb0 => 0x5f6d, + 0xb1 => 0x6f8e, 0xb2 => 0x70f9, 0xb3 => 0x81a8, 0xb4 => 0x610e, + 0xb5 => 0x4fbf, 0xb6 => 0x504f, 0xb7 => 0x6241, 0xb8 => 0x7247, + 0xb9 => 0x7bc7, 0xba => 0x7de8, 0xbb => 0x7fe9, 0xbc => 0x904d, + 0xbd => 0x97ad, 0xbe => 0x9a19, 0xbf => 0x8cb6, 0xc0 => 0x576a, + 0xc1 => 0x5e73, 0xc2 => 0x67b0, 0xc3 => 0x840d, 0xc4 => 0x8a55, + 0xc5 => 0x5420, 0xc6 => 0x5b16, 0xc7 => 0x5e63, 0xc8 => 0x5ee2, + 0xc9 => 0x5f0a, 0xca => 0x6583, 0xcb => 0x80ba, 0xcc => 0x853d, + 0xcd => 0x9589, 0xce => 0x965b, 0xcf => 0x4f48, 0xd0 => 0x5305, + 0xd1 => 0x530d, 0xd2 => 0x530f, 0xd3 => 0x5486, 0xd4 => 0x54fa, + 0xd5 => 0x5703, 0xd6 => 0x5e03, 0xd7 => 0x6016, 0xd8 => 0x629b, + 0xd9 => 0x62b1, 0xda => 0x6355, 0xdb => 0xfa06, 0xdc => 0x6ce1, + 0xdd => 0x6d66, 0xde => 0x75b1, 0xdf => 0x7832, 0xe0 => 0x80de, + 0xe1 => 0x812f, 0xe2 => 0x82de, 0xe3 => 0x8461, 0xe4 => 0x84b2, + 0xe5 => 0x888d, 0xe6 => 0x8912, 0xe7 => 0x900b, 0xe8 => 0x92ea, + 0xe9 => 0x98fd, 0xea => 0x9b91, 0xeb => 0x5e45, 0xec => 0x66b4, + 0xed => 0x66dd, 0xee => 0x7011, 0xef => 0x7206, 0xf0 => 0xfa07, + 0xf1 => 0x4ff5, 0xf2 => 0x527d, 0xf3 => 0x5f6a, 0xf4 => 0x6153, + 0xf5 => 0x6753, 0xf6 => 0x6a19, 0xf7 => 0x6f02, 0xf8 => 0x74e2, + 0xf9 => 0x7968, 0xfa => 0x8868, 0xfb => 0x8c79, 0xfc => 0x98c7, + 0xfd => 0x98c4, 0xfe => 0x9a43, + }, + 0xf9 => { + 0xa1 => 0x54c1, 0xa2 => 0x7a1f, 0xa3 => 0x6953, 0xa4 => 0x8af7, + 0xa5 => 0x8c4a, 0xa6 => 0x98a8, 0xa7 => 0x99ae, 0xa8 => 0x5f7c, + 0xa9 => 0x62ab, 0xaa => 0x75b2, 0xab => 0x76ae, 0xac => 0x88ab, + 0xad => 0x907f, 0xae => 0x9642, 0xaf => 0x5339, 0xb0 => 0x5f3c, + 0xb1 => 0x5fc5, 0xb2 => 0x6ccc, 0xb3 => 0x73cc, 0xb4 => 0x7562, + 0xb5 => 0x758b, 0xb6 => 0x7b46, 0xb7 => 0x82fe, 0xb8 => 0x999d, + 0xb9 => 0x4e4f, 0xba => 0x903c, 0xbb => 0x4e0b, 0xbc => 0x4f55, + 0xbd => 0x53a6, 0xbe => 0x590f, 0xbf => 0x5ec8, 0xc0 => 0x6630, + 0xc1 => 0x6cb3, 0xc2 => 0x7455, 0xc3 => 0x8377, 0xc4 => 0x8766, + 0xc5 => 0x8cc0, 0xc6 => 0x9050, 0xc7 => 0x971e, 0xc8 => 0x9c15, + 0xc9 => 0x58d1, 0xca => 0x5b78, 0xcb => 0x8650, 0xcc => 0x8b14, + 0xcd => 0x9db4, 0xce => 0x5bd2, 0xcf => 0x6068, 0xd0 => 0x608d, + 0xd1 => 0x65f1, 0xd2 => 0x6c57, 0xd3 => 0x6f22, 0xd4 => 0x6fa3, + 0xd5 => 0x701a, 0xd6 => 0x7f55, 0xd7 => 0x7ff0, 0xd8 => 0x9591, + 0xd9 => 0x9592, 0xda => 0x9650, 0xdb => 0x97d3, 0xdc => 0x5272, + 0xdd => 0x8f44, 0xde => 0x51fd, 0xdf => 0x542b, 0xe0 => 0x54b8, + 0xe1 => 0x5563, 0xe2 => 0x558a, 0xe3 => 0x6abb, 0xe4 => 0x6db5, + 0xe5 => 0x7dd8, 0xe6 => 0x8266, 0xe7 => 0x929c, 0xe8 => 0x9677, + 0xe9 => 0x9e79, 0xea => 0x5408, 0xeb => 0x54c8, 0xec => 0x76d2, + 0xed => 0x86e4, 0xee => 0x95a4, 0xef => 0x95d4, 0xf0 => 0x965c, + 0xf1 => 0x4ea2, 0xf2 => 0x4f09, 0xf3 => 0x59ee, 0xf4 => 0x5ae6, + 0xf5 => 0x5df7, 0xf6 => 0x6052, 0xf7 => 0x6297, 0xf8 => 0x676d, + 0xf9 => 0x6841, 0xfa => 0x6c86, 0xfb => 0x6e2f, 0xfc => 0x7f38, + 0xfd => 0x809b, 0xfe => 0x822a, + }, + 0xfa => { + 0xa1 => 0xfa08, 0xa2 => 0xfa09, 0xa3 => 0x9805, 0xa4 => 0x4ea5, + 0xa5 => 0x5055, 0xa6 => 0x54b3, 0xa7 => 0x5793, 0xa8 => 0x595a, + 0xa9 => 0x5b69, 0xaa => 0x5bb3, 0xab => 0x61c8, 0xac => 0x6977, + 0xad => 0x6d77, 0xae => 0x7023, 0xaf => 0x87f9, 0xb0 => 0x89e3, + 0xb1 => 0x8a72, 0xb2 => 0x8ae7, 0xb3 => 0x9082, 0xb4 => 0x99ed, + 0xb5 => 0x9ab8, 0xb6 => 0x52be, 0xb7 => 0x6838, 0xb8 => 0x5016, + 0xb9 => 0x5e78, 0xba => 0x674f, 0xbb => 0x8347, 0xbc => 0x884c, + 0xbd => 0x4eab, 0xbe => 0x5411, 0xbf => 0x56ae, 0xc0 => 0x73e6, + 0xc1 => 0x9115, 0xc2 => 0x97ff, 0xc3 => 0x9909, 0xc4 => 0x9957, + 0xc5 => 0x9999, 0xc6 => 0x5653, 0xc7 => 0x589f, 0xc8 => 0x865b, + 0xc9 => 0x8a31, 0xca => 0x61b2, 0xcb => 0x6af6, 0xcc => 0x737b, + 0xcd => 0x8ed2, 0xce => 0x6b47, 0xcf => 0x96aa, 0xd0 => 0x9a57, + 0xd1 => 0x5955, 0xd2 => 0x7200, 0xd3 => 0x8d6b, 0xd4 => 0x9769, + 0xd5 => 0x4fd4, 0xd6 => 0x5cf4, 0xd7 => 0x5f26, 0xd8 => 0x61f8, + 0xd9 => 0x665b, 0xda => 0x6ceb, 0xdb => 0x70ab, 0xdc => 0x7384, + 0xdd => 0x73b9, 0xde => 0x73fe, 0xdf => 0x7729, 0xe0 => 0x774d, + 0xe1 => 0x7d43, 0xe2 => 0x7d62, 0xe3 => 0x7e23, 0xe4 => 0x8237, + 0xe5 => 0x8852, 0xe6 => 0xfa0a, 0xe7 => 0x8ce2, 0xe8 => 0x9249, + 0xe9 => 0x986f, 0xea => 0x5b51, 0xeb => 0x7a74, 0xec => 0x8840, + 0xed => 0x9801, 0xee => 0x5acc, 0xef => 0x4fe0, 0xf0 => 0x5354, + 0xf1 => 0x593e, 0xf2 => 0x5cfd, 0xf3 => 0x633e, 0xf4 => 0x6d79, + 0xf5 => 0x72f9, 0xf6 => 0x8105, 0xf7 => 0x8107, 0xf8 => 0x83a2, + 0xf9 => 0x92cf, 0xfa => 0x9830, 0xfb => 0x4ea8, 0xfc => 0x5144, + 0xfd => 0x5211, 0xfe => 0x578b, + }, + 0xfb => { + 0xa1 => 0x5f62, 0xa2 => 0x6cc2, 0xa3 => 0x6ece, 0xa4 => 0x7005, + 0xa5 => 0x7050, 0xa6 => 0x70af, 0xa7 => 0x7192, 0xa8 => 0x73e9, + 0xa9 => 0x7469, 0xaa => 0x834a, 0xab => 0x87a2, 0xac => 0x8861, + 0xad => 0x9008, 0xae => 0x90a2, 0xaf => 0x93a3, 0xb0 => 0x99a8, + 0xb1 => 0x516e, 0xb2 => 0x5f57, 0xb3 => 0x60e0, 0xb4 => 0x6167, + 0xb5 => 0x66b3, 0xb6 => 0x8559, 0xb7 => 0x8e4a, 0xb8 => 0x91af, + 0xb9 => 0x978b, 0xba => 0x4e4e, 0xbb => 0x4e92, 0xbc => 0x547c, + 0xbd => 0x58d5, 0xbe => 0x58fa, 0xbf => 0x597d, 0xc0 => 0x5cb5, + 0xc1 => 0x5f27, 0xc2 => 0x6236, 0xc3 => 0x6248, 0xc4 => 0x660a, + 0xc5 => 0x6667, 0xc6 => 0x6beb, 0xc7 => 0x6d69, 0xc8 => 0x6dcf, + 0xc9 => 0x6e56, 0xca => 0x6ef8, 0xcb => 0x6f94, 0xcc => 0x6fe0, + 0xcd => 0x6fe9, 0xce => 0x705d, 0xcf => 0x72d0, 0xd0 => 0x7425, + 0xd1 => 0x745a, 0xd2 => 0x74e0, 0xd3 => 0x7693, 0xd4 => 0x795c, + 0xd5 => 0x7cca, 0xd6 => 0x7e1e, 0xd7 => 0x80e1, 0xd8 => 0x82a6, + 0xd9 => 0x846b, 0xda => 0x84bf, 0xdb => 0x864e, 0xdc => 0x865f, + 0xdd => 0x8774, 0xde => 0x8b77, 0xdf => 0x8c6a, 0xe0 => 0x93ac, + 0xe1 => 0x9800, 0xe2 => 0x9865, 0xe3 => 0x60d1, 0xe4 => 0x6216, + 0xe5 => 0x9177, 0xe6 => 0x5a5a, 0xe7 => 0x660f, 0xe8 => 0x6df7, + 0xe9 => 0x6e3e, 0xea => 0x743f, 0xeb => 0x9b42, 0xec => 0x5ffd, + 0xed => 0x60da, 0xee => 0x7b0f, 0xef => 0x54c4, 0xf0 => 0x5f18, + 0xf1 => 0x6c5e, 0xf2 => 0x6cd3, 0xf3 => 0x6d2a, 0xf4 => 0x70d8, + 0xf5 => 0x7d05, 0xf6 => 0x8679, 0xf7 => 0x8a0c, 0xf8 => 0x9d3b, + 0xf9 => 0x5316, 0xfa => 0x548c, 0xfb => 0x5b05, 0xfc => 0x6a3a, + 0xfd => 0x706b, 0xfe => 0x7575, + }, + 0xfc => { + 0xa1 => 0x798d, 0xa2 => 0x79be, 0xa3 => 0x82b1, 0xa4 => 0x83ef, + 0xa5 => 0x8a71, 0xa6 => 0x8b41, 0xa7 => 0x8ca8, 0xa8 => 0x9774, + 0xa9 => 0xfa0b, 0xaa => 0x64f4, 0xab => 0x652b, 0xac => 0x78ba, + 0xad => 0x78bb, 0xae => 0x7a6b, 0xaf => 0x4e38, 0xb0 => 0x559a, + 0xb1 => 0x5950, 0xb2 => 0x5ba6, 0xb3 => 0x5e7b, 0xb4 => 0x60a3, + 0xb5 => 0x63db, 0xb6 => 0x6b61, 0xb7 => 0x6665, 0xb8 => 0x6853, + 0xb9 => 0x6e19, 0xba => 0x7165, 0xbb => 0x74b0, 0xbc => 0x7d08, + 0xbd => 0x9084, 0xbe => 0x9a69, 0xbf => 0x9c25, 0xc0 => 0x6d3b, + 0xc1 => 0x6ed1, 0xc2 => 0x733e, 0xc3 => 0x8c41, 0xc4 => 0x95ca, + 0xc5 => 0x51f0, 0xc6 => 0x5e4c, 0xc7 => 0x5fa8, 0xc8 => 0x604d, + 0xc9 => 0x60f6, 0xca => 0x6130, 0xcb => 0x614c, 0xcc => 0x6643, + 0xcd => 0x6644, 0xce => 0x69a5, 0xcf => 0x6cc1, 0xd0 => 0x6e5f, + 0xd1 => 0x6ec9, 0xd2 => 0x6f62, 0xd3 => 0x714c, 0xd4 => 0x749c, + 0xd5 => 0x7687, 0xd6 => 0x7bc1, 0xd7 => 0x7c27, 0xd8 => 0x8352, + 0xd9 => 0x8757, 0xda => 0x9051, 0xdb => 0x968d, 0xdc => 0x9ec3, + 0xdd => 0x532f, 0xde => 0x56de, 0xdf => 0x5efb, 0xe0 => 0x5f8a, + 0xe1 => 0x6062, 0xe2 => 0x6094, 0xe3 => 0x61f7, 0xe4 => 0x6666, + 0xe5 => 0x6703, 0xe6 => 0x6a9c, 0xe7 => 0x6dee, 0xe8 => 0x6fae, + 0xe9 => 0x7070, 0xea => 0x736a, 0xeb => 0x7e6a, 0xec => 0x81be, + 0xed => 0x8334, 0xee => 0x86d4, 0xef => 0x8aa8, 0xf0 => 0x8cc4, + 0xf1 => 0x5283, 0xf2 => 0x7372, 0xf3 => 0x5b96, 0xf4 => 0x6a6b, + 0xf5 => 0x9404, 0xf6 => 0x54ee, 0xf7 => 0x5686, 0xf8 => 0x5b5d, + 0xf9 => 0x6548, 0xfa => 0x6585, 0xfb => 0x66c9, 0xfc => 0x689f, + 0xfd => 0x6d8d, 0xfe => 0x6dc6, + }, + 0xfd => { + 0xa1 => 0x723b, 0xa2 => 0x80b4, 0xa3 => 0x9175, 0xa4 => 0x9a4d, + 0xa5 => 0x4faf, 0xa6 => 0x5019, 0xa7 => 0x539a, 0xa8 => 0x540e, + 0xa9 => 0x543c, 0xaa => 0x5589, 0xab => 0x55c5, 0xac => 0x5e3f, + 0xad => 0x5f8c, 0xae => 0x673d, 0xaf => 0x7166, 0xb0 => 0x73dd, + 0xb1 => 0x9005, 0xb2 => 0x52db, 0xb3 => 0x52f3, 0xb4 => 0x5864, + 0xb5 => 0x58ce, 0xb6 => 0x7104, 0xb7 => 0x718f, 0xb8 => 0x71fb, + 0xb9 => 0x85b0, 0xba => 0x8a13, 0xbb => 0x6688, 0xbc => 0x85a8, + 0xbd => 0x55a7, 0xbe => 0x6684, 0xbf => 0x714a, 0xc0 => 0x8431, + 0xc1 => 0x5349, 0xc2 => 0x5599, 0xc3 => 0x6bc1, 0xc4 => 0x5f59, + 0xc5 => 0x5fbd, 0xc6 => 0x63ee, 0xc7 => 0x6689, 0xc8 => 0x7147, + 0xc9 => 0x8af1, 0xca => 0x8f1d, 0xcb => 0x9ebe, 0xcc => 0x4f11, + 0xcd => 0x643a, 0xce => 0x70cb, 0xcf => 0x7566, 0xd0 => 0x8667, + 0xd1 => 0x6064, 0xd2 => 0x8b4e, 0xd3 => 0x9df8, 0xd4 => 0x5147, + 0xd5 => 0x51f6, 0xd6 => 0x5308, 0xd7 => 0x6d36, 0xd8 => 0x80f8, + 0xd9 => 0x9ed1, 0xda => 0x6615, 0xdb => 0x6b23, 0xdc => 0x7098, + 0xdd => 0x75d5, 0xde => 0x5403, 0xdf => 0x5c79, 0xe0 => 0x7d07, + 0xe1 => 0x8a16, 0xe2 => 0x6b20, 0xe3 => 0x6b3d, 0xe4 => 0x6b46, + 0xe5 => 0x5438, 0xe6 => 0x6070, 0xe7 => 0x6d3d, 0xe8 => 0x7fd5, + 0xe9 => 0x8208, 0xea => 0x50d6, 0xeb => 0x51de, 0xec => 0x559c, + 0xed => 0x566b, 0xee => 0x56cd, 0xef => 0x59ec, 0xf0 => 0x5b09, + 0xf1 => 0x5e0c, 0xf2 => 0x6199, 0xf3 => 0x6198, 0xf4 => 0x6231, + 0xf5 => 0x665e, 0xf6 => 0x66e6, 0xf7 => 0x7199, 0xf8 => 0x71b9, + 0xf9 => 0x71ba, 0xfa => 0x72a7, 0xfb => 0x79a7, 0xfc => 0x7a00, + 0xfd => 0x7fb2, 0xfe => 0x8a70, + }, +); + +1; # end diff --git a/lib/Image/ExifTool/Charset/MacLatin2.pm b/lib/Image/ExifTool/Charset/MacLatin2.pm new file mode 100644 index 0000000..5b891ec --- /dev/null +++ b/lib/Image/ExifTool/Charset/MacLatin2.pm @@ -0,0 +1,44 @@ +#------------------------------------------------------------------------------ +# File: MacLatin2.pm +# +# Description: Mac Central European to Unicode +# +# Revisions: 2010/01/20 - P. Harvey created +# +# References: 1) http://unicode.org/Public/MAPPINGS/VENDORS/APPLE/CENTEURO.TXT +# +# Notes: The table omits 1-byte characters with the same values as Unicode +#------------------------------------------------------------------------------ +use strict; + +%Image::ExifTool::Charset::MacLatin2 = ( + 0x80 => 0xc4, 0x81 => 0x0100, 0x82 => 0x0101, 0x83 => 0xc9, 0x84 => 0x0104, + 0x85 => 0xd6, 0x86 => 0xdc, 0x87 => 0xe1, 0x88 => 0x0105, 0x89 => 0x010c, + 0x8a => 0xe4, 0x8b => 0x010d, 0x8c => 0x0106, 0x8d => 0x0107, 0x8e => 0xe9, + 0x8f => 0x0179, 0x90 => 0x017a, 0x91 => 0x010e, 0x92 => 0xed, 0x93 => 0x010f, + 0x94 => 0x0112, 0x95 => 0x0113, 0x96 => 0x0116, 0x97 => 0xf3, 0x98 => 0x0117, + 0x99 => 0xf4, 0x9a => 0xf6, 0x9b => 0xf5, 0x9c => 0xfa, 0x9d => 0x011a, + 0x9e => 0x011b, 0x9f => 0xfc, 0xa0 => 0x2020, 0xa1 => 0xb0, 0xa2 => 0x0118, + 0xa4 => 0xa7, 0xa5 => 0x2022, 0xa6 => 0xb6, 0xa7 => 0xdf, 0xa8 => 0xae, + 0xaa => 0x2122, 0xab => 0x0119, 0xac => 0xa8, 0xad => 0x2260, 0xae => 0x0123, + 0xaf => 0x012e, 0xb0 => 0x012f, 0xb1 => 0x012a, 0xb2 => 0x2264, + 0xb3 => 0x2265, 0xb4 => 0x012b, 0xb5 => 0x0136, 0xb6 => 0x2202, + 0xb7 => 0x2211, 0xb8 => 0x0142, 0xb9 => 0x013b, 0xba => 0x013c, + 0xbb => 0x013d, 0xbc => 0x013e, 0xbd => 0x0139, 0xbe => 0x013a, + 0xbf => 0x0145, 0xc0 => 0x0146, 0xc1 => 0x0143, 0xc2 => 0xac, 0xc3 => 0x221a, + 0xc4 => 0x0144, 0xc5 => 0x0147, 0xc6 => 0x2206, 0xc7 => 0xab, 0xc8 => 0xbb, + 0xc9 => 0x2026, 0xca => 0xa0, 0xcb => 0x0148, 0xcc => 0x0150, 0xcd => 0xd5, + 0xce => 0x0151, 0xcf => 0x014c, 0xd0 => 0x2013, 0xd1 => 0x2014, + 0xd2 => 0x201c, 0xd3 => 0x201d, 0xd4 => 0x2018, 0xd5 => 0x2019, 0xd6 => 0xf7, + 0xd7 => 0x25ca, 0xd8 => 0x014d, 0xd9 => 0x0154, 0xda => 0x0155, + 0xdb => 0x0158, 0xdc => 0x2039, 0xdd => 0x203a, 0xde => 0x0159, + 0xdf => 0x0156, 0xe0 => 0x0157, 0xe1 => 0x0160, 0xe2 => 0x201a, + 0xe3 => 0x201e, 0xe4 => 0x0161, 0xe5 => 0x015a, 0xe6 => 0x015b, 0xe7 => 0xc1, + 0xe8 => 0x0164, 0xe9 => 0x0165, 0xea => 0xcd, 0xeb => 0x017d, 0xec => 0x017e, + 0xed => 0x016a, 0xee => 0xd3, 0xef => 0xd4, 0xf0 => 0x016b, 0xf1 => 0x016e, + 0xf2 => 0xda, 0xf3 => 0x016f, 0xf4 => 0x0170, 0xf5 => 0x0171, 0xf6 => 0x0172, + 0xf7 => 0x0173, 0xf8 => 0xdd, 0xf9 => 0xfd, 0xfa => 0x0137, 0xfb => 0x017b, + 0xfc => 0x0141, 0xfd => 0x017c, 0xfe => 0x0122, 0xff => 0x02c7, +); + +1; # end diff --git a/lib/Image/ExifTool/Charset/MacRSymbol.pm b/lib/Image/ExifTool/Charset/MacRSymbol.pm new file mode 100644 index 0000000..073c743 --- /dev/null +++ b/lib/Image/ExifTool/Charset/MacRSymbol.pm @@ -0,0 +1,2087 @@ +#------------------------------------------------------------------------------ +# File: MacRSymbol.pm +# +# Description: Mac RSymbol (cp10008) to Unicode +# +# Revisions: 2010/01/20 - P. Harvey created +# +# References: 1) http://www.haible.de/bruno/charsets/conversion-tables/GB2312.tar.bz2 +# +# Notes: The table omits 1-byte characters with the same values as Unicode +#------------------------------------------------------------------------------ +use strict; + +%Image::ExifTool::Charset::MacRSymbol = ( + 0x81 => 0xf8d8, 0x82 => 0xf8d9, 0x83 => 0xf8da, 0x84 => 0xf8db, + 0x85 => 0xf8dc, 0x86 => 0xf8dd, 0x87 => 0xf8de, 0x88 => 0xf8df, + 0x89 => 0xf8e0, 0x8a => 0xf8e1, 0x8b => 0xf8e2, 0x8c => 0xf8e3, + 0x8d => 0xf8e4, 0x8e => 0xf8e5, 0x8f => 0xf8e6, 0x90 => 0xf8e7, + 0x91 => 0xf8e8, 0x92 => 0xf8e9, 0x93 => 0xf8ea, 0x94 => 0xf8eb, + 0x95 => 0xf8ec, 0x96 => 0xf8ed, 0x97 => 0xf8ee, 0x98 => 0xf8ef, + 0x99 => 0xf8f0, 0x9a => 0xf8f1, 0x9b => 0xf8f2, 0x9c => 0xf8f3, + 0x9d => 0xf8f4, 0x9e => 0xf8f5, 0x9f => 0xf8f6, 0xa0 => 0xf8f7, + 0xa1 => { + 0xa1 => 0x3000, 0xa2 => 0x3001, 0xa3 => 0x3002, 0xa4 => 0x30fb, + 0xa5 => 0x02c9, 0xa6 => 0x02c7, 0xa7 => 0xa8, 0xa8 => 0x3003, + 0xa9 => 0x3005, 0xaa => 0x2015, 0xab => 0xff5e, 0xad => 0x2026, + 0xae => 0x2018, 0xaf => 0x2019, 0xb0 => 0x201c, 0xb1 => 0x201d, + 0xb2 => 0x3014, 0xb3 => 0x3015, 0xb4 => 0x3008, 0xb5 => 0x3009, + 0xb6 => 0x300a, 0xb7 => 0x300b, 0xb8 => 0x300c, 0xb9 => 0x300d, + 0xba => 0x300e, 0xbb => 0x300f, 0xbc => 0x3016, 0xbd => 0x3017, + 0xbe => 0x3010, 0xbf => 0x3011, 0xc0 => 0xb1, 0xc1 => 0xd7, 0xc2 => 0xf7, + 0xc3 => 0x2236, 0xc4 => 0x2227, 0xc5 => 0x2228, 0xc6 => 0x2211, + 0xc7 => 0x220f, 0xc8 => 0x222a, 0xc9 => 0x2229, 0xca => 0x2208, + 0xcb => 0x2237, 0xcc => 0x221a, 0xcd => 0x22a5, 0xce => 0x2225, + 0xcf => 0x2220, 0xd0 => 0x2312, 0xd1 => 0x2299, 0xd2 => 0x222b, + 0xd3 => 0x222e, 0xd4 => 0x2261, 0xd5 => 0x224c, 0xd6 => 0x2248, + 0xd7 => 0x223d, 0xd8 => 0x221d, 0xd9 => 0x2260, 0xda => 0x226e, + 0xdb => 0x226f, 0xdc => 0x2264, 0xdd => 0x2265, 0xde => 0x221e, + 0xdf => 0x2235, 0xe0 => 0x2234, 0xe1 => 0x2642, 0xe2 => 0x2640, + 0xe3 => 0xb0, 0xe4 => 0x2032, 0xe5 => 0x2033, 0xe6 => 0x2103, + 0xe7 => 0xff04, 0xe8 => 0xa4, 0xe9 => 0xffe0, 0xea => 0xffe1, + 0xeb => 0x2030, 0xec => 0xa7, 0xed => 0x2116, 0xee => 0x2606, + 0xef => 0x2605, 0xf0 => 0x25cb, 0xf1 => 0x25cf, 0xf2 => 0x25ce, + 0xf3 => 0x25c7, 0xf4 => 0x25c6, 0xf5 => 0x25a1, 0xf6 => 0x25a0, + 0xf7 => 0x25b3, 0xf8 => 0x25b2, 0xf9 => 0x203b, 0xfa => 0x2192, + 0xfb => 0x2190, 0xfc => 0x2191, 0xfd => 0x2193, 0xfe => 0x3013, + }, + 0xa2 => { + 0xb1 => 0x2488, 0xb2 => 0x2489, 0xb3 => 0x248a, 0xb4 => 0x248b, + 0xb5 => 0x248c, 0xb6 => 0x248d, 0xb7 => 0x248e, 0xb8 => 0x248f, + 0xb9 => 0x2490, 0xba => 0x2491, 0xbb => 0x2492, 0xbc => 0x2493, + 0xbd => 0x2494, 0xbe => 0x2495, 0xbf => 0x2496, 0xc0 => 0x2497, + 0xc1 => 0x2498, 0xc2 => 0x2499, 0xc3 => 0x249a, 0xc4 => 0x249b, + 0xc5 => 0x2474, 0xc6 => 0x2475, 0xc7 => 0x2476, 0xc8 => 0x2477, + 0xc9 => 0x2478, 0xca => 0x2479, 0xcb => 0x247a, 0xcc => 0x247b, + 0xcd => 0x247c, 0xce => 0x247d, 0xcf => 0x247e, 0xd0 => 0x247f, + 0xd1 => 0x2480, 0xd2 => 0x2481, 0xd3 => 0x2482, 0xd4 => 0x2483, + 0xd5 => 0x2484, 0xd6 => 0x2485, 0xd7 => 0x2486, 0xd8 => 0x2487, + 0xd9 => 0x2460, 0xda => 0x2461, 0xdb => 0x2462, 0xdc => 0x2463, + 0xdd => 0x2464, 0xde => 0x2465, 0xdf => 0x2466, 0xe0 => 0x2467, + 0xe1 => 0x2468, 0xe2 => 0x2469, 0xe5 => 0x3220, 0xe6 => 0x3221, + 0xe7 => 0x3222, 0xe8 => 0x3223, 0xe9 => 0x3224, 0xea => 0x3225, + 0xeb => 0x3226, 0xec => 0x3227, 0xed => 0x3228, 0xee => 0x3229, + 0xf1 => 0x2160, 0xf2 => 0x2161, 0xf3 => 0x2162, 0xf4 => 0x2163, + 0xf5 => 0x2164, 0xf6 => 0x2165, 0xf7 => 0x2166, 0xf8 => 0x2167, + 0xf9 => 0x2168, 0xfa => 0x2169, 0xfb => 0x216a, 0xfc => 0x216b, + }, + 0xa3 => { + 0xa1 => 0xff01, 0xa2 => 0xff02, 0xa3 => 0xff03, 0xa4 => 0xffe5, + 0xa5 => 0xff05, 0xa6 => 0xff06, 0xa7 => 0xff07, 0xa8 => 0xff08, + 0xa9 => 0xff09, 0xaa => 0xff0a, 0xab => 0xff0b, 0xac => 0xff0c, + 0xad => 0xff0d, 0xae => 0xff0e, 0xaf => 0xff0f, 0xb0 => 0xff10, + 0xb1 => 0xff11, 0xb2 => 0xff12, 0xb3 => 0xff13, 0xb4 => 0xff14, + 0xb5 => 0xff15, 0xb6 => 0xff16, 0xb7 => 0xff17, 0xb8 => 0xff18, + 0xb9 => 0xff19, 0xba => 0xff1a, 0xbb => 0xff1b, 0xbc => 0xff1c, + 0xbd => 0xff1d, 0xbe => 0xff1e, 0xbf => 0xff1f, 0xc0 => 0xff20, + 0xc1 => 0xff21, 0xc2 => 0xff22, 0xc3 => 0xff23, 0xc4 => 0xff24, + 0xc5 => 0xff25, 0xc6 => 0xff26, 0xc7 => 0xff27, 0xc8 => 0xff28, + 0xc9 => 0xff29, 0xca => 0xff2a, 0xcb => 0xff2b, 0xcc => 0xff2c, + 0xcd => 0xff2d, 0xce => 0xff2e, 0xcf => 0xff2f, 0xd0 => 0xff30, + 0xd1 => 0xff31, 0xd2 => 0xff32, 0xd3 => 0xff33, 0xd4 => 0xff34, + 0xd5 => 0xff35, 0xd6 => 0xff36, 0xd7 => 0xff37, 0xd8 => 0xff38, + 0xd9 => 0xff39, 0xda => 0xff3a, 0xdb => 0xff3b, 0xdc => 0xff3c, + 0xdd => 0xff3d, 0xde => 0xff3e, 0xdf => 0xff3f, 0xe0 => 0xff40, + 0xe1 => 0xff41, 0xe2 => 0xff42, 0xe3 => 0xff43, 0xe4 => 0xff44, + 0xe5 => 0xff45, 0xe6 => 0xff46, 0xe7 => 0xff47, 0xe8 => 0xff48, + 0xe9 => 0xff49, 0xea => 0xff4a, 0xeb => 0xff4b, 0xec => 0xff4c, + 0xed => 0xff4d, 0xee => 0xff4e, 0xef => 0xff4f, 0xf0 => 0xff50, + 0xf1 => 0xff51, 0xf2 => 0xff52, 0xf3 => 0xff53, 0xf4 => 0xff54, + 0xf5 => 0xff55, 0xf6 => 0xff56, 0xf7 => 0xff57, 0xf8 => 0xff58, + 0xf9 => 0xff59, 0xfa => 0xff5a, 0xfb => 0xff5b, 0xfc => 0xff5c, + 0xfd => 0xff5d, 0xfe => 0xffe3, + }, + 0xa4 => { + 0xa1 => 0x3041, 0xa2 => 0x3042, 0xa3 => 0x3043, 0xa4 => 0x3044, + 0xa5 => 0x3045, 0xa6 => 0x3046, 0xa7 => 0x3047, 0xa8 => 0x3048, + 0xa9 => 0x3049, 0xaa => 0x304a, 0xab => 0x304b, 0xac => 0x304c, + 0xad => 0x304d, 0xae => 0x304e, 0xaf => 0x304f, 0xb0 => 0x3050, + 0xb1 => 0x3051, 0xb2 => 0x3052, 0xb3 => 0x3053, 0xb4 => 0x3054, + 0xb5 => 0x3055, 0xb6 => 0x3056, 0xb7 => 0x3057, 0xb8 => 0x3058, + 0xb9 => 0x3059, 0xba => 0x305a, 0xbb => 0x305b, 0xbc => 0x305c, + 0xbd => 0x305d, 0xbe => 0x305e, 0xbf => 0x305f, 0xc0 => 0x3060, + 0xc1 => 0x3061, 0xc2 => 0x3062, 0xc3 => 0x3063, 0xc4 => 0x3064, + 0xc5 => 0x3065, 0xc6 => 0x3066, 0xc7 => 0x3067, 0xc8 => 0x3068, + 0xc9 => 0x3069, 0xca => 0x306a, 0xcb => 0x306b, 0xcc => 0x306c, + 0xcd => 0x306d, 0xce => 0x306e, 0xcf => 0x306f, 0xd0 => 0x3070, + 0xd1 => 0x3071, 0xd2 => 0x3072, 0xd3 => 0x3073, 0xd4 => 0x3074, + 0xd5 => 0x3075, 0xd6 => 0x3076, 0xd7 => 0x3077, 0xd8 => 0x3078, + 0xd9 => 0x3079, 0xda => 0x307a, 0xdb => 0x307b, 0xdc => 0x307c, + 0xdd => 0x307d, 0xde => 0x307e, 0xdf => 0x307f, 0xe0 => 0x3080, + 0xe1 => 0x3081, 0xe2 => 0x3082, 0xe3 => 0x3083, 0xe4 => 0x3084, + 0xe5 => 0x3085, 0xe6 => 0x3086, 0xe7 => 0x3087, 0xe8 => 0x3088, + 0xe9 => 0x3089, 0xea => 0x308a, 0xeb => 0x308b, 0xec => 0x308c, + 0xed => 0x308d, 0xee => 0x308e, 0xef => 0x308f, 0xf0 => 0x3090, + 0xf1 => 0x3091, 0xf2 => 0x3092, 0xf3 => 0x3093, + }, + 0xa5 => { + 0xa1 => 0x30a1, 0xa2 => 0x30a2, 0xa3 => 0x30a3, 0xa4 => 0x30a4, + 0xa5 => 0x30a5, 0xa6 => 0x30a6, 0xa7 => 0x30a7, 0xa8 => 0x30a8, + 0xa9 => 0x30a9, 0xaa => 0x30aa, 0xab => 0x30ab, 0xac => 0x30ac, + 0xad => 0x30ad, 0xae => 0x30ae, 0xaf => 0x30af, 0xb0 => 0x30b0, + 0xb1 => 0x30b1, 0xb2 => 0x30b2, 0xb3 => 0x30b3, 0xb4 => 0x30b4, + 0xb5 => 0x30b5, 0xb6 => 0x30b6, 0xb7 => 0x30b7, 0xb8 => 0x30b8, + 0xb9 => 0x30b9, 0xba => 0x30ba, 0xbb => 0x30bb, 0xbc => 0x30bc, + 0xbd => 0x30bd, 0xbe => 0x30be, 0xbf => 0x30bf, 0xc0 => 0x30c0, + 0xc1 => 0x30c1, 0xc2 => 0x30c2, 0xc3 => 0x30c3, 0xc4 => 0x30c4, + 0xc5 => 0x30c5, 0xc6 => 0x30c6, 0xc7 => 0x30c7, 0xc8 => 0x30c8, + 0xc9 => 0x30c9, 0xca => 0x30ca, 0xcb => 0x30cb, 0xcc => 0x30cc, + 0xcd => 0x30cd, 0xce => 0x30ce, 0xcf => 0x30cf, 0xd0 => 0x30d0, + 0xd1 => 0x30d1, 0xd2 => 0x30d2, 0xd3 => 0x30d3, 0xd4 => 0x30d4, + 0xd5 => 0x30d5, 0xd6 => 0x30d6, 0xd7 => 0x30d7, 0xd8 => 0x30d8, + 0xd9 => 0x30d9, 0xda => 0x30da, 0xdb => 0x30db, 0xdc => 0x30dc, + 0xdd => 0x30dd, 0xde => 0x30de, 0xdf => 0x30df, 0xe0 => 0x30e0, + 0xe1 => 0x30e1, 0xe2 => 0x30e2, 0xe3 => 0x30e3, 0xe4 => 0x30e4, + 0xe5 => 0x30e5, 0xe6 => 0x30e6, 0xe7 => 0x30e7, 0xe8 => 0x30e8, + 0xe9 => 0x30e9, 0xea => 0x30ea, 0xeb => 0x30eb, 0xec => 0x30ec, + 0xed => 0x30ed, 0xee => 0x30ee, 0xef => 0x30ef, 0xf0 => 0x30f0, + 0xf1 => 0x30f1, 0xf2 => 0x30f2, 0xf3 => 0x30f3, 0xf4 => 0x30f4, + 0xf5 => 0x30f5, 0xf6 => 0x30f6, + }, + 0xa6 => { + 0xa1 => 0x0391, 0xa2 => 0x0392, 0xa3 => 0x0393, 0xa4 => 0x0394, + 0xa5 => 0x0395, 0xa6 => 0x0396, 0xa7 => 0x0397, 0xa8 => 0x0398, + 0xa9 => 0x0399, 0xaa => 0x039a, 0xab => 0x039b, 0xac => 0x039c, + 0xad => 0x039d, 0xae => 0x039e, 0xaf => 0x039f, 0xb0 => 0x03a0, + 0xb1 => 0x03a1, 0xb2 => 0x03a3, 0xb3 => 0x03a4, 0xb4 => 0x03a5, + 0xb5 => 0x03a6, 0xb6 => 0x03a7, 0xb7 => 0x03a8, 0xb8 => 0x03a9, + 0xc1 => 0x03b1, 0xc2 => 0x03b2, 0xc3 => 0x03b3, 0xc4 => 0x03b4, + 0xc5 => 0x03b5, 0xc6 => 0x03b6, 0xc7 => 0x03b7, 0xc8 => 0x03b8, + 0xc9 => 0x03b9, 0xca => 0x03ba, 0xcb => 0x03bb, 0xcc => 0x03bc, + 0xcd => 0x03bd, 0xce => 0x03be, 0xcf => 0x03bf, 0xd0 => 0x03c0, + 0xd1 => 0x03c1, 0xd2 => 0x03c3, 0xd3 => 0x03c4, 0xd4 => 0x03c5, + 0xd5 => 0x03c6, 0xd6 => 0x03c7, 0xd7 => 0x03c8, 0xd8 => 0x03c9, + }, + 0xa7 => { + 0xa1 => 0x0410, 0xa2 => 0x0411, 0xa3 => 0x0412, 0xa4 => 0x0413, + 0xa5 => 0x0414, 0xa6 => 0x0415, 0xa7 => 0x0401, 0xa8 => 0x0416, + 0xa9 => 0x0417, 0xaa => 0x0418, 0xab => 0x0419, 0xac => 0x041a, + 0xad => 0x041b, 0xae => 0x041c, 0xaf => 0x041d, 0xb0 => 0x041e, + 0xb1 => 0x041f, 0xb2 => 0x0420, 0xb3 => 0x0421, 0xb4 => 0x0422, + 0xb5 => 0x0423, 0xb6 => 0x0424, 0xb7 => 0x0425, 0xb8 => 0x0426, + 0xb9 => 0x0427, 0xba => 0x0428, 0xbb => 0x0429, 0xbc => 0x042a, + 0xbd => 0x042b, 0xbe => 0x042c, 0xbf => 0x042d, 0xc0 => 0x042e, + 0xc1 => 0x042f, 0xd1 => 0x0430, 0xd2 => 0x0431, 0xd3 => 0x0432, + 0xd4 => 0x0433, 0xd5 => 0x0434, 0xd6 => 0x0435, 0xd7 => 0x0451, + 0xd8 => 0x0436, 0xd9 => 0x0437, 0xda => 0x0438, 0xdb => 0x0439, + 0xdc => 0x043a, 0xdd => 0x043b, 0xde => 0x043c, 0xdf => 0x043d, + 0xe0 => 0x043e, 0xe1 => 0x043f, 0xe2 => 0x0440, 0xe3 => 0x0441, + 0xe4 => 0x0442, 0xe5 => 0x0443, 0xe6 => 0x0444, 0xe7 => 0x0445, + 0xe8 => 0x0446, 0xe9 => 0x0447, 0xea => 0x0448, 0xeb => 0x0449, + 0xec => 0x044a, 0xed => 0x044b, 0xee => 0x044c, 0xef => 0x044d, + 0xf0 => 0x044e, 0xf1 => 0x044f, + }, + 0xa8 => { + 0xa1 => 0x0101, 0xa2 => 0xe1, 0xa3 => 0x01ce, 0xa4 => 0xe0, 0xa5 => 0x0113, + 0xa6 => 0xe9, 0xa7 => 0x011b, 0xa8 => 0xe8, 0xa9 => 0x012b, 0xaa => 0xed, + 0xab => 0x01d0, 0xac => 0xec, 0xad => 0x014d, 0xae => 0xf3, 0xaf => 0x01d2, + 0xb0 => 0xf2, 0xb1 => 0x016b, 0xb2 => 0xfa, 0xb3 => 0x01d4, 0xb4 => 0xf9, + 0xb5 => 0x01d6, 0xb6 => 0x01d8, 0xb7 => 0x01da, 0xb8 => 0x01dc, + 0xb9 => 0xfc, 0xba => 0xea, 0xc5 => 0x3105, 0xc6 => 0x3106, 0xc7 => 0x3107, + 0xc8 => 0x3108, 0xc9 => 0x3109, 0xca => 0x310a, 0xcb => 0x310b, + 0xcc => 0x310c, 0xcd => 0x310d, 0xce => 0x310e, 0xcf => 0x310f, + 0xd0 => 0x3110, 0xd1 => 0x3111, 0xd2 => 0x3112, 0xd3 => 0x3113, + 0xd4 => 0x3114, 0xd5 => 0x3115, 0xd6 => 0x3116, 0xd7 => 0x3117, + 0xd8 => 0x3118, 0xd9 => 0x3119, 0xda => 0x311a, 0xdb => 0x311b, + 0xdc => 0x311c, 0xdd => 0x311d, 0xde => 0x311e, 0xdf => 0x311f, + 0xe0 => 0x3120, 0xe1 => 0x3121, 0xe2 => 0x3122, 0xe3 => 0x3123, + 0xe4 => 0x3124, 0xe5 => 0x3125, 0xe6 => 0x3126, 0xe7 => 0x3127, + 0xe8 => 0x3128, 0xe9 => 0x3129, + }, + 0xa9 => { + 0xa4 => 0x2500, 0xa5 => 0x2501, 0xa6 => 0x2502, 0xa7 => 0x2503, + 0xa8 => 0x2504, 0xa9 => 0x2505, 0xaa => 0x2506, 0xab => 0x2507, + 0xac => 0x2508, 0xad => 0x2509, 0xae => 0x250a, 0xaf => 0x250b, + 0xb0 => 0x250c, 0xb1 => 0x250d, 0xb2 => 0x250e, 0xb3 => 0x250f, + 0xb4 => 0x2510, 0xb5 => 0x2511, 0xb6 => 0x2512, 0xb7 => 0x2513, + 0xb8 => 0x2514, 0xb9 => 0x2515, 0xba => 0x2516, 0xbb => 0x2517, + 0xbc => 0x2518, 0xbd => 0x2519, 0xbe => 0x251a, 0xbf => 0x251b, + 0xc0 => 0x251c, 0xc1 => 0x251d, 0xc2 => 0x251e, 0xc3 => 0x251f, + 0xc4 => 0x2520, 0xc5 => 0x2521, 0xc6 => 0x2522, 0xc7 => 0x2523, + 0xc8 => 0x2524, 0xc9 => 0x2525, 0xca => 0x2526, 0xcb => 0x2527, + 0xcc => 0x2528, 0xcd => 0x2529, 0xce => 0x252a, 0xcf => 0x252b, + 0xd0 => 0x252c, 0xd1 => 0x252d, 0xd2 => 0x252e, 0xd3 => 0x252f, + 0xd4 => 0x2530, 0xd5 => 0x2531, 0xd6 => 0x2532, 0xd7 => 0x2533, + 0xd8 => 0x2534, 0xd9 => 0x2535, 0xda => 0x2536, 0xdb => 0x2537, + 0xdc => 0x2538, 0xdd => 0x2539, 0xde => 0x253a, 0xdf => 0x253b, + 0xe0 => 0x253c, 0xe1 => 0x253d, 0xe2 => 0x253e, 0xe3 => 0x253f, + 0xe4 => 0x2540, 0xe5 => 0x2541, 0xe6 => 0x2542, 0xe7 => 0x2543, + 0xe8 => 0x2544, 0xe9 => 0x2545, 0xea => 0x2546, 0xeb => 0x2547, + 0xec => 0x2548, 0xed => 0x2549, 0xee => 0x254a, 0xef => 0x254b, + }, + 0xb0 => { + 0xa1 => 0x554a, 0xa2 => 0x963f, 0xa3 => 0x57c3, 0xa4 => 0x6328, + 0xa5 => 0x54ce, 0xa6 => 0x5509, 0xa7 => 0x54c0, 0xa8 => 0x7691, + 0xa9 => 0x764c, 0xaa => 0x853c, 0xab => 0x77ee, 0xac => 0x827e, + 0xad => 0x788d, 0xae => 0x7231, 0xaf => 0x9698, 0xb0 => 0x978d, + 0xb1 => 0x6c28, 0xb2 => 0x5b89, 0xb3 => 0x4ffa, 0xb4 => 0x6309, + 0xb5 => 0x6697, 0xb6 => 0x5cb8, 0xb7 => 0x80fa, 0xb8 => 0x6848, + 0xb9 => 0x80ae, 0xba => 0x6602, 0xbb => 0x76ce, 0xbc => 0x51f9, + 0xbd => 0x6556, 0xbe => 0x71ac, 0xbf => 0x7ff1, 0xc0 => 0x8884, + 0xc1 => 0x50b2, 0xc2 => 0x5965, 0xc3 => 0x61ca, 0xc4 => 0x6fb3, + 0xc5 => 0x82ad, 0xc6 => 0x634c, 0xc7 => 0x6252, 0xc8 => 0x53ed, + 0xc9 => 0x5427, 0xca => 0x7b06, 0xcb => 0x516b, 0xcc => 0x75a4, + 0xcd => 0x5df4, 0xce => 0x62d4, 0xcf => 0x8dcb, 0xd0 => 0x9776, + 0xd1 => 0x628a, 0xd2 => 0x8019, 0xd3 => 0x575d, 0xd4 => 0x9738, + 0xd5 => 0x7f62, 0xd6 => 0x7238, 0xd7 => 0x767d, 0xd8 => 0x67cf, + 0xd9 => 0x767e, 0xda => 0x6446, 0xdb => 0x4f70, 0xdc => 0x8d25, + 0xdd => 0x62dc, 0xde => 0x7a17, 0xdf => 0x6591, 0xe0 => 0x73ed, + 0xe1 => 0x642c, 0xe2 => 0x6273, 0xe3 => 0x822c, 0xe4 => 0x9881, + 0xe5 => 0x677f, 0xe6 => 0x7248, 0xe7 => 0x626e, 0xe8 => 0x62cc, + 0xe9 => 0x4f34, 0xea => 0x74e3, 0xeb => 0x534a, 0xec => 0x529e, + 0xed => 0x7eca, 0xee => 0x90a6, 0xef => 0x5e2e, 0xf0 => 0x6886, + 0xf1 => 0x699c, 0xf2 => 0x8180, 0xf3 => 0x7ed1, 0xf4 => 0x68d2, + 0xf5 => 0x78c5, 0xf6 => 0x868c, 0xf7 => 0x9551, 0xf8 => 0x508d, + 0xf9 => 0x8c24, 0xfa => 0x82de, 0xfb => 0x80de, 0xfc => 0x5305, + 0xfd => 0x8912, 0xfe => 0x5265, + }, + 0xb1 => { + 0xa1 => 0x8584, 0xa2 => 0x96f9, 0xa3 => 0x4fdd, 0xa4 => 0x5821, + 0xa5 => 0x9971, 0xa6 => 0x5b9d, 0xa7 => 0x62b1, 0xa8 => 0x62a5, + 0xa9 => 0x66b4, 0xaa => 0x8c79, 0xab => 0x9c8d, 0xac => 0x7206, + 0xad => 0x676f, 0xae => 0x7891, 0xaf => 0x60b2, 0xb0 => 0x5351, + 0xb1 => 0x5317, 0xb2 => 0x8f88, 0xb3 => 0x80cc, 0xb4 => 0x8d1d, + 0xb5 => 0x94a1, 0xb6 => 0x500d, 0xb7 => 0x72c8, 0xb8 => 0x5907, + 0xb9 => 0x60eb, 0xba => 0x7119, 0xbb => 0x88ab, 0xbc => 0x5954, + 0xbd => 0x82ef, 0xbe => 0x672c, 0xbf => 0x7b28, 0xc0 => 0x5d29, + 0xc1 => 0x7ef7, 0xc2 => 0x752d, 0xc3 => 0x6cf5, 0xc4 => 0x8e66, + 0xc5 => 0x8ff8, 0xc6 => 0x903c, 0xc7 => 0x9f3b, 0xc8 => 0x6bd4, + 0xc9 => 0x9119, 0xca => 0x7b14, 0xcb => 0x5f7c, 0xcc => 0x78a7, + 0xcd => 0x84d6, 0xce => 0x853d, 0xcf => 0x6bd5, 0xd0 => 0x6bd9, + 0xd1 => 0x6bd6, 0xd2 => 0x5e01, 0xd3 => 0x5e87, 0xd4 => 0x75f9, + 0xd5 => 0x95ed, 0xd6 => 0x655d, 0xd7 => 0x5f0a, 0xd8 => 0x5fc5, + 0xd9 => 0x8f9f, 0xda => 0x58c1, 0xdb => 0x81c2, 0xdc => 0x907f, + 0xdd => 0x965b, 0xde => 0x97ad, 0xdf => 0x8fb9, 0xe0 => 0x7f16, + 0xe1 => 0x8d2c, 0xe2 => 0x6241, 0xe3 => 0x4fbf, 0xe4 => 0x53d8, + 0xe5 => 0x535e, 0xe6 => 0x8fa8, 0xe7 => 0x8fa9, 0xe8 => 0x8fab, + 0xe9 => 0x904d, 0xea => 0x6807, 0xeb => 0x5f6a, 0xec => 0x8198, + 0xed => 0x8868, 0xee => 0x9cd6, 0xef => 0x618b, 0xf0 => 0x522b, + 0xf1 => 0x762a, 0xf2 => 0x5f6c, 0xf3 => 0x658c, 0xf4 => 0x6fd2, + 0xf5 => 0x6ee8, 0xf6 => 0x5bbe, 0xf7 => 0x6448, 0xf8 => 0x5175, + 0xf9 => 0x51b0, 0xfa => 0x67c4, 0xfb => 0x4e19, 0xfc => 0x79c9, + 0xfd => 0x997c, 0xfe => 0x70b3, + }, + 0xb2 => { + 0xa1 => 0x75c5, 0xa2 => 0x5e76, 0xa3 => 0x73bb, 0xa4 => 0x83e0, + 0xa5 => 0x64ad, 0xa6 => 0x62e8, 0xa7 => 0x94b5, 0xa8 => 0x6ce2, + 0xa9 => 0x535a, 0xaa => 0x52c3, 0xab => 0x640f, 0xac => 0x94c2, + 0xad => 0x7b94, 0xae => 0x4f2f, 0xaf => 0x5e1b, 0xb0 => 0x8236, + 0xb1 => 0x8116, 0xb2 => 0x818a, 0xb3 => 0x6e24, 0xb4 => 0x6cca, + 0xb5 => 0x9a73, 0xb6 => 0x6355, 0xb7 => 0x535c, 0xb8 => 0x54fa, + 0xb9 => 0x8865, 0xba => 0x57e0, 0xbb => 0x4e0d, 0xbc => 0x5e03, + 0xbd => 0x6b65, 0xbe => 0x7c3f, 0xbf => 0x90e8, 0xc0 => 0x6016, + 0xc1 => 0x64e6, 0xc2 => 0x731c, 0xc3 => 0x88c1, 0xc4 => 0x6750, + 0xc5 => 0x624d, 0xc6 => 0x8d22, 0xc7 => 0x776c, 0xc8 => 0x8e29, + 0xc9 => 0x91c7, 0xca => 0x5f69, 0xcb => 0x83dc, 0xcc => 0x8521, + 0xcd => 0x9910, 0xce => 0x53c2, 0xcf => 0x8695, 0xd0 => 0x6b8b, + 0xd1 => 0x60ed, 0xd2 => 0x60e8, 0xd3 => 0x707f, 0xd4 => 0x82cd, + 0xd5 => 0x8231, 0xd6 => 0x4ed3, 0xd7 => 0x6ca7, 0xd8 => 0x85cf, + 0xd9 => 0x64cd, 0xda => 0x7cd9, 0xdb => 0x69fd, 0xdc => 0x66f9, + 0xdd => 0x8349, 0xde => 0x5395, 0xdf => 0x7b56, 0xe0 => 0x4fa7, + 0xe1 => 0x518c, 0xe2 => 0x6d4b, 0xe3 => 0x5c42, 0xe4 => 0x8e6d, + 0xe5 => 0x63d2, 0xe6 => 0x53c9, 0xe7 => 0x832c, 0xe8 => 0x8336, + 0xe9 => 0x67e5, 0xea => 0x78b4, 0xeb => 0x643d, 0xec => 0x5bdf, + 0xed => 0x5c94, 0xee => 0x5dee, 0xef => 0x8be7, 0xf0 => 0x62c6, + 0xf1 => 0x67f4, 0xf2 => 0x8c7a, 0xf3 => 0x6400, 0xf4 => 0x63ba, + 0xf5 => 0x8749, 0xf6 => 0x998b, 0xf7 => 0x8c17, 0xf8 => 0x7f20, + 0xf9 => 0x94f2, 0xfa => 0x4ea7, 0xfb => 0x9610, 0xfc => 0x98a4, + 0xfd => 0x660c, 0xfe => 0x7316, + }, + 0xb3 => { + 0xa1 => 0x573a, 0xa2 => 0x5c1d, 0xa3 => 0x5e38, 0xa4 => 0x957f, + 0xa5 => 0x507f, 0xa6 => 0x80a0, 0xa7 => 0x5382, 0xa8 => 0x655e, + 0xa9 => 0x7545, 0xaa => 0x5531, 0xab => 0x5021, 0xac => 0x8d85, + 0xad => 0x6284, 0xae => 0x949e, 0xaf => 0x671d, 0xb0 => 0x5632, + 0xb1 => 0x6f6e, 0xb2 => 0x5de2, 0xb3 => 0x5435, 0xb4 => 0x7092, + 0xb5 => 0x8f66, 0xb6 => 0x626f, 0xb7 => 0x64a4, 0xb8 => 0x63a3, + 0xb9 => 0x5f7b, 0xba => 0x6f88, 0xbb => 0x90f4, 0xbc => 0x81e3, + 0xbd => 0x8fb0, 0xbe => 0x5c18, 0xbf => 0x6668, 0xc0 => 0x5ff1, + 0xc1 => 0x6c89, 0xc2 => 0x9648, 0xc3 => 0x8d81, 0xc4 => 0x886c, + 0xc5 => 0x6491, 0xc6 => 0x79f0, 0xc7 => 0x57ce, 0xc8 => 0x6a59, + 0xc9 => 0x6210, 0xca => 0x5448, 0xcb => 0x4e58, 0xcc => 0x7a0b, + 0xcd => 0x60e9, 0xce => 0x6f84, 0xcf => 0x8bda, 0xd0 => 0x627f, + 0xd1 => 0x901e, 0xd2 => 0x9a8b, 0xd3 => 0x79e4, 0xd4 => 0x5403, + 0xd5 => 0x75f4, 0xd6 => 0x6301, 0xd7 => 0x5319, 0xd8 => 0x6c60, + 0xd9 => 0x8fdf, 0xda => 0x5f1b, 0xdb => 0x9a70, 0xdc => 0x803b, + 0xdd => 0x9f7f, 0xde => 0x4f88, 0xdf => 0x5c3a, 0xe0 => 0x8d64, + 0xe1 => 0x7fc5, 0xe2 => 0x65a5, 0xe3 => 0x70bd, 0xe4 => 0x5145, + 0xe5 => 0x51b2, 0xe6 => 0x866b, 0xe7 => 0x5d07, 0xe8 => 0x5ba0, + 0xe9 => 0x62bd, 0xea => 0x916c, 0xeb => 0x7574, 0xec => 0x8e0c, + 0xed => 0x7a20, 0xee => 0x6101, 0xef => 0x7b79, 0xf0 => 0x4ec7, + 0xf1 => 0x7ef8, 0xf2 => 0x7785, 0xf3 => 0x4e11, 0xf4 => 0x81ed, + 0xf5 => 0x521d, 0xf6 => 0x51fa, 0xf7 => 0x6a71, 0xf8 => 0x53a8, + 0xf9 => 0x8e87, 0xfa => 0x9504, 0xfb => 0x96cf, 0xfc => 0x6ec1, + 0xfd => 0x9664, 0xfe => 0x695a, + }, + 0xb4 => { + 0xa1 => 0x7840, 0xa2 => 0x50a8, 0xa3 => 0x77d7, 0xa4 => 0x6410, + 0xa5 => 0x89e6, 0xa6 => 0x5904, 0xa7 => 0x63e3, 0xa8 => 0x5ddd, + 0xa9 => 0x7a7f, 0xaa => 0x693d, 0xab => 0x4f20, 0xac => 0x8239, + 0xad => 0x5598, 0xae => 0x4e32, 0xaf => 0x75ae, 0xb0 => 0x7a97, + 0xb1 => 0x5e62, 0xb2 => 0x5e8a, 0xb3 => 0x95ef, 0xb4 => 0x521b, + 0xb5 => 0x5439, 0xb6 => 0x708a, 0xb7 => 0x6376, 0xb8 => 0x9524, + 0xb9 => 0x5782, 0xba => 0x6625, 0xbb => 0x693f, 0xbc => 0x9187, + 0xbd => 0x5507, 0xbe => 0x6df3, 0xbf => 0x7eaf, 0xc0 => 0x8822, + 0xc1 => 0x6233, 0xc2 => 0x7ef0, 0xc3 => 0x75b5, 0xc4 => 0x8328, + 0xc5 => 0x78c1, 0xc6 => 0x96cc, 0xc7 => 0x8f9e, 0xc8 => 0x6148, + 0xc9 => 0x74f7, 0xca => 0x8bcd, 0xcb => 0x6b64, 0xcc => 0x523a, + 0xcd => 0x8d50, 0xce => 0x6b21, 0xcf => 0x806a, 0xd0 => 0x8471, + 0xd1 => 0x56f1, 0xd2 => 0x5306, 0xd3 => 0x4ece, 0xd4 => 0x4e1b, + 0xd5 => 0x51d1, 0xd6 => 0x7c97, 0xd7 => 0x918b, 0xd8 => 0x7c07, + 0xd9 => 0x4fc3, 0xda => 0x8e7f, 0xdb => 0x7be1, 0xdc => 0x7a9c, + 0xdd => 0x6467, 0xde => 0x5d14, 0xdf => 0x50ac, 0xe0 => 0x8106, + 0xe1 => 0x7601, 0xe2 => 0x7cb9, 0xe3 => 0x6dec, 0xe4 => 0x7fe0, + 0xe5 => 0x6751, 0xe6 => 0x5b58, 0xe7 => 0x5bf8, 0xe8 => 0x78cb, + 0xe9 => 0x64ae, 0xea => 0x6413, 0xeb => 0x63aa, 0xec => 0x632b, + 0xed => 0x9519, 0xee => 0x642d, 0xef => 0x8fbe, 0xf0 => 0x7b54, + 0xf1 => 0x7629, 0xf2 => 0x6253, 0xf3 => 0x5927, 0xf4 => 0x5446, + 0xf5 => 0x6b79, 0xf6 => 0x50a3, 0xf7 => 0x6234, 0xf8 => 0x5e26, + 0xf9 => 0x6b86, 0xfa => 0x4ee3, 0xfb => 0x8d37, 0xfc => 0x888b, + 0xfd => 0x5f85, 0xfe => 0x902e, + }, + 0xb5 => { + 0xa1 => 0x6020, 0xa2 => 0x803d, 0xa3 => 0x62c5, 0xa4 => 0x4e39, + 0xa5 => 0x5355, 0xa6 => 0x90f8, 0xa7 => 0x63b8, 0xa8 => 0x80c6, + 0xa9 => 0x65e6, 0xaa => 0x6c2e, 0xab => 0x4f46, 0xac => 0x60ee, + 0xad => 0x6de1, 0xae => 0x8bde, 0xaf => 0x5f39, 0xb0 => 0x86cb, + 0xb1 => 0x5f53, 0xb2 => 0x6321, 0xb3 => 0x515a, 0xb4 => 0x8361, + 0xb5 => 0x6863, 0xb6 => 0x5200, 0xb7 => 0x6363, 0xb8 => 0x8e48, + 0xb9 => 0x5012, 0xba => 0x5c9b, 0xbb => 0x7977, 0xbc => 0x5bfc, + 0xbd => 0x5230, 0xbe => 0x7a3b, 0xbf => 0x60bc, 0xc0 => 0x9053, + 0xc1 => 0x76d7, 0xc2 => 0x5fb7, 0xc3 => 0x5f97, 0xc4 => 0x7684, + 0xc5 => 0x8e6c, 0xc6 => 0x706f, 0xc7 => 0x767b, 0xc8 => 0x7b49, + 0xc9 => 0x77aa, 0xca => 0x51f3, 0xcb => 0x9093, 0xcc => 0x5824, + 0xcd => 0x4f4e, 0xce => 0x6ef4, 0xcf => 0x8fea, 0xd0 => 0x654c, + 0xd1 => 0x7b1b, 0xd2 => 0x72c4, 0xd3 => 0x6da4, 0xd4 => 0x7fdf, + 0xd5 => 0x5ae1, 0xd6 => 0x62b5, 0xd7 => 0x5e95, 0xd8 => 0x5730, + 0xd9 => 0x8482, 0xda => 0x7b2c, 0xdb => 0x5e1d, 0xdc => 0x5f1f, + 0xdd => 0x9012, 0xde => 0x7f14, 0xdf => 0x98a0, 0xe0 => 0x6382, + 0xe1 => 0x6ec7, 0xe2 => 0x7898, 0xe3 => 0x70b9, 0xe4 => 0x5178, + 0xe5 => 0x975b, 0xe6 => 0x57ab, 0xe7 => 0x7535, 0xe8 => 0x4f43, + 0xe9 => 0x7538, 0xea => 0x5e97, 0xeb => 0x60e6, 0xec => 0x5960, + 0xed => 0x6dc0, 0xee => 0x6bbf, 0xef => 0x7889, 0xf0 => 0x53fc, + 0xf1 => 0x96d5, 0xf2 => 0x51cb, 0xf3 => 0x5201, 0xf4 => 0x6389, + 0xf5 => 0x540a, 0xf6 => 0x9493, 0xf7 => 0x8c03, 0xf8 => 0x8dcc, + 0xf9 => 0x7239, 0xfa => 0x789f, 0xfb => 0x8776, 0xfc => 0x8fed, + 0xfd => 0x8c0d, 0xfe => 0x53e0, + }, + 0xb6 => { + 0xa1 => 0x4e01, 0xa2 => 0x76ef, 0xa3 => 0x53ee, 0xa4 => 0x9489, + 0xa5 => 0x9876, 0xa6 => 0x9f0e, 0xa7 => 0x952d, 0xa8 => 0x5b9a, + 0xa9 => 0x8ba2, 0xaa => 0x4e22, 0xab => 0x4e1c, 0xac => 0x51ac, + 0xad => 0x8463, 0xae => 0x61c2, 0xaf => 0x52a8, 0xb0 => 0x680b, + 0xb1 => 0x4f97, 0xb2 => 0x606b, 0xb3 => 0x51bb, 0xb4 => 0x6d1e, + 0xb5 => 0x515c, 0xb6 => 0x6296, 0xb7 => 0x6597, 0xb8 => 0x9661, + 0xb9 => 0x8c46, 0xba => 0x9017, 0xbb => 0x75d8, 0xbc => 0x90fd, + 0xbd => 0x7763, 0xbe => 0x6bd2, 0xbf => 0x728a, 0xc0 => 0x72ec, + 0xc1 => 0x8bfb, 0xc2 => 0x5835, 0xc3 => 0x7779, 0xc4 => 0x8d4c, + 0xc5 => 0x675c, 0xc6 => 0x9540, 0xc7 => 0x809a, 0xc8 => 0x5ea6, + 0xc9 => 0x6e21, 0xca => 0x5992, 0xcb => 0x7aef, 0xcc => 0x77ed, + 0xcd => 0x953b, 0xce => 0x6bb5, 0xcf => 0x65ad, 0xd0 => 0x7f0e, + 0xd1 => 0x5806, 0xd2 => 0x5151, 0xd3 => 0x961f, 0xd4 => 0x5bf9, + 0xd5 => 0x58a9, 0xd6 => 0x5428, 0xd7 => 0x8e72, 0xd8 => 0x6566, + 0xd9 => 0x987f, 0xda => 0x56e4, 0xdb => 0x949d, 0xdc => 0x76fe, + 0xdd => 0x9041, 0xde => 0x6387, 0xdf => 0x54c6, 0xe0 => 0x591a, + 0xe1 => 0x593a, 0xe2 => 0x579b, 0xe3 => 0x8eb2, 0xe4 => 0x6735, + 0xe5 => 0x8dfa, 0xe6 => 0x8235, 0xe7 => 0x5241, 0xe8 => 0x60f0, + 0xe9 => 0x5815, 0xea => 0x86fe, 0xeb => 0x5ce8, 0xec => 0x9e45, + 0xed => 0x4fc4, 0xee => 0x989d, 0xef => 0x8bb9, 0xf0 => 0x5a25, + 0xf1 => 0x6076, 0xf2 => 0x5384, 0xf3 => 0x627c, 0xf4 => 0x904f, + 0xf5 => 0x9102, 0xf6 => 0x997f, 0xf7 => 0x6069, 0xf8 => 0x800c, + 0xf9 => 0x513f, 0xfa => 0x8033, 0xfb => 0x5c14, 0xfc => 0x9975, + 0xfd => 0x6d31, 0xfe => 0x4e8c, + }, + 0xb7 => { + 0xa1 => 0x8d30, 0xa2 => 0x53d1, 0xa3 => 0x7f5a, 0xa4 => 0x7b4f, + 0xa5 => 0x4f10, 0xa6 => 0x4e4f, 0xa7 => 0x9600, 0xa8 => 0x6cd5, + 0xa9 => 0x73d0, 0xaa => 0x85e9, 0xab => 0x5e06, 0xac => 0x756a, + 0xad => 0x7ffb, 0xae => 0x6a0a, 0xaf => 0x77fe, 0xb0 => 0x9492, + 0xb1 => 0x7e41, 0xb2 => 0x51e1, 0xb3 => 0x70e6, 0xb4 => 0x53cd, + 0xb5 => 0x8fd4, 0xb6 => 0x8303, 0xb7 => 0x8d29, 0xb8 => 0x72af, + 0xb9 => 0x996d, 0xba => 0x6cdb, 0xbb => 0x574a, 0xbc => 0x82b3, + 0xbd => 0x65b9, 0xbe => 0x80aa, 0xbf => 0x623f, 0xc0 => 0x9632, + 0xc1 => 0x59a8, 0xc2 => 0x4eff, 0xc3 => 0x8bbf, 0xc4 => 0x7eba, + 0xc5 => 0x653e, 0xc6 => 0x83f2, 0xc7 => 0x975e, 0xc8 => 0x5561, + 0xc9 => 0x98de, 0xca => 0x80a5, 0xcb => 0x532a, 0xcc => 0x8bfd, + 0xcd => 0x5420, 0xce => 0x80ba, 0xcf => 0x5e9f, 0xd0 => 0x6cb8, + 0xd1 => 0x8d39, 0xd2 => 0x82ac, 0xd3 => 0x915a, 0xd4 => 0x5429, + 0xd5 => 0x6c1b, 0xd6 => 0x5206, 0xd7 => 0x7eb7, 0xd8 => 0x575f, + 0xd9 => 0x711a, 0xda => 0x6c7e, 0xdb => 0x7c89, 0xdc => 0x594b, + 0xdd => 0x4efd, 0xde => 0x5fff, 0xdf => 0x6124, 0xe0 => 0x7caa, + 0xe1 => 0x4e30, 0xe2 => 0x5c01, 0xe3 => 0x67ab, 0xe4 => 0x8702, + 0xe5 => 0x5cf0, 0xe6 => 0x950b, 0xe7 => 0x98ce, 0xe8 => 0x75af, + 0xe9 => 0x70fd, 0xea => 0x9022, 0xeb => 0x51af, 0xec => 0x7f1d, + 0xed => 0x8bbd, 0xee => 0x5949, 0xef => 0x51e4, 0xf0 => 0x4f5b, + 0xf1 => 0x5426, 0xf2 => 0x592b, 0xf3 => 0x6577, 0xf4 => 0x80a4, + 0xf5 => 0x5b75, 0xf6 => 0x6276, 0xf7 => 0x62c2, 0xf8 => 0x8f90, + 0xf9 => 0x5e45, 0xfa => 0x6c1f, 0xfb => 0x7b26, 0xfc => 0x4f0f, + 0xfd => 0x4fd8, 0xfe => 0x670d, + }, + 0xb8 => { + 0xa1 => 0x6d6e, 0xa2 => 0x6daa, 0xa3 => 0x798f, 0xa4 => 0x88b1, + 0xa5 => 0x5f17, 0xa6 => 0x752b, 0xa7 => 0x629a, 0xa8 => 0x8f85, + 0xa9 => 0x4fef, 0xaa => 0x91dc, 0xab => 0x65a7, 0xac => 0x812f, + 0xad => 0x8151, 0xae => 0x5e9c, 0xaf => 0x8150, 0xb0 => 0x8d74, + 0xb1 => 0x526f, 0xb2 => 0x8986, 0xb3 => 0x8d4b, 0xb4 => 0x590d, + 0xb5 => 0x5085, 0xb6 => 0x4ed8, 0xb7 => 0x961c, 0xb8 => 0x7236, + 0xb9 => 0x8179, 0xba => 0x8d1f, 0xbb => 0x5bcc, 0xbc => 0x8ba3, + 0xbd => 0x9644, 0xbe => 0x5987, 0xbf => 0x7f1a, 0xc0 => 0x5490, + 0xc1 => 0x5676, 0xc2 => 0x560e, 0xc3 => 0x8be5, 0xc4 => 0x6539, + 0xc5 => 0x6982, 0xc6 => 0x9499, 0xc7 => 0x76d6, 0xc8 => 0x6e89, + 0xc9 => 0x5e72, 0xca => 0x7518, 0xcb => 0x6746, 0xcc => 0x67d1, + 0xcd => 0x7aff, 0xce => 0x809d, 0xcf => 0x8d76, 0xd0 => 0x611f, + 0xd1 => 0x79c6, 0xd2 => 0x6562, 0xd3 => 0x8d63, 0xd4 => 0x5188, + 0xd5 => 0x521a, 0xd6 => 0x94a2, 0xd7 => 0x7f38, 0xd8 => 0x809b, + 0xd9 => 0x7eb2, 0xda => 0x5c97, 0xdb => 0x6e2f, 0xdc => 0x6760, + 0xdd => 0x7bd9, 0xde => 0x768b, 0xdf => 0x9ad8, 0xe0 => 0x818f, + 0xe1 => 0x7f94, 0xe2 => 0x7cd5, 0xe3 => 0x641e, 0xe4 => 0x9550, + 0xe5 => 0x7a3f, 0xe6 => 0x544a, 0xe7 => 0x54e5, 0xe8 => 0x6b4c, + 0xe9 => 0x6401, 0xea => 0x6208, 0xeb => 0x9e3d, 0xec => 0x80f3, + 0xed => 0x7599, 0xee => 0x5272, 0xef => 0x9769, 0xf0 => 0x845b, + 0xf1 => 0x683c, 0xf2 => 0x86e4, 0xf3 => 0x9601, 0xf4 => 0x9694, + 0xf5 => 0x94ec, 0xf6 => 0x4e2a, 0xf7 => 0x5404, 0xf8 => 0x7ed9, + 0xf9 => 0x6839, 0xfa => 0x8ddf, 0xfb => 0x8015, 0xfc => 0x66f4, + 0xfd => 0x5e9a, 0xfe => 0x7fb9, + }, + 0xb9 => { + 0xa1 => 0x57c2, 0xa2 => 0x803f, 0xa3 => 0x6897, 0xa4 => 0x5de5, + 0xa5 => 0x653b, 0xa6 => 0x529f, 0xa7 => 0x606d, 0xa8 => 0x9f9a, + 0xa9 => 0x4f9b, 0xaa => 0x8eac, 0xab => 0x516c, 0xac => 0x5bab, + 0xad => 0x5f13, 0xae => 0x5de9, 0xaf => 0x6c5e, 0xb0 => 0x62f1, + 0xb1 => 0x8d21, 0xb2 => 0x5171, 0xb3 => 0x94a9, 0xb4 => 0x52fe, + 0xb5 => 0x6c9f, 0xb6 => 0x82df, 0xb7 => 0x72d7, 0xb8 => 0x57a2, + 0xb9 => 0x6784, 0xba => 0x8d2d, 0xbb => 0x591f, 0xbc => 0x8f9c, + 0xbd => 0x83c7, 0xbe => 0x5495, 0xbf => 0x7b8d, 0xc0 => 0x4f30, + 0xc1 => 0x6cbd, 0xc2 => 0x5b64, 0xc3 => 0x59d1, 0xc4 => 0x9f13, + 0xc5 => 0x53e4, 0xc6 => 0x86ca, 0xc7 => 0x9aa8, 0xc8 => 0x8c37, + 0xc9 => 0x80a1, 0xca => 0x6545, 0xcb => 0x987e, 0xcc => 0x56fa, + 0xcd => 0x96c7, 0xce => 0x522e, 0xcf => 0x74dc, 0xd0 => 0x5250, + 0xd1 => 0x5be1, 0xd2 => 0x6302, 0xd3 => 0x8902, 0xd4 => 0x4e56, + 0xd5 => 0x62d0, 0xd6 => 0x602a, 0xd7 => 0x68fa, 0xd8 => 0x5173, + 0xd9 => 0x5b98, 0xda => 0x51a0, 0xdb => 0x89c2, 0xdc => 0x7ba1, + 0xdd => 0x9986, 0xde => 0x7f50, 0xdf => 0x60ef, 0xe0 => 0x704c, + 0xe1 => 0x8d2f, 0xe2 => 0x5149, 0xe3 => 0x5e7f, 0xe4 => 0x901b, + 0xe5 => 0x7470, 0xe6 => 0x89c4, 0xe7 => 0x572d, 0xe8 => 0x7845, + 0xe9 => 0x5f52, 0xea => 0x9f9f, 0xeb => 0x95fa, 0xec => 0x8f68, + 0xed => 0x9b3c, 0xee => 0x8be1, 0xef => 0x7678, 0xf0 => 0x6842, + 0xf1 => 0x67dc, 0xf2 => 0x8dea, 0xf3 => 0x8d35, 0xf4 => 0x523d, + 0xf5 => 0x8f8a, 0xf6 => 0x6eda, 0xf7 => 0x68cd, 0xf8 => 0x9505, + 0xf9 => 0x90ed, 0xfa => 0x56fd, 0xfb => 0x679c, 0xfc => 0x88f9, + 0xfd => 0x8fc7, 0xfe => 0x54c8, + }, + 0xba => { + 0xa1 => 0x9ab8, 0xa2 => 0x5b69, 0xa3 => 0x6d77, 0xa4 => 0x6c26, + 0xa5 => 0x4ea5, 0xa6 => 0x5bb3, 0xa7 => 0x9a87, 0xa8 => 0x9163, + 0xa9 => 0x61a8, 0xaa => 0x90af, 0xab => 0x97e9, 0xac => 0x542b, + 0xad => 0x6db5, 0xae => 0x5bd2, 0xaf => 0x51fd, 0xb0 => 0x558a, + 0xb1 => 0x7f55, 0xb2 => 0x7ff0, 0xb3 => 0x64bc, 0xb4 => 0x634d, + 0xb5 => 0x65f1, 0xb6 => 0x61be, 0xb7 => 0x608d, 0xb8 => 0x710a, + 0xb9 => 0x6c57, 0xba => 0x6c49, 0xbb => 0x592f, 0xbc => 0x676d, + 0xbd => 0x822a, 0xbe => 0x58d5, 0xbf => 0x568e, 0xc0 => 0x8c6a, + 0xc1 => 0x6beb, 0xc2 => 0x90dd, 0xc3 => 0x597d, 0xc4 => 0x8017, + 0xc5 => 0x53f7, 0xc6 => 0x6d69, 0xc7 => 0x5475, 0xc8 => 0x559d, + 0xc9 => 0x8377, 0xca => 0x83cf, 0xcb => 0x6838, 0xcc => 0x79be, + 0xcd => 0x548c, 0xce => 0x4f55, 0xcf => 0x5408, 0xd0 => 0x76d2, + 0xd1 => 0x8c89, 0xd2 => 0x9602, 0xd3 => 0x6cb3, 0xd4 => 0x6db8, + 0xd5 => 0x8d6b, 0xd6 => 0x8910, 0xd7 => 0x9e64, 0xd8 => 0x8d3a, + 0xd9 => 0x563f, 0xda => 0x9ed1, 0xdb => 0x75d5, 0xdc => 0x5f88, + 0xdd => 0x72e0, 0xde => 0x6068, 0xdf => 0x54fc, 0xe0 => 0x4ea8, + 0xe1 => 0x6a2a, 0xe2 => 0x8861, 0xe3 => 0x6052, 0xe4 => 0x8f70, + 0xe5 => 0x54c4, 0xe6 => 0x70d8, 0xe7 => 0x8679, 0xe8 => 0x9e3f, + 0xe9 => 0x6d2a, 0xea => 0x5b8f, 0xeb => 0x5f18, 0xec => 0x7ea2, + 0xed => 0x5589, 0xee => 0x4faf, 0xef => 0x7334, 0xf0 => 0x543c, + 0xf1 => 0x539a, 0xf2 => 0x5019, 0xf3 => 0x540e, 0xf4 => 0x547c, + 0xf5 => 0x4e4e, 0xf6 => 0x5ffd, 0xf7 => 0x745a, 0xf8 => 0x58f6, + 0xf9 => 0x846b, 0xfa => 0x80e1, 0xfb => 0x8774, 0xfc => 0x72d0, + 0xfd => 0x7cca, 0xfe => 0x6e56, + }, + 0xbb => { + 0xa1 => 0x5f27, 0xa2 => 0x864e, 0xa3 => 0x552c, 0xa4 => 0x62a4, + 0xa5 => 0x4e92, 0xa6 => 0x6caa, 0xa7 => 0x6237, 0xa8 => 0x82b1, + 0xa9 => 0x54d7, 0xaa => 0x534e, 0xab => 0x733e, 0xac => 0x6ed1, + 0xad => 0x753b, 0xae => 0x5212, 0xaf => 0x5316, 0xb0 => 0x8bdd, + 0xb1 => 0x69d0, 0xb2 => 0x5f8a, 0xb3 => 0x6000, 0xb4 => 0x6dee, + 0xb5 => 0x574f, 0xb6 => 0x6b22, 0xb7 => 0x73af, 0xb8 => 0x6853, + 0xb9 => 0x8fd8, 0xba => 0x7f13, 0xbb => 0x6362, 0xbc => 0x60a3, + 0xbd => 0x5524, 0xbe => 0x75ea, 0xbf => 0x8c62, 0xc0 => 0x7115, + 0xc1 => 0x6da3, 0xc2 => 0x5ba6, 0xc3 => 0x5e7b, 0xc4 => 0x8352, + 0xc5 => 0x614c, 0xc6 => 0x9ec4, 0xc7 => 0x78fa, 0xc8 => 0x8757, + 0xc9 => 0x7c27, 0xca => 0x7687, 0xcb => 0x51f0, 0xcc => 0x60f6, + 0xcd => 0x714c, 0xce => 0x6643, 0xcf => 0x5e4c, 0xd0 => 0x604d, + 0xd1 => 0x8c0e, 0xd2 => 0x7070, 0xd3 => 0x6325, 0xd4 => 0x8f89, + 0xd5 => 0x5fbd, 0xd6 => 0x6062, 0xd7 => 0x86d4, 0xd8 => 0x56de, + 0xd9 => 0x6bc1, 0xda => 0x6094, 0xdb => 0x6167, 0xdc => 0x5349, + 0xdd => 0x60e0, 0xde => 0x6666, 0xdf => 0x8d3f, 0xe0 => 0x79fd, + 0xe1 => 0x4f1a, 0xe2 => 0x70e9, 0xe3 => 0x6c47, 0xe4 => 0x8bb3, + 0xe5 => 0x8bf2, 0xe6 => 0x7ed8, 0xe7 => 0x8364, 0xe8 => 0x660f, + 0xe9 => 0x5a5a, 0xea => 0x9b42, 0xeb => 0x6d51, 0xec => 0x6df7, + 0xed => 0x8c41, 0xee => 0x6d3b, 0xef => 0x4f19, 0xf0 => 0x706b, + 0xf1 => 0x83b7, 0xf2 => 0x6216, 0xf3 => 0x60d1, 0xf4 => 0x970d, + 0xf5 => 0x8d27, 0xf6 => 0x7978, 0xf7 => 0x51fb, 0xf8 => 0x573e, + 0xf9 => 0x57fa, 0xfa => 0x673a, 0xfb => 0x7578, 0xfc => 0x7a3d, + 0xfd => 0x79ef, 0xfe => 0x7b95, + }, + 0xbc => { + 0xa1 => 0x808c, 0xa2 => 0x9965, 0xa3 => 0x8ff9, 0xa4 => 0x6fc0, + 0xa5 => 0x8ba5, 0xa6 => 0x9e21, 0xa7 => 0x59ec, 0xa8 => 0x7ee9, + 0xa9 => 0x7f09, 0xaa => 0x5409, 0xab => 0x6781, 0xac => 0x68d8, + 0xad => 0x8f91, 0xae => 0x7c4d, 0xaf => 0x96c6, 0xb0 => 0x53ca, + 0xb1 => 0x6025, 0xb2 => 0x75be, 0xb3 => 0x6c72, 0xb4 => 0x5373, + 0xb5 => 0x5ac9, 0xb6 => 0x7ea7, 0xb7 => 0x6324, 0xb8 => 0x51e0, + 0xb9 => 0x810a, 0xba => 0x5df1, 0xbb => 0x84df, 0xbc => 0x6280, + 0xbd => 0x5180, 0xbe => 0x5b63, 0xbf => 0x4f0e, 0xc0 => 0x796d, + 0xc1 => 0x5242, 0xc2 => 0x60b8, 0xc3 => 0x6d4e, 0xc4 => 0x5bc4, + 0xc5 => 0x5bc2, 0xc6 => 0x8ba1, 0xc7 => 0x8bb0, 0xc8 => 0x65e2, + 0xc9 => 0x5fcc, 0xca => 0x9645, 0xcb => 0x5993, 0xcc => 0x7ee7, + 0xcd => 0x7eaa, 0xce => 0x5609, 0xcf => 0x67b7, 0xd0 => 0x5939, + 0xd1 => 0x4f73, 0xd2 => 0x5bb6, 0xd3 => 0x52a0, 0xd4 => 0x835a, + 0xd5 => 0x988a, 0xd6 => 0x8d3e, 0xd7 => 0x7532, 0xd8 => 0x94be, + 0xd9 => 0x5047, 0xda => 0x7a3c, 0xdb => 0x4ef7, 0xdc => 0x67b6, + 0xdd => 0x9a7e, 0xde => 0x5ac1, 0xdf => 0x6b7c, 0xe0 => 0x76d1, + 0xe1 => 0x575a, 0xe2 => 0x5c16, 0xe3 => 0x7b3a, 0xe4 => 0x95f4, + 0xe5 => 0x714e, 0xe6 => 0x517c, 0xe7 => 0x80a9, 0xe8 => 0x8270, + 0xe9 => 0x5978, 0xea => 0x7f04, 0xeb => 0x8327, 0xec => 0x68c0, + 0xed => 0x67ec, 0xee => 0x78b1, 0xef => 0x7877, 0xf0 => 0x62e3, + 0xf1 => 0x6361, 0xf2 => 0x7b80, 0xf3 => 0x4fed, 0xf4 => 0x526a, + 0xf5 => 0x51cf, 0xf6 => 0x8350, 0xf7 => 0x69db, 0xf8 => 0x9274, + 0xf9 => 0x8df5, 0xfa => 0x8d31, 0xfb => 0x89c1, 0xfc => 0x952e, + 0xfd => 0x7bad, 0xfe => 0x4ef6, + }, + 0xbd => { + 0xa1 => 0x5065, 0xa2 => 0x8230, 0xa3 => 0x5251, 0xa4 => 0x996f, + 0xa5 => 0x6e10, 0xa6 => 0x6e85, 0xa7 => 0x6da7, 0xa8 => 0x5efa, + 0xa9 => 0x50f5, 0xaa => 0x59dc, 0xab => 0x5c06, 0xac => 0x6d46, + 0xad => 0x6c5f, 0xae => 0x7586, 0xaf => 0x848b, 0xb0 => 0x6868, + 0xb1 => 0x5956, 0xb2 => 0x8bb2, 0xb3 => 0x5320, 0xb4 => 0x9171, + 0xb5 => 0x964d, 0xb6 => 0x8549, 0xb7 => 0x6912, 0xb8 => 0x7901, + 0xb9 => 0x7126, 0xba => 0x80f6, 0xbb => 0x4ea4, 0xbc => 0x90ca, + 0xbd => 0x6d47, 0xbe => 0x9a84, 0xbf => 0x5a07, 0xc0 => 0x56bc, + 0xc1 => 0x6405, 0xc2 => 0x94f0, 0xc3 => 0x77eb, 0xc4 => 0x4fa5, + 0xc5 => 0x811a, 0xc6 => 0x72e1, 0xc7 => 0x89d2, 0xc8 => 0x997a, + 0xc9 => 0x7f34, 0xca => 0x7ede, 0xcb => 0x527f, 0xcc => 0x6559, + 0xcd => 0x9175, 0xce => 0x8f7f, 0xcf => 0x8f83, 0xd0 => 0x53eb, + 0xd1 => 0x7a96, 0xd2 => 0x63ed, 0xd3 => 0x63a5, 0xd4 => 0x7686, + 0xd5 => 0x79f8, 0xd6 => 0x8857, 0xd7 => 0x9636, 0xd8 => 0x622a, + 0xd9 => 0x52ab, 0xda => 0x8282, 0xdb => 0x6854, 0xdc => 0x6770, + 0xdd => 0x6377, 0xde => 0x776b, 0xdf => 0x7aed, 0xe0 => 0x6d01, + 0xe1 => 0x7ed3, 0xe2 => 0x89e3, 0xe3 => 0x59d0, 0xe4 => 0x6212, + 0xe5 => 0x85c9, 0xe6 => 0x82a5, 0xe7 => 0x754c, 0xe8 => 0x501f, + 0xe9 => 0x4ecb, 0xea => 0x75a5, 0xeb => 0x8beb, 0xec => 0x5c4a, + 0xed => 0x5dfe, 0xee => 0x7b4b, 0xef => 0x65a4, 0xf0 => 0x91d1, + 0xf1 => 0x4eca, 0xf2 => 0x6d25, 0xf3 => 0x895f, 0xf4 => 0x7d27, + 0xf5 => 0x9526, 0xf6 => 0x4ec5, 0xf7 => 0x8c28, 0xf8 => 0x8fdb, + 0xf9 => 0x9773, 0xfa => 0x664b, 0xfb => 0x7981, 0xfc => 0x8fd1, + 0xfd => 0x70ec, 0xfe => 0x6d78, + }, + 0xbe => { + 0xa1 => 0x5c3d, 0xa2 => 0x52b2, 0xa3 => 0x8346, 0xa4 => 0x5162, + 0xa5 => 0x830e, 0xa6 => 0x775b, 0xa7 => 0x6676, 0xa8 => 0x9cb8, + 0xa9 => 0x4eac, 0xaa => 0x60ca, 0xab => 0x7cbe, 0xac => 0x7cb3, + 0xad => 0x7ecf, 0xae => 0x4e95, 0xaf => 0x8b66, 0xb0 => 0x666f, + 0xb1 => 0x9888, 0xb2 => 0x9759, 0xb3 => 0x5883, 0xb4 => 0x656c, + 0xb5 => 0x955c, 0xb6 => 0x5f84, 0xb7 => 0x75c9, 0xb8 => 0x9756, + 0xb9 => 0x7adf, 0xba => 0x7ade, 0xbb => 0x51c0, 0xbc => 0x70af, + 0xbd => 0x7a98, 0xbe => 0x63ea, 0xbf => 0x7a76, 0xc0 => 0x7ea0, + 0xc1 => 0x7396, 0xc2 => 0x97ed, 0xc3 => 0x4e45, 0xc4 => 0x7078, + 0xc5 => 0x4e5d, 0xc6 => 0x9152, 0xc7 => 0x53a9, 0xc8 => 0x6551, + 0xc9 => 0x65e7, 0xca => 0x81fc, 0xcb => 0x8205, 0xcc => 0x548e, + 0xcd => 0x5c31, 0xce => 0x759a, 0xcf => 0x97a0, 0xd0 => 0x62d8, + 0xd1 => 0x72d9, 0xd2 => 0x75bd, 0xd3 => 0x5c45, 0xd4 => 0x9a79, + 0xd5 => 0x83ca, 0xd6 => 0x5c40, 0xd7 => 0x5480, 0xd8 => 0x77e9, + 0xd9 => 0x4e3e, 0xda => 0x6cae, 0xdb => 0x805a, 0xdc => 0x62d2, + 0xdd => 0x636e, 0xde => 0x5de8, 0xdf => 0x5177, 0xe0 => 0x8ddd, + 0xe1 => 0x8e1e, 0xe2 => 0x952f, 0xe3 => 0x4ff1, 0xe4 => 0x53e5, + 0xe5 => 0x60e7, 0xe6 => 0x70ac, 0xe7 => 0x5267, 0xe8 => 0x6350, + 0xe9 => 0x9e43, 0xea => 0x5a1f, 0xeb => 0x5026, 0xec => 0x7737, + 0xed => 0x5377, 0xee => 0x7ee2, 0xef => 0x6485, 0xf0 => 0x652b, + 0xf1 => 0x6289, 0xf2 => 0x6398, 0xf3 => 0x5014, 0xf4 => 0x7235, + 0xf5 => 0x89c9, 0xf6 => 0x51b3, 0xf7 => 0x8bc0, 0xf8 => 0x7edd, + 0xf9 => 0x5747, 0xfa => 0x83cc, 0xfb => 0x94a7, 0xfc => 0x519b, + 0xfd => 0x541b, 0xfe => 0x5cfb, + }, + 0xbf => { + 0xa1 => 0x4fca, 0xa2 => 0x7ae3, 0xa3 => 0x6d5a, 0xa4 => 0x90e1, + 0xa5 => 0x9a8f, 0xa6 => 0x5580, 0xa7 => 0x5496, 0xa8 => 0x5361, + 0xa9 => 0x54af, 0xaa => 0x5f00, 0xab => 0x63e9, 0xac => 0x6977, + 0xad => 0x51ef, 0xae => 0x6168, 0xaf => 0x520a, 0xb0 => 0x582a, + 0xb1 => 0x52d8, 0xb2 => 0x574e, 0xb3 => 0x780d, 0xb4 => 0x770b, + 0xb5 => 0x5eb7, 0xb6 => 0x6177, 0xb7 => 0x7ce0, 0xb8 => 0x625b, + 0xb9 => 0x6297, 0xba => 0x4ea2, 0xbb => 0x7095, 0xbc => 0x8003, + 0xbd => 0x62f7, 0xbe => 0x70e4, 0xbf => 0x9760, 0xc0 => 0x5777, + 0xc1 => 0x82db, 0xc2 => 0x67ef, 0xc3 => 0x68f5, 0xc4 => 0x78d5, + 0xc5 => 0x9897, 0xc6 => 0x79d1, 0xc7 => 0x58f3, 0xc8 => 0x54b3, + 0xc9 => 0x53ef, 0xca => 0x6e34, 0xcb => 0x514b, 0xcc => 0x523b, + 0xcd => 0x5ba2, 0xce => 0x8bfe, 0xcf => 0x80af, 0xd0 => 0x5543, + 0xd1 => 0x57a6, 0xd2 => 0x6073, 0xd3 => 0x5751, 0xd4 => 0x542d, + 0xd5 => 0x7a7a, 0xd6 => 0x6050, 0xd7 => 0x5b54, 0xd8 => 0x63a7, + 0xd9 => 0x62a0, 0xda => 0x53e3, 0xdb => 0x6263, 0xdc => 0x5bc7, + 0xdd => 0x67af, 0xde => 0x54ed, 0xdf => 0x7a9f, 0xe0 => 0x82e6, + 0xe1 => 0x9177, 0xe2 => 0x5e93, 0xe3 => 0x88e4, 0xe4 => 0x5938, + 0xe5 => 0x57ae, 0xe6 => 0x630e, 0xe7 => 0x8de8, 0xe8 => 0x80ef, + 0xe9 => 0x5757, 0xea => 0x7b77, 0xeb => 0x4fa9, 0xec => 0x5feb, + 0xed => 0x5bbd, 0xee => 0x6b3e, 0xef => 0x5321, 0xf0 => 0x7b50, + 0xf1 => 0x72c2, 0xf2 => 0x6846, 0xf3 => 0x77ff, 0xf4 => 0x7736, + 0xf5 => 0x65f7, 0xf6 => 0x51b5, 0xf7 => 0x4e8f, 0xf8 => 0x76d4, + 0xf9 => 0x5cbf, 0xfa => 0x7aa5, 0xfb => 0x8475, 0xfc => 0x594e, + 0xfd => 0x9b41, 0xfe => 0x5080, + }, + 0xc0 => { + 0xa1 => 0x9988, 0xa2 => 0x6127, 0xa3 => 0x6e83, 0xa4 => 0x5764, + 0xa5 => 0x6606, 0xa6 => 0x6346, 0xa7 => 0x56f0, 0xa8 => 0x62ec, + 0xa9 => 0x6269, 0xaa => 0x5ed3, 0xab => 0x9614, 0xac => 0x5783, + 0xad => 0x62c9, 0xae => 0x5587, 0xaf => 0x8721, 0xb0 => 0x814a, + 0xb1 => 0x8fa3, 0xb2 => 0x5566, 0xb3 => 0x83b1, 0xb4 => 0x6765, + 0xb5 => 0x8d56, 0xb6 => 0x84dd, 0xb7 => 0x5a6a, 0xb8 => 0x680f, + 0xb9 => 0x62e6, 0xba => 0x7bee, 0xbb => 0x9611, 0xbc => 0x5170, + 0xbd => 0x6f9c, 0xbe => 0x8c30, 0xbf => 0x63fd, 0xc0 => 0x89c8, + 0xc1 => 0x61d2, 0xc2 => 0x7f06, 0xc3 => 0x70c2, 0xc4 => 0x6ee5, + 0xc5 => 0x7405, 0xc6 => 0x6994, 0xc7 => 0x72fc, 0xc8 => 0x5eca, + 0xc9 => 0x90ce, 0xca => 0x6717, 0xcb => 0x6d6a, 0xcc => 0x635e, + 0xcd => 0x52b3, 0xce => 0x7262, 0xcf => 0x8001, 0xd0 => 0x4f6c, + 0xd1 => 0x59e5, 0xd2 => 0x916a, 0xd3 => 0x70d9, 0xd4 => 0x6d9d, + 0xd5 => 0x52d2, 0xd6 => 0x4e50, 0xd7 => 0x96f7, 0xd8 => 0x956d, + 0xd9 => 0x857e, 0xda => 0x78ca, 0xdb => 0x7d2f, 0xdc => 0x5121, + 0xdd => 0x5792, 0xde => 0x64c2, 0xdf => 0x808b, 0xe0 => 0x7c7b, + 0xe1 => 0x6cea, 0xe2 => 0x68f1, 0xe3 => 0x695e, 0xe4 => 0x51b7, + 0xe5 => 0x5398, 0xe6 => 0x68a8, 0xe7 => 0x7281, 0xe8 => 0x9ece, + 0xe9 => 0x7bf1, 0xea => 0x72f8, 0xeb => 0x79bb, 0xec => 0x6f13, + 0xed => 0x7406, 0xee => 0x674e, 0xef => 0x91cc, 0xf0 => 0x9ca4, + 0xf1 => 0x793c, 0xf2 => 0x8389, 0xf3 => 0x8354, 0xf4 => 0x540f, + 0xf5 => 0x6817, 0xf6 => 0x4e3d, 0xf7 => 0x5389, 0xf8 => 0x52b1, + 0xf9 => 0x783e, 0xfa => 0x5386, 0xfb => 0x5229, 0xfc => 0x5088, + 0xfd => 0x4f8b, 0xfe => 0x4fd0, + }, + 0xc1 => { + 0xa1 => 0x75e2, 0xa2 => 0x7acb, 0xa3 => 0x7c92, 0xa4 => 0x6ca5, + 0xa5 => 0x96b6, 0xa6 => 0x529b, 0xa7 => 0x7483, 0xa8 => 0x54e9, + 0xa9 => 0x4fe9, 0xaa => 0x8054, 0xab => 0x83b2, 0xac => 0x8fde, + 0xad => 0x9570, 0xae => 0x5ec9, 0xaf => 0x601c, 0xb0 => 0x6d9f, + 0xb1 => 0x5e18, 0xb2 => 0x655b, 0xb3 => 0x8138, 0xb4 => 0x94fe, + 0xb5 => 0x604b, 0xb6 => 0x70bc, 0xb7 => 0x7ec3, 0xb8 => 0x7cae, + 0xb9 => 0x51c9, 0xba => 0x6881, 0xbb => 0x7cb1, 0xbc => 0x826f, + 0xbd => 0x4e24, 0xbe => 0x8f86, 0xbf => 0x91cf, 0xc0 => 0x667e, + 0xc1 => 0x4eae, 0xc2 => 0x8c05, 0xc3 => 0x64a9, 0xc4 => 0x804a, + 0xc5 => 0x50da, 0xc6 => 0x7597, 0xc7 => 0x71ce, 0xc8 => 0x5be5, + 0xc9 => 0x8fbd, 0xca => 0x6f66, 0xcb => 0x4e86, 0xcc => 0x6482, + 0xcd => 0x9563, 0xce => 0x5ed6, 0xcf => 0x6599, 0xd0 => 0x5217, + 0xd1 => 0x88c2, 0xd2 => 0x70c8, 0xd3 => 0x52a3, 0xd4 => 0x730e, + 0xd5 => 0x7433, 0xd6 => 0x6797, 0xd7 => 0x78f7, 0xd8 => 0x9716, + 0xd9 => 0x4e34, 0xda => 0x90bb, 0xdb => 0x9cde, 0xdc => 0x6dcb, + 0xdd => 0x51db, 0xde => 0x8d41, 0xdf => 0x541d, 0xe0 => 0x62ce, + 0xe1 => 0x73b2, 0xe2 => 0x83f1, 0xe3 => 0x96f6, 0xe4 => 0x9f84, + 0xe5 => 0x94c3, 0xe6 => 0x4f36, 0xe7 => 0x7f9a, 0xe8 => 0x51cc, + 0xe9 => 0x7075, 0xea => 0x9675, 0xeb => 0x5cad, 0xec => 0x9886, + 0xed => 0x53e6, 0xee => 0x4ee4, 0xef => 0x6e9c, 0xf0 => 0x7409, + 0xf1 => 0x69b4, 0xf2 => 0x786b, 0xf3 => 0x998f, 0xf4 => 0x7559, + 0xf5 => 0x5218, 0xf6 => 0x7624, 0xf7 => 0x6d41, 0xf8 => 0x67f3, + 0xf9 => 0x516d, 0xfa => 0x9f99, 0xfb => 0x804b, 0xfc => 0x5499, + 0xfd => 0x7b3c, 0xfe => 0x7abf, + }, + 0xc2 => { + 0xa1 => 0x9686, 0xa2 => 0x5784, 0xa3 => 0x62e2, 0xa4 => 0x9647, + 0xa5 => 0x697c, 0xa6 => 0x5a04, 0xa7 => 0x6402, 0xa8 => 0x7bd3, + 0xa9 => 0x6f0f, 0xaa => 0x964b, 0xab => 0x82a6, 0xac => 0x5362, + 0xad => 0x9885, 0xae => 0x5e90, 0xaf => 0x7089, 0xb0 => 0x63b3, + 0xb1 => 0x5364, 0xb2 => 0x864f, 0xb3 => 0x9c81, 0xb4 => 0x9e93, + 0xb5 => 0x788c, 0xb6 => 0x9732, 0xb7 => 0x8def, 0xb8 => 0x8d42, + 0xb9 => 0x9e7f, 0xba => 0x6f5e, 0xbb => 0x7984, 0xbc => 0x5f55, + 0xbd => 0x9646, 0xbe => 0x622e, 0xbf => 0x9a74, 0xc0 => 0x5415, + 0xc1 => 0x94dd, 0xc2 => 0x4fa3, 0xc3 => 0x65c5, 0xc4 => 0x5c65, + 0xc5 => 0x5c61, 0xc6 => 0x7f15, 0xc7 => 0x8651, 0xc8 => 0x6c2f, + 0xc9 => 0x5f8b, 0xca => 0x7387, 0xcb => 0x6ee4, 0xcc => 0x7eff, + 0xcd => 0x5ce6, 0xce => 0x631b, 0xcf => 0x5b6a, 0xd0 => 0x6ee6, + 0xd1 => 0x5375, 0xd2 => 0x4e71, 0xd3 => 0x63a0, 0xd4 => 0x7565, + 0xd5 => 0x62a1, 0xd6 => 0x8f6e, 0xd7 => 0x4f26, 0xd8 => 0x4ed1, + 0xd9 => 0x6ca6, 0xda => 0x7eb6, 0xdb => 0x8bba, 0xdc => 0x841d, + 0xdd => 0x87ba, 0xde => 0x7f57, 0xdf => 0x903b, 0xe0 => 0x9523, + 0xe1 => 0x7ba9, 0xe2 => 0x9aa1, 0xe3 => 0x88f8, 0xe4 => 0x843d, + 0xe5 => 0x6d1b, 0xe6 => 0x9a86, 0xe7 => 0x7edc, 0xe8 => 0x5988, + 0xe9 => 0x9ebb, 0xea => 0x739b, 0xeb => 0x7801, 0xec => 0x8682, + 0xed => 0x9a6c, 0xee => 0x9a82, 0xef => 0x561b, 0xf0 => 0x5417, + 0xf1 => 0x57cb, 0xf2 => 0x4e70, 0xf3 => 0x9ea6, 0xf4 => 0x5356, + 0xf5 => 0x8fc8, 0xf6 => 0x8109, 0xf7 => 0x7792, 0xf8 => 0x9992, + 0xf9 => 0x86ee, 0xfa => 0x6ee1, 0xfb => 0x8513, 0xfc => 0x66fc, + 0xfd => 0x6162, 0xfe => 0x6f2b, + }, + 0xc3 => { + 0xa1 => 0x8c29, 0xa2 => 0x8292, 0xa3 => 0x832b, 0xa4 => 0x76f2, + 0xa5 => 0x6c13, 0xa6 => 0x5fd9, 0xa7 => 0x83bd, 0xa8 => 0x732b, + 0xa9 => 0x8305, 0xaa => 0x951a, 0xab => 0x6bdb, 0xac => 0x77db, + 0xad => 0x94c6, 0xae => 0x536f, 0xaf => 0x8302, 0xb0 => 0x5192, + 0xb1 => 0x5e3d, 0xb2 => 0x8c8c, 0xb3 => 0x8d38, 0xb4 => 0x4e48, + 0xb5 => 0x73ab, 0xb6 => 0x679a, 0xb7 => 0x6885, 0xb8 => 0x9176, + 0xb9 => 0x9709, 0xba => 0x7164, 0xbb => 0x6ca1, 0xbc => 0x7709, + 0xbd => 0x5a92, 0xbe => 0x9541, 0xbf => 0x6bcf, 0xc0 => 0x7f8e, + 0xc1 => 0x6627, 0xc2 => 0x5bd0, 0xc3 => 0x59b9, 0xc4 => 0x5a9a, + 0xc5 => 0x95e8, 0xc6 => 0x95f7, 0xc7 => 0x4eec, 0xc8 => 0x840c, + 0xc9 => 0x8499, 0xca => 0x6aac, 0xcb => 0x76df, 0xcc => 0x9530, + 0xcd => 0x731b, 0xce => 0x68a6, 0xcf => 0x5b5f, 0xd0 => 0x772f, + 0xd1 => 0x919a, 0xd2 => 0x9761, 0xd3 => 0x7cdc, 0xd4 => 0x8ff7, + 0xd5 => 0x8c1c, 0xd6 => 0x5f25, 0xd7 => 0x7c73, 0xd8 => 0x79d8, + 0xd9 => 0x89c5, 0xda => 0x6ccc, 0xdb => 0x871c, 0xdc => 0x5bc6, + 0xdd => 0x5e42, 0xde => 0x68c9, 0xdf => 0x7720, 0xe0 => 0x7ef5, + 0xe1 => 0x5195, 0xe2 => 0x514d, 0xe3 => 0x52c9, 0xe4 => 0x5a29, + 0xe5 => 0x7f05, 0xe6 => 0x9762, 0xe7 => 0x82d7, 0xe8 => 0x63cf, + 0xe9 => 0x7784, 0xea => 0x85d0, 0xeb => 0x79d2, 0xec => 0x6e3a, + 0xed => 0x5e99, 0xee => 0x5999, 0xef => 0x8511, 0xf0 => 0x706d, + 0xf1 => 0x6c11, 0xf2 => 0x62bf, 0xf3 => 0x76bf, 0xf4 => 0x654f, + 0xf5 => 0x60af, 0xf6 => 0x95fd, 0xf7 => 0x660e, 0xf8 => 0x879f, + 0xf9 => 0x9e23, 0xfa => 0x94ed, 0xfb => 0x540d, 0xfc => 0x547d, + 0xfd => 0x8c2c, 0xfe => 0x6478, + }, + 0xc4 => { + 0xa1 => 0x6479, 0xa2 => 0x8611, 0xa3 => 0x6a21, 0xa4 => 0x819c, + 0xa5 => 0x78e8, 0xa6 => 0x6469, 0xa7 => 0x9b54, 0xa8 => 0x62b9, + 0xa9 => 0x672b, 0xaa => 0x83ab, 0xab => 0x58a8, 0xac => 0x9ed8, + 0xad => 0x6cab, 0xae => 0x6f20, 0xaf => 0x5bde, 0xb0 => 0x964c, + 0xb1 => 0x8c0b, 0xb2 => 0x725f, 0xb3 => 0x67d0, 0xb4 => 0x62c7, + 0xb5 => 0x7261, 0xb6 => 0x4ea9, 0xb7 => 0x59c6, 0xb8 => 0x6bcd, + 0xb9 => 0x5893, 0xba => 0x66ae, 0xbb => 0x5e55, 0xbc => 0x52df, + 0xbd => 0x6155, 0xbe => 0x6728, 0xbf => 0x76ee, 0xc0 => 0x7766, + 0xc1 => 0x7267, 0xc2 => 0x7a46, 0xc3 => 0x62ff, 0xc4 => 0x54ea, + 0xc5 => 0x5450, 0xc6 => 0x94a0, 0xc7 => 0x90a3, 0xc8 => 0x5a1c, + 0xc9 => 0x7eb3, 0xca => 0x6c16, 0xcb => 0x4e43, 0xcc => 0x5976, + 0xcd => 0x8010, 0xce => 0x5948, 0xcf => 0x5357, 0xd0 => 0x7537, + 0xd1 => 0x96be, 0xd2 => 0x56ca, 0xd3 => 0x6320, 0xd4 => 0x8111, + 0xd5 => 0x607c, 0xd6 => 0x95f9, 0xd7 => 0x6dd6, 0xd8 => 0x5462, + 0xd9 => 0x9981, 0xda => 0x5185, 0xdb => 0x5ae9, 0xdc => 0x80fd, + 0xdd => 0x59ae, 0xde => 0x9713, 0xdf => 0x502a, 0xe0 => 0x6ce5, + 0xe1 => 0x5c3c, 0xe2 => 0x62df, 0xe3 => 0x4f60, 0xe4 => 0x533f, + 0xe5 => 0x817b, 0xe6 => 0x9006, 0xe7 => 0x6eba, 0xe8 => 0x852b, + 0xe9 => 0x62c8, 0xea => 0x5e74, 0xeb => 0x78be, 0xec => 0x64b5, + 0xed => 0x637b, 0xee => 0x5ff5, 0xef => 0x5a18, 0xf0 => 0x917f, + 0xf1 => 0x9e1f, 0xf2 => 0x5c3f, 0xf3 => 0x634f, 0xf4 => 0x8042, + 0xf5 => 0x5b7d, 0xf6 => 0x556e, 0xf7 => 0x954a, 0xf8 => 0x954d, + 0xf9 => 0x6d85, 0xfa => 0x60a8, 0xfb => 0x67e0, 0xfc => 0x72de, + 0xfd => 0x51dd, 0xfe => 0x5b81, + }, + 0xc5 => { + 0xa1 => 0x62e7, 0xa2 => 0x6cde, 0xa3 => 0x725b, 0xa4 => 0x626d, + 0xa5 => 0x94ae, 0xa6 => 0x7ebd, 0xa7 => 0x8113, 0xa8 => 0x6d53, + 0xa9 => 0x519c, 0xaa => 0x5f04, 0xab => 0x5974, 0xac => 0x52aa, + 0xad => 0x6012, 0xae => 0x5973, 0xaf => 0x6696, 0xb0 => 0x8650, + 0xb1 => 0x759f, 0xb2 => 0x632a, 0xb3 => 0x61e6, 0xb4 => 0x7cef, + 0xb5 => 0x8bfa, 0xb6 => 0x54e6, 0xb7 => 0x6b27, 0xb8 => 0x9e25, + 0xb9 => 0x6bb4, 0xba => 0x85d5, 0xbb => 0x5455, 0xbc => 0x5076, + 0xbd => 0x6ca4, 0xbe => 0x556a, 0xbf => 0x8db4, 0xc0 => 0x722c, + 0xc1 => 0x5e15, 0xc2 => 0x6015, 0xc3 => 0x7436, 0xc4 => 0x62cd, + 0xc5 => 0x6392, 0xc6 => 0x724c, 0xc7 => 0x5f98, 0xc8 => 0x6e43, + 0xc9 => 0x6d3e, 0xca => 0x6500, 0xcb => 0x6f58, 0xcc => 0x76d8, + 0xcd => 0x78d0, 0xce => 0x76fc, 0xcf => 0x7554, 0xd0 => 0x5224, + 0xd1 => 0x53db, 0xd2 => 0x4e53, 0xd3 => 0x5e9e, 0xd4 => 0x65c1, + 0xd5 => 0x802a, 0xd6 => 0x80d6, 0xd7 => 0x629b, 0xd8 => 0x5486, + 0xd9 => 0x5228, 0xda => 0x70ae, 0xdb => 0x888d, 0xdc => 0x8dd1, + 0xdd => 0x6ce1, 0xde => 0x5478, 0xdf => 0x80da, 0xe0 => 0x57f9, + 0xe1 => 0x88f4, 0xe2 => 0x8d54, 0xe3 => 0x966a, 0xe4 => 0x914d, + 0xe5 => 0x4f69, 0xe6 => 0x6c9b, 0xe7 => 0x55b7, 0xe8 => 0x76c6, + 0xe9 => 0x7830, 0xea => 0x62a8, 0xeb => 0x70f9, 0xec => 0x6f8e, + 0xed => 0x5f6d, 0xee => 0x84ec, 0xef => 0x68da, 0xf0 => 0x787c, + 0xf1 => 0x7bf7, 0xf2 => 0x81a8, 0xf3 => 0x670b, 0xf4 => 0x9e4f, + 0xf5 => 0x6367, 0xf6 => 0x78b0, 0xf7 => 0x576f, 0xf8 => 0x7812, + 0xf9 => 0x9739, 0xfa => 0x6279, 0xfb => 0x62ab, 0xfc => 0x5288, + 0xfd => 0x7435, 0xfe => 0x6bd7, + }, + 0xc6 => { + 0xa1 => 0x5564, 0xa2 => 0x813e, 0xa3 => 0x75b2, 0xa4 => 0x76ae, + 0xa5 => 0x5339, 0xa6 => 0x75de, 0xa7 => 0x50fb, 0xa8 => 0x5c41, + 0xa9 => 0x8b6c, 0xaa => 0x7bc7, 0xab => 0x504f, 0xac => 0x7247, + 0xad => 0x9a97, 0xae => 0x98d8, 0xaf => 0x6f02, 0xb0 => 0x74e2, + 0xb1 => 0x7968, 0xb2 => 0x6487, 0xb3 => 0x77a5, 0xb4 => 0x62fc, + 0xb5 => 0x9891, 0xb6 => 0x8d2b, 0xb7 => 0x54c1, 0xb8 => 0x8058, + 0xb9 => 0x4e52, 0xba => 0x576a, 0xbb => 0x82f9, 0xbc => 0x840d, + 0xbd => 0x5e73, 0xbe => 0x51ed, 0xbf => 0x74f6, 0xc0 => 0x8bc4, + 0xc1 => 0x5c4f, 0xc2 => 0x5761, 0xc3 => 0x6cfc, 0xc4 => 0x9887, + 0xc5 => 0x5a46, 0xc6 => 0x7834, 0xc7 => 0x9b44, 0xc8 => 0x8feb, + 0xc9 => 0x7c95, 0xca => 0x5256, 0xcb => 0x6251, 0xcc => 0x94fa, + 0xcd => 0x4ec6, 0xce => 0x8386, 0xcf => 0x8461, 0xd0 => 0x83e9, + 0xd1 => 0x84b2, 0xd2 => 0x57d4, 0xd3 => 0x6734, 0xd4 => 0x5703, + 0xd5 => 0x666e, 0xd6 => 0x6d66, 0xd7 => 0x8c31, 0xd8 => 0x66dd, + 0xd9 => 0x7011, 0xda => 0x671f, 0xdb => 0x6b3a, 0xdc => 0x6816, + 0xdd => 0x621a, 0xde => 0x59bb, 0xdf => 0x4e03, 0xe0 => 0x51c4, + 0xe1 => 0x6f06, 0xe2 => 0x67d2, 0xe3 => 0x6c8f, 0xe4 => 0x5176, + 0xe5 => 0x68cb, 0xe6 => 0x5947, 0xe7 => 0x6b67, 0xe8 => 0x7566, + 0xe9 => 0x5d0e, 0xea => 0x8110, 0xeb => 0x9f50, 0xec => 0x65d7, + 0xed => 0x7948, 0xee => 0x7941, 0xef => 0x9a91, 0xf0 => 0x8d77, + 0xf1 => 0x5c82, 0xf2 => 0x4e5e, 0xf3 => 0x4f01, 0xf4 => 0x542f, + 0xf5 => 0x5951, 0xf6 => 0x780c, 0xf7 => 0x5668, 0xf8 => 0x6c14, + 0xf9 => 0x8fc4, 0xfa => 0x5f03, 0xfb => 0x6c7d, 0xfc => 0x6ce3, + 0xfd => 0x8bab, 0xfe => 0x6390, + }, + 0xc7 => { + 0xa1 => 0x6070, 0xa2 => 0x6d3d, 0xa3 => 0x7275, 0xa4 => 0x6266, + 0xa5 => 0x948e, 0xa6 => 0x94c5, 0xa7 => 0x5343, 0xa8 => 0x8fc1, + 0xa9 => 0x7b7e, 0xaa => 0x4edf, 0xab => 0x8c26, 0xac => 0x4e7e, + 0xad => 0x9ed4, 0xae => 0x94b1, 0xaf => 0x94b3, 0xb0 => 0x524d, + 0xb1 => 0x6f5c, 0xb2 => 0x9063, 0xb3 => 0x6d45, 0xb4 => 0x8c34, + 0xb5 => 0x5811, 0xb6 => 0x5d4c, 0xb7 => 0x6b20, 0xb8 => 0x6b49, + 0xb9 => 0x67aa, 0xba => 0x545b, 0xbb => 0x8154, 0xbc => 0x7f8c, + 0xbd => 0x5899, 0xbe => 0x8537, 0xbf => 0x5f3a, 0xc0 => 0x62a2, + 0xc1 => 0x6a47, 0xc2 => 0x9539, 0xc3 => 0x6572, 0xc4 => 0x6084, + 0xc5 => 0x6865, 0xc6 => 0x77a7, 0xc7 => 0x4e54, 0xc8 => 0x4fa8, + 0xc9 => 0x5de7, 0xca => 0x9798, 0xcb => 0x64ac, 0xcc => 0x7fd8, + 0xcd => 0x5ced, 0xce => 0x4fcf, 0xcf => 0x7a8d, 0xd0 => 0x5207, + 0xd1 => 0x8304, 0xd2 => 0x4e14, 0xd3 => 0x602f, 0xd4 => 0x7a83, + 0xd5 => 0x94a6, 0xd6 => 0x4fb5, 0xd7 => 0x4eb2, 0xd8 => 0x79e6, + 0xd9 => 0x7434, 0xda => 0x52e4, 0xdb => 0x82b9, 0xdc => 0x64d2, + 0xdd => 0x79bd, 0xde => 0x5bdd, 0xdf => 0x6c81, 0xe0 => 0x9752, + 0xe1 => 0x8f7b, 0xe2 => 0x6c22, 0xe3 => 0x503e, 0xe4 => 0x537f, + 0xe5 => 0x6e05, 0xe6 => 0x64ce, 0xe7 => 0x6674, 0xe8 => 0x6c30, + 0xe9 => 0x60c5, 0xea => 0x9877, 0xeb => 0x8bf7, 0xec => 0x5e86, + 0xed => 0x743c, 0xee => 0x7a77, 0xef => 0x79cb, 0xf0 => 0x4e18, + 0xf1 => 0x90b1, 0xf2 => 0x7403, 0xf3 => 0x6c42, 0xf4 => 0x56da, + 0xf5 => 0x914b, 0xf6 => 0x6cc5, 0xf7 => 0x8d8b, 0xf8 => 0x533a, + 0xf9 => 0x86c6, 0xfa => 0x66f2, 0xfb => 0x8eaf, 0xfc => 0x5c48, + 0xfd => 0x9a71, 0xfe => 0x6e20, + }, + 0xc8 => { + 0xa1 => 0x53d6, 0xa2 => 0x5a36, 0xa3 => 0x9f8b, 0xa4 => 0x8da3, + 0xa5 => 0x53bb, 0xa6 => 0x5708, 0xa7 => 0x98a7, 0xa8 => 0x6743, + 0xa9 => 0x919b, 0xaa => 0x6cc9, 0xab => 0x5168, 0xac => 0x75ca, + 0xad => 0x62f3, 0xae => 0x72ac, 0xaf => 0x5238, 0xb0 => 0x529d, + 0xb1 => 0x7f3a, 0xb2 => 0x7094, 0xb3 => 0x7638, 0xb4 => 0x5374, + 0xb5 => 0x9e4a, 0xb6 => 0x69b7, 0xb7 => 0x786e, 0xb8 => 0x96c0, + 0xb9 => 0x88d9, 0xba => 0x7fa4, 0xbb => 0x7136, 0xbc => 0x71c3, + 0xbd => 0x5189, 0xbe => 0x67d3, 0xbf => 0x74e4, 0xc0 => 0x58e4, + 0xc1 => 0x6518, 0xc2 => 0x56b7, 0xc3 => 0x8ba9, 0xc4 => 0x9976, + 0xc5 => 0x6270, 0xc6 => 0x7ed5, 0xc7 => 0x60f9, 0xc8 => 0x70ed, + 0xc9 => 0x58ec, 0xca => 0x4ec1, 0xcb => 0x4eba, 0xcc => 0x5fcd, + 0xcd => 0x97e7, 0xce => 0x4efb, 0xcf => 0x8ba4, 0xd0 => 0x5203, + 0xd1 => 0x598a, 0xd2 => 0x7eab, 0xd3 => 0x6254, 0xd4 => 0x4ecd, + 0xd5 => 0x65e5, 0xd6 => 0x620e, 0xd7 => 0x8338, 0xd8 => 0x84c9, + 0xd9 => 0x8363, 0xda => 0x878d, 0xdb => 0x7194, 0xdc => 0x6eb6, + 0xdd => 0x5bb9, 0xde => 0x7ed2, 0xdf => 0x5197, 0xe0 => 0x63c9, + 0xe1 => 0x67d4, 0xe2 => 0x8089, 0xe3 => 0x8339, 0xe4 => 0x8815, + 0xe5 => 0x5112, 0xe6 => 0x5b7a, 0xe7 => 0x5982, 0xe8 => 0x8fb1, + 0xe9 => 0x4e73, 0xea => 0x6c5d, 0xeb => 0x5165, 0xec => 0x8925, + 0xed => 0x8f6f, 0xee => 0x962e, 0xef => 0x854a, 0xf0 => 0x745e, + 0xf1 => 0x9510, 0xf2 => 0x95f0, 0xf3 => 0x6da6, 0xf4 => 0x82e5, + 0xf5 => 0x5f31, 0xf6 => 0x6492, 0xf7 => 0x6d12, 0xf8 => 0x8428, + 0xf9 => 0x816e, 0xfa => 0x9cc3, 0xfb => 0x585e, 0xfc => 0x8d5b, + 0xfd => 0x4e09, 0xfe => 0x53c1, + }, + 0xc9 => { + 0xa1 => 0x4f1e, 0xa2 => 0x6563, 0xa3 => 0x6851, 0xa4 => 0x55d3, + 0xa5 => 0x4e27, 0xa6 => 0x6414, 0xa7 => 0x9a9a, 0xa8 => 0x626b, + 0xa9 => 0x5ac2, 0xaa => 0x745f, 0xab => 0x8272, 0xac => 0x6da9, + 0xad => 0x68ee, 0xae => 0x50e7, 0xaf => 0x838e, 0xb0 => 0x7802, + 0xb1 => 0x6740, 0xb2 => 0x5239, 0xb3 => 0x6c99, 0xb4 => 0x7eb1, + 0xb5 => 0x50bb, 0xb6 => 0x5565, 0xb7 => 0x715e, 0xb8 => 0x7b5b, + 0xb9 => 0x6652, 0xba => 0x73ca, 0xbb => 0x82eb, 0xbc => 0x6749, + 0xbd => 0x5c71, 0xbe => 0x5220, 0xbf => 0x717d, 0xc0 => 0x886b, + 0xc1 => 0x95ea, 0xc2 => 0x9655, 0xc3 => 0x64c5, 0xc4 => 0x8d61, + 0xc5 => 0x81b3, 0xc6 => 0x5584, 0xc7 => 0x6c55, 0xc8 => 0x6247, + 0xc9 => 0x7f2e, 0xca => 0x5892, 0xcb => 0x4f24, 0xcc => 0x5546, + 0xcd => 0x8d4f, 0xce => 0x664c, 0xcf => 0x4e0a, 0xd0 => 0x5c1a, + 0xd1 => 0x88f3, 0xd2 => 0x68a2, 0xd3 => 0x634e, 0xd4 => 0x7a0d, + 0xd5 => 0x70e7, 0xd6 => 0x828d, 0xd7 => 0x52fa, 0xd8 => 0x97f6, + 0xd9 => 0x5c11, 0xda => 0x54e8, 0xdb => 0x90b5, 0xdc => 0x7ecd, + 0xdd => 0x5962, 0xde => 0x8d4a, 0xdf => 0x86c7, 0xe0 => 0x820c, + 0xe1 => 0x820d, 0xe2 => 0x8d66, 0xe3 => 0x6444, 0xe4 => 0x5c04, + 0xe5 => 0x6151, 0xe6 => 0x6d89, 0xe7 => 0x793e, 0xe8 => 0x8bbe, + 0xe9 => 0x7837, 0xea => 0x7533, 0xeb => 0x547b, 0xec => 0x4f38, + 0xed => 0x8eab, 0xee => 0x6df1, 0xef => 0x5a20, 0xf0 => 0x7ec5, + 0xf1 => 0x795e, 0xf2 => 0x6c88, 0xf3 => 0x5ba1, 0xf4 => 0x5a76, + 0xf5 => 0x751a, 0xf6 => 0x80be, 0xf7 => 0x614e, 0xf8 => 0x6e17, + 0xf9 => 0x58f0, 0xfa => 0x751f, 0xfb => 0x7525, 0xfc => 0x7272, + 0xfd => 0x5347, 0xfe => 0x7ef3, + }, + 0xca => { + 0xa1 => 0x7701, 0xa2 => 0x76db, 0xa3 => 0x5269, 0xa4 => 0x80dc, + 0xa5 => 0x5723, 0xa6 => 0x5e08, 0xa7 => 0x5931, 0xa8 => 0x72ee, + 0xa9 => 0x65bd, 0xaa => 0x6e7f, 0xab => 0x8bd7, 0xac => 0x5c38, + 0xad => 0x8671, 0xae => 0x5341, 0xaf => 0x77f3, 0xb0 => 0x62fe, + 0xb1 => 0x65f6, 0xb2 => 0x4ec0, 0xb3 => 0x98df, 0xb4 => 0x8680, + 0xb5 => 0x5b9e, 0xb6 => 0x8bc6, 0xb7 => 0x53f2, 0xb8 => 0x77e2, + 0xb9 => 0x4f7f, 0xba => 0x5c4e, 0xbb => 0x9a76, 0xbc => 0x59cb, + 0xbd => 0x5f0f, 0xbe => 0x793a, 0xbf => 0x58eb, 0xc0 => 0x4e16, + 0xc1 => 0x67ff, 0xc2 => 0x4e8b, 0xc3 => 0x62ed, 0xc4 => 0x8a93, + 0xc5 => 0x901d, 0xc6 => 0x52bf, 0xc7 => 0x662f, 0xc8 => 0x55dc, + 0xc9 => 0x566c, 0xca => 0x9002, 0xcb => 0x4ed5, 0xcc => 0x4f8d, + 0xcd => 0x91ca, 0xce => 0x9970, 0xcf => 0x6c0f, 0xd0 => 0x5e02, + 0xd1 => 0x6043, 0xd2 => 0x5ba4, 0xd3 => 0x89c6, 0xd4 => 0x8bd5, + 0xd5 => 0x6536, 0xd6 => 0x624b, 0xd7 => 0x9996, 0xd8 => 0x5b88, + 0xd9 => 0x5bff, 0xda => 0x6388, 0xdb => 0x552e, 0xdc => 0x53d7, + 0xdd => 0x7626, 0xde => 0x517d, 0xdf => 0x852c, 0xe0 => 0x67a2, + 0xe1 => 0x68b3, 0xe2 => 0x6b8a, 0xe3 => 0x6292, 0xe4 => 0x8f93, + 0xe5 => 0x53d4, 0xe6 => 0x8212, 0xe7 => 0x6dd1, 0xe8 => 0x758f, + 0xe9 => 0x4e66, 0xea => 0x8d4e, 0xeb => 0x5b70, 0xec => 0x719f, + 0xed => 0x85af, 0xee => 0x6691, 0xef => 0x66d9, 0xf0 => 0x7f72, + 0xf1 => 0x8700, 0xf2 => 0x9ecd, 0xf3 => 0x9f20, 0xf4 => 0x5c5e, + 0xf5 => 0x672f, 0xf6 => 0x8ff0, 0xf7 => 0x6811, 0xf8 => 0x675f, + 0xf9 => 0x620d, 0xfa => 0x7ad6, 0xfb => 0x5885, 0xfc => 0x5eb6, + 0xfd => 0x6570, 0xfe => 0x6f31, + }, + 0xcb => { + 0xa1 => 0x6055, 0xa2 => 0x5237, 0xa3 => 0x800d, 0xa4 => 0x6454, + 0xa5 => 0x8870, 0xa6 => 0x7529, 0xa7 => 0x5e05, 0xa8 => 0x6813, + 0xa9 => 0x62f4, 0xaa => 0x971c, 0xab => 0x53cc, 0xac => 0x723d, + 0xad => 0x8c01, 0xae => 0x6c34, 0xaf => 0x7761, 0xb0 => 0x7a0e, + 0xb1 => 0x542e, 0xb2 => 0x77ac, 0xb3 => 0x987a, 0xb4 => 0x821c, + 0xb5 => 0x8bf4, 0xb6 => 0x7855, 0xb7 => 0x6714, 0xb8 => 0x70c1, + 0xb9 => 0x65af, 0xba => 0x6495, 0xbb => 0x5636, 0xbc => 0x601d, + 0xbd => 0x79c1, 0xbe => 0x53f8, 0xbf => 0x4e1d, 0xc0 => 0x6b7b, + 0xc1 => 0x8086, 0xc2 => 0x5bfa, 0xc3 => 0x55e3, 0xc4 => 0x56db, + 0xc5 => 0x4f3a, 0xc6 => 0x4f3c, 0xc7 => 0x9972, 0xc8 => 0x5df3, + 0xc9 => 0x677e, 0xca => 0x8038, 0xcb => 0x6002, 0xcc => 0x9882, + 0xcd => 0x9001, 0xce => 0x5b8b, 0xcf => 0x8bbc, 0xd0 => 0x8bf5, + 0xd1 => 0x641c, 0xd2 => 0x8258, 0xd3 => 0x64de, 0xd4 => 0x55fd, + 0xd5 => 0x82cf, 0xd6 => 0x9165, 0xd7 => 0x4fd7, 0xd8 => 0x7d20, + 0xd9 => 0x901f, 0xda => 0x7c9f, 0xdb => 0x50f3, 0xdc => 0x5851, + 0xdd => 0x6eaf, 0xde => 0x5bbf, 0xdf => 0x8bc9, 0xe0 => 0x8083, + 0xe1 => 0x9178, 0xe2 => 0x849c, 0xe3 => 0x7b97, 0xe4 => 0x867d, + 0xe5 => 0x968b, 0xe6 => 0x968f, 0xe7 => 0x7ee5, 0xe8 => 0x9ad3, + 0xe9 => 0x788e, 0xea => 0x5c81, 0xeb => 0x7a57, 0xec => 0x9042, + 0xed => 0x96a7, 0xee => 0x795f, 0xef => 0x5b59, 0xf0 => 0x635f, + 0xf1 => 0x7b0b, 0xf2 => 0x84d1, 0xf3 => 0x68ad, 0xf4 => 0x5506, + 0xf5 => 0x7f29, 0xf6 => 0x7410, 0xf7 => 0x7d22, 0xf8 => 0x9501, + 0xf9 => 0x6240, 0xfa => 0x584c, 0xfb => 0x4ed6, 0xfc => 0x5b83, + 0xfd => 0x5979, 0xfe => 0x5854, + }, + 0xcc => { + 0xa1 => 0x736d, 0xa2 => 0x631e, 0xa3 => 0x8e4b, 0xa4 => 0x8e0f, + 0xa5 => 0x80ce, 0xa6 => 0x82d4, 0xa7 => 0x62ac, 0xa8 => 0x53f0, + 0xa9 => 0x6cf0, 0xaa => 0x915e, 0xab => 0x592a, 0xac => 0x6001, + 0xad => 0x6c70, 0xae => 0x574d, 0xaf => 0x644a, 0xb0 => 0x8d2a, + 0xb1 => 0x762b, 0xb2 => 0x6ee9, 0xb3 => 0x575b, 0xb4 => 0x6a80, + 0xb5 => 0x75f0, 0xb6 => 0x6f6d, 0xb7 => 0x8c2d, 0xb8 => 0x8c08, + 0xb9 => 0x5766, 0xba => 0x6bef, 0xbb => 0x8892, 0xbc => 0x78b3, + 0xbd => 0x63a2, 0xbe => 0x53f9, 0xbf => 0x70ad, 0xc0 => 0x6c64, + 0xc1 => 0x5858, 0xc2 => 0x642a, 0xc3 => 0x5802, 0xc4 => 0x68e0, + 0xc5 => 0x819b, 0xc6 => 0x5510, 0xc7 => 0x7cd6, 0xc8 => 0x5018, + 0xc9 => 0x8eba, 0xca => 0x6dcc, 0xcb => 0x8d9f, 0xcc => 0x70eb, + 0xcd => 0x638f, 0xce => 0x6d9b, 0xcf => 0x6ed4, 0xd0 => 0x7ee6, + 0xd1 => 0x8404, 0xd2 => 0x6843, 0xd3 => 0x9003, 0xd4 => 0x6dd8, + 0xd5 => 0x9676, 0xd6 => 0x8ba8, 0xd7 => 0x5957, 0xd8 => 0x7279, + 0xd9 => 0x85e4, 0xda => 0x817e, 0xdb => 0x75bc, 0xdc => 0x8a8a, + 0xdd => 0x68af, 0xde => 0x5254, 0xdf => 0x8e22, 0xe0 => 0x9511, + 0xe1 => 0x63d0, 0xe2 => 0x9898, 0xe3 => 0x8e44, 0xe4 => 0x557c, + 0xe5 => 0x4f53, 0xe6 => 0x66ff, 0xe7 => 0x568f, 0xe8 => 0x60d5, + 0xe9 => 0x6d95, 0xea => 0x5243, 0xeb => 0x5c49, 0xec => 0x5929, + 0xed => 0x6dfb, 0xee => 0x586b, 0xef => 0x7530, 0xf0 => 0x751c, + 0xf1 => 0x606c, 0xf2 => 0x8214, 0xf3 => 0x8146, 0xf4 => 0x6311, + 0xf5 => 0x6761, 0xf6 => 0x8fe2, 0xf7 => 0x773a, 0xf8 => 0x8df3, + 0xf9 => 0x8d34, 0xfa => 0x94c1, 0xfb => 0x5e16, 0xfc => 0x5385, + 0xfd => 0x542c, 0xfe => 0x70c3, + }, + 0xcd => { + 0xa1 => 0x6c40, 0xa2 => 0x5ef7, 0xa3 => 0x505c, 0xa4 => 0x4ead, + 0xa5 => 0x5ead, 0xa6 => 0x633a, 0xa7 => 0x8247, 0xa8 => 0x901a, + 0xa9 => 0x6850, 0xaa => 0x916e, 0xab => 0x77b3, 0xac => 0x540c, + 0xad => 0x94dc, 0xae => 0x5f64, 0xaf => 0x7ae5, 0xb0 => 0x6876, + 0xb1 => 0x6345, 0xb2 => 0x7b52, 0xb3 => 0x7edf, 0xb4 => 0x75db, + 0xb5 => 0x5077, 0xb6 => 0x6295, 0xb7 => 0x5934, 0xb8 => 0x900f, + 0xb9 => 0x51f8, 0xba => 0x79c3, 0xbb => 0x7a81, 0xbc => 0x56fe, + 0xbd => 0x5f92, 0xbe => 0x9014, 0xbf => 0x6d82, 0xc0 => 0x5c60, + 0xc1 => 0x571f, 0xc2 => 0x5410, 0xc3 => 0x5154, 0xc4 => 0x6e4d, + 0xc5 => 0x56e2, 0xc6 => 0x63a8, 0xc7 => 0x9893, 0xc8 => 0x817f, + 0xc9 => 0x8715, 0xca => 0x892a, 0xcb => 0x9000, 0xcc => 0x541e, + 0xcd => 0x5c6f, 0xce => 0x81c0, 0xcf => 0x62d6, 0xd0 => 0x6258, + 0xd1 => 0x8131, 0xd2 => 0x9e35, 0xd3 => 0x9640, 0xd4 => 0x9a6e, + 0xd5 => 0x9a7c, 0xd6 => 0x692d, 0xd7 => 0x59a5, 0xd8 => 0x62d3, + 0xd9 => 0x553e, 0xda => 0x6316, 0xdb => 0x54c7, 0xdc => 0x86d9, + 0xdd => 0x6d3c, 0xde => 0x5a03, 0xdf => 0x74e6, 0xe0 => 0x889c, + 0xe1 => 0x6b6a, 0xe2 => 0x5916, 0xe3 => 0x8c4c, 0xe4 => 0x5f2f, + 0xe5 => 0x6e7e, 0xe6 => 0x73a9, 0xe7 => 0x987d, 0xe8 => 0x4e38, + 0xe9 => 0x70f7, 0xea => 0x5b8c, 0xeb => 0x7897, 0xec => 0x633d, + 0xed => 0x665a, 0xee => 0x7696, 0xef => 0x60cb, 0xf0 => 0x5b9b, + 0xf1 => 0x5a49, 0xf2 => 0x4e07, 0xf3 => 0x8155, 0xf4 => 0x6c6a, + 0xf5 => 0x738b, 0xf6 => 0x4ea1, 0xf7 => 0x6789, 0xf8 => 0x7f51, + 0xf9 => 0x5f80, 0xfa => 0x65fa, 0xfb => 0x671b, 0xfc => 0x5fd8, + 0xfd => 0x5984, 0xfe => 0x5a01, + }, + 0xce => { + 0xa1 => 0x5dcd, 0xa2 => 0x5fae, 0xa3 => 0x5371, 0xa4 => 0x97e6, + 0xa5 => 0x8fdd, 0xa6 => 0x6845, 0xa7 => 0x56f4, 0xa8 => 0x552f, + 0xa9 => 0x60df, 0xaa => 0x4e3a, 0xab => 0x6f4d, 0xac => 0x7ef4, + 0xad => 0x82c7, 0xae => 0x840e, 0xaf => 0x59d4, 0xb0 => 0x4f1f, + 0xb1 => 0x4f2a, 0xb2 => 0x5c3e, 0xb3 => 0x7eac, 0xb4 => 0x672a, + 0xb5 => 0x851a, 0xb6 => 0x5473, 0xb7 => 0x754f, 0xb8 => 0x80c3, + 0xb9 => 0x5582, 0xba => 0x9b4f, 0xbb => 0x4f4d, 0xbc => 0x6e2d, + 0xbd => 0x8c13, 0xbe => 0x5c09, 0xbf => 0x6170, 0xc0 => 0x536b, + 0xc1 => 0x761f, 0xc2 => 0x6e29, 0xc3 => 0x868a, 0xc4 => 0x6587, + 0xc5 => 0x95fb, 0xc6 => 0x7eb9, 0xc7 => 0x543b, 0xc8 => 0x7a33, + 0xc9 => 0x7d0a, 0xca => 0x95ee, 0xcb => 0x55e1, 0xcc => 0x7fc1, + 0xcd => 0x74ee, 0xce => 0x631d, 0xcf => 0x8717, 0xd0 => 0x6da1, + 0xd1 => 0x7a9d, 0xd2 => 0x6211, 0xd3 => 0x65a1, 0xd4 => 0x5367, + 0xd5 => 0x63e1, 0xd6 => 0x6c83, 0xd7 => 0x5deb, 0xd8 => 0x545c, + 0xd9 => 0x94a8, 0xda => 0x4e4c, 0xdb => 0x6c61, 0xdc => 0x8bec, + 0xdd => 0x5c4b, 0xde => 0x65e0, 0xdf => 0x829c, 0xe0 => 0x68a7, + 0xe1 => 0x543e, 0xe2 => 0x5434, 0xe3 => 0x6bcb, 0xe4 => 0x6b66, + 0xe5 => 0x4e94, 0xe6 => 0x6342, 0xe7 => 0x5348, 0xe8 => 0x821e, + 0xe9 => 0x4f0d, 0xea => 0x4fae, 0xeb => 0x575e, 0xec => 0x620a, + 0xed => 0x96fe, 0xee => 0x6664, 0xef => 0x7269, 0xf0 => 0x52ff, + 0xf1 => 0x52a1, 0xf2 => 0x609f, 0xf3 => 0x8bef, 0xf4 => 0x6614, + 0xf5 => 0x7199, 0xf6 => 0x6790, 0xf7 => 0x897f, 0xf8 => 0x7852, + 0xf9 => 0x77fd, 0xfa => 0x6670, 0xfb => 0x563b, 0xfc => 0x5438, + 0xfd => 0x9521, 0xfe => 0x727a, + }, + 0xcf => { + 0xa1 => 0x7a00, 0xa2 => 0x606f, 0xa3 => 0x5e0c, 0xa4 => 0x6089, + 0xa5 => 0x819d, 0xa6 => 0x5915, 0xa7 => 0x60dc, 0xa8 => 0x7184, + 0xa9 => 0x70ef, 0xaa => 0x6eaa, 0xab => 0x6c50, 0xac => 0x7280, + 0xad => 0x6a84, 0xae => 0x88ad, 0xaf => 0x5e2d, 0xb0 => 0x4e60, + 0xb1 => 0x5ab3, 0xb2 => 0x559c, 0xb3 => 0x94e3, 0xb4 => 0x6d17, + 0xb5 => 0x7cfb, 0xb6 => 0x9699, 0xb7 => 0x620f, 0xb8 => 0x7ec6, + 0xb9 => 0x778e, 0xba => 0x867e, 0xbb => 0x5323, 0xbc => 0x971e, + 0xbd => 0x8f96, 0xbe => 0x6687, 0xbf => 0x5ce1, 0xc0 => 0x4fa0, + 0xc1 => 0x72ed, 0xc2 => 0x4e0b, 0xc3 => 0x53a6, 0xc4 => 0x590f, + 0xc5 => 0x5413, 0xc6 => 0x6380, 0xc7 => 0x9528, 0xc8 => 0x5148, + 0xc9 => 0x4ed9, 0xca => 0x9c9c, 0xcb => 0x7ea4, 0xcc => 0x54b8, + 0xcd => 0x8d24, 0xce => 0x8854, 0xcf => 0x8237, 0xd0 => 0x95f2, + 0xd1 => 0x6d8e, 0xd2 => 0x5f26, 0xd3 => 0x5acc, 0xd4 => 0x663e, + 0xd5 => 0x9669, 0xd6 => 0x73b0, 0xd7 => 0x732e, 0xd8 => 0x53bf, + 0xd9 => 0x817a, 0xda => 0x9985, 0xdb => 0x7fa1, 0xdc => 0x5baa, + 0xdd => 0x9677, 0xde => 0x9650, 0xdf => 0x7ebf, 0xe0 => 0x76f8, + 0xe1 => 0x53a2, 0xe2 => 0x9576, 0xe3 => 0x9999, 0xe4 => 0x7bb1, + 0xe5 => 0x8944, 0xe6 => 0x6e58, 0xe7 => 0x4e61, 0xe8 => 0x7fd4, + 0xe9 => 0x7965, 0xea => 0x8be6, 0xeb => 0x60f3, 0xec => 0x54cd, + 0xed => 0x4eab, 0xee => 0x9879, 0xef => 0x5df7, 0xf0 => 0x6a61, + 0xf1 => 0x50cf, 0xf2 => 0x5411, 0xf3 => 0x8c61, 0xf4 => 0x8427, + 0xf5 => 0x785d, 0xf6 => 0x9704, 0xf7 => 0x524a, 0xf8 => 0x54ee, + 0xf9 => 0x56a3, 0xfa => 0x9500, 0xfb => 0x6d88, 0xfc => 0x5bb5, + 0xfd => 0x6dc6, 0xfe => 0x6653, + }, + 0xd0 => { + 0xa1 => 0x5c0f, 0xa2 => 0x5b5d, 0xa3 => 0x6821, 0xa4 => 0x8096, + 0xa5 => 0x5578, 0xa6 => 0x7b11, 0xa7 => 0x6548, 0xa8 => 0x6954, + 0xa9 => 0x4e9b, 0xaa => 0x6b47, 0xab => 0x874e, 0xac => 0x978b, + 0xad => 0x534f, 0xae => 0x631f, 0xaf => 0x643a, 0xb0 => 0x90aa, + 0xb1 => 0x659c, 0xb2 => 0x80c1, 0xb3 => 0x8c10, 0xb4 => 0x5199, + 0xb5 => 0x68b0, 0xb6 => 0x5378, 0xb7 => 0x87f9, 0xb8 => 0x61c8, + 0xb9 => 0x6cc4, 0xba => 0x6cfb, 0xbb => 0x8c22, 0xbc => 0x5c51, + 0xbd => 0x85aa, 0xbe => 0x82af, 0xbf => 0x950c, 0xc0 => 0x6b23, + 0xc1 => 0x8f9b, 0xc2 => 0x65b0, 0xc3 => 0x5ffb, 0xc4 => 0x5fc3, + 0xc5 => 0x4fe1, 0xc6 => 0x8845, 0xc7 => 0x661f, 0xc8 => 0x8165, + 0xc9 => 0x7329, 0xca => 0x60fa, 0xcb => 0x5174, 0xcc => 0x5211, + 0xcd => 0x578b, 0xce => 0x5f62, 0xcf => 0x90a2, 0xd0 => 0x884c, + 0xd1 => 0x9192, 0xd2 => 0x5e78, 0xd3 => 0x674f, 0xd4 => 0x6027, + 0xd5 => 0x59d3, 0xd6 => 0x5144, 0xd7 => 0x51f6, 0xd8 => 0x80f8, + 0xd9 => 0x5308, 0xda => 0x6c79, 0xdb => 0x96c4, 0xdc => 0x718a, + 0xdd => 0x4f11, 0xde => 0x4fee, 0xdf => 0x7f9e, 0xe0 => 0x673d, + 0xe1 => 0x55c5, 0xe2 => 0x9508, 0xe3 => 0x79c0, 0xe4 => 0x8896, + 0xe5 => 0x7ee3, 0xe6 => 0x589f, 0xe7 => 0x620c, 0xe8 => 0x9700, + 0xe9 => 0x865a, 0xea => 0x5618, 0xeb => 0x987b, 0xec => 0x5f90, + 0xed => 0x8bb8, 0xee => 0x84c4, 0xef => 0x9157, 0xf0 => 0x53d9, + 0xf1 => 0x65ed, 0xf2 => 0x5e8f, 0xf3 => 0x755c, 0xf4 => 0x6064, + 0xf5 => 0x7d6e, 0xf6 => 0x5a7f, 0xf7 => 0x7eea, 0xf8 => 0x7eed, + 0xf9 => 0x8f69, 0xfa => 0x55a7, 0xfb => 0x5ba3, 0xfc => 0x60ac, + 0xfd => 0x65cb, 0xfe => 0x7384, + }, + 0xd1 => { + 0xa1 => 0x9009, 0xa2 => 0x7663, 0xa3 => 0x7729, 0xa4 => 0x7eda, + 0xa5 => 0x9774, 0xa6 => 0x859b, 0xa7 => 0x5b66, 0xa8 => 0x7a74, + 0xa9 => 0x96ea, 0xaa => 0x8840, 0xab => 0x52cb, 0xac => 0x718f, + 0xad => 0x5faa, 0xae => 0x65ec, 0xaf => 0x8be2, 0xb0 => 0x5bfb, + 0xb1 => 0x9a6f, 0xb2 => 0x5de1, 0xb3 => 0x6b89, 0xb4 => 0x6c5b, + 0xb5 => 0x8bad, 0xb6 => 0x8baf, 0xb7 => 0x900a, 0xb8 => 0x8fc5, + 0xb9 => 0x538b, 0xba => 0x62bc, 0xbb => 0x9e26, 0xbc => 0x9e2d, + 0xbd => 0x5440, 0xbe => 0x4e2b, 0xbf => 0x82bd, 0xc0 => 0x7259, + 0xc1 => 0x869c, 0xc2 => 0x5d16, 0xc3 => 0x8859, 0xc4 => 0x6daf, + 0xc5 => 0x96c5, 0xc6 => 0x54d1, 0xc7 => 0x4e9a, 0xc8 => 0x8bb6, + 0xc9 => 0x7109, 0xca => 0x54bd, 0xcb => 0x9609, 0xcc => 0x70df, + 0xcd => 0x6df9, 0xce => 0x76d0, 0xcf => 0x4e25, 0xd0 => 0x7814, + 0xd1 => 0x8712, 0xd2 => 0x5ca9, 0xd3 => 0x5ef6, 0xd4 => 0x8a00, + 0xd5 => 0x989c, 0xd6 => 0x960e, 0xd7 => 0x708e, 0xd8 => 0x6cbf, + 0xd9 => 0x5944, 0xda => 0x63a9, 0xdb => 0x773c, 0xdc => 0x884d, + 0xdd => 0x6f14, 0xde => 0x8273, 0xdf => 0x5830, 0xe0 => 0x71d5, + 0xe1 => 0x538c, 0xe2 => 0x781a, 0xe3 => 0x96c1, 0xe4 => 0x5501, + 0xe5 => 0x5f66, 0xe6 => 0x7130, 0xe7 => 0x5bb4, 0xe8 => 0x8c1a, + 0xe9 => 0x9a8c, 0xea => 0x6b83, 0xeb => 0x592e, 0xec => 0x9e2f, + 0xed => 0x79e7, 0xee => 0x6768, 0xef => 0x626c, 0xf0 => 0x4f6f, + 0xf1 => 0x75a1, 0xf2 => 0x7f8a, 0xf3 => 0x6d0b, 0xf4 => 0x9633, + 0xf5 => 0x6c27, 0xf6 => 0x4ef0, 0xf7 => 0x75d2, 0xf8 => 0x517b, + 0xf9 => 0x6837, 0xfa => 0x6f3e, 0xfb => 0x9080, 0xfc => 0x8170, + 0xfd => 0x5996, 0xfe => 0x7476, + }, + 0xd2 => { + 0xa1 => 0x6447, 0xa2 => 0x5c27, 0xa3 => 0x9065, 0xa4 => 0x7a91, + 0xa5 => 0x8c23, 0xa6 => 0x59da, 0xa7 => 0x54ac, 0xa8 => 0x8200, + 0xa9 => 0x836f, 0xaa => 0x8981, 0xab => 0x8000, 0xac => 0x6930, + 0xad => 0x564e, 0xae => 0x8036, 0xaf => 0x7237, 0xb0 => 0x91ce, + 0xb1 => 0x51b6, 0xb2 => 0x4e5f, 0xb3 => 0x9875, 0xb4 => 0x6396, + 0xb5 => 0x4e1a, 0xb6 => 0x53f6, 0xb7 => 0x66f3, 0xb8 => 0x814b, + 0xb9 => 0x591c, 0xba => 0x6db2, 0xbb => 0x4e00, 0xbc => 0x58f9, + 0xbd => 0x533b, 0xbe => 0x63d6, 0xbf => 0x94f1, 0xc0 => 0x4f9d, + 0xc1 => 0x4f0a, 0xc2 => 0x8863, 0xc3 => 0x9890, 0xc4 => 0x5937, + 0xc5 => 0x9057, 0xc6 => 0x79fb, 0xc7 => 0x4eea, 0xc8 => 0x80f0, + 0xc9 => 0x7591, 0xca => 0x6c82, 0xcb => 0x5b9c, 0xcc => 0x59e8, + 0xcd => 0x5f5d, 0xce => 0x6905, 0xcf => 0x8681, 0xd0 => 0x501a, + 0xd1 => 0x5df2, 0xd2 => 0x4e59, 0xd3 => 0x77e3, 0xd4 => 0x4ee5, + 0xd5 => 0x827a, 0xd6 => 0x6291, 0xd7 => 0x6613, 0xd8 => 0x9091, + 0xd9 => 0x5c79, 0xda => 0x4ebf, 0xdb => 0x5f79, 0xdc => 0x81c6, + 0xdd => 0x9038, 0xde => 0x8084, 0xdf => 0x75ab, 0xe0 => 0x4ea6, + 0xe1 => 0x88d4, 0xe2 => 0x610f, 0xe3 => 0x6bc5, 0xe4 => 0x5fc6, + 0xe5 => 0x4e49, 0xe6 => 0x76ca, 0xe7 => 0x6ea2, 0xe8 => 0x8be3, + 0xe9 => 0x8bae, 0xea => 0x8c0a, 0xeb => 0x8bd1, 0xec => 0x5f02, + 0xed => 0x7ffc, 0xee => 0x7fcc, 0xef => 0x7ece, 0xf0 => 0x8335, + 0xf1 => 0x836b, 0xf2 => 0x56e0, 0xf3 => 0x6bb7, 0xf4 => 0x97f3, + 0xf5 => 0x9634, 0xf6 => 0x59fb, 0xf7 => 0x541f, 0xf8 => 0x94f6, + 0xf9 => 0x6deb, 0xfa => 0x5bc5, 0xfb => 0x996e, 0xfc => 0x5c39, + 0xfd => 0x5f15, 0xfe => 0x9690, + }, + 0xd3 => { + 0xa1 => 0x5370, 0xa2 => 0x82f1, 0xa3 => 0x6a31, 0xa4 => 0x5a74, + 0xa5 => 0x9e70, 0xa6 => 0x5e94, 0xa7 => 0x7f28, 0xa8 => 0x83b9, + 0xa9 => 0x8424, 0xaa => 0x8425, 0xab => 0x8367, 0xac => 0x8747, + 0xad => 0x8fce, 0xae => 0x8d62, 0xaf => 0x76c8, 0xb0 => 0x5f71, + 0xb1 => 0x9896, 0xb2 => 0x786c, 0xb3 => 0x6620, 0xb4 => 0x54df, + 0xb5 => 0x62e5, 0xb6 => 0x4f63, 0xb7 => 0x81c3, 0xb8 => 0x75c8, + 0xb9 => 0x5eb8, 0xba => 0x96cd, 0xbb => 0x8e0a, 0xbc => 0x86f9, + 0xbd => 0x548f, 0xbe => 0x6cf3, 0xbf => 0x6d8c, 0xc0 => 0x6c38, + 0xc1 => 0x607f, 0xc2 => 0x52c7, 0xc3 => 0x7528, 0xc4 => 0x5e7d, + 0xc5 => 0x4f18, 0xc6 => 0x60a0, 0xc7 => 0x5fe7, 0xc8 => 0x5c24, + 0xc9 => 0x7531, 0xca => 0x90ae, 0xcb => 0x94c0, 0xcc => 0x72b9, + 0xcd => 0x6cb9, 0xce => 0x6e38, 0xcf => 0x9149, 0xd0 => 0x6709, + 0xd1 => 0x53cb, 0xd2 => 0x53f3, 0xd3 => 0x4f51, 0xd4 => 0x91c9, + 0xd5 => 0x8bf1, 0xd6 => 0x53c8, 0xd7 => 0x5e7c, 0xd8 => 0x8fc2, + 0xd9 => 0x6de4, 0xda => 0x4e8e, 0xdb => 0x76c2, 0xdc => 0x6986, + 0xdd => 0x865e, 0xde => 0x611a, 0xdf => 0x8206, 0xe0 => 0x4f59, + 0xe1 => 0x4fde, 0xe2 => 0x903e, 0xe3 => 0x9c7c, 0xe4 => 0x6109, + 0xe5 => 0x6e1d, 0xe6 => 0x6e14, 0xe7 => 0x9685, 0xe8 => 0x4e88, + 0xe9 => 0x5a31, 0xea => 0x96e8, 0xeb => 0x4e0e, 0xec => 0x5c7f, + 0xed => 0x79b9, 0xee => 0x5b87, 0xef => 0x8bed, 0xf0 => 0x7fbd, + 0xf1 => 0x7389, 0xf2 => 0x57df, 0xf3 => 0x828b, 0xf4 => 0x90c1, + 0xf5 => 0x5401, 0xf6 => 0x9047, 0xf7 => 0x55bb, 0xf8 => 0x5cea, + 0xf9 => 0x5fa1, 0xfa => 0x6108, 0xfb => 0x6b32, 0xfc => 0x72f1, + 0xfd => 0x80b2, 0xfe => 0x8a89, + }, + 0xd4 => { + 0xa1 => 0x6d74, 0xa2 => 0x5bd3, 0xa3 => 0x88d5, 0xa4 => 0x9884, + 0xa5 => 0x8c6b, 0xa6 => 0x9a6d, 0xa7 => 0x9e33, 0xa8 => 0x6e0a, + 0xa9 => 0x51a4, 0xaa => 0x5143, 0xab => 0x57a3, 0xac => 0x8881, + 0xad => 0x539f, 0xae => 0x63f4, 0xaf => 0x8f95, 0xb0 => 0x56ed, + 0xb1 => 0x5458, 0xb2 => 0x5706, 0xb3 => 0x733f, 0xb4 => 0x6e90, + 0xb5 => 0x7f18, 0xb6 => 0x8fdc, 0xb7 => 0x82d1, 0xb8 => 0x613f, + 0xb9 => 0x6028, 0xba => 0x9662, 0xbb => 0x66f0, 0xbc => 0x7ea6, + 0xbd => 0x8d8a, 0xbe => 0x8dc3, 0xbf => 0x94a5, 0xc0 => 0x5cb3, + 0xc1 => 0x7ca4, 0xc2 => 0x6708, 0xc3 => 0x60a6, 0xc4 => 0x9605, + 0xc5 => 0x8018, 0xc6 => 0x4e91, 0xc7 => 0x90e7, 0xc8 => 0x5300, + 0xc9 => 0x9668, 0xca => 0x5141, 0xcb => 0x8fd0, 0xcc => 0x8574, + 0xcd => 0x915d, 0xce => 0x6655, 0xcf => 0x97f5, 0xd0 => 0x5b55, + 0xd1 => 0x531d, 0xd2 => 0x7838, 0xd3 => 0x6742, 0xd4 => 0x683d, + 0xd5 => 0x54c9, 0xd6 => 0x707e, 0xd7 => 0x5bb0, 0xd8 => 0x8f7d, + 0xd9 => 0x518d, 0xda => 0x5728, 0xdb => 0x54b1, 0xdc => 0x6512, + 0xdd => 0x6682, 0xde => 0x8d5e, 0xdf => 0x8d43, 0xe0 => 0x810f, + 0xe1 => 0x846c, 0xe2 => 0x906d, 0xe3 => 0x7cdf, 0xe4 => 0x51ff, + 0xe5 => 0x85fb, 0xe6 => 0x67a3, 0xe7 => 0x65e9, 0xe8 => 0x6fa1, + 0xe9 => 0x86a4, 0xea => 0x8e81, 0xeb => 0x566a, 0xec => 0x9020, + 0xed => 0x7682, 0xee => 0x7076, 0xef => 0x71e5, 0xf0 => 0x8d23, + 0xf1 => 0x62e9, 0xf2 => 0x5219, 0xf3 => 0x6cfd, 0xf4 => 0x8d3c, + 0xf5 => 0x600e, 0xf6 => 0x589e, 0xf7 => 0x618e, 0xf8 => 0x66fe, + 0xf9 => 0x8d60, 0xfa => 0x624e, 0xfb => 0x55b3, 0xfc => 0x6e23, + 0xfd => 0x672d, 0xfe => 0x8f67, + }, + 0xd5 => { + 0xa1 => 0x94e1, 0xa2 => 0x95f8, 0xa3 => 0x7728, 0xa4 => 0x6805, + 0xa5 => 0x69a8, 0xa6 => 0x548b, 0xa7 => 0x4e4d, 0xa8 => 0x70b8, + 0xa9 => 0x8bc8, 0xaa => 0x6458, 0xab => 0x658b, 0xac => 0x5b85, + 0xad => 0x7a84, 0xae => 0x503a, 0xaf => 0x5be8, 0xb0 => 0x77bb, + 0xb1 => 0x6be1, 0xb2 => 0x8a79, 0xb3 => 0x7c98, 0xb4 => 0x6cbe, + 0xb5 => 0x76cf, 0xb6 => 0x65a9, 0xb7 => 0x8f97, 0xb8 => 0x5d2d, + 0xb9 => 0x5c55, 0xba => 0x8638, 0xbb => 0x6808, 0xbc => 0x5360, + 0xbd => 0x6218, 0xbe => 0x7ad9, 0xbf => 0x6e5b, 0xc0 => 0x7efd, + 0xc1 => 0x6a1f, 0xc2 => 0x7ae0, 0xc3 => 0x5f70, 0xc4 => 0x6f33, + 0xc5 => 0x5f20, 0xc6 => 0x638c, 0xc7 => 0x6da8, 0xc8 => 0x6756, + 0xc9 => 0x4e08, 0xca => 0x5e10, 0xcb => 0x8d26, 0xcc => 0x4ed7, + 0xcd => 0x80c0, 0xce => 0x7634, 0xcf => 0x969c, 0xd0 => 0x62db, + 0xd1 => 0x662d, 0xd2 => 0x627e, 0xd3 => 0x6cbc, 0xd4 => 0x8d75, + 0xd5 => 0x7167, 0xd6 => 0x7f69, 0xd7 => 0x5146, 0xd8 => 0x8087, + 0xd9 => 0x53ec, 0xda => 0x906e, 0xdb => 0x6298, 0xdc => 0x54f2, + 0xdd => 0x86f0, 0xde => 0x8f99, 0xdf => 0x8005, 0xe0 => 0x9517, + 0xe1 => 0x8517, 0xe2 => 0x8fd9, 0xe3 => 0x6d59, 0xe4 => 0x73cd, + 0xe5 => 0x659f, 0xe6 => 0x771f, 0xe7 => 0x7504, 0xe8 => 0x7827, + 0xe9 => 0x81fb, 0xea => 0x8d1e, 0xeb => 0x9488, 0xec => 0x4fa6, + 0xed => 0x6795, 0xee => 0x75b9, 0xef => 0x8bca, 0xf0 => 0x9707, + 0xf1 => 0x632f, 0xf2 => 0x9547, 0xf3 => 0x9635, 0xf4 => 0x84b8, + 0xf5 => 0x6323, 0xf6 => 0x7741, 0xf7 => 0x5f81, 0xf8 => 0x72f0, + 0xf9 => 0x4e89, 0xfa => 0x6014, 0xfb => 0x6574, 0xfc => 0x62ef, + 0xfd => 0x6b63, 0xfe => 0x653f, + }, + 0xd6 => { + 0xa1 => 0x5e27, 0xa2 => 0x75c7, 0xa3 => 0x90d1, 0xa4 => 0x8bc1, + 0xa5 => 0x829d, 0xa6 => 0x679d, 0xa7 => 0x652f, 0xa8 => 0x5431, + 0xa9 => 0x8718, 0xaa => 0x77e5, 0xab => 0x80a2, 0xac => 0x8102, + 0xad => 0x6c41, 0xae => 0x4e4b, 0xaf => 0x7ec7, 0xb0 => 0x804c, + 0xb1 => 0x76f4, 0xb2 => 0x690d, 0xb3 => 0x6b96, 0xb4 => 0x6267, + 0xb5 => 0x503c, 0xb6 => 0x4f84, 0xb7 => 0x5740, 0xb8 => 0x6307, + 0xb9 => 0x6b62, 0xba => 0x8dbe, 0xbb => 0x53ea, 0xbc => 0x65e8, + 0xbd => 0x7eb8, 0xbe => 0x5fd7, 0xbf => 0x631a, 0xc0 => 0x63b7, + 0xc1 => 0x81f3, 0xc2 => 0x81f4, 0xc3 => 0x7f6e, 0xc4 => 0x5e1c, + 0xc5 => 0x5cd9, 0xc6 => 0x5236, 0xc7 => 0x667a, 0xc8 => 0x79e9, + 0xc9 => 0x7a1a, 0xca => 0x8d28, 0xcb => 0x7099, 0xcc => 0x75d4, + 0xcd => 0x6ede, 0xce => 0x6cbb, 0xcf => 0x7a92, 0xd0 => 0x4e2d, + 0xd1 => 0x76c5, 0xd2 => 0x5fe0, 0xd3 => 0x949f, 0xd4 => 0x8877, + 0xd5 => 0x7ec8, 0xd6 => 0x79cd, 0xd7 => 0x80bf, 0xd8 => 0x91cd, + 0xd9 => 0x4ef2, 0xda => 0x4f17, 0xdb => 0x821f, 0xdc => 0x5468, + 0xdd => 0x5dde, 0xde => 0x6d32, 0xdf => 0x8bcc, 0xe0 => 0x7ca5, + 0xe1 => 0x8f74, 0xe2 => 0x8098, 0xe3 => 0x5e1a, 0xe4 => 0x5492, + 0xe5 => 0x76b1, 0xe6 => 0x5b99, 0xe7 => 0x663c, 0xe8 => 0x9aa4, + 0xe9 => 0x73e0, 0xea => 0x682a, 0xeb => 0x86db, 0xec => 0x6731, + 0xed => 0x732a, 0xee => 0x8bf8, 0xef => 0x8bdb, 0xf0 => 0x9010, + 0xf1 => 0x7af9, 0xf2 => 0x70db, 0xf3 => 0x716e, 0xf4 => 0x62c4, + 0xf5 => 0x77a9, 0xf6 => 0x5631, 0xf7 => 0x4e3b, 0xf8 => 0x8457, + 0xf9 => 0x67f1, 0xfa => 0x52a9, 0xfb => 0x86c0, 0xfc => 0x8d2e, + 0xfd => 0x94f8, 0xfe => 0x7b51, + }, + 0xd7 => { + 0xa1 => 0x4f4f, 0xa2 => 0x6ce8, 0xa3 => 0x795d, 0xa4 => 0x9a7b, + 0xa5 => 0x6293, 0xa6 => 0x722a, 0xa7 => 0x62fd, 0xa8 => 0x4e13, + 0xa9 => 0x7816, 0xaa => 0x8f6c, 0xab => 0x64b0, 0xac => 0x8d5a, + 0xad => 0x7bc6, 0xae => 0x6869, 0xaf => 0x5e84, 0xb0 => 0x88c5, + 0xb1 => 0x5986, 0xb2 => 0x649e, 0xb3 => 0x58ee, 0xb4 => 0x72b6, + 0xb5 => 0x690e, 0xb6 => 0x9525, 0xb7 => 0x8ffd, 0xb8 => 0x8d58, + 0xb9 => 0x5760, 0xba => 0x7f00, 0xbb => 0x8c06, 0xbc => 0x51c6, + 0xbd => 0x6349, 0xbe => 0x62d9, 0xbf => 0x5353, 0xc0 => 0x684c, + 0xc1 => 0x7422, 0xc2 => 0x8301, 0xc3 => 0x914c, 0xc4 => 0x5544, + 0xc5 => 0x7740, 0xc6 => 0x707c, 0xc7 => 0x6d4a, 0xc8 => 0x5179, + 0xc9 => 0x54a8, 0xca => 0x8d44, 0xcb => 0x59ff, 0xcc => 0x6ecb, + 0xcd => 0x6dc4, 0xce => 0x5b5c, 0xcf => 0x7d2b, 0xd0 => 0x4ed4, + 0xd1 => 0x7c7d, 0xd2 => 0x6ed3, 0xd3 => 0x5b50, 0xd4 => 0x81ea, + 0xd5 => 0x6e0d, 0xd6 => 0x5b57, 0xd7 => 0x9b03, 0xd8 => 0x68d5, + 0xd9 => 0x8e2a, 0xda => 0x5b97, 0xdb => 0x7efc, 0xdc => 0x603b, + 0xdd => 0x7eb5, 0xde => 0x90b9, 0xdf => 0x8d70, 0xe0 => 0x594f, + 0xe1 => 0x63cd, 0xe2 => 0x79df, 0xe3 => 0x8db3, 0xe4 => 0x5352, + 0xe5 => 0x65cf, 0xe6 => 0x7956, 0xe7 => 0x8bc5, 0xe8 => 0x963b, + 0xe9 => 0x7ec4, 0xea => 0x94bb, 0xeb => 0x7e82, 0xec => 0x5634, + 0xed => 0x9189, 0xee => 0x6700, 0xef => 0x7f6a, 0xf0 => 0x5c0a, + 0xf1 => 0x9075, 0xf2 => 0x6628, 0xf3 => 0x5de6, 0xf4 => 0x4f50, + 0xf5 => 0x67de, 0xf6 => 0x505a, 0xf7 => 0x4f5c, 0xf8 => 0x5750, + 0xf9 => 0x5ea7, + }, + 0xd8 => { + 0xa1 => 0x4e8d, 0xa2 => 0x4e0c, 0xa3 => 0x5140, 0xa4 => 0x4e10, + 0xa5 => 0x5eff, 0xa6 => 0x5345, 0xa7 => 0x4e15, 0xa8 => 0x4e98, + 0xa9 => 0x4e1e, 0xaa => 0x9b32, 0xab => 0x5b6c, 0xac => 0x5669, + 0xad => 0x4e28, 0xae => 0x79ba, 0xaf => 0x4e3f, 0xb0 => 0x5315, + 0xb1 => 0x4e47, 0xb2 => 0x592d, 0xb3 => 0x723b, 0xb4 => 0x536e, + 0xb5 => 0x6c10, 0xb6 => 0x56df, 0xb7 => 0x80e4, 0xb8 => 0x9997, + 0xb9 => 0x6bd3, 0xba => 0x777e, 0xbb => 0x9f17, 0xbc => 0x4e36, + 0xbd => 0x4e9f, 0xbe => 0x9f10, 0xbf => 0x4e5c, 0xc0 => 0x4e69, + 0xc1 => 0x4e93, 0xc2 => 0x8288, 0xc3 => 0x5b5b, 0xc4 => 0x556c, + 0xc5 => 0x560f, 0xc6 => 0x4ec4, 0xc7 => 0x538d, 0xc8 => 0x539d, + 0xc9 => 0x53a3, 0xca => 0x53a5, 0xcb => 0x53ae, 0xcc => 0x9765, + 0xcd => 0x8d5d, 0xce => 0x531a, 0xcf => 0x53f5, 0xd0 => 0x5326, + 0xd1 => 0x532e, 0xd2 => 0x533e, 0xd3 => 0x8d5c, 0xd4 => 0x5366, + 0xd5 => 0x5363, 0xd6 => 0x5202, 0xd7 => 0x5208, 0xd8 => 0x520e, + 0xd9 => 0x522d, 0xda => 0x5233, 0xdb => 0x523f, 0xdc => 0x5240, + 0xdd => 0x524c, 0xde => 0x525e, 0xdf => 0x5261, 0xe0 => 0x525c, + 0xe1 => 0x84af, 0xe2 => 0x527d, 0xe3 => 0x5282, 0xe4 => 0x5281, + 0xe5 => 0x5290, 0xe6 => 0x5293, 0xe7 => 0x5182, 0xe8 => 0x7f54, + 0xe9 => 0x4ebb, 0xea => 0x4ec3, 0xeb => 0x4ec9, 0xec => 0x4ec2, + 0xed => 0x4ee8, 0xee => 0x4ee1, 0xef => 0x4eeb, 0xf0 => 0x4ede, + 0xf1 => 0x4f1b, 0xf2 => 0x4ef3, 0xf3 => 0x4f22, 0xf4 => 0x4f64, + 0xf5 => 0x4ef5, 0xf6 => 0x4f25, 0xf7 => 0x4f27, 0xf8 => 0x4f09, + 0xf9 => 0x4f2b, 0xfa => 0x4f5e, 0xfb => 0x4f67, 0xfc => 0x6538, + 0xfd => 0x4f5a, 0xfe => 0x4f5d, + }, + 0xd9 => { + 0xa1 => 0x4f5f, 0xa2 => 0x4f57, 0xa3 => 0x4f32, 0xa4 => 0x4f3d, + 0xa5 => 0x4f76, 0xa6 => 0x4f74, 0xa7 => 0x4f91, 0xa8 => 0x4f89, + 0xa9 => 0x4f83, 0xaa => 0x4f8f, 0xab => 0x4f7e, 0xac => 0x4f7b, + 0xad => 0x4faa, 0xae => 0x4f7c, 0xaf => 0x4fac, 0xb0 => 0x4f94, + 0xb1 => 0x4fe6, 0xb2 => 0x4fe8, 0xb3 => 0x4fea, 0xb4 => 0x4fc5, + 0xb5 => 0x4fda, 0xb6 => 0x4fe3, 0xb7 => 0x4fdc, 0xb8 => 0x4fd1, + 0xb9 => 0x4fdf, 0xba => 0x4ff8, 0xbb => 0x5029, 0xbc => 0x504c, + 0xbd => 0x4ff3, 0xbe => 0x502c, 0xbf => 0x500f, 0xc0 => 0x502e, + 0xc1 => 0x502d, 0xc2 => 0x4ffe, 0xc3 => 0x501c, 0xc4 => 0x500c, + 0xc5 => 0x5025, 0xc6 => 0x5028, 0xc7 => 0x507e, 0xc8 => 0x5043, + 0xc9 => 0x5055, 0xca => 0x5048, 0xcb => 0x504e, 0xcc => 0x506c, + 0xcd => 0x507b, 0xce => 0x50a5, 0xcf => 0x50a7, 0xd0 => 0x50a9, + 0xd1 => 0x50ba, 0xd2 => 0x50d6, 0xd3 => 0x5106, 0xd4 => 0x50ed, + 0xd5 => 0x50ec, 0xd6 => 0x50e6, 0xd7 => 0x50ee, 0xd8 => 0x5107, + 0xd9 => 0x510b, 0xda => 0x4edd, 0xdb => 0x6c3d, 0xdc => 0x4f58, + 0xdd => 0x4f65, 0xde => 0x4fce, 0xdf => 0x9fa0, 0xe0 => 0x6c46, + 0xe1 => 0x7c74, 0xe2 => 0x516e, 0xe3 => 0x5dfd, 0xe4 => 0x9ec9, + 0xe5 => 0x9998, 0xe6 => 0x5181, 0xe7 => 0x5914, 0xe8 => 0x52f9, + 0xe9 => 0x530d, 0xea => 0x8a07, 0xeb => 0x5310, 0xec => 0x51eb, + 0xed => 0x5919, 0xee => 0x5155, 0xef => 0x4ea0, 0xf0 => 0x5156, + 0xf1 => 0x4eb3, 0xf2 => 0x886e, 0xf3 => 0x88a4, 0xf4 => 0x4eb5, + 0xf5 => 0x8114, 0xf6 => 0x88d2, 0xf7 => 0x7980, 0xf8 => 0x5b34, + 0xf9 => 0x8803, 0xfa => 0x7fb8, 0xfb => 0x51ab, 0xfc => 0x51b1, + 0xfd => 0x51bd, 0xfe => 0x51bc, + }, + 0xda => { + 0xa1 => 0x51c7, 0xa2 => 0x5196, 0xa3 => 0x51a2, 0xa4 => 0x51a5, + 0xa5 => 0x8ba0, 0xa6 => 0x8ba6, 0xa7 => 0x8ba7, 0xa8 => 0x8baa, + 0xa9 => 0x8bb4, 0xaa => 0x8bb5, 0xab => 0x8bb7, 0xac => 0x8bc2, + 0xad => 0x8bc3, 0xae => 0x8bcb, 0xaf => 0x8bcf, 0xb0 => 0x8bce, + 0xb1 => 0x8bd2, 0xb2 => 0x8bd3, 0xb3 => 0x8bd4, 0xb4 => 0x8bd6, + 0xb5 => 0x8bd8, 0xb6 => 0x8bd9, 0xb7 => 0x8bdc, 0xb8 => 0x8bdf, + 0xb9 => 0x8be0, 0xba => 0x8be4, 0xbb => 0x8be8, 0xbc => 0x8be9, + 0xbd => 0x8bee, 0xbe => 0x8bf0, 0xbf => 0x8bf3, 0xc0 => 0x8bf6, + 0xc1 => 0x8bf9, 0xc2 => 0x8bfc, 0xc3 => 0x8bff, 0xc4 => 0x8c00, + 0xc5 => 0x8c02, 0xc6 => 0x8c04, 0xc7 => 0x8c07, 0xc8 => 0x8c0c, + 0xc9 => 0x8c0f, 0xca => 0x8c11, 0xcb => 0x8c12, 0xcc => 0x8c14, + 0xcd => 0x8c15, 0xce => 0x8c16, 0xcf => 0x8c19, 0xd0 => 0x8c1b, + 0xd1 => 0x8c18, 0xd2 => 0x8c1d, 0xd3 => 0x8c1f, 0xd4 => 0x8c20, + 0xd5 => 0x8c21, 0xd6 => 0x8c25, 0xd7 => 0x8c27, 0xd8 => 0x8c2a, + 0xd9 => 0x8c2b, 0xda => 0x8c2e, 0xdb => 0x8c2f, 0xdc => 0x8c32, + 0xdd => 0x8c33, 0xde => 0x8c35, 0xdf => 0x8c36, 0xe0 => 0x5369, + 0xe1 => 0x537a, 0xe2 => 0x961d, 0xe3 => 0x9622, 0xe4 => 0x9621, + 0xe5 => 0x9631, 0xe6 => 0x962a, 0xe7 => 0x963d, 0xe8 => 0x963c, + 0xe9 => 0x9642, 0xea => 0x9649, 0xeb => 0x9654, 0xec => 0x965f, + 0xed => 0x9667, 0xee => 0x966c, 0xef => 0x9672, 0xf0 => 0x9674, + 0xf1 => 0x9688, 0xf2 => 0x968d, 0xf3 => 0x9697, 0xf4 => 0x96b0, + 0xf5 => 0x9097, 0xf6 => 0x909b, 0xf7 => 0x909d, 0xf8 => 0x9099, + 0xf9 => 0x90ac, 0xfa => 0x90a1, 0xfb => 0x90b4, 0xfc => 0x90b3, + 0xfd => 0x90b6, 0xfe => 0x90ba, + }, + 0xdb => { + 0xa1 => 0x90b8, 0xa2 => 0x90b0, 0xa3 => 0x90cf, 0xa4 => 0x90c5, + 0xa5 => 0x90be, 0xa6 => 0x90d0, 0xa7 => 0x90c4, 0xa8 => 0x90c7, + 0xa9 => 0x90d3, 0xaa => 0x90e6, 0xab => 0x90e2, 0xac => 0x90dc, + 0xad => 0x90d7, 0xae => 0x90db, 0xaf => 0x90eb, 0xb0 => 0x90ef, + 0xb1 => 0x90fe, 0xb2 => 0x9104, 0xb3 => 0x9122, 0xb4 => 0x911e, + 0xb5 => 0x9123, 0xb6 => 0x9131, 0xb7 => 0x912f, 0xb8 => 0x9139, + 0xb9 => 0x9143, 0xba => 0x9146, 0xbb => 0x520d, 0xbc => 0x5942, + 0xbd => 0x52a2, 0xbe => 0x52ac, 0xbf => 0x52ad, 0xc0 => 0x52be, + 0xc1 => 0x54ff, 0xc2 => 0x52d0, 0xc3 => 0x52d6, 0xc4 => 0x52f0, + 0xc5 => 0x53df, 0xc6 => 0x71ee, 0xc7 => 0x77cd, 0xc8 => 0x5ef4, + 0xc9 => 0x51f5, 0xca => 0x51fc, 0xcb => 0x9b2f, 0xcc => 0x53b6, + 0xcd => 0x5f01, 0xce => 0x755a, 0xcf => 0x5def, 0xd0 => 0x574c, + 0xd1 => 0x57a9, 0xd2 => 0x57a1, 0xd3 => 0x587e, 0xd4 => 0x58bc, + 0xd5 => 0x58c5, 0xd6 => 0x58d1, 0xd7 => 0x5729, 0xd8 => 0x572c, + 0xd9 => 0x572a, 0xda => 0x5733, 0xdb => 0x5739, 0xdc => 0x572e, + 0xdd => 0x572f, 0xde => 0x575c, 0xdf => 0x573b, 0xe0 => 0x5742, + 0xe1 => 0x5769, 0xe2 => 0x5785, 0xe3 => 0x576b, 0xe4 => 0x5786, + 0xe5 => 0x577c, 0xe6 => 0x577b, 0xe7 => 0x5768, 0xe8 => 0x576d, + 0xe9 => 0x5776, 0xea => 0x5773, 0xeb => 0x57ad, 0xec => 0x57a4, + 0xed => 0x578c, 0xee => 0x57b2, 0xef => 0x57cf, 0xf0 => 0x57a7, + 0xf1 => 0x57b4, 0xf2 => 0x5793, 0xf3 => 0x57a0, 0xf4 => 0x57d5, + 0xf5 => 0x57d8, 0xf6 => 0x57da, 0xf7 => 0x57d9, 0xf8 => 0x57d2, + 0xf9 => 0x57b8, 0xfa => 0x57f4, 0xfb => 0x57ef, 0xfc => 0x57f8, + 0xfd => 0x57e4, 0xfe => 0x57dd, + }, + 0xdc => { + 0xa1 => 0x580b, 0xa2 => 0x580d, 0xa3 => 0x57fd, 0xa4 => 0x57ed, + 0xa5 => 0x5800, 0xa6 => 0x581e, 0xa7 => 0x5819, 0xa8 => 0x5844, + 0xa9 => 0x5820, 0xaa => 0x5865, 0xab => 0x586c, 0xac => 0x5881, + 0xad => 0x5889, 0xae => 0x589a, 0xaf => 0x5880, 0xb0 => 0x99a8, + 0xb1 => 0x9f19, 0xb2 => 0x61ff, 0xb3 => 0x8279, 0xb4 => 0x827d, + 0xb5 => 0x827f, 0xb6 => 0x828f, 0xb7 => 0x828a, 0xb8 => 0x82a8, + 0xb9 => 0x8284, 0xba => 0x828e, 0xbb => 0x8291, 0xbc => 0x8297, + 0xbd => 0x8299, 0xbe => 0x82ab, 0xbf => 0x82b8, 0xc0 => 0x82be, + 0xc1 => 0x82b0, 0xc2 => 0x82c8, 0xc3 => 0x82ca, 0xc4 => 0x82e3, + 0xc5 => 0x8298, 0xc6 => 0x82b7, 0xc7 => 0x82ae, 0xc8 => 0x82cb, + 0xc9 => 0x82cc, 0xca => 0x82c1, 0xcb => 0x82a9, 0xcc => 0x82b4, + 0xcd => 0x82a1, 0xce => 0x82aa, 0xcf => 0x829f, 0xd0 => 0x82c4, + 0xd1 => 0x82ce, 0xd2 => 0x82a4, 0xd3 => 0x82e1, 0xd4 => 0x8309, + 0xd5 => 0x82f7, 0xd6 => 0x82e4, 0xd7 => 0x830f, 0xd8 => 0x8307, + 0xd9 => 0x82dc, 0xda => 0x82f4, 0xdb => 0x82d2, 0xdc => 0x82d8, + 0xdd => 0x830c, 0xde => 0x82fb, 0xdf => 0x82d3, 0xe0 => 0x8311, + 0xe1 => 0x831a, 0xe2 => 0x8306, 0xe3 => 0x8314, 0xe4 => 0x8315, + 0xe5 => 0x82e0, 0xe6 => 0x82d5, 0xe7 => 0x831c, 0xe8 => 0x8351, + 0xe9 => 0x835b, 0xea => 0x835c, 0xeb => 0x8308, 0xec => 0x8392, + 0xed => 0x833c, 0xee => 0x8334, 0xef => 0x8331, 0xf0 => 0x839b, + 0xf1 => 0x835e, 0xf2 => 0x832f, 0xf3 => 0x834f, 0xf4 => 0x8347, + 0xf5 => 0x8343, 0xf6 => 0x835f, 0xf7 => 0x8340, 0xf8 => 0x8317, + 0xf9 => 0x8360, 0xfa => 0x832d, 0xfb => 0x833a, 0xfc => 0x8333, + 0xfd => 0x8366, 0xfe => 0x8365, + }, + 0xdd => { + 0xa1 => 0x8368, 0xa2 => 0x831b, 0xa3 => 0x8369, 0xa4 => 0x836c, + 0xa5 => 0x836a, 0xa6 => 0x836d, 0xa7 => 0x836e, 0xa8 => 0x83b0, + 0xa9 => 0x8378, 0xaa => 0x83b3, 0xab => 0x83b4, 0xac => 0x83a0, + 0xad => 0x83aa, 0xae => 0x8393, 0xaf => 0x839c, 0xb0 => 0x8385, + 0xb1 => 0x837c, 0xb2 => 0x83b6, 0xb3 => 0x83a9, 0xb4 => 0x837d, + 0xb5 => 0x83b8, 0xb6 => 0x837b, 0xb7 => 0x8398, 0xb8 => 0x839e, + 0xb9 => 0x83a8, 0xba => 0x83ba, 0xbb => 0x83bc, 0xbc => 0x83c1, + 0xbd => 0x8401, 0xbe => 0x83e5, 0xbf => 0x83d8, 0xc0 => 0x5807, + 0xc1 => 0x8418, 0xc2 => 0x840b, 0xc3 => 0x83dd, 0xc4 => 0x83fd, + 0xc5 => 0x83d6, 0xc6 => 0x841c, 0xc7 => 0x8438, 0xc8 => 0x8411, + 0xc9 => 0x8406, 0xca => 0x83d4, 0xcb => 0x83df, 0xcc => 0x840f, + 0xcd => 0x8403, 0xce => 0x83f8, 0xcf => 0x83f9, 0xd0 => 0x83ea, + 0xd1 => 0x83c5, 0xd2 => 0x83c0, 0xd3 => 0x8426, 0xd4 => 0x83f0, + 0xd5 => 0x83e1, 0xd6 => 0x845c, 0xd7 => 0x8451, 0xd8 => 0x845a, + 0xd9 => 0x8459, 0xda => 0x8473, 0xdb => 0x8487, 0xdc => 0x8488, + 0xdd => 0x847a, 0xde => 0x8489, 0xdf => 0x8478, 0xe0 => 0x843c, + 0xe1 => 0x8446, 0xe2 => 0x8469, 0xe3 => 0x8476, 0xe4 => 0x848c, + 0xe5 => 0x848e, 0xe6 => 0x8431, 0xe7 => 0x846d, 0xe8 => 0x84c1, + 0xe9 => 0x84cd, 0xea => 0x84d0, 0xeb => 0x84e6, 0xec => 0x84bd, + 0xed => 0x84d3, 0xee => 0x84ca, 0xef => 0x84bf, 0xf0 => 0x84ba, + 0xf1 => 0x84e0, 0xf2 => 0x84a1, 0xf3 => 0x84b9, 0xf4 => 0x84b4, + 0xf5 => 0x8497, 0xf6 => 0x84e5, 0xf7 => 0x84e3, 0xf8 => 0x850c, + 0xf9 => 0x750d, 0xfa => 0x8538, 0xfb => 0x84f0, 0xfc => 0x8539, + 0xfd => 0x851f, 0xfe => 0x853a, + }, + 0xde => { + 0xa1 => 0x8556, 0xa2 => 0x853b, 0xa3 => 0x84ff, 0xa4 => 0x84fc, + 0xa5 => 0x8559, 0xa6 => 0x8548, 0xa7 => 0x8568, 0xa8 => 0x8564, + 0xa9 => 0x855e, 0xaa => 0x857a, 0xab => 0x77a2, 0xac => 0x8543, + 0xad => 0x8572, 0xae => 0x857b, 0xaf => 0x85a4, 0xb0 => 0x85a8, + 0xb1 => 0x8587, 0xb2 => 0x858f, 0xb3 => 0x8579, 0xb4 => 0x85ae, + 0xb5 => 0x859c, 0xb6 => 0x8585, 0xb7 => 0x85b9, 0xb8 => 0x85b7, + 0xb9 => 0x85b0, 0xba => 0x85d3, 0xbb => 0x85c1, 0xbc => 0x85dc, + 0xbd => 0x85ff, 0xbe => 0x8627, 0xbf => 0x8605, 0xc0 => 0x8629, + 0xc1 => 0x8616, 0xc2 => 0x863c, 0xc3 => 0x5efe, 0xc4 => 0x5f08, + 0xc5 => 0x593c, 0xc6 => 0x5941, 0xc7 => 0x8037, 0xc8 => 0x5955, + 0xc9 => 0x595a, 0xca => 0x5958, 0xcb => 0x530f, 0xcc => 0x5c22, + 0xcd => 0x5c25, 0xce => 0x5c2c, 0xcf => 0x5c34, 0xd0 => 0x624c, + 0xd1 => 0x626a, 0xd2 => 0x629f, 0xd3 => 0x62bb, 0xd4 => 0x62ca, + 0xd5 => 0x62da, 0xd6 => 0x62d7, 0xd7 => 0x62ee, 0xd8 => 0x6322, + 0xd9 => 0x62f6, 0xda => 0x6339, 0xdb => 0x634b, 0xdc => 0x6343, + 0xdd => 0x63ad, 0xde => 0x63f6, 0xdf => 0x6371, 0xe0 => 0x637a, + 0xe1 => 0x638e, 0xe2 => 0x63b4, 0xe3 => 0x636d, 0xe4 => 0x63ac, + 0xe5 => 0x638a, 0xe6 => 0x6369, 0xe7 => 0x63ae, 0xe8 => 0x63bc, + 0xe9 => 0x63f2, 0xea => 0x63f8, 0xeb => 0x63e0, 0xec => 0x63ff, + 0xed => 0x63c4, 0xee => 0x63de, 0xef => 0x63ce, 0xf0 => 0x6452, + 0xf1 => 0x63c6, 0xf2 => 0x63be, 0xf3 => 0x6445, 0xf4 => 0x6441, + 0xf5 => 0x640b, 0xf6 => 0x641b, 0xf7 => 0x6420, 0xf8 => 0x640c, + 0xf9 => 0x6426, 0xfa => 0x6421, 0xfb => 0x645e, 0xfc => 0x6484, + 0xfd => 0x646d, 0xfe => 0x6496, + }, + 0xdf => { + 0xa1 => 0x647a, 0xa2 => 0x64b7, 0xa3 => 0x64b8, 0xa4 => 0x6499, + 0xa5 => 0x64ba, 0xa6 => 0x64c0, 0xa7 => 0x64d0, 0xa8 => 0x64d7, + 0xa9 => 0x64e4, 0xaa => 0x64e2, 0xab => 0x6509, 0xac => 0x6525, + 0xad => 0x652e, 0xae => 0x5f0b, 0xaf => 0x5fd2, 0xb0 => 0x7519, + 0xb1 => 0x5f11, 0xb2 => 0x535f, 0xb3 => 0x53f1, 0xb4 => 0x53fd, + 0xb5 => 0x53e9, 0xb6 => 0x53e8, 0xb7 => 0x53fb, 0xb8 => 0x5412, + 0xb9 => 0x5416, 0xba => 0x5406, 0xbb => 0x544b, 0xbc => 0x5452, + 0xbd => 0x5453, 0xbe => 0x5454, 0xbf => 0x5456, 0xc0 => 0x5443, + 0xc1 => 0x5421, 0xc2 => 0x5457, 0xc3 => 0x5459, 0xc4 => 0x5423, + 0xc5 => 0x5432, 0xc6 => 0x5482, 0xc7 => 0x5494, 0xc8 => 0x5477, + 0xc9 => 0x5471, 0xca => 0x5464, 0xcb => 0x549a, 0xcc => 0x549b, + 0xcd => 0x5484, 0xce => 0x5476, 0xcf => 0x5466, 0xd0 => 0x549d, + 0xd1 => 0x54d0, 0xd2 => 0x54ad, 0xd3 => 0x54c2, 0xd4 => 0x54b4, + 0xd5 => 0x54d2, 0xd6 => 0x54a7, 0xd7 => 0x54a6, 0xd8 => 0x54d3, + 0xd9 => 0x54d4, 0xda => 0x5472, 0xdb => 0x54a3, 0xdc => 0x54d5, + 0xdd => 0x54bb, 0xde => 0x54bf, 0xdf => 0x54cc, 0xe0 => 0x54d9, + 0xe1 => 0x54da, 0xe2 => 0x54dc, 0xe3 => 0x54a9, 0xe4 => 0x54aa, + 0xe5 => 0x54a4, 0xe6 => 0x54dd, 0xe7 => 0x54cf, 0xe8 => 0x54de, + 0xe9 => 0x551b, 0xea => 0x54e7, 0xeb => 0x5520, 0xec => 0x54fd, + 0xed => 0x5514, 0xee => 0x54f3, 0xef => 0x5522, 0xf0 => 0x5523, + 0xf1 => 0x550f, 0xf2 => 0x5511, 0xf3 => 0x5527, 0xf4 => 0x552a, + 0xf5 => 0x5567, 0xf6 => 0x558f, 0xf7 => 0x55b5, 0xf8 => 0x5549, + 0xf9 => 0x556d, 0xfa => 0x5541, 0xfb => 0x5555, 0xfc => 0x553f, + 0xfd => 0x5550, 0xfe => 0x553c, + }, + 0xe0 => { + 0xa1 => 0x5537, 0xa2 => 0x5556, 0xa3 => 0x5575, 0xa4 => 0x5576, + 0xa5 => 0x5577, 0xa6 => 0x5533, 0xa7 => 0x5530, 0xa8 => 0x555c, + 0xa9 => 0x558b, 0xaa => 0x55d2, 0xab => 0x5583, 0xac => 0x55b1, + 0xad => 0x55b9, 0xae => 0x5588, 0xaf => 0x5581, 0xb0 => 0x559f, + 0xb1 => 0x557e, 0xb2 => 0x55d6, 0xb3 => 0x5591, 0xb4 => 0x557b, + 0xb5 => 0x55df, 0xb6 => 0x55bd, 0xb7 => 0x55be, 0xb8 => 0x5594, + 0xb9 => 0x5599, 0xba => 0x55ea, 0xbb => 0x55f7, 0xbc => 0x55c9, + 0xbd => 0x561f, 0xbe => 0x55d1, 0xbf => 0x55eb, 0xc0 => 0x55ec, + 0xc1 => 0x55d4, 0xc2 => 0x55e6, 0xc3 => 0x55dd, 0xc4 => 0x55c4, + 0xc5 => 0x55ef, 0xc6 => 0x55e5, 0xc7 => 0x55f2, 0xc8 => 0x55f3, + 0xc9 => 0x55cc, 0xca => 0x55cd, 0xcb => 0x55e8, 0xcc => 0x55f5, + 0xcd => 0x55e4, 0xce => 0x8f94, 0xcf => 0x561e, 0xd0 => 0x5608, + 0xd1 => 0x560c, 0xd2 => 0x5601, 0xd3 => 0x5624, 0xd4 => 0x5623, + 0xd5 => 0x55fe, 0xd6 => 0x5600, 0xd7 => 0x5627, 0xd8 => 0x562d, + 0xd9 => 0x5658, 0xda => 0x5639, 0xdb => 0x5657, 0xdc => 0x562c, + 0xdd => 0x564d, 0xde => 0x5662, 0xdf => 0x5659, 0xe0 => 0x565c, + 0xe1 => 0x564c, 0xe2 => 0x5654, 0xe3 => 0x5686, 0xe4 => 0x5664, + 0xe5 => 0x5671, 0xe6 => 0x566b, 0xe7 => 0x567b, 0xe8 => 0x567c, + 0xe9 => 0x5685, 0xea => 0x5693, 0xeb => 0x56af, 0xec => 0x56d4, + 0xed => 0x56d7, 0xee => 0x56dd, 0xef => 0x56e1, 0xf0 => 0x56f5, + 0xf1 => 0x56eb, 0xf2 => 0x56f9, 0xf3 => 0x56ff, 0xf4 => 0x5704, + 0xf5 => 0x570a, 0xf6 => 0x5709, 0xf7 => 0x571c, 0xf8 => 0x5e0f, + 0xf9 => 0x5e19, 0xfa => 0x5e14, 0xfb => 0x5e11, 0xfc => 0x5e31, + 0xfd => 0x5e3b, 0xfe => 0x5e3c, + }, + 0xe1 => { + 0xa1 => 0x5e37, 0xa2 => 0x5e44, 0xa3 => 0x5e54, 0xa4 => 0x5e5b, + 0xa5 => 0x5e5e, 0xa6 => 0x5e61, 0xa7 => 0x5c8c, 0xa8 => 0x5c7a, + 0xa9 => 0x5c8d, 0xaa => 0x5c90, 0xab => 0x5c96, 0xac => 0x5c88, + 0xad => 0x5c98, 0xae => 0x5c99, 0xaf => 0x5c91, 0xb0 => 0x5c9a, + 0xb1 => 0x5c9c, 0xb2 => 0x5cb5, 0xb3 => 0x5ca2, 0xb4 => 0x5cbd, + 0xb5 => 0x5cac, 0xb6 => 0x5cab, 0xb7 => 0x5cb1, 0xb8 => 0x5ca3, + 0xb9 => 0x5cc1, 0xba => 0x5cb7, 0xbb => 0x5cc4, 0xbc => 0x5cd2, + 0xbd => 0x5ce4, 0xbe => 0x5ccb, 0xbf => 0x5ce5, 0xc0 => 0x5d02, + 0xc1 => 0x5d03, 0xc2 => 0x5d27, 0xc3 => 0x5d26, 0xc4 => 0x5d2e, + 0xc5 => 0x5d24, 0xc6 => 0x5d1e, 0xc7 => 0x5d06, 0xc8 => 0x5d1b, + 0xc9 => 0x5d58, 0xca => 0x5d3e, 0xcb => 0x5d34, 0xcc => 0x5d3d, + 0xcd => 0x5d6c, 0xce => 0x5d5b, 0xcf => 0x5d6f, 0xd0 => 0x5d5d, + 0xd1 => 0x5d6b, 0xd2 => 0x5d4b, 0xd3 => 0x5d4a, 0xd4 => 0x5d69, + 0xd5 => 0x5d74, 0xd6 => 0x5d82, 0xd7 => 0x5d99, 0xd8 => 0x5d9d, + 0xd9 => 0x8c73, 0xda => 0x5db7, 0xdb => 0x5dc5, 0xdc => 0x5f73, + 0xdd => 0x5f77, 0xde => 0x5f82, 0xdf => 0x5f87, 0xe0 => 0x5f89, + 0xe1 => 0x5f8c, 0xe2 => 0x5f95, 0xe3 => 0x5f99, 0xe4 => 0x5f9c, + 0xe5 => 0x5fa8, 0xe6 => 0x5fad, 0xe7 => 0x5fb5, 0xe8 => 0x5fbc, + 0xe9 => 0x8862, 0xea => 0x5f61, 0xeb => 0x72ad, 0xec => 0x72b0, + 0xed => 0x72b4, 0xee => 0x72b7, 0xef => 0x72b8, 0xf0 => 0x72c3, + 0xf1 => 0x72c1, 0xf2 => 0x72ce, 0xf3 => 0x72cd, 0xf4 => 0x72d2, + 0xf5 => 0x72e8, 0xf6 => 0x72ef, 0xf7 => 0x72e9, 0xf8 => 0x72f2, + 0xf9 => 0x72f4, 0xfa => 0x72f7, 0xfb => 0x7301, 0xfc => 0x72f3, + 0xfd => 0x7303, 0xfe => 0x72fa, + }, + 0xe2 => { + 0xa1 => 0x72fb, 0xa2 => 0x7317, 0xa3 => 0x7313, 0xa4 => 0x7321, + 0xa5 => 0x730a, 0xa6 => 0x731e, 0xa7 => 0x731d, 0xa8 => 0x7315, + 0xa9 => 0x7322, 0xaa => 0x7339, 0xab => 0x7325, 0xac => 0x732c, + 0xad => 0x7338, 0xae => 0x7331, 0xaf => 0x7350, 0xb0 => 0x734d, + 0xb1 => 0x7357, 0xb2 => 0x7360, 0xb3 => 0x736c, 0xb4 => 0x736f, + 0xb5 => 0x737e, 0xb6 => 0x821b, 0xb7 => 0x5925, 0xb8 => 0x98e7, + 0xb9 => 0x5924, 0xba => 0x5902, 0xbb => 0x9963, 0xbc => 0x9967, + 0xbd => 0x9968, 0xbe => 0x9969, 0xbf => 0x996a, 0xc0 => 0x996b, + 0xc1 => 0x996c, 0xc2 => 0x9974, 0xc3 => 0x9977, 0xc4 => 0x997d, + 0xc5 => 0x9980, 0xc6 => 0x9984, 0xc7 => 0x9987, 0xc8 => 0x998a, + 0xc9 => 0x998d, 0xca => 0x9990, 0xcb => 0x9991, 0xcc => 0x9993, + 0xcd => 0x9994, 0xce => 0x9995, 0xcf => 0x5e80, 0xd0 => 0x5e91, + 0xd1 => 0x5e8b, 0xd2 => 0x5e96, 0xd3 => 0x5ea5, 0xd4 => 0x5ea0, + 0xd5 => 0x5eb9, 0xd6 => 0x5eb5, 0xd7 => 0x5ebe, 0xd8 => 0x5eb3, + 0xd9 => 0x8d53, 0xda => 0x5ed2, 0xdb => 0x5ed1, 0xdc => 0x5edb, + 0xdd => 0x5ee8, 0xde => 0x5eea, 0xdf => 0x81ba, 0xe0 => 0x5fc4, + 0xe1 => 0x5fc9, 0xe2 => 0x5fd6, 0xe3 => 0x5fcf, 0xe4 => 0x6003, + 0xe5 => 0x5fee, 0xe6 => 0x6004, 0xe7 => 0x5fe1, 0xe8 => 0x5fe4, + 0xe9 => 0x5ffe, 0xea => 0x6005, 0xeb => 0x6006, 0xec => 0x5fea, + 0xed => 0x5fed, 0xee => 0x5ff8, 0xef => 0x6019, 0xf0 => 0x6035, + 0xf1 => 0x6026, 0xf2 => 0x601b, 0xf3 => 0x600f, 0xf4 => 0x600d, + 0xf5 => 0x6029, 0xf6 => 0x602b, 0xf7 => 0x600a, 0xf8 => 0x603f, + 0xf9 => 0x6021, 0xfa => 0x6078, 0xfb => 0x6079, 0xfc => 0x607b, + 0xfd => 0x607a, 0xfe => 0x6042, + }, + 0xe3 => { + 0xa1 => 0x606a, 0xa2 => 0x607d, 0xa3 => 0x6096, 0xa4 => 0x609a, + 0xa5 => 0x60ad, 0xa6 => 0x609d, 0xa7 => 0x6083, 0xa8 => 0x6092, + 0xa9 => 0x608c, 0xaa => 0x609b, 0xab => 0x60ec, 0xac => 0x60bb, + 0xad => 0x60b1, 0xae => 0x60dd, 0xaf => 0x60d8, 0xb0 => 0x60c6, + 0xb1 => 0x60da, 0xb2 => 0x60b4, 0xb3 => 0x6120, 0xb4 => 0x6126, + 0xb5 => 0x6115, 0xb6 => 0x6123, 0xb7 => 0x60f4, 0xb8 => 0x6100, + 0xb9 => 0x610e, 0xba => 0x612b, 0xbb => 0x614a, 0xbc => 0x6175, + 0xbd => 0x61ac, 0xbe => 0x6194, 0xbf => 0x61a7, 0xc0 => 0x61b7, + 0xc1 => 0x61d4, 0xc2 => 0x61f5, 0xc3 => 0x5fdd, 0xc4 => 0x96b3, + 0xc5 => 0x95e9, 0xc6 => 0x95eb, 0xc7 => 0x95f1, 0xc8 => 0x95f3, + 0xc9 => 0x95f5, 0xca => 0x95f6, 0xcb => 0x95fc, 0xcc => 0x95fe, + 0xcd => 0x9603, 0xce => 0x9604, 0xcf => 0x9606, 0xd0 => 0x9608, + 0xd1 => 0x960a, 0xd2 => 0x960b, 0xd3 => 0x960c, 0xd4 => 0x960d, + 0xd5 => 0x960f, 0xd6 => 0x9612, 0xd7 => 0x9615, 0xd8 => 0x9616, + 0xd9 => 0x9617, 0xda => 0x9619, 0xdb => 0x961a, 0xdc => 0x4e2c, + 0xdd => 0x723f, 0xde => 0x6215, 0xdf => 0x6c35, 0xe0 => 0x6c54, + 0xe1 => 0x6c5c, 0xe2 => 0x6c4a, 0xe3 => 0x6ca3, 0xe4 => 0x6c85, + 0xe5 => 0x6c90, 0xe6 => 0x6c94, 0xe7 => 0x6c8c, 0xe8 => 0x6c68, + 0xe9 => 0x6c69, 0xea => 0x6c74, 0xeb => 0x6c76, 0xec => 0x6c86, + 0xed => 0x6ca9, 0xee => 0x6cd0, 0xef => 0x6cd4, 0xf0 => 0x6cad, + 0xf1 => 0x6cf7, 0xf2 => 0x6cf8, 0xf3 => 0x6cf1, 0xf4 => 0x6cd7, + 0xf5 => 0x6cb2, 0xf6 => 0x6ce0, 0xf7 => 0x6cd6, 0xf8 => 0x6cfa, + 0xf9 => 0x6ceb, 0xfa => 0x6cee, 0xfb => 0x6cb1, 0xfc => 0x6cd3, + 0xfd => 0x6cef, 0xfe => 0x6cfe, + }, + 0xe4 => { + 0xa1 => 0x6d39, 0xa2 => 0x6d27, 0xa3 => 0x6d0c, 0xa4 => 0x6d43, + 0xa5 => 0x6d48, 0xa6 => 0x6d07, 0xa7 => 0x6d04, 0xa8 => 0x6d19, + 0xa9 => 0x6d0e, 0xaa => 0x6d2b, 0xab => 0x6d4d, 0xac => 0x6d2e, + 0xad => 0x6d35, 0xae => 0x6d1a, 0xaf => 0x6d4f, 0xb0 => 0x6d52, + 0xb1 => 0x6d54, 0xb2 => 0x6d33, 0xb3 => 0x6d91, 0xb4 => 0x6d6f, + 0xb5 => 0x6d9e, 0xb6 => 0x6da0, 0xb7 => 0x6d5e, 0xb8 => 0x6d93, + 0xb9 => 0x6d94, 0xba => 0x6d5c, 0xbb => 0x6d60, 0xbc => 0x6d7c, + 0xbd => 0x6d63, 0xbe => 0x6e1a, 0xbf => 0x6dc7, 0xc0 => 0x6dc5, + 0xc1 => 0x6dde, 0xc2 => 0x6e0e, 0xc3 => 0x6dbf, 0xc4 => 0x6de0, + 0xc5 => 0x6e11, 0xc6 => 0x6de6, 0xc7 => 0x6ddd, 0xc8 => 0x6dd9, + 0xc9 => 0x6e16, 0xca => 0x6dab, 0xcb => 0x6e0c, 0xcc => 0x6dae, + 0xcd => 0x6e2b, 0xce => 0x6e6e, 0xcf => 0x6e4e, 0xd0 => 0x6e6b, + 0xd1 => 0x6eb2, 0xd2 => 0x6e5f, 0xd3 => 0x6e86, 0xd4 => 0x6e53, + 0xd5 => 0x6e54, 0xd6 => 0x6e32, 0xd7 => 0x6e25, 0xd8 => 0x6e44, + 0xd9 => 0x6edf, 0xda => 0x6eb1, 0xdb => 0x6e98, 0xdc => 0x6ee0, + 0xdd => 0x6f2d, 0xde => 0x6ee2, 0xdf => 0x6ea5, 0xe0 => 0x6ea7, + 0xe1 => 0x6ebd, 0xe2 => 0x6ebb, 0xe3 => 0x6eb7, 0xe4 => 0x6ed7, + 0xe5 => 0x6eb4, 0xe6 => 0x6ecf, 0xe7 => 0x6e8f, 0xe8 => 0x6ec2, + 0xe9 => 0x6e9f, 0xea => 0x6f62, 0xeb => 0x6f46, 0xec => 0x6f47, + 0xed => 0x6f24, 0xee => 0x6f15, 0xef => 0x6ef9, 0xf0 => 0x6f2f, + 0xf1 => 0x6f36, 0xf2 => 0x6f4b, 0xf3 => 0x6f74, 0xf4 => 0x6f2a, + 0xf5 => 0x6f09, 0xf6 => 0x6f29, 0xf7 => 0x6f89, 0xf8 => 0x6f8d, + 0xf9 => 0x6f8c, 0xfa => 0x6f78, 0xfb => 0x6f72, 0xfc => 0x6f7c, + 0xfd => 0x6f7a, 0xfe => 0x6fd1, + }, + 0xe5 => { + 0xa1 => 0x6fc9, 0xa2 => 0x6fa7, 0xa3 => 0x6fb9, 0xa4 => 0x6fb6, + 0xa5 => 0x6fc2, 0xa6 => 0x6fe1, 0xa7 => 0x6fee, 0xa8 => 0x6fde, + 0xa9 => 0x6fe0, 0xaa => 0x6fef, 0xab => 0x701a, 0xac => 0x7023, + 0xad => 0x701b, 0xae => 0x7039, 0xaf => 0x7035, 0xb0 => 0x704f, + 0xb1 => 0x705e, 0xb2 => 0x5b80, 0xb3 => 0x5b84, 0xb4 => 0x5b95, + 0xb5 => 0x5b93, 0xb6 => 0x5ba5, 0xb7 => 0x5bb8, 0xb8 => 0x752f, + 0xb9 => 0x9a9e, 0xba => 0x6434, 0xbb => 0x5be4, 0xbc => 0x5bee, + 0xbd => 0x8930, 0xbe => 0x5bf0, 0xbf => 0x8e47, 0xc0 => 0x8b07, + 0xc1 => 0x8fb6, 0xc2 => 0x8fd3, 0xc3 => 0x8fd5, 0xc4 => 0x8fe5, + 0xc5 => 0x8fee, 0xc6 => 0x8fe4, 0xc7 => 0x8fe9, 0xc8 => 0x8fe6, + 0xc9 => 0x8ff3, 0xca => 0x8fe8, 0xcb => 0x9005, 0xcc => 0x9004, + 0xcd => 0x900b, 0xce => 0x9026, 0xcf => 0x9011, 0xd0 => 0x900d, + 0xd1 => 0x9016, 0xd2 => 0x9021, 0xd3 => 0x9035, 0xd4 => 0x9036, + 0xd5 => 0x902d, 0xd6 => 0x902f, 0xd7 => 0x9044, 0xd8 => 0x9051, + 0xd9 => 0x9052, 0xda => 0x9050, 0xdb => 0x9068, 0xdc => 0x9058, + 0xdd => 0x9062, 0xde => 0x905b, 0xdf => 0x66b9, 0xe0 => 0x9074, + 0xe1 => 0x907d, 0xe2 => 0x9082, 0xe3 => 0x9088, 0xe4 => 0x9083, + 0xe5 => 0x908b, 0xe6 => 0x5f50, 0xe7 => 0x5f57, 0xe8 => 0x5f56, + 0xe9 => 0x5f58, 0xea => 0x5c3b, 0xeb => 0x54ab, 0xec => 0x5c50, + 0xed => 0x5c59, 0xee => 0x5b71, 0xef => 0x5c63, 0xf0 => 0x5c66, + 0xf1 => 0x7fbc, 0xf2 => 0x5f2a, 0xf3 => 0x5f29, 0xf4 => 0x5f2d, + 0xf5 => 0x8274, 0xf6 => 0x5f3c, 0xf7 => 0x9b3b, 0xf8 => 0x5c6e, + 0xf9 => 0x5981, 0xfa => 0x5983, 0xfb => 0x598d, 0xfc => 0x59a9, + 0xfd => 0x59aa, 0xfe => 0x59a3, + }, + 0xe6 => { + 0xa1 => 0x5997, 0xa2 => 0x59ca, 0xa3 => 0x59ab, 0xa4 => 0x599e, + 0xa5 => 0x59a4, 0xa6 => 0x59d2, 0xa7 => 0x59b2, 0xa8 => 0x59af, + 0xa9 => 0x59d7, 0xaa => 0x59be, 0xab => 0x5a05, 0xac => 0x5a06, + 0xad => 0x59dd, 0xae => 0x5a08, 0xaf => 0x59e3, 0xb0 => 0x59d8, + 0xb1 => 0x59f9, 0xb2 => 0x5a0c, 0xb3 => 0x5a09, 0xb4 => 0x5a32, + 0xb5 => 0x5a34, 0xb6 => 0x5a11, 0xb7 => 0x5a23, 0xb8 => 0x5a13, + 0xb9 => 0x5a40, 0xba => 0x5a67, 0xbb => 0x5a4a, 0xbc => 0x5a55, + 0xbd => 0x5a3c, 0xbe => 0x5a62, 0xbf => 0x5a75, 0xc0 => 0x80ec, + 0xc1 => 0x5aaa, 0xc2 => 0x5a9b, 0xc3 => 0x5a77, 0xc4 => 0x5a7a, + 0xc5 => 0x5abe, 0xc6 => 0x5aeb, 0xc7 => 0x5ab2, 0xc8 => 0x5ad2, + 0xc9 => 0x5ad4, 0xca => 0x5ab8, 0xcb => 0x5ae0, 0xcc => 0x5ae3, + 0xcd => 0x5af1, 0xce => 0x5ad6, 0xcf => 0x5ae6, 0xd0 => 0x5ad8, + 0xd1 => 0x5adc, 0xd2 => 0x5b09, 0xd3 => 0x5b17, 0xd4 => 0x5b16, + 0xd5 => 0x5b32, 0xd6 => 0x5b37, 0xd7 => 0x5b40, 0xd8 => 0x5c15, + 0xd9 => 0x5c1c, 0xda => 0x5b5a, 0xdb => 0x5b65, 0xdc => 0x5b73, + 0xdd => 0x5b51, 0xde => 0x5b53, 0xdf => 0x5b62, 0xe0 => 0x9a75, + 0xe1 => 0x9a77, 0xe2 => 0x9a78, 0xe3 => 0x9a7a, 0xe4 => 0x9a7f, + 0xe5 => 0x9a7d, 0xe6 => 0x9a80, 0xe7 => 0x9a81, 0xe8 => 0x9a85, + 0xe9 => 0x9a88, 0xea => 0x9a8a, 0xeb => 0x9a90, 0xec => 0x9a92, + 0xed => 0x9a93, 0xee => 0x9a96, 0xef => 0x9a98, 0xf0 => 0x9a9b, + 0xf1 => 0x9a9c, 0xf2 => 0x9a9d, 0xf3 => 0x9a9f, 0xf4 => 0x9aa0, + 0xf5 => 0x9aa2, 0xf6 => 0x9aa3, 0xf7 => 0x9aa5, 0xf8 => 0x9aa7, + 0xf9 => 0x7e9f, 0xfa => 0x7ea1, 0xfb => 0x7ea3, 0xfc => 0x7ea5, + 0xfd => 0x7ea8, 0xfe => 0x7ea9, + }, + 0xe7 => { + 0xa1 => 0x7ead, 0xa2 => 0x7eb0, 0xa3 => 0x7ebe, 0xa4 => 0x7ec0, + 0xa5 => 0x7ec1, 0xa6 => 0x7ec2, 0xa7 => 0x7ec9, 0xa8 => 0x7ecb, + 0xa9 => 0x7ecc, 0xaa => 0x7ed0, 0xab => 0x7ed4, 0xac => 0x7ed7, + 0xad => 0x7edb, 0xae => 0x7ee0, 0xaf => 0x7ee1, 0xb0 => 0x7ee8, + 0xb1 => 0x7eeb, 0xb2 => 0x7eee, 0xb3 => 0x7eef, 0xb4 => 0x7ef1, + 0xb5 => 0x7ef2, 0xb6 => 0x7f0d, 0xb7 => 0x7ef6, 0xb8 => 0x7efa, + 0xb9 => 0x7efb, 0xba => 0x7efe, 0xbb => 0x7f01, 0xbc => 0x7f02, + 0xbd => 0x7f03, 0xbe => 0x7f07, 0xbf => 0x7f08, 0xc0 => 0x7f0b, + 0xc1 => 0x7f0c, 0xc2 => 0x7f0f, 0xc3 => 0x7f11, 0xc4 => 0x7f12, + 0xc5 => 0x7f17, 0xc6 => 0x7f19, 0xc7 => 0x7f1c, 0xc8 => 0x7f1b, + 0xc9 => 0x7f1f, 0xca => 0x7f21, 0xcb => 0x7f22, 0xcc => 0x7f23, + 0xcd => 0x7f24, 0xce => 0x7f25, 0xcf => 0x7f26, 0xd0 => 0x7f27, + 0xd1 => 0x7f2a, 0xd2 => 0x7f2b, 0xd3 => 0x7f2c, 0xd4 => 0x7f2d, + 0xd5 => 0x7f2f, 0xd6 => 0x7f30, 0xd7 => 0x7f31, 0xd8 => 0x7f32, + 0xd9 => 0x7f33, 0xda => 0x7f35, 0xdb => 0x5e7a, 0xdc => 0x757f, + 0xdd => 0x5ddb, 0xde => 0x753e, 0xdf => 0x9095, 0xe0 => 0x738e, + 0xe1 => 0x7391, 0xe2 => 0x73ae, 0xe3 => 0x73a2, 0xe4 => 0x739f, + 0xe5 => 0x73cf, 0xe6 => 0x73c2, 0xe7 => 0x73d1, 0xe8 => 0x73b7, + 0xe9 => 0x73b3, 0xea => 0x73c0, 0xeb => 0x73c9, 0xec => 0x73c8, + 0xed => 0x73e5, 0xee => 0x73d9, 0xef => 0x987c, 0xf0 => 0x740a, + 0xf1 => 0x73e9, 0xf2 => 0x73e7, 0xf3 => 0x73de, 0xf4 => 0x73ba, + 0xf5 => 0x73f2, 0xf6 => 0x740f, 0xf7 => 0x742a, 0xf8 => 0x745b, + 0xf9 => 0x7426, 0xfa => 0x7425, 0xfb => 0x7428, 0xfc => 0x7430, + 0xfd => 0x742e, 0xfe => 0x742c, + }, + 0xe8 => { + 0xa1 => 0x741b, 0xa2 => 0x741a, 0xa3 => 0x7441, 0xa4 => 0x745c, + 0xa5 => 0x7457, 0xa6 => 0x7455, 0xa7 => 0x7459, 0xa8 => 0x7477, + 0xa9 => 0x746d, 0xaa => 0x747e, 0xab => 0x749c, 0xac => 0x748e, + 0xad => 0x7480, 0xae => 0x7481, 0xaf => 0x7487, 0xb0 => 0x748b, + 0xb1 => 0x749e, 0xb2 => 0x74a8, 0xb3 => 0x74a9, 0xb4 => 0x7490, + 0xb5 => 0x74a7, 0xb6 => 0x74d2, 0xb7 => 0x74ba, 0xb8 => 0x97ea, + 0xb9 => 0x97eb, 0xba => 0x97ec, 0xbb => 0x674c, 0xbc => 0x6753, + 0xbd => 0x675e, 0xbe => 0x6748, 0xbf => 0x6769, 0xc0 => 0x67a5, + 0xc1 => 0x6787, 0xc2 => 0x676a, 0xc3 => 0x6773, 0xc4 => 0x6798, + 0xc5 => 0x67a7, 0xc6 => 0x6775, 0xc7 => 0x67a8, 0xc8 => 0x679e, + 0xc9 => 0x67ad, 0xca => 0x678b, 0xcb => 0x6777, 0xcc => 0x677c, + 0xcd => 0x67f0, 0xce => 0x6809, 0xcf => 0x67d8, 0xd0 => 0x680a, + 0xd1 => 0x67e9, 0xd2 => 0x67b0, 0xd3 => 0x680c, 0xd4 => 0x67d9, + 0xd5 => 0x67b5, 0xd6 => 0x67da, 0xd7 => 0x67b3, 0xd8 => 0x67dd, + 0xd9 => 0x6800, 0xda => 0x67c3, 0xdb => 0x67b8, 0xdc => 0x67e2, + 0xdd => 0x680e, 0xde => 0x67c1, 0xdf => 0x67fd, 0xe0 => 0x6832, + 0xe1 => 0x6833, 0xe2 => 0x6860, 0xe3 => 0x6861, 0xe4 => 0x684e, + 0xe5 => 0x6862, 0xe6 => 0x6844, 0xe7 => 0x6864, 0xe8 => 0x6883, + 0xe9 => 0x681d, 0xea => 0x6855, 0xeb => 0x6866, 0xec => 0x6841, + 0xed => 0x6867, 0xee => 0x6840, 0xef => 0x683e, 0xf0 => 0x684a, + 0xf1 => 0x6849, 0xf2 => 0x6829, 0xf3 => 0x68b5, 0xf4 => 0x688f, + 0xf5 => 0x6874, 0xf6 => 0x6877, 0xf7 => 0x6893, 0xf8 => 0x686b, + 0xf9 => 0x68c2, 0xfa => 0x696e, 0xfb => 0x68fc, 0xfc => 0x691f, + 0xfd => 0x6920, 0xfe => 0x68f9, + }, + 0xe9 => { + 0xa1 => 0x6924, 0xa2 => 0x68f0, 0xa3 => 0x690b, 0xa4 => 0x6901, + 0xa5 => 0x6957, 0xa6 => 0x68e3, 0xa7 => 0x6910, 0xa8 => 0x6971, + 0xa9 => 0x6939, 0xaa => 0x6960, 0xab => 0x6942, 0xac => 0x695d, + 0xad => 0x6984, 0xae => 0x696b, 0xaf => 0x6980, 0xb0 => 0x6998, + 0xb1 => 0x6978, 0xb2 => 0x6934, 0xb3 => 0x69cc, 0xb4 => 0x6987, + 0xb5 => 0x6988, 0xb6 => 0x69ce, 0xb7 => 0x6989, 0xb8 => 0x6966, + 0xb9 => 0x6963, 0xba => 0x6979, 0xbb => 0x699b, 0xbc => 0x69a7, + 0xbd => 0x69bb, 0xbe => 0x69ab, 0xbf => 0x69ad, 0xc0 => 0x69d4, + 0xc1 => 0x69b1, 0xc2 => 0x69c1, 0xc3 => 0x69ca, 0xc4 => 0x69df, + 0xc5 => 0x6995, 0xc6 => 0x69e0, 0xc7 => 0x698d, 0xc8 => 0x69ff, + 0xc9 => 0x6a2f, 0xca => 0x69ed, 0xcb => 0x6a17, 0xcc => 0x6a18, + 0xcd => 0x6a65, 0xce => 0x69f2, 0xcf => 0x6a44, 0xd0 => 0x6a3e, + 0xd1 => 0x6aa0, 0xd2 => 0x6a50, 0xd3 => 0x6a5b, 0xd4 => 0x6a35, + 0xd5 => 0x6a8e, 0xd6 => 0x6a79, 0xd7 => 0x6a3d, 0xd8 => 0x6a28, + 0xd9 => 0x6a58, 0xda => 0x6a7c, 0xdb => 0x6a91, 0xdc => 0x6a90, + 0xdd => 0x6aa9, 0xde => 0x6a97, 0xdf => 0x6aab, 0xe0 => 0x7337, + 0xe1 => 0x7352, 0xe2 => 0x6b81, 0xe3 => 0x6b82, 0xe4 => 0x6b87, + 0xe5 => 0x6b84, 0xe6 => 0x6b92, 0xe7 => 0x6b93, 0xe8 => 0x6b8d, + 0xe9 => 0x6b9a, 0xea => 0x6b9b, 0xeb => 0x6ba1, 0xec => 0x6baa, + 0xed => 0x8f6b, 0xee => 0x8f6d, 0xef => 0x8f71, 0xf0 => 0x8f72, + 0xf1 => 0x8f73, 0xf2 => 0x8f75, 0xf3 => 0x8f76, 0xf4 => 0x8f78, + 0xf5 => 0x8f77, 0xf6 => 0x8f79, 0xf7 => 0x8f7a, 0xf8 => 0x8f7c, + 0xf9 => 0x8f7e, 0xfa => 0x8f81, 0xfb => 0x8f82, 0xfc => 0x8f84, + 0xfd => 0x8f87, 0xfe => 0x8f8b, + }, + 0xea => { + 0xa1 => 0x8f8d, 0xa2 => 0x8f8e, 0xa3 => 0x8f8f, 0xa4 => 0x8f98, + 0xa5 => 0x8f9a, 0xa6 => 0x8ece, 0xa7 => 0x620b, 0xa8 => 0x6217, + 0xa9 => 0x621b, 0xaa => 0x621f, 0xab => 0x6222, 0xac => 0x6221, + 0xad => 0x6225, 0xae => 0x6224, 0xaf => 0x622c, 0xb0 => 0x81e7, + 0xb1 => 0x74ef, 0xb2 => 0x74f4, 0xb3 => 0x74ff, 0xb4 => 0x750f, + 0xb5 => 0x7511, 0xb6 => 0x7513, 0xb7 => 0x6534, 0xb8 => 0x65ee, + 0xb9 => 0x65ef, 0xba => 0x65f0, 0xbb => 0x660a, 0xbc => 0x6619, + 0xbd => 0x6772, 0xbe => 0x6603, 0xbf => 0x6615, 0xc0 => 0x6600, + 0xc1 => 0x7085, 0xc2 => 0x66f7, 0xc3 => 0x661d, 0xc4 => 0x6634, + 0xc5 => 0x6631, 0xc6 => 0x6636, 0xc7 => 0x6635, 0xc8 => 0x8006, + 0xc9 => 0x665f, 0xca => 0x6654, 0xcb => 0x6641, 0xcc => 0x664f, + 0xcd => 0x6656, 0xce => 0x6661, 0xcf => 0x6657, 0xd0 => 0x6677, + 0xd1 => 0x6684, 0xd2 => 0x668c, 0xd3 => 0x66a7, 0xd4 => 0x669d, + 0xd5 => 0x66be, 0xd6 => 0x66db, 0xd7 => 0x66dc, 0xd8 => 0x66e6, + 0xd9 => 0x66e9, 0xda => 0x8d32, 0xdb => 0x8d33, 0xdc => 0x8d36, + 0xdd => 0x8d3b, 0xde => 0x8d3d, 0xdf => 0x8d40, 0xe0 => 0x8d45, + 0xe1 => 0x8d46, 0xe2 => 0x8d48, 0xe3 => 0x8d49, 0xe4 => 0x8d47, + 0xe5 => 0x8d4d, 0xe6 => 0x8d55, 0xe7 => 0x8d59, 0xe8 => 0x89c7, + 0xe9 => 0x89ca, 0xea => 0x89cb, 0xeb => 0x89cc, 0xec => 0x89ce, + 0xed => 0x89cf, 0xee => 0x89d0, 0xef => 0x89d1, 0xf0 => 0x726e, + 0xf1 => 0x729f, 0xf2 => 0x725d, 0xf3 => 0x7266, 0xf4 => 0x726f, + 0xf5 => 0x727e, 0xf6 => 0x727f, 0xf7 => 0x7284, 0xf8 => 0x728b, + 0xf9 => 0x728d, 0xfa => 0x728f, 0xfb => 0x7292, 0xfc => 0x6308, + 0xfd => 0x6332, 0xfe => 0x63b0, + }, + 0xeb => { + 0xa1 => 0x643f, 0xa2 => 0x64d8, 0xa3 => 0x8004, 0xa4 => 0x6bea, + 0xa5 => 0x6bf3, 0xa6 => 0x6bfd, 0xa7 => 0x6bf5, 0xa8 => 0x6bf9, + 0xa9 => 0x6c05, 0xaa => 0x6c07, 0xab => 0x6c06, 0xac => 0x6c0d, + 0xad => 0x6c15, 0xae => 0x6c18, 0xaf => 0x6c19, 0xb0 => 0x6c1a, + 0xb1 => 0x6c21, 0xb2 => 0x6c29, 0xb3 => 0x6c24, 0xb4 => 0x6c2a, + 0xb5 => 0x6c32, 0xb6 => 0x6535, 0xb7 => 0x6555, 0xb8 => 0x656b, + 0xb9 => 0x724d, 0xba => 0x7252, 0xbb => 0x7256, 0xbc => 0x7230, + 0xbd => 0x8662, 0xbe => 0x5216, 0xbf => 0x809f, 0xc0 => 0x809c, + 0xc1 => 0x8093, 0xc2 => 0x80bc, 0xc3 => 0x670a, 0xc4 => 0x80bd, + 0xc5 => 0x80b1, 0xc6 => 0x80ab, 0xc7 => 0x80ad, 0xc8 => 0x80b4, + 0xc9 => 0x80b7, 0xca => 0x80e7, 0xcb => 0x80e8, 0xcc => 0x80e9, + 0xcd => 0x80ea, 0xce => 0x80db, 0xcf => 0x80c2, 0xd0 => 0x80c4, + 0xd1 => 0x80d9, 0xd2 => 0x80cd, 0xd3 => 0x80d7, 0xd4 => 0x6710, + 0xd5 => 0x80dd, 0xd6 => 0x80eb, 0xd7 => 0x80f1, 0xd8 => 0x80f4, + 0xd9 => 0x80ed, 0xda => 0x810d, 0xdb => 0x810e, 0xdc => 0x80f2, + 0xdd => 0x80fc, 0xde => 0x6715, 0xdf => 0x8112, 0xe0 => 0x8c5a, + 0xe1 => 0x8136, 0xe2 => 0x811e, 0xe3 => 0x812c, 0xe4 => 0x8118, + 0xe5 => 0x8132, 0xe6 => 0x8148, 0xe7 => 0x814c, 0xe8 => 0x8153, + 0xe9 => 0x8174, 0xea => 0x8159, 0xeb => 0x815a, 0xec => 0x8171, + 0xed => 0x8160, 0xee => 0x8169, 0xef => 0x817c, 0xf0 => 0x817d, + 0xf1 => 0x816d, 0xf2 => 0x8167, 0xf3 => 0x584d, 0xf4 => 0x5ab5, + 0xf5 => 0x8188, 0xf6 => 0x8182, 0xf7 => 0x8191, 0xf8 => 0x6ed5, + 0xf9 => 0x81a3, 0xfa => 0x81aa, 0xfb => 0x81cc, 0xfc => 0x6726, + 0xfd => 0x81ca, 0xfe => 0x81bb, + }, + 0xec => { + 0xa1 => 0x81c1, 0xa2 => 0x81a6, 0xa3 => 0x6b24, 0xa4 => 0x6b37, + 0xa5 => 0x6b39, 0xa6 => 0x6b43, 0xa7 => 0x6b46, 0xa8 => 0x6b59, + 0xa9 => 0x98d1, 0xaa => 0x98d2, 0xab => 0x98d3, 0xac => 0x98d5, + 0xad => 0x98d9, 0xae => 0x98da, 0xaf => 0x6bb3, 0xb0 => 0x5f40, + 0xb1 => 0x6bc2, 0xb2 => 0x89f3, 0xb3 => 0x6590, 0xb4 => 0x9f51, + 0xb5 => 0x6593, 0xb6 => 0x65bc, 0xb7 => 0x65c6, 0xb8 => 0x65c4, + 0xb9 => 0x65c3, 0xba => 0x65cc, 0xbb => 0x65ce, 0xbc => 0x65d2, + 0xbd => 0x65d6, 0xbe => 0x7080, 0xbf => 0x709c, 0xc0 => 0x7096, + 0xc1 => 0x709d, 0xc2 => 0x70bb, 0xc3 => 0x70c0, 0xc4 => 0x70b7, + 0xc5 => 0x70ab, 0xc6 => 0x70b1, 0xc7 => 0x70e8, 0xc8 => 0x70ca, + 0xc9 => 0x7110, 0xca => 0x7113, 0xcb => 0x7116, 0xcc => 0x712f, + 0xcd => 0x7131, 0xce => 0x7173, 0xcf => 0x715c, 0xd0 => 0x7168, + 0xd1 => 0x7145, 0xd2 => 0x7172, 0xd3 => 0x714a, 0xd4 => 0x7178, + 0xd5 => 0x717a, 0xd6 => 0x7198, 0xd7 => 0x71b3, 0xd8 => 0x71b5, + 0xd9 => 0x71a8, 0xda => 0x71a0, 0xdb => 0x71e0, 0xdc => 0x71d4, + 0xdd => 0x71e7, 0xde => 0x71f9, 0xdf => 0x721d, 0xe0 => 0x7228, + 0xe1 => 0x706c, 0xe2 => 0x7118, 0xe3 => 0x7166, 0xe4 => 0x71b9, + 0xe5 => 0x623e, 0xe6 => 0x623d, 0xe7 => 0x6243, 0xe8 => 0x6248, + 0xe9 => 0x6249, 0xea => 0x793b, 0xeb => 0x7940, 0xec => 0x7946, + 0xed => 0x7949, 0xee => 0x795b, 0xef => 0x795c, 0xf0 => 0x7953, + 0xf1 => 0x795a, 0xf2 => 0x7962, 0xf3 => 0x7957, 0xf4 => 0x7960, + 0xf5 => 0x796f, 0xf6 => 0x7967, 0xf7 => 0x797a, 0xf8 => 0x7985, + 0xf9 => 0x798a, 0xfa => 0x799a, 0xfb => 0x79a7, 0xfc => 0x79b3, + 0xfd => 0x5fd1, 0xfe => 0x5fd0, + }, + 0xed => { + 0xa1 => 0x603c, 0xa2 => 0x605d, 0xa3 => 0x605a, 0xa4 => 0x6067, + 0xa5 => 0x6041, 0xa6 => 0x6059, 0xa7 => 0x6063, 0xa8 => 0x60ab, + 0xa9 => 0x6106, 0xaa => 0x610d, 0xab => 0x615d, 0xac => 0x61a9, + 0xad => 0x619d, 0xae => 0x61cb, 0xaf => 0x61d1, 0xb0 => 0x6206, + 0xb1 => 0x8080, 0xb2 => 0x807f, 0xb3 => 0x6c93, 0xb4 => 0x6cf6, + 0xb5 => 0x6dfc, 0xb6 => 0x77f6, 0xb7 => 0x77f8, 0xb8 => 0x7800, + 0xb9 => 0x7809, 0xba => 0x7817, 0xbb => 0x7818, 0xbc => 0x7811, + 0xbd => 0x65ab, 0xbe => 0x782d, 0xbf => 0x781c, 0xc0 => 0x781d, + 0xc1 => 0x7839, 0xc2 => 0x783a, 0xc3 => 0x783b, 0xc4 => 0x781f, + 0xc5 => 0x783c, 0xc6 => 0x7825, 0xc7 => 0x782c, 0xc8 => 0x7823, + 0xc9 => 0x7829, 0xca => 0x784e, 0xcb => 0x786d, 0xcc => 0x7856, + 0xcd => 0x7857, 0xce => 0x7826, 0xcf => 0x7850, 0xd0 => 0x7847, + 0xd1 => 0x784c, 0xd2 => 0x786a, 0xd3 => 0x789b, 0xd4 => 0x7893, + 0xd5 => 0x789a, 0xd6 => 0x7887, 0xd7 => 0x789c, 0xd8 => 0x78a1, + 0xd9 => 0x78a3, 0xda => 0x78b2, 0xdb => 0x78b9, 0xdc => 0x78a5, + 0xdd => 0x78d4, 0xde => 0x78d9, 0xdf => 0x78c9, 0xe0 => 0x78ec, + 0xe1 => 0x78f2, 0xe2 => 0x7905, 0xe3 => 0x78f4, 0xe4 => 0x7913, + 0xe5 => 0x7924, 0xe6 => 0x791e, 0xe7 => 0x7934, 0xe8 => 0x9f9b, + 0xe9 => 0x9ef9, 0xea => 0x9efb, 0xeb => 0x9efc, 0xec => 0x76f1, + 0xed => 0x7704, 0xee => 0x770d, 0xef => 0x76f9, 0xf0 => 0x7707, + 0xf1 => 0x7708, 0xf2 => 0x771a, 0xf3 => 0x7722, 0xf4 => 0x7719, + 0xf5 => 0x772d, 0xf6 => 0x7726, 0xf7 => 0x7735, 0xf8 => 0x7738, + 0xf9 => 0x7750, 0xfa => 0x7751, 0xfb => 0x7747, 0xfc => 0x7743, + 0xfd => 0x775a, 0xfe => 0x7768, + }, + 0xee => { + 0xa1 => 0x7762, 0xa2 => 0x7765, 0xa3 => 0x777f, 0xa4 => 0x778d, + 0xa5 => 0x777d, 0xa6 => 0x7780, 0xa7 => 0x778c, 0xa8 => 0x7791, + 0xa9 => 0x779f, 0xaa => 0x77a0, 0xab => 0x77b0, 0xac => 0x77b5, + 0xad => 0x77bd, 0xae => 0x753a, 0xaf => 0x7540, 0xb0 => 0x754e, + 0xb1 => 0x754b, 0xb2 => 0x7548, 0xb3 => 0x755b, 0xb4 => 0x7572, + 0xb5 => 0x7579, 0xb6 => 0x7583, 0xb7 => 0x7f58, 0xb8 => 0x7f61, + 0xb9 => 0x7f5f, 0xba => 0x8a48, 0xbb => 0x7f68, 0xbc => 0x7f74, + 0xbd => 0x7f71, 0xbe => 0x7f79, 0xbf => 0x7f81, 0xc0 => 0x7f7e, + 0xc1 => 0x76cd, 0xc2 => 0x76e5, 0xc3 => 0x8832, 0xc4 => 0x9485, + 0xc5 => 0x9486, 0xc6 => 0x9487, 0xc7 => 0x948b, 0xc8 => 0x948a, + 0xc9 => 0x948c, 0xca => 0x948d, 0xcb => 0x948f, 0xcc => 0x9490, + 0xcd => 0x9494, 0xce => 0x9497, 0xcf => 0x9495, 0xd0 => 0x949a, + 0xd1 => 0x949b, 0xd2 => 0x949c, 0xd3 => 0x94a3, 0xd4 => 0x94a4, + 0xd5 => 0x94ab, 0xd6 => 0x94aa, 0xd7 => 0x94ad, 0xd8 => 0x94ac, + 0xd9 => 0x94af, 0xda => 0x94b0, 0xdb => 0x94b2, 0xdc => 0x94b4, + 0xdd => 0x94b6, 0xde => 0x94b7, 0xdf => 0x94b8, 0xe0 => 0x94b9, + 0xe1 => 0x94ba, 0xe2 => 0x94bc, 0xe3 => 0x94bd, 0xe4 => 0x94bf, + 0xe5 => 0x94c4, 0xe6 => 0x94c8, 0xe7 => 0x94c9, 0xe8 => 0x94ca, + 0xe9 => 0x94cb, 0xea => 0x94cc, 0xeb => 0x94cd, 0xec => 0x94ce, + 0xed => 0x94d0, 0xee => 0x94d1, 0xef => 0x94d2, 0xf0 => 0x94d5, + 0xf1 => 0x94d6, 0xf2 => 0x94d7, 0xf3 => 0x94d9, 0xf4 => 0x94d8, + 0xf5 => 0x94db, 0xf6 => 0x94de, 0xf7 => 0x94df, 0xf8 => 0x94e0, + 0xf9 => 0x94e2, 0xfa => 0x94e4, 0xfb => 0x94e5, 0xfc => 0x94e7, + 0xfd => 0x94e8, 0xfe => 0x94ea, + }, + 0xef => { + 0xa1 => 0x94e9, 0xa2 => 0x94eb, 0xa3 => 0x94ee, 0xa4 => 0x94ef, + 0xa5 => 0x94f3, 0xa6 => 0x94f4, 0xa7 => 0x94f5, 0xa8 => 0x94f7, + 0xa9 => 0x94f9, 0xaa => 0x94fc, 0xab => 0x94fd, 0xac => 0x94ff, + 0xad => 0x9503, 0xae => 0x9502, 0xaf => 0x9506, 0xb0 => 0x9507, + 0xb1 => 0x9509, 0xb2 => 0x950a, 0xb3 => 0x950d, 0xb4 => 0x950e, + 0xb5 => 0x950f, 0xb6 => 0x9512, 0xb7 => 0x9513, 0xb8 => 0x9514, + 0xb9 => 0x9515, 0xba => 0x9516, 0xbb => 0x9518, 0xbc => 0x951b, + 0xbd => 0x951d, 0xbe => 0x951e, 0xbf => 0x951f, 0xc0 => 0x9522, + 0xc1 => 0x952a, 0xc2 => 0x952b, 0xc3 => 0x9529, 0xc4 => 0x952c, + 0xc5 => 0x9531, 0xc6 => 0x9532, 0xc7 => 0x9534, 0xc8 => 0x9536, + 0xc9 => 0x9537, 0xca => 0x9538, 0xcb => 0x953c, 0xcc => 0x953e, + 0xcd => 0x953f, 0xce => 0x9542, 0xcf => 0x9535, 0xd0 => 0x9544, + 0xd1 => 0x9545, 0xd2 => 0x9546, 0xd3 => 0x9549, 0xd4 => 0x954c, + 0xd5 => 0x954e, 0xd6 => 0x954f, 0xd7 => 0x9552, 0xd8 => 0x9553, + 0xd9 => 0x9554, 0xda => 0x9556, 0xdb => 0x9557, 0xdc => 0x9558, + 0xdd => 0x9559, 0xde => 0x955b, 0xdf => 0x955e, 0xe0 => 0x955f, + 0xe1 => 0x955d, 0xe2 => 0x9561, 0xe3 => 0x9562, 0xe4 => 0x9564, + 0xe5 => 0x9565, 0xe6 => 0x9566, 0xe7 => 0x9567, 0xe8 => 0x9568, + 0xe9 => 0x9569, 0xea => 0x956a, 0xeb => 0x956b, 0xec => 0x956c, + 0xed => 0x956f, 0xee => 0x9571, 0xef => 0x9572, 0xf0 => 0x9573, + 0xf1 => 0x953a, 0xf2 => 0x77e7, 0xf3 => 0x77ec, 0xf4 => 0x96c9, + 0xf5 => 0x79d5, 0xf6 => 0x79ed, 0xf7 => 0x79e3, 0xf8 => 0x79eb, + 0xf9 => 0x7a06, 0xfa => 0x5d47, 0xfb => 0x7a03, 0xfc => 0x7a02, + 0xfd => 0x7a1e, 0xfe => 0x7a14, + }, + 0xf0 => { + 0xa1 => 0x7a39, 0xa2 => 0x7a37, 0xa3 => 0x7a51, 0xa4 => 0x9ecf, + 0xa5 => 0x99a5, 0xa6 => 0x7a70, 0xa7 => 0x7688, 0xa8 => 0x768e, + 0xa9 => 0x7693, 0xaa => 0x7699, 0xab => 0x76a4, 0xac => 0x74de, + 0xad => 0x74e0, 0xae => 0x752c, 0xaf => 0x9e20, 0xb0 => 0x9e22, + 0xb1 => 0x9e28, 0xb2 => 0x9e29, 0xb3 => 0x9e2a, 0xb4 => 0x9e2b, + 0xb5 => 0x9e2c, 0xb6 => 0x9e32, 0xb7 => 0x9e31, 0xb8 => 0x9e36, + 0xb9 => 0x9e38, 0xba => 0x9e37, 0xbb => 0x9e39, 0xbc => 0x9e3a, + 0xbd => 0x9e3e, 0xbe => 0x9e41, 0xbf => 0x9e42, 0xc0 => 0x9e44, + 0xc1 => 0x9e46, 0xc2 => 0x9e47, 0xc3 => 0x9e48, 0xc4 => 0x9e49, + 0xc5 => 0x9e4b, 0xc6 => 0x9e4c, 0xc7 => 0x9e4e, 0xc8 => 0x9e51, + 0xc9 => 0x9e55, 0xca => 0x9e57, 0xcb => 0x9e5a, 0xcc => 0x9e5b, + 0xcd => 0x9e5c, 0xce => 0x9e5e, 0xcf => 0x9e63, 0xd0 => 0x9e66, + 0xd1 => 0x9e67, 0xd2 => 0x9e68, 0xd3 => 0x9e69, 0xd4 => 0x9e6a, + 0xd5 => 0x9e6b, 0xd6 => 0x9e6c, 0xd7 => 0x9e71, 0xd8 => 0x9e6d, + 0xd9 => 0x9e73, 0xda => 0x7592, 0xdb => 0x7594, 0xdc => 0x7596, + 0xdd => 0x75a0, 0xde => 0x759d, 0xdf => 0x75ac, 0xe0 => 0x75a3, + 0xe1 => 0x75b3, 0xe2 => 0x75b4, 0xe3 => 0x75b8, 0xe4 => 0x75c4, + 0xe5 => 0x75b1, 0xe6 => 0x75b0, 0xe7 => 0x75c3, 0xe8 => 0x75c2, + 0xe9 => 0x75d6, 0xea => 0x75cd, 0xeb => 0x75e3, 0xec => 0x75e8, + 0xed => 0x75e6, 0xee => 0x75e4, 0xef => 0x75eb, 0xf0 => 0x75e7, + 0xf1 => 0x7603, 0xf2 => 0x75f1, 0xf3 => 0x75fc, 0xf4 => 0x75ff, + 0xf5 => 0x7610, 0xf6 => 0x7600, 0xf7 => 0x7605, 0xf8 => 0x760c, + 0xf9 => 0x7617, 0xfa => 0x760a, 0xfb => 0x7625, 0xfc => 0x7618, + 0xfd => 0x7615, 0xfe => 0x7619, + }, + 0xf1 => { + 0xa1 => 0x761b, 0xa2 => 0x763c, 0xa3 => 0x7622, 0xa4 => 0x7620, + 0xa5 => 0x7640, 0xa6 => 0x762d, 0xa7 => 0x7630, 0xa8 => 0x763f, + 0xa9 => 0x7635, 0xaa => 0x7643, 0xab => 0x763e, 0xac => 0x7633, + 0xad => 0x764d, 0xae => 0x765e, 0xaf => 0x7654, 0xb0 => 0x765c, + 0xb1 => 0x7656, 0xb2 => 0x766b, 0xb3 => 0x766f, 0xb4 => 0x7fca, + 0xb5 => 0x7ae6, 0xb6 => 0x7a78, 0xb7 => 0x7a79, 0xb8 => 0x7a80, + 0xb9 => 0x7a86, 0xba => 0x7a88, 0xbb => 0x7a95, 0xbc => 0x7aa6, + 0xbd => 0x7aa0, 0xbe => 0x7aac, 0xbf => 0x7aa8, 0xc0 => 0x7aad, + 0xc1 => 0x7ab3, 0xc2 => 0x8864, 0xc3 => 0x8869, 0xc4 => 0x8872, + 0xc5 => 0x887d, 0xc6 => 0x887f, 0xc7 => 0x8882, 0xc8 => 0x88a2, + 0xc9 => 0x88c6, 0xca => 0x88b7, 0xcb => 0x88bc, 0xcc => 0x88c9, + 0xcd => 0x88e2, 0xce => 0x88ce, 0xcf => 0x88e3, 0xd0 => 0x88e5, + 0xd1 => 0x88f1, 0xd2 => 0x891a, 0xd3 => 0x88fc, 0xd4 => 0x88e8, + 0xd5 => 0x88fe, 0xd6 => 0x88f0, 0xd7 => 0x8921, 0xd8 => 0x8919, + 0xd9 => 0x8913, 0xda => 0x891b, 0xdb => 0x890a, 0xdc => 0x8934, + 0xdd => 0x892b, 0xde => 0x8936, 0xdf => 0x8941, 0xe0 => 0x8966, + 0xe1 => 0x897b, 0xe2 => 0x758b, 0xe3 => 0x80e5, 0xe4 => 0x76b2, + 0xe5 => 0x76b4, 0xe6 => 0x77dc, 0xe7 => 0x8012, 0xe8 => 0x8014, + 0xe9 => 0x8016, 0xea => 0x801c, 0xeb => 0x8020, 0xec => 0x8022, + 0xed => 0x8025, 0xee => 0x8026, 0xef => 0x8027, 0xf0 => 0x8029, + 0xf1 => 0x8028, 0xf2 => 0x8031, 0xf3 => 0x800b, 0xf4 => 0x8035, + 0xf5 => 0x8043, 0xf6 => 0x8046, 0xf7 => 0x804d, 0xf8 => 0x8052, + 0xf9 => 0x8069, 0xfa => 0x8071, 0xfb => 0x8983, 0xfc => 0x9878, + 0xfd => 0x9880, 0xfe => 0x9883, + }, + 0xf2 => { + 0xa1 => 0x9889, 0xa2 => 0x988c, 0xa3 => 0x988d, 0xa4 => 0x988f, + 0xa5 => 0x9894, 0xa6 => 0x989a, 0xa7 => 0x989b, 0xa8 => 0x989e, + 0xa9 => 0x989f, 0xaa => 0x98a1, 0xab => 0x98a2, 0xac => 0x98a5, + 0xad => 0x98a6, 0xae => 0x864d, 0xaf => 0x8654, 0xb0 => 0x866c, + 0xb1 => 0x866e, 0xb2 => 0x867f, 0xb3 => 0x867a, 0xb4 => 0x867c, + 0xb5 => 0x867b, 0xb6 => 0x86a8, 0xb7 => 0x868d, 0xb8 => 0x868b, + 0xb9 => 0x86ac, 0xba => 0x869d, 0xbb => 0x86a7, 0xbc => 0x86a3, + 0xbd => 0x86aa, 0xbe => 0x8693, 0xbf => 0x86a9, 0xc0 => 0x86b6, + 0xc1 => 0x86c4, 0xc2 => 0x86b5, 0xc3 => 0x86ce, 0xc4 => 0x86b0, + 0xc5 => 0x86ba, 0xc6 => 0x86b1, 0xc7 => 0x86af, 0xc8 => 0x86c9, + 0xc9 => 0x86cf, 0xca => 0x86b4, 0xcb => 0x86e9, 0xcc => 0x86f1, + 0xcd => 0x86f2, 0xce => 0x86ed, 0xcf => 0x86f3, 0xd0 => 0x86d0, + 0xd1 => 0x8713, 0xd2 => 0x86de, 0xd3 => 0x86f4, 0xd4 => 0x86df, + 0xd5 => 0x86d8, 0xd6 => 0x86d1, 0xd7 => 0x8703, 0xd8 => 0x8707, + 0xd9 => 0x86f8, 0xda => 0x8708, 0xdb => 0x870a, 0xdc => 0x870d, + 0xdd => 0x8709, 0xde => 0x8723, 0xdf => 0x873b, 0xe0 => 0x871e, + 0xe1 => 0x8725, 0xe2 => 0x872e, 0xe3 => 0x871a, 0xe4 => 0x873e, + 0xe5 => 0x8748, 0xe6 => 0x8734, 0xe7 => 0x8731, 0xe8 => 0x8729, + 0xe9 => 0x8737, 0xea => 0x873f, 0xeb => 0x8782, 0xec => 0x8722, + 0xed => 0x877d, 0xee => 0x877e, 0xef => 0x877b, 0xf0 => 0x8760, + 0xf1 => 0x8770, 0xf2 => 0x874c, 0xf3 => 0x876e, 0xf4 => 0x878b, + 0xf5 => 0x8753, 0xf6 => 0x8763, 0xf7 => 0x877c, 0xf8 => 0x8764, + 0xf9 => 0x8759, 0xfa => 0x8765, 0xfb => 0x8793, 0xfc => 0x87af, + 0xfd => 0x87a8, 0xfe => 0x87d2, + }, + 0xf3 => { + 0xa1 => 0x87c6, 0xa2 => 0x8788, 0xa3 => 0x8785, 0xa4 => 0x87ad, + 0xa5 => 0x8797, 0xa6 => 0x8783, 0xa7 => 0x87ab, 0xa8 => 0x87e5, + 0xa9 => 0x87ac, 0xaa => 0x87b5, 0xab => 0x87b3, 0xac => 0x87cb, + 0xad => 0x87d3, 0xae => 0x87bd, 0xaf => 0x87d1, 0xb0 => 0x87c0, + 0xb1 => 0x87ca, 0xb2 => 0x87db, 0xb3 => 0x87ea, 0xb4 => 0x87e0, + 0xb5 => 0x87ee, 0xb6 => 0x8816, 0xb7 => 0x8813, 0xb8 => 0x87fe, + 0xb9 => 0x880a, 0xba => 0x881b, 0xbb => 0x8821, 0xbc => 0x8839, + 0xbd => 0x883c, 0xbe => 0x7f36, 0xbf => 0x7f42, 0xc0 => 0x7f44, + 0xc1 => 0x7f45, 0xc2 => 0x8210, 0xc3 => 0x7afa, 0xc4 => 0x7afd, + 0xc5 => 0x7b08, 0xc6 => 0x7b03, 0xc7 => 0x7b04, 0xc8 => 0x7b15, + 0xc9 => 0x7b0a, 0xca => 0x7b2b, 0xcb => 0x7b0f, 0xcc => 0x7b47, + 0xcd => 0x7b38, 0xce => 0x7b2a, 0xcf => 0x7b19, 0xd0 => 0x7b2e, + 0xd1 => 0x7b31, 0xd2 => 0x7b20, 0xd3 => 0x7b25, 0xd4 => 0x7b24, + 0xd5 => 0x7b33, 0xd6 => 0x7b3e, 0xd7 => 0x7b1e, 0xd8 => 0x7b58, + 0xd9 => 0x7b5a, 0xda => 0x7b45, 0xdb => 0x7b75, 0xdc => 0x7b4c, + 0xdd => 0x7b5d, 0xde => 0x7b60, 0xdf => 0x7b6e, 0xe0 => 0x7b7b, + 0xe1 => 0x7b62, 0xe2 => 0x7b72, 0xe3 => 0x7b71, 0xe4 => 0x7b90, + 0xe5 => 0x7ba6, 0xe6 => 0x7ba7, 0xe7 => 0x7bb8, 0xe8 => 0x7bac, + 0xe9 => 0x7b9d, 0xea => 0x7ba8, 0xeb => 0x7b85, 0xec => 0x7baa, + 0xed => 0x7b9c, 0xee => 0x7ba2, 0xef => 0x7bab, 0xf0 => 0x7bb4, + 0xf1 => 0x7bd1, 0xf2 => 0x7bc1, 0xf3 => 0x7bcc, 0xf4 => 0x7bdd, + 0xf5 => 0x7bda, 0xf6 => 0x7be5, 0xf7 => 0x7be6, 0xf8 => 0x7bea, + 0xf9 => 0x7c0c, 0xfa => 0x7bfe, 0xfb => 0x7bfc, 0xfc => 0x7c0f, + 0xfd => 0x7c16, 0xfe => 0x7c0b, + }, + 0xf4 => { + 0xa1 => 0x7c1f, 0xa2 => 0x7c2a, 0xa3 => 0x7c26, 0xa4 => 0x7c38, + 0xa5 => 0x7c41, 0xa6 => 0x7c40, 0xa7 => 0x81fe, 0xa8 => 0x8201, + 0xa9 => 0x8202, 0xaa => 0x8204, 0xab => 0x81ec, 0xac => 0x8844, + 0xad => 0x8221, 0xae => 0x8222, 0xaf => 0x8223, 0xb0 => 0x822d, + 0xb1 => 0x822f, 0xb2 => 0x8228, 0xb3 => 0x822b, 0xb4 => 0x8238, + 0xb5 => 0x823b, 0xb6 => 0x8233, 0xb7 => 0x8234, 0xb8 => 0x823e, + 0xb9 => 0x8244, 0xba => 0x8249, 0xbb => 0x824b, 0xbc => 0x824f, + 0xbd => 0x825a, 0xbe => 0x825f, 0xbf => 0x8268, 0xc0 => 0x887e, + 0xc1 => 0x8885, 0xc2 => 0x8888, 0xc3 => 0x88d8, 0xc4 => 0x88df, + 0xc5 => 0x895e, 0xc6 => 0x7f9d, 0xc7 => 0x7f9f, 0xc8 => 0x7fa7, + 0xc9 => 0x7faf, 0xca => 0x7fb0, 0xcb => 0x7fb2, 0xcc => 0x7c7c, + 0xcd => 0x6549, 0xce => 0x7c91, 0xcf => 0x7c9d, 0xd0 => 0x7c9c, + 0xd1 => 0x7c9e, 0xd2 => 0x7ca2, 0xd3 => 0x7cb2, 0xd4 => 0x7cbc, + 0xd5 => 0x7cbd, 0xd6 => 0x7cc1, 0xd7 => 0x7cc7, 0xd8 => 0x7ccc, + 0xd9 => 0x7ccd, 0xda => 0x7cc8, 0xdb => 0x7cc5, 0xdc => 0x7cd7, + 0xdd => 0x7ce8, 0xde => 0x826e, 0xdf => 0x66a8, 0xe0 => 0x7fbf, + 0xe1 => 0x7fce, 0xe2 => 0x7fd5, 0xe3 => 0x7fe5, 0xe4 => 0x7fe1, + 0xe5 => 0x7fe6, 0xe6 => 0x7fe9, 0xe7 => 0x7fee, 0xe8 => 0x7ff3, + 0xe9 => 0x7cf8, 0xea => 0x7d77, 0xeb => 0x7da6, 0xec => 0x7dae, + 0xed => 0x7e47, 0xee => 0x7e9b, 0xef => 0x9eb8, 0xf0 => 0x9eb4, + 0xf1 => 0x8d73, 0xf2 => 0x8d84, 0xf3 => 0x8d94, 0xf4 => 0x8d91, + 0xf5 => 0x8db1, 0xf6 => 0x8d67, 0xf7 => 0x8d6d, 0xf8 => 0x8c47, + 0xf9 => 0x8c49, 0xfa => 0x914a, 0xfb => 0x9150, 0xfc => 0x914e, + 0xfd => 0x914f, 0xfe => 0x9164, + }, + 0xf5 => { + 0xa1 => 0x9162, 0xa2 => 0x9161, 0xa3 => 0x9170, 0xa4 => 0x9169, + 0xa5 => 0x916f, 0xa6 => 0x917d, 0xa7 => 0x917e, 0xa8 => 0x9172, + 0xa9 => 0x9174, 0xaa => 0x9179, 0xab => 0x918c, 0xac => 0x9185, + 0xad => 0x9190, 0xae => 0x918d, 0xaf => 0x9191, 0xb0 => 0x91a2, + 0xb1 => 0x91a3, 0xb2 => 0x91aa, 0xb3 => 0x91ad, 0xb4 => 0x91ae, + 0xb5 => 0x91af, 0xb6 => 0x91b5, 0xb7 => 0x91b4, 0xb8 => 0x91ba, + 0xb9 => 0x8c55, 0xba => 0x9e7e, 0xbb => 0x8db8, 0xbc => 0x8deb, + 0xbd => 0x8e05, 0xbe => 0x8e59, 0xbf => 0x8e69, 0xc0 => 0x8db5, + 0xc1 => 0x8dbf, 0xc2 => 0x8dbc, 0xc3 => 0x8dba, 0xc4 => 0x8dc4, + 0xc5 => 0x8dd6, 0xc6 => 0x8dd7, 0xc7 => 0x8dda, 0xc8 => 0x8dde, + 0xc9 => 0x8dce, 0xca => 0x8dcf, 0xcb => 0x8ddb, 0xcc => 0x8dc6, + 0xcd => 0x8dec, 0xce => 0x8df7, 0xcf => 0x8df8, 0xd0 => 0x8de3, + 0xd1 => 0x8df9, 0xd2 => 0x8dfb, 0xd3 => 0x8de4, 0xd4 => 0x8e09, + 0xd5 => 0x8dfd, 0xd6 => 0x8e14, 0xd7 => 0x8e1d, 0xd8 => 0x8e1f, + 0xd9 => 0x8e2c, 0xda => 0x8e2e, 0xdb => 0x8e23, 0xdc => 0x8e2f, + 0xdd => 0x8e3a, 0xde => 0x8e40, 0xdf => 0x8e39, 0xe0 => 0x8e35, + 0xe1 => 0x8e3d, 0xe2 => 0x8e31, 0xe3 => 0x8e49, 0xe4 => 0x8e41, + 0xe5 => 0x8e42, 0xe6 => 0x8e51, 0xe7 => 0x8e52, 0xe8 => 0x8e4a, + 0xe9 => 0x8e70, 0xea => 0x8e76, 0xeb => 0x8e7c, 0xec => 0x8e6f, + 0xed => 0x8e74, 0xee => 0x8e85, 0xef => 0x8e8f, 0xf0 => 0x8e94, + 0xf1 => 0x8e90, 0xf2 => 0x8e9c, 0xf3 => 0x8e9e, 0xf4 => 0x8c78, + 0xf5 => 0x8c82, 0xf6 => 0x8c8a, 0xf7 => 0x8c85, 0xf8 => 0x8c98, + 0xf9 => 0x8c94, 0xfa => 0x659b, 0xfb => 0x89d6, 0xfc => 0x89de, + 0xfd => 0x89da, 0xfe => 0x89dc, + }, + 0xf6 => { + 0xa1 => 0x89e5, 0xa2 => 0x89eb, 0xa3 => 0x89ef, 0xa4 => 0x8a3e, + 0xa5 => 0x8b26, 0xa6 => 0x9753, 0xa7 => 0x96e9, 0xa8 => 0x96f3, + 0xa9 => 0x96ef, 0xaa => 0x9706, 0xab => 0x9701, 0xac => 0x9708, + 0xad => 0x970f, 0xae => 0x970e, 0xaf => 0x972a, 0xb0 => 0x972d, + 0xb1 => 0x9730, 0xb2 => 0x973e, 0xb3 => 0x9f80, 0xb4 => 0x9f83, + 0xb5 => 0x9f85, 0xb6 => 0x9f86, 0xb7 => 0x9f87, 0xb8 => 0x9f88, + 0xb9 => 0x9f89, 0xba => 0x9f8a, 0xbb => 0x9f8c, 0xbc => 0x9efe, + 0xbd => 0x9f0b, 0xbe => 0x9f0d, 0xbf => 0x96b9, 0xc0 => 0x96bc, + 0xc1 => 0x96bd, 0xc2 => 0x96ce, 0xc3 => 0x96d2, 0xc4 => 0x77bf, + 0xc5 => 0x96e0, 0xc6 => 0x928e, 0xc7 => 0x92ae, 0xc8 => 0x92c8, + 0xc9 => 0x933e, 0xca => 0x936a, 0xcb => 0x93ca, 0xcc => 0x938f, + 0xcd => 0x943e, 0xce => 0x946b, 0xcf => 0x9c7f, 0xd0 => 0x9c82, + 0xd1 => 0x9c85, 0xd2 => 0x9c86, 0xd3 => 0x9c87, 0xd4 => 0x9c88, + 0xd5 => 0x7a23, 0xd6 => 0x9c8b, 0xd7 => 0x9c8e, 0xd8 => 0x9c90, + 0xd9 => 0x9c91, 0xda => 0x9c92, 0xdb => 0x9c94, 0xdc => 0x9c95, + 0xdd => 0x9c9a, 0xde => 0x9c9b, 0xdf => 0x9c9e, 0xe0 => 0x9c9f, + 0xe1 => 0x9ca0, 0xe2 => 0x9ca1, 0xe3 => 0x9ca2, 0xe4 => 0x9ca3, + 0xe5 => 0x9ca5, 0xe6 => 0x9ca6, 0xe7 => 0x9ca7, 0xe8 => 0x9ca8, + 0xe9 => 0x9ca9, 0xea => 0x9cab, 0xeb => 0x9cad, 0xec => 0x9cae, + 0xed => 0x9cb0, 0xee => 0x9cb1, 0xef => 0x9cb2, 0xf0 => 0x9cb3, + 0xf1 => 0x9cb4, 0xf2 => 0x9cb5, 0xf3 => 0x9cb6, 0xf4 => 0x9cb7, + 0xf5 => 0x9cba, 0xf6 => 0x9cbb, 0xf7 => 0x9cbc, 0xf8 => 0x9cbd, + 0xf9 => 0x9cc4, 0xfa => 0x9cc5, 0xfb => 0x9cc6, 0xfc => 0x9cc7, + 0xfd => 0x9cca, 0xfe => 0x9ccb, + }, + 0xf7 => { + 0xa1 => 0x9ccc, 0xa2 => 0x9ccd, 0xa3 => 0x9cce, 0xa4 => 0x9ccf, + 0xa5 => 0x9cd0, 0xa6 => 0x9cd3, 0xa7 => 0x9cd4, 0xa8 => 0x9cd5, + 0xa9 => 0x9cd7, 0xaa => 0x9cd8, 0xab => 0x9cd9, 0xac => 0x9cdc, + 0xad => 0x9cdd, 0xae => 0x9cdf, 0xaf => 0x9ce2, 0xb0 => 0x977c, + 0xb1 => 0x9785, 0xb2 => 0x9791, 0xb3 => 0x9792, 0xb4 => 0x9794, + 0xb5 => 0x97af, 0xb6 => 0x97ab, 0xb7 => 0x97a3, 0xb8 => 0x97b2, + 0xb9 => 0x97b4, 0xba => 0x9ab1, 0xbb => 0x9ab0, 0xbc => 0x9ab7, + 0xbd => 0x9e58, 0xbe => 0x9ab6, 0xbf => 0x9aba, 0xc0 => 0x9abc, + 0xc1 => 0x9ac1, 0xc2 => 0x9ac0, 0xc3 => 0x9ac5, 0xc4 => 0x9ac2, + 0xc5 => 0x9acb, 0xc6 => 0x9acc, 0xc7 => 0x9ad1, 0xc8 => 0x9b45, + 0xc9 => 0x9b43, 0xca => 0x9b47, 0xcb => 0x9b49, 0xcc => 0x9b48, + 0xcd => 0x9b4d, 0xce => 0x9b51, 0xcf => 0x98e8, 0xd0 => 0x990d, + 0xd1 => 0x992e, 0xd2 => 0x9955, 0xd3 => 0x9954, 0xd4 => 0x9adf, + 0xd5 => 0x9ae1, 0xd6 => 0x9ae6, 0xd7 => 0x9aef, 0xd8 => 0x9aeb, + 0xd9 => 0x9afb, 0xda => 0x9aed, 0xdb => 0x9af9, 0xdc => 0x9b08, + 0xdd => 0x9b0f, 0xde => 0x9b13, 0xdf => 0x9b1f, 0xe0 => 0x9b23, + 0xe1 => 0x9ebd, 0xe2 => 0x9ebe, 0xe3 => 0x7e3b, 0xe4 => 0x9e82, + 0xe5 => 0x9e87, 0xe6 => 0x9e88, 0xe7 => 0x9e8b, 0xe8 => 0x9e92, + 0xe9 => 0x93d6, 0xea => 0x9e9d, 0xeb => 0x9e9f, 0xec => 0x9edb, + 0xed => 0x9edc, 0xee => 0x9edd, 0xef => 0x9ee0, 0xf0 => 0x9edf, + 0xf1 => 0x9ee2, 0xf2 => 0x9ee9, 0xf3 => 0x9ee7, 0xf4 => 0x9ee5, + 0xf5 => 0x9eea, 0xf6 => 0x9eef, 0xf7 => 0x9f22, 0xf8 => 0x9f2c, + 0xf9 => 0x9f2f, 0xfa => 0x9f39, 0xfb => 0x9f37, 0xfc => 0x9f3d, + 0xfd => 0x9f3e, 0xfe => 0x9f44, + }, + 0xf8 => 0xf8f8, 0xf9 => 0xf8f9, 0xfa => 0xf8fa, 0xfb => 0xf8fb, + 0xfc => 0xf8fc, 0xfd => 0xf8fd, 0xfe => 0xf8fe, 0xff => 0xf8ff, +); + +1; # end diff --git a/lib/Image/ExifTool/Charset/MacRoman.pm b/lib/Image/ExifTool/Charset/MacRoman.pm new file mode 100644 index 0000000..a672b26 --- /dev/null +++ b/lib/Image/ExifTool/Charset/MacRoman.pm @@ -0,0 +1,42 @@ +#------------------------------------------------------------------------------ +# File: MacRoman.pm +# +# Description: Mac Roman to Unicode +# +# Revisions: 2010/01/20 - P. Harvey created +# +# References: 1) http://unicode.org/Public/MAPPINGS/VENDORS/APPLE/ROMAN.TXT +# +# Notes: The table omits 1-byte characters with the same values as Unicode +#------------------------------------------------------------------------------ +use strict; + +%Image::ExifTool::Charset::MacRoman = ( + 0x80 => 0xc4, 0x81 => 0xc5, 0x82 => 0xc7, 0x83 => 0xc9, 0x84 => 0xd1, + 0x85 => 0xd6, 0x86 => 0xdc, 0x87 => 0xe1, 0x88 => 0xe0, 0x89 => 0xe2, + 0x8a => 0xe4, 0x8b => 0xe3, 0x8c => 0xe5, 0x8d => 0xe7, 0x8e => 0xe9, + 0x8f => 0xe8, 0x90 => 0xea, 0x91 => 0xeb, 0x92 => 0xed, 0x93 => 0xec, + 0x94 => 0xee, 0x95 => 0xef, 0x96 => 0xf1, 0x97 => 0xf3, 0x98 => 0xf2, + 0x99 => 0xf4, 0x9a => 0xf6, 0x9b => 0xf5, 0x9c => 0xfa, 0x9d => 0xf9, + 0x9e => 0xfb, 0x9f => 0xfc, 0xa0 => 0x2020, 0xa1 => 0xb0, 0xa4 => 0xa7, + 0xa5 => 0x2022, 0xa6 => 0xb6, 0xa7 => 0xdf, 0xa8 => 0xae, 0xaa => 0x2122, + 0xab => 0xb4, 0xac => 0xa8, 0xad => 0x2260, 0xae => 0xc6, 0xaf => 0xd8, + 0xb0 => 0x221e, 0xb2 => 0x2264, 0xb3 => 0x2265, 0xb4 => 0xa5, 0xb6 => 0x2202, + 0xb7 => 0x2211, 0xb8 => 0x220f, 0xb9 => 0x03c0, 0xba => 0x222b, 0xbb => 0xaa, + 0xbc => 0xba, 0xbd => 0x03a9, 0xbe => 0xe6, 0xbf => 0xf8, 0xc0 => 0xbf, + 0xc1 => 0xa1, 0xc2 => 0xac, 0xc3 => 0x221a, 0xc4 => 0x0192, 0xc5 => 0x2248, + 0xc6 => 0x2206, 0xc7 => 0xab, 0xc8 => 0xbb, 0xc9 => 0x2026, 0xca => 0xa0, + 0xcb => 0xc0, 0xcc => 0xc3, 0xcd => 0xd5, 0xce => 0x0152, 0xcf => 0x0153, + 0xd0 => 0x2013, 0xd1 => 0x2014, 0xd2 => 0x201c, 0xd3 => 0x201d, + 0xd4 => 0x2018, 0xd5 => 0x2019, 0xd6 => 0xf7, 0xd7 => 0x25ca, 0xd8 => 0xff, + 0xd9 => 0x0178, 0xda => 0x2044, 0xdb => 0x20ac, 0xdc => 0x2039, + 0xdd => 0x203a, 0xde => 0xfb01, 0xdf => 0xfb02, 0xe0 => 0x2021, 0xe1 => 0xb7, + 0xe2 => 0x201a, 0xe3 => 0x201e, 0xe4 => 0x2030, 0xe5 => 0xc2, 0xe6 => 0xca, + 0xe7 => 0xc1, 0xe8 => 0xcb, 0xe9 => 0xc8, 0xea => 0xcd, 0xeb => 0xce, + 0xec => 0xcf, 0xed => 0xcc, 0xee => 0xd3, 0xef => 0xd4, 0xf0 => 0xf8ff, + 0xf1 => 0xd2, 0xf2 => 0xda, 0xf3 => 0xdb, 0xf4 => 0xd9, 0xf5 => 0x0131, + 0xf6 => 0x02c6, 0xf7 => 0x02dc, 0xf8 => 0xaf, 0xf9 => 0x02d8, 0xfa => 0x02d9, + 0xfb => 0x02da, 0xfc => 0xb8, 0xfd => 0x02dd, 0xfe => 0x02db, 0xff => 0x02c7, +); + +1; # end diff --git a/lib/Image/ExifTool/Charset/MacRomanian.pm b/lib/Image/ExifTool/Charset/MacRomanian.pm new file mode 100644 index 0000000..69c9396 --- /dev/null +++ b/lib/Image/ExifTool/Charset/MacRomanian.pm @@ -0,0 +1,42 @@ +#------------------------------------------------------------------------------ +# File: MacRomanian.pm +# +# Description: Mac Romanian to Unicode +# +# Revisions: 2010/01/20 - P. Harvey created +# +# References: 1) http://unicode.org/Public/MAPPINGS/VENDORS/APPLE/ROMANIAN.TXT +# +# Notes: The table omits 1-byte characters with the same values as Unicode +#------------------------------------------------------------------------------ +use strict; + +%Image::ExifTool::Charset::MacRomanian = ( + 0x80 => 0xc4, 0x81 => 0xc5, 0x82 => 0xc7, 0x83 => 0xc9, 0x84 => 0xd1, + 0x85 => 0xd6, 0x86 => 0xdc, 0x87 => 0xe1, 0x88 => 0xe0, 0x89 => 0xe2, + 0x8a => 0xe4, 0x8b => 0xe3, 0x8c => 0xe5, 0x8d => 0xe7, 0x8e => 0xe9, + 0x8f => 0xe8, 0x90 => 0xea, 0x91 => 0xeb, 0x92 => 0xed, 0x93 => 0xec, + 0x94 => 0xee, 0x95 => 0xef, 0x96 => 0xf1, 0x97 => 0xf3, 0x98 => 0xf2, + 0x99 => 0xf4, 0x9a => 0xf6, 0x9b => 0xf5, 0x9c => 0xfa, 0x9d => 0xf9, + 0x9e => 0xfb, 0x9f => 0xfc, 0xa0 => 0x2020, 0xa1 => 0xb0, 0xa4 => 0xa7, + 0xa5 => 0x2022, 0xa6 => 0xb6, 0xa7 => 0xdf, 0xa8 => 0xae, 0xaa => 0x2122, + 0xab => 0xb4, 0xac => 0xa8, 0xad => 0x2260, 0xae => 0x0102, 0xaf => 0x0218, + 0xb0 => 0x221e, 0xb2 => 0x2264, 0xb3 => 0x2265, 0xb4 => 0xa5, 0xb6 => 0x2202, + 0xb7 => 0x2211, 0xb8 => 0x220f, 0xb9 => 0x03c0, 0xba => 0x222b, 0xbb => 0xaa, + 0xbc => 0xba, 0xbd => 0x03a9, 0xbe => 0x0103, 0xbf => 0x0219, 0xc0 => 0xbf, + 0xc1 => 0xa1, 0xc2 => 0xac, 0xc3 => 0x221a, 0xc4 => 0x0192, 0xc5 => 0x2248, + 0xc6 => 0x2206, 0xc7 => 0xab, 0xc8 => 0xbb, 0xc9 => 0x2026, 0xca => 0xa0, + 0xcb => 0xc0, 0xcc => 0xc3, 0xcd => 0xd5, 0xce => 0x0152, 0xcf => 0x0153, + 0xd0 => 0x2013, 0xd1 => 0x2014, 0xd2 => 0x201c, 0xd3 => 0x201d, + 0xd4 => 0x2018, 0xd5 => 0x2019, 0xd6 => 0xf7, 0xd7 => 0x25ca, 0xd8 => 0xff, + 0xd9 => 0x0178, 0xda => 0x2044, 0xdb => 0x20ac, 0xdc => 0x2039, + 0xdd => 0x203a, 0xde => 0x021a, 0xdf => 0x021b, 0xe0 => 0x2021, 0xe1 => 0xb7, + 0xe2 => 0x201a, 0xe3 => 0x201e, 0xe4 => 0x2030, 0xe5 => 0xc2, 0xe6 => 0xca, + 0xe7 => 0xc1, 0xe8 => 0xcb, 0xe9 => 0xc8, 0xea => 0xcd, 0xeb => 0xce, + 0xec => 0xcf, 0xed => 0xcc, 0xee => 0xd3, 0xef => 0xd4, 0xf0 => 0xf8ff, + 0xf1 => 0xd2, 0xf2 => 0xda, 0xf3 => 0xdb, 0xf4 => 0xd9, 0xf5 => 0x0131, + 0xf6 => 0x02c6, 0xf7 => 0x02dc, 0xf8 => 0xaf, 0xf9 => 0x02d8, 0xfa => 0x02d9, + 0xfb => 0x02da, 0xfc => 0xb8, 0xfd => 0x02dd, 0xfe => 0x02db, 0xff => 0x02c7, +); + +1; # end diff --git a/lib/Image/ExifTool/Charset/MacThai.pm b/lib/Image/ExifTool/Charset/MacThai.pm new file mode 100644 index 0000000..7292255 --- /dev/null +++ b/lib/Image/ExifTool/Charset/MacThai.pm @@ -0,0 +1,49 @@ +#------------------------------------------------------------------------------ +# File: MacThai.pm +# +# Description: Mac Thai to Unicode +# +# Revisions: 2010/01/20 - P. Harvey created +# +# References: 1) http://unicode.org/Public/MAPPINGS/VENDORS/APPLE/THAI.TXT +# +# Notes: The table omits 1-byte characters with the same values as Unicode +#------------------------------------------------------------------------------ +use strict; + +%Image::ExifTool::Charset::MacThai = ( + 0x80 => 0xab, 0x81 => 0xbb, 0x82 => 0x2026, 0x83 => [0x0e48,0xf875], + 0x84 => [0x0e49,0xf875], 0x85 => [0x0e4a,0xf875], 0x86 => [0x0e4b,0xf875], + 0x87 => [0x0e4c,0xf875], 0x88 => [0x0e48,0xf873], 0x89 => [0x0e49,0xf873], + 0x8a => [0x0e4a,0xf873], 0x8b => [0x0e4b,0xf873], 0x8c => [0x0e4c,0xf873], + 0x8d => 0x201c, 0x8e => 0x201d, 0x8f => [0x0e4d,0xf874], 0x91 => 0x2022, + 0x92 => [0x0e31,0xf874], 0x93 => [0x0e47,0xf874], 0x94 => [0x0e34,0xf874], + 0x95 => [0x0e35,0xf874], 0x96 => [0x0e36,0xf874], 0x97 => [0x0e37,0xf874], + 0x98 => [0x0e48,0xf874], 0x99 => [0x0e49,0xf874], 0x9a => [0x0e4a,0xf874], + 0x9b => [0x0e4b,0xf874], 0x9c => [0x0e4c,0xf874], 0x9d => 0x2018, + 0x9e => 0x2019, 0xa1 => 0x0e01, 0xa2 => 0x0e02, 0xa3 => 0x0e03, + 0xa4 => 0x0e04, 0xa5 => 0x0e05, 0xa6 => 0x0e06, 0xa7 => 0x0e07, + 0xa8 => 0x0e08, 0xa9 => 0x0e09, 0xaa => 0x0e0a, 0xab => 0x0e0b, + 0xac => 0x0e0c, 0xad => 0x0e0d, 0xae => 0x0e0e, 0xaf => 0x0e0f, + 0xb0 => 0x0e10, 0xb1 => 0x0e11, 0xb2 => 0x0e12, 0xb3 => 0x0e13, + 0xb4 => 0x0e14, 0xb5 => 0x0e15, 0xb6 => 0x0e16, 0xb7 => 0x0e17, + 0xb8 => 0x0e18, 0xb9 => 0x0e19, 0xba => 0x0e1a, 0xbb => 0x0e1b, + 0xbc => 0x0e1c, 0xbd => 0x0e1d, 0xbe => 0x0e1e, 0xbf => 0x0e1f, + 0xc0 => 0x0e20, 0xc1 => 0x0e21, 0xc2 => 0x0e22, 0xc3 => 0x0e23, + 0xc4 => 0x0e24, 0xc5 => 0x0e25, 0xc6 => 0x0e26, 0xc7 => 0x0e27, + 0xc8 => 0x0e28, 0xc9 => 0x0e29, 0xca => 0x0e2a, 0xcb => 0x0e2b, + 0xcc => 0x0e2c, 0xcd => 0x0e2d, 0xce => 0x0e2e, 0xcf => 0x0e2f, + 0xd0 => 0x0e30, 0xd1 => 0x0e31, 0xd2 => 0x0e32, 0xd3 => 0x0e33, + 0xd4 => 0x0e34, 0xd5 => 0x0e35, 0xd6 => 0x0e36, 0xd7 => 0x0e37, + 0xd8 => 0x0e38, 0xd9 => 0x0e39, 0xda => 0x0e3a, 0xdb => 0x2060, + 0xdc => 0x200b, 0xdd => 0x2013, 0xde => 0x2014, 0xdf => 0x0e3f, + 0xe0 => 0x0e40, 0xe1 => 0x0e41, 0xe2 => 0x0e42, 0xe3 => 0x0e43, + 0xe4 => 0x0e44, 0xe5 => 0x0e45, 0xe6 => 0x0e46, 0xe7 => 0x0e47, + 0xe8 => 0x0e48, 0xe9 => 0x0e49, 0xea => 0x0e4a, 0xeb => 0x0e4b, + 0xec => 0x0e4c, 0xed => 0x0e4d, 0xee => 0x2122, 0xef => 0x0e4f, + 0xf0 => 0x0e50, 0xf1 => 0x0e51, 0xf2 => 0x0e52, 0xf3 => 0x0e53, + 0xf4 => 0x0e54, 0xf5 => 0x0e55, 0xf6 => 0x0e56, 0xf7 => 0x0e57, + 0xf8 => 0x0e58, 0xf9 => 0x0e59, 0xfa => 0xae, 0xfb => 0xa9, +); + +1; # end diff --git a/lib/Image/ExifTool/Charset/MacTurkish.pm b/lib/Image/ExifTool/Charset/MacTurkish.pm new file mode 100644 index 0000000..d95cb35 --- /dev/null +++ b/lib/Image/ExifTool/Charset/MacTurkish.pm @@ -0,0 +1,42 @@ +#------------------------------------------------------------------------------ +# File: MacTurkish.pm +# +# Description: Mac Turkish to Unicode +# +# Revisions: 2010/01/20 - P. Harvey created +# +# References: 1) http://unicode.org/Public/MAPPINGS/VENDORS/APPLE/TURKISH.TXT +# +# Notes: The table omits 1-byte characters with the same values as Unicode +#------------------------------------------------------------------------------ +use strict; + +%Image::ExifTool::Charset::MacTurkish = ( + 0x80 => 0xc4, 0x81 => 0xc5, 0x82 => 0xc7, 0x83 => 0xc9, 0x84 => 0xd1, + 0x85 => 0xd6, 0x86 => 0xdc, 0x87 => 0xe1, 0x88 => 0xe0, 0x89 => 0xe2, + 0x8a => 0xe4, 0x8b => 0xe3, 0x8c => 0xe5, 0x8d => 0xe7, 0x8e => 0xe9, + 0x8f => 0xe8, 0x90 => 0xea, 0x91 => 0xeb, 0x92 => 0xed, 0x93 => 0xec, + 0x94 => 0xee, 0x95 => 0xef, 0x96 => 0xf1, 0x97 => 0xf3, 0x98 => 0xf2, + 0x99 => 0xf4, 0x9a => 0xf6, 0x9b => 0xf5, 0x9c => 0xfa, 0x9d => 0xf9, + 0x9e => 0xfb, 0x9f => 0xfc, 0xa0 => 0x2020, 0xa1 => 0xb0, 0xa4 => 0xa7, + 0xa5 => 0x2022, 0xa6 => 0xb6, 0xa7 => 0xdf, 0xa8 => 0xae, 0xaa => 0x2122, + 0xab => 0xb4, 0xac => 0xa8, 0xad => 0x2260, 0xae => 0xc6, 0xaf => 0xd8, + 0xb0 => 0x221e, 0xb2 => 0x2264, 0xb3 => 0x2265, 0xb4 => 0xa5, 0xb6 => 0x2202, + 0xb7 => 0x2211, 0xb8 => 0x220f, 0xb9 => 0x03c0, 0xba => 0x222b, 0xbb => 0xaa, + 0xbc => 0xba, 0xbd => 0x03a9, 0xbe => 0xe6, 0xbf => 0xf8, 0xc0 => 0xbf, + 0xc1 => 0xa1, 0xc2 => 0xac, 0xc3 => 0x221a, 0xc4 => 0x0192, 0xc5 => 0x2248, + 0xc6 => 0x2206, 0xc7 => 0xab, 0xc8 => 0xbb, 0xc9 => 0x2026, 0xca => 0xa0, + 0xcb => 0xc0, 0xcc => 0xc3, 0xcd => 0xd5, 0xce => 0x0152, 0xcf => 0x0153, + 0xd0 => 0x2013, 0xd1 => 0x2014, 0xd2 => 0x201c, 0xd3 => 0x201d, + 0xd4 => 0x2018, 0xd5 => 0x2019, 0xd6 => 0xf7, 0xd7 => 0x25ca, 0xd8 => 0xff, + 0xd9 => 0x0178, 0xda => 0x011e, 0xdb => 0x011f, 0xdc => 0x0130, + 0xdd => 0x0131, 0xde => 0x015e, 0xdf => 0x015f, 0xe0 => 0x2021, 0xe1 => 0xb7, + 0xe2 => 0x201a, 0xe3 => 0x201e, 0xe4 => 0x2030, 0xe5 => 0xc2, 0xe6 => 0xca, + 0xe7 => 0xc1, 0xe8 => 0xcb, 0xe9 => 0xc8, 0xea => 0xcd, 0xeb => 0xce, + 0xec => 0xcf, 0xed => 0xcc, 0xee => 0xd3, 0xef => 0xd4, 0xf0 => 0xf8ff, + 0xf1 => 0xd2, 0xf2 => 0xda, 0xf3 => 0xdb, 0xf4 => 0xd9, 0xf5 => 0xf8a0, + 0xf6 => 0x02c6, 0xf7 => 0x02dc, 0xf8 => 0xaf, 0xf9 => 0x02d8, 0xfa => 0x02d9, + 0xfb => 0x02da, 0xfc => 0xb8, 0xfd => 0x02dd, 0xfe => 0x02db, 0xff => 0x02c7, +); + +1; # end diff --git a/lib/Image/ExifTool/Charset/PDFDoc.pm b/lib/Image/ExifTool/Charset/PDFDoc.pm new file mode 100644 index 0000000..83fa0e7 --- /dev/null +++ b/lib/Image/ExifTool/Charset/PDFDoc.pm @@ -0,0 +1,28 @@ +#------------------------------------------------------------------------------ +# File: PDFDoc.pm +# +# Description: PDFDocEncoding to Unicode +# +# Revisions: 2010/10/16 - P. Harvey created +# +# References: 1) http://www.adobe.com/devnet/pdf/pdf_reference.html +# +# Notes: The table omits 1-byte characters with the same values as Unicode +# This set re-maps characters with codepoints less than 0x80 +#------------------------------------------------------------------------------ +use strict; + +%Image::ExifTool::Charset::PDFDoc = ( + 0x18 => 0x02d8, 0x82 => 0x2021, 0x8c => 0x201e, 0x96 => 0x0152, + 0x19 => 0x02c7, 0x83 => 0x2026, 0x8d => 0x201c, 0x97 => 0x0160, + 0x1a => 0x02c6, 0x84 => 0x2014, 0x8e => 0x201d, 0x98 => 0x0178, + 0x1b => 0x02d9, 0x85 => 0x2013, 0x8f => 0x2018, 0x99 => 0x017d, + 0x1c => 0x02dd, 0x86 => 0x0192, 0x90 => 0x2019, 0x9a => 0x0131, + 0x1d => 0x02db, 0x87 => 0x2044, 0x91 => 0x201a, 0x9b => 0x0142, + 0x1e => 0x02da, 0x88 => 0x2039, 0x92 => 0x2122, 0x9c => 0x0153, + 0x1f => 0x02dc, 0x89 => 0x203a, 0x93 => 0xfb01, 0x9d => 0x0161, + 0x80 => 0x2022, 0x8a => 0x2212, 0x94 => 0xfb02, 0x9e => 0x017e, + 0x81 => 0x2020, 0x8b => 0x2030, 0x95 => 0x0141, 0xa0 => 0x20ac, +); + +1; # end diff --git a/lib/Image/ExifTool/Charset/ShiftJIS.pm b/lib/Image/ExifTool/Charset/ShiftJIS.pm new file mode 100644 index 0000000..d2a99d3 --- /dev/null +++ b/lib/Image/ExifTool/Charset/ShiftJIS.pm @@ -0,0 +1,1835 @@ +#------------------------------------------------------------------------------ +# File: ShiftJIS.pm +# +# Description: Shift-JIS to Unicode +# +# Revisions: 2010/01/20 - P. Harvey created +# 2010/07/30 - P. Harvey fixed to use variable-width characters +# +# References: 1) http://unicode.org/Public/MAPPINGS/OBSOLETE/EASTASIA/JIS/SHIFTJIS.TXT +# +# Notes: The table omits 1-byte characters with the same values as Unicode +#------------------------------------------------------------------------------ +use strict; + +%Image::ExifTool::Charset::ShiftJIS = ( + 0x5c => 0xa5, 0x7e => 0x203e, + 0x81 => { + 0x40 => 0x3000, 0x41 => 0x3001, 0x42 => 0x3002, 0x43 => 0xff0c, + 0x44 => 0xff0e, 0x45 => 0x30fb, 0x46 => 0xff1a, 0x47 => 0xff1b, + 0x48 => 0xff1f, 0x49 => 0xff01, 0x4a => 0x309b, 0x4b => 0x309c, + 0x4c => 0xb4, 0x4d => 0xff40, 0x4e => 0xa8, 0x4f => 0xff3e, 0x50 => 0xffe3, + 0x51 => 0xff3f, 0x52 => 0x30fd, 0x53 => 0x30fe, 0x54 => 0x309d, + 0x55 => 0x309e, 0x56 => 0x3003, 0x57 => 0x4edd, 0x58 => 0x3005, + 0x59 => 0x3006, 0x5a => 0x3007, 0x5b => 0x30fc, 0x5c => 0x2015, + 0x5d => 0x2010, 0x5e => 0xff0f, 0x5f => 0x5c, 0x60 => 0x301c, + 0x61 => 0x2016, 0x62 => 0xff5c, 0x63 => 0x2026, 0x64 => 0x2025, + 0x65 => 0x2018, 0x66 => 0x2019, 0x67 => 0x201c, 0x68 => 0x201d, + 0x69 => 0xff08, 0x6a => 0xff09, 0x6b => 0x3014, 0x6c => 0x3015, + 0x6d => 0xff3b, 0x6e => 0xff3d, 0x6f => 0xff5b, 0x70 => 0xff5d, + 0x71 => 0x3008, 0x72 => 0x3009, 0x73 => 0x300a, 0x74 => 0x300b, + 0x75 => 0x300c, 0x76 => 0x300d, 0x77 => 0x300e, 0x78 => 0x300f, + 0x79 => 0x3010, 0x7a => 0x3011, 0x7b => 0xff0b, 0x7c => 0x2212, + 0x7d => 0xb1, 0x7e => 0xd7, 0x80 => 0xf7, 0x81 => 0xff1d, 0x82 => 0x2260, + 0x83 => 0xff1c, 0x84 => 0xff1e, 0x85 => 0x2266, 0x86 => 0x2267, + 0x87 => 0x221e, 0x88 => 0x2234, 0x89 => 0x2642, 0x8a => 0x2640, + 0x8b => 0xb0, 0x8c => 0x2032, 0x8d => 0x2033, 0x8e => 0x2103, + 0x8f => 0xffe5, 0x90 => 0xff04, 0x91 => 0xa2, 0x92 => 0xa3, 0x93 => 0xff05, + 0x94 => 0xff03, 0x95 => 0xff06, 0x96 => 0xff0a, 0x97 => 0xff20, + 0x98 => 0xa7, 0x99 => 0x2606, 0x9a => 0x2605, 0x9b => 0x25cb, + 0x9c => 0x25cf, 0x9d => 0x25ce, 0x9e => 0x25c7, 0x9f => 0x25c6, + 0xa0 => 0x25a1, 0xa1 => 0x25a0, 0xa2 => 0x25b3, 0xa3 => 0x25b2, + 0xa4 => 0x25bd, 0xa5 => 0x25bc, 0xa6 => 0x203b, 0xa7 => 0x3012, + 0xa8 => 0x2192, 0xa9 => 0x2190, 0xaa => 0x2191, 0xab => 0x2193, + 0xac => 0x3013, 0xb8 => 0x2208, 0xb9 => 0x220b, 0xba => 0x2286, + 0xbb => 0x2287, 0xbc => 0x2282, 0xbd => 0x2283, 0xbe => 0x222a, + 0xbf => 0x2229, 0xc8 => 0x2227, 0xc9 => 0x2228, 0xca => 0xac, + 0xcb => 0x21d2, 0xcc => 0x21d4, 0xcd => 0x2200, 0xce => 0x2203, + 0xda => 0x2220, 0xdb => 0x22a5, 0xdc => 0x2312, 0xdd => 0x2202, + 0xde => 0x2207, 0xdf => 0x2261, 0xe0 => 0x2252, 0xe1 => 0x226a, + 0xe2 => 0x226b, 0xe3 => 0x221a, 0xe4 => 0x223d, 0xe5 => 0x221d, + 0xe6 => 0x2235, 0xe7 => 0x222b, 0xe8 => 0x222c, 0xf0 => 0x212b, + 0xf1 => 0x2030, 0xf2 => 0x266f, 0xf3 => 0x266d, 0xf4 => 0x266a, + 0xf5 => 0x2020, 0xf6 => 0x2021, 0xf7 => 0xb6, 0xfc => 0x25ef, + }, + 0x82 => { + 0x4f => 0xff10, 0x50 => 0xff11, 0x51 => 0xff12, 0x52 => 0xff13, + 0x53 => 0xff14, 0x54 => 0xff15, 0x55 => 0xff16, 0x56 => 0xff17, + 0x57 => 0xff18, 0x58 => 0xff19, 0x60 => 0xff21, 0x61 => 0xff22, + 0x62 => 0xff23, 0x63 => 0xff24, 0x64 => 0xff25, 0x65 => 0xff26, + 0x66 => 0xff27, 0x67 => 0xff28, 0x68 => 0xff29, 0x69 => 0xff2a, + 0x6a => 0xff2b, 0x6b => 0xff2c, 0x6c => 0xff2d, 0x6d => 0xff2e, + 0x6e => 0xff2f, 0x6f => 0xff30, 0x70 => 0xff31, 0x71 => 0xff32, + 0x72 => 0xff33, 0x73 => 0xff34, 0x74 => 0xff35, 0x75 => 0xff36, + 0x76 => 0xff37, 0x77 => 0xff38, 0x78 => 0xff39, 0x79 => 0xff3a, + 0x81 => 0xff41, 0x82 => 0xff42, 0x83 => 0xff43, 0x84 => 0xff44, + 0x85 => 0xff45, 0x86 => 0xff46, 0x87 => 0xff47, 0x88 => 0xff48, + 0x89 => 0xff49, 0x8a => 0xff4a, 0x8b => 0xff4b, 0x8c => 0xff4c, + 0x8d => 0xff4d, 0x8e => 0xff4e, 0x8f => 0xff4f, 0x90 => 0xff50, + 0x91 => 0xff51, 0x92 => 0xff52, 0x93 => 0xff53, 0x94 => 0xff54, + 0x95 => 0xff55, 0x96 => 0xff56, 0x97 => 0xff57, 0x98 => 0xff58, + 0x99 => 0xff59, 0x9a => 0xff5a, 0x9f => 0x3041, 0xa0 => 0x3042, + 0xa1 => 0x3043, 0xa2 => 0x3044, 0xa3 => 0x3045, 0xa4 => 0x3046, + 0xa5 => 0x3047, 0xa6 => 0x3048, 0xa7 => 0x3049, 0xa8 => 0x304a, + 0xa9 => 0x304b, 0xaa => 0x304c, 0xab => 0x304d, 0xac => 0x304e, + 0xad => 0x304f, 0xae => 0x3050, 0xaf => 0x3051, 0xb0 => 0x3052, + 0xb1 => 0x3053, 0xb2 => 0x3054, 0xb3 => 0x3055, 0xb4 => 0x3056, + 0xb5 => 0x3057, 0xb6 => 0x3058, 0xb7 => 0x3059, 0xb8 => 0x305a, + 0xb9 => 0x305b, 0xba => 0x305c, 0xbb => 0x305d, 0xbc => 0x305e, + 0xbd => 0x305f, 0xbe => 0x3060, 0xbf => 0x3061, 0xc0 => 0x3062, + 0xc1 => 0x3063, 0xc2 => 0x3064, 0xc3 => 0x3065, 0xc4 => 0x3066, + 0xc5 => 0x3067, 0xc6 => 0x3068, 0xc7 => 0x3069, 0xc8 => 0x306a, + 0xc9 => 0x306b, 0xca => 0x306c, 0xcb => 0x306d, 0xcc => 0x306e, + 0xcd => 0x306f, 0xce => 0x3070, 0xcf => 0x3071, 0xd0 => 0x3072, + 0xd1 => 0x3073, 0xd2 => 0x3074, 0xd3 => 0x3075, 0xd4 => 0x3076, + 0xd5 => 0x3077, 0xd6 => 0x3078, 0xd7 => 0x3079, 0xd8 => 0x307a, + 0xd9 => 0x307b, 0xda => 0x307c, 0xdb => 0x307d, 0xdc => 0x307e, + 0xdd => 0x307f, 0xde => 0x3080, 0xdf => 0x3081, 0xe0 => 0x3082, + 0xe1 => 0x3083, 0xe2 => 0x3084, 0xe3 => 0x3085, 0xe4 => 0x3086, + 0xe5 => 0x3087, 0xe6 => 0x3088, 0xe7 => 0x3089, 0xe8 => 0x308a, + 0xe9 => 0x308b, 0xea => 0x308c, 0xeb => 0x308d, 0xec => 0x308e, + 0xed => 0x308f, 0xee => 0x3090, 0xef => 0x3091, 0xf0 => 0x3092, + 0xf1 => 0x3093, + }, + 0x83 => { + 0x40 => 0x30a1, 0x41 => 0x30a2, 0x42 => 0x30a3, 0x43 => 0x30a4, + 0x44 => 0x30a5, 0x45 => 0x30a6, 0x46 => 0x30a7, 0x47 => 0x30a8, + 0x48 => 0x30a9, 0x49 => 0x30aa, 0x4a => 0x30ab, 0x4b => 0x30ac, + 0x4c => 0x30ad, 0x4d => 0x30ae, 0x4e => 0x30af, 0x4f => 0x30b0, + 0x50 => 0x30b1, 0x51 => 0x30b2, 0x52 => 0x30b3, 0x53 => 0x30b4, + 0x54 => 0x30b5, 0x55 => 0x30b6, 0x56 => 0x30b7, 0x57 => 0x30b8, + 0x58 => 0x30b9, 0x59 => 0x30ba, 0x5a => 0x30bb, 0x5b => 0x30bc, + 0x5c => 0x30bd, 0x5d => 0x30be, 0x5e => 0x30bf, 0x5f => 0x30c0, + 0x60 => 0x30c1, 0x61 => 0x30c2, 0x62 => 0x30c3, 0x63 => 0x30c4, + 0x64 => 0x30c5, 0x65 => 0x30c6, 0x66 => 0x30c7, 0x67 => 0x30c8, + 0x68 => 0x30c9, 0x69 => 0x30ca, 0x6a => 0x30cb, 0x6b => 0x30cc, + 0x6c => 0x30cd, 0x6d => 0x30ce, 0x6e => 0x30cf, 0x6f => 0x30d0, + 0x70 => 0x30d1, 0x71 => 0x30d2, 0x72 => 0x30d3, 0x73 => 0x30d4, + 0x74 => 0x30d5, 0x75 => 0x30d6, 0x76 => 0x30d7, 0x77 => 0x30d8, + 0x78 => 0x30d9, 0x79 => 0x30da, 0x7a => 0x30db, 0x7b => 0x30dc, + 0x7c => 0x30dd, 0x7d => 0x30de, 0x7e => 0x30df, 0x80 => 0x30e0, + 0x81 => 0x30e1, 0x82 => 0x30e2, 0x83 => 0x30e3, 0x84 => 0x30e4, + 0x85 => 0x30e5, 0x86 => 0x30e6, 0x87 => 0x30e7, 0x88 => 0x30e8, + 0x89 => 0x30e9, 0x8a => 0x30ea, 0x8b => 0x30eb, 0x8c => 0x30ec, + 0x8d => 0x30ed, 0x8e => 0x30ee, 0x8f => 0x30ef, 0x90 => 0x30f0, + 0x91 => 0x30f1, 0x92 => 0x30f2, 0x93 => 0x30f3, 0x94 => 0x30f4, + 0x95 => 0x30f5, 0x96 => 0x30f6, 0x9f => 0x0391, 0xa0 => 0x0392, + 0xa1 => 0x0393, 0xa2 => 0x0394, 0xa3 => 0x0395, 0xa4 => 0x0396, + 0xa5 => 0x0397, 0xa6 => 0x0398, 0xa7 => 0x0399, 0xa8 => 0x039a, + 0xa9 => 0x039b, 0xaa => 0x039c, 0xab => 0x039d, 0xac => 0x039e, + 0xad => 0x039f, 0xae => 0x03a0, 0xaf => 0x03a1, 0xb0 => 0x03a3, + 0xb1 => 0x03a4, 0xb2 => 0x03a5, 0xb3 => 0x03a6, 0xb4 => 0x03a7, + 0xb5 => 0x03a8, 0xb6 => 0x03a9, 0xbf => 0x03b1, 0xc0 => 0x03b2, + 0xc1 => 0x03b3, 0xc2 => 0x03b4, 0xc3 => 0x03b5, 0xc4 => 0x03b6, + 0xc5 => 0x03b7, 0xc6 => 0x03b8, 0xc7 => 0x03b9, 0xc8 => 0x03ba, + 0xc9 => 0x03bb, 0xca => 0x03bc, 0xcb => 0x03bd, 0xcc => 0x03be, + 0xcd => 0x03bf, 0xce => 0x03c0, 0xcf => 0x03c1, 0xd0 => 0x03c3, + 0xd1 => 0x03c4, 0xd2 => 0x03c5, 0xd3 => 0x03c6, 0xd4 => 0x03c7, + 0xd5 => 0x03c8, 0xd6 => 0x03c9, + }, + 0x84 => { + 0x40 => 0x0410, 0x41 => 0x0411, 0x42 => 0x0412, 0x43 => 0x0413, + 0x44 => 0x0414, 0x45 => 0x0415, 0x46 => 0x0401, 0x47 => 0x0416, + 0x48 => 0x0417, 0x49 => 0x0418, 0x4a => 0x0419, 0x4b => 0x041a, + 0x4c => 0x041b, 0x4d => 0x041c, 0x4e => 0x041d, 0x4f => 0x041e, + 0x50 => 0x041f, 0x51 => 0x0420, 0x52 => 0x0421, 0x53 => 0x0422, + 0x54 => 0x0423, 0x55 => 0x0424, 0x56 => 0x0425, 0x57 => 0x0426, + 0x58 => 0x0427, 0x59 => 0x0428, 0x5a => 0x0429, 0x5b => 0x042a, + 0x5c => 0x042b, 0x5d => 0x042c, 0x5e => 0x042d, 0x5f => 0x042e, + 0x60 => 0x042f, 0x70 => 0x0430, 0x71 => 0x0431, 0x72 => 0x0432, + 0x73 => 0x0433, 0x74 => 0x0434, 0x75 => 0x0435, 0x76 => 0x0451, + 0x77 => 0x0436, 0x78 => 0x0437, 0x79 => 0x0438, 0x7a => 0x0439, + 0x7b => 0x043a, 0x7c => 0x043b, 0x7d => 0x043c, 0x7e => 0x043d, + 0x80 => 0x043e, 0x81 => 0x043f, 0x82 => 0x0440, 0x83 => 0x0441, + 0x84 => 0x0442, 0x85 => 0x0443, 0x86 => 0x0444, 0x87 => 0x0445, + 0x88 => 0x0446, 0x89 => 0x0447, 0x8a => 0x0448, 0x8b => 0x0449, + 0x8c => 0x044a, 0x8d => 0x044b, 0x8e => 0x044c, 0x8f => 0x044d, + 0x90 => 0x044e, 0x91 => 0x044f, 0x9f => 0x2500, 0xa0 => 0x2502, + 0xa1 => 0x250c, 0xa2 => 0x2510, 0xa3 => 0x2518, 0xa4 => 0x2514, + 0xa5 => 0x251c, 0xa6 => 0x252c, 0xa7 => 0x2524, 0xa8 => 0x2534, + 0xa9 => 0x253c, 0xaa => 0x2501, 0xab => 0x2503, 0xac => 0x250f, + 0xad => 0x2513, 0xae => 0x251b, 0xaf => 0x2517, 0xb0 => 0x2523, + 0xb1 => 0x2533, 0xb2 => 0x252b, 0xb3 => 0x253b, 0xb4 => 0x254b, + 0xb5 => 0x2520, 0xb6 => 0x252f, 0xb7 => 0x2528, 0xb8 => 0x2537, + 0xb9 => 0x253f, 0xba => 0x251d, 0xbb => 0x2530, 0xbc => 0x2525, + 0xbd => 0x2538, 0xbe => 0x2542, + }, + 0x88 => { + 0x9f => 0x4e9c, 0xa0 => 0x5516, 0xa1 => 0x5a03, 0xa2 => 0x963f, + 0xa3 => 0x54c0, 0xa4 => 0x611b, 0xa5 => 0x6328, 0xa6 => 0x59f6, + 0xa7 => 0x9022, 0xa8 => 0x8475, 0xa9 => 0x831c, 0xaa => 0x7a50, + 0xab => 0x60aa, 0xac => 0x63e1, 0xad => 0x6e25, 0xae => 0x65ed, + 0xaf => 0x8466, 0xb0 => 0x82a6, 0xb1 => 0x9bf5, 0xb2 => 0x6893, + 0xb3 => 0x5727, 0xb4 => 0x65a1, 0xb5 => 0x6271, 0xb6 => 0x5b9b, + 0xb7 => 0x59d0, 0xb8 => 0x867b, 0xb9 => 0x98f4, 0xba => 0x7d62, + 0xbb => 0x7dbe, 0xbc => 0x9b8e, 0xbd => 0x6216, 0xbe => 0x7c9f, + 0xbf => 0x88b7, 0xc0 => 0x5b89, 0xc1 => 0x5eb5, 0xc2 => 0x6309, + 0xc3 => 0x6697, 0xc4 => 0x6848, 0xc5 => 0x95c7, 0xc6 => 0x978d, + 0xc7 => 0x674f, 0xc8 => 0x4ee5, 0xc9 => 0x4f0a, 0xca => 0x4f4d, + 0xcb => 0x4f9d, 0xcc => 0x5049, 0xcd => 0x56f2, 0xce => 0x5937, + 0xcf => 0x59d4, 0xd0 => 0x5a01, 0xd1 => 0x5c09, 0xd2 => 0x60df, + 0xd3 => 0x610f, 0xd4 => 0x6170, 0xd5 => 0x6613, 0xd6 => 0x6905, + 0xd7 => 0x70ba, 0xd8 => 0x754f, 0xd9 => 0x7570, 0xda => 0x79fb, + 0xdb => 0x7dad, 0xdc => 0x7def, 0xdd => 0x80c3, 0xde => 0x840e, + 0xdf => 0x8863, 0xe0 => 0x8b02, 0xe1 => 0x9055, 0xe2 => 0x907a, + 0xe3 => 0x533b, 0xe4 => 0x4e95, 0xe5 => 0x4ea5, 0xe6 => 0x57df, + 0xe7 => 0x80b2, 0xe8 => 0x90c1, 0xe9 => 0x78ef, 0xea => 0x4e00, + 0xeb => 0x58f1, 0xec => 0x6ea2, 0xed => 0x9038, 0xee => 0x7a32, + 0xef => 0x8328, 0xf0 => 0x828b, 0xf1 => 0x9c2f, 0xf2 => 0x5141, + 0xf3 => 0x5370, 0xf4 => 0x54bd, 0xf5 => 0x54e1, 0xf6 => 0x56e0, + 0xf7 => 0x59fb, 0xf8 => 0x5f15, 0xf9 => 0x98f2, 0xfa => 0x6deb, + 0xfb => 0x80e4, 0xfc => 0x852d, + }, + 0x89 => { + 0x40 => 0x9662, 0x41 => 0x9670, 0x42 => 0x96a0, 0x43 => 0x97fb, + 0x44 => 0x540b, 0x45 => 0x53f3, 0x46 => 0x5b87, 0x47 => 0x70cf, + 0x48 => 0x7fbd, 0x49 => 0x8fc2, 0x4a => 0x96e8, 0x4b => 0x536f, + 0x4c => 0x9d5c, 0x4d => 0x7aba, 0x4e => 0x4e11, 0x4f => 0x7893, + 0x50 => 0x81fc, 0x51 => 0x6e26, 0x52 => 0x5618, 0x53 => 0x5504, + 0x54 => 0x6b1d, 0x55 => 0x851a, 0x56 => 0x9c3b, 0x57 => 0x59e5, + 0x58 => 0x53a9, 0x59 => 0x6d66, 0x5a => 0x74dc, 0x5b => 0x958f, + 0x5c => 0x5642, 0x5d => 0x4e91, 0x5e => 0x904b, 0x5f => 0x96f2, + 0x60 => 0x834f, 0x61 => 0x990c, 0x62 => 0x53e1, 0x63 => 0x55b6, + 0x64 => 0x5b30, 0x65 => 0x5f71, 0x66 => 0x6620, 0x67 => 0x66f3, + 0x68 => 0x6804, 0x69 => 0x6c38, 0x6a => 0x6cf3, 0x6b => 0x6d29, + 0x6c => 0x745b, 0x6d => 0x76c8, 0x6e => 0x7a4e, 0x6f => 0x9834, + 0x70 => 0x82f1, 0x71 => 0x885b, 0x72 => 0x8a60, 0x73 => 0x92ed, + 0x74 => 0x6db2, 0x75 => 0x75ab, 0x76 => 0x76ca, 0x77 => 0x99c5, + 0x78 => 0x60a6, 0x79 => 0x8b01, 0x7a => 0x8d8a, 0x7b => 0x95b2, + 0x7c => 0x698e, 0x7d => 0x53ad, 0x7e => 0x5186, 0x80 => 0x5712, + 0x81 => 0x5830, 0x82 => 0x5944, 0x83 => 0x5bb4, 0x84 => 0x5ef6, + 0x85 => 0x6028, 0x86 => 0x63a9, 0x87 => 0x63f4, 0x88 => 0x6cbf, + 0x89 => 0x6f14, 0x8a => 0x708e, 0x8b => 0x7114, 0x8c => 0x7159, + 0x8d => 0x71d5, 0x8e => 0x733f, 0x8f => 0x7e01, 0x90 => 0x8276, + 0x91 => 0x82d1, 0x92 => 0x8597, 0x93 => 0x9060, 0x94 => 0x925b, + 0x95 => 0x9d1b, 0x96 => 0x5869, 0x97 => 0x65bc, 0x98 => 0x6c5a, + 0x99 => 0x7525, 0x9a => 0x51f9, 0x9b => 0x592e, 0x9c => 0x5965, + 0x9d => 0x5f80, 0x9e => 0x5fdc, 0x9f => 0x62bc, 0xa0 => 0x65fa, + 0xa1 => 0x6a2a, 0xa2 => 0x6b27, 0xa3 => 0x6bb4, 0xa4 => 0x738b, + 0xa5 => 0x7fc1, 0xa6 => 0x8956, 0xa7 => 0x9d2c, 0xa8 => 0x9d0e, + 0xa9 => 0x9ec4, 0xaa => 0x5ca1, 0xab => 0x6c96, 0xac => 0x837b, + 0xad => 0x5104, 0xae => 0x5c4b, 0xaf => 0x61b6, 0xb0 => 0x81c6, + 0xb1 => 0x6876, 0xb2 => 0x7261, 0xb3 => 0x4e59, 0xb4 => 0x4ffa, + 0xb5 => 0x5378, 0xb6 => 0x6069, 0xb7 => 0x6e29, 0xb8 => 0x7a4f, + 0xb9 => 0x97f3, 0xba => 0x4e0b, 0xbb => 0x5316, 0xbc => 0x4eee, + 0xbd => 0x4f55, 0xbe => 0x4f3d, 0xbf => 0x4fa1, 0xc0 => 0x4f73, + 0xc1 => 0x52a0, 0xc2 => 0x53ef, 0xc3 => 0x5609, 0xc4 => 0x590f, + 0xc5 => 0x5ac1, 0xc6 => 0x5bb6, 0xc7 => 0x5be1, 0xc8 => 0x79d1, + 0xc9 => 0x6687, 0xca => 0x679c, 0xcb => 0x67b6, 0xcc => 0x6b4c, + 0xcd => 0x6cb3, 0xce => 0x706b, 0xcf => 0x73c2, 0xd0 => 0x798d, + 0xd1 => 0x79be, 0xd2 => 0x7a3c, 0xd3 => 0x7b87, 0xd4 => 0x82b1, + 0xd5 => 0x82db, 0xd6 => 0x8304, 0xd7 => 0x8377, 0xd8 => 0x83ef, + 0xd9 => 0x83d3, 0xda => 0x8766, 0xdb => 0x8ab2, 0xdc => 0x5629, + 0xdd => 0x8ca8, 0xde => 0x8fe6, 0xdf => 0x904e, 0xe0 => 0x971e, + 0xe1 => 0x868a, 0xe2 => 0x4fc4, 0xe3 => 0x5ce8, 0xe4 => 0x6211, + 0xe5 => 0x7259, 0xe6 => 0x753b, 0xe7 => 0x81e5, 0xe8 => 0x82bd, + 0xe9 => 0x86fe, 0xea => 0x8cc0, 0xeb => 0x96c5, 0xec => 0x9913, + 0xed => 0x99d5, 0xee => 0x4ecb, 0xef => 0x4f1a, 0xf0 => 0x89e3, + 0xf1 => 0x56de, 0xf2 => 0x584a, 0xf3 => 0x58ca, 0xf4 => 0x5efb, + 0xf5 => 0x5feb, 0xf6 => 0x602a, 0xf7 => 0x6094, 0xf8 => 0x6062, + 0xf9 => 0x61d0, 0xfa => 0x6212, 0xfb => 0x62d0, 0xfc => 0x6539, + }, + 0x8a => { + 0x40 => 0x9b41, 0x41 => 0x6666, 0x42 => 0x68b0, 0x43 => 0x6d77, + 0x44 => 0x7070, 0x45 => 0x754c, 0x46 => 0x7686, 0x47 => 0x7d75, + 0x48 => 0x82a5, 0x49 => 0x87f9, 0x4a => 0x958b, 0x4b => 0x968e, + 0x4c => 0x8c9d, 0x4d => 0x51f1, 0x4e => 0x52be, 0x4f => 0x5916, + 0x50 => 0x54b3, 0x51 => 0x5bb3, 0x52 => 0x5d16, 0x53 => 0x6168, + 0x54 => 0x6982, 0x55 => 0x6daf, 0x56 => 0x788d, 0x57 => 0x84cb, + 0x58 => 0x8857, 0x59 => 0x8a72, 0x5a => 0x93a7, 0x5b => 0x9ab8, + 0x5c => 0x6d6c, 0x5d => 0x99a8, 0x5e => 0x86d9, 0x5f => 0x57a3, + 0x60 => 0x67ff, 0x61 => 0x86ce, 0x62 => 0x920e, 0x63 => 0x5283, + 0x64 => 0x5687, 0x65 => 0x5404, 0x66 => 0x5ed3, 0x67 => 0x62e1, + 0x68 => 0x64b9, 0x69 => 0x683c, 0x6a => 0x6838, 0x6b => 0x6bbb, + 0x6c => 0x7372, 0x6d => 0x78ba, 0x6e => 0x7a6b, 0x6f => 0x899a, + 0x70 => 0x89d2, 0x71 => 0x8d6b, 0x72 => 0x8f03, 0x73 => 0x90ed, + 0x74 => 0x95a3, 0x75 => 0x9694, 0x76 => 0x9769, 0x77 => 0x5b66, + 0x78 => 0x5cb3, 0x79 => 0x697d, 0x7a => 0x984d, 0x7b => 0x984e, + 0x7c => 0x639b, 0x7d => 0x7b20, 0x7e => 0x6a2b, 0x80 => 0x6a7f, + 0x81 => 0x68b6, 0x82 => 0x9c0d, 0x83 => 0x6f5f, 0x84 => 0x5272, + 0x85 => 0x559d, 0x86 => 0x6070, 0x87 => 0x62ec, 0x88 => 0x6d3b, + 0x89 => 0x6e07, 0x8a => 0x6ed1, 0x8b => 0x845b, 0x8c => 0x8910, + 0x8d => 0x8f44, 0x8e => 0x4e14, 0x8f => 0x9c39, 0x90 => 0x53f6, + 0x91 => 0x691b, 0x92 => 0x6a3a, 0x93 => 0x9784, 0x94 => 0x682a, + 0x95 => 0x515c, 0x96 => 0x7ac3, 0x97 => 0x84b2, 0x98 => 0x91dc, + 0x99 => 0x938c, 0x9a => 0x565b, 0x9b => 0x9d28, 0x9c => 0x6822, + 0x9d => 0x8305, 0x9e => 0x8431, 0x9f => 0x7ca5, 0xa0 => 0x5208, + 0xa1 => 0x82c5, 0xa2 => 0x74e6, 0xa3 => 0x4e7e, 0xa4 => 0x4f83, + 0xa5 => 0x51a0, 0xa6 => 0x5bd2, 0xa7 => 0x520a, 0xa8 => 0x52d8, + 0xa9 => 0x52e7, 0xaa => 0x5dfb, 0xab => 0x559a, 0xac => 0x582a, + 0xad => 0x59e6, 0xae => 0x5b8c, 0xaf => 0x5b98, 0xb0 => 0x5bdb, + 0xb1 => 0x5e72, 0xb2 => 0x5e79, 0xb3 => 0x60a3, 0xb4 => 0x611f, + 0xb5 => 0x6163, 0xb6 => 0x61be, 0xb7 => 0x63db, 0xb8 => 0x6562, + 0xb9 => 0x67d1, 0xba => 0x6853, 0xbb => 0x68fa, 0xbc => 0x6b3e, + 0xbd => 0x6b53, 0xbe => 0x6c57, 0xbf => 0x6f22, 0xc0 => 0x6f97, + 0xc1 => 0x6f45, 0xc2 => 0x74b0, 0xc3 => 0x7518, 0xc4 => 0x76e3, + 0xc5 => 0x770b, 0xc6 => 0x7aff, 0xc7 => 0x7ba1, 0xc8 => 0x7c21, + 0xc9 => 0x7de9, 0xca => 0x7f36, 0xcb => 0x7ff0, 0xcc => 0x809d, + 0xcd => 0x8266, 0xce => 0x839e, 0xcf => 0x89b3, 0xd0 => 0x8acc, + 0xd1 => 0x8cab, 0xd2 => 0x9084, 0xd3 => 0x9451, 0xd4 => 0x9593, + 0xd5 => 0x9591, 0xd6 => 0x95a2, 0xd7 => 0x9665, 0xd8 => 0x97d3, + 0xd9 => 0x9928, 0xda => 0x8218, 0xdb => 0x4e38, 0xdc => 0x542b, + 0xdd => 0x5cb8, 0xde => 0x5dcc, 0xdf => 0x73a9, 0xe0 => 0x764c, + 0xe1 => 0x773c, 0xe2 => 0x5ca9, 0xe3 => 0x7feb, 0xe4 => 0x8d0b, + 0xe5 => 0x96c1, 0xe6 => 0x9811, 0xe7 => 0x9854, 0xe8 => 0x9858, + 0xe9 => 0x4f01, 0xea => 0x4f0e, 0xeb => 0x5371, 0xec => 0x559c, + 0xed => 0x5668, 0xee => 0x57fa, 0xef => 0x5947, 0xf0 => 0x5b09, + 0xf1 => 0x5bc4, 0xf2 => 0x5c90, 0xf3 => 0x5e0c, 0xf4 => 0x5e7e, + 0xf5 => 0x5fcc, 0xf6 => 0x63ee, 0xf7 => 0x673a, 0xf8 => 0x65d7, + 0xf9 => 0x65e2, 0xfa => 0x671f, 0xfb => 0x68cb, 0xfc => 0x68c4, + }, + 0x8b => { + 0x40 => 0x6a5f, 0x41 => 0x5e30, 0x42 => 0x6bc5, 0x43 => 0x6c17, + 0x44 => 0x6c7d, 0x45 => 0x757f, 0x46 => 0x7948, 0x47 => 0x5b63, + 0x48 => 0x7a00, 0x49 => 0x7d00, 0x4a => 0x5fbd, 0x4b => 0x898f, + 0x4c => 0x8a18, 0x4d => 0x8cb4, 0x4e => 0x8d77, 0x4f => 0x8ecc, + 0x50 => 0x8f1d, 0x51 => 0x98e2, 0x52 => 0x9a0e, 0x53 => 0x9b3c, + 0x54 => 0x4e80, 0x55 => 0x507d, 0x56 => 0x5100, 0x57 => 0x5993, + 0x58 => 0x5b9c, 0x59 => 0x622f, 0x5a => 0x6280, 0x5b => 0x64ec, + 0x5c => 0x6b3a, 0x5d => 0x72a0, 0x5e => 0x7591, 0x5f => 0x7947, + 0x60 => 0x7fa9, 0x61 => 0x87fb, 0x62 => 0x8abc, 0x63 => 0x8b70, + 0x64 => 0x63ac, 0x65 => 0x83ca, 0x66 => 0x97a0, 0x67 => 0x5409, + 0x68 => 0x5403, 0x69 => 0x55ab, 0x6a => 0x6854, 0x6b => 0x6a58, + 0x6c => 0x8a70, 0x6d => 0x7827, 0x6e => 0x6775, 0x6f => 0x9ecd, + 0x70 => 0x5374, 0x71 => 0x5ba2, 0x72 => 0x811a, 0x73 => 0x8650, + 0x74 => 0x9006, 0x75 => 0x4e18, 0x76 => 0x4e45, 0x77 => 0x4ec7, + 0x78 => 0x4f11, 0x79 => 0x53ca, 0x7a => 0x5438, 0x7b => 0x5bae, + 0x7c => 0x5f13, 0x7d => 0x6025, 0x7e => 0x6551, 0x80 => 0x673d, + 0x81 => 0x6c42, 0x82 => 0x6c72, 0x83 => 0x6ce3, 0x84 => 0x7078, + 0x85 => 0x7403, 0x86 => 0x7a76, 0x87 => 0x7aae, 0x88 => 0x7b08, + 0x89 => 0x7d1a, 0x8a => 0x7cfe, 0x8b => 0x7d66, 0x8c => 0x65e7, + 0x8d => 0x725b, 0x8e => 0x53bb, 0x8f => 0x5c45, 0x90 => 0x5de8, + 0x91 => 0x62d2, 0x92 => 0x62e0, 0x93 => 0x6319, 0x94 => 0x6e20, + 0x95 => 0x865a, 0x96 => 0x8a31, 0x97 => 0x8ddd, 0x98 => 0x92f8, + 0x99 => 0x6f01, 0x9a => 0x79a6, 0x9b => 0x9b5a, 0x9c => 0x4ea8, + 0x9d => 0x4eab, 0x9e => 0x4eac, 0x9f => 0x4f9b, 0xa0 => 0x4fa0, + 0xa1 => 0x50d1, 0xa2 => 0x5147, 0xa3 => 0x7af6, 0xa4 => 0x5171, + 0xa5 => 0x51f6, 0xa6 => 0x5354, 0xa7 => 0x5321, 0xa8 => 0x537f, + 0xa9 => 0x53eb, 0xaa => 0x55ac, 0xab => 0x5883, 0xac => 0x5ce1, + 0xad => 0x5f37, 0xae => 0x5f4a, 0xaf => 0x602f, 0xb0 => 0x6050, + 0xb1 => 0x606d, 0xb2 => 0x631f, 0xb3 => 0x6559, 0xb4 => 0x6a4b, + 0xb5 => 0x6cc1, 0xb6 => 0x72c2, 0xb7 => 0x72ed, 0xb8 => 0x77ef, + 0xb9 => 0x80f8, 0xba => 0x8105, 0xbb => 0x8208, 0xbc => 0x854e, + 0xbd => 0x90f7, 0xbe => 0x93e1, 0xbf => 0x97ff, 0xc0 => 0x9957, + 0xc1 => 0x9a5a, 0xc2 => 0x4ef0, 0xc3 => 0x51dd, 0xc4 => 0x5c2d, + 0xc5 => 0x6681, 0xc6 => 0x696d, 0xc7 => 0x5c40, 0xc8 => 0x66f2, + 0xc9 => 0x6975, 0xca => 0x7389, 0xcb => 0x6850, 0xcc => 0x7c81, + 0xcd => 0x50c5, 0xce => 0x52e4, 0xcf => 0x5747, 0xd0 => 0x5dfe, + 0xd1 => 0x9326, 0xd2 => 0x65a4, 0xd3 => 0x6b23, 0xd4 => 0x6b3d, + 0xd5 => 0x7434, 0xd6 => 0x7981, 0xd7 => 0x79bd, 0xd8 => 0x7b4b, + 0xd9 => 0x7dca, 0xda => 0x82b9, 0xdb => 0x83cc, 0xdc => 0x887f, + 0xdd => 0x895f, 0xde => 0x8b39, 0xdf => 0x8fd1, 0xe0 => 0x91d1, + 0xe1 => 0x541f, 0xe2 => 0x9280, 0xe3 => 0x4e5d, 0xe4 => 0x5036, + 0xe5 => 0x53e5, 0xe6 => 0x533a, 0xe7 => 0x72d7, 0xe8 => 0x7396, + 0xe9 => 0x77e9, 0xea => 0x82e6, 0xeb => 0x8eaf, 0xec => 0x99c6, + 0xed => 0x99c8, 0xee => 0x99d2, 0xef => 0x5177, 0xf0 => 0x611a, + 0xf1 => 0x865e, 0xf2 => 0x55b0, 0xf3 => 0x7a7a, 0xf4 => 0x5076, + 0xf5 => 0x5bd3, 0xf6 => 0x9047, 0xf7 => 0x9685, 0xf8 => 0x4e32, + 0xf9 => 0x6adb, 0xfa => 0x91e7, 0xfb => 0x5c51, 0xfc => 0x5c48, + }, + 0x8c => { + 0x40 => 0x6398, 0x41 => 0x7a9f, 0x42 => 0x6c93, 0x43 => 0x9774, + 0x44 => 0x8f61, 0x45 => 0x7aaa, 0x46 => 0x718a, 0x47 => 0x9688, + 0x48 => 0x7c82, 0x49 => 0x6817, 0x4a => 0x7e70, 0x4b => 0x6851, + 0x4c => 0x936c, 0x4d => 0x52f2, 0x4e => 0x541b, 0x4f => 0x85ab, + 0x50 => 0x8a13, 0x51 => 0x7fa4, 0x52 => 0x8ecd, 0x53 => 0x90e1, + 0x54 => 0x5366, 0x55 => 0x8888, 0x56 => 0x7941, 0x57 => 0x4fc2, + 0x58 => 0x50be, 0x59 => 0x5211, 0x5a => 0x5144, 0x5b => 0x5553, + 0x5c => 0x572d, 0x5d => 0x73ea, 0x5e => 0x578b, 0x5f => 0x5951, + 0x60 => 0x5f62, 0x61 => 0x5f84, 0x62 => 0x6075, 0x63 => 0x6176, + 0x64 => 0x6167, 0x65 => 0x61a9, 0x66 => 0x63b2, 0x67 => 0x643a, + 0x68 => 0x656c, 0x69 => 0x666f, 0x6a => 0x6842, 0x6b => 0x6e13, + 0x6c => 0x7566, 0x6d => 0x7a3d, 0x6e => 0x7cfb, 0x6f => 0x7d4c, + 0x70 => 0x7d99, 0x71 => 0x7e4b, 0x72 => 0x7f6b, 0x73 => 0x830e, + 0x74 => 0x834a, 0x75 => 0x86cd, 0x76 => 0x8a08, 0x77 => 0x8a63, + 0x78 => 0x8b66, 0x79 => 0x8efd, 0x7a => 0x981a, 0x7b => 0x9d8f, + 0x7c => 0x82b8, 0x7d => 0x8fce, 0x7e => 0x9be8, 0x80 => 0x5287, + 0x81 => 0x621f, 0x82 => 0x6483, 0x83 => 0x6fc0, 0x84 => 0x9699, + 0x85 => 0x6841, 0x86 => 0x5091, 0x87 => 0x6b20, 0x88 => 0x6c7a, + 0x89 => 0x6f54, 0x8a => 0x7a74, 0x8b => 0x7d50, 0x8c => 0x8840, + 0x8d => 0x8a23, 0x8e => 0x6708, 0x8f => 0x4ef6, 0x90 => 0x5039, + 0x91 => 0x5026, 0x92 => 0x5065, 0x93 => 0x517c, 0x94 => 0x5238, + 0x95 => 0x5263, 0x96 => 0x55a7, 0x97 => 0x570f, 0x98 => 0x5805, + 0x99 => 0x5acc, 0x9a => 0x5efa, 0x9b => 0x61b2, 0x9c => 0x61f8, + 0x9d => 0x62f3, 0x9e => 0x6372, 0x9f => 0x691c, 0xa0 => 0x6a29, + 0xa1 => 0x727d, 0xa2 => 0x72ac, 0xa3 => 0x732e, 0xa4 => 0x7814, + 0xa5 => 0x786f, 0xa6 => 0x7d79, 0xa7 => 0x770c, 0xa8 => 0x80a9, + 0xa9 => 0x898b, 0xaa => 0x8b19, 0xab => 0x8ce2, 0xac => 0x8ed2, + 0xad => 0x9063, 0xae => 0x9375, 0xaf => 0x967a, 0xb0 => 0x9855, + 0xb1 => 0x9a13, 0xb2 => 0x9e78, 0xb3 => 0x5143, 0xb4 => 0x539f, + 0xb5 => 0x53b3, 0xb6 => 0x5e7b, 0xb7 => 0x5f26, 0xb8 => 0x6e1b, + 0xb9 => 0x6e90, 0xba => 0x7384, 0xbb => 0x73fe, 0xbc => 0x7d43, + 0xbd => 0x8237, 0xbe => 0x8a00, 0xbf => 0x8afa, 0xc0 => 0x9650, + 0xc1 => 0x4e4e, 0xc2 => 0x500b, 0xc3 => 0x53e4, 0xc4 => 0x547c, + 0xc5 => 0x56fa, 0xc6 => 0x59d1, 0xc7 => 0x5b64, 0xc8 => 0x5df1, + 0xc9 => 0x5eab, 0xca => 0x5f27, 0xcb => 0x6238, 0xcc => 0x6545, + 0xcd => 0x67af, 0xce => 0x6e56, 0xcf => 0x72d0, 0xd0 => 0x7cca, + 0xd1 => 0x88b4, 0xd2 => 0x80a1, 0xd3 => 0x80e1, 0xd4 => 0x83f0, + 0xd5 => 0x864e, 0xd6 => 0x8a87, 0xd7 => 0x8de8, 0xd8 => 0x9237, + 0xd9 => 0x96c7, 0xda => 0x9867, 0xdb => 0x9f13, 0xdc => 0x4e94, + 0xdd => 0x4e92, 0xde => 0x4f0d, 0xdf => 0x5348, 0xe0 => 0x5449, + 0xe1 => 0x543e, 0xe2 => 0x5a2f, 0xe3 => 0x5f8c, 0xe4 => 0x5fa1, + 0xe5 => 0x609f, 0xe6 => 0x68a7, 0xe7 => 0x6a8e, 0xe8 => 0x745a, + 0xe9 => 0x7881, 0xea => 0x8a9e, 0xeb => 0x8aa4, 0xec => 0x8b77, + 0xed => 0x9190, 0xee => 0x4e5e, 0xef => 0x9bc9, 0xf0 => 0x4ea4, + 0xf1 => 0x4f7c, 0xf2 => 0x4faf, 0xf3 => 0x5019, 0xf4 => 0x5016, + 0xf5 => 0x5149, 0xf6 => 0x516c, 0xf7 => 0x529f, 0xf8 => 0x52b9, + 0xf9 => 0x52fe, 0xfa => 0x539a, 0xfb => 0x53e3, 0xfc => 0x5411, + }, + 0x8d => { + 0x40 => 0x540e, 0x41 => 0x5589, 0x42 => 0x5751, 0x43 => 0x57a2, + 0x44 => 0x597d, 0x45 => 0x5b54, 0x46 => 0x5b5d, 0x47 => 0x5b8f, + 0x48 => 0x5de5, 0x49 => 0x5de7, 0x4a => 0x5df7, 0x4b => 0x5e78, + 0x4c => 0x5e83, 0x4d => 0x5e9a, 0x4e => 0x5eb7, 0x4f => 0x5f18, + 0x50 => 0x6052, 0x51 => 0x614c, 0x52 => 0x6297, 0x53 => 0x62d8, + 0x54 => 0x63a7, 0x55 => 0x653b, 0x56 => 0x6602, 0x57 => 0x6643, + 0x58 => 0x66f4, 0x59 => 0x676d, 0x5a => 0x6821, 0x5b => 0x6897, + 0x5c => 0x69cb, 0x5d => 0x6c5f, 0x5e => 0x6d2a, 0x5f => 0x6d69, + 0x60 => 0x6e2f, 0x61 => 0x6e9d, 0x62 => 0x7532, 0x63 => 0x7687, + 0x64 => 0x786c, 0x65 => 0x7a3f, 0x66 => 0x7ce0, 0x67 => 0x7d05, + 0x68 => 0x7d18, 0x69 => 0x7d5e, 0x6a => 0x7db1, 0x6b => 0x8015, + 0x6c => 0x8003, 0x6d => 0x80af, 0x6e => 0x80b1, 0x6f => 0x8154, + 0x70 => 0x818f, 0x71 => 0x822a, 0x72 => 0x8352, 0x73 => 0x884c, + 0x74 => 0x8861, 0x75 => 0x8b1b, 0x76 => 0x8ca2, 0x77 => 0x8cfc, + 0x78 => 0x90ca, 0x79 => 0x9175, 0x7a => 0x9271, 0x7b => 0x783f, + 0x7c => 0x92fc, 0x7d => 0x95a4, 0x7e => 0x964d, 0x80 => 0x9805, + 0x81 => 0x9999, 0x82 => 0x9ad8, 0x83 => 0x9d3b, 0x84 => 0x525b, + 0x85 => 0x52ab, 0x86 => 0x53f7, 0x87 => 0x5408, 0x88 => 0x58d5, + 0x89 => 0x62f7, 0x8a => 0x6fe0, 0x8b => 0x8c6a, 0x8c => 0x8f5f, + 0x8d => 0x9eb9, 0x8e => 0x514b, 0x8f => 0x523b, 0x90 => 0x544a, + 0x91 => 0x56fd, 0x92 => 0x7a40, 0x93 => 0x9177, 0x94 => 0x9d60, + 0x95 => 0x9ed2, 0x96 => 0x7344, 0x97 => 0x6f09, 0x98 => 0x8170, + 0x99 => 0x7511, 0x9a => 0x5ffd, 0x9b => 0x60da, 0x9c => 0x9aa8, + 0x9d => 0x72db, 0x9e => 0x8fbc, 0x9f => 0x6b64, 0xa0 => 0x9803, + 0xa1 => 0x4eca, 0xa2 => 0x56f0, 0xa3 => 0x5764, 0xa4 => 0x58be, + 0xa5 => 0x5a5a, 0xa6 => 0x6068, 0xa7 => 0x61c7, 0xa8 => 0x660f, + 0xa9 => 0x6606, 0xaa => 0x6839, 0xab => 0x68b1, 0xac => 0x6df7, + 0xad => 0x75d5, 0xae => 0x7d3a, 0xaf => 0x826e, 0xb0 => 0x9b42, + 0xb1 => 0x4e9b, 0xb2 => 0x4f50, 0xb3 => 0x53c9, 0xb4 => 0x5506, + 0xb5 => 0x5d6f, 0xb6 => 0x5de6, 0xb7 => 0x5dee, 0xb8 => 0x67fb, + 0xb9 => 0x6c99, 0xba => 0x7473, 0xbb => 0x7802, 0xbc => 0x8a50, + 0xbd => 0x9396, 0xbe => 0x88df, 0xbf => 0x5750, 0xc0 => 0x5ea7, + 0xc1 => 0x632b, 0xc2 => 0x50b5, 0xc3 => 0x50ac, 0xc4 => 0x518d, + 0xc5 => 0x6700, 0xc6 => 0x54c9, 0xc7 => 0x585e, 0xc8 => 0x59bb, + 0xc9 => 0x5bb0, 0xca => 0x5f69, 0xcb => 0x624d, 0xcc => 0x63a1, + 0xcd => 0x683d, 0xce => 0x6b73, 0xcf => 0x6e08, 0xd0 => 0x707d, + 0xd1 => 0x91c7, 0xd2 => 0x7280, 0xd3 => 0x7815, 0xd4 => 0x7826, + 0xd5 => 0x796d, 0xd6 => 0x658e, 0xd7 => 0x7d30, 0xd8 => 0x83dc, + 0xd9 => 0x88c1, 0xda => 0x8f09, 0xdb => 0x969b, 0xdc => 0x5264, + 0xdd => 0x5728, 0xde => 0x6750, 0xdf => 0x7f6a, 0xe0 => 0x8ca1, + 0xe1 => 0x51b4, 0xe2 => 0x5742, 0xe3 => 0x962a, 0xe4 => 0x583a, + 0xe5 => 0x698a, 0xe6 => 0x80b4, 0xe7 => 0x54b2, 0xe8 => 0x5d0e, + 0xe9 => 0x57fc, 0xea => 0x7895, 0xeb => 0x9dfa, 0xec => 0x4f5c, + 0xed => 0x524a, 0xee => 0x548b, 0xef => 0x643e, 0xf0 => 0x6628, + 0xf1 => 0x6714, 0xf2 => 0x67f5, 0xf3 => 0x7a84, 0xf4 => 0x7b56, + 0xf5 => 0x7d22, 0xf6 => 0x932f, 0xf7 => 0x685c, 0xf8 => 0x9bad, + 0xf9 => 0x7b39, 0xfa => 0x5319, 0xfb => 0x518a, 0xfc => 0x5237, + }, + 0x8e => { + 0x40 => 0x5bdf, 0x41 => 0x62f6, 0x42 => 0x64ae, 0x43 => 0x64e6, + 0x44 => 0x672d, 0x45 => 0x6bba, 0x46 => 0x85a9, 0x47 => 0x96d1, + 0x48 => 0x7690, 0x49 => 0x9bd6, 0x4a => 0x634c, 0x4b => 0x9306, + 0x4c => 0x9bab, 0x4d => 0x76bf, 0x4e => 0x6652, 0x4f => 0x4e09, + 0x50 => 0x5098, 0x51 => 0x53c2, 0x52 => 0x5c71, 0x53 => 0x60e8, + 0x54 => 0x6492, 0x55 => 0x6563, 0x56 => 0x685f, 0x57 => 0x71e6, + 0x58 => 0x73ca, 0x59 => 0x7523, 0x5a => 0x7b97, 0x5b => 0x7e82, + 0x5c => 0x8695, 0x5d => 0x8b83, 0x5e => 0x8cdb, 0x5f => 0x9178, + 0x60 => 0x9910, 0x61 => 0x65ac, 0x62 => 0x66ab, 0x63 => 0x6b8b, + 0x64 => 0x4ed5, 0x65 => 0x4ed4, 0x66 => 0x4f3a, 0x67 => 0x4f7f, + 0x68 => 0x523a, 0x69 => 0x53f8, 0x6a => 0x53f2, 0x6b => 0x55e3, + 0x6c => 0x56db, 0x6d => 0x58eb, 0x6e => 0x59cb, 0x6f => 0x59c9, + 0x70 => 0x59ff, 0x71 => 0x5b50, 0x72 => 0x5c4d, 0x73 => 0x5e02, + 0x74 => 0x5e2b, 0x75 => 0x5fd7, 0x76 => 0x601d, 0x77 => 0x6307, + 0x78 => 0x652f, 0x79 => 0x5b5c, 0x7a => 0x65af, 0x7b => 0x65bd, + 0x7c => 0x65e8, 0x7d => 0x679d, 0x7e => 0x6b62, 0x80 => 0x6b7b, + 0x81 => 0x6c0f, 0x82 => 0x7345, 0x83 => 0x7949, 0x84 => 0x79c1, + 0x85 => 0x7cf8, 0x86 => 0x7d19, 0x87 => 0x7d2b, 0x88 => 0x80a2, + 0x89 => 0x8102, 0x8a => 0x81f3, 0x8b => 0x8996, 0x8c => 0x8a5e, + 0x8d => 0x8a69, 0x8e => 0x8a66, 0x8f => 0x8a8c, 0x90 => 0x8aee, + 0x91 => 0x8cc7, 0x92 => 0x8cdc, 0x93 => 0x96cc, 0x94 => 0x98fc, + 0x95 => 0x6b6f, 0x96 => 0x4e8b, 0x97 => 0x4f3c, 0x98 => 0x4f8d, + 0x99 => 0x5150, 0x9a => 0x5b57, 0x9b => 0x5bfa, 0x9c => 0x6148, + 0x9d => 0x6301, 0x9e => 0x6642, 0x9f => 0x6b21, 0xa0 => 0x6ecb, + 0xa1 => 0x6cbb, 0xa2 => 0x723e, 0xa3 => 0x74bd, 0xa4 => 0x75d4, + 0xa5 => 0x78c1, 0xa6 => 0x793a, 0xa7 => 0x800c, 0xa8 => 0x8033, + 0xa9 => 0x81ea, 0xaa => 0x8494, 0xab => 0x8f9e, 0xac => 0x6c50, + 0xad => 0x9e7f, 0xae => 0x5f0f, 0xaf => 0x8b58, 0xb0 => 0x9d2b, + 0xb1 => 0x7afa, 0xb2 => 0x8ef8, 0xb3 => 0x5b8d, 0xb4 => 0x96eb, + 0xb5 => 0x4e03, 0xb6 => 0x53f1, 0xb7 => 0x57f7, 0xb8 => 0x5931, + 0xb9 => 0x5ac9, 0xba => 0x5ba4, 0xbb => 0x6089, 0xbc => 0x6e7f, + 0xbd => 0x6f06, 0xbe => 0x75be, 0xbf => 0x8cea, 0xc0 => 0x5b9f, + 0xc1 => 0x8500, 0xc2 => 0x7be0, 0xc3 => 0x5072, 0xc4 => 0x67f4, + 0xc5 => 0x829d, 0xc6 => 0x5c61, 0xc7 => 0x854a, 0xc8 => 0x7e1e, + 0xc9 => 0x820e, 0xca => 0x5199, 0xcb => 0x5c04, 0xcc => 0x6368, + 0xcd => 0x8d66, 0xce => 0x659c, 0xcf => 0x716e, 0xd0 => 0x793e, + 0xd1 => 0x7d17, 0xd2 => 0x8005, 0xd3 => 0x8b1d, 0xd4 => 0x8eca, + 0xd5 => 0x906e, 0xd6 => 0x86c7, 0xd7 => 0x90aa, 0xd8 => 0x501f, + 0xd9 => 0x52fa, 0xda => 0x5c3a, 0xdb => 0x6753, 0xdc => 0x707c, + 0xdd => 0x7235, 0xde => 0x914c, 0xdf => 0x91c8, 0xe0 => 0x932b, + 0xe1 => 0x82e5, 0xe2 => 0x5bc2, 0xe3 => 0x5f31, 0xe4 => 0x60f9, + 0xe5 => 0x4e3b, 0xe6 => 0x53d6, 0xe7 => 0x5b88, 0xe8 => 0x624b, + 0xe9 => 0x6731, 0xea => 0x6b8a, 0xeb => 0x72e9, 0xec => 0x73e0, + 0xed => 0x7a2e, 0xee => 0x816b, 0xef => 0x8da3, 0xf0 => 0x9152, + 0xf1 => 0x9996, 0xf2 => 0x5112, 0xf3 => 0x53d7, 0xf4 => 0x546a, + 0xf5 => 0x5bff, 0xf6 => 0x6388, 0xf7 => 0x6a39, 0xf8 => 0x7dac, + 0xf9 => 0x9700, 0xfa => 0x56da, 0xfb => 0x53ce, 0xfc => 0x5468, + }, + 0x8f => { + 0x40 => 0x5b97, 0x41 => 0x5c31, 0x42 => 0x5dde, 0x43 => 0x4fee, + 0x44 => 0x6101, 0x45 => 0x62fe, 0x46 => 0x6d32, 0x47 => 0x79c0, + 0x48 => 0x79cb, 0x49 => 0x7d42, 0x4a => 0x7e4d, 0x4b => 0x7fd2, + 0x4c => 0x81ed, 0x4d => 0x821f, 0x4e => 0x8490, 0x4f => 0x8846, + 0x50 => 0x8972, 0x51 => 0x8b90, 0x52 => 0x8e74, 0x53 => 0x8f2f, + 0x54 => 0x9031, 0x55 => 0x914b, 0x56 => 0x916c, 0x57 => 0x96c6, + 0x58 => 0x919c, 0x59 => 0x4ec0, 0x5a => 0x4f4f, 0x5b => 0x5145, + 0x5c => 0x5341, 0x5d => 0x5f93, 0x5e => 0x620e, 0x5f => 0x67d4, + 0x60 => 0x6c41, 0x61 => 0x6e0b, 0x62 => 0x7363, 0x63 => 0x7e26, + 0x64 => 0x91cd, 0x65 => 0x9283, 0x66 => 0x53d4, 0x67 => 0x5919, + 0x68 => 0x5bbf, 0x69 => 0x6dd1, 0x6a => 0x795d, 0x6b => 0x7e2e, + 0x6c => 0x7c9b, 0x6d => 0x587e, 0x6e => 0x719f, 0x6f => 0x51fa, + 0x70 => 0x8853, 0x71 => 0x8ff0, 0x72 => 0x4fca, 0x73 => 0x5cfb, + 0x74 => 0x6625, 0x75 => 0x77ac, 0x76 => 0x7ae3, 0x77 => 0x821c, + 0x78 => 0x99ff, 0x79 => 0x51c6, 0x7a => 0x5faa, 0x7b => 0x65ec, + 0x7c => 0x696f, 0x7d => 0x6b89, 0x7e => 0x6df3, 0x80 => 0x6e96, + 0x81 => 0x6f64, 0x82 => 0x76fe, 0x83 => 0x7d14, 0x84 => 0x5de1, + 0x85 => 0x9075, 0x86 => 0x9187, 0x87 => 0x9806, 0x88 => 0x51e6, + 0x89 => 0x521d, 0x8a => 0x6240, 0x8b => 0x6691, 0x8c => 0x66d9, + 0x8d => 0x6e1a, 0x8e => 0x5eb6, 0x8f => 0x7dd2, 0x90 => 0x7f72, + 0x91 => 0x66f8, 0x92 => 0x85af, 0x93 => 0x85f7, 0x94 => 0x8af8, + 0x95 => 0x52a9, 0x96 => 0x53d9, 0x97 => 0x5973, 0x98 => 0x5e8f, + 0x99 => 0x5f90, 0x9a => 0x6055, 0x9b => 0x92e4, 0x9c => 0x9664, + 0x9d => 0x50b7, 0x9e => 0x511f, 0x9f => 0x52dd, 0xa0 => 0x5320, + 0xa1 => 0x5347, 0xa2 => 0x53ec, 0xa3 => 0x54e8, 0xa4 => 0x5546, + 0xa5 => 0x5531, 0xa6 => 0x5617, 0xa7 => 0x5968, 0xa8 => 0x59be, + 0xa9 => 0x5a3c, 0xaa => 0x5bb5, 0xab => 0x5c06, 0xac => 0x5c0f, + 0xad => 0x5c11, 0xae => 0x5c1a, 0xaf => 0x5e84, 0xb0 => 0x5e8a, + 0xb1 => 0x5ee0, 0xb2 => 0x5f70, 0xb3 => 0x627f, 0xb4 => 0x6284, + 0xb5 => 0x62db, 0xb6 => 0x638c, 0xb7 => 0x6377, 0xb8 => 0x6607, + 0xb9 => 0x660c, 0xba => 0x662d, 0xbb => 0x6676, 0xbc => 0x677e, + 0xbd => 0x68a2, 0xbe => 0x6a1f, 0xbf => 0x6a35, 0xc0 => 0x6cbc, + 0xc1 => 0x6d88, 0xc2 => 0x6e09, 0xc3 => 0x6e58, 0xc4 => 0x713c, + 0xc5 => 0x7126, 0xc6 => 0x7167, 0xc7 => 0x75c7, 0xc8 => 0x7701, + 0xc9 => 0x785d, 0xca => 0x7901, 0xcb => 0x7965, 0xcc => 0x79f0, + 0xcd => 0x7ae0, 0xce => 0x7b11, 0xcf => 0x7ca7, 0xd0 => 0x7d39, + 0xd1 => 0x8096, 0xd2 => 0x83d6, 0xd3 => 0x848b, 0xd4 => 0x8549, + 0xd5 => 0x885d, 0xd6 => 0x88f3, 0xd7 => 0x8a1f, 0xd8 => 0x8a3c, + 0xd9 => 0x8a54, 0xda => 0x8a73, 0xdb => 0x8c61, 0xdc => 0x8cde, + 0xdd => 0x91a4, 0xde => 0x9266, 0xdf => 0x937e, 0xe0 => 0x9418, + 0xe1 => 0x969c, 0xe2 => 0x9798, 0xe3 => 0x4e0a, 0xe4 => 0x4e08, + 0xe5 => 0x4e1e, 0xe6 => 0x4e57, 0xe7 => 0x5197, 0xe8 => 0x5270, + 0xe9 => 0x57ce, 0xea => 0x5834, 0xeb => 0x58cc, 0xec => 0x5b22, + 0xed => 0x5e38, 0xee => 0x60c5, 0xef => 0x64fe, 0xf0 => 0x6761, + 0xf1 => 0x6756, 0xf2 => 0x6d44, 0xf3 => 0x72b6, 0xf4 => 0x7573, + 0xf5 => 0x7a63, 0xf6 => 0x84b8, 0xf7 => 0x8b72, 0xf8 => 0x91b8, + 0xf9 => 0x9320, 0xfa => 0x5631, 0xfb => 0x57f4, 0xfc => 0x98fe, + }, + 0x90 => { + 0x40 => 0x62ed, 0x41 => 0x690d, 0x42 => 0x6b96, 0x43 => 0x71ed, + 0x44 => 0x7e54, 0x45 => 0x8077, 0x46 => 0x8272, 0x47 => 0x89e6, + 0x48 => 0x98df, 0x49 => 0x8755, 0x4a => 0x8fb1, 0x4b => 0x5c3b, + 0x4c => 0x4f38, 0x4d => 0x4fe1, 0x4e => 0x4fb5, 0x4f => 0x5507, + 0x50 => 0x5a20, 0x51 => 0x5bdd, 0x52 => 0x5be9, 0x53 => 0x5fc3, + 0x54 => 0x614e, 0x55 => 0x632f, 0x56 => 0x65b0, 0x57 => 0x664b, + 0x58 => 0x68ee, 0x59 => 0x699b, 0x5a => 0x6d78, 0x5b => 0x6df1, + 0x5c => 0x7533, 0x5d => 0x75b9, 0x5e => 0x771f, 0x5f => 0x795e, + 0x60 => 0x79e6, 0x61 => 0x7d33, 0x62 => 0x81e3, 0x63 => 0x82af, + 0x64 => 0x85aa, 0x65 => 0x89aa, 0x66 => 0x8a3a, 0x67 => 0x8eab, + 0x68 => 0x8f9b, 0x69 => 0x9032, 0x6a => 0x91dd, 0x6b => 0x9707, + 0x6c => 0x4eba, 0x6d => 0x4ec1, 0x6e => 0x5203, 0x6f => 0x5875, + 0x70 => 0x58ec, 0x71 => 0x5c0b, 0x72 => 0x751a, 0x73 => 0x5c3d, + 0x74 => 0x814e, 0x75 => 0x8a0a, 0x76 => 0x8fc5, 0x77 => 0x9663, + 0x78 => 0x976d, 0x79 => 0x7b25, 0x7a => 0x8acf, 0x7b => 0x9808, + 0x7c => 0x9162, 0x7d => 0x56f3, 0x7e => 0x53a8, 0x80 => 0x9017, + 0x81 => 0x5439, 0x82 => 0x5782, 0x83 => 0x5e25, 0x84 => 0x63a8, + 0x85 => 0x6c34, 0x86 => 0x708a, 0x87 => 0x7761, 0x88 => 0x7c8b, + 0x89 => 0x7fe0, 0x8a => 0x8870, 0x8b => 0x9042, 0x8c => 0x9154, + 0x8d => 0x9310, 0x8e => 0x9318, 0x8f => 0x968f, 0x90 => 0x745e, + 0x91 => 0x9ac4, 0x92 => 0x5d07, 0x93 => 0x5d69, 0x94 => 0x6570, + 0x95 => 0x67a2, 0x96 => 0x8da8, 0x97 => 0x96db, 0x98 => 0x636e, + 0x99 => 0x6749, 0x9a => 0x6919, 0x9b => 0x83c5, 0x9c => 0x9817, + 0x9d => 0x96c0, 0x9e => 0x88fe, 0x9f => 0x6f84, 0xa0 => 0x647a, + 0xa1 => 0x5bf8, 0xa2 => 0x4e16, 0xa3 => 0x702c, 0xa4 => 0x755d, + 0xa5 => 0x662f, 0xa6 => 0x51c4, 0xa7 => 0x5236, 0xa8 => 0x52e2, + 0xa9 => 0x59d3, 0xaa => 0x5f81, 0xab => 0x6027, 0xac => 0x6210, + 0xad => 0x653f, 0xae => 0x6574, 0xaf => 0x661f, 0xb0 => 0x6674, + 0xb1 => 0x68f2, 0xb2 => 0x6816, 0xb3 => 0x6b63, 0xb4 => 0x6e05, + 0xb5 => 0x7272, 0xb6 => 0x751f, 0xb7 => 0x76db, 0xb8 => 0x7cbe, + 0xb9 => 0x8056, 0xba => 0x58f0, 0xbb => 0x88fd, 0xbc => 0x897f, + 0xbd => 0x8aa0, 0xbe => 0x8a93, 0xbf => 0x8acb, 0xc0 => 0x901d, + 0xc1 => 0x9192, 0xc2 => 0x9752, 0xc3 => 0x9759, 0xc4 => 0x6589, + 0xc5 => 0x7a0e, 0xc6 => 0x8106, 0xc7 => 0x96bb, 0xc8 => 0x5e2d, + 0xc9 => 0x60dc, 0xca => 0x621a, 0xcb => 0x65a5, 0xcc => 0x6614, + 0xcd => 0x6790, 0xce => 0x77f3, 0xcf => 0x7a4d, 0xd0 => 0x7c4d, + 0xd1 => 0x7e3e, 0xd2 => 0x810a, 0xd3 => 0x8cac, 0xd4 => 0x8d64, + 0xd5 => 0x8de1, 0xd6 => 0x8e5f, 0xd7 => 0x78a9, 0xd8 => 0x5207, + 0xd9 => 0x62d9, 0xda => 0x63a5, 0xdb => 0x6442, 0xdc => 0x6298, + 0xdd => 0x8a2d, 0xde => 0x7a83, 0xdf => 0x7bc0, 0xe0 => 0x8aac, + 0xe1 => 0x96ea, 0xe2 => 0x7d76, 0xe3 => 0x820c, 0xe4 => 0x8749, + 0xe5 => 0x4ed9, 0xe6 => 0x5148, 0xe7 => 0x5343, 0xe8 => 0x5360, + 0xe9 => 0x5ba3, 0xea => 0x5c02, 0xeb => 0x5c16, 0xec => 0x5ddd, + 0xed => 0x6226, 0xee => 0x6247, 0xef => 0x64b0, 0xf0 => 0x6813, + 0xf1 => 0x6834, 0xf2 => 0x6cc9, 0xf3 => 0x6d45, 0xf4 => 0x6d17, + 0xf5 => 0x67d3, 0xf6 => 0x6f5c, 0xf7 => 0x714e, 0xf8 => 0x717d, + 0xf9 => 0x65cb, 0xfa => 0x7a7f, 0xfb => 0x7bad, 0xfc => 0x7dda, + }, + 0x91 => { + 0x40 => 0x7e4a, 0x41 => 0x7fa8, 0x42 => 0x817a, 0x43 => 0x821b, + 0x44 => 0x8239, 0x45 => 0x85a6, 0x46 => 0x8a6e, 0x47 => 0x8cce, + 0x48 => 0x8df5, 0x49 => 0x9078, 0x4a => 0x9077, 0x4b => 0x92ad, + 0x4c => 0x9291, 0x4d => 0x9583, 0x4e => 0x9bae, 0x4f => 0x524d, + 0x50 => 0x5584, 0x51 => 0x6f38, 0x52 => 0x7136, 0x53 => 0x5168, + 0x54 => 0x7985, 0x55 => 0x7e55, 0x56 => 0x81b3, 0x57 => 0x7cce, + 0x58 => 0x564c, 0x59 => 0x5851, 0x5a => 0x5ca8, 0x5b => 0x63aa, + 0x5c => 0x66fe, 0x5d => 0x66fd, 0x5e => 0x695a, 0x5f => 0x72d9, + 0x60 => 0x758f, 0x61 => 0x758e, 0x62 => 0x790e, 0x63 => 0x7956, + 0x64 => 0x79df, 0x65 => 0x7c97, 0x66 => 0x7d20, 0x67 => 0x7d44, + 0x68 => 0x8607, 0x69 => 0x8a34, 0x6a => 0x963b, 0x6b => 0x9061, + 0x6c => 0x9f20, 0x6d => 0x50e7, 0x6e => 0x5275, 0x6f => 0x53cc, + 0x70 => 0x53e2, 0x71 => 0x5009, 0x72 => 0x55aa, 0x73 => 0x58ee, + 0x74 => 0x594f, 0x75 => 0x723d, 0x76 => 0x5b8b, 0x77 => 0x5c64, + 0x78 => 0x531d, 0x79 => 0x60e3, 0x7a => 0x60f3, 0x7b => 0x635c, + 0x7c => 0x6383, 0x7d => 0x633f, 0x7e => 0x63bb, 0x80 => 0x64cd, + 0x81 => 0x65e9, 0x82 => 0x66f9, 0x83 => 0x5de3, 0x84 => 0x69cd, + 0x85 => 0x69fd, 0x86 => 0x6f15, 0x87 => 0x71e5, 0x88 => 0x4e89, + 0x89 => 0x75e9, 0x8a => 0x76f8, 0x8b => 0x7a93, 0x8c => 0x7cdf, + 0x8d => 0x7dcf, 0x8e => 0x7d9c, 0x8f => 0x8061, 0x90 => 0x8349, + 0x91 => 0x8358, 0x92 => 0x846c, 0x93 => 0x84bc, 0x94 => 0x85fb, + 0x95 => 0x88c5, 0x96 => 0x8d70, 0x97 => 0x9001, 0x98 => 0x906d, + 0x99 => 0x9397, 0x9a => 0x971c, 0x9b => 0x9a12, 0x9c => 0x50cf, + 0x9d => 0x5897, 0x9e => 0x618e, 0x9f => 0x81d3, 0xa0 => 0x8535, + 0xa1 => 0x8d08, 0xa2 => 0x9020, 0xa3 => 0x4fc3, 0xa4 => 0x5074, + 0xa5 => 0x5247, 0xa6 => 0x5373, 0xa7 => 0x606f, 0xa8 => 0x6349, + 0xa9 => 0x675f, 0xaa => 0x6e2c, 0xab => 0x8db3, 0xac => 0x901f, + 0xad => 0x4fd7, 0xae => 0x5c5e, 0xaf => 0x8cca, 0xb0 => 0x65cf, + 0xb1 => 0x7d9a, 0xb2 => 0x5352, 0xb3 => 0x8896, 0xb4 => 0x5176, + 0xb5 => 0x63c3, 0xb6 => 0x5b58, 0xb7 => 0x5b6b, 0xb8 => 0x5c0a, + 0xb9 => 0x640d, 0xba => 0x6751, 0xbb => 0x905c, 0xbc => 0x4ed6, + 0xbd => 0x591a, 0xbe => 0x592a, 0xbf => 0x6c70, 0xc0 => 0x8a51, + 0xc1 => 0x553e, 0xc2 => 0x5815, 0xc3 => 0x59a5, 0xc4 => 0x60f0, + 0xc5 => 0x6253, 0xc6 => 0x67c1, 0xc7 => 0x8235, 0xc8 => 0x6955, + 0xc9 => 0x9640, 0xca => 0x99c4, 0xcb => 0x9a28, 0xcc => 0x4f53, + 0xcd => 0x5806, 0xce => 0x5bfe, 0xcf => 0x8010, 0xd0 => 0x5cb1, + 0xd1 => 0x5e2f, 0xd2 => 0x5f85, 0xd3 => 0x6020, 0xd4 => 0x614b, + 0xd5 => 0x6234, 0xd6 => 0x66ff, 0xd7 => 0x6cf0, 0xd8 => 0x6ede, + 0xd9 => 0x80ce, 0xda => 0x817f, 0xdb => 0x82d4, 0xdc => 0x888b, + 0xdd => 0x8cb8, 0xde => 0x9000, 0xdf => 0x902e, 0xe0 => 0x968a, + 0xe1 => 0x9edb, 0xe2 => 0x9bdb, 0xe3 => 0x4ee3, 0xe4 => 0x53f0, + 0xe5 => 0x5927, 0xe6 => 0x7b2c, 0xe7 => 0x918d, 0xe8 => 0x984c, + 0xe9 => 0x9df9, 0xea => 0x6edd, 0xeb => 0x7027, 0xec => 0x5353, + 0xed => 0x5544, 0xee => 0x5b85, 0xef => 0x6258, 0xf0 => 0x629e, + 0xf1 => 0x62d3, 0xf2 => 0x6ca2, 0xf3 => 0x6fef, 0xf4 => 0x7422, + 0xf5 => 0x8a17, 0xf6 => 0x9438, 0xf7 => 0x6fc1, 0xf8 => 0x8afe, + 0xf9 => 0x8338, 0xfa => 0x51e7, 0xfb => 0x86f8, 0xfc => 0x53ea, + }, + 0x92 => { + 0x40 => 0x53e9, 0x41 => 0x4f46, 0x42 => 0x9054, 0x43 => 0x8fb0, + 0x44 => 0x596a, 0x45 => 0x8131, 0x46 => 0x5dfd, 0x47 => 0x7aea, + 0x48 => 0x8fbf, 0x49 => 0x68da, 0x4a => 0x8c37, 0x4b => 0x72f8, + 0x4c => 0x9c48, 0x4d => 0x6a3d, 0x4e => 0x8ab0, 0x4f => 0x4e39, + 0x50 => 0x5358, 0x51 => 0x5606, 0x52 => 0x5766, 0x53 => 0x62c5, + 0x54 => 0x63a2, 0x55 => 0x65e6, 0x56 => 0x6b4e, 0x57 => 0x6de1, + 0x58 => 0x6e5b, 0x59 => 0x70ad, 0x5a => 0x77ed, 0x5b => 0x7aef, + 0x5c => 0x7baa, 0x5d => 0x7dbb, 0x5e => 0x803d, 0x5f => 0x80c6, + 0x60 => 0x86cb, 0x61 => 0x8a95, 0x62 => 0x935b, 0x63 => 0x56e3, + 0x64 => 0x58c7, 0x65 => 0x5f3e, 0x66 => 0x65ad, 0x67 => 0x6696, + 0x68 => 0x6a80, 0x69 => 0x6bb5, 0x6a => 0x7537, 0x6b => 0x8ac7, + 0x6c => 0x5024, 0x6d => 0x77e5, 0x6e => 0x5730, 0x6f => 0x5f1b, + 0x70 => 0x6065, 0x71 => 0x667a, 0x72 => 0x6c60, 0x73 => 0x75f4, + 0x74 => 0x7a1a, 0x75 => 0x7f6e, 0x76 => 0x81f4, 0x77 => 0x8718, + 0x78 => 0x9045, 0x79 => 0x99b3, 0x7a => 0x7bc9, 0x7b => 0x755c, + 0x7c => 0x7af9, 0x7d => 0x7b51, 0x7e => 0x84c4, 0x80 => 0x9010, + 0x81 => 0x79e9, 0x82 => 0x7a92, 0x83 => 0x8336, 0x84 => 0x5ae1, + 0x85 => 0x7740, 0x86 => 0x4e2d, 0x87 => 0x4ef2, 0x88 => 0x5b99, + 0x89 => 0x5fe0, 0x8a => 0x62bd, 0x8b => 0x663c, 0x8c => 0x67f1, + 0x8d => 0x6ce8, 0x8e => 0x866b, 0x8f => 0x8877, 0x90 => 0x8a3b, + 0x91 => 0x914e, 0x92 => 0x92f3, 0x93 => 0x99d0, 0x94 => 0x6a17, + 0x95 => 0x7026, 0x96 => 0x732a, 0x97 => 0x82e7, 0x98 => 0x8457, + 0x99 => 0x8caf, 0x9a => 0x4e01, 0x9b => 0x5146, 0x9c => 0x51cb, + 0x9d => 0x558b, 0x9e => 0x5bf5, 0x9f => 0x5e16, 0xa0 => 0x5e33, + 0xa1 => 0x5e81, 0xa2 => 0x5f14, 0xa3 => 0x5f35, 0xa4 => 0x5f6b, + 0xa5 => 0x5fb4, 0xa6 => 0x61f2, 0xa7 => 0x6311, 0xa8 => 0x66a2, + 0xa9 => 0x671d, 0xaa => 0x6f6e, 0xab => 0x7252, 0xac => 0x753a, + 0xad => 0x773a, 0xae => 0x8074, 0xaf => 0x8139, 0xb0 => 0x8178, + 0xb1 => 0x8776, 0xb2 => 0x8abf, 0xb3 => 0x8adc, 0xb4 => 0x8d85, + 0xb5 => 0x8df3, 0xb6 => 0x929a, 0xb7 => 0x9577, 0xb8 => 0x9802, + 0xb9 => 0x9ce5, 0xba => 0x52c5, 0xbb => 0x6357, 0xbc => 0x76f4, + 0xbd => 0x6715, 0xbe => 0x6c88, 0xbf => 0x73cd, 0xc0 => 0x8cc3, + 0xc1 => 0x93ae, 0xc2 => 0x9673, 0xc3 => 0x6d25, 0xc4 => 0x589c, + 0xc5 => 0x690e, 0xc6 => 0x69cc, 0xc7 => 0x8ffd, 0xc8 => 0x939a, + 0xc9 => 0x75db, 0xca => 0x901a, 0xcb => 0x585a, 0xcc => 0x6802, + 0xcd => 0x63b4, 0xce => 0x69fb, 0xcf => 0x4f43, 0xd0 => 0x6f2c, + 0xd1 => 0x67d8, 0xd2 => 0x8fbb, 0xd3 => 0x8526, 0xd4 => 0x7db4, + 0xd5 => 0x9354, 0xd6 => 0x693f, 0xd7 => 0x6f70, 0xd8 => 0x576a, + 0xd9 => 0x58f7, 0xda => 0x5b2c, 0xdb => 0x7d2c, 0xdc => 0x722a, + 0xdd => 0x540a, 0xde => 0x91e3, 0xdf => 0x9db4, 0xe0 => 0x4ead, + 0xe1 => 0x4f4e, 0xe2 => 0x505c, 0xe3 => 0x5075, 0xe4 => 0x5243, + 0xe5 => 0x8c9e, 0xe6 => 0x5448, 0xe7 => 0x5824, 0xe8 => 0x5b9a, + 0xe9 => 0x5e1d, 0xea => 0x5e95, 0xeb => 0x5ead, 0xec => 0x5ef7, + 0xed => 0x5f1f, 0xee => 0x608c, 0xef => 0x62b5, 0xf0 => 0x633a, + 0xf1 => 0x63d0, 0xf2 => 0x68af, 0xf3 => 0x6c40, 0xf4 => 0x7887, + 0xf5 => 0x798e, 0xf6 => 0x7a0b, 0xf7 => 0x7de0, 0xf8 => 0x8247, + 0xf9 => 0x8a02, 0xfa => 0x8ae6, 0xfb => 0x8e44, 0xfc => 0x9013, + }, + 0x93 => { + 0x40 => 0x90b8, 0x41 => 0x912d, 0x42 => 0x91d8, 0x43 => 0x9f0e, + 0x44 => 0x6ce5, 0x45 => 0x6458, 0x46 => 0x64e2, 0x47 => 0x6575, + 0x48 => 0x6ef4, 0x49 => 0x7684, 0x4a => 0x7b1b, 0x4b => 0x9069, + 0x4c => 0x93d1, 0x4d => 0x6eba, 0x4e => 0x54f2, 0x4f => 0x5fb9, + 0x50 => 0x64a4, 0x51 => 0x8f4d, 0x52 => 0x8fed, 0x53 => 0x9244, + 0x54 => 0x5178, 0x55 => 0x586b, 0x56 => 0x5929, 0x57 => 0x5c55, + 0x58 => 0x5e97, 0x59 => 0x6dfb, 0x5a => 0x7e8f, 0x5b => 0x751c, + 0x5c => 0x8cbc, 0x5d => 0x8ee2, 0x5e => 0x985b, 0x5f => 0x70b9, + 0x60 => 0x4f1d, 0x61 => 0x6bbf, 0x62 => 0x6fb1, 0x63 => 0x7530, + 0x64 => 0x96fb, 0x65 => 0x514e, 0x66 => 0x5410, 0x67 => 0x5835, + 0x68 => 0x5857, 0x69 => 0x59ac, 0x6a => 0x5c60, 0x6b => 0x5f92, + 0x6c => 0x6597, 0x6d => 0x675c, 0x6e => 0x6e21, 0x6f => 0x767b, + 0x70 => 0x83df, 0x71 => 0x8ced, 0x72 => 0x9014, 0x73 => 0x90fd, + 0x74 => 0x934d, 0x75 => 0x7825, 0x76 => 0x783a, 0x77 => 0x52aa, + 0x78 => 0x5ea6, 0x79 => 0x571f, 0x7a => 0x5974, 0x7b => 0x6012, + 0x7c => 0x5012, 0x7d => 0x515a, 0x7e => 0x51ac, 0x80 => 0x51cd, + 0x81 => 0x5200, 0x82 => 0x5510, 0x83 => 0x5854, 0x84 => 0x5858, + 0x85 => 0x5957, 0x86 => 0x5b95, 0x87 => 0x5cf6, 0x88 => 0x5d8b, + 0x89 => 0x60bc, 0x8a => 0x6295, 0x8b => 0x642d, 0x8c => 0x6771, + 0x8d => 0x6843, 0x8e => 0x68bc, 0x8f => 0x68df, 0x90 => 0x76d7, + 0x91 => 0x6dd8, 0x92 => 0x6e6f, 0x93 => 0x6d9b, 0x94 => 0x706f, + 0x95 => 0x71c8, 0x96 => 0x5f53, 0x97 => 0x75d8, 0x98 => 0x7977, + 0x99 => 0x7b49, 0x9a => 0x7b54, 0x9b => 0x7b52, 0x9c => 0x7cd6, + 0x9d => 0x7d71, 0x9e => 0x5230, 0x9f => 0x8463, 0xa0 => 0x8569, + 0xa1 => 0x85e4, 0xa2 => 0x8a0e, 0xa3 => 0x8b04, 0xa4 => 0x8c46, + 0xa5 => 0x8e0f, 0xa6 => 0x9003, 0xa7 => 0x900f, 0xa8 => 0x9419, + 0xa9 => 0x9676, 0xaa => 0x982d, 0xab => 0x9a30, 0xac => 0x95d8, + 0xad => 0x50cd, 0xae => 0x52d5, 0xaf => 0x540c, 0xb0 => 0x5802, + 0xb1 => 0x5c0e, 0xb2 => 0x61a7, 0xb3 => 0x649e, 0xb4 => 0x6d1e, + 0xb5 => 0x77b3, 0xb6 => 0x7ae5, 0xb7 => 0x80f4, 0xb8 => 0x8404, + 0xb9 => 0x9053, 0xba => 0x9285, 0xbb => 0x5ce0, 0xbc => 0x9d07, + 0xbd => 0x533f, 0xbe => 0x5f97, 0xbf => 0x5fb3, 0xc0 => 0x6d9c, + 0xc1 => 0x7279, 0xc2 => 0x7763, 0xc3 => 0x79bf, 0xc4 => 0x7be4, + 0xc5 => 0x6bd2, 0xc6 => 0x72ec, 0xc7 => 0x8aad, 0xc8 => 0x6803, + 0xc9 => 0x6a61, 0xca => 0x51f8, 0xcb => 0x7a81, 0xcc => 0x6934, + 0xcd => 0x5c4a, 0xce => 0x9cf6, 0xcf => 0x82eb, 0xd0 => 0x5bc5, + 0xd1 => 0x9149, 0xd2 => 0x701e, 0xd3 => 0x5678, 0xd4 => 0x5c6f, + 0xd5 => 0x60c7, 0xd6 => 0x6566, 0xd7 => 0x6c8c, 0xd8 => 0x8c5a, + 0xd9 => 0x9041, 0xda => 0x9813, 0xdb => 0x5451, 0xdc => 0x66c7, + 0xdd => 0x920d, 0xde => 0x5948, 0xdf => 0x90a3, 0xe0 => 0x5185, + 0xe1 => 0x4e4d, 0xe2 => 0x51ea, 0xe3 => 0x8599, 0xe4 => 0x8b0e, + 0xe5 => 0x7058, 0xe6 => 0x637a, 0xe7 => 0x934b, 0xe8 => 0x6962, + 0xe9 => 0x99b4, 0xea => 0x7e04, 0xeb => 0x7577, 0xec => 0x5357, + 0xed => 0x6960, 0xee => 0x8edf, 0xef => 0x96e3, 0xf0 => 0x6c5d, + 0xf1 => 0x4e8c, 0xf2 => 0x5c3c, 0xf3 => 0x5f10, 0xf4 => 0x8fe9, + 0xf5 => 0x5302, 0xf6 => 0x8cd1, 0xf7 => 0x8089, 0xf8 => 0x8679, + 0xf9 => 0x5eff, 0xfa => 0x65e5, 0xfb => 0x4e73, 0xfc => 0x5165, + }, + 0x94 => { + 0x40 => 0x5982, 0x41 => 0x5c3f, 0x42 => 0x97ee, 0x43 => 0x4efb, + 0x44 => 0x598a, 0x45 => 0x5fcd, 0x46 => 0x8a8d, 0x47 => 0x6fe1, + 0x48 => 0x79b0, 0x49 => 0x7962, 0x4a => 0x5be7, 0x4b => 0x8471, + 0x4c => 0x732b, 0x4d => 0x71b1, 0x4e => 0x5e74, 0x4f => 0x5ff5, + 0x50 => 0x637b, 0x51 => 0x649a, 0x52 => 0x71c3, 0x53 => 0x7c98, + 0x54 => 0x4e43, 0x55 => 0x5efc, 0x56 => 0x4e4b, 0x57 => 0x57dc, + 0x58 => 0x56a2, 0x59 => 0x60a9, 0x5a => 0x6fc3, 0x5b => 0x7d0d, + 0x5c => 0x80fd, 0x5d => 0x8133, 0x5e => 0x81bf, 0x5f => 0x8fb2, + 0x60 => 0x8997, 0x61 => 0x86a4, 0x62 => 0x5df4, 0x63 => 0x628a, + 0x64 => 0x64ad, 0x65 => 0x8987, 0x66 => 0x6777, 0x67 => 0x6ce2, + 0x68 => 0x6d3e, 0x69 => 0x7436, 0x6a => 0x7834, 0x6b => 0x5a46, + 0x6c => 0x7f75, 0x6d => 0x82ad, 0x6e => 0x99ac, 0x6f => 0x4ff3, + 0x70 => 0x5ec3, 0x71 => 0x62dd, 0x72 => 0x6392, 0x73 => 0x6557, + 0x74 => 0x676f, 0x75 => 0x76c3, 0x76 => 0x724c, 0x77 => 0x80cc, + 0x78 => 0x80ba, 0x79 => 0x8f29, 0x7a => 0x914d, 0x7b => 0x500d, + 0x7c => 0x57f9, 0x7d => 0x5a92, 0x7e => 0x6885, 0x80 => 0x6973, + 0x81 => 0x7164, 0x82 => 0x72fd, 0x83 => 0x8cb7, 0x84 => 0x58f2, + 0x85 => 0x8ce0, 0x86 => 0x966a, 0x87 => 0x9019, 0x88 => 0x877f, + 0x89 => 0x79e4, 0x8a => 0x77e7, 0x8b => 0x8429, 0x8c => 0x4f2f, + 0x8d => 0x5265, 0x8e => 0x535a, 0x8f => 0x62cd, 0x90 => 0x67cf, + 0x91 => 0x6cca, 0x92 => 0x767d, 0x93 => 0x7b94, 0x94 => 0x7c95, + 0x95 => 0x8236, 0x96 => 0x8584, 0x97 => 0x8feb, 0x98 => 0x66dd, + 0x99 => 0x6f20, 0x9a => 0x7206, 0x9b => 0x7e1b, 0x9c => 0x83ab, + 0x9d => 0x99c1, 0x9e => 0x9ea6, 0x9f => 0x51fd, 0xa0 => 0x7bb1, + 0xa1 => 0x7872, 0xa2 => 0x7bb8, 0xa3 => 0x8087, 0xa4 => 0x7b48, + 0xa5 => 0x6ae8, 0xa6 => 0x5e61, 0xa7 => 0x808c, 0xa8 => 0x7551, + 0xa9 => 0x7560, 0xaa => 0x516b, 0xab => 0x9262, 0xac => 0x6e8c, + 0xad => 0x767a, 0xae => 0x9197, 0xaf => 0x9aea, 0xb0 => 0x4f10, + 0xb1 => 0x7f70, 0xb2 => 0x629c, 0xb3 => 0x7b4f, 0xb4 => 0x95a5, + 0xb5 => 0x9ce9, 0xb6 => 0x567a, 0xb7 => 0x5859, 0xb8 => 0x86e4, + 0xb9 => 0x96bc, 0xba => 0x4f34, 0xbb => 0x5224, 0xbc => 0x534a, + 0xbd => 0x53cd, 0xbe => 0x53db, 0xbf => 0x5e06, 0xc0 => 0x642c, + 0xc1 => 0x6591, 0xc2 => 0x677f, 0xc3 => 0x6c3e, 0xc4 => 0x6c4e, + 0xc5 => 0x7248, 0xc6 => 0x72af, 0xc7 => 0x73ed, 0xc8 => 0x7554, + 0xc9 => 0x7e41, 0xca => 0x822c, 0xcb => 0x85e9, 0xcc => 0x8ca9, + 0xcd => 0x7bc4, 0xce => 0x91c6, 0xcf => 0x7169, 0xd0 => 0x9812, + 0xd1 => 0x98ef, 0xd2 => 0x633d, 0xd3 => 0x6669, 0xd4 => 0x756a, + 0xd5 => 0x76e4, 0xd6 => 0x78d0, 0xd7 => 0x8543, 0xd8 => 0x86ee, + 0xd9 => 0x532a, 0xda => 0x5351, 0xdb => 0x5426, 0xdc => 0x5983, + 0xdd => 0x5e87, 0xde => 0x5f7c, 0xdf => 0x60b2, 0xe0 => 0x6249, + 0xe1 => 0x6279, 0xe2 => 0x62ab, 0xe3 => 0x6590, 0xe4 => 0x6bd4, + 0xe5 => 0x6ccc, 0xe6 => 0x75b2, 0xe7 => 0x76ae, 0xe8 => 0x7891, + 0xe9 => 0x79d8, 0xea => 0x7dcb, 0xeb => 0x7f77, 0xec => 0x80a5, + 0xed => 0x88ab, 0xee => 0x8ab9, 0xef => 0x8cbb, 0xf0 => 0x907f, + 0xf1 => 0x975e, 0xf2 => 0x98db, 0xf3 => 0x6a0b, 0xf4 => 0x7c38, + 0xf5 => 0x5099, 0xf6 => 0x5c3e, 0xf7 => 0x5fae, 0xf8 => 0x6787, + 0xf9 => 0x6bd8, 0xfa => 0x7435, 0xfb => 0x7709, 0xfc => 0x7f8e, + }, + 0x95 => { + 0x40 => 0x9f3b, 0x41 => 0x67ca, 0x42 => 0x7a17, 0x43 => 0x5339, + 0x44 => 0x758b, 0x45 => 0x9aed, 0x46 => 0x5f66, 0x47 => 0x819d, + 0x48 => 0x83f1, 0x49 => 0x8098, 0x4a => 0x5f3c, 0x4b => 0x5fc5, + 0x4c => 0x7562, 0x4d => 0x7b46, 0x4e => 0x903c, 0x4f => 0x6867, + 0x50 => 0x59eb, 0x51 => 0x5a9b, 0x52 => 0x7d10, 0x53 => 0x767e, + 0x54 => 0x8b2c, 0x55 => 0x4ff5, 0x56 => 0x5f6a, 0x57 => 0x6a19, + 0x58 => 0x6c37, 0x59 => 0x6f02, 0x5a => 0x74e2, 0x5b => 0x7968, + 0x5c => 0x8868, 0x5d => 0x8a55, 0x5e => 0x8c79, 0x5f => 0x5edf, + 0x60 => 0x63cf, 0x61 => 0x75c5, 0x62 => 0x79d2, 0x63 => 0x82d7, + 0x64 => 0x9328, 0x65 => 0x92f2, 0x66 => 0x849c, 0x67 => 0x86ed, + 0x68 => 0x9c2d, 0x69 => 0x54c1, 0x6a => 0x5f6c, 0x6b => 0x658c, + 0x6c => 0x6d5c, 0x6d => 0x7015, 0x6e => 0x8ca7, 0x6f => 0x8cd3, + 0x70 => 0x983b, 0x71 => 0x654f, 0x72 => 0x74f6, 0x73 => 0x4e0d, + 0x74 => 0x4ed8, 0x75 => 0x57e0, 0x76 => 0x592b, 0x77 => 0x5a66, + 0x78 => 0x5bcc, 0x79 => 0x51a8, 0x7a => 0x5e03, 0x7b => 0x5e9c, + 0x7c => 0x6016, 0x7d => 0x6276, 0x7e => 0x6577, 0x80 => 0x65a7, + 0x81 => 0x666e, 0x82 => 0x6d6e, 0x83 => 0x7236, 0x84 => 0x7b26, + 0x85 => 0x8150, 0x86 => 0x819a, 0x87 => 0x8299, 0x88 => 0x8b5c, + 0x89 => 0x8ca0, 0x8a => 0x8ce6, 0x8b => 0x8d74, 0x8c => 0x961c, + 0x8d => 0x9644, 0x8e => 0x4fae, 0x8f => 0x64ab, 0x90 => 0x6b66, + 0x91 => 0x821e, 0x92 => 0x8461, 0x93 => 0x856a, 0x94 => 0x90e8, + 0x95 => 0x5c01, 0x96 => 0x6953, 0x97 => 0x98a8, 0x98 => 0x847a, + 0x99 => 0x8557, 0x9a => 0x4f0f, 0x9b => 0x526f, 0x9c => 0x5fa9, + 0x9d => 0x5e45, 0x9e => 0x670d, 0x9f => 0x798f, 0xa0 => 0x8179, + 0xa1 => 0x8907, 0xa2 => 0x8986, 0xa3 => 0x6df5, 0xa4 => 0x5f17, + 0xa5 => 0x6255, 0xa6 => 0x6cb8, 0xa7 => 0x4ecf, 0xa8 => 0x7269, + 0xa9 => 0x9b92, 0xaa => 0x5206, 0xab => 0x543b, 0xac => 0x5674, + 0xad => 0x58b3, 0xae => 0x61a4, 0xaf => 0x626e, 0xb0 => 0x711a, + 0xb1 => 0x596e, 0xb2 => 0x7c89, 0xb3 => 0x7cde, 0xb4 => 0x7d1b, + 0xb5 => 0x96f0, 0xb6 => 0x6587, 0xb7 => 0x805e, 0xb8 => 0x4e19, + 0xb9 => 0x4f75, 0xba => 0x5175, 0xbb => 0x5840, 0xbc => 0x5e63, + 0xbd => 0x5e73, 0xbe => 0x5f0a, 0xbf => 0x67c4, 0xc0 => 0x4e26, + 0xc1 => 0x853d, 0xc2 => 0x9589, 0xc3 => 0x965b, 0xc4 => 0x7c73, + 0xc5 => 0x9801, 0xc6 => 0x50fb, 0xc7 => 0x58c1, 0xc8 => 0x7656, + 0xc9 => 0x78a7, 0xca => 0x5225, 0xcb => 0x77a5, 0xcc => 0x8511, + 0xcd => 0x7b86, 0xce => 0x504f, 0xcf => 0x5909, 0xd0 => 0x7247, + 0xd1 => 0x7bc7, 0xd2 => 0x7de8, 0xd3 => 0x8fba, 0xd4 => 0x8fd4, + 0xd5 => 0x904d, 0xd6 => 0x4fbf, 0xd7 => 0x52c9, 0xd8 => 0x5a29, + 0xd9 => 0x5f01, 0xda => 0x97ad, 0xdb => 0x4fdd, 0xdc => 0x8217, + 0xdd => 0x92ea, 0xde => 0x5703, 0xdf => 0x6355, 0xe0 => 0x6b69, + 0xe1 => 0x752b, 0xe2 => 0x88dc, 0xe3 => 0x8f14, 0xe4 => 0x7a42, + 0xe5 => 0x52df, 0xe6 => 0x5893, 0xe7 => 0x6155, 0xe8 => 0x620a, + 0xe9 => 0x66ae, 0xea => 0x6bcd, 0xeb => 0x7c3f, 0xec => 0x83e9, + 0xed => 0x5023, 0xee => 0x4ff8, 0xef => 0x5305, 0xf0 => 0x5446, + 0xf1 => 0x5831, 0xf2 => 0x5949, 0xf3 => 0x5b9d, 0xf4 => 0x5cf0, + 0xf5 => 0x5cef, 0xf6 => 0x5d29, 0xf7 => 0x5e96, 0xf8 => 0x62b1, + 0xf9 => 0x6367, 0xfa => 0x653e, 0xfb => 0x65b9, 0xfc => 0x670b, + }, + 0x96 => { + 0x40 => 0x6cd5, 0x41 => 0x6ce1, 0x42 => 0x70f9, 0x43 => 0x7832, + 0x44 => 0x7e2b, 0x45 => 0x80de, 0x46 => 0x82b3, 0x47 => 0x840c, + 0x48 => 0x84ec, 0x49 => 0x8702, 0x4a => 0x8912, 0x4b => 0x8a2a, + 0x4c => 0x8c4a, 0x4d => 0x90a6, 0x4e => 0x92d2, 0x4f => 0x98fd, + 0x50 => 0x9cf3, 0x51 => 0x9d6c, 0x52 => 0x4e4f, 0x53 => 0x4ea1, + 0x54 => 0x508d, 0x55 => 0x5256, 0x56 => 0x574a, 0x57 => 0x59a8, + 0x58 => 0x5e3d, 0x59 => 0x5fd8, 0x5a => 0x5fd9, 0x5b => 0x623f, + 0x5c => 0x66b4, 0x5d => 0x671b, 0x5e => 0x67d0, 0x5f => 0x68d2, + 0x60 => 0x5192, 0x61 => 0x7d21, 0x62 => 0x80aa, 0x63 => 0x81a8, + 0x64 => 0x8b00, 0x65 => 0x8c8c, 0x66 => 0x8cbf, 0x67 => 0x927e, + 0x68 => 0x9632, 0x69 => 0x5420, 0x6a => 0x982c, 0x6b => 0x5317, + 0x6c => 0x50d5, 0x6d => 0x535c, 0x6e => 0x58a8, 0x6f => 0x64b2, + 0x70 => 0x6734, 0x71 => 0x7267, 0x72 => 0x7766, 0x73 => 0x7a46, + 0x74 => 0x91e6, 0x75 => 0x52c3, 0x76 => 0x6ca1, 0x77 => 0x6b86, + 0x78 => 0x5800, 0x79 => 0x5e4c, 0x7a => 0x5954, 0x7b => 0x672c, + 0x7c => 0x7ffb, 0x7d => 0x51e1, 0x7e => 0x76c6, 0x80 => 0x6469, + 0x81 => 0x78e8, 0x82 => 0x9b54, 0x83 => 0x9ebb, 0x84 => 0x57cb, + 0x85 => 0x59b9, 0x86 => 0x6627, 0x87 => 0x679a, 0x88 => 0x6bce, + 0x89 => 0x54e9, 0x8a => 0x69d9, 0x8b => 0x5e55, 0x8c => 0x819c, + 0x8d => 0x6795, 0x8e => 0x9baa, 0x8f => 0x67fe, 0x90 => 0x9c52, + 0x91 => 0x685d, 0x92 => 0x4ea6, 0x93 => 0x4fe3, 0x94 => 0x53c8, + 0x95 => 0x62b9, 0x96 => 0x672b, 0x97 => 0x6cab, 0x98 => 0x8fc4, + 0x99 => 0x4fad, 0x9a => 0x7e6d, 0x9b => 0x9ebf, 0x9c => 0x4e07, + 0x9d => 0x6162, 0x9e => 0x6e80, 0x9f => 0x6f2b, 0xa0 => 0x8513, + 0xa1 => 0x5473, 0xa2 => 0x672a, 0xa3 => 0x9b45, 0xa4 => 0x5df3, + 0xa5 => 0x7b95, 0xa6 => 0x5cac, 0xa7 => 0x5bc6, 0xa8 => 0x871c, + 0xa9 => 0x6e4a, 0xaa => 0x84d1, 0xab => 0x7a14, 0xac => 0x8108, + 0xad => 0x5999, 0xae => 0x7c8d, 0xaf => 0x6c11, 0xb0 => 0x7720, + 0xb1 => 0x52d9, 0xb2 => 0x5922, 0xb3 => 0x7121, 0xb4 => 0x725f, + 0xb5 => 0x77db, 0xb6 => 0x9727, 0xb7 => 0x9d61, 0xb8 => 0x690b, + 0xb9 => 0x5a7f, 0xba => 0x5a18, 0xbb => 0x51a5, 0xbc => 0x540d, + 0xbd => 0x547d, 0xbe => 0x660e, 0xbf => 0x76df, 0xc0 => 0x8ff7, + 0xc1 => 0x9298, 0xc2 => 0x9cf4, 0xc3 => 0x59ea, 0xc4 => 0x725d, + 0xc5 => 0x6ec5, 0xc6 => 0x514d, 0xc7 => 0x68c9, 0xc8 => 0x7dbf, + 0xc9 => 0x7dec, 0xca => 0x9762, 0xcb => 0x9eba, 0xcc => 0x6478, + 0xcd => 0x6a21, 0xce => 0x8302, 0xcf => 0x5984, 0xd0 => 0x5b5f, + 0xd1 => 0x6bdb, 0xd2 => 0x731b, 0xd3 => 0x76f2, 0xd4 => 0x7db2, + 0xd5 => 0x8017, 0xd6 => 0x8499, 0xd7 => 0x5132, 0xd8 => 0x6728, + 0xd9 => 0x9ed9, 0xda => 0x76ee, 0xdb => 0x6762, 0xdc => 0x52ff, + 0xdd => 0x9905, 0xde => 0x5c24, 0xdf => 0x623b, 0xe0 => 0x7c7e, + 0xe1 => 0x8cb0, 0xe2 => 0x554f, 0xe3 => 0x60b6, 0xe4 => 0x7d0b, + 0xe5 => 0x9580, 0xe6 => 0x5301, 0xe7 => 0x4e5f, 0xe8 => 0x51b6, + 0xe9 => 0x591c, 0xea => 0x723a, 0xeb => 0x8036, 0xec => 0x91ce, + 0xed => 0x5f25, 0xee => 0x77e2, 0xef => 0x5384, 0xf0 => 0x5f79, + 0xf1 => 0x7d04, 0xf2 => 0x85ac, 0xf3 => 0x8a33, 0xf4 => 0x8e8d, + 0xf5 => 0x9756, 0xf6 => 0x67f3, 0xf7 => 0x85ae, 0xf8 => 0x9453, + 0xf9 => 0x6109, 0xfa => 0x6108, 0xfb => 0x6cb9, 0xfc => 0x7652, + }, + 0x97 => { + 0x40 => 0x8aed, 0x41 => 0x8f38, 0x42 => 0x552f, 0x43 => 0x4f51, + 0x44 => 0x512a, 0x45 => 0x52c7, 0x46 => 0x53cb, 0x47 => 0x5ba5, + 0x48 => 0x5e7d, 0x49 => 0x60a0, 0x4a => 0x6182, 0x4b => 0x63d6, + 0x4c => 0x6709, 0x4d => 0x67da, 0x4e => 0x6e67, 0x4f => 0x6d8c, + 0x50 => 0x7336, 0x51 => 0x7337, 0x52 => 0x7531, 0x53 => 0x7950, + 0x54 => 0x88d5, 0x55 => 0x8a98, 0x56 => 0x904a, 0x57 => 0x9091, + 0x58 => 0x90f5, 0x59 => 0x96c4, 0x5a => 0x878d, 0x5b => 0x5915, + 0x5c => 0x4e88, 0x5d => 0x4f59, 0x5e => 0x4e0e, 0x5f => 0x8a89, + 0x60 => 0x8f3f, 0x61 => 0x9810, 0x62 => 0x50ad, 0x63 => 0x5e7c, + 0x64 => 0x5996, 0x65 => 0x5bb9, 0x66 => 0x5eb8, 0x67 => 0x63da, + 0x68 => 0x63fa, 0x69 => 0x64c1, 0x6a => 0x66dc, 0x6b => 0x694a, + 0x6c => 0x69d8, 0x6d => 0x6d0b, 0x6e => 0x6eb6, 0x6f => 0x7194, + 0x70 => 0x7528, 0x71 => 0x7aaf, 0x72 => 0x7f8a, 0x73 => 0x8000, + 0x74 => 0x8449, 0x75 => 0x84c9, 0x76 => 0x8981, 0x77 => 0x8b21, + 0x78 => 0x8e0a, 0x79 => 0x9065, 0x7a => 0x967d, 0x7b => 0x990a, + 0x7c => 0x617e, 0x7d => 0x6291, 0x7e => 0x6b32, 0x80 => 0x6c83, + 0x81 => 0x6d74, 0x82 => 0x7fcc, 0x83 => 0x7ffc, 0x84 => 0x6dc0, + 0x85 => 0x7f85, 0x86 => 0x87ba, 0x87 => 0x88f8, 0x88 => 0x6765, + 0x89 => 0x83b1, 0x8a => 0x983c, 0x8b => 0x96f7, 0x8c => 0x6d1b, + 0x8d => 0x7d61, 0x8e => 0x843d, 0x8f => 0x916a, 0x90 => 0x4e71, + 0x91 => 0x5375, 0x92 => 0x5d50, 0x93 => 0x6b04, 0x94 => 0x6feb, + 0x95 => 0x85cd, 0x96 => 0x862d, 0x97 => 0x89a7, 0x98 => 0x5229, + 0x99 => 0x540f, 0x9a => 0x5c65, 0x9b => 0x674e, 0x9c => 0x68a8, + 0x9d => 0x7406, 0x9e => 0x7483, 0x9f => 0x75e2, 0xa0 => 0x88cf, + 0xa1 => 0x88e1, 0xa2 => 0x91cc, 0xa3 => 0x96e2, 0xa4 => 0x9678, + 0xa5 => 0x5f8b, 0xa6 => 0x7387, 0xa7 => 0x7acb, 0xa8 => 0x844e, + 0xa9 => 0x63a0, 0xaa => 0x7565, 0xab => 0x5289, 0xac => 0x6d41, + 0xad => 0x6e9c, 0xae => 0x7409, 0xaf => 0x7559, 0xb0 => 0x786b, + 0xb1 => 0x7c92, 0xb2 => 0x9686, 0xb3 => 0x7adc, 0xb4 => 0x9f8d, + 0xb5 => 0x4fb6, 0xb6 => 0x616e, 0xb7 => 0x65c5, 0xb8 => 0x865c, + 0xb9 => 0x4e86, 0xba => 0x4eae, 0xbb => 0x50da, 0xbc => 0x4e21, + 0xbd => 0x51cc, 0xbe => 0x5bee, 0xbf => 0x6599, 0xc0 => 0x6881, + 0xc1 => 0x6dbc, 0xc2 => 0x731f, 0xc3 => 0x7642, 0xc4 => 0x77ad, + 0xc5 => 0x7a1c, 0xc6 => 0x7ce7, 0xc7 => 0x826f, 0xc8 => 0x8ad2, + 0xc9 => 0x907c, 0xca => 0x91cf, 0xcb => 0x9675, 0xcc => 0x9818, + 0xcd => 0x529b, 0xce => 0x7dd1, 0xcf => 0x502b, 0xd0 => 0x5398, + 0xd1 => 0x6797, 0xd2 => 0x6dcb, 0xd3 => 0x71d0, 0xd4 => 0x7433, + 0xd5 => 0x81e8, 0xd6 => 0x8f2a, 0xd7 => 0x96a3, 0xd8 => 0x9c57, + 0xd9 => 0x9e9f, 0xda => 0x7460, 0xdb => 0x5841, 0xdc => 0x6d99, + 0xdd => 0x7d2f, 0xde => 0x985e, 0xdf => 0x4ee4, 0xe0 => 0x4f36, + 0xe1 => 0x4f8b, 0xe2 => 0x51b7, 0xe3 => 0x52b1, 0xe4 => 0x5dba, + 0xe5 => 0x601c, 0xe6 => 0x73b2, 0xe7 => 0x793c, 0xe8 => 0x82d3, + 0xe9 => 0x9234, 0xea => 0x96b7, 0xeb => 0x96f6, 0xec => 0x970a, + 0xed => 0x9e97, 0xee => 0x9f62, 0xef => 0x66a6, 0xf0 => 0x6b74, + 0xf1 => 0x5217, 0xf2 => 0x52a3, 0xf3 => 0x70c8, 0xf4 => 0x88c2, + 0xf5 => 0x5ec9, 0xf6 => 0x604b, 0xf7 => 0x6190, 0xf8 => 0x6f23, + 0xf9 => 0x7149, 0xfa => 0x7c3e, 0xfb => 0x7df4, 0xfc => 0x806f, + }, + 0x98 => { + 0x40 => 0x84ee, 0x41 => 0x9023, 0x42 => 0x932c, 0x43 => 0x5442, + 0x44 => 0x9b6f, 0x45 => 0x6ad3, 0x46 => 0x7089, 0x47 => 0x8cc2, + 0x48 => 0x8def, 0x49 => 0x9732, 0x4a => 0x52b4, 0x4b => 0x5a41, + 0x4c => 0x5eca, 0x4d => 0x5f04, 0x4e => 0x6717, 0x4f => 0x697c, + 0x50 => 0x6994, 0x51 => 0x6d6a, 0x52 => 0x6f0f, 0x53 => 0x7262, + 0x54 => 0x72fc, 0x55 => 0x7bed, 0x56 => 0x8001, 0x57 => 0x807e, + 0x58 => 0x874b, 0x59 => 0x90ce, 0x5a => 0x516d, 0x5b => 0x9e93, + 0x5c => 0x7984, 0x5d => 0x808b, 0x5e => 0x9332, 0x5f => 0x8ad6, + 0x60 => 0x502d, 0x61 => 0x548c, 0x62 => 0x8a71, 0x63 => 0x6b6a, + 0x64 => 0x8cc4, 0x65 => 0x8107, 0x66 => 0x60d1, 0x67 => 0x67a0, + 0x68 => 0x9df2, 0x69 => 0x4e99, 0x6a => 0x4e98, 0x6b => 0x9c10, + 0x6c => 0x8a6b, 0x6d => 0x85c1, 0x6e => 0x8568, 0x6f => 0x6900, + 0x70 => 0x6e7e, 0x71 => 0x7897, 0x72 => 0x8155, 0x9f => 0x5f0c, + 0xa0 => 0x4e10, 0xa1 => 0x4e15, 0xa2 => 0x4e2a, 0xa3 => 0x4e31, + 0xa4 => 0x4e36, 0xa5 => 0x4e3c, 0xa6 => 0x4e3f, 0xa7 => 0x4e42, + 0xa8 => 0x4e56, 0xa9 => 0x4e58, 0xaa => 0x4e82, 0xab => 0x4e85, + 0xac => 0x8c6b, 0xad => 0x4e8a, 0xae => 0x8212, 0xaf => 0x5f0d, + 0xb0 => 0x4e8e, 0xb1 => 0x4e9e, 0xb2 => 0x4e9f, 0xb3 => 0x4ea0, + 0xb4 => 0x4ea2, 0xb5 => 0x4eb0, 0xb6 => 0x4eb3, 0xb7 => 0x4eb6, + 0xb8 => 0x4ece, 0xb9 => 0x4ecd, 0xba => 0x4ec4, 0xbb => 0x4ec6, + 0xbc => 0x4ec2, 0xbd => 0x4ed7, 0xbe => 0x4ede, 0xbf => 0x4eed, + 0xc0 => 0x4edf, 0xc1 => 0x4ef7, 0xc2 => 0x4f09, 0xc3 => 0x4f5a, + 0xc4 => 0x4f30, 0xc5 => 0x4f5b, 0xc6 => 0x4f5d, 0xc7 => 0x4f57, + 0xc8 => 0x4f47, 0xc9 => 0x4f76, 0xca => 0x4f88, 0xcb => 0x4f8f, + 0xcc => 0x4f98, 0xcd => 0x4f7b, 0xce => 0x4f69, 0xcf => 0x4f70, + 0xd0 => 0x4f91, 0xd1 => 0x4f6f, 0xd2 => 0x4f86, 0xd3 => 0x4f96, + 0xd4 => 0x5118, 0xd5 => 0x4fd4, 0xd6 => 0x4fdf, 0xd7 => 0x4fce, + 0xd8 => 0x4fd8, 0xd9 => 0x4fdb, 0xda => 0x4fd1, 0xdb => 0x4fda, + 0xdc => 0x4fd0, 0xdd => 0x4fe4, 0xde => 0x4fe5, 0xdf => 0x501a, + 0xe0 => 0x5028, 0xe1 => 0x5014, 0xe2 => 0x502a, 0xe3 => 0x5025, + 0xe4 => 0x5005, 0xe5 => 0x4f1c, 0xe6 => 0x4ff6, 0xe7 => 0x5021, + 0xe8 => 0x5029, 0xe9 => 0x502c, 0xea => 0x4ffe, 0xeb => 0x4fef, + 0xec => 0x5011, 0xed => 0x5006, 0xee => 0x5043, 0xef => 0x5047, + 0xf0 => 0x6703, 0xf1 => 0x5055, 0xf2 => 0x5050, 0xf3 => 0x5048, + 0xf4 => 0x505a, 0xf5 => 0x5056, 0xf6 => 0x506c, 0xf7 => 0x5078, + 0xf8 => 0x5080, 0xf9 => 0x509a, 0xfa => 0x5085, 0xfb => 0x50b4, + 0xfc => 0x50b2, + }, + 0x99 => { + 0x40 => 0x50c9, 0x41 => 0x50ca, 0x42 => 0x50b3, 0x43 => 0x50c2, + 0x44 => 0x50d6, 0x45 => 0x50de, 0x46 => 0x50e5, 0x47 => 0x50ed, + 0x48 => 0x50e3, 0x49 => 0x50ee, 0x4a => 0x50f9, 0x4b => 0x50f5, + 0x4c => 0x5109, 0x4d => 0x5101, 0x4e => 0x5102, 0x4f => 0x5116, + 0x50 => 0x5115, 0x51 => 0x5114, 0x52 => 0x511a, 0x53 => 0x5121, + 0x54 => 0x513a, 0x55 => 0x5137, 0x56 => 0x513c, 0x57 => 0x513b, + 0x58 => 0x513f, 0x59 => 0x5140, 0x5a => 0x5152, 0x5b => 0x514c, + 0x5c => 0x5154, 0x5d => 0x5162, 0x5e => 0x7af8, 0x5f => 0x5169, + 0x60 => 0x516a, 0x61 => 0x516e, 0x62 => 0x5180, 0x63 => 0x5182, + 0x64 => 0x56d8, 0x65 => 0x518c, 0x66 => 0x5189, 0x67 => 0x518f, + 0x68 => 0x5191, 0x69 => 0x5193, 0x6a => 0x5195, 0x6b => 0x5196, + 0x6c => 0x51a4, 0x6d => 0x51a6, 0x6e => 0x51a2, 0x6f => 0x51a9, + 0x70 => 0x51aa, 0x71 => 0x51ab, 0x72 => 0x51b3, 0x73 => 0x51b1, + 0x74 => 0x51b2, 0x75 => 0x51b0, 0x76 => 0x51b5, 0x77 => 0x51bd, + 0x78 => 0x51c5, 0x79 => 0x51c9, 0x7a => 0x51db, 0x7b => 0x51e0, + 0x7c => 0x8655, 0x7d => 0x51e9, 0x7e => 0x51ed, 0x80 => 0x51f0, + 0x81 => 0x51f5, 0x82 => 0x51fe, 0x83 => 0x5204, 0x84 => 0x520b, + 0x85 => 0x5214, 0x86 => 0x520e, 0x87 => 0x5227, 0x88 => 0x522a, + 0x89 => 0x522e, 0x8a => 0x5233, 0x8b => 0x5239, 0x8c => 0x524f, + 0x8d => 0x5244, 0x8e => 0x524b, 0x8f => 0x524c, 0x90 => 0x525e, + 0x91 => 0x5254, 0x92 => 0x526a, 0x93 => 0x5274, 0x94 => 0x5269, + 0x95 => 0x5273, 0x96 => 0x527f, 0x97 => 0x527d, 0x98 => 0x528d, + 0x99 => 0x5294, 0x9a => 0x5292, 0x9b => 0x5271, 0x9c => 0x5288, + 0x9d => 0x5291, 0x9e => 0x8fa8, 0x9f => 0x8fa7, 0xa0 => 0x52ac, + 0xa1 => 0x52ad, 0xa2 => 0x52bc, 0xa3 => 0x52b5, 0xa4 => 0x52c1, + 0xa5 => 0x52cd, 0xa6 => 0x52d7, 0xa7 => 0x52de, 0xa8 => 0x52e3, + 0xa9 => 0x52e6, 0xaa => 0x98ed, 0xab => 0x52e0, 0xac => 0x52f3, + 0xad => 0x52f5, 0xae => 0x52f8, 0xaf => 0x52f9, 0xb0 => 0x5306, + 0xb1 => 0x5308, 0xb2 => 0x7538, 0xb3 => 0x530d, 0xb4 => 0x5310, + 0xb5 => 0x530f, 0xb6 => 0x5315, 0xb7 => 0x531a, 0xb8 => 0x5323, + 0xb9 => 0x532f, 0xba => 0x5331, 0xbb => 0x5333, 0xbc => 0x5338, + 0xbd => 0x5340, 0xbe => 0x5346, 0xbf => 0x5345, 0xc0 => 0x4e17, + 0xc1 => 0x5349, 0xc2 => 0x534d, 0xc3 => 0x51d6, 0xc4 => 0x535e, + 0xc5 => 0x5369, 0xc6 => 0x536e, 0xc7 => 0x5918, 0xc8 => 0x537b, + 0xc9 => 0x5377, 0xca => 0x5382, 0xcb => 0x5396, 0xcc => 0x53a0, + 0xcd => 0x53a6, 0xce => 0x53a5, 0xcf => 0x53ae, 0xd0 => 0x53b0, + 0xd1 => 0x53b6, 0xd2 => 0x53c3, 0xd3 => 0x7c12, 0xd4 => 0x96d9, + 0xd5 => 0x53df, 0xd6 => 0x66fc, 0xd7 => 0x71ee, 0xd8 => 0x53ee, + 0xd9 => 0x53e8, 0xda => 0x53ed, 0xdb => 0x53fa, 0xdc => 0x5401, + 0xdd => 0x543d, 0xde => 0x5440, 0xdf => 0x542c, 0xe0 => 0x542d, + 0xe1 => 0x543c, 0xe2 => 0x542e, 0xe3 => 0x5436, 0xe4 => 0x5429, + 0xe5 => 0x541d, 0xe6 => 0x544e, 0xe7 => 0x548f, 0xe8 => 0x5475, + 0xe9 => 0x548e, 0xea => 0x545f, 0xeb => 0x5471, 0xec => 0x5477, + 0xed => 0x5470, 0xee => 0x5492, 0xef => 0x547b, 0xf0 => 0x5480, + 0xf1 => 0x5476, 0xf2 => 0x5484, 0xf3 => 0x5490, 0xf4 => 0x5486, + 0xf5 => 0x54c7, 0xf6 => 0x54a2, 0xf7 => 0x54b8, 0xf8 => 0x54a5, + 0xf9 => 0x54ac, 0xfa => 0x54c4, 0xfb => 0x54c8, 0xfc => 0x54a8, + }, + 0x9a => { + 0x40 => 0x54ab, 0x41 => 0x54c2, 0x42 => 0x54a4, 0x43 => 0x54be, + 0x44 => 0x54bc, 0x45 => 0x54d8, 0x46 => 0x54e5, 0x47 => 0x54e6, + 0x48 => 0x550f, 0x49 => 0x5514, 0x4a => 0x54fd, 0x4b => 0x54ee, + 0x4c => 0x54ed, 0x4d => 0x54fa, 0x4e => 0x54e2, 0x4f => 0x5539, + 0x50 => 0x5540, 0x51 => 0x5563, 0x52 => 0x554c, 0x53 => 0x552e, + 0x54 => 0x555c, 0x55 => 0x5545, 0x56 => 0x5556, 0x57 => 0x5557, + 0x58 => 0x5538, 0x59 => 0x5533, 0x5a => 0x555d, 0x5b => 0x5599, + 0x5c => 0x5580, 0x5d => 0x54af, 0x5e => 0x558a, 0x5f => 0x559f, + 0x60 => 0x557b, 0x61 => 0x557e, 0x62 => 0x5598, 0x63 => 0x559e, + 0x64 => 0x55ae, 0x65 => 0x557c, 0x66 => 0x5583, 0x67 => 0x55a9, + 0x68 => 0x5587, 0x69 => 0x55a8, 0x6a => 0x55da, 0x6b => 0x55c5, + 0x6c => 0x55df, 0x6d => 0x55c4, 0x6e => 0x55dc, 0x6f => 0x55e4, + 0x70 => 0x55d4, 0x71 => 0x5614, 0x72 => 0x55f7, 0x73 => 0x5616, + 0x74 => 0x55fe, 0x75 => 0x55fd, 0x76 => 0x561b, 0x77 => 0x55f9, + 0x78 => 0x564e, 0x79 => 0x5650, 0x7a => 0x71df, 0x7b => 0x5634, + 0x7c => 0x5636, 0x7d => 0x5632, 0x7e => 0x5638, 0x80 => 0x566b, + 0x81 => 0x5664, 0x82 => 0x562f, 0x83 => 0x566c, 0x84 => 0x566a, + 0x85 => 0x5686, 0x86 => 0x5680, 0x87 => 0x568a, 0x88 => 0x56a0, + 0x89 => 0x5694, 0x8a => 0x568f, 0x8b => 0x56a5, 0x8c => 0x56ae, + 0x8d => 0x56b6, 0x8e => 0x56b4, 0x8f => 0x56c2, 0x90 => 0x56bc, + 0x91 => 0x56c1, 0x92 => 0x56c3, 0x93 => 0x56c0, 0x94 => 0x56c8, + 0x95 => 0x56ce, 0x96 => 0x56d1, 0x97 => 0x56d3, 0x98 => 0x56d7, + 0x99 => 0x56ee, 0x9a => 0x56f9, 0x9b => 0x5700, 0x9c => 0x56ff, + 0x9d => 0x5704, 0x9e => 0x5709, 0x9f => 0x5708, 0xa0 => 0x570b, + 0xa1 => 0x570d, 0xa2 => 0x5713, 0xa3 => 0x5718, 0xa4 => 0x5716, + 0xa5 => 0x55c7, 0xa6 => 0x571c, 0xa7 => 0x5726, 0xa8 => 0x5737, + 0xa9 => 0x5738, 0xaa => 0x574e, 0xab => 0x573b, 0xac => 0x5740, + 0xad => 0x574f, 0xae => 0x5769, 0xaf => 0x57c0, 0xb0 => 0x5788, + 0xb1 => 0x5761, 0xb2 => 0x577f, 0xb3 => 0x5789, 0xb4 => 0x5793, + 0xb5 => 0x57a0, 0xb6 => 0x57b3, 0xb7 => 0x57a4, 0xb8 => 0x57aa, + 0xb9 => 0x57b0, 0xba => 0x57c3, 0xbb => 0x57c6, 0xbc => 0x57d4, + 0xbd => 0x57d2, 0xbe => 0x57d3, 0xbf => 0x580a, 0xc0 => 0x57d6, + 0xc1 => 0x57e3, 0xc2 => 0x580b, 0xc3 => 0x5819, 0xc4 => 0x581d, + 0xc5 => 0x5872, 0xc6 => 0x5821, 0xc7 => 0x5862, 0xc8 => 0x584b, + 0xc9 => 0x5870, 0xca => 0x6bc0, 0xcb => 0x5852, 0xcc => 0x583d, + 0xcd => 0x5879, 0xce => 0x5885, 0xcf => 0x58b9, 0xd0 => 0x589f, + 0xd1 => 0x58ab, 0xd2 => 0x58ba, 0xd3 => 0x58de, 0xd4 => 0x58bb, + 0xd5 => 0x58b8, 0xd6 => 0x58ae, 0xd7 => 0x58c5, 0xd8 => 0x58d3, + 0xd9 => 0x58d1, 0xda => 0x58d7, 0xdb => 0x58d9, 0xdc => 0x58d8, + 0xdd => 0x58e5, 0xde => 0x58dc, 0xdf => 0x58e4, 0xe0 => 0x58df, + 0xe1 => 0x58ef, 0xe2 => 0x58fa, 0xe3 => 0x58f9, 0xe4 => 0x58fb, + 0xe5 => 0x58fc, 0xe6 => 0x58fd, 0xe7 => 0x5902, 0xe8 => 0x590a, + 0xe9 => 0x5910, 0xea => 0x591b, 0xeb => 0x68a6, 0xec => 0x5925, + 0xed => 0x592c, 0xee => 0x592d, 0xef => 0x5932, 0xf0 => 0x5938, + 0xf1 => 0x593e, 0xf2 => 0x7ad2, 0xf3 => 0x5955, 0xf4 => 0x5950, + 0xf5 => 0x594e, 0xf6 => 0x595a, 0xf7 => 0x5958, 0xf8 => 0x5962, + 0xf9 => 0x5960, 0xfa => 0x5967, 0xfb => 0x596c, 0xfc => 0x5969, + }, + 0x9b => { + 0x40 => 0x5978, 0x41 => 0x5981, 0x42 => 0x599d, 0x43 => 0x4f5e, + 0x44 => 0x4fab, 0x45 => 0x59a3, 0x46 => 0x59b2, 0x47 => 0x59c6, + 0x48 => 0x59e8, 0x49 => 0x59dc, 0x4a => 0x598d, 0x4b => 0x59d9, + 0x4c => 0x59da, 0x4d => 0x5a25, 0x4e => 0x5a1f, 0x4f => 0x5a11, + 0x50 => 0x5a1c, 0x51 => 0x5a09, 0x52 => 0x5a1a, 0x53 => 0x5a40, + 0x54 => 0x5a6c, 0x55 => 0x5a49, 0x56 => 0x5a35, 0x57 => 0x5a36, + 0x58 => 0x5a62, 0x59 => 0x5a6a, 0x5a => 0x5a9a, 0x5b => 0x5abc, + 0x5c => 0x5abe, 0x5d => 0x5acb, 0x5e => 0x5ac2, 0x5f => 0x5abd, + 0x60 => 0x5ae3, 0x61 => 0x5ad7, 0x62 => 0x5ae6, 0x63 => 0x5ae9, + 0x64 => 0x5ad6, 0x65 => 0x5afa, 0x66 => 0x5afb, 0x67 => 0x5b0c, + 0x68 => 0x5b0b, 0x69 => 0x5b16, 0x6a => 0x5b32, 0x6b => 0x5ad0, + 0x6c => 0x5b2a, 0x6d => 0x5b36, 0x6e => 0x5b3e, 0x6f => 0x5b43, + 0x70 => 0x5b45, 0x71 => 0x5b40, 0x72 => 0x5b51, 0x73 => 0x5b55, + 0x74 => 0x5b5a, 0x75 => 0x5b5b, 0x76 => 0x5b65, 0x77 => 0x5b69, + 0x78 => 0x5b70, 0x79 => 0x5b73, 0x7a => 0x5b75, 0x7b => 0x5b78, + 0x7c => 0x6588, 0x7d => 0x5b7a, 0x7e => 0x5b80, 0x80 => 0x5b83, + 0x81 => 0x5ba6, 0x82 => 0x5bb8, 0x83 => 0x5bc3, 0x84 => 0x5bc7, + 0x85 => 0x5bc9, 0x86 => 0x5bd4, 0x87 => 0x5bd0, 0x88 => 0x5be4, + 0x89 => 0x5be6, 0x8a => 0x5be2, 0x8b => 0x5bde, 0x8c => 0x5be5, + 0x8d => 0x5beb, 0x8e => 0x5bf0, 0x8f => 0x5bf6, 0x90 => 0x5bf3, + 0x91 => 0x5c05, 0x92 => 0x5c07, 0x93 => 0x5c08, 0x94 => 0x5c0d, + 0x95 => 0x5c13, 0x96 => 0x5c20, 0x97 => 0x5c22, 0x98 => 0x5c28, + 0x99 => 0x5c38, 0x9a => 0x5c39, 0x9b => 0x5c41, 0x9c => 0x5c46, + 0x9d => 0x5c4e, 0x9e => 0x5c53, 0x9f => 0x5c50, 0xa0 => 0x5c4f, + 0xa1 => 0x5b71, 0xa2 => 0x5c6c, 0xa3 => 0x5c6e, 0xa4 => 0x4e62, + 0xa5 => 0x5c76, 0xa6 => 0x5c79, 0xa7 => 0x5c8c, 0xa8 => 0x5c91, + 0xa9 => 0x5c94, 0xaa => 0x599b, 0xab => 0x5cab, 0xac => 0x5cbb, + 0xad => 0x5cb6, 0xae => 0x5cbc, 0xaf => 0x5cb7, 0xb0 => 0x5cc5, + 0xb1 => 0x5cbe, 0xb2 => 0x5cc7, 0xb3 => 0x5cd9, 0xb4 => 0x5ce9, + 0xb5 => 0x5cfd, 0xb6 => 0x5cfa, 0xb7 => 0x5ced, 0xb8 => 0x5d8c, + 0xb9 => 0x5cea, 0xba => 0x5d0b, 0xbb => 0x5d15, 0xbc => 0x5d17, + 0xbd => 0x5d5c, 0xbe => 0x5d1f, 0xbf => 0x5d1b, 0xc0 => 0x5d11, + 0xc1 => 0x5d14, 0xc2 => 0x5d22, 0xc3 => 0x5d1a, 0xc4 => 0x5d19, + 0xc5 => 0x5d18, 0xc6 => 0x5d4c, 0xc7 => 0x5d52, 0xc8 => 0x5d4e, + 0xc9 => 0x5d4b, 0xca => 0x5d6c, 0xcb => 0x5d73, 0xcc => 0x5d76, + 0xcd => 0x5d87, 0xce => 0x5d84, 0xcf => 0x5d82, 0xd0 => 0x5da2, + 0xd1 => 0x5d9d, 0xd2 => 0x5dac, 0xd3 => 0x5dae, 0xd4 => 0x5dbd, + 0xd5 => 0x5d90, 0xd6 => 0x5db7, 0xd7 => 0x5dbc, 0xd8 => 0x5dc9, + 0xd9 => 0x5dcd, 0xda => 0x5dd3, 0xdb => 0x5dd2, 0xdc => 0x5dd6, + 0xdd => 0x5ddb, 0xde => 0x5deb, 0xdf => 0x5df2, 0xe0 => 0x5df5, + 0xe1 => 0x5e0b, 0xe2 => 0x5e1a, 0xe3 => 0x5e19, 0xe4 => 0x5e11, + 0xe5 => 0x5e1b, 0xe6 => 0x5e36, 0xe7 => 0x5e37, 0xe8 => 0x5e44, + 0xe9 => 0x5e43, 0xea => 0x5e40, 0xeb => 0x5e4e, 0xec => 0x5e57, + 0xed => 0x5e54, 0xee => 0x5e5f, 0xef => 0x5e62, 0xf0 => 0x5e64, + 0xf1 => 0x5e47, 0xf2 => 0x5e75, 0xf3 => 0x5e76, 0xf4 => 0x5e7a, + 0xf5 => 0x9ebc, 0xf6 => 0x5e7f, 0xf7 => 0x5ea0, 0xf8 => 0x5ec1, + 0xf9 => 0x5ec2, 0xfa => 0x5ec8, 0xfb => 0x5ed0, 0xfc => 0x5ecf, + }, + 0x9c => { + 0x40 => 0x5ed6, 0x41 => 0x5ee3, 0x42 => 0x5edd, 0x43 => 0x5eda, + 0x44 => 0x5edb, 0x45 => 0x5ee2, 0x46 => 0x5ee1, 0x47 => 0x5ee8, + 0x48 => 0x5ee9, 0x49 => 0x5eec, 0x4a => 0x5ef1, 0x4b => 0x5ef3, + 0x4c => 0x5ef0, 0x4d => 0x5ef4, 0x4e => 0x5ef8, 0x4f => 0x5efe, + 0x50 => 0x5f03, 0x51 => 0x5f09, 0x52 => 0x5f5d, 0x53 => 0x5f5c, + 0x54 => 0x5f0b, 0x55 => 0x5f11, 0x56 => 0x5f16, 0x57 => 0x5f29, + 0x58 => 0x5f2d, 0x59 => 0x5f38, 0x5a => 0x5f41, 0x5b => 0x5f48, + 0x5c => 0x5f4c, 0x5d => 0x5f4e, 0x5e => 0x5f2f, 0x5f => 0x5f51, + 0x60 => 0x5f56, 0x61 => 0x5f57, 0x62 => 0x5f59, 0x63 => 0x5f61, + 0x64 => 0x5f6d, 0x65 => 0x5f73, 0x66 => 0x5f77, 0x67 => 0x5f83, + 0x68 => 0x5f82, 0x69 => 0x5f7f, 0x6a => 0x5f8a, 0x6b => 0x5f88, + 0x6c => 0x5f91, 0x6d => 0x5f87, 0x6e => 0x5f9e, 0x6f => 0x5f99, + 0x70 => 0x5f98, 0x71 => 0x5fa0, 0x72 => 0x5fa8, 0x73 => 0x5fad, + 0x74 => 0x5fbc, 0x75 => 0x5fd6, 0x76 => 0x5ffb, 0x77 => 0x5fe4, + 0x78 => 0x5ff8, 0x79 => 0x5ff1, 0x7a => 0x5fdd, 0x7b => 0x60b3, + 0x7c => 0x5fff, 0x7d => 0x6021, 0x7e => 0x6060, 0x80 => 0x6019, + 0x81 => 0x6010, 0x82 => 0x6029, 0x83 => 0x600e, 0x84 => 0x6031, + 0x85 => 0x601b, 0x86 => 0x6015, 0x87 => 0x602b, 0x88 => 0x6026, + 0x89 => 0x600f, 0x8a => 0x603a, 0x8b => 0x605a, 0x8c => 0x6041, + 0x8d => 0x606a, 0x8e => 0x6077, 0x8f => 0x605f, 0x90 => 0x604a, + 0x91 => 0x6046, 0x92 => 0x604d, 0x93 => 0x6063, 0x94 => 0x6043, + 0x95 => 0x6064, 0x96 => 0x6042, 0x97 => 0x606c, 0x98 => 0x606b, + 0x99 => 0x6059, 0x9a => 0x6081, 0x9b => 0x608d, 0x9c => 0x60e7, + 0x9d => 0x6083, 0x9e => 0x609a, 0x9f => 0x6084, 0xa0 => 0x609b, + 0xa1 => 0x6096, 0xa2 => 0x6097, 0xa3 => 0x6092, 0xa4 => 0x60a7, + 0xa5 => 0x608b, 0xa6 => 0x60e1, 0xa7 => 0x60b8, 0xa8 => 0x60e0, + 0xa9 => 0x60d3, 0xaa => 0x60b4, 0xab => 0x5ff0, 0xac => 0x60bd, + 0xad => 0x60c6, 0xae => 0x60b5, 0xaf => 0x60d8, 0xb0 => 0x614d, + 0xb1 => 0x6115, 0xb2 => 0x6106, 0xb3 => 0x60f6, 0xb4 => 0x60f7, + 0xb5 => 0x6100, 0xb6 => 0x60f4, 0xb7 => 0x60fa, 0xb8 => 0x6103, + 0xb9 => 0x6121, 0xba => 0x60fb, 0xbb => 0x60f1, 0xbc => 0x610d, + 0xbd => 0x610e, 0xbe => 0x6147, 0xbf => 0x613e, 0xc0 => 0x6128, + 0xc1 => 0x6127, 0xc2 => 0x614a, 0xc3 => 0x613f, 0xc4 => 0x613c, + 0xc5 => 0x612c, 0xc6 => 0x6134, 0xc7 => 0x613d, 0xc8 => 0x6142, + 0xc9 => 0x6144, 0xca => 0x6173, 0xcb => 0x6177, 0xcc => 0x6158, + 0xcd => 0x6159, 0xce => 0x615a, 0xcf => 0x616b, 0xd0 => 0x6174, + 0xd1 => 0x616f, 0xd2 => 0x6165, 0xd3 => 0x6171, 0xd4 => 0x615f, + 0xd5 => 0x615d, 0xd6 => 0x6153, 0xd7 => 0x6175, 0xd8 => 0x6199, + 0xd9 => 0x6196, 0xda => 0x6187, 0xdb => 0x61ac, 0xdc => 0x6194, + 0xdd => 0x619a, 0xde => 0x618a, 0xdf => 0x6191, 0xe0 => 0x61ab, + 0xe1 => 0x61ae, 0xe2 => 0x61cc, 0xe3 => 0x61ca, 0xe4 => 0x61c9, + 0xe5 => 0x61f7, 0xe6 => 0x61c8, 0xe7 => 0x61c3, 0xe8 => 0x61c6, + 0xe9 => 0x61ba, 0xea => 0x61cb, 0xeb => 0x7f79, 0xec => 0x61cd, + 0xed => 0x61e6, 0xee => 0x61e3, 0xef => 0x61f6, 0xf0 => 0x61fa, + 0xf1 => 0x61f4, 0xf2 => 0x61ff, 0xf3 => 0x61fd, 0xf4 => 0x61fc, + 0xf5 => 0x61fe, 0xf6 => 0x6200, 0xf7 => 0x6208, 0xf8 => 0x6209, + 0xf9 => 0x620d, 0xfa => 0x620c, 0xfb => 0x6214, 0xfc => 0x621b, + }, + 0x9d => { + 0x40 => 0x621e, 0x41 => 0x6221, 0x42 => 0x622a, 0x43 => 0x622e, + 0x44 => 0x6230, 0x45 => 0x6232, 0x46 => 0x6233, 0x47 => 0x6241, + 0x48 => 0x624e, 0x49 => 0x625e, 0x4a => 0x6263, 0x4b => 0x625b, + 0x4c => 0x6260, 0x4d => 0x6268, 0x4e => 0x627c, 0x4f => 0x6282, + 0x50 => 0x6289, 0x51 => 0x627e, 0x52 => 0x6292, 0x53 => 0x6293, + 0x54 => 0x6296, 0x55 => 0x62d4, 0x56 => 0x6283, 0x57 => 0x6294, + 0x58 => 0x62d7, 0x59 => 0x62d1, 0x5a => 0x62bb, 0x5b => 0x62cf, + 0x5c => 0x62ff, 0x5d => 0x62c6, 0x5e => 0x64d4, 0x5f => 0x62c8, + 0x60 => 0x62dc, 0x61 => 0x62cc, 0x62 => 0x62ca, 0x63 => 0x62c2, + 0x64 => 0x62c7, 0x65 => 0x629b, 0x66 => 0x62c9, 0x67 => 0x630c, + 0x68 => 0x62ee, 0x69 => 0x62f1, 0x6a => 0x6327, 0x6b => 0x6302, + 0x6c => 0x6308, 0x6d => 0x62ef, 0x6e => 0x62f5, 0x6f => 0x6350, + 0x70 => 0x633e, 0x71 => 0x634d, 0x72 => 0x641c, 0x73 => 0x634f, + 0x74 => 0x6396, 0x75 => 0x638e, 0x76 => 0x6380, 0x77 => 0x63ab, + 0x78 => 0x6376, 0x79 => 0x63a3, 0x7a => 0x638f, 0x7b => 0x6389, + 0x7c => 0x639f, 0x7d => 0x63b5, 0x7e => 0x636b, 0x80 => 0x6369, + 0x81 => 0x63be, 0x82 => 0x63e9, 0x83 => 0x63c0, 0x84 => 0x63c6, + 0x85 => 0x63e3, 0x86 => 0x63c9, 0x87 => 0x63d2, 0x88 => 0x63f6, + 0x89 => 0x63c4, 0x8a => 0x6416, 0x8b => 0x6434, 0x8c => 0x6406, + 0x8d => 0x6413, 0x8e => 0x6426, 0x8f => 0x6436, 0x90 => 0x651d, + 0x91 => 0x6417, 0x92 => 0x6428, 0x93 => 0x640f, 0x94 => 0x6467, + 0x95 => 0x646f, 0x96 => 0x6476, 0x97 => 0x644e, 0x98 => 0x652a, + 0x99 => 0x6495, 0x9a => 0x6493, 0x9b => 0x64a5, 0x9c => 0x64a9, + 0x9d => 0x6488, 0x9e => 0x64bc, 0x9f => 0x64da, 0xa0 => 0x64d2, + 0xa1 => 0x64c5, 0xa2 => 0x64c7, 0xa3 => 0x64bb, 0xa4 => 0x64d8, + 0xa5 => 0x64c2, 0xa6 => 0x64f1, 0xa7 => 0x64e7, 0xa8 => 0x8209, + 0xa9 => 0x64e0, 0xaa => 0x64e1, 0xab => 0x62ac, 0xac => 0x64e3, + 0xad => 0x64ef, 0xae => 0x652c, 0xaf => 0x64f6, 0xb0 => 0x64f4, + 0xb1 => 0x64f2, 0xb2 => 0x64fa, 0xb3 => 0x6500, 0xb4 => 0x64fd, + 0xb5 => 0x6518, 0xb6 => 0x651c, 0xb7 => 0x6505, 0xb8 => 0x6524, + 0xb9 => 0x6523, 0xba => 0x652b, 0xbb => 0x6534, 0xbc => 0x6535, + 0xbd => 0x6537, 0xbe => 0x6536, 0xbf => 0x6538, 0xc0 => 0x754b, + 0xc1 => 0x6548, 0xc2 => 0x6556, 0xc3 => 0x6555, 0xc4 => 0x654d, + 0xc5 => 0x6558, 0xc6 => 0x655e, 0xc7 => 0x655d, 0xc8 => 0x6572, + 0xc9 => 0x6578, 0xca => 0x6582, 0xcb => 0x6583, 0xcc => 0x8b8a, + 0xcd => 0x659b, 0xce => 0x659f, 0xcf => 0x65ab, 0xd0 => 0x65b7, + 0xd1 => 0x65c3, 0xd2 => 0x65c6, 0xd3 => 0x65c1, 0xd4 => 0x65c4, + 0xd5 => 0x65cc, 0xd6 => 0x65d2, 0xd7 => 0x65db, 0xd8 => 0x65d9, + 0xd9 => 0x65e0, 0xda => 0x65e1, 0xdb => 0x65f1, 0xdc => 0x6772, + 0xdd => 0x660a, 0xde => 0x6603, 0xdf => 0x65fb, 0xe0 => 0x6773, + 0xe1 => 0x6635, 0xe2 => 0x6636, 0xe3 => 0x6634, 0xe4 => 0x661c, + 0xe5 => 0x664f, 0xe6 => 0x6644, 0xe7 => 0x6649, 0xe8 => 0x6641, + 0xe9 => 0x665e, 0xea => 0x665d, 0xeb => 0x6664, 0xec => 0x6667, + 0xed => 0x6668, 0xee => 0x665f, 0xef => 0x6662, 0xf0 => 0x6670, + 0xf1 => 0x6683, 0xf2 => 0x6688, 0xf3 => 0x668e, 0xf4 => 0x6689, + 0xf5 => 0x6684, 0xf6 => 0x6698, 0xf7 => 0x669d, 0xf8 => 0x66c1, + 0xf9 => 0x66b9, 0xfa => 0x66c9, 0xfb => 0x66be, 0xfc => 0x66bc, + }, + 0x9e => { + 0x40 => 0x66c4, 0x41 => 0x66b8, 0x42 => 0x66d6, 0x43 => 0x66da, + 0x44 => 0x66e0, 0x45 => 0x663f, 0x46 => 0x66e6, 0x47 => 0x66e9, + 0x48 => 0x66f0, 0x49 => 0x66f5, 0x4a => 0x66f7, 0x4b => 0x670f, + 0x4c => 0x6716, 0x4d => 0x671e, 0x4e => 0x6726, 0x4f => 0x6727, + 0x50 => 0x9738, 0x51 => 0x672e, 0x52 => 0x673f, 0x53 => 0x6736, + 0x54 => 0x6741, 0x55 => 0x6738, 0x56 => 0x6737, 0x57 => 0x6746, + 0x58 => 0x675e, 0x59 => 0x6760, 0x5a => 0x6759, 0x5b => 0x6763, + 0x5c => 0x6764, 0x5d => 0x6789, 0x5e => 0x6770, 0x5f => 0x67a9, + 0x60 => 0x677c, 0x61 => 0x676a, 0x62 => 0x678c, 0x63 => 0x678b, + 0x64 => 0x67a6, 0x65 => 0x67a1, 0x66 => 0x6785, 0x67 => 0x67b7, + 0x68 => 0x67ef, 0x69 => 0x67b4, 0x6a => 0x67ec, 0x6b => 0x67b3, + 0x6c => 0x67e9, 0x6d => 0x67b8, 0x6e => 0x67e4, 0x6f => 0x67de, + 0x70 => 0x67dd, 0x71 => 0x67e2, 0x72 => 0x67ee, 0x73 => 0x67b9, + 0x74 => 0x67ce, 0x75 => 0x67c6, 0x76 => 0x67e7, 0x77 => 0x6a9c, + 0x78 => 0x681e, 0x79 => 0x6846, 0x7a => 0x6829, 0x7b => 0x6840, + 0x7c => 0x684d, 0x7d => 0x6832, 0x7e => 0x684e, 0x80 => 0x68b3, + 0x81 => 0x682b, 0x82 => 0x6859, 0x83 => 0x6863, 0x84 => 0x6877, + 0x85 => 0x687f, 0x86 => 0x689f, 0x87 => 0x688f, 0x88 => 0x68ad, + 0x89 => 0x6894, 0x8a => 0x689d, 0x8b => 0x689b, 0x8c => 0x6883, + 0x8d => 0x6aae, 0x8e => 0x68b9, 0x8f => 0x6874, 0x90 => 0x68b5, + 0x91 => 0x68a0, 0x92 => 0x68ba, 0x93 => 0x690f, 0x94 => 0x688d, + 0x95 => 0x687e, 0x96 => 0x6901, 0x97 => 0x68ca, 0x98 => 0x6908, + 0x99 => 0x68d8, 0x9a => 0x6922, 0x9b => 0x6926, 0x9c => 0x68e1, + 0x9d => 0x690c, 0x9e => 0x68cd, 0x9f => 0x68d4, 0xa0 => 0x68e7, + 0xa1 => 0x68d5, 0xa2 => 0x6936, 0xa3 => 0x6912, 0xa4 => 0x6904, + 0xa5 => 0x68d7, 0xa6 => 0x68e3, 0xa7 => 0x6925, 0xa8 => 0x68f9, + 0xa9 => 0x68e0, 0xaa => 0x68ef, 0xab => 0x6928, 0xac => 0x692a, + 0xad => 0x691a, 0xae => 0x6923, 0xaf => 0x6921, 0xb0 => 0x68c6, + 0xb1 => 0x6979, 0xb2 => 0x6977, 0xb3 => 0x695c, 0xb4 => 0x6978, + 0xb5 => 0x696b, 0xb6 => 0x6954, 0xb7 => 0x697e, 0xb8 => 0x696e, + 0xb9 => 0x6939, 0xba => 0x6974, 0xbb => 0x693d, 0xbc => 0x6959, + 0xbd => 0x6930, 0xbe => 0x6961, 0xbf => 0x695e, 0xc0 => 0x695d, + 0xc1 => 0x6981, 0xc2 => 0x696a, 0xc3 => 0x69b2, 0xc4 => 0x69ae, + 0xc5 => 0x69d0, 0xc6 => 0x69bf, 0xc7 => 0x69c1, 0xc8 => 0x69d3, + 0xc9 => 0x69be, 0xca => 0x69ce, 0xcb => 0x5be8, 0xcc => 0x69ca, + 0xcd => 0x69dd, 0xce => 0x69bb, 0xcf => 0x69c3, 0xd0 => 0x69a7, + 0xd1 => 0x6a2e, 0xd2 => 0x6991, 0xd3 => 0x69a0, 0xd4 => 0x699c, + 0xd5 => 0x6995, 0xd6 => 0x69b4, 0xd7 => 0x69de, 0xd8 => 0x69e8, + 0xd9 => 0x6a02, 0xda => 0x6a1b, 0xdb => 0x69ff, 0xdc => 0x6b0a, + 0xdd => 0x69f9, 0xde => 0x69f2, 0xdf => 0x69e7, 0xe0 => 0x6a05, + 0xe1 => 0x69b1, 0xe2 => 0x6a1e, 0xe3 => 0x69ed, 0xe4 => 0x6a14, + 0xe5 => 0x69eb, 0xe6 => 0x6a0a, 0xe7 => 0x6a12, 0xe8 => 0x6ac1, + 0xe9 => 0x6a23, 0xea => 0x6a13, 0xeb => 0x6a44, 0xec => 0x6a0c, + 0xed => 0x6a72, 0xee => 0x6a36, 0xef => 0x6a78, 0xf0 => 0x6a47, + 0xf1 => 0x6a62, 0xf2 => 0x6a59, 0xf3 => 0x6a66, 0xf4 => 0x6a48, + 0xf5 => 0x6a38, 0xf6 => 0x6a22, 0xf7 => 0x6a90, 0xf8 => 0x6a8d, + 0xf9 => 0x6aa0, 0xfa => 0x6a84, 0xfb => 0x6aa2, 0xfc => 0x6aa3, + }, + 0x9f => { + 0x40 => 0x6a97, 0x41 => 0x8617, 0x42 => 0x6abb, 0x43 => 0x6ac3, + 0x44 => 0x6ac2, 0x45 => 0x6ab8, 0x46 => 0x6ab3, 0x47 => 0x6aac, + 0x48 => 0x6ade, 0x49 => 0x6ad1, 0x4a => 0x6adf, 0x4b => 0x6aaa, + 0x4c => 0x6ada, 0x4d => 0x6aea, 0x4e => 0x6afb, 0x4f => 0x6b05, + 0x50 => 0x8616, 0x51 => 0x6afa, 0x52 => 0x6b12, 0x53 => 0x6b16, + 0x54 => 0x9b31, 0x55 => 0x6b1f, 0x56 => 0x6b38, 0x57 => 0x6b37, + 0x58 => 0x76dc, 0x59 => 0x6b39, 0x5a => 0x98ee, 0x5b => 0x6b47, + 0x5c => 0x6b43, 0x5d => 0x6b49, 0x5e => 0x6b50, 0x5f => 0x6b59, + 0x60 => 0x6b54, 0x61 => 0x6b5b, 0x62 => 0x6b5f, 0x63 => 0x6b61, + 0x64 => 0x6b78, 0x65 => 0x6b79, 0x66 => 0x6b7f, 0x67 => 0x6b80, + 0x68 => 0x6b84, 0x69 => 0x6b83, 0x6a => 0x6b8d, 0x6b => 0x6b98, + 0x6c => 0x6b95, 0x6d => 0x6b9e, 0x6e => 0x6ba4, 0x6f => 0x6baa, + 0x70 => 0x6bab, 0x71 => 0x6baf, 0x72 => 0x6bb2, 0x73 => 0x6bb1, + 0x74 => 0x6bb3, 0x75 => 0x6bb7, 0x76 => 0x6bbc, 0x77 => 0x6bc6, + 0x78 => 0x6bcb, 0x79 => 0x6bd3, 0x7a => 0x6bdf, 0x7b => 0x6bec, + 0x7c => 0x6beb, 0x7d => 0x6bf3, 0x7e => 0x6bef, 0x80 => 0x9ebe, + 0x81 => 0x6c08, 0x82 => 0x6c13, 0x83 => 0x6c14, 0x84 => 0x6c1b, + 0x85 => 0x6c24, 0x86 => 0x6c23, 0x87 => 0x6c5e, 0x88 => 0x6c55, + 0x89 => 0x6c62, 0x8a => 0x6c6a, 0x8b => 0x6c82, 0x8c => 0x6c8d, + 0x8d => 0x6c9a, 0x8e => 0x6c81, 0x8f => 0x6c9b, 0x90 => 0x6c7e, + 0x91 => 0x6c68, 0x92 => 0x6c73, 0x93 => 0x6c92, 0x94 => 0x6c90, + 0x95 => 0x6cc4, 0x96 => 0x6cf1, 0x97 => 0x6cd3, 0x98 => 0x6cbd, + 0x99 => 0x6cd7, 0x9a => 0x6cc5, 0x9b => 0x6cdd, 0x9c => 0x6cae, + 0x9d => 0x6cb1, 0x9e => 0x6cbe, 0x9f => 0x6cba, 0xa0 => 0x6cdb, + 0xa1 => 0x6cef, 0xa2 => 0x6cd9, 0xa3 => 0x6cea, 0xa4 => 0x6d1f, + 0xa5 => 0x884d, 0xa6 => 0x6d36, 0xa7 => 0x6d2b, 0xa8 => 0x6d3d, + 0xa9 => 0x6d38, 0xaa => 0x6d19, 0xab => 0x6d35, 0xac => 0x6d33, + 0xad => 0x6d12, 0xae => 0x6d0c, 0xaf => 0x6d63, 0xb0 => 0x6d93, + 0xb1 => 0x6d64, 0xb2 => 0x6d5a, 0xb3 => 0x6d79, 0xb4 => 0x6d59, + 0xb5 => 0x6d8e, 0xb6 => 0x6d95, 0xb7 => 0x6fe4, 0xb8 => 0x6d85, + 0xb9 => 0x6df9, 0xba => 0x6e15, 0xbb => 0x6e0a, 0xbc => 0x6db5, + 0xbd => 0x6dc7, 0xbe => 0x6de6, 0xbf => 0x6db8, 0xc0 => 0x6dc6, + 0xc1 => 0x6dec, 0xc2 => 0x6dde, 0xc3 => 0x6dcc, 0xc4 => 0x6de8, + 0xc5 => 0x6dd2, 0xc6 => 0x6dc5, 0xc7 => 0x6dfa, 0xc8 => 0x6dd9, + 0xc9 => 0x6de4, 0xca => 0x6dd5, 0xcb => 0x6dea, 0xcc => 0x6dee, + 0xcd => 0x6e2d, 0xce => 0x6e6e, 0xcf => 0x6e2e, 0xd0 => 0x6e19, + 0xd1 => 0x6e72, 0xd2 => 0x6e5f, 0xd3 => 0x6e3e, 0xd4 => 0x6e23, + 0xd5 => 0x6e6b, 0xd6 => 0x6e2b, 0xd7 => 0x6e76, 0xd8 => 0x6e4d, + 0xd9 => 0x6e1f, 0xda => 0x6e43, 0xdb => 0x6e3a, 0xdc => 0x6e4e, + 0xdd => 0x6e24, 0xde => 0x6eff, 0xdf => 0x6e1d, 0xe0 => 0x6e38, + 0xe1 => 0x6e82, 0xe2 => 0x6eaa, 0xe3 => 0x6e98, 0xe4 => 0x6ec9, + 0xe5 => 0x6eb7, 0xe6 => 0x6ed3, 0xe7 => 0x6ebd, 0xe8 => 0x6eaf, + 0xe9 => 0x6ec4, 0xea => 0x6eb2, 0xeb => 0x6ed4, 0xec => 0x6ed5, + 0xed => 0x6e8f, 0xee => 0x6ea5, 0xef => 0x6ec2, 0xf0 => 0x6e9f, + 0xf1 => 0x6f41, 0xf2 => 0x6f11, 0xf3 => 0x704c, 0xf4 => 0x6eec, + 0xf5 => 0x6ef8, 0xf6 => 0x6efe, 0xf7 => 0x6f3f, 0xf8 => 0x6ef2, + 0xf9 => 0x6f31, 0xfa => 0x6eef, 0xfb => 0x6f32, 0xfc => 0x6ecc, + }, + 0xa1 => 0xff61, 0xa2 => 0xff62, 0xa3 => 0xff63, 0xa4 => 0xff64, + 0xa5 => 0xff65, 0xa6 => 0xff66, 0xa7 => 0xff67, 0xa8 => 0xff68, + 0xa9 => 0xff69, 0xaa => 0xff6a, 0xab => 0xff6b, 0xac => 0xff6c, + 0xad => 0xff6d, 0xae => 0xff6e, 0xaf => 0xff6f, 0xb0 => 0xff70, + 0xb1 => 0xff71, 0xb2 => 0xff72, 0xb3 => 0xff73, 0xb4 => 0xff74, + 0xb5 => 0xff75, 0xb6 => 0xff76, 0xb7 => 0xff77, 0xb8 => 0xff78, + 0xb9 => 0xff79, 0xba => 0xff7a, 0xbb => 0xff7b, 0xbc => 0xff7c, + 0xbd => 0xff7d, 0xbe => 0xff7e, 0xbf => 0xff7f, 0xc0 => 0xff80, + 0xc1 => 0xff81, 0xc2 => 0xff82, 0xc3 => 0xff83, 0xc4 => 0xff84, + 0xc5 => 0xff85, 0xc6 => 0xff86, 0xc7 => 0xff87, 0xc8 => 0xff88, + 0xc9 => 0xff89, 0xca => 0xff8a, 0xcb => 0xff8b, 0xcc => 0xff8c, + 0xcd => 0xff8d, 0xce => 0xff8e, 0xcf => 0xff8f, 0xd0 => 0xff90, + 0xd1 => 0xff91, 0xd2 => 0xff92, 0xd3 => 0xff93, 0xd4 => 0xff94, + 0xd5 => 0xff95, 0xd6 => 0xff96, 0xd7 => 0xff97, 0xd8 => 0xff98, + 0xd9 => 0xff99, 0xda => 0xff9a, 0xdb => 0xff9b, 0xdc => 0xff9c, + 0xdd => 0xff9d, 0xde => 0xff9e, 0xdf => 0xff9f, + 0xe0 => { + 0x40 => 0x6f3e, 0x41 => 0x6f13, 0x42 => 0x6ef7, 0x43 => 0x6f86, + 0x44 => 0x6f7a, 0x45 => 0x6f78, 0x46 => 0x6f81, 0x47 => 0x6f80, + 0x48 => 0x6f6f, 0x49 => 0x6f5b, 0x4a => 0x6ff3, 0x4b => 0x6f6d, + 0x4c => 0x6f82, 0x4d => 0x6f7c, 0x4e => 0x6f58, 0x4f => 0x6f8e, + 0x50 => 0x6f91, 0x51 => 0x6fc2, 0x52 => 0x6f66, 0x53 => 0x6fb3, + 0x54 => 0x6fa3, 0x55 => 0x6fa1, 0x56 => 0x6fa4, 0x57 => 0x6fb9, + 0x58 => 0x6fc6, 0x59 => 0x6faa, 0x5a => 0x6fdf, 0x5b => 0x6fd5, + 0x5c => 0x6fec, 0x5d => 0x6fd4, 0x5e => 0x6fd8, 0x5f => 0x6ff1, + 0x60 => 0x6fee, 0x61 => 0x6fdb, 0x62 => 0x7009, 0x63 => 0x700b, + 0x64 => 0x6ffa, 0x65 => 0x7011, 0x66 => 0x7001, 0x67 => 0x700f, + 0x68 => 0x6ffe, 0x69 => 0x701b, 0x6a => 0x701a, 0x6b => 0x6f74, + 0x6c => 0x701d, 0x6d => 0x7018, 0x6e => 0x701f, 0x6f => 0x7030, + 0x70 => 0x703e, 0x71 => 0x7032, 0x72 => 0x7051, 0x73 => 0x7063, + 0x74 => 0x7099, 0x75 => 0x7092, 0x76 => 0x70af, 0x77 => 0x70f1, + 0x78 => 0x70ac, 0x79 => 0x70b8, 0x7a => 0x70b3, 0x7b => 0x70ae, + 0x7c => 0x70df, 0x7d => 0x70cb, 0x7e => 0x70dd, 0x80 => 0x70d9, + 0x81 => 0x7109, 0x82 => 0x70fd, 0x83 => 0x711c, 0x84 => 0x7119, + 0x85 => 0x7165, 0x86 => 0x7155, 0x87 => 0x7188, 0x88 => 0x7166, + 0x89 => 0x7162, 0x8a => 0x714c, 0x8b => 0x7156, 0x8c => 0x716c, + 0x8d => 0x718f, 0x8e => 0x71fb, 0x8f => 0x7184, 0x90 => 0x7195, + 0x91 => 0x71a8, 0x92 => 0x71ac, 0x93 => 0x71d7, 0x94 => 0x71b9, + 0x95 => 0x71be, 0x96 => 0x71d2, 0x97 => 0x71c9, 0x98 => 0x71d4, + 0x99 => 0x71ce, 0x9a => 0x71e0, 0x9b => 0x71ec, 0x9c => 0x71e7, + 0x9d => 0x71f5, 0x9e => 0x71fc, 0x9f => 0x71f9, 0xa0 => 0x71ff, + 0xa1 => 0x720d, 0xa2 => 0x7210, 0xa3 => 0x721b, 0xa4 => 0x7228, + 0xa5 => 0x722d, 0xa6 => 0x722c, 0xa7 => 0x7230, 0xa8 => 0x7232, + 0xa9 => 0x723b, 0xaa => 0x723c, 0xab => 0x723f, 0xac => 0x7240, + 0xad => 0x7246, 0xae => 0x724b, 0xaf => 0x7258, 0xb0 => 0x7274, + 0xb1 => 0x727e, 0xb2 => 0x7282, 0xb3 => 0x7281, 0xb4 => 0x7287, + 0xb5 => 0x7292, 0xb6 => 0x7296, 0xb7 => 0x72a2, 0xb8 => 0x72a7, + 0xb9 => 0x72b9, 0xba => 0x72b2, 0xbb => 0x72c3, 0xbc => 0x72c6, + 0xbd => 0x72c4, 0xbe => 0x72ce, 0xbf => 0x72d2, 0xc0 => 0x72e2, + 0xc1 => 0x72e0, 0xc2 => 0x72e1, 0xc3 => 0x72f9, 0xc4 => 0x72f7, + 0xc5 => 0x500f, 0xc6 => 0x7317, 0xc7 => 0x730a, 0xc8 => 0x731c, + 0xc9 => 0x7316, 0xca => 0x731d, 0xcb => 0x7334, 0xcc => 0x732f, + 0xcd => 0x7329, 0xce => 0x7325, 0xcf => 0x733e, 0xd0 => 0x734e, + 0xd1 => 0x734f, 0xd2 => 0x9ed8, 0xd3 => 0x7357, 0xd4 => 0x736a, + 0xd5 => 0x7368, 0xd6 => 0x7370, 0xd7 => 0x7378, 0xd8 => 0x7375, + 0xd9 => 0x737b, 0xda => 0x737a, 0xdb => 0x73c8, 0xdc => 0x73b3, + 0xdd => 0x73ce, 0xde => 0x73bb, 0xdf => 0x73c0, 0xe0 => 0x73e5, + 0xe1 => 0x73ee, 0xe2 => 0x73de, 0xe3 => 0x74a2, 0xe4 => 0x7405, + 0xe5 => 0x746f, 0xe6 => 0x7425, 0xe7 => 0x73f8, 0xe8 => 0x7432, + 0xe9 => 0x743a, 0xea => 0x7455, 0xeb => 0x743f, 0xec => 0x745f, + 0xed => 0x7459, 0xee => 0x7441, 0xef => 0x745c, 0xf0 => 0x7469, + 0xf1 => 0x7470, 0xf2 => 0x7463, 0xf3 => 0x746a, 0xf4 => 0x7476, + 0xf5 => 0x747e, 0xf6 => 0x748b, 0xf7 => 0x749e, 0xf8 => 0x74a7, + 0xf9 => 0x74ca, 0xfa => 0x74cf, 0xfb => 0x74d4, 0xfc => 0x73f1, + }, + 0xe1 => { + 0x40 => 0x74e0, 0x41 => 0x74e3, 0x42 => 0x74e7, 0x43 => 0x74e9, + 0x44 => 0x74ee, 0x45 => 0x74f2, 0x46 => 0x74f0, 0x47 => 0x74f1, + 0x48 => 0x74f8, 0x49 => 0x74f7, 0x4a => 0x7504, 0x4b => 0x7503, + 0x4c => 0x7505, 0x4d => 0x750c, 0x4e => 0x750e, 0x4f => 0x750d, + 0x50 => 0x7515, 0x51 => 0x7513, 0x52 => 0x751e, 0x53 => 0x7526, + 0x54 => 0x752c, 0x55 => 0x753c, 0x56 => 0x7544, 0x57 => 0x754d, + 0x58 => 0x754a, 0x59 => 0x7549, 0x5a => 0x755b, 0x5b => 0x7546, + 0x5c => 0x755a, 0x5d => 0x7569, 0x5e => 0x7564, 0x5f => 0x7567, + 0x60 => 0x756b, 0x61 => 0x756d, 0x62 => 0x7578, 0x63 => 0x7576, + 0x64 => 0x7586, 0x65 => 0x7587, 0x66 => 0x7574, 0x67 => 0x758a, + 0x68 => 0x7589, 0x69 => 0x7582, 0x6a => 0x7594, 0x6b => 0x759a, + 0x6c => 0x759d, 0x6d => 0x75a5, 0x6e => 0x75a3, 0x6f => 0x75c2, + 0x70 => 0x75b3, 0x71 => 0x75c3, 0x72 => 0x75b5, 0x73 => 0x75bd, + 0x74 => 0x75b8, 0x75 => 0x75bc, 0x76 => 0x75b1, 0x77 => 0x75cd, + 0x78 => 0x75ca, 0x79 => 0x75d2, 0x7a => 0x75d9, 0x7b => 0x75e3, + 0x7c => 0x75de, 0x7d => 0x75fe, 0x7e => 0x75ff, 0x80 => 0x75fc, + 0x81 => 0x7601, 0x82 => 0x75f0, 0x83 => 0x75fa, 0x84 => 0x75f2, + 0x85 => 0x75f3, 0x86 => 0x760b, 0x87 => 0x760d, 0x88 => 0x7609, + 0x89 => 0x761f, 0x8a => 0x7627, 0x8b => 0x7620, 0x8c => 0x7621, + 0x8d => 0x7622, 0x8e => 0x7624, 0x8f => 0x7634, 0x90 => 0x7630, + 0x91 => 0x763b, 0x92 => 0x7647, 0x93 => 0x7648, 0x94 => 0x7646, + 0x95 => 0x765c, 0x96 => 0x7658, 0x97 => 0x7661, 0x98 => 0x7662, + 0x99 => 0x7668, 0x9a => 0x7669, 0x9b => 0x766a, 0x9c => 0x7667, + 0x9d => 0x766c, 0x9e => 0x7670, 0x9f => 0x7672, 0xa0 => 0x7676, + 0xa1 => 0x7678, 0xa2 => 0x767c, 0xa3 => 0x7680, 0xa4 => 0x7683, + 0xa5 => 0x7688, 0xa6 => 0x768b, 0xa7 => 0x768e, 0xa8 => 0x7696, + 0xa9 => 0x7693, 0xaa => 0x7699, 0xab => 0x769a, 0xac => 0x76b0, + 0xad => 0x76b4, 0xae => 0x76b8, 0xaf => 0x76b9, 0xb0 => 0x76ba, + 0xb1 => 0x76c2, 0xb2 => 0x76cd, 0xb3 => 0x76d6, 0xb4 => 0x76d2, + 0xb5 => 0x76de, 0xb6 => 0x76e1, 0xb7 => 0x76e5, 0xb8 => 0x76e7, + 0xb9 => 0x76ea, 0xba => 0x862f, 0xbb => 0x76fb, 0xbc => 0x7708, + 0xbd => 0x7707, 0xbe => 0x7704, 0xbf => 0x7729, 0xc0 => 0x7724, + 0xc1 => 0x771e, 0xc2 => 0x7725, 0xc3 => 0x7726, 0xc4 => 0x771b, + 0xc5 => 0x7737, 0xc6 => 0x7738, 0xc7 => 0x7747, 0xc8 => 0x775a, + 0xc9 => 0x7768, 0xca => 0x776b, 0xcb => 0x775b, 0xcc => 0x7765, + 0xcd => 0x777f, 0xce => 0x777e, 0xcf => 0x7779, 0xd0 => 0x778e, + 0xd1 => 0x778b, 0xd2 => 0x7791, 0xd3 => 0x77a0, 0xd4 => 0x779e, + 0xd5 => 0x77b0, 0xd6 => 0x77b6, 0xd7 => 0x77b9, 0xd8 => 0x77bf, + 0xd9 => 0x77bc, 0xda => 0x77bd, 0xdb => 0x77bb, 0xdc => 0x77c7, + 0xdd => 0x77cd, 0xde => 0x77d7, 0xdf => 0x77da, 0xe0 => 0x77dc, + 0xe1 => 0x77e3, 0xe2 => 0x77ee, 0xe3 => 0x77fc, 0xe4 => 0x780c, + 0xe5 => 0x7812, 0xe6 => 0x7926, 0xe7 => 0x7820, 0xe8 => 0x792a, + 0xe9 => 0x7845, 0xea => 0x788e, 0xeb => 0x7874, 0xec => 0x7886, + 0xed => 0x787c, 0xee => 0x789a, 0xef => 0x788c, 0xf0 => 0x78a3, + 0xf1 => 0x78b5, 0xf2 => 0x78aa, 0xf3 => 0x78af, 0xf4 => 0x78d1, + 0xf5 => 0x78c6, 0xf6 => 0x78cb, 0xf7 => 0x78d4, 0xf8 => 0x78be, + 0xf9 => 0x78bc, 0xfa => 0x78c5, 0xfb => 0x78ca, 0xfc => 0x78ec, + }, + 0xe2 => { + 0x40 => 0x78e7, 0x41 => 0x78da, 0x42 => 0x78fd, 0x43 => 0x78f4, + 0x44 => 0x7907, 0x45 => 0x7912, 0x46 => 0x7911, 0x47 => 0x7919, + 0x48 => 0x792c, 0x49 => 0x792b, 0x4a => 0x7940, 0x4b => 0x7960, + 0x4c => 0x7957, 0x4d => 0x795f, 0x4e => 0x795a, 0x4f => 0x7955, + 0x50 => 0x7953, 0x51 => 0x797a, 0x52 => 0x797f, 0x53 => 0x798a, + 0x54 => 0x799d, 0x55 => 0x79a7, 0x56 => 0x9f4b, 0x57 => 0x79aa, + 0x58 => 0x79ae, 0x59 => 0x79b3, 0x5a => 0x79b9, 0x5b => 0x79ba, + 0x5c => 0x79c9, 0x5d => 0x79d5, 0x5e => 0x79e7, 0x5f => 0x79ec, + 0x60 => 0x79e1, 0x61 => 0x79e3, 0x62 => 0x7a08, 0x63 => 0x7a0d, + 0x64 => 0x7a18, 0x65 => 0x7a19, 0x66 => 0x7a20, 0x67 => 0x7a1f, + 0x68 => 0x7980, 0x69 => 0x7a31, 0x6a => 0x7a3b, 0x6b => 0x7a3e, + 0x6c => 0x7a37, 0x6d => 0x7a43, 0x6e => 0x7a57, 0x6f => 0x7a49, + 0x70 => 0x7a61, 0x71 => 0x7a62, 0x72 => 0x7a69, 0x73 => 0x9f9d, + 0x74 => 0x7a70, 0x75 => 0x7a79, 0x76 => 0x7a7d, 0x77 => 0x7a88, + 0x78 => 0x7a97, 0x79 => 0x7a95, 0x7a => 0x7a98, 0x7b => 0x7a96, + 0x7c => 0x7aa9, 0x7d => 0x7ac8, 0x7e => 0x7ab0, 0x80 => 0x7ab6, + 0x81 => 0x7ac5, 0x82 => 0x7ac4, 0x83 => 0x7abf, 0x84 => 0x9083, + 0x85 => 0x7ac7, 0x86 => 0x7aca, 0x87 => 0x7acd, 0x88 => 0x7acf, + 0x89 => 0x7ad5, 0x8a => 0x7ad3, 0x8b => 0x7ad9, 0x8c => 0x7ada, + 0x8d => 0x7add, 0x8e => 0x7ae1, 0x8f => 0x7ae2, 0x90 => 0x7ae6, + 0x91 => 0x7aed, 0x92 => 0x7af0, 0x93 => 0x7b02, 0x94 => 0x7b0f, + 0x95 => 0x7b0a, 0x96 => 0x7b06, 0x97 => 0x7b33, 0x98 => 0x7b18, + 0x99 => 0x7b19, 0x9a => 0x7b1e, 0x9b => 0x7b35, 0x9c => 0x7b28, + 0x9d => 0x7b36, 0x9e => 0x7b50, 0x9f => 0x7b7a, 0xa0 => 0x7b04, + 0xa1 => 0x7b4d, 0xa2 => 0x7b0b, 0xa3 => 0x7b4c, 0xa4 => 0x7b45, + 0xa5 => 0x7b75, 0xa6 => 0x7b65, 0xa7 => 0x7b74, 0xa8 => 0x7b67, + 0xa9 => 0x7b70, 0xaa => 0x7b71, 0xab => 0x7b6c, 0xac => 0x7b6e, + 0xad => 0x7b9d, 0xae => 0x7b98, 0xaf => 0x7b9f, 0xb0 => 0x7b8d, + 0xb1 => 0x7b9c, 0xb2 => 0x7b9a, 0xb3 => 0x7b8b, 0xb4 => 0x7b92, + 0xb5 => 0x7b8f, 0xb6 => 0x7b5d, 0xb7 => 0x7b99, 0xb8 => 0x7bcb, + 0xb9 => 0x7bc1, 0xba => 0x7bcc, 0xbb => 0x7bcf, 0xbc => 0x7bb4, + 0xbd => 0x7bc6, 0xbe => 0x7bdd, 0xbf => 0x7be9, 0xc0 => 0x7c11, + 0xc1 => 0x7c14, 0xc2 => 0x7be6, 0xc3 => 0x7be5, 0xc4 => 0x7c60, + 0xc5 => 0x7c00, 0xc6 => 0x7c07, 0xc7 => 0x7c13, 0xc8 => 0x7bf3, + 0xc9 => 0x7bf7, 0xca => 0x7c17, 0xcb => 0x7c0d, 0xcc => 0x7bf6, + 0xcd => 0x7c23, 0xce => 0x7c27, 0xcf => 0x7c2a, 0xd0 => 0x7c1f, + 0xd1 => 0x7c37, 0xd2 => 0x7c2b, 0xd3 => 0x7c3d, 0xd4 => 0x7c4c, + 0xd5 => 0x7c43, 0xd6 => 0x7c54, 0xd7 => 0x7c4f, 0xd8 => 0x7c40, + 0xd9 => 0x7c50, 0xda => 0x7c58, 0xdb => 0x7c5f, 0xdc => 0x7c64, + 0xdd => 0x7c56, 0xde => 0x7c65, 0xdf => 0x7c6c, 0xe0 => 0x7c75, + 0xe1 => 0x7c83, 0xe2 => 0x7c90, 0xe3 => 0x7ca4, 0xe4 => 0x7cad, + 0xe5 => 0x7ca2, 0xe6 => 0x7cab, 0xe7 => 0x7ca1, 0xe8 => 0x7ca8, + 0xe9 => 0x7cb3, 0xea => 0x7cb2, 0xeb => 0x7cb1, 0xec => 0x7cae, + 0xed => 0x7cb9, 0xee => 0x7cbd, 0xef => 0x7cc0, 0xf0 => 0x7cc5, + 0xf1 => 0x7cc2, 0xf2 => 0x7cd8, 0xf3 => 0x7cd2, 0xf4 => 0x7cdc, + 0xf5 => 0x7ce2, 0xf6 => 0x9b3b, 0xf7 => 0x7cef, 0xf8 => 0x7cf2, + 0xf9 => 0x7cf4, 0xfa => 0x7cf6, 0xfb => 0x7cfa, 0xfc => 0x7d06, + }, + 0xe3 => { + 0x40 => 0x7d02, 0x41 => 0x7d1c, 0x42 => 0x7d15, 0x43 => 0x7d0a, + 0x44 => 0x7d45, 0x45 => 0x7d4b, 0x46 => 0x7d2e, 0x47 => 0x7d32, + 0x48 => 0x7d3f, 0x49 => 0x7d35, 0x4a => 0x7d46, 0x4b => 0x7d73, + 0x4c => 0x7d56, 0x4d => 0x7d4e, 0x4e => 0x7d72, 0x4f => 0x7d68, + 0x50 => 0x7d6e, 0x51 => 0x7d4f, 0x52 => 0x7d63, 0x53 => 0x7d93, + 0x54 => 0x7d89, 0x55 => 0x7d5b, 0x56 => 0x7d8f, 0x57 => 0x7d7d, + 0x58 => 0x7d9b, 0x59 => 0x7dba, 0x5a => 0x7dae, 0x5b => 0x7da3, + 0x5c => 0x7db5, 0x5d => 0x7dc7, 0x5e => 0x7dbd, 0x5f => 0x7dab, + 0x60 => 0x7e3d, 0x61 => 0x7da2, 0x62 => 0x7daf, 0x63 => 0x7ddc, + 0x64 => 0x7db8, 0x65 => 0x7d9f, 0x66 => 0x7db0, 0x67 => 0x7dd8, + 0x68 => 0x7ddd, 0x69 => 0x7de4, 0x6a => 0x7dde, 0x6b => 0x7dfb, + 0x6c => 0x7df2, 0x6d => 0x7de1, 0x6e => 0x7e05, 0x6f => 0x7e0a, + 0x70 => 0x7e23, 0x71 => 0x7e21, 0x72 => 0x7e12, 0x73 => 0x7e31, + 0x74 => 0x7e1f, 0x75 => 0x7e09, 0x76 => 0x7e0b, 0x77 => 0x7e22, + 0x78 => 0x7e46, 0x79 => 0x7e66, 0x7a => 0x7e3b, 0x7b => 0x7e35, + 0x7c => 0x7e39, 0x7d => 0x7e43, 0x7e => 0x7e37, 0x80 => 0x7e32, + 0x81 => 0x7e3a, 0x82 => 0x7e67, 0x83 => 0x7e5d, 0x84 => 0x7e56, + 0x85 => 0x7e5e, 0x86 => 0x7e59, 0x87 => 0x7e5a, 0x88 => 0x7e79, + 0x89 => 0x7e6a, 0x8a => 0x7e69, 0x8b => 0x7e7c, 0x8c => 0x7e7b, + 0x8d => 0x7e83, 0x8e => 0x7dd5, 0x8f => 0x7e7d, 0x90 => 0x8fae, + 0x91 => 0x7e7f, 0x92 => 0x7e88, 0x93 => 0x7e89, 0x94 => 0x7e8c, + 0x95 => 0x7e92, 0x96 => 0x7e90, 0x97 => 0x7e93, 0x98 => 0x7e94, + 0x99 => 0x7e96, 0x9a => 0x7e8e, 0x9b => 0x7e9b, 0x9c => 0x7e9c, + 0x9d => 0x7f38, 0x9e => 0x7f3a, 0x9f => 0x7f45, 0xa0 => 0x7f4c, + 0xa1 => 0x7f4d, 0xa2 => 0x7f4e, 0xa3 => 0x7f50, 0xa4 => 0x7f51, + 0xa5 => 0x7f55, 0xa6 => 0x7f54, 0xa7 => 0x7f58, 0xa8 => 0x7f5f, + 0xa9 => 0x7f60, 0xaa => 0x7f68, 0xab => 0x7f69, 0xac => 0x7f67, + 0xad => 0x7f78, 0xae => 0x7f82, 0xaf => 0x7f86, 0xb0 => 0x7f83, + 0xb1 => 0x7f88, 0xb2 => 0x7f87, 0xb3 => 0x7f8c, 0xb4 => 0x7f94, + 0xb5 => 0x7f9e, 0xb6 => 0x7f9d, 0xb7 => 0x7f9a, 0xb8 => 0x7fa3, + 0xb9 => 0x7faf, 0xba => 0x7fb2, 0xbb => 0x7fb9, 0xbc => 0x7fae, + 0xbd => 0x7fb6, 0xbe => 0x7fb8, 0xbf => 0x8b71, 0xc0 => 0x7fc5, + 0xc1 => 0x7fc6, 0xc2 => 0x7fca, 0xc3 => 0x7fd5, 0xc4 => 0x7fd4, + 0xc5 => 0x7fe1, 0xc6 => 0x7fe6, 0xc7 => 0x7fe9, 0xc8 => 0x7ff3, + 0xc9 => 0x7ff9, 0xca => 0x98dc, 0xcb => 0x8006, 0xcc => 0x8004, + 0xcd => 0x800b, 0xce => 0x8012, 0xcf => 0x8018, 0xd0 => 0x8019, + 0xd1 => 0x801c, 0xd2 => 0x8021, 0xd3 => 0x8028, 0xd4 => 0x803f, + 0xd5 => 0x803b, 0xd6 => 0x804a, 0xd7 => 0x8046, 0xd8 => 0x8052, + 0xd9 => 0x8058, 0xda => 0x805a, 0xdb => 0x805f, 0xdc => 0x8062, + 0xdd => 0x8068, 0xde => 0x8073, 0xdf => 0x8072, 0xe0 => 0x8070, + 0xe1 => 0x8076, 0xe2 => 0x8079, 0xe3 => 0x807d, 0xe4 => 0x807f, + 0xe5 => 0x8084, 0xe6 => 0x8086, 0xe7 => 0x8085, 0xe8 => 0x809b, + 0xe9 => 0x8093, 0xea => 0x809a, 0xeb => 0x80ad, 0xec => 0x5190, + 0xed => 0x80ac, 0xee => 0x80db, 0xef => 0x80e5, 0xf0 => 0x80d9, + 0xf1 => 0x80dd, 0xf2 => 0x80c4, 0xf3 => 0x80da, 0xf4 => 0x80d6, + 0xf5 => 0x8109, 0xf6 => 0x80ef, 0xf7 => 0x80f1, 0xf8 => 0x811b, + 0xf9 => 0x8129, 0xfa => 0x8123, 0xfb => 0x812f, 0xfc => 0x814b, + }, + 0xe4 => { + 0x40 => 0x968b, 0x41 => 0x8146, 0x42 => 0x813e, 0x43 => 0x8153, + 0x44 => 0x8151, 0x45 => 0x80fc, 0x46 => 0x8171, 0x47 => 0x816e, + 0x48 => 0x8165, 0x49 => 0x8166, 0x4a => 0x8174, 0x4b => 0x8183, + 0x4c => 0x8188, 0x4d => 0x818a, 0x4e => 0x8180, 0x4f => 0x8182, + 0x50 => 0x81a0, 0x51 => 0x8195, 0x52 => 0x81a4, 0x53 => 0x81a3, + 0x54 => 0x815f, 0x55 => 0x8193, 0x56 => 0x81a9, 0x57 => 0x81b0, + 0x58 => 0x81b5, 0x59 => 0x81be, 0x5a => 0x81b8, 0x5b => 0x81bd, + 0x5c => 0x81c0, 0x5d => 0x81c2, 0x5e => 0x81ba, 0x5f => 0x81c9, + 0x60 => 0x81cd, 0x61 => 0x81d1, 0x62 => 0x81d9, 0x63 => 0x81d8, + 0x64 => 0x81c8, 0x65 => 0x81da, 0x66 => 0x81df, 0x67 => 0x81e0, + 0x68 => 0x81e7, 0x69 => 0x81fa, 0x6a => 0x81fb, 0x6b => 0x81fe, + 0x6c => 0x8201, 0x6d => 0x8202, 0x6e => 0x8205, 0x6f => 0x8207, + 0x70 => 0x820a, 0x71 => 0x820d, 0x72 => 0x8210, 0x73 => 0x8216, + 0x74 => 0x8229, 0x75 => 0x822b, 0x76 => 0x8238, 0x77 => 0x8233, + 0x78 => 0x8240, 0x79 => 0x8259, 0x7a => 0x8258, 0x7b => 0x825d, + 0x7c => 0x825a, 0x7d => 0x825f, 0x7e => 0x8264, 0x80 => 0x8262, + 0x81 => 0x8268, 0x82 => 0x826a, 0x83 => 0x826b, 0x84 => 0x822e, + 0x85 => 0x8271, 0x86 => 0x8277, 0x87 => 0x8278, 0x88 => 0x827e, + 0x89 => 0x828d, 0x8a => 0x8292, 0x8b => 0x82ab, 0x8c => 0x829f, + 0x8d => 0x82bb, 0x8e => 0x82ac, 0x8f => 0x82e1, 0x90 => 0x82e3, + 0x91 => 0x82df, 0x92 => 0x82d2, 0x93 => 0x82f4, 0x94 => 0x82f3, + 0x95 => 0x82fa, 0x96 => 0x8393, 0x97 => 0x8303, 0x98 => 0x82fb, + 0x99 => 0x82f9, 0x9a => 0x82de, 0x9b => 0x8306, 0x9c => 0x82dc, + 0x9d => 0x8309, 0x9e => 0x82d9, 0x9f => 0x8335, 0xa0 => 0x8334, + 0xa1 => 0x8316, 0xa2 => 0x8332, 0xa3 => 0x8331, 0xa4 => 0x8340, + 0xa5 => 0x8339, 0xa6 => 0x8350, 0xa7 => 0x8345, 0xa8 => 0x832f, + 0xa9 => 0x832b, 0xaa => 0x8317, 0xab => 0x8318, 0xac => 0x8385, + 0xad => 0x839a, 0xae => 0x83aa, 0xaf => 0x839f, 0xb0 => 0x83a2, + 0xb1 => 0x8396, 0xb2 => 0x8323, 0xb3 => 0x838e, 0xb4 => 0x8387, + 0xb5 => 0x838a, 0xb6 => 0x837c, 0xb7 => 0x83b5, 0xb8 => 0x8373, + 0xb9 => 0x8375, 0xba => 0x83a0, 0xbb => 0x8389, 0xbc => 0x83a8, + 0xbd => 0x83f4, 0xbe => 0x8413, 0xbf => 0x83eb, 0xc0 => 0x83ce, + 0xc1 => 0x83fd, 0xc2 => 0x8403, 0xc3 => 0x83d8, 0xc4 => 0x840b, + 0xc5 => 0x83c1, 0xc6 => 0x83f7, 0xc7 => 0x8407, 0xc8 => 0x83e0, + 0xc9 => 0x83f2, 0xca => 0x840d, 0xcb => 0x8422, 0xcc => 0x8420, + 0xcd => 0x83bd, 0xce => 0x8438, 0xcf => 0x8506, 0xd0 => 0x83fb, + 0xd1 => 0x846d, 0xd2 => 0x842a, 0xd3 => 0x843c, 0xd4 => 0x855a, + 0xd5 => 0x8484, 0xd6 => 0x8477, 0xd7 => 0x846b, 0xd8 => 0x84ad, + 0xd9 => 0x846e, 0xda => 0x8482, 0xdb => 0x8469, 0xdc => 0x8446, + 0xdd => 0x842c, 0xde => 0x846f, 0xdf => 0x8479, 0xe0 => 0x8435, + 0xe1 => 0x84ca, 0xe2 => 0x8462, 0xe3 => 0x84b9, 0xe4 => 0x84bf, + 0xe5 => 0x849f, 0xe6 => 0x84d9, 0xe7 => 0x84cd, 0xe8 => 0x84bb, + 0xe9 => 0x84da, 0xea => 0x84d0, 0xeb => 0x84c1, 0xec => 0x84c6, + 0xed => 0x84d6, 0xee => 0x84a1, 0xef => 0x8521, 0xf0 => 0x84ff, + 0xf1 => 0x84f4, 0xf2 => 0x8517, 0xf3 => 0x8518, 0xf4 => 0x852c, + 0xf5 => 0x851f, 0xf6 => 0x8515, 0xf7 => 0x8514, 0xf8 => 0x84fc, + 0xf9 => 0x8540, 0xfa => 0x8563, 0xfb => 0x8558, 0xfc => 0x8548, + }, + 0xe5 => { + 0x40 => 0x8541, 0x41 => 0x8602, 0x42 => 0x854b, 0x43 => 0x8555, + 0x44 => 0x8580, 0x45 => 0x85a4, 0x46 => 0x8588, 0x47 => 0x8591, + 0x48 => 0x858a, 0x49 => 0x85a8, 0x4a => 0x856d, 0x4b => 0x8594, + 0x4c => 0x859b, 0x4d => 0x85ea, 0x4e => 0x8587, 0x4f => 0x859c, + 0x50 => 0x8577, 0x51 => 0x857e, 0x52 => 0x8590, 0x53 => 0x85c9, + 0x54 => 0x85ba, 0x55 => 0x85cf, 0x56 => 0x85b9, 0x57 => 0x85d0, + 0x58 => 0x85d5, 0x59 => 0x85dd, 0x5a => 0x85e5, 0x5b => 0x85dc, + 0x5c => 0x85f9, 0x5d => 0x860a, 0x5e => 0x8613, 0x5f => 0x860b, + 0x60 => 0x85fe, 0x61 => 0x85fa, 0x62 => 0x8606, 0x63 => 0x8622, + 0x64 => 0x861a, 0x65 => 0x8630, 0x66 => 0x863f, 0x67 => 0x864d, + 0x68 => 0x4e55, 0x69 => 0x8654, 0x6a => 0x865f, 0x6b => 0x8667, + 0x6c => 0x8671, 0x6d => 0x8693, 0x6e => 0x86a3, 0x6f => 0x86a9, + 0x70 => 0x86aa, 0x71 => 0x868b, 0x72 => 0x868c, 0x73 => 0x86b6, + 0x74 => 0x86af, 0x75 => 0x86c4, 0x76 => 0x86c6, 0x77 => 0x86b0, + 0x78 => 0x86c9, 0x79 => 0x8823, 0x7a => 0x86ab, 0x7b => 0x86d4, + 0x7c => 0x86de, 0x7d => 0x86e9, 0x7e => 0x86ec, 0x80 => 0x86df, + 0x81 => 0x86db, 0x82 => 0x86ef, 0x83 => 0x8712, 0x84 => 0x8706, + 0x85 => 0x8708, 0x86 => 0x8700, 0x87 => 0x8703, 0x88 => 0x86fb, + 0x89 => 0x8711, 0x8a => 0x8709, 0x8b => 0x870d, 0x8c => 0x86f9, + 0x8d => 0x870a, 0x8e => 0x8734, 0x8f => 0x873f, 0x90 => 0x8737, + 0x91 => 0x873b, 0x92 => 0x8725, 0x93 => 0x8729, 0x94 => 0x871a, + 0x95 => 0x8760, 0x96 => 0x875f, 0x97 => 0x8778, 0x98 => 0x874c, + 0x99 => 0x874e, 0x9a => 0x8774, 0x9b => 0x8757, 0x9c => 0x8768, + 0x9d => 0x876e, 0x9e => 0x8759, 0x9f => 0x8753, 0xa0 => 0x8763, + 0xa1 => 0x876a, 0xa2 => 0x8805, 0xa3 => 0x87a2, 0xa4 => 0x879f, + 0xa5 => 0x8782, 0xa6 => 0x87af, 0xa7 => 0x87cb, 0xa8 => 0x87bd, + 0xa9 => 0x87c0, 0xaa => 0x87d0, 0xab => 0x96d6, 0xac => 0x87ab, + 0xad => 0x87c4, 0xae => 0x87b3, 0xaf => 0x87c7, 0xb0 => 0x87c6, + 0xb1 => 0x87bb, 0xb2 => 0x87ef, 0xb3 => 0x87f2, 0xb4 => 0x87e0, + 0xb5 => 0x880f, 0xb6 => 0x880d, 0xb7 => 0x87fe, 0xb8 => 0x87f6, + 0xb9 => 0x87f7, 0xba => 0x880e, 0xbb => 0x87d2, 0xbc => 0x8811, + 0xbd => 0x8816, 0xbe => 0x8815, 0xbf => 0x8822, 0xc0 => 0x8821, + 0xc1 => 0x8831, 0xc2 => 0x8836, 0xc3 => 0x8839, 0xc4 => 0x8827, + 0xc5 => 0x883b, 0xc6 => 0x8844, 0xc7 => 0x8842, 0xc8 => 0x8852, + 0xc9 => 0x8859, 0xca => 0x885e, 0xcb => 0x8862, 0xcc => 0x886b, + 0xcd => 0x8881, 0xce => 0x887e, 0xcf => 0x889e, 0xd0 => 0x8875, + 0xd1 => 0x887d, 0xd2 => 0x88b5, 0xd3 => 0x8872, 0xd4 => 0x8882, + 0xd5 => 0x8897, 0xd6 => 0x8892, 0xd7 => 0x88ae, 0xd8 => 0x8899, + 0xd9 => 0x88a2, 0xda => 0x888d, 0xdb => 0x88a4, 0xdc => 0x88b0, + 0xdd => 0x88bf, 0xde => 0x88b1, 0xdf => 0x88c3, 0xe0 => 0x88c4, + 0xe1 => 0x88d4, 0xe2 => 0x88d8, 0xe3 => 0x88d9, 0xe4 => 0x88dd, + 0xe5 => 0x88f9, 0xe6 => 0x8902, 0xe7 => 0x88fc, 0xe8 => 0x88f4, + 0xe9 => 0x88e8, 0xea => 0x88f2, 0xeb => 0x8904, 0xec => 0x890c, + 0xed => 0x890a, 0xee => 0x8913, 0xef => 0x8943, 0xf0 => 0x891e, + 0xf1 => 0x8925, 0xf2 => 0x892a, 0xf3 => 0x892b, 0xf4 => 0x8941, + 0xf5 => 0x8944, 0xf6 => 0x893b, 0xf7 => 0x8936, 0xf8 => 0x8938, + 0xf9 => 0x894c, 0xfa => 0x891d, 0xfb => 0x8960, 0xfc => 0x895e, + }, + 0xe6 => { + 0x40 => 0x8966, 0x41 => 0x8964, 0x42 => 0x896d, 0x43 => 0x896a, + 0x44 => 0x896f, 0x45 => 0x8974, 0x46 => 0x8977, 0x47 => 0x897e, + 0x48 => 0x8983, 0x49 => 0x8988, 0x4a => 0x898a, 0x4b => 0x8993, + 0x4c => 0x8998, 0x4d => 0x89a1, 0x4e => 0x89a9, 0x4f => 0x89a6, + 0x50 => 0x89ac, 0x51 => 0x89af, 0x52 => 0x89b2, 0x53 => 0x89ba, + 0x54 => 0x89bd, 0x55 => 0x89bf, 0x56 => 0x89c0, 0x57 => 0x89da, + 0x58 => 0x89dc, 0x59 => 0x89dd, 0x5a => 0x89e7, 0x5b => 0x89f4, + 0x5c => 0x89f8, 0x5d => 0x8a03, 0x5e => 0x8a16, 0x5f => 0x8a10, + 0x60 => 0x8a0c, 0x61 => 0x8a1b, 0x62 => 0x8a1d, 0x63 => 0x8a25, + 0x64 => 0x8a36, 0x65 => 0x8a41, 0x66 => 0x8a5b, 0x67 => 0x8a52, + 0x68 => 0x8a46, 0x69 => 0x8a48, 0x6a => 0x8a7c, 0x6b => 0x8a6d, + 0x6c => 0x8a6c, 0x6d => 0x8a62, 0x6e => 0x8a85, 0x6f => 0x8a82, + 0x70 => 0x8a84, 0x71 => 0x8aa8, 0x72 => 0x8aa1, 0x73 => 0x8a91, + 0x74 => 0x8aa5, 0x75 => 0x8aa6, 0x76 => 0x8a9a, 0x77 => 0x8aa3, + 0x78 => 0x8ac4, 0x79 => 0x8acd, 0x7a => 0x8ac2, 0x7b => 0x8ada, + 0x7c => 0x8aeb, 0x7d => 0x8af3, 0x7e => 0x8ae7, 0x80 => 0x8ae4, + 0x81 => 0x8af1, 0x82 => 0x8b14, 0x83 => 0x8ae0, 0x84 => 0x8ae2, + 0x85 => 0x8af7, 0x86 => 0x8ade, 0x87 => 0x8adb, 0x88 => 0x8b0c, + 0x89 => 0x8b07, 0x8a => 0x8b1a, 0x8b => 0x8ae1, 0x8c => 0x8b16, + 0x8d => 0x8b10, 0x8e => 0x8b17, 0x8f => 0x8b20, 0x90 => 0x8b33, + 0x91 => 0x97ab, 0x92 => 0x8b26, 0x93 => 0x8b2b, 0x94 => 0x8b3e, + 0x95 => 0x8b28, 0x96 => 0x8b41, 0x97 => 0x8b4c, 0x98 => 0x8b4f, + 0x99 => 0x8b4e, 0x9a => 0x8b49, 0x9b => 0x8b56, 0x9c => 0x8b5b, + 0x9d => 0x8b5a, 0x9e => 0x8b6b, 0x9f => 0x8b5f, 0xa0 => 0x8b6c, + 0xa1 => 0x8b6f, 0xa2 => 0x8b74, 0xa3 => 0x8b7d, 0xa4 => 0x8b80, + 0xa5 => 0x8b8c, 0xa6 => 0x8b8e, 0xa7 => 0x8b92, 0xa8 => 0x8b93, + 0xa9 => 0x8b96, 0xaa => 0x8b99, 0xab => 0x8b9a, 0xac => 0x8c3a, + 0xad => 0x8c41, 0xae => 0x8c3f, 0xaf => 0x8c48, 0xb0 => 0x8c4c, + 0xb1 => 0x8c4e, 0xb2 => 0x8c50, 0xb3 => 0x8c55, 0xb4 => 0x8c62, + 0xb5 => 0x8c6c, 0xb6 => 0x8c78, 0xb7 => 0x8c7a, 0xb8 => 0x8c82, + 0xb9 => 0x8c89, 0xba => 0x8c85, 0xbb => 0x8c8a, 0xbc => 0x8c8d, + 0xbd => 0x8c8e, 0xbe => 0x8c94, 0xbf => 0x8c7c, 0xc0 => 0x8c98, + 0xc1 => 0x621d, 0xc2 => 0x8cad, 0xc3 => 0x8caa, 0xc4 => 0x8cbd, + 0xc5 => 0x8cb2, 0xc6 => 0x8cb3, 0xc7 => 0x8cae, 0xc8 => 0x8cb6, + 0xc9 => 0x8cc8, 0xca => 0x8cc1, 0xcb => 0x8ce4, 0xcc => 0x8ce3, + 0xcd => 0x8cda, 0xce => 0x8cfd, 0xcf => 0x8cfa, 0xd0 => 0x8cfb, + 0xd1 => 0x8d04, 0xd2 => 0x8d05, 0xd3 => 0x8d0a, 0xd4 => 0x8d07, + 0xd5 => 0x8d0f, 0xd6 => 0x8d0d, 0xd7 => 0x8d10, 0xd8 => 0x9f4e, + 0xd9 => 0x8d13, 0xda => 0x8ccd, 0xdb => 0x8d14, 0xdc => 0x8d16, + 0xdd => 0x8d67, 0xde => 0x8d6d, 0xdf => 0x8d71, 0xe0 => 0x8d73, + 0xe1 => 0x8d81, 0xe2 => 0x8d99, 0xe3 => 0x8dc2, 0xe4 => 0x8dbe, + 0xe5 => 0x8dba, 0xe6 => 0x8dcf, 0xe7 => 0x8dda, 0xe8 => 0x8dd6, + 0xe9 => 0x8dcc, 0xea => 0x8ddb, 0xeb => 0x8dcb, 0xec => 0x8dea, + 0xed => 0x8deb, 0xee => 0x8ddf, 0xef => 0x8de3, 0xf0 => 0x8dfc, + 0xf1 => 0x8e08, 0xf2 => 0x8e09, 0xf3 => 0x8dff, 0xf4 => 0x8e1d, + 0xf5 => 0x8e1e, 0xf6 => 0x8e10, 0xf7 => 0x8e1f, 0xf8 => 0x8e42, + 0xf9 => 0x8e35, 0xfa => 0x8e30, 0xfb => 0x8e34, 0xfc => 0x8e4a, + }, + 0xe7 => { + 0x40 => 0x8e47, 0x41 => 0x8e49, 0x42 => 0x8e4c, 0x43 => 0x8e50, + 0x44 => 0x8e48, 0x45 => 0x8e59, 0x46 => 0x8e64, 0x47 => 0x8e60, + 0x48 => 0x8e2a, 0x49 => 0x8e63, 0x4a => 0x8e55, 0x4b => 0x8e76, + 0x4c => 0x8e72, 0x4d => 0x8e7c, 0x4e => 0x8e81, 0x4f => 0x8e87, + 0x50 => 0x8e85, 0x51 => 0x8e84, 0x52 => 0x8e8b, 0x53 => 0x8e8a, + 0x54 => 0x8e93, 0x55 => 0x8e91, 0x56 => 0x8e94, 0x57 => 0x8e99, + 0x58 => 0x8eaa, 0x59 => 0x8ea1, 0x5a => 0x8eac, 0x5b => 0x8eb0, + 0x5c => 0x8ec6, 0x5d => 0x8eb1, 0x5e => 0x8ebe, 0x5f => 0x8ec5, + 0x60 => 0x8ec8, 0x61 => 0x8ecb, 0x62 => 0x8edb, 0x63 => 0x8ee3, + 0x64 => 0x8efc, 0x65 => 0x8efb, 0x66 => 0x8eeb, 0x67 => 0x8efe, + 0x68 => 0x8f0a, 0x69 => 0x8f05, 0x6a => 0x8f15, 0x6b => 0x8f12, + 0x6c => 0x8f19, 0x6d => 0x8f13, 0x6e => 0x8f1c, 0x6f => 0x8f1f, + 0x70 => 0x8f1b, 0x71 => 0x8f0c, 0x72 => 0x8f26, 0x73 => 0x8f33, + 0x74 => 0x8f3b, 0x75 => 0x8f39, 0x76 => 0x8f45, 0x77 => 0x8f42, + 0x78 => 0x8f3e, 0x79 => 0x8f4c, 0x7a => 0x8f49, 0x7b => 0x8f46, + 0x7c => 0x8f4e, 0x7d => 0x8f57, 0x7e => 0x8f5c, 0x80 => 0x8f62, + 0x81 => 0x8f63, 0x82 => 0x8f64, 0x83 => 0x8f9c, 0x84 => 0x8f9f, + 0x85 => 0x8fa3, 0x86 => 0x8fad, 0x87 => 0x8faf, 0x88 => 0x8fb7, + 0x89 => 0x8fda, 0x8a => 0x8fe5, 0x8b => 0x8fe2, 0x8c => 0x8fea, + 0x8d => 0x8fef, 0x8e => 0x9087, 0x8f => 0x8ff4, 0x90 => 0x9005, + 0x91 => 0x8ff9, 0x92 => 0x8ffa, 0x93 => 0x9011, 0x94 => 0x9015, + 0x95 => 0x9021, 0x96 => 0x900d, 0x97 => 0x901e, 0x98 => 0x9016, + 0x99 => 0x900b, 0x9a => 0x9027, 0x9b => 0x9036, 0x9c => 0x9035, + 0x9d => 0x9039, 0x9e => 0x8ff8, 0x9f => 0x904f, 0xa0 => 0x9050, + 0xa1 => 0x9051, 0xa2 => 0x9052, 0xa3 => 0x900e, 0xa4 => 0x9049, + 0xa5 => 0x903e, 0xa6 => 0x9056, 0xa7 => 0x9058, 0xa8 => 0x905e, + 0xa9 => 0x9068, 0xaa => 0x906f, 0xab => 0x9076, 0xac => 0x96a8, + 0xad => 0x9072, 0xae => 0x9082, 0xaf => 0x907d, 0xb0 => 0x9081, + 0xb1 => 0x9080, 0xb2 => 0x908a, 0xb3 => 0x9089, 0xb4 => 0x908f, + 0xb5 => 0x90a8, 0xb6 => 0x90af, 0xb7 => 0x90b1, 0xb8 => 0x90b5, + 0xb9 => 0x90e2, 0xba => 0x90e4, 0xbb => 0x6248, 0xbc => 0x90db, + 0xbd => 0x9102, 0xbe => 0x9112, 0xbf => 0x9119, 0xc0 => 0x9132, + 0xc1 => 0x9130, 0xc2 => 0x914a, 0xc3 => 0x9156, 0xc4 => 0x9158, + 0xc5 => 0x9163, 0xc6 => 0x9165, 0xc7 => 0x9169, 0xc8 => 0x9173, + 0xc9 => 0x9172, 0xca => 0x918b, 0xcb => 0x9189, 0xcc => 0x9182, + 0xcd => 0x91a2, 0xce => 0x91ab, 0xcf => 0x91af, 0xd0 => 0x91aa, + 0xd1 => 0x91b5, 0xd2 => 0x91b4, 0xd3 => 0x91ba, 0xd4 => 0x91c0, + 0xd5 => 0x91c1, 0xd6 => 0x91c9, 0xd7 => 0x91cb, 0xd8 => 0x91d0, + 0xd9 => 0x91d6, 0xda => 0x91df, 0xdb => 0x91e1, 0xdc => 0x91db, + 0xdd => 0x91fc, 0xde => 0x91f5, 0xdf => 0x91f6, 0xe0 => 0x921e, + 0xe1 => 0x91ff, 0xe2 => 0x9214, 0xe3 => 0x922c, 0xe4 => 0x9215, + 0xe5 => 0x9211, 0xe6 => 0x925e, 0xe7 => 0x9257, 0xe8 => 0x9245, + 0xe9 => 0x9249, 0xea => 0x9264, 0xeb => 0x9248, 0xec => 0x9295, + 0xed => 0x923f, 0xee => 0x924b, 0xef => 0x9250, 0xf0 => 0x929c, + 0xf1 => 0x9296, 0xf2 => 0x9293, 0xf3 => 0x929b, 0xf4 => 0x925a, + 0xf5 => 0x92cf, 0xf6 => 0x92b9, 0xf7 => 0x92b7, 0xf8 => 0x92e9, + 0xf9 => 0x930f, 0xfa => 0x92fa, 0xfb => 0x9344, 0xfc => 0x932e, + }, + 0xe8 => { + 0x40 => 0x9319, 0x41 => 0x9322, 0x42 => 0x931a, 0x43 => 0x9323, + 0x44 => 0x933a, 0x45 => 0x9335, 0x46 => 0x933b, 0x47 => 0x935c, + 0x48 => 0x9360, 0x49 => 0x937c, 0x4a => 0x936e, 0x4b => 0x9356, + 0x4c => 0x93b0, 0x4d => 0x93ac, 0x4e => 0x93ad, 0x4f => 0x9394, + 0x50 => 0x93b9, 0x51 => 0x93d6, 0x52 => 0x93d7, 0x53 => 0x93e8, + 0x54 => 0x93e5, 0x55 => 0x93d8, 0x56 => 0x93c3, 0x57 => 0x93dd, + 0x58 => 0x93d0, 0x59 => 0x93c8, 0x5a => 0x93e4, 0x5b => 0x941a, + 0x5c => 0x9414, 0x5d => 0x9413, 0x5e => 0x9403, 0x5f => 0x9407, + 0x60 => 0x9410, 0x61 => 0x9436, 0x62 => 0x942b, 0x63 => 0x9435, + 0x64 => 0x9421, 0x65 => 0x943a, 0x66 => 0x9441, 0x67 => 0x9452, + 0x68 => 0x9444, 0x69 => 0x945b, 0x6a => 0x9460, 0x6b => 0x9462, + 0x6c => 0x945e, 0x6d => 0x946a, 0x6e => 0x9229, 0x6f => 0x9470, + 0x70 => 0x9475, 0x71 => 0x9477, 0x72 => 0x947d, 0x73 => 0x945a, + 0x74 => 0x947c, 0x75 => 0x947e, 0x76 => 0x9481, 0x77 => 0x947f, + 0x78 => 0x9582, 0x79 => 0x9587, 0x7a => 0x958a, 0x7b => 0x9594, + 0x7c => 0x9596, 0x7d => 0x9598, 0x7e => 0x9599, 0x80 => 0x95a0, + 0x81 => 0x95a8, 0x82 => 0x95a7, 0x83 => 0x95ad, 0x84 => 0x95bc, + 0x85 => 0x95bb, 0x86 => 0x95b9, 0x87 => 0x95be, 0x88 => 0x95ca, + 0x89 => 0x6ff6, 0x8a => 0x95c3, 0x8b => 0x95cd, 0x8c => 0x95cc, + 0x8d => 0x95d5, 0x8e => 0x95d4, 0x8f => 0x95d6, 0x90 => 0x95dc, + 0x91 => 0x95e1, 0x92 => 0x95e5, 0x93 => 0x95e2, 0x94 => 0x9621, + 0x95 => 0x9628, 0x96 => 0x962e, 0x97 => 0x962f, 0x98 => 0x9642, + 0x99 => 0x964c, 0x9a => 0x964f, 0x9b => 0x964b, 0x9c => 0x9677, + 0x9d => 0x965c, 0x9e => 0x965e, 0x9f => 0x965d, 0xa0 => 0x965f, + 0xa1 => 0x9666, 0xa2 => 0x9672, 0xa3 => 0x966c, 0xa4 => 0x968d, + 0xa5 => 0x9698, 0xa6 => 0x9695, 0xa7 => 0x9697, 0xa8 => 0x96aa, + 0xa9 => 0x96a7, 0xaa => 0x96b1, 0xab => 0x96b2, 0xac => 0x96b0, + 0xad => 0x96b4, 0xae => 0x96b6, 0xaf => 0x96b8, 0xb0 => 0x96b9, + 0xb1 => 0x96ce, 0xb2 => 0x96cb, 0xb3 => 0x96c9, 0xb4 => 0x96cd, + 0xb5 => 0x894d, 0xb6 => 0x96dc, 0xb7 => 0x970d, 0xb8 => 0x96d5, + 0xb9 => 0x96f9, 0xba => 0x9704, 0xbb => 0x9706, 0xbc => 0x9708, + 0xbd => 0x9713, 0xbe => 0x970e, 0xbf => 0x9711, 0xc0 => 0x970f, + 0xc1 => 0x9716, 0xc2 => 0x9719, 0xc3 => 0x9724, 0xc4 => 0x972a, + 0xc5 => 0x9730, 0xc6 => 0x9739, 0xc7 => 0x973d, 0xc8 => 0x973e, + 0xc9 => 0x9744, 0xca => 0x9746, 0xcb => 0x9748, 0xcc => 0x9742, + 0xcd => 0x9749, 0xce => 0x975c, 0xcf => 0x9760, 0xd0 => 0x9764, + 0xd1 => 0x9766, 0xd2 => 0x9768, 0xd3 => 0x52d2, 0xd4 => 0x976b, + 0xd5 => 0x9771, 0xd6 => 0x9779, 0xd7 => 0x9785, 0xd8 => 0x977c, + 0xd9 => 0x9781, 0xda => 0x977a, 0xdb => 0x9786, 0xdc => 0x978b, + 0xdd => 0x978f, 0xde => 0x9790, 0xdf => 0x979c, 0xe0 => 0x97a8, + 0xe1 => 0x97a6, 0xe2 => 0x97a3, 0xe3 => 0x97b3, 0xe4 => 0x97b4, + 0xe5 => 0x97c3, 0xe6 => 0x97c6, 0xe7 => 0x97c8, 0xe8 => 0x97cb, + 0xe9 => 0x97dc, 0xea => 0x97ed, 0xeb => 0x9f4f, 0xec => 0x97f2, + 0xed => 0x7adf, 0xee => 0x97f6, 0xef => 0x97f5, 0xf0 => 0x980f, + 0xf1 => 0x980c, 0xf2 => 0x9838, 0xf3 => 0x9824, 0xf4 => 0x9821, + 0xf5 => 0x9837, 0xf6 => 0x983d, 0xf7 => 0x9846, 0xf8 => 0x984f, + 0xf9 => 0x984b, 0xfa => 0x986b, 0xfb => 0x986f, 0xfc => 0x9870, + }, + 0xe9 => { + 0x40 => 0x9871, 0x41 => 0x9874, 0x42 => 0x9873, 0x43 => 0x98aa, + 0x44 => 0x98af, 0x45 => 0x98b1, 0x46 => 0x98b6, 0x47 => 0x98c4, + 0x48 => 0x98c3, 0x49 => 0x98c6, 0x4a => 0x98e9, 0x4b => 0x98eb, + 0x4c => 0x9903, 0x4d => 0x9909, 0x4e => 0x9912, 0x4f => 0x9914, + 0x50 => 0x9918, 0x51 => 0x9921, 0x52 => 0x991d, 0x53 => 0x991e, + 0x54 => 0x9924, 0x55 => 0x9920, 0x56 => 0x992c, 0x57 => 0x992e, + 0x58 => 0x993d, 0x59 => 0x993e, 0x5a => 0x9942, 0x5b => 0x9949, + 0x5c => 0x9945, 0x5d => 0x9950, 0x5e => 0x994b, 0x5f => 0x9951, + 0x60 => 0x9952, 0x61 => 0x994c, 0x62 => 0x9955, 0x63 => 0x9997, + 0x64 => 0x9998, 0x65 => 0x99a5, 0x66 => 0x99ad, 0x67 => 0x99ae, + 0x68 => 0x99bc, 0x69 => 0x99df, 0x6a => 0x99db, 0x6b => 0x99dd, + 0x6c => 0x99d8, 0x6d => 0x99d1, 0x6e => 0x99ed, 0x6f => 0x99ee, + 0x70 => 0x99f1, 0x71 => 0x99f2, 0x72 => 0x99fb, 0x73 => 0x99f8, + 0x74 => 0x9a01, 0x75 => 0x9a0f, 0x76 => 0x9a05, 0x77 => 0x99e2, + 0x78 => 0x9a19, 0x79 => 0x9a2b, 0x7a => 0x9a37, 0x7b => 0x9a45, + 0x7c => 0x9a42, 0x7d => 0x9a40, 0x7e => 0x9a43, 0x80 => 0x9a3e, + 0x81 => 0x9a55, 0x82 => 0x9a4d, 0x83 => 0x9a5b, 0x84 => 0x9a57, + 0x85 => 0x9a5f, 0x86 => 0x9a62, 0x87 => 0x9a65, 0x88 => 0x9a64, + 0x89 => 0x9a69, 0x8a => 0x9a6b, 0x8b => 0x9a6a, 0x8c => 0x9aad, + 0x8d => 0x9ab0, 0x8e => 0x9abc, 0x8f => 0x9ac0, 0x90 => 0x9acf, + 0x91 => 0x9ad1, 0x92 => 0x9ad3, 0x93 => 0x9ad4, 0x94 => 0x9ade, + 0x95 => 0x9adf, 0x96 => 0x9ae2, 0x97 => 0x9ae3, 0x98 => 0x9ae6, + 0x99 => 0x9aef, 0x9a => 0x9aeb, 0x9b => 0x9aee, 0x9c => 0x9af4, + 0x9d => 0x9af1, 0x9e => 0x9af7, 0x9f => 0x9afb, 0xa0 => 0x9b06, + 0xa1 => 0x9b18, 0xa2 => 0x9b1a, 0xa3 => 0x9b1f, 0xa4 => 0x9b22, + 0xa5 => 0x9b23, 0xa6 => 0x9b25, 0xa7 => 0x9b27, 0xa8 => 0x9b28, + 0xa9 => 0x9b29, 0xaa => 0x9b2a, 0xab => 0x9b2e, 0xac => 0x9b2f, + 0xad => 0x9b32, 0xae => 0x9b44, 0xaf => 0x9b43, 0xb0 => 0x9b4f, + 0xb1 => 0x9b4d, 0xb2 => 0x9b4e, 0xb3 => 0x9b51, 0xb4 => 0x9b58, + 0xb5 => 0x9b74, 0xb6 => 0x9b93, 0xb7 => 0x9b83, 0xb8 => 0x9b91, + 0xb9 => 0x9b96, 0xba => 0x9b97, 0xbb => 0x9b9f, 0xbc => 0x9ba0, + 0xbd => 0x9ba8, 0xbe => 0x9bb4, 0xbf => 0x9bc0, 0xc0 => 0x9bca, + 0xc1 => 0x9bb9, 0xc2 => 0x9bc6, 0xc3 => 0x9bcf, 0xc4 => 0x9bd1, + 0xc5 => 0x9bd2, 0xc6 => 0x9be3, 0xc7 => 0x9be2, 0xc8 => 0x9be4, + 0xc9 => 0x9bd4, 0xca => 0x9be1, 0xcb => 0x9c3a, 0xcc => 0x9bf2, + 0xcd => 0x9bf1, 0xce => 0x9bf0, 0xcf => 0x9c15, 0xd0 => 0x9c14, + 0xd1 => 0x9c09, 0xd2 => 0x9c13, 0xd3 => 0x9c0c, 0xd4 => 0x9c06, + 0xd5 => 0x9c08, 0xd6 => 0x9c12, 0xd7 => 0x9c0a, 0xd8 => 0x9c04, + 0xd9 => 0x9c2e, 0xda => 0x9c1b, 0xdb => 0x9c25, 0xdc => 0x9c24, + 0xdd => 0x9c21, 0xde => 0x9c30, 0xdf => 0x9c47, 0xe0 => 0x9c32, + 0xe1 => 0x9c46, 0xe2 => 0x9c3e, 0xe3 => 0x9c5a, 0xe4 => 0x9c60, + 0xe5 => 0x9c67, 0xe6 => 0x9c76, 0xe7 => 0x9c78, 0xe8 => 0x9ce7, + 0xe9 => 0x9cec, 0xea => 0x9cf0, 0xeb => 0x9d09, 0xec => 0x9d08, + 0xed => 0x9ceb, 0xee => 0x9d03, 0xef => 0x9d06, 0xf0 => 0x9d2a, + 0xf1 => 0x9d26, 0xf2 => 0x9daf, 0xf3 => 0x9d23, 0xf4 => 0x9d1f, + 0xf5 => 0x9d44, 0xf6 => 0x9d15, 0xf7 => 0x9d12, 0xf8 => 0x9d41, + 0xf9 => 0x9d3f, 0xfa => 0x9d3e, 0xfb => 0x9d46, 0xfc => 0x9d48, + }, + 0xea => { + 0x40 => 0x9d5d, 0x41 => 0x9d5e, 0x42 => 0x9d64, 0x43 => 0x9d51, + 0x44 => 0x9d50, 0x45 => 0x9d59, 0x46 => 0x9d72, 0x47 => 0x9d89, + 0x48 => 0x9d87, 0x49 => 0x9dab, 0x4a => 0x9d6f, 0x4b => 0x9d7a, + 0x4c => 0x9d9a, 0x4d => 0x9da4, 0x4e => 0x9da9, 0x4f => 0x9db2, + 0x50 => 0x9dc4, 0x51 => 0x9dc1, 0x52 => 0x9dbb, 0x53 => 0x9db8, + 0x54 => 0x9dba, 0x55 => 0x9dc6, 0x56 => 0x9dcf, 0x57 => 0x9dc2, + 0x58 => 0x9dd9, 0x59 => 0x9dd3, 0x5a => 0x9df8, 0x5b => 0x9de6, + 0x5c => 0x9ded, 0x5d => 0x9def, 0x5e => 0x9dfd, 0x5f => 0x9e1a, + 0x60 => 0x9e1b, 0x61 => 0x9e1e, 0x62 => 0x9e75, 0x63 => 0x9e79, + 0x64 => 0x9e7d, 0x65 => 0x9e81, 0x66 => 0x9e88, 0x67 => 0x9e8b, + 0x68 => 0x9e8c, 0x69 => 0x9e92, 0x6a => 0x9e95, 0x6b => 0x9e91, + 0x6c => 0x9e9d, 0x6d => 0x9ea5, 0x6e => 0x9ea9, 0x6f => 0x9eb8, + 0x70 => 0x9eaa, 0x71 => 0x9ead, 0x72 => 0x9761, 0x73 => 0x9ecc, + 0x74 => 0x9ece, 0x75 => 0x9ecf, 0x76 => 0x9ed0, 0x77 => 0x9ed4, + 0x78 => 0x9edc, 0x79 => 0x9ede, 0x7a => 0x9edd, 0x7b => 0x9ee0, + 0x7c => 0x9ee5, 0x7d => 0x9ee8, 0x7e => 0x9eef, 0x80 => 0x9ef4, + 0x81 => 0x9ef6, 0x82 => 0x9ef7, 0x83 => 0x9ef9, 0x84 => 0x9efb, + 0x85 => 0x9efc, 0x86 => 0x9efd, 0x87 => 0x9f07, 0x88 => 0x9f08, + 0x89 => 0x76b7, 0x8a => 0x9f15, 0x8b => 0x9f21, 0x8c => 0x9f2c, + 0x8d => 0x9f3e, 0x8e => 0x9f4a, 0x8f => 0x9f52, 0x90 => 0x9f54, + 0x91 => 0x9f63, 0x92 => 0x9f5f, 0x93 => 0x9f60, 0x94 => 0x9f61, + 0x95 => 0x9f66, 0x96 => 0x9f67, 0x97 => 0x9f6c, 0x98 => 0x9f6a, + 0x99 => 0x9f77, 0x9a => 0x9f72, 0x9b => 0x9f76, 0x9c => 0x9f95, + 0x9d => 0x9f9c, 0x9e => 0x9fa0, 0x9f => 0x582f, 0xa0 => 0x69c7, + 0xa1 => 0x9059, 0xa2 => 0x7464, 0xa3 => 0x51dc, 0xa4 => 0x7199, + }, +); + +1; # end diff --git a/lib/Image/ExifTool/Charset/Symbol.pm b/lib/Image/ExifTool/Charset/Symbol.pm new file mode 100644 index 0000000..cb240ef --- /dev/null +++ b/lib/Image/ExifTool/Charset/Symbol.pm @@ -0,0 +1,54 @@ +#------------------------------------------------------------------------------ +# File: Symbol.pm +# +# Description: Symbol to Unicode +# +# Revisions: 2010/01/20 - P. Harvey created +# +# References: 1) http://blogs.msdn.com/michkap/archive/2005/11/08/490495.aspx +# +# Notes: The table omits 1-byte characters with the same values as Unicode. +# This set re-maps characters with codepoints less than 0x80 +# (Although all bytes >= 0x20 should be mapped according to the +# reference, I didn't map chars below 0x80 because I have some +# samples where these are regular ASCII characters, even though +# I think the encoding is probably incorrect for these samples) +#------------------------------------------------------------------------------ +use strict; + +%Image::ExifTool::Charset::Symbol = ( + 0x80 => 0xf080, 0x81 => 0xf081, 0x82 => 0xf082, 0x83 => 0xf083, + 0x84 => 0xf084, 0x85 => 0xf085, 0x86 => 0xf086, 0x87 => 0xf087, + 0x88 => 0xf088, 0x89 => 0xf089, 0x8a => 0xf08a, 0x8b => 0xf08b, + 0x8c => 0xf08c, 0x8d => 0xf08d, 0x8e => 0xf08e, 0x8f => 0xf08f, + 0x90 => 0xf090, 0x91 => 0xf091, 0x92 => 0xf092, 0x93 => 0xf093, + 0x94 => 0xf094, 0x95 => 0xf095, 0x96 => 0xf096, 0x97 => 0xf097, + 0x98 => 0xf098, 0x99 => 0xf099, 0x9a => 0xf09a, 0x9b => 0xf09b, + 0x9c => 0xf09c, 0x9d => 0xf09d, 0x9e => 0xf09e, 0x9f => 0xf09f, + 0xa0 => 0xf0a0, 0xa1 => 0xf0a1, 0xa2 => 0xf0a2, 0xa3 => 0xf0a3, + 0xa4 => 0xf0a4, 0xa5 => 0xf0a5, 0xa6 => 0xf0a6, 0xa7 => 0xf0a7, + 0xa8 => 0xf0a8, 0xa9 => 0xf0a9, 0xaa => 0xf0aa, 0xab => 0xf0ab, + 0xac => 0xf0ac, 0xad => 0xf0ad, 0xae => 0xf0ae, 0xaf => 0xf0af, + 0xb0 => 0xf0b0, 0xb1 => 0xf0b1, 0xb2 => 0xf0b2, 0xb3 => 0xf0b3, + 0xb4 => 0xf0b4, 0xb5 => 0xf0b5, 0xb6 => 0xf0b6, 0xb7 => 0xf0b7, + 0xb8 => 0xf0b8, 0xb9 => 0xf0b9, 0xba => 0xf0ba, 0xbb => 0xf0bb, + 0xbc => 0xf0bc, 0xbd => 0xf0bd, 0xbe => 0xf0be, 0xbf => 0xf0bf, + 0xc0 => 0xf0c0, 0xc1 => 0xf0c1, 0xc2 => 0xf0c2, 0xc3 => 0xf0c3, + 0xc4 => 0xf0c4, 0xc5 => 0xf0c5, 0xc6 => 0xf0c6, 0xc7 => 0xf0c7, + 0xc8 => 0xf0c8, 0xc9 => 0xf0c9, 0xca => 0xf0ca, 0xcb => 0xf0cb, + 0xcc => 0xf0cc, 0xcd => 0xf0cd, 0xce => 0xf0ce, 0xcf => 0xf0cf, + 0xd0 => 0xf0d0, 0xd1 => 0xf0d1, 0xd2 => 0xf0d2, 0xd3 => 0xf0d3, + 0xd4 => 0xf0d4, 0xd5 => 0xf0d5, 0xd6 => 0xf0d6, 0xd7 => 0xf0d7, + 0xd8 => 0xf0d8, 0xd9 => 0xf0d9, 0xda => 0xf0da, 0xdb => 0xf0db, + 0xdc => 0xf0dc, 0xdd => 0xf0dd, 0xde => 0xf0de, 0xdf => 0xf0df, + 0xe0 => 0xf0e0, 0xe1 => 0xf0e1, 0xe2 => 0xf0e2, 0xe3 => 0xf0e3, + 0xe4 => 0xf0e4, 0xe5 => 0xf0e5, 0xe6 => 0xf0e6, 0xe7 => 0xf0e7, + 0xe8 => 0xf0e8, 0xe9 => 0xf0e9, 0xea => 0xf0ea, 0xeb => 0xf0eb, + 0xec => 0xf0ec, 0xed => 0xf0ed, 0xee => 0xf0ee, 0xef => 0xf0ef, + 0xf0 => 0xf0f0, 0xf1 => 0xf0f1, 0xf2 => 0xf0f2, 0xf3 => 0xf0f3, + 0xf4 => 0xf0f4, 0xf5 => 0xf0f5, 0xf6 => 0xf0f6, 0xf7 => 0xf0f7, + 0xf8 => 0xf0f8, 0xf9 => 0xf0f9, 0xfa => 0xf0fa, 0xfb => 0xf0fb, + 0xfc => 0xf0fc, 0xfd => 0xf0fd, 0xfe => 0xf0fe, 0xff => 0xf0ff, +); + +1; # end diff --git a/lib/Image/ExifTool/Charset/Thai.pm b/lib/Image/ExifTool/Charset/Thai.pm new file mode 100644 index 0000000..068018e --- /dev/null +++ b/lib/Image/ExifTool/Charset/Thai.pm @@ -0,0 +1,41 @@ +#------------------------------------------------------------------------------ +# File: Thai.pm +# +# Description: cp874 to Unicode +# +# Revisions: 2010/01/20 - P. Harvey created +# +# References: 1) http://unicode.org/Public/MAPPINGS/VENDORS/MICSFT/WINDOWS/CP874.TXT +# +# Notes: The table omits 1-byte characters with the same values as Unicode +#------------------------------------------------------------------------------ +use strict; + +%Image::ExifTool::Charset::Thai = ( + 0x80 => 0x20ac, 0x85 => 0x2026, 0x91 => 0x2018, 0x92 => 0x2019, + 0x93 => 0x201c, 0x94 => 0x201d, 0x95 => 0x2022, 0x96 => 0x2013, + 0x97 => 0x2014, 0xa1 => 0x0e01, 0xa2 => 0x0e02, 0xa3 => 0x0e03, + 0xa4 => 0x0e04, 0xa5 => 0x0e05, 0xa6 => 0x0e06, 0xa7 => 0x0e07, + 0xa8 => 0x0e08, 0xa9 => 0x0e09, 0xaa => 0x0e0a, 0xab => 0x0e0b, + 0xac => 0x0e0c, 0xad => 0x0e0d, 0xae => 0x0e0e, 0xaf => 0x0e0f, + 0xb0 => 0x0e10, 0xb1 => 0x0e11, 0xb2 => 0x0e12, 0xb3 => 0x0e13, + 0xb4 => 0x0e14, 0xb5 => 0x0e15, 0xb6 => 0x0e16, 0xb7 => 0x0e17, + 0xb8 => 0x0e18, 0xb9 => 0x0e19, 0xba => 0x0e1a, 0xbb => 0x0e1b, + 0xbc => 0x0e1c, 0xbd => 0x0e1d, 0xbe => 0x0e1e, 0xbf => 0x0e1f, + 0xc0 => 0x0e20, 0xc1 => 0x0e21, 0xc2 => 0x0e22, 0xc3 => 0x0e23, + 0xc4 => 0x0e24, 0xc5 => 0x0e25, 0xc6 => 0x0e26, 0xc7 => 0x0e27, + 0xc8 => 0x0e28, 0xc9 => 0x0e29, 0xca => 0x0e2a, 0xcb => 0x0e2b, + 0xcc => 0x0e2c, 0xcd => 0x0e2d, 0xce => 0x0e2e, 0xcf => 0x0e2f, + 0xd0 => 0x0e30, 0xd1 => 0x0e31, 0xd2 => 0x0e32, 0xd3 => 0x0e33, + 0xd4 => 0x0e34, 0xd5 => 0x0e35, 0xd6 => 0x0e36, 0xd7 => 0x0e37, + 0xd8 => 0x0e38, 0xd9 => 0x0e39, 0xda => 0x0e3a, 0xdf => 0x0e3f, + 0xe0 => 0x0e40, 0xe1 => 0x0e41, 0xe2 => 0x0e42, 0xe3 => 0x0e43, + 0xe4 => 0x0e44, 0xe5 => 0x0e45, 0xe6 => 0x0e46, 0xe7 => 0x0e47, + 0xe8 => 0x0e48, 0xe9 => 0x0e49, 0xea => 0x0e4a, 0xeb => 0x0e4b, + 0xec => 0x0e4c, 0xed => 0x0e4d, 0xee => 0x0e4e, 0xef => 0x0e4f, + 0xf0 => 0x0e50, 0xf1 => 0x0e51, 0xf2 => 0x0e52, 0xf3 => 0x0e53, + 0xf4 => 0x0e54, 0xf5 => 0x0e55, 0xf6 => 0x0e56, 0xf7 => 0x0e57, + 0xf8 => 0x0e58, 0xf9 => 0x0e59, 0xfa => 0x0e5a, 0xfb => 0x0e5b, +); + +1; # end diff --git a/lib/Image/ExifTool/Charset/Turkish.pm b/lib/Image/ExifTool/Charset/Turkish.pm new file mode 100644 index 0000000..7f0a784 --- /dev/null +++ b/lib/Image/ExifTool/Charset/Turkish.pm @@ -0,0 +1,25 @@ +#------------------------------------------------------------------------------ +# File: Turkish.pm +# +# Description: cp1254 to Unicode +# +# Revisions: 2010/01/20 - P. Harvey created +# +# References: 1) http://unicode.org/Public/MAPPINGS/VENDORS/MICSFT/WINDOWS/CP1254.TXT +# +# Notes: The table omits 1-byte characters with the same values as Unicode +#------------------------------------------------------------------------------ +use strict; + +%Image::ExifTool::Charset::Turkish = ( + 0x80 => 0x20ac, 0x82 => 0x201a, 0x83 => 0x0192, 0x84 => 0x201e, + 0x85 => 0x2026, 0x86 => 0x2020, 0x87 => 0x2021, 0x88 => 0x02c6, + 0x89 => 0x2030, 0x8a => 0x0160, 0x8b => 0x2039, 0x8c => 0x0152, + 0x91 => 0x2018, 0x92 => 0x2019, 0x93 => 0x201c, 0x94 => 0x201d, + 0x95 => 0x2022, 0x96 => 0x2013, 0x97 => 0x2014, 0x98 => 0x02dc, + 0x99 => 0x2122, 0x9a => 0x0161, 0x9b => 0x203a, 0x9c => 0x0153, + 0x9f => 0x0178, 0xd0 => 0x011e, 0xdd => 0x0130, 0xde => 0x015e, + 0xf0 => 0x011f, 0xfd => 0x0131, 0xfe => 0x015f, +); + +1; # end diff --git a/lib/Image/ExifTool/Charset/Vietnam.pm b/lib/Image/ExifTool/Charset/Vietnam.pm new file mode 100644 index 0000000..6275ea5 --- /dev/null +++ b/lib/Image/ExifTool/Charset/Vietnam.pm @@ -0,0 +1,27 @@ +#------------------------------------------------------------------------------ +# File: Vietnam.pm +# +# Description: cp1258 to Unicode +# +# Revisions: 2010/01/20 - P. Harvey created +# +# References: 1) http://unicode.org/Public/MAPPINGS/VENDORS/MICSFT/WINDOWS/CP1258.TXT +# +# Notes: The table omits 1-byte characters with the same values as Unicode +#------------------------------------------------------------------------------ +use strict; + +%Image::ExifTool::Charset::Vietnam = ( + 0x80 => 0x20ac, 0x82 => 0x201a, 0x83 => 0x0192, 0x84 => 0x201e, + 0x85 => 0x2026, 0x86 => 0x2020, 0x87 => 0x2021, 0x88 => 0x02c6, + 0x89 => 0x2030, 0x8b => 0x2039, 0x8c => 0x0152, 0x91 => 0x2018, + 0x92 => 0x2019, 0x93 => 0x201c, 0x94 => 0x201d, 0x95 => 0x2022, + 0x96 => 0x2013, 0x97 => 0x2014, 0x98 => 0x02dc, 0x99 => 0x2122, + 0x9b => 0x203a, 0x9c => 0x0153, 0x9f => 0x0178, 0xc3 => 0x0102, + 0xcc => 0x0300, 0xd0 => 0x0110, 0xd2 => 0x0309, 0xd5 => 0x01a0, + 0xdd => 0x01af, 0xde => 0x0303, 0xe3 => 0x0103, 0xec => 0x0301, + 0xf0 => 0x0111, 0xf2 => 0x0323, 0xf5 => 0x01a1, 0xfd => 0x01b0, + 0xfe => 0x20ab, +); + +1; # end diff --git a/lib/Image/ExifTool/DICOM.pm b/lib/Image/ExifTool/DICOM.pm new file mode 100644 index 0000000..e5e13c6 --- /dev/null +++ b/lib/Image/ExifTool/DICOM.pm @@ -0,0 +1,3881 @@ +#------------------------------------------------------------------------------ +# File: DICOM.pm +# +# Description: Read DICOM and ACR-NEMA medical images +# +# Revisions: 2005/11/09 - P. Harvey Created +# 2009/11/19 - P. Harvey Added private GE tags from ref 4 +# 2009/12/11 - P. Harvey Updated to DICOM 2008 spec +# 2010/04/08 - P. Harvey Updated to DICOM 2009 spec +# +# References: 1) http://medical.nema.org/ +# 2) http://www.sph.sc.edu/comd/rorden/dicom.html +# 3) http://www.dclunie.com/ +# 4) http://www.gehealthcare.com/usen/interoperability/dicom/docs/2258357r3.pdf +#------------------------------------------------------------------------------ + +package Image::ExifTool::DICOM; + +use strict; +use vars qw($VERSION %uid); +use Image::ExifTool qw(:DataAccess :Utils); + +$VERSION = '1.21'; + +# DICOM VR (Value Representation) format conversions +my %dicomFormat = ( + FD => 'double', + FL => 'float', + OB => 'int8u', + OF => 'float', + OW => 'int16u', + SL => 'int32s', + SS => 'int16s', + UL => 'int32u', + US => 'int16u', +); + +# VR elements with 32-bit length in explicit VR syntax +my %vr32 = ( OB=>1, OW=>1, OF=>1, SQ=>1, UT=>1, UN=>1 ); + +# data elements with implicit VR regardless of syntax +my %implicitVR = ( + 'FFFE,E000' => 1, + 'FFFE,E00D' => 1, + 'FFFE,E0DD' => 1, +); + +# DICOM tags +# Note: "XxxGroupLength" tags are generated automatically if they don't exist +%Image::ExifTool::DICOM::Main = ( + GROUPS => { 2 => 'Image' }, + VARS => { NO_LOOKUP => 1 }, # omit tags from lookup (way too many!) + NOTES => q{ + The DICOM format is based on the ACR-NEMA specification, but adds a file + header and a number of new tags. ExifTool will extract information from + either type of file. The Tag ID's in the following table are the tag group + and element numbers in hexadecimal, as given in the DICOM specification (see + L<http://medical.nema.org/>). The table below contains tags from the DICOM + 2009 and earlier specifications plus some vendor-specific private tags. + + Note that DICOM information may be saved in other file formats using the + L<XMP DICOM Tags|Image::ExifTool::TagNames/XMP DICOM Tags>. + }, + # file meta information group (names end with VR) + '0002,0000' => { VR => 'UL', Name => 'FileMetaInfoGroupLength' }, + '0002,0001' => { VR => 'OB', Name => 'FileMetaInfoVersion' }, + '0002,0002' => { VR => 'UI', Name => 'MediaStorageSOPClassUID' }, + '0002,0003' => { VR => 'UI', Name => 'MediaStorageSOPInstanceUID' }, + '0002,0010' => { VR => 'UI', Name => 'TransferSyntaxUID' }, + '0002,0012' => { VR => 'UI', Name => 'ImplementationClassUID' }, + '0002,0013' => { VR => 'SH', Name => 'ImplementationVersionName' }, + '0002,0016' => { VR => 'AE', Name => 'SourceApplicationEntityTitle' }, + '0002,0100' => { VR => 'UI', Name => 'PrivateInformationCreatorUID' }, + '0002,0102' => { VR => 'OB', Name => 'PrivateInformation' }, + # directory structuring group + '0004,1130' => { VR => 'CS', Name => 'FileSetID' }, + '0004,1141' => { VR => 'CS', Name => 'FileSetDescriptorFileID' }, + '0004,1142' => { VR => 'CS', Name => 'SpecificCharacterSetOfFile' }, + '0004,1200' => { VR => 'UL', Name => 'FirstDirectoryRecordOffset' }, + '0004,1202' => { VR => 'UL', Name => 'LastDirectoryRecordOffset' }, + '0004,1212' => { VR => 'US', Name => 'FileSetConsistencyFlag' }, + '0004,1220' => { VR => 'SQ', Name => 'DirectoryRecordSequence' }, + '0004,1400' => { VR => 'UL', Name => 'OffsetOfNextDirectoryRecord' }, + '0004,1410' => { VR => 'US', Name => 'RecordInUseFlag' }, + '0004,1420' => { VR => 'UL', Name => 'LowerLevelDirectoryEntityOffset' }, + '0004,1430' => { VR => 'CS', Name => 'DirectoryRecordType' }, + '0004,1432' => { VR => 'UI', Name => 'PrivateRecordUID' }, + '0004,1500' => { VR => 'CS', Name => 'ReferencedFileID' }, + '0004,1504' => { VR => 'UL', Name => 'MRDRDirectoryRecordOffset' }, + '0004,1510' => { VR => 'UI', Name => 'ReferencedSOPClassUIDInFile' }, + '0004,1511' => { VR => 'UI', Name => 'ReferencedSOPInstanceUIDInFile' }, + '0004,1512' => { VR => 'UI', Name => 'ReferencedTransferSyntaxUIDInFile' }, + '0004,151A' => { VR => 'UI', Name => 'ReferencedRelatedSOPClassUIDInFile' }, + '0004,1600' => { VR => 'UL', Name => 'NumberOfReferences' }, + # identifying group + '0008,0000' => { VR => 'UL', Name => 'IdentifyingGroupLength' }, + '0008,0001' => { VR => 'UL', Name => 'LengthToEnd' }, + '0008,0005' => { VR => 'CS', Name => 'SpecificCharacterSet' }, + '0008,0006' => { VR => 'SQ', Name => 'LanguageCodeSequence' }, + '0008,0008' => { VR => 'CS', Name => 'ImageType' }, + '0008,0010' => { VR => 'CS', Name => 'RecognitionCode' }, + '0008,0012' => { VR => 'DA', Name => 'InstanceCreationDate' }, + '0008,0013' => { VR => 'TM', Name => 'InstanceCreationTime' }, + '0008,0014' => { VR => 'UI', Name => 'InstanceCreatorUID' }, + '0008,0016' => { VR => 'UI', Name => 'SOPClassUID' }, + '0008,0018' => { VR => 'UI', Name => 'SOPInstanceUID' }, + '0008,001A' => { VR => 'UI', Name => 'RelatedGeneralSOPClassUID' }, + '0008,001B' => { VR => 'UI', Name => 'OriginalSpecializedSOPClassUID' }, + '0008,0020' => { VR => 'DA', Name => 'StudyDate' }, + '0008,0021' => { VR => 'DA', Name => 'SeriesDate' }, + '0008,0022' => { VR => 'DA', Name => 'AcquisitionDate' }, + '0008,0023' => { VR => 'DA', Name => 'ContentDate' }, + '0008,0024' => { VR => 'DA', Name => 'OverlayDate' }, + '0008,0025' => { VR => 'DA', Name => 'CurveDate' }, + '0008,002A' => { VR => 'DT', Name => 'AcquisitionDateTime' }, + '0008,0030' => { VR => 'TM', Name => 'StudyTime' }, + '0008,0031' => { VR => 'TM', Name => 'SeriesTime' }, + '0008,0032' => { VR => 'TM', Name => 'AcquisitionTime' }, + '0008,0033' => { VR => 'TM', Name => 'ContentTime' }, + '0008,0034' => { VR => 'TM', Name => 'OverlayTime' }, + '0008,0035' => { VR => 'TM', Name => 'CurveTime' }, + '0008,0040' => { VR => 'US', Name => 'DataSetType' }, + '0008,0041' => { VR => 'LO', Name => 'DataSetSubtype' }, + '0008,0042' => { VR => 'CS', Name => 'NuclearMedicineSeriesType' }, + '0008,0050' => { VR => 'SH', Name => 'AccessionNumber' }, + '0008,0052' => { VR => 'CS', Name => 'QueryRetrieveLevel' }, + '0008,0054' => { VR => 'AE', Name => 'RetrieveAETitle' }, + '0008,0056' => { VR => 'CS', Name => 'InstanceAvailability' }, + '0008,0058' => { VR => 'UI', Name => 'FailedSOPInstanceUIDList' }, + '0008,0060' => { VR => 'CS', Name => 'Modality' }, + '0008,0061' => { VR => 'CS', Name => 'ModalitiesInStudy' }, + '0008,0062' => { VR => 'UI', Name => 'SOPClassesInStudy' }, + '0008,0064' => { VR => 'CS', Name => 'ConversionType' }, + '0008,0068' => { VR => 'CS', Name => 'PresentationIntentType' }, + '0008,0070' => { VR => 'LO', Name => 'Manufacturer' }, + '0008,0080' => { VR => 'LO', Name => 'InstitutionName' }, + '0008,0081' => { VR => 'ST', Name => 'InstitutionAddress' }, + '0008,0082' => { VR => 'SQ', Name => 'InstitutionCodeSequence' }, + '0008,0090' => { VR => 'PN', Name => 'ReferringPhysicianName' }, + '0008,0092' => { VR => 'ST', Name => 'ReferringPhysicianAddress' }, + '0008,0094' => { VR => 'SH', Name => 'ReferringPhysicianTelephoneNumber' }, + '0008,0096' => { VR => 'SQ', Name => 'ReferringPhysicianIDSequence' }, + '0008,0100' => { VR => 'SH', Name => 'CodeValue' }, + '0008,0102' => { VR => 'SH', Name => 'CodingSchemeDesignator' }, + '0008,0103' => { VR => 'SH', Name => 'CodingSchemeVersion' }, + '0008,0104' => { VR => 'LO', Name => 'CodeMeaning' }, + '0008,0105' => { VR => 'CS', Name => 'MappingResource' }, + '0008,0106' => { VR => 'DT', Name => 'ContextGroupVersion' }, + '0008,0107' => { VR => 'DT', Name => 'ContextGroupLocalVersion' }, + '0008,010B' => { VR => 'CS', Name => 'ContextGroupExtensionFlag' }, + '0008,010C' => { VR => 'UI', Name => 'CodingSchemeUID' }, + '0008,010D' => { VR => 'UI', Name => 'ContextGroupExtensionCreatorUID' }, + '0008,010F' => { VR => 'CS', Name => 'ContextIdentifier' }, + '0008,0110' => { VR => 'SQ', Name => 'CodingSchemeIDSequence' }, + '0008,0112' => { VR => 'LO', Name => 'CodingSchemeRegistry' }, + '0008,0114' => { VR => 'ST', Name => 'CodingSchemeExternalID' }, + '0008,0115' => { VR => 'ST', Name => 'CodingSchemeName' }, + '0008,0116' => { VR => 'ST', Name => 'ResponsibleOrganization' }, + '0008,0117' => { VR => 'UI', Name => 'ContextUID' }, + '0008,0201' => { VR => 'SH', Name => 'TimezoneOffsetFromUTC' }, + '0008,1000' => { VR => 'AE', Name => 'NetworkID' }, + '0008,1010' => { VR => 'SH', Name => 'StationName' }, + '0008,1030' => { VR => 'LO', Name => 'StudyDescription' }, + '0008,1032' => { VR => 'SQ', Name => 'ProcedureCodeSequence' }, + '0008,103E' => { VR => 'LO', Name => 'SeriesDescription' }, + '0008,1040' => { VR => 'LO', Name => 'InstitutionalDepartmentName' }, + '0008,1048' => { VR => 'PN', Name => 'PhysiciansOfRecord' }, + '0008,1049' => { VR => 'SQ', Name => 'PhysiciansOfRecordIDSequence' }, + '0008,1050' => { VR => 'PN', Name => 'PerformingPhysicianName' }, + '0008,1052' => { VR => 'SQ', Name => 'PerformingPhysicianIDSequence' }, + '0008,1060' => { VR => 'PN', Name => 'NameOfPhysicianReadingStudy' }, + '0008,1062' => { VR => 'SQ', Name => 'PhysicianReadingStudyIDSequence' }, + '0008,1070' => { VR => 'PN', Name => 'OperatorsName' }, + '0008,1072' => { VR => 'SQ', Name => 'OperatorIDSequence' }, + '0008,1080' => { VR => 'LO', Name => 'AdmittingDiagnosesDescription' }, + '0008,1084' => { VR => 'SQ', Name => 'AdmittingDiagnosesCodeSequence' }, + '0008,1090' => { VR => 'LO', Name => 'ManufacturersModelName' }, + '0008,1100' => { VR => 'SQ', Name => 'ReferencedResultsSequence' }, + '0008,1110' => { VR => 'SQ', Name => 'ReferencedStudySequence' }, + '0008,1111' => { VR => 'SQ', Name => 'ReferencedProcedureStepSequence' }, + '0008,1115' => { VR => 'SQ', Name => 'ReferencedSeriesSequence' }, + '0008,1120' => { VR => 'SQ', Name => 'ReferencedPatientSequence' }, + '0008,1125' => { VR => 'SQ', Name => 'ReferencedVisitSequence' }, + '0008,1130' => { VR => 'SQ', Name => 'ReferencedOverlaySequence' }, + '0008,113A' => { VR => 'SQ', Name => 'ReferencedWaveformSequence' }, + '0008,1140' => { VR => 'SQ', Name => 'ReferencedImageSequence' }, + '0008,1145' => { VR => 'SQ', Name => 'ReferencedCurveSequence' }, + '0008,114A' => { VR => 'SQ', Name => 'ReferencedInstanceSequence' }, + '0008,1150' => { VR => 'UI', Name => 'ReferencedSOPClassUID' }, + '0008,1155' => { VR => 'UI', Name => 'ReferencedSOPInstanceUID' }, + '0008,115A' => { VR => 'UI', Name => 'SOPClassesSupported' }, + '0008,1160' => { VR => 'IS', Name => 'ReferencedFrameNumber' }, + '0008,1161' => { VR => 'UL', Name => 'SimpleFrameList' }, + '0008,1162' => { VR => 'UL', Name => 'CalculatedFrameList' }, + '0008,1163' => { VR => 'FD', Name => 'TimeRange' }, + '0008,1164' => { VR => 'SQ', Name => 'FrameExtractionSequence' }, + '0008,1195' => { VR => 'UI', Name => 'TransactionUID' }, + '0008,1197' => { VR => 'US', Name => 'FailureReason' }, + '0008,1198' => { VR => 'SQ', Name => 'FailedSOPSequence' }, + '0008,1199' => { VR => 'SQ', Name => 'ReferencedSOPSequence' }, + '0008,1200' => { VR => 'SQ', Name => 'OtherReferencedStudiesSequence' }, + '0008,1250' => { VR => 'SQ', Name => 'RelatedSeriesSequence' }, + '0008,2110' => { VR => 'CS', Name => 'LossyImageCompression' }, + '0008,2111' => { VR => 'ST', Name => 'DerivationDescription' }, + '0008,2112' => { VR => 'SQ', Name => 'SourceImageSequence' }, + '0008,2120' => { VR => 'SH', Name => 'StageName' }, + '0008,2122' => { VR => 'IS', Name => 'StageNumber' }, + '0008,2124' => { VR => 'IS', Name => 'NumberOfStages' }, + '0008,2127' => { VR => 'SH', Name => 'ViewName' }, + '0008,2128' => { VR => 'IS', Name => 'ViewNumber' }, + '0008,2129' => { VR => 'IS', Name => 'NumberOfEventTimers' }, + '0008,212A' => { VR => 'IS', Name => 'NumberOfViewsInStage' }, + '0008,2130' => { VR => 'DS', Name => 'EventElapsedTimes' }, + '0008,2132' => { VR => 'LO', Name => 'EventTimerNames' }, + '0008,2133' => { VR => 'SQ', Name => 'EventTimerSequence' }, + '0008,2134' => { VR => 'FD', Name => 'EventTimeOffset' }, + '0008,2135' => { VR => 'SQ', Name => 'EventCodeSequence' }, + '0008,2142' => { VR => 'IS', Name => 'StartTrim' }, + '0008,2143' => { VR => 'IS', Name => 'StopTrim' }, + '0008,2144' => { VR => 'IS', Name => 'RecommendedDisplayFrameRate' }, + '0008,2200' => { VR => 'CS', Name => 'TransducerPosition' }, + '0008,2204' => { VR => 'CS', Name => 'TransducerOrientation' }, + '0008,2208' => { VR => 'CS', Name => 'AnatomicStructure' }, + '0008,2218' => { VR => 'SQ', Name => 'AnatomicRegionSequence' }, + '0008,2220' => { VR => 'SQ', Name => 'AnatomicRegionModifierSequence' }, + '0008,2228' => { VR => 'SQ', Name => 'PrimaryAnatomicStructureSequence' }, + '0008,2229' => { VR => 'SQ', Name => 'AnatomicStructureOrRegionSequence' }, + '0008,2230' => { VR => 'SQ', Name => 'AnatomicStructureModifierSequence' }, + '0008,2240' => { VR => 'SQ', Name => 'TransducerPositionSequence' }, + '0008,2242' => { VR => 'SQ', Name => 'TransducerPositionModifierSequence' }, + '0008,2244' => { VR => 'SQ', Name => 'TransducerOrientationSequence' }, + '0008,2246' => { VR => 'SQ', Name => 'TransducerOrientationModifierSeq' }, + '0008,2253' => { VR => 'SQ', Name => 'AnatomicEntrancePortalCodeSeqTrial' }, + '0008,2255' => { VR => 'SQ', Name => 'AnatomicApproachDirCodeSeqTrial' }, + '0008,2256' => { VR => 'ST', Name => 'AnatomicPerspectiveDescrTrial' }, + '0008,2257' => { VR => 'SQ', Name => 'AnatomicPerspectiveCodeSeqTrial' }, + '0008,3001' => { VR => 'SQ', Name => 'AlternateRepresentationSequence' }, + '0008,3010' => { VR => 'UI', Name => 'IrradiationEventUID' }, + '0008,4000' => { VR => 'LT', Name => 'IdentifyingComments' }, + '0008,9007' => { VR => 'CS', Name => 'FrameType' }, + '0008,9092' => { VR => 'SQ', Name => 'ReferencedImageEvidenceSequence' }, + '0008,9121' => { VR => 'SQ', Name => 'ReferencedRawDataSequence' }, + '0008,9123' => { VR => 'UI', Name => 'CreatorVersionUID' }, + '0008,9124' => { VR => 'SQ', Name => 'DerivationImageSequence' }, + '0008,9154' => { VR => 'SQ', Name => 'SourceImageEvidenceSequence' }, + '0008,9205' => { VR => 'CS', Name => 'PixelPresentation' }, + '0008,9206' => { VR => 'CS', Name => 'VolumetricProperties' }, + '0008,9207' => { VR => 'CS', Name => 'VolumeBasedCalculationTechnique' }, + '0008,9208' => { VR => 'CS', Name => 'ComplexImageComponent' }, + '0008,9209' => { VR => 'CS', Name => 'AcquisitionContrast' }, + '0008,9215' => { VR => 'SQ', Name => 'DerivationCodeSequence' }, + '0008,9237' => { VR => 'SQ', Name => 'GrayscalePresentationStateSequence' }, + '0008,9410' => { VR => 'SQ', Name => 'ReferencedOtherPlaneSequence' }, + '0008,9458' => { VR => 'SQ', Name => 'FrameDisplaySequence' }, + '0008,9459' => { VR => 'FL', Name => 'RecommendedDisplayFrameRateInFloat' }, + '0008,9460' => { VR => 'CS', Name => 'SkipFrameRangeFlag' }, + # GEMS_IDEN_01 (ref 4) + '0009,1001' => { VR => 'LO', Name => 'FullFidelity' }, + '0009,1002' => { VR => 'SH', Name => 'SuiteID' }, + '0009,1004' => { VR => 'SH', Name => 'ProductID' }, + '0009,1027' => { VR => 'SL', Name => 'ImageActualDate' }, + '0009,1030' => { VR => 'SH', Name => 'ServiceID' }, + '0009,1031' => { VR => 'SH', Name => 'MobileLocationNumber' }, + '0009,10E3' => { VR => 'UI', Name => 'EquipmentUID' }, + '0009,10E6' => { VR => 'SH', Name => 'GenesisVersionNow' }, + '0009,10E7' => { VR => 'UL', Name => 'ExamRecordChecksum' }, + '0009,10E9' => { VR => 'SL', Name => 'ActualSeriesDataTimeStamp' }, + # patient group + '0010,0000' => { VR => 'UL', Name => 'PatientGroupLength' }, + '0010,0010' => { VR => 'PN', Name => 'PatientName' }, + '0010,0020' => { VR => 'LO', Name => 'PatientID' }, + '0010,0021' => { VR => 'LO', Name => 'IssuerOfPatientID' }, + '0010,0022' => { VR => 'CS', Name => 'TypeOfPatientID' }, + '0010,0030' => { VR => 'DA', Name => 'PatientBirthDate' }, + '0010,0032' => { VR => 'TM', Name => 'PatientBirthTime' }, + '0010,0040' => { VR => 'CS', Name => 'PatientSex' }, + '0010,0050' => { VR => 'SQ', Name => 'PatientInsurancePlanCodeSequence' }, + '0010,0101' => { VR => 'SQ', Name => 'PatientPrimaryLanguageCodeSeq' }, + '0010,0102' => { VR => 'SQ', Name => 'PatientPrimaryLanguageCodeModSeq' }, + '0010,1000' => { VR => 'LO', Name => 'OtherPatientIDs' }, + '0010,1001' => { VR => 'PN', Name => 'OtherPatientNames' }, + '0010,1002' => { VR => 'SQ', Name => 'OtherPatientIDsSequence' }, + '0010,1005' => { VR => 'PN', Name => 'PatientBirthName' }, + '0010,1010' => { VR => 'AS', Name => 'PatientAge' }, + '0010,1020' => { VR => 'DS', Name => 'PatientSize' }, + '0010,1030' => { VR => 'DS', Name => 'PatientWeight' }, + '0010,1040' => { VR => 'LO', Name => 'PatientAddress' }, + '0010,1050' => { VR => 'LO', Name => 'InsurancePlanIdentification' }, + '0010,1060' => { VR => 'PN', Name => 'PatientMotherBirthName' }, + '0010,1080' => { VR => 'LO', Name => 'MilitaryRank' }, + '0010,1081' => { VR => 'LO', Name => 'BranchOfService' }, + '0010,1090' => { VR => 'LO', Name => 'MedicalRecordLocator' }, + '0010,2000' => { VR => 'LO', Name => 'MedicalAlerts' }, + '0010,2110' => { VR => 'LO', Name => 'Allergies' }, + '0010,2150' => { VR => 'LO', Name => 'CountryOfResidence' }, + '0010,2152' => { VR => 'LO', Name => 'RegionOfResidence' }, + '0010,2154' => { VR => 'SH', Name => 'PatientTelephoneNumbers' }, + '0010,2160' => { VR => 'SH', Name => 'EthnicGroup' }, + '0010,2180' => { VR => 'SH', Name => 'Occupation' }, + '0010,21A0' => { VR => 'CS', Name => 'SmokingStatus' }, + '0010,21B0' => { VR => 'LT', Name => 'AdditionalPatientHistory' }, + '0010,21C0' => { VR => 'US', Name => 'PregnancyStatus' }, + '0010,21D0' => { VR => 'DA', Name => 'LastMenstrualDate' }, + '0010,21F0' => { VR => 'LO', Name => 'PatientReligiousPreference' }, + '0010,2201' => { VR => 'LO', Name => 'PatientSpeciesDescription' }, + '0010,2202' => { VR => 'SQ', Name => 'PatientSpeciesCodeSequence' }, + '0010,2203' => { VR => 'CS', Name => 'PatientSexNeutered' }, + '0010,2210' => { VR => 'CS', Name => 'AnatomicalOrientationType' }, + '0010,2292' => { VR => 'LO', Name => 'PatientBreedDescription' }, + '0010,2293' => { VR => 'SQ', Name => 'PatientBreedCodeSequence' }, + '0010,2294' => { VR => 'SQ', Name => 'BreedRegistrationSequence' }, + '0010,2295' => { VR => 'LO', Name => 'BreedRegistrationNumber' }, + '0010,2296' => { VR => 'SQ', Name => 'BreedRegistryCodeSequence' }, + '0010,2297' => { VR => 'PN', Name => 'ResponsiblePerson' }, + '0010,2298' => { VR => 'CS', Name => 'ResponsiblePersonRole' }, + '0010,2299' => { VR => 'LO', Name => 'ResponsibleOrganization' }, + '0010,4000' => { VR => 'LT', Name => 'PatientComments' }, + '0010,9431' => { VR => 'FL', Name => 'ExaminedBodyThickness' }, + # GEMS_PATI_01 (ref 4) + '0011,1010' => { VR => 'SS', Name => 'PatientStatus' }, + # clinical trial group + '0012,0010' => { VR => 'LO', Name => 'ClinicalTrialSponsorName' }, + '0012,0020' => { VR => 'LO', Name => 'ClinicalTrialProtocolID' }, + '0012,0021' => { VR => 'LO', Name => 'ClinicalTrialProtocolName' }, + '0012,0030' => { VR => 'LO', Name => 'ClinicalTrialSiteID' }, + '0012,0031' => { VR => 'LO', Name => 'ClinicalTrialSiteName' }, + '0012,0040' => { VR => 'LO', Name => 'ClinicalTrialSubjectID' }, + '0012,0042' => { VR => 'LO', Name => 'ClinicalTrialSubjectReadingID' }, + '0012,0050' => { VR => 'LO', Name => 'ClinicalTrialTimePointID' }, + '0012,0051' => { VR => 'ST', Name => 'ClinicalTrialTimePointDescription' }, + '0012,0060' => { VR => 'LO', Name => 'ClinicalTrialCoordinatingCenter' }, + '0012,0062' => { VR => 'CS', Name => 'PatientIdentityRemoved' }, + '0012,0063' => { VR => 'LO', Name => 'DeidentificationMethod' }, + '0012,0064' => { VR => 'SQ', Name => 'DeidentificationMethodCodeSequence' }, + '0012,0071' => { VR => 'LO', Name => 'ClinicalTrialSeriesID' }, + '0012,0072' => { VR => 'LO', Name => 'ClinicalTrialSeriesDescription' }, + '0012,0084' => { VR => 'CS', Name => 'DistributionType' }, + '0012,0085' => { VR => 'CS', Name => 'ConsentForDistributionFlag' }, + # acquisition group + '0018,0000' => { VR => 'UL', Name => 'AcquisitionGroupLength' }, + '0018,0010' => { VR => 'LO', Name => 'ContrastBolusAgent' }, + '0018,0012' => { VR => 'SQ', Name => 'ContrastBolusAgentSequence' }, + '0018,0014' => { VR => 'SQ', Name => 'ContrastBolusAdministrationRoute' }, + '0018,0015' => { VR => 'CS', Name => 'BodyPartExamined' }, + '0018,0020' => { VR => 'CS', Name => 'ScanningSequence' }, + '0018,0021' => { VR => 'CS', Name => 'SequenceVariant' }, + '0018,0022' => { VR => 'CS', Name => 'ScanOptions' }, + '0018,0023' => { VR => 'CS', Name => 'MRAcquisitionType' }, + '0018,0024' => { VR => 'SH', Name => 'SequenceName' }, + '0018,0025' => { VR => 'CS', Name => 'AngioFlag' }, + '0018,0026' => { VR => 'SQ', Name => 'InterventionDrugInformationSeq' }, + '0018,0027' => { VR => 'TM', Name => 'InterventionDrugStopTime' }, + '0018,0028' => { VR => 'DS', Name => 'InterventionDrugDose' }, + '0018,0029' => { VR => 'SQ', Name => 'InterventionDrugSequence' }, + '0018,002A' => { VR => 'SQ', Name => 'AdditionalDrugSequence' }, + '0018,0030' => { VR => 'LO', Name => 'Radionuclide' }, + '0018,0031' => { VR => 'LO', Name => 'Radiopharmaceutical' }, + '0018,0032' => { VR => 'DS', Name => 'EnergyWindowCenterline' }, + '0018,0033' => { VR => 'DS', Name => 'EnergyWindowTotalWidth' }, + '0018,0034' => { VR => 'LO', Name => 'InterventionDrugName' }, + '0018,0035' => { VR => 'TM', Name => 'InterventionDrugStartTime' }, + '0018,0036' => { VR => 'SQ', Name => 'InterventionSequence' }, + '0018,0037' => { VR => 'CS', Name => 'TherapyType' }, + '0018,0038' => { VR => 'CS', Name => 'InterventionStatus' }, + '0018,0039' => { VR => 'CS', Name => 'TherapyDescription' }, + '0018,003A' => { VR => 'ST', Name => 'InterventionDescription' }, + '0018,0040' => { VR => 'IS', Name => 'CineRate' }, + '0018,0042' => { VR => 'CS', Name => 'InitialCineRunState' }, + '0018,0050' => { VR => 'DS', Name => 'SliceThickness' }, + '0018,0060' => { VR => 'DS', Name => 'KVP' }, + '0018,0070' => { VR => 'IS', Name => 'CountsAccumulated' }, + '0018,0071' => { VR => 'CS', Name => 'AcquisitionTerminationCondition' }, + '0018,0072' => { VR => 'DS', Name => 'EffectiveDuration' }, + '0018,0073' => { VR => 'CS', Name => 'AcquisitionStartCondition' }, + '0018,0074' => { VR => 'IS', Name => 'AcquisitionStartConditionData' }, + '0018,0075' => { VR => 'IS', Name => 'AcquisitionEndConditionData' }, + '0018,0080' => { VR => 'DS', Name => 'RepetitionTime' }, + '0018,0081' => { VR => 'DS', Name => 'EchoTime' }, + '0018,0082' => { VR => 'DS', Name => 'InversionTime' }, + '0018,0083' => { VR => 'DS', Name => 'NumberOfAverages' }, + '0018,0084' => { VR => 'DS', Name => 'ImagingFrequency' }, + '0018,0085' => { VR => 'SH', Name => 'ImagedNucleus' }, + '0018,0086' => { VR => 'IS', Name => 'EchoNumber' }, + '0018,0087' => { VR => 'DS', Name => 'MagneticFieldStrength' }, + '0018,0088' => { VR => 'DS', Name => 'SpacingBetweenSlices' }, + '0018,0089' => { VR => 'IS', Name => 'NumberOfPhaseEncodingSteps' }, + '0018,0090' => { VR => 'DS', Name => 'DataCollectionDiameter' }, + '0018,0091' => { VR => 'IS', Name => 'EchoTrainLength' }, + '0018,0093' => { VR => 'DS', Name => 'PercentSampling' }, + '0018,0094' => { VR => 'DS', Name => 'PercentPhaseFieldOfView' }, + '0018,0095' => { VR => 'DS', Name => 'PixelBandwidth' }, + '0018,1000' => { VR => 'LO', Name => 'DeviceSerialNumber' }, + '0018,1002' => { VR => 'UI', Name => 'DeviceUID' }, + '0018,1003' => { VR => 'LO', Name => 'DeviceID' }, + '0018,1004' => { VR => 'LO', Name => 'PlateID' }, + '0018,1005' => { VR => 'LO', Name => 'GeneratorID' }, + '0018,1006' => { VR => 'LO', Name => 'GridID' }, + '0018,1007' => { VR => 'LO', Name => 'CassetteID' }, + '0018,1008' => { VR => 'LO', Name => 'GantryID' }, + '0018,1010' => { VR => 'LO', Name => 'SecondaryCaptureDeviceID' }, + '0018,1011' => { VR => 'LO', Name => 'HardcopyCreationDeviceID' }, + '0018,1012' => { VR => 'DA', Name => 'DateOfSecondaryCapture' }, + '0018,1014' => { VR => 'TM', Name => 'TimeOfSecondaryCapture' }, + '0018,1016' => { VR => 'LO', Name => 'SecondaryCaptureDeviceManufacturer' }, + '0018,1017' => { VR => 'LO', Name => 'HardcopyDeviceManufacturer' }, + '0018,1018' => { VR => 'LO', Name => 'SecondaryCaptureDeviceModelName' }, + '0018,1019' => { VR => 'LO', Name => 'SecondaryCaptureDeviceSoftwareVers' }, + '0018,101A' => { VR => 'LO', Name => 'HardcopyDeviceSoftwareVersion' }, + '0018,101B' => { VR => 'LO', Name => 'HardcopyDeviceModelName' }, + '0018,1020' => { VR => 'LO', Name => 'SoftwareVersion' }, + '0018,1022' => { VR => 'SH', Name => 'VideoImageFormatAcquired' }, + '0018,1023' => { VR => 'LO', Name => 'DigitalImageFormatAcquired' }, + '0018,1030' => { VR => 'LO', Name => 'ProtocolName' }, + '0018,1040' => { VR => 'LO', Name => 'ContrastBolusRoute' }, + '0018,1041' => { VR => 'DS', Name => 'ContrastBolusVolume' }, + '0018,1042' => { VR => 'TM', Name => 'ContrastBolusStartTime' }, + '0018,1043' => { VR => 'TM', Name => 'ContrastBolusStopTime' }, + '0018,1044' => { VR => 'DS', Name => 'ContrastBolusTotalDose' }, + '0018,1045' => { VR => 'IS', Name => 'SyringeCounts' }, + '0018,1046' => { VR => 'DS', Name => 'ContrastFlowRate' }, + '0018,1047' => { VR => 'DS', Name => 'ContrastFlowDuration' }, + '0018,1048' => { VR => 'CS', Name => 'ContrastBolusIngredient' }, + '0018,1049' => { VR => 'DS', Name => 'ContrastBolusConcentration' }, + '0018,1050' => { VR => 'DS', Name => 'SpatialResolution' }, + '0018,1060' => { VR => 'DS', Name => 'TriggerTime' }, + '0018,1061' => { VR => 'LO', Name => 'TriggerSourceOrType' }, + '0018,1062' => { VR => 'IS', Name => 'NominalInterval' }, + '0018,1063' => { VR => 'DS', Name => 'FrameTime' }, + '0018,1064' => { VR => 'LO', Name => 'CardiacFramingType' }, + '0018,1065' => { VR => 'DS', Name => 'FrameTimeVector' }, + '0018,1066' => { VR => 'DS', Name => 'FrameDelay' }, + '0018,1067' => { VR => 'DS', Name => 'ImageTriggerDelay' }, + '0018,1068' => { VR => 'DS', Name => 'MultiplexGroupTimeOffset' }, + '0018,1069' => { VR => 'DS', Name => 'TriggerTimeOffset' }, + '0018,106A' => { VR => 'CS', Name => 'SynchronizationTrigger' }, + '0018,106C' => { VR => 'US', Name => 'SynchronizationChannel' }, + '0018,106E' => { VR => 'UL', Name => 'TriggerSamplePosition' }, + '0018,1070' => { VR => 'LO', Name => 'RadiopharmaceuticalRoute' }, + '0018,1071' => { VR => 'DS', Name => 'RadiopharmaceuticalVolume' }, + '0018,1072' => { VR => 'TM', Name => 'RadiopharmaceuticalStartTime' }, + '0018,1073' => { VR => 'TM', Name => 'RadiopharmaceuticalStopTime' }, + '0018,1074' => { VR => 'DS', Name => 'RadionuclideTotalDose' }, + '0018,1075' => { VR => 'DS', Name => 'RadionuclideHalfLife' }, + '0018,1076' => { VR => 'DS', Name => 'RadionuclidePositronFraction' }, + '0018,1077' => { VR => 'DS', Name => 'RadiopharmaceuticalSpecActivity' }, + '0018,1078' => { VR => 'DT', Name => 'RadiopharmaceuticalStartDateTime' }, + '0018,1079' => { VR => 'DT', Name => 'RadiopharmaceuticalStopDateTime' }, + '0018,1080' => { VR => 'CS', Name => 'BeatRejectionFlag' }, + '0018,1081' => { VR => 'IS', Name => 'LowRRValue' }, + '0018,1082' => { VR => 'IS', Name => 'HighRRValue' }, + '0018,1083' => { VR => 'IS', Name => 'IntervalsAcquired' }, + '0018,1084' => { VR => 'IS', Name => 'IntervalsRejected' }, + '0018,1085' => { VR => 'LO', Name => 'PVCRejection' }, + '0018,1086' => { VR => 'IS', Name => 'SkipBeats' }, + '0018,1088' => { VR => 'IS', Name => 'HeartRate' }, + '0018,1090' => { VR => 'IS', Name => 'CardiacNumberOfImages' }, + '0018,1094' => { VR => 'IS', Name => 'TriggerWindow' }, + '0018,1100' => { VR => 'DS', Name => 'ReconstructionDiameter' }, + '0018,1110' => { VR => 'DS', Name => 'DistanceSourceToDetector' }, + '0018,1111' => { VR => 'DS', Name => 'DistanceSourceToPatient' }, + '0018,1114' => { VR => 'DS', Name => 'EstimatedRadiographicMagnification' }, + '0018,1120' => { VR => 'DS', Name => 'GantryDetectorTilt' }, + '0018,1121' => { VR => 'DS', Name => 'GantryDetectorSlew' }, + '0018,1130' => { VR => 'DS', Name => 'TableHeight' }, + '0018,1131' => { VR => 'DS', Name => 'TableTraverse' }, + '0018,1134' => { VR => 'CS', Name => 'TableMotion' }, + '0018,1135' => { VR => 'DS', Name => 'TableVerticalIncrement' }, + '0018,1136' => { VR => 'DS', Name => 'TableLateralIncrement' }, + '0018,1137' => { VR => 'DS', Name => 'TableLongitudinalIncrement' }, + '0018,1138' => { VR => 'DS', Name => 'TableAngle' }, + '0018,113A' => { VR => 'CS', Name => 'TableType' }, + '0018,1140' => { VR => 'CS', Name => 'RotationDirection' }, + '0018,1141' => { VR => 'DS', Name => 'AngularPosition' }, + '0018,1142' => { VR => 'DS', Name => 'RadialPosition' }, + '0018,1143' => { VR => 'DS', Name => 'ScanArc' }, + '0018,1144' => { VR => 'DS', Name => 'AngularStep' }, + '0018,1145' => { VR => 'DS', Name => 'CenterOfRotationOffset' }, + '0018,1146' => { VR => 'DS', Name => 'RotationOffset' }, + '0018,1147' => { VR => 'CS', Name => 'FieldOfViewShape' }, + '0018,1149' => { VR => 'IS', Name => 'FieldOfViewDimensions' }, + '0018,1150' => { VR => 'IS', Name => 'ExposureTime' }, + '0018,1151' => { VR => 'IS', Name => 'XRayTubeCurrent' }, + '0018,1152' => { VR => 'IS', Name => 'Exposure' }, + '0018,1153' => { VR => 'IS', Name => 'ExposureInMicroAmpSec' }, + '0018,1154' => { VR => 'DS', Name => 'AveragePulseWidth' }, + '0018,1155' => { VR => 'CS', Name => 'RadiationSetting' }, + '0018,1156' => { VR => 'CS', Name => 'RectificationType' }, + '0018,115A' => { VR => 'CS', Name => 'RadiationMode' }, + '0018,115E' => { VR => 'DS', Name => 'ImageAreaDoseProduct' }, + '0018,1160' => { VR => 'SH', Name => 'FilterType' }, + '0018,1161' => { VR => 'LO', Name => 'TypeOfFilters' }, + '0018,1162' => { VR => 'DS', Name => 'IntensifierSize' }, + '0018,1164' => { VR => 'DS', Name => 'ImagerPixelSpacing' }, + '0018,1166' => { VR => 'CS', Name => 'Grid' }, + '0018,1170' => { VR => 'IS', Name => 'GeneratorPower' }, + '0018,1180' => { VR => 'SH', Name => 'CollimatorGridName' }, + '0018,1181' => { VR => 'CS', Name => 'CollimatorType' }, + '0018,1182' => { VR => 'IS', Name => 'FocalDistance' }, + '0018,1183' => { VR => 'DS', Name => 'XFocusCenter' }, + '0018,1184' => { VR => 'DS', Name => 'YFocusCenter' }, + '0018,1190' => { VR => 'DS', Name => 'FocalSpots' }, + '0018,1191' => { VR => 'CS', Name => 'AnodeTargetMaterial' }, + '0018,11A0' => { VR => 'DS', Name => 'BodyPartThickness' }, + '0018,11A2' => { VR => 'DS', Name => 'CompressionForce' }, + '0018,1200' => { VR => 'DA', Name => 'DateOfLastCalibration' }, + '0018,1201' => { VR => 'TM', Name => 'TimeOfLastCalibration' }, + '0018,1210' => { VR => 'SH', Name => 'ConvolutionKernel' }, + '0018,1240' => { VR => 'IS', Name => 'UpperLowerPixelValues' }, + '0018,1242' => { VR => 'IS', Name => 'ActualFrameDuration' }, + '0018,1243' => { VR => 'IS', Name => 'CountRate' }, + '0018,1244' => { VR => 'US', Name => 'PreferredPlaybackSequencing' }, + '0018,1250' => { VR => 'SH', Name => 'ReceiveCoilName' }, + '0018,1251' => { VR => 'SH', Name => 'TransmitCoilName' }, + '0018,1260' => { VR => 'SH', Name => 'PlateType' }, + '0018,1261' => { VR => 'LO', Name => 'PhosphorType' }, + '0018,1300' => { VR => 'DS', Name => 'ScanVelocity' }, + '0018,1301' => { VR => 'CS', Name => 'WholeBodyTechnique' }, + '0018,1302' => { VR => 'IS', Name => 'ScanLength' }, + '0018,1310' => { VR => 'US', Name => 'AcquisitionMatrix' }, + '0018,1312' => { VR => 'CS', Name => 'InPlanePhaseEncodingDirection' }, + '0018,1314' => { VR => 'DS', Name => 'FlipAngle' }, + '0018,1315' => { VR => 'CS', Name => 'VariableFlipAngleFlag' }, + '0018,1316' => { VR => 'DS', Name => 'SAR' }, + '0018,1318' => { VR => 'DS', Name => 'DB-Dt' }, + '0018,1400' => { VR => 'LO', Name => 'AcquisitionDeviceProcessingDescr' }, + '0018,1401' => { VR => 'LO', Name => 'AcquisitionDeviceProcessingCode' }, + '0018,1402' => { VR => 'CS', Name => 'CassetteOrientation' }, + '0018,1403' => { VR => 'CS', Name => 'CassetteSize' }, + '0018,1404' => { VR => 'US', Name => 'ExposuresOnPlate' }, + '0018,1405' => { VR => 'IS', Name => 'RelativeXRayExposure' }, + '0018,1450' => { VR => 'DS', Name => 'ColumnAngulation' }, + '0018,1460' => { VR => 'DS', Name => 'TomoLayerHeight' }, + '0018,1470' => { VR => 'DS', Name => 'TomoAngle' }, + '0018,1480' => { VR => 'DS', Name => 'TomoTime' }, + '0018,1490' => { VR => 'CS', Name => 'TomoType' }, + '0018,1491' => { VR => 'CS', Name => 'TomoClass' }, + '0018,1495' => { VR => 'IS', Name => 'NumberOfTomosynthesisSourceImages' }, + '0018,1500' => { VR => 'CS', Name => 'PositionerMotion' }, + '0018,1508' => { VR => 'CS', Name => 'PositionerType' }, + '0018,1510' => { VR => 'DS', Name => 'PositionerPrimaryAngle' }, + '0018,1511' => { VR => 'DS', Name => 'PositionerSecondaryAngle' }, + '0018,1520' => { VR => 'DS', Name => 'PositionerPrimaryAngleIncrement' }, + '0018,1521' => { VR => 'DS', Name => 'PositionerSecondaryAngleIncrement' }, + '0018,1530' => { VR => 'DS', Name => 'DetectorPrimaryAngle' }, + '0018,1531' => { VR => 'DS', Name => 'DetectorSecondaryAngle' }, + '0018,1600' => { VR => 'CS', Name => 'ShutterShape' }, + '0018,1602' => { VR => 'IS', Name => 'ShutterLeftVerticalEdge' }, + '0018,1604' => { VR => 'IS', Name => 'ShutterRightVerticalEdge' }, + '0018,1606' => { VR => 'IS', Name => 'ShutterUpperHorizontalEdge' }, + '0018,1608' => { VR => 'IS', Name => 'ShutterLowerHorizontalEdge' }, + '0018,1610' => { VR => 'IS', Name => 'CenterOfCircularShutter' }, + '0018,1612' => { VR => 'IS', Name => 'RadiusOfCircularShutter' }, + '0018,1620' => { VR => 'IS', Name => 'VerticesOfPolygonalShutter' }, + '0018,1622' => { VR => 'US', Name => 'ShutterPresentationValue' }, + '0018,1623' => { VR => 'US', Name => 'ShutterOverlayGroup' }, + '0018,1624' => { VR => 'US', Name => 'ShutterPresentationColorCIELabVal' }, + '0018,1700' => { VR => 'CS', Name => 'CollimatorShape' }, + '0018,1702' => { VR => 'IS', Name => 'CollimatorLeftVerticalEdge' }, + '0018,1704' => { VR => 'IS', Name => 'CollimatorRightVerticalEdge' }, + '0018,1706' => { VR => 'IS', Name => 'CollimatorUpperHorizontalEdge' }, + '0018,1708' => { VR => 'IS', Name => 'CollimatorLowerHorizontalEdge' }, + '0018,1710' => { VR => 'IS', Name => 'CenterOfCircularCollimator' }, + '0018,1712' => { VR => 'IS', Name => 'RadiusOfCircularCollimator' }, + '0018,1720' => { VR => 'IS', Name => 'VerticesOfPolygonalCollimator' }, + '0018,1800' => { VR => 'CS', Name => 'AcquisitionTimeSynchronized' }, + '0018,1801' => { VR => 'SH', Name => 'TimeSource' }, + '0018,1802' => { VR => 'CS', Name => 'TimeDistributionProtocol' }, + '0018,1803' => { VR => 'LO', Name => 'NTPSourceAddress' }, + '0018,2001' => { VR => 'IS', Name => 'PageNumberVector' }, + '0018,2002' => { VR => 'SH', Name => 'FrameLabelVector' }, + '0018,2003' => { VR => 'DS', Name => 'FramePrimaryAngleVector' }, + '0018,2004' => { VR => 'DS', Name => 'FrameSecondaryAngleVector' }, + '0018,2005' => { VR => 'DS', Name => 'SliceLocationVector' }, + '0018,2006' => { VR => 'SH', Name => 'DisplayWindowLabelVector' }, + '0018,2010' => { VR => 'DS', Name => 'NominalScannedPixelSpacing' }, + '0018,2020' => { VR => 'CS', Name => 'DigitizingDeviceTransportDirection' }, + '0018,2030' => { VR => 'DS', Name => 'RotationOfScannedFilm' }, + '0018,3100' => { VR => 'CS', Name => 'IVUSAcquisition' }, + '0018,3101' => { VR => 'DS', Name => 'IVUSPullbackRate' }, + '0018,3102' => { VR => 'DS', Name => 'IVUSGatedRate' }, + '0018,3103' => { VR => 'IS', Name => 'IVUSPullbackStartFrameNumber' }, + '0018,3104' => { VR => 'IS', Name => 'IVUSPullbackStopFrameNumber' }, + '0018,3105' => { VR => 'IS', Name => 'LesionNumber' }, + '0018,4000' => { VR => 'LT', Name => 'AcquisitionComments' }, + '0018,5000' => { VR => 'SH', Name => 'OutputPower' }, + '0018,5010' => { VR => 'LO', Name => 'TransducerData' }, + '0018,5012' => { VR => 'DS', Name => 'FocusDepth' }, + '0018,5020' => { VR => 'LO', Name => 'ProcessingFunction' }, + '0018,5021' => { VR => 'LO', Name => 'PostprocessingFunction' }, + '0018,5022' => { VR => 'DS', Name => 'MechanicalIndex' }, + '0018,5024' => { VR => 'DS', Name => 'BoneThermalIndex' }, + '0018,5026' => { VR => 'DS', Name => 'CranialThermalIndex' }, + '0018,5027' => { VR => 'DS', Name => 'SoftTissueThermalIndex' }, + '0018,5028' => { VR => 'DS', Name => 'SoftTissueFocusThermalIndex' }, + '0018,5029' => { VR => 'DS', Name => 'SoftTissueSurfaceThermalIndex' }, + '0018,5030' => { VR => 'DS', Name => 'DynamicRange' }, + '0018,5040' => { VR => 'DS', Name => 'TotalGain' }, + '0018,5050' => { VR => 'IS', Name => 'DepthOfScanField' }, + '0018,5100' => { VR => 'CS', Name => 'PatientPosition' }, + '0018,5101' => { VR => 'CS', Name => 'ViewPosition' }, + '0018,5104' => { VR => 'SQ', Name => 'ProjectionEponymousNameCodeSeq' }, + '0018,5210' => { VR => 'DS', Name => 'ImageTransformationMatrix' }, + '0018,5212' => { VR => 'DS', Name => 'ImageTranslationVector' }, + '0018,6000' => { VR => 'DS', Name => 'Sensitivity' }, + '0018,6011' => { VR => 'SQ', Name => 'SequenceOfUltrasoundRegions' }, + '0018,6012' => { VR => 'US', Name => 'RegionSpatialFormat' }, + '0018,6014' => { VR => 'US', Name => 'RegionDataType' }, + '0018,6016' => { VR => 'UL', Name => 'RegionFlags' }, + '0018,6018' => { VR => 'UL', Name => 'RegionLocationMinX0' }, + '0018,601A' => { VR => 'UL', Name => 'RegionLocationMinY0' }, + '0018,601C' => { VR => 'UL', Name => 'RegionLocationMaxX1' }, + '0018,601E' => { VR => 'UL', Name => 'RegionLocationMaxY1' }, + '0018,6020' => { VR => 'SL', Name => 'ReferencePixelX0' }, + '0018,6022' => { VR => 'SL', Name => 'ReferencePixelY0' }, + '0018,6024' => { VR => 'US', Name => 'PhysicalUnitsXDirection' }, + '0018,6026' => { VR => 'US', Name => 'PhysicalUnitsYDirection' }, + '0018,6028' => { VR => 'FD', Name => 'ReferencePixelPhysicalValueX' }, + '0018,602A' => { VR => 'FD', Name => 'ReferencePixelPhysicalValueY' }, + '0018,602C' => { VR => 'FD', Name => 'PhysicalDeltaX' }, + '0018,602E' => { VR => 'FD', Name => 'PhysicalDeltaY' }, + '0018,6030' => { VR => 'UL', Name => 'TransducerFrequency' }, + '0018,6031' => { VR => 'CS', Name => 'TransducerType' }, + '0018,6032' => { VR => 'UL', Name => 'PulseRepetitionFrequency' }, + '0018,6034' => { VR => 'FD', Name => 'DopplerCorrectionAngle' }, + '0018,6036' => { VR => 'FD', Name => 'SteeringAngle' }, + '0018,6038' => { VR => 'UL', Name => 'DopplerSampleVolumeXPosRetired' }, + '0018,6039' => { VR => 'SL', Name => 'DopplerSampleVolumeXPosition' }, + '0018,603A' => { VR => 'UL', Name => 'DopplerSampleVolumeYPosRetired' }, + '0018,603B' => { VR => 'SL', Name => 'DopplerSampleVolumeYPosition' }, + '0018,603C' => { VR => 'UL', Name => 'TMLinePositionX0Retired' }, + '0018,603D' => { VR => 'SL', Name => 'TMLinePositionX0' }, + '0018,603E' => { VR => 'UL', Name => 'TMLinePositionY0Retired' }, + '0018,603F' => { VR => 'SL', Name => 'TMLinePositionY0' }, + '0018,6040' => { VR => 'UL', Name => 'TMLinePositionX1Retired' }, + '0018,6041' => { VR => 'SL', Name => 'TMLinePositionX1' }, + '0018,6042' => { VR => 'UL', Name => 'TMLinePositionY1Retired' }, + '0018,6043' => { VR => 'SL', Name => 'TMLinePositionY1' }, + '0018,6044' => { VR => 'US', Name => 'PixelComponentOrganization' }, + '0018,6046' => { VR => 'UL', Name => 'PixelComponentMask' }, + '0018,6048' => { VR => 'UL', Name => 'PixelComponentRangeStart' }, + '0018,604A' => { VR => 'UL', Name => 'PixelComponentRangeStop' }, + '0018,604C' => { VR => 'US', Name => 'PixelComponentPhysicalUnits' }, + '0018,604E' => { VR => 'US', Name => 'PixelComponentDataType' }, + '0018,6050' => { VR => 'UL', Name => 'NumberOfTableBreakPoints' }, + '0018,6052' => { VR => 'UL', Name => 'TableOfXBreakPoints' }, + '0018,6054' => { VR => 'FD', Name => 'TableOfYBreakPoints' }, + '0018,6056' => { VR => 'UL', Name => 'NumberOfTableEntries' }, + '0018,6058' => { VR => 'UL', Name => 'TableOfPixelValues' }, + '0018,605A' => { VR => 'FL', Name => 'TableOfParameterValues' }, + '0018,6060' => { VR => 'FL', Name => 'RWaveTimeVector' }, + '0018,7000' => { VR => 'CS', Name => 'DetectorConditionsNominalFlag' }, + '0018,7001' => { VR => 'DS', Name => 'DetectorTemperature' }, + '0018,7004' => { VR => 'CS', Name => 'DetectorType' }, + '0018,7005' => { VR => 'CS', Name => 'DetectorConfiguration' }, + '0018,7006' => { VR => 'LT', Name => 'DetectorDescription' }, + '0018,7008' => { VR => 'LT', Name => 'DetectorMode' }, + '0018,700A' => { VR => 'SH', Name => 'DetectorID' }, + '0018,700C' => { VR => 'DA', Name => 'DateOfLastDetectorCalibration' }, + '0018,700E' => { VR => 'TM', Name => 'TimeOfLastDetectorCalibration' }, + '0018,7010' => { VR => 'IS', Name => 'DetectorExposuresSinceCalibration' }, + '0018,7011' => { VR => 'IS', Name => 'DetectorExposuresSinceManufactured' }, + '0018,7012' => { VR => 'DS', Name => 'DetectorTimeSinceLastExposure' }, + '0018,7014' => { VR => 'DS', Name => 'DetectorActiveTime' }, + '0018,7016' => { VR => 'DS', Name => 'DetectorActiveOffsetFromExposure' }, + '0018,701A' => { VR => 'DS', Name => 'DetectorBinning' }, + '0018,7020' => { VR => 'DS', Name => 'DetectorElementPhysicalSize' }, + '0018,7022' => { VR => 'DS', Name => 'DetectorElementSpacing' }, + '0018,7024' => { VR => 'CS', Name => 'DetectorActiveShape' }, + '0018,7026' => { VR => 'DS', Name => 'DetectorActiveDimensions' }, + '0018,7028' => { VR => 'DS', Name => 'DetectorActiveOrigin' }, + '0018,702A' => { VR => 'LO', Name => 'DetectorManufacturerName' }, + '0018,702B' => { VR => 'LO', Name => 'DetectorManufacturersModelName' }, + '0018,7030' => { VR => 'DS', Name => 'FieldOfViewOrigin' }, + '0018,7032' => { VR => 'DS', Name => 'FieldOfViewRotation' }, + '0018,7034' => { VR => 'CS', Name => 'FieldOfViewHorizontalFlip' }, + '0018,7040' => { VR => 'LT', Name => 'GridAbsorbingMaterial' }, + '0018,7041' => { VR => 'LT', Name => 'GridSpacingMaterial' }, + '0018,7042' => { VR => 'DS', Name => 'GridThickness' }, + '0018,7044' => { VR => 'DS', Name => 'GridPitch' }, + '0018,7046' => { VR => 'IS', Name => 'GridAspectRatio' }, + '0018,7048' => { VR => 'DS', Name => 'GridPeriod' }, + '0018,704C' => { VR => 'DS', Name => 'GridFocalDistance' }, + '0018,7050' => { VR => 'CS', Name => 'FilterMaterial' }, + '0018,7052' => { VR => 'DS', Name => 'FilterThicknessMinimum' }, + '0018,7054' => { VR => 'DS', Name => 'FilterThicknessMaximum' }, + '0018,7060' => { VR => 'CS', Name => 'ExposureControlMode' }, + '0018,7062' => { VR => 'LT', Name => 'ExposureControlModeDescription' }, + '0018,7064' => { VR => 'CS', Name => 'ExposureStatus' }, + '0018,7065' => { VR => 'DS', Name => 'PhototimerSetting' }, + '0018,8150' => { VR => 'DS', Name => 'ExposureTimeInMicroSec' }, + '0018,8151' => { VR => 'DS', Name => 'XRayTubeCurrentInMicroAmps' }, + '0018,9004' => { VR => 'CS', Name => 'ContentQualification' }, + '0018,9005' => { VR => 'SH', Name => 'PulseSequenceName' }, + '0018,9006' => { VR => 'SQ', Name => 'MRImagingModifierSequence' }, + '0018,9008' => { VR => 'CS', Name => 'EchoPulseSequence' }, + '0018,9009' => { VR => 'CS', Name => 'InversionRecovery' }, + '0018,9010' => { VR => 'CS', Name => 'FlowCompensation' }, + '0018,9011' => { VR => 'CS', Name => 'MultipleSpinEcho' }, + '0018,9012' => { VR => 'CS', Name => 'MultiPlanarExcitation' }, + '0018,9014' => { VR => 'CS', Name => 'PhaseContrast' }, + '0018,9015' => { VR => 'CS', Name => 'TimeOfFlightContrast' }, + '0018,9016' => { VR => 'CS', Name => 'Spoiling' }, + '0018,9017' => { VR => 'CS', Name => 'SteadyStatePulseSequence' }, + '0018,9018' => { VR => 'CS', Name => 'EchoPlanarPulseSequence' }, + '0018,9019' => { VR => 'FD', Name => 'TagAngleFirstAxis' }, + '0018,9020' => { VR => 'CS', Name => 'MagnetizationTransfer' }, + '0018,9021' => { VR => 'CS', Name => 'T2Preparation' }, + '0018,9022' => { VR => 'CS', Name => 'BloodSignalNulling' }, + '0018,9022' => { VR => 'CS', Name => 'BloodSignalNulling' }, + '0018,9024' => { VR => 'CS', Name => 'SaturationRecovery' }, + '0018,9025' => { VR => 'CS', Name => 'SpectrallySelectedSuppression' }, + '0018,9026' => { VR => 'CS', Name => 'SpectrallySelectedExcitation' }, + '0018,9027' => { VR => 'CS', Name => 'SpatialPresaturation' }, + '0018,9028' => { VR => 'CS', Name => 'Tagging' }, + '0018,9029' => { VR => 'CS', Name => 'OversamplingPhase' }, + '0018,9030' => { VR => 'FD', Name => 'TagSpacingFirstDimension' }, + '0018,9032' => { VR => 'CS', Name => 'GeometryOfKSpaceTraversal' }, + '0018,9033' => { VR => 'CS', Name => 'SegmentedKSpaceTraversal' }, + '0018,9034' => { VR => 'CS', Name => 'RectilinearPhaseEncodeReordering' }, + '0018,9035' => { VR => 'FD', Name => 'TagThickness' }, + '0018,9036' => { VR => 'CS', Name => 'PartialFourierDirection' }, + '0018,9037' => { VR => 'CS', Name => 'CardiacSynchronizationTechnique' }, + '0018,9041' => { VR => 'LO', Name => 'ReceiveCoilManufacturerName' }, + '0018,9042' => { VR => 'SQ', Name => 'MRReceiveCoilSequence' }, + '0018,9043' => { VR => 'CS', Name => 'ReceiveCoilType' }, + '0018,9044' => { VR => 'CS', Name => 'QuadratureReceiveCoil' }, + '0018,9045' => { VR => 'SQ', Name => 'MultiCoilDefinitionSequence' }, + '0018,9046' => { VR => 'LO', Name => 'MultiCoilConfiguration' }, + '0018,9047' => { VR => 'SH', Name => 'MultiCoilElementName' }, + '0018,9048' => { VR => 'CS', Name => 'MultiCoilElementUsed' }, + '0018,9049' => { VR => 'SQ', Name => 'MRTransmitCoilSequence' }, + '0018,9050' => { VR => 'LO', Name => 'TransmitCoilManufacturerName' }, + '0018,9051' => { VR => 'CS', Name => 'TransmitCoilType' }, + '0018,9052' => { VR => 'FD', Name => 'SpectralWidth' }, + '0018,9053' => { VR => 'FD', Name => 'ChemicalShiftReference' }, + '0018,9054' => { VR => 'CS', Name => 'VolumeLocalizationTechnique' }, + '0018,9058' => { VR => 'US', Name => 'MRAcquisitionFrequencyEncodeSteps' }, + '0018,9059' => { VR => 'CS', Name => 'Decoupling' }, + '0018,9060' => { VR => 'CS', Name => 'DecoupledNucleus' }, + '0018,9061' => { VR => 'FD', Name => 'DecouplingFrequency' }, + '0018,9062' => { VR => 'CS', Name => 'DecouplingMethod' }, + '0018,9063' => { VR => 'FD', Name => 'DecouplingChemicalShiftReference' }, + '0018,9064' => { VR => 'CS', Name => 'KSpaceFiltering' }, + '0018,9065' => { VR => 'CS', Name => 'TimeDomainFiltering' }, + '0018,9066' => { VR => 'US', Name => 'NumberOfZeroFills' }, + '0018,9067' => { VR => 'CS', Name => 'BaselineCorrection' }, + '0018,9069' => { VR => 'FD', Name => 'ParallelReductionFactorInPlane' }, + '0018,9070' => { VR => 'FD', Name => 'CardiacRRIntervalSpecified' }, + '0018,9073' => { VR => 'FD', Name => 'AcquisitionDuration' }, + '0018,9074' => { VR => 'DT', Name => 'FrameAcquisitionDateTime' }, + '0018,9075' => { VR => 'CS', Name => 'DiffusionDirectionality' }, + '0018,9076' => { VR => 'SQ', Name => 'DiffusionGradientDirectionSequence' }, + '0018,9077' => { VR => 'CS', Name => 'ParallelAcquisition' }, + '0018,9078' => { VR => 'CS', Name => 'ParallelAcquisitionTechnique' }, + '0018,9079' => { VR => 'FD', Name => 'InversionTimes' }, + '0018,9080' => { VR => 'ST', Name => 'MetaboliteMapDescription' }, + '0018,9081' => { VR => 'CS', Name => 'PartialFourier' }, + '0018,9082' => { VR => 'FD', Name => 'EffectiveEchoTime' }, + '0018,9083' => { VR => 'SQ', Name => 'MetaboliteMapCodeSequence' }, + '0018,9084' => { VR => 'SQ', Name => 'ChemicalShiftSequence' }, + '0018,9085' => { VR => 'CS', Name => 'CardiacSignalSource' }, + '0018,9087' => { VR => 'FD', Name => 'DiffusionBValue' }, + '0018,9089' => { VR => 'FD', Name => 'DiffusionGradientOrientation' }, + '0018,9090' => { VR => 'FD', Name => 'VelocityEncodingDirection' }, + '0018,9091' => { VR => 'FD', Name => 'VelocityEncodingMinimumValue' }, + '0018,9093' => { VR => 'US', Name => 'NumberOfKSpaceTrajectories' }, + '0018,9094' => { VR => 'CS', Name => 'CoverageOfKSpace' }, + '0018,9095' => { VR => 'UL', Name => 'SpectroscopyAcquisitionPhaseRows' }, + '0018,9096' => { VR => 'FD', Name => 'ParallelReductFactorInPlaneRetired' }, + '0018,9098' => { VR => 'FD', Name => 'TransmitterFrequency' }, + '0018,9100' => { VR => 'CS', Name => 'ResonantNucleus' }, + '0018,9101' => { VR => 'CS', Name => 'FrequencyCorrection' }, + '0018,9103' => { VR => 'SQ', Name => 'MRSpectroscopyFOV-GeometrySequence' }, + '0018,9104' => { VR => 'FD', Name => 'SlabThickness' }, + '0018,9105' => { VR => 'FD', Name => 'SlabOrientation' }, + '0018,9106' => { VR => 'FD', Name => 'MidSlabPosition' }, + '0018,9107' => { VR => 'SQ', Name => 'MRSpatialSaturationSequence' }, + '0018,9112' => { VR => 'SQ', Name => 'MRTimingAndRelatedParametersSeq' }, + '0018,9114' => { VR => 'SQ', Name => 'MREchoSequence' }, + '0018,9115' => { VR => 'SQ', Name => 'MRModifierSequence' }, + '0018,9117' => { VR => 'SQ', Name => 'MRDiffusionSequence' }, + '0018,9118' => { VR => 'SQ', Name => 'CardiacTriggerSequence' }, + '0018,9119' => { VR => 'SQ', Name => 'MRAveragesSequence' }, + '0018,9125' => { VR => 'SQ', Name => 'MRFOV-GeometrySequence' }, + '0018,9126' => { VR => 'SQ', Name => 'VolumeLocalizationSequence' }, + '0018,9127' => { VR => 'UL', Name => 'SpectroscopyAcquisitionDataColumns' }, + '0018,9147' => { VR => 'CS', Name => 'DiffusionAnisotropyType' }, + '0018,9151' => { VR => 'DT', Name => 'FrameReferenceDateTime' }, + '0018,9152' => { VR => 'SQ', Name => 'MRMetaboliteMapSequence' }, + '0018,9155' => { VR => 'FD', Name => 'ParallelReductionFactorOutOfPlane' }, + '0018,9159' => { VR => 'UL', Name => 'SpectroscopyOutOfPlanePhaseSteps' }, + '0018,9166' => { VR => 'CS', Name => 'BulkMotionStatus' }, + '0018,9168' => { VR => 'FD', Name => 'ParallelReductionFactSecondInPlane' }, + '0018,9169' => { VR => 'CS', Name => 'CardiacBeatRejectionTechnique' }, + '0018,9170' => { VR => 'CS', Name => 'RespiratoryMotionCompTechnique' }, + '0018,9171' => { VR => 'CS', Name => 'RespiratorySignalSource' }, + '0018,9172' => { VR => 'CS', Name => 'BulkMotionCompensationTechnique' }, + '0018,9173' => { VR => 'CS', Name => 'BulkMotionSignalSource' }, + '0018,9174' => { VR => 'CS', Name => 'ApplicableSafetyStandardAgency' }, + '0018,9175' => { VR => 'LO', Name => 'ApplicableSafetyStandardDescr' }, + '0018,9176' => { VR => 'SQ', Name => 'OperatingModeSequence' }, + '0018,9177' => { VR => 'CS', Name => 'OperatingModeType' }, + '0018,9178' => { VR => 'CS', Name => 'OperatingMode' }, + '0018,9179' => { VR => 'CS', Name => 'SpecificAbsorptionRateDefinition' }, + '0018,9180' => { VR => 'CS', Name => 'GradientOutputType' }, + '0018,9181' => { VR => 'FD', Name => 'SpecificAbsorptionRateValue' }, + '0018,9182' => { VR => 'FD', Name => 'GradientOutput' }, + '0018,9183' => { VR => 'CS', Name => 'FlowCompensationDirection' }, + '0018,9184' => { VR => 'FD', Name => 'TaggingDelay' }, + '0018,9185' => { VR => 'ST', Name => 'RespiratoryMotionCompTechDescr' }, + '0018,9186' => { VR => 'SH', Name => 'RespiratorySignalSourceID' }, + '0018,9195' => { VR => 'FD', Name => 'ChemicalShiftsMinIntegrateLimitHz' }, + '0018,9196' => { VR => 'FD', Name => 'ChemicalShiftsMaxIntegrateLimitHz' }, + '0018,9197' => { VR => 'SQ', Name => 'MRVelocityEncodingSequence' }, + '0018,9198' => { VR => 'CS', Name => 'FirstOrderPhaseCorrection' }, + '0018,9199' => { VR => 'CS', Name => 'WaterReferencedPhaseCorrection' }, + '0018,9200' => { VR => 'CS', Name => 'MRSpectroscopyAcquisitionType' }, + '0018,9214' => { VR => 'CS', Name => 'RespiratoryCyclePosition' }, + '0018,9217' => { VR => 'FD', Name => 'VelocityEncodingMaximumValue' }, + '0018,9218' => { VR => 'FD', Name => 'TagSpacingSecondDimension' }, + '0018,9219' => { VR => 'SS', Name => 'TagAngleSecondAxis' }, + '0018,9220' => { VR => 'FD', Name => 'FrameAcquisitionDuration' }, + '0018,9226' => { VR => 'SQ', Name => 'MRImageFrameTypeSequence' }, + '0018,9227' => { VR => 'SQ', Name => 'MRSpectroscopyFrameTypeSequence' }, + '0018,9231' => { VR => 'US', Name => 'MRAcqPhaseEncodingStepsInPlane' }, + '0018,9232' => { VR => 'US', Name => 'MRAcqPhaseEncodingStepsOutOfPlane' }, + '0018,9234' => { VR => 'UL', Name => 'SpectroscopyAcqPhaseColumns' }, + '0018,9236' => { VR => 'CS', Name => 'CardiacCyclePosition' }, + '0018,9239' => { VR => 'SQ', Name => 'SpecificAbsorptionRateSequence' }, + '0018,9240' => { VR => 'US', Name => 'RFEchoTrainLength' }, + '0018,9241' => { VR => 'US', Name => 'GradientEchoTrainLength' }, + '0018,9295' => { VR => 'FD', Name => 'ChemicalShiftsMinIntegrateLimitPPM' }, + '0018,9296' => { VR => 'FD', Name => 'ChemicalShiftsMaxIntegrateLimitPPM' }, + '0018,9301' => { VR => 'SQ', Name => 'CTAcquisitionTypeSequence' }, + '0018,9302' => { VR => 'CS', Name => 'AcquisitionType' }, + '0018,9303' => { VR => 'FD', Name => 'TubeAngle' }, + '0018,9304' => { VR => 'SQ', Name => 'CTAcquisitionDetailsSequence' }, + '0018,9305' => { VR => 'FD', Name => 'RevolutionTime' }, + '0018,9306' => { VR => 'FD', Name => 'SingleCollimationWidth' }, + '0018,9307' => { VR => 'FD', Name => 'TotalCollimationWidth' }, + '0018,9308' => { VR => 'SQ', Name => 'CTTableDynamicsSequence' }, + '0018,9309' => { VR => 'FD', Name => 'TableSpeed' }, + '0018,9310' => { VR => 'FD', Name => 'TableFeedPerRotation' }, + '0018,9311' => { VR => 'FD', Name => 'SpiralPitchFactor' }, + '0018,9312' => { VR => 'SQ', Name => 'CTGeometrySequence' }, + '0018,9313' => { VR => 'FD', Name => 'DataCollectionCenterPatient' }, + '0018,9314' => { VR => 'SQ', Name => 'CTReconstructionSequence' }, + '0018,9315' => { VR => 'CS', Name => 'ReconstructionAlgorithm' }, + '0018,9316' => { VR => 'CS', Name => 'ConvolutionKernelGroup' }, + '0018,9317' => { VR => 'FD', Name => 'ReconstructionFieldOfView' }, + '0018,9318' => { VR => 'FD', Name => 'ReconstructionTargetCenterPatient' }, + '0018,9319' => { VR => 'FD', Name => 'ReconstructionAngle' }, + '0018,9320' => { VR => 'SH', Name => 'ImageFilter' }, + '0018,9321' => { VR => 'SQ', Name => 'CTExposureSequence' }, + '0018,9322' => { VR => 'FD', Name => 'ReconstructionPixelSpacing' }, + '0018,9323' => { VR => 'CS', Name => 'ExposureModulationType' }, + '0018,9324' => { VR => 'FD', Name => 'EstimatedDoseSaving' }, + '0018,9325' => { VR => 'SQ', Name => 'CTXRayDetailsSequence' }, + '0018,9326' => { VR => 'SQ', Name => 'CTPositionSequence' }, + '0018,9327' => { VR => 'FD', Name => 'TablePosition' }, + '0018,9328' => { VR => 'FD', Name => 'ExposureTimeInMilliSec' }, + '0018,9329' => { VR => 'SQ', Name => 'CTImageFrameTypeSequence' }, + '0018,9330' => { VR => 'FD', Name => 'XRayTubeCurrentInMilliAmps' }, + '0018,9332' => { VR => 'FD', Name => 'ExposureInMilliAmpSec' }, + '0018,9333' => { VR => 'CS', Name => 'ConstantVolumeFlag' }, + '0018,9334' => { VR => 'CS', Name => 'FluoroscopyFlag' }, + '0018,9335' => { VR => 'FD', Name => 'SourceToDataCollectionCenterDist' }, + '0018,9337' => { VR => 'US', Name => 'ContrastBolusAgentNumber' }, + '0018,9338' => { VR => 'SQ', Name => 'ContrastBolusIngredientCodeSeq' }, + '0018,9340' => { VR => 'SQ', Name => 'ContrastAdministrationProfileSeq' }, + '0018,9341' => { VR => 'SQ', Name => 'ContrastBolusUsageSequence' }, + '0018,9342' => { VR => 'CS', Name => 'ContrastBolusAgentAdministered' }, + '0018,9343' => { VR => 'CS', Name => 'ContrastBolusAgentDetected' }, + '0018,9344' => { VR => 'CS', Name => 'ContrastBolusAgentPhase' }, + '0018,9345' => { VR => 'FD', Name => 'CTDIvol' }, + '0018,9346' => { VR => 'SQ', Name => 'CTDIPhantomTypeCodeSequence' }, + '0018,9351' => { VR => 'FL', Name => 'CalciumScoringMassFactorPatient' }, + '0018,9352' => { VR => 'FL', Name => 'CalciumScoringMassFactorDevice' }, + '0018,9353' => { VR => 'FL', Name => 'EnergyWeightingFactor' }, + '0018,9360' => { VR => 'SQ', Name => 'CTAdditionalXRaySourceSequence' }, + '0018,9401' => { VR => 'SQ', Name => 'ProjectionPixelCalibrationSequence' }, + '0018,9402' => { VR => 'FL', Name => 'DistanceSourceToIsocenter' }, + '0018,9403' => { VR => 'FL', Name => 'DistanceObjectToTableTop' }, + '0018,9404' => { VR => 'FL', Name => 'ObjectPixelSpacingInCenterOfBeam' }, + '0018,9405' => { VR => 'SQ', Name => 'PositionerPositionSequence' }, + '0018,9406' => { VR => 'SQ', Name => 'TablePositionSequence' }, + '0018,9407' => { VR => 'SQ', Name => 'CollimatorShapeSequence' }, + '0018,9412' => { VR => 'SQ', Name => 'XA-XRFFrameCharacteristicsSequence' }, + '0018,9417' => { VR => 'SQ', Name => 'FrameAcquisitionSequence' }, + '0018,9420' => { VR => 'CS', Name => 'XRayReceptorType' }, + '0018,9423' => { VR => 'LO', Name => 'AcquisitionProtocolName' }, + '0018,9424' => { VR => 'LT', Name => 'AcquisitionProtocolDescription' }, + '0018,9425' => { VR => 'CS', Name => 'ContrastBolusIngredientOpaque' }, + '0018,9426' => { VR => 'FL', Name => 'DistanceReceptorPlaneToDetHousing' }, + '0018,9427' => { VR => 'CS', Name => 'IntensifierActiveShape' }, + '0018,9428' => { VR => 'FL', Name => 'IntensifierActiveDimensions' }, + '0018,9429' => { VR => 'FL', Name => 'PhysicalDetectorSize' }, + '0018,9430' => { VR => 'US', Name => 'PositionOfIsocenterProjection' }, + '0018,9432' => { VR => 'SQ', Name => 'FieldOfViewSequence' }, + '0018,9433' => { VR => 'LO', Name => 'FieldOfViewDescription' }, + '0018,9434' => { VR => 'SQ', Name => 'ExposureControlSensingRegionsSeq' }, + '0018,9435' => { VR => 'CS', Name => 'ExposureControlSensingRegionShape' }, + '0018,9436' => { VR => 'SS', Name => 'ExposureControlSensRegionLeftEdge' }, + '0018,9437' => { VR => 'SS', Name => 'ExposureControlSensRegionRightEdge' }, + '0018,9440' => { VR => 'SS', Name => 'CenterOfCircExposControlSensRegion' }, + '0018,9441' => { VR => 'US', Name => 'RadiusOfCircExposControlSensRegion' }, + '0018,9447' => { VR => 'FL', Name => 'ColumnAngulationPatient' }, + '0018,9449' => { VR => 'FL', Name => 'BeamAngle' }, + '0018,9451' => { VR => 'SQ', Name => 'FrameDetectorParametersSequence' }, + '0018,9452' => { VR => 'FL', Name => 'CalculatedAnatomyThickness' }, + '0018,9455' => { VR => 'SQ', Name => 'CalibrationSequence' }, + '0018,9456' => { VR => 'SQ', Name => 'ObjectThicknessSequence' }, + '0018,9457' => { VR => 'CS', Name => 'PlaneIdentification' }, + '0018,9461' => { VR => 'FL', Name => 'FieldOfViewDimensionsInFloat' }, + '0018,9462' => { VR => 'SQ', Name => 'IsocenterReferenceSystemSequence' }, + '0018,9463' => { VR => 'FL', Name => 'PositionerIsocenterPrimaryAngle' }, + '0018,9464' => { VR => 'FL', Name => 'PositionerIsocenterSecondaryAngle' }, + '0018,9465' => { VR => 'FL', Name => 'PositionerIsocenterDetRotAngle' }, + '0018,9466' => { VR => 'FL', Name => 'TableXPositionToIsocenter' }, + '0018,9467' => { VR => 'FL', Name => 'TableYPositionToIsocenter' }, + '0018,9468' => { VR => 'FL', Name => 'TableZPositionToIsocenter' }, + '0018,9469' => { VR => 'FL', Name => 'TableHorizontalRotationAngle' }, + '0018,9470' => { VR => 'FL', Name => 'TableHeadTiltAngle' }, + '0018,9471' => { VR => 'FL', Name => 'TableCradleTiltAngle' }, + '0018,9472' => { VR => 'SQ', Name => 'FrameDisplayShutterSequence' }, + '0018,9473' => { VR => 'FL', Name => 'AcquiredImageAreaDoseProduct' }, + '0018,9474' => { VR => 'CS', Name => 'CArmPositionerTabletopRelationship' }, + '0018,9476' => { VR => 'SQ', Name => 'XRayGeometrySequence' }, + '0018,9477' => { VR => 'SQ', Name => 'IrradiationEventIDSequence' }, + '0018,9504' => { VR => 'SQ', Name => 'XRay3DFrameTypeSequence' }, + '0018,9506' => { VR => 'SQ', Name => 'ContributingSourcesSequence' }, + '0018,9507' => { VR => 'SQ', Name => 'XRay3DAcquisitionSequence' }, + '0018,9508' => { VR => 'FL', Name => 'PrimaryPositionerScanArc' }, + '0018,9509' => { VR => 'FL', Name => 'SecondaryPositionerScanArc' }, + '0018,9510' => { VR => 'FL', Name => 'PrimaryPositionerScanStartAngle' }, + '0018,9511' => { VR => 'FL', Name => 'SecondaryPositionerScanStartAngle' }, + '0018,9514' => { VR => 'FL', Name => 'PrimaryPositionerIncrement' }, + '0018,9515' => { VR => 'FL', Name => 'SecondaryPositionerIncrement' }, + '0018,9516' => { VR => 'DT', Name => 'StartAcquisitionDateTime' }, + '0018,9517' => { VR => 'DT', Name => 'EndAcquisitionDateTime' }, + '0018,9524' => { VR => 'LO', Name => 'ApplicationName' }, + '0018,9525' => { VR => 'LO', Name => 'ApplicationVersion' }, + '0018,9526' => { VR => 'LO', Name => 'ApplicationManufacturer' }, + '0018,9527' => { VR => 'CS', Name => 'AlgorithmType' }, + '0018,9528' => { VR => 'LO', Name => 'AlgorithmDescription' }, + '0018,9530' => { VR => 'SQ', Name => 'XRay3DReconstructionSequence' }, + '0018,9531' => { VR => 'LO', Name => 'ReconstructionDescription' }, + '0018,9538' => { VR => 'SQ', Name => 'PerProjectionAcquisitionSequence' }, + '0018,9601' => { VR => 'SQ', Name => 'DiffusionBMatrixSequence' }, + '0018,9602' => { VR => 'FD', Name => 'DiffusionBValueXX' }, + '0018,9603' => { VR => 'FD', Name => 'DiffusionBValueXY' }, + '0018,9604' => { VR => 'FD', Name => 'DiffusionBValueXZ' }, + '0018,9605' => { VR => 'FD', Name => 'DiffusionBValueYY' }, + '0018,9606' => { VR => 'FD', Name => 'DiffusionBValueYZ' }, + '0018,9607' => { VR => 'FD', Name => 'DiffusionBValueZZ' }, + '0018,9701' => { VR => 'DT', Name => 'DecayCorrectionDateTime' }, + '0018,9715' => { VR => 'FD', Name => 'StartDensityThreshold' }, + '0018,9722' => { VR => 'FD', Name => 'TerminationTimeThreshold' }, + '0018,9725' => { VR => 'CS', Name => 'DetectorGeometry' }, + '0018,9727' => { VR => 'FD', Name => 'AxialDetectorDimension' }, + '0018,9735' => { VR => 'SQ', Name => 'PETPositionSequence' }, + '0018,9739' => { VR => 'US', Name => 'NumberOfIterations' }, + '0018,9740' => { VR => 'US', Name => 'NumberOfSubsets' }, + '0018,9751' => { VR => 'SQ', Name => 'PETFrameTypeSequence' }, + '0018,9756' => { VR => 'CS', Name => 'ReconstructionType' }, + '0018,9758' => { VR => 'CS', Name => 'DecayCorrected' }, + '0018,9759' => { VR => 'CS', Name => 'AttenuationCorrected' }, + '0018,9760' => { VR => 'CS', Name => 'ScatterCorrected' }, + '0018,9761' => { VR => 'CS', Name => 'DeadTimeCorrected' }, + '0018,9762' => { VR => 'CS', Name => 'GantryMotionCorrected' }, + '0018,9763' => { VR => 'CS', Name => 'PatientMotionCorrected' }, + '0018,9765' => { VR => 'CS', Name => 'RandomsCorrected' }, + '0018,9767' => { VR => 'CS', Name => 'SensitivityCalibrated' }, + '0018,9801' => { VR => 'FD', Name => 'DepthsOfFocus' }, + '0018,9804' => { VR => 'DT', Name => 'ExclusionStartDatetime' }, + '0018,9805' => { VR => 'FD', Name => 'ExclusionDuration' }, + '0018,9807' => { VR => 'SQ', Name => 'ImageDataTypeSequence' }, + '0018,9808' => { VR => 'CS', Name => 'DataType' }, + '0018,980B' => { VR => 'CS', Name => 'AliasedDataType' }, + '0018,A001' => { VR => 'SQ', Name => 'ContributingEquipmentSequence' }, + '0018,A002' => { VR => 'DT', Name => 'ContributionDateTime' }, + '0018,A003' => { VR => 'ST', Name => 'ContributionDescription' }, + # GEMS_ACQU_01 (ref 4) + '0019,1002' => { VR => 'SL', Name => 'NumberOfCellsIInDetector' }, + '0019,1003' => { VR => 'DS', Name => 'CellNumberAtTheta' }, + '0019,1004' => { VR => 'DS', Name => 'CellSpacing' }, + '0019,100F' => { VR => 'DS', Name => 'HorizFrameOfRef' }, + '0019,1011' => { VR => 'SS', Name => 'SeriesContrast' }, + '0019,1012' => { VR => 'SS', Name => 'LastPseq' }, + '0019,1013' => { VR => 'SS', Name => 'StartNumberForBaseline' }, + '0019,1014' => { VR => 'SS', Name => 'EndNumberForBaseline' }, + '0019,1015' => { VR => 'SS', Name => 'StartNumberForEnhancedScans' }, + '0019,1016' => { VR => 'SS', Name => 'EndNumberForEnhancedScans' }, + '0019,1017' => { VR => 'SS', Name => 'SeriesPlane' }, + '0019,1018' => { VR => 'LO', Name => 'FirstScanRas' }, + '0019,1019' => { VR => 'DS', Name => 'FirstScanLocation' }, + '0019,101A' => { VR => 'LO', Name => 'LastScanRas' }, + '0019,101B' => { VR => 'DS', Name => 'LastScanLoc' }, + '0019,101E' => { VR => 'DS', Name => 'DisplayFieldOfView' }, + '0019,1023' => { VR => 'DS', Name => 'TableSpeed' }, + '0019,1024' => { VR => 'DS', Name => 'MidScanTime' }, + '0019,1025' => { VR => 'SS', Name => 'MidScanFlag' }, + '0019,1026' => { VR => 'SL', Name => 'DegreesOfAzimuth' }, + '0019,1027' => { VR => 'DS', Name => 'GantryPeriod' }, + '0019,102A' => { VR => 'DS', Name => 'XRayOnPosition' }, + '0019,102B' => { VR => 'DS', Name => 'XRayOffPosition' }, + '0019,102C' => { VR => 'SL', Name => 'NumberOfTriggers' }, + '0019,102E' => { VR => 'DS', Name => 'AngleOfFirstView' }, + '0019,102F' => { VR => 'DS', Name => 'TriggerFrequency' }, + '0019,1039' => { VR => 'SS', Name => 'ScanFOVType' }, + '0019,1040' => { VR => 'SS', Name => 'StatReconFlag' }, + '0019,1041' => { VR => 'SS', Name => 'ComputeType' }, + '0019,1042' => { VR => 'SS', Name => 'SegmentNumber' }, + '0019,1043' => { VR => 'SS', Name => 'TotalSegmentsRequested' }, + '0019,1044' => { VR => 'DS', Name => 'InterscanDelay' }, + '0019,1047' => { VR => 'SS', Name => 'ViewCompressionFactor' }, + '0019,104A' => { VR => 'SS', Name => 'TotalNoOfRefChannels' }, + '0019,104B' => { VR => 'SL', Name => 'DataSizeForScanData' }, + '0019,1052' => { VR => 'SS', Name => 'ReconPostProcflag' }, + '0019,1057' => { VR => 'SS', Name => 'CTWaterNumber' }, + '0019,1058' => { VR => 'SS', Name => 'CTBoneNumber' }, + '0019,105A' => { VR => 'FL', Name => 'AcquisitionDuration' }, + '0019,105E' => { VR => 'SL', Name => 'NumberOfChannels' }, + '0019,105F' => { VR => 'SL', Name => 'IncrementBetweenChannels' }, + '0019,1060' => { VR => 'SL', Name => 'StartingView' }, + '0019,1061' => { VR => 'SL', Name => 'NumberOfViews' }, + '0019,1062' => { VR => 'SL', Name => 'IncrementBetweenViews' }, + '0019,106A' => { VR => 'SS', Name => 'DependantOnNoViewsProcessed' }, + '0019,106B' => { VR => 'SS', Name => 'FieldOfViewInDetectorCells' }, + '0019,1070' => { VR => 'SS', Name => 'ValueOfBackProjectionButton' }, + '0019,1071' => { VR => 'SS', Name => 'SetIfFatqEstimatesWereUsed' }, + '0019,1072' => { VR => 'DS', Name => 'ZChanAvgOverViews' }, + '0019,1073' => { VR => 'DS', Name => 'AvgOfLeftRefChansOverViews' }, + '0019,1074' => { VR => 'DS', Name => 'MaxLeftChanOverViews' }, + '0019,1075' => { VR => 'DS', Name => 'AvgOfRightRefChansOverViews' }, + '0019,1076' => { VR => 'DS', Name => 'MaxRightChanOverViews' }, + '0019,107D' => { VR => 'DS', Name => 'SecondEcho' }, + '0019,107E' => { VR => 'SS', Name => 'NumberOfEchoes' }, + '0019,107F' => { VR => 'DS', Name => 'TableDelta' }, + '0019,1081' => { VR => 'SS', Name => 'Contiguous' }, + '0019,1084' => { VR => 'DS', Name => 'PeakSAR' }, + '0019,1085' => { VR => 'SS', Name => 'MonitorSAR' }, + '0019,1087' => { VR => 'DS', Name => 'CardiacRepetitionTime' }, + '0019,1088' => { VR => 'SS', Name => 'ImagesPerCardiacCycle' }, + '0019,108A' => { VR => 'SS', Name => 'ActualReceiveGainAnalog' }, + '0019,108B' => { VR => 'SS', Name => 'ActualReceiveGainDigital' }, + '0019,108D' => { VR => 'DS', Name => 'DelayAfterTrigger' }, + '0019,108F' => { VR => 'SS', Name => 'Swappf' }, + '0019,1090' => { VR => 'SS', Name => 'PauseInterval' }, + '0019,1091' => { VR => 'DS', Name => 'PulseTime' }, + '0019,1092' => { VR => 'SL', Name => 'SliceOffsetOnFreqAxis' }, + '0019,1093' => { VR => 'DS', Name => 'CenterFrequency' }, + '0019,1094' => { VR => 'SS', Name => 'TransmitGain' }, + '0019,1095' => { VR => 'SS', Name => 'AnalogReceiverGain' }, + '0019,1096' => { VR => 'SS', Name => 'DigitalReceiverGain' }, + '0019,1097' => { VR => 'SL', Name => 'BitmapDefiningCVs' }, + '0019,1098' => { VR => 'SS', Name => 'CenterFreqMethod' }, + '0019,109B' => { VR => 'SS', Name => 'PulseSeqMode' }, + '0019,109C' => { VR => 'LO', Name => 'PulseSeqName' }, + '0019,109D' => { VR => 'DT', Name => 'PulseSeqDate' }, + '0019,109E' => { VR => 'LO', Name => 'InternalPulseSeqName' }, + '0019,109F' => { VR => 'SS', Name => 'TransmittingCoil' }, + '0019,10A0' => { VR => 'SS', Name => 'SurfaceCoilType' }, + '0019,10A1' => { VR => 'SS', Name => 'ExtremityCoilFlag' }, + '0019,10A2' => { VR => 'SL', Name => 'RawDataRunNumber' }, + '0019,10A3' => { VR => 'UL', Name => 'CalibratedFieldStrength' }, + '0019,10A4' => { VR => 'SS', Name => 'SATFatWaterBone' }, + '0019,10A5' => { VR => 'DS', Name => 'ReceiveBandwidth' }, + '0019,10A7' => { VR => 'DS', Name => 'UserData01' }, + '0019,10A8' => { VR => 'DS', Name => 'UserData02' }, + '0019,10A9' => { VR => 'DS', Name => 'UserData03' }, + '0019,10AA' => { VR => 'DS', Name => 'UserData04' }, + '0019,10AB' => { VR => 'DS', Name => 'UserData05' }, + '0019,10AC' => { VR => 'DS', Name => 'UserData06' }, + '0019,10AD' => { VR => 'DS', Name => 'UserData07' }, + '0019,10AE' => { VR => 'DS', Name => 'UserData08' }, + '0019,10AF' => { VR => 'DS', Name => 'UserData09' }, + '0019,10B0' => { VR => 'DS', Name => 'UserData10' }, + '0019,10B1' => { VR => 'DS', Name => 'UserData11' }, + '0019,10B2' => { VR => 'DS', Name => 'UserData12' }, + '0019,10B3' => { VR => 'DS', Name => 'UserData13' }, + '0019,10B4' => { VR => 'DS', Name => 'UserData14' }, + '0019,10B5' => { VR => 'DS', Name => 'UserData15' }, + '0019,10B6' => { VR => 'DS', Name => 'UserData16' }, + '0019,10B7' => { VR => 'DS', Name => 'UserData17' }, + '0019,10B8' => { VR => 'DS', Name => 'UserData18' }, + '0019,10B9' => { VR => 'DS', Name => 'UserData19' }, + '0019,10BA' => { VR => 'DS', Name => 'UserData20' }, + '0019,10BB' => { VR => 'DS', Name => 'UserData21' }, + '0019,10BC' => { VR => 'DS', Name => 'UserData22' }, + '0019,10BD' => { VR => 'DS', Name => 'UserData23' }, + '0019,10BE' => { VR => 'DS', Name => 'ProjectionAngle' }, + '0019,10C0' => { VR => 'SS', Name => 'SaturationPlanes' }, + '0019,10C1' => { VR => 'SS', Name => 'SurfaceCoilIntensity' }, + '0019,10C2' => { VR => 'SS', Name => 'SATLocationR' }, + '0019,10C3' => { VR => 'SS', Name => 'SATLocationL' }, + '0019,10C4' => { VR => 'SS', Name => 'SATLocationA' }, + '0019,10C5' => { VR => 'SS', Name => 'SATLocationP' }, + '0019,10C6' => { VR => 'SS', Name => 'SATLocationH' }, + '0019,10C7' => { VR => 'SS', Name => 'SATLocationF' }, + '0019,10C8' => { VR => 'SS', Name => 'SATThicknessR-L' }, + '0019,10C9' => { VR => 'SS', Name => 'SATThicknessA-P' }, + '0019,10CA' => { VR => 'SS', Name => 'SATThicknessH-F' }, + '0019,10CB' => { VR => 'SS', Name => 'PrescribedFlowAxis' }, + '0019,10CC' => { VR => 'SS', Name => 'VelocityEncoding' }, + '0019,10CD' => { VR => 'SS', Name => 'ThicknessDisclaimer' }, + '0019,10CE' => { VR => 'SS', Name => 'PrescanType' }, + '0019,10CF' => { VR => 'SS', Name => 'PrescanStatus' }, + '0019,10D0' => { VR => 'SH', Name => 'RawDataType' }, + '0019,10D2' => { VR => 'SS', Name => 'ProjectionAlgorithm' }, + '0019,10D3' => { VR => 'SH', Name => 'ProjectionAlgorithm' }, + '0019,10D5' => { VR => 'SS', Name => 'FractionalEcho' }, + '0019,10D6' => { VR => 'SS', Name => 'PrepPulse' }, + '0019,10D7' => { VR => 'SS', Name => 'CardiacPhases' }, + '0019,10D8' => { VR => 'SS', Name => 'VariableEchoflag' }, + '0019,10D9' => { VR => 'DS', Name => 'ConcatenatedSAT' }, + '0019,10DA' => { VR => 'SS', Name => 'ReferenceChannelUsed' }, + '0019,10DB' => { VR => 'DS', Name => 'BackProjectorCoefficient' }, + '0019,10DC' => { VR => 'SS', Name => 'PrimarySpeedCorrectionUsed' }, + '0019,10DD' => { VR => 'SS', Name => 'OverrangeCorrectionUsed' }, + '0019,10DE' => { VR => 'DS', Name => 'DynamicZAlphaValue' }, + '0019,10DF' => { VR => 'DS', Name => 'UserData' }, + '0019,10E0' => { VR => 'DS', Name => 'UserData' }, + '0019,10E2' => { VR => 'DS', Name => 'VelocityEncodeScale' }, + '0019,10F2' => { VR => 'SS', Name => 'FastPhases' }, + '0019,10F9' => { VR => 'DS', Name => 'TransmissionGain' }, + # relationship group + '0020,0000' => { VR => 'UL', Name => 'RelationshipGroupLength' }, + '0020,000D' => { VR => 'UI', Name => 'StudyInstanceUID' }, + '0020,000E' => { VR => 'UI', Name => 'SeriesInstanceUID' }, + '0020,0010' => { VR => 'SH', Name => 'StudyID' }, + '0020,0011' => { VR => 'IS', Name => 'SeriesNumber' }, + '0020,0012' => { VR => 'IS', Name => 'AcquisitionNumber' }, + '0020,0013' => { VR => 'IS', Name => 'InstanceNumber' }, + '0020,0014' => { VR => 'IS', Name => 'IsotopeNumber' }, + '0020,0015' => { VR => 'IS', Name => 'PhaseNumber' }, + '0020,0016' => { VR => 'IS', Name => 'IntervalNumber' }, + '0020,0017' => { VR => 'IS', Name => 'TimeSlotNumber' }, + '0020,0018' => { VR => 'IS', Name => 'AngleNumber' }, + '0020,0019' => { VR => 'IS', Name => 'ItemNumber' }, + '0020,0020' => { VR => 'CS', Name => 'PatientOrientation' }, + '0020,0022' => { VR => 'IS', Name => 'OverlayNumber' }, + '0020,0024' => { VR => 'IS', Name => 'CurveNumber' }, + '0020,0026' => { VR => 'IS', Name => 'LookupTableNumber' }, + '0020,0030' => { VR => 'DS', Name => 'ImagePosition' }, + '0020,0032' => { VR => 'DS', Name => 'ImagePositionPatient' }, + '0020,0035' => { VR => 'DS', Name => 'ImageOrientation' }, + '0020,0037' => { VR => 'DS', Name => 'ImageOrientationPatient' }, + '0020,0050' => { VR => 'DS', Name => 'Location' }, + '0020,0052' => { VR => 'UI', Name => 'FrameOfReferenceUID' }, + '0020,0060' => { VR => 'CS', Name => 'Laterality' }, + '0020,0062' => { VR => 'CS', Name => 'ImageLaterality' }, + '0020,0070' => { VR => 'LO', Name => 'ImageGeometryType' }, + '0020,0080' => { VR => 'CS', Name => 'MaskingImage' }, + '0020,0100' => { VR => 'IS', Name => 'TemporalPositionIdentifier' }, + '0020,0105' => { VR => 'IS', Name => 'NumberOfTemporalPositions' }, + '0020,0110' => { VR => 'DS', Name => 'TemporalResolution' }, + '0020,0200' => { VR => 'UI', Name => 'SynchronizationFrameOfReferenceUID' }, + '0020,1000' => { VR => 'IS', Name => 'SeriesInStudy' }, + '0020,1001' => { VR => 'IS', Name => 'AcquisitionsInSeries' }, + '0020,1002' => { VR => 'IS', Name => 'ImagesInAcquisition' }, + '0020,1003' => { VR => 'IS', Name => 'ImagesInSeries' }, + '0020,1004' => { VR => 'IS', Name => 'AcquisitionsInStudy' }, + '0020,1005' => { VR => 'IS', Name => 'ImagesInStudy' }, + '0020,1020' => { VR => 'CS', Name => 'Reference' }, + '0020,1040' => { VR => 'LO', Name => 'PositionReferenceIndicator' }, + '0020,1041' => { VR => 'DS', Name => 'SliceLocation' }, + '0020,1070' => { VR => 'IS', Name => 'OtherStudyNumbers' }, + '0020,1200' => { VR => 'IS', Name => 'NumberOfPatientRelatedStudies' }, + '0020,1202' => { VR => 'IS', Name => 'NumberOfPatientRelatedSeries' }, + '0020,1204' => { VR => 'IS', Name => 'NumberOfPatientRelatedInstances' }, + '0020,1206' => { VR => 'IS', Name => 'NumberOfStudyRelatedSeries' }, + '0020,1208' => { VR => 'IS', Name => 'NumberOfStudyRelatedInstances' }, + '0020,1209' => { VR => 'IS', Name => 'NumberOfSeriesRelatedInstances' }, + '0020,31xx' => { VR => 'CS', Name => 'SourceImageIDs' }, + '0020,3401' => { VR => 'CS', Name => 'ModifyingDeviceID' }, + '0020,3402' => { VR => 'CS', Name => 'ModifiedImageID' }, + '0020,3403' => { VR => 'DA', Name => 'ModifiedImageDate' }, + '0020,3404' => { VR => 'LO', Name => 'ModifyingDeviceManufacturer' }, + '0020,3405' => { VR => 'TM', Name => 'ModifiedImageTime' }, + '0020,3406' => { VR => 'LO', Name => 'ModifiedImageDescription' }, + '0020,4000' => { VR => 'LT', Name => 'ImageComments' }, + '0020,5000' => { VR => 'AT', Name => 'OriginalImageIdentification' }, + '0020,5002' => { VR => 'CS', Name => 'OriginalImageIdentNomenclature' }, + '0020,9056' => { VR => 'SH', Name => 'StackID' }, + '0020,9057' => { VR => 'UL', Name => 'InStackPositionNumber' }, + '0020,9071' => { VR => 'SQ', Name => 'FrameAnatomySequence' }, + '0020,9072' => { VR => 'CS', Name => 'FrameLaterality' }, + '0020,9111' => { VR => 'SQ', Name => 'FrameContentSequence' }, + '0020,9113' => { VR => 'SQ', Name => 'PlanePositionSequence' }, + '0020,9116' => { VR => 'SQ', Name => 'PlaneOrientationSequence' }, + '0020,9128' => { VR => 'UL', Name => 'TemporalPositionIndex' }, + '0020,9153' => { VR => 'FD', Name => 'TriggerDelayTime' }, + '0020,9156' => { VR => 'US', Name => 'FrameAcquisitionNumber' }, + '0020,9157' => { VR => 'UL', Name => 'DimensionIndexValues' }, + '0020,9158' => { VR => 'LT', Name => 'FrameComments' }, + '0020,9161' => { VR => 'UI', Name => 'ConcatenationUID' }, + '0020,9162' => { VR => 'US', Name => 'InConcatenationNumber' }, + '0020,9163' => { VR => 'US', Name => 'InConcatenationTotalNumber' }, + '0020,9164' => { VR => 'UI', Name => 'DimensionOrganizationUID' }, + '0020,9165' => { VR => 'AT', Name => 'DimensionIndexPointer' }, + '0020,9167' => { VR => 'AT', Name => 'FunctionalGroupPointer' }, + '0020,9213' => { VR => 'LO', Name => 'DimensionIndexPrivateCreator' }, + '0020,9221' => { VR => 'SQ', Name => 'DimensionOrganizationSequence' }, + '0020,9222' => { VR => 'SQ', Name => 'DimensionIndexSequence' }, + '0020,9228' => { VR => 'UL', Name => 'ConcatenationFrameOffsetNumber' }, + '0020,9238' => { VR => 'LO', Name => 'FunctionalGroupPrivateCreator' }, + '0020,9241' => { VR => 'FL', Name => 'NominalPercentageOfCardiacPhase' }, + '0020,9245' => { VR => 'FL', Name => 'NominalPercentOfRespiratoryPhase' }, + '0020,9246' => { VR => 'FL', Name => 'StartingRespiratoryAmplitude' }, + '0020,9247' => { VR => 'CS', Name => 'StartingRespiratoryPhase' }, + '0020,9248' => { VR => 'FL', Name => 'EndingRespiratoryAmplitude' }, + '0020,9249' => { VR => 'CS', Name => 'EndingRespiratoryPhase' }, + '0020,9250' => { VR => 'CS', Name => 'RespiratoryTriggerType' }, + '0020,9251' => { VR => 'FD', Name => 'RRIntervalTimeNominal' }, + '0020,9252' => { VR => 'FD', Name => 'ActualCardiacTriggerDelayTime' }, + '0020,9253' => { VR => 'SQ', Name => 'RespiratorySynchronizationSequence' }, + '0020,9254' => { VR => 'FD', Name => 'RespiratoryIntervalTime' }, + '0020,9255' => { VR => 'FD', Name => 'NominalRespiratoryTriggerDelayTime' }, + '0020,9256' => { VR => 'FD', Name => 'RespiratoryTriggerDelayThreshold' }, + '0020,9257' => { VR => 'FD', Name => 'ActualRespiratoryTriggerDelayTime' }, + '0020,9301' => { VR => 'FD', Name => 'ImagePositionVolume' }, + '0020,9302' => { VR => 'FD', Name => 'ImageOrientationVolume' }, + '0020,9308' => { VR => 'FD', Name => 'ApexPosition' }, + '0020,9421' => { VR => 'LO', Name => 'DimensionDescriptionLabel' }, + '0020,9450' => { VR => 'SQ', Name => 'PatientOrientationInFrameSequence' }, + '0020,9453' => { VR => 'LO', Name => 'FrameLabel' }, + '0020,9518' => { VR => 'US', Name => 'AcquisitionIndex' }, + '0020,9529' => { VR => 'SQ', Name => 'ContributingSOPInstancesRefSeq' }, + '0020,9536' => { VR => 'US', Name => 'ReconstructionIndex' }, + # GEMS_RELA_01 (ref 4) + '0021,1003' => { VR => 'SS', Name => 'SeriesFromWhichPrescribed' }, + '0021,1005' => { VR => 'SH', Name => 'GenesisVersionNow' }, + '0021,1005' => { VR => 'SH', Name => 'GenesisVersionNow' }, + '0021,1007' => { VR => 'UL', Name => 'SeriesRecordChecksum' }, + '0021,1018' => { VR => 'SH', Name => 'GenesisVersionNow' }, + '0021,1018' => { VR => 'SH', Name => 'GenesisVersionNow' }, + '0021,1019' => { VR => 'UL', Name => 'AcqReconRecordChecksum' }, + '0021,1019' => { VR => 'UL', Name => 'AcqreconRecordChecksum' }, + '0021,1020' => { VR => 'DS', Name => 'TableStartLocation' }, + '0021,1035' => { VR => 'SS', Name => 'SeriesFromWhichPrescribed' }, + '0021,1036' => { VR => 'SS', Name => 'ImageFromWhichPrescribed' }, + '0021,1037' => { VR => 'SS', Name => 'ScreenFormat' }, + '0021,104A' => { VR => 'LO', Name => 'AnatomicalReferenceForScout' }, + '0021,104F' => { VR => 'SS', Name => 'LocationsInAcquisition' }, + '0021,1050' => { VR => 'SS', Name => 'GraphicallyPrescribed' }, + '0021,1051' => { VR => 'DS', Name => 'RotationFromSourceXRot' }, + '0021,1052' => { VR => 'DS', Name => 'RotationFromSourceYRot' }, + '0021,1053' => { VR => 'DS', Name => 'RotationFromSourceZRot' }, + '0021,1054' => { VR => 'SH', Name => 'ImagePosition' }, + '0021,1055' => { VR => 'SH', Name => 'ImageOrientation' }, + '0021,1056' => { VR => 'SL', Name => 'IntegerSlop' }, + '0021,1057' => { VR => 'SL', Name => 'IntegerSlop' }, + '0021,1058' => { VR => 'SL', Name => 'IntegerSlop' }, + '0021,1059' => { VR => 'SL', Name => 'IntegerSlop' }, + '0021,105A' => { VR => 'SL', Name => 'IntegerSlop' }, + '0021,105B' => { VR => 'DS', Name => 'FloatSlop' }, + '0021,105C' => { VR => 'DS', Name => 'FloatSlop' }, + '0021,105D' => { VR => 'DS', Name => 'FloatSlop' }, + '0021,105E' => { VR => 'DS', Name => 'FloatSlop' }, + '0021,105F' => { VR => 'DS', Name => 'FloatSlop' }, + '0021,1081' => { VR => 'DS', Name => 'AutoWindowLevelAlpha' }, + '0021,1082' => { VR => 'DS', Name => 'AutoWindowLevelBeta' }, + '0021,1083' => { VR => 'DS', Name => 'AutoWindowLevelWindow' }, + '0021,1084' => { VR => 'DS', Name => 'ToWindowLevelLevel' }, + '0021,1090' => { VR => 'SS', Name => 'TubeFocalSpotPosition' }, + '0021,1091' => { VR => 'SS', Name => 'BiopsyPosition' }, + '0021,1092' => { VR => 'FL', Name => 'BiopsyTLocation' }, + '0021,1093' => { VR => 'FL', Name => 'BiopsyRefLocation' }, + # ? + '0022,0001' => { VR => 'US', Name => 'LightPathFilterPassThroughWavelen' }, + '0022,0002' => { VR => 'US', Name => 'LightPathFilterPassBand' }, + '0022,0003' => { VR => 'US', Name => 'ImagePathFilterPassThroughWavelen' }, + '0022,0004' => { VR => 'US', Name => 'ImagePathFilterPassBand' }, + '0022,0005' => { VR => 'CS', Name => 'PatientEyeMovementCommanded' }, + '0022,0006' => { VR => 'SQ', Name => 'PatientEyeMovementCommandCodeSeq' }, + '0022,0007' => { VR => 'FL', Name => 'SphericalLensPower' }, + '0022,0008' => { VR => 'FL', Name => 'CylinderLensPower' }, + '0022,0009' => { VR => 'FL', Name => 'CylinderAxis' }, + '0022,000A' => { VR => 'FL', Name => 'EmmetropicMagnification' }, + '0022,000B' => { VR => 'FL', Name => 'IntraOcularPressure' }, + '0022,000C' => { VR => 'FL', Name => 'HorizontalFieldOfView' }, + '0022,000D' => { VR => 'CS', Name => 'PupilDilated' }, + '0022,000E' => { VR => 'FL', Name => 'DegreeOfDilation' }, + '0022,0010' => { VR => 'FL', Name => 'StereoBaselineAngle' }, + '0022,0011' => { VR => 'FL', Name => 'StereoBaselineDisplacement' }, + '0022,0012' => { VR => 'FL', Name => 'StereoHorizontalPixelOffset' }, + '0022,0013' => { VR => 'FL', Name => 'StereoVerticalPixelOffset' }, + '0022,0014' => { VR => 'FL', Name => 'StereoRotation' }, + '0022,0015' => { VR => 'SQ', Name => 'AcquisitionDeviceTypeCodeSequence' }, + '0022,0016' => { VR => 'SQ', Name => 'IlluminationTypeCodeSequence' }, + '0022,0017' => { VR => 'SQ', Name => 'LightPathFilterTypeStackCodeSeq' }, + '0022,0018' => { VR => 'SQ', Name => 'ImagePathFilterTypeStackCodeSeq' }, + '0022,0019' => { VR => 'SQ', Name => 'LensesCodeSequence' }, + '0022,001A' => { VR => 'SQ', Name => 'ChannelDescriptionCodeSequence' }, + '0022,001B' => { VR => 'SQ', Name => 'RefractiveStateSequence' }, + '0022,001C' => { VR => 'SQ', Name => 'MydriaticAgentCodeSequence' }, + '0022,001D' => { VR => 'SQ', Name => 'RelativeImagePositionCodeSequence' }, + '0022,0020' => { VR => 'SQ', Name => 'StereoPairsSequence' }, + '0022,0021' => { VR => 'SQ', Name => 'LeftImageSequence' }, + '0022,0022' => { VR => 'SQ', Name => 'RightImageSequence' }, + '0022,0030' => { VR => 'FL', Name => 'AxialLengthOfTheEye' }, + '0022,0031' => { VR => 'SQ', Name => 'OphthalmicFrameLocationSequence' }, + '0022,0032' => { VR => 'FL', Name => 'ReferenceCoordinates' }, + '0022,0035' => { VR => 'FL', Name => 'DepthSpatialResolution' }, + '0022,0036' => { VR => 'FL', Name => 'MaximumDepthDistortion' }, + '0022,0037' => { VR => 'FL', Name => 'AlongScanSpatialResolution' }, + '0022,0038' => { VR => 'FL', Name => 'MaximumAlongScanDistortion' }, + '0022,0039' => { VR => 'CS', Name => 'OphthalmicImageOrientation' }, + '0022,0041' => { VR => 'FL', Name => 'DepthOfTransverseImage' }, + '0022,0042' => { VR => 'SQ', Name => 'MydriaticAgentConcUnitsSeq' }, + '0022,0048' => { VR => 'FL', Name => 'AcrossScanSpatialResolution' }, + '0022,0049' => { VR => 'FL', Name => 'MaximumAcrossScanDistortion' }, + '0022,004E' => { VR => 'DS', Name => 'MydriaticAgentConcentration' }, + '0022,0055' => { VR => 'FL', Name => 'IlluminationWaveLength' }, + '0022,0056' => { VR => 'FL', Name => 'IlluminationPower' }, + '0022,0057' => { VR => 'FL', Name => 'IlluminationBandwidth' }, + '0022,0058' => { VR => 'SQ', Name => 'MydriaticAgentSequence' }, + # GEMS_STDY_01 (ref 4) + '0023,1001' => { VR => 'SL', Name => 'NumberOfSeriesInStudy' }, + '0023,1002' => { VR => 'SL', Name => 'NumberOfUnarchivedSeries' }, + '0023,1010' => { VR => 'SS', Name => 'ReferenceImageField' }, + '0023,1050' => { VR => 'SS', Name => 'SummaryImage' }, + '0023,1070' => { VR => 'FD', Name => 'StartTimeSecsInFirstAxial' }, + '0023,1074' => { VR => 'SL', Name => 'NoofUpdatesToHeader' }, + '0023,107D' => { VR => 'SS', Name => 'IndicatesIfStudyHasCompleteInfo' }, + '0023,107D' => { VR => 'SS', Name => 'IndicatesIfTheStudyHasCompleteInfo' }, + # GEMS_SERS_01 (ref 4) + '0025,1006' => { VR => 'SS', Name => 'LastPulseSequenceUsed' }, + '0025,1007' => { VR => 'SL', Name => 'ImagesInSeries' }, + '0025,1010' => { VR => 'SL', Name => 'LandmarkCounter' }, + '0025,1011' => { VR => 'SS', Name => 'NumberOfAcquisitions' }, + '0025,1014' => { VR => 'SL', Name => 'IndicatesNoofUpdatesToHeader' }, + '0025,1017' => { VR => 'SL', Name => 'SeriesCompleteFlag' }, + '0025,1018' => { VR => 'SL', Name => 'NumberOfImagesArchived' }, + '0025,1019' => { VR => 'SL', Name => 'LastImageNumberUsed' }, + '0025,101A' => { VR => 'SH', Name => 'PrimaryReceiverSuiteAndHost' }, + # GEMS_IMAG_01 (ref 4) + '0027,1006' => { VR => 'SL', Name => 'ImageArchiveFlag' }, + '0027,1010' => { VR => 'SS', Name => 'ScoutType' }, + '0027,101C' => { VR => 'SL', Name => 'VmaMamp' }, + '0027,101D' => { VR => 'SS', Name => 'VmaPhase' }, + '0027,101E' => { VR => 'SL', Name => 'VmaMod' }, + '0027,101F' => { VR => 'SL', Name => 'VmaClip' }, + '0027,1020' => { VR => 'SS', Name => 'SmartScanOnOffFlag' }, + '0027,1030' => { VR => 'SH', Name => 'ForeignImageRevision' }, + '0027,1031' => { VR => 'SS', Name => 'ImagingMode' }, + '0027,1032' => { VR => 'SS', Name => 'PulseSequence' }, + '0027,1033' => { VR => 'SL', Name => 'ImagingOptions' }, + '0027,1035' => { VR => 'SS', Name => 'PlaneType' }, + '0027,1036' => { VR => 'SL', Name => 'ObliquePlane' }, + '0027,1040' => { VR => 'SH', Name => 'RASLetterOfImageLocation' }, + '0027,1041' => { VR => 'FL', Name => 'ImageLocation' }, + '0027,1042' => { VR => 'FL', Name => 'CenterRCoordOfPlaneImage' }, + '0027,1043' => { VR => 'FL', Name => 'CenterACoordOfPlaneImage' }, + '0027,1044' => { VR => 'FL', Name => 'CenterSCoordOfPlaneImage' }, + '0027,1045' => { VR => 'FL', Name => 'NormalRCoord' }, + '0027,1046' => { VR => 'FL', Name => 'NormalACoord' }, + '0027,1047' => { VR => 'FL', Name => 'NormalSCoord' }, + '0027,1048' => { VR => 'FL', Name => 'RCoordOfTopRightCorner' }, + '0027,1049' => { VR => 'FL', Name => 'ACoordOfTopRightCorner' }, + '0027,104A' => { VR => 'FL', Name => 'SCoordOfTopRightCorner' }, + '0027,104B' => { VR => 'FL', Name => 'RCoordOfBottomRightCorner' }, + '0027,104C' => { VR => 'FL', Name => 'ACoordOfBottomRightCorner' }, + '0027,104D' => { VR => 'FL', Name => 'SCoordOfBottomRightCorner' }, + '0027,1050' => { VR => 'FL', Name => 'TableStartLocation' }, + '0027,1051' => { VR => 'FL', Name => 'TableEndLocation' }, + '0027,1052' => { VR => 'SH', Name => 'RASLetterForSideOfImage' }, + '0027,1053' => { VR => 'SH', Name => 'RASLetterForAnteriorPosterior' }, + '0027,1054' => { VR => 'SH', Name => 'RASLetterForScoutStartLoc' }, + '0027,1055' => { VR => 'SH', Name => 'RASLetterForScoutEndLoc' }, + '0027,1060' => { VR => 'FL', Name => 'ImageDimensionX' }, + '0027,1061' => { VR => 'FL', Name => 'ImageDimensionY' }, + '0027,1062' => { VR => 'FL', Name => 'NumberOfExcitations' }, + # image presentation group + '0028,0000' => { VR => 'UL', Name => 'ImagePresentationGroupLength' }, + '0028,0002' => { VR => 'US', Name => 'SamplesPerPixel' }, + '0028,0003' => { VR => 'US', Name => 'SamplesPerPixelUsed' }, + '0028,0004' => { VR => 'CS', Name => 'PhotometricInterpretation' }, + '0028,0005' => { VR => 'US', Name => 'ImageDimensions' }, + '0028,0006' => { VR => 'US', Name => 'PlanarConfiguration' }, + '0028,0008' => { VR => 'IS', Name => 'NumberOfFrames' }, + '0028,0009' => { VR => 'AT', Name => 'FrameIncrementPointer' }, + '0028,000A' => { VR => 'AT', Name => 'FrameDimensionPointer' }, + '0028,0010' => { VR => 'US', Name => 'Rows' }, + '0028,0011' => { VR => 'US', Name => 'Columns' }, + '0028,0012' => { VR => 'US', Name => 'Planes' }, + '0028,0014' => { VR => 'US', Name => 'UltrasoundColorDataPresent' }, + '0028,0030' => { VR => 'DS', Name => 'PixelSpacing' }, + '0028,0031' => { VR => 'DS', Name => 'ZoomFactor' }, + '0028,0032' => { VR => 'DS', Name => 'ZoomCenter' }, + '0028,0034' => { VR => 'IS', Name => 'PixelAspectRatio' }, + '0028,0040' => { VR => 'CS', Name => 'ImageFormat' }, + '0028,0050' => { VR => 'LO', Name => 'ManipulatedImage' }, + '0028,0051' => { VR => 'CS', Name => 'CorrectedImage' }, + '0028,005F' => { VR => 'LO', Name => 'CompressionRecognitionCode' }, + '0028,0060' => { VR => 'CS', Name => 'CompressionCode' }, + '0028,0061' => { VR => 'SH', Name => 'CompressionOriginator' }, + '0028,0062' => { VR => 'LO', Name => 'CompressionLabel' }, + '0028,0063' => { VR => 'SH', Name => 'CompressionDescription' }, + '0028,0065' => { VR => 'CS', Name => 'CompressionSequence' }, + '0028,0066' => { VR => 'AT', Name => 'CompressionStepPointers' }, + '0028,0068' => { VR => 'US', Name => 'RepeatInterval' }, + '0028,0069' => { VR => 'US', Name => 'BitsGrouped' }, + '0028,0070' => { VR => 'US', Name => 'PerimeterTable' }, + '0028,0071' => { VR => 'US', Name => 'PerimeterValue' }, + '0028,0080' => { VR => 'US', Name => 'PredictorRows' }, + '0028,0081' => { VR => 'US', Name => 'PredictorColumns' }, + '0028,0082' => { VR => 'US', Name => 'PredictorConstants' }, + '0028,0090' => { VR => 'CS', Name => 'BlockedPixels' }, + '0028,0091' => { VR => 'US', Name => 'BlockRows' }, + '0028,0092' => { VR => 'US', Name => 'BlockColumns' }, + '0028,0093' => { VR => 'US', Name => 'RowOverlap' }, + '0028,0094' => { VR => 'US', Name => 'ColumnOverlap' }, + '0028,0100' => { VR => 'US', Name => 'BitsAllocated' }, + '0028,0101' => { VR => 'US', Name => 'BitsStored' }, + '0028,0102' => { VR => 'US', Name => 'HighBit' }, + '0028,0103' => { VR => 'US', Name => 'PixelRepresentation', PrintConv => { 0 => 'Unsigned', 1 => 'Signed' } }, + '0028,0104' => { VR => 'US', Name => 'SmallestValidPixelValue' }, + '0028,0105' => { VR => 'US', Name => 'LargestValidPixelValue' }, + '0028,0106' => { VR => 'US', Name => 'SmallestImagePixelValue' }, + '0028,0107' => { VR => 'US', Name => 'LargestImagePixelValue' }, + '0028,0108' => { VR => 'US', Name => 'SmallestPixelValueInSeries' }, + '0028,0109' => { VR => 'US', Name => 'LargestPixelValueInSeries' }, + '0028,0110' => { VR => 'US', Name => 'SmallestImagePixelValueInPlane' }, + '0028,0111' => { VR => 'US', Name => 'LargestImagePixelValueInPlane' }, + '0028,0120' => { VR => 'US', Name => 'PixelPaddingValue' }, + '0028,0121' => { VR => 'US', Name => 'PixelPaddingRangeLimit' }, + '0028,0200' => { VR => 'US', Name => 'ImageLocation' }, + '0028,0300' => { VR => 'CS', Name => 'QualityControlImage' }, + '0028,0301' => { VR => 'CS', Name => 'BurnedInAnnotation' }, + '0028,0400' => { VR => 'LO', Name => 'TransformLabel' }, + '0028,0401' => { VR => 'LO', Name => 'TransformVersionNumber' }, + '0028,0402' => { VR => 'US', Name => 'NumberOfTransformSteps' }, + '0028,0403' => { VR => 'LO', Name => 'SequenceOfCompressedData' }, + '0028,0404' => { VR => 'AT', Name => 'DetailsOfCoefficients' }, + '0028,04x2' => { VR => 'LO', Name => 'CoefficientCoding' }, + '0028,04x3' => { VR => 'AT', Name => 'CoefficientCodingPointers' }, + '0028,0700' => { VR => 'LO', Name => 'DCTLabel' }, + '0028,0701' => { VR => 'CS', Name => 'DataBlockDescription' }, + '0028,0702' => { VR => 'AT', Name => 'DataBlock' }, + '0028,0710' => { VR => 'US', Name => 'NormalizationFactorFormat' }, + '0028,0720' => { VR => 'US', Name => 'ZonalMapNumberFormat' }, + '0028,0721' => { VR => 'AT', Name => 'ZonalMapLocation' }, + '0028,0722' => { VR => 'US', Name => 'ZonalMapFormat' }, + '0028,0730' => { VR => 'US', Name => 'AdaptiveMapFormat' }, + '0028,0740' => { VR => 'US', Name => 'CodeNumberFormat' }, + '0028,08x0' => { VR => 'CS', Name => 'CodeLabel' }, + '0028,08x2' => { VR => 'US', Name => 'NumberOfTables' }, + '0028,08x3' => { VR => 'AT', Name => 'CodeTableLocation' }, + '0028,08x4' => { VR => 'US', Name => 'BitsForCodeWord' }, + '0028,08x8' => { VR => 'AT', Name => 'ImageDataLocation' }, + '0028,1040' => { VR => 'CS', Name => 'PixelIntensityRelationship' }, + '0028,0A02' => { VR => 'CS', Name => 'PixelSpacingCalibrationType' }, + '0028,0A04' => { VR => 'LO', Name => 'PixelSpacingCalibrationDescription' }, + '0028,1040' => { VR => 'CS', Name => 'PixelIntensityRelationship' }, + '0028,1041' => { VR => 'SS', Name => 'PixelIntensityRelationshipSign' }, + '0028,1050' => { VR => 'DS', Name => 'WindowCenter' }, + '0028,1051' => { VR => 'DS', Name => 'WindowWidth' }, + '0028,1052' => { VR => 'DS', Name => 'RescaleIntercept' }, + '0028,1053' => { VR => 'DS', Name => 'RescaleSlope' }, + '0028,1054' => { VR => 'LO', Name => 'RescaleType' }, + '0028,1055' => { VR => 'LO', Name => 'WindowCenterAndWidthExplanation' }, + '0028,1056' => { VR => 'CS', Name => 'VOI_LUTFunction' }, + '0028,1080' => { VR => 'CS', Name => 'GrayScale' }, + '0028,1090' => { VR => 'CS', Name => 'RecommendedViewingMode' }, + '0028,1100' => { VR => 'SS', Name => 'GrayLookupTableDescriptor' }, + '0028,1101' => { VR => 'SS', Name => 'RedPaletteColorTableDescriptor' }, + '0028,1102' => { VR => 'SS', Name => 'GreenPaletteColorTableDescriptor' }, + '0028,1103' => { VR => 'SS', Name => 'BluePaletteColorTableDescriptor' }, + '0028,1111' => { VR => 'SS', Name => 'LargeRedPaletteColorTableDescr' }, + '0028,1112' => { VR => 'SS', Name => 'LargeGreenPaletteColorTableDescr' }, + '0028,1113' => { VR => 'SS', Name => 'LargeBluePaletteColorTableDescr' }, + '0028,1199' => { VR => 'UI', Name => 'PaletteColorTableUID' }, + '0028,1200' => { VR => 'US', Name => 'GrayLookupTableData' }, + '0028,1201' => { VR => 'OW', Name => 'RedPaletteColorTableData' }, + '0028,1202' => { VR => 'OW', Name => 'GreenPaletteColorTableData' }, + '0028,1203' => { VR => 'OW', Name => 'BluePaletteColorTableData' }, + '0028,1211' => { VR => 'OW', Name => 'LargeRedPaletteColorTableData', Binary => 1 }, + '0028,1212' => { VR => 'OW', Name => 'LargeGreenPaletteColorTableData', Binary => 1 }, + '0028,1213' => { VR => 'OW', Name => 'LargeBluePaletteColorTableData', Binary => 1 }, + '0028,1214' => { VR => 'UI', Name => 'LargePaletteColorLookupTableUID' }, + '0028,1221' => { VR => 'OW', Name => 'SegmentedRedColorTableData' }, + '0028,1222' => { VR => 'OW', Name => 'SegmentedGreenColorTableData' }, + '0028,1223' => { VR => 'OW', Name => 'SegmentedBlueColorTableData' }, + '0028,1300' => { VR => 'CS', Name => 'BreastImplantPresent' }, + '0028,1350' => { VR => 'CS', Name => 'PartialView' }, + '0028,1351' => { VR => 'ST', Name => 'PartialViewDescription' }, + '0028,1352' => { VR => 'SQ', Name => 'PartialViewCodeSequence' }, + '0028,135A' => { VR => 'CS', Name => 'SpatialLocationsPreserved' }, + '0028,1402' => { VR => 'CS', Name => 'DataPathAssignment' }, + '0028,1404' => { VR => 'SQ', Name => 'BlendingLUT1Sequence' }, + '0028,1406' => { VR => 'FD', Name => 'BlendingWeightConstant' }, + '0028,1408' => { VR => 'OW', Name => 'BlendingLookupTableData' }, + '0028,140C' => { VR => 'SQ', Name => 'BlendingLUT2Sequence' }, + '0028,140E' => { VR => 'CS', Name => 'DataPathID' }, + '0028,140F' => { VR => 'CS', Name => 'RGBLUTTransferFunction' }, + '0028,1410' => { VR => 'CS', Name => 'AlphaLUTTransferFunction' }, + '0028,2000' => { VR => 'OB', Name => 'ICCProfile' }, + '0028,2110' => { VR => 'CS', Name => 'LossyImageCompression' }, + '0028,2112' => { VR => 'DS', Name => 'LossyImageCompressionRatio' }, + '0028,2114' => { VR => 'CS', Name => 'LossyImageCompressionMethod' }, + '0028,3000' => { VR => 'SQ', Name => 'ModalityLUTSequence' }, + '0028,3002' => { VR => 'US', Name => 'LUTDescriptor' }, + '0028,3003' => { VR => 'LO', Name => 'LUTExplanation' }, + '0028,3004' => { VR => 'LO', Name => 'ModalityLUTType' }, + '0028,3006' => { VR => 'SS', Name => 'LUTData' }, + '0028,3010' => { VR => 'SQ', Name => 'VOILUTSequence' }, + '0028,3110' => { VR => 'SQ', Name => 'SoftcopyVOILUTSequence' }, + '0028,4000' => { VR => 'LT', Name => 'ImagePresentationComments' }, + '0028,5000' => { VR => 'SQ', Name => 'BiPlaneAcquisitionSequence' }, + '0028,6010' => { VR => 'US', Name => 'RepresentativeFrameNumber' }, + '0028,6020' => { VR => 'US', Name => 'FrameNumbersOfInterest' }, + '0028,6022' => { VR => 'LO', Name => 'FrameOfInterestDescription' }, + '0028,6023' => { VR => 'CS', Name => 'FrameOfInterestType' }, + '0028,6030' => { VR => 'US', Name => 'MaskPointers' }, + '0028,6040' => { VR => 'US', Name => 'RWavePointer' }, + '0028,6100' => { VR => 'SQ', Name => 'MaskSubtractionSequence' }, + '0028,6101' => { VR => 'CS', Name => 'MaskOperation' }, + '0028,6102' => { VR => 'US', Name => 'ApplicableFrameRange' }, + '0028,6110' => { VR => 'US', Name => 'MaskFrameNumbers' }, + '0028,6112' => { VR => 'US', Name => 'ContrastFrameAveraging' }, + '0028,6114' => { VR => 'FL', Name => 'MaskSubPixelShift' }, + '0028,6120' => { VR => 'SS', Name => 'TIDOffset' }, + '0028,6190' => { VR => 'ST', Name => 'MaskOperationExplanation' }, + '0028,7FE0' => { VR => 'UT', Name => 'PixelDataProviderURL' }, + '0028,9001' => { VR => 'UL', Name => 'DataPointRows' }, + '0028,9002' => { VR => 'UL', Name => 'DataPointColumns' }, + '0028,9003' => { VR => 'CS', Name => 'SignalDomainColumns' }, + '0028,9099' => { VR => 'US', Name => 'LargestMonochromePixelValue' }, + '0028,9108' => { VR => 'CS', Name => 'DataRepresentation' }, + '0028,9110' => { VR => 'SQ', Name => 'PixelMeasuresSequence' }, + '0028,9132' => { VR => 'SQ', Name => 'FrameVOILUTSequence' }, + '0028,9145' => { VR => 'SQ', Name => 'PixelValueTransformationSequence' }, + '0028,9235' => { VR => 'CS', Name => 'SignalDomainRows' }, + '0028,9411' => { VR => 'FL', Name => 'DisplayFilterPercentage' }, + '0028,9415' => { VR => 'SQ', Name => 'FramePixelShiftSequence' }, + '0028,9416' => { VR => 'US', Name => 'SubtractionItemID' }, + '0028,9422' => { VR => 'SQ', Name => 'PixelIntensityRelationshipLUTSeq' }, + '0028,9443' => { VR => 'SQ', Name => 'FramePixelDataPropertiesSequence' }, + '0028,9444' => { VR => 'CS', Name => 'GeometricalProperties' }, + '0028,9445' => { VR => 'FL', Name => 'GeometricMaximumDistortion' }, + '0028,9446' => { VR => 'CS', Name => 'ImageProcessingApplied' }, + '0028,9454' => { VR => 'CS', Name => 'MaskSelectionMode' }, + '0028,9474' => { VR => 'CS', Name => 'LUTFunction' }, + '0028,9478' => { VR => 'FL', Name => 'MaskVisibilityPercentage' }, + '0028,9501' => { VR => 'SQ', Name => 'PixelShiftSequence' }, + '0028,9502' => { VR => 'SQ', Name => 'RegionPixelShiftSequence' }, + '0028,9503' => { VR => 'SS', Name => 'VerticesOfTheRegion' }, + '0028,9506' => { VR => 'US', Name => 'PixelShiftFrameRange' }, + '0028,9507' => { VR => 'US', Name => 'LUTFrameRange' }, + '0028,9520' => { VR => 'DS', Name => 'ImageToEquipmentMappingMatrix' }, + '0028,9537' => { VR => 'CS', Name => 'EquipmentCoordinateSystemID' }, + # GEMS_IMPS_01 (ref 4) + '0029,1004' => { VR => 'SL', Name => 'LowerRangeOfPixels1a' }, + '0029,1005' => { VR => 'DS', Name => 'LowerRangeOfPixels1b' }, + '0029,1006' => { VR => 'DS', Name => 'LowerRangeOfPixels1c' }, + '0029,1007' => { VR => 'SL', Name => 'LowerRangeOfPixels1d' }, + '0029,1008' => { VR => 'SH', Name => 'LowerRangeOfPixels1e' }, + '0029,1009' => { VR => 'SH', Name => 'LowerRangeOfPixels1f' }, + '0029,100A' => { VR => 'SS', Name => 'LowerRangeOfPixels1g' }, + '0029,1015' => { VR => 'SL', Name => 'LowerRangeOfPixels1h' }, + '0029,1016' => { VR => 'SL', Name => 'LowerRangeOfPixels1i' }, + '0029,1017' => { VR => 'SL', Name => 'LowerRangeOfPixels2' }, + '0029,1018' => { VR => 'SL', Name => 'UpperRangeOfPixels2' }, + '0029,101A' => { VR => 'SL', Name => 'LenOfTotHdrInBytes' }, + '0029,1026' => { VR => 'SS', Name => 'VersionOfTheHdrStruct' }, + '0029,1034' => { VR => 'SL', Name => 'AdvantageCompOverflow' }, + '0029,1035' => { VR => 'SL', Name => 'AdvantageCompUnderflow' }, + # study group + '0032,0000' => { VR => 'UL', Name => 'StudyGroupLength' }, + '0032,000A' => { VR => 'CS', Name => 'StudyStatusID' }, + '0032,000C' => { VR => 'CS', Name => 'StudyPriorityID' }, + '0032,0012' => { VR => 'LO', Name => 'StudyIDIssuer' }, + '0032,0032' => { VR => 'DA', Name => 'StudyVerifiedDate' }, + '0032,0033' => { VR => 'TM', Name => 'StudyVerifiedTime' }, + '0032,0034' => { VR => 'DA', Name => 'StudyReadDate' }, + '0032,0035' => { VR => 'TM', Name => 'StudyReadTime' }, + '0032,1000' => { VR => 'DA', Name => 'ScheduledStudyStartDate' }, + '0032,1001' => { VR => 'TM', Name => 'ScheduledStudyStartTime' }, + '0032,1010' => { VR => 'DA', Name => 'ScheduledStudyStopDate' }, + '0032,1011' => { VR => 'TM', Name => 'ScheduledStudyStopTime' }, + '0032,1020' => { VR => 'LO', Name => 'ScheduledStudyLocation' }, + '0032,1021' => { VR => 'AE', Name => 'ScheduledStudyLocationAETitle' }, + '0032,1030' => { VR => 'LO', Name => 'ReasonForStudy' }, + '0032,1031' => { VR => 'SQ', Name => 'RequestingPhysicianIDSequence' }, + '0032,1032' => { VR => 'PN', Name => 'RequestingPhysician' }, + '0032,1033' => { VR => 'LO', Name => 'RequestingService' }, + '0032,1040' => { VR => 'DA', Name => 'StudyArrivalDate' }, + '0032,1041' => { VR => 'TM', Name => 'StudyArrivalTime' }, + '0032,1050' => { VR => 'DA', Name => 'StudyCompletionDate' }, + '0032,1051' => { VR => 'TM', Name => 'StudyCompletionTime' }, + '0032,1055' => { VR => 'CS', Name => 'StudyComponentStatusID' }, + '0032,1060' => { VR => 'LO', Name => 'RequestedProcedureDescription' }, + '0032,1064' => { VR => 'SQ', Name => 'RequestedProcedureCodeSequence' }, + '0032,1070' => { VR => 'LO', Name => 'RequestedContrastAgent' }, + '0032,4000' => { VR => 'LT', Name => 'StudyComments' }, + # visit group + '0038,0004' => { VR => 'SQ', Name => 'ReferencedPatientAliasSequence' }, + '0038,0008' => { VR => 'CS', Name => 'VisitStatusID' }, + '0038,0010' => { VR => 'LO', Name => 'AdmissionID' }, + '0038,0011' => { VR => 'LO', Name => 'IssuerOfAdmissionID' }, + '0038,0016' => { VR => 'LO', Name => 'RouteOfAdmissions' }, + '0038,001A' => { VR => 'DA', Name => 'ScheduledAdmissionDate' }, + '0038,001B' => { VR => 'TM', Name => 'ScheduledAdmissionTime' }, + '0038,001C' => { VR => 'DA', Name => 'ScheduledDischargeDate' }, + '0038,001D' => { VR => 'TM', Name => 'ScheduledDischargeTime' }, + '0038,001E' => { VR => 'LO', Name => 'ScheduledPatientInstitResidence' }, + '0038,0020' => { VR => 'DA', Name => 'AdmittingDate' }, + '0038,0021' => { VR => 'TM', Name => 'AdmittingTime' }, + '0038,0030' => { VR => 'DA', Name => 'DischargeDate' }, + '0038,0032' => { VR => 'TM', Name => 'DischargeTime' }, + '0038,0040' => { VR => 'LO', Name => 'DischargeDiagnosisDescription' }, + '0038,0044' => { VR => 'SQ', Name => 'DischargeDiagnosisCodeSequence' }, + '0038,0050' => { VR => 'LO', Name => 'SpecialNeeds' }, + '0038,0060' => { VR => 'LO', Name => 'ServiceEpisodeID' }, + '0038,0061' => { VR => 'LO', Name => 'IssuerOfServiceEpisodeID' }, + '0038,0062' => { VR => 'LO', Name => 'ServiceEpisodeDescription' }, + '0038,0100' => { VR => 'SQ', Name => 'PertinentDocumentsSequence' }, + '0038,0300' => { VR => 'LO', Name => 'CurrentPatientLocation' }, + '0038,0400' => { VR => 'LO', Name => 'PatientInstitutionResidence' }, + '0038,0500' => { VR => 'LO', Name => 'PatientState' }, + '0038,0502' => { VR => 'SQ', Name => 'PatientClinicalTrialParticipSeq' }, + '0038,4000' => { VR => 'LT', Name => 'VisitComments' }, + '003A,0004' => { VR => 'CS', Name => 'WaveformOriginality' }, + '003A,0005' => { VR => 'US', Name => 'NumberOfWaveformChannels' }, + '003A,0010' => { VR => 'UL', Name => 'NumberOfWaveformSamples' }, + '003A,001A' => { VR => 'DS', Name => 'SamplingFrequency' }, + '003A,0020' => { VR => 'SH', Name => 'MultiplexGroupLabel' }, + '003A,0200' => { VR => 'SQ', Name => 'ChannelDefinitionSequence' }, + '003A,0202' => { VR => 'IS', Name => 'WaveformChannelNumber' }, + '003A,0203' => { VR => 'SH', Name => 'ChannelLabel' }, + '003A,0205' => { VR => 'CS', Name => 'ChannelStatus' }, + '003A,0208' => { VR => 'SQ', Name => 'ChannelSourceSequence' }, + '003A,0209' => { VR => 'SQ', Name => 'ChannelSourceModifiersSequence' }, + '003A,020A' => { VR => 'SQ', Name => 'SourceWaveformSequence' }, + '003A,020C' => { VR => 'LO', Name => 'ChannelDerivationDescription' }, + '003A,0210' => { VR => 'DS', Name => 'ChannelSensitivity' }, + '003A,0211' => { VR => 'SQ', Name => 'ChannelSensitivityUnitsSequence' }, + '003A,0212' => { VR => 'DS', Name => 'ChannelSensitivityCorrectionFactor' }, + '003A,0213' => { VR => 'DS', Name => 'ChannelBaseline' }, + '003A,0214' => { VR => 'DS', Name => 'ChannelTimeSkew' }, + '003A,0215' => { VR => 'DS', Name => 'ChannelSampleSkew' }, + '003A,0218' => { VR => 'DS', Name => 'ChannelOffset' }, + '003A,021A' => { VR => 'US', Name => 'WaveformBitsStored' }, + '003A,0220' => { VR => 'DS', Name => 'FilterLowFrequency' }, + '003A,0221' => { VR => 'DS', Name => 'FilterHighFrequency' }, + '003A,0222' => { VR => 'DS', Name => 'NotchFilterFrequency' }, + '003A,0223' => { VR => 'DS', Name => 'NotchFilterBandwidth' }, + '003A,0230' => { VR => 'FL', Name => 'WaveformDataDisplayScale' }, + '003A,0231' => { VR => 'US', Name => 'WaveformDisplayBkgCIELabValue' }, + '003A,0240' => { VR => 'SQ', Name => 'WaveformPresentationGroupSequence' }, + '003A,0241' => { VR => 'US', Name => 'PresentationGroupNumber' }, + '003A,0242' => { VR => 'SQ', Name => 'ChannelDisplaySequence' }, + '003A,0244' => { VR => 'US', Name => 'ChannelRecommendDisplayCIELabValue' }, + '003A,0245' => { VR => 'FL', Name => 'ChannelPosition' }, + '003A,0246' => { VR => 'CS', Name => 'DisplayShadingFlag' }, + '003A,0247' => { VR => 'FL', Name => 'FractionalChannelDisplayScale' }, + '003A,0248' => { VR => 'FL', Name => 'AbsoluteChannelDisplayScale' }, + '003A,0300' => { VR => 'SQ', Name => 'MultiplexAudioChannelsDescrCodeSeq' }, + '003A,0301' => { VR => 'IS', Name => 'ChannelIdentificationCode' }, + '003A,0302' => { VR => 'CS', Name => 'ChannelMode' }, + '0040,0001' => { VR => 'AE', Name => 'ScheduledStationAETitle' }, + '0040,0002' => { VR => 'DA', Name => 'ScheduledProcedureStepStartDate' }, + '0040,0003' => { VR => 'TM', Name => 'ScheduledProcedureStepStartTime' }, + '0040,0004' => { VR => 'DA', Name => 'ScheduledProcedureStepEndDate' }, + '0040,0005' => { VR => 'TM', Name => 'ScheduledProcedureStepEndTime' }, + '0040,0006' => { VR => 'PN', Name => 'ScheduledPerformingPhysiciansName' }, + '0040,0007' => { VR => 'LO', Name => 'ScheduledProcedureStepDescription' }, + '0040,0008' => { VR => 'SQ', Name => 'ScheduledProtocolCodeSequence' }, + '0040,0009' => { VR => 'SH', Name => 'ScheduledProcedureStepID' }, + '0040,000A' => { VR => 'SQ', Name => 'StageCodeSequence' }, + '0040,000B' => { VR => 'SQ', Name => 'ScheduledPerformingPhysicianIDSeq' }, + '0040,0010' => { VR => 'SH', Name => 'ScheduledStationName' }, + '0040,0011' => { VR => 'SH', Name => 'ScheduledProcedureStepLocation' }, + '0040,0012' => { VR => 'LO', Name => 'PreMedication' }, + '0040,0020' => { VR => 'CS', Name => 'ScheduledProcedureStepStatus' }, + '0040,0031' => { VR => 'UT', Name => 'LocalNamespaceEntityID' }, + '0040,0032' => { VR => 'UT', Name => 'UniversalEntityID' }, + '0040,0033' => { VR => 'CS', Name => 'UniversalEntityIDType' }, + '0040,0035' => { VR => 'CS', Name => 'IdentifierTypeCode' }, + '0040,0036' => { VR => 'SQ', Name => 'AssigningFacilitySequence' }, + '0040,0100' => { VR => 'SQ', Name => 'ScheduledProcedureStepSequence' }, + '0040,0220' => { VR => 'SQ', Name => 'ReferencedNonImageCompositeSOPSeq' }, + '0040,0241' => { VR => 'AE', Name => 'PerformedStationAETitle' }, + '0040,0242' => { VR => 'SH', Name => 'PerformedStationName' }, + '0040,0243' => { VR => 'SH', Name => 'PerformedLocation' }, + '0040,0244' => { VR => 'DA', Name => 'PerformedProcedureStepStartDate' }, + '0040,0245' => { VR => 'TM', Name => 'PerformedProcedureStepStartTime' }, + '0040,0250' => { VR => 'DA', Name => 'PerformedProcedureStepEndDate' }, + '0040,0251' => { VR => 'TM', Name => 'PerformedProcedureStepEndTime' }, + '0040,0252' => { VR => 'CS', Name => 'PerformedProcedureStepStatus' }, + '0040,0253' => { VR => 'SH', Name => 'PerformedProcedureStepID' }, + '0040,0254' => { VR => 'LO', Name => 'PerformedProcedureStepDescription' }, + '0040,0255' => { VR => 'LO', Name => 'PerformedProcedureTypeDescription' }, + '0040,0260' => { VR => 'SQ', Name => 'PerformedProtocolCodeSequence' }, + '0040,0261' => { VR => 'CS', Name => 'PerformedProtocolType' }, + '0040,0270' => { VR => 'SQ', Name => 'ScheduledStepAttributesSequence' }, + '0040,0275' => { VR => 'SQ', Name => 'RequestAttributesSequence' }, + '0040,0280' => { VR => 'ST', Name => 'CommentsOnPerformedProcedureStep' }, + '0040,0281' => { VR => 'SQ', Name => 'ProcStepDiscontinueReasonCodeSeq' }, + '0040,0293' => { VR => 'SQ', Name => 'QuantitySequence' }, + '0040,0294' => { VR => 'DS', Name => 'Quantity' }, + '0040,0295' => { VR => 'SQ', Name => 'MeasuringUnitsSequence' }, + '0040,0296' => { VR => 'SQ', Name => 'BillingItemSequence' }, + '0040,0300' => { VR => 'US', Name => 'TotalTimeOfFluoroscopy' }, + '0040,0301' => { VR => 'US', Name => 'TotalNumberOfExposures' }, + '0040,0302' => { VR => 'US', Name => 'EntranceDose' }, + '0040,0303' => { VR => 'US', Name => 'ExposedArea' }, + '0040,0306' => { VR => 'DS', Name => 'DistanceSourceToEntrance' }, + '0040,0307' => { VR => 'DS', Name => 'DistanceSourceToSupport' }, + '0040,030E' => { VR => 'SQ', Name => 'ExposureDoseSequence' }, + '0040,0310' => { VR => 'ST', Name => 'CommentsOnRadiationDose' }, + '0040,0312' => { VR => 'DS', Name => 'XRayOutput' }, + '0040,0314' => { VR => 'DS', Name => 'HalfValueLayer' }, + '0040,0316' => { VR => 'DS', Name => 'OrganDose' }, + '0040,0318' => { VR => 'CS', Name => 'OrganExposed' }, + '0040,0320' => { VR => 'SQ', Name => 'BillingProcedureStepSequence' }, + '0040,0321' => { VR => 'SQ', Name => 'FilmConsumptionSequence' }, + '0040,0324' => { VR => 'SQ', Name => 'BillingSuppliesAndDevicesSequence' }, + '0040,0330' => { VR => 'SQ', Name => 'ReferencedProcedureStepSequence' }, + '0040,0340' => { VR => 'SQ', Name => 'PerformedSeriesSequence' }, + '0040,0400' => { VR => 'LT', Name => 'CommentsOnScheduledProcedureStep' }, + '0040,0440' => { VR => 'SQ', Name => 'ProtocolContextSequence' }, + '0040,0441' => { VR => 'SQ', Name => 'ContentItemModifierSequence' }, + '0040,050A' => { VR => 'LO', Name => 'SpecimenAccessionNumber' }, + '0040,0512' => { VR => 'LO', Name => 'ContainerIdentifier' }, + '0040,051A' => { VR => 'LO', Name => 'ContainerDescription' }, + '0040,0550' => { VR => 'SQ', Name => 'SpecimenSequence' }, + '0040,0551' => { VR => 'LO', Name => 'SpecimenIdentifier' }, + '0040,0552' => { VR => 'SQ', Name => 'SpecimenDescriptionSequenceTrial' }, + '0040,0553' => { VR => 'ST', Name => 'SpecimenDescriptionTrial' }, + '0040,0554' => { VR => 'UI', Name => 'SpecimenUID' }, + '0040,0555' => { VR => 'SQ', Name => 'AcquisitionContextSequence' }, + '0040,0556' => { VR => 'ST', Name => 'AcquisitionContextDescription' }, + '0040,059A' => { VR => 'SQ', Name => 'SpecimenTypeCodeSequence' }, + '0040,0600' => { VR => 'LO', Name => 'SpecimenShortDescription' }, + '0040,06FA' => { VR => 'LO', Name => 'SlideIdentifier' }, + '0040,071A' => { VR => 'SQ', Name => 'ImageCenterPointCoordinatesSeq' }, + '0040,072A' => { VR => 'DS', Name => 'XOffsetInSlideCoordinateSystem' }, + '0040,073A' => { VR => 'DS', Name => 'YOffsetInSlideCoordinateSystem' }, + '0040,074A' => { VR => 'DS', Name => 'ZOffsetInSlideCoordinateSystem' }, + '0040,08D8' => { VR => 'SQ', Name => 'PixelSpacingSequence' }, + '0040,08DA' => { VR => 'SQ', Name => 'CoordinateSystemAxisCodeSequence' }, + '0040,08EA' => { VR => 'SQ', Name => 'MeasurementUnitsCodeSequence' }, + '0040,09F8' => { VR => 'SQ', Name => 'VitalStainCodeSequenceTrial' }, + '0040,1001' => { VR => 'SH', Name => 'RequestedProcedureID' }, + '0040,1002' => { VR => 'LO', Name => 'ReasonForRequestedProcedure' }, + '0040,1003' => { VR => 'SH', Name => 'RequestedProcedurePriority' }, + '0040,1004' => { VR => 'LO', Name => 'PatientTransportArrangements' }, + '0040,1005' => { VR => 'LO', Name => 'RequestedProcedureLocation' }, + '0040,1006' => { VR => 'SH', Name => 'PlacerOrderNumber-Procedure' }, + '0040,1007' => { VR => 'SH', Name => 'FillerOrderNumber-Procedure' }, + '0040,1008' => { VR => 'LO', Name => 'ConfidentialityCode' }, + '0040,1009' => { VR => 'SH', Name => 'ReportingPriority' }, + '0040,100A' => { VR => 'SQ', Name => 'ReasonForRequestedProcedureCodeSeq' }, + '0040,1010' => { VR => 'PN', Name => 'NamesOfIntendedRecipientsOfResults' }, + '0040,1011' => { VR => 'SQ', Name => 'IntendedRecipientsOfResultsIDSeq' }, + '0040,1101' => { VR => 'SQ', Name => 'PersonIdentificationCodeSequence' }, + '0040,1102' => { VR => 'ST', Name => 'PersonAddress' }, + '0040,1103' => { VR => 'LO', Name => 'PersonTelephoneNumbers' }, + '0040,1400' => { VR => 'LT', Name => 'RequestedProcedureComments' }, + '0040,2001' => { VR => 'LO', Name => 'ReasonForImagingServiceRequest' }, + '0040,2004' => { VR => 'DA', Name => 'IssueDateOfImagingServiceRequest' }, + '0040,2005' => { VR => 'TM', Name => 'IssueTimeOfImagingServiceRequest' }, + '0040,2006' => { VR => 'SH', Name => 'PlacerOrderNum-ImagingServiceReq' }, + '0040,2007' => { VR => 'SH', Name => 'FillerOrderNum-ImagingServiceReq' }, + '0040,2008' => { VR => 'PN', Name => 'OrderEnteredBy' }, + '0040,2009' => { VR => 'SH', Name => 'OrderEntererLocation' }, + '0040,2010' => { VR => 'SH', Name => 'OrderCallbackPhoneNumber' }, + '0040,2016' => { VR => 'LO', Name => 'PlacerOrderNum-ImagingServiceReq' }, + '0040,2017' => { VR => 'LO', Name => 'FillerOrderNum-ImagingServiceReq' }, + '0040,2400' => { VR => 'LT', Name => 'ImagingServiceRequestComments' }, + '0040,3001' => { VR => 'LO', Name => 'ConfidentialityOnPatientDataDescr' }, + '0040,4001' => { VR => 'CS', Name => 'GenPurposeScheduledProcStepStatus' }, + '0040,4002' => { VR => 'CS', Name => 'GenPurposePerformedProcStepStatus' }, + '0040,4003' => { VR => 'CS', Name => 'GenPurposeSchedProcStepPriority' }, + '0040,4004' => { VR => 'SQ', Name => 'SchedProcessingApplicationsCodeSeq' }, + '0040,4005' => { VR => 'DT', Name => 'SchedProcedureStepStartDateAndTime' }, + '0040,4006' => { VR => 'CS', Name => 'MultipleCopiesFlag' }, + '0040,4007' => { VR => 'SQ', Name => 'PerformedProcessingAppsCodeSeq' }, + '0040,4009' => { VR => 'SQ', Name => 'HumanPerformerCodeSequence' }, + '0040,4010' => { VR => 'DT', Name => 'SchedProcStepModificationDateTime' }, + '0040,4011' => { VR => 'DT', Name => 'ExpectedCompletionDateAndTime' }, + '0040,4015' => { VR => 'SQ', Name => 'ResultingGenPurposePerfProcStepSeq' }, + '0040,4016' => { VR => 'SQ', Name => 'RefGenPurposeSchedProcStepSeq' }, + '0040,4018' => { VR => 'SQ', Name => 'ScheduledWorkitemCodeSequence' }, + '0040,4019' => { VR => 'SQ', Name => 'PerformedWorkitemCodeSequence' }, + '0040,4020' => { VR => 'CS', Name => 'InputAvailabilityFlag' }, + '0040,4021' => { VR => 'SQ', Name => 'InputInformationSequence' }, + '0040,4022' => { VR => 'SQ', Name => 'RelevantInformationSequence' }, + '0040,4023' => { VR => 'UI', Name => 'RefGenPurSchedProcStepTransUID' }, + '0040,4025' => { VR => 'SQ', Name => 'ScheduledStationNameCodeSequence' }, + '0040,4026' => { VR => 'SQ', Name => 'ScheduledStationClassCodeSequence' }, + '0040,4027' => { VR => 'SQ', Name => 'SchedStationGeographicLocCodeSeq' }, + '0040,4028' => { VR => 'SQ', Name => 'PerformedStationNameCodeSequence' }, + '0040,4029' => { VR => 'SQ', Name => 'PerformedStationClassCodeSequence' }, + '0040,4030' => { VR => 'SQ', Name => 'PerformedStationGeogLocCodeSeq' }, + '0040,4031' => { VR => 'SQ', Name => 'RequestedSubsequentWorkItemCodeSeq' }, + '0040,4032' => { VR => 'SQ', Name => 'NonDICOMOutputCodeSequence' }, + '0040,4033' => { VR => 'SQ', Name => 'OutputInformationSequence' }, + '0040,4034' => { VR => 'SQ', Name => 'ScheduledHumanPerformersSequence' }, + '0040,4035' => { VR => 'SQ', Name => 'ActualHumanPerformersSequence' }, + '0040,4036' => { VR => 'LO', Name => 'HumanPerformersOrganization' }, + '0040,4037' => { VR => 'PN', Name => 'HumanPerformerName' }, + '0040,4040' => { VR => 'CS', Name => 'RawDataHandling' }, + '0040,8302' => { VR => 'DS', Name => 'EntranceDoseInMilliGy' }, + '0040,9094' => { VR => 'SQ', Name => 'RefImageRealWorldValueMappingSeq' }, + '0040,9096' => { VR => 'SQ', Name => 'RealWorldValueMappingSequence' }, + '0040,9098' => { VR => 'SQ', Name => 'PixelValueMappingCodeSequence' }, + '0040,9210' => { VR => 'SH', Name => 'LUTLabel' }, + '0040,9211' => { VR => 'SS', Name => 'RealWorldValueLastValueMapped' }, + '0040,9212' => { VR => 'FD', Name => 'RealWorldValueLUTData' }, + '0040,9216' => { VR => 'SS', Name => 'RealWorldValueFirstValueMapped' }, + '0040,9224' => { VR => 'FD', Name => 'RealWorldValueIntercept' }, + '0040,9225' => { VR => 'FD', Name => 'RealWorldValueSlope' }, + '0040,A010' => { VR => 'CS', Name => 'RelationshipType' }, + '0040,A027' => { VR => 'LO', Name => 'VerifyingOrganization' }, + '0040,A030' => { VR => 'DT', Name => 'VerificationDateTime' }, + '0040,A032' => { VR => 'DT', Name => 'ObservationDateTime' }, + '0040,A040' => { VR => 'CS', Name => 'ValueType' }, + '0040,A043' => { VR => 'SQ', Name => 'ConceptNameCodeSequence' }, + '0040,A050' => { VR => 'CS', Name => 'ContinuityOfContent' }, + '0040,A073' => { VR => 'SQ', Name => 'VerifyingObserverSequence' }, + '0040,A075' => { VR => 'PN', Name => 'VerifyingObserverName' }, + '0040,A078' => { VR => 'SQ', Name => 'AuthorObserverSequence' }, + '0040,A07A' => { VR => 'SQ', Name => 'ParticipantSequence' }, + '0040,A07C' => { VR => 'SQ', Name => 'CustodialOrganizationSequence' }, + '0040,A080' => { VR => 'CS', Name => 'ParticipationType' }, + '0040,A082' => { VR => 'DT', Name => 'ParticipationDateTime' }, + '0040,A084' => { VR => 'CS', Name => 'ObserverType' }, + '0040,A088' => { VR => 'SQ', Name => 'VerifyingObserverIdentCodeSequence' }, + '0040,A090' => { VR => 'SQ', Name => 'EquivalentCDADocumentSequence' }, + '0040,A0B0' => { VR => 'US', Name => 'ReferencedWaveformChannels' }, + '0040,A120' => { VR => 'DT', Name => 'DateTime' }, + '0040,A121' => { VR => 'DA', Name => 'Date' }, + '0040,A122' => { VR => 'TM', Name => 'Time' }, + '0040,A123' => { VR => 'PN', Name => 'PersonName' }, + '0040,A124' => { VR => 'UI', Name => 'UID' }, + '0040,A130' => { VR => 'CS', Name => 'TemporalRangeType' }, + '0040,A132' => { VR => 'UL', Name => 'ReferencedSamplePositions' }, + '0040,A136' => { VR => 'US', Name => 'ReferencedFrameNumbers' }, + '0040,A138' => { VR => 'DS', Name => 'ReferencedTimeOffsets' }, + '0040,A13A' => { VR => 'DT', Name => 'ReferencedDateTime' }, + '0040,A160' => { VR => 'UT', Name => 'TextValue' }, + '0040,A168' => { VR => 'SQ', Name => 'ConceptCodeSequence' }, + '0040,A170' => { VR => 'SQ', Name => 'PurposeOfReferenceCodeSequence' }, + '0040,A180' => { VR => 'US', Name => 'AnnotationGroupNumber' }, + '0040,A195' => { VR => 'SQ', Name => 'ModifierCodeSequence' }, + '0040,A300' => { VR => 'SQ', Name => 'MeasuredValueSequence' }, + '0040,A301' => { VR => 'SQ', Name => 'NumericValueQualifierCodeSequence' }, + '0040,A30A' => { VR => 'DS', Name => 'NumericValue' }, + '0040,A353' => { VR => 'ST', Name => 'AddressTrial' }, + '0040,A354' => { VR => 'LO', Name => 'TelephoneNumberTrial' }, + '0040,A360' => { VR => 'SQ', Name => 'PredecessorDocumentsSequence' }, + '0040,A370' => { VR => 'SQ', Name => 'ReferencedRequestSequence' }, + '0040,A372' => { VR => 'SQ', Name => 'PerformedProcedureCodeSequence' }, + '0040,A375' => { VR => 'SQ', Name => 'CurrentRequestedProcEvidenceSeq' }, + '0040,A385' => { VR => 'SQ', Name => 'PertinentOtherEvidenceSequence' }, + '0040,A390' => { VR => 'SQ', Name => 'HL7StructuredDocumentRefSeq' }, + '0040,A491' => { VR => 'CS', Name => 'CompletionFlag' }, + '0040,A492' => { VR => 'LO', Name => 'CompletionFlagDescription' }, + '0040,A493' => { VR => 'CS', Name => 'VerificationFlag' }, + '0040,A494' => { VR => 'CS', Name => 'ArchiveRequested' }, + '0040,A496' => { VR => 'CS', Name => 'PreliminaryFlag' }, + '0040,A504' => { VR => 'SQ', Name => 'ContentTemplateSequence' }, + '0040,A525' => { VR => 'SQ', Name => 'IdenticalDocumentsSequence' }, + '0040,A730' => { VR => 'SQ', Name => 'ContentSequence' }, + '0040,B020' => { VR => 'SQ', Name => 'AnnotationSequence' }, + '0040,DB00' => { VR => 'CS', Name => 'TemplateIdentifier' }, + '0040,DB06' => { VR => 'DT', Name => 'TemplateVersion' }, + '0040,DB07' => { VR => 'DT', Name => 'TemplateLocalVersion' }, + '0040,DB0B' => { VR => 'CS', Name => 'TemplateExtensionFlag' }, + '0040,DB0C' => { VR => 'UI', Name => 'TemplateExtensionOrganizationUID' }, + '0040,DB0D' => { VR => 'UI', Name => 'TemplateExtensionCreatorUID' }, + '0040,DB73' => { VR => 'UL', Name => 'ReferencedContentItemIdentifier' }, + '0040,E001' => { VR => 'ST', Name => 'HL7InstanceIdentifier' }, + '0040,E004' => { VR => 'DT', Name => 'HL7DocumentEffectiveTime' }, + '0040,E006' => { VR => 'SQ', Name => 'HL7DocumentTypeCodeSequence' }, + '0040,E010' => { VR => 'UT', Name => 'RetrieveURI' }, + '0040,E011' => { VR => 'UI', Name => 'RetrieveLocationUID' }, + '0042,0010' => { VR => 'ST', Name => 'DocumentTitle' }, + '0042,0011' => { VR => 'OB', Name => 'EncapsulatedDocument' }, + '0042,0012' => { VR => 'LO', Name => 'MIMETypeOfEncapsulatedDocument' }, + '0042,0013' => { VR => 'SQ', Name => 'SourceInstanceSequence' }, + '0042,0014' => { VR => 'LO', Name => 'ListOfMIMETypes' }, + # GEMS_PARM_01 (ref 4) + '0043,1001' => { VR => 'SS', Name => 'BitmapOfPrescanOptions' }, + '0043,1002' => { VR => 'SS', Name => 'GradientOffsetInX' }, + '0043,1003' => { VR => 'SS', Name => 'GradientOffsetInY' }, + '0043,1004' => { VR => 'SS', Name => 'GradientOffsetInZ' }, + '0043,1005' => { VR => 'SS', Name => 'ImgIsOriginalOrUnoriginal' }, + '0043,1006' => { VR => 'SS', Name => 'NumberOfEPIShots' }, + '0043,1007' => { VR => 'SS', Name => 'ViewsPerSegment' }, + '0043,1008' => { VR => 'SS', Name => 'RespiratoryRateBpm' }, + '0043,1009' => { VR => 'SS', Name => 'RespiratoryTriggerPoint' }, + '0043,100A' => { VR => 'SS', Name => 'TypeOfReceiverUsed' }, + '0043,100B' => { VR => 'DS', Name => 'PeakRateOfChangeOfGradientField' }, + '0043,100C' => { VR => 'DS', Name => 'LimitsInUnitsOfPercent' }, + '0043,100D' => { VR => 'DS', Name => 'PSDEstimatedLimit' }, + '0043,100E' => { VR => 'DS', Name => 'PSDEstimatedLimitInTeslaPerSecond' }, + '0043,100F' => { VR => 'DS', Name => 'Saravghead' }, + '0043,1010' => { VR => 'US', Name => 'WindowValue' }, + '0043,1011' => { VR => 'US', Name => 'TotalInputViews' }, + '0043,1012' => { VR => 'SS', Name => 'X-RayChain' }, + '0043,1013' => { VR => 'SS', Name => 'DeconKernelParameters' }, + '0043,1014' => { VR => 'SS', Name => 'CalibrationParameters' }, + '0043,1015' => { VR => 'SS', Name => 'TotalOutputViews' }, + '0043,1016' => { VR => 'SS', Name => 'NumberOfOverranges' }, + '0043,1017' => { VR => 'DS', Name => 'IBHImageScaleFactors' }, + '0043,1018' => { VR => 'DS', Name => 'BBHCoefficients' }, + '0043,1019' => { VR => 'SS', Name => 'NumberOfBBHChainsToBlend' }, + '0043,101A' => { VR => 'SL', Name => 'StartingChannelNumber' }, + '0043,101B' => { VR => 'SS', Name => 'PpscanParameters' }, + '0043,101C' => { VR => 'SS', Name => 'GEImageIntegrity' }, + '0043,101D' => { VR => 'SS', Name => 'LevelValue' }, + '0043,101E' => { VR => 'DS', Name => 'DeltaStartTime' }, + '0043,101F' => { VR => 'SL', Name => 'MaxOverrangesInAView' }, + '0043,1020' => { VR => 'DS', Name => 'AvgOverrangesAllViews' }, + '0043,1021' => { VR => 'SS', Name => 'CorrectedAfterGlowTerms' }, + '0043,1025' => { VR => 'SS', Name => 'ReferenceChannels' }, + '0043,1026' => { VR => 'US', Name => 'NoViewsRefChansBlocked' }, + '0043,1027' => { VR => 'SH', Name => 'ScanPitchRatio' }, + '0043,1028' => { VR => 'OB', Name => 'UniqueImageIden' }, + '0043,1029' => { VR => 'OB', Name => 'HistogramTables' }, + '0043,102A' => { VR => 'OB', Name => 'UserDefinedData' }, + '0043,102B' => { VR => 'SS', Name => 'PrivateScanOptions' }, + '0043,102C' => { VR => 'SS', Name => 'EffectiveEchoSpacing' }, + '0043,102D' => { VR => 'SH', Name => 'StringSlopField1' }, + '0043,102E' => { VR => 'SH', Name => 'StringSlopField2' }, + '0043,102F' => { VR => 'SS', Name => 'RawDataType' }, + '0043,1030' => { VR => 'SS', Name => 'RawDataType' }, + '0043,1031' => { VR => 'DS', Name => 'RACordOfTargetReconCenter' }, + '0043,1032' => { VR => 'SS', Name => 'RawDataType' }, + '0043,1033' => { VR => 'FL', Name => 'NegScanspacing' }, + '0043,1034' => { VR => 'IS', Name => 'OffsetFrequency' }, + '0043,1035' => { VR => 'UL', Name => 'UserUsageTag' }, + '0043,1036' => { VR => 'UL', Name => 'UserFillMapMSW' }, + '0043,1037' => { VR => 'UL', Name => 'UserFillMapLSW' }, + '0043,1038' => { VR => 'FL', Name => 'User25-48' }, + '0043,1039' => { VR => 'IS', Name => 'SlopInt6-9' }, + '0043,1040' => { VR => 'FL', Name => 'TriggerOnPosition' }, + '0043,1041' => { VR => 'FL', Name => 'DegreeOfRotation' }, + '0043,1042' => { VR => 'SL', Name => 'DASTriggerSource' }, + '0043,1043' => { VR => 'SL', Name => 'DASFpaGain' }, + '0043,1044' => { VR => 'SL', Name => 'DASOutputSource' }, + '0043,1045' => { VR => 'SL', Name => 'DASAdInput' }, + '0043,1046' => { VR => 'SL', Name => 'DASCalMode' }, + '0043,1047' => { VR => 'SL', Name => 'DASCalFrequency' }, + '0043,1048' => { VR => 'SL', Name => 'DASRegXm' }, + '0043,1049' => { VR => 'SL', Name => 'DASAutoZero' }, + '0043,104A' => { VR => 'SS', Name => 'StartingChannelOfView' }, + '0043,104B' => { VR => 'SL', Name => 'DASXmPattern' }, + '0043,104C' => { VR => 'SS', Name => 'TGGCTriggerMode' }, + '0043,104D' => { VR => 'FL', Name => 'StartScanToXrayOnDelay' }, + '0043,104E' => { VR => 'FL', Name => 'DurationOfXrayOn' }, + '0043,1060' => { VR => 'IS', Name => 'SlopInt10-17' }, + '0043,1061' => { VR => 'UI', Name => 'ScannerStudyEntityUID' }, + '0043,1062' => { VR => 'SH', Name => 'ScannerStudyID' }, + '0043,106f' => { VR => 'DS', Name => 'ScannerTableEntry' }, + # ? + '0044,0001' => { VR => 'ST', Name => 'ProductPackageIdentifier' }, + '0044,0002' => { VR => 'CS', Name => 'SubstanceAdministrationApproval' }, + '0044,0003' => { VR => 'LT', Name => 'ApprovalStatusFurtherDescription' }, + '0044,0004' => { VR => 'DT', Name => 'ApprovalStatusDateTime' }, + '0044,0007' => { VR => 'SQ', Name => 'ProductTypeCodeSequence' }, + '0044,0008' => { VR => 'LO', Name => 'ProductName' }, + '0044,0009' => { VR => 'LT', Name => 'ProductDescription' }, + '0044,000A' => { VR => 'LO', Name => 'ProductLotIdentifier' }, + '0044,000B' => { VR => 'DT', Name => 'ProductExpirationDateTime' }, + '0044,0010' => { VR => 'DT', Name => 'SubstanceAdministrationDateTime' }, + '0044,0011' => { VR => 'LO', Name => 'SubstanceAdministrationNotes' }, + '0044,0012' => { VR => 'LO', Name => 'SubstanceAdministrationDeviceID' }, + '0044,0013' => { VR => 'SQ', Name => 'ProductParameterSequence' }, + '0044,0019' => { VR => 'SQ', Name => 'SubstanceAdminParameterSeq' }, + # GEMS_HELIOS_01 (ref 4) + '0045,1001' => { VR => 'LO', Name => 'NumberOfMacroRowsInDetector' }, + '0045,1002' => { VR => 'FL', Name => 'MacroWidthAtISOCenter' }, + '0045,1003' => { VR => 'SS', Name => 'DASType' }, + '0045,1004' => { VR => 'SS', Name => 'DASGain' }, + '0045,1005' => { VR => 'SS', Name => 'DASTemperature' }, + '0045,1006' => { VR => 'CS', Name => 'TableDirectionInOrOut' }, + '0045,1007' => { VR => 'FL', Name => 'ZSmoothingFactor' }, + '0045,1008' => { VR => 'SS', Name => 'ViewWeightingMode' }, + '0045,1009' => { VR => 'SS', Name => 'SigmaRowNumberWhichRowsWereUsed' }, + '0045,100A' => { VR => 'FL', Name => 'MinimumDasValueFoundInTheScanData' }, + '0045,100B' => { VR => 'FL', Name => 'MaximumOffsetShiftValueUsed' }, + '0045,100C' => { VR => 'SS', Name => 'NumberOfViewsShifted' }, + '0045,100D' => { VR => 'SS', Name => 'ZTrackingFlag' }, + '0045,100E' => { VR => 'FL', Name => 'MeanZError' }, + '0045,100F' => { VR => 'FL', Name => 'ZTrackingMaximumError' }, + '0045,1010' => { VR => 'SS', Name => 'StartingViewForRow2a' }, + '0045,1011' => { VR => 'SS', Name => 'NumberOfViewsInRow2a' }, + '0045,1012' => { VR => 'SS', Name => 'StartingViewForRow1a' }, + '0045,1013' => { VR => 'SS', Name => 'SigmaMode' }, + '0045,1014' => { VR => 'SS', Name => 'NumberOfViewsInRow1a' }, + '0045,1015' => { VR => 'SS', Name => 'StartingViewForRow2b' }, + '0045,1016' => { VR => 'SS', Name => 'NumberOfViewsInRow2b' }, + '0045,1017' => { VR => 'SS', Name => 'StartingViewForRow1b' }, + '0045,1018' => { VR => 'SS', Name => 'NumberOfViewsInRow1b' }, + '0045,1019' => { VR => 'SS', Name => 'AirFilterCalibrationDate' }, + '0045,101A' => { VR => 'SS', Name => 'AirFilterCalibrationTime' }, + '0045,101B' => { VR => 'SS', Name => 'PhantomCalibrationDate' }, + '0045,101C' => { VR => 'SS', Name => 'PhantomCalibrationTime' }, + '0045,101D' => { VR => 'SS', Name => 'ZSlopeCalibrationDate' }, + '0045,101E' => { VR => 'SS', Name => 'ZSlopeCalibrationTime' }, + '0045,101F' => { VR => 'SS', Name => 'CrosstalkCalibrationDate' }, + '0045,1020' => { VR => 'SS', Name => 'CrosstalkCalibrationTime' }, + '0045,1021' => { VR => 'SS', Name => 'IterboneOptionFlag' }, + '0045,1022' => { VR => 'SS', Name => 'PeristalticFlagOption' }, + '0046,0012' => { VR => 'LO', Name => 'LensDescription' }, + '0046,0014' => { VR => 'SQ', Name => 'RightLensSequence' }, + '0046,0015' => { VR => 'SQ', Name => 'LeftLensSequence' }, + '0046,0018' => { VR => 'SQ', Name => 'CylinderSequence' }, + '0046,0028' => { VR => 'SQ', Name => 'PrismSequence' }, + '0046,0030' => { VR => 'FD', Name => 'HorizontalPrismPower' }, + '0046,0032' => { VR => 'CS', Name => 'HorizontalPrismBase' }, + '0046,0034' => { VR => 'FD', Name => 'VerticalPrismPower' }, + '0046,0036' => { VR => 'CS', Name => 'VerticalPrismBase' }, + '0046,0038' => { VR => 'CS', Name => 'LensSegmentType' }, + '0046,0040' => { VR => 'FD', Name => 'OpticalTransmittance' }, + '0046,0042' => { VR => 'FD', Name => 'ChannelWidth' }, + '0046,0044' => { VR => 'FD', Name => 'PupilSize' }, + '0046,0046' => { VR => 'FD', Name => 'CornealSize' }, + '0046,0060' => { VR => 'FD', Name => 'DistancePupillaryDistance' }, + '0046,0062' => { VR => 'FD', Name => 'NearPupillaryDistance' }, + '0046,0064' => { VR => 'FD', Name => 'OtherPupillaryDistance' }, + '0046,0075' => { VR => 'FD', Name => 'RadiusOfCurvature' }, + '0046,0076' => { VR => 'FD', Name => 'KeratometricPower' }, + '0046,0077' => { VR => 'FD', Name => 'KeratometricAxis' }, + '0046,0092' => { VR => 'CS', Name => 'BackgroundColor' }, + '0046,0094' => { VR => 'CS', Name => 'Optotype' }, + '0046,0095' => { VR => 'CS', Name => 'OptotypePresentation' }, + '0046,0100' => { VR => 'SQ', Name => 'AddNearSequence' }, + '0046,0101' => { VR => 'SQ', Name => 'AddIntermediateSequence' }, + '0046,0102' => { VR => 'SQ', Name => 'AddOtherSequence' }, + '0046,0104' => { VR => 'FD', Name => 'AddPower' }, + '0046,0106' => { VR => 'FD', Name => 'ViewingDistance' }, + '0046,0125' => { VR => 'CS', Name => 'ViewingDistanceType' }, + '0046,0135' => { VR => 'SS', Name => 'VisualAcuityModifiers' }, + '0046,0137' => { VR => 'FD', Name => 'DecimalVisualAcuity' }, + '0046,0139' => { VR => 'LO', Name => 'OptotypeDetailedDefinition' }, + '0046,0146' => { VR => 'FD', Name => 'SpherePower' }, + '0046,0147' => { VR => 'FD', Name => 'CylinderPower' }, + # calibration group + '0050,0004' => { VR => 'CS', Name => 'CalibrationImage' }, + '0050,0010' => { VR => 'SQ', Name => 'DeviceSequence' }, + '0050,0014' => { VR => 'DS', Name => 'DeviceLength' }, + '0050,0015' => { VR => 'FD', Name => 'ContainerComponentWidth' }, + '0050,0016' => { VR => 'DS', Name => 'DeviceDiameter' }, + '0050,0017' => { VR => 'CS', Name => 'DeviceDiameterUnits' }, + '0050,0018' => { VR => 'DS', Name => 'DeviceVolume' }, + '0050,0019' => { VR => 'DS', Name => 'InterMarkerDistance' }, + '0050,001B' => { VR => 'LO', Name => 'ContainerComponentID' }, + '0050,0020' => { VR => 'LO', Name => 'DeviceDescription' }, + # nuclear acquisition group + '0054,0010' => { VR => 'US', Name => 'EnergyWindowVector' }, + '0054,0011' => { VR => 'US', Name => 'NumberOfEnergyWindows' }, + '0054,0012' => { VR => 'SQ', Name => 'EnergyWindowInformationSequence' }, + '0054,0013' => { VR => 'SQ', Name => 'EnergyWindowRangeSequence' }, + '0054,0014' => { VR => 'DS', Name => 'EnergyWindowLowerLimit' }, + '0054,0015' => { VR => 'DS', Name => 'EnergyWindowUpperLimit' }, + '0054,0016' => { VR => 'SQ', Name => 'RadiopharmaceuticalInformationSeq' }, + '0054,0017' => { VR => 'IS', Name => 'ResidualSyringeCounts' }, + '0054,0018' => { VR => 'SH', Name => 'EnergyWindowName' }, + '0054,0020' => { VR => 'US', Name => 'DetectorVector' }, + '0054,0021' => { VR => 'US', Name => 'NumberOfDetectors' }, + '0054,0022' => { VR => 'SQ', Name => 'DetectorInformationSequence' }, + '0054,0030' => { VR => 'US', Name => 'PhaseVector' }, + '0054,0031' => { VR => 'US', Name => 'NumberOfPhases' }, + '0054,0032' => { VR => 'SQ', Name => 'PhaseInformationSequence' }, + '0054,0033' => { VR => 'US', Name => 'NumberOfFramesInPhase' }, + '0054,0036' => { VR => 'IS', Name => 'PhaseDelay' }, + '0054,0038' => { VR => 'IS', Name => 'PauseBetweenFrames' }, + '0054,0039' => { VR => 'CS', Name => 'PhaseDescription' }, + '0054,0050' => { VR => 'US', Name => 'RotationVector' }, + '0054,0051' => { VR => 'US', Name => 'NumberOfRotations' }, + '0054,0052' => { VR => 'SQ', Name => 'RotationInformationSequence' }, + '0054,0053' => { VR => 'US', Name => 'NumberOfFramesInRotation' }, + '0054,0060' => { VR => 'US', Name => 'RRIntervalVector' }, + '0054,0061' => { VR => 'US', Name => 'NumberOfRRIntervals' }, + '0054,0062' => { VR => 'SQ', Name => 'GatedInformationSequence' }, + '0054,0063' => { VR => 'SQ', Name => 'DataInformationSequence' }, + '0054,0070' => { VR => 'US', Name => 'TimeSlotVector' }, + '0054,0071' => { VR => 'US', Name => 'NumberOfTimeSlots' }, + '0054,0072' => { VR => 'SQ', Name => 'TimeSlotInformationSequence' }, + '0054,0073' => { VR => 'DS', Name => 'TimeSlotTime' }, + '0054,0080' => { VR => 'US', Name => 'SliceVector' }, + '0054,0081' => { VR => 'US', Name => 'NumberOfSlices' }, + '0054,0090' => { VR => 'US', Name => 'AngularViewVector' }, + '0054,0100' => { VR => 'US', Name => 'TimeSliceVector' }, + '0054,0101' => { VR => 'US', Name => 'NumberOfTimeSlices' }, + '0054,0200' => { VR => 'DS', Name => 'StartAngle' }, + '0054,0202' => { VR => 'CS', Name => 'TypeOfDetectorMotion' }, + '0054,0210' => { VR => 'IS', Name => 'TriggerVector' }, + '0054,0211' => { VR => 'US', Name => 'NumberOfTriggersInPhase' }, + '0054,0220' => { VR => 'SQ', Name => 'ViewCodeSequence' }, + '0054,0222' => { VR => 'SQ', Name => 'ViewModifierCodeSequence' }, + '0054,0300' => { VR => 'SQ', Name => 'RadionuclideCodeSequence' }, + '0054,0302' => { VR => 'SQ', Name => 'AdministrationRouteCodeSequence' }, + '0054,0304' => { VR => 'SQ', Name => 'RadiopharmaceuticalCodeSequence' }, + '0054,0306' => { VR => 'SQ', Name => 'CalibrationDataSequence' }, + '0054,0308' => { VR => 'US', Name => 'EnergyWindowNumber' }, + '0054,0400' => { VR => 'SH', Name => 'ImageID' }, + '0054,0410' => { VR => 'SQ', Name => 'PatientOrientationCodeSequence' }, + '0054,0412' => { VR => 'SQ', Name => 'PatientOrientationModifierCodeSeq' }, + '0054,0414' => { VR => 'SQ', Name => 'PatientGantryRelationshipCodeSeq' }, + '0054,0500' => { VR => 'CS', Name => 'SliceProgressionDirection' }, + '0054,1000' => { VR => 'CS', Name => 'SeriesType' }, + '0054,1001' => { VR => 'CS', Name => 'Units' }, + '0054,1002' => { VR => 'CS', Name => 'CountsSource' }, + '0054,1004' => { VR => 'CS', Name => 'ReprojectionMethod' }, + '0054,1100' => { VR => 'CS', Name => 'RandomsCorrectionMethod' }, + '0054,1101' => { VR => 'LO', Name => 'AttenuationCorrectionMethod' }, + '0054,1102' => { VR => 'CS', Name => 'DecayCorrection' }, + '0054,1103' => { VR => 'LO', Name => 'ReconstructionMethod' }, + '0054,1104' => { VR => 'LO', Name => 'DetectorLinesOfResponseUsed' }, + '0054,1105' => { VR => 'LO', Name => 'ScatterCorrectionMethod' }, + '0054,1200' => { VR => 'DS', Name => 'AxialAcceptance' }, + '0054,1201' => { VR => 'IS', Name => 'AxialMash' }, + '0054,1202' => { VR => 'IS', Name => 'TransverseMash' }, + '0054,1203' => { VR => 'DS', Name => 'DetectorElementSize' }, + '0054,1210' => { VR => 'DS', Name => 'CoincidenceWindowWidth' }, + '0054,1220' => { VR => 'CS', Name => 'SecondaryCountsType' }, + '0054,1300' => { VR => 'DS', Name => 'FrameReferenceTime' }, + '0054,1310' => { VR => 'IS', Name => 'PrimaryCountsAccumulated' }, + '0054,1311' => { VR => 'IS', Name => 'SecondaryCountsAccumulated' }, + '0054,1320' => { VR => 'DS', Name => 'SliceSensitivityFactor' }, + '0054,1321' => { VR => 'DS', Name => 'DecayFactor' }, + '0054,1322' => { VR => 'DS', Name => 'DoseCalibrationFactor' }, + '0054,1323' => { VR => 'DS', Name => 'ScatterFractionFactor' }, + '0054,1324' => { VR => 'DS', Name => 'DeadTimeFactor' }, + '0054,1330' => { VR => 'US', Name => 'ImageIndex' }, + '0054,1400' => { VR => 'CS', Name => 'CountsIncluded' }, + '0054,1401' => { VR => 'CS', Name => 'DeadTimeCorrectionFlag' }, + '0060,3000' => { VR => 'SQ', Name => 'HistogramSequence' }, + '0060,3002' => { VR => 'US', Name => 'HistogramNumberOfBins' }, + '0060,3004' => { VR => 'US', Name => 'HistogramFirstBinValue' }, + '0060,3006' => { VR => 'US', Name => 'HistogramLastBinValue' }, + '0060,3008' => { VR => 'US', Name => 'HistogramBinWidth' }, + '0060,3010' => { VR => 'LO', Name => 'HistogramExplanation' }, + '0060,3020' => { VR => 'UL', Name => 'HistogramData' }, + '0062,0001' => { VR => 'CS', Name => 'SegmentationType' }, + '0062,0002' => { VR => 'SQ', Name => 'SegmentSequence' }, + '0062,0003' => { VR => 'SQ', Name => 'SegmentedPropertyCategoryCodeSeq' }, + '0062,0004' => { VR => 'US', Name => 'SegmentNumber' }, + '0062,0005' => { VR => 'LO', Name => 'SegmentLabel' }, + '0062,0006' => { VR => 'ST', Name => 'SegmentDescription' }, + '0062,0008' => { VR => 'CS', Name => 'SegmentAlgorithmType' }, + '0062,0009' => { VR => 'LO', Name => 'SegmentAlgorithmName' }, + '0062,000A' => { VR => 'SQ', Name => 'SegmentIdentificationSequence' }, + '0062,000B' => { VR => 'US', Name => 'ReferencedSegmentNumber' }, + '0062,000C' => { VR => 'US', Name => 'RecommendedDisplayGrayscaleValue' }, + '0062,000D' => { VR => 'US', Name => 'RecommendedDisplayCIELabValue' }, + '0062,000E' => { VR => 'US', Name => 'MaximumFractionalValue' }, + '0062,000F' => { VR => 'SQ', Name => 'SegmentedPropertyTypeCodeSequence' }, + '0062,0010' => { VR => 'CS', Name => 'SegmentationFractionalType' }, + '0064,0002' => { VR => 'SQ', Name => 'DeformableRegistrationSequence' }, + '0064,0003' => { VR => 'UI', Name => 'SourceFrameOfReferenceUID' }, + '0064,0005' => { VR => 'SQ', Name => 'DeformableRegistrationGridSequence' }, + '0064,0007' => { VR => 'UL', Name => 'GridDimensions' }, + '0064,0008' => { VR => 'FD', Name => 'GridResolution' }, + '0064,0009' => { VR => 'OF', Name => 'VectorGridData' }, + '0064,000F' => { VR => 'SQ', Name => 'PreDeformationMatrixRegistSeq' }, + '0064,0010' => { VR => 'SQ', Name => 'PostDeformationMatrixRegistSeq' }, + '0066,0001' => { VR => 'UL', Name => 'NumberOfSurfaces' }, + '0066,0002' => { VR => 'SQ', Name => 'SurfaceSequence' }, + '0066,0003' => { VR => 'UL', Name => 'SurfaceNumber' }, + '0066,0004' => { VR => 'LT', Name => 'SurfaceComments' }, + '0066,0009' => { VR => 'CS', Name => 'SurfaceProcessing' }, + '0066,000A' => { VR => 'FL', Name => 'SurfaceProcessingRatio' }, + '0066,000E' => { VR => 'CS', Name => 'FiniteVolume' }, + '0066,0010' => { VR => 'CS', Name => 'Manifold' }, + '0066,0011' => { VR => 'SQ', Name => 'SurfacePointsSequence' }, + '0066,0015' => { VR => 'UL', Name => 'NumberOfSurfacePoints' }, + '0066,0016' => { VR => 'OF', Name => 'PointCoordinatesData' }, + '0066,0017' => { VR => 'FL', Name => 'PointPositionAccuracy' }, + '0066,0018' => { VR => 'FL', Name => 'MeanPointDistance' }, + '0066,0019' => { VR => 'FL', Name => 'MaximumPointDistance' }, + '0066,001B' => { VR => 'FL', Name => 'AxisOfRotation' }, + '0066,001C' => { VR => 'FL', Name => 'CenterOfRotation' }, + '0066,001E' => { VR => 'UL', Name => 'NumberOfVectors' }, + '0066,001F' => { VR => 'US', Name => 'VectorDimensionality' }, + '0066,0020' => { VR => 'FL', Name => 'VectorAccuracy' }, + '0066,0021' => { VR => 'OF', Name => 'VectorCoordinateData' }, + '0066,0023' => { VR => 'OW', Name => 'TrianglePointIndexList' }, + '0066,0024' => { VR => 'OW', Name => 'EdgePointIndexList' }, + '0066,0025' => { VR => 'OW', Name => 'VertexPointIndexList' }, + '0066,0026' => { VR => 'SQ', Name => 'TriangleStripSequence' }, + '0066,0027' => { VR => 'SQ', Name => 'TriangleFanSequence' }, + '0066,0028' => { VR => 'SQ', Name => 'LineSequence' }, + '0066,0029' => { VR => 'OW', Name => 'PrimitivePointIndexList' }, + '0066,002A' => { VR => 'UL', Name => 'SurfaceCount' }, + '0066,002F' => { VR => 'SQ', Name => 'AlgorithmFamilyCodeSequ' }, + '0066,0031' => { VR => 'LO', Name => 'AlgorithmVersion' }, + '0066,0032' => { VR => 'LT', Name => 'AlgorithmParameters' }, + '0066,0034' => { VR => 'SQ', Name => 'FacetSequence' }, + '0066,0036' => { VR => 'LO', Name => 'AlgorithmName' }, + '0070,0001' => { VR => 'SQ', Name => 'GraphicAnnotationSequence' }, + '0070,0002' => { VR => 'CS', Name => 'GraphicLayer' }, + '0070,0003' => { VR => 'CS', Name => 'BoundingBoxAnnotationUnits' }, + '0070,0004' => { VR => 'CS', Name => 'AnchorPointAnnotationUnits' }, + '0070,0005' => { VR => 'CS', Name => 'GraphicAnnotationUnits' }, + '0070,0006' => { VR => 'ST', Name => 'UnformattedTextValue' }, + '0070,0008' => { VR => 'SQ', Name => 'TextObjectSequence' }, + '0070,0009' => { VR => 'SQ', Name => 'GraphicObjectSequence' }, + '0070,0010' => { VR => 'FL', Name => 'BoundingBoxTopLeftHandCorner' }, + '0070,0011' => { VR => 'FL', Name => 'BoundingBoxBottomRightHandCorner' }, + '0070,0012' => { VR => 'CS', Name => 'BoundingBoxTextHorizJustification' }, + '0070,0014' => { VR => 'FL', Name => 'AnchorPoint' }, + '0070,0015' => { VR => 'CS', Name => 'AnchorPointVisibility' }, + '0070,0020' => { VR => 'US', Name => 'GraphicDimensions' }, + '0070,0021' => { VR => 'US', Name => 'NumberOfGraphicPoints' }, + '0070,0022' => { VR => 'FL', Name => 'GraphicData' }, + '0070,0023' => { VR => 'CS', Name => 'GraphicType' }, + '0070,0024' => { VR => 'CS', Name => 'GraphicFilled' }, + '0070,0040' => { VR => 'IS', Name => 'ImageRotationRetired' }, + '0070,0041' => { VR => 'CS', Name => 'ImageHorizontalFlip' }, + '0070,0042' => { VR => 'US', Name => 'ImageRotation' }, + '0070,0050' => { VR => 'US', Name => 'DisplayedAreaTopLeftTrial' }, + '0070,0051' => { VR => 'US', Name => 'DisplayedAreaBottomRightTrial' }, + '0070,0052' => { VR => 'SL', Name => 'DisplayedAreaTopLeft' }, + '0070,0053' => { VR => 'SL', Name => 'DisplayedAreaBottomRight' }, + '0070,005A' => { VR => 'SQ', Name => 'DisplayedAreaSelectionSequence' }, + '0070,0060' => { VR => 'SQ', Name => 'GraphicLayerSequence' }, + '0070,0062' => { VR => 'IS', Name => 'GraphicLayerOrder' }, + '0070,0066' => { VR => 'US', Name => 'GraphicLayerRecDisplayGraysclValue' }, + '0070,0067' => { VR => 'US', Name => 'GraphicLayerRecDisplayRGBValue' }, + '0070,0068' => { VR => 'LO', Name => 'GraphicLayerDescription' }, + '0070,0080' => { VR => 'CS', Name => 'ContentLabel' }, + '0070,0081' => { VR => 'LO', Name => 'ContentDescription' }, + '0070,0082' => { VR => 'DA', Name => 'PresentationCreationDate' }, + '0070,0083' => { VR => 'TM', Name => 'PresentationCreationTime' }, + '0070,0084' => { VR => 'PN', Name => 'ContentCreatorName' }, + '0070,0086' => { VR => 'SQ', Name => 'ContentCreatorIDCodeSequence' }, + '0070,0100' => { VR => 'CS', Name => 'PresentationSizeMode' }, + '0070,0101' => { VR => 'DS', Name => 'PresentationPixelSpacing' }, + '0070,0102' => { VR => 'IS', Name => 'PresentationPixelAspectRatio' }, + '0070,0103' => { VR => 'FL', Name => 'PresentationPixelMagRatio' }, + '0070,0306' => { VR => 'CS', Name => 'ShapeType' }, + '0070,0308' => { VR => 'SQ', Name => 'RegistrationSequence' }, + '0070,0309' => { VR => 'SQ', Name => 'MatrixRegistrationSequence' }, + '0070,030A' => { VR => 'SQ', Name => 'MatrixSequence' }, + '0070,030C' => { VR => 'CS', Name => 'FrameOfRefTransformationMatrixType' }, + '0070,030D' => { VR => 'SQ', Name => 'RegistrationTypeCodeSequence' }, + '0070,030F' => { VR => 'ST', Name => 'FiducialDescription' }, + '0070,0310' => { VR => 'SH', Name => 'FiducialIdentifier' }, + '0070,0311' => { VR => 'SQ', Name => 'FiducialIdentifierCodeSequence' }, + '0070,0312' => { VR => 'FD', Name => 'ContourUncertaintyRadius' }, + '0070,0314' => { VR => 'SQ', Name => 'UsedFiducialsSequence' }, + '0070,0318' => { VR => 'SQ', Name => 'GraphicCoordinatesDataSequence' }, + '0070,031A' => { VR => 'UI', Name => 'FiducialUID' }, + '0070,031C' => { VR => 'SQ', Name => 'FiducialSetSequence' }, + '0070,031E' => { VR => 'SQ', Name => 'FiducialSequence' }, + '0070,0401' => { VR => 'US', Name => 'GraphicLayerRecomDisplayCIELabVal' }, + '0070,0402' => { VR => 'SQ', Name => 'BlendingSequence' }, + '0070,0403' => { VR => 'FL', Name => 'RelativeOpacity' }, + '0070,0404' => { VR => 'SQ', Name => 'ReferencedSpatialRegistrationSeq' }, + '0070,0405' => { VR => 'CS', Name => 'BlendingPosition' }, + '0072,0002' => { VR => 'SH', Name => 'HangingProtocolName' }, + '0072,0004' => { VR => 'LO', Name => 'HangingProtocolDescription' }, + '0072,0006' => { VR => 'CS', Name => 'HangingProtocolLevel' }, + '0072,0008' => { VR => 'LO', Name => 'HangingProtocolCreator' }, + '0072,000A' => { VR => 'DT', Name => 'HangingProtocolCreationDateTime' }, + '0072,000C' => { VR => 'SQ', Name => 'HangingProtocolDefinitionSequence' }, + '0072,000E' => { VR => 'SQ', Name => 'HangingProtocolUserIDCodeSequence' }, + '0072,0010' => { VR => 'LO', Name => 'HangingProtocolUserGroupName' }, + '0072,0012' => { VR => 'SQ', Name => 'SourceHangingProtocolSequence' }, + '0072,0014' => { VR => 'US', Name => 'NumberOfPriorsReferenced' }, + '0072,0020' => { VR => 'SQ', Name => 'ImageSetsSequence' }, + '0072,0022' => { VR => 'SQ', Name => 'ImageSetSelectorSequence' }, + '0072,0024' => { VR => 'CS', Name => 'ImageSetSelectorUsageFlag' }, + '0072,0026' => { VR => 'AT', Name => 'SelectorAttribute' }, + '0072,0028' => { VR => 'US', Name => 'SelectorValueNumber' }, + '0072,0030' => { VR => 'SQ', Name => 'TimeBasedImageSetsSequence' }, + '0072,0032' => { VR => 'US', Name => 'ImageSetNumber' }, + '0072,0034' => { VR => 'CS', Name => 'ImageSetSelectorCategory' }, + '0072,0038' => { VR => 'US', Name => 'RelativeTime' }, + '0072,003A' => { VR => 'CS', Name => 'RelativeTimeUnits' }, + '0072,003C' => { VR => 'SS', Name => 'AbstractPriorValue' }, + '0072,003E' => { VR => 'SQ', Name => 'AbstractPriorCodeSequence' }, + '0072,0040' => { VR => 'LO', Name => 'ImageSetLabel' }, + '0072,0050' => { VR => 'CS', Name => 'SelectorAttributeVR' }, + '0072,0052' => { VR => 'AT', Name => 'SelectorSequencePointer' }, + '0072,0054' => { VR => 'LO', Name => 'SelectorSeqPointerPrivateCreator' }, + '0072,0056' => { VR => 'LO', Name => 'SelectorAttributePrivateCreator' }, + '0072,0060' => { VR => 'AT', Name => 'SelectorATValue' }, + '0072,0062' => { VR => 'CS', Name => 'SelectorCSValue' }, + '0072,0064' => { VR => 'IS', Name => 'SelectorISValue' }, + '0072,0066' => { VR => 'LO', Name => 'SelectorLOValue' }, + '0072,0068' => { VR => 'LT', Name => 'SelectorLTValue' }, + '0072,006A' => { VR => 'PN', Name => 'SelectorPNValue' }, + '0072,006C' => { VR => 'SH', Name => 'SelectorSHValue' }, + '0072,006E' => { VR => 'ST', Name => 'SelectorSTValue' }, + '0072,0070' => { VR => 'UT', Name => 'SelectorUTValue' }, + '0072,0072' => { VR => 'DS', Name => 'SelectorDSValue' }, + '0072,0074' => { VR => 'FD', Name => 'SelectorFDValue' }, + '0072,0076' => { VR => 'FL', Name => 'SelectorFLValue' }, + '0072,0078' => { VR => 'UL', Name => 'SelectorULValue' }, + '0072,007A' => { VR => 'US', Name => 'SelectorUSValue' }, + '0072,007C' => { VR => 'SL', Name => 'SelectorSLValue' }, + '0072,007E' => { VR => 'SS', Name => 'SelectorSSValue' }, + '0072,0080' => { VR => 'SQ', Name => 'SelectorCodeSequenceValue' }, + '0072,0100' => { VR => 'US', Name => 'NumberOfScreens' }, + '0072,0102' => { VR => 'SQ', Name => 'NominalScreenDefinitionSequence' }, + '0072,0104' => { VR => 'US', Name => 'NumberOfVerticalPixels' }, + '0072,0106' => { VR => 'US', Name => 'NumberOfHorizontalPixels' }, + '0072,0108' => { VR => 'FD', Name => 'DisplayEnvironmentSpatialPosition' }, + '0072,010A' => { VR => 'US', Name => 'ScreenMinimumGrayscaleBitDepth' }, + '0072,010C' => { VR => 'US', Name => 'ScreenMinimumColorBitDepth' }, + '0072,010E' => { VR => 'US', Name => 'ApplicationMaximumRepaintTime' }, + '0072,0200' => { VR => 'SQ', Name => 'DisplaySetsSequence' }, + '0072,0202' => { VR => 'US', Name => 'DisplaySetNumber' }, + '0072,0203' => { VR => 'LO', Name => 'DisplaySetLabel' }, + '0072,0204' => { VR => 'US', Name => 'DisplaySetPresentationGroup' }, + '0072,0206' => { VR => 'LO', Name => 'DisplaySetPresentationGroupDescr' }, + '0072,0208' => { VR => 'CS', Name => 'PartialDataDisplayHandling' }, + '0072,0210' => { VR => 'SQ', Name => 'SynchronizedScrollingSequence' }, + '0072,0212' => { VR => 'US', Name => 'DisplaySetScrollingGroup' }, + '0072,0214' => { VR => 'SQ', Name => 'NavigationIndicatorSequence' }, + '0072,0216' => { VR => 'US', Name => 'NavigationDisplaySet' }, + '0072,0218' => { VR => 'US', Name => 'ReferenceDisplaySets' }, + '0072,0300' => { VR => 'SQ', Name => 'ImageBoxesSequence' }, + '0072,0302' => { VR => 'US', Name => 'ImageBoxNumber' }, + '0072,0304' => { VR => 'CS', Name => 'ImageBoxLayoutType' }, + '0072,0306' => { VR => 'US', Name => 'ImageBoxTileHorizontalDimension' }, + '0072,0308' => { VR => 'US', Name => 'ImageBoxTileVerticalDimension' }, + '0072,0310' => { VR => 'CS', Name => 'ImageBoxScrollDirection' }, + '0072,0312' => { VR => 'CS', Name => 'ImageBoxSmallScrollType' }, + '0072,0314' => { VR => 'US', Name => 'ImageBoxSmallScrollAmount' }, + '0072,0316' => { VR => 'CS', Name => 'ImageBoxLargeScrollType' }, + '0072,0318' => { VR => 'US', Name => 'ImageBoxLargeScrollAmount' }, + '0072,0320' => { VR => 'US', Name => 'ImageBoxOverlapPriority' }, + '0072,0330' => { VR => 'FD', Name => 'CineRelativeToRealTime' }, + '0072,0400' => { VR => 'SQ', Name => 'FilterOperationsSequence' }, + '0072,0402' => { VR => 'CS', Name => 'FilterByCategory' }, + '0072,0404' => { VR => 'CS', Name => 'FilterByAttributePresence' }, + '0072,0406' => { VR => 'CS', Name => 'FilterByOperator' }, + '0072,0432' => { VR => 'US', Name => 'SynchronizedImageBoxList' }, + '0072,0434' => { VR => 'CS', Name => 'TypeOfSynchronization' }, + '0072,0500' => { VR => 'CS', Name => 'BlendingOperationType' }, + '0072,0510' => { VR => 'CS', Name => 'ReformattingOperationType' }, + '0072,0512' => { VR => 'FD', Name => 'ReformattingThickness' }, + '0072,0514' => { VR => 'FD', Name => 'ReformattingInterval' }, + '0072,0516' => { VR => 'CS', Name => 'ReformattingOpInitialViewDir' }, + '0072,0520' => { VR => 'CS', Name => 'RenderingType3D' }, + '0072,0600' => { VR => 'SQ', Name => 'SortingOperationsSequence' }, + '0072,0602' => { VR => 'CS', Name => 'SortByCategory' }, + '0072,0604' => { VR => 'CS', Name => 'SortingDirection' }, + '0072,0700' => { VR => 'CS', Name => 'DisplaySetPatientOrientation' }, + '0072,0702' => { VR => 'CS', Name => 'VOIType' }, + '0072,0704' => { VR => 'CS', Name => 'PseudoColorType' }, + '0072,0706' => { VR => 'CS', Name => 'ShowGrayscaleInverted' }, + '0072,0710' => { VR => 'CS', Name => 'ShowImageTrueSizeFlag' }, + '0072,0712' => { VR => 'CS', Name => 'ShowGraphicAnnotationFlag' }, + '0072,0714' => { VR => 'CS', Name => 'ShowPatientDemographicsFlag' }, + '0072,0716' => { VR => 'CS', Name => 'ShowAcquisitionTechniquesFlag' }, + '0072,0717' => { VR => 'CS', Name => 'DisplaySetHorizontalJustification' }, + '0072,0718' => { VR => 'CS', Name => 'DisplaySetVerticalJustification' }, + '0074,1000' => { VR => 'CS', Name => 'UnifiedProcedureStepState' }, + '0074,1002' => { VR => 'SQ', Name => 'UPSProgressInformationSequence' }, + '0074,1004' => { VR => 'DS', Name => 'UnifiedProcedureStepProgress' }, + '0074,1006' => { VR => 'ST', Name => 'UnifiedProcedureStepProgressDescr' }, + '0074,1008' => { VR => 'SQ', Name => 'UnifiedProcedureStepComURISeq' }, + '0074,100a' => { VR => 'ST', Name => 'ContactURI' }, + '0074,100c' => { VR => 'LO', Name => 'ContactDisplayName' }, + '0074,1020' => { VR => 'SQ', Name => 'BeamTaskSequence' }, + '0074,1022' => { VR => 'CS', Name => 'BeamTaskType' }, + '0074,1024' => { VR => 'IS', Name => 'BeamOrderIndex' }, + '0074,1030' => { VR => 'SQ', Name => 'DeliveryVerificationImageSequence' }, + '0074,1032' => { VR => 'CS', Name => 'VerificationImageTiming' }, + '0074,1034' => { VR => 'CS', Name => 'DoubleExposureFlag' }, + '0074,1036' => { VR => 'CS', Name => 'DoubleExposureOrdering' }, + '0074,1038' => { VR => 'DS', Name => 'DoubleExposureMeterset' }, + '0074,103A' => { VR => 'DS', Name => 'DoubleExposureFieldDelta' }, + '0074,1040' => { VR => 'SQ', Name => 'RelatedReferenceRTImageSequence' }, + '0074,1042' => { VR => 'SQ', Name => 'GeneralMachineVerificationSequence' }, + '0074,1044' => { VR => 'SQ', Name => 'ConventionalMachineVerificationSeq' }, + '0074,1046' => { VR => 'SQ', Name => 'IonMachineVerificationSequence' }, + '0074,1048' => { VR => 'SQ', Name => 'FailedAttributesSequence' }, + '0074,104A' => { VR => 'SQ', Name => 'OverriddenAttributesSequence' }, + '0074,104C' => { VR => 'SQ', Name => 'ConventionalControlPointVerifySeq' }, + '0074,104E' => { VR => 'SQ', Name => 'IonControlPointVerificationSeq' }, + '0074,1050' => { VR => 'SQ', Name => 'AttributeOccurrenceSequence' }, + '0074,1052' => { VR => 'AT', Name => 'AttributeOccurrencePointer' }, + '0074,1054' => { VR => 'UL', Name => 'AttributeItemSelector' }, + '0074,1056' => { VR => 'LO', Name => 'AttributeOccurrencePrivateCreator' }, + '0074,1200' => { VR => 'CS', Name => 'ScheduledProcedureStepPriority' }, + '0074,1202' => { VR => 'LO', Name => 'WorklistLabel' }, + '0074,1204' => { VR => 'LO', Name => 'ProcedureStepLabel' }, + '0074,1210' => { VR => 'SQ', Name => 'ScheduledProcessingParametersSeq' }, + '0074,1212' => { VR => 'SQ', Name => 'PerformedProcessingParametersSeq' }, + '0074,1216' => { VR => 'SQ', Name => 'UPSPerformedProcedureSequence' }, + '0074,1220' => { VR => 'SQ', Name => 'RelatedProcedureStepSequence' }, + '0074,1222' => { VR => 'LO', Name => 'ProcedureStepRelationshipType' }, + '0074,1230' => { VR => 'LO', Name => 'DeletionLock' }, + '0074,1234' => { VR => 'AE', Name => 'ReceivingAE' }, + '0074,1236' => { VR => 'AE', Name => 'RequestingAE' }, + '0074,1238' => { VR => 'LT', Name => 'ReasonForCancellation' }, + '0074,1242' => { VR => 'CS', Name => 'SCPStatus' }, + '0074,1244' => { VR => 'CS', Name => 'SubscriptionListStatus' }, + '0074,1246' => { VR => 'CS', Name => 'UPSListStatus' }, + # storage group + '0088,0130' => { VR => 'SH', Name => 'StorageMediaFileSetID' }, + '0088,0140' => { VR => 'UI', Name => 'StorageMediaFileSetUID' }, + '0088,0200' => { VR => 'SQ', Name => 'IconImageSequence' }, + '0088,0904' => { VR => 'LO', Name => 'TopicTitle' }, + '0088,0906' => { VR => 'ST', Name => 'TopicSubject' }, + '0088,0910' => { VR => 'LO', Name => 'TopicAuthor' }, + '0088,0912' => { VR => 'LO', Name => 'TopicKeywords' }, + '0100,0410' => { VR => 'CS', Name => 'SOPInstanceStatus' }, + '0100,0420' => { VR => 'DT', Name => 'SOPAuthorizationDateAndTime' }, + '0100,0424' => { VR => 'LT', Name => 'SOPAuthorizationComment' }, + '0100,0426' => { VR => 'LO', Name => 'AuthorizationEquipmentCertNumber' }, + '0400,0005' => { VR => 'US', Name => 'MACIDNumber' }, + '0400,0010' => { VR => 'UI', Name => 'MACCalculationTransferSyntaxUID' }, + '0400,0015' => { VR => 'CS', Name => 'MACAlgorithm' }, + '0400,0020' => { VR => 'AT', Name => 'DataElementsSigned' }, + '0400,0100' => { VR => 'UI', Name => 'DigitalSignatureUID' }, + '0400,0105' => { VR => 'DT', Name => 'DigitalSignatureDateTime' }, + '0400,0110' => { VR => 'CS', Name => 'CertificateType' }, + '0400,0115' => { VR => 'OB', Name => 'CertificateOfSigner' }, + '0400,0120' => { VR => 'OB', Name => 'Signature' }, + '0400,0305' => { VR => 'CS', Name => 'CertifiedTimestampType' }, + '0400,0310' => { VR => 'OB', Name => 'CertifiedTimestamp' }, + '0400,0401' => { VR => 'SQ', Name => 'DigitalSignaturePurposeCodeSeq' }, + '0400,0402' => { VR => 'SQ', Name => 'ReferencedDigitalSignatureSeq' }, + '0400,0403' => { VR => 'SQ', Name => 'ReferencedSOPInstanceMACSeq' }, + '0400,0404' => { VR => 'OB', Name => 'MAC' }, + '0400,0500' => { VR => 'SQ', Name => 'EncryptedAttributesSequence' }, + '0400,0510' => { VR => 'UI', Name => 'EncryptedContentTransferSyntaxUID' }, + '0400,0520' => { VR => 'OB', Name => 'EncryptedContent' }, + '0400,0550' => { VR => 'SQ', Name => 'ModifiedAttributesSequence' }, + '0400,0561' => { VR => 'SQ', Name => 'OriginalAttributesSequence' }, + '0400,0562' => { VR => 'DT', Name => 'AttributeModificationDateTime' }, + '0400,0563' => { VR => 'LO', Name => 'ModifyingSystem' }, + '0400,0564' => { VR => 'LO', Name => 'SourceOfPreviousValues' }, + '0400,0565' => { VR => 'CS', Name => 'ReasonForTheAttributeModification' }, + '1000,xxx0' => { VR => 'US', Name => 'EscapeTriplet' }, + '1000,xxx1' => { VR => 'US', Name => 'RunLengthTriplet' }, + '1000,xxx2' => { VR => 'US', Name => 'HuffmanTableSize' }, + '1000,xxx3' => { VR => 'US', Name => 'HuffmanTableTriplet' }, + '1000,xxx4' => { VR => 'US', Name => 'ShiftTableSize' }, + '1000,xxx5' => { VR => 'US', Name => 'ShiftTableTriplet' }, + '1010,xxxx' => { VR => 'US', Name => 'ZonalMap' }, + '2000,0010' => { VR => 'IS', Name => 'NumberOfCopies' }, + '2000,001E' => { VR => 'SQ', Name => 'PrinterConfigurationSequence' }, + '2000,0020' => { VR => 'CS', Name => 'PrintPriority' }, + '2000,0030' => { VR => 'CS', Name => 'MediumType' }, + '2000,0040' => { VR => 'CS', Name => 'FilmDestination' }, + '2000,0050' => { VR => 'LO', Name => 'FilmSessionLabel' }, + '2000,0060' => { VR => 'IS', Name => 'MemoryAllocation' }, + '2000,0061' => { VR => 'IS', Name => 'MaximumMemoryAllocation' }, + '2000,0062' => { VR => 'CS', Name => 'ColorImagePrintingFlag' }, + '2000,0063' => { VR => 'CS', Name => 'CollationFlag' }, + '2000,0065' => { VR => 'CS', Name => 'AnnotationFlag' }, + '2000,0067' => { VR => 'CS', Name => 'ImageOverlayFlag' }, + '2000,0069' => { VR => 'CS', Name => 'PresentationLUTFlag' }, + '2000,006A' => { VR => 'CS', Name => 'ImageBoxPresentationLUTFlag' }, + '2000,00A0' => { VR => 'US', Name => 'MemoryBitDepth' }, + '2000,00A1' => { VR => 'US', Name => 'PrintingBitDepth' }, + '2000,00A2' => { VR => 'SQ', Name => 'MediaInstalledSequence' }, + '2000,00A4' => { VR => 'SQ', Name => 'OtherMediaAvailableSequence' }, + '2000,00A8' => { VR => 'SQ', Name => 'SupportedImageDisplayFormatSeq' }, + '2000,0500' => { VR => 'SQ', Name => 'ReferencedFilmBoxSequence' }, + '2000,0510' => { VR => 'SQ', Name => 'ReferencedStoredPrintSequence' }, + # film box group + '2010,0010' => { VR => 'ST', Name => 'ImageDisplayFormat' }, + '2010,0030' => { VR => 'CS', Name => 'AnnotationDisplayFormatID' }, + '2010,0040' => { VR => 'CS', Name => 'FilmOrientation' }, + '2010,0050' => { VR => 'CS', Name => 'FilmSizeID' }, + '2010,0052' => { VR => 'CS', Name => 'PrinterResolutionID' }, + '2010,0054' => { VR => 'CS', Name => 'DefaultPrinterResolutionID' }, + '2010,0060' => { VR => 'CS', Name => 'MagnificationType' }, + '2010,0080' => { VR => 'CS', Name => 'SmoothingType' }, + '2010,00A6' => { VR => 'CS', Name => 'DefaultMagnificationType' }, + '2010,00A7' => { VR => 'CS', Name => 'OtherMagnificationTypesAvailable' }, + '2010,00A8' => { VR => 'CS', Name => 'DefaultSmoothingType' }, + '2010,00A9' => { VR => 'CS', Name => 'OtherSmoothingTypesAvailable' }, + '2010,0100' => { VR => 'CS', Name => 'BorderDensity' }, + '2010,0110' => { VR => 'CS', Name => 'EmptyImageDensity' }, + '2010,0120' => { VR => 'US', Name => 'MinDensity' }, + '2010,0130' => { VR => 'US', Name => 'MaxDensity' }, + '2010,0140' => { VR => 'CS', Name => 'Trim' }, + '2010,0150' => { VR => 'ST', Name => 'ConfigurationInformation' }, + '2010,0152' => { VR => 'LT', Name => 'ConfigurationInformationDescr' }, + '2010,0154' => { VR => 'IS', Name => 'MaximumCollatedFilms' }, + '2010,015E' => { VR => 'US', Name => 'Illumination' }, + '2010,0160' => { VR => 'US', Name => 'ReflectedAmbientLight' }, + '2010,0376' => { VR => 'DS', Name => 'PrinterPixelSpacing' }, + '2010,0500' => { VR => 'SQ', Name => 'ReferencedFilmSessionSequence' }, + '2010,0510' => { VR => 'SQ', Name => 'ReferencedImageBoxSequence' }, + '2010,0520' => { VR => 'SQ', Name => 'ReferencedBasicAnnotationBoxSeq' }, + # image box group + '2020,0010' => { VR => 'US', Name => 'ImageBoxPosition' }, + '2020,0020' => { VR => 'CS', Name => 'Polarity' }, + '2020,0030' => { VR => 'DS', Name => 'RequestedImageSize' }, + '2020,0040' => { VR => 'CS', Name => 'RequestedDecimate-CropBehavior' }, + '2020,0050' => { VR => 'CS', Name => 'RequestedResolutionID' }, + '2020,00A0' => { VR => 'CS', Name => 'RequestedImageSizeFlag' }, + '2020,00A2' => { VR => 'CS', Name => 'DecimateCropResult' }, + '2020,0110' => { VR => 'SQ', Name => 'BasicGrayscaleImageSequence' }, + '2020,0111' => { VR => 'SQ', Name => 'BasicColorImageSequence' }, + '2020,0130' => { VR => 'SQ', Name => 'ReferencedImageOverlayBoxSequence' }, + '2020,0140' => { VR => 'SQ', Name => 'ReferencedVOILUTBoxSequence' }, + # annotation group + '2030,0010' => { VR => 'US', Name => 'AnnotationPosition' }, + '2030,0020' => { VR => 'LO', Name => 'TextString' }, + # overlay box group + '2040,0010' => { VR => 'SQ', Name => 'ReferencedOverlayPlaneSequence' }, + '2040,0011' => { VR => 'US', Name => 'ReferencedOverlayPlaneGroups' }, + '2040,0020' => { VR => 'SQ', Name => 'OverlayPixelDataSequence' }, + '2040,0060' => { VR => 'CS', Name => 'OverlayMagnificationType' }, + '2040,0070' => { VR => 'CS', Name => 'OverlaySmoothingType' }, + '2040,0072' => { VR => 'CS', Name => 'OverlayOrImageMagnification' }, + '2040,0074' => { VR => 'US', Name => 'MagnifyToNumberOfColumns' }, + '2040,0080' => { VR => 'CS', Name => 'OverlayForegroundDensity' }, + '2040,0082' => { VR => 'CS', Name => 'OverlayBackgroundDensity' }, + '2040,0090' => { VR => 'CS', Name => 'OverlayMode' }, + '2040,0100' => { VR => 'CS', Name => 'ThresholdDensity' }, + '2040,0500' => { VR => 'SQ', Name => 'ReferencedImageBoxSequence' }, + '2050,0010' => { VR => 'SQ', Name => 'PresentationLUTSequence' }, + '2050,0020' => { VR => 'CS', Name => 'PresentationLUTShape' }, + '2050,0500' => { VR => 'SQ', Name => 'ReferencedPresentationLUTSequence' }, + '2100,0010' => { VR => 'SH', Name => 'PrintJobID' }, + '2100,0020' => { VR => 'CS', Name => 'ExecutionStatus' }, + '2100,0030' => { VR => 'CS', Name => 'ExecutionStatusInfo' }, + '2100,0040' => { VR => 'DA', Name => 'CreationDate' }, + '2100,0050' => { VR => 'TM', Name => 'CreationTime' }, + '2100,0070' => { VR => 'AE', Name => 'Originator' }, + '2100,0140' => { VR => 'AE', Name => 'DestinationAE' }, + '2100,0160' => { VR => 'SH', Name => 'OwnerID' }, + '2100,0170' => { VR => 'IS', Name => 'NumberOfFilms' }, + '2100,0500' => { VR => 'SQ', Name => 'ReferencedPrintJobSequence' }, + # printer group + '2110,0010' => { VR => 'CS', Name => 'PrinterStatus' }, + '2110,0020' => { VR => 'CS', Name => 'PrinterStatusInfo' }, + '2110,0030' => { VR => 'LO', Name => 'PrinterName' }, + '2110,0099' => { VR => 'SH', Name => 'PrintQueueID' }, + '2120,0010' => { VR => 'CS', Name => 'QueueStatus' }, + # print job group + '2120,0050' => { VR => 'SQ', Name => 'PrintJobDescriptionSequence' }, + '2120,0070' => { VR => 'SQ', Name => 'ReferencedPrintJobSequence' }, + '2130,0010' => { VR => 'SQ', Name => 'PrintManagementCapabilitiesSeq' }, + '2130,0015' => { VR => 'SQ', Name => 'PrinterCharacteristicsSequence' }, + '2130,0030' => { VR => 'SQ', Name => 'FilmBoxContentSequence' }, + '2130,0040' => { VR => 'SQ', Name => 'ImageBoxContentSequence' }, + '2130,0050' => { VR => 'SQ', Name => 'AnnotationContentSequence' }, + '2130,0060' => { VR => 'SQ', Name => 'ImageOverlayBoxContentSequence' }, + '2130,0080' => { VR => 'SQ', Name => 'PresentationLUTContentSequence' }, + '2130,00A0' => { VR => 'SQ', Name => 'ProposedStudySequence' }, + '2130,00C0' => { VR => 'SQ', Name => 'OriginalImageSequence' }, + '2200,0001' => { VR => 'CS', Name => 'LabelFromInfoExtractedFromInstance' }, + '2200,0002' => { VR => 'UT', Name => 'LabelText' }, + '2200,0003' => { VR => 'CS', Name => 'LabelStyleSelection' }, + '2200,0004' => { VR => 'LT', Name => 'MediaDisposition' }, + '2200,0005' => { VR => 'LT', Name => 'BarcodeValue' }, + '2200,0006' => { VR => 'CS', Name => 'BarcodeSymbology' }, + '2200,0007' => { VR => 'CS', Name => 'AllowMediaSplitting' }, + '2200,0008' => { VR => 'CS', Name => 'IncludeNonDICOMObjects' }, + '2200,0009' => { VR => 'CS', Name => 'IncludeDisplayApplication' }, + '2200,000A' => { VR => 'CS', Name => 'SaveCompInstancesAfterMediaCreate' }, + '2200,000B' => { VR => 'US', Name => 'TotalNumberMediaPiecesCreated' }, + '2200,000C' => { VR => 'LO', Name => 'RequestedMediaApplicationProfile' }, + '2200,000D' => { VR => 'SQ', Name => 'ReferencedStorageMediaSequence' }, + '2200,000E' => { VR => 'AT', Name => 'FailureAttributes' }, + '2200,000F' => { VR => 'CS', Name => 'AllowLossyCompression' }, + '2200,0020' => { VR => 'CS', Name => 'RequestPriority' }, + '3002,0002' => { VR => 'SH', Name => 'RTImageLabel' }, + '3002,0003' => { VR => 'LO', Name => 'RTImageName' }, + '3002,0004' => { VR => 'ST', Name => 'RTImageDescription' }, + '3002,000A' => { VR => 'CS', Name => 'ReportedValuesOrigin' }, + '3002,000C' => { VR => 'CS', Name => 'RTImagePlane' }, + '3002,000D' => { VR => 'DS', Name => 'XRayImageReceptorTranslation' }, + '3002,000E' => { VR => 'DS', Name => 'XRayImageReceptorAngle' }, + '3002,0010' => { VR => 'DS', Name => 'RTImageOrientation' }, + '3002,0011' => { VR => 'DS', Name => 'ImagePlanePixelSpacing' }, + '3002,0012' => { VR => 'DS', Name => 'RTImagePosition' }, + '3002,0020' => { VR => 'SH', Name => 'RadiationMachineName' }, + '3002,0022' => { VR => 'DS', Name => 'RadiationMachineSAD' }, + '3002,0024' => { VR => 'DS', Name => 'RadiationMachineSSD' }, + '3002,0026' => { VR => 'DS', Name => 'RTImageSID' }, + '3002,0028' => { VR => 'DS', Name => 'SourceToReferenceObjectDistance' }, + '3002,0029' => { VR => 'IS', Name => 'FractionNumber' }, + '3002,0030' => { VR => 'SQ', Name => 'ExposureSequence' }, + '3002,0032' => { VR => 'DS', Name => 'MetersetExposure' }, + '3002,0034' => { VR => 'DS', Name => 'DiaphragmPosition' }, + '3002,0040' => { VR => 'SQ', Name => 'FluenceMapSequence' }, + '3002,0041' => { VR => 'CS', Name => 'FluenceDataSource' }, + '3002,0042' => { VR => 'DS', Name => 'FluenceDataScale' }, + '3002,0051' => { VR => 'CS', Name => 'FluenceMode' }, + '3002,0052' => { VR => 'SH', Name => 'FluenceModeID' }, + '3004,0001' => { VR => 'CS', Name => 'DVHType' }, + '3004,0002' => { VR => 'CS', Name => 'DoseUnits' }, + '3004,0004' => { VR => 'CS', Name => 'DoseType' }, + '3004,0006' => { VR => 'LO', Name => 'DoseComment' }, + '3004,0008' => { VR => 'DS', Name => 'NormalizationPoint' }, + '3004,000A' => { VR => 'CS', Name => 'DoseSummationType' }, + '3004,000C' => { VR => 'DS', Name => 'GridFrameOffsetVector' }, + '3004,000E' => { VR => 'DS', Name => 'DoseGridScaling' }, + '3004,0010' => { VR => 'SQ', Name => 'RTDoseROISequence' }, + '3004,0012' => { VR => 'DS', Name => 'DoseValue' }, + '3004,0014' => { VR => 'CS', Name => 'TissueHeterogeneityCorrection' }, + '3004,0040' => { VR => 'DS', Name => 'DVHNormalizationPoint' }, + '3004,0042' => { VR => 'DS', Name => 'DVHNormalizationDoseValue' }, + '3004,0050' => { VR => 'SQ', Name => 'DVHSequence' }, + '3004,0052' => { VR => 'DS', Name => 'DVHDoseScaling' }, + '3004,0054' => { VR => 'CS', Name => 'DVHVolumeUnits' }, + '3004,0056' => { VR => 'IS', Name => 'DVHNumberOfBins' }, + '3004,0058' => { VR => 'DS', Name => 'DVHData' }, + '3004,0060' => { VR => 'SQ', Name => 'DVHReferencedROISequence' }, + '3004,0062' => { VR => 'CS', Name => 'DVHROIContributionType' }, + '3004,0070' => { VR => 'DS', Name => 'DVHMinimumDose' }, + '3004,0072' => { VR => 'DS', Name => 'DVHMaximumDose' }, + '3004,0074' => { VR => 'DS', Name => 'DVHMeanDose' }, + '3006,0002' => { VR => 'SH', Name => 'StructureSetLabel' }, + '3006,0004' => { VR => 'LO', Name => 'StructureSetName' }, + '3006,0006' => { VR => 'ST', Name => 'StructureSetDescription' }, + '3006,0008' => { VR => 'DA', Name => 'StructureSetDate' }, + '3006,0009' => { VR => 'TM', Name => 'StructureSetTime' }, + '3006,0010' => { VR => 'SQ', Name => 'ReferencedFrameOfReferenceSequence' }, + '3006,0012' => { VR => 'SQ', Name => 'RTReferencedStudySequence' }, + '3006,0014' => { VR => 'SQ', Name => 'RTReferencedSeriesSequence' }, + '3006,0016' => { VR => 'SQ', Name => 'ContourImageSequence' }, + '3006,0020' => { VR => 'SQ', Name => 'StructureSetROISequence' }, + '3006,0022' => { VR => 'IS', Name => 'ROINumber' }, + '3006,0024' => { VR => 'UI', Name => 'ReferencedFrameOfReferenceUID' }, + '3006,0026' => { VR => 'LO', Name => 'ROIName' }, + '3006,0028' => { VR => 'ST', Name => 'ROIDescription' }, + '3006,002A' => { VR => 'IS', Name => 'ROIDisplayColor' }, + '3006,002C' => { VR => 'DS', Name => 'ROIVolume' }, + '3006,0030' => { VR => 'SQ', Name => 'RTRelatedROISequence' }, + '3006,0033' => { VR => 'CS', Name => 'RTROIRelationship' }, + '3006,0036' => { VR => 'CS', Name => 'ROIGenerationAlgorithm' }, + '3006,0038' => { VR => 'LO', Name => 'ROIGenerationDescription' }, + '3006,0039' => { VR => 'SQ', Name => 'ROIContourSequence' }, + '3006,0040' => { VR => 'SQ', Name => 'ContourSequence' }, + '3006,0042' => { VR => 'CS', Name => 'ContourGeometricType' }, + '3006,0044' => { VR => 'DS', Name => 'ContourSlabThickness' }, + '3006,0045' => { VR => 'DS', Name => 'ContourOffsetVector' }, + '3006,0046' => { VR => 'IS', Name => 'NumberOfContourPoints' }, + '3006,0048' => { VR => 'IS', Name => 'ContourNumber' }, + '3006,0049' => { VR => 'IS', Name => 'AttachedContours' }, + '3006,0050' => { VR => 'DS', Name => 'ContourData' }, + '3006,0080' => { VR => 'SQ', Name => 'RTROIObservationsSequence' }, + '3006,0082' => { VR => 'IS', Name => 'ObservationNumber' }, + '3006,0084' => { VR => 'IS', Name => 'ReferencedROINumber' }, + '3006,0085' => { VR => 'SH', Name => 'ROIObservationLabel' }, + '3006,0086' => { VR => 'SQ', Name => 'RTROIIdentificationCodeSequence' }, + '3006,0088' => { VR => 'ST', Name => 'ROIObservationDescription' }, + '3006,00A0' => { VR => 'SQ', Name => 'RelatedRTROIObservationsSequence' }, + '3006,00A4' => { VR => 'CS', Name => 'RTROIInterpretedType' }, + '3006,00A6' => { VR => 'PN', Name => 'ROIInterpreter' }, + '3006,00B0' => { VR => 'SQ', Name => 'ROIPhysicalPropertiesSequence' }, + '3006,00B2' => { VR => 'CS', Name => 'ROIPhysicalProperty' }, + '3006,00B4' => { VR => 'DS', Name => 'ROIPhysicalPropertyValue' }, + '3006,00B6' => { VR => 'SQ', Name => 'ROIElementalCompositionSequence' }, + '3006,00B7' => { VR => 'US', Name => 'ROIElementalCompAtomicNumber' }, + '3006,00B8' => { VR => 'FL', Name => 'ROIElementalCompAtomicMassFraction' }, + '3006,00C0' => { VR => 'SQ', Name => 'FrameOfReferenceRelationshipSeq' }, + '3006,00C2' => { VR => 'UI', Name => 'RelatedFrameOfReferenceUID' }, + '3006,00C4' => { VR => 'CS', Name => 'FrameOfReferenceTransformType' }, + '3006,00C6' => { VR => 'DS', Name => 'FrameOfReferenceTransformMatrix' }, + '3006,00C8' => { VR => 'LO', Name => 'FrameOfReferenceTransformComment' }, + '3008,0010' => { VR => 'SQ', Name => 'MeasuredDoseReferenceSequence' }, + '3008,0012' => { VR => 'ST', Name => 'MeasuredDoseDescription' }, + '3008,0014' => { VR => 'CS', Name => 'MeasuredDoseType' }, + '3008,0016' => { VR => 'DS', Name => 'MeasuredDoseValue' }, + '3008,0020' => { VR => 'SQ', Name => 'TreatmentSessionBeamSequence' }, + '3008,0021' => { VR => 'SQ', Name => 'TreatmentSessionIonBeamSequence' }, + '3008,0022' => { VR => 'IS', Name => 'CurrentFractionNumber' }, + '3008,0024' => { VR => 'DA', Name => 'TreatmentControlPointDate' }, + '3008,0025' => { VR => 'TM', Name => 'TreatmentControlPointTime' }, + '3008,002A' => { VR => 'CS', Name => 'TreatmentTerminationStatus' }, + '3008,002B' => { VR => 'SH', Name => 'TreatmentTerminationCode' }, + '3008,002C' => { VR => 'CS', Name => 'TreatmentVerificationStatus' }, + '3008,0030' => { VR => 'SQ', Name => 'ReferencedTreatmentRecordSequence' }, + '3008,0032' => { VR => 'DS', Name => 'SpecifiedPrimaryMeterset' }, + '3008,0033' => { VR => 'DS', Name => 'SpecifiedSecondaryMeterset' }, + '3008,0036' => { VR => 'DS', Name => 'DeliveredPrimaryMeterset' }, + '3008,0037' => { VR => 'DS', Name => 'DeliveredSecondaryMeterset' }, + '3008,003A' => { VR => 'DS', Name => 'SpecifiedTreatmentTime' }, + '3008,003B' => { VR => 'DS', Name => 'DeliveredTreatmentTime' }, + '3008,0040' => { VR => 'SQ', Name => 'ControlPointDeliverySequence' }, + '3008,0041' => { VR => 'SQ', Name => 'IonControlPointDeliverySequence' }, + '3008,0042' => { VR => 'DS', Name => 'SpecifiedMeterset' }, + '3008,0044' => { VR => 'DS', Name => 'DeliveredMeterset' }, + '3008,0045' => { VR => 'FL', Name => 'MetersetRateSet' }, + '3008,0046' => { VR => 'FL', Name => 'MetersetRateDelivered' }, + '3008,0047' => { VR => 'FL', Name => 'ScanSpotMetersetsDelivered' }, + '3008,0048' => { VR => 'DS', Name => 'DoseRateDelivered' }, + '3008,0050' => { VR => 'SQ', Name => 'TreatmentSummaryCalcDoseRefSeq' }, + '3008,0052' => { VR => 'DS', Name => 'CumulativeDoseToDoseReference' }, + '3008,0054' => { VR => 'DA', Name => 'FirstTreatmentDate' }, + '3008,0056' => { VR => 'DA', Name => 'MostRecentTreatmentDate' }, + '3008,005A' => { VR => 'IS', Name => 'NumberOfFractionsDelivered' }, + '3008,0060' => { VR => 'SQ', Name => 'OverrideSequence' }, + '3008,0061' => { VR => 'AT', Name => 'ParameterSequencePointer' }, + '3008,0062' => { VR => 'AT', Name => 'OverrideParameterPointer' }, + '3008,0063' => { VR => 'IS', Name => 'ParameterItemIndex' }, + '3008,0064' => { VR => 'IS', Name => 'MeasuredDoseReferenceNumber' }, + '3008,0065' => { VR => 'AT', Name => 'ParameterPointer' }, + '3008,0066' => { VR => 'ST', Name => 'OverrideReason' }, + '3008,0068' => { VR => 'SQ', Name => 'CorrectedParameterSequence' }, + '3008,006A' => { VR => 'FL', Name => 'CorrectionValue' }, + '3008,0070' => { VR => 'SQ', Name => 'CalculatedDoseReferenceSequence' }, + '3008,0072' => { VR => 'IS', Name => 'CalculatedDoseReferenceNumber' }, + '3008,0074' => { VR => 'ST', Name => 'CalculatedDoseReferenceDescription' }, + '3008,0076' => { VR => 'DS', Name => 'CalculatedDoseReferenceDoseValue' }, + '3008,0078' => { VR => 'DS', Name => 'StartMeterset' }, + '3008,007A' => { VR => 'DS', Name => 'EndMeterset' }, + '3008,0080' => { VR => 'SQ', Name => 'ReferencedMeasuredDoseReferenceSeq' }, + '3008,0082' => { VR => 'IS', Name => 'ReferencedMeasuredDoseReferenceNum' }, + '3008,0090' => { VR => 'SQ', Name => 'ReferencedCalculatedDoseRefSeq' }, + '3008,0092' => { VR => 'IS', Name => 'ReferencedCalculatedDoseRefNumber' }, + '3008,00A0' => { VR => 'SQ', Name => 'BeamLimitingDeviceLeafPairsSeq' }, + '3008,00B0' => { VR => 'SQ', Name => 'RecordedWedgeSequence' }, + '3008,00C0' => { VR => 'SQ', Name => 'RecordedCompensatorSequence' }, + '3008,00D0' => { VR => 'SQ', Name => 'RecordedBlockSequence' }, + '3008,00E0' => { VR => 'SQ', Name => 'TreatmentSummaryMeasuredDoseRefSeq' }, + '3008,00F0' => { VR => 'SQ', Name => 'RecordedSnoutSequence' }, + '3008,00F2' => { VR => 'SQ', Name => 'RecordedRangeShifterSequence' }, + '3008,00F4' => { VR => 'SQ', Name => 'RecordedLateralSpreadingDeviceSeq' }, + '3008,00F6' => { VR => 'SQ', Name => 'RecordedRangeModulatorSequence' }, + '3008,0100' => { VR => 'SQ', Name => 'RecordedSourceSequence' }, + '3008,0105' => { VR => 'LO', Name => 'SourceSerialNumber' }, + '3008,0110' => { VR => 'SQ', Name => 'TreatmentSessionAppSetupSeq' }, + '3008,0116' => { VR => 'CS', Name => 'ApplicationSetupCheck' }, + '3008,0120' => { VR => 'SQ', Name => 'RecordedBrachyAccessoryDeviceSeq' }, + '3008,0122' => { VR => 'IS', Name => 'ReferencedBrachyAccessoryDeviceNum' }, + '3008,0130' => { VR => 'SQ', Name => 'RecordedChannelSequence' }, + '3008,0132' => { VR => 'DS', Name => 'SpecifiedChannelTotalTime' }, + '3008,0134' => { VR => 'DS', Name => 'DeliveredChannelTotalTime' }, + '3008,0136' => { VR => 'IS', Name => 'SpecifiedNumberOfPulses' }, + '3008,0138' => { VR => 'IS', Name => 'DeliveredNumberOfPulses' }, + '3008,013A' => { VR => 'DS', Name => 'SpecifiedPulseRepetitionInterval' }, + '3008,013C' => { VR => 'DS', Name => 'DeliveredPulseRepetitionInterval' }, + '3008,0140' => { VR => 'SQ', Name => 'RecordedSourceApplicatorSequence' }, + '3008,0142' => { VR => 'IS', Name => 'ReferencedSourceApplicatorNumber' }, + '3008,0150' => { VR => 'SQ', Name => 'RecordedChannelShieldSequence' }, + '3008,0152' => { VR => 'IS', Name => 'ReferencedChannelShieldNumber' }, + '3008,0160' => { VR => 'SQ', Name => 'BrachyControlPointDeliveredSeq' }, + '3008,0162' => { VR => 'DA', Name => 'SafePositionExitDate' }, + '3008,0164' => { VR => 'TM', Name => 'SafePositionExitTime' }, + '3008,0166' => { VR => 'DA', Name => 'SafePositionReturnDate' }, + '3008,0168' => { VR => 'TM', Name => 'SafePositionReturnTime' }, + '3008,0200' => { VR => 'CS', Name => 'CurrentTreatmentStatus' }, + '3008,0202' => { VR => 'ST', Name => 'TreatmentStatusComment' }, + '3008,0220' => { VR => 'SQ', Name => 'FractionGroupSummarySequence' }, + '3008,0223' => { VR => 'IS', Name => 'ReferencedFractionNumber' }, + '3008,0224' => { VR => 'CS', Name => 'FractionGroupType' }, + '3008,0230' => { VR => 'CS', Name => 'BeamStopperPosition' }, + '3008,0240' => { VR => 'SQ', Name => 'FractionStatusSummarySequence' }, + '3008,0250' => { VR => 'DA', Name => 'TreatmentDate' }, + '3008,0251' => { VR => 'TM', Name => 'TreatmentTime' }, + '300A,0002' => { VR => 'SH', Name => 'RTPlanLabel' }, + '300A,0003' => { VR => 'LO', Name => 'RTPlanName' }, + '300A,0004' => { VR => 'ST', Name => 'RTPlanDescription' }, + '300A,0006' => { VR => 'DA', Name => 'RTPlanDate' }, + '300A,0007' => { VR => 'TM', Name => 'RTPlanTime' }, + '300A,0009' => { VR => 'LO', Name => 'TreatmentProtocols' }, + '300A,000A' => { VR => 'CS', Name => 'PlanIntent' }, + '300A,000B' => { VR => 'LO', Name => 'TreatmentSites' }, + '300A,000C' => { VR => 'CS', Name => 'RTPlanGeometry' }, + '300A,000E' => { VR => 'ST', Name => 'PrescriptionDescription' }, + '300A,0010' => { VR => 'SQ', Name => 'DoseReferenceSequence' }, + '300A,0012' => { VR => 'IS', Name => 'DoseReferenceNumber' }, + '300A,0013' => { VR => 'UI', Name => 'DoseReferenceUID' }, + '300A,0014' => { VR => 'CS', Name => 'DoseReferenceStructureType' }, + '300A,0015' => { VR => 'CS', Name => 'NominalBeamEnergyUnit' }, + '300A,0016' => { VR => 'LO', Name => 'DoseReferenceDescription' }, + '300A,0018' => { VR => 'DS', Name => 'DoseReferencePointCoordinates' }, + '300A,001A' => { VR => 'DS', Name => 'NominalPriorDose' }, + '300A,0020' => { VR => 'CS', Name => 'DoseReferenceType' }, + '300A,0021' => { VR => 'DS', Name => 'ConstraintWeight' }, + '300A,0022' => { VR => 'DS', Name => 'DeliveryWarningDose' }, + '300A,0023' => { VR => 'DS', Name => 'DeliveryMaximumDose' }, + '300A,0025' => { VR => 'DS', Name => 'TargetMinimumDose' }, + '300A,0026' => { VR => 'DS', Name => 'TargetPrescriptionDose' }, + '300A,0027' => { VR => 'DS', Name => 'TargetMaximumDose' }, + '300A,0028' => { VR => 'DS', Name => 'TargetUnderdoseVolumeFraction' }, + '300A,002A' => { VR => 'DS', Name => 'OrganAtRiskFullVolumeDose' }, + '300A,002B' => { VR => 'DS', Name => 'OrganAtRiskLimitDose' }, + '300A,002C' => { VR => 'DS', Name => 'OrganAtRiskMaximumDose' }, + '300A,002D' => { VR => 'DS', Name => 'OrganAtRiskOverdoseVolumeFraction' }, + '300A,0040' => { VR => 'SQ', Name => 'ToleranceTableSequence' }, + '300A,0042' => { VR => 'IS', Name => 'ToleranceTableNumber' }, + '300A,0043' => { VR => 'SH', Name => 'ToleranceTableLabel' }, + '300A,0044' => { VR => 'DS', Name => 'GantryAngleTolerance' }, + '300A,0046' => { VR => 'DS', Name => 'BeamLimitingDeviceAngleTolerance' }, + '300A,0048' => { VR => 'SQ', Name => 'BeamLimitingDeviceToleranceSeq' }, + '300A,004A' => { VR => 'DS', Name => 'BeamLimitingDevicePositionTol' }, + '300A,004B' => { VR => 'FL', Name => 'SnoutPositionTolerance' }, + '300A,004C' => { VR => 'DS', Name => 'PatientSupportAngleTolerance' }, + '300A,004E' => { VR => 'DS', Name => 'TableTopEccentricAngleTolerance' }, + '300A,004F' => { VR => 'FL', Name => 'TableTopPitchAngleTolerance' }, + '300A,0050' => { VR => 'FL', Name => 'TableTopRollAngleTolerance' }, + '300A,0051' => { VR => 'DS', Name => 'TableTopVerticalPositionTolerance' }, + '300A,0052' => { VR => 'DS', Name => 'TableTopLongitudinalPositionTol' }, + '300A,0053' => { VR => 'DS', Name => 'TableTopLateralPositionTolerance' }, + '300A,0055' => { VR => 'CS', Name => 'RTPlanRelationship' }, + '300A,0070' => { VR => 'SQ', Name => 'FractionGroupSequence' }, + '300A,0071' => { VR => 'IS', Name => 'FractionGroupNumber' }, + '300A,0072' => { VR => 'LO', Name => 'FractionGroupDescription' }, + '300A,0078' => { VR => 'IS', Name => 'NumberOfFractionsPlanned' }, + '300A,0079' => { VR => 'IS', Name => 'NumberFractionPatternDigitsPerDay' }, + '300A,007A' => { VR => 'IS', Name => 'RepeatFractionCycleLength' }, + '300A,007B' => { VR => 'LT', Name => 'FractionPattern' }, + '300A,0080' => { VR => 'IS', Name => 'NumberOfBeams' }, + '300A,0082' => { VR => 'DS', Name => 'BeamDoseSpecificationPoint' }, + '300A,0084' => { VR => 'DS', Name => 'BeamDose' }, + '300A,0086' => { VR => 'DS', Name => 'BeamMeterset' }, + '300A,0088' => { VR => 'FL', Name => 'BeamDosePointDepth' }, + '300A,0089' => { VR => 'FL', Name => 'BeamDosePointEquivalentDepth' }, + '300A,008A' => { VR => 'FL', Name => 'BeamDosePointSSD' }, + '300A,00A0' => { VR => 'IS', Name => 'NumberOfBrachyApplicationSetups' }, + '300A,00A2' => { VR => 'DS', Name => 'BrachyAppSetupDoseSpecPoint' }, + '300A,00A4' => { VR => 'DS', Name => 'BrachyApplicationSetupDose' }, + '300A,00B0' => { VR => 'SQ', Name => 'BeamSequence' }, + '300A,00B2' => { VR => 'SH', Name => 'TreatmentMachineName' }, + '300A,00B3' => { VR => 'CS', Name => 'PrimaryDosimeterUnit' }, + '300A,00B4' => { VR => 'DS', Name => 'SourceAxisDistance' }, + '300A,00B6' => { VR => 'SQ', Name => 'BeamLimitingDeviceSequence' }, + '300A,00B8' => { VR => 'CS', Name => 'RTBeamLimitingDeviceType' }, + '300A,00BA' => { VR => 'DS', Name => 'SourceToBeamLimitingDeviceDistance' }, + '300A,00BB' => { VR => 'FL', Name => 'IsocenterToBeamLimitingDeviceDist' }, + '300A,00BC' => { VR => 'IS', Name => 'NumberOfLeafJawPairs' }, + '300A,00BE' => { VR => 'DS', Name => 'LeafPositionBoundaries' }, + '300A,00C0' => { VR => 'IS', Name => 'BeamNumber' }, + '300A,00C2' => { VR => 'LO', Name => 'BeamName' }, + '300A,00C3' => { VR => 'ST', Name => 'BeamDescription' }, + '300A,00C4' => { VR => 'CS', Name => 'BeamType' }, + '300A,00C6' => { VR => 'CS', Name => 'RadiationType' }, + '300A,00C7' => { VR => 'CS', Name => 'HighDoseTechniqueType' }, + '300A,00C8' => { VR => 'IS', Name => 'ReferenceImageNumber' }, + '300A,00CA' => { VR => 'SQ', Name => 'PlannedVerificationImageSequence' }, + '300A,00CC' => { VR => 'LO', Name => 'ImagingDeviceSpecificAcqParams' }, + '300A,00CE' => { VR => 'CS', Name => 'TreatmentDeliveryType' }, + '300A,00D0' => { VR => 'IS', Name => 'NumberOfWedges' }, + '300A,00D1' => { VR => 'SQ', Name => 'WedgeSequence' }, + '300A,00D2' => { VR => 'IS', Name => 'WedgeNumber' }, + '300A,00D3' => { VR => 'CS', Name => 'WedgeType' }, + '300A,00D4' => { VR => 'SH', Name => 'WedgeID' }, + '300A,00D5' => { VR => 'IS', Name => 'WedgeAngle' }, + '300A,00D6' => { VR => 'DS', Name => 'WedgeFactor' }, + '300A,00D7' => { VR => 'FL', Name => 'TotalWedgeTrayWaterEquivThickness' }, + '300A,00D8' => { VR => 'DS', Name => 'WedgeOrientation' }, + '300A,00D9' => { VR => 'FL', Name => 'IsocenterToWedgeTrayDistance' }, + '300A,00DA' => { VR => 'DS', Name => 'SourceToWedgeTrayDistance' }, + '300A,00DB' => { VR => 'FL', Name => 'WedgeThinEdgePosition' }, + '300A,00DC' => { VR => 'SH', Name => 'BolusID' }, + '300A,00DD' => { VR => 'ST', Name => 'BolusDescription' }, + '300A,00E0' => { VR => 'IS', Name => 'NumberOfCompensators' }, + '300A,00E1' => { VR => 'SH', Name => 'MaterialID' }, + '300A,00E2' => { VR => 'DS', Name => 'TotalCompensatorTrayFactor' }, + '300A,00E3' => { VR => 'SQ', Name => 'CompensatorSequence' }, + '300A,00E4' => { VR => 'IS', Name => 'CompensatorNumber' }, + '300A,00E5' => { VR => 'SH', Name => 'CompensatorID' }, + '300A,00E6' => { VR => 'DS', Name => 'SourceToCompensatorTrayDistance' }, + '300A,00E7' => { VR => 'IS', Name => 'CompensatorRows' }, + '300A,00E8' => { VR => 'IS', Name => 'CompensatorColumns' }, + '300A,00E9' => { VR => 'DS', Name => 'CompensatorPixelSpacing' }, + '300A,00EA' => { VR => 'DS', Name => 'CompensatorPosition' }, + '300A,00EB' => { VR => 'DS', Name => 'CompensatorTransmissionData' }, + '300A,00EC' => { VR => 'DS', Name => 'CompensatorThicknessData' }, + '300A,00ED' => { VR => 'IS', Name => 'NumberOfBoli' }, + '300A,00EE' => { VR => 'CS', Name => 'CompensatorType' }, + '300A,00F0' => { VR => 'IS', Name => 'NumberOfBlocks' }, + '300A,00F2' => { VR => 'DS', Name => 'TotalBlockTrayFactor' }, + '300A,00F3' => { VR => 'FL', Name => 'TotalBlockTrayWaterEquivThickness' }, + '300A,00F4' => { VR => 'SQ', Name => 'BlockSequence' }, + '300A,00F5' => { VR => 'SH', Name => 'BlockTrayID' }, + '300A,00F6' => { VR => 'DS', Name => 'SourceToBlockTrayDistance' }, + '300A,00F7' => { VR => 'FL', Name => 'IsocenterToBlockTrayDistance' }, + '300A,00F8' => { VR => 'CS', Name => 'BlockType' }, + '300A,00F9' => { VR => 'LO', Name => 'AccessoryCode' }, + '300A,00FA' => { VR => 'CS', Name => 'BlockDivergence' }, + '300A,00FB' => { VR => 'CS', Name => 'BlockMountingPosition' }, + '300A,00FC' => { VR => 'IS', Name => 'BlockNumber' }, + '300A,00FE' => { VR => 'LO', Name => 'BlockName' }, + '300A,0100' => { VR => 'DS', Name => 'BlockThickness' }, + '300A,0102' => { VR => 'DS', Name => 'BlockTransmission' }, + '300A,0104' => { VR => 'IS', Name => 'BlockNumberOfPoints' }, + '300A,0106' => { VR => 'DS', Name => 'BlockData' }, + '300A,0107' => { VR => 'SQ', Name => 'ApplicatorSequence' }, + '300A,0108' => { VR => 'SH', Name => 'ApplicatorID' }, + '300A,0109' => { VR => 'CS', Name => 'ApplicatorType' }, + '300A,010A' => { VR => 'LO', Name => 'ApplicatorDescription' }, + '300A,010C' => { VR => 'DS', Name => 'CumulativeDoseReferenceCoefficient' }, + '300A,010E' => { VR => 'DS', Name => 'FinalCumulativeMetersetWeight' }, + '300A,0110' => { VR => 'IS', Name => 'NumberOfControlPoints' }, + '300A,0111' => { VR => 'SQ', Name => 'ControlPointSequence' }, + '300A,0112' => { VR => 'IS', Name => 'ControlPointIndex' }, + '300A,0114' => { VR => 'DS', Name => 'NominalBeamEnergy' }, + '300A,0115' => { VR => 'DS', Name => 'DoseRateSet' }, + '300A,0116' => { VR => 'SQ', Name => 'WedgePositionSequence' }, + '300A,0118' => { VR => 'CS', Name => 'WedgePosition' }, + '300A,011A' => { VR => 'SQ', Name => 'BeamLimitingDevicePositionSequence' }, + '300A,011C' => { VR => 'DS', Name => 'LeafJawPositions' }, + '300A,011E' => { VR => 'DS', Name => 'GantryAngle' }, + '300A,011F' => { VR => 'CS', Name => 'GantryRotationDirection' }, + '300A,0120' => { VR => 'DS', Name => 'BeamLimitingDeviceAngle' }, + '300A,0121' => { VR => 'CS', Name => 'BeamLimitingDeviceRotateDirection' }, + '300A,0122' => { VR => 'DS', Name => 'PatientSupportAngle' }, + '300A,0123' => { VR => 'CS', Name => 'PatientSupportRotationDirection' }, + '300A,0124' => { VR => 'DS', Name => 'TableTopEccentricAxisDistance' }, + '300A,0125' => { VR => 'DS', Name => 'TableTopEccentricAngle' }, + '300A,0126' => { VR => 'CS', Name => 'TableTopEccentricRotateDirection' }, + '300A,0128' => { VR => 'DS', Name => 'TableTopVerticalPosition' }, + '300A,0129' => { VR => 'DS', Name => 'TableTopLongitudinalPosition' }, + '300A,012A' => { VR => 'DS', Name => 'TableTopLateralPosition' }, + '300A,012C' => { VR => 'DS', Name => 'IsocenterPosition' }, + '300A,012E' => { VR => 'DS', Name => 'SurfaceEntryPoint' }, + '300A,0130' => { VR => 'DS', Name => 'SourceToSurfaceDistance' }, + '300A,0134' => { VR => 'DS', Name => 'CumulativeMetersetWeight' }, + '300A,0140' => { VR => 'FL', Name => 'TableTopPitchAngle' }, + '300A,0142' => { VR => 'CS', Name => 'TableTopPitchRotationDirection' }, + '300A,0144' => { VR => 'FL', Name => 'TableTopRollAngle' }, + '300A,0146' => { VR => 'CS', Name => 'TableTopRollRotationDirection' }, + '300A,0148' => { VR => 'FL', Name => 'HeadFixationAngle' }, + '300A,014A' => { VR => 'FL', Name => 'GantryPitchAngle' }, + '300A,014C' => { VR => 'CS', Name => 'GantryPitchRotationDirection' }, + '300A,014E' => { VR => 'FL', Name => 'GantryPitchAngleTolerance' }, + '300A,0180' => { VR => 'SQ', Name => 'PatientSetupSequence' }, + '300A,0182' => { VR => 'IS', Name => 'PatientSetupNumber' }, + '300A,0183' => { VR => 'LO', Name => 'PatientSetupLabel' }, + '300A,0184' => { VR => 'LO', Name => 'PatientAdditionalPosition' }, + '300A,0190' => { VR => 'SQ', Name => 'FixationDeviceSequence' }, + '300A,0192' => { VR => 'CS', Name => 'FixationDeviceType' }, + '300A,0194' => { VR => 'SH', Name => 'FixationDeviceLabel' }, + '300A,0196' => { VR => 'ST', Name => 'FixationDeviceDescription' }, + '300A,0198' => { VR => 'SH', Name => 'FixationDevicePosition' }, + '300A,0199' => { VR => 'FL', Name => 'FixationDevicePitchAngle' }, + '300A,019A' => { VR => 'FL', Name => 'FixationDeviceRollAngle' }, + '300A,01A0' => { VR => 'SQ', Name => 'ShieldingDeviceSequence' }, + '300A,01A2' => { VR => 'CS', Name => 'ShieldingDeviceType' }, + '300A,01A4' => { VR => 'SH', Name => 'ShieldingDeviceLabel' }, + '300A,01A6' => { VR => 'ST', Name => 'ShieldingDeviceDescription' }, + '300A,01A8' => { VR => 'SH', Name => 'ShieldingDevicePosition' }, + '300A,01B0' => { VR => 'CS', Name => 'SetupTechnique' }, + '300A,01B2' => { VR => 'ST', Name => 'SetupTechniqueDescription' }, + '300A,01B4' => { VR => 'SQ', Name => 'SetupDeviceSequence' }, + '300A,01B6' => { VR => 'CS', Name => 'SetupDeviceType' }, + '300A,01B8' => { VR => 'SH', Name => 'SetupDeviceLabel' }, + '300A,01BA' => { VR => 'ST', Name => 'SetupDeviceDescription' }, + '300A,01BC' => { VR => 'DS', Name => 'SetupDeviceParameter' }, + '300A,01D0' => { VR => 'ST', Name => 'SetupReferenceDescription' }, + '300A,01D2' => { VR => 'DS', Name => 'TableTopVerticalSetupDisplacement' }, + '300A,01D4' => { VR => 'DS', Name => 'TableTopLongitudinalSetupDisplace' }, + '300A,01D6' => { VR => 'DS', Name => 'TableTopLateralSetupDisplacement' }, + '300A,0200' => { VR => 'CS', Name => 'BrachyTreatmentTechnique' }, + '300A,0202' => { VR => 'CS', Name => 'BrachyTreatmentType' }, + '300A,0206' => { VR => 'SQ', Name => 'TreatmentMachineSequence' }, + '300A,0210' => { VR => 'SQ', Name => 'SourceSequence' }, + '300A,0212' => { VR => 'IS', Name => 'SourceNumber' }, + '300A,0214' => { VR => 'CS', Name => 'SourceType' }, + '300A,0216' => { VR => 'LO', Name => 'SourceManufacturer' }, + '300A,0218' => { VR => 'DS', Name => 'ActiveSourceDiameter' }, + '300A,021A' => { VR => 'DS', Name => 'ActiveSourceLength' }, + '300A,0222' => { VR => 'DS', Name => 'SourceEncapsulationNomThickness' }, + '300A,0224' => { VR => 'DS', Name => 'SourceEncapsulationNomTransmission' }, + '300A,0226' => { VR => 'LO', Name => 'SourceIsotopeName' }, + '300A,0228' => { VR => 'DS', Name => 'SourceIsotopeHalfLife' }, + '300A,0229' => { VR => 'CS', Name => 'SourceStrengthUnits' }, + '300A,022A' => { VR => 'DS', Name => 'ReferenceAirKermaRate' }, + '300A,022B' => { VR => 'DS', Name => 'SourceStrength' }, + '300A,022C' => { VR => 'DA', Name => 'SourceStrengthReferenceDate' }, + '300A,022E' => { VR => 'TM', Name => 'SourceStrengthReferenceTime' }, + '300A,0230' => { VR => 'SQ', Name => 'ApplicationSetupSequence' }, + '300A,0232' => { VR => 'CS', Name => 'ApplicationSetupType' }, + '300A,0234' => { VR => 'IS', Name => 'ApplicationSetupNumber' }, + '300A,0236' => { VR => 'LO', Name => 'ApplicationSetupName' }, + '300A,0238' => { VR => 'LO', Name => 'ApplicationSetupManufacturer' }, + '300A,0240' => { VR => 'IS', Name => 'TemplateNumber' }, + '300A,0242' => { VR => 'SH', Name => 'TemplateType' }, + '300A,0244' => { VR => 'LO', Name => 'TemplateName' }, + '300A,0250' => { VR => 'DS', Name => 'TotalReferenceAirKerma' }, + '300A,0260' => { VR => 'SQ', Name => 'BrachyAccessoryDeviceSequence' }, + '300A,0262' => { VR => 'IS', Name => 'BrachyAccessoryDeviceNumber' }, + '300A,0263' => { VR => 'SH', Name => 'BrachyAccessoryDeviceID' }, + '300A,0264' => { VR => 'CS', Name => 'BrachyAccessoryDeviceType' }, + '300A,0266' => { VR => 'LO', Name => 'BrachyAccessoryDeviceName' }, + '300A,026A' => { VR => 'DS', Name => 'BrachyAccessoryDeviceNomThickness' }, + '300A,026C' => { VR => 'DS', Name => 'BrachyAccessoryDevNomTransmission' }, + '300A,0280' => { VR => 'SQ', Name => 'ChannelSequence' }, + '300A,0282' => { VR => 'IS', Name => 'ChannelNumber' }, + '300A,0284' => { VR => 'DS', Name => 'ChannelLength' }, + '300A,0286' => { VR => 'DS', Name => 'ChannelTotalTime' }, + '300A,0288' => { VR => 'CS', Name => 'SourceMovementType' }, + '300A,028A' => { VR => 'IS', Name => 'NumberOfPulses' }, + '300A,028C' => { VR => 'DS', Name => 'PulseRepetitionInterval' }, + '300A,0290' => { VR => 'IS', Name => 'SourceApplicatorNumber' }, + '300A,0291' => { VR => 'SH', Name => 'SourceApplicatorID' }, + '300A,0292' => { VR => 'CS', Name => 'SourceApplicatorType' }, + '300A,0294' => { VR => 'LO', Name => 'SourceApplicatorName' }, + '300A,0296' => { VR => 'DS', Name => 'SourceApplicatorLength' }, + '300A,0298' => { VR => 'LO', Name => 'SourceApplicatorManufacturer' }, + '300A,029C' => { VR => 'DS', Name => 'SourceApplicatorWallNomThickness' }, + '300A,029E' => { VR => 'DS', Name => 'SourceApplicatorWallNomTrans' }, + '300A,02A0' => { VR => 'DS', Name => 'SourceApplicatorStepSize' }, + '300A,02A2' => { VR => 'IS', Name => 'TransferTubeNumber' }, + '300A,02A4' => { VR => 'DS', Name => 'TransferTubeLength' }, + '300A,02B0' => { VR => 'SQ', Name => 'ChannelShieldSequence' }, + '300A,02B2' => { VR => 'IS', Name => 'ChannelShieldNumber' }, + '300A,02B3' => { VR => 'SH', Name => 'ChannelShieldID' }, + '300A,02B4' => { VR => 'LO', Name => 'ChannelShieldName' }, + '300A,02B8' => { VR => 'DS', Name => 'ChannelShieldNominalThickness' }, + '300A,02BA' => { VR => 'DS', Name => 'ChannelShieldNominalTransmission' }, + '300A,02C8' => { VR => 'DS', Name => 'FinalCumulativeTimeWeight' }, + '300A,02D0' => { VR => 'SQ', Name => 'BrachyControlPointSequence' }, + '300A,02D2' => { VR => 'DS', Name => 'ControlPointRelativePosition' }, + '300A,02D4' => { VR => 'DS', Name => 'ControlPoint3DPosition' }, + '300A,02D6' => { VR => 'DS', Name => 'CumulativeTimeWeight' }, + '300A,02E0' => { VR => 'CS', Name => 'CompensatorDivergence' }, + '300A,02E1' => { VR => 'CS', Name => 'CompensatorMountingPosition' }, + '300A,02E2' => { VR => 'DS', Name => 'SourceToCompensatorDistance' }, + '300A,02E3' => { VR => 'FL', Name => 'TotalCompTrayWaterEquivThickness' }, + '300A,02E4' => { VR => 'FL', Name => 'IsocenterToCompensatorTrayDistance' }, + '300A,02E5' => { VR => 'FL', Name => 'CompensatorColumnOffset' }, + '300A,02E6' => { VR => 'FL', Name => 'IsocenterToCompensatorDistances' }, + '300A,02E7' => { VR => 'FL', Name => 'CompensatorRelStoppingPowerRatio' }, + '300A,02E8' => { VR => 'FL', Name => 'CompensatorMillingToolDiameter' }, + '300A,02EA' => { VR => 'SQ', Name => 'IonRangeCompensatorSequence' }, + '300A,02EB' => { VR => 'LT', Name => 'CompensatorDescription' }, + '300A,0302' => { VR => 'IS', Name => 'RadiationMassNumber' }, + '300A,0304' => { VR => 'IS', Name => 'RadiationAtomicNumber' }, + '300A,0306' => { VR => 'SS', Name => 'RadiationChargeState' }, + '300A,0308' => { VR => 'CS', Name => 'ScanMode' }, + '300A,030A' => { VR => 'FL', Name => 'VirtualSourceAxisDistances' }, + '300A,030C' => { VR => 'SQ', Name => 'SnoutSequence' }, + '300A,030D' => { VR => 'FL', Name => 'SnoutPosition' }, + '300A,030F' => { VR => 'SH', Name => 'SnoutID' }, + '300A,0312' => { VR => 'IS', Name => 'NumberOfRangeShifters' }, + '300A,0314' => { VR => 'SQ', Name => 'RangeShifterSequence' }, + '300A,0316' => { VR => 'IS', Name => 'RangeShifterNumber' }, + '300A,0318' => { VR => 'SH', Name => 'RangeShifterID' }, + '300A,0320' => { VR => 'CS', Name => 'RangeShifterType' }, + '300A,0322' => { VR => 'LO', Name => 'RangeShifterDescription' }, + '300A,0330' => { VR => 'IS', Name => 'NumberOfLateralSpreadingDevices' }, + '300A,0332' => { VR => 'SQ', Name => 'LateralSpreadingDeviceSequence' }, + '300A,0334' => { VR => 'IS', Name => 'LateralSpreadingDeviceNumber' }, + '300A,0336' => { VR => 'SH', Name => 'LateralSpreadingDeviceID' }, + '300A,0338' => { VR => 'CS', Name => 'LateralSpreadingDeviceType' }, + '300A,033A' => { VR => 'LO', Name => 'LateralSpreadingDeviceDescription' }, + '300A,033C' => { VR => 'FL', Name => 'LateralSpreadingDevWaterEquivThick' }, + '300A,0340' => { VR => 'IS', Name => 'NumberOfRangeModulators' }, + '300A,0342' => { VR => 'SQ', Name => 'RangeModulatorSequence' }, + '300A,0344' => { VR => 'IS', Name => 'RangeModulatorNumber' }, + '300A,0346' => { VR => 'SH', Name => 'RangeModulatorID' }, + '300A,0348' => { VR => 'CS', Name => 'RangeModulatorType' }, + '300A,034A' => { VR => 'LO', Name => 'RangeModulatorDescription' }, + '300A,034C' => { VR => 'SH', Name => 'BeamCurrentModulationID' }, + '300A,0350' => { VR => 'CS', Name => 'PatientSupportType' }, + '300A,0352' => { VR => 'SH', Name => 'PatientSupportID' }, + '300A,0354' => { VR => 'LO', Name => 'PatientSupportAccessoryCode' }, + '300A,0356' => { VR => 'FL', Name => 'FixationLightAzimuthalAngle' }, + '300A,0358' => { VR => 'FL', Name => 'FixationLightPolarAngle' }, + '300A,035A' => { VR => 'FL', Name => 'MetersetRate' }, + '300A,0360' => { VR => 'SQ', Name => 'RangeShifterSettingsSequence' }, + '300A,0362' => { VR => 'LO', Name => 'RangeShifterSetting' }, + '300A,0364' => { VR => 'FL', Name => 'IsocenterToRangeShifterDistance' }, + '300A,0366' => { VR => 'FL', Name => 'RangeShifterWaterEquivThickness' }, + '300A,0370' => { VR => 'SQ', Name => 'LateralSpreadingDeviceSettingsSeq' }, + '300A,0372' => { VR => 'LO', Name => 'LateralSpreadingDeviceSetting' }, + '300A,0374' => { VR => 'FL', Name => 'IsocenterToLateralSpreadingDevDist' }, + '300A,0380' => { VR => 'SQ', Name => 'RangeModulatorSettingsSequence' }, + '300A,0382' => { VR => 'FL', Name => 'RangeModulatorGatingStartValue' }, + '300A,0384' => { VR => 'FL', Name => 'RangeModulatorGatingStopValue' }, + '300A,038A' => { VR => 'FL', Name => 'IsocenterToRangeModulatorDistance' }, + '300A,0390' => { VR => 'SH', Name => 'ScanSpotTuneID' }, + '300A,0392' => { VR => 'IS', Name => 'NumberOfScanSpotPositions' }, + '300A,0394' => { VR => 'FL', Name => 'ScanSpotPositionMap' }, + '300A,0396' => { VR => 'FL', Name => 'ScanSpotMetersetWeights' }, + '300A,0398' => { VR => 'FL', Name => 'ScanningSpotSize' }, + '300A,039A' => { VR => 'IS', Name => 'NumberOfPaintings' }, + '300A,03A0' => { VR => 'SQ', Name => 'IonToleranceTableSequence' }, + '300A,03A2' => { VR => 'SQ', Name => 'IonBeamSequence' }, + '300A,03A4' => { VR => 'SQ', Name => 'IonBeamLimitingDeviceSequence' }, + '300A,03A6' => { VR => 'SQ', Name => 'IonBlockSequence' }, + '300A,03A8' => { VR => 'SQ', Name => 'IonControlPointSequence' }, + '300A,03AA' => { VR => 'SQ', Name => 'IonWedgeSequence' }, + '300A,03AC' => { VR => 'SQ', Name => 'IonWedgePositionSequence' }, + '300A,0401' => { VR => 'SQ', Name => 'ReferencedSetupImageSequence' }, + '300A,0402' => { VR => 'ST', Name => 'SetupImageComment' }, + '300A,0410' => { VR => 'SQ', Name => 'MotionSynchronizationSequence' }, + '300A,0412' => { VR => 'FL', Name => 'ControlPointOrientation' }, + '300A,0420' => { VR => 'SQ', Name => 'GeneralAccessorySequence' }, + '300A,0421' => { VR => 'SH', Name => 'GeneralAccessoryID' }, + '300A,0422' => { VR => 'ST', Name => 'GeneralAccessoryDescription' }, + '300A,0423' => { VR => 'CS', Name => 'GeneralAccessoryType' }, + '300A,0424' => { VR => 'IS', Name => 'GeneralAccessoryNumber' }, + '300C,0002' => { VR => 'SQ', Name => 'ReferencedRTPlanSequence' }, + '300C,0004' => { VR => 'SQ', Name => 'ReferencedBeamSequence' }, + '300C,0006' => { VR => 'IS', Name => 'ReferencedBeamNumber' }, + '300C,0007' => { VR => 'IS', Name => 'ReferencedReferenceImageNumber' }, + '300C,0008' => { VR => 'DS', Name => 'StartCumulativeMetersetWeight' }, + '300C,0009' => { VR => 'DS', Name => 'EndCumulativeMetersetWeight' }, + '300C,000A' => { VR => 'SQ', Name => 'ReferencedBrachyAppSetupSeq' }, + '300C,000C' => { VR => 'IS', Name => 'ReferencedBrachyAppSetupNumber' }, + '300C,000E' => { VR => 'IS', Name => 'ReferencedSourceNumber' }, + '300C,0020' => { VR => 'SQ', Name => 'ReferencedFractionGroupSequence' }, + '300C,0022' => { VR => 'IS', Name => 'ReferencedFractionGroupNumber' }, + '300C,0040' => { VR => 'SQ', Name => 'ReferencedVerificationImageSeq' }, + '300C,0042' => { VR => 'SQ', Name => 'ReferencedReferenceImageSequence' }, + '300C,0050' => { VR => 'SQ', Name => 'ReferencedDoseReferenceSequence' }, + '300C,0051' => { VR => 'IS', Name => 'ReferencedDoseReferenceNumber' }, + '300C,0055' => { VR => 'SQ', Name => 'BrachyReferencedDoseReferenceSeq' }, + '300C,0060' => { VR => 'SQ', Name => 'ReferencedStructureSetSequence' }, + '300C,006A' => { VR => 'IS', Name => 'ReferencedPatientSetupNumber' }, + '300C,0080' => { VR => 'SQ', Name => 'ReferencedDoseSequence' }, + '300C,00A0' => { VR => 'IS', Name => 'ReferencedToleranceTableNumber' }, + '300C,00B0' => { VR => 'SQ', Name => 'ReferencedBolusSequence' }, + '300C,00C0' => { VR => 'IS', Name => 'ReferencedWedgeNumber' }, + '300C,00D0' => { VR => 'IS', Name => 'ReferencedCompensatorNumber' }, + '300C,00E0' => { VR => 'IS', Name => 'ReferencedBlockNumber' }, + '300C,00F0' => { VR => 'IS', Name => 'ReferencedControlPointIndex' }, + '300C,00F2' => { VR => 'SQ', Name => 'ReferencedControlPointSequence' }, + '300C,00F4' => { VR => 'IS', Name => 'ReferencedStartControlPointIndex' }, + '300C,00F6' => { VR => 'IS', Name => 'ReferencedStopControlPointIndex' }, + '300C,0100' => { VR => 'IS', Name => 'ReferencedRangeShifterNumber' }, + '300C,0102' => { VR => 'IS', Name => 'ReferencedLateralSpreadingDevNum' }, + '300C,0104' => { VR => 'IS', Name => 'ReferencedRangeModulatorNumber' }, + '300E,0002' => { VR => 'CS', Name => 'ApprovalStatus' }, + '300E,0004' => { VR => 'DA', Name => 'ReviewDate' }, + '300E,0005' => { VR => 'TM', Name => 'ReviewTime' }, + '300E,0008' => { VR => 'PN', Name => 'ReviewerName' }, + # text group + '4000,0000' => { VR => 'UL', Name => 'TextGroupLength' }, + '4000,0010' => { VR => 'LT', Name => 'Arbitrary' }, + '4000,4000' => { VR => 'LT', Name => 'TextComments' }, + # results group + '4008,0040' => { VR => 'SH', Name => 'ResultsID' }, + '4008,0042' => { VR => 'LO', Name => 'ResultsIDIssuer' }, + '4008,0050' => { VR => 'SQ', Name => 'ReferencedInterpretationSequence' }, + '4008,0100' => { VR => 'DA', Name => 'InterpretationRecordedDate' }, + '4008,0101' => { VR => 'TM', Name => 'InterpretationRecordedTime' }, + '4008,0102' => { VR => 'PN', Name => 'InterpretationRecorder' }, + '4008,0103' => { VR => 'LO', Name => 'ReferenceToRecordedSound' }, + '4008,0108' => { VR => 'DA', Name => 'InterpretationTranscriptionDate' }, + '4008,0109' => { VR => 'TM', Name => 'InterpretationTranscriptionTime' }, + '4008,010A' => { VR => 'PN', Name => 'InterpretationTranscriber' }, + '4008,010B' => { VR => 'ST', Name => 'InterpretationText' }, + '4008,010C' => { VR => 'PN', Name => 'InterpretationAuthor' }, + '4008,0111' => { VR => 'SQ', Name => 'InterpretationApproverSequence' }, + '4008,0112' => { VR => 'DA', Name => 'InterpretationApprovalDate' }, + '4008,0113' => { VR => 'TM', Name => 'InterpretationApprovalTime' }, + '4008,0114' => { VR => 'PN', Name => 'PhysicianApprovingInterpretation' }, + '4008,0115' => { VR => 'LT', Name => 'InterpretationDiagnosisDescription' }, + '4008,0117' => { VR => 'SQ', Name => 'InterpretationDiagnosisCodeSeq' }, + '4008,0118' => { VR => 'SQ', Name => 'ResultsDistributionListSequence' }, + '4008,0119' => { VR => 'PN', Name => 'DistributionName' }, + '4008,011A' => { VR => 'LO', Name => 'DistributionAddress' }, + '4008,0200' => { VR => 'SH', Name => 'InterpretationID' }, + '4008,0202' => { VR => 'LO', Name => 'InterpretationIDIssuer' }, + '4008,0210' => { VR => 'CS', Name => 'InterpretationTypeID' }, + '4008,0212' => { VR => 'CS', Name => 'InterpretationStatusID' }, + '4008,0300' => { VR => 'ST', Name => 'Impressions' }, + '4008,4000' => { VR => 'ST', Name => 'ResultsComments' }, + '4FFE,0001' => { VR => 'SQ', Name => 'MACParametersSequence' }, + # curve group + '50xx,0005' => { VR => 'US', Name => 'CurveDimensions' }, + '50xx,0010' => { VR => 'US', Name => 'NumberOfPoints' }, + '50xx,0020' => { VR => 'CS', Name => 'TypeOfData' }, + '50xx,0022' => { VR => 'LO', Name => 'CurveDescription' }, + '50xx,0030' => { VR => 'SH', Name => 'AxisUnits' }, + '50xx,0040' => { VR => 'SH', Name => 'AxisLabels' }, + '50xx,0103' => { VR => 'US', Name => 'DataValueRepresentation' }, + '50xx,0104' => { VR => 'US', Name => 'MinimumCoordinateValue' }, + '50xx,0105' => { VR => 'US', Name => 'MaximumCoordinateValue' }, + '50xx,0106' => { VR => 'SH', Name => 'CurveRange' }, + '50xx,0110' => { VR => 'US', Name => 'CurveDataDescriptor' }, + '50xx,0112' => { VR => 'US', Name => 'CoordinateStartValue' }, + '50xx,0114' => { VR => 'US', Name => 'CoordinateStepValue' }, + '50xx,1001' => { VR => 'CS', Name => 'CurveActivationLayer' }, + '50xx,2000' => { VR => 'US', Name => 'AudioType' }, + '50xx,2002' => { VR => 'US', Name => 'AudioSampleFormat' }, + '50xx,2004' => { VR => 'US', Name => 'NumberOfChannels' }, + '50xx,2006' => { VR => 'UL', Name => 'NumberOfSamples' }, + '50xx,2008' => { VR => 'UL', Name => 'SampleRate' }, + '50xx,200A' => { VR => 'UL', Name => 'TotalTime' }, + '50xx,200C' => { VR => 'OW', Name => 'AudioSampleData' }, + '50xx,200E' => { VR => 'LT', Name => 'AudioComments' }, + '50xx,2500' => { VR => 'LO', Name => 'CurveLabel' }, + '50xx,2600' => { VR => 'SQ', Name => 'ReferencedOverlaySequence' }, + '50xx,2610' => { VR => 'US', Name => 'ReferencedOverlayGroup' }, + '50xx,3000' => { VR => 'OW', Name => 'CurveData' }, + '5200,9229' => { VR => 'SQ', Name => 'SharedFunctionalGroupsSequence' }, + '5200,9230' => { VR => 'SQ', Name => 'PerFrameFunctionalGroupsSequence' }, + '5400,0100' => { VR => 'SQ', Name => 'WaveformSequence' }, + '5400,0110' => { VR => 'OB', Name => 'ChannelMinimumValue' }, + '5400,0112' => { VR => 'OB', Name => 'ChannelMaximumValue' }, + '5400,1004' => { VR => 'US', Name => 'WaveformBitsAllocated' }, + '5400,1006' => { VR => 'CS', Name => 'WaveformSampleInterpretation' }, + '5400,100A' => { VR => 'OB', Name => 'WaveformPaddingValue' }, + '5400,1010' => { VR => 'OB', Name => 'WaveformData' }, + '5600,0010' => { VR => 'OF', Name => 'FirstOrderPhaseCorrectionAngle' }, + '5600,0020' => { VR => 'OF', Name => 'SpectroscopyData' }, + # overlay group + '6000,0000' => { VR => 'UL', Name => 'OverlayGroupLength' }, + '60xx,0010' => { VR => 'US', Name => 'OverlayRows' }, + '60xx,0011' => { VR => 'US', Name => 'OverlayColumns' }, + '60xx,0012' => { VR => 'US', Name => 'OverlayPlanes' }, + '60xx,0015' => { VR => 'IS', Name => 'NumberOfFramesInOverlay' }, + '60xx,0022' => { VR => 'LO', Name => 'OverlayDescription' }, + '60xx,0040' => { VR => 'CS', Name => 'OverlayType' }, + '60xx,0045' => { VR => 'LO', Name => 'OverlaySubtype' }, + '60xx,0050' => { VR => 'SS', Name => 'OverlayOrigin' }, + '60xx,0051' => { VR => 'US', Name => 'ImageFrameOrigin' }, + '60xx,0052' => { VR => 'US', Name => 'OverlayPlaneOrigin' }, + '60xx,0060' => { VR => 'CS', Name => 'OverlayCompressionCode' }, + '60xx,0061' => { VR => 'SH', Name => 'OverlayCompressionOriginator' }, + '60xx,0062' => { VR => 'SH', Name => 'OverlayCompressionLabel' }, + '60xx,0063' => { VR => 'CS', Name => 'OverlayCompressionDescription' }, + '60xx,0066' => { VR => 'AT', Name => 'OverlayCompressionStepPointers' }, + '60xx,0068' => { VR => 'US', Name => 'OverlayRepeatInterval' }, + '60xx,0069' => { VR => 'US', Name => 'OverlayBitsGrouped' }, + '60xx,0100' => { VR => 'US', Name => 'OverlayBitsAllocated' }, + '60xx,0102' => { VR => 'US', Name => 'OverlayBitPosition' }, + '60xx,0110' => { VR => 'CS', Name => 'OverlayFormat' }, + '60xx,0200' => { VR => 'US', Name => 'OverlayLocation' }, + '60xx,0800' => { VR => 'CS', Name => 'OverlayCodeLabel' }, + '60xx,0802' => { VR => 'US', Name => 'OverlayNumberOfTables' }, + '60xx,0803' => { VR => 'AT', Name => 'OverlayCodeTableLocation' }, + '60xx,0804' => { VR => 'US', Name => 'OverlayBitsForCodeWord' }, + '60xx,1001' => { VR => 'CS', Name => 'OverlayActivationLayer' }, + '60xx,1100' => { VR => 'US', Name => 'OverlayDescriptorGray' }, + '60xx,1101' => { VR => 'US', Name => 'OverlayDescriptorRed' }, + '60xx,1102' => { VR => 'US', Name => 'OverlayDescriptorGreen' }, + '60xx,1103' => { VR => 'US', Name => 'OverlayDescriptorBlue' }, + '60xx,1200' => { VR => 'US', Name => 'OverlaysGray' }, + '60xx,1201' => { VR => 'US', Name => 'OverlaysRed' }, + '60xx,1202' => { VR => 'US', Name => 'OverlaysGreen' }, + '60xx,1203' => { VR => 'US', Name => 'OverlaysBlue' }, + '60xx,1301' => { VR => 'IS', Name => 'ROIArea' }, + '60xx,1302' => { VR => 'DS', Name => 'ROIMean' }, + '60xx,1303' => { VR => 'DS', Name => 'ROIStandardDeviation' }, + '60xx,1500' => { VR => 'LO', Name => 'OverlayLabel' }, + '60xx,3000' => { VR => 'OB', Name => 'OverlayData' }, + '60xx,4000' => { VR => 'LT',Name => 'OverlayComments' }, + # pixel data group + '7Fxx,0000' => { VR => 'UL', Name => 'PixelDataGroupLength' }, + '7Fxx,0010' => { VR => 'OB', Name => 'PixelData', Binary => 1 }, + '7Fxx,0011' => { VR => 'US', Name => 'VariableNextDataGroup' }, + '7Fxx,0020' => { VR => 'OW', Name => 'VariableCoefficientsSDVN' }, + '7Fxx,0030' => { VR => 'OW', Name => 'VariableCoefficientsSDHN' }, + '7Fxx,0040' => { VR => 'OW', Name => 'VariableCoefficientsSDDN' }, + 'FFFA,FFFA' => { VR => 'SQ', Name => 'DigitalSignaturesSequence' }, + 'FFFC,FFFC' => { VR => 'OB', Name => 'DataSetTrailingPadding', Binary => 1 }, + # the sequence delimiters have no VR: + 'FFFE,E000' => 'StartOfItem', + 'FFFE,E00D' => 'EndOfItems', + 'FFFE,E0DD' => 'EndOfSequence', +); + +# table to translate registered UID values to readable strings +# (the PrintConv is added dynamically when a 'UI' format tag is extracted) +%uid = ( + '1.2.840.10008.1.1' => 'Verification SOP Class', + '1.2.840.10008.1.2' => 'Implicit VR Little Endian', + '1.2.840.10008.1.2.1' => 'Explicit VR Little Endian', + '1.2.840.10008.1.2.1.99' => 'Deflated Explicit VR Little Endian', + '1.2.840.10008.1.2.2' => 'Explicit VR Big Endian', + '1.2.840.10008.1.2.4.50' => 'JPEG Baseline (Process 1)', + '1.2.840.10008.1.2.4.51' => 'JPEG Extended (Process 2 & 4)', + '1.2.840.10008.1.2.4.52' => 'JPEG Extended (Process 3 & 5)', + '1.2.840.10008.1.2.4.53' => 'JPEG Spectral Selection, Non-Hierarchical (Process 6 & 8)', + '1.2.840.10008.1.2.4.54' => 'JPEG Spectral Selection, Non-Hierarchical (Process 7 & 9)', + '1.2.840.10008.1.2.4.55' => 'JPEG Full Progression, Non-Hierarchical (Process 10 & 12)', + '1.2.840.10008.1.2.4.56' => 'JPEG Full Progression, Non-Hierarchical (Process 11 & 13)', + '1.2.840.10008.1.2.4.57' => 'JPEG Lossless, Non-Hierarchical (Process 14)', + '1.2.840.10008.1.2.4.58' => 'JPEG Lossless, Non-Hierarchical (Process 15) ', + '1.2.840.10008.1.2.4.59' => 'JPEG Extended, Hierarchical (Process 16 & 18) ', + '1.2.840.10008.1.2.4.60' => 'JPEG Extended, Hierarchical (Process 17 & 19) ', + '1.2.840.10008.1.2.4.61' => 'JPEG Spectral Selection, Hierarchical (Process 20 & 22)', + '1.2.840.10008.1.2.4.62' => 'JPEG Spectral Selection, Hierarchical (Process 21 & 23)', + '1.2.840.10008.1.2.4.63' => 'JPEG Full Progression, Hierarchical (Process 24 & 26)', + '1.2.840.10008.1.2.4.64' => 'JPEG Full Progression, Hierarchical (Process 25 & 27)', + '1.2.840.10008.1.2.4.65' => 'JPEG Lossless, Hierarchical (Process 28) ', + '1.2.840.10008.1.2.4.66' => 'JPEG Lossless, Hierarchical (Process 29) ', + '1.2.840.10008.1.2.4.70' => 'JPEG Lossless, Non-Hierarchical, First-Order Prediction (Process 14-1)', + '1.2.840.10008.1.2.4.80' => 'JPEG-LS Lossless Image Compression', + '1.2.840.10008.1.2.4.81' => 'JPEG-LS Lossy (Near-Lossless) Image Compression', + '1.2.840.10008.1.2.4.90' => 'JPEG 2000 Image Compression (Lossless Only)', + '1.2.840.10008.1.2.4.91' => 'JPEG 2000 Image Compression', + '1.2.840.10008.1.2.4.92' => 'JPEG 2000 Part 2 Multi-component Image Compression (Lossless Only)', + '1.2.840.10008.1.2.4.93' => 'JPEG 2000 Part 2 Multi-component Image Compression', + '1.2.840.10008.1.2.4.94' => 'JPIP Referenced', + '1.2.840.10008.1.2.4.95' => 'JPIP Referenced Deflate', + '1.2.840.10008.1.2.4.100' => 'MPEG2 Main Profile @ Main Level', + '1.2.840.10008.1.2.5' => 'RLE Lossless', + '1.2.840.10008.1.2.6.1' => 'RFC 2557 MIME encapsulation', + '1.2.840.10008.1.2.6.2' => 'XML Encoding', + '1.2.840.10008.1.3.10' => 'Media Storage Directory Storage', + '1.2.840.10008.1.4.1.1' => 'Talairach Brain Atlas Frame of Reference', + '1.2.840.10008.1.4.1.2' => 'SPM2 T1 Frame of Reference', + '1.2.840.10008.1.4.1.3' => 'SPM2 T2 Frame of Reference', + '1.2.840.10008.1.4.1.4' => 'SPM2 PD Frame of Reference', + '1.2.840.10008.1.4.1.5' => 'SPM2 EPI Frame of Reference', + '1.2.840.10008.1.4.1.6' => 'SPM2 FIL T1 Frame of Reference', + '1.2.840.10008.1.4.1.7' => 'SPM2 PET Frame of Reference', + '1.2.840.10008.1.4.1.8' => 'SPM2 TRANSM Frame of Reference', + '1.2.840.10008.1.4.1.9' => 'SPM2 SPECT Frame of Reference', + '1.2.840.10008.1.4.1.10' => 'SPM2 GRAY Frame of Reference', + '1.2.840.10008.1.4.1.11' => 'SPM2 WHITE Frame of Reference', + '1.2.840.10008.1.4.1.12' => 'SPM2 CSF Frame of Reference', + '1.2.840.10008.1.4.1.13' => 'SPM2 BRAINMASK Frame of Reference', + '1.2.840.10008.1.4.1.14' => 'SPM2 AVG305T1 Frame of Reference', + '1.2.840.10008.1.4.1.15' => 'SPM2 AVG152T1 Frame of Reference', + '1.2.840.10008.1.4.1.16' => 'SPM2 AVG152T2 Frame of Reference', + '1.2.840.10008.1.4.1.17' => 'SPM2 AVG152PD Frame of Reference', + '1.2.840.10008.1.4.1.18' => 'SPM2 SINGLESUBJT1 Frame of Reference', + '1.2.840.10008.1.4.2.1' => 'ICBM 452 T1 Frame of Reference', + '1.2.840.10008.1.4.2.2' => 'ICBM Single Subject MRI Frame of Reference', + '1.2.840.10008.1.9' => 'Basic Study Content Notification SOP Class', + '1.2.840.10008.1.20.1' => 'Storage Commitment Push Model SOP Class', + '1.2.840.10008.1.20.1.1' => 'Storage Commitment Push Model SOP Instance', + '1.2.840.10008.1.20.2' => 'Storage Commitment Pull Model SOP Class ', + '1.2.840.10008.1.20.2.1' => 'Storage Commitment Pull Model SOP Instance ', + '1.2.840.10008.1.40' => 'Procedural Event Logging SOP Class', + '1.2.840.10008.1.40.1' => 'Procedural Event Logging SOP Instance', + '1.2.840.10008.1.42' => 'Substance Administration Logging SOP Class', + '1.2.840.10008.1.42.1' => 'Substance Administration Logging SOP Instance', + '1.2.840.10008.2.6.1' => 'DICOM UID Registry', + '1.2.840.10008.2.16.4' => 'DICOM Controlled Terminology', + '1.2.840.10008.3.1.1.1' => 'DICOM Application Context Name', + '1.2.840.10008.3.1.2.1.1' => 'Detached Patient Management SOP Class', + '1.2.840.10008.3.1.2.1.4' => 'Detached Patient Management Meta SOP Class', + '1.2.840.10008.3.1.2.2.1' => 'Detached Visit Management SOP Class', + '1.2.840.10008.3.1.2.3.1' => 'Detached Study Management SOP Class', + '1.2.840.10008.3.1.2.3.2' => 'Study Component Management SOP Class', + '1.2.840.10008.3.1.2.3.3' => 'Modality Performed Procedure Step SOP Class', + '1.2.840.10008.3.1.2.3.4' => 'Modality Performed Procedure Step Retrieve SOP Class', + '1.2.840.10008.3.1.2.3.5' => 'Modality Performed Procedure Step Notification SOP Class', + '1.2.840.10008.3.1.2.5.1' => 'Detached Results Management SOP Class', + '1.2.840.10008.3.1.2.5.4' => 'Detached Results Management Meta SOP Class', + '1.2.840.10008.3.1.2.5.5' => 'Detached Study Management Meta SOP Class', + '1.2.840.10008.3.1.2.6.1' => 'Detached Interpretation Management SOP Class', + '1.2.840.10008.4.2' => 'Storage Service Class Service Class PS 3.4', + '1.2.840.10008.5.1.1.1' => 'Basic Film Session SOP Class', + '1.2.840.10008.5.1.1.2' => 'Basic Film Box SOP Class', + '1.2.840.10008.5.1.1.4' => 'Basic Grayscale Image Box SOP Class', + '1.2.840.10008.5.1.1.4.1' => 'Basic Color Image Box SOP Class', + '1.2.840.10008.5.1.1.4.2' => 'Referenced Image Box SOP Class', + '1.2.840.10008.5.1.1.9' => 'Basic Grayscale Print ManagementMeta SOP Class', + '1.2.840.10008.5.1.1.9.1' => 'Referenced Grayscale Print Management Meta SOP Class', + '1.2.840.10008.5.1.1.14' => 'Print Job SOP Class', + '1.2.840.10008.5.1.1.15' => 'Basic Annotation Box SOP Class', + '1.2.840.10008.5.1.1.16' => 'Printer SOP Class', + '1.2.840.10008.5.1.1.16.376' => 'Printer Configuration Retrieval SOP Class', + '1.2.840.10008.5.1.1.17' => 'Printer SOP Instance', + '1.2.840.10008.5.1.1.17.376' => 'Printer Configuration RetrievalSOP Instance', + '1.2.840.10008.5.1.1.18' => 'Basic Color Print Management Meta SOP Class', + '1.2.840.10008.5.1.1.18.1' => 'Referenced Color Print Management Meta SOP Class', + '1.2.840.10008.5.1.1.22' => 'VOI LUT Box SOP Class', + '1.2.840.10008.5.1.1.23' => 'Presentation LUT SOP Class', + '1.2.840.10008.5.1.1.24' => 'Image Overlay Box SOP Class', + '1.2.840.10008.5.1.1.24.1' => 'Basic Print Image Overlay Box SOP Class', + '1.2.840.10008.5.1.1.25' => 'Print Queue SOP Instance', + '1.2.840.10008.5.1.1.26' => 'Print Queue Management SOP Class', + '1.2.840.10008.5.1.1.27' => 'Stored Print Storage SOP Class', + '1.2.840.10008.5.1.1.29' => 'Hardcopy Grayscale Image', + '1.2.840.10008.5.1.1.30' => 'Hardcopy Color Image Storage SOP Class', + '1.2.840.10008.5.1.1.31' => 'Pull Print Request SOP Class', + '1.2.840.10008.5.1.1.32' => 'Pull Stored Print Management Meta SOP Class', + '1.2.840.10008.5.1.1.33' => 'Media Creation Management SOP Class', + '1.2.840.10008.5.1.4.1.1.1' => 'Computed Radiography Image Storage', + '1.2.840.10008.5.1.4.1.1.1.1' => 'Digital X-Ray Image Storage - For Presentation', + '1.2.840.10008.5.1.4.1.1.1.1.1' => 'Digital X-Ray Image Storage - For Processing', + '1.2.840.10008.5.1.4.1.1.1.2' => 'Digital Mammography X-Ray Image Storage - For Presentation', + '1.2.840.10008.5.1.4.1.1.1.2.1' => 'Digital Mammography X-Ray Image Storage - For Processing', + '1.2.840.10008.5.1.4.1.1.1.3' => 'Digital Intra-oral X-Ray Image Storage - For Presentation', + '1.2.840.10008.5.1.4.1.1.1.3.1' => 'Digital Intra-oral X-Ray Image Storage - For Processing', + '1.2.840.10008.5.1.4.1.1.2' => 'CT Image Storage', + '1.2.840.10008.5.1.4.1.1.2.1' => 'Enhanced CT Image Storage', + '1.2.840.10008.5.1.4.1.1.3' => 'Ultrasound Multi-frame Image Storage ', + '1.2.840.10008.5.1.4.1.1.3.1' => 'Ultrasound Multi-frame Image Storage', + '1.2.840.10008.5.1.4.1.1.4' => 'MR Image Storage', + '1.2.840.10008.5.1.4.1.1.4.1' => 'Enhanced MR Image Storage', + '1.2.840.10008.5.1.4.1.1.4.2' => 'MR Spectroscopy Storage', + '1.2.840.10008.5.1.4.1.1.5' => 'Nuclear Medicine Image Storage', + '1.2.840.10008.5.1.4.1.1.6' => 'Ultrasound Image Storage', + '1.2.840.10008.5.1.4.1.1.6.1' => 'Ultrasound Image Storage', + '1.2.840.10008.5.1.4.1.1.7' => 'Secondary Capture Image Storage', + '1.2.840.10008.5.1.4.1.1.7.1' => 'Multi-frame Single Bit Secondary', + '1.2.840.10008.5.1.4.1.1.7.2' => 'Multi-frame Grayscale Byte Secondary Capture Image Storage', + '1.2.840.10008.5.1.4.1.1.7.3' => 'Multi-frame Grayscale Word Secondary Capture Image Storage', + '1.2.840.10008.5.1.4.1.1.7.4' => 'Multi-frame True Color Secondary Capture Image Storage', + '1.2.840.10008.5.1.4.1.1.8' => 'Standalone Overlay Storage', + '1.2.840.10008.5.1.4.1.1.9' => 'Standalone Curve Storage', + '1.2.840.10008.5.1.4.1.1.9.1' => 'Waveform Storage - Trial (Retired)', + '1.2.840.10008.5.1.4.1.1.9.1.1' => '12-lead ECG Waveform Storage', + '1.2.840.10008.5.1.4.1.1.9.1.2' => 'General ECG Waveform Storage', + '1.2.840.10008.5.1.4.1.1.9.1.3' => 'Ambulatory ECG Waveform Storage', + '1.2.840.10008.5.1.4.1.1.9.2.1' => 'Hemodynamic Waveform Storage', + '1.2.840.10008.5.1.4.1.1.9.3.1' => 'Cardiac Electrophysiology Waveform Storage', + '1.2.840.10008.5.1.4.1.1.9.4.1' => 'Basic Voice Audio Waveform Storage', + '1.2.840.10008.5.1.4.1.1.10' => 'Standalone Modality LUT Storage', + '1.2.840.10008.5.1.4.1.1.11' => 'Standalone VOI LUT Storage', + '1.2.840.10008.5.1.4.1.1.11.1' => 'Grayscale Softcopy Presentation State Storage SOP Class', + '1.2.840.10008.5.1.4.1.1.11.2' => 'Color Softcopy Presentation State Storage SOP Class', + '1.2.840.10008.5.1.4.1.1.11.3' => 'Pseudo-Color Softcopy Presentation State Storage SOP Class', + '1.2.840.10008.5.1.4.1.1.11.4' => 'Blending Softcopy Presentation State Storage SOP Class', + '1.2.840.10008.5.1.4.1.1.12.1' => 'X-Ray Angiographic Image Storage', + '1.2.840.10008.5.1.4.1.1.12.1.1' => 'Enhanced XA Image Storage', + '1.2.840.10008.5.1.4.1.1.12.2' => 'X-Ray Radiofluoroscopic Image Storage', + '1.2.840.10008.5.1.4.1.1.12.2.1' => 'Enhanced XRF Image Storage', + '1.2.840.10008.5.1.4.1.1.12.3' => 'X-Ray Angiographic Bi-Plane Image Storage ', + '1.2.840.10008.5.1.4.1.1.13.1.1' => 'X-Ray 3D Angiographic Image Storage', + '1.2.840.10008.5.1.4.1.1.13.1.2' => 'X-Ray 3D Craniofacial Image Storage', + '1.2.840.10008.5.1.4.1.1.13.1.3' => 'Breast Tomosynthesis Image Storage', + '1.2.840.10008.5.1.4.1.1.14.1' => 'Intravascular Optical Coherence Tomography Image Storage - For Presentation', + '1.2.840.10008.5.1.4.1.1.14.2' => 'Intravascular Optical Coherence Tomography Image Storage - For Processing', + '1.2.840.10008.5.1.4.1.1.20' => 'Nuclear Medicine Image Storage', + '1.2.840.10008.5.1.4.1.1.66' => 'Raw Data Storage', + '1.2.840.10008.5.1.4.1.1.66.1' => 'Spatial Registration Storage', + '1.2.840.10008.5.1.4.1.1.66.2' => 'Spatial Fiducials Storage', + '1.2.840.10008.5.1.4.1.1.66.3' => 'Deformable Spatial Registration Storage', + '1.2.840.10008.5.1.4.1.1.66.4' => 'Segmentation Storage', + '1.2.840.10008.5.1.4.1.1.67' => 'Real World Value Mapping Storage', + '1.2.840.10008.5.1.4.1.1.77.1' => 'VL Image Storage ', + '1.2.840.10008.5.1.4.1.1.77.2' => 'VL Multi-frame Image Storage', + '1.2.840.10008.5.1.4.1.1.77.1.1' => 'VL Endoscopic Image Storage', + '1.2.840.10008.5.1.4.1.1.77.1.1.1' => 'Video Endoscopic Image Storage', + '1.2.840.10008.5.1.4.1.1.77.1.2' => 'VL Microscopic Image Storage', + '1.2.840.10008.5.1.4.1.1.77.1.2.1' => 'Video Microscopic Image Storage', + '1.2.840.10008.5.1.4.1.1.77.1.3' => 'VL Slide-Coordinates Microscopic Image Storage', + '1.2.840.10008.5.1.4.1.1.77.1.4' => 'VL Photographic Image Storage', + '1.2.840.10008.5.1.4.1.1.77.1.4.1' => 'Video Photographic Image Storage', + '1.2.840.10008.5.1.4.1.1.77.1.5.1' => 'Ophthalmic Photography 8 Bit Image Storage', + '1.2.840.10008.5.1.4.1.1.77.1.5.2' => 'Ophthalmic Photography 16 Bit Image Storage', + '1.2.840.10008.5.1.4.1.1.77.1.5.3' => 'Stereometric Relationship Storage', + '1.2.840.10008.5.1.4.1.1.77.1.5.4' => 'Ophthalmic Tomography Image Storage', + '1.2.840.10008.5.1.4.1.1.77.1.6' => 'VL Whole Slide Microscopy Image Storage', + '1.2.840.10008.5.1.4.1.1.78.1' => 'Lensometry Measurements Storage', + '1.2.840.10008.5.1.4.1.1.78.2' => 'Autorefraction Measurements Storage', + '1.2.840.10008.5.1.4.1.1.78.3' => 'Keratometry Measurements Storage', + '1.2.840.10008.5.1.4.1.1.78.4' => 'Subjective Refraction Measurements Storage', + '1.2.840.10008.5.1.4.1.1.78.5' => 'Visual Acuity Measurements Storage', + '1.2.840.10008.5.1.4.1.1.78.6' => 'Spectacle Prescription Report Storage', + '1.2.840.10008.5.1.4.1.1.78.7' => 'Ophthalmic Axial Measurements Storage', + '1.2.840.10008.5.1.4.1.1.78.8' => 'Intraocular Lens Calculations Storage', + '1.2.840.10008.5.1.4.1.1.79.1' => 'Macular Grid Thickness and Volume Report Storage SOP Class', + '1.2.840.10008.5.1.4.1.1.80.1' => 'Ophthalmic Visual Field Static Perimetry Measurements Storage', + '1.2.840.10008.5.1.4.1.1.88.1' => 'Text SR Storage - Trial (Retired)', + '1.2.840.10008.5.1.4.1.1.88.2' => 'Audio SR Storage - Trial (Retired)', + '1.2.840.10008.5.1.4.1.1.88.3' => 'Detail SR Storage - Trial (Retired)', + '1.2.840.10008.5.1.4.1.1.88.4' => 'Comprehensive SR Storage - Trial (Retired)', + '1.2.840.10008.5.1.4.1.1.88.11' => 'Basic Text SR', + '1.2.840.10008.5.1.4.1.1.88.22' => 'Enhanced SR', + '1.2.840.10008.5.1.4.1.1.88.33' => 'Comprehensive SR', + '1.2.840.10008.5.1.4.1.1.88.40' => 'Procedure Log Storage', + '1.2.840.10008.5.1.4.1.1.88.50' => 'Mammography CAD SR', + '1.2.840.10008.5.1.4.1.1.88.59' => 'Key Object Selection Document', + '1.2.840.10008.5.1.4.1.1.88.65' => 'Chest CAD SR', + '1.2.840.10008.5.1.4.1.1.88.67' => 'X-Ray Radiation Dose SR Storage', + '1.2.840.10008.5.1.4.1.1.88.69' => 'Colon CAD SR', + '1.2.840.10008.5.1.4.1.1.88.70' => 'Implantation Plan SR Document Storage', + '1.2.840.10008.5.1.4.1.1.104.1' => 'Encapsulated PDF Storage', + '1.2.840.10008.5.1.4.1.1.104.2' => 'Encapsulated CDA Storage', + '1.2.840.10008.5.1.4.1.1.128' => 'Positron Emission Tomography Image Storage', + '1.2.840.10008.5.1.4.1.1.129' => 'Standalone PET Curve Storage', + '1.2.840.10008.5.1.4.1.1.481.1' => 'RT Image Storage', + '1.2.840.10008.5.1.4.1.1.481.2' => 'RT Dose Storage', + '1.2.840.10008.5.1.4.1.1.481.3' => 'RT Structure Set Storage', + '1.2.840.10008.5.1.4.1.1.481.4' => 'RT Beams Treatment Record Storage', + '1.2.840.10008.5.1.4.1.1.481.5' => 'RT Plan Storage', + '1.2.840.10008.5.1.4.1.1.481.6' => 'RT Brachy Treatment Record Storage', + '1.2.840.10008.5.1.4.1.1.481.7' => 'RT Treatment Summary Record Storage', + '1.2.840.10008.5.1.4.1.1.481.8' => 'RT Ion Plan Storage', + '1.2.840.10008.5.1.4.1.1.481.9' => 'RT Ion Beams Treatment Record Storage', + '1.2.840.10008.5.1.4.1.2.1.1' => 'Patient Root Query/Retrieve Information Model - FIND', + '1.2.840.10008.5.1.4.1.2.1.2' => 'Patient Root Query/Retrieve Information Model - MOVE', + '1.2.840.10008.5.1.4.1.2.1.3' => 'Patient Root Query/Retrieve Information Model - GET', + '1.2.840.10008.5.1.4.1.2.2.1' => 'Study Root Query/Retrieve Information Model - FIND', + '1.2.840.10008.5.1.4.1.2.2.2' => 'Study Root Query/Retrieve Information Model - MOVE', + '1.2.840.10008.5.1.4.1.2.2.3' => 'Study Root Query/Retrieve Information Model - GET', + '1.2.840.10008.5.1.4.1.2.3.1' => 'Patient/Study Only Query/Retrieve Information Model - FIND', + '1.2.840.10008.5.1.4.1.2.3.2' => 'Patient/Study Only Query/Retrieve Information Model - MOVE', + '1.2.840.10008.5.1.4.1.2.3.3' => 'Patient/Study Only Query/Retrieve Information Model - GET', + '1.2.840.10008.5.1.4.31' => 'Modality Worklist Information Model - FIND', + '1.2.840.10008.5.1.4.32.1' => 'General Purpose Worklist Information Model - FIND', + '1.2.840.10008.5.1.4.32.2' => 'General Purpose Scheduled Procedure Step SOP Class', + '1.2.840.10008.5.1.4.32.3' => 'General Purpose Performed Procedure Step SOP Class', + '1.2.840.10008.5.1.4.32' => 'General Purpose Worklist Management Meta SOP Class', + '1.2.840.10008.5.1.4.33' => 'Instance Availability Notification SOP Class', + '1.2.840.10008.5.1.4.34.1' => 'RT Beams Delivery Instruction Storage', + '1.2.840.10008.5.1.4.34.2' => 'RT Conventional Machine Verification', + '1.2.840.10008.5.1.4.34.3' => 'RT Ion Machine Verification', + '1.2.840.10008.5.1.4.34.4' => 'Unified Worklist and Procedure Step Service Class', + '1.2.840.10008.5.1.4.34.4.1' => 'Unified Procedure Step - Push SOP Class', + '1.2.840.10008.5.1.4.34.4.2' => 'Unified Procedure Step - Watch SOP Class', + '1.2.840.10008.5.1.4.34.4.3' => 'Unified Procedure Step - Pull SOP Class', + '1.2.840.10008.5.1.4.34.4.4' => 'Unified Procedure Step - Event SOP Class', + '1.2.840.10008.5.1.4.34.5' => 'Unified Worklist and Procedure Step SOP Instance', + '1.2.840.10008.5.1.4.34.6.1' => 'Unified Procedure Step - Push SOP Class', + '1.2.840.10008.5.1.4.34.6.2' => 'Unified Procedure Step - Watch SOP Class', + '1.2.840.10008.5.1.4.34.6.3' => 'Unified Procedure Step - Pull SOP Class', + '1.2.840.10008.5.1.4.34.6.4' => 'Unified Procedure Step - Event SOP Class', + '1.2.840.10008.5.1.4.34.7' => 'RT Beams Delivery Instruction Storage', + '1.2.840.10008.5.1.4.34.8' => 'RT Conventional Machine Verification', + '1.2.840.10008.5.1.4.34.9' => 'RT Ion Machine Verification', + '1.2.840.10008.5.1.4.37.1' => 'General Relevant Patient Information Query', + '1.2.840.10008.5.1.4.37.2' => 'Breast Imaging Relevant Patient Information Query', + '1.2.840.10008.5.1.4.37.3' => 'Cardiac Relevant Patient Information Query', + '1.2.840.10008.5.1.4.38.1' => 'Hanging Protocol Storage', + '1.2.840.10008.5.1.4.38.2' => 'Hanging Protocol Information Model - FIND', + '1.2.840.10008.5.1.4.38.3' => 'Hanging Protocol Information Model - MOVE', + '1.2.840.10008.5.1.4.39.1' => 'Color Palette Storage', + '1.2.840.10008.5.1.4.39.2' => 'Color Palette Information Model - FIND', + '1.2.840.10008.5.1.4.39.3' => 'Color Palette Information Model - MOVE', + '1.2.840.10008.5.1.4.39.4' => 'Color Palette Information Model - GET', + '1.2.840.10008.5.1.4.41' => 'Product Characteristics Query SOP Class', + '1.2.840.10008.5.1.4.42' => 'Substance Approval Query SOP Class', + '1.2.840.10008.5.1.4.43.1' => 'Generic Implant Template Storage', + '1.2.840.10008.5.1.4.43.2' => 'Generic Implant Template Information Model - FIND', + '1.2.840.10008.5.1.4.43.3' => 'Generic Implant Template Information Model - MOVE', + '1.2.840.10008.5.1.4.43.4' => 'Generic Implant Template Information Model - GET', + '1.2.840.10008.5.1.4.44.1' => 'Implant Assembly Template Storage', + '1.2.840.10008.5.1.4.44.2' => 'Implant Assembly Template Information Model - FIND', + '1.2.840.10008.5.1.4.44.3' => 'Implant Assembly Template Information Model - MOVE', + '1.2.840.10008.5.1.4.44.4' => 'Implant Assembly Template Information Model - GET', + '1.2.840.10008.5.1.4.45.1' => 'Implant Template Group Storage', + '1.2.840.10008.5.1.4.45.2' => 'Implant Template Group Information Model - FIND', + '1.2.840.10008.5.1.4.45.3' => 'Implant Template Group Information Model - MOVE', + '1.2.840.10008.5.1.4.45.4' => 'Implant Template Group Information Model - GET', + '1.2.840.10008.15.0.3.1' => 'dicomDeviceName', + '1.2.840.10008.15.0.3.2' => 'dicomDescription', + '1.2.840.10008.15.0.3.3' => 'dicomManufacturer', + '1.2.840.10008.15.0.3.4' => 'dicomManufacturerModelName', + '1.2.840.10008.15.0.3.5' => 'dicomSoftwareVersion', + '1.2.840.10008.15.0.3.6' => 'dicomVendorData', + '1.2.840.10008.15.0.3.7' => 'dicomAETitle', + '1.2.840.10008.15.0.3.8' => 'dicomNetworkConnectionReference', + '1.2.840.10008.15.0.3.9' => 'dicomApplicationCluster', + '1.2.840.10008.15.0.3.10' => 'dicomAssociationInitiator', + '1.2.840.10008.15.0.3.11' => 'dicomAssociationAcceptor', + '1.2.840.10008.15.0.3.12' => 'dicomHostname', + '1.2.840.10008.15.0.3.13' => 'dicomPort', + '1.2.840.10008.15.0.3.14' => 'dicomSOPClass', + '1.2.840.10008.15.0.3.15' => 'dicomTransferRole', + '1.2.840.10008.15.0.3.16' => 'dicomTransferSyntax', + '1.2.840.10008.15.0.3.17' => 'dicomPrimaryDeviceType', + '1.2.840.10008.15.0.3.18' => 'dicomRelatedDeviceReference', + '1.2.840.10008.15.0.3.19' => 'dicomPreferredCalledAETitle', + '1.2.840.10008.15.0.3.20' => 'dicomTLSCyphersuite', + '1.2.840.10008.15.0.3.21' => 'dicomAuthorizedNodeCertificateReference', + '1.2.840.10008.15.0.3.22' => 'dicomThisNodeCertificateReference', + '1.2.840.10008.15.0.3.23' => 'dicomInstalled', + '1.2.840.10008.15.0.3.24' => 'dicomStationName', + '1.2.840.10008.15.0.3.25' => 'dicomDeviceSerialNumber', + '1.2.840.10008.15.0.3.26' => 'dicomInstitutionName', + '1.2.840.10008.15.0.3.27' => 'dicomInstitutionAddress', + '1.2.840.10008.15.0.3.28' => 'dicomInstitutionDepartmentName', + '1.2.840.10008.15.0.3.29' => 'dicomIssuerOfPatientID', + '1.2.840.10008.15.0.3.30' => 'dicomPreferredCallingAETitle', + '1.2.840.10008.15.0.3.31' => 'dicomSupportedCharacterSet', + '1.2.840.10008.15.0.4.1' => 'dicomConfigurationRoot', + '1.2.840.10008.15.0.4.2' => 'dicomDevicesRoot', + '1.2.840.10008.15.0.4.3' => 'dicomUniqueAETitlesRegistryRoot', + '1.2.840.10008.15.0.4.4' => 'dicomDevice', + '1.2.840.10008.15.0.4.5' => 'dicomNetworkAE', + '1.2.840.10008.15.0.4.6' => 'dicomNetworkConnection', + '1.2.840.10008.15.0.4.7' => 'dicomUniqueAETitle', + '1.2.840.10008.15.0.4.8' => 'dicomTransferCapability', +); + +#------------------------------------------------------------------------------ +# Extract information from a DICOM (DCM) image +# Inputs: 0) ExifTool object reference, 1) DirInfo reference +# Returns: 1 on success, 0 if this wasn't a valid DICOM file +sub ProcessDICOM($$) +{ + my ($et, $dirInfo) = @_; + my $raf = $$dirInfo{RAF}; + my $unknown = $et->Options('Unknown'); + my $verbose = $et->Options('Verbose'); + my ($hdr, $buff, $implicit, $vr, $len); +# +# identify the DICOM or ACR-NEMA file +# + $raf->Read($hdr, 12) == 12 or return 0; # save for ACR identification later + $raf->Seek(128, 0) or return 0; # skip to end of DICM header + $raf->Read($buff, 4) == 4 or return 0; # read signature + if ($buff eq 'DICM') { + # file meta information transfer syntax is explicit little endian + SetByteOrder('II'); + $et->SetFileType('DICOM'); + } else { + # test for a RAW DCM image (ACR-NEMA format, ie. no header) + foreach ('II','MM','') { + return 0 unless $_; # no luck identifying the syntax + SetByteOrder($_); + my $g = Get16u(\$hdr, 0); + # expect group number to be small and even + next if $g < 2 or $g > 8 or $g & 0x01; + my $e = Get16u(\$hdr, 2); + next if $e > 0x20; # expect a low element number at start + $vr = substr($hdr, 4, 2); # look for explicit VR + if ($vr =~ /^[A-Z]{2}$/) { + $implicit = 0; + if ($vr32{$vr}) { + next unless Get16u(\$hdr, 6) == 0; # must be 2 zero bytes + $len = Get32u(\$hdr, 8); + } else { + next if $e == 0 and $vr ne 'UL'; # group length must be UL + $len = Get16u(\$hdr, 6); + } + } else { + $implicit = 1; + $len = Get32u(\$hdr, 4); + } + next if $e == 0 and $len != 4; # group length value must be 4 bytes + next if $len > 64; # first element shouldn't be too long + last; # success! + } + $raf->Seek(0, 0) or return 0; # rewind to start of file + $et->SetFileType('ACR'); + } +# +# process the meta information +# + my $tagTablePtr = GetTagTable('Image::ExifTool::DICOM::Main'); + my $pos = $raf->Tell(); + my $err = 1; + my ($transferSyntax, $group2end); + for (;;) { + $raf->Read($buff, 8) == 8 or $err = 0, last; + $pos += 8; + my $group = Get16u(\$buff, 0); + # implement the transfer syntax at the end of the group 2 data + if ($transferSyntax and ($group != 0x0002 or + ($group2end and $pos > $group2end))) + { + # 1.2.840.10008.1.2 = implicit VR little endian + # 1.2.840.10008.1.2.2 = explicit VR big endian + # 1.2.840.10008.1.2.x = explicit VR little endian + # 1.2.840.10008.1.2.1.99 = deflated + unless ($transferSyntax =~ /^1\.2\.840\.10008\.1\.2(\.\d+)?(\.\d+)?/) { + $et->Warn("Unrecognized transfer syntax $transferSyntax"); + last; + } + if (not $1) { + $implicit = 1; + } elsif ($1 eq '.2') { + SetByteOrder('MM'); + $group = Get16u(\$buff, 0); # must get group again + } elsif ($1 eq '.1' and $2 and $2 eq '.99') { + # inflate compressed data stream + if (eval { require Compress::Zlib }) { + # must use undocumented zlib feature to disable zlib header information + # because DICOM deflated data doesn't have the zlib header (ref 3) + my $wbits = -Compress::Zlib::MAX_WBITS(); + my $inflate = Compress::Zlib::inflateInit(-WindowBits => $wbits); + if ($inflate) { + $raf->Seek(-8, 1) or last; + my $data = ''; + while ($raf->Read($buff, 65536)) { + my ($buf, $stat) = $inflate->inflate($buff); + if ($stat == Compress::Zlib::Z_OK() or + $stat == Compress::Zlib::Z_STREAM_END()) + { + $data .= $buf; + last if $stat == Compress::Zlib::Z_STREAM_END(); + } else { + $et->Warn('Error inflating compressed data stream'); + return 1; + } + } + last if length $data < 8; + # create new RAF object from inflated data stream + $raf = new File::RandomAccess(\$data); + # re-read start of stream (now decompressed) + $raf->Read($buff, 8) == 8 or last; + $group = Get16u(\$buff, 0); + } else { + $et->Warn('Error initializing inflation'); + return 1; + } + } else { + $et->Warn('Install Compress::Zlib to decode compressed data stream'); + return 1; + } + } + undef $transferSyntax; + } + my $element = Get16u(\$buff,2); + my $tag = sprintf('%.4X,%.4X', $group, $element); + + if ($implicit or $implicitVR{$tag}) { + # treat everything as string if implicit VR because it + # isn't worth it to generate the necessary VR lookup tables + # for the thousands of defined data elements + $vr = ''; # no VR (treat everything as string) + $len = Get32u(\$buff, 4); + } else { + $vr = substr($buff,4,2); + last unless $vr =~ /^[A-Z]{2}$/; + if ($vr32{$vr}) { + $raf->Read($buff, 4) == 4 or last; + $pos += 4; + $len = Get32u(\$buff, 0); + $len = 0 if $vr eq 'SQ'; # just recurse into sequences + } else { + $len = Get16u(\$buff, 6); + } + } + if ($len == 0xffffffff) { + $len = 0; # don't read value if undefined length + if ($verbose) { + # start list of items in verbose output + $et->VPrint(0, "$$et{INDENT}+ [List of items]\n"); + $$et{INDENT} .= '| '; + } + } + # read the element value + if ($len) { + $raf->Read($buff, $len) == $len or last; + $pos += $len; + } else { + $buff = ''; + } + + # handle tags not found in the table + my $tagInfo = $$tagTablePtr{$tag}; + unless ($tagInfo) { + # accept tag ID's with "x" for a wildcard in the following patterns: + # '60xx,1203', '0020,31xx', '0028,04x2', '1000,xxx0', '1010,xxxx' + my $xx; + if ((($xx = $tag) =~ s/^(..)../$1xx/ and $$tagTablePtr{$xx}) or + (($xx = $tag) =~ s/..$/xx/ and $$tagTablePtr{$xx}) or + (($xx = $tag) =~ s/.(.)$/x$1/ and $$tagTablePtr{$xx}) or + (($xx = $tag) =~ s/...(.)$/xxx$1/ and $$tagTablePtr{$xx}) or + (($xx = $tag) =~ s/....$/xxxx/ and $$tagTablePtr{$xx})) + { + $tag = $xx; + $tagInfo = $$tagTablePtr{$xx}; + } elsif ($unknown) { + # create tag info hash for unknown elements + if ($element == 0) { # element zero is group length + $tagInfo = { + Name => sprintf("Group%.4X_Length", $group), + Description => sprintf("Group %.4X Length", $group), + }; + } else { + $tagInfo = { + Name => sprintf("DICOM_%.4X_%.4X", $group, $element), + Description => sprintf("DICOM %.4X,%.4X", $group, $element), + }; + } + $$tagInfo{Unknown} = 1; + AddTagToTable($tagTablePtr, $tag, $tagInfo); + } + } + # get VR from our tag information if implicit + $vr = $$tagInfo{VR} || ' ' if $tagInfo and not $vr; + + if ($element == 0) { + $vr = 'UL'; # group length element is always unsigned long + } + my $val; + my $format = $dicomFormat{$vr}; + # remove trailing space used to pad to an even number of characters + $buff =~ s/ $// unless $format or length($buff) & 0x01; + if ($len > 1024) { + # treat large data elements as binary data + my $binData; + my $lcTag = $tagInfo ? lc($$tagInfo{Name}) : 'unknown'; + if ($$et{REQ_TAG_LOOKUP}{$lcTag} or + ($$et{OPTIONS}{Binary} and not $$et{EXCL_TAG_LOOKUP}{$lcTag})) + { + $binData = $buff; # must make a copy + } else { + $binData = "Binary data $len bytes"; + } + $val = \$binData; + } elsif ($format) { + $val = ReadValue(\$buff, 0, $format, undef, $len); + } else { + $val = $buff; + $format = 'string'; + if ($vr eq 'DA') { + # format date values + $val =~ s/^ *(\d{4})(\d{2})(\d{2})/$1:$2:$3/; + } elsif ($vr eq 'TM') { + # format time values + $val =~ s/^ *(\d{2})(\d{2})(\d{2}[^ ]*)/$1:$2:$3/; + } elsif ($vr eq 'DT') { + # format date/time values + $val =~ s/^ *(\d{4})(\d{2})(\d{2})(\d{2})(\d{2})(\d{2}[^ ]*)/$1:$2:$3 $4:$5:$6/; + } elsif ($vr eq 'AT' and $len == 4) { + # convert attribute tag ID to hex format + my ($g, $e) = (Get16u(\$buff,0), Get16u(\$buff,2)); + $val = sprintf('%.4X,%.4X', $g, $e); + } elsif ($vr eq 'UI') { + # add PrintConv to translate registered UID's + $val =~ s/\0.*//s; # truncate at null + $$tagInfo{PrintConv} = \%uid if $uid{$val} and $tagInfo; + } elsif ($vr =~ /^(AE|CS|DS|IS|LO|PN|SH)$/) { + $buff =~ s/ +$//; # leading/trailing spaces not significant + $buff =~ s/^ +//; + } elsif ($vr =~ /^(LT|ST|UT)$/) { + $buff =~ s/ +$//; # trailing spaces not significant + } + } + # save the group 2 end position and transfer syntax + if ($group == 0x0002) { + $element == 0x0000 and $group2end = $pos + $val; + $element == 0x0010 and $transferSyntax = $val; + } + + # handle the new tag information + $et->HandleTag($tagTablePtr, $tag, $val, + DataPt => \$buff, + DataPos => $pos - $len, + Format => $format, + Start => 0, + Size => $len, + Extra => " ($vr)", + ); + + # stop indenting for list if we reached EndOfItems tag + $$et{INDENT} =~ s/..$// if $verbose and $tag eq 'FFFE,E00D'; + } + $err and $et->Warn('Error reading DICOM file (corrupted?)'); + return 1; +} + +1; # end + +__END__ + +=head1 NAME + +Image::ExifTool::DICOM - Read DICOM and ACR-NEMA medical images + +=head1 SYNOPSIS + +This module is used by Image::ExifTool + +=head1 DESCRIPTION + +This module contains routines required by Image::ExifTool to extract meta +information from DICOM (Digital Imaging and Communications in Medicine) DCM +and ACR-NEMA (American College of Radiology - National Electrical +Manufacturer's Association) ACR medical images. + +=head1 NOTES + +Images compressed using the DICOM deflated transfer syntax will be decoded +if Compress::Zlib is installed. + +No translation of special characters sets is done. + +=head1 AUTHOR + +Copyright 2003-2019, Phil Harvey (phil at owl.phy.queensu.ca) + +This library is free software; you can redistribute it and/or modify it +under the same terms as Perl itself. + +=head1 REFERENCES + +=over 4 + +=item L<http://medical.nema.org/> + +=item L<http://www.sph.sc.edu/comd/rorden/dicom.html> + +=item L<http://www.dclunie.com/> + +=item L<http://www.gehealthcare.com/usen/interoperability/dicom/docs/2258357r3.pdf> + +=back + +=head1 SEE ALSO + +L<Image::ExifTool::TagNames/DICOM Tags>, +L<Image::ExifTool(3pm)|Image::ExifTool> + +=cut + diff --git a/lib/Image/ExifTool/DJI.pm b/lib/Image/ExifTool/DJI.pm new file mode 100644 index 0000000..cfebb5e --- /dev/null +++ b/lib/Image/ExifTool/DJI.pm @@ -0,0 +1,138 @@ +#------------------------------------------------------------------------------ +# File: DJI.pm +# +# Description: DJI Phantom maker notes tags +# +# Revisions: 2016-07-25 - P. Harvey Created +# 2017-06-23 - PH Added XMP tags +#------------------------------------------------------------------------------ + +package Image::ExifTool::DJI; + +use strict; +use vars qw($VERSION); +use Image::ExifTool::Exif; +use Image::ExifTool::XMP; +use Image::ExifTool::GPS; + +$VERSION = '1.02'; + +my %convFloat2 = ( + PrintConv => 'sprintf("%+.2f", $val)', + PrintConvInv => '$val', +); + +# DJI maker notes (ref PH, mostly educated guesses based on DJI QuickTime::UserData tags) +%Image::ExifTool::DJI::Main = ( + WRITE_PROC => \&Image::ExifTool::Exif::WriteExif, + CHECK_PROC => \&Image::ExifTool::Exif::CheckExif, + GROUPS => { 0 => 'MakerNotes', 2 => 'Camera' }, + NOTES => q{ + This table lists tags found in the maker notes of images from some DJI + Phantom drones. + }, + 0x01 => { Name => 'Make', Writable => 'string' }, + # 0x02 - int8u[4]: "1 0 0 0", "1 1 0 0" + 0x03 => { Name => 'SpeedX', Writable => 'float', %convFloat2 }, # (guess) + 0x04 => { Name => 'SpeedY', Writable => 'float', %convFloat2 }, # (guess) + 0x05 => { Name => 'SpeedZ', Writable => 'float', %convFloat2 }, # (guess) + 0x06 => { Name => 'Pitch', Writable => 'float', %convFloat2 }, + 0x07 => { Name => 'Yaw', Writable => 'float', %convFloat2 }, + 0x08 => { Name => 'Roll', Writable => 'float', %convFloat2 }, + 0x09 => { Name => 'CameraPitch',Writable => 'float', %convFloat2 }, + 0x0a => { Name => 'CameraYaw', Writable => 'float', %convFloat2 }, + 0x0b => { Name => 'CameraRoll', Writable => 'float', %convFloat2 }, +); + +%Image::ExifTool::DJI::XMP = ( + %Image::ExifTool::XMP::xmpTableDefaults, + GROUPS => { 0 => 'XMP', 1 => 'XMP-drone-dji', 2 => 'Location' }, + NAMESPACE => 'drone-dji', + TABLE_DESC => 'XMP DJI', + VARS => { NO_ID => 1 }, + NOTES => 'XMP tags used by DJI for images from drones.', + AbsoluteAltitude => { Writable => 'real' }, + RelativeAltitude => { Writable => 'real' }, + GimbalRollDegree => { Writable => 'real' }, + GimbalYawDegree => { Writable => 'real' }, + GimbalPitchDegree => { Writable => 'real' }, + FlightRollDegree => { Writable => 'real' }, + FlightYawDegree => { Writable => 'real' }, + FlightPitchDegree => { Writable => 'real' }, + GpsLatitude => { + Name => 'GPSLatitude', + Writable => 'real', + Avoid => 1, + PrintConv => 'Image::ExifTool::GPS::ToDMS($self, $val, 1, "N")', + PrintConvInv => 'Image::ExifTool::GPS::ToDegrees($val, 1)', + }, + GpsLongtitude => { # (sic) + Name => 'GPSLongtitude', + Writable => 'real', + PrintConv => 'Image::ExifTool::GPS::ToDMS($self, $val, 1, "E")', + PrintConvInv => 'Image::ExifTool::GPS::ToDegrees($val, 1)', + }, + GpsLongitude => { #PH (NC) + Name => 'GPSLongitude', + Writable => 'real', + Avoid => 1, + PrintConv => 'Image::ExifTool::GPS::ToDMS($self, $val, 1, "E")', + PrintConvInv => 'Image::ExifTool::GPS::ToDegrees($val, 1)', + }, + FlightXSpeed => { Writable => 'real' }, + FlightYSpeed => { Writable => 'real' }, + FlightZSpeed => { Writable => 'real' }, + CamReverse => { }, # integer? + GimbalReverse => { }, # integer? + SelfData => { Groups => { 2 => 'Image' } }, + CalibratedFocalLength => { Writable => 'real', Groups => { 2 => 'Image' } }, + CalibratedOpticalCenterX => { Writable => 'real', Groups => { 2 => 'Image' } }, + CalibratedOpticalCenterY => { Writable => 'real', Groups => { 2 => 'Image' } }, + RtkFlag => { }, # integer? + RtkStdLon => { Writable => 'real' }, + RtkStdLat => { Writable => 'real' }, + RtkStdHgt => { Writable => 'real' }, + DewarpData => { Groups => { 2 => 'Image' } }, + DewarpFlag => { Groups => { 2 => 'Image' } }, # integer? + Latitude => { + Name => 'Latitude', + Writable => 'real', + PrintConv => 'Image::ExifTool::GPS::ToDMS($self, $val, 1, "N")', + PrintConvInv => 'Image::ExifTool::GPS::ToDegrees($val, 1)', + }, + Longitude => { + Name => 'Longitude', + Writable => 'real', + PrintConv => 'Image::ExifTool::GPS::ToDMS($self, $val, 1, "E")', + PrintConvInv => 'Image::ExifTool::GPS::ToDegrees($val, 1)', + }, +); + +__END__ + +=head1 NAME + +Image::ExifTool::DJI - DJI Phantom maker notes tags + +=head1 SYNOPSIS + +This module is loaded automatically by Image::ExifTool when required. + +=head1 DESCRIPTION + +This module contains definitions required by Image::ExifTool to interpret +the maker notes in images from some DJI Phantom drones. + +=head1 AUTHOR + +Copyright 2003-2019, Phil Harvey (phil at owl.phy.queensu.ca) + +This library is free software; you can redistribute it and/or modify it +under the same terms as Perl itself. + +=head1 SEE ALSO + +L<Image::ExifTool::TagNames/DJI Tags>, +L<Image::ExifTool(3pm)|Image::ExifTool> + +=cut diff --git a/lib/Image/ExifTool/DNG.pm b/lib/Image/ExifTool/DNG.pm new file mode 100644 index 0000000..cfaa90c --- /dev/null +++ b/lib/Image/ExifTool/DNG.pm @@ -0,0 +1,842 @@ +#------------------------------------------------------------------------------ +# File: DNG.pm +# +# Description: Read DNG-specific information +# +# Revisions: 01/09/2006 - P. Harvey Created +# +# References: 1) http://www.adobe.com/products/dng/ +#------------------------------------------------------------------------------ + +package Image::ExifTool::DNG; + +use strict; +use vars qw($VERSION); +use Image::ExifTool qw(:DataAccess :Utils); +use Image::ExifTool::Exif; +use Image::ExifTool::MakerNotes; +use Image::ExifTool::CanonRaw; + +$VERSION = '1.23'; + +sub ProcessOriginalRaw($$$); +sub ProcessAdobeData($$$); +sub ProcessAdobeMakN($$$); +sub ProcessAdobeCRW($$$); +sub ProcessAdobeRAF($$$); +sub ProcessAdobeMRW($$$); +sub ProcessAdobeSR2($$$); +sub ProcessAdobeIFD($$$); +sub WriteAdobeStuff($$$); + +# data in OriginalRawFileData +%Image::ExifTool::DNG::OriginalRaw = ( + GROUPS => { 2 => 'Image' }, + PROCESS_PROC => \&ProcessOriginalRaw, + NOTES => q{ + This table defines tags extracted from the DNG OriginalRawFileData + information. + }, + 0 => { Name => 'OriginalRawImage', Binary => 1 }, + 1 => { Name => 'OriginalRawResource', Binary => 1 }, + 2 => 'OriginalRawFileType', + 3 => 'OriginalRawCreator', + 4 => { Name => 'OriginalTHMImage', Binary => 1 }, + 5 => { Name => 'OriginalTHMResource', Binary => 1 }, + 6 => 'OriginalTHMFileType', + 7 => 'OriginalTHMCreator', +); + +%Image::ExifTool::DNG::AdobeData = ( #PH + GROUPS => { 0 => 'MakerNotes', 1 => 'AdobeDNG', 2 => 'Image' }, + PROCESS_PROC => \&ProcessAdobeData, + WRITE_PROC => \&WriteAdobeStuff, + NOTES => q{ + This information is found in the "Adobe" DNGPrivateData. + + The maker notes ('MakN') are processed by ExifTool, but some information may + have been lost by the Adobe DNG Converter. This is because the Adobe DNG + Converter (as of version 6.3) doesn't properly handle information referenced + from inside the maker notes that lies outside the original maker notes + block. This information is lost when only the maker note block is copied to + the DNG image. While this doesn't effect all makes of cameras, it is a + problem for some major brands such as Olympus and Sony. + + Other entries in this table represent proprietary information that is + extracted from the original RAW image and restructured to a different (but + still proprietary) Adobe format. + }, + MakN => [ ], # (filled in later) + 'CRW ' => { + Name => 'AdobeCRW', + SubDirectory => { + TagTable => 'Image::ExifTool::CanonRaw::Main', + ProcessProc => \&ProcessAdobeCRW, + WriteProc => \&WriteAdobeStuff, + }, + }, + 'MRW ' => { + Name => 'AdobeMRW', + SubDirectory => { + TagTable => 'Image::ExifTool::MinoltaRaw::Main', + ProcessProc => \&ProcessAdobeMRW, + WriteProc => \&WriteAdobeStuff, + }, + }, + 'SR2 ' => { + Name => 'AdobeSR2', + SubDirectory => { + TagTable => 'Image::ExifTool::Sony::SR2Private', + ProcessProc => \&ProcessAdobeSR2, + }, + }, + 'RAF ' => { + Name => 'AdobeRAF', + SubDirectory => { + TagTable => 'Image::ExifTool::FujiFilm::RAF', + ProcessProc => \&ProcessAdobeRAF, + }, + }, + 'Pano' => { + Name => 'AdobePano', + SubDirectory => { + TagTable => 'Image::ExifTool::PanasonicRaw::Main', + ProcessProc => \&ProcessAdobeIFD, + }, + }, + 'Koda' => { + Name => 'AdobeKoda', + SubDirectory => { + TagTable => 'Image::ExifTool::Kodak::IFD', + ProcessProc => \&ProcessAdobeIFD, + }, + }, + 'Leaf' => { + Name => 'AdobeLeaf', + SubDirectory => { + TagTable => 'Image::ExifTool::Leaf::SubIFD', + ProcessProc => \&ProcessAdobeIFD, + }, + }, +); + +# fill in maker notes +{ + my $tagInfo; + my $list = $Image::ExifTool::DNG::AdobeData{MakN}; + foreach $tagInfo (@Image::ExifTool::MakerNotes::Main) { + unless (ref $tagInfo eq 'HASH') { + push @$list, $tagInfo; + next; + } + my %copy = %$tagInfo; + delete $copy{Groups}; + delete $copy{GotGroups}; + delete $copy{Table}; + push @$list, \%copy; + } +} + +#------------------------------------------------------------------------------ +# Process DNG OriginalRawFileData information +# Inputs: 0) ExifTool object ref, 1) dirInfo ref, 2) tag table ref +# Returns: 1 on success, otherwise returns 0 and sets a Warning +sub ProcessOriginalRaw($$$) +{ + my ($et, $dirInfo, $tagTablePtr) = @_; + my $dataPt = $$dirInfo{DataPt}; + my $start = $$dirInfo{DirStart}; + my $end = $start + $$dirInfo{DirLen}; + my $pos = $start; + my ($index, $err); + + SetByteOrder('MM'); # pointers are always big-endian in this structure + for ($index=0; $index<8; ++$index) { + last if $pos + 4 > $end; + my $val = Get32u($dataPt, $pos); + $val or $pos += 4, next; # ignore zero values + my $tagInfo = $et->GetTagInfo($tagTablePtr, $index); + $tagInfo or $err = "Missing DNG tag $index", last; + if ($index & 0x02) { + # extract a simple file type (tags 2, 3, 6 and 7) + $val = substr($$dataPt, $pos, 4); + $pos += 4; + } else { + # extract a compressed data block (tags 0, 1, 4 and 5) + my $n = int(($val + 65535) / 65536); + my $hdrLen = 4 * ($n + 2); + $pos + $hdrLen > $end and $err = '', last; + my $tag = $$tagInfo{Name}; + # only extract this information if requested (because it takes time) + my $lcTag = lc $tag; + if (($$et{OPTIONS}{Binary} and not $$et{EXCL_TAG_LOOKUP}{$lcTag}) or + $$et{REQ_TAG_LOOKUP}{$lcTag}) + { + unless (eval { require Compress::Zlib }) { + $err = 'Install Compress::Zlib to extract compressed images'; + last; + } + my $i; + $val = ''; + my $p2 = $pos + Get32u($dataPt, $pos + 4); + for ($i=0; $i<$n; ++$i) { + # inflate this compressed block + my $p1 = $p2; + $p2 = $pos + Get32u($dataPt, $pos + ($i + 2) * 4); + if ($p1 >= $p2 or $p2 > $end) { + $err = 'Bad compressed RAW image'; + last; + } + my $buff = substr($$dataPt, $p1, $p2 - $p1); + my ($v2, $stat); + my $inflate = Compress::Zlib::inflateInit(); + $inflate and ($v2, $stat) = $inflate->inflate($buff); + if ($inflate and $stat == Compress::Zlib::Z_STREAM_END()) { + $val .= $v2; + } else { + $err = 'Error inflating compressed RAW image'; + last; + } + } + $pos = $p2; + } else { + $pos + $hdrLen > $end and $err = '', last; + my $len = Get32u($dataPt, $pos + $hdrLen - 4); + $pos + $len > $end and $err = '', last; + $val = substr($$dataPt, $pos + $hdrLen, $len - $hdrLen); + $val = "Binary data $len bytes"; + $pos += $len; # skip over this block + } + } + $et->FoundTag($tagInfo, $val); + } + $et->Warn($err || 'Bad OriginalRawFileData') if defined $err; + return 1; +} + +#------------------------------------------------------------------------------ +# Process Adobe DNGPrivateData directory +# Inputs: 0) ExifTool object ref, 1) dirInfo ref, 2) tag table ref +# Returns: 1 on success +sub ProcessAdobeData($$$) +{ + my ($et, $dirInfo, $tagTablePtr) = @_; + my $dataPt = $$dirInfo{DataPt}; + my $dataPos = $$dirInfo{DataPos}; + my $pos = $$dirInfo{DirStart}; + my $end = $$dirInfo{DirLen} + $pos; + my $outfile = $$dirInfo{OutFile}; + my $verbose = $et->Options('Verbose'); + my $htmlDump = $et->Options('HtmlDump'); + + return 0 unless $$dataPt =~ /^Adobe\0/; + unless ($outfile) { + $et->VerboseDir($dirInfo); + # don't parse makernotes if FastScan > 1 + my $fast = $et->Options('FastScan'); + return 1 if $fast and $fast > 1; + } + $htmlDump and $et->HDump($dataPos, 6, 'Adobe DNGPrivateData header'); + SetByteOrder('MM'); # always big endian + $pos += 6; + while ($pos + 8 <= $end) { + my ($tag, $size) = unpack("x${pos}a4N", $$dataPt); + $pos += 8; + last if $pos + $size > $end; + my $tagInfo = $$tagTablePtr{$tag}; + if ($htmlDump) { + my $name = "Adobe$tag"; + $name =~ tr/ //d; + $et->HDump($dataPos + $pos - 8, 8, "$name header", "Data Size: $size bytes"); + # dump non-EXIF format data + unless ($tag =~ /^(MakN|SR2 )$/) { + $et->HDump($dataPos + $pos, $size, "$name data"); + } + } + if ($verbose and not $outfile) { + $tagInfo or $et->VPrint(0, "$$et{INDENT}Unsupported DNGAdobeData record: ($tag)\n"); + $et->VerboseInfo($tag, + ref $tagInfo eq 'HASH' ? $tagInfo : undef, + DataPt => $dataPt, + DataPos => $dataPos, + Start => $pos, + Size => $size, + ); + } + my $value; + while ($tagInfo) { + my ($subTable, $subName, $processProc); + if (ref $tagInfo eq 'HASH') { + unless ($$tagInfo{SubDirectory}) { + if ($outfile) { + # copy value across to outfile + $value = substr($$dataPt, $pos, $size); + } else { + $et->HandleTag($tagTablePtr, $tag, substr($$dataPt, $pos, $size)); + } + last; + } + $subTable = GetTagTable($tagInfo->{SubDirectory}->{TagTable}); + $subName = $$tagInfo{Name}; + $processProc = $tagInfo->{SubDirectory}->{ProcessProc}; + } else { + $subTable = $tagTablePtr; + $subName = 'AdobeMakN'; + $processProc = \&ProcessAdobeMakN; + } + my %dirInfo = ( + Base => $$dirInfo{Base}, + DataPt => $dataPt, + DataPos => $dataPos, + DataLen => $$dirInfo{DataLen}, + DirStart => $pos, + DirLen => $size, + DirName => $subName, + ); + if ($outfile) { + $dirInfo{Proc} = $processProc; # WriteAdobeStuff() calls this to do the actual writing + $value = $et->WriteDirectory(\%dirInfo, $subTable, \&WriteAdobeStuff); + # use old directory if an error occurred + defined $value or $value = substr($$dataPt, $pos, $size); + } else { + # override process proc for MakN + $et->ProcessDirectory(\%dirInfo, $subTable, $processProc); + } + last; + } + if (defined $value and length $value) { + # add "Adobe" header if necessary + $$outfile = "Adobe\0" unless $$outfile and length $$outfile; + $$outfile .= $tag . pack('N', length $value) . $value; + $$outfile .= "\0" if length($value) & 0x01; # pad if necessary + } + $pos += $size; + ++$pos if $size & 0x01; # (darn padding) + } + $pos == $end or $et->Warn("$pos $end Adobe private data is corrupt"); + return 1; +} + +#------------------------------------------------------------------------------ +# Process Adobe CRW directory +# Inputs: 0) ExifTool object ref, 1) dirInfo ref, 2) tag table ref +# Returns: 1 on success, otherwise returns 0 and sets a Warning +# Notes: data has 4 byte header (2 for byte order and 2 for entry count) +# - this routine would be as simple as ProcessAdobeMRW() below if Adobe hadn't +# pulled the bonehead move of reformatting the CRW information +sub ProcessAdobeCRW($$$) +{ + my ($et, $dirInfo, $tagTablePtr) = @_; + my $dataPt = $$dirInfo{DataPt}; + my $start = $$dirInfo{DirStart}; + my $end = $start + $$dirInfo{DirLen}; + my $verbose = $et->Options('Verbose'); + my $buildMakerNotes = $et->Options('MakerNotes'); + my $outfile = $$dirInfo{OutFile}; + my ($newTags, $oldChanged); + + SetByteOrder('MM'); # always big endian + return 0 if $$dirInfo{DirLen} < 4; + my $byteOrder = substr($$dataPt, $start, 2); + return 0 unless $byteOrder =~ /^(II|MM)$/; + + # initialize maker note data if building maker notes + $buildMakerNotes and Image::ExifTool::CanonRaw::InitMakerNotes($et); + + my $entries = Get16u($dataPt, $start + 2); + my $pos = $start + 4; + $et->VerboseDir($dirInfo, $entries) unless $outfile; + if ($outfile) { + # get hash of new tags + $newTags = $et->GetNewTagInfoHash($tagTablePtr); + $$outfile = substr($$dataPt, $start, 4); + $oldChanged = $$et{CHANGED}; + } + # loop through entries in Adobe CRW information + my $index; + for ($index=0; $index<$entries; ++$index) { + last if $pos + 6 > $end; + my $tag = Get16u($dataPt, $pos); + my $size = Get32u($dataPt, $pos + 2); + $pos += 6; + last if $pos + $size > $end; + my $value = substr($$dataPt, $pos, $size); + my $tagID = $tag & 0x3fff; + my $tagType = ($tag >> 8) & 0x38; # get tag type + my $format = $Image::ExifTool::CanonRaw::crwTagFormat{$tagType}; + my $count; + my $tagInfo = $et->GetTagInfo($tagTablePtr, $tagID, \$value); + if ($tagInfo) { + $format = $$tagInfo{Format} if $$tagInfo{Format}; + $count = $$tagInfo{Count}; + } + # set count to 1 by default for values that were in the directory entry + if (not defined $count and $tag & 0x4000 and $format and $format ne 'string') { + $count = 1; + } + # set count from tagInfo count if necessary + if ($format and not $count) { + # set count according to format and size + my $fnum = $Image::ExifTool::Exif::formatNumber{$format}; + my $fsiz = $Image::ExifTool::Exif::formatSize[$fnum]; + $count = int($size / $fsiz); + } + $format or $format = 'undef'; + SetByteOrder($byteOrder); + my $val = ReadValue(\$value, 0, $format, $count, $size); + if ($outfile) { + if ($tagInfo) { + my $subdir = $$tagInfo{SubDirectory}; + if ($subdir and $$subdir{TagTable}) { + my $name = $$tagInfo{Name}; + my $newTagTable = GetTagTable($$subdir{TagTable}); + return 0 unless $newTagTable; + my $subdirStart = 0; + #### eval Start () + $subdirStart = eval $$subdir{Start} if $$subdir{Start}; + my $dirData = \$value; + my %subdirInfo = ( + Name => $name, + DataPt => $dirData, + DataLen => $size, + DirStart => $subdirStart, + DirLen => $size - $subdirStart, + Parent => $$dirInfo{DirName}, + ); + #### eval Validate ($dirData, $subdirStart, $size) + if (defined $$subdir{Validate} and not eval $$subdir{Validate}) { + $et->Warn("Invalid $name data"); + } else { + $subdir = $et->WriteDirectory(\%subdirInfo, $newTagTable); + if (defined $subdir and length $subdir) { + if ($subdirStart) { + # add header before data directory + $value = substr($value, 0, $subdirStart) . $subdir; + } else { + $value = $subdir; + } + } + } + } elsif ($$newTags{$tagID}) { + my $nvHash = $et->GetNewValueHash($tagInfo); + if ($et->IsOverwriting($nvHash, $val)) { + my $newVal = $et->GetNewValue($nvHash); + my $verboseVal; + $verboseVal = $newVal if $verbose > 1; + # convert to specified format if necessary + if (defined $newVal and $format) { + $newVal = WriteValue($newVal, $format, $count); + } + if (defined $newVal) { + $et->VerboseValue("- CanonRaw:$$tagInfo{Name}", $value); + $et->VerboseValue("+ CanonRaw:$$tagInfo{Name}", $verboseVal); + $value = $newVal; + ++$$et{CHANGED}; + } + } + } + } + # write out new value (always big-endian) + SetByteOrder('MM'); + # (verified that there is no padding here) + $$outfile .= Set16u($tag) . Set32u(length($value)) . $value; + } else { + $et->HandleTag($tagTablePtr, $tagID, $val, + Index => $index, + DataPt => $dataPt, + DataPos => $$dirInfo{DataPos}, + Start => $pos, + Size => $size, + TagInfo => $tagInfo, + ); + if ($buildMakerNotes) { + # build maker notes information if requested + Image::ExifTool::CanonRaw::BuildMakerNotes($et, $tagID, $tagInfo, + \$value, $format, $count); + } + } + # (we lost the directory structure, but the second tag 0x0805 + # should be in the ImageDescription directory) + $$et{DIR_NAME} = 'ImageDescription' if $tagID == 0x0805; + SetByteOrder('MM'); + $pos += $size; + } + if ($outfile and (not defined $$outfile or $index != $entries or + $$et{CHANGED} == $oldChanged)) + { + $$et{CHANGED} = $oldChanged; # nothing changed + undef $$outfile; # rewrite old directory + } + if ($index != $entries) { + $et->Warn('Truncated CRW notes'); + } elsif ($pos < $end) { + $et->Warn($end-$pos . ' extra bytes at end of CRW notes'); + } + # finish building maker notes if necessary + if ($buildMakerNotes) { + SetByteOrder($byteOrder); + Image::ExifTool::CanonRaw::SaveMakerNotes($et); + } + return 1; +} + +#------------------------------------------------------------------------------ +# Process Adobe MRW directory +# Inputs: 0) ExifTool object ref, 1) dirInfo ref, 2) tag table ref +# Returns: 1 on success, otherwise returns 0 and sets a Warning +# Notes: data has 4 byte header (2 for byte order and 2 for entry count) +sub ProcessAdobeMRW($$$) +{ + my ($et, $dirInfo, $tagTablePtr) = @_; + my $dataPt = $$dirInfo{DataPt}; + my $dirLen = $$dirInfo{DirLen}; + my $dirStart = $$dirInfo{DirStart}; + my $outfile = $$dirInfo{OutFile}; + + # construct fake MRW file + my $buff = "\0MRM" . pack('N', $dirLen - 4); + # ignore leading byte order and directory count words + $buff .= substr($$dataPt, $dirStart + 4, $dirLen - 4); + my $raf = new File::RandomAccess(\$buff); + my %dirInfo = ( RAF => $raf, OutFile => $outfile ); + my $rtnVal = Image::ExifTool::MinoltaRaw::ProcessMRW($et, \%dirInfo); + if ($outfile and defined $$outfile and length $$outfile) { + # remove MRW header and add Adobe header + $$outfile = substr($$dataPt, $dirStart, 4) . substr($$outfile, 8); + } + return $rtnVal; +} + +#------------------------------------------------------------------------------ +# Process Adobe RAF directory +# Inputs: 0) ExifTool object ref, 1) dirInfo ref, 2) tag table ref +# Returns: 1 on success, otherwise returns 0 and sets a Warning +sub ProcessAdobeRAF($$$) +{ + my ($et, $dirInfo, $tagTablePtr) = @_; + return 0 if $$dirInfo{OutFile}; # (can't write this yet) + my $dataPt = $$dirInfo{DataPt}; + my $pos = $$dirInfo{DirStart}; + my $dirEnd = $$dirInfo{DirLen} + $pos; + my ($readIt, $warn); + + # set byte order according to first 2 bytes of Adobe RAF data + if ($pos + 2 <= $dirEnd and SetByteOrder(substr($$dataPt, $pos, 2))) { + $pos += 2; + } else { + $et->Warn('Invalid DNG RAF data'); + return 0; + } + $et->VerboseDir($dirInfo); + # make fake RAF object for processing (same acronym, different meaning) + my $raf = new File::RandomAccess($dataPt); + my $num = ''; + # loop through all records in Adobe RAF data: + # 0 - RAF table (not processed) + # 1 - first RAF directory + # 2 - second RAF directory (if available) + for (;;) { + last if $pos + 4 > $dirEnd; + my $len = Get32u($dataPt, $pos); + $pos += 4 + $len; # step to next entry in Adobe RAF record + $len or last; # ends with an empty entry + $readIt or $readIt = 1, next; # ignore first entry (RAF table) + my %dirInfo = ( + RAF => $raf, + DirStart => $pos - $len, + ); + $$et{SET_GROUP1} = "RAF$num"; + $et->ProcessDirectory(\%dirInfo, $tagTablePtr) or $warn = 1; + delete $$et{SET_GROUP1}; + $num = ($num || 1) + 1; + } + $warn and $et->Warn('Possibly corrupt RAF information'); + return 1; +} + +#------------------------------------------------------------------------------ +# Process Adobe SR2 directory +# Inputs: 0) ExifTool object ref, 1) dirInfo ref, 2) tag table ref +# Returns: 1 on success, otherwise returns 0 and sets a Warning +# Notes: data has 6 byte header (2 for byte order and 4 for original offset) +sub ProcessAdobeSR2($$$) +{ + my ($et, $dirInfo, $tagTablePtr) = @_; + return 0 if $$dirInfo{OutFile}; # (can't write this yet) + my $dataPt = $$dirInfo{DataPt}; + my $start = $$dirInfo{DirStart}; + my $len = $$dirInfo{DirLen}; + + return 0 if $len < 6; + SetByteOrder('MM'); + my $originalPos = Get32u($dataPt, $start + 2); + return 0 unless SetByteOrder(substr($$dataPt, $start, 2)); + + $et->VerboseDir($dirInfo); + my $dataPos = $$dirInfo{DataPos}; + my $dirStart = $start + 6; # pointer to maker note directory + my $dirLen = $len - 6; + + # initialize subdirectory information + my $fix = $dataPos + $dirStart - $originalPos; + my %subdirInfo = ( + DirName => 'AdobeSR2', + Base => $$dirInfo{Base} + $fix, + DataPt => $dataPt, + DataPos => $dataPos - $fix, + DataLen => $$dirInfo{DataLen}, + DirStart => $dirStart, + DirLen => $dirLen, + Parent => $$dirInfo{DirName}, + ); + if ($et->Options('HtmlDump')) { + $et->HDump($dataPos + $start, 6, 'Adobe SR2 data'); + } + # parse the SR2 directory + $et->ProcessDirectory(\%subdirInfo, $tagTablePtr); + return 1; +} + +#------------------------------------------------------------------------------ +# Process Adobe-mutilated IFD directory +# Inputs: 0) ExifTool object ref, 1) dirInfo ref, 2) tag table ref +# Returns: 1 on success, otherwise returns 0 and sets a Warning +# Notes: data has 2 byte header (byte order of the data) +sub ProcessAdobeIFD($$$) +{ + my ($et, $dirInfo, $tagTablePtr) = @_; + return 0 if $$dirInfo{OutFile}; # (can't write this yet) + my $dataPt = $$dirInfo{DataPt}; + my $pos = $$dirInfo{DirStart}; + my $dataPos = $$dirInfo{DataPos}; + + return 0 if $$dirInfo{DirLen} < 4; + my $dataOrder = substr($$dataPt, $pos, 2); + return 0 unless SetByteOrder($dataOrder); # validate byte order of data + + # parse the mutilated IFD. This is similar to a TIFF IFD, except: + # - data follows directly after Count entry in IFD + # - byte order of IFD entires is always big-endian, but byte order of data changes + SetByteOrder('MM'); # IFD structure is always big-endian + my $entries = Get16u($dataPt, $pos + 2); + $et->VerboseDir($dirInfo, $entries); + $pos += 4; + + my $end = $pos + $$dirInfo{DirLen}; + my $index; + for ($index=0; $index<$entries; ++$index) { + last if $pos + 8 > $end; + SetByteOrder('MM'); # directory entries always big-endian (doh!) + my $tagID = Get16u($dataPt, $pos); + my $format = Get16u($dataPt, $pos+2); + my $count = Get32u($dataPt, $pos+4); + if ($format < 1 or $format > 13) { + # warn unless the IFD was just padded with zeros + $format and $et->Warn( + sprintf("Unknown format ($format) for $$dirInfo{DirName} tag 0x%x",$tagID)); + return 0; # must be corrupted + } + my $size = $Image::ExifTool::Exif::formatSize[$format] * $count; + last if $pos + 8 + $size > $end; + my $formatStr = $Image::ExifTool::Exif::formatName[$format]; + SetByteOrder($dataOrder); # data stored in native order + my $val = ReadValue($dataPt, $pos + 8, $formatStr, $count, $size); + $et->HandleTag($tagTablePtr, $tagID, $val, + Index => $index, + DataPt => $dataPt, + DataPos => $dataPos, + Start => $pos + 8, + Size => $size + ); + $pos += 8 + $size; + } + if ($index < $entries) { + $et->Warn("Truncated $$dirInfo{DirName} directory"); + return 0; + } + return 1; +} + +#------------------------------------------------------------------------------ +# Process Adobe MakerNotes directory +# Inputs: 0) ExifTool object ref, 1) dirInfo ref, 2) tag table ref +# Returns: 1 on success, otherwise returns 0 and sets a Warning +# Notes: data has 6 byte header (2 for byte order and 4 for original offset) +# --> or 18 bytes for DNG converted from JPG by Adobe Camera Raw! +sub ProcessAdobeMakN($$$) +{ + my ($et, $dirInfo, $tagTablePtr) = @_; + my $dataPt = $$dirInfo{DataPt}; + my $start = $$dirInfo{DirStart}; + my $len = $$dirInfo{DirLen}; + my $outfile = $$dirInfo{OutFile}; + + return 0 if $len < 6; + SetByteOrder('MM'); + my $originalPos = Get32u($dataPt, $start + 2); + return 0 unless SetByteOrder(substr($$dataPt, $start, 2)); + + $et->VerboseDir($dirInfo) unless $outfile; + my $dataPos = $$dirInfo{DataPos}; + my $hdrLen = 6; + + # hack for extra 12 bytes in MakN header of JPEG converted to DNG by Adobe Camera Raw + # (4 bytes "00 00 00 01" followed by 8 unknown bytes) + $hdrLen += 12 if $len >= 18 and substr($$dataPt, $start+6, 4) eq "\0\0\0\x01"; + + my $dirStart = $start + $hdrLen; # pointer to maker note directory + my $dirLen = $len - $hdrLen; + + my $hdr = substr($$dataPt, $dirStart, $dirLen < 48 ? $dirLen : 48); + my $tagInfo = $et->GetTagInfo($tagTablePtr, 'MakN', \$hdr); + return 0 unless $tagInfo and $$tagInfo{SubDirectory}; + my $subdir = $$tagInfo{SubDirectory}; + my $subTable = GetTagTable($$subdir{TagTable}); + # initialize subdirectory information + my %subdirInfo = ( + DirName => 'MakerNotes', + Name => $$tagInfo{Name}, # needed for maker notes verbose dump + Base => $$dirInfo{Base}, + DataPt => $dataPt, + DataPos => $dataPos, + DataLen => $$dirInfo{DataLen}, + DirStart => $dirStart, + DirLen => $dirLen, + TagInfo => $tagInfo, + FixBase => $$subdir{FixBase}, + EntryBased=> $$subdir{EntryBased}, + Parent => $$dirInfo{DirName}, + ); + # look for start of maker notes IFD + my $loc = Image::ExifTool::MakerNotes::LocateIFD($et,\%subdirInfo); + unless (defined $loc) { + $et->Warn('Maker notes could not be parsed'); + return 0; + } + if ($et->Options('HtmlDump')) { + $et->HDump($dataPos + $start, $hdrLen, 'Adobe MakN data'); + $et->HDump($dataPos + $dirStart, $loc, "$$tagInfo{Name} header") if $loc; + } + + my $fix = 0; + unless ($$subdir{Base}) { + # adjust base offset for current maker note position + $fix = $dataPos + $dirStart - $originalPos; + $subdirInfo{Base} += $fix; + $subdirInfo{DataPos} -= $fix; + } + if ($outfile) { + # rewrite the maker notes directory + my $fixup = $subdirInfo{Fixup} = new Image::ExifTool::Fixup; + my $oldChanged = $$et{CHANGED}; + my $buff = $et->WriteDirectory(\%subdirInfo, $subTable); + # nothing to do if error writing directory or nothing changed + unless (defined $buff and $$et{CHANGED} != $oldChanged) { + $$et{CHANGED} = $oldChanged; + return 1; + } + # deleting maker notes if directory is empty + unless (length $buff) { + $$outfile = ''; + return 1; + } + # apply a one-time fixup to offsets + if ($subdirInfo{Relative}) { + # shift all offsets to be relative to new base + my $baseShift = $dataPos + $dirStart + $$dirInfo{Base} - $subdirInfo{Base}; + $fixup->{Shift} += $baseShift; + } else { + # shift offsets to position of original maker notes + $fixup->{Shift} += $originalPos; + } + # if we wrote the directory as a block the header is already included + $loc = 0 if $subdirInfo{BlockWrite}; + $fixup->{Shift} += $loc; # adjust for makernotes header + $fixup->ApplyFixup(\$buff); # fix up pointer offsets + # get copy of original Adobe header (6 or 18) and makernotes header ($loc) + my $header = substr($$dataPt, $start, $hdrLen + $loc); + # add Adobe and makernotes headers to new directory + $$outfile = $header . $buff; + } else { + # parse the maker notes directory + $et->ProcessDirectory(\%subdirInfo, $subTable, $$subdir{ProcessProc}); + # extract maker notes as a block if specified + if ($et->Options('MakerNotes') or + $$et{REQ_TAG_LOOKUP}{lc($$tagInfo{Name})}) + { + my $val; + if ($$tagInfo{MakerNotes}) { + $subdirInfo{Base} = $$dirInfo{Base} + $fix; + $subdirInfo{DataPos} = $dataPos - $fix; + $subdirInfo{DirStart} = $dirStart; + $subdirInfo{DirLen} = $dirLen; + # rebuild the maker notes to identify all offsets that require fixing up + $val = Image::ExifTool::Exif::RebuildMakerNotes($et, \%subdirInfo, $subTable); + if (not defined $val and $dirLen > 4) { + $et->Warn('Error rebuilding maker notes (may be corrupt)'); + } + } else { + # extract this directory as a block if specified + return 1 unless $$tagInfo{Writable}; + } + $val = substr($$dataPt, 20) unless defined $val; + $et->FoundTag($tagInfo, $val); + } + } + return 1; +} + +#------------------------------------------------------------------------------ +# Write Adobe information (calls appropriate ProcessProc to do the actual work) +# Inputs: 0) ExifTool object ref, 1) source dirInfo ref, 2) tag table ref +# Returns: new data block (may be empty if directory is deleted) or undef on error +sub WriteAdobeStuff($$$) +{ + my ($et, $dirInfo, $tagTablePtr) = @_; + $et or return 1; # allow dummy access + my $proc = $$dirInfo{Proc} || \&ProcessAdobeData; + my $buff; + $$dirInfo{OutFile} = \$buff; + &$proc($et, $dirInfo, $tagTablePtr) or undef $buff; + return $buff; +} + +1; # end + +__END__ + +=head1 NAME + +Image::ExifTool::DNG.pm - Read DNG-specific information + +=head1 SYNOPSIS + +This module is used by Image::ExifTool + +=head1 DESCRIPTION + +This module contains routines required by Image::ExifTool to process +information in DNG (Digital Negative) images. + +=head1 AUTHOR + +Copyright 2003-2019, Phil Harvey (phil at owl.phy.queensu.ca) + +This library is free software; you can redistribute it and/or modify it +under the same terms as Perl itself. + +=head1 REFERENCES + +=over 4 + +=item L<http://www.adobe.com/products/dng/> + +=back + +=head1 SEE ALSO + +L<Image::ExifTool::TagNames/DNG Tags>, +L<Image::ExifTool::TagNames/EXIF Tags>, +L<Image::ExifTool(3pm)|Image::ExifTool> + +=cut diff --git a/lib/Image/ExifTool/DPX.pm b/lib/Image/ExifTool/DPX.pm new file mode 100644 index 0000000..5a54a79 --- /dev/null +++ b/lib/Image/ExifTool/DPX.pm @@ -0,0 +1,182 @@ +#------------------------------------------------------------------------------ +# File: DPX.pm +# +# Description: Read DPX meta information +# +# Revisions: 2013-09-19 - P. Harvey created +# +# References: 1) http://www.cineon.com/ff_draft.php +#------------------------------------------------------------------------------ + +package Image::ExifTool::DPX; + +use strict; +use vars qw($VERSION); +use Image::ExifTool qw(:DataAccess :Utils); + +$VERSION = '1.03'; + +# DPX tags +%Image::ExifTool::DPX::Main = ( + PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData, + GROUPS => { 0 => 'File', 1 => 'File', 2 => 'Image' }, + NOTES => 'Tags extracted from DPX (Digital Picture Exchange) images.', + 0 => { Name => 'ByteOrder', Format => 'undef[4]', PrintConv => { SDPX => 'Big-endian', XPDS => 'Little-endian' } }, + 8 => { Name => 'HeaderVersion', Format => 'string[8]' }, + # 24 => { Name => 'GenericHeaderSize', Format => 'int32u' }, # = 1664 + # 28 => { Name => 'IndustryStandardHeaderSize', Format => 'int32u' }, # = 384 + 16 => { Name => 'DPXFileSize', Format => 'int32u' }, + 20 => { Name => 'DittoKey', Format => 'int32u', PrintConv => { 0 => 'Same', 1 => 'New' } }, + 36 => { Name => 'ImageFileName', Format => 'string[100]' }, + 136 => { + Name => 'CreateDate', + Format => 'string[24]', + Groups => { 2 => 'Time' }, + ValueConv => '$val =~ s/(\d{4}:\d{2}:\d{2}):/$1 /; $val', + PrintConv => '$self->ConvertDateTime($val)', + }, + 160 => { Name => 'Creator', Format => 'string[100]', Groups => { 2 => 'Author' } }, + 260 => { Name => 'Project', Format => 'string[200]' }, + 460 => { Name => 'Copyright', Format => 'string[200]', Groups => { 2 => 'Author' } }, + 660 => { Name => 'EncryptionKey', Format => 'int32u', PrintConv => 'sprintf("%.8x",$val)' }, + 768 => { + Name => 'Orientation', + Format => 'int16u', + PrintConv => { + 0 => 'Horizontal (normal)', + 1 => 'Mirror vertical', + 2 => 'Mirror horizontal', + 3 => 'Rotate 180', + 4 => 'Mirror horizontal and rotate 270 CW', + 5 => 'Rotate 90 CW', + 6 => 'Rotate 270 CW', + 7 => 'Mirror horizontal and rotate 90 CW', + }, + }, + 770 => { Name => 'ImageElements', Format => 'int16u' }, + 772 => { Name => 'ImageWidth', Format => 'int32u' }, + 776 => { Name => 'ImageHeight', Format => 'int32u' }, + 780 => { Name => 'DataSign', Format => 'int32u', PrintConv => { 0 => 'Unsigned', 1 => 'Signed' } }, + 800 => { + Name => 'ComponentsConfiguration', + Format => 'int8u', + PrintConv => { + 0 => 'User-defined single component', + 1 => 'Red (R)', + 2 => 'Green (G)', + 3 => 'Blue (B)', + 4 => 'Alpha (matte)', + 6 => 'Luminance (Y)', + 7 => 'Chrominance (Cb, Cr, subsampled by two)', + 8 => 'Depth (Z)', + 9 => 'Composite video', + 50 => 'R, G, B', + 51 => 'R, G, B, Alpha', + 52 => 'Alpha, B, G, R', + 100 => 'Cb, Y, Cr, Y (4:2:2)', + 101 => 'Cb, Y, A, Cr, Y, A (4:2:2:4)', + 102 => 'Cb, Y, Cr (4:4:4)', + 103 => 'Cb, Y, Cr, A (4:4:4:4)', + 150 => 'User-defined 2 component element', + 151 => 'User-defined 3 component element', + 152 => 'User-defined 4 component element', + 153 => 'User-defined 5 component element', + 154 => 'User-defined 6 component element', + 155 => 'User-defined 7 component element', + 156 => 'User-defined 8 component element', + }, + }, + 803 => { Name => 'BitDepth', Format => 'int8u' }, + 820 => { Name => 'ImageDescription', Format => 'string[32]' }, + 892 => { Name => 'Image2Description', Format => 'string[32]', RawConv => '$val=~/[^\xff]/ ? $val : undef' }, + 964 => { Name => 'Image3Description', Format => 'string[32]', RawConv => '$val=~/[^\xff]/ ? $val : undef' }, + 1036=> { Name => 'Image4Description', Format => 'string[32]', RawConv => '$val=~/[^\xff]/ ? $val : undef' }, + 1108=> { Name => 'Image5Description', Format => 'string[32]', RawConv => '$val=~/[^\xff]/ ? $val : undef' }, + 1180=> { Name => 'Image6Description', Format => 'string[32]', RawConv => '$val=~/[^\xff]/ ? $val : undef' }, + 1252=> { Name => 'Image7Description', Format => 'string[32]', RawConv => '$val=~/[^\xff]/ ? $val : undef' }, + 1324=> { Name => 'Image8Description', Format => 'string[32]', RawConv => '$val=~/[^\xff]/ ? $val : undef' }, + # 1408=> { Name => 'XOffset', Format => 'int32u' }, + # 1412=> { Name => 'YOffset', Format => 'int32u' }, + # 1416=> { Name => 'XCenter', Format => 'float' }, + # 1420=> { Name => 'YCenter', Format => 'float' }, + # 1424=> { Name => 'XOriginalSize', Format => 'int32u' }, + # 1428=> { Name => 'YOriginalSize', Format => 'int32u' }, + 1432=> { Name => 'SourceFileName', Format => 'string[100]' }, + 1532=> { Name => 'SourceCreateDate', Format => 'string[24]' }, + 1556=> { Name => 'InputDeviceName', Format => 'string[32]' }, + 1588=> { Name => 'InputDeviceSerialNumber', Format => 'string[32]' }, + # 1620=> { Name => 'AspectRatio', Format => 'int32u' }, + 1724 => { Name => 'FrameRate', Format => 'float' }, + 1732 => { Name => 'FrameID', Format => 'string[32]' }, + 1764 => { Name => 'SlateInformation', Format => 'string[100]' }, + 1972 => { Name => 'Reserved5', Format => 'string[76]', Unknown => 1 }, + 2048 => { Name => 'UserID', Format => 'string[32]' }, +); + +#------------------------------------------------------------------------------ +# Extract EXIF information from a DPX image +# Inputs: 0) ExifTool object reference, 1) dirInfo reference +# Returns: 1 on success, 0 if this wasn't a valid DPX file +sub ProcessDPX($$) +{ + my ($et, $dirInfo) = @_; + my $raf = $$dirInfo{RAF}; + my $buff; + + # verify this is a valid DPX file + return 0 unless $raf->Read($buff, 2080) == 2080; + return 0 unless $buff =~ /^(SDPX|XPDS)/; + SetByteOrder($1 eq 'SDPX' ? 'MM' : 'II'); + $et->SetFileType(); # set the FileType tag + my $hdrLen = Get32u(\$buff,24) + Get32u(\$buff,28); + $hdrLen == 2048 or $et->Warn("Unexpected DPX header length ($hdrLen)"); + my %dirInfo = ( + DataPt => \$buff, + DirStart => 0, + DirLen => length($buff), + ); + my $tagTablePtr = GetTagTable('Image::ExifTool::DPX::Main'); + $et->ProcessDirectory(\%dirInfo, $tagTablePtr); + + return 1; +} + +1; # end + +__END__ + +=head1 NAME + +Image::ExifTool::DPX - Read DPX meta information + +=head1 SYNOPSIS + +This module is used by Image::ExifTool + +=head1 DESCRIPTION + +This module contains definitions required by Image::ExifTool to read +metadata from DPX (Digital Picture Exchange) images. + +=head1 AUTHOR + +Copyright 2003-2019, Phil Harvey (phil at owl.phy.queensu.ca) + +This library is free software; you can redistribute it and/or modify it +under the same terms as Perl itself. + +=head1 REFERENCES + +=over 4 + +=item L<http://www.cineon.com/ff_draft.php> + +=back + +=head1 SEE ALSO + +L<Image::ExifTool::TagNames/DPX Tags>, +L<Image::ExifTool(3pm)|Image::ExifTool> + +=cut + diff --git a/lib/Image/ExifTool/DV.pm b/lib/Image/ExifTool/DV.pm new file mode 100644 index 0000000..66fd6c9 --- /dev/null +++ b/lib/Image/ExifTool/DV.pm @@ -0,0 +1,319 @@ +#------------------------------------------------------------------------------ +# File: DV.pm +# +# Description: Read DV meta information +# +# Revisions: 2010/12/24 - P. Harvey Created +# +# References: 1) http://www.ffmpeg.org/ +# 2) http://dvswitch.alioth.debian.org/wiki/DV_format/ +#------------------------------------------------------------------------------ + +package Image::ExifTool::DV; + +use strict; +use vars qw($VERSION); +use Image::ExifTool qw(:DataAccess :Utils); + +$VERSION = '1.01'; + +# DV profiles (ref 1) +my @dvProfiles = ( + { + DSF => 0, + VideoSType => 0x0, + FrameSize => 120000, + VideoFormat => 'IEC 61834, SMPTE-314M - 525/60 (NTSC)', + VideoScanType => 'Progressive', + Colorimetry => '4:1:1', + FrameRate => 30000/1001, + ImageHeight => 480, + ImageWidth => 720, + },{ + DSF => 1, + VideoSType => 0x0, + FrameSize => 144000, + VideoFormat => 'IEC 61834 - 625/50 (PAL)', + VideoScanType => 'Progressive', + Colorimetry => '4:2:0', + FrameRate => 25/1, + ImageHeight => 576, + ImageWidth => 720, + },{ + DSF => 1, + VideoSType => 0x0, + FrameSize => 144000, + VideoFormat => 'SMPTE-314M - 625/50 (PAL)', + VideoScanType => 'Progressive', + Colorimetry => '4:1:1', + FrameRate => 25/1, + ImageHeight => 576, + ImageWidth => 720, + },{ + DSF => 0, + VideoSType => 0x4, + FrameSize => 240000, + VideoFormat => 'DVCPRO50: SMPTE-314M - 525/60 (NTSC) 50 Mbps', + VideoScanType => 'Progressive', + Colorimetry => '4:2:2', + FrameRate => 30000/1001, + ImageHeight => 480, + ImageWidth => 720, + },{ + DSF => 1, + VideoSType => 0x4, + FrameSize => 288000, + VideoFormat => 'DVCPRO50: SMPTE-314M - 625/50 (PAL) 50 Mbps', + VideoScanType => 'Progressive', + Colorimetry => '4:2:2', + FrameRate => 25/1, + ImageHeight => 576, + ImageWidth => 720, + },{ + DSF => 0, + VideoSType => 0x14, + FrameSize => 480000, + VideoFormat => 'DVCPRO HD: SMPTE-370M - 1080i60 100 Mbps', + VideoScanType => 'Interlaced', + Colorimetry => '4:2:2', + FrameRate => 30000/1001, + ImageHeight => 1080, + ImageWidth => 1280, + },{ + DSF => 1, + VideoSType => 0x14, + FrameSize => 576000, + VideoFormat => 'DVCPRO HD: SMPTE-370M - 1080i50 100 Mbps', + VideoScanType => 'Interlaced', + Colorimetry => '4:2:2', + FrameRate => 25/1, + ImageHeight => 1080, + ImageWidth => 1440, + },{ + DSF => 0, + VideoSType => 0x18, + FrameSize => 240000, + VideoFormat => 'DVCPRO HD: SMPTE-370M - 720p60 100 Mbps', + VideoScanType => 'Progressive', + Colorimetry => '4:2:2', + FrameRate => 60000/1001, + ImageHeight => 720, + ImageWidth => 960, + },{ + DSF => 1, + VideoSType => 0x18, + FrameSize => 288000, + VideoFormat => 'DVCPRO HD: SMPTE-370M - 720p50 100 Mbps', + VideoScanType => 'Progressive', + Colorimetry => '4:2:2', + FrameRate => 50/1, + ImageHeight => 720, + ImageWidth => 960, + },{ + DSF => 1, + VideoSType => 0x1, + FrameSize => 144000, + VideoFormat => 'IEC 61883-5 - 625/50 (PAL)', + VideoScanType => 'Progressive', + Colorimetry => '4:2:0', + FrameRate => 25/1, + ImageHeight => 576, + ImageWidth => 720, + }, +); + +# tags to extract, in the order we want to extract them +my @dvTags = ( + 'DateTimeOriginal', 'ImageWidth', 'ImageHeight', 'Duration', + 'TotalBitrate', 'VideoFormat', 'VideoScanType', 'FrameRate', + 'AspectRatio', 'Colorimetry', 'AudioChannels', 'AudioSampleRate', + 'AudioBitsPerSample', +); + +# DV tags +%Image::ExifTool::DV::Main = ( + GROUPS => { 2 => 'Video' }, + VARS => { NO_ID => 1 }, + NOTES => 'The following tags are extracted from DV videos.', + DateTimeOriginal => { + Groups => { 2 => 'Time' }, + PrintConv => '$self->ConvertDateTime($val)', + }, + ImageWidth => { }, + ImageHeight => { }, + Duration => { PrintConv => 'ConvertDuration($val)' }, + TotalBitrate => { PrintConv => 'ConvertBitrate($val)' }, + VideoFormat => { }, + VideoScanType => { }, + FrameRate => { PrintConv => 'int($val * 1000 + 0.5) / 1000' }, + AspectRatio => { }, + Colorimetry => { }, + AudioChannels => { Groups => { 2 => 'Audio' } }, + AudioSampleRate => { Groups => { 2 => 'Audio' } }, + AudioBitsPerSample => { Groups => { 2 => 'Audio' } }, +); + +#------------------------------------------------------------------------------ +# Read information in a DV file (ref 1) +# Inputs: 0) ExifTool ref, 1) dirInfo ref +# Returns: 1 on success, 0 if this wasn't a valid DV file +sub ProcessDV($$) +{ + my ($et, $dirInfo) = @_; + local $_; + my $raf = $$dirInfo{RAF}; + my ($buff, $start, $profile, $tag, $i, $j); + + $raf->Read($buff, 12000) or return 0; + if ($buff =~ /\x1f\x07\0[\x3f\xbf]/sg) { + $start = pos($buff) - 4; + } else { + while ($buff =~ /[\0\xff]\x3f\x07\0.{76}\xff\x3f\x07\x01/sg) { + next if pos($buff) - 163 < 0; + $start = pos($buff) - 163; + last; + } + return 0 unless defined $start; + } + my $len = length $buff; + # must at least have a full DIF header + return 0 if $start + 80 * 6 > $len; + + $et->SetFileType(); + + my $pos = $start; + my $dsf = Get8u(\$buff, $pos + 3) & 0x80 >> 7; + my $stype = Get8u(\$buff, $pos + 80*5 + 48 + 3) & 0x1f; + + # 576i50 25Mbps 4:1:1 is a special case + if ($dsf == 1 && $stype == 0 && Get8u(\$buff, 4) & 0x07) { + $profile = $dvProfiles[2]; + } else { + foreach (@dvProfiles) { + next unless $dsf == $$_{DSF} and $stype == $$_{VideoSType}; + $profile = $_; + last; + } + $profile or $et->Warn("Unrecognized DV profile"), return 1; + } + my $tagTablePtr = GetTagTable('Image::ExifTool::DV::Main'); + + # calculate total bit rate and duration + my $byteRate = $$profile{FrameSize} * $$profile{FrameRate}; + my $fileSize = $$et{VALUE}{FileSize}; + $$profile{TotalBitrate} = 8 * $byteRate; + $$profile{Duration} = $fileSize / $byteRate if defined $fileSize; + + # read DVPack metadata from the VAUX DIF's to extract video tags + delete $$profile{DateTimeOriginal}; + delete $$profile{AspectRatio}; + my ($date, $time, $is16_9); + for ($i=1; $i<6; ++$i) { + $pos += 80; + my $type = Get8u(\$buff, $pos); + next unless ($type & 0xf0) == 0x50; # look for VAUX types + for ($j=0; $j<15; ++$j) { + my $p = $pos + $j * 5 + 3; + $type = Get8u(\$buff, $p); + if ($type == 0x61) { # video control + my $apt = Get8u(\$buff, $start + 4) & 0x07; + my $t = Get8u(\$buff, $p + 2); + $is16_9 = (($t & 0x07) == 0x02 or (not $apt and ($t & 0x07) == 0x07)); + } elsif ($type == 0x62) { # date + # mask off unused bits + my @d = unpack('C*', substr($buff, $p + 1, 4)); + # (ignore timezone in byte 0 until we can test this properly - see ref 2) + $date = sprintf('%.2x:%.2x:%.2x', $d[3], $d[2] & 0x1f, $d[1] & 0x3f); + if ($date =~ /[a-f]/) { + undef $date; # invalid date + } else { + # add century (this will work until 2089) + $date = ($date lt '9' ? '20' : '19') . $date; + } + undef $time; + } elsif ($type == 0x63 and $date) { # time + # (ignore frames past second in byte 0 for now - see ref 2) + my $val = Get32u(\$buff, $p + 1) & 0x007f7f3f; + my @t = unpack('C*', substr($buff, $p + 1, 4)); + $time = sprintf('%.2x:%.2x:%.2x', $t[3] & 0x3f, $t[2] & 0x7f, $t[1] & 0x7f); + last; + } else { + undef $time; # must be consecutive + } + } + } + if ($date and $time) { + $$profile{DateTimeOriginal} = "$date $time"; + $$profile{AspectRatio} = $is16_9 ? '16:9' : '5:4' if defined $is16_9; + } + + # read audio tags if available + delete $$profile{AudioSampleRate}; + delete $$profile{AudioBitsPerSample}; + delete $$profile{AudioChannels}; + $pos = $start + 80*6 + 80*16*3 + 3; + if ($pos + 4 < $len and Get8u(\$buff, $pos) == 0x50) { + my $smpls = Get8u(\$buff, $pos + 1); + my $freq = (Get8u(\$buff, $pos + 4) >> 3) & 0x07; + my $stype = Get8u(\$buff, $pos + 3) & 0x1f; + my $quant = Get8u(\$buff, $pos + 4) & 0x07; + if ($freq < 3) { + $$profile{AudioSampleRate} = {0=>48000, 1=>44100, 2=>32000}->{$freq}; + } + if ($stype < 3) { + $stype = 2 if $stype == 0 and $quant and $freq == 2; + $$profile{AudioChannels} = {0=>2, 1=>0, 2=>4, 3=>8}->{$stype}; + } + $$profile{AudioBitsPerSample} = $quant ? 12 : 16; + } + + # save our metadata + foreach $tag (@dvTags) { + next unless defined $$profile{$tag}; + $et->HandleTag($tagTablePtr, $tag, $$profile{$tag}); + } + + return 1; +} + +1; # end + +__END__ + +=head1 NAME + +Image::ExifTool::DV - Read DV meta information + +=head1 SYNOPSIS + +This module is used by Image::ExifTool + +=head1 DESCRIPTION + +This module contains definitions required by Image::ExifTool to read meta +information from DV (raw Digital Video) files. + +=head1 AUTHOR + +Copyright 2003-2019, Phil Harvey (phil at owl.phy.queensu.ca) + +This library is free software; you can redistribute it and/or modify it +under the same terms as Perl itself. + +=head1 REFERENCES + +=over 4 + +=item L<http://ffmpeg.org/> + +=item L<http://dvswitch.alioth.debian.org/wiki/DV_format/> + +=back + +=head1 SEE ALSO + +L<Image::ExifTool::TagNames/DV Tags>, +L<Image::ExifTool(3pm)|Image::ExifTool> + +=cut + diff --git a/lib/Image/ExifTool/DarwinCore.pm b/lib/Image/ExifTool/DarwinCore.pm new file mode 100644 index 0000000..2be0ebd --- /dev/null +++ b/lib/Image/ExifTool/DarwinCore.pm @@ -0,0 +1,362 @@ +#------------------------------------------------------------------------------ +# File: DarwinCore.pm +# +# Description: Darwin Core XMP tags +# +# Revisions: 2013-01-28 - P. Harvey Created +# +# References: 1) http://rs.tdwg.org/dwc/index.htm +# 2) http://u88.n24.queensu.ca/exiftool/forum/index.php/topic,4442.0/all.html +#------------------------------------------------------------------------------ + +package Image::ExifTool::DarwinCore; + +use strict; +use vars qw($VERSION); +use Image::ExifTool::XMP; + +$VERSION = '1.02'; + +my %dateTimeInfo = ( + # NOTE: Do NOT put "Groups" here because Groups hash must not be common! + Writable => 'date', + Shift => 'Time', + PrintConv => '$self->ConvertDateTime($val)', + PrintConvInv => '$self->InverseDateTime($val,undef,1)', +); + +my %materialSample = ( + STRUCT_NAME => 'DarwinCore MaterialSample', + NAMESPACE => 'dwc', + materialSampleID => { }, +); + +my %event = ( + STRUCT_NAME => 'DarwinCore Event', + NAMESPACE => 'dwc', + day => { Writable => 'integer', Groups => { 2 => 'Time' } }, + earliestDate => { %dateTimeInfo, Groups => { 2 => 'Time' } }, + endDayOfYear => { Writable => 'integer', Groups => { 2 => 'Time' } }, + eventDate => { %dateTimeInfo, Groups => { 2 => 'Time' } }, + eventID => { }, + eventRemarks => { Writable => 'lang-alt' }, + eventTime => { %dateTimeInfo, Groups => { 2 => 'Time' } }, + fieldNotes => { }, + fieldNumber => { }, + habitat => { }, + latestDate => { %dateTimeInfo, Groups => { 2 => 'Time' } }, + month => { Writable => 'integer', Groups => { 2 => 'Time' } }, + parentEventID => { }, + samplingEffort => { }, + samplingProtocol => { }, + sampleSizeValue => { }, + sampleSizeUnit => { }, + startDayOfYear => { Writable => 'integer', Groups => { 2 => 'Time' } }, + verbatimEventDate => { Groups => { 2 => 'Time' } }, + year => { Writable => 'integer', Groups => { 2 => 'Time' } }, +); + +# Darwin Core tags +%Image::ExifTool::DarwinCore::Main = ( + GROUPS => { 0 => 'XMP', 1 => 'XMP-dwc', 2 => 'Other' }, + NAMESPACE => 'dwc', + WRITABLE => 'string', + NOTES => q{ + Tags defined in the Darwin Core (dwc) XMP namespace. See + L<http://rs.tdwg.org/dwc/index.htm> for the official specification. + }, + Event => { + Name => 'DCEvent', # (avoid conflict with XMP-iptcExt:Event) + FlatName => 'Event', + Struct => \%event, + }, + # tweak a few of the flattened tag names + EventEventDate => { Name => 'EventDate', Flat => 1 }, + EventEventID => { Name => 'EventID', Flat => 1 }, + EventEventRemarks => { Name => 'EventRemarks', Flat => 1 }, + EventEventTime => { Name => 'EventTime', Flat => 1 }, + FossilSpecimen => { Struct => \%materialSample }, + GeologicalContext => { + FlatName => '', # ('GeologicalContext' is too long) + Struct => { + STRUCT_NAME => 'DarwinCore GeologicalContext', + NAMESPACE => 'dwc', + bed => { }, + earliestAgeOrLowestStage => { }, + earliestEonOrLowestEonothem => { }, + earliestEpochOrLowestSeries => { }, + earliestEraOrLowestErathem => { }, + earliestPeriodOrLowestSystem=> { }, + formation => { }, + geologicalContextID => { }, + group => { }, + highestBiostratigraphicZone => { }, + latestAgeOrHighestStage => { }, + latestEonOrHighestEonothem => { }, + latestEpochOrHighestSeries => { }, + latestEraOrHighestErathem => { }, + latestPeriodOrHighestSystem => { }, + lithostratigraphicTerms => { }, + lowestBiostratigraphicZone => { }, + member => { }, + }, + }, + GeologicalContextBed => { Name => 'GeologicalContextBed', Flat => 1 }, + GeologicalContextFormation => { Name => 'GeologicalContextFormation', Flat => 1 }, + GeologicalContextGroup => { Name => 'GeologicalContextGroup', Flat => 1 }, + GeologicalContextMember => { Name => 'GeologicalContextMember', Flat => 1 }, + HumanObservation => { Struct => \%event }, + Identification => { + FlatName => '', # ('Identification' is redundant) + Struct => { + STRUCT_NAME => 'DarwinCore Identification', + NAMESPACE => 'dwc', + dateIdentified => { %dateTimeInfo, Groups => { 2 => 'Time' } }, + identificationID => { }, + identificationQualifier => { }, + identificationReferences => { }, + identificationRemarks => { }, + identificationVerificationStatus => { }, + identifiedBy => { }, + typeStatus => { }, + }, + }, + LivingSpecimen => { Struct => \%materialSample }, + MachineObservation => { Struct => \%event }, + MaterialSample => { Struct => \%materialSample }, + MaterialSampleMaterialSampleID => { Name => 'MaterialSampleID', Flat => 1 }, + MeasurementOrFact => { + FlatName => '', # ('MeasurementOrFact' is redundant and too long) + Struct => { + STRUCT_NAME => 'DarwinCore MeasurementOrFact', + NAMESPACE => 'dwc', + measurementAccuracy => { Format => 'real' }, + measurementDeterminedBy => { }, + measurementDeterminedDate => { %dateTimeInfo, Groups => { 2 => 'Time' } }, + measurementID => { }, + measurementMethod => { }, + measurementRemarks => { }, + measurementType => { }, + measurementUnit => { }, + measurementValue => { }, + }, + }, + Occurrence => { + Struct => { + STRUCT_NAME => 'DarwinCore Occurrence', + NAMESPACE => 'dwc', + associatedMedia => { }, + associatedOccurrences => { }, + associatedReferences => { }, + associatedSequences => { }, + associatedTaxa => { }, + behavior => { }, + catalogNumber => { }, + disposition => { }, + establishmentMeans => { }, + individualCount => { }, + individualID => { }, + lifeStage => { }, + occurrenceDetails => { }, + occurrenceID => { }, + occurrenceRemarks => { }, + occurrenceStatus => { }, + organismQuantity => { }, + organismQuantityType => { }, + otherCatalogNumbers => { }, + preparations => { }, + previousIdentifications => { }, + recordedBy => { }, + recordNumber => { }, + reproductiveCondition => { }, + sex => { }, + }, + }, + OccurrenceOccurrenceDetails => { Name => 'OccurrenceDetails', Flat => 1 }, + OccurrenceOccurrenceID => { Name => 'OccurrenceID', Flat => 1 }, + OccurrenceOccurrenceRemarks => { Name => 'OccurrenceRemarks', Flat => 1 }, + OccurrenceOccurrenceStatus => { Name => 'OccurrenceStatus', Flat => 1 }, + Organism => { + Struct => { + STRUCT_NAME => 'DarwinCore Organism', + NAMESPACE => 'dwc', + associatedOccurrences => { }, + associatedOrganisms => { }, + organismID => { }, + organismName => { }, + organismRemarks => { }, + organismScope => { }, + previousIdentifications => { }, + }, + }, + OrganismOrganismID => { Name => 'OrganismID', Flat => 1 }, + OrganismOrganismName => { Name => 'OrganismName', Flat => 1 }, + OrganismOrganismRemarks => { Name => 'OrganismRemarks', Flat => 1 }, + OrganismOrganismScope => { Name => 'OrganismScope', Flat => 1 }, + PreservedSpecimen => { Struct => \%materialSample }, + Record => { + Struct => { + STRUCT_NAME => 'DarwinCore Record', + NAMESPACE => 'dwc', + basisOfRecord => { }, + collectionCode => { }, + collectionID => { }, + dataGeneralizations => { }, + datasetID => { }, + datasetName => { }, + dynamicProperties => { }, + informationWithheld => { }, + institutionCode => { }, + institutionID => { }, + ownerInstitutionCode => { }, + }, + }, + ResourceRelationship => { + FlatName => '', # ('ResourceRelationship' is redundant and too long) + Struct => { + STRUCT_NAME => 'DarwinCore ResourceRelationship', + NAMESPACE => 'dwc', + relatedResourceID => { }, + relationshipAccordingTo => { }, + relationshipEstablishedDate => { %dateTimeInfo, Groups => { 2 => 'Time' } }, + relationshipOfResource => { }, + relationshipRemarks => { }, + resourceID => { }, + resourceRelationshipID => { }, + }, + }, + Taxon => { + Struct => { + STRUCT_NAME => 'DarwinCore Taxon', + NAMESPACE => 'dwc', + acceptedNameUsage => { }, + acceptedNameUsageID => { }, + class => { }, + family => { }, + genus => { }, + higherClassification => { }, + infraspecificEpithet => { }, + kingdom => { }, + nameAccordingTo => { }, + nameAccordingToID => { }, + namePublishedIn => { }, + namePublishedInID => { }, + namePublishedInYear => { }, + nomenclaturalCode => { }, + nomenclaturalStatus => { }, + order => { }, + originalNameUsage => { }, + originalNameUsageID => { }, + parentNameUsage => { }, + parentNameUsageID => { }, + phylum => { }, + scientificName => { }, + scientificNameAuthorship => { }, + scientificNameID => { }, + specificEpithet => { }, + subgenus => { }, + taxonConceptID => { }, + taxonID => { }, + taxonRank => { }, + taxonRemarks => { }, + taxonomicStatus => { }, + verbatimTaxonRank => { }, + vernacularName => { Writable => 'lang-alt' }, + }, + }, + TaxonTaxonConceptID => { Name => 'TaxonConceptID', Flat => 1 }, + TaxonTaxonID => { Name => 'TaxonID', Flat => 1 }, + TaxonTaxonRank => { Name => 'TaxonRank', Flat => 1 }, + TaxonTaxonRemarks => { Name => 'TaxonRemarks', Flat => 1 }, + dctermsLocation => { + Name => 'DCTermsLocation', + Groups => { 2 => 'Location' }, + FlatName => 'DC', # ('dctermsLocation' is too long) + Struct => { + STRUCT_NAME => 'DarwinCore DCTermsLocation', + NAMESPACE => 'dwc', + continent => { }, + coordinatePrecision => { }, + coordinateUncertaintyInMeters => { }, + country => { }, + countryCode => { }, + county => { }, + decimalLatitude => { }, + decimalLongitude => { }, + footprintSpatialFit => { }, + footprintSRS => { }, + footprintWKT => { }, + geodeticDatum => { }, + georeferencedBy => { }, + georeferencedDate => { }, + georeferenceProtocol => { }, + georeferenceRemarks => { }, + georeferenceSources => { }, + georeferenceVerificationStatus => { }, + higherGeography => { }, + higherGeographyID => { }, + island => { }, + islandGroup => { }, + locality => { }, + locationAccordingTo => { }, + locationID => { }, + locationRemarks => { }, + maximumDepthInMeters => { }, + maximumDistanceAboveSurfaceInMeters => { }, + maximumElevationInMeters => { }, + minimumDepthInMeters => { }, + minimumDistanceAboveSurfaceInMeters => { }, + minimumElevationInMeters => { }, + municipality => { }, + pointRadiusSpatialFit => { }, + stateProvince => { }, + verbatimCoordinates => { }, + verbatimCoordinateSystem => { }, + verbatimDepth => { }, + verbatimElevation => { }, + verbatimLatitude => { }, + verbatimLocality => { }, + verbatimLongitude => { }, + verbatimSRS => { }, + waterBody => { }, + }, + }, +); + +1; #end + +__END__ + +=head1 NAME + +Image::ExifTool::DarwinCore - Darwin Core XMP tags + +=head1 SYNOPSIS + +This module is used by Image::ExifTool + +=head1 DESCRIPTION + +This file contains tag definitions for the Darwin Core XMP namespace. + +=head1 AUTHOR + +Copyright 2003-2019, Phil Harvey (phil at owl.phy.queensu.ca) + +This library is free software; you can redistribute it and/or modify it +under the same terms as Perl itself. + +=head1 REFERENCES + +=over 4 + +=item L<http://rs.tdwg.org/dwc/index.htm> + +=back + +=head1 SEE ALSO + +L<Image::ExifTool::TagNames/XMP Tags>, +L<Image::ExifTool(3pm)|Image::ExifTool> + +=cut diff --git a/lib/Image/ExifTool/DjVu.pm b/lib/Image/ExifTool/DjVu.pm new file mode 100644 index 0000000..9f461be --- /dev/null +++ b/lib/Image/ExifTool/DjVu.pm @@ -0,0 +1,378 @@ +#------------------------------------------------------------------------------ +# File: DjVu.pm +# +# Description: Read DjVu archive meta information +# +# Revisions: 09/25/2008 - P. Harvey Created +# +# References: 1) http://djvu.sourceforge.net/ (DjVu v3 specification, Nov 2005) +# 2) http://www.djvu.org/ +# +# Notes: DjVu files are recognized and the IFF structure is processed +# by Image::ExifTool::AIFF +#------------------------------------------------------------------------------ + +package Image::ExifTool::DjVu; + +use strict; +use vars qw($VERSION); +use Image::ExifTool qw(:DataAccess :Utils); + +$VERSION = '1.06'; + +sub ParseAnt($); +sub ProcessAnt($$$); +sub ProcessMeta($$$); +sub ProcessBZZ($$$); + +# DjVu chunks that we parse (ref 4) +%Image::ExifTool::DjVu::Main = ( + GROUPS => { 2 => 'Image' }, + NOTES => q{ + Information is extracted from the following chunks in DjVu images. See + L<http://www.djvu.org/> for the DjVu specification. + }, + INFO => { + SubDirectory => { TagTable => 'Image::ExifTool::DjVu::Info' }, + }, + FORM => { + TypeOnly => 1, # extract chunk type only, then descend into chunk + SubDirectory => { TagTable => 'Image::ExifTool::DjVu::Form' }, + }, + ANTa => { + SubDirectory => { TagTable => 'Image::ExifTool::DjVu::Ant' }, + }, + ANTz => { + Name => 'CompressedAnnotation', + SubDirectory => { + TagTable => 'Image::ExifTool::DjVu::Ant', + ProcessProc => \&ProcessBZZ, + } + }, + INCL => 'IncludedFileID', +); + +# information in the DjVu INFO chunk +%Image::ExifTool::DjVu::Info = ( + PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData, + GROUPS => { 2 => 'Image' }, + FORMAT => 'int8u', + PRIORITY => 0, # first INFO block takes priority + 0 => { + Name => 'ImageWidth', + Format => 'int16u', + }, + 2 => { + Name => 'ImageHeight', + Format => 'int16u', + }, + 4 => { + Name => 'DjVuVersion', + Description => 'DjVu Version', + Format => 'int8u[2]', + # (this may be just one byte as with version 0.16) + ValueConv => '$val=~/(\d+) (\d+)/ ? "$2.$1" : "0.$val"', + }, + 6 => { + Name => 'SpatialResolution', + Format => 'int16u', + ValueConv => '(($val & 0xff)<<8) + ($val>>8)', # (little-endian!) + }, + 8 => { + Name => 'Gamma', + ValueConv => '$val / 10', + }, + 9 => { + Name => 'Orientation', + Mask => 0x07, # (upper 5 bits reserved) + PrintConv => { + 1 => 'Horizontal (normal)', + 2 => 'Rotate 180', + 5 => 'Rotate 90 CW', + 6 => 'Rotate 270 CW', + }, + }, +); + +# information in the DjVu FORM chunk +%Image::ExifTool::DjVu::Form = ( + PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData, + GROUPS => { 2 => 'Image' }, + 0 => { + Name => 'SubfileType', + Format => 'undef[4]', + Priority => 0, + PrintConv => { + DJVU => 'Single-page image', + DJVM => 'Multi-page document', + PM44 => 'Color IW44', + BM44 => 'Grayscale IW44', + DJVI => 'Shared component', + THUM => 'Thumbnail image', + }, + }, +); + +# tags found in the DjVu annotation chunk (ANTz or ANTa) +%Image::ExifTool::DjVu::Ant = ( + PROCESS_PROC => \&Image::ExifTool::DjVu::ProcessAnt, + GROUPS => { 2 => 'Image' }, + NOTES => 'Information extracted from annotation chunks.', + # Note: For speed, ProcessAnt() pre-scans for known tag ID's, so if any + # new tags are added here they must also be added to the pre-scan check + metadata => { + SubDirectory => { TagTable => 'Image::ExifTool::DjVu::Meta' } + }, + xmp => { + Name => 'XMP', + SubDirectory => { TagTable => 'Image::ExifTool::XMP::Main' } + }, +); + +# tags found in the DjVu annotation metadata +%Image::ExifTool::DjVu::Meta = ( + PROCESS_PROC => \&Image::ExifTool::DjVu::ProcessMeta, + GROUPS => { 1 => 'DjVu-Meta', 2 => 'Image' }, + NOTES => q{ + This table lists the standard DjVu metadata tags, but ExifTool will extract + any tags that exist even if they don't appear here. The DjVu v3 + documentation endorses tags borrowed from two standards: 1) BibTeX + bibliography system tags (all lowercase Tag ID's in the table below), and 2) + PDF DocInfo tags (capitalized Tag ID's). + }, + # BibTeX tags (ref http://en.wikipedia.org/wiki/BibTeX) + address => { Groups => { 2 => 'Location' } }, + annote => { Name => 'Annotation' }, + author => { Groups => { 2 => 'Author' } }, + booktitle => { Name => 'BookTitle' }, + chapter => { }, + crossref => { Name => 'CrossRef' }, + edition => { }, + eprint => { Name => 'EPrint' }, + howpublished=> { Name => 'HowPublished' }, + institution => { }, + journal => { }, + key => { }, + month => { Groups => { 2 => 'Time' } }, + note => { }, + number => { }, + organization=> { }, + pages => { }, + publisher => { }, + school => { }, + series => { }, + title => { }, + type => { }, + url => { Name => 'URL' }, + volume => { }, + year => { Groups => { 2 => 'Time' } }, + # PDF tags (same as Image::ExifTool::PDF::Info) + Title => { }, + Author => { Groups => { 2 => 'Author' } }, + Subject => { }, + Keywords => { }, + Creator => { }, + Producer => { }, + CreationDate => { + Name => 'CreateDate', + Groups => { 2 => 'Time' }, + # RFC 3339 date/time format + ValueConv => 'require Image::ExifTool::XMP; Image::ExifTool::XMP::ConvertXMPDate($val)', + PrintConv => '$self->ConvertDateTime($val)', + }, + ModDate => { + Name => 'ModifyDate', + Groups => { 2 => 'Time' }, + ValueConv => 'require Image::ExifTool::XMP; Image::ExifTool::XMP::ConvertXMPDate($val)', + PrintConv => '$self->ConvertDateTime($val)', + }, + Trapped => { + # remove leading '/' from '/True' or '/False' + ValueConv => '$val=~s{^/}{}; $val', + }, +); + +#------------------------------------------------------------------------------ +# Parse DjVu annotation "s-expression" syntax (recursively) +# Inputs: 0) data ref (with pos($$dataPt) set to start of annotation) +# Returns: reference to list of tokens/references, or undef if no tokens, +# and the position in $$dataPt is set to end of last token +# Notes: The DjVu annotation syntax is not well documented, so I make +# a number of assumptions here! +sub ParseAnt($) +{ + my $dataPt = shift; + my (@toks, $tok, $more); + # (the DjVu annotation syntax really sucks, and requires that every + # single token be parsed in order to properly scan through the items) +Tok: for (;;) { + # find the next token + last unless $$dataPt =~ /(\S)/sg; # get next non-space character + if ($1 eq '(') { # start of list + $tok = ParseAnt($dataPt); + } elsif ($1 eq ')') { # end of list + $more = 1; + last; + } elsif ($1 eq '"') { # quoted string + $tok = ''; + for (;;) { + # get string up to the next quotation mark + # this doesn't work in perl 5.6.2! grrrr + # last Tok unless $$dataPt =~ /(.*?)"/sg; + # $tok .= $1; + my $pos = pos($$dataPt); + last Tok unless $$dataPt =~ /"/sg; + $tok .= substr($$dataPt, $pos, pos($$dataPt)-1-$pos); + # we're good unless quote was escaped by odd number of backslashes + last unless $tok =~ /(\\+)$/ and length($1) & 0x01; + $tok .= '"'; # quote is part of the string + } + # must protect unescaped "$" and "@" symbols, and "\" at end of string + $tok =~ s{\\(.)|([\$\@]|\\$)}{'\\'.($2 || $1)}sge; + # convert C escape sequences (allowed in quoted text) + $tok = eval qq{"$tok"}; + } else { # key name + pos($$dataPt) = pos($$dataPt) - 1; + # allow anything in key but whitespace, braces and double quotes + # (this is one of those assumptions I mentioned) + $$dataPt =~ /([^\s()"]+)/sg; + $tok = $1; + } + push @toks, $tok if defined $tok; + } + # prevent further parsing unless more after this + pos($$dataPt) = length $$dataPt unless $more; + return @toks ? \@toks : undef; +} + +#------------------------------------------------------------------------------ +# Process DjVu annotation chunk (ANTa or decoded ANTz) +# Inputs: 0) ExifTool object reference, 1) DirInfo reference, 2) tag table ref +# Returns: 1 on success +sub ProcessAnt($$$) +{ + my ($et, $dirInfo, $tagTablePtr) = @_; + my $dataPt = $$dirInfo{DataPt}; + + # quick pre-scan to check for metadata or XMP + return 1 unless $$dataPt =~ /\(\s*(metadata|xmp)[\s("]/s; + + # parse annotations into a tree structure + pos($$dataPt) = 0; + my $toks = ParseAnt($dataPt) or return 0; + + # process annotations individually + my $ant; + foreach $ant (@$toks) { + next unless ref $ant eq 'ARRAY' and @$ant >= 2; + my $tag = shift @$ant; + next if ref $tag or not defined $$tagTablePtr{$tag}; + if ($tag eq 'metadata') { + # ProcessMeta() takes array reference + $et->HandleTag($tagTablePtr, $tag, $ant); + } else { + next if ref $$ant[0]; # only process simple values + $et->HandleTag($tagTablePtr, $tag, $$ant[0]); + } + } + return 1; +} + +#------------------------------------------------------------------------------ +# Process DjVu metadata +# Inputs: 0) ExifTool object reference, 1) DirInfo reference, 2) tag table ref +# Returns: 1 on success +# Notes: input dirInfo DataPt is a reference to a list of pre-parsed metadata entries +sub ProcessMeta($$$) +{ + my ($et, $dirInfo, $tagTablePtr) = @_; + my $dataPt = $$dirInfo{DataPt}; + return 0 unless ref $$dataPt eq 'ARRAY'; + $et->VerboseDir('Metadata', scalar @$$dataPt); + my ($item, $err); + foreach $item (@$$dataPt) { + # make sure item is a simple tag/value pair + $err=1, next unless ref $item eq 'ARRAY' and @$item >= 2 and + not ref $$item[0] and not ref $$item[1]; + # add any new tags to the table + unless ($$tagTablePtr{$$item[0]}) { + my $name = $$item[0]; + $name =~ tr/-_a-zA-Z0-9//dc; # remove illegal characters + length $name or $err = 1, next; + AddTagToTable($tagTablePtr, $$item[0], { Name => ucfirst($name) }); + } + $et->HandleTag($tagTablePtr, $$item[0], $$item[1]); + } + $err and $et->Warn('Ignored invalid metadata entry(s)'); + return 1; +} + +#------------------------------------------------------------------------------ +# Process BZZ-compressed data (in DjVu images) +# Inputs: 0) ExifTool object reference, 1) DirInfo reference, 2) tag table ref +# Returns: 1 on success +sub ProcessBZZ($$$) +{ + my ($et, $dirInfo, $tagTablePtr) = @_; + require Image::ExifTool::BZZ; + my $buff = Image::ExifTool::BZZ::Decode($$dirInfo{DataPt}); + unless (defined $buff) { + $et->Warn("Error decoding $$dirInfo{DirName}"); + return 0; + } + my $verbose = $et->Options('Verbose'); + if ($verbose >= 3) { + # dump the decoded data in very verbose mode + $et->VerboseDir("Decoded $$dirInfo{DirName}", 0, length $buff); + $et->VerboseDump(\$buff); + } + $$dirInfo{DataPt} = \$buff; + $$dirInfo{DataLen} = $$dirInfo{DirLen} = length $buff; + # process the data using the default process proc for this table + my $processProc = $$tagTablePtr{PROCESS_PROC} or return 0; + return &$processProc($et, $dirInfo, $tagTablePtr); +} + +1; # end + +__END__ + +=head1 NAME + +Image::ExifTool::DjVu - Read DjVu meta information + +=head1 SYNOPSIS + +This module is used by Image::ExifTool + +=head1 DESCRIPTION + +This module contains definitions required by Image::ExifTool to extract meta +information from DjVu images. Parsing of the DjVu IFF structure is done by +Image::ExifTool::AIFF. + +=head1 AUTHOR + +Copyright 2003-2019, Phil Harvey (phil at owl.phy.queensu.ca) + +This library is free software; you can redistribute it and/or modify it +under the same terms as Perl itself. + +=head1 REFERENCES + +=over 4 + +=item L<http://djvu.sourceforge.net/> + +=item L<http://www.djvu.org/> + +=back + +=head1 SEE ALSO + +L<Image::ExifTool::TagNames/DjVu Tags>, +L<Image::ExifTool::AIFF(3pm)|Image::ExifTool::AIFF>, +L<Image::ExifTool(3pm)|Image::ExifTool> + +=cut + diff --git a/lib/Image/ExifTool/EXE.pm b/lib/Image/ExifTool/EXE.pm new file mode 100644 index 0000000..6644e07 --- /dev/null +++ b/lib/Image/ExifTool/EXE.pm @@ -0,0 +1,1425 @@ +#------------------------------------------------------------------------------ +# File: EXE.pm +# +# Description: Read meta information of various executable file formats +# +# Revisions: 2008/08/28 - P. Harvey Created +# 2011/07/12 - P. Harvey Added CHM (ok, not EXE, but it fits here) +# +# References: 1) http://www.openwatcom.org/ftp/devel/docs/pecoff.pdf +# 2) http://support.microsoft.com/kb/65122 +# 3) http://www.opensource.apple.com +# 4) http://www.skyfree.org/linux/references/ELF_Format.pdf +# 5) http://msdn.microsoft.com/en-us/library/ms809762.aspx +# 6) http://code.google.com/p/pefile/ +# 7) http://www.codeproject.com/KB/DLL/showver.aspx +#------------------------------------------------------------------------------ + +package Image::ExifTool::EXE; + +use strict; +use vars qw($VERSION); +use Image::ExifTool qw(:DataAccess :Utils); + +$VERSION = '1.15'; + +sub ProcessPEResources($$); +sub ProcessPEVersion($$); + +# PE file resource types (ref 6) +my %resourceType = ( + 1 => 'Cursor', + 2 => 'Bitmap', + 3 => 'Icon', + 4 => 'Menu', + 5 => 'Dialog', + 6 => 'String', + 7 => 'Font Dir', + 8 => 'Font', + 9 => 'Accelerator', + 10 => 'RC Data', + 11 => 'Message Table', + 12 => 'Group Cursor', + 14 => 'Group Icon', + 16 => 'Version', + 17 => 'Dialog Include', + 19 => 'Plug-n-Play', + 20 => 'VxD', + 21 => 'Animated Cursor', + 22 => 'Animated Icon', + 23 => 'HTML', + 24 => 'Manifest', +); + +my %languageCode = ( + '0000' => 'Neutral', + '007F' => 'Invariant', + '0400' => 'Process default', + '0401' => 'Arabic', + '0402' => 'Bulgarian', + '0403' => 'Catalan', + '0404' => 'Chinese (Traditional)', + '0405' => 'Czech', + '0406' => 'Danish', + '0407' => 'German', + '0408' => 'Greek', + '0409' => 'English (U.S.)', + '040A' => 'Spanish (Castilian)', + '040B' => 'Finnish', + '040C' => 'French', + '040D' => 'Hebrew', + '040E' => 'Hungarian', + '040F' => 'Icelandic', + '0410' => 'Italian', + '0411' => 'Japanese', + '0412' => 'Korean', + '0413' => 'Dutch', + '0414' => 'Norwegian (Bokml)', + '0415' => 'Polish', + '0416' => 'Portuguese (Brazilian)', + '0417' => 'Rhaeto-Romanic', + '0418' => 'Romanian', + '0419' => 'Russian', + '041A' => 'Croato-Serbian (Latin)', + '041B' => 'Slovak', + '041C' => 'Albanian', + '041D' => 'Swedish', + '041E' => 'Thai', + '041F' => 'Turkish', + '0420' => 'Urdu', + # 0421-0493 ref 6 + '0421' => 'Indonesian', + '0422' => 'Ukrainian', + '0423' => 'Belarusian', + '0424' => 'Slovenian', + '0425' => 'Estonian', + '0426' => 'Latvian', + '0427' => 'Lithuanian', + '0428' => 'Maori', + '0429' => 'Farsi', + '042a' => 'Vietnamese', + '042b' => 'Armenian', + '042c' => 'Azeri', + '042d' => 'Basque', + '042e' => 'Sorbian', + '042f' => 'Macedonian', + '0430' => 'Sutu', + '0431' => 'Tsonga', + '0432' => 'Tswana', + '0433' => 'Venda', + '0434' => 'Xhosa', + '0435' => 'Zulu', + '0436' => 'Afrikaans', + '0437' => 'Georgian', + '0438' => 'Faeroese', + '0439' => 'Hindi', + '043a' => 'Maltese', + '043b' => 'Saami', + '043c' => 'Gaelic', + '043e' => 'Malay', + '043f' => 'Kazak', + '0440' => 'Kyrgyz', + '0441' => 'Swahili', + '0443' => 'Uzbek', + '0444' => 'Tatar', + '0445' => 'Bengali', + '0446' => 'Punjabi', + '0447' => 'Gujarati', + '0448' => 'Oriya', + '0449' => 'Tamil', + '044a' => 'Telugu', + '044b' => 'Kannada', + '044c' => 'Malayalam', + '044d' => 'Assamese', + '044e' => 'Marathi', + '044f' => 'Sanskrit', + '0450' => 'Mongolian', + '0456' => 'Galician', + '0457' => 'Konkani', + '0458' => 'Manipuri', + '0459' => 'Sindhi', + '045a' => 'Syriac', + '0460' => 'Kashmiri', + '0461' => 'Nepali', + '0465' => 'Divehi', + '047f' => 'Invariant', + '048f' => 'Esperanto', + '0490' => 'Walon', + '0491' => 'Cornish', + '0492' => 'Welsh', + '0493' => 'Breton', + '0800' => 'Neutral 2', + '0804' => 'Chinese (Simplified)', + '0807' => 'German (Swiss)', + '0809' => 'English (British)', + '080A' => 'Spanish (Mexican)', + '080C' => 'French (Belgian)', + '0810' => 'Italian (Swiss)', + '0813' => 'Dutch (Belgian)', + '0814' => 'Norwegian (Nynorsk)', + '0816' => 'Portuguese', + '081A' => 'Serbo-Croatian (Cyrillic)', + '0C07' => 'German (Austrian)', + '0C09' => 'English (Australian)', + '0C0A' => 'Spanish (Modern)', + '0C0C' => 'French (Canadian)', + '1009' => 'English (Canadian)', + '100C' => 'French (Swiss)', +); + +# Information extracted from PE COFF (Windows EXE) file header +%Image::ExifTool::EXE::Main = ( + PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData, + GROUPS => { 2 => 'Other' }, + FORMAT => 'int16u', + NOTES => q{ + This module extracts information from various types of Windows, MacOS and + Unix executable and library files. The first table below lists information + extracted from the header of Windows PE (Portable Executable) EXE files and + DLL libraries. + }, + 0 => { + Name => 'MachineType', + PrintHex => 1, + PrintConv => { + 0x014c => 'Intel 386 or later, and compatibles', + 0x014d => 'Intel i860', #5 + 0x0162 => 'MIPS R3000', + 0x0166 => 'MIPS little endian (R4000)', + 0x0168 => 'MIPS R10000', + 0x0169 => 'MIPS little endian WCI v2', + 0x0183 => 'Alpha AXP (old)', #5 + 0x0184 => 'Alpha AXP', + 0x01a2 => 'Hitachi SH3', + 0x01a3 => 'Hitachi SH3 DSP', + 0x01a6 => 'Hitachi SH4', + 0x01a8 => 'Hitachi SH5', + 0x01c0 => 'ARM little endian', + 0x01c2 => 'Thumb', + 0x01d3 => 'Matsushita AM33', + 0x01f0 => 'PowerPC little endian', + 0x01f1 => 'PowerPC with floating point support', + 0x0200 => 'Intel IA64', + 0x0266 => 'MIPS16', + 0x0268 => 'Motorola 68000 series', + 0x0284 => 'Alpha AXP 64-bit', + 0x0366 => 'MIPS with FPU', + 0x0466 => 'MIPS16 with FPU', + 0x0ebc => 'EFI Byte Code', + 0x8664 => 'AMD AMD64', + 0x9041 => 'Mitsubishi M32R little endian', + 0xc0ee => 'clr pure MSIL', + }, + }, + 2 => { + Name => 'TimeStamp', + Format => 'int32u', + Groups => { 2 => 'Time' }, + ValueConv => 'ConvertUnixTime($val,1)', + PrintConv => '$self->ConvertDateTime($val)', + }, + 9 => { + Name => 'ImageFileCharacteristics', + # ref https://docs.microsoft.com/en-us/windows/desktop/api/winnt/ns-winnt-_image_file_header + PrintConv => { BITMASK => { + 0 => 'No relocs', + 1 => 'Executable', + 2 => 'No line numbers', + 3 => 'No symbols', + 4 => 'Aggressive working-set trim', + 5 => 'Large address aware', + 7 => 'Bytes reversed lo', + 8 => '32-bit', + 9 => 'No debug', + 10 => 'Removable run from swap', + 11 => 'Net run from swap', + 12 => 'System file', + 13 => 'DLL', + 14 => 'Uniprocessor only', + 15 => 'Bytes reversed hi', + }}, + }, + 10 => { + Name => 'PEType', + PrintHex => 1, + PrintConv => { + 0x107 => 'ROM Image', + 0x10b => 'PE32', + 0x20b => 'PE32+', + }, + }, + 11 => { + Name => 'LinkerVersion', + Format => 'int8u[2]', + ValueConv => '$val=~tr/ /./; $val', + }, + 12 => { + Name => 'CodeSize', + Format => 'int32u', + }, + 14 => { + Name => 'InitializedDataSize', + Format => 'int32u', + }, + 16 => { + Name => 'UninitializedDataSize', + Format => 'int32u', + }, + 18 => { + Name => 'EntryPoint', + Format => 'int32u', + PrintConv => 'sprintf("0x%.4x", $val)', + }, + 30 => { + Name => 'OSVersion', + Format => 'int16u[2]', + ValueConv => '$val=~tr/ /./; $val', + }, + 32 => { + Name => 'ImageVersion', + Format => 'int16u[2]', + ValueConv => '$val=~tr/ /./; $val', + }, + 34 => { + Name => 'SubsystemVersion', + Format => 'int16u[2]', + ValueConv => '$val=~tr/ /./; $val', + }, + 44 => { + Name => 'Subsystem', + PrintConv => { + 0 => 'Unknown', + 1 => 'Native', + 2 => 'Windows GUI', + 3 => 'Windows command line', + 5 => 'OS/2 command line', #5 + 7 => 'POSIX command line', + 9 => 'Windows CE GUI', + 10 => 'EFI application', + 11 => 'EFI boot service', + 12 => 'EFI runtime driver', + 13 => 'EFI ROM', #6 + 14 => 'XBOX', #6 + }, + }, +); + +# PE file version information (ref 6) +%Image::ExifTool::EXE::PEVersion = ( + PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData, + GROUPS => { 2 => 'Other' }, + FORMAT => 'int32u', + NOTES => q{ + Information extracted from the VS_VERSION_INFO structure of Windows PE + files. + }, + # (boring -- always 0xfeef04bd) + #0 => { + # Name => 'Signature', + # PrintConv => 'sprintf("0x%.4x",$val)', + #}, + # (boring -- always 1.0) + #1 => { + # Name => 'StructVersion', + # Format => 'int16u[2]', + # ValueConv => 'my @a=split(" ",$val); "$a[1].$a[0]"', + #}, + 2 => { + Name => 'FileVersionNumber', + Format => 'int16u[4]', + ValueConv => 'my @a=split(" ",$val); "$a[1].$a[0].$a[3].$a[2]"', + }, + 4 => { + Name => 'ProductVersionNumber', + Format => 'int16u[4]', + ValueConv => 'my @a=split(" ",$val); "$a[1].$a[0].$a[3].$a[2]"', + }, + 6 => { + Name => 'FileFlagsMask', + PrintConv => 'sprintf("0x%.4x",$val)', + }, + 7 => { # ref Cygwin /usr/include/w32api/winver.h + Name => 'FileFlags', + PrintConv => { BITMASK => { + 0 => 'Debug', + 1 => 'Pre-release', + 2 => 'Patched', + 3 => 'Private build', + 4 => 'Info inferred', + 5 => 'Special build', + }}, + }, + 8 => { + Name => 'FileOS', + PrintHex => 1, + PrintConv => { # ref Cygwin /usr/include/w32api/winver.h + 0x00001 => 'Win16', + 0x00002 => 'PM-16', + 0x00003 => 'PM-32', + 0x00004 => 'Win32', + 0x10000 => 'DOS', + 0x20000 => 'OS/2 16-bit', + 0x30000 => 'OS/2 32-bit', + 0x40000 => 'Windows NT', + 0x10001 => 'Windows 16-bit', + 0x10004 => 'Windows 32-bit', + 0x20002 => 'OS/2 16-bit PM-16', + 0x30003 => 'OS/2 32-bit PM-32', + 0x40004 => 'Windows NT 32-bit', + }, + }, + 9 => { # ref Cygwin /usr/include/w32api/winver.h + Name => 'ObjectFileType', + PrintConv => { + 0 => 'Unknown', + 1 => 'Executable application', + 2 => 'Dynamic link library', + 3 => 'Driver', + 4 => 'Font', + 5 => 'VxD', + 7 => 'Static library', + }, + }, + 10 => 'FileSubtype', + # (these are usually zero, so ignore them) + # 11 => 'FileDateMS', + # 12 => 'FileDateLS', +); + +# Windows PE StringFileInfo resource strings +# (see http://msdn.microsoft.com/en-us/library/aa381049.aspx) +%Image::ExifTool::EXE::PEString = ( + GROUPS => { 2 => 'Other' }, + VARS => { NO_ID => 1 }, + NOTES => q{ + Resource strings found in Windows PE files. The B<TagID>'s are not shown + because they are the same as the B<Tag Name>. ExifTool will extract any + existing StringFileInfo tags even if not listed in this table. + }, + LanguageCode => { + Notes => 'extracted from the StringFileInfo value', + # ref http://techsupt.winbatch.com/TS/T000001050F49.html + # (also see http://support.bigfix.com/fixlet/documents/WinInspectors-2006-08-10.pdf) + # (also see ftp://ftp.dyu.edu.tw/pub/cpatch/faq/tech/tech_nlsnt.txt) + # (not a complete set) + PrintString => 1, + SeparateTable => 1, + PrintConv => \%languageCode, + }, + CharacterSet => { + Notes => 'extracted from the StringFileInfo value', + # ref http://techsupt.winbatch.com/TS/T000001050F49.html + # (also see http://blog.chinaunix.net/u1/41189/showart_345768.html) + PrintString => 1, + PrintConv => { + '0000' => 'ASCII', + '03A4' => 'Windows, Japan (Shift - JIS X-0208)', # cp932 + '03A8' => 'Windows, Chinese (Simplified)', # cp936 + '03B5' => 'Windows, Korea (Shift - KSC 5601)', # cp949 + '03B6' => 'Windows, Taiwan (Big5)', # cp950 + '04B0' => 'Unicode', # UCS-2 + '04E2' => 'Windows, Latin2 (Eastern European)', + '04E3' => 'Windows, Cyrillic', + '04E4' => 'Windows, Latin1', + '04E5' => 'Windows, Greek', + '04E6' => 'Windows, Turkish', + '04E7' => 'Windows, Hebrew', + '04E8' => 'Windows, Arabic', + }, + }, + BuildDate => { Groups => { 2 => 'Time' } }, # (non-standard) + BuildVersion => { }, # (non-standard) + Comments => { }, + CompanyName => { }, + Copyright => { }, # (non-standard) + FileDescription => { }, + FileVersion => { }, + InternalName => { }, + LegalCopyright => { }, + LegalTrademarks => { }, + OriginalFilename=> { Name => 'OriginalFileName' }, + PrivateBuild => { }, + ProductName => { }, + ProductVersion => { }, + SpecialBuild => { }, +); + +# Information extracted from Mach-O (Mac OS X) file header +%Image::ExifTool::EXE::MachO = ( + GROUPS => { 2 => 'Other' }, + VARS => { ID_LABEL => 'Index' }, + NOTES => q{ + Information extracted from Mach-O (Mac OS X) executable files and DYLIB + libraries. + }, + # ref http://www.opensource.apple.com/darwinsource/DevToolsOct2007/cctools-622.9/include/mach/machine.h + 0 => 'CPUArchitecture', + 1 => 'CPUByteOrder', + 2 => 'CPUCount', + # ref /System/Library/Frameworks/Kernel.framework/Versions/A/Headers/mach/machine.h + 3 => { + Name => 'CPUType', + List => 1, + PrintConv => { + # handle 64-bit flag (0x1000000) + OTHER => sub { + my ($val, $inv, $conv) = @_; + my $v = $val & 0xfeffffff; + return $$conv{$v} ? "$$conv{$v} 64-bit" : "Unknown ($val)"; + }, + -1 => 'Any', + 1 => 'VAX', + 2 => 'ROMP', + 4 => 'NS32032', + 5 => 'NS32332', + 6 => 'MC680x0', + 7 => 'x86', + 8 => 'MIPS', + 9 => 'NS32532', + 10 => 'MC98000', + 11 => 'HPPA', + 12 => 'ARM', + 13 => 'MC88000', + 14 => 'SPARC', + 15 => 'i860 big endian', + 16 => 'i860 little endian', + 17 => 'RS6000', + 18 => 'PowerPC', + 255 => 'VEO', + }, + }, + # ref /System/Library/Frameworks/Kernel.framework/Versions/A/Headers/mach/machine.h + 4 => { + Name => 'CPUSubtype', + List => 1, + PrintConv => { + # handle 64-bit flags on CPUType (0x1000000) and CPUSubtype (0x80000000) + OTHER => sub { + my ($val, $inv, $conv) = @_; + my @v = split ' ', $val; + my $v = ($v[0] & 0xfeffffff) . ' ' . ($v[1] & 0x7fffffff); + return $$conv{$v} ? "$$conv{$v} 64-bit" : "Unknown ($val)"; + }, + # in theory, subtype can be -1 for multiple CPU types, + # but in practice I'm not sure anyone uses this - PH + '1 0' => 'VAX (all)', + '1 1' => 'VAX780', + '1 2' => 'VAX785', + '1 3' => 'VAX750', + '1 4' => 'VAX730', + '1 5' => 'UVAXI', + '1 6' => 'UVAXII', + '1 7' => 'VAX8200', + '1 8' => 'VAX8500', + '1 9' => 'VAX8600', + '1 10' => 'VAX8650', + '1 11' => 'VAX8800', + '1 12' => 'UVAXIII', + '2 0' => 'RT (all)', + '2 1' => 'RT PC', + '2 2' => 'RT APC', + '2 3' => 'RT 135', + # 32032/32332/32532 subtypes. + '4 0' => 'NS32032 (all)', + '4 1' => 'NS32032 DPC (032 CPU)', + '4 2' => 'NS32032 SQT', + '4 3' => 'NS32032 APC FPU (32081)', + '4 4' => 'NS32032 APC FPA (Weitek)', + '4 5' => 'NS32032 XPC (532)', + '5 0' => 'NS32332 (all)', + '5 1' => 'NS32332 DPC (032 CPU)', + '5 2' => 'NS32332 SQT', + '5 3' => 'NS32332 APC FPU (32081)', + '5 4' => 'NS32332 APC FPA (Weitek)', + '5 5' => 'NS32332 XPC (532)', + '6 1' => 'MC680x0 (all)', + '6 2' => 'MC68040', + '6 3' => 'MC68030', + '7 3' => 'i386 (all)', + '7 4' => 'i486', + '7 132' => 'i486SX', + '7 5' => 'i586', + '7 22' => 'Pentium Pro', + '7 54' => 'Pentium II M3', + '7 86' => 'Pentium II M5', + '7 103' => 'Celeron', + '7 119' => 'Celeron Mobile', + '7 8' => 'Pentium III', + '7 24' => 'Pentium III M', + '7 40' => 'Pentium III Xeon', + '7 9' => 'Pentium M', + '7 10' => 'Pentium 4', + '7 26' => 'Pentium 4 M', + '7 11' => 'Itanium', + '7 27' => 'Itanium 2', + '7 12' => 'Xeon', + '7 28' => 'Xeon MP', + '8 0' => 'MIPS (all)', + '8 1' => 'MIPS R2300', + '8 2' => 'MIPS R2600', + '8 3' => 'MIPS R2800', + '8 4' => 'MIPS R2000a', + '8 5' => 'MIPS R2000', + '8 6' => 'MIPS R3000a', + '8 7' => 'MIPS R3000', + '10 0' => 'MC98000 (all)', + '10 1' => 'MC98601', + '11 0' => 'HPPA (all)', + '11 1' => 'HPPA 7100LC', + '12 0' => 'ARM (all)', + '12 1' => 'ARM A500 ARCH', + '12 2' => 'ARM A500', + '12 3' => 'ARM A440', + '12 4' => 'ARM M4', + '12 5' => 'ARM A680/V4T', + '12 6' => 'ARM V6', + '12 7' => 'ARM V5TEJ', + '12 8' => 'ARM XSCALE', + '12 9' => 'ARM V7', + '13 0' => 'MC88000 (all)', + '13 1' => 'MC88100', + '13 2' => 'MC88110', + '14 0' => 'SPARC (all)', + '14 1' => 'SUN 4/260', + '14 2' => 'SUN 4/110', + '15 0' => 'i860 (all)', + '15 1' => 'i860 860', + '16 0' => 'i860 little (all)', + '16 1' => 'i860 little', + '17 0' => 'RS6000 (all)', + '17 1' => 'RS6000', + '18 0' => 'PowerPC (all)', + '18 1' => 'PowerPC 601', + '18 2' => 'PowerPC 602', + '18 3' => 'PowerPC 603', + '18 4' => 'PowerPC 603e', + '18 5' => 'PowerPC 603ev', + '18 6' => 'PowerPC 604', + '18 7' => 'PowerPC 604e', + '18 8' => 'PowerPC 620', + '18 9' => 'PowerPC 750', + '18 10' => 'PowerPC 7400', + '18 11' => 'PowerPC 7450', + '18 100' => 'PowerPC 970', + '255 1' => 'VEO 1', + '255 2' => 'VEO 2', + }, + }, + 5 => { + Name => 'ObjectFileType', + PrintHex => 1, + # ref https://svn.red-bean.com/pyobjc/branches/pyobjc-20x-branch/macholib/macholib/mach_o.py + PrintConv => { + -1 => 'Static library', #PH (internal use only) + 1 => 'Relocatable object', + 2 => 'Demand paged executable', + 3 => 'Fixed VM shared library', + 4 => 'Core', + 5 => 'Preloaded executable', + 6 => 'Dynamically bound shared library', + 7 => 'Dynamic link editor', + 8 => 'Dynamically bound bundle', + 9 => 'Shared library stub for static linking', + # (the following from Apple loader.h header file) + 10 => 'Debug information', + 11 => 'x86_64 kexts', + }, + }, + 6 => { + Name => 'ObjectFlags', + PrintHex => 1, + # ref Apple loader.h header file + PrintConv => { BITMASK => { + 0 => 'No undefs', + 1 => 'Incrementa link', + 2 => 'Dyld link', + 3 => 'Bind at load', + 4 => 'Prebound', + 5 => 'Split segs', + 6 => 'Lazy init', + 7 => 'Two level', + 8 => 'Force flat', + 9 => 'No multi defs', + 10 => 'No fix prebinding', + 11 => 'Prebindable', + 12 => 'All mods bound', + 13 => 'Subsections via symbols', + 14 => 'Canonical', + 15 => 'Weak defines', + 16 => 'Binds to weak', + 17 => 'Allow stack execution', + 18 => 'Dead strippable dylib', + 19 => 'Root safe', + 20 => 'No reexported dylibs', + 21 => 'Random address', + }}, + }, +); + +# Information extracted from PEF (Classic MacOS executable) file header +%Image::ExifTool::EXE::PEF = ( + PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData, + GROUPS => { 2 => 'Other' }, + NOTES => q{ + Information extracted from PEF (Classic MacOS) executable files and + libraries. + }, + FORMAT => 'int32u', + 2 => { + Name => 'CPUArchitecture', + Format => 'undef[4]', + PrintConv => { + pwpc => 'PowerPC', + m68k => '68000', + }, + }, + 3 => 'PEFVersion', + 4 => { + Name => 'TimeStamp', + Groups => { 2 => 'Time' }, + # timestamp is relative to Jan 1, 1904 + ValueConv => 'ConvertUnixTime($val - ((66 * 365 + 17) * 24 * 3600))', + PrintConv => '$self->ConvertDateTime($val)', + }, + #5 => 'OldDefVersion', + #6 => 'OldImpVersion', + #7 => 'CurrentVersion', +); + +# Information extracted from ELF (Unix executable) file header +%Image::ExifTool::EXE::ELF = ( + PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData, + GROUPS => { 2 => 'Other' }, + NOTES => q{ + Information extracted from ELF (Unix) executable files and SO libraries. + }, + 4 => { + Name => 'CPUArchitecture', + PrintConv => { + 1 => '32 bit', + 2 => '64 bit', + }, + }, + 5 => { + Name => 'CPUByteOrder', + PrintConv => { + 1 => 'Little endian', + 2 => 'Big endian', + }, + }, + 16 => { + Name => 'ObjectFileType', + Format => 'int16u', + PrintConv => { + 0 => 'None', + 1 => 'Relocatable file', + 2 => 'Executable file', + 3 => 'Shared object file', + 4 => 'Core file', + }, + }, + 18 => { + Name => 'CPUType', + Format => 'int16u', + # ref /usr/include/linux/elf-em.h + PrintConv => { + 0 => 'None', + 1 => 'AT&T WE 32100', + 2 => 'SPARC', + 3 => 'i386', + 4 => 'Motorola 68000', + 5 => 'Motorola 88000', + 6 => 'i486', + 7 => 'i860', + 8 => 'MIPS R3000', + 10 => 'MIPS R4000', + 15 => 'HPPA', + 18 => 'Sun v8plus', + 20 => 'PowerPC', + 21 => 'PowerPC 64-bit', + 22 => 'IBM S/390', + 23 => 'Cell BE SPU', + 42 => 'SuperH', + 43 => 'SPARC v9 64-bit', + 46 => 'Renesas H8/300,300H,H8S', + 50 => 'HP/Intel IA-64', + 62 => 'AMD x86-64', + 76 => 'Axis Communications 32-bit embedded processor', + 87 => 'NEC v850', + 88 => 'Renesas M32R', + 0x5441 => 'Fujitsu FR-V', + 0x9026 => 'Alpha', # (interim value) + 0x9041 => 'm32r (old)', + 0x9080 => 'v850 (old)', + 0xa390 => 'S/390 (old)', + }, + }, +); + +# Information extracted from static library archives +# (ref http://opensource.apple.com//source/xnu/xnu-1456.1.26/EXTERNAL_HEADERS/ar.h) +%Image::ExifTool::EXE::AR = ( + PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData, + GROUPS => { 2 => 'Other' }, + NOTES => q{ + Information extracted from static libraries. + }, + # 0 string[16] ar_name + 16 => { + Name => 'CreateDate', + Groups => { 2 => 'Time' }, + Format => 'string[12]', + ValueConv => 'ConvertUnixTime($val,1)', + PrintConv => '$self->ConvertDateTime($val)', + }, + # 28 string[6] ar_uid + # 34 string[6] ar_gid + # 40 string[8] ar_mode + # 48 string[10] ar_size + # 58 string[2] terminator "`\n" +); + +# Microsoft compiled help format (ref http://www.russotto.net/chm/chmformat.html) +%Image::ExifTool::EXE::CHM = ( + PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData, + GROUPS => { 2 => 'Other' }, + NOTES => 'Tags extracted from Microsoft Compiled HTML files.', + FORMAT => 'int32u', + 1 => { Name => 'CHMVersion' }, + # 2 - total header length + # 3 - 1 + # 4 - low bits of date/time value plus 42 (ref http://www.nongnu.org/chmspec/latest/ITSF.html) + 5 => { + Name => 'LanguageCode', + SeparateTable => 1, + ValueConv => 'sprintf("%.4X", $val)', + PrintConv => \%languageCode, + }, +); + +#------------------------------------------------------------------------------ +# Extract information from a CHM file +# Inputs: 0) ExifTool object reference, 1) dirInfo reference +# Returns: 1 on success, 0 if this wasn't a valid CHM file +sub ProcessCHM($$) +{ + my ($et, $dirInfo) = @_; + my $raf = $$dirInfo{RAF}; + my $buff; + + return 0 unless $raf->Read($buff, 56) == 56 and + $buff =~ /^ITSF.{20}\x10\xfd\x01\x7c\xaa\x7b\xd0\x11\x9e\x0c\0\xa0\xc9\x22\xe6\xec/s; + my $tagTablePtr = GetTagTable('Image::ExifTool::EXE::CHM'); + $et->SetFileType(); + SetByteOrder('II'); + $et->ProcessDirectory({ DataPt => \$buff }, $tagTablePtr); + return 1; +} + +#------------------------------------------------------------------------------ +# Read Unicode string (null terminated) from resource +# Inputs: 0) data ref, 1) start offset, 2) data end, 3) optional ExifTool object ref +# Returns: 0) Unicode string translated to UTF8, or current CharSet with ExifTool ref +# 1) end pos (rounded up to nearest 4 bytes) +sub ReadUnicodeStr($$$;$) +{ + my ($dataPt, $pos, $end, $et) = @_; + $end = length $$dataPt if $end > length $$dataPt; # (be safe) + my $str = ''; + while ($pos + 2 <= $end) { + my $ch = substr($$dataPt, $pos, 2); + $pos += 2; + last if $ch eq "\0\0"; + $str .= $ch; + } + $pos += 2 if $pos & 0x03; + my $to = $et ? $et->Options('Charset') : 'UTF8'; + return (Image::ExifTool::Decode(undef,$str,'UCS2','II',$to), $pos); +} + +#------------------------------------------------------------------------------ +# Process Windows PE Version Resource +# Inputs: 0) ExifTool object ref, 1) dirInfo ref +# Returns: true on success +sub ProcessPEVersion($$) +{ + my ($et, $dirInfo) = @_; + my $dataPt = $$dirInfo{DataPt}; + my $pos = $$dirInfo{DirStart}; + my $end = $pos + $$dirInfo{DirLen}; + my ($index, $len, $valLen, $type, $string, $strEnd); + + # get VS_VERSION_INFO + for ($index = 0; ; ++$index) { + $pos = ($pos + 3) & 0xfffffffc; # align on a 4-byte boundary + last if $pos + 6 > $end; + $len = Get16u($dataPt, $pos); + $valLen = Get16u($dataPt, $pos + 2); + $type = Get16u($dataPt, $pos + 4); + return 0 unless $len or $valLen; # prevent possible infinite loop + ($string, $strEnd) = ReadUnicodeStr($dataPt, $pos + 6, $pos + $len); + return 0 if $strEnd + $valLen > $end; + unless ($index or $string eq 'VS_VERSION_INFO') { + $et->Warn('Invalid Version Info block'); + return 0; + } + if ($string eq 'VS_VERSION_INFO') { + # parse the fixed version info + $$dirInfo{DirStart} = $strEnd; + $$dirInfo{DirLen} = $valLen; + my $subTablePtr = GetTagTable('Image::ExifTool::EXE::PEVersion'); + $et->ProcessDirectory($dirInfo, $subTablePtr); + $pos = $strEnd + $valLen; + } elsif ($string eq 'StringFileInfo' and $valLen == 0) { + $pos += $len; + my $pt = $strEnd; + # parse string table + my $tagTablePtr = GetTagTable('Image::ExifTool::EXE::PEString'); + for ($index = 0; $pt + 6 < $pos; ++$index) { + $len = Get16u($dataPt, $pt); + $valLen = Get16u($dataPt, $pt + 2); + # $type = Get16u($dataPt, $pt + 4); + my $entryEnd = $pt + $len; + # get tag ID (converted to UTF8) + ($string, $pt) = ReadUnicodeStr($dataPt, $pt + 6, $entryEnd); + unless ($index) { + # separate the language code and character set + # (not sure what the CharacterSet tag is for, but the string + # values stored here are UCS-2 in all my files even if the + # CharacterSet is otherwise) + my $char; + if (length($string) > 4) { + $char = substr($string, 4); + $string = substr($string, 0, 4); + } + $et->HandleTag($tagTablePtr, 'LanguageCode', uc $string); + $et->HandleTag($tagTablePtr, 'CharacterSet', uc $char) if $char; + next; + } + my $tag = $string; + # create entry in tag table if it doesn't already exist + unless ($$tagTablePtr{$tag}) { + my $name = $tag; + $name =~ tr/-_a-zA-Z0-9//dc; # remove illegal characters + next unless length $name; + AddTagToTable($tagTablePtr, $tag, { Name => $name }); + } + # get tag value (converted to current Charset) + if ($valLen) { + ($string, $pt) = ReadUnicodeStr($dataPt, $pt, $entryEnd, $et); + } else { + $string = ''; + } + $et->HandleTag($tagTablePtr, $tag, $string); + # step to next entry (padded to an even word) + $pt = ($entryEnd + 3) & 0xfffffffc; + } + } else { + $pos += $len + $valLen; + # ignore other information (for now) + } + } + return 1; +} + +#------------------------------------------------------------------------------ +# Process Windows PE Resources +# Inputs: 0) ExifTool object ref, 1) dirInfo ref +# Returns: true on success +sub ProcessPEResources($$) +{ + my ($et, $dirInfo) = @_; + my $raf = $$dirInfo{RAF}; + my $base = $$dirInfo{Base}; + my $dirStart = $$dirInfo{DirStart} + $base; + my $level = $$dirInfo{Level} || 0; + my $verbose = $et->Options('Verbose'); + my ($buff, $buf2, $item); + + return 0 if $level > 10; # protect against deep recursion + # read the resource header + $raf->Seek($dirStart, 0) and $raf->Read($buff, 16) == 16 or return 0; + my $nameEntries = Get16u(\$buff, 12); + my $idEntries = Get16u(\$buff, 14); + my $count = $nameEntries + $idEntries; + $raf->Read($buff, $count * 8) == $count * 8 or return 0; + # loop through all resource entries + for ($item=0; $item<$count; ++$item) { + my $pos = $item * 8; + my $name = Get32u(\$buff, $pos); + my $entryPos = Get32u(\$buff, $pos + 4); + unless ($level) { + # set resource type if this is the 0th level directory + my $resType = $resourceType{$name} || sprintf('Unknown (0x%x)', $name); + # ignore everything but the Version resource unless verbose + if ($verbose) { + $et->VPrint(0, "$resType resource:\n"); + } else { + next unless $resType eq 'Version'; + } + $$dirInfo{ResType} = $resType; + } + if ($entryPos & 0x80000000) { # is this a directory? + # descend into next directory level + $$dirInfo{DirStart} = $entryPos & 0x7fffffff; + $$dirInfo{Level} = $level + 1; + ProcessPEResources($et, $dirInfo) or return 0; + --$$dirInfo{Level}; + } elsif ($$dirInfo{ResType} eq 'Version' and $level == 2 and + not $$dirInfo{GotVersion}) # (only process first Version resource) + { + # get position of this resource in the file + my $buf2; + $raf->Seek($entryPos + $base, 0) and $raf->Read($buf2, 16) == 16 or return 0; + my $off = Get32u(\$buf2, 0); + my $len = Get32u(\$buf2, 4); + # determine which section this is in so we can convert the virtual address + my ($section, $filePos); + foreach $section (@{$$dirInfo{Sections}}) { + next unless $off >= $$section{VirtualAddress} and + $off < $$section{VirtualAddress} + $$section{Size}; + $filePos = $off + $$section{Base} - $$section{VirtualAddress}; + last; + } + return 0 unless $filePos; + $raf->Seek($filePos, 0) and $raf->Read($buf2, $len) == $len or return 0; + ProcessPEVersion($et, { + DataPt => \$buf2, + DataLen => $len, + DirStart => 0, + DirLen => $len, + }) or $et->Warn('Possibly corrupt Version resource'); + $$dirInfo{GotVersion} = 1; # set flag so we don't do this again + } + } + return 1; +} + +#------------------------------------------------------------------------------ +# Process Windows PE file data dictionary +# Inputs: 0) ExifTool object ref, 1) dirInfo ref +# Returns: true on success +sub ProcessPEDict($$) +{ + my ($et, $dirInfo) = @_; + my $raf = $$dirInfo{RAF}; + my $dataPt = $$dirInfo{DataPt}; + my $dirLen = length($$dataPt); + my ($pos, @sections, %dirInfo); + + # loop through all sections + for ($pos=0; $pos+40<=$dirLen; $pos+=40) { + my $name = substr($$dataPt, $pos, 8); + my $va = Get32u($dataPt, $pos + 12); + my $size = Get32u($dataPt, $pos + 16); + my $offset = Get32u($dataPt, $pos + 20); + # remember the section offsets for the VirtualAddress lookup later + push @sections, { Base => $offset, Size => $size, VirtualAddress => $va }; + # save details of the first resource section + %dirInfo = ( + RAF => $raf, + Base => $offset, + DirStart => 0, # (relative to Base) + DirLen => $size, + Sections => \@sections, + ) if $name eq ".rsrc\0\0\0" and not %dirInfo; + } + # process the first resource section + ProcessPEResources($et, \%dirInfo) or return 0 if %dirInfo; + return 1; +} + +#------------------------------------------------------------------------------ +# Override file type if necessary for Mach object files and libraries +# Inputs: 0) ExifTool ref, 1) ObjectFileType number, 2) flag for fat binary +my %machOverride = ( + 1 => [ 'object file', 'O' ], + 6 => [ 'dynamic link library', 'DYLIB' ], + 8 => [ 'dynamic bound bundle', 'DYLIB' ], + 9 => [ 'dynamic link library stub', 'DYLIB' ], +); +sub MachOverride($$;$) +{ + my ($et, $objType, $fat) = @_; + my $override = $machOverride{$objType}; + if ($override) { + my $desc = 'Mach-O ' . ($fat ? 'fat ' : '') . $$override[0]; + $et->OverrideFileType($desc, undef, $$override[1]); + } +} + +#------------------------------------------------------------------------------ +# Extract tags from Mach header +# Inputs: 0) ExifTool ref, 1) data ref, 2) flag to extract object type +# Returns: true if Mach header was found +# Mach type based on magic number +# [bit depth, byte order starting with "Little" or "Big"] +my %machType = ( + "\xfe\xed\xfa\xce" => ['32 bit', 'Big endian'], + "\xce\xfa\xed\xfe" => ['32 bit', 'Little endian'], + "\xfe\xed\xfa\xcf" => ['64 bit', 'Big endian'], + "\xcf\xfa\xed\xfe" => ['64 bit', 'Little endian'], +); +sub ExtractMachTags($$;$) +{ + my ($et, $dataPt, $doObj) = @_; + # get information about mach header based on the magic number (first 4 bytes) + my $info = $machType{substr($$dataPt, 0, 4)}; + if ($info) { + # Mach header structure: + # 0 int32u magic + # 4 int32u cputype + # 8 int32u cpusubtype + # 12 int32u filetype + # 16 int32u ncmds + # 20 int32u sizeofcmds + # 24 int32u flags + my $tagTablePtr = GetTagTable('Image::ExifTool::EXE::MachO'); + SetByteOrder($$info[1]); + my $cpuType = Get32s($dataPt, 4); + my $subType = Get32s($dataPt, 8); + $et->HandleTag($tagTablePtr, 0, $$info[0]); + $et->HandleTag($tagTablePtr, 1, $$info[1]); + $et->HandleTag($tagTablePtr, 3, $cpuType); + $et->HandleTag($tagTablePtr, 4, "$cpuType $subType"); + if ($doObj) { + my $objType = Get32u($dataPt, 12); + my $flags = Get32u($dataPt, 24); + $et->HandleTag($tagTablePtr, 5, $objType); + $et->HandleTag($tagTablePtr, 6, $flags); + # override file type if this is an object file or library + MachOverride($et, $objType); + } else { # otherwise this was a static library + $et->OverrideFileType('Mach-O static library', undef, 'A'); + } + return 1; + } + return 0; +} + +#------------------------------------------------------------------------------ +# Extract information from an EXE file +# Inputs: 0) ExifTool object reference, 1) dirInfo reference +# Returns: 1 on success, 0 if this wasn't a valid EXE file +sub ProcessEXE($$) +{ + my ($et, $dirInfo) = @_; + my $raf = $$dirInfo{RAF}; + my ($buff, $buf2, $type, $mime, $ext, $tagTablePtr, %dirInfo); + + my $size = $raf->Read($buff, 0x40) or return 0; + my $fast3 = $$et{OPTIONS}{FastScan} && $$et{OPTIONS}{FastScan} == 3; +# +# DOS and Windows EXE +# + if ($buff =~ /^MZ/ and $size == 0x40) { + # DOS/Windows executable + # validate DOS header + # (ref http://www.delphidabbler.com/articles?article=8&part=2) + # 0 int16u magic - Magic number ("MZ") + # 2 int16u cblp - Bytes on last page of file + # 4 int16u cp - Pages in file + # 6 int16u crlc - Relocations + # 8 int16u cparhdr - Size of header in paragraphs + # 10 int16u minalloc - Minimum extra paragraphs needed + # 12 int16u maxalloc - Maximum extra paragraphs needed + # 14 int16u ss - Initial (relative) SS value + # 16 int16u sp - Initial SP value + # 18 int16u csum - Checksum + # 20 int16u ip - Initial IP value + # 22 int16u cs - Initial (relative) CS value + # 24 int16u lfarlc - Address of relocation table + # 26 int16u ovno - Overlay number + # 28 int16u[4] res - Reserved words + # 36 int16u oemid - OEM identifier (for oeminfo) + # 38 int16u oeminfo - OEM info; oemid specific + # 40 int16u[10] res2 - Reserved words + # 60 int32u; lfanew - File address of new exe header + SetByteOrder('II'); + my ($cblp, $cp, $lfarlc, $lfanew) = unpack('x2v2x18vx34V', $buff); + my $fileSize = ($cp - ($cblp ? 1 : 0)) * 512 + $cblp; + #(patch to accommodate observed 64-bit files) + #return 0 if $fileSize < 0x40 or $fileSize < $lfarlc; + return 0 if $fileSize < 0x40; + # read the Windows NE, PE or LE (virtual device driver) header + #if ($lfarlc == 0x40 and $fileSize > $lfanew + 2 and ... + if ($raf->Seek($lfanew, 0) and $raf->Read($buff, 0x40) and $buff =~ /^(NE|PE|LE)/) { + if ($1 eq 'NE') { + if ($size >= 0x40) { # NE header is 64 bytes (ref 2) + # check for DLL + my $appFlags = Get16u(\$buff, 0x0c); + $ext = $appFlags & 0x80 ? 'DLL' : 'EXE'; + $type = "Win16 $ext"; + # offset 0x02 is 2 bytes with linker version and revision numbers + # offset 0x36 is executable type (2 = Windows) + } + } elsif ($1 eq 'PE') { + # PE header comes at byte 4 in buff: + # 4 int16u Machine + # 6 int16u NumberOfSections + # 8 int32u TimeDateStamp + # 12 int32u PointerToSymbolTable + # 16 int32u NumberOfSymbols + # 20 int16u SizeOfOptionalHeader + # 22 int16u Characteristics + if ($size >= 24) { # PE header is 24 bytes (plus optional header) + my $mach = Get16u(\$buff, 4); # MachineType + my $flags = Get16u(\$buff, 22); # ImageFileCharacteristics + my $machine = $Image::ExifTool::EXE::Main{0}{PrintConv}{$mach} || ''; + my $winType = $machine =~ /64/ ? 'Win64' : 'Win32'; + $ext = $flags & 0x2000 ? 'DLL' : 'EXE'; + $et->SetFileType("$winType $ext", undef, $ext); + return 1 if $fast3; + # read the rest of the optional header if necessary + my $optSize = Get16u(\$buff, 20); + my $more = $optSize + 24 - $size; + if ($more > 0) { + if ($raf->Read($buf2, $more) == $more) { + $buff .= $buf2; + $size += $more; + my $magic = Get16u(\$buff, 24); + # verify PE magic number + unless ($magic == 0x107 or $magic == 0x10b or $magic == 0x20b) { + $et->Warn('Unknown PE magic number'); + return 1; + } + # --> 64-bit if $magic is 0x20b ???? + } else { + $et->Warn('Error reading optional header'); + } + } + # process PE COFF file header + $tagTablePtr = GetTagTable('Image::ExifTool::EXE::Main'); + %dirInfo = ( + DataPt => \$buff, + DataPos => $raf->Tell() - $size, + DataLen => $size, + DirStart => 4, + DirLen => $size - 4, + ); + $et->ProcessDirectory(\%dirInfo, $tagTablePtr); + # process data dictionary + my $num = Get16u(\$buff, 6); # NumberOfSections + if ($raf->Read($buff, 40 * $num) == 40 * $num) { + %dirInfo = ( + RAF => $raf, + DataPt => \$buff, + ); + ProcessPEDict($et, \%dirInfo) or $et->Warn('Error processing PE data dictionary'); + } + return 1; + } + } else { + $type = 'Virtual Device Driver'; + $ext = '386'; + } + } else { + $type = 'DOS EXE'; + $ext = 'exe'; + } +# +# Mach-O (Mac OS X) +# + } elsif ($buff =~ /^(\xca\xfe\xba\xbe|\xfe\xed\xfa(\xce|\xcf)|(\xce|\xcf)\xfa\xed\xfe)/ and $size > 12) { + # Mach-O executable + # (ref http://developer.apple.com/documentation/DeveloperTools/Conceptual/MachORuntime/Reference/reference.html) + $tagTablePtr = GetTagTable('Image::ExifTool::EXE::MachO'); + if ($1 eq "\xca\xfe\xba\xbe") { + SetByteOrder('MM'); + $et->SetFileType('Mach-O fat binary executable', undef, ''); + return 1 if $fast3; + my $count = Get32u(\$buff, 4); # get architecture count + my $more = $count * 20 - ($size - 8); + if ($more > 0) { + unless ($raf->Read($buf2, $more) == $more) { + $et->Warn('Error reading fat-arch headers'); + return 1; + } + $buff .= $buf2; + $size += $more; + } + $et->HandleTag($tagTablePtr, 2, $count); + my $i; + for ($i=0; $i<$count; ++$i) { + my $cpuType = Get32s(\$buff, 8 + $i * 20); + my $subType = Get32s(\$buff, 12 + $i * 20); + $et->HandleTag($tagTablePtr, 3, $cpuType); + $et->HandleTag($tagTablePtr, 4, "$cpuType $subType"); + } + # load first Mach-O header to get the object file type + my $offset = Get32u(\$buff, 16); + if ($raf->Seek($offset, 0) and $raf->Read($buf2, 16) == 16) { + if ($buf2 =~ /^(\xfe\xed\xfa(\xce|\xcf)|(\xce|\xcf)\xfa\xed\xfe)/) { + SetByteOrder($buf2 =~ /^\xfe\xed/ ? 'MM' : 'II'); + my $objType = Get32u(\$buf2, 12); + $et->HandleTag($tagTablePtr, 5, $objType); + # override file type if this is a library or object file + MachOverride($et, $objType, 'fat'); + } elsif ($buf2 =~ /^!<arch>\x0a/) { + # .a libraries use this magic number + $et->HandleTag($tagTablePtr, 5, -1); + # override file type since this is a library + $et->OverrideFileType('Mach-O fat static library', undef, 'A'); + } else { + $et->Warn('Unrecognized object file type'); + } + } else { + $et->Warn('Error reading file'); + } + } elsif ($size >= 16) { + $et->SetFileType('Mach-O executable', undef, ''); + return 1 if $fast3; + ExtractMachTags($et, \$buff, 1); + } + return 1; +# +# PEF (classic MacOS) +# + } elsif ($buff =~ /^Joy!peff/ and $size > 12) { + # ref http://developer.apple.com/documentation/mac/pdf/MacOS_RT_Architectures.pdf + $et->SetFileType('Classic MacOS executable', undef, ''); + return 1 if $fast3; + SetByteOrder('MM'); + $tagTablePtr = GetTagTable('Image::ExifTool::EXE::PEF'); + %dirInfo = ( + DataPt => \$buff, + DataPos => 0, + DataLen => $size, + DirStart => 0, + DirLen => $size, + ); + $et->ProcessDirectory(\%dirInfo, $tagTablePtr); + return 1; +# +# ELF (Unix) +# + } elsif ($buff =~ /^\x7fELF/ and $size >= 16) { + $et->SetFileType('ELF executable', undef, ''); + return 1 if $fast3; + SetByteOrder(Get8u(\$buff,5) == 1 ? 'II' : 'MM'); + $tagTablePtr = GetTagTable('Image::ExifTool::EXE::ELF'); + %dirInfo = ( + DataPt => \$buff, + DataPos => 0, + DataLen => $size, + DirLen => $size, + ); + $et->ProcessDirectory(\%dirInfo, $tagTablePtr); + # override file type if this is a library or object file + my $override = { + 1 => [ 'ELF object file', 'O' ], + 3 => [ 'ELF shared library', 'SO' ], + }->{$$et{VALUE}{ObjectFileType} || 0}; + $et->OverrideFileType($$override[0], undef, $$override[1]) if $override; + return 1; +# +# .a libraries +# + } elsif ($buff =~ /^!<arch>\x0a/) { + $et->SetFileType('Static library', undef, 'A'); + return 1 if $fast3; + my $pos = 8; # current file position + my $max = 10; # maximum number of archive files to check + # read into list of ar structures (each 60 bytes long): + while ($max-- > 0) { + # seek to start of the ar structure and read it + $raf->Seek($pos, 0) and $raf->Read($buff, 60) == 60 or last; + substr($buff, 58, 2) eq "`\n" or $et->Warn('Invalid archive header'), last; + unless ($tagTablePtr) { + # extract some information from first file in archive + $tagTablePtr = GetTagTable('Image::ExifTool::EXE::AR'); + %dirInfo = ( + DataPt => \$buff, + DataPos => $pos, + ); + $et->ProcessDirectory(\%dirInfo, $tagTablePtr); + } + my $name = substr($buff, 0, 16); + if ($name =~ m{^#1/(\d+) *$}) { # check for extended archive (BSD variant) + my $len = $1; + $len > 256 and $et->Warn('Invalid extended archive name length'), last; + # (we read the name here just to move the file pointer) + $raf->Read($name, $len) == $len or $et->Warn('Error reading archive name'), last; + } + my $arSize = substr($buff, 48, 10); + $arSize =~ s/^(\d+).*/$1/s or last; # make sure archive size is a number + $raf->Read($buff, 28) == 28 or last; # read (possible) Mach header + ExtractMachTags($et, \$buff) and last; # try to extract tags + $pos += 60 + $arSize; # step to next entry + ++$pos if $pos & 0x01; # padded to an even byte + } + return 1; +# +# various scripts (perl, sh, etc...) +# + } elsif ($buff =~ m{^#!\s*/\S*bin/(\w+)}) { + my $prog = $1; + $prog = $1 if $prog eq 'env' and $buff =~ /\b(perl|python|ruby|php)\b/; + $type = "$prog script"; + $mime = "text/x-$prog"; + $ext = { + perl => 'pl', + python => 'py', + ruby => 'rb', + php => 'php', + }->{$1}; + # use '.sh' for extension of all shell scripts + $ext = $prog =~ /sh$/ ? 'sh' : '' unless defined $ext; + } + return 0 unless $type; + $et->SetFileType($type, $mime, $ext); + return 1; +} + +1; # end + +__END__ + +=head1 NAME + +Image::ExifTool::EXE - Read executable file meta information + +=head1 SYNOPSIS + +This module is used by Image::ExifTool + +=head1 DESCRIPTION + +This module contains definitions required by Image::ExifTool to extract meta +information from various types of Windows, MacOS and Unix executable and +library files. + +=head1 AUTHOR + +Copyright 2003-2019, Phil Harvey (phil at owl.phy.queensu.ca) + +This library is free software; you can redistribute it and/or modify it +under the same terms as Perl itself. + +=head1 REFERENCES + +=over 4 + +=item L<http://www.openwatcom.org/ftp/devel/docs/pecoff.pdf> + +=item L<http://support.microsoft.com/kb/65122> + +=item L<http://www.opensource.apple.com> + +=item L<http://www.skyfree.org/linux/references/ELF_Format.pdf> + +=item L<http://msdn.microsoft.com/en-us/library/ms809762.aspx> + +=item L<http://code.google.com/p/pefile/> + +=item L<http://www.codeproject.com/KB/DLL/showver.aspx> + +=back + +=head1 SEE ALSO + +L<Image::ExifTool::TagNames/EXE Tags>, +L<Image::ExifTool(3pm)|Image::ExifTool> + +=cut + diff --git a/lib/Image/ExifTool/Exif.pm b/lib/Image/ExifTool/Exif.pm new file mode 100644 index 0000000..b779c9b --- /dev/null +++ b/lib/Image/ExifTool/Exif.pm @@ -0,0 +1,6384 @@ +#------------------------------------------------------------------------------ +# File: Exif.pm +# +# Description: Read EXIF/TIFF meta information +# +# Revisions: 11/25/2003 - P. Harvey Created +# 02/06/2004 - P. Harvey Moved processing functions from ExifTool +# 03/19/2004 - P. Harvey Check PreviewImage for validity +# 11/11/2004 - P. Harvey Split off maker notes into MakerNotes.pm +# 12/13/2004 - P. Harvey Added AUTOLOAD to load write routines +# +# References: 0) http://www.exif.org/Exif2-2.PDF +# 1) http://partners.adobe.com/asn/developer/pdfs/tn/TIFF6.pdf +# 2) http://www.adobe.com/products/dng/pdfs/dng_spec_1_3_0_0.pdf +# 3) http://www.awaresystems.be/imaging/tiff/tifftags.html +# 4) http://www.remotesensing.org/libtiff/TIFFTechNote2.html +# 5) http://www.exif.org/dcf.PDF +# 6) http://park2.wakwak.com/~tsuruzoh/Computer/Digicams/exif-e.html +# 7) http://www.fine-view.com/jp/lab/doc/ps6ffspecsv2.pdf +# 8) http://www.ozhiker.com/electronics/pjmt/jpeg_info/meta.html +# 9) http://hul.harvard.edu/jhove/tiff-tags.html +# 10) http://partners.adobe.com/public/developer/en/tiff/TIFFPM6.pdf +# 11) Robert Mucke private communication +# 12) http://www.broomscloset.com/closet/photo/exif/TAG2000-22_DIS12234-2.PDF +# 13) http://www.microsoft.com/whdc/xps/wmphoto.mspx +# 14) http://www.asmail.be/msg0054681802.html +# 15) http://crousseau.free.fr/imgfmt_raw.htm +# 16) http://www.cybercom.net/~dcoffin/dcraw/ +# 17) http://www.digitalpreservation.gov/formats/content/tiff_tags.shtml +# 18) http://www.asmail.be/msg0055568584.html +# 19) http://libpsd.graphest.com/files/Photoshop%20File%20Formats.pdf +# 20) http://tiki-lounge.com/~raf/tiff/fields.html +# 21) http://community.roxen.com/developers/idocs/rfc/rfc3949.html +# 22) http://tools.ietf.org/html/draft-ietf-fax-tiff-fx-extension1-01 +# 23) MetaMorph Stack (STK) Image File Format: +# --> ftp://ftp.meta.moleculardevices.com/support/stack/STK.doc +# 24) http://www.cipa.jp/std/documents/e/DC-008-2012_E.pdf (Exif 2.3) +# 25) Vesa Kivisto private communication (7D) +# 26) Jeremy Brown private communication +# 27) Gregg Lee private communication +# 28) http://wwwimages.adobe.com/www.adobe.com/content/dam/Adobe/en/devnet/cinemadng/pdfs/CinemaDNG_Format_Specification_v1_1.pdf +# 29) http://www.libtiff.org +# 30) http://geotiff.maptools.org/spec/geotiffhome.html +# 31) https://android.googlesource.com/platform/external/dng_sdk/+/refs/heads/master/source/dng_tag_codes.h +# IB) Iliah Borg private communication (LibRaw) +# JD) Jens Duttke private communication +#------------------------------------------------------------------------------ + +package Image::ExifTool::Exif; + +use strict; +use vars qw($VERSION $AUTOLOAD @formatSize @formatName %formatNumber %intFormat + %lightSource %flash %compression %photometricInterpretation %orientation + %subfileType %saveForValidate); +use Image::ExifTool qw(:DataAccess :Utils); +use Image::ExifTool::MakerNotes; + +$VERSION = '4.11'; + +sub ProcessExif($$$); +sub WriteExif($$$); +sub CheckExif($$$); +sub RebuildMakerNotes($$$); +sub EncodeExifText($$); +sub ValidateIFD($;$); +sub ValidateImageData($$$;$); +sub ProcessTiffIFD($$$); +sub PrintParameter($$$); +sub GetOffList($$$$$); +sub PrintLensInfo($); +sub ConvertLensInfo($); + +# size limit for loading binary data block into memory +sub BINARY_DATA_LIMIT { return 10 * 1024 * 1024; } + +# byte sizes for the various EXIF format types below +@formatSize = (undef,1,1,2,4,8,1,1,2,4,8,4,8,4,2,8,8,8,8); + +@formatName = ( + undef, 'int8u', 'string', 'int16u', + 'int32u', 'rational64u','int8s', 'undef', + 'int16s', 'int32s', 'rational64s','float', + 'double', 'ifd', 'unicode', 'complex', + 'int64u', 'int64s', 'ifd64', # (new BigTIFF formats) +); + +# hash to look up EXIF format numbers by name +# (format types are all lower case) +%formatNumber = ( + 'int8u' => 1, # BYTE + 'string' => 2, # ASCII + 'int16u' => 3, # SHORT + 'int32u' => 4, # LONG + 'rational64u' => 5, # RATIONAL + 'int8s' => 6, # SBYTE + 'undef' => 7, # UNDEFINED + 'binary' => 7, # (same as undef) + 'int16s' => 8, # SSHORT + 'int32s' => 9, # SLONG + 'rational64s' => 10, # SRATIONAL + 'float' => 11, # FLOAT + 'double' => 12, # DOUBLE + 'ifd' => 13, # IFD (with int32u format) + 'unicode' => 14, # UNICODE [see Note below] + 'complex' => 15, # COMPLEX [see Note below] + 'int64u' => 16, # LONG8 [BigTIFF] + 'int64s' => 17, # SLONG8 [BigTIFF] + 'ifd64' => 18, # IFD8 (with int64u format) [BigTIFF] + # Note: unicode and complex types are not yet properly supported by ExifTool. + # These are types which have been observed in the Adobe DNG SDK code, but + # aren't fully supported there either. We know the sizes, but that's about it. + # We don't know if the unicode is null terminated, or the format for complex + # (although I suspect it would be two 4-byte floats, real and imaginary). +); + +# lookup for integer format strings +%intFormat = ( + 'int8u' => 1, + 'int16u' => 3, + 'int32u' => 4, + 'int8s' => 6, + 'int16s' => 8, + 'int32s' => 9, + 'ifd' => 13, + 'int64u' => 16, + 'int64s' => 17, + 'ifd64' => 18, +); + +# EXIF LightSource PrintConv values +%lightSource = ( + 0 => 'Unknown', + 1 => 'Daylight', + 2 => 'Fluorescent', + 3 => 'Tungsten (Incandescent)', + 4 => 'Flash', + 9 => 'Fine Weather', + 10 => 'Cloudy', + 11 => 'Shade', + 12 => 'Daylight Fluorescent', # (D 5700 - 7100K) + 13 => 'Day White Fluorescent', # (N 4600 - 5500K) + 14 => 'Cool White Fluorescent', # (W 3800 - 4500K) + 15 => 'White Fluorescent', # (WW 3250 - 3800K) + 16 => 'Warm White Fluorescent', # (L 2600 - 3250K) + 17 => 'Standard Light A', + 18 => 'Standard Light B', + 19 => 'Standard Light C', + 20 => 'D55', + 21 => 'D65', + 22 => 'D75', + 23 => 'D50', + 24 => 'ISO Studio Tungsten', + 255 => 'Other', +); + +# EXIF Flash values +%flash = ( + OTHER => sub { + # translate "Off" and "On" when writing + my ($val, $inv) = @_; + return undef unless $inv and $val =~ /^(off|on)$/i; + return lc $val eq 'off' ? 0x00 : 0x01; + }, + 0x00 => 'No Flash', + 0x01 => 'Fired', + 0x05 => 'Fired, Return not detected', + 0x07 => 'Fired, Return detected', + 0x08 => 'On, Did not fire', # not charged up? + 0x09 => 'On, Fired', + 0x0d => 'On, Return not detected', + 0x0f => 'On, Return detected', + 0x10 => 'Off, Did not fire', + 0x14 => 'Off, Did not fire, Return not detected', + 0x18 => 'Auto, Did not fire', + 0x19 => 'Auto, Fired', + 0x1d => 'Auto, Fired, Return not detected', + 0x1f => 'Auto, Fired, Return detected', + 0x20 => 'No flash function', + 0x30 => 'Off, No flash function', + 0x41 => 'Fired, Red-eye reduction', + 0x45 => 'Fired, Red-eye reduction, Return not detected', + 0x47 => 'Fired, Red-eye reduction, Return detected', + 0x49 => 'On, Red-eye reduction', + 0x4d => 'On, Red-eye reduction, Return not detected', + 0x4f => 'On, Red-eye reduction, Return detected', + 0x50 => 'Off, Red-eye reduction', + 0x58 => 'Auto, Did not fire, Red-eye reduction', + 0x59 => 'Auto, Fired, Red-eye reduction', + 0x5d => 'Auto, Fired, Red-eye reduction, Return not detected', + 0x5f => 'Auto, Fired, Red-eye reduction, Return detected', +); + +# TIFF Compression values +# (values with format "Xxxxx XXX Compressed" are used to identify RAW file types) +%compression = ( + 1 => 'Uncompressed', + 2 => 'CCITT 1D', + 3 => 'T4/Group 3 Fax', + 4 => 'T6/Group 4 Fax', + 5 => 'LZW', + 6 => 'JPEG (old-style)', #3 + 7 => 'JPEG', #4 + 8 => 'Adobe Deflate', #3 + 9 => 'JBIG B&W', #3 + 10 => 'JBIG Color', #3 + 99 => 'JPEG', #16 + 262 => 'Kodak 262', #16 + 32766 => 'Next', #3 + 32767 => 'Sony ARW Compressed', #16 + 32769 => 'Packed RAW', #PH (used by Epson, Nikon, Samsung) + 32770 => 'Samsung SRW Compressed', #PH + 32771 => 'CCIRLEW', #3 + 32772 => 'Samsung SRW Compressed 2', #PH (NX3000,NXmini) + 32773 => 'PackBits', + 32809 => 'Thunderscan', #3 + 32867 => 'Kodak KDC Compressed', #PH + 32895 => 'IT8CTPAD', #3 + 32896 => 'IT8LW', #3 + 32897 => 'IT8MP', #3 + 32898 => 'IT8BL', #3 + 32908 => 'PixarFilm', #3 + 32909 => 'PixarLog', #3 + # 32910,32911 - Pixar reserved + 32946 => 'Deflate', #3 + 32947 => 'DCS', #3 + 33003 => 'Aperio JPEG 2000 YCbCr', #https://openslide.org/formats/aperio/ + 33005 => 'Aperio JPEG 2000 RGB', #https://openslide.org/formats/aperio/ + 34661 => 'JBIG', #3 + 34676 => 'SGILog', #3 + 34677 => 'SGILog24', #3 + 34712 => 'JPEG 2000', #3 + 34713 => 'Nikon NEF Compressed', #PH + 34715 => 'JBIG2 TIFF FX', #20 + 34718 => 'Microsoft Document Imaging (MDI) Binary Level Codec', #18 + 34719 => 'Microsoft Document Imaging (MDI) Progressive Transform Codec', #18 + 34720 => 'Microsoft Document Imaging (MDI) Vector', #18 + 34887 => 'ESRI Lerc', #LibTiff + # 34888,34889 - ESRI reserved + 34892 => 'Lossy JPEG', # (DNG 1.4) + 34925 => 'LZMA2', #LibTiff + 34926 => 'Zstd', #LibTiff + 34927 => 'WebP', #LibTiff + 34933 => 'PNG', # (TIFF mail list) + 34934 => 'JPEG XR', # (TIFF mail list) + 65000 => 'Kodak DCR Compressed', #PH + 65535 => 'Pentax PEF Compressed', #Jens +); + +%photometricInterpretation = ( + 0 => 'WhiteIsZero', + 1 => 'BlackIsZero', + 2 => 'RGB', + 3 => 'RGB Palette', + 4 => 'Transparency Mask', + 5 => 'CMYK', + 6 => 'YCbCr', + 8 => 'CIELab', + 9 => 'ICCLab', #3 + 10 => 'ITULab', #3 + 32803 => 'Color Filter Array', #2 + 32844 => 'Pixar LogL', #3 + 32845 => 'Pixar LogLuv', #3 + 32892 => 'Sequential Color Filter', #JR (Sony ARQ) + 34892 => 'Linear Raw', #2 +); + +%orientation = ( + 1 => 'Horizontal (normal)', + 2 => 'Mirror horizontal', + 3 => 'Rotate 180', + 4 => 'Mirror vertical', + 5 => 'Mirror horizontal and rotate 270 CW', + 6 => 'Rotate 90 CW', + 7 => 'Mirror horizontal and rotate 90 CW', + 8 => 'Rotate 270 CW', +); + +%subfileType = ( + 0 => 'Full-resolution Image', + 1 => 'Reduced-resolution image', + 2 => 'Single page of multi-page image', + 3 => 'Single page of multi-page reduced-resolution image', + 4 => 'Transparency mask', + 5 => 'Transparency mask of reduced-resolution image', + 6 => 'Transparency mask of multi-page image', + 7 => 'Transparency mask of reduced-resolution multi-page image', + 0x10001 => 'Alternate reduced-resolution image', # (DNG 1.2) + 0xffffffff => 'invalid', #(found in E5700 NEF's) + BITMASK => { + 0 => 'Reduced resolution', + 1 => 'Single page', + 2 => 'Transparency mask', + 3 => 'TIFF/IT final page', #20 + 4 => 'TIFF-FX mixed raster content', #20 + }, +); + +# PrintConv for parameter tags +%Image::ExifTool::Exif::printParameter = ( + PrintConv => { + 0 => 'Normal', + OTHER => \&Image::ExifTool::Exif::PrintParameter, + }, +); + +# convert DNG UTF-8 string values (may be string or int8u format) +my %utf8StringConv = ( + Writable => 'string', + Format => 'string', + ValueConv => '$self->Decode($val, "UTF8")', + ValueConvInv => '$self->Encode($val,"UTF8")', +); + +# ValueConv that makes long values binary type +my %longBin = ( + ValueConv => 'length($val) > 64 ? \$val : $val', + ValueConvInv => '$val', +); + +# PrintConv for SampleFormat (0x153) +my %sampleFormat = ( + 1 => 'Unsigned', # unsigned integer + 2 => 'Signed', # two's complement signed integer + 3 => 'Float', # IEEE floating point + 4 => 'Undefined', + 5 => 'Complex int', # complex integer (ref 3) + 6 => 'Complex float', # complex IEEE floating point (ref 3) +); + +# save the values of these tags for additional validation checks +%saveForValidate = ( + 0x100 => 1, # ImageWidth + 0x101 => 1, # ImageHeight + 0x102 => 1, # BitsPerSample + 0x103 => 1, # Compression + 0x115 => 1, # SamplesPerPixel +); + +# main EXIF tag table +%Image::ExifTool::Exif::Main = ( + GROUPS => { 0 => 'EXIF', 1 => 'IFD0', 2 => 'Image'}, + WRITE_PROC => \&WriteExif, + CHECK_PROC => \&CheckExif, + WRITE_GROUP => 'ExifIFD', # default write group + SET_GROUP1 => 1, # set group1 name to directory name for all tags in table + 0x1 => { + Name => 'InteropIndex', + Description => 'Interoperability Index', + Protected => 1, + Writable => 'string', + WriteGroup => 'InteropIFD', + PrintConv => { + R98 => 'R98 - DCF basic file (sRGB)', + R03 => 'R03 - DCF option file (Adobe RGB)', + THM => 'THM - DCF thumbnail file', + }, + }, + 0x2 => { #5 + Name => 'InteropVersion', + Description => 'Interoperability Version', + Protected => 1, + Writable => 'undef', + Mandatory => 1, + WriteGroup => 'InteropIFD', + RawConv => '$val=~s/\0+$//; $val', # (some idiots add null terminators) + }, + 0x0b => { #PH + Name => 'ProcessingSoftware', + Writable => 'string', + WriteGroup => 'IFD0', + Notes => 'used by ACD Systems Digital Imaging', + }, + 0xfe => { + Name => 'SubfileType', + Notes => 'called NewSubfileType by the TIFF specification', + Protected => 1, + Writable => 'int32u', + WriteGroup => 'IFD0', + # set priority directory if this is the full resolution image + DataMember => 'SubfileType', + RawConv => '$self->SetPriorityDir() if $val eq "0"; $$self{SubfileType} = $val', + PrintConv => \%subfileType, + }, + 0xff => { + Name => 'OldSubfileType', + Notes => 'called SubfileType by the TIFF specification', + Protected => 1, + Writable => 'int16u', + WriteGroup => 'IFD0', + # set priority directory if this is the full resolution image + RawConv => '$self->SetPriorityDir() if $val eq "1"; $val', + PrintConv => { + 1 => 'Full-resolution image', + 2 => 'Reduced-resolution image', + 3 => 'Single page of multi-page image', + }, + }, + 0x100 => { + Name => 'ImageWidth', + # even though Group 1 is set dynamically we need to register IFD1 once + # so it will show up in the group lists + Groups => { 1 => 'IFD1' }, + Protected => 1, + Writable => 'int32u', + WriteGroup => 'IFD0', + # Note: priority 0 tags automatically have their priority increased for the + # priority direcory (the directory with a SubfileType of "Full-resolution image") + Priority => 0, + }, + 0x101 => { + Name => 'ImageHeight', + Notes => 'called ImageLength by the EXIF spec.', + Protected => 1, + Writable => 'int32u', + WriteGroup => 'IFD0', + Priority => 0, + }, + 0x102 => { + Name => 'BitsPerSample', + Protected => 1, + Writable => 'int16u', + WriteGroup => 'IFD0', + Count => -1, # can be 1 or 3: -1 means 'variable' + Priority => 0, + }, + 0x103 => { + Name => 'Compression', + Protected => 1, + Writable => 'int16u', + WriteGroup => 'IFD0', + Mandatory => 1, + DataMember => 'Compression', + SeparateTable => 'Compression', + RawConv => q{ + Image::ExifTool::Exif::IdentifyRawFile($self, $val); + return $$self{Compression} = $val; + }, + PrintConv => \%compression, + Priority => 0, + }, + 0x106 => { + Name => 'PhotometricInterpretation', + Protected => 1, + Writable => 'int16u', + WriteGroup => 'IFD0', + PrintConv => \%photometricInterpretation, + Priority => 0, + }, + 0x107 => { + Name => 'Thresholding', + Protected => 1, + Writable => 'int16u', + WriteGroup => 'IFD0', + PrintConv => { + 1 => 'No dithering or halftoning', + 2 => 'Ordered dither or halftone', + 3 => 'Randomized dither', + }, + }, + 0x108 => { + Name => 'CellWidth', + Protected => 1, + Writable => 'int16u', + WriteGroup => 'IFD0', + }, + 0x109 => { + Name => 'CellLength', + Protected => 1, + Writable => 'int16u', + WriteGroup => 'IFD0', + }, + 0x10a => { + Name => 'FillOrder', + Protected => 1, + Writable => 'int16u', + WriteGroup => 'IFD0', + PrintConv => { + 1 => 'Normal', + 2 => 'Reversed', + }, + }, + 0x10d => { + Name => 'DocumentName', + Writable => 'string', + WriteGroup => 'IFD0', + }, + 0x10e => { + Name => 'ImageDescription', + Writable => 'string', + WriteGroup => 'IFD0', + Priority => 0, + }, + 0x10f => { + Name => 'Make', + Groups => { 2 => 'Camera' }, + Writable => 'string', + WriteGroup => 'IFD0', + DataMember => 'Make', + # remove trailing blanks and save as an ExifTool member variable + RawConv => '$val =~ s/\s+$//; $$self{Make} = $val', + # NOTE: trailing "blanks" (spaces) are removed from all EXIF tags which + # may be "unknown" (filled with spaces) according to the EXIF spec. + # This allows conditional replacement with "exiftool -TAG-= -TAG=VALUE". + # - also removed are any other trailing whitespace characters + }, + 0x110 => { + Name => 'Model', + Description => 'Camera Model Name', + Groups => { 2 => 'Camera' }, + Writable => 'string', + WriteGroup => 'IFD0', + DataMember => 'Model', + # remove trailing blanks and save as an ExifTool member variable + RawConv => '$val =~ s/\s+$//; $$self{Model} = $val', + }, + 0x111 => [ + { + Condition => q[ + $$self{TIFF_TYPE} eq 'MRW' and $$self{DIR_NAME} eq 'IFD0' and + $$self{Model} =~ /^DiMAGE A200/ + ], + Name => 'StripOffsets', + IsOffset => 1, + OffsetPair => 0x117, # point to associated byte counts + # A200 stores this information in the wrong byte order!! + ValueConv => '$val=join(" ",unpack("N*",pack("V*",split(" ",$val))));\$val', + ByteOrder => 'LittleEndian', + }, + { + # (APP1 IFD2 is for Leica JPEG preview) + Condition => q[ + not ($$self{TIFF_TYPE} eq 'CR2' and $$self{DIR_NAME} eq 'IFD0') and + not ($$self{TIFF_TYPE} eq 'DNG' and $$self{Compression} eq '7' and $$self{SubfileType} ne '0') and + not ($$self{TIFF_TYPE} eq 'APP1' and $$self{DIR_NAME} eq 'IFD2') + ], + Name => 'StripOffsets', + IsOffset => 1, + OffsetPair => 0x117, # point to associated byte counts + ValueConv => 'length($val) > 32 ? \$val : $val', + }, + { + # PreviewImageStart in IFD0 of CR2 images + Condition => '$$self{TIFF_TYPE} eq "CR2"', + Name => 'PreviewImageStart', + IsOffset => 1, + OffsetPair => 0x117, + Notes => q{ + called StripOffsets in most locations, but it is PreviewImageStart in IFD0 + of CR2 images and various IFD's of DNG images except for SubIFD2 where it is + JpgFromRawStart + }, + DataTag => 'PreviewImage', + Writable => 'int32u', + WriteGroup => 'IFD0', + Protected => 2, + Permanent => 1, + }, + { + # PreviewImageStart in various IFD's of DNG images except SubIFD2 + Condition => '$$self{DIR_NAME} ne "SubIFD2"', + Name => 'PreviewImageStart', + IsOffset => 1, + OffsetPair => 0x117, + DataTag => 'PreviewImage', + Writable => 'int32u', + WriteGroup => 'All', # (writes to specific group of associated Composite tag) + Protected => 2, + Permanent => 1, + }, + { + # JpgFromRawStart in various IFD's of DNG images except SubIFD2 + Name => 'JpgFromRawStart', + IsOffset => 1, + OffsetPair => 0x117, + DataTag => 'JpgFromRaw', + Writable => 'int32u', + WriteGroup => 'SubIFD2', + Protected => 2, + Permanent => 1, + }, + ], + 0x112 => { + Name => 'Orientation', + Writable => 'int16u', + WriteGroup => 'IFD0', + PrintConv => \%orientation, + Priority => 0, # so PRIORITY_DIR takes precedence + }, + 0x115 => { + Name => 'SamplesPerPixel', + Protected => 1, + Writable => 'int16u', + WriteGroup => 'IFD0', + Priority => 0, + }, + 0x116 => { + Name => 'RowsPerStrip', + Protected => 1, + Writable => 'int32u', + WriteGroup => 'IFD0', + Priority => 0, + }, + 0x117 => [ + { + Condition => q[ + $$self{TIFF_TYPE} eq 'MRW' and $$self{DIR_NAME} eq 'IFD0' and + $$self{Model} =~ /^DiMAGE A200/ + ], + Name => 'StripByteCounts', + OffsetPair => 0x111, # point to associated offset + # A200 stores this information in the wrong byte order!! + ValueConv => '$val=join(" ",unpack("N*",pack("V*",split(" ",$val))));\$val', + ByteOrder => 'LittleEndian', + }, + { + # (APP1 IFD2 is for Leica JPEG preview) + Condition => q[ + not ($$self{TIFF_TYPE} eq 'CR2' and $$self{DIR_NAME} eq 'IFD0') and + not ($$self{TIFF_TYPE} eq 'DNG' and $$self{Compression} eq '7' and $$self{SubfileType} ne '0') and + not ($$self{TIFF_TYPE} eq 'APP1' and $$self{DIR_NAME} eq 'IFD2') + ], + Name => 'StripByteCounts', + OffsetPair => 0x111, # point to associated offset + ValueConv => 'length($val) > 32 ? \$val : $val', + }, + { + # PreviewImageLength in IFD0 of CR2 images + Condition => '$$self{TIFF_TYPE} eq "CR2"', + Name => 'PreviewImageLength', + OffsetPair => 0x111, + Notes => q{ + called StripByteCounts in most locations, but it is PreviewImageLength in + IFD0 of CR2 images and various IFD's of DNG images except for SubIFD2 where + it is JpgFromRawLength + }, + DataTag => 'PreviewImage', + Writable => 'int32u', + WriteGroup => 'IFD0', + Protected => 2, + Permanent => 1, + }, + { + # PreviewImageLength in various IFD's of DNG images except SubIFD2 + Condition => '$$self{DIR_NAME} ne "SubIFD2"', + Name => 'PreviewImageLength', + OffsetPair => 0x111, + DataTag => 'PreviewImage', + Writable => 'int32u', + WriteGroup => 'All', # (writes to specific group of associated Composite tag) + Protected => 2, + Permanent => 1, + }, + { + # JpgFromRawLength in SubIFD2 of DNG images + Name => 'JpgFromRawLength', + OffsetPair => 0x111, + DataTag => 'JpgFromRaw', + Writable => 'int32u', + WriteGroup => 'SubIFD2', + Protected => 2, + Permanent => 1, + }, + ], + 0x118 => { + Name => 'MinSampleValue', + Writable => 'int16u', + WriteGroup => 'IFD0', + }, + 0x119 => { + Name => 'MaxSampleValue', + Writable => 'int16u', + WriteGroup => 'IFD0', + }, + 0x11a => { + Name => 'XResolution', + Writable => 'rational64u', + WriteGroup => 'IFD0', + Mandatory => 1, + Priority => 0, # so PRIORITY_DIR takes precedence + }, + 0x11b => { + Name => 'YResolution', + Writable => 'rational64u', + WriteGroup => 'IFD0', + Mandatory => 1, + Priority => 0, + }, + 0x11c => { + Name => 'PlanarConfiguration', + Protected => 1, + Writable => 'int16u', + WriteGroup => 'IFD0', + PrintConv => { + 1 => 'Chunky', + 2 => 'Planar', + }, + Priority => 0, + }, + 0x11d => { + Name => 'PageName', + Writable => 'string', + WriteGroup => 'IFD0', + }, + 0x11e => { + Name => 'XPosition', + Writable => 'rational64u', + WriteGroup => 'IFD0', + }, + 0x11f => { + Name => 'YPosition', + Writable => 'rational64u', + WriteGroup => 'IFD0', + }, + # FreeOffsets/FreeByteCounts are used by Ricoh for RMETA information + # in TIFF images (not yet supported) + 0x120 => { + Name => 'FreeOffsets', + IsOffset => 1, + OffsetPair => 0x121, + ValueConv => 'length($val) > 32 ? \$val : $val', + }, + 0x121 => { + Name => 'FreeByteCounts', + OffsetPair => 0x120, + ValueConv => 'length($val) > 32 ? \$val : $val', + }, + 0x122 => { + Name => 'GrayResponseUnit', + Writable => 'int16u', + WriteGroup => 'IFD0', + PrintConv => { #3 + 1 => 0.1, + 2 => 0.001, + 3 => 0.0001, + 4 => 0.00001, + 5 => 0.000001, + }, + }, + 0x123 => { + Name => 'GrayResponseCurve', + Binary => 1, + }, + 0x124 => { + Name => 'T4Options', + PrintConv => { BITMASK => { + 0 => '2-Dimensional encoding', + 1 => 'Uncompressed', + 2 => 'Fill bits added', + } }, #3 + }, + 0x125 => { + Name => 'T6Options', + PrintConv => { BITMASK => { + 1 => 'Uncompressed', + } }, #3 + }, + 0x128 => { + Name => 'ResolutionUnit', + Notes => 'the value 1 is not standard EXIF', + Writable => 'int16u', + WriteGroup => 'IFD0', + Mandatory => 1, + PrintConv => { + 1 => 'None', + 2 => 'inches', + 3 => 'cm', + }, + Priority => 0, + }, + 0x129 => { + Name => 'PageNumber', + Writable => 'int16u', + WriteGroup => 'IFD0', + Count => 2, + }, + 0x12c => 'ColorResponseUnit', #9 + 0x12d => { + Name => 'TransferFunction', + Protected => 1, + Writable => 'int16u', + WriteGroup => 'IFD0', + Count => 768, + Binary => 1, + }, + 0x131 => { + Name => 'Software', + Writable => 'string', + WriteGroup => 'IFD0', + RawConv => '$val =~ s/\s+$//; $val', # trim trailing blanks + }, + 0x132 => { + Name => 'ModifyDate', + Groups => { 2 => 'Time' }, + Notes => 'called DateTime by the EXIF spec.', + Writable => 'string', + Shift => 'Time', + WriteGroup => 'IFD0', + Validate => 'ValidateExifDate($val)', + PrintConv => '$self->ConvertDateTime($val)', + PrintConvInv => '$self->InverseDateTime($val,0)', + }, + 0x13b => { + Name => 'Artist', + Groups => { 2 => 'Author' }, + Notes => 'becomes a list-type tag when the MWG module is loaded', + Writable => 'string', + WriteGroup => 'IFD0', + RawConv => '$val =~ s/\s+$//; $val', # trim trailing blanks + }, + 0x13c => { + Name => 'HostComputer', + Writable => 'string', + WriteGroup => 'IFD0', + }, + 0x13d => { + Name => 'Predictor', + Protected => 1, + Writable => 'int16u', + WriteGroup => 'IFD0', + PrintConv => { + 1 => 'None', + 2 => 'Horizontal differencing', + }, + }, + 0x13e => { + Name => 'WhitePoint', + Groups => { 2 => 'Camera' }, + Writable => 'rational64u', + WriteGroup => 'IFD0', + Count => 2, + }, + 0x13f => { + Name => 'PrimaryChromaticities', + Writable => 'rational64u', + WriteGroup => 'IFD0', + Count => 6, + Priority => 0, + }, + 0x140 => { + Name => 'ColorMap', + Format => 'binary', + Binary => 1, + }, + 0x141 => { + Name => 'HalftoneHints', + Writable => 'int16u', + WriteGroup => 'IFD0', + Count => 2, + }, + 0x142 => { + Name => 'TileWidth', + Protected => 1, + Writable => 'int32u', + WriteGroup => 'IFD0', + }, + 0x143 => { + Name => 'TileLength', + Protected => 1, + Writable => 'int32u', + WriteGroup => 'IFD0', + }, + 0x144 => { + Name => 'TileOffsets', + IsOffset => 1, + OffsetPair => 0x145, + ValueConv => 'length($val) > 32 ? \$val : $val', + }, + 0x145 => { + Name => 'TileByteCounts', + OffsetPair => 0x144, + ValueConv => 'length($val) > 32 ? \$val : $val', + }, + 0x146 => 'BadFaxLines', #3 + 0x147 => { #3 + Name => 'CleanFaxData', + PrintConv => { + 0 => 'Clean', + 1 => 'Regenerated', + 2 => 'Unclean', + }, + }, + 0x148 => 'ConsecutiveBadFaxLines', #3 + 0x14a => [ + { + Name => 'SubIFD', + # use this opportunity to identify an ARW image, and if so we + # must decide if this is a SubIFD or the A100 raw data + # (use SubfileType, Compression and FILE_TYPE to identify ARW/SR2, + # then call SetARW to finish the job) + Condition => q{ + $$self{DIR_NAME} ne 'IFD0' or $$self{FILE_TYPE} ne 'TIFF' or + $$self{Make} !~ /^SONY/ or + not $$self{SubfileType} or $$self{SubfileType} != 1 or + not $$self{Compression} or $$self{Compression} != 6 or + not require Image::ExifTool::Sony or + Image::ExifTool::Sony::SetARW($self, $valPt) + }, + Groups => { 1 => 'SubIFD' }, + Flags => 'SubIFD', + SubDirectory => { + Start => '$val', + MaxSubdirs => 10, # (have seen 5 in a DNG 1.4 image) + }, + }, + { #16 + Name => 'A100DataOffset', + Notes => 'the data offset in original Sony DSLR-A100 ARW images', + DataMember => 'A100DataOffset', + RawConv => '$$self{A100DataOffset} = $val', + WriteGroup => 'IFD0', # (only for Validate) + IsOffset => 1, + Protected => 2, + }, + ], + 0x14c => { + Name => 'InkSet', + Writable => 'int16u', + WriteGroup => 'IFD0', + PrintConv => { #3 + 1 => 'CMYK', + 2 => 'Not CMYK', + }, + }, + 0x14d => 'InkNames', #3 + 0x14e => 'NumberofInks', #3 + 0x150 => 'DotRange', + 0x151 => { + Name => 'TargetPrinter', + Writable => 'string', + WriteGroup => 'IFD0', + }, + 0x152 => { + Name => 'ExtraSamples', + PrintConv => { #20 + 0 => 'Unspecified', + 1 => 'Associated Alpha', + 2 => 'Unassociated Alpha', + }, + }, + 0x153 => { + Name => 'SampleFormat', + Notes => 'SamplesPerPixel values', + WriteGroup => 'SubIFD', # (only for Validate) + PrintConvColumns => 2, + PrintConv => [ \%sampleFormat, \%sampleFormat, \%sampleFormat, \%sampleFormat ], + }, + 0x154 => 'SMinSampleValue', + 0x155 => 'SMaxSampleValue', + 0x156 => 'TransferRange', + 0x157 => 'ClipPath', #3 + 0x158 => 'XClipPathUnits', #3 + 0x159 => 'YClipPathUnits', #3 + 0x15a => { #3 + Name => 'Indexed', + PrintConv => { 0 => 'Not indexed', 1 => 'Indexed' }, + }, + 0x15b => { + Name => 'JPEGTables', + Binary => 1, + }, + 0x15f => { #10 + Name => 'OPIProxy', + PrintConv => { + 0 => 'Higher resolution image does not exist', + 1 => 'Higher resolution image exists', + }, + }, + # 0x181 => 'Decode', #20 (typo! - should be 0x1b1, ref 21) + # 0x182 => 'DefaultImageColor', #20 (typo! - should be 0x1b2, ref 21) + 0x190 => { #3 + Name => 'GlobalParametersIFD', + Groups => { 1 => 'GlobParamIFD' }, + Flags => 'SubIFD', + SubDirectory => { + DirName => 'GlobParamIFD', + Start => '$val', + MaxSubdirs => 1, + }, + }, + 0x191 => { #3 + Name => 'ProfileType', + PrintConv => { 0 => 'Unspecified', 1 => 'Group 3 FAX' }, + }, + 0x192 => { #3 + Name => 'FaxProfile', + PrintConv => { + 0 => 'Unknown', + 1 => 'Minimal B&W lossless, S', + 2 => 'Extended B&W lossless, F', + 3 => 'Lossless JBIG B&W, J', + 4 => 'Lossy color and grayscale, C', + 5 => 'Lossless color and grayscale, L', + 6 => 'Mixed raster content, M', + 7 => 'Profile T', #20 + 255 => 'Multi Profiles', #20 + }, + }, + 0x193 => { #3 + Name => 'CodingMethods', + PrintConv => { BITMASK => { + 0 => 'Unspecified compression', + 1 => 'Modified Huffman', + 2 => 'Modified Read', + 3 => 'Modified MR', + 4 => 'JBIG', + 5 => 'Baseline JPEG', + 6 => 'JBIG color', + } }, + }, + 0x194 => 'VersionYear', #3 + 0x195 => 'ModeNumber', #3 + 0x1b1 => 'Decode', #3 + 0x1b2 => 'DefaultImageColor', #3 (changed to ImageBaseColor, ref 21) + 0x1b3 => 'T82Options', #20 + 0x1b5 => { #19 + Name => 'JPEGTables', + Binary => 1, + }, + 0x200 => { + Name => 'JPEGProc', + PrintConv => { + 1 => 'Baseline', + 14 => 'Lossless', + }, + }, + 0x201 => [ + { + Name => 'ThumbnailOffset', + Notes => q{ + ThumbnailOffset in IFD1 of JPEG and some TIFF-based images, IFD0 of MRW + images and AVI and MOV videos, and the SubIFD in IFD1 of SRW images; + PreviewImageStart in MakerNotes and IFD0 of ARW and SR2 images; + JpgFromRawStart in SubIFD of NEF images and IFD2 of PEF images; and + OtherImageStart in everything else + }, + # thumbnail is found in IFD1 of JPEG and TIFF images, and + # IFD0 of EXIF information in FujiFilm AVI (RIFF) and MOV videos + Condition => q{ + # recognize NRW file from a JPEG-compressed thumbnail in IFD0 + if ($$self{TIFF_TYPE} eq 'NEF' and $$self{DIR_NAME} eq 'IFD0' and $$self{Compression} == 6) { + $self->OverrideFileType($$self{TIFF_TYPE} = 'NRW'); + } + $$self{DIR_NAME} eq 'IFD1' or + ($$self{DIR_NAME} eq 'IFD0' and $$self{FILE_TYPE} =~ /^(RIFF|MOV)$/) + }, + IsOffset => 1, + OffsetPair => 0x202, + DataTag => 'ThumbnailImage', + Writable => 'int32u', + WriteGroup => 'IFD1', + # according to the EXIF spec. a JPEG-compressed thumbnail image may not + # be stored in a TIFF file, but these TIFF-based RAW image formats + # use IFD1 for a JPEG-compressed thumbnail: CR2, ARW, SR2 and PEF. + # (SRF also stores a JPEG image in IFD1, but it is actually a preview + # and we don't yet write SRF anyway) + WriteCondition => q{ + $$self{FILE_TYPE} ne "TIFF" or + $$self{TIFF_TYPE} =~ /^(CR2|ARW|SR2|PEF)$/ + }, + Protected => 2, + }, + { + Name => 'ThumbnailOffset', + # thumbnail in IFD0 of MRW images (Minolta A200) + # and IFD0 of NRW images (Nikon Coolpix P6000,P7000,P7100) + Condition => '$$self{DIR_NAME} eq "IFD0" and $$self{TIFF_TYPE} =~ /^(MRW|NRW)$/', + IsOffset => 1, + OffsetPair => 0x202, + # A200 uses the wrong base offset for this pointer!! + WrongBase => '$$self{Model} =~ /^DiMAGE A200/ ? $$self{MRW_WrongBase} : undef', + DataTag => 'ThumbnailImage', + Writable => 'int32u', + WriteGroup => 'IFD0', + Protected => 2, + Permanent => 1, + }, + { + Name => 'ThumbnailOffset', + # in SubIFD of IFD1 in Samsung SRW images + Condition => q{ + $$self{TIFF_TYPE} eq 'SRW' and $$self{DIR_NAME} eq 'SubIFD' and + $$self{PATH}[-2] eq 'IFD1' + }, + IsOffset => 1, + OffsetPair => 0x202, + DataTag => 'ThumbnailImage', + Writable => 'int32u', + WriteGroup => 'SubIFD', + Protected => 2, + Permanent => 1, + }, + { + Name => 'PreviewImageStart', + Condition => '$$self{DIR_NAME} eq "MakerNotes"', + IsOffset => 1, + OffsetPair => 0x202, + DataTag => 'PreviewImage', + Writable => 'int32u', + WriteGroup => 'MakerNotes', + Protected => 2, + Permanent => 1, + }, + { + Name => 'PreviewImageStart', + # PreviewImage in IFD0 of ARW and SR2 files for all models + Condition => '$$self{DIR_NAME} eq "IFD0" and $$self{TIFF_TYPE} =~ /^(ARW|SR2)$/', + IsOffset => 1, + OffsetPair => 0x202, + DataTag => 'PreviewImage', + Writable => 'int32u', + WriteGroup => 'IFD0', + Protected => 2, + Permanent => 1, + }, + { + Name => 'JpgFromRawStart', + Condition => '$$self{DIR_NAME} eq "SubIFD"', + IsOffset => 1, + OffsetPair => 0x202, + DataTag => 'JpgFromRaw', + Writable => 'int32u', + WriteGroup => 'SubIFD', + # JpgFromRaw is in SubIFD of NEF, NRW and SRW files + Protected => 2, + Permanent => 1, + }, + { + Name => 'JpgFromRawStart', + Condition => '$$self{DIR_NAME} eq "IFD2"', + IsOffset => 1, + OffsetPair => 0x202, + DataTag => 'JpgFromRaw', + Writable => 'int32u', + WriteGroup => 'IFD2', + # JpgFromRaw is in IFD2 of PEF files + Protected => 2, + Permanent => 1, + }, + { + Name => 'OtherImageStart', + Condition => '$$self{DIR_NAME} eq "SubIFD1"', + IsOffset => 1, + OffsetPair => 0x202, + DataTag => 'OtherImage', + Writable => 'int32u', + WriteGroup => 'SubIFD1', + Protected => 2, + Permanent => 1, + }, + { + Name => 'OtherImageStart', + Condition => '$$self{DIR_NAME} eq "SubIFD2"', + IsOffset => 1, + OffsetPair => 0x202, + DataTag => 'OtherImage', + Writable => 'int32u', + WriteGroup => 'SubIFD2', + Protected => 2, + Permanent => 1, + }, + { + Name => 'OtherImageStart', + IsOffset => 1, + OffsetPair => 0x202, + }, + ], + 0x202 => [ + { + Name => 'ThumbnailLength', + Notes => q{ + ThumbnailLength in IFD1 of JPEG and some TIFF-based images, IFD0 of MRW + images and AVI and MOV videos, and the SubIFD in IFD1 of SRW images; + PreviewImageLength in MakerNotes and IFD0 of ARW and SR2 images; + JpgFromRawLength in SubIFD of NEF images, and IFD2 of PEF images; and + OtherImageLength in everything else + }, + Condition => q{ + $$self{DIR_NAME} eq 'IFD1' or + ($$self{DIR_NAME} eq 'IFD0' and $$self{FILE_TYPE} =~ /^(RIFF|MOV)$/) + }, + OffsetPair => 0x201, + DataTag => 'ThumbnailImage', + Writable => 'int32u', + WriteGroup => 'IFD1', + WriteCondition => q{ + $$self{FILE_TYPE} ne "TIFF" or + $$self{TIFF_TYPE} =~ /^(CR2|ARW|SR2|PEF)$/ + }, + Protected => 2, + }, + { + Name => 'ThumbnailLength', + # thumbnail in IFD0 of MRW images (Minolta A200) + # and IFD0 of NRW images (Nikon Coolpix P6000,P7000,P7100) + Condition => '$$self{DIR_NAME} eq "IFD0" and $$self{TIFF_TYPE} =~ /^(MRW|NRW)$/', + OffsetPair => 0x201, + DataTag => 'ThumbnailImage', + Writable => 'int32u', + WriteGroup => 'IFD0', + Protected => 2, + Permanent => 1, + }, + { + Name => 'ThumbnailLength', + # in SubIFD of IFD1 in Samsung SRW images + Condition => q{ + $$self{TIFF_TYPE} eq 'SRW' and $$self{DIR_NAME} eq 'SubIFD' and + $$self{PATH}[-2] eq 'IFD1' + }, + OffsetPair => 0x201, + DataTag => 'ThumbnailImage', + Writable => 'int32u', + WriteGroup => 'SubIFD', + Protected => 2, + Permanent => 1, + }, + { + Name => 'PreviewImageLength', + Condition => '$$self{DIR_NAME} eq "MakerNotes"', + OffsetPair => 0x201, + DataTag => 'PreviewImage', + Writable => 'int32u', + WriteGroup => 'MakerNotes', + Protected => 2, + Permanent => 1, + }, + { + Name => 'PreviewImageLength', + # PreviewImage in IFD0 of ARW and SR2 files for all models + Condition => '$$self{DIR_NAME} eq "IFD0" and $$self{TIFF_TYPE} =~ /^(ARW|SR2)$/', + OffsetPair => 0x201, + DataTag => 'PreviewImage', + Writable => 'int32u', + WriteGroup => 'IFD0', + Protected => 2, + Permanent => 1, + }, + { + Name => 'JpgFromRawLength', + Condition => '$$self{DIR_NAME} eq "SubIFD"', + OffsetPair => 0x201, + DataTag => 'JpgFromRaw', + Writable => 'int32u', + WriteGroup => 'SubIFD', + Protected => 2, + Permanent => 1, + }, + { + Name => 'JpgFromRawLength', + Condition => '$$self{DIR_NAME} eq "IFD2"', + OffsetPair => 0x201, + DataTag => 'JpgFromRaw', + Writable => 'int32u', + WriteGroup => 'IFD2', + Protected => 2, + Permanent => 1, + }, + { + Name => 'OtherImageLength', + Condition => '$$self{DIR_NAME} eq "SubIFD1"', + OffsetPair => 0x201, + DataTag => 'OtherImage', + Writable => 'int32u', + WriteGroup => 'SubIFD1', + Protected => 2, + Permanent => 1, + }, + { + Name => 'OtherImageLength', + Condition => '$$self{DIR_NAME} eq "SubIFD2"', + OffsetPair => 0x201, + DataTag => 'OtherImage', + Writable => 'int32u', + WriteGroup => 'SubIFD2', + Protected => 2, + Permanent => 1, + }, + { + Name => 'OtherImageLength', + OffsetPair => 0x201, + }, + ], + 0x203 => 'JPEGRestartInterval', + 0x205 => 'JPEGLosslessPredictors', + 0x206 => 'JPEGPointTransforms', + 0x207 => { + Name => 'JPEGQTables', + IsOffset => 1, + # this tag is not supported for writing, so define an + # invalid offset pair to cause a "No size tag" error to be + # generated if we try to write a file containing this tag + OffsetPair => -1, + }, + 0x208 => { + Name => 'JPEGDCTables', + IsOffset => 1, + OffsetPair => -1, # (see comment for JPEGQTables) + }, + 0x209 => { + Name => 'JPEGACTables', + IsOffset => 1, + OffsetPair => -1, # (see comment for JPEGQTables) + }, + 0x211 => { + Name => 'YCbCrCoefficients', + Protected => 1, + Writable => 'rational64u', + WriteGroup => 'IFD0', + Count => 3, + Priority => 0, + }, + 0x212 => { + Name => 'YCbCrSubSampling', + Protected => 1, + Writable => 'int16u', + WriteGroup => 'IFD0', + Count => 2, + PrintConvColumns => 2, + PrintConv => \%Image::ExifTool::JPEG::yCbCrSubSampling, + Priority => 0, + }, + 0x213 => { + Name => 'YCbCrPositioning', + Protected => 1, + Writable => 'int16u', + WriteGroup => 'IFD0', + Mandatory => 1, + PrintConv => { + 1 => 'Centered', + 2 => 'Co-sited', + }, + Priority => 0, + }, + 0x214 => { + Name => 'ReferenceBlackWhite', + Writable => 'rational64u', + WriteGroup => 'IFD0', + Count => 6, + Priority => 0, + }, + 0x22f => 'StripRowCounts', + 0x2bc => { + Name => 'ApplicationNotes', # (writable directory!) + Format => 'undef', + Writable => 'int8u', + WriteGroup => 'IFD0', # (only for Validate) + Flags => [ 'Binary', 'Protected' ], + # this could be an XMP block + SubDirectory => { + DirName => 'XMP', + TagTable => 'Image::ExifTool::XMP::Main', + }, + }, + 0x3e7 => 'USPTOMiscellaneous', #20 + 0x1000 => { #5 + Name => 'RelatedImageFileFormat', + Protected => 1, + Writable => 'string', + WriteGroup => 'InteropIFD', + }, + 0x1001 => { #5 + Name => 'RelatedImageWidth', + Protected => 1, + Writable => 'int16u', + WriteGroup => 'InteropIFD', + }, + 0x1002 => { #5 + Name => 'RelatedImageHeight', + Notes => 'called RelatedImageLength by the DCF spec.', + Protected => 1, + Writable => 'int16u', + WriteGroup => 'InteropIFD', + }, + # (0x474x tags written by MicrosoftPhoto) + 0x4746 => { #PH + Name => 'Rating', + Writable => 'int16u', + WriteGroup => 'IFD0', + Avoid => 1, + }, + 0x4747 => { # (written by Digital Image Pro) + Name => 'XP_DIP_XML', + Format => 'undef', + # the following reference indicates this is Unicode: + # http://social.msdn.microsoft.com/Forums/en-US/isvvba/thread/ce6edcbb-8fc2-40c6-ad98-85f5d835ddfb + ValueConv => '$self->Decode($val,"UCS2","II")', + }, + 0x4748 => { + Name => 'StitchInfo', + SubDirectory => { + TagTable => 'Image::ExifTool::Microsoft::Stitch', + ByteOrder => 'LittleEndian', #PH (NC) + }, + }, + 0x4749 => { #PH + Name => 'RatingPercent', + Writable => 'int16u', + WriteGroup => 'IFD0', + Avoid => 1, + }, + 0x7000 => { #JR + Name => 'SonyRawFileType', + # (only valid if Sony:FileFormat >= ARW 2.0, ref IB) + # Writable => 'int16u', (don't allow writes for now) + PrintConv => { + 0 => 'Sony Uncompressed 14-bit RAW', + 1 => 'Sony Uncompressed 12-bit RAW', #IB + 2 => 'Sony Compressed RAW', # (lossy, ref IB) + 3 => 'Sony Lossless Compressed RAW', #IB + }, + }, + # 0x7001 - int16u[1] (in SubIFD of Sony ARW images) - values: 0,1 + 0x7010 => { #IB + Name => 'SonyToneCurve', + # int16u[4] (in SubIFD of Sony ARW images -- don't allow writes for now) + # - only the middle 4 points are stored (lower comes from black level, + # and upper from data maximum) + }, + # 0x7011 - int16u[4] (in SubIFD of Sony ARW images) - values: "0 4912 8212 12287","4000 7200 10050 12075" + # 0x7020 - int32u[1] (in SubIFD of Sony ARW images) - values: 0,3 + 0x7031 => { + Name => 'VignettingCorrection', + Notes => 'found in Sony ARW images', + Protected => 1, + Writable => 'int16s', + WriteGroup => 'SubIFD', + PrintConv => { + 256 => 'Off', + 257 => 'Auto', + 511 => 'No correction params available', + }, + }, + 0x7032 => { + Name => 'VignettingCorrParams', #forum7640 + Notes => 'found in Sony ARW images', + Protected => 1, + Writable => 'int16s', + WriteGroup => 'SubIFD', + Count => 17, + }, + 0x7034 => { + Name => 'ChromaticAberrationCorrection', + Notes => 'found in Sony ARW images', + Protected => 1, + Writable => 'int16s', + WriteGroup => 'SubIFD', + PrintConv => { + 0 => 'Off', + 1 => 'Auto', + 255 => 'No correction params available', + }, + }, + 0x7035 => { + Name => 'ChromaticAberrationCorrParams', #forum6509 + Notes => 'found in Sony ARW images', + Protected => 1, + Writable => 'int16s', + WriteGroup => 'SubIFD', + Count => 33, + }, + 0x7036 => { + Name => 'DistortionCorrection', + Notes => 'found in Sony ARW images', + Protected => 1, + Writable => 'int16s', + WriteGroup => 'SubIFD', + PrintConv => { + 0 => 'Off', + 1 => 'Auto', + 17 => 'Auto fixed by lens', + 255 => 'No correction params available', + }, + }, + 0x7037 => { + Name => 'DistortionCorrParams', #forum6509 + Notes => 'found in Sony ARW images', + Protected => 1, + Writable => 'int16s', + WriteGroup => 'SubIFD', + Count => 17, + }, + 0x800d => 'ImageID', #10 + 0x80a3 => { Name => 'WangTag1', Binary => 1 }, #20 + 0x80a4 => { Name => 'WangAnnotation', Binary => 1 }, + 0x80a5 => { Name => 'WangTag3', Binary => 1 }, #20 + 0x80a6 => { #20 + Name => 'WangTag4', + PrintConv => 'length($val) <= 64 ? $val : \$val', + }, + # tags 0x80b8-0x80bc are registered to Island Graphics + 0x80b9 => 'ImageReferencePoints', #29 + 0x80ba => 'RegionXformTackPoint', #29 + 0x80bb => 'WarpQuadrilateral', #29 + 0x80bc => 'AffineTransformMat', #29 + 0x80e3 => 'Matteing', #9 + 0x80e4 => 'DataType', #9 + 0x80e5 => 'ImageDepth', #9 + 0x80e6 => 'TileDepth', #9 + # tags 0x8214-0x8219 are registered to Pixar + 0x8214 => 'ImageFullWidth', #29 + 0x8215 => 'ImageFullHeight', #29 + 0x8216 => 'TextureFormat', #29 + 0x8217 => 'WrapModes', #29 + 0x8218 => 'FovCot', #29 + 0x8219 => 'MatrixWorldToScreen', #29 + 0x821a => 'MatrixWorldToCamera', #29 + 0x827d => 'Model2', #29 (Eastman Kodak) + 0x828d => { #12 + Name => 'CFARepeatPatternDim', + Protected => 1, + Writable => 'int16u', + WriteGroup => 'SubIFD', + Count => 2, + }, + 0x828e => { + Name => 'CFAPattern2', #12 + Format => 'int8u', # (written incorrectly as 'undef' in Nikon NRW images) + Protected => 1, + Writable => 'int8u', + WriteGroup => 'SubIFD', + Count => -1, + }, + 0x828f => { #12 + Name => 'BatteryLevel', + Groups => { 2 => 'Camera' }, + }, + 0x8290 => { + Name => 'KodakIFD', + Groups => { 1 => 'KodakIFD' }, + Flags => 'SubIFD', + Notes => 'used in various types of Kodak images', + SubDirectory => { + TagTable => 'Image::ExifTool::Kodak::IFD', + DirName => 'KodakIFD', + Start => '$val', + MaxSubdirs => 1, + }, + }, + 0x8298 => { + Name => 'Copyright', + Groups => { 2 => 'Author' }, + Format => 'undef', + Writable => 'string', + WriteGroup => 'IFD0', + RawConvInv => '$val . "\0"', + PrintConvInv => sub { + my ($val, $self) = @_; + # encode if necessary (not automatic because Format is 'undef') + my $enc = $self->Options('CharsetEXIF'); + $val = $self->Encode($val,$enc) if $enc and $val !~ /\0/; + if ($val =~ /(.*?)\s*[\n\r]+\s*(.*)/s) { + return $1 unless length $2; + # photographer copyright set to ' ' if it doesn't exist, according to spec. + return((length($1) ? $1 : ' ') . "\0" . $2); + } + return $val; + }, + Notes => q{ + may contain copyright notices for photographer and editor, separated by a + newline. As per the EXIF specification, the newline is replaced by a null + byte when writing to file, but this may be avoided by disabling the print + conversion + }, + # internally the strings are separated by a null character in this format: + # Photographer only: photographer + NULL + # Both: photographer + NULL + editor + NULL + # Editor only: SPACE + NULL + editor + NULL + # (this is done as a RawConv so conditional replaces will work properly) + RawConv => sub { + my ($val, $self) = @_; + $val =~ s/ *\0/\n/; # translate first NULL to a newline, removing trailing blanks + $val =~ s/ *\0.*//s; # truncate at second NULL and remove trailing blanks + $val =~ s/\n$//; # remove trailing newline if it exists + # decode if necessary (note: this is the only non-'string' EXIF value like this) + my $enc = $self->Options('CharsetEXIF'); + $val = $self->Decode($val,$enc) if $enc; + return $val; + }, + }, + 0x829a => { + Name => 'ExposureTime', + Writable => 'rational64u', + PrintConv => 'Image::ExifTool::Exif::PrintExposureTime($val)', + PrintConvInv => '$val', + }, + 0x829d => { + Name => 'FNumber', + Writable => 'rational64u', + PrintConv => 'Image::ExifTool::Exif::PrintFNumber($val)', + PrintConvInv => '$val', + }, + 0x82a5 => { #3 + Name => 'MDFileTag', + Notes => 'tags 0x82a5-0x82ac are used in Molecular Dynamics GEL files', + }, + 0x82a6 => 'MDScalePixel', #3 + 0x82a7 => 'MDColorTable', #3 + 0x82a8 => 'MDLabName', #3 + 0x82a9 => 'MDSampleInfo', #3 + 0x82aa => 'MDPrepDate', #3 + 0x82ab => 'MDPrepTime', #3 + 0x82ac => 'MDFileUnits', #3 + 0x830e => { #30 + Name => 'PixelScale', + Writable => 'double', + WriteGroup => 'IFD0', + Count => 3, + }, + 0x8335 => 'AdventScale', #20 + 0x8336 => 'AdventRevision', #20 + 0x835c => 'UIC1Tag', #23 + 0x835d => 'UIC2Tag', #23 + 0x835e => 'UIC3Tag', #23 + 0x835f => 'UIC4Tag', #23 + 0x83bb => { #12 + Name => 'IPTC-NAA', # (writable directory! -- but see note below) + # this should actually be written as 'undef' (see + # http://www.awaresystems.be/imaging/tiff/tifftags/iptc.html), + # but Photoshop writes it as int32u and Nikon Capture won't read + # anything else, so we do the same thing here... Doh! + Format => 'undef', # convert binary values as undef + Writable => 'int32u', # but write int32u format code in IFD + WriteGroup => 'IFD0', + Flags => [ 'Binary', 'Protected' ], + SubDirectory => { + DirName => 'IPTC', + TagTable => 'Image::ExifTool::IPTC::Main', + }, + # Note: This directory may be written as a block via the IPTC-NAA tag, + # but this technique is not recommended. Instead, it is better to + # write the Extra IPTC tag and let ExifTool decide where it should go. + }, + 0x847e => 'IntergraphPacketData', #3 + 0x847f => 'IntergraphFlagRegisters', #3 + 0x8480 => { #30 (obsolete) + Name => 'IntergraphMatrix', + Writable => 'double', + WriteGroup => 'IFD0', + Count => -1, + }, + 0x8481 => 'INGRReserved', #20 + 0x8482 => { #30 + Name => 'ModelTiePoint', + Groups => { 2 => 'Location' }, + Writable => 'double', + WriteGroup => 'IFD0', + Count => -1, + }, + 0x84e0 => 'Site', #9 + 0x84e1 => 'ColorSequence', #9 + 0x84e2 => 'IT8Header', #9 + 0x84e3 => { #9 + Name => 'RasterPadding', + PrintConv => { #20 + 0 => 'Byte', + 1 => 'Word', + 2 => 'Long Word', + 9 => 'Sector', + 10 => 'Long Sector', + }, + }, + 0x84e4 => 'BitsPerRunLength', #9 + 0x84e5 => 'BitsPerExtendedRunLength', #9 + 0x84e6 => 'ColorTable', #9 + 0x84e7 => { #9 + Name => 'ImageColorIndicator', + PrintConv => { #20 + 0 => 'Unspecified Image Color', + 1 => 'Specified Image Color', + }, + }, + 0x84e8 => { #9 + Name => 'BackgroundColorIndicator', + PrintConv => { #20 + 0 => 'Unspecified Background Color', + 1 => 'Specified Background Color', + }, + }, + 0x84e9 => 'ImageColorValue', #9 + 0x84ea => 'BackgroundColorValue', #9 + 0x84eb => 'PixelIntensityRange', #9 + 0x84ec => 'TransparencyIndicator', #9 + 0x84ed => 'ColorCharacterization', #9 + 0x84ee => { #9 + Name => 'HCUsage', + PrintConv => { #20 + 0 => 'CT', + 1 => 'Line Art', + 2 => 'Trap', + }, + }, + 0x84ef => 'TrapIndicator', #17 + 0x84f0 => 'CMYKEquivalent', #17 + 0x8546 => { #11 + Name => 'SEMInfo', + Notes => 'found in some scanning electron microscope images', + Writable => 'string', + WriteGroup => 'IFD0', + }, + 0x8568 => { + Name => 'AFCP_IPTC', + SubDirectory => { + # must change directory name so we don't create this directory + DirName => 'AFCP_IPTC', + TagTable => 'Image::ExifTool::IPTC::Main', + }, + }, + 0x85b8 => 'PixelMagicJBIGOptions', #20 + 0x85d7 => 'JPLCartoIFD', #exifprobe (NC) + 0x85d8 => { #30 + Name => 'ModelTransform', + Groups => { 2 => 'Location' }, + Writable => 'double', + WriteGroup => 'IFD0', + Count => 16, + }, + 0x8602 => { #16 + Name => 'WB_GRGBLevels', + Notes => 'found in IFD0 of Leaf MOS images', + }, + # 0x8603 - Leaf CatchLight color matrix (ref 16) + 0x8606 => { + Name => 'LeafData', + Format => 'undef', # avoid converting huge block to string of int8u's! + SubDirectory => { + DirName => 'LeafIFD', + TagTable => 'Image::ExifTool::Leaf::Main', + }, + }, + 0x8649 => { #19 + Name => 'PhotoshopSettings', + Format => 'binary', + WriteGroup => 'IFD0', # (only for Validate) + SubDirectory => { + DirName => 'Photoshop', + TagTable => 'Image::ExifTool::Photoshop::Main', + }, + }, + 0x8769 => { + Name => 'ExifOffset', + Groups => { 1 => 'ExifIFD' }, + WriteGroup => 'IFD0', # (only for Validate) + SubIFD => 2, + SubDirectory => { + DirName => 'ExifIFD', + Start => '$val', + }, + }, + 0x8773 => { + Name => 'ICC_Profile', + WriteGroup => 'IFD0', # (only for Validate) + SubDirectory => { + TagTable => 'Image::ExifTool::ICC_Profile::Main', + }, + }, + 0x877f => { #20 + Name => 'TIFF_FXExtensions', + PrintConv => { BITMASK => { + 0 => 'Resolution/Image Width', + 1 => 'N Layer Profile M', + 2 => 'Shared Data', + 3 => 'B&W JBIG2', + 4 => 'JBIG2 Profile M', + }}, + }, + 0x8780 => { #20 + Name => 'MultiProfiles', + PrintConv => { BITMASK => { + 0 => 'Profile S', + 1 => 'Profile F', + 2 => 'Profile J', + 3 => 'Profile C', + 4 => 'Profile L', + 5 => 'Profile M', + 6 => 'Profile T', + 7 => 'Resolution/Image Width', + 8 => 'N Layer Profile M', + 9 => 'Shared Data', + 10 => 'JBIG2 Profile M', + }}, + }, + 0x8781 => { #22 + Name => 'SharedData', + IsOffset => 1, + # this tag is not supported for writing, so define an + # invalid offset pair to cause a "No size tag" error to be + # generated if we try to write a file containing this tag + OffsetPair => -1, + }, + 0x8782 => 'T88Options', #20 + 0x87ac => 'ImageLayer', + 0x87af => { #30 + Name => 'GeoTiffDirectory', + Format => 'undef', + Binary => 1, + Notes => q{ + these "GeoTiff" tags may read and written as a block, but they aren't + extracted unless specifically requested. Byte order changes are handled + automatically when copying between TIFF images with different byte order + }, + Writable => 'undef', + WriteGroup => 'IFD0', + RawConv => '$val . GetByteOrder()', # save byte order + # swap byte order if necessary + RawConvInv => q{ + return $val if length $val < 2; + my $order = substr($val, -2); + return $val unless $order eq 'II' or $order eq 'MM'; + $val = substr($val, 0, -2); + return $val if $order eq GetByteOrder(); + return pack('v*',unpack('n*',$val)); + }, + }, + 0x87b0 => { #30 + Name => 'GeoTiffDoubleParams', + Format => 'undef', + Binary => 1, + Writable => 'undef', + WriteGroup => 'IFD0', + RawConv => '$val . GetByteOrder()', # save byte order + # swap byte order if necessary + RawConvInv => q{ + return $val if length $val < 2; + my $order = substr($val, -2); + return $val unless $order eq 'II' or $order eq 'MM'; + $val = substr($val, 0, -2); + return $val if $order eq GetByteOrder(); + $val =~ s/(.{4})(.{4})/$2$1/sg; # swap words + return pack('V*',unpack('N*',$val)); + }, + }, + 0x87b1 => { #30 + Name => 'GeoTiffAsciiParams', + Writable => 'string', + WriteGroup => 'IFD0', + Binary => 1, + }, + 0x87be => 'JBIGOptions', #29 + 0x8822 => { + Name => 'ExposureProgram', + Groups => { 2 => 'Camera' }, + Notes => 'the value of 9 is not standard EXIF, but is used by the Canon EOS 7D', + Writable => 'int16u', + PrintConv => { + 0 => 'Not Defined', + 1 => 'Manual', + 2 => 'Program AE', + 3 => 'Aperture-priority AE', + 4 => 'Shutter speed priority AE', + 5 => 'Creative (Slow speed)', + 6 => 'Action (High speed)', + 7 => 'Portrait', + 8 => 'Landscape', + 9 => 'Bulb', #25 + }, + }, + 0x8824 => { + Name => 'SpectralSensitivity', + Groups => { 2 => 'Camera' }, + Writable => 'string', + }, + 0x8825 => { + Name => 'GPSInfo', + Groups => { 1 => 'GPS' }, + WriteGroup => 'IFD0', # (only for Validate) + Flags => 'SubIFD', + SubDirectory => { + DirName => 'GPS', + TagTable => 'Image::ExifTool::GPS::Main', + Start => '$val', + MaxSubdirs => 1, + }, + }, + 0x8827 => { + Name => 'ISO', + Notes => q{ + called ISOSpeedRatings by EXIF 2.2, then PhotographicSensitivity by the EXIF + 2.3 spec. + }, + Writable => 'int16u', + Count => -1, + PrintConv => '$val=~s/\s+/, /g; $val', + PrintConvInv => '$val=~tr/,//d; $val', + }, + 0x8828 => { + Name => 'Opto-ElectricConvFactor', + Notes => 'called OECF by the EXIF spec.', + Binary => 1, + }, + 0x8829 => 'Interlace', #12 + 0x882a => { #12 + Name => 'TimeZoneOffset', + Writable => 'int16s', + Count => -1, # can be 1 or 2 + Notes => q{ + 1 or 2 values: 1. The time zone offset of DateTimeOriginal from GMT in + hours, 2. If present, the time zone offset of ModifyDate + }, + }, + 0x882b => { #12 + Name => 'SelfTimerMode', + Writable => 'int16u', + }, + 0x8830 => { #24 + Name => 'SensitivityType', + Notes => 'applies to EXIF:ISO tag', + Writable => 'int16u', + PrintConv => { + 0 => 'Unknown', + 1 => 'Standard Output Sensitivity', + 2 => 'Recommended Exposure Index', + 3 => 'ISO Speed', + 4 => 'Standard Output Sensitivity and Recommended Exposure Index', + 5 => 'Standard Output Sensitivity and ISO Speed', + 6 => 'Recommended Exposure Index and ISO Speed', + 7 => 'Standard Output Sensitivity, Recommended Exposure Index and ISO Speed', + }, + }, + 0x8831 => { #24 + Name => 'StandardOutputSensitivity', + Writable => 'int32u', + }, + 0x8832 => { #24 + Name => 'RecommendedExposureIndex', + Writable => 'int32u', + }, + 0x8833 => { #24 + Name => 'ISOSpeed', + Writable => 'int32u', + }, + 0x8834 => { #24 + Name => 'ISOSpeedLatitudeyyy', + Description => 'ISO Speed Latitude yyy', + Writable => 'int32u', + }, + 0x8835 => { #24 + Name => 'ISOSpeedLatitudezzz', + Description => 'ISO Speed Latitude zzz', + Writable => 'int32u', + }, + 0x885c => 'FaxRecvParams', #9 + 0x885d => 'FaxSubAddress', #9 + 0x885e => 'FaxRecvTime', #9 + 0x8871 => 'FedexEDR', #exifprobe (NC) + 0x888a => { #PH + Name => 'LeafSubIFD', + Format => 'int32u', # Leaf incorrectly uses 'undef' format! + Groups => { 1 => 'LeafSubIFD' }, + Flags => 'SubIFD', + SubDirectory => { + TagTable => 'Image::ExifTool::Leaf::SubIFD', + Start => '$val', + }, + }, + # 0x89ab - seen "11 100 130 16 0 0 0 0" in IFD0 of TIFF image from IR scanner (forum8470) + 0x9000 => { + Name => 'ExifVersion', + Writable => 'undef', + Mandatory => 1, + RawConv => '$val=~s/\0+$//; $val', # (some idiots add null terminators) + PrintConvInv => '$val=~tr/.//d; $val=~/^\d{4}$/ ? $val : undef', + }, + 0x9003 => { + Name => 'DateTimeOriginal', + Description => 'Date/Time Original', + Groups => { 2 => 'Time' }, + Notes => 'date/time when original image was taken', + Writable => 'string', + Shift => 'Time', + Validate => 'ValidateExifDate($val)', + PrintConv => '$self->ConvertDateTime($val)', + PrintConvInv => '$self->InverseDateTime($val,0)', + }, + 0x9004 => { + Name => 'CreateDate', + Groups => { 2 => 'Time' }, + Notes => 'called DateTimeDigitized by the EXIF spec.', + Writable => 'string', + Shift => 'Time', + Validate => 'ValidateExifDate($val)', + PrintConv => '$self->ConvertDateTime($val)', + PrintConvInv => '$self->InverseDateTime($val,0)', + }, + 0x9009 => { # undef[44] (or undef[11]) written by Google Plus uploader - PH + Name => 'GooglePlusUploadCode', + Format => 'int8u', + Writable => 'undef', + Count => -1, + }, + 0x9010 => { + Name => 'OffsetTime', + Groups => { 2 => 'Time' }, + Notes => 'time zone for ModifyDate', + Writable => 'string', + PrintConvInv => q{ + return "+00:00" if $val =~ /\d{2}Z$/; + return sprintf("%s%.2d:%.2d",$1,$2,$3) if $val =~ /([-+])(\d{1,2}):(\d{2})/; + return undef; + }, + }, + 0x9011 => { + Name => 'OffsetTimeOriginal', + Groups => { 2 => 'Time' }, + Notes => 'time zone for DateTimeOriginal', + Writable => 'string', + PrintConvInv => q{ + return "+00:00" if $val =~ /\d{2}Z$/; + return sprintf("%s%.2d:%.2d",$1,$2,$3) if $val =~ /([-+])(\d{1,2}):(\d{2})/; + return undef; + }, + }, + 0x9012 => { + Name => 'OffsetTimeDigitized', + Groups => { 2 => 'Time' }, + Notes => 'time zone for CreateDate', + Writable => 'string', + PrintConvInv => q{ + return "+00:00" if $val =~ /\d{2}Z$/; + return sprintf("%s%.2d:%.2d",$1,$2,$3) if $val =~ /([-+])(\d{1,2}):(\d{2})/; + return undef; + }, + }, + 0x9101 => { + Name => 'ComponentsConfiguration', + Format => 'int8u', + Protected => 1, + Writable => 'undef', + Count => 4, + Mandatory => 1, + ValueConvInv => '$val=~tr/,//d; $val', # (so we can copy from XMP with -n) + PrintConvColumns => 2, + PrintConv => { + 0 => '-', + 1 => 'Y', + 2 => 'Cb', + 3 => 'Cr', + 4 => 'R', + 5 => 'G', + 6 => 'B', + OTHER => sub { + my ($val, $inv, $conv) = @_; + my @a = split /,?\s+/, $val; + if ($inv) { + my %invConv; + $invConv{lc $$conv{$_}} = $_ foreach keys %$conv; + # strings like "YCbCr" and "RGB" still work for writing + @a = $a[0] =~ /(Y|Cb|Cr|R|G|B)/g if @a == 1; + foreach (@a) { + $_ = $invConv{lc $_}; + return undef unless defined $_; + } + push @a, 0 while @a < 4; + } else { + foreach (@a) { + $_ = $$conv{$_} || "Err ($_)"; + } + } + return join ', ', @a; + }, + }, + }, + 0x9102 => { + Name => 'CompressedBitsPerPixel', + Protected => 1, + Writable => 'rational64u', + }, + # 0x9103 - int16u: 1 (found in Pentax XG-1 samples) + 0x9201 => { + Name => 'ShutterSpeedValue', + Notes => 'displayed in seconds, but stored as an APEX value', + Format => 'rational64s', # Leica M8 patch (incorrectly written as rational64u) + Writable => 'rational64s', + ValueConv => 'abs($val)<100 ? 2**(-$val) : 0', + ValueConvInv => '$val>0 ? -log($val)/log(2) : -100', + PrintConv => 'Image::ExifTool::Exif::PrintExposureTime($val)', + PrintConvInv => 'Image::ExifTool::Exif::ConvertFraction($val)', + }, + 0x9202 => { + Name => 'ApertureValue', + Notes => 'displayed as an F number, but stored as an APEX value', + Writable => 'rational64u', + ValueConv => '2 ** ($val / 2)', + ValueConvInv => '$val>0 ? 2*log($val)/log(2) : 0', + PrintConv => 'sprintf("%.1f",$val)', + PrintConvInv => '$val', + }, + # Wikipedia: BrightnessValue = Bv = Av + Tv - Sv + # ExifTool: LightValue = LV = Av + Tv - Sv + 5 (5 is the Sv for ISO 100 in Exif usage) + 0x9203 => { + Name => 'BrightnessValue', + Writable => 'rational64s', + }, + 0x9204 => { + Name => 'ExposureCompensation', + Format => 'rational64s', # Leica M8 patch (incorrectly written as rational64u) + Notes => 'called ExposureBiasValue by the EXIF spec.', + Writable => 'rational64s', + PrintConv => 'Image::ExifTool::Exif::PrintFraction($val)', + PrintConvInv => '$val', + }, + 0x9205 => { + Name => 'MaxApertureValue', + Notes => 'displayed as an F number, but stored as an APEX value', + Groups => { 2 => 'Camera' }, + Writable => 'rational64u', + ValueConv => '2 ** ($val / 2)', + ValueConvInv => '$val>0 ? 2*log($val)/log(2) : 0', + PrintConv => 'sprintf("%.1f",$val)', + PrintConvInv => '$val', + }, + 0x9206 => { + Name => 'SubjectDistance', + Groups => { 2 => 'Camera' }, + Writable => 'rational64u', + PrintConv => '$val =~ /^(inf|undef)$/ ? $val : "${val} m"', + PrintConvInv => '$val=~s/\s*m$//;$val', + }, + 0x9207 => { + Name => 'MeteringMode', + Groups => { 2 => 'Camera' }, + Writable => 'int16u', + PrintConv => { + 0 => 'Unknown', + 1 => 'Average', + 2 => 'Center-weighted average', + 3 => 'Spot', + 4 => 'Multi-spot', + 5 => 'Multi-segment', + 6 => 'Partial', + 255 => 'Other', + }, + }, + 0x9208 => { + Name => 'LightSource', + Groups => { 2 => 'Camera' }, + Writable => 'int16u', + SeparateTable => 'LightSource', + PrintConv => \%lightSource, + }, + 0x9209 => { + Name => 'Flash', + Groups => { 2 => 'Camera' }, + Writable => 'int16u', + Flags => 'PrintHex', + SeparateTable => 'Flash', + PrintConv => \%flash, + }, + 0x920a => { + Name => 'FocalLength', + Groups => { 2 => 'Camera' }, + Writable => 'rational64u', + PrintConv => 'sprintf("%.1f mm",$val)', + PrintConvInv => '$val=~s/\s*mm$//;$val', + }, + # Note: tags 0x920b-0x9217 are duplicates of 0xa20b-0xa217 + # (The EXIF standard uses 0xa2xx, but you'll find both in images) + 0x920b => { #12 + Name => 'FlashEnergy', + Groups => { 2 => 'Camera' }, + }, + 0x920c => 'SpatialFrequencyResponse', #12 (not in Fuji images - PH) + 0x920d => 'Noise', #12 + 0x920e => 'FocalPlaneXResolution', #12 + 0x920f => 'FocalPlaneYResolution', #12 + 0x9210 => { #12 + Name => 'FocalPlaneResolutionUnit', + Groups => { 2 => 'Camera' }, + PrintConv => { + 1 => 'None', + 2 => 'inches', + 3 => 'cm', + 4 => 'mm', + 5 => 'um', + }, + }, + 0x9211 => { #12 + Name => 'ImageNumber', + Writable => 'int32u', + }, + 0x9212 => { #12 + Name => 'SecurityClassification', + Writable => 'string', + PrintConv => { + T => 'Top Secret', + S => 'Secret', + C => 'Confidential', + R => 'Restricted', + U => 'Unclassified', + }, + }, + 0x9213 => { #12 + Name => 'ImageHistory', + Writable => 'string', + }, + 0x9214 => { + Name => 'SubjectArea', + Groups => { 2 => 'Camera' }, + Writable => 'int16u', + Count => -1, # 2, 3 or 4 values + }, + 0x9215 => 'ExposureIndex', #12 + 0x9216 => 'TIFF-EPStandardID', #12 + 0x9217 => { #12 + Name => 'SensingMethod', + Groups => { 2 => 'Camera' }, + PrintConv => { + # (values 1 and 6 are not used by corresponding EXIF tag 0xa217) + 1 => 'Monochrome area', + 2 => 'One-chip color area', + 3 => 'Two-chip color area', + 4 => 'Three-chip color area', + 5 => 'Color sequential area', + 6 => 'Monochrome linear', + 7 => 'Trilinear', + 8 => 'Color sequential linear', + }, + }, + 0x923a => 'CIP3DataFile', #20 + 0x923b => 'CIP3Sheet', #20 + 0x923c => 'CIP3Side', #20 + 0x923f => 'StoNits', #9 + # handle maker notes as a conditional list + 0x927c => \@Image::ExifTool::MakerNotes::Main, + 0x9286 => { + Name => 'UserComment', + # I have seen other applications write it incorrectly as 'string' or 'int8u' + Format => 'undef', + Writable => 'undef', + RawConv => 'Image::ExifTool::Exif::ConvertExifText($self,$val,1,$tag)', + # (starts with "ASCII\0\0\0", "UNICODE\0", "JIS\0\0\0\0\0" or "\0\0\0\0\0\0\0\0") + RawConvInv => 'Image::ExifTool::Exif::EncodeExifText($self,$val)', + # SHOULD ADD SPECIAL LOGIC TO ALLOW CONDITIONAL OVERWRITE OF + # "UNKNOWN" VALUES FILLED WITH SPACES + }, + 0x9290 => { + Name => 'SubSecTime', + Groups => { 2 => 'Time' }, + Notes => 'fractional seconds for ModifyDate', + Writable => 'string', + ValueConv => '$val=~s/ +$//; $val', # trim trailing blanks + # extract fractional seconds from a full date/time value + ValueConvInv => '$val=~/^(\d+)\s*$/ ? $1 : ($val=~/\.(\d+)/ ? $1 : undef)', + }, + 0x9291 => { + Name => 'SubSecTimeOriginal', + Groups => { 2 => 'Time' }, + Notes => 'fractional seconds for DateTimeOriginal', + Writable => 'string', + ValueConv => '$val=~s/ +$//; $val', # trim trailing blanks + ValueConvInv => '$val=~/^(\d+)\s*$/ ? $1 : ($val=~/\.(\d+)/ ? $1 : undef)', + }, + 0x9292 => { + Name => 'SubSecTimeDigitized', + Groups => { 2 => 'Time' }, + Notes => 'fractional seconds for CreateDate', + Writable => 'string', + ValueConv => '$val=~s/ +$//; $val', # trim trailing blanks + ValueConvInv => '$val=~/^(\d+)\s*$/ ? $1 : ($val=~/\.(\d+)/ ? $1 : undef)', + }, + # The following 3 tags are found in MSOffice TIFF images + # References: + # http://social.msdn.microsoft.com/Forums/en-US/os_standocs/thread/03086d55-294a-49d5-967a-5303d34c40f8/ + # http://blogs.msdn.com/openspecification/archive/2009/12/08/details-of-three-tiff-tag-extensions-that-microsoft-office-document-imaging-modi-software-may-write-into-the-tiff-files-it-generates.aspx + # http://www.microsoft.com/downloads/details.aspx?FamilyID=0dbc435d-3544-4f4b-9092-2f2643d64a39&displaylang=en#filelist + 0x932f => 'MSDocumentText', + 0x9330 => { + Name => 'MSPropertySetStorage', + Binary => 1, + }, + 0x9331 => { + Name => 'MSDocumentTextPosition', + Binary => 1, # (just in case -- don't know what format this is) + }, + 0x935c => { #3/19 + Name => 'ImageSourceData', # (writable directory!) + Writable => 'undef', + WriteGroup => 'IFD0', + SubDirectory => { TagTable => 'Image::ExifTool::Photoshop::DocumentData' }, + Binary => 1, + Protected => 1, # (because this can be hundreds of megabytes) + ReadFromRAF => 1, # don't load into memory when reading + }, + 0x9400 => { + Name => 'AmbientTemperature', + Notes => 'ambient temperature in degrees C, called Temperature by the EXIF spec.', + Writable => 'rational64s', + PrintConv => '"$val C"', + PrintConvInv => '$val=~s/ ?C//; $val', + }, + 0x9401 => { + Name => 'Humidity', + Notes => 'ambient relative humidity in percent', + Writable => 'rational64u', + }, + 0x9402 => { + Name => 'Pressure', + Notes => 'air pressure in hPa or mbar', + Writable => 'rational64u', + }, + 0x9403 => { + Name => 'WaterDepth', + Notes => 'depth under water in metres, negative for above water', + Writable => 'rational64s', + }, + 0x9404 => { + Name => 'Acceleration', + Notes => 'directionless camera acceleration in units of mGal, or 10-5 m/s2', + Writable => 'rational64u', + }, + 0x9405 => { + Name => 'CameraElevationAngle', + Writable => 'rational64s', + }, + 0x9c9b => { + Name => 'XPTitle', + Format => 'undef', + Writable => 'int8u', + WriteGroup => 'IFD0', + Notes => q{ + tags 0x9c9b-0x9c9f are used by Windows Explorer; special characters + in these values are converted to UTF-8 by default, or Windows Latin1 + with the -L option. XPTitle is ignored by Windows Explorer if + ImageDescription exists + }, + ValueConv => '$self->Decode($val,"UCS2","II")', + ValueConvInv => '$self->Encode($val,"UCS2","II") . "\0\0"', + }, + 0x9c9c => { + Name => 'XPComment', + Format => 'undef', + Writable => 'int8u', + WriteGroup => 'IFD0', + ValueConv => '$self->Decode($val,"UCS2","II")', + ValueConvInv => '$self->Encode($val,"UCS2","II") . "\0\0"', + }, + 0x9c9d => { + Name => 'XPAuthor', + Groups => { 2 => 'Author' }, + Format => 'undef', + Writable => 'int8u', + WriteGroup => 'IFD0', + Notes => 'ignored by Windows Explorer if Artist exists', + ValueConv => '$self->Decode($val,"UCS2","II")', + ValueConvInv => '$self->Encode($val,"UCS2","II") . "\0\0"', + }, + 0x9c9e => { + Name => 'XPKeywords', + Format => 'undef', + Writable => 'int8u', + WriteGroup => 'IFD0', + ValueConv => '$self->Decode($val,"UCS2","II")', + ValueConvInv => '$self->Encode($val,"UCS2","II") . "\0\0"', + }, + 0x9c9f => { + Name => 'XPSubject', + Format => 'undef', + Writable => 'int8u', + WriteGroup => 'IFD0', + ValueConv => '$self->Decode($val,"UCS2","II")', + ValueConvInv => '$self->Encode($val,"UCS2","II") . "\0\0"', + }, + 0xa000 => { + Name => 'FlashpixVersion', + Writable => 'undef', + Mandatory => 1, + RawConv => '$val=~s/\0+$//; $val', # (some idiots add null terminators) + PrintConvInv => '$val=~tr/.//d; $val=~/^\d{4}$/ ? $val : undef', + }, + 0xa001 => { + Name => 'ColorSpace', + Notes => q{ + the value of 0x2 is not standard EXIF. Instead, an Adobe RGB image is + indicated by "Uncalibrated" with an InteropIndex of "R03". The values + 0xfffd and 0xfffe are also non-standard, and are used by some Sony cameras + }, + Writable => 'int16u', + Mandatory => 1, + PrintHex => 1, + PrintConv => { + 1 => 'sRGB', + 2 => 'Adobe RGB', + 0xffff => 'Uncalibrated', + # Sony uses these definitions: (ref JD) + # 0xffff => 'Adobe RGB', (conflicts with Uncalibrated) + 0xfffe => 'ICC Profile', + 0xfffd => 'Wide Gamut RGB', + }, + }, + 0xa002 => { + Name => 'ExifImageWidth', + Notes => 'called PixelXDimension by the EXIF spec.', + Writable => 'int16u', + Mandatory => 1, + }, + 0xa003 => { + Name => 'ExifImageHeight', + Notes => 'called PixelYDimension by the EXIF spec.', + Writable => 'int16u', + Mandatory => 1, + }, + 0xa004 => { + Name => 'RelatedSoundFile', + Writable => 'string', + }, + 0xa005 => { + Name => 'InteropOffset', + Groups => { 1 => 'InteropIFD' }, + Flags => 'SubIFD', + Description => 'Interoperability Offset', + SubDirectory => { + DirName => 'InteropIFD', + Start => '$val', + MaxSubdirs => 1, + }, + }, + # the following 4 tags found in SubIFD1 of some Samsung SRW images + 0xa010 => { + Name => 'SamsungRawPointersOffset', + IsOffset => 1, + OffsetPair => 0xa011, # point to associated byte count + }, + 0xa011 => { + Name => 'SamsungRawPointersLength', + OffsetPair => 0xa010, # point to associated offset + }, + 0xa101 => { + Name => 'SamsungRawByteOrder', + Format => 'undef', + # this is written incorrectly as string[1], but is "\0\0MM" or "II\0\0" + FixedSize => 4, + Count => 1, + }, + 0xa102 => { + Name => 'SamsungRawUnknown', + Unknown => 1, + }, + 0xa20b => { + Name => 'FlashEnergy', + Groups => { 2 => 'Camera' }, + Writable => 'rational64u', + }, + 0xa20c => { + Name => 'SpatialFrequencyResponse', + PrintConv => 'Image::ExifTool::Exif::PrintSFR($val)', + }, + 0xa20d => 'Noise', + 0xa20e => { + Name => 'FocalPlaneXResolution', + Groups => { 2 => 'Camera' }, + Writable => 'rational64u', + }, + 0xa20f => { + Name => 'FocalPlaneYResolution', + Groups => { 2 => 'Camera' }, + Writable => 'rational64u', + }, + 0xa210 => { + Name => 'FocalPlaneResolutionUnit', + Groups => { 2 => 'Camera' }, + Notes => 'values 1, 4 and 5 are not standard EXIF', + Writable => 'int16u', + PrintConv => { + 1 => 'None', # (not standard EXIF) + 2 => 'inches', + 3 => 'cm', + 4 => 'mm', # (not standard EXIF) + 5 => 'um', # (not standard EXIF) + }, + }, + 0xa211 => 'ImageNumber', + 0xa212 => 'SecurityClassification', + 0xa213 => 'ImageHistory', + 0xa214 => { + Name => 'SubjectLocation', + Groups => { 2 => 'Camera' }, + Writable => 'int16u', + Count => 2, + }, + 0xa215 => { Name => 'ExposureIndex', Writable => 'rational64u' }, + 0xa216 => 'TIFF-EPStandardID', + 0xa217 => { + Name => 'SensingMethod', + Groups => { 2 => 'Camera' }, + Writable => 'int16u', + PrintConv => { + 1 => 'Not defined', + 2 => 'One-chip color area', + 3 => 'Two-chip color area', + 4 => 'Three-chip color area', + 5 => 'Color sequential area', + 7 => 'Trilinear', + 8 => 'Color sequential linear', + }, + }, + 0xa300 => { + Name => 'FileSource', + Writable => 'undef', + ValueConvInv => '($val=~/^\d+$/ and $val < 256) ? chr($val) : $val', + PrintConv => { + 1 => 'Film Scanner', + 2 => 'Reflection Print Scanner', + 3 => 'Digital Camera', + # handle the case where Sigma incorrectly gives this tag a count of 4 + "\3\0\0\0" => 'Sigma Digital Camera', + }, + }, + 0xa301 => { + Name => 'SceneType', + Writable => 'undef', + ValueConvInv => 'chr($val)', + PrintConv => { + 1 => 'Directly photographed', + }, + }, + 0xa302 => { + Name => 'CFAPattern', + Writable => 'undef', + RawConv => 'Image::ExifTool::Exif::DecodeCFAPattern($self, $val)', + RawConvInv => q{ + my @a = split ' ', $val; + return $val if @a <= 2; # also accept binary data for backward compatibility + return pack(GetByteOrder() eq 'II' ? 'v2C*' : 'n2C*', @a); + }, + PrintConv => 'Image::ExifTool::Exif::PrintCFAPattern($val)', + PrintConvInv => 'Image::ExifTool::Exif::GetCFAPattern($val)', + }, + 0xa401 => { + Name => 'CustomRendered', + Writable => 'int16u', + Notes => q{ + only 0 and 1 are standard EXIF, but other values are used by Apple iOS + devices + }, + PrintConv => { + 0 => 'Normal', + 1 => 'Custom', + # 2 - also seen (Apple iOS) + 3 => 'HDR', # non-standard (Apple iOS) + # 4 - also seen (Apple iOS) - normal image from iOS Camera app (ref http://regex.info/blog/lightroom-goodies/metadata-presets) + 6 => 'Panorama', # non-standard (Apple iOS, horizontal or vertical) + # 7 - also seen (Apple iOS) + 8 => 'Portrait', # non-standard (Apple iOS, blurred background) + # 9 - also seen (Apple iOS) (HDR Portrait?) + }, + }, + 0xa402 => { + Name => 'ExposureMode', + Groups => { 2 => 'Camera' }, + Writable => 'int16u', + PrintConv => { + 0 => 'Auto', + 1 => 'Manual', + 2 => 'Auto bracket', + # have seen 3 from Samsung EX1, NX30, NX200 - PH + }, + }, + 0xa403 => { + Name => 'WhiteBalance', + Groups => { 2 => 'Camera' }, + Writable => 'int16u', + # set Priority to zero to keep this WhiteBalance from overriding the + # MakerNotes WhiteBalance, since the MakerNotes WhiteBalance and is more + # accurate and contains more information (if it exists) + Priority => 0, + PrintConv => { + 0 => 'Auto', + 1 => 'Manual', + }, + }, + 0xa404 => { + Name => 'DigitalZoomRatio', + Groups => { 2 => 'Camera' }, + Writable => 'rational64u', + }, + 0xa405 => { + Name => 'FocalLengthIn35mmFormat', + Notes => 'called FocalLengthIn35mmFilm by the EXIF spec.', + Groups => { 2 => 'Camera' }, + Writable => 'int16u', + PrintConv => '"$val mm"', + PrintConvInv => '$val=~s/\s*mm$//;$val', + }, + 0xa406 => { + Name => 'SceneCaptureType', + Groups => { 2 => 'Camera' }, + Writable => 'int16u', + PrintConv => { + 0 => 'Standard', + 1 => 'Landscape', + 2 => 'Portrait', + 3 => 'Night', + # 4 - HDR (Samsung GT-I9300) + }, + }, + 0xa407 => { + Name => 'GainControl', + Groups => { 2 => 'Camera' }, + Writable => 'int16u', + PrintConv => { + 0 => 'None', + 1 => 'Low gain up', + 2 => 'High gain up', + 3 => 'Low gain down', + 4 => 'High gain down', + }, + }, + 0xa408 => { + Name => 'Contrast', + Groups => { 2 => 'Camera' }, + Writable => 'int16u', + PrintConv => { + 0 => 'Normal', + 1 => 'Low', + 2 => 'High', + }, + PrintConvInv => 'Image::ExifTool::Exif::ConvertParameter($val)', + }, + 0xa409 => { + Name => 'Saturation', + Groups => { 2 => 'Camera' }, + Writable => 'int16u', + PrintConv => { + 0 => 'Normal', + 1 => 'Low', + 2 => 'High', + }, + PrintConvInv => 'Image::ExifTool::Exif::ConvertParameter($val)', + }, + 0xa40a => { + Name => 'Sharpness', + Groups => { 2 => 'Camera' }, + Writable => 'int16u', + PrintConv => { + 0 => 'Normal', + 1 => 'Soft', + 2 => 'Hard', + }, + PrintConvInv => 'Image::ExifTool::Exif::ConvertParameter($val)', + }, + 0xa40b => { + Name => 'DeviceSettingDescription', + Groups => { 2 => 'Camera' }, + Binary => 1, + }, + 0xa40c => { + Name => 'SubjectDistanceRange', + Groups => { 2 => 'Camera' }, + Writable => 'int16u', + PrintConv => { + 0 => 'Unknown', + 1 => 'Macro', + 2 => 'Close', + 3 => 'Distant', + }, + }, + # 0xa40d - int16u: 0 (GE E1486 TW) + # 0xa40e - int16u: 1 (GE E1486 TW) + 0xa420 => { Name => 'ImageUniqueID', Writable => 'string' }, + 0xa430 => { #24 + Name => 'OwnerName', + Notes => 'called CameraOwnerName by the EXIF spec.', + Writable => 'string', + }, + 0xa431 => { #24 + Name => 'SerialNumber', + Notes => 'called BodySerialNumber by the EXIF spec.', + Writable => 'string', + }, + 0xa432 => { #24 + Name => 'LensInfo', + Notes => q{ + 4 rational values giving focal and aperture ranges, called LensSpecification + by the EXIF spec. + }, + Writable => 'rational64u', + Count => 4, + # convert to the form "12-20mm f/3.8-4.5" or "50mm f/1.4" + PrintConv => \&PrintLensInfo, + PrintConvInv => \&ConvertLensInfo, + }, + 0xa433 => { Name => 'LensMake', Writable => 'string' }, #24 + 0xa434 => { Name => 'LensModel', Writable => 'string' }, #24 + 0xa435 => { Name => 'LensSerialNumber', Writable => 'string' }, #24 + 0xa480 => 'GDALMetadata', #3 + 0xa481 => 'GDALNoData', #3 + 0xa500 => { Name => 'Gamma', Writable => 'rational64u' }, + 0xafc0 => 'ExpandSoftware', #JD (Opanda) + 0xafc1 => 'ExpandLens', #JD (Opanda) + 0xafc2 => 'ExpandFilm', #JD (Opanda) + 0xafc3 => 'ExpandFilterLens', #JD (Opanda) + 0xafc4 => 'ExpandScanner', #JD (Opanda) + 0xafc5 => 'ExpandFlashLamp', #JD (Opanda) +# +# Windows Media Photo / HD Photo (WDP/HDP) tags +# + 0xbc01 => { #13 + Name => 'PixelFormat', + PrintHex => 1, + Format => 'undef', + Notes => q{ + tags 0xbc** are used in Windows HD Photo (HDP and WDP) images. The actual + PixelFormat values are 16-byte GUID's but the leading 15 bytes, + '6fddc324-4e03-4bfe-b1853-d77768dc9', have been removed below to avoid + unnecessary clutter + }, + ValueConv => q{ + require Image::ExifTool::ASF; + $val = Image::ExifTool::ASF::GetGUID($val); + # GUID's are too long, so remove redundant information + $val =~ s/^6fddc324-4e03-4bfe-b185-3d77768dc9//i and $val = hex($val); + return $val; + }, + PrintConv => { + 0x0d => '24-bit RGB', + 0x0c => '24-bit BGR', + 0x0e => '32-bit BGR', + 0x15 => '48-bit RGB', + 0x12 => '48-bit RGB Fixed Point', + 0x3b => '48-bit RGB Half', + 0x18 => '96-bit RGB Fixed Point', + 0x1b => '128-bit RGB Float', + 0x0f => '32-bit BGRA', + 0x16 => '64-bit RGBA', + 0x1d => '64-bit RGBA Fixed Point', + 0x3a => '64-bit RGBA Half', + 0x1e => '128-bit RGBA Fixed Point', + 0x19 => '128-bit RGBA Float', + 0x10 => '32-bit PBGRA', + 0x17 => '64-bit PRGBA', + 0x1a => '128-bit PRGBA Float', + 0x1c => '32-bit CMYK', + 0x2c => '40-bit CMYK Alpha', + 0x1f => '64-bit CMYK', + 0x2d => '80-bit CMYK Alpha', + 0x20 => '24-bit 3 Channels', + 0x21 => '32-bit 4 Channels', + 0x22 => '40-bit 5 Channels', + 0x23 => '48-bit 6 Channels', + 0x24 => '56-bit 7 Channels', + 0x25 => '64-bit 8 Channels', + 0x2e => '32-bit 3 Channels Alpha', + 0x2f => '40-bit 4 Channels Alpha', + 0x30 => '48-bit 5 Channels Alpha', + 0x31 => '56-bit 6 Channels Alpha', + 0x32 => '64-bit 7 Channels Alpha', + 0x33 => '72-bit 8 Channels Alpha', + 0x26 => '48-bit 3 Channels', + 0x27 => '64-bit 4 Channels', + 0x28 => '80-bit 5 Channels', + 0x29 => '96-bit 6 Channels', + 0x2a => '112-bit 7 Channels', + 0x2b => '128-bit 8 Channels', + 0x34 => '64-bit 3 Channels Alpha', + 0x35 => '80-bit 4 Channels Alpha', + 0x36 => '96-bit 5 Channels Alpha', + 0x37 => '112-bit 6 Channels Alpha', + 0x38 => '128-bit 7 Channels Alpha', + 0x39 => '144-bit 8 Channels Alpha', + 0x08 => '8-bit Gray', + 0x0b => '16-bit Gray', + 0x13 => '16-bit Gray Fixed Point', + 0x3e => '16-bit Gray Half', + 0x3f => '32-bit Gray Fixed Point', + 0x11 => '32-bit Gray Float', + 0x05 => 'Black & White', + 0x09 => '16-bit BGR555', + 0x0a => '16-bit BGR565', + 0x13 => '32-bit BGR101010', + 0x3d => '32-bit RGBE', + }, + }, + 0xbc02 => { #13 + Name => 'Transformation', + PrintConv => { + 0 => 'Horizontal (normal)', + 1 => 'Mirror vertical', + 2 => 'Mirror horizontal', + 3 => 'Rotate 180', + 4 => 'Rotate 90 CW', + 5 => 'Mirror horizontal and rotate 90 CW', + 6 => 'Mirror horizontal and rotate 270 CW', + 7 => 'Rotate 270 CW', + }, + }, + 0xbc03 => { #13 + Name => 'Uncompressed', + PrintConv => { 0 => 'No', 1 => 'Yes' }, + }, + 0xbc04 => { #13 + Name => 'ImageType', + PrintConv => { BITMASK => { + 0 => 'Preview', + 1 => 'Page', + } }, + }, + 0xbc80 => 'ImageWidth', #13 + 0xbc81 => 'ImageHeight', #13 + 0xbc82 => 'WidthResolution', #13 + 0xbc83 => 'HeightResolution', #13 + 0xbcc0 => { #13 + Name => 'ImageOffset', + IsOffset => 1, + OffsetPair => 0xbcc1, # point to associated byte count + }, + 0xbcc1 => { #13 + Name => 'ImageByteCount', + OffsetPair => 0xbcc0, # point to associated offset + }, + 0xbcc2 => { #13 + Name => 'AlphaOffset', + IsOffset => 1, + OffsetPair => 0xbcc3, # point to associated byte count + }, + 0xbcc3 => { #13 + Name => 'AlphaByteCount', + OffsetPair => 0xbcc2, # point to associated offset + }, + 0xbcc4 => { #13 + Name => 'ImageDataDiscard', + PrintConv => { + 0 => 'Full Resolution', + 1 => 'Flexbits Discarded', + 2 => 'HighPass Frequency Data Discarded', + 3 => 'Highpass and LowPass Frequency Data Discarded', + }, + }, + 0xbcc5 => { #13 + Name => 'AlphaDataDiscard', + PrintConv => { + 0 => 'Full Resolution', + 1 => 'Flexbits Discarded', + 2 => 'HighPass Frequency Data Discarded', + 3 => 'Highpass and LowPass Frequency Data Discarded', + }, + }, +# + 0xc427 => 'OceScanjobDesc', #3 + 0xc428 => 'OceApplicationSelector', #3 + 0xc429 => 'OceIDNumber', #3 + 0xc42a => 'OceImageLogic', #3 + 0xc44f => { Name => 'Annotations', Binary => 1 }, #7/19 + 0xc4a5 => { + Name => 'PrintIM', # (writable directory!) + # must set Writable here so this tag will be saved with MakerNotes option + Writable => 'undef', + WriteGroup => 'IFD0', + Binary => 1, + # (don't make Binary/Protected because we can't copy individual PrintIM tags anyway) + Description => 'Print Image Matching', + SubDirectory => { + TagTable => 'Image::ExifTool::PrintIM::Main', + }, + PrintConvInv => '$val =~ /^PrintIM/ ? $val : undef', # quick validation + }, + 0xc573 => { #PH + Name => 'OriginalFileName', + Notes => 'used by some obscure software', # (possibly Swizzy Photosmacker?) + # (it is a 'string', but obscure, so don't make it writable) + }, + 0xc580 => { #20 + Name => 'USPTOOriginalContentType', + PrintConv => { + 0 => 'Text or Drawing', + 1 => 'Grayscale', + 2 => 'Color', + }, + }, + # 0xc5d8 - found in CR2 images + # 0xc5d9 - found in CR2 images + 0xc5e0 => { #forum8153 (CR2 images) + Name => 'CR2CFAPattern', + ValueConv => { + 1 => '0 1 1 2', + 2 => '2 1 1 0', + 3 => '1 2 0 1', + 4 => '1 0 2 1', + }, + PrintConv => { + '0 1 1 2' => '[Red,Green][Green,Blue]', + '2 1 1 0' => '[Blue,Green][Green,Red]', + '1 2 0 1' => '[Green,Blue][Red,Green]', + '1 0 2 1' => '[Green,Red][Blue,Green]', + }, + }, +# +# DNG tags 0xc6XX and 0xc7XX (ref 2 unless otherwise stated) +# + 0xc612 => { + Name => 'DNGVersion', + Notes => q{ + tags 0xc612-0xc7b5 are defined by the DNG specification unless otherwise + noted. See L<https://helpx.adobe.com/photoshop/digital-negative.html> for + the specification + }, + Writable => 'int8u', + WriteGroup => 'IFD0', + Count => 4, + Protected => 1, # (confuses Apple Preview if written to a TIFF image) + DataMember => 'DNGVersion', + RawConv => '$$self{DNGVersion} = $val', + PrintConv => '$val =~ tr/ /./; $val', + PrintConvInv => '$val =~ tr/./ /; $val', + }, + 0xc613 => { + Name => 'DNGBackwardVersion', + Writable => 'int8u', + WriteGroup => 'IFD0', + Count => 4, + Protected => 1, + PrintConv => '$val =~ tr/ /./; $val', + PrintConvInv => '$val =~ tr/./ /; $val', + }, + 0xc614 => { + Name => 'UniqueCameraModel', + Writable => 'string', + WriteGroup => 'IFD0', + }, + 0xc615 => { + Name => 'LocalizedCameraModel', + WriteGroup => 'IFD0', + %utf8StringConv, + PrintConv => '$self->Printable($val, 0)', + PrintConvInv => '$val', + }, + 0xc616 => { + Name => 'CFAPlaneColor', + WriteGroup => 'SubIFD', # (only for Validate) + PrintConv => q{ + my @cols = qw(Red Green Blue Cyan Magenta Yellow White); + my @vals = map { $cols[$_] || "Unknown($_)" } split(' ', $val); + return join(',', @vals); + }, + }, + 0xc617 => { + Name => 'CFALayout', + WriteGroup => 'SubIFD', # (only for Validate) + PrintConv => { + 1 => 'Rectangular', + 2 => 'Even columns offset down 1/2 row', + 3 => 'Even columns offset up 1/2 row', + 4 => 'Even rows offset right 1/2 column', + 5 => 'Even rows offset left 1/2 column', + # the following are new for DNG 1.3: + 6 => 'Even rows offset up by 1/2 row, even columns offset left by 1/2 column', + 7 => 'Even rows offset up by 1/2 row, even columns offset right by 1/2 column', + 8 => 'Even rows offset down by 1/2 row, even columns offset left by 1/2 column', + 9 => 'Even rows offset down by 1/2 row, even columns offset right by 1/2 column', + }, + }, + 0xc618 => { + Name => 'LinearizationTable', + Writable => 'int16u', + WriteGroup => 'SubIFD', + Count => -1, + Protected => 1, + Binary => 1, + }, + 0xc619 => { + Name => 'BlackLevelRepeatDim', + Writable => 'int16u', + WriteGroup => 'SubIFD', + Count => 2, + Protected => 1, + }, + 0xc61a => { + Name => 'BlackLevel', + Writable => 'rational64u', + WriteGroup => 'SubIFD', + Count => -1, + Protected => 1, + }, + 0xc61b => { + Name => 'BlackLevelDeltaH', + %longBin, + Writable => 'rational64s', + WriteGroup => 'SubIFD', + Count => -1, + Protected => 1, + }, + 0xc61c => { + Name => 'BlackLevelDeltaV', + %longBin, + Writable => 'rational64s', + WriteGroup => 'SubIFD', + Count => -1, + Protected => 1, + }, + 0xc61d => { + Name => 'WhiteLevel', + Writable => 'int32u', + WriteGroup => 'SubIFD', + Count => -1, + Protected => 1, + }, + 0xc61e => { + Name => 'DefaultScale', + Writable => 'rational64u', + WriteGroup => 'SubIFD', + Count => 2, + Protected => 1, + }, + 0xc61f => { + Name => 'DefaultCropOrigin', + Writable => 'int32u', + WriteGroup => 'SubIFD', + Count => 2, + Protected => 1, + }, + 0xc620 => { + Name => 'DefaultCropSize', + Writable => 'int32u', + WriteGroup => 'SubIFD', + Count => 2, + Protected => 1, + }, + 0xc621 => { + Name => 'ColorMatrix1', + Writable => 'rational64s', + WriteGroup => 'IFD0', + Count => -1, + Protected => 1, + }, + 0xc622 => { + Name => 'ColorMatrix2', + Writable => 'rational64s', + WriteGroup => 'IFD0', + Count => -1, + Protected => 1, + }, + 0xc623 => { + Name => 'CameraCalibration1', + Writable => 'rational64s', + WriteGroup => 'IFD0', + Count => -1, + Protected => 1, + }, + 0xc624 => { + Name => 'CameraCalibration2', + Writable => 'rational64s', + WriteGroup => 'IFD0', + Count => -1, + Protected => 1, + }, + 0xc625 => { + Name => 'ReductionMatrix1', + Writable => 'rational64s', + WriteGroup => 'IFD0', + Count => -1, + Protected => 1, + }, + 0xc626 => { + Name => 'ReductionMatrix2', + Writable => 'rational64s', + WriteGroup => 'IFD0', + Count => -1, + Protected => 1, + }, + 0xc627 => { + Name => 'AnalogBalance', + Writable => 'rational64u', + WriteGroup => 'IFD0', + Count => -1, + Protected => 1, + }, + 0xc628 => { + Name => 'AsShotNeutral', + Writable => 'rational64u', + WriteGroup => 'IFD0', + Count => -1, + Protected => 1, + }, + 0xc629 => { + Name => 'AsShotWhiteXY', + Writable => 'rational64u', + WriteGroup => 'IFD0', + Count => 2, + Protected => 1, + }, + 0xc62a => { + Name => 'BaselineExposure', + Writable => 'rational64s', + WriteGroup => 'IFD0', + Protected => 1, + }, + 0xc62b => { + Name => 'BaselineNoise', + Writable => 'rational64u', + WriteGroup => 'IFD0', + Protected => 1, + }, + 0xc62c => { + Name => 'BaselineSharpness', + Writable => 'rational64u', + WriteGroup => 'IFD0', + Protected => 1, + }, + 0xc62d => { + Name => 'BayerGreenSplit', + Writable => 'int32u', + WriteGroup => 'SubIFD', + Protected => 1, + }, + 0xc62e => { + Name => 'LinearResponseLimit', + Writable => 'rational64u', + WriteGroup => 'IFD0', + Protected => 1, + }, + 0xc62f => { + Name => 'CameraSerialNumber', + Groups => { 2 => 'Camera' }, + Writable => 'string', + WriteGroup => 'IFD0', + }, + 0xc630 => { + Name => 'DNGLensInfo', + Groups => { 2 => 'Camera' }, + Writable => 'rational64u', + WriteGroup => 'IFD0', + Count => 4, + PrintConv =>\&PrintLensInfo, + PrintConvInv => \&ConvertLensInfo, + }, + 0xc631 => { + Name => 'ChromaBlurRadius', + Writable => 'rational64u', + WriteGroup => 'SubIFD', + Protected => 1, + }, + 0xc632 => { + Name => 'AntiAliasStrength', + Writable => 'rational64u', + WriteGroup => 'SubIFD', + Protected => 1, + }, + 0xc633 => { + Name => 'ShadowScale', + Writable => 'rational64u', + WriteGroup => 'IFD0', + Protected => 1, + }, + 0xc634 => [ + { + Condition => '$$self{TIFF_TYPE} =~ /^(ARW|SR2)$/', + Name => 'SR2Private', + Groups => { 1 => 'SR2' }, + Flags => 'SubIFD', + Format => 'int32u', + # some utilites have problems unless this is int8u format: + # - Adobe Camera Raw 5.3 gives an error + # - Apple Preview 10.5.8 gets the wrong white balance + FixFormat => 'int8u', # (stupid Sony) + WriteGroup => 'IFD0', # (for Validate) + SubDirectory => { + DirName => 'SR2Private', + TagTable => 'Image::ExifTool::Sony::SR2Private', + Start => '$val', + }, + }, + { + Condition => '$$valPt =~ /^Adobe\0/', + Name => 'DNGAdobeData', + Flags => [ 'Binary', 'Protected' ], + Writable => 'undef', # (writable directory!) (to make it possible to delete this mess) + WriteGroup => 'IFD0', + NestedHtmlDump => 1, + SubDirectory => { TagTable => 'Image::ExifTool::DNG::AdobeData' }, + Format => 'undef', # but written as int8u (change to undef for speed) + }, + { + # Pentax/Samsung models that write AOC maker notes in JPG images: + # K-5,K-7,K-m,K-x,K-r,K10D,K20D,K100D,K110D,K200D,K2000,GX10,GX20 + # (Note: the following expression also appears in WriteExif.pl) + Condition => q{ + $$valPt =~ /^(PENTAX |SAMSUNG)\0/ and + $$self{Model} =~ /\b(K(-[57mrx]|(10|20|100|110|200)D|2000)|GX(10|20))\b/ + }, + Name => 'MakerNotePentax', + MakerNotes => 1, # (causes "MakerNotes header" to be identified in HtmlDump output) + Binary => 1, + WriteGroup => 'IFD0', # (for Validate) + # Note: Don't make this block-writable for a few reasons: + # 1) It would be dangerous (possibly confusing Pentax software) + # 2) It is a different format from the JPEG version of MakerNotePentax + # 3) It is converted to JPEG format by RebuildMakerNotes() when copying + SubDirectory => { + TagTable => 'Image::ExifTool::Pentax::Main', + Start => '$valuePtr + 10', + Base => '$start - 10', + ByteOrder => 'Unknown', # easier to do this than read byteorder word + }, + Format => 'undef', # but written as int8u (change to undef for speed) + }, + { + # must duplicate the above tag with a different name for more recent + # Pentax models which use the "PENTAX" instead of the "AOC" maker notes + # in JPG images (needed when copying maker notes from DNG to JPG) + Condition => '$$valPt =~ /^(PENTAX |SAMSUNG)\0/', + Name => 'MakerNotePentax5', + MakerNotes => 1, + Binary => 1, + WriteGroup => 'IFD0', # (for Validate) + SubDirectory => { + TagTable => 'Image::ExifTool::Pentax::Main', + Start => '$valuePtr + 10', + Base => '$start - 10', + ByteOrder => 'Unknown', + }, + Format => 'undef', + }, + { + # Ricoh models such as the GR III + Condition => '$$valPt =~ /^RICOH\0(II|MM)/', + Name => 'MakerNoteRicohPentax', + MakerNotes => 1, + Binary => 1, + WriteGroup => 'IFD0', # (for Validate) + SubDirectory => { + TagTable => 'Image::ExifTool::Pentax::Main', + Start => '$valuePtr + 8', + Base => '$start - 8', + ByteOrder => 'Unknown', + }, + Format => 'undef', + }, + { + Name => 'DNGPrivateData', + Flags => [ 'Binary', 'Protected' ], + Format => 'undef', + Writable => 'int8u', + WriteGroup => 'IFD0', + }, + ], + 0xc635 => { + Name => 'MakerNoteSafety', + Writable => 'int16u', + WriteGroup => 'IFD0', + PrintConv => { + 0 => 'Unsafe', + 1 => 'Safe', + }, + }, + 0xc640 => { #15 + Name => 'RawImageSegmentation', + # (int16u[3], not writable) + Notes => q{ + used in segmented Canon CR2 images. 3 numbers: 1. Number of segments minus + one; 2. Pixel width of segments except last; 3. Pixel width of last segment + }, + }, + 0xc65a => { + Name => 'CalibrationIlluminant1', + Writable => 'int16u', + WriteGroup => 'IFD0', + Protected => 1, + SeparateTable => 'LightSource', + PrintConv => \%lightSource, + }, + 0xc65b => { + Name => 'CalibrationIlluminant2', + Writable => 'int16u', + WriteGroup => 'IFD0', + Protected => 1, + SeparateTable => 'LightSource', + PrintConv => \%lightSource, + }, + 0xc65c => { + Name => 'BestQualityScale', + Writable => 'rational64u', + WriteGroup => 'SubIFD', + Protected => 1, + }, + 0xc65d => { + Name => 'RawDataUniqueID', + Format => 'undef', + Writable => 'int8u', + WriteGroup => 'IFD0', + Count => 16, + Protected => 1, + ValueConv => 'uc(unpack("H*",$val))', + ValueConvInv => 'pack("H*", $val)', + }, + 0xc660 => { #3 + Name => 'AliasLayerMetadata', + Notes => 'used by Alias Sketchbook Pro', + }, + 0xc68b => { + Name => 'OriginalRawFileName', + WriteGroup => 'IFD0', + Protected => 1, + %utf8StringConv, + }, + 0xc68c => { + Name => 'OriginalRawFileData', # (writable directory!) + Writable => 'undef', # must be defined here so tag will be extracted if specified + WriteGroup => 'IFD0', + Flags => [ 'Binary', 'Protected' ], + SubDirectory => { + TagTable => 'Image::ExifTool::DNG::OriginalRaw', + }, + }, + 0xc68d => { + Name => 'ActiveArea', + Writable => 'int32u', + WriteGroup => 'SubIFD', + Count => 4, + Protected => 1, + }, + 0xc68e => { + Name => 'MaskedAreas', + Writable => 'int32u', + WriteGroup => 'SubIFD', + Count => -1, + Protected => 1, + }, + 0xc68f => { + Name => 'AsShotICCProfile', # (writable directory) + Binary => 1, + Writable => 'undef', # must be defined here so tag will be extracted if specified + WriteGroup => 'IFD0', + Protected => 1, + WriteCheck => q{ + require Image::ExifTool::ICC_Profile; + return Image::ExifTool::ICC_Profile::ValidateICC(\$val); + }, + SubDirectory => { + DirName => 'AsShotICCProfile', + TagTable => 'Image::ExifTool::ICC_Profile::Main', + }, + }, + 0xc690 => { + Name => 'AsShotPreProfileMatrix', + Writable => 'rational64s', + WriteGroup => 'IFD0', + Count => -1, + Protected => 1, + }, + 0xc691 => { + Name => 'CurrentICCProfile', # (writable directory) + Binary => 1, + Writable => 'undef', # must be defined here so tag will be extracted if specified + SubDirectory => { + DirName => 'CurrentICCProfile', + TagTable => 'Image::ExifTool::ICC_Profile::Main', + }, + Writable => 'undef', + WriteGroup => 'IFD0', + Protected => 1, + WriteCheck => q{ + require Image::ExifTool::ICC_Profile; + return Image::ExifTool::ICC_Profile::ValidateICC(\$val); + }, + }, + 0xc692 => { + Name => 'CurrentPreProfileMatrix', + Writable => 'rational64s', + WriteGroup => 'IFD0', + Count => -1, + Protected => 1, + }, + 0xc6bf => { + Name => 'ColorimetricReference', + Writable => 'int16u', + WriteGroup => 'IFD0', + Protected => 1, + }, + 0xc6c5 => { Name => 'SRawType', Description => 'SRaw Type', WriteGroup => 'IFD0' }, #exifprobe (CR2 proprietary) + 0xc6d2 => { #JD (Panasonic DMC-TZ5) + # this text is UTF-8 encoded (hooray!) - PH (TZ5) + Name => 'PanasonicTitle', + Format => 'string', # written incorrectly as 'undef' + Notes => 'proprietary Panasonic tag used for baby/pet name, etc', + Writable => 'undef', + WriteGroup => 'IFD0', + # panasonic always records this tag (64 zero bytes), + # so ignore it unless it contains valid information + RawConv => 'length($val) ? $val : undef', + ValueConv => '$self->Decode($val, "UTF8")', + ValueConvInv => '$self->Encode($val,"UTF8")', + }, + 0xc6d3 => { #PH (Panasonic DMC-FS7) + Name => 'PanasonicTitle2', + Format => 'string', # written incorrectly as 'undef' + Notes => 'proprietary Panasonic tag used for baby/pet name with age', + Writable => 'undef', + WriteGroup => 'IFD0', + # panasonic always records this tag (128 zero bytes), + # so ignore it unless it contains valid information + RawConv => 'length($val) ? $val : undef', + ValueConv => '$self->Decode($val, "UTF8")', + ValueConvInv => '$self->Encode($val,"UTF8")', + }, + # 0xc6dc - int32u[4]: found in CR2 images (PH, 7DmkIII) + # 0xc6dd - int16u[256]: found in CR2 images (PH, 5DmkIV) + 0xc6f3 => { + Name => 'CameraCalibrationSig', + WriteGroup => 'IFD0', + Protected => 1, + %utf8StringConv, + }, + 0xc6f4 => { + Name => 'ProfileCalibrationSig', + WriteGroup => 'IFD0', + Protected => 1, + %utf8StringConv, + }, + 0xc6f5 => { + Name => 'ProfileIFD', # (ExtraCameraProfiles) + Groups => { 1 => 'ProfileIFD' }, + Flags => 'SubIFD', + WriteGroup => 'IFD0', # (only for Validate) + SubDirectory => { + ProcessProc => \&ProcessTiffIFD, + WriteProc => \&ProcessTiffIFD, + DirName => 'ProfileIFD', + Start => '$val', + Base => '$start', # offsets relative to start of TIFF-like header + MaxSubdirs => 10, + Magic => 0x4352, # magic number for TIFF-like header + }, + }, + 0xc6f6 => { + Name => 'AsShotProfileName', + WriteGroup => 'IFD0', + Protected => 1, + %utf8StringConv, + }, + 0xc6f7 => { + Name => 'NoiseReductionApplied', + Writable => 'rational64u', + WriteGroup => 'SubIFD', + Protected => 1, + }, + 0xc6f8 => { + Name => 'ProfileName', + WriteGroup => 'IFD0', + Protected => 1, + %utf8StringConv, + }, + 0xc6f9 => { + Name => 'ProfileHueSatMapDims', + Writable => 'int32u', + WriteGroup => 'IFD0', + Count => 3, + Protected => 1, + }, + 0xc6fa => { + Name => 'ProfileHueSatMapData1', + %longBin, + Writable => 'float', + WriteGroup => 'IFD0', + Count => -1, + Protected => 1, + }, + 0xc6fb => { + Name => 'ProfileHueSatMapData2', + %longBin, + Writable => 'float', + WriteGroup => 'IFD0', + Count => -1, + Protected => 1, + }, + 0xc6fc => { + Name => 'ProfileToneCurve', + Writable => 'float', + WriteGroup => 'IFD0', + Count => -1, + Protected => 1, + Binary => 1, + }, + 0xc6fd => { + Name => 'ProfileEmbedPolicy', + Writable => 'int32u', + WriteGroup => 'IFD0', + Protected => 1, + PrintConv => { + 0 => 'Allow Copying', + 1 => 'Embed if Used', + 2 => 'Never Embed', + 3 => 'No Restrictions', + }, + }, + 0xc6fe => { + Name => 'ProfileCopyright', + WriteGroup => 'IFD0', + Protected => 1, + %utf8StringConv, + }, + 0xc714 => { + Name => 'ForwardMatrix1', + Writable => 'rational64s', + WriteGroup => 'IFD0', + Count => -1, + Protected => 1, + }, + 0xc715 => { + Name => 'ForwardMatrix2', + Writable => 'rational64s', + WriteGroup => 'IFD0', + Count => -1, + Protected => 1, + }, + 0xc716 => { + Name => 'PreviewApplicationName', + WriteGroup => 'IFD0', + Protected => 1, + %utf8StringConv, + }, + 0xc717 => { + Name => 'PreviewApplicationVersion', + Writable => 'string', + WriteGroup => 'IFD0', + Protected => 1, + %utf8StringConv, + }, + 0xc718 => { + Name => 'PreviewSettingsName', + Writable => 'string', + WriteGroup => 'IFD0', + Protected => 1, + %utf8StringConv, + }, + 0xc719 => { + Name => 'PreviewSettingsDigest', + Format => 'undef', + Writable => 'int8u', + WriteGroup => 'IFD0', + Protected => 1, + ValueConv => 'unpack("H*", $val)', + ValueConvInv => 'pack("H*", $val)', + }, + 0xc71a => { + Name => 'PreviewColorSpace', + Writable => 'int32u', + WriteGroup => 'IFD0', + Protected => 1, + PrintConv => { + 0 => 'Unknown', + 1 => 'Gray Gamma 2.2', + 2 => 'sRGB', + 3 => 'Adobe RGB', + 4 => 'ProPhoto RGB', + }, + }, + 0xc71b => { + Name => 'PreviewDateTime', + Groups => { 2 => 'Time' }, + Writable => 'string', + Shift => 'Time', + WriteGroup => 'IFD0', + Protected => 1, + ValueConv => q{ + require Image::ExifTool::XMP; + return Image::ExifTool::XMP::ConvertXMPDate($val); + }, + ValueConvInv => q{ + require Image::ExifTool::XMP; + return Image::ExifTool::XMP::FormatXMPDate($val); + }, + PrintConv => '$self->ConvertDateTime($val)', + PrintConvInv => '$self->InverseDateTime($val,1,1)', + }, + 0xc71c => { + Name => 'RawImageDigest', + Format => 'undef', + Writable => 'int8u', + WriteGroup => 'IFD0', + Count => 16, + Protected => 1, + ValueConv => 'unpack("H*", $val)', + ValueConvInv => 'pack("H*", $val)', + }, + 0xc71d => { + Name => 'OriginalRawFileDigest', + Format => 'undef', + Writable => 'int8u', + WriteGroup => 'IFD0', + Count => 16, + Protected => 1, + ValueConv => 'unpack("H*", $val)', + ValueConvInv => 'pack("H*", $val)', + }, + 0xc71e => 'SubTileBlockSize', + 0xc71f => 'RowInterleaveFactor', + 0xc725 => { + Name => 'ProfileLookTableDims', + Writable => 'int32u', + WriteGroup => 'IFD0', + Count => 3, + Protected => 1, + }, + 0xc726 => { + Name => 'ProfileLookTableData', + Writable => 'float', + WriteGroup => 'IFD0', + Count => -1, + Protected => 1, + Binary => 1, + }, + 0xc740 => { # DNG 1.3 + Name => 'OpcodeList1', + Writable => 'undef', + WriteGroup => 'SubIFD', + Protected => 1, + Binary => 1, + # opcodes: + # 1 => 'WarpRectilinear', + # 2 => 'WarpFisheye', + # 3 => 'FixVignetteRadial', + # 4 => 'FixBadPixelsConstant', + # 5 => 'FixBadPixelsList', + # 6 => 'TrimBounds', + # 7 => 'MapTable', + # 8 => 'MapPolynomial', + # 9 => 'GainMap', + # 10 => 'DeltaPerRow', + # 11 => 'DeltaPerColumn', + # 12 => 'ScalePerRow', + # 13 => 'ScalePerColumn', + }, + 0xc741 => { # DNG 1.3 + Name => 'OpcodeList2', + Writable => 'undef', + WriteGroup => 'SubIFD', + Protected => 1, + Binary => 1, + }, + 0xc74e => { # DNG 1.3 + Name => 'OpcodeList3', + Writable => 'undef', + WriteGroup => 'SubIFD', + Protected => 1, + Binary => 1, + }, + 0xc761 => { # DNG 1.3 + Name => 'NoiseProfile', + Writable => 'double', + WriteGroup => 'SubIFD', + Count => -1, + Protected => 1, + }, + 0xc763 => { #28 + Name => 'TimeCodes', + Writable => 'int8u', + WriteGroup => 'IFD0', + Count => -1, # (8 * number of time codes, max 10) + ValueConv => q{ + my @a = split ' ', $val; + my @v; + push @v, join('.', map { sprintf('%.2x',$_) } splice(@a,0,8)) while @a >= 8; + join ' ', @v; + }, + ValueConvInv => q{ + my @a = map hex, split /[. ]+/, $val; + join ' ', @a; + }, + # Note: Currently ignore the flags: + # byte 0 0x80 - color frame + # byte 0 0x40 - drop frame + # byte 1 0x80 - field phase + PrintConv => q{ + my @a = map hex, split /[. ]+/, $val; + my @v; + while (@a >= 8) { + my $str = sprintf("%.2x:%.2x:%.2x.%.2x", $a[3]&0x3f, + $a[2]&0x7f, $a[1]&0x7f, $a[0]&0x3f); + if ($a[3] & 0x80) { # date+timezone exist if BGF2 is set + my $tz = $a[7] & 0x3f; + my $bz = sprintf('%.2x', $tz); + $bz = 100 if $bz =~ /[a-f]/i; # not BCD + if ($bz < 26) { + $tz = ($bz < 13 ? 0 : 26) - $bz; + } elsif ($bz == 32) { + $tz = 12.75; + } elsif ($bz >= 28 and $bz <= 31) { + $tz = 0; # UTC + } elsif ($bz < 100) { + undef $tz; # undefined or user-defined + } elsif ($tz < 0x20) { + $tz = (($tz < 0x10 ? 10 : 20) - $tz) - 0.5; + } else { + $tz = (($tz < 0x30 ? 53 : 63) - $tz) + 0.5; + } + if ($a[7] & 0x80) { # MJD format (/w UTC time) + my ($h,$m,$s,$f) = split /[:.]/, $str; + my $jday = sprintf('%x%.2x%.2x', reverse @a[4..6]); + $str = ConvertUnixTime(($jday - 40587) * 24 * 3600 + + ((($h+$tz) * 60) + $m) * 60 + $s) . ".$f"; + $str =~ s/^(\d+):(\d+):(\d+) /$1-$2-${3}T/; + } else { # YYMMDD (Note: CinemaDNG 1.1 example seems wrong) + my $yr = sprintf('%.2x',$a[6]) + 1900; + $yr += 100 if $yr < 1970; + $str = sprintf('%d-%.2x-%.2xT%s',$yr,$a[5],$a[4],$str); + } + $str .= TimeZoneString($tz*60) if defined $tz; + } + push @v, $str; + splice @a, 0, 8; + } + join ' ', @v; + }, + PrintConvInv => q{ + my @a = split ' ', $val; + my @v; + foreach (@a) { + my @td = reverse split /T/; + my $tz = 0x39; # default to unknown timezone + if ($td[0] =~ s/([-+])(\d+):(\d+)$//) { + if ($3 == 0) { + $tz = hex(($1 eq '-') ? $2 : 0x26 - $2); + } elsif ($3 == 30) { + if ($1 eq '-') { + $tz = $2 + 0x0a; + $tz += 0x0a if $tz > 0x0f; + } else { + $tz = 0x3f - $2; + $tz -= 0x0a if $tz < 0x3a; + } + } elsif ($3 == 45) { + $tz = 0x32 if $1 eq '+' and $2 == 12; + } + } + my @t = split /[:.]/, $td[0]; + push @t, '00' while @t < 4; + my $bg; + if ($td[1]) { + # date was specified: fill in date & timezone + my @d = split /[-]/, $td[1]; + next if @d < 3; + $bg = sprintf('.%.2d.%.2d.%.2d.%.2x', $d[2], $d[1], $d[0]%100, $tz); + $t[0] = sprintf('%.2x', hex($t[0]) + 0xc0); # set BGF1+BGF2 + } else { # time only + $bg = '.00.00.00.00'; + } + push @v, join('.', reverse(@t[0..3])) . $bg; + } + join ' ', @v; + }, + }, + 0xc764 => { #28 + Name => 'FrameRate', + Writable => 'rational64s', + WriteGroup => 'IFD0', + PrintConv => 'int($val * 1000 + 0.5) / 1000', + PrintConvInv => '$val', + }, + 0xc772 => { #28 + Name => 'TStop', + Writable => 'rational64u', + WriteGroup => 'IFD0', + Count => -1, # (1 or 2) + PrintConv => 'join("-", map { sprintf("%.2f",$_) } split " ", $val)', + PrintConvInv => '$val=~tr/-/ /; $val', + }, + 0xc789 => { #28 + Name => 'ReelName', + Writable => 'string', + WriteGroup => 'IFD0', + }, + 0xc791 => { # DNG 1.4 + Name => 'OriginalDefaultFinalSize', + Writable => 'int32u', + WriteGroup => 'IFD0', + Count => 2, + Protected => 1, + }, + 0xc792 => { # DNG 1.4 + Name => 'OriginalBestQualitySize', + Notes => 'called OriginalBestQualityFinalSize by the DNG spec', + Writable => 'int32u', + WriteGroup => 'IFD0', + Count => 2, + Protected => 1, + }, + 0xc793 => { # DNG 1.4 + Name => 'OriginalDefaultCropSize', + Writable => 'rational64u', + WriteGroup => 'IFD0', + Count => 2, + Protected => 1, + }, + 0xc7a1 => { #28 + Name => 'CameraLabel', + Writable => 'string', + WriteGroup => 'IFD0', + }, + 0xc7a3 => { # DNG 1.4 + Name => 'ProfileHueSatMapEncoding', + Writable => 'int32u', + WriteGroup => 'IFD0', + Protected => 1, + PrintConv => { + 0 => 'Linear', + 1 => 'sRGB', + }, + }, + 0xc7a4 => { # DNG 1.4 + Name => 'ProfileLookTableEncoding', + Writable => 'int32u', + WriteGroup => 'IFD0', + Protected => 1, + PrintConv => { + 0 => 'Linear', + 1 => 'sRGB', + }, + }, + 0xc7a5 => { # DNG 1.4 + Name => 'BaselineExposureOffset', + Writable => 'rational64s', # (incorrectly "RATIONAL" in DNG 1.4 spec) + WriteGroup => 'IFD0', + Protected => 1, + }, + 0xc7a6 => { # DNG 1.4 + Name => 'DefaultBlackRender', + Writable => 'int32u', + WriteGroup => 'IFD0', + Protected => 1, + PrintConv => { + 0 => 'Auto', + 1 => 'None', + }, + }, + 0xc7a7 => { # DNG 1.4 + Name => 'NewRawImageDigest', + Format => 'undef', + Writable => 'int8u', + WriteGroup => 'IFD0', + Count => 16, + Protected => 1, + ValueConv => 'unpack("H*", $val)', + ValueConvInv => 'pack("H*", $val)', + }, + 0xc7a8 => { # DNG 1.4 + Name => 'RawToPreviewGain', + Writable => 'double', + WriteGroup => 'IFD0', + Protected => 1, + }, + # 0xc7a9 - CacheBlob (ref 31) + 0xc7aa => { #31 undocumented DNG tag written by LR4 (val=256, related to fast load data?) + Name => 'CacheVersion', + Writable => 'int32u', + WriteGroup => 'SubIFD2', + Format => 'int8u', + Count => 4, + Protected => 1, + PrintConv => '$val =~ tr/ /./; $val', + PrintConvInv => '$val =~ tr/./ /; $val', + }, + 0xc7b5 => { # DNG 1.4 + Name => 'DefaultUserCrop', + Writable => 'rational64u', + WriteGroup => 'SubIFD', + Count => 4, + Protected => 1, + }, + 0xc7d5 => { #PH (in SubIFD1 of Nikon Z6/Z7 NEF images) + Name => 'NikonNEFInfo', + Condition => '$$valPt =~ /^Nikon\0/', + SubDirectory => { + TagTable => 'Image::ExifTool::Nikon::NEFInfo', + Start => '$valuePtr + 18', + Base => '$start - 8', + ByteOrder => 'Unknown', + }, + }, + # 0xc7d6 - int8u: 1 (SubIFD1 of Nikon Z6/Z7 NEF) + 0xea1c => { #13 + Name => 'Padding', + Binary => 1, + Protected => 1, + Writable => 'undef', + # must start with 0x1c 0xea by the WM Photo specification + # (not sure what should happen if padding is only 1 byte) + # (why does MicrosoftPhoto write "1c ea 00 00 00 08"?) + RawConvInv => '$val=~s/^../\x1c\xea/s; $val', + }, + 0xea1d => { + Name => 'OffsetSchema', + Notes => "Microsoft's ill-conceived maker note offset difference", + Protected => 1, + Writable => 'int32s', + # From the Microsoft documentation: + # + # Any time the "Maker Note" is relocated by Windows, the Exif MakerNote + # tag (37500) is updated automatically to reference the new location. In + # addition, Windows records the offset (or difference) between the old and + # new locations in the Exif OffsetSchema tag (59933). If the "Maker Note" + # contains relative references, the developer can add the value in + # OffsetSchema to the original references to find the correct information. + # + # My recommendation is for other developers to ignore this tag because the + # information it contains is unreliable. It will be wrong if the image has + # been subsequently edited by another application that doesn't recognize the + # new Microsoft tag. + # + # The new tag unfortunately only gives the difference between the new maker + # note offset and the original offset. Instead, it should have been designed + # to store the original offset. The new offset may change if the image is + # edited, which will invalidate the tag as currently written. If instead the + # original offset had been stored, the new difference could be easily + # calculated because the new maker note offset is known. + # + # I exchanged emails with a Microsoft technical representative, pointing out + # this problem shortly after they released the update (Feb 2007), but so far + # they have taken no steps to address this. + }, + # 0xefee - int16u: 0 - seen this from a WIC-scanned image + + # tags in the range 0xfde8-0xfe58 have been observed in PS7 files + # generated from RAW images. They are all strings with the + # tag name at the start of the string. To accomodate these types + # of tags, all tags with values above 0xf000 are handled specially + # by ProcessExif(). + 0xfde8 => { + Name => 'OwnerName', + Condition => '$$self{TIFF_TYPE} ne "DCR"', # (used for another purpose in Kodak DCR images) + Avoid => 1, + PSRaw => 1, + Writable => 'string', + ValueConv => '$val=~s/^.*: //;$val', + ValueConvInv => q{"Owner's Name: $val"}, + Notes => q{ + tags 0xfde8-0xfdea and 0xfe4c-0xfe58 are generated by Photoshop Camera RAW. + Some names are the same as other EXIF tags, but ExifTool will avoid writing + these unless they already exist in the file + }, + }, + 0xfde9 => { + Name => 'SerialNumber', + Condition => '$$self{TIFF_TYPE} ne "DCR"', # (used for another purpose in Kodak DCR SubIFD) + Avoid => 1, + PSRaw => 1, + Writable => 'string', + ValueConv => '$val=~s/^.*: //;$val', + ValueConvInv => q{"Serial Number: $val"}, + }, + 0xfdea => { + Name => 'Lens', + Condition => '$$self{TIFF_TYPE} ne "DCR"', # (used for another purpose in Kodak DCR SubIFD) + Avoid => 1, + PSRaw => 1, + Writable => 'string', + ValueConv => '$val=~s/^.*: //;$val', + ValueConvInv => q{"Lens: $val"}, + }, + 0xfe4c => { + Name => 'RawFile', + Avoid => 1, + PSRaw => 1, + Writable => 'string', + ValueConv => '$val=~s/^.*: //;$val', + ValueConvInv => q{"Raw File: $val"}, + }, + 0xfe4d => { + Name => 'Converter', + Avoid => 1, + PSRaw => 1, + Writable => 'string', + ValueConv => '$val=~s/^.*: //;$val', + ValueConvInv => q{"Converter: $val"}, + }, + 0xfe4e => { + Name => 'WhiteBalance', + Avoid => 1, + PSRaw => 1, + Writable => 'string', + ValueConv => '$val=~s/^.*: //;$val', + ValueConvInv => q{"White Balance: $val"}, + }, + 0xfe51 => { + Name => 'Exposure', + Avoid => 1, + PSRaw => 1, + Writable => 'string', + ValueConv => '$val=~s/^.*: //;$val', + ValueConvInv => q{"Exposure: $val"}, + }, + 0xfe52 => { + Name => 'Shadows', + Avoid => 1, + PSRaw => 1, + Writable => 'string', + ValueConv => '$val=~s/^.*: //;$val', + ValueConvInv => q{"Shadows: $val"}, + }, + 0xfe53 => { + Name => 'Brightness', + Avoid => 1, + PSRaw => 1, + Writable => 'string', + ValueConv => '$val=~s/^.*: //;$val', + ValueConvInv => q{"Brightness: $val"}, + }, + 0xfe54 => { + Name => 'Contrast', + Avoid => 1, + PSRaw => 1, + Writable => 'string', + ValueConv => '$val=~s/^.*: //;$val', + ValueConvInv => q{"Contrast: $val"}, + }, + 0xfe55 => { + Name => 'Saturation', + Avoid => 1, + PSRaw => 1, + Writable => 'string', + ValueConv => '$val=~s/^.*: //;$val', + ValueConvInv => q{"Saturation: $val"}, + }, + 0xfe56 => { + Name => 'Sharpness', + Avoid => 1, + PSRaw => 1, + Writable => 'string', + ValueConv => '$val=~s/^.*: //;$val', + ValueConvInv => q{"Sharpness: $val"}, + }, + 0xfe57 => { + Name => 'Smoothness', + Avoid => 1, + PSRaw => 1, + Writable => 'string', + ValueConv => '$val=~s/^.*: //;$val', + ValueConvInv => q{"Smoothness: $val"}, + }, + 0xfe58 => { + Name => 'MoireFilter', + Avoid => 1, + PSRaw => 1, + Writable => 'string', + ValueConv => '$val=~s/^.*: //;$val', + ValueConvInv => q{"Moire Filter: $val"}, + }, + + #------------- + 0xfe00 => { + Name => 'KDC_IFD', + Groups => { 1 => 'KDC_IFD' }, + Flags => 'SubIFD', + Notes => 'used in some Kodak KDC images', + SubDirectory => { + TagTable => 'Image::ExifTool::Kodak::KDC_IFD', + DirName => 'KDC_IFD', + Start => '$val', + }, + }, +); + +# conversions for Composite SubSec date/time tags +my %subSecConv = ( + # @val array: 0) date/time, 1) sub-seconds, 2) time zone offset + RawConv => q{ + my $v; + if (defined $val[1] and $val[1]=~/^(\d+)/) { + my $subSec = $1; + # be careful here just in case the time already contains a timezone (contrary to spec) + undef $v unless ($v = $val[0]) =~ s/( \d{2}:\d{2}:\d{2})/$1\.$subSec/; + } + if (defined $val[2] and $val[0]!~/[-+]/ and $val[2]=~/^([-+])(\d{1,2}):(\d{2})/) { + $v = ($v || $val[0]) . sprintf('%s%.2d:%.2d', $1, $2, $3); + } + return $v; + }, + PrintConv => '$self->ConvertDateTime($val)', + PrintConvInv => '$self->InverseDateTime($val)', +); + +# EXIF Composite tags (plus other more general Composite tags) +%Image::ExifTool::Exif::Composite = ( + GROUPS => { 2 => 'Image' }, + ImageSize => { + Require => { + 0 => 'ImageWidth', + 1 => 'ImageHeight', + }, + Desire => { + 2 => 'ExifImageWidth', + 3 => 'ExifImageHeight', + }, + # use ExifImageWidth/Height only for Canon and Phase One TIFF-base RAW images + ValueConv => q{ + return "$val[2]x$val[3]" if $val[2] and $val[3] and + $$self{TIFF_TYPE} =~ /^(CR2|Canon 1D RAW|IIQ|EIP)$/; + return "$val[0]x$val[1]" if IsFloat($val[0]) and IsFloat($val[1]); + return undef; + }, + }, + Megapixels => { + Require => 'ImageSize', + ValueConv => 'my @d = ($val =~ /\d+/g); $d[0] * $d[1] / 1000000', + PrintConv => 'sprintf("%.*f", ($val >= 1 ? 1 : ($val >= 0.001 ? 3 : 6)), $val)', + }, + # pick the best shutter speed value + ShutterSpeed => { + Desire => { + 0 => 'ExposureTime', + 1 => 'ShutterSpeedValue', + 2 => 'BulbDuration', + }, + ValueConv => '($val[2] and $val[2]>0) ? $val[2] : (defined($val[0]) ? $val[0] : $val[1])', + PrintConv => 'Image::ExifTool::Exif::PrintExposureTime($val)', + }, + Aperture => { + Desire => { + 0 => 'FNumber', + 1 => 'ApertureValue', + }, + RawConv => '($val[0] || $val[1]) ? $val : undef', + ValueConv => '$val[0] || $val[1]', + PrintConv => 'Image::ExifTool::Exif::PrintFNumber($val)', + }, + LightValue => { + Notes => q{ + calculated LV = 2 * log2(Aperture) - log2(ShutterSpeed) - log2(ISO/100); + similar to exposure value but normalized to ISO 100 + }, + Require => { + 0 => 'Aperture', + 1 => 'ShutterSpeed', + 2 => 'ISO', + }, + ValueConv => 'Image::ExifTool::Exif::CalculateLV($val[0],$val[1],$prt[2])', + PrintConv => 'sprintf("%.1f",$val)', + }, + FocalLength35efl => { #26/PH + Description => 'Focal Length', + Notes => 'this value may be incorrect if the image has been resized', + Groups => { 2 => 'Camera' }, + Require => { + 0 => 'FocalLength', + }, + Desire => { + 1 => 'ScaleFactor35efl', + }, + ValueConv => 'ToFloat(@val); ($val[0] || 0) * ($val[1] || 1)', + PrintConv => '$val[1] ? sprintf("%.1f mm (35 mm equivalent: %.1f mm)", $val[0], $val) : sprintf("%.1f mm", $val)', + }, + ScaleFactor35efl => { #26/PH + Description => 'Scale Factor To 35 mm Equivalent', + Notes => q{ + this value and any derived values may be incorrect if the image has been + resized + }, + Groups => { 2 => 'Camera' }, + Desire => { + 0 => 'FocalLength', + 1 => 'FocalLengthIn35mmFormat', + 2 => 'Composite:DigitalZoom', + 3 => 'FocalPlaneDiagonal', + 4 => 'SensorSize', + 5 => 'FocalPlaneXSize', + 6 => 'FocalPlaneYSize', + 7 => 'FocalPlaneResolutionUnit', + 8 => 'FocalPlaneXResolution', + 9 => 'FocalPlaneYResolution', + 10 => 'ExifImageWidth', + 11 => 'ExifImageHeight', + 12 => 'CanonImageWidth', + 13 => 'CanonImageHeight', + 14 => 'ImageWidth', + 15 => 'ImageHeight', + }, + ValueConv => 'Image::ExifTool::Exif::CalcScaleFactor35efl($self, @val)', + PrintConv => 'sprintf("%.1f", $val)', + }, + CircleOfConfusion => { + Notes => q{ + calculated as D/1440, where D is the focal plane diagonal in mm. This value + may be incorrect if the image has been resized + }, + Groups => { 2 => 'Camera' }, + Require => 'ScaleFactor35efl', + ValueConv => 'sqrt(24*24+36*36) / ($val * 1440)', + PrintConv => 'sprintf("%.3f mm",$val)', + }, + HyperfocalDistance => { + Notes => 'this value may be incorrect if the image has been resized', + Groups => { 2 => 'Camera' }, + Require => { + 0 => 'FocalLength', + 1 => 'Aperture', + 2 => 'CircleOfConfusion', + }, + ValueConv => q{ + ToFloat(@val); + return 'inf' unless $val[1] and $val[2]; + return $val[0] * $val[0] / ($val[1] * $val[2] * 1000); + }, + PrintConv => 'sprintf("%.2f m", $val)', + }, + DOF => { + Description => 'Depth Of Field', + Notes => 'this value may be incorrect if the image has been resized', + Require => { + 0 => 'FocalLength', + 1 => 'Aperture', + 2 => 'CircleOfConfusion', + }, + Desire => { + 3 => 'FocusDistance', # focus distance in metres (0 is infinity) + 4 => 'SubjectDistance', + 5 => 'ObjectDistance', + 6 => 'ApproximateFocusDistance', + 7 => 'FocusDistanceLower', + 8 => 'FocusDistanceUpper', + }, + ValueConv => q{ + ToFloat(@val); + my ($d, $f) = ($val[3], $val[0]); + if (defined $d) { + $d or $d = 1e10; # (use large number for infinity) + } else { + $d = $val[4] || $val[5] || $val[6]; + unless (defined $d) { + return undef unless defined $val[7] and defined $val[8]; + $d = ($val[7] + $val[8]) / 2; + } + } + return 0 unless $f and $val[2]; + my $t = $val[1] * $val[2] * ($d * 1000 - $f) / ($f * $f); + my @v = ($d / (1 + $t), $d / (1 - $t)); + $v[1] < 0 and $v[1] = 0; # 0 means 'inf' + return join(' ',@v); + }, + PrintConv => q{ + $val =~ tr/,/./; # in case locale is whacky + my @v = split ' ', $val; + $v[1] or return sprintf("inf (%.2f m - inf)", $v[0]); + my $dof = $v[1] - $v[0]; + my $fmt = ($dof>0 and $dof<0.02) ? "%.3f" : "%.2f"; + return sprintf("$fmt m ($fmt - $fmt m)",$dof,$v[0],$v[1]); + }, + }, + FOV => { + Description => 'Field Of View', + Notes => q{ + calculated for the long image dimension. This value may be incorrect for + fisheye lenses, or if the image has been resized + }, + Require => { + 0 => 'FocalLength', + 1 => 'ScaleFactor35efl', + }, + Desire => { + 2 => 'FocusDistance', # (multiply by 1000 to convert to mm) + }, + # ref http://www.bobatkins.com/photography/technical/field_of_view.html + # (calculations below apply to rectilinear lenses only, not fisheye) + ValueConv => q{ + ToFloat(@val); + return undef unless $val[0] and $val[1]; + my $corr = 1; + if ($val[2]) { + my $d = 1000 * $val[2] - $val[0]; + $corr += $val[0]/$d if $d > 0; + } + my $fd2 = atan2(36, 2*$val[0]*$val[1]*$corr); + my @fov = ( $fd2 * 360 / 3.14159 ); + if ($val[2] and $val[2] > 0 and $val[2] < 10000) { + push @fov, 2 * $val[2] * sin($fd2) / cos($fd2); + } + return join(' ', @fov); + }, + PrintConv => q{ + my @v = split(' ',$val); + my $str = sprintf("%.1f deg", $v[0]); + $str .= sprintf(" (%.2f m)", $v[1]) if $v[1]; + return $str; + }, + }, + # generate DateTimeOriginal from Date and Time Created if not extracted already + DateTimeOriginal => { + Condition => 'not defined $$self{VALUE}{DateTimeOriginal}', + Description => 'Date/Time Original', + Groups => { 2 => 'Time' }, + Desire => { + 0 => 'DateTimeCreated', + 1 => 'DateCreated', + 2 => 'TimeCreated', + }, + RawConv => '($val[1] and $val[2]) ? $val : undef', + ValueConv => q{ + return $val[0] if $val[0] and $val[0]=~/ /; + return "$val[1] $val[2]"; + }, + PrintConv => '$self->ConvertDateTime($val)', + }, + ThumbnailImage => { + Groups => { 0 => 'EXIF', 1 => 'IFD1', 2 => 'Preview' }, + Writable => 1, + WriteGroup => 'All', + WriteCheck => '$self->CheckImage(\$val)', + WriteAlso => { + # (the 0xfeedfeed values are translated in the Exif write routine) + ThumbnailOffset => 'defined $val ? 0xfeedfeed : undef', + ThumbnailLength => 'defined $val ? 0xfeedfeed : undef', + }, + Require => { + 0 => 'ThumbnailOffset', + 1 => 'ThumbnailLength', + }, + Notes => q{ + this tag is writable, and may be used to update existing thumbnails, but may + only create a thumbnail in IFD1 of certain types of files. Note that for + this and other Composite embedded-image tags the family 0 and 1 groups match + those of the originating tags + }, + # retrieve the thumbnail from our EXIF data + RawConv => q{ + @grps = $self->GetGroup($$val{0}); # set groups from ThumbnailOffsets + Image::ExifTool::Exif::ExtractImage($self,$val[0],$val[1],"ThumbnailImage"); + }, + }, + ThumbnailTIFF => { + Groups => { 2 => 'Preview' }, + Require => { + 0 => 'SubfileType', + 1 => 'Compression', + 2 => 'ImageWidth', + 3 => 'ImageHeight', + 4 => 'BitsPerSample', + 5 => 'PhotometricInterpretation', + 6 => 'StripOffsets', + 7 => 'SamplesPerPixel', + 8 => 'RowsPerStrip', + 9 => 'StripByteCounts', + }, + Desire => { + 10 => 'PlanarConfiguration', + 11 => 'Orientation', + }, + # rebuild the TIFF thumbnail from our EXIF data + RawConv => q{ + my $tiff; + ($tiff, @grps) = Image::ExifTool::Exif::RebuildTIFF($self, @val); + return $tiff; + }, + }, + PreviewImage => { + Groups => { 0 => 'EXIF', 1 => 'SubIFD', 2 => 'Preview' }, + Writable => 1, + WriteGroup => 'All', + WriteCheck => '$self->CheckImage(\$val)', + DelCheck => '$val = ""; return undef', # can't delete, so set to empty string + WriteAlso => { + PreviewImageStart => 'defined $val ? 0xfeedfeed : undef', + PreviewImageLength => 'defined $val ? 0xfeedfeed : undef', + PreviewImageValid => 'defined $val and length $val ? 1 : 0', # (for Olympus) + }, + Require => { + 0 => 'PreviewImageStart', + 1 => 'PreviewImageLength', + }, + Desire => { + 2 => 'PreviewImageValid', + # (DNG and A100 ARW may be have 2 preview images) + 3 => 'PreviewImageStart (1)', + 4 => 'PreviewImageLength (1)', + }, + Notes => q{ + this tag is writable, and may be used to update existing embedded images, + but not create or delete them + }, + # note: extract 2nd preview, but ignore double-referenced preview + # (in A100 ARW images, the 2nd PreviewImageLength from IFD0 may be wrong anyway) + RawConv => q{ + if ($val[3] and $val[4] and $val[0] ne $val[3]) { + my %val = ( + 0 => 'PreviewImageStart (1)', + 1 => 'PreviewImageLength (1)', + 2 => 'PreviewImageValid', + ); + $self->FoundTag($tagInfo, \%val); + } + return undef if defined $val[2] and not $val[2]; + @grps = $self->GetGroup($$val{0}); + return Image::ExifTool::Exif::ExtractImage($self,$val[0],$val[1],'PreviewImage'); + }, + }, + JpgFromRaw => { + Groups => { 0 => 'EXIF', 1 => 'SubIFD', 2 => 'Preview' }, + Writable => 1, + WriteGroup => 'All', + WriteCheck => '$self->CheckImage(\$val)', + # Note: ExifTool 10.38 had disabled the ability to delete this -- why? + # --> added the DelCheck in 10.61 to re-enable this + DelCheck => '$val = ""; return undef', # can't delete, so set to empty string + WriteAlso => { + JpgFromRawStart => 'defined $val ? 0xfeedfeed : undef', + JpgFromRawLength => 'defined $val ? 0xfeedfeed : undef', + }, + Require => { + 0 => 'JpgFromRawStart', + 1 => 'JpgFromRawLength', + }, + Notes => q{ + this tag is writable, and may be used to update existing embedded images, + but not create or delete them + }, + RawConv => q{ + @grps = $self->GetGroup($$val{0}); + return Image::ExifTool::Exif::ExtractImage($self,$val[0],$val[1],"JpgFromRaw"); + }, + }, + OtherImage => { + Groups => { 0 => 'EXIF', 1 => 'SubIFD', 2 => 'Preview' }, + Writable => 1, + WriteGroup => 'All', + WriteCheck => '$self->CheckImage(\$val)', + DelCheck => '$val = ""; return undef', # can't delete, so set to empty string + WriteAlso => { + OtherImageStart => 'defined $val ? 0xfeedfeed : undef', + OtherImageLength => 'defined $val ? 0xfeedfeed : undef', + }, + Require => { + 0 => 'OtherImageStart', + 1 => 'OtherImageLength', + }, + Notes => q{ + this tag is writable, and may be used to update existing embedded images, + but not create or delete them + }, + # retrieve the thumbnail from our EXIF data + RawConv => q{ + @grps = $self->GetGroup($$val{0}); + Image::ExifTool::Exif::ExtractImage($self,$val[0],$val[1],"OtherImage"); + }, + }, + PreviewImageSize => { + Require => { + 0 => 'PreviewImageWidth', + 1 => 'PreviewImageHeight', + }, + ValueConv => '"$val[0]x$val[1]"', + }, + SubSecDateTimeOriginal => { + Description => 'Date/Time Original', + Groups => { 2 => 'Time' }, + Writable => 1, + Shift => 0, # don't shift this tag + Require => { + 0 => 'EXIF:DateTimeOriginal', + }, + Desire => { + 1 => 'SubSecTimeOriginal', + 2 => 'OffsetTimeOriginal', + }, + WriteAlso => { + 'EXIF:DateTimeOriginal' => '($val and $val=~/^(\d{4}:\d{2}:\d{2} \d{2}:\d{2}:\d{2})/) ? $1 : undef', + 'EXIF:SubSecTimeOriginal' => '($val and $val=~/\.(\d+)/) ? $1 : undef', + 'EXIF:OffsetTimeOriginal' => '($val and $val=~/([-+]\d{2}:\d{2}|Z)$/) ? ($1 eq "Z" ? "+00:00" : $1) : undef', + }, + %subSecConv, + }, + SubSecCreateDate => { + Description => 'Create Date', + Groups => { 2 => 'Time' }, + Writable => 1, + Shift => 0, # don't shift this tag + Require => { + 0 => 'EXIF:CreateDate', + }, + Desire => { + 1 => 'SubSecTimeDigitized', + 2 => 'OffsetTimeDigitized', + }, + WriteAlso => { + 'EXIF:CreateDate' => '($val and $val=~/^(\d{4}:\d{2}:\d{2} \d{2}:\d{2}:\d{2})/) ? $1 : undef', + 'EXIF:SubSecTimeDigitized' => '($val and $val=~/\.(\d+)/) ? $1 : undef', + 'EXIF:OffsetTimeDigitized' => '($val and $val=~/([-+]\d{2}:\d{2}|Z)$/) ? ($1 eq "Z" ? "+00:00" : $1) : undef', + }, + %subSecConv, + }, + SubSecModifyDate => { + Description => 'Modify Date', + Groups => { 2 => 'Time' }, + Writable => 1, + Shift => 0, # don't shift this tag + Require => { + 0 => 'EXIF:ModifyDate', + }, + Desire => { + 1 => 'SubSecTime', + 2 => 'OffsetTime', + }, + WriteAlso => { + 'EXIF:ModifyDate' => '($val and $val=~/^(\d{4}:\d{2}:\d{2} \d{2}:\d{2}:\d{2})/) ? $1 : undef', + 'EXIF:SubSecTime' => '($val and $val=~/\.(\d+)/) ? $1 : undef', + 'EXIF:OffsetTime' => '($val and $val=~/([-+]\d{2}:\d{2}|Z)$/) ? ($1 eq "Z" ? "+00:00" : $1) : undef', + }, + %subSecConv, + }, + CFAPattern => { + Require => { + 0 => 'CFARepeatPatternDim', + 1 => 'CFAPattern2', + }, + # generate CFAPattern + ValueConv => q{ + my @a = split / /, $val[0]; + my @b = split / /, $val[1]; + return '?' unless @a==2 and @b==$a[0]*$a[1]; + return "$a[0] $a[1] @b"; + }, + PrintConv => 'Image::ExifTool::Exif::PrintCFAPattern($val)', + }, + RedBalance => { + Groups => { 2 => 'Camera' }, + Desire => { + 0 => 'WB_RGGBLevels', + 1 => 'WB_RGBGLevels', + 2 => 'WB_RBGGLevels', + 3 => 'WB_GRBGLevels', + 4 => 'WB_GRGBLevels', + 5 => 'WB_GBRGLevels', + 6 => 'WB_RGBLevels', + 7 => 'WB_GRBLevels', + 8 => 'WB_RBLevels', + 9 => 'WBRedLevel', # red + 10 => 'WBGreenLevel', + }, + ValueConv => 'Image::ExifTool::Exif::RedBlueBalance(0,@val)', + PrintConv => 'int($val * 1e6 + 0.5) * 1e-6', + }, + BlueBalance => { + Groups => { 2 => 'Camera' }, + Desire => { + 0 => 'WB_RGGBLevels', + 1 => 'WB_RGBGLevels', + 2 => 'WB_RBGGLevels', + 3 => 'WB_GRBGLevels', + 4 => 'WB_GRGBLevels', + 5 => 'WB_GBRGLevels', + 6 => 'WB_RGBLevels', + 7 => 'WB_GRBLevels', + 8 => 'WB_RBLevels', + 9 => 'WBBlueLevel', # blue + 10 => 'WBGreenLevel', + }, + ValueConv => 'Image::ExifTool::Exif::RedBlueBalance(1,@val)', + PrintConv => 'int($val * 1e6 + 0.5) * 1e-6', + }, + GPSPosition => { + Groups => { 2 => 'Location' }, + Require => { + 0 => 'GPSLatitude', + 1 => 'GPSLongitude', + }, + Priority => 0, + ValueConv => '(length($val[0]) or length($val[1])) ? "$val[0] $val[1]" : undef', + PrintConv => '"$prt[0], $prt[1]"', + }, + LensID => { + Groups => { 2 => 'Camera' }, + Require => 'LensType', + Desire => { + 1 => 'FocalLength', + 2 => 'MaxAperture', + 3 => 'MaxApertureValue', + 4 => 'MinFocalLength', + 5 => 'MaxFocalLength', + 6 => 'LensModel', + 7 => 'LensFocalRange', + 8 => 'LensSpec', + 9 => 'LensType2', + 10 => 'LensFocalLength', # (for Pentax to check for converter) + }, + Notes => q{ + attempt to identify the actual lens from all lenses with a given LensType. + Applies only to LensType values with a lookup table. May be configured + by adding user-defined lenses + }, + # this LensID is only valid if the LensType has a PrintConv or is a model name + RawConv => q{ + my $printConv = $$self{TAG_INFO}{LensType}{PrintConv}; + return $val if ref $printConv eq 'HASH' or (ref $printConv eq 'ARRAY' and + ref $$printConv[0] eq 'HASH') or $val[0] =~ /(mm|\d\/F)/; + return undef; + }, + ValueConv => '$val', + PrintConv => q{ + my $pcv; + # use LensType2 instead of LensType if available and valid (Sony E-mount lenses) + if ($val[9] and $val[9] & 0x8000) { + $val[0] = $val[9]; + $prt[0] = $prt[9]; + $pcv = $$self{TAG_INFO}{LensType2}{PrintConv}; + } + my $lens = Image::ExifTool::Exif::PrintLensID($self, $prt[0], $pcv, $prt[8], @val); + # check for use of lens converter (Pentax K-3) + if ($val[10] and $val[1] and $lens) { + my $conv = $val[1] / $val[10]; + $lens .= sprintf(' + %.1fx converter', $conv) if $conv > 1.1; + } + return $lens; + }, + }, +); + +# table for unknown IFD entries +%Image::ExifTool::Exif::Unknown = ( + GROUPS => { 0 => 'EXIF', 1 => 'UnknownIFD', 2 => 'Image'}, + WRITE_PROC => \&WriteExif, +); + +# add our composite tags +Image::ExifTool::AddCompositeTags('Image::ExifTool::Exif'); + + +#------------------------------------------------------------------------------ +# AutoLoad our writer routines when necessary +# +sub AUTOLOAD +{ + return Image::ExifTool::DoAutoLoad($AUTOLOAD, @_); +} + +#------------------------------------------------------------------------------ +# Identify RAW file type for some TIFF-based formats using Compression value +# Inputs: 0) ExifTool object reference, 1) Compression value +# - sets TIFF_TYPE and FileType if identified +sub IdentifyRawFile($$) +{ + my ($et, $comp) = @_; + if ($$et{FILE_TYPE} eq 'TIFF' and not $$et{IdentifiedRawFile}) { + if ($compression{$comp} and $compression{$comp} =~ /^\w+ ([A-Z]{3}) Compressed$/) { + $et->OverrideFileType($$et{TIFF_TYPE} = $1); + $$et{IdentifiedRawFile} = 1; + } + } +} + +#------------------------------------------------------------------------------ +# Calculate LV (Light Value) +# Inputs: 0) Aperture, 1) ShutterSpeed, 2) ISO +# Returns: LV value (and converts input values to floating point if necessary) +sub CalculateLV($$$) +{ + local $_; + # do validity checks on arguments + return undef unless @_ >= 3; + foreach (@_) { + return undef unless $_ and /([+-]?(?=\d|\.\d)\d*(\.\d*)?([Ee]([+-]?\d+))?)/ and $1 > 0; + $_ = $1; # extract float from any other garbage + } + # (A light value of 0 is defined as f/1.0 at 1 second with ISO 100) + return log($_[0] * $_[0] * 100 / ($_[1] * $_[2])) / log(2); +} + +#------------------------------------------------------------------------------ +# Calculate scale factor for 35mm effective focal length (ref 26/PH) +# Inputs: 0) ExifTool object ref +# 1) Focal length +# 2) Focal length in 35mm format +# 3) Canon digital zoom factor +# 4) Focal plane diagonal size (in mm) +# 5) Sensor size (X and Y in mm) +# 6/7) Focal plane X/Y size (in mm) +# 8) focal plane resolution units (1=None,2=inches,3=cm,4=mm,5=um) +# 9/10) Focal plane X/Y resolution +# 11/12,13/14...) Image width/height in order of precedence (first valid pair is used) +# Returns: 35mm conversion factor (or undefined if it can't be calculated) +sub CalcScaleFactor35efl +{ + my $et = shift; + my $res = $_[7]; # save resolution units (in case they have been converted to string) + my $sensXY = $_[4]; + Image::ExifTool::ToFloat(@_); + my $focal = shift; + my $foc35 = shift; + + return $foc35 / $focal if $focal and $foc35; + + my $digz = shift || 1; + my $diag = shift; + my $sens = shift; + # calculate Canon sensor size using a dedicated algorithm + if ($$et{Make} eq 'Canon') { + require Image::ExifTool::Canon; + my $canonDiag = Image::ExifTool::Canon::CalcSensorDiag( + $$et{RATIONAL}{FocalPlaneXResolution}, + $$et{RATIONAL}{FocalPlaneYResolution}, + ); + $diag = $canonDiag if $canonDiag; + } + unless ($diag and Image::ExifTool::IsFloat($diag)) { + if ($sens and $sensXY =~ / (\d+(\.?\d*)?)$/) { + $diag = sqrt($sens * $sens + $1 * $1); + } else { + undef $diag; + my $xsize = shift; + my $ysize = shift; + if ($xsize and $ysize) { + # validate by checking aspect ratio because FocalPlaneX/YSize is not reliable + my $a = $xsize / $ysize; + if (abs($a-1.3333) < .1 or abs($a-1.5) < .1) { + $diag = sqrt($xsize * $xsize + $ysize * $ysize); + } + } + } + unless ($diag) { + # get number of mm in units (assume inches unless otherwise specified) + my %lkup = ( 3=>10, 4=>1, 5=>0.001 , cm=>10, mm=>1, um=>0.001 ); + my $units = $lkup{ shift() || $res || '' } || 25.4; + my $x_res = shift || return undef; + my $y_res = shift || $x_res; + Image::ExifTool::IsFloat($x_res) and $x_res != 0 or return undef; + Image::ExifTool::IsFloat($y_res) and $y_res != 0 or return undef; + my ($w, $h); + for (;;) { + @_ < 2 and return undef; + $w = shift; + $h = shift; + next unless $w and $h; + my $a = $w / $h; + last if $a > 0.5 and $a < 2; # stop if we get a reasonable value + } + # calculate focal plane size in mm + $w *= $units / $x_res; + $h *= $units / $y_res; + $diag = sqrt($w*$w+$h*$h); + # make sure size is reasonable + return undef unless $diag > 1 and $diag < 100; + } + } + return sqrt(36*36+24*24) * $digz / $diag; +} + +#------------------------------------------------------------------------------ +# Print exposure compensation fraction +sub PrintFraction($) +{ + my $val = shift; + my $str; + if (defined $val) { + $val *= 1.00001; # avoid round-off errors + if (not $val) { + $str = '0'; + } elsif (int($val)/$val > 0.999) { + $str = sprintf("%+d", int($val)); + } elsif ((int($val*2))/($val*2) > 0.999) { + $str = sprintf("%+d/2", int($val * 2)); + } elsif ((int($val*3))/($val*3) > 0.999) { + $str = sprintf("%+d/3", int($val * 3)); + } else { + $str = sprintf("%+.3g", $val); + } + } + return $str; +} + +#------------------------------------------------------------------------------ +# Convert fraction or number to floating point value (or 'undef' or 'inf') +sub ConvertFraction($) +{ + my $val = shift; + if ($val =~ m{([-+]?\d+)/(\d+)}) { + $val = $2 ? $1 / $2 : ($1 ? 'inf' : 'undef'); + } + return $val; +} + +#------------------------------------------------------------------------------ +# Convert EXIF text to something readable +# Inputs: 0) ExifTool object reference, 1) EXIF text, +# 2) [optional] 1 to apply CharsetEXIF to ASCII text, +# 3) tag name for warning message (may be argument 2) +# Returns: text encoded according to Charset option (with trailing spaces removed) +sub ConvertExifText($$;$$) +{ + my ($et, $val, $asciiFlex, $tag) = @_; + return $val if length($val) < 8; + my $id = substr($val, 0, 8); + my $str = substr($val, 8); + my $type; + + delete $$et{WrongByteOrder}; + if ($$et{OPTIONS}{Validate} and $id =~ /^(ASCII|UNICODE|JIS)?\0* \0*$/) { + $et->Warn(($1 || 'Undefined') . ' text header' . ($tag ? " for $tag" : '') . ' has spaces instead of nulls'); + } + # Note: allow spaces instead of nulls in the ID codes because + # it is fairly common for camera manufacturers to get this wrong + # (also handle Canon ZoomBrowser EX 4.5 null followed by 7 bytes of garbage) + if ($id =~ /^(ASCII)?(\0|[\0 ]+$)/) { + # truncate at null terminator (shouldn't have a null based on the + # EXIF spec, but it seems that few people actually read the spec) + $str =~ s/\0.*//s; + # allow ASCII text to contain any other specified encoding + if ($asciiFlex and $asciiFlex eq '1') { + my $enc = $et->Options('CharsetEXIF'); + $str = $et->Decode($str, $enc) if $enc; + } + # by the EXIF spec, the following string should be "UNICODE\0", but + # apparently Kodak sometimes uses "Unicode\0" in the APP3 "Meta" information. + # However, unfortunately Ricoh uses "Unicode\0" in the RR30 EXIF UserComment + # when the text is actually ASCII, so only recognize uppercase "UNICODE\0". + } elsif ($id =~ /^(UNICODE)[\0 ]$/) { + $type = $1; + # MicrosoftPhoto writes as little-endian even in big-endian EXIF, + # so we must guess at the true byte ordering + $str = $et->Decode($str, 'UTF16', 'Unknown'); + } elsif ($id =~ /^(JIS)[\0 ]{5}$/) { + $type = $1; + $str = $et->Decode($str, 'JIS', 'Unknown'); + } else { + $tag = $asciiFlex if $asciiFlex and $asciiFlex ne 1; + $et->Warn('Invalid EXIF text encoding' . ($tag ? " for $tag" : '')); + $str = $id . $str; + } + if ($$et{WrongByteOrder} and $$et{OPTIONS}{Validate}) { + $et->Warn('Wrong byte order for EXIF' . ($tag ? " $tag" : '') . + ($type ? " $type" : '') . ' text'); + } + $str =~ s/ +$//; # trim trailing blanks + return $str; +} + +#------------------------------------------------------------------------------ +# Print conversion for SpatialFrequencyResponse +sub PrintSFR($) +{ + my $val = shift; + return $val unless length $val > 4; + my ($n, $m) = (Get16u(\$val, 0), Get16u(\$val, 2)); + my @cols = split /\0/, substr($val, 4), $n+1; + my $pos = length($val) - 8 * $n * $m; + return $val unless @cols == $n+1 and $pos >= 4; + pop @cols; + my ($i, $j); + for ($i=0; $i<$n; ++$i) { + my @rows; + for ($j=0; $j<$m; ++$j) { + push @rows, Image::ExifTool::GetRational64u(\$val, $pos + 8*($i+$j*$n)); + } + $cols[$i] .= '=' . join(',',@rows) . ''; + } + return join '; ', @cols; +} + +#------------------------------------------------------------------------------ +# Print numerical parameter value (with sign, or 'Normal' for zero) +# Inputs: 0) value, 1) flag for inverse conversion, 2) conversion hash reference +sub PrintParameter($$$) +{ + my ($val, $inv, $conv) = @_; + return $val if $inv; + if ($val > 0) { + if ($val > 0xfff0) { # a negative value in disguise? + $val = $val - 0x10000; + } else { + $val = "+$val"; + } + } + return $val; +} + +#------------------------------------------------------------------------------ +# Convert parameter back to standard EXIF value +# 0,0.00,etc or "Normal" => 0 +# -1,-2,etc or "Soft" or "Low" => 1 +# +1,+2,1,2,etc or "Hard" or "High" => 2 +sub ConvertParameter($) +{ + my $val = shift; + my $isFloat = Image::ExifTool::IsFloat($val); + # normal is a value of zero + return 0 if $val =~ /\bn/i or ($isFloat and $val == 0); + # "soft", "low" or any negative number is a value of 1 + return 1 if $val =~ /\b(s|l)/i or ($isFloat and $val < 0); + # "hard", "high" or any positive number is a value of 2 + return 2 if $val =~ /\bh/i or $isFloat; + return undef; +} + +#------------------------------------------------------------------------------ +# Calculate Red/BlueBalance +# Inputs: 0) 0=red, 1=blue, 1-8) WB_RGGB/RGBG/RBGG/GRBG/GRGB/RGB/GRB/RBLevels, +# 8) red or blue level, 9) green level +my @rggbLookup = ( + # indices for R, G, G and B components in input value + [ 0, 1, 2, 3 ], # 0 RGGB + [ 0, 1, 3, 2 ], # 1 RGBG + [ 0, 2, 3, 1 ], # 2 RBGG + [ 1, 0, 3, 2 ], # 3 GRBG + [ 1, 0, 2, 3 ], # 4 GRGB + [ 2, 3, 0, 1 ], # 5 GBRG + [ 0, 1, 1, 2 ], # 6 RGB + [ 1, 0, 0, 2 ], # 7 GRB + [ 0, 256, 256, 1 ], # 8 RB (green level is 256) +); +sub RedBlueBalance($@) +{ + my $blue = shift; + my ($i, $val, $levels); + for ($i=0; $i<@rggbLookup; ++$i) { + $levels = shift or next; + my @levels = split ' ', $levels; + next if @levels < 2; + my $lookup = $rggbLookup[$i]; + my $g = $$lookup[1]; # get green level or index + if ($g < 4) { + next if @levels < 3; + $g = ($levels[$g] + $levels[$$lookup[2]]) / 2 or next; + } elsif ($levels[$$lookup[$blue * 3]] < 4) { + $g = 1; # Some Nikon cameras use a scaling factor of 1 (E5700) + } + $val = $levels[$$lookup[$blue * 3]] / $g; + last; + } + $val = $_[0] / $_[1] if not defined $val and ($_[0] and $_[1]); + return $val; +} + +#------------------------------------------------------------------------------ +# Print exposure time as a fraction +sub PrintExposureTime($) +{ + my $secs = shift; + if ($secs < 0.25001 and $secs > 0) { + return sprintf("1/%d",int(0.5 + 1/$secs)); + } + $_ = sprintf("%.1f",$secs); + s/\.0$//; + return $_; +} + +#------------------------------------------------------------------------------ +# Print FNumber +sub PrintFNumber($) +{ + my $val = shift; + if (Image::ExifTool::IsFloat($val) and $val > 0) { + # round to 1 decimal place, or 2 for values < 1.0 + $val = sprintf(($val<1 ? "%.2f" : "%.1f"), $val); + } + return $val; +} + +#------------------------------------------------------------------------------ +# Decode raw CFAPattern value +# Inputs: 0) ExifTool ref, 1) binary value +# Returns: string of numbers +sub DecodeCFAPattern($$) +{ + my ($self, $val) = @_; + # some panasonic cameras (SV-AS3, SV-AS30) write this in ascii (very odd) + if ($val =~ /^[0-6]+$/) { + $self->Warn('Incorrectly formatted CFAPattern', 1); + $val =~ tr/0-6/\x00-\x06/; + } + return $val unless length($val) >= 4; + my @a = unpack(GetByteOrder() eq 'II' ? 'v2C*' : 'n2C*', $val); + my $end = 2 + $a[0] * $a[1]; + if ($end > @a) { + # try swapping byte order (I have seen this order different than in EXIF) + my ($x, $y) = unpack('n2',pack('v2',$a[0],$a[1])); + if (@a < 2 + $x * $y) { + $self->Warn('Invalid CFAPattern', 1); + } else { + ($a[0], $a[1]) = ($x, $y); + # (can't technically be wrong because the order isn't well defined by the EXIF spec) + # $self->Warn('Wrong byte order for CFAPattern'); + } + } + return "@a"; +} + +#------------------------------------------------------------------------------ +# Print CFA Pattern +sub PrintCFAPattern($) +{ + my $val = shift; + my @a = split ' ', $val; + return '<truncated data>' unless @a >= 2; + return '<zero pattern size>' unless $a[0] and $a[1]; + my $end = 2 + $a[0] * $a[1]; + return '<invalid pattern size>' if $end > @a; + my @cfaColor = qw(Red Green Blue Cyan Magenta Yellow White); + my ($pos, $rtnVal) = (2, '['); + for (;;) { + $rtnVal .= $cfaColor[$a[$pos]] || 'Unknown'; + last if ++$pos >= $end; + ($pos - 2) % $a[1] and $rtnVal .= ',', next; + $rtnVal .= ']['; + } + return $rtnVal . ']'; +} + +#------------------------------------------------------------------------------ +# Print conversion for lens info +# Inputs: 0) string of values (min focal, max focal, min F, max F) +# Returns: string in the form "12-20mm f/3.8-4.5" or "50mm f/1.4" +sub PrintLensInfo($) +{ + my $val = shift; + my @vals = split ' ', $val; + return $val unless @vals == 4; + my $c = 0; + foreach (@vals) { + Image::ExifTool::IsFloat($_) and ++$c, next; + $_ eq 'inf' and $_ = '?', ++$c, next; + $_ eq 'undef' and $_ = '?', ++$c, next; + } + return $val unless $c == 4; + $val = $vals[0]; + # (the Pentax Q writes zero for upper value of fixed-focal-length lenses) + $val .= "-$vals[1]" if $vals[1] and $vals[1] ne $vals[0]; + $val .= "mm f/$vals[2]"; + $val .= "-$vals[3]" if $vals[3] and $vals[3] ne $vals[2]; + return $val; +} + +#------------------------------------------------------------------------------ +# Get lens info from lens model string +# Inputs: 0) lens string, 1) flag to allow unknown "?" values +# Returns: 0) min focal, 1) max focal, 2) min aperture, 3) max aperture +# Notes: returns empty list if lens string could not be parsed +sub GetLensInfo($;$) +{ + my ($lens, $unk) = @_; + # extract focal length and aperture ranges for this lens + my $pat = '\\d+(?:\\.\\d+)?'; + $pat .= '|\\?' if $unk; + return () unless $lens =~ /($pat)(?:-($pat))?\s*mm.*?(?:[fF]\/?\s*)($pat)(?:-($pat))?/; + # ($1=short focal, $2=long focal, $3=max aperture wide, $4=max aperture tele) + my @a = ($1, $2, $3, $4); + $a[1] or $a[1] = $a[0]; + $a[3] or $a[3] = $a[2]; + if ($unk) { + local $_; + $_ eq '?' and $_ = 'undef' foreach @a; + } + return @a; +} + +#------------------------------------------------------------------------------ +# Attempt to identify the specific lens if multiple lenses have the same LensType +# Inputs: 0) ExifTool object ref, 1) LensType print value, 2) PrintConv hash ref, +# 3) LensSpec print value, 4) LensType numerical value, 5) FocalLength, +# 6) MaxAperture, 7) MaxApertureValue, 8) MinFocalLength, 9) MaxFocalLength, +# 10) LensModel, 11) LensFocalRange, 12) LensSpec +sub PrintLensID($$@) +{ + my ($et, $lensTypePrt, $printConv, $lensSpecPrt, $lensType, $focalLength, + $maxAperture, $maxApertureValue, $shortFocal, $longFocal, $lensModel, + $lensFocalRange, $lensSpec) = @_; + # this logic relies on the LensType lookup: + return undef unless defined $lensType; + # get print conversion hash if necessary + $printConv or $printConv = $$et{TAG_INFO}{LensType}{PrintConv}; + # just copy LensType PrintConv value if it was a lens name + # (Olympus or Panasonic -- just exclude things like Nikon and Leaf LensType) + unless (ref $printConv eq 'HASH') { + if (ref $printConv eq 'ARRAY' and ref $$printConv[0] eq 'HASH') { + $printConv = $$printConv[0]; + $lensTypePrt =~ s/;.*//; + $lensType =~ s/ .*//; + } else { + return $lensTypePrt if $lensTypePrt =~ /mm/; + return $lensTypePrt if $lensTypePrt =~ s/(\d)\/F/$1mm F/; + return undef; + } + } + # get LensSpec information if available (Sony) + my ($sf0, $lf0, $sa0, $la0); + if ($lensSpecPrt) { + ($sf0, $lf0, $sa0, $la0) = GetLensInfo($lensSpecPrt); + undef $sf0 unless $sa0; # (make sure aperture isn't zero) + } + # use MaxApertureValue if MaxAperture is not available + $maxAperture = $maxApertureValue unless $maxAperture; + if ($lensFocalRange and $lensFocalRange =~ /^(\d+)(?: (?:to )?(\d+))?$/) { + ($shortFocal, $longFocal) = ($1, $2 || $1); + } + if ($$et{Make} eq 'SONY') { + # Patch for Metabones or other adapters on Sony E-mount cameras (ref Jos Roost) + # Metabones Canon EF to E-mount adapters add 0xef00, 0xbc00 or 0x7700 to the + # high byte for 2-byte Canon LensType values, so we need to adjust for these. + # Offset 0xef00 is also used by Sigma MC-11, Fotodiox and Viltrox EF-E adapters. + # Have to exclude A-mount Sigma Filtermatic with 'odd' LensType=0xff00. + if ($lensType != 0xffff and $lensType != 0xff00) { + require Image::ExifTool::Minolta; + if ($Image::ExifTool::Minolta::metabonesID{$lensType & 0xff00}) { + $lensType -= ($lensType >= 0xef00 ? 0xef00 : $lensType >= 0xbc00 ? 0xbc00 : 0x7700); + require Image::ExifTool::Canon; + $printConv = \%Image::ExifTool::Canon::canonLensTypes; + $lensTypePrt = $$printConv{$lensType} if $$printConv{$lensType}; + # Test for Sigma MC-11 SA-E adapter with Sigma SA lens using 0x4900 offset. + # (upper limit of test cuts off two highest Sigma lenses, but prevents + # conflict with old Minolta 25xxx and higher ID's) + } elsif ($lensType >= 0x4900 and $lensType <= 0x590a) { + require Image::ExifTool::Sigma; + $lensType -= 0x4900; + $printConv = \%Image::ExifTool::Sigma::sigmaLensTypes; + $lensTypePrt = $$printConv{$lensType} if $$printConv{$lensType}; + } + } + } elsif ($shortFocal and $longFocal) { + # Canon (and some other makes) include makernote information + # which allows better lens identification + require Image::ExifTool::Canon; + return Image::ExifTool::Canon::PrintLensID($printConv, $lensType, + $shortFocal, $longFocal, $maxAperture, $lensModel); + } + my $lens = $$printConv{$lensType}; + return ($lensModel || $lensTypePrt) unless $lens; + return $lens unless $$printConv{"$lensType.1"}; + $lens =~ s/ or .*//s; # remove everything after "or" + # make list of all possible matching lenses + my @lenses = ( $lens ); + my $i; + for ($i=1; $$printConv{"$lensType.$i"}; ++$i) { + push @lenses, $$printConv{"$lensType.$i"}; + } + # attempt to determine actual lens + my (@matches, @best, @user, $diff); + foreach $lens (@lenses) { + push @user, $lens if $Image::ExifTool::userLens{$lens}; + # sf = short focal + # lf = long focal + # sa = max aperture at short focal + # la = max aperture at long focal + my ($sf, $lf, $sa, $la) = GetLensInfo($lens); + next unless $sf; + # check against LensSpec parameters if available + if ($sf0) { + next if abs($sf - $sf0) > 0.5 or abs($sa - $sa0) > 0.15 or + abs($lf - $lf0) > 0.5 or abs($la - $la0) > 0.15; + # the basic parameters match, but also check against additional lens features: + # for Sony A and E lenses, the full LensSpec string should match with end of LensType, + # excluding any part between () at the end, and preceded by a space (the space + # ensures that e.g. Zeiss Loxia 21mm having LensSpec "E 21mm F2.8" will not be + # identified as "Sony FE 21mm F2.8 (SEL28F20 + SEL075UWC)") + $lensSpecPrt and $lens =~ / \Q$lensSpecPrt\E( \(|$)/ and @best = ( $lens ), last; + # exactly-matching Sony lens should have been found above, so only add non-Sony lenses + push @best, $lens unless $lens =~ /^Sony /; + next; + } + # adjust focal length and aperture if teleconverter is attached (Minolta) + if ($lens =~ / \+ .*? (\d+(\.\d+)?)x( |$)/) { + $sf *= $1; $lf *= $1; + $sa *= $1; $la *= $1; + } + # see if we can rule out this lens using FocalLength and MaxAperture + if ($focalLength) { + next if $focalLength < $sf - 0.5; + next if $focalLength > $lf + 0.5; + } + if ($maxAperture) { + # it seems that most manufacturers set MaxAperture and MaxApertureValue + # to the maximum aperture (smallest F number) for the current focal length + # of the lens, so assume that MaxAperture varies with focal length and find + # the closest match (this is somewhat contrary to the EXIF specification which + # states "The smallest F number of the lens", without mention of focal length) + next if $maxAperture < $sa - 0.15; # (0.15 is arbitrary) + next if $maxAperture > $la + 0.15; + # now determine the best match for this aperture + my $aa; # approximate maximum aperture at this focal length + if ($sf == $lf or $sa == $la or $focalLength <= $sf) { + # either 1) prime lens, 2) fixed-aperture zoom, or 3) zoom at min focal + $aa = $sa; + } elsif ($focalLength >= $lf) { + $aa = $la; + } else { + # assume a log-log variation of max aperture with focal length + # (see http://regex.info/blog/2006-10-05/263) + $aa = exp(log($sa) + (log($la)-log($sa)) / (log($lf)-log($sf)) * + (log($focalLength)-log($sf))); + # a linear relationship between 1/FocalLength and 1/MaxAperture fits Sony better (ref 27) + #$aa = 1 / (1/$sa + (1/$focalLength - 1/$sf) * (1/$la - 1/$sa) / (1/$lf - 1/$sf)); + } + my $d = abs($maxAperture - $aa); + if (defined $diff) { + $d > $diff + 0.15 and next; # (0.15 is arbitrary) + $d < $diff - 0.15 and undef @best; + } + $diff = $d; + push @best, $lens; + } + push @matches, $lens; + } + # return the user-defined lens if it exists + if (@user) { + # choose the best match if we have more than one + if (@user > 1) { + my ($try, @good); + foreach $try (\@best, \@matches) { + $Image::ExifTool::userLens{$_} and push @good, $_ foreach @$try; + return join(' or ', @good) if @good; + } + } + return join(' or ', @user); + } + # return the best match(es) from the possible lenses + return join(' or ', @best) if @best; + return join(' or ', @matches) if @matches; + $lens = $$printConv{$lensType}; + return $lensModel if $lensModel and $lens =~ / or /; # (eg. Sony NEX-5N) + return $lens; +} + +#------------------------------------------------------------------------------ +# Translate date into standard EXIF format +# Inputs: 0) date +# Returns: date in format '2003:10:22' +# - bad formats recognized: '2003-10-22','2003/10/22','2003 10 22','20031022' +# - removes null terminator if it exists +sub ExifDate($) +{ + my $date = shift; + $date =~ s/\0$//; # remove any null terminator + # separate year:month:day with colons + # (have seen many other characters, including nulls, used erroneously) + $date =~ s/(\d{4})[^\d]*(\d{2})[^\d]*(\d{2})$/$1:$2:$3/; + return $date; +} + +#------------------------------------------------------------------------------ +# Translate time into standard EXIF format +# Inputs: 0) time +# Returns: time in format '10:30:55' +# - bad formats recognized: '10 30 55', '103055', '103055+0500' +# - removes null terminator if it exists +# - leaves time zone intact if specified (eg. '10:30:55+05:00') +sub ExifTime($) +{ + my $time = shift; + $time =~ tr/ /:/; # use ':' (not ' ') as a separator + $time =~ s/\0$//; # remove any null terminator + # add separators if they don't exist + $time =~ s/^(\d{2})(\d{2})(\d{2})/$1:$2:$3/; + $time =~ s/([+-]\d{2})(\d{2})\s*$/$1:$2/; # to timezone too + return $time; +} + +#------------------------------------------------------------------------------ +# Generate TIFF file from scratch (in current byte order) +# Inputs: 0) hash of IFD entries (TagID => Value; multiple values space-delimited) +# 1) raw image data reference +# Returns: TIFF image data, or undef on error +sub GenerateTIFF($$) +{ + my ($entries, $dataPt) = @_; + my ($rtnVal, $tag, $offsetPos); + + my $num = scalar keys %$entries; + my $ifdBuff = GetByteOrder() . Set16u(42) . Set32u(8) . Set16u($num); + my $valBuff = ''; + my $tagTablePtr = GetTagTable('Image::ExifTool::Exif::Main'); + foreach $tag (sort { $a <=> $b } keys %$entries) { + my $tagInfo = $$tagTablePtr{$tag}; + my $fmt = ref $tagInfo eq 'HASH' ? $$tagInfo{Writable} : 'int32u'; + return undef unless defined $fmt; + my $val = Image::ExifTool::WriteValue($$entries{$tag}, $fmt, -1); + return undef unless defined $val; + my $format = $formatNumber{$fmt}; + $ifdBuff .= Set16u($tag) . Set16u($format) . Set32u(length($val)/$formatSize[$format]); + $offsetPos = length($ifdBuff) if $tag == 0x111; # (remember StripOffsets position) + if (length $val > 4) { + $ifdBuff .= Set32u(10 + 12 * $num + 4 + length($valBuff)); + $valBuff .= $val; + } else { + $val .= "\0" x (4 - length($val)) if length $val < 4; + $ifdBuff .= $val; + } + } + $ifdBuff .= "\0\0\0\0"; # (no IFD1) + return undef unless $offsetPos; + Set32u(length($ifdBuff) + length($valBuff), \$ifdBuff, $offsetPos); + return $ifdBuff . $valBuff . $$dataPt; +} + +#------------------------------------------------------------------------------ +# Rebuild TIFF thumbnail(s)/preview(s) into stand-alone files with current byte order +# Inputs: 0) ExifTool ref, 1) SubfileType, 2) Compression, 3) ImageWidth, 4) ImageHeight, +# 5) BitsPerSample, 6) PhotometricInterpretation, 7) StripOffsets, 8) SamplesPerPixel, +# 9) RowsPerStrip, 10) StripByteCounts, 10) PlanarConfiguration, 11) Orientation +# Returns: 0) TIFF image or undef, 1/2) Family 0/1 groups for TIFF preview IFD +sub RebuildTIFF($;@) +{ + local $_; + my $et = $_[0]; + my $value = $$et{VALUE}; + my ($i, $j, $rtn, $grp0, $grp1); + return undef if $$et{FILE_TYPE} eq 'RWZ'; +SubFile: + for ($i=0; ; ++$i) { + my $key = 'SubfileType' . ($i ? " ($i)" : ''); + last unless defined $$value{$key}; + next unless $$value{$key} == 1; # (reduced-resolution image) + my $grp = $et->GetGroup($key, 1); + my $cmp = $et->FindValue('Compression', $grp); + next unless $cmp == 1; # (no compression) + my %vals = (Compression=>$cmp, PlanarConfiguration=>1, Orientation=>1); + foreach (qw(ImageWidth ImageHeight BitsPerSample PhotometricInterpretation + StripOffsets SamplesPerPixel RowsPerStrip StripByteCounts + PlanarConfiguration Orientation)) + { + my $val = $et->FindValue($_, $grp); + defined $val and $vals{$_} = $val, next; + next SubFile unless defined $vals{$_}; + } + my ($w, $h) = @vals{'ImageWidth', 'ImageHeight'}; + my @bits = split ' ', $vals{BitsPerSample}; + my $rowBytes = 0; + $rowBytes += $w * int(($_+7)/8) foreach @bits; + my $dat = ''; + my @off = split ' ', $vals{StripOffsets}; + my @len = split ' ', $vals{StripByteCounts}; + # read the image data + for ($j=0; $j<@off; ++$j) { + next SubFile unless $len[$j] == $rowBytes * $vals{RowsPerStrip}; + my $tmp = $et->ExtractBinary($off[$j], $len[$j]); + next SubFile unless defined $tmp; + $dat .= $tmp; + } + # generate the TIFF image + my %entries = ( + 0x0fe => 0, # SubfileType = 0 + 0x100 => $w, # ImageWidth + 0x101 => $h, # ImageHeight + 0x102 => $vals{BitsPerSample},# BitsPerSample + 0x103 => $vals{Compression},# Compression + 0x106 => $vals{PhotometricInterpretation}, # PhotometricInterpretation + 0x111 => 0, # StripOffsets (will be adjusted later) + 0x112 => $vals{Orientation},# Orientation + 0x115 => $vals{SamplesPerPixel}, # SamplesPerPixel + 0x116 => $h, # RowsPerStrip + 0x117 => $h * $rowBytes, # StripByteCounts + 0x11a => 72, # XResolution = 72 + 0x11b => 72, # YResolution = 72 + 0x11c => $vals{PlanarConfiguration}, # PlanarConfiguration + 0x128 => 2, # ResolutionUnit = 2 + ); + my $img = GenerateTIFF(\%entries, \$dat); + + if (not defined $img) { + $et->Warn('Invalid ' . ($w > 256 ? 'Preview' : 'Thumbnail') . 'TIFF data'); + } elsif ($rtn or $w > 256) { # (call it a preview if larger than 256 pixels) + $et->FoundTag('PreviewTIFF', \$img, $et->GetGroup($key)); + } else { + $rtn = \$img; + ($grp0, $grp1) = $et->GetGroup($key); + } + } + return $rtn unless wantarray; + return ($rtn, $grp0, $grp1); +} + +#------------------------------------------------------------------------------ +# Extract image from file +# Inputs: 0) ExifTool object reference, 1) data offset (in file), 2) data length +# 3) [optional] tag name +# Returns: Reference to Image if specifically requested or "Binary data" message +# Returns undef if there was an error loading the image +sub ExtractImage($$$$) +{ + my ($et, $offset, $len, $tag) = @_; + my $dataPt = \$$et{EXIF_DATA}; + my $dataPos = $$et{EXIF_POS}; + my $image; + + # no image if length is zero, and don't try to extract binary from XMP file + return undef if not $len or $$et{FILE_TYPE} eq 'XMP'; + + # take data from EXIF block if possible + if (defined $dataPos and $offset>=$dataPos and $offset+$len<=$dataPos+length($$dataPt)) { + $image = substr($$dataPt, $offset-$dataPos, $len); + } else { + $image = $et->ExtractBinary($offset, $len, $tag); + return undef unless defined $image; + # patch for incorrect ThumbnailOffset in some Sony DSLR-A100 ARW images + if ($tag and $tag eq 'ThumbnailImage' and $$et{TIFF_TYPE} eq 'ARW' and + $$et{Model} eq 'DSLR-A100' and $offset < 0x10000 and + $image !~ /^(Binary data|\xff\xd8\xff)/) + { + my $try = $et->ExtractBinary($offset + 0x10000, $len, $tag); + if (defined $try and $try =~ /^\xff\xd8\xff/) { + $image = $try; + $$et{VALUE}{ThumbnailOffset} += 0x10000; + $et->Warn('Adjusted incorrect A100 ThumbnailOffset', 1); + } + } + } + return $et->ValidateImage(\$image, $tag); +} + +#------------------------------------------------------------------------------ +# Utility routine to return tag ID string for warnings +# Inputs: 0) Tag ID, 1) [optional] TagInfo ref +# Returns: "tag 0xXXXX NAME" +sub TagName($;$) +{ + my ($tagID, $tagInfo) = @_; + my $tagName = $tagInfo ? ' '.$$tagInfo{Name} : ''; + return sprintf('tag 0x%.4x%s', $tagID, $tagName); +} + +#------------------------------------------------------------------------------ +# Get class name of next IFD offset for HtmlDump output +# Inputs: 0) ExifTool ref, 1) current class ID +# Returns: 0) new IFD offset name, 1) new class ID including "Offset_" for new offset +# 2) new "Offset_" ID +sub NextOffsetName($;$) +{ + my ($et, $id) = @_; + $$et{OffsetNum} = defined $$et{OffsetNum} ? $$et{OffsetNum} + 1 : 0; + my $offName = 'o' . $$et{OffsetNum}; + my $sid = "Offset_$offName"; + $id = (defined $id ? "$id " : '') . $sid; + return ($offName, $id, $sid); +} + +#------------------------------------------------------------------------------ +# Process EXIF directory +# Inputs: 0) ExifTool object reference +# 1) Reference to directory information hash +# 2) Pointer to tag table for this directory +# Returns: 1 on success, otherwise returns 0 and sets a Warning +sub ProcessExif($$$) +{ + my ($et, $dirInfo, $tagTablePtr) = @_; + my $dataPt = $$dirInfo{DataPt}; + my $dataPos = $$dirInfo{DataPos} || 0; + my $dataLen = $$dirInfo{DataLen}; + my $dirStart = $$dirInfo{DirStart} || 0; + my $dirLen = $$dirInfo{DirLen} || $dataLen - $dirStart; + my $dirName = $$dirInfo{DirName}; + my $base = $$dirInfo{Base} || 0; + my $firstBase = $base; + my $raf = $$dirInfo{RAF}; + my $verbose = $et->Options('Verbose'); + my $validate = $et->Options('Validate'); + my $htmlDump = $$et{HTML_DUMP}; + my $success = 1; + my ($tagKey, $dirSize, $makerAddr, $strEnc, %offsetInfo, $offName, $nextOffName); + my $inMakerNotes = $$tagTablePtr{GROUPS}{0} eq 'MakerNotes'; + my $isExif = ($tagTablePtr eq \%Image::ExifTool::Exif::Main); + + # set encoding to assume for strings + $strEnc = $et->Options('CharsetEXIF') if $$tagTablePtr{GROUPS}{0} eq 'EXIF'; + + # ignore non-standard EXIF while in strict MWG compatibility mode + if (($validate or $Image::ExifTool::MWG::strict) and $dirName eq 'IFD0' and + $isExif and $$et{FILE_TYPE} =~ /^(JPEG|TIFF|PSD)$/) + { + my $path = $et->MetadataPath(); + unless ($path =~ /^(JPEG-APP1-IFD0|TIFF-IFD0|PSD-EXIFInfo-IFD0)$/) { + if ($Image::ExifTool::MWG::strict) { + $et->Warn("Ignored non-standard EXIF at $path"); + return 1; + } else { + $et->Warn("Non-standard EXIF at $path", 1); + } + } + } + # mix htmlDump and Validate into verbose so we can test for all at once + $verbose = -1 if $htmlDump; + $verbose = -2 if $validate and not $verbose; + $dirName eq 'EXIF' and $dirName = $$dirInfo{DirName} = 'IFD0'; + $$dirInfo{Multi} = 1 if $dirName =~ /^(IFD0|SubIFD)$/ and not defined $$dirInfo{Multi}; + # get a more descriptive name for MakerNote sub-directories + my $dir = $$dirInfo{Name}; + $dir = $dirName unless $dir and $inMakerNotes and $dir !~ /^MakerNote/; + + my ($numEntries, $dirEnd); + if ($dirStart >= 0 and $dirStart <= $dataLen-2) { + # make sure data is large enough (patches bug in Olympus subdirectory lengths) + $numEntries = Get16u($dataPt, $dirStart); + $dirSize = 2 + 12 * $numEntries; + $dirEnd = $dirStart + $dirSize; + if ($dirSize > $dirLen) { + if (($verbose > 0 or $validate) and not $$dirInfo{SubIFD}) { + my $short = $dirSize - $dirLen; + $$et{INDENT} =~ s/..$//; # keep indent the same + $et->Warn("Short directory size for $dir (missing $short bytes)"); + $$et{INDENT} .= '| '; + } + undef $dirSize if $dirEnd > $dataLen; # read from file if necessary + } + } + # read IFD from file if necessary + unless ($dirSize) { + $success = 0; + if ($raf) { + # read the count of entries in this IFD + my $offset = $dirStart + $dataPos; + my ($buff, $buf2); + if ($raf->Seek($offset + $base, 0) and $raf->Read($buff,2) == 2) { + my $len = 12 * Get16u(\$buff,0); + # also read next IFD pointer if available + if ($raf->Read($buf2, $len+4) >= $len) { + $buff .= $buf2; + # make copy of dirInfo since we're going to modify it + my %newDirInfo = %$dirInfo; + $dirInfo = \%newDirInfo; + # update directory parameters for the newly loaded IFD + $dataPt = $$dirInfo{DataPt} = \$buff; + $dataPos = $$dirInfo{DataPos} = $offset; + $dataLen = $$dirInfo{DataLen} = length $buff; + $dirStart = $$dirInfo{DirStart} = 0; + $dirLen = $$dirInfo{DirLen} = length $buff; + $success = 1; + } + } + } + unless ($success) { + $et->Warn("Bad $dir directory"); + return 0; + } + $numEntries = Get16u($dataPt, $dirStart); + $dirSize = 2 + 12 * $numEntries; + $dirEnd = $dirStart + $dirSize; + } + $verbose > 0 and $et->VerboseDir($dirName, $numEntries); + my $bytesFromEnd = $dataLen - $dirEnd; + if ($bytesFromEnd < 4) { + unless ($bytesFromEnd==2 or $bytesFromEnd==0) { + $et->Warn("Illegal $dir directory size ($numEntries entries)"); + return 0; + } + } + # fix base offset for maker notes if necessary + if (defined $$dirInfo{MakerNoteAddr}) { + $makerAddr = $$dirInfo{MakerNoteAddr}; + delete $$dirInfo{MakerNoteAddr}; + if (Image::ExifTool::MakerNotes::FixBase($et, $dirInfo)) { + $base = $$dirInfo{Base}; + $dataPos = $$dirInfo{DataPos}; + } + } + if ($htmlDump) { + $offName = $$dirInfo{OffsetName}; + my $longName = $dir eq 'MakerNotes' ? ($$dirInfo{Name} || $dir) : $dir; + if (defined $makerAddr) { + my $hdrLen = $dirStart + $dataPos + $base - $makerAddr; + $et->HDump($makerAddr, $hdrLen, "MakerNotes header", $longName) if $hdrLen > 0; + } + unless ($$dirInfo{NoDumpEntryCount}) { + $et->HDump($dirStart + $dataPos + $base, 2, "$longName entries", + "Entry count: $numEntries", undef, $offName); + } + my $tip; + my $id = $offName; + if ($bytesFromEnd >= 4) { + my $nxt = ($dir =~ /^(.*?)(\d+)$/) ? $1 . ($2 + 1) : 'Next IFD'; + my $off = Get32u($dataPt, $dirEnd); + $tip = sprintf("$nxt offset: 0x%.4x", $off); + ($nextOffName, $id) = NextOffsetName($et, $offName) if $off; + } + $et->HDump($dirEnd + $dataPos + $base, 4, "Next IFD", $tip, 0, $id); + } + + # patch for Canon EOS 40D firmware 1.0.4 bug (incorrect directory counts) + # (must do this before parsing directory or CameraSettings offset will be suspicious) + if ($inMakerNotes and $$et{Model} eq 'Canon EOS 40D' and $numEntries) { + my $entry = $dirStart + 2 + 12 * ($numEntries - 1); + my $fmt = Get16u($dataPt, $entry + 2); + if ($fmt < 1 or $fmt > 13) { + $et->HDump($entry+$dataPos+$base,12,"[invalid IFD entry]", + "Bad format type: $fmt", 1, $offName); + # adjust the number of directory entries + --$numEntries; + $dirEnd -= 12; + } + } + + # make sure that Compression and SubfileType are defined for this IFD (for Condition's) + $$et{Compression} = $$et{SubfileType} = ''; + + # loop through all entries in an EXIF directory (IFD) + my ($index, $valEnd, $offList, $offHash, $mapFmt); + $mapFmt = $$tagTablePtr{VARS}{MAP_FORMAT} if $$tagTablePtr{VARS}; + + my ($warnCount, $lastID) = (0, -1); + for ($index=0; $index<$numEntries; ++$index) { + if ($warnCount > 10) { + $et->Warn("Too many warnings -- $dir parsing aborted", 2) and return 0; + } + my $entry = $dirStart + 2 + 12 * $index; + my $tagID = Get16u($dataPt, $entry); + my $format = Get16u($dataPt, $entry+2); + my $count = Get32u($dataPt, $entry+4); + if ($format < 1 or $format > 13) { + if ($mapFmt and $$mapFmt{$format}) { + $format = $$mapFmt{$format}; + } else { + $et->HDump($entry+$dataPos+$base,12,"[invalid IFD entry]", + "Bad format type: $format", 1, $offName); + # warn unless the IFD was just padded with zeros + if ($format or $validate) { + $et->Warn("Bad format ($format) for $dir entry $index", $inMakerNotes); + ++$warnCount; + } + # assume corrupted IFD if this is our first entry (except Sony ILCE-7M2 firmware 1.21) + return 0 unless $index or $$et{Model} eq 'ILCE-7M2'; + next; + } + } + my $formatStr = $formatName[$format]; # get name of this format + my $valueDataPt = $dataPt; + my $valueDataPos = $dataPos; + my $valueDataLen = $dataLen; + my $valuePtr = $entry + 8; # pointer to value within $$dataPt + my $tagInfo = $et->GetTagInfo($tagTablePtr, $tagID); + my ($origFormStr, $bad, $rational, $subOffName); + # hack to patch incorrect count in Kodak SubIFD3 tags + if ($count < 2 and ref $$tagTablePtr{$tagID} eq 'HASH' and $$tagTablePtr{$tagID}{FixCount}) { + $offList or ($offList, $offHash) = GetOffList($dataPt, $dirStart, $dataPos, + $numEntries, $tagTablePtr); + my $i = $$offHash{Get32u($dataPt, $valuePtr)}; + if (defined $i and $i < $#$offList) { + my $oldCount = $count; + $count = int(($$offList[$i+1] - $$offList[$i]) / $formatSize[$format]); + $origFormStr = $formatName[$format] . '[' . $oldCount . ']' if $oldCount != $count; + } + } + $validate and not $inMakerNotes and Image::ExifTool::Validate::ValidateExif( + $et, $tagTablePtr, $tagID, $tagInfo, $lastID, $dir, $count, $formatStr); + my $size = $count * $formatSize[$format]; + my $readSize = $size; + if ($size > 4) { + if ($size > 0x7fffffff) { + $et->Warn(sprintf("Invalid size (%u) for %s %s",$size,$dir,TagName($tagID,$tagInfo)), $inMakerNotes); + ++$warnCount; + next; + } + $valuePtr = Get32u($dataPt, $valuePtr); + if ($validate and not $inMakerNotes) { + $et->Warn(sprintf('Odd offset for %s %s',$dir,TagName($tagID,$tagInfo)), 1) if $valuePtr & 0x01; + if ($valuePtr < 8 || ($valuePtr + $size > length($$dataPt) and + $valuePtr + $size > $$et{VALUE}{FileSize})) + { + $et->Warn(sprintf('Invalid offset for %s %s',$dir,TagName($tagID,$tagInfo))); + ++$warnCount; + next; + } + if ($valuePtr + $size > $dirStart + $dataPos and $valuePtr < $dirEnd + $dataPos + 4) { + $et->Warn(sprintf('Value for %s %s overlaps IFD', $dir, TagName($tagID,$tagInfo))); + } + } + # fix valuePtr if necessary + if ($$dirInfo{FixOffsets}) { + my $wFlag; + $valEnd or $valEnd = $dataPos + $dirEnd + 4; + #### eval FixOffsets ($valuePtr, $valEnd, $size, $tagID, $wFlag) + eval $$dirInfo{FixOffsets}; + } + my $suspect; + # offset shouldn't point into TIFF header + $valuePtr < 8 and not $$dirInfo{ZeroOffsetOK} and $suspect = $warnCount; + # convert offset to pointer in $$dataPt + if ($$dirInfo{EntryBased} or (ref $$tagTablePtr{$tagID} eq 'HASH' and + $$tagTablePtr{$tagID}{EntryBased})) + { + $valuePtr += $entry; + } else { + $valuePtr -= $dataPos; + } + # value shouldn't overlap our directory + $suspect = $warnCount if $valuePtr < $dirEnd and $valuePtr+$size > $dirStart; + # load value from file if necessary + if ($valuePtr < 0 or $valuePtr+$size > $dataLen) { + # get value by seeking in file if we are allowed + my $buff; + if ($raf) { + # avoid loading large binary data unless necessary + while ($size > BINARY_DATA_LIMIT) { + if ($tagInfo) { + # make large unknown blocks binary data + $$tagInfo{Binary} = 1 if $$tagInfo{Unknown}; + last unless $$tagInfo{Binary}; # must read non-binary data + last if $$tagInfo{SubDirectory}; + my $lcTag = lc($$tagInfo{Name}); + if ($$et{OPTIONS}{Binary} and + not $$et{EXCL_TAG_LOOKUP}{$lcTag}) + { + # read binary data if specified unless tagsFromFile won't use it + last unless $$et{TAGS_FROM_FILE} and $$tagInfo{Protected}; + } + # must read if tag is specified by name + last if $$et{REQ_TAG_LOOKUP}{$lcTag}; + } else { + # must read value if needed for a condition + last if defined $tagInfo; + } + # (note: changing the value without changing $size will cause + # a warning in the verbose output, but we need to maintain the + # proper size for the htmlDump, so we can't change this) + $buff = "Binary data $size bytes"; + $readSize = length $buff; + last; + } + # read from file if necessary + unless (defined $buff) { + my $wrn; + my $readFromRAF = ($tagInfo and $$tagInfo{ReadFromRAF}); + if (not $raf->Seek($base + $valuePtr + $dataPos, 0)) { + $wrn = "Invalid offset for $dir entry $index"; + } elsif ($readFromRAF and $size > BINARY_DATA_LIMIT and + not $$et{REQ_TAG_LOOKUP}{lc $$tagInfo{Name}}) + { + $buff = "$$tagInfo{Name} data $size bytes"; + $readSize = length $buff; + } elsif ($raf->Read($buff,$size) != $size) { + $wrn = "Error reading value for $dir entry $index"; + } elsif ($readFromRAF) { + # seek back to the start of the value + $raf->Seek($base + $valuePtr + $dataPos, 0); + } + if ($wrn) { + $et->Warn($wrn, $inMakerNotes); + return 0 unless $inMakerNotes or $htmlDump; + ++$warnCount; + $buff = '' unless defined $buff; + $readSize = length $buff; + $bad = 1; + } + } + $valueDataLen = length $buff; + $valueDataPt = \$buff; + $valueDataPos = $valuePtr + $dataPos; + $valuePtr = 0; + } else { + my ($tagStr, $tmpInfo, $leicaTrailer); + if ($tagInfo) { + $tagStr = $$tagInfo{Name}; + $leicaTrailer = $$tagInfo{LeicaTrailer}; + } elsif (defined $tagInfo) { + $tmpInfo = $et->GetTagInfo($tagTablePtr, $tagID, \ '', $formatStr, $count); + if ($tmpInfo) { + $tagStr = $$tmpInfo{Name}; + $leicaTrailer = $$tmpInfo{LeicaTrailer}; + } + } + if ($tagInfo and $$tagInfo{ChangeBase}) { + # adjust base offset for this tag only + #### eval ChangeBase ($dirStart,$dataPos) + my $newBase = eval $$tagInfo{ChangeBase}; + $valuePtr += $newBase; + } + $tagStr or $tagStr = sprintf("tag 0x%.4x",$tagID); + # allow PreviewImage to run outside EXIF data + if ($tagStr eq 'PreviewImage' and $$et{RAF}) { + my $pos = $$et{RAF}->Tell(); + $buff = $et->ExtractBinary($base + $valuePtr + $dataPos, $size, 'PreviewImage'); + $$et{RAF}->Seek($pos, 0); + $valueDataPt = \$buff; + $valueDataPos = $valuePtr + $dataPos; + $valueDataLen = $size; + $valuePtr = 0; + } elsif ($leicaTrailer and $$et{RAF}) { + if ($verbose > 0) { + $et->VPrint(0, "$$et{INDENT}$index) $tagStr --> (outside APP1 segment)\n"); + } + if ($et->Options('FastScan')) { + $et->Warn('Ignored Leica MakerNote trailer'); + } else { + require Image::ExifTool::Fixup; + $$et{LeicaTrailer} = { + TagInfo => $tagInfo || $tmpInfo, + Offset => $base + $valuePtr + $dataPos, + Size => $size, + Fixup => new Image::ExifTool::Fixup, + }; + } + } else { + $et->Warn("Bad offset for $dir $tagStr", $inMakerNotes); + ++$warnCount; + } + unless (defined $buff) { + $valueDataPt = ''; + $valueDataPos = $valuePtr + $dataPos; + $valueDataLen = 0; + $valuePtr = 0; + $bad = 1; + } + } + } + # warn about suspect offsets if they didn't already cause another warning + if (defined $suspect and $suspect == $warnCount) { + my $tagStr = $tagInfo ? $$tagInfo{Name} : sprintf('tag 0x%.4x', $tagID); + if ($et->Warn("Suspicious $dir offset for $tagStr", $inMakerNotes)) { + ++$warnCount; + next unless $verbose; + } + } + } + # treat single unknown byte as int8u + $formatStr = 'int8u' if $format == 7 and $count == 1; + + my ($val, $subdir, $wrongFormat); + if ($tagID > 0xf000 and $isExif) { + my $oldInfo = $$tagTablePtr{$tagID}; + if ((not $oldInfo or (ref $oldInfo eq 'HASH' and $$oldInfo{Condition} and + not $$oldInfo{PSRaw})) and not $bad) + { + # handle special case of Photoshop RAW tags (0xfde8-0xfe58) + # --> generate tags from the value if possible + $val = ReadValue($valueDataPt,$valuePtr,$formatStr,$count,$readSize); + if (defined $val and $val =~ /(.*): (.*)/) { + my $tag = $1; + $val = $2; + $tag =~ s/'s//; # remove 's (so "Owner's Name" becomes "OwnerName") + $tag =~ tr/a-zA-Z0-9_//cd; # remove unknown characters + if ($tag) { + $tagInfo = { + Name => $tag, + Condition => '$$self{TIFF_TYPE} ne "DCR"', + ValueConv => '$_=$val;s/^.*: //;$_', # remove descr + PSRaw => 1, # (just as flag to avoid adding this again) + }; + AddTagToTable($tagTablePtr, $tagID, $tagInfo); + # generate conditional list if a conditional tag already existed + $$tagTablePtr{$tagID} = [ $oldInfo, $tagInfo ] if $oldInfo; + } + } + } + } + if (defined $tagInfo and not $tagInfo) { + if ($bad) { + undef $tagInfo; + } else { + # GetTagInfo() required the value for a Condition + my $tmpVal = substr($$valueDataPt, $valuePtr, $readSize < 128 ? $readSize : 128); + # (use original format name in this call -- $formatStr may have been changed to int8u) + $tagInfo = $et->GetTagInfo($tagTablePtr, $tagID, \$tmpVal, + $formatName[$format], $count); + } + } + # make sure we are handling the 'ifd' format properly + if (($format == 13 or $format == 18) and (not $tagInfo or not $$tagInfo{SubIFD})) { + my $str = sprintf('%s tag 0x%.4x IFD format not handled', $dirName, $tagID); + $et->Warn($str, $inMakerNotes); + } + if (defined $tagInfo) { + my $readFormat = $$tagInfo{Format}; + $subdir = $$tagInfo{SubDirectory}; + # unless otherwise specified, all SubDirectory data except + # EXIF SubIFD offsets should be unformatted + $readFormat = 'undef' if $subdir and not $$tagInfo{SubIFD} and not $readFormat; + # override EXIF format if specified + if ($readFormat) { + $formatStr = $readFormat; + my $newNum = $formatNumber{$formatStr}; + if ($newNum and $newNum != $format) { + $origFormStr = $formatName[$format] . '[' . $count . ']'; + $format = $newNum; + $size = $readSize = $$tagInfo{FixedSize} if $$tagInfo{FixedSize}; + # adjust number of items for new format size + $count = int($size / $formatSize[$format]); + } + } + # verify that offset-type values are integral + if (($$tagInfo{IsOffset} or $$tagInfo{SubIFD}) and not $intFormat{$formatStr}) { + $et->Warn(sprintf('Wrong format (%s) for %s 0x%.4x %s',$formatStr,$dir,$tagID,$$tagInfo{Name})); + if ($validate) { + $$et{WrongFormat}{"$dir:$$tagInfo{Name}"} = 1; + $offsetInfo{$tagID} = [ $tagInfo, '' ]; + } + next unless $verbose; + $wrongFormat = 1; + } + } else { + next unless $verbose; + } + unless ($bad) { + # limit maximum length of data to reformat + # (avoids long delays when processing some corrupted files) + if ($count > 100000 and $formatStr !~ /^(undef|string|binary)$/) { + my $tagName = $tagInfo ? $$tagInfo{Name} : sprintf('tag 0x%.4x', $tagID); + if ($tagName ne 'TransferFunction' or $count ne 196608) { + my $minor = $count > 2000000 ? 0 : 2; + next if $et->Warn("Ignoring $dirName $tagName with excessive count", $minor); + } + } + # convert according to specified format + $val = ReadValue($valueDataPt,$valuePtr,$formatStr,$count,$readSize,\$rational); + # re-code if necessary + if ($strEnc and $formatStr eq 'string' and defined $val) { + $val = $et->Decode($val, $strEnc); + } + } + + if ($verbose) { + my $tval = $val; + # also show as a rational + $tval .= " ($rational)" if defined $rational; + if ($htmlDump) { + my ($tagName, $colName); + if ($tagID == 0x927c and $dirName eq 'ExifIFD') { + $tagName = 'MakerNotes'; + } elsif ($tagInfo) { + $tagName = $$tagInfo{Name}; + } else { + $tagName = sprintf("Tag 0x%.4x",$tagID); + } + my $dname = sprintf("${dir}-%.2d", $index); + # build our tool tip + $size < 0 and $size = $count * $formatSize[$format]; + my $fstr = "$formatName[$format]\[$count]"; + $fstr = "$origFormStr read as $fstr" if $origFormStr and $origFormStr ne $fstr; + $fstr .= ' <-- WRONG' if $wrongFormat; + my $tip = sprintf("Tag ID: 0x%.4x\n", $tagID) . + "Format: $fstr\nSize: $size bytes\n"; + if ($size > 4) { + my $offPt = Get32u($dataPt,$entry+8); + my $actPt = $valuePtr + $valueDataPos + $base - ($$et{EXIF_POS} || 0); + $tip .= sprintf("Value offset: 0x%.4x\n", $offPt); + # highlight tag name (red for bad size) + my $style = ($bad or not defined $tval) ? 'V' : 'H'; + if ($actPt != $offPt) { + $tip .= sprintf("Actual offset: 0x%.4x\n", $actPt); + my $sign = $actPt < $offPt ? '-' : ''; + $tip .= sprintf("Offset base: ${sign}0x%.4x\n", abs($actPt - $offPt)); + $style = 'F' if $style eq 'H'; # purple for different offsets + } + $colName = "<span class=$style>$tagName</span>"; + $colName .= ' <span class=V>(odd)</span>' if $offPt & 0x01; + } else { + $colName = $tagName; + } + $colName .= ' <span class=V>(err)</span>' if $wrongFormat; + $colName .= ' <span class=V>(seq)</span>' if $tagID <= $lastID and not $inMakerNotes; + $lastID = $tagID; + if (not defined $tval) { + $tval = '<bad size/offset>'; + } else { + $tval = substr($tval,0,28) . '[...]' if length($tval) > 32; + if ($formatStr =~ /^(string|undef|binary)/) { + # translate non-printable characters + $tval =~ tr/\x00-\x1f\x7f-\xff/./; + } elsif ($tagInfo and Image::ExifTool::IsInt($tval)) { + if ($$tagInfo{IsOffset} or $$tagInfo{SubIFD}) { + $tval = sprintf('0x%.4x', $tval); + my $actPt = $val + $base - ($$et{EXIF_POS} || 0); + if ($actPt != $val) { + $tval .= sprintf("\nActual offset: 0x%.4x", $actPt); + my $sign = $actPt < $val ? '-' : ''; + $tval .= sprintf("\nOffset base: ${sign}0x%.4x", abs($actPt - $val)); + } + } elsif ($$tagInfo{PrintHex}) { + $tval = sprintf('0x%x', $tval); + } + } + } + $tip .= "Value: $tval"; + my $id = $offName; + my $sid; + ($subOffName, $id, $sid) = NextOffsetName($et, $offName) if $tagInfo and $$tagInfo{SubIFD}; + $et->HDump($entry+$dataPos+$base, 12, "$dname $colName", $tip, 1, $id); + next if $valueDataLen < 0; # don't process bad pointer entry + if ($size > 4) { + my $exifDumpPos = $valuePtr + $valueDataPos + $base; + my $flag = 0; + if ($subdir) { + if ($$tagInfo{MakerNotes}) { + $flag = 0x04; + } elsif ($$tagInfo{NestedHtmlDump}) { + $flag = $$tagInfo{NestedHtmlDump} == 2 ? 0x10 : 0x04; + } + } + # add value data block (underlining maker notes data) + $et->HDump($exifDumpPos,$size,"$tagName value",'SAME', $flag, $sid); + } + } else { + if ($tagID <= $lastID and not $inMakerNotes) { + my $str = $tagInfo ? ' '.$$tagInfo{Name} : ''; + if ($tagID == $lastID) { + $et->Warn(sprintf('Duplicate tag 0x%.4x%s in %s', $tagID, $str, $dirName)); + } else { + $et->Warn(sprintf('Tag ID 0x%.4x%s out of sequence in %s', $tagID, $str, $dirName)); + } + } + $lastID = $tagID; + if ($verbose > 0) { + my $fstr = $formatName[$format]; + $fstr = "$origFormStr read as $fstr" if $origFormStr; + $et->VerboseInfo($tagID, $tagInfo, + Table => $tagTablePtr, + Index => $index, + Value => $tval, + DataPt => $valueDataPt, + DataPos => $valueDataPos + $base, + Size => $size, + Start => $valuePtr, + Format => $fstr, + Count => $count, + ); + } + } + next if not $tagInfo or $wrongFormat; + } + next unless defined $val; +#.............................................................................. +# Handle SubDirectory tag types +# + if ($subdir) { + # don't process empty subdirectories + unless ($size) { + unless ($$tagInfo{MakerNotes} or $inMakerNotes) { + $et->Warn("Empty $$tagInfo{Name} data", 1); + } + next; + } + my (@values, $newTagTable, $dirNum, $newByteOrder, $invalid); + my $tagStr = $$tagInfo{Name}; + if ($$subdir{MaxSubdirs}) { + @values = split ' ', $val; + # limit the number of subdirectories we parse + my $over = @values - $$subdir{MaxSubdirs}; + if ($over > 0) { + $et->Warn("Ignoring $over $tagStr directories"); + splice @values, $$subdir{MaxSubdirs}; + } + $val = shift @values; + } + if ($$subdir{TagTable}) { + $newTagTable = GetTagTable($$subdir{TagTable}); + $newTagTable or warn("Unknown tag table $$subdir{TagTable}"), next; + } else { + $newTagTable = $tagTablePtr; # use existing table + } + # loop through all sub-directories specified by this tag + for ($dirNum=0; ; ++$dirNum) { + my $subdirBase = $base; + my $subdirDataPt = $valueDataPt; + my $subdirDataPos = $valueDataPos; + my $subdirDataLen = $valueDataLen; + my $subdirStart = $valuePtr; + if (defined $$subdir{Start}) { + # set local $valuePtr relative to file $base for eval + my $valuePtr = $subdirStart + $subdirDataPos; + #### eval Start ($valuePtr, $val) + my $newStart = eval($$subdir{Start}); + unless (Image::ExifTool::IsInt($newStart)) { + $et->Warn("Bad value for $tagStr"); + last; + } + # convert back to relative to $subdirDataPt + $newStart -= $subdirDataPos; + # adjust directory size if necessary + unless ($$tagInfo{SubIFD} or $$subdir{BadOffset}) { + $size -= $newStart - $subdirStart; + } + $subdirStart = $newStart; + } + # this is a pain, but some maker notes are always a specific + # byte order, regardless of the byte order of the file + my $oldByteOrder = GetByteOrder(); + $newByteOrder = $$subdir{ByteOrder}; + if ($newByteOrder) { + if ($newByteOrder =~ /^Little/i) { + $newByteOrder = 'II'; + } elsif ($newByteOrder =~ /^Big/i) { + $newByteOrder = 'MM'; + } elsif ($$subdir{OffsetPt}) { + undef $newByteOrder; + warn "Can't have variable byte ordering for SubDirectories using OffsetPt"; + last; + } elsif ($subdirStart + 2 <= $subdirDataLen) { + # attempt to determine the byte ordering by checking + # the number of directory entries. This is an int16u + # that should be a reasonable value. + my $num = Get16u($subdirDataPt, $subdirStart); + if ($num & 0xff00 and ($num>>8) > ($num&0xff)) { + # This looks wrong, we shouldn't have this many entries + my %otherOrder = ( II=>'MM', MM=>'II' ); + $newByteOrder = $otherOrder{$oldByteOrder}; + } else { + $newByteOrder = $oldByteOrder; + } + } + } else { + $newByteOrder = $oldByteOrder; + } + # set base offset if necessary + if ($$subdir{Base}) { + # calculate subdirectory start relative to $base for eval + my $start = $subdirStart + $subdirDataPos; + #### eval Base ($start,$base) + $subdirBase = eval($$subdir{Base}) + $base; + } + # add offset to the start of the directory if necessary + if ($$subdir{OffsetPt}) { + #### eval OffsetPt ($valuePtr) + my $pos = eval $$subdir{OffsetPt}; + if ($pos + 4 > $subdirDataLen) { + $et->Warn("Bad $tagStr OffsetPt"); + last; + } + SetByteOrder($newByteOrder); + $subdirStart += Get32u($subdirDataPt, $pos); + SetByteOrder($oldByteOrder); + } + if ($subdirStart < 0 or $subdirStart + 2 > $subdirDataLen) { + # convert $subdirStart back to a file offset + if ($raf) { + # reset SubDirectory buffer (we will load it later) + my $buff = ''; + $subdirDataPt = \$buff; + $subdirDataLen = $size = length $buff; + } else { + my $msg = "Bad $tagStr SubDirectory start"; + if ($verbose > 0) { + if ($subdirStart < 0) { + $msg .= " (directory start $subdirStart is before EXIF start)"; + } else { + my $end = $subdirStart + $size; + $msg .= " (directory end is $end but EXIF size is only $subdirDataLen)"; + } + } + $et->Warn($msg, $inMakerNotes); + last; + } + } + + # must update subdirDataPos if $base changes for this subdirectory + $subdirDataPos += $base - $subdirBase; + + # build information hash for new directory + my %subdirInfo = ( + Name => $tagStr, + Base => $subdirBase, + DataPt => $subdirDataPt, + DataPos => $subdirDataPos, + DataLen => $subdirDataLen, + DirStart => $subdirStart, + DirLen => $size, + RAF => $raf, + Parent => $dirName, + DirName => $$subdir{DirName}, + FixBase => $$subdir{FixBase}, + FixOffsets => $$subdir{FixOffsets}, + EntryBased => $$subdir{EntryBased}, + TagInfo => $tagInfo, + SubIFD => $$tagInfo{SubIFD}, + Subdir => $subdir, + OffsetName => $subOffName, + ); + # (remember: some cameras incorrectly write maker notes in IFD0) + if ($$tagInfo{MakerNotes}) { + # don't parse makernotes if FastScan > 1 + my $fast = $et->Options('FastScan'); + last if $fast and $fast > 1; + $subdirInfo{MakerNoteAddr} = $valuePtr + $valueDataPos + $base; + $subdirInfo{NoFixBase} = 1 if defined $$subdir{Base}; + } + # set directory IFD name from group name of family 1 if it exists, + # unless the tag is writable as a block in which case group 1 may + # have been set automatically + if ($$tagInfo{Groups} and not $$tagInfo{Writable}) { + $subdirInfo{DirName} = $$tagInfo{Groups}{1}; + # number multiple subdirectories + $subdirInfo{DirName} =~ s/\d*$/$dirNum/ if $dirNum; + } + SetByteOrder($newByteOrder); # set byte order for this subdir + # validate the subdirectory if necessary + my $dirData = $subdirDataPt; # set data pointer to be used in eval + #### eval Validate ($val, $dirData, $subdirStart, $size) + my $ok = 0; + if (defined $$subdir{Validate} and not eval $$subdir{Validate}) { + $et->Warn("Invalid $tagStr data"); + $invalid = 1; + } else { + if (not $subdirInfo{DirName} and $inMakerNotes) { + $subdirInfo{DirName} = $$tagInfo{Name}; + } + # process the subdirectory + $ok = $et->ProcessDirectory(\%subdirInfo, $newTagTable, $$subdir{ProcessProc}); + } + # print debugging information if there were errors + if (not $ok and $verbose > 1 and $subdirStart != $valuePtr) { + my $out = $et->Options('TextOut'); + printf $out "%s (SubDirectory start = 0x%x)\n", $$et{INDENT}, $subdirStart; + } + SetByteOrder($oldByteOrder); # restore original byte swapping + + @values or last; + $val = shift @values; # continue with next subdir + } + my $doMaker = $et->Options('MakerNotes'); + next unless $doMaker or $$et{REQ_TAG_LOOKUP}{lc($tagStr)} or $$tagInfo{BlockExtract}; + # extract as a block if specified + if ($$tagInfo{MakerNotes}) { + # save maker note byte order (if it was significant and valid) + if ($$subdir{ByteOrder} and not $invalid) { + $$et{MAKER_NOTE_BYTE_ORDER} = + defined ($$et{UnknownByteOrder}) ? + $$et{UnknownByteOrder} : $newByteOrder; + } + if ($doMaker and $doMaker eq '2') { + # extract maker notes without rebuilding (no fixup information) + delete $$et{MAKER_NOTE_FIXUP}; + } elsif (not $$tagInfo{NotIFD} or $$tagInfo{IsPhaseOne}) { + # this is a pain, but we must rebuild EXIF-type maker notes to + # include all the value data if data was outside the maker notes + my %makerDirInfo = ( + Name => $tagStr, + Base => $base, + DataPt => $valueDataPt, + DataPos => $valueDataPos, + DataLen => $valueDataLen, + DirStart => $valuePtr, + DirLen => $size, + RAF => $raf, + Parent => $dirName, + DirName => 'MakerNotes', + FixOffsets => $$subdir{FixOffsets}, + TagInfo => $tagInfo, + ); + my $val2; + if ($$tagInfo{IsPhaseOne}) { + $$et{DropTags} = 1; + $val2 = Image::ExifTool::PhaseOne::WritePhaseOne($et, \%makerDirInfo, $newTagTable); + delete $$et{DropTags}; + } else { + $makerDirInfo{FixBase} = 1 if $$subdir{FixBase}; + # rebuild maker notes (creates $$et{MAKER_NOTE_FIXUP}) + $val2 = RebuildMakerNotes($et, \%makerDirInfo, $newTagTable); + } + if (defined $val2) { + $val = $val2; + } elsif ($size > 4) { + $et->Warn('Error rebuilding maker notes (may be corrupt)'); + } + } + } else { + # extract this directory as a block if specified + next unless $$tagInfo{Writable}; + } + } + #.............................................................................. + # convert to absolute offsets if this tag is an offset + #### eval IsOffset ($val, $et) + if ($$tagInfo{IsOffset} and eval $$tagInfo{IsOffset}) { + my $offsetBase = $$tagInfo{IsOffset} eq '2' ? $firstBase : $base; + $offsetBase += $$et{BASE}; + # handle offsets which use a wrong base (Minolta A200) + if ($$tagInfo{WrongBase}) { + my $self = $et; + #### eval WrongBase ($self) + $offsetBase += eval $$tagInfo{WrongBase} || 0; + } + my @vals = split(' ',$val); + foreach $val (@vals) { + $val += $offsetBase; + } + $val = join(' ', @vals); + } + if ($validate) { + if ($$tagInfo{OffsetPair}) { + $offsetInfo{$tagID} = [ $tagInfo, $val ]; + } elsif ($saveForValidate{$tagID} and $isExif) { + $offsetInfo{$tagID} = $val; + } + } + # save the value of this tag + $tagKey = $et->FoundTag($tagInfo, $val); + if (defined $tagKey) { + # set the group 1 name for tags in specified tables + $et->SetGroup($tagKey, $dirName) if $$tagTablePtr{SET_GROUP1}; + # save original components of rational numbers (used when copying) + $$et{RATIONAL}{$tagKey} = $rational if defined $rational; + } + } + + # validate image data offsets for this IFD + if ($validate and %offsetInfo) { + Image::ExifTool::Validate::ValidateOffsetInfo($et, \%offsetInfo, $$dirInfo{DirName}, $inMakerNotes) + } + + # scan for subsequent IFD's if specified + if ($$dirInfo{Multi} and $bytesFromEnd >= 4) { + my $offset = Get32u($dataPt, $dirEnd); + if ($offset) { + my $subdirStart = $offset - $dataPos; + # use same directory information for trailing directory, + # but change the start location (ProcessDirectory will + # test to make sure we don't reprocess the same dir twice) + my %newDirInfo = %$dirInfo; + $newDirInfo{DirStart} = $subdirStart; + # increment IFD number + my $ifdNum = $newDirInfo{DirName} =~ s/(\d+)$// ? $1 : 0; + $newDirInfo{DirName} .= $ifdNum + 1; + $newDirInfo{OffsetName} = $nextOffName; + # must validate SubIFD1 because the nextIFD pointer is invalid for some RAW formats + if ($newDirInfo{DirName} ne 'SubIFD1' or ValidateIFD(\%newDirInfo)) { + $$et{INDENT} =~ s/..$//; # keep indent the same + my $cur = pop @{$$et{PATH}}; + $et->ProcessDirectory(\%newDirInfo, $tagTablePtr) or $success = 0; + push @{$$et{PATH}}, $cur; + } elsif ($verbose or $$et{TIFF_TYPE} eq 'TIFF') { + $et->Warn('Ignored bad IFD linked from SubIFD'); + } + } + } + return $success; +} + +1; # end + +__END__ + +=head1 NAME + +Image::ExifTool::Exif - Read EXIF/TIFF meta information + +=head1 SYNOPSIS + +This module is required by Image::ExifTool. + +=head1 DESCRIPTION + +This module contains routines required by Image::ExifTool for processing +EXIF and TIFF meta information. + +=head1 AUTHOR + +Copyright 2003-2019, Phil Harvey (phil at owl.phy.queensu.ca) + +This library is free software; you can redistribute it and/or modify it +under the same terms as Perl itself. + +=head1 REFERENCES + +=over 4 + +=item L<http://www.exif.org/Exif2-2.PDF> + +=item L<http://www.cipa.jp/std/documents/e/DC-008-2012_E.pdf> + +=item L<http://partners.adobe.com/asn/developer/pdfs/tn/TIFF6.pdf> + +=item L<http://partners.adobe.com/public/developer/en/tiff/TIFFPM6.pdf> + +=item L<http://www.adobe.com/products/dng/pdfs/dng_spec.pdf> + +=item L<http://www.awaresystems.be/imaging/tiff/tifftags.html> + +=item L<http://www.remotesensing.org/libtiff/TIFFTechNote2.html> + +=item L<http://www.exif.org/dcf.PDF> + +=item L<http://park2.wakwak.com/~tsuruzoh/Computer/Digicams/exif-e.html> + +=item L<http://www.fine-view.com/jp/lab/doc/ps6ffspecsv2.pdf> + +=item L<http://www.ozhiker.com/electronics/pjmt/jpeg_info/meta.html> + +=item L<http://hul.harvard.edu/jhove/tiff-tags.html> + +=item L<http://www.microsoft.com/whdc/xps/wmphoto.mspx> + +=item L<http://www.asmail.be/msg0054681802.html> + +=item L<http://crousseau.free.fr/imgfmt_raw.htm> + +=item L<http://www.cybercom.net/~dcoffin/dcraw/> + +=item L<http://www.digitalpreservation.gov/formats/content/tiff_tags.shtml> + +=item L<http://community.roxen.com/developers/idocs/rfc/rfc3949.html> + +=item L<http://tools.ietf.org/html/draft-ietf-fax-tiff-fx-extension1-01> + +=item L<http://wwwimages.adobe.com/www.adobe.com/content/dam/Adobe/en/devnet/cinemadng/pdfs/CinemaDNG_Format_Specification_v1_1.pdf> + +=item L<http://geotiff.maptools.org/spec/geotiffhome.html> + +=back + +=head1 ACKNOWLEDGEMENTS + +Thanks to Jeremy Brown for the 35efl tags, and Matt Madrid for his help with +the XP character code conversions. + +=head1 SEE ALSO + +L<Image::ExifTool::TagNames/EXIF Tags>, +L<Image::ExifTool(3pm)|Image::ExifTool> + +=cut diff --git a/lib/Image/ExifTool/FLAC.pm b/lib/Image/ExifTool/FLAC.pm new file mode 100644 index 0000000..822b1bd --- /dev/null +++ b/lib/Image/ExifTool/FLAC.pm @@ -0,0 +1,307 @@ +#------------------------------------------------------------------------------ +# File: FLAC.pm +# +# Description: Read Free Lossless Audio Codec information +# +# Revisions: 11/13/2006 - P. Harvey Created +# +# References: 1) http://flac.sourceforge.net/ +#------------------------------------------------------------------------------ + +package Image::ExifTool::FLAC; + +use strict; +use vars qw($VERSION); +use Image::ExifTool qw(:DataAccess :Utils); + +$VERSION = '1.08'; + +sub ProcessBitStream($$$); + +# FLAC metadata blocks +%Image::ExifTool::FLAC::Main = ( + NOTES => q{ + Free Lossless Audio Codec (FLAC) meta information. ExifTool also extracts + ID3 information from these files. + }, + 0 => { + Name => 'StreamInfo', + SubDirectory => { TagTable => 'Image::ExifTool::FLAC::StreamInfo' }, + }, + 1 => { Name => 'Padding', Binary => 1, Unknown => 1 }, + 2 => { Name => 'Application', Binary => 1, Unknown => 1 }, + 3 => { Name => 'SeekTable', Binary => 1, Unknown => 1 }, + 4 => { + Name => 'VorbisComment', + SubDirectory => { TagTable => 'Image::ExifTool::Vorbis::Comments' }, + }, + 5 => { Name => 'CueSheet', Binary => 1, Unknown => 1 }, + 6 => { + Name => 'Picture', + SubDirectory => { TagTable => 'Image::ExifTool::FLAC::Picture' }, + }, + # 7-126 - Reserved + # 127 - Invalid +); + +%Image::ExifTool::FLAC::StreamInfo = ( + PROCESS_PROC => \&ProcessBitStream, + NOTES => 'FLAC is big-endian, so bit 0 is the high-order bit in this table.', + GROUPS => { 2 => 'Audio' }, + 'Bit000-015' => 'BlockSizeMin', + 'Bit016-031' => 'BlockSizeMax', + 'Bit032-055' => 'FrameSizeMin', + 'Bit056-079' => 'FrameSizeMax', + 'Bit080-099' => 'SampleRate', + 'Bit100-102' => { + Name => 'Channels', + ValueConv => '$val + 1', + }, + 'Bit103-107' => { + Name => 'BitsPerSample', + ValueConv => '$val + 1', + }, + 'Bit108-143' => 'TotalSamples', + 'Bit144-271' => { #Tim Eliseo + Name => 'MD5Signature', + Format => 'undef', + ValueConv => 'unpack("H*",$val)', + }, +); + +%Image::ExifTool::FLAC::Picture = ( + PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData, + GROUPS => { 2 => 'Image' }, + FORMAT => 'int32u', + 0 => { + Name => 'PictureType', + PrintConv => { # (Note: Duplicated in ID3, ASF and FLAC modules!) + 0 => 'Other', + 1 => '32x32 PNG Icon', + 2 => 'Other Icon', + 3 => 'Front Cover', + 4 => 'Back Cover', + 5 => 'Leaflet', + 6 => 'Media', + 7 => 'Lead Artist', + 8 => 'Artist', + 9 => 'Conductor', + 10 => 'Band', + 11 => 'Composer', + 12 => 'Lyricist', + 13 => 'Recording Studio or Location', + 14 => 'Recording Session', + 15 => 'Performance', + 16 => 'Capture from Movie or Video', + 17 => 'Bright(ly) Colored Fish', + 18 => 'Illustration', + 19 => 'Band Logo', + 20 => 'Publisher Logo', + }, + }, + 1 => { + Name => 'PictureMIMEType', + Format => 'var_pstr32', + }, + 2 => { + Name => 'PictureDescription', + Format => 'var_pstr32', + ValueConv => '$self->Decode($val, "UTF8")', + }, + 3 => 'PictureWidth', + 4 => 'PictureHeight', + 5 => 'PictureBitsPerPixel', + 6 => 'PictureIndexedColors', + 7 => 'PictureLength', + 8 => { + Name => 'Picture', + Groups => { 2 => 'Preview' }, + Format => 'undef[$val{7}]', + Binary => 1, + }, +); + +# FLAC composite tags +%Image::ExifTool::FLAC::Composite = ( + Duration => { + Require => { + 0 => 'FLAC:SampleRate', + 1 => 'FLAC:TotalSamples', + }, + ValueConv => '($val[0] and $val[1]) ? $val[1] / $val[0] : undef', + PrintConv => 'ConvertDuration($val)', + }, +); + +# add our composite tags +Image::ExifTool::AddCompositeTags('Image::ExifTool::FLAC'); + + +#------------------------------------------------------------------------------ +# Process information in a bit stream +# Inputs: 0) ExifTool object ref, 1) dirInfo ref, 2) tag table ref +# Notes: Byte order is used to determine the ordering of bits in the stream: +# 'MM' = bit 0 is most significant, 'II' = bit 0 is least significant +# - can handle arbitrarily wide values (eg. 8-byte or larger integers) +sub ProcessBitStream($$$) +{ + my ($et, $dirInfo, $tagTablePtr) = @_; + my $dataPt = $$dirInfo{DataPt}; + my $dataPos = $$dirInfo{DataPos}; + my $dirStart = $$dirInfo{DirStart} || 0; + my $dirLen = $$dirInfo{DirLen} || (length($$dataPt) - $dirStart); + my $verbose = $et->Options('Verbose'); + my $byteOrder = GetByteOrder(); + my $tag; + + if ($verbose) { + $et->VPrint(0, " + [BitStream directory, $dirLen bytes, '${byteOrder}' order]\n"); + } + foreach $tag (sort keys %$tagTablePtr) { + next unless $tag =~ /^Bit(\d+)-?(\d+)?/; + my ($b1, $b2) = ($1, $2 || $1); # start/end bit numbers in stream + my ($i1, $i2) = (int($b1 / 8), int($b2 / 8)); # start/end byte numbers + my ($f1, $f2) = ($b1 % 8, $b2 % 8); # start/end bit numbers within each byte + last if $i2 >= $dirLen; + my ($val, $extra); + # if Format is unspecified, convert the specified number of bits to an unsigned integer, + # otherwise allow HandleTag to convert whole bytes the normal way (via undefined $val) + if (ref $$tagTablePtr{$tag} ne 'HASH' or not $$tagTablePtr{$tag}{Format}) { + my ($i, $mask); + $val = 0; + $extra = ', Mask=0x' if $verbose and ($f1 != 0 or $f2 != 7); + if ($byteOrder eq 'MM') { + # loop from high byte to low byte + for ($i=$i1; $i<=$i2; ++$i) { + $mask = 0xff; + if ($i == $i1 and $f1) { + # mask off high bits in first word (0 is high bit) + foreach ((8-$f1) .. 7) { $mask ^= (1 << $_) } + } + if ($i == $i2 and $f2 < 7) { + # mask off low bits in last word (7 is low bit) + foreach (0 .. (6-$f2)) { $mask ^= (1 << $_) } + } + $val = $val * 256 + ($mask & Get8u($dataPt, $i + $dirStart)); + $extra .= sprintf('%.2x', $mask) if $extra; + } + } else { + # (FLAC is big-endian, but support little-endian bit streams + # so this routine can be used by other modules) + # loop from high byte to low byte + for ($i=$i2; $i>=$i1; --$i) { + $mask = 0xff; + if ($i == $i1 and $f1) { + # mask off low bits in first word (0 is low bit) + foreach (0 .. ($f1-1)) { $mask ^= (1 << $_) } + } + if ($i == $i2 and $f2 < 7) { + # mask off high bits in last word (7 is high bit) + foreach (($f2+1) .. 7) { $mask ^= (1 << $_) } + } + $val = $val * 256 + ($mask & Get8u($dataPt, $i + $dirStart)); + $extra .= sprintf('%.2x', $mask) if $extra; + } + } + # shift word down until low bit is in position 0 + until ($mask & 0x01) { + $val /= 2; + $mask >>= 1; + } + } + $et->HandleTag($tagTablePtr, $tag, $val, + DataPt => $dataPt, + DataPos => $dataPos, + Start => $dirStart + $i1, + Size => $i2 - $i1 + 1, + Extra => $extra, + ); + } + return 1; +} + +#------------------------------------------------------------------------------ +# Extract information from an Ogg FLAC file +# Inputs: 0) ExifTool object reference, 1) dirInfo reference +# Returns: 1 on success, 0 if this wasn't a valid Ogg FLAC file +sub ProcessFLAC($$) +{ + my ($et, $dirInfo) = @_; + + # must first check for leading/trailing ID3 information + unless ($$et{DoneID3}) { + require Image::ExifTool::ID3; + Image::ExifTool::ID3::ProcessID3($et, $dirInfo) and return 1; + } + my $raf = $$dirInfo{RAF}; + my $verbose = $et->Options('Verbose'); + my $out = $et->Options('TextOut'); + my ($buff, $err); + + # check FLAC signature + $raf->Read($buff, 4) == 4 and $buff eq 'fLaC' or return 0; + $et->SetFileType(); + SetByteOrder('MM'); + my $tagTablePtr = GetTagTable('Image::ExifTool::FLAC::Main'); + for (;;) { + # read next metadata block header + $raf->Read($buff, 4) == 4 or last; + my $flag = unpack('C', $buff); + my $size = unpack('N', $buff) & 0x00ffffff; + $raf->Read($buff, $size) == $size or $err = 1, last; + my $last = $flag & 0x80; # last-metadata-block flag + my $tag = $flag & 0x7f; # tag bits + if ($verbose) { + print $out "FLAC metadata block, type $tag:\n"; + $et->VerboseDump(\$buff, DataPos => $raf->Tell() - $size); + } + $et->HandleTag($tagTablePtr, $tag, undef, + DataPt => \$buff, + DataPos => $raf->Tell() - $size, + ); + last if $last; # all done if is set + } + $err and $et->Warn('Format error in FLAC file'); + return 1; +} + +1; # end + +__END__ + +=head1 NAME + +Image::ExifTool::FLAC - Read Free Lossless Audio Codec information + +=head1 SYNOPSIS + +This module is used by Image::ExifTool + +=head1 DESCRIPTION + +This module contains definitions required by Image::ExifTool to extract meta +information from Free Lossless Audio Codec (FLAC) audio files. + +=head1 AUTHOR + +Copyright 2003-2019, Phil Harvey (phil at owl.phy.queensu.ca) + +This library is free software; you can redistribute it and/or modify it +under the same terms as Perl itself. + +=head1 REFERENCES + +=over 4 + +=item L<http://flac.sourceforge.net/> + +=back + +=head1 SEE ALSO + +L<Image::ExifTool::TagNames/FLAC Tags>, +L<Image::ExifTool::TagNames/Ogg Tags>, +L<Image::ExifTool(3pm)|Image::ExifTool> + +=cut + diff --git a/lib/Image/ExifTool/FLIF.pm b/lib/Image/ExifTool/FLIF.pm new file mode 100644 index 0000000..95dbe7e --- /dev/null +++ b/lib/Image/ExifTool/FLIF.pm @@ -0,0 +1,353 @@ +#------------------------------------------------------------------------------ +# File: FLIF.pm +# +# Description: Read/write FLIF meta information +# +# Revisions: 2016/10/11 - P. Harvey Created +# 2016/10/14 - PH Added write support +# +# References: 1) http://flif.info/ +# 2) https://github.com/FLIF-hub/FLIF/blob/master/doc/metadata +#------------------------------------------------------------------------------ + +package Image::ExifTool::FLIF; + +use strict; +use vars qw($VERSION); +use Image::ExifTool qw(:DataAccess :Utils); + +$VERSION = '1.02'; + +my %flifMap = ( + EXIF => 'FLIF', + XMP => 'FLIF', + ICC_Profile => 'FLIF', + IFD0 => 'EXIF', + IFD1 => 'IFD0', + ExifIFD => 'IFD0', + GPS => 'IFD0', + SubIFD => 'IFD0', + GlobParamIFD => 'IFD0', + PrintIM => 'IFD0', + InteropIFD => 'ExifIFD', + MakerNotes => 'ExifIFD', +); + +# FLIF tags +%Image::ExifTool::FLIF::Main = ( + GROUPS => { 0 => 'File', 1 => 'File', 2 => 'Image' }, + VARS => { HEX_ID => 0 }, + NOTES => q{ + Information extracted from Free Lossless Image Format files. See + L<http://flif.info/> for more information. + }, +# +# header information +# + 0 => { + Name => 'ImageType', + PrintConv => { + '1' => 'Grayscale (non-interlaced)', + '3' => 'RGB (non-interlaced)', + '4' => 'RGBA (non-interlaced)', + 'A' => 'Grayscale (interlaced)', + 'C' => 'RGB (interlaced)', + 'D' => 'RGBA (interlaced)', + 'Q' => 'Grayscale Animation (non-interlaced)', + 'S' => 'RGB Animation (non-interlaced)', + 'T' => 'RGBA Animation (non-interlaced)', + 'a' => 'Grayscale Animation (interlaced)', + 'c' => 'RGB Animation (interlaced)', + 'd' => 'RGBA Animation (interlaced)', + }, + }, + 1 => { + Name => 'BitDepth', + PrintConv => { + '0' => 'Custom', + '1' => 8, + '2' => 16, + }, + }, + 2 => 'ImageWidth', + 3 => 'ImageHeight', + 4 => 'AnimationFrames', + 5 => { + Name => 'Encoding', + PrintConv => { + 0 => 'FLIF16', + }, + }, +# +# metadata chunks +# + iCCP => { + Name => 'ICC_Profile', + SubDirectory => { + TagTable => 'Image::ExifTool::ICC_Profile::Main', + }, + }, + eXif => { + Name => 'EXIF', + SubDirectory => { + TagTable => 'Image::ExifTool::Exif::Main', + ProcessProc => \&Image::ExifTool::ProcessTIFF, + WriteProc => \&Image::ExifTool::WriteTIFF, + Start => 6, # (skip "Exif\0\0" header) + Header => "Exif\0\0", + }, + }, + eXmp => { + Name => 'XMP', + SubDirectory => { + TagTable => 'Image::ExifTool::XMP::Main', + }, + }, + # tRko - list of truncation offsets + # \0 - FLIF16-format image data +); + +#------------------------------------------------------------------------------ +# Read variable-length FLIF integer +# Inputs: 0) raf reference, 1) number to add to returned value +# Returns: integer, or undef on EOF +sub GetVarInt($;$) +{ + my ($raf, $add) = @_; + my ($val, $buff); + for ($val=0; ; $val<<=7) { + $raf->Read($buff, 1) or return undef; + my $byte = ord($buff); + $val |= ($byte & 0x7f); + last unless $byte & 0x80; + } + return $val + ($add || 0); +} + +#------------------------------------------------------------------------------ +# Construct variable-length FLIF integer +# Inputs: 0) integer +# Returns: FLIF variable-length integer byte stream +sub SetVarInt($) +{ + my $val = shift; + my $buff = ''; + my $high = 0; + for (;;) { + $buff = chr(($val & 0x7f) | $high) . $buff; + last unless $val >>= 7; + $high = 0x80; + } + return $buff; +} + +#------------------------------------------------------------------------------ +# Read FLIF header +# Inputs: 0) RAF ref +# Returns: Scalar context: binary header block +# List context: header values (4 or 5 elements: type,depth,width,height[,frames]) +# or undef if this isn't a valid FLIF file header +sub ReadFLIFHeader($) +{ + my $raf = shift; + my ($buff, @vals); + + # verify this is a valid FLIF file + return () unless $raf->Read($buff, 6) == 6 and $buff =~ /^FLIF([0-\x6f])([0-2])/; + + # decode header information ("FLIF" chunk) + push @vals, $1, $2; # type, depth + push @vals, GetVarInt($raf,+1), GetVarInt($raf,+1); # width, height (+1 each) + push @vals, GetVarInt($raf,+2) if $vals[0] gt 'H'; # frames (+2) + + return () unless defined $vals[-1]; + return @vals if wantarray; # return the decoded header values + + # return the binary header block + my $hdrLen = $raf->Tell(); + return () unless $raf->Seek(0,0) and $raf->Read($buff, $hdrLen) == $hdrLen; + return $buff; +} + +#------------------------------------------------------------------------------ +# WriteFLIF : Write FLIF image +# Inputs: 0) ExifTool object reference, 1) dirInfo reference +# Returns: 1 on success, 0 if this wasn't a valid FLIF file, or -1 if +# an output file was specified and a write error occurred +sub WriteFLIF($$) +{ + my ($et, $dirInfo) = @_; + my $raf = $$dirInfo{RAF}; + my ($buff, $soi, @addTags, %doneTag); + + # verify FLIF header and copy it to the output file + $buff = ReadFLIFHeader($raf) or return 0; + my $outfile = $$dirInfo{OutFile}; + Write($outfile, $buff) or return -1; + + $et->InitWriteDirs(\%flifMap); + my $tagTablePtr = GetTagTable('Image::ExifTool::FLIF::Main'); + + # loop through the FLIF chunks + for (;;) { + my ($tag, $size, $inflated); + # read new tag (or soi) unless we already hit the soi (start of image) + if (not defined $soi) { + $raf->Read($buff, 4) == 4 or $et->Error('Unexpected EOF'), last; + if ($buff lt ' ') { + $soi = $buff; # we have hit the start of image (no more metadata) + # make list of new tags to add + foreach $tag ('eXif', 'eXmp', 'iCCP') { + push @addTags, $tag if $$et{ADD_DIRS}{$$tagTablePtr{$tag}{Name}} and not $doneTag{$tag}; + } + } + } + if (not defined $soi) { + $tag = $buff; + $size = GetVarInt($raf); # read the data size + } elsif (@addTags) { + $tag = shift @addTags; + ($buff, $size) = ('', 0); # create metadata from scratch + } else { + # finish copying file (no more metadata to add) + Write($outfile, $soi) or return -1; + Write($outfile, $buff) or return -1 while $raf->Read($buff, 65536); + last; # all done! + } + my $tagInfo = $et->GetTagInfo($tagTablePtr, $tag); + if ($tagInfo and $$tagInfo{SubDirectory} and $$et{EDIT_DIRS}{$$tagInfo{Name}}) { + $doneTag{$tag} = 1; # prevent adding this back again later + unless (defined $soi) { + $raf->Read($buff, $size) == $size or $et->Error("Truncated FLIF $tag chunk"), last; + } + # rewrite the compressed data + if (eval { require IO::Uncompress::RawInflate } and eval { require IO::Compress::RawDeflate } ) { + if (length $buff == 0) { + $inflated = $buff; # (creating from scratch, so no need to inflate) + } elsif (not IO::Uncompress::RawInflate::rawinflate(\$buff => \$inflated)) { + $et->Error("Error inflating FLIF $tag chunk"), last; + } + my $subdir = $$tagInfo{SubDirectory}; + my %subdirInfo = ( + DirName => $$tagInfo{Name}, + DataPt => \$inflated, + DirStart => length($inflated) ? $$subdir{Start} : undef, + ReadOnly => 1, # (used only by WriteXMP) + ); + my $subTable = GetTagTable($$subdir{TagTable}); + $inflated = $et->WriteDirectory(\%subdirInfo, $subTable, $$subdir{WriteProc}); + if (defined $inflated) { + next unless length $inflated; # (delete directory if length is zero) + $inflated = $$subdir{Header} . $inflated if $$subdir{Header}; # (add back header if necessary) + unless (IO::Compress::RawDeflate::rawdeflate(\$inflated => \$buff)) { + $et->Error("Error deflating FLIF $tag chunk"), last; + } + } + } else { + $et->WarnOnce('Install IO::Compress::RawDeflate to write FLIF metadata'); + } + Write($outfile, $tag, SetVarInt(length $buff), $buff) or return -1; + } elsif (not defined $soi) { + Write($outfile, $tag, SetVarInt($size)) or return -1; + Image::ExifTool::CopyBlock($raf, $outfile, $size) or return -1; + } + } + return 1; +} + +#------------------------------------------------------------------------------ +# Extract information from an FLIF file +# Inputs: 0) ExifTool object reference, 1) DirInfo reference +# Returns: 1 on success, 0 if this wasn't a valid FLIF file +sub ProcessFLIF($$) +{ + my ($et, $dirInfo) = @_; + my $raf = $$dirInfo{RAF}; + my ($buff, $tag, $inflated); + + # verify this is a valid FLIF file and read the header + my @vals = ReadFLIFHeader($raf) or return 0; + + $et->SetFileType(); + my $tagTablePtr = GetTagTable('Image::ExifTool::FLIF::Main'); + my $verbose = $et->Options('Verbose'); + + # save the header information + $et->VPrint(0, "FLIF header:\n") if $verbose; + for ($tag=0; defined $vals[$tag]; ++$tag) { + $et->HandleTag($tagTablePtr, $tag, $vals[$tag]); + } + + # loop through the FLIF chunks + for (;;) { + $raf->Read($tag, 4) == 4 or $et->Warn('Unexpected EOF'), last; + my $byte = ord substr($tag, 0, 1); + # all done if we arrived at the image chunk + $byte < 32 and $et->HandleTag($tagTablePtr, 5, $byte), last; + my $size = GetVarInt($raf); + $et->VPrint(0, "FLIF $tag ($size bytes):\n") if $verbose; + if ($$tagTablePtr{$tag}) { + $raf->Read($buff, $size) == $size or $et->Warn("Truncated FLIF $tag chunk"), last; + $et->VerboseDump(\$buff, Addr => $raf->Tell() - $size) if $verbose > 2; + # inflate the compressed data + if (eval { require IO::Uncompress::RawInflate }) { + if (IO::Uncompress::RawInflate::rawinflate(\$buff => \$inflated)) { + $et->HandleTag($tagTablePtr, $tag, $inflated, + DataPt => \$inflated, + Size => length $inflated, + Extra => ' inflated', + ); + } else { + $et->Warn("Error inflating FLIF $tag chunk"); + } + } else { + $et->WarnOnce('Install IO::Uncompress::RawInflate to decode FLIF metadata'); + } + } else { + $raf->Seek($size, 1) or $et->Warn('Seek error'), last; + } + } + return 1; +} + +1; # end + +__END__ + +=head1 NAME + +Image::ExifTool::FLIF - Read/write FLIF meta information + +=head1 SYNOPSIS + +This module is used by Image::ExifTool + +=head1 DESCRIPTION + +This module contains routines required by Image::ExifTool to read and write +meta information in FLIF (Free Lossless Image Format) images. + +=head1 AUTHOR + +Copyright 2003-2019, Phil Harvey (phil at owl.phy.queensu.ca) + +This library is free software; you can redistribute it and/or modify it +under the same terms as Perl itself. + +=head1 REFERENCES + +=over 4 + +=item L<http://flif.info/> + +=item L<https://github.com/FLIF-hub/FLIF/blob/master/doc/metadata> + +=back + +=head1 SEE ALSO + +L<Image::ExifTool::TagNames/FLIF Tags>, +L<Image::ExifTool(3pm)|Image::ExifTool> + +=cut + diff --git a/lib/Image/ExifTool/FLIR.pm b/lib/Image/ExifTool/FLIR.pm new file mode 100644 index 0000000..7b3618f --- /dev/null +++ b/lib/Image/ExifTool/FLIR.pm @@ -0,0 +1,1629 @@ +#------------------------------------------------------------------------------ +# File: FLIR.pm +# +# Description: Read FLIR meta information +# +# Revisions: 2013/03/28 - P. Harvey Created +# +# References: 1) http://u88.n24.queensu.ca/exiftool/forum/index.php/topic,4898.0.html +# 2) http://www.nuage.ch/site/flir-i7-some-analysis/ +# 3) http://www.workswell.cz/manuals/flir/hardware/A3xx_and_A6xx_models/Streaming_format_ThermoVision.pdf +# 4) http://support.flir.com/DocDownload/Assets/62/English/1557488%24A.pdf +# 5) http://code.google.com/p/dvelib/source/browse/trunk/flirPublicFormat/fpfConverter/Fpfimg.h?spec=svn3&r=3 +# 6) http://u88.n24.queensu.ca/exiftool/forum/index.php/topic,5538.0.html +# JD) Jens Duttke private communication +# +# Glossary: FLIR = Forward Looking Infra Red +#------------------------------------------------------------------------------ + +package Image::ExifTool::FLIR; + +use strict; +use vars qw($VERSION); +use Image::ExifTool qw(:DataAccess :Utils); +use Image::ExifTool::Exif; +use Image::ExifTool::GPS; + +$VERSION = '1.17'; + +sub ProcessFLIR($$;$); +sub ProcessFLIRText($$$); +sub ProcessMeasInfo($$$); +sub GetImageType($$$); + +my %temperatureInfo = ( + Writable => 'rational64u', + Format => 'rational64s', # (have seen negative values) +); + +# tag information for floating point Kelvin tag +my %floatKelvin = ( + Format => 'float', + ValueConv => '$val - 273.15', + PrintConv => 'sprintf("%.1f C",$val)', +); + +# commonly used tag information elements +my %float1f = ( Format => 'float', PrintConv => 'sprintf("%.1f",$val)' ); +my %float2f = ( Format => 'float', PrintConv => 'sprintf("%.2f",$val)' ); +my %float6f = ( Format => 'float', PrintConv => 'sprintf("%.6f",$val)' ); +my %float8g = ( Format => 'float', PrintConv => 'sprintf("%.8g",$val)' ); + +# FLIR makernotes tags (ref PH) +%Image::ExifTool::FLIR::Main = ( + WRITE_PROC => \&Image::ExifTool::Exif::WriteExif, + CHECK_PROC => \&Image::ExifTool::Exif::CheckExif, + GROUPS => { 0 => 'MakerNotes', 2 => 'Camera' }, + WRITABLE => 1, + PRIORITY => 0, # (unreliable) + NOTES => q{ + Information extracted from the maker notes of JPEG images from thermal + imaging cameras by FLIR Systems Inc. + }, + 0x01 => { #2 + Name => 'ImageTemperatureMax', + %temperatureInfo, + Notes => q{ + these temperatures may be in Celcius, Kelvin or Fahrenheit, but there is no + way to tell which + }, + }, + 0x02 => { Name => 'ImageTemperatureMin', %temperatureInfo }, #2 + 0x03 => { #1 + Name => 'Emissivity', + Writable => 'rational64u', + PrintConv => 'sprintf("%.2f",$val)', + PrintConvInv => '$val', + }, + # 0x04 does not change with temperature units; often 238, 250 or 457 + 0x04 => { Name => 'UnknownTemperature', %temperatureInfo, Unknown => 1 }, + # 0x05,0x06 are unreliable. As written by FLIR tools, these are the + # CameraTemperatureRangeMax/Min, but the units vary depending on the + # options settings. But as written by some cameras, the values are different. + 0x05 => { Name => 'CameraTemperatureRangeMax', %temperatureInfo, Unknown => 1 }, + 0x06 => { Name => 'CameraTemperatureRangeMin', %temperatureInfo, Unknown => 1 }, + # 0x07 - string[33] (some sort of image ID?) + # 0x08 - string[33] + # 0x09 - undef (tool info) + # 0x0a - int32u: 1 + # 0x0f - rational64u: 0/1000 + # 0x10,0x11,0x12 - int32u: 0 + # 0x13 - rational64u: 0/1000 +); + +# FLIR FFF tag table (ref PH) +%Image::ExifTool::FLIR::FFF = ( + GROUPS => { 0 => 'APP1', 2 => 'Image' }, + PROCESS_PROC => \&ProcessFLIR, + VARS => { ALPHA_FIRST => 1 }, + NOTES => q{ + Information extracted from FLIR FFF images and the APP1 FLIR segment of JPEG + images. These tags may also be extracted from the first frame of an FLIR + SEQ file. + }, + "_header" => { + Name => 'FFFHeader', + SubDirectory => { TagTable => 'Image::ExifTool::FLIR::Header' }, + }, + # 0 = free (ref 3) + 0x01 => { + Name => 'RawData', + SubDirectory => { TagTable => 'Image::ExifTool::FLIR::RawData' }, + }, + # 2 = GainMap (ref 3) + # 3 = OffsMap (ref 3) + # 4 = DeadMap (ref 3) + 0x05 => { #6 + Name => 'GainDeadData', + SubDirectory => { TagTable => 'Image::ExifTool::FLIR::GainDeadData' }, + }, + 0x06 => { #6 + Name => 'CoarseData', + SubDirectory => { TagTable => 'Image::ExifTool::FLIR::CoarseData' }, + }, + # 7 = ImageMap (ref 3) + 0x0e => { + Name => 'EmbeddedImage', + SubDirectory => { TagTable => 'Image::ExifTool::FLIR::EmbeddedImage' }, + }, + 0x20 => { + Name => 'CameraInfo', # (BasicData - ref 3) + SubDirectory => { TagTable => 'Image::ExifTool::FLIR::CameraInfo' }, + }, + 0x21 => { #6 + Name => 'MeasurementInfo', + SubDirectory => { TagTable => 'Image::ExifTool::FLIR::MeasInfo' }, + }, + 0x22 => { + Name => 'PaletteInfo', # (ColorPal - ref 3) + SubDirectory => { TagTable => 'Image::ExifTool::FLIR::PaletteInfo' }, + }, + 0x23 => { + Name => 'TextInfo', + SubDirectory => { TagTable => 'Image::ExifTool::FLIR::TextInfo' }, + }, + 0x24 => { + Name => 'EmbeddedAudioFile', + # (sometimes has an unknown 8-byte header) + RawConv => q{ + return \$val if $val =~ s/^.{0,16}?RIFF/RIFF/s; + $self->Warn('Unknown EmbeddedAudioFile format'); + return undef; + }, + }, + # 0x27: 01 00 08 00 10 00 00 00 + 0x28 => { + Name => 'PaintData', + SubDirectory => { TagTable => 'Image::ExifTool::FLIR::PaintData' }, + }, + 0x2a => { + Name => 'PiP', + SubDirectory => { + TagTable => 'Image::ExifTool::FLIR::PiP', + ByteOrder => 'LittleEndian', + }, + }, + 0x2b => { + Name => 'GPSInfo', + SubDirectory => { + TagTable => 'Image::ExifTool::FLIR::GPSInfo', + ByteOrder => 'LittleEndian', + }, + }, + 0x2c => { + Name => 'MeterLink', + SubDirectory => { + TagTable => 'Image::ExifTool::FLIR::MeterLink' , + ByteOrder => 'LittleEndian' + }, + }, + 0x2e => { + Name => 'ParameterInfo', + SubDirectory => { TagTable => 'Image::ExifTool::FLIR::ParamInfo' }, + }, +); + +# FFF file header (ref PH) +%Image::ExifTool::FLIR::Header = ( + GROUPS => { 0 => 'APP1', 2 => 'Image' }, + PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData, + FIRST_ENTRY => 0, + NOTES => 'Tags extracted from the FLIR FFF/AFF header.', + 4 => { Name => 'CreatorSoftware', Format => 'string[16]' }, +); + +# FLIR raw data record (ref PH) +%Image::ExifTool::FLIR::RawData = ( + GROUPS => { 0 => 'APP1', 2 => 'Image' }, + PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData, + FORMAT => 'int16u', + FIRST_ENTRY => 0, + NOTES => q{ + The thermal image data may be stored either as raw data, or in PNG format. + If stored as raw data, ExifTool adds a TIFF header to allow the data to be + viewed as a TIFF image. If stored in PNG format, the PNG image is extracted + as-is. Note that most FLIR cameras using the PNG format seem to write the + 16-bit raw image data in the wrong byte order. + }, + 0x00 => { + # use this tag only to determine the byte order of the raw data + # (the value should be 0x0002 if the byte order is correct) + # - always "II" when RawThermalImageType is "TIFF" + # - seen both "II" and "MM" when RawThermalImageType is "PNG" + Name => 'RawDataByteOrder', + Hidden => 1, + RawConv => 'ToggleByteOrder() if $val >= 0x0100; undef', + }, + 0x01 => { + Name => 'RawThermalImageWidth', + RawConv => '$$self{RawThermalImageWidth} = $val', + }, + 0x02 => { + Name => 'RawThermalImageHeight', + RawConv => '$$self{RawThermalImageHeight} = $val', + }, + # 0x03-0x05: 0 + # 0x06: raw image width - 1 + # 0x07: 0 + # 0x08: raw image height - 1 + # 0x09: 0,15,16 + # 0x0a: 0,2,3,11,12,13,30 + # 0x0b: 0,2 + # 0x0c: 0 or a large number + # 0x0d: 0,3,4,6 + # 0x0e-0x0f: 0 + 16 => { + Name => 'RawThermalImageType', + Format => 'undef[$size-0x20]', + RawConv => 'Image::ExifTool::FLIR::GetImageType($self, $val, "RawThermalImage")', + }, + 16.1 => { + Name => 'RawThermalImage', + Groups => { 2 => 'Preview' }, + RawConv => '\$$self{RawThermalImage}', + }, +); + +# GainDeadMap record (ref 6) (see RawData above) +%Image::ExifTool::FLIR::GainDeadData = ( + GROUPS => { 0 => 'APP1', 2 => 'Image' }, + PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData, + FORMAT => 'int16u', + FIRST_ENTRY => 0, + NOTES => 'Information found in FFF-format .GAN calibration image files.', + 0x00 => { + Name => 'GainDeadMapByteOrder', + Hidden => 1, + RawConv => 'ToggleByteOrder() if $val >= 0x0100; undef', + }, + 0x01 => { + Name => 'GainDeadMapImageWidth', + RawConv => '$$self{GainDeadMapImageWidth} = $val', + }, + 0x02 => { + Name => 'GainDeadMapImageHeight', + RawConv => '$$self{GainDeadMapImageHeight} = $val', + }, + 16 => { + Name => 'GainDeadMapImageType', + Format => 'undef[$size-0x20]', + RawConv => 'Image::ExifTool::FLIR::GetImageType($self, $val, "GainDeadMapImage")', + }, + 16.1 => { + Name => 'GainDeadMapImage', + RawConv => '\$$self{GainDeadMapImage}', + }, +); + +# CoarseMap record (ref 6) (see RawData above) +%Image::ExifTool::FLIR::CoarseData = ( + GROUPS => { 0 => 'APP1', 2 => 'Image' }, + PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData, + FORMAT => 'int16u', + FIRST_ENTRY => 0, + NOTES => 'Information found in FFF-format .CRS correction image files.', + 0x00 => { + Name => 'CoarseMapByteOrder', + Hidden => 1, + RawConv => 'ToggleByteOrder() if $val >= 0x0100; undef', + }, + 0x01 => { + Name => 'CoarseMapImageWidth', + RawConv => '$$self{CoarseMapImageWidth} = $val', + }, + 0x02 => { + Name => 'CoarseMapImageHeight', + RawConv => '$$self{CoarseMapImageHeight} = $val', + }, + 16 => { + Name => 'CoarseMapImageType', + Format => 'undef[$size-0x20]', + RawConv => 'Image::ExifTool::FLIR::GetImageType($self, $val, "CoarseMapImage")', + }, + 16.1 => { + Name => 'CoarseMapImage', + RawConv => '\$$self{CoarseMapImage}', + }, +); + +# "Paint colors" record (ref PH) +%Image::ExifTool::FLIR::PaintData = ( + GROUPS => { 0 => 'APP1', 2 => 'Image' }, + PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData, + FORMAT => 'int16u', + FIRST_ENTRY => 0, + NOTES => 'Information generated by FLIR Tools "Paint colors" tool.', + 0x01 => { + Name => 'PaintByteOrder', + Hidden => 1, + RawConv => 'ToggleByteOrder() if $val >= 0x0100; undef', + }, + 0x05 => { + Name => 'PaintImageWidth', + RawConv => '$$self{PaintImageWidth} = $val', + }, + 0x06 => { + Name => 'PaintImageHeight', + RawConv => '$$self{PaintImageHeight} = $val', + }, + 20 => { + Name => 'PaintImageType', + Format => 'undef[$size-0x28]', + RawConv => 'Image::ExifTool::FLIR::GetImageType($self, $val, "PaintImage")', + }, + 20.1 => { + Name => 'PaintImage', + RawConv => '\$$self{PaintImage}', + }, +); + +# FLIR embedded image (ref 1) +%Image::ExifTool::FLIR::EmbeddedImage = ( + GROUPS => { 0 => 'APP1', 2 => 'Image' }, + PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData, + FORMAT => 'int16u', + FIRST_ENTRY => 0, + 0 => { + # use this tag only to determine the byte order + # (the value should be 0x0003 if the byte order is correct) + Name => 'EmbeddedImageByteOrder', + Format => 'int16u', + Hidden => 1, + RawConv => 'ToggleByteOrder() if $val >= 0x0100; undef', + }, + 1 => 'EmbeddedImageWidth', + 2 => 'EmbeddedImageHeight', + 16 => { + Name => 'EmbeddedImageType', + Format => 'undef[4]', + RawConv => '$val =~ /^\x89PNG/s ? "PNG" : ($val =~ /^\xff\xd8\xff/ ? "JPG" : "DAT")', + Notes => q{ + "PNG" for PNG image in Y Cb Cr colors, "JPG" for a JPEG image, or "DAT" for + other image data + }, + }, + 16.1 => { + Name => 'EmbeddedImage', + Groups => { 2 => 'Preview' }, + Format => 'undef[$size-0x20]', + Binary => 1, + }, +); + +# FLIR camera record (ref PH) +%Image::ExifTool::FLIR::CameraInfo = ( + GROUPS => { 0 => 'APP1', 2 => 'Camera' }, + PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData, + FIRST_ENTRY => 0, + NOTES => q{ + FLIR camera information. The Planck tags are variables used in the + temperature calculation. See + L<http://u88.n24.queensu.ca/exiftool/forum/index.php?topic=4898.msg23972#msg23972> + for details. + }, + 0x00 => { + # use this tag only to determine the byte order + # (the value should be 0x0002 if the byte order is correct) + Name => 'CameraInfoByteOrder', + Format => 'int16u', + Hidden => 1, + RawConv => 'ToggleByteOrder() if $val >= 0x0100; undef', + }, + # 0x02 - int16u: image width + # 0x04 - int16u: image height + # 0x0c - int32u: image width - 1 + # 0x10 - int32u: image height - 1 + 0x20 => { Name => 'Emissivity', %float2f }, + 0x24 => { Name => 'ObjectDistance', Format => 'float', PrintConv => 'sprintf("%.2f m",$val)' }, + 0x28 => { Name => 'ReflectedApparentTemperature', %floatKelvin }, + 0x2c => { Name => 'AtmosphericTemperature', %floatKelvin }, + 0x30 => { Name => 'IRWindowTemperature', %floatKelvin }, + 0x34 => { Name => 'IRWindowTransmission', %float2f }, + # 0x38: 0 + 0x3c => { + Name => 'RelativeHumidity', + Format => 'float', + ValueConv => '$val > 2 ? $val / 100 : $val', # have seen value expressed as percent in FFF file + PrintConv => 'sprintf("%.1f %%",$val*100)', + }, + # 0x40 - float: 0,6 + # 0x44,0x48,0x4c: 0 + # 0x50 - int32u: 1 + # 0x54: 0 + 0x58 => { Name => 'PlanckR1', %float8g }, #1 + 0x5c => { Name => 'PlanckB', %float8g }, #1 + 0x60 => { Name => 'PlanckF', %float8g }, #1 + # 0x64,0x68,0x6c: 0 + 0x070 => { Name => 'AtmosphericTransAlpha1', %float6f }, #1 (value: 0.006569) + 0x074 => { Name => 'AtmosphericTransAlpha2', %float6f }, #1 (value: 0.012620) + 0x078 => { Name => 'AtmosphericTransBeta1', %float6f }, #1 (value: -0.002276) + 0x07c => { Name => 'AtmosphericTransBeta2', %float6f }, #1 (value: -0.006670) + 0x080 => { Name => 'AtmosphericTransX', %float6f }, #1 (value: 1.900000) + # 0x84,0x88: 0 + # 0x8c - float: 0,4,6 + 0x90 => { Name => 'CameraTemperatureRangeMax', %floatKelvin }, + 0x94 => { Name => 'CameraTemperatureRangeMin', %floatKelvin }, + 0x98 => { Name => 'CameraTemperatureMaxClip', %floatKelvin }, # 50 degrees over camera max + 0x9c => { Name => 'CameraTemperatureMinClip', %floatKelvin }, # usually 10 or 20 degrees below camera min + 0xa0 => { Name => 'CameraTemperatureMaxWarn', %floatKelvin }, # same as camera max + 0xa4 => { Name => 'CameraTemperatureMinWarn', %floatKelvin }, # same as camera min + 0xa8 => { Name => 'CameraTemperatureMaxSaturated', %floatKelvin }, # usually 50 or 88 degrees over camera max + 0xac => { Name => 'CameraTemperatureMinSaturated', %floatKelvin }, # usually 10, 20 or 40 degrees below camera min + 0xd4 => { Name => 'CameraModel', Format => 'string[32]' }, + 0xf4 => { Name => 'CameraPartNumber', Format => 'string[16]' }, #1 + 0x104 => { Name => 'CameraSerialNumber',Format => 'string[16]' }, #1 + 0x114 => { Name => 'CameraSoftware', Format => 'string[16]' }, #1/PH (NC) + 0x170 => { Name => 'LensModel', Format => 'string[32]' }, + # note: it seems that FLIR updated their lenses at some point, so lenses with the same + # name may have different part numbers (eg. the FOL38 is either 1196456 or T197089) + 0x190 => { Name => 'LensPartNumber', Format => 'string[16]' }, + 0x1a0 => { Name => 'LensSerialNumber', Format => 'string[16]' }, + 0x1b4 => { Name => 'FieldOfView', Format => 'float', PrintConv => 'sprintf("%.1f deg", $val)' }, #1 + # 0x1d0 - int16u: 0,12,24,25,46 + # 0x1d2 - int16u: 170,180,190,380,760,52320 + 0x1ec => { Name => 'FilterModel', Format => 'string[16]' }, + 0x1fc => { Name => 'FilterPartNumber', Format => 'string[32]' }, + 0x21c => { Name => 'FilterSerialNumber',Format => 'string[32]' }, + 0x308 => { Name => 'PlanckO', Format => 'int32s' }, #1 + 0x30c => { Name => 'PlanckR2', %float8g }, #1 + 0x338 => { Name => 'RawValueMedian', Format => 'int16u', Groups => { 2 => 'Image' } }, + 0x33c => { Name => 'RawValueRange', Format => 'int16u', Groups => { 2 => 'Image' } }, + 0x384 => { + Name => 'DateTimeOriginal', + Description => 'Date/Time Original', + Format => 'undef[10]', + Groups => { 2 => 'Time' }, + RawConv => q{ + my $tm = Get32u(\$val, 0); + my $ss = Get32u(\$val, 4) & 0xffff; + my $tz = Get16s(\$val, 8); + ConvertUnixTime($tm - $tz * 60) . sprintf('.%.3d', $ss) . TimeZoneString(-$tz); + }, + PrintConv => '$self->ConvertDateTime($val)', + }, + 0x390 => { Name => 'FocusStepCount', Format => 'int16u' }, + 0x45c => { Name => 'FocusDistance', Format => 'float', PrintConv => 'sprintf("%.1f m",$val)' }, + # 0x43c - string: either "Live" or the file name + 0x464 => { Name => 'FrameRate', Format => 'int16u' }, #SebastianHani +); + +# FLIR measurement tools record (ref 6) +%Image::ExifTool::FLIR::MeasInfo = ( + GROUPS => { 0 => 'APP1', 2 => 'Image' }, + PROCESS_PROC => \&ProcessMeasInfo, + FORMAT => 'int16u', + VARS => { NO_ID => 1 }, + NOTES => q{ + Tags listed below are only for the first measurement tool, however multiple + measurements may be added, and information is extracted for all of them. + Tags for subsequent measurements are generated as required with the prefixes + "Meas2", "Meas3", etc. + }, + Meas1Type => { + PrintConv => { + 1 => 'Spot', + 2 => 'Area', + 3 => 'Ellipse', + 4 => 'Line', + 5 => 'Endpoint', #PH (NC, FLIR Tools v2.0 for Mac generates an empty one of these after each Line) + 6 => 'Alarm', #PH seen params: "0 1 0 1 9142 0 9142 0" (called "Isotherm" by Mac version) + 7 => 'Unused', #PH (NC) (or maybe "Free"?) + 8 => 'Difference', + }, + }, + Meas1Params => { + Notes => 'Spot=X,Y; Area=X1,Y1,W,H; Ellipse=XC,YC,X1,Y1,X2,Y2; Line=X1,Y1,X2,Y2', + }, + Meas1Label => { }, +); + +# FLIR palette record (ref PH/JD) +%Image::ExifTool::FLIR::PaletteInfo = ( + GROUPS => { 0 => 'APP1', 2 => 'Image' }, + PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData, + FIRST_ENTRY => 0, + 0x00 => { #JD + Name => 'PaletteColors', + RawConv => '$$self{PaletteColors} = $val', + }, + 0x06 => { Name => 'AboveColor', Format => 'int8u[3]', Notes => 'Y Cr Cb color components' }, #JD + 0x09 => { Name => 'BelowColor', Format => 'int8u[3]' }, #JD + 0x0c => { Name => 'OverflowColor', Format => 'int8u[3]' }, #JD + 0x0f => { Name => 'UnderflowColor', Format => 'int8u[3]' }, #JD + 0x12 => { Name => 'Isotherm1Color', Format => 'int8u[3]' }, #JD + 0x15 => { Name => 'Isotherm2Color', Format => 'int8u[3]' }, #JD + 0x1a => { Name => 'PaletteMethod' }, #JD + 0x1b => { Name => 'PaletteStretch' }, #JD + 0x30 => { + Name => 'PaletteFileName', + Format => 'string[32]', + # (not valid for all images) + RawConv => q{ + $val =~ s/\0.*//; + $val =~ /^[\x20-\x7e]{3,31}$/ ? $val : undef; + }, + }, + 0x50 => { + Name => 'PaletteName', + Format => 'string[32]', + # (not valid for all images) + RawConv => q{ + $val =~ s/\0.*//; + $val =~ /^[\x20-\x7e]{3,31}$/ ? $val : undef; + }, + }, + 0x70 => { + Name => 'Palette', + Format => 'undef[3*$$self{PaletteColors}]', + Notes => 'Y Cr Cb byte values for each palette color', + Binary => 1, + }, +); + +# FLIR text information record (ref PH) +%Image::ExifTool::FLIR::TextInfo = ( + GROUPS => { 0 => 'APP1', 2 => 'Image' }, + PROCESS_PROC => \&ProcessFLIRText, + VARS => { NO_ID => 1 }, + Label0 => { }, + Value0 => { }, + Label1 => { }, + Value1 => { }, + Label2 => { }, + Value2 => { }, + Label3 => { }, + Value3 => { }, + # (there could be more, and we will generate these on the fly if necessary) +); + +# FLIR parameter information record (ref PH) +%Image::ExifTool::FLIR::ParamInfo = ( + GROUPS => { 0 => 'APP1', 2 => 'Image' }, + PROCESS_PROC => \&ProcessFLIRText, + VARS => { NO_ID => 1 }, + Generated => { + Name => 'DateTimeGenerated', + Description => 'Date/Time Generated', + Groups => { 2 => 'Time' }, + ValueConv => '$val =~ tr/-/:/; $val', + PrintConv => '$self->ConvertDateTime($val)', + }, + Param0 => { }, + Param1 => { }, + Param2 => { }, + Param3 => { }, + # (there could be more, and we will generate these on the fly if necessary) +); + +# FLIR Picture in Picture record (ref 1) +%Image::ExifTool::FLIR::PiP = ( + GROUPS => { 0 => 'APP1', 2 => 'Image' }, + PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData, + FIRST_ENTRY => 0, + NOTES => 'FLIR Picture in Picture tags.', + FORMAT => 'int16s', + 0x00 => { + Name => 'Real2IR', + Format => 'float', + }, + 2 => { + Name => 'OffsetX', + Notes => 'offset from of insertion point from center', + PrintConv => 'sprintf("%+d",$val)', # (add sign for direct use with IM convert) + }, + 3 => { + Name => 'OffsetY', + PrintConv => 'sprintf("%+d",$val)', + }, + 4 => { + Name => 'PiPX1', + Description => 'PiP X1', + Notes => 'crop size for radiometric image', + }, + 5 => { Name => 'PiPX2', Description => 'PiP X2' }, + 6 => { Name => 'PiPY1', Description => 'PiP Y1' }, + 7 => { Name => 'PiPY2', Description => 'PiP Y2' }, +); + +# FLIR GPS record (ref PH/JD/forum9615) +%Image::ExifTool::FLIR::GPSInfo = ( + GROUPS => { 0 => 'APP1', 2 => 'Location' }, + PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData, + FIRST_ENTRY => 0, + 0x00 => { + Name => 'GPSValid', + Format => 'int32u', + RawConv => '$$self{GPSValid} = $val', + PrintConv => { 0 => 'No', 1 => 'Yes' }, + }, + 0x04 => { + Name => 'GPSVersionID', + Format => 'undef[4]', + RawConv => '$val eq "\0\0\0\0" ? undef : $val', + PrintConv => 'join ".", split //, $val', + }, + 0x08 => { + Name => 'GPSLatitudeRef', + Format => 'string[2]', + RawConv => 'length($val) ? $val : undef', + PrintConv => { + N => 'North', + S => 'South', + }, + }, + 0x0a => { + Name => 'GPSLongitudeRef', + Format => 'string[2]', + RawConv => 'length($val) ? $val : undef', + PrintConv => { + E => 'East', + W => 'West', + }, + }, + # 0x0c - 4 unknown bytes + 0x10 => { + Name => 'GPSLatitude', + Condition => '$$self{GPSValid}', # valid only if GPSValid is 1 + Format => 'double', # (signed) + PrintConv => 'Image::ExifTool::GPS::ToDMS($self, $val, 1, "N")', + }, + 0x18 => { + Name => 'GPSLongitude', + Condition => '$$self{GPSValid}', # valid only if GPSValid is 1 + Format => 'double', # (signed) + PrintConv => 'Image::ExifTool::GPS::ToDMS($self, $val, 1, "E")', + }, + 0x20 => { + Name => 'GPSAltitude', + Condition => '$$self{GPSValid}', # valid only if GPSValid is 1 + Format => 'float', + # (have seen likely invalid value of -1 when GPSValid is 1) + PrintConv => 'sprintf("%.2f m", $val)', + }, + # 0x24 - 28 unknown bytes: + # 0x28 - int8u: seen 0,49,51,55,57 (ASCII "1","3","7","9") + # 0x29 - int8u: seen 0,48 (ASCII "0") + 0x40 => { + Name => 'GPSDOP', + Description => 'GPS Dilution Of Precision', + Format => 'float', + RawConv => '$val > 0 ? $val : undef', # (have also seen likely invalid value of 1) + PrintConv => 'sprintf("%.2f", $val)', + }, + 0x44 => { + Name => 'GPSSpeedRef', + Format => 'string[2]', + RawConv => 'length($val) ? $val : undef', + PrintConv => { + K => 'km/h', + M => 'mph', + N => 'knots', + }, + }, + 0x46 => { + Name => 'GPSTrackRef', + Format => 'string[2]', + RawConv => 'length($val) ? $val : undef', + PrintConv => { + M => 'Magnetic North', + T => 'True North', + }, + }, + # 0x48 - int32u: seen 0,77 + 0x4c => { + Name => 'GPSSpeed', + %float2f, + RawConv => '$val < 0 ? undef : $val', + }, + 0x50 => { + Name => 'GPSTrack', + %float2f, + RawConv => '$val < 0 ? undef : $val', + }, + # 0x54 - float: seen 0,-1 + 0x58 => { + Name => 'GPSMapDatum', + Format => 'string[16]', + RawConv => 'length($val) ? $val : undef', + }, + # 0xa4 - string[6]: seen 000208,081210,020409,000608,010408,020808,091011 + # 0x78 - double[2]: seen "-1 -1","0 0" + # 0x78 - float[2]: seen "-1 -1","0 0" + # 0xb2 - string[2]?: seen "5\0" +); + +# humidity meter information +# (ref http://u88.n24.queensu.ca/exiftool/forum/index.php/topic,5325.0.html) +# The %Image::ExifTool::UserDefined hash defines new tags to be added to existing tables. +%Image::ExifTool::FLIR::MeterLink = ( + GROUPS => { 0 => 'APP1', 2 => 'Image' }, + PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData, + FIRST_ENTRY => 0, + NOTES => 'Tags containing Meterlink humidity meter information.', + 26 => { + Name => 'Reading1Units', + DataMember => 'Reading1Units', + RawConv => '$$self{Reading1Units} = $val', + PrintHex => 1, + PrintConv => { + 0x0d => 'C', + 0x1b => '%', + 0x1d => 'Relative', + 0x24 => 'g/kg', + }, + }, + 28 => { + Name => 'Reading1Description', + DataMember => 'Reading1Description', + RawConv => '$$self{Reading1Description} = $val', + PrintConv => { + 0 => 'Humidity', + 3 => 'Moisture', # Pinless Moisture Readings with INTernal sensor + 7 => 'Dew Point', + 8 => 'Air Temperature', + 9 => 'IR Temperature', + 11 => 'Difference Temperature', # Difference Temp: IR-Temp and DewPoint + }, + }, + 32 => { + Name => 'Reading1Device', + Format => 'string[16]', + }, + 96 => { + Name => 'Reading1Value', + Format => 'double', + # convert Kelvin -> Celcius and kg/kg -> g/kg + ValueConv => q{ + return $val - 273.15 if $$self{Reading1Units} == 0x0d and $$self{Reading1Description} != 11; + return $val *= 1000 if $$self{Reading1Units} == 0x24; + return $val; + }, + }, + # add 100 for subsequent readings + 126 => { + Name => 'Reading2Units', + DataMember => 'Reading2Units', + RawConv => '$$self{Reading2Units} = $val', + PrintHex => 1, + PrintConv => { + 0x0d => 'C', + 0x1b => '%', + 0x1d => 'rel', + 0x24 => 'g/kg', + }, + }, + 128 => { + Name => 'Reading2Description', + DataMember => 'Reading2Description', + RawConv => '$$self{Reading2Description} = $val', + PrintConv => { + 0 => 'Humidity', + 3 => 'Moisture', + 7 => 'Dew Point', + 8 => 'Air Temperature', + 9 => 'IR Temperature', + 11 => 'Difference Temperature', # Difference Temp: IR-Temp and DewPoint + }, + }, + 132 => { + Name => 'Reading2Device', + Format => 'string[16]', + }, + 196 => { + Name => 'Reading2Value', + Format => 'double', + # convert Kelvin -> Celcius and kg/kg -> g/kg + ValueConv => q{ + return $val - 273.15 if $$self{Reading2Units} == 0x0d and $$self{Reading2Description} != 11; + return $val *= 1000 if $$self{Reading2Units} == 0x24; + return $val; + }, + }, + 226 => { + Name => 'Reading3Units', + DataMember => 'Reading3Units', + RawConv => '$$self{Reading3Units} = $val', + PrintHex => 1, + PrintConv => { + 0x0d => 'C', + 0x1b => '%', + 0x1d => 'rel', + 0x24 => 'g/kg', + }, + }, + 228 => { + Name => 'Reading3Description', + DataMember => 'Reading3Description', + RawConv => '$$self{Reading3Description} = $val', + PrintConv => { + 0 => 'Humidity', + 3 => 'Moisture', + 7 => 'Dew Point', + 8 => 'Air Temperature', + 9 => 'IR Temperature', + 11 => 'Difference Temperature', # Difference Temp: IR-Temp and DewPoint + }, + }, + 232 => { + Name => 'Reading3Device', + Format => 'string[16]', + }, + 296 => { + Name => 'Reading3Value', + Format => 'double', + # convert Kelvin -> Celcius and kg/kg -> g/kg + ValueConv => q{ + return $val - 273.15 if $$self{Reading3Units} == 0x0d and $$self{Reading3Description} != 11; + return $val *= 1000 if $$self{Reading3Units} == 0x24; + return $val; + }, + }, + + 326 => { + Name => 'Reading4Units', + DataMember => 'Reading4Units', + RawConv => '$$self{Reading4Units} = $val', + PrintHex => 1, + PrintConv => { + 0x0d => 'C', + 0x1b => '%', + 0x1d => 'rel', + 0x24 => 'g/kg', + }, + }, + 328 => { + Name => 'Reading4Description', + DataMember => 'Reading4Description', + RawConv => '$$self{Reading4Description} = $val', + PrintConv => { + 0 => 'Humidity', + 3 => 'Moisture', + 7 => 'Dew Point', + 8 => 'Air Temperature', + 9 => 'IR Temperature', + 11 => 'Difference Temperature', # Difference Temp: IR-Temp and DewPoint + }, + }, + 332 => { + Name => 'Reading4Device', + Format => 'string[16]', + }, + 396 => { + Name => 'Reading4Value', + Format => 'double', + # convert Kelvin -> Celcius and kg/kg -> g/kg + ValueConv => q{ + return $val - 273.15 if $$self{Reading4Units} == 0x0d and $$self{Reading4Description} != 11; + return $val *= 1000 if $$self{Reading4Units} == 0x24; + return $val; + }, + }, +); + +# FLIR public image format (ref 4/5) +%Image::ExifTool::FLIR::FPF = ( + GROUPS => { 0 => 'FLIR', 2 => 'Image' }, + PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData, + NOTES => 'Tags extracted from FLIR Public image Format (FPF) files.', + 0x20 => { Name => 'FPFVersion', Format => 'int32u' }, + 0x24 => { Name => 'ImageDataOffset', Format => 'int32u' }, + 0x28 => { + Name => 'ImageType', + Format => 'int16u', + PrintConv => { + 0 => 'Temperature', + 1 => 'Temperature Difference', + 2 => 'Object Signal', + 3 => 'Object Signal Difference', + }, + }, + 0x2a => { + Name => 'ImagePixelFormat', + Format => 'int16u', + PrintConv => { + 0 => '2-byte short integer', + 1 => '4-byte long integer', + 2 => '4-byte float', + 3 => '8-byte double', + }, + }, + 0x2c => { Name => 'ImageWidth', Format => 'int16u' }, + 0x2e => { Name => 'ImageHeight', Format => 'int16u' }, + 0x30 => { Name => 'ExternalTriggerCount',Format => 'int32u' }, + 0x34 => { Name => 'SequenceFrameNumber',Format => 'int32u' }, + 0x78 => { Name => 'CameraModel', Format => 'string[32]', Groups => { 2 => 'Camera' } }, + 0x98 => { Name => 'CameraPartNumber', Format => 'string[32]', Groups => { 2 => 'Camera' } }, + 0xb8 => { Name => 'CameraSerialNumber', Format => 'string[32]', Groups => { 2 => 'Camera' } }, + 0xd8 => { Name => 'CameraTemperatureRangeMin', %floatKelvin, Groups => { 2 => 'Camera' } }, + 0xdc => { Name => 'CameraTemperatureRangeMax', %floatKelvin, Groups => { 2 => 'Camera' } }, + 0xe0 => { Name => 'LensModel', Format => 'string[32]', Groups => { 2 => 'Camera' } }, + 0x100 => { Name => 'LensPartNumber', Format => 'string[32]', Groups => { 2 => 'Camera' } }, + 0x120 => { Name => 'LensSerialNumber', Format => 'string[32]', Groups => { 2 => 'Camera' } }, + 0x140 => { Name => 'FilterModel', Format => 'string[32]', Groups => { 2 => 'Camera' } }, + 0x150 => { Name => 'FilterPartNumber', Format => 'string[32]', Groups => { 2 => 'Camera' } }, + 0x180 => { Name => 'FilterSerialNumber',Format => 'string[32]', Groups => { 2 => 'Camera' } }, + 0x1e0 => { Name => 'Emissivity', %float2f }, + 0x1e4 => { Name => 'ObjectDistance', Format => 'float', PrintConv => 'sprintf("%.2f m",$val)' }, + 0x1e8 => { Name => 'ReflectedApparentTemperature', %floatKelvin }, + 0x1ec => { Name => 'AtmosphericTemperature', %floatKelvin }, + 0x1f0 => { Name => 'RelativeHumidity', Format => 'float', PrintConv => 'sprintf("%.1f %%",$val*100)' }, + 0x1f4 => { Name => 'ComputedAtmosphericTrans', %float2f }, + 0x1f8 => { Name => 'EstimatedAtmosphericTrans',%float2f }, + 0x1fc => { Name => 'ReferenceTemperature', %floatKelvin }, + 0x200 => { Name => 'IRWindowTemperature', %floatKelvin, Groups => { 2 => 'Camera' } }, + 0x204 => { Name => 'IRWindowTransmission', %float2f, Groups => { 2 => 'Camera' } }, + 0x248 => { + Name => 'DateTimeOriginal', + Description => 'Date/Time Original', + Groups => { 2 => 'Time' }, + Format => 'int32u[7]', + ValueConv => 'sprintf("%.4d:%.2d:%.2d %.2d:%.2d:%.2d.%.3d",split(" ",$val))', + PrintConv => '$self->ConvertDateTime($val)', + }, + # Notes (based on ref 4): + # 1) The above date/time structure is documented to be 32 bytes for FPFVersion 1, but in + # fact it is only 28. Maybe this is why the full header length of my FPFVersion 2 + # sample is 892 bytes instead of 896. If this was a documentation error, we are OK, + # but if the alignment was really different in version 1, then the temperatures below + # will be mis-aligned. I don't have any version 1 samples to check this. + # 2) The following temperatures may not always be in Kelvin + 0x2a4 => { Name => 'CameraScaleMin', %float1f }, + 0x2a8 => { Name => 'CameraScaleMax', %float1f }, + 0x2ac => { Name => 'CalculatedScaleMin',%float1f }, + 0x2b0 => { Name => 'CalculatedScaleMax',%float1f }, + 0x2b4 => { Name => 'ActualScaleMin', %float1f }, + 0x2b8 => { Name => 'ActualScaleMax', %float1f }, +); + +# top-level user data written by FLIR cameras in MP4 videos +%Image::ExifTool::FLIR::UserData = ( + GROUPS => { 1 => 'FLIR', 2 => 'Camera' }, + NOTES => q{ + Tags written by some FLIR cameras in a top-level (!) "udta" atom of MP4 + videos. + }, + uuid => [ + { + Name => 'FLIR_Parts', + Condition => '$$valPt=~/^\x43\xc3\x99\x3b\x0f\x94\x42\x4b\x82\x05\x6b\x66\x51\x3f\x48\x5d/s', + SubDirectory => { + TagTable => 'Image::ExifTool::FLIR::Parts', + Start => 16, + }, + }, + { + Name => 'FLIR_Serial', + Condition => '$$valPt=~/^\x57\xf5\xb9\x3e\x51\xe4\x48\xaf\xa0\xd9\xc3\xef\x1b\x37\xf7\x12/s', + SubDirectory => { + TagTable => 'Image::ExifTool::FLIR::SerialNums', + Start => 16, + }, + }, + { + Name => 'FLIR_Params', + Condition => '$$valPt=~/^\x41\xe5\xdc\xf9\xe8\x0a\x41\xce\xad\xfe\x7f\x0c\x58\x08\x2c\x19/s', + SubDirectory => { + TagTable => 'Image::ExifTool::FLIR::Params', + Start => 16, + }, + }, + { + Name => 'FLIR_UnknownUUID', + Condition => '$$valPt=~/^\x57\x45\x20\x50\x2c\xbb\x44\xad\xae\x54\x15\xe9\xb8\x39\xd9\x03/s', + SubDirectory => { + TagTable => 'Image::ExifTool::FLIR::UnknownUUID', + Start => 16, + }, + }, + { + Name => 'FLIR_GPS', + Condition => '$$valPt=~/^\x7f\x2e\x21\x00\x8b\x46\x49\x18\xaf\xb1\xde\x70\x9a\x74\xf6\xf5/s', + SubDirectory => { + TagTable => 'Image::ExifTool::FLIR::GPS_UUID', + Start => 16, + }, + }, + { + Name => 'FLIR_MoreInfo', + Condition => '$$valPt=~/^\x2b\x45\x2f\xdc\x74\x35\x40\x94\xba\xee\x22\xa6\xb2\x3a\x7c\xf8/s', + SubDirectory => { + TagTable => 'Image::ExifTool::FLIR::MoreInfo', + Start => 16, + }, + }, + { + Name => 'SoftwareComponents', + Condition => '$$valPt=~/^\x78\x3f\xc7\x83\x0c\x95\x4b\x00\x8c\xc7\xac\xf1\xec\xb4\xd3\x9a/s', + Unknown => 1, + ValueConv => 'join " ", unpack "x20N4xZ*", $val', + }, + { + Name => 'FLIR_Unknown', + Condition => '$$valPt=~/^\x52\xae\xda\x45\x17\x1e\x48\xb1\x92\x47\x93\xa4\x21\x4e\x43\xf5/s', + Unknown => 1, + ValueConv => 'unpack "x20C*", $val', + }, + { + Name => 'Units', + Condition => '$$valPt=~/^\xf8\xab\x72\x1e\x84\x73\x44\xa0\xb8\xc8\x1b\x04\x82\x6e\x07\x24/s', + List => 1, + RawConv => 'my @a = split "\0", substr($val, 20); \@a', + }, + { + Name => 'ThumbnailImage', + Groups => { 2 => 'Preview' }, + Condition => '$$valPt=~/^\x91\xaf\x9b\x93\x45\x9b\x44\x56\x98\xd1\x5e\x76\xea\x01\x04\xac....\xff\xd8\xff/s', + RawConv => 'substr($val, 20)', + Binary => 1, + }, + ], +); + +# uuid 43c3993b0f94424b82056b66513f485d box of MP4 videos (ref PH) +%Image::ExifTool::FLIR::Parts = ( + GROUPS => { 0 => 'MakerNotes', 1 => 'FLIR', 2 => 'Camera' }, + PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData, + FORMAT => 'undef', + NOTES => q{ + Tags extracted from the "uuid" box with ID 43c3993b0f94424b82056b66513f485d + in FLIR MP4 videos. + }, + 4 => [ + { + Name => 'BAHPVer', + Condition => '$$valPt =~ /^bahpver\0/', + Format => 'undef[$size]', + RawConv => 'join " ", split "\0", substr($val, 8)', + }, + { + Name => 'BALPVer', + Condition => '$$valPt =~ /^balpver\0/', + Format => 'undef[$size]', + ValueConv => 'join " ", split "\0", substr($val, 8)', + }, + { + Name => 'Battery', + Condition => '$$valPt =~ /^battery\0/', + Format => 'undef[$size]', + ValueConv => 'join " ", split "\0", substr($val, 8)', + }, + { + Name => 'BAVPVer', + Condition => '$$valPt =~ /^bavpver\0/', + Format => 'undef[$size]', + ValueConv => 'join " ", split "\0", substr($val, 8)', + # (the first string corresponds with a lens part number) + }, + { + Name => 'CamCore', + Condition => '$$valPt =~ /^camcore\0/', + Format => 'undef[$size]', + ValueConv => 'join " ", split "\0", substr($val, 8)', + }, + { + Name => 'DetectorBoard', + Condition => '$$valPt =~ /^det_board\0/', + Format => 'undef[$size]', + ValueConv => 'join " ", split "\0", substr($val, 10)', + }, + { + Name => 'Detector', + Condition => '$$valPt =~ /^detector\0/', + Format => 'undef[$size]', + ValueConv => 'join " ", split "\0", substr($val, 9)', + }, + { + Name => 'GIDCVer', + Condition => '$$valPt =~ /^gidcver\0/', + Format => 'undef[$size]', + ValueConv => 'join " ", split "\0", substr($val, 8)', + }, + { + Name => 'GIDPVer', + Condition => '$$valPt =~ /^gidpver\0/', + Format => 'undef[$size]', + ValueConv => 'join " ", split "\0", substr($val, 8)', + }, + { + Name => 'GIPC_CPLD', + Condition => '$$valPt =~ /^gipccpld\0/', + Format => 'undef[$size]', + ValueConv => 'join " ", split "\0", substr($val, 9)', + }, + { + Name => 'GIPCVer', + Condition => '$$valPt =~ /^gipcver\0/', + Format => 'undef[$size]', + ValueConv => 'join " ", split "\0", substr($val, 8)', + }, + { + Name => 'GIXIVer', + Condition => '$$valPt =~ /^gixiver\0/', + Format => 'undef[$size]', + ValueConv => 'join " ", split "\0", substr($val, 8)', + }, + { + Name => 'MainBoard', + Condition => '$$valPt =~ /^mainboard\0/', + Format => 'undef[$size]', + ValueConv => 'join " ", split "\0", substr($val, 10)', + }, + { + Name => 'Optics', + Condition => '$$valPt =~ /^optics\0/', + Format => 'undef[$size]', + ValueConv => 'join " ", split "\0", substr($val, 7)', + }, + { + Name => 'PartNumber', + Format => 'undef[$size]', + ValueConv => 'join " ", split "\0", $val', + }, + ], +); + +# uuid 57f5b93e51e448afa0d9c3ef1b37f712 box of MP4 videos (ref PH) +%Image::ExifTool::FLIR::SerialNums = ( + GROUPS => { 0 => 'MakerNotes', 1 => 'FLIR', 2 => 'Camera' }, + PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData, + FIRST_ENTRY => 0, + NOTES => q{ + Tags extracted from the "uuid" box with ID 57f5b93e51e448afa0d9c3ef1b37f712 + in FLIR MP4 videos. + }, + # (not sure if these offsets are constant) + 0x0c => { Name => 'UnknownSerial1', Format => 'string[33]', Unknown => 1 }, + 0x2d => { Name => 'UnknownSerial2', Format => 'string[33]', Unknown => 1 }, + 0x4e => { Name => 'UnknownSerial3', Format => 'string[33]', Unknown => 1 }, + 0x6f => { Name => 'UnknownSerial4', Format => 'string[11]', Unknown => 1 }, + 0x7b => { Name => 'UnknownNumber', Format => 'string[3]', Unknown => 1 }, + 0x7e => { Name => 'CameraSerialNumber', Format => 'string[9]' }, +); + +# uuid 41e5dcf9e80a41ceadfe7f0c58082c19 box of MP4 videos (ref PH) +%Image::ExifTool::FLIR::Params = ( + GROUPS => { 0 => 'MakerNotes', 1 => 'FLIR', 2 => 'Camera' }, + PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData, + FORMAT => 'float', + FIRST_ENTRY => 0, + NOTES => q{ + Tags extracted from the "uuid" box with ID 41e5dcf9e80a41ceadfe7f0c58082c19 + in FLIR MP4 videos. + }, + 1 => { Name => 'ReflectedApparentTemperature', %floatKelvin }, + 2 => { Name => 'AtmosphericTemperature', %floatKelvin }, + 3 => { Name => 'Emissivity', %float2f }, + 4 => { Name => 'ObjectDistance', PrintConv => 'sprintf("%.2f m",$val)' }, + 5 => { Name => 'RelativeHumidity', PrintConv => 'sprintf("%.1f %%",$val*100)' }, + 6 => { Name => 'EstimatedAtmosphericTrans', %float2f }, + 7 => { Name => 'IRWindowTemperature', %floatKelvin }, + 8 => { Name => 'IRWindowTransmission', %float2f }, +); + +# uuid 574520502cbb44adae5415e9b839d903 box of MP4 videos (ref PH) +%Image::ExifTool::FLIR::UnknownUUID = ( + GROUPS => { 0 => 'MakerNotes', 1 => 'FLIR', 2 => 'Camera' }, + PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData, + FORMAT => 'float', + FIRST_ENTRY => 0, + NOTES => q{ + Tags extracted from the "uuid" box with ID 574520502cbb44adae5415e9b839d903 + in FLIR MP4 videos. + }, + # 1 - 1 + # 2 - 0 + # 3 - 0 +); + +# uuid 7f2e21008b464918afb1de709a74f6f5 box of MP4 videos (ref PH) +%Image::ExifTool::FLIR::GPS_UUID = ( + GROUPS => { 0 => 'MakerNotes', 1 => 'FLIR', 2 => 'Location' }, + PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData, + FORMAT => 'float', + FIRST_ENTRY => 0, + NOTES => q{ + Tags extracted from the "uuid" box with ID 7f2e21008b464918afb1de709a74f6f5 + in FLIR MP4 videos. + }, + 1 => { + Name => 'GPSLatitude', + PrintConv => 'Image::ExifTool::GPS::ToDMS($self, $val, 1, "N")', + }, + 2 => { + Name => 'GPSLongitude', + PrintConv => 'Image::ExifTool::GPS::ToDMS($self, $val, 1, "E")', + }, + 3 => { + Name => 'GPSAltitude', + PrintConv => '$val=int($val*100+0.5)/100;"$val m"', + }, + # 4 - int32u: 0x0001bf74 + # 5 - int32u: 0 + # 6 - int32u: 1 +); + +# uuid 2b452fdc74354094baee22a6b23a7cf8 box of MP4 videos (ref PH) +%Image::ExifTool::FLIR::MoreInfo = ( + GROUPS => { 0 => 'MakerNotes', 1 => 'FLIR', 2 => 'Camera' }, + PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData, + FIRST_ENTRY => 0, + NOTES => q{ + Tags extracted from the "uuid" box with ID 2b452fdc74354094baee22a6b23a7cf8 + in FLIR MP4 videos. + }, + 5 => { Name => 'LensModel', Format => 'string[6]' }, + 11 => { Name => 'UnknownTemperature1', %floatKelvin, Unknown => 1 }, # (-14.9 C) + 15 => { Name => 'UnknownTemperature2', %floatKelvin, Unknown => 1 }, # (60.0 C) +); + +# FLIR AFF tag table (ref PH) +%Image::ExifTool::FLIR::AFF = ( + GROUPS => { 0 => 'FLIR', 1 => 'FLIR', 2 => 'Image' }, + NOTES => 'Tags extracted from FLIR "AFF" SEQ images.', + VARS => { ALPHA_FIRST => 1 }, + "_header" => { + Name => 'AFFHeader', + SubDirectory => { TagTable => 'Image::ExifTool::FLIR::Header' }, + }, + 0x01 => { + Name => 'AFF1', + SubDirectory => { TagTable => 'Image::ExifTool::FLIR::AFF1' }, + }, + 0x05 => { + Name => 'AFF5', + SubDirectory => { TagTable => 'Image::ExifTool::FLIR::AFF5' }, + }, +); + +# AFF record type 1 (ref forum?topic=4898.msg27627) +%Image::ExifTool::FLIR::AFF1 = ( + GROUPS => { 0 => 'FLIR', 1 => 'FLIR', 2 => 'Camera' }, + PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData, + FORMAT => 'int16u', + FIRST_ENTRY => 0, + 0x00 => { + # use this tag only to determine the byte order of the raw data + # (the value should be 0x0002 if the byte order is correct) + Name => 'RawDataByteOrder', + Hidden => 1, + RawConv => 'ToggleByteOrder() if $val >= 0x0100; undef', + }, + 0x01 => { Name => 'SensorWidth', Format => 'int16u' }, + 0x02 => { Name => 'SensorHeight', Format => 'int16u' }, +); + +# AFF record type 5 (ref forum?topic=4898.msg27628) +%Image::ExifTool::FLIR::AFF5 = ( + GROUPS => { 0 => 'FLIR', 1 => 'FLIR', 2 => 'Camera' }, + PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData, + FORMAT => 'int16u', + FIRST_ENTRY => 0, + 0x12 => { + # use this tag only to determine the byte order of the raw data + # (the value should be 0x0002 if the byte order is correct) + Name => 'RawDataByteOrder', + Hidden => 1, + RawConv => 'ToggleByteOrder() if $val >= 0x0100; undef', + }, + 0x13 => { Name => 'SensorWidth', Format => 'int16u' }, + 0x14 => { Name => 'SensorHeight', Format => 'int16u' }, +); + +# FLIR composite tags (ref 1) +%Image::ExifTool::FLIR::Composite = ( + GROUPS => { 1 => 'FLIR', 2 => 'Camera' }, + PeakSpectralSensitivity => { + Require => 'FLIR:PlanckB', + ValueConv => '14387.6515/$val', + PrintConv => 'sprintf("%.1f um", $val)', + }, +); + +# add our composite tags +Image::ExifTool::AddCompositeTags('Image::ExifTool::FLIR'); + +#------------------------------------------------------------------------------ +# Get image type from raw image data +# Inputs: 0) ExifTool ref, 1) image data, 2) tag name +# Returns: image type (PNG, JPG, TIFF or undef) +# - image itself is stored in $$et{$tag} +sub GetImageType($$$) +{ + my ($et, $val, $tag) = @_; + my ($w, $h) = @$et{"${tag}Width","${tag}Height"}; + my $type = 'DAT'; + # add TIFF header only if this looks like 16-bit raw data + # (note: MakeTiffHeader currently works only for little-endian, + # and I haven't seen any big-endian samples, but check anwyay) + if ($val =~ /^\x89PNG\r\n\x1a\n/) { + $type = 'PNG'; + } elsif ($val =~ /^\xff\xd8\xff/) { # (haven't seen this, but just in case - PH) + $type = 'JPG'; + } elsif (length $val != $w * $h * 2) { + $et->Warn("Unrecognized FLIR $tag data format"); + } elsif (GetByteOrder() eq 'II') { + $val = Image::ExifTool::MakeTiffHeader($w,$h,1,16) . $val; + $type = 'TIFF'; + } else { + $et->Warn("Don't yet support big-endian TIFF $tag"); + } + # save image data + $$et{$tag} = $val; + return $type; +} + +#------------------------------------------------------------------------------ +# Unescape FLIR Unicode character +# Inputs: 0) escaped character code +# Returns: UTF8 character +sub UnescapeFLIR($) +{ + my $char = shift; + return $char unless length $char eq 4; # escaped ASCII char (eg. '\\') + my $val = hex $char; + return chr($val) if $val < 0x80; # simple ASCII + return pack('C0U', $val) if $] >= 5.006001; + return Image::ExifTool::PackUTF8($val); +} + +#------------------------------------------------------------------------------ +# Process FLIR text info record (ref PH) +# Inputs: 0) ExifTool ref, 1) dirInfo ref, 2) tag table ref +# Returns: 1 on success +sub ProcessFLIRText($$$) +{ + my ($et, $dirInfo, $tagTablePtr) = @_; + my $dataPt = $$dirInfo{DataPt}; + my $dirStart = $$dirInfo{DirStart} || 0; + my $dirLen = $$dirInfo{DirLen}; + + return 0 if $dirLen < 12; + + $et->VerboseDir('FLIR Text'); + + my $dat = substr($$dataPt, $dirStart+12, $dirLen-12); + $dat =~ s/\0.*//s; # truncate at null + + # the parameter text contains an additional header entry... + if ($tagTablePtr eq \%Image::ExifTool::FLIR::ParamInfo and + $dat =~ /# (Generated) at (.*?)[\n\r]/) + { + $et->HandleTag($tagTablePtr, $1, $2); + } + + for (;;) { + $dat =~ /.(\d+).(label|value|param) (unicode|text) "(.*)"/g or last; + my ($tag, $val) = (ucfirst($2) . $1, $4); + if ($3 eq 'unicode' and $val =~ /\\/) { + # convert escaped Unicode characters (backslash followed by 4 hex digits) + $val =~ s/\\([0-9a-fA-F]{4}|.)/UnescapeFLIR($1)/sge; + $et->Decode($val, 'UTF8'); + } + $$tagTablePtr{$tag} or AddTagToTable($tagTablePtr, $tag, { Name => $tag }); + $et->HandleTag($tagTablePtr, $tag, $val); + } + + return 1; +} + +#------------------------------------------------------------------------------ +# Process FLIR measurement tool record (ref 6) +# Inputs: 0) ExifTool ref, 1) dirInfo ref, 2) tag table ref +# Returns: 1 on success +# (code-driven decoding isn't pretty, but sometimes it is necessary) +sub ProcessMeasInfo($$$) +{ + my ($et, $dirInfo, $tagTablePtr) = @_; + my $dataPt = $$dirInfo{DataPt}; + my $dirStart = $$dirInfo{DirStart} || 0; + my $dataPos = $$dirInfo{DataPos}; + my $dirEnd = $dirStart + $$dirInfo{DirLen}; + my $verbose = $et->Options('Verbose'); + + my $pos = $dirStart + 12; + return 0 if $pos > $dirEnd; + ToggleByteOrder() if Get16u($dataPt, $dirStart) >= 0x100; + my ($i, $t, $p); + for ($i=1; ; ++$i) { + last if $pos + 2 > $dirEnd; + my $recLen = Get16u($dataPt, $pos); + last if $recLen < 0x28 or $pos + $recLen > $dirEnd; + my $pre = 'Meas' . $i; + $et->VerboseDir("MeasInfo $i", undef, $recLen); + $et->VerboseDump($dataPt, Len => $recLen, Start=>$pos, DataPos=>$dataPos); + my $coordLen = Get16u($dataPt, $pos+4); + # generate tag table entries for this tool if necessary + foreach $t ('Type', 'Params', 'Label') { + my $tag = $pre . $t; + last if $$tagTablePtr{$tag}; + my $tagInfo = { Name => $tag }; + $$tagInfo{PrintConv} = $$tagTablePtr{"Meas1$t"}{PrintConv}; + AddTagToTable($tagTablePtr, $tag, $tagInfo); + } + # extract measurement tool type + $et->HandleTag($tagTablePtr, "${pre}Type", undef, + DataPt=>$dataPt, DataPos=>$dataPos, Start=>$pos+0x0a, Size=>2); + last if $pos + 0x24 + $coordLen > $dirEnd; + # extract measurement parameters + $et->HandleTag($tagTablePtr, "${pre}Params", undef, + DataPt=>$dataPt, DataPos=>$dataPos, Start=>$pos+0x24, Size=>$coordLen); + my @uni; + # extract label (sometimes-null-terminated Unicode) + for ($p=0x24+$coordLen; $p<$recLen-1; $p+=2) { + my $ch = Get16u($dataPt, $p+$pos); + # FLIR Tools v2.0 for Mac doesn't properly null-terminate these strings, + # so end the string at any funny character + last if $ch < 0x20 or $ch > 0x7f; + push @uni, $ch; + } + # convert to the ExifTool character set + require Image::ExifTool::Charset; + my $val = Image::ExifTool::Charset::Recompose($et, \@uni); + $et->HandleTag($tagTablePtr, "${pre}Label", $val, + DataPt=>$dataPt, DataPos=>$dataPos, Start=>$pos+0x24+$coordLen, Size=>2*scalar(@uni)); + $pos += $recLen; # step to next record + } + return 1; +} + +#------------------------------------------------------------------------------ +# Process FLIR FFF record (ref PH/1/3) +# Inputs: 0) ExifTool ref, 1) dirInfo ref, 2) tag table ref +# Returns: 1 if this was a valid FFF record +sub ProcessFLIR($$;$) +{ + my ($et, $dirInfo, $tagTablePtr) = @_; + my $raf = $$dirInfo{RAF} || new File::RandomAccess($$dirInfo{DataPt}); + my $verbose = $et->Options('Verbose'); + my $out = $et->Options('TextOut'); + my ($i, $hdr, $buff, $rec); + + # read and verify FFF header + $raf->Read($hdr, 0x40) == 0x40 and $hdr =~ /^([AF]FF)\0/ or return 0; + + my $type = $1; + + # set file type if reading from FFF or SEQ file ($tagTablePtr will not be defined) + $et->SetFileType($type eq 'FFF' ? 'FLIR' : 'SEQ') unless $tagTablePtr; + + # FLIR file header (ref 3) + # 0x00 - string[4] file format ID = "FFF\0" + # 0x04 - string[16] file creator: seen "\0","MTX IR\0","CAMCTRL\0" + # 0x14 - int32u file format version = 100 + # 0x18 - int32u offset to record directory + # 0x1c - int32u number of entries in record directory + # 0x20 - int32u next free index ID = 2 + # 0x24 - int16u swap pattern = 0 (?) + # 0x28 - int16u[7] spares + # 0x34 - int32u[2] reserved + # 0x3c - int32u checksum + + # determine byte ordering by validating version number + # (in my samples FLIR APP1 is big-endian, FFF files are little-endian) + for ($i=0; ; ++$i) { + my $ver = Get32u(\$hdr, 0x14); + last if $ver >= 100 and $ver < 200; # (have seen 100 and 101 - PH) + ToggleByteOrder(); + $i and $et->Warn("Unsupported FLIR $type version"), return 1; + } + + # read the FLIR record directory + my $pos = Get32u(\$hdr, 0x18); + my $num = Get32u(\$hdr, 0x1c); + unless ($raf->Seek($pos) and $raf->Read($buff, $num * 0x20) == $num * 0x20) { + $et->Warn('Truncated FLIR FFF directory'); + return 1; + } + + unless ($tagTablePtr) { + $tagTablePtr = GetTagTable("Image::ExifTool::FLIR::$type"); + $$et{SET_GROUP0} = 'FLIR'; # (set group 0 to 'FLIR' for FFF files) + } + + # process the header data + $et->HandleTag($tagTablePtr, '_header', $hdr); + + my $oldIndent = $$et{INDENT}; + $$et{INDENT} .= '| '; + $et->VerboseDir($type, $num); + + for ($i=0; $i<$num; ++$i) { + + # FLIR record entry (ref 3): + # 0x00 - int16u record type + # 0x02 - int16u record subtype: RawData 1=BE, 2=LE, 3=PNG; 1 for other record types + # 0x04 - int32u record version: seen 0x64,0x66,0x67,0x68,0x6f,0x104 + # 0x08 - int32u index id = 1 + # 0x0c - int32u record offset from start of FLIR data + # 0x10 - int32u record length + # 0x14 - int32u parent = 0 (?) + # 0x18 - int32u object number = 0 (?) + # 0x1c - int32u checksum: 0 for no checksum + + my $entry = $i * 0x20; + my $recType = Get16u(\$buff, $entry); + if ($recType == 0) { + $verbose and print $out "$$et{INDENT}$i) FLIR Record 0x00 (empty)\n"; + next; + } + my $recPos = Get32u(\$buff, $entry + 0x0c); + my $recLen = Get32u(\$buff, $entry + 0x10); + + $verbose and printf $out "%s%d) FLIR Record 0x%.2x, offset 0x%.4x, length 0x%.4x\n", + $$et{INDENT}, $i, $recType, $recPos, $recLen; + + unless ($raf->Seek($recPos) and $raf->Read($rec, $recLen) == $recLen) { + $et->Warn('Invalid FLIR record'); + last; + } + if ($$tagTablePtr{$recType}) { + $et->HandleTag($tagTablePtr, $recType, undef, + DataPt => \$rec, + DataPos => $recPos, + Start => 0, + Size => $recLen, + ); + } elsif ($verbose > 2) { + $et->VerboseDump(\$rec, Len => $recLen, DataPos => $recPos); + } + } + delete $$et{SET_GROUP0}; + $$et{INDENT} = $oldIndent; + return 1; +} + +#------------------------------------------------------------------------------ +# Process FLIR public image format (FPF) file (ref PH/4) +# Inputs: 0) ExifTool ref, 1) dirInfo ref, 2) tag table ref +# Returns: 1 if this was a valid FFF file +sub ProcessFPF($$) +{ + my ($et, $dirInfo) = @_; + my $raf = $$dirInfo{RAF}; + my $buff; + + $raf->Read($buff, 892) == 892 and $buff =~ /^FPF Public Image Format\0/ or return 0; + + # I think these are always little-endian, but check FPFVersion just in case + SetByteOrder('II'); + ToggleByteOrder() unless Get32u(\$buff, 0x20) & 0xffff; + + my $tagTablePtr = GetTagTable('Image::ExifTool::FLIR::FPF'); + $et->SetFileType(); + $et->ProcessDirectory( { DataPt => \$buff, Parent => 'FPF' }, $tagTablePtr); + return 1; +} + +1; # end + +__END__ + +=head1 NAME + +Image::ExifTool::FLIR - Read FLIR meta information + +=head1 SYNOPSIS + +This module is loaded automatically by Image::ExifTool when required. + +=head1 DESCRIPTION + +This module contains the definitions to read meta information from FLIR +Systems Inc. thermal image files (FFF, FPF and JPEG format). + +=head1 AUTHOR + +Copyright 2003-2019, Phil Harvey (phil at owl.phy.queensu.ca) + +This library is free software; you can redistribute it and/or modify it +under the same terms as Perl itself. + +=head1 REFERENCES + +=over 4 + +=item L<http://u88.n24.queensu.ca/exiftool/forum/index.php/topic,4898.0.html> + +=item L<http://www.nuage.ch/site/flir-i7-some-analysis/> + +=item L<http://www.workswell.cz/manuals/flir/hardware/A3xx_and_A6xx_models/Streaming_format_ThermoVision.pdf> + +=item L<http://support.flir.com/DocDownload/Assets/62/English/1557488%24A.pdf> + +=item L<http://code.google.com/p/dvelib/source/browse/trunk/flirPublicFormat/fpfConverter/Fpfimg.h?spec=svn3&r=3> + +=item L<http://u88.n24.queensu.ca/exiftool/forum/index.php/topic,5538.0.html> + +=back + +=head1 ACKNOWLEDGEMENTS + +Thanks to Tomas for his hard work in decoding much of this information, and +to Jens Duttke for getting me started on this format. + +=head1 SEE ALSO + +L<Image::ExifTool::TagNames/FLIR Tags>, +L<Image::ExifTool(3pm)|Image::ExifTool> + +=cut diff --git a/lib/Image/ExifTool/Fixup.pm b/lib/Image/ExifTool/Fixup.pm new file mode 100644 index 0000000..a89be80 --- /dev/null +++ b/lib/Image/ExifTool/Fixup.pm @@ -0,0 +1,366 @@ +#------------------------------------------------------------------------------ +# File: Fixup.pm +# +# Description: Utility to handle pointer fixups +# +# Revisions: 01/19/2005 - P. Harvey Created +# 04/11/2005 - P. Harvey Allow fixups to be tagged with a marker, +# and add new marker-related routines +# 06/21/2006 - P. Harvey Patch to work with negative offsets +# 07/07/2006 - P. Harvey Added support for 16-bit pointers +# 02/19/2013 - P. Harvey Added IsEmpty() +# +# Data Members: +# +# Start - Position in data where a zero pointer points to. +# Shift - Amount to shift offsets (relative to Start). +# Fixups - List of Fixup object references to to shift relative to this Fixup. +# Pointers - Hash of references to fixup pointer arrays, keyed by ByteOrder +# string (with "2" added if pointer is 16-bit [default is 32-bit], +# plus "_$marker" suffix if tagged with a marker name). +# +# Procedure: +# +# 1. Create a Fixup object for each data block containing pointers +# 2. Call AddFixup with the offset of each pointer in the block +# - pointer is assumed int32u with the current byte order +# - may also be called with a fixup reference for contained blocks +# 3. Add the necessary pointer offset to $$fixup{Shift} +# 4. Add data size to $$fixup{Start} if data is added before the block +# - automatically also shifts pointers by this amount +# 5. Call ApplyFixup to apply the fixup to all pointers +# - resets Shift and Start to 0 after applying fixup +#------------------------------------------------------------------------------ + +package Image::ExifTool::Fixup; + +use strict; +use Image::ExifTool qw(GetByteOrder SetByteOrder Get32u Get32s Set32u + Get16u Get16s Set16u); +use vars qw($VERSION); + +$VERSION = '1.05'; + +sub AddFixup($$;$$); +sub ApplyFixup($$); +sub Dump($;$); + +#------------------------------------------------------------------------------ +# New - create new Fixup object +# Inputs: 0) reference to Fixup object or Fixup class name +sub new +{ + local $_; + my $that = shift; + my $class = ref($that) || $that || 'Image::ExifTool::Fixup'; + my $self = bless {}, $class; + + # initialize required members + $self->{Start} = 0; + $self->{Shift} = 0; + + return $self; +} + +#------------------------------------------------------------------------------ +# Clone this object +# Inputs: 0) reference to Fixup object or Fixup class name +# Returns: reference to new Fixup object +sub Clone($) +{ + my $self = shift; + my $clone = new Image::ExifTool::Fixup; + $clone->{Start} = $self->{Start}; + $clone->{Shift} = $self->{Shift}; + my $phash = $self->{Pointers}; + if ($phash) { + $clone->{Pointers} = { }; + my $byteOrder; + foreach $byteOrder (keys %$phash) { + my @pointers = @{$phash->{$byteOrder}}; + $clone->{Pointers}->{$byteOrder} = \@pointers; + } + } + if ($self->{Fixups}) { + $clone->{Fixups} = [ ]; + my $subFixup; + foreach $subFixup (@{$self->{Fixups}}) { + push @{$clone->{Fixups}}, $subFixup->Clone(); + } + } + return $clone; +} + +#------------------------------------------------------------------------------ +# Add fixup pointer or another fixup object below this one +# Inputs: 0) Fixup object reference +# 1) Scalar for pointer offset, or reference to Fixup object +# 2) Optional marker name for the pointer +# 3) Optional pointer format ('int16u' or 'int32u', defaults to 'int32u') +# Notes: Byte ordering must be set properly for the pointer being added (must keep +# track of the byte order of each offset since MakerNotes may have different byte order!) +sub AddFixup($$;$$) +{ + my ($self, $pointer, $marker, $format) = @_; + if (ref $pointer) { + $self->{Fixups} or $self->{Fixups} = [ ]; + push @{$self->{Fixups}}, $pointer; + } else { + my $byteOrder = GetByteOrder(); + if (defined $format) { + if ($format eq 'int16u') { + $byteOrder .= '2'; + } elsif ($format ne 'int32u') { + warn "Bad Fixup pointer format $format\n"; + } + } + $byteOrder .= "_$marker" if defined $marker; + my $phash = $self->{Pointers}; + $phash or $phash = $self->{Pointers} = { }; + $phash->{$byteOrder} or $phash->{$byteOrder} = [ ]; + push @{$phash->{$byteOrder}}, $pointer; + } +} + +#------------------------------------------------------------------------------ +# fix up pointer offsets +# Inputs: 0) Fixup object reference, 1) data reference +# Outputs: Collapses fixup hierarchy into linear lists of fixup pointers +sub ApplyFixup($$) +{ + my ($self, $dataPt) = @_; + + my $start = $self->{Start}; + my $shift = $self->{Shift} + $start; # make shift relative to start + my $phash = $self->{Pointers}; + + # fix up pointers in this fixup + if ($phash and ($start or $shift)) { + my $saveOrder = GetByteOrder(); # save original byte ordering + my ($byteOrder, $ptr); + foreach $byteOrder (keys %$phash) { + SetByteOrder(substr($byteOrder,0,2)); + # apply the fixup offset shift (must get as signed integer + # to avoid overflow in case it was negative before) + my ($get, $set) = ($byteOrder =~ /^(II2|MM2)/) ? + (\&Get16s, \&Set16u) : (\&Get32s, \&Set32u); + foreach $ptr (@{$phash->{$byteOrder}}) { + $ptr += $start; # update pointer to new start location + next unless $shift; + &$set(&$get($dataPt, $ptr) + $shift, $dataPt, $ptr); + } + } + SetByteOrder($saveOrder); # restore original byte ordering + } + # recurse into contained fixups + if ($self->{Fixups}) { + # create our pointer hash if it doesn't exist + $phash or $phash = $self->{Pointers} = { }; + # loop through all contained fixups + my $subFixup; + foreach $subFixup (@{$self->{Fixups}}) { + # adjust the subfixup start and shift + $subFixup->{Start} += $start; + $subFixup->{Shift} += $shift - $start; + # recursively apply contained fixups + ApplyFixup($subFixup, $dataPt); + my $shash = $subFixup->{Pointers} or next; + # add all pointers to our collapsed lists + my $byteOrder; + foreach $byteOrder (keys %$shash) { + $phash->{$byteOrder} or $phash->{$byteOrder} = [ ]; + push @{$phash->{$byteOrder}}, @{$shash->{$byteOrder}}; + delete $shash->{$byteOrder}; + } + delete $subFixup->{Pointers}; + } + delete $self->{Fixups}; # remove our contained fixups + } + # reset our Start/Shift for the collapsed fixup + $self->{Start} = $self->{Shift} = 0; +} + +#------------------------------------------------------------------------------ +# Is this Fixup empty? +# Inputs: 0) Fixup object ref +# Returns: True if there are no offsets to fix +sub IsEmpty($) +{ + my $self = shift; + my $phash = $self->{Pointers}; + if ($phash) { + my $key; + foreach $key (keys %$phash) { + next unless ref $$phash{$key} eq 'ARRAY'; + return 0 if @{$$phash{$key}}; + } + } + return 1; +} + +#------------------------------------------------------------------------------ +# Does specified marker exist? +# Inputs: 0) Fixup object reference, 1) marker name +# Returns: True if fixup contains specified marker name +sub HasMarker($$) +{ + my ($self, $marker) = @_; + my $phash = $self->{Pointers}; + return 0 unless $phash; + return 1 if grep /_$marker$/, keys %$phash; + return 0 unless $self->{Fixups}; + my $subFixup; + foreach $subFixup (@{$self->{Fixups}}) { + return 1 if $subFixup->HasMarker($marker); + } + return 0; +} + +#------------------------------------------------------------------------------ +# Set all marker pointers to specified value +# Inputs: 0) Fixup object reference, 1) data reference +# 2) marker name, 3) pointer value, 4) offset to start of data +sub SetMarkerPointers($$$$;$) +{ + my ($self, $dataPt, $marker, $value, $startOffset) = @_; + my $start = $self->{Start} + ($startOffset || 0); + my $phash = $self->{Pointers}; + + if ($phash) { + my $saveOrder = GetByteOrder(); # save original byte ordering + my ($byteOrder, $ptr); + foreach $byteOrder (keys %$phash) { + next unless $byteOrder =~ /^(II|MM)(2?)_$marker$/; + SetByteOrder($1); + my $set = $2 ? \&Set16u : \&Set32u; + foreach $ptr (@{$phash->{$byteOrder}}) { + &$set($value, $dataPt, $ptr + $start); + } + } + SetByteOrder($saveOrder); # restore original byte ordering + } + if ($self->{Fixups}) { + my $subFixup; + foreach $subFixup (@{$self->{Fixups}}) { + $subFixup->SetMarkerPointers($dataPt, $marker, $value, $start); + } + } +} + +#------------------------------------------------------------------------------ +# Get pointer values for specified marker +# Inputs: 0) Fixup object reference, 1) data reference, +# 2) marker name, 3) offset to start of data +# Returns: List of marker pointers in list context, or first marker pointer otherwise +sub GetMarkerPointers($$$;$) +{ + my ($self, $dataPt, $marker, $startOffset) = @_; + my $start = $self->{Start} + ($startOffset || 0); + my $phash = $self->{Pointers}; + my @pointers; + + if ($phash) { + my $saveOrder = GetByteOrder(); + my ($byteOrder, $ptr); + foreach $byteOrder (grep /_$marker$/, keys %$phash) { + SetByteOrder(substr($byteOrder,0,2)); + my $get = ($byteOrder =~ /^(II2|MM2)/) ? \&Get16u : \&Get32u; + foreach $ptr (@{$phash->{$byteOrder}}) { + push @pointers, &$get($dataPt, $ptr + $start); + } + } + SetByteOrder($saveOrder); # restore original byte ordering + } + if ($self->{Fixups}) { + my $subFixup; + foreach $subFixup (@{$self->{Fixups}}) { + push @pointers, $subFixup->GetMarkerPointers($dataPt, $marker, $start); + } + } + return @pointers if wantarray; + return $pointers[0]; +} + +#------------------------------------------------------------------------------ +# Dump fixup to console for debugging +# Inputs: 0) Fixup object reference, 1) optional initial indent string +sub Dump($;$) +{ + my ($self, $indent) = @_; + $indent or $indent = ''; + printf "${indent}Fixup start=0x%x shift=0x%x\n", $self->{Start}, $self->{Shift}; + my $phash = $self->{Pointers}; + if ($phash) { + my $byteOrder; + foreach $byteOrder (sort keys %$phash) { + print "$indent $byteOrder: ", join(' ',@{$phash->{$byteOrder}}),"\n"; + } + } + if ($self->{Fixups}) { + my $subFixup; + foreach $subFixup (@{$self->{Fixups}}) { + Dump($subFixup, $indent . ' '); + } + } +} + + +1; # end + +__END__ + +=head1 NAME + +Image::ExifTool::Fixup - Utility to handle pointer fixups + +=head1 SYNOPSIS + + use Image::ExifTool::Fixup; + + $fixup = new Image::ExifTool::Fixup; + + # add a new fixup to a pointer at the specified offset in data + $fixup->AddFixup($offset); + + # add a new Fixup object to the tree + $fixup->AddFixup($subFixup); + + $fixup->{Start} += $shift1; # shift pointer offsets and values + + $fixup->{Shift} += $shift2; # shift pointer values only + + # recursively apply fixups to the specified data + $fixup->ApplyFixups(\$data); + + $fixup->Dump(); # dump debugging information + + $fixup->IsEmpty(); # return true if no offsets to fix + +=head1 DESCRIPTION + +This module contains the code to keep track of pointers in memory and to +shift these pointers as required. It is used by ExifTool to maintain the +pointers in image file directories (IFD's). + +=head1 NOTES + +Keeps track of pointers with different byte ordering, and relies on +Image::ExifTool::GetByteOrder() to determine the current byte ordering +when adding new pointers to a fixup. + +Maintains a hierarchical list of fixups so that the whole hierarchy can +be shifted by a simple shift at the base. Hierarchy is collapsed to a +linear list when ApplyFixups() is called. + +=head1 AUTHOR + +Copyright 2003-2019, Phil Harvey (phil at owl.phy.queensu.ca) + +This library is free software; you can redistribute it and/or modify it +under the same terms as Perl itself. + +=head1 SEE ALSO + +L<Image::ExifTool(3pm)|Image::ExifTool> + +=cut diff --git a/lib/Image/ExifTool/Flash.pm b/lib/Image/ExifTool/Flash.pm new file mode 100644 index 0000000..85d6558 --- /dev/null +++ b/lib/Image/ExifTool/Flash.pm @@ -0,0 +1,755 @@ +#------------------------------------------------------------------------------ +# File: Flash.pm +# +# Description: Read Shockwave Flash meta information +# +# Revisions: 05/16/2006 - P. Harvey Created +# 06/07/2007 - PH Added support for FLV (Flash Video) files +# 10/23/2008 - PH Added support for XMP in FLV and SWF +# +# References: 1) http://www.the-labs.com/MacromediaFlash/SWF-Spec/SWFfileformat.html +# 2) http://sswf.sourceforge.net/SWFalexref.html +# 3) http://osflash.org/flv/ +# 4) http://www.irisa.fr/texmex/people/dufouil/ffmpegdoxy/flv_8h.html +# 5) http://www.adobe.com/devnet/xmp/pdfs/XMPSpecificationPart3.pdf (Oct 2008) +# 6) http://www.adobe.com/devnet/swf/pdf/swf_file_format_spec_v9.pdf +# 7) http://help.adobe.com/en_US/FlashMediaServer/3.5_Deving/WS5b3ccc516d4fbf351e63e3d11a0773d56e-7ff6.html +# 8) http://www.adobe.com/devnet/flv/pdf/video_file_format_spec_v10.pdf +# +# Notes: I'll add AMF3 support if someone sends me a FLV with AMF3 data +#------------------------------------------------------------------------------ + +package Image::ExifTool::Flash; + +use strict; +use vars qw($VERSION); +use Image::ExifTool qw(:DataAccess :Utils); +use Image::ExifTool::FLAC; + +$VERSION = '1.12'; + +sub ProcessMeta($$$;$); + +# Meta packets that we process +my %processMetaPacket = ( onMetaData => 1, onXMPData => 1 ); + +# information extracted from SWF header +%Image::ExifTool::Flash::Main = ( + GROUPS => { 2 => 'Video' }, + VARS => { ALPHA_FIRST => 1 }, + NOTES => q{ + The information below is extracted from SWF (Shockwave Flash) files. Tags + with string ID's represent information extracted from the file header. + }, + FlashVersion => { }, + Compressed => { PrintConv => { 0 => 'False', 1 => 'True' } }, + ImageWidth => { }, + ImageHeight => { }, + FrameRate => { }, + FrameCount => { }, + Duration => { + Notes => 'calculated from FrameRate and FrameCount', + PrintConv => 'ConvertDuration($val)', + }, + 69 => { + Name => 'FlashAttributes', + PrintConv => { BITMASK => { + 0 => 'UseNetwork', + 3 => 'ActionScript3', + 4 => 'HasMetadata', + } }, + }, + 77 => { + Name => 'XMP', + SubDirectory => { TagTable => 'Image::ExifTool::XMP::Main' }, + }, +); + +# packets in Flash Video files +%Image::ExifTool::Flash::FLV = ( + NOTES => q{ + Information is extracted from the following packets in FLV (Flash Video) + files. + }, + 0x08 => { + Name => 'Audio', + BitMask => 0x04, + SubDirectory => { TagTable => 'Image::ExifTool::Flash::Audio' }, + }, + 0x09 => { + Name => 'Video', + BitMask => 0x01, + SubDirectory => { TagTable => 'Image::ExifTool::Flash::Video' }, + }, + 0x12 => { + Name => 'Meta', + SubDirectory => { TagTable => 'Image::ExifTool::Flash::Meta' }, + }, +); + +# tags in Flash Video packet header +%Image::ExifTool::Flash::Audio = ( + PROCESS_PROC => \&Image::ExifTool::FLAC::ProcessBitStream, + GROUPS => { 2 => 'Audio' }, + NOTES => 'Information extracted from the Flash Audio header.', + 'Bit0-3' => { + Name => 'AudioEncoding', + PrintConv => { + 0 => 'PCM-BE (uncompressed)', # PCM-BE according to ref 4 + 1 => 'ADPCM', + 2 => 'MP3', + 3 => 'PCM-LE (uncompressed)', #4 + 4 => 'Nellymoser 16kHz Mono', #8 + 5 => 'Nellymoser 8kHz Mono', + 6 => 'Nellymoser', + 7 => 'G.711 A-law logarithmic PCM', #8 + 8 => 'G.711 mu-law logarithmic PCM', #8 + # (9 is reserved, ref 8) + 10 => 'AAC', #8 + 11 => 'Speex', #8 + 13 => 'MP3 8-Khz', #8 + 15 => 'Device-specific sound', #8 + }, + }, + 'Bit4-5' => { + Name => 'AudioSampleRate', + ValueConv => { + 0 => 5512, + 1 => 11025, + 2 => 22050, + 3 => 44100, + }, + }, + 'Bit6' => { + Name => 'AudioBitsPerSample', + ValueConv => '8 * ($val + 1)', + }, + 'Bit7' => { + Name => 'AudioChannels', + ValueConv => '$val + 1', + PrintConv => { + 1 => '1 (mono)', + 2 => '2 (stereo)', + }, + }, +); + +# tags in Flash Video packet header +%Image::ExifTool::Flash::Video = ( + PROCESS_PROC => \&Image::ExifTool::FLAC::ProcessBitStream, + GROUPS => { 2 => 'Video' }, + NOTES => 'Information extracted from the Flash Video header.', + 'Bit4-7' => { + Name => 'VideoEncoding', + PrintConv => { + 1 => 'JPEG', #8 + 2 => 'Sorensen H.263', + 3 => 'Screen Video', + 4 => 'On2 VP6', + 5 => 'On2 VP6 Alpha', #3 + 6 => 'Screen Video 2', #3 + 7 => 'H.264', #7 (called "AVC" by ref 8) + }, + }, +); + +# tags in Flash META packet (in ActionScript Message Format) +%Image::ExifTool::Flash::Meta = ( + PROCESS_PROC => \&ProcessMeta, + GROUPS => { 2 => 'Video' }, + NOTES => q{ + Below are a few observed FLV Meta tags, but ExifTool will attempt to extract + information from any tag found. + }, + 'audiocodecid' => { Name => 'AudioCodecID', Groups => { 2 => 'Audio' } }, + 'audiodatarate' => { + Name => 'AudioBitrate', + Groups => { 2 => 'Audio' }, + ValueConv => '$val * 1000', + PrintConv => 'ConvertBitrate($val)', + }, + 'audiodelay' => { Name => 'AudioDelay', Groups => { 2 => 'Audio' } }, + 'audiosamplerate'=>{ Name => 'AudioSampleRate', Groups => { 2 => 'Audio' } }, + 'audiosamplesize'=>{ Name => 'AudioSampleSize', Groups => { 2 => 'Audio' } }, + 'audiosize' => { Name => 'AudioSize', Groups => { 2 => 'Audio' } }, + 'bytelength' => 'ByteLength', # (youtube) + 'canseekontime' => 'CanSeekOnTime', # (youtube) + 'canSeekToEnd' => 'CanSeekToEnd', + 'creationdate' => { + # (not an AMF date type in my sample) + Name => 'CreateDate', + Groups => { 2 => 'Time' }, + ValueConv => '$val=~s/\s+$//; $val', # trim trailing whitespace + }, + 'createdby' => 'CreatedBy', #7 + 'cuePoints' => { + Name => 'CuePoint', + SubDirectory => { TagTable => 'Image::ExifTool::Flash::CuePoint' }, + }, + 'datasize' => 'DataSize', + 'duration' => { + Name => 'Duration', + PrintConv => 'ConvertDuration($val)', + }, + 'filesize' => 'FileSizeBytes', + 'framerate' => { + Name => 'FrameRate', + PrintConv => 'int($val * 1000 + 0.5) / 1000', + }, + 'hasAudio' => { Name => 'HasAudio', Groups => { 2 => 'Audio' } }, + 'hasCuePoints' => 'HasCuePoints', + 'hasKeyframes' => 'HasKeyFrames', + 'hasMetadata' => 'HasMetadata', + 'hasVideo' => 'HasVideo', + 'height' => 'ImageHeight', + 'httphostheader'=> 'HTTPHostHeader', # (youtube) + 'keyframesTimes'=> 'KeyFramesTimes', + 'keyframesFilepositions' => 'KeyFramePositions', + 'lasttimestamp' => 'LastTimeStamp', + 'lastkeyframetimestamp' => 'LastKeyFrameTime', + 'metadatacreator'=>'MetadataCreator', + 'metadatadate' => { + Name => 'MetadataDate', + Groups => { 2 => 'Time' }, + PrintConv => '$self->ConvertDateTime($val)', + }, + 'purl' => 'URL', # (youtube) (what does P mean?) + 'pmsg' => 'Message', # (youtube) (what does P mean?) + 'sourcedata' => 'SourceData', # (youtube) + 'starttime' => { # (youtube) + Name => 'StartTime', + PrintConv => 'ConvertDuration($val)', + }, + 'stereo' => { Name => 'Stereo', Groups => { 2 => 'Audio' } }, + 'totalduration' => { # (youtube) + Name => 'TotalDuration', + PrintConv => 'ConvertDuration($val)', + }, + 'totaldatarate' => { # (youtube) + Name => 'TotalDataRate', + ValueConv => '$val * 1000', + PrintConv => 'int($val + 0.5)', + }, + 'totalduration' => 'TotalDuration', + 'videocodecid' => 'VideoCodecID', + 'videodatarate' => { + Name => 'VideoBitrate', + ValueConv => '$val * 1000', + PrintConv => 'ConvertBitrate($val)', + }, + 'videosize' => 'VideoSize', + 'width' => 'ImageWidth', + # tags in 'onXMPData' packets + 'liveXML' => { #5 + Name => 'XMP', + SubDirectory => { TagTable => 'Image::ExifTool::XMP::Main' }, + }, +); + +# tags in Flash META CuePoint structure +%Image::ExifTool::Flash::CuePoint = ( + PROCESS_PROC => \&ProcessMeta, + GROUPS => { 2 => 'Video' }, + NOTES => q{ + These tag names are added to the CuePoint name to generate complete tag + names like "CuePoint0Name". + }, + 'name' => 'Name', + 'type' => 'Type', + 'time' => 'Time', + 'parameters' => { + Name => 'Parameter', + SubDirectory => { TagTable => 'Image::ExifTool::Flash::Parameter' }, + }, +); + +# tags in Flash META CuePoint Parameter structure +%Image::ExifTool::Flash::Parameter = ( + PROCESS_PROC => \&ProcessMeta, + GROUPS => { 2 => 'Video' }, + NOTES => q{ + There are no pre-defined parameter tags, but ExifTool will extract any + existing parameters, with tag names like "CuePoint0ParameterXxx". + }, +); + +# name lookup for known AMF data types +my @amfType = qw(double boolean string object movieClip null undefined reference + mixedArray objectEnd array date longString unsupported recordSet + XML typedObject AMF3data); + +# test for AMF structure types (object, mixed array or typed object) +my %isStruct = ( 0x03 => 1, 0x08 => 1, 0x10 => 1 ); + +#------------------------------------------------------------------------------ +# Process Flash Video AMF Meta packet (ref 3) +# Inputs: 0) ExifTool object ref, 1) dirInfo ref, 2) tag table ref +# 3) Set to extract single type/value only +# Returns: 1 on success, (or type/value if extracting single value) +# Notes: Updates DataPos in dirInfo if extracting single value +sub ProcessMeta($$$;$) +{ + my ($et, $dirInfo, $tagTablePtr, $single) = @_; + my $dataPt = $$dirInfo{DataPt}; + my $dataPos = $$dirInfo{DataPos}; + my $dirLen = $$dirInfo{DirLen} || length($$dataPt); + my $pos = $$dirInfo{Pos} || 0; + my ($type, $val, $rec); + + $et->VerboseDir('Meta') unless $single; + +Record: for ($rec=0; ; ++$rec) { + last if $pos >= $dirLen; + $type = ord(substr($$dataPt, $pos)); + ++$pos; + if ($type == 0x00 or $type == 0x0b) { # double or date + last if $pos + 8 > $dirLen; + $val = GetDouble($dataPt, $pos); + $pos += 8; + if ($type == 0x0b) { # date + $val /= 1000; # convert to seconds + my $frac = $val - int($val); # fractional seconds + # get time zone + last if $pos + 2 > $dirLen; + my $tz = Get16s($dataPt, $pos); + $pos += 2; + # construct date/time string + $val = Image::ExifTool::ConvertUnixTime(int($val)); + if ($frac) { + $frac = sprintf('%.6f', $frac); + $frac =~ s/(^0|0+$)//g; + $val .= $frac; + } + # add timezone + if ($tz < 0) { + $val .= '-'; + $tz *= -1; + } else { + $val .= '+'; + } + $val .= sprintf('%.2d:%.2d', int($tz/60), $tz%60); + } + } elsif ($type == 0x01) { # boolean + last if $pos + 1 > $dirLen; + $val = Get8u($dataPt, $pos); + $val = { 0 => 'No', 1 => 'Yes' }->{$val} if $val < 2; + ++$pos; + } elsif ($type == 0x02) { # string + last if $pos + 2 > $dirLen; + my $len = Get16u($dataPt, $pos); + last if $pos + 2 + $len > $dirLen; + $val = substr($$dataPt, $pos + 2, $len); + $pos += 2 + $len; + } elsif ($isStruct{$type}) { # object, mixed array or typed object + $et->VPrint(1, " + [$amfType[$type]]\n"); + my $getName; + $val = ''; # dummy value + if ($type == 0x08) { # mixed array + # skip last array index for mixed array + last if $pos + 4 > $dirLen; + $pos += 4; + } elsif ($type == 0x10) { # typed object + $getName = 1; + } + for (;;) { + # get tag ID (or typed object name) + last Record if $pos + 2 > $dirLen; + my $len = Get16u($dataPt, $pos); + if ($pos + 2 + $len > $dirLen) { + $et->Warn("Truncated $amfType[$type] record"); + last Record; + } + my $tag = substr($$dataPt, $pos + 2, $len); + $pos += 2 + $len; + # first string of a typed object is the object name + if ($getName) { + $et->VPrint(1," | (object name '${tag}')\n"); + undef $getName; + next; # (ignore name for now) + } + my $subTablePtr = $tagTablePtr; + my $tagInfo = $$subTablePtr{$tag}; + # switch to subdirectory table if necessary + if ($tagInfo and $$tagInfo{SubDirectory}) { + my $subTable = $tagInfo->{SubDirectory}->{TagTable}; + # descend into Flash SubDirectory + if ($subTable =~ /^Image::ExifTool::Flash::/) { + $tag = $$tagInfo{Name}; # use our name for the tag + $subTablePtr = GetTagTable($subTable); + } + } + # get object value + my $valPos = $pos + 1; + $$dirInfo{Pos} = $pos; + my $structName = $$dirInfo{StructName}; + # add structure name to start of tag name + $tag = $structName . ucfirst($tag) if defined $structName; + $$dirInfo{StructName} = $tag; # set new structure name + my ($t, $v) = ProcessMeta($et, $dirInfo, $subTablePtr, 1); + $$dirInfo{StructName} = $structName;# restore original structure name + $pos = $$dirInfo{Pos}; # update to new position in packet + # all done if this value contained tags + last Record unless defined $t and defined $v; + next if $isStruct{$t}; # already handled tags in sub-structures + next if ref($v) eq 'ARRAY' and not @$v; # ignore empty arrays + last if $t == 0x09; # (end of object) + if (not $$subTablePtr{$tag} and $tag =~ /^\w+$/) { + AddTagToTable($subTablePtr, $tag, { Name => ucfirst($tag) }); + $et->VPrint(1, " | (adding $tag)\n"); + } + $et->HandleTag($subTablePtr, $tag, $v, + DataPt => $dataPt, + DataPos => $dataPos, + Start => $valPos, + Size => $pos - $valPos, + Format => $amfType[$t] || sprintf('0x%x',$t), + ); + } + # } elsif ($type == 0x04) { # movie clip (not supported) + } elsif ($type == 0x05 or $type == 0x06 or $type == 0x09 or $type == 0x0d) { + # null, undefined, dirLen of object, or unsupported + $val = ''; + } elsif ($type == 0x07) { # reference + last if $pos + 2 > $dirLen; + $val = Get16u($dataPt, $pos); + $pos += 2; + } elsif ($type == 0x0a) { # array + last if $pos + 4 > $dirLen; + my $num = Get32u($dataPt, $pos); + $$dirInfo{Pos} = $pos + 4; + my ($i, @vals); + # add array index to compount tag name + my $structName = $$dirInfo{StructName}; + for ($i=0; $i<$num; ++$i) { + $$dirInfo{StructName} = $structName . $i if defined $structName; + my ($t, $v) = ProcessMeta($et, $dirInfo, $tagTablePtr, 1); + last Record unless defined $v; + # save value unless contained in a sub-structure + push @vals, $v unless $isStruct{$t}; + } + $$dirInfo{StructName} = $structName; + $pos = $$dirInfo{Pos}; + $val = \@vals; + } elsif ($type == 0x0c or $type == 0x0f) { # long string or XML + last if $pos + 4 > $dirLen; + my $len = Get32u($dataPt, $pos); + last if $pos + 4 + $len > $dirLen; + $val = substr($$dataPt, $pos + 4, $len); + $pos += 4 + $len; + # } elsif ($type == 0x0e) { # record set (not supported) + # } elsif ($type == 0x11) { # AMF3 data (can't add support for this without a test sample) + } else { + my $t = $amfType[$type] || sprintf('type 0x%x',$type); + $et->Warn("AMF $t record not yet supported"); + undef $type; # (so we don't print another warning) + last; # can't continue + } + last if $single; # all done if extracting single value + unless ($isStruct{$type}) { + # only process certain Meta packets + if ($type == 0x02 and not $rec) { + my $verb = $processMetaPacket{$val} ? 'processing' : 'ignoring'; + $et->VPrint(0, " | ($verb $val information)\n"); + last unless $processMetaPacket{$val}; + } else { + # give verbose indication if we ignore a lone value + my $t = $amfType[$type] || sprintf('type 0x%x',$type); + $et->VPrint(1, " | (ignored lone $t value '${val}')\n"); + } + } + } + if (not defined $val and defined $type) { + $et->Warn(sprintf("Truncated AMF record 0x%x",$type)); + } + return 1 unless $single; # all done + $$dirInfo{Pos} = $pos; # update position + return($type,$val); # return single type/value pair +} + +#------------------------------------------------------------------------------ +# Read information frame a Flash Video file +# Inputs: 0) ExifTool object reference, 1) Directory information reference +# Returns: 1 on success, 0 if this wasn't a valid Flash Video file +sub ProcessFLV($$) +{ + my ($et, $dirInfo) = @_; + my $verbose = $et->Options('Verbose'); + my $raf = $$dirInfo{RAF}; + my $buff; + + $raf->Read($buff, 9) == 9 or return 0; + $buff =~ /^FLV\x01/ or return 0; + SetByteOrder('MM'); + $et->SetFileType(); + my ($flags, $offset) = unpack('x4CN', $buff); + $raf->Seek($offset-9, 1) or return 1 if $offset > 9; + $flags &= 0x05; # only look for audio/video + my $found = 0; + my $tagTablePtr = GetTagTable('Image::ExifTool::Flash::FLV'); + for (;;) { + $raf->Read($buff, 15) == 15 or last; + my $len = unpack('x4N', $buff); + my $type = $len >> 24; + $len &= 0x00ffffff; + my $tagInfo = $et->GetTagInfo($tagTablePtr, $type); + if ($verbose > 1) { + my $name = $tagInfo ? $$tagInfo{Name} : "type $type"; + $et->VPrint(1, "FLV $name packet, len $len\n"); + } + undef $buff; + if ($tagInfo and $$tagInfo{SubDirectory}) { + my $mask = $$tagInfo{BitMask}; + if ($mask) { + # handle audio or video packet + unless ($found & $mask) { + $found |= $mask; + $flags &= ~$mask; + if ($len>=1 and $raf->Read($buff, 1) == 1) { + $len -= 1; + } else { + $et->Warn("Bad $$tagInfo{Name} packet"); + last; + } + } + } elsif ($raf->Read($buff, $len) == $len) { + $len = 0; + } else { + $et->Warn('Truncated Meta packet'); + last; + } + } + if (defined $buff) { + $et->HandleTag($tagTablePtr, $type, undef, + DataPt => \$buff, + DataPos => $raf->Tell() - length($buff), + ); + } + last unless $flags; + $raf->Seek($len, 1) or last if $len; + } + return 1; +} + +#------------------------------------------------------------------------------ +# Found a Flash tag +# Inputs: 0) ExifTool object ref, 1) tag name, 2) tag value +sub FoundFlashTag($$$) +{ + my ($et, $tag, $val) = @_; + $et->HandleTag(\%Image::ExifTool::Flash::Main, $tag, $val); +} + +#------------------------------------------------------------------------------ +# Read data from possibly compressed file +# Inputs: 0) RAF reference, 1) data buffer, 2) bytes to read, 2) compressed flag +# Returns: number of bytes read (may be greater than requested bytes if compressed) +# - concatenates data to current buffer +# - updates compressed flag with reference to inflate object for future calls +# (or sets to error message and returns zero on error) +sub ReadCompressed($$$$) +{ + my ($raf, $len, $inflate) = ($_[0], $_[2], $_[3]); + my $buff; + unless ($raf->Read($buff, $len)) { + $_[3] = 'Error reading file'; + return 0; + } + # uncompress if necessary + if ($inflate) { + unless (ref $inflate) { + unless (eval { require Compress::Zlib }) { + $_[3] = 'Install Compress::Zlib to extract compressed information'; + return 0; + } + $inflate = Compress::Zlib::inflateInit(); + unless ($inflate) { + $_[3] = 'Error initializing inflate for Flash data'; + return 0; + } + $_[3] = $inflate; # pass inflate object back to caller + } + my $tmp = $buff; + $buff = ''; + # read 64 more bytes at a time and inflate until we get enough uncompressed data + for (;;) { + my ($dat, $stat) = $inflate->inflate($tmp); + if ($stat == Compress::Zlib::Z_STREAM_END() or + $stat == Compress::Zlib::Z_OK()) + { + $buff .= $dat; # add inflated data to buffer + last if length $buff >= $len or $stat == Compress::Zlib::Z_STREAM_END(); + $raf->Read($tmp,64) or last; # must read a bit more data + } else { + $buff = ''; + last; + } + } + $_[3] = 'Error inflating compressed Flash data' unless length $buff; + } + $_[1] = defined $_[1] ? $_[1] . $buff : $buff; + return length $buff; +} + +#------------------------------------------------------------------------------ +# Read information frame a Flash file +# Inputs: 0) ExifTool object reference, 1) Directory information reference +# Returns: 1 on success, 0 if this wasn't a valid Flash file +sub ProcessSWF($$) +{ + my ($et, $dirInfo) = @_; + my $raf = $$dirInfo{RAF}; + my ($buff, $hasMeta); + + $raf->Read($buff, 8) == 8 or return 0; + $buff =~ /^(F|C)WS([^\0])/ or return 0; + my ($compressed, $vers) = ($1 eq 'C' ? 1 : 0, ord($2)); + + SetByteOrder('II'); + $et->SetFileType(); + GetTagTable('Image::ExifTool::Flash::Main'); # make sure table is initialized + + FoundFlashTag($et, FlashVersion => $vers); + FoundFlashTag($et, Compressed => $compressed); + + # read the next 64 bytes of the file (and inflate if necessary) + $buff = ''; + unless (ReadCompressed($raf, $buff, 64, $compressed)) { + $et->Warn($compressed) if $compressed; + return 1; + } + + # unpack elements of bit-packed Flash Rect structure + my $nBits = unpack('C', $buff) >> 3; # bits in x1,x2,y1,y2 elements + my $totBits = 5 + $nBits * 4; # total bits in Rect structure + my $nBytes = int(($totBits + 7) / 8); # byte length of Rect structure + if (length $buff < $nBytes + 4) { + $et->Warn('Truncated Flash file'); + return 1; + } + my $bits = unpack("B$totBits", $buff); + # isolate Rect elements and convert from ASCII bit strings to integers + my @vals = unpack('x5' . "a$nBits" x 4, $bits); + # (do conversion the hard way because oct("0b$val") requires Perl 5.6) + map { $_ = unpack('N', pack('B32', '0' x (32 - length $_) . $_)) } @vals; + + # calculate and store ImageWidth/Height + FoundFlashTag($et, ImageWidth => ($vals[1] - $vals[0]) / 20); + FoundFlashTag($et, ImageHeight => ($vals[3] - $vals[2]) / 20); + + # get frame rate and count + @vals = unpack("x${nBytes}v2", $buff); + FoundFlashTag($et, FrameRate => $vals[0] / 256); + FoundFlashTag($et, FrameCount => $vals[1]); + FoundFlashTag($et, Duration => $vals[1] * 256 / $vals[0]) if $vals[0]; + + # scan through the tags to find FlashAttributes and XMP + $buff = substr($buff, $nBytes + 4); + for (;;) { + my $buffLen = length $buff; + last if $buffLen < 2; + my $code = Get16u(\$buff, 0); + my $pos = 2; + my $tag = $code >> 6; + my $size = $code & 0x3f; + $et->VPrint(1, "SWF tag $tag ($size bytes):\n"); + last unless $tag == 69 or $tag == 77 or $hasMeta; + # read enough to get a complete short record + if ($pos + $size > $buffLen) { + # (read 2 extra bytes if available to get next tag word) + unless (ReadCompressed($raf, $buff, $size + 2, $compressed)) { + $et->Warn($compressed) if $compressed; + return 1; + } + $buffLen = length $buff; + last if $pos + $size > $buffLen; + } + # read extended record if necessary + if ($size == 0x3f) { + last if $pos + 4 > $buffLen; + $size = Get32u(\$buff, $pos); + $pos += 4; + last if $size > 1000000; # don't read anything huge + if ($pos + $size > $buffLen) { + unless (ReadCompressed($raf, $buff, $size + 2, $compressed)) { + $et->Warn($compressed) if $compressed; + return 1; + } + $buffLen = length $buff; + last if $pos + $size > $buffLen; + } + $et->VPrint(1, " [extended size $size bytes]\n"); + } + if ($tag == 69) { # FlashAttributes + last unless $size; + my $flags = Get8u(\$buff, $pos); + FoundFlashTag($et, $tag => $flags); + last unless $flags & 0x10; # only continue if we have metadata (XMP) + $hasMeta = 1; + } elsif ($tag == 77) { # Metadata + my $val = substr($buff, $pos, $size); + FoundFlashTag($et, $tag => $val); + last; + } + last if $pos + 2 > $buffLen; + $buff = substr($buff, $pos); # remove everything before the next tag + } + return 1; +} + +1; # end + +__END__ + +=head1 NAME + +Image::ExifTool::Flash - Read Shockwave Flash meta information + +=head1 SYNOPSIS + +This module is used by Image::ExifTool + +=head1 DESCRIPTION + +This module contains definitions required by Image::ExifTool to read SWF +(Shockwave Flash) and FLV (Flash Video) files. + +=head1 NOTES + +Flash Video AMF3 support has not yet been added because I haven't yet found +a FLV file containing AMF3 information. If someone sends me a sample then I +will add AMF3 support. + +=head1 AUTHOR + +Copyright 2003-2019, Phil Harvey (phil at owl.phy.queensu.ca) + +This library is free software; you can redistribute it and/or modify it +under the same terms as Perl itself. + +=head1 REFERENCES + +=over 4 + +=item L<http://www.the-labs.com/MacromediaFlash/SWF-Spec/SWFfileformat.html> + +=item L<http://sswf.sourceforge.net/SWFalexref.html> + +=item L<http://osflash.org/flv/> + +=item L<http://www.irisa.fr/texmex/people/dufouil/ffmpegdoxy/flv_8h.html> + +=item L<http://help.adobe.com/en_US/FlashMediaServer/3.5_Deving/WS5b3ccc516d4fbf351e63e3d11a0773d56e-7ff6.html> + +=item L<http://www.adobe.com/devnet/swf/pdf/swf_file_format_spec_v9.pdf> + +=item L<http://www.adobe.com/devnet/flv/pdf/video_file_format_spec_v10.pdf> + +=back + +=head1 SEE ALSO + +L<Image::ExifTool::TagNames/Flash Tags>, +L<Image::ExifTool(3pm)|Image::ExifTool> + +=cut + diff --git a/lib/Image/ExifTool/FlashPix.pm b/lib/Image/ExifTool/FlashPix.pm new file mode 100644 index 0000000..70cf7f8 --- /dev/null +++ b/lib/Image/ExifTool/FlashPix.pm @@ -0,0 +1,2395 @@ +#------------------------------------------------------------------------------ +# File: FlashPix.pm +# +# Description: Read FlashPix meta information +# +# Revisions: 05/29/2006 - P. Harvey Created +# +# References: 1) http://www.exif.org/Exif2-2.PDF +# 2) http://www.graphcomp.com/info/specs/livepicture/fpx.pdf +# 3) http://search.cpan.org/~jdb/libwin32/ +# 4) http://msdn.microsoft.com/en-us/library/aa380374.aspx +# 5) http://www.cpan.org/modules/by-authors/id/H/HC/HCARVEY/File-MSWord-0.1.zip +# 6) https://msdn.microsoft.com/en-us/library/cc313153(v=office.12).aspx +#------------------------------------------------------------------------------ + +package Image::ExifTool::FlashPix; + +use strict; +use vars qw($VERSION); +use Image::ExifTool qw(:DataAccess :Utils); +use Image::ExifTool::Exif; +use Image::ExifTool::ASF; # for GetGUID() + +$VERSION = '1.36'; + +sub ProcessFPX($$); +sub ProcessFPXR($$$); +sub ProcessProperties($$$); +sub ReadFPXValue($$$$$;$$); +sub ProcessHyperlinks($$); +sub ProcessContents($$$); +sub ProcessWordDocument($$$); +sub ProcessDocumentTable($); +sub ProcessCommentBy($$$); +sub ProcessLastSavedBy($$$); +sub SetDocNum($$;$$$); +sub ConvertDTTM($); + +# sector type constants +sub HDR_SIZE () { 512; } +sub DIF_SECT () { 0xfffffffc; } +sub FAT_SECT () { 0xfffffffd; } +sub END_OF_CHAIN () { 0xfffffffe; } +sub FREE_SECT () { 0xffffffff; } + +# format flags +sub VT_VECTOR () { 0x1000; } +sub VT_ARRAY () { 0x2000; } +sub VT_BYREF () { 0x4000; } +sub VT_RESERVED () { 0x8000; } + +# other constants +sub VT_VARIANT () { 12; } +sub VT_LPSTR () { 30; } + +# list of OLE format codes (unsupported codes commented out) +my %oleFormat = ( + 0 => undef, # VT_EMPTY + 1 => undef, # VT_NULL + 2 => 'int16s', # VT_I2 + 3 => 'int32s', # VT_I4 + 4 => 'float', # VT_R4 + 5 => 'double', # VT_R8 + 6 => undef, # VT_CY + 7 => 'VT_DATE', # VT_DATE (double, number of days since Dec 30, 1899) + 8 => 'VT_BSTR', # VT_BSTR (int32u count, followed by binary string) +# 9 => 'VT_DISPATCH', + 10 => 'int32s', # VT_ERROR + 11 => 'int16s', # VT_BOOL + 12 => 'VT_VARIANT', # VT_VARIANT +# 13 => 'VT_UNKNOWN', +# 14 => 'VT_DECIMAL', + 16 => 'int8s', # VT_I1 + 17 => 'int8u', # VT_UI1 + 18 => 'int16u', # VT_UI2 + 19 => 'int32u', # VT_UI4 + 20 => 'int64s', # VT_I8 + 21 => 'int64u', # VT_UI8 +# 22 => 'VT_INT', +# 23 => 'VT_UINT', +# 24 => 'VT_VOID', +# 25 => 'VT_HRESULT', +# 26 => 'VT_PTR', +# 27 => 'VT_SAFEARRAY', +# 28 => 'VT_CARRAY', +# 29 => 'VT_USERDEFINED', + 30 => 'VT_LPSTR', # VT_LPSTR (int32u count, followed by string) + 31 => 'VT_LPWSTR', # VT_LPWSTR (int32u word count, followed by Unicode string) + 64 => 'VT_FILETIME',# VT_FILETIME (int64u, 100 ns increments since Jan 1, 1601) + 65 => 'VT_BLOB', # VT_BLOB +# 66 => 'VT_STREAM', +# 67 => 'VT_STORAGE', +# 68 => 'VT_STREAMED_OBJECT', +# 69 => 'VT_STORED_OBJECT', +# 70 => 'VT_BLOB_OBJECT', + 71 => 'VT_CF', # VT_CF + 72 => 'VT_CLSID', # VT_CLSID +); + +# OLE flag codes (high nibble of property type) +my %oleFlags = ( + 0x1000 => 'VT_VECTOR', + 0x2000 => 'VT_ARRAY', # not yet supported + 0x4000 => 'VT_BYREF', # ditto + 0x8000 => 'VT_RESERVED', +); + +# byte sizes for supported VT_* format and flag types +my %oleFormatSize = ( + VT_DATE => 8, + VT_BSTR => 4, # (+ string length) + VT_VARIANT => 4, # (+ data length) + VT_LPSTR => 4, # (+ string length) + VT_LPWSTR => 4, # (+ string character length) + VT_FILETIME => 8, + VT_BLOB => 4, # (+ data length) + VT_CF => 4, # (+ data length) + VT_CLSID => 16, + VT_VECTOR => 4, # (+ vector elements) +); + +# names for each type of directory entry +my @dirEntryType = qw(INVALID STORAGE STREAM LOCKBYTES PROPERTY ROOT); + +# list of code pages used by Microsoft +# (ref http://msdn.microsoft.com/en-us/library/dd317756(VS.85).aspx) +my %codePage = ( + 037 => 'IBM EBCDIC US-Canada', + 437 => 'DOS United States', + 500 => 'IBM EBCDIC International', + 708 => 'Arabic (ASMO 708)', + 709 => 'Arabic (ASMO-449+, BCON V4)', + 710 => 'Arabic - Transparent Arabic', + 720 => 'DOS Arabic (Transparent ASMO)', + 737 => 'DOS Greek (formerly 437G)', + 775 => 'DOS Baltic', + 850 => 'DOS Latin 1 (Western European)', + 852 => 'DOS Latin 2 (Central European)', + 855 => 'DOS Cyrillic (primarily Russian)', + 857 => 'DOS Turkish', + 858 => 'DOS Multilingual Latin 1 with Euro', + 860 => 'DOS Portuguese', + 861 => 'DOS Icelandic', + 862 => 'DOS Hebrew', + 863 => 'DOS French Canadian', + 864 => 'DOS Arabic', + 865 => 'DOS Nordic', + 866 => 'DOS Russian (Cyrillic)', + 869 => 'DOS Modern Greek', + 870 => 'IBM EBCDIC Multilingual/ROECE (Latin 2)', + 874 => 'Windows Thai (same as 28605, ISO 8859-15)', + 875 => 'IBM EBCDIC Greek Modern', + 932 => 'Windows Japanese (Shift-JIS)', + 936 => 'Windows Simplified Chinese (PRC, Singapore)', + 949 => 'Windows Korean (Unified Hangul Code)', + 950 => 'Windows Traditional Chinese (Taiwan)', + 1026 => 'IBM EBCDIC Turkish (Latin 5)', + 1047 => 'IBM EBCDIC Latin 1/Open System', + 1140 => 'IBM EBCDIC US-Canada with Euro', + 1141 => 'IBM EBCDIC Germany with Euro', + 1142 => 'IBM EBCDIC Denmark-Norway with Euro', + 1143 => 'IBM EBCDIC Finland-Sweden with Euro', + 1144 => 'IBM EBCDIC Italy with Euro', + 1145 => 'IBM EBCDIC Latin America-Spain with Euro', + 1146 => 'IBM EBCDIC United Kingdom with Euro', + 1147 => 'IBM EBCDIC France with Euro', + 1148 => 'IBM EBCDIC International with Euro', + 1149 => 'IBM EBCDIC Icelandic with Euro', + 1200 => 'Unicode UTF-16, little endian', + 1201 => 'Unicode UTF-16, big endian', + 1250 => 'Windows Latin 2 (Central European)', + 1251 => 'Windows Cyrillic', + 1252 => 'Windows Latin 1 (Western European)', + 1253 => 'Windows Greek', + 1254 => 'Windows Turkish', + 1255 => 'Windows Hebrew', + 1256 => 'Windows Arabic', + 1257 => 'Windows Baltic', + 1258 => 'Windows Vietnamese', + 1361 => 'Korean (Johab)', + 10000 => 'Mac Roman (Western European)', + 10001 => 'Mac Japanese', + 10002 => 'Mac Traditional Chinese', + 10003 => 'Mac Korean', + 10004 => 'Mac Arabic', + 10005 => 'Mac Hebrew', + 10006 => 'Mac Greek', + 10007 => 'Mac Cyrillic', + 10008 => 'Mac Simplified Chinese', + 10010 => 'Mac Romanian', + 10017 => 'Mac Ukrainian', + 10021 => 'Mac Thai', + 10029 => 'Mac Latin 2 (Central European)', + 10079 => 'Mac Icelandic', + 10081 => 'Mac Turkish', + 10082 => 'Mac Croatian', + 12000 => 'Unicode UTF-32, little endian', + 12001 => 'Unicode UTF-32, big endian', + 20000 => 'CNS Taiwan', + 20001 => 'TCA Taiwan', + 20002 => 'Eten Taiwan', + 20003 => 'IBM5550 Taiwan', + 20004 => 'TeleText Taiwan', + 20005 => 'Wang Taiwan', + 20105 => 'IA5 (IRV International Alphabet No. 5, 7-bit)', + 20106 => 'IA5 German (7-bit)', + 20107 => 'IA5 Swedish (7-bit)', + 20108 => 'IA5 Norwegian (7-bit)', + 20127 => 'US-ASCII (7-bit)', + 20261 => 'T.61', + 20269 => 'ISO 6937 Non-Spacing Accent', + 20273 => 'IBM EBCDIC Germany', + 20277 => 'IBM EBCDIC Denmark-Norway', + 20278 => 'IBM EBCDIC Finland-Sweden', + 20280 => 'IBM EBCDIC Italy', + 20284 => 'IBM EBCDIC Latin America-Spain', + 20285 => 'IBM EBCDIC United Kingdom', + 20290 => 'IBM EBCDIC Japanese Katakana Extended', + 20297 => 'IBM EBCDIC France', + 20420 => 'IBM EBCDIC Arabic', + 20423 => 'IBM EBCDIC Greek', + 20424 => 'IBM EBCDIC Hebrew', + 20833 => 'IBM EBCDIC Korean Extended', + 20838 => 'IBM EBCDIC Thai', + 20866 => 'Russian/Cyrillic (KOI8-R)', + 20871 => 'IBM EBCDIC Icelandic', + 20880 => 'IBM EBCDIC Cyrillic Russian', + 20905 => 'IBM EBCDIC Turkish', + 20924 => 'IBM EBCDIC Latin 1/Open System with Euro', + 20932 => 'Japanese (JIS 0208-1990 and 0121-1990)', + 20936 => 'Simplified Chinese (GB2312)', + 20949 => 'Korean Wansung', + 21025 => 'IBM EBCDIC Cyrillic Serbian-Bulgarian', + 21027 => 'Extended Alpha Lowercase (deprecated)', + 21866 => 'Ukrainian/Cyrillic (KOI8-U)', + 28591 => 'ISO 8859-1 Latin 1 (Western European)', + 28592 => 'ISO 8859-2 (Central European)', + 28593 => 'ISO 8859-3 Latin 3', + 28594 => 'ISO 8859-4 Baltic', + 28595 => 'ISO 8859-5 Cyrillic', + 28596 => 'ISO 8859-6 Arabic', + 28597 => 'ISO 8859-7 Greek', + 28598 => 'ISO 8859-8 Hebrew (Visual)', + 28599 => 'ISO 8859-9 Turkish', + 28603 => 'ISO 8859-13 Estonian', + 28605 => 'ISO 8859-15 Latin 9', + 29001 => 'Europa 3', + 38598 => 'ISO 8859-8 Hebrew (Logical)', + 50220 => 'ISO 2022 Japanese with no halfwidth Katakana (JIS)', + 50221 => 'ISO 2022 Japanese with halfwidth Katakana (JIS-Allow 1 byte Kana)', + 50222 => 'ISO 2022 Japanese JIS X 0201-1989 (JIS-Allow 1 byte Kana - SO/SI)', + 50225 => 'ISO 2022 Korean', + 50227 => 'ISO 2022 Simplified Chinese', + 50229 => 'ISO 2022 Traditional Chinese', + 50930 => 'EBCDIC Japanese (Katakana) Extended', + 50931 => 'EBCDIC US-Canada and Japanese', + 50933 => 'EBCDIC Korean Extended and Korean', + 50935 => 'EBCDIC Simplified Chinese Extended and Simplified Chinese', + 50936 => 'EBCDIC Simplified Chinese', + 50937 => 'EBCDIC US-Canada and Traditional Chinese', + 50939 => 'EBCDIC Japanese (Latin) Extended and Japanese', + 51932 => 'EUC Japanese', + 51936 => 'EUC Simplified Chinese', + 51949 => 'EUC Korean', + 51950 => 'EUC Traditional Chinese', + 52936 => 'HZ-GB2312 Simplified Chinese', + 54936 => 'Windows XP and later: GB18030 Simplified Chinese (4 byte)', + 57002 => 'ISCII Devanagari', + 57003 => 'ISCII Bengali', + 57004 => 'ISCII Tamil', + 57005 => 'ISCII Telugu', + 57006 => 'ISCII Assamese', + 57007 => 'ISCII Oriya', + 57008 => 'ISCII Kannada', + 57009 => 'ISCII Malayalam', + 57010 => 'ISCII Gujarati', + 57011 => 'ISCII Punjabi', + 65000 => 'Unicode (UTF-7)', + 65001 => 'Unicode (UTF-8)', +); + +# test for file extensions which may be variants of the FPX format +# (have seen one password-protected DOCX file that is FPX-like, so assume +# that all the rest could be as well) +my %fpxFileType = ( + DOC => 1, DOCX => 1, DOCM => 1, + DOT => 1, DOTX => 1, DOTM => 1, + POT => 1, POTX => 1, POTM => 1, + PPS => 1, PPSX => 1, PPSM => 1, + PPT => 1, PPTX => 1, PPTM => 1, THMX => 1, + XLA => 1, XLAM => 1, + XLS => 1, XLSX => 1, XLSM => 1, XLSB => 1, + XLT => 1, XLTX => 1, XLTM => 1, + # non MSOffice types + FLA => 1, VSD => 1, +); + +%Image::ExifTool::FlashPix::Main = ( + PROCESS_PROC => \&ProcessFPXR, + GROUPS => { 2 => 'Image' }, + NOTES => q{ + The FlashPix file format, introduced in 1996, was developed by Kodak, + Hewlett-Packard and Microsoft. Internally the FPX file structure mimics + that of an old DOS disk with fixed-sized "sectors" (usually 512 bytes) and a + "file allocation table" (FAT). No wonder this image format never became + popular. However, some of the structures used in FlashPix streams are part + of the EXIF specification, and are still being used in the APP2 FPXR segment + of JPEG images by some digital cameras from manufacturers such as FujiFilm, + Hewlett-Packard, Kodak and Sanyo. + + ExifTool extracts FlashPix information from both FPX images and the APP2 + FPXR segment of JPEG images. As well, FlashPix information is extracted + from DOC, PPT, XLS (Microsoft Word, PowerPoint and Excel) documents, VSD + (Microsoft Visio) drawings, and FLA (Macromedia/Adobe Flash project) files + since these are based on the same file format as FlashPix (the Windows + Compound Binary File format). See + L<http://graphcomp.com/info/specs/livepicture/fpx.pdf> for the FlashPix + specification. + }, + "\x05SummaryInformation" => { + Name => 'SummaryInfo', + SubDirectory => { + TagTable => 'Image::ExifTool::FlashPix::SummaryInfo', + }, + }, + "\x05DocumentSummaryInformation" => { + Name => 'DocumentInfo', + Multi => 1, # flag to process UserDefined information after this + SubDirectory => { + TagTable => 'Image::ExifTool::FlashPix::DocumentInfo', + }, + }, + "\x01CompObj" => { + Name => 'CompObj', + SubDirectory => { + TagTable => 'Image::ExifTool::FlashPix::CompObj', + DirStart => 0x1c, # skip stream header + }, + }, + "\x05Image Info" => { + Name => 'ImageInfo', + SubDirectory => { + TagTable => 'Image::ExifTool::FlashPix::ImageInfo', + }, + }, + "\x05Image Contents" => { + Name => 'Image', + SubDirectory => { + TagTable => 'Image::ExifTool::FlashPix::Image', + }, + }, + "Contents" => { + Name => 'Contents', + Notes => 'found in FLA files; may contain XMP', + SubDirectory => { + TagTable => 'Image::ExifTool::XMP::Main', + ProcessProc => \&ProcessContents, + }, + }, + "ICC Profile 0001" => { + Name => 'ICC_Profile', + SubDirectory => { + TagTable => 'Image::ExifTool::ICC_Profile::Main', + DirStart => 0x1c, # skip stream header + }, + }, + "\x05Extension List" => { + Name => 'Extensions', + SubDirectory => { + TagTable => 'Image::ExifTool::FlashPix::Extensions', + }, + }, + 'Subimage 0000 Header' => { + Name => 'SubimageHdr', + SubDirectory => { + TagTable => 'Image::ExifTool::FlashPix::SubimageHdr', + DirStart => 0x1c, # skip stream header + }, + }, +# 'Subimage 0000 Data' + "\x05Data Object" => { # plus instance number (eg. " 000000") + Name => 'DataObject', + SubDirectory => { + TagTable => 'Image::ExifTool::FlashPix::DataObject', + }, + }, +# "\x05Data Object Store" => { # plus instance number (eg. " 000000") + "\x05Transform" => { # plus instance number (eg. " 000000") + Name => 'Transform', + SubDirectory => { + TagTable => 'Image::ExifTool::FlashPix::Transform', + }, + }, + "\x05Operation" => { # plus instance number (eg. " 000000") + Name => 'Operation', + SubDirectory => { + TagTable => 'Image::ExifTool::FlashPix::Operation', + }, + }, + "\x05Global Info" => { + Name => 'GlobalInfo', + SubDirectory => { + TagTable => 'Image::ExifTool::FlashPix::GlobalInfo', + }, + }, + "\x05Screen Nail" => { # plus class ID (eg. "_bd0100609719a180") + Name => 'ScreenNail', + Groups => { 2 => 'Other' }, + # strip off stream header + ValueConv => 'length($val) > 0x1c and $val = substr($val, 0x1c); \$val', + }, + "\x05Audio Info" => { + Name => 'AudioInfo', + SubDirectory => { + TagTable => 'Image::ExifTool::FlashPix::AudioInfo', + }, + }, + 'Audio Stream' => { # plus instance number (eg. " 000000") + Name => 'AudioStream', + Groups => { 2 => 'Audio' }, + # strip off stream header + ValueConv => 'length($val) > 0x1c and $val = substr($val, 0x1c); \$val', + }, + 'Current User' => { #PH + Name => 'CurrentUser', + # not sure what the rest of this data is, but extract ASCII name from it - PH + ValueConv => q{ + return undef if length $val < 12; + my ($size,$pos) = unpack('x4VV', $val); + my $len = $size - $pos - 4; + return undef if $len < 0 or length $val < $size + 8; + return substr($val, 8 + $pos, $len); + }, + }, + 'WordDocument' => { + Name => 'WordDocument', + SubDirectory => { TagTable => 'Image::ExifTool::FlashPix::WordDocument' }, + }, + # save these tables until after the WordDocument was processed + '0Table' => { + Name => 'Table0', + Hidden => 1, # (used only as temporary storage until table is processed) + Binary => 1, + }, + '1Table' => { + Name => 'Table1', + Hidden => 1, # (used only as temporary storage until table is processed) + Binary => 1, + }, + Preview => { + Name => 'PreviewImage', + Groups => { 2 => 'Preview' }, + Binary => 1, + Notes => 'written by some FujiFilm models', + # skip 47-byte Fuji header + RawConv => q{ + return undef unless length $val > 47; + $val = substr($val, 47); + return $val =~ /^\xff\xd8\xff/ ? $val : undef; + }, + }, + Property => { + Name => 'PreviewInfo', + SubDirectory => { + TagTable => 'Image::ExifTool::FlashPix::PreviewInfo', + ByteOrder => 'BigEndian', + }, + }, +); + +# Summary Information properties +%Image::ExifTool::FlashPix::SummaryInfo = ( + PROCESS_PROC => \&ProcessProperties, + GROUPS => { 2 => 'Document' }, + NOTES => q{ + The Dictionary, CodePage and LocalIndicator tags are common to all FlashPix + property tables, even though they are only listed in the SummaryInfo table. + }, + 0x00 => { Name => 'Dictionary', Groups => { 2 => 'Other' }, Binary => 1 }, + 0x01 => { + Name => 'CodePage', + Groups => { 2 => 'Other' }, + PrintConv => \%codePage, + }, + 0x02 => 'Title', + 0x03 => 'Subject', + 0x04 => { Name => 'Author', Groups => { 2 => 'Author' } }, + 0x05 => 'Keywords', + 0x06 => 'Comments', + 0x07 => 'Template', + 0x08 => { Name => 'LastModifiedBy', Groups => { 2 => 'Author' } }, + 0x09 => 'RevisionNumber', + 0x0a => { Name => 'TotalEditTime', PrintConv => 'ConvertTimeSpan($val)' }, # (in sec) + 0x0b => { Name => 'LastPrinted', Groups => { 2 => 'Time' } }, + 0x0c => { + Name => 'CreateDate', + Groups => { 2 => 'Time' }, + PrintConv => '$self->ConvertDateTime($val)', + }, + 0x0d => { + Name => 'ModifyDate', + Groups => { 2 => 'Time' }, + PrintConv => '$self->ConvertDateTime($val)', + }, + 0x0e => 'Pages', + 0x0f => 'Words', + 0x10 => 'Characters', + 0x11 => { + Name => 'ThumbnailClip', + # (not a displayable format, so not in the "Preview" group) + Binary => 1, + }, + 0x12 => { + Name => 'Software', + RawConv => '$$self{Software} = $val', # (use to determine file type) + }, + 0x13 => { + Name => 'Security', + # see http://msdn.microsoft.com/en-us/library/aa379255(VS.85).aspx + PrintConv => { + 0 => 'None', + BITMASK => { + 0 => 'Password protected', + 1 => 'Read-only recommended', + 2 => 'Read-only enforced', + 3 => 'Locked for annotations', + }, + }, + }, + 0x22 => { Name => 'CreatedBy', Groups => { 2 => 'Author' } }, #PH (guess) (MAX files) + 0x23 => 'DocumentID', # PH (guess) (MAX files) + # 0x25 ? seen values 1.0-1.97 (MAX files) + 0x80000000 => { Name => 'LocaleIndicator', Groups => { 2 => 'Other' } }, +); + +# Document Summary Information properties (ref 4) +%Image::ExifTool::FlashPix::DocumentInfo = ( + PROCESS_PROC => \&ProcessProperties, + GROUPS => { 2 => 'Document' }, + NOTES => q{ + The DocumentSummaryInformation property set includes a UserDefined property + set for which only the Hyperlinks and HyperlinkBase tags are pre-defined. + However, ExifTool will also extract any other information found in the + UserDefined properties. + }, + 0x02 => 'Category', + 0x03 => 'PresentationTarget', + 0x04 => 'Bytes', + 0x05 => 'Lines', + 0x06 => 'Paragraphs', + 0x07 => 'Slides', + 0x08 => 'Notes', + 0x09 => 'HiddenSlides', + 0x0a => 'MMClips', + 0x0b => { + Name => 'ScaleCrop', + PrintConv => { 0 => 'No', 1 => 'Yes' }, + }, + 0x0c => 'HeadingPairs', + 0x0d => { + Name => 'TitleOfParts', + # look for "3ds Max" software name at beginning of TitleOfParts + RawConv => q{ + (ref $val eq 'ARRAY' ? $$val[0] : $val) =~ /^(3ds Max)/ and $$self{Software} = $1; + return $val; + } + }, + 0x0e => 'Manager', + 0x0f => 'Company', + 0x10 => { + Name => 'LinksUpToDate', + PrintConv => { 0 => 'No', 1 => 'Yes' }, + }, + 0x11 => 'CharCountWithSpaces', + # 0x12 ? seen -32.1850395202637,-386.220672607422,-9.8100004196167,-9810,... + 0x13 => { #PH (unconfirmed) + Name => 'SharedDoc', + PrintConv => { 0 => 'No', 1 => 'Yes' }, + }, + # 0x14 ? seen -1 + # 0x15 ? seen 1 + 0x16 => { + Name => 'HyperlinksChanged', + PrintConv => { 0 => 'No', 1 => 'Yes' }, + }, + 0x17 => { #PH (unconfirmed handling of lower 16 bits, not valid for MAX files) + Name => 'AppVersion', + ValueConv => 'sprintf("%d.%.4d",$val >> 16, $val & 0xffff)', + }, + # 0x18 ? seen -1 + # 0x19 ? seen 0 + # 0x1a ? seen 0 + # 0x1b ? seen 0 + # 0x1c ? seen 0,1 + # 0x1d ? seen 1 + # 0x1e ? seen 1 + # 0x1f ? seen 1,5 + # 0x20 ? seen 0,5 + # 0x21 ? seen -1 + # 0x22 ? seen 0 + '_PID_LINKBASE' => { + Name => 'HyperlinkBase', + ValueConv => '$self->Decode($val, "UCS2","II")', + }, + '_PID_HLINKS' => { + Name => 'Hyperlinks', + RawConv => \&ProcessHyperlinks, + }, +); + +# Image Information properties +%Image::ExifTool::FlashPix::ImageInfo = ( + PROCESS_PROC => \&ProcessProperties, + GROUPS => { 2 => 'Image' }, + 0x21000000 => { + Name => 'FileSource', + PrintConv => { + 1 => 'Film Scanner', + 2 => 'Reflection Print Scanner', + 3 => 'Digital Camera', + 4 => 'Video Capture', + 5 => 'Computer Graphics', + }, + }, + 0x21000001 => { + Name => 'SceneType', + PrintConv => { + 1 => 'Original Scene', + 2 => 'Second Generation Scene', + 3 => 'Digital Scene Generation', + }, + }, + 0x21000002 => 'CreationPathVector', + 0x21000003 => 'SoftwareRelease', + 0x21000004 => 'UserDefinedID', + 0x21000005 => 'SharpnessApproximation', + 0x22000000 => { Name => 'Copyright', Groups => { 2 => 'Author' } }, + 0x22000001 => { Name => 'OriginalImageBroker', Groups => { 2 => 'Author' } }, + 0x22000002 => { Name => 'DigitalImageBroker', Groups => { 2 => 'Author' } }, + 0x22000003 => { Name => 'Authorship', Groups => { 2 => 'Author' } }, + 0x22000004 => { Name => 'IntellectualPropertyNotes', Groups => { 2 => 'Author' } }, + 0x23000000 => { + Name => 'TestTarget', + PrintConv => { + 1 => 'Color Chart', + 2 => 'Gray Card', + 3 => 'Grayscale', + 4 => 'Resolution Chart', + 5 => 'Inch Scale', + 6 => 'Centimeter Scale', + 7 => 'Millimeter Scale', + 8 => 'Micrometer Scale', + }, + }, + 0x23000002 => 'GroupCaption', + 0x23000003 => 'CaptionText', + 0x23000004 => 'People', + 0x23000007 => 'Things', + 0x2300000A => { + Name => 'DateTimeOriginal', + Description => 'Date/Time Original', + Groups => { 2 => 'Time' }, + PrintConv => '$self->ConvertDateTime($val)', + }, + 0x2300000B => 'Events', + 0x2300000C => 'Places', + 0x2300000F => 'ContentDescriptionNotes', + 0x24000000 => { Name => 'Make', Groups => { 2 => 'Camera' } }, + 0x24000001 => { + Name => 'Model', + Description => 'Camera Model Name', + Groups => { 2 => 'Camera' }, + }, + 0x24000002 => { Name => 'SerialNumber', Groups => { 2 => 'Camera' } }, + 0x25000000 => { + Name => 'CreateDate', + Groups => { 2 => 'Time' }, + PrintConv => '$self->ConvertDateTime($val)', + }, + 0x25000001 => { + Name => 'ExposureTime', + PrintConv => 'Image::ExifTool::Exif::PrintExposureTime($val)', + }, + 0x25000002 => { + Name => 'FNumber', + PrintConv => 'sprintf("%.1f",$val)', + }, + 0x25000003 => { + Name => 'ExposureProgram', + Groups => { 2 => 'Camera' }, + # use PrintConv of corresponding EXIF tag + PrintConv => $Image::ExifTool::Exif::Main{0x8822}->{PrintConv}, + }, + 0x25000004 => 'BrightnessValue', + 0x25000005 => 'ExposureCompensation', + 0x25000006 => { + Name => 'SubjectDistance', + Groups => { 2 => 'Camera' }, + PrintConv => 'sprintf("%.3f m", $val)', + }, + 0x25000007 => { + Name => 'MeteringMode', + Groups => { 2 => 'Camera' }, + PrintConv => $Image::ExifTool::Exif::Main{0x9207}->{PrintConv}, + }, + 0x25000008 => { + Name => 'LightSource', + Groups => { 2 => 'Camera' }, + PrintConv => $Image::ExifTool::Exif::Main{0x9208}->{PrintConv}, + }, + 0x25000009 => { + Name => 'FocalLength', + Groups => { 2 => 'Camera' }, + PrintConv => 'sprintf("%.1f mm",$val)', + }, + 0x2500000A => { + Name => 'MaxApertureValue', + Groups => { 2 => 'Camera' }, + ValueConv => '2 ** ($val / 2)', + PrintConv => 'sprintf("%.1f",$val)', + }, + 0x2500000B => { + Name => 'Flash', + Groups => { 2 => 'Camera' }, + PrintConv => { + 1 => 'No Flash', + 2 => 'Flash Fired', + }, + }, + 0x2500000C => { + Name => 'FlashEnergy', + Groups => { 2 => 'Camera' }, + }, + 0x2500000D => { + Name => 'FlashReturn', + Groups => { 2 => 'Camera' }, + PrintConv => { + 1 => 'Subject Outside Flash Range', + 2 => 'Subject Inside Flash Range', + }, + }, + 0x2500000E => { + Name => 'BackLight', + PrintConv => { + 1 => 'Front Lit', + 2 => 'Back Lit 1', + 3 => 'Back Lit 2', + }, + }, + 0x2500000F => { Name => 'SubjectLocation', Groups => { 2 => 'Camera' } }, + 0x25000010 => 'ExposureIndex', + 0x25000011 => { + Name => 'SpecialEffectsOpticalFilter', + PrintConv => { + 1 => 'None', + 2 => 'Colored', + 3 => 'Diffusion', + 4 => 'Multi-image', + 5 => 'Polarizing', + 6 => 'Split-field', + 7 => 'Star', + }, + }, + 0x25000012 => 'PerPictureNotes', + 0x26000000 => { + Name => 'SensingMethod', + Groups => { 2 => 'Camera' }, + PrintConv => $Image::ExifTool::Exif::Main{0x9217}->{PrintConv}, + }, + 0x26000001 => { Name => 'FocalPlaneXResolution', Groups => { 2 => 'Camera' } }, + 0x26000002 => { Name => 'FocalPlaneYResolution', Groups => { 2 => 'Camera' } }, + 0x26000003 => { + Name => 'FocalPlaneResolutionUnit', + Groups => { 2 => 'Camera' }, + PrintConv => $Image::ExifTool::Exif::Main{0xa210}->{PrintConv}, + }, + 0x26000004 => 'SpatialFrequencyResponse', + 0x26000005 => 'CFAPattern', + 0x27000001 => { + Name => 'FilmCategory', + PrintConv => { + 1 => 'Negative B&W', + 2 => 'Negative Color', + 3 => 'Reversal B&W', + 4 => 'Reversal Color', + 5 => 'Chromagenic', + 6 => 'Internegative B&W', + 7 => 'Internegative Color', + }, + }, + 0x26000007 => 'ISO', + 0x26000008 => 'Opto-ElectricConvFactor', + 0x27000000 => 'FilmBrand', + 0x27000001 => 'FilmCategory', + 0x27000002 => 'FilmSize', + 0x27000003 => 'FilmRollNumber', + 0x27000004 => 'FilmFrameNumber', + 0x29000000 => 'OriginalScannedImageSize', + 0x29000001 => 'OriginalDocumentSize', + 0x29000002 => { + Name => 'OriginalMedium', + PrintConv => { + 1 => 'Continuous Tone Image', + 2 => 'Halftone Image', + 3 => 'Line Art', + }, + }, + 0x29000003 => { + Name => 'TypeOfOriginal', + PrintConv => { + 1 => 'B&W Print', + 2 => 'Color Print', + 3 => 'B&W Document', + 4 => 'Color Document', + }, + }, + 0x28000000 => 'ScannerMake', + 0x28000001 => 'ScannerModel', + 0x28000002 => 'ScannerSerialNumber', + 0x28000003 => 'ScanSoftware', + 0x28000004 => { Name => 'ScanSoftwareRevisionDate', Groups => { 2 => 'Time' } }, + 0x28000005 => 'ServiceOrganizationName', + 0x28000006 => 'ScanOperatorID', + 0x28000008 => { + Name => 'ScanDate', + Groups => { 2 => 'Time' }, + PrintConv => '$self->ConvertDateTime($val)', + }, + 0x28000009 => { + Name => 'ModifyDate', + Groups => { 2 => 'Time' }, + PrintConv => '$self->ConvertDateTime($val)', + }, + 0x2800000A => 'ScannerPixelSize', +); + +# Image Contents properties +%Image::ExifTool::FlashPix::Image = ( + PROCESS_PROC => \&ProcessProperties, + GROUPS => { 2 => 'Image' }, + # VARS storage is used as a hash lookup for tagID's which aren't constant. + # The key is a mask for significant bits of the tagID, and the value + # is a lookup for tagID's for which this mask is valid. + VARS => { + # ID's are different for each subimage + 0xff00ffff => { + 0x02000000=>1, 0x02000001=>1, 0x02000002=>1, 0x02000003=>1, + 0x02000004=>1, 0x02000005=>1, 0x02000006=>1, 0x02000007=>1, + 0x03000001=>1, + }, + }, + 0x01000000 => 'NumberOfResolutions', + 0x01000002 => 'ImageWidth', # width of highest resolution image + 0x01000003 => 'ImageHeight', + 0x01000004 => 'DefaultDisplayHeight', + 0x01000005 => 'DefaultDisplayWidth', + 0x01000006 => { + Name => 'DisplayUnits', + PrintConv => { + 0 => 'inches', + 1 => 'meters', + 2 => 'cm', + 3 => 'mm', + }, + }, + 0x02000000 => 'SubimageWidth', + 0x02000001 => 'SubimageHeight', + 0x02000002 => { + Name => 'SubimageColor', + # decode only component count and color space of first component + ValueConv => 'sprintf("%.2x %.4x", unpack("x4vx4v",$val))', + PrintConv => { + '01 0000' => 'Opacity Only', + '01 8000' => 'Opacity Only (uncalibrated)', + '01 0001' => 'Monochrome', + '01 8001' => 'Monochrome (uncalibrated)', + '03 0002' => 'YCbCr', + '03 8002' => 'YCbCr (uncalibrated)', + '03 0003' => 'RGB', + '03 8003' => 'RGB (uncalibrated)', + '04 0002' => 'YCbCr with Opacity', + '04 8002' => 'YCbCr with Opacity (uncalibrated)', + '04 0003' => 'RGB with Opacity', + '04 8003' => 'RGB with Opacity (uncalibrated)', + }, + }, + 0x02000003 => { + Name => 'SubimageNumericalFormat', + PrintConv => { + 17 => '8-bit, Unsigned', + 18 => '16-bit, Unsigned', + 19 => '32-bit, Unsigned', + }, + }, + 0x02000004 => { + Name => 'DecimationMethod', + PrintConv => { + 0 => 'None (Full-sized Image)', + 8 => '8-point Prefilter', + }, + }, + 0x02000005 => 'DecimationPrefilterWidth', + 0x02000007 => 'SubimageICC_Profile', + 0x03000001 => { Name => 'JPEGTables', Binary => 1 }, + 0x03000002 => 'MaxJPEGTableIndex', +); + +# Extension List properties +%Image::ExifTool::FlashPix::Extensions = ( + PROCESS_PROC => \&ProcessProperties, + GROUPS => { 2 => 'Other' }, + VARS => { + # ID's are different for each extension type + 0x0000ffff => { + 0x0001=>1, 0x0002=>1, 0x0003=>1, 0x0004=>1, + 0x0005=>1, 0x0006=>1, 0x0007=>1, 0x1000=>1, + 0x2000=>1, 0x2001=>1, 0x3000=>1, 0x4000=>1, + }, + 0x0000f00f => { 0x3001=>1, 0x3002=>1 }, + }, + 0x10000000 => 'UsedExtensionNumbers', + 0x0001 => 'ExtensionName', + 0x0002 => 'ExtensionClassID', + 0x0003 => { + Name => 'ExtensionPersistence', + PrintConv => { + 0 => 'Always Valid', + 1 => 'Invalidated By Modification', + 2 => 'Potentially Invalidated By Modification', + }, + }, + 0x0004 => { Name => 'ExtensionCreateDate', Groups => { 2 => 'Time' } }, + 0x0005 => { Name => 'ExtensionModifyDate', Groups => { 2 => 'Time' } }, + 0x0006 => 'CreatingApplication', + 0x0007 => 'ExtensionDescription', + 0x1000 => 'Storage-StreamPathname', + 0x2000 => 'FlashPixStreamPathname', + 0x2001 => 'FlashPixStreamFieldOffset', + 0x3000 => 'PropertySetPathname', + 0x3001 => 'PropertySetIDCodes', + 0x3002 => 'PropertyVectorElements', + 0x4000 => 'SubimageResolutions', +); + +# Subimage Header tags +%Image::ExifTool::FlashPix::SubimageHdr = ( + PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData, + FORMAT => 'int32u', +# 0 => 'HeaderLength', + 1 => 'SubimageWidth', + 2 => 'SubimageHeight', + 3 => 'SubimageTileCount', + 4 => 'SubimageTileWidth', + 5 => 'SubimageTileHeight', + 6 => 'NumChannels', +# 7 => 'TileHeaderOffset', +# 8 => 'TileHeaderLength', + # ... followed by tile header table +); + +# Data Object properties +%Image::ExifTool::FlashPix::DataObject = ( + PROCESS_PROC => \&ProcessProperties, + GROUPS => { 2 => 'Other' }, + 0x00010000 => 'DataObjectID', + 0x00010002 => 'LockedPropertyList', + 0x00010003 => 'DataObjectTitle', + 0x00010004 => 'LastModifier', + 0x00010005 => 'RevisionNumber', + 0x00010006 => { Name => 'DataCreateDate', Groups => { 2 => 'Time' } }, + 0x00010007 => { Name => 'DataModifyDate', Groups => { 2 => 'Time' } }, + 0x00010008 => 'CreatingApplication', + 0x00010100 => { + Name => 'DataObjectStatus', + PrintConv => q{ + ($val & 0x0000ffff ? 'Exists' : 'Does Not Exist') . + ', ' . ($val & 0xffff0000 ? 'Not ' : '') . 'Purgeable' + }, + }, + 0x00010101 => { + Name => 'CreatingTransform', + PrintConv => '$val ? $val : "Source Image"', + }, + 0x00010102 => 'UsingTransforms', + 0x10000000 => 'CachedImageHeight', + 0x10000001 => 'CachedImageWidth', +); + +# Transform properties +%Image::ExifTool::FlashPix::Transform = ( + PROCESS_PROC => \&ProcessProperties, + GROUPS => { 2 => 'Other' }, + 0x00010000 => 'TransformNodeID', + 0x00010001 => 'OperationClassID', + 0x00010002 => 'LockedPropertyList', + 0x00010003 => 'TransformTitle', + 0x00010004 => 'LastModifier', + 0x00010005 => 'RevisionNumber', + 0x00010006 => { Name => 'TransformCreateDate', Groups => { 2 => 'Time' } }, + 0x00010007 => { Name => 'TransformModifyDate', Groups => { 2 => 'Time' } }, + 0x00010008 => 'CreatingApplication', + 0x00010100 => 'InputDataObjectList', + 0x00010101 => 'OutputDataObjectList', + 0x00010102 => 'OperationNumber', + 0x10000000 => 'ResultAspectRatio', + 0x10000001 => 'RectangleOfInterest', + 0x10000002 => 'Filtering', + 0x10000003 => 'SpatialOrientation', + 0x10000004 => 'ColorTwistMatrix', + 0x10000005 => 'ContrastAdjustment', +); + +# Operation properties +%Image::ExifTool::FlashPix::Operation = ( + PROCESS_PROC => \&ProcessProperties, + 0x00010000 => 'OperationID', +); + +# Global Info properties +%Image::ExifTool::FlashPix::GlobalInfo = ( + PROCESS_PROC => \&ProcessProperties, + 0x00010002 => 'LockedPropertyList', + 0x00010003 => 'TransformedImageTitle', + 0x00010004 => 'LastModifier', + 0x00010100 => 'VisibleOutputs', + 0x00010101 => 'MaximumImageIndex', + 0x00010102 => 'MaximumTransformIndex', + 0x00010103 => 'MaximumOperationIndex', +); + +# Audio Info properties +%Image::ExifTool::FlashPix::AudioInfo = ( + PROCESS_PROC => \&ProcessProperties, + GROUPS => { 2 => 'Audio' }, +); + +# MacroMedia flash contents +%Image::ExifTool::FlashPix::Contents = ( + PROCESS_PROC => \&ProcessProperties, + GROUPS => { 2 => 'Image' }, +); + +# CompObj tags +%Image::ExifTool::FlashPix::CompObj = ( + PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData, + GROUPS => { 2 => 'Other' }, + FORMAT => 'int32u', + 0 => { Name => 'CompObjUserTypeLen' }, + 1 => { + Name => 'CompObjUserType', + Format => 'string[$val{0}]', + RawConv => '$$self{CompObjUserType} = $val', # (use to determine file type) + }, +); + +# decode Word document FIB header (ref [MS-DOC].pdf) +%Image::ExifTool::FlashPix::WordDocument = ( + PROCESS_PROC => \&ProcessWordDocument, + GROUPS => { 2 => 'Other' }, + FORMAT => 'int16u', + NOTES => 'Tags extracted from the Microsoft Word document stream.', + 0 => { + Name => 'Identification', + PrintHex => 1, + PrintConv => { + 0x6a62 => 'MS Word 97', + 0x626a => 'Word 98 Mac', + 0xa5dc => 'Word 6.0/7.0', + 0xa5ec => 'Word 8.0', + }, + }, + 3 => { + Name => 'LanguageCode', + PrintHex => 1, + PrintConv => { + 0x0400 => 'None', + 0x0401 => 'Arabic', + 0x0402 => 'Bulgarian', + 0x0403 => 'Catalan', + 0x0404 => 'Traditional Chinese', + 0x0804 => 'Simplified Chinese', + 0x0405 => 'Czech', + 0x0406 => 'Danish', + 0x0407 => 'German', + 0x0807 => 'German (Swiss)', + 0x0408 => 'Greek', + 0x0409 => 'English (US)', + 0x0809 => 'English (British)', + 0x0c09 => 'English (Australian)', + 0x040a => 'Spanish (Castilian)', + 0x080a => 'Spanish (Mexican)', + 0x040b => 'Finnish', + 0x040c => 'French', + 0x080c => 'French (Belgian)', + 0x0c0c => 'French (Canadian)', + 0x100c => 'French (Swiss)', + 0x040d => 'Hebrew', + 0x040e => 'Hungarian', + 0x040f => 'Icelandic', + 0x0410 => 'Italian', + 0x0810 => 'Italian (Swiss)', + 0x0411 => 'Japanese', + 0x0412 => 'Korean', + 0x0413 => 'Dutch', + 0x0813 => 'Dutch (Belgian)', + 0x0414 => 'Norwegian (Bokmal)', + 0x0814 => 'Norwegian (Nynorsk)', + 0x0415 => 'Polish', + 0x0416 => 'Portuguese (Brazilian)', + 0x0816 => 'Portuguese', + 0x0417 => 'Rhaeto-Romanic', + 0x0418 => 'Romanian', + 0x0419 => 'Russian', + 0x041a => 'Croato-Serbian (Latin)', + 0x081a => 'Serbo-Croatian (Cyrillic)', + 0x041b => 'Slovak', + 0x041c => 'Albanian', + 0x041d => 'Swedish', + 0x041e => 'Thai', + 0x041f => 'Turkish', + 0x0420 => 'Urdu', + 0x0421 => 'Bahasa', + 0x0422 => 'Ukrainian', + 0x0423 => 'Byelorussian', + 0x0424 => 'Slovenian', + 0x0425 => 'Estonian', + 0x0426 => 'Latvian', + 0x0427 => 'Lithuanian', + 0x0429 => 'Farsi', + 0x042d => 'Basque', + 0x042f => 'Macedonian', + 0x0436 => 'Afrikaans', + 0x043e => 'Malaysian', + }, + }, + 5 => { + Name => 'DocFlags', + Mask => 0xff0f, # ignore save count + RawConv => '$$self{DocFlags} = $val', + PrintConv => { BITMASK => { + 0 => 'Template', + 1 => 'AutoText only', + 2 => 'Complex', + 3 => 'Has picture', + # 4-7 = number of incremental saves + 8 => 'Encrypted', + 9 => '1Table', + 10 => 'Read only', + 11 => 'Passworded', + 12 => 'ExtChar', + 13 => 'Load override', + 14 => 'Far east', + 15 => 'Obfuscated', + }}, + }, + 9.1 => { + Name => 'System', + Mask => 0x0001, + PrintConv => { + 0x0000 => 'Windows', + 0x0001 => 'Macintosh', + }, + }, + 9.2 => { + Name => 'Word97', + Mask => 0x0010, + PrintConv => { 0 => 'No', 1 => 'Yes' }, + }, +); + +# tags decoded from Word document table +%Image::ExifTool::FlashPix::DocTable = ( + GROUPS => { 1 => 'MS-DOC', 2 => 'Document' }, + NOTES => 'Tags extracted from the Microsoft Word document table.', + VARS => { NO_ID => 1 }, + CommentBy => { + Groups => { 2 => 'Author' }, + Notes => 'enable Duplicates option to extract all entries', + }, + LastSavedBy => { + Groups => { 2 => 'Author' }, + Notes => 'enable Duplicates option to extract history of up to 10 entries', + }, + DOP => { SubDirectory => { TagTable => 'Image::ExifTool::FlashPix::DOP' } }, + ModifyDate => { + Groups => { 2 => 'Time' }, + Format => 'int64u', + Priority => 0, + RawConv => q{ + $val = $val * 1e-7 - 11644473600; # convert to seconds since 1970 + return $val > 0 ? $val : undef; + }, + ValueConv => 'ConvertUnixTime($val)', + PrintConv => '$self->ConvertDateTime($val)', + }, +# +# tags below are used internally in intermediate steps to extract the tags above +# + TableOffsets => { Hidden => 1 }, # stores offsets to extract data from document table + CommentByBlock => { # entire block of CommentBy entries + SubDirectory => { + TagTable => 'Image::ExifTool::FlashPix::DocTable', + ProcessProc => \&ProcessCommentBy, + }, + Hidden => 1, + }, + LastSavedByBlock => { # entire block of LastSavedBy entries + SubDirectory => { + TagTable => 'Image::ExifTool::FlashPix::DocTable', + ProcessProc => \&ProcessLastSavedBy, + }, + Hidden => 1, + }, +); + +# Microsoft Office Document Properties (ref [MS-DOC].pdf) +%Image::ExifTool::FlashPix::DOP = ( + PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData, + GROUPS => { 1 => 'MS-DOC', 2 => 'Document' }, + NOTES => 'Microsoft office document properties.', + 20 => { + Name => 'CreateDate', + Format => 'int32u', + Groups => { 2 => 'Time' }, + Priority => 0, + RawConv => \&ConvertDTTM, + PrintConv => '$self->ConvertDateTime($val)', + }, + 24 => { + Name => 'ModifyDate', + Format => 'int32u', + Groups => { 2 => 'Time' }, + Priority => 0, + RawConv => \&ConvertDTTM, + PrintConv => '$self->ConvertDateTime($val)', + }, + 28 => { + Name => 'LastPrinted', + Format => 'int32u', + Groups => { 2 => 'Time' }, + RawConv => \&ConvertDTTM, + PrintConv => '$self->ConvertDateTime($val)', + }, + 32 => { Name => 'RevisionNumber', Format => 'int16u' }, + 34 => { + Name => 'TotalEditTime', + Format => 'int32u', + PrintConv => 'ConvertTimeSpan($val,60)', + }, + # (according to the MS-DOC specification, the following are accurate only if + # flag 'X' is set, and flag 'u' specifies whether the main or subdoc tags are + # used, but in my tests it seems that both are filled in with reasonable values, + # so just extract the main counts and ignore the subdoc counts for now - PH) + 38 => { Name => 'Words', Format => 'int32u' }, + 42 => { Name => 'Characters', Format => 'int32u' }, + 46 => { Name => 'Pages', Format => 'int16u' }, + 48 => { Name => 'Paragraphs', Format => 'int32u' }, + 56 => { Name => 'Lines', Format => 'int32u' }, + #60 => { Name => 'WordsWithSubdocs', Format => 'int32u' }, + #64 => { Name => 'CharactersWithSubdocs', Format => 'int32u' }, + #68 => { Name => 'PagesWithSubdocs', Format => 'int16u' }, + #70 => { Name => 'ParagraphsWithSubdocs', Format => 'int32u' }, + #74 => { Name => 'LinesWithSubdocs', Format => 'int32u' }, +); + +# FujiFilm "Property" information (ref PH) +%Image::ExifTool::FlashPix::PreviewInfo = ( + PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData, + GROUPS => { 2 => 'Image' }, + NOTES => 'Preview information written by some FujiFilm models.', + FIRST_ENTRY => 0, + # values are all constant for for my samples except the two decoded tags + # 0x0000: 01 01 00 00 02 01 00 00 00 00 00 00 00 xx xx 01 + # 0x0010: 01 00 00 00 00 00 00 xx xx 00 00 00 00 00 00 00 + # 0x0020: 00 00 00 00 00 + 0x0d => { + Name => 'PreviewImageWidth', + Format => 'int16u', + }, + 0x17 => { + Name => 'PreviewImageHeight', + Format => 'int16u', + }, +); + +# composite FlashPix tags +%Image::ExifTool::FlashPix::Composite = ( + GROUPS => { 2 => 'Image' }, + PreviewImage => { + Groups => { 2 => 'Preview' }, + # extract JPEG preview from ScreenNail if possible + Require => { + 0 => 'ScreenNail', + }, + Binary => 1, + RawConv => q{ + return undef unless $val[0] =~ /\xff\xd8\xff/g; + @grps = $self->GetGroup($$val{0}); # set groups from ScreenNail + return substr($val[0], pos($val[0])-3); + }, + }, +); + +# add our composite tags +Image::ExifTool::AddCompositeTags('Image::ExifTool::FlashPix'); + +#------------------------------------------------------------------------------ +# Convert Microsoft DTTM structure to date/time +# Inputs: 0) DTTM value +# Returns: EXIF-format date/time string ("0000:00:00 00:00:00" for zero date/time) +sub ConvertDTTM($) +{ + my $val = shift; + my $yr = ($val >> 20) & 0x1ff; + my $mon = ($val >> 16) & 0x0f; + my $day = ($val >> 11) & 0x1f; + my $hr = ($val >> 6) & 0x1f; + my $min = ($val & 0x3f); + $yr += 1900 if $val; + return sprintf("%.4d:%.2d:%.2d %.2d:%.2d:00%s",$yr,$mon,$day,$hr,$min,$val ? 'Z' : ''); +} + +#------------------------------------------------------------------------------ +# Process hyperlinks from PID_HYPERLINKS array +# (ref http://msdn.microsoft.com/archive/default.asp?url=/archive/en-us/dnaro97ta/html/msdn_hyper97.asp) +# Inputs: 0) value, 1) ExifTool ref +# Returns: list of hyperlinks +sub ProcessHyperlinks($$) +{ + my ($val, $et) = @_; + + # process as an array of VT_VARIANT's + my $dirEnd = length $val; + return undef if $dirEnd < 4; + my $num = Get32u(\$val, 0); + my $valPos = 4; + my ($i, @vals); + for ($i=0; $i<$num; ++$i) { + # read VT_BLOB entries as an array of VT_VARIANT's + my $value = ReadFPXValue($et, \$val, $valPos, VT_VARIANT, $dirEnd); + last unless defined $value; + push @vals, $value; + } + # filter values to extract only the links + my @links; + for ($i=0; $i<@vals; $i+=6) { + push @links, $vals[$i+4]; # get address + $links[-1] .= '#' . $vals[$i+5] if length $vals[$i+5]; # add subaddress + } + return \@links; +} + +#------------------------------------------------------------------------------ +# Read FlashPix value +# Inputs: 0) ExifTool ref, 1) data ref, 2) value offset, 3) FPX format number, +# 4) end offset, 5) flag for no padding, 6) code page +# Returns: converted value (or list of values in list context) and updates +# value offset to end of value if successful, or returns undef on error +sub ReadFPXValue($$$$$;$$) +{ + my ($et, $dataPt, $valPos, $type, $dirEnd, $noPad, $codePage) = @_; + my @vals; + + my $format = $oleFormat{$type & 0x0fff}; + while ($format) { + my $count = 1; + # handle VT_VECTOR types + my $flags = $type & 0xf000; + if ($flags) { + if ($flags == VT_VECTOR) { + $noPad = 1; # values don't seem to be padded inside vectors + my $size = $oleFormatSize{VT_VECTOR}; + last if $valPos + $size > $dirEnd; + $count = Get32u($dataPt, $valPos); + push @vals, '' if $count == 0; # allow zero-element vector + $valPos += 4; + } else { + # can't yet handle this property flag + last; + } + } + unless ($format =~ /^VT_/) { + my $size = Image::ExifTool::FormatSize($format) * $count; + last if $valPos + $size > $dirEnd; + @vals = ReadValue($dataPt, $valPos, $format, $count, $size); + # update position to end of value plus padding + $valPos += ($count * $size + 3) & 0xfffffffc; + last; + } + my $size = $oleFormatSize{$format}; + my ($item, $val); + for ($item=0; $item<$count; ++$item) { + last if $valPos + $size > $dirEnd; + if ($format eq 'VT_VARIANT') { + my $subType = Get32u($dataPt, $valPos); + $valPos += $size; + $val = ReadFPXValue($et, $dataPt, $valPos, $subType, $dirEnd, $noPad, $codePage); + last unless defined $val; + push @vals, $val; + next; # avoid adding $size to $valPos again + } elsif ($format eq 'VT_FILETIME') { + # convert from time in 100 ns increments to time in seconds + $val = 1e-7 * Image::ExifTool::Get64u($dataPt, $valPos); + # print as date/time if value is greater than one year (PH hack) + my $secDay = 24 * 3600; + if ($val > 365 * $secDay) { + # shift from Jan 1, 1601 to Jan 1, 1970 + my $unixTimeZero = 134774 * $secDay; + $val -= $unixTimeZero; + # there are a lot of bad programmers out there... + my $sec100yr = 100 * 365 * $secDay; + if ($val < 0 || $val > $sec100yr) { + # some software writes the wrong byte order (but the proper word order) + my @w = unpack("x${valPos}NN", $$dataPt); + my $v2 = ($w[0] + $w[1] * 4294967296) * 1e-7 - $unixTimeZero; + if ($v2 > 0 && $v2 < $sec100yr) { + $val = $v2; + # also check for wrong time base + } elsif ($val < 0 && $val + $unixTimeZero > 0) { + $val += $unixTimeZero; + } + } + $val = Image::ExifTool::ConvertUnixTime($val); + } + } elsif ($format eq 'VT_DATE') { + $val = Image::ExifTool::GetDouble($dataPt, $valPos); + # shift zero from Dec 30, 1899 to Jan 1, 1970 and convert to secs + $val = ($val - 25569) * 24 * 3600 if $val != 0; + $val = Image::ExifTool::ConvertUnixTime($val); + } elsif ($format =~ /STR$/) { + my $len = Get32u($dataPt, $valPos); + $len *= 2 if $format eq 'VT_LPWSTR'; # convert to byte count + last if $valPos + $len + 4 > $dirEnd; + $val = substr($$dataPt, $valPos + 4, $len); + if ($format eq 'VT_LPWSTR') { + # convert wide string from Unicode + $val = $et->Decode($val, 'UCS2'); + } elsif ($codePage) { + my $charset = $Image::ExifTool::charsetName{"cp$codePage"}; + if ($charset) { + $val = $et->Decode($val, $charset); + } elsif ($codePage eq 1200) { # UTF-16, little endian + $val = $et->Decode($val, 'UCS2', 'II'); + } + } + $val =~ s/\0.*//s; # truncate at null terminator + # update position for string length + # (the spec states that strings should be padded to align + # on even 32-bit boundaries, but this isn't always the case) + $valPos += $noPad ? $len : ($len + 3) & 0xfffffffc; + } elsif ($format eq 'VT_BLOB' or $format eq 'VT_CF') { + my $len = Get32u($dataPt, $valPos); + last if $valPos + $len + 4 > $dirEnd; + $val = substr($$dataPt, $valPos + 4, $len); + # update position for data length plus padding + # (does this padding disappear in arrays too?) + $valPos += ($len + 3) & 0xfffffffc; + } elsif ($format eq 'VT_CLSID') { + $val = Image::ExifTool::ASF::GetGUID(substr($$dataPt, $valPos, $size)); + } + $valPos += $size; # update value pointer to end of value + push @vals, $val; + } + # join VT_ values with commas unless we want an array + @vals = ( join $et->Options('ListSep'), @vals ) if @vals > 1 and not wantarray; + last; # didn't really want to loop + } + $_[2] = $valPos; # return updated value position + + if (wantarray) { + return @vals; + } elsif (@vals > 1) { + return join(' ', @vals); + } else { + return $vals[0]; + } +} + +#------------------------------------------------------------------------------ +# Scan for XMP in FLA Contents (ref PH) +# Inputs: 0) ExifTool object ref, 1) dirInfo ref, 2) tag table ref +# Returns: 1 on success +# Notes: FLA format is proprietary and I couldn't find any documentation, +# so this routine is entirely based on observations from sample files +sub ProcessContents($$$) +{ + my ($et, $dirInfo, $tagTablePtr) = @_; + my $dataPt = $$dirInfo{DataPt}; + my $isFLA; + + # all of my FLA samples contain "Contents" data, and no other FPX-like samples have + # this, but check the data for a familiar pattern to be sure this is FLA: the + # Contents of all of my FLA samples start with two bytes (0x29,0x38,0x3f,0x43 or 0x47, + # then 0x01) followed by a number of zero bytes (from 0x18 to 0x26 of them, related + # somehow to the value of the first byte), followed by the string "DocumentPage" + $isFLA = 1 if $$dataPt =~ /^..\0+\xff\xff\x01\0\x0d\0CDocumentPage/s; + + # do a brute-force scan of the "Contents" for UTF-16 XMP + # (this may always be little-endian, but allow for either endianness) + if ($$dataPt =~ /<\0\?\0x\0p\0a\0c\0k\0e\0t\0 \0b\0e\0g\0i\0n\0=\0['"](\0\xff\xfe|\xfe\xff)/g) { + $$dirInfo{DirStart} = pos($$dataPt) - 36; + if ($$dataPt =~ /<\0\?\0x\0p\0a\0c\0k\0e\0t\0 \0e\0n\0d\0=\0['"]\0[wr]\0['"]\0\?\0>\0?/g) { + $$dirInfo{DirLen} = pos($$dataPt) - $$dirInfo{DirStart}; + Image::ExifTool::XMP::ProcessXMP($et, $dirInfo, $tagTablePtr); + # override format if not already FLA but XMP-dc:Format indicates it is + $isFLA = 1 if $$et{FILE_TYPE} ne 'FLA' and $$et{VALUE}{Format} and + $$et{VALUE}{Format} eq 'application/vnd.adobe.fla'; + } + } + $et->OverrideFileType('FLA') if $isFLA; + return 1; +} + +#------------------------------------------------------------------------------ +# Process WordDocument stream of MSWord doc file (ref 6) +# Inputs: 0) ExifTool object ref, 1) dirInfo ref, 2) tag table ref +# Returns: 1 on success +sub ProcessWordDocument($$$) +{ + my ($et, $dirInfo, $tagTablePtr) = @_; + my $dataPt = $$dirInfo{DataPt} or return 0; + my $dirLen = length $$dataPt; + # validate the FIB signature + unless ($dirLen > 2 and Get16u($dataPt,0) == 0xa5ec) { + $et->WarnOnce('Invalid FIB signature', 1); + return 0; + } + $et->ProcessBinaryData($dirInfo, $tagTablePtr); # process FIB + # continue parsing the WordDocument stream until we find the FibRgFcLcb + my $pos = 32; + return 0 if $pos + 2 > $dirLen; + my $n = Get16u($dataPt, $pos); # read csw + $pos += 2 + $n * 2; # skip fibRgW + return 0 if $pos + 2 > $dirLen; + $n = Get16u($dataPt, $pos); # read cslw + $pos += 2 + $n * 4; # skip fibRgLw + return 0 if $pos + 2 > $dirLen; + $n = Get16u($dataPt, $pos); # read cbRgFcLcb + $pos += 2; # point to start of fibRgFcLcbBlob + return 0 if $pos + $n * 8 > $dirLen; + my ($off, @tableOffsets); + # save necessary entries for later processing of document table + # (DOP, CommentBy, LastSavedBy) + foreach $off (0xf8, 0x120, 0x238) { + last if $off + 8 > $n * 8; + push @tableOffsets, Get32u($dataPt, $pos + $off); + push @tableOffsets, Get32u($dataPt, $pos + $off + 4); + } + my $tbl = GetTagTable('Image::ExifTool::FlashPix::DocTable'); + # extract ModifyDate if it exists + $et->HandleTag($tbl, 'ModifyDate', undef, + DataPt => $dataPt, + Start => $pos + 0x2b8, + Size => 8, + ); + $et->HandleTag($tbl, TableOffsets => \@tableOffsets); # save for later + # $pos += $n * 8; # skip fibRgFcLcbBlob + # return 0 if $pos + 2 > $dirLen; + # $n = Get16u($dataPt, $pos); # read cswNew + # return 0 if $pos + 2 + $n * 2 > $dirLen; + # my $nFib = Get16u($dataPt, 2 + ($n ? $pos : 0)); + # $pos += 2 + $n * 2; # skip fibRgCswNew + return 1; +} + +#------------------------------------------------------------------------------ +# Process Microsoft Word Document Table +# Inputs: 0) ExifTool object ref +sub ProcessDocumentTable($) +{ + my $et = shift; + my $value = $$et{VALUE}; + my $extra = $$et{TAG_EXTRA}; + my ($i, $j, $tag); + # loop through TableOffsets for each sub-document + for ($i=0; ; ++$i) { + my $key = 'TableOffsets' . ($i ? " ($i)" : ''); + my $offsets = $$value{$key}; + last unless defined $offsets; + my $doc = $$extra{$key}{G3} if $$extra{$key}; + $doc = '' unless $doc; + # get DocFlags for this sub-document + my ($docFlags, $docTable); + for ($j=0; ; ++$j) { + my $key = 'DocFlags' . ($j ? " ($j)" : ''); + last unless defined $$value{$key}; + my $tmp = $$extra{$key}{G3} if $$extra{$key}; + $tmp = '' unless $tmp; + if ($tmp eq $doc) { + $docFlags = $$value{$key}; + last; + } + } + next unless defined $docFlags; + $tag = $docFlags & 0x200 ? 'Table1' : 'Table0'; + # get table for this sub-document + for ($j=0; ; ++$j) { + my $key = $tag . ($j ? " ($j)" : ''); + last unless defined $$value{$key}; + my $tmp = $$extra{$key}{G3} if $$extra{$key}; + $tmp = '' unless $tmp; + if ($tmp eq $doc) { + $docTable = \$$value{$key}; + last; + } + } + next unless defined $docTable; + # extract DOP and LastSavedBy information from document table + $$et{DOC_NUM} = $doc; # use same document number + my $tagTablePtr = GetTagTable('Image::ExifTool::FlashPix::DocTable'); + foreach $tag (qw(DOP CommentByBlock LastSavedByBlock)) { + last unless @$offsets; + my $off = shift @$offsets; + my $len = shift @$offsets; + next unless $len and $off + $len <= length $$docTable; + $et->HandleTag($tagTablePtr, $tag, undef, + DataPt => $docTable, + Start => $off, + Size => $len, + ); + } + delete $$et{DOC_NUM}; + } + # delete intermediate tags + foreach $tag (qw(TableOffsets Table0 Table1)) { + for ($i=0; ; ++$i) { + my $key = $tag . ($i ? " ($i)" : ''); + last unless defined $$value{$key}; + $et->DeleteTag($key); + } + } +} + +#------------------------------------------------------------------------------ +# Extract names of comment authors (ref 6) +# Inputs: 0) ExifTool object ref, 1) dirInfo ref, 2) tag table ref +# Returns: 1 on success +sub ProcessCommentBy($$$) +{ + my ($et, $dirInfo, $tagTablePtr) = @_; + my $dataPt = $$dirInfo{DataPt}; + my $pos = $$dirInfo{DirStart}; + my $end = $$dirInfo{DirLen} + $pos; + $et->VerboseDir($$dirInfo{DirName}); + while ($pos + 2 < $end) { + my $len = Get16u($dataPt, $pos); + $pos += 2; + last if $pos + $len * 2 > $end; + my $author = $et->Decode(substr($$dataPt, $pos, $len*2), 'UCS2'); + $pos += $len * 2; + $et->HandleTag($tagTablePtr, CommentBy => $author); + } + return 1; +} + +#------------------------------------------------------------------------------ +# Extract last-saved-by names (ref 5) +# Inputs: 0) ExifTool object ref, 1) dirInfo ref, 2) tag table ref +# Returns: 1 on success +sub ProcessLastSavedBy($$$) +{ + my ($et, $dirInfo, $tagTablePtr) = @_; + my $dataPt = $$dirInfo{DataPt}; + my $pos = $$dirInfo{DirStart}; + my $end = $$dirInfo{DirLen} + $pos; + return 0 if $pos + 6 > $end; + $et->VerboseDir($$dirInfo{DirName}); + my $num = Get16u($dataPt, $pos+2); + $pos += 6; + while ($num >= 2) { + last if $pos + 2 > $end; + my $len = Get16u($dataPt, $pos); + $pos += 2; + last if $pos + $len * 2 > $end; + my $author = $et->Decode(substr($$dataPt, $pos, $len*2), 'UCS2'); + $pos += $len * 2; + last if $pos + 2 > $end; + $len = Get16u($dataPt, $pos); + $pos += 2; + last if $pos + $len * 2 > $end; + my $path = $et->Decode(substr($$dataPt, $pos, $len*2), 'UCS2'); + $pos += $len * 2; + $et->HandleTag($tagTablePtr, LastSavedBy => "$author ($path)"); + $num -= 2; + } + return 1; +} + +#------------------------------------------------------------------------------ +# Check FPX byte order mark (BOM) and set byte order appropriately +# Inputs: 0) data ref, 1) offset to BOM +# Returns: true on success +sub CheckBOM($$) +{ + my ($dataPt, $pos) = @_; + my $bom = Get16u($dataPt, $pos); + return 1 if $bom == 0xfffe; + return 0 unless $bom == 0xfeff; + ToggleByteOrder(); + return 1; +} + +#------------------------------------------------------------------------------ +# Process FlashPix properties +# Inputs: 0) ExifTool object ref, 1) dirInfo ref, 2) tag table ref +# Returns: 1 on success +sub ProcessProperties($$$) +{ + my ($et, $dirInfo, $tagTablePtr) = @_; + my $dataPt = $$dirInfo{DataPt}; + my $pos = $$dirInfo{DirStart} || 0; + my $dirLen = $$dirInfo{DirLen} || length($$dataPt) - $pos; + my $dirEnd = $pos + $dirLen; + my $verbose = $et->Options('Verbose'); + my $n; + + if ($dirLen < 48) { + $et->Warn('Truncated FPX properties'); + return 0; + } + # check and set our byte order if necessary + unless (CheckBOM($dataPt, $pos)) { + $et->Warn('Bad FPX property byte order mark'); + return 0; + } + # get position of start of section + $pos = Get32u($dataPt, $pos + 44); + if ($pos < 48) { + $et->Warn('Bad FPX property section offset'); + return 0; + } + for ($n=0; $n<2; ++$n) { + my %dictionary; # dictionary to translate user-defined properties + my $codePage; + last if $pos + 8 > $dirEnd; + # read property section header + my $size = Get32u($dataPt, $pos); + last unless $size; + my $numEntries = Get32u($dataPt, $pos + 4); + $verbose and $et->VerboseDir('Property Info', $numEntries, $size); + if ($pos + 8 + 8 * $numEntries > $dirEnd) { + $et->Warn('Truncated property list'); + last; + } + my $index; + for ($index=0; $index<$numEntries; ++$index) { + my $entry = $pos + 8 + 8 * $index; + my $tag = Get32u($dataPt, $entry); + my $offset = Get32u($dataPt, $entry + 4); + my $valStart = $pos + 4 + $offset; + last if $valStart >= $dirEnd; + my $valPos = $valStart; + my $type = Get32u($dataPt, $pos + $offset); + if ($tag == 0) { + # read dictionary to get tag name lookup for this property set + my $i; + for ($i=0; $i<$type; ++$i) { + last if $valPos + 8 > $dirEnd; + $tag = Get32u($dataPt, $valPos); + my $len = Get32u($dataPt, $valPos + 4); + $valPos += 8 + $len; + last if $valPos > $dirEnd; + my $name = substr($$dataPt, $valPos - $len, $len); + $name =~ s/\0.*//s; + next unless length $name; + $dictionary{$tag} = $name; + next if $$tagTablePtr{$name}; + $tag = $name; + $name =~ s/(^| )([a-z])/\U$2/g; # start with uppercase + $name =~ tr/-_a-zA-Z0-9//dc; # remove illegal characters + next unless length $name; + $et->VPrint(0, "$$et{INDENT}\[adding $name]\n") if $verbose; + AddTagToTable($tagTablePtr, $tag, { Name => $name }); + } + next; + } + # use tag name from dictionary if available + my ($custom, $val); + if (defined $dictionary{$tag}) { + $tag = $dictionary{$tag}; + $custom = 1; + } + my @vals = ReadFPXValue($et, $dataPt, $valPos, $type, $dirEnd, undef, $codePage); + @vals or $et->Warn('Error reading property value'); + $val = @vals > 1 ? \@vals : $vals[0]; + my $format = $type & 0x0fff; + my $flags = $type & 0xf000; + my $formStr = $oleFormat{$format} || "Type $format"; + $formStr .= '|' . ($oleFlags{$flags} || sprintf("0x%x",$flags)) if $flags; + my $tagInfo; + # check for common tag ID's: Dictionary, CodePage and LocaleIndicator + # (must be done before masking because masked tags may overlap these ID's) + if (not $custom and ($tag == 1 or $tag == 0x80000000)) { + # get tagInfo from SummaryInfo table + my $summaryTable = GetTagTable('Image::ExifTool::FlashPix::SummaryInfo'); + $tagInfo = $et->GetTagInfo($summaryTable, $tag); + if ($tag == 1) { + $val += 0x10000 if $val < 0; # (may be incorrectly stored as int16s) + $codePage = $val; # save code page for translating values + } + } elsif ($$tagTablePtr{$tag}) { + $tagInfo = $et->GetTagInfo($tagTablePtr, $tag); + } elsif ($$tagTablePtr{VARS} and not $custom) { + # mask off insignificant bits of tag ID if necessary + my $masked = $$tagTablePtr{VARS}; + my $mask; + foreach $mask (keys %$masked) { + if ($masked->{$mask}->{$tag & $mask}) { + $tagInfo = $et->GetTagInfo($tagTablePtr, $tag & $mask); + last; + } + } + } + $et->HandleTag($tagTablePtr, $tag, $val, + DataPt => $dataPt, + Start => $valStart, + Size => $valPos - $valStart, + Format => $formStr, + Index => $index, + TagInfo => $tagInfo, + Extra => ", type=$type", + ); + } + # issue warning if we hit end of property section prematurely + $et->Warn('Truncated property data') if $index < $numEntries; + last unless $$dirInfo{Multi}; + $pos += $size; + } + + return 1; +} + +#------------------------------------------------------------------------------ +# Load chain of sectors from file +# Inputs: 0) RAF ref, 1) first sector number, 2) FAT ref, 3) sector size, 4) header size +sub LoadChain($$$$$) +{ + my ($raf, $sect, $fatPt, $sectSize, $hdrSize) = @_; + return undef unless $raf; + my $chain = ''; + my ($buff, %loadedSect); + for (;;) { + last if $sect >= END_OF_CHAIN; + return undef if $loadedSect{$sect}; # avoid infinite loop + $loadedSect{$sect} = 1; + my $offset = $sect * $sectSize + $hdrSize; + return undef unless ($offset <= 0x7fffffff or $$raf{LargeFileSupport}) and + $raf->Seek($offset, 0) and + $raf->Read($buff, $sectSize) == $sectSize; + $chain .= $buff; + # step to next sector in chain + return undef if $sect * 4 > length($$fatPt) - 4; + $sect = Get32u($fatPt, $sect * 4); + } + return $chain; +} + +#------------------------------------------------------------------------------ +# Extract information from a JPEG APP2 FPXR segment +# Inputs: 0) ExifTool object ref, 1) dirInfo ref, 2) tag table ref +# Returns: 1 on success +sub ProcessFPXR($$$) +{ + my ($et, $dirInfo, $tagTablePtr) = @_; + my $dataPt = $$dirInfo{DataPt}; + my $dirStart = $$dirInfo{DirStart}; + my $dirLen = $$dirInfo{DirLen}; + my $verbose = $et->Options('Verbose'); + + if ($dirLen < 13) { + $et->Warn('FPXR segment too small'); + return 0; + } + + # get version and segment type (version is 0 in all my samples) + my ($vers, $type) = unpack('x5C2', $$dataPt); + + if ($type == 1) { # a "Contents List" segment + + $vers != 0 and $et->Warn("Untested FPXR version $vers"); + if ($$et{FPXR}) { + $et->Warn('Multiple FPXR contents lists'); + delete $$et{FPXR}; + } + my $numEntries = unpack('x7n', $$dataPt); + my @contents; + $verbose and $et->VerboseDir('Contents List', $numEntries); + my $pos = 9; + my $entry; + for ($entry = 0; $entry < $numEntries; ++$entry) { + if ($pos + 4 > $dirLen) { + $et->Warn('Truncated FPXR contents'); + return 0; + } + my ($size, $default) = unpack("x${pos}Na", $$dataPt); + pos($$dataPt) = $pos + 5; + # according to the spec, this string is little-endian + # (very odd, since the size word is big-endian), + # and the first char must be '/' + unless ($$dataPt =~ m{\G(/\0(..)*?)\0\0}sg) { + $et->Warn('Invalid FPXR stream name'); + return 0; + } + # convert stream pathname to ascii + my $name = Image::ExifTool::Decode(undef, $1, 'UCS2', 'II', 'Latin'); + if ($verbose) { + my $psize = ($size == 0xffffffff) ? 'storage' : "$size bytes"; + $et->VPrint(0," | $entry) Name: '${name}' [$psize]\n"); + } + # remove directory specification + $name =~ s{.*/}{}s; + # read storage class ID if necessary + my $classID; + if ($size == 0xffffffff) { + unless ($$dataPt =~ m{(.{16})}sg) { + $et->Warn('Truncated FPXR storage class ID'); + return 0; + } + # unpack class ID in case we want to use it sometime + $classID = Image::ExifTool::ASF::GetGUID($1); + } + # find the tagInfo if available + my $tagInfo; + unless ($$tagTablePtr{$name}) { + # remove instance number or class ID from tag if necessary + $tagInfo = $et->GetTagInfo($tagTablePtr, $1) if + ($name =~ /(.*) \d{6}$/s and $$tagTablePtr{$1}) or + ($name =~ /(.*)_[0-9a-f]{16}$/s and $$tagTablePtr{$1}); + } + # update position in list + $pos = pos($$dataPt); + # add to our contents list + push @contents, { + Name => $name, + Size => $size, + Default => $default, + ClassID => $classID, + TagInfo => $tagInfo, + }; + } + # save contents list as $et member variable + # (must do this last so we don't save list on error) + $$et{FPXR} = \@contents; + + } elsif ($type == 2) { # a "Stream Data" segment + + # get the contents list index and stream data offset + my ($index, $offset) = unpack('x7nN', $$dataPt); + my $fpxr = $$et{FPXR}; + if ($fpxr and $$fpxr[$index]) { + my $obj = $$fpxr[$index]; + # extract stream data (after 13-byte header) + if (not defined $$obj{Stream}) { + # ignore offset for first segment of this type + # (in my sample images, this isn't always zero as one would expect) + $$obj{Stream} = substr($$dataPt, $dirStart+13); + } else { + # add data at the proper offset to the stream + my $overlap = length($$obj{Stream}) - $offset; + my $start = $dirStart + 13; + if ($overlap < 0 or $dirLen - $overlap < 13) { + $et->WarnOnce("Bad FPXR stream $index offset",1); + } else { + # ignore any overlapping data in this segment + # (this seems to be the convention) + $start += $overlap; + } + # concatenate data with this stream + $$obj{Stream} .= substr($$dataPt, $start); + } + # save value for this tag if stream is complete + my $len = length $$obj{Stream}; + if ($len >= $$obj{Size}) { + $et->VPrint(0, " + [FPXR stream $index, $len bytes]\n") if $verbose; + if ($len > $$obj{Size}) { + $et->Warn('Extra data in FPXR segment (truncated)'); + $$obj{Stream} = substr($$obj{Stream}, 0, $$obj{Size}); + } + # handle this tag + $et->HandleTag($tagTablePtr, $$obj{Name}, $$obj{Stream}, + DataPt => \$$obj{Stream}, + TagInfo => $$obj{TagInfo}, + ); + delete $$obj{Stream}; # done with this stream + } + # hack for improperly stored FujiFilm PreviewImage (stored with no contents list) + } elsif ($index == 512 and $dirLen > 60 and ($$et{FujiPreview} or + ($dirLen > 64 and substr($$dataPt, $dirStart+60, 4) eq "\xff\xd8\xff\xdb"))) + { + $$et{FujiPreview} = '' unless defined $$et{FujiPreview}; + # recombine PreviewImage, skipping 13-byte FPXR header + 47-byte Fuji header + $$et{FujiPreview} .= substr($$dataPt, $dirStart+60); + } else { + # (Kodak uses index 255 for a free segment in images from some cameras) + $et->Warn("Unlisted FPXR segment (index $index)") if $index != 255; + } + + } elsif ($type ne 3) { # not a "Reserved" segment + + $et->Warn("Unknown FPXR segment (type $type)"); + + } + + # clean up if this was the last FPXR segment + if ($$dirInfo{LastFPXR}) { + if ($$et{FPXR}) { + my $obj; + foreach $obj (@{$$et{FPXR}}) { + next unless defined $$obj{Stream} and length $$obj{Stream}; + # parse it even though it isn't the proper length + $et->HandleTag($tagTablePtr, $$obj{Name}, $$obj{Stream}, + DataPt => \$$obj{Stream}, + TagInfo => $$obj{TagInfo}, + ); + } + delete $$et{FPXR}; # delete our temporary variables + } + if ($$et{FujiPreview}) { + $et->FoundTag('PreviewImage', $$et{FujiPreview}); + delete $$et{FujiPreview}; + } + } + return 1; +} + +#------------------------------------------------------------------------------ +# Set document number for objects +# Inputs: 0) object hierarchy hash ref, 1) object index, 2) doc number list ref, +# 3) doc numbers used at each level, 4) flag set for metadata levels +sub SetDocNum($$;$$$) +{ + my ($hier, $index, $doc, $used, $meta) = @_; + my $obj = $$hier{$index} or return; + return if exists $$obj{DocNum}; + $$obj{DocNum} = $doc; + SetDocNum($hier, $$obj{Left}, $doc, $used, $meta) if $$obj{Left}; + SetDocNum($hier, $$obj{Right}, $doc, $used, $meta) if $$obj{Right}; + if (defined $$obj{Child}) { + $used or $used = [ ]; + my @subDoc; + push @subDoc, @$doc if $doc; + # we must dive down 2 levels for each sub-document, so use the + # $meta flag to add a sub-document level only for every 2nd generation + if ($meta) { + my $subNum = ($$used[scalar @subDoc] || 0); + $$used[scalar @subDoc] = $subNum; + push @subDoc, $subNum; + } elsif (@subDoc) { + $subDoc[-1] = ++$$used[$#subDoc]; + } + SetDocNum($hier, $$obj{Child}, \@subDoc, $used, not $meta); + } +} + +#------------------------------------------------------------------------------ +# Extract information from a FlashPix (FPX) file +# Inputs: 0) ExifTool object ref, 1) dirInfo ref +# Returns: 1 on success, 0 if this wasn't a valid FPX-format file +sub ProcessFPX($$) +{ + my ($et, $dirInfo) = @_; + my $raf = $$dirInfo{RAF}; + my ($buff, $out, $oldIndent, $miniStreamBuff); + my ($tag, %hier, %objIndex, %loadedDifSect); + + # read header + return 0 unless $raf->Read($buff,HDR_SIZE) == HDR_SIZE; + # check signature + return 0 unless $buff =~ /^\xd0\xcf\x11\xe0\xa1\xb1\x1a\xe1/; + + # set FileType initially based on file extension (we may override this later) + my $fileType = $$et{FILE_EXT}; + $fileType = 'FPX' unless $fileType and $fpxFileType{$fileType}; + $et->SetFileType($fileType); + SetByteOrder(substr($buff, 0x1c, 2) eq "\xff\xfe" ? 'MM' : 'II'); + my $tagTablePtr = GetTagTable('Image::ExifTool::FlashPix::Main'); + my $verbose = $et->Options('Verbose'); + # copy LargeFileSupport option to RAF for use in LoadChain + $$raf{LargeFileSupport} = $et->Options('LargeFileSupport'); + + my $sectSize = 1 << Get16u(\$buff, 0x1e); + my $miniSize = 1 << Get16u(\$buff, 0x20); + my $fatCount = Get32u(\$buff, 0x2c); # number of FAT sectors + my $dirStart = Get32u(\$buff, 0x30); # first directory sector + my $miniCutoff = Get32u(\$buff, 0x38); # minimum size for big-FAT streams + my $miniStart = Get32u(\$buff, 0x3c); # first sector of mini-FAT + my $miniCount = Get32u(\$buff, 0x40); # number of mini-FAT sectors + my $difStart = Get32u(\$buff, 0x44); # first sector of DIF chain + my $difCount = Get32u(\$buff, 0x48); # number of DIF sectors + + if ($verbose) { + $out = $et->Options('TextOut'); + print $out " Sector size=$sectSize\n FAT: Count=$fatCount\n"; + print $out " DIR: Start=$dirStart\n"; + print $out " MiniFAT: Mini-sector size=$miniSize Start=$miniStart Count=$miniCount Cutoff=$miniCutoff\n"; + print $out " DIF FAT: Start=$difStart Count=$difCount\n"; + } +# +# load the FAT +# + my $pos = 0x4c; + my $endPos = length($buff); + my $fat = ''; + my $fatCountCheck = 0; + my $difCountCheck = 0; + my $hdrSize = $sectSize > HDR_SIZE ? $sectSize : HDR_SIZE; + + for (;;) { + while ($pos <= $endPos - 4) { + my $sect = Get32u(\$buff, $pos); + $pos += 4; + next if $sect == FREE_SECT; + my $offset = $sect * $sectSize + $hdrSize; + my $fatSect; + unless ($raf->Seek($offset, 0) and + $raf->Read($fatSect, $sectSize) == $sectSize) + { + $et->Error("Error reading FAT from sector $sect"); + return 1; + } + $fat .= $fatSect; + ++$fatCountCheck; + } + last if $difStart >= END_OF_CHAIN; + # read next DIF (Dual Indirect FAT) sector + if (++$difCountCheck > $difCount) { + $et->Warn('Unterminated DIF FAT'); + last; + } + if ($loadedDifSect{$difStart}) { + $et->Warn('Cyclical reference in DIF FAT'); + last; + } + my $offset = $difStart * $sectSize + $hdrSize; + unless ($raf->Seek($offset, 0) and $raf->Read($buff, $sectSize) == $sectSize) { + $et->Error("Error reading DIF sector $difStart"); + return 1; + } + $loadedDifSect{$difStart} = 1; + # set end of sector information in this DIF + $pos = 0; + $endPos = $sectSize - 4; + # next time around we want to read next DIF in chain + $difStart = Get32u(\$buff, $endPos); + } + if ($fatCountCheck != $fatCount) { + $et->Warn("Bad number of FAT sectors (expected $fatCount but found $fatCountCheck)"); + } +# +# load the mini-FAT and the directory +# + my $miniFat = LoadChain($raf, $miniStart, \$fat, $sectSize, $hdrSize); + my $dir = LoadChain($raf, $dirStart, \$fat, $sectSize, $hdrSize); + unless (defined $miniFat and defined $dir) { + $et->Error('Error reading mini-FAT or directory stream'); + return 1; + } + if ($verbose) { + print $out " FAT [",length($fat)," bytes]:\n"; + $et->VerboseDump(\$fat); + print $out " Mini-FAT [",length($miniFat)," bytes]:\n"; + $et->VerboseDump(\$miniFat); + print $out " Directory [",length($dir)," bytes]:\n"; + $et->VerboseDump(\$dir); + } +# +# process the directory +# + if ($verbose) { + $oldIndent = $$et{INDENT}; + $$et{INDENT} .= '| '; + $et->VerboseDir('FPX', undef, length $dir); + } + my $miniStream; + $endPos = length($dir); + my $index = 0; + + for ($pos=0; $pos<=$endPos-128; $pos+=128, ++$index) { + + # get directory entry type + # (0=invalid, 1=storage, 2=stream, 3=lockbytes, 4=property, 5=root) + my $type = Get8u(\$dir, $pos + 0x42); + next if $type == 0; # skip invalid entries + if ($type > 5) { + $et->Warn("Invalid directory entry type $type"); + last; # rest of directory is probably garbage + } + # get entry name (note: this is supposed to be length in 2-byte + # characters but this isn't what is done in my sample FPX file, so + # be very tolerant of this count -- it's null terminated anyway) + my $len = Get16u(\$dir, $pos + 0x40); + $len > 32 and $len = 32; + $tag = Image::ExifTool::Decode(undef, substr($dir,$pos,$len*2), 'UCS2', 'II', 'Latin'); + $tag =~ s/\0.*//s; # truncate at null (in case length was wrong) + + my $sect = Get32u(\$dir, $pos + 0x74); # start sector number + my $size = Get32u(\$dir, $pos + 0x78); # stream length + + # load Ministream (referenced from first directory entry) + unless ($miniStream) { + $miniStreamBuff = LoadChain($raf, $sect, \$fat, $sectSize, $hdrSize); + unless (defined $miniStreamBuff) { + $et->Warn('Error loading Mini-FAT stream'); + last; + } + $miniStream = new File::RandomAccess(\$miniStreamBuff); + } + + my $tagInfo; + if ($$tagTablePtr{$tag}) { + $tagInfo = $et->GetTagInfo($tagTablePtr, $tag); + } else { + # remove instance number or class ID from tag if necessary + $tagInfo = $et->GetTagInfo($tagTablePtr, $1) if + ($tag =~ /(.*) \d{6}$/s and $$tagTablePtr{$1}) or + ($tag =~ /(.*)_[0-9a-f]{16}$/s and $$tagTablePtr{$1}); + } + + my $lSib = Get32u(\$dir, $pos + 0x44); # left sibling + my $rSib = Get32u(\$dir, $pos + 0x48); # right sibling + my $chld = Get32u(\$dir, $pos + 0x4c); # child directory + + # save information about object hierachy + my ($obj, $sub); + $obj = $hier{$index} or $obj = $hier{$index} = { }; + $$obj{Left} = $lSib unless $lSib == FREE_SECT; + $$obj{Right} = $rSib unless $rSib == FREE_SECT; + unless ($chld == FREE_SECT) { + $$obj{Child} = $chld; + $sub = $hier{$chld} or $sub = $hier{$chld} = { }; + $$sub{Parent} = $index; + } + + next unless $tagInfo or $verbose; + + # load the data for stream types + my $extra = ''; + my $typeStr = $dirEntryType[$type] || $type; + if ($typeStr eq 'STREAM') { + if ($size >= $miniCutoff) { + # stream is in the main FAT + $buff = LoadChain($raf, $sect, \$fat, $sectSize, $hdrSize); + } elsif ($size) { + # stream is in the mini-FAT + $buff = LoadChain($miniStream, $sect, \$miniFat, $miniSize, 0); + } else { + $buff = ''; # an empty stream + } + unless (defined $buff) { + my $name = $tagInfo ? $$tagInfo{Name} : 'unknown'; + $et->Warn("Error reading $name stream"); + $buff = ''; + } + } elsif ($typeStr eq 'ROOT') { + $buff = $miniStreamBuff; + $extra .= ' (Ministream)'; + } else { + $buff = ''; + undef $size; + } + if ($verbose) { + my $flags = Get8u(\$dir, $pos + 0x43); # 0=red, 1=black + my $col = { 0 => 'Red', 1 => 'Black' }->{$flags} || $flags; + $extra .= " Type=$typeStr Flags=$col"; + $extra .= " Left=$lSib" unless $lSib == FREE_SECT; + $extra .= " Right=$rSib" unless $rSib == FREE_SECT; + $extra .= " Child=$chld" unless $chld == FREE_SECT; + $et->VerboseInfo($tag, $tagInfo, + Index => $index, + Value => $buff, + DataPt => \$buff, + Extra => $extra, + Size => $size, + ); + } + if ($tagInfo and $buff) { + my $num = $$et{NUM_FOUND}; + my $subdir = $$tagInfo{SubDirectory}; + if ($subdir) { + my %dirInfo = ( + DataPt => \$buff, + DirStart => $$subdir{DirStart}, + DirLen => length $buff, + Multi => $$tagInfo{Multi}, + ); + my $subTablePtr = GetTagTable($$subdir{TagTable}); + $et->ProcessDirectory(\%dirInfo, $subTablePtr, $$subdir{ProcessProc}); + } else { + $et->FoundTag($tagInfo, $buff); + } + # save object index number for all found tags + my $num2 = $$et{NUM_FOUND}; + $objIndex{++$num} = $index while $num < $num2; + } + } + # set document numbers for tags extracted from embedded documents + unless ($$et{DOC_NUM}) { + # initialize document number for all objects, beginning at root (index 0) + SetDocNum(\%hier, 0); + # set family 3 group name for all tags in embedded documents + my $order = $$et{FILE_ORDER}; + my (@pri, $copy, $member); + foreach $tag (keys %$order) { + my $num = $$order{$tag}; + next unless defined $num and $objIndex{$num}; + my $obj = $hier{$objIndex{$num}} or next; + my $docNums = $$obj{DocNum}; + next unless $docNums and @$docNums; + $$et{TAG_EXTRA}{$tag}{G3} = join '-', @$docNums; + push @pri, $tag unless $tag =~ / /; # save keys for priority sub-doc tags + } + # swap priority sub-document tags with main document tags if they exist + foreach $tag (@pri) { + for ($copy=1; ;++$copy) { + my $key = "$tag ($copy)"; + last unless defined $$et{VALUE}{$key}; + my $extra = $$et{TAG_EXTRA}{$key}; + next if $extra and $$extra{G3}; # not Main if family 3 group is set + foreach $member ('PRIORITY','VALUE','FILE_ORDER','TAG_INFO','TAG_EXTRA') { + my $pHash = $$et{$member}; + my $t = $$pHash{$tag}; + $$pHash{$tag} = $$pHash{$key}; + $$pHash{$key} = $t; + } + last; + } + } + } + $$et{INDENT} = $oldIndent if $verbose; + # try to better identify the file type + if ($$et{VALUE}{FileType} eq 'FPX') { + my $val = $$et{CompObjUserType} || $$et{Software}; + if ($val) { + my %type = ( '^3ds Max' => 'MAX', Word => 'DOC', PowerPoint => 'PPT', Excel => 'XLS' ); + my $pat; + foreach $pat (sort keys %type) { + next unless $val =~ /$pat/; + $et->OverrideFileType($type{$pat}); + last; + } + } + } + # process Word document table + ProcessDocumentTable($et); + + return 1; +} + +1; # end + +__END__ + +=head1 NAME + +Image::ExifTool::FlashPix - Read FlashPix meta information + +=head1 SYNOPSIS + +This module is used by Image::ExifTool + +=head1 DESCRIPTION + +This module contains routines required by Image::ExifTool to extract +FlashPix meta information from FPX images, and from the APP2 FPXR segment of +JPEG images. + +=head1 AUTHOR + +Copyright 2003-2019, Phil Harvey (phil at owl.phy.queensu.ca) + +This library is free software; you can redistribute it and/or modify it +under the same terms as Perl itself. + +=head1 REFERENCES + +=over 4 + +=item L<http://www.exif.org/Exif2-2.PDF> + +=item L<http://www.graphcomp.com/info/specs/livepicture/fpx.pdf> + +=item L<http://search.cpan.org/~jdb/libwin32/> + +=item L<http://msdn.microsoft.com/en-us/library/aa380374.aspx> + +=back + +=head1 SEE ALSO + +L<Image::ExifTool::TagNames/FlashPix Tags>, +L<Image::ExifTool::TagNames/OOXML Tags>, +L<Image::ExifTool(3pm)|Image::ExifTool> + +=cut + diff --git a/lib/Image/ExifTool/Font.pm b/lib/Image/ExifTool/Font.pm new file mode 100644 index 0000000..5c72590 --- /dev/null +++ b/lib/Image/ExifTool/Font.pm @@ -0,0 +1,647 @@ +#------------------------------------------------------------------------------ +# File: Font.pm +# +# Description: Read meta information from font files +# +# Revisions: 2010/01/15 - P. Harvey Created +# +# References: 1) http://developer.apple.com/textfonts/TTRefMan/RM06/Chap6.html +# 2) http://www.microsoft.com/typography/otspec/otff.htm +# 3) http://partners.adobe.com/public/developer/opentype/index_font_file.html +# 4) http://partners.adobe.com/public/developer/en/font/5178.PFM.pdf +# 5) http://opensource.adobe.com/svn/opensource/flex/sdk/trunk/modules/compiler/src/java/flex2/compiler/util/MimeMappings.java +# 6) http://www.adobe.com/devnet/font/pdfs/5004.AFM_Spec.pdf +#------------------------------------------------------------------------------ + +package Image::ExifTool::Font; + +use strict; +use vars qw($VERSION %ttLang); +use Image::ExifTool qw(:DataAccess :Utils); + +$VERSION = '1.08'; + +sub ProcessOTF($$); + +# TrueType 'name' platform codes +my %ttPlatform = ( + 0 => 'Unicode', + 1 => 'Macintosh', + 2 => 'ISO', + 3 => 'Windows', + 4 => 'Custom', +); + +# convert TrueType 'name' character encoding to ExifTool Charset (ref 1/2) +my %ttCharset = ( + Macintosh => { + 0 => 'MacRoman', 17 => 'MacMalayalam', + 1 => 'MacJapanese', 18 => 'MacSinhalese', + 2 => 'MacChineseTW', 19 => 'MacBurmese', + 3 => 'MacKorean', 20 => 'MacKhmer', + 4 => 'MacArabic', 21 => 'MacThai', + 5 => 'MacHebrew', 22 => 'MacLaotian', + 6 => 'MacGreek', 23 => 'MacGeorgian', + 7 => 'MacCyrillic', 24 => 'MacArmenian', # 7=Russian + 8 => 'MacRSymbol', 25 => 'MacChineseCN', + 9 => 'MacDevanagari', 26 => 'MacTibetan', + 10 => 'MacGurmukhi', 27 => 'MacMongolian', + 11 => 'MacGujarati', 28 => 'MacGeez', + 12 => 'MacOriya', 29 => 'MacCyrillic', # 29=Slavic + 13 => 'MacBengali', 30 => 'MacVietnam', + 14 => 'MacTamil', 31 => 'MacSindhi', + 15 => 'MacTelugu', 32 => '', # 32=uninterpreted + 16 => 'MacKannada', + }, + Windows => { + 0 => 'Symbol', 4 => 'Big5', + 1 => 'UCS2', 5 => 'Wansung', + 2 => 'ShiftJIS', 6 => 'Johab', + 3 => 'PRC', 10 => 'UCS4', + }, + Unicode => { + # (we don't currently handle the various Unicode flavours) + 0 => 'UCS2', # Unicode 1.0 semantics + 1 => 'UCS2', # Unicode 1.1 semantics + 2 => 'UCS2', # ISO 10646 semantics + 3 => 'UCS2', # Unicode 2.0 and onwards semantics, Unicode BMP only. + 4 => 'UCS2', # Unicode 2.0 and onwards semantics, Unicode full repertoire. + # 5 => Unicode Variation Sequences (not used in Naming table) + }, + ISO => { # (deprecated) + 0 => 'UTF8', # (7-bit ASCII) + 1 => 'UCS2', # ISO 10646 + 2 => 'Latin', # ISO 8859-1 + }, + Custom => { }, +); + +# convert TrueType 'name' language code to ExifTool language code +%ttLang = ( + # Macintosh language codes (also used by QuickTime.pm) + # oddities: + # 49 - Cyrllic version 83 - Roman + # 50 - Arabic version 84 - Arabic + # 146 - with dot above + Macintosh => { + 0 => 'en', 24 => 'lt', 48 => 'kk', 72 => 'ml', 129 => 'eu', + 1 => 'fr', 25 => 'pl', 49 => 'az', 73 => 'kn', 130 => 'ca', + 2 => 'de', 26 => 'hu', 50 => 'az', 74 => 'ta', 131 => 'la', + 3 => 'it', 27 => 'et', 51 => 'hy', 75 => 'te', 132 => 'qu', + 4 => 'nl', 28 => 'lv', 52 => 'ka', 76 => 'si', 133 => 'gn', + 5 => 'sv', 29 => 'smi', 53 => 'ro', 77 => 'my', 134 => 'ay', + 6 => 'es', 30 => 'fo', 54 => 'ky', 78 => 'km', 135 => 'tt', + 7 => 'da', 31 => 'fa', 55 => 'tg', 79 => 'lo', 136 => 'ug', + 8 => 'pt', 32 => 'ru', 56 => 'tk', 80 => 'vi', 137 => 'dz', + 9 => 'no', 33 => 'zh-CN', 57 => 'mn-MN', 81 => 'id', 138 => 'jv', + 10 => 'he', 34 => 'nl', 58 => 'mn-CN', 82 => 'tl', 139 => 'su', + 11 => 'ja', 35 => 'ga', 59 => 'ps', 83 => 'ms-MY', 140 => 'gl', + 12 => 'ar', 36 => 'sq', 60 => 'ku', 84 => 'ms-BN', 141 => 'af', + 13 => 'fi', 37 => 'ro', 61 => 'ks', 85 => 'am', 142 => 'br', + 14 => 'iu', 38 => 'cs', 62 => 'sd', 86 => 'ti', 144 => 'gd', + 15 => 'is', 39 => 'sk', 63 => 'bo', 87 => 'om', 145 => 'vg', + 16 => 'mt', 40 => 'sl', 64 => 'ne', 88 => 'so', 146 => 'ga', + 17 => 'tr', 41 => 'yi', 65 => 'sa', 89 => 'sw', 147 => 'rar', + 18 => 'hr', 42 => 'sr', 66 => 'mr', 90 => 'rw', 148 => 'el', + 19 => 'zh-TW', 43 => 'mk', 67 => 'bn', 91 => 'rn', 149 => 'kl', + 20 => 'ur', 44 => 'bg', 68 => 'as', 92 => 'ny', 150 => 'az', + 21 => 'hi', 45 => 'uk', 69 => 'gu', 93 => 'mg', + 22 => 'th', 46 => 'be', 70 => 'pa', 94 => 'eo', + 23 => 'ko', 47 => 'uz', 71 => 'or', 128 => 'cy', + }, + # Windows language codes (http://msdn.microsoft.com/en-us/library/0h88fahh(VS.85).aspx) + # Notes: This isn't an exact science. The reference above gives language codes + # which are different from some ISO 639-1 numbers. Also, some Windows language + # codes don't appear to have ISO 639-1 equivalents. + # 0x0428 - fa by ref above + # 0x048c - no ISO equivalent + # 0x081a/0x83c - sr-SP + # 0x0c0a - modern? + # 0x2409 - Carribean country code not found in ISO 3166-1 + Windows => { + 0x0401 => 'ar-SA', 0x0438 => 'fo', 0x0481 => 'mi', 0x1409 => 'en-NZ', + 0x0402 => 'bg', 0x0439 => 'hi', 0x0482 => 'oc', 0x140a => 'es-CR', + 0x0403 => 'ca', 0x043a => 'mt', 0x0483 => 'co', 0x140c => 'fr-LU', + 0x0404 => 'zh-TW', 0x043b => 'se-NO', 0x0484 => 'gsw', 0x141a => 'bs-BA', + 0x0405 => 'cs', 0x043c => 'gd', 0x0485 => 'sah', 0x143b => 'smj-SE', + 0x0406 => 'da', 0x043d => 'yi', 0x0486 => 'ny', 0x1801 => 'ar-MA', + 0x0407 => 'de-DE', 0x043e => 'ms-MY', 0x0487 => 'rw', 0x1809 => 'en-IE', + 0x0408 => 'el', 0x043f => 'kk', 0x048c => 'Dari', 0x180a => 'es-PA', + 0x0409 => 'en-US', 0x0440 => 'ky', 0x0801 => 'ar-IQ', 0x180c => 'fr-MC', + 0x040a => 'es-ES', 0x0441 => 'sw', 0x0804 => 'zh-CN', 0x181a => 'sr-BA', + 0x040b => 'fi', 0x0442 => 'tk', 0x0807 => 'de-CH', 0x183b => 'sma-NO', + 0x040c => 'fr-FR', 0x0443 => 'uz-UZ', 0x0809 => 'en-GB', 0x1c01 => 'ar-TN', + 0x040d => 'he', 0x0444 => 'tt', 0x080a => 'es-MX', 0x1c09 => 'en-ZA', + 0x040e => 'hu', 0x0445 => 'bn-IN', 0x080c => 'fr-BE', 0x1c0a => 'es-DO', + 0x040f => 'is', 0x0446 => 'pa', 0x0810 => 'it-CH', 0x1c1a => 'sr-BA', + 0x0410 => 'it-IT', 0x0447 => 'gu', 0x0813 => 'nl-BE', 0x1c3b => 'sma-SE', + 0x0411 => 'ja', 0x0448 => 'wo', 0x0814 => 'nn', 0x2001 => 'ar-OM', + 0x0412 => 'ko', 0x0449 => 'ta', 0x0816 => 'pt-PT', 0x2009 => 'en-JM', + 0x0413 => 'nl-NL', 0x044a => 'te', 0x0818 => 'ro-MO', 0x200a => 'es-VE', + 0x0414 => 'no-NO', 0x044b => 'kn', 0x0819 => 'ru-MO', 0x201a => 'bs-BA', + 0x0415 => 'pl', 0x044c => 'ml', 0x081a => 'sr-RS', 0x203b => 'sms', + 0x0416 => 'pt-BR', 0x044d => 'as', 0x081d => 'sv-FI', 0x2401 => 'ar-YE', + 0x0417 => 'rm', 0x044e => 'mr', 0x082c => 'az-AZ', 0x2409 => 'en-CB', + 0x0418 => 'ro', 0x044f => 'sa', 0x082e => 'dsb', 0x240a => 'es-CO', + 0x0419 => 'ru', 0x0450 => 'mn-MN', 0x083b => 'se-SE', 0x243b => 'smn', + 0x041a => 'hr', 0x0451 => 'bo', 0x083c => 'ga', 0x2801 => 'ar-SY', + 0x041b => 'sk', 0x0452 => 'cy', 0x083e => 'ms-BN', 0x2809 => 'en-BZ', + 0x041c => 'sq', 0x0453 => 'km', 0x0843 => 'uz-UZ', 0x280a => 'es-PE', + 0x041d => 'sv-SE', 0x0454 => 'lo', 0x0845 => 'bn-BD', 0x2c01 => 'ar-JO', + 0x041e => 'th', 0x0456 => 'gl', 0x0850 => 'mn-CN', 0x2c09 => 'en-TT', + 0x041f => 'tr', 0x0457 => 'kok', 0x085d => 'iu-CA', 0x2c0a => 'es-AR', + 0x0420 => 'ur', 0x045a => 'syr', 0x085f => 'tmh', 0x3001 => 'ar-LB', + 0x0421 => 'id', 0x045b => 'si', 0x086b => 'qu-EC', 0x3009 => 'en-ZW', + 0x0422 => 'uk', 0x045d => 'iu-CA', 0x0c01 => 'ar-EG', 0x300a => 'es-EC', + 0x0423 => 'be', 0x045e => 'am', 0x0c04 => 'zh-HK', 0x3401 => 'ar-KW', + 0x0424 => 'sl', 0x0461 => 'ne', 0x0c07 => 'de-AT', 0x3409 => 'en-PH', + 0x0425 => 'et', 0x0462 => 'fy', 0x0c09 => 'en-AU', 0x340a => 'es-CL', + 0x0426 => 'lv', 0x0463 => 'ps', 0x0c0a => 'es-ES', 0x3801 => 'ar-AE', + 0x0427 => 'lt', 0x0464 => 'fil', 0x0c0c => 'fr-CA', 0x380a => 'es-UY', + 0x0428 => 'tg', 0x0465 => 'dv', 0x0c1a => 'sr-RS', 0x3c01 => 'ar-BH', + 0x042a => 'vi', 0x0468 => 'ha', 0x0c3b => 'se-FI', 0x3c0a => 'es-PY', + 0x042b => 'hy', 0x046a => 'yo', 0x0c6b => 'qu-PE', 0x4001 => 'ar-QA', + 0x042c => 'az-AZ', 0x046b => 'qu-BO', 0x1001 => 'ar-LY', 0x4009 => 'en-IN', + 0x042d => 'eu', 0x046c => 'st', 0x1004 => 'zh-SG', 0x400a => 'es-BO', + 0x042e => 'hsb', 0x046d => 'ba', 0x1007 => 'de-LU', 0x4409 => 'en-MY', + 0x042f => 'mk', 0x046e => 'lb', 0x1009 => 'en-CA', 0x440a => 'es-SV', + 0x0430 => 'st', 0x046f => 'kl', 0x100a => 'es-GT', 0x4809 => 'en-SG', + 0x0431 => 'ts', 0x0470 => 'ig', 0x100c => 'fr-CH', 0x480a => 'es-HN', + 0x0432 => 'tn', 0x0478 => 'yi', 0x101a => 'hr-BA', 0x4c0a => 'es-NI', + 0x0434 => 'xh', 0x047a => 'arn', 0x103b => 'smj-NO',0x500a => 'es-PR', + 0x0435 => 'zu', 0x047c => 'moh', 0x1401 => 'ar-DZ', 0x540a => 'es-US', + 0x0436 => 'af', 0x047e => 'br', 0x1404 => 'zh-MO', + 0x0437 => 'ka', 0x0480 => 'ug', 0x1407 => 'de-LI', + }, + Unicode => { }, + ISO => { }, + Custom => { }, +); + +# eclectic table of tags for various format font files +%Image::ExifTool::Font::Main = ( + GROUPS => { 2 => 'Document' }, + NOTES => q{ + This table contains a collection of tags found in font files of various + formats. ExifTool current recognizes OTF, TTF, TTC, DFONT, PFA, PFB, PFM, + AFM, ACFM and AMFM font files. + }, + name => { + SubDirectory => { TagTable => 'Image::ExifTool::Font::Name' }, + }, + PFM => { + Name => 'PFMHeader', + SubDirectory => { TagTable => 'Image::ExifTool::Font::PFM' }, + }, + PSInfo => { + Name => 'PSFontInfo', + SubDirectory => { TagTable => 'Image::ExifTool::Font::PSInfo' }, + }, + AFM => { + Name => 'AFM', + SubDirectory => { TagTable => 'Image::ExifTool::Font::AFM' }, + }, + numfonts => 'NumFonts', + fontname => 'FontName', + postfont => { + Name => 'PostScriptFontName', + Description => 'PostScript Font Name', + }, +); + +# TrueType name tags (ref 1/2) +%Image::ExifTool::Font::Name = ( + GROUPS => { 2 => 'Document' }, + NOTES => q{ + The following tags are extracted from the TrueType font "name" table found + in OTF, TTF, TTC and DFONT files. These tags support localized languages by + adding a hyphen followed by a language code to the end of the tag name (eg. + "Copyright-fr" or "License-en-US"). Tags with no language code use the + default language of "en". + }, + 0 => { Name => 'Copyright', Groups => { 2 => 'Author' } }, + 1 => 'FontFamily', + 2 => 'FontSubfamily', + 3 => 'FontSubfamilyID', + 4 => 'FontName', # full name + 5 => 'NameTableVersion', + 6 => { Name => 'PostScriptFontName', Description => 'PostScript Font Name' }, + 7 => 'Trademark', + 8 => 'Manufacturer', + 9 => 'Designer', + 10 => 'Description', + 11 => 'VendorURL', + 12 => 'DesignerURL', + 13 => 'License', + 14 => 'LicenseInfoURL', + 16 => 'PreferredFamily', + 17 => 'PreferredSubfamily', + 18 => 'CompatibleFontName', + 19 => 'SampleText', + 20 => { + Name => 'PostScriptFontName', + Description => 'PostScript Font Name', + }, + 21 => 'WWSFamilyName', + 22 => 'WWSSubfamilyName', +); + +# PostScript Font Metric file header (ref 4) +%Image::ExifTool::Font::PFM = ( + GROUPS => { 2 => 'Document' }, + PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData, + NOTES => 'Tags extracted from the PFM file header.', + 0 => { + Name => 'PFMVersion', + Format => 'int16u', + PrintConv => 'sprintf("%x.%.2x",$val>>8,$val&0xff)', + }, + 6 => { Name => 'Copyright', Format => 'string[60]', Groups => { 2 => 'Author' } }, + 66 => { Name => 'FontType', Format => 'int16u' }, + 68 => { Name => 'PointSize', Format => 'int16u' }, + 70 => { Name => 'YResolution', Format => 'int16u' }, + 72 => { Name => 'XResolution', Format => 'int16u' }, + 74 => { Name => 'Ascent', Format => 'int16u' }, + 76 => { Name => 'InternalLeading', Format => 'int16u' }, + 78 => { Name => 'ExternalLeading', Format => 'int16u' }, + 80 => { Name => 'Italic' }, + 81 => { Name => 'Underline' }, + 82 => { Name => 'Strikeout' }, + 83 => { Name => 'Weight', Format => 'int16u' }, + 85 => { Name => 'CharacterSet' }, + 86 => { Name => 'PixWidth', Format => 'int16u' }, + 88 => { Name => 'PixHeight', Format => 'int16u' }, + 90 => { Name => 'PitchAndFamily' }, + 91 => { Name => 'AvgWidth', Format => 'int16u' }, + 93 => { Name => 'MaxWidth', Format => 'int16u' }, + 95 => { Name => 'FirstChar' }, + 96 => { Name => 'LastChar' }, + 97 => { Name => 'DefaultChar' }, + 98 => { Name => 'BreakChar' }, + 99 => { Name => 'WidthBytes', Format => 'int16u' }, + # 101 => { Name => 'DeviceTypeOffset', Format => 'int32u' }, + # 105 => { Name => 'FontNameOffset', Format => 'int32u' }, + # 109 => { Name => 'BitsPointer', Format => 'int32u' }, + # 113 => { Name => 'BitsOffset', Format => 'int32u' }, +); + +# PostScript FontInfo attributes (PFA, PFB) (ref PH) +%Image::ExifTool::Font::PSInfo = ( + GROUPS => { 2 => 'Document' }, + NOTES => 'Tags extracted from PostScript font files (PFA and PFB).', + FullName => { }, + FamilyName => { Name => 'FontFamily' }, + Weight => { }, + ItalicAngle => { }, + isFixedPitch=> { }, + UnderlinePosition => { }, + UnderlineThickness => { }, + Copyright => { Groups => { 2 => 'Author' } }, + Notice => { Groups => { 2 => 'Author' } }, + version => { }, + FontName => { }, + FontType => { }, + FSType => { }, +); + +# Adobe Font Metrics tags (AFM) (ref 6) +%Image::ExifTool::Font::AFM = ( + GROUPS => { 2 => 'Document' }, + NOTES => 'Tags extracted from Adobe Font Metrics files (AFM, ACFM and AMFM).', + 'Creation Date' => { Name => 'CreateDate', Groups => { 2 => 'Time' } }, + FontName => { }, + FullName => { }, + FamilyName => { Name => 'FontFamily' }, + Weight => { }, + Version => { }, + Notice => { Groups => { 2 => 'Author' } }, + EncodingScheme => { }, + MappingScheme => { }, + EscChar => { }, + CharacterSet=> { }, + Characters => { }, + IsBaseFont => { }, + # VVector => { }, + IsFixedV => { }, + CapHeight => { }, + XHeight => { }, + Ascender => { }, + Descender => { }, +); + +#------------------------------------------------------------------------------ +# Read information from a TrueType font collection (TTC) (refs 2,3) +# Inputs: 0) ExifTool ref, 1) dirInfo ref +# Returns: 1 on success, 0 if this wasn't a valid TrueType font collection +sub ProcessTTC($$) +{ + my ($et, $dirInfo) = @_; + my $raf = $$dirInfo{RAF}; + my ($buff, $i); + + return 0 unless $raf->Read($buff, 12) == 12; + return 0 unless $buff =~ /^ttcf\0[\x01\x02]\0\0/; + SetByteOrder('MM'); + my $num = Get32u(\$buff, 8); + # might as well put a limit on the number of fonts we will parse (< 256) + return 0 unless $num < 0x100 and $raf->Read($buff, $num * 4) == $num * 4; + $et->SetFileType('TTC'); + return 1 if $$et{OPTIONS}{FastScan} and $$et{OPTIONS}{FastScan} == 3; + my $tagTablePtr = GetTagTable('Image::ExifTool::Font::Main'); + $et->HandleTag($tagTablePtr, 'numfonts', $num); + # loop through all fonts in the collection + for ($i=0; $i<$num; ++$i) { + my $n = $i + 1; + $et->VPrint(0, "Font $n:\n"); + $$et{SET_GROUP1} = "+$n"; + my $offset = Get32u(\$buff, $i * 4); + $raf->Seek($offset, 0) or last; + ProcessOTF($et, $dirInfo) or last; + } + delete $$et{SET_GROUP1}; + return 1; +} + +#------------------------------------------------------------------------------ +# Read information from a TrueType font file (OTF or TTF) (refs 1,2) +# Inputs: 0) ExifTool ref, 1) dirInfo ref +# Returns: 1 on success, 0 if this wasn't a valid TrueType font file +sub ProcessOTF($$) +{ + my ($et, $dirInfo) = @_; + my $raf = $$dirInfo{RAF}; + my ($tbl, $buff, $pos, $i); + my $base = $$dirInfo{Base} || 0; + + return 0 unless $raf->Read($buff, 12) == 12; + return 0 unless $buff =~ /^(\0\x01\0\0|OTTO|true|typ1|\xa5(kbd|lst))[\0\x01]/; + + $et->SetFileType($1 eq 'OTTO' ? 'OTF' : 'TTF'); + return 1 if $$et{OPTIONS}{FastScan} and $$et{OPTIONS}{FastScan} == 3; + SetByteOrder('MM'); + my $numTables = Get16u(\$buff, 4); + return 0 unless $numTables > 0 and $numTables < 0x200; + my $len = $numTables * 16; + return 0 unless $raf->Read($tbl, $len) == $len; + + my $verbose = $et->Options('Verbose'); + my $oldIndent = $$et{INDENT}; + $$et{INDENT} .= '| '; + $et->VerboseDir('TrueType', $numTables) if $verbose; + + for ($pos=0; $pos<$len; $pos+=16) { + # look for 'name' table + my $tag = substr($tbl, $pos, 4); + next unless $tag eq 'name' or $verbose; + my $offset = Get32u(\$tbl, $pos + 8); + my $size = Get32u(\$tbl, $pos + 12); + unless ($raf->Seek($offset+$base, 0) and $raf->Read($buff, $size) == $size) { + $et->Warn("Error reading '${tag}' data"); + next; + } + if ($verbose) { + $tag =~ s/([\0-\x1f\x80-\xff])/sprintf('\x%.2x',ord $1)/ge; + my $str = sprintf("%s%d) Tag '%s' (offset 0x%.4x, %d bytes)\n", + $$et{INDENT}, $pos/16, $tag, $offset, $size); + $et->VPrint(0, $str); + $et->VerboseDump(\$buff, Addr => $offset) if $verbose > 2; + next unless $tag eq 'name'; + } + next unless $size >= 8; + my $entries = Get16u(\$buff, 2); + my $recEnd = 6 + $entries * 12; + if ($recEnd > $size) { + $et->Warn('Truncated name record'); + last; + } + my $strStart = Get16u(\$buff, 4); + if ($strStart < $recEnd or $strStart > $size) { + $et->Warn('Invalid string offset'); + last; + } + # parse language-tag record (in format 1 Naming table only) (ref 2) + my %langTag; + if (Get16u(\$buff, 0) == 1 and $recEnd + 2 <= $size) { + my $langTags = Get16u(\$buff, $recEnd); + if ($langTags and $recEnd + 2 + $langTags * 4 < $size) { + for ($i=0; $i<$langTags; ++$i) { + my $pt = $recEnd + 2 + $i * 4; + my $langLen = Get16u(\$buff, $pt); + # make sure the language string length is reasonable (UTF-16BE) + last if $langLen == 0 or $langLen & 0x01 or $langLen > 40; + my $langPt = Get16u(\$buff, $pt + 2) + $strStart; + last if $langPt + $langLen > $size; + my $lang = substr($buff, $langPt, $langLen); + $lang = $et->Decode($lang,'UCS2','MM','UTF8'); + $lang =~ tr/-_a-zA-Z0-9//dc; # remove naughty characters + $langTag{$i + 0x8000} = $lang; + } + } + } + my $tagTablePtr = GetTagTable('Image::ExifTool::Font::Name'); + $$et{INDENT} .= '| '; + $et->VerboseDir('Name', $entries) if $verbose; + for ($i=0; $i<$entries; ++$i) { + my $pt = 6 + $i * 12; + my $platform = Get16u(\$buff, $pt); + my $encoding = Get16u(\$buff, $pt + 2); + my $langID = Get16u(\$buff, $pt + 4); + my $nameID = Get16u(\$buff, $pt + 6); + my $strLen = Get16u(\$buff, $pt + 8); + my $strPt = Get16u(\$buff, $pt + 10) + $strStart; + if ($strPt + $strLen <= $size) { + my $val = substr($buff, $strPt, $strLen); + my ($lang, $charset, $extra); + my $sys = $ttPlatform{$platform}; + # translate from specified encoding + if ($sys) { + $lang = $ttLang{$sys}{$langID} || $langTag{$langID}; + $charset = $ttCharset{$sys}{$encoding}; + if (not $charset) { + if (not defined $charset and not $$et{FontWarn}) { + $et->Warn("Unknown $sys character set ($encoding)"); + $$et{FontWarn} = 1; + } + } else { + # translate to ExifTool character set + $val = $et->Decode($val, $charset); + } + } else { + $et->Warn("Unknown platform ($platform) for name $nameID"); + } + # get the tagInfo for our specific language (use 'en' for default) + my $tagInfo = $et->GetTagInfo($tagTablePtr, $nameID); + if ($tagInfo and $lang and $lang ne 'en') { + my $langInfo = Image::ExifTool::GetLangInfo($tagInfo, $lang); + $tagInfo = $langInfo if $langInfo; + } + if ($verbose) { + $langID > 0x400 and $langID = sprintf('0x%x', $langID); + $extra = ", Plat=$platform/" . ($sys || 'Unknown') . ', ' . + "Enc=$encoding/" . ($charset || 'Unknown') . ', ' . + "Lang=$langID/" . ($lang || 'Unknown'); + } + $et->HandleTag($tagTablePtr, $nameID, $val, + TagInfo => $tagInfo, + DataPt => \$buff, + DataPos => $offset, + Start => $strPt, + Size => $strLen, + Index => $i, + Extra => $extra, + ); + } + } + $$et{INDENT} = $oldIndent . '| '; + last unless $verbose; + } + $$et{INDENT} = $oldIndent; + return 1; +} + +#------------------------------------------------------------------------------ +# Read information from an Adobe Font Metrics file (AFM, ACFM, AMFM) (ref 6) +# Inputs: 0) ExifTool ref, 1) dirInfo ref +# Returns: 1 on success, 0 if this wasn't a recognized AFM-type file +sub ProcessAFM($$) +{ + my ($et, $dirInfo) = @_; + my $raf = $$dirInfo{RAF}; + my ($buff, $comment); + + require Image::ExifTool::PostScript; + local $/ = Image::ExifTool::PostScript::GetInputRecordSeparator($raf); + $raf->ReadLine($buff); + return 0 unless $buff =~ /^Start(Comp|Master)?FontMetrics\s+\d+/; + my $ftyp = $1 ? ($1 eq 'Comp' ? 'ACFM' : 'AMFM') : 'AFM'; + $et->SetFileType($ftyp, 'application/x-font-afm'); + return 1 if $$et{OPTIONS}{FastScan} and $$et{OPTIONS}{FastScan} == 3; + my $tagTablePtr = GetTagTable('Image::ExifTool::Font::AFM'); + + for (;;) { + $raf->ReadLine($buff) or last; + if (defined $comment and $buff !~ /^Comment\s/) { + $et->FoundTag('Comment', $comment); + undef $comment; + } + $buff =~ /^(\w+)\s+(.*?)[\x0d\x0a]/ or next; + my ($tag, $val) = ($1, $2); + if ($tag eq 'Comment' and $val =~ /^(Creation Date):\s+(.*)/) { + ($tag, $val) = ($1, $2); + } + $val =~ s/^\((.*)\)$/$1/; # (some values may be in brackets) + if ($tag eq 'Comment') { + # concatinate all comments into a single value + $comment = defined($comment) ? "$comment\n$val" : $val; + next; + } + unless ($et->HandleTag($tagTablePtr, $tag, $val)) { + # end parsing if we start any subsection + last if $tag =~ /^Start/ and $tag ne 'StartDirection'; + } + } + return 1; +} + +#------------------------------------------------------------------------------ +# Read information from various format font files +# Inputs: 0) ExifTool ref, 1) dirInfo ref +# Returns: 1 on success, 0 if this wasn't a recognized Font file +sub ProcessFont($$) +{ + my ($et, $dirInfo) = @_; + my $raf = $$dirInfo{RAF}; + my ($buff, $buf2, $rtnVal); + return 0 unless $raf->Read($buff, 24) and $raf->Seek(0,0); + if ($buff =~ /^(\0\x01\0\0|OTTO|true|typ1)[\0\x01]/) { # OTF, TTF + $rtnVal = ProcessOTF($et, $dirInfo); + } elsif ($buff =~ /^ttcf\0[\x01\x02]\0\0/) { # TTC + $rtnVal = ProcessTTC($et, $dirInfo); + } elsif ($buff =~ /^Start(Comp|Master)?FontMetrics\s+\d+/s) { # AFM + $rtnVal = ProcessAFM($et, $dirInfo); + } elsif ($buff =~ /^(.{6})?%!(PS-(AdobeFont-|Bitstream )|FontType1-)/s) {# PFA, PFB + $raf->Seek(6,0) and $et->SetFileType('PFB') if $1; + require Image::ExifTool::PostScript; + $rtnVal = Image::ExifTool::PostScript::ProcessPS($et, $dirInfo); + } elsif ($buff =~ /^\0[\x01\x02]/ and $raf->Seek(0, 2) and # PFM + # validate file size + $raf->Tell() > 117 and $raf->Tell() == unpack('x2V',$buff) and + # read PFM header + $raf->Seek(0,0) and $raf->Read($buff,117) == 117 and + # validate "DeviceType" string (must be "PostScript\0") + SetByteOrder('II') and $raf->Seek(Get32u(\$buff, 101), 0) and + # the DeviceType should be "PostScript\0", but FontForge + # incorrectly writes "Postscript\0", so ignore case + $raf->Read($buf2, 11) == 11 and lc($buf2) eq "postscript\0") + { + $et->SetFileType('PFM'); + return 1 if $$et{OPTIONS}{FastScan} and $$et{OPTIONS}{FastScan} == 3; + SetByteOrder('II'); + my $tagTablePtr = GetTagTable('Image::ExifTool::Font::Main'); + # process the PFM header + $et->HandleTag($tagTablePtr, 'PFM', $buff); + # extract the font names + my $nameOff = Get32u(\$buff, 105); + if ($raf->Seek($nameOff, 0) and $raf->Read($buff, 256) and + $buff =~ /^([\x20-\xff]+)\0([\x20-\xff]+)\0/) + { + $et->HandleTag($tagTablePtr, 'fontname', $1); + $et->HandleTag($tagTablePtr, 'postfont', $2); + } + $rtnVal = 1; + } else { + $rtnVal = 0; + } + return $rtnVal; +} + +1; # end + +__END__ + +=head1 NAME + +Image::ExifTool::Font - Read meta information from font files + +=head1 SYNOPSIS + +This module is used by Image::ExifTool + +=head1 DESCRIPTION + +This module contains the routines required by Image::ExifTool to read meta +information from various format font files. Currently recognized font file +types are OTF, TTF, TTC, DFONT, PFA, PFB, PFM, AFM, ACFM and AMFM. + +=head1 AUTHOR + +Copyright 2003-2019, Phil Harvey (phil at owl.phy.queensu.ca) + +This library is free software; you can redistribute it and/or modify it +under the same terms as Perl itself. + +=head1 REFERENCES + +=over 4 + +=item L<http://developer.apple.com/textfonts/TTRefMan/RM06/Chap6.html> + +=item L<http://www.microsoft.com/typography/otspec/otff.htm> + +=item L<http://partners.adobe.com/public/developer/opentype/index_font_file.html> + +=item L<http://partners.adobe.com/public/developer/en/font/5178.PFM.pdf> + +=item L<http://opensource.adobe.com/svn/opensource/flex/sdk/trunk/modules/compiler/src/java/flex2/compiler/util/MimeMappings.java> + +=item L<http://www.adobe.com/devnet/font/pdfs/5004.AFM_Spec.pdf> + +=back + +=head1 SEE ALSO + +L<Image::ExifTool::TagNames/Font Tags>, +L<Image::ExifTool(3pm)|Image::ExifTool> + +=cut + diff --git a/lib/Image/ExifTool/FotoStation.pm b/lib/Image/ExifTool/FotoStation.pm new file mode 100644 index 0000000..2330b3f --- /dev/null +++ b/lib/Image/ExifTool/FotoStation.pm @@ -0,0 +1,261 @@ +#------------------------------------------------------------------------------ +# File: FotoStation.pm +# +# Description: Read/write FotoWare FotoStation trailer +# +# Revisions: 10/28/2006 - P. Harvey Created +#------------------------------------------------------------------------------ + +package Image::ExifTool::FotoStation; + +use strict; +use vars qw($VERSION); +use Image::ExifTool qw(:DataAccess :Utils); + +$VERSION = '1.04'; + +sub ProcessFotoStation($$); + +%Image::ExifTool::FotoStation::Main = ( + PROCESS_PROC => \&ProcessFotoStation, + WRITE_PROC => \&ProcessFotoStation, + GROUPS => { 2 => 'Image' }, + NOTES => q{ + The following tables define information found in the FotoWare FotoStation + trailer. + }, + 0x01 => { + Name => 'IPTC', + SubDirectory => { + TagTable => 'Image::ExifTool::IPTC::Main', + }, + }, + 0x02 => { + Name => 'SoftEdit', + SubDirectory => { + TagTable => 'Image::ExifTool::FotoStation::SoftEdit', + }, + }, + 0x03 => { + Name => 'ThumbnailImage', + Groups => { 2 => 'Preview' }, + Writable => 1, + RawConv => '$self->ValidateImage(\$val,$tag)', + }, + 0x04 => { + Name => 'PreviewImage', + Groups => { 2 => 'Preview' }, + Writable => 1, + RawConv => '$self->ValidateImage(\$val,$tag)', + }, +); + +# crop coordinate conversions +my %cropConv = ( + ValueConv => '$val / 1000', + ValueConvInv => '$val * 1000', + PrintConv => '"$val%"', + PrintConvInv => '$val=~tr/ %//d; $val', +); + +# soft crop record +%Image::ExifTool::FotoStation::SoftEdit = ( + PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData, + WRITE_PROC => \&Image::ExifTool::WriteBinaryData, + CHECK_PROC => \&Image::ExifTool::CheckBinaryData, + WRITABLE => 1, + FORMAT => 'int32s', + FIRST_ENTRY => 0, + GROUPS => { 2 => 'Image' }, + 0 => { + Name => 'OriginalImageWidth', + }, + 1 => 'OriginalImageHeight', + 2 => 'ColorPlanes', + 3 => { + Name => 'XYResolution', + ValueConv => '$val / 1000', + ValueConvInv => '$val * 1000', + }, + 4 => { + Name => 'Rotation', + Notes => q{ + rotations are stored as degrees CCW * 100, but converted to degrees CW by + ExifTool + }, + # raw value is 0, 9000, 18000 or 27000 + ValueConv => '$val ? 360 - $val / 100 : 0', + ValueConvInv => '$val ? (360 - $val) * 100 : 0', + }, + # 5 Validity Check (0x11222211) + 6 => { + Name => 'CropLeft', + %cropConv, + }, + 7 => { + Name => 'CropTop', + %cropConv, + }, + 8 => { + Name => 'CropRight', + %cropConv, + }, + 9 => { + Name => 'CropBottom', + %cropConv, + }, + 11 => { + Name => 'CropRotation', + # raw value in the range -4500 to 4500 + ValueConv => '-$val / 100', + ValueConvInv => '-$val * 100', + }, +); + +#------------------------------------------------------------------------------ +# Read/write FotoStation information in a file +# Inputs: 0) ExifTool object reference, 1) dirInfo reference +# Returns: 1 on success, 0 if this file didn't contain FotoStation information +# - updates DataPos to point to start of FotoStation information +# - updates DirLen to trailer length +sub ProcessFotoStation($$) +{ + my ($et, $dirInfo) = @_; + $et or return 1; # allow dummy access to autoload this package + my ($buff, $footer, $dirBuff, $tagTablePtr); + my $raf = $$dirInfo{RAF}; + my $outfile = $$dirInfo{OutFile}; + my $offset = $$dirInfo{Offset} || 0; + my $verbose = $et->Options('Verbose'); + my $out = $et->Options('TextOut'); + my $rtnVal = 0; + + $$dirInfo{DirLen} = 0; # initialize returned trailer length + $raf->Seek(-$offset, 2); # seek to specified offset from end of file + + # loop through FotoStation records + for (;;) { + # look for trailer signature + last unless $raf->Seek(-10, 1) and $raf->Read($footer, 10) == 10; + my ($tag, $size, $sig) = unpack('nNN', $footer); + last unless $sig == 0xa1b2c3d4 and $size >= 10 and $raf->Seek(-$size, 1); + $size -= 10; # size of data only + last unless $raf->Read($buff, $size) == $size; + $raf->Seek(-$size, 1); + # set variables returned in dirInfo hash + $$dirInfo{DataPos} = $raf->Tell(); + $$dirInfo{DirLen} += $size + 10; + + unless ($tagTablePtr) { + $tagTablePtr = GetTagTable('Image::ExifTool::FotoStation::Main'); + SetByteOrder('MM'); # necessary for the binary data + $rtnVal = 1; # we found a valid FotoStation trailer + } + unless ($outfile) { + # print verbose trailer information + if ($verbose or $$et{HTML_DUMP}) { + $et->DumpTrailer({ + RAF => $raf, + DataPos => $$dirInfo{DataPos}, + DirLen => $size + 10, + DirName => "FotoStation_$tag", + }); + } + # extract information for this tag + $et->HandleTag($tagTablePtr, $tag, $buff, + DataPt => \$buff, + Start => 0, + Size => $size, + DataPos => $$dirInfo{DataPos}, + ); + next; + } + if ($$et{DEL_GROUP}{FotoStation}) { + $verbose and print $out " Deleting FotoStation trailer\n"; + $verbose = 0; # no more verbose messages after this + ++$$et{CHANGED}; + next; + } + # rewrite this information + my $tagInfo = $et->GetTagInfo($tagTablePtr, $tag); + if ($tagInfo) { + my $newVal; + my $tagName = $$tagInfo{Name}; + if ($$tagInfo{SubDirectory}) { + my %subdirInfo = ( + DataPt => \$buff, + DirStart => 0, + DirLen => $size, + DataPos => $$dirInfo{DataPos}, + DirName => $tagName, + Parent => 'FotoStation', + ); + my $subTable = GetTagTable($tagInfo->{SubDirectory}->{TagTable}); + $newVal = $et->WriteDirectory(\%subdirInfo, $subTable); + } else { + my $nvHash = $et->GetNewValueHash($tagInfo); + if ($et->IsOverwriting($nvHash) > 0) { + $newVal = $et->GetNewValue($nvHash); + $newVal = '' unless defined $newVal; + if ($verbose > 1) { + my $n = length $newVal; + print $out " - FotoStation:$tagName ($size bytes)\n" if $size; + print $out " + FotoStation:$tagName ($n bytes)\n" if $n; + } + ++$$et{CHANGED}; + } + } + if (defined $newVal) { + # note: length may be 0 here, but we write the empty record anyway + $buff = $newVal; + $size = length($newVal) + 10; + $footer = pack('nNN', $tag, $size, $sig); + } + } + if (defined $dirBuff) { + # maintain original record order + $dirBuff = $buff . $footer . $dirBuff; + } else { + $dirBuff = $buff . $footer; + } + } + # write the modified FotoStation trailer + Write($outfile, $dirBuff) or $rtnVal = -1 if $dirBuff; + return $rtnVal; +} + +1; # end + +__END__ + +=head1 NAME + +Image::ExifTool::FotoStation - Read/write FotoWare FotoStation trailer + +=head1 SYNOPSIS + +This module is used by Image::ExifTool + +=head1 DESCRIPTION + +This module contains definitions required by Image::ExifTool to read and +write information from the FotoWare FotoStation trailer. + +=head1 AUTHOR + +Copyright 2003-2019, Phil Harvey (phil at owl.phy.queensu.ca) + +This library is free software; you can redistribute it and/or modify it +under the same terms as Perl itself. + +=head1 ACKNOWLEDGEMENTS + +Thanks to Mark Tate for information about the FotoStation data format. + +=head1 SEE ALSO + +L<Image::ExifTool::TagNames/FotoStation Tags>, +L<Image::ExifTool(3pm)|Image::ExifTool> + +=cut + diff --git a/lib/Image/ExifTool/FujiFilm.pm b/lib/Image/ExifTool/FujiFilm.pm new file mode 100644 index 0000000..d3634c2 --- /dev/null +++ b/lib/Image/ExifTool/FujiFilm.pm @@ -0,0 +1,1591 @@ +#------------------------------------------------------------------------------ +# File: FujiFilm.pm +# +# Description: Read/write FujiFilm maker notes and RAF images +# +# Revisions: 11/25/2003 - P. Harvey Created +# 11/14/2007 - PH Added abilty to write RAF images +# +# References: 1) http://park2.wakwak.com/~tsuruzoh/Computer/Digicams/exif-e.html +# 2) http://homepage3.nifty.com/kamisaka/makernote/makernote_fuji.htm (2007/09/11) +# 3) Michael Meissner private communication +# 4) Paul Samuelson private communication (S5) +# 5) http://www.cybercom.net/~dcoffin/dcraw/ +# 6) http://forums.dpreview.com/forums/readflat.asp?forum=1012&thread=31350384 +# and http://forum.photome.de/viewtopic.php?f=2&t=353&p=742#p740 +# 7) Kai Lappalainen private communication +# 8) http://u88.n24.queensu.ca/exiftool/forum/index.php/topic,5223.0.html +# 9) Zilvinas Brobliauskas private communication +# 10) Albert Shan private communication +# 11) http://u88.n24.queensu.ca/exiftool/forum/index.php/topic,8377.0.html +# 12) http://u88.n24.queensu.ca/exiftool/forum/index.php/topic,9607.0.html +# IB) Iliah Borg private communication (LibRaw) +# JD) Jens Duttke private communication +#------------------------------------------------------------------------------ + +package Image::ExifTool::FujiFilm; + +use strict; +use vars qw($VERSION); +use Image::ExifTool qw(:DataAccess :Utils); +use Image::ExifTool::Exif; + +$VERSION = '1.67'; + +sub ProcessFujiDir($$$); +sub ProcessFaceRec($$$); + +# the following RAF version numbers have been tested for writing: +my %testedRAF = ( + '0100' => 'E550, E900, F770, S5600, S6000fd, S6500fd, HS10/HS11, HS30, S200EXR, X100, XF1, X-Pro1, X-S1, XQ2 Ver1.00, X-T100, GFX 50R, XF10', + '0101' => 'X-E1, X20 Ver1.01, X-T3', + '0102' => 'S100FS, X10 Ver1.02', + '0103' => 'IS Pro Ver1.03', + '0104' => 'S5Pro Ver1.04', + '0106' => 'S5Pro Ver1.06', + '0111' => 'S5Pro Ver1.11', + '0114' => 'S9600 Ver1.00', + '0132' => 'X-T2 Ver1.32', + '0144' => 'X100T Ver1.44', + '0159' => 'S2Pro Ver1.00', + '0200' => 'X10 Ver2.00', + '0212' => 'S3Pro Ver2.12', + '0216' => 'S3Pro Ver2.16', # (NC) + '0218' => 'S3Pro Ver2.18', + '0264' => 'F700 Ver2.00', + '0266' => 'S9500 Ver1.01', + '0269' => 'S9500 Ver1.02', + '0271' => 'S3Pro Ver2.71', # UV/IR model? + '0300' => 'X-E2', + # 0400 - expect to see this for X-T1 + '0540' => 'X-T1 Ver5.40', + '0712' => 'S5000 Ver3.00', + '0716' => 'S5000 Ver3.00', # (yes, 2 RAF versions with the same Software version) + '0Dgi' => 'X-A10 Ver1.01 and X-A3 Ver1.02', # (yes, non-digits in the firmware number) +); + +my %faceCategories = ( + Format => 'int8u', + PrintConv => { BITMASK => { + 1 => 'Partner', + 2 => 'Family', + 3 => 'Friend', + }}, +); + +# FujiFilm MakerNotes tags +%Image::ExifTool::FujiFilm::Main = ( + WRITE_PROC => \&Image::ExifTool::Exif::WriteExif, + CHECK_PROC => \&Image::ExifTool::Exif::CheckExif, + WRITABLE => 1, + GROUPS => { 0 => 'MakerNotes', 2 => 'Camera' }, + 0x0 => { + Name => 'Version', + Writable => 'undef', + }, + 0x0010 => { #PH/IB + Name => 'InternalSerialNumber', + Writable => 'string', + Notes => q{ + this number is unique for most models, and contains the camera model ID and + the date of manufacture + }, + # eg) "FPX20017035 592D31313034060427796060110384" + # "FPX 20495643 592D313335310701318AD010110047" (F40fd) + # HHHHHHHHHHHHyymmdd + # HHHHHHHHHHHH = camera body number in hex + # yymmdd = date of manufacture + PrintConv => q{ + if ($val =~ /^(.*?\s*)([0-9a-fA-F]*)(\d{2})(\d{2})(\d{2})(.{12})\s*\0*$/s + and $4 >= 1 and $4 <= 12 and $5 >= 1 and $5 <= 31) + { + my $yr = $3 + ($3 < 70 ? 2000 : 1900); + my $sn = pack 'H*', $2; + return "$1$sn $yr:$4:$5 $6"; + } else { + # handle a couple of models which use a slightly different format + $val =~ s/\b(592D(3[0-9])+)/pack("H*",$1).' '/e; + } + return $val; + }, + # (this inverse conversion doesn't work in all cases, so it is best to write + # the ValueConv value if an authentic internal serial number is required) + PrintConvInv => '$_=$val; s/(\S+) (19|20)(\d{2}):(\d{2}):(\d{2}) /unpack("H*",$1)."$3$4$5"/e; $_', + }, + 0x1000 => { + Name => 'Quality', + Writable => 'string', + }, + 0x1001 => { + Name => 'Sharpness', + Flags => 'PrintHex', + Writable => 'int16u', + PrintConv => { + 0x00 => '-4 (softest)', #10 + 0x01 => '-3 (very soft)', + 0x02 => '-2 (soft)', + 0x03 => '0 (normal)', + 0x04 => '+2 (hard)', + 0x05 => '+3 (very hard)', + 0x06 => '+4 (hardest)', + 0x82 => '-1 (medium soft)', #2 + 0x84 => '+1 (medium hard)', #2 + 0x8000 => 'Film Simulation', #2 + 0xffff => 'n/a', #2 + }, + }, + 0x1002 => { + Name => 'WhiteBalance', + Flags => 'PrintHex', + Writable => 'int16u', + PrintConv => { + 0x0 => 'Auto', + 0x100 => 'Daylight', + 0x200 => 'Cloudy', + 0x300 => 'Daylight Fluorescent', + 0x301 => 'Day White Fluorescent', + 0x302 => 'White Fluorescent', + 0x303 => 'Warm White Fluorescent', #2/PH (S5) + 0x304 => 'Living Room Warm White Fluorescent', #2/PH (S5) + 0x400 => 'Incandescent', + 0x500 => 'Flash', #4 + 0x600 => 'Underwater', #forum6109 + 0xf00 => 'Custom', + 0xf01 => 'Custom2', #2 + 0xf02 => 'Custom3', #2 + 0xf03 => 'Custom4', #2 + 0xf04 => 'Custom5', #2 + # 0xfe0 => 'Gray Point?', #2 + 0xff0 => 'Kelvin', #4 + }, + }, + 0x1003 => { + Name => 'Saturation', + Flags => 'PrintHex', + Writable => 'int16u', + PrintConv => { + 0x0 => '0 (normal)', # # ("Color 0", ref 8) + 0x080 => '+1 (medium high)', #2 ("Color +1", ref 8) + 0x100 => '+2 (high)', # ("Color +2", ref 8) + 0x0c0 => '+3 (very high)', + 0x0e0 => '+4 (highest)', + 0x180 => '-1 (medium low)', #2 ("Color -1", ref 8) + 0x200 => 'Low', + 0x300 => 'None (B&W)', #2 + 0x301 => 'B&W Red Filter', #PH/8 + 0x302 => 'B&W Yellow Filter', #PH (X100) + 0x303 => 'B&W Green Filter', #PH/8 + 0x310 => 'B&W Sepia', #PH (X100) + 0x400 => '-2 (low)', #8 ("Color -2") + 0x4c0 => '-3 (very low)', + 0x4e0 => '-4 (lowest)', + 0x500 => 'Acros', #PH (X-Pro2) + 0x501 => 'Acros Red Filter', #PH (X-Pro2) + 0x502 => 'Acros Yellow Filter', #PH (X-Pro2) + 0x503 => 'Acros Green Filter', #PH (X-Pro2) + 0x8000 => 'Film Simulation', #2 + }, + }, + 0x1004 => { + Name => 'Contrast', + Flags => 'PrintHex', + Writable => 'int16u', + PrintConv => { + 0x0 => 'Normal', + 0x080 => 'Medium High', #2 + 0x100 => 'High', + 0x180 => 'Medium Low', #2 + 0x200 => 'Low', + 0x8000 => 'Film Simulation', #2 + }, + }, + 0x1005 => { #4 + Name => 'ColorTemperature', + Writable => 'int16u', + }, + 0x1006 => { #JD + Name => 'Contrast', + Flags => 'PrintHex', + Writable => 'int16u', + PrintConv => { + 0x0 => 'Normal', + 0x100 => 'High', + 0x300 => 'Low', + }, + }, + 0x100a => { #2 + Name => 'WhiteBalanceFineTune', + Writable => 'int32s', + Count => 2, + PrintConv => 'sprintf("Red %+d, Blue %+d", split(" ", $val))', + PrintConvInv => 'my @v=($val=~/-?\d+/g);"@v"', + }, + 0x100b => { #2 + Name => 'NoiseReduction', + Flags => 'PrintHex', + Writable => 'int16u', + RawConv => '$val == 0x100 ? undef : $val', + PrintConv => { + 0x40 => 'Low', + 0x80 => 'Normal', + 0x100 => 'n/a', #PH (NC) (all X100 samples) + }, + }, + 0x100e => { #PH (X100) + Name => 'NoiseReduction', + Flags => 'PrintHex', + Writable => 'int16u', + PrintConv => { + 0x000 => '0 (normal)', # ("NR 0, ref 8) + 0x100 => '+2 (strong)', # ("NR+2, ref 8) + 0x180 => '+1 (medium strong)', #8 ("NR+1") + 0x1c0 => '+3 (very strong)', + 0x1e0 => '+4 (strongest)', + 0x200 => '-2 (weak)', # ("NR-2, ref 8) + 0x280 => '-1 (medium weak)', #8 ("NR-1") + 0x2c0 => '-3 (very weak)', #10 (-3) + 0x2e0 => '-4 (weakest)', #10 (-4) + }, + }, + 0x1010 => { + Name => 'FujiFlashMode', + Writable => 'int16u', + PrintHex => 1, + PrintConv => { + 0 => 'Auto', + 1 => 'On', + 2 => 'Off', + 3 => 'Red-eye reduction', + 4 => 'External', #JD + 16 => 'Commander', + 0x8000 => 'Not Attached', #10 (X-T2) (or external flash off) + 0x8120 => 'TTL', #10 (X-T2) + 0x9840 => 'Manual', #10 (X-T2) + 0x9880 => 'Multi-flash', #10 (X-T2) + 0xa920 => '1st Curtain (front)', #10 (EF-X500 flash) + 0xc920 => '2nd Curtain (rear)', #10 + 0xe920 => 'High Speed Sync (HSS)', #10 + }, + }, + 0x1011 => { + Name => 'FlashExposureComp', #JD + Writable => 'rational64s', + }, + 0x1020 => { + Name => 'Macro', + Writable => 'int16u', + PrintConv => { + 0 => 'Off', + 1 => 'On', + }, + }, + 0x1021 => { + Name => 'FocusMode', + Writable => 'int16u', + PrintConv => { + 0 => 'Auto', + 1 => 'Manual', + }, + }, + 0x1022 => { #8/forum6579 + Name => 'AFMode', + Writable => 'int16u', + Notes => '"No" for manual and some AF-multi focus modes', + PrintConv => { + 0 => 'No', + 1 => 'Single Point', + 256 => 'Zone', + 512 => 'Wide/Tracking', + }, + }, + 0x102b => { + Name => 'PrioritySettings', + SubDirectory => { TagTable => 'Image::ExifTool::FujiFilm::PrioritySettings' }, + }, + 0x102d => { + Name => 'FocusSettings', + SubDirectory => { TagTable => 'Image::ExifTool::FujiFilm::FocusSettings' }, + }, + 0x102e => { + Name => 'AFCSettings', + SubDirectory => { TagTable => 'Image::ExifTool::FujiFilm::AFCSettings' }, + }, + 0x1023 => { #2 + Name => 'FocusPixel', + Writable => 'int16u', + Count => 2, + }, + 0x1030 => { + Name => 'SlowSync', + Writable => 'int16u', + PrintConv => { + 0 => 'Off', + 1 => 'On', + }, + }, + 0x1031 => { + Name => 'PictureMode', + Flags => 'PrintHex', + Writable => 'int16u', + PrintConv => { + 0x0 => 'Auto', # (or 'SR+' if SceneRecognition present, ref 11) + 0x1 => 'Portrait', + 0x2 => 'Landscape', + 0x3 => 'Macro', #JD + 0x4 => 'Sports', + 0x5 => 'Night Scene', + 0x6 => 'Program AE', + 0x7 => 'Natural Light', #3 + 0x8 => 'Anti-blur', #3 + 0x9 => 'Beach & Snow', #JD + 0xa => 'Sunset', #3 + 0xb => 'Museum', #3 + 0xc => 'Party', #3 + 0xd => 'Flower', #3 + 0xe => 'Text', #3 + 0xf => 'Natural Light & Flash', #3 + 0x10 => 'Beach', #3 + 0x11 => 'Snow', #3 + 0x12 => 'Fireworks', #3 + 0x13 => 'Underwater', #3 + 0x14 => 'Portrait with Skin Correction', #7 + 0x16 => 'Panorama', #PH (X100) + 0x17 => 'Night (tripod)', #7 + 0x18 => 'Pro Low-light', #7 + 0x19 => 'Pro Focus', #7 + 0x1a => 'Portrait 2', #PH (NC, T500, maybe "Smile & Shoot"?) + 0x1b => 'Dog Face Detection', #7 + 0x1c => 'Cat Face Detection', #7 + 0x40 => 'Advanced Filter', + 0x100 => 'Aperture-priority AE', + 0x200 => 'Shutter speed priority AE', + 0x300 => 'Manual', + }, + }, + 0x1032 => { #8 + Name => 'ExposureCount', + Writable => 'int16u', + Notes => 'number of exposures used for this image', + }, + 0x1033 => { #6 + Name => 'EXRAuto', + Writable => 'int16u', + PrintConv => { + 0 => 'Auto', + 1 => 'Manual', + }, + }, + 0x1034 => { #6 + Name => 'EXRMode', + Writable => 'int16u', + PrintHex => 1, + PrintConv => { + 0x100 => 'HR (High Resolution)', + 0x200 => 'SN (Signal to Noise priority)', + 0x300 => 'DR (Dynamic Range priority)', + }, + }, + 0x1040 => { #8 + Name => 'ShadowTone', + Writable => 'int32s', + PrintConv => { + -64 => '+4 (hardest)', + -48 => '+3 (very hard)', + -32 => '+2 (hard)', + -16 => '+1 (medium hard)', + 0 => '0 (normal)', + 16 => '-1 (medium soft)', + 32 => '-2 (soft)', + }, + }, + 0x1041 => { #8 + Name => 'HighlightTone', + Writable => 'int32s', + PrintConv => { + -64 => '+4 (hardest)', + -48 => '+3 (very hard)', + -32 => '+2 (hard)', + -16 => '+1 (medium hard)', + 0 => '0 (normal)', + 16 => '-1 (medium soft)', + 32 => '-2 (soft)', + }, + }, + 0x1044 => { #forum7668 + Name => 'DigitalZoom', + Writable => 'int32u', + ValueConv => '$val / 8', + ValueConvInv => '$val * 8', + }, + 0x1045 => { #12 + Name => 'LensModulationOptimizer', + Writable => 'int32u', + PrintConv => { 0 => 'Off', 1 => 'On' }, + }, + 0x1047 => { #12 + Name => 'GrainEffect', + Writable => 'int32s', + PrintConv => { + 0 => 'Off', + 32 => 'Weak', + 64 => 'Strong', + }, + }, + 0x1048 => { #12 + Name => 'ColorChromeEffect', + Writable => 'int32s', + PrintConv => { + 0 => 'Off', + 32 => 'Weak', + 64 => 'Strong', + }, + }, + 0x1049 => { #12 + Name => 'BWAdjustment', + Notes => 'positive values are warm, negative values are cool', + Format => 'int8s', + PrintConv => '$val > 0 ? "+$val" : $val', + PrintConvInv => '$val + 0', + }, + 0x104d => { #forum9634 + Name => 'CropMode', + Writable => 'int16u', + PrintConv => { + 0 => 'n/a', + 2 => 'Sports Finder Mode', # (mechanical shutter) + 4 => 'Electronic Shutter 1.25x Crop', # (continuous high) + }, + }, + 0x1050 => { #forum6109 + Name => 'ShutterType', + Writable => 'int16u', + PrintConv => { + 0 => 'Mechanical', + 1 => 'Electronic', + 2 => 'Electronic (long shutter speed)', #12 + 3 => 'Electronic Front Curtain', #10 + }, + }, + 0x1100 => [{ + Name => 'AutoBracketing', + Condition => '$$self{Model} eq "X-T3"', + Notes => 'X-T3 only', + Writable => 'int16u', + PrintConv => { + 0 => 'Off', + 1 => 'On', + 2 => 'Pre-shot', #12 (Electronic Shutter and Continuous High drive mode only) + }, + },{ + Name => 'AutoBracketing', + Notes => 'other models', + Writable => 'int16u', + PrintConv => { + 0 => 'Off', + 1 => 'On', + 2 => 'No flash & flash', #3 + }, + }], + 0x1101 => { + Name => 'SequenceNumber', + Writable => 'int16u', + }, + 0x1103 => { + Name => 'DriveSettings', + SubDirectory => { TagTable => 'Image::ExifTool::FujiFilm::DriveSettings' }, + }, + # (0x1150-0x1152 exist only for Pro Low-light and Pro Focus PictureModes) + # 0x1150 - Pro Low-light - val=1; Pro Focus - val=2 (ref 7) + # 0x1151 - Pro Low-light - val=4 (number of pictures taken?); Pro Focus - val=2,3 (ref 7) + # 0x1152 - Pro Low-light - val=1,3,4 (stacked pictures used?); Pro Focus - val=1,2 (ref 7) + 0x1153 => { #forum7668 + Name => 'PanoramaAngle', + Writable => 'int16u', + }, + 0x1154 => { #forum7668 + Name => 'PanoramaDirection', + Writable => 'int16u', + PrintConv => { + 1 => 'Right', + 2 => 'Up', + 3 => 'Left', + 4 => 'Down', + }, + }, + 0x1201 => { #forum6109 + Name => 'AdvancedFilter', + Writable => 'int32u', + PrintHex => 1, + PrintConv => { + 0x10000 => 'Pop Color', + 0x20000 => 'Hi Key', + 0x30000 => 'Toy Camera', + 0x40000 => 'Miniature', + 0x50000 => 'Dynamic Tone', + 0x60001 => 'Partial Color Red', + 0x60002 => 'Partial Color Yellow', + 0x60003 => 'Partial Color Green', + 0x60004 => 'Partial Color Blue', + 0x60005 => 'Partial Color Orange', + 0x60006 => 'Partial Color Purple', + 0x70000 => 'Soft Focus', + 0x90000 => 'Low Key', + }, + }, + 0x1210 => { #2 + Name => 'ColorMode', + Writable => 'int16u', + PrintHex => 1, + PrintConv => { + 0x00 => 'Standard', + 0x10 => 'Chrome', + 0x30 => 'B & W', + }, + }, + 0x1300 => { + Name => 'BlurWarning', + Writable => 'int16u', + PrintConv => { + 0 => 'None', + 1 => 'Blur Warning', + }, + }, + 0x1301 => { + Name => 'FocusWarning', + Writable => 'int16u', + PrintConv => { + 0 => 'Good', + 1 => 'Out of focus', + }, + }, + 0x1302 => { + Name => 'ExposureWarning', + Writable => 'int16u', + PrintConv => { + 0 => 'Good', + 1 => 'Bad exposure', + }, + }, + 0x1304 => { #PH + Name => 'GEImageSize', + Condition => '$$self{Make} =~ /^GENERAL IMAGING/', + Writable => 'string', + Notes => 'GE models only', + }, + 0x1400 => { #2 + Name => 'DynamicRange', + Writable => 'int16u', + PrintConv => { + 1 => 'Standard', + 3 => 'Wide', + # the S5Pro has 100%(STD),130%,170%,230%(W1),300%,400%(W2) - PH + }, + }, + 0x1401 => { #2 (this doesn't seem to work for the X100 - PH) + Name => 'FilmMode', + Writable => 'int16u', + PrintHex => 1, + PrintConv => { + 0x000 => 'F0/Standard (Provia)', # X-Pro2 "Provia/Standard" + 0x100 => 'F1/Studio Portrait', + 0x110 => 'F1a/Studio Portrait Enhanced Saturation', + 0x120 => 'F1b/Studio Portrait Smooth Skin Tone (Astia)', # X-Pro2 "Astia/Soft" + 0x130 => 'F1c/Studio Portrait Increased Sharpness', + 0x200 => 'F2/Fujichrome (Velvia)', # X-Pro2 "Velvia/Vivid" + 0x300 => 'F3/Studio Portrait Ex', + 0x400 => 'F4/Velvia', + 0x500 => 'Pro Neg. Std', #PH (X-Pro1) + 0x501 => 'Pro Neg. Hi', #PH (X-Pro1) + 0x600 => 'Classic Chrome', #forum6109 + 0x700 => 'Eterna', #12 + }, + }, + 0x1402 => { #2 + Name => 'DynamicRangeSetting', + Writable => 'int16u', + PrintHex => 1, + PrintConv => { + 0x000 => 'Auto (100-400%)', + 0x001 => 'Manual', #(ref http://forum.photome.de/viewtopic.php?f=2&t=353) + 0x100 => 'Standard (100%)', + 0x200 => 'Wide1 (230%)', + 0x201 => 'Wide2 (400%)', + 0x8000 => 'Film Simulation', + }, + }, + 0x1403 => { #2 (only valid for manual DR, ref 6) + Name => 'DevelopmentDynamicRange', + Writable => 'int16u', + }, + 0x1404 => { #2 + Name => 'MinFocalLength', + Writable => 'rational64s', + }, + 0x1405 => { #2 + Name => 'MaxFocalLength', + Writable => 'rational64s', + }, + 0x1406 => { #2 + Name => 'MaxApertureAtMinFocal', + Writable => 'rational64s', + }, + 0x1407 => { #2 + Name => 'MaxApertureAtMaxFocal', + Writable => 'rational64s', + }, + # 0x1408 - values: '0100', 'S100', 'VQ10' + # 0x1409 - values: same as 0x1408 + # 0x140a - values: 0, 1, 3, 5, 7 (bit 2=red-eye detection, ref 11) + 0x140b => { #6 + Name => 'AutoDynamicRange', + Writable => 'int16u', + PrintConv => '"$val%"', + PrintConvInv => '$val=~s/\s*\%$//; $val', + }, + 0x1422 => { #8 + Name => 'ImageStabilization', + Writable => 'int16u', + Count => 3, + PrintConv => [{ + 0 => 'None', + 1 => 'Optical', #PH + 2 => 'Sensor-shift', #PH + 3 => 'OIS Lens', #forum9815 (optical+sensor?) + 512 => 'Digital', #PH + },{ + 0 => 'Off', + 1 => 'On (mode 1, continuous)', + 2 => 'On (mode 2, shooting only)', + }], + }, + 0x1425 => { # if present and 0x1031 PictureMode is zero, then PictureMode is SR+, not Auto (ref 11) + Name => 'SceneRecognition', + Writable => 'int16u', + PrintHex => 1, + PrintConv => { + 0 => 'Unrecognized', + 0x100 => 'Portrait Image', + 0x200 => 'Landscape Image', + 0x300 => 'Night Scene', + 0x400 => 'Macro', + }, + }, + 0x1431 => { #forum6109 + Name => 'Rating', + Groups => { 2 => 'Image' }, + Writable => 'int32u', + Priority => 0, + }, + 0x1436 => { #8 + Name => 'ImageGeneration', + Writable => 'int16u', + PrintConv => { + 0 => 'Original Image', + 1 => 'Re-developed from RAW', + }, + }, + 0x1438 => { #forum6579 (X-T1 firmware version 3) + Name => 'ImageCount', + Notes => 'may reset to 0 when new firmware is installed', + Writable => 'int16u', + ValueConv => '$val & 0x7fff', + ValueConvInv => '$val | 0x8000', + }, + 0x1443 => { #12 (X-T3) + Name => 'DRangePriority', + Writable => 'int16u', + PrintConv => { 0 => 'Auto', 1 => 'Fixed' }, + }, + 0x1444 => { #12 (X-T3, only exists if DRangePriority is 'Auto') + Name => 'DRangePriorityAuto', + Writable => 'int16u', + PrintConv => { 1 => 'Weak', 2 => 'Strong' }, + }, + 0x1445 => { #12 (X-T3, only exists if DRangePriority is 'Fixed') + Name => 'DRangePriorityFixed', + Writable => 'int16u', + PrintConv => { 1 => 'Weak', 2 => 'Strong' }, + }, + 0x1446 => { #12 + Name => 'FlickerReduction', + Writable => 'int32u', + PrintConv => q{ + my $on = ((($val >> 12) & 0xff) == 3) ? 'On' : 'Off'; + return sprintf('%s (0x%.4x)', $on, $val); + }, + PrintConvInv => '$val=~/(0x[0-9a-f]+)/i; hex $1', + }, + 0x3820 => { #PH (HS20EXR MOV) + Name => 'FrameRate', + Writable => 'int16u', + Groups => { 2 => 'Video' }, + }, + 0x3821 => { #PH (HS20EXR MOV) + Name => 'FrameWidth', + Writable => 'int16u', + Groups => { 2 => 'Video' }, + }, + 0x3822 => { #PH (HS20EXR MOV) + Name => 'FrameHeight', + Writable => 'int16u', + Groups => { 2 => 'Video' }, + }, + 0x4005 => { #forum9634 + Name => 'FaceElementSelected', # (could be face or eye) + Writable => 'int16u', + Count => 4, + }, + 0x4100 => { #PH + Name => 'FacesDetected', + Writable => 'int16u', + }, + 0x4103 => { #PH + Name => 'FacePositions', + Writable => 'int16u', + Count => -1, + Notes => q{ + left, top, right and bottom coordinates in full-sized image for each face + detected + }, + }, + 0x4200 => { #11 + Name => 'NumFaceElements', + Writable => 'int16u', + }, + 0x4201 => { #11 + Name => 'FaceElementTypes', + Writable => 'int8u', + Count => -1, + PrintConv => [{ + 1 => 'Face', + 2 => 'Left Eye', + 3 => 'Right Eye', + },'REPEAT'], + }, + # 0x4202 int8u[-1] - number of cooredinates in each rectangle? (ref 11) + 0x4203 => { #11 + Name => 'FaceElementPositions', + Writable => 'int16u', + Count => -1, + Notes => q{ + left, top, right and bottom coordinates in full-sized image for each face + element + }, + }, + # 0x4101-0x4105 - exist only if face detection active + # 0x4104 - also related to face detection (same number of entries as FacePositions) + # 0x4200 - same as 0x4100? + # 0x4203 - same as 0x4103 + # 0x4204 - same as 0x4104 + 0x4282 => { #PH + Name => 'FaceRecInfo', + SubDirectory => { TagTable => 'Image::ExifTool::FujiFilm::FaceRecInfo' }, + }, + 0x8000 => { #2 + Name => 'FileSource', + Writable => 'string', + }, + 0x8002 => { #2 + Name => 'OrderNumber', + Writable => 'int32u', + }, + 0x8003 => { #2 + Name => 'FrameNumber', + Writable => 'int16u', + }, + 0xb211 => { #PH + Name => 'Parallax', + # (value set in camera is -0.5 times this value in MPImage2... why?) + Writable => 'rational64s', + Notes => 'only found in MPImage2 of .MPO images', + }, + # 0xb212 - also found in MPIMage2 images - PH +); + +# Focus Priority settings, tag 0x102b (X-T3, ref forum 9607) +%Image::ExifTool::FujiFilm::PrioritySettings = ( + PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData, + WRITE_PROC => \&Image::ExifTool::WriteBinaryData, + CHECK_PROC => \&Image::ExifTool::CheckBinaryData, + GROUPS => { 0 => 'MakerNotes', 2 => 'Camera' }, + FORMAT => 'int16u', + WRITABLE => 1, + 0.1 => { + Name => 'AF-SPriority', + Mask => 0x000f, + PrintConv => { + 1 => 'Release', + 2 => 'Focus', + }, + }, + 0.2 => { + Name => 'AF-CPriority', + Mask => 0x00f0, + PrintConv => { + 1 => 'Release', + 2 => 'Focus', + }, + }, +); + +# Focus settings, tag 0x102d (X-T3, ref forum 9607) +%Image::ExifTool::FujiFilm::FocusSettings = ( + PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData, + WRITE_PROC => \&Image::ExifTool::WriteBinaryData, + CHECK_PROC => \&Image::ExifTool::CheckBinaryData, + GROUPS => { 0 => 'MakerNotes', 2 => 'Camera' }, + FORMAT => 'int32u', + WRITABLE => 1, + 0.1 => { + Name => 'FocusMode2', + Mask => 0x000000ff, + PrintConv => { + 0 => 'AF-M', + 1 => 'AF-S', + 2 => 'AF-C', + }, + }, + 0.2 => { + Name => 'AFAreaMode', + Mask => 0x0f00, + PrintConv => { + 0 => 'Single Point', + 1 => 'Zone', + 2 => 'Wide/Tracking', + }, + }, + 0.3 => { + Name => 'AFAreaPointSize', + Mask => 0xf000, + PrintConv => { + 0 => 'n/a', + OTHER => sub { return $_[0] }, + }, + }, + 0.4 => { + Name => 'AFAreaZoneSize', + Mask => 0xf0000, + PrintConv => { + 0 => 'n/a', + OTHER => sub { + my ($val, $inv) = @_; + return "$val x $val" unless $inv; + $val =~ s/ ?x.*//; + return $val; + }, + }, + }, +); + +# AF-C settings, tag 0x102e (ref forum 9607) +%Image::ExifTool::FujiFilm::AFCSettings = ( + PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData, + WRITE_PROC => \&Image::ExifTool::WriteBinaryData, + CHECK_PROC => \&Image::ExifTool::CheckBinaryData, + GROUPS => { 0 => 'MakerNotes', 2 => 'Camera' }, + FORMAT => 'int32u', + WRITABLE => 1, + 0 => { + Name => 'AF-CSetting', + PrintHex => 3, + PrintSort => 1, # sort PrintConv by value + # decode in-camera preset values (X-T3) + PrintConv => { + 0x102 => 'Set 1 (multi-purpose)', # (2,0,Auto) + 0x203 => 'Set 2 (ignore obstacles)', # (3,0,Center) + 0x122 => 'Set 3 (accelerating subject)', # (2,2,Auto) + 0x010 => 'Set 4 (suddenly appearing subject)', # (0,1,Front) + 0x123 => 'Set 5 (erratic motion)', # (3,2,Auto) + OTHER => sub { + my ($val, $inv) = @_; + return $val =~ /(0x\w+)/ ? hex $1 : undef if $inv; + return sprintf 'Set 6 (custom 0x%.3x)', $val; + }, + }, + }, + 0.1 => { + Name => 'AF-CTrackingSensitivity', + Mask => 0x000f, # (values 0-4) + }, + 0.2 => { + Name => 'AF-CSpeedTrackingSensitivity', + Mask => 0x00f0, + # (values 0-2) + }, + 0.3 => { + Name => 'AF-CZoneAreaSwitching', + Mask => 0x0f00, + PrintConv => { + 0 => 'Front', + 1 => 'Auto', + 2 => 'Center', + }, + }, +); + +# DriveMode settings, tag 0x1103 (X-T3, ref forum 9607) +%Image::ExifTool::FujiFilm::DriveSettings = ( + PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData, + WRITE_PROC => \&Image::ExifTool::WriteBinaryData, + CHECK_PROC => \&Image::ExifTool::CheckBinaryData, + GROUPS => { 0 => 'MakerNotes', 2 => 'Camera' }, + FORMAT => 'int32u', + WRITABLE => 1, + 0.1 => { + Name => 'DriveMode', + Mask => 0x000000ff, + PrintConv => { + 0 => 'Single', + 1 => 'Continuous Low', + 2 => 'Continuous High', + }, + }, + 0.2 => { + Name => 'DriveSpeed', + Mask => 0xff000000, + PrintConv => { + 0 => 'n/a', + OTHER => sub { + my ($val, $inv) = @_; + return "$val fps" unless $inv; + $val =~ s/ ?fps$//; + return $val; + }, + }, + }, +); + +# Face recognition information from FinePix F550EXR (ref PH) +%Image::ExifTool::FujiFilm::FaceRecInfo = ( + PROCESS_PROC => \&ProcessFaceRec, + GROUPS => { 0 => 'MakerNotes', 2 => 'Image' }, + VARS => { NO_ID => 1 }, + NOTES => 'Face recognition information.', + Face1Name => { }, + Face2Name => { }, + Face3Name => { }, + Face4Name => { }, + Face5Name => { }, + Face6Name => { }, + Face7Name => { }, + Face8Name => { }, + Face1Category => { %faceCategories }, + Face2Category => { %faceCategories }, + Face3Category => { %faceCategories }, + Face4Category => { %faceCategories }, + Face5Category => { %faceCategories }, + Face6Category => { %faceCategories }, + Face7Category => { %faceCategories }, + Face8Category => { %faceCategories }, + Face1Birthday => { }, + Face2Birthday => { }, + Face3Birthday => { }, + Face4Birthday => { }, + Face5Birthday => { }, + Face6Birthday => { }, + Face7Birthday => { }, + Face8Birthday => { }, +); + +# tags in RAF images (ref 5) +%Image::ExifTool::FujiFilm::RAF = ( + PROCESS_PROC => \&ProcessFujiDir, + GROUPS => { 0 => 'RAF', 1 => 'RAF', 2 => 'Image' }, + PRIORITY => 0, # so the first RAF directory takes precedence + NOTES => q{ + FujiFilm RAF images contain meta information stored in a proprietary + FujiFilm RAF format, as well as EXIF information stored inside an embedded + JPEG preview image. The table below lists tags currently decoded from the + RAF-format information. + }, + 0x100 => { + Name => 'RawImageFullSize', + Format => 'int16u', + Groups => { 1 => 'RAF2' }, # (so RAF2 shows up in family 1 list) + Count => 2, + Notes => 'including borders', + ValueConv => 'my @v=reverse split(" ",$val);"@v"', + PrintConv => '$val=~tr/ /x/; $val', + }, + 0x121 => [ + { + Name => 'RawImageSize', + Condition => '$$self{Model} eq "FinePixS2Pro"', + Format => 'int16u', + Count => 2, + ValueConv => q{ + my @v=split(" ",$val); + $v[0]*=2, $v[1]/=2; + return "@v"; + }, + PrintConv => '$val=~tr/ /x/; $val', + }, + { + Name => 'RawImageSize', + Format => 'int16u', + Count => 2, + # values are height then width, adjusted for the layout + ValueConv => q{ + my @v=reverse split(" ",$val); + $$self{FujiLayout} and $v[0]/=2, $v[1]*=2; + return "@v"; + }, + PrintConv => '$val=~tr/ /x/; $val', + }, + ], + 0x130 => { + Name => 'FujiLayout', + Format => 'int8u', + RawConv => q{ + my ($v) = split ' ', $val; + $$self{FujiLayout} = $v & 0x80 ? 1 : 0; + return $val; + }, + }, + 0x131 => { #5 + Name => 'XTransLayout', + Description => 'X-Trans Layout', + Format => 'int8u', + Count => 36, + PrintConv => '$val =~ tr/012 /RGB/d; join " ", $val =~ /....../g', + }, + 0x2000 => { #IB + Name => 'WB_GRGBLevelsAuto', + Format => 'int16u', + Count => 4, # (ignore the duplicate values) + }, + 0x2100 => { #IB + Name => 'WB_GRGBLevelsDaylight', + Format => 'int16u', + Count => 4, + }, + 0x2200 => { #IB + Name => 'WB_GRGBLevelsCloudy', + Format => 'int16u', + Count => 4, + }, + 0x2300 => { #IB + Name => 'WB_GRGBLevelsDaylightFluor', + Format => 'int16u', + Count => 4, + }, + 0x2301 => { #IB + Name => 'WB_GRGBLevelsDayWhiteFluor', + Format => 'int16u', + Count => 4, + }, + 0x2302 => { #IB + Name => 'WB_GRGBLevelsWhiteFluorescent', + Format => 'int16u', + Count => 4, + }, + 0x2310 => { #IB + Name => 'WB_GRGBLevelsWarmWhiteFluor', + Format => 'int16u', + Count => 4, + }, + 0x2311 => { #IB + Name => 'WB_GRGBLevelsLivingRoomWarmWhiteFluor', + Format => 'int16u', + Count => 4, + }, + 0x2400 => { #IB + Name => 'WB_GRGBLevelsTungsten', + Format => 'int16u', + Count => 4, + }, + # 0x2f00 => WB_GRGBLevelsCustom: int32u count, then count * (int16u GRGBGRGB), ref IB + 0x2ff0 => { + Name => 'WB_GRGBLevels', + Format => 'int16u', + Count => 4, + }, + 0x9200 => { #Frank Markesteijn + Name => 'RelativeExposure', + Format => 'rational32s', + ValueConv => 'log($val) / log(2)', + ValueConvInv => 'exp($val * log(2))', + PrintConv => '$val ? sprintf("%+.1f",$val) : 0', + PrintConvInv => '$val', + }, + # 0x9200 - relative exposure? (ref Frank Markesteijn) + 0x9650 => { #Frank Markesteijn + Name => 'RawExposureBias', + Format => 'rational32s', + PrintConv => '$val ? sprintf("%+.1f",$val) : 0', + PrintConvInv => '$val', + }, + 0xc000 => { + Name => 'RAFData', + SubDirectory => { + TagTable => 'Image::ExifTool::FujiFilm::RAFData', + ByteOrder => 'Little-endian', + } + }, +); + +%Image::ExifTool::FujiFilm::RAFData = ( + PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData, + GROUPS => { 0 => 'MakerNotes', 2 => 'Camera' }, + DATAMEMBER => [ 0, 4, 8 ], + FIRST_ENTRY => 0, + # (FujiFilm image dimensions are REALLY confusing) + # --> this needs some cleaning up + # [Note to self: See email from Iliah Borg for more information about WB settings in this data] + 0 => { + Name => 'RawImageWidth', + Format => 'int32u', + DataMember => 'FujiWidth', + RawConv => '$val < 10000 ? $$self{FujiWidth} = $val : undef', #5 + ValueConv => '$$self{FujiLayout} ? ($val / 2) : $val', + }, + 4 => [ + { + Name => 'RawImageWidth', + Condition => 'not $$self{FujiWidth}', + Format => 'int32u', + DataMember => 'FujiWidth', + RawConv => '$val < 10000 ? $$self{FujiWidth} = $val : undef', #PH + ValueConv => '$$self{FujiLayout} ? ($val / 2) : $val', + }, + { + Name => 'RawImageHeight', + Format => 'int32u', + DataMember => 'FujiHeight', + RawConv => '$$self{FujiHeight} = $val', + ValueConv => '$$self{FujiLayout} ? ($val * 2) : $val', + }, + ], + 8 => [ + { + Name => 'RawImageWidth', + Condition => 'not $$self{FujiWidth}', + Format => 'int32u', + DataMember => 'FujiWidth', + RawConv => '$val < 10000 ? $$self{FujiWidth} = $val : undef', #PH + ValueConv => '$$self{FujiLayout} ? ($val / 2) : $val', + }, + { + Name => 'RawImageHeight', + Condition => 'not $$self{FujiHeight}', + Format => 'int32u', + DataMember => 'FujiHeight', + RawConv => '$$self{FujiHeight} = $val', + ValueConv => '$$self{FujiLayout} ? ($val * 2) : $val', + }, + ], + 12 => { + Name => 'RawImageHeight', + Condition => 'not $$self{FujiHeight}', + Format => 'int32u', + ValueConv => '$$self{FujiLayout} ? ($val * 2) : $val', + }, +); + +# TIFF IFD-format information stored in FujiFilm RAF images (ref 5) +%Image::ExifTool::FujiFilm::IFD = ( + PROCESS_PROC => \&Image::ExifTool::Exif::ProcessExif, + GROUPS => { 0 => 'RAF', 1 => 'FujiIFD', 2 => 'Image' }, + NOTES => 'Tags found in the FujiIFD information of RAF images from some models.', + 0xf000 => { + Name => 'FujiIFD', + Groups => { 1 => 'FujiIFD' }, + Flags => 'SubIFD', + SubDirectory => { + TagTable => 'Image::ExifTool::FujiFilm::IFD', + DirName => 'FujiSubIFD', + Start => '$val', + }, + }, + 0xf001 => 'RawImageFullWidth', + 0xf002 => 'RawImageFullHeight', + 0xf003 => 'BitsPerSample', + # 0xf004 - values: 4 + # 0xf005 - values: 1374, 1668 + # 0xf006 - some sort of flag indicating packed format? + 0xf007 => { + Name => 'StripOffsets', + IsOffset => 1, + OffsetPair => 0xf008, # point to associated byte counts + }, + 0xf008 => { + Name => 'StripByteCounts', + OffsetPair => 0xf007, # point to associated offsets + }, + # 0xf009 - values: 0, 3 + 0xf00a => 'BlackLevel', #IB + 0xf00b => 'GeometricDistortionParams', #9 (rational64s[23, 35 or 43]) + 0xf00c => 'WB_GRBLevelsStandard', #IB (GRBXGRBX; X=17 is standard illuminant A, X=21 is D65) + 0xf00d => 'WB_GRBLevelsAuto', #IB + 0xf00e => 'WB_GRBLevels', + 0xf00f => 'ChromaticAberrationParams', # (rational64s[23]) + 0xf010 => 'VignettingParams', #9 (rational64s[31 or 64]) +); + +# information found in FFMV atom of MOV videos +%Image::ExifTool::FujiFilm::FFMV = ( + PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData, + GROUPS => { 0 => 'MakerNotes', 2 => 'Camera' }, + FIRST_ENTRY => 0, + NOTES => 'Information found in the FFMV atom of MOV videos.', + 0 => { + Name => 'MovieStreamName', + Format => 'string[34]', + }, +); + +# tags in FujiFilm QuickTime videos (ref PH) +# (similar information in Kodak,Minolta,Nikon,Olympus,Pentax and Sanyo videos) +%Image::ExifTool::FujiFilm::MOV = ( + PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData, + GROUPS => { 0 => 'MakerNotes', 2 => 'Camera' }, + FIRST_ENTRY => 0, + NOTES => 'This information is found in MOV videos from some FujiFilm cameras.', + 0x00 => { + Name => 'Make', + Format => 'string[24]', + }, + 0x18 => { + Name => 'Model', + Description => 'Camera Model Name', + Format => 'string[16]', + }, + 0x2e => { # (NC) + Name => 'ExposureTime', + Format => 'int32u', + ValueConv => '$val ? 1 / $val : 0', + PrintConv => 'Image::ExifTool::Exif::PrintExposureTime($val)', + }, + 0x32 => { + Name => 'FNumber', + Format => 'rational64u', + PrintConv => 'sprintf("%.1f",$val)', + }, + 0x3a => { # (NC) + Name => 'ExposureCompensation', + Format => 'rational64s', + PrintConv => '$val ? sprintf("%+.1f", $val) : 0', + }, +); + +#------------------------------------------------------------------------------ +# decode information from FujiFilm face recognition information +# Inputs: 0) ExifTool object reference, 1) dirInfo reference, 2) tag table ref +# Returns: 1 +sub ProcessFaceRec($$$) +{ + my ($et, $dirInfo, $tagTablePtr) = @_; + my $dataPt = $$dirInfo{DataPt}; + my $dataPos = $$dirInfo{DataPos} + ($$dirInfo{Base} || 0); + my $dirStart = $$dirInfo{DirStart}; + my $dirLen = $$dirInfo{DirLen}; + my $pos = $dirStart; + my $end = $dirStart + $dirLen; + my ($i, $n, $p, $val); + $et->VerboseDir('FaceRecInfo'); + for ($i=1; ; ++$i) { + last if $pos + 8 > $end; + my $off = Get32u($dataPt, $pos) + $dirStart; + my $len = Get32u($dataPt, $pos + 4); + last if $len==0 or $off>$end or $off+$len>$end or $len < 62; + # values observed for each offset (always zero if not listed): + # 0=5; 3=1; 4=4; 6=1; 10-13=numbers(constant for a given registered face) + # 15=16; 16=3; 18=1; 22=nameLen; 26=1; 27=16; 28=7; 30-33=nameLen(int32u) + # 34-37=nameOffset(int32u); 38=32; 39=16; 40=4; 42=1; 46=0,2,4,8(category) + # 50=33; 51=16; 52=7; 54-57=dateLen(int32u); 58-61=dateOffset(int32u) + $n = Get32u($dataPt, $off + 30); + $p = Get32u($dataPt, $off + 34) + $dirStart; + last if $p < $dirStart or $p + $n > $end; + $val = substr($$dataPt, $p, $n); + $et->HandleTag($tagTablePtr, "Face${i}Name", $val, + DataPt => $dataPt, + DataPos => $dataPos, + Start => $p, + Size => $n, + ); + $n = Get32u($dataPt, $off + 54); + $p = Get32u($dataPt, $off + 58) + $dirStart; + last if $p < $dirStart or $p + $n > $end; + $val = substr($$dataPt, $p, $n); + $val =~ s/(\d{4})(\d{2})(\d{2})/$1:$2:$2/; + $et->HandleTag($tagTablePtr, "Face${i}Birthday", $val, + DataPt => $dataPt, + DataPos => $dataPos, + Start => $p, + Size => $n, + ); + $et->HandleTag($tagTablePtr, "Face${i}Category", undef, + DataPt => $dataPt, + DataPos => $dataPos, + Start => $off + 46, + Size => 1, + ); + $pos += 8; + } + return 1; +} + +#------------------------------------------------------------------------------ +# get information from FujiFilm RAF directory +# Inputs: 0) ExifTool object reference, 1) dirInfo reference, 2) tag table ref +# Returns: 1 if this was a valid FujiFilm directory +sub ProcessFujiDir($$$) +{ + my ($et, $dirInfo, $tagTablePtr) = @_; + my $raf = $$dirInfo{RAF}; + my $offset = $$dirInfo{DirStart}; + $raf->Seek($offset, 0) or return 0; + my ($buff, $index); + $raf->Read($buff, 4) or return 0; + my $entries = unpack 'N', $buff; + $entries < 256 or return 0; + $et->Options('Verbose') and $et->VerboseDir('Fuji', $entries); + SetByteOrder('MM'); + my $pos = $offset + 4; + for ($index=0; $index<$entries; ++$index) { + $raf->Read($buff,4) or return 0; + $pos += 4; + my ($tag, $len) = unpack 'nn', $buff; + my ($val, $vbuf); + $raf->Read($vbuf, $len) or return 0; + my $tagInfo = $et->GetTagInfo($tagTablePtr, $tag); + if ($tagInfo and $$tagInfo{Format}) { + $val = ReadValue(\$vbuf, 0, $$tagInfo{Format}, $$tagInfo{Count}, $len); + next unless defined $val; + } elsif ($len == 4) { + # interpret unknown 4-byte values as int32u + $val = Get32u(\$vbuf, 0); + } else { + # treat other unknown values as binary data + $val = \$vbuf; + } + $et->HandleTag($tagTablePtr, $tag, $val, + Index => $index, + DataPt => \$vbuf, + DataPos => $pos, + Size => $len, + TagInfo => $tagInfo, + ); + $pos += $len; + } + return 1; +} + +#------------------------------------------------------------------------------ +# write information to FujiFilm RAW file (RAF) +# Inputs: 0) ExifTool object reference, 1) dirInfo reference +# Returns: 1 on success, 0 if this wasn't a valid RAF file, or -1 on write error +sub WriteRAF($$) +{ + my ($et, $dirInfo) = @_; + my $raf = $$dirInfo{RAF}; + my ($hdr, $jpeg, $outJpeg, $offset, $err, $buff); + + $raf->Read($hdr,0x94) == 0x94 or return 0; + $hdr =~ /^FUJIFILM/ or return 0; + my $ver = substr($hdr, 0x3c, 4); + $ver =~ /^\d{4}$/ or $testedRAF{$ver} or return 0; + + # get the position and size of embedded JPEG + my ($jpos, $jlen) = unpack('x84NN', $hdr); + # check to be sure the JPEG starts in the expected location + if ($jpos > 0x94 or $jpos < 0x68 or $jpos & 0x03) { + $et->Error("Unsupported or corrupted RAF image (version $ver)"); + return 1; + } + # check to make sure this version of RAF has been tested + unless ($testedRAF{$ver}) { + $et->Warn("RAF version $ver not yet tested", 1); + } + # read the embedded JPEG + unless ($raf->Seek($jpos, 0) and $raf->Read($jpeg, $jlen) == $jlen) { + $et->Error('Error reading RAF meta information'); + return 1; + } + # use same write directories as JPEG + $et->InitWriteDirs('JPEG'); + # rewrite the embedded JPEG in memory + my %jpegInfo = ( + Parent => 'RAF', + RAF => new File::RandomAccess(\$jpeg), + OutFile => \$outJpeg, + ); + $$et{FILE_TYPE} = 'JPEG'; + my $success = $et->WriteJPEG(\%jpegInfo); + $$et{FILE_TYPE} = 'RAF'; + unless ($success and $outJpeg) { + $et->Error("Invalid RAF format"); + return 1; + } + return -1 if $success < 0; + + # rewrite the RAF image + SetByteOrder('MM'); + my $jpegLen = length $outJpeg; + # pad JPEG to an even 4 bytes (ALWAYS use padding as Fuji does) + my $pad = "\0" x (4 - ($jpegLen % 4)); + # update JPEG size in header (size without padding) + Set32u(length($outJpeg), \$hdr, 0x58); + # get pointer to start of the next RAF block + my $nextPtr = Get32u(\$hdr, 0x5c); + # determine the length of padding at the end of the original JPEG + my $oldPadLen = $nextPtr - ($jpos + $jlen); + if ($oldPadLen) { + if ($oldPadLen > 1000000 or $oldPadLen < 0 or + not $raf->Seek($jpos+$jlen, 0) or + $raf->Read($buff, $oldPadLen) != $oldPadLen) + { + $et->Error('Bad RAF pointer at 0x5c'); + return 1; + } + # make sure padding is only zero bytes (can be >100k for HS10) + # (have seen non-null padding in X-Pro1) + if ($buff =~ /[^\0]/) { + return 1 if $et->Error('Non-null bytes found in padding', 2); + } + } + # calculate offset difference due to change in JPEG size + my $ptrDiff = length($outJpeg) + length($pad) - ($jlen + $oldPadLen); + # update necessary pointers in header + foreach $offset (0x5c, 0x64, 0x78, 0x80) { + last if $offset >= $jpos; # some versions have a short header + my $oldPtr = Get32u(\$hdr, $offset); + next unless $oldPtr; # don't update if pointer is zero + Set32u($oldPtr + $ptrDiff, \$hdr, $offset); + } + # write the new header + my $outfile = $$dirInfo{OutFile}; + Write($outfile, substr($hdr, 0, $jpos)) or $err = 1; + # write the updated JPEG plus padding + Write($outfile, $outJpeg, $pad) or $err = 1; + # copy over the rest of the RAF image + unless ($raf->Seek($nextPtr, 0)) { + $et->Error('Error reading RAF image'); + return 1; + } + while ($raf->Read($buff, 65536)) { + Write($outfile, $buff) or $err = 1, last; + } + return $err ? -1 : 1; +} + +#------------------------------------------------------------------------------ +# get information from FujiFilm RAW file (RAF) +# Inputs: 0) ExifTool object reference, 1) dirInfo reference +# Returns: 1 if this was a valid RAF file +sub ProcessRAF($$) +{ + my ($et, $dirInfo) = @_; + my ($buff, $jpeg, $warn, $offset); + + my $raf = $$dirInfo{RAF}; + $raf->Read($buff,0x5c) == 0x5c or return 0; + $buff =~ /^FUJIFILM/ or return 0; + my ($jpos, $jlen) = unpack('x84NN', $buff); + $jpos & 0x8000 and return 0; + $raf->Seek($jpos, 0) or return 0; + $raf->Read($jpeg, $jlen) == $jlen or return 0; + + $et->SetFileType(); + $et->FoundTag('RAFVersion', substr($buff, 0x3c, 4)); + + # extract information from embedded JPEG + my %dirInfo = ( + Parent => 'RAF', + RAF => new File::RandomAccess(\$jpeg), + ); + $$et{BASE} += $jpos; + my $rtnVal = $et->ProcessJPEG(\%dirInfo); + $$et{BASE} -= $jpos; + $et->FoundTag('PreviewImage', \$jpeg) if $rtnVal; + + # extract information from Fuji RAF and TIFF directories + my ($rafNum, $ifdNum) = ('',''); + foreach $offset (0x5c, 0x64, 0x78, 0x80) { + last if $offset >= $jpos; + unless ($raf->Seek($offset, 0) and $raf->Read($buff, 4)) { + $warn = 1; + last; + } + my $start = unpack('N',$buff); + next unless $start; + if ($offset == 0x64 or $offset == 0x80) { + # parse FujiIFD directory + %dirInfo = ( + RAF => $raf, + Base => $start, + ); + $$et{SET_GROUP1} = "FujiIFD$ifdNum"; + my $tagTablePtr = GetTagTable('Image::ExifTool::FujiFilm::IFD'); + # this is TIFF-format data only for some models, so no warning if it fails + $et->ProcessTIFF(\%dirInfo, $tagTablePtr, \&Image::ExifTool::ProcessTIFF); + delete $$et{SET_GROUP1}; + $ifdNum = ($ifdNum || 1) + 1; + } else { + # parse RAF directory + %dirInfo = ( + RAF => $raf, + DirStart => $start, + ); + $$et{SET_GROUP1} = "RAF$rafNum"; + my $tagTablePtr = GetTagTable('Image::ExifTool::FujiFilm::RAF'); + $et->ProcessDirectory(\%dirInfo, $tagTablePtr) or $warn = 1; + delete $$et{SET_GROUP1}; + $rafNum = ($rafNum || 1) + 1; + } + } + $warn and $et->Warn('Possibly corrupt RAF information'); + + return $rtnVal; +} + +1; # end + +__END__ + +=head1 NAME + +Image::ExifTool::FujiFilm - Read/write FujiFilm maker notes and RAF images + +=head1 SYNOPSIS + +This module is loaded automatically by Image::ExifTool when required. + +=head1 DESCRIPTION + +This module contains definitions required by Image::ExifTool to interpret +FujiFilm maker notes in EXIF information, and to read/write FujiFilm RAW +(RAF) images. + +=head1 AUTHOR + +Copyright 2003-2019, Phil Harvey (phil at owl.phy.queensu.ca) + +This library is free software; you can redistribute it and/or modify it +under the same terms as Perl itself. + +=head1 REFERENCES + +=over 4 + +=item L<http://park2.wakwak.com/~tsuruzoh/Computer/Digicams/exif-e.html> + +=item L<http://homepage3.nifty.com/kamisaka/makernote/makernote_fuji.htm> + +=item L<http://www.cybercom.net/~dcoffin/dcraw/> + +=item (...plus testing with my own FinePix 2400 Zoom) + +=back + +=head1 ACKNOWLEDGEMENTS + +Thanks to Michael Meissner, Paul Samuelson and Jens Duttke for help decoding +some FujiFilm information. + +=head1 SEE ALSO + +L<Image::ExifTool::TagNames/FujiFilm Tags>, +L<Image::ExifTool(3pm)|Image::ExifTool> + +=cut diff --git a/lib/Image/ExifTool/GE.pm b/lib/Image/ExifTool/GE.pm new file mode 100644 index 0000000..70ed52f --- /dev/null +++ b/lib/Image/ExifTool/GE.pm @@ -0,0 +1,81 @@ +#------------------------------------------------------------------------------ +# File: GE.pm +# +# Description: General Imaging maker notes tags +# +# Revisions: 2010-12-14 - P. Harvey Created +#------------------------------------------------------------------------------ + +package Image::ExifTool::GE; + +use strict; +use vars qw($VERSION); +use Image::ExifTool qw(:DataAccess :Utils); +use Image::ExifTool::Exif; + +$VERSION = '1.00'; + +sub ProcessGE2($$$); + +# GE type 1 maker notes (ref PH) +# (similar to Kodak::Type11 and Ricoh::Type2) +%Image::ExifTool::GE::Main = ( + WRITE_PROC => \&Image::ExifTool::Exif::WriteExif, + CHECK_PROC => \&Image::ExifTool::Exif::CheckExif, + WRITABLE => 1, + GROUPS => { 0 => 'MakerNotes', 2 => 'Camera' }, + NOTES => q{ + This table lists tags found in the maker notes of some General Imaging + camera models. + }, + # 0x0104 - int32u + # 0x0200 - int32u[3] (with invalid offset of 0) + 0x0202 => { + Name => 'Macro', + Writable => 'int16u', + PrintConv => { 0 => 'Off', 1 => 'On' }, + }, + # 0x0203 - int16u: 0 + # 0x0204 - rational64u: 10/10 + # 0x0205 - rational64u: 7.249,7.34,9.47 (changes with camera model) + # 0x0206 - int16u[6] (with invalid offset of 0) + 0x0207 => { + Name => 'GEModel', + Format => 'string', + }, + 0x0300 => { + Name => 'GEMake', + Format => 'string', + }, + # 0x0500 - int16u: 0 + # 0x0600 - int32u: 0 +); + +__END__ + +=head1 NAME + +Image::ExifTool::GE - General Imaging maker notes tags + +=head1 SYNOPSIS + +This module is loaded automatically by Image::ExifTool when required. + +=head1 DESCRIPTION + +This module contains definitions required by Image::ExifTool to interpret +General Imaging maker notes. + +=head1 AUTHOR + +Copyright 2003-2019, Phil Harvey (phil at owl.phy.queensu.ca) + +This library is free software; you can redistribute it and/or modify it +under the same terms as Perl itself. + +=head1 SEE ALSO + +L<Image::ExifTool::TagNames/GE Tags>, +L<Image::ExifTool(3pm)|Image::ExifTool> + +=cut diff --git a/lib/Image/ExifTool/GIF.pm b/lib/Image/ExifTool/GIF.pm new file mode 100644 index 0000000..e8e51b4 --- /dev/null +++ b/lib/Image/ExifTool/GIF.pm @@ -0,0 +1,560 @@ +#------------------------------------------------------------------------------ +# File: GIF.pm +# +# Description: Read and write GIF meta information +# +# Revisions: 10/18/2005 - P. Harvey Separated from ExifTool.pm +# 05/23/2008 - P. Harvey Added ability to read/write XMP +# 10/28/2011 - P. Harvey Added ability to read/write ICC_Profile +# +# References: 1) http://www.w3.org/Graphics/GIF/spec-gif89a.txt +# 2) http://www.adobe.com/devnet/xmp/ +# 3) http://graphcomp.com/info/specs/ani_gif.html +# 4) http://www.color.org/icc_specs2.html +# 5) http://www.midiox.com/mmgif.htm +#------------------------------------------------------------------------------ + +package Image::ExifTool::GIF; + +use strict; +use vars qw($VERSION); +use Image::ExifTool qw(:DataAccess :Utils); + +$VERSION = '1.16'; + +# road map of directory locations in GIF images +my %gifMap = ( + XMP => 'GIF', + ICC_Profile => 'GIF', +); + +%Image::ExifTool::GIF::Main = ( + GROUPS => { 2 => 'Image' }, + VARS => { NO_ID => 1 }, + NOTES => q{ + This table lists information extracted from GIF images. See + L<http://www.w3.org/Graphics/GIF/spec-gif89a.txt> for the official GIF89a + specification. + }, + GIFVersion => { }, + FrameCount => { Notes => 'number of animated images' }, + Text => { Notes => 'text displayed in image' }, + Comment => { + # for documentation only -- flag as writable for the docs, but + # it won't appear in the TagLookup because there is no WRITE_PROC + Writable => 1, + }, + Duration => { + Notes => 'duration of a single animation iteration', + PrintConv => 'sprintf("%.2f s",$val)', + }, + ScreenDescriptor => { + SubDirectory => { TagTable => 'Image::ExifTool::GIF::Screen' }, + }, + Extensions => { # (for documentation only) + SubDirectory => { TagTable => 'Image::ExifTool::GIF::Extensions' }, + }, +); + +# GIF89a application extensions: +%Image::ExifTool::GIF::Extensions = ( + GROUPS => { 2 => 'Image' }, + NOTES => 'Tags extracted from GIF89a application extensions.', + 'NETSCAPE/2.0' => { #3 + Name => 'Animation', + SubDirectory => { TagTable => 'Image::ExifTool::GIF::Animation' }, + }, + 'XMP Data/XMP' => { #2 + Name => 'XMP', + IncludeLengthBytes => 1, # length bytes are included in the data + Writable => 1, + SubDirectory => { TagTable => 'Image::ExifTool::XMP::Main' }, + }, + 'ICCRGBG1/012' => { #4 + Name => 'ICC_Profile', + Writable => 1, + SubDirectory => { TagTable => 'Image::ExifTool::ICC_Profile::Main' }, + }, + 'MIDICTRL/Jon' => { #5 + Name => 'MIDIControl', + SubDirectory => { TagTable => 'Image::ExifTool::GIF::MIDIControl' }, + }, + 'MIDISONG/Dm7' => { #5 + Name => 'MIDISong', + Groups => { 2 => 'Audio' }, + Binary => 1, + }, +); + +# GIF locical screen descriptor +%Image::ExifTool::GIF::Screen = ( + PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData, + GROUPS => { 2 => 'Image' }, + NOTES => 'Information extracted from the GIF logical screen descriptor.', + 0 => { + Name => 'ImageWidth', + Format => 'int16u', + }, + 2 => { + Name => 'ImageHeight', + Format => 'int16u', + }, + 4.1 => { + Name => 'HasColorMap', + Mask => 0x80, + PrintConv => { 0 => 'No', 1 => 'Yes' }, + }, + 4.2 => { + Name => 'ColorResolutionDepth', + Mask => 0x70, + ValueConv => '$val + 1', + }, + 4.3 => { + Name => 'BitsPerPixel', + Mask => 0x07, + ValueConv => '$val + 1', + }, + 5 => 'BackgroundColor', +); + +# GIF Netscape 2.0 animation extension (ref 3) +%Image::ExifTool::GIF::Animation = ( + PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData, + GROUPS => { 2 => 'Image' }, + NOTES => 'Information extracted from the "NETSCAPE2.0" animation extension.', + 1 => { + Name => 'AnimationIterations', + Format => 'int16u', + PrintConv => '$val ? $val : "Infinite"', + }, +); + +# GIF MIDICTRL extension (ref 5) +%Image::ExifTool::GIF::MIDIControl = ( + PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData, + GROUPS => { 2 => 'Audio' }, + NOTES => 'Information extracted from the MIDI control block extension.', + 0 => 'MIDIControlVersion', + 1 => 'SequenceNumber', + 2 => 'MelodicPolyphony', + 3 => 'PercussivePolyphony', + 4 => { + Name => 'ChannelUsage', + Format => 'int16u', + PrintConv => 'sprintf("0x%.4x", $val)', + }, + 6 => { + Name => 'DelayTime', + Format => 'int16u', + ValueConv => '$val / 100', + PrintConv => '$val . " s"', + }, +); + +#------------------------------------------------------------------------------ +# Process meta information in GIF image +# Inputs: 0) ExifTool object reference, 1) Directory information ref +# Returns: 1 on success, 0 if this wasn't a valid GIF file, or -1 if +# an output file was specified and a write error occurred +sub ProcessGIF($$) +{ + my ($et, $dirInfo) = @_; + my $outfile = $$dirInfo{OutFile}; + my $raf = $$dirInfo{RAF}; + my $verbose = $et->Options('Verbose'); + my $out = $et->Options('TextOut'); + my ($a, $s, $ch, $length, $buff); + my ($err, $newComment, $setComment, $nvComment); + my ($addDirs, %doneDir); + my ($frameCount, $delayTime) = (0, 0); + + # verify this is a valid GIF file + return 0 unless $raf->Read($buff, 6) == 6 + and $buff =~ /^GIF(8[79]a)$/ + and $raf->Read($s, 7) == 7; + + my $ver = $1; + my $rtnVal = 0; + my $tagTablePtr = GetTagTable('Image::ExifTool::GIF::Main'); + SetByteOrder('II'); + + if ($outfile) { + $et->InitWriteDirs(\%gifMap, 'XMP'); # make XMP the preferred group for GIF + $addDirs = $$et{ADD_DIRS}; + # determine if we are editing the File:Comment tag + my $delGroup = $$et{DEL_GROUP}; + $newComment = $et->GetNewValue('Comment', \$nvComment); + $setComment = 1 if $nvComment or $$delGroup{File}; + # change to GIF 89a if adding comment, XMP or ICC_Profile + $buff = 'GIF89a' if $$addDirs{XMP} or $$addDirs{ICC_Profile} or defined $newComment; + Write($outfile, $buff, $s) or $err = 1; + } else { + $et->SetFileType(); # set file type + $et->HandleTag($tagTablePtr, 'GIFVersion', $ver); + $et->HandleTag($tagTablePtr, 'ScreenDescriptor', $s); + } + my $flags = Get8u(\$s, 4); + if ($flags & 0x80) { # does this image contain a color table? + # calculate color table size + $length = 3 * (2 << ($flags & 0x07)); + $raf->Read($buff, $length) == $length or return 0; # skip color table + Write($outfile, $buff) or $err = 1 if $outfile; + } +# +# loop through GIF blocks +# +Block: + for (;;) { + last unless $raf->Read($ch, 1); + # write out any new metadata now if this isn't an extension block + if ($outfile and ord($ch) != 0x21) { + # write the comment first if necessary + if (defined $newComment and $$nvComment{IsCreating}) { + # write comment marker + Write($outfile, "\x21\xfe") or $err = 1; + $verbose and print $out " + Comment = $newComment\n"; + my $len = length($newComment); + # write out the comment in 255-byte chunks, each + # chunk beginning with a length byte + my $n; + for ($n=0; $n<$len; $n+=255) { + my $size = $len - $n; + $size > 255 and $size = 255; + my $str = substr($newComment,$n,$size); + Write($outfile, pack('C',$size), $str) or $err = 1; + } + Write($outfile, "\0") or $err = 1; # empty chunk as terminator + undef $newComment; + undef $nvComment; # delete any other extraneous comments + ++$$et{CHANGED}; # increment file changed flag + } + # add application extension containing XMP block if necessary + # (this will place XMP before the first non-extension block) + if (exists $$addDirs{XMP} and not defined $doneDir{XMP}) { + $doneDir{XMP} = 1; + # write new XMP data + my $xmpTable = GetTagTable('Image::ExifTool::XMP::Main'); + my %dirInfo = ( Parent => 'GIF' ); + $verbose and print $out "Creating XMP application extension block:\n"; + $buff = $et->WriteDirectory(\%dirInfo, $xmpTable); + if (defined $buff and length $buff) { + my $lz = pack('C*',1,reverse(0..255),0); + Write($outfile, "\x21\xff\x0bXMP DataXMP", $buff, $lz) or $err = 1; + ++$doneDir{XMP}; # set to 2 to indicate we added XMP + } else { + $verbose and print $out " -> no XMP to add\n"; + } + } + # add application extension containing ICC_Profile if necessary + if (exists $$addDirs{ICC_Profile} and not defined $doneDir{ICC_Profile}) { + $doneDir{ICC_Profile} = 1; + # write new ICC_Profile + my $iccTable = GetTagTable('Image::ExifTool::ICC_Profile::Main'); + my %dirInfo = ( Parent => 'GIF' ); + $verbose and print $out "Creating ICC_Profile application extension block:\n"; + $buff = $et->WriteDirectory(\%dirInfo, $iccTable); + if (defined $buff and length $buff) { + my $pos = 0; + Write($outfile, "\x21\xff\x0bICCRGBG1012") or $err = 1; + my $len = length $buff; + while ($pos < $len) { + my $n = $len - $pos; + $n = 255 if $n > 255; + Write($outfile, chr($n), substr($buff, $pos, $n)) or $err = 1; + $pos += $n; + } + Write($outfile, "\0") or $err = 1; # write null terminator + ++$doneDir{ICC_Profile}; # set to 2 to indicate we added a new profile + } else { + $verbose and print $out " -> no ICC_Profile to add\n"; + } + } + } + if (ord($ch) == 0x2c) { + ++$frameCount; + Write($outfile, $ch) or $err = 1 if $outfile; + # image descriptor + last unless $raf->Read($buff, 8) == 8 and $raf->Read($ch, 1); + Write($outfile, $buff, $ch) or $err = 1 if $outfile; + if ($verbose) { + my ($left, $top, $w, $h) = unpack('v*', $buff); + print $out "Image: left=$left top=$top width=$w height=$h\n"; + } + if (ord($ch) & 0x80) { # does color table exist? + $length = 3 * (2 << (ord($ch) & 0x07)); + # skip the color table + last unless $raf->Read($buff, $length) == $length; + Write($outfile, $buff) or $err = 1 if $outfile; + } + # skip "LZW Minimum Code Size" byte + last unless $raf->Read($buff, 1); + Write($outfile,$buff) or $err = 1 if $outfile; + # skip image blocks + for (;;) { + last unless $raf->Read($ch, 1); + Write($outfile, $ch) or $err = 1 if $outfile; + last unless ord($ch); + last unless $raf->Read($buff, ord($ch)); + Write($outfile,$buff) or $err = 1 if $outfile; + } + next; # continue with next field + } +# last if ord($ch) == 0x3b; # normal end of GIF marker + unless (ord($ch) == 0x21) { + if ($outfile) { + Write($outfile, $ch) or $err = 1; + # copy the rest of the file + while ($raf->Read($buff, 65536)) { + Write($outfile, $buff) or $err = 1; + } + } + $rtnVal = 1; + last; + } + # get extension block type/size + last unless $raf->Read($s, 2) == 2; + # get marker and block size + ($a,$length) = unpack("C"x2, $s); + + if ($a == 0xfe) { # comment extension + + my $comment = ''; + while ($length) { + last unless $raf->Read($buff, $length) == $length; + $et->VerboseDump(\$buff) unless $outfile; + # add buffer to comment string + $comment .= $buff; + last unless $raf->Read($ch, 1); # read next block header + $length = ord($ch); # get next block size + } + last if $length; # was a read error if length isn't zero + if ($outfile) { + my $isOverwriting; + if ($setComment) { + if ($nvComment) { + $isOverwriting = $et->IsOverwriting($nvComment,$comment); + # get new comment again (may have been shifted) + $newComment = $et->GetNewValue($nvComment) if defined $newComment; + } else { + # group delete, or deleting additional comments after writing one + $isOverwriting = 1; + } + } + if ($isOverwriting) { + ++$$et{CHANGED}; # increment file changed flag + $et->VerboseValue('- Comment', $comment); + $comment = $newComment; + $et->VerboseValue('+ Comment', $comment) if defined $comment; + undef $nvComment; # just delete remaining comments + } else { + undef $setComment; # leave remaining comments alone + } + if (defined $comment) { + # write comment marker + Write($outfile, "\x21\xfe") or $err = 1; + my $len = length($comment); + # write out the comment in 255-byte chunks, each + # chunk beginning with a length byte + my $n; + for ($n=0; $n<$len; $n+=255) { + my $size = $len - $n; + $size > 255 and $size = 255; + my $str = substr($comment,$n,$size); + Write($outfile, pack('C',$size), $str) or $err = 1; + } + Write($outfile, "\0") or $err = 1; # empty chunk as terminator + } + undef $newComment; # don't write the new comment again + } else { + $rtnVal = 1; + $et->FoundTag('Comment', $comment) if $comment; + undef $comment; + # assume no more than one comment in FastScan mode + last if $et->Options('FastScan'); + } + next; + + } elsif ($a == 0xff and $length == 0x0b) { # application extension + + last unless $raf->Read($buff, $length) == $length; + my $hdr = "$ch$s$buff"; + # add "/" for readability + my $tag = substr($buff, 0, 8) . '/' . substr($buff, 8); + $tag =~ tr/\0-\x1f//d; # remove nulls and control characters + $verbose and print $out "Application Extension: $tag\n"; + + my $extTable = GetTagTable('Image::ExifTool::GIF::Extensions'); + my $extInfo = $$extTable{$tag}; + my ($subdir, $inclLen, $justCopy); + if ($extInfo) { + $subdir = $$extInfo{SubDirectory}; + $inclLen = $$extInfo{IncludeLengthBytes}; + # rewrite as-is unless this is a writable subdirectory + $justCopy = 1 if $outfile and (not $subdir or not $$extInfo{Writable}); + } else { + $justCopy = 1 if $outfile; + } + Write($outfile, $hdr) or $err = 1 if $justCopy; + + # read the extension data + my $dat = ''; + for (;;) { + $raf->Read($ch, 1) or last Block; # read next block header + $length = ord($ch) or last; # get next block size + $raf->Read($buff, $length) == $length or last Block; + Write($outfile, $ch, $buff) or $err = 1 if $justCopy; + $dat .= $inclLen ? $ch . $buff : $buff; + } + Write($outfile, "\0") if $justCopy; + + if ($subdir) { + my $dirLen = length $dat; + my $name = $$extInfo{Name}; + if ($name eq 'XMP') { + # get length of XMP without landing zone data + # (note that LZ data may not be exactly the same as what we use) + $dirLen = pos($dat) if $dat =~ /<\?xpacket end=['"][wr]['"]\?>/g; + } + my %dirInfo = ( + DataPt => \$dat, + DataLen => length $dat, + DirLen => $dirLen, + DirName => $name, + Parent => 'GIF', + ); + my $subTable = GetTagTable($$subdir{TagTable}); + if (not $outfile) { + $et->ProcessDirectory(\%dirInfo, $subTable); + } elsif ($$extInfo{Writable}) { + if ($doneDir{$name} and $doneDir{$name} > 1) { + $et->Warn("Duplicate $name block created"); + } + $buff = $et->WriteDirectory(\%dirInfo, $subTable); + if (defined $buff) { + next unless length $buff; # delete this extension if length is zero + # check for null just to be safe + $et->Error("$name contained NULL character") if $buff =~ /\0/; + $dat = $buff; + # add landing zone (without terminator, which will be added later) + $dat .= pack('C*',1,reverse(0..255)) if $$extInfo{IncludeLengthBytes}; + } # (else rewrite original data) + + $doneDir{$name} = 1; + + if ($$extInfo{IncludeLengthBytes}) { + # write data and landing zone + Write($outfile, $hdr, $dat) or $err = 1; + } else { + # write as sub-blocks + Write($outfile, $hdr) or $err = 1; + my $pos = 0; + my $len = length $dat; + while ($pos < $len) { + my $n = $len - $pos; + $n = 255 if $n > 255; + Write($outfile, chr($n), substr($dat, $pos, $n)) or $err = 1; + $pos += $n; + } + } + Write($outfile, "\0") or $err = 1; # write null terminator + } + } elsif (not $outfile) { + $et->HandleTag($extTable, $tag, $dat); + } + next; + + } elsif ($a == 0xf9 and $length == 4) { # graphic control extension + + last unless $raf->Read($buff, $length) == $length; + # sum the indivual delay times + my $delay = Get16u(\$buff, 1); + $delayTime += $delay; + $verbose and printf $out "Graphic Control: delay=%.2f\n", $delay / 100; + $raf->Seek(-$length, 1) or last; + + } elsif ($a == 0x01 and $length == 12) { # plain text extension + + last unless $raf->Read($buff, $length) == $length; + Write($outfile, $ch, $s, $buff) or $err = 1 if $outfile; + if ($verbose) { + my ($left, $top, $w, $h) = unpack('v4', $buff); + print $out "Text: left=$left top=$top width=$w height=$h\n"; + } + my $text = ''; + for (;;) { + last unless $raf->Read($ch, 1); + $length = ord($ch) or last; + last unless $raf->Read($buff, $length) == $length; + Write($outfile, $ch, $buff) or $err = 1 if $outfile; # write block + $text .= $buff; + } + Write($outfile, "\0") or $err = 1 if $outfile; # write terminator block + $et->HandleTag($tagTablePtr, 'Text', $text); + next; + } + Write($outfile, $ch, $s) or $err = 1 if $outfile; + # skip the block + while ($length) { + last unless $raf->Read($buff, $length) == $length; + Write($outfile, $buff) or $err = 1 if $outfile; + last unless $raf->Read($ch, 1); # read next block header + Write($outfile, $ch) or $err = 1 if $outfile; + $length = ord($ch); # get next block size + } + } + unless ($outfile) { + $et->HandleTag($tagTablePtr, 'FrameCount', $frameCount) if $frameCount > 1; + $et->HandleTag($tagTablePtr, 'Duration', $delayTime/100) if $delayTime; + } + + # set return value to -1 if we only had a write error + $rtnVal = -1 if $rtnVal and $err; + return $rtnVal; +} + + +1; #end + +__END__ + +=head1 NAME + +Image::ExifTool::GIF - Read and write GIF meta information + +=head1 SYNOPSIS + +This module is loaded automatically by Image::ExifTool when required. + +=head1 DESCRIPTION + +This module contains definitions required by Image::ExifTool to read and +write GIF meta information. + +=head1 AUTHOR + +Copyright 2003-2019, Phil Harvey (phil at owl.phy.queensu.ca) + +This library is free software; you can redistribute it and/or modify it +under the same terms as Perl itself. + +=head1 REFERENCES + +=over 4 + +=item L<http://www.w3.org/Graphics/GIF/spec-gif89a.txt> + +=item L<http://www.adobe.com/devnet/xmp/> + +=item L<http://graphcomp.com/info/specs/ani_gif.html> + +=item L<http://www.color.org/icc_specs2.html> + +=item L<http://www.midiox.com/mmgif.htm> + +=back + +=head1 SEE ALSO + +L<Image::ExifTool(3pm)|Image::ExifTool> + +=cut diff --git a/lib/Image/ExifTool/GIMP.pm b/lib/Image/ExifTool/GIMP.pm new file mode 100644 index 0000000..6bf6b2a --- /dev/null +++ b/lib/Image/ExifTool/GIMP.pm @@ -0,0 +1,294 @@ +#------------------------------------------------------------------------------ +# File: GIMP.pm +# +# Description: Read meta information from GIMP XCF images +# +# Revisions: 2010/10/05 - P. Harvey Created +# 2018/08/21 - PH Updated to current XCF specification (v013) +# +# References: 1) GIMP source code +# 2) https://gitlab.gnome.org/GNOME/gimp/blob/master/devel-docs/xcf.txt +#------------------------------------------------------------------------------ + +package Image::ExifTool::GIMP; + +use strict; +use vars qw($VERSION); +use Image::ExifTool qw(:DataAccess :Utils); + +$VERSION = '1.03'; + +sub ProcessParasites($$$); + +# GIMP XCF properties (ref 2) +%Image::ExifTool::GIMP::Main = ( + GROUPS => { 2 => 'Image' }, + VARS => { ALPHA_FIRST => 1 }, + NOTES => q{ + The GNU Image Manipulation Program (GIMP) writes these tags in its native + XCF (eXperimental Computing Facilty) images. + }, + header => { SubDirectory => { TagTable => 'Image::ExifTool::GIMP::Header' } }, + # recognized properties + # 1 - ColorMap + # 17 - SamplePoints? (doc says 17 is also "PROP_SAMPLE_POINTS"??) + 17 => { + Name => 'Compression', + Format => 'int8u', + PrintConv => { + 0 => 'None', + 1 => 'RLE Encoding', + 2 => 'Zlib', + 3 => 'Fractal', + }, + }, + # 18 - Guides + 19 => { + Name => 'Resolution', + SubDirectory => { TagTable => 'Image::ExifTool::GIMP::Resolution' }, + }, + 20 => { + Name => 'Tattoo', + Format => 'int32u', + }, + 21 => { + Name => 'Parasites', + SubDirectory => { TagTable => 'Image::ExifTool::GIMP::Parasite' }, + }, + 22 => { + Name => 'Units', + Format => 'int32u', + PrintConv => { + 1 => 'Inches', + 2 => 'mm', + 3 => 'Points', + 4 => 'Picas', + }, + }, + # 23 Paths + # 24 UserUnit + # 25 Vectors +); + +# information extracted from the XCF file header (ref 2) +%Image::ExifTool::GIMP::Header = ( + GROUPS => { 2 => 'Image' }, + PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData, + 9 => { + Name => 'XCFVersion', + Format => 'string[5]', + DataMember => 'XCFVersion', + RawConv => '$$self{XCFVersion} = $val', + PrintConv => { + 'file' => '0', + 'v001' => '1', + 'v002' => '2', + OTHER => sub { my $val = shift; $val =~ s/^v0*//; return $val }, + }, + }, + 14 => { Name => 'ImageWidth', Format => 'int32u' }, + 18 => { Name => 'ImageHeight', Format => 'int32u' }, + 22 => { + Name => 'ColorMode', + Format => 'int32u', + PrintConv => { + 0 => 'RGB Color', + 1 => 'Grayscale', + 2 => 'Indexed Color', + }, + }, + # 26 - [XCF 4 or later] Precision +); + +# XCF resolution data (property type 19) (ref 2) +%Image::ExifTool::GIMP::Resolution = ( + GROUPS => { 2 => 'Image' }, + PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData, + FORMAT => 'float', + 0 => 'XResolution', + 1 => 'YResolution', +); + +# XCF "Parasite" data (property type 21) (ref 1/PH) +%Image::ExifTool::GIMP::Parasite = ( + GROUPS => { 2 => 'Image' }, + PROCESS_PROC => \&ProcessParasites, + 'gimp-comment' => { + Name => 'Comment', + Format => 'string', + }, + 'exif-data' => { + Name => 'ExifData', + SubDirectory => { + TagTable => 'Image::ExifTool::Exif::Main', + ProcessProc => \&Image::ExifTool::ProcessTIFF, + Start => 6, # starts after "Exif\0\0" header + }, + }, + 'jpeg-exif-data' => { # (deprecated, untested) + Name => 'JPEGExifData', + SubDirectory => { + TagTable => 'Image::ExifTool::Exif::Main', + ProcessProc => \&Image::ExifTool::ProcessTIFF, + Start => 6, + }, + }, + 'iptc-data' => { # (untested) + Name => 'IPTCData', + SubDirectory => { TagTable => 'Image::ExifTool::IPTC::Main' }, + }, + 'icc-profile' => { + Name => 'ICC_Profile', + SubDirectory => { TagTable => 'Image::ExifTool::ICC_Profile::Main' }, + }, + 'icc-profile-name' => { + Name => 'ICCProfileName', + Format => 'string', + }, + 'gimp-metadata' => { + Name => 'XMP', + SubDirectory => { + TagTable => 'Image::ExifTool::XMP::Main', + Start => 10, # starts after "GIMP_XMP_1" header + }, + }, + 'gimp-image-metadata' => { + Name => 'XML', + SubDirectory => { TagTable => 'Image::ExifTool::XMP::XML' }, + }, + # Seen, but not yet decoded: + # gimp-image-grid + # jpeg-settings +); + +#------------------------------------------------------------------------------ +# Read information in a GIMP XCF parasite data (ref PH) +# Inputs: 0) ExifTool ref, 1) dirInfo ref, 2) tag table ref +# Returns: 1 on success +sub ProcessParasites($$$) +{ + my ($et, $dirInfo, $tagTablePtr) = @_; + my $unknown = $et->Options('Unknown') || $et->Options('Verbose'); + my $dataPt = $$dirInfo{DataPt}; + my $pos = $$dirInfo{DirStart} || 0; + my $end = length $$dataPt; + $et->VerboseDir('Parasites', undef, $end); + for (;;) { + last if $pos + 4 > $end; + my $size = Get32u($dataPt, $pos); # length of tag string + $pos += 4; + last if $pos + $size + 8 > $end; + my $tag = substr($$dataPt, $pos, $size); + $pos += $size; + $tag =~ s/\0.*//s; # trim at null terminator + # my $flags = Get32u($dataPt, $pos); (ignore flags) + $size = Get32u($dataPt, $pos + 4); # length of data + $pos += 8; + last if $pos + $size > $end; + if (not $$tagTablePtr{$tag} and $unknown) { + my $name = $tag; + $name =~ tr/-_A-Za-z0-9//dc; + $name =~ s/^gimp-//; + next unless length $name; + $name = ucfirst $name; + $name =~ s/([a-z])-([a-z])/$1\u$2/g; + $name = "GIMP-$name" unless length($name) > 1; + AddTagToTable($tagTablePtr, $tag, { Name => $name, Unknown => 1 }); + } + $et->HandleTag($tagTablePtr, $tag, undef, + DataPt => $dataPt, + Start => $pos, + Size => $size, + ); + $pos += $size; + } + return 1; +} + +#------------------------------------------------------------------------------ +# Read information in a GIMP XCF document +# Inputs: 0) ExifTool ref, 1) dirInfo ref +# Returns: 1 on success, 0 if this wasn't a valid XCF file +sub ProcessXCF($$) +{ + my ($et, $dirInfo) = @_; + my $raf = $$dirInfo{RAF}; + my $buff; + + return 0 unless $raf->Read($buff, 26) == 26; + return 0 unless $buff =~ /^gimp xcf /; + + my $tagTablePtr = GetTagTable('Image::ExifTool::GIMP::Main'); + my $verbose = $et->Options('Verbose'); + $et->SetFileType(); + SetByteOrder('MM'); + + # process the XCF header + $et->HandleTag($tagTablePtr, 'header', $buff); + + # skip over precision for XCV version 4 or later + $raf->Seek(4, 1) if $$et{XCFVersion} =~ /^v0*(\d+)/ and $1 >= 4; + + # loop through image properties + for (;;) { + $raf->Read($buff, 8) == 8 or last; + my $tag = Get32u(\$buff, 0) or last; + my $size = Get32u(\$buff, 4); + $verbose and $et->VPrint(0, "XCF property $tag ($size bytes):\n"); + unless ($$tagTablePtr{$tag}) { + $raf->Seek($size, 1); + next; + } + $raf->Read($buff, $size) == $size or last; + $et->HandleTag($tagTablePtr, $tag, undef, + DataPt => \$buff, + DataPos => $raf->Tell() - $size, + Size => $size, + ); + } + return 1; +} + +1; # end + +__END__ + +=head1 NAME + +Image::ExifTool::GIMP - Read meta information from GIMP XCF images + +=head1 SYNOPSIS + +This module is used by Image::ExifTool + +=head1 DESCRIPTION + +This module contains definitions required by Image::ExifTool to read meta +information from GIMP (GNU Image Manipulation Program) XCF (eXperimental +Computing Facility) images. This is the native image format used by the +GIMP software. + +=head1 AUTHOR + +Copyright 2003-2019, Phil Harvey (phil at owl.phy.queensu.ca) + +This library is free software; you can redistribute it and/or modify it +under the same terms as Perl itself. + +=head1 REFERENCES + +=over 4 + +=item L<GIMP source code> + +=item L<http://svn.gnome.org/viewvc/gimp/trunk/devel-docs/xcf.txt?view=markup> + +=back + +=head1 SEE ALSO + +L<Image::ExifTool::TagNames/GIMP Tags>, +L<Image::ExifTool(3pm)|Image::ExifTool> + +=cut + diff --git a/lib/Image/ExifTool/GPS.pm b/lib/Image/ExifTool/GPS.pm new file mode 100644 index 0000000..66f81d0 --- /dev/null +++ b/lib/Image/ExifTool/GPS.pm @@ -0,0 +1,585 @@ +#------------------------------------------------------------------------------ +# File: GPS.pm +# +# Description: EXIF GPS meta information tags +# +# Revisions: 12/09/2003 - P. Harvey Created +#------------------------------------------------------------------------------ + +package Image::ExifTool::GPS; + +use strict; +use vars qw($VERSION); +use Image::ExifTool::Exif; + +$VERSION = '1.50'; + +my %coordConv = ( + ValueConv => 'Image::ExifTool::GPS::ToDegrees($val)', + ValueConvInv => 'Image::ExifTool::GPS::ToDMS($self, $val)', + PrintConv => 'Image::ExifTool::GPS::ToDMS($self, $val, 1)', + PrintConvInv => 'Image::ExifTool::GPS::ToDegrees($val)', +); + +%Image::ExifTool::GPS::Main = ( + GROUPS => { 0 => 'EXIF', 1 => 'GPS', 2 => 'Location' }, + WRITE_PROC => \&Image::ExifTool::Exif::WriteExif, + CHECK_PROC => \&Image::ExifTool::Exif::CheckExif, + WRITABLE => 1, + WRITE_GROUP => 'GPS', + 0x0000 => { + Name => 'GPSVersionID', + Writable => 'int8u', + Mandatory => 1, + Count => 4, + PrintConv => '$val =~ tr/ /./; $val', + PrintConvInv => '$val =~ tr/./ /; $val', + }, + 0x0001 => { + Name => 'GPSLatitudeRef', + Writable => 'string', + Notes => q{ + tags 0x0001-0x0006 used for camera location according to MWG 2.0. ExifTool + will also accept a number when writing GPSLatitudeRef, positive for north + latitudes or negative for south, or a string ending in N or S + }, + Count => 2, + PrintConv => { + # extract N/S if written from Composite:GPSLatitude + # (also allow writing from a signed number) + OTHER => sub { + my ($val, $inv) = @_; + return undef unless $inv; + return uc $1 if $val =~ /\b([NS])$/i; + return $1 eq '-' ? 'S' : 'N' if $val =~ /^([-+]?)\d+(\.\d*)?$/; + return undef; + }, + N => 'North', + S => 'South', + }, + }, + 0x0002 => { + Name => 'GPSLatitude', + Writable => 'rational64u', + Count => 3, + %coordConv, + }, + 0x0003 => { + Name => 'GPSLongitudeRef', + Writable => 'string', + Count => 2, + Notes => q{ + ExifTool will also accept a number when writing this tag, positive for east + longitudes or negative for west, or a string ending in E or W + }, + PrintConv => { + # extract E/W if written from Composite:GPSLongitude + # (also allow writing from a signed number) + OTHER => sub { + my ($val, $inv) = @_; + return undef unless $inv; + return uc $1 if $val =~ /\b([EW])$/i; + return $1 eq '-' ? 'W' : 'E' if $val =~ /^([-+]?)\d+(\.\d*)?$/; + return undef; + }, + E => 'East', + W => 'West', + }, + }, + 0x0004 => { + Name => 'GPSLongitude', + Writable => 'rational64u', + Count => 3, + %coordConv, + }, + 0x0005 => { + Name => 'GPSAltitudeRef', + Writable => 'int8u', + Notes => q{ + ExifTool will also accept a signed number when writing this tag, beginning + with "+" for above sea level, or "-" for below + }, + PrintConv => { + OTHER => sub { + my ($val, $inv) = @_; + return undef unless $inv and $val =~ /^([-+])/; + return($1 eq '-' ? 1 : 0); + }, + 0 => 'Above Sea Level', + 1 => 'Below Sea Level', + }, + }, + 0x0006 => { + Name => 'GPSAltitude', + Writable => 'rational64u', + # extricate unsigned decimal number from string + ValueConvInv => '$val=~/((?=\d|\.\d)\d*(?:\.\d*)?)/ ? $1 : undef', + PrintConv => '$val =~ /^(inf|undef)$/ ? $val : "$val m"', + PrintConvInv => '$val=~s/\s*m$//;$val', + }, + 0x0007 => { + Name => 'GPSTimeStamp', + Groups => { 2 => 'Time' }, + Writable => 'rational64u', + Count => 3, + Shift => 'Time', + Notes => q{ + UTC time of GPS fix. When writing, date is stripped off if present, and + time is adjusted to UTC if it includes a timezone + }, + ValueConv => 'Image::ExifTool::GPS::ConvertTimeStamp($val)', + ValueConvInv => '$val=~tr/:/ /;$val', + PrintConv => 'Image::ExifTool::GPS::PrintTimeStamp($val)', + # pull time out of any format date/time string + # (converting to UTC if a timezone is given) + PrintConvInv => sub { + my ($v, $et) = @_; + $v = $et->TimeNow() if lc($v) eq 'now'; + my @tz; + if ($v =~ s/([-+])(.*)//s) { # remove timezone + my $s = $1 eq '-' ? 1 : -1; # opposite sign to convert back to UTC + my $t = $2; + @tz = ($s*$1, $s*$2) if $t =~ /^(\d{2}):?(\d{2})\s*$/; + } + my @a = ($v =~ /((?=\d|\.\d)\d*(?:\.\d*)?)/g); + push @a, '00' while @a < 3; + if (@tz) { + # adjust to UTC + $a[-2] += $tz[1]; + $a[-3] += $tz[0]; + while ($a[-2] >= 60) { $a[-2] -= 60; ++$a[-3] } + while ($a[-2] < 0) { $a[-2] += 60; --$a[-3] } + $a[-3] = ($a[-3] + 24) % 24; + } + return "$a[-3]:$a[-2]:$a[-1]"; + }, + }, + 0x0008 => { + Name => 'GPSSatellites', + Writable => 'string', + }, + 0x0009 => { + Name => 'GPSStatus', + Writable => 'string', + Count => 2, + PrintConv => { + A => 'Measurement Active', # Exif2.2 "Measurement in progress" + V => 'Measurement Void', # Exif2.2 "Measurement Interoperability" (WTF?) + # (meaning for 'V' taken from status code in NMEA GLL and RMC sentences) + }, + }, + 0x000a => { + Name => 'GPSMeasureMode', + Writable => 'string', + Count => 2, + PrintConv => { + 2 => '2-Dimensional Measurement', + 3 => '3-Dimensional Measurement', + }, + }, + 0x000b => { + Name => 'GPSDOP', + Description => 'GPS Dilution Of Precision', + Writable => 'rational64u', + }, + 0x000c => { + Name => 'GPSSpeedRef', + Writable => 'string', + Count => 2, + PrintConv => { + K => 'km/h', + M => 'mph', + N => 'knots', + }, + }, + 0x000d => { + Name => 'GPSSpeed', + Writable => 'rational64u', + }, + 0x000e => { + Name => 'GPSTrackRef', + Writable => 'string', + Count => 2, + PrintConv => { + M => 'Magnetic North', + T => 'True North', + }, + }, + 0x000f => { + Name => 'GPSTrack', + Writable => 'rational64u', + }, + 0x0010 => { + Name => 'GPSImgDirectionRef', + Writable => 'string', + Count => 2, + PrintConv => { + M => 'Magnetic North', + T => 'True North', + }, + }, + 0x0011 => { + Name => 'GPSImgDirection', + Writable => 'rational64u', + }, + 0x0012 => { + Name => 'GPSMapDatum', + Writable => 'string', + }, + 0x0013 => { + Name => 'GPSDestLatitudeRef', + Writable => 'string', + Notes => 'tags 0x0013-0x001a used for subject location according to MWG 2.0', + Count => 2, + PrintConv => { N => 'North', S => 'South' }, + }, + 0x0014 => { + Name => 'GPSDestLatitude', + Writable => 'rational64u', + Count => 3, + %coordConv, + }, + 0x0015 => { + Name => 'GPSDestLongitudeRef', + Writable => 'string', + Count => 2, + PrintConv => { E => 'East', W => 'West' }, + }, + 0x0016 => { + Name => 'GPSDestLongitude', + Writable => 'rational64u', + Count => 3, + %coordConv, + }, + 0x0017 => { + Name => 'GPSDestBearingRef', + Writable => 'string', + Count => 2, + PrintConv => { + M => 'Magnetic North', + T => 'True North', + }, + }, + 0x0018 => { + Name => 'GPSDestBearing', + Writable => 'rational64u', + }, + 0x0019 => { + Name => 'GPSDestDistanceRef', + Writable => 'string', + Count => 2, + PrintConv => { + K => 'Kilometers', + M => 'Miles', + N => 'Nautical Miles', + }, + }, + 0x001a => { + Name => 'GPSDestDistance', + Writable => 'rational64u', + }, + 0x001b => { + Name => 'GPSProcessingMethod', + Writable => 'undef', + Notes => 'values of "GPS", "CELLID", "WLAN" or "MANUAL" by the EXIF spec.', + RawConv => 'Image::ExifTool::Exif::ConvertExifText($self,$val,1,$tag)', + RawConvInv => 'Image::ExifTool::Exif::EncodeExifText($self,$val)', + }, + 0x001c => { + Name => 'GPSAreaInformation', + Writable => 'undef', + RawConv => 'Image::ExifTool::Exif::ConvertExifText($self,$val,1,$tag)', + RawConvInv => 'Image::ExifTool::Exif::EncodeExifText($self,$val)', + }, + 0x001d => { + Name => 'GPSDateStamp', + Groups => { 2 => 'Time' }, + Writable => 'string', + Format => 'undef', # (Casio EX-H20G uses "\0" instead of ":" as a separator) + Count => 11, + Shift => 'Time', + Notes => q{ + when writing, time is stripped off if present, after adjusting date/time to + UTC if time includes a timezone. Format is YYYY:mm:dd + }, + RawConv => '$val =~ s/\0+$//; $val', + ValueConv => 'Image::ExifTool::Exif::ExifDate($val)', + ValueConvInv => '$val', + # pull date out of any format date/time string + # (and adjust to UTC if this is a full date/time/timezone value) + PrintConvInv => q{ + my $secs; + $val = $self->TimeNow() if lc($val) eq 'now'; + if ($val =~ /[-+]/ and ($secs = Image::ExifTool::GetUnixTime($val, 1))) { + $val = Image::ExifTool::ConvertUnixTime($secs); + } + return $val =~ /(\d{4}).*?(\d{2}).*?(\d{2})/ ? "$1:$2:$3" : undef; + }, + }, + 0x001e => { + Name => 'GPSDifferential', + Writable => 'int16u', + PrintConv => { + 0 => 'No Correction', + 1 => 'Differential Corrected', + }, + }, + 0x001f => { + Name => 'GPSHPositioningError', + Description => 'GPS Horizontal Positioning Error', + PrintConv => '"$val m"', + PrintConvInv => '$val=~s/\s*m$//; $val', + Writable => 'rational64u', + }, + # 0xea1c - Nokia Lumina 1020, Samsung GT-I8750, and other Windows 8 + # phones write this (padding) in GPS IFD - PH +); + +# Composite GPS tags +%Image::ExifTool::GPS::Composite = ( + GROUPS => { 2 => 'Location' }, + GPSDateTime => { + Description => 'GPS Date/Time', + Groups => { 2 => 'Time' }, + SubDoc => 1, # generate for all sub-documents + Require => { + 0 => 'GPS:GPSDateStamp', + 1 => 'GPS:GPSTimeStamp', + }, + ValueConv => '"$val[0] $val[1]Z"', + PrintConv => '$self->ConvertDateTime($val)', + }, + # Note: The following tags are used by other modules + # which must therefore require this module as necessary + GPSLatitude => { + SubDoc => 1, # generate for all sub-documents + Require => { + 0 => 'GPS:GPSLatitude', + 1 => 'GPS:GPSLatitudeRef', + }, + ValueConv => '$val[1] =~ /^S/i ? -$val[0] : $val[0]', + PrintConv => 'Image::ExifTool::GPS::ToDMS($self, $val, 1, "N")', + }, + GPSLongitude => { + SubDoc => 1, # generate for all sub-documents + Require => { + 0 => 'GPS:GPSLongitude', + 1 => 'GPS:GPSLongitudeRef', + }, + ValueConv => '$val[1] =~ /^W/i ? -$val[0] : $val[0]', + PrintConv => 'Image::ExifTool::GPS::ToDMS($self, $val, 1, "E")', + }, + GPSAltitude => { + SubDoc => [1,3], # generate for sub-documents if Desire 1 or 3 has a chance to exist + Desire => { + 0 => 'GPS:GPSAltitude', + 1 => 'GPS:GPSAltitudeRef', + 2 => 'XMP:GPSAltitude', + 3 => 'XMP:GPSAltitudeRef', + }, + # Require either GPS:GPSAltitudeRef or XMP:GPSAltitudeRef + RawConv => '(defined $val[1] or defined $val[3]) ? $val : undef', + ValueConv => q{ + my $alt = $val[0]; + $alt = $val[2] unless defined $alt; + return undef unless defined $alt and IsFloat($alt); + return ($val[1] || $val[3]) ? -$alt : $alt; + }, + PrintConv => q{ + $val = int($val * 10) / 10; + return ($val =~ s/^-// ? "$val m Below" : "$val m Above") . " Sea Level"; + }, + }, + GPSDestLatitude => { + Require => { + 0 => 'GPS:GPSDestLatitude', + 1 => 'GPS:GPSDestLatitudeRef', + }, + ValueConv => '$val[1] =~ /^S/i ? -$val[0] : $val[0]', + PrintConv => 'Image::ExifTool::GPS::ToDMS($self, $val, 1, "N")', + }, + GPSDestLongitude => { + SubDoc => 1, # generate for all sub-documents + Require => { + 0 => 'GPS:GPSDestLongitude', + 1 => 'GPS:GPSDestLongitudeRef', + }, + ValueConv => '$val[1] =~ /^W/i ? -$val[0] : $val[0]', + PrintConv => 'Image::ExifTool::GPS::ToDMS($self, $val, 1, "E")', + }, +); + +# add our composite tags +Image::ExifTool::AddCompositeTags('Image::ExifTool::GPS'); + +#------------------------------------------------------------------------------ +# Convert GPS timestamp value +# Inputs: 0) raw timestamp value string +# Returns: EXIF-formatted time string +sub ConvertTimeStamp($) +{ + my $val = shift; + my ($h,$m,$s) = split ' ', $val; + my $f = (($h || 0) * 60 + ($m || 0)) * 60 + ($s || 0); + $h = int($f / 3600); $f -= $h * 3600; + $m = int($f / 60); $f -= $m * 60; + my $ss = sprintf('%012.9f', $f); + if ($ss >= 60) { + $ss = '00'; + ++$m >= 60 and $m -= 60, ++$h; + } else { + $ss =~ s/\.?0+$//; # trim trailing zeros + decimal + } + return sprintf("%.2d:%.2d:%s",$h,$m,$ss); +} + +#------------------------------------------------------------------------------ +# Print GPS timestamp +# Inputs: 0) EXIF-formatted time string +# Returns: time rounded to the nearest microsecond +sub PrintTimeStamp($) +{ + my $val = shift; + return $val unless $val =~ s/:(\d{2}\.\d+)$//; + my $s = int($1 * 1000000 + 0.5) / 1000000; + $s = "0$s" if $s < 10; + return "${val}:$s"; +} + +#------------------------------------------------------------------------------ +# Convert degrees to DMS, or whatever the current settings are +# Inputs: 0) ExifTool reference, 1) Value in degrees, +# 2) format code (0=no format, 1=CoordFormat, 2=XMP format) +# 3) 'N' or 'E' if sign is significant and N/S/E/W should be added +# Returns: DMS string +sub ToDMS($$;$$) +{ + my ($et, $val, $doPrintConv, $ref) = @_; + my ($fmt, @fmt, $num, $sign, $rtnVal); + + unless (length $val) { + # don't convert an empty value + return $val if $doPrintConv and $doPrintConv eq 1; # avoid hiding existing tag when extracting + return undef; # avoid writing empty value + } + if ($ref) { + if ($val < 0) { + $val = -$val; + $ref = {N => 'S', E => 'W'}->{$ref}; + $sign = '-'; + } else { + $sign = '+'; + } + $ref = " $ref" unless $doPrintConv and $doPrintConv eq '2'; + } else { + $val = abs($val); + $ref = ''; + } + if ($doPrintConv) { + if ($doPrintConv eq '1') { + $fmt = $et->Options('CoordFormat'); + if (not $fmt) { + $fmt = q{%d deg %d' %.2f"} . $ref; + } elsif ($ref) { + # use signed value instead of reference direction if specified + $fmt =~ s/%\+/$sign%/g or $fmt .= $ref; + } else { + $fmt =~ s/%\+/%/g; # don't know sign, so don't print it + } + } else { + $fmt = "%d,%.8f$ref"; # use XMP format with 8 decimal minutes + } + # count (and capture) the format specifiers (max 3) + while ($fmt =~ /(%(%|[^%]*?[diouxXDOUeEfFgGcs]))/g) { + next if $1 eq '%%'; + push @fmt, $1; + last if @fmt >= 3; + } + $num = scalar @fmt; + } else { + $num = 3; + } + my @c; # coordinates (D) or (D,M) or (D,M,S) + $c[0] = $val; + if ($num > 1) { + $c[0] = int($c[0]); + $c[1] = ($val - $c[0]) * 60; + if ($num > 2) { + $c[1] = int($c[1]); + $c[2] = ($val - $c[0] - $c[1] / 60) * 3600; + } + # handle round-off errors to ensure minutes and seconds are + # less than 60 (eg. convert "72 59 60.00" to "73 0 0.00") + $c[-1] = $doPrintConv ? sprintf($fmt[-1], $c[-1]) : ($c[-1] . ''); + if ($c[-1] >= 60) { + $c[-1] -= 60; + ($c[-2] += 1) >= 60 and $num > 2 and $c[-2] -= 60, $c[-3] += 1; + } + } + if ($doPrintConv) { + $rtnVal = sprintf($fmt, @c); + # trim trailing zeros in XMP + $rtnVal =~ s/(\d)0+$ref$/$1$ref/ if $doPrintConv eq '2'; + } else { + $rtnVal = "@c$ref"; + } + return $rtnVal; +} + +#------------------------------------------------------------------------------ +# Convert to decimal degrees +# Inputs: 0) a string containing 1-3 decimal numbers and any amount of other garbage +# 1) true if value should be negative if coordinate ends in 'S' or 'W' +# Returns: Coordinate in degrees +sub ToDegrees($;$) +{ + my ($val, $doSign) = @_; + # extract decimal or floating point values out of any other garbage + my ($d, $m, $s) = ($val =~ /((?:[+-]?)(?=\d|\.\d)\d*(?:\.\d*)?(?:[Ee][+-]\d+)?)/g); + return '' unless defined $d; + my $deg = $d + (($m || 0) + ($s || 0)/60) / 60; + # make negative if S or W coordinate + $deg = -$deg if $doSign ? $val =~ /[^A-Z](S|W)$/i : $deg < 0; + return $deg; +} + + +1; #end + +__END__ + +=head1 NAME + +Image::ExifTool::GPS - EXIF GPS meta information tags + +=head1 SYNOPSIS + +This module is loaded automatically by Image::ExifTool when required. + +=head1 DESCRIPTION + +This module contains definitions required by Image::ExifTool to interpret +GPS (Global Positioning System) meta information in EXIF data. + +=head1 AUTHOR + +Copyright 2003-2019, Phil Harvey (phil at owl.phy.queensu.ca) + +This library is free software; you can redistribute it and/or modify it +under the same terms as Perl itself. + +=head1 REFERENCES + +=over 4 + +=item L<Image::Info|Image::Info> + +=back + +=head1 SEE ALSO + +L<Image::ExifTool::TagNames/GPS Tags>, +L<Image::ExifTool(3pm)|Image::ExifTool>, +L<Image::Info(3pm)|Image::Info> + +=cut diff --git a/lib/Image/ExifTool/GeoTiff.pm b/lib/Image/ExifTool/GeoTiff.pm new file mode 100644 index 0000000..840682d --- /dev/null +++ b/lib/Image/ExifTool/GeoTiff.pm @@ -0,0 +1,2263 @@ +#------------------------------------------------------------------------------ +# File: GeoTiff.pm +# +# Description: Read GeoTiff meta information +# +# Revisions: 02/23/2004 - P. Harvey Created +# 02/25/2004 - PH Added new codes from libgeotiff-1.2.1 +# 02/01/2007 - PH Added new codes from libgeotiff-1.2.3 +# 01/22/2014 - PH Added new code from libgeotiff-1.4.0 +# 01/19/2015 - PH Added ChartTIFF tags +# +# References: 1) ftp://ftp.remotesensing.org/geotiff/libgeotiff/libgeotiff-1.1.4.tar.gz +# 2) http://www.charttiff.com/whitepapers.shtml +#------------------------------------------------------------------------------ + +package Image::ExifTool::GeoTiff; + +use strict; +use vars qw($VERSION); +use Image::ExifTool qw(:DataAccess :Utils); + +$VERSION = '1.12'; + +# format codes for geoTiff directory entries +my %geoTiffFormat = ( + 0 => 'int16u', # (value is stored in offset, and count is 1) + 0x87af => 'int16u', # (value is stored after directory) + 0x87b0 => 'double', + 0x87b1 => 'string', +); + +my %epsg_units = ( + 9001 => 'Linear Meter', + 9002 => 'Linear Foot', + 9003 => 'Linear Foot US Survey', + 9004 => 'Linear Foot Modified American', + 9005 => 'Linear Foot Clarke', + 9006 => 'Linear Foot Indian', + 9007 => 'Linear Link', + 9008 => 'Linear Link Benoit', + 9009 => 'Linear Link Sears', + 9010 => 'Linear Chain Benoit', + 9011 => 'Linear Chain Sears', + 9012 => 'Linear Yard Sears', + 9013 => 'Linear Yard Indian', + 9014 => 'Linear Fathom', + 9015 => 'Linear Mile International Nautical', + 9101 => 'Angular Radian', + 9102 => 'Angular Degree', + 9103 => 'Angular Arc Minute', + 9104 => 'Angular Arc Second', + 9105 => 'Angular Grad', + 9106 => 'Angular Gon', + 9107 => 'Angular DMS', + 9108 => 'Angular DMS Hemisphere', + 32767 => 'User Defined', +); + +my %epsg_vertcs = ( + 0 => 'Undefined', + 5001 => 'Airy 1830 ellipsoid', + 5002 => 'Airy Modified 1849 ellipsoid', + 5003 => 'ANS ellipsoid', + 5004 => 'Bessel 1841 ellipsoid', + 5005 => 'Bessel Modified ellipsoid', + 5006 => 'Bessel Namibia ellipsoid', + 5007 => 'Clarke 1858 ellipsoid', + 5008 => 'Clarke 1866 ellipsoid', + 5010 => 'Clarke 1880 Benoit ellipsoid', + 5011 => 'Clarke 1880 IGN ellipsoid', + 5012 => 'Clarke 1880 RGS ellipsoid', + 5013 => 'Clarke 1880 Arc ellipsoid', + 5014 => 'Clarke 1880 SGA 1922 ellipsoid', + 5015 => 'Everest 1830 1937 Adjustment ellipsoid', + 5016 => 'Everest 1830 1967 Definition ellipsoid', + 5017 => 'Everest 1830 1975 Definition ellipsoid', + 5018 => 'Everest 1830 Modified ellipsoid', + 5019 => 'GRS 1980 ellipsoid', + 5020 => 'Helmert 1906 ellipsoid', + 5021 => 'INS ellipsoid', + 5022 => 'International 1924 ellipsoid', + 5023 => 'International 1967 ellipsoid', + 5024 => 'Krassowsky 1940 ellipsoid', + 5025 => 'NWL 9D ellipsoid', + 5026 => 'NWL 10D ellipsoid', + 5027 => 'Plessis 1817 ellipsoid', + 5028 => 'Struve 1860 ellipsoid', + 5029 => 'War Office ellipsoid', + 5030 => 'WGS 84 ellipsoid', + 5031 => 'GEM 10C ellipsoid', + 5032 => 'OSU86F ellipsoid', + 5033 => 'OSU91A ellipsoid', + 5101 => 'Newlyn', + 5102 => 'North American Vertical Datum 1929', + 5103 => 'North American Vertical Datum 1988', + 5104 => 'Yellow Sea 1956', + 5105 => 'Baltic Sea', + 5106 => 'Caspian Sea', + 32767 => 'User Defined', +); + +%Image::ExifTool::GeoTiff::Main = ( + GROUPS => { 2 => 'Location' }, + 1 => { + # this isn't a real GeoTiff key, but put it here + # so it will appear in tag lists since we generate it below + Name => 'GeoTiffVersion', + }, + 1024 => { + Name => 'GTModelType', + PrintConv => { + 1 => 'Projected', + 2 => 'Geographic', + 3 => 'Geocentric', + 32767 => 'User Defined', + }, + }, + 1025 => { + Name => 'GTRasterType', + PrintConv => { + 1 => 'Pixel Is Area', + 2 => 'Pixel Is Point', + 32767 => 'User Defined', + }, + }, + 1026 => 'GTCitation', + 2048 => { + Name => 'GeographicType', + PrintConv => { + # epsg_gcs + 4001 => 'Airy 1830', + 4002 => 'Airy Modified 1849', + 4003 => 'Australian National Spheroid', + 4004 => 'Bessel 1841', + 4005 => 'Bessel Modified', + 4006 => 'Bessel Namibia', + 4007 => 'Clarke 1858', + 4008 => 'Clarke 1866', + 4009 => 'Clarke 1866 Michigan', + 4010 => 'Clarke 1880 Benoit', + 4011 => 'Clarke 1880 IGN', + 4012 => 'Clarke 1880 RGS', + 4013 => 'Clarke 1880 Arc', + 4014 => 'Clarke 1880 SGA 1922', + 4015 => 'Everest 1830 1937 Adjustment', + 4016 => 'Everest 1830 1967 Definition', + 4017 => 'Everest 1830 1975 Definition', + 4018 => 'Everest 1830 Modified', + 4019 => 'GRS 1980', + 4020 => 'Helmert 1906', + 4021 => 'Indonesian National Spheroid', + 4022 => 'International 1924', + 4023 => 'International 1967', + 4024 => 'Krassowsky 1940', + 4025 => 'NWL9D', + 4026 => 'NWL10D', + 4027 => 'Plessis 1817', + 4028 => 'Struve 1860', + 4029 => 'War Office', + 4030 => 'WGS84', + 4031 => 'GEM10C', + 4032 => 'OSU86F', + 4033 => 'OSU91A', + 4034 => 'Clarke 1880', + 4035 => 'Sphere', + 4120 => 'Greek', + 4121 => 'GGRS87', + 4123 => 'KKJ', + 4124 => 'RT90', + 4133 => 'EST92', + 4815 => 'Greek Athens', + 4201 => 'Adindan', + 4202 => 'AGD66', + 4203 => 'AGD84', + 4204 => 'Ain el Abd', + 4205 => 'Afgooye', + 4206 => 'Agadez', + 4207 => 'Lisbon', + 4208 => 'Aratu', + 4209 => 'Arc 1950', + 4210 => 'Arc 1960', + 4211 => 'Batavia', + 4212 => 'Barbados', + 4213 => 'Beduaram', + 4214 => 'Beijing 1954', + 4215 => 'Belge 1950', + 4216 => 'Bermuda 1957', + 4217 => 'Bern 1898', + 4218 => 'Bogota', + 4219 => 'Bukit Rimpah', + 4220 => 'Camacupa', + 4221 => 'Campo Inchauspe', + 4222 => 'Cape', + 4223 => 'Carthage', + 4224 => 'Chua', + 4225 => 'Corrego Alegre', + 4226 => 'Cote d Ivoire', + 4227 => 'Deir ez Zor', + 4228 => 'Douala', + 4229 => 'Egypt 1907', + 4230 => 'ED50', + 4231 => 'ED87', + 4232 => 'Fahud', + 4233 => 'Gandajika 1970', + 4234 => 'Garoua', + 4235 => 'Guyane Francaise', + 4236 => 'Hu Tzu Shan', + 4237 => 'HD72', + 4238 => 'ID74', + 4239 => 'Indian 1954', + 4240 => 'Indian 1975', + 4241 => 'Jamaica 1875', + 4242 => 'JAD69', + 4243 => 'Kalianpur', + 4244 => 'Kandawala', + 4245 => 'Kertau', + 4246 => 'KOC', + 4247 => 'La Canoa', + 4248 => 'PSAD56', + 4249 => 'Lake', + 4250 => 'Leigon', + 4251 => 'Liberia 1964', + 4252 => 'Lome', + 4253 => 'Luzon 1911', + 4254 => 'Hito XVIII 1963', + 4255 => 'Herat North', + 4256 => 'Mahe 1971', + 4257 => 'Makassar', + 4258 => 'EUREF89', + 4259 => 'Malongo 1987', + 4260 => 'Manoca', + 4261 => 'Merchich', + 4262 => 'Massawa', + 4263 => 'Minna', + 4264 => 'Mhast', + 4265 => 'Monte Mario', + 4266 => 'M poraloko', + 4267 => 'NAD27', + 4268 => 'NAD Michigan', + 4269 => 'NAD83', + 4270 => 'Nahrwan 1967', + 4271 => 'Naparima 1972', + 4272 => 'GD49', + 4273 => 'NGO 1948', + 4274 => '73', + 4275 => 'NTF', + 4276 => 'NSWC 9Z 2', + 4277 => 'OSGB 1936', + 4278 => 'OSGB70', + 4279 => 'OS SN80', + 4280 => 'Padang', + 4281 => 'Palestine 1923', + 4282 => 'Pointe Noire', + 4283 => 'GDA94', + 4284 => 'Pulkovo 1942', + 4285 => 'Qatar', + 4286 => 'Qatar 1948', + 4287 => 'Qornoq', + 4288 => 'Loma Quintana', + 4289 => 'Amersfoort', + 4290 => 'RT38', + 4291 => 'SAD69', + 4292 => 'Sapper Hill 1943', + 4293 => 'Schwarzeck', + 4294 => 'Segora', + 4295 => 'Serindung', + 4296 => 'Sudan', + 4297 => 'Tananarive', + 4298 => 'Timbalai 1948', + 4299 => 'TM65', + 4300 => 'TM75', + 4301 => 'Tokyo', + 4302 => 'Trinidad 1903', + 4303 => 'TC 1948', + 4304 => 'Voirol 1875', + 4305 => 'Voirol Unifie', + 4306 => 'Bern 1938', + 4307 => 'Nord Sahara 1959', + 4308 => 'Stockholm 1938', + 4309 => 'Yacare', + 4310 => 'Yoff', + 4311 => 'Zanderij', + 4312 => 'MGI', + 4313 => 'Belge 1972', + 4314 => 'DHDN', + 4315 => 'Conakry 1905', + 4317 => 'Dealul Piscului 1970', + 4322 => 'WGS 72', + 4324 => 'WGS 72BE', + 4326 => 'WGS 84', + 4801 => 'Bern 1898 Bern', + 4802 => 'Bogota Bogota', + 4803 => 'Lisbon Lisbon', + 4804 => 'Makassar Jakarta', + 4805 => 'MGI Ferro', + 4806 => 'Monte Mario Rome', + 4807 => 'NTF Paris', + 4808 => 'Padang Jakarta', + 4809 => 'Belge 1950 Brussels', + 4810 => 'Tananarive Paris', + 4811 => 'Voirol 1875 Paris', + 4812 => 'Voirol Unifie Paris', + 4813 => 'Batavia Jakarta', + 4901 => 'ATF Paris', + 4902 => 'NDG Paris', + 32767 => 'User Defined', + }, + }, + 2049 => 'GeogCitation', + 2050 => { + Name => 'GeogGeodeticDatum', + PrintConv => { + # epsg_datum, + 6001 => 'Airy 1830', + 6002 => 'Airy Modified 1849', + 6003 => 'Australian National Spheroid', + 6004 => 'Bessel 1841', + 6005 => 'Bessel Modified', + 6006 => 'Bessel Namibia', + 6007 => 'Clarke 1858', + 6008 => 'Clarke 1866', + 6009 => 'Clarke 1866 Michigan', + 6010 => 'Clarke 1880 Benoit', + 6011 => 'Clarke 1880 IGN', + 6012 => 'Clarke 1880 RGS', + 6013 => 'Clarke 1880 Arc', + 6014 => 'Clarke 1880 SGA 1922', + 6015 => 'Everest 1830 1937 Adjustment', + 6016 => 'Everest 1830 1967 Definition', + 6017 => 'Everest 1830 1975 Definition', + 6018 => 'Everest 1830 Modified', + 6019 => 'GRS 1980', + 6020 => 'Helmert 1906', + 6021 => 'Indonesian National Spheroid', + 6022 => 'International 1924', + 6023 => 'International 1967', + 6024 => 'Krassowsky 1960', + 6025 => 'NWL9D', + 6026 => 'NWL10D', + 6027 => 'Plessis 1817', + 6028 => 'Struve 1860', + 6029 => 'War Office', + 6030 => 'WGS84', + 6031 => 'GEM10C', + 6032 => 'OSU86F', + 6033 => 'OSU91A', + 6034 => 'Clarke 1880', + 6035 => 'Sphere', + 6201 => 'Adindan', + 6202 => 'Australian Geodetic Datum 1966', + 6203 => 'Australian Geodetic Datum 1984', + 6204 => 'Ain el Abd 1970', + 6205 => 'Afgooye', + 6206 => 'Agadez', + 6207 => 'Lisbon', + 6208 => 'Aratu', + 6209 => 'Arc 1950', + 6210 => 'Arc 1960', + 6211 => 'Batavia', + 6212 => 'Barbados', + 6213 => 'Beduaram', + 6214 => 'Beijing 1954', + 6215 => 'Reseau National Belge 1950', + 6216 => 'Bermuda 1957', + 6217 => 'Bern 1898', + 6218 => 'Bogota', + 6219 => 'Bukit Rimpah', + 6220 => 'Camacupa', + 6221 => 'Campo Inchauspe', + 6222 => 'Cape', + 6223 => 'Carthage', + 6224 => 'Chua', + 6225 => 'Corrego Alegre', + 6226 => 'Cote d Ivoire', + 6227 => 'Deir ez Zor', + 6228 => 'Douala', + 6229 => 'Egypt 1907', + 6230 => 'European Datum 1950', + 6231 => 'European Datum 1987', + 6232 => 'Fahud', + 6233 => 'Gandajika 1970', + 6234 => 'Garoua', + 6235 => 'Guyane Francaise', + 6236 => 'Hu Tzu Shan', + 6237 => 'Hungarian Datum 1972', + 6238 => 'Indonesian Datum 1974', + 6239 => 'Indian 1954', + 6240 => 'Indian 1975', + 6241 => 'Jamaica 1875', + 6242 => 'Jamaica 1969', + 6243 => 'Kalianpur', + 6244 => 'Kandawala', + 6245 => 'Kertau', + 6246 => 'Kuwait Oil Company', + 6247 => 'La Canoa', + 6248 => 'Provisional S American Datum 1956', + 6249 => 'Lake', + 6250 => 'Leigon', + 6251 => 'Liberia 1964', + 6252 => 'Lome', + 6253 => 'Luzon 1911', + 6254 => 'Hito XVIII 1963', + 6255 => 'Herat North', + 6256 => 'Mahe 1971', + 6257 => 'Makassar', + 6258 => 'European Reference System 1989', + 6259 => 'Malongo 1987', + 6260 => 'Manoca', + 6261 => 'Merchich', + 6262 => 'Massawa', + 6263 => 'Minna', + 6264 => 'Mhast', + 6265 => 'Monte Mario', + 6266 => 'M poraloko', + 6267 => 'North American Datum 1927', + 6268 => 'NAD Michigan', + 6269 => 'North American Datum 1983', + 6270 => 'Nahrwan 1967', + 6271 => 'Naparima 1972', + 6272 => 'New Zealand Geodetic Datum 1949', + 6273 => 'NGO 1948', + 6274 => 'Datum 73', + 6275 => 'Nouvelle Triangulation Francaise', + 6276 => 'NSWC 9Z 2', + 6277 => 'OSGB 1936', + 6278 => 'OSGB 1970 SN', + 6279 => 'OS SN 1980', + 6280 => 'Padang 1884', + 6281 => 'Palestine 1923', + 6282 => 'Pointe Noire', + 6283 => 'Geocentric Datum of Australia 1994', + 6284 => 'Pulkovo 1942', + 6285 => 'Qatar', + 6286 => 'Qatar 1948', + 6287 => 'Qornoq', + 6288 => 'Loma Quintana', + 6289 => 'Amersfoort', + 6290 => 'RT38', + 6291 => 'South American Datum 1969', + 6292 => 'Sapper Hill 1943', + 6293 => 'Schwarzeck', + 6294 => 'Segora', + 6295 => 'Serindung', + 6296 => 'Sudan', + 6297 => 'Tananarive 1925', + 6298 => 'Timbalai 1948', + 6299 => 'TM65', + 6300 => 'TM75', + 6301 => 'Tokyo', + 6302 => 'Trinidad 1903', + 6303 => 'Trucial Coast 1948', + 6304 => 'Voirol 1875', + 6305 => 'Voirol Unifie 1960', + 6306 => 'Bern 1938', + 6307 => 'Nord Sahara 1959', + 6308 => 'Stockholm 1938', + 6309 => 'Yacare', + 6310 => 'Yoff', + 6311 => 'Zanderij', + 6312 => 'Militar Geographische Institut', + 6313 => 'Reseau National Belge 1972', + 6314 => 'Deutsche Hauptdreiecksnetz', + 6315 => 'Conakry 1905', + 6317 => 'Dealul Piscului 1970', + 6322 => 'WGS72', + 6324 => 'WGS72 Transit Broadcast Ephemeris', + 6326 => 'WGS84', + 6901 => 'Ancienne Triangulation Francaise', + 6902 => 'Nord de Guerre', + 32767 => 'User Defined', + }, + }, + 2051 => { + Name => 'GeogPrimeMeridian', + PrintConv => { + # epsg_pm + 8901 => 'Greenwich', + 8902 => 'Lisbon', + 8903 => 'Paris', + 8904 => 'Bogota', + 8905 => 'Madrid', + 8906 => 'Rome', + 8907 => 'Bern', + 8908 => 'Jakarta', + 8909 => 'Ferro', + 8910 => 'Brussels', + 8911 => 'Stockholm', + 32767 => 'User Defined', + }, + }, + 2052 => { + Name => 'GeogLinearUnits', + SeparateTable => 'Units', + PrintConv => \%epsg_units, + }, + 2053 => 'GeogLinearUnitSize', + 2054 => { + Name => 'GeogAngularUnits', + SeparateTable => 'Units', + PrintConv => \%epsg_units, + }, + 2055 => 'GeogAngularUnitSize', + 2056 => { + Name => 'GeogEllipsoid', + PrintConv => { + # epsg_ellipse + 7001 => 'Airy 1830', + 7002 => 'Airy Modified 1849', + 7003 => 'Australian National Spheroid', + 7004 => 'Bessel 1841', + 7005 => 'Bessel Modified', + 7006 => 'Bessel Namibia', + 7007 => 'Clarke 1858', + 7008 => 'Clarke 1866', + 7009 => 'Clarke 1866 Michigan', + 7010 => 'Clarke 1880 Benoit', + 7011 => 'Clarke 1880 IGN', + 7012 => 'Clarke 1880 RGS', + 7013 => 'Clarke 1880 Arc', + 7014 => 'Clarke 1880 SGA 1922', + 7015 => 'Everest 1830 1937 Adjustment', + 7016 => 'Everest 1830 1967 Definition', + 7017 => 'Everest 1830 1975 Definition', + 7018 => 'Everest 1830 Modified', + 7019 => 'GRS 1980', + 7020 => 'Helmert 1906', + 7021 => 'Indonesian National Spheroid', + 7022 => 'International 1924', + 7023 => 'International 1967', + 7024 => 'Krassowsky 1940', + 7025 => 'NWL 9D', + 7026 => 'NWL 10D', + 7027 => 'Plessis 1817', + 7028 => 'Struve 1860', + 7029 => 'War Office', + 7030 => 'WGS 84', + 7031 => 'GEM 10C', + 7032 => 'OSU86F', + 7033 => 'OSU91A', + 7034 => 'Clarke 1880', + 7035 => 'Sphere', + 32767 => 'User Defined', + }, + }, + 2057 => 'GeogSemiMajorAxis', + 2058 => 'GeogSemiMinorAxis', + 2059 => 'GeogInvFlattening', + 2060 => { + Name => 'GeogAzimuthUnits', + SeparateTable => 'Units', + PrintConv => \%epsg_units, + }, + 2061 => 'GeogPrimeMeridianLong', + 2062 => 'GeogToWGS84', + 3072 => { + Name => 'ProjectedCSType', + PrintConv => { + # epsg_pcs + 2100 => 'GGRS87 Greek Grid', + 2176 => 'ETRS89 Poland CS2000 zone 5', + 2177 => 'ETRS89 Poland CS2000 zone 6', + 2177 => 'ETRS89 Poland CS2000 zone 7', + 2178 => 'ETRS89 Poland CS2000 zone 8', + 2180 => 'ETRS89 Poland CS92', + 2204 => 'NAD27 Tennessee', + 2205 => 'NAD83 Kentucky North', + 2391 => 'KKJ Finland zone 1', + 2392 => 'KKJ Finland zone 2', + 2393 => 'KKJ Finland zone 3', + 2394 => 'KKJ Finland zone 4', + 2400 => 'RT90 2 5 gon W', + 2600 => 'Lietuvos Koordinoei Sistema 1994', + 3053 => 'Hjorsey 1955 Lambert', + 3057 => 'ISN93 Lambert 1993', + 3300 => 'Estonian Coordinate System of 1992', + 20137 => 'Adindan UTM zone 37N', + 20138 => 'Adindan UTM zone 38N', + 20248 => 'AGD66 AMG zone 48', + 20249 => 'AGD66 AMG zone 49', + 20250 => 'AGD66 AMG zone 50', + 20251 => 'AGD66 AMG zone 51', + 20252 => 'AGD66 AMG zone 52', + 20253 => 'AGD66 AMG zone 53', + 20254 => 'AGD66 AMG zone 54', + 20255 => 'AGD66 AMG zone 55', + 20256 => 'AGD66 AMG zone 56', + 20257 => 'AGD66 AMG zone 57', + 20258 => 'AGD66 AMG zone 58', + 20348 => 'AGD84 AMG zone 48', + 20349 => 'AGD84 AMG zone 49', + 20350 => 'AGD84 AMG zone 50', + 20351 => 'AGD84 AMG zone 51', + 20352 => 'AGD84 AMG zone 52', + 20353 => 'AGD84 AMG zone 53', + 20354 => 'AGD84 AMG zone 54', + 20355 => 'AGD84 AMG zone 55', + 20356 => 'AGD84 AMG zone 56', + 20357 => 'AGD84 AMG zone 57', + 20358 => 'AGD84 AMG zone 58', + 20437 => 'Ain el Abd UTM zone 37N', + 20438 => 'Ain el Abd UTM zone 38N', + 20439 => 'Ain el Abd UTM zone 39N', + 20499 => 'Ain el Abd Bahrain Grid', + 20538 => 'Afgooye UTM zone 38N', + 20539 => 'Afgooye UTM zone 39N', + 20700 => 'Lisbon Portugese Grid', + 20822 => 'Aratu UTM zone 22S', + 20823 => 'Aratu UTM zone 23S', + 20824 => 'Aratu UTM zone 24S', + 20973 => 'Arc 1950 Lo13', + 20975 => 'Arc 1950 Lo15', + 20977 => 'Arc 1950 Lo17', + 20979 => 'Arc 1950 Lo19', + 20981 => 'Arc 1950 Lo21', + 20983 => 'Arc 1950 Lo23', + 20985 => 'Arc 1950 Lo25', + 20987 => 'Arc 1950 Lo27', + 20989 => 'Arc 1950 Lo29', + 20991 => 'Arc 1950 Lo31', + 20993 => 'Arc 1950 Lo33', + 20995 => 'Arc 1950 Lo35', + 21100 => 'Batavia NEIEZ', + 21148 => 'Batavia UTM zone 48S', + 21149 => 'Batavia UTM zone 49S', + 21150 => 'Batavia UTM zone 50S', + 21413 => 'Beijing Gauss zone 13', + 21414 => 'Beijing Gauss zone 14', + 21415 => 'Beijing Gauss zone 15', + 21416 => 'Beijing Gauss zone 16', + 21417 => 'Beijing Gauss zone 17', + 21418 => 'Beijing Gauss zone 18', + 21419 => 'Beijing Gauss zone 19', + 21420 => 'Beijing Gauss zone 20', + 21421 => 'Beijing Gauss zone 21', + 21422 => 'Beijing Gauss zone 22', + 21423 => 'Beijing Gauss zone 23', + 21473 => 'Beijing Gauss 13N', + 21474 => 'Beijing Gauss 14N', + 21475 => 'Beijing Gauss 15N', + 21476 => 'Beijing Gauss 16N', + 21477 => 'Beijing Gauss 17N', + 21478 => 'Beijing Gauss 18N', + 21479 => 'Beijing Gauss 19N', + 21480 => 'Beijing Gauss 20N', + 21481 => 'Beijing Gauss 21N', + 21482 => 'Beijing Gauss 22N', + 21483 => 'Beijing Gauss 23N', + 21500 => 'Belge Lambert 50', + 21790 => 'Bern 1898 Swiss Old', + 21817 => 'Bogota UTM zone 17N', + 21818 => 'Bogota UTM zone 18N', + 21891 => 'Bogota Colombia 3W', + 21892 => 'Bogota Colombia Bogota', + 21893 => 'Bogota Colombia 3E', + 21894 => 'Bogota Colombia 6E', + 22032 => 'Camacupa UTM 32S', + 22033 => 'Camacupa UTM 33S', + 22191 => 'C Inchauspe Argentina 1', + 22192 => 'C Inchauspe Argentina 2', + 22193 => 'C Inchauspe Argentina 3', + 22194 => 'C Inchauspe Argentina 4', + 22195 => 'C Inchauspe Argentina 5', + 22196 => 'C Inchauspe Argentina 6', + 22197 => 'C Inchauspe Argentina 7', + 22332 => 'Carthage UTM zone 32N', + 22391 => 'Carthage Nord Tunisie', + 22392 => 'Carthage Sud Tunisie', + 22523 => 'Corrego Alegre UTM 23S', + 22524 => 'Corrego Alegre UTM 24S', + 22832 => 'Douala UTM zone 32N', + 22992 => 'Egypt 1907 Red Belt', + 22993 => 'Egypt 1907 Purple Belt', + 22994 => 'Egypt 1907 Ext Purple', + 23028 => 'ED50 UTM zone 28N', + 23029 => 'ED50 UTM zone 29N', + 23030 => 'ED50 UTM zone 30N', + 23031 => 'ED50 UTM zone 31N', + 23032 => 'ED50 UTM zone 32N', + 23033 => 'ED50 UTM zone 33N', + 23034 => 'ED50 UTM zone 34N', + 23035 => 'ED50 UTM zone 35N', + 23036 => 'ED50 UTM zone 36N', + 23037 => 'ED50 UTM zone 37N', + 23038 => 'ED50 UTM zone 38N', + 23239 => 'Fahud UTM zone 39N', + 23240 => 'Fahud UTM zone 40N', + 23433 => 'Garoua UTM zone 33N', + 23700 => 'HD72 EOV', + 23846 => 'ID74 UTM zone 46N', + 23847 => 'ID74 UTM zone 47N', + 23848 => 'ID74 UTM zone 48N', + 23849 => 'ID74 UTM zone 49N', + 23850 => 'ID74 UTM zone 50N', + 23851 => 'ID74 UTM zone 51N', + 23852 => 'ID74 UTM zone 52N', + 23853 => 'ID74 UTM zone 53N', + 23886 => 'ID74 UTM zone 46S', + 23887 => 'ID74 UTM zone 47S', + 23888 => 'ID74 UTM zone 48S', + 23889 => 'ID74 UTM zone 49S', + 23890 => 'ID74 UTM zone 50S', + 23891 => 'ID74 UTM zone 51S', + 23892 => 'ID74 UTM zone 52S', + 23893 => 'ID74 UTM zone 53S', + 23894 => 'ID74 UTM zone 54S', + 23947 => 'Indian 1954 UTM 47N', + 23948 => 'Indian 1954 UTM 48N', + 24047 => 'Indian 1975 UTM 47N', + 24048 => 'Indian 1975 UTM 48N', + 24100 => 'Jamaica 1875 Old Grid', + 24200 => 'JAD69 Jamaica Grid', + 24370 => 'Kalianpur India 0', + 24371 => 'Kalianpur India I', + 24372 => 'Kalianpur India IIa', + 24373 => 'Kalianpur India IIIa', + 24374 => 'Kalianpur India IVa', + 24382 => 'Kalianpur India IIb', + 24383 => 'Kalianpur India IIIb', + 24384 => 'Kalianpur India IVb', + 24500 => 'Kertau Singapore Grid', + 24547 => 'Kertau UTM zone 47N', + 24548 => 'Kertau UTM zone 48N', + 24720 => 'La Canoa UTM zone 20N', + 24721 => 'La Canoa UTM zone 21N', + 24818 => 'PSAD56 UTM zone 18N', + 24819 => 'PSAD56 UTM zone 19N', + 24820 => 'PSAD56 UTM zone 20N', + 24821 => 'PSAD56 UTM zone 21N', + 24877 => 'PSAD56 UTM zone 17S', + 24878 => 'PSAD56 UTM zone 18S', + 24879 => 'PSAD56 UTM zone 19S', + 24880 => 'PSAD56 UTM zone 20S', + 24891 => 'PSAD56 Peru west zone', + 24892 => 'PSAD56 Peru central', + 24893 => 'PSAD56 Peru east zone', + 25000 => 'Leigon Ghana Grid', + 25231 => 'Lome UTM zone 31N', + 25391 => 'Luzon Philippines I', + 25392 => 'Luzon Philippines II', + 25393 => 'Luzon Philippines III', + 25394 => 'Luzon Philippines IV', + 25395 => 'Luzon Philippines V', + 25700 => 'Makassar NEIEZ', + 25932 => 'Malongo 1987 UTM 32S', + 26191 => 'Merchich Nord Maroc', + 26192 => 'Merchich Sud Maroc', + 26193 => 'Merchich Sahara', + 26237 => 'Massawa UTM zone 37N', + 26331 => 'Minna UTM zone 31N', + 26332 => 'Minna UTM zone 32N', + 26391 => 'Minna Nigeria West', + 26392 => 'Minna Nigeria Mid Belt', + 26393 => 'Minna Nigeria East', + 26432 => 'Mhast UTM zone 32S', + 26591 => 'Monte Mario Italy 1', + 26592 => 'Monte Mario Italy 2', + 26632 => 'M poraloko UTM 32N', + 26692 => 'M poraloko UTM 32S', + 26703 => 'NAD27 UTM zone 3N', + 26704 => 'NAD27 UTM zone 4N', + 26705 => 'NAD27 UTM zone 5N', + 26706 => 'NAD27 UTM zone 6N', + 26707 => 'NAD27 UTM zone 7N', + 26708 => 'NAD27 UTM zone 8N', + 26709 => 'NAD27 UTM zone 9N', + 26710 => 'NAD27 UTM zone 10N', + 26711 => 'NAD27 UTM zone 11N', + 26712 => 'NAD27 UTM zone 12N', + 26713 => 'NAD27 UTM zone 13N', + 26714 => 'NAD27 UTM zone 14N', + 26715 => 'NAD27 UTM zone 15N', + 26716 => 'NAD27 UTM zone 16N', + 26717 => 'NAD27 UTM zone 17N', + 26718 => 'NAD27 UTM zone 18N', + 26719 => 'NAD27 UTM zone 19N', + 26720 => 'NAD27 UTM zone 20N', + 26721 => 'NAD27 UTM zone 21N', + 26722 => 'NAD27 UTM zone 22N', + 26729 => 'NAD27 Alabama East', + 26730 => 'NAD27 Alabama West', + 26731 => 'NAD27 Alaska zone 1', + 26732 => 'NAD27 Alaska zone 2', + 26733 => 'NAD27 Alaska zone 3', + 26734 => 'NAD27 Alaska zone 4', + 26735 => 'NAD27 Alaska zone 5', + 26736 => 'NAD27 Alaska zone 6', + 26737 => 'NAD27 Alaska zone 7', + 26738 => 'NAD27 Alaska zone 8', + 26739 => 'NAD27 Alaska zone 9', + 26740 => 'NAD27 Alaska zone 10', + 26741 => 'NAD27 California I', + 26742 => 'NAD27 California II', + 26743 => 'NAD27 California III', + 26744 => 'NAD27 California IV', + 26745 => 'NAD27 California V', + 26746 => 'NAD27 California VI', + 26747 => 'NAD27 California VII', + 26748 => 'NAD27 Arizona East', + 26749 => 'NAD27 Arizona Central', + 26750 => 'NAD27 Arizona West', + 26751 => 'NAD27 Arkansas North', + 26752 => 'NAD27 Arkansas South', + 26753 => 'NAD27 Colorado North', + 26754 => 'NAD27 Colorado Central', + 26755 => 'NAD27 Colorado South', + 26756 => 'NAD27 Connecticut', + 26757 => 'NAD27 Delaware', + 26758 => 'NAD27 Florida East', + 26759 => 'NAD27 Florida West', + 26760 => 'NAD27 Florida North', + 26761 => 'NAD27 Hawaii zone 1', + 26762 => 'NAD27 Hawaii zone 2', + 26763 => 'NAD27 Hawaii zone 3', + 26764 => 'NAD27 Hawaii zone 4', + 26765 => 'NAD27 Hawaii zone 5', + 26766 => 'NAD27 Georgia East', + 26767 => 'NAD27 Georgia West', + 26768 => 'NAD27 Idaho East', + 26769 => 'NAD27 Idaho Central', + 26770 => 'NAD27 Idaho West', + 26771 => 'NAD27 Illinois East', + 26772 => 'NAD27 Illinois West', + 26773 => 'NAD27 Indiana East', + 26774 => 'NAD27 BLM 14N feet', + 26774 => 'NAD27 Indiana West', + 26775 => 'NAD27 BLM 15N feet', + 26775 => 'NAD27 Iowa North', + 26776 => 'NAD27 BLM 16N feet', + 26776 => 'NAD27 Iowa South', + 26777 => 'NAD27 BLM 17N feet', + 26777 => 'NAD27 Kansas North', + 26778 => 'NAD27 Kansas South', + 26779 => 'NAD27 Kentucky North', + 26780 => 'NAD27 Kentucky South', + 26781 => 'NAD27 Louisiana North', + 26782 => 'NAD27 Louisiana South', + 26783 => 'NAD27 Maine East', + 26784 => 'NAD27 Maine West', + 26785 => 'NAD27 Maryland', + 26786 => 'NAD27 Massachusetts', + 26787 => 'NAD27 Massachusetts Is', + 26788 => 'NAD27 Michigan North', + 26789 => 'NAD27 Michigan Central', + 26790 => 'NAD27 Michigan South', + 26791 => 'NAD27 Minnesota North', + 26792 => 'NAD27 Minnesota Cent', + 26793 => 'NAD27 Minnesota South', + 26794 => 'NAD27 Mississippi East', + 26795 => 'NAD27 Mississippi West', + 26796 => 'NAD27 Missouri East', + 26797 => 'NAD27 Missouri Central', + 26798 => 'NAD27 Missouri West', + 26801 => 'NAD Michigan Michigan East', + 26802 => 'NAD Michigan Michigan Old Central', + 26803 => 'NAD Michigan Michigan West', + 26903 => 'NAD83 UTM zone 3N', + 26904 => 'NAD83 UTM zone 4N', + 26905 => 'NAD83 UTM zone 5N', + 26906 => 'NAD83 UTM zone 6N', + 26907 => 'NAD83 UTM zone 7N', + 26908 => 'NAD83 UTM zone 8N', + 26909 => 'NAD83 UTM zone 9N', + 26910 => 'NAD83 UTM zone 10N', + 26911 => 'NAD83 UTM zone 11N', + 26912 => 'NAD83 UTM zone 12N', + 26913 => 'NAD83 UTM zone 13N', + 26914 => 'NAD83 UTM zone 14N', + 26915 => 'NAD83 UTM zone 15N', + 26916 => 'NAD83 UTM zone 16N', + 26917 => 'NAD83 UTM zone 17N', + 26918 => 'NAD83 UTM zone 18N', + 26919 => 'NAD83 UTM zone 19N', + 26920 => 'NAD83 UTM zone 20N', + 26921 => 'NAD83 UTM zone 21N', + 26922 => 'NAD83 UTM zone 22N', + 26923 => 'NAD83 UTM zone 23N', + 26929 => 'NAD83 Alabama East', + 26930 => 'NAD83 Alabama West', + 26931 => 'NAD83 Alaska zone 1', + 26932 => 'NAD83 Alaska zone 2', + 26933 => 'NAD83 Alaska zone 3', + 26934 => 'NAD83 Alaska zone 4', + 26935 => 'NAD83 Alaska zone 5', + 26936 => 'NAD83 Alaska zone 6', + 26937 => 'NAD83 Alaska zone 7', + 26938 => 'NAD83 Alaska zone 8', + 26939 => 'NAD83 Alaska zone 9', + 26940 => 'NAD83 Alaska zone 10', + 26941 => 'NAD83 California 1', + 26942 => 'NAD83 California 2', + 26943 => 'NAD83 California 3', + 26944 => 'NAD83 California 4', + 26945 => 'NAD83 California 5', + 26946 => 'NAD83 California 6', + 26948 => 'NAD83 Arizona East', + 26949 => 'NAD83 Arizona Central', + 26950 => 'NAD83 Arizona West', + 26951 => 'NAD83 Arkansas North', + 26952 => 'NAD83 Arkansas South', + 26953 => 'NAD83 Colorado North', + 26954 => 'NAD83 Colorado Central', + 26955 => 'NAD83 Colorado South', + 26956 => 'NAD83 Connecticut', + 26957 => 'NAD83 Delaware', + 26958 => 'NAD83 Florida East', + 26959 => 'NAD83 Florida West', + 26960 => 'NAD83 Florida North', + 26961 => 'NAD83 Hawaii zone 1', + 26962 => 'NAD83 Hawaii zone 2', + 26963 => 'NAD83 Hawaii zone 3', + 26964 => 'NAD83 Hawaii zone 4', + 26965 => 'NAD83 Hawaii zone 5', + 26966 => 'NAD83 Georgia East', + 26967 => 'NAD83 Georgia West', + 26968 => 'NAD83 Idaho East', + 26969 => 'NAD83 Idaho Central', + 26970 => 'NAD83 Idaho West', + 26971 => 'NAD83 Illinois East', + 26972 => 'NAD83 Illinois West', + 26973 => 'NAD83 Indiana East', + 26974 => 'NAD83 Indiana West', + 26975 => 'NAD83 Iowa North', + 26976 => 'NAD83 Iowa South', + 26977 => 'NAD83 Kansas North', + 26978 => 'NAD83 Kansas South', + 26979 => 'NAD83 Kentucky North', + 26980 => 'NAD83 Kentucky South', + 26981 => 'NAD83 Louisiana North', + 26982 => 'NAD83 Louisiana South', + 26983 => 'NAD83 Maine East', + 26984 => 'NAD83 Maine West', + 26985 => 'NAD83 Maryland', + 26986 => 'NAD83 Massachusetts', + 26987 => 'NAD83 Massachusetts Is', + 26988 => 'NAD83 Michigan North', + 26989 => 'NAD83 Michigan Central', + 26990 => 'NAD83 Michigan South', + 26991 => 'NAD83 Minnesota North', + 26992 => 'NAD83 Minnesota Cent', + 26993 => 'NAD83 Minnesota South', + 26994 => 'NAD83 Mississippi East', + 26995 => 'NAD83 Mississippi West', + 26996 => 'NAD83 Missouri East', + 26997 => 'NAD83 Missouri Central', + 26998 => 'NAD83 Missouri West', + 27038 => 'Nahrwan 1967 UTM 38N', + 27039 => 'Nahrwan 1967 UTM 39N', + 27040 => 'Nahrwan 1967 UTM 40N', + 27120 => 'Naparima UTM 20N', + 27200 => 'GD49 NZ Map Grid', + 27291 => 'GD49 North Island Grid', + 27292 => 'GD49 South Island Grid', + 27429 => 'Datum 73 UTM zone 29N', + 27500 => 'ATF Nord de Guerre', + 27581 => 'NTF France I', + 27582 => 'NTF France II', + 27583 => 'NTF France III', + 27591 => 'NTF Nord France', + 27592 => 'NTF Centre France', + 27593 => 'NTF Sud France', + 27700 => 'British National Grid', + 28232 => 'Point Noire UTM 32S', + 28348 => 'GDA94 MGA zone 48', + 28349 => 'GDA94 MGA zone 49', + 28350 => 'GDA94 MGA zone 50', + 28351 => 'GDA94 MGA zone 51', + 28352 => 'GDA94 MGA zone 52', + 28353 => 'GDA94 MGA zone 53', + 28354 => 'GDA94 MGA zone 54', + 28355 => 'GDA94 MGA zone 55', + 28356 => 'GDA94 MGA zone 56', + 28357 => 'GDA94 MGA zone 57', + 28358 => 'GDA94 MGA zone 58', + 28404 => 'Pulkovo Gauss zone 4', + 28405 => 'Pulkovo Gauss zone 5', + 28406 => 'Pulkovo Gauss zone 6', + 28407 => 'Pulkovo Gauss zone 7', + 28408 => 'Pulkovo Gauss zone 8', + 28409 => 'Pulkovo Gauss zone 9', + 28410 => 'Pulkovo Gauss zone 10', + 28411 => 'Pulkovo Gauss zone 11', + 28412 => 'Pulkovo Gauss zone 12', + 28413 => 'Pulkovo Gauss zone 13', + 28414 => 'Pulkovo Gauss zone 14', + 28415 => 'Pulkovo Gauss zone 15', + 28416 => 'Pulkovo Gauss zone 16', + 28417 => 'Pulkovo Gauss zone 17', + 28418 => 'Pulkovo Gauss zone 18', + 28419 => 'Pulkovo Gauss zone 19', + 28420 => 'Pulkovo Gauss zone 20', + 28421 => 'Pulkovo Gauss zone 21', + 28422 => 'Pulkovo Gauss zone 22', + 28423 => 'Pulkovo Gauss zone 23', + 28424 => 'Pulkovo Gauss zone 24', + 28425 => 'Pulkovo Gauss zone 25', + 28426 => 'Pulkovo Gauss zone 26', + 28427 => 'Pulkovo Gauss zone 27', + 28428 => 'Pulkovo Gauss zone 28', + 28429 => 'Pulkovo Gauss zone 29', + 28430 => 'Pulkovo Gauss zone 30', + 28431 => 'Pulkovo Gauss zone 31', + 28432 => 'Pulkovo Gauss zone 32', + 28464 => 'Pulkovo Gauss 4N', + 28465 => 'Pulkovo Gauss 5N', + 28466 => 'Pulkovo Gauss 6N', + 28467 => 'Pulkovo Gauss 7N', + 28468 => 'Pulkovo Gauss 8N', + 28469 => 'Pulkovo Gauss 9N', + 28470 => 'Pulkovo Gauss 10N', + 28471 => 'Pulkovo Gauss 11N', + 28472 => 'Pulkovo Gauss 12N', + 28473 => 'Pulkovo Gauss 13N', + 28474 => 'Pulkovo Gauss 14N', + 28475 => 'Pulkovo Gauss 15N', + 28476 => 'Pulkovo Gauss 16N', + 28477 => 'Pulkovo Gauss 17N', + 28478 => 'Pulkovo Gauss 18N', + 28479 => 'Pulkovo Gauss 19N', + 28480 => 'Pulkovo Gauss 20N', + 28481 => 'Pulkovo Gauss 21N', + 28482 => 'Pulkovo Gauss 22N', + 28483 => 'Pulkovo Gauss 23N', + 28484 => 'Pulkovo Gauss 24N', + 28485 => 'Pulkovo Gauss 25N', + 28486 => 'Pulkovo Gauss 26N', + 28487 => 'Pulkovo Gauss 27N', + 28488 => 'Pulkovo Gauss 28N', + 28489 => 'Pulkovo Gauss 29N', + 28490 => 'Pulkovo Gauss 30N', + 28491 => 'Pulkovo Gauss 31N', + 28492 => 'Pulkovo Gauss 32N', + 28600 => 'Qatar National Grid', + 28991 => 'RD Netherlands Old', + 28992 => 'RD Netherlands New', + 29118 => 'SAD69 UTM zone 18N', + 29119 => 'SAD69 UTM zone 19N', + 29120 => 'SAD69 UTM zone 20N', + 29121 => 'SAD69 UTM zone 21N', + 29122 => 'SAD69 UTM zone 22N', + 29177 => 'SAD69 UTM zone 17S', + 29178 => 'SAD69 UTM zone 18S', + 29179 => 'SAD69 UTM zone 19S', + 29180 => 'SAD69 UTM zone 20S', + 29181 => 'SAD69 UTM zone 21S', + 29182 => 'SAD69 UTM zone 22S', + 29183 => 'SAD69 UTM zone 23S', + 29184 => 'SAD69 UTM zone 24S', + 29185 => 'SAD69 UTM zone 25S', + 29220 => 'Sapper Hill UTM 20S', + 29221 => 'Sapper Hill UTM 21S', + 29333 => 'Schwarzeck UTM 33S', + 29635 => 'Sudan UTM zone 35N', + 29636 => 'Sudan UTM zone 36N', + 29700 => 'Tananarive Laborde', + 29738 => 'Tananarive UTM 38S', + 29739 => 'Tananarive UTM 39S', + 29800 => 'Timbalai 1948 Borneo', + 29849 => 'Timbalai 1948 UTM 49N', + 29850 => 'Timbalai 1948 UTM 50N', + 29900 => 'TM65 Irish Nat Grid', + 30200 => 'Trinidad 1903 Trinidad', + 30339 => 'TC 1948 UTM zone 39N', + 30340 => 'TC 1948 UTM zone 40N', + 30491 => 'Voirol N Algerie ancien', + 30492 => 'Voirol S Algerie ancien', + 30591 => 'Voirol Unifie N Algerie', + 30592 => 'Voirol Unifie S Algerie', + 30600 => 'Bern 1938 Swiss New', + 30729 => 'Nord Sahara UTM 29N', + 30730 => 'Nord Sahara UTM 30N', + 30731 => 'Nord Sahara UTM 31N', + 30732 => 'Nord Sahara UTM 32N', + 31028 => 'Yoff UTM zone 28N', + 31121 => 'Zanderij UTM zone 21N', + 31291 => 'MGI Austria West', + 31292 => 'MGI Austria Central', + 31293 => 'MGI Austria East', + 31300 => 'Belge Lambert 72', + 31491 => 'DHDN Germany zone 1', + 31492 => 'DHDN Germany zone 2', + 31493 => 'DHDN Germany zone 3', + 31494 => 'DHDN Germany zone 4', + 31495 => 'DHDN Germany zone 5', + 31700 => 'Dealul Piscului 1970 Stereo 70', + 32001 => 'NAD27 Montana North', + 32002 => 'NAD27 Montana Central', + 32003 => 'NAD27 Montana South', + 32005 => 'NAD27 Nebraska North', + 32006 => 'NAD27 Nebraska South', + 32007 => 'NAD27 Nevada East', + 32008 => 'NAD27 Nevada Central', + 32009 => 'NAD27 Nevada West', + 32010 => 'NAD27 New Hampshire', + 32011 => 'NAD27 New Jersey', + 32012 => 'NAD27 New Mexico East', + 32013 => 'NAD27 New Mexico Cent', + 32014 => 'NAD27 New Mexico West', + 32015 => 'NAD27 New York East', + 32016 => 'NAD27 New York Central', + 32017 => 'NAD27 New York West', + 32018 => 'NAD27 New York Long Is', + 32019 => 'NAD27 North Carolina', + 32020 => 'NAD27 North Dakota N', + 32021 => 'NAD27 North Dakota S', + 32022 => 'NAD27 Ohio North', + 32023 => 'NAD27 Ohio South', + 32024 => 'NAD27 Oklahoma North', + 32025 => 'NAD27 Oklahoma South', + 32026 => 'NAD27 Oregon North', + 32027 => 'NAD27 Oregon South', + 32028 => 'NAD27 Pennsylvania N', + 32029 => 'NAD27 Pennsylvania S', + 32030 => 'NAD27 Rhode Island', + 32031 => 'NAD27 South Carolina N', + 32033 => 'NAD27 South Carolina S', + 32034 => 'NAD27 South Dakota N', + 32035 => 'NAD27 South Dakota S', + 32036 => 'NAD27 Tennessee', + 32037 => 'NAD27 Texas North', + 32038 => 'NAD27 Texas North Cen', + 32039 => 'NAD27 Texas Central', + 32040 => 'NAD27 Texas South Cen', + 32041 => 'NAD27 Texas South', + 32042 => 'NAD27 Utah North', + 32043 => 'NAD27 Utah Central', + 32044 => 'NAD27 Utah South', + 32045 => 'NAD27 Vermont', + 32046 => 'NAD27 Virginia North', + 32047 => 'NAD27 Virginia South', + 32048 => 'NAD27 Washington North', + 32049 => 'NAD27 Washington South', + 32050 => 'NAD27 West Virginia N', + 32051 => 'NAD27 West Virginia S', + 32052 => 'NAD27 Wisconsin North', + 32053 => 'NAD27 Wisconsin Cen', + 32054 => 'NAD27 Wisconsin South', + 32055 => 'NAD27 Wyoming East', + 32056 => 'NAD27 Wyoming E Cen', + 32057 => 'NAD27 Wyoming W Cen', + 32058 => 'NAD27 Wyoming West', + 32059 => 'NAD27 Puerto Rico', + 32060 => 'NAD27 St Croix', + 32100 => 'NAD83 Montana', + 32104 => 'NAD83 Nebraska', + 32107 => 'NAD83 Nevada East', + 32108 => 'NAD83 Nevada Central', + 32109 => 'NAD83 Nevada West', + 32110 => 'NAD83 New Hampshire', + 32111 => 'NAD83 New Jersey', + 32112 => 'NAD83 New Mexico East', + 32113 => 'NAD83 New Mexico Cent', + 32114 => 'NAD83 New Mexico West', + 32115 => 'NAD83 New York East', + 32116 => 'NAD83 New York Central', + 32117 => 'NAD83 New York West', + 32118 => 'NAD83 New York Long Is', + 32119 => 'NAD83 North Carolina', + 32120 => 'NAD83 North Dakota N', + 32121 => 'NAD83 North Dakota S', + 32122 => 'NAD83 Ohio North', + 32123 => 'NAD83 Ohio South', + 32124 => 'NAD83 Oklahoma North', + 32125 => 'NAD83 Oklahoma South', + 32126 => 'NAD83 Oregon North', + 32127 => 'NAD83 Oregon South', + 32128 => 'NAD83 Pennsylvania N', + 32129 => 'NAD83 Pennsylvania S', + 32130 => 'NAD83 Rhode Island', + 32133 => 'NAD83 South Carolina', + 32134 => 'NAD83 South Dakota N', + 32135 => 'NAD83 South Dakota S', + 32136 => 'NAD83 Tennessee', + 32137 => 'NAD83 Texas North', + 32138 => 'NAD83 Texas North Cen', + 32139 => 'NAD83 Texas Central', + 32140 => 'NAD83 Texas South Cen', + 32141 => 'NAD83 Texas South', + 32142 => 'NAD83 Utah North', + 32143 => 'NAD83 Utah Central', + 32144 => 'NAD83 Utah South', + 32145 => 'NAD83 Vermont', + 32146 => 'NAD83 Virginia North', + 32147 => 'NAD83 Virginia South', + 32148 => 'NAD83 Washington North', + 32149 => 'NAD83 Washington South', + 32150 => 'NAD83 West Virginia N', + 32151 => 'NAD83 West Virginia S', + 32152 => 'NAD83 Wisconsin North', + 32153 => 'NAD83 Wisconsin Cen', + 32154 => 'NAD83 Wisconsin South', + 32155 => 'NAD83 Wyoming East', + 32156 => 'NAD83 Wyoming E Cen', + 32157 => 'NAD83 Wyoming W Cen', + 32158 => 'NAD83 Wyoming West', + 32161 => 'NAD83 Puerto Rico Virgin Is', + 32201 => 'WGS72 UTM zone 1N', + 32202 => 'WGS72 UTM zone 2N', + 32203 => 'WGS72 UTM zone 3N', + 32204 => 'WGS72 UTM zone 4N', + 32205 => 'WGS72 UTM zone 5N', + 32206 => 'WGS72 UTM zone 6N', + 32207 => 'WGS72 UTM zone 7N', + 32208 => 'WGS72 UTM zone 8N', + 32209 => 'WGS72 UTM zone 9N', + 32210 => 'WGS72 UTM zone 10N', + 32211 => 'WGS72 UTM zone 11N', + 32212 => 'WGS72 UTM zone 12N', + 32213 => 'WGS72 UTM zone 13N', + 32214 => 'WGS72 UTM zone 14N', + 32215 => 'WGS72 UTM zone 15N', + 32216 => 'WGS72 UTM zone 16N', + 32217 => 'WGS72 UTM zone 17N', + 32218 => 'WGS72 UTM zone 18N', + 32219 => 'WGS72 UTM zone 19N', + 32220 => 'WGS72 UTM zone 20N', + 32221 => 'WGS72 UTM zone 21N', + 32222 => 'WGS72 UTM zone 22N', + 32223 => 'WGS72 UTM zone 23N', + 32224 => 'WGS72 UTM zone 24N', + 32225 => 'WGS72 UTM zone 25N', + 32226 => 'WGS72 UTM zone 26N', + 32227 => 'WGS72 UTM zone 27N', + 32228 => 'WGS72 UTM zone 28N', + 32229 => 'WGS72 UTM zone 29N', + 32230 => 'WGS72 UTM zone 30N', + 32231 => 'WGS72 UTM zone 31N', + 32232 => 'WGS72 UTM zone 32N', + 32233 => 'WGS72 UTM zone 33N', + 32234 => 'WGS72 UTM zone 34N', + 32235 => 'WGS72 UTM zone 35N', + 32236 => 'WGS72 UTM zone 36N', + 32237 => 'WGS72 UTM zone 37N', + 32238 => 'WGS72 UTM zone 38N', + 32239 => 'WGS72 UTM zone 39N', + 32240 => 'WGS72 UTM zone 40N', + 32241 => 'WGS72 UTM zone 41N', + 32242 => 'WGS72 UTM zone 42N', + 32243 => 'WGS72 UTM zone 43N', + 32244 => 'WGS72 UTM zone 44N', + 32245 => 'WGS72 UTM zone 45N', + 32246 => 'WGS72 UTM zone 46N', + 32247 => 'WGS72 UTM zone 47N', + 32248 => 'WGS72 UTM zone 48N', + 32249 => 'WGS72 UTM zone 49N', + 32250 => 'WGS72 UTM zone 50N', + 32251 => 'WGS72 UTM zone 51N', + 32252 => 'WGS72 UTM zone 52N', + 32253 => 'WGS72 UTM zone 53N', + 32254 => 'WGS72 UTM zone 54N', + 32255 => 'WGS72 UTM zone 55N', + 32256 => 'WGS72 UTM zone 56N', + 32257 => 'WGS72 UTM zone 57N', + 32258 => 'WGS72 UTM zone 58N', + 32259 => 'WGS72 UTM zone 59N', + 32260 => 'WGS72 UTM zone 60N', + 32301 => 'WGS72 UTM zone 1S', + 32302 => 'WGS72 UTM zone 2S', + 32303 => 'WGS72 UTM zone 3S', + 32304 => 'WGS72 UTM zone 4S', + 32305 => 'WGS72 UTM zone 5S', + 32306 => 'WGS72 UTM zone 6S', + 32307 => 'WGS72 UTM zone 7S', + 32308 => 'WGS72 UTM zone 8S', + 32309 => 'WGS72 UTM zone 9S', + 32310 => 'WGS72 UTM zone 10S', + 32311 => 'WGS72 UTM zone 11S', + 32312 => 'WGS72 UTM zone 12S', + 32313 => 'WGS72 UTM zone 13S', + 32314 => 'WGS72 UTM zone 14S', + 32315 => 'WGS72 UTM zone 15S', + 32316 => 'WGS72 UTM zone 16S', + 32317 => 'WGS72 UTM zone 17S', + 32318 => 'WGS72 UTM zone 18S', + 32319 => 'WGS72 UTM zone 19S', + 32320 => 'WGS72 UTM zone 20S', + 32321 => 'WGS72 UTM zone 21S', + 32322 => 'WGS72 UTM zone 22S', + 32323 => 'WGS72 UTM zone 23S', + 32324 => 'WGS72 UTM zone 24S', + 32325 => 'WGS72 UTM zone 25S', + 32326 => 'WGS72 UTM zone 26S', + 32327 => 'WGS72 UTM zone 27S', + 32328 => 'WGS72 UTM zone 28S', + 32329 => 'WGS72 UTM zone 29S', + 32330 => 'WGS72 UTM zone 30S', + 32331 => 'WGS72 UTM zone 31S', + 32332 => 'WGS72 UTM zone 32S', + 32333 => 'WGS72 UTM zone 33S', + 32334 => 'WGS72 UTM zone 34S', + 32335 => 'WGS72 UTM zone 35S', + 32336 => 'WGS72 UTM zone 36S', + 32337 => 'WGS72 UTM zone 37S', + 32338 => 'WGS72 UTM zone 38S', + 32339 => 'WGS72 UTM zone 39S', + 32340 => 'WGS72 UTM zone 40S', + 32341 => 'WGS72 UTM zone 41S', + 32342 => 'WGS72 UTM zone 42S', + 32343 => 'WGS72 UTM zone 43S', + 32344 => 'WGS72 UTM zone 44S', + 32345 => 'WGS72 UTM zone 45S', + 32346 => 'WGS72 UTM zone 46S', + 32347 => 'WGS72 UTM zone 47S', + 32348 => 'WGS72 UTM zone 48S', + 32349 => 'WGS72 UTM zone 49S', + 32350 => 'WGS72 UTM zone 50S', + 32351 => 'WGS72 UTM zone 51S', + 32352 => 'WGS72 UTM zone 52S', + 32353 => 'WGS72 UTM zone 53S', + 32354 => 'WGS72 UTM zone 54S', + 32355 => 'WGS72 UTM zone 55S', + 32356 => 'WGS72 UTM zone 56S', + 32357 => 'WGS72 UTM zone 57S', + 32358 => 'WGS72 UTM zone 58S', + 32359 => 'WGS72 UTM zone 59S', + 32360 => 'WGS72 UTM zone 60S', + 32401 => 'WGS72BE UTM zone 1N', + 32402 => 'WGS72BE UTM zone 2N', + 32403 => 'WGS72BE UTM zone 3N', + 32404 => 'WGS72BE UTM zone 4N', + 32405 => 'WGS72BE UTM zone 5N', + 32406 => 'WGS72BE UTM zone 6N', + 32407 => 'WGS72BE UTM zone 7N', + 32408 => 'WGS72BE UTM zone 8N', + 32409 => 'WGS72BE UTM zone 9N', + 32410 => 'WGS72BE UTM zone 10N', + 32411 => 'WGS72BE UTM zone 11N', + 32412 => 'WGS72BE UTM zone 12N', + 32413 => 'WGS72BE UTM zone 13N', + 32414 => 'WGS72BE UTM zone 14N', + 32415 => 'WGS72BE UTM zone 15N', + 32416 => 'WGS72BE UTM zone 16N', + 32417 => 'WGS72BE UTM zone 17N', + 32418 => 'WGS72BE UTM zone 18N', + 32419 => 'WGS72BE UTM zone 19N', + 32420 => 'WGS72BE UTM zone 20N', + 32421 => 'WGS72BE UTM zone 21N', + 32422 => 'WGS72BE UTM zone 22N', + 32423 => 'WGS72BE UTM zone 23N', + 32424 => 'WGS72BE UTM zone 24N', + 32425 => 'WGS72BE UTM zone 25N', + 32426 => 'WGS72BE UTM zone 26N', + 32427 => 'WGS72BE UTM zone 27N', + 32428 => 'WGS72BE UTM zone 28N', + 32429 => 'WGS72BE UTM zone 29N', + 32430 => 'WGS72BE UTM zone 30N', + 32431 => 'WGS72BE UTM zone 31N', + 32432 => 'WGS72BE UTM zone 32N', + 32433 => 'WGS72BE UTM zone 33N', + 32434 => 'WGS72BE UTM zone 34N', + 32435 => 'WGS72BE UTM zone 35N', + 32436 => 'WGS72BE UTM zone 36N', + 32437 => 'WGS72BE UTM zone 37N', + 32438 => 'WGS72BE UTM zone 38N', + 32439 => 'WGS72BE UTM zone 39N', + 32440 => 'WGS72BE UTM zone 40N', + 32441 => 'WGS72BE UTM zone 41N', + 32442 => 'WGS72BE UTM zone 42N', + 32443 => 'WGS72BE UTM zone 43N', + 32444 => 'WGS72BE UTM zone 44N', + 32445 => 'WGS72BE UTM zone 45N', + 32446 => 'WGS72BE UTM zone 46N', + 32447 => 'WGS72BE UTM zone 47N', + 32448 => 'WGS72BE UTM zone 48N', + 32449 => 'WGS72BE UTM zone 49N', + 32450 => 'WGS72BE UTM zone 50N', + 32451 => 'WGS72BE UTM zone 51N', + 32452 => 'WGS72BE UTM zone 52N', + 32453 => 'WGS72BE UTM zone 53N', + 32454 => 'WGS72BE UTM zone 54N', + 32455 => 'WGS72BE UTM zone 55N', + 32456 => 'WGS72BE UTM zone 56N', + 32457 => 'WGS72BE UTM zone 57N', + 32458 => 'WGS72BE UTM zone 58N', + 32459 => 'WGS72BE UTM zone 59N', + 32460 => 'WGS72BE UTM zone 60N', + 32501 => 'WGS72BE UTM zone 1S', + 32502 => 'WGS72BE UTM zone 2S', + 32503 => 'WGS72BE UTM zone 3S', + 32504 => 'WGS72BE UTM zone 4S', + 32505 => 'WGS72BE UTM zone 5S', + 32506 => 'WGS72BE UTM zone 6S', + 32507 => 'WGS72BE UTM zone 7S', + 32508 => 'WGS72BE UTM zone 8S', + 32509 => 'WGS72BE UTM zone 9S', + 32510 => 'WGS72BE UTM zone 10S', + 32511 => 'WGS72BE UTM zone 11S', + 32512 => 'WGS72BE UTM zone 12S', + 32513 => 'WGS72BE UTM zone 13S', + 32514 => 'WGS72BE UTM zone 14S', + 32515 => 'WGS72BE UTM zone 15S', + 32516 => 'WGS72BE UTM zone 16S', + 32517 => 'WGS72BE UTM zone 17S', + 32518 => 'WGS72BE UTM zone 18S', + 32519 => 'WGS72BE UTM zone 19S', + 32520 => 'WGS72BE UTM zone 20S', + 32521 => 'WGS72BE UTM zone 21S', + 32522 => 'WGS72BE UTM zone 22S', + 32523 => 'WGS72BE UTM zone 23S', + 32524 => 'WGS72BE UTM zone 24S', + 32525 => 'WGS72BE UTM zone 25S', + 32526 => 'WGS72BE UTM zone 26S', + 32527 => 'WGS72BE UTM zone 27S', + 32528 => 'WGS72BE UTM zone 28S', + 32529 => 'WGS72BE UTM zone 29S', + 32530 => 'WGS72BE UTM zone 30S', + 32531 => 'WGS72BE UTM zone 31S', + 32532 => 'WGS72BE UTM zone 32S', + 32533 => 'WGS72BE UTM zone 33S', + 32534 => 'WGS72BE UTM zone 34S', + 32535 => 'WGS72BE UTM zone 35S', + 32536 => 'WGS72BE UTM zone 36S', + 32537 => 'WGS72BE UTM zone 37S', + 32538 => 'WGS72BE UTM zone 38S', + 32539 => 'WGS72BE UTM zone 39S', + 32540 => 'WGS72BE UTM zone 40S', + 32541 => 'WGS72BE UTM zone 41S', + 32542 => 'WGS72BE UTM zone 42S', + 32543 => 'WGS72BE UTM zone 43S', + 32544 => 'WGS72BE UTM zone 44S', + 32545 => 'WGS72BE UTM zone 45S', + 32546 => 'WGS72BE UTM zone 46S', + 32547 => 'WGS72BE UTM zone 47S', + 32548 => 'WGS72BE UTM zone 48S', + 32549 => 'WGS72BE UTM zone 49S', + 32550 => 'WGS72BE UTM zone 50S', + 32551 => 'WGS72BE UTM zone 51S', + 32552 => 'WGS72BE UTM zone 52S', + 32553 => 'WGS72BE UTM zone 53S', + 32554 => 'WGS72BE UTM zone 54S', + 32555 => 'WGS72BE UTM zone 55S', + 32556 => 'WGS72BE UTM zone 56S', + 32557 => 'WGS72BE UTM zone 57S', + 32558 => 'WGS72BE UTM zone 58S', + 32559 => 'WGS72BE UTM zone 59S', + 32560 => 'WGS72BE UTM zone 60S', + 32601 => 'WGS84 UTM zone 1N', + 32602 => 'WGS84 UTM zone 2N', + 32603 => 'WGS84 UTM zone 3N', + 32604 => 'WGS84 UTM zone 4N', + 32605 => 'WGS84 UTM zone 5N', + 32606 => 'WGS84 UTM zone 6N', + 32607 => 'WGS84 UTM zone 7N', + 32608 => 'WGS84 UTM zone 8N', + 32609 => 'WGS84 UTM zone 9N', + 32610 => 'WGS84 UTM zone 10N', + 32611 => 'WGS84 UTM zone 11N', + 32612 => 'WGS84 UTM zone 12N', + 32613 => 'WGS84 UTM zone 13N', + 32614 => 'WGS84 UTM zone 14N', + 32615 => 'WGS84 UTM zone 15N', + 32616 => 'WGS84 UTM zone 16N', + 32617 => 'WGS84 UTM zone 17N', + 32618 => 'WGS84 UTM zone 18N', + 32619 => 'WGS84 UTM zone 19N', + 32620 => 'WGS84 UTM zone 20N', + 32621 => 'WGS84 UTM zone 21N', + 32622 => 'WGS84 UTM zone 22N', + 32623 => 'WGS84 UTM zone 23N', + 32624 => 'WGS84 UTM zone 24N', + 32625 => 'WGS84 UTM zone 25N', + 32626 => 'WGS84 UTM zone 26N', + 32627 => 'WGS84 UTM zone 27N', + 32628 => 'WGS84 UTM zone 28N', + 32629 => 'WGS84 UTM zone 29N', + 32630 => 'WGS84 UTM zone 30N', + 32631 => 'WGS84 UTM zone 31N', + 32632 => 'WGS84 UTM zone 32N', + 32633 => 'WGS84 UTM zone 33N', + 32634 => 'WGS84 UTM zone 34N', + 32635 => 'WGS84 UTM zone 35N', + 32636 => 'WGS84 UTM zone 36N', + 32637 => 'WGS84 UTM zone 37N', + 32638 => 'WGS84 UTM zone 38N', + 32639 => 'WGS84 UTM zone 39N', + 32640 => 'WGS84 UTM zone 40N', + 32641 => 'WGS84 UTM zone 41N', + 32642 => 'WGS84 UTM zone 42N', + 32643 => 'WGS84 UTM zone 43N', + 32644 => 'WGS84 UTM zone 44N', + 32645 => 'WGS84 UTM zone 45N', + 32646 => 'WGS84 UTM zone 46N', + 32647 => 'WGS84 UTM zone 47N', + 32648 => 'WGS84 UTM zone 48N', + 32649 => 'WGS84 UTM zone 49N', + 32650 => 'WGS84 UTM zone 50N', + 32651 => 'WGS84 UTM zone 51N', + 32652 => 'WGS84 UTM zone 52N', + 32653 => 'WGS84 UTM zone 53N', + 32654 => 'WGS84 UTM zone 54N', + 32655 => 'WGS84 UTM zone 55N', + 32656 => 'WGS84 UTM zone 56N', + 32657 => 'WGS84 UTM zone 57N', + 32658 => 'WGS84 UTM zone 58N', + 32659 => 'WGS84 UTM zone 59N', + 32660 => 'WGS84 UTM zone 60N', + 32701 => 'WGS84 UTM zone 1S', + 32702 => 'WGS84 UTM zone 2S', + 32703 => 'WGS84 UTM zone 3S', + 32704 => 'WGS84 UTM zone 4S', + 32705 => 'WGS84 UTM zone 5S', + 32706 => 'WGS84 UTM zone 6S', + 32707 => 'WGS84 UTM zone 7S', + 32708 => 'WGS84 UTM zone 8S', + 32709 => 'WGS84 UTM zone 9S', + 32710 => 'WGS84 UTM zone 10S', + 32711 => 'WGS84 UTM zone 11S', + 32712 => 'WGS84 UTM zone 12S', + 32713 => 'WGS84 UTM zone 13S', + 32714 => 'WGS84 UTM zone 14S', + 32715 => 'WGS84 UTM zone 15S', + 32716 => 'WGS84 UTM zone 16S', + 32717 => 'WGS84 UTM zone 17S', + 32718 => 'WGS84 UTM zone 18S', + 32719 => 'WGS84 UTM zone 19S', + 32720 => 'WGS84 UTM zone 20S', + 32721 => 'WGS84 UTM zone 21S', + 32722 => 'WGS84 UTM zone 22S', + 32723 => 'WGS84 UTM zone 23S', + 32724 => 'WGS84 UTM zone 24S', + 32725 => 'WGS84 UTM zone 25S', + 32726 => 'WGS84 UTM zone 26S', + 32727 => 'WGS84 UTM zone 27S', + 32728 => 'WGS84 UTM zone 28S', + 32729 => 'WGS84 UTM zone 29S', + 32730 => 'WGS84 UTM zone 30S', + 32731 => 'WGS84 UTM zone 31S', + 32732 => 'WGS84 UTM zone 32S', + 32733 => 'WGS84 UTM zone 33S', + 32734 => 'WGS84 UTM zone 34S', + 32735 => 'WGS84 UTM zone 35S', + 32736 => 'WGS84 UTM zone 36S', + 32737 => 'WGS84 UTM zone 37S', + 32738 => 'WGS84 UTM zone 38S', + 32739 => 'WGS84 UTM zone 39S', + 32740 => 'WGS84 UTM zone 40S', + 32741 => 'WGS84 UTM zone 41S', + 32742 => 'WGS84 UTM zone 42S', + 32743 => 'WGS84 UTM zone 43S', + 32744 => 'WGS84 UTM zone 44S', + 32745 => 'WGS84 UTM zone 45S', + 32746 => 'WGS84 UTM zone 46S', + 32747 => 'WGS84 UTM zone 47S', + 32748 => 'WGS84 UTM zone 48S', + 32749 => 'WGS84 UTM zone 49S', + 32750 => 'WGS84 UTM zone 50S', + 32751 => 'WGS84 UTM zone 51S', + 32752 => 'WGS84 UTM zone 52S', + 32753 => 'WGS84 UTM zone 53S', + 32754 => 'WGS84 UTM zone 54S', + 32755 => 'WGS84 UTM zone 55S', + 32756 => 'WGS84 UTM zone 56S', + 32757 => 'WGS84 UTM zone 57S', + 32758 => 'WGS84 UTM zone 58S', + 32759 => 'WGS84 UTM zone 59S', + 32760 => 'WGS84 UTM zone 60S', + 32767 => 'User Defined', + }, + }, + 3073 => 'PCSCitation', + 3074 => { + Name => 'Projection', + PrintConv => { + # epsg_proj + 10101 => 'Alabama CS27 East', + 10102 => 'Alabama CS27 West', + 10131 => 'Alabama CS83 East', + 10132 => 'Alabama CS83 West', + 10201 => 'Arizona Coordinate System east', + 10202 => 'Arizona Coordinate System Central', + 10203 => 'Arizona Coordinate System west', + 10231 => 'Arizona CS83 east', + 10232 => 'Arizona CS83 Central', + 10233 => 'Arizona CS83 west', + 10301 => 'Arkansas CS27 North', + 10302 => 'Arkansas CS27 South', + 10331 => 'Arkansas CS83 North', + 10332 => 'Arkansas CS83 South', + 10401 => 'California CS27 I', + 10402 => 'California CS27 II', + 10403 => 'California CS27 III', + 10404 => 'California CS27 IV', + 10405 => 'California CS27 V', + 10406 => 'California CS27 VI', + 10407 => 'California CS27 VII', + 10431 => 'California CS83 1', + 10432 => 'California CS83 2', + 10433 => 'California CS83 3', + 10434 => 'California CS83 4', + 10435 => 'California CS83 5', + 10436 => 'California CS83 6', + 10501 => 'Colorado CS27 North', + 10502 => 'Colorado CS27 Central', + 10503 => 'Colorado CS27 South', + 10531 => 'Colorado CS83 North', + 10532 => 'Colorado CS83 Central', + 10533 => 'Colorado CS83 South', + 10600 => 'Connecticut CS27', + 10630 => 'Connecticut CS83', + 10700 => 'Delaware CS27', + 10730 => 'Delaware CS83', + 10901 => 'Florida CS27 East', + 10902 => 'Florida CS27 West', + 10903 => 'Florida CS27 North', + 10931 => 'Florida CS83 East', + 10932 => 'Florida CS83 West', + 10933 => 'Florida CS83 North', + 11001 => 'Georgia CS27 East', + 11002 => 'Georgia CS27 West', + 11031 => 'Georgia CS83 East', + 11032 => 'Georgia CS83 West', + 11101 => 'Idaho CS27 East', + 11102 => 'Idaho CS27 Central', + 11103 => 'Idaho CS27 West', + 11131 => 'Idaho CS83 East', + 11132 => 'Idaho CS83 Central', + 11133 => 'Idaho CS83 West', + 11201 => 'Illinois CS27 East', + 11202 => 'Illinois CS27 West', + 11231 => 'Illinois CS83 East', + 11232 => 'Illinois CS83 West', + 11301 => 'Indiana CS27 East', + 11302 => 'Indiana CS27 West', + 11331 => 'Indiana CS83 East', + 11332 => 'Indiana CS83 West', + 11401 => 'Iowa CS27 North', + 11402 => 'Iowa CS27 South', + 11431 => 'Iowa CS83 North', + 11432 => 'Iowa CS83 South', + 11501 => 'Kansas CS27 North', + 11502 => 'Kansas CS27 South', + 11531 => 'Kansas CS83 North', + 11532 => 'Kansas CS83 South', + 11601 => 'Kentucky CS27 North', + 11602 => 'Kentucky CS27 South', + 11631 => 'Kentucky CS83 North', + 11632 => 'Kentucky CS83 South', + 11701 => 'Louisiana CS27 North', + 11702 => 'Louisiana CS27 South', + 11731 => 'Louisiana CS83 North', + 11732 => 'Louisiana CS83 South', + 11801 => 'Maine CS27 East', + 11802 => 'Maine CS27 West', + 11831 => 'Maine CS83 East', + 11832 => 'Maine CS83 West', + 11900 => 'Maryland CS27', + 11930 => 'Maryland CS83', + 12001 => 'Massachusetts CS27 Mainland', + 12002 => 'Massachusetts CS27 Island', + 12031 => 'Massachusetts CS83 Mainland', + 12032 => 'Massachusetts CS83 Island', + 12101 => 'Michigan State Plane East', + 12102 => 'Michigan State Plane Old Central', + 12103 => 'Michigan State Plane West', + 12111 => 'Michigan CS27 North', + 12112 => 'Michigan CS27 Central', + 12113 => 'Michigan CS27 South', + 12141 => 'Michigan CS83 North', + 12142 => 'Michigan CS83 Central', + 12143 => 'Michigan CS83 South', + 12201 => 'Minnesota CS27 North', + 12202 => 'Minnesota CS27 Central', + 12203 => 'Minnesota CS27 South', + 12231 => 'Minnesota CS83 North', + 12232 => 'Minnesota CS83 Central', + 12233 => 'Minnesota CS83 South', + 12301 => 'Mississippi CS27 East', + 12302 => 'Mississippi CS27 West', + 12331 => 'Mississippi CS83 East', + 12332 => 'Mississippi CS83 West', + 12401 => 'Missouri CS27 East', + 12402 => 'Missouri CS27 Central', + 12403 => 'Missouri CS27 West', + 12431 => 'Missouri CS83 East', + 12432 => 'Missouri CS83 Central', + 12433 => 'Missouri CS83 West', + 12501 => 'Montana CS27 North', + 12502 => 'Montana CS27 Central', + 12503 => 'Montana CS27 South', + 12530 => 'Montana CS83', + 12601 => 'Nebraska CS27 North', + 12602 => 'Nebraska CS27 South', + 12630 => 'Nebraska CS83', + 12701 => 'Nevada CS27 East', + 12702 => 'Nevada CS27 Central', + 12703 => 'Nevada CS27 West', + 12731 => 'Nevada CS83 East', + 12732 => 'Nevada CS83 Central', + 12733 => 'Nevada CS83 West', + 12800 => 'New Hampshire CS27', + 12830 => 'New Hampshire CS83', + 12900 => 'New Jersey CS27', + 12930 => 'New Jersey CS83', + 13001 => 'New Mexico CS27 East', + 13002 => 'New Mexico CS27 Central', + 13003 => 'New Mexico CS27 West', + 13031 => 'New Mexico CS83 East', + 13032 => 'New Mexico CS83 Central', + 13033 => 'New Mexico CS83 West', + 13101 => 'New York CS27 East', + 13102 => 'New York CS27 Central', + 13103 => 'New York CS27 West', + 13104 => 'New York CS27 Long Island', + 13131 => 'New York CS83 East', + 13132 => 'New York CS83 Central', + 13133 => 'New York CS83 West', + 13134 => 'New York CS83 Long Island', + 13200 => 'North Carolina CS27', + 13230 => 'North Carolina CS83', + 13301 => 'North Dakota CS27 North', + 13302 => 'North Dakota CS27 South', + 13331 => 'North Dakota CS83 North', + 13332 => 'North Dakota CS83 South', + 13401 => 'Ohio CS27 North', + 13402 => 'Ohio CS27 South', + 13431 => 'Ohio CS83 North', + 13432 => 'Ohio CS83 South', + 13501 => 'Oklahoma CS27 North', + 13502 => 'Oklahoma CS27 South', + 13531 => 'Oklahoma CS83 North', + 13532 => 'Oklahoma CS83 South', + 13601 => 'Oregon CS27 North', + 13602 => 'Oregon CS27 South', + 13631 => 'Oregon CS83 North', + 13632 => 'Oregon CS83 South', + 13701 => 'Pennsylvania CS27 North', + 13702 => 'Pennsylvania CS27 South', + 13731 => 'Pennsylvania CS83 North', + 13732 => 'Pennsylvania CS83 South', + 13800 => 'Rhode Island CS27', + 13830 => 'Rhode Island CS83', + 13901 => 'South Carolina CS27 North', + 13902 => 'South Carolina CS27 South', + 13930 => 'South Carolina CS83', + 14001 => 'South Dakota CS27 North', + 14002 => 'South Dakota CS27 South', + 14031 => 'South Dakota CS83 North', + 14032 => 'South Dakota CS83 South', + 14100 => 'Tennessee CS27', + 14130 => 'Tennessee CS83', + 14201 => 'Texas CS27 North', + 14202 => 'Texas CS27 North Central', + 14203 => 'Texas CS27 Central', + 14204 => 'Texas CS27 South Central', + 14205 => 'Texas CS27 South', + 14231 => 'Texas CS83 North', + 14232 => 'Texas CS83 North Central', + 14233 => 'Texas CS83 Central', + 14234 => 'Texas CS83 South Central', + 14235 => 'Texas CS83 South', + 14301 => 'Utah CS27 North', + 14302 => 'Utah CS27 Central', + 14303 => 'Utah CS27 South', + 14331 => 'Utah CS83 North', + 14332 => 'Utah CS83 Central', + 14333 => 'Utah CS83 South', + 14400 => 'Vermont CS27', + 14430 => 'Vermont CS83', + 14501 => 'Virginia CS27 North', + 14502 => 'Virginia CS27 South', + 14531 => 'Virginia CS83 North', + 14532 => 'Virginia CS83 South', + 14601 => 'Washington CS27 North', + 14602 => 'Washington CS27 South', + 14631 => 'Washington CS83 North', + 14632 => 'Washington CS83 South', + 14701 => 'West Virginia CS27 North', + 14702 => 'West Virginia CS27 South', + 14731 => 'West Virginia CS83 North', + 14732 => 'West Virginia CS83 South', + 14801 => 'Wisconsin CS27 North', + 14802 => 'Wisconsin CS27 Central', + 14803 => 'Wisconsin CS27 South', + 14831 => 'Wisconsin CS83 North', + 14832 => 'Wisconsin CS83 Central', + 14833 => 'Wisconsin CS83 South', + 14901 => 'Wyoming CS27 East', + 14902 => 'Wyoming CS27 East Central', + 14903 => 'Wyoming CS27 West Central', + 14904 => 'Wyoming CS27 West', + 14931 => 'Wyoming CS83 East', + 14932 => 'Wyoming CS83 East Central', + 14933 => 'Wyoming CS83 West Central', + 14934 => 'Wyoming CS83 West', + 15001 => 'Alaska CS27 1', + 15002 => 'Alaska CS27 2', + 15003 => 'Alaska CS27 3', + 15004 => 'Alaska CS27 4', + 15005 => 'Alaska CS27 5', + 15006 => 'Alaska CS27 6', + 15007 => 'Alaska CS27 7', + 15008 => 'Alaska CS27 8', + 15009 => 'Alaska CS27 9', + 15010 => 'Alaska CS27 10', + 15031 => 'Alaska CS83 1', + 15032 => 'Alaska CS83 2', + 15033 => 'Alaska CS83 3', + 15034 => 'Alaska CS83 4', + 15035 => 'Alaska CS83 5', + 15036 => 'Alaska CS83 6', + 15037 => 'Alaska CS83 7', + 15038 => 'Alaska CS83 8', + 15039 => 'Alaska CS83 9', + 15040 => 'Alaska CS83 10', + 15101 => 'Hawaii CS27 1', + 15102 => 'Hawaii CS27 2', + 15103 => 'Hawaii CS27 3', + 15104 => 'Hawaii CS27 4', + 15105 => 'Hawaii CS27 5', + 15131 => 'Hawaii CS83 1', + 15132 => 'Hawaii CS83 2', + 15133 => 'Hawaii CS83 3', + 15134 => 'Hawaii CS83 4', + 15135 => 'Hawaii CS83 5', + 15201 => 'Puerto Rico CS27', + 15202 => 'St Croix', + 15230 => 'Puerto Rico Virgin Is', + 15302 => 'Kentucky CS27', + 15303 => 'Kentucky CS83 North', + 15914 => 'BLM 14N feet', + 15915 => 'BLM 15N feet', + 15916 => 'BLM 16N feet', + 15917 => 'BLM 17N feet', + 16001 => 'UTM zone 1N', + 16002 => 'UTM zone 2N', + 16003 => 'UTM zone 3N', + 16004 => 'UTM zone 4N', + 16005 => 'UTM zone 5N', + 16006 => 'UTM zone 6N', + 16007 => 'UTM zone 7N', + 16008 => 'UTM zone 8N', + 16009 => 'UTM zone 9N', + 16010 => 'UTM zone 10N', + 16011 => 'UTM zone 11N', + 16012 => 'UTM zone 12N', + 16013 => 'UTM zone 13N', + 16014 => 'UTM zone 14N', + 16015 => 'UTM zone 15N', + 16016 => 'UTM zone 16N', + 16017 => 'UTM zone 17N', + 16018 => 'UTM zone 18N', + 16019 => 'UTM zone 19N', + 16020 => 'UTM zone 20N', + 16021 => 'UTM zone 21N', + 16022 => 'UTM zone 22N', + 16023 => 'UTM zone 23N', + 16024 => 'UTM zone 24N', + 16025 => 'UTM zone 25N', + 16026 => 'UTM zone 26N', + 16027 => 'UTM zone 27N', + 16028 => 'UTM zone 28N', + 16029 => 'UTM zone 29N', + 16030 => 'UTM zone 30N', + 16031 => 'UTM zone 31N', + 16032 => 'UTM zone 32N', + 16033 => 'UTM zone 33N', + 16034 => 'UTM zone 34N', + 16035 => 'UTM zone 35N', + 16036 => 'UTM zone 36N', + 16037 => 'UTM zone 37N', + 16038 => 'UTM zone 38N', + 16039 => 'UTM zone 39N', + 16040 => 'UTM zone 40N', + 16041 => 'UTM zone 41N', + 16042 => 'UTM zone 42N', + 16043 => 'UTM zone 43N', + 16044 => 'UTM zone 44N', + 16045 => 'UTM zone 45N', + 16046 => 'UTM zone 46N', + 16047 => 'UTM zone 47N', + 16048 => 'UTM zone 48N', + 16049 => 'UTM zone 49N', + 16050 => 'UTM zone 50N', + 16051 => 'UTM zone 51N', + 16052 => 'UTM zone 52N', + 16053 => 'UTM zone 53N', + 16054 => 'UTM zone 54N', + 16055 => 'UTM zone 55N', + 16056 => 'UTM zone 56N', + 16057 => 'UTM zone 57N', + 16058 => 'UTM zone 58N', + 16059 => 'UTM zone 59N', + 16060 => 'UTM zone 60N', + 16101 => 'UTM zone 1S', + 16102 => 'UTM zone 2S', + 16103 => 'UTM zone 3S', + 16104 => 'UTM zone 4S', + 16105 => 'UTM zone 5S', + 16106 => 'UTM zone 6S', + 16107 => 'UTM zone 7S', + 16108 => 'UTM zone 8S', + 16109 => 'UTM zone 9S', + 16110 => 'UTM zone 10S', + 16111 => 'UTM zone 11S', + 16112 => 'UTM zone 12S', + 16113 => 'UTM zone 13S', + 16114 => 'UTM zone 14S', + 16115 => 'UTM zone 15S', + 16116 => 'UTM zone 16S', + 16117 => 'UTM zone 17S', + 16118 => 'UTM zone 18S', + 16119 => 'UTM zone 19S', + 16120 => 'UTM zone 20S', + 16121 => 'UTM zone 21S', + 16122 => 'UTM zone 22S', + 16123 => 'UTM zone 23S', + 16124 => 'UTM zone 24S', + 16125 => 'UTM zone 25S', + 16126 => 'UTM zone 26S', + 16127 => 'UTM zone 27S', + 16128 => 'UTM zone 28S', + 16129 => 'UTM zone 29S', + 16130 => 'UTM zone 30S', + 16131 => 'UTM zone 31S', + 16132 => 'UTM zone 32S', + 16133 => 'UTM zone 33S', + 16134 => 'UTM zone 34S', + 16135 => 'UTM zone 35S', + 16136 => 'UTM zone 36S', + 16137 => 'UTM zone 37S', + 16138 => 'UTM zone 38S', + 16139 => 'UTM zone 39S', + 16140 => 'UTM zone 40S', + 16141 => 'UTM zone 41S', + 16142 => 'UTM zone 42S', + 16143 => 'UTM zone 43S', + 16144 => 'UTM zone 44S', + 16145 => 'UTM zone 45S', + 16146 => 'UTM zone 46S', + 16147 => 'UTM zone 47S', + 16148 => 'UTM zone 48S', + 16149 => 'UTM zone 49S', + 16150 => 'UTM zone 50S', + 16151 => 'UTM zone 51S', + 16152 => 'UTM zone 52S', + 16153 => 'UTM zone 53S', + 16154 => 'UTM zone 54S', + 16155 => 'UTM zone 55S', + 16156 => 'UTM zone 56S', + 16157 => 'UTM zone 57S', + 16158 => 'UTM zone 58S', + 16159 => 'UTM zone 59S', + 16160 => 'UTM zone 60S', + 16200 => 'Gauss Kruger zone 0', + 16201 => 'Gauss Kruger zone 1', + 16202 => 'Gauss Kruger zone 2', + 16203 => 'Gauss Kruger zone 3', + 16204 => 'Gauss Kruger zone 4', + 16205 => 'Gauss Kruger zone 5', + 17348 => 'Map Grid of Australia 48', + 17349 => 'Map Grid of Australia 49', + 17350 => 'Map Grid of Australia 50', + 17351 => 'Map Grid of Australia 51', + 17352 => 'Map Grid of Australia 52', + 17353 => 'Map Grid of Australia 53', + 17354 => 'Map Grid of Australia 54', + 17355 => 'Map Grid of Australia 55', + 17356 => 'Map Grid of Australia 56', + 17357 => 'Map Grid of Australia 57', + 17358 => 'Map Grid of Australia 58', + 17448 => 'Australian Map Grid 48', + 17449 => 'Australian Map Grid 49', + 17450 => 'Australian Map Grid 50', + 17451 => 'Australian Map Grid 51', + 17452 => 'Australian Map Grid 52', + 17453 => 'Australian Map Grid 53', + 17454 => 'Australian Map Grid 54', + 17455 => 'Australian Map Grid 55', + 17456 => 'Australian Map Grid 56', + 17457 => 'Australian Map Grid 57', + 17458 => 'Australian Map Grid 58', + 18031 => 'Argentina 1', + 18032 => 'Argentina 2', + 18033 => 'Argentina 3', + 18034 => 'Argentina 4', + 18035 => 'Argentina 5', + 18036 => 'Argentina 6', + 18037 => 'Argentina 7', + 18051 => 'Colombia 3W', + 18052 => 'Colombia Bogota', + 18053 => 'Colombia 3E', + 18054 => 'Colombia 6E', + 18072 => 'Egypt Red Belt', + 18073 => 'Egypt Purple Belt', + 18074 => 'Extended Purple Belt', + 18141 => 'New Zealand North Island Nat Grid', + 18142 => 'New Zealand South Island Nat Grid', + 19900 => 'Bahrain Grid', + 19905 => 'Netherlands E Indies Equatorial', + 19912 => 'RSO Borneo', + 19926 => 'Stereo 70', + 32767 => 'User Defined', + }, + }, + 3075 => { + Name => 'ProjCoordTrans', + PrintConv => { + # geo_ctrans + 1 => 'Transverse Mercator', + 2 => 'Transverse Mercator Modified Alaska', + 3 => 'Oblique Mercator', + 4 => 'Oblique Mercator Laborde', + 5 => 'Oblique Mercator Rosenmund', + 6 => 'Oblique Mercator Spherical', # not advisable + 7 => 'Mercator', + 8 => 'Lambert Conf Conic 2SP', + 9 => 'Lambert Conf Conic 1SP', + 10 => 'Lambert Azim Equal Area', + 11 => 'Albers Equal Area', + 12 => 'Azimuthal Equidistant', + 13 => 'Equidistant Conic', + 14 => 'Stereographic', + 15 => 'Polar Stereographic', + 16 => 'Oblique Stereographic', # not advisable + 17 => 'Equirectangular', + 18 => 'Cassini Soldner', + 19 => 'Gnomonic', + 20 => 'Miller Cylindrical', + 21 => 'Orthographic', + 22 => 'Polyconic', + 23 => 'Robinson', + 24 => 'Sinusoidal', + 25 => 'VanDerGrinten', + 26 => 'New Zealand Map Grid', + 27 => 'Transverse Mercator South Orientated', + 28 => 'Cylindrical Equal Area', + 32767 => 'User Defined', + }, + }, + 3076 => { + Name => 'ProjLinearUnits', + SeparateTable => 'Units', + PrintConv => \%epsg_units, + }, + 3077 => 'ProjLinearUnitSize', + 3078 => 'ProjStdParallel1', + 3079 => 'ProjStdParallel2', + 3080 => 'ProjNatOriginLong', + 3081 => 'ProjNatOriginLat', + 3082 => 'ProjFalseEasting', + 3083 => 'ProjFalseNorthing', + 3084 => 'ProjFalseOriginLong', + 3085 => 'ProjFalseOriginLat', + 3086 => 'ProjFalseOriginEasting', + 3087 => 'ProjFalseOriginNorthing', + 3088 => 'ProjCenterLong', + 3089 => 'ProjCenterLat', + 3090 => 'ProjCenterEasting', + 3091 => 'ProjCenterNorthing', + 3092 => 'ProjScaleAtNatOrigin', + 3093 => 'ProjScaleAtCenter', + 3094 => 'ProjAzimuthAngle', + 3095 => 'ProjStraightVertPoleLong', + 3096 => 'ProjRectifiedGridAngle', + 4096 => { + Name => 'VerticalCSType', + SeparateTable => 'VerticalCS', + PrintConv => \%epsg_vertcs, + }, + 4097 => 'VerticalCitation', + 4098 => { + Name => 'VerticalDatum', + SeparateTable => 'VerticalCS', + PrintConv => \%epsg_vertcs, + }, + 4099 => { + Name => 'VerticalUnits', + SeparateTable => 'Units', + PrintConv => \%epsg_units, + }, +# +# ChartTiff extensions (ref 2) +# + 47001 => { + Name => 'ChartFormat', + PrintConv => { + 47500 => 'General', + 47501 => 'Coastal', + 47502 => 'Harbor', + 47503 => 'SailingInternational', + 47504 => 'SmallCraft Route', + 47505 => 'SmallCraftArea', + 47506 => 'SmallCraftFolio', + 47507 => 'Topographic', + 47508 => 'Recreation', + 47509 => 'Index', + 47510 => 'Inset', + }, + }, + 47002 => 'ChartSource', + 47003 => 'ChartSourceEdition', + 47004 => 'ChartSourceDate', + 47005 => 'ChartCorrDate', + 47006 => 'ChartCountryOrigin', + 47007 => 'ChartRasterEdition', + 47008 => { + Name => 'ChartSoundingDatum', + PrintConv => { + 47600 => 'Equatorial Spring Low Water', + 47601 => 'Indian Spring Low Water', + 47602 => 'Lowest Astronomical Tide', + 47603 => 'Lowest Low Water', + 47604 => 'Lowest Normal Low Water', + 47605 => 'Mean Higher High Water', + 47606 => 'Mean High Water', + 47607 => 'Mean High Water Springs', + 47608 => 'Mean Lower Low Water', + 47609 => 'Mean Lower Low Water Springs', + 47610 => 'Mean Low Water', + 47611 => 'Mean Sea Level', + 47612 => 'Tropic Higher High Water', + 47613 => 'Tropic Lower Low Water', + }, + }, + 47009 => { + Name => 'ChartDepthUnits', + SeparateTable => 'Units', + PrintConv => \%epsg_units, + }, + 47010 => 'ChartMagVar', + 47011 => 'ChartMagVarYear', + 47012 => 'ChartMagVarAnnChange', + 47013 => 'ChartWGSNSShift', + 47015 => 'InsetNWPixelX', + 47016 => 'InsetNWPixelY', + 47017 => 'ChartContourInterval', +); + +#------------------------------------------------------------------------------ +# Inputs: 0) ExifTool object ref +# Notes: byte order must be set before calling this routine +sub ProcessGeoTiff($) +{ + my $et = shift; + my $dirData = $et->GetValue('GeoTiffDirectory', 'ValueConv') or return; + + # avoid re-processing if another EXIF directory is found + $$et{DidGeoTiff} and $$et{DidGeoTiff} eq $dirData and return; + $$et{DidGeoTiff} = $dirData; + + my $doubleData = $et->GetValue('GeoTiffDoubleParams', 'ValueConv'); + my $asciiData = $et->GetValue('GeoTiffAsciiParams', 'ValueConv'); + my $verbose = $et->Options('Verbose'); + + if (length($$dirData) >= 8 and + length($$dirData) >= 8 * (Get16u($dirData,6) + 1)) + { + my $version = Get16u($dirData,0); + my $revision = Get16u($dirData,2); + my $minorRev = Get16u($dirData,4); + my $numEntries = Get16u($dirData,6); + + if ($verbose) { + $$et{INDENT} .= '| '; + $et->VerboseDir('GeoTiff',$numEntries); + } + # generate version number tag (not a real GeoTiff tag) + my $tagTable = GetTagTable("Image::ExifTool::GeoTiff::Main"); + my $tagInfo = $et->GetTagInfo($tagTable, 1); + $tagInfo and $et->FoundTag($tagInfo,"$version.$revision.$minorRev"); + + my $i; + for ($i=0; $i<$numEntries; ++$i) { + my $pt = 8 * ($i + 1); + my $tag = Get16u($dirData, $pt); + $tagInfo = $et->GetTagInfo($tagTable, $tag) or next; + my $loc = Get16u($dirData, $pt+2); + my $count = Get16u($dirData, $pt+4); + my $offset = Get16u($dirData, $pt+6); + my $format = $geoTiffFormat{$loc}; + my ($val, $dataPt); + if (not $format) { + $et->Warn("Unknown GeoTiff location ($loc) for $$tagInfo{Name}"); + next; + } elsif ($format eq 'double') { # in the double parms + $dataPt = $doubleData; + } elsif ($format eq 'string') { # in the ASCII parms + $dataPt = $asciiData; + } elsif ($format eq 'int16u') { # in the GeoTiffDirectory data + $dataPt = $dirData; + unless ($loc) { # is value is stored in offset? + $count = 1; # (implied by location of 0) + $offset = ($pt + 6) / 2; # offset of the "offset" value + } + } + my $size = Image::ExifTool::FormatSize($format); + if (not $dataPt or length($$dataPt) < $size*($offset+$count)) { + $et->Warn("Missing $format data for $$tagInfo{Name}"); + next; + } + $offset *= $size; + $val = Image::ExifTool::ReadValue($dataPt, $offset, $format, + $count, length($$dataPt)-$offset); + # remove trailing terminator (NULL or '|') from string value + $val =~ s/(\0|\|)$// if $format eq 'string'; + $verbose and $et->VerboseInfo($tag, $tagInfo, + 'Table' => $tagTable, + 'Index' => $i, + 'Value' => $val, + 'DataPt' => $dataPt, + 'Start' => $offset, + 'Format' => $format, + 'Count' => $count, + 'Size' => $count * $size, + ); + $et->FoundTag($tagInfo, $val); + } + if ($verbose) { + $$et{INDENT} =~ s/..$//; + } + } else { + $et->Warn('Bad GeoTIFF directory'); + } + # extract block tags only if requested + unless ($$et{OPTIONS}{RequestAll}) { + $et->DeleteTag('GeoTiffDirectory') unless $$et{REQ_TAG_LOOKUP}{geotiffdirectory}; + $et->DeleteTag('GeoTiffDoubleParams') unless $$et{REQ_TAG_LOOKUP}{geotiffdoubleparams}; + $et->DeleteTag('GeoTiffAsciiParams') unless $$et{REQ_TAG_LOOKUP}{geotiffasciiparams}; + } +} + + +1; #end + +__END__ + +=head1 NAME + +Image::ExifTool::GeoTiff - Read GeoTiff meta information + +=head1 SYNOPSIS + +This module is loaded automatically by Image::ExifTool when required. + +=head1 DESCRIPTION + +This module contains definitions required by Image::ExifTool to interpret +GeoTiff meta information. GeoTiff information is used in images to specify +exact geometric mappings used to transform the image to real world +coordinates. + +=head1 AUTHOR + +Copyright 2003-2019, Phil Harvey (phil at owl.phy.queensu.ca) + +This library is free software; you can redistribute it and/or modify it +under the same terms as Perl itself. + +=head1 REFERENCES + +=over 4 + +=item ftp://ftp.remotesensing.org/geotiff/libgeotiff/libgeotiff-1.1.4.tar.gz + +=item http://www.charttiff.com/whitepapers.shtml + +=back + +=head1 SEE ALSO + +L<Image::ExifTool::TagNames/GeoTiff Tags>, +L<Image::ExifTool(3pm)|Image::ExifTool> + +=cut diff --git a/lib/Image/ExifTool/Geotag.pm b/lib/Image/ExifTool/Geotag.pm new file mode 100644 index 0000000..87c48f4 --- /dev/null +++ b/lib/Image/ExifTool/Geotag.pm @@ -0,0 +1,1327 @@ +#------------------------------------------------------------------------------ +# File: Geotag.pm +# +# Description: Geotagging utility routines +# +# Revisions: 2009/04/01 - P. Harvey Created +# 2009/09/27 - PH Added Geosync feature +# 2009/06/25 - PH Read Garmin TCX track logs +# 2009/09/11 - PH Read ITC GPS track logs +# 2012/01/08 - PH Extract orientation information from PTNTHPR +# 2012/05/08 - PH Read Winplus Beacon .TXT files +# 2015/05/30 - PH Read Bramor gEO log files +# 2016/07/13 - PH Added ability to geotag date/time only +# +# References: 1) http://www.topografix.com/GPX/1/1/ +# 2) http://www.gpsinformation.org/dale/nmea.htm#GSA +# 3) http://code.google.com/apis/kml/documentation/kmlreference.html +# 4) http://www.fai.org/gliding/system/files/tech_spec_gnss.pdf +#------------------------------------------------------------------------------ + +package Image::ExifTool::Geotag; + +use strict; +use vars qw($VERSION); +use Image::ExifTool qw(:Public); + +$VERSION = '1.57'; + +sub JITTER() { return 2 } # maximum time jitter + +sub GetTime($); +sub SetGeoValues($$;$); +sub PrintFixTime($); +sub PrintFix($@); + +# XML tags that we recognize (keys are forced to lower case) +my %xmlTag = ( + lat => 'lat', # GPX + latitude => 'lat', # Garmin + latitudedegrees => 'lat', # Garmin TCX + lon => 'lon', # GPX + longitude => 'lon', # Garmin + longitudedegrees => 'lon', # Garmin TCX + ele => 'alt', # GPX + elevation => 'alt', # PH + alt => 'alt', # PH + altitude => 'alt', # Garmin + altitudemeters => 'alt', # Garmin TCX + 'time' => 'time', # GPX/Garmin + fix => 'fixtype', # GPX + hdop => 'hdop', # GPX + vdop => 'vdop', # GPX + pdop => 'pdop', # GPX + sat => 'nsats', # GPX + atemp => 'atemp', # GPX (Garmin 550t) + when => 'time', # KML + coordinates => 'coords', # KML + coord => 'coords', # KML, as written by Google Location History + begin => 'begin', # KML TimeSpan + end => 'time', # KML TimeSpan + course => 'dir', # (written by Arduino) + pitch => 'pitch', # (written by Arduino) + roll => 'roll', # (written by Arduino) + # XML containers (fix is reset at the opening tag of these properties) + wpt => '', # GPX + trkpt => '', # GPX + rtept => '', # GPX + trackpoint => '', # Garmin + placemark => '', # KML +); + +# fix information keys which must be interpolated around a circle +my %cyclical = (lon => 1, track => 1, dir => 1, roll => 1); + +# fix information keys for each of our general categories +my %fixInfoKeys = ( + 'pos' => [ 'lat', 'lon' ], + track => [ 'track', 'speed' ], + alt => [ 'alt' ], + orient => [ 'dir', 'pitch', 'roll' ], + atemp => [ 'atemp' ], +); + +my %isOrient = ( dir => 1, pitch => 1, roll => 1 ); # test for orientation key + +# conversion factors for GPSSpeed +my %speedConv = ( + 'K' => 1.852, # km/h per knot + 'M' => 1.150779448, # mph per knot + 'k' => 'K', # (allow lower case) + 'm' => 'M', + 'km/h' => 'K', # (allow other formats) + 'mph' => 'M', +); + +my $secPerDay = 24 * 3600; # a useful constant + +#------------------------------------------------------------------------------ +# Load GPS track log file +# Inputs: 0) ExifTool ref, 1) track log data or file name +# Returns: geotag hash data reference or error string +# - the geotag hash has the following members: +# Points - hash of GPS fix information hashes keyed by Unix time +# Times - list of sorted Unix times (keys of Points hash) +# NoDate - flag if some points have no date (ie. referenced to 1970:01:01) +# IsDate - flag if some points have date +# Has - hash of flags for available information (track, orient, alt) +# - the fix information hash may contain: +# lat - signed latitude (required) +# lon - signed longitude (required) +# alt - signed altitude +# time - fix time in UTC as XML string +# fixtype- type of fix ('none'|'2d'|'3d'|'dgps'|'pps') +# pdop - dilution of precision +# hdop - horizontal DOP +# vdop - vertical DOP +# sats - comma-separated list of active satellites +# nsats - number of active satellites +# track - track heading (deg true) +# dir - image direction (deg true) +# pitch - pitch angle (deg) +# roll - roll angle (deg) +# speed - speed (knots) +# first - flag set for first fix of track +# - concatenates new data with existing track data stored in ExifTool NEW_VALUE +# for the Geotag tag +sub LoadTrackLog($$;$) +{ + local ($_, $/, *EXIFTOOL_TRKFILE); + my ($et, $val) = @_; + my ($raf, $from, $time, $isDate, $noDate, $noDateChanged, $lastDate, $dateFlarm); + my ($nmeaStart, $fixSecs, @fixTimes, $lastFix, %nmea); + my ($canCut, $cutPDOP, $cutHDOP, $cutSats, $e0, $e1, @tmp); + + unless (eval { require Time::Local }) { + return 'Geotag feature requires Time::Local installed'; + } + # add data to existing track + my $geotag = $et->GetNewValue('Geotag') || { }; + + # initialize track points lookup + my $points = $$geotag{Points}; + $points or $points = $$geotag{Points} = { }; + + # get lookup for available information types + my $has = $$geotag{Has}; + $has or $has = $$geotag{Has} = { 'pos' => 1 }; + + my $format = ''; + # is $val track log data? + if ($val =~ /^(\xef\xbb\xbf)?<(\?xml|gpx)[\s>]/) { + $format = 'XML'; + $/ = '>'; # set input record separator to '>' for XML/GPX data + } elsif ($val =~ /(\x0d\x0a|\x0d|\x0a)/) { + $/ = $1; + } else { + # $val is track file name + if ($et->Open(\*EXIFTOOL_TRKFILE, $val)) { + $raf = new File::RandomAccess(\*EXIFTOOL_TRKFILE); + unless ($raf->Read($_, 256)) { + close EXIFTOOL_TRKFILE; + return "Empty track file '${val}'"; + } + # look for XML or GPX header (might as well allow UTF-8 BOM) + if (/^(\xef\xbb\xbf)?<(\?xml|gpx)[\s>]/) { + $format = 'XML'; + $/ = '>'; # set input record separator to '>' for XML/GPX data + } elsif (/(\x0d\x0a|\x0d|\x0a)/) { + $/ = $1; + } else { + close EXIFTOOL_TRKFILE; + return "Invalid track file '${val}'"; + } + $raf->Seek(0,0); + $from = "file '${val}'"; + } elsif ($val eq 'DATETIMEONLY') { + $$geotag{DateTimeOnly} = 1; + $$geotag{IsDate} = 1; + $et->VPrint(0, 'Geotagging date/time only'); + return $geotag; + } else { + return "Error opening GPS file '${val}'"; + } + } + unless ($from) { + # set up RAF for reading log file in memory + $raf = new File::RandomAccess(\$val); + $from = 'data'; + } + + # initialize cuts + my $maxHDOP = $et->Options('GeoMaxHDOP'); + my $maxPDOP = $et->Options('GeoMaxPDOP'); + my $minSats = $et->Options('GeoMinSats'); + my $isCut = $maxHDOP || $maxPDOP || $minSats; + + my $numPoints = 0; + my $skipped = 0; + my $lastSecs = 0; + my $fix = { }; + my (@saveFix, $timeSpan); + for (;;) { + $raf->ReadLine($_) or last; + # determine file format + if (not $format) { + if (/^<(\?xml|gpx)[\s>]/) { # look for XML or GPX header + $format = 'XML'; + # check for NMEA sentence + # (must ONLY start with ones that have timestamps! eg. not GSA or PTNTHPR!) + } elsif (/^\$([A-Z]{2}(RMC|GGA|GLL|ZDA)|PMGNTRK),/) { + $format = 'NMEA'; + $nmeaStart = $2 || $1; # save type of first sentence + } elsif (/^A(FLA|XSY|FIL)/) { + # (don't set format yet because we want to read HFDTE first) + $nmeaStart = 'B' ; + next; + } elsif (/^HFDTE(\d{2})(\d{2})(\d{2})/) { + my $year = $3 + ($3 >= 70 ? 1900 : 2000); + $dateFlarm = Time::Local::timegm(0,0,0,$1,$2-1,$year-1900); + $nmeaStart = 'B' ; + $format = 'IGC'; + next; + } elsif ($nmeaStart and /^B/) { + # parse IGC fixes without a date + $format = 'IGC'; + } elsif (/^TP,D,/) { + $format = 'Winplus'; + } elsif (/^\s*\d+\s+.*\sypr\s*$/ and (@tmp=split) == 12) { + $format = 'Bramor'; + } else { + # search only first 50 lines of file for a valid fix + last if ++$skipped > 50; + next; + } + } +# +# XML format (GPX, KML, Garmin XML/TCX etc) +# + if ($format eq 'XML') { + my ($arg, $tok, $td); + s/\s*=\s*(['"])\s*/=$1/g; # remove unnecessary white space in attributes + # Workaround for KML generated by Google Location History: + # lat/lon/alt are space-separated; we want commas. + s{(\S+)\s+(\S+)\s+(\S+)(</gx:coord>)}{$1,$2,$3$4}; + foreach $arg (split) { + # parse attributes (eg. GPX 'lat' and 'lon') + # (note: ignore namespace prefixes if they exist) + if ($arg =~ /^(\w+:)?(\w+)=(['"])(.*?)\3/g) { + my $tag = $xmlTag{lc $2}; + if ($tag) { + $$fix{$tag} = $4; + if ($isOrient{$tag}) { + $$has{orient} = 1; + } elsif ($tag eq 'alt') { + # validate altitude + undef $$fix{alt} if defined $$fix{alt} and $$fix{alt} !~ /^[+-]?\d+\.?\d*/; + $$has{alt} = 1 if $$fix{alt}; # set "has altitude" flag if appropriate + } elsif ($tag eq 'atemp') { + $$has{atemp} = 1; + } + } + } + # loop through XML elements + while ($arg =~ m{([^<>]*)<(/)?(\w+:)?(\w+)(>|$)}g) { + my $tag = $xmlTag{$tok = lc $4}; + # parse as a simple property if this element has a value + if (defined $tag and not $tag) { + # a containing property was opened or closed + if (not $2) { + # opened: start a new fix + $lastFix = $fix = { }; + undef @saveFix; + next; + } elsif ($fix and $lastFix and %$fix) { + # closed: transfer additional tags from current fix + foreach (keys %$fix) { + $$lastFix{$_} = $$fix{$_} unless defined $$lastFix{$_}; + } + undef $lastFix; + } + } + if (length $1) { + if ($tag) { + if ($tag eq 'coords') { + # save other fixes if there are more than one + if (defined $$fix{lon} and defined $$fix{lat} and defined $$fix{alt}) { + push @saveFix, [ @$fix{'lon','lat','alt'} ]; + } + # read KML "Point" coordinates + @$fix{'lon','lat','alt'} = split ',', $1; + } else { + $$fix{$tag} = $1; + if ($isOrient{$tag}) { + $$has{orient} = 1; + } elsif ($tag eq 'alt') { + # validate altitude + undef $$fix{alt} if defined $$fix{alt} and $$fix{alt} !~ /^[+-]?\d+\.?\d*/; + $$has{alt} = 1 if $$fix{alt}; # set "has altitude" flag if appropriate + } elsif ($tag eq 'atemp') { + $$has{atemp} = 1; + } + } + } + next; + } elsif ($tok eq 'td') { + $td = 1; + } + # validate and store GPS fix + next unless defined $$fix{lat} and defined $$fix{lon} and $$fix{'time'}; + unless ($$fix{lat} =~ /^[+-]?\d+\.?\d*/ and $$fix{lon} =~ /^[+-]?\d+\.?\d*/) { + $e0 or $et->VPrint(0, "Coordinate format error in $from\n"), $e0 = 1; + next; + } + unless (defined($time = GetTime($$fix{'time'}))) { + $e1 or $et->VPrint(0, "Timestamp format error in $from\n"), $e1 = 1; + next; + } + $isDate = 1; + $canCut= 1 if defined $$fix{pdop} or defined $$fix{hdop} or defined $$fix{nsats}; + # generate extra fixes assuming an equally spaced track + if ($$fix{begin}) { + my $begin = GetTime($$fix{begin}); + undef $$fix{begin}; + if (defined $begin and $begin < $time) { + $$fix{span} = $timeSpan = ($timeSpan || 0) + 1; + my $i; + # duplicate the fix if there is only one so we will have + # a fix and the start and end of the TimeSpan + @saveFix or push @saveFix, [ @$fix{'lon','lat','alt'} ]; + for ($i=0; $i<@saveFix; ++$i) { + my $t = $begin + ($time - $begin) * ($i / scalar(@saveFix)); + my %f; + @f{'lon','lat','alt'} = @{$saveFix[$i]}; + $t += 0.001 if not $i and $$points{$t}; # (avoid dupicates) + $f{span} = $timeSpan; + $$points{$t} = \%f; + push @fixTimes, $t; + } + } + } + $$points{$time} = $fix; + push @fixTimes, $time; # save times of all fixes in order + $fix = { }; + undef @saveFix; + ++$numPoints; + } + } + # last ditch check KML description for timestamp (assume it is UTC) + $$fix{'time'} = "$1T$2Z" if $td and not $$fix{'time'} and + /[\s>](\d{4}-\d{2}-\d{2})[T ](\d{2}:\d{2}:\d{2}(\.\d+)?)/; + next; +# +# Winplus Beacon text file +# + } elsif ($format eq 'Winplus') { + # TP,D, 44.933666667, -93.186555556, 10/26/2011, 19:07:28, 0 + # latitude longitude date time + /^TP,D,\s*([-+]?\d+\.\d*),\s*([-+]?\d+\.\d*),\s*(\d+)\/(\d+)\/(\d{4}),\s*(\d+):(\d+):(\d+)/ or next; + $$fix{lat} = $1; + $$fix{lon} = $2; + $time = Time::Local::timegm($8,$7,$6,$4,$3-1,$5-1900); +DoneFix: $isDate = 1; + $$points{$time} = $fix; + push @fixTimes, $time; + $fix = { }; + ++$numPoints; + next; +# +# Bramor gEO log file +# + } elsif ($format eq 'Bramor') { + # 1 0015 18.723675 50.672752 149 169.31 22/04/2015 07:06:55 169.31 8.88 28.07 ypr + # ? index latitude longitude alt track date time dir pitch roll + my @parts = split ' ', $_; + next unless @parts == 12 and $parts[11] eq 'ypr'; + my @d = split m{/}, $parts[6]; # date (dd/mm/YYYY) + my @t = split m{:}, $parts[7]; # time (HH:MM:SS) + next unless @d == 3 and @t == 3; + @$fix{qw(lat lon alt track dir pitch roll)} = @parts[2,3,4,5,8,9,10]; + # (add the seconds afterwards in case some models have decimal seconds) + $time = Time::Local::timegm(0,$t[1],$t[0],$d[0],$d[1]-1,$d[2]-1900) + $t[2]; + # set necessary flags for extra available information + @$has{qw(alt track orient)} = (1,1,1); + goto DoneFix; # save this fix + } + my (%fix, $secs, $date, $nmea); + if ($format eq 'NMEA') { + # ignore unrecognized NMEA sentences + # (first 2 characters: GP=GPS, GL=GLONASS, GA=Gallileo, GN=combined, BD=Beidou) + next unless /^\$([A-Z]{2}(RMC|GGA|GLL|GSA|ZDA)|PMGNTRK|PTNTHPR),/; + $nmea = $2 || $1; + } +# +# IGC (flarm) (ref 4) +# + if ($format eq 'IGC') { + # B0939564531208N00557021EA007670089100207 + # BHHMMSSDDMMmmmNDDDMMmmmEAaaaaaAAAAAxxyy + # HH MM SS DD MM mmm DDD MM mmm aaaaa AAAAA + # 1 2 3 4 5 6 7 8 9 10 11 12 13 14 + /^B(\d{2})(\d{2})(\d{2})(\d{2})(\d{2})(\d{3})([NS])(\d{3})(\d{2})(\d{3})([EW])([AV])(\d{5})(\d{5})/ or next; + $fix{lat} = ($4 + ($5 + $6/1000)/60) * ($7 eq 'N' ? 1 : -1); + $fix{lon} = ($8 + ($9 +$10/1000)/60) * ($11 eq 'E' ? 1 : -1); + $fix{alt} = $12 eq 'A' ? $14 : undef; + $secs = (($1 * 60) + $2) * 60 + $3; + # wrap to next day if necessary + if ($dateFlarm) { + $dateFlarm += $secPerDay if $secs < $lastSecs - JITTER(); + $date = $dateFlarm; + } + $nmea = 'B'; +# +# NMEA RMC sentence (contains date) +# + } elsif ($nmea eq 'RMC') { + # $GPRMC,092204.999,A,4250.5589,S,14718.5084,E,0.00,89.68,211200,,*25 + # $GPRMC,093657.007,,3652.835020,N,01053.104094,E,1.642,,290913,,,A*0F + # $GPRMC,hhmmss.sss,A/V,ddmm.mmmm,N/S,ddmmm.mmmm,E/W,spd(knots),dir(deg),DDMMYY,,*cs + /^\$[A-Z]{2}RMC,(\d{2})(\d{2})(\d+(\.\d*)?),A?,(\d*?)(\d{1,2}\.\d+),([NS]),(\d*?)(\d{1,2}\.\d+),([EW]),(\d*\.?\d*),(\d*\.?\d*),(\d{2})(\d{2})(\d+)/ or next; + next if $13 > 31 or $14 > 12 or $15 > 99; # validate day/month/year + $fix{lat} = (($5 || 0) + $6/60) * ($7 eq 'N' ? 1 : -1); + $fix{lon} = (($8 || 0) + $9/60) * ($10 eq 'E' ? 1 : -1); + $fix{speed} = $11 if length $11; + $fix{track} = $12 if length $12; + my $year = $15 + ($15 >= 70 ? 1900 : 2000); + $secs = (($1 * 60) + $2) * 60 + $3; + $date = Time::Local::timegm(0,0,0,$13,$14-1,$year-1900); +# +# NMEA GGA sentence (no date) +# + } elsif ($nmea eq 'GGA') { + # $GPGGA,092204.999,4250.5589,S,14718.5084,E,1,04,24.4,19.7,M,,,,0000*1F + # $GPGGA,093657.000,3652.835020,N,01053.104094,E,,8,,166.924,M,40.9,M,,*77 + # $GPGGA,hhmmss.sss,ddmm.mmmm,N/S,dddmm.mmmm,E/W,0=invalid,sats,hdop,alt,M,... + /^\$[A-Z]{2}GGA,(\d{2})(\d{2})(\d+(\.\d*)?),(\d*?)(\d{1,2}\.\d+),([NS]),(\d*?)(\d{1,2}\.\d+),([EW]),[1-6]?,(\d+)?,(\.\d+|\d+\.?\d*)?,(-?\d+\.?\d*)?,M?/ or next; + $fix{lat} = (($5 || 0) + $6/60) * ($7 eq 'N' ? 1 : -1); + $fix{lon} = (($8 || 0) + $9/60) * ($10 eq 'E' ? 1 : -1); + @fix{qw(nsats hdop alt)} = ($11,$12,$13); + $secs = (($1 * 60) + $2) * 60 + $3; + $canCut = 1; +# +# NMEA GLL sentence (no date) +# + } elsif ($nmea eq 'GLL') { + # $GPGLL,4250.5589,S,14718.5084,E,092204.999,A*2D + # $GPGLL,ddmm.mmmm,N/S,dddmm.mmmm,E/W,hhmmss.sss,A/V*cs + /^\$[A-Z]{2}GLL,(\d*?)(\d{1,2}\.\d+),([NS]),(\d*?)(\d{1,2}\.\d+),([EW]),(\d{2})(\d{2})(\d+(\.\d*)?),A/ or next; + $fix{lat} = (($1 || 0) + $2/60) * ($3 eq 'N' ? 1 : -1); + $fix{lon} = (($4 || 0) + $5/60) * ($6 eq 'E' ? 1 : -1); + $secs = (($7 * 60) + $8) * 60 + $9; +# +# NMEA GSA sentence (satellite status, no date) +# + } elsif ($nmea eq 'GSA') { + # $GPGSA,A,3,04,05,,,,,,,,,,,pdop,hdop,vdop*HH + /^\$[A-Z]{2}GSA,[AM],([23]),((?:\d*,){11}(?:\d*)),(\d+\.?\d*|\.\d+)?,(\d+\.?\d*|\.\d+)?,(\d+\.?\d*|\.\d+)?\*/ or next; + @fix{qw(fixtype sats pdop hdop vdop)} = ($1.'d',$2,$3,$4,$5); + # count the number of acquired satellites + my @a = ($fix{sats} =~ /\d+/g); + $fix{nsats} = scalar @a; + $canCut = 1; +# +# NMEA ZDA sentence (date/time, contains date) +# + } elsif ($nmea eq 'ZDA') { + # $GPZDA,093655.000,29,09,2013,,*58 + # $GPZDA,hhmmss.ss,DD,MM,YYYY,tzh,tzm (hhmmss in UTC) + /^\$[A-Z]{2}ZDA,(\d{2})(\d{2})(\d{2}(\.\d*)?),(\d+),(\d+),(\d+)/ or next; + $secs = (($1 * 60) + $2) * 60 + $3; + $date = Time::Local::timegm(0,0,0,$5,$6-1,$7-1900); +# +# Magellan eXplorist PMGNTRK (Proprietary MaGellaN TRacK) sentence (optional date) +# + } elsif ($nmea eq 'PMGNTRK') { + # $PMGNTRK,4415.026,N,07631.091,W,00092,M,185031.06,A,,020409*65 + # $PMGNTRK,ddmm.mmm,N/S,dddmm.mmm,E/W,alt,F/M,hhmmss.ss,A/V,trkname,DDMMYY*cs + /^\$PMGNTRK,(\d+)(\d{2}\.\d+),([NS]),(\d+)(\d{2}\.\d+),([EW]),(-?\d+\.?\d*),([MF]),(\d{2})(\d{2})(\d+(\.\d*)?),A,(?:[^,]*,(\d{2})(\d{2})(\d+))?/ or next; + $fix{lat} = ($1 + $2/60) * ($3 eq 'N' ? 1 : -1); + $fix{lon} = ($4 + $5/60) * ($6 eq 'E' ? 1 : -1); + $fix{alt} = $8 eq 'M' ? $7 : $7 * 12 * 0.0254; + $secs = (($9 * 60) + $10) * 60 + $11; + if (defined $15) { + next if $13 > 31 or $14 > 12 or $15 > 99; # validate day/month/year + # optional date is available in PMGNTRK sentence + my $year = $15 + ($15 >= 70 ? 1900 : 2000); + $date = Time::Local::timegm(0,0,0,$13,$14-1,$year-1900); + } +# +# Honeywell HMR3000 PTNTHPR (Heading Pitch Roll) sentence (no date) +# (ref http://www.gpsarea.com/uploadfile/download/introduce/hmr3000_manual.pdf) +# + } elsif ($nmea eq 'PTNTHPR') { + # $PTNTHPR,85.9,N,-0.9,N,0.8,N*HH + # $PTNTHPR,heading,heading status,pitch,pitch status,roll,roll status,*cs + # status: L=low alarm, M=low warning, N=normal, O=high warning + # P=high alarm, C=tuning analog circuit + # (ignore this information on any alarm status) + /^\$PTNTHPR,(-?[\d.]+),[MNO],(-?[\d.]+),[MNO],(-?[\d.]+),[MNO]/ or next; + @fix{qw(dir pitch roll)} = ($1,$2,$3); + + } else { + next; # this shouldn't happen + } + # remember the NMEA formats we successfully read + $nmea{$nmea} = 1; + # use last date if necessary (and appropriate) + if (defined $secs and not defined $date and defined $lastDate) { + # wrap to next day if necessary + if ($secs < $lastSecs - JITTER()) { + $lastSecs -= $secPerDay; + $lastDate += $secPerDay; + } + # use earlier date only if we are within 10 seconds + if ($secs - $lastSecs < 10) { + # last date is close, use it for this fix + $date = $lastDate; + } else { + # last date is old, discard it + undef $lastDate; + undef $lastSecs; + } + } + # save our last date/time + if (defined $date) { + $lastDate = $date; + $lastSecs = $secs; + } +# +# Add NMEA/IGC fix to our lookup +# (this is much more complicated than it needs to be because +# the stupid NMEA format provides no end-of-fix indication) +# + # assumptions for each NMEA sentence: + # - we only parse a time if we get a lat/lon + # - we always get a time if we have a date + if ($nmea eq $nmeaStart or (defined $secs and (not defined $fixSecs or + # don't combine sentences that are outside 10 seconds apart + ($secs >= $fixSecs and $secs - $fixSecs >= 10) or + ($secs < $fixSecs and $secs + $secPerDay - $fixSecs >= 10)))) + { + # start a new fix + $fix = \%fix; + $fixSecs = $secs; + undef $noDateChanged; + # does this fix have a date/time or time stamp? + if (defined $date) { + $fix{isDate} = $isDate = 1; + $time = $date + $secs; + } elsif (defined $secs) { + $time = $secs; + $noDate = $noDateChanged = 1; + } else { + next; # wait until we have a time before adding to lookup + } + } else { + # add new data to existing fix (but don't overwrite earlier values to + # keep the coordinates in sync with the fix time) + foreach (keys %fix) { + $$fix{$_} = $fix{$_} unless defined $$fix{$_}; + } + if (defined $date) { + next if $$fix{isDate}; + # move this fix to the proper date + if (defined $fixSecs) { + delete $$points{$fixSecs}; + pop @fixTimes if @fixTimes and $fixTimes[-1] == $fixSecs; + --$numPoints; + # if we wrapped to the next day since the start of this fix, + # we must shift the date back to the day of $fixSecs + $date -= $secPerDay if $secs < $fixSecs; + } else { + $fixSecs = $secs; + } + $time = $date + $fixSecs; + $$fix{isDate} = $isDate = 1; + # revert noDate flag if it was set for this fix + $noDate = 0 if $noDateChanged; + } elsif (defined $secs and not defined $fixSecs) { + $time = $fixSecs = $secs; + $noDate = $noDateChanged = 1; + } else { + next; # wait until we have a time + } + } + # add fix to our lookup + $$points{$time} = $fix; + push @fixTimes, $time; # save time of all fixes in order + ++$numPoints; + } + $raf->Close(); + + # set date flags + if ($noDate and not $$geotag{NoDate}) { + if ($isDate) { + $et->Warn('Fixes are date-less -- will use time-only interpolation'); + } else { + $et->Warn('Some fixes are date-less -- may use time-only interpolation'); + } + $$geotag{NoDate} = 1; + } + $$geotag{IsDate} = 1 if $isDate; + + # cut bad fixes if necessary + if ($isCut and $canCut) { + $cutPDOP = $cutHDOP = $cutSats = 0; + my @goodTimes; + foreach (@fixTimes) { + $fix = $$points{$_} or next; + if ($maxPDOP and $$fix{pdop} and $$fix{pdop} > $maxPDOP) { + delete $$points{$_}; + ++$cutPDOP; + } elsif ($maxHDOP and $$fix{hdop} and $$fix{hdop} > $maxHDOP) { + delete $$points{$_}; + ++$cutHDOP; + } elsif ($minSats and defined $$fix{nsats} and $$fix{nsats} ne '' and + $$fix{nsats} < $minSats) + { + delete $$points{$_}; + ++$cutSats; + } else { + push @goodTimes, $_; + } + } + @fixTimes = @goodTimes; # update fix times + $numPoints -= $cutPDOP; + $numPoints -= $cutHDOP; + $numPoints -= $cutSats; + } + # mark first fix of the track + while (@fixTimes) { + $fix = $$points{$fixTimes[0]} or shift(@fixTimes), next; + $$fix{first} = 1; + last; + } + my $verbose = $et->Options('Verbose'); + if ($verbose) { + my $out = $et->Options('TextOut'); + $format or $format = 'unknown'; + print $out "Loaded $numPoints points from $format-format GPS track log $from\n"; + print $out "Ignored $cutPDOP points due to GeoMaxPDOP cut\n" if $cutPDOP; + print $out "Ignored $cutHDOP points due to GeoMaxHDOP cut\n" if $cutHDOP; + print $out "Ignored $cutSats points due to GeoMinSats cut\n" if $cutSats; + if ($numPoints and $verbose > 1) { + my @lbl = ('start:', 'end: '); + # (fixes may be in reverse order in GPX files) + @lbl = reverse @lbl if $fixTimes[0] > $fixTimes[-1]; + print $out " GPS track $lbl[0] " . PrintFixTime($fixTimes[0]) . "\n"; + if ($verbose > 3) { + print $out PrintFix($points, $_) foreach @fixTimes; + } + print $out " GPS track $lbl[1] " . PrintFixTime($fixTimes[-1]) . "\n"; + } + } + if ($numPoints) { + # reset timestamp list to force it to be regenerated + delete $$geotag{Times}; + # set flags for available information + $$has{alt} = 1 if $nmea{GGA} or $nmea{PMGNTRK} or $nmea{B}; # alt + $$has{track} = 1 if $nmea{RMC}; # track, speed + $$has{orient} = 1 if $nmea{PTNTHPR}; # dir, pitch, roll + return $geotag; # success! + } + return "No track points found in GPS $from"; +} + + +#------------------------------------------------------------------------------ +# Get floating point UTC time +# Inputs: 0) XML time string +# Returns: floating point time or undef on error +sub GetTime($) +{ + my $timeStr = shift; + $timeStr =~ /^(\d{4})-(\d+)-(\d+)T(\d+):(\d+):(\d+)(\.\d+)?(.*)/ or return undef; + my $time = Time::Local::timegm($6,$5,$4,$3,$2-1,$1-1900); + $time += $7 if $7; # add fractional seconds + my $tz = $8; + # adjust for time zone (otherwise assume UTC) + # - allow timezone of +-HH:MM, +-H:MM, +-HHMM or +-HH since + # the spec is unclear about timezone format + if ($tz =~ /^([-+])(\d+):(\d{2})\b/ or $tz =~ /^([-+])(\d{2})(\d{2})?\b/) { + $tz = ($2 * 60 + ($3 || 0)) * 60; + $tz *= -1 if $1 eq '+'; # opposite sign to change back to UTC + $time += $tz; + } + return $time; +} + +#------------------------------------------------------------------------------ +# Apply Geosync time correction +# Inputs: 0) ExifTool ref, 1) Unix UTC time value +# Returns: sync time difference (and updates input time), or undef if no sync +sub ApplySyncCorr($$) +{ + my ($et, $time) = @_; + my $sync = $et->GetNewValue('Geosync'); + if (ref $sync eq 'HASH') { + my $syncTimes = $$sync{Times}; + if ($syncTimes) { + # find the nearest 2 sync points + my ($i0, $i1) = (0, scalar(@$syncTimes) - 1); + while ($i1 > $i0 + 1) { + my $pt = int(($i0 + $i1) / 2); + ($time < $$syncTimes[$pt] ? $i1 : $i0) = $pt; + } + my ($t0, $t1) = ($$syncTimes[$i0], $$syncTimes[$i1]); + # interpolate/extrapolate to account for linear camera clock drift + my $syncPoints = $$sync{Points}; + my $f = $t1 == $t0 ? 0 : ($time - $t0) / ($t1 - $t0); + $sync = $$syncPoints{$t1} * $f + $$syncPoints{$t0} * (1 - $f); + } else { + $sync = $$sync{Offset}; # use fixed time offset + } + $_[1] += $sync; + } else { + undef $sync; + } + return $sync; +} + +#------------------------------------------------------------------------------ +# Scan outwards for a fix containing the requested parameter +# Inputs: 0) name of fix parameter, 1) reference to list of fix times, +# 2) reference to fix points hash, 3) index of starting time, +# 4) direction to scan (-1 or +1), 5) maximum time difference +# Returns: 0) time for fix containing requested information (or undef) +# 1) the corresponding fix, 2) the value of the requested fix parameter +sub ScanOutwards($$$$$$) +{ + my ($key, $times, $points, $i, $dir, $maxSecs) = @_; + my $t0 = $$times[$i]; + for (;;) { + $i += $dir; + last if $i < 0 or $i >= scalar @$times; + my $t = $$times[$i]; + last if abs($t - $t0) > $maxSecs; # don't look too far + my $p = $$points{$t}; + my $v = $$p{$key}; + return($t,$p,$v) if defined $v; + } + return(); +} + +#------------------------------------------------------------------------------ +# Find nearest fix containing the specified parameter +# Inputs: 0) ExifTool ref, 1) name of fix parameter, 2) reference to list of fix times, +# 3) reference to fix points hash, 4) index of starting time, +# 5) direction to scan (-1, +1 or undef), 6) maximum time difference +# Returns: reference to fix hash or undef +sub FindFix($$$$$$$) +{ + my ($et, $key, $times, $points, $i, $dir, $maxSecs) = @_; + my ($t,$p); + if ($dir) { + ($t,$p) = ScanOutwards($key, $times, $points, $i, $dir, $maxSecs); + } else { + my ($t1, $p1) = ScanOutwards($key, $times, $points, $i, -1, $maxSecs); + my ($t2, $p2) = ScanOutwards($key, $times, $points, $i, 1, $maxSecs); + if (defined $t1) { + if (defined $t2) { + # both surrounding points are valid, so take the closest one + ($t, $p) = ($t - $t1 < $t2 - $t) ? ($t1, $p1) : ($t2, $p2); + } else { + ($t, $p) = ($t1, $p1); + } + } elsif (defined $t2) { + ($t, $p) = ($t2, $p2); + } + } + if (defined $p and $$et{OPTIONS}{Verbose} > 2) { + $et->VPrint(2, " Taking $key from fix:\n", PrintFix($points, $t)) + } + return $p; +} + +#------------------------------------------------------------------------------ +# Set new geotagging values according to date/time +# Inputs: 0) ExifTool object ref, 1) date/time value (or undef to delete tags) +# 2) optional write group +# Returns: error string, or '' on success +# Notes: Uses track data stored in ExifTool NEW_VALUE for Geotag tag +sub SetGeoValues($$;$) +{ + local $_; + my ($et, $val, $writeGroup) = @_; + my $geotag = $et->GetNewValue('Geotag'); + my $verbose = $et->Options('Verbose'); + my ($fix, $time, $fsec, $noDate, $secondTry, $iExt, $iDir); + + # remove date if none of our fixes had date information + $val =~ s/^\S+\s+// if $val and $geotag and not $$geotag{IsDate}; + + # maximum time (sec) from nearest GPS fix when position is still considered valid + my $geoMaxIntSecs = $et->Options('GeoMaxIntSecs'); + my $geoMaxExtSecs = $et->Options('GeoMaxExtSecs'); + + # use 30 minutes for a default + defined $geoMaxIntSecs or $geoMaxIntSecs = 1800; + defined $geoMaxExtSecs or $geoMaxExtSecs = 1800; + + my $times = $$geotag{Times}; + my $points = $$geotag{Points}; + my $has = $$geotag{Has}; + my $err = ''; + # loop to try date/time value first, then time-only value + while (defined $val) { + unless (defined $geotag) { + $err = 'No GPS track loaded'; + last; + } + unless ($times) { + # generate sorted timestamp list for binary search + my @times = sort { $a <=> $b } keys %$points; + $times = $$geotag{Times} = \@times; + } + unless ($times and @$times or $$geotag{DateTimeOnly}) { + $err = 'GPS track is empty'; + last; + } + unless (eval { require Time::Local }) { + $err = 'Geotag feature requires Time::Local installed'; + last; + } + # convert date/time to UTC + my ($year,$mon,$day,$hr,$min,$sec,$fs,$tz,$t0,$t1,$t2); + if ($val =~ /^(\d{4}):(\d+):(\d+)\s+(\d+):(\d+):(\d+)(\.\d*)?(Z|([-+])(\d+):(\d+))?/) { + # valid date/time value + ($year,$mon,$day,$hr,$min,$sec,$fs,$tz,$t0,$t1,$t2) = ($1,$2,$3,$4,$5,$6,$7,$8,$9,$10,$11); + } elsif ($val =~ /^(\d{2}):(\d+):(\d+)(\.\d*)?(Z|([-+])(\d+):(\d+))?/) { + # valid time-only value + ($hr,$min,$sec,$fs,$tz,$t0,$t1,$t2) = ($1,$2,$3,$4,$5,$6,$7,$8); + # use Jan. 2 to avoid going negative after tz adjustment + ($year,$mon,$day) = (1970,1,2); + $noDate = 1; + } else { + $err = 'Invalid date/time (use YYYY:mm:dd HH:MM:SS[.ss][+/-HH:MM|Z])'; + last; + } + if ($tz) { + $time = Time::Local::timegm($sec,$min,$hr,$day,$mon-1,$year-1900); + # use timezone from date/time value + if ($tz ne 'Z') { + my $tzmin = $t1 * 60 + $t2; + $time -= ($t0 eq '-' ? -$tzmin : $tzmin) * 60; + } + } else { + # assume local timezone + $time = Image::ExifTool::TimeLocal($sec,$min,$hr,$day,$mon-1,$year-1900); + } + # add fractional seconds + $time += $fs if $fs and $fs ne '.'; + + # bring UTC time back to Jan. 1 if no date is given + # (don't use '%' operator here because it drops fractional seconds) + $time -= int($time / $secPerDay) * $secPerDay if $noDate; + + # apply time synchronization if available + my $sync = ApplySyncCorr($et, $time); + + # save fractional seconds string + $fsec = ($time =~ /(\.\d+)$/) ? $1 : ''; + + if ($et->Options('Verbose') > 1 and not $secondTry) { + my $out = $et->Options('TextOut'); + my $str = ''; + $str .= sprintf(" (incl. Geosync offset of %+.3f sec)", $sync) if defined $sync; + unless ($tz) { + my $tzs = Image::ExifTool::TimeZoneString([$sec,$min,$hr,$day,$mon-1,$year-1900],$time); + $str .= " (local timezone is $tzs)"; + } + print $out ' Geotime value: ' . PrintFixTime($time) . "$str\n"; + } + if (not $times or not @$times) { + $fix = { }; # dummy fix to geotag date/time only + # interpolate GPS track at $time + } elsif ($time < $$times[0]) { + if ($time < $$times[0] - $geoMaxExtSecs) { + $err or $err = 'Time is too far before track'; + $et->VPrint(2, ' Track start: ', PrintFixTime($$times[0]), "\n") if $verbose > 2; + $fix = { } if $$geotag{DateTimeOnly}; + } else { + $fix = $$points{$$times[0]}; + $iExt = 0; $iDir = 1; + $et->VPrint(2, " Taking pos from fix:\n", + PrintFix($points, $$times[0])) if $verbose > 2; + } + } elsif ($time > $$times[-1]) { + if ($time > $$times[-1] + $geoMaxExtSecs) { + $err or $err = 'Time is too far beyond track'; + $et->VPrint(2, ' Track end: ', PrintFixTime($$times[-1]), "\n") if $verbose > 2; + $fix = { } if $$geotag{DateTimeOnly}; + } else { + $fix = $$points{$$times[-1]}; + $iExt = $#$times; $iDir = -1; + $et->VPrint(2, " Taking pos from fix:\n", + PrintFix($points, $$times[-1])) if $verbose > 2; + } + } else { + # find nearest 2 points in time + my ($i0, $i1) = (0, scalar(@$times) - 1); + while ($i1 > $i0 + 1) { + my $pt = int(($i0 + $i1) / 2); + ($time < $$times[$pt] ? $i1 : $i0) = $pt; + } + # do linear interpolation for position + my $t0 = $$times[$i0]; + my $t1 = $$times[$i1]; + my $p1 = $$points{$t1}; + # check to see if we are extrapolating before the first entry in a track + my $maxSecs = ($$p1{first} and $geoMaxIntSecs) ? $geoMaxExtSecs : $geoMaxIntSecs; + # don't interpolate if fixes are too far apart + # (but always interpolate fixes inside the same TimeSpan) + if ($t1 - $t0 > $maxSecs and (not $$p1{span} or not $$points{$t0}{span} or + $$p1{span} != $$points{$t0}{span})) + { + # treat as an extrapolation -- use nearest fix if close enough + my $tn; + if ($time - $t0 < $t1 - $time) { + $tn = $t0; + $iExt = $i0; + } else { + $tn = $t1; + $iExt = $i1; + } + if (abs($time - $tn) > $geoMaxExtSecs) { + $err or $err = 'Time is too far from nearest GPS fix'; + $et->VPrint(2, ' Nearest fix: ', PrintFixTime($tn), "\n") if $verbose > 2; + $fix = { } if $$geotag{DateTimeOnly}; + } else { + $fix = $$points{$tn}; + $et->VPrint(2, " Taking pos from fix:\n", + PrintFix($points, $tn)) if $verbose > 2; + } + } else { + my $f0 = $t1 == $t0 ? 0 : ($time - $t0) / ($t1 - $t0); + my $p0 = $$points{$t0}; + $et->VPrint(2, " Interpolating between fixes (f=$f0):\n", + PrintFix($points, $t0, $t1)) if $verbose > 2; + $fix = { }; + # loop through available fix information categories + # (pos, track, alt, orient) + my ($category, $key); +Category: foreach $category (qw{pos track alt orient atemp}) { + next unless $$has{$category}; + my ($f, $p0b, $p1b, $f0b); + # loop through specific fix information keys + # (lat, lon, alt, track, speed, dir, pitch, roll) + foreach $key (@{$fixInfoKeys{$category}}) { + my $v0 = $$p0{$key}; + my $v1 = $$p1{$key}; + if (defined $v0 and defined $v1) { + $f = $f0; + } elsif (defined $f0b) { + $v0 = $$p0b{$key}; + $v1 = $$p1b{$key}; + next unless defined $v0 and defined $v1; + $f = $f0b; + } else { + # scan outwards looking for fixes with the required information + # (NOTE: SHOULD EVENTUALLY DO THIS FOR EXTRAPOLATION TOO!) + my ($t0b, $t1b); + if (defined $v0) { + $t0b = $t0; $p0b = $p0; + } else { + ($t0b,$p0b,$v0) = ScanOutwards($key,$times,$points,$i0,-1,$maxSecs); + next Category unless defined $t0b; + } + if (defined $v1) { + $t1b = $t1; $p1b = $p1; + } else { + ($t1b,$p1b,$v1) = ScanOutwards($key,$times,$points,$i1,1,$maxSecs); + next Category unless defined $t1b; + } + # re-calculate the interpolation factor + $f = $f0b = $t1b == $t0b ? 0 : ($time - $t0b) / ($t1b - $t0b); + $et->VPrint(2, " Interpolating $category between fixes (f=$f):\n", + PrintFix($points, $t0b, $t1b)) if $verbose > 2; + } + # must interpolate cyclical values differently + if ($cyclical{$key} and abs($v1 - $v0) > 180) { + # the acute angle spans the discontinuity, so add + # 360 degrees to the smaller angle before interpolating + $v0 < $v1 ? $v0 += 360 : $v1 += 360; + $$fix{$key} = $v1 * $f + $v0 * (1 - $f); + # longitude and roll ranges are -180 to 180, others are 0 to 360 + my $max = ($key eq 'lon' or $key eq 'roll') ? 180 : 360; + $$fix{$key} -= 360 if $$fix{$key} >= $max; + } else { + # simple linear interpolation + $$fix{$key} = $v1 * $f + $v0 * (1 - $f); + } + } + } + } + } + if ($fix) { + $err = ''; # success! + } elsif ($$geotag{NoDate} and not $noDate and $val =~ s/^\S+\s+//) { + # try again with no date since some of our track points are date-less + $secondTry = 1; + next; + } + last; + } + if ($fix) { + my ($gpsDate, $gpsAlt, $gpsAltRef); + my @t = gmtime(int $time); + my $gpsTime = sprintf('%.2d:%.2d:%.2d', $t[2], $t[1], $t[0]) . $fsec; + # write GPSDateStamp if date included in track log, otherwise delete it + $gpsDate = sprintf('%.2d:%.2d:%.2d', $t[5]+1900, $t[4]+1, $t[3]) unless $noDate; + # write GPSAltitude tags if altitude included in track log, otherwise delete them + if (defined $$fix{alt}) { + $gpsAlt = abs $$fix{alt}; + $gpsAltRef = ($$fix{alt} < 0 ? 1 : 0); + } elsif ($$has{alt} and defined $iExt) { + my $tFix = FindFix($et,'alt',$times,$points,$iExt,$iDir,$geoMaxExtSecs); + if ($tFix) { + $gpsAlt = abs $$tFix{alt}; + $gpsAltRef = ($$tFix{alt} < 0 ? 1 : 0); + } + } + # set new GPS tag values (EXIF, or XMP if write group is 'xmp') + my ($xmp, $exif, @r); + my %opts = ( Type => 'ValueConv' ); # write ValueConv values + if ($writeGroup) { + $opts{Group} = $writeGroup; + $xmp = ($writeGroup =~ /xmp/i); + $exif = ($writeGroup =~ /^(exif|gps)$/i); + } + # (capture error messages by calling SetNewValue in list context) + @r = $et->SetNewValue(GPSLatitude => $$fix{lat}, %opts); + @r = $et->SetNewValue(GPSLongitude => $$fix{lon}, %opts); + @r = $et->SetNewValue(GPSAltitude => $gpsAlt, %opts); + @r = $et->SetNewValue(GPSAltitudeRef => $gpsAltRef, %opts); + if ($$has{track}) { + my $tFix = $fix; + if (not defined $$fix{track} and defined $iExt) { + my $p = FindFix($et,'track',$times,$points,$iExt,$iDir,$geoMaxExtSecs); + $tFix = $p if $p; + } + @r = $et->SetNewValue(GPSTrack => $$tFix{track}, %opts); + @r = $et->SetNewValue(GPSTrackRef => (defined $$tFix{track} ? 'T' : undef), %opts); + my ($spd, $ref); + if (defined($spd = $$tFix{speed})) { + $ref = $$et{OPTIONS}{GeoSpeedRef}; + if ($ref and defined $speedConv{$ref}) { + $ref = $speedConv{$ref} if $speedConv{$speedConv{$ref}}; + $spd *= $speedConv{$ref}; + } else { + $ref = 'N'; # knots by default + } + } + @r = $et->SetNewValue(GPSSpeed => $spd, %opts); + @r = $et->SetNewValue(GPSSpeedRef => $ref, %opts); + } + if ($$has{orient}) { + my $tFix = $fix; + if (not defined $$fix{dir} and defined $iExt) { + my $p = FindFix($et,'dir',$times,$points,$iExt,$iDir,$geoMaxExtSecs); + $tFix = $p if $p; + } + @r = $et->SetNewValue(GPSImgDirection => $$tFix{dir}, %opts); + @r = $et->SetNewValue(GPSImgDirectionRef => (defined $$tFix{dir} ? 'T' : undef), %opts); + # Note: GPSPitch and GPSRoll are non-standard, and must be user-defined + @r = $et->SetNewValue(GPSPitch => $$tFix{pitch}, %opts); + @r = $et->SetNewValue(GPSRoll => $$tFix{roll}, %opts); + } + if ($$has{atemp}) { + my $tFix = $fix; + if (not defined $$fix{atemp} and defined $iExt) { + # (not all fixes have atemp, so try interpolating specifically for this) + my $p = FindFix($et,'atemp',$times,$points,$iExt,$iDir,$geoMaxExtSecs); + $tFix = $p if $p; + } + @r = $et->SetNewValue(AmbientTemperature => $$tFix{atemp}, %opts); + } + unless ($xmp) { + my ($latRef, $lonRef); + $latRef = ($$fix{lat} > 0 ? 'N' : 'S') if defined $$fix{lat}; + $lonRef = ($$fix{lon} > 0 ? 'E' : 'W') if defined $$fix{lon}; + @r = $et->SetNewValue(GPSLatitudeRef => $latRef, %opts); + @r = $et->SetNewValue(GPSLongitudeRef => $lonRef, %opts); + @r = $et->SetNewValue(GPSDateStamp => $gpsDate, %opts); + @r = $et->SetNewValue(GPSTimeStamp => $gpsTime, %opts); + # set options to edit XMP:GPSDateTime only if it already exists + $opts{EditOnly} = 1; + $opts{Group} = 'XMP'; + } + unless ($exif) { + @r = $et->SetNewValue(GPSDateTime => "$gpsDate $gpsTime", %opts); + } + } else { + my %opts; + $opts{Replace} = 2 if defined $val; # remove existing new values + $opts{Group} = $writeGroup if $writeGroup; + + # reset any GPS values we might have already set + foreach (qw(GPSLatitude GPSLatitudeRef GPSLongitude GPSLongitudeRef + GPSAltitude GPSAltitudeRef GPSDateStamp GPSTimeStamp GPSDateTime + GPSTrack GPSTrackRef GPSSpeed GPSSpeedRef GPSImgDirection + GPSImgDirectionRef GPSPitch GPSRoll AmbientTemperature)) + { + my @r = $et->SetNewValue($_, undef, %opts); + } + } + return $err; +} + +#------------------------------------------------------------------------------ +# Convert Geotagging time synchronization value +# Inputs: 0) exiftool object ref, +# 1) time difference string ("[+-]DD MM:HH:SS.ss"), geosync'd file name, +# "GPSTIME@IMAGETIME", or "GPSTIME@FILENAME" +# Returns: geosync hash: +# Offset = Offset in seconds for latest synchronization (GPS - image time) +# Points = hash of all sync offsets keyed by image times in seconds +# Times = sorted list of image synchronization times (keys in Points hash) +# Notes: calling this routine with more than one geosync'd file causes time drift +# correction to be implemented +sub ConvertGeosync($$) +{ + my ($et, $val) = @_; + my $sync = $et->GetNewValue('Geosync') || { }; + my ($syncFile, $gpsTime, $imgTime); + + if ($val =~ /(.*?)\@(.*)/) { + $gpsTime = $1; + (-f $2 ? $syncFile : $imgTime) = $2; + # (take care because "-f '1:30'" crashes ActivePerl 5.10) + } elsif ($val !~ /^\d/ or $val !~ /:/) { + $syncFile = $val if -f $val; + } + if ($gpsTime or defined $syncFile) { + # (this is a time synchronization vector) + if (defined $syncFile) { + # check the following tags in order to obtain the image timestamp + my @timeTags = qw(SubSecDateTimeOriginal SubSecCreateDate SubSecModifyDate + DateTimeOriginal CreateDate ModifyDate FileModifyDate); + my $info = ImageInfo($syncFile, { PrintConv => 0 }, @timeTags, + 'GPSDateTime', 'GPSTimeStamp'); + $$info{Error} and warn("$$info{Err}\n"), return undef; + unless ($gpsTime) { + $gpsTime = $$info{GPSDateTime} || $$info{GPSTimeStamp}; + $gpsTime .= 'Z' if $gpsTime and not $$info{GPSDateTime}; + } + $gpsTime or warn("No GPSTimeStamp in '$syncFile\n"), return undef; + my $tag; + foreach $tag (@timeTags) { + if ($$info{$tag}) { + $imgTime = $$info{$tag}; + $et->VPrint(2, "Geosyncing with $tag from '${syncFile}'\n"); + last; + } + } + $imgTime or warn("No image timestamp in '${syncFile}'\n"), return undef; + } + # add date to date-less timestamps + my ($imgDateTime, $gpsDateTime, $noDate); + if ($imgTime =~ /^(\d+:\d+:\d+)\s+\d+/) { + $imgDateTime = $imgTime; + my $date = $1; + if ($gpsTime =~ /^\d+:\d+:\d+\s+\d+/) { + $gpsDateTime = $gpsTime; + } else { + $gpsDateTime = "$date $gpsTime"; + } + } elsif ($gpsTime =~ /^(\d+:\d+:\d+)\s+\d+/) { + $imgDateTime = "$1 $imgTime"; + $gpsDateTime = $gpsTime; + } else { + # use a today's date (so hopefully the DST setting will be intuitive) + my @tm = localtime; + my $date = sprintf('%.4d:%.2d:%.2d', $tm[5]+1900, $tm[4]+1, $tm[3]); + $gpsDateTime = "$date $gpsTime"; + $imgDateTime = "$date $imgTime"; + $noDate = 1; + } + # calculate Unix seconds since the epoch + my $imgSecs = Image::ExifTool::GetUnixTime($imgDateTime, 1); + defined $imgSecs or warn("Invalid image time '${imgTime}'\n"), return undef; + my $gpsSecs = Image::ExifTool::GetUnixTime($gpsDateTime, 1); + defined $gpsSecs or warn("Invalid GPS time '${gpsTime}'\n"), return undef; + # add fractional seconds + $gpsSecs += $1 if $gpsTime =~ /(\.\d+)/; + $imgSecs += $1 if $imgTime =~ /(\.\d+)/; + # shift dates within 12 hours of each other if either timestamp was date-less + if ($gpsDateTime ne $gpsTime or $imgDateTime ne $imgTime) { + my $diff = ($imgSecs - $gpsSecs) % (24 * 3600); + $diff -= 24 * 3600 if $diff > 12 * 3600; + $diff += 24 * 3600 if $diff < -12 * 3600; + if ($gpsDateTime ne $gpsTime) { + $gpsSecs = $imgSecs - $diff; + } else { + $imgSecs = $gpsSecs + $diff; + } + } + # save the synchronization offset + $$sync{Offset} = $gpsSecs - $imgSecs; + # save this synchronization point if either timestamp had a date + unless ($noDate) { + $$sync{Points} or $$sync{Points} = { }; + $$sync{Points}{$imgSecs} = $$sync{Offset}; + # print verbose output + if ($et->Options('Verbose') > 1) { + # print GPS and image timestamps in UTC + $et->VPrint(1, "Added Geosync point:\n", + ' GPS time stamp: ', PrintFixTime($gpsSecs), "\n", + ' Image date/time: ', PrintFixTime($imgSecs), "\n"); + } + # save sorted list of image sync times if we have more than one + my @times = keys %{$$sync{Points}}; + if (@times > 1) { + @times = sort { $a <=> $b } @times; + $$sync{Times} = \@times; + } + } + } else { + # (this is a simple time difference) + my @vals = $val =~ /(?=\d|\.\d)\d*(?:\.\d*)?/g; # (allow decimal values too) + @vals or warn("Invalid value (please refer to geotag documentation)\n"), return undef; + my $secs = 0; + my $mult; + foreach $mult (1, 60, 3600, $secPerDay) { + $secs += $mult * pop(@vals); + last unless @vals; + } + # set constant sync offset + $$sync{Offset} = $val =~ /^\s*-/ ? -$secs : $secs; + } + return $sync; +} + +#------------------------------------------------------------------------------ +# Print fix time +# Inputs: 0) time since the epoch +# Returns: UTC time string with fractional seconds +sub PrintFixTime($) +{ + my $time = $_[0] + 0.0005; # round off to nearest ms + my $fsec = int(($time - int($time)) * 1000); + return sprintf('%s.%.3d UTC', Image::ExifTool::ConvertUnixTime($time), $fsec); +} + +#------------------------------------------------------------------------------ +# Print fix information +# Inputs: 0) lookup for all fix points, 1-n) list of fix times +# Returns: fix string (including leading indent and trailing newline) +sub PrintFix($@) +{ + local $_; + my $points = shift; + my $str = ''; + while (@_) { + my $time = shift; + $str .= ' ' . PrintFixTime($time) . ' -'; + my $fix = $$points{$time}; + if ($fix) { + foreach (sort keys %$fix) { + $str .= " $_=$$fix{$_}" unless $_ eq 'time' or not defined $$fix{$_}; + } + } + $str .= "\n"; + } + return $str; +} + +#------------------------------------------------------------------------------ +1; # end + +__END__ + +=head1 NAME + +Image::ExifTool::Geotag - Geotagging utility routines + +=head1 SYNOPSIS + +This module is used by Image::ExifTool + +=head1 DESCRIPTION + +This module loads GPS track logs, interpolates to determine position based +on time, and sets new GPS values for geotagging images. Currently supported +formats are GPX, NMEA RMC/GGA/GLL, KML, IGC, Garmin XML and TCX, Magellan +PMGNTRK, Honeywell PTNTHPR, Winplus Beacon text, and Bramor gEO log files. + +Methods in this module should not be called directly. Instead, the Geotag +feature is accessed by writing the values of the ExifTool Geotag, Geosync +and Geotime tags (see the L<Extra Tags|Image::ExifTool::TagNames/Extra Tags> +in the tag name documentation). + +=head1 NOTES + +To take advantage of attitude information in the PTNTHPR NMEA sentence, two +user-defined tags, GPSPitch and GPSRoll, must be active. + +=head1 AUTHOR + +Copyright 2003-2019, Phil Harvey (phil at owl.phy.queensu.ca) + +This library is free software; you can redistribute it and/or modify it +under the same terms as Perl itself. + +=head1 REFERENCES + +=over 4 + +=item L<http://www.topografix.com/GPX/1/1/> + +=item L<http://www.gpsinformation.org/dale/nmea.htm#GSA> + +=item L<http://code.google.com/apis/kml/documentation/kmlreference.html> + +=item L<http://www.fai.org/gliding/system/files/tech_spec_gnss.pdf> + +=back + +=head1 ACKNOWLEDGEMENTS + +Thanks to Lionel Genet for the ability to read IGC format track logs. + +=head1 SEE ALSO + +L<Image::ExifTool::TagNames/Extra Tags>, +L<Image::ExifTool(3pm)|Image::ExifTool> + +=cut diff --git a/lib/Image/ExifTool/GoPro.pm b/lib/Image/ExifTool/GoPro.pm new file mode 100644 index 0000000..4e67941 --- /dev/null +++ b/lib/Image/ExifTool/GoPro.pm @@ -0,0 +1,709 @@ +#------------------------------------------------------------------------------ +# File: GoPro.pm +# +# Description: Read information from GoPro videos +# +# Revisions: 2018/01/12 - P. Harvey Created +# +# References: 1) https://github.com/gopro/gpmf-parser +# 2) https://github.com/stilldavid/gopro-utils +#------------------------------------------------------------------------------ + +package Image::ExifTool::GoPro; + +use strict; +use vars qw($VERSION); +use Image::ExifTool qw(:DataAccess :Utils); +use Image::ExifTool::QuickTime; + +$VERSION = '1.02'; + +sub ProcessGoPro($$$); +sub ProcessString($$$); +sub ScaleValues($$); +sub AddUnits($$$); +sub ConvertSystemTime($$); + +# GoPro data types that have ExifTool equivalents (ref 1) +my %goProFmt = ( # format codes + # 0x00 - container (subdirectory) + 0x62 => 'int8s', # 'b' + 0x42 => 'int8u', # 'B' + 0x63 => 'string', # 'c' (possibly null terminated) + 0x73 => 'int16s', # 's' + 0x53 => 'int16u', # 'S' + 0x6c => 'int32s', # 'l' + 0x4c => 'int32u', # 'L' + 0x66 => 'float', # 'f' + 0x64 => 'double', # 'd' + 0x46 => 'undef', # 'F' (4-char ID) + 0x47 => 'undef', # 'G' (16-byte uuid) + 0x6a => 'int64s', # 'j' + 0x4a => 'int64u', # 'J' + 0x71 => 'fixed32s', # 'q' + 0x51 => 'fixed64s', # 'Q' + 0x55 => 'undef', # 'U' (16-byte date) + 0x3f => 'undef', # '?' (complex structure) +); + +# sizes of format codes if different than what FormatSize() would return +my %goProSize = ( + 0x46 => 4, + 0x47 => 16, + 0x55 => 16, +); + +# tagInfo elements to add units to PrintConv value +my %addUnits = ( + AddUnits => 1, + PrintConv => 'Image::ExifTool::GoPro::AddUnits($self, $val, $tag)', +); + +# Tags found in the GPMF box of Hero6 mp4 videos (ref PH), and +# the gpmd-format timed metadata of Hero5 and Hero6 videos (ref 1) +%Image::ExifTool::GoPro::GPMF = ( + PROCESS_PROC => \&ProcessGoPro, + GROUPS => { 2 => 'Camera' }, + NOTES => q{ + Tags extracted from the GPMF box of GoPro MP4 videos, the APP6 "GoPro" segment + of JPEG files, and from the "gpmd" timed metadata if the ExtractEmbedded option + is enabled. Many more tags exist, but are currently unknown and extracted only + with the -u option. Please let me know if you discover the meaning of any of + these unknown tags. See L<https://github.com/gopro/gpmf-parser> for details + about this format. + }, + ACCL => { #2 (gpmd) + Name => 'Accelerometer', + Notes => 'accelerator readings in m/s', + Binary => 1, + }, + ALLD => 'AutoLowLightDuration', #1 (gpmd) (untested) + # APTO (GPMF) - seen: 'RAW' (fmt c) + ATTD => { #PH (Karma) + Name => 'Attitude', + # UNIT=s,rad,rad,rad,rad/s,rad/s,rad/s, + # TYPE=LffffffB + # SCAL=1000 1 1 1 1 1 1 1 + Binary => 1, + }, + ATTR => { #PH (Karma) + Name => 'AttitudeTarget', + # UNIT=s,rad,rad,rad, + # TYPE=Jffff + # SCAL=1000 1 1 1 1 + Binary => 1, + }, + AUDO => 'AudioSetting', #PH (GPMF - seen: 'WIND', fmt c) + # AUPT (GPMF) - seen: 'N' (fmt c) + BPOS => { #PH (Karma) + Name => 'Controller', + Unknown => 1, + # UNIT=deg,deg,m,deg,deg,m,m,m + # TYPE=lllfffff + # SCAL=10000000 10000000 1000 1 1 1 1 1 + %addUnits, + }, + # BRID (GPMF) - seen: 0 (fmt B) + # BROD (GPMF) - seen: 'ASK' (fmt c) + CASN => 'CameraSerialNumber', #PH (GPMF - seen: 'C3221324545448', fmt c) + # CINF (GPMF) - seen: 0x67376be7709bc8876a8baf3940908618 (fmt B) + # CMOD (GPMF) - seen: 12,13,17 [13 time-laps video, 17 JPEG] (fmt B) + CYTS => { #PH (Karma) + Name => 'CoyoteStatus', + # UNIT=s,,,,,rad,rad,rad,, + # TYPE=LLLLLfffBB + # SCAL=1000 1 1 1 1 1 1 1 1 1 + Binary => 1, + }, + CSEN => { #PH (Karma) + Name => 'CoyoteSense', + # UNIT=s,rad/s,rad/s,rad/s,g,g,g,,,, + # TYPE=LffffffLLLL + # SCAL=1000 1 1 1 1 1 1 1 1 1 1 + Binary => 1, + }, + DEVC => { #PH (gpmd,GPMF, fmt \0) + Name => 'DeviceContainer', + SubDirectory => { TagTable => 'Image::ExifTool::GoPro::GPMF' }, + }, + # DVID (GPMF) - DeviceID; seen: 1 (fmt L), HLMT (fmt F) + DVID => { Name => 'DeviceID', Unknown => 1 }, #2 (gpmd) + # DVNM (GPMF) seen: 'Video Global Settings' (fmt c), 'Highlights' (fmt c) + # DVNM (gpmd) seen: 'Camera' (Hero5), 'Hero6 Black' (Hero6), 'GoPro Karma v1.0' (Karma) + DVNM => 'DeviceName', #PH + DZOM => { #PH (GPMF - seen: 'Y', fmt c) + Name => 'DigitalZoom', + PrintConv => { N => 'No', Y => 'Yes' }, + }, + # DZST (GPMF) - seen: 0 (fmt L) (something to do with digital zoom maybe?) + # EISA (GPMF) - seen: 'Y','N' [N was for a time-lapse video] (fmt c) + # EISE (GPMF) - seen: 'Y' (fmt c) + EMPT => { Name => 'Empty', Unknown => 1 }, #2 (gpmd) + ESCS => { #PH (Karma) + Name => 'EscapeStatus', + # UNIT=s,rpm,rpm,rpm,rpm,rpm,rpm,rpm,rpm,degC,degC,degC,degC,V,V,V,V,A,A,A,A,,,,,,,,, + # TYPE=JSSSSSSSSssssSSSSSSSSSSSSSSSSB + # (no SCAL!) + Unknown => 1, + %addUnits, + }, + # EXPT (GPMF) - seen: '' (fmt c) + FACE => 'FaceDetected', #PH (gpmd) + FCNM => 'FaceNumbers', #PH (gpmd) (faces counted per frame, ref 1) + FMWR => 'FirmwareVersion', #PH (GPMF - seen: HD6.01.01.51.00, fmt c) + FWVS => 'OtherFirmware', #PH (NC) (gpmd - seen: '1.1.11.0', Karma) + GLPI => { #PH (gpmd, Karma) + Name => 'GPSPos', + # UNIT=s,deg,deg,m,m,m/s,m/s,m/s,deg + # TYPE=LllllsssS + # SCAL=1000 10000000 10000000 1000 1000 100 100 100 100 + RawConv => '$val', # necessary to use scaled value instead of raw data as subdir data + SubDirectory => { TagTable => 'Image::ExifTool::GoPro::GLPI' }, + }, + GPRI => { #PH (gpmd, Karma) + Name => 'GPSRaw', + # UNIT=s,deg,deg,m,m,m,m/s,deg,, + # TYPE=JlllSSSSBB + # SCAL=1000000,10000000,10000000,1000,100,100,100,100,1,1 + Unknown => 1, + RawConv => '$val', # necessary to use scaled value instead of raw data as subdir data + SubDirectory => { TagTable => 'Image::ExifTool::GoPro::GPRI' }, + }, + GPS5 => { #2 (gpmd) + Name => 'GPSInfo', + # SCAL=10000000,10000000,1000,1000,100 + RawConv => '$val', # necessary to use scaled value instead of raw data as subdir data + SubDirectory => { TagTable => 'Image::ExifTool::GoPro::GPS5' }, + }, + GPSF => { #2 (gpmd) + Name => 'GPSMeasureMode', + PrintConv => { + 2 => '2-Dimensional Measurement', + 3 => '3-Dimensional Measurement', + }, + }, + GPSP => { #2 (gpmd) + Name => 'GPSHPositioningError', + Description => 'GPS Horizontal Positioning Error', + ValueConv => '$val / 100', # convert from cm to m + }, + GPSU => { #2 (gpmd) + Name => 'GPSDateTime', + Groups => { 2 => 'Time' }, + # (HERO5 writes this in 'c' format, HERO6 writes 'U') + ValueConv => '$val =~ s/^(\d{2})(\d{2})(\d{2})(\d{2})(\d{2})/20$1:$2:$3 $4:$5:/; $val', + PrintConv => '$self->ConvertDateTime($val)', + }, + GYRO => { #2 (gpmd) + Name => 'Gyroscope', + Notes => 'gyroscope readings in rad/s', + Binary => 1, + }, + # HFLG (APP6) - seen: 0 + ISOE => 'ISOSpeeds', #PH (gpmd) + ISOG => { #2 (gpmd) + Name => 'ImageSensorGain', + Binary => 1, + }, + KBAT => { #PH (gpmd) (Karma) + Name => 'BatteryStatus', + # UNIT=A,Ah,J,degC,V,V,V,V,s,%,,,,,% + # TYPE=lLlsSSSSSSSBBBb + # SCAL=1000,1000,0.00999999977648258,100,1000,1000,1000,1000,0.0166666675359011,1,1,1,1,1,1 + RawConv => '$val', # necessary to use scaled value instead of raw data as subdir data + SubDirectory => { TagTable => 'Image::ExifTool::GoPro::KBAT' }, + }, + # LINF (GPMF) - seen: LAJ7061916601668 (fmt c) + LNED => { #PH (Karma) + Name => 'LocalPositionNED', + # UNIT=s,m,m,m,m/s,m/s,m/s + # TYPE=Lffffff + # SCAL=1000 1 1 1 1 1 1 + Binary => 1, + }, + MAGN => 'Magnetometer', #1 (gpmd) (units of uT) + MINF => { #PH (GPMF - seen: HERO6 Black, fmt c) + Name => 'Model', + Groups => { 2 => 'Camera' }, + Description => 'Camera Model Name', + }, + # MTYP (GPMF) - seen: 0,1,11 [1 for time-lapse video, 11 for JPEG] (fmt B) + # MUID (GPMF) - seen: 3882563431 2278071152 967805802 411471936 0 0 0 0 (fmt L) + OREN => { #PH (GPMF - seen: 'U', fmt c) + Name => 'AutoRotation', + PrintConv => { + U => 'Up', + D => 'Down', # (NC) + A => 'Auto', # (NC) + }, + }, + # (most of the "P" tags are ProTune settings - PH) + PHDR => 'HDRSetting', #PH (APP6 - seen: 0) + PIMN => 'AutoISOMin', #PH (GPMF - seen: 100, fmt L) + PIMX => 'AutoISOMax', #PH (GPMF - seen: 1600, fmt L) + # PRAW (APP6) - seen: 0 + PRES => 'PhotoResolution', #PH (APP6 - seen: '12MP_W') + PRTN => { #PH (GPMF - seen: 'N', fmt c) + Name => 'ProTune', + PrintConv => { + N => 'Off', + Y => 'On', # (NC) + }, + }, + PTCL => 'ColorMode', #PH (GPMF - seen: 'GOPRO', fmt c' APP6: 'FLAT') + PTEV => 'ExposureCompensation', #PH (GPMF - seen: '0.0', fmt c) + PTSH => 'Sharpness', #PH (GPMF - seen: 'HIGH', fmt c) + PTWB => 'WhiteBalance', #PH (GPMF - seen: 'AUTO', fmt c) + RATE => 'Rate', #PH (GPMF - seen: '0_5SEC', fmt c; APP6 - seen: '4_1SEC') + RMRK => { #2 (gpmd) + Name => 'Comments', + ValueConv => '$self->Decode($val, "Latin")', + }, + SCAL => { #2 (gpmd) scale factor for subsequent data + Name => 'ScaleFactor', + Unknown => 1, + }, + SCPR => { #PH (Karma) [stream was empty] + Name => 'ScaledPressure', + # UNIT=s,Pa,Pa,degC + # TYPE=Lffs + # SCAL=1000 0.00999999977648258 0.00999999977648258 100 + %addUnits, + }, + SHUT => { #2 (gpmd) + Name => 'ExposureTimes', + PrintConv => q{ + my @a = split ' ', $val; + $_ = Image::ExifTool::Exif::PrintExposureTime($_) foreach @a; + return join ' ', @a; + }, + }, + SIMU => { #PH (Karma) + Name => 'ScaledIMU', + # UNIT=s,g,g,g,rad/s,rad/s,rad/s,T,T,T + # TYPE=Lsssssssss + # SCAL=1000 1000 1000 1000 1000 1000 1000 1000 1000 1000 + %addUnits, + }, + SIUN => { #2 (gpmd - seen : 'm/s2','rad/s') + Name => 'SIUnits', + Unknown => 1, + ValueConv => '$self->Decode($val, "Latin")', + }, + # SMTR (GPMF) - seen: 'N' (fmt c) + STMP => { #1 (gpmd) + Name => 'TimeStamp', + ValueConv => '$val / 1e6', + }, + STRM => { #2 (gpmd,GPMF, fmt \0) + Name => 'NestedSignalStream', + SubDirectory => { TagTable => 'Image::ExifTool::GoPro::GPMF' }, + }, + STNM => { #2 (gpmd) + Name => 'StreamName', + Unknown => 1, + ValueConv => '$self->Decode($val, "Latin")', + }, + SYST => { #PH (Karma) + Name => 'SystemTime', + # UNIT=s,s + # TYPE=JJ + # SCAL=1000000 1000 + # save system time calibrations for later + RawConv => q{ + my @v = split ' ', $val; + if (@v == 2) { + my $s = $$self{SystemTimeList}; + $s or $s = $$self{SystemTimeList} = [ ]; + push @$s, \@v; + } + return $val; + }, + }, + # TICK => { Name => 'InTime', Unknown => 1, ValueConv => '$val/1000' }, #1 (gpmd) + TMPC => { #2 (gpmd) + Name => 'CameraTemperature', + PrintConv => '"$val C"', + }, + # TOCK => { Name => 'OutTime', Unknown => 1, ValueConv => '$val/1000' }, #1 (gpmd) + TSMP => { Name => 'TotalSamples', Unknown => 1 }, #2 (gpmd) + TYPE => { Name => 'StructureType', Unknown => 1 }, #2 (gpmd,GPMF - eg 'LLLllfFff', fmt c) + UNIT => { #2 (gpmd) alternative units + Name => 'Units', + Unknown => 1, + ValueConv => '$self->Decode($val, "Latin")', + }, + VFOV => { #PH (GPMF - seen: 'W', fmt c) + Name => 'FieldOfView', + PrintConv => { + W => 'Wide', + S => 'Super View', # (NC, not seen) + L => 'Linear', # (NC, not seen) + }, + }, + # VLTA (GPMF) - seen: 78 ('N') (fmt B -- wrong format?) + VFRH => { #PH (Karma) + Name => 'VisualFlightRulesHUD', + BinaryData => 1, + # UNIT=m/s,m/s,m,m/s,deg,% + # TYPE=ffffsS + }, + # VLTE (GPMF) - seen: 'Y' (fmt c) + WBAL => 'ColorTemperatures', #PH (gpmd) + WRGB => { #PH (gpmd) + Name => 'WhiteBalanceRGB', + Binary => 1, + }, +); + +# GoPro GPS5 tags (ref 2) (Hero5,Hero6) +%Image::ExifTool::GoPro::GPS5 = ( + PROCESS_PROC => \&ProcessString, + GROUPS => { 1 => 'GoPro', 2 => 'Location' }, + VARS => { HEX_ID => 0, ID_LABEL => 'Index' }, + 0 => { # (unit='deg') + Name => 'GPSLatitude', + PrintConv => 'Image::ExifTool::GPS::ToDMS($self, $val, 1, "N")', + }, + 1 => { # (unit='deg') + Name => 'GPSLongitude', + PrintConv => 'Image::ExifTool::GPS::ToDMS($self, $val, 1, "E")', + }, + 2 => { # (unit='m') + Name => 'GPSAltitude', + PrintConv => '"$val m"', + }, + 3 => 'GPSSpeed', # (unit='m/s') + 4 => 'GPSSpeed3D', # (unit='m/s') +); + +# GoPro GPRI tags (ref PH) (Karma) +%Image::ExifTool::GoPro::GPRI = ( + PROCESS_PROC => \&ProcessString, + GROUPS => { 1 => 'GoPro', 2 => 'Location' }, + VARS => { HEX_ID => 0, ID_LABEL => 'Index' }, + 0 => { # (unit='s') + Name => 'GPSDateTimeRaw', + Groups => { 2 => 'Time' }, + ValueConv => \&ConvertSystemTime, # convert to date/time based on SystemTime clock + PrintConv => '$self->ConvertDateTime($val)', + }, + 1 => { # (unit='deg') + Name => 'GPSLatitudeRaw', + PrintConv => 'Image::ExifTool::GPS::ToDMS($self, $val, 1, "N")', + }, + 2 => { # (unit='deg') + Name => 'GPSLongitudeRaw', + PrintConv => 'Image::ExifTool::GPS::ToDMS($self, $val, 1, "E")', + }, + 3 => { + Name => 'GPSAltitudeRaw', # (NC) + PrintConv => '"$val m"', + }, + # (unknown tags must be defined so that ProcessString() will iterate through all values) + 4 => { Name => 'GPRI_Unknown4', Unknown => 1, Hidden => 1, PrintConv => '"$val m"' }, + 5 => { Name => 'GPRI_Unknown5', Unknown => 1, Hidden => 1, PrintConv => '"$val m"' }, + 6 => 'GPSSpeedRaw', # (NC) # (unit='m/s' -- should convert to other units?) + 7 => 'GPSTrackRaw', # (NC) # (unit='deg') + 8 => { Name => 'GPRI_Unknown8', Unknown => 1, Hidden => 1 }, # (no units) + 9 => { Name => 'GPRI_Unknown9', Unknown => 1, Hidden => 1 }, # (no units) +); + +# GoPro GLPI tags (ref PH) (Karma) +%Image::ExifTool::GoPro::GLPI = ( + PROCESS_PROC => \&ProcessString, + GROUPS => { 1 => 'GoPro', 2 => 'Location' }, + VARS => { HEX_ID => 0, ID_LABEL => 'Index' }, + 0 => { # (unit='s') + Name => 'GPSDateTime', + Groups => { 2 => 'Time' }, + ValueConv => \&ConvertSystemTime, # convert to date/time based on SystemTime clock + PrintConv => '$self->ConvertDateTime($val)', + }, + 1 => { # (unit='deg') + Name => 'GPSLatitude', + PrintConv => 'Image::ExifTool::GPS::ToDMS($self, $val, 1, "N")', + }, + 2 => { # (unit='deg') + Name => 'GPSLongitude', + PrintConv => 'Image::ExifTool::GPS::ToDMS($self, $val, 1, "E")', + }, + 3 => { # (unit='m') + Name => 'GPSAltitude', # (NC) + PrintConv => '"$val m"', + }, + # (unknown tags must be defined so that ProcessString() will iterate through all values) + 4 => { Name => 'GLPI_Unknown4', Unknown => 1, Hidden => 1, PrintConv => '"$val m"' }, + 5 => { Name => 'GPSSpeedX', PrintConv => '"$val m/s"' }, # (NC) + 6 => { Name => 'GPSSpeedY', PrintConv => '"$val m/s"' }, # (NC) + 7 => { Name => 'GPSSpeedZ', PrintConv => '"$val m/s"' }, # (NC) + 8 => { Name => 'GPSTrack' }, # (unit='deg') +); + +# GoPro KBAT tags (ref PH) +%Image::ExifTool::GoPro::KBAT = ( + PROCESS_PROC => \&ProcessString, + GROUPS => { 1 => 'GoPro', 2 => 'Camera' }, + VARS => { HEX_ID => 0, ID_LABEL => 'Index' }, + NOTES => 'Battery status information found in GoPro Karma videos.', + 0 => { Name => 'BatteryCurrent', PrintConv => '"$val A"' }, + 1 => { Name => 'BatteryCapacity', PrintConv => '"$val Ah"' }, + 2 => { Name => 'KBAT_Unknown2', PrintConv => '"$val J"', Unknown => 1, Hidden => 1 }, + 3 => { Name => 'BatteryTemperature', PrintConv => '"$val C"' }, + 4 => { Name => 'BatteryVoltage1', PrintConv => '"$val V"' }, + 5 => { Name => 'BatteryVoltage2', PrintConv => '"$val V"' }, + 6 => { Name => 'BatteryVoltage3', PrintConv => '"$val V"' }, + 7 => { Name => 'BatteryVoltage4', PrintConv => '"$val V"' }, + 8 => { Name => 'BatteryTime', PrintConv => 'ConvertDuration(int($val + 0.5))' }, # (NC) + 9 => { Name => 'KBAT_Unknown9', PrintConv => '"$val %"', Unknown => 1, Hidden => 1, }, + 10 => { Name => 'KBAT_Unknown10', Unknown => 1, Hidden => 1 }, # (no units) + 11 => { Name => 'KBAT_Unknown11', Unknown => 1, Hidden => 1 }, # (no units) + 12 => { Name => 'KBAT_Unknown12', Unknown => 1, Hidden => 1 }, # (no units) + 13 => { Name => 'KBAT_Unknown13', Unknown => 1, Hidden => 1 }, # (no units) + 14 => { Name => 'BatteryLevel', PrintConv => '"$val %"' }, +); + +# GoPro fdsc tags written by the Hero5 and Hero6 (ref PH) +%Image::ExifTool::GoPro::fdsc = ( + GROUPS => { 2 => 'Camera' }, + PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData, + NOTES => q{ + Tags extracted from the MP4 "fdsc" timed metadata when the ExtractEmbedded + option is used. + }, + 0x08 => { Name => 'FirmwareVersion', Format => 'string[15]' }, + 0x17 => { Name => 'SerialNumber', Format => 'string[16]' }, + 0x57 => { Name => 'OtherSerialNumber', Format => 'string[15]' }, # (NC) + 0x66 => { + Name => 'Model', + Description => 'Camera Model Name', + Format => 'string[16]', + }, + # ... + # after this there are lots of interesting values also found in the GPMF box, + # but this block is lacking tag ID's and any directory structure, so the + # value offsets are therefore presumably firmware dependent :( +); + +#------------------------------------------------------------------------------ +# Convert system time to date/time string +# Inputs: 0) system time value, 1) ExifTool ref +# Returns: EXIF-format date/time string with milliseconds +sub ConvertSystemTime($$) +{ + my ($val, $et) = @_; + my $s = $$et{SystemTimeList} or return '<uncalibrated>'; + unless ($$et{SystemTimeListSorted}) { + $s = $$et{SystemTimeList} = [ sort { $$a[0] <=> $$b[0] } @$s ]; + $$et{SystemTimeListSorted} = 1; + } + my ($i, $j) = (0, $#$s); + # perform binary search to find this system time value + while ($j - $i > 1) { + my $t = int(($i + $j) / 2); + ($val < $$s[$t][0] ? $j : $i) = $t; + } + if ($i == $j or $$s[$j][0] == $$s[$i][0]) { + $val = $$s[$i][1]; + } else { + # interpolate between values + $val = $$s[$i][1] + ($$s[$j][1] - $$s[$i][1]) * ($val - $$s[$i][0]) / ($$s[$j][0] - $$s[$i][0]); + } + # (a bit tricky to remove fractional seconds then add them back again after + # the date/time conversion while avoiding round-off errors which could + # put the seconds out by 1...) + my ($t, $f) = ("$val" =~ /^(\d+)(\.\d+)/); + return Image::ExifTool::ConvertUnixTime($t, $$et{OPTIONS}{QuickTimeUTC}) . $f; +} + +#------------------------------------------------------------------------------ +# Scale values by last 'SCAL' constants +# Inputs: 0) value or list of values, 1) string of scale factors +# Returns: nothing, but updates values +sub ScaleValues($$) +{ + my ($val, $scl) = @_; + return unless $val and $scl; + my @scl = split ' ', $scl or return; + my @scaled; + my $v = (ref $val eq 'ARRAY') ? $val : [ $val ]; + foreach $val (@$v) { + my @a = split ' ', $val; + $a[$_] /= $scl[$_ % @scl] foreach 0..$#a; + push @scaled, join(' ', @a); + } + $_[0] = @scaled > 1 ? \@scaled : $scaled[0]; +} + +#------------------------------------------------------------------------------ +# Add units to values for human-readable output +# Inputs: 0) ExifTool ref, 1) value, 2) tag key +# Returns: converted value +sub AddUnits($$$) +{ + my ($et, $val, $tag) = @_; + if ($et and $$et{TAG_EXTRA}{$tag} and $$et{TAG_EXTRA}{$tag}{Units}) { + my $u = $$et{TAG_EXTRA}{$tag}{Units}; + $u = [ $u ] unless ref $u eq 'ARRAY'; + my @a = split ' ', $val; + if (@$u == @a) { + my $i; + for ($i=0; $i<@a; ++$i) { + $a[$i] .= ' ' . $$u[$i] if $$u[$i]; + } + $val = join ' ', @a; + } + } + return $val; +} + +#------------------------------------------------------------------------------ +# Process string of values (or array of strings) to extract as separate tags +# Inputs: 0) ExifTool object ref, 1) directory information ref, 2) tag table ref +# Returns: 1 on success +sub ProcessString($$$) +{ + my ($et, $dirInfo, $tagTablePtr) = @_; + my $dataPt = $$dirInfo{DataPt}; + my @list = ref $$dataPt eq 'ARRAY' ? @{$$dataPt} : ( $$dataPt ); + my ($string, $val); + $et->VerboseDir('GoPro structure'); + foreach $string (@list) { + my @val = split ' ', $string; + my $i = 0; + foreach $val (@val) { + $et->HandleTag($tagTablePtr, $i, $val); + $$tagTablePtr{++$i} or $i = 0; + } + } + return 1; +} + +#------------------------------------------------------------------------------ +# Process GoPro metadata (gpmd samples, GPMF box, or APP6) (ref PH/1/2) +# Inputs: 0) ExifTool object ref, 1) dirInfo ref, 2) tag table ref +# Returns: 1 on success +sub ProcessGoPro($$$) +{ + my ($et, $dirInfo, $tagTablePtr) = @_; + my $dataPt = $$dirInfo{DataPt}; + my $base = $$dirInfo{Base}; + my $pos = $$dirInfo{DirStart} || 0; + my $dirEnd = $pos + ($$dirInfo{DirLen} || (length($$dataPt) - $pos)); + my $verbose = $et->Options('Verbose'); + my $unknown = $verbose || $et->Options('Unknown'); + my ($size, $type, $unit, $scal, $setGroup0); + + $et->VerboseDir($$dirInfo{DirName} || 'GPMF', undef, $dirEnd-$pos) if $verbose; + if ($pos) { + my $parent = $$dirInfo{Parent}; + $setGroup0 = $$et{SET_GROUP0} = 'APP6' if $parent and $parent eq 'APP6'; + } else { + # set group0 to "QuickTime" unless group1 is being changed (to Track#) + $setGroup0 = $$et{SET_GROUP0} = 'QuickTime' unless $$et{SET_GROUP1}; + } + + for (; $pos+8<=$dirEnd; $pos+=($size+3)&0xfffffffc) { + my ($tag,$fmt,$len,$count) = unpack("x${pos}a4CCn", $$dataPt); + $size = $len * $count; + $pos += 8; + last if $pos + $size > $dirEnd; + my $tagInfo = $et->GetTagInfo($tagTablePtr, $tag); + last if $tag eq "\0\0\0\0"; # stop at null tag + next unless $size or $verbose; # don't save empty values unless verbose + my $format = $goProFmt{$fmt} || 'undef'; + my ($val, $i, $j, $p, @v); + if ($fmt eq 0x3f and defined $type) { + # decode structure with format given by previous 'TYPE' + for ($i=0; $i<$count; ++$i) { + my (@s, $l); + for ($j=0, $p=0; $j<length($type); ++$j, $p+=$l) { + my $b = Get8u(\$type, $j); + my $f = $goProFmt{$b} or last; + $l = $goProSize{$b} || Image::ExifTool::FormatSize($f) or last; + last if $p + $l > $len; + my $s = ReadValue($dataPt, $pos+$i*$len+$p, $f, undef, $l); + last unless defined $s; + push @s, $s; + } + push @v, join ' ', @s if @s; + } + $val = @v > 1 ? \@v : $v[0]; + } elsif (($format eq 'undef' or $format eq 'string') and $count > 1 and $len > 1) { + # unpack multiple undef/string values as a list + my $a = $format eq 'undef' ? 'a' : 'A'; + $val = [ unpack("x${pos}".("$a$len" x $count), $$dataPt) ]; + } else { + $val = ReadValue($dataPt, $pos, $format, undef, $size); + } + # save TYPE, UNIT/SIUN and SCAL values for later + $type = $val if $tag eq 'TYPE'; + $unit = $val if $tag eq 'UNIT' or $tag eq 'SIUN'; + $scal = $val if $tag eq 'SCAL'; + + unless ($tagInfo) { + next unless $unknown; + my $name = Image::ExifTool::QuickTime::PrintableTagID($tag); + $tagInfo = { Name => "GoPro_$name", Description => "GoPro $name", Unknown => 1 }; + $$tagInfo{SubDirectory} = { TagTable => 'Image::ExifTool::GoPro::GPMF' } if not $fmt; + AddTagToTable($tagTablePtr, $tag, $tagInfo); + } + # apply scaling if available to last tag in this container + ScaleValues($val, $scal) if $scal and $tag ne 'SCAL' and $pos+$size+3>=$dirEnd; + my $key = $et->HandleTag($tagTablePtr, $tag, $val, + DataPt => $dataPt, + Base => $base, + Start => $pos, + Size => $size, + TagInfo => $tagInfo, + Format => $format, + Extra => $verbose ? ", type='".($fmt ? chr($fmt) : '\0')."' size=$len count=$count" : undef, + ); + # save units for adding in print conversion if specified + $$et{TAG_EXTRA}{$key}{Units} = $unit if $$tagInfo{AddUnits} and $key; + } + delete $$et{SET_GROUP0} if $setGroup0; + return 1; +} + +1; # end + +__END__ + +=head1 NAME + +Image::ExifTool::GoPro - Read information from GoPro videos + +=head1 SYNOPSIS + +This module is used by Image::ExifTool + +=head1 DESCRIPTION + +This module contains definitions required by Image::ExifTool to decode +metadata from GoPro MP4 videos. + +=head1 AUTHOR + +Copyright 2003-2019, Phil Harvey (phil at owl.phy.queensu.ca) + +This library is free software; you can redistribute it and/or modify it +under the same terms as Perl itself. + +=head1 REFERENCES + +=over 4 + +=item L<https://github.com/gopro/gpmf-parser> + +=item L<https://github.com/stilldavid/gopro-utils> + +=back + +=head1 SEE ALSO + +L<Image::ExifTool::TagNames/GoPro Tags>, +L<Image::ExifTool(3pm)|Image::ExifTool> + +=cut + diff --git a/lib/Image/ExifTool/H264.pm b/lib/Image/ExifTool/H264.pm new file mode 100644 index 0000000..59a6a28 --- /dev/null +++ b/lib/Image/ExifTool/H264.pm @@ -0,0 +1,1134 @@ +#------------------------------------------------------------------------------ +# File: H264.pm +# +# Description: Read meta information from H.264 video +# +# Revisions: 2010/01/31 - P. Harvey Created +# +# References: 1) http://www.itu.int/rec/T-REC-H.264/e (T-REC-H.264-200305-S!!PDF-E.pdf) +# 2) http://miffteevee.co.uk/documentation/development/H264Parser_8cpp-source.html +# 3) http://ffmpeg.org/ +# 4) US Patent 2009/0052875 A1 +# 5) European Patent (EP2 051 528A1) application no. 07792522.0 filed 08.08.2007 +# 6) Dave Nicholson private communication +# 7) http://www.freepatentsonline.com/20050076039.pdf +# 8) Michael Reitinger private communication (RX100) +# +# Glossary: RBSP = Raw Byte Sequence Payload +#------------------------------------------------------------------------------ + +package Image::ExifTool::H264; + +use strict; +use vars qw($VERSION %convMake); +use Image::ExifTool qw(:DataAccess :Utils); +use Image::ExifTool::Exif; +use Image::ExifTool::GPS; + +$VERSION = '1.17'; + +sub ProcessSEI($$); + +my $parsePictureTiming; # flag to enable parsing of picture timing information (test only) + +# lookup for camera manufacturer name +%convMake = ( + 0x0103 => 'Panasonic', + 0x0108 => 'Sony', + 0x1011 => 'Canon', + 0x1104 => 'JVC', #Rob Lewis +); + +# information extracted from H.264 video streams +%Image::ExifTool::H264::Main = ( + GROUPS => { 2 => 'Video' }, + VARS => { NO_ID => 1 }, + NOTES => q{ + Tags extracted from H.264 video streams. The metadata for AVCHD videos is + stored in this stream. + }, + ImageWidth => { }, + ImageHeight => { }, + MDPM => { SubDirectory => { TagTable => 'Image::ExifTool::H264::MDPM' } }, +); + +# H.264 Supplemental Enhancement Information User Data (ref PH/4) +%Image::ExifTool::H264::MDPM = ( + GROUPS => { 2 => 'Camera' }, + PROCESS_PROC => \&ProcessSEI, + TAG_PREFIX => 'MDPM', + NOTES => q{ + The following tags are decoded from the Modified Digital Video Pack Metadata + (MDPM) of the unregistered user data with UUID + 17ee8c60f84d11d98cd60800200c9a66 in the H.264 Supplemental Enhancement + Information (SEI). I<[Yes, this description is confusing, but nothing + compared to the challenge of actually decoding the data!]> This information + may exist at regular intervals through the entire video, but only the first + occurrence is extracted unless the ExtractEmbedded (-ee) option is used (in + which case subsequent occurrences are extracted as sub-documents). + }, + # (Note: all these are explained in IEC 61834-4, but it costs money so it is useless to me) + # 0x00 - ControlCassetteID (ref 7) + # 0x01 - ControlTapeLength (ref 7) + # 0x02 - ControlTimerActDate (ref 7) + # 0x03 - ControlTimerACS_S_S (ref 7) + # 0x04-0x05 - ControlPR_StartPoint (ref 7) + # 0x06 - ControlTagIDNoGenre (ref 7) + # 0x07 - ControlTopicPageHeader (ref 7) + # 0x08 - ControlTextHeader (ref 7) + # 0x09 - ControlText (ref 7) + # 0x0a-0x0b - ControlTag (ref 7) + # 0x0c - ControlTeletextInfo (ref 7) + # 0x0d - ControlKey (ref 7) + # 0x0e-0x0f - ControlZoneEnd (ref 7) + # 0x10 - TitleTotalTime (ref 7) + # 0x11 - TitleRemainTime (ref 7) + # 0x12 - TitleChapterTotalNo (ref 7) + 0x13 => { + Name => 'TimeCode', + Notes => 'hours:minutes:seconds:frames', + ValueConv => 'sprintf("%.2x:%.2x:%.2x:%.2x",reverse unpack("C*",$val))', + }, + # 0x14 - TitleBinaryGroup + # 0x15 - TitleCassetteNo (ref 7) + # 0x16-0x17 - TitleSoftID (ref 7) + # (0x18,0x19 listed as TitleTextHeader/TitleText by ref 7) + 0x18 => { + Name => 'DateTimeOriginal', + Description => 'Date/Time Original', + Groups => { 2 => 'Time' }, + Notes => 'combined with tag 0x19', + Combine => 1, # the next tag (0x19) contains the rest of the date + # first byte is timezone information: + # 0x80 - unused + # 0x40 - DST flag + # 0x20 - TimeZoneSign + # 0x1e - TimeZoneValue + # 0x01 - half-hour flag + ValueConv => q{ + my ($tz, @a) = unpack('C*',$val); + return sprintf('%.2x%.2x:%.2x:%.2x %.2x:%.2x:%.2x%s%.2d:%s%s', @a, + $tz & 0x20 ? '-' : '+', ($tz >> 1) & 0x0f, + $tz & 0x01 ? '30' : '00', + $tz & 0x40 ? ' DST' : ''); + }, + PrintConv => '$self->ConvertDateTime($val)', + }, + # 0x1a-0x1b - TitleStart (ref 7) + # 0x1c-0x1d - TitleReelID (ref 7) + # 0x1e-0x1f - TitleEnd (ref 7) + # 0x20 - ChapterTotalTime (ref 7) + # 0x42 - ProgramRecDTime (ref 7) + # 0x50/0x60 - (AAUX/VAUX)Source (ref 7) + # 0x51/0x61 - (AAUX/VAUX)SourceControl (ref 7) + # 0x52/0x62 - (AAUX/VAUX)RecDate (ref 7) + # 0x53/0x63 - (AAUX/VAUX)RecTime (ref 7) + # 0x54/0x64 - (AAUX/VAUX)BinaryGroup (ref 7) + # 0x55/0x65 - (AAUX/VAUX)ClosedCaption (ref 7) + # 0x56/0x66 - (AAUX/VAUX)TR (ref 7) + 0x70 => { # ConsumerCamera1 + Name => 'Camera1', + SubDirectory => { TagTable => 'Image::ExifTool::H264::Camera1' }, + }, + 0x71 => { # ConsumerCamera2 + Name => 'Camera2', + SubDirectory => { TagTable => 'Image::ExifTool::H264::Camera2' }, + }, + # 0x73 Lens - val: 0x75ffffd3,0x0effffd3,0x59ffffd3,0x79ffffd3,0xffffffd3... + # 0x74 Gain + # 0x75 Pedestal + # 0x76 Gamma + # 0x77 Detail + # 0x7b CameraPreset + # 0x7c Flare + # 0x7d Shading + # 0x7e Knee + 0x7f => { # Shutter + Name => 'Shutter', + SubDirectory => { + TagTable => 'Image::ExifTool::H264::Shutter', + ByteOrder => 'LittleEndian', # weird + }, + }, + 0xa0 => { + Name => 'ExposureTime', + Format => 'rational32u', + Groups => { 2 => 'Image' }, + PrintConv => 'Image::ExifTool::Exif::PrintExposureTime($val)', + }, + 0xa1 => { + Name => 'FNumber', + Format => 'rational32u', + Groups => { 2 => 'Image' }, + }, + 0xa2 => { + Name => 'ExposureProgram', + Format => 'int32u', # (guess) + PrintConv => { + 0 => 'Not Defined', + 1 => 'Manual', + 2 => 'Program AE', + 3 => 'Aperture-priority AE', + 4 => 'Shutter speed priority AE', + 5 => 'Creative (Slow speed)', + 6 => 'Action (High speed)', + 7 => 'Portrait', + 8 => 'Landscape', + }, + }, + 0xa3 => { + Name => 'BrightnessValue', + Format => 'rational32s', + Groups => { 2 => 'Image' }, + }, + 0xa4 => { + Name => 'ExposureCompensation', + Format => 'rational32s', + Groups => { 2 => 'Image' }, + PrintConv => 'Image::ExifTool::Exif::PrintFraction($val)', + }, + 0xa5 => { + Name => 'MaxApertureValue', + Format => 'rational32u', + ValueConv => '2 ** ($val / 2)', + PrintConv => 'sprintf("%.1f",$val)', + }, + 0xa6 => { + Name => 'Flash', + Format => 'int32u', # (guess) + Flags => 'PrintHex', + SeparateTable => 'EXIF Flash', + PrintConv => \%Image::ExifTool::Exif::flash, + }, + 0xa7 => { + Name => 'CustomRendered', + Format => 'int32u', # (guess) + Groups => { 2 => 'Image' }, + PrintConv => { + 0 => 'Normal', + 1 => 'Custom', + }, + }, + 0xa8 => { + Name => 'WhiteBalance', + Format => 'int32u', # (guess) + Priority => 0, + PrintConv => { + 0 => 'Auto', + 1 => 'Manual', + }, + }, + 0xa9 => { + Name => 'FocalLengthIn35mmFormat', + Format => 'rational32u', + PrintConv => '"$val mm"', + }, + 0xaa => { + Name => 'SceneCaptureType', + Format => 'int32u', # (guess) + PrintConv => { + 0 => 'Standard', + 1 => 'Landscape', + 2 => 'Portrait', + 3 => 'Night', + }, + }, + # 0xab-0xaf ExifOption + 0xb0 => { + Name => 'GPSVersionID', + Format => 'int8u', + Count => 4, + Groups => { 1 => 'GPS', 2 => 'Location' }, + PrintConv => '$val =~ tr/ /./; $val', + }, + 0xb1 => { + Name => 'GPSLatitudeRef', + Format => 'string', + Groups => { 1 => 'GPS', 2 => 'Location' }, + PrintConv => { + N => 'North', + S => 'South', + }, + }, + 0xb2 => { + Name => 'GPSLatitude', + Format => 'rational32u', + Groups => { 1 => 'GPS', 2 => 'Location' }, + Notes => 'combined with tags 0xb3 and 0xb4', + Combine => 2, # combine the next 2 tags (0xb2=deg, 0xb3=min, 0xb4=sec) + ValueConv => 'Image::ExifTool::GPS::ToDegrees($val)', + PrintConv => 'Image::ExifTool::GPS::ToDMS($self, $val, 1)', + }, + 0xb5 => { + Name => 'GPSLongitudeRef', + Format => 'string', + Groups => { 1 => 'GPS', 2 => 'Location' }, + PrintConv => { + E => 'East', + W => 'West', + }, + }, + 0xb6 => { + Name => 'GPSLongitude', + Format => 'rational32u', + Groups => { 1 => 'GPS', 2 => 'Location' }, + Combine => 2, # combine the next 2 tags (0xb6=deg, 0xb7=min, 0xb8=sec) + Notes => 'combined with tags 0xb7 and 0xb8', + ValueConv => 'Image::ExifTool::GPS::ToDegrees($val)', + PrintConv => 'Image::ExifTool::GPS::ToDMS($self, $val, 1)', + }, + 0xb9 => { + Name => 'GPSAltitudeRef', + Format => 'int32u', # (guess) + Groups => { 1 => 'GPS', 2 => 'Location' }, + ValueConv => '$val ? 1 : 0', # because I'm not sure about the Format + PrintConv => { + 0 => 'Above Sea Level', + 1 => 'Below Sea Level', + }, + }, + 0xba => { + Name => 'GPSAltitude', + Format => 'rational32u', + Groups => { 1 => 'GPS', 2 => 'Location' }, + }, + 0xbb => { + Name => 'GPSTimeStamp', + Format => 'rational32u', + Groups => { 1 => 'GPS', 2 => 'Time' }, + Combine => 2, # the next tags (0xbc/0xbd) contain the minutes/seconds + Notes => 'combined with tags 0xbc and 0xbd', + ValueConv => 'Image::ExifTool::GPS::ConvertTimeStamp($val)', + PrintConv => 'Image::ExifTool::GPS::PrintTimeStamp($val)', + }, + 0xbe => { + Name => 'GPSStatus', + Format => 'string', + Groups => { 1 => 'GPS', 2 => 'Location' }, + PrintConv => { + A => 'Measurement Active', + V => 'Measurement Void', + }, + }, + 0xbf => { + Name => 'GPSMeasureMode', + Format => 'string', + Groups => { 1 => 'GPS', 2 => 'Location' }, + PrintConv => { + 2 => '2-Dimensional Measurement', + 3 => '3-Dimensional Measurement', + }, + }, + 0xc0 => { + Name => 'GPSDOP', + Description => 'GPS Dilution Of Precision', + Format => 'rational32u', + Groups => { 1 => 'GPS', 2 => 'Location' }, + }, + 0xc1 => { + Name => 'GPSSpeedRef', + Format => 'string', + Groups => { 1 => 'GPS', 2 => 'Location' }, + PrintConv => { + K => 'km/h', + M => 'mph', + N => 'knots', + }, + }, + 0xc2 => { + Name => 'GPSSpeed', + Format => 'rational32u', + Groups => { 1 => 'GPS', 2 => 'Location' }, + }, + 0xc3 => { + Name => 'GPSTrackRef', + Format => 'string', + Groups => { 1 => 'GPS', 2 => 'Location' }, + PrintConv => { + M => 'Magnetic North', + T => 'True North', + }, + }, + 0xc4 => { + Name => 'GPSTrack', + Format => 'rational32u', + Groups => { 1 => 'GPS', 2 => 'Location' }, + }, + 0xc5 => { + Name => 'GPSImgDirectionRef', + Format => 'string', + Groups => { 1 => 'GPS', 2 => 'Location' }, + PrintConv => { + M => 'Magnetic North', + T => 'True North', + }, + }, + 0xc6 => { + Name => 'GPSImgDirection', + Format => 'rational32u', + Groups => { 1 => 'GPS', 2 => 'Location' }, + }, + 0xc7 => { + Name => 'GPSMapDatum', + Format => 'string', + Groups => { 1 => 'GPS', 2 => 'Location' }, + Combine => 1, # the next tag (0xc8) contains the rest of the string + Notes => 'combined with tag 0xc8', + }, + # 0xc9-0xcf - GPSOption + 0xe0 => { + Name => 'MakeModel', + SubDirectory => { TagTable => 'Image::ExifTool::H264::MakeModel' }, + }, + # 0xe1-0xef - MakerOption + # 0xe1 - val: 0x01000670,0x01000678,0x06ffffff,0x01ffffff,0x01000020,0x01000400... + # 0xe2-0xe8 - val: 0x00000000 in many samples + 0xe1 => { #6 + Name => 'RecInfo', + Condition => '$$self{Make} eq "Canon"', + Notes => 'Canon only', + SubDirectory => { TagTable => 'Image::ExifTool::H264::RecInfo' }, + }, + 0xe4 => { #PH + Name => 'Model', + Condition => '$$self{Make} eq "Sony"', # (possibly also Canon models?) + Description => 'Camera Model Name', + Notes => 'Sony cameras only, combined with tags 0xe5 and 0xe6', + Format => 'string', + Combine => 2, # (not sure about 0xe6, but include it just in case) + RawConv => '$val eq "" ? undef : $val', + }, + 0xee => { #6 (HFS200) + Name => 'FrameInfo', + Condition => '$$self{Make} eq "Canon"', + Notes => 'Canon only', + SubDirectory => { TagTable => 'Image::ExifTool::H264::FrameInfo' }, + }, +); + +# ConsumerCamera1 information (ref PH) +%Image::ExifTool::H264::Camera1 = ( + PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData, + GROUPS => { 2 => 'Camera' }, + TAG_PREFIX => 'Camera1', + PRINT_CONV => 'sprintf("0x%.2x",$val)', + FIRST_ENTRY => 0, + 0 => { + Name => 'ApertureSetting', + PrintHex => 1, + PrintConv => { + 0xff => 'Auto', + 0xfe => 'Closed', + OTHER => sub { sprintf('%.1f', 2 ** (($_[0] & 0x3f) / 8)) }, + }, + }, + 1 => { + Name => 'Gain', + Mask => 0x0f, + # (0x0f would translate to 42 dB, but this value is used by the Sony + # HXR-NX5U for any out-of-range value such as -6 dB or "hyper gain" - PH) + ValueConv => '($val - 1) * 3', + PrintConv => '$val==42 ? "Out of range" : "$val dB"', + }, + 1.1 => { + Name => 'ExposureProgram', + Mask => 0xf0, + ValueConv => '$val == 15 ? undef : $val', + PrintConv => { + 0 => 'Program AE', + 1 => 'Gain', #? + 2 => 'Shutter speed priority AE', + 3 => 'Aperture-priority AE', + 4 => 'Manual', + }, + }, + 2.1 => { + Name => 'WhiteBalance', + Mask => 0xe0, + ValueConv => '$val == 7 ? undef : $val', + PrintConv => { + 0 => 'Auto', + 1 => 'Hold', + 2 => '1-Push', + 3 => 'Daylight', + }, + }, + 3 => { + Name => 'Focus', + ValueConv => '$val == 0xff ? undef : $val', + PrintConv => q{ + my $foc = ($val & 0x7e) / (($val & 0x01) ? 40 : 400); + return ($val & 0x80 ? 'Manual' : 'Auto') . " ($foc)"; + }, + }, +); + +# ConsumerCamera2 information (ref PH) +%Image::ExifTool::H264::Camera2 = ( + PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData, + GROUPS => { 2 => 'Camera' }, + TAG_PREFIX => 'Camera2', + PRINT_CONV => 'sprintf("0x%.2x",$val)', + FIRST_ENTRY => 0, + 1 => { + Name => 'ImageStabilization', + PrintHex => 1, + PrintConv => { + 0 => 'Off', + 0x3f => 'On (0x3f)', #8 + 0xbf => 'Off (0xbf)', #8 + 0xff => 'n/a', + OTHER => sub { + my $val = shift; + sprintf("%s (0x%.2x)", $val & 0x10 ? "On" : "Off", $val); + }, + }, + }, +); + +# camera info 0x7f (ref PH) +%Image::ExifTool::H264::Shutter = ( + PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData, + GROUPS => { 2 => 'Image' }, + TAG_PREFIX => 'Shutter', + PRINT_CONV => 'sprintf("0x%.2x",$val)', + FIRST_ENTRY => 0, + FORMAT => 'int16u', + 1.1 => { #6 + Name => 'ExposureTime', + Mask => 0x7fff, # (what is bit 0x8000 for?) + RawConv => '$val == 0x7fff ? undef : $val', #7 + ValueConv => '$val / 28125', #PH (Vixia HF G30, ref forum5588) (was $val/33640 until 9.49) + PrintConv => 'Image::ExifTool::Exif::PrintExposureTime($val)', + }, +); + +# camera info 0xe0 (ref PH) +%Image::ExifTool::H264::MakeModel = ( + PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData, + GROUPS => { 2 => 'Camera' }, + FORMAT => 'int16u', + FIRST_ENTRY => 0, + 0 => { + Name => 'Make', + PrintHex => 1, + RawConv => '$$self{Make} = ($Image::ExifTool::H264::convMake{$val} || "Unknown"); $val', + PrintConv => \%convMake, + }, + # 1 => ModelIDCode according to ref 4/5 (I think not - PH) + # 1 => { Name => 'ModelIDCode', PrintConv => 'sprintf("%.4x",$val)' }, + # vals: 0x0313 - various Pansonic HDC models + # 0x0345 - Panasonic HC-V7272 + # 0x0414 - Panasonic AG-AF100 + # 0x0591 - various Panasonic DMC models + # 0x0802 - Panasonic DMC-TZ60 with GPS information off + # 0x0803 - Panasonic DMC-TZ60 with GPS information on + # 0x3001 - various Sony DSC, HDR, NEX and SLT models + # 0x3003 - various Sony DSC models + # 0x3100 - various Sony DSC, ILCE, NEX and SLT models + # 0x1000 - Sony HDR-UX1 + # 0x2000 - Canon HF100 (60i) + # 0x3000 - Canon HF100 (30p) + # 0x3101 - Canon HFM300 (PH, all qualities and frame rates) + # 0x3102 - Canon HFS200 + # 0x4300 - Canon HFG30 +); + +# camera info 0xe1 (ref 6) +%Image::ExifTool::H264::RecInfo = ( + PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData, + GROUPS => { 2 => 'Camera' }, + FORMAT => 'int8u', + NOTES => 'Recording information stored by some Canon video cameras.', + FIRST_ENTRY => 0, + 0 => { + Name => 'RecordingMode', + PrintConv => { + 0x02 => 'XP+', # High Quality 12 Mbps + 0x04 => 'SP', # Standard Play 7 Mbps + 0x05 => 'LP', # Long Play 5 Mbps + 0x06 => 'FXP', # High Quality 17 Mbps + 0x07 => 'MXP', # High Quality 24 Mbps + }, + }, +); + +# camera info 0xee (ref 6) +%Image::ExifTool::H264::FrameInfo = ( + PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData, + GROUPS => { 2 => 'Video' }, + FORMAT => 'int8u', + NOTES => 'Frame rate information stored by some Canon video cameras.', + FIRST_ENTRY => 0, + 0 => 'CaptureFrameRate', + 1 => 'VideoFrameRate', + # 2 - 8=60i, 10=PF30, 74=PF24 (PH, HFM300) +); + +#============================================================================== +# Bitstream functions (used for H264 video) +# +# Member variables: +# Mask = mask for next bit to read (0 when all data has been read) +# Pos = byte offset of next word to read +# Word = current data word +# Len = total data length in bytes +# DataPt = data pointer +#.............................................................................. + +#------------------------------------------------------------------------------ +# Read next word from bitstream +# Inputs: 0) BitStream ref +# Returns: true if there is more data (and updates +# Mask, Pos and Word for first bit in next word) +sub ReadNextWord($) +{ + my $bstr = shift; + my $pos = $$bstr{Pos}; + if ($pos + 4 <= $$bstr{Len}) { + $$bstr{Word} = unpack("x$pos N", ${$$bstr{DataPt}}); + $$bstr{Mask} = 0x80000000; + $$bstr{Pos} += 4; + } elsif ($pos < $$bstr{Len}) { + my @bytes = unpack("x$pos C*", ${$$bstr{DataPt}}); + my ($word, $mask) = (shift(@bytes), 0x80); + while (@bytes) { + $word = ($word << 8) | shift(@bytes); + $mask <<= 8; + } + $$bstr{Word} = $word; + $$bstr{Mask} = $mask; + $$bstr{Pos} = $$bstr{Len}; + } else { + return 0; + } + return 1; +} + +#------------------------------------------------------------------------------ +# Create a new BitStream object +# Inputs: 0) data ref +# Returns: BitStream ref, or null if data is empty +sub NewBitStream($) +{ + my $dataPt = shift; + my $bstr = { + DataPt => $dataPt, + Len => length($$dataPt), + Pos => 0, + Mask => 0, + }; + ReadNextWord($bstr) or undef $bstr; + return $bstr; +} + +#------------------------------------------------------------------------------ +# Get number of bits remaining in bit stream +# Inputs: 0) BitStream ref +# Returns: number of bits remaining +sub BitsLeft($) +{ + my $bstr = shift; + my $bits = 0; + my $mask = $$bstr{Mask}; + while ($mask) { + ++$bits; + $mask >>= 1; + } + return $bits + 8 * ($$bstr{Len} - $$bstr{Pos}); +} + +#------------------------------------------------------------------------------ +# Get integer from bitstream +# Inputs: 0) BitStream ref, 1) number of bits +# Returns: integer (and increments position in bitstream) +sub GetIntN($$) +{ + my ($bstr, $bits) = @_; + my $val = 0; + while ($bits--) { + $val <<= 1; + ++$val if $$bstr{Mask} & $$bstr{Word}; + $$bstr{Mask} >>= 1 and next; + ReadNextWord($bstr) or last; + } + return $val; +} + +#------------------------------------------------------------------------------ +# Get Exp-Golomb integer from bitstream +# Inputs: 0) BitStream ref +# Returns: integer (and increments position in bitstream) +sub GetGolomb($) +{ + my $bstr = shift; + # first, count the number of zero bits to get the integer bit width + my $count = 0; + until ($$bstr{Mask} & $$bstr{Word}) { + ++$count; + $$bstr{Mask} >>= 1 and next; + ReadNextWord($bstr) or last; + } + # then return the adjusted integer + return GetIntN($bstr, $count + 1) - 1; +} + +#------------------------------------------------------------------------------ +# Get signed Exp-Golomb integer from bitstream +# Inputs: 0) BitStream ref +# Returns: integer (and increments position in bitstream) +sub GetGolombS($) +{ + my $bstr = shift; + my $val = GetGolomb($bstr) + 1; + return ($val & 1) ? -($val >> 1) : ($val >> 1); +} + +# end bitstream functions +#============================================================================== + +#------------------------------------------------------------------------------ +# Decode H.264 scaling matrices +# Inputs: 0) BitStream ref +# Reference: http://ffmpeg.org/ +sub DecodeScalingMatrices($) +{ + my $bstr = shift; + if (GetIntN($bstr, 1)) { + my ($i, $j); + for ($i=0; $i<8; ++$i) { + my $size = $i<6 ? 16 : 64; + next unless GetIntN($bstr, 1); + my ($last, $next) = (8, 8); + for ($j=0; $j<$size; ++$j) { + $next = ($last + GetGolombS($bstr)) & 0xff if $next; + last unless $j or $next; + } + } + } +} + +#------------------------------------------------------------------------------ +# Parse H.264 sequence parameter set RBSP (ref 1) +# Inputs: 0) ExifTool ref, 1) tag table ref, 2) data ref +# Notes: All this just to get the image size! +sub ParseSeqParamSet($$$) +{ + my ($et, $tagTablePtr, $dataPt) = @_; + # initialize our bitstream object + my $bstr = NewBitStream($dataPt) or return; + my ($t, $i, $j, $n); + # the messy nature of H.264 encoding makes it difficult to use + # data-driven structure parsing, so I code it explicitly (yuck!) + $t = GetIntN($bstr, 8); # profile_idc + GetIntN($bstr, 16); # constraints and level_idc + GetGolomb($bstr); # seq_parameter_set_id + if ($t >= 100) { # (ref b) + $t = GetGolomb($bstr); # chroma_format_idc + if ($t == 3) { + GetIntN($bstr, 1); # separate_colour_plane_flag + $n = 12; + } else { + $n = 8; + } + GetGolomb($bstr); # bit_depth_luma_minus8 + GetGolomb($bstr); # bit_depth_chroma_minus8 + GetIntN($bstr, 1); # qpprime_y_zero_transform_bypass_flag + DecodeScalingMatrices($bstr); + } + GetGolomb($bstr); # log2_max_frame_num_minus4 + $t = GetGolomb($bstr); # pic_order_cnt_type + if ($t == 0) { + GetGolomb($bstr); # log2_max_pic_order_cnt_lsb_minus4 + } elsif ($t == 1) { + GetIntN($bstr, 1); # delta_pic_order_always_zero_flag + GetGolomb($bstr); # offset_for_non_ref_pic + GetGolomb($bstr); # offset_for_top_to_bottom_field + $n = GetGolomb($bstr); # num_ref_frames_in_pic_order_cnt_cycle + for ($i=0; $i<$n; ++$i) { + GetGolomb($bstr); # offset_for_ref_frame[i] + } + } + GetGolomb($bstr); # num_ref_frames + GetIntN($bstr, 1); # gaps_in_frame_num_value_allowed_flag + my $w = GetGolomb($bstr); # pic_width_in_mbs_minus1 + my $h = GetGolomb($bstr); # pic_height_in_map_units_minus1 + my $f = GetIntN($bstr, 1); # frame_mbs_only_flag + $f or GetIntN($bstr, 1); # mb_adaptive_frame_field_flag + GetIntN($bstr, 1); # direct_8x8_inference_flag + # convert image size to pixels + $w = ($w + 1) * 16; + $h = (2 - $f) * ($h + 1) * 16; + # account for cropping (if any) + $t = GetIntN($bstr, 1); # frame_cropping_flag + if ($t) { + my $m = 4 - $f * 2; + $w -= 4 * GetGolomb($bstr);# frame_crop_left_offset + $w -= 4 * GetGolomb($bstr);# frame_crop_right_offset + $h -= $m * GetGolomb($bstr);# frame_crop_top_offset + $h -= $m * GetGolomb($bstr);# frame_crop_bottom_offset + } + # quick validity checks (just in case) + return unless $$bstr{Mask}; + if ($w>=160 and $w<=4096 and $h>=120 and $h<=3072) { + $et->HandleTag($tagTablePtr, ImageWidth => $w); + $et->HandleTag($tagTablePtr, ImageHeight => $h); + # (whew! -- so much work just to get ImageSize!!) + } + # return now unless interested in picture timing information + return unless $parsePictureTiming; + + # parse vui parameters if they exist + GetIntN($bstr, 1) or return; # vui_parameters_present_flag + $t = GetIntN($bstr, 1); # aspect_ratio_info_present_flag + if ($t) { + $t = GetIntN($bstr, 8); # aspect_ratio_idc + if ($t == 255) { # Extended_SAR ? + GetIntN($bstr, 32); # sar_width/sar_height + } + } + $t = GetIntN($bstr, 1); # overscan_info_present_flag + GetIntN($bstr, 1) if $t; # overscan_appropriate_flag + $t = GetIntN($bstr, 1); # video_signal_type_present_flag + if ($t) { + GetIntN($bstr, 4); # video_format/video_full_range_flag + $t = GetIntN($bstr, 1); # colour_description_present_flag + GetIntN($bstr, 24) if $t; # colour_primaries/transfer_characteristics/matrix_coefficients + } + $t = GetIntN($bstr, 1); # chroma_loc_info_present_flag + if ($t) { + GetGolomb($bstr); # chroma_sample_loc_type_top_field + GetGolomb($bstr); # chroma_sample_loc_type_bottom_field + } + $t = GetIntN($bstr, 1); # timing_info_present_flag + if ($t) { + return if BitsLeft($bstr) < 65; + $$et{VUI_units} = GetIntN($bstr, 32); # num_units_in_tick + $$et{VUI_scale} = GetIntN($bstr, 32); # time_scale + GetIntN($bstr, 1); # fixed_frame_rate_flag + } + my $hard; + for ($j=0; $j<2; ++$j) { + $t = GetIntN($bstr, 1); # nal_/vcl_hrd_parameters_present_flag + if ($t) { + $$et{VUI_hard} = 1; + $hard = 1; + $n = GetGolomb($bstr); # cpb_cnt_minus1 + GetIntN($bstr, 8); # bit_rate_scale/cpb_size_scale + for ($i=0; $i<=$n; ++$i) { + GetGolomb($bstr); # bit_rate_value_minus1[SchedSelIdx] + GetGolomb($bstr); # cpb_size_value_minus1[SchedSelIdx] + GetIntN($bstr, 1); # cbr_flag[SchedSelIdx] + } + GetIntN($bstr, 5); # initial_cpb_removal_delay_length_minus1 + $$et{VUI_clen} = GetIntN($bstr, 5); # cpb_removal_delay_length_minus1 + $$et{VUI_dlen} = GetIntN($bstr, 5); # dpb_output_delay_length_minus1 + $$et{VUI_toff} = GetIntN($bstr, 5); # time_offset_length + } + } + GetIntN($bstr, 1) if $hard; # low_delay_hrd_flag + $$et{VUI_pic} = GetIntN($bstr, 1); # pic_struct_present_flag + # (don't yet decode the rest of the vui data) +} + +#------------------------------------------------------------------------------ +# Parse H.264 picture timing SEI message (payload type 1) (ref 1) +# Inputs: 0) ExifTool ref, 1) data ref +# Notes: this routine is for test purposes only, and not called unless the +# $parsePictureTiming flag is set +sub ParsePictureTiming($$) +{ + my ($et, $dataPt) = @_; + my $bstr = NewBitStream($dataPt) or return; + my ($i, $t, $n); + # the specification is very odd on this point: the following delays + # exist if the VUI hardware parameters are present, or if + # "determined by the application, by some means not specified" -- WTF?? + if ($$et{VUI_hard}) { + GetIntN($bstr, $$et{VUI_clen} + 1); # cpb_removal_delay + GetIntN($bstr, $$et{VUI_dlen} + 1); # dpb_output_delay + } + if ($$et{VUI_pic}) { + $t = GetIntN($bstr, 4); # pic_struct + # determine NumClockTS ($n) + $n = { 0=>1, 1=>1, 2=>1, 3=>2, 4=>2, 5=>3, 6=>3, 7=>2, 8=>3 }->{$t}; + $n or return; + for ($i=0; $i<$n; ++$i) { + $t = GetIntN($bstr, 1); # clock_timestamp_flag[i] + next unless $t; + my ($nu, $s, $m, $h, $o); + GetIntN($bstr, 2); # ct_type + $nu = GetIntN($bstr, 1);# nuit_field_based_flag + GetIntN($bstr, 5); # counting_type + $t = GetIntN($bstr, 1); # full_timestamp_flag + GetIntN($bstr, 1); # discontinuity_flag + GetIntN($bstr, 1); # cnt_dropped_flag + GetIntN($bstr, 8); # n_frames + if ($t) { + $s = GetIntN($bstr, 6); # seconds_value + $m = GetIntN($bstr, 6); # minutes_value + $h = GetIntN($bstr, 5); # hours_value + } else { + $t = GetIntN($bstr, 1); # seconds_flag + if ($t) { + $s = GetIntN($bstr, 6); # seconds_value + $t = GetIntN($bstr, 1); # minutes_flag + if ($t) { + $m = GetIntN($bstr, 6); # minutes_value + $t = GetIntN($bstr, 1); # hours_flag + $h = GetIntN($bstr, 5) if $t; # hours_value + } + } + } + if ($$et{VUI_toff}) { + $o = GetIntN($bstr, $$et{VUI_toff}); # time_offset + } + last; # only parse the first clock timestamp found + } + } +} + +#------------------------------------------------------------------------------ +# Process H.264 Supplementary Enhancement Information (ref 1/PH) +# Inputs: 0) Exiftool ref, 1) dirInfo ref, 2) tag table ref +# Returns: 1 if we processed payload type 5 +# Payload types: +# 0 - buffer period +# 1 - pic timing +# 2 - pan scan rect +# 3 - filler payload +# 4 - user data registered itu t t35 +# 5 - user data unregistered +# 6 - recovery point +# 7 - dec ref pic marking repetition +# 8 - spare pic +# 9 - sene info +# 10 - sub seq info +# 11 - sub seq layer characteristics +# 12 - sub seq characteristics +# 13 - full frame freeze +# 14 - full frame freeze release +# 15 - full frame snapshot +# 16 - progressive refinement segment start +# 17 - progressive refinement segment end +# 18 - motion constrained slice group set +sub ProcessSEI($$) +{ + my ($et, $dirInfo) = @_; + my $dataPt = $$dirInfo{DataPt}; + my $end = length($$dataPt); + my $pos = 0; + my ($type, $size, $index, $t); + + # scan through SEI payload for type 5 (the unregistered user data) + for (;;) { + $type = 0; + for (;;) { + return 0 if $pos >= $end; + $t = Get8u($dataPt, $pos++); # payload type + $type += $t; + last unless $t == 255; + } + return 0 if $type == 0x80; # terminator (ref PH - maybe byte alignment bits?) + $size = 0; + for (;;) { + return 0 if $pos >= $end; + $t = Get8u($dataPt, $pos++); # payload data length + $size += $t; + last unless $t == 255; + } + return 0 if $pos + $size > $end; + $et->VPrint(1," (SEI type $type)\n"); + if ($type == 1) { # picture timing information + if ($parsePictureTiming) { + my $buff = substr($$dataPt, $pos, $size); + ParsePictureTiming($et, $dataPt); + } + } elsif ($type == 5) { # unregistered user data + last; # exit loop to process user data now + } + $pos += $size; + } + + # look for our 16-byte UUID + # - plus "MDPM" for "ModifiedDVPackMeta" + # - plus "GA94" for closed-caption data (currently not decoded) + return 0 unless $size > 20 and substr($$dataPt, $pos, 20) eq + "\x17\xee\x8c\x60\xf8\x4d\x11\xd9\x8c\xd6\x08\0\x20\x0c\x9a\x66MDPM"; +# +# parse the MDPM records in the UUID 17ee8c60f84d11d98cd60800200c9a66 +# unregistered user data payload (ref PH) +# + my $tagTablePtr = GetTagTable('Image::ExifTool::H264::MDPM'); + my $oldIndent = $$et{INDENT}; + $$et{INDENT} .= '| '; + $end = $pos + $size; # end of payload + $pos += 20; # skip UUID + "MDPM" + my $num = Get8u($dataPt, $pos++); # get entry count + my $lastTag = 0; + $et->VerboseDir('MDPM', $num) if $et->Options('Verbose'); + # walk through entries in the MDPM payload + for ($index=0; $index<$num and $pos<$end; ++$index) { + my $tag = Get8u($dataPt, $pos); + if ($tag <= $lastTag) { # should be in numerical order (PH) + $et->Warn('Entries in MDPM directory are out of sequence'); + last; + } + $lastTag = $tag; + my $buff = substr($$dataPt, $pos + 1, 4); + my $from; + my $tagInfo = $et->GetTagInfo($tagTablePtr, $tag); + if ($tagInfo) { + # use our own print conversion for Unknown tags + if ($$tagInfo{Unknown} and not $$tagInfo{SetPrintConv}) { + $$tagInfo{PrintConv} = 'sprintf("0x%.8x", unpack("N", $val))'; + $$tagInfo{SetPrintConv} = 1; + } + # combine with next value(s) if necessary + my $combine = $$tagTablePtr{$tag}{Combine}; + while ($combine) { + last if $pos + 5 >= $end; + my $t = Get8u($dataPt, $pos + 5); + last if $t != $lastTag + 1; # must be consecutive tag ID's + $pos += 5; + $buff .= substr($$dataPt, $pos + 1, 4); + $from = $index unless defined $from; + ++$index; + ++$lastTag; + --$combine; + } + $et->HandleTag($tagTablePtr, $tag, undef, + TagInfo => $tagInfo, + DataPt => \$buff, + Size => length($buff), + Index => defined $from ? "$from-$index" : $index, + ); + } + $pos += 5; + } + $$et{INDENT} = $oldIndent; + return 1; +} + +#------------------------------------------------------------------------------ +# Extract information from H.264 video stream +# Inputs: 0) ExifTool ref, 1) data ref +# Returns: 0 = done parsing, 1 = we want to parse more of these +sub ParseH264Video($$) +{ + my ($et, $dataPt) = @_; + my $verbose = $et->Options('Verbose'); + my $out = $et->Options('TextOut'); + my $tagTablePtr = GetTagTable('Image::ExifTool::H264::Main'); + my %parseNalUnit = ( 0x06 => 1, 0x07 => 1 ); # NAL unit types to parse + my $foundUserData; + my $len = length $$dataPt; + my $pos = 0; + while ($pos < $len) { + my ($nextPos, $end); + # find start of next NAL unit + if ($$dataPt =~ /(\0{2,3}\x01)/g) { + $nextPos = pos $$dataPt; + $end = $nextPos - length $1; + $pos or $pos = $nextPos, next; + } else { + last unless $pos; + $nextPos = $end = $len; + } + last if $pos >= $len; + # parse NAL unit from $pos to $end + my $nal_unit_type = Get8u($dataPt, $pos); + ++$pos; + # check forbidden_zero_bit + $nal_unit_type & 0x80 and $et->Warn('H264 forbidden bit error'), last; + $nal_unit_type &= 0x1f; + # ignore this NAL unit unless we will parse it + $parseNalUnit{$nal_unit_type} or $verbose or $pos = $nextPos, next; + # read NAL unit (and convert all 0x000003's to 0x0000 as per spec.) + my $buff = ''; + pos($$dataPt) = $pos + 1; + while ($$dataPt =~ /\0\0\x03/g) { + last if pos $$dataPt > $end; + $buff .= substr($$dataPt, $pos, pos($$dataPt)-1-$pos); + $pos = pos $$dataPt; + } + $buff .= substr($$dataPt, $pos, $end - $pos); + if ($verbose > 1) { + printf $out " NAL Unit Type: 0x%x (%d bytes)\n",$nal_unit_type, length $buff; + $et->VerboseDump(\$buff); + } + pos($$dataPt) = $pos = $nextPos; + + if ($nal_unit_type == 0x06) { # sei_rbsp (supplemental enhancement info) + + if ($$et{GotNAL06}) { + # process only the first SEI unless ExtractEmbedded is set + next unless $et->Options('ExtractEmbedded'); + $$et{DOC_NUM} = $$et{GotNAL06}; + } + $foundUserData = ProcessSEI($et, { DataPt => \$buff } ); + delete $$et{DOC_NUM}; + # keep parsing SEI's until we find the user data + next unless $foundUserData; + $$et{GotNAL06} = ($$et{GotNAL06} || 0) + 1; + + } elsif ($nal_unit_type == 0x07) { # sequence_parameter_set_rbsp + + # process this NAL unit type only once + next if $$et{GotNAL07}; + $$et{GotNAL07} = 1; + ParseSeqParamSet($et, $tagTablePtr, \$buff); + } + # we were successful, so don't parse this NAL unit type again + delete $parseNalUnit{$nal_unit_type}; + } + # parse one extra H264 frame if we didn't find the user data in this one + # (Panasonic cameras don't put the SEI in the first frame) + return 0 if $foundUserData or $$et{ParsedH264}; + $$et{ParsedH264} = 1; + return 1; +} + +1; # end + +__END__ + +=head1 NAME + +Image::ExifTool::H264 - Read meta information from H.264 video + +=head1 SYNOPSIS + +This module is used by Image::ExifTool + +=head1 DESCRIPTION + +This module contains routines required by Image::ExifTool to extract +information from H.264 video streams. + +=head1 AUTHOR + +Copyright 2003-2019, Phil Harvey (phil at owl.phy.queensu.ca) + +This library is free software; you can redistribute it and/or modify it +under the same terms as Perl itself. + +=head1 REFERENCES + +=over 4 + +=item L<http://www.itu.int/rec/T-REC-H.264/e> + +=item L<http://miffteevee.co.uk/documentation/development/H264Parser_8cpp-source.html> + +=item L<http://ffmpeg.org/> + +=back + +=head1 SEE ALSO + +L<Image::ExifTool::TagNames/H264 Tags>, +L<Image::ExifTool(3pm)|Image::ExifTool> + +=cut + diff --git a/lib/Image/ExifTool/HP.pm b/lib/Image/ExifTool/HP.pm new file mode 100644 index 0000000..94aeaa9 --- /dev/null +++ b/lib/Image/ExifTool/HP.pm @@ -0,0 +1,263 @@ +#------------------------------------------------------------------------------ +# File: HP.pm +# +# Description: Hewlett-Packard maker notes tags +# +# Revisions: 2007-05-03 - P. Harvey Created +#------------------------------------------------------------------------------ + +package Image::ExifTool::HP; + +use strict; +use vars qw($VERSION); +use Image::ExifTool qw(:DataAccess :Utils); + +$VERSION = '1.04'; + +sub ProcessHP($$$); +sub ProcessTDHD($$$); + +# HP EXIF-format maker notes (or is it Vivitar?) +%Image::ExifTool::HP::Main = ( + GROUPS => { 0 => 'MakerNotes', 2 => 'Camera' }, + NOTES => q{ + These tables list tags found in the maker notes of some Hewlett-Packard + camera models. + + The first table lists tags found in the EXIF-format maker notes of the + PhotoSmart 720 (also used by the Vivitar ViviCam 3705, 3705B and 3715). + }, + 0x0e00 => { + Name => 'PrintIM', + Description => 'Print Image Matching', + SubDirectory => { + TagTable => 'Image::ExifTool::PrintIM::Main', + }, + }, +); + +# other types of HP maker notes +%Image::ExifTool::HP::Type2 = ( + PROCESS_PROC => \&ProcessHP, + GROUPS => { 0 => 'MakerNotes', 2 => 'Camera' }, + NOTES => 'These tags are used by the PhotoSmart E427.', + 'PreviewImage' => { + Name => 'PreviewImage', + Groups => { 2 => 'Preview' }, + RawConv => '$self->ValidateImage(\$val,$tag)', + }, + 'Serial Number' => 'SerialNumber', + 'Lens Shading' => 'LensShading', +); + +%Image::ExifTool::HP::Type4 = ( + PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData, + GROUPS => { 0 => 'MakerNotes', 2 => 'Camera' }, + NOTES => 'These tags are used by the PhotoSmart M627.', + 0x0c => { + Name => 'MaxAperture', + Format => 'int16u', + ValueConv => '$val / 10', + }, + 0x10 => { + Name => 'ExposureTime', + Format => 'int32u', + ValueConv => '$val / 1e6', + PrintConv => 'Image::ExifTool::Exif::PrintExposureTime($val)', + }, + 0x14 => { + Name => 'CameraDateTime', + Groups => { 2 => 'Time' }, + Format => 'string[20]', + }, + 0x34 => { + Name => 'ISO', + Format => 'int16u', + }, + 0x5c => { + Name => 'SerialNumber', + Format => 'string[26]', + RawConv => '$val =~ s/^SERIAL NUMBER:// ? $val : undef', + }, +); + +%Image::ExifTool::HP::Type6 = ( + PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData, + GROUPS => { 0 => 'MakerNotes', 2 => 'Camera' }, + NOTES => 'These tags are used by the PhotoSmart M425, M525 and M527.', + 0x0c => { + Name => 'FNumber', + Format => 'int16u', + ValueConv => '$val / 10', + }, + 0x10 => { + Name => 'ExposureTime', + Format => 'int32u', + ValueConv => '$val / 1e6', + PrintConv => 'Image::ExifTool::Exif::PrintExposureTime($val)', + }, + 0x14 => { + Name => 'CameraDateTime', + Groups => { 2 => 'Time' }, + Format => 'string[20]', + }, + 0x34 => { + Name => 'ISO', + Format => 'int16u', + }, + 0x58 => { + Name => 'SerialNumber', + Format => 'string[26]', + RawConv => '$val =~ s/^SERIAL NUMBER:// ? $val : undef', + }, +); + +# proprietary format TDHD data written by Photosmart R837 (ref PH) +%Image::ExifTool::HP::TDHD = ( + PROCESS_PROC => \&ProcessTDHD, + GROUPS => { 0 => 'MakerNotes', 2 => 'Camera' }, + NOTES => q{ + These tags are extracted from the APP6 "TDHD" segment of Photosmart R837 + JPEG images. Many other unknown tags exist in is data, and can be seen with + the Unknown (-u) option. + }, + # (all subdirectories except TDHD and LSLV are automatically recognized + # by their "type" word of 0x10001) + TDHD => { + Name => 'TDHD', + SubDirectory => { TagTable => 'Image::ExifTool::HP::TDHD' }, + }, + LSLV => { + Name => 'LSLV', + SubDirectory => { TagTable => 'Image::ExifTool::HP::TDHD' }, + }, + FWRV => 'FirmwareVersion', + CMSN => 'SerialNumber', # (unverified) + # LTEM - some temperature? +); + +#------------------------------------------------------------------------------ +# Process HP APP6 TDHD metadata (ref PH) +# Inputs: 0) ExifTool object ref, 1) dirInfo ref, 2) tag table ref +# Returns: 1 on success +sub ProcessTDHD($$$) +{ + my ($et, $dirInfo, $tagTablePtr) = @_; + my $dataPt = $$dirInfo{DataPt}; + my $dataPos = $$dirInfo{DataPos}; + my $pos = $$dirInfo{DirStart}; + my $dirEnd = $pos + $$dirInfo{DirLen}; + my $unknown = $et->Options('Unknown') || $et->Options('Verbose'); + $et->VerboseDir('TDHD', undef, $$dirInfo{DirLen}); + SetByteOrder('II'); + while ($pos + 12 < $dirEnd) { + my $tag = substr($$dataPt, $pos, 4); + my $type = Get32u($dataPt, $pos + 4); + my $size = Get32u($dataPt, $pos + 8); + $pos += 12; + last if $size < 0 or $pos + $size > $dirEnd; + if ($type == 0x10001) { + # this is a subdirectory containing more tags + my %dirInfo = ( + DataPt => $dataPt, + DataPos => $dataPos, + DirStart => $pos, + DirLen => $size, + ); + $et->ProcessDirectory(\%dirInfo, $tagTablePtr); + } else { + if (not $$tagTablePtr{$tag} and $unknown) { + my $name = $tag; + $name =~ tr/-_A-Za-z0-9//dc; # remove invalid characters + my %tagInfo = ( + Name => "HP_TDHD_$name", + Unknown => 1, + ); + # guess format based on data size + if ($size == 1) { + $tagInfo{Format} = 'int8u'; + } elsif ($size == 2) { + $tagInfo{Format} = 'int16u'; + } elsif ($size == 4) { + $tagInfo{Format} = 'int32s'; + } elsif ($size > 80) { + $tagInfo{Binary} = 1; + } + AddTagToTable($tagTablePtr, $tag, \%tagInfo); + } + $et->HandleTag($tagTablePtr, $tag, undef, + DataPt => $dataPt, + DataPos => $dataPos, + Start => $pos, + Size => $size, + ); + } + $pos += $size; + } + return 1; +} + +#------------------------------------------------------------------------------ +# Process HP maker notes +# Inputs: 0) ExifTool object ref, 1) dirInfo ref, 2) tag table ref +# Returns: 1 on success, otherwise returns 0 and sets a Warning +sub ProcessHP($$$) +{ + my ($et, $dirInfo, $tagTablePtr) = @_; + my $dataPt = $$dirInfo{DataPt}; + my $dataLen = $$dirInfo{DataLen}; + my $dirStart = $$dirInfo{DirStart} || 0; + my $dirLen = $$dirInfo{DirLen} || $dataLen - $dirStart; + + # look for known text-type tags + if ($dirStart or $dirLen != length($$dataPt)) { + my $buff = substr($$dataPt, $dirStart, $dirLen); + $dataPt = \$buff; + } + my $tagID; + # brute-force scan for PreviewImage + if ($$tagTablePtr{PreviewImage} and $$dataPt =~ /(\xff\xd8\xff\xdb.*\xff\xd9)/gs) { + $et->HandleTag($tagTablePtr, 'PreviewImage', $1); + # truncate preview to speed subsequent tag scans + my $buff = substr($$dataPt, 0, pos($$dataPt)-length($1)); + $dataPt = \$buff; + } + # scan for other tag ID's + foreach $tagID (sort(TagTableKeys($tagTablePtr))) { + next if $tagID eq 'PreviewImage'; + next unless $$dataPt =~ /$tagID:\s*([\x20-\x7f]+)/i; + $et->HandleTag($tagTablePtr, $tagID, $1); + } + return 1; +} + +1; # end + +__END__ + +=head1 NAME + +Image::ExifTool::HP - Hewlett-Packard maker notes tags + +=head1 SYNOPSIS + +This module is loaded automatically by Image::ExifTool when required. + +=head1 DESCRIPTION + +This module contains definitions required by Image::ExifTool to interpret +Hewlett-Packard maker notes. + +=head1 AUTHOR + +Copyright 2003-2019, Phil Harvey (phil at owl.phy.queensu.ca) + +This library is free software; you can redistribute it and/or modify it +under the same terms as Perl itself. + +=head1 SEE ALSO + +L<Image::ExifTool::TagNames/HP Tags>, +L<Image::ExifTool(3pm)|Image::ExifTool> + +=cut diff --git a/lib/Image/ExifTool/HTML.pm b/lib/Image/ExifTool/HTML.pm new file mode 100644 index 0000000..43bdf5b --- /dev/null +++ b/lib/Image/ExifTool/HTML.pm @@ -0,0 +1,583 @@ +#------------------------------------------------------------------------------ +# File: HTML.pm +# +# Description: Read HTML meta information +# +# Revisions: 01/30/2007 - P. Harvey Created +# +# References: 1) http://www.w3.org/TR/html4/ +# 2) http://www.daisy.org/publications/specifications/daisy_202.html +# 3) http://vancouver-webpages.com/META/metatags.detail.html +# 4) http://www.html-reference.com/META.htm +#------------------------------------------------------------------------------ + +package Image::ExifTool::HTML; + +use strict; +use vars qw($VERSION @ISA @EXPORT_OK); +use Image::ExifTool qw(:DataAccess :Utils); +use Image::ExifTool::PostScript; +use Image::ExifTool::XMP qw(EscapeXML UnescapeXML); +require Exporter; + +$VERSION = '1.16'; +@ISA = qw(Exporter); +@EXPORT_OK = qw(EscapeHTML UnescapeHTML); + +sub SetHTMLCharset($$); + +# convert HTML charset (lower case) to ExifTool Charset name +my %htmlCharset = ( + macintosh => 'MacRoman', + 'iso-8859-1' => 'Latin', + 'utf-8' => 'UTF8', + 'windows-1252' => 'Latin', +); + +# HTML 4 character entity references +my %entityNum = ( + 'quot' => 34, 'eth' => 240, 'lsquo' => 8216, + 'amp' => 38, 'ntilde' => 241, 'rsquo' => 8217, + 'apos' => 39, 'ograve' => 242, 'sbquo' => 8218, + 'lt' => 60, 'oacute' => 243, 'ldquo' => 8220, + 'gt' => 62, 'ocirc' => 244, 'rdquo' => 8221, + 'nbsp' => 160, 'otilde' => 245, 'bdquo' => 8222, + 'iexcl' => 161, 'ouml' => 246, 'dagger' => 8224, + 'cent' => 162, 'divide' => 247, 'Dagger' => 8225, + 'pound' => 163, 'oslash' => 248, 'bull' => 8226, + 'curren' => 164, 'ugrave' => 249, 'hellip' => 8230, + 'yen' => 165, 'uacute' => 250, 'permil' => 8240, + 'brvbar' => 166, 'ucirc' => 251, 'prime' => 8242, + 'sect' => 167, 'uuml' => 252, 'Prime' => 8243, + 'uml' => 168, 'yacute' => 253, 'lsaquo' => 8249, + 'copy' => 169, 'thorn' => 254, 'rsaquo' => 8250, + 'ordf' => 170, 'yuml' => 255, 'oline' => 8254, + 'laquo' => 171, 'OElig' => 338, 'frasl' => 8260, + 'not' => 172, 'oelig' => 339, 'euro' => 8364, + 'shy' => 173, 'Scaron' => 352, 'image' => 8465, + 'reg' => 174, 'scaron' => 353, 'weierp' => 8472, + 'macr' => 175, 'Yuml' => 376, 'real' => 8476, + 'deg' => 176, 'fnof' => 402, 'trade' => 8482, + 'plusmn' => 177, 'circ' => 710, 'alefsym'=> 8501, + 'sup2' => 178, 'tilde' => 732, 'larr' => 8592, + 'sup3' => 179, 'Alpha' => 913, 'uarr' => 8593, + 'acute' => 180, 'Beta' => 914, 'rarr' => 8594, + 'micro' => 181, 'Gamma' => 915, 'darr' => 8595, + 'para' => 182, 'Delta' => 916, 'harr' => 8596, + 'middot' => 183, 'Epsilon'=> 917, 'crarr' => 8629, + 'cedil' => 184, 'Zeta' => 918, 'lArr' => 8656, + 'sup1' => 185, 'Eta' => 919, 'uArr' => 8657, + 'ordm' => 186, 'Theta' => 920, 'rArr' => 8658, + 'raquo' => 187, 'Iota' => 921, 'dArr' => 8659, + 'frac14' => 188, 'Kappa' => 922, 'hArr' => 8660, + 'frac12' => 189, 'Lambda' => 923, 'forall' => 8704, + 'frac34' => 190, 'Mu' => 924, 'part' => 8706, + 'iquest' => 191, 'Nu' => 925, 'exist' => 8707, + 'Agrave' => 192, 'Xi' => 926, 'empty' => 8709, + 'Aacute' => 193, 'Omicron'=> 927, 'nabla' => 8711, + 'Acirc' => 194, 'Pi' => 928, 'isin' => 8712, + 'Atilde' => 195, 'Rho' => 929, 'notin' => 8713, + 'Auml' => 196, 'Sigma' => 931, 'ni' => 8715, + 'Aring' => 197, 'Tau' => 932, 'prod' => 8719, + 'AElig' => 198, 'Upsilon'=> 933, 'sum' => 8721, + 'Ccedil' => 199, 'Phi' => 934, 'minus' => 8722, + 'Egrave' => 200, 'Chi' => 935, 'lowast' => 8727, + 'Eacute' => 201, 'Psi' => 936, 'radic' => 8730, + 'Ecirc' => 202, 'Omega' => 937, 'prop' => 8733, + 'Euml' => 203, 'alpha' => 945, 'infin' => 8734, + 'Igrave' => 204, 'beta' => 946, 'ang' => 8736, + 'Iacute' => 205, 'gamma' => 947, 'and' => 8743, + 'Icirc' => 206, 'delta' => 948, 'or' => 8744, + 'Iuml' => 207, 'epsilon'=> 949, 'cap' => 8745, + 'ETH' => 208, 'zeta' => 950, 'cup' => 8746, + 'Ntilde' => 209, 'eta' => 951, 'int' => 8747, + 'Ograve' => 210, 'theta' => 952, 'there4' => 8756, + 'Oacute' => 211, 'iota' => 953, 'sim' => 8764, + 'Ocirc' => 212, 'kappa' => 954, 'cong' => 8773, + 'Otilde' => 213, 'lambda' => 955, 'asymp' => 8776, + 'Ouml' => 214, 'mu' => 956, 'ne' => 8800, + 'times' => 215, 'nu' => 957, 'equiv' => 8801, + 'Oslash' => 216, 'xi' => 958, 'le' => 8804, + 'Ugrave' => 217, 'omicron'=> 959, 'ge' => 8805, + 'Uacute' => 218, 'pi' => 960, 'sub' => 8834, + 'Ucirc' => 219, 'rho' => 961, 'sup' => 8835, + 'Uuml' => 220, 'sigmaf' => 962, 'nsub' => 8836, + 'Yacute' => 221, 'sigma' => 963, 'sube' => 8838, + 'THORN' => 222, 'tau' => 964, 'supe' => 8839, + 'szlig' => 223, 'upsilon'=> 965, 'oplus' => 8853, + 'agrave' => 224, 'phi' => 966, 'otimes' => 8855, + 'aacute' => 225, 'chi' => 967, 'perp' => 8869, + 'acirc' => 226, 'psi' => 968, 'sdot' => 8901, + 'atilde' => 227, 'omega' => 969, 'lceil' => 8968, + 'auml' => 228, 'thetasym'=>977, 'rceil' => 8969, + 'aring' => 229, 'upsih' => 978, 'lfloor' => 8970, + 'aelig' => 230, 'piv' => 982, 'rfloor' => 8971, + 'ccedil' => 231, 'ensp' => 8194, 'lang' => 9001, + 'egrave' => 232, 'emsp' => 8195, 'rang' => 9002, + 'eacute' => 233, 'thinsp' => 8201, 'loz' => 9674, + 'ecirc' => 234, 'zwnj' => 8204, 'spades' => 9824, + 'euml' => 235, 'zwj' => 8205, 'clubs' => 9827, + 'igrave' => 236, 'lrm' => 8206, 'hearts' => 9829, + 'iacute' => 237, 'rlm' => 8207, 'diams' => 9830, + 'icirc' => 238, 'ndash' => 8211, + 'iuml' => 239, 'mdash' => 8212, +); +my %entityName; # look up entity names by number (built as necessary) + +# HTML info +# (tag ID's are case insensitive and must be all lower case in tables) +%Image::ExifTool::HTML::Main = ( + GROUPS => { 2 => 'Document' }, + NOTES => q{ + Meta information extracted from the header of HTML and XHTML files. This is + a mix of information found in the C<META> elements, C<XML> element, and the + C<TITLE> element. + }, + dc => { + Name => 'DC', + SubDirectory => { TagTable => 'Image::ExifTool::HTML::dc' }, + }, + ncc => { + Name => 'NCC', + SubDirectory => { TagTable => 'Image::ExifTool::HTML::ncc' }, + }, + prod => { + Name => 'Prod', + SubDirectory => { TagTable => 'Image::ExifTool::HTML::prod' }, + }, + vw96 => { + Name => 'VW96', + SubDirectory => { TagTable => 'Image::ExifTool::HTML::vw96' }, + }, + 'http-equiv' => { + Name => 'HTTP-equiv', + SubDirectory => { TagTable => 'Image::ExifTool::HTML::equiv' }, + }, + o => { + Name => 'Office', + SubDirectory => { TagTable => 'Image::ExifTool::HTML::Office' }, + }, + abstract => { }, + author => { }, + classification => { }, + 'content-language'=>{ Name => 'ContentLanguage' }, + copyright => { }, + description => { }, + distribution => { }, + 'doc-class' => { Name => 'DocClass' }, + 'doc-rights' => { Name => 'DocRights' }, + 'doc-type' => { Name => 'DocType' }, + formatter => { }, + generator => { }, + generatorversion=> { Name => 'GeneratorVersion' }, + googlebot => { Name => 'GoogleBot' }, + keywords => { List => 1 }, + mssmarttagspreventparsing => { Name => 'NoMSSmartTags' }, + originator => { }, + owner => { }, + progid => { Name => 'ProgID' }, + rating => { }, + refresh => { }, + 'resource-type' => { Name => 'ResourceType' }, + 'revisit-after' => { Name => 'RevisitAfter' }, + robots => { List => 1 }, + title => { Notes => "the only extracted tag which isn't from an HTML META element" }, +); + +# ref 2 +%Image::ExifTool::HTML::dc = ( + GROUPS => { 1 => 'HTML-dc', 2 => 'Document' }, + NOTES => 'Dublin Core schema tags (also used in XMP).', + contributor => { Groups => { 2 => 'Author' }, List => 'Bag' }, + coverage => { }, + creator => { Groups => { 2 => 'Author' }, List => 'Seq' }, + date => { + Groups => { 2 => 'Time' }, + List => 'Seq', + PrintConv => '$self->ConvertDateTime($val)', + }, + description => { }, + 'format' => { }, + identifier => { }, + language => { List => 'Bag' }, + publisher => { Groups => { 2 => 'Author' }, List => 'Bag' }, + relation => { List => 'Bag' }, + rights => { Groups => { 2 => 'Author' } }, + source => { Groups => { 2 => 'Author' } }, + subject => { List => 'Bag' }, + title => { }, + type => { List => 'Bag' }, +); + +# ref 2 +%Image::ExifTool::HTML::ncc = ( + GROUPS => { 1 => 'HTML-ncc', 2 => 'Document' }, + charset => { Name => 'CharacterSet' }, # name changed to avoid conflict with -charset option + depth => { }, + files => { }, + footnotes => { }, + generator => { }, + kbytesize => { Name => 'KByteSize' }, + maxpagenormal => { Name => 'MaxPageNormal' }, + multimediatype => { Name => 'MultimediaType' }, + narrator => { }, + pagefront => { Name => 'PageFront' }, + pagenormal => { Name => 'PageNormal' }, + pagespecial => { Name => 'PageSpecial' }, + prodnotes => { Name => 'ProdNotes' }, + producer => { }, + produceddate => { Name => 'ProducedDate', Groups => { 2 => 'Time' } }, # YYYY-mm-dd + revision => { }, + revisiondate => { Name => 'RevisionDate', Groups => { 2 => 'Time' } }, + setinfo => { Name => 'SetInfo' }, + sidebars => { }, + sourcedate => { Name => 'SourceDate', Groups => { 2 => 'Time' } }, + sourceedition => { Name => 'SourceEdition' }, + sourcepublisher => { Name => 'SourcePublisher' }, + sourcerights => { Name => 'SourceRights' }, + sourcetitle => { Name => 'SourceTitle' }, + tocitems => { Name => 'TOCItems' }, + totaltime => { Name => 'Duration' }, # HH:MM:SS +); + +# ref 3 +%Image::ExifTool::HTML::vw96 = ( + GROUPS => { 1 => 'HTML-vw96', 2 => 'Document' }, + objecttype => { Name => 'ObjectType' }, +); + +# ref 2 +%Image::ExifTool::HTML::prod = ( + GROUPS => { 1 => 'HTML-prod', 2 => 'Document' }, + reclocation => { Name => 'RecLocation' }, + recengineer => { Name => 'RecEngineer' }, +); + +# ref 3/4 +%Image::ExifTool::HTML::equiv = ( + GROUPS => { 1 => 'HTTP-equiv', 2 => 'Document' }, + NOTES => 'These tags have a family 1 group name of "HTTP-equiv".', + 'cache-control' => { Name => 'CacheControl' }, + 'content-disposition' => { Name => 'ContentDisposition' }, + 'content-language' => { Name => 'ContentLanguage' }, + 'content-script-type' => { Name => 'ContentScriptType' }, + 'content-style-type' => { Name => 'ContentStyleType' }, + # note: setting the HTMLCharset like this will miss any tags which come earlier + 'content-type' => { Name => 'ContentType', RawConv => \&SetHTMLCharset }, + 'default-style' => { Name => 'DefaultStyle' }, + expires => { }, + 'ext-cache' => { Name => 'ExtCache' }, + imagetoolbar => { Name => 'ImageToolbar' }, + lotus => { }, + 'page-enter' => { Name => 'PageEnter' }, + 'page-exit' => { Name => 'PageExit' }, + 'pics-label' => { Name => 'PicsLabel' }, + pragma => { }, + refresh => { }, + 'reply-to' => { Name => 'ReplyTo' }, + 'set-cookie' => { Name => 'SetCookie' }, + 'site-enter' => { Name => 'SiteEnter' }, + 'site-exit' => { Name => 'SiteExit' }, + vary => { }, + 'window-target' => { Name => 'WindowTarget' }, +); + +# MS Office namespace (ref PH) +%Image::ExifTool::HTML::Office = ( + GROUPS => { 1 => 'HTML-office', 2 => 'Document' }, + NOTES => 'Tags written by Microsoft Office applications.', + Subject => { }, + Author => { Groups => { 2 => 'Author' } }, + Keywords => { }, + Description => { }, + Template => { }, + LastAuthor => { Groups => { 2 => 'Author' } }, + Revision => { Name => 'RevisionNumber' }, + TotalTime => { Name => 'TotalEditTime', PrintConv => 'ConvertTimeSpan($val, 60)' }, + Created => { + Name => 'CreateDate', + Groups => { 2 => 'Time' }, + ValueConv => 'Image::ExifTool::XMP::ConvertXMPDate($val)', + PrintConv => '$self->ConvertDateTime($val)', + }, + LastSaved => { + Name => 'ModifyDate', + Groups => { 2 => 'Time' }, + ValueConv => 'Image::ExifTool::XMP::ConvertXMPDate($val)', + PrintConv => '$self->ConvertDateTime($val)', + }, + LastSaved => { + Name => 'ModifyDate', + Groups => { 2 => 'Time' }, + ValueConv => 'Image::ExifTool::XMP::ConvertXMPDate($val)', + PrintConv => '$self->ConvertDateTime($val)', + }, + LastPrinted => { + Name => 'LastPrinted', + Groups => { 2 => 'Time' }, + ValueConv => 'Image::ExifTool::XMP::ConvertXMPDate($val)', + PrintConv => '$self->ConvertDateTime($val)', + }, + Pages => { }, + Words => { }, + Characters => { }, + Category => { }, + Manager => { }, + Company => { }, + Lines => { }, + Paragraphs => { }, + CharactersWithSpaces => { }, + Version => { Name => 'RevisionNumber' }, +); + +#------------------------------------------------------------------------------ +# Set HTMLCharset member based on content type +# Inputs: 0) content type string, 1) ExifTool ref +# Returns: original string +sub SetHTMLCharset($$) +{ + my ($val, $et) = @_; + $$et{HTMLCharset} = $htmlCharset{lc $1} if $val =~ /charset=['"]?([-\w]+)/; + return $val; +} + +#------------------------------------------------------------------------------ +# Convert single UTF-8 character to HTML character reference +# Inputs: 0) UTF-8 character sequence +# Returns: HTML character reference (eg. "&quot;"); +# Note: Must be called via EscapeHTML to load name lookup +sub EscapeChar($) +{ + my $ch = shift; + my $val; + if ($] < 5.006001) { + ($val) = Image::ExifTool::UnpackUTF8($ch); + } else { + # the meaning of "U0" is reversed as of Perl 5.10.0! + ($val) = unpack($] < 5.010000 ? 'U0U' : 'C0U', $ch); + } + return '?' unless defined $val; + return "&$entityName{$val};" if $entityName{$val}; + return sprintf('&#x%x;',$val); +} + +#------------------------------------------------------------------------------ +# Escape any special characters for HTML +# Inputs: 0) string to be escaped, 1) optional string encoding (default 'UTF8') +# Returns: escaped string +sub EscapeHTML($;$) +{ + my ($str, $enc) = @_; + # escape XML characters + $str = EscapeXML($str); + # escape other special characters if they exist + if ($str =~ /[\x80-\xff]/) { + # generate entity name lookup if necessary + unless (%entityName) { + local $_; + foreach (keys %entityNum) { + $entityName{$entityNum{$_}} = $_; + } + delete $entityName{39}; # 'apos' is not valid HTML + } + # suppress warnings + local $SIG{'__WARN__'} = sub { 1 }; + if ($enc and $enc ne 'UTF8') { + $str = Image::ExifTool::Decode(undef, $str, $enc, undef, 'UTF8'); + $str =~ s/([\xc2-\xf7][\x80-\xbf]+)/EscapeChar($1)/sge; + $str = Image::ExifTool::Decode(undef, $str, 'UTF8', undef, $enc); + } else { + # escape any non-ascii characters for HTML + $str =~ s/([\xc2-\xf7][\x80-\xbf]+)/EscapeChar($1)/sge; + } + } + return $str; +} + +#------------------------------------------------------------------------------ +# Unescape all HTML character references +# Inputs: 0) string to be unescaped, 1) optional string encoding (default 'UTF8') +# Returns: unescaped string +sub UnescapeHTML($;$) +{ + my ($str, $enc) = @_; + return UnescapeXML($str, \%entityNum, $enc); +} + +#------------------------------------------------------------------------------ +# Extract information from a HTML file +# Inputs: 0) ExifTool object reference, 1) DirInfo reference +# Returns: 1 on success, 0 if this wasn't a valid HTML file +sub ProcessHTML($$) +{ + my ($et, $dirInfo) = @_; + my $raf = $$dirInfo{RAF}; + my $buff; + + # validate HTML or XHTML file + $raf->Read($buff, 256) or return 0; + $buff =~ /^(\xef\xbb\xbf)?\s*<(!DOCTYPE\s+HTML|HTML|\?xml)/i or return 0; + $buff =~ /<(!DOCTYPE\s+)?HTML/i or return 0 if $2 eq '?xml'; + $et->SetFileType(); + + $raf->Seek(0,0) or $et->Warn('Seek error'), return 1; + + local $/ = Image::ExifTool::PostScript::GetInputRecordSeparator($raf); + $/ or $et->Warn('Invalid HTML data'), return 1; + + # extract header information + my $doc; + while ($raf->ReadLine($buff)) { + if (not defined $doc) { + # look for 'head' element + next unless $buff =~ /<head\b/ig; + $doc = substr($buff, pos($buff)); + next; + } + $doc .= $buff; + last if $buff =~ m{</head>}i; + } + return 1 unless defined $doc; + + # process all elements in header + my $tagTablePtr = GetTagTable('Image::ExifTool::HTML::Main'); + for (;;) { + last unless $doc =~ m{<([\w:.-]+)(.*?)>}sg; + my ($tagName, $attrs) = ($1, $2); + my $tag = lc($tagName); + my ($val, $grp); + if ($attrs =~ m{/$}) { # self-contained XHTML tags end in '/>' + $val = ''; + } else { + # look for element close + my $pos = pos($doc); + my $close = "</$tagName>"; + # the following doesn't work on Solaris Perl 5.6.1 due to Perl bug: + # if ($doc =~ m{(.*?)</$tagName>}sg) { + # $val = $1; + if ($doc =~ m{$close}sg) { + $val = substr($doc, $pos, pos($doc)-$pos-length($close)); + } else { + pos($doc) = $pos; + next unless $tag eq 'meta'; # META tags don't need to be closed + $val = ''; + } + } + my $table = $tagTablePtr; + if ($tag eq 'meta') { + # parse HTML META element + undef $tag; + # tag name is in NAME or HTTP-EQUIV attribute + if ($attrs =~ /\bname\s*=\s*['"]?([\w:.-]+)/si) { + $tagName = $1; + } elsif ($attrs =~ /\bhttp-equiv\s*=\s*['"]?([\w:.-]+)/si) { + $tagName = "HTTP-equiv.$1"; + } else { + next; # no name + } + $tag = lc($tagName) or next; + # tag value is in CONTENT attribute + if ($attrs =~ /\bcontent\s*=\s*(['"])(.*?)\1/si or + $attrs =~ /\bcontent\s*=\s*(['"]?)([\w:.-]+)/si) + { + $val = $2; + } else { + next unless length $val; + } + # isolate group name (separator is '.' in HTML, but ':' in ref 2) + if ($tag =~ /^([\w-]+)[:.]([\w-]+)/) { + ($grp, $tag) = ($1, $2); + my $tagInfo = $et->GetTagInfo($tagTablePtr, $grp); + if ($tagInfo and $$tagInfo{SubDirectory}) { + $table = GetTagTable($tagInfo->{SubDirectory}->{TagTable}); + } else { + $tag = "$grp.$tag"; + } + } + } elsif ($tag eq 'xml') { + $et->VPrint(0, "Parsing XML\n"); + # parse XML tags (quick-and-dirty) + my $xml = $val; + while ($xml =~ /<([\w-]+):([\w-]+)(\s.*?)?>([^<]*?)<\/\1:\2>/g) { + ($grp, $tag, $val) = ($1, $2, $4); + my $tagInfo = $et->GetTagInfo($tagTablePtr, $grp); + next unless $tagInfo and $$tagInfo{SubDirectory}; + $table = GetTagTable($tagInfo->{SubDirectory}->{TagTable}); + unless ($$table{$tag}) { + my $name = ucfirst $tag; + $name =~ s/_x([0-9a-f]{4})_/chr(hex($1))/gie; # convert hex codes + $name =~ s/\s(.)/\U$1/g; # capitalize all words in tag name + $name =~ tr/-_a-zA-Z0-9//dc; # remove illegal characters (also hex code wide chars) + AddTagToTable($table, $tag, { Name => $name }); + $et->VPrint(0, " [adding $tag '${name}']\n"); + } + $val = $et->Decode($val, $$et{HTMLCharset}) if $$et{HTMLCharset}; + $et->HandleTag($table, $tag, UnescapeXML($val)); + } + next; + } else { + # the only other element we process is TITLE + next unless $tag eq 'title'; + } + unless ($$table{$tag}) { + my $name = $tagName; + $name =~ s/\W+(\w)/\u$1/sg; + my $info = { Name => $name, Groups => { 0 => 'HTML' } }; + $info->{Groups}->{1} = ($grp eq 'http-equiv' ? 'HTTP-equiv' : "HTML-$grp") if $grp; + AddTagToTable($table, $tag, $info); + $et->VPrint(0, " [adding $tag '${tagName}']\n"); + } + # recode if necessary + $val = $et->Decode($val, $$et{HTMLCharset}) if $$et{HTMLCharset}; + $val =~ s{\s*$/\s*}{ }sg; # replace linefeeds and indenting spaces + $val = UnescapeHTML($val); # unescape HTML character references + $et->HandleTag($table, $tag, $val); + } + return 1; +} + +1; # end + +__END__ + +=head1 NAME + +Image::ExifTool::HTML - Read HTML meta information + +=head1 SYNOPSIS + +This module is used by Image::ExifTool + +=head1 DESCRIPTION + +This module contains routines required by Image::ExifTool to extract +meta information from HTML documents. + +=head1 AUTHOR + +Copyright 2003-2019, Phil Harvey (phil at owl.phy.queensu.ca) + +This library is free software; you can redistribute it and/or modify it +under the same terms as Perl itself. + +=head1 REFERENCES + +=over 4 + +=item L<http://www.w3.org/TR/html4/> + +=item L<http://www.daisy.org/publications/specifications/daisy_202.html> + +=item L<http://vancouver-webpages.com/META/metatags.detail.html> + +=item L<http://www.html-reference.com/META.htm> + +=back + +=head1 SEE ALSO + +L<Image::ExifTool::TagNames/HTML Tags>, +L<Image::ExifTool(3pm)|Image::ExifTool> + +=cut + diff --git a/lib/Image/ExifTool/HtmlDump.pm b/lib/Image/ExifTool/HtmlDump.pm new file mode 100644 index 0000000..9136aec --- /dev/null +++ b/lib/Image/ExifTool/HtmlDump.pm @@ -0,0 +1,909 @@ +#------------------------------------------------------------------------------ +# File: HtmlDump.pm +# +# Description: Dump information in hex to HTML page +# +# Revisions: 12/05/2005 - P. Harvey Created +#------------------------------------------------------------------------------ + +package Image::ExifTool::HtmlDump; + +use strict; +use vars qw($VERSION); +use Image::ExifTool; # only for FinishTiffDump() +use Image::ExifTool::HTML qw(EscapeHTML); + +$VERSION = '1.37'; + +sub DumpTable($$$;$$$$$$); +sub Open($$$;@); +sub Write($@); + +my ($bkgStart, $bkgEnd, @bkgSpan); + +my $htmlHeader1 = <<_END_PART_1_; +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" + "http://www.w3.org/TR/1998/REC-html40-19980424/loose.dtd"> +<html> +<head> +<title> +_END_PART_1_ + +# Note: Don't change font-weight style because it can affect line height +my $htmlHeader2 = <<_END_PART_2_; +</title> +<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> +<style type="text/css"> +<!-- +/* character style ID's */ +.D { color: #000000 } /* default color */ +.V { color: #ff0000 } /* duplicate block 1 */ +.W { color: #004400 } /* normal block 1 */ +.X { color: #ff4488 } /* duplicate block 2 */ +.Y { color: #448844 } /* normal block 2 */ +.U { color: #cc8844 } /* unused data block */ +.H { color: #0000ff } /* highlighted tag name */ +.F { color: #aa00dd } /* actual offset differs */ +.M { text-decoration: underline } /* maker notes data */ +.tt { /* tooltip text */ + visibility: hidden; + position: absolute; + white-space: nowrap; + top: 0; + left: 0; + font-family: Verdana, sans-serif; + font-size: .7em; + padding: 2px 4px; + border: 1px solid gray; + z-index: 3; +} +.tb { /* tooltip background */ + visibility: hidden; + position: absolute; + background: #ffffdd; + zoom: 1; + -moz-opacity: 0.8; + -khtml-opacity: 0.8; + -ms-filter: 'progid:DXImageTransform.Microsoft.Alpha(Opacity=80)'; + filter: alpha(opacity=80); + opacity: 0.8; + z-index: 2; +} +/* table styles */ +table.dump { + border-top: 1px solid gray; + border-bottom: 1px solid gray; +} +table.dump td { padding: .2em .3em } +td.c2 { + border-left: 1px solid gray; + border-right: 1px solid gray; +} +pre { margin: 0 } +table { font-size: .9em } +body { color: black; background: white } +--> +</style> +<script language="JavaScript" type="text/JavaScript"> +<!-- Begin +// tooltip positioning constants +var TMAR = 4; // top/left margins +var BMAR = 16; // bottom/right margins (scrollbars may overhang inner dimensions) +var XOFF = 10; // x offset from cursor +var YOFF = 40; // y offset +var YMIN = 10; // minimum y offset +var YTOP = 20; // y offset when above cursor +// common variables +var safari1 = navigator.userAgent.indexOf("Safari/312.6") >= 0; +var ie6 = navigator.userAgent.toLowerCase().indexOf('msie 6') >= 0; +var mspan = new Array; +var hlist, tt, tb; + +function GetElementsByClass(classname, tagname) { + var found = new Array(); + var list = document.getElementsByTagName(tagname); + var len = list.length; + for (var i=0, j=0; i<len; ++i) { + var classes = list[i].className.split(' '); + for (var k=0; k<classes.length; ++k) { + if (classes[k] == classname) { + found[j++] = list[i]; + break; + } + } + } + return found; +} + +// move tooltip +function move(e) +{ + if (!tt) return; + if (ie6 && (tt.style.top == '' || tt.style.top == 0) && + (tt.style.left == '' || tt.style.left == 0)) + { + tt.style.width = tt.offsetWidth + 'px'; + tt.style.height = tt.offsetHeight + 'px'; + } + var w, h; + // browser inconsistencies make getting window size more complex than it should be, + // and even then we don't know if it is smaller due to scrollbar width + if (typeof(window.innerWidth) == 'number') { + w = window.innerWidth; + h = window.innerHeight; + } else if (document.documentElement && document.documentElement.clientWidth) { + w = document.documentElement.clientWidth; + h = document.documentElement.clientHeight; + } else { + w = document.body.clientWidth; + h = document.body.clientHeight; + } + var x = e.clientX + XOFF; + var y = e.clientY + YOFF; + if (safari1) { // patch for people still using OS X 10.3.9 + x -= document.body.scrollLeft + document.documentElement.scrollLeft; + y -= document.body.scrollTop + document.documentElement.scrollTop; + } + var mx = w - BMAR - tt.offsetWidth; + var my = h - BMAR - tt.offsetHeight; + if (y > my + YOFF - YMIN) y = e.clientY - YTOP - tt.offsetHeight; + if (x > mx) x = mx; + if (y > my) y = my; + if (x < TMAR) x = TMAR; + if (y < TMAR) y = TMAR; + x += document.body.scrollLeft + document.documentElement.scrollLeft; + y += document.body.scrollTop + document.documentElement.scrollTop; + tb.style.width = tt.offsetWidth + 'px'; + tb.style.height = tt.offsetHeight + 'px'; + tt.style.top = tb.style.top = y + 'px'; + tt.style.left = tb.style.left = x + 'px'; + tt.style.visibility = tb.style.visibility = 'visible'; +} + +// highlight/unhighlight text +function high(e,on) { + var targ; + if (e.target) targ = e.target; + else if (e.srcElement) targ = e.srcElement; + if (targ.nodeType == 3) targ = targ.parentNode; // defeat Safari bug + if (!targ.name) targ = targ.parentNode; // go up another level if necessary + if (targ.name && document.getElementsByName) { + // un-highlight current objects + if (hlist) { + for (var i=0; i<hlist.length; ++i) { + for (var j=0; j<hlist[i].length; ++j) { + hlist[i][j].style.background = 'transparent'; + } + } + hlist = null; + } + if (tt) { + // hide old tooltip + tt.style.visibility = tb.style.visibility = 'hidden'; + tt = null; + } + if (on) { + if (targ.name.substring(0,1) == 't') { + // show our tooltip (ID is different than name to avoid confusing IE) + tt = document.getElementById('p' + targ.name.substring(1)); + if (tt) { + tb = document.getElementById('tb'); + move(e); + } + } + // highlight anchor elements with the same name + hlist = new Array; + hlist.push(document.getElementsByName(targ.name)); + // is this an IFD pointer? + var pos = targ.className.indexOf('Offset_'); + if (pos > 0) { + // add elements from this IFD to our highlight list + hlist.push(document.getElementsByClassName(targ.className.substr(pos+7))); + } + // use class name to highlight span elements if necessary + for (var i=0; i<mspan.length; ++i) { + if (mspan[i] != targ.name) continue; + // add these span elements to our highlight list + hlist.push(GetElementsByClass(targ.name, 'span')); + break; + } + for (var i=0; i<hlist.length; ++i) { + for (var j=0; j<hlist[i].length; ++j) { + hlist[i][j].style.background = '#ffcc99'; + } + } + } + } +} +_END_PART_2_ + +my $htmlHeader3 = q[ +// End ---> +</script></head> +<body><noscript><b class=V>--&gt; +Enable JavaScript for active highlighting and information tool tips! +</b></noscript> +<table class=dump cellspacing=0 cellpadding=2> +<tr><td valign='top'><pre>]; + +my $preMouse = q(<pre onmouseover="high(event,1)" onmouseout="high(event,0)" onmousemove="move(event)">); + +#------------------------------------------------------------------------------ +# New - create new HtmlDump object +# Inputs: 0) reference to HtmlDump object or HtmlDump class name +sub new +{ + local $_; + my $that = shift; + my $class = ref($that) || $that || 'Image::ExifTool::HtmlDump'; + return bless { Block => {}, TipNum => 0 }, $class; +} + +#------------------------------------------------------------------------------ +# Add information to dump +# Inputs: 0) HTML dump hash ref, 1) absolute offset in file, 2) data size, +# 3) comment string, 4) tool tip (or SAME to use previous tip), +# 5) bit flags (see below), 6) IFD name +# Bits: 0x01 - print at start of line +# 0x02 - print red address +# 0x04 - maker notes data ('M'-class span) +# 0x08 - limit block length +# 0x10 - allow double references +# 0x100 - (reserved) +# Notes: Block will be shown in 'unused' color if comment string begins with '[' +sub Add($$$$;$$) +{ + my ($self, $start, $size, $msg, $tip, $flag, $ifd) = @_; + my $block = $$self{Block}; + $$block{$start} or $$block{$start} = [ ]; + my $htip; + if ($tip and $tip eq 'SAME') { + $htip = ''; + } else { + # use message as first line of tip, and make bold unless in brackets + $htip = ($msg =~ /^[[(]/) ? $msg : "<b>$msg</b>"; + if (defined $tip) { + ($tip = EscapeHTML($tip)) =~ s/\n/<br>/g; # HTML-ize tooltip text + $htip .= '<br>' . $tip; + } + # add size if not already done + $htip .= "<br>($size bytes)" unless $htip =~ /<br>Size:/; + ++$self->{TipNum}; + } + push @{$$block{$start}}, [ $size, $msg, $htip, $flag, $self->{TipNum}, $ifd ]; +} + +#------------------------------------------------------------------------------ +# Print dump information to HTML page +# Inputs: 0) Dump information hash reference, 1) source file RAF reference, +# 2) data pointer, 3) data position, 4) output file or scalar reference, +# 5) limit level (1-3), 6) title +# Returns: non-zero if useful output was generated, +# or -1 on error loading data and "ERROR" is set to offending data name +# Note: The "Error" member may be set externally to print a specific error +# message instead of doing the dump. +sub Print($$;$$$$$) +{ + local $_; + my ($self, $raf, $dataPt, $dataPos, $outfile, $level, $title) = @_; + my ($i, $buff, $rtnVal, $limit, $err); + my $block = $$self{Block}; + $dataPos = 0 unless $dataPos; + $outfile = \*STDOUT unless ref $outfile; + $title = 'HtmlDump' unless $title; + $level or $level = 0; + my $tell = $raf->Tell(); + my $pos = 0; + my $dataEnd = $dataPos + ($dataPt ? length($$dataPt) : 0); + # initialize member variables + $$self{Open} = []; + $$self{Closed} = []; + $$self{TipList} = []; + $$self{MSpanList} = []; + $$self{Cols} = [ '', '', '', '' ]; # text columns + # set dump size limits (limits are 4x smaller if bit 0x08 set in flags) + if ($level <= 1) { + $limit = 1024; + } elsif ($level <= 2) { + $limit = 16384; + } else { + $limit = 256 * 1024 * 1024; # never dump bigger than 256 MB + } + $$self{Limit} = $limit; + # pre-initialize open/closed hashes for all columns + for ($i=0; $i<4; ++$i) { + $self->{Open}->[$i] = { ID => [ ], Element => { } }; + $self->{Closed}->[$i] = { ID => [ ], Element => { } }; + } + $bkgStart = $bkgEnd = 0; + undef @bkgSpan; + my $index = 0; # initialize tooltip index + my (@names, $wasUnused, @starts); + # only do dump if we didn't have a serious error + @starts = sort { $a <=> $b } keys %$block unless $$self{Error}; + for ($i=0; $i<=@starts; ++$i) { + my $start = $starts[$i]; + my $parmList; + if (defined $start) { + $parmList = $$block{$start}; + } elsif ($bkgEnd and $pos < $bkgEnd and not defined $wasUnused) { + $start = $bkgEnd; # finish last bkg block + } else { + last; + } + my $len = $start - $pos; + if ($len > 0 and not $wasUnused) { + # we have a unused bytes before this data block + --$i; # dump the data block next time around + # split unused data into 2 blocks if it spans end of a bkg block + my ($nextBkgEnd, $bkg); + if (not defined $wasUnused and $bkgEnd) { + foreach $bkg (@bkgSpan) { + next if $pos >= $$bkg{End} + $dataPos or $pos + $len <= $$bkg{End} + $dataPos; + $nextBkgEnd = $$bkg{End} unless $nextBkgEnd and $nextBkgEnd < $$bkg{End}; + } + } + if ($nextBkgEnd) { + $start = $pos; + $len = $nextBkgEnd + $dataPos - $pos; + $wasUnused = 0; + } else { + $start = $pos; # dump the unused bytes now + $wasUnused = 1; # avoid re-dumping unused bytes if we get a read error + } + my $str = ($len > 1) ? "unused $len bytes" : 'pad byte'; + $parmList = [ [ $len, "[$str]", undef, 0x108 ] ]; + } else { + undef $wasUnused; + } + my $parms; + foreach $parms (@$parmList) { + my ($len, $msg, $tip, $flag, $tipNum, $ifd) = @$parms; + next unless $len > 0; + $flag = 0 unless defined $flag; + # generate same name for all blocks indexed by this tooltip + my $name; + $name = $names[$tipNum] if defined $tipNum; + my $idx = $index; + if ($name) { + # get index from existing ID + $idx = substr($name, 1); + } else { + $name = "t$index"; + $names[$tipNum] = $name if defined $tipNum; + ++$index; + } + if ($flag & 0x14) { + my $class = $flag & 0x04 ? "$name M" : $name; + $class .= " $ifd" if $ifd; + my %bkg = ( + Class => $class, + Start => $start - $dataPos, + End => $start - $dataPos + $len, + ); + push @bkgSpan, \%bkg; + $bkgStart = $bkg{Start} unless $bkgStart and $bkgStart < $bkg{Start}; + $bkgEnd = $bkg{End} unless $bkgEnd and $bkgEnd > $bkg{End}; + push @{$self->{MSpanList}}, $name; + next; + } + # loop until we read the value properly + my ($end, $try); + for ($try=0; $try<2; ++$try) { + $end = $start + $len; + # only load as much of the block as we are going to dump + # (read 32 more bytes than necessary just in case there + # is only one skipped line that we decide to print) + my $size = ($len > $limit + 32) ? $limit / 2 + 16 : $len; + if ($start >= $dataPos and $end <= $dataEnd) { + $buff = substr($$dataPt, $start-$dataPos, $size); + if ($len != $size) { + $buff .= substr($$dataPt, $start-$dataPos+$len-$size, $size); + } + } else { + $buff = ''; + if ($raf->Seek($start, 0) and $raf->Read($buff, $size) == $size) { + # read end of block + if ($len != $size) { + my $buf2 = ''; + unless ($raf->Seek($start+$len-$size, 0) and + $raf->Read($buf2, $size) == $size) + { + $err = $msg; + # reset $len to the actual length of available data + $raf->Seek(0, 2); + $len = $raf->Tell() - $start; + $tip .= "<br>Error: Only $len bytes available!" if $tip; + next; + } + $buff .= $buf2; + undef $buf2; + } + } else { + $err = $msg; + $len = length $buff; + $tip .= "<br>Error: Only $len bytes available!" if $tip; + } + } + last; + } + $tip and $self->{TipList}->[$idx] = $tip; + next unless length $buff; + # set flag to continue this line if next block is contiguous + if ($i+1 < @starts and $parms eq $$parmList[-1] and + ($end == $starts[$i+1] or ($end < $starts[$i+1] and $end >= $pos))) + { + my $nextFlag = $block->{$starts[$i+1]}->[0]->[3] || 0; + $flag |= 0x100 unless $flag & 0x01 or $nextFlag & 0x01; + } + $self->DumpTable($start-$dataPos, \$buff, $msg, $name, + $flag, $len, $pos-$dataPos, $ifd); + undef $buff; + $pos = $end if $pos < $end; + } + } + $self->Open('',''); # close all open elements + $raf->Seek($tell,0); + + # write output HTML file + Write($outfile, $htmlHeader1, $title); + if ($self->{Cols}->[0]) { + Write($outfile, $htmlHeader2); + my $mspan = \@{$$self{MSpanList}}; + for ($i=0; $i<@$mspan; ++$i) { + Write($outfile, qq(mspan[$i] = "$$mspan[$i]";\n)); + } + Write($outfile, $htmlHeader3, $self->{Cols}->[0]); + Write($outfile, '</pre></td><td valign="top">', + $preMouse, $self->{Cols}->[1]); + Write($outfile, '</pre></td><td class=c2 valign="top">', + $preMouse, $self->{Cols}->[2]); + Write($outfile, '</pre></td><td valign="top">', + $preMouse, $self->{Cols}->[3]); + Write($outfile, "</pre></td></tr></table>\n<div id=tb class=tb> </div>\n"); + my $tips = \@{$$self{TipList}}; + for ($i=0; $i<@$tips; ++$i) { + my $tip = $$tips[$i]; + Write($outfile, "<div id=p$i class=tt>$tip</div>\n") if defined $tip; + } + delete $$self{TipList}; + $rtnVal = 1; + } else { + my $err = $$self{Error} || 'No EXIF or TIFF information found in image'; + Write($outfile, "$title</title></head><body>\n$err\n"); + $rtnVal = 0; + } + Write($outfile, "</body></html>\n"); + for ($i=0; $i<4; ++$i) { + $self->{Cols}->[$i] = ''; # free memory + } + if ($err) { + $err =~ tr/()//d; + $$self{ERROR} = $err; + return -1; + } + return $rtnVal; +} + +#------------------------------------------------------------------------------ +# Open or close a specified html element +# Inputs: 0) HtmlDump object ref, 1) element id, 2) element string, +# 3-N) list of column numbers (empty for all columns) +# - element id may be '' to close all elements +# - element string may be '' to close element by ID (or 0 to close without reopening) +# - element id and string may both be 1 to reopen temporarily closed elements +sub Open($$$;@) +{ + my ($self, $id, $element, @colNums) = @_; + + # loop through specified columns + @colNums or @colNums = (0 .. $#{$self->{Open}}); + my $col; + foreach $col (@colNums) { + # get information about open elements in this column + my $opHash = $self->{Open}->[$col]; + my $opElem = $$opHash{Element}; + if ($element) { + # next if already open + next if $$opElem{$id} and $$opElem{$id} eq $element; + } elsif ($id and not $$opElem{$id}) { + # next if already closed and nothing to reopen + next unless $element eq '' and @{$self->{Closed}->[$col]->{ID}}; + } + my $opID = $$opHash{ID}; + my $clHash = $self->{Closed}->[$col]; + my $clID = $$clHash{ID}; + my $clElem = $$clHash{Element}; + # get reference to output column list (use temp list if available) + my $cols = $$self{TmpCols} || $$self{Cols}; + # close everything down to this element if necessary + if ($$opElem{$id} or not $id) { + while (@$opID) { + my $tid = pop @$opID; + my $e = $$opElem{$tid}; + $e =~ s/^<(\S+).*/<\/$1>/s; + $$cols[$col] .= $e; + if ($id eq $tid or not $id) { + delete $$opElem{$tid}; + last if $id; + next; + } + # add this to the temporarily closed list + # (because we really didn't want to close it) + push @$clID, $tid; + $$clElem{$tid} = $$opElem{$tid}; + delete $$opElem{$tid}; + } + unless ($id) { + # forget all temporarily closed elements + $clID = $$clHash{ID} = [ ]; + $clElem = $$clHash{Element} = { }; + } + } elsif ($$clElem{$id}) { + # delete from the list of temporarily closed elements + delete $$clElem{$id}; + @$clID = grep !/^$id$/, @$clID; + } + next if $element eq '0'; # 0 = don't reopen temporarily closed elements + + # re-open temporarily closed elements + while (@$clID) { + my $tid = pop @$clID; + $$cols[$col] .= $$clElem{$tid}; + push @$opID, $tid; + $$opElem{$tid} = $$clElem{$tid}; + delete $$clElem{$tid}; + } + # open specified element + if ($element and $element ne '1') { + $$cols[$col] .= $element; + push @$opID, $id; + $$opElem{$id} = $element; + } + } +} + +#------------------------------------------------------------------------------ +# Dump a block of data in HTML table form +# Inputs: 0) HtmlDump object ref, 1) data position, 2) block pointer, +# 3) message, 4) object name, 5) flag, 6) full block length (actual +# data may be shorter), 7) data end position, 8) IFD name +sub DumpTable($$$;$$$$$$) +{ + my ($self, $pos, $blockPt, $msg, $name, $flag, $len, $endPos, $ifd) = @_; + $len = length $$blockPt unless defined $len; + $endPos = 0 unless $endPos; + my ($f0, $dblRef, $id); + my $skipped = 0; + if (($endPos and $pos < $endPos) or $flag & 0x02) { + # display double-reference addresses in red + $f0 = "<span class=V>"; + $dblRef = 1 if $endPos and $pos < $endPos; + } else { + $f0 = ''; + } + my @c = ('','','',''); + $$self{TmpCols} = \@c; + if ($name) { + if ($msg and $msg =~ /^\[/) { + $id = 'U'; + } else { + if ($$self{A}) { + $id = 'X'; + $$self{A} = 0; + } else { + $id = 'V'; + $$self{A} = 1; + } + ++$id unless $dblRef; + } + my $class = $ifd ? "'$id $ifd'" : $id; + $name = "<a name=$name class=$class>"; + $msg and $msg = "$name$msg</a>"; + } else { + $name = ''; + } + # use base-relative offsets from now on + my $cols = 0; + my $p = $pos; + if ($$self{Cont}) { + $cols = $pos & 0x0f; + $c[1] .= ($cols == 8) ? ' ' : ' '; + } else { + my $addr = $pos < 0 ? sprintf("-%.4x",-$pos) : sprintf("%5.4x",$pos); + $self->Open('fgd', $f0, 0); + $self->Open('fgd', '', 3); + $c[0] .= "$addr"; + $p -= $pos & 0x0f unless $flag & 0x01; + if ($p < $pos) { + $self->Open('bkg', '', 1, 2); # don't underline white space + $cols = $pos - $p; + my $n = 3 * $cols; + ++$n if $cols > 7; + $c[1] .= ' ' x $n; + $c[2] .= ' ' x $cols; + $p = $pos; + } + } + # loop through each column of hex numbers + for (;;) { + my (@spanClass, @spanCont, $spanClose, $bkg); + if ($p >= $bkgStart and $p < $bkgEnd) { + foreach $bkg (@bkgSpan) { + next unless $p >= $$bkg{Start} and $p < $$bkg{End}; + push @spanClass, $$bkg{Class}; + if ($p + 1 == $$bkg{End}) { + $spanClose = 1; + } else { + push @spanCont, $$bkg{Class}; # this span continues + } + } + $self->Open('bkg', @spanClass ? "<span class='@spanClass'>" : '', 1, 2); + } else { + $self->Open('bkg', '', 1, 2); + } + $self->Open('a', $name, 1, 2); + my $ch = substr($$blockPt,$p-$pos-$skipped,1); + $c[1] .= sprintf("%.2x", ord($ch)); + # make the character HTML-friendly + $ch =~ tr/\x00-\x1f\x7f-\xff/./; + $ch =~ s/&/&amp;/g; + $ch =~ s/>/&gt;/g; + $ch =~ s/</&lt;/g; + $c[2] .= $ch; + ++$p; + ++$cols; + # close necessary elements + if ($spanClose) { + my $spanCont = @spanCont ? "<span class='@spanCont'>" : ''; + # close without reopening if closing anchor later + my $arg = ($p - $pos >= $len) ? 0 : $spanCont; + $self->Open('bkg', $arg, 1, 2); + } + if ($dblRef and $p >= $endPos) { + $dblRef = 0; + ++$id; + my $class = $ifd ? "'$id $ifd'" : $id; + $name =~ s/class=\w\b/class=$class/; + $f0 = ''; + $self->Open('fgd', $f0, 0); + } + if ($p - $pos >= $len) { + $self->Open('a', '', 1, 2); # close our anchor + last; + } + if ($cols < 16) { + $c[1] .= ($cols == 8 ? ' ' : ' '); + next; + } elsif ($flag & 0x01 and $cols < $len) { + $c[1] .= ' '; + next; # put it all on one line + } + unless ($$self{Msg}) { + $c[3] .= $msg; + $msg = ''; + } + $_ .= "\n" foreach @c; # add CR to all lines + $$self{Msg} = 0; + # limit data length if specified + if ($$self{Limit}) { + my $div = ($flag & 0x08) ? 4 : 1; + my $lim = $$self{Limit} / (2 * $div) - 16; + if ($p - $pos > $lim and $len - $p + $pos > $lim) { + my $n = ($len - $p + $pos - $lim) & ~0x0f; + if ($n > 16) { # (no use just cutting out one line) + $self->Open('bkg', '', 1, 2); # no underline + my $note = sprintf "[snip %d lines]", $n / 16; + $note = (' ' x (24-length($note)/2)) . $note; + $c[0] .= " ...\n"; + $c[1] .= $note . (' ' x (48-length($note))) . "\n"; + $c[2] .= " [snip] \n"; + $c[3] .= "\n"; + $p += $n; + $skipped += $len - length $$blockPt; + } + } + } + $c[0] .= ($p < 0 ? sprintf("-%.4x",-$p) : sprintf("%5.4x",$p)); + $cols = 0; + } + if ($msg) { + $msg = " $msg" if $$self{Msg}; + $c[3] .= $msg; + } + if ($flag & 0x100 and $cols < 16) { # continue on same line? + $$self{Cont} = 1; + $$self{Msg} = 1 if $msg; + } else { + $_ .= "\n" foreach @c; + $$self{Msg} = 0; + $$self{Cont} = 0; + } + # add temporary column data to our real columns + my $i; + for ($i=0; $i<4; ++$i) { + $self->{Cols}->[$i] .= $c[$i]; + } + delete $$self{TmpCols}; +} + +#------------------------------------------------------------------------------ +# Finish dumping of TIFF image data +# Inputs: 0) HtmlDump object ref, 1) ExifTool object ref, 2) length of file +# (this really belongs in Image::ExifTool::Exif, but is placed here so it +# is only compiled when needed) +sub FinishTiffDump($$$) +{ + my ($self, $et, $size) = @_; + my ($tag, $key, $start, $blockInfo, $i); + + # list of all indirectly referenced TIFF data tags + my %offsetPair = ( + StripOffsets => 'StripByteCounts', + TileOffsets => 'TileByteCounts', + FreeOffsets => 'FreeByteCounts', + ThumbnailOffset => 'ThumbnailLength', + PreviewImageStart => 'PreviewImageLength', + JpgFromRawStart => 'JpgFromRawLength', + OtherImageStart => 'OtherImageLength', + ImageOffset => 'ImageByteCount', + AlphaOffset => 'AlphaByteCount', + MPImageStart => 'MPImageLength', + IDCPreviewStart => 'IDCPreviewLength', + SamsungRawPointersOffset => 'SamsungRawPointersLength', + ); + + # add TIFF data to html dump + foreach $tag (keys %offsetPair) { + my $info = $et->GetInfo($tag); + next unless %$info; + # Panasonic hack: StripOffsets is not valid for Panasonic RW2 files, + # and StripRowBytes is not valid for some RAW images + if ($tag eq 'StripOffsets' and $$et{TAG_INFO}{$tag}{PanasonicHack}) { + # use RawDataOffset instead if available since it is valid in RW2 + my $info2 = $et->GetInfo('RawDataOffset'); + $info2 = $info unless %$info2; + my @keys = keys %$info2; + my $offset = $$info2{$keys[0]}; + my $raf = $$et{RAF}; + # ignore StripByteCounts and assume raw data runs to the end of file + if (@keys == 1 and $offset =~ /^\d+$/ and $raf) { + my $pos = $raf->Tell(); + $raf->Seek(0, 2); # seek to end + my $len = $raf->Tell() - $offset; + $raf->Seek($pos, 0); + if ($len > 0) { + $self->Add($offset, $len, "(Panasonic raw data)", "Size: $len bytes", 0x08); + next; + } + } + } + # loop through all offsets tags + foreach $key (keys %$info) { + my $name = Image::ExifTool::GetTagName($key); + my $grp1 = $et->GetGroup($key, 1); + my $info2 = $et->GetInfo($offsetPair{$tag}, { Group1 => $grp1 }); + my $key2 = $offsetPair{$tag}; + $key2 .= $1 if $key =~ /( .*)/; # use same instance number as $tag + next unless $$info2{$key2}; + my $offsets = $$info{$key}; + my $byteCounts = $$info2{$key2}; + # ignore primary MPImage (this is the whole JPEG) + next if $tag eq 'MPImageStart' and $offsets eq '0'; + # (long lists may be SCALAR references) + my @offsets = split ' ', (ref $offsets ? $$offsets : $offsets); + my @byteCounts = split ' ', (ref $byteCounts ? $$byteCounts : $byteCounts); + my $num = scalar @offsets; + my $li = 0; + my $padBytes = 0; + for ($i=0; @offsets and @byteCounts; ++$i) { + my $offset = shift @offsets; + my $byteCount = shift @byteCounts; + my $end = $offset + $byteCount; + if (@offsets and @byteCounts) { + # show data as contiguous if only normal pad bytes between blocks + if ($end & 0x01 and $end + 1 == $offsets[0]) { + $end += 1; + ++$padBytes; # count them + } + if ($end == $offsets[0]) { + # combine these two blocks + $byteCounts[0] += $offsets[0] - $offset; + $offsets[0] = $offset; + next; + } + } + my $msg = $et->GetGroup($key, 1) . ':' . $tag; + $msg =~ s/(Offsets?|Start)$/ /; + if ($num > 1) { + $msg .= "$li-" if $li != $i; + $msg .= "$i "; + $li = $i + 1; + } + $msg .= "data"; + my $tip = "Size: $byteCount bytes"; + $tip .= ", incl. $padBytes pad bytes" if $padBytes; + $self->Add($offset, $byteCount, "($msg)", $tip, 0x08); + } + } + } + # find offset of last dumped information, and dump any unknown trailer + my $last = 0; + my $block = $$self{Block}; + foreach $start (keys %$block) { + foreach $blockInfo (@{$$block{$start}}) { + my $end = $start + $$blockInfo[0]; + $last = $end if $last < $end; + } + } + my $diff = $size - $last; + if ($diff > 0 and ($last or $et->Options('Unknown'))) { + if ($diff > 1 or $size & 0x01) { + $self->Add($last, $diff, "[unknown data]", "Size: $diff bytes", 0x08); + } else { + $self->Add($last, $diff, "[trailing pad byte]", undef, 0x08); + } + } +} + +#------------------------------------------------------------------------------ +# utility routine to write to file or memory +# Inputs: 0) file or scalar reference, 1-N) list of stuff to write +# Returns: true on success +sub Write($@) +{ + my $outfile = shift; + if (UNIVERSAL::isa($outfile,'GLOB')) { + return print $outfile @_; + } elsif (ref $outfile eq 'SCALAR') { + $$outfile .= join('', @_); + return 1; + } + return 0; +} + +1; # end + +__END__ + +=head1 NAME + +Image::ExifTool::HtmlDump - Dump information in hex to HTML page + +=head1 SYNOPSIS + + use Image::ExifTool::HtmlDump; + my $dump = new Image::ExifTool::HtmlDump; + $dump->Add($start, $size, $comment); + $dump->Print($dumpInfo, $raf, $dataPt, $dataPos, $outfile); + +=head1 DESCRIPTION + +This module contains code used to generate an HTML-based hex dump of +information for debugging purposes. This is code is called when the +ExifTool 'HtmlDump' option is used. + +Currently, only EXIF/TIFF and JPEG information is dumped. + +=head1 BUGS + +Due to a memory allocation bug in ActivePerl 5.8.x for Windows, this code +may run extremely slowly when processing large files with this version of +Perl. + +An HTML 4 compliant browser is needed to properly display the generated HTML +page. + +=head1 AUTHOR + +Copyright 2003-2019, Phil Harvey (phil at owl.phy.queensu.ca) + +This library is free software; you can redistribute it and/or modify it +under the same terms as Perl itself. + +=head1 SEE ALSO + +L<Image::ExifTool(3pm)|Image::ExifTool> + +=cut + diff --git a/lib/Image/ExifTool/ICC_Profile.pm b/lib/Image/ExifTool/ICC_Profile.pm new file mode 100644 index 0000000..3777e7d --- /dev/null +++ b/lib/Image/ExifTool/ICC_Profile.pm @@ -0,0 +1,1287 @@ +#------------------------------------------------------------------------------ +# File: ICC_Profile.pm +# +# Description: Read ICC Profile meta information +# +# Revisions: 11/16/2004 - P. Harvey Created +# +# References: 1) http://www.color.org/icc_specs2.html (ICC.1:2003-09) +# 2) http://www.color.org/icc_specs2.html (ICC.1:2001-04) +# 3) http://developer.apple.com/documentation/GraphicsImaging/Reference/ColorSync_Manager/ColorSync_Manager.pdf +# 4) http://www.color.org/privatetag2007-01.pdf +# 5) http://www.color.org/icc_specs2.xalter (approved revisions, 2010-07-16) +# 6) Eef Vreeland private communication +# +# Notes: The ICC profile information is different: the format of each +# tag is embedded in the information instead of in the directory +# structure. This makes things a bit more complex because I need +# an extra level of logic to decode the variable-format tags. +#------------------------------------------------------------------------------ + +package Image::ExifTool::ICC_Profile; + +use strict; +use vars qw($VERSION); +use Image::ExifTool qw(:DataAccess :Utils); + +$VERSION = '1.35'; + +sub ProcessICC($$); +sub ProcessICC_Profile($$$); +sub WriteICC_Profile($$;$); +sub ProcessMetadata($$$); +sub ValidateICC($); + +# illuminant type definitions +my %illuminantType = ( + 1 => 'D50', + 2 => 'D65', + 3 => 'D93', + 4 => 'F2', + 5 => 'D55', + 6 => 'A', + 7 => 'Equi-Power (E)', + 8 => 'F8', +); +my %profileClass = ( + scnr => 'Input Device Profile', + mntr => 'Display Device Profile', + prtr => 'Output Device Profile', + 'link'=> 'DeviceLink Profile', + spac => 'ColorSpace Conversion Profile', + abst => 'Abstract Profile', + nmcl => 'NamedColor Profile', + nkpf => 'Nikon Input Device Profile (NON-STANDARD!)', # (written by Nikon utilities) +); +my %manuSig = ( #6 + 'NONE' => 'none', + 'none' => 'none', #PH + '' => '', #PH + '4d2p' => 'Erdt Systems GmbH & Co KG', + 'AAMA' => 'Aamazing Technologies, Inc.', + 'ACER' => 'Acer Peripherals', + 'ACLT' => 'Acolyte Color Research', + 'ACTI' => 'Actix Sytems, Inc.', + 'ADAR' => 'Adara Technology, Inc.', + 'ADBE' => 'Adobe Systems Inc.', + 'ADI ' => 'ADI Systems, Inc.', + 'AGFA' => 'Agfa Graphics N.V.', + 'ALMD' => 'Alps Electric USA, Inc.', + 'ALPS' => 'Alps Electric USA, Inc.', + 'ALWN' => 'Alwan Color Expertise', + 'AMTI' => 'Amiable Technologies, Inc.', + 'AOC ' => 'AOC International (U.S.A), Ltd.', + 'APAG' => 'Apago', + 'APPL' => 'Apple Computer Inc.', + 'appl' => 'Apple Computer Inc.', + 'AST ' => 'AST', + 'AT&T' => 'AT&T Computer Systems', + 'BAEL' => 'BARBIERI electronic', + 'berg' => 'bergdesign incorporated', + 'bICC' => 'basICColor GmbH', + 'BRCO' => 'Barco NV', + 'BRKP' => 'Breakpoint Pty Limited', + 'BROT' => 'Brother Industries, LTD', + 'BULL' => 'Bull', + 'BUS ' => 'Bus Computer Systems', + 'C-IT' => 'C-Itoh', + 'CAMR' => 'Intel Corporation', + 'CANO' => 'Canon, Inc. (Canon Development Americas, Inc.)', + 'CARR' => 'Carroll Touch', + 'CASI' => 'Casio Computer Co., Ltd.', + 'CBUS' => 'Colorbus PL', + 'CEL ' => 'Crossfield', + 'CELx' => 'Crossfield', + 'ceyd' => 'Integrated Color Solutions, Inc.', + 'CGS ' => 'CGS Publishing Technologies International GmbH', + 'CHM ' => 'Rochester Robotics', + 'CIGL' => 'Colour Imaging Group, London', + 'CITI' => 'Citizen', + 'CL00' => 'Candela, Ltd.', + 'CLIQ' => 'Color IQ', + 'clsp' => 'MacDermid ColorSpan, Inc.', + 'CMCO' => 'Chromaco, Inc.', + 'CMiX' => 'CHROMiX', + 'COLO' => 'Colorgraphic Communications Corporation', + 'COMP' => 'COMPAQ Computer Corporation', + 'COMp' => 'Compeq USA/Focus Technology', + 'CONR' => 'Conrac Display Products', + 'CORD' => 'Cordata Technologies, Inc.', + 'CPQ ' => 'Compaq Computer Corporation', + 'CPRO' => 'ColorPro', + 'CRN ' => 'Cornerstone', + 'CTX ' => 'CTX International, Inc.', + 'CVIS' => 'ColorVision', + 'CWC ' => 'Fujitsu Laboratories, Ltd.', + 'DARI' => 'Darius Technology, Ltd.', + 'DATA' => 'Dataproducts', + 'DCP ' => 'Dry Creek Photo', + 'DCRC' => 'Digital Contents Resource Center, Chung-Ang University', + 'DELL' => 'Dell Computer Corporation', + 'DIC ' => 'Dainippon Ink and Chemicals', + 'DICO' => 'Diconix', + 'DIGI' => 'Digital', + 'DL&C' => 'Digital Light & Color', + 'DPLG' => 'Doppelganger, LLC', + 'DS ' => 'Dainippon Screen', + 'ds ' => 'Dainippon Screen', + 'DSOL' => 'DOOSOL', + 'DUPN' => 'DuPont', + 'dupn' => 'DuPont', + 'Eizo' => 'EIZO NANAO CORPORATION', + 'EPSO' => 'Epson', + 'ESKO' => 'Esko-Graphics', + 'ETRI' => 'Electronics and Telecommunications Research Institute', + 'EVER' => 'Everex Systems, Inc.', + 'EXAC' => 'ExactCODE GmbH', + 'FALC' => 'Falco Data Products, Inc.', + 'FF ' => 'Fuji Photo Film Co.,LTD', + 'FFEI' => 'FujiFilm Electronic Imaging, Ltd.', + 'ffei' => 'FujiFilm Electronic Imaging, Ltd.', + 'flux' => 'FluxData Corporation', + 'FNRD' => 'fnord software', + 'FORA' => 'Fora, Inc.', + 'FORE' => 'Forefront Technology Corporation', + 'FP ' => 'Fujitsu', + 'FPA ' => 'WayTech Development, Inc.', + 'FUJI' => 'Fujitsu', + 'FX ' => 'Fuji Xerox Co., Ltd.', + 'GCC ' => 'GCC Technologies, Inc.', + 'GGSL' => 'Global Graphics Software Limited', + 'GMB ' => 'Gretagmacbeth', + 'GMG ' => 'GMG GmbH & Co. KG', + 'GOLD' => 'GoldStar Technology, Inc.', + 'GOOG' => 'Google', #PH + 'GPRT' => 'Giantprint Pty Ltd', + 'GTMB' => 'Gretagmacbeth', + 'GVC ' => 'WayTech Development, Inc.', + 'GW2K' => 'Sony Corporation', + 'HCI ' => 'HCI', + 'HDM ' => 'Heidelberger Druckmaschinen AG', + 'HERM' => 'Hermes', + 'HITA' => 'Hitachi America, Ltd.', + 'HiTi' => 'HiTi Digital, Inc.', + 'HP ' => 'Hewlett-Packard', + 'HTC ' => 'Hitachi, Ltd.', + 'IBM ' => 'IBM Corporation', + 'IDNT' => 'Scitex Corporation, Ltd.', + 'Idnt' => 'Scitex Corporation, Ltd.', + 'IEC ' => 'Hewlett-Packard', + 'IIYA' => 'Iiyama North America, Inc.', + 'IKEG' => 'Ikegami Electronics, Inc.', + 'IMAG' => 'Image Systems Corporation', + 'IMI ' => 'Ingram Micro, Inc.', + 'Inca' => 'Inca Digital Printers Ltd.', + 'INTC' => 'Intel Corporation', + 'INTL' => 'N/A (INTL)', + 'INTR' => 'Intra Electronics USA, Inc.', + 'IOCO' => 'Iocomm International Technology Corporation', + 'IPS ' => 'InfoPrint Solutions Company', + 'IRIS' => 'Scitex Corporation, Ltd.', + 'Iris' => 'Scitex Corporation, Ltd.', + 'iris' => 'Scitex Corporation, Ltd.', + 'ISL ' => 'Ichikawa Soft Laboratory', + 'ITNL' => 'N/A (ITNL)', + 'IVM ' => 'IVM', + 'IWAT' => 'Iwatsu Electric Co., Ltd.', + 'JPEG' => 'Joint Photographic Experts Group', #PH + 'JSFT' => 'Jetsoft Development', + 'JVC ' => 'JVC Information Products Co.', + 'KART' => 'Scitex Corporation, Ltd.', + 'Kart' => 'Scitex Corporation, Ltd.', + 'kart' => 'Scitex Corporation, Ltd.', + 'KFC ' => 'KFC Computek Components Corporation', + 'KLH ' => 'KLH Computers', + 'KMHD' => 'Konica Minolta Holdings, Inc.', + 'KNCA' => 'Konica Corporation', + 'KODA' => 'Kodak', + 'KYOC' => 'Kyocera', + 'LCAG' => 'Leica Camera AG', + 'LCCD' => 'Leeds Colour', + 'lcms' => 'Little CMS', #NealKrawetz + 'LDAK' => 'Left Dakota', + 'LEAD' => 'Leading Technology, Inc.', + 'Leaf' => 'Leaf', #PH + 'LEXM' => 'Lexmark International, Inc.', + 'LINK' => 'Link Computer, Inc.', + 'LINO' => 'Linotronic', + 'Lino' => 'Linotronic', #PH (NC) + 'lino' => 'Linotronic', #PH (NC) + 'LITE' => 'Lite-On, Inc.', + 'MAGC' => 'Mag Computronic (USA) Inc.', + 'MAGI' => 'MAG Innovision, Inc.', + 'MANN' => 'Mannesmann', + 'MICN' => 'Micron Technology, Inc.', + 'MICR' => 'Microtek', + 'MICV' => 'Microvitec, Inc.', + 'MINO' => 'Minolta', + 'MITS' => 'Mitsubishi Electronics America, Inc.', + 'MITs' => 'Mitsuba Corporation', + 'Mits' => 'Mitsubishi Electric Corporation Kyoto Works', + 'MNLT' => 'Minolta', + 'MODG' => 'Modgraph, Inc.', + 'MONI' => 'Monitronix, Inc.', + 'MONS' => 'Monaco Systems Inc.', + 'MORS' => 'Morse Technology, Inc.', + 'MOTI' => 'Motive Systems', + 'MSFT' => 'Microsoft Corporation', + 'MUTO' => 'MUTOH INDUSTRIES LTD.', + 'NANA' => 'NANAO USA Corporation', + 'NEC ' => 'NEC Corporation', + 'NEXP' => 'NexPress Solutions LLC', + 'NISS' => 'Nissei Sangyo America, Ltd.', + 'NKON' => 'Nikon Corporation', + 'ob4d' => 'Erdt Systems GmbH & Co KG', + 'obic' => 'Medigraph GmbH', + 'OCE ' => 'Oce Technologies B.V.', + 'OCEC' => 'OceColor', + 'OKI ' => 'Oki', + 'OKID' => 'Okidata', + 'OKIP' => 'Okidata', + 'OLIV' => 'Olivetti', + 'OLYM' => 'OLYMPUS OPTICAL CO., LTD', + 'ONYX' => 'Onyx Graphics', + 'OPTI' => 'Optiquest', + 'PACK' => 'Packard Bell', + 'PANA' => 'Matsushita Electric Industrial Co., Ltd.', + 'PANT' => 'Pantone, Inc.', + 'PBN ' => 'Packard Bell', + 'PFU ' => 'PFU Limited', + 'PHIL' => 'Philips Consumer Electronics Co.', + 'PNTX' => 'HOYA Corporation PENTAX Imaging Systems Division', + 'POne' => 'Phase One A/S', + 'PREM' => 'Premier Computer Innovations', + 'PRIN' => 'Princeton Graphic Systems', + 'PRIP' => 'Princeton Publishing Labs', + 'QLUX' => 'Hong Kong', + 'QMS ' => 'QMS, Inc.', + 'QPCD' => 'QPcard AB', + 'QUAD' => 'QuadLaser', + 'quby' => 'Qubyx Sarl', + 'QUME' => 'Qume Corporation', + 'RADI' => 'Radius, Inc.', + 'RDDx' => 'Integrated Color Solutions, Inc.', + 'RDG ' => 'Roland DG Corporation', + 'REDM' => 'REDMS Group, Inc.', + 'RELI' => 'Relisys', + 'RGMS' => 'Rolf Gierling Multitools', + 'RICO' => 'Ricoh Corporation', + 'RNLD' => 'Edmund Ronald', + 'ROYA' => 'Royal', + 'RPC ' => 'Ricoh Printing Systems,Ltd.', + 'RTL ' => 'Royal Information Electronics Co., Ltd.', + 'SAMP' => 'Sampo Corporation of America', + 'SAMS' => 'Samsung, Inc.', + 'SANT' => 'Jaime Santana Pomares', + 'SCIT' => 'Scitex Corporation, Ltd.', + 'Scit' => 'Scitex Corporation, Ltd.', + 'scit' => 'Scitex Corporation, Ltd.', + 'SCRN' => 'Dainippon Screen', + 'scrn' => 'Dainippon Screen', + 'SDP ' => 'Scitex Corporation, Ltd.', + 'Sdp ' => 'Scitex Corporation, Ltd.', + 'sdp ' => 'Scitex Corporation, Ltd.', + 'SEC ' => 'SAMSUNG ELECTRONICS CO.,LTD', + 'SEIK' => 'Seiko Instruments U.S.A., Inc.', + 'SEIk' => 'Seikosha', + 'SGUY' => 'ScanGuy.com', + 'SHAR' => 'Sharp Laboratories', + 'SICC' => 'International Color Consortium', + 'siwi' => 'SIWI GRAFIKA CORPORATION', + 'SONY' => 'SONY Corporation', + 'Sony' => 'Sony Corporation', + 'SPCL' => 'SpectraCal', + 'STAR' => 'Star', + 'STC ' => 'Sampo Technology Corporation', + 'TALO' => 'Talon Technology Corporation', + 'TAND' => 'Tandy', + 'TATU' => 'Tatung Co. of America, Inc.', + 'TAXA' => 'TAXAN America, Inc.', + 'TDS ' => 'Tokyo Denshi Sekei K.K.', + 'TECO' => 'TECO Information Systems, Inc.', + 'TEGR' => 'Tegra', + 'TEKT' => 'Tektronix, Inc.', + 'TI ' => 'Texas Instruments', + 'TMKR' => 'TypeMaker Ltd.', + 'TOSB' => 'TOSHIBA corp.', + 'TOSH' => 'Toshiba, Inc.', + 'TOTK' => 'TOTOKU ELECTRIC Co., LTD', + 'TRIU' => 'Triumph', + 'TSBT' => 'TOSHIBA TEC CORPORATION', + 'TTX ' => 'TTX Computer Products, Inc.', + 'TVM ' => 'TVM Professional Monitor Corporation', + 'TW ' => 'TW Casper Corporation', + 'ULSX' => 'Ulead Systems', + 'UNIS' => 'Unisys', + 'UTZF' => 'Utz Fehlau & Sohn', + 'VARI' => 'Varityper', + 'VIEW' => 'Viewsonic', + 'VISL' => 'Visual communication', + 'VIVO' => 'Vivo Mobile Communication Co., Ltd', + 'WANG' => 'Wang', + 'WLBR' => 'Wilbur Imaging', + 'WTG2' => 'Ware To Go', + 'WYSE' => 'WYSE Technology', + 'XERX' => 'Xerox Corporation', + 'XRIT' => 'X-Rite', + 'yxym' => 'YxyMaster GmbH', + 'Z123' => "Lavanya's test Company", + 'Zebr' => 'Zebra Technologies Inc', + 'ZRAN' => 'Zoran Corporation', + # also seen: " ",ACMS,KCMS,UCCM,etc2,SCTX +); + +# ICC_Profile tag table +%Image::ExifTool::ICC_Profile::Main = ( + GROUPS => { 2 => 'Image' }, + PROCESS_PROC => \&ProcessICC_Profile, + WRITE_PROC => \&WriteICC_Profile, + NOTES => q{ + ICC profile information is used in many different file types including JPEG, + TIFF, PDF, PostScript, Photoshop, PNG, MIFF, PICT, QuickTime, XCF and some + RAW formats. While the tags listed below are not individually writable, the + entire profile itself can be accessed via the extra 'ICC_Profile' tag, but + this tag is neither extracted nor written unless specified explicitly. See + L<http://www.color.org/icc_specs2.xalter> for the official ICC + specification. + }, + A2B0 => 'AToB0', + A2B1 => 'AToB1', + A2B2 => 'AToB2', + bXYZ => 'BlueMatrixColumn', # (called BlueColorant in ref 2) + bTRC => { + Name => 'BlueTRC', + Description => 'Blue Tone Reproduction Curve', + }, + B2A0 => 'BToA0', + B2A1 => 'BToA1', + B2A2 => 'BToA2', + calt => { + Name => 'CalibrationDateTime', + Groups => { 2 => 'Time' }, + PrintConv => '$self->ConvertDateTime($val)', + }, + targ => { + Name => 'CharTarget', + ValueConv => '$val=~s/\0.*//; length $val > 128 ? \$val : $val', + }, + chad => 'ChromaticAdaptation', + chrm => { + Name => 'Chromaticity', + Groups => { 1 => 'ICC_Profile#' }, #(just for the group list) + SubDirectory => { + TagTable => 'Image::ExifTool::ICC_Profile::Chromaticity', + Validate => '$type eq "chrm"', + }, + }, + clro => 'ColorantOrder', + clrt => { + Name => 'ColorantTable', + SubDirectory => { + TagTable => 'Image::ExifTool::ICC_Profile::ColorantTable', + Validate => '$type eq "clrt"', + }, + }, + clot => { # new in version 4.2 + Name => 'ColorantTableOut', + Binary => 1, + }, + cprt => { + Name => 'ProfileCopyright', + ValueConv => '$val=~s/\0.*//; $val', # may be null terminated + }, + crdi => 'CRDInfo', #2 + dmnd => { + Name => 'DeviceMfgDesc', + Groups => { 2 => 'Camera' }, + }, + dmdd => { + Name => 'DeviceModelDesc', + Groups => { 2 => 'Camera' }, + }, + devs => { + Name => 'DeviceSettings', #2 + Groups => { 2 => 'Camera' }, + }, + gamt => 'Gamut', + kTRC => { + Name => 'GrayTRC', + Description => 'Gray Tone Reproduction Curve', + }, + gXYZ => 'GreenMatrixColumn', # (called GreenColorant in ref 2) + gTRC => { + Name => 'GreenTRC', + Description => 'Green Tone Reproduction Curve', + }, + lumi => 'Luminance', + meas => { + Name => 'Measurement', + SubDirectory => { + TagTable => 'Image::ExifTool::ICC_Profile::Measurement', + Validate => '$type eq "meas"', + }, + }, + bkpt => 'MediaBlackPoint', + wtpt => 'MediaWhitePoint', + ncol => 'NamedColor', #2 + ncl2 => 'NamedColor2', + resp => 'OutputResponse', + pre0 => 'Preview0', + pre1 => 'Preview1', + pre2 => 'Preview2', + desc => 'ProfileDescription', + pseq => 'ProfileSequenceDesc', + psd0 => 'PostScript2CRD0', #2 + psd1 => 'PostScript2CRD1', #2 + psd2 => 'PostScript2CRD2', #2 + ps2s => 'PostScript2CSA', #2 + ps2i => 'PS2RenderingIntent', #2 + rXYZ => 'RedMatrixColumn', # (called RedColorant in ref 2) + rTRC => { + Name => 'RedTRC', + Description => 'Red Tone Reproduction Curve', + }, + scrd => 'ScreeningDesc', + scrn => 'Screening', + 'bfd '=> { + Name => 'UCRBG', + Description => 'Under Color Removal and Black Gen.', + }, + tech => { + Name => 'Technology', + PrintConv => { + fscn => 'Film Scanner', + dcam => 'Digital Camera', + rscn => 'Reflective Scanner', + ijet => 'Ink Jet Printer', + twax => 'Thermal Wax Printer', + epho => 'Electrophotographic Printer', + esta => 'Electrostatic Printer', + dsub => 'Dye Sublimation Printer', + rpho => 'Photographic Paper Printer', + fprn => 'Film Writer', + vidm => 'Video Monitor', + vidc => 'Video Camera', + pjtv => 'Projection Television', + 'CRT '=> 'Cathode Ray Tube Display', + 'PMD '=> 'Passive Matrix Display', + 'AMD '=> 'Active Matrix Display', + KPCD => 'Photo CD', + imgs => 'Photo Image Setter', + grav => 'Gravure', + offs => 'Offset Lithography', + silk => 'Silkscreen', + flex => 'Flexography', + mpfs => 'Motion Picture Film Scanner', #5 + mpfr => 'Motion Picture Film Recorder', #5 + dmpc => 'Digital Motion Picture Camera', #5 + dcpj => 'Digital Cinema Projector', #5 + }, + }, + vued => 'ViewingCondDesc', + view => { + Name => 'ViewingConditions', + SubDirectory => { + TagTable => 'Image::ExifTool::ICC_Profile::ViewingConditions', + Validate => '$type eq "view"', + }, + }, + ciis => 'ColorimetricIntentImageState', #5 + scoe => 'SceneColorimetryEstimates', #5 + sape => 'SceneAppearanceEstimates', #5 + fpce => 'FocalPlaneColorimetryEstimates', #5 + rhoc => 'ReflectionHardcopyOrigColorimetry', #5 + rpoc => 'ReflectionPrintOutputColorimetry', #5 + psid => { #5 + Name => 'ProfileSequenceIdentifier', + Binary => 1, + }, + B2D0 => { Name => 'BToD0', Binary => 1 }, #5 + B2D1 => { Name => 'BToD1', Binary => 1 }, #5 + B2D2 => { Name => 'BToD2', Binary => 1 }, #5 + B2D3 => { Name => 'BToD3', Binary => 1 }, #5 + D2B0 => { Name => 'DToB0', Binary => 1 }, #5 + D2B1 => { Name => 'DToB1', Binary => 1 }, #5 + D2B2 => { Name => 'DToB2', Binary => 1 }, #5 + D2B3 => { Name => 'DToB3', Binary => 1 }, #5 + rig0 => { #5 + Name => 'PerceptualRenderingIntentGamut', + PrintConv => { + prmg => 'Perceptual Reference Medium Gamut', + }, + }, + rig2 => { #5 + Name => 'SaturationRenderingIntentGamut', + PrintConv => { + prmg => 'Perceptual Reference Medium Gamut', + }, + }, + meta => { #5 (EVENTUALLY DECODE THIS ONCE WE HAVE A SAMPLE!!) + Name => 'Metadata', + SubDirectory => { + TagTable => 'Image::ExifTool::ICC_Profile::Metadata', + Validate => '$type eq "meta"', + }, + }, + + # ColorSync custom tags (ref 3) + psvm => 'PS2CRDVMSize', + vcgt => 'VideoCardGamma', + mmod => 'MakeAndModel', + dscm => 'ProfileDescriptionML', + ndin => 'NativeDisplayInfo', + + # Microsoft custom tags (ref http://msdn2.microsoft.com/en-us/library/ms536870.aspx) + MS00 => 'WCSProfiles', + + psd3 => { #6 + Name => 'PostScript2CRD3', + Binary => 1, # (NC) + }, + + # the following entry represents the ICC profile header, and doesn't + # exist as a tag in the directory. It is only in this table to provide + # a link so ExifTool can locate the header tags + Header => { + Name => 'ProfileHeader', + SubDirectory => { + TagTable => 'Image::ExifTool::ICC_Profile::Header', + }, + }, +); + +# ICC profile header definition +%Image::ExifTool::ICC_Profile::Header = ( + PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData, + GROUPS => { 0 => 'ICC_Profile', 1 => 'ICC-header', 2 => 'Image' }, + 4 => { + Name => 'ProfileCMMType', + Format => 'string[4]', + SeparateTable => 'ManuSig', + PrintConv => \%manuSig, + }, + 8 => { + Name => 'ProfileVersion', + Format => 'int16s', + PrintConv => '($val >> 8).".".(($val & 0xf0)>>4).".".($val & 0x0f)', + }, + 12 => { + Name => 'ProfileClass', + Format => 'string[4]', + PrintConv => \%profileClass, + }, + 16 => { + Name => 'ColorSpaceData', + Format => 'string[4]', + }, + 20 => { + Name => 'ProfileConnectionSpace', + Format => 'string[4]', + }, + 24 => { + Name => 'ProfileDateTime', + Groups => { 2 => 'Time' }, + Format => 'int16u[6]', + ValueConv => 'sprintf("%.4d:%.2d:%.2d %.2d:%.2d:%.2d",split(" ",$val));', + PrintConv => '$self->ConvertDateTime($val)', + }, + 36 => { + Name => 'ProfileFileSignature', + Format => 'string[4]', + }, + 40 => { + Name => 'PrimaryPlatform', + Format => 'string[4]', + PrintConv => { + 'APPL' => 'Apple Computer Inc.', + 'MSFT' => 'Microsoft Corporation', + 'SGI ' => 'Silicon Graphics Inc.', + 'SUNW' => 'Sun Microsystems Inc.', + 'TGNT' => 'Taligent Inc.', + }, + }, + 44 => { + Name => 'CMMFlags', + Format => 'int32u', + PrintConv => q[ + ($val & 0x01 ? "Embedded, " : "Not Embedded, ") . + ($val & 0x02 ? "Not Independent" : "Independent") + ], + }, + 48 => { + Name => 'DeviceManufacturer', + Format => 'string[4]', + SeparateTable => 'ManuSig', + PrintConv => \%manuSig, + }, + 52 => { + Name => 'DeviceModel', + Format => 'string[4]', + # ROMM = Reference Output Medium Metric + }, + 56 => { + Name => 'DeviceAttributes', + Format => 'int32u[2]', + PrintConv => q[ + my @v = split ' ', $val; + ($v[1] & 0x01 ? "Transparency, " : "Reflective, ") . + ($v[1] & 0x02 ? "Matte, " : "Glossy, ") . + ($v[1] & 0x04 ? "Negative, " : "Positive, ") . + ($v[1] & 0x08 ? "B&W" : "Color"); + ], + }, + 64 => { + Name => 'RenderingIntent', + Format => 'int32u', + PrintConv => { + 0 => 'Perceptual', + 1 => 'Media-Relative Colorimetric', + 2 => 'Saturation', + 3 => 'ICC-Absolute Colorimetric', + }, + }, + 68 => { + Name => 'ConnectionSpaceIlluminant', + Format => 'fixed32s[3]', # xyz + }, + 80 => { + Name => 'ProfileCreator', + Format => 'string[4]', + SeparateTable => 'ManuSig', + PrintConv => \%manuSig, + }, + 84 => { + Name => 'ProfileID', + Format => 'int8u[16]', + PrintConv => 'Image::ExifTool::ICC_Profile::HexID($val)', + }, +); + +# viewingConditionsType (view) definition +%Image::ExifTool::ICC_Profile::ViewingConditions = ( + PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData, + GROUPS => { 0 => 'ICC_Profile', 1 => 'ICC-view', 2 => 'Image' }, + 8 => { + Name => 'ViewingCondIlluminant', + Format => 'fixed32s[3]', # xyz + }, + 20 => { + Name => 'ViewingCondSurround', + Format => 'fixed32s[3]', # xyz + }, + 32 => { + Name => 'ViewingCondIlluminantType', + Format => 'int32u', + PrintConv => \%illuminantType, + }, +); + +# measurementType (meas) definition +%Image::ExifTool::ICC_Profile::Measurement = ( + PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData, + GROUPS => { 0 => 'ICC_Profile', 1 => 'ICC-meas', 2 => 'Image' }, + 8 => { + Name => 'MeasurementObserver', + Format => 'int32u', + PrintConv => { + 1 => 'CIE 1931', + 2 => 'CIE 1964', + }, + }, + 12 => { + Name => 'MeasurementBacking', + Format => 'fixed32s[3]', # xyz + }, + 24 => { + Name => 'MeasurementGeometry', + Format => 'int32u', + PrintConv => { + 0 => 'Unknown', + 1 => '0/45 or 45/0', + 2 => '0/d or d/0', + }, + }, + 28 => { + Name => 'MeasurementFlare', + Format => 'fixed32u', + PrintConv => '$val*100 . "%"', # change into a percent + }, + 32 => { + Name => 'MeasurementIlluminant', + Format => 'int32u', + PrintConv => \%illuminantType, + }, +); + +# chromaticity (chrm) definition +%Image::ExifTool::ICC_Profile::Chromaticity = ( + PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData, + GROUPS => { 0 => 'ICC_Profile', 1 => 'ICC-chrm', 2 => 'Image' }, + 8 => { + Name => 'ChromaticityChannels', + Format => 'int16u', + }, + 10 => { + Name => 'ChromaticityColorant', + Format => 'int16u', + PrintConv => { + 1 => 'ITU-R BT.709', + 2 => 'SMPTE RP145-1994', + 3 => 'EBU Tech.3213-E', + 4 => 'P22', + }, + }, + # include definitions for 4 channels -- if there are + # fewer then the ProcessBinaryData logic won't print them. + # If there are more, oh well. + 12 => { + Name => 'ChromaticityChannel1', + Format => 'fixed32u[2]', + }, + 20 => { + Name => 'ChromaticityChannel2', + Format => 'fixed32u[2]', + }, + 28 => { + Name => 'ChromaticityChannel3', + Format => 'fixed32u[2]', + }, + 36 => { + Name => 'ChromaticityChannel4', + Format => 'fixed32u[2]', + }, +); + +# colorantTable (clrt) definition +%Image::ExifTool::ICC_Profile::ColorantTable = ( + PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData, + GROUPS => { 0 => 'ICC_Profile', 1 => 'ICC-clrt', 2 => 'Image' }, + 8 => { + Name => 'ColorantCount', + Format => 'int32u', + }, + # include definitions for 3 colorants -- if there are + # fewer then the ProcessBinaryData logic won't print them. + # If there are more, oh well. + 12 => { + Name => 'Colorant1Name', + Format => 'string[32]', + }, + 44 => { + Name => 'Colorant1Coordinates', + Format => 'int16u[3]', + }, + 50 => { + Name => 'Colorant2Name', + Format => 'string[32]', + }, + 82 => { + Name => 'Colorant2Coordinates', + Format => 'int16u[3]', + }, + 88 => { + Name => 'Colorant3Name', + Format => 'string[32]', + }, + 120 => { + Name => 'Colorant3Coordinates', + Format => 'int16u[3]', + }, +); + +# metadata (meta) tags +%Image::ExifTool::ICC_Profile::Metadata = ( + PROCESS_PROC => \&ProcessMetadata, + GROUPS => { 0 => 'ICC_Profile', 1 => 'ICC-meta', 2 => 'Image' }, + VARS => { NO_ID => 1 }, + NOTES => q{ + Only these few tags have been pre-defined, but ExifTool will extract any + Metadata tags that exist. + }, + ManufacturerName => { }, + MediaColor => { }, + MediaWeight => { }, +); + +#------------------------------------------------------------------------------ +# Print ICC Profile ID in hex +# Inputs: 1) string of numbers +# Returns: string of hex digits +sub HexID($) +{ + my $val = shift; + my @vals = split(' ', $val); + # return a simple zero if no MD5 done + return 0 unless grep(!/^0/, @vals); + $val = ''; + foreach (@vals) { $val .= sprintf("%.2x",$_); } + return $val; +} + +#------------------------------------------------------------------------------ +# Get formatted value from ICC tag (which has the type embedded) +# Inputs: 0) data reference, 1) offset to tag data, 2) tag data size +# Returns: Formatted value or undefined if format not supported +# Notes: The following types are handled by BinaryTables: +# chromaticityType, colorantTableType, measurementType, viewingConditionsType +# The following types are currently not handled (most are large tables): +# curveType, lut16Type, lut8Type, lutAtoBType, lutBtoAType, namedColor2Type, +# parametricCurveType, profileSeqDescType, responseCurveSet16Type +# The multiLocalizedUnicodeType must be handled by the calling routine. +sub FormatICCTag($$$) +{ + my ($dataPt, $offset, $size) = @_; + + my $type; + if ($size >= 8) { + # get data type from start of tag data + $type = substr($$dataPt, $offset, 4); + } else { + $type = 'err'; + } + # colorantOrderType + if ($type eq 'clro' and $size >= 12) { + my $num = Get32u($dataPt, $offset+8); + if ($size >= $num + 12) { + my $pos = $offset + 12; + return join(' ',unpack("x$pos c$num", $$dataPt)); + } + } + # dataType + if ($type eq 'data' and $size >= 12) { + my $form = Get32u($dataPt, $offset+8); + # format 0 is ASCII data + $form == 0 and return substr($$dataPt, $offset+12, $size-12); + # binary data and other data types treat as binary (ie. don't format) + } + # dateTimeType + if ($type eq 'dtim' and $size >= 20) { + return sprintf("%.4d:%.2d:%.2d %.2d:%.2d:%.2d", + Get16u($dataPt, $offset+8), Get16u($dataPt, $offset+10), + Get16u($dataPt, $offset+12), Get16u($dataPt, $offset+14), + Get16u($dataPt, $offset+16), Get16u($dataPt, $offset+18)); + } + # s15Fixed16ArrayType + if ($type eq 'sf32') { + return ReadValue($dataPt,$offset+8,'fixed32s',($size-8)/4,$size-8); + } + # signatureType + if ($type eq 'sig ' and $size >= 12) { + return substr($$dataPt, $offset+8, 4); + } + # textType + $type eq 'text' and return substr($$dataPt, $offset+8, $size-8); + # textDescriptionType (ref 2, replaced by multiLocalizedUnicodeType) + if ($type eq 'desc' and $size >= 12) { + my $len = Get32u($dataPt, $offset+8); + if ($size >= $len + 12) { + my $str = substr($$dataPt, $offset+12, $len); + $str =~ s/\0.*//s; # truncate at null terminator + return $str; + } + } + # u16Fixed16ArrayType + if ($type eq 'uf32') { + return ReadValue($dataPt,$offset+8,'fixed32u',($size-8)/4,$size-8); + } + # uInt32ArrayType + if ($type eq 'ui32') { + return ReadValue($dataPt,$offset+8,'int32u',($size-8)/4,$size-8); + } + # uInt64ArrayType + if ($type eq 'ui64') { + return ReadValue($dataPt,$offset+8,'int64u',($size-8)/8,$size-8); + } + # uInt8ArrayType + if ($type eq 'ui08') { + return ReadValue($dataPt,$offset+8,'int8u',$size-8,$size-8); + } + # XYZType + if ($type eq 'XYZ ') { + my $str = ''; + my $pos; + for ($pos=8; $pos+12<=$size; $pos+=12) { + $str and $str .= ', '; + $str .= ReadValue($dataPt,$offset+$pos,'fixed32s',3,$size-$pos); + } + return $str; + } + return undef; # data type is not supported +} + +#------------------------------------------------------------------------------ +# Process ICC metadata record (ref 5) (UNTESTED!) +# Inputs: 0) ExifTool ref, 1) dirInfo ref, 2) tag table ref +# Returns: 1 on success +sub ProcessMetadata($$$) +{ + my ($et, $dirInfo, $tagTablePtr) = @_; + my $dataPt = $$dirInfo{DataPt}; + my $dirStart = $$dirInfo{DirStart}; + my $dirLen = $$dirInfo{DirLen}; + my $dirEnd = $dirStart + $dirLen; + + if ($dirLen < 16 or substr($$dataPt, $dirStart, 4) ne 'dict') { + $et->Warn('Invalid ICC meta dictionary'); + return 0; + } + my $num = Get32u($dataPt, $dirStart + 8); + $et->VerboseDir('Metadata', $num); + my $size = Get32u($dataPt, $dirStart + 12); + $size < 16 and $et->Warn('Invalid ICC meta record size'), return 0; + # NOTE: In the example the minimum offset is 20, + # but this doesn't jive with the table (both in ref 5) + my $minPtr = 16 + $size * $num; + my $index; + for ($index=0; $index<$num; ++$index) { + my $entry = $dirStart + 16 + $size * $index; + if ($entry + $size > $dirEnd) { + $et->Warn('Truncated ICC meta dictionary'); + last; + } + my $namePtr = Get32u($dataPt, $entry); + my $nameLen = Get32u($dataPt, $entry + 4); + my $valuePtr = Get32u($dataPt, $entry + 8); + my $valueLen = Get32u($dataPt, $entry + 16); + next unless $namePtr and $valuePtr; # ignore if offsets are zero + if ($namePtr < $minPtr or $namePtr + $nameLen > $dirLen or + $valuePtr < $minPtr or $valuePtr + $valueLen > $dirLen) + { + $et->Warn('Corrupted ICC meta dictionary'); + last; + } + my $tag = substr($dataPt, $dirStart + $namePtr, $nameLen); + my $val = substr($dataPt, $dirStart + $valuePtr, $valueLen); + $tag = $et->Decode($tag, 'UTF16', 'MM', 'UTF8'); + $val = $et->Decode($val, 'UTF16', 'MM'); + # generate tagInfo if it doesn't exist + unless ($$tagTablePtr{$tag}) { + my $name = ucfirst $tag; + $name =~ s/\s+(.)/\u$1/g; + $name =~ tr/-_a-zA-Z0-9//dc; + next unless length $name; + AddTagToTable($tagTablePtr, $tag, { Name => $name }); + } + $et->HandleTag($tagTablePtr, $tag, $val); + } + return 1; +} + +#------------------------------------------------------------------------------ +# Write ICC profile file +# Inputs: 0) ExifTool object reference, 1) Reference to directory information +# Returns: 1 on success, 0 if this wasn't a valid ICC file, +# or -1 if a write error occurred +sub WriteICC($$) +{ + my ($et, $dirInfo) = @_; + # first make sure this is a valid ICC file (or no file at all) + my $raf = $$dirInfo{RAF}; + my $buff; + return 0 if $raf->Read($buff, 24) and ValidateICC(\$buff); + # now write the new ICC + $buff = WriteICC_Profile($et, $dirInfo); + if (defined $buff and length $buff) { + Write($$dirInfo{OutFile}, $buff) or return -1; + } else { + $et->Error('No ICC information to write'); + } + return 1; +} + +#------------------------------------------------------------------------------ +# Write ICC data as a block +# Inputs: 0) ExifTool object reference, 1) source dirInfo reference, +# 2) tag table reference +# Returns: ICC data block (may be empty if no ICC data) +# Notes: Increments ExifTool CHANGED flag if changed +sub WriteICC_Profile($$;$) +{ + my ($et, $dirInfo, $tagTablePtr) = @_; + $et or return 1; # allow dummy access + my $dirName = $$dirInfo{DirName} || 'ICC_Profile'; + # (don't write AsShotICCProfile or CurrentICCProfile here) + return undef unless $dirName eq 'ICC_Profile'; + my $nvHash = $et->GetNewValueHash($Image::ExifTool::Extra{$dirName}); + my $val = $et->GetNewValue($nvHash); + $val = '' unless defined $val; + return undef unless $et->IsOverwriting($nvHash, $val); + ++$$et{CHANGED}; + return $val; +} + +#------------------------------------------------------------------------------ +# Validate ICC data +# Inputs: 0) ICC data reference +# Returns: error string or undef on success +sub ValidateICC($) +{ + my $valPtr = shift; + my $err; + length($$valPtr) < 24 and return 'Invalid ICC profile'; + $profileClass{substr($$valPtr, 12, 4)} or $err = 'profile class'; + my $col = substr($$valPtr, 16, 4); # ColorSpaceData + my $con = substr($$valPtr, 20, 4); # ConnectionSpace + my $match = '(XYZ |Lab |Luv |YCbr|Yxy |RGB |GRAY|HSV |HLS |CMYK|CMY |[2-9A-F]CLR)'; + $col =~ /$match/ or $err = 'color space'; + $con =~ /$match/ or $err = 'connection space'; + return $err ? "Invalid ICC profile (bad $err)" : undef; +} + +#------------------------------------------------------------------------------ +# Process ICC profile file +# Inputs: 0) ExifTool object reference, 1) Reference to directory information +# Returns: 1 if this was an ICC file +sub ProcessICC($$) +{ + my ($et, $dirInfo) = @_; + my $raf = $$dirInfo{RAF}; + my $buff; + $raf->Read($buff, 24) == 24 or return 0; + # check to see if this is a valid ICC profile file + return 0 if ValidateICC(\$buff); + $et->SetFileType(); + # read the profile + my $size = unpack('N', $buff); + if ($size < 128 or $size & 0x80000000) { + $et->Error("Bad ICC Profile length ($size)"); + return 1; + } + $raf->Seek(0, 0); + unless ($raf->Read($buff, $size) == $size) { + $et->Error('Truncated ICC profile'); + return 1; + } + my %dirInfo = ( + DataPt => \$buff, + DataLen => $size, + DirStart => 0, + DirLen => $size, + ); + my $tagTablePtr = GetTagTable('Image::ExifTool::ICC_Profile::Main'); + return ProcessICC_Profile($et, \%dirInfo, $tagTablePtr); +} + +#------------------------------------------------------------------------------ +# Process ICC_Profile APP13 record +# Inputs: 0) ExifTool object reference, 1) Reference to directory information +# 2) Tag table reference (undefined to read ICC file) +# Returns: 1 on success +sub ProcessICC_Profile($$$) +{ + my ($et, $dirInfo, $tagTablePtr) = @_; + my $dataPt = $$dirInfo{DataPt}; + my $dirStart = $$dirInfo{DirStart} || 0; + my $dirLen = $$dirInfo{DirLen}; + my $verbose = $et->Options('Verbose'); + + return 0 if $dirLen < 4; + + # extract binary ICC_Profile data block if binary mode or requested + if ((($$et{TAGS_FROM_FILE} and not $$et{EXCL_TAG_LOOKUP}{icc_profile}) or + $$et{REQ_TAG_LOOKUP}{icc_profile}) and + # (don't extract from AsShotICCProfile or CurrentICCProfile) + (not $$dirInfo{Name} or $$dirInfo{Name} eq 'ICC_Profile')) + { + $et->FoundTag('ICC_Profile', substr($$dataPt, $dirStart, $dirLen)); + } + + SetByteOrder('MM'); # ICC_Profile is always big-endian + + # check length of table + my $len = Get32u($dataPt, $dirStart); + if ($len != $dirLen or $len < 128) { + $et->Warn("Bad length ICC_Profile (length $len)"); + return 0 if $len < 128 or $dirLen < $len; + } + my $pos = $dirStart + 128; # position at start of table + my $numEntries = Get32u($dataPt, $pos); + if ($numEntries < 1 or $numEntries >= 0x100 + or $numEntries * 12 + 132 > $dirLen) + { + $et->Warn("Bad ICC_Profile table ($numEntries entries)"); + return 0; + } + + if ($verbose) { + $et->VerboseDir('ICC_Profile', $numEntries, $dirLen); + my $fakeInfo = { Name=>'ProfileHeader', SubDirectory => { } }; + $et->VerboseInfo(undef, $fakeInfo); + } + # increment ICC dir count + my $dirCount = $$et{DIR_COUNT}{ICC} = ($$et{DIR_COUNT}{ICC} || 0) + 1; + $$et{SET_GROUP1} = '+' . $dirCount if $dirCount > 1; + # process the header block + my %subdirInfo = ( + Name => 'ProfileHeader', + DataPt => $dataPt, + DataLen => $$dirInfo{DataLen}, + DirStart => $dirStart, + DirLen => 128, + Parent => $$dirInfo{DirName}, + DirName => 'Header', + ); + my $newTagTable = GetTagTable('Image::ExifTool::ICC_Profile::Header'); + $et->ProcessDirectory(\%subdirInfo, $newTagTable); + + $pos += 4; # skip item count + my $index; + for ($index=0; $index<$numEntries; ++$index) { + my $tagID = substr($$dataPt, $pos, 4); + my $offset = Get32u($dataPt, $pos + 4); + my $size = Get32u($dataPt, $pos + 8); + $pos += 12; + my $tagInfo = $et->GetTagInfo($tagTablePtr, $tagID); + # unknown tags aren't generated automatically by GetTagInfo() + # if the tagID's aren't numeric, so we must do this manually: + if (not $tagInfo and $$et{OPTIONS}{Unknown}) { + $tagInfo = { Unknown => 1 }; + AddTagToTable($tagTablePtr, $tagID, $tagInfo); + } + next unless defined $tagInfo; + + if ($offset + $size > $dirLen) { + $et->Warn("Bad ICC_Profile table (truncated)"); + last; + } + my $valuePtr = $dirStart + $offset; + + my $subdir = $$tagInfo{SubDirectory}; + # format the value unless this is a subdirectory + my ($value, $fmt); + if ($size > 4) { + $fmt = substr($$dataPt, $valuePtr, 4); + # handle multiLocalizedUnicodeType + if ($fmt eq 'mluc' and not $subdir) { + next if $size < 28; + my $count = Get32u($dataPt, $valuePtr + 8); + my $recLen = Get32u($dataPt, $valuePtr + 12); + next if $recLen < 12; + my $i; + for ($i=0; $i<$count; ++$i) { + my $recPos = $valuePtr + 16 + $i * $recLen; + last if $recPos + $recLen > $valuePtr + $size; + my $lang = substr($$dataPt, $recPos, 4); + my $langInfo; + # validate language code and change to standard case (just in case) + if ($lang =~ s/^([a-z]{2})([A-Z]{2})$/\L$1-\U$2/i and $lang ne 'en-US') { + $langInfo = Image::ExifTool::GetLangInfo($tagInfo, $lang); + } + my $strLen = Get32u($dataPt, $recPos + 4); + my $strPos = Get32u($dataPt, $recPos + 8); + last if $strPos + $strLen > $size; + my $str = substr($$dataPt, $valuePtr + $strPos, $strLen); + $str = $et->Decode($str, 'UTF16'); + $et->HandleTag($tagTablePtr, $tagID, $str, + TagInfo => $langInfo || $tagInfo, + Table => $tagTablePtr, + Index => $index, + Value => $str, + DataPt => $dataPt, + Size => $strLen, + Start => $valuePtr + $strPos, + Format => "type '${fmt}'", + ); + } + $et->Warn("Corrupted $$tagInfo{Name} data") if $i < $count; + next; + } + } else { + $fmt = 'err '; + } + $value = FormatICCTag($dataPt, $valuePtr, $size) unless $subdir; + $verbose and $et->VerboseInfo($tagID, $tagInfo, + Table => $tagTablePtr, + Index => $index, + Value => $value, + DataPt => $dataPt, + Size => $size, + Start => $valuePtr, + Format => "type '${fmt}'", + ); + if ($subdir) { + my $name = $$tagInfo{Name}; + undef $newTagTable; + if ($$subdir{TagTable}) { + $newTagTable = GetTagTable($$subdir{TagTable}); + unless ($newTagTable) { + warn "Unknown tag table $$subdir{TagTable}\n"; + next; + } + } else { + warn "Must specify TagTable for SubDirectory $name\n"; + next; + } + %subdirInfo = ( + Name => $name, + DataPt => $dataPt, + DataPos => $$dirInfo{DataPos}, + DataLen => $$dirInfo{DataLen}, + DirStart => $valuePtr, + DirLen => $size, + DirName => $name, + Parent => $$dirInfo{DirName}, + ); + my $type = substr($$dataPt, $valuePtr, 4); + #### eval Validate ($type) + if (defined $$subdir{Validate} and not eval $$subdir{Validate}) { + $et->Warn("Invalid $name data"); + } else { + $et->ProcessDirectory(\%subdirInfo, $newTagTable, $$subdir{ProcessProc}); + } + } elsif (defined $value) { + $et->FoundTag($tagInfo, $value); + } else { + $value = substr($$dataPt, $valuePtr, $size); + # treat unsupported formats as binary data + $$tagInfo{ValueConv} = '\$val' unless defined $$tagInfo{ValueConv}; + $et->FoundTag($tagInfo, $value); + } + } + delete $$et{SET_GROUP1}; + return 1; +} + + +1; # end + + +__END__ + +=head1 NAME + +Image::ExifTool::ICC_Profile - Read ICC Profile meta information + +=head1 SYNOPSIS + +This module is loaded automatically by Image::ExifTool when required. + +=head1 DESCRIPTION + +This module contains the definitions to read information from ICC profiles. +ICC (International Color Consortium) profiles are used to translate color +data created on one device into another device's native color space. + +=head1 AUTHOR + +Copyright 2003-2019, Phil Harvey (phil at owl.phy.queensu.ca) + +This library is free software; you can redistribute it and/or modify it +under the same terms as Perl itself. + +=head1 REFERENCES + +=over 4 + +=item L<http://www.color.org/icc_specs2.html> + +=item L<http://developer.apple.com/documentation/GraphicsImaging/Reference/ColorSync_Manager/ColorSync_Manager.pdf> + +=back + +=head1 SEE ALSO + +L<Image::ExifTool::TagNames/ICC_Profile Tags>, +L<Image::ExifTool(3pm)|Image::ExifTool> + +=cut diff --git a/lib/Image/ExifTool/ID3.pm b/lib/Image/ExifTool/ID3.pm new file mode 100644 index 0000000..56c3dae --- /dev/null +++ b/lib/Image/ExifTool/ID3.pm @@ -0,0 +1,1580 @@ +#------------------------------------------------------------------------------ +# File: ID3.pm +# +# Description: Read ID3 meta information +# +# Revisions: 09/12/2005 - P. Harvey Created +# +# References: 1) http://www.id3.org/ +# 2) http://www.mp3-tech.org/ +# 3) http://www.fortunecity.com/underworld/sonic/3/id3tag.html +#------------------------------------------------------------------------------ + +package Image::ExifTool::ID3; + +use strict; +use vars qw($VERSION); +use Image::ExifTool qw(:DataAccess :Utils); + +$VERSION = '1.51'; + +sub ProcessID3v2($$$); +sub ProcessPrivate($$$); +sub ProcessSynText($$$); +sub ConvertID3v1Text($$); +sub ConvertTimeStamp($); + +# audio formats that we process after an ID3v2 header (in order) +my @audioFormats = qw(APE MPC FLAC OGG MP3); + +# audio formats where the processing proc is in a differently-named module +my %audioModule = ( + MP3 => 'ID3', + OGG => 'Ogg', +); + +# picture types for 'PIC' and 'APIC' tags +# (Note: Duplicated in ID3, ASF and FLAC modules!) +my %pictureType = ( + 0 => 'Other', + 1 => '32x32 PNG Icon', + 2 => 'Other Icon', + 3 => 'Front Cover', + 4 => 'Back Cover', + 5 => 'Leaflet', + 6 => 'Media', + 7 => 'Lead Artist', + 8 => 'Artist', + 9 => 'Conductor', + 10 => 'Band', + 11 => 'Composer', + 12 => 'Lyricist', + 13 => 'Recording Studio or Location', + 14 => 'Recording Session', + 15 => 'Performance', + 16 => 'Capture from Movie or Video', + 17 => 'Bright(ly) Colored Fish', + 18 => 'Illustration', + 19 => 'Band Logo', + 20 => 'Publisher Logo', +); + +my %dateTimeConv = ( + ValueConv => 'require Image::ExifTool::XMP; Image::ExifTool::XMP::ConvertXMPDate($val)', + PrintConv => '$self->ConvertDateTime($val)', +); + +# This table is just for documentation purposes +%Image::ExifTool::ID3::Main = ( + VARS => { NO_ID => 1 }, + NOTES => q{ + ExifTool extracts ID3 information from MP3, MPEG, AIFF, OGG, FLAC, APE, MPC + and RealAudio files. ID3v2 tags which support multiple languages (eg. + Comment and Lyrics) are extracted by specifying the tag name, followed by a + dash ('-'), then a 3-character ISO 639-2 language code (eg. "Comment-spa"). + See L<http://www.id3.org/> for the official ID3 specification and + L<http://www.loc.gov/standards/iso639-2/php/code_list.php> for a list of ISO + 639-2 language codes. + }, + ID3v1 => { + Name => 'ID3v1', + SubDirectory => { TagTable => 'Image::ExifTool::ID3::v1' }, + }, + ID3v1Enh => { + Name => 'ID3v1_Enh', + SubDirectory => { TagTable => 'Image::ExifTool::ID3::v1_Enh' }, + }, + ID3v22 => { + Name => 'ID3v2_2', + SubDirectory => { TagTable => 'Image::ExifTool::ID3::v2_2' }, + }, + ID3v23 => { + Name => 'ID3v2_3', + SubDirectory => { TagTable => 'Image::ExifTool::ID3::v2_3' }, + }, + ID3v24 => { + Name => 'ID3v2_4', + SubDirectory => { TagTable => 'Image::ExifTool::ID3::v2_4' }, + }, +); + +# Mapping for ID3v1 Genre numbers +my %genre = ( + 0 => 'Blues', + 1 => 'Classic Rock', + 2 => 'Country', + 3 => 'Dance', + 4 => 'Disco', + 5 => 'Funk', + 6 => 'Grunge', + 7 => 'Hip-Hop', + 8 => 'Jazz', + 9 => 'Metal', + 10 => 'New Age', + 11 => 'Oldies', + 12 => 'Other', + 13 => 'Pop', + 14 => 'R&B', + 15 => 'Rap', + 16 => 'Reggae', + 17 => 'Rock', + 18 => 'Techno', + 19 => 'Industrial', + 20 => 'Alternative', + 21 => 'Ska', + 22 => 'Death Metal', + 23 => 'Pranks', + 24 => 'Soundtrack', + 25 => 'Euro-Techno', + 26 => 'Ambient', + 27 => 'Trip-Hop', + 28 => 'Vocal', + 29 => 'Jazz+Funk', + 30 => 'Fusion', + 31 => 'Trance', + 32 => 'Classical', + 33 => 'Instrumental', + 34 => 'Acid', + 35 => 'House', + 36 => 'Game', + 37 => 'Sound Clip', + 38 => 'Gospel', + 39 => 'Noise', + 40 => 'Alt. Rock', # (was AlternRock) + 41 => 'Bass', + 42 => 'Soul', + 43 => 'Punk', + 44 => 'Space', + 45 => 'Meditative', + 46 => 'Instrumental Pop', + 47 => 'Instrumental Rock', + 48 => 'Ethnic', + 49 => 'Gothic', + 50 => 'Darkwave', + 51 => 'Techno-Industrial', + 52 => 'Electronic', + 53 => 'Pop-Folk', + 54 => 'Eurodance', + 55 => 'Dream', + 56 => 'Southern Rock', + 57 => 'Comedy', + 58 => 'Cult', + 59 => 'Gangsta Rap', # (was Gansta) + 60 => 'Top 40', + 61 => 'Christian Rap', + 62 => 'Pop/Funk', + 63 => 'Jungle', + 64 => 'Native American', + 65 => 'Cabaret', + 66 => 'New Wave', + 67 => 'Psychedelic', # (was misspelt) + 68 => 'Rave', + 69 => 'Showtunes', + 70 => 'Trailer', + 71 => 'Lo-Fi', + 72 => 'Tribal', + 73 => 'Acid Punk', + 74 => 'Acid Jazz', + 75 => 'Polka', + 76 => 'Retro', + 77 => 'Musical', + 78 => 'Rock & Roll', + 79 => 'Hard Rock', + # The following genres are Winamp extensions + 80 => 'Folk', + 81 => 'Folk-Rock', + 82 => 'National Folk', + 83 => 'Swing', + 84 => 'Fast-Fusion', # (was Fast Fusion) + 85 => 'Bebop', # (was misspelt) + 86 => 'Latin', + 87 => 'Revival', + 88 => 'Celtic', + 89 => 'Bluegrass', + 90 => 'Avantgarde', + 91 => 'Gothic Rock', + 92 => 'Progressive Rock', + 93 => 'Psychedelic Rock', + 94 => 'Symphonic Rock', + 95 => 'Slow Rock', + 96 => 'Big Band', + 97 => 'Chorus', + 98 => 'Easy Listening', + 99 => 'Acoustic', + 100 => 'Humour', + 101 => 'Speech', + 102 => 'Chanson', + 103 => 'Opera', + 104 => 'Chamber Music', + 105 => 'Sonata', + 106 => 'Symphony', + 107 => 'Booty Bass', + 108 => 'Primus', + 109 => 'Porn Groove', + 110 => 'Satire', + 111 => 'Slow Jam', + 112 => 'Club', + 113 => 'Tango', + 114 => 'Samba', + 115 => 'Folklore', + 116 => 'Ballad', + 117 => 'Power Ballad', + 118 => 'Rhythmic Soul', + 119 => 'Freestyle', + 120 => 'Duet', + 121 => 'Punk Rock', + 122 => 'Drum Solo', + 123 => 'A Cappella', # (was Acapella) + 124 => 'Euro-House', + 125 => 'Dance Hall', + # ref http://yar.hole.ru/MP3Tech/lamedoc/id3.html + 126 => 'Goa', + 127 => 'Drum & Bass', + 128 => 'Club-House', + 129 => 'Hardcore', + 130 => 'Terror', + 131 => 'Indie', + 132 => 'BritPop', + 133 => 'Afro-Punk', # (was Negerpunk) + 134 => 'Polsk Punk', + 135 => 'Beat', + 136 => 'Christian Gangsta Rap', # (was Christian Gangsta) + 137 => 'Heavy Metal', + 138 => 'Black Metal', + 139 => 'Crossover', + 140 => 'Contemporary Christian', # (was Contemporary C) + 141 => 'Christian Rock', + 142 => 'Merengue', + 143 => 'Salsa', + 144 => 'Thrash Metal', + 145 => 'Anime', + 146 => 'JPop', + 147 => 'Synthpop', # (was SynthPop) + # ref http://alicja.homelinux.com/~mats/text/Music/MP3/ID3/Genres.txt + # (also used to update some Genres above) + 148 => 'Abstract', + 149 => 'Art Rock', + 150 => 'Baroque', + 151 => 'Bhangra', + 152 => 'Big Beat', + 153 => 'Breakbeat', + 154 => 'Chillout', + 155 => 'Downtempo', + 156 => 'Dub', + 157 => 'EBM', + 158 => 'Eclectic', + 159 => 'Electro', + 160 => 'Electroclash', + 161 => 'Emo', + 162 => 'Experimental', + 163 => 'Garage', + 164 => 'Global', + 165 => 'IDM', + 166 => 'Illbient', + 167 => 'Industro-Goth', + 168 => 'Jam Band', + 169 => 'Krautrock', + 170 => 'Leftfield', + 171 => 'Lounge', + 172 => 'Math Rock', + 173 => 'New Romantic', + 174 => 'Nu-Breakz', + 175 => 'Post-Punk', + 176 => 'Post-Rock', + 177 => 'Psytrance', + 178 => 'Shoegaze', + 179 => 'Space Rock', + 180 => 'Trop Rock', + 181 => 'World Music', + 182 => 'Neoclassical', + 183 => 'Audiobook', + 184 => 'Audio Theatre', + 185 => 'Neue Deutsche Welle', + 186 => 'Podcast', + 187 => 'Indie Rock', + 188 => 'G-Funk', + 189 => 'Dubstep', + 190 => 'Garage Rock', + 191 => 'Psybient', + 255 => 'None', + # ID3v2 adds some text short forms... + CR => 'Cover', + RX => 'Remix', +); + +# Tags for ID3v1 +%Image::ExifTool::ID3::v1 = ( + PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData, + GROUPS => { 1 => 'ID3v1', 2 => 'Audio' }, + PRIORITY => 0, # let ID3v2 tags replace these if they come later + 3 => { + Name => 'Title', + Format => 'string[30]', + ValueConv => 'Image::ExifTool::ID3::ConvertID3v1Text($self,$val)', + }, + 33 => { + Name => 'Artist', + Groups => { 2 => 'Author' }, + Format => 'string[30]', + ValueConv => 'Image::ExifTool::ID3::ConvertID3v1Text($self,$val)', + }, + 63 => { + Name => 'Album', + Format => 'string[30]', + ValueConv => 'Image::ExifTool::ID3::ConvertID3v1Text($self,$val)', + }, + 93 => { + Name => 'Year', + Groups => { 2 => 'Time' }, + Format => 'string[4]', + }, + 97 => { + Name => 'Comment', + Format => 'string[30]', + ValueConv => 'Image::ExifTool::ID3::ConvertID3v1Text($self,$val)', + }, + 125 => { # ID3v1.1 (ref http://en.wikipedia.org/wiki/ID3#Layout) + Name => 'Track', + Format => 'int8u[2]', + Notes => 'v1.1 addition -- last 2 bytes of v1.0 Comment field', + RawConv => '($val =~ s/^0 // and $val) ? $val : undef', + }, + 127 => { + Name => 'Genre', + Notes => 'CR and RX are ID3v2 only', + Format => 'int8u', + PrintConv => \%genre, + PrintConvColumns => 3, + }, +); + +# ID3v1 "Enhanced TAG" information (ref 3) +%Image::ExifTool::ID3::v1_Enh = ( + PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData, + GROUPS => { 1 => 'ID3v1_Enh', 2 => 'Audio' }, + NOTES => 'ID3 version 1 "Enhanced TAG" information (not part of the official spec).', + PRIORITY => 0, # let ID3v2 tags replace these if they come later + 4 => { + Name => 'Title2', + Format => 'string[60]', + ValueConv => 'Image::ExifTool::ID3::ConvertID3v1Text($self,$val)', + }, + 64 => { + Name => 'Artist2', + Groups => { 2 => 'Author' }, + Format => 'string[60]', + ValueConv => 'Image::ExifTool::ID3::ConvertID3v1Text($self,$val)', + }, + 124 => { + Name => 'Album2', + Format => 'string[60]', + ValueConv => 'Image::ExifTool::ID3::ConvertID3v1Text($self,$val)', + }, + 184 => { + Name => 'Speed', + Format => 'int8u', + PrintConv => { + 1 => 'Slow', + 2 => 'Medium', + 3 => 'Fast', + 4 => 'Hardcore', + }, + }, + 185 => { + Name => 'Genre', + Format => 'string[30]', + ValueConv => 'Image::ExifTool::ID3::ConvertID3v1Text($self,$val)', + }, + 215 => { + Name => 'StartTime', + Format => 'string[6]', + }, + 221 => { + Name => 'EndTime', + Format => 'string[6]', + }, +); + +# Tags for ID2v2.2 +%Image::ExifTool::ID3::v2_2 = ( + PROCESS_PROC => \&Image::ExifTool::ID3::ProcessID3v2, + GROUPS => { 1 => 'ID3v2_2', 2 => 'Audio' }, + NOTES => q{ + ExifTool extracts mainly text-based tags from ID3v2 information. The tags + in the tables below are those extracted by ExifTool, and don't represent a + complete list of available ID3v2 tags. + + ID3 version 2.2 tags. (These are the tags written by iTunes 5.0.) + }, + CNT => 'PlayCounter', + COM => 'Comment', + IPL => 'InvolvedPeople', + PIC => { + Name => 'Picture', + Groups => { 2 => 'Preview' }, + Binary => 1, + Notes => 'the 3 tags below are also extracted from this PIC frame', + }, + 'PIC-1' => { Name => 'PictureFormat', Groups => { 2 => 'Image' } }, + 'PIC-2' => { + Name => 'PictureType', + Groups => { 2 => 'Image' }, + PrintConv => \%pictureType, + SeparateTable => 1, + }, + 'PIC-3' => { Name => 'PictureDescription', Groups => { 2 => 'Image' } }, + POP => { + Name => 'Popularimeter', + PrintConv => '$val=~s/^(.*?) (\d+) (\d+)$/$1 Rating=$2 Count=$3/s; $val', + }, + SLT => { + Name => 'SynLyrics', + SubDirectory => { TagTable => 'Image::ExifTool::ID3::SynLyrics' }, + }, + TAL => 'Album', + TBP => 'BeatsPerMinute', + TCM => 'Composer', + TCO =>{ + Name => 'Genre', + Notes => 'uses same lookup table as ID3v1 Genre', + PrintConv => 'Image::ExifTool::ID3::PrintGenre($val)', + }, + TCP => { Name => 'Compilation', PrintConv => { 0 => 'No', 1 => 'Yes' } }, # iTunes + TCR => { Name => 'Copyright', Groups => { 2 => 'Author' } }, + TDA => { Name => 'Date', Groups => { 2 => 'Time' } }, + TDY => 'PlaylistDelay', + TEN => 'EncodedBy', + TFT => 'FileType', + TIM => { Name => 'Time', Groups => { 2 => 'Time' } }, + TKE => 'InitialKey', + TLA => 'Language', + TLE => 'Length', + TMT => 'Media', + TOA => { Name => 'OriginalArtist', Groups => { 2 => 'Author' } }, + TOF => 'OriginalFileName', + TOL => 'OriginalLyricist', + TOR => 'OriginalReleaseYear', + TOT => 'OriginalAlbum', + TP1 => { Name => 'Artist', Groups => { 2 => 'Author' } }, + TP2 => 'Band', + TP3 => 'Conductor', + TP4 => 'InterpretedBy', + TPA => 'PartOfSet', + TPB => 'Publisher', + TRC => 'ISRC', # (international standard recording code) + TRD => 'RecordingDates', + TRK => 'Track', + TSI => 'Size', + TSS => 'EncoderSettings', + TT1 => 'Grouping', + TT2 => 'Title', + TT3 => 'Subtitle', + TXT => 'Lyricist', + TXX => 'UserDefinedText', + TYE => { Name => 'Year', Groups => { 2 => 'Time' } }, + ULT => 'Lyrics', + WAF => 'FileURL', + WAR => { Name => 'ArtistURL', Groups => { 2 => 'Author' } }, + WAS => 'SourceURL', + WCM => 'CommercialURL', + WCP => { Name => 'CopyrightURL', Groups => { 2 => 'Author' } }, + WPB => 'PublisherURL', + WXX => 'UserDefinedURL', + # the following written by iTunes 10.5 (ref PH) + RVA => 'RelativeVolumeAdjustment', + TST => 'TitleSortOrder', + TSA => 'AlbumSortOrder', + TSP => 'PerformerSortOrder', + TS2 => 'AlbumArtistSortOrder', + TSC => 'ComposerSortOrder', + ITU => { Name => 'iTunesU', Description => 'iTunes U', Binary => 1, Unknown => 1 }, + PCS => { Name => 'Podcast', Binary => 1, Unknown => 1 }, +); + +# tags common to ID3v2.3 and ID3v2.4 +my %id3v2_common = ( + # AENC => 'AudioEncryption', # Owner, preview start, preview length, encr data + APIC => { + Name => 'Picture', + Groups => { 2 => 'Preview' }, + Binary => 1, + Notes => 'the 3 tags below are also extracted from this APIC frame', + }, + 'APIC-1' => { Name => 'PictureMIMEType', Groups => { 2 => 'Image' } }, + 'APIC-2' => { + Name => 'PictureType', + Groups => { 2 => 'Image' }, + PrintConv => \%pictureType, + SeparateTable => 1, + }, + 'APIC-3' => { Name => 'PictureDescription', Groups => { 2 => 'Image' } }, + COMM => 'Comment', + # COMR => 'Commercial', + # ENCR => 'EncryptionMethod', + # ETCO => 'EventTimingCodes', + # GEOB => 'GeneralEncapsulatedObject', + # GRID => 'GroupIdentification', + # LINK => 'LinkedInformation', + MCDI => { Name => 'MusicCDIdentifier', Binary => 1 }, + # MLLT => 'MPEGLocationLookupTable', + OWNE => 'Ownership', + PCNT => 'PlayCounter', + POPM => { + Name => 'Popularimeter', + PrintConv => '$val=~s/^(.*?) (\d+) (\d+)$/$1 Rating=$2 Count=$3/s; $val', + }, + # POSS => 'PostSynchronization', + PRIV => { + Name => 'Private', + SubDirectory => { TagTable => 'Image::ExifTool::ID3::Private' }, + }, + # RBUF => 'RecommendedBufferSize', + # RVRB => 'Reverb', + SYLT => { + Name => 'SynLyrics', + SubDirectory => { TagTable => 'Image::ExifTool::ID3::SynLyrics' }, + }, + # SYTC => 'SynchronizedTempoCodes', + TALB => 'Album', + TBPM => 'BeatsPerMinute', + TCMP => { Name => 'Compilation', PrintConv => { 0 => 'No', 1 => 'Yes' } }, #PH (iTunes) + TCOM => 'Composer', + TCON =>{ + Name => 'Genre', + Notes => 'uses same lookup table as ID3v1 Genre', + PrintConv => 'Image::ExifTool::ID3::PrintGenre($val)', + }, + TCOP => { Name => 'Copyright', Groups => { 2 => 'Author' } }, + TDLY => 'PlaylistDelay', + TENC => 'EncodedBy', + TEXT => 'Lyricist', + TFLT => 'FileType', + TIT1 => 'Grouping', + TIT2 => 'Title', + TIT3 => 'Subtitle', + TKEY => 'InitialKey', + TLAN => 'Language', + TLEN => { + Name => 'Length', + ValueConv => '$val / 1000', + PrintConv => '"$val s"', + }, + TMED => 'Media', + TOAL => 'OriginalAlbum', + TOFN => 'OriginalFileName', + TOLY => 'OriginalLyricist', + TOPE => { Name => 'OriginalArtist', Groups => { 2 => 'Author' } }, + TOWN => 'FileOwner', + TPE1 => { Name => 'Artist', Groups => { 2 => 'Author' } }, + TPE2 => 'Band', + TPE3 => 'Conductor', + TPE4 => 'InterpretedBy', + TPOS => 'PartOfSet', + TPUB => 'Publisher', + TRCK => 'Track', + TRSN => 'InternetRadioStationName', + TRSO => 'InternetRadioStationOwner', + TSRC => 'ISRC', # (international standard recording code) + TSSE => 'EncoderSettings', + TXXX => 'UserDefinedText', + # UFID => 'UniqueFileID', (not extracted because it is long and nasty and not very useful) + USER => 'TermsOfUse', + USLT => 'Lyrics', + WCOM => 'CommercialURL', + WCOP => 'CopyrightURL', + WOAF => 'FileURL', + WOAR => { Name => 'ArtistURL', Groups => { 2 => 'Author' } }, + WOAS => 'SourceURL', + WORS => 'InternetRadioStationURL', + WPAY => 'PaymentURL', + WPUB => 'PublisherURL', + WXXX => 'UserDefinedURL', +# +# non-standard frames +# + # the following are written by iTunes 10.5 (ref PH) + TSO2 => 'AlbumArtistSortOrder', + TSOC => 'ComposerSortOrder', + ITNU => { Name => 'iTunesU', Description => 'iTunes U', Binary => 1, Unknown => 1 }, + PCST => { Name => 'Podcast', Binary => 1, Unknown => 1 }, + # other proprietary Apple tags (ref http://help.mp3tag.de/main_tags.html) + TDES => 'PodcastDescription', + TGID => 'PodcastID', + WFED => 'PodcastURL', + TKWD => 'PodcastKeywords', + TCAT => 'PodcastCategory', + # more non-standard tags (ref http://eyed3.nicfit.net/compliance.html) + # NCON - unknown MusicMatch binary data + XDOR => { Name => 'OriginalReleaseTime',Groups => { 2 => 'Time' }, %dateTimeConv }, + XSOA => 'AlbumSortOrder', + XSOP => 'PerformerSortOrder', + XSOT => 'TitleSortOrder', + XOLY => { + Name => 'OlympusDSS', + SubDirectory => { TagTable => 'Image::ExifTool::Olympus::DSS' }, + }, +); + +# Tags for ID3v2.3 (http://www.id3.org/id3v2.3.0) +%Image::ExifTool::ID3::v2_3 = ( + PROCESS_PROC => \&Image::ExifTool::ID3::ProcessID3v2, + GROUPS => { 1 => 'ID3v2_3', 2 => 'Audio' }, + NOTES => q{ + ID3 version 2.3 tags. Includes some non-standard tags written by other + software. + }, + %id3v2_common, # include common tags + # EQUA => 'Equalization', + IPLS => 'InvolvedPeople', + # RVAD => 'RelativeVolumeAdjustment', + TDAT => { Name => 'Date', Groups => { 2 => 'Time' } }, + TIME => { Name => 'Time', Groups => { 2 => 'Time' } }, + TORY => 'OriginalReleaseYear', + TRDA => 'RecordingDates', + TSIZ => 'Size', + TYER => { Name => 'Year', Groups => { 2 => 'Time' } }, +); + +# Tags for ID3v2.4 (http://www.id3.org/id3v2.4.0-frames) +%Image::ExifTool::ID3::v2_4 = ( + PROCESS_PROC => \&Image::ExifTool::ID3::ProcessID3v2, + GROUPS => { 1 => 'ID3v2_4', 2 => 'Audio' }, + NOTES => q{ + ID3 version 2.4 tags. Includes some non-standard tags written by other + software. + }, + %id3v2_common, # include common tags + # EQU2 => 'Equalization', + RVA2 => 'RelativeVolumeAdjustment', + # SEEK => 'Seek', + # SIGN => 'Signature', + TDEN => { Name => 'EncodingTime', Groups => { 2 => 'Time' }, %dateTimeConv }, + TDOR => { Name => 'OriginalReleaseTime',Groups => { 2 => 'Time' }, %dateTimeConv }, + TDRC => { Name => 'RecordingTime', Groups => { 2 => 'Time' }, %dateTimeConv }, + TDRL => { Name => 'ReleaseTime', Groups => { 2 => 'Time' }, %dateTimeConv }, + TDTG => { Name => 'TaggingTime', Groups => { 2 => 'Time' }, %dateTimeConv }, + TIPL => 'InvolvedPeople', + TMCL => 'MusicianCredits', + TMOO => 'Mood', + TPRO => 'ProducedNotice', + TSOA => 'AlbumSortOrder', + TSOP => 'PerformerSortOrder', + TSOT => 'TitleSortOrder', + TSST => 'SetSubtitle', +); + +# Synchronized lyrics/text +%Image::ExifTool::ID3::SynLyrics = ( + GROUPS => { 1 => 'ID3', 2 => 'Audio' }, + VARS => { NO_ID => 1 }, + PROCESS_PROC => \&ProcessSynText, + NOTES => 'The following tags are extracted from synchronized lyrics/text frames.', + desc => { Name => 'SynchronizedLyricsDescription' }, + type => { + Name => 'SynchronizedLyricsType', + PrintConv => { + 0 => 'Other', + 1 => 'Lyrics', + 2 => 'Text Transcription', + 3 => 'Movement/part Name', + 4 => 'Events', + 5 => 'Chord', + 6 => 'Trivia/"pop-up" Information', + 7 => 'Web Page URL', + 8 => 'Image URL', + }, + }, + text => { + Name => 'SynchronizedLyricsText', + List => 1, + Notes => q{ + each list item has a leading time stamp in square brackets. Time stamps may + be in seconds with format [MM:SS.ss], or MPEG frames with format [FFFF], + depending on how this information was stored + }, + PrintConv => \&ConvertTimeStamp, + }, +); + +# ID3 PRIV tags (ref PH) +%Image::ExifTool::ID3::Private = ( + PROCESS_PROC => \&Image::ExifTool::ID3::ProcessPrivate, + GROUPS => { 1 => 'ID3', 2 => 'Audio' }, + VARS => { NO_ID => 1 }, + NOTES => q{ + ID3 private (PRIV) tags. ExifTool will decode any private tags found, even + if they do not appear in this table. + }, + XMP => { + SubDirectory => { + DirName => 'XMP', + TagTable => 'Image::ExifTool::XMP::Main', + }, + }, + PeakValue => { + ValueConv => 'length($val)==4 ? unpack("V",$val) : \$val', + }, + AverageLevel => { + ValueConv => 'length($val)==4 ? unpack("V",$val) : \$val', + }, + # Windows Media attributes ("/" in tag ID is converted to "_" by ProcessPrivate) + WM_WMContentID => { + Name => 'WM_ContentID', + ValueConv => 'require Image::ExifTool::ASF; Image::ExifTool::ASF::GetGUID($val)', + }, + WM_WMCollectionID => { + Name => 'WM_CollectionID', + ValueConv => 'require Image::ExifTool::ASF; Image::ExifTool::ASF::GetGUID($val)', + }, + WM_WMCollectionGroupID => { + Name => 'WM_CollectionGroupID', + ValueConv => 'require Image::ExifTool::ASF; Image::ExifTool::ASF::GetGUID($val)', + }, + WM_MediaClassPrimaryID => { + ValueConv => 'require Image::ExifTool::ASF; Image::ExifTool::ASF::GetGUID($val)', + }, + WM_MediaClassSecondaryID => { + ValueConv => 'require Image::ExifTool::ASF; Image::ExifTool::ASF::GetGUID($val)', + }, + WM_Provider => { + ValueConv => '$self->Decode($val,"UCS2","II")', #PH (NC) + }, + # there are lots more WM tags that could be decoded if I had samples or documentation - PH + # WM/AlbumArtist + # WM/AlbumTitle + # WM/Category + # WM/Composer + # WM/Conductor + # WM/ContentDistributor + # WM/ContentGroupDescription + # WM/EncodingTime + # WM/Genre + # WM/GenreID + # WM/InitialKey + # WM/Language + # WM/Lyrics + # WM/MCDI + # WM/MediaClassPrimaryID + # WM/MediaClassSecondaryID + # WM/Mood + # WM/ParentalRating + # WM/Period + # WM/ProtectionType + # WM/Provider + # WM/ProviderRating + # WM/ProviderStyle + # WM/Publisher + # WM/SubscriptionContentID + # WM/SubTitle + # WM/TrackNumber + # WM/UniqueFileIdentifier + # WM/WMCollectionGroupID + # WM/WMCollectionID + # WM/WMContentID + # WM/Writer + # WM/Year +); + +# lookup to check for existence of tags in other ID3 versions +my %otherTable = ( + \%Image::ExifTool::ID3::v2_4 => \%Image::ExifTool::ID3::v2_3, + \%Image::ExifTool::ID3::v2_3 => \%Image::ExifTool::ID3::v2_4, +); + +# ID3 Composite tags +%Image::ExifTool::ID3::Composite = ( + GROUPS => { 2 => 'Image' }, + DateTimeOriginal => { + Description => 'Date/Time Original', + Groups => { 2 => 'Time' }, + Priority => 0, + Desire => { + 0 => 'ID3:RecordingTime', + 1 => 'ID3:Year', + 2 => 'ID3:Date', + 3 => 'ID3:Time', + }, + ValueConv => q{ + return $val[0] if $val[0]; + return undef unless $val[1]; + return $val[1] unless $val[2] and $val[2] =~ /^(\d{2})(\d{2})$/; + $val[1] .= ":$1:$2"; + return $val[1] unless $val[3] and $val[3] =~ /^(\d{2})(\d{2})$/; + return "$val[1] $1:$2"; + }, + PrintConv => '$self->ConvertDateTime($val)', + }, +); + +# add our composite tags +Image::ExifTool::AddCompositeTags('Image::ExifTool::ID3'); + +# can't share tagInfo hashes between two tables, so we must make +# copies of the necessary hashes +{ + my $tag; + foreach $tag (keys %id3v2_common) { + next unless ref $id3v2_common{$tag} eq 'HASH'; + my %tagInfo = %{$id3v2_common{$tag}}; + # must also copy Groups hash if it exists + my $groups = $tagInfo{Groups}; + $tagInfo{Groups} = { %$groups } if $groups; + $Image::ExifTool::ID3::v2_4{$tag} = \%tagInfo; + } +} + +#------------------------------------------------------------------------------ +# Convert ID3v1 text to exiftool character set +# Inputs: 0) ExifTool object ref, 1) text string +# Returns: converted text +sub ConvertID3v1Text($$) +{ + my ($et, $val) = @_; + return $et->Decode($val, $et->Options('CharsetID3')); +} + +#------------------------------------------------------------------------------ +# Re-format time stamp in synchronized lyrics +# Inputs: 0) synchronized lyrics entry (eg. "[84.030]Da do do do") +# Returns: entry with formatted timestamp (eg. "[01:24.03]Da do do do") +sub ConvertTimeStamp($) +{ + my $val = shift; + # do nothing if this isn't a time stamp (frame count doesn't contain a decimal) + return $val unless $val =~ /^\[(\d+\.\d+)\]/g; + my $time = $1; + # print hours only if more than 60 minutes + my $h = int($time / 3600); + if ($h) { + $time -= $h * 3600; + $h = "$h:"; + } else { + $h = ''; + } + my $m = int($time / 60); + my $s = $time - $m * 60; + my $ss = sprintf('%05.2f', $s); + if ($ss >= 60) { + $ss = '00.00'; + ++$m >= 60 and $m -= 60, ++$h; + } + return sprintf('[%s%.2d:%s]', $h, $m, $ss) . substr($val, pos($val)); +} + +#------------------------------------------------------------------------------ +# Process ID3 synchronized lyrics/text +# Inputs: 0) ExifTool object ref, 1) dirInfo ref, 2) tag table ref +sub ProcessSynText($$$) +{ + my ($et, $dirInfo, $tagTablePtr) = @_; + my $dataPt = $$dirInfo{DataPt}; + + $et->VerboseDir('SynLyrics', 0, length $$dataPt); + return unless length $$dataPt > 6; + + my ($enc,$lang,$timeCode,$type) = unpack('Ca3CC', $$dataPt); + $lang = lc $lang; + undef $lang if $lang !~ /^[a-z]{3}$/ or $lang eq 'eng'; + pos($$dataPt) = 6; + my ($termLen, $pat); + if ($enc == 1 or $enc == 2) { + $$dataPt =~ /\G(..)*?\0\0/sg or return; + $termLen = 2; + $pat = '\G(?:..)*?\0\0(....)'; + } else { + $$dataPt =~ /\0/g or return; + $termLen = 1; + $pat = '\0(....)'; + } + my $desc = substr($$dataPt, 6, pos($$dataPt) - 6 - $termLen); + $desc = DecodeString($et, $desc, $enc); + + my $tagInfo = $et->GetTagInfo($tagTablePtr, 'desc'); + $tagInfo = Image::ExifTool::GetLangInfo($tagInfo, $lang) if $lang; + $et->HandleTag($tagTablePtr, 'type', $type); + $et->HandleTag($tagTablePtr, 'desc', $desc, TagInfo => $tagInfo); + $tagInfo = $et->GetTagInfo($tagTablePtr, 'text'); + $tagInfo = Image::ExifTool::GetLangInfo($tagInfo, $lang) if $lang; + + for (;;) { + my $pos = pos $$dataPt; + last unless $$dataPt =~ /$pat/sg; + my $time = unpack('N', $1); + my $text = substr($$dataPt, $pos, pos($$dataPt) - $pos - 4 - $termLen); + $text = DecodeString($et, $text, $enc); + my $timeStr; + if ($timeCode == 2) { # time in ms + $timeStr = sprintf('%.3f', $time / 1000); + } else { # time in MPEG frames + $timeStr = sprintf('%.4d', $time); + $timeStr .= '?' if $timeCode != 1; + } + $et->HandleTag($tagTablePtr, 'text', "[$timeStr]$text", TagInfo => $tagInfo); + } +} + +#------------------------------------------------------------------------------ +# Process ID3 PRIV data +# Inputs: 0) ExifTool object ref, 1) dirInfo ref, 2) tag table ref +sub ProcessPrivate($$$) +{ + my ($et, $dirInfo, $tagTablePtr) = @_; + my $dataPt = $$dirInfo{DataPt}; + my ($tag, $start); + $et->VerboseDir('PRIV', 0, length $$dataPt); + if ($$dataPt =~ /^(.*?)\0/s) { + $tag = $1; + $start = length($tag) + 1; + } else { + $tag = ''; + $start = 0; + } + unless ($$tagTablePtr{$tag}) { + $tag =~ tr{/ }{_}d; # translate '/' to '_' and remove spaces + $tag = 'private' unless $tag =~ /^[-\w]{1,24}$/; + unless ($$tagTablePtr{$tag}) { + AddTagToTable($tagTablePtr, $tag, + { Name => ucfirst($tag), Binary => 1 }); + } + } + my $key = $et->HandleTag($tagTablePtr, $tag, undef, + Size => length($$dataPt) - $start, + Start => $start, + DataPt => $dataPt, + ); + # set group1 name + $et->SetGroup($key, $$et{ID3_Ver}) if $key; +} + +#------------------------------------------------------------------------------ +# Print ID3v2 Genre +# Inputs: TCON or TCO frame data +# Returns: Content type with decoded genre numbers +sub PrintGenre($) +{ + my $val = shift; + # make sure that %genre has an entry for all numbers we are interested in + # (genre numbers are in brackets for ID3v2.2 and v2.3) + while ($val =~ /\((\d+)\)/g) { + $genre{$1} or $genre{$1} = "Unknown ($1)"; + } + # (genre numbers are separated by nulls in ID3v2.4, + # but nulls are converted to '/' by DecodeString()) + while ($val =~ /(?:^|\/)(\d+)(\/|$)/g) { + $genre{$1} or $genre{$1} = "Unknown ($1)"; + } + $val =~ s/\((\d+)\)/\($genre{$1}\)/g; + $val =~ s/(^|\/)(\d+)(?=\/|$)/$1$genre{$2}$3/g; + $val =~ s/^\(([^)]+)\)\1?$/$1/; # clean up by removing brackets and duplicates + return $val; +} + +#------------------------------------------------------------------------------ +# Decode ID3 string +# Inputs: 0) ExifTool object reference +# 1) string beginning with encoding byte unless specified as argument +# 2) optional encoding (0=ISO-8859-1, 1=UTF-16 BOM, 2=UTF-16BE, 3=UTF-8) +# Returns: Decoded string in scalar context, or list of strings in list context +sub DecodeString($$;$) +{ + my ($et, $val, $enc) = @_; + return '' unless length $val; + unless (defined $enc) { + $enc = unpack('C', $val); + $val = substr($val, 1); # remove encoding byte + } + my @vals; + if ($enc == 0 or $enc == 3) { # ISO 8859-1 or UTF-8 + $val =~ s/\0+$//; # remove any null padding + # (must split before converting because conversion routines truncate at null) + @vals = split "\0", $val; + foreach $val (@vals) { + $val = $et->Decode($val, $enc ? 'UTF8' : 'Latin'); + } + } elsif ($enc == 1 or $enc == 2) { # UTF-16 with BOM, or UTF-16BE + my $bom = "\xfe\xff"; + my %order = ( "\xfe\xff" => 'MM', "\xff\xfe", => 'II' ); + for (;;) { + my $v; + # split string at null terminators on word boundaries + if ($val =~ s/((..)*?)\0\0//s) { + $v = $1; + } else { + last unless length $val > 1; + $v = $val; + $val = ''; + } + $bom = $1 if $v =~ s/^(\xfe\xff|\xff\xfe)//; + push @vals, $et->Decode($v, 'UCS2', $order{$bom}); + } + } else { + $val =~ s/\0+$//; + return "<Unknown encoding $enc> $val"; + } + return @vals if wantarray; + return join('/',@vals); +} + +#------------------------------------------------------------------------------ +# Convert sync-safe integer to a number we can use +# Inputs: 0) int32u sync-safe value +# Returns: actual number or undef on invalid value +sub UnSyncSafe($) +{ + my $val = shift; + return undef if $val & 0x80808080; + return ($val & 0x0000007f) | + (($val & 0x00007f00) >> 1) | + (($val & 0x007f0000) >> 2) | + (($val & 0x7f000000) >> 3); +} + +#------------------------------------------------------------------------------ +# Process ID3v2 information +# Inputs: 0) ExifTool object ref, 1) dirInfo ref, 2) tag table ref +sub ProcessID3v2($$$) +{ + my ($et, $dirInfo, $tagTablePtr) = @_; + my $dataPt = $$dirInfo{DataPt}; + my $offset = $$dirInfo{DirStart}; + my $size = $$dirInfo{DirLen}; + my $vers = $$dirInfo{Version}; + my $verbose = $et->Options('Verbose'); + my $len; # frame data length + + $et->VerboseDir($tagTablePtr->{GROUPS}->{1}, 0, $size); + $et->VerboseDump($dataPt, Len => $size, Start => $offset); + + for (;;$offset+=$len) { + my ($id, $flags, $hi); + if ($vers < 0x0300) { + # version 2.2 frame header is 6 bytes + last if $offset + 6 > $size; + ($id, $hi, $len) = unpack("x${offset}a3Cn",$$dataPt); + last if $id eq "\0\0\0"; + $len += $hi << 16; + $offset += 6; + } else { + # version 2.3/2.4 frame header is 10 bytes + last if $offset + 10 > $size; + ($id, $len, $flags) = unpack("x${offset}a4Nn",$$dataPt); + last if $id eq "\0\0\0\0"; + $offset += 10; + # length is a "sync-safe" integer by the ID3v2.4 specification, but + # reportedly some versions of iTunes write this as a normal integer + # (ref http://www.id3.org/iTunes) + while ($vers >= 0x0400 and $len > 0x7f and not $len & 0x80808080) { + my $oldLen = $len; + $len = UnSyncSafe($len); + if (not defined $len or $offset + $len + 10 > $size) { + $et->Warn('Invalid ID3 frame size'); + last; + } + # check next ID to see if it makes sense + my $nextID = substr($$dataPt, $offset + $len, 4); + last if $$tagTablePtr{$nextID}; + # try again with the incorrect length word (patch for iTunes bug) + last if $offset + $oldLen + 10 > $size; + $nextID = substr($$dataPt, $offset + $len, 4); + $len = $oldLen if $$tagTablePtr{$nextID}; + last; # yes, "while" was really a "goto" in disguise + } + } + last if $offset + $len > $size; + my $tagInfo = $et->GetTagInfo($tagTablePtr, $id); + unless ($tagInfo) { + my $otherTable = $otherTable{$tagTablePtr}; + $tagInfo = $et->GetTagInfo($otherTable, $id) if $otherTable; + if ($tagInfo) { + $et->WarnOnce("Frame '${id}' is not valid for this ID3 version", 1); + } else { + next unless $verbose or $et->Options('Unknown'); + $id =~ tr/-A-Za-z0-9_//dc; + $id = 'unknown' unless length $id; + unless ($$tagTablePtr{$id}) { + $tagInfo = { Name => "ID3_$id", Binary => 1 }; + AddTagToTable($tagTablePtr, $id, $tagInfo); + } + } + } + # decode v2.3 and v2.4 flags + my (%flags, %extra); + if ($flags) { + if ($vers < 0x0400) { + # version 2.3 flags + $flags & 0x80 and $flags{Compress} = 1; + $flags & 0x40 and $flags{Encrypt} = 1; + $flags & 0x20 and $flags{GroupID} = 1; + } else { + # version 2.4 flags + $flags & 0x40 and $flags{GroupID} = 1; + $flags & 0x08 and $flags{Compress} = 1; + $flags & 0x04 and $flags{Encrypt} = 1; + $flags & 0x02 and $flags{Unsync} = 1; + $flags & 0x01 and $flags{DataLen} = 1; + } + } + if ($flags{Encrypt}) { + $et->WarnOnce('Encrypted frames currently not supported'); + next; + } + # extract the value + my $val = substr($$dataPt, $offset, $len); + + # reverse the unsynchronization + $val =~ s/\xff\x00/\xff/g if $flags{Unsync}; + + # read grouping identity + if ($flags{GroupID}) { + length($val) >= 1 or $et->Warn("Short $id frame"), next; + $val = substr($val, 1); # (ignore it) + } + # read data length + my $dataLen; + if ($flags{DataLen} or $flags{Compress}) { + length($val) >= 4 or $et->Warn("Short $id frame"), next; + $dataLen = unpack('N', $val); # save the data length word + $val = substr($val, 4); + } + # uncompress data + if ($flags{Compress}) { + if (eval { require Compress::Zlib }) { + my $inflate = Compress::Zlib::inflateInit(); + my ($buff, $stat); + $inflate and ($buff, $stat) = $inflate->inflate($val); + if ($inflate and $stat == Compress::Zlib::Z_STREAM_END()) { + $val = $buff; + } else { + $et->Warn("Error inflating $id frame"); + next; + } + } else { + $et->WarnOnce('Install Compress::Zlib to decode compressed frames'); + next; + } + } + # validate data length + if (defined $dataLen) { + $dataLen = UnSyncSafe($dataLen); + defined $dataLen or $et->Warn("Invalid length for $id frame"), next; + $dataLen == length($val) or $et->Warn("Wrong length for $id frame"), next; + } + unless ($tagInfo) { + next unless $verbose; + %flags and $extra{Extra} = ', Flags=' . join(',', sort keys %flags); + $et->VerboseInfo($id, $tagInfo, + Table => $tagTablePtr, + Value => $val, + DataPt => $dataPt, + DataPos => $$dirInfo{DataPos}, + Size => $len, + Start => $offset, + %extra + ); + next; + } +# +# decode data in this frame (it is bad form to hard-code these, but the ID3 frame formats +# are so variable that it would be more work to define format types for each of them) +# + my $lang; + my $valLen = length($val); # actual value length (after decompression, etc) + if ($id =~ /^(TXX|TXXX)$/) { + # two encoded strings separated by a null + my @vals = DecodeString($et, $val); + foreach (0..1) { $vals[$_] = '' unless defined $vals[$_]; } + ($val = "($vals[0]) $vals[1]") =~ s/^\(\) //; + } elsif ($id =~ /^T/ or $id =~ /^(IPL|IPLS)$/) { + $val = DecodeString($et, $val); + } elsif ($id =~ /^(WXX|WXXX)$/) { + # one encoded string and one Latin string separated by a null + my $enc = unpack('C', $val); + my $url; + if ($enc == 1 or $enc == 2) { + ($val, $url) = ($val =~ /^(.(?:..)*?)\0\0(.*)/s); + } else { + ($val, $url) = ($val =~ /^(..*?)\0(.*)/s); + } + unless (defined $val and defined $url) { + $et->Warn("Invalid $id frame value"); + next; + } + $val = DecodeString($et, $val); + $url =~ s/\0.*//s; + $val = length($val) ? "($val) $url" : $url; + } elsif ($id =~ /^W/) { + $val =~ s/\0.*//s; # truncate at null + } elsif ($id =~ /^(COM|COMM|ULT|USLT)$/) { + $valLen > 4 or $et->Warn("Short $id frame"), next; + $lang = substr($val,1,3); + my @vals = DecodeString($et, substr($val,4), Get8u(\$val,0)); + foreach (0..1) { $vals[$_] = '' unless defined $vals[$_]; } + $val = length($vals[0]) ? "($vals[0]) $vals[1]" : $vals[1]; + } elsif ($id eq 'USER') { + $valLen > 4 or $et->Warn("Short $id frame"), next; + $lang = substr($val,1,3); + $val = DecodeString($et, substr($val,4), Get8u(\$val,0)); + } elsif ($id =~ /^(CNT|PCNT)$/) { + $valLen >= 4 or $et->Warn("Short $id frame"), next; + my ($cnt, @xtra) = unpack('NC*', $val); + $cnt = ($cnt << 8) + $_ foreach @xtra; + $val = $cnt; + } elsif ($id =~ /^(PIC|APIC)$/) { + $valLen >= 4 or $et->Warn("Short $id frame"), next; + my ($hdr, $attr); + my $enc = unpack('C', $val); + if ($enc == 1 or $enc == 2) { + $hdr = ($id eq 'PIC') ? ".(...)(.)((?:..)*?)\0\0" : ".(.*?)\0(.)((?:..)*?)\0\0"; + } else { + $hdr = ($id eq 'PIC') ? ".(...)(.)(.*?)\0" : ".(.*?)\0(.)(.*?)\0"; + } + # remove header (encoding, image format or MIME type, picture type, description) + $val =~ s/^$hdr//s or $et->Warn("Invalid $id frame"), next; + my @attrs = ($1, ord($2), DecodeString($et, $3, $enc)); + my $i = 1; + foreach $attr (@attrs) { + # must store descriptions even if they are empty to maintain + # sync between copy numbers when multiple images + $et->HandleTag($tagTablePtr, "$id-$i", $attr); + ++$i; + } + } elsif ($id eq 'POP' or $id eq 'POPM') { + # _email, 00, rating(1), counter(4-N) + my ($email, $dat) = ($val =~ /^([^\0]*)\0(.*)$/s); + unless (defined $dat and length($dat)) { + $et->Warn("Invalid $id frame"); + next; + } + my ($rating, @xtra) = unpack('C*', $dat); + my $cnt = 0; + $cnt = ($cnt << 8) + $_ foreach @xtra; + $val = "$email $rating $cnt"; + } elsif ($id eq 'OWNE') { + # enc(1), _price, 00, _date(8), Seller + my @strs = DecodeString($et, $val); + $strs[1] =~ s/^(\d{4})(\d{2})(\d{2})/$1:$2:$3 /s if $strs[1]; # format date + $val = "@strs"; + } elsif ($id eq 'RVA' or $id eq 'RVAD') { + my @dat = unpack('C*', $val); + my $flag = shift @dat; + my $bits = shift @dat or $et->Warn("Short $id frame"), next; + my $bytes = int(($bits + 7) / 8); + my @parse = (['Right',0,2,0x01],['Left',1,3,0x02],['Back-right',4,6,0x04], + ['Back-left',5,7,0x08],['Center',8,9,0x10],['Bass',10,11,0x20]); + $val = ''; + while (@parse) { + my $elem = shift @parse; + my $j = $$elem[2] * $bytes; + last if scalar(@dat) < $j + $bytes; + my $i = $$elem[1] * $bytes; + $val .= ', ' if $val; + my ($rel, $pk, $b); + for ($rel=0, $pk=0, $b=0; $b<$bytes; ++$b) { + $rel = $rel * 256 + $dat[$i + $b]; + $pk = $pk * 256 + $dat[$j + $b]; # (peak - not used in printout) + } + $rel =-$rel unless $flag & $$elem[3]; + $val .= sprintf("%+.1f%% %s", 100 * $rel / ((1<<$bits)-1), $$elem[0]); + } + } elsif ($id eq 'RVA2') { + my ($pos, $id) = $val=~/^([^\0]*)\0/s ? (length($1)+1, $1) : (1, ''); + my @vals; + while ($pos + 4 <= $valLen) { + my $type = Get8u(\$val, $pos); + my $str = ({ + 0 => 'Other', + 1 => 'Master', + 2 => 'Front-right', + 3 => 'Front-left', + 4 => 'Back-right', + 5 => 'Back-left', + 6 => 'Front-centre', + 7 => 'Back-centre', + 8 => 'Subwoofer', + }->{$type} || "Unknown($type)"); + my $db = Get16s(\$val,$pos+1) / 512; + # convert dB to percent as displayed by iTunes 10.5 + # (not sure why I need to divide by 20 instead of 10 as expected - PH) + push @vals, sprintf('%+.1f%% %s', 10**($db/20+2)-100, $str); + # step to next channel (ignoring peak volume) + $pos += 4 + int((Get8u(\$val,$pos+3) + 7) / 8); + } + $val = join ', ', @vals; + $val .= " ($id)" if $id; + } elsif ($id eq 'PRIV') { + # save version number to set group1 name for tag later + $$et{ID3_Ver} = $$tagTablePtr{GROUPS}{1}; + $et->HandleTag($tagTablePtr, $id, $val); + next; + } elsif ($$tagInfo{Format} or $$tagInfo{SubDirectory}) { + $et->HandleTag($tagTablePtr, $id, undef, DataPt => \$val); + next; + } elsif (not $$tagInfo{Binary}) { + $et->Warn("Don't know how to handle $id frame"); + next; + } + if ($lang and $lang =~ /^[a-z]{3}$/i and $lang ne 'eng') { + $tagInfo = Image::ExifTool::GetLangInfo($tagInfo, lc $lang); + } + %flags and $extra{Extra} = ', Flags=' . join(',', sort keys %flags); + $et->HandleTag($tagTablePtr, $id, $val, + TagInfo => $tagInfo, + DataPt => $dataPt, + DataPos => $$dirInfo{DataPos}, + Size => $len, + Start => $offset, + %extra + ); + } +} + +#------------------------------------------------------------------------------ +# Extract ID3 information from an audio file +# Inputs: 0) ExifTool object reference, 1) dirInfo reference +# Returns: 1 on success, 0 if this file didn't contain ID3 information +# - also processes audio data if any ID3 information was found +# - sets ExifTool DoneID3 to 1 when called, or to 2 if an ID3v1 trailer exists +sub ProcessID3($$) +{ + my ($et, $dirInfo) = @_; + + return 0 if $$et{DoneID3}; # avoid infinite recursion + $$et{DoneID3} = 1; + + # allow this to be called with either RAF or DataPt + my $raf = $$dirInfo{RAF} || new File::RandomAccess($$dirInfo{DataPt}); + my ($buff, %id3Header, %id3Trailer, $hBuff, $tBuff, $eBuff, $tagTablePtr); + my $rtnVal = 0; + my $hdrEnd = 0; + my $id3Len = 0; + + # read first 3 bytes of file + $raf->Seek(0, 0); + return 0 unless $raf->Read($buff, 3) == 3; +# +# identify ID3v2 header +# + while ($buff =~ /^ID3/) { + $rtnVal = 1; + $raf->Read($hBuff, 7) == 7 or $et->Warn('Short ID3 header'), last; + my ($vers, $flags, $size) = unpack('nCN', $hBuff); + $size = UnSyncSafe($size); + defined $size or $et->Warn('Invalid ID3 header'), last; + my $verStr = sprintf("2.%d.%d", $vers >> 8, $vers & 0xff); + if ($vers >= 0x0500) { + $et->Warn("Unsupported ID3 version: $verStr"); + last; + } + unless ($raf->Read($hBuff, $size) == $size) { + $et->Warn('Truncated ID3 data'); + last; + } + # this flag only indicates use of unsynchronized frames in ID3v2.4 + if ($flags & 0x80 and $vers < 0x0400) { + # reverse the unsynchronization + $hBuff =~ s/\xff\x00/\xff/g; + } + my $pos = 10; + if ($flags & 0x40) { + # skip the extended header + $size >= 4 or $et->Warn('Bad ID3 extended header'), last; + my $len = unpack('N', $hBuff); + if ($len > length($hBuff) - 4) { + $et->Warn('Truncated ID3 extended header'); + last; + } + $hBuff = substr($hBuff, $len + 4); + $pos += $len + 4; + } + if ($flags & 0x10) { + # ignore v2.4 footer (10 bytes long) + $raf->Seek(10, 1); + } + %id3Header = ( + DataPt => \$hBuff, + DataPos => $pos, + DirStart => 0, + DirLen => length($hBuff), + Version => $vers, + DirName => "ID3v$verStr", + ); + $id3Len += length($hBuff) + 10; + if ($vers >= 0x0400) { + $tagTablePtr = GetTagTable('Image::ExifTool::ID3::v2_4'); + } elsif ($vers >= 0x0300) { + $tagTablePtr = GetTagTable('Image::ExifTool::ID3::v2_3'); + } else { + $tagTablePtr = GetTagTable('Image::ExifTool::ID3::v2_2'); + } + $hdrEnd = $raf->Tell(); + last; + } +# +# read ID3v1 trailer if it exists +# + if ($raf->Seek(-128, 2) and $raf->Read($tBuff, 128) == 128 and $tBuff =~ /^TAG/) { + $$et{DoneID3} = 2; # set to 2 as flag that trailer exists + %id3Trailer = ( + DataPt => \$tBuff, + DataPos => $raf->Tell() - 128, + DirStart => 0, + DirLen => length($tBuff), + ); + $id3Len += length($tBuff); + $rtnVal = 1; + # load 'Enhanced TAG' information if available + if ($raf->Seek(-355, 2) and $raf->Read($eBuff, 227) == 227 and $eBuff =~ /^TAG+/) { + $id3Trailer{EnhancedTAG} = \$eBuff; + } + } +# +# process the the information +# + if ($rtnVal) { + # first process audio data if it exists + if ($$dirInfo{RAF}) { + my $oldType = $$et{FILE_TYPE}; # save file type + # check current file type first + my @types = grep /^$oldType$/, @audioFormats; + push @types, grep(!/^$oldType$/, @audioFormats); + my $type; + foreach $type (@types) { + # seek to end of ID3 header + $raf->Seek($hdrEnd, 0); + # set type for this file if we are successful + $$et{FILE_TYPE} = $type; + my $module = $audioModule{$type} || $type; + require "Image/ExifTool/$module.pm" or next; + my $func = "Image::ExifTool::${module}::Process$type"; + # process the file + no strict 'refs'; + &$func($et, $dirInfo) and last; + use strict 'refs'; + } + $$et{FILE_TYPE} = $oldType; # restore original file type + } + # set file type to MP3 if we didn't find audio data + $et->SetFileType('MP3'); + # record the size of the ID3 metadata + $et->FoundTag('ID3Size', $id3Len); + # process ID3v2 header if it exists + if (%id3Header) { + $et->VPrint(0, "$id3Header{DirName}:\n"); + $et->ProcessDirectory(\%id3Header, $tagTablePtr); + } + # process ID3v1 trailer if it exists + if (%id3Trailer) { + $et->VPrint(0, "ID3v1:\n"); + SetByteOrder('MM'); + $tagTablePtr = GetTagTable('Image::ExifTool::ID3::v1'); + $et->ProcessDirectory(\%id3Trailer, $tagTablePtr); + # process "Enhanced TAG" information if available + if ($id3Trailer{EnhancedTAG}) { + $et->VPrint(0, "ID3v1 Enhanced TAG:\n"); + $tagTablePtr = GetTagTable('Image::ExifTool::ID3::v1_Enh'); + $id3Trailer{DataPt} = $id3Trailer{EnhancedTAG}; + $id3Trailer{DataPos} -= 227; # (227 = length of Enhanced TAG block) + $id3Trailer{DirLen} = 227; + $et->ProcessDirectory(\%id3Trailer, $tagTablePtr); + } + } + } + # return file pointer to start of file to read audio data if necessary + $raf->Seek(0, 0); + return $rtnVal; +} + +#------------------------------------------------------------------------------ +# Extract ID3 information from an MP3 audio file +# Inputs: 0) ExifTool object reference, 1) dirInfo reference +# Returns: 1 on success, 0 if this wasn't a valid MP3 file +sub ProcessMP3($$) +{ + my ($et, $dirInfo) = @_; + my $rtnVal = 0; + + # must first check for leading/trailing ID3 information + # (and process the rest of the file if found) + unless ($$et{DoneID3}) { + $rtnVal = ProcessID3($et, $dirInfo); + } + + # check for MPEG A/V data if not already processed above + unless ($rtnVal) { + my $raf = $$dirInfo{RAF}; + my $buff; +# +# extract information from first audio/video frame headers +# (if found in the first $scanLen bytes) +# + # scan further into a file that should be an MP3 + my $scanLen = ($$et{FILE_EXT} and $$et{FILE_EXT} eq 'MP3') ? 8192 : 256; + if ($raf->Read($buff, $scanLen)) { + require Image::ExifTool::MPEG; + if ($buff =~ /\0\0\x01(\xb3|\xc0)/) { + # look for A/V headers in first 64kB + my $buf2; + $raf->Read($buf2, 0x10000 - $scanLen) and $buff .= $buf2; + $rtnVal = 1 if Image::ExifTool::MPEG::ParseMPEGAudioVideo($et, \$buff); + } else { + # look for audio frame sync in first $scanLen bytes + # (set MP3 flag to 1 so this will fail unless layer 3 audio) + my $ext = $$et{FILE_EXT} || ''; + my $mp3 = ($ext eq 'MUS') ? 0 : 1; # MUS files are MP2 + $rtnVal = 1 if Image::ExifTool::MPEG::ParseMPEGAudio($et, \$buff, $mp3); + } + } + } + + # check for an APE trailer if this was a valid A/V file and we haven't already done it + if ($rtnVal and not $$et{DoneAPE}) { + require Image::ExifTool::APE; + Image::ExifTool::APE::ProcessAPE($et, $dirInfo); + } + return $rtnVal; +} + +1; # end + +__END__ + +=head1 NAME + +Image::ExifTool::ID3 - Read ID3 meta information + +=head1 SYNOPSIS + +This module is used by Image::ExifTool + +=head1 DESCRIPTION + +This module contains definitions required by Image::ExifTool to extract ID3 +information from audio files. ID3 information is found in MP3 and various +other types of audio files. + +=head1 AUTHOR + +Copyright 2003-2019, Phil Harvey (phil at owl.phy.queensu.ca) + +This library is free software; you can redistribute it and/or modify it +under the same terms as Perl itself. + +=head1 REFERENCES + +=over 4 + +=item L<http://www.id3.org/> + +=item L<http://www.mp3-tech.org/> + +=item L<http://www.fortunecity.com/underworld/sonic/3/id3tag.html> + +=back + +=head1 SEE ALSO + +L<Image::ExifTool::TagNames/ID3 Tags>, +L<Image::ExifTool(3pm)|Image::ExifTool> + +=cut + diff --git a/lib/Image/ExifTool/IPTC.pm b/lib/Image/ExifTool/IPTC.pm new file mode 100644 index 0000000..5ab6600 --- /dev/null +++ b/lib/Image/ExifTool/IPTC.pm @@ -0,0 +1,1274 @@ +#------------------------------------------------------------------------------ +# File: IPTC.pm +# +# Description: Read IPTC meta information +# +# Revisions: Jan. 08/2003 - P. Harvey Created +# Feb. 05/2004 - P. Harvey Added support for records other than 2 +# +# References: 1) http://www.iptc.org/IIM/ +#------------------------------------------------------------------------------ + +package Image::ExifTool::IPTC; + +use strict; +use vars qw($VERSION $AUTOLOAD %iptcCharset); +use Image::ExifTool qw(:DataAccess :Utils); + +$VERSION = '1.56'; + +%iptcCharset = ( + "\x1b%G" => 'UTF8', + # don't translate these (at least until we handle ISO 2022 shift codes) + # because the sets are only designated and not invoked + # "\x1b,A" => 'Latin', # G0 = ISO 8859-1 (similar to Latin1, but codes 0x80-0x9f are missing) + # "\x1b-A" => 'Latin', # G1 " + # "\x1b.A" => 'Latin', # G2 + # "\x1b/A" => 'Latin', # G3 +); + +sub ProcessIPTC($$$); +sub WriteIPTC($$$); +sub CheckIPTC($$$); +sub PrintCodedCharset($); +sub PrintInvCodedCharset($); + +# standard IPTC locations +# (MWG specifies locations only for JPEG, TIFF and PSD -- the rest are ExifTool-defined) +my %isStandardIPTC = ( + 'JPEG-APP13-Photoshop-IPTC' => 1, + 'TIFF-IFD0-IPTC' => 1, + 'PSD-IPTC' => 1, + 'MIE-IPTC' => 1, + 'EPS-Photoshop-IPTC' => 1, + 'PS-Photoshop-IPTC' => 1, + 'EXV-APP13-Photoshop-IPTC' => 1, + # set file types to 0 if they have a standard location + JPEG => 0, + TIFF => 0, + PSD => 0, + MIE => 0, + EPS => 0, + PS => 0, + EXV => 0, +); + +my %fileFormat = ( + 0 => 'No ObjectData', + 1 => 'IPTC-NAA Digital Newsphoto Parameter Record', + 2 => 'IPTC7901 Recommended Message Format', + 3 => 'Tagged Image File Format (Adobe/Aldus Image data)', + 4 => 'Illustrator (Adobe Graphics data)', + 5 => 'AppleSingle (Apple Computer Inc)', + 6 => 'NAA 89-3 (ANPA 1312)', + 7 => 'MacBinary II', + 8 => 'IPTC Unstructured Character Oriented File Format (UCOFF)', + 9 => 'United Press International ANPA 1312 variant', + 10 => 'United Press International Down-Load Message', + 11 => 'JPEG File Interchange (JFIF)', + 12 => 'Photo-CD Image-Pac (Eastman Kodak)', + 13 => 'Bit Mapped Graphics File [.BMP] (Microsoft)', + 14 => 'Digital Audio File [.WAV] (Microsoft & Creative Labs)', + 15 => 'Audio plus Moving Video [.AVI] (Microsoft)', + 16 => 'PC DOS/Windows Executable Files [.COM][.EXE]', + 17 => 'Compressed Binary File [.ZIP] (PKWare Inc)', + 18 => 'Audio Interchange File Format AIFF (Apple Computer Inc)', + 19 => 'RIFF Wave (Microsoft Corporation)', + 20 => 'Freehand (Macromedia/Aldus)', + 21 => 'Hypertext Markup Language [.HTML] (The Internet Society)', + 22 => 'MPEG 2 Audio Layer 2 (Musicom), ISO/IEC', + 23 => 'MPEG 2 Audio Layer 3, ISO/IEC', + 24 => 'Portable Document File [.PDF] Adobe', + 25 => 'News Industry Text Format (NITF)', + 26 => 'Tape Archive [.TAR]', + 27 => 'Tidningarnas Telegrambyra NITF version (TTNITF DTD)', + 28 => 'Ritzaus Bureau NITF version (RBNITF DTD)', + 29 => 'Corel Draw [.CDR]', +); + +# main IPTC tag table +# Note: ALL entries in main IPTC table (except PROCESS_PROC) must be SubDirectory +# entries, each specifying a TagTable. +%Image::ExifTool::IPTC::Main = ( + GROUPS => { 2 => 'Image' }, + PROCESS_PROC => \&ProcessIPTC, + WRITE_PROC => \&WriteIPTC, + 1 => { + Name => 'IPTCEnvelope', + SubDirectory => { + TagTable => 'Image::ExifTool::IPTC::EnvelopeRecord', + }, + }, + 2 => { + Name => 'IPTCApplication', + SubDirectory => { + TagTable => 'Image::ExifTool::IPTC::ApplicationRecord', + }, + }, + 3 => { + Name => 'IPTCNewsPhoto', + SubDirectory => { + TagTable => 'Image::ExifTool::IPTC::NewsPhoto', + }, + }, + 7 => { + Name => 'IPTCPreObjectData', + SubDirectory => { + TagTable => 'Image::ExifTool::IPTC::PreObjectData', + }, + }, + 8 => { + Name => 'IPTCObjectData', + SubDirectory => { + TagTable => 'Image::ExifTool::IPTC::ObjectData', + }, + }, + 9 => { + Name => 'IPTCPostObjectData', + Groups => { 1 => 'IPTC#' }, #(just so this shows up in group list) + SubDirectory => { + TagTable => 'Image::ExifTool::IPTC::PostObjectData', + }, + }, + 240 => { + Name => 'IPTCFotoStation', + SubDirectory => { + TagTable => 'Image::ExifTool::IPTC::FotoStation', + }, + }, +); + +# Record 1 -- EnvelopeRecord +%Image::ExifTool::IPTC::EnvelopeRecord = ( + GROUPS => { 2 => 'Other' }, + WRITE_PROC => \&WriteIPTC, + CHECK_PROC => \&CheckIPTC, + WRITABLE => 1, + 0 => { + Name => 'EnvelopeRecordVersion', + Format => 'int16u', + Mandatory => 1, + }, + 5 => { + Name => 'Destination', + Flags => 'List', + Groups => { 2 => 'Location' }, + Format => 'string[0,1024]', + }, + 20 => { + Name => 'FileFormat', + Groups => { 2 => 'Image' }, + Format => 'int16u', + PrintConv => \%fileFormat, + }, + 22 => { + Name => 'FileVersion', + Groups => { 2 => 'Image' }, + Format => 'int16u', + }, + 30 => { + Name => 'ServiceIdentifier', + Format => 'string[0,10]', + }, + 40 => { + Name => 'EnvelopeNumber', + Format => 'digits[8]', + }, + 50 => { + Name => 'ProductID', + Flags => 'List', + Format => 'string[0,32]', + }, + 60 => { + Name => 'EnvelopePriority', + Format => 'digits[1]', + PrintConv => { + 0 => '0 (reserved)', + 1 => '1 (most urgent)', + 2 => 2, + 3 => 3, + 4 => 4, + 5 => '5 (normal urgency)', + 6 => 6, + 7 => 7, + 8 => '8 (least urgent)', + 9 => '9 (user-defined priority)', + }, + }, + 70 => { + Name => 'DateSent', + Groups => { 2 => 'Time' }, + Format => 'digits[8]', + Shift => 'Time', + ValueConv => 'Image::ExifTool::Exif::ExifDate($val)', + ValueConvInv => 'Image::ExifTool::IPTC::IptcDate($val)', + PrintConvInv => 'Image::ExifTool::IPTC::InverseDateOrTime($self,$val)', + }, + 80 => { + Name => 'TimeSent', + Groups => { 2 => 'Time' }, + Format => 'string[11]', + Shift => 'Time', + ValueConv => 'Image::ExifTool::Exif::ExifTime($val)', + ValueConvInv => 'Image::ExifTool::IPTC::IptcTime($val)', + PrintConvInv => 'Image::ExifTool::IPTC::InverseDateOrTime($self,$val)', + }, + 90 => { + Name => 'CodedCharacterSet', + Notes => q{ + values are entered in the form "ESC X Y[, ...]". The escape sequence for + UTF-8 character coding is "ESC % G", but this is displayed as "UTF8" for + convenience. Either string may be used when writing. The value of this tag + affects the decoding of string values in the Application and NewsPhoto + records. This tag is marked as "unsafe" to prevent it from being copied by + default in a group operation because existing tags in the destination image + may use a different encoding. When creating a new IPTC record from scratch, + it is suggested that this be set to "UTF8" if special characters are a + possibility + }, + Protected => 1, + Format => 'string[0,32]', + ValueConvInv => '$val =~ /^UTF-?8$/i ? "\x1b%G" : $val', + # convert ISO 2022 escape sequences to a more readable format + PrintConv => \&PrintCodedCharset, + PrintConvInv => \&PrintInvCodedCharset, + }, + 100 => { + Name => 'UniqueObjectName', + Format => 'string[14,80]', + }, + 120 => { + Name => 'ARMIdentifier', + Format => 'int16u', + }, + 122 => { + Name => 'ARMVersion', + Format => 'int16u', + }, +); + +# Record 2 -- ApplicationRecord +%Image::ExifTool::IPTC::ApplicationRecord = ( + GROUPS => { 2 => 'Other' }, + WRITE_PROC => \&WriteIPTC, + CHECK_PROC => \&CheckIPTC, + WRITABLE => 1, + 0 => { + Name => 'ApplicationRecordVersion', + Format => 'int16u', + Mandatory => 1, + }, + 3 => { + Name => 'ObjectTypeReference', + Format => 'string[3,67]', + }, + 4 => { + Name => 'ObjectAttributeReference', + Flags => 'List', + Format => 'string[4,68]', + }, + 5 => { + Name => 'ObjectName', + Format => 'string[0,64]', + }, + 7 => { + Name => 'EditStatus', + Format => 'string[0,64]', + }, + 8 => { + Name => 'EditorialUpdate', + Format => 'digits[2]', + PrintConv => { + '01' => 'Additional language', + }, + }, + 10 => { + Name => 'Urgency', + Format => 'digits[1]', + PrintConv => { + 0 => '0 (reserved)', + 1 => '1 (most urgent)', + 2 => 2, + 3 => 3, + 4 => 4, + 5 => '5 (normal urgency)', + 6 => 6, + 7 => 7, + 8 => '8 (least urgent)', + 9 => '9 (user-defined priority)', + }, + }, + 12 => { + Name => 'SubjectReference', + Flags => 'List', + Format => 'string[13,236]', + }, + 15 => { + Name => 'Category', + Format => 'string[0,3]', + }, + 20 => { + Name => 'SupplementalCategories', + Flags => 'List', + Format => 'string[0,32]', + }, + 22 => { + Name => 'FixtureIdentifier', + Format => 'string[0,32]', + }, + 25 => { + Name => 'Keywords', + Flags => 'List', + Format => 'string[0,64]', + }, + 26 => { + Name => 'ContentLocationCode', + Flags => 'List', + Groups => { 2 => 'Location' }, + Format => 'string[3]', + }, + 27 => { + Name => 'ContentLocationName', + Flags => 'List', + Groups => { 2 => 'Location' }, + Format => 'string[0,64]', + }, + 30 => { + Name => 'ReleaseDate', + Groups => { 2 => 'Time' }, + Format => 'digits[8]', + Shift => 'Time', + ValueConv => 'Image::ExifTool::Exif::ExifDate($val)', + ValueConvInv => 'Image::ExifTool::IPTC::IptcDate($val)', + PrintConvInv => 'Image::ExifTool::IPTC::InverseDateOrTime($self,$val)', + }, + 35 => { + Name => 'ReleaseTime', + Groups => { 2 => 'Time' }, + Format => 'string[11]', + Shift => 'Time', + ValueConv => 'Image::ExifTool::Exif::ExifTime($val)', + ValueConvInv => 'Image::ExifTool::IPTC::IptcTime($val)', + PrintConvInv => 'Image::ExifTool::IPTC::InverseDateOrTime($self,$val)', + }, + 37 => { + Name => 'ExpirationDate', + Groups => { 2 => 'Time' }, + Format => 'digits[8]', + Shift => 'Time', + ValueConv => 'Image::ExifTool::Exif::ExifDate($val)', + ValueConvInv => 'Image::ExifTool::IPTC::IptcDate($val)', + PrintConvInv => 'Image::ExifTool::IPTC::InverseDateOrTime($self,$val)', + }, + 38 => { + Name => 'ExpirationTime', + Groups => { 2 => 'Time' }, + Format => 'string[11]', + Shift => 'Time', + ValueConv => 'Image::ExifTool::Exif::ExifTime($val)', + ValueConvInv => 'Image::ExifTool::IPTC::IptcTime($val)', + PrintConvInv => 'Image::ExifTool::IPTC::InverseDateOrTime($self,$val)', + }, + 40 => { + Name => 'SpecialInstructions', + Format => 'string[0,256]', + }, + 42 => { + Name => 'ActionAdvised', + Format => 'digits[2]', + PrintConv => { + '' => '', + '01' => 'Object Kill', + '02' => 'Object Replace', + '03' => 'Object Append', + '04' => 'Object Reference', + }, + }, + 45 => { + Name => 'ReferenceService', + Flags => 'List', + Format => 'string[0,10]', + }, + 47 => { + Name => 'ReferenceDate', + Groups => { 2 => 'Time' }, + Flags => 'List', + Format => 'digits[8]', + Shift => 'Time', + ValueConv => 'Image::ExifTool::Exif::ExifDate($val)', + ValueConvInv => 'Image::ExifTool::IPTC::IptcDate($val)', + PrintConvInv => 'Image::ExifTool::IPTC::InverseDateOrTime($self,$val)', + }, + 50 => { + Name => 'ReferenceNumber', + Flags => 'List', + Format => 'digits[8]', + }, + 55 => { + Name => 'DateCreated', + Groups => { 2 => 'Time' }, + Format => 'digits[8]', + Shift => 'Time', + ValueConv => 'Image::ExifTool::Exif::ExifDate($val)', + ValueConvInv => 'Image::ExifTool::IPTC::IptcDate($val)', + PrintConvInv => 'Image::ExifTool::IPTC::InverseDateOrTime($self,$val)', + }, + 60 => { + Name => 'TimeCreated', + Groups => { 2 => 'Time' }, + Format => 'string[11]', + Shift => 'Time', + ValueConv => 'Image::ExifTool::Exif::ExifTime($val)', + ValueConvInv => 'Image::ExifTool::IPTC::IptcTime($val)', + PrintConvInv => 'Image::ExifTool::IPTC::InverseDateOrTime($self,$val)', + }, + 62 => { + Name => 'DigitalCreationDate', + Groups => { 2 => 'Time' }, + Format => 'digits[8]', + Shift => 'Time', + ValueConv => 'Image::ExifTool::Exif::ExifDate($val)', + ValueConvInv => 'Image::ExifTool::IPTC::IptcDate($val)', + PrintConvInv => 'Image::ExifTool::IPTC::InverseDateOrTime($self,$val)', + }, + 63 => { + Name => 'DigitalCreationTime', + Groups => { 2 => 'Time' }, + Format => 'string[11]', + Shift => 'Time', + ValueConv => 'Image::ExifTool::Exif::ExifTime($val)', + ValueConvInv => 'Image::ExifTool::IPTC::IptcTime($val)', + PrintConvInv => 'Image::ExifTool::IPTC::InverseDateOrTime($self,$val)', + }, + 65 => { + Name => 'OriginatingProgram', + Format => 'string[0,32]', + }, + 70 => { + Name => 'ProgramVersion', + Format => 'string[0,10]', + }, + 75 => { + Name => 'ObjectCycle', + Format => 'string[1]', + PrintConv => { + 'a' => 'Morning', + 'p' => 'Evening', + 'b' => 'Both Morning and Evening', + }, + }, + 80 => { + Name => 'By-line', + Flags => 'List', + Format => 'string[0,32]', + Groups => { 2 => 'Author' }, + }, + 85 => { + Name => 'By-lineTitle', + Flags => 'List', + Format => 'string[0,32]', + Groups => { 2 => 'Author' }, + }, + 90 => { + Name => 'City', + Format => 'string[0,32]', + Groups => { 2 => 'Location' }, + }, + 92 => { + Name => 'Sub-location', + Format => 'string[0,32]', + Groups => { 2 => 'Location' }, + }, + 95 => { + Name => 'Province-State', + Format => 'string[0,32]', + Groups => { 2 => 'Location' }, + }, + 100 => { + Name => 'Country-PrimaryLocationCode', + Format => 'string[3]', + Groups => { 2 => 'Location' }, + }, + 101 => { + Name => 'Country-PrimaryLocationName', + Format => 'string[0,64]', + Groups => { 2 => 'Location' }, + }, + 103 => { + Name => 'OriginalTransmissionReference', + Format => 'string[0,32]', + }, + 105 => { + Name => 'Headline', + Format => 'string[0,256]', + }, + 110 => { + Name => 'Credit', + Groups => { 2 => 'Author' }, + Format => 'string[0,32]', + }, + 115 => { + Name => 'Source', + Groups => { 2 => 'Author' }, + Format => 'string[0,32]', + }, + 116 => { + Name => 'CopyrightNotice', + Groups => { 2 => 'Author' }, + Format => 'string[0,128]', + }, + 118 => { + Name => 'Contact', + Flags => 'List', + Groups => { 2 => 'Author' }, + Format => 'string[0,128]', + }, + 120 => { + Name => 'Caption-Abstract', + Format => 'string[0,2000]', + }, + 121 => { + Name => 'LocalCaption', + Format => 'string[0,256]', # (guess) + Notes => q{ + I haven't found a reference for the format of tags 121, 184-188 and + 225-232, so I have just make them writable as strings with + reasonable length. Beware that if this is wrong, other utilities + may not be able to read these tags as written by ExifTool + }, + }, + 122 => { + Name => 'Writer-Editor', + Flags => 'List', + Groups => { 2 => 'Author' }, + Format => 'string[0,32]', + }, + 125 => { + Name => 'RasterizedCaption', + Format => 'undef[7360]', + Binary => 1, + }, + 130 => { + Name => 'ImageType', + Groups => { 2 => 'Image' }, + Format => 'string[2]', + }, + 131 => { + Name => 'ImageOrientation', + Groups => { 2 => 'Image' }, + Format => 'string[1]', + PrintConv => { + P => 'Portrait', + L => 'Landscape', + S => 'Square', + }, + }, + 135 => { + Name => 'LanguageIdentifier', + Format => 'string[2,3]', + }, + 150 => { + Name => 'AudioType', + Format => 'string[2]', + PrintConv => { + '1A' => 'Mono Actuality', + '2A' => 'Stereo Actuality', + '1C' => 'Mono Question and Answer Session', + '2C' => 'Stereo Question and Answer Session', + '1M' => 'Mono Music', + '2M' => 'Stereo Music', + '1Q' => 'Mono Response to a Question', + '2Q' => 'Stereo Response to a Question', + '1R' => 'Mono Raw Sound', + '2R' => 'Stereo Raw Sound', + '1S' => 'Mono Scener', + '2S' => 'Stereo Scener', + '0T' => 'Text Only', + '1V' => 'Mono Voicer', + '2V' => 'Stereo Voicer', + '1W' => 'Mono Wrap', + '2W' => 'Stereo Wrap', + }, + }, + 151 => { + Name => 'AudioSamplingRate', + Format => 'digits[6]', + }, + 152 => { + Name => 'AudioSamplingResolution', + Format => 'digits[2]', + }, + 153 => { + Name => 'AudioDuration', + Format => 'digits[6]', + }, + 154 => { + Name => 'AudioOutcue', + Format => 'string[0,64]', + }, + 184 => { + Name => 'JobID', + Format => 'string[0,64]', # (guess) + }, + 185 => { + Name => 'MasterDocumentID', + Format => 'string[0,256]', # (guess) + }, + 186 => { + Name => 'ShortDocumentID', + Format => 'string[0,64]', # (guess) + }, + 187 => { + Name => 'UniqueDocumentID', + Format => 'string[0,128]', # (guess) + }, + 188 => { + Name => 'OwnerID', + Format => 'string[0,128]', # (guess) + }, + 200 => { + Name => 'ObjectPreviewFileFormat', + Groups => { 2 => 'Image' }, + Format => 'int16u', + PrintConv => \%fileFormat, + }, + 201 => { + Name => 'ObjectPreviewFileVersion', + Groups => { 2 => 'Image' }, + Format => 'int16u', + }, + 202 => { + Name => 'ObjectPreviewData', + Groups => { 2 => 'Preview' }, + Format => 'undef[0,256000]', + Binary => 1, + }, + 221 => { + Name => 'Prefs', + Groups => { 2 => 'Image' }, + Format => 'string[0,64]', + Notes => 'PhotoMechanic preferences', + PrintConv => q{ + $val =~ s[\s*(\d+):\s*(\d+):\s*(\d+):\s*(\S*)] + [Tagged:$1, ColorClass:$2, Rating:$3, FrameNum:$4]; + return $val; + }, + PrintConvInv => q{ + $val =~ s[Tagged:\s*(\d+).*ColorClass:\s*(\d+).*Rating:\s*(\d+).*FrameNum:\s*(\S*)] + [$1:$2:$3:$4]is; + return $val; + }, + }, + 225 => { + Name => 'ClassifyState', + Format => 'string[0,64]', # (guess) + }, + 228 => { + Name => 'SimilarityIndex', + Format => 'string[0,32]', # (guess) + }, + 230 => { + Name => 'DocumentNotes', + Format => 'string[0,1024]', # (guess) + }, + 231 => { + Name => 'DocumentHistory', + Format => 'string[0,256]', # (guess) + ValueConv => '$val =~ s/\0+/\n/g; $val', # (have seen embedded nulls) + ValueConvInv => '$val', + }, + 232 => { + Name => 'ExifCameraInfo', + Format => 'string[0,4096]', # (guess) + }, + 255 => { #PH + Name => 'CatalogSets', + List => 1, + Format => 'string[0,256]', # (guess) + Notes => 'written by iView MediaPro', + }, +); + +# Record 3 -- News photo +%Image::ExifTool::IPTC::NewsPhoto = ( + GROUPS => { 2 => 'Image' }, + WRITE_PROC => \&WriteIPTC, + CHECK_PROC => \&CheckIPTC, + WRITABLE => 1, + 0 => { + Name => 'NewsPhotoVersion', + Format => 'int16u', + Mandatory => 1, + }, + 10 => { + Name => 'IPTCPictureNumber', + Format => 'string[16]', + Notes => '4 numbers: 1-Manufacturer ID, 2-Equipment ID, 3-Date, 4-Sequence', + PrintConv => 'Image::ExifTool::IPTC::ConvertPictureNumber($val)', + PrintConvInv => 'Image::ExifTool::IPTC::InvConvertPictureNumber($val)', + }, + 20 => { + Name => 'IPTCImageWidth', + Format => 'int16u', + }, + 30 => { + Name => 'IPTCImageHeight', + Format => 'int16u', + }, + 40 => { + Name => 'IPTCPixelWidth', + Format => 'int16u', + }, + 50 => { + Name => 'IPTCPixelHeight', + Format => 'int16u', + }, + 55 => { + Name => 'SupplementalType', + Format => 'int8u', + PrintConv => { + 0 => 'Main Image', + 1 => 'Reduced Resolution Image', + 2 => 'Logo', + 3 => 'Rasterized Caption', + }, + }, + 60 => { + Name => 'ColorRepresentation', + Format => 'int16u', + PrintHex => 1, + PrintConv => { + 0x000 => 'No Image, Single Frame', + 0x100 => 'Monochrome, Single Frame', + 0x300 => '3 Components, Single Frame', + 0x301 => '3 Components, Frame Sequential in Multiple Objects', + 0x302 => '3 Components, Frame Sequential in One Object', + 0x303 => '3 Components, Line Sequential', + 0x304 => '3 Components, Pixel Sequential', + 0x305 => '3 Components, Special Interleaving', + 0x400 => '4 Components, Single Frame', + 0x401 => '4 Components, Frame Sequential in Multiple Objects', + 0x402 => '4 Components, Frame Sequential in One Object', + 0x403 => '4 Components, Line Sequential', + 0x404 => '4 Components, Pixel Sequential', + 0x405 => '4 Components, Special Interleaving', + }, + }, + 64 => { + Name => 'InterchangeColorSpace', + Format => 'int8u', + PrintConv => { + 1 => 'X,Y,Z CIE', + 2 => 'RGB SMPTE', + 3 => 'Y,U,V (K) (D65)', + 4 => 'RGB Device Dependent', + 5 => 'CMY (K) Device Dependent', + 6 => 'Lab (K) CIE', + 7 => 'YCbCr', + 8 => 'sRGB', + }, + }, + 65 => { + Name => 'ColorSequence', + Format => 'int8u', + }, + 66 => { + Name => 'ICC_Profile', + # ...could add SubDirectory support to read into this (if anybody cares) + Writable => 0, + Binary => 1, + }, + 70 => { + Name => 'ColorCalibrationMatrix', + Writable => 0, + Binary => 1, + }, + 80 => { + Name => 'LookupTable', + Writable => 0, + Binary => 1, + }, + 84 => { + Name => 'NumIndexEntries', + Format => 'int16u', + }, + 85 => { + Name => 'ColorPalette', + Writable => 0, + Binary => 1, + }, + 86 => { + Name => 'IPTCBitsPerSample', + Format => 'int8u', + }, + 90 => { + Name => 'SampleStructure', + Format => 'int8u', + PrintConv => { + 0 => 'OrthogonalConstangSampling', + 1 => 'Orthogonal4-2-2Sampling', + 2 => 'CompressionDependent', + }, + }, + 100 => { + Name => 'ScanningDirection', + Format => 'int8u', + PrintConv => { + 0 => 'L-R, Top-Bottom', + 1 => 'R-L, Top-Bottom', + 2 => 'L-R, Bottom-Top', + 3 => 'R-L, Bottom-Top', + 4 => 'Top-Bottom, L-R', + 5 => 'Bottom-Top, L-R', + 6 => 'Top-Bottom, R-L', + 7 => 'Bottom-Top, R-L', + }, + }, + 102 => { + Name => 'IPTCImageRotation', + Format => 'int8u', + PrintConv => { + 0 => 0, + 1 => 90, + 2 => 180, + 3 => 270, + }, + }, + 110 => { + Name => 'DataCompressionMethod', + Format => 'int32u', + }, + 120 => { + Name => 'QuantizationMethod', + Format => 'int8u', + PrintConv => { + 0 => 'Linear Reflectance/Transmittance', + 1 => 'Linear Density', + 2 => 'IPTC Ref B', + 3 => 'Linear Dot Percent', + 4 => 'AP Domestic Analogue', + 5 => 'Compression Method Specific', + 6 => 'Color Space Specific', + 7 => 'Gamma Compensated', + }, + }, + 125 => { + Name => 'EndPoints', + Writable => 0, + Binary => 1, + }, + 130 => { + Name => 'ExcursionTolerance', + Format => 'int8u', + PrintConv => { + 0 => 'Not Allowed', + 1 => 'Allowed', + }, + }, + 135 => { + Name => 'BitsPerComponent', + Format => 'int8u', + }, + 140 => { + Name => 'MaximumDensityRange', + Format => 'int16u', + }, + 145 => { + Name => 'GammaCompensatedValue', + Format => 'int16u', + }, +); + +# Record 7 -- Pre-object Data +%Image::ExifTool::IPTC::PreObjectData = ( + # (not actually writable, but used in BuildTagLookup to recognize IPTC tables) + WRITE_PROC => \&WriteIPTC, + 10 => { + Name => 'SizeMode', + Format => 'int8u', + PrintConv => { + 0 => 'Size Not Known', + 1 => 'Size Known', + }, + }, + 20 => { + Name => 'MaxSubfileSize', + Format => 'int32u', + }, + 90 => { + Name => 'ObjectSizeAnnounced', + Format => 'int32u', + }, + 95 => { + Name => 'MaximumObjectSize', + Format => 'int32u', + }, +); + +# Record 8 -- ObjectData +%Image::ExifTool::IPTC::ObjectData = ( + WRITE_PROC => \&WriteIPTC, + 10 => { + Name => 'SubFile', + Flags => 'List', + Binary => 1, + }, +); + +# Record 9 -- PostObjectData +%Image::ExifTool::IPTC::PostObjectData = ( + WRITE_PROC => \&WriteIPTC, + 10 => { + Name => 'ConfirmedObjectSize', + Format => 'int32u', + }, +); + +# Record 240 -- FotoStation proprietary data (ref PH) +%Image::ExifTool::IPTC::FotoStation = ( + GROUPS => { 2 => 'Other' }, + WRITE_PROC => \&WriteIPTC, + CHECK_PROC => \&CheckIPTC, + WRITABLE => 1, +); + +# IPTC Composite tags +%Image::ExifTool::IPTC::Composite = ( + GROUPS => { 2 => 'Image' }, + DateTimeCreated => { + Description => 'Date/Time Created', + Groups => { 2 => 'Time' }, + Require => { + 0 => 'IPTC:DateCreated', + 1 => 'IPTC:TimeCreated', + }, + ValueConv => '"$val[0] $val[1]"', + PrintConv => '$self->ConvertDateTime($val)', + }, + DigitalCreationDateTime => { + Description => 'Digital Creation Date/Time', + Groups => { 2 => 'Time' }, + Require => { + 0 => 'IPTC:DigitalCreationDate', + 1 => 'IPTC:DigitalCreationTime', + }, + ValueConv => '"$val[0] $val[1]"', + PrintConv => '$self->ConvertDateTime($val)', + }, +); + +# add our composite tags +Image::ExifTool::AddCompositeTags('Image::ExifTool::IPTC'); + + +#------------------------------------------------------------------------------ +# AutoLoad our writer routines when necessary +# +sub AUTOLOAD +{ + return Image::ExifTool::DoAutoLoad($AUTOLOAD, @_); +} + +#------------------------------------------------------------------------------ +# Print conversion for CodedCharacterSet +# Inputs: 0) value +sub PrintCodedCharset($) +{ + my $val = shift; + return $iptcCharset{$val} if $iptcCharset{$val}; + $val =~ s/(.)/ $1/g; + $val =~ s/ \x1b/, ESC/g; + $val =~ s/^,? //; + return $val; +} + +#------------------------------------------------------------------------------ +# Handle CodedCharacterSet +# Inputs: 0) ExifTool ref, 1) CodedCharacterSet value +# Returns: IPTC character set if translation required (or 'bad' if unknown) +sub HandleCodedCharset($$) +{ + my ($et, $val) = @_; + my $xlat = $iptcCharset{$val}; + unless ($xlat) { + if ($val =~ /^\x1b\x25/) { + # some unknown character set invoked + $xlat = 'bad'; # flag unsupported coding + } else { + $xlat = $et->Options('CharsetIPTC'); + } + } + # no need to translate if Charset is the same + undef $xlat if $xlat eq $et->Options('Charset'); + return $xlat; +} + +#------------------------------------------------------------------------------ +# Encode or decode coded string +# Inputs: 0) ExifTool ref, 1) value ptr, 2) IPTC charset (or 'bad') ref +# 3) flag set to decode (read) value from IPTC +# Updates value on return +sub TranslateCodedString($$$$) +{ + my ($et, $valPtr, $xlatPtr, $read) = @_; + if ($$xlatPtr eq 'bad') { + $et->Warn('Some IPTC characters not converted (unsupported CodedCharacterSet)'); + undef $$xlatPtr; + } elsif (not $read) { + $$valPtr = $et->Decode($$valPtr, undef, undef, $$xlatPtr); + } elsif ($$valPtr !~ /[\x14\x15\x1b]/) { + $$valPtr = $et->Decode($$valPtr, $$xlatPtr); + } else { + # don't yet support reading ISO 2022 shifted character sets + $et->WarnOnce('Some IPTC characters not converted (ISO 2022 shifting not supported)'); + } +} + +#------------------------------------------------------------------------------ +# Is this IPTC in a standard location? +# Inputs: 0) Current metadata path string +# Returns: true if path is standard, 0 if file type doesn't have standard IPTC, +# or undef if IPTC is non-standard +sub IsStandardIPTC($) +{ + my $path = shift; + return 1 if $isStandardIPTC{$path}; + return 0 unless $path =~ /^(\w+)/ and defined $isStandardIPTC{$1}; + return undef; # non-standard +} + +#------------------------------------------------------------------------------ +# get IPTC info +# Inputs: 0) ExifTool object reference, 1) dirInfo reference +# 2) reference to tag table +# Returns: 1 on success, 0 otherwise +sub ProcessIPTC($$$) +{ + my ($et, $dirInfo, $tagTablePtr) = @_; + my $dataPt = $$dirInfo{DataPt}; + my $pos = $$dirInfo{DirStart} || 0; + my $dirLen = $$dirInfo{DirLen} || 0; + my $dirEnd = $pos + $dirLen; + my $verbose = $et->Options('Verbose'); + my $success = 0; + my ($lastRec, $recordPtr, $recordName); + + $verbose and $dirInfo and $et->VerboseDir('IPTC', 0, $$dirInfo{DirLen}); + + if ($tagTablePtr eq \%Image::ExifTool::IPTC::Main) { + my $path = $et->MetadataPath(); + my $isStd = IsStandardIPTC($path); + if (defined $isStd and not $$et{DIR_COUNT}{STD_IPTC}) { + # set flag to ensure we only have one family 1 "IPTC" group + $$et{DIR_COUNT}{STD_IPTC} = 1; + # calculate MD5 if Digest::MD5 is available (truly standard IPTC only) + if ($isStd) { + my $md5; + if (eval { require Digest::MD5 }) { + if ($pos or $dirLen != length($$dataPt)) { + $md5 = Digest::MD5::md5(substr $$dataPt, $pos, $dirLen); + } else { + $md5 = Digest::MD5::md5($$dataPt); + } + } else { + # a zero digest indicates IPTC exists but we don't have Digest::MD5 + $md5 = "\0" x 16; + } + $et->FoundTag('CurrentIPTCDigest', $md5); + } + } else { + if (($Image::ExifTool::MWG::strict or $et->Options('Validate')) and + $$et{FILE_TYPE} =~ /^(JPEG|TIFF|PSD)$/) + { + if ($Image::ExifTool::MWG::strict) { + # ignore non-standard IPTC while in strict MWG compatibility mode + $et->Warn("Ignored non-standard IPTC at $path"); + return 1; + } else { + $et->Warn("Non-standard IPTC at $path", 1); + } + } + # extract non-standard IPTC + my $count = ($$et{DIR_COUNT}{IPTC} || 0) + 1; # count non-standard IPTC + $$et{DIR_COUNT}{IPTC} = $count; + $$et{LOW_PRIORITY_DIR}{IPTC} = 1; # lower priority of non-standard IPTC + $$et{SET_GROUP1} = '+' . ($count + 1); # add number to family 1 group name + } + } + # begin by assuming default IPTC encoding + my $xlat = $et->Options('CharsetIPTC'); + undef $xlat if $xlat eq $et->Options('Charset'); + + # quick check for improperly byte-swapped IPTC + if ($dirLen >= 4 and substr($$dataPt, $pos, 1) ne "\x1c" and + substr($$dataPt, $pos + 3, 1) eq "\x1c") + { + $et->Warn('IPTC data was improperly byte-swapped'); + my $newData = pack('N*', unpack('V*', substr($$dataPt, $pos, $dirLen) . "\0\0\0")); + $dataPt = \$newData; + $pos = 0; + $dirEnd = $pos + $dirLen; + # NOTE: MUST NOT access $dirInfo DataPt, DirStart or DataLen after this! + } + # extract IPTC as a block if specified + if ($$et{REQ_TAG_LOOKUP}{iptc} or ($$et{TAGS_FROM_FILE} and + not $$et{EXCL_TAG_LOOKUP}{iptc})) + { + if ($pos or $dirLen != length($$dataPt)) { + $et->FoundTag('IPTC', substr($$dataPt, $pos, $dirLen)); + } else { + $et->FoundTag('IPTC', $$dataPt); + } + } + while ($pos + 5 <= $dirEnd) { + my $buff = substr($$dataPt, $pos, 5); + my ($id, $rec, $tag, $len) = unpack("CCCn", $buff); + unless ($id == 0x1c) { + unless ($id) { + # scan the rest of the data an give warning unless all zeros + # (iMatch pads the IPTC block with nulls for some reason) + my $remaining = substr($$dataPt, $pos, $dirEnd - $pos); + last unless $remaining =~ /[^\0]/; + } + $et->Warn(sprintf('Bad IPTC data tag (marker 0x%x)',$id)); + last; + } + $pos += 5; # step to after field header + # handle extended IPTC entry if necessary + if ($len & 0x8000) { + my $n = $len & 0x7fff; # get num bytes in length field + if ($pos + $n > $dirEnd or $n > 8) { + $et->VPrint(0, "Invalid extended IPTC entry (dataset $rec:$tag, len $len)\n"); + $success = 0; + last; + } + # determine length (a big-endian, variable sized int) + for ($len = 0; $n; ++$pos, --$n) { + $len = $len * 256 + ord(substr($$dataPt, $pos, 1)); + } + } + if ($pos + $len > $dirEnd) { + $et->VPrint(0, "Invalid IPTC entry (dataset $rec:$tag, len $len)\n"); + $success = 0; + last; + } + if (not defined $lastRec or $lastRec != $rec) { + my $tableInfo = $tagTablePtr->{$rec}; + unless ($tableInfo) { + $et->WarnOnce("Unrecognized IPTC record $rec (ignored)"); + $pos += $len; + next; # ignore this entry + } + my $tableName = $tableInfo->{SubDirectory}->{TagTable}; + unless ($tableName) { + $et->Warn("No table for IPTC record $rec!"); + last; # this shouldn't happen + } + $recordName = $$tableInfo{Name}; + $recordPtr = Image::ExifTool::GetTagTable($tableName); + $et->VPrint(0,$$et{INDENT},"-- $recordName record --\n"); + $lastRec = $rec; + } + my $val = substr($$dataPt, $pos, $len); + + # add tagInfo for all unknown tags: + unless ($$recordPtr{$tag}) { + # - no Format so format is auto-detected + # - no Name so name is generated automatically with decimal tag number + AddTagToTable($recordPtr, $tag, { Unknown => 1 }); + } + + my $tagInfo = $et->GetTagInfo($recordPtr, $tag); + my $format; + # (could use $$recordPtr{FORMAT} if no Format below, but don't do this to + # be backward compatible with improperly written PhotoMechanic tags) + $format = $$tagInfo{Format} if $tagInfo; + # use logic to determine format if not specified + unless ($format) { + $format = 'int' if $len <= 4 and $len != 3 and $val =~ /[\0-\x08]/; + } + if ($format) { + if ($format =~ /^int/) { + if ($len <= 8) { # limit integer conversion to 8 bytes long + $val = 0; + my $i; + for ($i=0; $i<$len; ++$i) { + $val = $val * 256 + ord(substr($$dataPt, $pos+$i, 1)); + } + } + } elsif ($format =~ /^string/) { + $val =~ s/\0+$//; # some braindead softwares add null terminators + if ($rec == 1) { + # handle CodedCharacterSet tag + $xlat = HandleCodedCharset($et, $val) if $tag == 90; + # translate characters if necessary and special characters exist + } elsif ($xlat and $rec < 7 and $val =~ /[\x80-\xff]/) { + # translate to specified character set + TranslateCodedString($et, \$val, \$xlat, 1); + } + } elsif ($format =~ /^digits/) { + $val =~ s/\0+$//; + } elsif ($format !~ /^undef/) { + warn("Invalid IPTC format: $format"); + } + } + $verbose and $et->VerboseInfo($tag, $tagInfo, + Table => $tagTablePtr, + Value => $val, + DataPt => $dataPt, + DataPos => $$dirInfo{DataPos}, + Size => $len, + Start => $pos, + Extra => ", $recordName record", + Format => $format, + ); + $et->FoundTag($tagInfo, $val) if $tagInfo; + $success = 1; + + $pos += $len; # increment to next field + } + delete $$et{SET_GROUP1}; + delete $$et{LOW_PRIORITY_DIR}{IPTC}; + return $success; +} + +1; # end + + +__END__ + +=head1 NAME + +Image::ExifTool::IPTC - Read IPTC meta information + +=head1 SYNOPSIS + +This module is loaded automatically by Image::ExifTool when required. + +=head1 DESCRIPTION + +This module contains definitions required by Image::ExifTool to interpret +IPTC (International Press Telecommunications Council) meta information in +image files. + +=head1 AUTHOR + +Copyright 2003-2019, Phil Harvey (phil at owl.phy.queensu.ca) + +This library is free software; you can redistribute it and/or modify it +under the same terms as Perl itself. + +=head1 REFERENCES + +=over 4 + +=item L<http://www.iptc.org/IIM/> + +=back + +=head1 SEE ALSO + +L<Image::ExifTool::TagNames/IPTC Tags>, +L<Image::ExifTool(3pm)|Image::ExifTool> + +=cut diff --git a/lib/Image/ExifTool/ISO.pm b/lib/Image/ExifTool/ISO.pm new file mode 100644 index 0000000..ef04082 --- /dev/null +++ b/lib/Image/ExifTool/ISO.pm @@ -0,0 +1,206 @@ +#------------------------------------------------------------------------------ +# File: ISO.pm +# +# Description: Read information from ISO 9660 disk images +# +# Revisions: 2016-04-07 - P. Harvey created +# +# References: 1) http://wiki.osdev.org/ISO_9660 +#------------------------------------------------------------------------------ + +package Image::ExifTool::ISO; + +use strict; +use vars qw($VERSION); +use Image::ExifTool qw(:DataAccess :Utils); + +$VERSION = '1.01'; + +# trim trailing spaces and ignore tag if empty +my %rawStr = ( + RawConv => sub { + my $val = shift; + $val =~ s/ +$//; + return length($val) ? $val : undef; + }, +); + +# tag info for date/time tags +my %dateInfo = ( + Format => 'undef[17]', + Groups => { 2 => 'Time' }, + ValueConv => q{ + return undef if $val !~ /[^0\0 ]/; # ignore if empty + if ($val =~ s/(\d{4})(\d{2})(\d{2})(\d{2})(\d{2})(\d{2})(\d{2})(.)/$1:$2:$3 $4:$5:$6.$7/s) { + $val .= TimeZoneString(unpack('c', $8) * 15); + } + return $val; + }, + PrintConv => '$self->ConvertDateTime($val)', +); + +# lookup for volume descriptor types +my %volumeDescriptorType = ( + 0 => 'Boot Record', + 1 => 'Primary Volume', + 2 => 'Supplementary Volume', + 3 => 'Volume Partition', + 255 => 'Terminator', +); + +# ISO tags +%Image::ExifTool::ISO::Main = ( + GROUPS => { 2 => 'Other' }, + NOTES => 'Tags extracted from ISO 9660 disk images.', + 0 => { + Name => 'BootRecord', + SubDirectory => { TagTable => 'Image::ExifTool::ISO::BootRecord' }, + }, + 1 => { + Name => 'PrimaryVolume', + SubDirectory => { TagTable => 'Image::ExifTool::ISO::PrimaryVolume' }, + }, +); + +%Image::ExifTool::ISO::BootRecord = ( + GROUPS => { 2 => 'Other' }, + PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData, + # 0 => { Name => 'VolumeType', PrintConv => \%volumeDescriptorType }, # (0 for boot record) + # 1 => { Name => 'Identifier', Format => 'undef[5]' }, # (always "CD001") + # 6 => 'VolumeDesriptorVersion', # (always 1) + # always extract BootSystem, even if empty, as an indication that this is bootable + 7 => { Name => 'BootSystem', Format => 'string[32]', ValueConv => '$val=~s/ +$//; $val' }, + 39 => { Name => 'BootIdentifier', Format => 'string[32]', %rawStr }, +); + +%Image::ExifTool::ISO::PrimaryVolume = ( + GROUPS => { 2 => 'Other' }, + PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData, + # 0 => { Name => 'VolumeType', PrintConv => \%volumeDescriptorType }, # (1 for primary volume) + # 1 => { Name => 'Identifier', Format => 'undef[5]' }, # (always "CD001") + # 6 => 'VolumeDesriptorVersion', # (always 1) + 8 => { Name => 'System', Format => 'string[32]', %rawStr }, + 40 => { Name => 'VolumeName', Format => 'string[32]', %rawStr }, + 80 => { Name => 'VolumeBlockCount', Format => 'int32u' }, + 120 => { Name => 'VolumeSetDiskCount', Format => 'int16u', Unknown => 1 }, + 124 => { Name => 'VolumeSetDiskNumber', Format => 'int16u', Unknown => 1 }, + 128 => { Name => 'VolumeBlockSize', Format => 'int16u' }, + 132 => { Name => 'PathTableSize', Format => 'int32u', Unknown => 1 }, + 140 => { Name => 'PathTableLocation', Format => 'int32u', Unknown => 1 }, + 174 => { + Name => 'RootDirectoryCreateDate', + Format => 'undef[7]', + Groups => { 2 => 'Time' }, + ValueConv => q{ + my @a = unpack('C6c', $val); + $a[0] += 1900; + $a[6] = TimeZoneString($a[6] * 15); + return sprintf('%.4d:%.2d:%.2d %.2d:%.2d:%.2d%s', @a); + }, + PrintConv => '$self->ConvertDateTime($val)', + }, + 190 => { Name => 'VolumeSetName', Format => 'string[128]', %rawStr }, + 318 => { Name => 'Publisher', Format => 'string[128]', %rawStr }, + 446 => { Name => 'DataPreparer', Format => 'string[128]', %rawStr }, + 574 => { Name => 'Software', Format => 'string[128]', %rawStr }, + 702 => { Name => 'CopyrightFileName', Format => 'string[38]', %rawStr }, + 740 => { Name => 'AbstractFileName', Format => 'string[36]', %rawStr }, + 776 => { Name => 'BibligraphicFileName',Format => 'string[37]', %rawStr }, + 813 => { Name => 'VolumeCreateDate', %dateInfo }, + 830 => { Name => 'VolumeModifyDate', %dateInfo }, + 847 => { Name => 'VolumeExpirationDate',%dateInfo }, + 864 => { Name => 'VolumeEffectiveDate', %dateInfo }, + #881 => 'FileStructureVersion', # (always 1) +); + +# ISO Composite tags +%Image::ExifTool::ISO::Composite = ( + GROUPS => { 2 => 'Other' }, + VolumeSize => { + Require => { + 0 => 'ISO:VolumeBlockCount', + 1 => 'ISO:VolumeBlockSize', + }, + ValueConv => '$val[0] * $val[1]', + PrintConv => \&Image::ExifTool::ConvertFileSize, + }, +); + +# add our composite tags +Image::ExifTool::AddCompositeTags('Image::ExifTool::ISO'); + +#------------------------------------------------------------------------------ +# Extract information from an ISO 9660 disk image +# Inputs: 0) ExifTool object reference, 1) dirInfo reference +# Returns: 1 on success, 0 if this wasn't a valid ISO 9660 image +sub ProcessISO($$) +{ + my ($et, $dirInfo) = @_; + my $raf = $$dirInfo{RAF}; + my ($buff, $tagTablePtr); + + # verify this is a valid ISO file + return 0 unless $raf->Seek(32768, 0); + + while ($raf->Read($buff, 2048) == 2048) { + last unless $buff =~ /^[\0-\x03\xff]CD001/; + unless ($tagTablePtr) { + $et->SetFileType(); # set the FileType tag + SetByteOrder('II'); # read little-endian values only + $tagTablePtr = GetTagTable('Image::ExifTool::ISO::Main'); + } + my $type = unpack('C', $buff); + $et->VPrint(0, "Volume descriptor type $type ($volumeDescriptorType{$type})\n"); + last if $type == 255; # stop at terminator + next unless $$tagTablePtr{$type}; + my $subTablePtr = GetTagTable($$tagTablePtr{$type}{SubDirectory}{TagTable}); + my %dirInfo = ( + DataPt => \$buff, + DataPos => $raf->Tell() - 2048, + DirStart => 0, + DirLen => length($buff), + ); + $et->ProcessDirectory(\%dirInfo, $subTablePtr); + } + return $tagTablePtr ? 1 : 0; +} + +1; # end + +__END__ + +=head1 NAME + +Image::ExifTool::ISO - Read information from ISO 9660 disk images + +=head1 SYNOPSIS + +This module is used by Image::ExifTool + +=head1 DESCRIPTION + +This module contains definitions required by Image::ExifTool to read +information from ISO 9660 disk images. + +=head1 AUTHOR + +Copyright 2003-2019, Phil Harvey (phil at owl.phy.queensu.ca) + +This library is free software; you can redistribute it and/or modify it +under the same terms as Perl itself. + +=head1 REFERENCES + +=over 4 + +=item L<http://wiki.osdev.org/ISO_9660> + +=back + +=head1 SEE ALSO + +L<Image::ExifTool::TagNames/ISO Tags>, +L<Image::ExifTool(3pm)|Image::ExifTool> + +=cut + diff --git a/lib/Image/ExifTool/ITC.pm b/lib/Image/ExifTool/ITC.pm new file mode 100644 index 0000000..ea830f2 --- /dev/null +++ b/lib/Image/ExifTool/ITC.pm @@ -0,0 +1,215 @@ +#------------------------------------------------------------------------------ +# File: ITC.pm +# +# Description: Read iTunes Cover Flow meta information +# +# Revisions: 01/12/2008 - P. Harvey Created +# +# References: 1) http://www.waldoland.com/dev/Articles/ITCFileFormat.aspx +# 2) http://www.falsecognate.org/2007/01/deciphering_the_itunes_itc_fil/ +#------------------------------------------------------------------------------ + +package Image::ExifTool::ITC; + +use strict; +use vars qw($VERSION); +use Image::ExifTool qw(:DataAccess :Utils); + +$VERSION = '1.02'; + +sub ProcessITC($$); + +# tags used in ITC files +%Image::ExifTool::ITC::Main = ( + NOTES => 'This information is found in iTunes Cover Flow data files.', + itch => { SubDirectory => { TagTable => 'Image::ExifTool::ITC::Header' } }, + item => { SubDirectory => { TagTable => 'Image::ExifTool::ITC::Item' } }, + data => { + Name => 'ImageData', + Notes => 'embedded JPEG or PNG image, depending on ImageType', + }, +); + +# ITC header information +%Image::ExifTool::ITC::Header = ( + PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData, + GROUPS => { 2 => 'Image' }, + 0x10 => { + Name => 'DataType', + Format => 'undef[4]', + PrintConv => { artw => 'Artwork' }, + }, +); + +# ITC item information +%Image::ExifTool::ITC::Item = ( + PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData, + GROUPS => { 2 => 'Image' }, + FORMAT => 'int32u', + FIRST_ENTRY => 0, + 0 => { + Name => 'LibraryID', + Format => 'undef[8]', + ValueConv => 'uc unpack "H*", $val', + }, + 2 => { + Name => 'TrackID', + Format => 'undef[8]', + ValueConv => 'uc unpack "H*", $val', + }, + 4 => { + Name => 'DataLocation', + Format => 'undef[4]', + PrintConv => { + down => 'Downloaded Separately', + locl => 'Local Music File', + }, + }, + 5 => { + Name => 'ImageType', + Format => 'undef[4]', + ValueConv => { # (not PrintConv because the unconverted JPEG value is nasty) + 'PNGf' => 'PNG', + "\0\0\0\x0d" => 'JPEG', + }, + }, + 7 => 'ImageWidth', + 8 => 'ImageHeight', +); + +#------------------------------------------------------------------------------ +# Process an iTunes Cover Flow (ITC) file +# Inputs: 0) ExifTool object reference, 1) Directory information reference +# Returns: 1 on success, 0 if this wasn't a valid ITC file +sub ProcessITC($$) +{ + my ($et, $dirInfo) = @_; + my $raf = $$dirInfo{RAF}; + my $rtnVal = 0; + my ($buff, $err, $pos, $tagTablePtr, %dirInfo); + + # loop through all blocks in this image + for (;;) { + # read the block header + my $n = $raf->Read($buff, 8); + unless ($n == 8) { + # no error if we reached the EOF normally + undef $err unless $n; + last; + } + my ($size, $tag) = unpack('Na4', $buff); + if ($rtnVal) { + last unless $size >= 8 and $size < 0x80000000; + } else { + # check to be sure this is a valid ITC image + # (first block must be 'itch') + last unless $tag eq 'itch'; + last unless $size >= 0x1c and $size < 0x10000; + $et->SetFileType(); + SetByteOrder('MM'); + $rtnVal = 1; # this is an ITC file + $err = 1; # format error unless we read to EOF + } + if ($tag eq 'itch') { + $pos = $raf->Tell(); + $size -= 8; # size of remaining data in block + $raf->Read($buff,$size) == $size or last; + # extract header information + %dirInfo = ( + DirName => 'ITC Header', + DataPt => \$buff, + DataPos => $pos, + ); + my $tagTablePtr = GetTagTable('Image::ExifTool::ITC::Header'); + $et->ProcessDirectory(\%dirInfo, $tagTablePtr); + } elsif ($tag eq 'item') { + # don't want to read the entire item data (includes image) + $size > 12 or last; + $raf->Read($buff, 4) == 4 or last; + my $len = unpack('N', $buff); + $len >= 0xd0 and $len <= $size or last; + $size -= $len; # size of data after item header + $len -= 12; # length of remaining item header + # read in 4-byte blocks until we find the null terminator + # (this is just a guess about how to parse this variable-length part) + while ($len >= 4) { + $raf->Read($buff, 4) == 4 or last; + $len -= 4; + last if $buff eq "\0\0\0\0"; + } + last if $len < 4; + $pos = $raf->Tell(); + $raf->Read($buff, $len) == $len or last; + unless ($len >= 0xb4 and substr($buff, 0xb0, 4) eq 'data') { + $et->Warn('Parsing error. Please submit this ITC file for testing'); + last; + } + %dirInfo = ( + DirName => 'ITC Item', + DataPt => \$buff, + DataPos => $pos, + ); + $tagTablePtr = GetTagTable('Image::ExifTool::ITC::Item'); + $et->ProcessDirectory(\%dirInfo, $tagTablePtr); + # extract embedded image + $pos += $len; + if ($size > 0) { + $tagTablePtr = GetTagTable('Image::ExifTool::ITC::Main'); + my $tagInfo = $et->GetTagInfo($tagTablePtr, 'data'); + my $image = $et->ExtractBinary($pos, $size, $$tagInfo{Name}); + $et->FoundTag($tagInfo, \$image); + # skip the rest of the block if necessary + $raf->Seek($pos+$size, 0) or last + } elsif ($size < 0) { + last; + } + } else { + $et->VPrint(0, "Unknown $tag block ($size bytes)\n"); + $raf->Seek($size-8, 1) or last; + } + } + $err and $et->Warn('ITC file format error'); + return $rtnVal; +} + +1; # end + +__END__ + +=head1 NAME + +Image::ExifTool::ITC - Read iTunes Cover Flow meta information + +=head1 SYNOPSIS + +This module is used by Image::ExifTool + +=head1 DESCRIPTION + +This module contains the routines required by Image::ExifTool to read meta +information (including artwork images) from iTunes Cover Flow files. + +=head1 AUTHOR + +Copyright 2003-2019, Phil Harvey (phil at owl.phy.queensu.ca) + +This library is free software; you can redistribute it and/or modify it +under the same terms as Perl itself. + +=head1 REFERENCES + +=over 4 + +=item L<http://www.waldoland.com/dev/Articles/ITCFileFormat.aspx> + +=item L<http://www.falsecognate.org/2007/01/deciphering_the_itunes_itc_fil/> + +=back + +=head1 SEE ALSO + +L<Image::ExifTool::TagNames/ITC Tags>, +L<Image::ExifTool(3pm)|Image::ExifTool> + +=cut + diff --git a/lib/Image/ExifTool/Import.pm b/lib/Image/ExifTool/Import.pm new file mode 100644 index 0000000..ae5fc5c --- /dev/null +++ b/lib/Image/ExifTool/Import.pm @@ -0,0 +1,357 @@ +#------------------------------------------------------------------------------ +# File: Import.pm +# +# Description: Import CSV and JSON database files +# +# Revisions: 2011-03-05 - P. Harvey Created +#------------------------------------------------------------------------------ +package Image::ExifTool::Import; + +use strict; +require Exporter; + +use vars qw($VERSION @ISA @EXPORT_OK); + +$VERSION = '1.09'; +@ISA = qw(Exporter); +@EXPORT_OK = qw(ReadCSV ReadJSON); + +sub ReadJSONObject($;$); + +my %unescapeJSON = ( 't'=>"\t", 'n'=>"\n", 'r'=>"\r" ); +my $charset; + +#------------------------------------------------------------------------------ +# Read CSV file +# Inputs: 0) CSV file name, file ref or RAF ref, 1) database hash ref, 2) missing tag value +# Returns: undef on success, or error string +# Notes: There are various flavours of CSV, but here we assume that only +# double quotes are escaped, and they are escaped by doubling them +sub ReadCSV($$;$) +{ + local ($_, $/); + my ($file, $database, $missingValue) = @_; + my ($buff, @tags, $found, $err, $raf, $openedFile); + + if (UNIVERSAL::isa($file, 'File::RandomAccess')) { + $raf = $file; + $file = 'CSV file'; + } elsif (ref $file eq 'GLOB') { + $raf = new File::RandomAccess($file); + $file = 'CSV file'; + } else { + open CSVFILE, $file or return "Error opening CSV file '${file}'"; + binmode CSVFILE; + $openedFile = 1; + $raf = new File::RandomAccess(\*CSVFILE); + } + # set input record separator by first newline found in the file + # (safe because first line should contain only tag names) + while ($raf->Read($buff, 65536)) { + $buff =~ /(\x0d\x0a|\x0d|\x0a)/ and $/ = $1, last; + } + $raf->Seek(0,0); + while ($raf->ReadLine($buff)) { + my (@vals, $v, $i, %fileInfo); + my @toks = split ',', $buff; + while (@toks) { + ($v = shift @toks) =~ s/^ +//; # remove leading spaces + if ($v =~ s/^"//) { + # quoted value must end in an odd number of quotes + while ($v !~ /("+)\s*$/ or not length($1) & 1) { + if (@toks) { + $v .= ',' . shift @toks; + } else { + # read another line from the file + $raf->ReadLine($buff) or last; + @toks = split ',', $buff; + last unless @toks; + $v .= shift @toks; + } + } + $v =~ s/"\s*$//; # remove trailing quote and whitespace + $v =~ s/""/"/g; # un-escape quotes + } else { + $v =~ s/[ \n\r]+$//;# remove trailing spaces/newlines + } + push @vals, $v; + } + if (@tags) { + # save values for each tag + for ($i=0; $i<@vals and $i<@tags; ++$i) { + # ignore empty entries unless missingValue is empty too + next unless length $vals[$i] or defined $missingValue and $missingValue eq ''; + # delete tag (set value to undef) if value is same as missing tag + $fileInfo{$tags[$i]} = + (defined $missingValue and $vals[$i] eq $missingValue) ? undef : $vals[$i]; + } + # figure out the file name to use + if ($fileInfo{SourceFile}) { + $$database{$fileInfo{SourceFile}} = \%fileInfo; + $found = 1; + } + } else { + # the first row should be the tag names + foreach (@vals) { + # terminate at first blank tag name (eg. extra comma at end of line) + last unless length $_; + @tags or s/^\xef\xbb\xbf//; # remove UTF-8 BOM if it exists + /^[-\w]+(:[-\w+]+)?#?$/ or $err = "Invalid tag name '${_}'", last; + push(@tags, $_); + } + last if $err; + @tags or $err = 'No tags found', last; + # fix "SourceFile" case if necessary + $tags[0] = 'SourceFile' if lc $tags[0] eq 'sourcefile'; + } + } + close CSVFILE if $openedFile; + undef $raf; + $err = 'No SourceFile column' unless $found or $err; + return $err ? "$err in $file" : undef; +} + +#------------------------------------------------------------------------------ +# Convert unicode code point to UTF-8 +# Inputs: 0) integer Unicode character +# Returns: UTF-8 bytes +sub ToUTF8($) +{ + require Image::ExifTool::Charset; + return Image::ExifTool::Charset::Recompose(undef, [$_[0]], $charset); +} + +#------------------------------------------------------------------------------ +# Read JSON object from file +# Inputs: 0) RAF reference or undef, 1) optional scalar reference for data +# to read before reading from file (ie. the file read buffer) +# Returns: JSON object (scalar, hash ref, or array ref), or undef on EOF or +# empty object or array (and sets $$buffPt to empty string on EOF) +# Notes: position in buffer is significant +sub ReadJSONObject($;$) +{ + my ($raf, $buffPt) = @_; + # initialize buffer if necessary + my ($pos, $readMore, $rtnVal, $tok, $key, $didBOM); + if ($buffPt) { + $pos = pos $$buffPt; + $pos = pos($$buffPt) = 0 unless defined $pos; + } else { + my $buff = ''; + $buffPt = \$buff; + $pos = 0; + } +Tok: for (;;) { + # (didn't spend the time to understand how $pos could be undef, but + # put a test here to be safe because one user reported this problem) + last unless defined $pos; + if ($pos >= length $$buffPt or $readMore) { + last unless defined $raf; + # read another 64kB and add to unparsed data + my $offset = length($$buffPt) - $pos; + if ($offset) { + my $buff; + $raf->Read($buff, 65536) or $$buffPt = '', last; + $$buffPt = substr($$buffPt, $pos) . $buff; + } else { + $raf->Read($$buffPt, 65536) or $$buffPt = '', last; + } + unless ($didBOM) { + $$buffPt =~ s/^\xef\xbb\xbf//; # remove UTF-8 BOM if it exists + $didBOM = 1; + } + $pos = pos($$buffPt) = 0; + $readMore = 0; + } + unless ($tok) { + # skip white space and find next character + $$buffPt =~ /(\S)/g or $pos = length($$buffPt), next; + $tok = $1; + $pos = pos $$buffPt; + } + # see what type of object this is + if ($tok eq '{') { # object (hash) + $rtnVal = { } unless defined $rtnVal; + for (;;) { + # read "KEY":"VALUE" pairs + unless (defined $key) { + $key = ReadJSONObject($raf, $buffPt); + $pos = pos $$buffPt; + } + # ($key may be undef for empty JSON object) + if (defined $key) { + # scan to delimiting ':' + $$buffPt =~ /(\S)/g or $readMore = 1, next Tok; + $1 eq ':' or return undef; # error if not a colon + my $val = ReadJSONObject($raf, $buffPt); + $pos = pos $$buffPt; + return undef unless defined $val; + $$rtnVal{$key} = $val; + undef $key; + } + # scan to delimiting ',' or bounding '}' + $$buffPt =~ /(\S)/g or $readMore = 1, next Tok; + last if $1 eq '}'; # check for end of object + $1 eq ',' or return undef; # error if not a comma + } + } elsif ($tok eq '[') { # array + $rtnVal = [ ] unless defined $rtnVal; + for (;;) { + my $item = ReadJSONObject($raf, $buffPt); + $pos = pos $$buffPt; + # ($item may be undef for empty array) + push @$rtnVal, $item if defined $item; + # scan to delimiting ',' or bounding ']' + $$buffPt =~ /(\S)/g or $readMore = 1, next Tok; + last if $1 eq ']'; # check for end of array + $1 eq ',' or return undef; # error if not a comma + } + } elsif ($tok eq '"') { # quoted string + for (;;) { + $$buffPt =~ /(\\*)"/g or $readMore = 1, next Tok; + last unless length($1) & 1; # check for escaped quote + } + $rtnVal = substr($$buffPt, $pos, pos($$buffPt)-$pos-1); + # unescape characters + $rtnVal =~ s/\\u([0-9a-f]{4})/ToUTF8(hex $1)/ige; + $rtnVal =~ s/\\(.)/$unescapeJSON{$1}||$1/sge; + # decode base64 (binary data) values + if ($rtnVal =~ /^base64:[A-Za-z0-9+\/]*={0,2}$/ and length($rtnVal) % 4 == 3) { + require Image::ExifTool::XMP; + $rtnVal = ${Image::ExifTool::XMP::DecodeBase64(substr($rtnVal,7))}; + } + } elsif ($tok eq ']' or $tok eq '}' or $tok eq ',') { + # return undef for empty object, array, or list item + # (empty list item actually not valid JSON) + pos($$buffPt) = pos($$buffPt) - 1; + } else { # number, 'true', 'false', 'null' + $$buffPt =~ /([\s:,\}\]])/g or $readMore = 1, next; + pos($$buffPt) = pos($$buffPt) - 1; + $rtnVal = $tok . substr($$buffPt, $pos, pos($$buffPt)-$pos); + } + last; + } + return $rtnVal; +} + +#------------------------------------------------------------------------------ +# Read JSON file +# Inputs: 0) JSON file name, file ref or RAF ref, 1) database hash ref, +# 2) flag to delete "-" tags, 3) character set +# Returns: undef on success, or error string +sub ReadJSON($$;$$) +{ + local $_; + my ($file, $database, $missingValue, $chset) = @_; + my ($raf, $openedFile); + + # initialize character set for converting "\uHHHH" chars + $charset = $chset || 'UTF8'; + if (UNIVERSAL::isa($file, 'File::RandomAccess')) { + $raf = $file; + $file = 'JSON file'; + } elsif (ref $file eq 'GLOB') { + $raf = new File::RandomAccess($file); + $file = 'JSON file'; + } else { + open JSONFILE, $file or return "Error opening JSON file '${file}'"; + binmode JSONFILE; + $openedFile = 1; + $raf = new File::RandomAccess(\*JSONFILE); + } + my $obj = ReadJSONObject($raf); + close JSONFILE if $openedFile; + unless (ref $obj eq 'ARRAY') { + ref $obj eq 'HASH' or return "Format error in JSON file '${file}'"; + $obj = [ $obj ]; + } + my ($info, $found); + foreach $info (@$obj) { + next unless ref $info eq 'HASH'; + # fix "SourceFile" case, or assume '*' if SourceFile not specified + unless (defined $$info{SourceFile}) { + my ($key) = grep /^SourceFile$/i, keys %$info; + if ($key) { + $$info{SourceFile} = $$info{$key}; + delete $$info{$key}; + } else { + $$info{SourceFile} = '*'; + } + } + if (defined $missingValue) { + $$info{$_} eq $missingValue and $$info{$_} = undef foreach keys %$info; + } + $$database{$$info{SourceFile}} = $info; + $found = 1; + } + return $found ? undef : "No valid JSON objects in '${file}'"; +} + + +1; # end + +__END__ + +=head1 NAME + +Image::ExifTool::Import - Import CSV and JSON database files + +=head1 SYNOPSIS + + use Image::ExifTool::Import qw(ReadCSV ReadJSON); + + $err = ReadCSV($csvFile, \%database); + + $err = ReadJSON($jsonfile, \%database); + +=head1 DESCRIPTION + +This module contains routines for importing tag information from CSV (Comma +Separated Value) and JSON (JavaScript Object Notation) database files. + +=head1 EXPORTS + +Exports nothing by default, but ReadCSV and ReadJSON may be exported. + +=head1 METHODS + +=head2 ReadCSV / ReadJSON + +Read CSV or JSON file into a database hash. + +=over 4 + +=item Inputs: + +0) CSV file name or file reference. + +1) Hash reference for database object. + +2) Optional string used to represent an undefined (missing) tag value. +(Used for deleting tags.) + +3) [ReadJSON only] Optional character set for converting Unicode escape +sequences in strings. Defaults to "UTF8". See the ExifTool Charset option +for a list of valid settings. + +=item Return Value: + +These functions return an error string, or undef on success and populate the +database hash with entries from the CSV or JSON file. Entries are keyed +based on the SourceFile column of the CSV or JSON information, and are +stored as hash lookups of tag name/value for each SourceFile. + +=back + +=head1 AUTHOR + +Copyright 2003-2019, Phil Harvey (phil at owl.phy.queensu.ca) + +This library is free software; you can redistribute it and/or modify it +under the same terms as Perl itself. + +=head1 SEE ALSO + +L<Image::ExifTool(3pm)|Image::ExifTool> + +=cut diff --git a/lib/Image/ExifTool/InDesign.pm b/lib/Image/ExifTool/InDesign.pm new file mode 100644 index 0000000..a250451 --- /dev/null +++ b/lib/Image/ExifTool/InDesign.pm @@ -0,0 +1,279 @@ +#------------------------------------------------------------------------------ +# File: InDesign.pm +# +# Description: Read/write meta information in Adobe InDesign files +# +# Revisions: 2009-06-17 - P. Harvey Created +# +# References: 1) http://www.adobe.com/devnet/xmp/pdfs/XMPSpecificationPart3.pdf +#------------------------------------------------------------------------------ + +package Image::ExifTool::InDesign; + +use strict; +use vars qw($VERSION); +use Image::ExifTool qw(:DataAccess :Utils); + +$VERSION = '1.06'; + +# map for writing metadata to InDesign files (currently only write XMP) +my %indMap = ( + XMP => 'IND', +); + +# GUID's used in InDesign files +my $masterPageGUID = "\x06\x06\xed\xf5\xd8\x1d\x46\xe5\xbd\x31\xef\xe7\xfe\x74\xb7\x1d"; +my $objectHeaderGUID = "\xde\x39\x39\x79\x51\x88\x4b\x6c\x8E\x63\xee\xf8\xae\xe0\xdd\x38"; +my $objectTrailerGUID = "\xfd\xce\xdb\x70\xf7\x86\x4b\x4f\xa4\xd3\xc7\x28\xb3\x41\x71\x06"; + +#------------------------------------------------------------------------------ +# Read or write meta information in an InDesign file +# Inputs: 0) ExifTool object reference, 1) dirInfo reference +# Returns: 1 on success, 0 if this wasn't a valid InDesign file, or -1 on write error +sub ProcessIND($$) +{ + my ($et, $dirInfo) = @_; + my $raf = $$dirInfo{RAF}; + my $outfile = $$dirInfo{OutFile}; + my ($hdr, $buff, $buf2, $err, $writeLen, $foundXMP); + + # validate the InDesign file + return 0 unless $raf->Read($hdr, 16) == 16; + return 0 unless $hdr eq $masterPageGUID; + return 0 unless $raf->Read($buff, 8) == 8; + $et->SetFileType($buff eq 'DOCUMENT' ? 'INDD' : 'IND'); # set the FileType tag + + # read the master pages + $raf->Seek(0, 0) or $err = 'Seek error', goto DONE; + unless ($raf->Read($buff, 4096) == 4096 and + $raf->Read($buf2, 4096) == 4096) + { + $err = 'Unexpected end of file'; + goto DONE; # (goto's can be our friend) + } + SetByteOrder('II'); + unless ($buf2 =~ /^\Q$masterPageGUID/) { + $err = 'Second master page is invalid'; + goto DONE; + } + my $seq1 = Get64u(\$buff, 264); + my $seq2 = Get64u(\$buf2, 264); + # take the most current master page + my $curPage = $seq2 > $seq1 ? \$buf2 : \$buff; + # byte order of stream data may be different than headers + my $streamInt32u = Get8u($curPage, 24); + if ($streamInt32u == 1) { + $streamInt32u = 'V'; # little-endian int32u + } elsif ($streamInt32u == 2) { + $streamInt32u = 'N'; # big-endian int32u + } else { + $err = 'Invalid stream byte order'; + goto DONE; + } + my $pages = Get32u($curPage, 280); + $pages < 2 and $err = 'Invalid page count', goto DONE; + my $pos = $pages * 4096; + if ($pos > 0x7fffffff and not $et->Options('LargeFileSupport')) { + $err = 'InDesign files larger than 2 GB not supported (LargeFileSupport not set)'; + goto DONE; + } + if ($outfile) { + # make XMP the preferred group for writing + $et->InitWriteDirs(\%indMap, 'XMP'); + + Write($outfile, $buff, $buf2) or $err = 1, goto DONE; + my $result = Image::ExifTool::CopyBlock($raf, $outfile, $pos - 8192); + unless ($result) { + $err = defined $result ? 'Error reading InDesign database' : 1; + goto DONE; + } + $writeLen = 0; + } else { + $raf->Seek($pos, 0) or $err = 'Seek error', goto DONE; + } + # scan through the contiguous objects for XMP + my $verbose = $et->Options('Verbose'); + my $out = $et->Options('TextOut'); + for (;;) { + $raf->Read($hdr, 32) or last; + unless (length($hdr) == 32 and $hdr =~ /^\Q$objectHeaderGUID/) { + # this must be null padding or we have an error + $hdr =~ /^\0+$/ or $err = 'Corrupt file or unsupported InDesign version'; + last; + } + my $len = Get32u(\$hdr, 24); + if ($verbose) { + printf $out "Contiguous object at offset 0x%x (%d bytes):\n", $raf->Tell(), $len; + if ($verbose > 2) { + my $len2 = $len < 1024000 ? $len : 1024000; + $raf->Seek(-$raf->Read($buff, $len2), 1) or $err = 1; + $et->VerboseDump(\$buff, Addr => $raf->Tell()); + } + } + # check for XMP if stream data is long enough + # (56 bytes is just enough for XMP header) + if ($len > 56) { + $raf->Read($buff, 56) == 56 or $err = 'Unexpected end of file', last; + if ($buff =~ /^(....)<\?xpacket begin=(['"])\xef\xbb\xbf\2 id=(['"])W5M0MpCehiHzreSzNTczkc9d\3/s) { + my $lenWord = $1; # save length word for writing later + $len -= 4; # get length of XMP only + $foundXMP = 1; + # I have a sample where the XMP is 107 MB, and ActivePerl may run into + # memory troubles (with its apparent 1 GB limit) if the XMP is larger + # than about 400 MB, so guard against this + if ($len > 300 * 1024 * 1024) { + my $msg = sprintf('Insanely large XMP (%.0f MB)', $len / (1024 * 1024)); + if ($outfile) { + $et->Error($msg, 2) and $err = 1, last; + } elsif ($et->Options('IgnoreMinorErrors')) { + $et->Warn($msg); + } else { + $et->Warn("$msg. Ignored.", 1); + $err = 1; + last; + } + } + # load and parse the XMP data + unless ($raf->Seek(-52, 1) and $raf->Read($buff, $len) == $len) { + $err = 'Error reading XMP stream'; + last; + } + my %dirInfo = ( + DataPt => \$buff, + Parent => 'IND', + NoDelete => 1, # do not allow this to be deleted when writing + ); + # validate xmp data length (should be same as length in header - 4) + my $xmpLen = unpack($streamInt32u, $lenWord); + unless ($xmpLen == $len) { + if ($xmpLen < $len) { + $dirInfo{DirLen} = $xmpLen; + } else { + $err = 'Truncated XMP stream (missing ' . ($xmpLen - $len) . ' bytes)'; + } + } + my $tagTablePtr = GetTagTable('Image::ExifTool::XMP::Main'); + if ($outfile) { + last if $err; + # make sure that XMP is writable + my $classID = Get32u(\$hdr, 20); + $classID & 0x40000000 or $err = 'XMP stream is not writable', last; + my $xmp = $et->WriteDirectory(\%dirInfo, $tagTablePtr); + if ($xmp and length $xmp) { + # write new xmp with leading length word + $buff = pack($streamInt32u, length $xmp) . $xmp; + # update header with new length and invalid checksum + Set32u(length($buff), \$hdr, 24); + Set32u(0xffffffff, \$hdr, 28); + } else { + $$et{CHANGED} = 0; # didn't change anything + $et->Warn("Can't delete XMP as a block from InDesign file") if defined $xmp; + # put length word back at start of stream + $buff = $lenWord . $buff; + } + } else { + $et->ProcessDirectory(\%dirInfo, $tagTablePtr); + } + $len = 0; # we got the full stream (nothing left to read) + } else { + $len -= 56; # we got 56 bytes of the stream + } + } else { + $buff = ''; # must reset this for writing later + } + if ($outfile) { + # write object header and data + Write($outfile, $hdr, $buff) or $err = 1, last; + my $result = Image::ExifTool::CopyBlock($raf, $outfile, $len); + unless ($result) { + $err = defined $result ? 'Truncated stream data' : 1; + last; + } + $writeLen += 32 + length($buff) + $len; + } elsif ($len) { + # skip over remaining stream data + $raf->Seek($len, 1) or $err = 'Seek error', last; + } + $raf->Read($buff, 32) == 32 or $err = 'Unexpected end of file', last; + unless ($buff =~ /^\Q$objectTrailerGUID/) { + $err = 'Invalid object trailer'; + last; + } + if ($outfile) { + # make sure object UID and ClassID are the same in the trailer + substr($hdr,16,8) eq substr($buff,16,8) or $err = 'Non-matching object trailer', last; + # write object trailer + Write($outfile, $objectTrailerGUID, substr($hdr,16)) or $err = 1, last; + $writeLen += 32; + } + } + if ($outfile) { + # write null padding if necessary + # (InDesign files must be an even number of 4096-byte blocks) + my $part = $writeLen % 4096; + Write($outfile, "\0" x (4096 - $part)) or $err = 1 if $part; + } +DONE: + if (not $err) { + $et->Warn('No XMP stream to edit') if $outfile and not $foundXMP; + return 1; # success! + } elsif (not $outfile) { + # issue warning on read error + $et->Warn($err) unless $err eq '1'; + } elsif ($err ne '1') { + # set error and return success code + $et->Error($err); + } else { + return -1; # write error + } + return 1; +} + +1; # end + +__END__ + +=head1 NAME + +Image::ExifTool::InDesign - Read/write meta information in Adobe InDesign files + +=head1 SYNOPSIS + +This module is used by Image::ExifTool + +=head1 DESCRIPTION + +This module contains routines required by Image::ExifTool to read XMP +meta information from Adobe InDesign (.IND, .INDD and .INDT) files. + +=head1 LIMITATIONS + +1) Only XMP meta information is processed. + +2) A new XMP stream may not be created, so XMP tags may only be written to +InDesign files which previously contained XMP. + +3) File sizes of greater than 2 GB are supported only if the system supports +them and the LargeFileSupport option is enabled. + +=head1 AUTHOR + +Copyright 2003-2019, Phil Harvey (phil at owl.phy.queensu.ca) + +This library is free software; you can redistribute it and/or modify it +under the same terms as Perl itself. + +=head1 REFERENCES + +=over 4 + +=item L<http://www.adobe.com/devnet/xmp/pdfs/XMPSpecificationPart3.pdf> + +=back + +=head1 SEE ALSO + +L<Image::ExifTool(3pm)|Image::ExifTool> + +=cut + diff --git a/lib/Image/ExifTool/JPEG.pm b/lib/Image/ExifTool/JPEG.pm new file mode 100644 index 0000000..12c46c3 --- /dev/null +++ b/lib/Image/ExifTool/JPEG.pm @@ -0,0 +1,616 @@ +#------------------------------------------------------------------------------ +# File: JPEG.pm +# +# Description: Definitions for uncommon JPEG segments +# +# Revisions: 10/06/2006 - P. Harvey Created +#------------------------------------------------------------------------------ + +package Image::ExifTool::JPEG; +use strict; +use vars qw($VERSION); +use Image::ExifTool qw(:DataAccess :Utils); + +$VERSION = '1.27'; + +sub ProcessOcad($$$); +sub ProcessJPEG_HDR($$$); + +# (this main JPEG table is for documentation purposes only) +%Image::ExifTool::JPEG::Main = ( + NOTES => q{ + This table lists information extracted by ExifTool from JPEG images. See + L<https://www.w3.org/Graphics/JPEG/jfif3.pdf> for the JPEG specification. + }, + APP0 => [{ + Name => 'JFIF', + Condition => '$$valPt =~ /^JFIF\0/', + SubDirectory => { TagTable => 'Image::ExifTool::JFIF::Main' }, + }, { + Name => 'JFXX', + Condition => '$$valPt =~ /^JFXX\0\x10/', + SubDirectory => { TagTable => 'Image::ExifTool::JFIF::Extension' }, + }, { + Name => 'CIFF', + Condition => '$$valPt =~ /^(II|MM).{4}HEAPJPGM/s', + SubDirectory => { TagTable => 'Image::ExifTool::CanonRaw::Main' }, + }, { + Name => 'AVI1', + Condition => '$$valPt =~ /^AVI1/', + SubDirectory => { TagTable => 'Image::ExifTool::JPEG::AVI1' }, + }, { + Name => 'Ocad', + Condition => '$$valPt =~ /^Ocad/', + SubDirectory => { TagTable => 'Image::ExifTool::JPEG::Ocad' }, + }], + APP1 => [{ + Name => 'EXIF', + Condition => '$$valPt =~ /^Exif\0/', + SubDirectory => { TagTable => 'Image::ExifTool::Exif::Main' }, + }, { + Name => 'ExtendedXMP', + Condition => '$$valPt =~ m{^http://ns.adobe.com/xmp/extension/\0}', + SubDirectory => { TagTable => 'Image::ExifTool::XMP::Main' }, + }, { + Name => 'XMP', + Condition => '$$valPt =~ /^http/ or $$valPt =~ /<exif:/', + SubDirectory => { TagTable => 'Image::ExifTool::XMP::Main' }, + }, { + Name => 'QVCI', + Condition => '$$valPt =~ /^QVCI\0/', + SubDirectory => { TagTable => 'Image::ExifTool::Casio::QVCI' }, + }, { + Name => 'FLIR', + Condition => '$$valPt =~ /^FLIR\0/', + SubDirectory => { TagTable => 'Image::ExifTool::FLIR::FFF' }, + }], + APP2 => [{ + Name => 'ICC_Profile', + Condition => '$$valPt =~ /^ICC_PROFILE\0/', + SubDirectory => { TagTable => 'Image::ExifTool::ICC_Profile::Main' }, + }, { + Name => 'FPXR', + Condition => '$$valPt =~ /^FPXR\0/', + SubDirectory => { TagTable => 'Image::ExifTool::FlashPix::Main' }, + }, { + Name => 'MPF', + Condition => '$$valPt =~ /^MPF\0/', + SubDirectory => { TagTable => 'Image::ExifTool::MPF::Main' }, + }, { + Name => 'PreviewImage', + Condition => '$$valPt =~ /^(|QVGA\0|BGTH)\xff\xd8\xff\xdb/', + Notes => 'Samsung APP2 preview image', # (Samsung/GoPro="", BenQ="QVGA\0", Digilife="BGTH") + }], + APP3 => [{ + Name => 'Meta', + Condition => '$$valPt =~ /^(Meta|META|Exif)\0\0/', + SubDirectory => { TagTable => 'Image::ExifTool::Kodak::Meta' }, + }, { + Name => 'Stim', + Condition => '$$valPt =~ /^Stim\0/', + SubDirectory => { TagTable => 'Image::ExifTool::Stim::Main' }, + }, { + Name => 'PreviewImage', # (written by HP R837 and Samsung S1060) + Condition => '$$valPt =~ /^\xff\xd8\xff\xdb/', + Notes => 'Samsung/HP preview image', # (Samsung, HP, BenQ) + }], + APP4 => [{ + Name => 'Scalado', + Condition => '$$valPt =~ /^SCALADO\0/', + SubDirectory => { TagTable => 'Image::ExifTool::Scalado::Main' }, + }, { + Name => 'FPXR', # (non-standard location written by some HP models) + Condition => '$$valPt =~ /^FPXR\0/', + SubDirectory => { TagTable => 'Image::ExifTool::FlashPix::Main' }, + }, { + Name => 'PreviewImage', # (eg. Samsung S1060) + Notes => 'continued from APP3', + }], + APP5 => [{ + Name => 'RMETA', + Condition => '$$valPt =~ /^RMETA\0/', + SubDirectory => { TagTable => 'Image::ExifTool::Ricoh::RMETA' }, + }, { + Name => 'SamsungUniqueID', + Condition => '$$valPt =~ /ssuniqueid\0/', + SubDirectory => { TagTable => 'Image::ExifTool::Samsung::APP5' }, + }, { + Name => 'PreviewImage', # (eg. BenQ DC E1050) + Notes => 'continued from APP4', + }], + APP6 => [{ + Name => 'EPPIM', + Condition => '$$valPt =~ /^EPPIM\0/', + SubDirectory => { TagTable => 'Image::ExifTool::JPEG::EPPIM' }, + }, { + Name => 'NITF', + Condition => '$$valPt =~ /^NTIF\0/', + SubDirectory => { TagTable => 'Image::ExifTool::JPEG::NITF' }, + }, { + Name => 'HP_TDHD', # (written by R837) + Condition => '$$valPt =~ /^TDHD\x01\0\0\0/', + SubDirectory => { TagTable => 'Image::ExifTool::HP::TDHD' }, + }, { + Name => 'GoPro', + Condition => '$$valPt =~ /^GoPro\0/', + SubDirectory => { TagTable => 'Image::ExifTool::GoPro::GPMF' }, + }], + APP7 => [{ + Name => 'Pentax', + Condition => '$$valPt =~ /^PENTAX \0/', + SubDirectory => { TagTable => 'Image::ExifTool::Pentax::Main' }, + }, { + Name => 'Qualcomm', + Condition => '$$valPt =~ /^\x1aQualcomm Camera Attributes/', + SubDirectory => { TagTable => 'Image::ExifTool::Qualcomm::Main' }, + }], + APP8 => { + Name => 'SPIFF', + Condition => '$$valPt =~ /^SPIFF\0/', + SubDirectory => { TagTable => 'Image::ExifTool::JPEG::SPIFF' }, + }, + APP9 => { + Name => 'MediaJukebox', + Condition => '$$valPt =~ /^Media Jukebox\0/', + SubDirectory => { TagTable => 'Image::ExifTool::JPEG::MediaJukebox' }, + }, + APP10 => { + Name => 'Comment', + Condition => '$$valPt =~ /^UNICODE\0/', + Notes => 'PhotoStudio Unicode comment', + }, + APP11 => { + Name => 'JPEG-HDR', + Condition => '$$valPt =~ /^HDR_RI /', + SubDirectory => { TagTable => 'Image::ExifTool::JPEG::HDR' }, + }, + APP12 => [{ + Name => 'PictureInfo', + Condition => '$$valPt =~ /(\[picture info\]|Type=)/', + SubDirectory => { TagTable => 'Image::ExifTool::APP12::PictureInfo' }, + }, { + Name => 'Ducky', + Condition => '$$valPt =~ /^Ducky/', + SubDirectory => { TagTable => 'Image::ExifTool::APP12::Ducky' }, + }], + APP13 => [{ + Name => 'Photoshop', + Condition => '$$valPt =~ /^(Photoshop 3.0\0|Adobe_Photoshop2.5)/', + SubDirectory => { TagTable => 'Image::ExifTool::Photoshop::Main' }, + }, { + Name => 'Adobe_CM', + Condition => '$$valPt =~ /^Adobe_CM/', + SubDirectory => { TagTable => 'Image::ExifTool::JPEG::AdobeCM' }, + }], + APP14 => { + Name => 'Adobe', + Condition => '$$valPt =~ /^Adobe/', + Writable => 1, # (for docs only) + SubDirectory => { TagTable => 'Image::ExifTool::JPEG::Adobe' }, + }, + APP15 => { + Name => 'GraphicConverter', + Condition => '$$valPt =~ /^Q\s*(\d+)/', + SubDirectory => { TagTable => 'Image::ExifTool::JPEG::GraphConv' }, + }, + # APP15 - Also unknown "TEXT\0" segment stored by Casio/FujiFilm + COM => { + Name => 'Comment', + # note: flag as writable for documentation, but it won't show up + # in the TagLookup as writable because there is no WRITE_PROC + Writable => 1, + }, + SOF => { + Name => 'StartOfFrame', + SubDirectory => { TagTable => 'Image::ExifTool::JPEG::SOF' }, + }, + DQT => { + Name => 'DefineQuantizationTable', + Notes => 'used to calculate the Extra JPEGDigest tag value', + }, + Trailer => [{ + Name => 'AFCP', + Condition => '$$valPt =~ /AXS(!|\*).{8}$/s', + SubDirectory => { TagTable => 'Image::ExifTool::AFCP::Main' }, + }, { + Name => 'CanonVRD', + Condition => '$$valPt =~ /CANON OPTIONAL DATA\0.{44}$/s', + SubDirectory => { TagTable => 'Image::ExifTool::CanonVRD::Main' }, + }, { + Name => 'FotoStation', + Condition => '$$valPt =~ /\xa1\xb2\xc3\xd4$/', + SubDirectory => { TagTable => 'Image::ExifTool::FotoStation::Main' }, + }, { + Name => 'PhotoMechanic', + Condition => '$$valPt =~ /cbipcbbl$/', + SubDirectory => { TagTable => 'Image::ExifTool::PhotoMechanic::Main' }, + }, { + Name => 'MIE', + Condition => q{ + $$valPt =~ /~\0\x04\0zmie~\0\0\x06.{4}[\x10\x18]\x04$/s or + $$valPt =~ /~\0\x04\0zmie~\0\0\x0a.{8}[\x10\x18]\x08$/s + }, + SubDirectory => { TagTable => 'Image::ExifTool::MIE::Main' }, + }, { + Name => 'Samsung', + Condition => '$$valPt =~ /QDIOBS$/', + SubDirectory => { TagTable => 'Image::ExifTool::Samsung::Trailer' }, + }, { + Name => 'PreviewImage', + Condition => '$$valPt =~ /^\xff\xd8\xff/', + Writable => 1, # (for docs only) + }], +); + +# EPPIM APP6 (Toshiba PrintIM) segment (ref PH, from PDR-M700 samples) +%Image::ExifTool::JPEG::EPPIM = ( + GROUPS => { 0 => 'APP6', 1 => 'EPPIM', 2 => 'Image' }, + NOTES => q{ + APP6 is used in by the Toshiba PDR-M700 to store a TIFF structure containing + PrintIM information. + }, + 0xc4a5 => { + Name => 'PrintIM', + # must set Writable here so this tag will be saved with MakerNotes option + Writable => 'undef', + Description => 'Print Image Matching', + SubDirectory => { + TagTable => 'Image::ExifTool::PrintIM::Main', + }, + }, +); + +# APP8 SPIFF segment. Refs: +# 1) http://www.fileformat.info/format/spiff/ +# 2) http://www.jpeg.org/public/spiff.pdf +%Image::ExifTool::JPEG::SPIFF = ( + PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData, + GROUPS => { 0 => 'APP8', 1 => 'SPIFF', 2 => 'Image' }, + NOTES => q{ + This information is found in APP8 of SPIFF-style JPEG images (the "official" + yet rarely used JPEG file format standard: Still Picture Interchange File + Format). See L<http://www.jpeg.org/public/spiff.pdf> for the official + specification. + }, + 0 => { + Name => 'SPIFFVersion', + Format => 'int8u[2]', + PrintConv => '$val =~ tr/ /./; $val', + }, + 2 => { + Name => 'ProfileID', + PrintConv => { + 0 => 'Not Specified', + 1 => 'Continuous-tone Base', + 2 => 'Continuous-tone Progressive', + 3 => 'Bi-level Facsimile', + 4 => 'Continuous-tone Facsimile', + }, + }, + 3 => 'ColorComponents', + 6 => { + Name => 'ImageHeight', + Notes => q{ + at index 4 in specification, but there are 2 extra bytes here in my only + SPIFF sample, version 1.2 + }, + Format => 'int32u', + }, + 10 => { + Name => 'ImageWidth', + Format => 'int32u', + }, + 14 => { + Name => 'ColorSpace', + PrintConv => { + 0 => 'Bi-level', + 1 => 'YCbCr, ITU-R BT 709, video', + 2 => 'No color space specified', + 3 => 'YCbCr, ITU-R BT 601-1, RGB', + 4 => 'YCbCr, ITU-R BT 601-1, video', + 8 => 'Gray-scale', + 9 => 'PhotoYCC', + 10 => 'RGB', + 11 => 'CMY', + 12 => 'CMYK', + 13 => 'YCCK', + 14 => 'CIELab', + }, + }, + 15 => 'BitsPerSample', + 16 => { + Name => 'Compression', + PrintConv => { + 0 => 'Uncompressed, interleaved, 8 bits per sample', + 1 => 'Modified Huffman', + 2 => 'Modified READ', + 3 => 'Modified Modified READ', + 4 => 'JBIG', + 5 => 'JPEG', + }, + }, + 17 => { + Name => 'ResolutionUnit', + PrintConv => { + 0 => 'None', + 1 => 'inches', + 2 => 'cm', + }, + }, + 18 => { + Name => 'YResolution', + Format => 'int32u', + }, + 22 => { + Name => 'XResolution', + Format => 'int32u', + }, +); + +# APP9 Media Jukebox segment (ref PH) +%Image::ExifTool::JPEG::MediaJukebox = ( + GROUPS => { 0 => 'XML', 1 => 'MediaJukebox', 2 => 'Image' }, + VARS => { NO_ID => 1 }, + NOTES => 'Tags found in the XML metadata of the APP9 "Media Jukebox" segment.', + Date => { + Groups => { 2 => 'Time' }, + # convert from days since Dec 30, 1899 to seconds since Jan 1, 1970 + ValueConv => 'ConvertUnixTime(($val - (70 * 365 + 17 + 2)) * 24 * 3600)', + PrintConv => '$self->ConvertDateTime($val)', + }, + Album => { }, + Caption => { }, + Keywords => { }, + Name => { }, + People => { }, + Places => { }, + Tool_Name => { }, + Tool_Version => { }, +); + +# JPEG-HDR APP11 information (ref PH, guessed from http://anyhere.com/gward/papers/cic05.pdf) +%Image::ExifTool::JPEG::HDR = ( + GROUPS => { 0 => 'APP11', 1 => 'JPEG-HDR', 2 => 'Image' }, + PROCESS_PROC => \&ProcessJPEG_HDR, + TAG_PREFIX => '', # (no prefix for unknown tags) + NOTES => 'Information extracted from APP11 of a JPEG-HDR image.', + ver => 'JPEG-HDRVersion', + # (need names for the next 3 tags) + ln0 => { Description => 'Ln0' }, + ln1 => { Description => 'Ln1' }, + s2n => { Description => 'S2n' }, + alp => { Name => 'Alpha' }, # (Alpha/Beta are saturation parameters) + bet => { Name => 'Beta' }, + cor => { Name => 'CorrectionMethod' }, + RatioImage => { + Groups => { 2 => 'Preview' }, + Notes => 'the embedded JPEG-compressed ratio image', + Binary => 1, + }, +); + +# AdobeCM APP13 (no references) +%Image::ExifTool::JPEG::AdobeCM = ( + PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData, + GROUPS => { 0 => 'APP13', 1 => 'AdobeCM', 2 => 'Image' }, + NOTES => q{ + The APP13 "Adobe_CM" segment presumably contains color management + information, but the meaning of the data is currently unknown. If anyone + has an idea about what this means, please let me know. + }, + FORMAT => 'int16u', + 0 => 'AdobeCMType', +); + +# Adobe APP14 refs: +# http://partners.adobe.com/public/developer/en/ps/sdk/5116.DCT_Filter.pdf +# http://java.sun.com/j2se/1.5.0/docs/api/javax/imageio/metadata/doc-files/jpeg_metadata.html#color +%Image::ExifTool::JPEG::Adobe = ( + PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData, + GROUPS => { 0 => 'APP14', 1 => 'Adobe', 2 => 'Image' }, + NOTES => q{ + The APP14 "Adobe" segment stores image encoding information for DCT filters. + This segment may be copied or deleted as a block using the Extra "Adobe" + tag, but note that it is not deleted by default when deleting all metadata + because it may affect the appearance of the image. + }, + FORMAT => 'int16u', + 0 => 'DCTEncodeVersion', + 1 => { + Name => 'APP14Flags0', + PrintConv => { + 0 => '(none)', + BITMASK => { + 15 => 'Encoded with Blend=1 downsampling' + }, + }, + }, + 2 => { + Name => 'APP14Flags1', + PrintConv => { + 0 => '(none)', + BITMASK => { }, + }, + }, + 3 => { + Name => 'ColorTransform', + Format => 'int8u', + PrintConv => { + 0 => 'Unknown (RGB or CMYK)', + 1 => 'YCbCr', + 2 => 'YCCK', + }, + }, +); + +# GraphicConverter APP15 (ref PH) +%Image::ExifTool::JPEG::GraphConv = ( + GROUPS => { 0 => 'APP15', 1 => 'GraphConv', 2 => 'Image' }, + NOTES => 'APP15 is used by GraphicConverter to store JPEG quality.', + 'Q' => 'Quality', +); + +# APP0 AVI1 segment (ref http://www.schnarff.com/file-formats/bmp/BMPDIB.TXT) +%Image::ExifTool::JPEG::AVI1 = ( + PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData, + GROUPS => { 0 => 'APP0', 1 => 'AVI1', 2 => 'Image' }, + NOTES => 'This information may be found in APP0 of JPEG image data from AVI videos.', + FIRST_ENTRY => 0, + 0 => { + Name => 'InterleavedField', + PrintConv => { + 0 => 'Not Interleaved', + 1 => 'Odd', + 2 => 'Even', + }, + }, +); + +# APP0 Ocad segment (ref PH) +%Image::ExifTool::JPEG::Ocad = ( + PROCESS_PROC => \&ProcessOcad, + GROUPS => { 0 => 'APP0', 1 => 'Ocad', 2 => 'Image' }, + TAG_PREFIX => 'Ocad', + FIRST_ENTRY => 0, + NOTES => q{ + Tags extracted from the JPEG APP0 "Ocad" segment (found in Photobucket + images). + }, + Rev => { + Name => 'OcadRevision', + Format => 'string[6]', + } +); + +# APP6 NITF segment (National Imagery Transmission Format) +# ref http://www.gwg.nga.mil/ntb/baseline/docs/n010697/bwcguide25aug98.pdf +%Image::ExifTool::JPEG::NITF = ( + PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData, + GROUPS => { 0 => 'APP6', 1 => 'NITF', 2 => 'Image' }, + NOTES => q{ + Information in APP6 used by the National Imagery Transmission Format. See + L<http://www.gwg.nga.mil/ntb/baseline/docs/n010697/bwcguide25aug98.pdf> for + the official specification. + }, + 0 => { + Name => 'NITFVersion', + Format => 'int8u[2]', + ValueConv => 'sprintf("%d.%.2d", split(" ",$val))', + }, + 2 => { + Name => 'ImageFormat', + ValueConv => 'chr($val)', + PrintConv => { B => 'IMode B' }, + }, + 3 => { + Name => 'BlocksPerRow', + Format => 'int16u', + }, + 5 => { + Name => 'BlocksPerColumn', + Format => 'int16u', + }, + 7 => { + Name => 'ImageColor', + PrintConv => { 0 => 'Monochrome' }, + }, + 8 => 'BitDepth', + 9 => { + Name => 'ImageClass', + PrintConv => { + 0 => 'General Purpose', + 4 => 'Tactical Imagery', + }, + }, + 10 => { + Name => 'JPEGProcess', + PrintConv => { + 1 => 'Baseline sequential DCT, Huffman coding, 8-bit samples', + 4 => 'Extended sequential DCT, Huffman coding, 12-bit samples', + }, + }, + 11 => 'Quality', + 12 => { + Name => 'StreamColor', + PrintConv => { 0 => 'Monochrome' }, + }, + 13 => 'StreamBitDepth', + 14 => { + Name => 'Flags', + Format => 'int32u', + PrintConv => 'sprintf("0x%x", $val)', + }, +); + +#------------------------------------------------------------------------------ +# Extract information from the JPEG APP0 Ocad segment +# Inputs: 0) ExifTool object ref, 1) dirInfo ref, 2) tag table ref +# Returns: 1 on success +sub ProcessOcad($$$) +{ + my ($et, $dirInfo, $tagTablePtr) = @_; + my $dataPt = $$dirInfo{DataPt}; + $et->VerboseDir('APP0 Ocad', undef, length $$dataPt); + for (;;) { + last unless $$dataPt =~ /\$(\w+):([^\0\$]+)/g; + my ($tag, $val) = ($1, $2); + $val =~ s/^\s+//; $val =~ s/\s+$//; # remove leading/trailing spaces + AddTagToTable($tagTablePtr, $tag) unless $$tagTablePtr{$tag}; + $et->HandleTag($tagTablePtr, $tag, $val); + } + return 1; +} + +#------------------------------------------------------------------------------ +# Extract information from the JPEG APP0 Ocad segment +# Inputs: 0) ExifTool object ref, 1) dirInfo ref, 2) tag table ref +# Returns: 1 on success +sub ProcessJPEG_HDR($$$) +{ + my ($et, $dirInfo, $tagTablePtr) = @_; + my $dataPt = $$dirInfo{DataPt}; + $$dataPt =~ /~\0/g or $et->Warn('Unrecognized JPEG-HDR format'), return 0; + my $pos = pos $$dataPt; + my $meta = substr($$dataPt, 7, $pos-9); + $et->VerboseDir('APP11 JPEG-HDR', undef, length $$dataPt); + while ($meta =~ /(\w+)=([^,\s]*)/g) { + my ($tag, $val) = ($1, $2); + AddTagToTable($tagTablePtr, $tag) unless $$tagTablePtr{$tag}; + $et->HandleTag($tagTablePtr, $tag, $val); + } + $et->HandleTag($tagTablePtr, 'RatioImage', substr($$dataPt, $pos)); + return 1; +} + +1; # end + +__END__ + +=head1 NAME + +Image::ExifTool::JPEG - Definitions for uncommon JPEG segments + +=head1 SYNOPSIS + +This module is used by Image::ExifTool + +=head1 DESCRIPTION + +This module contains definitions required by Image::ExifTool for some +uncommon JPEG segments. For speed reasons, definitions for more common JPEG +segments are included in the Image::ExifTool module itself. + +=head1 AUTHOR + +Copyright 2003-2019, Phil Harvey (phil at owl.phy.queensu.ca) + +This library is free software; you can redistribute it and/or modify it +under the same terms as Perl itself. + +=head1 SEE ALSO + +L<Image::ExifTool::TagNames/JPEG Tags>, +L<Image::ExifTool(3pm)|Image::ExifTool> + +=cut + diff --git a/lib/Image/ExifTool/JPEGDigest.pm b/lib/Image/ExifTool/JPEGDigest.pm new file mode 100644 index 0000000..ed26e15 --- /dev/null +++ b/lib/Image/ExifTool/JPEGDigest.pm @@ -0,0 +1,2617 @@ +#------------------------------------------------------------------------------ +# File: JPEGDigest.pm +# +# Description: Calculate JPEGDigest and JPEGQualityEstimate +# +# Revisions: 2008/09/15 - P. Harvey Created +# 2016/01/05 - PH Added calculation of JPEGQualityEstimate +# +# References: JD) Jens Duttke +# 2) Franz Buchinger private communication +# 3) https://github.com/ImageMagick/ImageMagick/blob/master/coders/jpeg.c +#------------------------------------------------------------------------------ + +package Image::ExifTool::JPEGDigest; +use strict; +use vars qw($VERSION); + +$VERSION = '1.06'; + +# the print conversion for the JPEGDigest tag +my %PrintConv = ( #JD + # No DQT defined + 'd41d8cd98f00b204e9800998ecf8427e' => 'No DQT defined', + + # Tested with: + # - Independent JPEG Group library (used by many applications) X3 (Win) + # - Different subsamplings possible + # - Dynamic Photo HDR 3.0 (Win) + # - Fixed to quality 92? + # - Fixed subsampling of 111111? + # - FixFoto (Win) + # - These DQTs are only used for the Quality settings 24 to 100 + # - Different subsamplings possible + # - Subsampling of 221111 is default + # - GraphicConverter 4.4.4 (Mac) + # - Using the JPEG 6.0 library + # - Fixed subsampling to 221111 + # - IrfanView 4.10 (Win) + # - Subsampling 111111 with option "Disable subsampling", otherwise 221111 + # - Quality mode 0 doesn't exist here + # - Jasc Paint Shop Pro Version 5.01 (Win) + # - Fixed subsampling of 221111 + # - Use reversed Quality values (0 or 1 = 99; 2 = 98; 3 = 97 etc.) + # - Microsoft GDI+ Version 5.1.3102.2180 (Win) + # - Fixed subsampling of 221111 (or is that just the default subsampling?) + # - Photomatix pro 3.0 (Win) + # - Fixed subsampling to 221111 + + # IJG library + 'f83c5bc303fa1f74265863c2c6844edf' => 'Independent JPEG Group library (used by many applications), Quality 0 or 1', + '1e81ee25c96cdf46f44a9b930780f8c0' => 'Independent JPEG Group library (used by many applications), Quality 2', + '205d4a597e68f2da78137e52f39d2728' => 'Independent JPEG Group library (used by many applications), Quality 3', + '81a936d8371a7d59da428fcfc349850f' => 'Independent JPEG Group library (used by many applications), Quality 4', + '610772f3cf75c2fd89214fafbd7617a6' => 'Independent JPEG Group library (used by many applications), Quality 5', + '577ec8895d884612d064771e84cf231f' => 'Independent JPEG Group library (used by many applications), Quality 6', + '7dc25cc528116e25dd1aeb590dd7cb66' => 'Independent JPEG Group library (used by many applications), Quality 7', + 'e3cc8a85db1a32e81650b9668b98644a' => 'Independent JPEG Group library (used by many applications), Quality 8', + 'e2408846813c1f5c7f5ce3cf69e741c4' => 'Independent JPEG Group library (used by many applications), Quality 9', + 'e800426d2ef8d3cda13a0b41f1b2cc5a' => 'Independent JPEG Group library (used by many applications), Quality 10', + '8ef467e72e5006d1b48209e7b5d94541' => 'Independent JPEG Group library (used by many applications), Quality 11', + 'af6a08d0742aa8ed6bae2f1c374e7931' => 'Independent JPEG Group library (used by many applications), Quality 12', + 'e002d9728c73f60e4d0509e1cea9af43' => 'Independent JPEG Group library (used by many applications), Quality 13', + '1eb8b98bef8b062e4bc10cffea2d8372' => 'Independent JPEG Group library (used by many applications), Quality 14', + '99d933a8a9ece6f2ee65757aa81ef5bd' => 'Independent JPEG Group library (used by many applications), Quality 15', + 'c7d0f7dee5631d01bc55b7c598805d98' => 'Independent JPEG Group library (used by many applications), Quality 16', + '71555bee8d64c9dfca3cefa9dd332472' => 'Independent JPEG Group library (used by many applications), Quality 17', + '5009778c2a1df1deeb040c85fb9d0db2' => 'Independent JPEG Group library (used by many applications), Quality 18', + '81339d89e8294729c69fc096f1a448f3' => 'Independent JPEG Group library (used by many applications), Quality 19', + '82028a770d9e45d64d6aa26faee97e72' => 'Independent JPEG Group library (used by many applications), Quality 20', + '3ebb7aa9113b3e1628f55732de7dae7f' => 'Independent JPEG Group library (used by many applications), Quality 21', + '704c1868fe865f1038aa2bd0697f71a0' => 'Independent JPEG Group library (used by many applications), Quality 22', + '555fd108ab97e641fcfefee4bda6a306' => 'Independent JPEG Group library (used by many applications), Quality 23', + 'f1d9a0410c5ea11613569783625f5cf3' => 'Independent JPEG Group library (used by many applications), Quality 24', + 'ce378a14d52ee5752ded23b5a444f75e' => 'Independent JPEG Group library (used by many applications), Quality 25', + '3f243aacd371617b69f1e1eacadbbe2e' => 'Independent JPEG Group library (used by many applications), Quality 26', + 'c70a1df73760a88deb890003cdab3bfe' => 'Independent JPEG Group library (used by many applications), Quality 27', + 'aa5e05f96c53f6bc498f5016b1113651' => 'Independent JPEG Group library (used by many applications), Quality 28', + '740d4a06f4d0f774c6aac95719673793' => 'Independent JPEG Group library (used by many applications), Quality 29', + '1426dd9c1c8098936f395e201f1eb56d' => 'Independent JPEG Group library (used by many applications), Quality 30', + '891a53bb6a5261a2c076cf8931c3660e' => 'Independent JPEG Group library (used by many applications), Quality 31', + '1c87cb13f4b7a5ed45b09fc4f0e52d68' => 'Independent JPEG Group library (used by many applications), Quality 32', + '2457f78378c5efdac8e1ef619a4285cd' => 'Independent JPEG Group library (used by many applications), Quality 33', + '20f79a557d4edb1917d243d00a7a9ba8' => 'Independent JPEG Group library (used by many applications), Quality 34', + 'e06d44ffef23792c88f215a5b2ed9478' => 'Independent JPEG Group library (used by many applications), Quality 35', + 'df1b50991b82b66c82dc856cf82383da' => 'Independent JPEG Group library (used by many applications), Quality 36', + 'ffd6e30af6d99997d38ec3e303687e25' => 'Independent JPEG Group library (used by many applications), Quality 37', + 'ed923fdb1e5009215a49c0d92061c3b0' => 'Independent JPEG Group library (used by many applications), Quality 38', + 'aaf1ebc6949569327f95cf7da78ee7bc' => 'Independent JPEG Group library (used by many applications), Quality 39', + '0fe5225afaf055efd8453426c00e81e1' => 'Independent JPEG Group library (used by many applications), Quality 40', + 'a79e66299883be78b02ceaaf9159c320' => 'Independent JPEG Group library (used by many applications), Quality 41', + 'c9f10fb6d352cc8a8967e7e96a64862c' => 'Independent JPEG Group library (used by many applications), Quality 42', + '6dc3abbdd52b2f26b790ddb33b82099a' => 'Independent JPEG Group library (used by many applications), Quality 43', + '29572be1991c210fabacaeb658a74844' => 'Independent JPEG Group library (used by many applications), Quality 44', + '0c9f89a3728234e0e85645c968d1d84a' => 'Independent JPEG Group library (used by many applications), Quality 45', + 'a5e5355ae60c569dec306eb971a49276' => 'Independent JPEG Group library (used by many applications), Quality 46', + '4a2605b7c5b1bc99b6715342de7b6562' => 'Independent JPEG Group library (used by many applications), Quality 47', + '6af4053465275c1b1b2d5c97f4d841aa' => 'Independent JPEG Group library (used by many applications), Quality 48', + '905a0b1688644902f6a65d872d68a9db' => 'Independent JPEG Group library (used by many applications), Quality 49', + 'ffcd5eab8daeced571d59d4cdcc002c4' => 'Independent JPEG Group library (used by many applications), Quality 50', + '76806382fa57818da2e406a0dc23ce20' => 'Independent JPEG Group library (used by many applications), Quality 51', + '7c71a5eb9408b93be3ea6cf9be1d31ea' => 'Independent JPEG Group library (used by many applications), Quality 52', + 'ccf3f63196092667f97c2ff723481a21' => 'Independent JPEG Group library (used by many applications), Quality 53', + 'acc5e596cc4eb156b83eb89190b289a7' => 'Independent JPEG Group library (used by many applications), Quality 54', + 'a16e53aa41aa66124557c0b976d73734' => 'Independent JPEG Group library (used by many applications), Quality 55', + '2101fdf5c6f6e92943bc16ccf8aa46a8' => 'Independent JPEG Group library (used by many applications), Quality 56', + 'aaa2026d750590e466d9198f20b888e4' => 'Independent JPEG Group library (used by many applications), Quality 57', + 'fcd8c97cf6004230444ce21dab8a167f' => 'Independent JPEG Group library (used by many applications), Quality 58', + '318081abf5329c90d984c2214d69f097' => 'Independent JPEG Group library (used by many applications), Quality 59', + '95348adff2bf5a88f3967e9237fc571e' => 'Independent JPEG Group library (used by many applications), Quality 60; Pentax Better', + 'e22b26930415798b7ecf2b060c1cdc2a' => 'Independent JPEG Group library (used by many applications), Quality 61', + '3e646bfadb62d25ae8404b179e93e74e' => 'Independent JPEG Group library (used by many applications), Quality 62', + '34bf5c46342f2a514f8ae562e520ece0' => 'Independent JPEG Group library (used by many applications), Quality 63', + 'fc9f2bd278075ea89d482e1f9e66738f' => 'Independent JPEG Group library (used by many applications), Quality 64', + 'b55f27c368f119f25957c8e0036b27f8' => 'Independent JPEG Group library (used by many applications), Quality 65', + '5f7b9af6d66eaf12874aa680e7b0d31b' => 'Independent JPEG Group library (used by many applications), Quality 66', + 'a78fd0f1183b268b2fdfa23308c3ad44' => 'Independent JPEG Group library (used by many applications), Quality 67', + '61814a2eca233e10b0ba26881551fb50' => 'Independent JPEG Group library (used by many applications), Quality 68', + 'ce0f36a3d870b24f9816634000ea2d2e' => 'Independent JPEG Group library (used by many applications), Quality 69', + 'f7cba1affebd362a322abd45ce580e56' => 'Independent JPEG Group library (used by many applications), Quality 70', + '7b85fffdf97680de53e49788712c50de' => 'Independent JPEG Group library (used by many applications), Quality 71', + '4abd7dbca7735c987eb899b0f8646ce4' => 'Independent JPEG Group library (used by many applications), Quality 72', + '167959a11aff7940df84ed9f3379ed0a' => 'Independent JPEG Group library (used by many applications), Quality 73', + 'd61807da54a72c4651466049c9f67541' => 'Independent JPEG Group library (used by many applications), Quality 74', + '2851eea5e15f1b977c1496a77c884b4f' => 'Independent JPEG Group library (used by many applications), Quality 75', + 'b095631a0665a515d9aa290639f6672b' => 'Independent JPEG Group library (used by many applications), Quality 76', + '0ee4ea4687d3c57d060e3afd2559b7bb' => 'Independent JPEG Group library (used by many applications), Quality 77', + '37e999828e5bc43ee4a470bf29ea97b7' => 'Independent JPEG Group library (used by many applications), Quality 78', + 'dd9b9d09a624deab730d9bd5b8825baa' => 'Independent JPEG Group library (used by many applications), Quality 79', + '5319a82dc93c1ee5c8d2265e4f1fb60e' => 'Independent JPEG Group library (used by many applications), Quality 80', + '6fa04ba1184e986c4da3df8141e05a42' => 'Independent JPEG Group library (used by many applications), Quality 81', + '1d099901cfe37674e4aeb2cdbddf0703' => 'Independent JPEG Group library (used by many applications), Quality 82', + '8cc04e05813c028683e3cb8e6eab79eb' => 'Independent JPEG Group library (used by many applications), Quality 83', + '3eafbf05c0dd233b385856065e456c11' => 'Independent JPEG Group library (used by many applications), Quality 84', + '98dec36fe95ed7c1772d9ed67a67e260' => 'Independent JPEG Group library (used by many applications), Quality 85', + 'a1ee06d19dcb62c7467768d1ba73cf12' => 'Independent JPEG Group library (used by many applications), Quality 86', + '643ad95753c261eacc5ea3f4c9e4d469' => 'Independent JPEG Group library (used by many applications), Quality 87', + '2557828257dd798ad636df350c685a26' => 'Independent JPEG Group library (used by many applications), Quality 88', + 'a5b4bbf018828a3d00e54ab72a175fdc' => 'Independent JPEG Group library (used by many applications), Quality 89', + '50325a7b6e0a9b7f9aea8f5a6f7f31aa' => 'Independent JPEG Group library (used by many applications), Quality 90', + 'c0cf6b0c508a35a13acd8c912548a269' => 'Independent JPEG Group library (used by many applications), Quality 91', + 'ff0aa07a220cd8973a4b86f3ecd4325b' => 'Independent JPEG Group library (used by many applications), Quality 92', + 'f251d4554524d22f94a34668ab17957c' => 'Independent JPEG Group library (used by many applications), Quality 93', + 'cd993be55bad60bb539df0cc2d7f9f6f' => 'Independent JPEG Group library (used by many applications), Quality 94', + 'adf507352f9ce218a4605700459d597f' => 'Independent JPEG Group library (used by many applications), Quality 95', + '9e9e3e22af4e41ea4ec1b8f656f28f42' => 'Independent JPEG Group library (used by many applications), Quality 96', + 'b9f5c003ef62cbd8fc93be6679c1c3bc' => 'Independent JPEG Group library (used by many applications), Quality 97', + '95b6a316836182441b12039279872ec3' => 'Independent JPEG Group library (used by many applications), Quality 98', + 'b9b1ce23552e2f82b95b48de20065ed3' => 'Independent JPEG Group library (used by many applications), Quality 99', + 'a97591462e9b2339efd4f88ca97bb471' => 'Independent JPEG Group library (used by many applications), Quality 100', + + # Independent JPEG Group library (Grayscale) + # + # Tested with: + # - Corel PhotoImpact X3 (Win) + # - IrfanView (Win) + # - Quality mode 0 doesn't exist here + '185893c53196f6156d458a84e1135c43:11' => 'Independent JPEG Group library (used by many applications), Quality 0 or 1 (Grayscale)', + 'b41ccbe66e41a05de5e68832c07969a7:11' => 'Independent JPEG Group library (used by many applications), Quality 2 (Grayscale)', + 'efa024d741ecc5204e7edd4f590a7a25:11' => 'Independent JPEG Group library (used by many applications), Quality 3 (Grayscale)', + '3396344724a1868ada2330ebaeb9448e:11' => 'Independent JPEG Group library (used by many applications), Quality 4 (Grayscale)', + '14276fffb98deb42b7dbce30abb8425f:11' => 'Independent JPEG Group library (used by many applications), Quality 5 (Grayscale)', + 'a99e2826c10d0922ce8942c5437f53a6:11' => 'Independent JPEG Group library (used by many applications), Quality 6 (Grayscale)', + '0d3de456aa5cbb8a2578208250aa9b88:11' => 'Independent JPEG Group library (used by many applications), Quality 7 (Grayscale)', + 'fa987940fdedbe883cc0e9fcc907f89e:11' => 'Independent JPEG Group library (used by many applications), Quality 8 (Grayscale)', + '1c9bb67190ee64e82d3c67f7943bf4a4:11' => 'Independent JPEG Group library (used by many applications), Quality 9 (Grayscale)', + '57d20578d190b04c7667b10d3df241bb:11' => 'Independent JPEG Group library (used by many applications), Quality 10 (Grayscale)', + '619fd49197f0403ce13d86cffec46419:11' => 'Independent JPEG Group library (used by many applications), Quality 11 (Grayscale)', + '327f47dd8f999b2bbb3bb25c43cf5be5:11' => 'Independent JPEG Group library (used by many applications), Quality 12 (Grayscale)', + 'e4e5bc705c40cfaffff6565f16fe98a9:11' => 'Independent JPEG Group library (used by many applications), Quality 13 (Grayscale)', + '6c64fa9ad302624a826f04ecc80459be:11' => 'Independent JPEG Group library (used by many applications), Quality 14 (Grayscale)', + '039a3f0e101f1bcdb6bb81478cf7ae6b:11' => 'Independent JPEG Group library (used by many applications), Quality 15 (Grayscale)', + 'c23b08c94d7537c9447691d54ae1080c:11' => 'Independent JPEG Group library (used by many applications), Quality 16 (Grayscale)', + '200107bc0174104bbf1d4653c4b05058:11' => 'Independent JPEG Group library (used by many applications), Quality 17 (Grayscale)', + '72abfdc6e65b32ded2cd7ac77a04f447:11' => 'Independent JPEG Group library (used by many applications), Quality 18 (Grayscale)', + '1799a236c36da0b30729d9005ca7c7f9:11' => 'Independent JPEG Group library (used by many applications), Quality 19 (Grayscale)', + 'c33a667bff7f590655d196010c5e39f3:11' => 'Independent JPEG Group library (used by many applications), Quality 20 (Grayscale)', + 'b1dc98f6a2f8828f8432872da43e7d94:11' => 'Independent JPEG Group library (used by many applications), Quality 21 (Grayscale)', + '07318a0acfebe9086f0e04a4c4f5398a:11' => 'Independent JPEG Group library (used by many applications), Quality 22 (Grayscale)', + 'a295b7163305f327a5a45ae177a0a19c:11' => 'Independent JPEG Group library (used by many applications), Quality 23 (Grayscale)', + 'c741c1b134cf81ab69acc81f15a67137:11' => 'Independent JPEG Group library (used by many applications), Quality 24 (Grayscale)', + 'a68893776502a591548c7b5bece13e1b:11' => 'Independent JPEG Group library (used by many applications), Quality 25 (Grayscale)', + '111848d9e41f6f408ef70841f90c0519:11' => 'Independent JPEG Group library (used by many applications), Quality 26 (Grayscale)', + '886374ceebcfd4dfed200b0b34b4baca:11' => 'Independent JPEG Group library (used by many applications), Quality 27 (Grayscale)', + '666dd95fd0e20f5c20bc44d78d528869:11' => 'Independent JPEG Group library (used by many applications), Quality 28 (Grayscale)', + '1aa58cb85dda84de2ddf436667124dcd:11' => 'Independent JPEG Group library (used by many applications), Quality 29 (Grayscale)', + '9d321ab2bdda6f3cb76d2d88838aa8c3:11' => 'Independent JPEG Group library (used by many applications), Quality 30 (Grayscale)', + '6ad87d648101c268f83fa379d4c773f2:11' => 'Independent JPEG Group library (used by many applications), Quality 31 (Grayscale)', + 'cdf8e921300f27a4af7661a2de16e91a:11' => 'Independent JPEG Group library (used by many applications), Quality 32 (Grayscale)', + '3f48672e37b6dd2e571b222e4b7ff97d:11' => 'Independent JPEG Group library (used by many applications), Quality 33 (Grayscale)', + 'a53a7d4cc86d01f4c1b867270c9c078f:11' => 'Independent JPEG Group library (used by many applications), Quality 34 (Grayscale)', + '09ec03f5096df106c692123f3fd34296:11' => 'Independent JPEG Group library (used by many applications), Quality 35 (Grayscale)', + 'a946498fd1902c9de87a1f5182966742:11' => 'Independent JPEG Group library (used by many applications), Quality 36 (Grayscale)', + '5d650a1d38108fd79d4f336ba8e254c2:11' => 'Independent JPEG Group library (used by many applications), Quality 37 (Grayscale)', + '81d620f1b470fd535b26544b4ea20643:11' => 'Independent JPEG Group library (used by many applications), Quality 38 (Grayscale)', + '892788bdf8cbef5c6fbd7019a079bf8e:11' => 'Independent JPEG Group library (used by many applications), Quality 39 (Grayscale)', + 'cf3929fd4c1e5c28b7f137f982178ad1:11' => 'Independent JPEG Group library (used by many applications), Quality 40 (Grayscale)', + '31f288945896ed839f1d936bff06fb03:11' => 'Independent JPEG Group library (used by many applications), Quality 41 (Grayscale)', + 'e0c38f0c5e6562445d4e92bae51713be:11' => 'Independent JPEG Group library (used by many applications), Quality 42 (Grayscale)', + '18fa29d1164984883a6af76377b60d5a:11' => 'Independent JPEG Group library (used by many applications), Quality 43 (Grayscale)', + 'eff737b226fbce48c42625c5bf9dabb6:11' => 'Independent JPEG Group library (used by many applications), Quality 44 (Grayscale)', + 'b900f91ee8697255d5daebce858caaeb:11' => 'Independent JPEG Group library (used by many applications), Quality 45 (Grayscale)', + 'ab2f8513823067af242f7e3c04a88a9c:11' => 'Independent JPEG Group library (used by many applications), Quality 46 (Grayscale)', + '60b682c4d412f5255efbaa32787c46ca:11' => 'Independent JPEG Group library (used by many applications), Quality 47 (Grayscale)', + 'ea50813e06203c2ad1165252bcb99a1d:11' => 'Independent JPEG Group library (used by many applications), Quality 48 (Grayscale)', + 'f6308a717437d3653b0751ebf511db0f:11' => 'Independent JPEG Group library (used by many applications), Quality 49 (Grayscale)', + '7c8242581553e818ef243fc680879a19:11' => 'Independent JPEG Group library (used by many applications), Quality 50 (Grayscale)', + 'fc41ab8251718977bc6676f502f457e0:11' => 'Independent JPEG Group library (used by many applications), Quality 51 (Grayscale)', + '606c4c78c0226646bf4d3c5a5898fb17:11' => 'Independent JPEG Group library (used by many applications), Quality 52 (Grayscale)', + '0e6c6a5440d33d25f1c25836a45cfa69:11' => 'Independent JPEG Group library (used by many applications), Quality 53 (Grayscale)', + '7464b2361e5b5f5a9ba74a87475dda91:11' => 'Independent JPEG Group library (used by many applications), Quality 54 (Grayscale)', + 'aeaa2ca48eabb3088ebb713b3c4e1a67:11' => 'Independent JPEG Group library (used by many applications), Quality 55 (Grayscale)', + '3f36450b0ba074578391e77f7340cef0:11' => 'Independent JPEG Group library (used by many applications), Quality 56 (Grayscale)', + 'be232444027e83db6f8d8b79d078442e:11' => 'Independent JPEG Group library (used by many applications), Quality 57 (Grayscale)', + '712c145d6472a2b315b2ecfb916d1590:11' => 'Independent JPEG Group library (used by many applications), Quality 58 (Grayscale)', + 'ae3dd4568cc71c47d068cf831c66b59d:11' => 'Independent JPEG Group library (used by many applications), Quality 59 (Grayscale)', + 'b290e52c21a435fede4586636ef5e287:11' => 'Independent JPEG Group library (used by many applications), Quality 60 (Grayscale)', + 'a09ca4c4391e0221396a08f229a65f9d:11' => 'Independent JPEG Group library (used by many applications), Quality 61 (Grayscale)', + '0818578fc5fc571b4f8d5ffefc9dc0d8:11' => 'Independent JPEG Group library (used by many applications), Quality 62 (Grayscale)', + '7c685e2916555eda34cb37a1e71adc6a:11' => 'Independent JPEG Group library (used by many applications), Quality 63 (Grayscale)', + '69c6b9440342adfc0db89a6c91aba332:11' => 'Independent JPEG Group library (used by many applications), Quality 64 (Grayscale)', + 'd5d484b68e25b44288e67e699829695c:11' => 'Independent JPEG Group library (used by many applications), Quality 65 (Grayscale)', + 'de8310d09116a7a62965f3e0e43ef525:11' => 'Independent JPEG Group library (used by many applications), Quality 66 (Grayscale)', + 'e4735f63e88baf04599afc034e690845:11' => 'Independent JPEG Group library (used by many applications), Quality 67 (Grayscale)', + 'b4ef810b14dee9c6d6d8cace98f799a6:11' => 'Independent JPEG Group library (used by many applications), Quality 68 (Grayscale)', + '52886ef80147c9a136e20b2bc3b76f52:11' => 'Independent JPEG Group library (used by many applications), Quality 69 (Grayscale)', + '9c62dbc848be82ef91219ba9843998be:11' => 'Independent JPEG Group library (used by many applications), Quality 70 (Grayscale)', + 'bfe8c1c73eea84b85673487a82f67627:11' => 'Independent JPEG Group library (used by many applications), Quality 71 (Grayscale)', + 'ea445840d29c51009a2a8cd49b96ccee:11' => 'Independent JPEG Group library (used by many applications), Quality 72 (Grayscale)', + '71c1a56890fff9b0a095fa5a1c96132b:11' => 'Independent JPEG Group library (used by many applications), Quality 73 (Grayscale)', + 'f080b02331ac8adf03de2281042d2b49:11' => 'Independent JPEG Group library (used by many applications), Quality 74 (Grayscale)', + 'd0eaa368737f17f6037757d393a22599:11' => 'Independent JPEG Group library (used by many applications), Quality 75 (Grayscale)', + '303663905d055b77bb547fe0b0beb9c5:11' => 'Independent JPEG Group library (used by many applications), Quality 76 (Grayscale)', + '5cdf1d5bbe19375ad5c7237273dddede:11' => 'Independent JPEG Group library (used by many applications), Quality 77 (Grayscale)', + 'd64e7ff8292fd77131932864d3c9ce7c:11' => 'Independent JPEG Group library (used by many applications), Quality 78 (Grayscale)', + '12b4cc13891c5aef3dadb3405b6fa65d:11' => 'Independent JPEG Group library (used by many applications), Quality 79 (Grayscale)', + 'b008cd63591f8fd366f77d2b224b9c9c:11' => 'Independent JPEG Group library (used by many applications), Quality 80 (Grayscale)', + '49b6e472c7d5ecead593c6009768e765:11' => 'Independent JPEG Group library (used by many applications), Quality 81 (Grayscale)', + 'bce6fa61623ad4f65ff3fec1528cb026:11' => 'Independent JPEG Group library (used by many applications), Quality 82 (Grayscale)', + 'c2b037bf9f5e5baba804d7bbbb2dc73b:11' => 'Independent JPEG Group library (used by many applications), Quality 83 (Grayscale)', + '7fe7b339c6ffc62b984eeab4b0df9168:11' => 'Independent JPEG Group library (used by many applications), Quality 84 (Grayscale)', + '274bbeb0ac3939f90c578ebb1f5a9eef:11' => 'Independent JPEG Group library (used by many applications), Quality 85 (Grayscale)', + '0a0268c655d616b0e4af2851533aa3af:11' => 'Independent JPEG Group library (used by many applications), Quality 86 (Grayscale)', + '52318e260c0d6b3dbee85c87f9b94e63:11' => 'Independent JPEG Group library (used by many applications), Quality 87 (Grayscale)', + 'b64cc19a0f81a506ed5bcfb9c131c8fe:11' => 'Independent JPEG Group library (used by many applications), Quality 88 (Grayscale)', + 'd8c54333eb475b8db9f32f11fe96337e:11' => 'Independent JPEG Group library (used by many applications), Quality 89 (Grayscale)', + '12fe6b9bfd20f4d7f0ac2a221c566c45:11' => 'Independent JPEG Group library (used by many applications), Quality 90 (Grayscale)', + '12aefbf7689633c83da714c9f0e90e05:11' => 'Independent JPEG Group library (used by many applications), Quality 91 (Grayscale)', + 'a3a96add050fc51a2b3ce59a9a491034:11' => 'Independent JPEG Group library (used by many applications), Quality 92 (Grayscale)', + '7b0242bd9aaeab4962f5d5b39b9a4027:11' => 'Independent JPEG Group library (used by many applications), Quality 93 (Grayscale)', + '12fc29c1d8940c93a47ee9d927a17561:11' => 'Independent JPEG Group library (used by many applications), Quality 94 (Grayscale)', + 'e1fedef5184beeb7b0f5c055c7ae1d31:11' => 'Independent JPEG Group library (used by many applications), Quality 95 (Grayscale)', + 'ae9202355f603776794d3e62c43578d6:11' => 'Independent JPEG Group library (used by many applications), Quality 96 (Grayscale)', + '36da00bae6cd81d1f97e32748c07e33f:11' => 'Independent JPEG Group library (used by many applications), Quality 97 (Grayscale)', + '54dc50b16e7cc9bc383eb9e73e85e199:11' => 'Independent JPEG Group library (used by many applications), Quality 98 (Grayscale)', + '23a59c4f9ec045faf9f8379b3ca302bb:11' => 'Independent JPEG Group library (used by many applications), Quality 99 (Grayscale)', + 'bbd2dbcfe20b59e981e9a42cd1eb6ece:11' => 'Independent JPEG Group library (used by many applications), Quality 100 (Grayscale)', + + # Tested with Adobe Photoshop Lightroom 1.4.1 (Win) - "Export" + '683506a889c78d9bc230a0c7ee5f62f3:221111' => 'Adobe Lightroom, Quality 0% - 7%', + 'bc490651af6592cd1dbbbc4fa2cfa1fb:221111' => 'Adobe Lightroom, Quality 8% - 15%', + 'ce4286d9f07999524c3c7472b065c5ab:221111' => 'Adobe Lightroom, Quality 16% - 23%', + 'cbfbfef12aead8841585ef605c789b9f:221111' => 'Adobe Lightroom, Quality 24% - 30%', + 'a0772e73dec2bdc4057c27da47bff376:221111' => 'Adobe Lightroom, Quality 31% - 38%', + '7ef06dbde538346b8b01c6b538ca70c6:221111' => 'Adobe Lightroom, Quality 39% - 46%', + '0ff225f58a214f79d1d85d78f6f5dab8:221111' => 'Adobe Lightroom, Quality 47% - 53%', + '8a8603650fa5ae5fdcf4b2eaf0b23638:111111' => 'Adobe Lightroom, Quality 54% - 61%', + '44f583ed6b65cb8ba915ec5df051616c:111111' => 'Adobe Lightroom, Quality 62% - 69%', + 'de94c5591bafc7456ccaef430271b907:111111' => 'Adobe Lightroom, Quality 70% - 76%', + 'a6841b35e9ffefa5d83a0445dddd2621:111111' => 'Adobe Lightroom, Quality 77% - 84%', + '6e3f6a3a5a1eae6155331d42d6f968dd:111111' => 'Adobe Lightroom, Quality 85% - 92%', + '5379e0133d4439b6f7c7039fc7f7734f:111111' => 'Adobe Lightroom, Quality 93% - 100%', + + # Adobe Photoshop Lightroom 2.1 (Win) - "Export" + # (0-23% equal to Lightroom 1.4.1) + '8453391d3adf377c46a1a0cee08c35c3:221111' => 'Adobe Lightroom, Quality 24% - 30%', + 'f8ede291b1272576d1580e333d30103e:221111' => 'Adobe Lightroom, Quality 31% - 38%', + 'de0fb6d13e12e8df26140dd74691bf0f:221111' => 'Adobe Lightroom, Quality 39% - 46%', + '0d5b0af72561f68c671731f22d9e41e2:221111' => 'Adobe Lightroom, Quality 47% - 53%', + 'b9fd15fd52408af5ea2a5045227233d8:111111' => 'Adobe Lightroom, Quality 54% - 61%', + '27472e3714251402d5509438505611c3:111111' => 'Adobe Lightroom, Quality 62% - 69%', + '34a599dff2b6aaed12143938b7374f2f:111111' => 'Adobe Lightroom, Quality 70% - 76%', + '5c508e529d045b6f0c800e29ba2d6ab5:111111' => 'Adobe Lightroom, Quality 77% - 84%', + '42bfe52476bf07f1ed0e6451903cc9ee:111111' => 'Adobe Lightroom, Quality 85% - 92%', + '4c3c425b4024b68c0de03904a825bc35:111111' => 'Adobe Lightroom, Quality 93% - 100%', + + # Tested with Adobe Photoshop CS2 Version 9.0.2 (Win) - "Save as..." (RGB/CYMK) + '683506a889c78d9bc230a0c7ee5f62f3:221111' => 'Adobe Photoshop, Quality 0', + 'bc490651af6592cd1dbbbc4fa2cfa1fb:221111' => 'Adobe Photoshop, Quality 1', + 'ce4286d9f07999524c3c7472b065c5ab:221111' => 'Adobe Photoshop, Quality 2', + 'cbfbfef12aead8841585ef605c789b9f:221111' => 'Adobe Photoshop, Quality 3', + 'a0772e73dec2bdc4057c27da47bff376:221111' => 'Adobe Photoshop, Quality 4', + '7ef06dbde538346b8b01c6b538ca70c6:221111' => 'Adobe Photoshop, Quality 5', + '0ff225f58a214f79d1d85d78f6f5dab8:221111' => 'Adobe Photoshop, Quality 6', + '8a8603650fa5ae5fdcf4b2eaf0b23638:111111' => 'Adobe Photoshop, Quality 7', + '44f583ed6b65cb8ba915ec5df051616c:111111' => 'Adobe Photoshop, Quality 8', + 'de94c5591bafc7456ccaef430271b907:111111' => 'Adobe Photoshop, Quality 9', + 'a6841b35e9ffefa5d83a0445dddd2621:111111' => 'Adobe Photoshop, Quality 10', + '6e3f6a3a5a1eae6155331d42d6f968dd:111111' => 'Adobe Photoshop, Quality 11', + '5379e0133d4439b6f7c7039fc7f7734f:111111' => 'Adobe Photoshop, Quality 12', + + # Tested with Adobe Photoshop CS2 Version 9.0.2 (Win) - "Save as..." (Grayscale) + '3b0b5975a0e1c9d732c93e1b37a6978b:11' => 'Adobe Photoshop, Quality 0', + 'f4d19ed563e2d0519d6a547088771ddb:11' => 'Adobe Photoshop, Quality 1', + 'e9ef286567fd84a1f479b35ca00db43c:11' => 'Adobe Photoshop, Quality 2', + 'b39cafdb459a42749be3f6459a596677:11' => 'Adobe Photoshop, Quality 3', + 'b3f215deea48e982e205619af279205f:11' => 'Adobe Photoshop, Quality 4', + 'fccd63ce166e198065eaae05c8d78407:11' => 'Adobe Photoshop, Quality 5', + '0a50266ad8d1dff11c90cd1480c0a2be:11' => 'Adobe Photoshop, Quality 6', + '6579941db0216f41f0a20de9b626538a:11' => 'Adobe Photoshop, Quality 7', + '57aa47876e10c6b4f35ecb8889e55ad9:11' => 'Adobe Photoshop, Quality 8', + '076598d43c5186f6d7a1020b64b93625:11' => 'Adobe Photoshop, Quality 9', + '37132e8ea81137fdf26ce30926ab8100:11' => 'Adobe Photoshop, Quality 10', + '46f55ee294723cee9faa816549b3cfa7:11' => 'Adobe Photoshop, Quality 11', + '7b83284f61decf47ab3f8f7361c18943:11' => 'Adobe Photoshop, Quality 12', + + # Tested with Adobe Photoshop CS2 Version 9.0.2 (Win) - "Save for web..." + '9ac881c536e509675e5cf3795a85d9de:221111' => 'Adobe Photoshop, Save for web, Quality 0', + '3521d793fd9d2d9aac85dc4f0be40290:221111' => 'Adobe Photoshop, Save for web, Quality 1', + '041c9e3cf0d34a8b89539e3115bca31b:221111' => 'Adobe Photoshop, Save for web, Quality 2', + '029b3a6f0b92af6786d753788eafabfe:221111' => 'Adobe Photoshop, Save for web, Quality 3', + '6cdd3762e346b16a59af4bddb213b07a:221111' => 'Adobe Photoshop, Save for web, Quality 4', + '84a69c0b43505dd0cbc25d640873b5b9:221111' => 'Adobe Photoshop, Save for web, Quality 5', + '7254c012821f2bc866d7d6dd7906c92d:221111' => 'Adobe Photoshop, Save for web, Quality 6', + '428ba2c747ea4e495ff3c7ff44a988d2:221111' => 'Adobe Photoshop, Save for web, Quality 7', + '42cb001aea7e24d239f6c2fcbd861862:221111' => 'Adobe Photoshop, Save for web, Quality 8', + 'a3698813ce90772a30b6eb9a7deb3f4a:221111' => 'Adobe Photoshop, Save for web, Quality 9', + '301158b292e3232856a765486da26fa6:221111' => 'Adobe Photoshop, Save for web, Quality 10', + '8d9edea9287aa919e433b620f61468dc:221111' => 'Adobe Photoshop, Save for web, Quality 11', + 'c1e0554d8a6ed003eb98e068429b56b9:221111' => 'Adobe Photoshop, Save for web, Quality 12', + '0e0a151e0a52097cbd7683c9385e3a7c:221111' => 'Adobe Photoshop, Save for web, Quality 13', + '911e66f21fe242cc74e0a5738b0330bd:221111' => 'Adobe Photoshop, Save for web, Quality 14', + '028fafd94aa66ee269f58d800c89d838:221111' => 'Adobe Photoshop, Save for web, Quality 15', + '866b8adb1ce7c9dc0e58b7c1e013280f:221111' => 'Adobe Photoshop, Save for web, Quality 16', + '7f712aecf513621f635a007aadda61af:221111' => 'Adobe Photoshop, Save for web, Quality 17', + '38f26622a54ba22accac05f7c0a3b307:221111' => 'Adobe Photoshop, Save for web, Quality 18', + 'd241d5165e64e98024b47dfbf76be88c:221111' => 'Adobe Photoshop, Save for web, Quality 19', + 'afb31cfed194d4e125bde8fd4755bb8a:221111' => 'Adobe Photoshop, Save for web, Quality 20', + '0d501a036c984d2caf49fd298b2d0d16:221111' => 'Adobe Photoshop, Save for web, Quality 21', + '9e992f35767c4aa023b8afd243b247bf:221111' => 'Adobe Photoshop, Save for web, Quality 22', + '0a80e5bf01a9c5650384dfe1a428f61d:221111' => 'Adobe Photoshop, Save for web, Quality 23', + '2501aad23cdf94b25c6df0ab6984b6e0:221111' => 'Adobe Photoshop, Save for web, Quality 24', + '09c168d2e075070d3a2535e7f2e455df:221111' => 'Adobe Photoshop, Save for web, Quality 25', + '63190207beeb805306f7d0bcc3898cb3:221111' => 'Adobe Photoshop, Save for web, Quality 26', + 'e47902bc7ba3037921010c568648c8c3:221111' => 'Adobe Photoshop, Save for web, Quality 27', + '410ed63b6e5225d8b99da6272fd6069b:221111' => 'Adobe Photoshop, Save for web, Quality 28', + 'b40f3f3c46d70a560e2033fadd8c7bb5:221111' => 'Adobe Photoshop, Save for web, Quality 29', + '45148ae63b12ccaa6fb5a487ca7620e9:221111' => 'Adobe Photoshop, Save for web, Quality 30', + '5180e51bd58432c7b51a305ed0c24d1b:221111' => 'Adobe Photoshop, Save for web, Quality 31', + 'c5c472d899462bbe31da9aa8c072c0bc:221111' => 'Adobe Photoshop, Save for web, Quality 32', + '28cdbc95898e02dd0ffc45ba48596ca7:221111' => 'Adobe Photoshop, Save for web, Quality 33', + '42cd88e0eb3c14a705b952550ec2eacd:221111' => 'Adobe Photoshop, Save for web, Quality 34', + '78a2a442aac5cca7fa2ef5a8bd96219e:221111' => 'Adobe Photoshop, Save for web, Quality 35', + '96bce854134a2fccfcb68dca6687cd51:221111' => 'Adobe Photoshop, Save for web, Quality 36', + 'fefd00ec4610895e4294de690f5977e9:221111' => 'Adobe Photoshop, Save for web, Quality 37', + 'd71c8ddb9117920304d83a6f8b7832a4:221111' => 'Adobe Photoshop, Save for web, Quality 38', + '1727e720300403e5f315b5e17ef84d3f:221111' => 'Adobe Photoshop, Save for web, Quality 39', + '8fb05e3c3b0a7404ff6ca54f952d2a5e:221111' => 'Adobe Photoshop, Save for web, Quality 40', + '328ab751ea48f5a8bc7c4b8628138ce0:221111' => 'Adobe Photoshop, Save for web, Quality 41', + 'd9653333a3af8842dd4b72856ac4ef4e:221111' => 'Adobe Photoshop, Save for web, Quality 42', + '276da99e50e1b39134e13826789d655e:221111' => 'Adobe Photoshop, Save for web, Quality 43', + '23f2bd2d96ec531815609503dae4a2b0:221111' => 'Adobe Photoshop, Save for web, Quality 44', + 'bafe2a89809f23bc7367e9a819570728:221111' => 'Adobe Photoshop, Save for web, Quality 45', + '6bfdcd36327406f801be86d0e8ca6b60:221111' => 'Adobe Photoshop, Save for web, Quality 46', + 'eb8e5c42d31b916737ac21dffd6f012b:221111' => 'Adobe Photoshop, Save for web, Quality 47', + 'e57a9878be74473990343573c6585f79:221111' => 'Adobe Photoshop, Save for web, Quality 48', + '91dfacd928ce717cb135c6da03afd907:221111' => 'Adobe Photoshop, Save for web, Quality 49', + '16c443478b9417d44893f8748d49b790:221111' => 'Adobe Photoshop, Save for web, Quality 50', + '84de345dcf710f937a39a0b631b87fc4:111111' => 'Adobe Photoshop, Save for web, Quality 51', + 'bdd6043e7f5a5f1512b99b2394a075e2:111111' => 'Adobe Photoshop, Save for web, Quality 52', + 'c7614d3d384a02630721be335062ef75:111111' => 'Adobe Photoshop, Save for web, Quality 53', + '42d6f71aace3de2ccfdd8348b0198704:111111' => 'Adobe Photoshop, Save for web, Quality 54', + '84d5f059ce3e1b78d91355e1e86e2d1a:111111' => 'Adobe Photoshop, Save for web, Quality 55', + '5881004f575752d77ee00e767d848e51:111111' => 'Adobe Photoshop, Save for web, Quality 56', + '0cb697537acde3d2e85078377461a8e0:111111' => 'Adobe Photoshop, Save for web, Quality 57', + 'b2762ffa5c0a1799fb2e9ad6dfd2171a:111111' => 'Adobe Photoshop, Save for web, Quality 58', + '2b7a6a83259aa9967e098d3e70f1ee09:111111' => 'Adobe Photoshop, Save for web, Quality 59', + '6123a3685e1012af5a0d024de1ce0304:111111' => 'Adobe Photoshop, Save for web, Quality 60', + 'd08c8435de33f2c186aa2dd9cba3e874:111111' => 'Adobe Photoshop, Save for web, Quality 61', + 'e69be2174dbbfb952e54576fbdfe6c14:111111' => 'Adobe Photoshop, Save for web, Quality 62', + '2ec2d5c10641952fce5c435b331b8872:111111' => 'Adobe Photoshop, Save for web, Quality 63', + '98201e1185b7069f1247ac3cdc56c824:111111' => 'Adobe Photoshop, Save for web, Quality 64', + '8fc0325d05c9199bc1e2dec417c3a55e:111111' => 'Adobe Photoshop, Save for web, Quality 65', + '016600f44a61cc5a5673c9bad85e23a3:111111' => 'Adobe Photoshop, Save for web, Quality 66', + '91d7b4300c98c726aff7b19cbe098a3e:111111' => 'Adobe Photoshop, Save for web, Quality 67', + 'f9b83ba21b86a3d4ddb507e3edce490c:111111' => 'Adobe Photoshop, Save for web, Quality 68', + 'd312a23c8ecb3bf59bc11bbe17d79e55:111111' => 'Adobe Photoshop, Save for web, Quality 69', + '240fffe5f8e2d8f3345b8175f9cb0a40:111111' => 'Adobe Photoshop, Save for web, Quality 70', + 'ba60a642bfb1a184c11e5561581d7115:111111' => 'Adobe Photoshop, Save for web, Quality 71', + 'c901580e589f58d309f8b50590cfe214:111111' => 'Adobe Photoshop, Save for web, Quality 72', + 'c244f94d84a016840c6ef06250c58ade:111111' => 'Adobe Photoshop, Save for web, Quality 73', + '3589227bdd85f880f3337b492e895c5d:111111' => 'Adobe Photoshop, Save for web, Quality 74', + 'cae6fd91a423ff181d50bb9c26a0d392:111111' => 'Adobe Photoshop, Save for web, Quality 75', + '7d8ee11ca66d2c22ff9ed1f778b5dbac:111111' => 'Adobe Photoshop, Save for web, Quality 76', + 'a16371762ce48953d42dfb5b77d1bfc6:111111' => 'Adobe Photoshop, Save for web, Quality 77', + '204b111d4aaa85b430e86273a63fd004:111111' => 'Adobe Photoshop, Save for web, Quality 78', + '6a243ac0b8575c2ed962070cd7d39e04:111111' => 'Adobe Photoshop, Save for web, Quality 79', + '51879d6e5178d2282d5e8276ed4e2439:111111' => 'Adobe Photoshop, Save for web, Quality 80', + 'ca683ab6caaa3132bf661a0ebf32ef4e:111111' => 'Adobe Photoshop, Save for web, Quality 81', + '5399adc3f21ecb30c96d6a94b38ab74c:111111' => 'Adobe Photoshop, Save for web, Quality 82', + '43eb3b161279ccc1fb4f9cbe7b92398f:111111' => 'Adobe Photoshop, Save for web, Quality 83', + '2d387641f4e94b6986908b3770fb762e:111111' => 'Adobe Photoshop, Save for web, Quality 84', + '75ee5a0fd61559c6bf8e6ebc920c93b0:111111' => 'Adobe Photoshop, Save for web, Quality 85', + '60d17e041a23d47b96c5aac86180a022:111111' => 'Adobe Photoshop, Save for web, Quality 86', + '8e5290b1d12832ad259de92a53e1ef4e:111111' => 'Adobe Photoshop, Save for web, Quality 87', + 'dc19a48af9051bbdc54cf7e88c03f13e:111111' => 'Adobe Photoshop, Save for web, Quality 88', + 'c3fbc85c803ddc81c8882c03330b5b15:111111' => 'Adobe Photoshop, Save for web, Quality 89', + '5e016a2d28f8ad3e7e27e4e2981031d2:111111' => 'Adobe Photoshop, Save for web, Quality 90', + 'ef4fa43f4d548e0687c4d4151a0bf1bd:111111' => 'Adobe Photoshop, Save for web, Quality 91', + '00f03e367cd316b71de360c6e7af0e6b:111111' => 'Adobe Photoshop, Save for web, Quality 92', + '982fc46fd167df238fbf23494a1ce761:111111' => 'Adobe Photoshop, Save for web, Quality 93', + '6fd7b56ac6b58dc861e6021815fb5704:111111' => 'Adobe Photoshop, Save for web, Quality 94', + 'c6d9120293c8435cf6b40574b45756bb:111111' => 'Adobe Photoshop, Save for web, Quality 95', + '1e133f4bf9f7c7c1e0accf44c0b1107d:111111' => 'Adobe Photoshop, Save for web, Quality 96', + 'fb91d6a8a1b72388d68130f551698865:111111' => 'Adobe Photoshop, Save for web, Quality 97', + '4ea4e07900e04a3bd7572d4b59aa7a74:111111' => 'Adobe Photoshop, Save for web, Quality 98', + '15e1d2321b96b355d4ad109a8d2fe882:111111' => 'Adobe Photoshop, Save for web, Quality 99', + '234d8f310d75effc9f77beb1d3847f49:111111' => 'Adobe Photoshop, Save for web, Quality 100', + + # Adobe Photoshop Express (Release build number: 481589) + 'aeb34eb083acc888770d65e691497bcf:111111' => 'Adobe Photoshop Express, Original Size', + + # Apple QuickTime (Color) + # + # Tested with: + # - QuickTime 7.5.0 (Win) + # - QuickTime 7.5.0 (Mac) + # - QuickTime 7.4.1 (Mac) + # - GraphicConverter 4.4.4 (Mac) + # - Using the QuickTime library + # - Fixed subsampling to 221111 + # - Use a subset of 101 of the 1024 values + 'dbdc6a6f3c9ffff19e67cfad2cc51ae4:221111' => 'Apple QuickTime, Quality 0-63 (0-6%)', + '23bd5edb6224e03e2f7c282e04986553:221111' => 'Apple QuickTime, Quality 64-80 (6-8%)', + '69747272d4079b78c2ee2ef0f5e63f30:221111' => 'Apple QuickTime, Quality 81-92 (8-9%)', + '4f50903ec9314f739e460c79552a20c5:221111' => 'Apple QuickTime, Quality 93-101 (9-10%)', + '2535e621267a9ff2e2d09148643e3389:221111' => 'Apple QuickTime, Quality 102-109 (10-11%)', + '46a125048b572576eed271816b2cbad2:221111' => 'Apple QuickTime, Quality 110-116 (11%)', + 'ce05e4b45c53a6e321d9cf1061c62128:221111' => 'Apple QuickTime, Quality 117-122 (11-12%)', + 'c3b80241282d06ac5114f2750089589a:221111' => 'Apple QuickTime, Quality 123-127 (12%)', + '9d91481900305fb9ad09339f0924f690:221111' => 'Apple QuickTime, Quality 128-133 (13%)', + '348f4874d57ae6aae04ef96132374913:221111' => 'Apple QuickTime, Quality 134-137 (13%)', + '4e3daadebe0517955b1c86fb1fbc1dc1:221111' => 'Apple QuickTime, Quality 138-142 (13-14%)', + '599b6ad93f32b9d5ce67e1622338c379:221111' => 'Apple QuickTime, Quality 143-146 (14%)', + '66aeb0f03343673eeed6462e0ce9e1aa:221111' => 'Apple QuickTime, Quality 147-150 (14-15%)', + '13570e05da917fe51235ef66a295bc78:221111' => 'Apple QuickTime, Quality 151-154 (15%)', + '25e399a9cf70fe7a13867b40ac2c3416:221111' => 'Apple QuickTime, Quality 155-157 (15%)', + '25eb3d27e65659435a89e401edfab65f:221111' => 'Apple QuickTime, Quality 158-161 (15-16%)', + 'c3bb3c557e70b56a890b07236348518b:221111' => 'Apple QuickTime, Quality 162-164 (16%)', + '792e93c41ac63451068b887b11ad0c2e:221111' => 'Apple QuickTime, Quality 165-167 (16%)', + '35af99d11406974cf2ffa6676801b10c:221111' => 'Apple QuickTime, Quality 168-170 (16-17%)', + '606e5652fc33c6a02328f0bd23ee9751:221111' => 'Apple QuickTime, Quality 171-173 (17%)', + '9b62a9e4544cbc1033c67732ea0bbb08:221111' => 'Apple QuickTime, Quality 174-176 (17%)', + '93ef48999d5659763a33c45a2a0fa784:221111' => 'Apple QuickTime, Quality 177-179 (17%)', + '01b48291bfeccf2fadab996816225b9b:221111' => 'Apple QuickTime, Quality 180-182 (18%)', + '613ef896fc4af5baad36e2680968a7ba:221111' => 'Apple QuickTime, Quality 183-184 (18%)', + '758d37a9d3b91c0ba383d23f5a080d8f:221111' => 'Apple QuickTime, Quality 185-187 (18%)', + '34457d32b9531f04696a52969e02dc1a:221111' => 'Apple QuickTime, Quality 188-189 (18%)', + '6634cdad61e7a8e6fb3a4ba1a0416256:221111' => 'Apple QuickTime, Quality 190-191 (19%)', + 'e5b0739f8e02c6d481e0cdafe7326ae2:221111' => 'Apple QuickTime, Quality 192-194 (19%)', + 'fca91c73d4275748587f97b472b59280:221111' => 'Apple QuickTime, Quality 195-196 (19%)', + '7dc9316230c4f197fb5d1b36f09cd883:221111' => 'Apple QuickTime, Quality 197-198 (19%)', + '13d6536913342860ab993be8b141f644:221111' => 'Apple QuickTime, Quality 199-201 (19-20%)', + 'd835580b2be669d4aa6c68ead27c0c2f:221111' => 'Apple QuickTime, Quality 202-203 (20%)', + '1e91365abfe1d9f7a008c363c834a66e:221111' => 'Apple QuickTime, Quality 204-205 (20%)', + '6f7825365b673f9eb2ac050d27a21d1b:221111' => 'Apple QuickTime, Quality 206-207 (20%)', + '2a98c0b884281080eefcdf98dd33fd6b:221111' => 'Apple QuickTime, Quality 208-209 (20%)', + '0ffe7e9fc17393a338b95c345052b7c5:221111' => 'Apple QuickTime, Quality 210-211 (21%)', + '9dd5c9717d0fd45486af4d26e59ebb35:221111' => 'Apple QuickTime, Quality 212-213 (21%)', + '0ef85155f08194f8fed3f4e7197126e6:221111' => 'Apple QuickTime, Quality 214-215 (21%)', + '35886289b5c8921f7932f895d7f1855d:221111' => 'Apple QuickTime, Quality 216-217 (21%)', + '1d7ac617d70b1880be9c7ba16f96a3ec:221111' => 'Apple QuickTime, Quality 218 (21%)', + 'b26a53dce1477ac3970335df110bb240:221111' => 'Apple QuickTime, Quality 219-220 (21%)', + 'a333be9f2b13b53bfdf64bf5665f8e55:221111' => 'Apple QuickTime, Quality 221-222 (22%)', + 'f1e8d9b3d66fa34ec9a51a987b48a159:221111' => 'Apple QuickTime, Quality 223-224 (22%)', + '20f37f34a9fd18089aa58fe77493a7b7:221111' => 'Apple QuickTime, Quality 225 (22%)', + 'b80e56d3ed0c4a8e1c6bb0c5a1d45ca9:221111' => 'Apple QuickTime, Quality 226-227 (22%)', + 'd14411ab659ac68209ee8c75b941cb48:221111' => 'Apple QuickTime, Quality 228-229 (22%)', + 'a5da49ac5bfe27aafda44bae107ae1c5:221111' => 'Apple QuickTime, Quality 230 (22%)', + '9aa9359126240c0712610121371f870c:221111' => 'Apple QuickTime, Quality 231-232 (23%)', + '5975500a23ab9a547ba149bf1aaa1893:221111' => 'Apple QuickTime, Quality 233-234 (23%)', + 'd03a4790dd96a862113b1a2408103ad6:221111' => 'Apple QuickTime, Quality 235 (23%)', + '44d2a7baaf1e3f8c3d45e4e6272a39b1:221111' => 'Apple QuickTime, Quality 236-237 (23%)', + '7755ba223679105c184be0ada8c99f92:221111' => 'Apple QuickTime, Quality 238 (23%)', + '1ea3f373d0adf989e8416ecb11c38608:221111' => 'Apple QuickTime, Quality 239-240 (23%)', + '12196a46c697fbb88d8bef279b52b106:221111' => 'Apple QuickTime, Quality 241 (24%)', + '2183a6f77fe72f5c70726244dcabc963:221111' => 'Apple QuickTime, Quality 242-243 (24%)', + 'd1ca3a3723c1385d2989b199a7a30557:221111' => 'Apple QuickTime, Quality 244 (24%)', + 'd83207842d60965f9d194d89f3281ccd:221111' => 'Apple QuickTime, Quality 245-246 (24%)', + '6ae041573525edd42e800e1b61d4313c:221111' => 'Apple QuickTime, Quality 247 (24%)', + '6c42d12564d1c5706653a8ddb5375192:221111' => 'Apple QuickTime, Quality 248-249 (24%)', + '671a071a1b17f49a774da3893f7199c7:221111' => 'Apple QuickTime, Quality 250 (24%)', + 'fb3c0cc15ad21b6c19576dd8d7d29a0e:221111' => 'Apple QuickTime, Quality 251 (25%)', + 'c9ce3dc3d0567f631e463cc3ff1b2e30:221111' => 'Apple QuickTime, Quality 252-253 (25%)', + 'b309a0dc90b16ac01f0798a04c3127e8:221111' => 'Apple QuickTime, Quality 254 (25%)', + 'cd15038a76bd8752c3afd14669816c2e:221111' => 'Apple QuickTime, Quality 255 (25%)', + 'd275e9aebd39cf411496caf6e54d0c5f:221111' => 'Apple QuickTime, Quality 256-257 (25%)', + '5e75328df5dadca132bb83e0883ce522:221111' => 'Apple QuickTime, Quality 258 (25%)', + 'b04cbc1812939770d59461982cd9d32d:221111' => 'Apple QuickTime, Quality 259 (25%)', + 'ddf1f3b922ea51f6f4ca3cb6863eeae0:221111' => 'Apple QuickTime, Quality 260-261 (25%)', + '5532e398abb0a455b528659e59c7cfd7:221111' => 'Apple QuickTime, Quality 262 (26%)', + 'f9bff3eeb4e94fb9ab4820184b0b6058:221111' => 'Apple QuickTime, Quality 263 (26%)', + '081da80ed314194b571ff9880a7c11d3:221111' => 'Apple QuickTime, Quality 264-265 (26%)', + '178aa0138d7a08be081aeff794956a71:221111' => 'Apple QuickTime, Quality 266 (26%)', + '78bb04e3ced3eee51c78e94b421ecc26:221111' => 'Apple QuickTime, Quality 267 (26%)', + '17782e930dc2cba42da909d95278fe9b:221111' => 'Apple QuickTime, Quality 268 (26%)', + '093b011ce21ae794d3eca7c64eecf5b6:221111' => 'Apple QuickTime, Quality 269 (26%)', + '4bf515768d1a06e4c529ebae3e03b4b5:221111' => 'Apple QuickTime, Quality 270-271 (26%)', + '3dd79429ada0455422ff6605c1727456:221111' => 'Apple QuickTime, Quality 272 (27%)', + '4be1504b9732d1d9f6265d0616bad21b:221111' => 'Apple QuickTime, Quality 273 (27%)', + 'b2118dc8e8b1762cc634e135a2a1893c:221111' => 'Apple QuickTime, Quality 274 (27%)', + '70d843457698f46db30181ac616deb75:221111' => 'Apple QuickTime, Quality 275 (27%)', + 'f3c42f077883313db21c72bd240de05f:221111' => 'Apple QuickTime, Quality 276 (27%)', + '56e9a02eb25508a9f71ad1a7cb9f9f4d:221111' => 'Apple QuickTime, Quality 277-278 (27%)', + '1d956197da5eb19ffe8855a0e2a52c98:221111' => 'Apple QuickTime, Quality 279 (27%)', + '3e37de5c00962684feba769939fce685:221111' => 'Apple QuickTime, Quality 280 (27%)', + '5628aeb29bb04d9c5073bc1caf371f01:221111' => 'Apple QuickTime, Quality 281 (27%)', + 'a2e7b219d18177294378485759215f72:221111' => 'Apple QuickTime, Quality 282 (28%)', + '537f40d0aae588fbce4cde9ba148604d:221111' => 'Apple QuickTime, Quality 283 (28%)', + '14b7d58b539ad8d6f1c4f8fd82c91358:221111' => 'Apple QuickTime, Quality 284 (28%)', + '58b302794024b9842657bbe7cb667577:221111' => 'Apple QuickTime, Quality 285 (28%)', + '4be64c2782cbb36b757cdcadd756498a:221111' => 'Apple QuickTime, Quality 286 (28%)', + '6c947f09bc02f87b257a26f9f5c77a77:221111' => 'Apple QuickTime, Quality 287 (28%)', + '663b8a9dbd00efa78281f5028b35c503:221111' => 'Apple QuickTime, Quality 288 (28%)', + 'e5deb190a5e17492a01e8136afdfd6c1:221111' => 'Apple QuickTime, Quality 289 (28%)', + 'ba36e1298ce7fed908ee3e02b83ae7c3:221111' => 'Apple QuickTime, Quality 290 (28%)', + 'bc4abc4600f2efc0bdead1e4be78801b:221111' => 'Apple QuickTime, Quality 291-292 (28-29%)', + '43887ad276efb9ca8e8110498b38d814:221111' => 'Apple QuickTime, Quality 293 (29%)', + '3050624718ce9acc06f85c2fa0208cc7:221111' => 'Apple QuickTime, Quality 294 (29%)', + 'f6d9c8699e54823040b66c4b8e1361aa:221111' => 'Apple QuickTime, Quality 295 (29%)', + 'a9b2875fc3c21e7b998969c57f74fa7a:221111' => 'Apple QuickTime, Quality 296 (29%)', + 'b9be740b8a374a52808ad5ef6db2bfe7:221111' => 'Apple QuickTime, Quality 297 (29%)', + '63f9786c6a9b8ef87c791818ddaba058:221111' => 'Apple QuickTime, Quality 298 (29%)', + 'a65113fd3b66ef137f9b1144367f731b:221111' => 'Apple QuickTime, Quality 299 (29%)', + 'ee58773aa7b774040d650365937cf173:221111' => 'Apple QuickTime, Quality 300 (29%)', + '29a9ee0cae41784d90fa74d7cd240a3e:221111' => 'Apple QuickTime, Quality 301 (29%)', + '369e1cfc338b45a239cb7db09778037e:221111' => 'Apple QuickTime, Quality 302 (29%)', + '131ddd6eec5f51e825cf7afd9c7ab3b2:221111' => 'Apple QuickTime, Quality 303 (30%)', + '88a2772be7b74a5a9b7ebbea28ddde47:221111' => 'Apple QuickTime, Quality 304 (30%)', + '83e206dafb515f20a4b9a0c16f770940:221111' => 'Apple QuickTime, Quality 305 (30%)', + 'dddc3adae44a64457b05416affc2502e:221111' => 'Apple QuickTime, Quality 306 (30%)', + 'ff0758d87a0cbdb323fb93bf9ed1fdff:221111' => 'Apple QuickTime, Quality 307 (30%)', + 'b1b1a08ebaf13142b731c95771d97226:221111' => 'Apple QuickTime, Quality 308 (30%)', + 'd6e206f8224d6a3582fb1066b511437b:221111' => 'Apple QuickTime, Quality 309 (30%)', + '2926d6bf5a27174bd9057bd6198413cd:221111' => 'Apple QuickTime, Quality 310 (30%)', + '5d1b5e80f9777a636d1d5cb402fcfc32:221111' => 'Apple QuickTime, Quality 311 (30%)', + 'ae39c8775a10e34accdf2bba3bffc483:221111' => 'Apple QuickTime, Quality 312 (30%)', + 'bc6d3a9f349a97c5cde3f8fa4e1b5beb:221111' => 'Apple QuickTime, Quality 313 (31%)', + '91bd468ca96fe548a7df9646b51880d1:221111' => 'Apple QuickTime, Quality 314 (31%)', + '104c3b63e4ca667a4ee2e4250340052c:221111' => 'Apple QuickTime, Quality 315 (31%)', + '64b80be38604eaecc99236b1f74a99f8:221111' => 'Apple QuickTime, Quality 316 (31%)', + '284efada45882694778e65969f761478:221111' => 'Apple QuickTime, Quality 317 (31%)', + 'd8bd88390c27b2b05a0784eafd4b31ef:221111' => 'Apple QuickTime, Quality 318 (31%)', + '99bf8158a4060d354b521f3d6f5648ac:221111' => 'Apple QuickTime, Quality 319 (31%)', + '96c9e3cd827097ec03edc458fc1053e4:221111' => 'Apple QuickTime, Quality 320 (31%)', + '272b5b12f7701be4cceba51e9d5dbf13:221111' => 'Apple QuickTime, Quality 321 (31%)', + 'dcc3ffcda228ab283d53e1dc2cb739ef:221111' => 'Apple QuickTime, Quality 322-324 (31-32%)', + 'c44701e8185306f5e6d09be16a2b0fbd:221111' => 'Apple QuickTime, Quality 325 (32%)', + '476a1ebd043ed59e56d18dd6d08777d7:221111' => 'Apple QuickTime, Quality 326 (32%)', + '26831dfc8d0dc1d202d50d6cf7b4f4a4:221111' => 'Apple QuickTime, Quality 327 (32%)', + '00f929d549fdd9f89fbb10303445cc2c:221111' => 'Apple QuickTime, Quality 328 (32%)', + '030736cda242f0583a7064cb60cc026e:221111' => 'Apple QuickTime, Quality 329 (32%)', + '825fb58744c6c2432d232f5fb83a9597:221111' => 'Apple QuickTime, Quality 330 (32%)', + '0bac94d5b6ef090da7875e294a7f8040:221111' => 'Apple QuickTime, Quality 331 (32%)', + '16de07616490b8439576d837c74aefbe:221111' => 'Apple QuickTime, Quality 332 (32%)', + '8190e844832ee8ea97492b509c728de4:221111' => 'Apple QuickTime, Quality 333 (33%)', + '0bb6bf7365676f75d285bb38a40b8e3f:221111' => 'Apple QuickTime, Quality 334 (33%)', + '04710d4ba5233b4f82bd260263f9e992:221111' => 'Apple QuickTime, Quality 335 (33%)', + 'fcb49e821b83f8436d450b03f1b1f182:221111' => 'Apple QuickTime, Quality 336 (33%)', + '1bca645051a125cd2c3af262074f70e7:221111' => 'Apple QuickTime, Quality 337 (33%)', + '7a5c04b63f9fe6af176efef387ba1f03:221111' => 'Apple QuickTime, Quality 338 (33%)', + '24fff8dcfdc8640225fff020ad869c18:221111' => 'Apple QuickTime, Quality 339 (33%)', + '08549fa433585b86d6eab75b6dcb1fe3:221111' => 'Apple QuickTime, Quality 340 (33%)', + 'caabe462a50217592c74902def037c07:221111' => 'Apple QuickTime, Quality 341 (33%)', + '757e97f3490ebc5b74fd63792fb23992:221111' => 'Apple QuickTime, Quality 342 (33%)', + 'aa6072a632f7bae361c8d371aa022c57:221111' => 'Apple QuickTime, Quality 343 (33%)', + '03809d08372d3a9fd86ff254854f45b7:221111' => 'Apple QuickTime, Quality 344 (34%)', + 'bdebcafc7b5f6b7fea114943e042df5e:221111' => 'Apple QuickTime, Quality 345 (34%)', + '555dc90fb10df448f37c67ee7ec31bc2:221111' => 'Apple QuickTime, Quality 346 (34%)', + 'a2f2a404cd1c2278ef65f2a27c0365e0:221111' => 'Apple QuickTime, Quality 347 (34%)', + 'aee867276d6dc4ed4b682a454815acd1:221111' => 'Apple QuickTime, Quality 348 (34%)', + '8f2f9e8433104cedb50c3e54577fcd00:221111' => 'Apple QuickTime, Quality 349 (34%)', + '84c2067991afbb6851204f21f5d132ea:221111' => 'Apple QuickTime, Quality 350 (34%)', + '2d2a77bf6078ab4f07261c76b637b597:221111' => 'Apple QuickTime, Quality 351 (34%)', + 'fc9d0f82571701e8b4cf764125ac0d2e:221111' => 'Apple QuickTime, Quality 352 (34%)', + '75d4ffdc6c10675cb1b5bd002d4e0e41:221111' => 'Apple QuickTime, Quality 353 (34%)', + '4b96c3457701c201f90d56af1a82d43b:221111' => 'Apple QuickTime, Quality 354 (35%)', + 'a56edeb9e571dc790a429c26ebc59976:221111' => 'Apple QuickTime, Quality 355 (35%)', + '3673ce9ec4f6f916009d39282ff3a8d7:221111' => 'Apple QuickTime, Quality 356 (35%)', + 'b7279ade733ff1c88073971cebe6edd8:221111' => 'Apple QuickTime, Quality 357 (35%)', + 'b35f3358027aa4d2cca0c64425aa8f1b:221111' => 'Apple QuickTime, Quality 358 (35%)', + '854d2e536bc92a9e2e3db3ff2c18e138:221111' => 'Apple QuickTime, Quality 359 (35%)', + '48b6aa4f0258162cceb9d43e19c96043:221111' => 'Apple QuickTime, Quality 360 (35%)', + '1dfb48b5955cf2a50011f52b9a05f1a4:221111' => 'Apple QuickTime, Quality 361 (35%)', + 'd67da3fcbac8975acffe7f1ab088f646:221111' => 'Apple QuickTime, Quality 362 (35%)', + '7be7bded72d0ade6f907e3adcf62b391:221111' => 'Apple QuickTime, Quality 363 (35%)', + '02c0554e4a004ceaddd0d7772e68a38b:221111' => 'Apple QuickTime, Quality 364 (36%)', + 'e7b9303f785f78a2cb27f83616c18726:221111' => 'Apple QuickTime, Quality 365 (36%)', + '4a4a154781db3f5f500e8cf177a4b446:221111' => 'Apple QuickTime, Quality 366 (36%)', + '7e4b44f2900a405e7b85090af7d40298:221111' => 'Apple QuickTime, Quality 367 (36%)', + '76aa290370382de8a3516f73389f9350:221111' => 'Apple QuickTime, Quality 368 (36%)', + '912779b5b7c935f2b533af0f400402f3:221111' => 'Apple QuickTime, Quality 369 (36%)', + '91c7f694fbf07321037a838c3a4d6e7d:221111' => 'Apple QuickTime, Quality 370 (36%)', + 'f98a4286abf1cbe8bf46fba1e78cec61:221111' => 'Apple QuickTime, Quality 371 (36%)', + '2fbbcce5a035d6215e4851a0ae63481f:221111' => 'Apple QuickTime, Quality 372 (36%)', + '8d8fab3b6b7386a4e81f10c15a7abaa5:221111' => 'Apple QuickTime, Quality 373 (36%)', + '82e672854d7e00d47a988855b95d2f7f:221111' => 'Apple QuickTime, Quality 374 (37%)', + '9fffe6b2fbbce23598c19e6cd177adb0:221111' => 'Apple QuickTime, Quality 375 (37%)', + '3f69293a4abeb2201004e7241fe22c75:221111' => 'Apple QuickTime, Quality 376 (37%)', + 'a01d3a7766c7c593a79ff6c63433860a:221111' => 'Apple QuickTime, Quality 377 (37%)', + '787ed74c3d5570c03f98804bc9d0c448:221111' => 'Apple QuickTime, Quality 378 (37%)', + '12239aa16bb4091d8f873f9536e40371:221111' => 'Apple QuickTime, Quality 379 (37%)', + 'f45d495d3b470eadba70bcca888042b3:221111' => 'Apple QuickTime, Quality 380 (37%)', + '97346edee67c3afea7823c72e57cb6c5:221111' => 'Apple QuickTime, Quality 381 (37%)', + '5b35e4bc9cbbc353b8e4b73132324088:221111' => 'Apple QuickTime, Quality 382 (37%)', + 'a43b370edaaee853bb16e46ee4a002e8:221111' => 'Apple QuickTime, Quality 383 (37%)', + '7f3d110973a4d7d5824724c4e577b407:221111' => 'Apple QuickTime, Quality 384 (38%)', + '0e36104efe90a5a77e9b686d0a6528ab:221111' => 'Apple QuickTime, Quality 385 (38%)', + '0bc0941c2a59d9a12b66d1d34117cfd7:221111' => 'Apple QuickTime, Quality 386 (38%)', + '342e3bddb81140ea9df00400a46461d7:221111' => 'Apple QuickTime, Quality 387 (38%)', + 'ad8bbd6b23b87950d1b76278fbb7de87:221111' => 'Apple QuickTime, Quality 388 (38%)', + 'd58f5d339b69e1296911a3387cc664a4:221111' => 'Apple QuickTime, Quality 389 (38%)', + 'c740804ef8493bb467744e1cdb8882c1:221111' => 'Apple QuickTime, Quality 390 (38%)', + 'ab975404bdb713bb6a58ac560330aaf1:221111' => 'Apple QuickTime, Quality 391 (38%)', + 'eb68a0ff9c83267e5fb5e998365b4480:221111' => 'Apple QuickTime, Quality 392 (38%)', + '9c1865e7fdc0289dc5fe8f4c1f65577e:221111' => 'Apple QuickTime, Quality 393 (38%)', + '21db4122ad8183006542018e53e0c653:221111' => 'Apple QuickTime, Quality 394 (38%)', + '734255167cbd052200fb4c474f05bcd9:221111' => 'Apple QuickTime, Quality 395 (39%)', + 'e5dcd017a9734f9f0e18b515c7fa1787:221111' => 'Apple QuickTime, Quality 396 (39%)', + 'c58a47c2e3dc737b9591420812b9cc27:221111' => 'Apple QuickTime, Quality 397 (39%)', + 'ea25d0beaa91434a14348fb60f5cff31:221111' => 'Apple QuickTime, Quality 398 (39%)', + '21f8a4a67742edcde0ac854522028c9f:221111' => 'Apple QuickTime, Quality 399 (39%)', + '8b8dc34912d8b18742a7670be4b1c867:221111' => 'Apple QuickTime, Quality 400 (39%)', + 'f7adac1fb54bb1fc566b66822122a9c6:221111' => 'Apple QuickTime, Quality 401 (39%)', + '0fe0c7e65c0696d9e76ad819d61e44ae:221111' => 'Apple QuickTime, Quality 402 (39%)', + '6dabf05ddc213b650ff08aa9a8cb9f50:221111' => 'Apple QuickTime, Quality 403 (39%)', + '226788e417078cdcc5aa989379b9e824:221111' => 'Apple QuickTime, Quality 404 (39%)', + '9366dde6c37f4cac36a8e8cea4d5f51c:221111' => 'Apple QuickTime, Quality 405 (40%)', + '3ce5057aaf0ff155ee69d66591c8290d:221111' => 'Apple QuickTime, Quality 406 (40%)', + '58fe81014a9ee26a7bd393c8e31f4011:221111' => 'Apple QuickTime, Quality 407 (40%)', + '41e44bae14ab49d1b0f06438d34cb316:221111' => 'Apple QuickTime, Quality 408 (40%)', + '80ccbe5645cc62ebd4ae7b2128b42d91:221111' => 'Apple QuickTime, Quality 409 (40%)', + 'b08af3cffd1904e8a8cfbbba71077069:221111' => 'Apple QuickTime, Quality 410 (40%)', + 'abb56efe234d4b8fdf50016a19c63684:221111' => 'Apple QuickTime, Quality 411 (40%)', + 'e41806d0928fbb5552225e10db7b55d0:221111' => 'Apple QuickTime, Quality 412 (40%)', + 'ae9de0a8343d730e2e6a358849c29a4e:221111' => 'Apple QuickTime, Quality 413 (40%)', + 'b83146f54d17b2c8e242f7f36dc36f19:221111' => 'Apple QuickTime, Quality 414 (40%)', + 'a748fdfe8d6dc9493253908410e517eb:221111' => 'Apple QuickTime, Quality 415 (41%)', + 'd4bb4c59b5284630a4c716a0290d9091:221111' => 'Apple QuickTime, Quality 416 (41%)', + 'de93dd8ab7918b25f191923f4a43a5c2:221111' => 'Apple QuickTime, Quality 417 (41%)', + '0807f8b3b41b01054509858fa74dcf4d:221111' => 'Apple QuickTime, Quality 418 (41%)', + 'efd780e10dcd0ab8ca0a0f4f3cb215d3:221111' => 'Apple QuickTime, Quality 419 (41%)', + '2ec3d0ec37690e40f009b7a9f9b17c49:221111' => 'Apple QuickTime, Quality 420 (41%)', + 'a4680e71907e5c6f7b18e20e46286412:221111' => 'Apple QuickTime, Quality 421 (41%)', + '8e54abf2320cca661b6dd67b7658c9f3:221111' => 'Apple QuickTime, Quality 422 (41%)', + '00f76480eafd05aa5267053aec3aa122:221111' => 'Apple QuickTime, Quality 423 (41%)', + '849bce1254b14d44e24a6b419c385597:221111' => 'Apple QuickTime, Quality 424 (41%)', + '8a91452f2df82874183be50601242106:221111' => 'Apple QuickTime, Quality 425 (42%)', + 'a670182cd48f37dd16652db878791a7a:221111' => 'Apple QuickTime, Quality 426 (42%)', + 'c2afe9aca67de0276a6fb507861c3e80:221111' => 'Apple QuickTime, Quality 427 (42%)', + '18836b72e5399e2a19cd6420562ab1ff:221111' => 'Apple QuickTime, Quality 428 (42%)', + 'cb207af75faf8ee1ef0ca3caa593bb69:221111' => 'Apple QuickTime, Quality 429 (42%)', + '7a318965f27e3c09d11f53cbb10a872b:221111' => 'Apple QuickTime, Quality 430 (42%)', + 'b0a501129cb83e54f97006610ec9ed64:221111' => 'Apple QuickTime, Quality 431 (42%)', + 'f1a8af8c0abe4b3423d5ac8c6273a7ca:221111' => 'Apple QuickTime, Quality 432 (42%)', + '56224ea0ac2fccb92cbe9702896f9796:221111' => 'Apple QuickTime, Quality 433 (42%)', + '2f2101a8450c617a09ccad472c275b88:221111' => 'Apple QuickTime, Quality 434 (42%)', + '13e218420429e2c94d4b9474ab03f8e4:221111' => 'Apple QuickTime, Quality 435 (42%)', + '41061e1cdb97926ed5bded3da11af209:221111' => 'Apple QuickTime, Quality 436 (43%)', + 'cc3e4dc4e190d00a12bd03199efdcc6d:221111' => 'Apple QuickTime, Quality 437 (43%)', + '36b2371ec6df13143af12d600232c2ab:221111' => 'Apple QuickTime, Quality 438 (43%)', + '71d0e3444a4c82cf39048ba8cf7b1d5f:221111' => 'Apple QuickTime, Quality 439 (43%)', + '9f48e71f610caa47b94d3e474608cb3d:221111' => 'Apple QuickTime, Quality 440 (43%)', + 'dcecd4f366d521e118e94d87ef915caa:221111' => 'Apple QuickTime, Quality 441 (43%)', + 'cf0a070dc9b4a8983b50f8e3f105b857:221111' => 'Apple QuickTime, Quality 442 (43%)', + '5504a428191bc87e5c1ba4b5e9984a37:221111' => 'Apple QuickTime, Quality 443 (43%)', + 'de6a322383022ee8d966e848a2df4f28:221111' => 'Apple QuickTime, Quality 444 (43%)', + '163be99e863436e9b3d32615785ec8e1:221111' => 'Apple QuickTime, Quality 445 (43%)', + '958185c48000065b5b8d03b0f975d95b:221111' => 'Apple QuickTime, Quality 446 (44%)', + '2d719cb263e284fc8621bbec1fe52cd5:221111' => 'Apple QuickTime, Quality 447 (44%)', + '8f0f54955cf19689f38df36715908b76:221111' => 'Apple QuickTime, Quality 448 (44%)', + '737c61e006222488645fa2e007f83f3c:221111' => 'Apple QuickTime, Quality 449 (44%)', + 'bb342113b57cf66ce0cf3a09fae5fd16:221111' => 'Apple QuickTime, Quality 450 (44%)', + 'cd3ed5b396580d8e9f0cb7b78baed8b8:221111' => 'Apple QuickTime, Quality 451 (44%)', + 'e7914fbf6c9b2a127af3676726e6bd8b:221111' => 'Apple QuickTime, Quality 452 (44%)', + '377a7b50c2d7484255bbbf537bf9fa86:221111' => 'Apple QuickTime, Quality 453 (44%)', + '09f9009406d2fe8dfa1b35236f8b1bdb:221111' => 'Apple QuickTime, Quality 454 (44%)', + '78b0e590ea36cb11c495097049022d2e:221111' => 'Apple QuickTime, Quality 455 (44%)', + '984c0f34636e6197b508265f17cbd6c9:221111' => 'Apple QuickTime, Quality 456 (45%)', + '7fca22065811c0efe6599a15ca38f05e:221111' => 'Apple QuickTime, Quality 457 (45%)', + 'd55d9744065708d7b6fa7fb6e8eb2453:221111' => 'Apple QuickTime, Quality 458 (45%)', + '63ef900bf59d41003a0e0602baa60681:221111' => 'Apple QuickTime, Quality 459 (45%)', + 'e8b31dbd18c91229a3c40356efeb2622:221111' => 'Apple QuickTime, Quality 460 (45%)', + '8cb1bb16c6fa524199dad5513386d225:221111' => 'Apple QuickTime, Quality 461 (45%)', + 'c53438ece0552cedb1ec0d50ad2d5dbe:221111' => 'Apple QuickTime, Quality 462 (45%)', + '5db6302d7e68c1a274139033681b8fcc:221111' => 'Apple QuickTime, Quality 463 (45%)', + 'acd1d5ec1787c9d346d87c281a7b6da0:221111' => 'Apple QuickTime, Quality 464-465 (45%)', + 'e66c03f97b19213f385136f014c78ac1:221111' => 'Apple QuickTime, Quality 466-467 (46%)', + '23816ed847127a41e3c7f52e04072e41:221111' => 'Apple QuickTime, Quality 468 (46%)', + 'ebce337e9ef5a07775cebe40d7623862:221111' => 'Apple QuickTime, Quality 469 (46%)', + '09563e47ab174b05fb19f722e9aa43c3:221111' => 'Apple QuickTime, Quality 470 (46%)', + '545e14e832fb81f032526a9efcbf2450:221111' => 'Apple QuickTime, Quality 471 (46%)', + 'edda5d6ae456d4cdccec80e390ac9279:221111' => 'Apple QuickTime, Quality 472 (46%)', + '9a43fc0aa6223673c32a49fb76d6525c:221111' => 'Apple QuickTime, Quality 473 (46%)', + 'bdaf3e68c2925cbaad3864359fdbbb77:221111' => 'Apple QuickTime, Quality 474 (46%)', + '4f83a1a8338a8e6e70eaa58cd236f62a:221111' => 'Apple QuickTime, Quality 475 (46%)', + '879b320cfd6e27b2e283b573483bda81:221111' => 'Apple QuickTime, Quality 476 (46%)', + '2748fa249a86361b1b5f0662a88abdb3:221111' => 'Apple QuickTime, Quality 477 (47%)', + '32eb803f68d72719267a1313548e7180:221111' => 'Apple QuickTime, Quality 478 (47%)', + '771eeb43856b1821a271b0aa8398a243:221111' => 'Apple QuickTime, Quality 479 (47%)', + '653c5006512bb3aaa1e6a4e77078b630:221111' => 'Apple QuickTime, Quality 480 (47%)', + 'c5c102ba5f004d49656f424d89e9773c:221111' => 'Apple QuickTime, Quality 481 (47%)', + 'd5220fcfa99764e440684fbac6273cff:221111' => 'Apple QuickTime, Quality 482 (47%)', + 'd300f18258f46060d89c994dbc370131:221111' => 'Apple QuickTime, Quality 483 (47%)', + '60258dcc1e3a81858d176080ef774730:221111' => 'Apple QuickTime, Quality 484 (47%)', + '8bda9fb1ed75249ac5b2feaad7b51d2f:221111' => 'Apple QuickTime, Quality 485 (47%)', + '9e334af92d75ab7d4ea1a9816840ea73:221111' => 'Apple QuickTime, Quality 486 (47%)', + 'c40a38c96832a6042c6ddfc9754c1d6d:221111' => 'Apple QuickTime, Quality 487 (48%)', + '30be130aa27d0b91d6f55ed9b1cd6c84:221111' => 'Apple QuickTime, Quality 488 (48%)', + '3601e95d6cd507065d46b3f058229d91:221111' => 'Apple QuickTime, Quality 489 (48%)', + '9127f8ddd20e583523bc848e99061126:221111' => 'Apple QuickTime, Quality 490 (48%)', + '0d605d279c48a74ef71a24e89ca426a8:221111' => 'Apple QuickTime, Quality 491 (48%)', + 'a5cd2d8592e1c45b67cfb3009d07fb49:221111' => 'Apple QuickTime, Quality 492 (48%)', + 'e346ce6e3bee6abff16420f5ba95ceb9:221111' => 'Apple QuickTime, Quality 493 (48%)', + '03295b26893cab9c7dea4ec15ed56d08:221111' => 'Apple QuickTime, Quality 494 (48%)', + '76af24fe94edf8f3992e38c1dd6eebce:221111' => 'Apple QuickTime, Quality 495 (48%)', + '3c58e82299d87346d37023ea015f3e80:221111' => 'Apple QuickTime, Quality 496 (48%)', + 'aa8940194463b7adc14f20dbee9c6a75:221111' => 'Apple QuickTime, Quality 497 (49%)', + '68a808b23bfa8096e04006171926b72c:221111' => 'Apple QuickTime, Quality 498 (49%)', + '34c0043b98d09193beda0cf5d1ada274:221111' => 'Apple QuickTime, Quality 499 (49%)', + '5881bb3c6e7e2ac43983b4b1e947a6c3:221111' => 'Apple QuickTime, Quality 500 (49%)', + 'a0a7061bc100f051a3c5470559661138:221111' => 'Apple QuickTime, Quality 501 (49%)', + '62e6812d1f7935adddd1a69227cdf626:221111' => 'Apple QuickTime, Quality 502 (49%)', + '94f6dbd754fb4ba3c92698d5f08084f9:221111' => 'Apple QuickTime, Quality 503 (49%)', + 'b7257ba67e4b38b7ccdca2a65d60c970:221111' => 'Apple QuickTime, Quality 504 (49%)', + '5a19d6130b03080dfedef45b6415f4f8:221111' => 'Apple QuickTime, Quality 505 (49%)', + '2b3262e10b1563600a5f0738fec342ed:221111' => 'Apple QuickTime, Quality 506 (49%)', + '295cb1e2772312ba5cd546966d1aa70d:221111' => 'Apple QuickTime, Quality 507 (50%)', + 'c910bcb7b9e8967b87cfa08229d9ca34:221111' => 'Apple QuickTime, Quality 508 (50%)', + '61c8506b490d5e596151b951ffa7a14f:221111' => 'Apple QuickTime, Quality 509 (50%)', + 'ae15629cecc940fef9f24ad9f207fa10:221111' => 'Apple QuickTime, Quality 510 (50%)', + 'c8ef3c50ca99c44ea13f1692ac1190dc:221111' => 'Apple QuickTime, Quality 511 (50%)', + '50500b1272433ef5c9c96f16069fbdf1:221111' => 'Apple QuickTime, Quality 512 (50%)', + 'e41e5416e21dbfb5a41f006b3485f5bb:221111' => 'Apple QuickTime, Quality 513 (50%)', + 'd606add3e7590885ac8978af6d09a2aa:221111' => 'Apple QuickTime, Quality 514 (50%)', + 'cc3936c39c298ef67d9196d0254b0c19:221111' => 'Apple QuickTime, Quality 515 (50%)', + 'e83f8505dc3f5f46b37e22b590f71b98:221111' => 'Apple QuickTime, Quality 516 (50%)', + '2a8e27e03b6e1555335c91231c452bba:221111' => 'Apple QuickTime, Quality 517 (50%)', + '52ab880d25db7b36137e2a3c04987c9a:221111' => 'Apple QuickTime, Quality 518 (51%)', + 'ce2335cc1f8289deda620877f50fd90d:221111' => 'Apple QuickTime, Quality 519 (51%)', + 'bbad0e19b252268530df19c563aa9176:221111' => 'Apple QuickTime, Quality 520 (51%)', + '3184b71ca26bfe0c80811cf10423fa92:221111' => 'Apple QuickTime, Quality 521 (51%)', + '37802f44dab089a35e03b94a298b19da:221111' => 'Apple QuickTime, Quality 522 (51%)', + '5e528bd6778792490c6cf292cf9ba8df:221111' => 'Apple QuickTime, Quality 523 (51%)', + 'fbe0f5b89f266ff382f2b14c70a83097:221111' => 'Apple QuickTime, Quality 524 (51%)', + 'a4bfd80e0c8b9ae7a1114d79a7b63ad6:221111' => 'Apple QuickTime, Quality 525 (51%)', + 'abdf532dc2005805db7d8d0214227146:221111' => 'Apple QuickTime, Quality 526 (51%)', + '2a7ec778642b15b8bce238f7b63ef537:221111' => 'Apple QuickTime, Quality 527 (51%)', + '70073f02f04ee893510bceb09e411d53:221111' => 'Apple QuickTime, Quality 528 (52%)', + '345d210b180a45bd23b0c7931c59c263:221111' => 'Apple QuickTime, Quality 529 (52%)', + 'ddbc4e6566bbcc74b6205526393ef468:221111' => 'Apple QuickTime, Quality 530 (52%)', + '420af34c4f718cc0a10de5285140b6e0:221111' => 'Apple QuickTime, Quality 531 (52%)', + '16b6c2d8688113b1a28afbbc57f46f80:221111' => 'Apple QuickTime, Quality 532-533 (52%)', + '4a2a0e381fed49e5d5ba074998652561:221111' => 'Apple QuickTime, Quality 534 (52%)', + '50f1255f2424b2de5b930751ddf24842:221111' => 'Apple QuickTime, Quality 535 (52%)', + '80f2c05e2ad3524f18dd55bac10ee2e3:221111' => 'Apple QuickTime, Quality 536 (52%)', + '6c0916ab5aa02602cc682bcdbc22369e:221111' => 'Apple QuickTime, Quality 537 (52%)', + 'f7e5656e1f2cf036e9a57a6c02373398:221111' => 'Apple QuickTime, Quality 538 (53%)', + '92044affd220e31ee953aff021144b29:221111' => 'Apple QuickTime, Quality 539 (53%)', + '2bafe4b75b8a105d72e981b21fe3b6cf:221111' => 'Apple QuickTime, Quality 540 (53%)', + 'ca0e84028714f19cf20cb868d1cd346c:221111' => 'Apple QuickTime, Quality 541 (53%)', + 'db1ae392a31d30cd5564dc7bbea24019:221111' => 'Apple QuickTime, Quality 542 (53%)', + '4417e739b9244781987769c2177abc6f:221111' => 'Apple QuickTime, Quality 543 (53%)', + 'f1de58c1c6a48dc36ce7e8c69636539c:221111' => 'Apple QuickTime, Quality 544 (53%)', + '10c931d7bff7bfcc20e37f0868887228:221111' => 'Apple QuickTime, Quality 545 (53%)', + 'e082971717023e667f3d922bbccf089b:221111' => 'Apple QuickTime, Quality 546 (53%)', + '5a285190351b16fee0eb14778280d74f:221111' => 'Apple QuickTime, Quality 547 (53%)', + 'aad0e2cd42c5adaec41080a05be4ffdc:221111' => 'Apple QuickTime, Quality 548 (54%)', + 'de802b8c64d7f854081c7df6ed345b43:221111' => 'Apple QuickTime, Quality 549 (54%)', + '82f45d11d651d93a67995965b94aa649:221111' => 'Apple QuickTime, Quality 550 (54%)', + '617c4c853344ef079f4a1f1062672e8c:221111' => 'Apple QuickTime, Quality 551-552 (54%)', + '90d96923be1883e6ee15a9d0d32a114c:221111' => 'Apple QuickTime, Quality 553 (54%)', + '307c47179fdad179b5f962228c115db8:221111' => 'Apple QuickTime, Quality 554 (54%)', + 'a4683813bdf6e2bd429c4c5676128384:221111' => 'Apple QuickTime, Quality 555 (54%)', + '8e3cfc2fc9cfbba0f6aed9850504ebb6:221111' => 'Apple QuickTime, Quality 556 (54%)', + 'a8f8928c72b69049e1da7639e977c9c7:221111' => 'Apple QuickTime, Quality 557 (54%)', + '1fb4c8af2d70cdeecab3fd9fc882e0ce:221111' => 'Apple QuickTime, Quality 558 (54%)', + '98ddda3b0ada32ce919b9af9df4054dd:221111' => 'Apple QuickTime, Quality 559 (55%)', + 'b43ab5c404469c416e853e52497b3f0d:221111' => 'Apple QuickTime, Quality 560 (55%)', + 'd9696efa02b9de813caf8d684b06346f:221111' => 'Apple QuickTime, Quality 561 (55%)', + 'be63c4e967eff819bd8a052a561a4576:221111' => 'Apple QuickTime, Quality 562 (55%)', + 'f984581f90913e44f3898fffd8fce8b0:221111' => 'Apple QuickTime, Quality 563 (55%)', + '082779cf55f6b922036f11b74df54110:221111' => 'Apple QuickTime, Quality 564 (55%)', + '066fd6cb3a5dd994fc6159987afde581:221111' => 'Apple QuickTime, Quality 565 (55%)', + '133351a0f39427f1199312585cd6c997:221111' => 'Apple QuickTime, Quality 566 (55%)', + '6c23da63c864f1433ec198ae202e56f0:221111' => 'Apple QuickTime, Quality 567 (55%)', + '7d1819ccce2756fcf6dfbb67565c2552:221111' => 'Apple QuickTime, Quality 568 (55%)', + 'd9794fa54e2ef47be48b972cdca910c2:221111' => 'Apple QuickTime, Quality 569 (56%)', + '085db73bd47194c8fdf567fc619c3b62:221111' => 'Apple QuickTime, Quality 570 (56%)', + '9866add6e1d251e1d4c40793f4300dce:221111' => 'Apple QuickTime, Quality 571 (56%)', + '1b9e7e39831b05b058025ae0a7482d44:221111' => 'Apple QuickTime, Quality 572 (56%)', + 'a8b52e666bd3d81404c0f8915ac18b43:221111' => 'Apple QuickTime, Quality 573 (56%)', + 'e34d11f979458a87492b57eabfd4f4ea:221111' => 'Apple QuickTime, Quality 574 (56%)', + '4295c1330dec60585760cbb05b79662d:221111' => 'Apple QuickTime, Quality 575 (56%)', + '9205cc28769d94d6d00c25804ac70a88:221111' => 'Apple QuickTime, Quality 576 (56%)', + 'b5648f13228d20fd7ae81965394f7515:221111' => 'Apple QuickTime, Quality 577 (56%)', + 'c8f02bf550c40daa39b28911a4ef5a69:221111' => 'Apple QuickTime, Quality 578 (56%)', + 'c2b23a91d377ce2d99ac4109f2740069:221111' => 'Apple QuickTime, Quality 579 (57%)', + 'c0cecb47363aff00a2764a915f95cd35:221111' => 'Apple QuickTime, Quality 580 (57%)', + 'fc0d8f17be060220464fe7bc0a2d754e:221111' => 'Apple QuickTime, Quality 581 (57%)', + '63b59904874e5e427ddecb37e12f90c7:221111' => 'Apple QuickTime, Quality 582 (57%)', + 'df6535865562ce7cbf08e9368e991a95:221111' => 'Apple QuickTime, Quality 583 (57%)', + '74523ad3424dcff6aa697c3ce433ad4e:221111' => 'Apple QuickTime, Quality 584 (57%)', + 'cbdec670ec6d9105277434b304226920:221111' => 'Apple QuickTime, Quality 585 (57%)', + '68783ed0a7956cf0b7a1b2787e756213:221111' => 'Apple QuickTime, Quality 586 (57%)', + 'a431976a61e281e7b9d808f094b74d2e:221111' => 'Apple QuickTime, Quality 587 (57%)', + '8e2a66454fb149552d4538d53ec033aa:221111' => 'Apple QuickTime, Quality 588 (57%)', + '49222c4a3be01e93baad695bba63b254:221111' => 'Apple QuickTime, Quality 589 (58%)', + 'ab8fe796c87f9f61cedbfa64af9f5dec:221111' => 'Apple QuickTime, Quality 590 (58%)', + '9bfe788e7ae4bc9cbe76d36f9a2b1b5e:221111' => 'Apple QuickTime, Quality 591 (58%)', + '22b5f11b635ea5484469708cd7e6e3d9:221111' => 'Apple QuickTime, Quality 592 (58%)', + '44e36eb25c6f9e313ef2a8f4c520c335:221111' => 'Apple QuickTime, Quality 593 (58%)', + 'c71aa81fb12b378dd31a1ca128942f76:221111' => 'Apple QuickTime, Quality 594 (58%)', + 'e56ca8f4da20395ec1f87d380198fa0a:221111' => 'Apple QuickTime, Quality 595 (58%)', + '38f4d508dcf9c82d9488b42a2487b191:221111' => 'Apple QuickTime, Quality 596 (58%)', + '3da1e7270e0900a17a0a4ff8d3c9a488:221111' => 'Apple QuickTime, Quality 597 (58%)', + '900fee18a5f6d1dc3fd856d3d92f5414:221111' => 'Apple QuickTime, Quality 598 (58%)', + '3c724d4b5d8cbe203ebbf92ea8e22808:221111' => 'Apple QuickTime, Quality 599 (58%)', + 'e7e7befa282a985a0532634f360df7db:221111' => 'Apple QuickTime, Quality 600 (59%)', + '1f21bf5b7e0e79c229ef4d06fc9d3cc8:221111' => 'Apple QuickTime, Quality 601 (59%)', + '3bb09b202acd618286d26a33f688f7c7:221111' => 'Apple QuickTime, Quality 602 (59%)', + '9717c5a17cbffdfaa2e5d3769b87fbc5:221111' => 'Apple QuickTime, Quality 603 (59%)', + 'ffa7874d293c62ecc55c098b8f305ae1:221111' => 'Apple QuickTime, Quality 604 (59%)', + 'e68841bf28d33d749d0031bfe3a5219c:221111' => 'Apple QuickTime, Quality 605 (59%)', + '5862c8c2b241a9760f6804d970eefd66:221111' => 'Apple QuickTime, Quality 606 (59%)', + '1d069604250e871bd92a4a24c7be2bd5:221111' => 'Apple QuickTime, Quality 607 (59%)', + '3806bcbefd350e8791be95dfc62bab27:221111' => 'Apple QuickTime, Quality 608 (59%)', + '490b035a665ef80c7b48804461d55b7f:221111' => 'Apple QuickTime, Quality 609 (59%)', + 'bd6943a8c92a14e74d2b24052a19400a:221111' => 'Apple QuickTime, Quality 610 (60%)', + '93e725418f46b2a70723523bef0979fe:221111' => 'Apple QuickTime, Quality 611 (60%)', + '5b66fa5c0c1ba746289747229193cfb0:221111' => 'Apple QuickTime, Quality 612 (60%)', + '1bdac971e8cddd198ad3123849370037:221111' => 'Apple QuickTime, Quality 613 (60%)', + '20f7b70185f4b324a8451ac4657c1d66:221111' => 'Apple QuickTime, Quality 614 (60%)', + '86ab18d6c1359a424f303fcfd0930df2:221111' => 'Apple QuickTime, Quality 615 (60%)', + '0d70031c9962dba7c39da59ada2f1660:221111' => 'Apple QuickTime, Quality 616-617 (60%)', + '9cb9a256b6deb481cf13e5230fe87dbb:221111' => 'Apple QuickTime, Quality 618-619 (60%)', + 'cb34e1a0e18a4dd7ffe823f9c92b3622:221111' => 'Apple QuickTime, Quality 620 (61%)', + 'ac015afc1d80314edd832aebfb495d25:221111' => 'Apple QuickTime, Quality 621 (61%)', + '4974cc7044768888244b324449a238ab:221111' => 'Apple QuickTime, Quality 622 (61%)', + 'bc4541f5bc4d58b99b53d24f3f520b32:221111' => 'Apple QuickTime, Quality 623 (61%)', + 'ec2fd56a50df0e42498018d441a3aa75:221111' => 'Apple QuickTime, Quality 624 (61%)', + '153a6f0994d16003aa4f1112e6757467:221111' => 'Apple QuickTime, Quality 625 (61%)', + 'ed6b90ca62ed648d1102e1c506a0af26:221111' => 'Apple QuickTime, Quality 626 (61%)', + '18593e50c21c8ad521b30933ef7479b1:221111' => 'Apple QuickTime, Quality 627 (61%)', + '6f96ed52a987d67e8d950b2627d3fbc2:221111' => 'Apple QuickTime, Quality 628 (61%)', + 'e76d86e8de4f0bf9e58cd389e0a8c117:221111' => 'Apple QuickTime, Quality 629 (61%)', + '4fa27c83741226576ac6359cd4f6248e:221111' => 'Apple QuickTime, Quality 630 (62%)', + 'be010732a7783ee345548a1eb95d024a:221111' => 'Apple QuickTime, Quality 631 (62%)', + '6700663d4ebaeb394bfd3c85597347b5:221111' => 'Apple QuickTime, Quality 632 (62%)', + '34dba33043aa5ee317b7649242e702b1:221111' => 'Apple QuickTime, Quality 633 (62%)', + '821d7e59bcf756171b7644ec5736266e:221111' => 'Apple QuickTime, Quality 634 (62%)', + 'd81683c0458d9ad72751530d6fbc1389:221111' => 'Apple QuickTime, Quality 635 (62%)', + '4c04d6fe904a4b6ff8b25c9f0e9f0a16:221111' => 'Apple QuickTime, Quality 636 (62%)', + '8efda55d6186d9867189c5cb572c5413:221111' => 'Apple QuickTime, Quality 637 (62%)', + '25497c83113bd738e89d91bd48d7086c:221111' => 'Apple QuickTime, Quality 638 (62%)', + '84c8e142e6d27734b126f76653b9199d:221111' => 'Apple QuickTime, Quality 639 (62%)', + 'bdaf13038b56b5701f60300528f8a89c:221111' => 'Apple QuickTime, Quality 640-641 (63%)', + 'b015ada43293b8d5bd2a8f288f8fb928:221111' => 'Apple QuickTime, Quality 642 (63%)', + '8134ff0c4713cc1ef4a25ff60b49ac54:221111' => 'Apple QuickTime, Quality 643 (63%)', + '967fc5c3ece2b69662257c76397416c9:221111' => 'Apple QuickTime, Quality 644 (63%)', + 'd01a38e0f568d2a7b6b71f8fa63b8bcc:221111' => 'Apple QuickTime, Quality 645 (63%)', + '5229288e448311401bb284133ac7d48c:221111' => 'Apple QuickTime, Quality 646 (63%)', + '76d22de881d1b95b491689b589743b7a:221111' => 'Apple QuickTime, Quality 647 (63%)', + 'c81b03b0291d2277461a551ed6861252:221111' => 'Apple QuickTime, Quality 648-649 (63%)', + 'ebb774b4e106d1a9df5824958d4e5a95:221111' => 'Apple QuickTime, Quality 650 (63%)', + '9ed53fb5bc8e397daf9409251c0a0a6c:221111' => 'Apple QuickTime, Quality 651 (64%)', + '87d40f2e4dad34fa435c62af6817dc18:221111' => 'Apple QuickTime, Quality 652 (64%)', + '0b933cf90e62682da926267d6356ac2b:221111' => 'Apple QuickTime, Quality 653 (64%)', + '2c4a4cb841ee92aa3a2b4c93467ba7a8:221111' => 'Apple QuickTime, Quality 654 (64%)', + '8a6ba56597670b7adb70901eca278049:221111' => 'Apple QuickTime, Quality 655 (64%)', + 'd1ef25928fd4eefe131ffcfc249b9f8a:221111' => 'Apple QuickTime, Quality 656 (64%)', + '8c85462b5a01db09bcbf304d7be1d543:221111' => 'Apple QuickTime, Quality 657 (64%)', + '19c03533b9b2e3304a0b02d9b1054497:221111' => 'Apple QuickTime, Quality 658 (64%)', + 'd2baa8fbc56f0970f820c376c6065d41:221111' => 'Apple QuickTime, Quality 659 (64%)', + 'e6a0a679a13a99de16e13c6ea2829deb:221111' => 'Apple QuickTime, Quality 660-661 (64-65%)', + '8e4f695afcf2a06254561e5e22b7a80b:221111' => 'Apple QuickTime, Quality 662 (65%)', + 'd053fd2c67ce96b0ecf9ffc4b7f7775d:221111' => 'Apple QuickTime, Quality 663 (65%)', + '326c33f64f96592487d2bfdd198738bf:221111' => 'Apple QuickTime, Quality 664 (65%)', + '1ff8f5ff33353a3ee0b6dc8fbb6321a0:221111' => 'Apple QuickTime, Quality 665 (65%)', + '14a5534e4216458662a43101d56d84c8:221111' => 'Apple QuickTime, Quality 666 (65%)', + '0643b87475939754c8d56825cd96242f:221111' => 'Apple QuickTime, Quality 667 (65%)', + '45c46a02a434d8ea759742907bfa0ee5:221111' => 'Apple QuickTime, Quality 668 (65%)', + '2916d9453b885ee4123e6e3ee94ccbc7:221111' => 'Apple QuickTime, Quality 669-671 (65-66%)', + 'b8fca611f92cbc459fe21e11f0214328:221111' => 'Apple QuickTime, Quality 672-673 (66%)', + 'f40fb322c4bde68a2902c86c613af841:221111' => 'Apple QuickTime, Quality 674 (66%)', + '1cbd419717a2916b53f9f504ec1167ca:221111' => 'Apple QuickTime, Quality 675 (66%)', + '79f546689b548868a904f50214928aa1:221111' => 'Apple QuickTime, Quality 676 (66%)', + '8ff6f2d4369155b0474417b00c3c4ac9:221111' => 'Apple QuickTime, Quality 677 (66%)', + 'c60dbbefd4f215b9359dd004f4fb0fd3:221111' => 'Apple QuickTime, Quality 678 (66%)', + 'c192d5847d1146a31db621263a9ce2f5:221111' => 'Apple QuickTime, Quality 679 (66%)', + '4a2361c48a583f6df779d1e6088ed83c:221111' => 'Apple QuickTime, Quality 680 (66%)', + '6c6260b84a3a588614d65133430289ea:221111' => 'Apple QuickTime, Quality 681 (67%)', + '6773f3db56ae831012dbe43c1650571a:221111' => 'Apple QuickTime, Quality 682 (67%)', + '813b89236cfe429fe534361f28ace015:221111' => 'Apple QuickTime, Quality 683 (67%)', + '363b54d38094e5f2e2d63c50870ae76c:221111' => 'Apple QuickTime, Quality 684 (67%)', + '7b17607b9954c37e525b1fbc35271553:221111' => 'Apple QuickTime, Quality 685 (67%)', + '8b1138e2d88033d42698a386a2e8605b:221111' => 'Apple QuickTime, Quality 686 (67%)', + 'c029b8a48e3c93f7c0367f2a149491c7:221111' => 'Apple QuickTime, Quality 687 (67%)', + 'a36199f5a090de94b10a32fbe05f2916:221111' => 'Apple QuickTime, Quality 688-689 (67%)', + 'a873e49b871c32bcaf8e3c6622744e70:221111' => 'Apple QuickTime, Quality 690 (67%)', + 'b9d16f36087d4cca70eef1512c4be569:221111' => 'Apple QuickTime, Quality 691 (67%)', + 'd5994dbe056ea3544b3256a7a6b53749:221111' => 'Apple QuickTime, Quality 692 (68%)', + '0106cf02dcf4109cc6f02fa4ec0e2700:221111' => 'Apple QuickTime, Quality 693 (68%)', + '7d71776416a8771d10e3c2e6dc6a5f21:221111' => 'Apple QuickTime, Quality 694-695 (68%)', + 'c1557f789acc622c8858be4dfbc53c31:221111' => 'Apple QuickTime, Quality 696 (68%)', + '5a54f085c1780cadb13a7dea8347c7c6:221111' => 'Apple QuickTime, Quality 697 (68%)', + '04a5bb959bc203221e72e6575ff39602:221111' => 'Apple QuickTime, Quality 698 (68%)', + '116e3d5fee4e3a695c0f79c09c89ff84:221111' => 'Apple QuickTime, Quality 699 (68%)', + '145bfd5481e99e18c4c3707228557fa5:221111' => 'Apple QuickTime, Quality 700 (68%)', + '19ceef79e864691318beea6502ddc3e1:221111' => 'Apple QuickTime, Quality 701 (68%)', + 'dd0a023941d7bfd118d272f4f925e6e2:221111' => 'Apple QuickTime, Quality 702 (69%)', + '81f039d6a0ded8227dc51273d153b295:221111' => 'Apple QuickTime, Quality 703-704 (69%)', + '9a7ebf265afce16abaa6ca2fbb550b63:221111' => 'Apple QuickTime, Quality 705 (69%)', + '8d0fed09156984328f90f9f19fb5a079:221111' => 'Apple QuickTime, Quality 706 (69%)', + 'be7c72e09c46622b0d2b93e170a03e17:221111' => 'Apple QuickTime, Quality 707 (69%)', + '50a510968effffab80bed1d08c6c5ccc:221111' => 'Apple QuickTime, Quality 708 (69%)', + 'da2501a6f59b2256adb0833b58b504f2:221111' => 'Apple QuickTime, Quality 709 (69%)', + '2a1b83345108443a090cdab4c83143fb:221111' => 'Apple QuickTime, Quality 710 (69%)', + 'e7f293f640878b53fe95a7cb0b1dcc83:221111' => 'Apple QuickTime, Quality 711-712 (69-70%)', + 'd9e0a4c08ef5d7f72eecce74c94c054d:221111' => 'Apple QuickTime, Quality 713 (70%)', + 'c5774ffb4573926fd03d4175818c0e5d:221111' => 'Apple QuickTime, Quality 714 (70%)', + 'e2b368a164b67e15598683f9f184bd77:221111' => 'Apple QuickTime, Quality 715 (70%)', + 'f30792e8fad278c3e1677b5f5b74c682:221111' => 'Apple QuickTime, Quality 716-717 (70%)', + '6f6bfc10750e6717cc3791a9ea1d7569:221111' => 'Apple QuickTime, Quality 718-719 (70%)', + '5e3981a937c61480451d5bdc253e5472:221111' => 'Apple QuickTime, Quality 720 (70%)', + 'c4fb82f47a7b002d5cab421592ae4972:221111' => 'Apple QuickTime, Quality 721 (70%)', + 'a6c4a173169d168e003839e51f035661:221111' => 'Apple QuickTime, Quality 722 (71%)', + '72df283a5c07671eba341500a3fc18f1:221111' => 'Apple QuickTime, Quality 723 (71%)', + 'dfb203555c34fe146c526350e11309eb:221111' => 'Apple QuickTime, Quality 724 (71%)', + '033472a8a855fab8cd8f6a5788dd07c8:221111' => 'Apple QuickTime, Quality 725 (71%)', + '5b8a79eec9b7eb7755deb7f2c189e94a:221111' => 'Apple QuickTime, Quality 726 (71%)', + 'ad3aad027e3829959ebeb6288bfab268:221111' => 'Apple QuickTime, Quality 727 (71%)', + '2234156f0550a047700c2a08459c8242:221111' => 'Apple QuickTime, Quality 728 (71%)', + '0c0351c3a444b851cd105dd5cc4db59c:221111' => 'Apple QuickTime, Quality 729 (71%)', + 'c10fca5e6f66238ab09f7e8105f54e39:221111' => 'Apple QuickTime, Quality 730 (71%)', + '74cc07bbb7049d59aff0c4965d4d5084:221111' => 'Apple QuickTime, Quality 731 (71%)', + 'ce9ad8466ffd84b91039326e8688c44a:221111' => 'Apple QuickTime, Quality 732-733 (71-72%)', + 'e4b0c56d41f4af9e10971876ad7ad56d:221111' => 'Apple QuickTime, Quality 734 (72%)', + '96076425ecc546ec028d0eab48332756:221111' => 'Apple QuickTime, Quality 735 (72%)', + 'ba49b0656894f3c76d852223721b3b1f:221111' => 'Apple QuickTime, Quality 736 (72%)', + 'ae5c6eab0d57249acbcb8b1990b2602f:221111' => 'Apple QuickTime, Quality 737-738 (72%)', + '72f08842473a6c504469d341259e5cd7:221111' => 'Apple QuickTime, Quality 739-740 (72%)', + 'c9f953acdfc1f5afdbb9e9f74692d23e:221111' => 'Apple QuickTime, Quality 741 (72%)', + '5a1b57a2583acf5c2428cd62fe24b773:221111' => 'Apple QuickTime, Quality 742 (72%)', + '6a9ead8b2339567482a172a581e86c15:221111' => 'Apple QuickTime, Quality 743-744 (73%)', + '513d9e9dabbb480eb60f7ef76b1d755e:221111' => 'Apple QuickTime, Quality 745 (73%)', + 'b99bdcd0145833d52b916e71f2c20a04:221111' => 'Apple QuickTime, Quality 746 (73%)', + 'ff084566430a3ed4733cd59aec26a55d:221111' => 'Apple QuickTime, Quality 747 (73%)', + '76bcc27918d8f12b343e6e5a41108781:221111' => 'Apple QuickTime, Quality 748 (73%)', + '7bf7022a7c12b3b7ea085b46158253e6:221111' => 'Apple QuickTime, Quality 749 (73%)', + '4baf3b1df2426fbdac3d0aaa0503ee94:221111' => 'Apple QuickTime, Quality 750 (73%)', + 'bb0180b9eda074c3f913c8ada3d4c1ad:221111' => 'Apple QuickTime, Quality 751 (73%)', + 'c5fcb1748f616ac97794d34b1b93616e:221111' => 'Apple QuickTime, Quality 752-753 (73-74%)', + '0da77ccec22a9cff9a049a47e86d3502:221111' => 'Apple QuickTime, Quality 754 (74%)', + 'c31f71de437dc301d34f847d95267d9e:221111' => 'Apple QuickTime, Quality 755 (74%)', + '01137dc7ef90f0aee15362c221f7b1d3:221111' => 'Apple QuickTime, Quality 756-758 (74%)', + '026780f2172c289bc1ff73a34c6aee57:221111' => 'Apple QuickTime, Quality 759-760 (74%)', + '3fab8f2b141f95a989fc4b046ad825cb:221111' => 'Apple QuickTime, Quality 761 (74%)', + 'cd091eeb9d27d9dc7cdb5bff73572679:221111' => 'Apple QuickTime, Quality 762 (74%)', + 'ad2221ee8bb94a3558ed16766efaec4f:221111' => 'Apple QuickTime, Quality 763 (75%)', + '8a4ff70dce3efc9312ff7239e79b6bc9:221111' => 'Apple QuickTime, Quality 764 (75%)', + 'b8d1fcda3a19d00788c2be73fd4c2c8e:221111' => 'Apple QuickTime, Quality 765-766 (75%)', + '3af16b87c33bb2e48152e249beb9147b:221111' => 'Apple QuickTime, Quality 767 (75%)', + '3af16b87c33bb2e48152e249beb9147b:211111' => 'Apple QuickTime, Quality 768 (75%)', + '683270dbffdc5cd2d4e6cb841f17b206:211111' => 'Apple QuickTime, Quality 769 (75%)', + '285bdd58fac87b174a22d2a93d69cd7c:211111' => 'Apple QuickTime, Quality 770 (75%)', + '312e047b5d9076cd1e126f3dbce928e5:211111' => 'Apple QuickTime, Quality 771 (75%)', + '99458d7a01a39fe126592d9afb1402ce:211111' => 'Apple QuickTime, Quality 772 (75%)', + 'b4633256b0e0d5e2a5021f01ebabc105:211111' => 'Apple QuickTime, Quality 773 (75%)', + '90d39fd222f9114f613a315a894283ca:211111' => 'Apple QuickTime, Quality 774 (76%)', + '61b1d4a02498b7467f2c8e8cfebdfae9:211111' => 'Apple QuickTime, Quality 775-776 (76%)', + '987ebcbd20b633b40241fcd30266e986:211111' => 'Apple QuickTime, Quality 777 (76%)', + '31e214243395b008048469d4bc4dc780:211111' => 'Apple QuickTime, Quality 778 (76%)', + 'db5b3a078a942131b5d86bc189baac24:211111' => 'Apple QuickTime, Quality 779 (76%)', + 'ec440a2ffcbce8895beb663b36975073:211111' => 'Apple QuickTime, Quality 780-781 (76%)', + '93d7ac97a931be74c7fe849edc482ea1:211111' => 'Apple QuickTime, Quality 782 (76%)', + '3974d72e6831171ec970bbb09b9cc506:211111' => 'Apple QuickTime, Quality 783 (76%)', + '07bd22218437079a86ce0b93ffa9cc90:211111' => 'Apple QuickTime, Quality 784 (77%)', + '32757023bb5e7f703acf737a5a29c9d6:211111' => 'Apple QuickTime, Quality 785-786 (77%)', + '6096eb584b99a587f5527e20473aa9d1:211111' => 'Apple QuickTime, Quality 787 (77%)', + 'c6d134475eb85bd454f2ee5153366c51:211111' => 'Apple QuickTime, Quality 788 (77%)', + 'a3ba20f325ff36f874d633919185f92d:211111' => 'Apple QuickTime, Quality 789 (77%)', + 'af10133169e143a2b3634c48dede9440:211111' => 'Apple QuickTime, Quality 790 (77%)', + '9dbb8223620e7f25ca3292849f7aa025:211111' => 'Apple QuickTime, Quality 791-792 (77%)', + '5071640a38c5898dd5d2043346fd23e1:211111' => 'Apple QuickTime, Quality 793-795 (77-78%)', + '60a0ca27f3e7289d97c033ca217899cc:211111' => 'Apple QuickTime, Quality 796-798 (78%)', + 'f7a5ea485a254cba0d39cdeaf89ad344:211111' => 'Apple QuickTime, Quality 799 (78%)', + 'd8cd0ca367d9afaf9a1aca0415da5361:211111' => 'Apple QuickTime, Quality 800 (78%)', + '87fb3c7402ba4edcda34b71696d2b0e3:211111' => 'Apple QuickTime, Quality 801 (78%)', + 'f8df76525f7f97d2e89173989e6786af:211111' => 'Apple QuickTime, Quality 802-804 (78-79%)', + '64677161baed1c47d2fdd6eefd779583:211111' => 'Apple QuickTime, Quality 805 (79%)', + 'ca39dde8e9b4ccd6261b28e089181639:211111' => 'Apple QuickTime, Quality 806-807 (79%)', + 'e6c99d520b86fd6f5eb513d1a084324e:211111' => 'Apple QuickTime, Quality 808 (79%)', + '9e048c787b12b9ab47d6166e81bc8bda:211111' => 'Apple QuickTime, Quality 809 (79%)', + '03c035b39889356e0b10805d8549a1f7:211111' => 'Apple QuickTime, Quality 810 (79%)', + '15de51ede231cfbe123daa42a1a46070:211111' => 'Apple QuickTime, Quality 811-813 (79%)', + '725bcc59a6f5a1436dfa0dfd96cdcf44:211111' => 'Apple QuickTime, Quality 814 (79%)', + 'd00103d50108e8be370a78d47f51aba0:211111' => 'Apple QuickTime, Quality 815 (80%)', + '1c4c74ccc581b11050cfe18792246e5e:211111' => 'Apple QuickTime, Quality 816 (80%)', + 'b63e97c56859f2476ed3f15f40775fb5:211111' => 'Apple QuickTime, Quality 817 (80%)', + 'aac2510e3cd617eb2cd60e7dc6f5d252:211111' => 'Apple QuickTime, Quality 818 (80%)', + '028caa124d0837dd9b1a64028e4f2965:211111' => 'Apple QuickTime, Quality 819 (80%)', + '0440231d1a4a1187bffaa5b5576827f9:211111' => 'Apple QuickTime, Quality 820 (80%)', + '6f879b2b5642ee3d01faf3410a721e2d:211111' => 'Apple QuickTime, Quality 821 (80%)', + '4642245b427d5dd5c1c3766c323204ac:211111' => 'Apple QuickTime, Quality 822-824 (80%)', + '8bd486eb557ae8f39948775aba222731:211111' => 'Apple QuickTime, Quality 825 (81%)', + '8bc4e4bec8e9b193c11ad90c7f8bfaf3:211111' => 'Apple QuickTime, Quality 826 (81%)', + 'f54c2ea8437408238f6c181a355af6cb:211111' => 'Apple QuickTime, Quality 827-829 (81%)', + '0f58458f2b9959dbc57b4868200c0432:211111' => 'Apple QuickTime, Quality 830-832 (81%)', + '24f95056dce30d11bad39b33ab271262:211111' => 'Apple QuickTime, Quality 833-834 (81%)', + 'bad6fdd8761fb9d0921384013acf783f:211111' => 'Apple QuickTime, Quality 835 (82%)', + '8c482fe6aef2a59a94cb779e6795e512:211111' => 'Apple QuickTime, Quality 836 (82%)', + '50b309f18bcf477742aa491ea55af777:211111' => 'Apple QuickTime, Quality 837 (82%)', + '92a9e0d027a1b2e5f7e49f7ffd96277e:211111' => 'Apple QuickTime, Quality 838-839 (82%)', + 'a6df2748a4972d4323f0386820ce35a4:211111' => 'Apple QuickTime, Quality 840 (82%)', + '9ffb80389e2eed2301e6b07860c2fbd7:211111' => 'Apple QuickTime, Quality 841 (82%)', + '6042038094d7f4ad72c61c2a2e7a467f:211111' => 'Apple QuickTime, Quality 842 (82%)', + '78d004490e822405acded09846135e50:211111' => 'Apple QuickTime, Quality 843 (82%)', + 'a589d880de576ed888c57814ccea47a0:211111' => 'Apple QuickTime, Quality 844 (82%)', + 'beee113eea5950b8211cdc49e5a04099:211111' => 'Apple QuickTime, Quality 845 (83%)', + 'f04fed79cdc47709d649187cfcc7e342:211111' => 'Apple QuickTime, Quality 846-849 (83%)', + 'edb0be7fcce943c28d02ff78ae600afb:211111' => 'Apple QuickTime, Quality 850 (83%)', + '0e9648c1f28b99a377dcf7deec6450e6:211111' => 'Apple QuickTime, Quality 851-852 (83%)', + '2dffe433bbb9c81b05e569afd3d9b585:211111' => 'Apple QuickTime, Quality 853 (83%)', + '0ef4f8fa922f87f1be646fccaa0ef42e:211111' => 'Apple QuickTime, Quality 854 (83%)', + '4b799df6fc9476102f890343080e66f5:211111' => 'Apple QuickTime, Quality 855-856 (83-84%)', + '53a66cb32deb83c855f36b26527f4c10:211111' => 'Apple QuickTime, Quality 857 (84%)', + '151d7cd5a95929d45c6790beb87705fe:211111' => 'Apple QuickTime, Quality 858 (84%)', + 'bc2afe0a9c7c68b8d84bd231209be3e2:211111' => 'Apple QuickTime, Quality 859-860 (84%)', + 'b9d66564ab9c4bb0910eb228aa9a48e1:211111' => 'Apple QuickTime, Quality 861-863 (84%)', + '6808ca55a29fcb9c15db1925a84370c3:211111' => 'Apple QuickTime, Quality 864 (84%)', + 'ee5b4ed7f04821d1e3a509d7565cb10d:211111' => 'Apple QuickTime, Quality 865 (84%)', + 'd38be79f7c8c6c27a3268275b144add6:211111' => 'Apple QuickTime, Quality 866 (85%)', + '59eedef87f255db058b5ba0b1d3a4ce8:211111' => 'Apple QuickTime, Quality 867 (85%)', + '5e5530c45def7006a7f672ce5778513d:211111' => 'Apple QuickTime, Quality 868 (85%)', + 'b09abfa40fc6607dc26d8b5df48c72fc:211111' => 'Apple QuickTime, Quality 869 (85%)', + 'cfc78404529f2b81b16d3f25fc96e8f4:211111' => 'Apple QuickTime, Quality 870 (85%)', + '14c62682032efe8dc2de80c9330c6206:211111' => 'Apple QuickTime, Quality 871-872 (85%)', + 'ffadac945c3420537e21e67ab3a843d6:211111' => 'Apple QuickTime, Quality 873-875 (85%)', + 'e67a8a7e92a9f03413e9a67b99624b8b:211111' => 'Apple QuickTime, Quality 876-877 (86%)', + 'ba4af3bb30dda0a7be4c04ff1ebbd9ef:211111' => 'Apple QuickTime, Quality 878-880 (86%)', + '3eedb8a357141ff5ae765fd3be2b232f:211111' => 'Apple QuickTime, Quality 881-886 (86-87%)', + '127b0599fc6804909a33832be7a9dd36:211111' => 'Apple QuickTime, Quality 887 (87%)', + 'b697448eec21ef07f3111b62d592c423:211111' => 'Apple QuickTime, Quality 888-890 (87%)', + 'a08a6b6535f292518b5ff6d0d05ae187:211111' => 'Apple QuickTime, Quality 891-893 (87%)', + 'a439b365c2d0cf1fbaad2e42d331d759:211111' => 'Apple QuickTime, Quality 894 (87%)', + 'bf0c20b20af6473b7c4a338ba57d1a96:211111' => 'Apple QuickTime, Quality 895 (87%)', + '09cf94311753aa9796ffd720749c51f7:211111' => 'Apple QuickTime, Quality 896 (88%)', + 'a60bbd6538af00192c411020d7494a1d:211111' => 'Apple QuickTime, Quality 897-898 (88%)', + 'df8ea903695e76e4b1466bdd3a3480c7:211111' => 'Apple QuickTime, Quality 899 (88%)', + 'eb4eb617beaa4f23acf41167742806fc:211111' => 'Apple QuickTime, Quality 900-901 (88%)', + '591c923a44c635c33769704c9cfa6ab7:211111' => 'Apple QuickTime, Quality 902 (88%)', + '960caf85ef273541ac2e76c9554dc860:211111' => 'Apple QuickTime, Quality 903 (88%)', + '22c77ec6f4e8f75d48f98473abe62e59:211111' => 'Apple QuickTime, Quality 904-905 (88%)', + 'fc8d384969030e7bc0255d34a7a5c0b0:211111' => 'Apple QuickTime, Quality 906 (88%)', + '42e7323506b113685e82e6d42664626f:211111' => 'Apple QuickTime, Quality 907-908 (89%)', + '7163b345b90553e246296a48b46cc0b3:211111' => 'Apple QuickTime, Quality 909-910 (89%)', + '52f25cf8c4d610dffcc45681def8fb49:211111' => 'Apple QuickTime, Quality 911-914 (89%)', + '5554cfd817a2713a690b957145b088ed:211111' => 'Apple QuickTime, Quality 915-917 (89-90%)', + '6ef0b71a5676c4645a3166b9c34744fa:211111' => 'Apple QuickTime, Quality 918-920 (90%)', + '1228da2b97793a88a41542ddcfca7ad2:211111' => 'Apple QuickTime, Quality 921-922 (90%)', + '9060906039e9ff37171ba48d908f6ad5:211111' => 'Apple QuickTime, Quality 923-924 (90%)', + '6eb301fb89e7d625129b77a53fe30dcc:211111' => 'Apple QuickTime, Quality 925-926 (90%)', + 'ad5399708089baad5891319303ba92df:211111' => 'Apple QuickTime, Quality 927 (91%)', + 'afd16e145464c7c5a3cd703017b4ef7a:211111' => 'Apple QuickTime, Quality 928 (91%)', + '4271405c840705072a102d7e18b374d9:211111' => 'Apple QuickTime, Quality 929 (91%)', + '72a91837a63fa7444416bc00a05d988b:211111' => 'Apple QuickTime, Quality 930 (91%)', + '8fe3845bafb06ee4de1a6f75c2a42e9b:211111' => 'Apple QuickTime, Quality 931 (91%)', + '8d3b678651ec71f27e3727718123f354:211111' => 'Apple QuickTime, Quality 932-933 (91%)', + '36d42b031eea0c9f626f15533e72162a:211111' => 'Apple QuickTime, Quality 934-936 (91%)', + '789076781ff1e18154091f2460c1bab5:211111' => 'Apple QuickTime, Quality 937-938 (92%)', + '07464723ecfd8e5ed8fd6904e9d15a23:211111' => 'Apple QuickTime, Quality 939 (92%)', + '0efd0d9423b440cfc8efacf2e4dfcb7f:211111' => 'Apple QuickTime, Quality 940 (92%)', + '80409b38f84336548b62e337a850e9cb:211111' => 'Apple QuickTime, Quality 941-943 (92%)', + '5fa6bb26309d43ca6c89d6cc776a68a4:211111' => 'Apple QuickTime, Quality 944-946 (92%)', + '705064f644ac4b24884500a40ad0f7cf:211111' => 'Apple QuickTime, Quality 947-948 (92-93%)', + 'c181c79bc41cf5fe11e6f253242ce2c4:211111' => 'Apple QuickTime, Quality 949-951 (93%)', + '1a7da03994ee019a30dbd37117761467:211111' => 'Apple QuickTime, Quality 952-954 (93%)', + '070620a25578b4a38ed0c09d6d512de8:211111' => 'Apple QuickTime, Quality 955 (93%)', + '6a092d8fd56ca0e852d74bd86cfc4f47:211111' => 'Apple QuickTime, Quality 956-957 (93%)', + '66e85870faf72f4f3fe25486409b286a:211111' => 'Apple QuickTime, Quality 958 (94%)', + '31365833a4d7d0ef2c1db9b90e515f7f:211111' => 'Apple QuickTime, Quality 959-961 (94%)', + '2edccd94198ab5a459a8396d9a0be4aa:211111' => 'Apple QuickTime, Quality 962 (94%)', + 'ca0bf66c467278f9d5ca5301840e7a7f:211111' => 'Apple QuickTime, Quality 963-967 (94%)', + '261bdba7fe6d8bca5302e4e93b52c1fb:211111' => 'Apple QuickTime, Quality 968-970 (95%)', + '762f9501e83d58307d1e102ddb343207:211111' => 'Apple QuickTime, Quality 971 (95%)', + 'ba18a8f4175bdedfea7af9bf5fe8dd9c:211111' => 'Apple QuickTime, Quality 972-973 (95%)', + 'd1a8052e7152e0c35d167e9e56418eb7:211111' => 'Apple QuickTime, Quality 974 (95%)', + '32682ece28c3bee7754fde6fec109b47:211111' => 'Apple QuickTime, Quality 975-977 (95%)', + 'a8780d0f85eef638c6a448e57b157378:211111' => 'Apple QuickTime, Quality 978-979 (96%)', + 'b79ff1a16807a48a31d457ad7e0b94f2:211111' => 'Apple QuickTime, Quality 980-984 (96%)', + '2bf80ea6a878f7ecb88ea827b58c98f8:211111' => 'Apple QuickTime, Quality 985-987 (96%)', + 'add779ad00786bd2ccb9dcc226386b1a:211111' => 'Apple QuickTime, Quality 988-991 (96-97%)', + '56c4efb597cc30275229486199e60f70:211111' => 'Apple QuickTime, Quality 992-993 (97%)', + 'c2df556e8ede9fb199b9a16e01279c6b:211111' => 'Apple QuickTime, Quality 994-996 (97%)', + '6af868a0eececd267495f749a38b4f95:211111' => 'Apple QuickTime, Quality 997-998 (97%)', + 'c92c755320e7ce8f46f644b90b7907e8:211111' => 'Apple QuickTime, Quality 999-1000 (98%)', + '6fcbaaa11108d1712bad5410b3db5b91:211111' => 'Apple QuickTime, Quality 1001-1002 (98%)', + 'f7d803e16f0c66df7d46747715b1ae24:211111' => 'Apple QuickTime, Quality 1003 (98%)', + '7f51ebf21174bcd3b027ae3cc77c4459:211111' => 'Apple QuickTime, Quality 1004 (98%)', + 'f2423a8ae68a49cc6191a2ec80367893:211111' => 'Apple QuickTime, Quality 1005-1006 (98%)', + 'f97cd4c7b1125556dc3eb57fc494e6b5:211111' => 'Apple QuickTime, Quality 1007-1009 (98-99%)', + '389e1ca056b1bd05dd29ecaecae5b4ae:211111' => 'Apple QuickTime, Quality 1010-1013 (99%)', + '43f9929d00af93968662983b891364d8:211111' => 'Apple QuickTime, Quality 1014-1016 (99%)', + '7e1453eec55a8c40166b2d8985ad6bdc:211111' => 'Apple QuickTime, Quality 1017 (99%)', + '31697e4b294a13e35ab8d55d3a9612ca:211111' => 'Apple QuickTime, Quality 1018-1020 (99-100%)', + 'ec76274ff22c07e53299ad34633ba88f:211111' => 'Apple QuickTime, Quality 1021-1023 (100%)', + '7f8b33a26e7f35a6eaf2e95df81e1cca:111111' => 'Apple QuickTime, Quality 1024 (Lossless)', + + # Apple QuickTime (Grayscale) + # + # Tested with: + # - QuickTime 7.5.0 (Win) + '7e6246d9be5273b979beb680b284e7b8:11' => 'Apple QuickTime, Quality 0-63 (0-6%)', + 'caf33ddc94762bf60a8c5e5024550b21:11' => 'Apple QuickTime, Quality 64-80 (6-8%)', + '042ae0dbef2b1e91c4eb36e66a39b5b9:11' => 'Apple QuickTime, Quality 81-92 (8-9%)', + 'bdcc7abca09941326c079bb3bc30de4d:11' => 'Apple QuickTime, Quality 93-101 (9-10%)', + '8edf0677ca6be750511593fad835bbb5:11' => 'Apple QuickTime, Quality 102-109 (10-11%)', + 'dd54b4e3d8801f3a7969be542d165c6b:11' => 'Apple QuickTime, Quality 110-116 (11%)', + 'c00374dece11c3cab5f2c3bf9621d365:11' => 'Apple QuickTime, Quality 117-122 (11-12%)', + 'a2e3baa02454492ef811619ac18c65da:11' => 'Apple QuickTime, Quality 123-127 (12%)', + '8f699e4439175f5f0cf0f903040fb3c5:11' => 'Apple QuickTime, Quality 128-133 (13%)', + '50f9224c87a32486851bdbd3e686fd5b:11' => 'Apple QuickTime, Quality 134-137 (13%)', + 'cccd5f36920fbe8ad77da2214f8ab6ed:11' => 'Apple QuickTime, Quality 138-142 (13-14%)', + '8bc7e3b8f24507e284075ebeb272c3f4:11' => 'Apple QuickTime, Quality 143-146 (14%)', + 'bc156b933365b88e5ba9f1bd4b2fee4e:11' => 'Apple QuickTime, Quality 147-150 (14-15%)', + 'a50ff29c6c2a7e73f742ca94678956ba:11' => 'Apple QuickTime, Quality 151-154 (15%)', + 'd0a67359275cf9e2e8f35de79d2e28ae:11' => 'Apple QuickTime, Quality 155-157 (15%)', + '37914b5d31e7f0f13066e5292c07c305:11' => 'Apple QuickTime, Quality 158-161 (15-16%)', + '340aeb15b2b6c05968bb2c6e3d85cbed:11' => 'Apple QuickTime, Quality 162-164 (16%)', + 'bc93228921ec863e90850325cfd90dd2:11' => 'Apple QuickTime, Quality 165-167 (16%)', + 'd5c95455812515ad4855ed725d5bf2d9:11' => 'Apple QuickTime, Quality 168-170 (16-17%)', + 'd018c811df2390446b43cc702888864c:11' => 'Apple QuickTime, Quality 171-173 (17%)', + '824a9788f50aad6ca26ada301cae5c72:11' => 'Apple QuickTime, Quality 174-176 (17%)', + 'd35254d58224b1b6babda94d7f1a5ffe:11' => 'Apple QuickTime, Quality 177-179 (17%)', + '4177be1c82543b32bf6578dc3a78d49d:11' => 'Apple QuickTime, Quality 180-182 (18%)', + '88b94edfd7a6c7aadac520905e6cfa0a:11' => 'Apple QuickTime, Quality 183-184 (18%)', + '589b1ef8cc8bece150218e4646d9dfd6:11' => 'Apple QuickTime, Quality 185-187 (18%)', + 'a6c15a75ab70e28c78e6084f909523bf:11' => 'Apple QuickTime, Quality 188-189 (18%)', + 'd052e48078f986c715e68f502d371ccc:11' => 'Apple QuickTime, Quality 190-191 (19%)', + '7d4205e3d4e0b6c7071a418c9b5840cb:11' => 'Apple QuickTime, Quality 192-194 (19%)', + '2200d1873e51bf812bdcb57c10c6c14b:11' => 'Apple QuickTime, Quality 195-196 (19%)', + '395ef59782311cd2081887c78c40c4bc:11' => 'Apple QuickTime, Quality 197-198 (19%)', + 'd33d12dc779097bee959fefac6de9a3e:11' => 'Apple QuickTime, Quality 199-201 (19-20%)', + '64ff54dc33f610e3705cae31428ce43d:11' => 'Apple QuickTime, Quality 202-203 (20%)', + 'dbee605b07dfe30c992622877dffb049:11' => 'Apple QuickTime, Quality 204-205 (20%)', + 'aa5a427657696f05da789e1516b8c2ff:11' => 'Apple QuickTime, Quality 206-207 (20%)', + 'cf8fce0d4bde00a2feb680bb52667c8f:11' => 'Apple QuickTime, Quality 208-209 (20%)', + '81ac42cc63416f7c66cd2a51a8801cbd:11' => 'Apple QuickTime, Quality 210-211 (21%)', + '5e55cc3328e61e88b9f2a49af4ec2268:11' => 'Apple QuickTime, Quality 212-213 (21%)', + 'ef938a0533502fe19f311d46c43fa86c:11' => 'Apple QuickTime, Quality 214-215 (21%)', + 'f841cbd6a77d64924ab19845219f3399:11' => 'Apple QuickTime, Quality 216-217 (21%)', + '98b684f30055c84ba5734e29f7b98b5f:11' => 'Apple QuickTime, Quality 218 (21%)', + '8d4f697b3a2baaecc8765f31f54a76ae:11' => 'Apple QuickTime, Quality 219-220 (21%)', + '6fc283989bb3a8c91f6c4384df2fa25d:11' => 'Apple QuickTime, Quality 221-222 (22%)', + 'dccca51d261b315120f069697872377d:11' => 'Apple QuickTime, Quality 223-224 (22%)', + '5869e4a9592a7900e740b09fe19261a1:11' => 'Apple QuickTime, Quality 225 (22%)', + 'ebd575cf069eb906d2f2b2e202f67247:11' => 'Apple QuickTime, Quality 226-227 (22%)', + '7ed52852c280b97fd44def8434d84051:11' => 'Apple QuickTime, Quality 228-229 (22%)', + '984d291debac8a0caeaccccea5fbfbdf:11' => 'Apple QuickTime, Quality 230 (22%)', + '9b2247e0f55b4485e7c55a04ee6a801c:11' => 'Apple QuickTime, Quality 231-232 (23%)', + 'd2a1887cf45aecd63d838e585dbb5794:11' => 'Apple QuickTime, Quality 233-234 (23%)', + '6bb5ab15f80beebcb73fae0ef089fa61:11' => 'Apple QuickTime, Quality 235 (23%)', + '281f65a19e5de33d9ff5f3afeda06973:11' => 'Apple QuickTime, Quality 236-237 (23%)', + '563f732877b2c654d571c269bbb36a40:11' => 'Apple QuickTime, Quality 238 (23%)', + 'fa11118bb9f90b1464e34c785d0da357:11' => 'Apple QuickTime, Quality 239-240 (23%)', + '8dc4cff27c3c5196b4bc8905ef32f119:11' => 'Apple QuickTime, Quality 241 (24%)', + '2ac28889e4ad4724d49f8b4c36b0cece:11' => 'Apple QuickTime, Quality 242-243 (24%)', + '5cbeb8f83a47b6a5e8711fe0ea7c42d7:11' => 'Apple QuickTime, Quality 244 (24%)', + 'd5d329f5687d154e4ceeb48697b848ba:11' => 'Apple QuickTime, Quality 245-246 (24%)', + 'd3eaad34ae4fc8a3ac6330c1c9dceb28:11' => 'Apple QuickTime, Quality 247 (24%)', + '29b74834ce7570b9c175d0200e75316e:11' => 'Apple QuickTime, Quality 248-249 (24%)', + '850f2b2aaa99ad390bc9443be1b587dc:11' => 'Apple QuickTime, Quality 250 (24%)', + '036d2395718f99bf916486e1af42cb92:11' => 'Apple QuickTime, Quality 251 (25%)', + 'e9275719ef4cb335f9dfed63c3737f0e:11' => 'Apple QuickTime, Quality 252-253 (25%)', + 'dfcbd3df5c6b96106e6348b77f89c56a:11' => 'Apple QuickTime, Quality 254 (25%)', + 'f9ef906cd67c9f9b62514a6ac1f8bd3f:11' => 'Apple QuickTime, Quality 255 (25%)', + '469d14cef27dbb7c1f6f49324c077852:11' => 'Apple QuickTime, Quality 256-257 (25%)', + '65d7471a913f6cc87e9dc65ea594606b:11' => 'Apple QuickTime, Quality 258 (25%)', + '6b590185b5d6ecbc1d79c2624a0d5319:11' => 'Apple QuickTime, Quality 259 (25%)', + 'fbf3d8d87f68077aa95e5e40047c1607:11' => 'Apple QuickTime, Quality 260-261 (25%)', + '7e3999424de8a8f6bb84e3cfc07628e8:11' => 'Apple QuickTime, Quality 262 (26%)', + '6c0476ba4b3fcc4675cfab20d3c96368:11' => 'Apple QuickTime, Quality 263 (26%)', + '0bb76dd0e08175a90343a9c7dab48bfa:11' => 'Apple QuickTime, Quality 264-265 (26%)', + '83c8ceab43dedde06d8068e5b8ccdc2b:11' => 'Apple QuickTime, Quality 266 (26%)', + '5aee693372b77c9721dba9d3596e371c:11' => 'Apple QuickTime, Quality 267 (26%)', + '1312bc5c7456856400f43749d407fb9f:11' => 'Apple QuickTime, Quality 268 (26%)', + '3f01645e33791ef09fbeb6c0e63db6a9:11' => 'Apple QuickTime, Quality 269 (26%)', + '785c36a6aa2bedd207cb1fa450a5e6d4:11' => 'Apple QuickTime, Quality 270-271 (26%)', + '84788c494352a07ab54f360f4a2a3d34:11' => 'Apple QuickTime, Quality 272 (27%)', + 'bf29abfdf0086437452e2ca220e69cae:11' => 'Apple QuickTime, Quality 273 (27%)', + 'c7da2e951711b8b1314a7c531e09cbdc:11' => 'Apple QuickTime, Quality 274 (27%)', + 'fb549f21b7ad3b556bc91165b3067a77:11' => 'Apple QuickTime, Quality 275 (27%)', + '0a7497e67acef345c655f79fd00b26de:11' => 'Apple QuickTime, Quality 276 (27%)', + '1e2be0dde2c5d2216bca879a3f89c565:11' => 'Apple QuickTime, Quality 277-278 (27%)', + 'd09f78b68290ff6b470720ead4d79b15:11' => 'Apple QuickTime, Quality 279 (27%)', + '5b54396a8a725e49e9bd4c9883b151df:11' => 'Apple QuickTime, Quality 280 (27%)', + 'f60d4afe566a641f0187a42ca6462560:11' => 'Apple QuickTime, Quality 281 (27%)', + 'b69090d1ab951e6355ab193b1f20bf48:11' => 'Apple QuickTime, Quality 282 (28%)', + '7ce7d00283cada911c3ebc347680bc7d:11' => 'Apple QuickTime, Quality 283 (28%)', + '2502314c1b957a0e4f911d17db770a01:11' => 'Apple QuickTime, Quality 284 (28%)', + '100f3392aa8292fb78548513a619671a:11' => 'Apple QuickTime, Quality 285 (28%)', + 'af683de3118ab595c41b5796b57a9540:11' => 'Apple QuickTime, Quality 286 (28%)', + '1228f1572d76b53658f4042bda8e99a2:11' => 'Apple QuickTime, Quality 287 (28%)', + 'e9c647b8bf2d7535d259eed6fbabe206:11' => 'Apple QuickTime, Quality 288 (28%)', + '9ab0afefad0e6bb7c3c1a8bca0c3f987:11' => 'Apple QuickTime, Quality 289 (28%)', + 'b6900aafebce0e59136abb701eacb1e5:11' => 'Apple QuickTime, Quality 290 (28%)', + 'a3c40b635e584c8f49d6b6b110846fee:11' => 'Apple QuickTime, Quality 291-292 (28-29%)', + '80175a9dbb871d045c738fdeb6fcbdc7:11' => 'Apple QuickTime, Quality 293 (29%)', + 'c79231716eff96853fe03a26c1c38120:11' => 'Apple QuickTime, Quality 294 (29%)', + '8f96a0f2af7f1f1b0b2d4895bced1326:11' => 'Apple QuickTime, Quality 295 (29%)', + 'ba3c103d00719e795b093ac7a75e6fac:11' => 'Apple QuickTime, Quality 296 (29%)', + '42fd2864197991a38b3f80374a69d4e9:11' => 'Apple QuickTime, Quality 297 (29%)', + '76bc1d777c94b680683610218732eb11:11' => 'Apple QuickTime, Quality 298 (29%)', + '8b9e19fe69d7c7e1989018aca76c0aea:11' => 'Apple QuickTime, Quality 299 (29%)', + 'd3c0e7437c630f3bed0867737c5f1921:11' => 'Apple QuickTime, Quality 300 (29%)', + 'a8ecf55a88fd0e1b29646207aff8c36f:11' => 'Apple QuickTime, Quality 301 (29%)', + 'eaffe0714878be5fb67a914f5bb79fef:11' => 'Apple QuickTime, Quality 302 (29%)', + 'a6a49ea0300157ecb401ce45d7f1f850:11' => 'Apple QuickTime, Quality 303 (30%)', + 'fc28ca358af7cd55dc78853e4288f26d:11' => 'Apple QuickTime, Quality 304 (30%)', + '61cb5e93e3e69f6929d97653824733b0:11' => 'Apple QuickTime, Quality 305 (30%)', + '2cba6ba1aede8c791ada1acaba8c162e:11' => 'Apple QuickTime, Quality 306 (30%)', + 'c1bcc3db9f417dc52595f2bb224e30d7:11' => 'Apple QuickTime, Quality 307 (30%)', + '2273274a8d695da4bebff145cbcbafcc:11' => 'Apple QuickTime, Quality 308 (30%)', + 'e8bdbff8c7908e36c51e1344c0e99746:11' => 'Apple QuickTime, Quality 309 (30%)', + 'ffb8ea8efdb22c5c8256cc4e4008f11c:11' => 'Apple QuickTime, Quality 310 (30%)', + 'a1a8f92dc00c42877eb9a1d7462f8408:11' => 'Apple QuickTime, Quality 311 (30%)', + '723c2a2de195391f2db06456e9345c5b:11' => 'Apple QuickTime, Quality 312 (30%)', + '916225049ab8d411a5e0138ea9087e37:11' => 'Apple QuickTime, Quality 313 (31%)', + '3b0315316de45b649bd8ba5b5471ab81:11' => 'Apple QuickTime, Quality 314 (31%)', + '6cf948e65c9d32279c757394a4f5b77e:11' => 'Apple QuickTime, Quality 315 (31%)', + '4c4b7fc28e54a2bbdccd90d3618f01e8:11' => 'Apple QuickTime, Quality 316 (31%)', + '767c20d7d54970b0974f205c790d7d04:11' => 'Apple QuickTime, Quality 317 (31%)', + '81c1ce1c7d15394d95eaf2d6bd1495e3:11' => 'Apple QuickTime, Quality 318 (31%)', + '6547daee398d39f773742be92ef2d0d0:11' => 'Apple QuickTime, Quality 319 (31%)', + '65edf81f975f01a7b3ad1c16a1af64cb:11' => 'Apple QuickTime, Quality 320 (31%)', + 'f8948967aeda9fb6ca1637a082ed04db:11' => 'Apple QuickTime, Quality 321 (31%)', + '2444e1c407a9965fb5ea2dafd269911f:11' => 'Apple QuickTime, Quality 322-324 (31-32%)', + '7c8242581553e818ef243fc680879a19:11' => 'Apple QuickTime, Quality 325 (32%)', + 'e2fe91d57078586f15b09e3b9c8cd3fa:11' => 'Apple QuickTime, Quality 326 (32%)', + '0740db8af7951c1363f2c8d75462d378:11' => 'Apple QuickTime, Quality 327 (32%)', + '3c1ff7ebab192163b4578e7dfcf63ce6:11' => 'Apple QuickTime, Quality 328 (32%)', + '705ae76b905302bd9f3b78cc8d1cb28f:11' => 'Apple QuickTime, Quality 329 (32%)', + '9438633929a283aac168f415d8ca44d6:11' => 'Apple QuickTime, Quality 330 (32%)', + '68799ccfa08e2f55b5be79264d3ca58a:11' => 'Apple QuickTime, Quality 331 (32%)', + '9bda57f21c56ea0dc971164b8dc56394:11' => 'Apple QuickTime, Quality 332 (32%)', + 'f9988c61ae580fcfc8bf929134b07c2e:11' => 'Apple QuickTime, Quality 333 (33%)', + '59faa8c6fb70d4cf42765a92c1c7afc1:11' => 'Apple QuickTime, Quality 334 (33%)', + '277982593a55786fe424c80a17224cd7:11' => 'Apple QuickTime, Quality 335 (33%)', + 'c2a8a67d050b22a0673ee9ad6685a540:11' => 'Apple QuickTime, Quality 336 (33%)', + '040e09f495355470a44c580bca654693:11' => 'Apple QuickTime, Quality 337 (33%)', + '93173762094b6b506aa495e022ced65f:11' => 'Apple QuickTime, Quality 338 (33%)', + '281c39340554f672ff62c65e0bf1036b:11' => 'Apple QuickTime, Quality 339 (33%)', + '82d40afcb23ac10dba01bbab101da176:11' => 'Apple QuickTime, Quality 340 (33%)', + 'f56a4679494e5af4692381caa63b9062:11' => 'Apple QuickTime, Quality 341 (33%)', + '78787c9f0aae4ab8d15ab47eaea5035c:11' => 'Apple QuickTime, Quality 342 (33%)', + 'a1664b510ce4c6aa3588cdbc327a6f57:11' => 'Apple QuickTime, Quality 343 (33%)', + 'f6150beda200179d9744527637e52baa:11' => 'Apple QuickTime, Quality 344 (34%)', + '620244f053fef313466fbcb232077aca:11' => 'Apple QuickTime, Quality 345 (34%)', + '91c1b36d4411306ba3afaea0658f1ad8:11' => 'Apple QuickTime, Quality 346 (34%)', + '0381b4e34e700adecd618afdcfb5513e:11' => 'Apple QuickTime, Quality 347 (34%)', + '4d8f909ee8cb53e0386eb09c1591099b:11' => 'Apple QuickTime, Quality 348 (34%)', + 'f7425d5d0a0207e6dfaa0ee7c35d4ec6:11' => 'Apple QuickTime, Quality 349 (34%)', + '8d0663f8149a308365e18bdeb8c867e8:11' => 'Apple QuickTime, Quality 350 (34%)', + '4fa58542b5953534072b6dc1085deadf:11' => 'Apple QuickTime, Quality 351 (34%)', + '2358594d2a85b48dc0bd03e024dec9bd:11' => 'Apple QuickTime, Quality 352 (34%)', + 'b9594c8100236f288cdc01e6488cbc41:11' => 'Apple QuickTime, Quality 353 (34%)', + '3542444d51fa859ed5af78a1f5fc4f36:11' => 'Apple QuickTime, Quality 354 (35%)', + '7c95c94440f652232530fe4c411be1a2:11' => 'Apple QuickTime, Quality 355 (35%)', + '8361a9dbb5d93ad098a0ce2091b0bdf5:11' => 'Apple QuickTime, Quality 356 (35%)', + '44c8e4d0d7678034cb206609652ffeef:11' => 'Apple QuickTime, Quality 357 (35%)', + '4694896b11fb898106e30fd4ed50cded:11' => 'Apple QuickTime, Quality 358 (35%)', + '9ddc6134fe65ea64048fdfd27c82bed7:11' => 'Apple QuickTime, Quality 359 (35%)', + 'c60f75f7e09f0454db9cc48392a7eeed:11' => 'Apple QuickTime, Quality 360 (35%)', + '151731e5cd38be847f4dad794c023a69:11' => 'Apple QuickTime, Quality 361 (35%)', + '0468ecbf6fc1303467adfdcab8edfe6d:11' => 'Apple QuickTime, Quality 362 (35%)', + 'debd5adf671e3b907c10155cc910dcc1:11' => 'Apple QuickTime, Quality 363 (35%)', + '6385ee79b090ea430190dbe1ee93ddca:11' => 'Apple QuickTime, Quality 364 (36%)', + '67ed20f2fe283549dae4ba40860c3777:11' => 'Apple QuickTime, Quality 365 (36%)', + 'e168523157ee45551ba30378d597dfd6:11' => 'Apple QuickTime, Quality 366 (36%)', + 'd0cbe6c7372724a802d0183c6de66f8b:11' => 'Apple QuickTime, Quality 367 (36%)', + '38a1f9d86241eb3b96d5d42bc6587598:11' => 'Apple QuickTime, Quality 368 (36%)', + '4dc4b433113acbde9d77a4cbad69bb14:11' => 'Apple QuickTime, Quality 369 (36%)', + '186948d91ea43a64f874ebb9dee44564:11' => 'Apple QuickTime, Quality 370 (36%)', + '786aa4e46172ac65e10b230f3dcaadb2:11' => 'Apple QuickTime, Quality 371 (36%)', + 'ac76c6ebb64c843736fc765a03674d94:11' => 'Apple QuickTime, Quality 372 (36%)', + '38a60cdb8033a9f90027895eab0c40ba:11' => 'Apple QuickTime, Quality 373 (36%)', + 'ce48f7fb2ba9edee46c3f4839b40ef60:11' => 'Apple QuickTime, Quality 374 (37%)', + '7b3058792db9876a86c65ec44c0261b3:11' => 'Apple QuickTime, Quality 375 (37%)', + '5e983407295808e244f6bdece469c8be:11' => 'Apple QuickTime, Quality 376 (37%)', + '68ff8bfc0e15c93586ef6b4cf347469c:11' => 'Apple QuickTime, Quality 377 (37%)', + '9d4a8c44917390e56bca2352a8a4b1be:11' => 'Apple QuickTime, Quality 378 (37%)', + '36e7560256c5ffd285a1ca0f6d4bf97d:11' => 'Apple QuickTime, Quality 379 (37%)', + 'a88bad671d80cf6a70bd6e37be9c95c9:11' => 'Apple QuickTime, Quality 380 (37%)', + '23ab27876006666358e95d9c1104bcd0:11' => 'Apple QuickTime, Quality 381 (37%)', + 'b87750acf49940bf1f01f6a134a600b1:11' => 'Apple QuickTime, Quality 382 (37%)', + '731fa7404c090db157030e40804604b6:11' => 'Apple QuickTime, Quality 383 (37%)', + '442c2664c07af1ec15d86581f43aab0b:11' => 'Apple QuickTime, Quality 384 (38%)', + '145c52a48a9b2e954e785c3f8df5c27e:11' => 'Apple QuickTime, Quality 385 (38%)', + '55d37ee1e3c8d12a70e67206fa1c9b0c:11' => 'Apple QuickTime, Quality 386 (38%)', + '60880ff1f7bfe6a85cd80c2d4582395b:11' => 'Apple QuickTime, Quality 387 (38%)', + '85fc5daf51e6cbb04352016c817e5714:11' => 'Apple QuickTime, Quality 388 (38%)', + 'd7c835210eec5a8bedb3a18d32cbe066:11' => 'Apple QuickTime, Quality 389 (38%)', + '315e7fee22864b37b1b7670957f259fe:11' => 'Apple QuickTime, Quality 390 (38%)', + '46dd3917c1473ed0f8fc3f1e6f08416d:11' => 'Apple QuickTime, Quality 391 (38%)', + '1e93645e6163af46937c35a18b55c601:11' => 'Apple QuickTime, Quality 392 (38%)', + 'ba1a32697c0ae4e76a78f4b5624a8ce0:11' => 'Apple QuickTime, Quality 393 (38%)', + '68a0d6250be9df2c05556ff59988c499:11' => 'Apple QuickTime, Quality 394 (38%)', + '13b1310840627eddaf435e9feffebebe:11' => 'Apple QuickTime, Quality 395 (39%)', + '2e420a34dcf01dab91fd8509d4dbaab5:11' => 'Apple QuickTime, Quality 396 (39%)', + 'eef3afec34329517513541a8509b7aab:11' => 'Apple QuickTime, Quality 397 (39%)', + '80bdd75a2fc87b5288bc77763481df83:11' => 'Apple QuickTime, Quality 398 (39%)', + 'e230e3ac7c740f3e8fe6bc74fff72c10:11' => 'Apple QuickTime, Quality 399 (39%)', + '68b07a219cda4b9fc9a8507b788d8230:11' => 'Apple QuickTime, Quality 400 (39%)', + 'f1c23475d19d9e950dbc4086902365a3:11' => 'Apple QuickTime, Quality 401 (39%)', + 'dc2af4340202aa481491b86539888720:11' => 'Apple QuickTime, Quality 402 (39%)', + '495aeee0f43a596938c98c5364feb2ee:11' => 'Apple QuickTime, Quality 403 (39%)', + '8319dfe3caedea6988e5024b0196d317:11' => 'Apple QuickTime, Quality 404 (39%)', + 'd62cd17e8e04ebd568a8f5abc38cad4a:11' => 'Apple QuickTime, Quality 405 (40%)', + '047e1711c44262f352034452d0b0d07b:11' => 'Apple QuickTime, Quality 406 (40%)', + '552bf986ae119444955ded5f485d5dc4:11' => 'Apple QuickTime, Quality 407 (40%)', + 'd39329b38fdcabe9e1ae5f1b205c825a:11' => 'Apple QuickTime, Quality 408 (40%)', + 'bf2904a3e3870a2b4d060e0863530d92:11' => 'Apple QuickTime, Quality 409 (40%)', + '1acceb7ae4f9edbb835006d97ca30094:11' => 'Apple QuickTime, Quality 410 (40%)', + '5de50c687a6e885634bf16adfd75e6bc:11' => 'Apple QuickTime, Quality 411 (40%)', + 'd92c5bba7cfd1bfbb8c662c1a27ca413:11' => 'Apple QuickTime, Quality 412 (40%)', + 'cea44b5645cd1dbf469c8ae5600e4ff5:11' => 'Apple QuickTime, Quality 413 (40%)', + '5caf3989a757842c716220e4e426bde2:11' => 'Apple QuickTime, Quality 414 (40%)', + 'fd2f7a6518c12848a9ecdb1c3beb1fa8:11' => 'Apple QuickTime, Quality 415 (41%)', + 'de0547c872fed9c9c75c8fec2fe010e6:11' => 'Apple QuickTime, Quality 416 (41%)', + '6cf4dfbe3df89d9728e0f34b7b145223:11' => 'Apple QuickTime, Quality 417 (41%)', + 'd94d79b70686d3e2568d61d07e5819eb:11' => 'Apple QuickTime, Quality 418 (41%)', + '9ec82f50503769a9bb17e876594833b6:11' => 'Apple QuickTime, Quality 419 (41%)', + '4a39b0ae55f0eaa5672f00015cae2d40:11' => 'Apple QuickTime, Quality 420 (41%)', + '42bae7ef4a41562b2e98d74248f4f22e:11' => 'Apple QuickTime, Quality 421 (41%)', + '8c0ea132cfacf212c518ad297229be34:11' => 'Apple QuickTime, Quality 422 (41%)', + 'c1af7f1a3716bef087124306b068605c:11' => 'Apple QuickTime, Quality 423 (41%)', + 'd3ea3c519f92dd870fed03f63cabf05e:11' => 'Apple QuickTime, Quality 424 (41%)', + '0442196d850319833f27df632e92f064:11' => 'Apple QuickTime, Quality 425 (42%)', + '8c372e99fa96d2598e431f8137e47da6:11' => 'Apple QuickTime, Quality 426 (42%)', + '9bade640c3fcb807ed1322479f9e7f1c:11' => 'Apple QuickTime, Quality 427 (42%)', + '8015ad9fa22d6565ca61ce9979f3663f:11' => 'Apple QuickTime, Quality 428 (42%)', + '09a13f94022839a24065b82d5f4ffdbd:11' => 'Apple QuickTime, Quality 429 (42%)', + '0e570bc627acaee0962472a1a646816b:11' => 'Apple QuickTime, Quality 430 (42%)', + 'be7e7114f08e1775ca9676d2feeeccca:11' => 'Apple QuickTime, Quality 431 (42%)', + '44be972c54cd64be7524a133a7395401:11' => 'Apple QuickTime, Quality 432 (42%)', + 'b2f7b5e3007387aa22df74e82e916195:11' => 'Apple QuickTime, Quality 433 (42%)', + '5c13c8db3a0b590f4fa3ec462b8890c3:11' => 'Apple QuickTime, Quality 434 (42%)', + '2733a3cb2e0a2313b74d686437fa3ae2:11' => 'Apple QuickTime, Quality 435 (42%)', + '66309175abaa59d6246237a77ce9eb76:11' => 'Apple QuickTime, Quality 436 (43%)', + '6a2eb9f07f3c96365a06d91da171e673:11' => 'Apple QuickTime, Quality 437 (43%)', + 'e395118c42b6492dd4d9d30754f0a697:11' => 'Apple QuickTime, Quality 438 (43%)', + '7a75abc5c5ec8cc0fa43f239ab048c08:11' => 'Apple QuickTime, Quality 439 (43%)', + 'c558f3407dc549c902efad68c54920de:11' => 'Apple QuickTime, Quality 440 (43%)', + '49cd1849b501868260d8a3b1e96d8625:11' => 'Apple QuickTime, Quality 441 (43%)', + 'f7d70cfab7ff888c97078d277fa01307:11' => 'Apple QuickTime, Quality 442 (43%)', + 'f06ddea698cebe653bdd0c208c3d8c95:11' => 'Apple QuickTime, Quality 443 (43%)', + '73478bb7714d1d2342bbf22c5fdc04d6:11' => 'Apple QuickTime, Quality 444 (43%)', + '24406aee81b89ea50881ae71f878d0ec:11' => 'Apple QuickTime, Quality 445 (43%)', + 'e3e88302627b6743725cace74ddb17f9:11' => 'Apple QuickTime, Quality 446 (44%)', + '3fb9c046dff30dcb4128df984532d6ba:11' => 'Apple QuickTime, Quality 447 (44%)', + 'c9a4b04bc8e580608014b6f3111322d7:11' => 'Apple QuickTime, Quality 448 (44%)', + '7749ec06b1f1b1be30aa58dbef838d49:11' => 'Apple QuickTime, Quality 449 (44%)', + 'c0a54e87a2ef1c163311bcc1abf85214:11' => 'Apple QuickTime, Quality 450 (44%)', + 'f20a253d2513f4d8f2cfeea980852820:11' => 'Apple QuickTime, Quality 451 (44%)', + '6538fc6f5f1744b40c0b8b5bc7179983:11' => 'Apple QuickTime, Quality 452 (44%)', + '68a4a67af696f82bbbb7db15a16c0c46:11' => 'Apple QuickTime, Quality 453 (44%)', + 'e477932560b308940ac7439eed9f63da:11' => 'Apple QuickTime, Quality 454 (44%)', + 'fd732b0493e7ff16da4bde7faa88e22d:11' => 'Apple QuickTime, Quality 455 (44%)', + '61884dc8b93e63c07bb487a6e29d6fb7:11' => 'Apple QuickTime, Quality 456 (45%)', + '67515a725833d40535a54b4ef9551e05:11' => 'Apple QuickTime, Quality 457 (45%)', + 'cc6bb734b742b0631ab6562a329e1603:11' => 'Apple QuickTime, Quality 458 (45%)', + '1801686a97836f690ce3d5523ffcfa9a:11' => 'Apple QuickTime, Quality 459 (45%)', + 'f73f690cacd5d4e247f59964ad0f43b9:11' => 'Apple QuickTime, Quality 460 (45%)', + '853946ede6a624136546ec5b68ecdc49:11' => 'Apple QuickTime, Quality 461 (45%)', + 'f05c48d79edbefdb4d260dc23cf258e6:11' => 'Apple QuickTime, Quality 462 (45%)', + '8dc8361e94137f5466c8dd1f9aa06781:11' => 'Apple QuickTime, Quality 463 (45%)', + '6c121faf4784a5a93fbf7fff4470dea4:11' => 'Apple QuickTime, Quality 464-465 (45%)', + 'd0eaa368737f17f6037757d393a22599:11' => 'Apple QuickTime, Quality 466-467 (46%)', + '9c6f5faa1009cafe8bc3060fe18d4b60:11' => 'Apple QuickTime, Quality 468 (46%)', + 'ac47d493602dddace7844a9bc962e5ed:11' => 'Apple QuickTime, Quality 469 (46%)', + '24784b5651e1790242c01de522a6e05b:11' => 'Apple QuickTime, Quality 470 (46%)', + 'adbb56f1f0e0392392f9c7a38351a9ec:11' => 'Apple QuickTime, Quality 471 (46%)', + '6e0952a44c37bc2d98dbede4ec429c99:11' => 'Apple QuickTime, Quality 472 (46%)', + '20c7942ddec30475a182cb281f12bc03:11' => 'Apple QuickTime, Quality 473 (46%)', + '4080277d75b20871d00ebc01ffbdb848:11' => 'Apple QuickTime, Quality 474 (46%)', + '4f15f7e4c56e7a75c0fe5454ab7e8f72:11' => 'Apple QuickTime, Quality 475 (46%)', + 'ff82adb92189413246aee9a992eb2013:11' => 'Apple QuickTime, Quality 476 (46%)', + '16df79eb7c5f062aeebde385fbce1553:11' => 'Apple QuickTime, Quality 477 (47%)', + 'df02b0ea9dab7d291950b6cfc65c4bb1:11' => 'Apple QuickTime, Quality 478 (47%)', + '4ca8ec2a0c651e0508aab3b153cfee23:11' => 'Apple QuickTime, Quality 479 (47%)', + 'bbbae155e558e9d37686ec34bd065a53:11' => 'Apple QuickTime, Quality 480 (47%)', + '9bf86a5ec6e5382f214e07364a62b1b3:11' => 'Apple QuickTime, Quality 481 (47%)', + '41d873034f29b298d899b48cd321c93f:11' => 'Apple QuickTime, Quality 482 (47%)', + '52092035b4e3fd45de3298c4d641385a:11' => 'Apple QuickTime, Quality 483 (47%)', + '70e5babe9507bae6725e401a36903070:11' => 'Apple QuickTime, Quality 484 (47%)', + '3cfa966dde2536c83c921aa250b978b3:11' => 'Apple QuickTime, Quality 485 (47%)', + 'b0144b1d2671d145d29812ebcebd863d:11' => 'Apple QuickTime, Quality 486 (47%)', + '2a6a136faaf1f13c2b80dcb4786d90b2:11' => 'Apple QuickTime, Quality 487 (48%)', + '3a6eac793d818f378e7b24826c9115cc:11' => 'Apple QuickTime, Quality 488 (48%)', + '4a78c6570fc84378e3334bfcd8a5680f:11' => 'Apple QuickTime, Quality 489 (48%)', + '0709c0afc0eae932a50903e56ec95ad2:11' => 'Apple QuickTime, Quality 490 (48%)', + 'b013b5c9b7bafc9dcad9a1e87fc629ff:11' => 'Apple QuickTime, Quality 491 (48%)', + '7cb380e582317b8387037450cc68db5e:11' => 'Apple QuickTime, Quality 492 (48%)', + 'f94618c1a011209cb3b060887c7e244e:11' => 'Apple QuickTime, Quality 493 (48%)', + '649a90949cab8f45d3ecef78068165d1:11' => 'Apple QuickTime, Quality 494 (48%)', + '70e105a22b036f7c1ce0b5d02fa1c34e:11' => 'Apple QuickTime, Quality 495 (48%)', + '18c10ea6fe5918e09daf1a3a7a74e678:11' => 'Apple QuickTime, Quality 496 (48%)', + '23822cafcc61ce2a52691f1fc963ff18:11' => 'Apple QuickTime, Quality 497 (49%)', + '5bb2cf3e6721c2dd8eb3341f9bff4159:11' => 'Apple QuickTime, Quality 498 (49%)', + 'e55b5345d9668d1b11b657537f707072:11' => 'Apple QuickTime, Quality 499 (49%)', + '4cbebcb06d1003e29429e9d5c9445919:11' => 'Apple QuickTime, Quality 500 (49%)', + '916b16f020b2b21e4c8114da8c05d584:11' => 'Apple QuickTime, Quality 501 (49%)', + '98abef3366c7f451e44f5c2799e2be6d:11' => 'Apple QuickTime, Quality 502 (49%)', + 'f8e99ed03828752f16c51bb8c9887e9e:11' => 'Apple QuickTime, Quality 503 (49%)', + 'eef05c558c1aba5cf2891fb13ee07167:11' => 'Apple QuickTime, Quality 504 (49%)', + 'cb5fc7927d88ac99f556b2dd7985eaf9:11' => 'Apple QuickTime, Quality 505 (49%)', + 'f0e3f635bbcf96654812e8c78b227701:11' => 'Apple QuickTime, Quality 506 (49%)', + '234c9cf6d7fe671b52c3ec5a20046ec8:11' => 'Apple QuickTime, Quality 507 (50%)', + '9dfcc9ae3baee4bb4ad63abf2f740275:11' => 'Apple QuickTime, Quality 508 (50%)', + 'b1f1b6519991ac7696b233dd9b9de6b5:11' => 'Apple QuickTime, Quality 509 (50%)', + 'dba2f5203ffecada66a8bf9b1272f1eb:11' => 'Apple QuickTime, Quality 510 (50%)', + '367b3d63cddc0cd27e58030c2b8f1aaa:11' => 'Apple QuickTime, Quality 511 (50%)', + 'c28ab3fd6480c92028327957228c0a11:11' => 'Apple QuickTime, Quality 512 (50%)', + '6bc9ebaf9f3ed62ec8818076f6f81c7f:11' => 'Apple QuickTime, Quality 513 (50%)', + '3bbfcd817441d2267a49bf76b48c5f47:11' => 'Apple QuickTime, Quality 514 (50%)', + '27e6ed2cecfebe31eb3d66128c926562:11' => 'Apple QuickTime, Quality 515 (50%)', + '3cf112c5843f98410599ea2a197e5cf6:11' => 'Apple QuickTime, Quality 516 (50%)', + '2821aae8108df4bd98e5eaa451a351d2:11' => 'Apple QuickTime, Quality 517 (50%)', + '798f48b6dbe3f1cd7b40b03fae8d2611:11' => 'Apple QuickTime, Quality 518 (51%)', + '67a7c8896d03a030b56130e1f9c5caad:11' => 'Apple QuickTime, Quality 519 (51%)', + '4bf1b53c292dec3f7cf3c020a3a9d911:11' => 'Apple QuickTime, Quality 520 (51%)', + '2bfe0ace876b80be6f601a1703187d94:11' => 'Apple QuickTime, Quality 521 (51%)', + '7590bc1a40090163a101bfd28daa3fc2:11' => 'Apple QuickTime, Quality 522 (51%)', + '118c7b118b1df404c90cfb1d10cf2a77:11' => 'Apple QuickTime, Quality 523 (51%)', + '86cfac24ca9f4ab254f882ad399ea758:11' => 'Apple QuickTime, Quality 524 (51%)', + '0268c3e9e3e1c3e6eb25fe0d31940c7f:11' => 'Apple QuickTime, Quality 525 (51%)', + '9beb1b7c55129a34c850c359d7263457:11' => 'Apple QuickTime, Quality 526 (51%)', + '0cec2c8f96c092bd6e7cf0f7ea294c99:11' => 'Apple QuickTime, Quality 527 (51%)', + 'd8c5179c2419775f43e9a7899bacddd7:11' => 'Apple QuickTime, Quality 528 (52%)', + '9ce50f6e0b00d2e601f2fcc151abc4d8:11' => 'Apple QuickTime, Quality 529 (52%)', + '80db52b1671d32d8bd3126bf1d7db8ec:11' => 'Apple QuickTime, Quality 530 (52%)', + 'f3ef06f90579eaf1008e07b94e818a40:11' => 'Apple QuickTime, Quality 531 (52%)', + '3c85026793f58eb45141847a27854fe2:11' => 'Apple QuickTime, Quality 532-533 (52%)', + 'e3042cbd43d2067ae92e1a8ce3f2c5a1:11' => 'Apple QuickTime, Quality 534 (52%)', + 'dd71fdab3d46341a9b6ca0b6c6929d23:11' => 'Apple QuickTime, Quality 535 (52%)', + 'a451c79ccddcd543a80e1ce0449dcb0d:11' => 'Apple QuickTime, Quality 536 (52%)', + '2da67fe5f0bb3c8b10403295895fb154:11' => 'Apple QuickTime, Quality 537 (52%)', + '4f72f3cdc82d433e7f749be8036d4ce0:11' => 'Apple QuickTime, Quality 538 (53%)', + 'da29cc9a4d5fd7e0dc36a2dd0c70e84f:11' => 'Apple QuickTime, Quality 539 (53%)', + '63f61a0d3c4f1ace8ebe5b6ae23e3f25:11' => 'Apple QuickTime, Quality 540 (53%)', + 'fde14219617069bbf6b26dcb42036de7:11' => 'Apple QuickTime, Quality 541 (53%)', + 'c84313bc621c6d05999510fa57c56d05:11' => 'Apple QuickTime, Quality 542 (53%)', + '92658d4c879d6e48bfda1a6e9f49ef8d:11' => 'Apple QuickTime, Quality 543 (53%)', + '3deffd01a1c03929873dddd86a5339f1:11' => 'Apple QuickTime, Quality 544 (53%)', + 'e76c1b26bbd196efe2e793e27727704d:11' => 'Apple QuickTime, Quality 545 (53%)', + '9f3289994c790a10ecb2d93021677840:11' => 'Apple QuickTime, Quality 546 (53%)', + 'f7493b01895b7880c651841c73678d33:11' => 'Apple QuickTime, Quality 547 (53%)', + '3c9d094741c995c2c0ac9daf14c4e683:11' => 'Apple QuickTime, Quality 548 (54%)', + '8c0e1d4cd6138817963af6ca149cb5d5:11' => 'Apple QuickTime, Quality 549 (54%)', + 'd781cc6f686fc7c7b9b6eef90fab4d87:11' => 'Apple QuickTime, Quality 550 (54%)', + '7dd6377a907070b1ca7e05f770ca2aab:11' => 'Apple QuickTime, Quality 551-552 (54%)', + 'c2d5e2e93ec191015d8181c9e25387d8:11' => 'Apple QuickTime, Quality 553 (54%)', + '65d20361f4ba0725cf150c7ae2033776:11' => 'Apple QuickTime, Quality 554 (54%)', + '2d7eb8eb9df9f4831a843626f4fc7e19:11' => 'Apple QuickTime, Quality 555 (54%)', + 'ce0e14187fec73f57242becd633a89a3:11' => 'Apple QuickTime, Quality 556 (54%)', + '140cc5a99ef865e318a217ea069aa84d:11' => 'Apple QuickTime, Quality 557 (54%)', + '0db59bd18beb49f9beb901f3435e22a5:11' => 'Apple QuickTime, Quality 558 (54%)', + '78d19da8de8095644aa31fb409033fe7:11' => 'Apple QuickTime, Quality 559 (55%)', + '00687c4e4852ed1cd446c09a3764e505:11' => 'Apple QuickTime, Quality 560 (55%)', + 'f3795398903c82e1beababf95d3a8413:11' => 'Apple QuickTime, Quality 561 (55%)', + 'b749b90354443bf17da7a67a5ad53397:11' => 'Apple QuickTime, Quality 562 (55%)', + 'c722656df4bb0651821cd90880953a20:11' => 'Apple QuickTime, Quality 563 (55%)', + '4d17c873e65b9d398f27735b0020c777:11' => 'Apple QuickTime, Quality 564 (55%)', + '067a76c2e5386ae85f9187e3e2134621:11' => 'Apple QuickTime, Quality 565 (55%)', + '09b689f7d0c1d4bb0d96d06c02b8dcf8:11' => 'Apple QuickTime, Quality 566 (55%)', + 'ffc0192eb5a182370a641cffe9b1d71f:11' => 'Apple QuickTime, Quality 567 (55%)', + '3af2163438180050bbcf123d4f4587d3:11' => 'Apple QuickTime, Quality 568 (55%)', + '3bdb097a9791f3ce6d7bbc4d6a194aa4:11' => 'Apple QuickTime, Quality 569 (56%)', + '8c1fead15819016583650eff5a4f5bda:11' => 'Apple QuickTime, Quality 570 (56%)', + '967aeb5bc4d75a0d5c0998bbfb282982:11' => 'Apple QuickTime, Quality 571 (56%)', + 'cdd7bd689f14d5f7c3ea790f6f09ae64:11' => 'Apple QuickTime, Quality 572 (56%)', + '6a20041beb5b67d38525bb7507ffeb49:11' => 'Apple QuickTime, Quality 573 (56%)', + '2bf57fbe54370c4d917f259631af033e:11' => 'Apple QuickTime, Quality 574 (56%)', + 'd2e983c44eae2983f48f526992fbbfb4:11' => 'Apple QuickTime, Quality 575 (56%)', + 'c5bb48d86e26ac496bb4b4bc888cc06a:11' => 'Apple QuickTime, Quality 576 (56%)', + 'a595c40b5dbd45557c3c8d23ebee5e24:11' => 'Apple QuickTime, Quality 577 (56%)', + 'f2d84e1114ef85682818b96720d439b5:11' => 'Apple QuickTime, Quality 578 (56%)', + '332d9c49c5b32ae2addbb06a1e32fd49:11' => 'Apple QuickTime, Quality 579 (57%)', + '19c5c7c0270bd36c49f695475a62c293:11' => 'Apple QuickTime, Quality 580 (57%)', + '6516e60b3995e21b6750ebca1ddcfee5:11' => 'Apple QuickTime, Quality 581 (57%)', + '8daf4a87b28106876529a549cf1040b8:11' => 'Apple QuickTime, Quality 582 (57%)', + '6b37d6acc52259bf972a41e84dea7754:11' => 'Apple QuickTime, Quality 583 (57%)', + '588666e111892f10ca3f17bc362d9276:11' => 'Apple QuickTime, Quality 584 (57%)', + '9ec2859c370f557783903608748e7fb1:11' => 'Apple QuickTime, Quality 585 (57%)', + '18e3ac85da74fe92ab5da3d5f7614e09:11' => 'Apple QuickTime, Quality 586 (57%)', + 'da4c88f145393972fbe9d3f40838cab9:11' => 'Apple QuickTime, Quality 587 (57%)', + '8ae7d2b569c437904a20a10bbd21fe89:11' => 'Apple QuickTime, Quality 588 (57%)', + 'fc6dfb9669566b249cb03228aeb020c3:11' => 'Apple QuickTime, Quality 589 (58%)', + '198f3a32e4036d7c37fbc0c343d883af:11' => 'Apple QuickTime, Quality 590 (58%)', + '876ec039f82e49b925b232843b4703d4:11' => 'Apple QuickTime, Quality 591 (58%)', + '673b05962b8255cbc9bdbbc48965b4b7:11' => 'Apple QuickTime, Quality 592 (58%)', + '02e9a58edf45d75be000dee144316c66:11' => 'Apple QuickTime, Quality 593 (58%)', + '2abebf7a61009c5c1aa9516539b9084e:11' => 'Apple QuickTime, Quality 594 (58%)', + 'fe44d8625d6242f4b5deb82be8ccaacf:11' => 'Apple QuickTime, Quality 595 (58%)', + '66529cc8ef9694e6a37e8787d0f160fd:11' => 'Apple QuickTime, Quality 596 (58%)', + '2129ee2bff47bfa8a8bb79ea9fb67b92:11' => 'Apple QuickTime, Quality 597 (58%)', + 'ccb55ec1549a51212859495e104c626b:11' => 'Apple QuickTime, Quality 598 (58%)', + '05e53fb216ba4a1734eefaccd249d8e2:11' => 'Apple QuickTime, Quality 599 (58%)', + 'f4923d7b7dedd365646169e720eee427:11' => 'Apple QuickTime, Quality 600 (59%)', + 'c0f2265630bdf5f29e8c95df25c89edb:11' => 'Apple QuickTime, Quality 601 (59%)', + '0fdd23e8274090da3c925a3db7303adf:11' => 'Apple QuickTime, Quality 602 (59%)', + 'a5bcbd80472fdf697db770ac78d6a4e3:11' => 'Apple QuickTime, Quality 603 (59%)', + 'b157c4aabba2816f391c8f76ca3d4072:11' => 'Apple QuickTime, Quality 604 (59%)', + 'b8ef26dabc2d81a8ba13b1f49ea711d3:11' => 'Apple QuickTime, Quality 605 (59%)', + '8a983844f9b0aec26fc8ac75a258e3ac:11' => 'Apple QuickTime, Quality 606 (59%)', + '44ced96f11e3a410201beed353a864cf:11' => 'Apple QuickTime, Quality 607 (59%)', + '4a14a3e37c89e5a7570f672b1970ca55:11' => 'Apple QuickTime, Quality 608 (59%)', + 'e5ec78e112e3ba6463de24b3518347eb:11' => 'Apple QuickTime, Quality 609 (59%)', + '29b7cdc7a570b950457d20541c22c4ce:11' => 'Apple QuickTime, Quality 610 (60%)', + '470c0c761e2bb5e314a7112f3d64b277:11' => 'Apple QuickTime, Quality 611 (60%)', + 'ced483058f2abf19df0f7935dafd217a:11' => 'Apple QuickTime, Quality 612 (60%)', + '8a202c89c57e77f50e1df27a3be7d5b7:11' => 'Apple QuickTime, Quality 613 (60%)', + '7eb9fe0338a7b802860a60e0088418fd:11' => 'Apple QuickTime, Quality 614 (60%)', + 'ac25112c596d62f95518af109457975c:11' => 'Apple QuickTime, Quality 615 (60%)', + 'f57e9a5f1d8dea7fd83a1b5840243686:11' => 'Apple QuickTime, Quality 616-617 (60%)', + '0eef5c6ff8ba65ff799081a9c96a2297:11' => 'Apple QuickTime, Quality 618-619 (60%)', + '05f98e12bfa14ba6347fb43f2241ba43:11' => 'Apple QuickTime, Quality 620 (61%)', + '91885755c780ebe16b1278a0359eda83:11' => 'Apple QuickTime, Quality 621 (61%)', + 'b44cb1ca15fc9e3a27420df2ddae5879:11' => 'Apple QuickTime, Quality 622 (61%)', + 'ae6c2112dd560530b7bacc8bfa9fb7f6:11' => 'Apple QuickTime, Quality 623 (61%)', + 'd3b05f3cd78e0ac3ab37a02152e22831:11' => 'Apple QuickTime, Quality 624 (61%)', + 'b0c2c3f76d848ee2e8f47a9a90131a21:11' => 'Apple QuickTime, Quality 625 (61%)', + '752fbc15f77a8c2149f5ae6bf49204b8:11' => 'Apple QuickTime, Quality 626 (61%)', + '9c34d3dedfe47d95edabdcbc5568a2a8:11' => 'Apple QuickTime, Quality 627 (61%)', + '252ba8a31aeb601e23b3a70f9af7abc1:11' => 'Apple QuickTime, Quality 628 (61%)', + '359038cd7c45242e96e176e91210922d:11' => 'Apple QuickTime, Quality 629 (61%)', + '8ab83dc2e7ca8b9db1f3b0ab500f3aca:11' => 'Apple QuickTime, Quality 630 (62%)', + '21c9f9a0ff71d4528ef7a19d2cfd0b6c:11' => 'Apple QuickTime, Quality 631 (62%)', + 'a62fb887c209e0fab99fcb7ac81137a2:11' => 'Apple QuickTime, Quality 632 (62%)', + 'e454ca92aca849d59b873d9be817baea:11' => 'Apple QuickTime, Quality 633 (62%)', + '9ad6008e7b4f8478043bfa54e1d9e48e:11' => 'Apple QuickTime, Quality 634 (62%)', + '45b20f0b0d7d88d8330354212af2e087:11' => 'Apple QuickTime, Quality 635 (62%)', + 'b0a00ffee2e55457cd999bba2d07f63e:11' => 'Apple QuickTime, Quality 636 (62%)', + '5dfcb96d9a1186f662c6adb38bb9520a:11' => 'Apple QuickTime, Quality 637 (62%)', + 'd973f38c501796adff40c4f70cbd8885:11' => 'Apple QuickTime, Quality 638 (62%)', + 'dcfe5898ec101a8b2bf98330445dd1bf:11' => 'Apple QuickTime, Quality 639 (62%)', + '2b81eecf0fecd33679adac27e79ef3f4:11' => 'Apple QuickTime, Quality 640-641 (63%)', + '5aad44c55bf4f6dc538eaca006cafac2:11' => 'Apple QuickTime, Quality 642 (63%)', + '7079c2d71ff33e7c4e8efdece23c307b:11' => 'Apple QuickTime, Quality 643 (63%)', + 'a5f724e9d7148f1a84ee597f45c33141:11' => 'Apple QuickTime, Quality 644 (63%)', + '3ae705fae9e895eda345d482525215e3:11' => 'Apple QuickTime, Quality 645 (63%)', + '7cbd635e5fee8bbd290b0d383b03da5a:11' => 'Apple QuickTime, Quality 646 (63%)', + '0f125e2c5ee6b123cf67b586ea23d422:11' => 'Apple QuickTime, Quality 647 (63%)', + '87eac5c1375cca9aa16eba0704616a7b:11' => 'Apple QuickTime, Quality 648-649 (63%)', + 'aa83fd556c569ddcd81e0cc1ba866373:11' => 'Apple QuickTime, Quality 650 (63%)', + 'dab4fa97da49aa37889185c5b43917c1:11' => 'Apple QuickTime, Quality 651 (64%)', + '51ad55cb254f36748123ca83f43556f4:11' => 'Apple QuickTime, Quality 652 (64%)', + '86e707c017682fe08213216d064b1b51:11' => 'Apple QuickTime, Quality 653 (64%)', + '3730182602996b4a1d540eb3fd970072:11' => 'Apple QuickTime, Quality 654 (64%)', + '1bf7a5d7477ad75b9c7b281de622d53b:11' => 'Apple QuickTime, Quality 655 (64%)', + '82b4bc7c4a832b620e810311a33c9771:11' => 'Apple QuickTime, Quality 656 (64%)', + '6502d634e5bf3f849e9d382886fc32fe:11' => 'Apple QuickTime, Quality 657 (64%)', + 'a10e87fa030f8177a4f59f8d16a20afd:11' => 'Apple QuickTime, Quality 658 (64%)', + '338a78a7658ff3c1de33d88aa0ab7c74:11' => 'Apple QuickTime, Quality 659 (64%)', + '4c30c4399ef4bb2920601d940ed404eb:11' => 'Apple QuickTime, Quality 660-661 (64-65%)', + 'ab7cfb73667875854893982a8cfcfab9:11' => 'Apple QuickTime, Quality 662 (65%)', + '7bff346b97abf46ca005af4e74b560fa:11' => 'Apple QuickTime, Quality 663 (65%)', + '2eae93ed601a50284ee31c20651584cb:11' => 'Apple QuickTime, Quality 664 (65%)', + 'e566eaef7eacd6c7161feebf4cec79e8:11' => 'Apple QuickTime, Quality 665 (65%)', + 'a9f461d3bca42dfab57c834fa5f34419:11' => 'Apple QuickTime, Quality 666 (65%)', + '2b394105d4dd418e79b32e66496679d4:11' => 'Apple QuickTime, Quality 667 (65%)', + 'c65677d79e37baf57767e10d7b7f1ce8:11' => 'Apple QuickTime, Quality 668 (65%)', + '688c7dca6b12c22a21e0caf1a0336c80:11' => 'Apple QuickTime, Quality 669-671 (65-66%)', + '20d4b3c9e3c292c68181974704fe5048:11' => 'Apple QuickTime, Quality 672-673 (66%)', + '3bc3948025869f25b143aa517b2154ac:11' => 'Apple QuickTime, Quality 674 (66%)', + '8a2ae82991917070de49cc48d104446f:11' => 'Apple QuickTime, Quality 675 (66%)', + 'b5424d9dce37dd5c9e0e38bcc775f48e:11' => 'Apple QuickTime, Quality 676 (66%)', + '28f718af4edb0069a1fdab00f6ea978d:11' => 'Apple QuickTime, Quality 677 (66%)', + '910416483a49503202cbe3ecee33afc9:11' => 'Apple QuickTime, Quality 678 (66%)', + '153196d4f99569f9bbd3fe0e96d2909c:11' => 'Apple QuickTime, Quality 679 (66%)', + '919a38ebb9fc0bcba388643a9b3ef27c:11' => 'Apple QuickTime, Quality 680 (66%)', + 'ef511ac2c9d7153c16e3e1846325b727:11' => 'Apple QuickTime, Quality 681 (67%)', + 'e8b4ef8f94d89c59c855758a73ec451f:11' => 'Apple QuickTime, Quality 682 (67%)', + 'a09fe2e60a7ff12e1e5ca00afa9719ef:11' => 'Apple QuickTime, Quality 683 (67%)', + 'e56cf84423c16869a9a4fd6605b15ba4:11' => 'Apple QuickTime, Quality 684 (67%)', + 'f64d88456f97a65fe562eb69e619782a:11' => 'Apple QuickTime, Quality 685 (67%)', + '8cbf6cda8ae0249fb91c1ff5ab788a04:11' => 'Apple QuickTime, Quality 686 (67%)', + 'f0ebdd8d44ac1a80727041a087553847:11' => 'Apple QuickTime, Quality 687 (67%)', + 'c8f917220d6285cda6428a2cf6a9a1b3:11' => 'Apple QuickTime, Quality 688-689 (67%)', + '83ff61ebceff5f888b9615b250aa7b76:11' => 'Apple QuickTime, Quality 690 (67%)', + 'a2d1de53a0882047287a954f86bc783d:11' => 'Apple QuickTime, Quality 691 (67%)', + 'c78717ac2705274888912f349eeb2c8e:11' => 'Apple QuickTime, Quality 692 (68%)', + 'e032225ecdcf1d91d85626df59a2d0c6:11' => 'Apple QuickTime, Quality 693 (68%)', + 'ebf82c50697d66a6913727095299f192:11' => 'Apple QuickTime, Quality 694-695 (68%)', + 'bcc29022955cc7532b08640ab118259c:11' => 'Apple QuickTime, Quality 696 (68%)', + '6a87dd29703c2b3ef80f1b5d2cc8d26a:11' => 'Apple QuickTime, Quality 697 (68%)', + '91c9d96e11d96e10b328a5f18960247b:11' => 'Apple QuickTime, Quality 698 (68%)', + '6eeaaacec8edc933b68602b01d16204e:11' => 'Apple QuickTime, Quality 699 (68%)', + 'c638d9151dc650993b56f4effc0fe19c:11' => 'Apple QuickTime, Quality 700 (68%)', + 'c67d246229fcc0dd1b974f7df556d247:11' => 'Apple QuickTime, Quality 701 (68%)', + '7a52e3960831057d58e9b1ba03b87cf3:11' => 'Apple QuickTime, Quality 702 (69%)', + '907e599e3c462b498e936dfc35b20bb9:11' => 'Apple QuickTime, Quality 703-704 (69%)', + '65bf1ddc176fe4002a7a2ecaac60e58c:11' => 'Apple QuickTime, Quality 705 (69%)', + '40e59fdb430180502ceacf7b4034eff8:11' => 'Apple QuickTime, Quality 706 (69%)', + '4205aec34791d70be03b90ab1e54ef8c:11' => 'Apple QuickTime, Quality 707 (69%)', + '5c0a83e613d3bdd9ec7e86983f75b5be:11' => 'Apple QuickTime, Quality 708 (69%)', + 'b3ebdf0376c9c48cca51ea8b550f6c51:11' => 'Apple QuickTime, Quality 709 (69%)', + '72161116404ed3cb449674760d0e4776:11' => 'Apple QuickTime, Quality 710 (69%)', + '35b3697c265e35185e9463aac6ce9b2d:11' => 'Apple QuickTime, Quality 711-712 (69-70%)', + '85adcc8c52c25334a9e7ea9d79433f8d:11' => 'Apple QuickTime, Quality 713 (70%)', + '8f72f67948f264bdbd33107c33b1e0a0:11' => 'Apple QuickTime, Quality 714 (70%)', + 'c25ed5069735a3f9677ee494108a52bc:11' => 'Apple QuickTime, Quality 715 (70%)', + 'fd3167b1cdcfa1bdd37a4841d37b1624:11' => 'Apple QuickTime, Quality 716-717 (70%)', + 'a02b6b8286cf6d036961911e98bd8f89:11' => 'Apple QuickTime, Quality 718-719 (70%)', + 'd876e8934da14a985abda0ebe722bbee:11' => 'Apple QuickTime, Quality 720 (70%)', + '31852b7659883eade6e273ac61ef0262:11' => 'Apple QuickTime, Quality 721 (70%)', + 'de3aa6ed96eaf3ed3cd3ea70a2f75002:11' => 'Apple QuickTime, Quality 722 (71%)', + 'f178977e9e0133711f395943816d26aa:11' => 'Apple QuickTime, Quality 723 (71%)', + '18fce3103e312ce26252ec4af6cd1350:11' => 'Apple QuickTime, Quality 724 (71%)', + 'fdf6b04a2d8ac06d3fe64d1dceba4cd9:11' => 'Apple QuickTime, Quality 725 (71%)', + '6a37c2572bb47dff514aa4b343c104b5:11' => 'Apple QuickTime, Quality 726 (71%)', + 'fdbe851f6e559bc17ce3610b91e7fead:11' => 'Apple QuickTime, Quality 727 (71%)', + '9fee7fc42e670d6e30a5e9fcf696241d:11' => 'Apple QuickTime, Quality 728 (71%)', + '5aedf3816a813ed63b0521b0c384a677:11' => 'Apple QuickTime, Quality 729 (71%)', + 'c1278992838bdd62e71bf41c20126a5f:11' => 'Apple QuickTime, Quality 730 (71%)', + '791e3897f6ac92fb5e708b28dbd361b1:11' => 'Apple QuickTime, Quality 731 (71%)', + 'd5b2902ae3fcd87e1521da86585e7b3a:11' => 'Apple QuickTime, Quality 732-733 (71-72%)', + 'a99810db58e835fe4b213d707dc0b754:11' => 'Apple QuickTime, Quality 734 (72%)', + 'e8032085aa55f664f7f74201ac10bb99:11' => 'Apple QuickTime, Quality 735 (72%)', + '488e5d04f779b15c53f76e67cccdb2ed:11' => 'Apple QuickTime, Quality 736 (72%)', + '548a841c0a8c3b2beeb134c6c3b922fc:11' => 'Apple QuickTime, Quality 737-738 (72%)', + 'cfe4549eb2dd81684920aa32b598260c:11' => 'Apple QuickTime, Quality 739-740 (72%)', + 'b6ff9215f87e4b053aaee36381f59005:11' => 'Apple QuickTime, Quality 741 (72%)', + 'd1c8c1e1fc2bfb776d2ee1aace3fc6f9:11' => 'Apple QuickTime, Quality 742 (72%)', + '365693ebd558aebc31a79a1abff9709d:11' => 'Apple QuickTime, Quality 743-744 (73%)', + '0233ba670d2891e75da3ce5e7664cb67:11' => 'Apple QuickTime, Quality 745 (73%)', + 'a91f5f8e8d743e52169d965992c5021e:11' => 'Apple QuickTime, Quality 746 (73%)', + '1a0487e7e1a8f4ade97b2e8a4cab46ec:11' => 'Apple QuickTime, Quality 747 (73%)', + '5a2311c438c7183f6cd1f45c10e5783a:11' => 'Apple QuickTime, Quality 748 (73%)', + '2750f3df7a97d6007d6a17f5dd27790a:11' => 'Apple QuickTime, Quality 749 (73%)', + '74fddf6faaf251b28a00b4d0cd9e5621:11' => 'Apple QuickTime, Quality 750 (73%)', + 'ea65bdd87f78f7507fe6098473cbe0c9:11' => 'Apple QuickTime, Quality 751 (73%)', + '26d087368a13e3aca9ca13a54bcc648f:11' => 'Apple QuickTime, Quality 752-753 (73-74%)', + '5664c6ca557bc75526f59bea6aebde51:11' => 'Apple QuickTime, Quality 754 (74%)', + 'ff7a6007b6aab26f3c72c715ce487d72:11' => 'Apple QuickTime, Quality 755 (74%)', + '912804912a3914f0b470b29495810d8c:11' => 'Apple QuickTime, Quality 756-758 (74%)', + '6537be61d21f1b6ded3253fdd84f599b:11' => 'Apple QuickTime, Quality 759-760 (74%)', + '72d947637340246a35ff3ee969fd613f:11' => 'Apple QuickTime, Quality 761 (74%)', + '8c5c788bd53945222fc98f1a6155004c:11' => 'Apple QuickTime, Quality 762 (74%)', + '9fa9c3d1041911322544aef0298695ba:11' => 'Apple QuickTime, Quality 763 (75%)', + '33113dc71a90e8db06b43dadfe36b020:11' => 'Apple QuickTime, Quality 764 (75%)', + '55e0cf02a898abf8e224e2e9cf6e6ca5:11' => 'Apple QuickTime, Quality 765-766 (75%)', + '4f00127e7931d668a7b472c8a669925a:11' => 'Apple QuickTime, Quality 767-768 (75%)', + '32aa33dc6de46b7c5c5948b0ae06cb0e:11' => 'Apple QuickTime, Quality 769 (75%)', + 'a2b6067d9e5731be8029e17c00d7e043:11' => 'Apple QuickTime, Quality 770 (75%)', + 'cb6bc96131c4a5f762b5e5f79e7c4b66:11' => 'Apple QuickTime, Quality 771 (75%)', + 'e582a5f93f66cf34facfba5918a1d9e2:11' => 'Apple QuickTime, Quality 772 (75%)', + '54ab2e8fbd7c4ecac9eba5fb02a5ccd9:11' => 'Apple QuickTime, Quality 773 (75%)', + 'c71131cb485b59faf920d11982f7d454:11' => 'Apple QuickTime, Quality 774 (76%)', + 'c18239304e22bd19e3c8a21f9875ba39:11' => 'Apple QuickTime, Quality 775-776 (76%)', + '8278e4f14c7bf6efd2a847ef40f392e3:11' => 'Apple QuickTime, Quality 777 (76%)', + '6c0e396c705a59ec610a22f11466621b:11' => 'Apple QuickTime, Quality 778 (76%)', + 'a0c4d0114c04c89c879d9dc03463b347:11' => 'Apple QuickTime, Quality 779 (76%)', + 'c804929d3963c7427fa143e0d1e8c94e:11' => 'Apple QuickTime, Quality 780-781 (76%)', + 'e331a0dd2c53616c2881bb381fc4c1e2:11' => 'Apple QuickTime, Quality 782 (76%)', + '24ec8f0996e5e8d4dd7019d2b6063290:11' => 'Apple QuickTime, Quality 783 (76%)', + '36e9cb02d3ef245a3e15272c5071b0ee:11' => 'Apple QuickTime, Quality 784 (77%)', + 'b691578c1d6b16687fe2df12843d0642:11' => 'Apple QuickTime, Quality 785-786 (77%)', + 'ecbf939a145939d5aa48fc3c9e19cfe8:11' => 'Apple QuickTime, Quality 787 (77%)', + '9440b11ee5eb970a3ea6de9353099761:11' => 'Apple QuickTime, Quality 788 (77%)', + '282914c43bab6e5c62f3caaf549f1510:11' => 'Apple QuickTime, Quality 789-790 (77%)', + '040c8ed8b19485d8677b964b03bc9929:11' => 'Apple QuickTime, Quality 791-792 (77%)', + 'd9e503dc2dd4f6493be988ecb0f44f2c:11' => 'Apple QuickTime, Quality 793-795 (77-78%)', + '64d056c9e5e558d6c04d07d9d21aa7a3:11' => 'Apple QuickTime, Quality 796-798 (78%)', + '498f446de17202060a4752434df1ed7b:11' => 'Apple QuickTime, Quality 799 (78%)', + '5519e1c07692f51d0ee421ede78fb907:11' => 'Apple QuickTime, Quality 800 (78%)', + '511c5bddc18566a2544732291920caf3:11' => 'Apple QuickTime, Quality 801 (78%)', + '659f7466f80a8034f74a00ba07b8c3fb:11' => 'Apple QuickTime, Quality 802-804 (78-79%)', + 'fb64b35fe4021c34f16cf5bb1e59c0e8:11' => 'Apple QuickTime, Quality 805 (79%)', + '54fcb6649f5ba51c32c68970797e41ea:11' => 'Apple QuickTime, Quality 806-807 (79%)', + '80ef22ca4475af1bbb8963ac511144d7:11' => 'Apple QuickTime, Quality 808 (79%)', + 'ccdf1a403ec068ad21ee78686a86dd10:11' => 'Apple QuickTime, Quality 809 (79%)', + '1487f0cfc64949393aee2eab71b6b72c:11' => 'Apple QuickTime, Quality 810 (79%)', + 'a8be3b3791e958d092b3e37286802e0c:11' => 'Apple QuickTime, Quality 811-813 (79%)', + 'f9176b3ef0b4038c6c52b30ba033eb7f:11' => 'Apple QuickTime, Quality 814 (79%)', + '60264e35250325032bf7866ca8beaf58:11' => 'Apple QuickTime, Quality 815 (80%)', + '5efe038d405e029badcea4c8ee2bfc88:11' => 'Apple QuickTime, Quality 816 (80%)', + '717cbe19ae1dc9f72c86ef518aefea16:11' => 'Apple QuickTime, Quality 817 (80%)', + '9f490145dcc00db3e57014d41d2f99f2:11' => 'Apple QuickTime, Quality 818 (80%)', + '120b93a6ab4a1e8c78578e86e3ef837f:11' => 'Apple QuickTime, Quality 819 (80%)', + '9d765f3947408b2c6f26163d7b072895:11' => 'Apple QuickTime, Quality 820 (80%)', + 'a9c018e06868989776a81650300bcfce:11' => 'Apple QuickTime, Quality 821 (80%)', + '2c6581e20fa5393b3dd4d58f0df01957:11' => 'Apple QuickTime, Quality 822-824 (80%)', + '925b6581f0ae2f288530b00168152b80:11' => 'Apple QuickTime, Quality 825 (81%)', + 'c94e09eec2df4a41b2806c23d9939cb6:11' => 'Apple QuickTime, Quality 826 (81%)', + '68d5ce8ce1a9e337ee9630dadad0650e:11' => 'Apple QuickTime, Quality 827-829 (81%)', + 'f73704219e174961963f0fcd832b09a8:11' => 'Apple QuickTime, Quality 830-832 (81%)', + 'b783df92ec8a787b1eae4e05888b184b:11' => 'Apple QuickTime, Quality 833-834 (81%)', + '55cd2cad99821382b1bd78355980b1d1:11' => 'Apple QuickTime, Quality 835 (82%)', + '9ebd96ea70c2bcf4f377a175c71baf2c:11' => 'Apple QuickTime, Quality 836 (82%)', + '12d303b2e6a467b4f20a34e695f9da7e:11' => 'Apple QuickTime, Quality 837 (82%)', + '8711d6e1c56049c0e643bc6cf19a735c:11' => 'Apple QuickTime, Quality 838-839 (82%)', + '88558d6e9a513ff713945bd60ed19cc7:11' => 'Apple QuickTime, Quality 840 (82%)', + '25b45d6c1668613a61b81c6b60fa158a:11' => 'Apple QuickTime, Quality 841 (82%)', + 'b2f95d6a0eec4de39e0964a3b7303e9f:11' => 'Apple QuickTime, Quality 842 (82%)', + '631548841b70e871ee16009737dd4b9c:11' => 'Apple QuickTime, Quality 843-844 (82%)', + '7fac641c5b795e68ca8cfae4466a19c7:11' => 'Apple QuickTime, Quality 845 (83%)', + 'a15a74418a924874c5f3d2ca20e7af90:11' => 'Apple QuickTime, Quality 846-849 (83%)', + 'e4d76c3cd4d36b72537a2234a3597933:11' => 'Apple QuickTime, Quality 850 (83%)', + '36f1ec430bae8e5c72af6388e2a4d807:11' => 'Apple QuickTime, Quality 851-852 (83%)', + 'b558f097ed59f547d2b370a73145caf9:11' => 'Apple QuickTime, Quality 853 (83%)', + 'ceecacb651d0e01e9b1c78cde2d7835a:11' => 'Apple QuickTime, Quality 854 (83%)', + '82a9cce34fb9c7c3c0ab908533a9a9bf:11' => 'Apple QuickTime, Quality 855-856 (83-84%)', + 'e93244fdb14bb27a2c30ee133b3e9f5e:11' => 'Apple QuickTime, Quality 857 (84%)', + '7a12ccd01bfdd2cf3b8ee2df498b8ae0:11' => 'Apple QuickTime, Quality 858 (84%)', + 'd0d6f781130c0fecd985df78c15c5c16:11' => 'Apple QuickTime, Quality 859-860 (84%)', + '1c19e4fde384a33f208074c73775d990:11' => 'Apple QuickTime, Quality 861-863 (84%)', + '8fb281fcf4d481e59e1c15ed51ef8f19:11' => 'Apple QuickTime, Quality 864 (84%)', + 'c3f615274e58eb887a2aa75acad436ff:11' => 'Apple QuickTime, Quality 865 (84%)', + '9146c5df73615b0f2a470521bab7e4c4:11' => 'Apple QuickTime, Quality 866 (85%)', + 'ac2d99dd3ff609760c207419312e7b30:11' => 'Apple QuickTime, Quality 867 (85%)', + '7c7d225760bce3b4e479aca8bcd2b850:11' => 'Apple QuickTime, Quality 868 (85%)', + '9da4a7e310cb44578b009e78458d3b19:11' => 'Apple QuickTime, Quality 869 (85%)', + '1ae782c12797f5e5c9b083099148e43a:11' => 'Apple QuickTime, Quality 870 (85%)', + '193ace8d9e274bb9188b1a9a7bdee777:11' => 'Apple QuickTime, Quality 871-872 (85%)', + '9160a8eeb898a05dcb02206603a45a65:11' => 'Apple QuickTime, Quality 873-877 (85-86%)', + '0443da2c934e95fca0df8a0a1433eea4:11' => 'Apple QuickTime, Quality 878-880 (86%)', + 'fa99ff1ecc29c5caa95fa62189fca670:11' => 'Apple QuickTime, Quality 881-886 (86-87%)', + 'd9a914baea5468bb52c09d1d0b5bd131:11' => 'Apple QuickTime, Quality 887 (87%)', + '6c0ac535ec30285b609e0b8ca18e4dc0:11' => 'Apple QuickTime, Quality 888-890 (87%)', + 'dffb0a244fa54783569693edf84d1cda:11' => 'Apple QuickTime, Quality 891-893 (87%)', + '507b49a59dce17c02dc16fcb329352eb:11' => 'Apple QuickTime, Quality 894 (87%)', + 'dd757185a44c3d6222e9d16a0c2ee890:11' => 'Apple QuickTime, Quality 895 (87%)', + 'f3526abe33de71ad0eb728c9d446b545:11' => 'Apple QuickTime, Quality 896 (88%)', + '34466385e7bf9b2708adf19be1eb3c2d:11' => 'Apple QuickTime, Quality 897-898 (88%)', + 'e43438348a912a2210261472d1a747ab:11' => 'Apple QuickTime, Quality 899 (88%)', + '184d01e77f6239f63fd6ab6d36761e64:11' => 'Apple QuickTime, Quality 900-901 (88%)', + '26005cdf9397dcce883660aeecb0426b:11' => 'Apple QuickTime, Quality 902 (88%)', + '09321d810a54503da7ad7b8e883227ea:11' => 'Apple QuickTime, Quality 903 (88%)', + 'd6438ea5a93b6d4d0ba26de7c56f2634:11' => 'Apple QuickTime, Quality 904-905 (88%)', + 'ddc90333cb2279aa533a339710bd81ef:11' => 'Apple QuickTime, Quality 906 (88%)', + '14a352b80a350e2df6b2bc444ccc74f6:11' => 'Apple QuickTime, Quality 907-908 (89%)', + '91a7f0747ed633f481918a83b1a7c77c:11' => 'Apple QuickTime, Quality 909-914 (89%)', + 'a3bb9728b3dfa7002364659db0c420fc:11' => 'Apple QuickTime, Quality 915-917 (89-90%)', + '9df94f927ffc1f3345923232691fab3b:11' => 'Apple QuickTime, Quality 918-920 (90%)', + '259764d950c1f1e399cdb27e159c8985:11' => 'Apple QuickTime, Quality 921-922 (90%)', + '73313d816524749545292ed2284c804c:11' => 'Apple QuickTime, Quality 923-924 (90%)', + '449ed4370a849e0f736b57ee7ccab942:11' => 'Apple QuickTime, Quality 925-926 (90%)', + 'bd1f81bd50cf9859eb0ae6d2dbf75d09:11' => 'Apple QuickTime, Quality 927 (91%)', + '820db98d1ee91bb648e7a05498a340b0:11' => 'Apple QuickTime, Quality 928 (91%)', + '93c1ba0af1f50d889cb5e2364be3a056:11' => 'Apple QuickTime, Quality 929 (91%)', + 'cc96e1c8906353c4023bc7e6b72bb684:11' => 'Apple QuickTime, Quality 930 (91%)', + 'eb728dc3105ddb5a0597384b54ed948c:11' => 'Apple QuickTime, Quality 931 (91%)', + 'dc0278d78fa5c8daf84f8c2672f582c6:11' => 'Apple QuickTime, Quality 932-933 (91%)', + '1a603cba63dbba0d0815fc7319271b93:11' => 'Apple QuickTime, Quality 934-936 (91%)', + '3d8f4957eab9756993a78efe08ba3798:11' => 'Apple QuickTime, Quality 937-938 (92%)', + 'cef5a49e1834c316a4a9e7dca8d69157:11' => 'Apple QuickTime, Quality 939 (92%)', + 'ca21386b17f3866a235fca4b6e72b124:11' => 'Apple QuickTime, Quality 940 (92%)', + 'ec662935c494c5abd6f6c907f77be65c:11' => 'Apple QuickTime, Quality 941-943 (92%)', + '190a54eb1127ee87231795bc3d661b5a:11' => 'Apple QuickTime, Quality 944-946 (92%)', + 'e78229129afca214a07ad978262c545e:11' => 'Apple QuickTime, Quality 947-951 (92-93%)', + 'c31cb63954b137b62c5fe35379235e2e:11' => 'Apple QuickTime, Quality 952-954 (93%)', + '25ca43baa972ad9c82128606cd383805:11' => 'Apple QuickTime, Quality 955 (93%)', + '334c67d739adf957d1620201cb7a521c:11' => 'Apple QuickTime, Quality 956-957 (93-93%)', + '29c42d951dc84d62bd134bec71bf731b:11' => 'Apple QuickTime, Quality 958 (94%)', + 'fa6f80883480ab3ddea8ee2f6796a14b:11' => 'Apple QuickTime, Quality 959-961 (94%)', + 'e40f6a9a3daf4bfc42aedcb9107076ea:11' => 'Apple QuickTime, Quality 962 (94%)', + 'd26a06f6114d83714e3b64b6dbe97e6f:11' => 'Apple QuickTime, Quality 963-967 (94%)', + 'c40848be9d1d1018747630cdac2d7294:11' => 'Apple QuickTime, Quality 968-970 (95%)', + 'ab2b6d0624f294bf4e53e34208caeaa6:11' => 'Apple QuickTime, Quality 971 (95%)', + 'b6ea2f838fa1942a21e41f6bba417782:11' => 'Apple QuickTime, Quality 972-973 (95%)', + 'ff765e75c06c9db34f66ae7ee0202d05:11' => 'Apple QuickTime, Quality 974 (95%)', + 'c33573208ef877f1bc9a64f595e00c4d:11' => 'Apple QuickTime, Quality 975-977 (95%)', + '6528da6df208ce35fd84dccabc81d4da:11' => 'Apple QuickTime, Quality 978-979 (96%)', + '420d094d00a4a8aec94c5667254d2053:11' => 'Apple QuickTime, Quality 980-984 (96%)', + '427271dd1e2a3d7a7ce54af73d9e6c77:11' => 'Apple QuickTime, Quality 985-987 (96%)', + '99589fb7d66a29f15d9ff0f37235e7a2:11' => 'Apple QuickTime, Quality 988-991 (96-97%)', + '98fddd9e5862e06385b46a016597c02f:11' => 'Apple QuickTime, Quality 992-993 (97%)', + '381d1ca1d61986f28cfd6da0fca348da:11' => 'Apple QuickTime, Quality 994-996 (97%)', + '11a232fa9de634fadde1869007baab9c:11' => 'Apple QuickTime, Quality 997-998 (97%)', + '02374d6405239e8fe5ab939b92f4fd03:11' => 'Apple QuickTime, Quality 999-1000 (98%)', + 'f91cfb708c99c2fef0f7148976514f44:11' => 'Apple QuickTime, Quality 1001-1002 (98%)', + '83f3452abc7906930b228c29a4320089:11' => 'Apple QuickTime, Quality 1003 (98%)', + '4379016ba81dc331ffd5f9a8ab5b6399:11' => 'Apple QuickTime, Quality 1004 (98%)', + 'e2cccecebc01c7d8a4fca2dab682ba8f:11' => 'Apple QuickTime, Quality 1005-1009 (98-99%)', + '8d4b2a14a176d63e509684aa4246dabb:11' => 'Apple QuickTime, Quality 1010-1013 (99%)', + '40a7c1d8f58612f4470c2531768d93b5:11' => 'Apple QuickTime, Quality 1014-1016 (99%)', + '8392742f8f5971ed08c7520d0e9c81f3:11' => 'Apple QuickTime, Quality 1017 (99%)', + '14040c7711b6fa62383da3edc9ade1b7:11' => 'Apple QuickTime, Quality 1018-1020 (99-100%)', + '22ccf9c976b36da34f48385a09b1951b:11' => 'Apple QuickTime, Quality 1021-1023 (100%)', + '4aa632db3be6b6e85565c1fe66cb22d1:11' => 'Apple QuickTime, Quality 1024 (lossless)', + + # Apple Aperture 2.1.3 (ref 2) + '60cb2afa0cfa7395635a9360fc690b46:221111' => 'Apple Aperture Quality 0', + '6b9be09d6ec6491a20c2827dbeb678c0:221111' => 'Apple Aperture Quality 1', + 'dbb17a02e661f2475411fc1dc37902ef:221111' => 'Apple Aperture Quality 2', + '8a5df2b5337bf8251c3f66f6adbb5262:221111' => 'Apple Aperture Quality 3', + '3841f0f3be30520a1a57f41c449588ee:221111' => 'Apple Aperture Quality 4', + '2b1dba266c728a9f46d06e6e5c247953:221111' => 'Apple Aperture Quality 5', + # 'Independent JPEG Group library (used by many applications), Quality 91' => 'Apple Aperture Quality 6', + '93818f3a0e6d491500cb62e1f683da22:221111' => 'Apple Aperture Quality 7', + '8c0c36696a99fd889e0f0c7d64824f3c:221111' => 'Apple Aperture Quality 8', + '043645382c79035b6f2afc62d373a37f:221111' => 'Apple Aperture Quality 9', + '558d017ce6d5b5282ce76727fe99b91e:221111' => 'Apple Aperture Quality 10', + '0b52b82694040193aee10e8074cd7ad5:221111' => 'Apple Aperture Quality 11', + # 'Independent JPEG Group library (used by many applications), Quality 100' => 'Apple Aperture Quality 12', + + # Tested with Corel Paint Shop Pro PHOTO X2 (Win) - Different subsamplings possible + '1c78c0daaa0bbfd4a1678b5569b0fa13' => 'Corel Paint Shop Pro PHOTO, Quality 1', + '5ffdd2e918ec293efc79083703737290' => 'Corel Paint Shop Pro PHOTO, Quality 2', + '4ed4751d772933938600c4e7560bf19c' => 'Corel Paint Shop Pro PHOTO, Quality 3', + 'f647f0fb4320c61f52e2a79d12bbc8cc' => 'Corel Paint Shop Pro PHOTO, Quality 4', + '6194167174dfcb4a769cf26f5c7a018d' => 'Corel Paint Shop Pro PHOTO, Quality 5', + '6120ded86d4cc42cd7ca2131b1f51fad' => 'Corel Paint Shop Pro PHOTO, Quality 6', + 'c07a6430e56ef16a0526673398e87ac6' => 'Corel Paint Shop Pro PHOTO, Quality 7', + '507cc511e561916efa3b49228ffc8c9a' => 'Corel Paint Shop Pro PHOTO, Quality 8', + '612941a50f2c0992938bc13106caf228' => 'Corel Paint Shop Pro PHOTO, Quality 9', + '7624f08396d811fdb6f1ead575e67e58' => 'Corel Paint Shop Pro PHOTO, Quality 10', + 'e215df38e258b3d8bceb57aa64388d26' => 'Corel Paint Shop Pro PHOTO, Quality 11', + '78f66ee0bc442950808e25daa02a2b02' => 'Corel Paint Shop Pro PHOTO, Quality 12', + '14efb0bb5124910a37bcbd5f06de9aa9' => 'Corel Paint Shop Pro PHOTO, Quality 13', + 'd61168238621bd221ef1eb3dcbe270a3' => 'Corel Paint Shop Pro PHOTO, Quality 14', + 'e2d2755891b4e4bc5f7c8d76dcbb0d53' => 'Corel Paint Shop Pro PHOTO, Quality 15', + 'f6c4502144a2e5c82c07994d3cd01665' => 'Corel Paint Shop Pro PHOTO, Quality 16', + '78801638505e95827c2f7cc0c7ef78f4' => 'Corel Paint Shop Pro PHOTO, Quality 17', + 'e8ff3d165b4c028c18ec8a8f940a12a1' => 'Corel Paint Shop Pro PHOTO, Quality 18', + '984c359b9fbcc4d6f805946aa23ae708' => 'Corel Paint Shop Pro PHOTO, Quality 19', + 'd1dc48d911055bc533779d6e086f7242' => 'Corel Paint Shop Pro PHOTO, Quality 20', + 'd7437a18e86ac2832d73204acd82aa89' => 'Corel Paint Shop Pro PHOTO, Quality 21', + 'bceaee6c1a150006b3643de6942ccfa3' => 'Corel Paint Shop Pro PHOTO, Quality 22', + 'c448e6817efa9acdad225e60ed0013f9' => 'Corel Paint Shop Pro PHOTO, Quality 23', + '904f231c98f390400ba7ae17c252813f' => 'Corel Paint Shop Pro PHOTO, Quality 24', + 'ccd6708ca1dbd66a23d40cee635a0f76' => 'Corel Paint Shop Pro PHOTO, Quality 25', + '10d87624d888b75b29e156be8dad35f4' => 'Corel Paint Shop Pro PHOTO, Quality 26', + '8558c6d41f03db192198dceefbd1e89b' => 'Corel Paint Shop Pro PHOTO, Quality 27', + '058fc759cff9d615f91d9ffb4b46436a' => 'Corel Paint Shop Pro PHOTO, Quality 28', + '5c606e0f7168a78fd8d0c91646c801a3' => 'Corel Paint Shop Pro PHOTO, Quality 29', + 'e9555e593a6fd9aeee399de16080cd61' => 'Corel Paint Shop Pro PHOTO, Quality 30', + '2c2726484978a15d3d756d43b0baa290' => 'Corel Paint Shop Pro PHOTO, Quality 31', + '8b1d11d31bc9445278cf9af55b0c156b' => 'Corel Paint Shop Pro PHOTO, Quality 32', + 'aa4a5528ae18ecd36ec052014b91f651' => 'Corel Paint Shop Pro PHOTO, Quality 33', + '9a26194b114b7db253601ff80b03da9a' => 'Corel Paint Shop Pro PHOTO, Quality 34', + '3fa780a3dff1d787f7d883585a46dcfb' => 'Corel Paint Shop Pro PHOTO, Quality 35', + '0a899361ed0d51e224dc535ceb02f9a1' => 'Corel Paint Shop Pro PHOTO, Quality 36', + '3a2ab96a6ad9612e1377ddc822f02ddd' => 'Corel Paint Shop Pro PHOTO, Quality 37', + '315f4faadd967e72d730155091c4912f' => 'Corel Paint Shop Pro PHOTO, Quality 38', + '5f6e3a66672d6e4c41b1689996ca57d3' => 'Corel Paint Shop Pro PHOTO, Quality 39', + '9503a86793e86d1fca3d8797548fa243' => 'Corel Paint Shop Pro PHOTO, Quality 40', + '3b95f11bd77cb8af977c09d5851131f8' => 'Corel Paint Shop Pro PHOTO, Quality 41', + 'ececf8dfa473110534b506db58d98f15' => 'Corel Paint Shop Pro PHOTO, Quality 42', + 'cfe3144d4f8048a0507269a9d8a85993' => 'Corel Paint Shop Pro PHOTO, Quality 43', + 'eb9d48d135b2c61c51fc3f23b0001b4d' => 'Corel Paint Shop Pro PHOTO, Quality 44', + 'b08313a6919d308e50b806f138a8a2a1' => 'Corel Paint Shop Pro PHOTO, Quality 45', + '7c34e6e7fe2cc760fa5c3ed812a8b74c' => 'Corel Paint Shop Pro PHOTO, Quality 46', + '90ece7123e8d614d9aab55eaba6dd7da' => 'Corel Paint Shop Pro PHOTO, Quality 47', + '6d79fe623c4c5320bdbe4d3026f4e71a' => 'Corel Paint Shop Pro PHOTO, Quality 48', + 'a7e85552c3e5e40288891d225f308590' => 'Corel Paint Shop Pro PHOTO, Quality 49', + '67b9a678d9f669167c5b4bf12422ad50' => 'Corel Paint Shop Pro PHOTO, Quality 50', + '1fab112b17e94f53e94a9208e9091b7b' => 'Corel Paint Shop Pro PHOTO, Quality 51', + '4971237e046795a030a99a0e8d2c5acb' => 'Corel Paint Shop Pro PHOTO, Quality 52', + 'f3e1672b93ff159231c51b1b157e45fd' => 'Corel Paint Shop Pro PHOTO, Quality 53', + '6e9cfb8131373c3d1873e3f497e46b64' => 'Corel Paint Shop Pro PHOTO, Quality 54', + '9155c8acf8322e8af898272c694fa1d6' => 'Corel Paint Shop Pro PHOTO, Quality 55', + '52b20edc779f206f2aed50610971f181' => 'Corel Paint Shop Pro PHOTO, Quality 56', + 'ad801813f822ef9774801ab4d9145a61' => 'Corel Paint Shop Pro PHOTO, Quality 57', + '07259679e2a842478df97c7f0ddd4df3' => 'Corel Paint Shop Pro PHOTO, Quality 58', + '67db25c57803c34b065736f46f6afadb' => 'Corel Paint Shop Pro PHOTO, Quality 59', + 'c7498fc4b3802b290a452631dd1e1b63' => 'Corel Paint Shop Pro PHOTO, Quality 60', + '3f7b04c7952f96d2624813ed9896f128' => 'Corel Paint Shop Pro PHOTO, Quality 61', + 'd5ec901d20f3887007d0f4cfb7d1460d' => 'Corel Paint Shop Pro PHOTO, Quality 62', + '61bb38e23040b6a8b0e8721e6d6eff66' => 'Corel Paint Shop Pro PHOTO, Quality 63', + '48fac53d9d168eab3ce9b6edc4b9fcb1' => 'Corel Paint Shop Pro PHOTO, Quality 64', + '8cb101a5ae986e45cc31a9e19a35535d' => 'Corel Paint Shop Pro PHOTO, Quality 65', + '0e08dc629e883530cb2ae78c90f125b3' => 'Corel Paint Shop Pro PHOTO, Quality 66', + '5134762d2d4baac8711a52e76730591c' => 'Corel Paint Shop Pro PHOTO, Quality 67', + '14b57dc6d5381fd0a743c7bd8b28bed1' => 'Corel Paint Shop Pro PHOTO, Quality 68', + '9d398f1b1f40b7aaec1bd9cdb6922530' => 'Corel Paint Shop Pro PHOTO, Quality 69', + 'c7e68d88bee5c2ee4b61a11bc2e68c80' => 'Corel Paint Shop Pro PHOTO, Quality 70', + '917fe67f6ded5decac1820642239622c' => 'Corel Paint Shop Pro PHOTO, Quality 71', + '362c3e0c08f6951018cde7b412cd513f' => 'Corel Paint Shop Pro PHOTO, Quality 72', + 'd91cd4a2dcd1a29e6ef652ebcfdd58d7' => 'Corel Paint Shop Pro PHOTO, Quality 73', + '11f5fbd5e74e5c5e305b95dbbc4356a8' => 'Corel Paint Shop Pro PHOTO, Quality 74', + 'bf010771f909049fc5fceedcaa0f917c' => 'Corel Paint Shop Pro PHOTO, Quality 75', + 'a455a3149812ba6951a016ee6114f9da' => 'Corel Paint Shop Pro PHOTO, Quality 76', + '42e0c4082ec4d026c77d19a053a983f4' => 'Corel Paint Shop Pro PHOTO, Quality 77', + '326bd5938e2db7de9250a9fb0efc6692' => 'Corel Paint Shop Pro PHOTO, Quality 78', + 'a3e2cc4ea95cda49501bc73c494e9420' => 'Corel Paint Shop Pro PHOTO, Quality 79', + '8c89043f00678bb5c68ee90390c1b43b' => 'Corel Paint Shop Pro PHOTO, Quality 80', + 'fc5812ad9a4cd0122eb1c63f0ac3b5a3' => 'Corel Paint Shop Pro PHOTO, Quality 81', + '84dbe33962674aab86e03681ac3bd35f' => 'Corel Paint Shop Pro PHOTO, Quality 82', + 'b6b80a78472dca05c9135702e96fdad9' => 'Corel Paint Shop Pro PHOTO, Quality 83', + '01f997907a4c1dfd1e6b00aca9ff5d80' => 'Corel Paint Shop Pro PHOTO, Quality 84', + '8431e86434062b325c519fd836353cd0' => 'Corel Paint Shop Pro PHOTO, Quality 85', + '15f375a620952738ff21ff4aa496b8f7' => 'Corel Paint Shop Pro PHOTO, Quality 86', + '7b0f02aa96271376d3f81658d98fb1df' => 'Corel Paint Shop Pro PHOTO, Quality 87', + '86e7666b05bd1fc130fbf4b48f854288' => 'Corel Paint Shop Pro PHOTO, Quality 88', + '6af05d547e8911fe2d1f2b4d968a477e' => 'Corel Paint Shop Pro PHOTO, Quality 89', + '8baa876790518bf509dd09093759331d' => 'Corel Paint Shop Pro PHOTO, Quality 90', + 'eb7d90d291044d1bd8f40ca1b3ce0ddf' => 'Corel Paint Shop Pro PHOTO, Quality 91', + '6f338385a8f2cd2dd3420a4f6138a206' => 'Corel Paint Shop Pro PHOTO, Quality 92', + 'b0a0fd1ec2dd366ad00d3e83d6dedec2' => 'Corel Paint Shop Pro PHOTO, Quality 93', + 'e09026128c9880b44ac71224f477cd3b' => 'Corel Paint Shop Pro PHOTO, Quality 94', + 'd0a8f50ff547da69a57eeb892e194cff' => 'Corel Paint Shop Pro PHOTO, Quality 95', + '7849ba902d96273b5ac7b6eb98f4d009' => 'Corel Paint Shop Pro PHOTO, Quality 96', + '379f9f196d4190298a732ab9a7031001' => 'Corel Paint Shop Pro PHOTO, Quality 97', + 'c3d1601f84ec3adfbc8ca17883ef6378' => 'Corel Paint Shop Pro PHOTO, Quality 98', + '1f5e87bec674bdd7dff166c2ea9ca004' => 'Corel Paint Shop Pro PHOTO, Quality 99', + + # Tested with FixFoto Version 2.90 Build 136 (Win) - different subsamplings possible + '866dd04cb0fe2e00cda7395162480117' => 'FixFoto, Quality 0 or 1', + '1e400ba25fa835e2771772bbfb15b94b' => 'FixFoto, Quality 2', + '302ff1ad1a50d0f01a82cc88f286c649' => 'FixFoto, Quality 3', + '1343a117f5fab26d556a3e7558366591' => 'FixFoto, Quality 4', + '8fbb8cc5368224625689df80bf4d2a04' => 'FixFoto, Quality 5', + 'a371d1ffc8d85d502854a356f3b0ea74' => 'FixFoto, Quality 6', + 'a9a0a5000cd6fb322960a4c45cf1d032' => 'FixFoto, Quality 7', + 'aaac84043224d33e1d3a1723b653b0cd' => 'FixFoto, Quality 8', + '701e4820f6d0b68e67b6a2b90a7baa0c' => 'FixFoto, Quality 9', + '877d03a5abf5b6c4ad03c39afd97f4a2' => 'FixFoto, Quality 10', + 'b3d9bdc2090200537fb42f4d69631150' => 'FixFoto, Quality 11', + '3cf156d54120b53057f56e9f38ee2896' => 'FixFoto, Quality 12', + '69fe5c29b9d5e4c823f8a082ab7b3285' => 'FixFoto, Quality 13', + 'cf8573af40ced1793dcbc2346f969240' => 'FixFoto, Quality 14', + '22944c3bc03d6adea8d6819f914452c3' => 'FixFoto, Quality 15', + 'd768df38fb51c4b9977e5d7185f97a6c' => 'FixFoto, Quality 16', + '7ef2cd2b66d51fe80d94d5db427ee9ef' => 'FixFoto, Quality 17', + 'ed3d3b9ff9faf0009e44b9803f6295d7' => 'FixFoto, Quality 18', + '70a0b15e2e5f97e0a9333a2011afe5cd' => 'FixFoto, Quality 19', + 'd798b707a6b83eb54664abe0833b46aa' => 'FixFoto, Quality 20', + 'bf68d1866b75cea8f99cf2fc46f9d686' => 'FixFoto, Quality 21', + 'b98b8adb8f1f78b65800efe6c329ceab' => 'FixFoto, Quality 22', + 'c063344185079018af9fcf161a3fdf98' => 'FixFoto, Quality 23', + + # Tested with Nikon Capture NX Version 2.0.0 (Win) + '0ef9d9f62ab68807eedf6cb8c2ec120b:221111' => 'Nikon Capture NX, Quality 0', + 'efbc50df45bc1d1fbbbd29c3e5de04b2:221111' => 'Nikon Capture NX, Quality 1', + 'cbde745c78fd546d6e83dd7512ebe863:221111' => 'Nikon Capture NX, Quality 2', + '33731f743fc28e9d81e542f0ed7cdfba:221111' => 'Nikon Capture NX, Quality 3', + '866fcb1296d7da02b4ad31afb242f25f:221111' => 'Nikon Capture NX, Quality 4', + 'cfbe44397240092d3a67241a23342528:221111' => 'Nikon Capture NX, Quality 5', + 'a4b8b3408ae302ae81f125e972901131:221111' => 'Nikon Capture NX, Quality 6', + '3a6cefd4f43c513fdf0858f26afeab5a:221111' => 'Nikon Capture NX, Quality 7', + '1e861ce223babf95bc795e18cbdb49d1:221111' => 'Nikon Capture NX, Quality 8', + '4d5b512d8bc173f14e6a3cf8574f670a:221111' => 'Nikon Capture NX, Quality 9', + '9b1e6d379d3030dfa313bcaedc1ef3c7:221111' => 'Nikon Capture NX, Quality 10', + 'e39b60fcecf3221d14c62dc13ddf4726:221111' => 'Nikon Capture NX, Quality 11', + '3654bbf4a45e0c0758a82a075b3f77cc:221111' => 'Nikon Capture NX, Quality 12', + '4f5889173779409ec604622a1894ab4a:221111' => 'Nikon Capture NX, Quality 13', + '738685b86b80ff0e8b562102d1b58f71:221111' => 'Nikon Capture NX, Quality 14', + '48a53035374c08e6490893d8113ed6b3:221111' => 'Nikon Capture NX, Quality 15', + '03651ac1d15043f77949a63ac3762584:221111' => 'Nikon Capture NX, Quality 16', + '27811b28d02bd417857904f0a9e1ed58:221111' => 'Nikon Capture NX, Quality 17', + '03201bd5642a451d99b99bfd10fc42df:221111' => 'Nikon Capture NX, Quality 18', + '67d5eb5f55c9a5baa0a67d42a841d77b:221111' => 'Nikon Capture NX, Quality 19', + '18392b08bf8cf788a579f376297c3334:221111' => 'Nikon Capture NX, Quality 20', + 'de0c784b75953851dc370f4daecfa1a9:221111' => 'Nikon Capture NX, Quality 21', + '75f260644b87a9779188126da8709e7f:221111' => 'Nikon Capture NX, Quality 22', + 'c44701e8185306f5e6d09be16a2b0fbd:221111' => 'Nikon Capture NX, Quality 23', + '086e5ce1149e14efd9e424956734fe05:221111' => 'Nikon Capture NX, Quality 24', + 'aad1109d9c49b8170feac125148b2a50:221111' => 'Nikon Capture NX, Quality 25', + 'c97965ce5392623f668a386b30e41cee:221111' => 'Nikon Capture NX, Quality 26', + 'd9dadfb6f0a25765abe00e69857c5520:221111' => 'Nikon Capture NX, Quality 27', + '0ee9ca02a1fe8a17b6e50a2e86d19a7c:221111' => 'Nikon Capture NX, Quality 28', + '88b1726a20759f29eecfa2b129773127:221111' => 'Nikon Capture NX, Quality 29', + '70a311935ed066da954897fad5079377:221111' => 'Nikon Capture NX, Quality 30', + 'aa2d374bbab2a30e00c1863264588a42:221111' => 'Nikon Capture NX, Quality 31', + '097b684846696b3a8bbdf2bd2f9ded9c:221111' => 'Nikon Capture NX, Quality 32', + 'bb313d5398065376c7765092fc8ea0f0:221111' => 'Nikon Capture NX, Quality 33', + 'aa049fdc1387851a664143df0408f55c:221111' => 'Nikon Capture NX, Quality 34', + '087c1c1a368adc82900d83235f432d3f:221111' => 'Nikon Capture NX, Quality 35', + '7dec6568dbad7a70622c994a326957e2:221111' => 'Nikon Capture NX, Quality 36', + 'd2e14d8ba7d38f7544b569eea7221255:221111' => 'Nikon Capture NX, Quality 37', + 'ce6bcb98c5f9358594f5934e64b4ecc3:221111' => 'Nikon Capture NX, Quality 38', + '4785aafc8471873402819e423b8969a9:221111' => 'Nikon Capture NX, Quality 39', + '66ae78a749b520b35d4daf4531df8ae5:221111' => 'Nikon Capture NX, Quality 40', + '946d9f9346a0c65eec478945ad3d6143:221111' => 'Nikon Capture NX, Quality 41', + 'f46e96afa026233c1662c9114feb61e9:221111' => 'Nikon Capture NX, Quality 42', + '96a267e050b6d8a13439f8a9bb89722c:221111' => 'Nikon Capture NX, Quality 43', + '27c301566e155f700b01906a43473ffe:221111' => 'Nikon Capture NX, Quality 44', + 'ceff136f6dd88242500bfd639cb0c003:221111' => 'Nikon Capture NX, Quality 45', + '939b804eefc95158a934bb48e3f3b545:221111' => 'Nikon Capture NX, Quality 46', + '06186292fe0ccaaeb5999319a366c4b4:221111' => 'Nikon Capture NX, Quality 47', + 'e456c998dc126c1efad013eb7b0186c1:221111' => 'Nikon Capture NX, Quality 48', + 'ef0cd1902fb1afe284468a67eaffd078:221111' => 'Nikon Capture NX, Quality 49', + 'f4693035f8db19e0788f41255c3c052e:221111' => 'Nikon Capture NX, Quality 50', + '40c6f2886cdca8f19a654ce321ea993e:221111' => 'Nikon Capture NX, Quality 51', + 'e9387b4065bba8570375d6535ab2124b:221111' => 'Nikon Capture NX, Quality 52', + 'f3a55e422a4ab829b2c1f5a1784ce9f6:221111' => 'Nikon Capture NX, Quality 53', + '2fff3c6e48247992d1543d9e5c679759:221111' => 'Nikon Capture NX, Quality 54', + '5a1849b49122ff09949f1d355b4f9eaa:221111' => 'Nikon Capture NX, Quality 55', + 'a582968bb1890620ffbae916ebafcb64:221111' => 'Nikon Capture NX, Quality 56', + '81597eb992e32e186d2b5565bbe4ae3a:221111' => 'Nikon Capture NX, Quality 57', + '7364416ce4f2a9282efdbe052574527b:221111' => 'Nikon Capture NX, Quality 58', + '5301c2bcae09fd4305e47ffc56b2c8a7:221111' => 'Nikon Capture NX, Quality 59', + '5a1849b49122ff09949f1d355b4f9eaa:211111' => 'Nikon Capture NX, Quality 60', + '9be2446f168941ff42d9fc7441f2429b:211111' => 'Nikon Capture NX, Quality 61', + 'bbba80e58afae43278e287021d4f1499:211111' => 'Nikon Capture NX, Quality 62', + '2a9ae394dc32a418960522cbe9c6df24:211111' => 'Nikon Capture NX, Quality 63', + '67fbe0dce139b6db1813e30bbbceccf3:211111' => 'Nikon Capture NX, Quality 64', + '17bce376f588ebf2b3e9002a337c239d:211111' => 'Nikon Capture NX, Quality 65', + 'cd2c6c01d8eb8d985086b54e2269278a:211111' => 'Nikon Capture NX, Quality 66', + '34b25782fc089616807bbbe7f7cd8413:211111' => 'Nikon Capture NX, Quality 67', + '37b8bbab382a228eabb0dc64c0edcb0f:211111' => 'Nikon Capture NX, Quality 68', + 'b163f35baed567d70aa2536695558724:211111' => 'Nikon Capture NX, Quality 69', + '251eb2d7903f63b168348ec483ba499a:211111' => 'Nikon Capture NX, Quality 70', + '42e7cdf33b9067a7124dd27020704f9a:211111' => 'Nikon Capture NX, Quality 71', + '032678d9de74e5530896c28079f666af:211111' => 'Nikon Capture NX, Quality 72', + '30d7b6db02954dfc4ce47a089d0f40d9:211111' => 'Nikon Capture NX, Quality 73', + '5c1a40094128ac76eab0405dcb4ae3c7:211111' => 'Nikon Capture NX, Quality 74', + '2706b8b0cf6686148e285b6d3e44dd72:211111' => 'Nikon Capture NX, Quality 75', + '6ca4a27cb36f35ab84b0e2df06bb32f4:211111' => 'Nikon Capture NX, Quality 76', + '6f9cae52d3f47f514f7c927314455a5a:211111' => 'Nikon Capture NX, Quality 77', + 'c0204862b8aafa2c286c7b58d755c31f:211111' => 'Nikon Capture NX, Quality 78', + 'd8ef40736b072f09bead5f73f5ec1372:211111' => 'Nikon Capture NX, Quality 79', + '8c389c29eca238b3b331f65f7e124a27:111111' => 'Nikon Capture NX, Quality 80', + '6f9cae52d3f47f514f7c927314455a5a:111111' => 'Nikon Capture NX, Quality 81', + '8e1ceace8fafe31282393d8677e76994:111111' => 'Nikon Capture NX, Quality 82', + '60f75a915647ed50d1724179d50a35d2:111111' => 'Nikon Capture NX, Quality 83', + 'df54eb20ec90f41f1e6c37e241ee381c:111111' => 'Nikon Capture NX, Quality 84', + '5522213c915e2af3ad01ee2ec27ee3ed:111111' => 'Nikon Capture NX, Quality 85', + '08c063f0997262d9977df4b44e682d82:111111' => 'Nikon Capture NX, Quality 86', + 'd2e34c70872ac119dda6bdeeb36bf229:111111' => 'Nikon Capture NX, Quality 87', + 'e5abf48ce0cc2b4a3db7eca3a1112b7a:111111' => 'Nikon Capture NX, Quality 88', + 'b69dcb672088f296323d891219464ad8:111111' => 'Nikon Capture NX, Quality 89', + 'b6d1c6efb27ea721577888b5f981ad7b:111111' => 'Nikon Capture NX, Quality 90', + 'b023f424f81c8cbbab20119c06163dce:111111' => 'Nikon Capture NX, Quality 91', + '77f680490d08697cb0f11ff3fe76b7e8:111111' => 'Nikon Capture NX, Quality 92', + '1860106097672532e7ebc2026d7f9681:111111' => 'Nikon Capture NX, Quality 93', + '0c7d4861b3bee5d766a93f2d34027bfa:111111' => 'Nikon Capture NX, Quality 94', + '3adf9a0b85a4000243bbf833cd8e6966:111111' => 'Nikon Capture NX, Quality 95', + '9530dfffc5574606841a597212ec25b4:111111' => 'Nikon Capture NX, Quality 96', + 'c7294290fe26155147072f9041705cfb:111111' => 'Nikon Capture NX, Quality 97', + 'c24c44a4dadd77c15e0b4c741a2d4bd5:111111' => 'Nikon Capture NX, Quality 98', + '36016cd5527c505ef3bbba8b3e22f9db:111111' => 'Nikon Capture NX, Quality 99', + 'c9309ab058680151be5f97e6c54dc687:111111' => 'Nikon Capture NX, Quality 100', + + # Tested with ACDsee PhotoEditor 4.0.208c-de (Win) + '2ab2f6a116ca6fc0bbf188b19b9de967' => 'ACD Systems Digital Imaging, Quality 0 or 1', + 'f4f9d5c07c78e8700a6f3def0782a18e' => 'ACD Systems Digital Imaging, Quality 2', + '66fc410ab8f71a7fdef86fd70b742dc1' => 'ACD Systems Digital Imaging, Quality 3', + '8e763b5b9255df1f4cb7b9732e99c210' => 'ACD Systems Digital Imaging, Quality 4', + 'fd3eed19f6667ab0bedfa3263390ce25' => 'ACD Systems Digital Imaging, Quality 5 or 6', + 'dc0dc92085037072e27247f64af0f22d' => 'ACD Systems Digital Imaging, Quality 7', + '233ed690eb7e9008c20ed16e79aa3eb5' => 'ACD Systems Digital Imaging, Quality 8', + '684649f6c1590f5a912a827a6d8bfc6b' => 'ACD Systems Digital Imaging, Quality 9', + 'ed6aec096e8776b483b2c2b3d7e15d76' => 'ACD Systems Digital Imaging, Quality 10 or 11', + '9cd85933ddb1101d9b859a19e9a30334' => 'ACD Systems Digital Imaging, Quality 12', + '222a8769205a592ec834b6f5fc654a21' => 'ACD Systems Digital Imaging, Quality 13', + '29f957e2a0af0f44d271c3c4e27eec4b' => 'ACD Systems Digital Imaging, Quality 14', + 'c46c764191f9c3db2bfe8d134512bcd8' => 'ACD Systems Digital Imaging, Quality 15 or 16', + '56caa684ce7eb0b1cf662e1c88ed1614' => 'ACD Systems Digital Imaging, Quality 17', + 'cedc5208c6e1cbffd8be0e47bfd76698' => 'ACD Systems Digital Imaging, Quality 18', + 'dec0717305bae8309a934e1d6a251d88' => 'ACD Systems Digital Imaging, Quality 19', + '8c85e0e8f41257e2cd739a5b158ec218' => 'ACD Systems Digital Imaging, Quality 20 or 21', + '6ae7ab4e6d5e0e67006cca59c70f843c' => 'ACD Systems Digital Imaging, Quality 22', + '840be626ed18db6cdef3c5c357e24d34' => 'ACD Systems Digital Imaging, Quality 23', + 'd48c2b9e514e25fcc4b3f2408d168d72' => 'ACD Systems Digital Imaging, Quality 24', + 'b9eb63b89c80c71f4eac8c6e27d272f1' => 'ACD Systems Digital Imaging, Quality 25 or 26', + 'bcd4d36a9db91a51d1a571f71f8230d4' => 'ACD Systems Digital Imaging, Quality 27', + 'ac2f66ab2559019fcf021b9a32b049ab' => 'ACD Systems Digital Imaging, Quality 28', + '4208fca702ec702bd5d41c8231883057' => 'ACD Systems Digital Imaging, Quality 29', + 'fa620c67ab09a4c0d1c5b8e65ade361e' => 'ACD Systems Digital Imaging, Quality 30 or 31', + '679dea81c8d4563e07efac4fab6b89ca' => 'ACD Systems Digital Imaging, Quality 32', + '43ceb0c1a5d94d55ee20dc3a168498b2' => 'ACD Systems Digital Imaging, Quality 33', + 'a9cc8a19ae25bc024c3d92d84c13c7a5' => 'ACD Systems Digital Imaging, Quality 34', + 'e3e7280c8a9e82d31e22d24d5b733580' => 'ACD Systems Digital Imaging, Quality 35 or 36', + 'a06d250213e349005897bd6fa5bebca8' => 'ACD Systems Digital Imaging, Quality 37', + '40d08b823fa60b838dd9998d1e2b550a' => 'ACD Systems Digital Imaging, Quality 38', + '4998abefc838e35cf0180395309e2e33' => 'ACD Systems Digital Imaging, Quality 39', + '280205c47c8d3706c2f36b1986e9b149' => 'ACD Systems Digital Imaging, Quality 40 or 41', + '8534b67f8115ddc0296623a1ed3fc8ec' => 'ACD Systems Digital Imaging, Quality 42', + '292b83b37765408b65f496cddd3f96ea' => 'ACD Systems Digital Imaging, Quality 43', + 'cae0c8eb9a11a1f6eb7eca9651d8dbc0' => 'ACD Systems Digital Imaging, Quality 44', + '078db0d0bffafa44def2e8b85eec26f6' => 'ACD Systems Digital Imaging, Quality 45 or 46', + '6a26a11cc28df00e01d5979e2e0fb4f7' => 'ACD Systems Digital Imaging, Quality 47', + 'b41b3d226ba21244b8070ba719ec721a' => 'ACD Systems Digital Imaging, Quality 48', + '9a8a54328e297faa0a546c46145c9aa8' => 'ACD Systems Digital Imaging, Quality 49', + '256e617be51dade18503fcbbe87cd4a6' => 'ACD Systems Digital Imaging, Quality 50 or 51', + '064f160a8504465551738c9071f3850f' => 'ACD Systems Digital Imaging, Quality 52', + '5aef4c0bc6a5c8f1baded29946a56310' => 'ACD Systems Digital Imaging, Quality 53', + 'c20f4841a1ff7e393af8f6ea4124403c' => 'ACD Systems Digital Imaging, Quality 54', + '14afe9b58e0eacef42db61e1d7fdd09c' => 'ACD Systems Digital Imaging, Quality 55 or 56', + '147598404233439485574200e253f88e' => 'ACD Systems Digital Imaging, Quality 57', + '17479c1e73d2c062872c871db80d949b' => 'ACD Systems Digital Imaging, Quality 58', + 'd237b1202f88ba8183bc1cb69dd4be66' => 'ACD Systems Digital Imaging, Quality 59', + 'fc923f2d38e0e549134e1ec86f58149a' => 'ACD Systems Digital Imaging, Quality 60 or 61', + '93b4929d4a3b955f4996ab7e3b6fbe53' => 'ACD Systems Digital Imaging, Quality 62', + '054f418c24a6a733186a27aa739dc93a' => 'ACD Systems Digital Imaging, Quality 63', + '0df2be705ae86e5de1e508db95efb182' => 'ACD Systems Digital Imaging, Quality 64', + 'c1978a445de1173b5039b0cf8d8a91fe' => 'ACD Systems Digital Imaging, Quality 65 or 66', + '3d8e25b74d0d9be662f26ec5fed6fe94' => 'ACD Systems Digital Imaging, Quality 67', + '8887b718c97e0d80ed8d9a198387e2eb' => 'ACD Systems Digital Imaging, Quality 68', + '8cdb9100cfbb246d440d469e72ce37a6' => 'ACD Systems Digital Imaging, Quality 69', + '379efafa6e71a90ccfcb57073d0bc5c8' => 'ACD Systems Digital Imaging, Quality 70 or 71', + 'e1e122ebb2733a5ccdb5ff1cdce86d4d' => 'ACD Systems Digital Imaging, Quality 72', + '41dd47887a2b87e22ad3bbacc022374e' => 'ACD Systems Digital Imaging, Quality 73', + 'a0a30c816d5d47a91c66e5645eb5fdb8' => 'ACD Systems Digital Imaging, Quality 74', + '731f7ffedba80407d039c1db5a785f95' => 'ACD Systems Digital Imaging, Quality 75 or 76', + '7cfd092a41a0e1c029e82467cb4c034f' => 'ACD Systems Digital Imaging, Quality 77', + 'f1b005980104aac41b49973beed9c8c2' => 'ACD Systems Digital Imaging, Quality 78', + 'ba12dbfbd652c9cde69822996bdb2139' => 'ACD Systems Digital Imaging, Quality 79', + 'd3784280d08a8df51e607bde8c8b5ead' => 'ACD Systems Digital Imaging, Quality 80 or 81', + '7ed560efea0b44168d910a73fab9204c' => 'ACD Systems Digital Imaging, Quality 82', + 'deaa8bbd7c5414b93d8029aa14a76d3a' => 'ACD Systems Digital Imaging, Quality 83', + '9ae3a57ce98290176c4700baaff5661f' => 'ACD Systems Digital Imaging, Quality 84', + 'cb99b9bd30ae36929755fee9208ab36b' => 'ACD Systems Digital Imaging, Quality 85 or 86', + '75ff62bbf17aa1762dd15677e961ce67' => 'ACD Systems Digital Imaging, Quality 87', + 'd4f1922c71a6c96a530a9a8268fbc63b' => 'ACD Systems Digital Imaging, Quality 88', + 'ec994ef421efd6bc78671858b9f942ad' => 'ACD Systems Digital Imaging, Quality 89', + '5ca52e1ffe2c84660d7377c33c88ad53' => 'ACD Systems Digital Imaging, Quality 90 or 91', + '5522213c915e2af3ad01ee2ec27ee3ed' => 'ACD Systems Digital Imaging, Quality 92', + '21aa1a0036251eecfffd24e37d7ce3dd' => 'ACD Systems Digital Imaging, Quality 93', + '3233b63fc39fbbaa9af364e8a33862ff' => 'ACD Systems Digital Imaging, Quality 94', + '1860106097672532e7ebc2026d7f9681' => 'ACD Systems Digital Imaging, Quality 95 or 96', + '0c7d4861b3bee5d766a93f2d34027bfa' => 'ACD Systems Digital Imaging, Quality 97', + 'c9309ab058680151be5f97e6c54dc687' => 'ACD Systems Digital Imaging, Quality 98', + 'ffe6bb565b2c9008ab917c57ba94cd67' => 'ACD Systems Digital Imaging, Quality 99', + 'd6390cc36d2f03c1d2dd13d6910ca46b' => 'ACD Systems Digital Imaging, Quality 100; Pentax K20D/OptioE60 Premium', + + # StereoPhoto Maker Version 3.25 - Option "No compression ghosting" activated + '185893c53196f6156d458a84e1135c43:111111' => 'StereoPhoto Maker, No compression ghosting, Quality 1', + 'b41ccbe66e41a05de5e68832c07969a7:111111' => 'StereoPhoto Maker, No compression ghosting, Quality 2', + 'efa024d741ecc5204e7edd4f590a7a25:111111' => 'StereoPhoto Maker, No compression ghosting, Quality 3', + '3396344724a1868ada2330ebaeb9448e:111111' => 'StereoPhoto Maker, No compression ghosting, Quality 4', + '14276fffb98deb42b7dbce30abb8425f:111111' => 'StereoPhoto Maker, No compression ghosting, Quality 5', + 'a99e2826c10d0922ce8942c5437f53a6:111111' => 'StereoPhoto Maker, No compression ghosting, Quality 6', + '0d3de456aa5cbb8a2578208250aa9b88:111111' => 'StereoPhoto Maker, No compression ghosting, Quality 7', + 'fa987940fdedbe883cc0e9fcc907f89e:111111' => 'StereoPhoto Maker, No compression ghosting, Quality 8', + '1c9bb67190ee64e82d3c67f7943bf4a4:111111' => 'StereoPhoto Maker, No compression ghosting, Quality 9', + '57d20578d190b04c7667b10d3df241bb:111111' => 'StereoPhoto Maker, No compression ghosting, Quality 10', + '619fd49197f0403ce13d86cffec46419:111111' => 'StereoPhoto Maker, No compression ghosting, Quality 11', + '327f47dd8f999b2bbb3bb25c43cf5be5:111111' => 'StereoPhoto Maker, No compression ghosting, Quality 12', + 'e4e5bc705c40cfaffff6565f16fe98a9:111111' => 'StereoPhoto Maker, No compression ghosting, Quality 13', + '6c64fa9ad302624a826f04ecc80459be:111111' => 'StereoPhoto Maker, No compression ghosting, Quality 14', + '039a3f0e101f1bcdb6bb81478cf7ae6b:111111' => 'StereoPhoto Maker, No compression ghosting, Quality 15', + 'c23b08c94d7537c9447691d54ae1080c:111111' => 'StereoPhoto Maker, No compression ghosting, Quality 16', + '200107bc0174104bbf1d4653c4b05058:111111' => 'StereoPhoto Maker, No compression ghosting, Quality 17', + '72abfdc6e65b32ded2cd7ac77a04f447:111111' => 'StereoPhoto Maker, No compression ghosting, Quality 18', + '1799a236c36da0b30729d9005ca7c7f9:111111' => 'StereoPhoto Maker, No compression ghosting, Quality 19', + 'c33a667bff7f590655d196010c5e39f3:111111' => 'StereoPhoto Maker, No compression ghosting, Quality 20', + 'b1dc98f6a2f8828f8432872da43e7d94:111111' => 'StereoPhoto Maker, No compression ghosting, Quality 21', + '07318a0acfebe9086f0e04a4c4f5398a:111111' => 'StereoPhoto Maker, No compression ghosting, Quality 22', + 'a295b7163305f327a5a45ae177a0a19c:111111' => 'StereoPhoto Maker, No compression ghosting, Quality 23', + 'c741c1b134cf81ab69acc81f15a67137:111111' => 'StereoPhoto Maker, No compression ghosting, Quality 24', + 'a68893776502a591548c7b5bece13e1b:111111' => 'StereoPhoto Maker, No compression ghosting, Quality 25', + '111848d9e41f6f408ef70841f90c0519:111111' => 'StereoPhoto Maker, No compression ghosting, Quality 26', + '886374ceebcfd4dfed200b0b34b4baca:111111' => 'StereoPhoto Maker, No compression ghosting, Quality 27', + '666dd95fd0e20f5c20bc44d78d528869:111111' => 'StereoPhoto Maker, No compression ghosting, Quality 28', + '1aa58cb85dda84de2ddf436667124dcd:111111' => 'StereoPhoto Maker, No compression ghosting, Quality 29', + '9d321ab2bdda6f3cb76d2d88838aa8c3:111111' => 'StereoPhoto Maker, No compression ghosting, Quality 30', + '6ad87d648101c268f83fa379d4c773f2:111111' => 'StereoPhoto Maker, No compression ghosting, Quality 31', + 'cdf8e921300f27a4af7661a2de16e91a:111111' => 'StereoPhoto Maker, No compression ghosting, Quality 32', + '3f48672e37b6dd2e571b222e4b7ff97d:111111' => 'StereoPhoto Maker, No compression ghosting, Quality 33', + 'a53a7d4cc86d01f4c1b867270c9c078f:111111' => 'StereoPhoto Maker, No compression ghosting, Quality 34', + '09ec03f5096df106c692123f3fd34296:111111' => 'StereoPhoto Maker, No compression ghosting, Quality 35', + 'a946498fd1902c9de87a1f5182966742:111111' => 'StereoPhoto Maker, No compression ghosting, Quality 36', + '5d650a1d38108fd79d4f336ba8e254c2:111111' => 'StereoPhoto Maker, No compression ghosting, Quality 37', + '81d620f1b470fd535b26544b4ea20643:111111' => 'StereoPhoto Maker, No compression ghosting, Quality 38', + '892788bdf8cbef5c6fbd7019a079bf8e:111111' => 'StereoPhoto Maker, No compression ghosting, Quality 39', + 'cf3929fd4c1e5c28b7f137f982178ad1:111111' => 'StereoPhoto Maker, No compression ghosting, Quality 40', + '31f288945896ed839f1d936bff06fb03:111111' => 'StereoPhoto Maker, No compression ghosting, Quality 41', + 'e0c38f0c5e6562445d4e92bae51713be:111111' => 'StereoPhoto Maker, No compression ghosting, Quality 42', + '18fa29d1164984883a6af76377b60d5a:111111' => 'StereoPhoto Maker, No compression ghosting, Quality 43', + 'eff737b226fbce48c42625c5bf9dabb6:111111' => 'StereoPhoto Maker, No compression ghosting, Quality 44', + 'b900f91ee8697255d5daebce858caaeb:111111' => 'StereoPhoto Maker, No compression ghosting, Quality 45', + 'ab2f8513823067af242f7e3c04a88a9c:111111' => 'StereoPhoto Maker, No compression ghosting, Quality 46', + '60b682c4d412f5255efbaa32787c46ca:111111' => 'StereoPhoto Maker, No compression ghosting, Quality 47', + 'ea50813e06203c2ad1165252bcb99a1d:111111' => 'StereoPhoto Maker, No compression ghosting, Quality 48', + 'f6308a717437d3653b0751ebf511db0f:111111' => 'StereoPhoto Maker, No compression ghosting, Quality 49', + '7c8242581553e818ef243fc680879a19:111111' => 'StereoPhoto Maker, No compression ghosting, Quality 50', + 'fc41ab8251718977bc6676f502f457e0:111111' => 'StereoPhoto Maker, No compression ghosting, Quality 51', + '606c4c78c0226646bf4d3c5a5898fb17:111111' => 'StereoPhoto Maker, No compression ghosting, Quality 52', + '0e6c6a5440d33d25f1c25836a45cfa69:111111' => 'StereoPhoto Maker, No compression ghosting, Quality 53', + '7464b2361e5b5f5a9ba74a87475dda91:111111' => 'StereoPhoto Maker, No compression ghosting, Quality 54', + 'aeaa2ca48eabb3088ebb713b3c4e1a67:111111' => 'StereoPhoto Maker, No compression ghosting, Quality 55', + '3f36450b0ba074578391e77f7340cef0:111111' => 'StereoPhoto Maker, No compression ghosting, Quality 56', + 'be232444027e83db6f8d8b79d078442e:111111' => 'StereoPhoto Maker, No compression ghosting, Quality 57', + '712c145d6472a2b315b2ecfb916d1590:111111' => 'StereoPhoto Maker, No compression ghosting, Quality 58', + 'ae3dd4568cc71c47d068cf831c66b59d:111111' => 'StereoPhoto Maker, No compression ghosting, Quality 59', + 'b290e52c21a435fede4586636ef5e287:111111' => 'StereoPhoto Maker, No compression ghosting, Quality 60', + 'a09ca4c4391e0221396a08f229a65f9d:111111' => 'StereoPhoto Maker, No compression ghosting, Quality 61', + '0818578fc5fc571b4f8d5ffefc9dc0d8:111111' => 'StereoPhoto Maker, No compression ghosting, Quality 62', + '7c685e2916555eda34cb37a1e71adc6a:111111' => 'StereoPhoto Maker, No compression ghosting, Quality 63', + '69c6b9440342adfc0db89a6c91aba332:111111' => 'StereoPhoto Maker, No compression ghosting, Quality 64', + 'd5d484b68e25b44288e67e699829695c:111111' => 'StereoPhoto Maker, No compression ghosting, Quality 65', + 'de8310d09116a7a62965f3e0e43ef525:111111' => 'StereoPhoto Maker, No compression ghosting, Quality 66', + 'e4735f63e88baf04599afc034e690845:111111' => 'StereoPhoto Maker, No compression ghosting, Quality 67', + 'b4ef810b14dee9c6d6d8cace98f799a6:111111' => 'StereoPhoto Maker, No compression ghosting, Quality 68', + '52886ef80147c9a136e20b2bc3b76f52:111111' => 'StereoPhoto Maker, No compression ghosting, Quality 69', + '9c62dbc848be82ef91219ba9843998be:111111' => 'StereoPhoto Maker, No compression ghosting, Quality 70', + 'bfe8c1c73eea84b85673487a82f67627:111111' => 'StereoPhoto Maker, No compression ghosting, Quality 71', + 'ea445840d29c51009a2a8cd49b96ccee:111111' => 'StereoPhoto Maker, No compression ghosting, Quality 72', + '71c1a56890fff9b0a095fa5a1c96132b:111111' => 'StereoPhoto Maker, No compression ghosting, Quality 73', + 'f080b02331ac8adf03de2281042d2b49:111111' => 'StereoPhoto Maker, No compression ghosting, Quality 74', + 'd0eaa368737f17f6037757d393a22599:111111' => 'StereoPhoto Maker, No compression ghosting, Quality 75', + '303663905d055b77bb547fe0b0beb9c5:111111' => 'StereoPhoto Maker, No compression ghosting, Quality 76', + '5cdf1d5bbe19375ad5c7237273dddede:111111' => 'StereoPhoto Maker, No compression ghosting, Quality 77', + 'd64e7ff8292fd77131932864d3c9ce7c:111111' => 'StereoPhoto Maker, No compression ghosting, Quality 78', + '12b4cc13891c5aef3dadb3405b6fa65d:111111' => 'StereoPhoto Maker, No compression ghosting, Quality 79', + 'b008cd63591f8fd366f77d2b224b9c9c:111111' => 'StereoPhoto Maker, No compression ghosting, Quality 80', + '49b6e472c7d5ecead593c6009768e765:111111' => 'StereoPhoto Maker, No compression ghosting, Quality 81', + 'bce6fa61623ad4f65ff3fec1528cb026:111111' => 'StereoPhoto Maker, No compression ghosting, Quality 82', + 'c2b037bf9f5e5baba804d7bbbb2dc73b:111111' => 'StereoPhoto Maker, No compression ghosting, Quality 83', + '7fe7b339c6ffc62b984eeab4b0df9168:111111' => 'StereoPhoto Maker, No compression ghosting, Quality 84', + '274bbeb0ac3939f90c578ebb1f5a9eef:111111' => 'StereoPhoto Maker, No compression ghosting, Quality 85', + '0a0268c655d616b0e4af2851533aa3af:111111' => 'StereoPhoto Maker, No compression ghosting, Quality 86', + '52318e260c0d6b3dbee85c87f9b94e63:111111' => 'StereoPhoto Maker, No compression ghosting, Quality 87', + 'b64cc19a0f81a506ed5bcfb9c131c8fe:111111' => 'StereoPhoto Maker, No compression ghosting, Quality 88', + 'd8c54333eb475b8db9f32f11fe96337e:111111' => 'StereoPhoto Maker, No compression ghosting, Quality 89', + '12fe6b9bfd20f4d7f0ac2a221c566c45:111111' => 'StereoPhoto Maker, No compression ghosting, Quality 90', + '12aefbf7689633c83da714c9f0e90e05:111111' => 'StereoPhoto Maker, No compression ghosting, Quality 91', + 'a3a96add050fc51a2b3ce59a9a491034:111111' => 'StereoPhoto Maker, No compression ghosting, Quality 92', + '7b0242bd9aaeab4962f5d5b39b9a4027:111111' => 'StereoPhoto Maker, No compression ghosting, Quality 93', + '12fc29c1d8940c93a47ee9d927a17561:111111' => 'StereoPhoto Maker, No compression ghosting, Quality 94', + 'e1fedef5184beeb7b0f5c055c7ae1d31:111111' => 'StereoPhoto Maker, No compression ghosting, Quality 95', + 'ae9202355f603776794d3e62c43578d6:111111' => 'StereoPhoto Maker, No compression ghosting, Quality 96', + '36da00bae6cd81d1f97e32748c07e33f:111111' => 'StereoPhoto Maker, No compression ghosting, Quality 97', + + # Tested with FujiFilm FinePixViewer Ver 5.4.11G (Win) + '3a8a34631e388e39d13616d003f05957:211111' => 'FinePixViewer, Basic', + 'b6a2598792fd87b7eb0c094cbd52862f:211111' => 'FinePixViewer, Fine', + '4ee61c39b97558a273f310e085d0bdd2:211111' => 'FinePixViewer, Normal', + + # Tested with Canon Digital Photo Professional Version 3.4.1.1 (Win) + '252482232ff1c8cf77db4f0c6402f858:211111' => 'Canon Digital Photo Professional, Quality 1', + 'ec6c55677b94970bc09f70265f1d5b55:211111' => 'Canon Digital Photo Professional, Quality 2', + 'a1085c167f1cd610258fe38c8a84a8b9:211111' => 'Canon Digital Photo Professional, Quality 3', + '8ab1119f4ed4941736cb8ec1796f5674:211111' => 'Canon Digital Photo Professional, Quality 4', + 'e66c03f97b19213f385136f014c78ac1:211111' => 'Canon Digital Photo Professional, Quality 5', + 'a2f4b6ac52f87791380bdfe38ae333e1:211111' => 'Canon Digital Photo Professional, Quality 6', + 'fe85b802c5779dcf45ea4bb7749ee886:211111' => 'Canon Digital Photo Professional, Quality 7', + '35686967efa5fb333fb8f4844efc33a3:211111' => 'Canon Digital Photo Professional, Quality 8', + 'a5894172d7ec5f0c1550934c9e9385c9:211111' => 'Canon Digital Photo Professional, Quality 9', + 'd6390cc36d2f03c1d2dd13d6910ca46b:211111' => 'Canon Digital Photo Professional, Quality 10', + + # Tested with Canon ZoomBrowser EX 6.1.1.21 (Win) + 'e66c03f97b19213f385136f014c78ac1:211111' => 'Canon ZoomBrowser, Low', + 'bf72e4d4aacbdaeb86fd3f67c8df2667:211111' => 'Canon ZoomBrowser, Medium', + 'd6390cc36d2f03c1d2dd13d6910ca46b:211111' => 'Canon ZoomBrowser, Highest', + 'aeb34eb083acc888770d65e691497bcf:211111' => 'Canon ZoomBrowser, High', + + # Tested with PENTAX PHOTO Laboratory 3.51 (Win) + '76d958276bf2cac3c36b7d9a677094a7:211111' => 'PENTAX PHOTO Laboratory, Highest compression', + 'bf72e4d4aacbdaeb86fd3f67c8df2667:211111' => 'PENTAX PHOTO Laboratory, High compression', + 'fa8720d025f2a164542b6a8e31112991:211111' => 'PENTAX PHOTO Laboratory, Medium quality', + 'f3235a7d187d083b7b7ead949653f730:211111' => 'PENTAX PHOTO Laboratory, High quality', + 'd6390cc36d2f03c1d2dd13d6910ca46b:211111' => 'PENTAX PHOTO Laboratory, Highest quality', + + # Tested with Sony Image Data Converter SR Version 2.0.00.08150 (Win) + 'd6390cc36d2f03c1d2dd13d6910ca46b:211111' => 'Sony Image Data Suite, Quality 1 (high quality)', + 'aeb34eb083acc888770d65e691497bcf:211111' => 'Sony Image Data Suite, Quality 2', + '524742ca0cff64ecc0c7d7413e7d4b8d:211111' => 'Sony Image Data Suite, Quality 3', + 'c44701e8185306f5e6d09be16a2b0fbd:211111' => 'Sony Image Data Suite, Quality 4 (high compression)', + + # Devices + + # Canon + '0147c5088beb16642f9754f8671f13b3:211111' => 'Canon PowerShot, Fine', + '586b40c7d4b95e11309636703e81fbe9:211111' => 'Canon EOS 20D, Fine', + '6640ae3bb6f646013769b182c74931b5:211111' => 'Canon PowerShot, Normal', + '83d6d7dd7ace56feeeb65b88accae1bc:211111' => 'Canon PowerShot, Normal Small', + 'b8548a302585d78a0c269b54bff86541:211111' => 'Canon PowerShot, Fine Small', + '9d125046484461bbc155d8eff6d4e8f0:211111' => 'Canon PowerShot, Superfine (A430/A460)', + '0e618a0e79b4d540da1f6e07fcdce354:211111' => 'Canon PowerShot, Superfine Small', + 'd255f70a910a2d0039f4e792d2c01210:211111' => 'Canon PowerShot, Superfine Medium2', + '8bc267b04a54c02fdee1f4fdf0bcce83:211111' => 'Canon EOS 1DmkIII/5DmkII/40D/1000D, Fine', + '17cb779485969589a5c7eb07a5d53247:211111' => 'Canon EOS 1DmkIII, Fine (pre-production)', + 'ee1c033afaf4cd5263ff2b1c1ff8966c:211111' => 'Canon PowerShot, Superfine', + 'a92912eb3c81e5c873d49433264af842:211111' => 'Canon EOS 30D/40D/50D/300D, Normal', + '0cec88a0cd8fe35720e78cdcdbdadef6:121111' => 'Canon EOS 1DmkII, Fine (A)', + '72cdcc91e3ddc2c3d17c20173b75c5ef:211111' => 'Canon EOS 1DmkII, Fine (B)', + '483b5288e4256aa8ff96d6ccb96eba43:211111' => 'Canon EOS 1DmkII, Fine (C)', + 'ea2f997a0261bab501bf122b04cbc859:211111' => 'Canon EOS 1DSmkII, Fine', + '98af13526b7e4bbf73a9fb11a8fa789d:121111' => 'Canon EOS 1DSmkII, Fine (vertical)', + '9e6abfb26d3b95b8cd2f710e78def947:121111' => 'Canon EOS 300D, Fine (vertical)', + '4d6b36e81fe30c67dd53edb4d7c05422:121111' => 'Canon EOS 40D, Fine (vertical)', + '92c1557deaa14f1cdaf92cf0531487f1:121111' => 'Canon EOS 1D/1DS, Fine', + 'db8d4df12405d0d69eb25f06a963ac5b:211111' => 'Canon DV', + 'eaead98bbdfde35210f48286662e8ad2:211111' => 'Canon DV Hi-Res', + '74f0ef9476707be45f06951ca9a809ba:211111' => 'Canon DV/Optura/Elura, Superfine', + + # HTC + 'bf72e4d4aacbdaeb86fd3f67c8df2667:221111' => 'HTC Touch Diamond P3700, Quality Unknown', + + # Konica/Minolta + 'b5c213a3785c4c62b25d8f8c30758593:211111' => 'Konica/Minolta DYNAX 7D, Fine', + + # Nikon + '118a60a90c56bcb363fdd93b911a3371:211111' => 'Nikon D50 / D80, Fine', + '457b05fd0787a8e29bd43cd65911d6ca:211111' => 'Nikon D80, Basic', + '5701582a0da2e9e8dcd923a5cf877494:211111' => 'Nikon D50, Fine', + '662bd7fb9dff6426e310f9261a3703d0:211111' => 'Nikon D50, Fine', + 'e06eb7848ec8766239ff014aa8b62e49:211111' => 'Nikon D80, Normal', + '9e201a496a3700a77d9102c0dd0f8dbf:211111' => 'Nikon D300, Basic', + + # Panasonic + '07d3cd227395b060a132411cbfc22593:211111' => 'Panasonic DMC-FZ50, High (A)', + '118a60a90c56bcb363fdd93b911a3371:211111' => 'Panasonic DMC-FZ50/TZ3, High (A)', + '1b8d04b1d56a4c0c811a0d3a68e86d06:211111' => 'Panasonic DMC-FZ50, High (B)', + '1e619cbdee1f8ff196d34dad9140876f:211111' => 'Panasonic DMC-FZ50, High (C)', + '493abc7f4b392a0341bfcac091edb8f8:211111' => 'Panasonic DMC-FZ30, High (B)', + '4aa883c43840de7f0d090284120c69bc:211111' => 'Panasonic DMC-FZ50, High (D)', + '7eafb9874384d391836e64911e912295:211111' => 'Panasonic DMC-FZ50, High (E)', + '82b56237e4eccde035edff4a5abdba44:211111' => 'Panasonic DMC-FZ50, High (F)', + '8335023e5a1ee8df80d52327b0556c44:211111' => 'Panasonic DMC-FZ30, High (C)', + '8c105b3669931607853fa5ba4fffb839:211111' => 'Panasonic DMC-FZ30, High (D)', + '8ecfb959bc76e5d6703f3f3bba2c5529:211111' => 'Panasonic DMC-FZ30, High (E)', + '96eda111b2153648b3f27d6c1a9ec48f:211111' => 'Panasonic DMC-FZ50/TZ3, High (B)', + '99f76923cfbd774febea883b603b8103:211111' => 'Panasonic DMC-FZ30, High (F)', + '9b3475b865b9d31e433538460b75a588:211111' => 'Panasonic DMC-FZ10, High', + '9eb7cdfd07099c1bb8e2c6c04b20b8ba:211111' => 'Panasonic DMC-FZ30, High (G)', + '9fc030294fa5c4044dbb0cb461b0cf93:211111' => 'Panasonic DMC-TZ5, High (A)', + 'a8779af4cb8afa2def1d346a9b16e81a:211111' => 'Panasonic DMC-TZ5, High (B)', + 'bebd334aca511e2a2b6c60f43f9e6cf1:211111' => 'Panasonic DMC-FZ30, High (H)', + 'c871ce0851d4647f226b2dcfd49fe9a9:211111' => 'Panasonic DMC-L1, Very High', + 'eb625c64e32314f51dc4286564a71f7b:211111' => 'Panasonic DMC-FZ10, High', + + # Pentax + # (K10D uses same DQT tables for different qualities) + '1027a4af6a2a07e58bbd6df5b197d44e:211111' => 'Pentax K10D (A)', + '17a77c2574ff5b72b3284f57977187f3:211111' => 'Pentax K10D (B)', + '1aee684c7eb75320d988f6296c4c16ea:211111' => 'Pentax K10D (C)', + '32386501afff88b45432b23fe41593e8:211111' => 'Pentax K10D (D)', + '35ad02c3d8237a074b67423c39d3d61c:211111' => 'Pentax K10D (E)', + '39d929c095f37a90e7d083db40e8642d:211111' => 'Pentax K10D (F)', + '4127433151f74654762b1ef3293781f4:211111' => 'Pentax K10D (G)', + '599a7794c32b9d60e80426909ed40a09:211111' => 'Pentax K10D (H)', + '641812174c82d5b62ec86c33bd852204:211111' => 'Pentax K10D (I)', + '76d958276bf2cac3c36b7d9a677094a7:211111' => 'Pentax K10D (J)', + '79b07131be4827795315bf42c65212f2:211111' => 'Pentax K10D (K)', + '836448ef538366adb50202927b53808a:211111' => 'Pentax K10D (L)', + '8f70e4a31ad4584043ddc655eca17e89:211111' => 'Pentax K10D (M)', + '90d3c964eaf6e4bd12cf5ca791a7d753:211111' => 'Pentax K10D (N)', + '994a9f2060976d95719ca7064be3a99c:211111' => 'Pentax K10D (0)', + '994a9f2060976d95719ca7064be3a99c:211111' => 'Pentax K10D/K20D (P)', + '9971f02a466c47d640e8f20a2e4b55b9:211111' => 'Pentax K10D (Q)', + 'a16626c285e5a2290d331f99f4eec774:211111' => 'Pentax K10D (R)', + 'a64569d6387a118992e44e41aaeac27e:211111' => 'Pentax K10D (S)', + 'a8055a53fda7f9a0e387026c81960aa4:211111' => 'Pentax K10D (T)', + 'ab50a9f53a44ffecc54efe1cb7c6620a:211111' => 'Pentax K10D (U)', + 'aeb34eb083acc888770d65e691497bcf:211111' => 'Pentax K10D (V)', + 'af2a112c30fa29213a402dbd3c2b2d3a:211111' => 'Pentax K10D (W)', + 'bb4475a9e14464eb4682fd81cceb1f91:211111' => 'Pentax K10D (X)', + 'bf72e4d4aacbdaeb86fd3f67c8df2667:211111' => 'Pentax K10D (Y)', + '0a953ba56b59fa0bbbdac0162ea1c96b:211111' => 'Pentax K10D (Z)', + '387354b46b9726f33da5c0c1a0c383a0:211111' => 'Pentax K10D/K20D (AA)', + '4e7f4e5cd15f4fc089ab25890619dc60:211111' => 'Pentax K10D (AB)', + '6518270228fd20730740a08cc8a171f6:211111' => 'Pentax K10D (AC)', + '72bce7df55635509eb6468fc6406941d:211111' => 'Pentax K10D (AD)', + '7cafc25f204fc4ddf39d86e2f0f07b62:211111' => 'Pentax K10D (AE)', + '811e5b0229f0e8baf4b40cd2d8777550:211111' => 'Pentax K10D (AF)', + '9282a1cec6bbd1232b3673091164d43d:211111' => 'Pentax K10D (AG)', + 'c59a4cf0beedbfd1b102dc3d3c8e73ac:211111' => 'Pentax K10D (AH)', + 'd97b27b45fdbe82a79364e0939adbf90:121111' => 'Pentax K10D (AI)', + 'db87a4c5c1d4e03dc6645bcf0535a930:211111' => 'Pentax K10D (AJ)', + 'f9a93cb70da7bbe87e35cd9980a5fd47:211111' => 'Pentax K10D (AK)', + 'ff6a158f803e42bfbf9f702c016b84b3:211111' => 'Pentax K10D (AL)', + 'ff6d4a4a60a1c5e032e7fb7d9c91f817:211111' => 'Pentax K10D (AM)', + 'dca5476d81d0ceca97f480fecd09b23c:211111' => 'Pentax K10D (AN)', + 'efbe7634221900639b3c072395c61bef:211111' => 'Pentax K10D (AO)', + 'f4dba22dd251350a21f8122f2777e7b0:211111' => 'Pentax K10D (AP)', + 'f90135fcff0e1720dda86e9ad718c0c0:211111' => 'Pentax K10D (AQ)', + 'fa3d7753be7b329ab9961657cbc65386:211111' => 'Pentax K10D (AR)', + 'fa8720d025f2a164542b6a8e31112991:211111' => 'Pentax K10D (AS)', + '2941d12ef34511d96b659ba30d682cd1:211111' => 'Pentax K10D (AT)', + '2aa82b6717f1cdfe6b6d60a4486b5671:211111' => 'Pentax K10D (AU)', + '2aa82b6717f1cdfe6b6d60a4486b5671:211111' => 'Pentax K10D (AV)', + '3527616df6f26a3ab36b80a8d885fc07:211111' => 'Pentax K10D (AW)', + '3527616df6f26a3ab36b80a8d885fc07:211111' => 'Pentax K10D (AX)', + '3527616df6f26a3ab36b80a8d885fc07:211111' => 'Pentax K10D (AY)', + '5ea9e766888399a41f3f1a3c5c15cd90:211111' => 'Pentax K10D (AZ)', + 'f83d978290d0699054eabb0a7811c7a4:211111' => 'Pentax K10D (BA)', + 'f83d978290d0699054eabb0a7811c7a4:211111' => 'Pentax K10D (BB)', + 'fa8720d025f2a164542b6a8e31112991:211111' => 'Pentax K10D/K100D', + '586b40c7d4b95e11309636703e81fbe9:211111' => 'Pentax K20D/K200D/Optio 230, Best; Canon EOS 10D/300D/350D, Fine', + 'b73481179da895f3b9ecea1737054a9c:211111' => 'Pentax K20D, Best (B)', + 'b8fce00f93108e7db57a012c51fad341:211111' => 'Pentax K20D, Best (C)', + '5ee766b90badc8fed5a5386e78a80783:211111' => 'Pentax *istDS, Good (edit in camera)', + 'd528fac9b63536ff52041745945dcb09:211111' => 'Pentax *istDS, Better (edit in camera)', + 'd6390cc36d2f03c1d2dd13d6910ca46b:211111' => 'Pentax *istDS, Best (edit in camera)', + 'dc149d41f08d16cb9d52a5bdd487a67e:121111' => 'Pentax *istD/K100Dsuper/Optio300GS, Best', + 'e10030f09a14acdd647eff13c0bf333a:211111' => 'Pentax *istD/DS/DS2/K100D/Optio330GS/33L, Best', + 'ef0cd1902fb1afe284468a67eaffd078:211111' => 'Pentax *istDS/K100D/K100Dsuper, Good', + 'f1262dfcada6e6c2cd4b9fa7e881233b:211111' => 'Pentax *istDL/DS, Better', + 'f3235a7d187d083b7b7ead949653f730:211111' => 'Pentax K20D/K200D, Best (D)', + '6686cddc46088f0987e7476861fbfb47:211111' => 'Pentax K2000, Best (A)', + '5910b8431fdd8ab93ce258f366c4b867:211111' => 'Pentax K2000, Best (B)', + 'c8bfcc60aeec937300405f59373be4ef:211111' => 'Pentax K2000, Best (C)', + '689a0e3511f2aea75637f46e6af9fd9f:211111' => 'Pentax Optio A40, Best (edit in camera)', + '8d14598ae9cc1b7f5357424a19d05a71:211111' => 'Pentax Optio A30/A40, Good', + 'a4cb8a3a000484b37c4373cde1170091:211111' => 'Pentax Optio A30/A40/S10/S12, Best', + '0ac5cb651c496369d0e924ae070b7c53:211111' => 'Pentax Optio A40, Better (edit in camera)', + '1068be028c278941bd8abf3b0021655e:211111' => 'Pentax Optio A40, Good (edit in camera)', + '336eeeb78e386bf66fe6325b4a0fcfa6:211111' => 'Pentax Optio A40, Better', + 'ae2efaf1a96a4fdcfa9003b9aa963ae4:221111' => 'Pentax Optio 330, Best (vertical)', + '3803d7f6b7aed64c658c21dbb2bc0797:221111' => 'Pentax Optio 330, Best', + '353bf09900feb764885329e7bebfd95e:211111' => 'Pentax Optio 330GS, Good', + '6c2bc41a4b6ad1e20655ffcc0dfd2c41:221111' => 'Pentax Optio 330RS, Fine', + 'e9206045838e9f5f9bd207744254e96d:221111' => 'Pentax Optio 430, Best', + '759fb7011e13fa5f975bb668f5b94d8b:211111' => 'Pentax Optio 550/750Z/M60/X, Best', + '637103ef9d8e84f8345f8218f158fc3c:211111' => 'Pentax Optio 550/M10/T30/W30, Best', + '23f2a5970523c5f7fd2ab7fa3b09dff9:211111' => 'Pentax Optio 550/555/M20/M30/W10/W20, Best', + '8d2f02a07bad6b5cec48466036fef319:121111' => 'Pentax Optio 550, Better', + '27297008a89ee49804f0859ea6435878:211111' => 'Pentax Optio MX, Best', + '6cfe3833aadd87487afc11129d8cb2aa:221111' => 'Pentax Optio S, Better', + 'fcef35c97674aeb26c67e539b726057f:221111' => 'Pentax Optio S, Best (A)', + '13b2644cdad6f75767667e8ea5c218a3:221111' => 'Pentax Optio S, Best (B)', + '310b70bc4fac884f64a07040a4b87468:221111' => 'Pentax Optio S, Best (C)', + 'aa05fbe795d86a1063c55865e8613536:221111' => 'Pentax Optio S, Best (D)', + 'd57ac6956e4fe86c386f0eef00a5e021:221111' => 'Pentax Optio S, Best (E)', + '28782f5ee24fe983fe90b9438b39ae2e:221111' => 'Pentax Optio S4, Best', + '804bd63907214e005f01fb65a2bb00e6:221111' => 'Pentax Optio S4i, Best', + '84285f5b3248884488e5142b8c7210e2:211111' => 'Pentax Optio S6, Good', + 'e97694f0093de13987a335e131b30eb0:221111' => 'Pentax Optio SVi, Best', + '037d043c8a8d5332c28d59f71a0dcfd2:211111' => 'Pentax Optio E35', + 'dd8ad8ce688c4248f924022c38d3228c:211111' => 'Pentax Optio 43WR, Good', + 'e55e0c1adbbca8b9d100881248050eb5:211111' => 'Pentax Optio 43WR, Better', + '7770d784d852b3333f9213713e481125:211111' => 'Pentax Optio 450, Best', + '61d311bde22762ae0e88b768e835eced:211111' => 'Pentax Optio 33WR/M50, Best', + 'bc066ff3fbea8a290c6f9882687945e0:221111' => 'Pentax Optio 430RS, Fine', + 'b6bd9f956309a20e3a56294077536391:211111' => 'Pentax Optio A10/S7, Best', + 'a4ecd6b77f06671530942783c3595aca:211111' => 'Pentax Optio A20, Best', + '40f66b0a209f24716320636b776dda94:211111' => 'Pentax Optio E30/E40, Best', + '59a868b3d11d9cdc87859c02757e13bb:211111' => 'Pentax Optio E50, Best', + '9570584f017ed2c4f0fb91782b51faa9:211111' => 'Pentax Optio M40/Z10, Best', + '5a74f09fb2586fa000c42e98e3b9f2d8:211111' => 'Pentax Optio T10', + '0867bdf854d1fbb141411de518a66ba6:211111' => 'Pentax Optio T20 (A)', + 'f74b3853185743c111ccb13e6febdc21:211111' => 'Pentax Optio T20 (B)', + 'b6640d3879f9922708d23e6adb3d61c9:211111' => 'Pentax Optio V10, Best', + '253467dc35dfbb32cb3d619fc635d689:211111' => 'Pentax Optio V20/W60, Best', + + # Sony + '6bd350bf5df27ed1b5bf1d83fa9d021f:211111' => 'Sony DSLR-A700, Fine', +); + +#------------------------------------------------------------------------------ +# Estimate JPEG quality from quantization tables (ref 3) +# Inputs: 0) 1) DQT segments array ref +# Returns: JPEG quality, or undefined if it can't be calculated +sub EstimateQuality($) +{ + local $_; + my $dqtList = shift; + my ($i, $dqt, @qtbl, $quality, @hash, @sums); + + # unpack DQT segments and sum quantization tables + my $sum=0; +DQT: foreach $dqt (@$dqtList) { + next unless defined $dqt; + for ($i=1; $i+64<=length($dqt); $i+=65) { + my @qt = unpack("x$i C64", $dqt); + $sum += $_ foreach @qt; + push @qtbl, \@qt; + last DQT if @qtbl >= 4; + } + } + return undef unless @qtbl; + + my $qval = $qtbl[0][2] + $qtbl[0][53]; + if (@qtbl > 1) { + # color JPEG + $qval += $qtbl[1][0] + $qtbl[1][63]; + @hash =( + 1020, 1015, 932, 848, 780, 735, 702, 679, 660, 645, + 632, 623, 613, 607, 600, 594, 589, 585, 581, 571, + 555, 542, 529, 514, 494, 474, 457, 439, 424, 410, + 397, 386, 373, 364, 351, 341, 334, 324, 317, 309, + 299, 294, 287, 279, 274, 267, 262, 257, 251, 247, + 243, 237, 232, 227, 222, 217, 213, 207, 202, 198, + 192, 188, 183, 177, 173, 168, 163, 157, 153, 148, + 143, 139, 132, 128, 125, 119, 115, 108, 104, 99, + 94, 90, 84, 79, 74, 70, 64, 59, 55, 49, + 45, 40, 34, 30, 25, 20, 15, 11, 6, 4 + ); + @sums = ( + 32640, 32635, 32266, 31495, 30665, 29804, 29146, 28599, 28104, 27670, + 27225, 26725, 26210, 25716, 25240, 24789, 24373, 23946, 23572, 22846, + 21801, 20842, 19949, 19121, 18386, 17651, 16998, 16349, 15800, 15247, + 14783, 14321, 13859, 13535, 13081, 12702, 12423, 12056, 11779, 11513, + 11135, 10955, 10676, 10392, 10208, 9928, 9747, 9564, 9369, 9193, + 9017, 8822, 8639, 8458, 8270, 8084, 7896, 7710, 7527, 7347, + 7156, 6977, 6788, 6607, 6422, 6236, 6054, 5867, 5684, 5495, + 5305, 5128, 4945, 4751, 4638, 4442, 4248, 4065, 3888, 3698, + 3509, 3326, 3139, 2957, 2775, 2586, 2405, 2216, 2037, 1846, + 1666, 1483, 1297, 1109, 927, 735, 554, 375, 201, 128 + ); + } else { + # greyscale JPEG + @hash = ( + 510, 505, 422, 380, 355, 338, 326, 318, 311, 305, + 300, 297, 293, 291, 288, 286, 284, 283, 281, 280, + 279, 278, 277, 273, 262, 251, 243, 233, 225, 218, + 211, 205, 198, 193, 186, 181, 177, 172, 168, 164, + 158, 156, 152, 148, 145, 142, 139, 136, 133, 131, + 129, 126, 123, 120, 118, 115, 113, 110, 107, 105, + 102, 100, 97, 94, 92, 89, 87, 83, 81, 79, + 76, 74, 70, 68, 66, 63, 61, 57, 55, 52, + 50, 48, 44, 42, 39, 37, 34, 31, 29, 26, + 24, 21, 18, 16, 13, 11, 8, 6, 3, 2 + ); + @sums = ( + 16320, 16315, 15946, 15277, 14655, 14073, 13623, 13230, 12859, 12560, + 12240, 11861, 11456, 11081, 10714, 10360, 10027, 9679, 9368, 9056, + 8680, 8331, 7995, 7668, 7376, 7084, 6823, 6562, 6345, 6125, + 5939, 5756, 5571, 5421, 5240, 5086, 4976, 4829, 4719, 4616, + 4463, 4393, 4280, 4166, 4092, 3980, 3909, 3835, 3755, 3688, + 3621, 3541, 3467, 3396, 3323, 3247, 3170, 3096, 3021, 2952, + 2874, 2804, 2727, 2657, 2583, 2509, 2437, 2362, 2290, 2211, + 2136, 2068, 1996, 1915, 1858, 1773, 1692, 1620, 1552, 1477, + 1398, 1326, 1251, 1179, 1109, 1031, 961, 884, 814, 736, + 667, 592, 518, 441, 369, 292, 221, 151, 86, 64 + ); + } + for ($i=0; $i<100; ++$i) { + next if $qval < $hash[$i] and $sum < $sums[$i]; + $quality = $i + 1 if ($qval <= $hash[$i] and $sum <= $sums[$i]) or $i >= 50; + last; + } + return $quality; +} + +#------------------------------------------------------------------------------ +# Calculate JPEGDigest and/or JPEGQualityEstimate +# Inputs: 0) ExifTool object ref, 1) DQT segments array ref, 2) subsampling string +sub Calculate($$$) +{ + my ($et, $dqtList, $subSampling) = @_; + + # estimate JPEG quality if requested + my $all = ($$et{OPTIONS}{RequestAll} and $$et{OPTIONS}{RequestAll} > 2); + if ($all or $$et{REQ_TAG_LOOKUP}{jpegqualityestimate}) { + my $quality = EstimateQuality($dqtList); + $quality = '<unknown>' unless defined $quality; + $et->FoundTag('JPEGQualityEstimate', $quality); + } + return unless ($all or $$et{REQ_TAG_LOOKUP}{jpegdigest}) and $subSampling; + + unless (eval { require Digest::MD5 }) { + $et->Warn('Digest::MD5 must be installed to calculate JPEGDigest'); + return; + } + # create a string of DQT tables (in indexed order), separated by zero bytes + my $dqt = ''; + my $dat; + foreach $dat (@$dqtList) { + next unless $dat; + $dqt .= "\0" if $dqt; + $dqt .= $dat; + } + # generate ASCII-hex string of DQT MD5 digest + my $md5 = unpack 'H*', Digest::MD5::md5($dqt); + + # add sub-sampling string unless we get a match without it + $md5 .= ':' . $subSampling unless $PrintConv{$md5}; + + # add print conversion for JPEGDigest dynamically so it doesn't + # bulk up the documentation and slow down loading unnecessarily + $Image::ExifTool::Extra{JPEGDigest}{PrintConv} = \%PrintConv; + $et->FoundTag('JPEGDigest', $md5); +} + + +1; # end + +__END__ + +=head1 NAME + +Image::ExifTool::JPEGDigest - Calculate JPEGDigest and JPEGQualityEstimate + +=head1 SYNOPSIS + +This module is used by Image::ExifTool + +=head1 DESCRIPTION + +This module contains a lookup for values of the JPEG DQT digest, allowing +some image identification from JPEG data alone. It also calculates an +estimated JPEG quality if requested. + +=head1 AUTHOR + +Copyright 2003-2019, Phil Harvey (phil at owl.phy.queensu.ca) + +This library is free software; you can redistribute it and/or modify it +under the same terms as Perl itself. + +=head1 REFERENCES + +=over 4 + +=item L<https://github.com/ImageMagick/ImageMagick/blob/master/coders/jpeg.c> + +=back + +=head1 ACKNOWLEDGEMENTS + +Thanks to Jens Duttke for most of the work that went into this module, and +to Franz Buchinger for the values he added. + +=head1 SEE ALSO + +L<Image::ExifTool::TagNames/JPEG Tags>, +L<Image::ExifTool(3pm)|Image::ExifTool> + +=cut + diff --git a/lib/Image/ExifTool/JSON.pm b/lib/Image/ExifTool/JSON.pm new file mode 100644 index 0000000..60186a2 --- /dev/null +++ b/lib/Image/ExifTool/JSON.pm @@ -0,0 +1,142 @@ +#------------------------------------------------------------------------------ +# File: JSON.pm +# +# Description: Read JSON files +# +# Notes: Set ExifTool MissingTagValue to "null" to ignore JSON nulls +# +# Revisions: 2017/03/13 - P. Harvey Created +#------------------------------------------------------------------------------ + +package Image::ExifTool::JSON; +use strict; +use vars qw($VERSION); +use Image::ExifTool qw(:DataAccess :Utils); +use Image::ExifTool::Import; + +$VERSION = '1.01'; + +sub ProcessTag($$$$%); + +%Image::ExifTool::JSON::Main = ( + GROUPS => { 0 => 'JSON', 1 => 'JSON', 2 => 'Other' }, + NOTES => q{ + No JSON tags have been pre-defined, but ExifTool will read any existing + tags from basic JSON-formatted files. + }, +); + +#------------------------------------------------------------------------------ +# Store a tag value +# Inputs: 0) ExifTool ref, 1) tag table, 2) tag ID, 3) value, 4) tagInfo flags +sub FoundTag($$$$%) +{ + my ($et, $tagTablePtr, $tag, $val, %flags) = @_; + + # avoid conflict with special table entries + $tag .= '!' if $Image::ExifTool::specialTags{$tag}; + + AddTagToTable($tagTablePtr, $tag, { + Name => Image::ExifTool::MakeTagName($tag), + %flags, + }) unless $$tagTablePtr{$tag}; + + $et->HandleTag($tagTablePtr, $tag, $val); +} + +#------------------------------------------------------------------------------ +# Process a JSON tag +# Inputs: 0) ExifTool ref, 1) tag table, 2) tag ID, 3) value, 4) tagInfo flags +# - expands structures into flattened tags as required +sub ProcessTag($$$$%) +{ + local $_; + my ($et, $tagTablePtr, $tag, $val, %flags) = @_; + + if (ref $val eq 'HASH') { + if ($et->Options('Struct')) { + FoundTag($et, $tagTablePtr, $tag, $val, %flags, Struct => 1); + return unless $et->Options('Struct') > 1; + } + foreach (sort keys %$val) { + ProcessTag($et, $tagTablePtr, $tag . ucfirst, $$val{$_}, %flags, Flat => 1); + } + } elsif (ref $val eq 'ARRAY') { + foreach (@$val) { + ProcessTag($et, $tagTablePtr, $tag, $_, %flags, List => 1); + } + } elsif (defined $val) { + FoundTag($et, $tagTablePtr, $tag, $val, %flags); + } +} + +#------------------------------------------------------------------------------ +# Extract meta information from a JSON file +# Inputs: 0) ExifTool object reference, 1) dirInfo reference +# Returns: 1 on success, 0 if this wasn't a recognized JSON file +sub ProcessJSON($$) +{ + local $_; + my ($et, $dirInfo) = @_; + my $raf = $$dirInfo{RAF}; + my $structOpt = $et->Options('Struct'); + my (%database, $key, $tag); + + # read information from JSON file into database structure + my $err = Image::ExifTool::Import::ReadJSON($raf, \%database, + $et->Options('MissingTagValue'), $et->Options('Charset')); + + return 0 if $err or not %database; + + $et->SetFileType(); + + my $tagTablePtr = GetTagTable('Image::ExifTool::JSON::Main'); + + # remove any old tag definitions in case they change flags + foreach $key (TagTableKeys($tagTablePtr)) { + delete $$tagTablePtr{$key}; + } + + # extract tags from JSON database + foreach $key (sort keys %database) { + foreach $tag (sort keys %{$database{$key}}) { + my $val = $database{$key}{$tag}; + # (ignore SourceFile if generated automatically by ReadJSON) + next if $tag eq 'SourceFile' and defined $val and $val eq '*'; + ProcessTag($et, $tagTablePtr, $tag, $val); + } + } + return 1; +} + +1; # end + +__END__ + +=head1 NAME + +Image::ExifTool::JSON - Read JSON files + +=head1 SYNOPSIS + +This module is used by Image::ExifTool + +=head1 DESCRIPTION + +This module contains definitions required by Image::ExifTool read +information from JSON files. + +=head1 AUTHOR + +Copyright 2003-2019, Phil Harvey (phil at owl.phy.queensu.ca) + +This library is free software; you can redistribute it and/or modify it +under the same terms as Perl itself. + +=head1 SEE ALSO + +L<Image::ExifTool::TagNames/JSON Tags>, +L<Image::ExifTool(3pm)|Image::ExifTool> + +=cut + diff --git a/lib/Image/ExifTool/JVC.pm b/lib/Image/ExifTool/JVC.pm new file mode 100644 index 0000000..4c63c33 --- /dev/null +++ b/lib/Image/ExifTool/JVC.pm @@ -0,0 +1,130 @@ +#------------------------------------------------------------------------------ +# File: JVC.pm +# +# Description: JVC EXIF maker notes tags +# +# Revisions: 12/21/2005 - P. Harvey Created +#------------------------------------------------------------------------------ + +package Image::ExifTool::JVC; + +use strict; +use vars qw($VERSION); +use Image::ExifTool qw(:DataAccess :Utils); +use Image::ExifTool::Exif; + +$VERSION = '1.03'; + +sub ProcessJVCText($$$); + +# JVC EXIF-based maker notes +%Image::ExifTool::JVC::Main = ( + WRITE_PROC => \&Image::ExifTool::Exif::WriteExif, + CHECK_PROC => \&Image::ExifTool::Exif::CheckExif, + GROUPS => { 0 => 'MakerNotes', 2 => 'Camera' }, + NOTES => 'JVC EXIF maker note tags.', + #0x0001 - almost always '2', but '3' for GR-DV700 samples + 0x0002 => { #PH + Name => 'CPUVersions', + # remove trailing nulls/spaces and split at remaining nulls/spaces + ValueConv => '$_=$val; s/(\s*\0)+$//; s/(\s*\0)+/, /g; $_', + }, + 0x0003 => { #PH + Name => 'Quality', + PrintConv => { + 0 => 'Low', + 1 => 'Normal', + 2 => 'Fine', + }, + }, +); + +# JVC text-based maker notes +%Image::ExifTool::JVC::Text = ( + GROUPS => { 0 => 'MakerNotes', 2 => 'Camera' }, + PROCESS_PROC => \&ProcessJVCText, + NOTES => 'JVC/Victor text-based maker note tags.', + VER => 'MakerNoteVersion', #PH + QTY => { #PH + Name => 'Quality', + PrintConv => { + STND => 'Normal', + STD => 'Normal', + FINE => 'Fine', + }, + }, +); + +#------------------------------------------------------------------------------ +# Process JVC text-based maker notes +# Inputs: 0) ExifTool object reference +# 1) Reference to directory information hash +# 2) Pointer to tag table for this directory +# Returns: 1 on success, otherwise returns 0 and sets a Warning +sub ProcessJVCText($$$) +{ + my ($et, $dirInfo, $tagTablePtr) = @_; + my $dataPt = $$dirInfo{DataPt}; + my $dirStart = $$dirInfo{DirStart} || 0; + my $dataLen = $$dirInfo{DataLen}; + my $dirLen = $$dirInfo{DirLen} || $dataLen - $dirStart; + my $verbose = $et->Options('Verbose'); + + my $data = substr($$dataPt, $dirStart, $dirLen); + # validate text maker notes + unless ($data =~ /^VER:/) { + $et->Warn('Bad JVC text maker notes'); + return 0; + } + while ($data =~ m/([A-Z]+):(.{3,4})/sg) { + my ($tag, $val) = ($1, $2); + my $tagInfo = $et->GetTagInfo($tagTablePtr, $tag); + $et->VerboseInfo($tag, $tagInfo, + Table => $tagTablePtr, + Value => $val, + ) if $verbose; + unless ($tagInfo) { + next unless $$et{OPTIONS}{Unknown}; + $tagInfo = { + Name => "JVC_Text_$tag", + Unknown => 1, + PrintConv => 'length($val) > 60 ? substr($val,0,55) . "[...]" : $val', + }; + # add tag information to table + AddTagToTable($tagTablePtr, $tag, $tagInfo); + } + $et->FoundTag($tagInfo, $val); + } + return 1; +} + +1; # end + +__END__ + +=head1 NAME + +Image::ExifTool::JVC - JVC EXIF maker notes tags + +=head1 SYNOPSIS + +This module is loaded automatically by Image::ExifTool when required. + +=head1 DESCRIPTION + +This module contains routines used by Image::ExifTool to interpret JVC maker +notes. + +=head1 AUTHOR + +Copyright 2003-2019, Phil Harvey (phil at owl.phy.queensu.ca) + +This library is free software; you can redistribute it and/or modify it +under the same terms as Perl itself. + +=head1 SEE ALSO + +L<Image::ExifTool::TagNames/JVC Tags>, +L<Image::ExifTool(3pm)|Image::ExifTool> + +=cut diff --git a/lib/Image/ExifTool/Jpeg2000.pm b/lib/Image/ExifTool/Jpeg2000.pm new file mode 100644 index 0000000..cfa1afc --- /dev/null +++ b/lib/Image/ExifTool/Jpeg2000.pm @@ -0,0 +1,898 @@ +#------------------------------------------------------------------------------ +# File: Jpeg2000.pm +# +# Description: Read JPEG 2000 meta information +# +# Revisions: 02/11/2005 - P. Harvey Created +# 06/22/2007 - PH Added write support (EXIF, IPTC and XMP only) +# +# References: 1) http://www.jpeg.org/public/fcd15444-2.pdf +# 2) ftp://ftp.remotesensing.org/jpeg2000/fcd15444-1.pdf +#------------------------------------------------------------------------------ + +package Image::ExifTool::Jpeg2000; + +use strict; +use vars qw($VERSION); +use Image::ExifTool qw(:DataAccess :Utils); + +$VERSION = '1.26'; + +sub ProcessJpeg2000Box($$$); + +my %resolutionUnit = ( + -3 => 'km', + -2 => '100 m', + -1 => '10 m', + 0 => 'm', + 1 => '10 cm', + 2 => 'cm', + 3 => 'mm', + 4 => '0.1 mm', + 5 => '0.01 mm', + 6 => 'um', +); + +# map of where information is written in JPEG2000 image +my %jp2Map = ( + IPTC => 'UUID-IPTC', + IFD0 => 'UUID-EXIF', + XMP => 'UUID-XMP', + 'UUID-IPTC' => 'JP2', + 'UUID-EXIF' => 'JP2', + 'UUID-XMP' => 'JP2', + # jp2h => 'JP2', (not yet functional) + # ICC_Profile => 'jp2h', (not yet functional) + IFD1 => 'IFD0', + EXIF => 'IFD0', # to write EXIF as a block + ExifIFD => 'IFD0', + GPS => 'IFD0', + SubIFD => 'IFD0', + GlobParamIFD => 'IFD0', + PrintIM => 'IFD0', + InteropIFD => 'ExifIFD', + MakerNotes => 'ExifIFD', +); + +# UUID's for writable UUID directories (by tag name) +my %uuid = ( + 'UUID-EXIF' => 'JpgTiffExif->JP2', + 'UUID-EXIF2' => '', # (flags a warning when writing) + 'UUID-EXIF_bad' => '0', # (flags a warning when reading and writing) + 'UUID-IPTC' => "\x33\xc7\xa4\xd2\xb8\x1d\x47\x23\xa0\xba\xf1\xa3\xe0\x97\xad\x38", + 'UUID-XMP' => "\xbe\x7a\xcf\xcb\x97\xa9\x42\xe8\x9c\x71\x99\x94\x91\xe3\xaf\xac", + # (can't yet write GeoJP2 information) + # 'UUID-GeoJP2' => "\xb1\x4b\xf8\xbd\x08\x3d\x4b\x43\xa5\xae\x8c\xd7\xd5\xa6\xce\x03", +); + +# JPEG2000 codestream markers (ref ISO/IEC FCD15444-1/2) +my %j2cMarker = ( + 0x4f => 'SOC', # start of codestream + 0x51 => 'SIZ', # image and tile size + 0x52 => 'COD', # coding style default + 0x53 => 'COC', # coding style component + 0x55 => 'TLM', # tile-part lengths + 0x57 => 'PLM', # packet length, main header + 0x58 => 'PLT', # packet length, tile-part header + 0x5c => 'QCD', # quantization default + 0x5d => 'QCC', # quantization component + 0x5e => 'RGN', # region of interest + 0x5f => 'POD', # progression order default + 0x60 => 'PPM', # packed packet headers, main + 0x61 => 'PPT', # packed packet headers, tile-part + 0x63 => 'CRG', # component registration + 0x64 => 'CME', # comment and extension + 0x90 => 'SOT', # start of tile-part + 0x91 => 'SOP', # start of packet + 0x92 => 'EPH', # end of packet header + 0x93 => 'SOD', # start of data + # extensions (ref ISO/IEC FCD15444-2) + 0x70 => 'DCO', # variable DC offset + 0x71 => 'VMS', # visual masking + 0x72 => 'DFS', # downsampling factor style + 0x73 => 'ADS', # arbitrary decomposition style + # 0x72 => 'ATK', # arbitrary transformation kernels ? + 0x78 => 'CBD', # component bit depth + 0x74 => 'MCT', # multiple component transformation definition + 0x75 => 'MCC', # multiple component collection + 0x77 => 'MIC', # multiple component intermediate collection + 0x76 => 'NLT', # non-linearity point transformation +); + +# JPEG 2000 "box" (ie. atom) names +# Note: only tags with a defined "Format" are extracted +%Image::ExifTool::Jpeg2000::Main = ( + GROUPS => { 2 => 'Image' }, + PROCESS_PROC => \&ProcessJpeg2000Box, + WRITE_PROC => \&ProcessJpeg2000Box, + PREFERRED => 1, # always add these tags when writing + NOTES => q{ + The tags below are extracted from JPEG 2000 images, however ExifTool + currently writes only EXIF, IPTC and XMP tags in these images. + }, + 'jP ' => 'JP2Signature', # (ref 1) + "jP\x1a\x1a" => 'JP2Signature', # (ref 2) + prfl => 'Profile', + ftyp => { + Name => 'FileType', + SubDirectory => { TagTable => 'Image::ExifTool::Jpeg2000::FileType' }, + }, + rreq => 'ReaderRequirements', + jp2h => { + Name => 'JP2Header', + SubDirectory => { }, + }, + # JP2Header sub boxes... + ihdr => { + Name => 'ImageHeader', + SubDirectory => { + TagTable => 'Image::ExifTool::Jpeg2000::ImageHeader', + }, + }, + bpcc => 'BitsPerComponent', + colr => { + Name => 'ColorSpecification', + SubDirectory => { + TagTable => 'Image::ExifTool::Jpeg2000::ColorSpec', + }, + }, + pclr => 'Palette', + cdef => 'ComponentDefinition', + 'res '=> { + Name => 'Resolution', + SubDirectory => { }, + }, + # Resolution sub boxes... + resc => { + Name => 'CaptureResolution', + SubDirectory => { + TagTable => 'Image::ExifTool::Jpeg2000::CaptureResolution', + }, + }, + resd => { + Name => 'DisplayResolution', + SubDirectory => { + TagTable => 'Image::ExifTool::Jpeg2000::DisplayResolution', + }, + }, + jpch => { + Name => 'CodestreamHeader', + SubDirectory => { }, + }, + # CodestreamHeader sub boxes... + 'lbl '=> { + Name => 'Label', + Format => 'string', + }, + cmap => 'ComponentMapping', + roid => 'ROIDescription', + jplh => { + Name => 'CompositingLayerHeader', + SubDirectory => { }, + }, + # CompositingLayerHeader sub boxes... + cgrp => 'ColorGroup', + opct => 'Opacity', + creg => 'CodestreamRegistration', + dtbl => 'DataReference', + ftbl => { + Name => 'FragmentTable', + Subdirectory => { }, + }, + # FragmentTable sub boxes... + flst => 'FragmentList', + cref => 'Cross-Reference', + mdat => 'MediaData', + comp => 'Composition', + copt => 'CompositionOptions', + inst => 'InstructionSet', + asoc => 'Association', + nlst => 'NumberList', + bfil => 'BinaryFilter', + drep => 'DesiredReproductions', + # DesiredReproductions sub boxes... + gtso => 'GraphicsTechnologyStandardOutput', + chck => 'DigitalSignature', + mp7b => 'MPEG7Binary', + free => 'Free', + jp2c => 'ContiguousCodestream', + jp2i => { + Name => 'IntellectualProperty', + SubDirectory => { TagTable => 'Image::ExifTool::XMP::Main' }, + }, + 'xml '=> { + Name => 'XML', + Writable => 'undef', + Flags => [ 'Binary', 'Protected', 'BlockExtract' ], + List => 1, + Notes => q{ + by default, the XML data in this tag is parsed using the ExifTool XMP module + to to allow individual tags to be accessed when reading, but it may also be + extracted as a block via the "XML" tag, which is also how this tag is + written and copied. This is a List-type tag because multiple XML blocks may + exist + }, + SubDirectory => { TagTable => 'Image::ExifTool::XMP::Main' }, + }, + uuid => [ + { + Name => 'UUID-EXIF', + # (this is the EXIF that we create) + Condition => '$$valPt=~/^JpgTiffExif->JP2(?!Exif\0\0)/', + SubDirectory => { + TagTable => 'Image::ExifTool::Exif::Main', + ProcessProc => \&Image::ExifTool::ProcessTIFF, + WriteProc => \&Image::ExifTool::WriteTIFF, + DirName => 'EXIF', + Start => '$valuePtr + 16', + }, + }, + { + Name => 'UUID-EXIF2', + # written by Photoshop 7.01+Adobe JPEG2000-plugin v1.5 + Condition => '$$valPt=~/^\x05\x37\xcd\xab\x9d\x0c\x44\x31\xa7\x2a\xfa\x56\x1f\x2a\x11\x3e/', + SubDirectory => { + TagTable => 'Image::ExifTool::Exif::Main', + ProcessProc => \&Image::ExifTool::ProcessTIFF, + WriteProc => \&Image::ExifTool::WriteTIFF, + DirName => 'EXIF', + Start => '$valuePtr + 16', + }, + }, + { + Name => 'UUID-EXIF_bad', + # written by Digikam + Condition => '$$valPt=~/^JpgTiffExif->JP2/', + SubDirectory => { + TagTable => 'Image::ExifTool::Exif::Main', + ProcessProc => \&Image::ExifTool::ProcessTIFF, + WriteProc => \&Image::ExifTool::WriteTIFF, + DirName => 'EXIF', + Start => '$valuePtr + 22', + }, + }, + { + Name => 'UUID-IPTC', + # (this is the IPTC that we create) + Condition => '$$valPt=~/^\x33\xc7\xa4\xd2\xb8\x1d\x47\x23\xa0\xba\xf1\xa3\xe0\x97\xad\x38/', + SubDirectory => { + TagTable => 'Image::ExifTool::IPTC::Main', + Start => '$valuePtr + 16', + }, + }, + { + Name => 'UUID-IPTC2', + # written by Photoshop 7.01+Adobe JPEG2000-plugin v1.5 + Condition => '$$valPt=~/^\x09\xa1\x4e\x97\xc0\xb4\x42\xe0\xbe\xbf\x36\xdf\x6f\x0c\xe3\x6f/', + SubDirectory => { + TagTable => 'Image::ExifTool::IPTC::Main', + Start => '$valuePtr + 16', + }, + }, + { + Name => 'UUID-XMP', + # ref http://www.adobe.com/products/xmp/pdfs/xmpspec.pdf + Condition => '$$valPt=~/^\xbe\x7a\xcf\xcb\x97\xa9\x42\xe8\x9c\x71\x99\x94\x91\xe3\xaf\xac/', + SubDirectory => { + TagTable => 'Image::ExifTool::XMP::Main', + Start => '$valuePtr + 16', + }, + }, + { + Name => 'UUID-GeoJP2', + # ref http://www.remotesensing.org/jpeg2000/ + Condition => '$$valPt=~/^\xb1\x4b\xf8\xbd\x08\x3d\x4b\x43\xa5\xae\x8c\xd7\xd5\xa6\xce\x03/', + SubDirectory => { + TagTable => 'Image::ExifTool::Exif::Main', + ProcessProc => \&Image::ExifTool::ProcessTIFF, + Start => '$valuePtr + 16', + }, + }, + { + Name => 'UUID-Photoshop', + # written by Photoshop 7.01+Adobe JPEG2000-plugin v1.5 + Condition => '$$valPt=~/^\x2c\x4c\x01\x00\x85\x04\x40\xb9\xa0\x3e\x56\x21\x48\xd6\xdf\xeb/', + SubDirectory => { + TagTable => 'Image::ExifTool::Photoshop::Main', + Start => '$valuePtr + 16', + }, + }, + { + Name => 'UUID-Unknown', + }, + # also written by Adobe JPEG2000 plugin v1.5: + # 3a 0d 02 18 0a e9 41 15 b3 76 4b ca 41 ce 0e 71 - 1 byte (01) + # 47 c9 2c cc d1 a1 45 81 b9 04 38 bb 54 67 71 3b - 1 byte (01) + # bc 45 a7 74 dd 50 4e c6 a9 f6 f3 a1 37 f4 7e 90 - 4 bytes (00 00 00 32) + # d7 c8 c5 ef 95 1f 43 b2 87 57 04 25 00 f5 38 e8 - 4 bytes (00 00 00 32) + ], + uinf => { + Name => 'UUIDInfo', + SubDirectory => { }, + }, + # UUIDInfo sub boxes... + ulst => 'UUIDList', + 'url '=> { + Name => 'URL', + Format => 'string', + }, +); + +%Image::ExifTool::Jpeg2000::ImageHeader = ( + PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData, + GROUPS => { 2 => 'Image' }, + 0 => { + Name => 'ImageHeight', + Format => 'int32u', + }, + 4 => { + Name => 'ImageWidth', + Format => 'int32u', + }, + 8 => { + Name => 'NumberOfComponents', + Format => 'int16u', + }, + 10 => { + Name => 'BitsPerComponent', + PrintConv => q{ + $val == 0xff and return 'Variable'; + my $sign = ($val & 0x80) ? 'Signed' : 'Unsigned'; + return (($val & 0x7f) + 1) . " Bits, $sign"; + }, + }, + 11 => { + Name => 'Compression', + PrintConv => { + 0 => 'Uncompressed', + 1 => 'Modified Huffman', + 2 => 'Modified READ', + 3 => 'Modified Modified READ', + 4 => 'JBIG', + 5 => 'JPEG', + 6 => 'JPEG-LS', + 7 => 'JPEG 2000', + 8 => 'JBIG2', + }, + }, +); + +# (ref fcd15444-1/2/6.pdf) +# (also see http://developer.apple.com/mac/library/documentation/QuickTime/QTFF/QTFFChap1/qtff1.html) +%Image::ExifTool::Jpeg2000::FileType = ( + PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData, + GROUPS => { 2 => 'Video' }, + FORMAT => 'int32u', + 0 => { + Name => 'MajorBrand', + Format => 'undef[4]', + PrintConv => { + 'jp2 ' => 'JPEG 2000 Image (.JP2)', # image/jp2 + 'jpm ' => 'JPEG 2000 Compound Image (.JPM)', # image/jpm + 'jpx ' => 'JPEG 2000 with extensions (.JPX)', # image/jpx + }, + }, + 1 => { + Name => 'MinorVersion', + Format => 'undef[4]', + ValueConv => 'sprintf("%x.%x.%x", unpack("nCC", $val))', + }, + 2 => { + Name => 'CompatibleBrands', + Format => 'undef[$size-8]', + # ignore any entry with a null, and return others as a list + ValueConv => 'my @a=($val=~/.{4}/sg); @a=grep(!/\0/,@a); \@a', + }, +); + +%Image::ExifTool::Jpeg2000::CaptureResolution = ( + PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData, + GROUPS => { 2 => 'Image' }, + FORMAT => 'int8s', + 0 => { + Name => 'CaptureYResolution', + Format => 'rational32u', + }, + 4 => { + Name => 'CaptureXResolution', + Format => 'rational32u', + }, + 8 => { + Name => 'CaptureYResolutionUnit', + SeparateTable => 'ResolutionUnit', + PrintConv => \%resolutionUnit, + }, + 9 => { + Name => 'CaptureXResolutionUnit', + SeparateTable => 'ResolutionUnit', + PrintConv => \%resolutionUnit, + }, +); + +%Image::ExifTool::Jpeg2000::DisplayResolution = ( + PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData, + GROUPS => { 2 => 'Image' }, + FORMAT => 'int8s', + 0 => { + Name => 'DisplayYResolution', + Format => 'rational32u', + }, + 4 => { + Name => 'DisplayXResolution', + Format => 'rational32u', + }, + 8 => { + Name => 'DisplayYResolutionUnit', + SeparateTable => 'ResolutionUnit', + PrintConv => \%resolutionUnit, + }, + 9 => { + Name => 'DisplayXResolutionUnit', + SeparateTable => 'ResolutionUnit', + PrintConv => \%resolutionUnit, + }, +); + +%Image::ExifTool::Jpeg2000::ColorSpec = ( + PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData, + GROUPS => { 2 => 'Image' }, + FORMAT => 'int8s', + 0 => { + Name => 'ColorSpecMethod', + RawConv => '$$self{ColorSpecMethod} = $val', + PrintConv => { + 1 => 'Enumerated', + 2 => 'Restricted ICC', + 3 => 'Any ICC', + 4 => 'Vendor Color', + }, + }, + 1 => 'ColorSpecPrecedence', + 2 => { + Name => 'ColorSpecApproximation', + PrintConv => { + 0 => 'Not Specified', + 1 => 'Accurate', + 2 => 'Exceptional Quality', + 3 => 'Reasonable Quality', + 4 => 'Poor Quality', + }, + }, + 3 => [ + { + Name => 'ICC_Profile', + Condition => q{ + $$self{ColorSpecMethod} == 2 or + $$self{ColorSpecMethod} == 3 + }, + Format => 'undef[$size-3]', + SubDirectory => { + TagTable => 'Image::ExifTool::ICC_Profile::Main', + }, + }, + { + Name => 'ColorSpace', + Condition => '$$self{ColorSpecMethod} == 1', + Format => 'int32u', + PrintConv => { # ref 15444-2 2002-05-15 + 0 => 'Bi-level', + 1 => 'YCbCr(1)', + 3 => 'YCbCr(2)', + 4 => 'YCbCr(3)', + 9 => 'PhotoYCC', + 11 => 'CMY', + 12 => 'CMYK', + 13 => 'YCCK', + 14 => 'CIELab', + 15 => 'Bi-level(2)', # (incorrectly listed as 18 in 15444-2 2000-12-07) + 16 => 'sRGB', + 17 => 'Grayscale', + 18 => 'sYCC', + 19 => 'CIEJab', + 20 => 'e-sRGB', + 21 => 'ROMM-RGB', + # incorrect in 15444-2 2000-12-07 + #22 => 'sRGB based YCbCr', + #23 => 'YPbPr(1125/60)', + #24 => 'YPbPr(1250/50)', + 22 => 'YPbPr(1125/60)', + 23 => 'YPbPr(1250/50)', + 24 => 'e-sYCC', + }, + }, + { + Name => 'ColorSpecData', + Format => 'undef[$size-3]', + Binary => 1, + }, + ], +); + +#------------------------------------------------------------------------------ +# Create new JPEG 2000 boxes when writing +# (Currently only supports adding top-level Writable JPEG2000 tags and certain UUID boxes) +# Inputs: 0) ExifTool object ref, 1) Output file or scalar ref +# Returns: 1 on success +sub CreateNewBoxes($$) +{ + my ($et, $outfile) = @_; + my $addTags = $$et{AddJp2Tags}; + my $addDirs = $$et{AddJp2Dirs}; + delete $$et{AddJp2Tags}; + delete $$et{AddJp2Dirs}; + my ($tag, $dirName); + # add JPEG2000 tags + foreach $tag (sort keys %$addTags) { + my $tagInfo = $$addTags{$tag}; + my $nvHash = $et->GetNewValueHash($tagInfo); + # (native JPEG2000 information is always preferred, so don't check IsCreating) + next unless $$tagInfo{List} or $et->IsOverwriting($nvHash) > 0; + next if $$nvHash{EditOnly}; + my @vals = $et->GetNewValue($nvHash); + my $val; + foreach $val (@vals) { + my $boxhdr = pack('N', length($val) + 8) . $$tagInfo{TagID}; + Write($outfile, $boxhdr, $val) or return 0; + ++$$et{CHANGED}; + $et->VerboseValue("+ Jpeg2000:$$tagInfo{Name}", $val); + } + } + # add UUID boxes + foreach $dirName (sort keys %$addDirs) { + next unless $uuid{$dirName}; + my $tagInfo; + foreach $tagInfo (@{$Image::ExifTool::Jpeg2000::Main{uuid}}) { + next unless $$tagInfo{Name} eq $dirName; + my $subdir = $$tagInfo{SubDirectory}; + my $tagTable = GetTagTable($$subdir{TagTable}); + my %dirInfo = ( + DirName => $$subdir{DirName} || $dirName, + Parent => 'JP2', + ); + # remove "UUID-" from start of directory name to allow appropriate + # directories to be written as a block + $dirInfo{DirName} =~ s/^UUID-//; + my $newdir = $et->WriteDirectory(\%dirInfo, $tagTable, $$subdir{WriteProc}); + if (defined $newdir and length $newdir) { + my $boxhdr = pack('N', length($newdir) + 24) . 'uuid' . $uuid{$dirName}; + Write($outfile, $boxhdr, $newdir) or return 0; + last; + } + } + } + return 1; +} + +#------------------------------------------------------------------------------ +# Process JPEG 2000 box +# Inputs: 0) ExifTool object reference, 1) dirInfo reference, 2) Pointer to tag table +# Returns: 1 on success when reading, or -1 on write error +# (or JP2 box or undef when writing from buffer) +sub ProcessJpeg2000Box($$$) +{ + my ($et, $dirInfo, $tagTablePtr) = @_; + my $dataPt = $$dirInfo{DataPt}; + my $dataLen = $$dirInfo{DataLen}; + my $dataPos = $$dirInfo{DataPos}; + my $dirLen = $$dirInfo{DirLen} || 0; + my $dirStart = $$dirInfo{DirStart} || 0; + my $base = $$dirInfo{Base} || 0; + my $raf = $$dirInfo{RAF}; + my $outfile = $$dirInfo{OutFile}; + my $dirEnd = $dirStart + $dirLen; + my ($err, $outBuff, $verbose); + + if ($outfile) { + unless ($raf) { + # buffer output to be used for return value + $outBuff = ''; + $outfile = \$outBuff; + } + } else { + # (must not set verbose flag when writing!) + $verbose = $$et{OPTIONS}{Verbose}; + $et->VerboseDir($$dirInfo{DirName}) if $verbose; + } + # loop through all contained boxes + my ($pos, $boxLen); + for ($pos=$dirStart; ; $pos+=$boxLen) { + my ($boxID, $buff, $valuePtr); + my $hdrLen = 8; # the box header length + if ($raf) { + $dataPos = $raf->Tell() - $base; + my $n = $raf->Read($buff,$hdrLen); + unless ($n == $hdrLen) { + $n and $err = '', last; + if ($outfile) { + CreateNewBoxes($et, $outfile) or $err = 1; + } + last; + } + $dataPt = \$buff; + $dirLen = $dirEnd = $hdrLen; + $pos = 0; + } elsif ($pos >= $dirEnd - $hdrLen) { + $err = '' unless $pos == $dirEnd; + last; + } + $boxLen = unpack("x$pos N",$$dataPt); # (length includes header and data) + $boxID = substr($$dataPt, $pos+4, 4); + $pos += $hdrLen; # move to end of box header + if ($boxLen == 1) { + # box header contains an additional 8-byte integer for length + $hdrLen += 8; + if ($raf) { + my $buf2; + if ($raf->Read($buf2,8) == 8) { + $buff .= $buf2; + $dirLen = $dirEnd = $hdrLen; + } + } + $pos > $dirEnd - 8 and $err = '', last; + my ($hi, $lo) = unpack("x$pos N2",$$dataPt); + $hi and $err = "Can't currently handle JPEG 2000 boxes > 4 GB", last; + $pos += 8; # move to end of extended-length box header + $boxLen = $lo - $hdrLen; # length of remaining box data + } elsif ($boxLen == 0) { + if ($raf) { + if ($outfile) { + CreateNewBoxes($et, $outfile) or $err = 1; + # copy over the rest of the file + Write($outfile, $$dataPt) or $err = 1; + while ($raf->Read($buff, 65536)) { + Write($outfile, $buff) or $err = 1; + } + } elsif ($verbose) { + my $msg = sprintf("offset 0x%.4x to end of file", $dataPos + $base + $pos); + $et->VPrint(0, "$$et{INDENT}- Tag '${boxID}' ($msg)\n"); + } + last; # (ignore the rest of the file when reading) + } + $boxLen = $dirEnd - $pos; # data runs to end of file + } else { + $boxLen -= $hdrLen; # length of remaining box data + } + $boxLen < 0 and $err = 'Invalid JPEG 2000 box length', last; + my $tagInfo = $et->GetTagInfo($tagTablePtr, $boxID); + unless (defined $tagInfo or $verbose) { + # no need to process this box + if ($raf) { + if ($outfile) { + Write($outfile, $$dataPt) or $err = 1; + $raf->Read($buff,$boxLen) == $boxLen or $err = '', last; + Write($outfile, $buff) or $err = 1; + } else { + $raf->Seek($boxLen, 1) or $err = 'Seek error', last; + } + } elsif ($outfile) { + Write($outfile, substr($$dataPt, $pos-$hdrLen, $boxLen+$hdrLen)) or $err = '', last; + } + next; + } + if ($raf) { + # read the box data + $dataPos = $raf->Tell() - $base; + $raf->Read($buff,$boxLen) == $boxLen or $err = '', last; + $valuePtr = 0; + $dataLen = $boxLen; + } elsif ($pos + $boxLen > $dirEnd) { + $err = ''; + last; + } else { + $valuePtr = $pos; + } + if (defined $tagInfo and not $tagInfo) { + # GetTagInfo() required the value for a Condition + my $tmpVal = substr($$dataPt, $valuePtr, $boxLen < 128 ? $boxLen : 128); + $tagInfo = $et->GetTagInfo($tagTablePtr, $boxID, \$tmpVal); + } + # delete all UUID boxes and any writable box if deleting all information + if ($outfile and $tagInfo) { + if ($boxID eq 'uuid' and $$et{DEL_GROUP}{'*'}) { + $et->VPrint(0, " Deleting $$tagInfo{Name}\n"); + ++$$et{CHANGED}; + next; + } elsif ($$tagInfo{Writable}) { + my $isOverwriting; + if ($$et{DEL_GROUP}{Jpeg2000}) { + $isOverwriting = 1; + } else { + my $nvHash = $et->GetNewValueHash($tagInfo); + $isOverwriting = $et->IsOverwriting($nvHash); + } + if ($isOverwriting) { + my $val = substr($$dataPt, $valuePtr, $boxLen); + $et->VerboseValue("- Jpeg2000:$$tagInfo{Name}", $val); + ++$$et{CHANGED}; + next; + } elsif (not $$tagInfo{List}) { + delete $$et{AddJp2Tags}{$boxID}; + } + } + } + if ($verbose) { + $et->VerboseInfo($boxID, $tagInfo, + Table => $tagTablePtr, + DataPt => $dataPt, + Size => $boxLen, + Start => $valuePtr, + Addr => $valuePtr + $dataPos + $base, + ); + next unless $tagInfo; + } + if ($$tagInfo{SubDirectory}) { + my $subdir = $$tagInfo{SubDirectory}; + my $subdirStart = $valuePtr; + if (defined $$subdir{Start}) { + #### eval Start ($valuePtr) + $subdirStart = eval($$subdir{Start}); + } + my $subdirLen = $boxLen - ($subdirStart - $valuePtr); + my %subdirInfo = ( + Parent => 'JP2', + DataPt => $dataPt, + DataPos => -$subdirStart, # (relative to Base) + DataLen => $dataLen, + DirStart => $subdirStart, + DirLen => $subdirLen, + DirName => $$subdir{DirName} || $$tagInfo{Name}, + OutFile => $outfile, + Base => $base + $dataPos + $subdirStart, + ); + my $uuid = $uuid{$$tagInfo{Name}}; + # remove "UUID-" prefix to allow appropriate directories to be written as a block + $subdirInfo{DirName} =~ s/^UUID-//; + my $subTable = GetTagTable($$subdir{TagTable}) || $tagTablePtr; + if ($outfile) { + # remove this directory from our create list + delete $$et{AddJp2Dirs}{$$tagInfo{Name}}; + my $newdir; + # only edit writable UUID boxes + if ($uuid) { + $newdir = $et->WriteDirectory(\%subdirInfo, $subTable, $$subdir{WriteProc}); + next if defined $newdir and not length $newdir; # next if deleting the box + } elsif (defined $uuid) { + $et->Warn("Not editing $$tagInfo{Name} box", 1); + } + # use old box data if not changed + defined $newdir or $newdir = substr($$dataPt, $subdirStart, $subdirLen); + my $prefixLen = $subdirStart - $valuePtr; + my $boxhdr = pack('N', length($newdir) + 8 + $prefixLen) . $boxID; + $boxhdr .= substr($$dataPt, $valuePtr, $prefixLen) if $prefixLen; + Write($outfile, $boxhdr, $newdir) or $err = 1; + } else { + # extract as a block if specified + $subdirInfo{BlockInfo} = $tagInfo if $$tagInfo{BlockExtract}; + $et->Warn("Reading non-standard $$tagInfo{Name} box") if defined $uuid and $uuid eq '0'; + unless ($et->ProcessDirectory(\%subdirInfo, $subTable, $$subdir{ProcessProc})) { + if ($subTable eq $tagTablePtr) { + $err = 'JPEG 2000 format error'; + last; + } + $et->Warn("Unrecognized $$tagInfo{Name} box"); + } + } + } elsif ($$tagInfo{Format} and not $outfile) { + # only save tag values if Format was specified + my $rational; + my $val = ReadValue($dataPt, $valuePtr, $$tagInfo{Format}, undef, $boxLen, \$rational); + if (defined $val) { + my $key = $et->FoundTag($tagInfo, $val); + # save Rational value + $$et{RATIONAL}{$key} = $rational if defined $rational and defined $key; + } + } elsif ($outfile) { + my $boxhdr = pack('N', $boxLen + 8) . $boxID; + Write($outfile, $boxhdr, substr($$dataPt, $valuePtr, $boxLen)) or $err = 1; + } + } + if (defined $err) { + $err or $err = 'Truncated JPEG 2000 box'; + if ($outfile) { + $et->Error($err) unless $err eq '1'; + return $raf ? -1 : undef; + } + $et->Warn($err); + } + return $outBuff if $outfile and not $raf; + return 1; +} + +#------------------------------------------------------------------------------ +# Read/write meta information from a JPEG 2000 image +# Inputs: 0) ExifTool object reference, 1) dirInfo reference +# Returns: 1 on success, 0 if this wasn't a valid JPEG 2000 file, or -1 on write error +sub ProcessJP2($$) +{ + local $_; + my ($et, $dirInfo) = @_; + my $raf = $$dirInfo{RAF}; + my $outfile = $$dirInfo{OutFile}; + my $hdr; + + # check to be sure this is a valid JPG2000 file + return 0 unless $raf->Read($hdr,12) == 12; + unless ($hdr eq "\x00\x00\x00\x0cjP \x0d\x0a\x87\x0a" or # (ref 1) + $hdr eq "\x00\x00\x00\x0cjP\x1a\x1a\x0d\x0a\x87\x0a") # (ref 2) + { + return 0 unless $hdr =~ /^\xff\x4f\xff\x51\0/; # check for JP2 codestream format + if ($outfile) { + $et->Error('Writing of J2C files is not yet supported'); + return 0 + } + # add J2C markers if not done already + unless ($Image::ExifTool::jpegMarker{0x4f}) { + $Image::ExifTool::jpegMarker{$_} = $j2cMarker{$_} foreach keys %j2cMarker; + } + $et->SetFileType('J2C'); + $raf->Seek(0,0); + return $et->ProcessJPEG($dirInfo); # decode with JPEG processor + } + if ($outfile) { + Write($outfile, $hdr) or return -1; + $et->InitWriteDirs(\%jp2Map); + # save list of directories to create + my %addDirs = %{$$et{ADD_DIRS}}; + $$et{AddJp2Dirs} = \%addDirs; + $$et{AddJp2Tags} = $et->GetNewTagInfoHash(\%Image::ExifTool::Jpeg2000::Main); + } else { + my ($buff, $fileType); + # recognize JPX and JPM as unique types of JP2 + if ($raf->Read($buff, 12) == 12 and $buff =~ /^.{4}ftyp(.{4})/s) { + $fileType = 'JPX' if $1 eq 'jpx '; + $fileType = 'JPM' if $1 eq 'jpm '; + } + $raf->Seek(-length($buff), 1) if defined $buff; + $et->SetFileType($fileType); + } + SetByteOrder('MM'); # JPEG 2000 files are big-endian + my %dirInfo = ( + RAF => $raf, + DirName => 'JP2', + OutFile => $$dirInfo{OutFile}, + ); + my $tagTablePtr = GetTagTable('Image::ExifTool::Jpeg2000::Main'); + return $et->ProcessDirectory(\%dirInfo, $tagTablePtr); +} + +1; # end + +__END__ + +=head1 NAME + +Image::ExifTool::Jpeg2000 - Read JPEG 2000 meta information + +=head1 SYNOPSIS + +This module is used by Image::ExifTool + +=head1 DESCRIPTION + +This module contains routines required by Image::ExifTool to read JPEG 2000 +files. + +=head1 AUTHOR + +Copyright 2003-2019, Phil Harvey (phil at owl.phy.queensu.ca) + +This library is free software; you can redistribute it and/or modify it +under the same terms as Perl itself. + +=head1 REFERENCES + +=over 4 + +=item L<http://www.jpeg.org/public/fcd15444-2.pdf> + +=item L<ftp://ftp.remotesensing.org/jpeg2000/fcd15444-1.pdf> + +=back + +=head1 SEE ALSO + +L<Image::ExifTool::TagNames/Jpeg2000 Tags>, +L<Image::ExifTool(3pm)|Image::ExifTool> + +=cut + diff --git a/lib/Image/ExifTool/Kodak.pm b/lib/Image/ExifTool/Kodak.pm new file mode 100644 index 0000000..1c46051 --- /dev/null +++ b/lib/Image/ExifTool/Kodak.pm @@ -0,0 +1,3272 @@ +#------------------------------------------------------------------------------ +# File: Kodak.pm +# +# Description: Kodak EXIF maker notes and APP3 "Meta" tags +# +# Revisions: 03/28/2005 - P. Harvey Created +# +# References: 1) http://search.cpan.org/dist/Image-MetaData-JPEG/ +# 2) http://www.ozhiker.com/electronics/pjmt/jpeg_info/meta.html +# 3) http://www.cybercom.net/~dcoffin/dcraw/ +# 4) Jim McGarvey private communication +# IB) Iliah Borg private communication (LibRaw) +# +# Notes: There really isn't much public information about Kodak formats. +# The only source I could find was Image::MetaData::JPEG, which +# didn't provide information about decoding the tag values. So +# this module represents a lot of work downloading sample images +# (about 100MB worth!), and testing with my daughter's CX4200. +#------------------------------------------------------------------------------ + +package Image::ExifTool::Kodak; + +use strict; +use vars qw($VERSION); +use Image::ExifTool qw(:DataAccess :Utils); +use Image::ExifTool::Exif; + +$VERSION = '1.44'; + +sub ProcessKodakIFD($$$); +sub ProcessKodakText($$$); +sub ProcessPose($$$); +sub WriteKodakIFD($$$); + +# Kodak type 1 maker notes (ref 1) +%Image::ExifTool::Kodak::Main = ( + GROUPS => { 0 => 'MakerNotes', 2 => 'Camera' }, + PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData, + WRITE_PROC => \&Image::ExifTool::WriteBinaryData, + CHECK_PROC => \&Image::ExifTool::CheckBinaryData, + NOTES => q{ + The table below contains the most common set of Kodak tags. The following + Kodak camera models have been tested and found to use these tags: C360, + C663, C875, CX6330, CX6445, CX7330, CX7430, CX7525, CX7530, DC4800, DC4900, + DX3500, DX3600, DX3900, DX4330, DX4530, DX4900, DX6340, DX6440, DX6490, + DX7440, DX7590, DX7630, EasyShare-One, LS420, LS443, LS633, LS743, LS753, + V530, V550, V570, V603, V610, V705, Z650, Z700, Z710, Z730, Z740, Z760 and + Z7590. + }, + WRITABLE => 1, + FIRST_ENTRY => 8, + 0x00 => { + Name => 'KodakModel', + Format => 'string[8]', + }, + 0x09 => { + Name => 'Quality', + PrintConv => { #PH + 1 => 'Fine', + 2 => 'Normal', + }, + }, + 0x0a => { + Name => 'BurstMode', + PrintConv => { 0 => 'Off', 1 => 'On' }, + }, + 0x0c => { + Name => 'KodakImageWidth', + Format => 'int16u', + }, + 0x0e => { + Name => 'KodakImageHeight', + Format => 'int16u', + }, + 0x10 => { + Name => 'YearCreated', + Groups => { 2 => 'Time' }, + Format => 'int16u', + }, + 0x12 => { + Name => 'MonthDayCreated', + Groups => { 2 => 'Time' }, + Format => 'int8u[2]', + ValueConv => 'sprintf("%.2d:%.2d",split(" ", $val))', + ValueConvInv => '$val=~tr/:./ /;$val', + }, + 0x14 => { + Name => 'TimeCreated', + Groups => { 2 => 'Time' }, + Format => 'int8u[4]', + Shift => 'Time', + ValueConv => 'sprintf("%.2d:%.2d:%.2d.%.2d",split(" ", $val))', + ValueConvInv => '$val=~tr/:./ /;$val', + }, + 0x18 => { + Name => 'BurstMode2', + Format => 'int16u', + Unknown => 1, # not sure about this tag (or other 'Unknown' tags) + }, + 0x1b => { + Name => 'ShutterMode', + PrintConv => { #PH + 0 => 'Auto', + 8 => 'Aperture Priority', + 32 => 'Manual?', + }, + }, + 0x1c => { + Name => 'MeteringMode', + PrintConv => { #PH + 0 => 'Multi-segment', + 1 => 'Center-weighted average', + 2 => 'Spot', + }, + }, + 0x1d => 'SequenceNumber', + 0x1e => { + Name => 'FNumber', + Format => 'int16u', + ValueConv => '$val / 100', + ValueConvInv => 'int($val * 100 + 0.5)', + }, + 0x20 => { + Name => 'ExposureTime', + Format => 'int32u', + ValueConv => '$val / 1e5', + ValueConvInv => '$val * 1e5', + PrintConv => 'Image::ExifTool::Exif::PrintExposureTime($val)', + PrintConvInv => 'Image::ExifTool::Exif::ConvertFraction($val)', + }, + 0x24 => { + Name => 'ExposureCompensation', + Format => 'int16s', + ValueConv => '$val / 1000', + ValueConvInv => '$val * 1000', + PrintConv => '$val > 0 ? "+$val" : $val', + PrintConvInv => 'Image::ExifTool::Exif::ConvertFraction($val)', + }, + 0x26 => { + Name => 'VariousModes', + Format => 'int16u', + Unknown => 1, + }, + 0x28 => { + Name => 'Distance1', + Format => 'int32u', + Unknown => 1, + }, + 0x2c => { + Name => 'Distance2', + Format => 'int32u', + Unknown => 1, + }, + 0x30 => { + Name => 'Distance3', + Format => 'int32u', + Unknown => 1, + }, + 0x34 => { + Name => 'Distance4', + Format => 'int32u', + Unknown => 1, + }, + 0x38 => { + Name => 'FocusMode', + PrintConv => { + 0 => 'Normal', + 2 => 'Macro', + }, + }, + 0x3a => { + Name => 'VariousModes2', + Format => 'int16u', + Unknown => 1, + }, + 0x3c => { + Name => 'PanoramaMode', + Format => 'int16u', + Unknown => 1, + }, + 0x3e => { + Name => 'SubjectDistance', + Format => 'int16u', + Unknown => 1, + }, + 0x40 => { + Name => 'WhiteBalance', + Priority => 0, + PrintConv => { #PH + 0 => 'Auto', + 1 => 'Flash?', + 2 => 'Tungsten', + 3 => 'Daylight', + # 5 - seen this for "Auto" with a ProBack 645M + }, + }, + 0x5c => { + Name => 'FlashMode', + Flags => 'PrintHex', + # various models express this number differently + PrintConv => { #PH + 0x00 => 'Auto', + 0x01 => 'Fill Flash', + 0x02 => 'Off', + 0x03 => 'Red-Eye', + 0x10 => 'Fill Flash', + 0x20 => 'Off', + 0x40 => 'Red-Eye?', + }, + }, + 0x5d => { + Name => 'FlashFired', + PrintConv => { 0 => 'No', 1 => 'Yes' }, + }, + 0x5e => { + Name => 'ISOSetting', + Format => 'int16u', + PrintConv => '$val ? $val : "Auto"', + PrintConvInv => '$val=~/^\d+$/ ? $val : 0', + }, + 0x60 => { + Name => 'ISO', + Format => 'int16u', + }, + 0x62 => { + Name => 'TotalZoom', + Format => 'int16u', + ValueConv => '$val / 100', + ValueConvInv => '$val * 100', + }, + 0x64 => { + Name => 'DateTimeStamp', + Format => 'int16u', + PrintConv => '$val ? "Mode $val" : "Off"', + PrintConvInv => '$val=~tr/0-9//dc; $val ? $val : 0', + }, + 0x66 => { + Name => 'ColorMode', + Format => 'int16u', + Flags => 'PrintHex', + # various models express this number differently + PrintConv => { #PH + 0x01 => 'B&W', + 0x02 => 'Sepia', + 0x03 => 'B&W Yellow Filter', + 0x04 => 'B&W Red Filter', + 0x20 => 'Saturated Color', + 0x40 => 'Neutral Color', + 0x100 => 'Saturated Color', + 0x200 => 'Neutral Color', + 0x2000 => 'B&W', + 0x4000 => 'Sepia', + }, + }, + 0x68 => { + Name => 'DigitalZoom', + Format => 'int16u', + ValueConv => '$val / 100', + ValueConvInv => '$val * 100', + }, + 0x6b => { + Name => 'Sharpness', + Format => 'int8s', + %Image::ExifTool::Exif::printParameter, + }, +); + +# Kodak type 2 maker notes (ref PH) +%Image::ExifTool::Kodak::Type2 = ( + GROUPS => { 0 => 'MakerNotes', 2 => 'Camera' }, + PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData, + WRITE_PROC => \&Image::ExifTool::WriteBinaryData, + CHECK_PROC => \&Image::ExifTool::CheckBinaryData, + NOTES => q{ + These tags are used by the Kodak DC220, DC260, DC265 and DC290, + Hewlett-Packard PhotoSmart 618, C500 and C912, Pentax EI-200 and EI-2000, + and Minolta EX1500Z. + }, + WRITABLE => 1, + FIRST_ENTRY => 0, + 0x08 => { + Name => 'KodakMaker', + Format => 'string[32]', + }, + 0x28 => { + Name => 'KodakModel', + Format => 'string[32]', + }, + 0x6c => { + Name => 'KodakImageWidth', + Format => 'int32u', + }, + 0x70 => { + Name => 'KodakImageHeight', + Format => 'int32u', + }, +); + +# Kodak type 3 maker notes (ref PH) +%Image::ExifTool::Kodak::Type3 = ( + GROUPS => { 0 => 'MakerNotes', 2 => 'Camera' }, + PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData, + WRITE_PROC => \&Image::ExifTool::WriteBinaryData, + CHECK_PROC => \&Image::ExifTool::CheckBinaryData, + NOTES => 'These tags are used by the DC240, DC280, DC3400 and DC5000.', + WRITABLE => 1, + FIRST_ENTRY => 0, + 0x0c => { + Name => 'YearCreated', + Groups => { 2 => 'Time' }, + Format => 'int16u', + }, + 0x0e => { + Name => 'MonthDayCreated', + Groups => { 2 => 'Time' }, + Format => 'int8u[2]', + ValueConv => 'sprintf("%.2d:%.2d",split(" ", $val))', + ValueConvInv => '$val=~tr/:./ /;$val', + }, + 0x10 => { + Name => 'TimeCreated', + Groups => { 2 => 'Time' }, + Format => 'int8u[4]', + Shift => 'Time', + ValueConv => 'sprintf("%2d:%.2d:%.2d.%.2d",split(" ", $val))', + ValueConvInv => '$val=~tr/:./ /;$val', + }, + 0x1e => { + Name => 'OpticalZoom', + Format => 'int16u', + ValueConv => '$val / 100', + ValueConvInv => '$val * 100', + }, + 0x37 => { + Name => 'Sharpness', + Format => 'int8s', + %Image::ExifTool::Exif::printParameter, + }, + 0x38 => { + Name => 'ExposureTime', + Format => 'int32u', + ValueConv => '$val / 1e5', + ValueConvInv => '$val * 1e5', + PrintConv => 'Image::ExifTool::Exif::PrintExposureTime($val)', + PrintConvInv => 'Image::ExifTool::Exif::ConvertFraction($val)', + }, + 0x3c => { + Name => 'FNumber', + Format => 'int16u', + ValueConv => '$val / 100', + ValueConvInv => 'int($val * 100 + 0.5)', + }, + 0x4e => { + Name => 'ISO', + Format => 'int16u', + }, +); + +# Kodak type 4 maker notes (ref PH) +%Image::ExifTool::Kodak::Type4 = ( + GROUPS => { 0 => 'MakerNotes', 2 => 'Camera' }, + PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData, + WRITE_PROC => \&Image::ExifTool::WriteBinaryData, + CHECK_PROC => \&Image::ExifTool::CheckBinaryData, + NOTES => 'These tags are used by the DC200 and DC215.', + WRITABLE => 1, + FIRST_ENTRY => 0, + 0x20 => { + Name => 'OriginalFileName', + Format => 'string[12]', + }, +); + +# Kodak type 5 maker notes (ref PH) +%Image::ExifTool::Kodak::Type5 = ( + GROUPS => { 0 => 'MakerNotes', 2 => 'Camera' }, + PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData, + NOTES => q{ + These tags are used by the CX4200, CX4210, CX4230, CX4300, CX4310, CX6200 + and CX6230. + }, + WRITABLE => 1, + FIRST_ENTRY => 0, + 0x14 => { + Name => 'ExposureTime', + Format => 'int32u', + ValueConv => '$val / 1e5', + ValueConvInv => '$val * 1e5', + PrintConv => 'Image::ExifTool::Exif::PrintExposureTime($val)', + PrintConvInv => 'Image::ExifTool::Exif::ConvertFraction($val)', + }, + 0x1a => { + Name => 'WhiteBalance', + PrintConv => { + 1 => 'Daylight', + 2 => 'Flash', + 3 => 'Tungsten', + }, + }, + 0x1c => { + Name => 'FNumber', + Format => 'int16u', + ValueConv => '$val / 100', + ValueConvInv => 'int($val * 100 + 0.5)', + }, + 0x1e => { + Name => 'ISO', + Format => 'int16u', + }, + 0x20 => { + Name => 'OpticalZoom', + Format => 'int16u', + ValueConv => '$val / 100', + ValueConvInv => '$val * 100', + }, + 0x22 => { + Name => 'DigitalZoom', + Format => 'int16u', + ValueConv => '$val / 100', + ValueConvInv => '$val * 100', + }, + 0x27 => { + Name => 'FlashMode', + PrintConv => { + 0 => 'Auto', + 1 => 'On', + 2 => 'Off', + 3 => 'Red-Eye', + }, + }, + 0x2a => { + Name => 'ImageRotated', + PrintConv => { 0 => 'No', 1 => 'Yes' }, + }, + 0x2b => { + Name => 'Macro', + PrintConv => { 0 => 'On', 1 => 'Off' }, + }, +); + +# Kodak type 6 maker notes (ref PH) +%Image::ExifTool::Kodak::Type6 = ( + GROUPS => { 0 => 'MakerNotes', 2 => 'Camera' }, + PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData, + NOTES => 'These tags are used by the DX3215 and DX3700.', + WRITABLE => 1, + FIRST_ENTRY => 0, + 0x10 => { + Name => 'ExposureTime', + Format => 'int32u', + ValueConv => '$val / 1e5', + ValueConvInv => '$val * 1e5', + PrintConv => 'Image::ExifTool::Exif::PrintExposureTime($val)', + PrintConvInv => 'Image::ExifTool::Exif::ConvertFraction($val)', + }, + 0x14 => { + Name => 'ISOSetting', + Format => 'int32u', + Unknown => 1, + }, + 0x18 => { + Name => 'FNumber', + Format => 'int16u', + ValueConv => '$val / 100', + ValueConvInv => 'int($val * 100 + 0.5)', + }, + 0x1a => { + Name => 'ISO', + Format => 'int16u', + }, + 0x1c => { + Name => 'OpticalZoom', + Format => 'int16u', + ValueConv => '$val / 100', + ValueConvInv => '$val * 100', + }, + 0x1e => { + Name => 'DigitalZoom', + Format => 'int16u', + ValueConv => '$val / 100', + ValueConvInv => '$val * 100', + }, + 0x22 => { + Name => 'Flash', + Format => 'int16u', + PrintConv => { + 0 => 'No Flash', + 1 => 'Fired', + }, + }, +); + +# Kodak type 7 maker notes (ref PH) +%Image::ExifTool::Kodak::Type7 = ( + GROUPS => { 0 => 'MakerNotes', 2 => 'Camera' }, + PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData, + WRITE_PROC => \&Image::ExifTool::WriteBinaryData, + CHECK_PROC => \&Image::ExifTool::CheckBinaryData, + WRITABLE => 1, + FIRST_ENTRY => 0, + NOTES => q{ + The maker notes of models such as the C340, C433, CC533, LS755, V803 and + V1003 seem to start with the camera serial number. The C310, C315, C330, + C643, C743, CD33, CD43, CX7220 and CX7300 maker notes are also decoded using + this table, although the strings for these cameras don't conform to the + usual Kodak serial number format, and instead have the model name followed + by 8 digits. + }, + 0 => { # (not confirmed) + Name => 'SerialNumber', + Format => 'string[16]', + ValueConv => '$val=~s/\s+$//; $val', # remove trailing whitespace + ValueConvInv => '$val', + }, +); + +# Kodak IFD-format maker notes (ref PH) +%Image::ExifTool::Kodak::Type8 = ( + WRITE_PROC => \&Image::ExifTool::Exif::WriteExif, + CHECK_PROC => \&Image::ExifTool::Exif::CheckExif, + GROUPS => { 0 => 'MakerNotes', 2 => 'Camera' }, + NOTES => q{ + Kodak models such as the ZD710, P712, P850, P880, V1233, V1253, V1275, + V1285, Z612, Z712, Z812, Z885 use standard TIFF IFD format for the maker + notes. In keeping with Kodak's strategy of inconsistent makernotes, models + such as the M380, M1033, M1093, V1073, V1273, Z1012, Z1085 and Z8612 + also use these tags, but these makernotes begin with a TIFF header instead + of an IFD entry count and use relative instead of absolute offsets. There + is a large amount of information stored in these maker notes (apparently + with much duplication), but relatively few tags have so far been decoded. + }, + 0xfc00 => [{ + Name => 'SubIFD0', + Condition => '$format eq "undef"', + Groups => { 1 => 'MakerNotes' }, # SubIFD needs group 1 set + NestedHtmlDump => 2, # (so HtmlDump doesn't show these as double-referenced) + SubDirectory => { + TagTable => 'Image::ExifTool::Kodak::SubIFD0', + Base => '$start', + ProcessProc => \&ProcessKodakIFD, + WriteProc => \&WriteKodakIFD, + }, + },{ + Name => 'SubIFD0', + Groups => { 1 => 'MakerNotes' }, # SubIFD needs group 1 set + Flags => 'SubIFD', + SubDirectory => { + TagTable => 'Image::ExifTool::Kodak::SubIFD0', + Start => '$val', + # (odd but true: the Base for this SubIFD is different than 0xfc01-0xfc06) + }, + }], + # SubIFD1 and higher data is preceded by a TIFF byte order mark to indicate + # the byte ordering used. Beginning with the M580, these subdirectories are + # stored as 'undef' data rather than as a standard EXIF SubIFD. + 0xfc01 => [{ + Name => 'SubIFD1', + Condition => '$format eq "undef"', + Groups => { 1 => 'MakerNotes' }, # SubIFD needs group 1 set + NestedHtmlDump => 2, + SubDirectory => { + TagTable => 'Image::ExifTool::Kodak::SubIFD1', + Base => '$start', + }, + },{ + Name => 'SubIFD1', + Condition => '$$valPt ne "\0\0\0\0"', # may be zero if dir doesn't exist + Groups => { 1 => 'MakerNotes' }, # SubIFD needs group 1 set + Flags => 'SubIFD', + SubDirectory => { + TagTable => 'Image::ExifTool::Kodak::SubIFD1', + Start => '$val', + Base => '$start', + }, + }], + 0xfc02 => [{ + Name => 'SubIFD2', + Condition => '$format eq "undef"', + Groups => { 1 => 'MakerNotes' }, # SubIFD needs group 1 set + NestedHtmlDump => 2, + SubDirectory => { + TagTable => 'Image::ExifTool::Kodak::SubIFD2', + Base => '$start', + }, + },{ + Name => 'SubIFD2', + Condition => '$$valPt ne "\0\0\0\0"', # may be zero if dir doesn't exist + Groups => { 1 => 'MakerNotes' }, # SubIFD needs group 1 set + Flags => 'SubIFD', + SubDirectory => { + TagTable => 'Image::ExifTool::Kodak::SubIFD2', + Start => '$val', + Base => '$start', + }, + }], + 0xfc03 => [{ + Name => 'SubIFD3', + Condition => '$format eq "undef"', + Groups => { 1 => 'MakerNotes' }, # SubIFD needs group 1 set + NestedHtmlDump => 2, + SubDirectory => { + TagTable => 'Image::ExifTool::Kodak::SubIFD3', + Base => '$start', + }, + },{ + Name => 'SubIFD3', + Condition => '$$valPt ne "\0\0\0\0"', # may be zero if dir doesn't exist + Groups => { 1 => 'MakerNotes' }, # SubIFD needs group 1 set + Flags => 'SubIFD', + SubDirectory => { + TagTable => 'Image::ExifTool::Kodak::SubIFD3', + Start => '$val', + Base => '$start', + }, + }], + # (SubIFD4 has the pointer zeroed in my samples, but support it + # in case it is used by future models -- ignored if pointer is zero) + 0xfc04 => [{ + Name => 'SubIFD4', + Condition => '$format eq "undef"', + Groups => { 1 => 'MakerNotes' }, # SubIFD needs group 1 set + NestedHtmlDump => 2, + SubDirectory => { + TagTable => 'Image::ExifTool::Kodak::SubIFD4', + Base => '$start', + }, + },{ + Name => 'SubIFD4', + Condition => '$$valPt ne "\0\0\0\0"', # may be zero if dir doesn't exist + Groups => { 1 => 'MakerNotes' }, # SubIFD needs group 1 set + Flags => 'SubIFD', + SubDirectory => { + TagTable => 'Image::ExifTool::Kodak::SubIFD4', + Start => '$val', + Base => '$start', + }, + }], + 0xfc05 => [{ + Name => 'SubIFD5', + Condition => '$format eq "undef"', + Groups => { 1 => 'MakerNotes' }, # SubIFD needs group 1 set + NestedHtmlDump => 2, + SubDirectory => { + TagTable => 'Image::ExifTool::Kodak::SubIFD5', + Base => '$start', + }, + },{ + Name => 'SubIFD5', + Condition => '$$valPt ne "\0\0\0\0"', # may be zero if dir doesn't exist + Groups => { 1 => 'MakerNotes' }, # SubIFD needs group 1 set + Flags => 'SubIFD', + SubDirectory => { + TagTable => 'Image::ExifTool::Kodak::SubIFD5', + Start => '$val', + Base => '$start', + }, + }], + 0xfc06 => [{ # new for the M580 + Name => 'SubIFD6', + Condition => '$format eq "undef"', + Groups => { 1 => 'MakerNotes' }, # SubIFD needs group 1 set + NestedHtmlDump => 2, + SubDirectory => { + TagTable => 'Image::ExifTool::Kodak::SubIFD6', + Base => '$start', + }, + },{ + Name => 'SubIFD6', + Condition => '$$valPt ne "\0\0\0\0"', # may be zero if dir doesn't exist + Groups => { 1 => 'MakerNotes' }, # SubIFD needs group 1 set + Flags => 'SubIFD', + SubDirectory => { + TagTable => 'Image::ExifTool::Kodak::SubIFD6', + Start => '$val', + Base => '$start', + }, + }], + 0xfcff => { + Name => 'SubIFD255', + Condition => '$format eq "undef"', + Groups => { 1 => 'MakerNotes' }, # SubIFD needs group 1 set + NestedHtmlDump => 2, + SubDirectory => { + TagTable => 'Image::ExifTool::Kodak::SubIFD0', + # (uses the same Base as the main MakerNote IFD) + }, + }, + 0xff00 => { + Name => 'CameraInfo', + Condition => '$$valPt ne "\0\0\0\0"', # may be zero if dir doesn't exist + Groups => { 1 => 'MakerNotes' }, # SubIFD needs group 1 set + Flags => 'SubIFD', + SubDirectory => { + TagTable => 'Image::ExifTool::Kodak::CameraInfo', + Start => '$val', + # (uses the same Base as the main MakerNote IFD) + }, + }, +); + +# Kodak type 9 maker notes (ref PH) +%Image::ExifTool::Kodak::Type9 = ( + GROUPS => { 0 => 'MakerNotes', 2 => 'Camera' }, + PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData, + WRITE_PROC => \&Image::ExifTool::WriteBinaryData, + CHECK_PROC => \&Image::ExifTool::CheckBinaryData, + WRITABLE => 1, + FIRST_ENTRY => 0, + NOTES => q{ + These tags are used by the Kodak C140, C180, C913, C1013, M320, M340 and + M550, as well as various cameras marketed by other manufacturers. + }, + 0x0c => [ + { + Name => 'FNumber', + Condition => '$$self{Make} =~ /Kodak/i', + Format => 'int16u', + ValueConv => '$val / 100', + ValueConvInv => 'int($val * 100 + 0.5)', + },{ + Name => 'FNumber', + Format => 'int16u', + ValueConv => '$val / 10', + ValueConvInv => 'int($val * 10 + 0.5)', + }, + ], + 0x10 => { + Name => 'ExposureTime', + Format => 'int32u', + ValueConv => '$val / 1e6', + ValueConvInv => '$val * 1e6', + PrintConv => 'Image::ExifTool::Exif::PrintExposureTime($val)', + PrintConvInv => 'Image::ExifTool::Exif::ConvertFraction($val)', + }, + 0x14 => { + Name => 'DateTimeOriginal', + Description => 'Date/Time Original', + Groups => { 2 => 'Time' }, + Format => 'string[20]', + Shift => 'Time', + ValueConv => '$val=~s{/}{:}g; $val', + ValueConvInv => '$val=~s{^(\d{4}):(\d{2}):}{$1/$2/}; $val', + PrintConv => '$self->ConvertDateTime($val)', + PrintConvInv => '$self->InverseDateTime($val,0)', + }, + 0x34 => { + Name => 'ISO', + Format => 'int16u', + }, + 0x57 => { + Name => 'FirmwareVersion', + Condition => '$$self{Make} =~ /Kodak/i', + Format => 'string[16]', + Notes => 'Kodak only', + }, + 0xa8 => { + Name => 'UnknownNumber', # (was SerialNumber, but not unique for all cameras. eg. C1013) + Condition => '$$self{Make} =~ /Kodak/i and $$valPt =~ /^([A-Z0-9]{1,11}\0|[A-Z0-9]{12})/i', + Format => 'string[12]', + Notes => 'Kodak only', + Writable => 0, + }, + 0xc4 => { + Name => 'UnknownNumber', # (confirmed NOT to be serial number for Easyshare Mini - PH) + Condition => '$$self{Make} =~ /Kodak/i and $$valPt =~ /^([A-Z0-9]{1,11}\0|[A-Z0-9]{12})/i', + Format => 'string[12]', + Notes => 'Kodak only', + Writable => 0, + }, +); + +# more Kodak IFD-format maker notes (ref PH) +%Image::ExifTool::Kodak::Type10 = ( + WRITE_PROC => \&Image::ExifTool::Exif::WriteExif, + CHECK_PROC => \&Image::ExifTool::Exif::CheckExif, + GROUPS => { 0 => 'MakerNotes', 2 => 'Camera' }, + PRIORITY => 0, + NOTES => q{ + Another variation of the IFD-format type, this time with just a byte order + indicator instead of a full TIFF header. These tags are used by the Z980. + }, + # 0x01 int16u - always 0 + 0x02 => { + Name => 'PreviewImageSize', + Writable => 'int16u', + Count => 2, + }, + # 0x03 int32u - ranges from about 33940 to 40680 + # 0x04 int32u - always 18493 + # 0x06 undef[4] - 07 d9 04 11 + # 0x07 undef[3] - varies + # 0x08 int16u - 1 (mostly), 2 + # 0x09 int16u - 255 + # 0x0b int16u[2] - '0 0' (mostly), '20 0', '21 0', '1 0' + # 0x0c int16u - 1 (mostly), 3, 259, 260 + # 0x0d int16u - 0 + # 0x0e int16u - 0, 1, 2 (MeteringMode? 0=Partial, 1,2=Multi) + # 0x0f int16u - 0, 5 (MeteringMode? 0=Multi, 5=Partial) + # 0x10 int16u - ranges from about 902 to 2308 + 0x12 => { + Name => 'ExposureTime', + Writable => 'int32u', + ValueConv => '$val / 1e5', + ValueConvInv => '$val * 1e5', + PrintConv => 'Image::ExifTool::Exif::PrintExposureTime($val)', + PrintConvInv => 'Image::ExifTool::Exif::ConvertFraction($val)', + }, + 0x13 => { + Name => 'FNumber', + Writable => 'int16u', + ValueConv => '$val / 10', + ValueConvInv => '$val * 10', + }, + 0x14 => { + Name => 'ISO', + Writable => 'int16u', + ValueConv => 'exp($val/3*log(2))*25', + ValueConvInv => '3*log($val/25)/log(2)', + PrintConv => 'int($val + 0.5)', + PrintConvInv => '$val', + }, + # 0x15 int16u - 18-25 (SceneMode? 21=auto, 24=Aperture Priority, 19=high speed) + # 0x16 int16u - 50 + # 0x17 int16u - 0, 65535 (MeteringMode? 0=Multi, 65535=Partial) + # 0x19 int16u - 0, 4 (WhiteBalance? 0=Auto, 4=Manual) + # 0x1a int16u - 0, 65535 + # 0x1b int16u - 416-696 + # 0x1c int16u - 251-439 (low when 0x1b is high) + 0x1d => { + Name => 'FocalLength', + Writable => 'int32u', + ValueConv => '$val / 100', + ValueConvInv => '$val * 100', + PrintConv => '"$val mm"', + PrintConvInv => '$val=~s/\s*mm//;$val', + }, + # 0x1e int16u - 100 + # 0x1f int16u - 0, 1 + # 0x20,0x21 int16u - 1 + # 0x27 undef[4] - fe ff ff ff + # 0x32 undef[4] - 00 00 00 00 + # 0x61 int32u[2] - '0 0' or '34050 0' + # 0x62 int8u - 0, 1 + # 0x63 int8u - 1 + # 0x64,0x65 int8u - 0, 1, 2 + # 0x66 int32u - 0 + # 0x67 int32u - 3 + # 0x68 int32u - 0 + # 0x3fe undef[2540] +); + +# Kodak PixPro S-1 maker notes (ref PH) +# (similar to Ricoh::Type2 and GE::Main) +%Image::ExifTool::Kodak::Type11 = ( + # (can't currently write these) + GROUPS => { 0 => 'MakerNotes', 2 => 'Camera' }, + NOTES =>q{ + These tags are found in models such as the PixPro S-1. They are not + writable because the inconsistency of Kodak maker notes is beginning to get + on my nerves. + }, + # (these are related to the Kodak QuickTime UserData tags) + 0x0104 => 'FirmwareVersion', + 0x0203 => { + Name => 'PictureEffect', + PrintConv => { + 0 => 'None', + 3 => 'Monochrome', + 9 => 'Kodachrome', + }, + }, + # 0x0204 - ExposureComp or FlashExposureComp maybe? + 0x0207 => 'KodakModel', + 0x0300 => 'KodakMake', + 0x0308 => 'LensSerialNumber', + 0x0309 => 'LensModel', + 0x030d => { Name => 'LevelMeter', Unknown => 1 }, # (guess) + 0x0311 => 'Pitch', # Units?? + 0x0312 => 'Yaw', # Units?? + 0x0313 => 'Roll', # Units?? + 0x0314 => { Name => 'CX', Unknown => 1 }, + 0x0315 => { Name => 'CY', Unknown => 1 }, + 0x0316 => { Name => 'Rads', Unknown => 1 }, +); + +# Kodak SubIFD0 tags (ref PH) +%Image::ExifTool::Kodak::SubIFD0 = ( + WRITE_PROC => \&Image::ExifTool::Exif::WriteExif, + CHECK_PROC => \&Image::ExifTool::Exif::CheckExif, + GROUPS => { 0 => 'MakerNotes', 2 => 'Camera' }, + NOTES => 'SubIFD0 through SubIFD5 tags are written a number of newer Kodak models.', + 0xfa02 => { + Name => 'SceneMode', + Writable => 'int16u', + Notes => 'may not be valid for some models', # eg. M580? + PrintConvColumns => 2, + PrintConv => { + 1 => 'Sport', + 3 => 'Portrait', + 4 => 'Landscape', + 6 => 'Beach', + 7 => 'Night Portrait', + 8 => 'Night Landscape', + 9 => 'Snow', + 10 => 'Text', + 11 => 'Fireworks', + 12 => 'Macro', + 13 => 'Museum', + 16 => 'Children', + 17 => 'Program', + 18 => 'Aperture Priority', + 19 => 'Shutter Priority', + 20 => 'Manual', + 25 => 'Back Light', + 28 => 'Candlelight', + 29 => 'Sunset', + 31 => 'Panorama Left-right', + 32 => 'Panorama Right-left', + 33 => 'Smart Scene', + 34 => 'High ISO', + }, + }, + # 0xfa04 - values: 0 (normally), 2 (panorama shots) + # 0xfa0f - values: 0 (normally), 1 (macro?) + # 0xfa11 - some sort of FNumber (x 100) + 0xfa19 => { + Name => 'SerialNumber', # (verified with Z712 - PH) + Writable => 'string', + }, + 0xfa1d => { + Name => 'KodakImageWidth', + Writable => 'int16u', + }, + 0xfa1e => { + Name => 'KodakImageHeight', + Writable => 'int16u', + }, + 0xfa20 => { + Name => 'SensorWidth', + Writable => 'int16u', + }, + 0xfa21 => { + Name => 'SensorHeight', + Writable => 'int16u', + }, + 0xfa23 => { + Name => 'FNumber', + Writable => 'int16u', + Priority => 0, + ValueConv => '$val / 100', + ValueConvInv => '$val * 100', + }, + 0xfa24 => { + Name => 'ExposureTime', + Writable => 'int32u', + Priority => 0, + ValueConv => '$val / 1e5', + ValueConvInv => '$val * 1e5', + PrintConv => 'Image::ExifTool::Exif::PrintExposureTime($val)', + PrintConvInv => 'Image::ExifTool::Exif::ConvertFraction($val)', + }, + 0xfa2e => { + Name => 'ISO', + Writable => 'int16u', + Priority => 0, + }, + 0xfa3d => { + Name => 'OpticalZoom', + Writable => 'int16u', + ValueConv => '$val / 100', + ValueConvInv => '$val * 100', + PrintConv => 'sprintf("%.2f",$val)', + PrintConvInv => '$val=~s/ ?x//; $val', + }, + 0xfa46 => { + Name => 'ISO', + Writable => 'int16u', + Priority => 0, + }, + # 0xfa4c - related to focal length (1=wide, 32=full zoom) + 0xfa51 => { + Name => 'KodakImageWidth', + Writable => 'int16u', + }, + 0xfa52 => { + Name => 'KodakImageHeight', + Writable => 'int16u', + }, + 0xfa54 => { + Name => 'ThumbnailWidth', + Writable => 'int16u', + }, + 0xfa55 => { + Name => 'ThumbnailHeight', + Writable => 'int16u', + }, + 0xfa57 => { + Name => 'PreviewImageWidth', + Writable => 'int16u', + }, + 0xfa58 => { + Name => 'PreviewImageHeight', + Writable => 'int16u', + }, +); + +# Kodak SubIFD1 tags (ref PH) +%Image::ExifTool::Kodak::SubIFD1 = ( + PROCESS_PROC => \&ProcessKodakIFD, + WRITE_PROC => \&WriteKodakIFD, + CHECK_PROC => \&Image::ExifTool::Exif::CheckExif, + GROUPS => { 0 => 'MakerNotes', 2 => 'Camera' }, + 0x0027 => { + Name => 'ISO', + Writable => 'int16u', + Priority => 0, + }, + 0x0028 => { + Name => 'ISO', + Writable => 'int16u', + Priority => 0, + }, +); + +my %sceneModeUsed = ( + 0 => 'Program', + 2 => 'Aperture Priority', + 3 => 'Shutter Priority', + 4 => 'Manual', + 5 => 'Portrait', + 6 => 'Sport', + 7 => 'Children', + 8 => 'Museum', + 10 => 'High ISO', + 11 => 'Text', + 12 => 'Macro', + 13 => 'Back Light', + 16 => 'Landscape', + 17 => 'Night Landscape', + 18 => 'Night Portrait', + 19 => 'Snow', + 20 => 'Beach', + 21 => 'Fireworks', + 22 => 'Sunset', + 23 => 'Candlelight', + 28 => 'Panorama', +); + +# Kodak SubIFD2 tags (ref PH) +%Image::ExifTool::Kodak::SubIFD2 = ( + PROCESS_PROC => \&ProcessKodakIFD, + WRITE_PROC => \&WriteKodakIFD, + CHECK_PROC => \&Image::ExifTool::Exif::CheckExif, + GROUPS => { 0 => 'MakerNotes', 2 => 'Camera' }, + 0x6002 => { + Name => 'SceneModeUsed', + Writable => 'int32u', + PrintConvColumns => 2, + PrintConv => \%sceneModeUsed, + }, + 0x6006 => { + Name => 'OpticalZoom', + Writable => 'int32u', + ValueConv => '$val / 100', + ValueConvInv => '$val * 100', + PrintConv => 'sprintf("%.2f",$val)', + PrintConvInv => '$val=~s/ ?x//; $val', + }, + # 0x6009 - some sort of FNumber (x 100) + 0x6103 => { + Name => 'MaxAperture', + Writable => 'int32u', + ValueConv => '$val / 100', + ValueConvInv => '$val * 100', + }, + 0xf002 => { + Name => 'SceneModeUsed', + Writable => 'int32u', + PrintConvColumns => 2, + PrintConv => \%sceneModeUsed, + }, + 0xf006 => { + Name => 'OpticalZoom', + Writable => 'int32u', + ValueConv => '$val / 100', + ValueConvInv => '$val * 100', + PrintConv => 'sprintf("%.2f",$val)', + PrintConvInv => '$val=~s/ ?x//; $val', + }, + # 0xf009 - some sort of FNumber (x 100) + 0xf103 => { + Name => 'FNumber', + Writable => 'int32u', + Priority => 0, + ValueConv => '$val / 100', + ValueConvInv => '$val * 100', + }, + 0xf104 => { + Name => 'ExposureTime', + Writable => 'int32u', + Priority => 0, + ValueConv => '$val / 1e6', + ValueConvInv => '$val * 1e6', + PrintConv => 'Image::ExifTool::Exif::PrintExposureTime($val)', + PrintConvInv => 'Image::ExifTool::Exif::ConvertFraction($val)', + }, + 0xf105 => { + Name => 'ISO', + Writable => 'int32u', + Priority => 0, + ValueConv => '$val / 10', + ValueConvInv => '$val * 10', + }, +); + +# Kodak SubIFD3 tags (ref PH) +%Image::ExifTool::Kodak::SubIFD3 = ( + PROCESS_PROC => \&ProcessKodakIFD, + WRITE_PROC => \&WriteKodakIFD, + CHECK_PROC => \&Image::ExifTool::Exif::CheckExif, + GROUPS => { 0 => 'MakerNotes', 2 => 'Camera' }, + 0x1000 => { + Name => 'OpticalZoom', + Writable => 'int16u', + ValueConv => '$val / 100', + ValueConvInv => '$val * 100', + PrintConv => 'sprintf("%.2f",$val)', + PrintConvInv => '$val=~s/ ?x//; $val', + }, + # 0x1002 - related to focal length (1=wide, 32=full zoom) + # 0x1006 - pictures remaining? (gradually decreases as pictures are taken) +# +# the following unknown Kodak tags in subIFD3 may store an IFD count of 0 or 1 instead +# of the correct value (which changes from model to model). This bad count is fixed +# with the "FixCount" patch. Models known to have this problem include: +# M380, M1033, M1093IS, V1073, V1233, V1253, V1273, V1275, V1285, Z612, Z712, +# Z812, Z885, Z915, Z950, Z1012IS, Z1085IS, ZD710 +# + 0x2007 => { + Name => 'Kodak_SubIFD3_0x2007', + Flags => [ 'FixCount', 'Unknown', 'Hidden' ], + }, + 0x2008 => { + Name => 'Kodak_SubIFD3_0x2008', + Flags => [ 'FixCount', 'Unknown', 'Hidden' ], + }, + 0x2009 => { + Name => 'Kodak_SubIFD3_0x2009', + Flags => [ 'FixCount', 'Unknown', 'Hidden' ], + }, + 0x200a => { + Name => 'Kodak_SubIFD3_0x200a', + Flags => [ 'FixCount', 'Unknown', 'Hidden' ], + }, + 0x200b => { + Name => 'Kodak_SubIFD3_0x200b', + Flags => [ 'FixCount', 'Unknown', 'Hidden' ], + }, + 0x3020 => { + Name => 'Kodak_SubIFD3_0x3020', + Flags => [ 'FixCount', 'Unknown', 'Hidden' ], + }, + 0x3030 => { + Name => 'Kodak_SubIFD3_0x3030', + Flags => [ 'FixCount', 'Unknown', 'Hidden' ], + }, + 0x3040 => { + Name => 'Kodak_SubIFD3_0x3040', + Flags => [ 'FixCount', 'Unknown', 'Hidden' ], + }, + 0x3050 => { + Name => 'Kodak_SubIFD3_0x3050', + Flags => [ 'FixCount', 'Unknown', 'Hidden' ], + }, + 0x3060 => { + Name => 'Kodak_SubIFD3_0x3060', + Flags => [ 'FixCount', 'Unknown', 'Hidden' ], + }, + 0x8001 => { + Name => 'Kodak_SubIFD3_0x8001', + Flags => [ 'FixCount', 'Unknown', 'Hidden' ], + }, + 0x8002 => { + Name => 'Kodak_SubIFD3_0x8002', + Flags => [ 'FixCount', 'Unknown', 'Hidden' ], + }, + 0x8003 => { + Name => 'Kodak_SubIFD3_0x8003', + Flags => [ 'FixCount', 'Unknown', 'Hidden' ], + }, + 0x8004 => { + Name => 'Kodak_SubIFD3_0x8004', + Flags => [ 'FixCount', 'Unknown', 'Hidden' ], + }, + 0x8005 => { + Name => 'Kodak_SubIFD3_0x8005', + Flags => [ 'FixCount', 'Unknown', 'Hidden' ], + }, + 0x8006 => { + Name => 'Kodak_SubIFD3_0x8006', + Flags => [ 'FixCount', 'Unknown', 'Hidden' ], + }, + 0x8007 => { + Name => 'Kodak_SubIFD3_0x8007', + Flags => [ 'FixCount', 'Unknown', 'Hidden' ], + }, + 0x8008 => { + Name => 'Kodak_SubIFD3_0x8008', + Flags => [ 'FixCount', 'Unknown', 'Hidden' ], + }, + 0x8009 => { + Name => 'Kodak_SubIFD3_0x8009', + Flags => [ 'FixCount', 'Unknown', 'Hidden' ], + }, + 0x800a => { + Name => 'Kodak_SubIFD3_0x800a', + Flags => [ 'FixCount', 'Unknown', 'Hidden' ], + }, + 0x800b => { + Name => 'Kodak_SubIFD3_0x800b', + Flags => [ 'FixCount', 'Unknown', 'Hidden' ], + }, + 0x800c => { + Name => 'Kodak_SubIFD3_0x800c', + Flags => [ 'FixCount', 'Unknown', 'Hidden' ], + }, +); + +# Kodak SubIFD4 tags (ref PH) +%Image::ExifTool::Kodak::SubIFD4 = ( + PROCESS_PROC => \&ProcessKodakIFD, + WRITE_PROC => \&WriteKodakIFD, + CHECK_PROC => \&Image::ExifTool::Exif::CheckExif, + GROUPS => { 0 => 'MakerNotes', 2 => 'Camera' }, +); + +# Kodak SubIFD5 tags (ref PH) +%Image::ExifTool::Kodak::SubIFD5 = ( + PROCESS_PROC => \&ProcessKodakIFD, + WRITE_PROC => \&WriteKodakIFD, + CHECK_PROC => \&Image::ExifTool::Exif::CheckExif, + GROUPS => { 0 => 'MakerNotes', 2 => 'Camera' }, + 0x000f => { + Name => 'OpticalZoom', + Writable => 'int16u', + ValueConv => '$val / 100', + ValueConvInv => '$val * 100', + PrintConv => 'sprintf("%.2f",$val)', + PrintConvInv => '$val=~s/ ?x//; $val', + }, +); + +# Kodak SubIFD6 tags (ref PH) +%Image::ExifTool::Kodak::SubIFD6 = ( + PROCESS_PROC => \&ProcessKodakIFD, + WRITE_PROC => \&WriteKodakIFD, + CHECK_PROC => \&Image::ExifTool::Exif::CheckExif, + GROUPS => { 0 => 'MakerNotes', 2 => 'Camera' }, + NOTES => 'SubIFD6 is written by the M580.', +); + +# Decoded from P712, P850 and P880 samples (ref PH) +%Image::ExifTool::Kodak::CameraInfo = ( + WRITE_PROC => \&Image::ExifTool::Exif::WriteExif, + CHECK_PROC => \&Image::ExifTool::Exif::CheckExif, + GROUPS => { 0 => 'MakerNotes', 2 => 'Camera' }, + NOTES => 'These tags are used by the P712, P850 and P880.', + 0xf900 => { + Name => 'SensorWidth', + Writable => 'int16u', + Notes => 'effective sensor size', + }, + 0xf901 => { + Name => 'SensorHeight', + Writable => 'int16u', + }, + 0xf902 => { + Name => 'BayerPattern', + Writable => 'string', + }, + 0xf903 => { + Name => 'SensorFullWidth', + Writable => 'int16u', + Notes => 'includes black border?', + }, + 0xf904 => { + Name => 'SensorFullHeight', + Writable => 'int16u', + }, + 0xf907 => { + Name => 'KodakImageWidth', + Writable => 'int16u', + }, + 0xf908 => { + Name => 'KodakImageHeight', + Writable => 'int16u', + }, + 0xfa00 => { + Name => 'KodakInfoType', + Writable => 'string', + }, + 0xfa04 => { + Name => 'SerialNumber', # (unverified) + Writable => 'string', + }, + 0xfd04 => { + Name => 'FNumber', + Writable => 'int16u', + Priority => 0, + ValueConv => '$val / 100', + ValueConvInv => '$val * 100', + }, + 0xfd05 => { + Name => 'ExposureTime', + Writable => 'int32u', + Priority => 0, + ValueConv => '$val / 1e6', + ValueConvInv => '$val * 1e6', + PrintConv => 'Image::ExifTool::Exif::PrintExposureTime($val)', + PrintConvInv => 'Image::ExifTool::Exif::ConvertFraction($val)', + }, + 0xfd06 => { + Name => 'ISO', + Writable => 'int16u', + Priority => 0, + }, +); + +# treat unknown maker notes as binary data (allows viewing with -U) +%Image::ExifTool::Kodak::Unknown = ( + GROUPS => { 0 => 'MakerNotes', 2 => 'Camera' }, + PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData, + FIRST_ENTRY => 0, +); + +# tags found in the KodakIFD (in IFD0 of KDC, DCR, TIFF and JPEG images) (ref PH) +%Image::ExifTool::Kodak::IFD = ( + GROUPS => { 0 => 'MakerNotes', 1 => 'KodakIFD', 2 => 'Image'}, + WRITE_PROC => \&Image::ExifTool::Exif::WriteExif, + CHECK_PROC => \&Image::ExifTool::Exif::CheckExif, + WRITE_GROUP => 'KodakIFD', + SET_GROUP1 => 1, + NOTES => q{ + These tags are found in a separate IFD of JPEG, TIFF, DCR and KDC images + from some older Kodak models such as the DC50, DC120, DCS760C, DCS Pro 14N, + 14nx, SLR/n, Pro Back and Canon EOS D2000. + }, + # 0x0000: int8u[4] - values: "1 0 0 0" (DC50), "1 1 0 0" (DC120) + 0x0000 => { #4 + Name => 'KodakVersion', + Writable => 'int8u', + Count => 4, + PrintConv => '$val =~ tr/ /./; $val', + PrintConvInv => '$val =~ tr/./ /; $val', + }, + 0x0001 => { + # (related to EV but exact meaning unknown) + Name => 'UnknownEV', # ("DeletedTag", ref 4) + Writable => 'rational64u', + Unknown => 1, + }, + # 0x0002: int8u - values: 0 + 0x0003 => { Name => 'ExposureValue', Writable => 'rational64u' }, + # 0x0004: rational64u - values: 2.875,3.375,3.625,4,4.125,7.25 + # 0x0005: int8u - values: 0 + # 0x0006: int32u[12] - ? + # 0x0007: int32u[3] - values: "65536 67932 69256" + 0x03e9 => { Name => 'OriginalFileName', Writable => 'string' }, + 0x03ea => { Name => 'KodakTag', Writable => 'int32u' }, #4 + 0x03eb => { Name => 'SensorLeftBorder', Writable => 'int16u' }, # ("FinishedImageX", ref 4) + 0x03ec => { Name => 'SensorTopBorder', Writable => 'int16u' }, # ("FinishedImageY", ref 4) + 0x03ed => { Name => 'SensorImageWidth', Writable => 'int16u' }, # ("FinishedImageWidth", ref 4) + 0x03ee => { Name => 'SensorImageHeight',Writable => 'int16u' }, # ("FinishedImageHeight", ref 4) + 0x03ef => { Name => 'BlackLevelTop', Writable => 'int16u' }, #4 + 0x03f0 => { Name => 'BlackLevelBottom', Writable => 'int16u' }, #4 + 0x03f1 => { + Name => 'TextualInfo', # ("CameraSettingString", ref 4) + SubDirectory => { + TagTable => 'Image::ExifTool::Kodak::TextualInfo', + }, + }, + 0x03f2 => { #IB/4 + Name => 'FlashMode', + Writable => 'int16u', + Unknown => 1, + Priority => 0, + }, + 0x03f3 => { #IB/4 + Name => 'FlashCompensation', + Writable => 'rational64s', + }, + 0x03f4 => { #4 + Name => 'WindMode', + Writable => 'int16u', + Unknown => 1, + }, + 0x03f5 => { #4 + Name => 'FocusMode', + Writable => 'int16u', + Unknown => 1, + Priority => 0, + }, + 0x03f8 => { #IB/4 + Name => 'MinAperture', + Writable => 'rational64u', + }, + 0x03f9 => { #IB/4 + Name => 'MaxAperture', + Writable => 'rational64u', + }, + 0x03fa => { #4 + Name => 'WhiteBalanceMode', + Writable => 'int16u', + Unknown => 1, + }, + 0x03fb => { #4 + Name => 'WhiteBalanceDetected', + Writable => 'int16u', + Unknown => 1, + }, + 0x03fc => { #3 + Name => 'WhiteBalance', + Writable => 'int16u', + Priority => 0, + PrintConv => { }, # no values yet known + }, + 0x03fd => [{ #3 + Name => 'Processing', + Condition => '$count == 72', + SubDirectory => { + TagTable => 'Image::ExifTool::Kodak::Processing', + }, + },{ + Name => 'ProcessingParameters', #4 + Binary => 1, + # int8u[256] + }], + 0x03fe => { Name => 'ImageAbsoluteX', Writable => 'int16s', }, #4 + 0x03ff => { Name => 'ImageAbsoluteY', Writable => 'int16s' }, #4 + 0x0400 => { Name => 'ApplicationKeyString', Writable => 'string' }, #4 + 0x0401 => { + Name => 'Time', # ("CaptureTime", ref 4) + Groups => { 2 => 'Time' }, + Writable => 'string', + }, + 0x0402 => { #4 + Name => 'GPSString', + Groups => { 2 => 'Location' }, + Writable => 'string', + }, + 0x0403 => { #4 + Name => 'EventLogCapture', + Binary => 1, + Unknown => 1, + # int32u[3072] + }, + 0x0404 => { #4 + Name => 'ComponentTable', + Binary => 1, + Unknown => 1, + }, + 0x0405 => { #4 + Name => 'CustomIlluminant', + Writable => 'int16u', + Unknown => 1, + }, + 0x0406 => [{ #IB/4 + Name => 'CameraTemperature', + Condition => '$count == 1', + Groups => { 2 => 'Camera' }, + Writable => 'rational64s', + PrintConv => '"$val C"', + PrintConvInv => '$val=~s/ ?C//; $val', + },{ + Name => 'CameraTemperature', + # (when count is 2, values seem related to temperature, but are not Celius) + }], + 0x0407 => { #IB/4 + Name => 'AdapterVoltage', + Groups => { 2 => 'Camera' }, + Writable => 'rational64u', + }, + 0x0408 => { #IB/4 + Name => 'BatteryVoltage', + Groups => { 2 => 'Camera' }, + Writable => 'rational64u', + }, + 0x0409 => { #4 + Name => 'DacVoltages', + # rational64u[8] + }, + 0x040a => { #4 + Name => 'IlluminantDetectorData', + Binary => 1, + Unknown => 1, + }, + 0x040b => { #4 + Name => 'PixelClockFrequency', + Writable => 'int32u', + }, + 0x040c => { #4 + Name => 'CenterPixel', + Writable => 'int16u', + Count => 3, + }, + 0x040d => { #4 + Name => 'BurstCount', + Writable => 'int16u', + }, + 0x040e => { #4 + Name => 'BlackLevelRough', + Writable => 'int16u', + }, + 0x040f => { #4 + Name => 'OffsetMapHorizontal', + Binary => 1, + Unknown => 1, + # int16s[1736] + }, + 0x0410 => { #4 + Name => 'OffsetMapVertical', + Binary => 1, + Unknown => 1, + # int16s[1160] + }, + 0x0411 => { #4 + Name => 'Histogram', + Binary => 1, + Unknown => 1, + # int16u[256] + }, + 0x0412 => { #4 + Name => 'VerticalClockOverlaps', + Writable => 'int16u', + Count => 2, + }, + 0x0413 => 'SensorTemperature', #4 + 0x0414 => { Name => 'XilinxVersion', Writable => 'string' }, #4 + 0x0415 => { Name => 'FirmwareVersion', Writable => 'int32u' }, #4 + 0x0416 => { Name => 'BlackLevelRoughAfter', Writable => 'int16u' }, #4 + 0x0417 => 'BrightRowsTop', #4 + 0x0418 => 'EventLogProcess', #4 + 0x0419 => 'DacVoltagesFlush', #4 + 0x041a => 'FlashUsed', #4 + 0x041b => 'FlashType', #4 + 0x041c => 'SelfTimer', #4 + 0x041d => 'AFMode', #4 + 0x041e => 'LensType', #4 + 0x041f => { Name => 'ImageCropX', Writable => 'int16s' }, #4 + 0x0420 => { Name => 'ImageCropY', Writable => 'int16s' }, #4 + 0x0421 => 'AdjustedTbnImageWidth', #4 + 0x0422 => 'AdjustedTbnImageHeight', #4 + 0x0423 => { Name => 'IntegrationTime', Writable => 'int32u' }, #4 + 0x0424 => 'BracketingMode', #4 + 0x0425 => 'BracketingStep', #4 + 0x0426 => 'BracketingCounter', #4 + 0x042e => 'HuffmanTableLength', #4 (int8u[16]) + 0x042f => 'HuffmanTableValue', #4 (int8u[13]) + 0x0438 => { Name => 'MainBoardVersion', Writable => 'int32u' }, #4 + 0x0439 => { Name => 'ImagerBoardVersion', Writable => 'int32u' }, #4 + 0x044c => 'FocusEdgeMap', #4 + 0x05e6 => 'IdleTiming', #4 + 0x05e7 => 'FlushTiming', #4 + 0x05e8 => 'IntegrateTiming', #4 + 0x05e9 => 'RegisterReadTiming', #4 + 0x05ea => 'FirstLineTransferTiming', #4 + 0x05eb => 'ShiftTiming', #4 + 0x05ec => 'NormalLineTransferTiming', #4 + 0x05ed => 'TestTransferTiming', #4 + # 0x05f0-0x05f9 "TestTiming", ref 4 + 0x05fa => 'MinimumFlushRows', #4 + 0x05fd => { Name => 'ImagerPowerOnDelayMsec', Writable => 'int32u' }, #4 + 0x05fe => 'ImagerInitialTimingCode', #4 + 0x05ff => 'ImagerLogicProgram', #4 + 0x0600 => { Name => 'ImagerBiasSettlingDelayMsec', Writable => 'int32u' }, #4 + 0x0604 => 'IdleSequence', #4 + 0x0605 => 'FirstFlushSequence', #4 + 0x0606 => 'FinalFlushSequence', #4 + 0x0607 => 'SampleBlackSequence', #4 + 0x0608 => 'TransferSequence', #4 + 0x060e => 'DacCountsPerVolt', #4 + 0x060f => 'BlackDacChannel', #4 + 0x0610 => 'BlackAdCountsPerDacVolt', #4 + 0x0611 => 'BlackTarget', #4 + 0x0612 => 'BlackDacSettlingMsec', #4 + # 0x0618-0x062b - reserved for .IF file use, ref 4 + 0x07d0 => { #4 + Name => 'StandardMatrixDaylight', + Writable => 'rational64s', + Count => 9, + }, + 0x07d1 => { #4 + Name => 'StandardMatrixTungsten', + Writable => 'rational64s', + Count => 9, + }, + 0x07d2 => { #4 + Name => 'StandardMatrixFluorescent', + Writable => 'rational64s', + Count => 9, + }, + 0x07d3 => { #4 + Name => 'StandardMatrixFlash', + Writable => 'rational64s', + Count => 9, + }, + 0x07d4 => { #4 (never used) + Name => 'StandardMatrixCustom', + Writable => 'rational64s', + Count => 9, + }, + 0x07da => { #4 + Name => 'DeviantMatrixDaylight', + Writable => 'rational64s', + Count => 9, + }, + 0x07db => { #4 + Name => 'DeviantMatrixTungsten', + Writable => 'rational64s', + Count => 9, + }, + 0x07dc => { #4 + Name => 'DeviantMatrixFluorescent', + Writable => 'rational64s', + Count => 9, + }, + 0x07dd => { #4 + Name => 'DeviantMatrixFlash', + Writable => 'rational64s', + Count => 9, + }, + 0x07de => { #4 (never used) + Name => 'DeviantMatrixCustom', + Writable => 'rational64s', + Count => 9, + }, + 0x07e4 => { #4 + Name => 'UniqueMatrixDaylight', + Writable => 'rational64s', + Count => 9, + }, + 0x07e5 => { #4 + Name => 'UniqueMatrixTungsten', + Writable => 'rational64s', + Count => 9, + }, + 0x07e6 => { #4 + Name => 'UniqueMatrixFluorescent', + Writable => 'rational64s', + Count => 9, + }, + 0x07e7 => { #4 + Name => 'UniqueMatrixFlash', + Writable => 'rational64s', + Count => 9, + }, + 0x07e8 => { #4 + Name => 'UniqueMatrixCustom', + Writable => 'rational64s', + Count => 9, + }, + 0x07e9 => { #4 + Name => 'UniqueMatrixAuto', + Writable => 'rational64s', + Count => 9, + }, + 0x0834 => { #4 + Name => 'StandardWhiteDaylight', + Writable => 'rational64s', + Count => 3, + }, + 0x0835 => { #4 + Name => 'StandardWhiteTungsten', + Writable => 'rational64s', + Count => 3, + }, + 0x0836 => { #4 + Name => 'StandardWhiteFluorescent', + Writable => 'rational64s', + Count => 3, + }, + 0x0837 => { #4 + Name => 'StandardWhiteFlash', + Writable => 'rational64s', + Count => 3, + }, + 0x0838 => { #4 (never used) + Name => 'StandardWhiteCustom', + Writable => 'rational64s', + Count => 3, + }, + 0x083e => { #4 + Name => 'DeviantWhiteDaylight', + Writable => 'rational64s', + Count => 3, + }, + 0x083f => { #4 + Name => 'DeviantWhiteTungsten', + Writable => 'rational64s', + Count => 3, + }, + 0x0840 => { #4 + Name => 'DeviantWhiteFluorescent', + Writable => 'rational64s', + Count => 3, + }, + 0x0841 => { #4 + Name => 'DeviantWhiteFlash', + Writable => 'rational64s', + Count => 3, + }, + 0x0842 => { #4 (never used) + Name => 'DeviantWhiteCustom', + Writable => 'rational64s', + Count => 3, + }, + # 0x0843 - rational64u[3] + # 0x0844 - rational64u[3] + 0x0846 => { #3 ("WhiteBalanceKelvin", ref 4) + Name => 'ColorTemperature', + Writable => 'int16u', + }, + 0x0847 => 'WB_RGBLevelsAsShot', #4 + 0x0848 => 'WB_RGBLevelsDaylight', #IB (rational64s/u[3]) ("UniqueWhiteDaylight", ref 4) + 0x0849 => 'WB_RGBLevelsTungsten', #IB (rational64s/u[3]) ("UniqueWhiteTungsten", ref 4) + 0x084a => 'WB_RGBLevelsFluorescent', #IB (rational64s/u[3]) ("UniqueWhiteFluorescent", ref 4) + 0x084b => 'WB_RGBLevelsFlash', #IB (rational64s/u[3]) ("UniqueWhiteFlash", ref 4) + 0x084c => 'WB_RGBLevelsCustom', #IB (rational64u[3]) ("UniqueWhiteCustom", ref 4) + 0x084d => 'WB_RGBLevelsAuto', #IB (rational64u[3]) ("UniqueWhiteAuto", ref 4) + 0x0852 => { #3/4 + Name => 'WB_RGBMulDaylight', # ("AdjustWhiteFactorsDaylight", ref 4) + Writable => 'rational64u', + Count => 3, + }, + 0x0853 => { #3/4 + Name => 'WB_RGBMulTungsten', # ("AdjustWhiteFactorsTungsten", ref 4) + Writable => 'rational64u', + Count => 3, + }, + 0x0854 => { #3/4 + Name => 'WB_RGBMulFluorescent', # ("AdjustWhiteFactorsFluorescent", ref 4) + Writable => 'rational64u', + Count => 3, + }, + 0x0855 => { #3/4 + Name => 'WB_RGBMulFlash', # ("AdjustWhiteFactorsFlash", ref 4) + Writable => 'rational64u', + Count => 3, + }, + 0x085c => { Name => 'WB_RGBCoeffsDaylight', Binary => 1 }, #3 ("WhiteBalanceParametersDaylight", ref 4) + 0x085d => { Name => 'WB_RGBCoeffsTungsten', Binary => 1 }, #3 ("WhiteBalanceParametersTungsten", ref 4) + 0x085e => { Name => 'WB_RGBCoeffsFluorescent',Binary=>1 }, #3 ("WhiteBalanceParametersFluorescent", ref 4) + 0x085f => { Name => 'WB_RGBCoeffsFlash', Binary => 1 }, #3 ("WhiteBalanceParametersFlash", ref 4) + 0x0898 => { Name => 'ExposureGainDaylight', Writable => 'rational64s' }, #4 + 0x0899 => { Name => 'ExposureGainTungsten', Writable => 'rational64s' }, #4 + 0x089a => { Name => 'ExposureGainFluorescent',Writable=>'rational64s' }, #4 + 0x089b => { Name => 'ExposureGainFlash', Writable => 'rational64s' }, #4 + 0x089c => { Name => 'ExposureGainCustom', Writable => 'rational64s' }, #4 (never used) + 0x089d => { Name => 'AnalogISOTable', Writable => 'rational64u', Count => 3 }, #4 + 0x089e => { Name => 'AnalogCaptureISO', Writable => 'int32u' }, #4 + 0x089f => { Name => 'ISOCalibrationGain', Writable => 'rational64u' }, #4 + 0x08a0 => 'ISOCalibrationGainTable', #4 + 0x08a1 => 'ExposureHeadroomFactor', #4 + 0x08ab => 'LinearitySplineTags', #4 (int16u[24]) + # 0x08ac-0x08fb - LinearitySpline(n) (rational64s[75]) + 0x08fc => { #4 + Name => 'MonitorMatrix', + Writable => 'rational64s', + Count => 9, + }, + 0x08fd => 'TonScaleTable', #4 + 0x08fe => { Name => 'Gamma', Writable => 'rational64u' }, #4 + 0x08ff => 'LogLinTable', #4 + 0x0900 => 'LinLogTable', #4 + 0x0901 => { Name => 'GammaTable', Binary => 1 }, #4 (int16u[4096]) + 0x0902 => { Name => 'LogScale', Writable => 'rational64u' }, #4 + 0x0903 => { Name => 'BaseISO', Writable => 'rational64u' }, #IB (ISO before digital gain) + 0x0904 => { Name => 'LinLogCoring', Writable => 'int16u' }, #4 + 0x0905 => { Name => 'PatternGainConversionTable', Binary => 1 }, #4 (int8u[256]) + 0x0906 => 'DefectCount', #4 + 0x0907 => { Name => 'DefectList', Binary => 1 }, #4 (undef[48]) + 0x0908 => { Name => 'DefectListPacked', Binary => 1 }, #4 (int16u[296]) + 0x0909 => { Name => 'ImageSpace', Writable => 'int16u' }, #4 + 0x090a => { Name => 'ThumbnailCompressionTable',Binary => 1 }, #4 (int8u[4096]) + 0x090b => { Name => 'ThumbnailExpansionTable', Binary => 1 }, #4 (int16u[256]) + 0x090c => { Name => 'ImageCompressionTable', Binary => 1 }, #4 (int16u[4096]) + 0x090d => { Name => 'ImageExpansionTable', Binary => 1 }, #4 (int16u[1024/4096]) + 0x090e => 'EighteenPercentPoint', #4 + 0x090f => { Name => 'DefectIsoCode', Writable => 'int16u' }, #4 + 0x0910 => { Name => 'BaseISODaylight', Writable => 'rational64u' }, #4 + 0x0911 => { Name => 'BaseISOTungsten', Writable => 'rational64u' }, #4 + 0x0912 => { Name => 'BaseISOFluorescent', Writable => 'rational64u' }, #4 + 0x0913 => { Name => 'BaseISOFlash', Writable => 'rational64u' }, #4 + 0x091a => { Name => 'MatrixSelectThreshold',Writable => 'int16s' }, #4 + 0x091b => { Name => 'MatrixSelectK', Writable => 'rational64u' }, #4 + 0x091c => { Name => 'IlluminantDetectTable',Binary => 1 }, #4 (int16u[200]) + 0x091d => 'RGTable', #4 + 0x091e => { Name => 'MatrixSelectThreshold1', Writable => 'int16s' }, #4 + 0x091f => { Name => 'MatrixSelectThreshold2', Writable => 'int16s' }, #4 + 0x0924 => 'PortraitMatrix', #4 + 0x0925 => 'PortraitToneScaleTable', #4 + 0x092e => { Name => 'EnableSharpening', Writable => 'int16u' }, #4 + 0x092f => { #4 + Name => 'SharpeningKernel', + Writable => 'int16s', + Count => 25, + }, + 0x0930 => { Name => 'EdgeMapSlope', Writable => 'int16u' }, #4 + 0x0931 => { Name => 'EdgeMapX1', Writable => 'int16u' }, #4 + 0x0932 => { Name => 'EdgeMapX2', Writable => 'int16u' }, #4 + 0x0933 => { #4 + Name => 'KernelDenominators', + Writable => 'int16u', + Count => 3, + }, + 0x0934 => { Name => 'EdgeMapX3', Writable => 'int16u' }, #4 + 0x0935 => { Name => 'EdgeMapX4', Writable => 'int16u' }, #4 + 0x0936 => 'SharpenForThumbnail', #4 + 0x0937 => 'EdgeSpline', #4 + 0x0938 => 'DownSampleBy2Hor', #4 (int16s[4]) + 0x0939 => 'DownSampleBy2Ver', #4 (int16s[4]) + 0x093a => 'DownSampleBy4Hor', #4 (int16s[6]) + 0x093b => 'DownSampleBy4Ver', #4 (int16s[6]) + 0x093c => 'DownSampleBy3Hor', #4 (int16s[6]) + 0x093d => 'DownSampleBy3Ver', #4 (int16s[6]) + 0x093e => 'DownSampleBy6Hor', #4 (int16s[8]) + 0x093f => 'DownSampleBy6Ver', #4 (int16s[8]) + 0x0940 => 'DownSampleBy2Hor3MPdcr', #4 + 0x0941 => 'DownSampleBy2Ver3MPdcr', #4 + 0x0942 => 'ThumbnailResizeRatio', #4 + 0x0943 => { Name => 'AtCaptureUserCrop', Writable => 'int32u', Count => 4 }, #4 (Top, Left, Bottom, Right) + 0x0944 => { Name => 'ImageResolution', Writable => 'int32u' }, #4 (Contains enum for imageDcrRes or imageJpegRes) + 0x0945 => { Name => 'ImageResolutionJpg', Writable => 'int32u' }, #4 (Contains enum for imageJpegRes) + 0x094c => 'USMParametersLow', #4 (int16s[8]) + 0x094d => 'USMParametersMed', #4 (int16s[8]) + 0x094e => 'USMParametersHigh', #4 (int16s[8]) + 0x094f => 'USMParametersHost', #4 (int16s[10]) + 0x0950 => { Name => 'EdgeSplineLow', Binary => 1 }, #4 (rational64s[57]) + 0x0951 => { Name => 'EdgeSplineMed', Binary => 1 }, #4 (rational64s[69]) + 0x0952 => { Name => 'EdgeSplineHigh',Binary => 1 }, #4 (rational64s[69]) + 0x0953 => 'USMParametersHost6MP', #4 (int16s[10]) + 0x0954 => 'USMParametersHost3MP', #4 (int16s[10]) + 0x0960 => { Name => 'PatternImagerWidth', Writable => 'int16u' }, #4 + 0x0961 => { Name => 'PatternImagerHeight', Writable => 'int16u' }, #4 + 0x0962 => { Name => 'PatternAreaWidth', Writable => 'int16u' }, #4 + 0x0963 => { Name => 'PatternAreaHeight', Writable => 'int16u' }, #4 + 0x0964 => { Name => 'PatternCorrectionGains', Binary => 1 }, #4 (undef[48174]) + 0x0965 => 'PatternCorrectionOffsets', #4 + 0x0966 => { Name => 'PatternX', Writable => 'int16u' }, #4 + 0x0967 => { Name => 'PatternY', Writable => 'int16u' }, #4 + 0x0968 => { Name => 'PatternCorrectionFactors', Binary => 1 }, #4 (undef[48174]) + 0x0969 => { Name => 'PatternCorrectionFactorScale', Writable => 'int16u' }, #4 + 0x096a => { Name => 'PatternCropRows1', Writable => 'int16u' }, #4 + 0x096b => { Name => 'PatternCropRows2', Writable => 'int16u' }, #4 + 0x096c => { Name => 'PatternCropCols1', Writable => 'int16u' }, #4 + 0x096d => { Name => 'PatternCropCols2', Writable => 'int16u' }, #4 + 0x096e => 'PixelCorrectionGains', #4 + 0x096f => 'StitchRows', #4 (int16u[6]) + 0x0970 => 'StitchColumns', #4 (int16u) + 0x0971 => { Name => 'PixelCorrectionScale', Writable => 'int16u' }, #4 + 0x0972 => { Name => 'PixelCorrectionOffset',Writable => 'int16u' }, #4 + 0x0988 => 'LensTableIndex', #4 + 0x0992 => 'DiffTileGains602832', #4 + 0x0993 => 'DiffTileGains24t852822', #4 (reserved tags 2450-2459) + 0x099c => 'TileGainDeterminationTable', #4 (int16s[0]) + 0x099d => 'NemoBlurKernel', #4 (int16s[14]) + 0x099e => 'NemoTileSize', #4 (int16u) + 0x099f => 'NemoGainFactors', #4 (rational64s[4]) + 0x09a0 => 'NemoDarkLimit', #4 (int16u) + 0x09a1 => 'NemoHighlight12Limit', #4 + 0x09c4 => { Name => 'ImagerFileProductionLevel',Writable => 'int16u' }, #4 + 0x09c5 => { Name => 'ImagerFileDateCreated', Writable => 'int32u' }, #4 (unknown encoding - PH) + 0x09c6 => { Name => 'CalibrationVersion', Writable => 'string' }, #4 + 0x09c7 => { Name => 'ImagerFileTagsVersionStandard', Writable => 'int16u' }, #4 + 0x09c8 => { Name => 'IFCameraModel', Writable => 'string' }, #4 + 0x09c9 => { Name => 'CalibrationHistory', Writable => 'string' }, #4 + 0x09ca => { Name => 'CalibrationLog', Binary => 1 }, #4 (undef[1140]) + 0x09ce => { Name => 'SensorSerialNumber', Writable => 'string', Groups => { 2 => 'Camera' } }, #IB/4 + 0x09f6 => 'DefectConcealArtCorrectThres', #4 (no longer used) + 0x09f7 => 'SglColDCACThres1', #4 + 0x09f8 => 'SglColDCACThres2', #4 + 0x09f9 => 'SglColDCACTHres3', #4 + 0x0a01 => 'DblColDCACThres1', #4 + 0x0a02 => 'DblColDCACThres2', #4 + 0x0a0a => { Name => 'DefectConcealThresTable', Binary => 1 }, #4 (int16u[121/79]) + 0x0a28 => 'MonoUniqueMatrix', #4 + 0x0a29 => 'MonoMonitorMatrix', #4 + 0x0a2a => 'MonoToneScaleTable', #4 + # 0x0a32-0x0a3b "OmenInitialSurfaceRed(n)", ref 4 + # 0x0a3c-0x0a45 "OmenInitialSurfaceGoR(n)", ref 4 + # 0x0a46-0x0a4f "OmenInitialSurfaceBlue(n)", ref 4 + # 0x0a50-0x0a59 "OmenInitialSurfaceGoB(n)", ref 4 + 0x0a5a => 'OmenInitialScaling', #4 + 0x0a5b => 'OmenInitialRows', #4 + 0x0a5c => 'OmenInitialColumns', #4 + 0x0a5d => { Name => 'OmenInitialIPFStrength',Writable => 'int32s', Count => 4 }, #4 + 0x0a5e => { Name => 'OmenEarlyStrength', Writable => 'int32s', Count => 4 }, #4 + 0x0a5f => { Name => 'OmenAutoStrength', Writable => 'int32s', Count => 4 }, #4 + 0x0a60 => { Name => 'OmenAtCaptureStrength', Writable => 'int32s', Count => 4 }, #4 + 0x0a61 => 'OmenAtCaptureMode', #4 + 0x0a62 => { Name => 'OmenFocalLengthLimit', Writable => 'int16s' }, #4 + 0x0a64 => { Name => 'OmenSurfaceIndex', Writable => 'int16s' }, #4 (which InitialSurface to use) + 0x0a65 => 'OmenPercentToRationalLimitsRed', #4 (signed rationals for 0 and 100) + 0x0a66 => 'OmenPercentToRationalLimitsGoR', #4 (signed rationals for 0 and 100) + 0x0a67 => 'OmenPercentToRationalLimitsBlue', #4 (signed rationals for 0 and 100) + 0x0a68 => 'OmenPercentToRationalLimitsGoB', #4 (signed rationals for 0 and 100) + 0x0a6e => 'OmenEarlyGoBSurface', #4 + 0x0a6f => 'OmenEarlyGoBRows', #4 + 0x0a70 => 'OmenEarlyGoBColumns', #4 + 0x0a73 => 'OmenSmoothingKernel', #4 + 0x0a74 => 'OmenGradientOffset', #4 + 0x0a75 => 'OmenGradientKernel', #4 + 0x0a76 => 'OmenGradientKernelTaps', #4 + 0x0a77 => 'OmenRatioClipFactors', #4 + 0x0a78 => 'OmenRatioExclusionFactors', #4 + 0x0a79 => 'OmenGradientExclusionLimits', #4 + 0x0a7a => 'OmenROICoordinates', #4 + 0x0a7b => 'OmenROICoefficients', #4 + 0x0a7c => 'OmenRangeWeighting', #4 + 0x0a7d => 'OmenMeanToStrength', #4 + 0x0bb8 => 'FactoryWhiteGainsDaylight', #4 + 0x0bb9 => 'FactoryWhiteOffsetsDaylight', #4 + 0x0bba => 'DacGainsCoarse', #4 + 0x0bbb => 'DacGainsFine', #4 + 0x0bbc => 'DigitalExposureGains', #4 + 0x0bbd => 'DigitalExposureBiases', #4 + 0x0bbe => 'BlackClamp', #4 + 0x0bbf => 'ChannelCoarseGainAdjust', #4 + 0x0bc0 => 'BlackClampOffset', #4 + 0x0bf4 => 'DMPixelThresholdFactor', #4 (TIFF_RATIONAL) + 0x0bf5 => 'DMWindowThresholdFactor', #4 (TIFF_RATIONAL) + 0x0bf6 => 'DMTrimFraction', #4 (TIFF_RATIONAL) + 0x0bf7 => 'DMSmoothRejThresh', #4 (TIFF_RATIONAL) + 0x0bf8 => 'DMFillRejThresh', #4 (TIFF_RATIONAL) + 0x0bf9 => 'VMWsize', #4 (TIFF_SHORT) + 0x0bfa => 'DMErodeRadius', #4 (TIFF_SHORT) + 0x0bfb => 'DMNumPatches', #4 (TIFF_SHORT) + 0x0bfc => 'DMNoiseScale', #4 (TIFF_RATIONAL) + 0x0bfe => 'BrightDefectThreshold', #4 + 0x0bff => 'BrightDefectIntegrationMS', #4 + 0x0c00 => 'BrightDefectIsoCode', #4 + 0x0c03 => 'TopDarkRow1', #4 (support 330 dark map generation algorithm) + 0x0c04 => 'TopDarkRow2', #4 (these tags were 3175-3192 prior to 18Jan2001) + 0x0c05 => 'BottomDarkRow1', #4 + 0x0c06 => 'BottomDarkRow2', #4 + 0x0c07 => 'LeftDarkCol1', #4 + 0x0c08 => 'LeftDarkCol2', #4 + 0x0c09 => 'RightDarkCol1', #4 + 0x0c0a => 'RightDarkCol2', #4 + 0x0c0b => 'HMPixThresh', #4 + 0x0c0c => 'HMColThresh', #4 + 0x0c0d => 'HMWsize', #4 + 0x0c0e => 'HMColRejThresh', #4 + 0x0c0f => 'VMPixThresh', #4 + 0x0c10 => 'VMColThresh', #4 + 0x0c11 => 'VMNbands', #4 + 0x0c12 => 'VMColDropThresh', #4 + 0x0c13 => 'VMPatchResLimit', #4 + 0x0c14 => 'MapScale', #4 + 0x0c1c => 'Klut', #4 + 0x0c1d => 'RimNonlinearity', #4 (Obsolete) + 0x0c1e => 'InverseRimNonlinearity', #4 (Obsolete) + 0x0c1f => 'RembrandtToneScale', #4 (Obsolete) + 0x0c20 => 'RimToNifColorTransform', #4 (Obsolete) + 0x0c21 => 'RimToNifScaleFactor', #4 (Obsolete) + 0x0c22 => 'NifNonlinearity', #4 (Obsolete) + 0x0c23 => 'SBALogTransform', #4 (Obsolete) + 0x0c24 => 'InverseSBALogTransform', #4 (Obsolete) + 0x0c25 => { Name => 'SBABlack', Writable => 'int16u' }, #4 + 0x0c26 => { Name => 'SBAGray', Writable => 'int16u' }, #4 + 0x0c27 => { Name => 'SBAWhite', Writable => 'int16u' }, #4 + 0x0c28 => { Name => 'GaussianWeights', Binary => 1 }, #4 (int16u[864]) + 0x0c29 => { Name => 'SfsBoundary', Binary => 1 }, #4 (int16u[6561]) + 0x0c2a => 'CoringTableBest', #4 (Obsolete) + 0x0c2b => 'CoringTableBetter', #4 (Obsolete) + 0x0c2c => 'CoringTableGood', #4 (Obsolete) + 0x0c2d => 'ExposureReferenceGain', #4 (Obsolete) + 0x0c2e => 'ExposureReferenceOffset', #4 (Obsolete) + 0x0c2f => 'SBARedBalanceLut', #4 (Obsolete) + 0x0c30 => 'SBAGreenBalanceLut', #4 (Obsolete) + 0x0c31 => 'SBABlueBalanceLut', #4 (Obsolete) + 0x0c32 => { Name => 'SBANeutralBAL', Writable => 'int32s' }, #4 + 0x0c33 => { Name => 'SBAGreenMagentaBAL', Writable => 'int32s' }, #4 + 0x0c34 => { Name => 'SBAIlluminantBAL', Writable => 'int32s' }, #4 + 0x0c35 => { Name => 'SBAAnalysisComplete', Writable => 'int8u' }, #4 + 0x0c36 => 'JPEGQTableBest', #4 + 0x0c37 => 'JPEGQTableBetter', #4 + 0x0c38 => 'JPEGQTableGood', #4 + 0x0c39 => 'RembrandtPortraitToneScale', #4 (Obsolete) + 0x0c3a => 'RembrandtConsumerToneScale', #4 (Obsolete) + 0x0c3b => 'CFAGreenThreshold1', #4 (Now CFAGreenThreshold1H) + 0x0c3c => 'CFAGreenThreshold2', #4 (Now CFAGreenThreshold2V) + 0x0c3d => { Name => 'QTableLarge50Pct', Binary => 1 }, #4 (undef[130]) + 0x0c3e => { Name => 'QTableLarge67Pct', Binary => 1 }, #4 (undef[130]) + 0x0c3f => { Name => 'QTableLarge100Pct', Binary => 1 }, #4 (undef[130]) + 0x0c40 => { Name => 'QTableMedium50Pct', Binary => 1 }, #4 (undef[130]) + 0x0c41 => { Name => 'QTableMedium67Pct', Binary => 1 }, #4 (undef[130]) + 0x0c42 => { Name => 'QTableMedium100Pct', Binary => 1 }, #4 (undef[130]) + 0x0c43 => { Name => 'QTableSmall50Pct', Binary => 1 }, #4 (undef[130]) + 0x0c44 => { Name => 'QTableSmall67Pct', Binary => 1 }, #4 (undef[130]) + 0x0c45 => { Name => 'QTableSmall100Pct', Binary => 1 }, #4 (undef[130]) + 0x0c46 => { Name => 'SBAHighGray', Writable => 'int16u' }, #4 + 0x0c47 => { Name => 'SBALowGray', Writable => 'int16u' }, #4 + 0x0c48 => { Name => 'CaptureLook', Writable => 'int16u' }, #4 (was "ToneScaleFlag") + 0x0c49 => { Name => 'SBAIllOffset', Writable => 'int16s' }, #4 + 0x0c4a => { Name => 'SBAGmOffset', Writable => 'int16s' }, #4 + 0x0c4b => 'NifNonlinearity12Bit', #4 (Obsolete) + 0x0c4c => 'SharpeningOn', #4 (Obsolete) + 0x0c4d => 'NifNonlinearity16Bit', #4 (Obsolete) + 0x0c4e => 'RawHistogram', #4 + 0x0c4f => 'RawCFAComponentAverages', #4 + 0x0c50 => 'DisableFlagsPresent', #4 + 0x0c51 => 'DelayCols', #4 + 0x0c52 => 'DummyColsLeft', #4 + 0x0c53 => 'TrashColsRight', #4 + 0x0c54 => 'BlackColsRight', #4 + 0x0c55 => 'DummyColsRight', #4 + 0x0c56 => 'OverClockColsRight', #4 + 0x0c57 => 'UnusedBlackRowsTopOut', #4 + 0x0c58 => 'TrashRowsBottom', #4 + 0x0c59 => 'BlackRowsBottom', #4 + 0x0c5a => 'OverClockRowsBottom', #4 + 0x0c5b => 'BlackColsLeft', #4 + 0x0c5c => 'BlackRowsTop', #4 + 0x0c5d => 'PartialActiveColsLeft', #4 + 0x0c5e => 'PartialActiveColsRight', #4 + 0x0c5f => 'PartialActiveRowsTop', #4 + 0x0c60 => 'PartialActiveRowsBottom', #4 + 0x0c61 => { Name => 'ProcessBorderColsLeft', Writable => 'int16u' }, #4 + 0x0c62 => { Name => 'ProcessBorderColsRight', Writable => 'int16u' }, #4 + 0x0c63 => { Name => 'ProcessBorderRowsTop', Writable => 'int16u' }, #4 + 0x0c64 => { Name => 'ProcessBorderRowsBottom', Writable => 'int16u' }, #4 + 0x0c65 => 'ActiveCols', #4 + 0x0c66 => 'ActiveRows', #4 + 0x0c67 => 'FirstLines', #4 + 0x0c68 => 'UnusedBlackRowsTopIn', #4 + 0x0c69 => 'UnusedBlackRowsBottomIn', #4 + 0x0c6a => 'UnusedBlackRowsBottomOut', #4 + 0x0c6b => 'UnusedBlackColsLeftOut', #4 + 0x0c6c => 'UnusedBlackColsLeftIn', #4 + 0x0c6d => 'UnusedBlackColsRightIn', #4 + 0x0c6e => 'UnusedBlackColsRightOut', #4 + 0x0c6f => { Name => 'CFAOffsetRows', Writable => 'int32u' }, #4 + 0x0c70 => { Name => 'ShiftCols', Writable => 'int16s' }, #4 + 0x0c71 => { Name => 'CFAOffsetCols', Writable => 'int32u' }, #4 + 0x0c76 => 'DarkMapScale', #4 + 0x0c77 => 'HMapHandling', #4 + 0x0c78 => 'VMapHandling', #4 + 0x0c79 => 'DarkThreshold', #4 + 0x0c7a => { Name => 'DMDitherMatrix', Writable => 'int16u' }, #4 + 0x0c7b => { Name => 'DMDitherMatrixWidth', Writable => 'int16u' }, #4 + 0x0c7c => { Name => 'DMDitherMatrixHeight', Writable => 'int16u' }, #4 + 0x0c7d => { Name => 'MaxPixelValueThreshold', Writable => 'int16u' }, #4 + 0x0c7e => { Name => 'HoleFillDeltaThreshold', Writable => 'int16u' }, #4 + 0x0c7f => { Name => 'DarkPedestal', Writable => 'int16u' }, #4 + 0x0c80 => { Name => 'ImageProcessingFileTagsVersionNumber', Writable => 'int16u' }, #4 + 0x0c81 => { Name => 'ImageProcessingFileDateCreated', Writable => 'string', Groups => { 2 => 'Time' } }, #4 + 0x0c82 => { Name => 'DoublingMicrovolts', Writable => 'int32s' }, #4 + 0x0c83 => { #4 + Name => 'DarkFrameShortExposure', + Writable => 'int32u', + ValueConv => '$val / 1e6', # (microseconds) + ValueConvInv => '$val * 1e6', + PrintConv => 'Image::ExifTool::Exif::PrintExposureTime($val)', + PrintConvInv => '$val', + }, + 0x0c84 => { #4 + Name => 'DarkFrameLongExposure', + Writable => 'int32u', + ValueConv => '$val / 1e6', # (microseconds) + ValueConvInv => '$val * 1e6', + PrintConv => 'Image::ExifTool::Exif::PrintExposureTime($val)', + PrintConvInv => '$val', + }, + 0x0c85 => { Name => 'DarkFrameCountFactor', Writable => 'rational64u' }, #4 + 0x0c88 => { Name => 'HoleFillDarkDeltaThreshold', Writable => 'int16u' }, #4 + 0x0c89 => 'FarkleWhiteThreshold', #4 + 0x0c8a => { Name => 'ColumnResetOffsets', Binary => 1 }, #4 (int16u[3012]) + 0x0c8b => { Name => 'ColumnGainFactors', Binary => 1 }, #4 (int16u[3012]) + # 0x0c94-0x0c9d ColumnOffsets (int16u[3012]), ref 4 + 0x0c8c => 'Channel0LagKernel', #4 + 0x0c8d => 'Channel1LagKernel', #4 + 0x0c8e => 'Channel2LagKernel', #4 + 0x0c8f => 'Channel3LagKernel', #4 + 0x0c90 => 'BluegrassTable', #4 + 0x0c91 => 'BluegrassScale1', #4 + 0x0c92 => 'BluegrassScale2', #4 + 0x0ce4 => 'FinishedFileProcessingRequest', #4 + 0x0ce5 => { Name => 'FirmwareVersion', Writable => 'string', Groups => { 2 => 'Camera' } }, # ("ProcessingSoftware", ref 4) + 0x0ce6 => 'HostSoftwareExportVersion', #4 (ULONG only exists if made by host SW) + 0x0ce7 => { #4 + Name => 'HostSoftwareRendering', + Writable => 'int32u', + PrintConv => { + 0 => 'Normal (sRGB)', + 1 => 'Linear (camera RGB)', + 2 => 'Pro Photo RGB', + 3 => 'Unknown', + 4 => 'Other Profile', + }, + }, + 0x0dac => 'DCS3XXProcessingInfoIFD', #4 (Obsolete) + 0x0dad => 'DCS3XXProcessingInfo', #4 (Obsolete) + 0x0dae => { Name => 'IPAVersion', Writable => 'int32u' }, #4 + 0x0db6 => 'FinishIPAVersion', #4 + 0x0db7 => 'FinishIPFVersion', #4 + 0x0db8 => { #4 + Name => 'FinishFileType', + Writable => 'int32u', + PrintConv => { + 0 => 'JPEG Best', + 1 => 'JPEG Better', + 2 => 'JPEG Good', + 3 => 'TIFF RGB', + }, + }, + 0x0db9 => { #4 + Name => 'FinishResolution', + Writable => 'int32u', + PrintConv => { + 0 => '100%', + 1 => '67%', + 2 => '50%', + 3 => '25%', + }, + }, + 0x0dba => { #4 + Name => 'FinishNoise', + Writable => 'int32u', + PrintConv => { + 0 => 'Normal', + 1 => 'Strong', + 2 => 'Low', + }, + }, + 0x0dbb => { #4 + Name => 'FinishSharpening', + Writable => 'int32u', + PrintConv => { + 0 => 'None', + 1 => 'High', + 2 => 'Medium', + 3 => 'Low', + }, + }, + 0x0dbc => { #4 + Name => 'FinishLook', + Writable => 'int32u', + PrintConv => { + 0 => 'Product', + 1 => 'Portrait', + 2 => 'Product Reduced', + 3 => 'Portrait Reduced', + 4 => 'Monochrome Product', + 5 => 'Monochrome Portrait', + 6 => 'Wedding', + 7 => 'Event', + 8 => 'Product Hi Color', + 9 => 'Portrait Hi Color', + # (past this is not yet implemented) + 10 => 'Product Hi Color Hold', + 11 => 'Portrait Hi Color Hold', + 13 => 'DCS BW Normal', + 14 => 'DCS BW Wratten 8', + 15 => 'DCS BW Wratten 25', + 16 => 'DCS Sepia 1', + 17 => 'DCS Sepia 2', + }, + }, + 0x0dbd => { #4 + Name => 'FinishExposure', + Writable => 'int32u', + PrintConv => { 0 => 'Yes', 1 => 'No' }, + }, + 0x0e0b => { Name => 'SigmaScalingFactorLowRes', Writable => 'rational64u' }, #4 (for scaling sigma tables in-camera) + 0x0e0c => { Name => 'SigmaScalingFactorCamera', Writable => 'rational64u' }, #4 (for scaling sigma tables in-camera) + 0x0e0d => { Name => 'SigmaImpulseParameters', Writable => 'int16u', Count => -1 }, #4 (for impulse reduction control) + 0x0e0e => { Name => 'SigmaNoiseThreshTableV2', Binary => 1 }, #4 (replaces V2 caltable) + 0x0e0f => { Name => 'SigmaSizeTable', Writable => 'int16u', Count => -1 }, #4 + 0x0e10 => 'DacGainsCoarseAdjPreIF41', #4 (Tag not used due to abandoned implementation) + 0x0e11 => { Name => 'SigmaNoiseFilterCalTableV1', Binary => 1 }, #4 (undef[418]) (Defines Version 1 of Sigma Noise Filter table within .IF/.IPF) + 0x0e12 => { Name => 'SigmaNoiseFilterTableV1', Binary => 1}, #4 (Defines Version 1 of Sigma Noise Filter table within image) + 0x0e13 => 'Lin12ToKlut8', #4 + 0x0e14 => 'SigmaNoiseFilterTableV1Version', #4 (int16u/int32u) (This tag describes the version level of the SigmaNoiseFilterTableV1 class of tags) + 0x0e15 => 'Lin12ToKlut12', #4 + 0x0e16 => 'Klut12ToLin12', #4 + 0x0e17 => { Name => 'NifNonlinearity12To16', Binary => 1 }, #4 (int16u[4096]) + 0x0e18 => { Name => 'SBALog12Transform', Binary => 1 }, #4 (int16u[4096]) + 0x0e19 => { Name => 'InverseSBALog12Transform', Binary=> 1 }, #4 (int16u[3613]) + 0x0e1a => { Name => 'ToneScale0', Binary => 1 }, #4 (int16u[4096]) (Was Portrait12ToneScale on DCS3XX 1.3.1) + 0x0e1b => { Name => 'ToneScale1', Binary => 1 }, #4 (int16u[4096]) (Was Consumer12ToneScale on DCS3XX 1.3.1) + 0x0e1c => { Name => 'ToneScale2', Binary => 1 }, #4 (int16u[4096]) + 0x0e1d => { Name => 'ToneScale3', Binary => 1 }, #4 (int16u[4096]) + 0x0e1e => { Name => 'ToneScale4', Binary => 1 }, #4 (int16u[4096]) + 0x0e1f => { Name => 'ToneScale5', Binary => 1 }, #4 (int16u[4096]) + 0x0e20 => { Name => 'ToneScale6', Binary => 1 }, #4 (int16u[4096]) + 0x0e21 => { Name => 'ToneScale7', Binary => 1 }, #4 (int16u[4096]) + 0x0e22 => { Name => 'ToneScale8', Binary => 1 }, #4 (int16u[4096]) + 0x0e23 => { Name => 'ToneScale9', Binary => 1 }, #4 (int16u[4096]) + 0x0e24 => 'DayMat0', #4 (Obsolete) + 0x0e25 => 'DayMat1', #4 (Obsolete) + 0x0e26 => 'DayMat2', #4 (Obsolete) + 0x0e27 => 'DayMat3', #4 (Obsolete) + 0x0e28 => 'DayMat4', #4 (Obsolete) + 0x0e29 => 'DayMat5', #4 (Obsolete) + 0x0e2a => 'DayMat6', #4 (Obsolete) + 0x0e2b => 'DayMat7', #4 (Obsolete) + 0x0e2c => 'DayMat8', #4 (Obsolete) + 0x0e2d => 'DayMat9', #4 (Obsolete) + 0x0e2e => 'TungMat0', #4 (Obsolete) + 0x0e2f => 'TungMat1', #4 (Obsolete) + 0x0e30 => 'TungMat2', #4 (Obsolete) + 0x0e31 => 'TungMat3', #4 (Obsolete) + 0x0e32 => 'TungMat4', #4 (Obsolete) + 0x0e33 => 'TungMat5', #4 (Obsolete) + 0x0e34 => 'TungMat6', #4 (Obsolete) + 0x0e35 => 'TungMat7', #4 (Obsolete) + 0x0e36 => 'TungMat8', #4 (Obsolete) + 0x0e37 => 'TungMat9', #4 (Obsolete) + 0x0e38 => 'FluorMat0', #4 (Obsolete) + 0x0e39 => 'FluorMat1', #4 (Obsolete) + 0x0e3a => 'FluorMat2', #4 (Obsolete) + 0x0e3b => 'FluorMat3', #4 (Obsolete) + 0x0e3c => 'FluorMat4', #4 (Obsolete) + 0x0e3d => 'FluorMat5', #4 (Obsolete) + 0x0e3e => 'FluorMat6', #4 (Obsolete) + 0x0e3f => 'FluorMat7', #4 (Obsolete) + 0x0e40 => 'FluorMat8', #4 (Obsolete) + 0x0e41 => 'FluorMat9', #4 (Obsolete) + 0x0e42 => 'FlashMat0', #4 (Obsolete) + 0x0e43 => 'FlashMat1', #4 (Obsolete) + 0x0e44 => 'FlashMat2', #4 (Obsolete) + 0x0e45 => 'FlashMat3', #4 (Obsolete) + 0x0e46 => 'FlashMat4', #4 (Obsolete) + 0x0e47 => 'FlashMat5', #4 (Obsolete) + 0x0e48 => 'FlashMat6', #4 (Obsolete) + 0x0e49 => 'FlashMat7', #4 (Obsolete) + 0x0e4a => 'FlashMat8', #4 (Obsolete) + 0x0e4b => 'FlashMat9', #4 (Obsolete) + 0x0e4c => { #IB + Name => 'KodakLook', # ("LookNameTable", ref 4) + Format => 'undef', + Writable => 'string', + ValueConv => '$val=~tr/\0/\n/; $val', + ValueConvInv => '$val=~tr/\n/\0/; $val', + }, + 0x0e4d => { Name => 'IPFCameraModel', Writable => 'string' }, #4 + 0x0e4e => { Name => 'AH2GreenInterpolationThreshold', Writable => 'int16u' }, #4 + 0x0e4f => { Name => 'ResamplingKernelDenominators067', Writable => 'int16u', Count => 3 }, #4 (table of sharpening denoms; 0=Low, 1=Medium, 2=High) + 0x0e50 => { Name => 'ResamplingKernelDenominators050', Writable => 'int16u', Count => 3 }, #4 (table of sharpening denoms; 0=Low, 1=Medium, 2=High) + 0x0e51 => { Name => 'ResamplingKernelDenominators100', Writable => 'int16u', Count => 3 }, #4 (table of sharpening denoms; 0=Low, 1=Medium, 2=High) + 0x0e56 => 'LookMat0', #4 (rational64s[9]) + 0x0e57 => 'LookMat1', #4 (rational64s[9]) + 0x0e58 => 'LookMat2', #4 (rational64s[9]) + 0x0e59 => 'LookMat3', #4 (rational64s[9]) + 0x0e5a => 'LookMat4', #4 (rational64s[9]) + 0x0e5b => 'LookMat5', #4 (rational64s[9]) + 0x0e5c => 'LookMat6', #4 (rational64s[9]) + 0x0e5d => 'LookMat7', #4 (rational64s[9]) + 0x0e5e => 'LookMat8', #4 (rational64s[9]) + 0x0e5f => 'LookMat9', #4 (rational64s[9]) + 0x0e60 => { #4 + Name => 'CFAInterpolationAlgorithm', + Writable => 'int16u', + PrintConv => { 0 => 'AH2', 1 => 'Karnak' }, + }, + 0x0e61 => { #4 + Name => 'CFAInterpolationMetric', + Writable => 'int16u', + PrintConv => { 0 => 'Linear12', 1 => 'KLUT12' }, + }, + 0x0e62 => { Name => 'CFAZipperFixThreshold', Writable => 'int16u' }, #4 + 0x0e63 => { Name => 'NoiseReductionParametersKhufuRGB', Writable => 'int16u', Count => 9 }, #4 + 0x0e64 => { Name => 'NoiseReductionParametersKhufu6MP', Writable => 'int16u', Count => 9 }, #4 + 0x0e65 => { Name => 'NoiseReductionParametersKhufu3MP', Writable => 'int16u', Count => 9 }, #4 + 0x0e6a => { Name => 'ChromaNoiseHighFThresh', Writable => 'int32u', Count => 2 }, #4 + 0x0e6b => { Name => 'ChromaNoiseLowFThresh', Writable => 'int32u', Count => 2 }, #4 + 0x0e6c => { Name => 'ChromaNoiseEdgeMapThresh', Writable => 'int32u' }, #4 + 0x0e6d => { Name => 'ChromaNoiseColorSpace', Writable => 'int32u' }, #4 + 0x0e6e => { Name => 'EnableChromaNoiseReduction', Writable => 'int16u' }, #4 + # 9 values for noise reduction parameters: + # 0 - NRLowType + # 1 - NRLowRadius + # 2 - NRLowStrength + # 3 - NRMediumType + # 4 - NRMediumRadius + # 5 - NRMediumStrength + # 6 - NRHighType + # 7 - NRHighRadius + # 8 - NRHighStrength + # NRType values: + # 0 = None + # 1 = SigmaChroma + # 2 = SigmaOnly + # 3 = SigmaMoire + # 4 = SigmaChromaWithRadius + # 5 = SigmaMoireWithRadius + # 6 = SigmaExpert (aka Khufu) + # 7 = SigmaWithRadius + 0x0e6f => { Name => 'NoiseReductionParametersHostRGB', Writable => 'int16u', Count => 9 }, #4 + 0x0e70 => { Name => 'NoiseReductionParametersHost6MP', Writable => 'int16u', Count => 9 }, #4 + 0x0e71 => { Name => 'NoiseReductionParametersHost3MP', Writable => 'int16u', Count => 9 }, #4 + 0x0e72 => { Name => 'NoiseReductionParametersCamera', Writable => 'int16u', Count => 6 }, #4 + 0x0e73 => { #4 + Name => 'NoiseReductionParametersAtCapture', + Writable => 'int16u', + Count => 6, + # 6 values: + # 0 - Algorithm type + # 1 - Radius + # 2 - Strength + # 3 - Khufu Luma + # 4 - Reserved 1 + # 5 - Reserved 2 + }, + 0x0e74 => { Name => 'LCDMatrix', Writable => 'rational64s', Count => 9 }, #4 + 0x0e75 => { Name => 'LCDMatrixChickFix', Writable => 'rational64s', Count => 9 }, #4 + 0x0e76 => { Name => 'LCDMatrixMarvin', Writable => 'rational64s', Count => 9 }, #4 + 0x0e7c => { Name => 'LCDGammaTableChickFix',Binary => 1 }, #4 (int16u[4096]) + 0x0e7d => { Name => 'LCDGammaTableMarvin', Binary => 1 }, #4 (int16u[4096]) + 0x0e7e => { Name => 'LCDGammaTable', Binary => 1 }, #4 (int16u[4096]) + 0x0e7f => 'LCDSharpeningF1', #4 (int16s[4]) + 0x0e80 => 'LCDSharpeningF2', #4 + 0x0e81 => 'LCDSharpeningF3', #4 + 0x0e82 => 'LCDSharpeningF4', #4 + 0x0e83 => 'LCDEdgeMapX1', #4 + 0x0e84 => 'LCDEdgeMapX2', #4 + 0x0e85 => 'LCDEdgeMapX3', #4 + 0x0e86 => 'LCDEdgeMapX4', #4 + 0x0e87 => 'LCDEdgeMapSlope', #4 + 0x0e88 => 'YCrCbMatrix', #4 + 0x0e89 => 'LCDEdgeSpline', #4 (rational64s[9]) + 0x0e92 => { Name => 'Fac18Per', Writable => 'int16u' }, #4 + 0x0e93 => { Name => 'Fac170Per', Writable => 'int16u' }, #4 + 0x0e94 => { Name => 'Fac100Per', Writable => 'int16u' }, #4 + 0x0e9b => 'ExtraTickLocations', #4 (int16u[7]) + 0x0e9c => { Name => 'RGBtoeV0', Binary => 1 }, #4 (int16s[256]) + 0x0e9d => { Name => 'RGBtoeV1', Binary => 1 }, #4 (int16s[256]) + 0x0e9e => { Name => 'RGBtoeV2', Binary => 1 }, #4 (int16s[256]) + 0x0e9f => { Name => 'RGBtoeV3', Binary => 1 }, #4 (int16s[256]) + 0x0ea0 => { Name => 'RGBtoeV4', Binary => 1 }, #4 (int16s[256]) + 0x0ea1 => { Name => 'RGBtoeV5', Binary => 1 }, #4 (int16s[256]) + 0x0ea2 => { Name => 'RGBtoeV6', Binary => 1 }, #4 (int16s[256]) + 0x0ea3 => { Name => 'RGBtoeV7', Binary => 1 }, #4 (int16s[256]) + 0x0ea4 => { Name => 'RGBtoeV8', Binary => 1 }, #4 (int16s[256]) + 0x0ea5 => { Name => 'RGBtoeV9', Binary => 1 }, #4 (int16s[256]) + 0x0ea6 => { Name => 'LCDHistLUT0', Binary => 1 }, #4 (rational64s[48]) + 0x0ea7 => { Name => 'LCDHistLUT1', Binary => 1 }, #4 (rational64s[57]) + 0x0ea8 => { Name => 'LCDHistLUT2', Binary => 1 }, #4 (rational64s[48]) + 0x0ea9 => { Name => 'LCDHistLUT3', Binary => 1 }, #4 (rational64s[57]) + 0x0eaa => { Name => 'LCDHistLUT4', Binary => 1 }, #4 (rational64s[48]) + 0x0eab => { Name => 'LCDHistLUT5', Binary => 1 }, #4 (rational64s[57]) + 0x0eac => { Name => 'LCDHistLUT6', Binary => 1 }, #4 (rational64s[48]) + 0x0ead => { Name => 'LCDHistLUT7', Binary => 1 }, #4 (rational64s[48]) + 0x0eae => { Name => 'LCDHistLUT8', Binary => 1 }, #4 + 0x0eaf => { Name => 'LCDHistLUT9', Binary => 1 }, #4 + 0x0eb0 => 'LCDLinearClipValue', #4 + 0x0ece => 'LCDStepYvalues', #4 (int8u[10]) + 0x0ecf => 'LCDStepYvaluesChickFix', #4 (int8u[10]) + 0x0ed0 => 'LCDStepYvaluesMarvin', #4 (int8u[10]) + 0x0ed8 => { Name => 'InterpolationCoefficients', Binary => 1 }, #4 (int16s[69]) + 0x0ed9 => 'InterpolationCoefficients6MP', #4 + 0x0eda => 'InterpolationCoefficients3MP', #4 + 0x0f00 => { Name => 'NoiseReductionParametersHostNormal', Binary => 1 }, #4 (int16u[140]) + 0x0f01 => { Name => 'NoiseReductionParametersHostStrong', Binary => 1 }, #4 (int16u[140]) + 0x0f02 => { Name => 'NoiseReductionParametersHostLow', Binary => 1 }, #4 + 0x0f0a => { Name => 'MariahTextureThreshold', Writable => 'int16u' }, #4 + 0x0f0b => { Name => 'MariahMapLoThreshold', Writable => 'int16u' }, #4 + 0x0f0c => { Name => 'MariahMapHiThreshold', Writable => 'int16u' }, #4 + 0x0f0d => { Name => 'MariahChromaBlurSize', Writable => 'int16u' }, #4 + 0x0f0e => { Name => 'MariahSigmaThreshold', Writable => 'int16u' }, #4 + 0x0f0f => { Name => 'MariahThresholds', Binary => 1 }, #4 + 0x0f10 => { Name => 'MariahThresholdsNormal', Binary => 1 }, #4 (int16u[140]) + 0x0f11 => { Name => 'MariahThresholdsStrong', Binary => 1 }, #4 (int16u[140]) + 0x0f12 => { Name => 'MariahThresholdsLow', Binary => 1 }, #4 + 0x0f14 => 'KhufuLinearRedMixingCoefficient', #4 + 0x0f15 => 'KhufuLinearGreenMixingCoefficient', #4 + 0x0f16 => 'KhufuLinearBlueMixingCoefficient', #4 + 0x0f17 => 'KhufuUSpaceC2MixingCoefficient', #4 + 0x0f18 => 'KhufuSigmaGaussianWeights', #4 + 0x0f19 => 'KhufuSigmaScalingFactors6MP', #4 (rational64u[6]) + 0x0f1a => 'KhufuSigmaScalingFactors3MP', #4 (rational64u[6]) + 0x0f1b => 'KhufuSigmaScalingFactors14MP', #4 + # 0x0f1e-0x0f27 - KhufuLinearRGBtoLogRGB(n), (for Khufu) ref 4 + # 0x0f28-0x0f31 - KhufuLogRGBtoLinearRGB(n), (for Khufu) ref 4 + 0x0f32 => { Name => 'KhufuI0Thresholds', Binary => 1 }, #4 (int32s[348]) + 0x0f33 => { Name => 'KhufuI1Thresholds', Binary => 1 }, #4 (int32s[348]) + 0x0f34 => { Name => 'KhufuI2Thresholds', Binary => 1 }, #4 (int32s[348]) + 0x0f35 => { Name => 'KhufuI3Thresholds', Binary => 1 }, #4 (int32s[348]) + 0x0f36 => { Name => 'KhufuI4Thresholds', Binary => 1 }, #4 (int32s[348]) + 0x0f37 => { Name => 'KhufuI5Thresholds', Binary => 1 }, #4 (int32s[348]) + 0x0f3c => { Name => 'CondadoDayBVThresh', Writable => 'int16u' }, #4 + 0x0f3d => { Name => 'CondadoNeuRange', Writable => 'int16u' }, #4 + 0x0f3e => { Name => 'CondadoBVFactor', Writable => 'int16s' }, #4 + 0x0f3f => { Name => 'CondadoIllFactor', Writable => 'int16s' }, #4 + 0x0f40 => { Name => 'CondadoTunThresh', Writable => 'int16s' }, #4 + 0x0f41 => { Name => 'CondadoFluThresh', Writable => 'int16s' }, #4 + 0x0f42 => { Name => 'CondadoDayOffsets', Writable => 'int16s', Count => 2 }, #4 + 0x0f43 => { Name => 'CondadoTunOffsets', Writable => 'int16s', Count => 2 }, #4 + 0x0f44 => { Name => 'CondadoFluOffsets', Writable => 'int16s', Count => 2 }, #4 + 0x0f5a => 'ERIMMToCRGB0Spline', #4 (rational64s[33]) + 0x0f5b => 'ERIMMToCRGB1Spline', #4 (rational64s[36]) + 0x0f5c => 'ERIMMToCRGB2Spline', #4 (rational64s[33]) + 0x0f5d => 'ERIMMToCRGB3Spline', #4 (rational64s[33]) + 0x0f5e => 'ERIMMToCRGB4Spline', #4 (rational64s[33]) + 0x0f5f => 'ERIMMToCRGB5Spline', #4 (rational64s[33]) + 0x0f60 => 'ERIMMToCRGB6Spline', #4 (rational64s[33]) + 0x0f61 => 'ERIMMToCRGB7Spline', #4 (rational64s[33]) + 0x0f62 => 'ERIMMToCRGB8Spline', #4 + 0x0f63 => 'ERIMMToCRGB9Spline', #4 + 0x0f64 => 'CRGBToERIMM0Spline', #4 (rational64s[27]) + 0x0f65 => 'CRGBToERIMM1Spline', #4 (rational64s[54]) + 0x0f66 => 'CRGBToERIMM2Spline', #4 (rational64s[27]) + 0x0f67 => 'CRGBToERIMM3Spline', #4 (rational64s[54]) + 0x0f68 => 'CRGBToERIMM4Spline', #4 (rational64s[27]) + 0x0f69 => 'CRGBToERIMM5Spline', #4 (rational64s[54]) + 0x0f6a => 'CRGBToERIMM6Spline', #4 (rational64s[27]) + 0x0f6b => 'CRGBToERIMM7Spline', #4 (rational64s[27]) + 0x0f6c => 'CRGBToERIMM8Spline', #4 + 0x0f6d => 'CRGBToERIMM9Spline', #4 + 0x0f6e => 'ERIMMNonLinearitySpline', #4 (rational64s[42]) + 0x0f6f => 'Delta12To8Spline', #4 (rational64s[12]) + 0x0f70 => 'Delta8To12Spline', #4 (rational64s[12]) + 0x0f71 => 'InverseMonitorMatrix', #4 (rational64s[9]) + 0x0f72 => { Name => 'NifNonlinearityExt', Binary => 1 }, #4 (int16s[8000]) + 0x0f73 => { Name => 'InvNifNonLinearity', Binary => 1 }, #4 (int16u[256]) + 0x0f74 => 'RIMM13ToERIMM12Spline', #4 (rational64s[51]) + 0x0f78 => 'ToneScale0Spline', #4 (rational64s[57]) + 0x0f79 => 'ToneScale1Spline', #4 (rational64s[51]) + 0x0f7a => 'ToneScale2Spline', #4 (rational64s[57]) + 0x0f7b => 'ToneScale3Spline', #4 (rational64s[51]) + 0x0f7c => 'ToneScale4Spline', #4 (rational64s[57]) + 0x0f7d => 'ToneScale5Spline', #4 (rational64s[51]) + 0x0f7e => 'ToneScale6Spline', #4 (rational64s[57]) + 0x0f7f => 'ToneScale7Spline', #4 (rational64s[57]) + 0x0f80 => 'ToneScale8Spline', #4 + 0x0f81 => 'ToneScale9Spline', #4 + 0x0f82 => 'ERIMMToneScale0Spline', #4 (rational64s[60]) + 0x0f83 => 'ERIMMToneScale1Spline', #4 (rational64s[54]) + 0x0f84 => 'ERIMMToneScale2Spline', #4 (rational64s[60]) + 0x0f85 => 'ERIMMToneScale3Spline', #4 (rational64s[54]) + 0x0f86 => 'ERIMMToneScale4Spline', #4 (rational64s[60]) + 0x0f87 => 'ERIMMToneScale5Spline', #4 (rational64s[54]) + 0x0f88 => 'ERIMMToneScale6Spline', #4 (rational64s[60]) + 0x0f89 => 'ERIMMToneScale7Spline', #4 (rational64s[60]) + 0x0f8a => 'ERIMMToneScale8Spline', #4 + 0x0f8b => 'ERIMMToneScale9Spline', #4 + 0x0f8c => 'RIMMToCRGB0Spline', #4 (rational64s[66]) + 0x0f8d => 'RIMMToCRGB1Spline', #4 (rational64s[84]) + 0x0f8e => 'RIMMToCRGB2Spline', #4 (rational64s[66]) + 0x0f8f => 'RIMMToCRGB3Spline', #4 (rational64s[84]) + 0x0f90 => 'RIMMToCRGB4Spline', #4 (rational64s[66]) + 0x0f91 => 'RIMMToCRGB5Spline', #4 (rational64s[84]) + 0x0f92 => 'RIMMToCRGB6Spline', #4 (rational64s[66]) + 0x0f93 => 'RIMMToCRGB7Spline', #4 (rational64s[66]) + 0x0f94 => 'RIMMToCRGB8Spline', #4 + 0x0f95 => 'RIMMToCRGB9Spline', #4 + 0x0fa0 => 'QTableLarge25Pct', #4 + 0x0fa1 => 'QTableMedium25Pct', #4 + 0x0fa2 => 'QTableSmall25Pct', #4 + 0x1130 => 'NoiseReductionKernel', #4 (Noise filter kernel. No longer needed) + 0x1388 => 'UserMetaData', #4 (undef[0]) + 0x1389 => { Name => 'InputProfile', Writable => 'undef', Binary => 1 }, #IB ("SourceProfile", ref 4) + 0x138a => { Name => 'KodakLookProfile', Writable => 'undef', Binary => 1 }, #IB ("LookProfile", ref 4) + 0x138b => { Name => 'OutputProfile', Writable => 'undef', Binary => 1 }, #IB ("DestinationProfile", ref 4) + 0x1390 => { Name => 'SourceProfilePrefix', Writable => 'string' }, #4 (eg. 'DCSProSLRn') + 0x1391 => { Name => 'ToneCurveProfileName', Writable => 'string' }, #4 + 0x1392 => { Name => 'InputProfile', SubDirectory => { TagTable => 'Image::ExifTool::ICC_Profile::Main' } }, #4 + 0x1393 => { Name => 'ProcessParametersV2', Binary => 1 }, #4 (Used by the SDK, Firmware should not use!) + 0x1394 => 'ReservedBlob2', #4 + 0x1395 => 'ReservedBlob3', #4 + 0x1396 => 'ReservedBlob4', #4 + 0x1397 => 'ReservedBlob5', #4 + 0x1398 => 'ReservedBlob6', #4 + 0x1399 => 'ReservedBlob7', #4 + 0x139a => 'ReservedBlob8', #4 + 0x139b => 'ReservedBlob9', #4 + 0x1770 => { Name => 'ScriptVersion', Writable => 'int32u' }, #4 + 0x177a => 'ImagerTimingData', #4 + 0x1784 => { Name => 'ISO', Writable => 'int32u' }, #3 ("NsecPerIcCode", ref 4) + 0x17a2 => 'Scav11Cols', #4 + 0x17a3 => 'Scav12Cols', #4 + 0x17a4 => 'Scav21Cols', #4 + 0x17a5 => 'Scav22Cols', #4 + 0x17a6 => 'ActiveCTEMonitor1Cols', #4 + 0x17a7 => 'ActiveCTEMonitor2Cols', #4 + 0x17a8 => 'ActiveCTEMonitorRows', #4 + 0x17a9 => 'ActiveBuf1Cols', #4 + 0x17aa => 'ActiveBuf2Cols', #4 + 0x17ab => 'ActiveBuf1Rows', #4 + 0x17ac => 'ActiveBuf2Rows', #4 + 0x17c0 => 'HRNoiseLines', #4 + 0x17c1 => 'RNoiseLines', #4 + 0x17c2 => 'ANoiseLines', #4 + 0x17d4 => { Name => 'ImagerCols', Writable => 'int16u' }, #4 + 0x17de => { Name => 'ImagerRows', Writable => 'int16u' }, #4 + 0x17e8 => { Name => 'PartialActiveCols1', Writable => 'int32u' }, #4 + 0x17f2 => { Name => 'PartialActiveCols2', Writable => 'int32u' }, #4 + 0x17fc => { Name => 'PartialActiveRows1', Writable => 'int32u' }, #4 + 0x1806 => { Name => 'PartialActiveRows2', Writable => 'int32u' }, #4 + 0x1810 => { Name => 'ElectricalBlackColumns',Writable=> 'int32u' }, #4 + 0x181a => { Name => 'ResetBlackSegRows', Writable => 'int32u' }, #4 + 0x1838 => { Name => 'CaptureWidthNormal', Writable => 'int32u' }, #4 + 0x1839 => { Name => 'CaptureHeightNormal', Writable => 'int32u' }, #4 + 0x183a => 'CaptureWidthResetBlackSegNormal', #4 + 0x183b => 'CaptureHeightResetBlackSegNormal', #4 + 0x183c => 'DarkRefOffsetNormal', #4 + 0x1842 => { Name => 'CaptureWidthTest', Writable => 'int32u' }, #4 + 0x1843 => 'CaptureHeightTest', #4 + 0x1844 => 'CaptureWidthResetBlackSegTest', #4 + 0x1845 => 'CaptureHeightResetBlackSegTest', #4 + 0x1846 => 'DarkRefOffsetTest', #4 + 0x184c => { Name => 'ImageSegmentStartLine',Writable => 'int32u' }, #4 + 0x184d => { Name => 'ImageSegmentLines', Writable => 'int32u' }, #4 + 0x184e => { Name => 'SkipLineTime', Writable => 'int32u' }, #4 + 0x1860 => { Name => 'FastResetLineTime', Writable => 'int32u' }, #4 + 0x186a => { Name => 'NormalLineTime', Writable => 'int32u' }, #4 + 0x1874 => { Name => 'MinIntegrationRows', Writable => 'int32u' }, #4 + 0x187e => { Name => 'PreReadFastResetCount',Writable => 'int32u' }, #4 + 0x1888 => { Name => 'TransferTimeNormal', Writable => 'int32u' }, #4 + 0x1889 => { Name => 'TransferTimeTest', Writable => 'int32u' }, #4 + 0x188a => { Name => 'QuietTime', Writable => 'int32u' }, #4 + 0x189c => { Name => 'OverClockCols', Writable => 'int16u' }, #4 + 0x18a6 => { Name => 'H2ResetBlackPixels', Writable => 'int32u' }, #4 + 0x18b0 => { Name => 'H3ResetBlackPixels', Writable => 'int32u' }, #4 + 0x18ba => { Name => 'BlackAcquireRows', Writable => 'int32u' }, #4 + 0x18c4 => { Name => 'OverClockRows', Writable => 'int16u' }, #4 + 0x18ce => { Name => 'H3ResetBlackColumns', Writable => 'int32u' }, #4 + 0x18d8 => { Name => 'DarkBlackSegRows', Writable => 'int32u' }, #4 + 0x1900 => 'CrossbarEnable', #4 + 0x1901 => { Name => 'FifoenOnePixelDelay', Writable => 'int32u' }, #4 + 0x1902 => { Name => 'ReadoutTypeRequested', Writable => 'int32u' }, #4 + 0x1903 => { Name => 'ReadoutTypeActual', Writable => 'int32u' }, #4 + 0x190a => { Name => 'OffsetDacValue', Writable => 'int32u' }, #4 + 0x1914 => { Name => 'TempAmpGainX100', Writable => 'int32u' }, #4 + 0x191e => { Name => 'VarrayDacNominalValues',Writable=> 'int32u', Count => 3 }, #4 + 0x1928 => 'VddimDacNominalValues', #4 + 0x1964 => { Name => 'C14Configuration', Writable => 'int32u' }, #4 + 0x196e => { Name => 'TDA1Offset', Writable => 'int32u', Count => 3 }, #4 + 0x196f => { Name => 'TDA1Bandwidth', Writable => 'int32u' }, #4 + 0x1970 => { Name => 'TDA1Gain', Writable => 'int32u', Count => 3 }, #4 + 0x1971 => { Name => 'TDA1EdgePolarity', Writable => 'int32u' }, #4 + 0x1978 => { Name => 'TDA2Offset', Writable => 'int32u', Count => 3 }, #4 + 0x1979 => { Name => 'TDA2Bandwidth', Writable => 'int32u' }, #4 + 0x197a => { Name => 'TDA2Gain', Writable => 'int32u', Count => 3 }, #4 + 0x197b => { Name => 'TDA2EdgePolarity', Writable => 'int32u' }, #4 + 0x1982 => { Name => 'TDA3Offset', Writable => 'int32u', Count => 3 }, #4 + 0x1983 => { Name => 'TDA3Bandwidth', Writable => 'int32u' }, #4 + 0x1984 => { Name => 'TDA3Gain', Writable => 'int32u', Count => 3 }, #4 + 0x1985 => { Name => 'TDA3EdgePolarity', Writable => 'int32u' }, #4 + 0x198c => { Name => 'TDA4Offset', Writable => 'int32u', Count => 3 }, #4 + 0x198d => { Name => 'TDA4Bandwidth', Writable => 'int32u' }, #4 + 0x198e => { Name => 'TDA4Gain', Writable => 'int32u', Count => 3 }, #4 + 0x198f => { Name => 'TDA4EdgePolarity', Writable => 'int32u' }, #4 + 0xfde8 => { Name => 'ComLenBlkSize', Writable => 'int16u' }, #4 +); + +# contains WB adjust set in software (ref 3) +%Image::ExifTool::Kodak::Processing = ( + GROUPS => { 0 => 'MakerNotes', 2 => 'Camera' }, + PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData, + WRITE_PROC => \&Image::ExifTool::WriteBinaryData, + CHECK_PROC => \&Image::ExifTool::CheckBinaryData, + FORMAT => 'int16u', + FIRST_ENTRY => 0, + 20 => { + Name => 'WB_RGBLevels', + Format => 'int16u[3]', + ValueConv => q{ + my @a = split ' ',$val; + foreach (@a) { + $_ = 2048 / $_ if $_; + } + return join ' ', @a; + } + }, +); + +# tags found in the Kodak KDC_IFD (in IFD0 of KDC images) (ref 3) +%Image::ExifTool::Kodak::KDC_IFD = ( + GROUPS => { 0 => 'MakerNotes', 1 => 'KDC_IFD', 2 => 'Image'}, + WRITE_PROC => \&Image::ExifTool::Exif::WriteExif, + CHECK_PROC => \&Image::ExifTool::Exif::CheckExif, + WRITE_GROUP => 'KDC_IFD', + SET_GROUP1 => 1, + NOTES => q{ + These tags are found in a separate IFD of KDC images from some newer Kodak + models such as the P880 and Z1015IS. + }, + 0xfa00 => { + Name => 'SerialNumber', #PH (unverified) + Writable => 'string', + }, + 0xfa0d => { + Name => 'WhiteBalance', + Writable => 'int8u', + PrintConv => { #PH + 0 => 'Auto', + 1 => 'Fluorescent', # (NC) + 2 => 'Tungsten', # (NC) + 3 => 'Daylight', # (NC) + 6 => 'Shade', # (NC, called "Open Shade" by Kodak) + }, + }, + # the following tags are numbered for use in the Composite tag lookup + 0xfa25 => 'WB_RGBLevelsAuto', + 0xfa27 => 'WB_RGBLevelsTungsten', # (NC) + 0xfa28 => 'WB_RGBLevelsFluorescent', # (NC) + 0xfa29 => 'WB_RGBLevelsDaylight', # (NC) + 0xfa2a => 'WB_RGBLevelsShade', # (NC) +); + +# textual-based Kodak TextualInfo tags (not found in KDC images) (ref PH) +%Image::ExifTool::Kodak::TextualInfo = ( + GROUPS => { 0 => 'MakerNotes', 1 => 'Kodak', 2 => 'Image'}, + PROCESS_PROC => \&ProcessKodakText, + NOTES => q{ + Below is a list of tags which have been observed in the Kodak TextualInfo + data, however ExifTool will extract information from any tags found here. + }, + 'Actual Compensation' => 'ActualCompensation', + 'AF Function' => 'AFMode', # values: "S" (=Single?, then maybe C for Continuous, M for Manual?) - PH + 'Aperture' => { + Name => 'Aperture', + ValueConv => '$val=~s/^f//i; $val', + }, + 'Auto Bracket' => 'AutoBracket', + 'Brightness Value' => 'BrightnessValue', + 'Camera' => 'CameraModel', + 'Camera body' => 'CameraBody', + 'Compensation' => 'ExposureCompensation', + 'Date' => { + Name => 'Date', + Groups => { 2 => 'Time' }, + }, + 'Exposure Bias' => 'ExposureBias', + 'Exposure Mode' => { + Name => 'ExposureMode', + PrintConv => { + OTHER => sub { shift }, # pass other values straight through + 'M' => 'Manual', + 'A' => 'Aperture Priority', #(NC -- I suppose this could be "Auto" too) + 'S' => 'Shutter Priority', #(NC) + 'P' => 'Program', #(NC) + 'B' => 'Bulb', #(NC) + # have seen "Manual (M)" written by DCS760C - PH + # and "Aperture priority AE (Av)" written by a ProBack 645M + }, + }, + 'Firmware Version' => 'FirmwareVersion', + 'Flash Compensation' => 'FlashExposureComp', + 'Flash Fired' => 'FlashFired', + 'Flash Sync Mode' => 'FlashSyncMode', + 'Focal Length' => { + Name => 'FocalLength', + PrintConv => '"$val mm"', + }, + 'Height' => 'KodakImageHeight', + 'Image Number' => 'ImageNumber', + 'ISO' => 'ISO', + 'ISO Speed' => 'ISO', + 'Max Aperture' => { + Name => 'MaxAperture', + ValueConv => '$val=~s/^f//i; $val', + }, + 'Meter Mode' => 'MeterMode', + 'Min Aperture' => { + Name => 'MinAperture', + ValueConv => '$val=~s/^f//i; $val', + }, + 'Popup Flash' => 'PopupFlash', + 'Serial Number' => 'SerialNumber', + 'Shooting Mode' => 'ShootingMode', + 'Shutter' => 'ShutterSpeed', + 'Temperature' => 'Temperature', # with a value of 15653, what could this be? - PH + 'Time' => { + Name => 'Time', + Groups => { 2 => 'Time' }, + }, + 'White balance' => 'WhiteBalance', + 'Width' => 'KodakImageWidth', + '_other_info' => { + Name => 'OtherInfo', + Notes => 'any other information without a tag name', + }, +); + +# Kodak APP3 "Meta" tags (ref 2) +%Image::ExifTool::Kodak::Meta = ( + GROUPS => { 0 => 'Meta', 1 => 'MetaIFD', 2 => 'Image'}, + WRITE_PROC => \&Image::ExifTool::Exif::WriteExif, + CHECK_PROC => \&Image::ExifTool::Exif::CheckExif, + WRITE_GROUP => 'MetaIFD', # default write group + NOTES => q{ + These tags are found in the APP3 "Meta" segment of JPEG images from Kodak + cameras such as the DC280, DC3400, DC5000, MC3, M580, Z950 and Z981. The + structure of this segment is similar to the APP1 "Exif" segment, but a + different set of tags is used. + }, + 0xc350 => 'FilmProductCode', + 0xc351 => 'ImageSourceEK', + 0xc352 => 'CaptureConditionsPAR', + 0xc353 => { + Name => 'CameraOwner', + Writable => 'undef', + RawConv => 'Image::ExifTool::Exif::ConvertExifText($self,$val,$tag)', + RawConvInv => 'Image::ExifTool::Exif::EncodeExifText($self,$val)', + }, + 0xc354 => { + Name => 'SerialNumber', + Writable => 'undef', + Groups => { 2 => 'Camera' }, + RawConv => 'Image::ExifTool::Exif::ConvertExifText($self,$val,$tag)', #PH + RawConvInv => 'Image::ExifTool::Exif::EncodeExifText($self,$val)', + }, + 0xc355 => 'UserSelectGroupTitle', + 0xc356 => 'DealerIDNumber', + 0xc357 => 'CaptureDeviceFID', + 0xc358 => 'EnvelopeNumber', + 0xc359 => 'FrameNumber', + 0xc35a => 'FilmCategory', + 0xc35b => 'FilmGencode', + 0xc35c => 'ModelAndVersion', + 0xc35d => 'FilmSize', + 0xc35e => 'SBA_RGBShifts', + 0xc35f => 'SBAInputImageColorspace', + 0xc360 => 'SBAInputImageBitDepth', + 0xc361 => { + Name => 'SBAExposureRecord', + Binary => 1, + }, + 0xc362 => { + Name => 'UserAdjSBA_RGBShifts', + Binary => 1, + }, + 0xc363 => 'ImageRotationStatus', + 0xc364 => 'RollGuidElements', + 0xc365 => 'MetadataNumber', + 0xc366 => 'EditTagArray', + 0xc367 => 'Magnification', + # 0xc36b - string[8]: "1.0" + 0xc36c => 'NativeXResolution', + 0xc36d => 'NativeYResolution', + 0xc36e => { + Name => 'KodakEffectsIFD', + Flags => 'SubIFD', + Groups => { 1 => 'KodakEffectsIFD' }, + SubDirectory => { + TagTable => 'Image::ExifTool::Kodak::SpecialEffects', + Start => '$val', + }, + }, + 0xc36f => { + Name => 'KodakBordersIFD', + Flags => 'SubIFD', + Groups => { 1 => 'KodakBordersIFD' }, + SubDirectory => { + TagTable => 'Image::ExifTool::Kodak::Borders', + Start => '$val', + }, + }, + 0xc37a => 'NativeResolutionUnit', + 0xc418 => 'SourceImageDirectory', + 0xc419 => 'SourceImageFileName', + 0xc41a => 'SourceImageVolumeName', + 0xc46c => 'PrintQuality', + 0xc46e => 'ImagePrintStatus', + # 0cx46f - int16u: 1 +); + +# Kodak APP3 "Meta" Special Effects sub-IFD (ref 2) +%Image::ExifTool::Kodak::SpecialEffects = ( + GROUPS => { 0 => 'Meta', 1 => 'KodakEffectsIFD', 2 => 'Image'}, + WRITE_PROC => \&Image::ExifTool::Exif::WriteExif, + 0 => 'DigitalEffectsVersion', + 1 => { + Name => 'DigitalEffectsName', + PrintConv => 'Image::ExifTool::Exif::ConvertExifText($self,$val,"DigitalEffectsName")', + }, + 2 => 'DigitalEffectsType', +); + +# Kodak APP3 "Meta" Borders sub-IFD (ref 2) +%Image::ExifTool::Kodak::Borders = ( + GROUPS => { 0 => 'Meta', 1 => 'KodakBordersIFD', 2 => 'Image'}, + WRITE_PROC => \&Image::ExifTool::Exif::WriteExif, + 0 => 'BordersVersion', + 1 => { + Name => 'BorderName', + PrintConv => 'Image::ExifTool::Exif::ConvertExifText($self,$val,"BorderName")', + }, + 2 => 'BorderID', + 3 => 'BorderLocation', + 4 => 'BorderType', + 8 => 'WatermarkType', +); + +# tags in Kodak MOV videos (ref PH) +# (similar information in Kodak,Minolta,Nikon,Olympus,Pentax and Sanyo videos) +%Image::ExifTool::Kodak::MOV = ( + PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData, + GROUPS => { 0 => 'MakerNotes', 2 => 'Camera' }, + FIRST_ENTRY => 0, + NOTES => q{ + This information is found in the TAGS atom of MOV videos from Kodak models + such as the P880. + }, + 0 => { + Name => 'Make', + Format => 'string[21]', + }, + 0x16 => { + Name => 'Model', + Format => 'string[42]', + }, + 0x40 => { + Name => 'ModelType', + Format => 'string[8]', + }, + # (01 00 at offset 0x48) + 0x4e => { + Name => 'ExposureTime', + Format => 'int32u', + ValueConv => '$val ? 10 / $val : 0', + PrintConv => 'Image::ExifTool::Exif::PrintExposureTime($val)', + }, + 0x52 => { + Name => 'FNumber', + Format => 'rational64u', + PrintConv => 'sprintf("%.1f",$val)', + }, + 0x5a => { + Name => 'ExposureCompensation', + Format => 'rational64s', + PrintConv => 'Image::ExifTool::Exif::PrintFraction($val)', + }, + # 0x6c => 'WhiteBalance', ? + 0x70 => { + Name => 'FocalLength', + Format => 'rational64u', + PrintConv => 'sprintf("%.1f mm",$val)', + }, +); + +# Kodak DcMD atoms (ref PH) +%Image::ExifTool::Kodak::DcMD = ( + GROUPS => { 0 => 'MakerNotes', 2 => 'Video' }, + NOTES => 'Metadata directory found in MOV and MP4 videos from some Kodak cameras.', + Cmbo => { + Name => 'CameraByteOrder', + PrintConv => { + II => 'Little-endian (Intel, II)', + MM => 'Big-endian (Motorola, MM)', + }, + }, + CMbo => { # (as written by Kodak Playsport video camera) + Name => 'CameraByteOrder', + PrintConv => { + II => 'Little-endian (Intel, II)', + MM => 'Big-endian (Motorola, MM)', + }, + }, + DcME => { + Name => 'DcME', + SubDirectory => { + TagTable => 'Image::ExifTool::Kodak::DcME', + }, + }, + DcEM => { + Name => 'DcEM', + SubDirectory => { + TagTable => 'Image::ExifTool::Kodak::DcEM', + }, + }, +); + +# Kodak DcME atoms (ref PH) +%Image::ExifTool::Kodak::DcME = ( + GROUPS => { 0 => 'MakerNotes', 2 => 'Video' }, + # Mtmd - 24 bytes: ("00 00 00 00 00 00 00 01" x 3) + # Keyw - keywords? (six bytes all zero) + # Rate - 2 bytes: 00 00 +); + +# Kodak DcEM atoms (ref PH) +%Image::ExifTool::Kodak::DcEM = ( + GROUPS => { 0 => 'MakerNotes', 2 => 'Video' }, + # Mtmd - 24 bytes: ("00 00 00 00 00 00 00 01" x 3) + # Csat - 16 bytes: 00 06 00 00 62 00 61 00 73 00 69 00 63 00 00 00 [....b.a.s.i.c...] + # Ksre - 8 bytes: 00 01 00 00 00 00 +); + +# tags in "free" atom of Kodak M5370 MP4 videos (ref PH) +%Image::ExifTool::Kodak::Free = ( + GROUPS => { 0 => 'MakerNotes', 2 => 'Video' }, + NOTES => q{ + Information stored in the "free" atom of Kodak MP4 videos. (VERY bad form + for Kodak to store useful information in an atom intended for unused space!) + }, + # (2012/01/19: Kodak files for bankruptcy -- this is poetic metadata justice) + Seri => { + Name => 'SerialNumber', + # byte 0 is string length; byte 1 is zero; string starts at byte 2 + ValueConv => 'substr($val, 2, unpack("C",$val))', + }, + SVer => { + Name => 'FirmwareVersion', + ValueConv => 'substr($val, 2, unpack("C",$val))', + }, + # Clor - 2 bytes: 0 1 (?) + # CapM - 2 bytes: 0 1 (capture mode? = exposure mode?) + # WBMD - 2 bytes: 0 0 (white balance?) + Expc => { # (NC) + Name => 'ExposureCompensation', + Format => 'int16s', + ValueConv => '$val / 3', # (guess) + PrintConv => 'Image::ExifTool::Exif::PrintFraction($val)', + }, + # Zone - 2 bytes: 0 2 (time zone? focus zone?) + # FoMD - 2 bytes: 0 0 (focus mode?) + # Shap - 2 bytes: 0 2 (sharpness?) + Expo => { + Name => 'ExposureTime', + Format => 'rational32u', + PrintConv => 'Image::ExifTool::Exif::PrintExposureTime($val)', + }, + FNum => { + Name => 'FNumber', + Format => 'int16u', + ValueConv => '$val / 100', + PrintConv => 'Image::ExifTool::Exif::PrintFNumber($val)', + }, + ISOS => { Name => 'ISO', Format => 'int16u' }, + StSV => { + Name => 'ShutterSpeedValue', + Format => 'int16s', + ValueConv => 'abs($val)<100 ? 2**(-$val/3) : 0', + PrintConv => 'Image::ExifTool::Exif::PrintExposureTime($val)', + }, + AprV => { + Name => 'ApertureValue', + Format => 'int16s', + ValueConv => '2 ** ($val / 2000)', + PrintConv => 'sprintf("%.1f",$val)', + }, + BrtV => { # (NC) + Name => 'BrightnessValue', + Format => 'int32s', + ValueConv => '$val / 1000', # (guess) + }, + FoLn => { + Name => 'FocalLength', + Groups => { 2 => 'Camera' }, + Format => 'int16u', + PrintConv => 'sprintf("%.1f mm",$val)', + }, + FL35 => { + Name => 'FocalLengthIn35mmFormat', + Groups => { 2 => 'Camera' }, + Format => 'int16u', + PrintConv => '"$val mm"', + }, + Scrn => { + Name => 'PreviewInfo', + SubDirectory => { TagTable => 'Image::ExifTool::Kodak::Scrn' }, + }, +); + +# tags in "frea" atom of Kodak PixPro SP360 MP4 videos (ref PH) +%Image::ExifTool::Kodak::frea = ( + GROUPS => { 0 => 'MakerNotes', 2 => 'Image' }, + NOTES => 'Information stored in the "frea" atom of Kodak PixPro SP360 MP4 videos.', + tima => { + Name => 'Duration', + Format => 'int32u', + Priority => 0, # (only integer seconds) + PrintConv => 'ConvertDuration($val)', + }, + 'ver '=> { Name => 'KodakVersion' }, + thma => { Name => 'ThumbnailImage', Groups => { 2 => 'Preview' }, Binary => 1 }, + scra => { Name => 'PreviewImage', Groups => { 2 => 'Preview' }, Binary => 1 }, +); + +# preview information in free/Scrn atom of MP4 videos (ref PH) +%Image::ExifTool::Kodak::Scrn = ( + GROUPS => { 0 => 'MakerNotes', 2 => 'Image' }, + PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData, + FORMAT => 'int16u', + 0 => 'PreviewImageWidth', + 1 => 'PreviewImageHeight', + 2 => { Name => 'PreviewImageLength', Format => 'int32u' }, + 4 => { + Name => 'PreviewImage', + Groups => { 2 => 'Preview' }, + Format => 'undef[$val{2}]', + RawConv => '$self->ValidateImage(\$val, $tag)', + }, +); + +# acceleration information extracted from 'pose' atom of MP4 videos (ref PH, PixPro 4KVR360) +%Image::ExifTool::Kodak::pose = ( + GROUPS => { 0 => 'MakerNotes', 2 => 'Video' }, + PROCESS_PROC => \&ProcessPose, + NOTES => q{ + Streamed orientation information from the PixPro 4KVR360, extracted as + sub-documents when the Duplicates option is used. + }, + Accelerometer => { }, # up, back, left? units of g + AngularVelocity => { } # left, up, ccw? units? +); + +# Kodak composite tags +%Image::ExifTool::Kodak::Composite = ( + GROUPS => { 2 => 'Camera' }, + DateCreated => { + Groups => { 2 => 'Time' }, + Require => { + 0 => 'Kodak:YearCreated', + 1 => 'Kodak:MonthDayCreated', + }, + ValueConv => '"$val[0]:$val[1]"', + }, + WB_RGBLevels => { + Require => { + 0 => 'KDC_IFD:WhiteBalance', + }, + # indices of the following entries are KDC_IFD:WhiteBalance + 1 + Desire => { + 1 => 'WB_RGBLevelsAuto', + 2 => 'WB_RGBLevelsFluorescent', + 3 => 'WB_RGBLevelsTungsten', + 4 => 'WB_RGBLevelsDaylight', + 5 => 'WB_RGBLevels4', + 6 => 'WB_RGBLevels5', + 7 => 'WB_RGBLevelsShade', + }, + ValueConv => '$val[$val[0] + 1]', + }, + WB_RGBLevels2 => { + Name => 'WB_RGBLevels', + Require => { + 0 => 'KodakIFD:WhiteBalance', + 1 => 'WB_RGBMul0', + 2 => 'WB_RGBMul1', + 3 => 'WB_RGBMul2', + 4 => 'WB_RGBMul3', + 5 => 'WB_RGBCoeffs0', + 6 => 'WB_RGBCoeffs1', + 7 => 'WB_RGBCoeffs2', + 8 => 'WB_RGBCoeffs3', + }, + # indices of the following entries are KDC_IFD:WhiteBalance + 1 + Desire => { + 9 => 'KodakIFD:ColorTemperature', + 10 => 'Kodak:WB_RGBLevels', + }, + ValueConv => 'Image::ExifTool::Kodak::CalculateRGBLevels(@val)', + }, +); + +# add our composite tags +Image::ExifTool::AddCompositeTags('Image::ExifTool::Kodak'); + +#------------------------------------------------------------------------------ +# Process Kodak accelerometer data (ref PH) +# Inputs: 0) ExifTool ref, 1) dirInfo ref, 2) tag table ref +# Returns: 1 on success +sub ProcessPose($$$) +{ + my ($et, $dirInfo, $tagTablePtr) = @_; + my $dataPt = $$dirInfo{DataPt}; + my $dirLen = length $$dataPt; + my $ee = $et->Options('ExtractEmbedded'); + my ($i, $pos); + + return 0 if $dirLen < 0x14; + my $num = Get32u($dataPt, 0x10); + return 0 if $dirLen < 0x14 + $num * 24; + + $et->VerboseDir('Kodak pose', undef, $dirLen); + + $$et{DOC_NUM} = 0; + for ($i=0, $pos=0x14; $i<$num; ++$i, $pos+=24) { + $et->HandleTag($tagTablePtr, AngularVelocity => + Image::ExifTool::GetRational64s($dataPt, $pos) . ' ' . + Image::ExifTool::GetRational64s($dataPt, $pos + 8) . ' ' . + Image::ExifTool::GetRational64s($dataPt, $pos + 16)); + $ee or $pos += $num * 24, last; + ++$$et{DOC_NUM}; + } + $$et{DOC_NUM} = 0; + + return 1 if $dirLen < $pos + 0x10; + $num = Get32u($dataPt, $pos + 0x0c); + return 1 if $dirLen < $pos + 0x10 + $num * 24; + + for ($i=0, $pos+=0x10; $i<$num; ++$i, $pos+=24) { + $et->HandleTag($tagTablePtr, Accelerometer => + Image::ExifTool::GetRational64s($dataPt, $pos) . ' ' . + Image::ExifTool::GetRational64s($dataPt, $pos + 8) . ' ' . + Image::ExifTool::GetRational64s($dataPt, $pos + 16)); + $ee or $pos += $num * 24, last; + ++$$et{DOC_NUM}; + } + $$et{DOC_NUM} = 0; + $ee or $et->Warn('Use the ExtractEmbedded option to extract all accelerometer data',3); + return 1; +} + +#------------------------------------------------------------------------------ +# Calculate RGB levels from associated tags (ref 3) +# Inputs: 0) KodakIFD:WhiteBalance, 1-4) WB_RGBMul0-3, 5-8) WB_RGBCoeffs0-3 +# 9) (optional) KodakIFD:ColorTemperature, 10) (optional) Kodak:WB_RGBLevels +# Returns: WB_RGBLevels or undef +sub CalculateRGBLevels(@) +{ + return undef if $_[10]; # use existing software levels if they exist + my $wbi = $_[0]; + return undef if $wbi < 0 or $wbi > 3; + my @mul = split ' ', $_[$wbi + 1], 13; # (only use the first 12 coeffs) + my @coefs = split ' ', ${$_[$wbi + 5]}; # (extra de-reference for Binary data) + my $wbtemp100 = ($_[9] || 6500) / 100; + return undef unless @mul >= 3 and @coefs >= 12; + my ($i, $c, $n, $num, @cam_mul); + for ($c=$n=0; $c<3; ++$c) { + for ($num=$i=0; $i<4; ++$i) { + $num += $coefs[$n++] * ($wbtemp100 ** $i); + } + $cam_mul[$c] = 2048 / ($num * $mul[$c]); + } + return join(' ', @cam_mul); +} + +#------------------------------------------------------------------------------ +# Process Kodak textual TextualInfo +# Inputs: 0) ExifTool object ref, 1) dirInfo hash ref, 2) tag table ref +# Returns: 1 on success +sub ProcessKodakText($$$) +{ + my ($et, $dirInfo, $tagTablePtr) = @_; + my $dataPt = $$dirInfo{DataPt}; + my $dirStart = $$dirInfo{DirStart} || 0; + my $dirLen = $$dirInfo{DirLen} || length($$dataPt) - $dirStart; + my $data = substr($$dataPt, $dirStart, $dirLen); + $data =~ s/\0.*//s; # truncate at null if it exists + my @lines = split /[\n\r]+/, $data; + my ($line, $success, @other, $tagInfo); + $et->VerboseDir('Kodak Text'); + foreach $line (@lines) { + if ($line =~ /(.*?):\s*(.*)/) { + my ($tag, $val) = ($1, $2); + if ($$tagTablePtr{$tag}) { + $tagInfo = $et->GetTagInfo($tagTablePtr, $tag); + } else { + my $tagName = $tag; + $tagName =~ s/([A-Z])\s+([A-Za-z])/${1}_\U$2/g; + $tagName =~ s/([a-z])\s+([A-Za-z0-9])/${1}\U$2/g; + $tagName =~ s/\s+//g; + $tagName =~ s/[^-\w]+//g; # delete remaining invalid characters + $tagName = 'NoName' unless $tagName; + $tagInfo = { Name => $tagName }; + AddTagToTable($tagTablePtr, $tag, $tagInfo); + } + $et->HandleTag($tagTablePtr, $tag, $val, TagInfo => $tagInfo); + $success = 1; + } else { + # strip off leading/trailing white space and ignore blank lines + push @other, $1 if $line =~ /^\s*(\S.*?)\s*$/; + } + } + if ($success) { + if (@other) { + $tagInfo = $et->GetTagInfo($tagTablePtr, '_other_info'); + $et->FoundTag($tagInfo, \@other); + } + } else { + $et->Warn("Can't parse Kodak TextualInfo data", 1); + } + return $success; +} + +#------------------------------------------------------------------------------ +# Process Kodak IFD (with leading byte order mark) +# Inputs: 0) ExifTool object ref, 1) dirInfo hash ref, 2) tag table ref +# Returns: 1 on success, otherwise returns 0 and sets a Warning +sub ProcessKodakIFD($$$) +{ + my ($et, $dirInfo, $tagTablePtr) = @_; + my $dirStart = $$dirInfo{DirStart} || 0; + return 1 if $dirStart <= 0 or $dirStart + 2 > $$dirInfo{DataLen}; + my $byteOrder = substr(${$$dirInfo{DataPt}}, $dirStart, 2); + unless (Image::ExifTool::SetByteOrder($byteOrder)) { + $et->Warn("Invalid Kodak $$dirInfo{Name} directory"); + return 1; + } + $$dirInfo{DirStart} += 2; # skip byte order mark + $$dirInfo{DirLen} -= 2; + if ($$et{HTML_DUMP}) { + my $base = $$dirInfo{Base} + $$dirInfo{DataPos}; + $et->HDump($dirStart+$base, 2, "Byte Order Mark"); + } + return Image::ExifTool::Exif::ProcessExif($et, $dirInfo, $tagTablePtr); +} + +#------------------------------------------------------------------------------ +# Write Kodak IFD (with leading byte order mark) +# Inputs: 0) ExifTool object ref, 1) source dirInfo ref, 2) tag table ref +# Returns: Exif data block (may be empty if no Exif data) or undef on error +sub WriteKodakIFD($$$) +{ + my ($et, $dirInfo, $tagTablePtr) = @_; + my $dirStart = $$dirInfo{DirStart} || 0; + return '' if $dirStart <= 0 or $dirStart + 2 > $$dirInfo{DataLen}; + my $byteOrder = substr(${$$dirInfo{DataPt}}, $dirStart, 2); + return '' unless Image::ExifTool::SetByteOrder($byteOrder); + $$dirInfo{DirStart} += 2; # skip byte order mark + $$dirInfo{DirLen} -= 2; + my $buff = Image::ExifTool::Exif::WriteExif($et, $dirInfo, $tagTablePtr); + return $buff unless defined $buff and length $buff; + # apply one-time fixup for length of byte order mark + if ($$dirInfo{Fixup}) { + $dirInfo->{Fixup}->{Shift} += 2; + $$dirInfo{Fixup}->ApplyFixup(\$buff); + delete $$dirInfo{Fixup}; + } + return Image::ExifTool::GetByteOrder() . $buff; +} + +1; # end + +__END__ + +=head1 NAME + +Image::ExifTool::Kodak - Kodak EXIF maker notes and APP3 "Meta" tags + +=head1 SYNOPSIS + +This module is loaded automatically by Image::ExifTool when required. + +=head1 DESCRIPTION + +This module contains definitions required by Image::ExifTool to +interpret Kodak maker notes EXIF meta information. + +=head1 AUTHOR + +Copyright 2003-2019, Phil Harvey (phil at owl.phy.queensu.ca) + +This library is free software; you can redistribute it and/or modify it +under the same terms as Perl itself. + +=head1 REFERENCES + +=over 4 + +=item L<Image::MetaData::JPEG|Image::MetaData::JPEG> + +=item L<http://www.ozhiker.com/electronics/pjmt/jpeg_info/meta.html> + +=item L<http://www.cybercom.net/~dcoffin/dcraw/> + +=item (...plus lots of testing with my daughter's CX4200!) + +=back + +=head1 SEE ALSO + +L<Image::ExifTool::TagNames/Kodak Tags>, +L<Image::ExifTool(3pm)|Image::ExifTool> + +=cut diff --git a/lib/Image/ExifTool/KyoceraRaw.pm b/lib/Image/ExifTool/KyoceraRaw.pm new file mode 100644 index 0000000..52074b6 --- /dev/null +++ b/lib/Image/ExifTool/KyoceraRaw.pm @@ -0,0 +1,173 @@ +#------------------------------------------------------------------------------ +# File: KyoceraRaw.pm +# +# Description: Read Kyocera RAW meta information +# +# Revisions: 02/17/2006 - P. Harvey Created +# +# References: 1) http://www.cybercom.net/~dcoffin/dcraw/ +#------------------------------------------------------------------------------ + +package Image::ExifTool::KyoceraRaw; + +use strict; +use vars qw($VERSION); +use Image::ExifTool qw(:DataAccess :Utils); + +$VERSION = '1.03'; + +sub ProcessRAW($$); + +# utility to reverse order of characters in a string +sub ReverseString($) { pack('C*',reverse unpack('C*',shift)) } + +# Contax N Digital tags (ref PH) +%Image::ExifTool::KyoceraRaw::Main = ( + PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData, + GROUPS => { 0 => 'MakerNotes', 2 => 'Camera' }, + NOTES => 'Tags for Kyocera Contax N Digital RAW images.', + 0x01 => { + Name => 'FirmwareVersion', + Format => 'string[10]', + ValueConv => \&ReverseString, + }, + 0x0c => { + Name => 'Model', + Format => 'string[12]', + ValueConv => \&ReverseString, + }, + 0x19 => { #1 + Name => 'Make', + Format => 'string[7]', + ValueConv => \&ReverseString, + }, + 0x21 => { #1 + Name => 'DateTimeOriginal', + Description => 'Date/Time Original', + Groups => { 2 => 'Time' }, + Format => 'string[20]', + ValueConv => \&ReverseString, + PrintConv => '$self->ConvertDateTime($val)', + }, + 0x34 => { + Name => 'ISO', + Groups => { 2 => 'Image' }, + Format => 'int32u', + PrintConv => { + 7 => 25, + 8 => 32, + 9 => 40, + 10 => 50, + 11 => 64, + 12 => 80, + 13 => 100, + 14 => 125, + 15 => 160, + 16 => 200, + 17 => 250, + 18 => 320, + 19 => 400, + }, + }, + 0x38 => { + Name => 'ExposureTime', + Groups => { 2 => 'Image' }, + Format => 'int32u', + ValueConv => '2**($val / 8) / 16000', + PrintConv => 'Image::ExifTool::Exif::PrintExposureTime($val)', + }, + 0x3c => { #1 + Name => 'WB_RGGBLevels', + Groups => { 2 => 'Image' }, + Format => 'int32u[4]', + }, + 0x58 => { + Name => 'FNumber', + Groups => { 2 => 'Image' }, + Format => 'int32u', + ValueConv => '2**($val/16)', + PrintConv => 'sprintf("%.2g",$val)', + }, + 0x68 => { + Name => 'MaxAperture', + Format => 'int32u', + ValueConv => '2**($val/16)', + PrintConv => 'sprintf("%.2g",$val)', + }, + 0x70 => { + Name => 'FocalLength', + Format => 'int32u', + PrintConv => '"$val mm"', + }, + 0x7c => { + Name => 'Lens', + Format => 'string[32]', + }, +); + +#------------------------------------------------------------------------------ +# Extract information from Kyocera RAW image +# Inputs: 0) ExifTool object reference, 1) dirInfo reference +# Returns: 1 if this was a valid Kyocera RAW image +sub ProcessRAW($$) +{ + my ($et, $dirInfo) = @_; + my $raf = $$dirInfo{RAF}; + my $size = 156; # size of header + my $buff; + + $raf->Read($buff, $size) == $size or return 0; + # validate Make string ('KYOCERA' reversed) + substr($buff, 0x19, 7) eq 'ARECOYK' or return 0; + $et->SetFileType(); + SetByteOrder('MM'); + my %dirInfo = ( + DataPt => \$buff, + DataPos => 0, + DataLen => $size, + DirStart => 0, + DirLen => $size, + ); + my $tagTablePtr = GetTagTable('Image::ExifTool::KyoceraRaw::Main'); + $et->ProcessDirectory(\%dirInfo, $tagTablePtr); + return 1; +} + +1; # end + +__END__ + +=head1 NAME + +Image::ExifTool::KyoceraRaw - Read Kyocera RAW meta information + +=head1 SYNOPSIS + +This module is loaded automatically by Image::ExifTool when required. + +=head1 DESCRIPTION + +This module contains definitions required by Image::ExifTool to read +meta information from Kyocera Contax N Digital RAW images. + +=head1 AUTHOR + +Copyright 2003-2019, Phil Harvey (phil at owl.phy.queensu.ca) + +This library is free software; you can redistribute it and/or modify it +under the same terms as Perl itself. + +=head1 REFERENCES + +=over 4 + +=item L<http://www.cybercom.net/~dcoffin/dcraw/> + +=back + +=head1 SEE ALSO + +L<Image::ExifTool::TagNames/KyoceraRaw Tags>, +L<Image::ExifTool(3pm)|Image::ExifTool> + +=cut diff --git a/lib/Image/ExifTool/LNK.pm b/lib/Image/ExifTool/LNK.pm new file mode 100644 index 0000000..c553620 --- /dev/null +++ b/lib/Image/ExifTool/LNK.pm @@ -0,0 +1,723 @@ +#------------------------------------------------------------------------------ +# File: LNK.pm +# +# Description: Read meta information from MS Shell Link files +# +# Revisions: 2009/09/19 - P. Harvey Created +# +# References: 1) http://msdn.microsoft.com/en-us/library/dd871305(PROT.10).aspx +# 2) http://www.i2s-lab.com/Papers/The_Windows_Shortcut_File_Format.pdf +#------------------------------------------------------------------------------ + +package Image::ExifTool::LNK; + +use strict; +use vars qw($VERSION); +use Image::ExifTool qw(:DataAccess :Utils); + +$VERSION = '1.07'; + +sub ProcessItemID($$$); +sub ProcessLinkInfo($$$); + +# Information extracted from LNK (Windows Shortcut) files +%Image::ExifTool::LNK::Main = ( + PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData, + GROUPS => { 2 => 'Other' }, + VARS => { HEX_ID => 1 }, # print hex ID's in documentation + NOTES => 'Information extracted from MS Shell Link (Windows shortcut) files.', + # maybe the Flags aren't very useful to the user (since they are + # mainly structural), but extract them anyway for completeness + 0x14 => { + Name => 'Flags', + Format => 'int32u', + PrintConv => { BITMASK => { + 0 => 'IDList', + 1 => 'LinkInfo', + 2 => 'Description', + 3 => 'RelativePath', + 4 => 'WorkingDir', + 5 => 'CommandArgs', + 6 => 'IconFile', + 7 => 'Unicode', + 8 => 'NoLinkInfo', + 9 => 'ExpString', + 10 => 'SeparateProc', + 12 => 'DarwinID', + 13 => 'RunAsUser', + 14 => 'ExpIcon', + 15 => 'NoPidAlias', + 17 => 'RunWithShim', + 18 => 'NoLinkTrack', + 19 => 'TargetMetadata', + 20 => 'NoLinkPathTracking', + 21 => 'NoKnownFolderTracking', + 22 => 'NoKnownFolderAlias', + 23 => 'LinkToLink', + 24 => 'UnaliasOnSave', + 25 => 'PreferEnvPath', + 26 => 'KeepLocalIDList', + }}, + }, + 0x18 => { + Name => 'FileAttributes', + Format => 'int32u', + PrintConv => { BITMASK => { + 0 => 'Read-only', + 1 => 'Hidden', + 2 => 'System', + 3 => 'Volume', #(not used) + 4 => 'Directory', + 5 => 'Archive', + 6 => 'Encrypted?', #(ref 2, not used in XP) + 7 => 'Normal', + 8 => 'Temporary', + 9 => 'Sparse', + 10 => 'Reparse point', + 11 => 'Compressed', + 12 => 'Offline', + 13 => 'Not indexed', + 14 => 'Encrypted', + }}, + }, + 0x1c => { + Name => 'CreateDate', + Format => 'int64u', + Groups => { 2 => 'Time' }, + # convert time from 100-ns intervals since Jan 1, 1601 + RawConv => '$val ? $val : undef', + ValueConv => '$val=$val/1e7-11644473600; ConvertUnixTime($val,1)', + PrintConv => '$self->ConvertDateTime($val)', + }, + 0x24 => { + Name => 'AccessDate', + Format => 'int64u', + Groups => { 2 => 'Time' }, + RawConv => '$val ? $val : undef', + ValueConv => '$val=$val/1e7-11644473600; ConvertUnixTime($val,1)', + PrintConv => '$self->ConvertDateTime($val)', + }, + 0x2c => { + Name => 'ModifyDate', + Format => 'int64u', + Groups => { 2 => 'Time' }, + RawConv => '$val ? $val : undef', + ValueConv => '$val=$val/1e7-11644473600; ConvertUnixTime($val,1)', + PrintConv => '$self->ConvertDateTime($val)', + }, + 0x34 => { + Name => 'TargetFileSize', + Format => 'int32u', + }, + 0x38 => { + Name => 'IconIndex', + Format => 'int32u', + PrintConv => '$val ? $val : "(none)"', + }, + 0x3c => { + Name => 'RunWindow', + Format => 'int32u', + PrintConv => { + 0 => 'Hide', + 1 => 'Normal', + 2 => 'Show Minimized', + 3 => 'Show Maximized', + 4 => 'Show No Activate', + 5 => 'Show', + 6 => 'Minimized', + 7 => 'Show Minimized No Activate', + 8 => 'Show NA', + 9 => 'Restore', + 10 => 'Show Default', + }, + }, + 0x40 => { + Name => 'HotKey', + Format => 'int32u', + PrintHex => 1, + PrintConv => { + OTHER => sub { + my $val = shift; + my $ch = $val & 0xff; + if (chr $ch =~ /^[A-Z0-9]$/) { + $ch = chr $ch; + } elsif ($ch >= 0x70 and $ch <= 0x87) { + $ch = 'F' . ($ch - 0x6f); + } elsif ($ch == 0x90) { + $ch = 'Num Lock'; + } elsif ($ch == 0x91) { + $ch = 'Scroll Lock'; + } else { + $ch = sprintf('Unknown (0x%x)', $ch); + } + $ch = "Alt-$ch" if $val & 0x400; + $ch = "Control-$ch" if $val & 0x200; + $ch = "Shift-$ch" if $val & 0x100; + return $ch; + }, + 0x00 => '(none)', + # these entries really only for documentation + 0x90 => 'Num Lock', + 0x91 => 'Scroll Lock', + "0x30'-'0x39" => "0-9", + "0x41'-'0x5a" => "A-Z", + "0x70'-'0x87" => "F1-F24", + 0x100 => 'Shift', + 0x200 => 'Control', + 0x400 => 'Alt', + }, + }, + # note: tags 0x10xx are synthesized tag ID's + 0x10000 => { + Name => 'ItemID', + SubDirectory => { TagTable => 'Image::ExifTool::LNK::ItemID' }, + }, + 0x20000 => { + Name => 'LinkInfo', + SubDirectory => { TagTable => 'Image::ExifTool::LNK::LinkInfo' }, + }, + 0x30004 => 'Description', + 0x30008 => 'RelativePath', + 0x30010 => 'WorkingDirectory', + 0x30020 => 'CommandLineArguments', + 0x30040 => 'IconFileName', + # note: tags 0xa000000x are actually ID's (not indices) + 0xa0000000 => { + Name => 'UnknownData', + SubDirectory => { TagTable => 'Image::ExifTool::LNK::UnknownData' }, + }, + 0xa0000001 => { + Name => 'EnvVarData', + SubDirectory => { TagTable => 'Image::ExifTool::LNK::UnknownData' }, + }, + 0xa0000002 => { + Name => 'ConsoleData', + SubDirectory => { TagTable => 'Image::ExifTool::LNK::ConsoleData' }, + }, + 0xa0000003 => { + Name => 'TrackerData', + SubDirectory => { TagTable => 'Image::ExifTool::LNK::TrackerData' }, + }, + 0xa0000004 => { + Name => 'ConsoleFEData', + SubDirectory => { TagTable => 'Image::ExifTool::LNK::ConsoleFEData' }, + }, + 0xa0000005 => { + Name => 'SpecialFolderData', + SubDirectory => { TagTable => 'Image::ExifTool::LNK::UnknownData' }, + }, + 0xa0000006 => { + Name => 'DarwinData', + SubDirectory => { TagTable => 'Image::ExifTool::LNK::UnknownData' }, + }, + 0xa0000007 => { + Name => 'IconEnvData', + SubDirectory => { TagTable => 'Image::ExifTool::LNK::UnknownData' }, + }, + 0xa0000008 => { + Name => 'ShimData', + SubDirectory => { TagTable => 'Image::ExifTool::LNK::UnknownData' }, + }, + 0xa0000009 => { + Name => 'PropertyStoreData', + SubDirectory => { TagTable => 'Image::ExifTool::LNK::UnknownData' }, + }, + 0xa000000b => { + Name => 'KnownFolderData', + SubDirectory => { TagTable => 'Image::ExifTool::LNK::UnknownData' }, + }, + 0xa000000c => { + Name => 'VistaIDListData', + SubDirectory => { TagTable => 'Image::ExifTool::LNK::UnknownData' }, + }, +); + +%Image::ExifTool::LNK::ItemID = ( + GROUPS => { 2 => 'Other' }, + PROCESS_PROC => \&ProcessItemID, + # (can't find any documentation on these items) + 0x0032 => { + Name => 'Item0032', + SubDirectory => { TagTable => 'Image::ExifTool::LNK::Item0032' }, + }, +); + +%Image::ExifTool::LNK::Item0032 = ( + GROUPS => { 2 => 'Other' }, + PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData, + 0x0e => { + Name => 'TargetFileDOSName', + Format => 'var_string', + }, + #not at a fixed offset -- offset is given by last 2 bytes of the item + 0x14 + #0x22 => { + # Name => 'TargetFileName', + # Format => 'var_ustring', + #}, +); + +%Image::ExifTool::LNK::LinkInfo = ( + GROUPS => { 2 => 'Other' }, + PROCESS_PROC => \&ProcessLinkInfo, + FORMAT => 'int32u', + VARS => { NO_ID => 1 }, + VolumeID => { }, + DriveType => { + PrintConv => { + 0 => 'Unknown', + 1 => 'Invalid Root Path', + 2 => 'Removable Media', + 3 => 'Fixed Disk', + 4 => 'Remote Drive', + 5 => 'CD-ROM', + 6 => 'Ram Disk', + }, + }, + DriveSerialNumber => { }, + VolumeLabel => { }, + LocalBasePath => { }, + CommonNetworkRelLink => { }, + CommonPathSuffix => { }, + NetName => { }, + DeviceName => { }, + NetProviderType => { + PrintHex => 1, + PrintConv => { + 0x1a0000 => 'AVID', + 0x1b0000 => 'DOCUSPACE', + 0x1c0000 => 'MANGOSOFT', + 0x1d0000 => 'SERNET', + 0x1e0000 => 'RIVERFRONT1', + 0x1f0000 => 'RIVERFRONT2', + 0x200000 => 'DECORB', + 0x210000 => 'PROTSTOR', + 0x220000 => 'FJ_REDIR', + 0x230000 => 'DISTINCT', + 0x240000 => 'TWINS', + 0x250000 => 'RDR2SAMPLE', + 0x260000 => 'CSC', + 0x270000 => '3IN1', + 0x290000 => 'EXTENDNET', + 0x2a0000 => 'STAC', + 0x2b0000 => 'FOXBAT', + 0x2c0000 => 'YAHOO', + 0x2d0000 => 'EXIFS', + 0x2e0000 => 'DAV', + 0x2f0000 => 'KNOWARE', + 0x300000 => 'OBJECT_DIRE', + 0x310000 => 'MASFAX', + 0x320000 => 'HOB_NFS', + 0x330000 => 'SHIVA', + 0x340000 => 'IBMAL', + 0x350000 => 'LOCK', + 0x360000 => 'TERMSRV', + 0x370000 => 'SRT', + 0x380000 => 'QUINCY', + 0x390000 => 'OPENAFS', + 0x3a0000 => 'AVID1', + 0x3b0000 => 'DFS', + }, + }, +); + +%Image::ExifTool::LNK::UnknownData = ( + PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData, + GROUPS => { 2 => 'Other' }, +); + +%Image::ExifTool::LNK::ConsoleData = ( + PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData, + GROUPS => { 2 => 'Other' }, + 0x08 => { + Name => 'FillAttributes', + Format => 'int16u', + PrintConv => 'sprintf("0x%.2x", $val)', + }, + 0x0a => { + Name => 'PopupFillAttributes', + Format => 'int16u', + PrintConv => 'sprintf("0x%.2x", $val)', + }, + 0x0c => { + Name => 'ScreenBufferSize', + Format => 'int16u[2]', + PrintConv => '$val=~s/ / x /; $val', + }, + 0x10 => { + Name => 'WindowSize', + Format => 'int16u[2]', + PrintConv => '$val=~s/ / x /; $val', + }, + 0x14 => { + Name => 'WindowOrigin', + Format => 'int16u[2]', + PrintConv => '$val=~s/ / x /; $val', + }, + 0x20 => { + Name => 'FontSize', + Format => 'int16u[2]', + PrintConv => '$val=~s/ / x /; $val', + }, + 0x24 => { + Name => 'FontFamily', + Format => 'int32u', + PrintHex => 1, + PrintConv => { + 0 => "Don't Care", + 0x10 => 'Roman', + 0x20 => 'Swiss', + 0x30 => 'Modern', + 0x40 => 'Script', + 0x50 => 'Decorative', + }, + }, + 0x28 => { + Name => 'FontWeight', + Format => 'int32u', + }, + 0x2c => { + Name => 'FontName', + Format => 'undef[64]', + RawConv => q{ + $val = $self->Decode($val, 'UCS2'); + $val =~ s/\0.*//s; + return length($val) ? $val : undef; + }, + }, + 0x6c => { + Name => 'CursorSize', + Format => 'int32u', + }, + 0x70 => { + Name => 'FullScreen', + Format => 'int32u', + PrintConv => '$val ? "Yes" : "No"', + }, + 0x74 => { #PH (MISSING FROM MS DOCUMENTATION! -- screws up subsequent offsets) + Name => 'QuickEdit', + Format => 'int32u', + PrintConv => '$val ? "Yes" : "No"', + }, + 0x78 => { + Name => 'InsertMode', + Format => 'int32u', + PrintConv => '$val ? "Yes" : "No"', + }, + 0x7c => { + Name => 'WindowOriginAuto', + Format => 'int32u', + PrintConv => '$val ? "Yes" : "No"', + }, + 0x80 => { + Name => 'HistoryBufferSize', + Format => 'int32u', + }, + 0x84 => { + Name => 'NumHistoryBuffers', + Format => 'int32u', + }, + 0x88 => { + Name => 'RemoveHistoryDuplicates', + Format => 'int32u', + PrintConv => '$val ? "Yes" : "No"', + }, +); + +%Image::ExifTool::LNK::TrackerData = ( + PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData, + GROUPS => { 2 => 'Other' }, + 0x10 => { + Name => 'MachineID', + Format => 'var_string', + }, +); + +%Image::ExifTool::LNK::ConsoleFEData = ( + PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData, + GROUPS => { 2 => 'Other' }, + 0x08 => { + Name => 'CodePage', + Format => 'int32u', + }, +); + +#------------------------------------------------------------------------------ +# Extract null-terminated ASCII or Unicode string from buffer +# Inputs: 0) buffer ref, 1) start position, 2) flag for unicode string +# Return: string or undef if start position is outside bounds +sub GetString($$;$) +{ + my ($dataPt, $pos, $unicode) = @_; + return undef if $pos >= length($$dataPt); + pos($$dataPt) = $pos; + return $1 if ($unicode ? $$dataPt=~/\G((?:..)*?)\0\0/sg : $$dataPt=~/\G(.*?)\0/sg); + return substr($$dataPt, $pos); +} + +#------------------------------------------------------------------------------ +# Process item ID data +# Inputs: 0) ExifTool object reference, 1) dirInfo reference, 2) tag table ref +# Returns: 1 on success +sub ProcessItemID($$$) +{ + my ($et, $dirInfo, $tagTablePtr) = @_; + my $dataPt = $$dirInfo{DataPt}; + my $dataLen = length $$dataPt; + my $pos = 0; + my %opts = ( + DataPt => $dataPt, + DataPos => $$dirInfo{DataPos}, + ); + $et->VerboseDir('ItemID', undef, $dataLen); + for (;;) { + last if $pos + 4 >= $dataLen; + my $size = Get16u($dataPt, $pos); + last if $size < 2 or $pos + $size > $dataLen; + my $tag = Get16u($dataPt, $pos+2); # (just a guess -- may not be a tag at all) + AddTagToTable($tagTablePtr, $tag, { + Name => sprintf('Item%.4x', $tag), + SubDirectory => { TagTable => 'Image::ExifTool::LNK::UnknownData' }, + }) unless $$tagTablePtr{$tag}; + $et->HandleTag($tagTablePtr, $tag, undef, %opts, Start => $pos, Size => $size); + $pos += $size; + } +} + +#------------------------------------------------------------------------------ +# Process link information data +# Inputs: 0) ExifTool object reference, 1) dirInfo reference, 2) tag table ref +# Returns: 1 on success +sub ProcessLinkInfo($$$) +{ + my ($et, $dirInfo, $tagTablePtr) = @_; + my $dataPt = $$dirInfo{DataPt}; + my $dataLen = length $$dataPt; + return 0 if $dataLen < 0x20; + my $hdrLen = Get32u($dataPt, 4); + my $lif = Get32u($dataPt, 8); # link info flags + my %opts = ( + DataPt => $dataPt, + DataPos => $$dirInfo{DataPos}, + Size => 4, # (typical value size) + ); + my ($off, $unicode, $pos, $val, $size); + $et->VerboseDir('LinkInfo', undef, $dataLen); + if ($lif & 0x01) { + # read Volume ID + $off = Get32u($dataPt, 0x0c); + if ($off + 0x20 <= $dataLen) { + # my $len = Get32u($dataPt, $off); + $et->HandleTag($tagTablePtr, 'DriveType', undef, %opts, Start=>$off+4); + $pos = Get32u($dataPt, $off + 0x0c); + if ($pos == 0x14) { + # use VolumeLabelOffsetUnicode instead + $pos = Get32u($dataPt, $off + 0x10); + $unicode = 1; + } + $pos += $off; + $val = GetString($dataPt, $pos, $unicode); + if (defined $val) { + $size = length $val; + $val = $et->Decode($val, 'UCS2') if $unicode; + $et->HandleTag($tagTablePtr, 'VolumeLabel', $val, %opts, Start=>$pos, Size=>$size); + } + } + # read local base path + if ($hdrLen >= 0x24) { + $pos = Get32u($dataPt, 0x1c); + $unicode = 1; + } else { + $pos = Get32u($dataPt, 0x10); + undef $unicode; + } + $val = GetString($dataPt, $pos, $unicode); + if (defined $val) { + $size = length $val; + $val = $et->Decode($val, 'UCS2') if $unicode; + $et->HandleTag($tagTablePtr, 'LocalBasePath', $val, %opts, Start=>$pos, Size=>$size); + } + } + if ($lif & 0x02) { + # read common network relative link + $off = Get32u($dataPt, 0x14); + if ($off and $off + 0x14 <= $dataLen) { + my $siz = Get32u($dataPt, $off); + $pos = Get32u($dataPt, $off + 0x08); + if ($pos > 0x14 and $siz >= 0x18) { + $pos = Get32u($dataPt, $off + 0x14); + $unicode = 1; + } else { + undef $unicode; + } + $val = GetString($dataPt, $pos, $unicode); + if (defined $val) { + $size = length $val; + $val = $et->Decode($val, 'UCS2') if $unicode; + $et->HandleTag($tagTablePtr, 'NetName', $val, %opts, Start=>$pos, Size=>$size); + } + my $flg = Get32u($dataPt, $off + 0x04); + if ($flg & 0x01) { + $pos = Get32u($dataPt, $off + 0x0c); + if ($pos > 0x14 and $siz >= 0x1c) { + $pos = Get32u($dataPt, $off + 0x18); + $unicode = 1; + } else { + undef $unicode; + } + $val = GetString($dataPt, $pos, $unicode); + if (defined $val) { + $size = length $val; + $val = $et->Decode($val, 'UCS2') if $unicode; + $et->HandleTag($tagTablePtr, 'DeviceName', $val, %opts, Start=>$pos, Size=>$size); + } + } + if ($flg & 0x02) { + $val = Get32u($dataPt, $off + 0x10); + $et->HandleTag($tagTablePtr, 'NetProviderType', $val, %opts, Start=>$off + 0x10); + } + } + } + return 1; +} + +#------------------------------------------------------------------------------ +# Extract information from a MS Shell Link (Windows shortcut) file +# Inputs: 0) ExifTool object reference, 1) dirInfo reference +# Returns: 1 on success, 0 if this wasn't a valid LNK file +sub ProcessLNK($$) +{ + my ($et, $dirInfo) = @_; + my $raf = $$dirInfo{RAF}; + my ($buff, $buf2, $len, $i); + + # read LNK file header + $raf->Read($buff, 0x4c) == 0x4c or return 0; + $buff =~ /^.{4}\x01\x14\x02\0{5}\xc0\0{6}\x46/s or return 0; + $len = unpack('V', $buff); + $len >= 0x4c or return 0; + if ($len > 0x4c) { + $raf->Read($buf2, $len - 0x4c) == $len - 0x4c or return 0; + $buff .= $buf2; + } + $et->SetFileType(); + SetByteOrder('II'); + + my $tagTablePtr = GetTagTable('Image::ExifTool::LNK::Main'); + my %dirInfo = ( + DataPt => \$buff, + DataPos => 0, + DataLen => length $buff, + DirLen => length $buff, + ); + $et->ProcessDirectory(\%dirInfo, $tagTablePtr); + + my $flags = Get32u(\$buff, 0x14); + + # read link target ID list + if ($flags & 0x01) { + $raf->Read($buff, 2) or return 1; + $len = unpack('v', $buff); + $raf->Read($buff, $len) == $len or return 1; + $et->HandleTag($tagTablePtr, 0x10000, undef, + DataPt => \$buff, + DataPos => $raf->Tell() - $len, + Size => $len, + ); + } + + # read link information + if ($flags & 0x02) { + $raf->Read($buff, 4) or return 1; + $len = unpack('V', $buff); + return 1 if $len < 4; + $raf->Read($buf2, $len - 4) == $len - 4 or return 1; + $buff .= $buf2; + $et->HandleTag($tagTablePtr, 0x20000, undef, + DataPt => \$buff, + DataPos => $raf->Tell() - $len, + Size => $len, + ); + } + + # read string data + my @strings = qw(Description RelativePath WorkingDirectory + CommandLineArguments IconFileName); + for ($i=0; $i<@strings; ++$i) { + my $mask = 0x04 << $i; + next unless $flags & $mask; + $raf->Read($buff, 2) or return 1; + $len = unpack('v', $buff); + $len *= 2 if $flags & 0x80; # characters are 2 bytes if Unicode flag is set + $raf->Read($buff, $len) or return 1; + my $val; + $val = $et->Decode($buff, 'UCS2') if $flags & 0x80; + $et->HandleTag($tagTablePtr, 0x30000 | $mask, $val, + DataPt => \$buff, + DataPos => $raf->Tell() - $len, + Size => $len, + ); + } + + # read extra data + while ($raf->Read($buff, 4) == 4) { + $len = unpack('V', $buff); + last if $len < 4; + $len -= 4; + $raf->Read($buf2, $len) == $len or last; + next unless $len > 4; + $buff .= $buf2; + my $tag = Get32u(\$buff, 4); + my $tagInfo = $$tagTablePtr{$tag}; + unless (ref $tagInfo eq 'HASH' and $$tagInfo{SubDirectory}) { + $tagInfo = $$tagTablePtr{0xa0000000}; + } + $et->HandleTag($tagTablePtr, $tag, undef, + DataPt => \$buff, + DataPos => $raf->Tell() - $len - 4, + TagInfo => $tagInfo, + ); + } + return 1; +} + +1; # end + +__END__ + +=head1 NAME + +Image::ExifTool::LNK - Read MS Shell Link (.LNK) meta information + +=head1 SYNOPSIS + +This module is used by Image::ExifTool + +=head1 DESCRIPTION + +This module contains definitions required by Image::ExifTool to extract meta +information MS Shell Link (Windows shortcut) files. + +=head1 AUTHOR + +Copyright 2003-2019, Phil Harvey (phil at owl.phy.queensu.ca) + +This library is free software; you can redistribute it and/or modify it +under the same terms as Perl itself. + +=head1 REFERENCES + +=over 4 + +=item L<http://msdn.microsoft.com/en-us/library/dd871305(PROT.10).aspx> + +=item L<http://www.i2s-lab.com/Papers/The_Windows_Shortcut_File_Format.pdf> + +=back + +=head1 SEE ALSO + +L<Image::ExifTool::TagNames/LNK Tags>, +L<Image::ExifTool(3pm)|Image::ExifTool> + +=cut + diff --git a/lib/Image/ExifTool/Lang/cs.pm b/lib/Image/ExifTool/Lang/cs.pm new file mode 100644 index 0000000..85dd7e6 --- /dev/null +++ b/lib/Image/ExifTool/Lang/cs.pm @@ -0,0 +1,1588 @@ +#------------------------------------------------------------------------------ +# File: cs.pm +# +# Description: ExifTool Czech language translations +# +# Notes: This file generated automatically by Image::ExifTool::TagInfoXML +#------------------------------------------------------------------------------ + +package Image::ExifTool::Lang::cs; + +use strict; +use vars qw($VERSION); + +$VERSION = '1.07'; + +%Image::ExifTool::Lang::cs::Translate = ( + 'AEMeteringMode' => { + PrintConv => { + 'Multi-segment' => 'Multi segment', + }, + }, + 'AEProgramMode' => { + PrintConv => { + 'Landscape' => 'Krajina', + 'Macro' => 'Makro', + 'Portrait' => 'Portrét', + }, + }, + 'AFPoint' => { + PrintConv => { + 'None' => 'Žádná', + }, + }, + 'AFPointBrightness' => { + PrintConv => { + 'Normal' => 'Normální', + }, + }, + 'AFPointSelectionMethod' => { + PrintConv => { + 'Normal' => 'Normální', + }, + }, + 'AFPointsInFocus' => { + PrintConv => { + 'None' => 'Žádná', + }, + }, + 'APEVersion' => 'APE verze', + 'ActiveD-Lighting' => { + PrintConv => { + 'Low' => 'Méně', + 'Normal' => 'Normální', + }, + }, + 'ActiveD-LightingMode' => { + PrintConv => { + 'Low' => 'Méně', + 'Normal' => 'Normální', + }, + }, + 'AdultContentWarning' => { + PrintConv => { + 'Unknown' => 'Neznámý', + }, + }, + 'Annotations' => 'Poznámky Photoshop', + 'Aperture' => 'Clona', + 'ApertureValue' => 'Clona', + 'Artist' => 'Autor', + 'AssistButtonFunction' => { + PrintConv => { + 'Normal' => 'Normální', + }, + }, + 'Author' => 'Autor', + 'AuthorsPosition' => 'Pozice autora', + 'AutoLightingOptimizer' => { + PrintConv => { + 'Low' => 'Méně', + }, + }, + 'AutoRotate' => { + PrintConv => { + 'None' => 'Žádná', + 'Rotate 180' => '180° (dolů/vpravo)', + 'Rotate 270 CW' => '90° po směru HR (vlevo/dolů)', + 'Rotate 90 CW' => '90° ptoti směru HR (vpravo/nahoru)', + 'n/a' => 'Neznámý', + }, + }, + 'BadFaxLines' => 'Špatné faxové řádky', + 'BannerImageType' => { + PrintConv => { + 'None' => 'Žádná', + }, + }, + 'BatteryLevel' => 'Stav baterie', + 'BitsPerSample' => 'Počet bitů na složku', + 'BlurWarning' => { + PrintConv => { + 'None' => 'Žádná', + }, + }, + 'Brightness' => 'Jas', + 'BrightnessValue' => 'Jas', + 'By-line' => 'Autor', + 'CFAPattern' => 'CFA matrice', + 'CFAPattern2' => 'CFA matice 2', + 'CFARepeatPatternDim' => 'Velikost berevné matice CFA', + 'CPUType' => { + PrintConv => { + 'None' => 'Žádná', + }, + }, + 'CalibrationIlluminant1' => { + PrintConv => { + 'Cloudy' => 'Zataženo', + 'Cool White Fluorescent' => 'Studená zářivka', + 'Day White Fluorescent' => 'Denní zářivka', + 'Daylight' => 'Denní světlo', + 'Daylight Fluorescent' => 'Denní světlo', + 'Fine Weather' => 'Slunečno', + 'Flash' => 'Blesk', + 'Fluorescent' => 'Žárovka', + 'ISO Studio Tungsten' => 'Studiová světla', + 'Other' => 'Jiné osvětlení', + 'Shade' => 'Stíny', + 'Standard Light A' => 'Standardní světlo A', + 'Standard Light B' => 'Standardní světlo B', + 'Standard Light C' => 'Standardní světlo C', + 'Tungsten (Incandescent)' => 'Zářivka', + 'Unknown' => 'Neznámý', + 'White Fluorescent' => 'Bílá zářivka', + }, + }, + 'CalibrationIlluminant2' => { + PrintConv => { + 'Cloudy' => 'Zataženo', + 'Cool White Fluorescent' => 'Studená zářivka', + 'Day White Fluorescent' => 'Denní zářivka', + 'Daylight' => 'Denní světlo', + 'Daylight Fluorescent' => 'Denní světlo', + 'Fine Weather' => 'Slunečno', + 'Flash' => 'Blesk', + 'Fluorescent' => 'Žárovka', + 'ISO Studio Tungsten' => 'Studiová světla', + 'Other' => 'Jiné osvětlení', + 'Shade' => 'Stíny', + 'Standard Light A' => 'Standardní světlo A', + 'Standard Light B' => 'Standardní světlo B', + 'Standard Light C' => 'Standardní světlo C', + 'Tungsten (Incandescent)' => 'Zářivka', + 'Unknown' => 'Neznámý', + 'White Fluorescent' => 'Bílá zářivka', + }, + }, + 'CameraOrientation' => { + Description => 'Orientace', + PrintConv => { + 'Horizontal (normal)' => '0° (nahoru/vlevo)', + 'Rotate 270 CW' => '90° po směru HR (vlevo/dolů)', + 'Rotate 90 CW' => '90° ptoti směru HR (vpravo/nahoru)', + }, + }, + 'CanonExposureMode' => { + PrintConv => { + 'Aperture-priority AE' => 'Priorita clony', + 'Manual' => 'Manuální', + 'Shutter speed priority AE' => 'Priorita času', + }, + }, + 'Caption-Abstract' => 'Popisek', + 'CaptionWriter' => 'Autor popisku', + 'CaptureXResolutionUnit' => { + PrintConv => { + 'um' => 'µm (mikrometr)', + }, + }, + 'CaptureYResolutionUnit' => { + PrintConv => { + 'um' => 'µm (mikrometr)', + }, + }, + 'Categories' => 'Kategorie', + 'Category' => 'Kategorie', + 'CellLength' => 'Délka buňky', + 'CellWidth' => 'Šířka buňky', + 'CenterWeightedAreaSize' => { + PrintConv => { + 'Average' => 'Průměr', + }, + }, + 'ChrominanceNR_TIFF_JPEG' => { + PrintConv => { + 'Low' => 'Méně', + }, + }, + 'ChrominanceNoiseReduction' => { + PrintConv => { + 'Low' => 'Méně', + }, + }, + 'City' => 'Město', + 'CleanFaxData' => 'Čistá fax data', + 'ColorEffect' => { + PrintConv => { + 'Sepia' => 'Sépie', + }, + }, + 'ColorFilter' => 'Barevný filtr', + 'ColorMap' => 'Barevná mapa', + 'ColorMode' => { + PrintConv => { + 'Landscape' => 'Krajina', + 'Normal' => 'Normální', + 'Portrait' => 'Portrét', + }, + }, + 'ColorMoireReductionMode' => { + PrintConv => { + 'Low' => 'Méně', + }, + }, + 'ColorResponseUnit' => 'Odpovídající barevná jednotka', + 'ColorSpace' => { + Description => 'Barevný prostor', + PrintConv => { + 'ICC Profile' => 'ICC Profil', + 'Uncalibrated' => 'Nekalibrován', + }, + }, + 'ColorTemperature' => 'Teplota barev', + 'ColorTone' => { + PrintConv => { + 'Normal' => 'Normální', + }, + }, + 'CommanderGroupAMode' => { + PrintConv => { + 'Manual' => 'Manuální', + }, + }, + 'CommanderGroupBMode' => { + PrintConv => { + 'Manual' => 'Manuální', + }, + }, + 'CommanderInternalFlash' => { + PrintConv => { + 'Manual' => 'Manuální', + }, + }, + 'Comment' => 'Komentář', + 'ComponentsConfiguration' => 'Určení složek', + 'CompressedBitsPerPixel' => 'Komprimační mod', + 'Compression' => { + Description => 'Kompresní algoritmus', + PrintConv => { + 'JPEG' => 'JPEG komprese', + 'JPEG (old-style)' => 'JPEG (pův. verze)', + 'Kodak DCR Compressed' => 'Kodak DCR komprese', + 'Kodak KDC Compressed' => 'Kodak KDC komprese', + 'Next' => 'Kódování NeXT 2-bit', + 'Nikon NEF Compressed' => 'Nikon NEF komprese', + 'None' => 'Žádná', + 'Pentax PEF Compressed' => 'Pentax PEF komprese', + 'SGILog' => 'Kódování SGI 32-bit Log Luminance', + 'SGILog24' => 'Kódování SGI 24-bit Log Luminance', + 'Sony ARW Compressed' => 'Sony ARW komprese', + 'Thunderscan' => 'Kódování ThunderScan 4-bit', + 'Uncompressed' => 'Bez komprese', + }, + }, + 'CompressionType' => { + PrintConv => { + 'None' => 'Žádná', + }, + }, + 'ConsecutiveBadFaxLines' => 'Sekvence vadných faxových řádků', + 'Contrast' => { + Description => 'Kontrast', + PrintConv => { + 'High' => 'Více', + 'Low' => 'Méně', + 'Normal' => 'Normální', + }, + }, + 'ConversionLens' => { + PrintConv => { + 'Macro' => 'Makro', + }, + }, + 'Copyright' => 'Držitel práv', + 'CopyrightNotice' => 'Oznámení o autorských právech', + 'CopyrightStatus' => { + PrintConv => { + 'Unknown' => 'Neznámý', + }, + }, + 'Country' => 'Země', + 'Country-PrimaryLocationName' => 'Země', + 'CreateDate' => 'Datum a čas generování digitálních dat', + 'CreationDate' => 'Datum vytvoření', + 'Credit' => 'Kredit', + 'CropUnit' => { + PrintConv => { + 'inches' => 'Palce', + }, + }, + 'CropUnits' => { + PrintConv => { + 'inches' => 'Palce', + }, + }, + 'CustomRendered' => { + Description => 'Zpracování obrazu', + PrintConv => { + 'Custom' => 'Uživatelské zpracování', + 'Normal' => 'Normální proces', + }, + }, + 'DataImprint' => { + PrintConv => { + 'None' => 'Žádná', + }, + }, + 'DateCreated' => 'Datum vytvoření', + 'DateTime' => 'Datum a čas změny souboru', + 'DateTimeOriginal' => 'Datum a čas vzniku originálních dat', + 'Description' => 'Popis', + 'DeviceSettingDescription' => 'Popis nastavení zařízení', + 'DialDirectionTvAv' => { + PrintConv => { + 'Normal' => 'Normální', + }, + }, + 'DigitalZoom' => { + Description => 'Digitální přiblížení', + PrintConv => { + 'None' => 'Žádná', + }, + }, + 'DigitalZoomRatio' => 'Digitální zoom', + 'Directory' => 'Umístění souboru', + 'DisplaySize' => { + PrintConv => { + 'Normal' => 'Normální', + }, + }, + 'DisplayUnits' => { + PrintConv => { + 'inches' => 'Palce', + }, + }, + 'DisplayXResolutionUnit' => { + PrintConv => { + 'um' => 'µm (mikrometr)', + }, + }, + 'DisplayYResolutionUnit' => { + PrintConv => { + 'um' => 'µm (mikrometr)', + }, + }, + 'DisplayedUnitsX' => { + PrintConv => { + 'inches' => 'Palce', + }, + }, + 'DisplayedUnitsY' => { + PrintConv => { + 'inches' => 'Palce', + }, + }, + 'DjVuVersion' => 'DjVu verze', + 'DocumentName' => 'Jméno dokumentu', + 'DotRange' => 'Bodová rozteč', + 'DriveMode' => 'Režim spouště', + 'ETTLII' => { + PrintConv => { + 'Average' => 'Průměr', + }, + }, + 'EasyMode' => { + PrintConv => { + 'Landscape' => 'Krajina', + 'Macro' => 'Makro', + 'Manual' => 'Manuální', + 'Night' => 'Noční foto', + 'Portrait' => 'Portrét', + }, + }, + 'Emphasis' => { + PrintConv => { + 'None' => 'Žádná', + }, + }, + 'ExifImageHeight' => 'Výška', + 'ExifImageWidth' => 'Šířka', + 'ExifOffset' => 'Ukazatel Exif IFD', + 'ExifToolVersion' => 'ExifTool verze', + 'ExifVersion' => 'Exif verze', + 'ExpandFilm' => 'Ext. film', + 'ExpandFilterLens' => 'Ext. filtr objektivu', + 'ExpandFlashLamp' => 'Ext. světlo blesku', + 'ExpandLens' => 'Ext. objektiv', + 'ExpandScanner' => 'Ext. skener', + 'ExpandSoftware' => 'Ext. Software', + 'ExposureCompensation' => 'Korekce expozice', + 'ExposureIndex' => 'Index expozice', + 'ExposureMode' => { + Description => 'Mód expozice', + PrintConv => { + 'Aperture Priority' => 'Priorita clony', + 'Aperture-priority AE' => 'Priorita clony', + 'Auto' => 'Automatická expozice', + 'Auto bracket' => 'Auto braketing', + 'Landscape' => 'Krajina', + 'Manual' => 'Manuální expozice', + 'Portrait' => 'Portrét', + 'Shutter Priority' => 'Priorita času', + 'Shutter speed priority AE' => 'Priorita času', + }, + }, + 'ExposureModeInManual' => { + PrintConv => { + 'Center-weighted average' => 'Zvýrazněný střed', + 'Partial metering' => 'Blokové', + 'Spot metering' => 'Středový bod', + }, + }, + 'ExposureProgram' => { + Description => 'Expoziční mod', + PrintConv => { + 'Action (High speed)' => 'Akční program (ovlivněný čas závěrky)', + 'Aperture Priority' => 'Priorita clony', + 'Aperture-priority AE' => 'Priorita clony', + 'Bulb' => 'Žárovka', + 'Creative (Slow speed)' => 'Kreativní program (ovlivněná hloubka ostrosti)', + 'Landscape' => 'Krajina', + 'Manual' => 'Manuální', + 'Not Defined' => 'Nedefinovaný', + 'Portrait' => 'Portrét', + 'Program AE' => 'Normální program', + 'Shutter Priority' => 'Priorita času', + 'Shutter speed priority AE' => 'Priorita času', + }, + }, + 'ExposureTime' => 'Expoziční čas', + 'ExposureTime2' => 'Expoziční čas 2', + 'FNumber' => 'F hodnota', + 'FaceOrientation' => { + PrintConv => { + 'Horizontal (normal)' => '0° (nahoru/vlevo)', + 'Rotate 180' => '180° (dolů/vpravo)', + 'Rotate 270 CW' => '90° po směru HR (vlevo/dolů)', + 'Rotate 90 CW' => '90° ptoti směru HR (vpravo/nahoru)', + }, + }, + 'FaxProfile' => { + PrintConv => { + 'Unknown' => 'Neznámý', + }, + }, + 'FaxRecvParams' => 'Parametry příjemce faxu', + 'FaxRecvTime' => 'Čas příjmu faxu', + 'FaxSubAddress' => 'Sub adresa faxu', + 'FileFormat' => 'Formát', + 'FileModifyDate' => 'Datum úpravy', + 'FileName' => 'Jméno', + 'FileSize' => 'Velikost', + 'FileSource' => { + Description => 'Zdroj dat', + PrintConv => { + 'Digital Camera' => 'Digitální fotoaparát', + 'Film Scanner' => 'Filmový skener', + 'Reflection Print Scanner' => 'Skener', + }, + }, + 'FileType' => 'Typ', + 'Filename' => 'Jméno', + 'FillOrder' => { + Description => 'Pořadí výplně', + PrintConv => { + 'Normal' => 'Normální', + }, + }, + 'FilterEffect' => { + PrintConv => { + 'None' => 'Žádná', + }, + }, + 'FilterEffectMonochrome' => { + PrintConv => { + 'None' => 'Žádná', + }, + }, + 'Flash' => { + Description => 'Blesk', + PrintConv => { + 'Auto, Did not fire' => 'Blesk nepoužit, auto mod', + 'Auto, Did not fire, Red-eye reduction' => 'Auto mod, nepoužit, redukce červených očí', + 'Auto, Fired' => 'Blesk použit, auto mod', + 'Auto, Fired, Red-eye reduction' => 'Blesk použit, auto mod, redukce červených očí', + 'Auto, Fired, Red-eye reduction, Return detected' => 'Blesk použit, auto mod, redukce červených očí, odraz detekován', + 'Auto, Fired, Red-eye reduction, Return not detected' => 'Blesk použit, auto mod, redukce červených očí, odraz nezjištěn', + 'Auto, Fired, Return detected' => 'Blesk použit, auto mod, odraz detekován', + 'Auto, Fired, Return not detected' => 'Blesk použit, auto mod, odraz nedetekován', + 'Did not fire' => 'Blesk ne', + 'Fired' => 'Blesk ano', + 'Fired, Red-eye reduction' => 'Blesk použit, redukce červených očí', + 'Fired, Red-eye reduction, Return detected' => 'Blesk použit, redukce červených očí, odraz detekován', + 'Fired, Red-eye reduction, Return not detected' => 'Blesk použit, redukce červených očí, odraz nezjištěn', + 'Fired, Return detected' => 'Odraz strobozáblesků detekován', + 'Fired, Return not detected' => 'Odraz strobozáblesků nezjištěn', + 'No Flash' => 'Blesk ne', + 'No flash function' => 'Blesk nezjištěn', + 'Off' => 'Blesk nepoužit, vynucený mod', + 'Off, Did not fire' => 'Blesk nepoužit, vynucený mod', + 'Off, Did not fire, Return not detected' => 'Blesk vypnut, bez záblesku, odraz nezachycen', + 'Off, No flash function' => 'Neaktivní, bez funkce blesku', + 'Off, Red-eye reduction' => 'Neaktivní, redukce červených očí', + 'On' => 'Blesk použit, vynucený mod', + 'On, Did not fire' => 'Blesk zapnut, nepoužit', + 'On, Fired' => 'Blesk použit, vynucený mod', + 'On, Red-eye reduction' => 'Blesk použit, vynucený mod, redukce červených očí', + 'On, Red-eye reduction, Return detected' => 'Blesk použit, vynucený mod, redukce červených očí, odraz detekován', + 'On, Red-eye reduction, Return not detected' => 'Blesk použit, vynucený mod, redukce červených očí, odraz nezjištěn', + 'On, Return detected' => 'Blesk použit, vynucený mod, odraz detekován', + 'On, Return not detected' => 'Blesk použit, vynucený mod, odraz nezjištěn', + }, + }, + 'FlashControlMode' => { + PrintConv => { + 'Manual' => 'Manuální', + }, + }, + 'FlashDevice' => { + PrintConv => { + 'None' => 'Žádná', + }, + }, + 'FlashEnergy' => 'Síla záblesku', + 'FlashExposureComp' => 'Kompenzace blesku', + 'FlashGroupAControlMode' => { + PrintConv => { + 'Manual' => 'Manuální', + }, + }, + 'FlashGroupBControlMode' => { + PrintConv => { + 'Manual' => 'Manuální', + }, + }, + 'FlashGroupCControlMode' => { + PrintConv => { + 'Manual' => 'Manuální', + }, + }, + 'FlashIntensity' => { + PrintConv => { + 'Normal' => 'Normální', + }, + }, + 'FlashMode' => { + PrintConv => { + 'Normal' => 'Normální', + 'Unknown' => 'Neznámý', + }, + }, + 'FlashModel' => { + PrintConv => { + 'None' => 'Žádná', + }, + }, + 'FlashOptions' => { + PrintConv => { + 'Normal' => 'Normální', + }, + }, + 'FlashOptions2' => { + PrintConv => { + 'Normal' => 'Normální', + }, + }, + 'FlashType' => { + PrintConv => { + 'None' => 'Žádná', + }, + }, + 'FlashpixVersion' => 'Podporovaná verze Flashpix', + 'FocalLength' => 'Ohnisková vzdálenost', + 'FocalLength35efl' => 'Ohnisková vzdálenost', + 'FocalLengthIn35mmFormat' => 'Přepočtená ohnisková vzdálenost (35mm)', + 'FocalPlaneResolutionUnit' => { + Description => 'Jednotka rozlišení senzoru', + PrintConv => { + 'None' => 'Žádná', + 'inches' => 'Palce', + 'um' => 'µm (mikrometr)', + }, + }, + 'FocalPlaneXResolution' => 'Horizontální rozlišení senzoru', + 'FocalPlaneYResolution' => 'Vertikální rozlišení senzoru', + 'Focus' => { + PrintConv => { + 'Manual' => 'Manuální', + }, + }, + 'FocusContinuous' => { + PrintConv => { + 'Manual' => 'Manuální', + }, + }, + 'FocusMode' => { + Description => 'Ostření', + PrintConv => { + 'Macro' => 'Makro', + 'Manual' => 'Manuální', + 'Normal' => 'Normální', + }, + }, + 'FocusMode2' => { + PrintConv => { + 'Manual' => 'Manuální', + }, + }, + 'FocusModeSetting' => { + PrintConv => { + 'Manual' => 'Manuální', + }, + }, + 'FocusRange' => { + PrintConv => { + 'Macro' => 'Makro', + 'Manual' => 'Manuální', + 'Normal' => 'Normální', + }, + }, + 'FocusTrackingLockOn' => { + PrintConv => { + 'Normal' => 'Normální', + }, + }, + 'FrameRate' => 'Snímkovací frekvence', + 'FrameSize' => 'Velikost snímku', + 'FreeByteCounts' => 'Počet volných bytů', + 'FreeOffsets' => 'Volná datová pozice', + 'GIFVersion' => 'GIF verze', + 'GPSAltitude' => 'Nadmořská výška', + 'GPSAltitudeRef' => { + Description => 'Nadmořská výška', + PrintConv => { + 'Above Sea Level' => 'Nadmořská výška', + 'Below Sea Level' => 'Nadmořská výška (záporná hodnota)', + }, + }, + 'GPSAreaInformation' => 'Název GPS oblasti', + 'GPSDOP' => 'Přesnost měření', + 'GPSDateStamp' => 'GPS Datum', + 'GPSDateTime' => 'GPS čas (atomový čas)', + 'GPSDestBearing' => 'Azimut cíle', + 'GPSDestBearingRef' => { + Description => 'Reference azimutu cíle.', + PrintConv => { + 'Magnetic North' => 'Magnetický směr', + 'True North' => 'Geografický směr', + }, + }, + 'GPSDestDistance' => 'Vzdálenost k cíli', + 'GPSDestDistanceRef' => { + Description => 'Reference vzdálenosti cíle', + PrintConv => { + 'Kilometers' => 'Kilometry', + 'Miles' => 'Míle', + 'Nautical Miles' => 'Uzle', + }, + }, + 'GPSDestLatitude' => 'Zeměpisná šířka cíle', + 'GPSDestLatitudeRef' => { + Description => 'Reference pro zeměpisnou šířku cíle', + PrintConv => { + 'North' => 'Severní šířka', + 'South' => 'Jižní šířka', + }, + }, + 'GPSDestLongitude' => 'Zeměpisná délka cíle', + 'GPSDestLongitudeRef' => { + Description => 'Reference pro zeměpisnou délku cíle', + PrintConv => { + 'East' => 'Východní délka', + 'West' => 'Západní délka', + }, + }, + 'GPSDifferential' => { + Description => 'GPS rozdílová korekce', + PrintConv => { + 'Differential Corrected' => 'Započítaná rozdílová korekce', + 'No Correction' => 'Měření bez korekce', + }, + }, + 'GPSImgDirection' => 'Orientace obrázku', + 'GPSImgDirectionRef' => { + Description => 'Reference k orientaci obrázku', + PrintConv => { + 'Magnetic North' => 'Magnetický směr', + 'True North' => 'Geografický směr', + }, + }, + 'GPSInfo' => 'IFD ukazatel v GPS informacích', + 'GPSLatitude' => 'Zeměpisná šířka', + 'GPSLatitudeRef' => { + Description => 'Severní nebo Jižní šířka', + PrintConv => { + 'North' => 'Severní šířka', + 'South' => 'Jižní šířka', + }, + }, + 'GPSLongitude' => 'Zeměpisná délka', + 'GPSLongitudeRef' => { + Description => 'Východní nebo západní délka', + PrintConv => { + 'East' => 'Východní délka', + 'West' => 'Západní délka', + }, + }, + 'GPSMapDatum' => 'Geodetická data', + 'GPSMeasureMode' => { + Description => 'Mod GPS', + PrintConv => { + '2-D' => '2-dimenzionální měření', + '2-Dimensional' => '2-dimenzionální měření', + '2-Dimensional Measurement' => '2-dimenzionální měření', + '3-D' => '3-dimenzionální měření', + '3-Dimensional' => '3-dimenzionální měření', + '3-Dimensional Measurement' => '3-dimenzionální měření', + }, + }, + 'GPSProcessingMethod' => 'Název procesní metody GPS', + 'GPSSatellites' => 'GPS satelity využité při měření', + 'GPSSpeed' => 'Rychlost GPS přijímače', + 'GPSSpeedRef' => { + Description => 'Jednotka rychlosti', + PrintConv => { + 'km/h' => 'Kilometry za hodinu', + 'knots' => 'Uzle', + 'mph' => 'Míle za hodinu', + }, + }, + 'GPSStatus' => { + Description => 'Stav GPS přijímače', + PrintConv => { + 'Measurement Active' => 'Probíhá měření', + 'Measurement Void' => 'Vzájemné měření', + }, + }, + 'GPSTimeStamp' => 'GPS čas (atomový čas)', + 'GPSTrack' => 'Směr pohybu', + 'GPSTrackRef' => { + Description => 'Reference pro směr pohybu', + PrintConv => { + 'Magnetic North' => 'Magnetický směr', + 'True North' => 'Geografický směr', + }, + }, + 'GPSVersionID' => 'Verze GPS TAGu', + 'GainControl' => { + Description => 'Míra jasu', + PrintConv => { + 'High gain down' => 'Silné zeslabení', + 'High gain up' => 'Silné zesílení', + 'Low gain down' => 'Slabé zeslabení', + 'Low gain up' => 'Slabé zesílení', + 'None' => 'Žádná', + }, + }, + 'Gradation' => 'Pusobivy', + 'GrayResponseCurve' => 'Šedá referenční křivka', + 'GrayResponseUnit' => { + Description => 'Jednotka odezvy šedé', + PrintConv => { + '0.0001' => 'Číslo udávající tisíce jednotek', + '0.001' => 'Číslo udávající stovky jednotek', + '0.1' => 'Číslo udávající desítky jednotek', + '1e-05' => 'Číslo udávající desetitisíce jednotek', + '1e-06' => 'Číslo udávající statisíce jednotek', + }, + }, + 'HalftoneHints' => 'Půltóny', + 'Headline' => 'Titulek', + 'HighISONoiseReduction' => { + PrintConv => { + 'Low' => 'Méně', + 'Normal' => 'Normální', + }, + }, + 'HostComputer' => 'Host', + 'Hue' => 'Odstín', + 'ICCProfile' => 'ICC-Profil', + 'IPTC-NAA' => 'IPTC-NAA metadata', + 'ISO' => 'Citlivost ISO', + 'ISOSetting' => { + PrintConv => { + 'Manual' => 'Manuální', + }, + }, + 'ImageDescription' => 'Popis obrázku', + 'ImageHeight' => 'Výška', + 'ImageHistory' => 'Historie obrázku', + 'ImageNumber' => 'Číslo obrázku', + 'ImageOrientation' => { + PrintConv => { + 'Portrait' => 'Portrét', + }, + }, + 'ImageQuality' => { + PrintConv => { + 'Normal' => 'Normální', + }, + }, + 'ImageSize' => 'Velikost snímku', + 'ImageSourceData' => 'Zdrojová data obrázku', + 'ImageTone' => { + PrintConv => { + 'Landscape' => 'Krajina', + 'Portrait' => 'Portrét', + }, + }, + 'ImageUniqueID' => 'Jedinečné ID obrázku', + 'ImageWidth' => 'Šířka', + 'Index' => 'Nápověda', + 'InkNames' => 'Název náplně', + 'InkSet' => 'Inkoustová sada', + 'Instructions' => 'Pokyny', + 'InternalFlash' => { + PrintConv => { + 'Fired' => 'Blesk ano', + 'Manual' => 'Manuální', + 'No' => 'Blesk ne', + }, + }, + 'InteropIndex' => { + Description => 'Identifikace', + PrintConv => { + 'R03 - DCF option file (Adobe RGB)' => 'R03: DCF option file (Adobe RGB)', + 'R98 - DCF basic file (sRGB)' => 'R98: DCF basic file (sRGB)', + 'THM - DCF thumbnail file' => 'THM: DCF thumbnail file', + }, + }, + 'InteropOffset' => 'Značka součinnosti', + 'InteropVersion' => 'Verze kompatibility', + 'JFIFVersion' => 'JFIF verze', + 'JPEGQuality' => { + PrintConv => { + 'Standard' => 'Normální', + }, + }, + 'Keyword' => 'Klíčová slova', + 'Keywords' => 'Klíčová slova', + 'LeafData' => 'Leaf data', + 'Lens' => 'Objektiv', + 'LensInfo' => 'Informace o optice', + 'LicenseType' => { + PrintConv => { + 'Unknown' => 'Neznámý', + }, + }, + 'LightSource' => { + Description => 'Zdroj světla', + PrintConv => { + 'Cloudy' => 'Zataženo', + 'Cool White Fluorescent' => 'Studená zářivka', + 'Day White Fluorescent' => 'Denní zářivka', + 'Daylight' => 'Denní světlo', + 'Daylight Fluorescent' => 'Denní světlo', + 'Fine Weather' => 'Slunečno', + 'Flash' => 'Blesk', + 'Fluorescent' => 'Žárovka', + 'ISO Studio Tungsten' => 'Studiová světla', + 'Other' => 'Jiné osvětlení', + 'Shade' => 'Stíny', + 'Standard Light A' => 'Standardní světlo A', + 'Standard Light B' => 'Standardní světlo B', + 'Standard Light C' => 'Standardní světlo C', + 'Tungsten (Incandescent)' => 'Zářivka', + 'Unknown' => 'Neznámý', + 'White Fluorescent' => 'Bílá zářivka', + }, + }, + 'Lightness' => 'Jas', + 'Location' => 'Lokalita', + 'LoopStyle' => { + PrintConv => { + 'Normal' => 'Normální', + }, + }, + 'LuminanceNoiseReduction' => { + PrintConv => { + 'Low' => 'Méně', + }, + }, + 'MIEVersion' => 'MIE verze', + 'Macro' => { + PrintConv => { + 'Macro' => 'Makro', + 'Manual' => 'Manuální', + 'Normal' => 'Normální', + }, + }, + 'MacroMode' => { + PrintConv => { + 'Macro' => 'Makro', + 'Normal' => 'Normální', + }, + }, + 'Make' => 'Výrobce', + 'MakerNote' => 'Privátní data výrobce', + 'MakerNotes' => 'Poznámka výrobce', + 'ManualFlashOutput' => { + PrintConv => { + 'Low' => 'Méně', + }, + }, + 'MaxAperture' => 'Maximální clona+C1233 objektivu', + 'MaxApertureValue' => 'Max clona objektivu', + 'MaxSampleValue' => 'Max. hodnota vzorku', + 'MediaType' => { + PrintConv => { + 'Normal' => 'Normální', + }, + }, + 'Metering' => { + PrintConv => { + 'Spot' => 'Středový bod', + }, + }, + 'MeteringMode' => { + Description => 'Režim měření expozice', + PrintConv => { + 'Average' => 'Průměr', + 'Center-weighted average' => 'Zvýrazněný střed', + 'Multi-segment' => 'Multi segment', + 'Multi-spot' => 'Vícebodové', + 'Other' => 'Jiné', + 'Partial' => 'Blokové', + 'Spot' => 'Středový bod', + 'Unknown' => 'Neznámý', + }, + }, + 'MeteringMode2' => { + PrintConv => { + 'Multi-segment' => 'Multi segment', + }, + }, + 'MeteringMode3' => { + PrintConv => { + 'Multi-segment' => 'Multi segment', + }, + }, + 'MinSampleValue' => 'Min. hodnota vzorku', + 'MinoltaQuality' => { + PrintConv => { + 'Normal' => 'Normální', + }, + }, + 'Model' => 'Typ fotoaparátu', + 'Model2' => 'Typ zařízení (2)', + 'ModifiedPictureStyle' => { + PrintConv => { + 'Landscape' => 'Krajina', + 'None' => 'Žádná', + 'Portrait' => 'Portrét', + }, + }, + 'ModifiedSharpnessFreq' => { + PrintConv => { + 'Low' => 'Méně', + }, + }, + 'ModifiedToneCurve' => { + PrintConv => { + 'Manual' => 'Manuální', + }, + }, + 'ModifiedWhiteBalance' => { + PrintConv => { + 'Cloudy' => 'Zataženo', + 'Daylight' => 'Denní světlo', + 'Daylight Fluorescent' => 'Denní světlo', + 'Flash' => 'Blesk', + 'Fluorescent' => 'Žárovka', + 'Shade' => 'Stíny', + 'Tungsten' => 'Zářivka', + }, + }, + 'ModifyDate' => 'Datum a čas změny souboru', + 'MonochromeFilterEffect' => { + PrintConv => { + 'None' => 'Žádná', + }, + }, + 'MonochromeToningEffect' => { + PrintConv => { + 'None' => 'Žádná', + }, + }, + 'NEFCompression' => { + PrintConv => { + 'Uncompressed' => 'Bez komprese', + }, + }, + 'Noise' => 'Šum', + 'NoiseFilter' => { + PrintConv => { + 'Low' => 'Méně', + }, + }, + 'NoiseReduction' => { + Description => 'Potlačení šumu', + PrintConv => { + 'Normal' => 'Normální', + }, + }, + 'NumberofInks' => 'Číslo náplně', + 'ObjectFileType' => { + PrintConv => { + 'None' => 'Žádná', + 'Unknown' => 'Neznámý', + }, + }, + 'OldSubfileType' => 'Typ podsekce', + 'Opto-ElectricConvFactor' => 'Optoel. konverzní faktor (OECF)', + 'Orientation' => { + Description => 'Orientace', + PrintConv => { + 'Horizontal (normal)' => '0° (nahoru/vlevo)', + 'Mirror horizontal' => '0° (nahoru/vpravo)', + 'Mirror horizontal and rotate 270 CW' => '90° po směru HR (vlevo/nahoru)', + 'Mirror horizontal and rotate 90 CW' => '90° ptoti směru HR (vpravo/dolů)', + 'Mirror vertical' => '180° (dolů/vlevo)', + 'Rotate 180' => '180° (dolů/vpravo)', + 'Rotate 270 CW' => '90° po směru HR (vlevo/dolů)', + 'Rotate 90 CW' => '90° ptoti směru HR (vpravo/nahoru)', + }, + }, + 'PEFVersion' => 'PEF verze', + 'Padding' => 'Náhradní znaky', + 'PageName' => 'Jméno stránky', + 'PageNumber' => 'Číslo stránky', + 'PhotoEffectsType' => { + PrintConv => { + 'None' => 'Žádná', + }, + }, + 'PhotometricInterpretation' => { + Description => 'Pixelové schéma', + PrintConv => { + 'BlackIsZero' => 'Černá je nula', + 'Color Filter Array' => 'CFA (Color Filter Matrix)', + 'Pixar LogL' => 'CIE Log2(L) (Log luminance)', + 'Pixar LogLuv' => 'CIE Log2(L)(u\',v\') (Log luminance and chrominance)', + 'RGB Palette' => 'Barevné schema', + 'Transparency Mask' => 'Průhlednost', + 'WhiteIsZero' => 'Bílá je nula', + }, + }, + 'PhotoshopAnnotations' => 'Poznámky Photoshop', + 'PictureFinish' => { + PrintConv => { + 'Portrait' => 'Portrét', + }, + }, + 'PictureMode' => { + PrintConv => { + 'Aperture-priority AE' => 'Priorita clony', + 'Landscape' => 'Krajina', + 'Macro' => 'Makro', + 'Manual' => 'Manuální', + 'Portrait' => 'Portrét', + 'Shutter speed priority AE' => 'Priorita času', + }, + }, + 'PictureMode2' => { + PrintConv => { + 'Aperture Priority' => 'Priorita clony', + 'Manual' => 'Manuální', + 'Shutter Speed Priority' => 'Priorita času', + }, + }, + 'PictureStyle' => { + PrintConv => { + 'Landscape' => 'Krajina', + 'None' => 'Žádná', + 'Portrait' => 'Portrét', + }, + }, + 'PixelUnits' => { + PrintConv => { + 'Unknown' => 'Neznámý', + }, + }, + 'PlanarConfiguration' => { + Description => 'Uspořádání obrazových dat', + PrintConv => { + 'Chunky' => 'Chunky Format (prokládaný)', + 'Planar' => 'Planární (dvojrozměrný)', + }, + }, + 'Predictor' => { + Description => 'Predikce', + PrintConv => { + 'Horizontal differencing' => 'Horizontální diferenciace', + 'None' => 'Bez predikce', + }, + }, + 'PreviewColorSpace' => { + PrintConv => { + 'Unknown' => 'Neznámý', + }, + }, + 'PreviewImage' => 'Náhled', + 'PreviewQuality' => { + PrintConv => { + 'Normal' => 'Normální', + }, + }, + 'PrimaryChromaticities' => 'Chromatičnost primárních barev', + 'ProgramLine' => { + PrintConv => { + 'Normal' => 'Normální', + }, + }, + 'ProgramMode' => { + PrintConv => { + 'None' => 'Žádná', + 'Portrait' => 'Portrét', + }, + }, + 'Province-State' => 'Stát/provincie', + 'Quality' => { + PrintConv => { + 'Low' => 'Méně', + 'Normal' => 'Normální', + }, + }, + 'QualityMode' => { + PrintConv => { + 'Normal' => 'Normální', + }, + }, + 'RAFVersion' => 'RAF verze', + 'Rating' => 'Hodnocení', + 'RatingPercent' => 'Hodnocení v procentech', + 'RawJpgQuality' => { + PrintConv => { + 'Normal' => 'Normální', + }, + }, + 'RecordMode' => { + Description => 'Režim záznamu', + PrintConv => { + 'Aperture Priority' => 'Priorita clony', + 'Manual' => 'Manuální', + 'Shutter Priority' => 'Priorita času', + }, + }, + 'RecordingMode' => { + PrintConv => { + 'Landscape' => 'Krajina', + 'Manual' => 'Manuální', + 'Portrait' => 'Portrét', + }, + }, + 'ReferenceBlackWhite' => 'Černý a bílý referenční bod', + 'RelatedImageFileFormat' => 'Obrazový formát', + 'RelatedImageHeight' => 'Výška obrázku', + 'RelatedImageWidth' => 'Šířka obrázku', + 'RelatedSoundFile' => 'Audio soubor', + 'ResampleParamsQuality' => { + PrintConv => { + 'Low' => 'Méně', + }, + }, + 'ResolutionUnit' => { + Description => 'Jednotka X a Y rozlišení', + PrintConv => { + 'None' => 'Žádná', + 'cm' => 'Pixely/cm', + 'inches' => 'Palce', + }, + }, + 'RetouchHistory' => { + PrintConv => { + 'None' => 'Žádná', + }, + }, + 'Rotation' => { + PrintConv => { + 'Horizontal' => '0° (nahoru/vlevo)', + 'Horizontal (Normal)' => '0° (nahoru/vlevo)', + 'Horizontal (normal)' => '0° (nahoru/vlevo)', + 'Rotate 180' => '180° (dolů/vpravo)', + 'Rotate 270 CW' => '90° po směru HR (vlevo/dolů)', + 'Rotate 90 CW' => '90° ptoti směru HR (vpravo/nahoru)', + 'Rotated 180' => '180° (dolů/vpravo)', + 'Rotated 270 CW' => '90° po směru HR (vlevo/dolů)', + 'Rotated 90 CW' => '90° ptoti směru HR (vpravo/nahoru)', + }, + }, + 'RowsPerStrip' => 'Počet řádek v části', + 'SPIFFVersion' => 'SPIFF verze', + 'SVGVersion' => 'SVG verze', + 'SampleFormat' => { + Description => 'Formát vzorku', + PrintConv => { + 'Complex int' => 'Komplexní číslo', + 'Float' => 'Desetinná čárka', + 'Signed' => 'Záporné číslo', + 'Undefined' => 'Nedefinované', + 'Unsigned' => 'Kladné číslo', + }, + }, + 'SamplesPerPixel' => 'Počet složek', + 'Saturation' => { + Description => 'Saturace', + PrintConv => { + 'High' => 'Vysoká', + 'Low' => 'Nízká', + 'Normal' => 'Normální', + }, + }, + 'SceneCaptureType' => { + Description => 'Typ scény', + PrintConv => { + 'Landscape' => 'Krajina', + 'Night' => 'Noční foto', + 'Portrait' => 'Portrét', + }, + }, + 'SceneMode' => { + PrintConv => { + 'Aperture Priority' => 'Priorita clony', + 'Landscape' => 'Krajina', + 'Macro' => 'Makro', + 'Manual' => 'Manuální', + 'Normal' => 'Normální', + 'Portrait' => 'Portrét', + 'Shutter Priority' => 'Priorita času', + 'Spot' => 'Středový bod', + 'Sunset' => 'Západ', + }, + }, + 'SceneModeUsed' => { + PrintConv => { + 'Aperture Priority' => 'Priorita clony', + 'Landscape' => 'Krajina', + 'Macro' => 'Makro', + 'Manual' => 'Manuální', + 'Portrait' => 'Portrét', + 'Shutter Priority' => 'Priorita času', + }, + }, + 'SceneSelect' => { + PrintConv => { + 'Night' => 'Noční foto', + }, + }, + 'SceneType' => { + Description => 'Typ scény', + PrintConv => { + 'Directly photographed' => 'Přímo pořízený snímek', + }, + }, + 'SecurityClassification' => { + Description => 'Bezpečnostní klasifikace', + PrintConv => { + 'Confidential' => 'Důvěrný', + 'Restricted' => 'Vyhrazený', + 'Secret' => 'Tajný', + 'Top Secret' => 'Velmi tajný', + 'Unclassified' => 'Neurčeno', + }, + }, + 'SelfTimerMode' => 'Samospoušť', + 'SensingMethod' => { + Description => 'Metoda měření', + PrintConv => { + 'Color sequential area' => 'Barevný sekvenční plošný sensor', + 'Color sequential linear' => 'Barevný sekvenčné-lineární senzor', + 'Monochrome area' => 'Monochromatický senzor', + 'Monochrome linear' => 'Monochromatický lineární senzor', + 'Not defined' => 'Nedefinovaný', + 'One-chip color area' => 'Jednočipový barevný senzor', + 'Three-chip color area' => 'Tříčipový barevný senzor', + 'Trilinear' => 'Třílineární senzor', + 'Two-chip color area' => 'Dvoučipový barevný senzor', + }, + }, + 'SequentialShot' => { + PrintConv => { + 'None' => 'Žádná', + }, + }, + 'SerialNumber' => 'ID fotoaparátu', + 'SetButtonCrossKeysFunc' => { + PrintConv => { + 'Normal' => 'Normální', + }, + }, + 'ShadingCompensation' => 'Kompenzace stínování', + 'Sharpness' => { + Description => 'Doostření', + PrintConv => { + 'Hard' => 'Silné', + 'Normal' => 'Normální', + 'Soft' => 'Lehké', + }, + }, + 'SharpnessFrequency' => { + PrintConv => { + 'Low' => 'Méně', + }, + }, + 'ShootingMode' => { + Description => 'Režim focení', + PrintConv => { + 'Aperture Priority' => 'Priorita clony', + 'Macro' => 'Makro', + 'Manual' => 'Manuální', + 'Normal' => 'Normální', + 'Portrait' => 'Portrét', + 'Shutter Priority' => 'Priorita času', + 'Spot' => 'Středový bod', + }, + }, + 'ShutterMode' => { + PrintConv => { + 'Aperture Priority' => 'Priorita clony', + }, + }, + 'ShutterSpeed' => 'Expoziční čas', + 'ShutterSpeedValue' => 'Čas závěrky', + 'SlowShutter' => { + PrintConv => { + 'None' => 'Žádná', + }, + }, + 'Software' => 'Použitý software', + 'Source' => 'Zdroj', + 'SpatialFrequencyResponse' => 'Spatial frequency response', + 'SpecialEffectsOpticalFilter' => { + PrintConv => { + 'None' => 'Žádná', + }, + }, + 'SpectralSensitivity' => 'Spektrální citlivost', + 'State' => 'Stát', + 'StripByteCounts' => 'Bytů na komprimovanou část', + 'StripOffsets' => 'Pozice obrazových dat', + 'SubSecCreateDate' => 'Datum a čas generování digitálních dat', + 'SubSecDateTimeOriginal' => 'Datum a čas vzniku originálních dat', + 'SubSecModifyDate' => 'Datum a čas změny souboru', + 'SubSecTime' => 'DateTime 1/100 sekundy', + 'SubSecTimeDigitized' => 'DateTimeDigitized 1/100 sekund', + 'SubSecTimeOriginal' => 'DateTimeOriginal 1/100 sekund', + 'SubfileType' => 'Nový typ podsekce', + 'Subject' => 'Popis', + 'SubjectArea' => 'Pozice hlavního objektu', + 'SubjectDistance' => 'Vzdálenost objektu', + 'SubjectDistanceRange' => { + Description => 'Rozsah vzdálenosti objektu', + PrintConv => { + 'Close' => 'Blízký', + 'Distant' => 'Vzdálený', + 'Macro' => 'Makro', + 'Unknown' => 'Neznámý', + }, + }, + 'SubjectLocation' => 'Pozice hlavního objektu', + 'SubjectProgram' => { + PrintConv => { + 'None' => 'Žádná', + 'Portrait' => 'Portrét', + }, + }, + 'Subsystem' => { + PrintConv => { + 'Unknown' => 'Neznámý', + }, + }, + 'SupplementalCategories' => 'Doplňkové kategorie', + 'T4Options' => 'Plné bity', + 'T6Options' => 'Volby T6', + 'TargetPrinter' => 'Cílová tiskárna', + 'Teleconverter' => { + PrintConv => { + 'None' => 'Žádná', + }, + }, + 'Thresholding' => 'Práh', + 'ThumbnailImage' => 'Náhled', + 'ThumbnailImageSize' => 'Velkost náhledu', + 'TileByteCounts' => 'Počet bytů prvku', + 'TileLength' => 'Délka prvku', + 'TileOffsets' => 'Offset prvku', + 'TileWidth' => 'Šířka prvku', + 'TimeScaleParamsQuality' => { + PrintConv => { + 'Low' => 'Méně', + }, + }, + 'Title' => 'Název', + 'ToneCurve' => { + PrintConv => { + 'Manual' => 'Manuální', + }, + }, + 'ToningEffect' => { + PrintConv => { + 'None' => 'Žádná', + }, + }, + 'ToningEffectMonochrome' => { + PrintConv => { + 'None' => 'Žádná', + }, + }, + 'TransferFunction' => 'Transfer funkce', + 'Transformation' => { + PrintConv => { + 'Horizontal (normal)' => '0° (nahoru/vlevo)', + 'Mirror horizontal' => '0° (nahoru/vpravo)', + 'Mirror horizontal and rotate 270 CW' => '90° po směru HR (vlevo/nahoru)', + 'Mirror horizontal and rotate 90 CW' => '90° ptoti směru HR (vpravo/dolů)', + 'Mirror vertical' => '180° (dolů/vlevo)', + 'Rotate 180' => '180° (dolů/vpravo)', + 'Rotate 270 CW' => '90° po směru HR (vlevo/dolů)', + 'Rotate 90 CW' => '90° ptoti směru HR (vpravo/nahoru)', + }, + }, + 'TransmissionReference' => 'Reference přenosu', + 'Trapped' => { + PrintConv => { + 'Unknown' => 'Neznámý', + }, + }, + 'Urgency' => 'Naléhavost', + 'UserComment' => 'Komentář', + 'UserDef1PictureStyle' => { + PrintConv => { + 'Landscape' => 'Krajina', + 'Portrait' => 'Portrét', + }, + }, + 'UserDef2PictureStyle' => { + PrintConv => { + 'Landscape' => 'Krajina', + 'Portrait' => 'Portrét', + }, + }, + 'UserDef3PictureStyle' => { + PrintConv => { + 'Landscape' => 'Krajina', + 'Portrait' => 'Portrét', + }, + }, + 'VRDVersion' => 'VRD verze', + 'Version' => 'Verze', + 'VignetteControl' => { + PrintConv => { + 'Normal' => 'Normální', + }, + }, + 'WBAdjLighting' => { + PrintConv => { + 'Daylight (direct sunlight)' => 'Denní světlo (0)', + 'Daylight (shade)' => 'Denní světlo (1)', + 'Daylight (cloudy)' => 'Denní světlo (2)', + 'Flash' => 'Blesk', + 'None' => 'Žádná', + }, + }, + 'WhiteBalance' => { + Description => 'Vyvážení bílé', + PrintConv => { + 'Auto' => 'Automatické vyvážení bílé', + 'Black & White' => 'Černobílé foto', + 'Cloudy' => 'Zataženo', + 'Cool White Fluorescent' => 'Chladná bílá fluorescentní', + 'Custom 1' => 'VLASTNÍ1', + 'Custom 2' => 'VLASTNÍ2', + 'Custom 3' => 'VLASTNÍ3', + 'Custom 4' => 'VLASTNÍ4', + 'Day White Fluorescent' => 'Denní zářivka', + 'Daylight' => 'Denní světlo', + 'Daylight Fluorescent' => 'Denní světlo', + 'Flash' => 'Blesk', + 'Fluorescent' => 'Žárovka', + 'Manual' => 'Manuální', + 'Shade' => 'Stíny', + 'Tungsten' => 'Zářivka', + 'Unknown' => 'Neznámý', + 'White Fluorescent' => 'Bílá zářivka', + }, + }, + 'WhiteBalanceAdj' => { + PrintConv => { + 'Cloudy' => 'Zataženo', + 'Daylight' => 'Denní světlo', + 'Flash' => 'Blesk', + 'Fluorescent' => 'Žárovka', + 'Shade' => 'Stíny', + 'Tungsten' => 'Zářivka', + }, + }, + 'WhiteBalanceMode' => { + PrintConv => { + 'Unknown' => 'Neznámý', + }, + }, + 'WhiteBalanceSet' => { + PrintConv => { + 'Cloudy' => 'Zataženo', + 'Daylight' => 'Denní světlo', + 'Daylight Fluorescent' => 'Denní světlo', + 'Flash' => 'Blesk', + 'Manual' => 'Manuální', + 'Shade' => 'Stíny', + 'Tungsten' => 'Zářivka', + 'White Fluorescent' => 'Bílá zářivka', + }, + }, + 'WhitePoint' => 'Chromatičnost bílého bodu', + 'Writer-Editor' => 'Autor popisku', + 'XMP' => 'XMP metadata', + 'XPAuthor' => 'Autor', + 'XPComment' => 'Komentář', + 'XPKeywords' => 'Klíčová slova', + 'XPSubject' => 'Popis', + 'XPTitle' => 'Název', + 'XPosition' => 'X-pozice', + 'XResolution' => 'Rozlišení obrázku na šířku', + 'YCbCrCoefficients' => 'Koeficienty transformační YCbCr matrice', + 'YCbCrPositioning' => { + Description => 'Y a C pozice', + PrintConv => { + 'Centered' => 'Centrované', + 'Co-sited' => 'Po stranách', + }, + }, + 'YCbCrSubSampling' => 'Vzorkovací poměr Y k C', + 'YPosition' => 'Y-pozice', + 'YResolution' => 'Rozlišení obrázku na výšku', +); + +1; # end + + +__END__ + +=head1 NAME + +Image::ExifTool::Lang::cs.pm - ExifTool Czech language translations + +=head1 DESCRIPTION + +This file is used by Image::ExifTool to generate localized tag descriptions +and values. + +=head1 AUTHOR + +Copyright 2003-2019, Phil Harvey (phil at owl.phy.queensu.ca) + +This library is free software; you can redistribute it and/or modify it +under the same terms as Perl itself. + +=head1 ACKNOWLEDGEMENTS + +Thanks to Jens Duttke and Petr MichE<aacute>lek for providing this +translation. + +=head1 SEE ALSO + +L<Image::ExifTool(3pm)|Image::ExifTool>, +L<Image::ExifTool::TagInfoXML(3pm)|Image::ExifTool::TagInfoXML> + +=cut diff --git a/lib/Image/ExifTool/Lang/de.pm b/lib/Image/ExifTool/Lang/de.pm new file mode 100644 index 0000000..2ebe176 --- /dev/null +++ b/lib/Image/ExifTool/Lang/de.pm @@ -0,0 +1,8708 @@ +#------------------------------------------------------------------------------ +# File: de.pm +# +# Description: ExifTool German language translations +# +# Notes: This file generated automatically by Image::ExifTool::TagInfoXML +#------------------------------------------------------------------------------ + +package Image::ExifTool::Lang::de; + +use strict; +use vars qw($VERSION); + +$VERSION = '1.33'; + +%Image::ExifTool::Lang::de::Translate = ( + 'AEAperture' => 'AE-Blende', + 'AEBAutoCancel' => { + Description => 'Automatisches Bracketingende', + PrintConv => { + 'Off' => 'Aus', + 'On' => 'Ein', + }, + }, + 'AEBBracketValue' => 'AEB-Korrekturwert', + 'AEBSequence' => 'Bracketing-Sequenz', + 'AEBSequenceAutoCancel' => { + Description => 'WB-Sequenz/autom. Abschaltung', + PrintConv => { + '-,0,+/Disabled' => '-,0,+/Aus', + '-,0,+/Enabled' => '-,0,+/Ein', + '0,-,+/Disabled' => '0,-,+/Aus', + '0,-,+/Enabled' => '0,-,+/Ein', + }, + }, + 'AEBShotCount' => 'Anzahl Belichtungsreihenaufnahmen', + 'AEBXv' => 'AEB-Belichtungskorrektur', + 'AEExposureTime' => 'AE-Belichtungszeit', + 'AEExtra' => 'AE-Extra?', + 'AEFlags' => { + PrintConv => { + 'AE lock' => 'AE Speicherung', + 'Aperture wide open' => 'Offene Blende', + 'Flash recommended?' => 'Blitz erforderlich', + }, + }, + 'AEInfo' => 'Automatikbelichtungs-Informationen', + 'AELock' => { + Description => 'Belichtungsspeicher', + PrintConv => { + 'Off' => 'Aus', + 'On' => 'Ein', + }, + }, + 'AELockButton' => { + Description => 'AE-L/AF-L-Taste', + PrintConv => { + 'AE Lock (hold)' => 'Nur Belichtung (halten)', + 'AE Lock Only' => 'Nur Belichtung', + 'AE-L/AF Area' => 'Belichtung & Messfeld', + 'AE-L/AF-L/AF Area' => 'Bel. & Fokus & Messfeld', + 'AE/AF Lock' => 'Belichtung & Fokus', + 'AF Lock Only' => 'Nur Fokus', + 'AF-L/AF Area' => 'Fokus & Messfeld', + 'AF-ON' => 'AF-Aktivierung', + 'AF-ON/AF Area' => 'AF-Aktiv. & Messfeld', + 'FV Lock' => 'FV-Messwertspeicher', + 'Focus Area Selection' => 'AF-Messfeldauswahl', + }, + }, + 'AEMaxAperture' => 'Größte AE-Blende', + 'AEMaxAperture2' => 'Größte AE-Blende (2)', + 'AEMeteringMode' => { + Description => 'AE Belichtungs-Messmethode', + PrintConv => { + 'Center-weighted average' => 'Mittenbetont', + 'Multi-segment' => 'Multi-Segment', + }, + }, + 'AEMeteringSegments' => 'AE-Messfelder', + 'AEMicroadjustment' => { + Description => 'AE Feinabstimmung', + PrintConv => { + 'Disable' => 'Deaktiviert', + 'Enable' => 'Aktiviert', + }, + }, + 'AEMinAperture' => 'Kleinste AE-Blende', + 'AEMinExposureTime' => 'Kürzeste AE Belichtungszeit', + 'AEProgramMode' => { + Description => 'AE-Programm-Modus', + PrintConv => { + 'Av, B or X' => 'Av, B oder X', + 'Candlelight' => 'Kerzenlicht', + 'DOF Program' => 'Schärfentiefe-Priorität', + 'DOF Program (P-Shift)' => 'Schärfentiefe-Priorität (P Shift)', + 'Hi-speed Program' => 'HS-Priorität', + 'Hi-speed Program (P-Shift)' => 'HS-Priorität (P Shift)', + 'Kids' => 'Kinder', + 'Landscape' => 'Landschaft', + 'M, P or TAv' => 'M, P oder TAv', + 'MTF Program' => 'MTF-Priorität', + 'MTF Program (P-Shift)' => 'MTF-Priorität (P Shift)', + 'Macro' => 'Makro', + 'Night Scene' => 'Nachtszene', + 'Night Scene Portrait' => 'Nacht-Porträt', + 'No Flash' => 'Kein Blitz', + 'Pet' => 'Haustiere', + 'Portrait' => 'Porträt', + 'Sunset' => 'Sonnenuntergang', + 'Surf & Snow' => 'Surf & Schnee', + 'Sv or Green Mode' => 'Sv oder "Grünes" AE-Programm', + }, + }, + 'AESetting' => { + Description => 'AE-Einstellung', + PrintConv => { + 'AE Lock' => 'AE-Speicherung', + 'AE Lock + Exposure Comp.' => 'AE-Speicherung + Belichtungskorrektur', + 'Exposure Compensation' => 'Belichtungskorrektur', + 'No AE' => 'Kein AE', + }, + }, + 'AEXv' => 'AE-Belichtungskorrektur', + 'AE_ISO' => 'AE-ISO-Empfindlichkeit', + 'AF-CPrioritySelection' => { + Description => 'Priorität bei AF-C', + PrintConv => { + 'Focus' => 'Schärfepriorität', + 'Release' => 'Auslösepriorität', + 'Release + Focus' => 'Auslösepriorität & AF', + }, + }, + 'AF-OnForMB-D10' => { + Description => 'AF-ON-Taste (MB-D10)', + PrintConv => { + 'AE Lock (hold)' => 'Belichtung speichern ein/aus', + 'AE Lock (reset on release)' => 'Bel. speichern ein/aus (Reset)', + 'AE Lock Only' => 'Belichtung speichern', + 'AE/AF Lock' => 'Belichtung & Fokus speichern', + 'AF Lock Only' => 'Fokus speichern', + 'AF-On' => 'Autofokus aktiviert', + 'Same as FUNC Button' => 'Wie Funktionstaste', + }, + }, + 'AF-SPrioritySelection' => { + Description => 'Priorität bei AF-S (Einzel-AF)', + PrintConv => { + 'Focus' => 'Schärfepriorität', + 'Release' => 'Auslösepriorität', + }, + }, + 'AFActivation' => { + Description => 'AF-Aktivierung', + PrintConv => { + 'AF-On Only' => 'Nur AF-ON-Taste', + 'Shutter/AF-On' => 'AF-On-Taste & Auslöser', + }, + }, + 'AFAdjustment' => 'AF-Korrektur', + 'AFAndMeteringButtons' => { + Description => 'AF And Mess-Tasten', + PrintConv => { + 'AE lock' => 'AE Speicherung', + 'AF stop' => 'AE Stopp', + 'Metering + AF start' => 'Messung + AF Start', + 'Metering start' => 'Messung Start', + 'No function' => 'Keine Funktion', + }, + }, + 'AFAperture' => 'AF-Blende', + 'AFArea' => 'AF Bereich', + 'AFAreaHeight' => 'AF-Bereichshöhe', + 'AFAreaHeights' => 'AF-Bereichshöhe', + 'AFAreaIllumination' => { + Description => 'Messfeld-LED', + PrintConv => { + 'Auto' => 'Automatisch', + 'Off' => 'Aus', + 'On' => 'Ein', + }, + }, + 'AFAreaMode' => { + Description => 'Messfeldsteuerung', + PrintConv => { + '1-area' => '1 Bereich', + '1-area (high speed)' => '1 Bereich (kurze Verschlußzeit)', + '23-area' => '23 Bereiche', + '3-area (center)?' => '3 Bereiche (mitte)', + '3-area (high speed)' => '3 Bereiche (kurze Verschlußzeit)', + '3-area (left)?' => '3 Bereiche (links)', + '3-area (right)?' => '3 Bereiche (rechts)', + '5-area' => '5 Bereiche', + '9-area' => '9 Bereiche', + 'AF Point Expansion' => 'AF Punkt-Erweiterung', + 'Auto (41 points)' => 'Automatisch (41 Punkte)', + 'Auto-area' => 'Autom. Messfeldgr.', + 'Center' => 'Mitte', + 'Contrast-detect' => 'Kontrasterkennung', + 'Contrast-detect (face priority)' => 'Kontrasterkennung (Gesichtserkennung)', + 'Contrast-detect (normal area)' => 'Kontrasterkennung (Standardbereich)', + 'Contrast-detect (subject tracking)' => 'Kontrasterkennung (Objektverfolgung)', + 'Contrast-detect (wide area)' => 'Kontrasterkennung (großer Bereich)', + 'Default' => 'Standard', + 'Dynamic Area' => 'Dynamisch', + 'Dynamic Area (21 points)' => 'Dynamischer Bereich (21 Punkte)', + 'Dynamic Area (3D-tracking)' => 'Dynamischer Bereich (3D-Nachführung)', + 'Dynamic Area (51 points)' => 'Dynamischer Bereich (51 Punkte)', + 'Dynamic Area (51 points, 3D-tracking)' => 'Dynamischer Bereich (51 Punkte, 3D-Nachführung)', + 'Dynamic Area (9 points)' => 'Dynamischer Bereich (9 Punkte)', + 'Dynamic Area (closest subject)' => 'Dynamic Messfeldgruppensteuerung (priorität der kürzesten Aufnahmedistanz)', + 'Dynamic Area (wide)' => 'Dynamische Messfeldsteuerung (groß)', + 'Dynamic Area (wide, 3D-tracking)' => 'Dynamischer Bereich (groß, 3D-Nachführung)', + 'Face + Tracking' => 'Gesichtserkennung + Nachführung', + 'Face Detect' => 'Gesichtserkennung', + 'Face Detect AF' => 'Gesichtserkennung AF', + 'Face Priority (41 points)' => 'Gesichtserkennung (41 Punkte)', + 'Face Tracking' => 'Gesichtserkennung', + 'Flexible' => 'Angepasst', + 'Flexible Spot' => 'Gesetzter Punkt', + 'Flexizone Multi' => 'Mehrpunkt-Bereich', + 'Flexizone Single' => 'Einpunkt-Bereich', + 'Group Dynamic' => 'Dynamische Messfeldgruppensteuerung', + 'Local' => 'Lokal', + 'Manual' => 'Manuell', + 'Multi' => 'Mehrpunkt', + 'Multi-point AF or AI AF' => 'Mehrpunkt AF oder AI AF', + 'Normal?' => 'Normal', + 'Off (Manual Focus)' => 'Aus (Manueller Fokus)', + 'Selective (for Miniature effect)' => 'Selektiv (für Vorschau-Effekt)', + 'Single (135 points)' => 'Einpunkt (135 Punkte)', + 'Single Area' => 'Einzelfeld', + 'Single Area (wide)' => 'Einzelfeldmessung (groß)', + 'Single-point AF' => 'Einpunkt AF', + 'Spot Focusing' => 'Spotfokussierung', + 'Spot Focusing 2' => 'Spotfokussierung 2', + 'Spot Mode Off' => 'Spot-Modus Aus', + 'Spot Mode On' => 'Spot-Modus Ein', + 'Subject Tracking (41 points)' => 'Objektverfolgung (41 Punkte)', + 'Touch' => 'Berührungspunkt', + 'Tracking' => 'Nachführung', + 'Wide' => 'Weit', + 'Zone' => 'Bereich', + 'Zone AF' => 'Zonen AF', + 'n/a' => '(nicht gesetzt)', + }, + }, + 'AFAreaModeSetting' => { + Description => 'Messfeldsteuerung', + PrintConv => { + '3D-tracking (11 points)' => '3D Nachführung (11 Punkte)', + 'Auto-area' => 'Automatischer Bereich', + 'Center' => 'Mitte', + 'Closest Subject' => 'Nächstes Objekt', + 'Dynamic Area' => 'Dynamisch', + 'Flexible Spot' => 'Gesetzter Punkt', + 'Local' => 'Lokal', + 'Multi' => 'Mehrpunkt', + 'Single Area' => 'Einzelfeld', + 'Wide' => 'Weit', + 'Zone' => 'Bereich', + }, + }, + 'AFAreaWidth' => 'AF-Bereichsbreite', + 'AFAreaWidths' => 'AF-Bereichsbreite', + 'AFAreaXPosition' => 'AF-Bereich X Position', + 'AFAreaXPosition1' => 'AF-Bereich X Position 1', + 'AFAreaXPositions' => 'AF Bereich X Positionen', + 'AFAreaYPosition' => 'AF-Bereich Y Position', + 'AFAreaYPosition1' => 'AF-Bereich Y Position 1', + 'AFAreaYPositions' => 'AF Bereich Y Positionen', + 'AFAreas' => 'AF-Bereiche', + 'AFAssist' => { + Description => 'AF-Hilfslicht', + PrintConv => { + 'Does not emit/Fires' => 'Kein Messlicht/Zündung', + 'Emits/Does not fire' => 'Messlicht/keine Zündung', + 'Emits/Fires' => 'Messlicht/Zündung', + 'Off' => 'Aus', + 'On' => 'Ein', + 'Only ext. flash emits/Fires' => 'Nur ext. Messl./Zündung', + }, + }, + 'AFAssistBeam' => { + Description => 'AF-Hilfslicht Aussendung', + PrintConv => { + 'Does not emit' => 'Deaktiv', + 'Emits' => 'Aktiv', + 'Only ext. flash emits' => 'Nur bei ext. Blitz aktiv', + }, + }, + 'AFAssistLamp' => { + Description => 'AF Hilfslicht', + PrintConv => { + 'Disabled and Not Required' => 'Nicht eingestellt, war nicht nötig', + 'Disabled but Required' => 'Nicht eingestellt, war aber nötig', + 'Enabled but Not Used' => 'Eingestellt, aber nicht verwendet', + 'Fired' => 'Blitz wurde ausgelöst', + }, + }, + 'AFDefocus' => 'AF-Defocus', + 'AFDuringLiveView' => { + Description => 'AF bei Live View-Aufnahmen', + PrintConv => { + 'Disable' => 'Inaktiv', + 'Enable' => 'Aktiv', + 'Live mode' => 'LiveModus', + 'Quick mode' => 'QuickModus', + }, + }, + 'AFFineTune' => { + Description => 'AF-Feinabstimmung', + PrintConv => { + 'Off' => 'Aus', + 'On (1)' => 'Ein (1)', + 'On (2)' => 'Ein (2)', + }, + }, + 'AFFineTuneAdj' => 'AF-Feinabstimmung', + 'AFIlluminator' => { + PrintConv => { + 'Off' => 'Aus', + 'n/a' => '(nicht gesetzt)', + }, + }, + 'AFImageHeight' => 'AF-Bildhöhe', + 'AFImageWidth' => 'AF-Bildbreite', + 'AFInFocus' => 'AF in Fokus', + 'AFInfo' => 'AF-Modus', + 'AFInfo2' => 'AF-Informationen', + 'AFInfo2Version' => 'AF-Info-Version', + 'AFIntegrationTime' => 'AF-Messzeit', + 'AFMicroAdj' => 'AF Feinabstimmung', + 'AFMicroAdjMode' => { + Description => 'AF Feinabstimmung Modus', + PrintConv => { + 'Adjust all by the same amount' => 'Korrektur immer um gleichen Wert', + 'Adjust by lens' => 'Korrektur objektivabhängig', + 'Disable' => 'Deaktiviert', + 'Off' => 'Aus', + 'On' => 'Ein', + }, + }, + 'AFMicroAdjRegisteredLenses' => 'AF Feinabstimmung bekannte Objektive', + 'AFMicroAdjValue' => 'AF Feinabstimmung Wert', + 'AFMicroadjustment' => { + Description => 'AF Feinabstimmung', + PrintConv => { + 'Adjust all by same amount' => 'Alle auf gleichen Wert', + 'Adjust by lens' => 'Abstimmung pro Objektiv', + 'Disable' => 'Deaktivieren', + }, + }, + 'AFMode' => { + Description => 'AF-Modus', + PrintConv => { + 'Face Detection' => 'Gesichtserkennung', + 'Off' => 'Aus', + 'Tracking' => 'Nachführung', + 'n/a' => '(nicht gesetzt)', + }, + }, + 'AFOnAELockButtonSwitch' => { + Description => 'AF-ON/AELocktaste- Schalter', + PrintConv => { + 'Disable' => 'Deaktiviert', + 'Enable' => 'Aktiviert', + }, + }, + 'AFPoint' => { + Description => 'Gewählter AF-Punkt', + PrintConv => { + '(none)' => '(keiner)', + 'Auto AF point selection' => 'Automatische Wahl des AF-Punktes', + 'Bottom' => 'Unten', + 'Bottom (horizontal)' => 'Unten (horizontal)', + 'Bottom (vertical)' => 'Unten (vertikal)', + 'Bottom Center' => 'Unten Mitte', + 'Bottom Left' => 'Unten Links', + 'Bottom Right' => 'Unten Rechts', + 'Bottom-center (horizontal)' => 'Unten Mitte (horizontal)', + 'Bottom-center (vertical)' => 'Unten Mitte (vertikal)', + 'Bottom-left' => 'Unten Links', + 'Bottom-left (horizontal)' => 'Unten Links (horizontal)', + 'Bottom-left (vertical)' => 'Unten Links (vertikal)', + 'Bottom-right' => 'Unten Rechts', + 'Bottom-right (horizontal)' => 'Unten Rechts (horizontal)', + 'Bottom-right (vertical)' => 'Unten Rechts (vertikal)', + 'Center' => 'Mitte', + 'Center (horizontal)' => 'Mitte (horizontal)', + 'Center (vertical)' => 'Mitte (vertikal)', + 'Center Left' => 'Mitte Links', + 'Center Right' => 'Mitte Rechts', + 'Face Detect' => 'Gesichtserkennung', + 'Far Left' => 'Weit links', + 'Far Left (horizontal)' => 'Weit links (horizontal)', + 'Far Left (vertical)' => 'Weit links (vertikal)', + 'Far Left/Right of Center' => 'Weit Links/Rechts der Mitte', + 'Far Left/Right of Center/Bottom' => 'Weit Links/Rechts der Mitte/Unten', + 'Far Right' => 'Weit rechts', + 'Far Right (horizontal)' => 'Weit rechts (horizontal)', + 'Far Right (vertical)' => 'Weit rechts (vertikal)', + 'Left' => 'Links', + 'Left (horizontal)' => 'Links (horizontal)', + 'Left (or n/a)' => 'Links (oder Nicht gesetzt)', + 'Left (vertical)' => 'Links (vertikal)', + 'Lower Far Left' => 'Unten ganz links', + 'Lower Far Right' => 'Unten ganz rechts', + 'Lower-left' => 'Links unten', + 'Lower-left (horizontal)' => 'Links unten (horizontal)', + 'Lower-left (vertical)' => 'Links unten (vertikal)', + 'Lower-middle' => 'Untere Mitte', + 'Lower-right' => 'Rechts unten', + 'Lower-right (horizontal)' => 'Rechts unten (horizontal)', + 'Lower-right (vertical)' => 'Unten rechts (vertikal)', + 'Manual AF point selection' => 'Manuell gewählter AF-Punkt', + 'Mid-left' => 'Links mitte', + 'Mid-left (horizontal)' => 'Links mitte (horizontal)', + 'Mid-left (vertical)' => 'Links mitte (vertikal)', + 'Mid-right' => 'Rechts mitte', + 'Mid-right (horizontal)' => 'Rechts mitte (horizontal)', + 'Mid-right (vertical)' => 'Rechts mitte (vertikal)', + 'Near Left' => 'Nahe Links', + 'Near Left/Right of Center' => 'Nahe Links/Rechts der Mitte', + 'Near Right' => 'Nahe Rechts', + 'Near Upper/Left' => 'Nahe Links oben', + 'None' => 'Keiner', + 'None (MF)' => 'Keiner (MF)', + 'Right' => 'Rechts', + 'Right (horizontal)' => 'Rechts (horizontal)', + 'Right (vertical)' => 'Rechts (vertikal)', + 'Top' => 'Oben', + 'Top (horizontal)' => 'Oben (horizontal)', + 'Top (vertical)' => 'Oben (vertikal)', + 'Top Center' => 'Oben Mitte', + 'Top Left' => 'Oben Links', + 'Top Near-left' => 'Oben nahe-Links', + 'Top Near-right' => 'Nahe Rechts-oben', + 'Top Right' => 'Oben Rechts', + 'Top-center (horizontal)' => 'Oben Mitte (horizontal)', + 'Top-center (vertical)' => 'Oben Mitte (vertikal)', + 'Top-left' => 'Oben Links', + 'Top-left (horizontal)' => 'Oben Links (horizontal)', + 'Top-left (vertical)' => 'Oben Links (vertikal)', + 'Top-right' => 'Oben Rechts', + 'Top-right (horizontal)' => 'Oben Rechts (horizontal)', + 'Top-right (vertical)' => 'Oben Rechts (vertikal)', + 'Upper Far Left' => 'Oben ganz links', + 'Upper Far Right' => 'Oben ganz rechts', + 'Upper Left' => 'Links oben', + 'Upper Right' => 'Rechts oben', + 'Upper-left' => 'Links oben', + 'Upper-left (horizontal)' => 'Links oben (horizontal)', + 'Upper-left (vertical)' => 'Links oben (vertikal)', + 'Upper-middle' => 'Obere Mitte', + 'Upper-right' => 'Rechts oben', + 'Upper-right (horizontal)' => 'Rechts oben (horizontal)', + 'Upper-right (vertical)' => 'Oben rechts (vertikal)', + 'n/a' => '(nicht gesetzt)', + }, + }, + 'AFPointActivationArea' => { + Description => 'AF-Messfeld-Aktivierungsbereich', + PrintConv => { + 'Expanded' => 'Erweitert', + }, + }, + 'AFPointAreaExpansion' => { + Description => 'AF-Messbereich Ausweitung', + PrintConv => { + 'All 45 points area' => 'Alle 45 Punkte', + 'Disable' => 'Aus', + 'Enable' => 'Ein', + 'Left/right AF points' => 'Möglich (linkes/rechtes zusätzliches AF-Messfeld)', + 'Surrounding AF points' => 'Möglich (entsprechendes zusätzliches AF-Messfeld)', + }, + }, + 'AFPointAtShutterRelease' => { + Description => 'AF-Punkt beim Auslösen', + PrintConv => { + '(out of focus)' => '(ausserhalb Fokus)', + 'Bottom (horizontal)' => 'Unten (horizontal)', + 'Bottom (vertical)' => 'Unten (vertikal)', + 'Center (horizontal)' => 'Mitte (horizontal)', + 'Center (vertical)' => 'Mitte (vertikal)', + 'Far Left' => 'Weit links', + 'Far Left (horizontal)' => 'Weit links (horizontal)', + 'Far Left (vertical)' => 'Weit links (vertikal)', + 'Far Right' => 'Weit rechts', + 'Far Right (horizontal)' => 'Weit rechts (horizontal)', + 'Far Right (vertical)' => 'Weit rechts (vertikal)', + 'Left' => 'Links', + 'Left (horizontal)' => 'Links (horizontal)', + 'Left (vertical)' => 'Links (vertikal)', + 'Lower Far Left' => 'Unten ganz links', + 'Lower Far Right' => 'Unten ganz rechts', + 'Lower-left' => 'Links unten', + 'Lower-left (horizontal)' => 'Links unten (horizontal)', + 'Lower-left (vertical)' => 'Links unten (vertikal)', + 'Lower-middle' => 'Unten mitte', + 'Lower-right' => 'Rechts unten', + 'Lower-right (horizontal)' => 'Rechts unten (horizontal)', + 'Lower-right (vertical)' => 'Rechts unten (vertikal)', + 'Near Left' => 'Nahe links', + 'Near Right' => 'Nahe rechts', + 'Right' => 'Rechts', + 'Right (horizontal)' => 'Rechts (horizontal)', + 'Right (vertical)' => 'Rechts (vertikal)', + 'Top (horizontal)' => 'Oben (horizontal)', + 'Top (vertical)' => 'Oben (vertikal)', + 'Upper Far Left' => 'Oben ganz links', + 'Upper Far Right' => 'Oben ganz rechts', + 'Upper-left' => 'Links oben', + 'Upper-left (horizontal)' => 'Links oben (horizontal)', + 'Upper-left (vertical)' => 'Links oben (vertikal)', + 'Upper-middle' => 'Oben mitte', + 'Upper-right' => 'Rechts oben', + 'Upper-right (horizontal)' => 'Rechts oben (horizontal)', + 'Upper-right (vertical)' => 'Rechts oben (vertikal)', + }, + }, + 'AFPointAutoSelection' => { + Description => 'Automatische AF-Feldwahl', + PrintConv => { + 'Control-direct:disable/Main:disable' => 'Schnelleinstellrad-Direkt:nicht möglich/Haupt-Wahlrad:nein', + 'Control-direct:disable/Main:enable' => 'Schnelleinstellrad-Direkt:nicht möglich/Haupt-Wahlrad:möglich', + 'Control-direct:enable/Main:enable' => 'Schnelleinstellrad-Direkt:möglich/Haupt-Wahlrad:möglich', + }, + }, + 'AFPointBrightness' => { + Description => 'AF-Feld Helligkeit', + PrintConv => { + 'Brighter' => 'Heller', + 'Extra High' => 'Extra Hoch', + 'High' => 'Hoch', + 'Low' => 'Niedrig', + }, + }, + 'AFPointDisplayDuringFocus' => { + Description => 'AF-Feld Anzeige während Fokus', + PrintConv => { + 'Off' => 'Aus', + 'On' => 'Ein', + 'On (when focus achieved)' => 'Ein (nach Scharfeinstellung)', + }, + }, + 'AFPointIllumination' => { + Description => 'Messfeld-LED', + PrintConv => { + 'Auto' => 'Automatisch', + 'Off' => 'Aus', + 'On' => 'Ein', + }, + }, + 'AFPointInFocus' => { + Description => 'AF-Punkt im Fokus', + PrintConv => { + '(none)' => '(keiner)', + 'Bottom (horizontal)' => 'Unten (horizontal)', + 'Bottom (vertical)' => 'Unten (vertikal)', + 'Center (horizontal)' => 'Mitte (horizontal)', + 'Center (vertical)' => 'Mitte (vertikal)', + 'Far Left' => 'Weit links', + 'Far Left (horizontal)' => 'Weit links(horizontal)', + 'Far Left (vertical)' => 'Weit links (vertikal)', + 'Far Right' => 'Weit rechts', + 'Far Right (horizontal)' => 'Weit rechts (horizontal)', + 'Far Right (vertical)' => 'Weit rechts (vertikal)', + 'Left' => 'Links', + 'Left (horizontal)' => 'Links (horizontal)', + 'Left (vertical)' => 'Links (vertikal)', + 'Lower Far Left' => 'Unten ganz Links', + 'Lower Far Right' => 'Unten ganz rechts', + 'Lower-left' => 'Links unten', + 'Lower-left (horizontal)' => 'Links unten (horizontal)', + 'Lower-left (vertical)' => 'Links unten (vertikal)', + 'Lower-middle' => 'Unten mitte', + 'Lower-right' => 'Rechts unten', + 'Lower-right (horizontal)' => 'Rechts unten (horizontal)', + 'Lower-right (vertical)' => 'Rechts unten (vertikal)', + 'Near Left' => 'Nahe links', + 'Near Right' => 'Nahe rechts', + 'Right' => 'Rechts', + 'Right (horizontal)' => 'Rechts (horizontal)', + 'Right (vertical)' => 'Rechts (vertikal)', + 'Top (horizontal)' => 'Oben (horizontal)', + 'Top (vertical)' => 'Oben (vertikal)', + 'Upper Far Left' => 'Oben ganz links', + 'Upper Far Right' => 'Oben ganz rechts', + 'Upper-left' => 'Links oben', + 'Upper-left (horizontal)' => 'Links oben (horizontal)', + 'Upper-left (vertical)' => 'Links oben (vertikal)', + 'Upper-middle' => 'Oben mitte', + 'Upper-right' => 'Rechts oben', + 'Upper-right (horizontal)' => 'Rechts oben (horizontal)', + 'Upper-right (vertical)' => 'Rechts oben (vertikal)', + }, + }, + 'AFPointMode' => { + Description => 'AF-Punkt-Modus', + PrintConv => { + 'Auto' => 'Automatisch', + }, + }, + 'AFPointPosition' => 'AF-Punkt Position', + 'AFPointRegistration' => { + Description => 'AF-Feld Speicherung', + PrintConv => { + 'Automatic' => 'Automatisch', + 'Bottom' => 'Unten', + 'Center' => 'Mitte', + 'Extreme Left' => 'Ganz links', + 'Extreme Right' => 'Ganz rechts', + 'Left' => 'Links', + 'Right' => 'Rechts', + 'Top' => 'Oben', + }, + }, + 'AFPointSelected' => { + Description => 'AF gewählter Punkt', + PrintConv => { + 'Auto' => 'Automatisch', + 'Automatic Tracking AF' => 'Nachführ AF', + 'Bottom' => 'Unten', + 'Bottom-left' => 'Unten-links', + 'Bottom-right' => 'Unten-rechts', + 'Center' => 'Mitte', + 'Face Detect AF' => 'Gesichtserkennungs-AF', + 'Far Left' => 'Weit links', + 'Far Right' => 'Weit rechts', + 'Fixed Center' => 'Auf Mitte fixiert', + 'Left' => 'Links', + 'Lower Far Left' => 'Unten weit Links', + 'Lower Far Right' => 'Unten weit Rechts', + 'Lower-left' => 'Links unten', + 'Lower-middle' => 'Untere Mitte', + 'Lower-right' => 'Rechts unten', + 'Mid-left' => 'Links mitte', + 'Mid-right' => 'Rechts mitte', + 'Near Left' => 'Nahe Links', + 'Near Right' => 'Nahe Rechts', + 'Right' => 'Rechts', + 'Top' => 'Oben', + 'Top-left' => 'Oben-links', + 'Top-right' => 'Oben-rechts', + 'Upper Far Left' => 'Oben weit Links', + 'Upper Far Right' => 'Oben weit Rechts', + 'Upper-left' => 'Links oben', + 'Upper-middle' => 'Obere Mitte', + 'Upper-right' => 'Rechts oben', + }, + }, + 'AFPointSelected2' => { + Description => 'AF gewählter Punkt 2', + PrintConv => { + 'Auto' => 'Automatisch', + 'Bottom' => 'Unten', + 'Center' => 'Mitte', + 'Left' => 'Links', + 'Lower-left' => 'Links unten', + 'Lower-right' => 'Rechts unten', + 'Mid-left' => 'Links mitte', + 'Mid-right' => 'Rechts mitte', + 'Right' => 'Rechts', + 'Top' => 'Oben', + 'Upper-left' => 'Links oben', + 'Upper-right' => 'Rechts oben', + }, + }, + 'AFPointSelection' => { + Description => 'AF-Messfeldauswahl', + PrintConv => { + '11 Points' => '11 Messfelder', + '51 Points' => '51 Messfelder (3D-Tracking)', + }, + }, + 'AFPointSelectionMethod' => { + Description => 'Wahlmethode für AF-Messfeld', + PrintConv => { + 'Multi-controller direct' => 'Multicontroller', + 'Quick Control Dial direct' => 'Schnelleinstellrad', + }, + }, + 'AFPointSet' => { + Description => 'AF-Punkt Einstellung', + PrintConv => { + 'No' => 'Nein', + 'Yes' => 'Ja', + }, + }, + 'AFPointSpotMetering' => 'Anzahl AF-Messff./Spotmsg.', + 'AFPoints' => 'AF-Punkte', + 'AFPointsInFocus' => { + Description => 'AF-Punkte im Fokus', + PrintConv => { + 'All' => 'Alle', + 'All 11 Points' => 'Alle 11 Punkte', + 'Bottom' => 'Unten', + 'Bottom, Center' => 'Unten, Mitte', + 'Bottom-center' => 'Unten-mitte', + 'Bottom-left' => 'Unten-links', + 'Bottom-right' => 'Unten-rechts', + 'Center' => 'Mitte', + 'Center (horizontal)' => 'Mitte (horizontal)', + 'Center (vertical)' => 'Mitte (vertikal)', + 'Center+Right' => 'Mitte Rechts', + 'Far Left' => 'Weit links', + 'Far Right' => 'Weit rechts', + 'Fixed Center or Multiple' => 'Auf Mitte fixiert oder mehrere', + 'Left' => 'Links', + 'Left+Center' => 'Links Mitte', + 'Left+Right' => 'Links Rechts', + 'Lower-left' => 'Links unten', + 'Lower-left, Bottom' => 'Links unten, Unten', + 'Lower-left, Mid-left' => 'Links unten, Links mitte', + 'Lower-right' => 'Rechts unten', + 'Lower-right, Bottom' => 'Rechts unten, Unten', + 'Lower-right, Mid-right' => 'Rechts unten, Rechts mitte', + 'Mid-left' => 'Links mitte', + 'Mid-left, Center' => 'Links mitte, Mitte', + 'Mid-right' => 'Rechts mitte', + 'Mid-right, Center' => 'Rechts mitte, Mitte', + 'None' => 'Keiner', + 'None (MF)' => 'Keiner (MF)', + 'Right' => 'Rechts', + 'Top' => 'Oben', + 'Top, Center' => 'Oben, Mitte', + 'Top-center' => 'Oben-Mitte', + 'Top-left' => 'Oben-links', + 'Top-right' => 'Oben-rechts', + 'Upper-left' => 'Links oben', + 'Upper-left, Mid-left' => 'Links oben, Links mitte', + 'Upper-left, Top' => 'Links oben, Oben', + 'Upper-right' => 'Rechts oben', + 'Upper-right, Mid-right' => 'Rechts oben, Rechts mitte', + 'Upper-right, Top' => 'Rechts oben, Oben', + }, + }, + 'AFPointsInFocus1D' => 'AF-Punkte im Fokus 1D', + 'AFPointsInFocus5D' => { + Description => 'AF-Punkte im Fokus', + PrintConv => { + 'Bottom' => 'Unten', + 'Center' => 'Mitte', + 'Left' => 'Links', + 'Lower-left' => 'Unten links', + 'Lower-right' => 'Rechts unten', + 'Right' => 'Rechts', + 'Top' => 'Oben', + 'Upper-left' => 'Links oben', + 'Upper-right' => 'Rechts oben', + }, + }, + 'AFPointsSelected' => 'AF gewählte Punkte', + 'AFPointsUnknown1' => { + Description => 'AF-Punkte Unbekannt 1', + PrintConv => { + 'All' => 'Alle', + 'Bottom' => 'Unten', + 'Center' => 'Mitte', + 'Central 9 points' => 'Alle mittleren 9 Punkte', + 'Left' => 'Links', + 'Lower-left' => 'Links unten', + 'Lower-right' => 'Rechts unten', + 'Mid-left' => 'Links mitte', + 'Mid-right' => 'Rechts mitte', + 'Right' => 'Rechts', + 'Top' => 'Oben', + 'Upper-left' => 'Links oben', + 'Upper-right' => 'Rechts oben', + }, + }, + 'AFPointsUnknown2' => { + Description => 'AF-Punkte Unbekannt 2?', + PrintConv => { + 'Auto' => 'Automatisch', + 'Bottom' => 'Unten', + 'Center' => 'Mitte', + 'Left' => 'Links', + 'Lower-left' => 'Links unten', + 'Lower-right' => 'Rechts unten', + 'Mid-left' => 'Links mitte', + 'Mid-right' => 'Rechts mitte', + 'Right' => 'Rechts', + 'Top' => 'Oben', + 'Upper-left' => 'Links oben', + 'Upper-right' => 'Rechts oben', + }, + }, + 'AFPointsUsed' => { + Description => 'Verwendete AF-Punkte', + PrintConv => { + 'All 11 Points' => 'Alle 11 Punkte', + 'Bottom' => 'Unten', + 'Center' => 'Mitte', + 'Far Left' => 'Weit links', + 'Far Right' => 'Weit rechts', + 'Lower-left' => 'Links unten', + 'Lower-right' => 'Rechts unten', + 'Mid-left' => 'Links mitte', + 'Mid-right' => 'Rechts mitte', + 'Top' => 'Oben', + 'Upper-left' => 'Links oben', + 'Upper-right' => 'Rechts oben', + }, + }, + 'AFPredictor' => 'AF-Prädiktor', + 'AFResponse' => 'Verwendeter AF', + 'AFSearch' => { + Description => 'AF Fokussierung', + PrintConv => { + 'Not Ready' => 'Nicht bereit', + 'Ready' => 'Bereit', + }, + }, + 'AFSensorActive' => { + Description => 'Aktiver AF Sensor', + PrintConv => { + 'Bottom' => 'Unten', + 'Bottom-left' => 'Unten Links', + 'Bottom-right' => 'Unten Rechts', + 'Center Vertical' => 'Mitte vertikal', + 'Middle Horizontal' => 'Mitte horizontal', + 'Top' => 'Oben', + 'Top-left' => 'Oben Links', + 'Top-right' => 'Rechts Oben', + }, + }, + 'AFStatusActiveSensor' => { + Description => 'Status aktiver AF Sensor', + PrintConv => { + 'In Focus' => 'Im Fokus', + 'Out of Focus' => 'Nicht im Fokus', + }, + }, + 'AFStatusBottom' => { + Description => 'AF Status Unten', + PrintConv => { + 'In Focus' => 'Im Fokus', + 'Out of Focus' => 'Nicht im Fokus', + }, + }, + 'AFStatusBottom-left' => { + Description => 'AF Status Unten Links', + PrintConv => { + 'In Focus' => 'Im Fokus', + 'Out of Focus' => 'Nicht im Fokus', + }, + }, + 'AFStatusBottom-right' => { + Description => 'AF Status Unten Rechts', + PrintConv => { + 'In Focus' => 'Im Fokus', + 'Out of Focus' => 'Nicht im Fokus', + }, + }, + 'AFStatusCenterHorizontal' => { + Description => 'AF Status Mitte horizontal', + PrintConv => { + 'In Focus' => 'Im Fokus', + 'Out of Focus' => 'Nicht im Fokus', + }, + }, + 'AFStatusCenterVertical' => { + Description => 'AF Status Mitte vertikal', + PrintConv => { + 'In Focus' => 'Im Fokus', + 'Out of Focus' => 'Nicht im Fokus', + }, + }, + 'AFStatusLeft' => { + Description => 'AF Status Links', + PrintConv => { + 'In Focus' => 'Im Fokus', + 'Out of Focus' => 'Nicht im Fokus', + }, + }, + 'AFStatusMiddleHorizontal' => { + Description => 'AF Status Mitte horizontal', + PrintConv => { + 'In Focus' => 'Im Fokus', + 'Out of Focus' => 'Nicht im Fokus', + }, + }, + 'AFStatusRight' => { + Description => 'AF Status Rechts', + PrintConv => { + 'In Focus' => 'Im Fokus', + 'Out of Focus' => 'Nicht im Fokus', + }, + }, + 'AFStatusTop' => { + Description => 'AF Status Oben', + PrintConv => { + 'In Focus' => 'Im Fokus', + 'Out of Focus' => 'Nicht im Fokus', + }, + }, + 'AFStatusTop-left' => { + Description => 'AF Status Oben Links', + PrintConv => { + 'In Focus' => 'Im Fokus', + 'Out of Focus' => 'Nicht im Fokus', + }, + }, + 'AFStatusTop-right' => { + Description => 'AF Status Oben Rechts', + PrintConv => { + 'In Focus' => 'Im Fokus', + 'Out of Focus' => 'Nicht im Fokus', + }, + }, + 'AFType' => { + Description => 'AF-Typ', + PrintConv => { + '15-point' => '15 Punkte', + '19-point' => '19 Punkte', + }, + }, + 'AIServoContinuousShooting' => 'Auslösepriorität', + 'AIServoImagePriority' => { + Description => 'AI Servo Priorität 1./2. Bild', + PrintConv => { + '1: AF, 2: Drive speed' => 'AF-Priorität/Transportgeschwindigkeit', + '1: AF, 2: Tracking' => 'AF-Priorität/Nachführpriorität', + '1: Release, 2: Drive speed' => 'Auslösung/Transportgeschwindigkeit', + '1: Release, 2: Tracking' => '1: Auslösung, 2: Nachführung', + }, + }, + 'AIServoTrackingMethod' => { + Description => 'AI Servo AF Nachführung', + PrintConv => { + 'Continuous AF track priority' => 'AF Nachführ-Priorität', + 'Main focus point priority' => 'Hauptfokussierungsfeld', + }, + }, + 'AIServoTrackingSensitivity' => { + Description => 'AI Servo Empfindlichkeit', + PrintConv => { + 'Fast' => 'Schnell', + 'Medium Fast' => 'Mittel-Schnell', + 'Medium Slow' => 'Mittel', + 'Slow' => 'Langsam', + }, + }, + 'APEVersion' => 'APE-Version', + 'ARMVersion' => 'ARM-Version', + 'AccessDate' => 'Zugriffsdatum', + 'AccessoryType' => 'Zubehör-Typ', + 'ActionAdvised' => 'Aktion empfohlen', + 'ActiveArea' => 'Aktiver Bereich', + 'ActiveD-Lighting' => { + Description => 'Aktives D-Lighting', + PrintConv => { + 'High' => 'Hoch', + 'Low' => 'Leicht', + 'Off' => 'Aus', + 'On' => 'Ein', + }, + }, + 'ActiveD-LightingMode' => { + PrintConv => { + 'High' => 'Hoch', + 'Low' => 'Leicht', + 'Off' => 'Aus', + }, + }, + 'AddAspectRatioInfo' => { + Description => 'Seitenverhältnisinfo zufügen', + PrintConv => { + 'Off' => 'Aus', + }, + }, + 'AddOriginalDecisionData' => { + Description => 'Originaldaten zufügen', + PrintConv => { + 'Off' => 'Aus', + 'On' => 'Ein', + }, + }, + 'Address' => 'Adresse', + 'AdjustmentMode' => 'Korrekturmodus', + 'AdultContentWarning' => { + PrintConv => { + 'Unknown' => 'Unbekannt', + }, + }, + 'AdvancedRaw' => { + PrintConv => { + 'Off' => 'Aus', + 'On' => 'Ein', + }, + }, + 'AdvancedSceneMode' => { + PrintConv => { + 'Creative Macro' => 'Makro kreativ', + 'Flower' => 'Blumen', + 'HDR B&W' => 'HDR Schwarz-Weiß', + 'High Key' => 'High-Key', + 'Indoor Sports' => 'Hallensport', + 'Low Key' => 'Low-Key', + 'Outdoor Sports' => 'Freiluftsport', + }, + }, + 'AdvancedSceneType' => 'Erweiterter Szenentyp', + 'AlphaByteCount' => 'Anzahl Bytes der Alpha-Kanal-Daten', + 'AlphaChannelsNames' => 'Alpha-Kanal-Namen', + 'AlphaDataDiscard' => { + Description => 'Verworfene Alpha-Kanal-Daten', + PrintConv => { + 'Flexbits Discarded' => 'FlexBits verworfen', + 'Full Resolution' => 'Volle Auflösung', + 'HighPass Frequency Data Discarded' => 'Hochpass-Frequenz-Daten verworfen', + 'Highpass and LowPass Frequency Data Discarded' => 'Hochpass- und Tiefpass-Frequenz-Daten verworfen', + }, + }, + 'AlphaOffset' => 'Alpha-Kanal-Datenposition', + 'AlreadyApplied' => 'Bereits zugewiesen', + 'AnalogBalance' => 'Analog-Balance', + 'Annotation' => 'Anmerkung', + 'Annotations' => 'Anmerkungen', + 'Anti-Blur' => { + Description => 'Verwacklungsschutz', + PrintConv => { + 'Off' => 'Aus', + 'On (Continuous)' => 'Ein (Kontinuierlich)', + 'On (Shooting)' => 'Ein (Aufnahme)', + 'n/a' => '(nicht gesetzt)', + }, + }, + 'AntiAliasStrength' => 'Anti-Aliasing Stärke', + 'Aperture' => 'Blende', + 'ApertureDisplayed' => 'Angezeigte Blende', + 'ApertureRange' => { + Description => 'Einstellung Verschlusszeitenbereich', + PrintConv => { + 'Disable' => 'Nicht möglich', + 'Enable' => 'Möglich', + }, + }, + 'ApertureRingUse' => { + Description => 'Blendenring-Verwendung', + PrintConv => { + 'Permitted' => 'Erlaubt', + 'Prohibited' => 'Nicht erlaubt', + }, + }, + 'ApertureSetting' => 'Blendeneinstellung', + 'ApertureValue' => 'Blende', + 'ApplicationRecordVersion' => 'IPTC-Modell-2-Version', + 'ApplyShootingMeteringMode' => { + Description => 'Angewandter Belichtungs-/Messmodus', + PrintConv => { + 'Disable' => 'Nicht möglich', + 'Enable' => 'Möglich', + }, + }, + 'ApproximateFNumber' => 'F-Wert angenähert', + 'ApproximateFocusDistance' => 'Fokus-Distanz angenähert', + 'ArtFilter' => { + Description => 'Kunst Filter', + PrintConv => { + 'Drawing' => 'Zeichnung', + 'Fish Eye' => 'Fischauge', + 'Off' => 'Aus', + 'Reflection' => 'Reflektierung', + 'Soft Focus' => 'Weichzeichner', + 'Soft Focus 2' => 'Weichzeichner 2', + 'Sparkle' => 'Perleffekt', + 'Watercolor' => 'Wasserfarbe', + 'Watercolor II' => 'Wasserfarbe II', + }, + }, + 'ArtFilterEffect' => { + Description => 'Filtereffekt Kunst', + PrintConv => { + 'B&W' => 'Schwarz/Weiß', + 'Drawing' => 'Zeichnung', + 'Fish Eye' => 'Fischauge', + 'No Effect' => 'Ohne Effekt', + 'Off' => 'Aus', + 'Reflection' => 'Reflektierung', + 'Soft Focus' => 'Weichzeichner', + 'Soft Focus 2' => 'Weichzeichner 2', + 'Sparkle' => 'Perleffekt', + 'Watercolor' => 'Wasserfarbe', + 'Watercolor II' => 'Wasserfarbe II', + }, + }, + 'ArtMode' => { + PrintConv => { + 'Silent Movie' => 'Stillleben', + }, + }, + 'Artist' => 'Künstler', + 'ArtworkCreator' => 'Artwork Ersteller', + 'AsShotICCProfile' => 'Aufnahme Farbprofil', + 'AsShotNeutral' => 'Aufnahme Neutral', + 'AsShotPreProfileMatrix' => 'Aufnahme Pre Profil Matrix', + 'AsShotProfileName' => 'Aufnahme Pre Profilname', + 'AsShotWhiteXY' => 'Aufnahme Weiß XY', + 'AspectRatio' => 'Bildformat', + 'AssignBktButton' => { + Description => 'Zugeordnete Belichtungsreihen-Taste', + PrintConv => { + 'Auto Bracketing' => 'Automatische Belichtungsreihe', + 'Multiple Exposure' => 'Mehrfachbelichtung', + }, + }, + 'AssignFuncButton' => { + Description => 'FUNC.-Taste zuordnen', + PrintConv => { + 'Exposure comp./AEB setting' => 'Belichtungskorrektur/AEB-Einstellung', + 'Image jump with main dial' => 'Bildsprung mit Haupt-Wahlrad', + 'Image quality' => 'Qualität ändern', + 'LCD brightness' => 'LCD-Helligkeit', + 'Live view function settings' => 'Livebild Funktionseinstellung', + }, + }, + 'AssistButtonFunction' => { + Description => 'Funktion Assist-Taste', + PrintConv => { + 'Av+/- (AF point by QCD)' => 'Av+/- (AF-Feld mit Daumenrad)', + 'FE lock' => 'FE Blitzmesswertspeicherung', + 'Select HP (while pressing)' => 'Ausw.G.pos.(Ass-Taste gedr.)', + 'Select Home Position' => 'Auswahl Grundposition', + }, + }, + 'Audio' => { + PrintConv => { + 'No' => 'Nein', + 'Yes' => 'Ja', + }, + }, + 'AudioCodecID' => { + PrintConv => { + 'Unknown -' => 'Unbekannt -', + }, + }, + 'AudioDuration' => 'Audiodauer', + 'AudioOutcue' => 'Audio-Outcue', + 'AudioSamplingRate' => 'Audio-Samplingrate', + 'AudioSamplingResolution' => 'Audio-Samplingauflösung', + 'AudioType' => 'Audiotyp', + 'Author' => 'Autor', + 'AuthorURL' => 'Autor URL', + 'AuthorsPosition' => 'Autorenposition', + 'AutoAperture' => { + Description => 'Blendenring auf A', + PrintConv => { + 'Off' => 'Aus', + 'On' => 'Ein', + }, + }, + 'AutoBracket' => 'Automatische Belichtungsreihe', + 'AutoBracketModeM' => { + Description => 'Belichtungsreihen bei M', + PrintConv => { + 'Flash Only' => 'Nur Blitz', + 'Flash/Aperture' => 'Blitz & Blende', + 'Flash/Speed' => 'Blitz & Zeit', + 'Flash/Speed/Aperture' => 'Blitz, Zeit & Blende', + }, + }, + 'AutoBracketOrder' => 'BKT-Reihenfolge', + 'AutoBracketSet' => { + Description => 'Belichtungsreihen', + PrintConv => { + 'AE & Flash' => 'Belichtung & Blitz', + 'AE Only' => 'Nur Belichtung', + 'Exposure' => 'Belichtung', + 'Flash Only' => 'Nur Blitz', + 'WB Bracketing' => 'Weißabgleichs-Belichtungsreihe', + }, + }, + 'AutoBracketing' => { + Description => 'Automatische Belichtungsreihe', + PrintConv => { + 'AE' => 'Belichtung', + 'Contrast' => 'Kontrast', + 'Effect' => 'Effekt', + 'No flash & flash' => 'Kein Blitz & Blitz', + 'Off' => 'Aus', + 'On' => 'Ein', + 'WB' => 'Weißabgleich', + 'WB2' => 'Weißabgleich 2', + }, + }, + 'AutoBracketingSet' => { + Description => 'Automatische Belichtungsreihen-Einstellung', + PrintConv => { + 'AE & Flash' => 'Belichtung & Blitz', + 'AE Only' => 'Nur Belichtung', + 'Flash Only' => 'Nur Blitz', + 'WB Bracketing' => 'Weißabgleich-Belichtungsreihe', + }, + }, + 'AutoBrightness' => 'Helligkeit Auto', + 'AutoContrast' => 'Kontrast Auto', + 'AutoDistortionControl' => { + Description => 'Automatische Verzeichnungskontrolle', + PrintConv => { + 'Off' => 'Aus', + 'On' => 'Ein', + }, + }, + 'AutoExposure' => 'Belichtung Auto', + 'AutoExposureBracketing' => { + Description => 'Auto-Belichtungsreihe', + PrintConv => { + 'Off' => 'Aus', + 'On' => 'Ein', + }, + }, + 'AutoFP' => { + Description => 'FP-Kurzzeitsynchr.', + PrintConv => { + 'Off' => 'Aus', + 'On' => 'Ein', + }, + }, + 'AutoFocus' => { + Description => 'Auto-Fokus', + PrintConv => { + 'Off' => 'Deaktiviert', + 'On' => 'Aktiviert', + }, + }, + 'AutoISO' => { + Description => 'ISO-Automatik', + PrintConv => { + 'Off' => 'Aus', + 'On' => 'Ein', + 'On (high sensitivity)' => 'Ein (Hohe Empfindlichkeit)', + }, + }, + 'AutoISOMax' => 'ISO-Automatik Max', + 'AutoISOMinShutterSpeed' => 'ISO-Automatik Längste Belichtungszeit', + 'AutoLightingOptimizer' => { + Description => 'Autom. Belichtungsoptimierung', + PrintConv => { + 'Disable' => 'Inaktiv', + 'Enable' => 'Aktiv', + 'Low' => 'Gering', + 'Off' => 'Aus', + 'Strong' => 'Stark', + 'n/a' => '(nicht gesetzt)', + }, + }, + 'AutoLightingOptimizerOn' => { + PrintConv => { + 'No' => 'Nein', + 'Yes' => 'Ja', + }, + }, + 'AutoPortraitFramed' => { + PrintConv => { + 'No' => 'Nein', + 'Yes' => 'Ja', + }, + }, + 'AutoRedEye' => { + PrintConv => { + 'Off' => 'Aus', + 'On' => 'Ein', + }, + }, + 'AutoRotate' => { + Description => 'Automatische Bilddrehung', + PrintConv => { + 'None' => 'Keine', + 'Rotate 180' => '180° gedreht', + 'Rotate 270 CW' => '90° gegen den Uhrzeigersinn', + 'Rotate 90 CW' => '90° im Uhrzeigersinn', + 'n/a' => '(nicht gesetzt)', + }, + }, + 'AutoShadows' => 'Schatten Auto', + 'AuxiliaryLens' => 'Vorsatzlinse', + 'AvApertureSetting' => 'Av Blenden-Einstellung', + 'AvSettingWithoutLens' => { + Description => 'Blendeneinstellung ohne Objektiv', + PrintConv => { + 'Disable' => 'Nicht möglich', + 'Enable' => 'Möglich', + }, + }, + 'BWFilter' => 'S/W-Filter', + 'BWMode' => { + Description => 'Schwarz-Weiß Modus', + PrintConv => { + 'Off' => 'Aus', + 'On' => 'Ein', + }, + }, + 'BabyAge' => 'Kindesalter', + 'BabyName' => 'Kindesname', + 'BackLight' => 'Hintergrundbeleuchtung', + 'BackgroundColor' => 'Hintergrundfarbe', + 'BackgroundColorIndicator' => 'Indikator Hintergrundfarbe', + 'BackgroundColorValue' => 'Hintergrundfarbwert', + 'BackgroundTiling' => { + PrintConv => { + 'No' => 'Nein', + 'Yes' => 'Ja', + }, + }, + 'BannerImageType' => { + PrintConv => { + 'None' => 'Keines', + }, + }, + 'BaseExposureCompensation' => 'Basis-Belichtungskorrektur', + 'BaseISO' => 'Basis-ISO', + 'BaseName' => 'Basisname', + 'BaseURL' => 'Basis URL', + 'BaselineExposure' => 'Referenzbelichtung', + 'BaselineExposureOffset' => 'Referenzbelichtung Abweichung', + 'BaselineNoise' => 'Grundrauschen', + 'BaselineSharpness' => 'Referenzschärfe', + 'BatteryInfo' => 'Stromquelle', + 'BatteryLevel' => 'Batteriestatus', + 'BatteryOrder' => { + Description => 'Akkureihenfolge', + PrintConv => { + 'Camera Battery First' => 'Zuerst Akku in der Kamera', + 'MB-D10 First' => 'Zuerst Akkus im MB-D10', + }, + }, + 'BatteryState' => { + Description => 'Batteriestatus', + PrintConv => { + 'Almost full' => 'Fast Voll', + 'Empty' => 'Leer', + 'Full' => 'Voll', + 'Half full' => 'Halb Voll', + 'Low' => 'Niedrig', + }, + }, + 'BayerGreenSplit' => 'Pixelaufteilung nach Bayer', + 'BayerPattern' => 'Bayer Matrix', + 'Beep' => { + Description => 'Tonsignal', + PrintConv => { + 'High' => 'Hoch', + 'Low' => 'Tief', + 'Off' => 'Aus', + 'On' => 'Ein', + }, + }, + 'BestShotMode' => { + Description => 'Bester Aufnahmemodus', + PrintConv => { + 'Autumn Leaves' => 'Herbstlaub', + 'Baby CS' => 'Kleinkind', + 'Backlight' => 'Hintergrundbeleuchtung', + 'Beach' => 'Strand', + 'Candlelight Portrait' => 'Kerzenlicht Porträt', + 'Child CS' => 'Kinder', + 'Children' => 'Kinder', + 'Collection' => 'Sammlung', + 'Fireworks' => 'Feuerwerk', + 'Flower' => 'Blumen', + 'Food' => 'Lebensmittel', + 'For YouTube' => 'Für YouTube', + 'For eBay' => 'Für eBay', + 'High Sensitivity' => 'Hohe Empfindlichkeit', + 'Natural Green' => 'Naturgrün', + 'Night Scene' => 'Nachtszene', + 'Night Scene Portrait' => 'Nacht-Porträt', + 'People' => 'Menschen', + 'Pet' => 'Haustiere', + 'Pet CS' => 'Haustiere', + 'Portrait' => 'Porträt', + 'Silent' => 'Stillleben', + 'Snow' => 'Schnee', + 'Sports' => 'Sport', + 'Sports CS' => 'Sport CS', + 'Sundown' => 'Sonnenuntergang', + 'Twilight' => 'Dämmerung', + 'Underwater' => 'Unterwasser', + }, + }, + 'BigImage' => 'Big Image Vorschaubild', + 'BitDepth' => 'Bit-Tiefe', + 'BitsPerSample' => 'Anzahl der Bits pro Komponente', + 'BlackLevel' => 'Schwarzwert', + 'BlackLevel2' => 'Schwarzwert 2', + 'BlackLevelData' => 'Schwarzwert Daten', + 'BlackLevelDeltaH' => 'Schwarzwert Delta H', + 'BlackLevelDeltaV' => 'Schwarzwert Delta V', + 'BlackPoint' => 'Schwarzpunkt', + 'BlueAdjust' => 'Blau-Korrektur', + 'BlueBalance' => 'Farbabgleich Blau', + 'BlueHue' => 'Farbton Blau', + 'BlueMatrixColumn' => 'Blau-Matrixspalte', + 'BlueSaturation' => 'Sättigung Blau', + 'BlueTRC' => 'Blau-Tonwertwiedergabe-Kurve', + 'BlueX' => 'Blaupunkt X', + 'BlueY' => 'Blaupunkt Y', + 'BlurControl' => { + Description => 'Bildstabilisierung', + PrintConv => { + 'High' => 'Hoch', + 'Low' => 'Niedrig', + 'Medium' => 'Mittel', + 'Off' => 'Aus', + }, + }, + 'BlurWarning' => { + Description => 'Verwackelungswarnung', + PrintConv => { + 'Blur Warning' => 'Verwackelungswarnung', + 'None' => 'Keine', + }, + }, + 'BodyBatteryADLoad' => 'Kamerabatterie A/D unter Last', + 'BodyBatteryADNoLoad' => 'Kamerabatterie A/D im Leerlauf', + 'BodyBatteryState' => { + Description => 'Kamerabatterie-Status', + PrintConv => { + 'Almost Empty' => 'Fast leer', + 'Empty or Missing' => 'Leer oder nicht vorhanden', + 'Full' => 'Voll geladen', + 'Running Low' => 'Schwach', + }, + }, + 'BodyFirmwareVersion' => 'Kamera-Firmware-Version', + 'BracketMode' => { + Description => 'Belichtungsreihen-Modus', + PrintConv => { + 'Off' => 'Aus', + }, + }, + 'BracketSequence' => 'Belichtungsreihen-Abfolge', + 'BracketShot' => 'Belichtungsreihen-Aufnahme', + 'BracketShotNumber' => { + Description => 'Belichtungsreihen-Bildnummer', + PrintConv => { + '1 of 2' => '1 von 2', + '1 of 3' => '1 von 3', + '1 of 5' => '1 von 5', + '2 of 2' => '2 von 2', + '2 of 3' => '2 von 3', + '2 of 5' => '2 von 5', + '3 of 3' => '3 von 3', + '3 of 5' => '3 von 5', + '4 of 5' => '4 von 5', + '5 of 5' => '5 von 5', + 'n/a' => '(nicht gesetzt)', + }, + }, + 'BracketStep' => { + Description => 'Belichtungsreihenschritte', + PrintConv => { + '1 EV' => '1 LW', + '1/3 EV' => '1/3 LW', + '2/3 EV' => '2/3 LW', + }, + }, + 'BracketValue' => 'Belichtungsreihen-Wert', + 'Brightness' => 'Helligkeit', + 'BrightnessAdj' => 'Helligkeitskorrektur', + 'BrightnessValue' => 'Helligkeit', + 'BulbDuration' => 'Bulb-Dauer', + 'BurstMode' => { + Description => 'Burst Modus', + PrintConv => { + 'Auto Exposure Bracketing (AEB)' => 'Automatische Belichtungsreihe', + 'Off' => 'Aus', + 'On' => 'Ein', + 'Unlimited' => 'Unbegrenzt', + }, + }, + 'BurstMode2' => 'Burst Modus 2', + 'BurstShot' => 'Burst Aufnahme', + 'ButtonFunctionControlOff' => { + Description => 'Tastenfunktion wenn Schnelleinstellrad OFF', + PrintConv => { + 'Disable main, Control, Multi-control' => 'Deaktiv Haupt-Wahlrad, Schnelleinstellrad, Multicontroller', + 'Normal (enable)' => 'Normal (eingeschaltet)', + }, + }, + 'By-line' => 'Ersteller', + 'By-lineTitle' => 'Beruf des Erstellers', + 'ByteOrder' => 'Bytereihenfolge', + 'CCDSensitivity' => 'CCD Empfindlichkeit', + 'CFALayout' => { + Description => 'Farbfilter Anordnung', + PrintConv => { + 'Rectangular' => 'Rechteckig', + }, + }, + 'CFAPattern' => 'Farbfiltermatrix', + 'CFAPattern2' => 'Farbfiltermatrix 2', + 'CFAPatternColumns' => 'Farbfiltermatrix Spalten', + 'CFAPatternRows' => 'Farbfiltermatrix Zeilen', + 'CFAPatternValues' => 'Farbfiltermatrix Werte', + 'CFARepeatPatternDim' => 'Farbfiltermatrix-Größe', + 'CLModeShootingSpeed' => 'Lowspeed-Bildrate', + 'CMContrast' => 'CM Kontrast', + 'CMExposureCompensation' => 'CM Belichtungskorrektur', + 'CMHue' => 'CM Farbton', + 'CMMFlags' => 'CMM-Flags', + 'CMSaturation' => 'CM Farbsättigung', + 'CMSharpness' => 'CM Schärfe', + 'CMWhiteBalance' => 'CM Weißabgleich', + 'CMWhiteBalanceComp' => 'CM Weißabgleichsausgleich', + 'CMWhiteBalanceGrayPoint' => 'CM Weißabgleich Graupunkt', + 'CPUArchitecture' => 'CPU Architektur', + 'CPUByteOrder' => { + Description => 'CPU Bytereihenfolge', + PrintConv => { + 'Big endian' => 'Big-endian', + 'Little endian' => 'Little-endian', + }, + }, + 'CPUCount' => 'Anzahl CPU', + 'CPUFirmwareVersion' => 'CPU-Firmware-Version', + 'CPUSubtype' => 'CPU Subtyp', + 'CPUType' => { + Description => 'CPU Typ', + PrintConv => { + 'Any' => 'Unbestimmt', + 'None' => 'Unbestimmt', + 'i860 big endian' => 'i860 big-endian', + 'i860 little endian' => 'i860 little-endian', + }, + }, + 'CalibrationIlluminant1' => { + Description => 'Lichtquellenkalibrierung 1', + PrintConv => { + 'Cloudy' => 'Bewölkt', + 'Cool White Fluorescent' => 'Neonlicht kaltweiß', + 'Day White Fluorescent' => 'Neonlicht neutralweiß', + 'Daylight' => 'Tageslicht', + 'Daylight Fluorescent' => 'Neonlicht tageslichtweiß', + 'Fine Weather' => 'Wolkenlos', + 'Flash' => 'Blitz', + 'Fluorescent' => 'Neonlicht', + 'ISO Studio Tungsten' => 'ISO Studio-Kunstlicht (Glühbirne)', + 'Other' => 'Andere Lichtquelle', + 'Shade' => 'Schatten', + 'Standard Light A' => 'Standard-Licht A', + 'Standard Light B' => 'Standard-Licht B', + 'Standard Light C' => 'Standard-Licht C', + 'Tungsten (Incandescent)' => 'Kunstlicht (Glühbirne)', + 'Unknown' => 'Unbekannt', + 'Warm White Fluorescent' => 'Neonlicht warmweiß', + 'White Fluorescent' => 'Neonlicht universalweiß', + }, + }, + 'CalibrationIlluminant2' => { + Description => 'Lichtquellenkalibrierung 2', + PrintConv => { + 'Cloudy' => 'Bewölkt', + 'Cool White Fluorescent' => 'Neonlicht kaltweiß', + 'Day White Fluorescent' => 'Neonlicht neutralweiß', + 'Daylight' => 'Tageslicht', + 'Daylight Fluorescent' => 'Neonlicht tageslichtweiß', + 'Fine Weather' => 'Wolkenlos', + 'Flash' => 'Blitz', + 'Fluorescent' => 'Neonlicht', + 'ISO Studio Tungsten' => 'ISO Studio-Kunstlicht (Glühbirne)', + 'Other' => 'Andere Lichtquelle', + 'Shade' => 'Schatten', + 'Standard Light A' => 'Standard-Licht A', + 'Standard Light B' => 'Standard-Licht B', + 'Standard Light C' => 'Standard-Licht C', + 'Tungsten (Incandescent)' => 'Kunstlicht (Glühbirne)', + 'Unknown' => 'Unbekannt', + 'Warm White Fluorescent' => 'Neonlicht warmweiß', + 'White Fluorescent' => 'Neonlicht universalweiß', + }, + }, + 'CameraBody' => 'Kamera Gehäuse', + 'CameraByteOrder' => 'Kamera Bytereihenfolge', + 'CameraCalibration1' => 'Kamerakalibrierung 1', + 'CameraCalibration2' => 'Kamerakalibrierung 2', + 'CameraColorCalibration01' => 'Kamera Farbkalibrierung 01', + 'CameraColorCalibration02' => 'Kamera Farbkalibrierung 02', + 'CameraColorCalibration03' => 'Kamera Farbkalibrierung 03', + 'CameraColorCalibration04' => 'Kamera Farbkalibrierung 04', + 'CameraColorCalibration05' => 'Kamera Farbkalibrierung 05', + 'CameraColorCalibration06' => 'Kamera Farbkalibrierung 06', + 'CameraColorCalibration07' => 'Kamera Farbkalibrierung 07', + 'CameraColorCalibration08' => 'Kamera Farbkalibrierung 08', + 'CameraColorCalibration09' => 'Kamera Farbkalibrierung 09', + 'CameraColorCalibration10' => 'Kamera Farbkalibrierung 10', + 'CameraColorCalibration11' => 'Kamera Farbkalibrierung 11', + 'CameraColorCalibration12' => 'Kamera Farbkalibrierung 12', + 'CameraColorCalibration13' => 'Kamera Farbkalibrierung 13', + 'CameraColorCalibration14' => 'Kamera Farbkalibrierung 14', + 'CameraColorCalibration15' => 'Kamera Farbkalibrierung 15', + 'CameraID' => 'Kamera ID', + 'CameraISO' => 'Kamera-ISO', + 'CameraInfo' => 'Pentax-Modell', + 'CameraInfoByteOrder' => 'Kamerainformation Bytereihenfolge', + 'CameraModel' => 'Kamera Modell', + 'CameraOrientation' => { + Description => 'Ausrichtung der Kamera', + PrintConv => { + 'Downwards' => 'Abwärts', + 'Rotate 180' => '180° gedreht', + 'Rotate 270 CW' => '90° gegen den Uhrzeigersinn', + 'Rotate 90 CW' => '90° im Uhrzeigersinn', + 'Upwards' => 'Aufwärts', + }, + }, + 'CameraProfile' => 'Kameraprofil', + 'CameraProfileDigest' => 'Kennwert des Kameraprofils', + 'CameraSerialNumber' => 'Kamera-Seriennummer', + 'CameraSettings' => 'Kameraeinstellungen', + 'CameraSettingsVersion' => 'Kameraeinstellungen-Version', + 'CameraTemperature' => 'Kamera-Temperatur', + 'CameraType' => { + Description => 'Kameratyp', + PrintConv => { + 'Compact' => 'Kompakt', + 'DV Camera' => 'DV Kamera', + 'EOS High-end' => 'EOS Highend', + 'EOS Mid-range' => 'EOS Mittelklasse', + 'n/a' => '(nicht gesetzt)', + }, + }, + 'CameraType2' => 'Kameratyp 2', + 'CanonAFInfo' => 'AF-Info', + 'CanonAFInfo2' => 'AF-Info (2)', + 'CanonExposureMode' => { + Description => 'Belichtungsmodus', + PrintConv => { + 'Aperture-priority AE' => 'Blendenpriorität', + 'Bulb' => 'Bulb-Modus', + 'Manual' => 'Manuell', + 'Program AE' => 'Programmautomatik', + 'Shutter speed priority AE' => 'Verschlusspriorität', + }, + }, + 'CanonFileDescription' => 'Canon Dateibeschreibung', + 'CanonFileInfo' => 'Dateiinformationen', + 'CanonFileLength' => 'Dateilänge', + 'CanonFirmwareVersion' => 'Firmware-Version', + 'CanonFlashMode' => { + Description => 'Blitz-Modus', + PrintConv => { + 'Auto' => 'Automatisch', + 'External flash' => 'Externer Blitz', + 'Off' => 'Aus', + 'On' => 'Ein', + 'Red-eye reduction' => 'Rote-Augen-Reduzierung', + 'Red-eye reduction (Auto)' => 'Rote-Augen-Reduzierung (Automatisch)', + 'Red-eye reduction (On)' => 'Rote-Augen-Reduzierung (Ein)', + 'n/a' => '(nicht gesetzt)', + }, + }, + 'CanonFocalLength' => 'Objektivart', + 'CanonImageHeight' => 'Canon-Bildhöhe', + 'CanonImageSize' => { + Description => 'Canon-Bildgröße', + PrintConv => { + 'Large' => 'Groß', + 'Medium' => 'Mittelgroß', + 'Medium 1' => 'Mittelgroß 1', + 'Medium 2' => 'Mittelgroß 2', + 'Medium 3' => 'Mittelgroß 3', + 'Medium Movie' => 'Mittelgroßer Film', + 'Postcard' => 'Postkarte', + 'Small' => 'Klein', + 'Small 1' => 'Klein 1', + 'Small 2' => 'Klein 2', + 'Small 3' => 'Klein 3', + 'Small Movie' => 'Kleiner Film', + 'Widescreen' => 'Breitbild', + }, + }, + 'CanonImageType' => 'Canon-Bildtyp', + 'CanonImageWidth' => 'Canon-Bildbreite', + 'CanonModelID' => 'Canon-Modell', + 'Caption' => 'Bildtext', + 'Caption-Abstract' => 'Beschreibung/Zusammenfassung', + 'CaptionWriter' => 'Bildtextautor', + 'CaptureXResolutionUnit' => { + PrintConv => { + 'um' => 'µm (Mikrometer)', + }, + }, + 'CaptureYResolutionUnit' => { + PrintConv => { + 'um' => 'µm (Mikrometer)', + }, + }, + 'CasioImageSize' => 'Casio Bildgröße', + 'CatalogSets' => 'Katalogzusammenstellungen', + 'Categories' => { + Description => 'Kategorien', + PrintConv => { + 'People' => 'Menschen', + 'Scenery' => 'Szene', + }, + }, + 'Category' => 'Kategorie', + 'CenterAFArea' => { + Description => 'AF-Messfeldgröße', + PrintConv => { + 'Normal Zone' => 'Normal', + 'Wide Zone' => 'Groß', + }, + }, + 'CenterFocusPoint' => { + Description => 'Fokuspunkt Mitte', + PrintConv => { + 'Normal Zone' => 'Normaler Bereich', + 'Wide Zone' => 'Großer Bereich', + }, + }, + 'CenterWeightedAreaSize' => { + Description => 'Messfeldgröße', + PrintConv => { + 'Average' => 'Durchschnitt', + }, + }, + 'Certificate' => 'Zertifikat', + 'Channels' => 'Kanäle', + 'Chapter' => 'Kapitel', + 'CharacterSet' => 'Zeichensatz', + 'Children' => 'Kinder', + 'ChromaticAberration' => 'Farbabweichung', + 'ChromaticAberrationB' => 'Farbabweichung B', + 'ChromaticAberrationBlue' => 'Farbabweichung Blau', + 'ChromaticAberrationCorr' => { + Description => 'Farbabweichung Korrektur', + PrintConv => { + 'Off' => 'Aus', + 'On' => 'Ein', + }, + }, + 'ChromaticAberrationCorrection' => { + Description => 'Farbabweichung Korrektur', + PrintConv => { + 'Off' => 'Aus', + 'On' => 'Ein', + }, + }, + 'ChromaticAberrationOn' => 'Farbabweichung Ein', + 'ChromaticAberrationR' => 'Farbabweichung R', + 'ChromaticAberrationRed' => 'Farbabweichung Rot', + 'ChromaticAberrationSetting' => { + Description => 'Farbabweichung Einstellung', + PrintConv => { + 'Off' => 'Aus', + 'On' => 'Ein', + }, + }, + 'Chromaticity' => 'Chromatizität', + 'ChrominanceNR_TIFF_JPEG' => { + PrintConv => { + 'High' => 'Hoch', + 'Low' => 'Leicht', + 'Off' => 'Aus', + }, + }, + 'ChrominanceNoiseReduction' => { + PrintConv => { + 'High' => 'Hoch', + 'Low' => 'Leicht', + 'Off' => 'Aus', + }, + }, + 'CircleOfConfusion' => 'Unschärfekreis', + 'City' => 'Stadt/Ort', + 'ClassifyState' => 'Klassifizierungs-Status', + 'CodePage' => { + PrintConv => { + 'Unicode UTF-16, big endian' => 'Unicode UTF-16, Big-endian', + 'Unicode UTF-16, little endian' => 'Unicode UTF-16, Little-endian', + 'Unicode UTF-32, big endian' => 'Unicode UTF-32, Big-endian', + 'Unicode UTF-32, little endian' => 'Unicode UTF-32, Little-endian', + }, + }, + 'CodedCharacterSet' => 'IPTC Characterset', + 'CodedContentScanningKind' => { + PrintConv => { + 'Unknown' => 'Unbekannt', + }, + }, + 'ColorAberrationControl' => { + PrintConv => { + 'Off' => 'Aus', + 'On' => 'Ein', + }, + }, + 'ColorAdjustment' => 'Farbkorrektur', + 'ColorAdjustmentMode' => { + Description => 'Farbtonkorrektur Modus', + PrintConv => { + 'Off' => 'Aus', + 'On' => 'Ein', + }, + }, + 'ColorBW' => 'Schwarz/Weiß', + 'ColorBalance' => 'Farbabgleich', + 'ColorBalance1' => 'Farbabgleich 1', + 'ColorBalanceA' => 'Farbabgleich A', + 'ColorBalanceAdj' => { + Description => 'Farbabgleich Korrektur', + PrintConv => { + 'Off' => 'Aus', + 'On' => 'Ein', + }, + }, + 'ColorBalanceBlue' => 'Farbbalance Blau', + 'ColorBalanceGreen' => 'Farbbalance Grün', + 'ColorBalanceRed' => 'Farbbalance Rot', + 'ColorBitDepth' => 'Farbtiefe', + 'ColorBoostType' => { + PrintConv => { + 'Nature' => 'Natur', + 'People' => 'Menschen', + }, + }, + 'ColorBooster' => { + PrintConv => { + 'Off' => 'Aus', + 'On' => 'Ein', + }, + }, + 'ColorCompensationFilter' => 'Farbkorrektur-Filter', + 'ColorComponents' => 'Anzahl der Bildkomponenten', + 'ColorCorrection' => 'Farbkorrektur', + 'ColorDataVersion' => 'Farbdaten Version', + 'ColorEffect' => { + Description => 'Farbeffekt', + PrintConv => { + 'Black & White' => 'Schwarz/Weiß', + 'Cool' => 'Kühl', + 'Off' => 'Aus', + }, + }, + 'ColorFilter' => { + Description => 'Farbfilter', + PrintConv => { + 'Black & White' => 'Schwarz/Weiß', + 'Blue' => 'Blau', + 'Green' => 'Grün', + 'Off' => 'Aus', + 'Purple' => 'Lila', + 'Red' => 'Rot', + 'Yellow' => 'Gelb', + }, + }, + 'ColorHue' => 'Farbwiedergabe', + 'ColorInfo' => 'Farb-Informationen', + 'ColorMap' => 'Farbtafel', + 'ColorMatrix' => 'Farb-Matrix', + 'ColorMatrix1' => 'Farbmatrix 1', + 'ColorMatrix2' => 'Farbmatrix 2', + 'ColorMatrixNumber' => 'Farbmatrix Nummer', + 'ColorMode' => { + Description => 'Farbmodus', + PrintConv => { + 'Autumn' => 'Herbst', + 'Autumn Leaves' => 'Herbstlaub', + 'B & W' => 'S/W', + 'B&W' => 'Schwarz/Weiß', + 'B&W Red Filter' => 'Schwarz-Weiß Rotfilter', + 'B&W Yellow Filter' => 'Schwarz-Weiß Gelbfilter', + 'Black & White' => 'Schwarz/Weiß', + 'Chrome' => 'Farbe', + 'Clear' => 'Klar', + 'Deep' => 'Tief', + 'Duotone' => 'Zweiton', + 'Evening' => 'Abends', + 'Grayscale' => 'Graustufen', + 'Indexed' => 'Indiziert', + 'Indexed Color' => 'Indizierte Farben', + 'Landscape' => 'Landschaft', + 'Light' => 'Hell', + 'Multichannel' => 'Mehrkanal', + 'Natural' => 'Natürlich', + 'Natural color' => 'Natürliche Farben', + 'Natural sRGB' => 'Neutral sRGB', + 'Natural+ sRGB' => 'Neutral+ sRGB', + 'Night Portrait' => 'Nachtporträt', + 'Night Scene' => 'Nachtszene', + 'Night View' => 'Abendszene', + 'Night View/Portrait' => 'Abendszene/Porträt', + 'Off' => 'Aus', + 'Portrait' => 'Porträt', + 'RGB Color' => 'RGB Farbe', + 'Solarization' => 'Solarisation', + 'Sunset' => 'Sonnenuntergang', + 'Vivid' => 'Lebhafte Farbe', + 'Vivid color' => 'Lebhafte Farbe', + 'n/a' => '(nicht gesetzt)', + }, + }, + 'ColorMoireReduction' => { + PrintConv => { + 'Off' => 'Aus', + 'On' => 'Ein', + }, + }, + 'ColorMoireReductionMode' => { + PrintConv => { + 'High' => 'Hoch', + 'Low' => 'Leicht', + 'Off' => 'Aus', + }, + }, + 'ColorNoiseReduction' => 'Farbrauschunterdrückung', + 'ColorNoiseReductionDetail' => 'Farbrauschunterdrückung Detail', + 'ColorPalette' => 'Farbpalette', + 'ColorPlanes' => 'Farbebenen', + 'ColorProfile' => { + Description => 'Farbprofil', + PrintConv => { + 'Embedded' => 'Eingebunden', + 'Not Embedded' => 'Nicht eingebunden', + }, + }, + 'ColorRepresentation' => 'Farbdarstellung', + 'ColorReproduction' => 'Farbreproduktion', + 'ColorSequence' => 'Farbreihenfolge', + 'ColorSpace' => { + Description => 'Farbraum', + PrintConv => { + 'B&W' => 'Schwarz/Weiß', + 'ICC Profile' => 'ICC-Profil', + 'Monochrome' => 'Monochrom', + 'Natural sRGB' => 'Neutral sRGB', + 'Natural+ sRGB' => 'Neutral+ sRGB', + 'Uncalibrated' => 'Nicht festgelegt', + 'Undefined' => 'Nicht definiert', + }, + }, + 'ColorSpaceData' => 'Farbraum Daten', + 'ColorTempAsShot' => 'Farbtemperatur Aufnahme', + 'ColorTempAuto' => 'Farbtemperatur Auto', + 'ColorTempCloudy' => 'Farbtemperatur Bewölkt', + 'ColorTempCustom' => 'Farbtemperatur Benutzerdefiniert', + 'ColorTempCustom1' => 'Farbtemperatur Benutzerdefiniert 1', + 'ColorTempCustom2' => 'Farbtemperatur Benutzerdefiniert 2', + 'ColorTempDaylight' => 'Farbtemperatur Tageslicht', + 'ColorTempFlash' => 'Farbtemperatur Blitz', + 'ColorTempFlashData' => 'Farbtemperatur Blitzdaten', + 'ColorTempFluorescent' => 'Farbtemperatur Neonlicht', + 'ColorTempKelvin' => 'Farbtemperatur Kelvin', + 'ColorTempMeasured' => 'Farbtemperatur Messung', + 'ColorTempPC1' => 'Farbtemperatur PC1', + 'ColorTempPC2' => 'Farbtemperatur PC2', + 'ColorTempPC3' => 'Farbtemperatur PC3', + 'ColorTempShade' => 'Farbtemperatur Schatten', + 'ColorTempTungsten' => 'Farbtemperatur Glühbirne', + 'ColorTempUnknown' => 'Farbtemperatur Unbekannt', + 'ColorTempUnknown10' => 'Farbtemperatur Unbekannt 10', + 'ColorTempUnknown11' => 'Farbtemperatur Unbekannt 11', + 'ColorTempUnknown12' => 'Farbtemperatur Unbekannt 12', + 'ColorTempUnknown13' => 'Farbtemperatur Unbekannt 13', + 'ColorTempUnknown14' => 'Farbtemperatur Unbekannt 14', + 'ColorTempUnknown15' => 'Farbtemperatur Unbekannt 15', + 'ColorTempUnknown16' => 'Farbtemperatur Unbekannt 16', + 'ColorTempUnknown17' => 'Farbtemperatur Unbekannt 17', + 'ColorTempUnknown18' => 'Farbtemperatur Unbekannt 18', + 'ColorTempUnknown19' => 'Farbtemperatur Unbekannt 19', + 'ColorTempUnknown2' => 'Farbtemperatur Unbekannt 2', + 'ColorTempUnknown20' => 'Farbtemperatur Unbekannt 20', + 'ColorTempUnknown3' => 'Farbtemperatur Unbekannt 3', + 'ColorTempUnknown4' => 'Farbtemperatur Unbekannt 4', + 'ColorTempUnknown5' => 'Farbtemperatur Unbekannt 5', + 'ColorTempUnknown6' => 'Farbtemperatur Unbekannt 6', + 'ColorTempUnknown7' => 'Farbtemperatur Unbekannt 7', + 'ColorTempUnknown8' => 'Farbtemperatur Unbekannt 8', + 'ColorTempUnknown9' => 'Farbtemperatur Unbekannt 9', + 'ColorTemperature' => 'Farbtemperatur', + 'ColorTemperatureAdj' => 'Farbtemperaturkorrektur', + 'ColorTemperatureSetting' => { + PrintConv => { + 'Color Filter' => 'Farbfilter', + }, + }, + 'ColorTone' => 'Farbton', + 'ColorToneAdj' => 'Farbtonkorrektur', + 'ColorToneFaithful' => { + Description => 'Farbton Natürlich', + PrintConv => { + 'n/a' => '(nicht gesetzt)', + }, + }, + 'ColorToneLandscape' => { + Description => 'Farbton Landschaft', + PrintConv => { + 'n/a' => '(nicht gesetzt)', + }, + }, + 'ColorToneMonochrome' => { + PrintConv => { + 'n/a' => '(nicht gesetzt)', + }, + }, + 'ColorToneNeutral' => { + Description => 'Farbton Neutral', + PrintConv => { + 'n/a' => '(nicht gesetzt)', + }, + }, + 'ColorTonePortrait' => { + Description => 'Farbton Porträt', + PrintConv => { + 'n/a' => '(nicht gesetzt)', + }, + }, + 'ColorToneStandard' => { + Description => 'Farbton Standard', + PrintConv => { + 'n/a' => '(nicht gesetzt)', + }, + }, + 'ColorToneUnknown' => { + PrintConv => { + 'n/a' => '(nicht gesetzt)', + }, + }, + 'ColorToneUserDef1' => { + Description => 'Farbton Benutzerdefiniert 1', + PrintConv => { + 'n/a' => '(nicht gesetzt)', + }, + }, + 'ColorToneUserDef2' => { + Description => 'Farbton Benutzerdefiniert 2', + PrintConv => { + 'n/a' => '(nicht gesetzt)', + }, + }, + 'ColorToneUserDef3' => { + Description => 'Farbton Benutzerdefiniert 3', + PrintConv => { + 'n/a' => '(nicht gesetzt)', + }, + }, + 'ColorTransform' => { + Description => 'Farbtransformation', + PrintConv => { + 'Unknown (RGB or CMYK)' => 'Unbekannt (RGB oder CMYK)', + }, + }, + 'ColorimetricReference' => 'Farbmetrische Referenz', + 'CommandDials' => { + Description => 'Einstellräder', + PrintConv => { + 'Reversed (Main Aperture, Sub Shutter)' => 'Vertauscht', + 'Standard (Main Shutter, Sub Aperture)' => 'Standard', + }, + }, + 'CommandDialsApertureSetting' => { + Description => 'Einstellräder Blendeneinstellung', + PrintConv => { + 'Aperture Ring' => 'Mit Blendenring', + 'Sub-command Dial' => 'Mit Einstellrad', + }, + }, + 'CommandDialsChangeMainSub' => { + Description => 'Einstellräder Funktionsbelegung', + PrintConv => { + 'Off' => 'Aus', + 'On' => 'Ein', + }, + }, + 'CommandDialsMenuAndPlayback' => { + Description => 'Einstellräder Menüs und Wiedergabe', + PrintConv => { + 'Off' => 'Aus', + 'On' => 'Ein', + }, + }, + 'CommandDialsReverseRotation' => { + Description => 'Einstellräder Auswahlrichtung', + PrintConv => { + 'No' => 'Standard', + 'Yes' => 'Umgekehrt', + }, + }, + 'CommanderChannel' => 'Master-Steuerung Kanal', + 'CommanderGroupAManualOutput' => 'Master-Steuerung Gruppe A M Korr', + 'CommanderGroupAMode' => { + Description => 'Master-Steuerung Gruppe A Modus', + PrintConv => { + 'Auto Aperture' => 'Blendenautomatik (AA)', + 'Manual' => 'Manuell', + 'Off' => 'Aus', + }, + }, + 'CommanderGroupA_TTL-AAComp' => 'Master-Steuerung Gruppe A TTL/AA Korr', + 'CommanderGroupA_TTLComp' => 'Master-Steuerung Gruppe-A TTL-Korrektur', + 'CommanderGroupBManualOutput' => 'Master-Steuerung Gruppe B M Korr', + 'CommanderGroupBMode' => { + Description => 'Master-Steuerung Gruppe B Modus', + PrintConv => { + 'Auto Aperture' => 'Blendenautomatik (AA)', + 'Manual' => 'Manuell', + 'Off' => 'Aus', + }, + }, + 'CommanderGroupB_TTL-AAComp' => 'Master-Steuerung Gruppe B TTL/AA Korr', + 'CommanderGroupB_TTLComp' => 'Master-Steuerung Gruppe-B TTL-Korrektur', + 'CommanderInternalFlash' => { + Description => 'Master-Steuerung Intgr. Blitz Modus', + PrintConv => { + 'Manual' => 'Manuell', + 'Off' => 'Aus', + }, + }, + 'CommanderInternalManualOutput' => 'Master-Steuerung Intgr. Blitz M Korr', + 'CommanderInternalTTLComp' => 'Master-Steuerung Intgr. Blitz TTL Korr', + 'Comment' => 'Kommentar', + 'Comments' => 'Kommentare', + 'Compilation' => { + PrintConv => { + 'No' => 'Nein', + 'Yes' => 'Ja', + }, + }, + 'ComponentBitDepth' => 'Komponente Farbtiefe', + 'ComponentsConfiguration' => 'Bedeutung jeder Komponente', + 'CompressedBitsPerPixel' => 'Bildkomprimierungsmodus', + 'CompressedImageSize' => 'Komprimierte Bildgröße', + 'Compression' => { + Description => 'Komprimierungsschema', + PrintConv => { + 'Bitfields' => 'Bitfelder', + 'JBIG B&W' => 'JBIG Schwarz-Weiß', + 'JBIG Color' => 'JBIG Farbe', + 'JPEG' => 'JPEG-Komprimierung', + 'JPEG (old-style)' => 'JPEG (alte Version)', + 'Kodak DCR Compressed' => 'Kodak DCR-Komprimierung', + 'Kodak KDC Compressed' => 'Kodak KDC-Komprimierung', + 'Next' => 'NeXT 2-Bit Kodierung', + 'Nikon NEF Compressed' => 'Nikon NEF-Komprimierung', + 'None' => 'Keines', + 'PNG' => 'PNG-Komprimierung', + 'Pentax PEF Compressed' => 'Pentax PEF-Komprimierung', + 'SGILog' => 'SGI 32-Bit Log Luminance Kodierung', + 'SGILog24' => 'SGI 24-Bit Log Luminance Kodierung', + 'Sony ARW Compressed' => 'Sony ARW-Komprimierung', + 'Thunderscan' => 'ThunderScan 4-Bit Kodierung', + 'Uncompressed' => 'Nicht komprimiert', + }, + }, + 'CompressionFactor' => 'Komprimierungsfaktor', + 'CompressionLevel' => 'Komprimierungsgrad', + 'CompressionRatio' => 'Komprimierungsrate', + 'CompressionType' => { + Description => 'Komprimierungsschema', + PrintConv => { + 'Little-endian, no compression' => 'Little-endian, keine Komprimierung', + 'None' => 'Keines', + }, + }, + 'ConditionalFEC' => 'Blitzbelichtungskorrektur', + 'ConnectionSpaceIlluminant' => 'Weißpunkt des Verbindungsfarbraums', + 'ConstrainedCropHeight' => 'Ausschnitt erzeugte Höhe', + 'ConstrainedCropWidth' => 'Ausschnitt erzeugte Breite', + 'Contact' => 'Kontakt', + 'ContentLocationCode' => 'Inhaltspositionscode', + 'ContentLocationName' => 'Inhaltspositionsname', + 'ContinuousBracketing' => { + Description => 'Serienbild-Belichtungsreihe', + PrintConv => { + 'High' => 'Hoch', + 'Low' => 'Niedrig', + }, + }, + 'ContinuousDrive' => { + Description => 'Aufnahme-Modus', + PrintConv => { + 'Continuous' => 'Serienaufnahme', + 'Movie' => 'Filmen', + 'Silent Single' => 'Stillleben', + 'Single' => 'Einzelbild', + }, + }, + 'ContinuousShootingSpeed' => { + Description => 'Geschwindigkeit Reihenaufnahmen', + PrintConv => { + 'Disable' => 'Nicht möglich', + 'Enable' => 'Möglich', + }, + }, + 'ContinuousShotLimit' => { + Description => 'Limit Anzahl Reihenaufnahmen', + PrintConv => { + 'Disable' => 'Nicht möglich', + 'Enable' => 'Möglich', + }, + }, + 'Contrast' => { + Description => 'Kontrast', + PrintConv => { + '+1 (medium high)' => '+1 (Leicht erhöht)', + '+2 (high)' => '+2 (Stark)', + '+3 (very high)' => '+3 (Sehr hoch)', + '-1 (medium low)' => '-1 (Leicht verringert)', + '-2 (low)' => '-2 (Leicht)', + '-3 (very low)' => '-3 (Sehr gering)', + 'Film Simulation' => 'Film-Simulation', + 'High' => 'Stark', + 'Low' => 'Leicht', + 'Med High' => 'Leicht erhöht', + 'Med Low' => 'Leicht verringert', + 'Medium High' => 'Mittel-Hoch', + 'Medium Low' => 'Mittel-Gering', + 'Very High' => 'Sehr hoch', + 'Very Low' => 'Sehr gering', + 'n/a' => '(nicht gesetzt)', + }, + }, + 'Contrast2012' => 'Kontrast 2012', + 'ContrastAdj' => 'Kontrastkorrektur', + 'ContrastAdjustment' => 'Kontrastkorrektur', + 'ContrastCurve' => 'Kontrast-Kurve', + 'ContrastDetectAFArea' => 'AF-Bereich Kontrast gesteuert', + 'ContrastFaithful' => { + Description => 'Kontrast Natürlich', + PrintConv => { + 'n/a' => '(nicht gesetzt)', + }, + }, + 'ContrastHighlightShadowAdj' => { + Description => 'Kontrast helle Stellen', + PrintConv => { + 'Off' => 'Aus', + 'On' => 'Ein', + }, + }, + 'ContrastLandscape' => { + Description => 'Kontrast Landschaft', + PrintConv => { + 'n/a' => '(nicht gesetzt)', + }, + }, + 'ContrastMode' => { + Description => 'Kontrast Modus', + PrintConv => { + 'High' => 'Hoch', + 'High Dynamic' => 'Hoch dynamisch', + 'Low' => 'Niedrig', + 'Low Key' => 'Low-Key', + 'Medium High' => 'Mitte hoch', + 'Medium Low' => 'Mitte niedrig', + }, + }, + 'ContrastMonochrome' => { + Description => 'Kontrast Monochrom', + PrintConv => { + 'n/a' => '(nicht gesetzt)', + }, + }, + 'ContrastNeutral' => { + Description => 'Kontrast Neutral', + PrintConv => { + 'n/a' => '(nicht gesetzt)', + }, + }, + 'ContrastPortrait' => { + Description => 'Kontrast Porträt', + PrintConv => { + 'n/a' => '(nicht gesetzt)', + }, + }, + 'ContrastSetting' => 'Kontrasteinstellung', + 'ContrastShadow' => 'Kontrast dunkle Stellen', + 'ContrastStandard' => { + Description => 'Kontrast Standard', + PrintConv => { + 'n/a' => '(nicht gesetzt)', + }, + }, + 'ContrastUnknown' => { + PrintConv => { + 'n/a' => '(nicht gesetzt)', + }, + }, + 'ContrastUserDef1' => { + Description => 'Kontrast Benutzerdefiniert 1', + PrintConv => { + 'n/a' => '(nicht gesetzt)', + }, + }, + 'ContrastUserDef2' => { + Description => 'Kontrast Benutzerdefiniert 2', + PrintConv => { + 'n/a' => '(nicht gesetzt)', + }, + }, + 'ContrastUserDef3' => { + Description => 'Kontrast Benutzerdefiniert 3', + PrintConv => { + 'n/a' => '(nicht gesetzt)', + }, + }, + 'Contributor' => 'Mitwirkender', + 'Contributors' => 'Mitwirkende', + 'ControlDialSet' => { + PrintConv => { + 'Aperture' => 'Blende', + 'Shutter Speed' => 'Belichtungszeit', + }, + }, + 'ControlMode' => { + Description => 'Steuerungsmethode', + PrintConv => { + 'Camera Local Control' => 'Lokale Kamerasteuerung', + 'Computer Remote Control' => 'Kamerasteuerung per Computer', + 'n/a' => '(nicht gesetzt)', + }, + }, + 'ConversionLens' => { + Description => 'Vorsatzlinse', + PrintConv => { + 'Macro' => 'Makro', + 'Off' => 'Aus', + 'Telephoto' => 'Tele', + }, + }, + 'Converter' => 'Konverter', + 'Copyright' => 'Urheberrechtsvermerk', + 'CopyrightNotice' => 'Urheberrechtsvermerk', + 'CopyrightStatus' => { + PrintConv => { + 'Unknown' => 'Unbekannt', + }, + }, + 'CoringValues' => 'Coring Werte', + 'Country' => 'Land', + 'Country-PrimaryLocationCode' => 'ISO-Ländercode', + 'Country-PrimaryLocationName' => 'Land', + 'CountryCode' => 'ISO-Ländercode', + 'Coverage' => 'Anwendungsbereich', + 'CreateDate' => 'Digitalisierungsdatum/-uhrzeit', + 'CreationDate' => 'Aufnahmedatum', + 'CreativeStyle' => { + Description => 'Kreativmodus', + PrintConv => { + 'Autumn' => 'Herbst', + 'Autumn Leaves' => 'Herbstlaub', + 'B&W' => 'Schwarz/Weiß', + 'Clear' => 'Klar', + 'Deep' => 'Tief', + 'Landscape' => 'Landschaft', + 'Light' => 'Hell', + 'Night View/Portrait' => 'Abendszene/Porträt', + 'Portrait' => 'Porträt', + 'Sunset' => 'Sonnenuntergang', + 'Vivid' => 'Lebhafte Farbe', + }, + }, + 'CreativeStyleSetting' => { + PrintConv => { + 'B&W' => 'Schwarz/Weiß', + 'Landscape' => 'Landschaft', + 'Portrait' => 'Porträt', + 'Sunset' => 'Sonnenuntergang', + }, + }, + 'Creator' => 'Ersteller', + 'CreatorAddress' => 'Ersteller - Adresse', + 'CreatorAppID' => { + Description => 'Ersteller App ID', + PrintConv => { + 'Unknown' => 'Unbekannt', + }, + }, + 'CreatorAppVersion' => 'Ersteller App Version', + 'CreatorApplication' => 'Ersteller der Applikation', + 'CreatorCity' => 'Ersteller - Ort', + 'CreatorContactInfo' => 'Ersteller Kontaktinfo', + 'CreatorCountry' => 'Ersteller - Land', + 'CreatorPostalCode' => 'Ersteller - PLZ', + 'CreatorRegion' => 'Ersteller - Bundesland/Kanton', + 'CreatorTool' => 'Erstellertool', + 'CreatorWorkEmail' => 'Ersteller - E-Mail', + 'CreatorWorkTelephone' => 'Ersteller - Telefon', + 'CreatorWorkURL' => 'Ersteller - Webseite(n)', + 'Credit' => 'Anbieter', + 'CropActive' => { + Description => 'Ausschnitt aktiviert', + PrintConv => { + 'No' => 'Nein', + 'Yes' => 'Ja', + }, + }, + 'CropAngle' => 'Ausschnitt Winkel', + 'CropAspectRatio' => { + Description => 'Ausschnitt Bildformat', + PrintConv => { + 'A-size Landscape' => 'DIN A Querformat', + 'A-size Portrait' => 'DIN A Hochformat', + 'Circle' => 'Kreis', + 'Custom' => 'Benutzerdefiniert', + 'Free' => 'Frei', + 'Letter-size Landscape' => 'Letter Querformat', + 'Letter-size Portrait' => 'Letter Querformat', + }, + }, + 'CropBottom' => 'Ausschnitt Unten', + 'CropBottomMargin' => 'Ausschnitt Rand Unten', + 'CropCircleActive' => { + PrintConv => { + 'No' => 'Nein', + 'Yes' => 'Ja', + }, + }, + 'CropHeight' => 'Ausschnitt Höhe', + 'CropHiSpeed' => 'Ausschnitt Highspeed', + 'CropLeft' => 'Ausschnitt Links', + 'CropLeftMargin' => 'Ausschnitt Rand Links', + 'CropRight' => 'Ausschnitt Rechts', + 'CropRightMargin' => 'Ausschnitt Rand Rechts', + 'CropRotation' => 'Ausschnitt Drehung', + 'CropTop' => 'Ausschnitt Oben', + 'CropTopMargin' => 'Ausschnitt Rand Oben', + 'CropUnit' => { + Description => 'Ausschnitt Einheit', + PrintConv => { + 'inches' => 'Zoll', + 'pixels' => 'Pixel', + }, + }, + 'CropUnits' => { + Description => 'Ausschnitt Einheiten', + PrintConv => { + 'inches' => 'Zoll', + 'pixels' => 'Pixel', + }, + }, + 'CropWidth' => 'Ausschnitt Breite', + 'CroppedImageHeight' => 'Ausschnitt Bildhöhe', + 'CroppedImageLeft' => 'Ausschnitt Bildanfang Links', + 'CroppedImageTop' => 'Ausschnitt Bildanfang Oben', + 'CroppedImageWidth' => 'Ausschnitt Bildbreite', + 'CurrentICCProfile' => 'Aktuelles ICC-Profile', + 'CurrentIPTCDigest' => 'Aktueller IPTC Kennwert', + 'Curves' => { + PrintConv => { + 'Off' => 'Aus', + 'On' => 'Ein', + }, + }, + 'Custom1' => 'Benutzerdefiniert 1', + 'Custom2' => 'Benutzerdefiniert 2', + 'Custom3' => 'Benutzerdefiniert 3', + 'Custom4' => 'Benutzerdefiniert 4', + 'CustomLinear' => { + PrintConv => { + 'No' => 'Nein', + 'Yes' => 'Ja', + }, + }, + 'CustomPictureStyleFileName' => 'Benutzer-Bildstil Dateiname', + 'CustomRendered' => { + Description => 'Benutzerdefinierte Bildverarbeitung', + PrintConv => { + 'Custom' => 'Benutzerdefinierter Prozess', + 'Normal' => 'Standard-Prozess', + }, + }, + 'D-LightingHQ' => { + PrintConv => { + 'Off' => 'Aus', + 'On' => 'Ein', + }, + }, + 'D-LightingHQSelected' => { + PrintConv => { + 'No' => 'Nein', + 'Yes' => 'Ja', + }, + }, + 'D-LightingHS' => { + PrintConv => { + 'Off' => 'Aus', + 'On' => 'Ein', + }, + }, + 'D-RangeOptimizerMode' => { + PrintConv => { + 'Manual' => 'Manuell', + 'Off' => 'Aus', + }, + }, + 'DECPosition' => { + Description => 'DEC-Position', + PrintConv => { + 'Contrast' => 'Kontrast', + 'Exposure' => 'Belichtung', + 'Saturation' => 'Sättigung', + }, + }, + 'DLOOn' => { + PrintConv => { + 'No' => 'Nein', + 'Yes' => 'Ja', + }, + }, + 'DNGBackwardVersion' => 'DNG Versionskompatibilität', + 'DNGLensInfo' => 'DNG Objektiv-Informationen', + 'DNGVersion' => 'DNG-Version', + 'DOF' => 'Schärfentiefe', + 'DSPFirmwareVersion' => 'DSP-Firmware-Version', + 'DataCompressionMethod' => 'Daten Komprimierungsmethode', + 'DataDump' => 'Daten-Dump', + 'DataDump2' => 'Daten-Dump 2', + 'DataImprint' => { + Description => 'Daten-Einblendung', + PrintConv => { + 'MM/DD/HH:MM' => 'MM/TT/SS:MM', + 'None' => 'Keine', + 'YYYY/MM/DD' => 'JJJJ/MM/TT', + }, + }, + 'DataLength' => 'Datenlänge', + 'Date' => 'Datum', + 'DateCreated' => 'Erstellungsdatum', + 'DateDisplayFormat' => { + Description => 'Datumsformat', + PrintConv => { + 'D/M/Y' => 'Tag/Monat/Jahr', + 'M/D/Y' => 'Monat/Tag/Jahr', + 'Y/M/D' => 'Jahr/Monat/Tag', + }, + }, + 'DateSent' => 'Absendedatum', + 'DateStampMode' => { + Description => 'Zeitstempel-Modus', + PrintConv => { + 'Date' => 'Datum', + 'Off' => 'Aus', + }, + }, + 'DateTime' => 'Änderungsdatum', + 'DateTimeCreated' => 'Erstellungsdatum/-uhrzeit', + 'DateTimeDigitized' => 'Datum/Uhrzeit der Digitalisierung', + 'DateTimeOriginal' => 'Erstellungsdatum/-uhrzeit', + 'DateTimeStamp' => 'Datum Uhrzeitangabe', + 'DaylightSavings' => { + Description => 'Sommerzeit', + PrintConv => { + 'No' => 'Aus', + 'Yes' => 'Ein', + }, + }, + 'Declination' => 'Deklination', + 'DefaultCropOrigin' => 'System-Ausschnitt Beginn', + 'DefaultCropSize' => 'System-Ausschnitt Größe', + 'DefaultDisplayHeight' => 'Default Anzeigehöhe', + 'DefaultDisplayWidth' => 'Default Anzeigebreite', + 'DefaultEraseOption' => { + Description => 'System-Löscheinstellung', + PrintConv => { + 'Cancel selected' => 'Abbruch', + 'Erase selected' => 'Löschen', + }, + }, + 'DefaultImageColor' => 'System-Bildfarbe', + 'DefaultScale' => 'Systemmaß', + 'DeletedImageCount' => 'Anzahl gelöschter Bilder', + 'Description' => 'Beschreibung', + 'Destination' => 'Ziel', + 'DestinationCity' => 'Zielort', + 'DestinationCityCode' => 'Zielort-Code', + 'DestinationDST' => { + Description => 'Zielort Sommerzeit (DST)', + PrintConv => { + 'No' => 'Deaktiviert', + 'Yes' => 'Aktiviert', + }, + }, + 'DevelopmentDynamicRange' => 'Dynamikbereich Entwicklung', + 'DeviceAttributes' => 'Geräte-Eigenschaften', + 'DeviceManufacturer' => 'Gerätehersteller', + 'DeviceMfgDesc' => 'Gerätehersteller-Bezeichnung', + 'DeviceModel' => 'Geräte-Modell', + 'DeviceModelDesc' => 'Geräte-Modell-Bezeichnung', + 'DeviceSettingDescription' => 'Geräteeinstellung', + 'DialDirectionTvAv' => { + Description => 'Drehung Wählrad bei Tv/Av', + PrintConv => { + 'Reversed' => 'Umgekehrt', + }, + }, + 'DigitalCreationDate' => 'Digitalisierungsdatum', + 'DigitalCreationDateTime' => 'Digitalisierungsdatum/-uhrzeit', + 'DigitalCreationTime' => 'Digitalisierungszeit', + 'DigitalFilter01' => { + PrintConv => { + 'Color Filter' => 'Farbfilter', + 'Fisheye' => 'Fischauge', + 'High Contrast' => 'Hoher Kontrast', + }, + }, + 'DigitalFilter02' => { + PrintConv => { + 'Color Filter' => 'Farbfilter', + 'Fisheye' => 'Fischauge', + 'High Contrast' => 'Hoher Kontrast', + }, + }, + 'DigitalFilter03' => { + PrintConv => { + 'Color Filter' => 'Farbfilter', + 'Fisheye' => 'Fischauge', + 'High Contrast' => 'Hoher Kontrast', + }, + }, + 'DigitalFilter04' => { + PrintConv => { + 'Color Filter' => 'Farbfilter', + 'Fisheye' => 'Fischauge', + 'High Contrast' => 'Hoher Kontrast', + }, + }, + 'DigitalFilter05' => { + PrintConv => { + 'Color Filter' => 'Farbfilter', + 'Fisheye' => 'Fischauge', + 'High Contrast' => 'Hoher Kontrast', + }, + }, + 'DigitalFilter06' => { + PrintConv => { + 'Color Filter' => 'Farbfilter', + 'Fisheye' => 'Fischauge', + 'High Contrast' => 'Hoher Kontrast', + }, + }, + 'DigitalFilter07' => { + PrintConv => { + 'Color Filter' => 'Farbfilter', + 'Fisheye' => 'Fischauge', + 'High Contrast' => 'Hoher Kontrast', + }, + }, + 'DigitalFilter08' => { + PrintConv => { + 'Color Filter' => 'Farbfilter', + 'Fisheye' => 'Fischauge', + 'High Contrast' => 'Hoher Kontrast', + }, + }, + 'DigitalFilter09' => { + PrintConv => { + 'Color Filter' => 'Farbfilter', + 'Fisheye' => 'Fischauge', + 'High Contrast' => 'Hoher Kontrast', + }, + }, + 'DigitalFilter10' => { + PrintConv => { + 'Color Filter' => 'Farbfilter', + 'Fisheye' => 'Fischauge', + 'High Contrast' => 'Hoher Kontrast', + }, + }, + 'DigitalFilter11' => { + PrintConv => { + 'Color Filter' => 'Farbfilter', + 'Fisheye' => 'Fischauge', + 'High Contrast' => 'Hoher Kontrast', + }, + }, + 'DigitalFilter12' => { + PrintConv => { + 'Color Filter' => 'Farbfilter', + 'Fisheye' => 'Fischauge', + 'High Contrast' => 'Hoher Kontrast', + }, + }, + 'DigitalFilter13' => { + PrintConv => { + 'Color Filter' => 'Farbfilter', + 'Fisheye' => 'Fischauge', + 'High Contrast' => 'Hoher Kontrast', + }, + }, + 'DigitalFilter14' => { + PrintConv => { + 'Color Filter' => 'Farbfilter', + 'Fisheye' => 'Fischauge', + 'High Contrast' => 'Hoher Kontrast', + }, + }, + 'DigitalFilter15' => { + PrintConv => { + 'Color Filter' => 'Farbfilter', + 'Fisheye' => 'Fischauge', + 'High Contrast' => 'Hoher Kontrast', + }, + }, + 'DigitalFilter16' => { + PrintConv => { + 'Color Filter' => 'Farbfilter', + 'Fisheye' => 'Fischauge', + 'High Contrast' => 'Hoher Kontrast', + }, + }, + 'DigitalFilter17' => { + PrintConv => { + 'Color Filter' => 'Farbfilter', + 'Fisheye' => 'Fischauge', + 'High Contrast' => 'Hoher Kontrast', + }, + }, + 'DigitalFilter18' => { + PrintConv => { + 'Color Filter' => 'Farbfilter', + 'Fisheye' => 'Fischauge', + 'High Contrast' => 'Hoher Kontrast', + }, + }, + 'DigitalFilter19' => { + PrintConv => { + 'Color Filter' => 'Farbfilter', + 'Fisheye' => 'Fischauge', + 'High Contrast' => 'Hoher Kontrast', + }, + }, + 'DigitalFilter20' => { + PrintConv => { + 'Color Filter' => 'Farbfilter', + 'Fisheye' => 'Fischauge', + 'High Contrast' => 'Hoher Kontrast', + }, + }, + 'DigitalGain' => 'Digitale Verstärkung', + 'DigitalZoom' => { + Description => 'Digital-Zoom', + PrintConv => { + 'Electronic magnification' => 'Elektronische Vergrößerung', + 'None' => 'Kein', + 'Off' => 'Aus', + 'Other' => 'Unbekannt', + }, + }, + 'DigitalZoomOn' => { + PrintConv => { + 'Off' => 'Aus', + 'On' => 'Ein', + }, + }, + 'DigitalZoomRatio' => 'Digitaler Zoom-Faktor', + 'Directory' => 'Verzeichnis', + 'DirectoryIndex' => 'Verzeichnis-Index', + 'DirectoryNumber' => 'Ordner-Nummer', + 'Disclaimer' => 'Haftungsbeschränkung', + 'DisplayAllAFPoints' => { + Description => 'Anzeige aller AF-Punkte', + PrintConv => { + 'Disable' => 'Deaktiviert', + 'Enable' => 'Aktiviert', + }, + }, + 'DisplayAperture' => 'Angezeigte Blende', + 'DisplayHeight' => 'Anzeigehöhe', + 'DisplayUnit' => { + PrintConv => { + 'Pixels' => 'Pixel', + 'inches' => 'Zoll', + }, + }, + 'DisplayUnits' => { + Description => 'Anzeigeeinheit', + PrintConv => { + 'inches' => 'Zoll', + 'meters' => 'Meter', + }, + }, + 'DisplayXResolutionUnit' => { + PrintConv => { + 'um' => 'µm (Mikrometer)', + }, + }, + 'DisplayYResolutionUnit' => { + PrintConv => { + 'um' => 'µm (Mikrometer)', + }, + }, + 'DisplayedUnitsX' => { + Description => 'Einheit der horiz. Auflösung', + PrintConv => { + 'inches' => 'Zoll', + }, + }, + 'DisplayedUnitsY' => { + Description => 'Einheit der vert. Auflösung', + PrintConv => { + 'inches' => 'Zoll', + }, + }, + 'DistortionControl' => { + Description => 'Verzeichnungskontrolle', + PrintConv => { + 'Off' => 'Aus', + 'On' => 'Ein', + }, + }, + 'DistortionCorrection' => { + Description => 'Verzeichnungskorrektur', + PrintConv => { + 'Off' => 'Aus', + 'On' => 'Ein', + 'n/a' => '(nicht gesetzt)', + }, + }, + 'DistortionCorrection2' => { + Description => 'Verzeichnungskorrektur 2', + PrintConv => { + 'Off' => 'Aus', + 'On' => 'Ein', + }, + }, + 'DistortionCorrectionOn' => 'Verzeichnungskorrektur Ein', + 'DistortionN' => 'Verzeichnung N', + 'DistortionParam02' => 'Verzeichnungsparameter 02', + 'DistortionParam04' => 'Verzeichnungsparameter 04', + 'DistortionParam08' => 'Verzeichnungsparameter 08', + 'DistortionParam09' => 'Verzeichnungsparameter 09', + 'DistortionParam11' => 'Verzeichnungsparameter 11', + 'DistortionScale' => 'Verzeichnungsausmaß', + 'DistortionVersion' => 'Verzeichnung Version', + 'DjVuVersion' => 'DjVu-Version', + 'DocSecurity' => { + Description => 'Dokumentensicherheit', + PrintConv => { + 'Locked for annotations' => 'Gesperrt für Anmerkungen', + 'None' => 'Keine', + 'Password protected' => 'Passwort geschützt', + 'Read-only enforced' => 'Nur Lesen - erzwungen', + 'Read-only recommended' => 'Nur Lesen - vorgeschlagen', + }, + }, + 'Document' => 'Dokument', + 'DocumentHistory' => 'Historie des Dokuments', + 'DocumentName' => 'Dokumentenname', + 'DocumentNotes' => 'Notizen zum Dokument', + 'DriveMode' => { + Description => 'Aufnahmeart', + PrintConv => { + '10 s Timer' => 'Selbstauslöser 10 s', + '2 s Timer' => 'Selbstauslöser 2 s', + 'Auto Bracket' => 'Belichtungsreihe', + 'Bracketing' => 'Belichtungsreihe', + 'Continuous' => 'Serienaufnahme', + 'Continuous (Lo)' => 'Serienaufnahme (Niedrig)', + 'Continuous Bracketing' => 'Serienbild-Belichtungsreihe', + 'Continuous Exposure Bracketing' => 'Serienaufnahme Belichtungsreihe', + 'Continuous High' => 'Serienaufnahme (Hi)', + 'Continuous Low' => 'Serienaufnahme Niedrig', + 'Continuous Shooting' => 'Serienaufnahme', + 'HS continuous' => 'High-Speed Serienbild', + 'Mirror Lock-up' => 'Spiegel hochgeklappt', + 'Multi Shot' => 'Serienaufnahme', + 'Multiple Exposure' => 'Mehrfachbelichtung', + 'No Timer' => 'Ohne Selbstauslöser', + 'Off' => 'Aus', + 'Remote Control' => 'Fernauslöser', + 'Remote Control (3 s delay)' => 'Fernauslöser (3 Sek. Verzögerung)', + 'Self-Timer 2 sec' => 'Selbstauslöser 2 s', + 'Self-timer' => 'Selbstauslöser', + 'Self-timer (12 s)' => 'Selbstauslöser (12 Sek.)', + 'Self-timer (2 s)' => 'Selbstauslöser (2 Sek.)', + 'Self-timer 10 sec' => 'Selbstauslöser 10 s', + 'Self-timer 2 sec, Mirror Lock-up' => 'Selbstauslöser 2 s, Spiegel hochgeklappt', + 'Self-timer Operation' => 'Selbstauslöser', + 'Shutter Button' => 'Kamera-Auslöser', + 'Single' => 'Einzelbild', + 'Single Exposure' => 'Einzelbelichtung', + 'Single Frame' => 'Einzelbild', + 'Single Shot' => 'Einzelbild', + 'Single-Frame Bracketing' => 'Einzelbild-Belichtungsreihe', + 'Single-frame' => 'Einzelbild', + 'Single-frame Bracketing' => 'Einzelbild-Belichtungsreihe', + 'Single-frame Exposure Bracketing' => 'Einzelbild Belichtungsreihe', + 'Single-frame Shooting' => 'Einzelbild', + 'UHS continuous' => 'Ultra High-Speed Serienbild', + 'White Balance Bracketing' => 'Weißabgleichs-Belichtungsreihe', + 'White Balance Bracketing High' => 'Weißabgleich-Belichtungsreihe Hoch', + 'White Balance Bracketing Low' => 'Weißabgleich-Belichtungsreihe Niedrig', + 'n/a' => '(nicht gesetzt)', + }, + }, + 'DriveMode2' => { + Description => 'Mehrfachbelichtung', + PrintConv => { + 'Continous Bracketing Low' => 'Serienaufnahme Belichtungsreihe Niedrig', + 'Continuous' => 'Serienaufnahme', + 'Continuous (Lo)' => 'Serienaufnahme (Niedrig)', + 'Continuous Bracketing' => 'Serienaufnahme Belichtungsreihe', + 'Continuous Bracketing 0.3 EV' => 'Serienaufnahme Belichtungsreihe 0.3 EV', + 'Continuous Bracketing 0.7 EV' => 'Serienaufnahme Belichtungsreihe 0.7 EV', + 'Continuous Bracketing High' => 'Serienaufnahme Belichtungsreihe Hoch', + 'Continuous High' => 'Serienaufnahme Hoch', + 'Continuous Low' => 'Serienaufnahme Niedrig', + 'Exposure Bracket' => 'Belichtungsreihe', + 'Mirror Lock-up' => 'Spiegel hochgeklappt', + 'Multiple Exposure' => 'Mehrfachbelichtung', + 'Remote Control' => 'Fernauslöser', + 'Remote Control (3 s delay)' => 'Fernauslöser (3 s verzögert)', + 'Self-timer (12 s)' => 'Selbstauslöser (12 s)', + 'Self-timer (2 s)' => 'Selbstauslöser (2 s)', + 'Self-timer 10 sec' => 'Selbstauslöser 10 s', + 'Self-timer 2 sec' => 'Selbstauslöser 2 s', + 'Self-timer 2 sec, Mirror Lock-up' => 'Selbstauslöser 2 s, Spiegel hochgeklappt', + 'Single Frame' => 'Einzelbild', + 'Single-frame' => 'Einzelbildaufnahme', + 'Single-frame Bracketing' => 'Einzelbild Belichtungsreihe', + 'Single-frame Bracketing High' => 'Einzelbild Belichtungsreihe Hoch', + 'Single-frame Bracketing Low' => 'Einzelbild Belichtungsreihe Niedrig', + 'White Balance Bracketing High' => 'Weißabgleich Belichtungsreihe Hoch', + 'White Balance Bracketing Low' => 'Weißabgleich Belichtungsreihe Niedrig', + }, + }, + 'DriveModeSetting' => { + Description => 'Aufnahmeart Einstellung', + PrintConv => { + 'Continuous High' => 'Serienaufnahme Hoch', + 'Continuous Low' => 'Serienaufnahme Niedrig', + 'Self-timer 10 sec' => 'Selbstauslöser 10 s', + 'Self-timer 2 sec, Mirror Lock-up' => 'Selbstauslöser 2 s, Spiegel hochgeklappt', + 'Single Frame' => 'Einzelbild', + }, + }, + 'DriveType' => { + PrintConv => { + 'Unknown' => 'Unbekannt', + }, + }, + 'Duration' => 'Dauer', + 'DustRemovalData' => 'Dunstentfernungsdaten', + 'DynamicAFArea' => { + Description => 'Dynamisches AF-Messfeld', + PrintConv => { + '21 Points' => '21 Messfelder', + '51 Points' => '51 Messfelder', + '51 Points (3D-tracking)' => '51 Messfelder (3D-Tracking)', + '9 Points' => '9 Messfelder', + }, + }, + 'DynamicRange' => { + Description => 'Dynamikbereich', + PrintConv => { + 'Wide' => 'Weit', + }, + }, + 'DynamicRangeExpansion' => { + Description => 'Dynamikbereich-Erweiterung', + PrintConv => { + 'Off' => 'Aus', + 'On' => 'Ein', + }, + }, + 'DynamicRangeOptimizer' => { + Description => 'Dynamikbereich-Optimierung', + PrintConv => { + 'Advanced Auto' => 'Erw. Automatik', + 'Advanced Lv1' => 'Erw. Stufe 1', + 'Advanced Lv2' => 'Erw. Stufe 2', + 'Advanced Lv3' => 'Erw. Stufe 3', + 'Advanced Lv4' => 'Erw. Stufe 4', + 'Advanced Lv5' => 'Erw. Stufe 5', + 'Auto' => 'Automatisch', + 'Off' => 'Aus', + }, + }, + 'DynamicRangeOptimizerBracket' => { + PrintConv => { + 'High' => 'Hoch', + 'Low' => 'Niedrig', + 'Off' => 'Aus', + }, + }, + 'DynamicRangeOptimizerMode' => { + PrintConv => { + 'Off' => 'Aus', + }, + }, + 'DynamicRangeSetting' => { + Description => 'Dynamikbereich-Einstellungen', + PrintConv => { + 'Film Simulation' => 'Film-Simulation', + 'Wide1 (230%)' => 'Weit1 (230%)', + 'Wide2 (400%)' => 'Weit2 (400%)', + }, + }, + 'E-DialInProgram' => { + PrintConv => { + 'Tv or Av' => 'Tv oder Av', + }, + }, + 'ETTLII' => { + PrintConv => { + 'Average' => 'Integralmessung', + 'Evaluative' => 'Mehrfeldmessung', + }, + }, + 'EVStepInfo' => 'EV-Schritte Information', + 'EVStepSize' => { + Description => 'Belichtungswerte', + PrintConv => { + '1/2 EV' => '1/2 LW', + '1/3 EV' => '1/3 LW', + }, + }, + 'EVSteps' => { + Description => 'LW-Schritte', + PrintConv => { + '1/2 EV Steps' => '1/2 LW-Schritte', + '1/3 EV Steps' => '1/3 LW-Schritte', + }, + }, + 'EasyExposureComp' => 'Easy Belichtungskorrektur', + 'EasyExposureCompensation' => { + Description => 'Easy Belichtungskorrektur', + PrintConv => { + 'Off' => 'Aus', + 'On' => 'Ein', + 'On (auto reset)' => 'Einstellrad (Reset)', + }, + }, + 'EasyMode' => { + Description => 'Easy-Modus', + PrintConv => { + 'Beach' => 'Strand', + 'Black & White' => 'Schwarz/Weiß', + 'Blur Reduction' => 'Unschärfereduktion', + 'Color Accent' => 'Farbton', + 'Color Swap' => 'Farbwechsel', + 'Digital Macro' => 'Digitales Makro', + 'Fireworks' => 'Feuerwerk', + 'Foliage' => 'Laub', + 'Full auto' => 'Vollautomatisch', + 'Indoor' => 'Innenaufnahme', + 'Kids & Pets' => 'Kinder & Tiere', + 'Landscape' => 'Landschaft', + 'Live View Control' => 'Live View Kontrolle', + 'Low Light' => 'Wenig Licht', + 'Low Light 2' => 'Wenig Licht 2', + 'Macro' => 'Makro', + 'Manual' => 'Manuell', + 'Night' => 'Nachtszene', + 'Night Scene' => 'Nachtszene', + 'Night Snapshot' => 'Nacht Schnappschuss', + 'Pan focus' => 'Pan Fokus', + 'Portrait' => 'Porträt', + 'Snow' => 'Schnee', + 'Sports' => 'Sport', + 'Sunset' => 'Sonnenuntergang', + 'Super Macro' => 'Super-Makro', + 'Super Macro 2' => 'Super Makro 2', + 'Underwater' => 'Unterwasser', + 'Zoom Blur' => 'Zoom Unschärfe', + }, + }, + 'EdgeNoiseReduction' => { + Description => 'Rauschunterdrückung Ecken', + PrintConv => { + 'Off' => 'Aus', + 'On' => 'Ein', + }, + }, + 'EditStatus' => 'Bearbeitungsstatus', + 'Edition' => 'Ausgabe', + 'EditorialUpdate' => 'Redaktionelle Überarbeitung', + 'EffectiveLV' => 'Effektiver LW', + 'EffectiveMaxAperture' => 'Effektiv größte Blende', + 'Email' => 'E-Mail', + 'EmbeddedImage' => 'Eingebettetes Bild', + 'EmbeddedImageByteOrder' => 'Eingebettetes Bild Bytereihenfolge', + 'EmbeddedImageHeight' => 'Eingebettetes Bild Bildhöhe', + 'EmbeddedImageType' => 'Eingebettetes Bild Bildtyp', + 'EmbeddedImageWidth' => 'Eingebettetes Bild Bildbreite', + 'Emphasis' => { + PrintConv => { + 'None' => 'Keine', + 'reserved' => 'reserviert', + }, + }, + 'Encoding' => { + PrintConv => { + 'Unknown -' => 'Unbekannt -', + }, + }, + 'EncodingProcess' => 'JPEG-Kodierung Prozess', + 'Encryption' => 'Verschlüsselung', + 'EnhanceDarkTones' => { + Description => 'Dunkle Stellen aufhellen', + PrintConv => { + 'Off' => 'Aus', + 'On' => 'Ein', + }, + }, + 'Enhancement' => { + PrintConv => { + 'Blue' => 'Blau', + 'Green' => 'Grün', + 'Off' => 'Aus', + 'Red' => 'Rot', + 'Underwater' => 'Unterwasser', + }, + }, + 'EnvelopePriority' => { + Description => 'Priorität', + PrintConv => { + '0 (reserved)' => '0 (reserviert)', + '1 (most urgent)' => '1 (sehr dringend)', + '5 (normal urgency)' => '5 (normale Dringlichkeit)', + '8 (least urgent)' => '8 (geringe Wichtigkeit)', + '9 (user-defined priority)' => '9 (benutzerdefinierte Priorität)', + }, + }, + 'EnvelopeRecordVersion' => 'IPTC-Modell-1-Version', + 'EpsonImageHeight' => 'Epson-Bildhöhe', + 'EpsonImageWidth' => 'Epson-Bildbreite', + 'Equipment' => 'Equipment-IFD-Zeiger', + 'EquipmentVersion' => 'Equipment-Version', + 'Error' => 'Fehler', + 'ExifByteOrder' => 'Exif Byte-Reihenfolge', + 'ExifCameraInfo' => 'Exif Kamerainformationen', + 'ExifImageHeight' => 'Exif-Bildhöhe', + 'ExifImageWidth' => 'Exif-Bildbreite', + 'ExifOffset' => 'Exif IFD-Zeiger', + 'ExifToolVersion' => 'ExifTool-Version', + 'ExifUnicodeByteOrder' => 'Exif Unicode Byte-Reihenfolge', + 'ExifVersion' => 'Exif-Version', + 'ExitPupilPosition' => 'Austrittspupillenposition', + 'ExpandFilm' => 'Erweitert Film', + 'ExpandFilterLens' => 'Erweitert Filterlinse', + 'ExpandFlashLamp' => 'Erweitert Blitzlicht', + 'ExpandLens' => 'Erweitert Objektiv', + 'ExpandScanner' => 'Erweitert Scanner', + 'ExpandSoftware' => 'Erweitert Software', + 'ExpirationDate' => 'Ablaufdatum', + 'ExpirationTime' => 'Ablaufzeit', + 'Exposure' => 'Belichtung', + 'Exposure2012' => 'Belichtung 2012', + 'ExposureAdj' => 'Belichtungskorrektur', + 'ExposureAdj2' => 'Belichtungskorrektur 2', + 'ExposureAdjust' => 'Belichtungskorrektur', + 'ExposureBias' => 'Belichtungskorrekturwert', + 'ExposureBracketShotNumber' => 'Belichtungsreihen-Bildnummer', + 'ExposureBracketStepSize' => 'Belichtungsreihen-Stufenabstand', + 'ExposureBracketValue' => 'Belichtungsreihenwert', + 'ExposureCompStepSize' => { + Description => 'Belichtungskorrekturstufe', + PrintConv => { + '1 EV' => '1 LW', + '1/2 EV' => '1/2 LW', + '1/3 EV' => '1/3 LW', + }, + }, + 'ExposureCompensation' => 'Belichtungskorrektur', + 'ExposureCompensation2' => 'Belichtungskorrektur 2', + 'ExposureCompensationMode' => 'Belichtungskorrekturmodus', + 'ExposureControlStepSize' => { + Description => 'Belichtungswert', + PrintConv => { + '1 EV' => '1 LW', + '1/2 EV' => '1/2 LW', + '1/3 EV' => '1/3 LW', + }, + }, + 'ExposureDelayMode' => { + Description => 'Spiegelvorauslösung', + PrintConv => { + 'Off' => 'Aus', + 'On' => 'Ein', + }, + }, + 'ExposureDifference' => 'Belichtungsabweichung', + 'ExposureIndex' => 'Belichtungsindex', + 'ExposureLevelIncrements' => { + Description => 'Belichtungswert', + PrintConv => { + '1-stop set, 1/3-stop comp.' => '1-Blende, 1/3-Blendenkompensation', + '1/2 Stop' => '1/2 LW', + '1/2-stop set, 1/2-stop comp.' => '1/2-Blende, 1/2-Blendenkompensation', + '1/3 Stop' => '1/3 LW', + '1/3-stop set, 1/3-stop comp.' => '1/3-Blende, 1/3-Blendenkompensation', + }, + }, + 'ExposureMode' => { + Description => 'Belichtungsmodus', + PrintConv => { + 'Anti Motion Blur' => 'Verwackelungsschutz', + 'Aperture Priority' => 'Blendenpriorität', + 'Aperture-priority AE' => 'Blendenpriorität', + 'Auto' => 'Automatische Belichtung', + 'Auto bracket' => 'Belichtungsreihe', + 'Auto?' => 'Automatisch?', + 'Backlight Correction HDR' => 'Hintergrundbeleuchtung HDR Korrektur', + 'Beach' => 'Strand', + 'Bulb' => 'Bulb-Modus', + 'Fireworks' => 'Feuerwerk', + 'Food' => 'Lebensmittel', + 'High Sensitivity' => 'Hohe Empfindlichkeit', + 'Landscape' => 'Landschaft', + 'Macro' => 'Makro', + 'Manual' => 'Manuelle Belichtung', + 'Night Scene / Twilight' => 'Nachtszene / Dämmerung', + 'Night View/Portrait' => 'Abendszene/Porträt', + 'Pet' => 'Haustiere', + 'Portrait' => 'Porträt', + 'Program' => 'Programm', + 'Program-shift' => 'Programm-Shift', + 'Program-shift A' => 'Programmverschiebung A', + 'Program-shift S' => 'Programmverschiebung S', + 'Shutter Priority' => 'Verschlusspriorität', + 'Shutter speed priority AE' => 'Verschlusspriorität', + 'Snow' => 'Schnee', + 'Sports' => 'Sport', + 'Sunset' => 'Sonnenuntergang', + 'Twilight Portrait' => 'Dämmerung Portät', + 'Underwater' => 'Unterwasser', + 'n/a' => '(nicht gesetzt)', + }, + }, + 'ExposureModeInManual' => { + Description => 'Belichtungsmodus bei manueller Belichtung', + PrintConv => { + 'Center-weighted average' => 'Mittenbetont', + 'Evaluative metering' => 'Mehrfeldmessung', + 'Partial metering' => 'Teilbild', + 'Specified metering mode' => 'Spezifizierte Messmethode', + 'Spot metering' => 'Spotmessung', + }, + }, + 'ExposureProgram' => { + Description => 'Belichtungsprogramm', + PrintConv => { + 'Action (High speed)' => 'Kreativ-Programm (ausgerichtet auf schnelle Verschlussgeschwindigkeit)', + 'Anti Motion Blur' => 'Verwackelungsschutz', + 'Aperture Priority' => 'Blendenpriorität', + 'Aperture-priority AE' => 'Blendenpriorität', + 'Creative (Slow speed)' => 'Kreativ-Programm (ausgerichtet auf Schärfentiefe)', + 'Landscape' => 'Landschaft', + 'Macro' => 'Makro', + 'Manual' => 'Manuell', + 'Night Portrait' => 'Nachtporträt', + 'Night view' => 'Abendszene', + 'Night view/portrait' => 'Abendszene/Porträt', + 'Not Defined' => 'Nicht definiert', + 'Portrait' => 'Porträt', + 'Program' => 'Programm', + 'Program AE' => 'Normal-Programm', + 'Shutter Priority' => 'Verschlusspriorität', + 'Shutter speed priority AE' => 'Verschlusspriorität', + 'Sports' => 'Sport', + 'Sunset' => 'Sonnenuntergang', + }, + }, + 'ExposureTime' => 'Belichtungsdauer', + 'ExposureTime2' => 'Belichtungsdauer 2', + 'ExposureValue' => 'Belichtungsdauer', + 'ExposureWarning' => { + Description => 'Belichtungswarnung', + PrintConv => { + 'Bad exposure' => 'Schlechte Belichtung', + 'Good' => 'OK', + }, + }, + 'ExtendedWBDetect' => { + PrintConv => { + 'Off' => 'Aus', + 'On' => 'Ein', + }, + }, + 'Extender' => { + Description => 'Konverter', + PrintConv => { + 'None' => 'Keiner', + }, + }, + 'ExtenderFirmwareVersion' => 'Konverter-Firmware-Version', + 'ExtenderMake' => 'Konverterhersteller', + 'ExtenderModel' => 'Konverter-Modell', + 'ExtenderSerialNumber' => 'Konverter-Seriennummer', + 'ExtenderStatus' => { + Description => 'Status Telekonverter', + PrintConv => { + 'Attached' => 'Angesetzt', + 'Not attached' => 'Nicht angesetzt', + 'Removed' => 'Entfernt', + }, + }, + 'ExternalFlash' => { + Description => 'Externer Blitz', + PrintConv => { + 'Off' => 'Aus', + 'On' => 'Ein', + }, + }, + 'ExternalFlashAE1' => 'Externer Blitz AE1', + 'ExternalFlashAE1_0' => 'Externer Blitz AE1 0', + 'ExternalFlashAE2' => 'Externer Blitz AE2', + 'ExternalFlashAE2_0' => 'Externer Blitz AE2 0', + 'ExternalFlashBounce' => { + Description => 'Externer Blitz - Bounce', + PrintConv => { + 'Bounce' => 'Mit Bounce', + 'Direct' => 'Direkt', + 'No' => 'Nein', + 'Yes' => 'Ja', + 'n/a' => '(nicht gesetzt)', + }, + }, + 'ExternalFlashCompensation' => 'Externe Blitzbelichtungskorrektur', + 'ExternalFlashExposureComp' => { + Description => 'Belichtungskorrektur des externen Blitzgeräts', + PrintConv => { + '-0.5' => '-0.5 LW', + '-1.0' => '-1.0 LW', + '-1.5' => '-1.5 LW', + '-2.0' => '-2.0 LW', + '-2.5' => '-2.5 LW', + '-3.0' => '-3.0 LW', + '0.0' => '0.0 LW', + '0.5' => '0.5 LW', + '1.0' => '1.0 LW', + 'n/a' => 'Nicht gesetzt (Aus oder Auto-Modi)', + 'n/a (Manual Mode)' => 'Nicht gesetzt (Manueller Modus)', + }, + }, + 'ExternalFlashFirmware' => { + Description => 'Externer Blitz Firmware', + PrintConv => { + 'n/a' => '(nicht gesetzt)', + }, + }, + 'ExternalFlashFlags' => { + Description => 'Externer Blitz Flags', + PrintConv => { + 'Fired' => 'Ausgelöst', + }, + }, + 'ExternalFlashGValue' => 'Externer Blitz Leitzahl', + 'ExternalFlashGuideNumber' => 'Leitzahl des externen Blitzgeräts', + 'ExternalFlashMode' => { + Description => 'Slave-Blitz-Messfeld 3', + PrintConv => { + 'Off' => 'Aus', + 'On, Auto' => 'Ein, Auto', + 'On, Contrast-control Sync' => 'Ein, Kontrast-Steuerungs-Synchronisation', + 'On, Flash Problem' => 'Ein, Blitzproblem?', + 'On, High-speed Sync' => 'Ein, High-Speed-Synchronisation', + 'On, Manual' => 'Ein, Manuell', + 'On, P-TTL Auto' => 'Ein, P-TTL-Blitzautomatik', + 'On, Wireless' => 'Ein, Drahtlos', + 'On, Wireless, High-speed Sync' => 'Ein, Drahtlos, High-Speed-Synchronisation', + 'n/a - Off-Auto-Aperture' => 'K/A - Blendenring nicht auf A', + }, + }, + 'ExternalFlashZoom' => 'Externer Blitz-Zoom', + 'ExternalSensorBrightnessValue' => 'Externer Sensor Helligkeitswert', + 'ExtraSamples' => 'Zusätzliche Komponenten', + 'FEMicroadjustment' => { + Description => 'FE Feinabstimmung', + PrintConv => { + 'Disable' => 'Deaktiviert', + 'Enable' => 'Aktiviert', + }, + }, + 'FNumber' => 'F-Wert', + 'FOV' => 'Sichtfeld', + 'Face0Position' => 'Position, 0. Gesicht', + 'Face10Position' => 'Position, 10. Gesicht', + 'Face10Size' => 'Größe, 10. Gesicht', + 'Face11Position' => 'Position, 11. Gesicht', + 'Face11Size' => 'Größe, 11. Gesicht', + 'Face12Position' => 'Position, 12. Gesicht', + 'Face12Size' => 'Größe, 12. Gesicht', + 'Face13Position' => 'Position, 13. Gesicht', + 'Face13Size' => 'Größe, 13. Gesicht', + 'Face14Position' => 'Position, 14. Gesicht', + 'Face14Size' => 'Größe, 14. Gesicht', + 'Face15Position' => 'Position, 15. Gesicht', + 'Face15Size' => 'Größe, 15. Gesicht', + 'Face16Position' => 'Position, 16. Gesicht', + 'Face16Size' => 'Größe, 16. Gesicht', + 'Face17Position' => 'Position, 17. Gesicht', + 'Face17Size' => 'Größe, 17. Gesicht', + 'Face18Position' => 'Position, 18. Gesicht', + 'Face18Size' => 'Größe, 18. Gesicht', + 'Face19Position' => 'Position, 19. Gesicht', + 'Face19Size' => 'Größe, 19. Gesicht', + 'Face1Position' => 'Position, 1. Gesicht', + 'Face1Size' => 'Größe, 1. Gesicht', + 'Face20Position' => 'Position, 20. Gesicht', + 'Face20Size' => 'Größe, 20. Gesicht', + 'Face21Position' => 'Position, 21. Gesicht', + 'Face21Size' => 'Größe, 21. Gesicht', + 'Face22Position' => 'Position, 22. Gesicht', + 'Face22Size' => 'Größe, 22. Gesicht', + 'Face23Position' => 'Position, 23. Gesicht', + 'Face23Size' => 'Größe, 23. Gesicht', + 'Face24Position' => 'Position, 24. Gesicht', + 'Face24Size' => 'Größe, 24. Gesicht', + 'Face25Position' => 'Position, 25. Gesicht', + 'Face25Size' => 'Größe, 25. Gesicht', + 'Face26Position' => 'Position, 26. Gesicht', + 'Face26Size' => 'Größe, 26. Gesicht', + 'Face27Position' => 'Position, 27. Gesicht', + 'Face27Size' => 'Größe, 27. Gesicht', + 'Face28Position' => 'Position, 28. Gesicht', + 'Face28Size' => 'Größe, 28. Gesicht', + 'Face29Position' => 'Position, 29. Gesicht', + 'Face29Size' => 'Größe, 29. Gesicht', + 'Face2Position' => 'Position, 2. Gesicht', + 'Face2Size' => 'Größe, 2. Gesicht', + 'Face30Position' => 'Position, 30. Gesicht', + 'Face30Size' => 'Größe, 30. Gesicht', + 'Face31Position' => 'Position, 31. Gesicht', + 'Face31Size' => 'Größe, 31. Gesicht', + 'Face32Position' => 'Position, 32. Gesicht', + 'Face32Size' => 'Größe, 32. Gesicht', + 'Face3Position' => 'Position, 3. Gesicht', + 'Face3Size' => 'Größe, 3. Gesicht', + 'Face4Position' => 'Position, 4. Gesicht', + 'Face4Size' => 'Größe, 4. Gesicht', + 'Face5Position' => 'Position, 5. Gesicht', + 'Face5Size' => 'Größe, 5. Gesicht', + 'Face6Position' => 'Position, 6. Gesicht', + 'Face6Size' => 'Größe, 6. Gesicht', + 'Face7Position' => 'Position, 7. Gesicht', + 'Face7Size' => 'Größe, 7. Gesicht', + 'Face8Position' => 'Position, 8. Gesicht', + 'Face8Size' => 'Größe, 8. Gesicht', + 'Face9Position' => 'Position, 9. Gesicht', + 'Face9Size' => 'Größe, 9. Gesicht', + 'FaceDetect' => { + Description => 'Gesichtserkennung', + PrintConv => { + 'Off' => 'Aus', + 'On' => 'Ein', + }, + }, + 'FaceDetectArea' => 'Gesichtserkennung Bereich', + 'FaceDetectFrameSize' => 'Gesichtserkennung Bereichsgröße', + 'FaceInfoUnknown' => 'Gesichterinformation Unbekannt', + 'FaceOrientation' => { + Description => 'Ausrichtung Gesichtserkennung', + PrintConv => { + 'Rotate 180' => '180° gedreht', + 'Rotate 270 CW' => '90° gegen den Uhrzeigersinn', + 'Rotate 90 CW' => '90° im Uhrzeigersinn', + }, + }, + 'FacePositions' => 'Positionen der Gesichter', + 'FacesDetected' => { + Description => 'Gesichter erkannt', + PrintConv => { + 'n/a' => '(nicht gesetzt)', + }, + }, + 'FacesRecognized' => 'Gesichter erkannt', + 'FastSeek' => { + PrintConv => { + 'No' => 'Nein', + 'Yes' => 'Ja', + }, + }, + 'FaxProfile' => { + Description => 'Faxprofil', + PrintConv => { + 'Unknown' => 'Unbekannt', + }, + }, + 'FaxRecvParams' => 'Fax-Empfangsparameter', + 'FaxRecvTime' => 'Fax-Empfangszeit', + 'FaxSubAddress' => 'Fax-Sub-Adresse', + 'FileAccessDate' => 'Datum/Uhrzeit des letzten Dateizugriffs', + 'FileCreateDate' => 'Datum/Uhrzeit der Dateierstellung', + 'FileDescription' => 'Dateibeschreibung', + 'FileExtension' => 'Dateiendung', + 'FileFormat' => 'Dateiformat', + 'FileIndex' => 'Datei-Index', + 'FileInfo' => 'Datei-Informationen', + 'FileInfoVersion' => 'Datei-Informationen-Version', + 'FileInodeChangeDate' => 'Datum/Uhrzeit der letzten Inode-Änderung', + 'FileModifyDate' => 'Datum/Uhrzeit der Dateiänderung', + 'FileName' => 'Dateiname', + 'FileNumber' => 'Dateinummer', + 'FileNumberMemory' => { + Description => 'Dateinummernspeicher', + PrintConv => { + 'Off' => 'Aus', + 'On' => 'Ein', + }, + }, + 'FileNumberSequence' => { + Description => 'Nummernspeicher', + PrintConv => { + 'Off' => 'Aus', + 'On' => 'Ein', + }, + }, + 'FilePermissions' => 'Dateiberechtigungen', + 'FileSequence' => 'Dateireihenfolge', + 'FileSize' => 'Dateigröße', + 'FileSource' => { + Description => 'Dateiquelle', + PrintConv => { + 'Digital Camera' => 'Digital-Kamera', + 'Film Scanner' => 'Film-Scanner', + 'Reflection Print Scanner' => 'Scanner', + 'Sigma Digital Camera' => 'Sigma Digital-Kamera', + }, + }, + 'FileType' => 'Dateityp', + 'FileTypeDescription' => 'Dateityp Beschreibung', + 'FileVersion' => 'Dateiformatversion', + 'Filename' => 'Dateiname', + 'FillFlashAutoReduction' => { + Description => 'E-TTL II-Automatikblitz-System', + PrintConv => { + 'Disable' => 'Nicht möglich', + 'Enable' => 'Möglich', + }, + }, + 'FilmMode' => { + Description => 'Film-Modus', + PrintConv => { + 'F1/Studio Portrait' => 'F1/Studio-Porträt', + 'F1a/Studio Portrait Enhanced Saturation' => 'F1a/Studio-Porträt Erweiterte Sättigung', + 'F1b/Studio Portrait Smooth Skin Tone (ASTIA)' => 'F1b/Studio-Porträt Weiche Hauttöne', + 'F1c/Studio Portrait Increased Sharpness' => 'F1c/Studio-Porträt Erhöhte Schärfe', + 'F3/Studio Portrait Ex' => 'F3/Studio Porträt Ex', + 'n/a' => '(nicht gesetzt)', + }, + }, + 'FilmType' => 'Filmtyp', + 'FilterEffect' => { + Description => 'Filtereffekt', + PrintConv => { + 'Green' => 'Grün', + 'None' => 'Keiner', + 'Off' => 'Aus', + 'Red' => 'Rot', + 'Yellow' => 'Gelb', + 'n/a' => '(nicht gesetzt)', + }, + }, + 'FilterEffectFaithful' => { + Description => 'Filtereffekt Natürlich', + PrintConv => { + 'n/a' => '(nicht gesetzt)', + }, + }, + 'FilterEffectLandscape' => { + Description => 'Filtereffekt Landschaft', + PrintConv => { + 'n/a' => '(nicht gesetzt)', + }, + }, + 'FilterEffectMonochrome' => { + Description => 'Filtereffekt Monochrom', + PrintConv => { + 'Green' => 'Grün', + 'None' => 'Keiner', + 'Red' => 'Rot', + 'Yellow' => 'Gelb', + 'n/a' => '(nicht gesetzt)', + }, + }, + 'FilterEffectNeutral' => { + Description => 'Filtereffekt Neutral', + PrintConv => { + 'n/a' => '(nicht gesetzt)', + }, + }, + 'FilterEffectPortrait' => { + Description => 'Filtereffekt Porträt', + PrintConv => { + 'n/a' => '(nicht gesetzt)', + }, + }, + 'FilterEffectStandard' => { + Description => 'Filtereffekt Standard', + PrintConv => { + 'n/a' => '(nicht gesetzt)', + }, + }, + 'FilterEffectUnknown' => { + Description => 'Filtereffekt Unbekannt', + PrintConv => { + 'Green' => 'Grün', + 'None' => 'Keiner', + 'Red' => 'Rot', + 'Yellow' => 'Gelb', + 'n/a' => '(nicht gesetzt)', + }, + }, + 'FilterEffectUserDef1' => { + Description => 'Filtereffekt Benutzerdefiniert 1', + PrintConv => { + 'Green' => 'Grün', + 'None' => 'Keiner', + 'Red' => 'Rot', + 'Yellow' => 'Gelb', + 'n/a' => '(nicht gesetzt)', + }, + }, + 'FilterEffectUserDef2' => { + Description => 'Filtereffekt Benutzerdefineirt 2', + PrintConv => { + 'Green' => 'Grün', + 'None' => 'Keiner', + 'Red' => 'Rot', + 'Yellow' => 'Gelb', + 'n/a' => '(nicht gesetzt)', + }, + }, + 'FilterEffectUserDef3' => { + Description => 'Filtereffekt Benutzerdefiniert 3', + PrintConv => { + 'Green' => 'Grün', + 'None' => 'Keiner', + 'Red' => 'Rot', + 'Yellow' => 'Gelb', + 'n/a' => '(nicht gesetzt)', + }, + }, + 'FinderDisplayDuringExposure' => { + Description => 'Sucheranzeige bei Belichtung', + PrintConv => { + 'Off' => 'Aus', + 'On' => 'Ein', + }, + }, + 'FineSharpness' => { + Description => 'Detail-Schärfe', + PrintConv => { + 'Extra fine' => 'Extra', + 'Off' => 'Aus', + 'On' => 'Ein', + }, + }, + 'FineTuneOptCenterWeighted' => 'Feinabst. der Bel.Messung Mittenbetonte Messung', + 'FineTuneOptMatrixMetering' => 'Feinabst. der Bel.Messung Matrixmessung', + 'FineTuneOptSpotMetering' => 'Feinabst. der Bel.Messung Spotmessung', + 'FirmwareRevision' => 'Firmware-Revision', + 'FirmwareRevision2' => 'Firmware-Revision 2', + 'FirmwareVersion' => 'Firmware-Version', + 'FixtureIdentifier' => 'Kennzeichnung', + 'Flash' => { + Description => 'Blitzmodus', + PrintConv => { + 'Auto, Did not fire' => 'Blitz wurde nicht ausgelöst, Automodus', + 'Auto, Did not fire, Red-eye reduction' => 'Blitz wurde nicht ausgelöst, Rote-Augen-Reduzierung', + 'Auto, Fired' => 'Blitz wurde ausgelöst, Automodus', + 'Auto, Fired, Red-eye reduction' => 'Blitz wurde ausgelöst, Automodus, Rote-Augen-Reduzierung', + 'Auto, Fired, Red-eye reduction, Return detected' => 'Blitz wurde ausgelöst, Automodus, Messblitz-Licht zurückgeworfen, Rote-Augen-Reduzierung', + 'Auto, Fired, Red-eye reduction, Return not detected' => 'Blitz wurde ausgelöst, Automodus, kein Messblitz-Licht zurückgeworfen, Rote-Augen-Reduzierung', + 'Auto, Fired, Return detected' => 'Blitz wurde ausgelöst, Automodus, Messblitz-Licht zurückgeworfen', + 'Auto, Fired, Return not detected' => 'Blitz wurde ausgelöst, Automodus, kein Messblitz-Licht zurückgeworfen', + 'Did not fire' => 'Blitz wurde nicht ausgelöst', + 'Fired' => 'Blitz wurde ausgelöst', + 'Fired, Red-eye reduction' => 'Blitz wurde ausgelöst, Rote-Augen-Reduzierung', + 'Fired, Red-eye reduction, Return detected' => 'Blitz wurde ausgelöst, Rote-Augen-Reduzierung, Messblitz-Licht zurückgeworfen', + 'Fired, Red-eye reduction, Return not detected' => 'Blitz wurde ausgelöst, Rote-Augen-Reduzierung, kein Messblitz-Licht zurückgeworfen', + 'Fired, Return detected' => 'Messblitz-Licht zurückgeworfen', + 'Fired, Return not detected' => 'Kein Messblitz-Licht zurückgeworfen', + 'No Flash' => 'Blitz wurde nicht ausgelöst', + 'No flash function' => 'Keine Blitzfunktion', + 'Off' => 'Aus', + 'Off, Did not fire' => 'Blitz wurde nicht ausgelöst, Blitz unterdrücken-Modus', + 'Off, Did not fire, Return not detected' => 'Deaktiviert, Blitz wurde nicht ausgelöst, kein Messblitz-Licht zurückgeworfen', + 'Off, No flash function' => 'Deaktiviert, Keine Blitzfunktion', + 'Off, Red-eye reduction' => 'Deaktiviert, Rote-Augen-Reduzierung', + 'On' => 'Ein', + 'On, Did not fire' => 'Ein, Blitz wurde nicht ausgelöst', + 'On, Fired' => 'Blitz wurde ausgelöst, Blitz erzwingen-Modus', + 'On, Red-eye reduction' => 'Blitz wurde ausgelöst, Blitz erzwingen-Modus, Rote-Augen-Reduzierung', + 'On, Red-eye reduction, Return detected' => 'Blitz wurde ausgelöst, Blitz erzwingen-Modus, Rote-Augen-Reduzierung, Messblitz-Licht zurückgeworfen', + 'On, Red-eye reduction, Return not detected' => 'Blitz wurde ausgelöst, Blitz erzwingen-Modus, Rote-Augen-Reduzierung, kein Messblitz-Licht zurückgeworfen', + 'On, Return detected' => 'Blitz wurde ausgelöst, Blitz erzwingen-Modus, Messblitz-Licht zurückgeworfen', + 'On, Return not detected' => 'Blitz wurde ausgelöst, Blitz erzwingen-Modus, kein Messblitz-Licht zurückgeworfen', + }, + }, + 'FlashAction2' => { + PrintConv => { + 'Did not fire' => 'Blitz wurde nicht ausgelöst', + 'Fired' => 'Blitz wurde ausgelöst', + }, + }, + 'FlashActivity' => 'Blitz-Leistung', + 'FlashBatteryLevel' => 'Blitz Batteriestatus', + 'FlashBias' => 'Blitzkorrektur', + 'FlashBits' => { + Description => 'Blitz-Details', + PrintConv => { + '2nd-curtain sync used' => 'Synchronisatiopn auf 2. Verschlußvorhang', + 'Built-in' => 'Integrierter Blitz', + 'External' => 'Extern', + 'FP sync enabled' => 'FP Synchronisation eingestellt', + 'FP sync used' => 'FP Synchronistaion', + 'Manual' => 'Manuell', + }, + }, + 'FlashColorFilter' => 'Blitz Farbfilter', + 'FlashCommanderMode' => { + Description => 'Master-Steuerung', + PrintConv => { + 'Off' => 'Aus', + 'On' => 'Ein', + }, + }, + 'FlashCompensation' => 'Blitzbelichtungs-Korrektur', + 'FlashControlBuilt-in' => { + PrintConv => { + 'Commander Mode' => 'Master-Steuerung', + }, + }, + 'FlashControlMode' => { + Description => 'Blitzlichtsteuerungsmodus', + PrintConv => { + 'Auto Aperture' => 'Blendenautomatik (AA)', + 'Manual' => 'Manuell', + 'Off' => 'Aus', + 'Repeating Flash' => 'Stroboskopblitz', + }, + }, + 'FlashCurtain' => { + Description => 'Blitzsynchronisation auf Verschluß', + PrintConv => { + '1st' => '1. Vorhang', + '2nd' => '2. Vorhang', + }, + }, + 'FlashDefault' => { + Description => 'Systemblitz', + PrintConv => { + 'Fill Flash' => 'Aufhellblitz', + }, + }, + 'FlashDevice' => { + Description => 'Blitzgerät', + PrintConv => { + 'External' => 'Extern', + 'Internal' => 'Intern', + 'Internal + External' => 'Intern + Extern', + 'None' => 'Keines', + }, + }, + 'FlashDistance' => 'Blitzabstand', + 'FlashEnergy' => 'Blitzstärke', + 'FlashExposureBracketValue' => 'Blitzbelichtungsreihenwert', + 'FlashExposureComp' => 'Blitzbelichtungskorrektur', + 'FlashExposureComp2' => 'Blitzbelichtungskorrektur 2', + 'FlashExposureComp3' => 'Blitzbelichtungskorrektur 3', + 'FlashExposureComp4' => 'Blitzbelichtungskorrektur 4', + 'FlashExposureCompSet' => 'Eingestellte Blitz-Belichtungskorrektur', + 'FlashExposureCompSet2' => 'Blitzbelichtungskorrektur 2', + 'FlashExposureIndicator' => { + Description => 'Blitz-Belichtungsindikator', + PrintConv => { + 'Bottom of Scale' => 'Unterer Wert', + 'Not Indicated' => 'Nicht angezeigt', + 'Over Scale' => 'Wert zu hoch', + 'Top of Scale' => 'Oberer Wert', + 'Under Scale' => 'Wert zu niedrig', + }, + }, + 'FlashExposureIndicatorLast' => { + Description => 'Blitz-Ende-Belichtungsindikator', + PrintConv => { + 'Bottom of Scale' => 'Unterer Wert', + 'Not Indicated' => 'Nicht angezeigt', + 'Over Scale' => 'Wert zu hoch', + 'Top of Scale' => 'Oberer Wert', + 'Under Scale' => 'Wert zu niedrig', + }, + }, + 'FlashExposureIndicatorNext' => { + Description => 'Blitz-Folge-Belichtungsindikator', + PrintConv => { + 'Bottom of Scale' => 'Unterer Wert', + 'Not Indicated' => 'Nicht angezeigt', + 'Over Scale' => 'Wert zu hoch', + 'Top of Scale' => 'Oberer Wert', + 'Under Scale' => 'Wert zu niedrig', + }, + }, + 'FlashExposureLock' => { + Description => 'Blitzbelichtung-Speicherung', + PrintConv => { + 'Off' => 'Aus', + 'On' => 'Ein', + }, + }, + 'FlashFired' => { + Description => 'Blitz wurde ausgelöst', + PrintConv => { + 'False' => 'Nein', + 'No' => 'Nein', + 'True' => 'Ja', + 'Yes' => 'Ja', + }, + }, + 'FlashFiring' => { + Description => 'Blitzzündung', + PrintConv => { + 'Does not fire' => 'Unterdrückt', + 'Fires' => 'Aktiv', + }, + }, + 'FlashFirmwareVersion' => 'Blitz-Firmware-Version', + 'FlashFocalLength' => 'Blitz-Brennweite', + 'FlashFunction' => { + Description => 'Blitzfunktion', + PrintConv => { + 'Built-in flash' => 'Integrierter Blitz', + 'False' => 'Nein', + 'Manual' => 'Manuell', + 'No flash' => 'Kein Blitz', + 'Strobe' => 'Stroboskop', + 'True' => 'Ja', + }, + }, + 'FlashGNDistance' => { + Description => 'Blitzleitzahl Entfernung', + PrintConv => { + 'n/a' => '(nicht gesetzt)', + }, + }, + 'FlashGroupACompensation' => 'Gruppe A, Blitzbelichtungs-Korrektur', + 'FlashGroupAControlMode' => { + Description => 'Gruppe A, Blitzlichtsteuerungsmodus', + PrintConv => { + 'Auto Aperture' => 'Blendenautomatik (AA)', + 'Manual' => 'Manuell', + 'Off' => 'Aus', + 'Repeating Flash' => 'Stroboskopblitz', + }, + }, + 'FlashGroupAOutput' => 'Gruppe A, Blitz-Leistung', + 'FlashGroupBCompensation' => 'Gruppe B, Blitzbelichtungs-Korrektur', + 'FlashGroupBControlMode' => { + Description => 'Gruppe B, Blitzlichtsteuerungsmodus', + PrintConv => { + 'Auto Aperture' => 'Blendenautomatik (AA)', + 'Automatic' => 'Automatik', + 'Manual' => 'Manuell', + 'Off' => 'Aus', + 'Repeating Flash' => 'Stroboskopblitz', + }, + }, + 'FlashGroupBOutput' => 'Gruppe B, Blitz-Leistung', + 'FlashGroupCCompensation' => 'Gruppe C, Blitzbelichtungs-Korrektur', + 'FlashGroupCControlMode' => { + Description => 'Gruppe C, Blitzlichtsteuerungsmodus', + PrintConv => { + 'Auto Aperture' => 'Blendenautomatik (AA)', + 'Manual' => 'Manuell', + 'Off' => 'Aus', + 'Repeating Flash' => 'Stroboskopblitz', + }, + }, + 'FlashGroupCOutput' => 'Gruppe C, Blitz-Leistung', + 'FlashGuideNumber' => 'Blitzleitzahl', + 'FlashInfo' => 'Blitz-Informationen', + 'FlashInfoVersion' => 'Blitz-Informationen-Version', + 'FlashIntensity' => { + Description => 'Blitz Stärke', + PrintConv => { + 'High' => 'Hoch', + 'Strong' => 'Stark', + }, + }, + 'FlashLevel' => { + Description => 'Blitzbelichtungskorr.', + PrintConv => { + 'High' => 'Hoch', + 'n/a' => '(nicht gesetzt)', + }, + }, + 'FlashMake' => 'Blitzgerätehersteller', + 'FlashMetering' => { + Description => 'Blitz-Messung', + PrintConv => { + 'Manual flash control' => 'Manuelle Blitz-Kontrolle', + 'Pre-flash TTL' => 'Vorblitz TTL', + }, + }, + 'FlashMeteringMode' => { + Description => 'Blitz-Belichtungsmessmethode', + PrintConv => { + 'External Auto' => 'Extern Automatisch', + 'External Manual' => 'Extern Manuell', + 'Off' => 'Aus', + }, + }, + 'FlashMeteringSegments' => 'Blitz-Messfelder', + 'FlashMode' => { + Description => 'Blitz-Modus', + PrintConv => { + '2nd Curtain' => 'Auf 2. Verschlußvorhang', + 'Auto' => 'Automatisch', + 'Auto, Did not fire' => 'Auto, nicht ausgelöst', + 'Auto, Did not fire, Red-eye reduction' => 'Auto, nicht ausgelöst, Rote-Augen-Reduzierung', + 'Auto, Fired' => 'Auto, ausgelöst', + 'Auto, Fired, Red-eye reduction' => 'Auto, ausgelöst, Rote-Augen-Reduzierung', + 'Did Not Fire' => 'Nicht ausgelöst', + 'Disabled' => 'Deaktiviert', + 'External, Auto' => 'Extern, Auto', + 'External, Contrast-control Sync' => 'Extern, Kontrast-Steuerungs-Synchronisation', + 'External, Flash Problem' => 'Extern, Blitzproblem?', + 'External, High-speed Sync' => 'Extern, High-Speed-Synchronisation', + 'External, Manual' => 'Extern, Manuell', + 'External, P-TTL Auto' => 'Extern, P-TTL-Blitzautomatik', + 'External, Wireless' => 'Extern, Drahtlos', + 'External, Wireless, High-speed Sync' => 'Extern, Drahtlos, High-Speed-Synchronisation', + 'Fill flash' => 'Aufhellblitz', + 'Fill-in' => 'Aufhellen', + 'Fired, Commander Mode' => 'Ausgelöst, Befehlsmodus', + 'Fired, External' => 'Ausgelöst, Extern', + 'Fired, Manual' => 'Ausgelöst, Manuell', + 'Fired, TTL Mode' => 'Ausgelöst, TTL-Modus', + 'Internal' => 'Intern', + 'Not Ready' => 'Nicht bereit', + 'Off' => 'Aus', + 'Off, Did not fire' => 'Aus', + 'Off?' => 'Aus?', + 'On' => 'Ein', + 'On, Did not fire' => 'Ein, nicht ausgelöst', + 'On, Did not fire, Wireless (Master)' => 'Ein, nicht ausgelöst, Drahtlos (Hauptblitz)', + 'On, Fired' => 'Ein', + 'On, Red-eye reduction' => 'Ein, Rote-Augen-Reduzierung', + 'On, Slow-sync' => 'Ein, Langzeit-Synchronisation', + 'On, Slow-sync, Red-eye reduction' => 'Ein, Langzeit-Synchronisation, Rote-Augen-Reduzierung', + 'On, Soft' => 'Ein, Softblitz', + 'On, Trailing-curtain Sync' => 'Ein, 2. Verschlussvorhang', + 'On, Wireless (Control)' => 'Ein, Drahtlos (Steuerblitz)', + 'On, Wireless (Master)' => 'Ein, Drahtlos (Hauptblitz)', + 'Rear flash sync' => 'Synchronisation auf den zweiten Verschlussvorhang', + 'Red eye' => 'Rote-Augen-Reduzierung', + 'Red-eye' => 'Rote Augen', + 'Red-eye Reduction' => 'Rote-Augen-Reduzierung', + 'Red-eye reduction' => 'Rote-Augen-Reduzierung', + 'Unknown' => 'Unbekannt', + 'Wireless' => 'Drahtlos', + 'n/a - Off-Auto-Aperture' => 'K/A - Blendenring nicht auf A', + }, + }, + 'FlashModel' => { + Description => 'Blitz-Modell', + PrintConv => { + 'None' => 'Keines', + }, + }, + 'FlashOptions' => { + Description => 'Blitz-Optionen', + PrintConv => { + 'Auto' => 'Automatisch', + 'Auto, Red-eye reduction' => 'Auto, Rote-Augen-Reduzierung', + 'Red-eye reduction' => 'Rote-Augen-Reduzierung', + 'Slow-sync' => 'Langzeit-Synchronisation', + 'Slow-sync, Red-eye reduction' => 'Langzeit-Synchronisation, Rote-Augen-Reduzierung', + 'Trailing-curtain Sync' => '2. Verschlussvorhang', + 'Wireless (Control)' => 'Drahtlos (Steuerblitz)', + 'Wireless (Master)' => 'Drahtlos (Hauptblitz)', + }, + }, + 'FlashOptions2' => { + Description => 'Blitz-Optionen (2)', + PrintConv => { + 'Auto' => 'Automatisch', + 'Auto, Red-eye reduction' => 'Auto, Rote-Augen-Reduzierung', + 'Red-eye reduction' => 'Rote-Augen-Reduzierung', + 'Slow-sync' => 'Langzeit-Synchronisation', + 'Slow-sync, Red-eye reduction' => 'Langzeit-Synchronisation, Rote-Augen-Reduzierung', + 'Trailing-curtain Sync' => '2. Verschlussvorhang', + 'Wireless (Control)' => 'Drahtlos (Steuerblitz)', + 'Wireless (Master)' => 'Drahtlos (Hauptblitz)', + }, + }, + 'FlashOutput' => 'Blitzstärke', + 'FlashRedEyeMode' => { + Description => 'Blitz Rote-Augen-Modus', + PrintConv => { + 'False' => 'Nein', + 'True' => 'Ja', + }, + }, + 'FlashRemoteControl' => { + Description => 'Blitz Fernauslöser', + PrintConv => { + 'Off' => 'Aus', + }, + }, + 'FlashReturn' => { + Description => 'Blitz Reflexion', + PrintConv => { + 'No return detection' => 'Keine Erkennung', + 'Return detected' => 'Reflexion erkannt', + 'Return not detected' => 'Reflexion nicht erkannt', + 'Subject Inside Flash Range' => 'Objekt innerhalb der Blitzreichweite', + 'Subject Outside Flash Range' => 'Objekt ausserhalb der Blitzreichweite', + }, + }, + 'FlashSerialNumber' => 'Blitz-Seriennummer', + 'FlashSetting' => 'Blitzeinstellung', + 'FlashShutterSpeed' => 'Längste Verschlussz. (Blitz)', + 'FlashStatus' => { + Description => 'Slave-Blitz-Messfeld 1', + PrintConv => { + 'Built-in Flash present' => 'Integrierter Blitz vorhanden', + 'Built-in Flash present and fired' => 'Integrierter Blitz vorhanden und ausgelöst', + 'External Flash present' => 'Externer Blitz vorhanden', + 'External Flash present and fired' => 'Externer Blitz vorhanden und ausgelöst', + 'External, Did not fire' => 'Extern, nicht ausgelöst', + 'External, Fired' => 'Extern, ausgelöst', + 'Internal, Did not fire' => 'Intern, nicht ausgelöst', + 'Internal, Did not fire (0x08)' => 'Intern, nicht ausgelöst', + 'Internal, Fired' => 'Intern, ausgelöst', + 'No Flash present' => 'Kein Blitz vorhanden', + 'Off' => 'Aus', + 'Off (1)' => 'Aus (1)', + }, + }, + 'FlashSyncMode' => 'Blitz-Synchronisationsmodus', + 'FlashSyncSpeed' => 'Blitzsynchronzeit', + 'FlashSyncSpeedAv' => { + Description => 'Blitzsynchronzeit bei Av', + PrintConv => { + '1/200 Fixed' => '1/200 Fest', + '1/200-1/60 Auto' => '1/200-1/60 automatisch', + '1/250 Fixed' => '1/250 Fest', + '1/250-1/60 Auto' => '1/200-1/60 automatisch', + '1/300 Fixed' => '1/300 Fest', + 'Auto' => 'Automatisch', + }, + }, + 'FlashTTLMode' => 'Blitz TTL-Modus', + 'FlashType' => { + Description => 'Blitztyp', + PrintConv => { + 'Built-In Flash' => 'Intern', + 'External' => 'Extern', + 'None' => 'Keiner', + }, + }, + 'FlashWarning' => { + Description => 'Blitzsymbol', + PrintConv => { + 'Off' => 'Aus', + 'On' => 'Ein', + }, + }, + 'FlashpixVersion' => 'Unterstützte Flashpix-Version', + 'FlickerReduce' => { + PrintConv => { + 'Off' => 'Aus', + 'On' => 'Ein', + }, + }, + 'FlipHorizontal' => { + PrintConv => { + 'No' => 'Nein', + 'Yes' => 'Ja', + }, + }, + 'FocalLength' => 'Brennweite', + 'FocalLength35efl' => 'Brennweite', + 'FocalLengthIn35mmFormat' => 'Brennweite in 35 mm-Kleinbildformat', + 'FocalPlaneDiagonal' => 'Diagonale des Sensors', + 'FocalPlaneResolutionUnit' => { + Description => 'Einheit der Sensorauflösung', + PrintConv => { + 'None' => 'Keine', + 'inches' => 'Zoll', + 'um' => 'µm (Mikrometer)', + }, + }, + 'FocalPlaneXResolution' => 'Sensorauflösung horizontal', + 'FocalPlaneXSize' => 'Sensorgröße horizontal', + 'FocalPlaneXUnknown' => 'Sensorgröße horizontal unbekannt', + 'FocalPlaneYResolution' => 'Sensorauflösung vertikal', + 'FocalPlaneYSize' => 'Sensorgröße vertikal', + 'FocalPlaneYUnknown' => 'Sensorgröße vertikal unbekannt', + 'FocalType' => { + Description => 'Objektivart', + PrintConv => { + 'Fixed' => 'Festbrennweite', + 'Zoom' => 'Zoom-Objektiv', + }, + }, + 'FocalUnits' => 'Fokussiereinheit', + 'Focus' => { + Description => 'Schärfepriorität', + PrintConv => { + 'Auto-focus Didn\'t Lock' => 'Autofokus nicht gesperrt', + 'Auto-focus Locked' => 'Autofokus gesperrt', + 'Manual' => 'Manuell', + }, + }, + 'FocusArea' => { + Description => 'Fokus-Bereich', + PrintConv => { + 'Spot Focus' => 'Spot-AF-Messfeld', + 'Wide Focus (normal)' => 'Großes AF-Messfeld (normal)', + }, + }, + 'FocusAreaSelection' => { + Description => 'Scrollen bei Messfeldauswahl', + PrintConv => { + 'No Wrap' => 'Am Rand stoppen', + 'Wrap' => 'Umlaufend', + }, + }, + 'FocusContinuous' => { + Description => 'Fortlaufende Fokussierung', + PrintConv => { + 'Continuous' => 'Serienaufnahme', + 'Manual' => 'Manuell', + }, + }, + 'FocusDisplayAIServoAndMF' => { + PrintConv => { + 'Disable' => 'Deaktiviert', + 'Enable' => 'Aktiviert', + }, + }, + 'FocusDistance' => 'Fokus-Distanz', + 'FocusDistanceLower' => 'Nahe Fokus-Distanz', + 'FocusDistanceUpper' => 'Entfernte Fokus-Distanz', + 'FocusInfoVersion' => 'FokusInfo Version', + 'FocusMode' => { + Description => 'Fokus-Modus', + PrintConv => { + 'AF-C' => 'AF-C (Kontinuierlicher Autofokus)', + 'AF-S' => 'AF-S (Einzelautofokus)', + 'AI Focus AF' => 'AI Fokus AF', + 'Auto' => 'Automatisch', + 'Continuous' => 'Serienaufnahme', + 'Custom' => 'Benutzerdefiniert', + 'Face detect' => 'Gesichtserkennung AF', + 'Infinity' => 'Unendlich', + 'Macro' => 'Makro', + 'Macro (1)' => 'Makro (1)', + 'Macro (2)' => 'Makro (2)', + 'Manual' => 'Manuell', + 'Manual Focus (3)' => 'Manueller Fokus (3)', + 'Manual Focus (6)' => 'Manueller Fokus (6)', + 'Multi AF' => 'Mehrpunkt AF', + 'One-shot AF' => 'One-Shot AF', + 'Pan Focus' => 'Pan-Fokus', + 'Single' => 'Einzelbild', + 'Single AF' => 'Einpunkt AF', + 'Super Macro' => 'Super-Makro', + 'n/a' => '(nicht gesetzt)', + }, + }, + 'FocusMode2' => { + Description => 'Fokus-Modus 2', + PrintConv => { + 'AF-C' => 'AF-C (Kontinuierlicher Autofokus)', + 'AF-S' => 'AF-S (Einzelautofokus)', + 'Manual' => 'Manuell', + }, + }, + 'FocusModeSetting' => { + Description => 'Autofokus', + PrintConv => { + 'AF-A' => 'AF-Automatik', + 'AF-C' => 'AF-C (Kontinuierlicher Autofokus)', + 'AF-S' => 'AF-S (Einzelautofokus)', + 'Manual' => 'Manuell', + }, + }, + 'FocusModeSwitch' => { + Description => 'Fokus-Modus Schalter', + PrintConv => { + 'Manual' => 'Manuell', + }, + }, + 'FocusPixel' => 'Fokus-Pixel', + 'FocusPointWrap' => { + Description => 'Scrollen bei Messfeldauswahl', + PrintConv => { + 'No Wrap' => 'Am Rand stoppen', + 'Wrap' => 'Umlaufend', + }, + }, + 'FocusPos' => 'Fokus-Position', + 'FocusPosition' => 'Fokus-Distanz', + 'FocusProcess' => { + Description => 'Fokussierung', + PrintConv => { + 'AF Not Used' => 'Ohne AF', + 'AF Used' => 'Mit AF', + }, + }, + 'FocusRange' => { + Description => 'Fokus-Bereich', + PrintConv => { + 'Auto' => 'Automatisch', + 'Close' => 'Nah', + 'Far Range' => 'Entfernt', + 'Infinity' => 'Unendlich', + 'Macro' => 'Makro', + 'Manual' => 'Manuell', + 'Middle Range' => 'Mittlerer Bereich', + 'Not Known' => 'Nicht bekannt', + 'Pan Focus' => 'Pan-Fokus', + 'Super Macro' => 'Super-Makro', + 'Very Close' => 'Sehr nah', + }, + }, + 'FocusStepCount' => 'Fokus-Stufenzähler', + 'FocusStepInfinity' => 'Fokus-Stufe Unendlich', + 'FocusStepNear' => 'Fokus-Stufe Nah', + 'FocusTrackingLockOn' => { + Description => 'Schärfenarchiv. mit Lock-On', + PrintConv => { + '1 (Short)' => '5 (Kurz)', + '1 Short' => '1 Kurz', + '5 (Long)' => '5 (Lang)', + '5 Long' => '5 Lang', + 'Long' => 'Lang', + 'Off' => 'Aus', + 'Short' => 'Kurz', + }, + }, + 'FocusWarning' => { + Description => 'Fokus-Warnung', + PrintConv => { + 'Good' => 'OK', + 'Out of focus' => 'Ausserhalb des Fokus', + }, + }, + 'FocusingScreen' => 'Mattscheibe', + 'FolderName' => 'Ordner-Name', + 'FrameHeight' => 'Bereichshöhe', + 'FrameNumber' => 'Bildnummer', + 'FrameRate' => 'Bildwechselfrequenz', + 'FrameSize' => 'Einzelbildgröße', + 'FrameWidth' => 'Bereichsbreite', + 'FreeByteCounts' => 'Anzahl Bytes des leeren Datenbereiches', + 'FreeMemoryCardImages' => 'Platz auf Speicherkarten für', + 'FreeOffsets' => 'Leerdatenposition', + 'FujiFlashMode' => { + Description => 'Blitz-Modus', + PrintConv => { + 'Auto' => 'Automatisch', + 'External' => 'Externer Blitz', + 'Off' => 'Unterdrückter Blitz', + 'On' => 'Erzwungener Blitz', + 'Red-eye reduction' => 'Rote-Augen-Reduzierung', + }, + }, + 'FullImageSize' => 'Volle Bildgröße', + 'FunctionButton' => { + Description => 'Funktionstaste', + PrintConv => { + 'AF-area Mode' => 'Messfeldsteuerung', + 'Auto Bracketing' => 'Belichtungsreihe', + 'Center AF Area' => 'AF-Messfeldgröße', + 'Center-weighted' => 'Mittenbetont', + 'FV Lock' => 'FV-Messwertspeicher', + 'Flash Off' => 'Blitz aus', + 'Framing Grid' => 'Gitterlinien', + 'ISO Display' => 'ISO-Anzeige', + 'Image Quality' => 'Bildqualität', + 'Matrix Metering' => 'Matrixmessung', + 'Spot Metering' => 'Spotmessung', + 'White Balance' => 'Weißabgleich', + }, + }, + 'GEImageSize' => 'GE Bildgröße', + 'GIFVersion' => 'GIF-Version', + 'GPSAltitude' => 'GPS Höhe', + 'GPSAltitudeRef' => { + Description => 'GPS-Höhe Bezug', + PrintConv => { + 'Above Sea Level' => 'Höhe über Normal-Null (Meeresspiegel)', + 'Below Sea Level' => 'Höhe unter Normal-Null (Meeresspiegel)', + }, + }, + 'GPSAreaInformation' => 'Name des GPS-Gebietes', + 'GPSDOP' => 'Messgenauigkeit', + 'GPSDateStamp' => 'GPS Datum', + 'GPSDateTime' => 'GPS Zeitstempel', + 'GPSDestBearing' => 'Motivrichtung', + 'GPSDestBearingRef' => { + Description => 'Referenz für Motivrichtung', + PrintConv => { + 'Magnetic North' => 'Magnetische Ausrichtung', + 'True North' => 'Geographische Ausrichtung', + }, + }, + 'GPSDestDistance' => 'GPS Zielentfernung', + 'GPSDestDistanceRef' => { + Description => 'GPS-Zielentfernung Maßeinheit', + PrintConv => { + 'Kilometers' => 'Kilometer', + 'Miles' => 'Meilen', + 'Nautical Miles' => 'Knoten', + }, + }, + 'GPSDestLatitude' => 'Breite des Zieles', + 'GPSDestLatitudeRef' => { + Description => 'Referenz für die Breite des Zieles', + PrintConv => { + 'North' => 'Nördliche Breite', + 'South' => 'Südliche Breite', + }, + }, + 'GPSDestLongitude' => 'Längengrad des Ziels', + 'GPSDestLongitudeRef' => { + Description => 'Referenz für die Länge des Zieles', + PrintConv => { + 'East' => 'Östliche Länge', + 'West' => 'Westliche Länge', + }, + }, + 'GPSDifferential' => { + Description => 'GPS Differentialkorrektur', + PrintConv => { + 'Differential Corrected' => 'Differentialkorrektur angewandt', + 'No Correction' => 'Messung ohne Differentialkorrektur', + }, + }, + 'GPSImgDirection' => 'Bildrichtung', + 'GPSImgDirectionRef' => { + Description => 'Referenz für die Ausrichtung des Bildes', + PrintConv => { + 'Magnetic North' => 'Magnetische Ausrichtung', + 'True North' => 'Geographische Ausrichtung', + }, + }, + 'GPSInfo' => 'GPS Info IFD-Zeiger', + 'GPSLatitude' => 'Geografische Breite', + 'GPSLatitudeRef' => { + Description => 'Nördl. oder südl. Breite', + PrintConv => { + 'North' => 'Nördliche Breite', + 'South' => 'Südliche Breite', + }, + }, + 'GPSLongitude' => 'Geografische Länge', + 'GPSLongitudeRef' => { + Description => 'östl. oder westl. Länge', + PrintConv => { + 'East' => 'Östliche Länge', + 'West' => 'Westliche Länge', + }, + }, + 'GPSMapDatum' => 'Geodätisches Datum', + 'GPSMeasureMode' => { + Description => 'GPS Messverfahren', + PrintConv => { + '2-D' => '2-Dimensionale Messung', + '2-Dimensional' => '2-Dimensionale Messung', + '2-Dimensional Measurement' => '2-Dimensionale Messung', + '3-D' => '3-Dimensionale Messung', + '3-Dimensional' => '3-Dimensionale Messung', + '3-Dimensional Measurement' => '3-Dimensionale Messung', + }, + }, + 'GPSProcessingMethod' => 'Name der GPS-Verarbeitungsmethode', + 'GPSSatellites' => 'Für die Messung verwendete Satelliten', + 'GPSSpeed' => 'Geschwindigkeit des GPS-Empfängers', + 'GPSSpeedRef' => { + Description => 'Geschwindigkeitseinheit', + PrintConv => { + 'km/h' => 'Kilometer pro Stunde', + 'knots' => 'Knoten', + 'mph' => 'Meilen pro Stunde', + }, + }, + 'GPSStatus' => { + Description => 'GPS-Empfänger Status', + PrintConv => { + 'Measurement Active' => 'Messung aktiv', + 'Measurement Void' => 'Messung ungültig', + }, + }, + 'GPSTimeStamp' => 'GPS-Zeit UTC', + 'GPSTrack' => 'Bewegungsrichtung', + 'GPSTrackRef' => { + Description => 'Referenz für Bewegungsrichtung', + PrintConv => { + 'Magnetic North' => 'Magnetische Ausrichtung', + 'True North' => 'Geographische Ausrichtung', + }, + }, + 'GPSVersionID' => 'GPS-Tag-Version', + 'GainControl' => { + Description => 'Belichtungsverstärkung', + PrintConv => { + 'High gain down' => 'Hohe Helligkeitsminderung', + 'High gain up' => 'Hohe Helligkeitsverstärkung', + 'Low gain down' => 'Geringe Helligkeitsminderung', + 'Low gain up' => 'Geringe Helligkeitsverstärkung', + 'None' => 'Keine', + }, + }, + 'Gapless' => { + PrintConv => { + 'No' => 'Nein', + 'Yes' => 'Ja', + }, + }, + 'Gradation' => { + PrintConv => { + 'Auto-Override' => 'Automatisch', + 'High Key' => 'High-Key', + 'Low Key' => 'Low-Key', + 'User-Selected' => 'Benutzerauswahl', + 'n/a' => '(nicht gesetzt)', + }, + }, + 'GrayResponseUnit' => { + PrintConv => { + '0.0001' => 'Nummer stellt ein 1000tel einer Einheit dar', + '0.001' => 'Nummer stellt ein 100tel einer Einheit dar', + '0.1' => 'Nummer stellt ein 10tel einer Einheit dar', + '1e-05' => 'Nummer stellt ein 10000tel einer Einheit dar', + '1e-06' => 'Nummer stellt ein 100000tel einer Einheit dar', + }, + }, + 'GrayTRC' => 'Grau-Tonwertwiedergabe-Kurve', + 'GreenAdjust' => 'Grün-Korrektur', + 'GreenMatrixColumn' => 'Grün-Matrixspalte', + 'GreenTRC' => 'Grün-Tonwertwiedergabe-Kurve', + 'GreenX' => 'Grünpunkt X', + 'GreenY' => 'Grünpunkt Y', + 'GridDisplay' => { + Description => 'Gitterlinien', + PrintConv => { + 'Off' => 'Aus', + 'On' => 'Ein', + }, + }, + 'GripBatteryADLoad' => 'Griffbatterie A/D unter Last', + 'GripBatteryADNoLoad' => 'Griffbatterie A/D im Leerlauf', + 'GripBatteryState' => { + Description => 'Griffbatterie-Status', + PrintConv => { + 'Almost Empty' => 'Fast leer', + 'Empty or Missing' => 'Leer oder nicht vorhanden', + 'Full' => 'Voll geladen', + 'Running Low' => 'Schwach', + }, + }, + 'Grouping' => 'Gruppierung', + 'HDR' => { + Description => 'Auto HDR', + PrintConv => { + 'Off' => 'Aus', + }, + }, + 'HDRImageType' => { + Description => 'HDR Bildtyp', + PrintConv => { + 'HDR Image' => 'HDR Bild', + 'Original Image' => 'Originalbild', + }, + }, + 'Headline' => 'Überschrift', + 'HeightResolution' => 'Vertikale Bildauflösung', + 'HierarchicalSubject' => 'Hierarchische Schlüsselwörter', + 'HighISONoiseReduction' => { + Description => 'Rauschunterdrückung bei hoher Empfindlichkeit', + PrintConv => { + '+1 (medium strong)' => '+1', + '+2 (strong)' => '+2 (Stark)', + '+3 (very strong)' => '+3', + '+4 (strongest)' => '+4', + '-1 (medium weak)' => '-1', + '-2 (weak)' => '-2 (Gering)', + '-3 (very weak)' => '-3', + '-4 (weakest)' => '-4 (Sehr gering)', + '0 (normal)' => '0 (Normal)', + 'Auto' => 'Automatisch', + 'High' => 'Stärker', + 'Low' => 'Schwächer', + 'Off' => 'Aus', + 'On' => 'Ein', + 'Strong' => 'Stark', + 'Weak' => 'Gering', + 'Weakest' => 'Sehr gering', + 'n/a' => '(nicht gesetzt)', + }, + }, + 'HighISONoiseReduction2' => { + Description => 'Rauschunterdrückung bei hoher Empfindlichkeit', + PrintConv => { + 'High' => 'Hoch', + 'Low' => 'Niedrig', + 'Off' => 'Aus', + 'n/a' => '(nicht gesetzt)', + }, + }, + 'HighLowKeyAdj' => 'High-/Low-Key Abstimmung', + 'Highlight' => 'Helle Stellen', + 'HighlightTonePriority' => { + Description => 'Tonwert Priorität', + PrintConv => { + 'Disable' => 'Nicht möglich', + 'Enable' => 'Möglich', + 'Off' => 'Aus', + 'On' => 'Ein', + }, + }, + 'HometownCity' => 'Heimatort', + 'HometownCityCode' => 'Heimatort-Code', + 'HometownDST' => { + Description => 'Heimatort Sommerzeit (DST)', + PrintConv => { + 'No' => 'Deaktiviert', + 'Yes' => 'Aktiviert', + }, + }, + 'Hue' => 'Farbton', + 'HueAdj' => 'Farbtonkorrektur', + 'HueAdjust' => { + Description => 'Farbtonkorrektur', + PrintConv => { + 'Cool' => 'Kühl', + 'Off' => 'Aus', + 'Yellow' => 'Gelb', + }, + }, + 'HueAdjustment' => 'Farbtonkorrektur', + 'HueSetting' => 'Farbtoneinstellung', + 'HuffmanTable' => 'Huffman Tabelle', + 'HyperfocalDistance' => 'Hyperfokale Entfernung', + 'ICCProfile' => 'ICC-Profil', + 'ICCProfileName' => 'ICC-Profil Name', + 'ICC_Profile' => 'ICC-Profil', + 'ID3Size' => 'ID3 Datenlänge', + 'IDCCreativeStyle' => { + PrintConv => { + 'Autumn Leaves' => 'Herbstlaub', + 'B&W' => 'Schwarz/Weiß', + 'Landscape' => 'Landschaft', + 'Night View' => 'Abendszene', + 'Portrait' => 'Porträt', + 'Sunset' => 'Sonnenuntergang', + }, + }, + 'IDCPreviewImage' => 'IDC Vorschaubild', + 'IDCPreviewLength' => 'IDC Vorschaubild-Datenlänge', + 'IDCPreviewStart' => 'IDC Vorschaubild-Datenposition', + 'IPTC-NAA' => 'IPTC-NAA Metadaten', + 'IPTCDigest' => 'IPTC Kennwert', + 'IPTCImageHeight' => 'IPTC-Bildhöhe', + 'IPTCImageRotation' => { + Description => 'IPTC Bildausrichtung', + PrintConv => { + '0' => 'Normal', + '180' => '180° gedreht', + '270' => '90° gegen den Uhrzeigersinn', + '90' => '90° im Uhrzeigersinn', + }, + }, + 'IPTCImageWidth' => 'IPTC-Bildbreite', + 'IPTCPictureNumber' => 'IPTC Bildnummer', + 'IPTCPixelHeight' => 'IPTC-Pixelhöhe', + 'IPTCPixelWidth' => 'IPTC-Pixelbreite', + 'ISO' => 'ISO-Empfindlichkeit', + 'ISO2' => 'ISO-Empfindlichkeit (2)', + 'ISOAuto' => 'ISO-Automatik', + 'ISODisplay' => 'ISO-Anzeige', + 'ISOExpansion' => { + Description => 'ISO-Erweiterung', + PrintConv => { + 'Off' => 'Aus', + 'On' => 'Ein', + }, + }, + 'ISOExpansion2' => { + Description => 'ISO-Erweiterung (2)', + PrintConv => { + 'Off' => 'Aus', + }, + }, + 'ISOFloor' => 'ISO-Untergrenze', + 'ISOInfo' => 'ISO-Informationen', + 'ISOSelection' => 'ISO-Auswahl', + 'ISOSetting' => { + Description => 'ISO-Einstellung', + PrintConv => { + '200 (Zone Matching High)' => '200 (Zonenabgleich High)', + '80 (Zone Matching Low)' => '80 (Zonenabgleich Low)', + 'Auto' => 'Automatisch', + 'Manual' => 'Manuell', + 'n/a' => '(nicht gesetzt)', + }, + }, + 'ISOSpeedExpansion' => { + Description => 'ISO-Erweiterung', + PrintConv => { + 'No' => 'Nein', + 'Yes' => 'Ja', + }, + }, + 'ISOSpeedIncrements' => { + Description => 'ISO-Schrittweite', + PrintConv => { + '1 Stop' => '1 LW', + '1/3 Stop' => '1/3 LW', + }, + }, + 'ISOSpeedRange' => { + Description => 'Einstellung ISO-Bereich', + PrintConv => { + 'Disable' => 'Nicht möglich', + 'Enable' => 'Möglich', + }, + }, + 'ISOStepSize' => { + Description => 'ISO-Schrittweite', + PrintConv => { + '1 EV' => '1 LW', + '1/2 EV' => '1/2 LW', + '1/3 EV' => '1/3 LW', + }, + }, + 'ISRCNumber' => 'ISRC Nummer', + 'Illumination' => { + Description => 'Displaybeleuchtung', + PrintConv => { + 'Off' => 'Aus', + 'On' => 'Ein', + }, + }, + 'Image::ExifTool::APP12::PictureInfo' => 'APP12 Bildinformation', + 'Image::ExifTool::Canon::AFMicroAdj' => 'Canon AF Feinabstimmung', + 'Image::ExifTool::Canon::CameraInfo1000D' => 'Canon KameraInfo 1000D', + 'Image::ExifTool::Canon::CameraInfo1D' => 'Canon KameraInfo 1D', + 'Image::ExifTool::Canon::CameraInfo1DX' => 'Canon KameraInfo 1DX', + 'Image::ExifTool::Canon::CameraInfo1DmkII' => 'Canon KameraInfo 1DmkII', + 'Image::ExifTool::Canon::CameraInfo1DmkIII' => 'Canon KameraInfo 1DmkIII', + 'Image::ExifTool::Canon::CameraInfo1DmkIIN' => 'Canon KameraInfo 1DmkIIN', + 'Image::ExifTool::Canon::CameraInfo1DmkIV' => 'Canon KameraInfo 1DmkIV', + 'Image::ExifTool::Canon::CameraInfo40D' => 'Canon KameraInfo 40D', + 'Image::ExifTool::Canon::CameraInfo450D' => 'Canon KameraInfo 450D', + 'Image::ExifTool::Canon::CameraInfo500D' => 'Canon KameraInfo 500D', + 'Image::ExifTool::Canon::CameraInfo50D' => 'Canon KameraInfo 50D', + 'Image::ExifTool::Canon::CameraInfo550D' => 'Canon KameraInfo 550D', + 'Image::ExifTool::Canon::CameraInfo5D' => 'Canon KameraInfo 5D', + 'Image::ExifTool::Canon::CameraInfo5DmkII' => 'Canon KameraInfo 5DmkII', + 'Image::ExifTool::Canon::CameraInfo5DmkIII' => 'Canon KameraInfo 5DmkIII', + 'Image::ExifTool::Canon::CameraInfo600D' => 'Canon KameraInfo 600D', + 'Image::ExifTool::Canon::CameraInfo60D' => 'Canon KameraInfo 60D', + 'Image::ExifTool::Canon::CameraInfo650D' => 'Canon KameraInfo 650D', + 'Image::ExifTool::Canon::CameraInfo7D' => 'Canon KameraInfo 7D', + 'Image::ExifTool::Canon::CameraInfoPowerShot' => 'Canon KameraInfo PowerShot', + 'Image::ExifTool::Canon::CameraInfoPowerShot2' => 'Canon KameraInfo PowerShot2', + 'Image::ExifTool::Canon::CameraInfoUnknown32' => 'Canon KameraInfo Unbekannt32', + 'Image::ExifTool::Canon::CropInfo' => 'Canon Ausschnitt Info', + 'Image::ExifTool::CanonRaw::ImageFormat' => 'CanonRaw Bildformat', + 'Image::ExifTool::DNG::OriginalRaw' => 'DNG Original RAW', + 'Image::ExifTool::ICC_Profile::Measurement' => 'ICC_Profil Messung', + 'Image::ExifTool::IPTC::ApplicationRecord' => 'IPTC Modell', + 'Image::ExifTool::Jpeg2000::FileType' => 'Jpeg2000 Dateityp', + 'Image::ExifTool::Jpeg2000::ImageHeader' => 'Jpeg2000 Bild-Header', + 'Image::ExifTool::Kodak::CameraInfo' => 'Kodak KameraInfo', + 'Image::ExifTool::MIE::Meta' => 'MIE Metadaten', + 'Image::ExifTool::Minolta::CameraInfoA100' => 'Minolta KameraInfo A100', + 'Image::ExifTool::Olympus::CameraSettings' => 'Olympus Kameraeinstellungen', + 'Image::ExifTool::Olympus::FocusInfo' => 'Olympus FokusInfo', + 'Image::ExifTool::Olympus::ImageProcessing' => 'Olympus Bildverarbeitung', + 'Image::ExifTool::PNG::ImageHeader' => 'PNG Bild-Header', + 'Image::ExifTool::PNG::PhysicalPixel' => 'PNG physikalische Pixel', + 'Image::ExifTool::PNG::PrimaryChromaticities' => 'PNG primäre Chromatizität', + 'Image::ExifTool::PNG::StereoImage' => 'PNG Stereobild', + 'Image::ExifTool::PNG::TextualData' => 'PNG Textdaten', + 'Image::ExifTool::PNG::VirtualPage' => 'PNG virtuelle Seite', + 'Image::ExifTool::PSP::Creator' => 'PSP Ersteller', + 'Image::ExifTool::Pentax::CameraInfo' => 'Pentax KameraInfo', + 'Image::ExifTool::Sony::CameraInfo' => 'Sony KameraInfo', + 'Image::ExifTool::Sony::CameraInfo2' => 'Sony KameraInfo2', + 'ImageAdjustment' => 'Bildanpassung', + 'ImageAreaOffset' => 'Bildbereichsoffset', + 'ImageAuthentication' => { + Description => 'Bild-Authentifikation', + PrintConv => { + 'Off' => 'Aus', + 'On' => 'Ein', + }, + }, + 'ImageBoundary' => 'Bildbegrenzung', + 'ImageByteCount' => 'Anzahl Bytes der Bilddaten', + 'ImageCount' => 'Bildzähler', + 'ImageDataDiscard' => { + Description => 'Verworfene Bilddaten', + PrintConv => { + 'Flexbits Discarded' => 'FlexBits verworfen', + 'Full Resolution' => 'Volle Auflösung', + 'HighPass Frequency Data Discarded' => 'Hochpass-Frequenz-Daten verworfen', + 'Highpass and LowPass Frequency Data Discarded' => 'Hochpass- und Tiefpass-Frequenz-Daten verworfen', + }, + }, + 'ImageDataSize' => 'Bilddatengröße', + 'ImageDescription' => 'Bildbeschreibung', + 'ImageDustOff' => { + PrintConv => { + 'Off' => 'Aus', + 'On' => 'Ein', + }, + }, + 'ImageEditCount' => 'Bildverarbeitungszähler', + 'ImageEditing' => { + Description => 'Bildverarbeitung', + PrintConv => { + 'Cropped' => 'Beschnitten', + 'Digital Filter' => 'Digitalfilter', + 'Frame Synthesis?' => 'Rahmen?', + 'None' => 'Unbearbeitet', + }, + }, + 'ImageEffects' => { + PrintConv => { + 'High Key' => 'High-Key', + }, + }, + 'ImageGeneration' => { + Description => 'Bilderstellung', + PrintConv => { + 'Original Image' => 'Originalbild', + 'Re-developed from RAW' => 'RAW generiert', + }, + }, + 'ImageHeight' => 'Bildhöhe', + 'ImageHistory' => 'Bild-Historie', + 'ImageLength' => 'Bild-Datenlänge', + 'ImageNumber' => 'Bildnummer', + 'ImageNumber2' => 'Bildnummer (2)', + 'ImageOffset' => 'Bilddatenposition', + 'ImageOptimization' => 'Bildoptimierung', + 'ImageOrientation' => { + Description => 'Bildausrichtung', + PrintConv => { + 'Landscape' => 'Querformat', + 'Portrait' => 'Porträt', + 'Square' => 'Quadratisch', + }, + }, + 'ImageProcessing' => 'Bildverarbeitung', + 'ImageProcessingVersion' => 'Bildverarbeitung Version', + 'ImageQuality' => { + Description => 'Bildqualität', + PrintConv => { + 'High' => 'Hoch', + }, + }, + 'ImageQuality2' => 'Bildqualität 2', + 'ImageReview' => { + Description => 'Bildkontrolle', + PrintConv => { + 'Off' => 'Aus', + 'On' => 'Ein', + }, + }, + 'ImageReviewTime' => 'Ausschaltzeit Bildkontrolle', + 'ImageRotated' => { + PrintConv => { + 'No' => 'Nein', + 'Yes' => 'Ja', + }, + }, + 'ImageRotation' => { + Description => 'Bildausrichtung', + PrintConv => { + 'None' => 'Keine', + }, + }, + 'ImageSize' => 'Bildgröße', + 'ImageStabilization' => { + Description => 'Bildstabilisierung', + PrintConv => { + 'Anti-Shake' => 'Verwackeln', + 'Best Shot' => 'Beste Aufnahme', + 'CCD Shift + High Sensitivity' => 'CCD Shift + Hohe Empfindlichkeit', + 'Dynamic' => 'Dynamisch', + 'Dynamic (2)' => 'Dynamisch (2)', + 'High Sensitivity' => 'Hohe Empfindlichkeit', + 'None' => 'Keine', + 'Off' => 'Aus', + 'Off (0xbf)' => 'Aus (0xbf)', + 'Off (1)' => 'Aus (1)', + 'Off (2)' => 'Aus (2)', + 'On' => 'Ein', + 'On (0x3f)' => 'Ein (0x3f)', + 'On (2)' => 'Ein (2)', + 'On (mode 1, continuous)' => 'Ein (Modus 1, nachführend)', + 'On (mode 2, shooting only)' => 'Ein (Modus 2, Aufnahme)', + 'On, Mode 1' => 'Ein, Modus 1', + 'On, Mode 2' => 'Ein, Modus 2', + 'On, Mode 3' => 'Ein, Modus 3', + 'On, Mode 4' => 'Ein, Modus 4', + 'Optical' => 'Optisch', + 'Panning' => 'Schwenken', + 'Panning (2)' => 'Schwenken (2)', + 'Sensor-shift' => 'Sensor-Shift', + 'Shoot Only' => 'Aufnahme', + 'Shoot Only (2)' => 'Aufnahme (2)', + 'Slow Shutter' => 'Kurzer Verschluß', + 'n/a' => '(nicht gesetzt)', + }, + }, + 'ImageStabilizationSetting' => { + PrintConv => { + 'Off' => 'Aus', + 'On' => 'Ein', + }, + }, + 'ImageStyle' => { + PrintConv => { + 'B&W' => 'Schwarz/Weiß', + 'Landscape' => 'Landschaft', + 'Night View/Portrait' => 'Abendszene/Porträt', + 'Portrait' => 'Porträt', + 'Sunset' => 'Sonnenuntergang', + }, + }, + 'ImageTone' => { + Description => 'Farbdynamik', + PrintConv => { + 'Bright' => 'Leuchtend', + 'Landscape' => 'Landschaft', + 'Monochrome' => 'Monochrom', + 'Natural' => 'Natürlich', + 'Portrait' => 'Porträt', + }, + }, + 'ImageType' => { + Description => 'Bildtyp', + PrintConv => { + 'Page' => 'Seite', + 'Preview' => 'Vorschau', + }, + }, + 'ImageUIDList' => 'Bilder UID Liste', + 'ImageUniqueID' => 'Eindeutige Bild-ID', + 'ImageWidth' => 'Bildbreite', + 'InfoButtonWhenShooting' => { + Description => 'INFO-Taste bei Aufnahme', + PrintConv => { + 'Displays camera settings' => 'Anzeige Kameradaten', + 'Displays shooting functions' => 'Anzeige Aufnahmedaten', + }, + }, + 'InitialZoomSetting' => { + Description => 'Erste Vergrößerungsstufe', + PrintConv => { + 'High Magnification' => 'Starke Vergrößerung', + 'Low Magnification' => 'Geringe Vergrößerung', + 'Medium Magnification' => 'Mittlere Vergrößerung', + }, + }, + 'Instructions' => 'Anweisungen', + 'IntellectualGenre' => 'Intellektuelles Genre', + 'IntelligentAuto' => { + PrintConv => { + 'Advanced' => 'Erweitert', + 'Off' => 'Aus', + 'On' => 'Ein', + }, + }, + 'IntelligentContrast' => { + Description => 'Intelligenter Kontrast', + PrintConv => { + 'Off' => 'Aus', + 'On' => 'Ein', + 'n/a' => '(nicht gesetzt)', + }, + }, + 'IntelligentD-Range' => { + Description => 'Intelligenter D-Bereich', + PrintConv => { + 'High' => 'Hoch', + 'Low' => 'Niedrig', + 'Off' => 'Aus', + }, + }, + 'IntelligentExposure' => { + Description => 'Intelligente Belichtung', + PrintConv => { + 'High' => 'Hoch', + 'Low' => 'Niedrig', + 'Off' => 'Aus', + }, + }, + 'IntelligentResolution' => { + Description => 'Intelligente Bildauflösung', + PrintConv => { + 'Extended' => 'Erweitert', + 'High' => 'Hoch', + 'Low' => 'Niedrig', + 'Off' => 'Aus', + }, + }, + 'IntensityStereo' => { + PrintConv => { + 'Off' => 'Aus', + 'On' => 'Ein', + }, + }, + 'InternalFlash' => { + Description => 'Integriertes Blitzgerät', + PrintConv => { + 'Commander Mode' => 'Master-Steuerung', + 'Fired' => 'Blitz wurde ausgelöst', + 'Manual' => 'Manuell', + 'No' => 'Blitz wurde nicht ausgelöst', + 'Off' => 'Aus', + 'On' => 'Ein', + 'Repeating Flash' => 'Stroboskopblitz', + }, + }, + 'InternalFlashAE1' => 'Integriertes Blitzgerät AE1', + 'InternalFlashAE1_0' => 'Integriertes Blitzgerät AE1 0', + 'InternalFlashAE2' => 'Integriertes Blitzgerät AE2', + 'InternalFlashAE2_0' => 'Integriertes Blitzgerät AE2 0', + 'InternalFlashMode' => { + Description => 'Slave-Blitz-Messfeld 2', + PrintConv => { + 'Did not fire, (Unknown 0xf4)' => 'Aus (Unbekannt 0xF4?)', + 'Did not fire, Auto' => 'Aus, Auto', + 'Did not fire, Auto, Red-eye reduction' => 'Aus, Auto, Rote-Augen-Reduzierung', + 'Did not fire, Normal' => 'Aus, Normal', + 'Did not fire, Red-eye reduction' => 'Aus, Rote-Augen-Reduzierung', + 'Did not fire, Slow-sync' => 'Aus, Langzeit-Synchronisation', + 'Did not fire, Slow-sync, Red-eye reduction' => 'Aus, Langzeit-Synchronisation, Rote-Augen-Reduzierung', + 'Did not fire, Trailing-curtain Sync' => 'Aus, 2. Verschlussvorhang', + 'Did not fire, Wireless (Control)' => 'Aus, Drahtlos (Steuerblitz)', + 'Did not fire, Wireless (Master)' => 'Aus, Drahtlos (Hauptblitz)', + 'Fired' => 'Ein', + 'Fired, Auto' => 'Ein, Auto', + 'Fired, Auto, Red-eye reduction' => 'Ein, Auto, Rote-Augen-Reduzierung', + 'Fired, Red-eye reduction' => 'Ein, Rote-Augen-Reduzierung', + 'Fired, Slow-sync' => 'Ein, Langzeit-Synchronisation', + 'Fired, Slow-sync, Red-eye reduction' => 'Ein, Langzeit-Synchronisation, Rote-Augen-Reduzierung', + 'Fired, Trailing-curtain Sync' => 'Ein, 2. Verschlussvorhang', + 'Fired, Wireless (Control)' => 'Ein, Drahtlos (Steuerblitz)', + 'Fired, Wireless (Master)' => 'Ein, Drahtlos (Hauptblitz)', + 'n/a - Off-Auto-Aperture' => 'K/A - Blendenring nicht auf A', + }, + }, + 'InternalFlashStrength' => 'Slave-Blitz-Messfeld 4', + 'InternalName' => 'Interner Name', + 'InternalSerialNumber' => 'Interne Seriennummer', + 'InteropIndex' => { + Description => 'Interoperabilität Identifikation', + PrintConv => { + 'R03 - DCF option file (Adobe RGB)' => 'R03: DCF Option-Format (Adobe RGB)', + 'R98 - DCF basic file (sRGB)' => 'R98: DCF Basic-Format (sRGB)', + 'THM - DCF thumbnail file' => 'THM: DCF Miniaturbild-Format', + }, + }, + 'InteropOffset' => 'Interoperabilitäts-Tag', + 'InteropVersion' => 'Interoperabilitäts-Version', + 'IntervalLength' => 'Intervallänge', + 'IntervalMode' => { + Description => 'Interval-Modus', + PrintConv => { + 'Still Image' => 'Standbild', + 'Time-lapse Movie' => 'Zeitraffer-Film', + }, + }, + 'IntervalNumber' => 'Intervalnummer', + 'IsCustomPictureStyle' => { + Description => 'Bildstil benutzerdefinert', + PrintConv => { + 'No' => 'Nein', + 'Yes' => 'Ja', + }, + }, + 'JFIFVersion' => 'JFIF-Version', + 'JPEGDigest' => 'JPEG Kennwert', + 'JPEGProc' => { + Description => 'JPEG Verfahren', + PrintConv => { + 'Lossless' => 'Verlustfrei', + }, + }, + 'JPEGQuality' => { + Description => 'Bildqualität', + PrintConv => { + 'Extra Fine' => 'Extra-Fein', + 'Fine' => 'Fein', + 'Standard' => 'Standardqualität', + 'n/a' => '(nicht gesetzt)', + }, + }, + 'JPEGSize' => 'JPEG Größe', + 'JPEGTables' => 'JPEG Tabellen', + 'JobID' => 'Job-Kennung', + 'JpgFromRaw' => 'Jpg From Raw Bild', + 'JpgFromRawLength' => 'Jpg From Raw Datenlänge', + 'JpgFromRawStart' => 'Jpg From Raw Datenposition', + 'JpgRecordedPixels' => 'JPEG-Auflösung', + 'Key' => 'Schlüssel', + 'Keyword' => 'Schlüsselwort', + 'Keywords' => 'Schlüsselwörter', + 'KodakImageHeight' => 'Kodak-Bildhöhe', + 'KodakImageWidth' => 'Kodak-Bildbreite', + 'LC1' => 'Objektiv-Wert', + 'LC10' => 'Mv\' nv\'-Daten', + 'LC11' => 'AVC 1/EXP-Wert', + 'LC12' => 'Mv1 Avminsif-Wert', + 'LC14' => 'UNT_12 UNT_6-Wert', + 'LC15' => 'Incorporated Flash Suited END-Wert', + 'LC2' => 'Entfernungscode', + 'LC3' => 'K-Wert (LC3)', + 'LC4' => 'Wert für Aberrationskorrektur im Nahbereich', + 'LC5' => 'Wert für Aberrationskorrektur heller Farben', + 'LC6' => 'Wert für Aberrationskorrektur bei offener Blende', + 'LC7' => 'AF Minimum Actuation Condition-Wert', + 'LCDDisplayAtPowerOn' => { + Description => 'LCD-Display bei Kamera Ein', + PrintConv => { + 'Retain power off status' => 'Aus-Status beibehalten', + }, + }, + 'LCDDisplayReturnToShoot' => { + Description => 'LC-Display->Zurück zur Aufn.', + PrintConv => { + 'Also with * etc.' => 'Auch mit * etc.', + 'With Shutter Button only' => 'Nur mit Auslöser', + }, + }, + 'LCDIllumination' => { + Description => 'Displaybeleuchtung', + PrintConv => { + 'Off' => 'Aus', + 'On' => 'Ein', + }, + }, + 'LCDIlluminationDuringBulb' => { + Description => 'LCD-Beleuchtung bei Langzeitaufnahme', + PrintConv => { + 'Off' => 'Aus', + 'On' => 'Ein', + }, + }, + 'LCDPanels' => 'LCD oben/LCD Rückwand', + 'LCHEditor' => { + PrintConv => { + 'Off' => 'Aus', + 'On' => 'Ein', + }, + }, + 'Label' => 'Beschriftung', + 'Landmark' => 'Sehenswürdigkeit', + 'Language' => 'Sprache', + 'LanguageCode' => { + Description => 'Sprache', + PrintConv => { + 'Process default' => 'Systemeinstellung', + }, + }, + 'LanguageIdentifier' => 'Sprachkennung', + 'LastFileNumber' => 'Letzte Dateinummer', + 'LastKeywordIPTC' => 'Letztes IPTC Schlüsselwort', + 'LastKeywordXMP' => 'Letztes XMP Schlüsselwort', + 'LateralChromaticAberration' => { + Description => 'Laterale Farbabweichung', + PrintConv => { + 'Off' => 'Aus', + 'n/a' => '(nicht gesetzt)', + }, + }, + 'LeafData' => 'Leaf Daten', + 'LegacyIPTCDigest' => 'Bisheriger IPTC Kennwert', + 'Lens' => 'Objektiv', + 'Lens35efl' => 'Objektiv', + 'LensAFStopButton' => { + Description => 'Funktion Objektiv-AF-Stopptaste', + PrintConv => { + 'AE lock' => 'AE-Speicherung', + 'AE lock while metering' => 'AE-Sperre b. aktiv. Messung', + 'AF Stop' => 'AF-Stopp', + 'AF point: M->Auto/Auto->ctr' => 'AF-Messf: M->Aut./Aut.->Ctr', + 'AF start' => 'AF-Start', + 'AF stop' => 'AF-Stopp', + 'IS start' => 'Start Bildstabilisierung', + 'Switch to registered AF point' => 'Auf gesp. AF-Messf. schalten', + }, + }, + 'LensApertureRange' => 'Objektiv Blendenbereich', + 'LensData' => 'K-Wert', + 'LensDataVersion' => 'Objektivdaten-Version', + 'LensDistortionParams' => 'Objektiv Verzeichnungsparameter', + 'LensDriveNoAF' => { + Description => 'Schärfensuche wenn AF unmöglich', + PrintConv => { + 'Focus search off' => 'Schärfensuche aus', + 'Focus search on' => 'Schärfensuche ein', + }, + }, + 'LensFStops' => 'Objektiv-Blendenstufen', + 'LensFirmwareVersion' => 'Objektiv-Firmware-Version', + 'LensID' => 'Objektiv-ID', + 'LensIDNumber' => 'Objektivkennnummer', + 'LensInfo' => 'Objektiv-Informationen', + 'LensKind' => 'Objektivtyp / Version (LC0)', + 'LensMake' => 'Objektivhersteller', + 'LensManufacturer' => 'Objektivhersteller', + 'LensMaxApertureRange' => 'Objektiv Blendenbereich', + 'LensModel' => 'Objektiv-Typ', + 'LensProfileDigest' => 'Kennwert des Objektivprofils', + 'LensProperties' => 'Objektivfunktionen?', + 'LensSerialNumber' => 'Objektiv-Seriennummer', + 'LensSpec' => 'Objektiv', + 'LensType' => { + Description => 'Objektivtyp', + PrintConv => { + 'Uncoded lens' => 'Nicht kodiertes Objektiv', + }, + }, + 'LevelOrientation' => { + Description => 'Level Ausrichtung', + PrintConv => { + 'Downwards' => 'Abwärts', + 'Horizontal; Off Level' => 'Horizontal; ohne Level', + 'Rotate 180' => '180° gedreht', + 'Rotate 180; Off Level' => '180° gedreht; ohne Level', + 'Rotate 270 CW' => '90° gegen den Uhrzeigersinn', + 'Rotate 270 CW; Off Level' => '90° gegen den Uhrzeigersinn; ohne Level', + 'Rotate 90 CW' => '90° im Uhrzeigersinn', + 'Rotate 90 CW; Off Level' => '90° im Uhrzeigersinn; ohne Level', + 'Upwards' => 'Aufwärts', + }, + }, + 'License' => 'Lizenz', + 'LicenseType' => { + Description => 'Lizenztyp', + PrintConv => { + 'Commercial' => 'Kommerziell', + 'Unknown' => 'Unbekannt', + }, + }, + 'LightReading' => 'Helligkeitsauswertung', + 'LightSource' => { + Description => 'Lichtquelle', + PrintConv => { + 'Cloudy' => 'Bewölkt', + 'Cool White Fluorescent' => 'Neonlicht kaltweiß', + 'Day White Fluorescent' => 'Neonlicht neutralweiß', + 'Daylight' => 'Tageslicht', + 'Daylight Fluorescent' => 'Neonlicht tageslichtweiß', + 'Evening Sunlight' => 'Abendstimmung', + 'Fine Weather' => 'Wolkenlos', + 'Flash' => 'Blitz', + 'Fluorescent' => 'Neonlicht', + 'ISO Studio Tungsten' => 'ISO Studio-Kunstlicht (Glühbirne)', + 'One Touch White Balance' => 'Sofort-Weißabgleich', + 'Other' => 'Andere Lichtquelle', + 'Shade' => 'Schatten', + 'Standard Light A' => 'Standard-Licht A', + 'Standard Light B' => 'Standard-Licht B', + 'Standard Light C' => 'Standard-Licht C', + 'Tungsten' => 'Glühbirne', + 'Tungsten (Incandescent)' => 'Kunstlicht (Glühbirne)', + 'Unknown' => 'Unbekannt', + 'Warm White Fluorescent' => 'Neonlicht warmweiß', + 'White Fluorescent' => 'Neonlicht universalweiß', + }, + }, + 'LightSourceSpecial' => { + PrintConv => { + 'Off' => 'Aus', + 'On' => 'Ein', + }, + }, + 'LightValue' => 'Lichtwert(ISO)', + 'Lightness' => 'Graustufung', + 'LinearizationTable' => 'Linearisierungstabelle', + 'Lit' => { + PrintConv => { + 'No' => 'Nein', + 'Yes' => 'Ja', + }, + }, + 'LiveViewAFAreaMode' => { + Description => 'Live-View AF-Modus', + PrintConv => { + 'Face-Priority' => 'Gesichtserkennung', + 'NormalArea' => 'Normaler Bereich', + 'SubjectTracking' => 'Objektnachführung', + 'WideArea' => 'Großer Bereich', + }, + }, + 'LiveViewAFMethod' => { + PrintConv => { + 'n/a' => '(nicht gesetzt)', + }, + }, + 'LiveViewAFMode' => 'Live-View AF-Modus', + 'LiveViewAFSetting' => { + Description => 'Live View AF Einstellung', + PrintConv => { + 'n/a' => '(nicht gesetzt)', + }, + }, + 'LiveViewExposureSimulation' => { + Description => 'Livebild-Belichtungssimulator', + PrintConv => { + 'Disable (LCD auto adjust)' => 'Inaktiv (automatische LCD-Anzeige)', + 'Enable (simulates exposure)' => 'Aktiv (simuliert Belichtung)', + }, + }, + 'LiveViewFocusMode' => { + Description => 'Live-View Fokus-Modus', + PrintConv => { + 'Manual' => 'Manuell', + 'n/a' => '(nicht gesetzt)', + }, + }, + 'LiveViewMetering' => { + PrintConv => { + 'n/a' => '(nicht gesetzt)', + }, + }, + 'LiveViewShooting' => { + Description => 'Live View Aufnahme', + PrintConv => { + 'Off' => 'Aus', + 'On' => 'Ein', + }, + }, + 'LocalizedCameraModel' => 'Lokalisiertes Kameramodell', + 'Location' => 'Aufnahmeort', + 'LockMicrophoneButton' => { + Description => 'Mikrofone-Tastenfunktion', + PrintConv => { + 'Protect (hold:record memo)' => 'Geschützt (drücken:Tonaufnahme)', + 'Record memo (protect:disable)' => 'Tonaufnahme (ungeschützt)', + }, + }, + 'LongExposureNoiseReduction' => { + Description => 'Langzeit-Rauschminderung', + PrintConv => { + 'Auto' => 'Automatisch', + 'Off' => 'Aus', + 'On' => 'Ein', + 'n/a' => '(nicht gesetzt)', + }, + }, + 'LongExposureNoiseReduction2' => { + Description => 'Langzeit Rauschunterdrückung 2', + PrintConv => { + 'Off' => 'Aus', + 'On' => 'Ein', + 'On (1D)' => 'Ein (1D)', + }, + }, + 'Luminance' => 'Luminanz', + 'LuminanceNoiseReduction' => { + PrintConv => { + 'High' => 'Hoch', + 'Low' => 'Leicht', + 'Off' => 'Aus', + }, + }, + 'MB-D10Batteries' => { + Description => 'Akku-/Batterietyp', + PrintConv => { + 'FR6 (AA lithium)' => 'FR6 (Mignon, Lithium)', + 'HR6 (AA Ni-MH)' => 'HR6 (Mignon, NiMH)', + 'LR6 (AA alkaline)' => 'LR6 (Mignon, Alkaline)', + 'ZR6 (AA Ni-Mn)' => 'ZR6 (Mignon, NiMn)', + }, + }, + 'MB-D10BatteryType' => 'Akku-/Batterietyp', + 'MB-D80Batteries' => { + Description => 'Akku-/Batterietyp', + PrintConv => { + 'FR6 (AA Lithium)' => 'FR6 (Mignon-Lithium)', + 'HR6 (AA Ni-MH)' => 'HR6 (Mignon-Ni-MH)', + 'LR6 (AA Alkaline)' => 'LR6 (Mignon-Alkaline)', + 'ZR6 (AA Ni-Mg)' => 'ZR6 (Mignon-Ni-Mg)', + }, + }, + 'MB-D80BatteryType' => 'MB-D80 Batterietyp', + 'MCUVersion' => 'MCU-Version', + 'MD5Digest' => 'MD5 Kennwert', + 'MIEVersion' => 'MIE-Version', + 'MIMEType' => 'MIME-Typ', + 'MPImage' => 'MP Vorschaubild', + 'MPImageFlags' => 'MP Vorschaubild Flags', + 'MPImageFormat' => 'MP Vorschaubild Format', + 'MPImageLength' => 'MP Vorschaubild-Datenlänge', + 'MPImageStart' => 'MP Vorschaubild Datenposition', + 'MPImageType' => { + Description => 'MP Vorschaubild Typ', + PrintConv => { + 'Large Thumbnail (VGA equivalent)' => 'Vorschaubild groß (VGA)', + 'Large Thumbnail (full HD equivalent)' => 'Vorschaubild groß (HD)', + 'Multi-frame Panorama' => 'Mehrbild Panorama', + 'Undefined' => 'Nicht definiert', + }, + }, + 'MSStereo' => { + PrintConv => { + 'Off' => 'Aus', + 'On' => 'Ein', + }, + }, + 'Macro' => { + Description => 'Makro', + PrintConv => { + 'Macro' => 'Makro', + 'Manual' => 'Manuell', + 'Off' => 'Aus', + 'On' => 'Ein', + 'Super Macro' => 'Super-Makro', + 'n/a' => '(nicht gesetzt)', + }, + }, + 'MacroLED' => { + Description => 'Makro LED', + PrintConv => { + 'Off' => 'Aus', + 'On' => 'Ein', + }, + }, + 'MacroMagnification' => 'Makro Vergrößerung', + 'MacroMode' => { + Description => 'Makro-Modus', + PrintConv => { + 'Macro' => 'Makro', + 'Macro Zoom' => 'Makro-Zoom', + 'Off' => 'Aus', + 'On' => 'Ein', + 'Super Macro' => 'Super-Makro', + 'Tele-Macro' => 'Tele-Makro', + }, + }, + 'MagicFilter' => { + PrintConv => { + 'Drawing' => 'Zeichnung', + 'Fish Eye' => 'Fischauge', + 'Off' => 'Aus', + 'Reflection' => 'Reflektierung', + 'Soft Focus' => 'Weichzeichner', + 'Soft Focus 2' => 'Weichzeichner 2', + 'Sparkle' => 'Perleffekt', + 'Watercolor' => 'Wasserfarben', + }, + }, + 'MagnifiedView' => { + Description => 'Lupenfunktion', + PrintConv => { + 'Image playback only' => 'Nur bei Bildwiedergabe', + 'Image review and playback' => 'Sofortbild u. Wiedergabe', + }, + }, + 'MainDialExposureComp' => { + Description => 'Main Dial Belichtungskorrektur', + PrintConv => { + 'Off' => 'Aus', + 'On' => 'Ein', + }, + }, + 'Make' => 'Gerätehersteller', + 'MakeAndModel' => 'Hersteller und Modell', + 'MakerNote' => 'Hersteller-eigene Daten', + 'MakerNoteApple' => 'Herstellerdaten Apple', + 'MakerNoteCanon' => 'Herstellerdaten Canon', + 'MakerNoteCasio' => 'Herstellerdaten Casio', + 'MakerNoteCasio2' => 'Herstellerdaten Casio 2', + 'MakerNoteFLIR' => 'Herstellerdaten FLIR', + 'MakerNoteFujiFilm' => 'Herstellerdaten Fuji Film', + 'MakerNoteGE' => 'Herstellerdaten GE', + 'MakerNoteGE2' => 'Herstellerdaten GE2', + 'MakerNoteHP' => 'Herstellerdaten HP', + 'MakerNoteHP2' => 'Herstellerdaten HP2', + 'MakerNoteHP4' => 'Herstellerdaten HP4', + 'MakerNoteHP6' => 'Herstellerdaten HP6', + 'MakerNoteHasselblad' => 'Herstellerdaten Hasselblad', + 'MakerNoteISL' => 'Herstellerdaten ISL', + 'MakerNoteJVC' => 'Herstellerdaten JVC', + 'MakerNoteJVCText' => 'Herstellerdaten JVC Text', + 'MakerNoteKodak10' => 'Herstellerdaten Kodak 10', + 'MakerNoteKodak1a' => 'Herstellerdaten Kodak 1a', + 'MakerNoteKodak1b' => 'Herstellerdaten Kodak 1b', + 'MakerNoteKodak2' => 'Herstellerdaten Kodak 2', + 'MakerNoteKodak3' => 'Herstellerdaten Kodak 3', + 'MakerNoteKodak4' => 'Herstellerdaten Kodak 4', + 'MakerNoteKodak5' => 'Herstellerdaten Kodak 5', + 'MakerNoteKodak6a' => 'Herstellerdaten Kodak 6a', + 'MakerNoteKodak6b' => 'Herstellerdaten Kodak 6b', + 'MakerNoteKodak7' => 'Herstellerdaten Kodak 7', + 'MakerNoteKodak8a' => 'Herstellerdaten Kodak 8a', + 'MakerNoteKodak8b' => 'Herstellerdaten Kodak 8b', + 'MakerNoteKodak9' => 'Herstellerdaten Kodak 9', + 'MakerNoteKodakUnknown' => 'Herstellerdaten Kodak Unbekannt', + 'MakerNoteKyocera' => 'Herstellerdaten Kyocera', + 'MakerNoteLeica' => 'Herstellerdaten Leica', + 'MakerNoteLeica2' => 'Herstellerdaten Leica 2', + 'MakerNoteLeica3' => 'Herstellerdaten Leica 3', + 'MakerNoteLeica4' => 'Herstellerdaten Leica 4', + 'MakerNoteLeica5' => 'Herstellerdaten Leica 5', + 'MakerNoteLeica6' => 'Herstellerdaten Leica 6', + 'MakerNoteMinolta' => 'Herstellerdaten Minolta', + 'MakerNoteMinolta2' => 'Herstellerdaten Minolta 2', + 'MakerNoteMinolta3' => 'Herstellerdaten Minolta 3', + 'MakerNoteNikon' => 'Herstellerdaten Nikon', + 'MakerNoteNikon2' => 'Herstellerdaten Nikon 2', + 'MakerNoteNikon3' => 'Herstellerdaten Nikon 3', + 'MakerNoteOlympus' => 'Herstellerdaten Olympus', + 'MakerNoteOlympus2' => 'Herstellerdaten Olympus 2', + 'MakerNotePanasonic' => 'Herstellerdaten Panasonic', + 'MakerNotePanasonic2' => 'Herstellerdaten Panasonic 2', + 'MakerNotePentax' => 'Herstellerdaten Pentax', + 'MakerNotePentax2' => 'Herstellerdaten Pentax 2', + 'MakerNotePentax3' => 'Herstellerdaten Pentax 3', + 'MakerNotePentax4' => 'Herstellerdaten Pentax 4', + 'MakerNotePentax5' => 'Herstellerdaten Pentax 5', + 'MakerNotePentax6' => 'Herstellerdaten Pentax 6', + 'MakerNotePhaseOne' => 'Herstellerdaten Phase One', + 'MakerNoteReconyx' => 'Herstellerdaten Reconyx', + 'MakerNoteRicoh' => 'Herstellerdaten Ricoh', + 'MakerNoteRicohText' => 'Herstellerdaten Ricoh Text', + 'MakerNoteSafety' => { + Description => 'Sicherheit der Hersteller-Informationsdaten', + PrintConv => { + 'Safe' => 'Sicher', + 'Unsafe' => 'Unsicher', + }, + }, + 'MakerNoteSamsung1a' => 'Herstellerdaten Samsung 1a', + 'MakerNoteSamsung1b' => 'Herstellerdaten Samsung 1b', + 'MakerNoteSamsung2' => 'Herstellerdaten Samsung 2', + 'MakerNoteSanyo' => 'Herstellerdaten Sanyo', + 'MakerNoteSanyoC4' => 'Herstellerdaten Sanyo C4', + 'MakerNoteSanyoPatch' => 'Herstellerdaten Sanyo Patch', + 'MakerNoteSigma' => 'Herstellerdaten Sigma', + 'MakerNoteSony' => 'Herstellerdaten Sony', + 'MakerNoteSony2' => 'Herstellerdaten Sony 2', + 'MakerNoteSony3' => 'Herstellerdaten Sony 3', + 'MakerNoteSony4' => 'Herstellerdaten Sony 4', + 'MakerNoteSony5' => 'Herstellerdaten Sony 5', + 'MakerNoteSonyEricsson' => 'Herstellerdaten Sony Ericsson', + 'MakerNoteSonySRF' => 'Herstellerdaten Sony SRF', + 'MakerNoteType' => 'Benutzerdaten Typ', + 'MakerNoteUnknown' => 'Herstellerdaten Unbekannt', + 'MakerNoteUnknownBinary' => 'Herstellerdaten Unbekannt-Binär', + 'MakerNoteUnknownText' => 'Herstellerdaten Unbekannt-Text', + 'MakerNoteVersion' => 'MakerNote-Version', + 'MakerNotes' => 'Hinweise des Herstellers', + 'ManometerPressure' => 'Gemessener Luft- bzw. Wasserdruck', + 'ManometerReading' => 'Berechnete Höhe oder Tauchtiefe', + 'ManualAFPointSelectPattern' => 'Manuelle Wahl der AF-Punkte', + 'ManualFlash' => 'Manueller Blitz', + 'ManualFlashOutput' => { + Description => 'Manuelle Blitzstärke', + PrintConv => { + 'Full' => 'Voll', + 'Low' => 'Gering', + 'Medium' => 'Mittel', + 'n/a' => '(nicht gesetzt)', + }, + }, + 'ManualFlashStrength' => 'Manuelle Blitzstärke', + 'ManualFocusDistance' => 'Manuelle Fokusdistanz', + 'ManualTv' => { + Description => 'Manuelle Tv/Av-Einstellung für Manuelle Belichtung', + PrintConv => { + 'Tv=Control/Av=Main' => 'Tv=Schnelleinstellrad/Av=Haupt-Wahlrad', + 'Tv=Main/Av=Control' => 'Tv=Haupt-Wahlrad/Av=Schnelleinstellrad', + }, + }, + 'ManufactureDate' => 'Herstellungsdatum', + 'Marked' => 'Markiert', + 'MasterDocumentID' => 'ID des Originaldokuments', + 'MaxAperture' => 'Größte Blende', + 'MaxApertureAtCurrentFocal' => 'Größte Blende bei aktueller Brennweite', + 'MaxApertureAtMaxFocal' => 'Größte Blende bei größter Brennweite', + 'MaxApertureAtMinFocal' => 'Größte Blende bei geringster Brennweite', + 'MaxApertureValue' => 'Größtmögliche Blende', + 'MaxContinuousRelease' => 'Max. Bildanzahl pro Serie', + 'MaxFocalLength' => 'Größte Brennweite', + 'MaxJPEGTableIndex' => 'Größter Index JPEG Tabellen', + 'MaxSampleValue' => 'Größter Sample Wert', + 'MeasuredEV' => 'Gemessener LW', + 'MeasuredLV' => 'Lichtwert gemessen', + 'MeasuredRGGB' => 'Messung RGGB', + 'MeasuredRGGBData' => 'Messung RGGB', + 'MeasurementBacking' => 'Basis der Messung', + 'MeasurementFlare' => 'Messung Lichtschein', + 'MeasurementGeometry' => { + Description => 'Geometrie der Messung', + PrintConv => { + '0/45 or 45/0' => '0/45 oder 45/0', + '0/d or d/0' => '0/d oder d/0', + }, + }, + 'MeasurementIlluminant' => 'Messung Beleuchtung', + 'MeasurementObserver' => 'Messung nach', + 'MediaBlackPoint' => 'Medium-Schwarzpunkt', + 'MediaWhitePoint' => 'Medium-Weißpunkt', + 'MenuButtonDisplayPosition' => { + Description => 'Positionsanzeige Menuetaste', + PrintConv => { + 'Previous' => 'Vorherige Anzeige', + 'Previous (top if power off)' => 'Vorherige (Anfang nach AUS)', + 'Top' => 'Oben', + }, + }, + 'MenuButtonReturn' => { + PrintConv => { + 'Previous' => 'Vorherige Anzeige', + 'Top' => 'Oben', + }, + }, + 'MetadataCreator' => 'Metadaten Ersteller', + 'MetadataDate' => 'Datum der Metadaten', + 'MetadataID' => 'Metadaten ID', + 'Metering' => { + Description => 'Belichtungsmessung', + PrintConv => { + 'Center-weighted' => 'Mittenbetont', + 'Matrix' => 'Matrixmessung', + 'Spot' => 'Spotmessung', + }, + }, + 'MeteringMode' => { + Description => 'Belichtungsmessmethode', + PrintConv => { + 'Average' => 'Integralmessung', + 'Center-weighted Average' => 'Mittenbetont', + 'Center-weighted average' => 'Mittenbetont', + 'Default' => 'System', + 'Evaluative' => 'Mehrfeldmessung', + 'Multi-segment' => 'Multi-Segment', + 'Multi-spot' => 'MultiSpot', + 'Other' => 'Andere', + 'Partial' => 'Teilbild', + 'Spot' => 'Spotmessung', + 'Spot+Highlight control' => 'Spot+Helligkeitsbetont', + 'Spot+Shadow control' => 'Spot+Schattenbetont', + 'Unknown' => 'Unbekannt', + }, + }, + 'MeteringMode2' => { + Description => 'Belichtungs-Messmethode 2', + PrintConv => { + 'Center-weighted average' => 'Mittenbetont', + 'Multi-segment' => 'Multi-Segment', + }, + }, + 'MeteringMode3' => { + Description => 'Belichtungs-Messmethode (3)', + PrintConv => { + 'Multi-segment' => 'Multi-Segment', + }, + }, + 'MeteringTime' => { + Description => 'Ausschaltzeit Belichtungsmesser', + PrintConv => { + 'No Limit' => 'Unbegrenzt', + }, + }, + 'MinAperture' => 'Kleinste Blende', + 'MinApertureValue' => 'Kleinste Blende', + 'MinFocalLength' => 'Kleinste Brennweite', + 'MinSampleValue' => 'Kleinster Sample Wert', + 'MiniatureFilterOrientation' => { + PrintConv => { + 'Vertical' => 'Vertikal', + }, + }, + 'MinoltaCameraSettings2' => 'Kameraeinstellungen 2', + 'MinoltaCameraSettings5D' => 'Kameraeinstellungen (5D)', + 'MinoltaCameraSettings7D' => 'Kameraeinstellungen (7D)', + 'MinoltaDate' => 'Minolta-Datum', + 'MinoltaImageSize' => { + Description => 'Minolta-Bildgröße', + PrintConv => { + 'Full' => 'Volle Größe', + 'Large' => 'Groß', + 'Medium' => 'Mittelgroß', + 'Small' => 'Klein', + }, + }, + 'MinoltaMakerNote' => 'Minolta-Herstellerinformationen', + 'MinoltaModelID' => 'Minolta-Modell', + 'MinoltaQuality' => { + Description => 'Minolta-Bildqualität', + PrintConv => { + 'Extra Fine' => 'Extra-Fein', + 'Fine' => 'Fein', + 'RAW+JPEG' => 'RAW + JPEG', + 'Super Fine' => 'Super-Fein', + }, + }, + 'MinoltaTime' => 'Minolta-Zeit', + 'MirrorLockup' => { + Description => 'Spiegelverriegelung', + PrintConv => { + 'Disable' => 'Ausgeschaltet', + 'Enable' => 'Eingeschaltet', + 'Enable: Down with Set' => 'Eingeschaltet: Abwärts mit SET (Taste)', + }, + }, + 'ModeDialPosition' => { + PrintConv => { + 'Aperture-priority AE' => 'Blendenpriorität', + 'Manual' => 'Manuell', + 'No Flash' => 'Kein Blitz', + 'Program AE' => 'Programmautomatik', + 'Shutter speed priority AE' => 'Verschlußpriorität', + }, + }, + 'Model' => 'Kameramodell', + 'Model2' => 'Kameramodell (2)', + 'ModelingFlash' => { + Description => 'Einstelllicht', + PrintConv => { + 'Off' => 'Aus', + 'On' => 'Ein', + }, + }, + 'ModifiedColorTemp' => 'Geänderte Farbtemperatur', + 'ModifiedDigitalGain' => 'Digitale Verstärkung geändert', + 'ModifiedPictureStyle' => { + Description => 'Geänderter Bildstil', + PrintConv => { + 'Faithful' => 'Natürlich', + 'Landscape' => 'Landschaft', + 'Monochrome' => 'Monochrom', + 'None' => 'Keiner', + 'Portrait' => 'Porträt', + 'User Def. 1' => 'Benutzerdefiniert 1', + 'User Def. 2' => 'Benutzerdefiniert 2', + 'User Def. 3' => 'Benutzerdefiniert 3', + }, + }, + 'ModifiedSaturation' => { + PrintConv => { + 'Off' => 'Aus', + }, + }, + 'ModifiedSharpness' => 'Schärfe verändert', + 'ModifiedSharpnessFreq' => { + PrintConv => { + 'High' => 'Hoch', + 'Highest' => 'Höchste', + 'Low' => 'Leicht', + 'Lowest' => 'Niedrigste', + 'n/a' => '(nicht gesetzt)', + }, + }, + 'ModifiedToneCurve' => { + Description => 'Tonwertkurve verändert', + PrintConv => { + 'Custom' => 'Benutzerdefiniert', + 'Manual' => 'Manuell', + }, + }, + 'ModifiedWhiteBalance' => { + PrintConv => { + 'Auto' => 'Automatisch', + 'Black & White' => 'Schwarz/Weiß', + 'Cloudy' => 'Bewölkt', + 'Custom' => 'Benutzerdefiniert', + 'Custom 1' => 'Benutzerdefiniert 1', + 'Custom 2' => 'Benutzerdefiniert 2', + 'Custom 3' => 'Benutzerdefiniert 3', + 'Custom 4' => 'Benutzerdefiniert 4', + 'Daylight' => 'Tageslicht', + 'Daylight Fluorescent' => 'Neonlicht tageslichtweiß', + 'Flash' => 'Blitz', + 'Fluorescent' => 'Neonlicht', + 'Manual Temperature (Kelvin)' => 'Manuelle Temperatur (Kelvin)', + 'Shade' => 'Schatten', + 'Tungsten' => 'Glühbirne', + 'Underwater' => 'Unterwasser', + }, + }, + 'ModifyDate' => 'Änderungsdatum', + 'MoireFilter' => { + PrintConv => { + 'Off' => 'Aus', + 'On' => 'Ein', + }, + }, + 'MonitorOffTime' => 'Ausschaltzeit des Monitors', + 'MonochromeFilterEffect' => { + Description => 'Filtereffekt Monochrom', + PrintConv => { + 'Green' => 'Grün', + 'None' => 'Keiner', + 'Red' => 'Rot', + 'Yellow' => 'Gelb', + }, + }, + 'MonochromeLinear' => { + PrintConv => { + 'No' => 'Nein', + 'Yes' => 'Ja', + }, + }, + 'MonochromeToningEffect' => { + Description => 'Tönungseffekt Monochrom', + PrintConv => { + 'Blue' => 'Blau', + 'Green' => 'Grün', + 'None' => 'Keiner', + 'Purple' => 'Lila', + }, + }, + 'Month' => 'Monat', + 'MultiBurstImageHeight' => 'Multi-Burst Bildhöhe', + 'MultiBurstImageWidth' => 'Multi-Burst Bildbreite', + 'MultiBurstMode' => { + Description => 'Mehrfach-Burst Modus', + PrintConv => { + 'Off' => 'Aus', + 'On' => 'Ein', + }, + }, + 'MultiControllerWhileMetering' => { + Description => 'Multicontroller bei Messung', + PrintConv => { + 'AF point selection' => 'AF-Punkt-Auswahl', + 'Off' => 'Aus', + }, + }, + 'MultiExposure' => 'Mehrfachbelichtungsdaten', + 'MultiExposureAutoGain' => { + Description => 'Mehrfachbelichtung Automatik', + PrintConv => { + 'Off' => 'Aus', + 'On' => 'Ein', + }, + }, + 'MultiExposureMode' => { + Description => 'Mehrfachbelichtungsmodus', + PrintConv => { + 'Image Overlay' => 'Bildüberlagerung', + 'Multiple Exposure' => 'Mehrfachbelichtung', + 'Off' => 'Aus', + }, + }, + 'MultiExposureShots' => 'Mehrfachbelichtung Anzahl Aufnahmen', + 'MultiExposureVersion' => 'Mehrfachbelichtungsdaten-Version', + 'MultiFrameNoiseReduction' => { + Description => 'Ruisond. Multi Frame', + PrintConv => { + 'Off' => 'Aus', + 'On' => 'Ein', + 'n/a' => '(nicht gesetzt)', + }, + }, + 'MultiFunctionLock' => { + PrintConv => { + 'Main dial' => 'Haupt-Wahlrad', + 'Multi-controller' => 'Multicontroller', + 'Off' => 'Aus', + 'On' => 'Ein', + 'Quick control dial' => 'Schnelleinstellrad', + }, + }, + 'MultiSelector' => { + Description => 'Multifunktionswähler', + PrintConv => { + 'Do Nothing' => 'Ohne Funktion', + 'Reset Meter-off Delay' => 'Ruhezustand verzögern', + }, + }, + 'MultiSelectorPlaybackMode' => { + Description => 'Mitteltaste Bei Wiedergabe', + PrintConv => { + 'Choose Folder' => 'Ordner auswählen', + 'Thumbnail On/Off' => 'Bildindex ein/aus', + 'View Histograms' => 'Histogramme anzeigen', + 'Zoom On/Off' => 'Ausschnitt ein/aus', + }, + }, + 'MultiSelectorShootMode' => { + Description => 'Mitteltaste Bei Aufnahme', + PrintConv => { + 'Highlight Active Focus Point' => 'AF-Messfeld hervorheben', + 'Not Used' => 'Ohne Funktion', + 'Select Center Focus Point' => 'Mittleres AF-Messfeld', + }, + }, + 'MultipleExposureMode' => { + PrintConv => { + 'Off' => 'Aus', + 'On (2 frames)' => 'Ein (2 Bilder', + 'On (3 frames)' => 'Ein (3 Bilder', + }, + }, + 'MultipleExposureSet' => { + Description => 'Mehrfachbelichtung', + PrintConv => { + 'Off' => 'Aus', + 'On' => 'Ein', + }, + }, + 'Mute' => { + PrintConv => { + 'Off' => 'Aus', + 'On' => 'Ein', + }, + }, + 'MyColorMode' => { + Description => 'My Color-Modus', + PrintConv => { + 'B&W' => 'Schwarz/Weiß', + 'Custom' => 'Benutzerdefiniert', + 'Off' => 'Aus', + }, + }, + 'MyColors' => 'My Color-Modus', + 'NDFilter' => { + Description => 'ND-Filter', + PrintConv => { + 'Off' => 'Aus', + 'On' => 'Ein', + 'n/a' => '(nicht gesetzt)', + }, + }, + 'NEFBitDepth' => { + PrintConv => { + 'n/a (JPEG)' => 'Nicht gesetzt (JPEG)', + }, + }, + 'NEFCompression' => { + Description => 'RAW-Komprimierung', + PrintConv => { + 'Lossless' => 'Verlustfrei', + 'Lossy (type 1)' => 'Verlustbehaftet (Type 1)', + 'Lossy (type 2)' => 'Verlustbehaftet (Type 2)', + 'Uncompressed' => 'Nicht komprimiert', + }, + }, + 'NEFLinearizationTable' => 'Linearisierungstabelle', + 'NativeDigest' => 'EXIF Kennwert', + 'NetExposureCompensation' => 'Net Belichtungskorrektur', + 'NewMieTag1' => 'Weiterer MIE Tag 1', + 'NewPngTag1' => 'Weiterer PNG Tag 1', + 'NewPngTag2' => 'Weiterer PNG Tag 2', + 'NewPngTag3' => 'Weiterer PNG Tag 3', + 'NewRawImageDigest' => 'Neuer RAW Image Kennwert', + 'NewsPhotoVersion' => 'IPTC-Modell-3-Version', + 'NikonCaptureData' => 'Nikon Capture-Daten', + 'NikonCaptureOutput' => 'Nikon Capture-Ausgabe', + 'NikonCaptureVersion' => 'Nikon Capture-Version', + 'NikonICCProfile' => 'Nikon ICC-Profil', + 'NikonImageSize' => { + Description => 'Nikon Bildgröße', + PrintConv => { + 'Large' => 'Groß', + 'Large (10.0 M)' => 'Groß (10.0M)', + 'Medium' => 'Mittel', + 'Medium (5.6 M)' => 'Mittel (5.6M)', + 'Small' => 'Klein', + 'Small (2.5 M)' => 'Klein (2.5M)', + }, + }, + 'NoMemoryCard' => { + Description => 'Auslösesperre', + PrintConv => { + 'Enable Release' => 'Aus', + 'Release Locked' => 'Ein', + }, + }, + 'Noise' => 'Bildrauschen', + 'NoiseFilter' => { + Description => 'Rauschfilter', + PrintConv => { + 'High' => 'Hoch', + 'Low' => 'Leicht', + 'Off' => 'Aus', + 'n/a' => '(nicht gesetzt)', + }, + }, + 'NoiseReduction' => { + Description => 'Rauschreduktion', + PrintConv => { + 'Auto' => 'Automatisch', + 'High (+1)' => 'Hoch (+1)', + 'Highest (+2)' => 'Am höchsten (+2)', + 'Low' => 'Gering', + 'Low (-1)' => 'Niedrig (-1)', + 'Lowest (-2)' => 'Am niedrigsten (+2)', + 'Max' => 'Maximal', + 'Noise Filter' => 'Rauschfilter', + 'Noise Filter (ISO Boost)' => 'Rauschfilter (ISO Boost)', + 'Noise Reduction' => 'Rauschreduktion', + 'Off' => 'Aus', + 'On' => 'Ein', + 'Strong' => 'Stark', + 'Weak' => 'Schwach', + 'n/a' => '(nicht gesetzt)', + }, + }, + 'NoiseReduction2' => { + Description => 'Rauschunterdrückung 2', + PrintConv => { + 'Noise Filter' => 'Rauschfilter', + 'Noise Filter (ISO Boost)' => 'Rauschfilter (ISO Boost)', + 'Noise Reduction' => 'Rauschreduktion', + }, + }, + 'NoiseReductionIntensity' => 'Stärke Rauschunterdrückung', + 'NoiseReductionMethod' => { + Description => 'Rauschunterdrückung Methode', + PrintConv => { + 'Better Quality' => 'Bessere Qualität"', + 'Faster' => 'Schneller', + }, + }, + 'NoiseReductionMode' => { + Description => 'Rauschunterdrückungsmodus', + PrintConv => { + 'Off' => 'Aus', + 'On' => 'Ein', + }, + }, + 'NoiseReductionSharpness' => 'Rauschunterdrückung Schärfe', + 'NoiseReductionValue' => 'Rauschunterdrückungswert', + 'NominalMaxAperture' => 'Nominaler AVmin', + 'NominalMinAperture' => 'Nominaler AVmax', + 'Notes' => 'Hinweise', + 'NumAFPoints' => 'Anzahl der AF-Punkte', + 'NumChannels' => 'Anzahl Kanäle', + 'NumColors' => 'Anzahl Farben', + 'NumFacePositions' => 'Gesichtspositionen', + 'NumImportantColors' => 'Anzahl Hauptfarben', + 'NumberOfFocusPoints' => { + Description => 'Anzahl AF-Punkte', + PrintConv => { + '11 Points' => '11 Punkte', + '39 Points' => '39 Punkte', + }, + }, + 'NumberOfImages' => 'Anzahl Bilder', + 'NumberOfPlanes' => 'Anzahl Ebenen', + 'OPIProxy' => { + PrintConv => { + 'Higher resolution image does not exist' => 'Höher aufgelöstes Bild nicht vorhanden', + 'Higher resolution image exists' => 'Höher aufgelöstes Bild vorhanden', + }, + }, + 'ObjectAttributeReference' => 'Gattung', + 'ObjectCycle' => { + Description => 'Objektzyklus', + PrintConv => { + 'Both Morning and Evening' => 'Beides', + 'Evening' => 'Abends', + 'Morning' => 'Morgens', + }, + }, + 'ObjectDistance' => 'Objektabstand', + 'ObjectFileType' => { + Description => 'Objekt Dateityp', + PrintConv => { + 'Executable file' => 'Ausführbare Datei', + 'None' => 'Keiner', + 'Unknown' => 'Unbekannt', + }, + }, + 'ObjectName' => 'Titel', + 'ObjectPreviewData' => 'Objektdatenvorschau', + 'ObjectPreviewFileFormat' => 'Dateiformat der Objektdatenvorschau', + 'ObjectPreviewFileVersion' => 'Dateiformatversion der Objektdatenvorschau', + 'ObjectTypeReference' => 'Objekttypreferenz', + 'OffsetSchema' => 'Offset-Schema', + 'OldSubfileType' => { + Description => 'Unterdatei-Typ', + PrintConv => { + 'Full-resolution image' => 'Bild in voller Auflösung', + 'Reduced-resolution image' => 'Bild in reduzierter Auflösung', + 'Single page of multi-page image' => 'Einzelbild eines mehrseitigen Bildes', + }, + }, + 'OlympusImageHeight' => 'Olympus-Bildhöhe', + 'OlympusImageWidth' => 'Olympus-Bildbreite', + 'OneTouchWB' => { + Description => 'Sofort-Weißabgleich', + PrintConv => { + 'Off' => 'Aus', + 'On' => 'Ein', + 'On (Preset)' => 'Ein (Preset)', + }, + }, + 'OperatingSystem' => { + PrintConv => { + 'unknown' => 'Unbekannt', + }, + }, + 'OpticalZoom' => 'Optischer Zoom', + 'OpticalZoomCode' => 'Optischer Zoom-Code', + 'OpticalZoomMode' => { + Description => 'Optischer Zoom-Modus', + PrintConv => { + 'Extended' => 'Erweitert', + }, + }, + 'OpticalZoomOn' => { + PrintConv => { + 'Off' => 'Aus', + 'On' => 'Ein', + }, + }, + 'Opto-ElectricConvFactor' => 'Optoelektronischer Umrechnungsfaktor', + 'OrderNumber' => 'Auftragsnummer', + 'Organization' => 'Organisation', + 'Orientation' => { + Description => 'Ausrichtung', + PrintConv => { + 'Mirror horizontal' => 'Horizontal gespiegelt', + 'Mirror horizontal and rotate 270 CW' => 'Horizontal gespiegelt und 90° gegen den Uhrzeigersinn', + 'Mirror horizontal and rotate 90 CW' => 'Horizontal gespiegelt und 90° im Uhrzeigersinn', + 'Mirror vertical' => 'Vertikal gespiegelt', + 'Rotate 180' => '180° gedreht', + 'Rotate 270 CW' => '90° gegen den Uhrzeigersinn', + 'Rotate 90 CW' => '90° im Uhrzeigersinn', + }, + }, + 'Orientation2' => { + Description => 'Ausrichtung 2', + PrintConv => { + 'Rotate 180' => '180° gedreht', + 'Rotate 270 CW' => '90° gegen den Uhrzeigersinn', + 'Rotate 90 CW' => '90° im Uhrzeigersinn', + }, + }, + 'OriginalFileName' => 'Original Dateiname', + 'OriginalFileType' => 'Original Dateityp', + 'OriginalImageHeight' => 'Bildbreite Original', + 'OriginalImageWidth' => 'Bildbreite Original', + 'OriginalRawCreator' => 'Original RAW Ersteller', + 'OriginalRawFileData' => 'Original Raw Daten', + 'OriginalRawFileDigest' => 'Original RAW Image Kennwert', + 'OriginalRawFileName' => 'Original Raw Dateiname', + 'OriginalRawFileType' => 'Original RAW Dateityp', + 'OriginalRawImage' => 'Original RAW Bild', + 'OriginalRawResource' => 'Original RAW Basisdaten', + 'OriginalTHMCreator' => 'Original THM Ersteller', + 'OriginalTHMFileType' => 'Original THM Dateityp', + 'OriginalTHMImage' => 'Original THM Bild', + 'OriginalTHMResource' => 'Original THM Basisdaten', + 'OriginalTransmissionReference' => 'Anbietervermerk Verweis', + 'OriginatingProgram' => 'Erstellungsprogramm', + 'OtherImage' => 'Other Image Vorschaubild', + 'OtherImageLength' => 'OtherImage Datenlänge', + 'OtherImageStart' => 'Other Image Datenposition', + 'OutputImageHeight' => 'Ausgabe-Bildhöhe', + 'OutputImageWidth' => 'Ausgabe-Bildbreite', + 'OutputResolution' => 'Ausgabe Auflösung', + 'OverlayPlanes' => 'Überlagerungsebenen', + 'Owner' => 'Besitzer', + 'OwnerID' => 'Besitzer-ID', + 'OwnerName' => 'Name des Besitzers', + 'PEFVersion' => 'PEF-Version', + 'PNGWarning' => 'PNG Warnung', + 'Padding' => 'Platzhalter', + 'PageName' => 'Seitenname', + 'PageNumber' => 'Seitenummer', + 'Pages' => 'Seiten', + 'PanOrientation' => { + Description => 'Pan Ausrichtung', + PrintConv => { + 'Bottom to top' => 'Von Unten nach Oben', + 'Clockwise' => 'Im Uhrzeigersinn', + 'Counter clockwise' => 'Gegen den Uhrzeigersinn', + 'Left to right' => 'Von Links nach Rechts', + 'Right to left' => 'Von Rechts nach Links', + 'Start at bottom left' => 'Links unten beginnend', + 'Start at bottom right' => 'Rechts unten beginnend', + 'Start at top left' => 'Links oben beginnend', + 'Start at top right' => 'Rechts oben beginnend', + 'Top to bottom' => 'Von Oben nach Unten', + '[unused]' => '[nicht verwendet]', + }, + }, + 'PanasonicImageHeight' => 'Panasonic Bildhöhe', + 'PanasonicImageWidth' => 'Panasonic Bildbreite', + 'PanasonicTitle' => 'Titel', + 'PanoramaCropBottom' => 'Panorama Ausschnitt Unten', + 'PanoramaCropLeft' => 'Panorama Ausschnitt Links', + 'PanoramaCropRight' => 'Panorame Ausschnitt Rechts', + 'PanoramaCropTop' => 'Panorama Ausschnitt Oben', + 'PanoramaDirection' => { + Description => 'Panorama-Richtung', + PrintConv => { + '2x2 Matrix (Clockwise)' => '2x2 Matrix (im Uhrzeigersinn)', + 'Bottom to Top' => 'Unten nach Oben', + 'Left to Right' => 'Links nach Rechts', + 'Right to Left' => 'Rechts nach Links', + 'Top to Bottom' => 'Oben nach Unten', + }, + }, + 'PanoramaFrameNumber' => 'Panorama-Bild', + 'PanoramaMode' => 'Panorama Modus', + 'PanoramaSize3D' => { + PrintConv => { + 'n/a' => '(nicht gesetzt)', + }, + }, + 'PentaxImageSize' => { + Description => 'Pentax-Bildgröße', + PrintConv => { + '2304x1728 or 2592x1944' => '2304 x 1728 oder 2592 x 1944', + '2560x1920 or 2304x1728' => '2560 x 1920 oder 2304 x 1728', + '2816x2212 or 2816x2112' => '2816 x 2212 oder 2816 x 2112', + '3008x2008 or 3040x2024' => '3008 x 2008 oder 3040 x 2024', + 'Full' => 'Voll', + }, + }, + 'PentaxModelID' => 'Pentax-Modell', + 'PentaxVersion' => 'Pentax-Version', + 'People' => 'Menschen', + 'Permits' => { + PrintConv => { + 'Distribution' => 'Verteilung', + 'Reproduction' => 'Reproduktion', + }, + }, + 'PhaseDetectAF' => { + Description => 'Auto-Fokus', + PrintConv => { + 'Off' => 'Aus', + 'On (11-point)' => 'Ein (11-Punkt)', + 'On (39-point)' => 'Ein (39 Punkte)', + 'On (51-point)' => 'Ein (51-Punkt)', + 'On (hybrid)' => 'Ein (Hybrid)', + }, + }, + 'PhoneNumber' => 'Telefonnummer', + 'PhotoEffect' => { + Description => 'Foto-Effekt', + PrintConv => { + 'B&W' => 'Schwarz/Weiß', + 'Custom' => 'Benutzerdefiniert', + 'Off' => 'Aus', + }, + }, + 'PhotoEffects' => { + PrintConv => { + 'Off' => 'Aus', + 'On' => 'Ein', + }, + }, + 'PhotoEffectsData' => 'Bildeffekt-Daten', + 'PhotoEffectsType' => { + Description => 'Bildeffekt-Methode', + PrintConv => { + 'B&W' => 'Schwarz/Weiß', + 'None' => 'Keine', + 'Tinted' => 'Getont', + }, + }, + 'PhotoInfoPlayback' => { + Description => 'Bildinfos & Wiedergabe', + PrintConv => { + 'Info Left-right, Playback Up-down' => 'Info <> / Wiedergabe', + 'Info Up-down, Playback Left-right' => 'Info / Wiedergabe <>', + }, + }, + 'PhotoStyle' => { + Description => 'Fotostil', + PrintConv => { + 'Monochrome' => 'Schwarz/Weiß', + 'Natural' => 'Natürlich', + 'Portrait' => 'Porträt', + 'Scenery' => 'Szene', + 'Standard or Custom' => 'Standard oder benutzerdefiniert', + 'Vivid' => 'Lebendig', + }, + }, + 'PhotometricInterpretation' => { + Description => 'Pixel-Schema', + PrintConv => { + 'BlackIsZero' => 'Schwarz ist Null', + 'Color Filter Array' => 'CFA (Farbfiltermatrix)', + 'Pixar LogL' => 'CIE Log2(L) (Log Luminanz)', + 'Pixar LogLuv' => 'CIE Log2(L)(u\',v\') (Log Luminanz und Chrominanz)', + 'Transparency Mask' => 'Transparenzmaske', + 'WhiteIsZero' => 'Weiß ist Null', + }, + }, + 'PhotoshopBGRThumbnail' => 'Photoshop BGR-Vorschaubild', + 'PhotoshopFormat' => 'Photoshop-Format', + 'PhotoshopQuality' => 'Photoshop-Qualität', + 'PhysicalImageSize' => 'Physikalische Bildgröße', + 'PictureControl' => { + Description => 'Bildoptimierung', + PrintConv => { + 'Off' => 'Aus', + 'On' => 'Ein', + }, + }, + 'PictureControlActive' => { + PrintConv => { + 'Off' => 'Aus', + 'On' => 'Ein', + }, + }, + 'PictureControlAdjust' => { + Description => 'Bildoptimierung-Anpassung', + PrintConv => { + 'Default Settings' => 'Standardeinstellungen', + 'Full Control' => 'Manuelle Einstellung', + 'Quick Adjust' => 'Schnelleinstellung', + }, + }, + 'PictureControlBase' => 'Bildoptimierung-Basis', + 'PictureControlName' => 'Bildoptimierung-Name', + 'PictureControlQuickAdjust' => 'Bildoptimierung-Schnelleinstellung', + 'PictureControlVersion' => 'Bildoptimierung-Version', + 'PictureFinish' => { + PrintConv => { + 'Evening Scene' => 'Abendszene', + 'Monochrome' => 'Monochrom', + 'Natural' => 'Natürlich', + 'Natural+' => 'Natürlich+', + 'Night Portrait' => 'Nachtporträt', + 'Night Scene' => 'Nachtszene', + 'Portrait' => 'Porträt', + 'Wind Scene' => 'Windszene', + }, + }, + 'PictureMode' => { + Description => 'Motivprogramm', + PrintConv => { + '1/2 EV steps' => '1/2 LW Schritte', + '1/3 EV steps' => '1/3 LW Schitte', + 'Anti-blur' => 'Motivschärfe-Modus', + 'Aperture Priority' => 'Zeitautomatik', + 'Aperture Priority, Off-Auto-Aperture' => 'Zeitautomatik (Blendenring nicht auf A)', + 'Aperture-priority AE' => 'Blendenpriorität', + 'Auto' => 'Automatisch', + 'Auto PICT (Landscape)' => 'Auto PICT (Landschaft)', + 'Auto PICT (Macro)' => 'Auto PICT (Makro)', + 'Auto PICT (Portrait)' => 'Auto PICT (Porträt)', + 'Auto PICT (Sport)' => 'Auto PICT (Motiv in Bewegung)', + 'Auto PICT (Standard)' => 'Auto PICT (Normal)', + 'Autumn' => 'Herbst', + 'Backlight Silhouette' => 'Hintergrundbeleuchtung Silhouette', + 'Beach' => 'Strand', + 'Beach & Snow' => 'Strand & Schnee', + 'Black & White' => 'Schwarz/Weiß', + 'Blue' => 'Blau', + 'Blur Control' => 'Bildstabilisierung', + 'Blur Reduction' => 'Unschärfereduktion', + 'Bulb' => 'Bulb-Modus', + 'Bulb, Off-Auto-Aperture' => 'Bulb (Blendenring nicht auf A)', + 'Candlelight' => 'Kerzenlicht', + 'DOF Program' => 'Schärfentiefe-Priorität', + 'DOF Program (HyP)' => 'Schärfentiefe-Priorität (Hyper-Programm)', + 'Dark Pet' => 'Haustier (Dunkel)', + 'Digital Filter' => 'Digitalfilter', + 'Fireworks' => 'Feuerwerk', + 'Fisheye' => 'Fischauge', + 'Flash X-Sync Speed AE' => 'Blitz X-synch. Zeit', + 'Flower' => 'Blumen', + 'Food' => 'Lebensmittel', + 'Forest' => 'Wald', + 'Frame Composite' => 'Rahmen', + 'Green' => 'Grün', + 'Green Mode' => 'Grüner Modus', + 'Half-length Portrait' => 'Brustbild', + 'Hi-speed Program' => 'HS-Priorität', + 'Hi-speed Program (HyP)' => 'HS-Priorität (Hyper-Programm)', + 'Illustrations' => 'Dokument', + 'Kids' => 'Kinder', + 'Landscape' => 'Landschaft', + 'Light Pet' => 'Haustier (Hell)', + 'MTF Program' => 'MTF-Priorität', + 'MTF Program (HyP)' => 'MTF-Priorität (Hyper-Programm)', + 'Macro' => 'Makro', + 'Manual' => 'Manuell', + 'Manual, Off-Auto-Aperture' => 'Manuell (Blendenring nicht auf A)', + 'Medium Pet' => 'Haustier (Neutrale Helligkeit)', + 'Natural' => 'Natur', + 'Natural Light' => 'Umgebungslicht', + 'Natural Light & Flash' => 'Umgebungslicht & Blitz', + 'Natural Skin Tone' => 'Nat. Hautton', + 'Night Scene' => 'Nachtszene', + 'Night Scene HDR' => 'Nachtszene', + 'Night Scene Portrait' => 'Nacht-Porträt', + 'No Flash' => 'Kein Blitz', + 'Pet' => 'Haustiere', + 'Pink' => 'Rosa', + 'Portrait' => 'Porträt', + 'Portrait 2' => 'Porträt 2', + 'Program' => 'Programm', + 'Program (HyP)' => 'Programmautomatik (Hyper-Programm)', + 'Program AE' => 'Programmautomatik', + 'Program Av Shift' => 'Av Shift-Belichtungsprogramm', + 'Program Tv Shift' => 'Tv Shift-Belichtungsprogramm', + 'Purple' => 'Violett', + 'Red' => 'Rot', + 'Self Portrait' => 'Selbstporträt', + 'Sensitivity Priority AE' => 'Blenden- & Zeitautomatik (Sv, ISO-Vorgabe)', + 'Shutter & Aperture Priority AE' => 'Empfindlichkeitsautomatik (TAv, Zeit-/Blendenvorgabe)', + 'Shutter Speed Priority' => 'Verschlusspriorität', + 'Shutter speed priority AE' => 'Verschlusspriorität', + 'Snow' => 'Schnee', + 'Soft' => 'Soft (Weichzeichnung)', + 'Sports' => 'Sport', + 'Sunset' => 'Sonnenuntergang', + 'Surf & Snow' => 'Surf & Schnee', + 'Synchro Sound Record' => 'Synchr. Sprachnotiz', + 'Underwater' => 'Unterwasser', + 'Yellow' => 'Gelb', + }, + }, + 'PictureMode2' => { + Description => 'Motivprogramm 2', + PrintConv => { + 'Aperture Priority' => 'Blendenpriorität', + 'Aperture Priority, Off-Auto-Aperture' => 'Zeitautomatik (Blendenring nicht auf A)', + 'Bulb' => 'Bulb-Modus', + 'Bulb, Off-Auto-Aperture' => 'Bulb (Blendenring nicht auf A)', + 'Flash X-Sync Speed AE' => 'Blitz X-synch. Zeit', + 'Green Mode' => '"Grünes" AE-Programm', + 'Manual' => 'Manuell', + 'Manual, Off-Auto-Aperture' => 'Manuell (Blendenring nicht auf A)', + 'Program AE' => 'Programmautomatik', + 'Program Av Shift' => 'Av Shift-Belichtungsprogramm', + 'Program Tv Shift' => 'Tv Shift-Belichtungsprogramm', + 'Scene Mode' => 'Motivprogramm', + 'Sensitivity Priority AE' => 'Blenden- & Zeitautomatik (Sv, ISO-Vorgabe)', + 'Shutter & Aperture Priority AE' => 'Empfindlichkeitsautomatik (TAv, Zeit-/Blendenvorgabe)', + 'Shutter Speed Priority' => 'Verschlusspriorität', + }, + }, + 'PictureModeBWFilter' => { + Description => 'Motivprogramm S/W Filter', + PrintConv => { + 'Green' => 'Grün', + 'Red' => 'Rot', + 'Yellow' => 'Gelb', + 'n/a' => '(nicht gesetzt)', + }, + }, + 'PictureModeContrast' => 'Motivprogramm Kontrast', + 'PictureModeEffect' => { + Description => 'Motivprogramm Effekt', + PrintConv => { + 'High' => 'Hoch', + 'Low' => 'Niedrig', + 'n/a' => '(nicht gesetzt)', + }, + }, + 'PictureModeHue' => 'Motivprogramm Farbton', + 'PictureModeSaturation' => 'Motivprogramm Farbsättigung', + 'PictureModeSharpness' => 'Motivprogramm Schärfe', + 'PictureModeTone' => { + Description => 'Motivprogramm Tonwert', + PrintConv => { + 'Blue' => 'Blau', + 'Green' => 'Grün', + 'Purple' => 'Lila', + 'n/a' => '(nicht gesetzt)', + }, + }, + 'PictureStyle' => { + Description => 'Bildstil', + PrintConv => { + 'Custom' => 'Benutzerdefiniert', + 'Faithful' => 'Natürlich', + 'High Saturation' => 'Hohe Farbsättigung', + 'Landscape' => 'Landschaft', + 'Low Saturation' => 'Geringe Farbsättigung', + 'Monochrome' => 'Monochrom', + 'None' => 'Keiner', + 'Portrait' => 'Porträt', + 'Unknown?' => 'Unbekannt?', + 'User Def. 1' => 'Benutzerdefiniert 1', + 'User Def. 2' => 'Benutzerdefiniert 2', + 'User Def. 3' => 'Benutzerdefiniert 3', + }, + }, + 'PictureWizardMode' => { + PrintConv => { + 'Forest' => 'Wald', + 'Landscape' => 'Landschaft', + 'Portrait' => 'Porträt', + 'n/a' => '(nicht gesetzt)', + }, + }, + 'PixelFormat' => { + Description => 'Pixel-Format', + PrintConv => { + 'Black & White' => 'Schwarz/Weiß', + }, + }, + 'PixelUnits' => { + Description => 'Pixel Einheit', + PrintConv => { + 'Unknown' => 'Unbekannt', + 'meters' => 'Meter', + }, + }, + 'PixelsPerMeterX' => 'Pixel per Meter X', + 'PixelsPerMeterY' => 'Pixel per Meter Y', + 'PixelsPerUnitX' => 'Pixel pro X-Einheit', + 'PixelsPerUnitY' => 'Pixel pro Y-Einheit', + 'PlanarConfiguration' => { + Description => 'Bilddatenausrichtung', + PrintConv => { + 'Chunky' => 'Kompaktformat', + 'Planar' => 'Ebenes Format', + }, + }, + 'Planes' => 'Ebenen', + 'PostalCode' => 'Postleitzahl', + 'PowerSource' => { + Description => 'Stromquelle', + PrintConv => { + 'Body Battery' => 'Batterie im Gehäuse', + 'External Power Supply' => 'Externe Stromversorgung', + 'Grip Battery' => 'Batterie im Griff', + }, + }, + 'Predictor' => { + Description => 'Prädiktor', + PrintConv => { + 'Horizontal differencing' => 'Horizontale Differenzierung', + 'None' => 'Kein Prädiktor-Schema in Benutzung', + }, + }, + 'PresetWhiteBalance' => { + Description => 'Weißabgleich Voreinstellung', + PrintConv => { + 'Cloudy' => 'Bewölkt', + 'Daylight' => 'Tageslicht', + 'Flash' => 'Blitz', + 'Fluorescent' => 'Neonlicht', + 'Shade' => 'Schatten', + 'Tungsten' => 'Glühbirne', + }, + }, + 'PresetWhiteBalanceAdj' => 'Weißabgleichkorrektur-Einstellung', + 'Preview' => 'Preview-IFD-Zeiger', + 'Preview0' => 'Vorschau 0', + 'Preview1' => 'Vorschau 1', + 'Preview2' => 'Vorschau 2', + 'PreviewColorSpace' => { + PrintConv => { + 'Unknown' => 'Unbekannt', + }, + }, + 'PreviewCropBottom' => 'Vorschau Ausschnitt Unten', + 'PreviewCropLeft' => 'Vorschau Ausschnitt Links', + 'PreviewCropRight' => 'Vorschau Ausschnitt Rechts', + 'PreviewCropTop' => 'Vorschau Ausschnitt Oben', + 'PreviewIFD' => 'Preview-IFD-Zeiger', + 'PreviewImage' => 'Vorschaubild', + 'PreviewImageBorders' => 'Vorschaubild-Ränder', + 'PreviewImageData' => 'Vorschaubild-Daten', + 'PreviewImageHeight' => 'Vorschaubild-Höhe', + 'PreviewImageLength' => 'Vorschaubild-Datenlänge', + 'PreviewImageName' => 'Vorschaubild-Name', + 'PreviewImageSize' => 'Vorschaubild-Größe', + 'PreviewImageStart' => 'Vorschaubild-Datenposition', + 'PreviewImageType' => 'Vorschaubild-Typ', + 'PreviewImageValid' => { + Description => 'Vorschaubild gültig', + PrintConv => { + 'No' => 'Nein', + 'Yes' => 'Ja', + }, + }, + 'PreviewImageWidth' => 'Vorschaubild-Breite', + 'PreviewPNG' => 'PNG Vorschaubild', + 'PreviewQuality' => { + Description => 'Vorschaubild-Qualität', + PrintConv => { + 'Fine' => 'Fein', + 'Superfine' => 'Superfein', + 'n/a' => '(nicht gesetzt)', + }, + }, + 'PreviewSettingsDigest' => 'Kennwert der Voreinstellungen', + 'PreviewWMF' => 'WMF Vorschaubild', + 'PrimaryAFPoint' => { + Description => 'Primärer AF-Punkt', + PrintConv => { + '(none)' => '(keiner)', + 'Bottom' => 'Unten', + 'C6 (Center)' => 'C6 (Mitte)', + 'Center' => 'Mitte', + 'Far Left' => 'Weit links', + 'Far Right' => 'Weit rechts', + 'Lower-left' => 'Links unten', + 'Lower-right' => 'Rechts unten', + 'Mid-left' => 'Links mitte', + 'Mid-right' => 'Rechts mitte', + 'Top' => 'Oben', + 'Upper-left' => 'Links oben', + 'Upper-right' => 'Rechts oben', + }, + }, + 'PrimaryChromaticities' => 'Chromatizität der Primärfarben', + 'PrimaryPlatform' => 'Hauptplattform', + 'ProcessingInfo' => 'Verarbeitungsinformationen', + 'ProcessingSoftware' => 'Verarbeitungssoftware', + 'Producer' => 'Produzent', + 'ProducerKeywords' => 'Hersteller Schlüsselwörter', + 'Producers' => 'Produzent', + 'ProductID' => 'Produkt-ID', + 'ProductionCode' => 'Herstellungskennzeichen', + 'ProfileCMMType' => 'Profil CMM-Typ', + 'ProfileClass' => { + Description => 'Profil-Klasse', + PrintConv => { + 'Abstract Profile' => 'Abstract-Profil', + 'ColorSpace Conversion Profile' => 'Farbraum-Konvertierungsprofile', + 'DeviceLink Profile' => 'DeviceLink-Profil', + 'Display Device Profile' => 'Bildschirm-Geräteprofil', + 'Input Device Profile' => 'Eingabe-Geräteprofil', + 'NamedColor Profile' => 'Named Color-Profil', + 'Nikon Input Device Profile (NON-STANDARD!)' => 'Nikon-Profil ("nkpf")', + 'Output Device Profile' => 'Ausgabe-Geräteprofil', + }, + }, + 'ProfileConnectionSpace' => 'Profil-Verbindungsfarbraum', + 'ProfileCopyright' => 'Urheberrechtsvermerk', + 'ProfileCreator' => 'Profilersteller', + 'ProfileDateTime' => 'Profil-Erstellungszeit', + 'ProfileDescription' => 'Farbprofil Name', + 'ProfileDescriptionML' => 'Farbprofil Name mehrsprachig', + 'ProfileFileSignature' => 'Profil-Datei-Signatur', + 'ProfileID' => 'Profile-ID', + 'ProfileSequenceDesc' => 'Profilsequenz-Beschreibung', + 'ProfileToneCurve' => 'Tonwertkurve Profil', + 'ProfileType' => { + Description => 'Profiltyp', + PrintConv => { + 'Group 3 FAX' => 'Gruppe 3 Fax', + 'Unspecified' => 'Nicht bekannt', + }, + }, + 'ProfileVersion' => 'Profil-Version', + 'ProgramISO' => { + Description => 'ISO Programm', + PrintConv => { + 'Intelligent ISO' => 'ISO intelligent', + 'n/a' => '(nicht gesetzt)', + }, + }, + 'ProgramLine' => { + Description => 'Belichtungsprogrammtyp', + PrintConv => { + 'Depth' => 'Schärfentiefe-Priorität', + 'Hi Speed' => 'HS-Priorität', + 'MTF' => 'MTF-Priorität', + }, + }, + 'ProgramMode' => { + Description => 'Programmmodus', + PrintConv => { + 'Night Portrait' => 'Nachtporträt', + 'None' => 'Keiner', + 'Portrait' => 'Porträt', + 'Sports' => 'Sport', + 'Sunset' => 'Sonnenuntergang', + }, + }, + 'ProgramShift' => 'Programmverschiebung', + 'ProgramVersion' => 'Programmversion', + 'Prohibits' => { + Description => 'Verbote', + PrintConv => { + 'Commercial Use' => 'Kommerzielle Verwendung', + }, + }, + 'Protect' => 'Schutz', + 'Province-State' => 'Bundesland/Kanton', + 'Publisher' => 'Herausgeber', + 'Quality' => { + Description => 'Bildqualität', + PrintConv => { + 'Best' => 'Optimal', + 'Better' => 'Besser', + 'Compressed RAW' => 'Komprimiertes RAW', + 'Compressed RAW + JPEG' => 'Komprimiertes RAW + JPEG', + 'Extra Fine' => 'Extra-Fein', + 'Fine' => 'Fein', + 'Good' => 'Gut', + 'High' => 'Hoch', + 'Low' => 'Leicht', + 'Normal' => 'Standardqualität', + 'RAW + JPEG' => 'RAW+JPEG', + 'Super Fine' => 'Super-Fein', + 'Superfine' => 'Superfein', + 'n/a' => '(nicht gesetzt)', + }, + }, + 'QualityMode' => { + PrintConv => { + 'Fine' => 'Fein', + }, + }, + 'QuickAdjust' => 'Schnelleinstellung', + 'QuickControlDialInMeter' => { + Description => 'Schnelleinstellrad bei Messung', + PrintConv => { + 'AF point selection' => 'Auswahl des AF-Messfelds', + 'Exposure comp/Aperture' => 'Belichtungskorrektur/Blende', + 'ISO speed' => 'ISO-Empfindlichkeit', + }, + }, + 'QuickShot' => { + PrintConv => { + 'Off' => 'Aus', + 'On' => 'Ein', + }, + }, + 'RAFVersion' => 'RAF-Version', + 'RasterizedCaption' => 'Rasterbeschreibung', + 'Rating' => 'Bewertung', + 'RatingPercent' => 'Bewertung in Prozent', + 'RawAndJpgRecording' => { + Description => 'Dateiformat und JPEG-Qualität', + PrintConv => { + 'JPEG (Best)' => 'JPEG (Optimal)', + 'JPEG (Better)' => 'JPEG (Besser)', + 'JPEG (Good)' => 'JPEG (Gut)', + 'RAW (DNG, Best)' => 'RAW (DNG, Optimal)', + 'RAW (DNG, Better)' => 'RAW (DNG, Besser)', + 'RAW (DNG, Good)' => 'RAW (DNG, Gut)', + 'RAW (PEF, Best)' => 'RAW (PEF, Optimal)', + 'RAW (PEF, Better)' => 'RAW (PEF, Besser)', + 'RAW (PEF, Good)' => 'RAW (PEF, Gut)', + 'RAW+JPEG (DNG, Best)' => 'RAW+JPEG (DNG, Optimal)', + 'RAW+JPEG (DNG, Better)' => 'RAW+JPEG (DNG, Besser)', + 'RAW+JPEG (DNG, Good)' => 'RAW+JPEG (DNG, Gut)', + 'RAW+JPEG (PEF, Best)' => 'RAW+JPEG (PEF, Optimal)', + 'RAW+JPEG (PEF, Better)' => 'RAW+JPEG (PEF, Besser)', + 'RAW+JPEG (PEF, Good)' => 'RAW+JPEG (PEF, Gut)', + 'RAW+Large/Fine' => 'RAW+Groß/Fein', + 'RAW+Large/Normal' => 'RAW+Groß/Normal', + 'RAW+Medium/Fine' => 'RAW+Mittel/Fein', + 'RAW+Medium/Normal' => 'RAW+Mittel/Normal', + 'RAW+Small/Fine' => 'RAW+Klein/Fein', + 'RAW+Small/Normal' => 'RAW+Klein/Normal', + }, + }, + 'RawBrightnessAdj' => 'Raw Helligkeitskorrektur', + 'RawColorAdj' => { + Description => 'Raw Farbkorrektur', + PrintConv => { + 'Custom' => 'Benutzerdefiniert', + 'Faithful' => 'Natürlich', + 'Shot Settings' => 'Aufnahmeeinstellung', + }, + }, + 'RawCropBottom' => 'Raw Ausschnitt Unten', + 'RawCropLeft' => 'Raw Ausschnitt Links', + 'RawCropRight' => 'Raw Ausschnitt Rechts', + 'RawCropTop' => 'Raw Ausschnitt Oben', + 'RawData' => 'Raw-Daten', + 'RawDataByteOrder' => 'RAW Daten Bytereihenfolge', + 'RawDataLength' => 'RAW-Daten Länge', + 'RawDataOffset' => 'RAW-Daten Offset', + 'RawDataUniqueID' => 'Raw-Daten eindeutige ID', + 'RawDevArtFilter' => { + PrintConv => { + 'Drawing' => 'Zeichnung', + 'Fish Eye' => 'Fischauge', + 'Off' => 'Aus', + 'Reflection' => 'Reflektierung', + 'Soft Focus' => 'Weichzeichner', + 'Soft Focus 2' => 'Weichzeichner 2', + 'Sparkle' => 'Perleffekt', + 'Watercolor' => 'Wasserfarbe', + 'Watercolor II' => 'Wasserfarbe II', + }, + }, + 'RawDevAutoGradation' => { + PrintConv => { + 'Off' => 'Aus', + 'On' => 'Ein', + }, + }, + 'RawDevNoiseReduction' => { + Description => 'RAW Rauschunterdrückung', + PrintConv => { + 'Noise Filter' => 'Rauschfilter', + 'Noise Filter (ISO Boost)' => 'Rauschfilter (ISO Boost)', + 'Noise Reduction' => 'Rauschreduktion', + }, + }, + 'RawDevPMPictureTone' => { + PrintConv => { + 'Blue' => 'Blau', + 'Green' => 'Grün', + 'Purple' => 'Lila', + }, + }, + 'RawDevPM_BWFilter' => { + PrintConv => { + 'Green' => 'Grün', + 'Red' => 'Rot', + 'Yellow' => 'Gelb', + }, + }, + 'RawDevPictureMode' => { + PrintConv => { + 'Natural' => 'Natürlich', + }, + }, + 'RawDevWhiteBalance' => { + PrintConv => { + 'Color Temperature' => 'Farbtemperatur', + }, + }, + 'RawFile' => 'RAW Datei', + 'RawFileName' => 'RAW Dateiname', + 'RawImageCenter' => 'RAW-Bildmitte', + 'RawImageDigest' => 'RAW Image Kennwert', + 'RawImageHeight' => 'Raw Bildhöhe', + 'RawImageSegmentation' => 'Raw Bild Aufteilung', + 'RawImageSize' => 'RAW-Bildgröße', + 'RawImageWidth' => 'Raw Bildbreite', + 'RawInfoVersion' => 'RawInfo Version', + 'RawJpgQuality' => { + Description => 'RAW JPEG-Qualität', + PrintConv => { + 'Fine' => 'Fein', + 'Superfine' => 'Superfein', + 'n/a' => '(nicht gesetzt)', + }, + }, + 'RawJpgSize' => { + Description => 'RAW JPEG-Größe', + PrintConv => { + 'Large' => 'Groß', + 'Medium' => 'Mittelgroß', + 'Medium 1' => 'Mittelgroß 1', + 'Medium 2' => 'Mittelgroß 2', + 'Medium 3' => 'Mittelgroß 3', + 'Medium Movie' => 'Mittelgroßer Film', + 'Postcard' => 'Postkarte', + 'Small' => 'Klein', + 'Small Movie' => 'Kleiner Film', + 'Widescreen' => 'Breitbild', + }, + }, + 'RawMeasuredRGGB' => 'Raw Messung RGGB', + 'RecognizedFace1Age' => 'Alter erkanntes Gesicht 1', + 'RecognizedFace1Name' => 'Name erkanntes Gesicht 1', + 'RecognizedFace1Position' => 'Position erkanntes Gesicht 1', + 'RecognizedFace2Age' => 'Alter erkanntes Gesicht 2', + 'RecognizedFace2Name' => 'Name erkanntes Gesicht 2', + 'RecognizedFace2Position' => 'Position erkanntes Gesicht 2', + 'RecognizedFace3Age' => 'Alter erkanntes Gesicht 3', + 'RecognizedFace3Name' => 'Name erkanntes Gesicht 3', + 'RecognizedFace3Position' => 'Position erkanntes Gesicht 3', + 'RecordMode' => { + Description => 'Aufzeichnungsmodus', + PrintConv => { + 'Aperture Priority' => 'Blendenpriorität', + 'Manual' => 'Manuell', + 'Shutter Priority' => 'Verschlusspriorität', + }, + }, + 'RecordingMode' => { + PrintConv => { + 'Auto' => 'Automatisch', + 'Landscape' => 'Landschaft', + 'Manual' => 'Manuell', + 'Night Scene' => 'Nachtszene', + 'Portrait' => 'Porträt', + }, + }, + 'RedAdjust' => 'Rot-Korrektur', + 'RedBalance' => 'Farbabgleich Rot', + 'RedEyeCorrection' => { + Description => 'Rote-Augen-Reduzierung', + PrintConv => { + 'Automatic' => 'Automatisch', + 'Click on Eyes' => 'Klick auf Augen', + 'Off' => 'Aus', + }, + }, + 'RedEyeReduction' => { + Description => 'Rote Augen Reduzierung', + PrintConv => { + 'Off' => 'Aus', + 'On' => 'Ein', + }, + }, + 'RedMatrixColumn' => 'Rot-Matrixspalte', + 'RedSaturation' => 'Farbsättingung Rot', + 'RedTRC' => 'Rot-Tonwertwiedergabe-Kurve', + 'RedX' => 'Rotpunkt X', + 'RedY' => 'Rotpunkt Y', + 'ReductionMatrix1' => 'Reduktionsmatrix 1', + 'ReductionMatrix2' => 'Reduktionsmatrix 2', + 'ReferenceBlackWhite' => 'Schwarz-Weiß-Referenzpunkte', + 'ReferenceDate' => 'Referenzdatum', + 'ReferenceNumber' => 'Referenznummer', + 'ReferenceService' => 'Referenzdienst', + 'References' => 'Verweise', + 'RelatedImageFileFormat' => 'Dateiformat der Bilddaten', + 'RelatedImageHeight' => 'Bildhöhe', + 'RelatedImageWidth' => 'Bildbreite', + 'RelatedSoundFile' => 'Zugehörige Audio-Datei', + 'ReleaseButtonToUseDial' => { + Description => 'Tastenverhalten', + PrintConv => { + 'No' => 'Gedrückt halten', + 'Yes' => 'Ein & aus', + }, + }, + 'ReleaseDate' => 'Veröffentlichungsdatum', + 'ReleaseMode' => { + Description => 'Auslösemodus', + PrintConv => { + 'AE Bracketing' => 'Belichtungsreihe', + 'Contrast Bracketing' => 'Kontrast Belichtungsreihe', + 'High Speed Burst' => 'Aufnahme Burst', + 'WB Bracketing' => 'Weißabgleich-Belichtungsreihe', + 'n/a' => '(nicht gesetzt)', + }, + }, + 'ReleaseTime' => 'Veröffentlichungszeit', + 'RemoteOnDuration' => 'Fernauslöser', + 'RenderingIntent' => { + Description => 'Umrechnungsmethode', + PrintConv => { + 'ICC-Absolute Colorimetric' => 'Absolut farbmetrisch', + 'Media-Relative Colorimetric' => 'Relativ farbmetrisch', + 'Perceptual' => 'Wahrnehmungsorientiert (perzeptiv, fotografisch)', + 'Saturation' => 'Sättigungserhaltend', + }, + }, + 'RepeatingFlashCount' => 'Stroboskopblitz Anzahl', + 'RepeatingFlashOutput' => 'Stroboskopblitz Leistung', + 'RepeatingFlashRate' => 'Stroboskopblitz Freq.', + 'ResampleParamsQuality' => { + PrintConv => { + 'High' => 'Hoch', + 'Low' => 'Leicht', + }, + }, + 'Resaved' => { + PrintConv => { + 'No' => 'Nein', + 'Yes' => 'Ja', + }, + }, + 'Resolution' => 'Bildauflösung', + 'ResolutionUnit' => { + Description => 'Einheit der X- und Y-Auflösung', + PrintConv => { + 'None' => 'Keine', + 'inches' => 'Zoll', + }, + }, + 'RetouchHistory' => { + Description => 'Bildbearbeitungsschritte', + PrintConv => { + 'B & W' => 'Schwarz/Weiß', + 'Color Custom' => 'Farbabgleich', + 'Cyanotype' => 'Blauton', + 'Distortion Control' => 'Verzeichnungskontrolle', + 'Fisheye' => 'Fischauge', + 'Image Overlay' => 'Bildmontage', + 'None' => 'Keine', + 'Perspective Control' => 'Perspektivenkontrolle', + 'Red Eye' => 'Rote-Augen-Korrektur', + 'Sky Light' => 'Skylight', + 'Small Picture' => 'Kompaktbild', + 'Soft Filter' => 'Weichzeichner', + 'Trim' => 'Beschneiden', + 'Warm Tone' => 'Warmer Farbton', + }, + }, + 'ReverseIndicators' => 'Skalen spiegeln', + 'ReverseShutterSpeedAperture' => { + PrintConv => { + 'No' => 'Nein', + 'Yes' => 'Ja', + }, + }, + 'RevisionDate' => 'Revisionsdatum', + 'RevisionNumber' => 'Revisionsnummer', + 'RicohDate' => 'Ricoh Datum', + 'RicohImageHeight' => 'Ricoh-Bildhöhe', + 'RicohImageWidth' => 'Ricoh-Bildbreite', + 'Rights' => 'Rechte', + 'Rotation' => { + Description => 'Ausrichtung', + PrintConv => { + 'Horizontal (Normal)' => 'Horizontal (normal)', + 'Rotate 180' => '180° gedreht', + 'Rotate 270 CW' => '90° gegen den Uhrzeigersinn', + 'Rotate 90 CW' => '90° im Uhrzeigersinn', + 'Rotated 180' => '180° gedreht', + 'Rotated 270 CW' => '90° gegen den Uhrzeigersinn', + 'Rotated 90 CW' => '90° im Uhrzeigersinn', + }, + }, + 'RowsPerStrip' => 'Anzahl der Bild-Zeilen', + 'SPIFFVersion' => 'SPIFF-Version', + 'SRAWQuality' => { + Description => 'SRAW Qualität', + PrintConv => { + 'n/a' => '(nicht gesetzt)', + }, + }, + 'SRActive' => { + Description => 'Bildstabilisator', + PrintConv => { + 'No' => 'Deaktiviert', + 'Yes' => 'Aktiviert', + }, + }, + 'SRFocalLength' => 'SR Brennweite', + 'SRHalfPressTime' => 'Auslöseverzögerung', + 'SRResult' => { + Description => 'Bildstabilisator', + PrintConv => { + 'Not stabilized' => 'Nicht stabilisiert', + }, + }, + 'SVGVersion' => 'SVG-Version', + 'SafetyShift' => { + PrintConv => { + 'Disable' => 'Nicht möglich', + 'Enable (ISO speed)' => 'Möglich (ISO Empfindlichkeit)', + 'Enable (Tv/Av)' => 'Möglich (Tv/Av)', + }, + }, + 'SafetyShiftInAvOrTv' => { + Description => 'Safety Shift in AV oder TV', + PrintConv => { + 'Disable' => 'Nicht möglich', + 'Enable' => 'Möglich', + }, + }, + 'SampleFormat' => { + PrintConv => { + 'Complex int' => 'Komplexer Integer', + 'Float' => 'Fließkommawert', + 'Signed' => 'Vorzeichenbehafteter Integer', + 'Undefined' => 'Nicht definiert', + 'Unsigned' => 'Vorzeichenloser Integer', + }, + }, + 'SamplesPerPixel' => 'Anzahl der Komponenten', + 'Saturation' => { + Description => 'Farbsättigung', + PrintConv => { + '+1 (medium high)' => '+1 (Leicht erhöht)', + '+2 (high)' => '+2 (Hohe Farbsättigung)', + '+3 (very high)' => '+3 (Sehr hoch)', + '+4 (highest)' => '+4', + '+4 (maximum)' => '+4', + '-1 (medium low)' => '-1 (Leicht verringert)', + '-2 (low)' => '-2 (Geringe Farbsättigung)', + '-3 (very low)' => '-3 (Sehr gering)', + '-4 (lowest)' => '-4', + '-4 (minimum)' => '-4', + '0 (normal)' => '0 (Normal)', + 'B&W' => 'Schwarz/Weiß', + 'B&W Green Filter' => 'Schwarz-Weiß Grünfilter', + 'B&W Red Filter' => 'Schwarz-Weiß Rotfilter', + 'B&W Sepia' => 'Schwarz-Weiß Sepia', + 'B&W Yellow Filter' => 'Schwarz-Weiß Gelbfilter', + 'Black & White' => 'Schwarz/Weiß', + 'Film Simulation' => 'Film-Simulation', + 'High' => 'Hohe Farbsättigung', + 'Low' => 'Geringe Farbsättigung', + 'Medium High' => 'Mittel-Hoch', + 'Medium Low' => 'Mittel-Gering', + 'Natural' => 'Natürlich', + 'None' => 'Nicht gesetzt', + 'None (B&W)' => 'Keine (S&W)', + 'Toning Effect' => 'Tönungseffekt', + 'Vintage B&W' => 'Vintage Schwarz-Weiß', + 'Vivid' => 'Lebhaft', + }, + }, + 'SaturationAdj' => 'Sättigungskorrektur', + 'SaturationAdjustmentAqua' => 'Farbsättigung Korrektur Cyan', + 'SaturationAdjustmentBlue' => 'Farbsättigung Korrektur Blau', + 'SaturationAdjustmentGreen' => 'Farbsättigung Korrektur Grün', + 'SaturationAdjustmentMagenta' => 'Farbsättigung Korrektur Magenta', + 'SaturationAdjustmentOrange' => 'Farbsättigung Korrektur Orange', + 'SaturationAdjustmentPurple' => 'Farbsättigung Korrektur Lila', + 'SaturationAdjustmentRed' => 'Farbsättigung Korrektur Rot', + 'SaturationAdjustmentYellow' => 'Farbsättigung Korrektur Gelb', + 'SaturationFaithful' => { + Description => 'Farbsättigung Natürlich', + PrintConv => { + 'n/a' => '(nicht gesetzt)', + }, + }, + 'SaturationInfo' => 'Farbsättigung', + 'SaturationLandscape' => { + Description => 'Farbsättigung Landschaft', + PrintConv => { + 'n/a' => '(nicht gesetzt)', + }, + }, + 'SaturationMonochrome' => { + PrintConv => { + 'n/a' => '(nicht gesetzt)', + }, + }, + 'SaturationNeutral' => { + Description => 'Farbsättigung Neutral', + PrintConv => { + 'n/a' => '(nicht gesetzt)', + }, + }, + 'SaturationPlanes' => 'Sättigungsebenen', + 'SaturationPortrait' => { + Description => 'Farbsättigung Porträt', + PrintConv => { + 'n/a' => '(nicht gesetzt)', + }, + }, + 'SaturationSetting' => 'Sättigungseinstellung', + 'SaturationStandard' => { + Description => 'Farbsättigung Standard', + PrintConv => { + 'n/a' => '(nicht gesetzt)', + }, + }, + 'SaturationUnknown' => { + PrintConv => { + 'n/a' => '(nicht gesetzt)', + }, + }, + 'SaturationUserDef1' => { + Description => 'Farbsättigung Benutzerdefiniert 1', + PrintConv => { + 'n/a' => '(nicht gesetzt)', + }, + }, + 'SaturationUserDef2' => { + Description => 'Farbsättigung Benutzerdefiniert 2', + PrintConv => { + 'n/a' => '(nicht gesetzt)', + }, + }, + 'SaturationUserDef3' => { + Description => 'Farbsättigung Benutzerdefiniert 3', + PrintConv => { + 'n/a' => '(nicht gesetzt)', + }, + }, + 'ScaleFactor35efl' => 'Formatfaktor zu 35 mm', + 'ScanImageEnhancer' => { + PrintConv => { + 'Off' => 'Aus', + 'On' => 'Ein', + }, + }, + 'Scene' => 'Szene', + 'SceneAssist' => 'Szenen-Assistent', + 'SceneCaptureType' => { + Description => 'Szenenaufnahmetyp', + PrintConv => { + 'Landscape' => 'Landschaft', + 'Night' => 'Nachtszene', + 'Portrait' => 'Porträt', + }, + }, + 'SceneMode' => { + Description => 'Szenen-Modus', + PrintConv => { + '3D Sweep Panorama' => '3D Sweep-Panorama', + 'Anti Motion Blur' => 'Verwackelungsschutz', + 'Aperture Priority' => 'Blendenpriorität', + 'Auto' => 'Automatisch', + 'Available Light' => 'Verfügbares Licht', + 'Baby' => 'Kleinkind', + 'Beach' => 'Strand', + 'Beach & Snow' => 'Strand & Schnee', + 'Behind Glass' => 'Hinterglas', + 'Candle' => 'Kerzenlicht', + 'Candlelight' => 'Kerzenlicht', + 'Children' => 'Kinder', + 'Color Effects' => 'Farbeffekte', + 'Cont. Priority AE' => 'Andauernde AE Priorität', + 'Creative Control' => 'Kreativprogramm', + 'Digital Filter' => 'Digitaler Filter', + 'Documents' => 'Dokumente', + 'Fireworks' => 'Feuerwerk', + 'Food' => 'Lebensmittel', + 'Handheld Night Shot' => 'Nachtaufnahme händisch', + 'High Key' => 'High-Key', + 'High Sensitivity' => 'Hohe Empfindlichkeit', + 'Indoor' => 'Innenaufnahme', + 'Intelligent ISO' => 'Iso Intelligent', + 'Landscape' => 'Landschaft', + 'Landscape+Portrait' => 'Landschaft+Porträt', + 'Low Key' => 'Low-Key', + 'Macro' => 'Makro', + 'Manual' => 'Manuell', + 'My Mode' => 'Benutzerdefiniert', + 'Night Landscape' => 'Landschaft bei Nacht', + 'Night Portrait' => 'Nachtporträt', + 'Night Scene' => 'Nachtszene', + 'Night Scenery' => 'Nachtszene', + 'Night View/Portrait' => 'Abendszene/Porträt', + 'Night+Portrait' => 'Nacht+Porträt', + 'Off' => 'Aus', + 'Pet' => 'Haustiere', + 'Portrait' => 'Porträt', + 'Program' => 'Programm', + 'Self Portrait' => 'Selbstporträt', + 'Self Portrait+Self Timer' => 'Selbstporträt+Selbstauslöser', + 'Shutter Priority' => 'Verschlusspriorität', + 'Snow' => 'Schnee', + 'Sports' => 'Sport', + 'Spot' => 'Spotmessung', + 'Starry Night' => 'Sternennacht', + 'Sunset' => 'Sonnenuntergang', + 'Super Macro' => 'Super-Makro', + 'Sweep Panorama' => 'Sweep-Panorama', + 'Underwater' => 'Unterwasser', + 'Underwater Macro' => 'Unterwasser Makro', + 'Underwater Wide1' => 'Unterwasserlandschaft', + 'Underwater Wide2' => 'Unterwasserlandschaft 2', + 'n/a' => '(nicht gesetzt)', + }, + }, + 'SceneModeUsed' => { + Description => 'Szenen-Modus', + PrintConv => { + 'Aperture Priority' => 'Blendenpriorität', + 'Beach' => 'Strand', + 'Candlelight' => 'Kerzenlicht', + 'Children' => 'Kinder', + 'Fireworks' => 'Feuerwerk', + 'Landscape' => 'Landschaft', + 'Macro' => 'Makro', + 'Manual' => 'Manuell', + 'Night Landscape' => 'Landschaft bei Nacht', + 'Night Portrait' => 'Nachtporträt', + 'Portrait' => 'Porträt', + 'Program' => 'Programm', + 'Shutter Priority' => 'Verschlusspriorität', + 'Snow' => 'Schnee', + 'Sunset' => 'Sonnenuntergang', + }, + }, + 'SceneSelect' => { + PrintConv => { + 'Night' => 'Nachtszene', + 'Off' => 'Aus', + }, + }, + 'SceneType' => { + Description => 'Szenentyp', + PrintConv => { + 'Directly photographed' => 'Direkt aufgenommenes Bild', + }, + }, + 'Security' => { + Description => 'Sicherheit', + PrintConv => { + 'Locked for annotations' => 'Gesperrt für Anmerkungen', + 'None' => 'Keine', + 'Password protected' => 'Passwort geschützt', + 'Read-only enforced' => 'Nur Lesen - erzwungen', + 'Read-only recommended' => 'Nur Lesen - vorgeschlagen', + }, + }, + 'SecurityClassification' => { + Description => 'Sicherheitsklassifizierung', + PrintConv => { + 'Confidential' => 'Vertraulich', + 'Restricted' => 'Eingeschränkt', + 'Secret' => 'Geheim', + 'Top Secret' => 'Streng geheim', + 'Unclassified' => 'Nicht klassifiziert', + }, + }, + 'SelectAFAreaSelectMode' => { + Description => 'AF-Bereich Auswahlmodus', + PrintConv => { + 'Disable' => 'Deaktiviert', + 'Enable' => 'Aktiviert', + 'Select AF-modes' => 'Wahl AF-Modus', + }, + }, + 'SelectableAFPoint' => { + Description => 'Wählbares AF-Feld', + PrintConv => { + '11 points' => '11 Felder', + '19 Points, Multi-controller selectable' => '19 Punkte, wählbar mit Multicontroller', + '19 points' => '19 Felder', + '45 points' => '45 Felder', + 'Inner 9 Points, Multi-controller selectable' => 'Innere 9 Punkte, wählbar mit Multicontroller', + 'Inner 9 points' => 'Innere 9 Felder', + 'Outer 9 Points, Multi-controller selectable' => 'Äußere 9 Punkte, wählbar mit Multicontroller', + 'Outer 9 points' => 'Äußere 9 Felder', + }, + }, + 'SelfTimer' => { + Description => 'Selbstauslöser', + PrintConv => { + '10 s / 3 pictures' => '10 s / 3 Bilder', + 'Off' => 'Aus', + 'On' => 'Ein', + }, + }, + 'SelfTimer2' => 'Selbstauslöser (2)', + 'SelfTimerMode' => 'Selbstauslösermodus', + 'SelfTimerTime' => 'Selbstauslöser-Vorlaufzeit', + 'SensingMethod' => { + Description => 'Messmethode', + PrintConv => { + 'Color sequential area' => 'Color-Sequential-Area-Sensor', + 'Color sequential linear' => 'Color-Sequential-Linear-Sensor', + 'Monochrome area' => 'Monochrom-Sensor', + 'Monochrome linear' => 'Monochrom-linearer Sensor', + 'Not defined' => 'Nicht definiert', + 'One-chip color area' => 'Ein-Chip-Farbsensor', + 'Three-chip color area' => 'Drei-Chip-Farbsensor', + 'Trilinear' => 'Trilinearer Sensor', + 'Two-chip color area' => 'Zwei-Chip-Farbsensor', + }, + }, + 'SensitivityAdjust' => 'ISO-Empfindlichkeitsanpassung', + 'SensitivitySteps' => { + Description => 'Empfindlichkeits-Schritte', + PrintConv => { + '1 EV Steps' => '1 LW-Schritte', + 'As EV Steps' => 'Wie LW-Schritte', + }, + }, + 'SensitivityType' => { + Description => 'Art der Empfindlichkeit', + PrintConv => { + 'ISO Speed' => 'ISO Empfindlichkeit', + 'Recommended Exposure Index' => 'Empfohlener Belichtungsindex', + 'Recommended Exposure Index and ISO Speed' => 'Empfohlener Belichtungsindex und ISO Empfindlichkeit', + 'Standard Output Sensitivity' => 'Standard Ausgabeempfindlichkeit', + 'Standard Output Sensitivity and ISO Speed' => 'Standard Ausgabeempfindlichkeit und ISO Empfindlichkeit', + 'Standard Output Sensitivity and Recommended Exposure Index' => 'Standard Ausgabeempfindlichkeit und empfohlener Belichtungsindex', + 'Standard Output Sensitivity, Recommended Exposure Index and ISO Speed' => 'Standard Ausgabeempfindlichkeit,empfohlener Belichtungsindex und ISO Empfindlichkeit', + 'Unknown' => 'Unbekannt', + }, + }, + 'SensorBlueLevel' => 'Sensor Blau-Level', + 'SensorBottomBorder' => 'Sensor unterer Rand', + 'SensorCleaning' => { + Description => 'Sensorreinigung', + PrintConv => { + 'Disable' => 'Nicht möglich', + 'Enable' => 'Möglich', + }, + }, + 'SensorHeight' => 'Sensor Höhe', + 'SensorImageHeight' => 'Sensor-Bildhöhe', + 'SensorImageWidth' => 'Sensor-Bildbreite', + 'SensorLeftBorder' => 'Sensor linker Rand', + 'SensorPixelSize' => 'Sensor-Pixelgröße', + 'SensorRedLevel' => 'Sensor Rot-Level', + 'SensorRightBorder' => 'Sensor rechter Rand', + 'SensorSize' => 'Sensorgröße', + 'SensorTemperature' => 'Sensor Temperatur', + 'SensorTopBorder' => 'Sensor oberer Rand', + 'SensorWidth' => 'Sensor Breite', + 'SequenceNumber' => { + Description => 'Bildsequenznummer', + PrintConv => { + 'n/a' => '(nicht gesetzt)', + }, + }, + 'SequentialShot' => { + Description => 'Reihenaufnahme', + PrintConv => { + 'Adjust Exposure' => 'Belichtungskorrektur', + 'Best' => 'Beste', + 'None' => 'Keine', + }, + }, + 'SerialNumber' => 'Seriennummer', + 'SerialNumberFormat' => 'Seriennummer-Format', + 'ServiceIdentifier' => 'Service-ID', + 'SetButtonCrossKeysFunc' => { + Description => 'SET Taste/Kreuztaste Funkt.', + PrintConv => { + 'Cross keys: AF point select' => 'Kreuztaste:AF Feld Auswahl', + 'Set: Flash Exposure Comp' => 'SET:Blitzbelichtungskorrektur', + 'Set: Parameter' => 'SET:Parameter ändern', + 'Set: Picture Style' => 'SET:Bildstil', + 'Set: Playback' => 'SET:Wiedergabe', + 'Set: Quality' => 'SET:Qualität', + }, + }, + 'SetButtonFunction' => 'Funktion SET-Taste b. Aufnahme', + 'SetButtonWhenShooting' => { + Description => 'SET-Taste bei Aufnahme', + PrintConv => { + 'Change ISO speed' => 'ISO-Wert ändern', + 'Change parameters' => 'Parameter ändern', + 'Default (no function)' => 'Normal (gesperrt)', + 'Disabled' => 'Gesperrt', + 'Flash exposure compensation' => 'Blitzbelichtungskorrektur', + 'ISO speed' => 'ISO-Empfindlichkeit', + 'Image playback' => 'Bildwiedergabe', + 'Image quality' => 'Qualität ändern', + 'Image size' => 'Bildgröße', + 'LCD monitor On/Off' => 'LCD-Monitor Ein/Aus', + 'Menu display' => 'Menüanzeige', + 'Normal (disabled)' => 'Normal (gesperrt)', + 'Picture style' => 'Bildstil', + 'Quick control screen' => 'Schnelleinstellung Bildschirm', + 'Record func. + media/folder' => 'Aufnahme-Funktion + Medium/Ordner', + 'Record movie (Live View)' => 'Movie-Aufnahme (Livebild)', + 'White balance' => 'Weißabgleich', + }, + }, + 'SetFunctionWhenShooting' => { + Description => 'SET-Taste bei Aufnahme', + PrintConv => { + 'Change Parameters' => 'Parameter ändern', + 'Change Picture Style' => 'Bildstil', + 'Change quality' => 'Qualität ändern', + 'Default (no function)' => 'Normal (gesperrt)', + 'Image replay' => 'Bildwiedergabe', + 'Menu display' => 'Menüanzeige', + }, + }, + 'ShadingCompensation' => { + Description => 'Schattenaufhellung', + PrintConv => { + 'Off' => 'Aus', + 'On' => 'Ein', + }, + }, + 'ShadingCompensation2' => { + Description => 'Schattenaufhellung 2', + PrintConv => { + 'Off' => 'Aus', + 'On' => 'Ein', + }, + }, + 'Shadow' => 'Schatten', + 'Shadows' => 'Schatten', + 'ShakeReduction' => { + Description => 'Bildstabilisator (Einstellung)', + PrintConv => { + 'Off' => 'Aus', + 'On' => 'Ein', + }, + }, + 'ShakeReductionInfo' => 'Bildstabilisator', + 'SharpenDetail' => 'Schärfungsdetail', + 'SharpenRadius' => 'Schärfungsradius', + 'Sharpening' => { + Description => 'Schärfung', + PrintConv => { + 'High' => 'Hoch', + 'Low' => 'Niedrig', + 'Medium High' => 'Mittel', + 'Off' => 'Aus', + }, + }, + 'SharpeningAdj' => 'Schärfekorrektur', + 'Sharpness' => { + Description => 'Schärfe', + PrintConv => { + '+1 (medium hard)' => '+1 (Leicht erhöht)', + '+2 (hard)' => '+2 (Stark)', + '+3 (very hard)' => '+3 (Sehr hoch)', + '+4 (hardest)' => '+4', + '+4 (maximum)' => '+4', + '-1 (medium soft)' => '-1 (Leicht verringert)', + '-2 (soft)' => '-2 (Leicht)', + '-3 (very soft)' => '-3 (Sehr weich)', + '-4 (minimum)' => '-4', + '-4 (softest)' => '-4', + '0 (normal)' => '0 (Normal)', + 'Film Simulation' => 'Film-Simulation', + 'Hard' => 'Stark', + 'Sharp' => 'Hart', + 'Soft' => 'Leicht', + 'n/a' => '(nicht gesetzt)', + }, + }, + 'SharpnessAdj' => 'Schärfekorrektur', + 'SharpnessFactor' => 'Schärfungsfaktor', + 'SharpnessFaithful' => { + Description => 'Schärfe Natürlich', + PrintConv => { + 'n/a' => '(nicht gesetzt)', + }, + }, + 'SharpnessFrequency' => { + PrintConv => { + 'High' => 'Hoch', + 'Highest' => 'Höchste', + 'Low' => 'Leicht', + 'n/a' => '(nicht gesetzt)', + }, + }, + 'SharpnessLandscape' => { + Description => 'Schärfe Landschaft', + PrintConv => { + 'n/a' => '(nicht gesetzt)', + }, + }, + 'SharpnessMonochrome' => { + Description => 'Schärfe Monochrom', + PrintConv => { + 'n/a' => '(nicht gesetzt)', + }, + }, + 'SharpnessNeutral' => { + Description => 'Schärfe Neutral', + PrintConv => { + 'n/a' => '(nicht gesetzt)', + }, + }, + 'SharpnessOvershoot' => 'Schärfe Grenzwertüberschreitung', + 'SharpnessPortrait' => { + Description => 'Schärfe Porträt', + PrintConv => { + 'n/a' => '(nicht gesetzt)', + }, + }, + 'SharpnessSetting' => 'Schärfeeinstellung', + 'SharpnessStandard' => { + Description => 'Schärfe Standard', + PrintConv => { + 'n/a' => '(nicht gesetzt)', + }, + }, + 'SharpnessTable' => 'Schärfe Tabelle', + 'SharpnessThreshold' => 'Schärfe Grenzwert', + 'SharpnessUndershoot' => 'Schärfe Grenzwertunterschreitung', + 'SharpnessUnknown' => { + PrintConv => { + 'n/a' => '(nicht gesetzt)', + }, + }, + 'SharpnessUserDef1' => { + Description => 'Schärfe Benutzerdefiniert 1', + PrintConv => { + 'n/a' => '(nicht gesetzt)', + }, + }, + 'SharpnessUserDef2' => { + Description => 'Schärfe Benutzerdefiniert 2', + PrintConv => { + 'n/a' => '(nicht gesetzt)', + }, + }, + 'SharpnessUserDef3' => { + Description => 'Schärfe Benutzerdefiniert 3', + PrintConv => { + 'n/a' => '(nicht gesetzt)', + }, + }, + 'ShootingInfoDisplay' => { + Description => 'Aufnahmeinfo-Ansicht', + PrintConv => { + 'Auto' => 'Automatisch', + 'Manual (dark on light)' => 'Manuell - Dunkel auf Hell', + 'Manual (light on dark)' => 'Manuell - Hell auf dunkel', + }, + }, + 'ShootingMode' => { + Description => 'Aufnahmemodus', + PrintConv => { + 'Aperture Priority' => 'Blendenpriorität', + 'Baby' => 'Kleinkind', + 'Beach' => 'Strand', + 'Candlelight' => 'Kerzenlicht', + 'Color Effects' => 'Farbeffekte', + 'Fireworks' => 'Feuerwerk', + 'Food' => 'Lebensmittel', + 'High Sensitivity' => 'Hohe Empfindlichkeit', + 'Macro' => 'Makro', + 'Manual' => 'Manuell', + 'Night Portrait' => 'Nachtporträt', + 'Night Scenery' => 'Nachtszene', + 'Pet' => 'Haustiere', + 'Portrait' => 'Porträt', + 'Program' => 'Programm', + 'Self Portrait' => 'Selbstportait', + 'Shutter Priority' => 'Verschlusspriorität', + 'Snow' => 'Schnee', + 'Sports' => 'Sport', + 'Spot' => 'Spotmessung', + 'Starry Night' => 'Sternennacht', + 'Sunset' => 'Sonnenuntergang', + 'Underwater' => 'Unterwasser', + }, + }, + 'ShootingModeSetting' => { + Description => 'Messfeldsteuerung', + PrintConv => { + 'Continuous' => 'Serienaufnahme', + 'Delayed Remote' => 'Fernauslöser m. Vorlauf', + 'Quick-response Remote' => 'Fernauslöser', + 'Self-timer' => 'Selbstauslöser', + 'Single Frame' => 'Einzelbild', + }, + }, + 'ShortDescription' => 'Kurzbeschreibung', + 'ShortDocumentID' => 'Kurze Bild-ID', + 'ShortReleaseTimeLag' => { + Description => 'Verkürzte Auslöseverzögerung', + PrintConv => { + 'Disable' => 'Ausgeschaltet', + 'Enable' => 'Eingeschaltet', + }, + }, + 'ShotInfoVersion' => 'Aufnahmeinfo-Version', + 'Shutter-AELock' => { + Description => 'Auslöser/AE-Speicherung', + PrintConv => { + 'AE lock/AF' => 'AE-Speicherung/AF', + 'AE/AF, No AE lock' => 'AE/AF, keine AE-Speicherung', + 'AF/AE lock' => 'AF/AE-Speicherung', + 'AF/AF lock' => 'AF/AF-Speicherung', + 'AF/AF lock, No AE lock' => 'AF/AF-Speicherung, keine AE-Speicherung', + }, + }, + 'ShutterAELButton' => 'Auslöser/AE-Speichertaste', + 'ShutterButtonAFOnButton' => { + Description => 'Auslöser/AF-Starttaste', + PrintConv => { + 'AE lock/Metering + AF start' => 'AESpeicherung/Messung+AFStart', + 'Metering + AF start' => 'Messung+AFStart', + 'Metering + AF start/AF stop' => 'Messung+AFStart / AFStopp', + 'Metering + AF start/disable' => 'Messung+AFStart/Deaktiviert', + 'Metering start/Meter + AF start' => 'Messung Start/Mess.+AFStart', + }, + }, + 'ShutterCount' => 'Anzahl der Auslösungen', + 'ShutterCurtainSync' => { + Description => 'Verschluss-Synchronisation', + PrintConv => { + '1st-curtain sync' => '1. Verschlussvorhang', + '2nd-curtain sync' => '2. Verschlussvorhang', + }, + }, + 'ShutterMode' => { + PrintConv => { + 'Aperture Priority' => 'Blendenpriorität', + 'Auto' => 'Automatisch', + }, + }, + 'ShutterReleaseButtonAE-L' => { + Description => 'Belichtungsspeicher', + PrintConv => { + 'Off' => 'Aus', + 'On' => 'Ein', + }, + }, + 'ShutterReleaseMethod' => { + PrintConv => { + 'Continuous Shooting' => 'Serienaufnahme', + 'Single Shot' => 'Einzelbild', + }, + }, + 'ShutterReleaseNoCFCard' => { + Description => 'Verschlussausl. ohne Karte', + PrintConv => { + 'No' => 'Nein', + 'Yes' => 'Ja', + }, + }, + 'ShutterReleaseTiming' => { + PrintConv => { + 'Priority on focus' => 'Schärfepriorität', + 'Priority on shutter' => 'Verschlußpriorität', + }, + }, + 'ShutterSpeed' => 'Belichtungsdauer', + 'ShutterSpeedDisplayed' => 'Angezeigte Belichtungszeit', + 'ShutterSpeedRange' => { + Description => 'Einstellung Blendenbereich', + PrintConv => { + 'Disable' => 'Nicht möglich', + 'Enable' => 'Möglich', + }, + }, + 'ShutterSpeedSetting' => 'Belichtungszeit Einstellung', + 'ShutterSpeedValue' => 'Belichtungszeit', + 'SimilarityIndex' => 'Bildgleichheits-Index', + 'SingleFrameBracketing' => { + Description => 'Einzelbild-Belichtungsreihe', + PrintConv => { + 'High' => 'Hoch', + 'Low' => 'Niedrig', + }, + }, + 'SlaveFlashMeteringSegments' => 'Slave-Blitz-Messfeld', + 'SlideShow' => { + PrintConv => { + 'No' => 'Nein', + 'Yes' => 'Ja', + }, + }, + 'SlowShutter' => { + Description => 'Langzeitbelichtungseinstellung', + PrintConv => { + 'Night Scene' => 'Nachtszene', + 'None' => 'Keine', + 'Off' => 'Aus', + 'On' => 'Ein', + 'n/a' => '(nicht gesetzt)', + }, + }, + 'SlowSync' => { + Description => 'Slow-Synchro', + PrintConv => { + 'Off' => 'Aus', + 'On' => 'Ein', + }, + }, + 'SoftSkinEffect' => { + PrintConv => { + 'n/a' => '(nicht gesetzt)', + }, + }, + 'SonyImageSize' => { + Description => 'Sony Bildgröße', + PrintConv => { + 'Large' => 'Groß', + 'Large (16:9)' => 'Groß (16:9)', + 'Large (3:2)' => 'Groß (3:2)', + 'Medium' => 'Mittel', + 'Medium (16:9)' => 'Mittel (16:9)', + 'Medium (3:2)' => 'Mittel (3:2)', + 'Small' => 'Klein', + 'Small (16:9)' => 'Klein (16:9)', + 'Small (3:2)' => 'Klein (3:2)', + }, + }, + 'Source' => 'Quelle', + 'SpatialFrequencyResponse' => 'Raumfrequenz-Antwort', + 'SpecialEffectMode' => { + Description => 'Spezialeffekte Modus', + PrintConv => { + 'Mist Removal' => 'Dunstentfernung', + 'Off' => 'Aus', + 'Vivid Landscape' => 'Lebende Landschaft', + }, + }, + 'SpecialEffectsOpticalFilter' => { + Description => 'Spezialeffekt Filter', + PrintConv => { + 'Colored' => 'Farbfilter', + 'Diffusion' => 'Diffusionsfilter', + 'Multi-image' => 'Mehrfachbildfilter', + 'None' => 'Keiner', + 'Polarizing' => 'Polarisationsfilter', + 'Split-field' => 'Splitfilter', + 'Star' => 'Sternenfilter', + }, + }, + 'SpecialInstructions' => 'Anweisungen', + 'SpecialMode' => 'Spezialmodus', + 'SpectralSensitivity' => 'Spektralempfindlichkeit', + 'SpotFocusPointX' => 'Spot-Fokuspunkt X', + 'SpotFocusPointY' => 'Spot-Fokuspunkt Y', + 'SpotMeterLinkToAFPoint' => { + Description => 'Spotmessung AF-Feld verknüpft', + PrintConv => { + 'Disable (use center AF point)' => 'Deaktiviert (zentrales AF-Feld)', + 'Enable (use active AF point)' => 'Aktiviert (aktives AF-Feld)', + }, + }, + 'SpotMeteringMode' => { + Description => 'Spot-Messmethode', + PrintConv => { + 'AF Point' => 'AF-Punkt', + 'Center' => 'Mitte', + }, + }, + 'State' => 'Bundesland/Kanton', + 'StereoMode' => 'Stereomodus', + 'StripByteCounts' => 'Anzahl Bytes pro komprimiertem Bildabschnitt', + 'StripOffsets' => 'Bilddatenposition', + 'Sub-location' => 'Ort des Motivs', + 'SubSecCreateDate' => 'Digitalisierungsdatum/-uhrzeit', + 'SubSecDateTimeOriginal' => 'Erstellungsdatum/-uhrzeit', + 'SubSecModifyDate' => 'Änderungsdatum', + 'SubSecTime' => 'Datum/Uhrzeit 1/100 Sekunden', + 'SubSecTimeDigitized' => 'Digitalisierungsdatum/-uhrzeit 1/100 Sekunden', + 'SubSecTimeOriginal' => 'Erstellungsdatum/-uhrzeit 1/100 Sekunden', + 'SubfileType' => { + Description => 'Unterdatei-Typ', + PrintConv => { + 'Alternate reduced-resolution image' => 'Alternatives Bild in reduzierter Auflösung', + 'Full-resolution Image' => 'Bild in voller Auflösung', + 'Reduced-resolution image' => 'Bild in reduzierter Auflösung', + 'Single page of multi-page image' => 'Einzelbild eines mehrseitigen Bildes', + 'Single page of multi-page reduced-resolution image' => 'Einzelbild eines mehrseitigen Bildes in reduzierter Auflösung', + 'TIFF-FX mixed raster content' => 'TIFF-FX gersteter Inhalt', + 'TIFF/IT final page' => 'TIFF/IT endgültige Seite', + 'Thumbnail image' => 'Miniaturbild', + 'Transparency mask' => 'Transparenzmaske', + 'Transparency mask of multi-page image' => 'Transparenzmaske eines mehrseitigen Bildes', + 'Transparency mask of reduced-resolution image' => 'Transparenzmaske eines Bildes in reduzierter Auflösung', + 'Transparency mask of reduced-resolution multi-page image' => 'Transparenzmaske eines mehrseitigen Bildes in reduzierter Auflösung', + }, + }, + 'SubimageColor' => { + PrintConv => { + 'Monochrome' => 'Monochrom', + }, + }, + 'Subject' => 'Themen/Schlüsselwörter', + 'SubjectArea' => 'Hauptobjektposition', + 'SubjectCode' => 'IPTC Themencode', + 'SubjectDistance' => 'Objektentfernung', + 'SubjectDistanceRange' => { + Description => 'Objektdistanzbereich', + PrintConv => { + 'Close' => 'Nahaufnahme', + 'Distant' => 'Fernaufnahme', + 'Macro' => 'Makro', + 'Unknown' => 'Unbekannt', + }, + }, + 'SubjectLocation' => 'Hauptobjektposition', + 'SubjectProgram' => { + Description => 'Szenenauswahl', + PrintConv => { + 'Night portrait' => 'Nachtporträt', + 'None' => 'Keine', + 'Portrait' => 'Porträt', + 'Sports action' => 'Sportereignis', + 'Sunset' => 'Sonnenuntergang', + }, + }, + 'SubjectReference' => 'Themencode', + 'SubjectUnits' => { + PrintConv => { + 'meters' => 'Meter', + 'radians' => 'Winkelgrade', + }, + }, + 'Subsystem' => { + PrintConv => { + 'Unknown' => 'Unbekannt', + }, + }, + 'SuperMacro' => { + Description => 'Super Makro', + PrintConv => { + 'Off' => 'Aus', + }, + }, + 'SuperimposedDisplay' => { + Description => 'Eingeblendete Anzeige', + PrintConv => { + 'Off' => 'Aus', + 'On' => 'Ein', + }, + }, + 'SupplementalCategories' => 'Zusätzliche Kategorien', + 'SvISOSetting' => 'Sv ISO-Einstellung', + 'SwitchToRegisteredAFPoint' => { + Description => 'Auf gesp. AF-Messf. schalten', + PrintConv => { + 'Disable' => 'Nicht möglich', + 'Enable' => 'Möglich', + 'Only while AEL is pressed' => 'Nur während AEL gedrückt', + 'Switch with multi-controller' => 'Wechseln mit Multicontroller', + }, + }, + 'T4Options' => 'Füllbits hinzugefügt', + 'T6Options' => 'T6 Optionen', + 'T82Options' => 'T82 Option', + 'TIFFPreview' => 'TIFF Vorschaubild', + 'TIFF_FXExtensions' => { + PrintConv => { + 'B&W JBIG2' => 'Schwarz-Weiß JBIG2', + }, + }, + 'TTL_DA_ADown' => 'Slave-Blitz-Messfeld 6', + 'TTL_DA_AUp' => 'Slave-Blitz-Messfeld 5', + 'TTL_DA_BDown' => 'Slave-Blitz-Messfeld 8', + 'TTL_DA_BUp' => 'Slave-Blitz-Messfeld 7', + 'Tagged' => { + PrintConv => { + 'No' => 'Nein', + 'Yes' => 'Ja', + }, + }, + 'TargetAperture' => 'Zielblendenwert', + 'TargetCompressionRatio' => 'Ziel-Komprimierungsrate', + 'TargetExposureTime' => 'Zielbelichtungszeit', + 'Technology' => { + Description => 'Technologie', + PrintConv => { + 'Active Matrix Display' => 'Aktives Matrix-Display', + 'Cathode Ray Tube Display' => 'Kathodenstrahlröhrenbildschirm', + 'Digital Camera' => 'Digitalkamera', + 'Dye Sublimation Printer' => 'Thermosublimationsdrucker', + 'Electrophotographic Printer' => 'Laserdrucker', + 'Electrostatic Printer' => 'Elektrostatischer Drucker', + 'Film Scanner' => 'Film-Scanner', + 'Film Writer' => 'Film-Writer', + 'Flexography' => 'Flexographie', + 'Gravure' => 'Gravur', + 'Ink Jet Printer' => 'Tintenstrahldrucker', + 'Offset Lithography' => 'Offset Lithographie', + 'Passive Matrix Display' => 'Passives Matrix-Display', + 'Photo CD' => 'Photo-CD', + 'Photo Image Setter' => 'Foto-Filmbelichter', + 'Photographic Paper Printer' => 'Fotopapierdrucker', + 'Projection Television' => 'Projektionsfernsehgerät', + 'Reflective Scanner' => 'Reflexionsscanner', + 'Thermal Wax Printer' => 'Thermowachsdrucker', + 'Video Camera' => 'Videokamera', + 'Video Monitor' => 'Video-Monitor', + }, + }, + 'Teleconverter' => { + Description => 'Telekonverter', + PrintConv => { + 'None' => 'Keiner', + }, + }, + 'TextEncoding' => { + PrintConv => { + 'n/a' => '(nicht gesetzt)', + }, + }, + 'TextStamp' => { + PrintConv => { + 'Off' => 'Aus', + 'On' => 'Ein', + }, + }, + 'ThumbnailFileName' => 'Miniaturbild-Dateiname', + 'ThumbnailFormat' => 'Miniaturbild-Format', + 'ThumbnailHeight' => 'Miniaturbild-Höhe', + 'ThumbnailImage' => 'Miniaturbild', + 'ThumbnailImageName' => 'Miniaturbild-Name', + 'ThumbnailImageSize' => 'Miniaturbild-Größe', + 'ThumbnailImageType' => 'Miniaturbild-Typ', + 'ThumbnailImageValidArea' => 'Gültiger Bereich des Miniaturbildes', + 'ThumbnailLength' => 'Miniaturbild-Datenlänge', + 'ThumbnailOffset' => 'Miniaturbild-Datenposition', + 'ThumbnailWidth' => 'Miniaturbild-Breite', + 'Time' => 'Zeit', + 'TimeCreated' => 'Erstellungszeit', + 'TimeScaleParamsQuality' => { + PrintConv => { + 'High' => 'Hoch', + 'Low' => 'Leicht', + }, + }, + 'TimeSent' => 'Absendezeit', + 'TimeSincePowerOn' => 'Einschaltdauer', + 'TimeStamp' => 'Zeitstempel', + 'TimeStamp1' => 'Zeitstempel (1)', + 'TimeZone' => 'Zeitzone', + 'TimeZoneCity' => { + Description => 'Zeitzone Stadt', + PrintConv => { + 'n/a' => '(nicht gesetzt)', + }, + }, + 'TimeZoneCode' => 'Zeitzonen-Code', + 'TimeZoneInfo' => 'Zeitzonen-Info', + 'TimeZoneOffset' => 'Zeitzonen-Offset', + 'TimerFunctionButton' => { + Description => 'Funktionstaste', + PrintConv => { + 'Auto Bracketing' => 'Belichtungsreihe', + 'ISO' => 'ISO-Empfindlichkeit', + 'Image Quality/Size' => 'Bildqualität/-größe', + 'Self-timer' => 'Selbstauslöser', + 'Shooting Mode' => 'Aufnahmebetriebsart', + 'White Balance' => 'Weißabgleich', + }, + }, + 'TimerLength' => { + Description => 'Intervalldauer für Timer', + PrintConv => { + 'Disable' => 'Nicht möglich', + 'Enable' => 'Möglich', + }, + }, + 'Title' => 'Titel', + 'ToneComp' => 'Tonwertkorrektur', + 'ToneCurve' => { + Description => 'Ton-Kurve', + PrintConv => { + 'Custom' => 'Benutzerdefiniert', + 'Manual' => 'Manuell', + }, + }, + 'ToneCurve1' => 'Tonwertkurve 1', + 'ToneCurve2' => 'Tonwertkurve 2', + 'ToneCurve3' => 'Tonwertkurve 3', + 'ToneCurve4' => 'Tonwertkurve 4', + 'ToneCurveActive' => { + Description => 'Tonwertkurve aktiv', + PrintConv => { + 'No' => 'Nein', + 'Yes' => 'Ja', + }, + }, + 'ToneCurveBlue' => 'Tonwertkurve Blau', + 'ToneCurveBlueX' => 'Tonwertkurve Blau X', + 'ToneCurveBlueY' => 'Tonwertkurve Blau Y', + 'ToneCurveBrightnessX' => 'Tonwertkurve Helligkeit X', + 'ToneCurveBrightnessY' => 'Tonwertkurve Helligkeit Y', + 'ToneCurveFileName' => 'Tonwertkurve Dateiname', + 'ToneCurveGreen' => 'Tonwertkurve Grün', + 'ToneCurveGreenX' => 'Tonwertkurve Grün X', + 'ToneCurveGreenY' => 'Tonwertkurve Grün Y', + 'ToneCurveInterpolation' => { + Description => 'Tonwertkurve Interpolation', + PrintConv => { + 'Curve' => 'Kurve', + 'Straight' => 'Gerade', + }, + }, + 'ToneCurveMatching' => 'Tonwertkurve Übereinstimmung', + 'ToneCurveMode' => { + Description => 'Tonwertkurve Modus', + PrintConv => { + 'Luminance' => 'Luminanz', + }, + }, + 'ToneCurveName' => { + Description => 'Tonwertkurve Name', + PrintConv => { + 'Custom' => 'Benutzerdefiniert', + 'Medium Contrast' => 'Kontrast mittel', + 'Strong Contrast' => 'Kontrast stark', + }, + }, + 'ToneCurveName2012' => 'Tonwertkurve Name 2012', + 'ToneCurvePV2012' => 'Tonwertkurve PV2012', + 'ToneCurvePV2012Blue' => 'Tonwertkurve PV2012 Blau', + 'ToneCurvePV2012Green' => 'Tonwertkurve PV2012 Grün', + 'ToneCurvePV2012Red' => 'Tonwertkurve PV2012 Rot', + 'ToneCurveProperty' => { + Description => 'Tonwertkurve Eigenschaft', + PrintConv => { + 'Custom 1' => 'Benutzerdefiniert 1', + 'Custom 2' => 'Benutzerdefiniert 2', + 'Custom 3' => 'Benutzerdefiniert 3', + 'Custom 4' => 'Benutzerdefiniert 4', + 'Custom 5' => 'Benutzerdefiniert 5', + 'Shot Settings' => 'Aufnahmeeinstellung', + }, + }, + 'ToneCurveRed' => 'Tonwertkurve Rot', + 'ToneCurveRedX' => 'Tonwertkurve Rot X', + 'ToneCurveRedY' => 'Tonwertkurve Rot Y', + 'ToneCurveTable' => 'Tonwertkurve Tabelle', + 'ToneCurves' => 'Ton-Kurven', + 'ToningEffect' => { + Description => 'Tönungseffekt', + PrintConv => { + 'B&W' => 'Schwarz/Weiß', + 'Blue' => 'Blau', + 'Blue-green' => 'Blau-Grün', + 'Color' => 'Farbe', + 'Green' => 'Grün', + 'None' => 'Keiner', + 'Purple' => 'Lila', + 'Purple-blue' => 'Violett-Blau', + 'Red' => 'Rot', + 'Red-purple' => 'Rot-Violett', + 'Yellow' => 'Gelb', + 'n/a' => '(nicht gesetzt)', + }, + }, + 'ToningEffectFaithful' => { + Description => 'Tönungseffekt Natürlich', + PrintConv => { + 'n/a' => '(nicht gesetzt)', + }, + }, + 'ToningEffectLandscape' => { + Description => 'Tönungseffekt Landschaft', + PrintConv => { + 'n/a' => '(nicht gesetzt)', + }, + }, + 'ToningEffectMonochrome' => { + Description => 'Tönungseffekt Monochrom', + PrintConv => { + 'Blue' => 'Blau', + 'Green' => 'Grün', + 'None' => 'Keiner', + 'Purple' => 'Lila', + 'n/a' => '(nicht gesetzt)', + }, + }, + 'ToningEffectNeutral' => { + Description => 'Tönungseffekt Neutral', + PrintConv => { + 'n/a' => '(nicht gesetzt)', + }, + }, + 'ToningEffectPortrait' => { + Description => 'Tönungseffekt Porträt', + PrintConv => { + 'n/a' => '(nicht gesetzt)', + }, + }, + 'ToningEffectStandard' => { + Description => 'Tönungseffekt Standard', + PrintConv => { + 'n/a' => '(nicht gesetzt)', + }, + }, + 'ToningEffectUnknown' => { + Description => 'Tönungseffekt Unbekannt', + PrintConv => { + 'Blue' => 'Blau', + 'Green' => 'Grün', + 'None' => 'Keiner', + 'Purple' => 'Lila', + 'n/a' => '(nicht gesetzt)', + }, + }, + 'ToningEffectUserDef1' => { + Description => 'Tönungseffekt Benutzerdefiniert 1', + PrintConv => { + 'Blue' => 'Blau', + 'Green' => 'Grün', + 'None' => 'Keiner', + 'Purple' => 'Lila', + 'n/a' => '(nicht gesetzt)', + }, + }, + 'ToningEffectUserDef2' => { + Description => 'Tönungseffekt Benutzerdefiniert 2', + PrintConv => { + 'Blue' => 'Blau', + 'Green' => 'Grün', + 'None' => 'Keiner', + 'Purple' => 'Lila', + 'n/a' => '(nicht gesetzt)', + }, + }, + 'ToningEffectUserDef3' => { + Description => 'Tönungseffekt Benutzerdefiniert 3', + PrintConv => { + 'Blue' => 'Blau', + 'Green' => 'Grün', + 'None' => 'Keiner', + 'Purple' => 'Lila', + 'n/a' => '(nicht gesetzt)', + }, + }, + 'ToningSaturation' => 'Tönungssättigung', + 'TotalZoom' => 'Gesamtzoom', + 'TrailerSignature' => 'Signatur des Nachspanns', + 'TransferFunction' => 'Transformationsfunktion', + 'Transform' => { + Description => 'Transformation', + PrintConv => { + 'Off' => 'Aus', + 'Slim High' => 'Stark abnehmend', + 'Slim Low' => 'Wenig abnehmend', + 'Stretch High' => 'Stark streckend', + 'Stretch Low' => 'Wenig streckend', + }, + }, + 'Transformation' => { + PrintConv => { + 'Mirror horizontal' => 'Horizontal gespiegelt', + 'Mirror horizontal and rotate 270 CW' => 'Horizontal gespiegelt und 90° gegen den Uhrzeigersinn', + 'Mirror horizontal and rotate 90 CW' => 'Horizontal gespiegelt und 90° im Uhrzeigersinn', + 'Mirror vertical' => 'Vertikal gespiegelt', + 'Rotate 180' => '180° gedreht', + 'Rotate 270 CW' => '90° gegen den Uhrzeigersinn', + 'Rotate 90 CW' => '90° im Uhrzeigersinn', + }, + }, + 'TransmissionReference' => 'Anbietervermerk', + 'Trapped' => { + PrintConv => { + 'Unknown' => 'Unbekannt', + }, + }, + 'TravelDay' => 'Reisetag', + 'TvExposureTimeSetting' => 'Tv Belichtungszeit-Einstellung', + 'Type' => 'Typ', + 'TypeOfOriginal' => { + PrintConv => { + 'B&W Document' => 'Schwarz-Weiß Dokument', + 'B&W Print' => 'Schwarz-Weiß Druck', + 'Color Document' => 'Farb Dokument', + 'Color Print' => 'Farbdruck', + }, + }, + 'USMLensElectronicMF' => { + Description => 'USM-Objektiv, elektr. MF', + PrintConv => { + 'Disable after one-shot AF' => 'Nicht mögl. nach One-Shot AF', + 'Disable in AF mode' => 'Nicht möglich im AF-Modus', + 'Enable after one-shot AF' => 'Möglich nach One-Shot AF', + }, + }, + 'Uncompressed' => { + Description => 'Unkomprimiert', + PrintConv => { + 'No' => 'Nein', + 'Yes' => 'Ja', + }, + }, + 'UniqueCameraModel' => 'Eindeutige Kamerabezeichnung', + 'UniqueDocumentID' => 'Eindeutige Bild-ID', + 'Unknown' => 'Unbekannt', + 'UnknownInfoVersion' => 'Unbekannte Info Version', + 'UnknownLinear' => { + PrintConv => { + 'No' => 'Nein', + 'Yes' => 'Ja', + }, + }, + 'Unknown_CNDB' => 'CNDB unbekannt', + 'Unsharp1Color' => { + PrintConv => { + 'Blue' => 'Blau', + 'Green' => 'Grün', + 'Red' => 'Rot', + 'Yellow' => 'Gelb', + }, + }, + 'Unsharp2Color' => { + PrintConv => { + 'Blue' => 'Blau', + 'Green' => 'Grün', + 'Red' => 'Rot', + 'Yellow' => 'Gelb', + }, + }, + 'Unsharp3Color' => { + PrintConv => { + 'Blue' => 'Blau', + 'Green' => 'Grün', + 'Red' => 'Rot', + 'Yellow' => 'Gelb', + }, + }, + 'Unsharp4Color' => { + PrintConv => { + 'Blue' => 'Blau', + 'Green' => 'Grün', + 'Red' => 'Rot', + 'Yellow' => 'Gelb', + }, + }, + 'UnsharpMask' => { + Description => 'Unschärfemaske', + PrintConv => { + 'Off' => 'Aus', + 'On' => 'Ein', + }, + }, + 'Urgency' => { + Description => 'Dringlichkeit', + PrintConv => { + '0 (reserved)' => '0 (reserviert)', + '1 (most urgent)' => '1 (sehr dringend)', + '5 (normal urgency)' => '5 (normale Dringlichkeit)', + '8 (least urgent)' => '8 (geringe Dringlichkeit)', + '9 (user-defined priority)' => '9 (benutzerdefinierte Priorität)', + }, + }, + 'UsableMeteringModes' => { + Description => 'Wahl nutzbarer Messmethoden', + PrintConv => { + 'Disable' => 'Nicht möglich', + 'Enable' => 'Möglich', + }, + }, + 'UsableShootingModes' => { + Description => 'Wahl nutzbarer Aufnahmemodi', + PrintConv => { + 'Disable' => 'Nicht möglich', + 'Enable' => 'Möglich', + }, + }, + 'UsageTerms' => 'Nutzungsbedingungen', + 'UserComment' => 'Benutzerkommentar', + 'UserDef1PictureStyle' => { + Description => 'Bildstil Benutzerdefiniert 1', + PrintConv => { + 'Faithful' => 'Natürlich', + 'Landscape' => 'Landschaft', + 'Monochrome' => 'Monochrom', + 'Portrait' => 'Porträt', + }, + }, + 'UserDef2PictureStyle' => { + Description => 'Bildstil Benutzerdefiniert 2', + PrintConv => { + 'Faithful' => 'Natürlich', + 'Landscape' => 'Landschaft', + 'Monochrome' => 'Monochrom', + 'Portrait' => 'Porträt', + }, + }, + 'UserDef3PictureStyle' => { + Description => 'Bildstil Benutzerdefiniert 3', + PrintConv => { + 'Faithful' => 'Natürlich', + 'Landscape' => 'Landschaft', + 'Monochrome' => 'Monochrom', + 'Portrait' => 'Porträt', + }, + }, + 'UserFields' => 'Benutzerfelder', + 'UserProfile' => { + Description => 'Benutzerprofil', + PrintConv => { + 'User Profile 0 (Dynamic)' => 'Benutzerprofil 0 (dynamisch)', + 'User Profile 1' => 'Benutzerprofil 1', + 'User Profile 2' => 'Benutzerprofil 2', + 'User Profile 3' => 'Benutzerprofil 3', + }, + }, + 'VFDisplayIllumination' => { + PrintConv => { + 'Disable' => 'Deaktiviert', + 'Enable' => 'Aktiviert', + }, + }, + 'VRDVersion' => 'VRD-Version', + 'VRInfo' => 'Bildstabilisator-Informationen', + 'VRInfoVersion' => 'VR-Info-Version', + 'VR_0x66' => { + PrintConv => { + 'Off' => 'Aus', + 'On (active)' => 'Ein (Aktiv)', + 'On (normal)' => 'Ein (Normal)', + }, + }, + 'ValidAFPoints' => 'Gültige AF-Punkte', + 'ValidBits' => 'Verwendete Bits', + 'ValidPixelDepth' => 'Farbtiefe', + 'VariProgram' => 'Aufnahmeprogramm', + 'VibrationReduction' => { + Description => 'Bildstabilisation', + PrintConv => { + 'Off' => 'Aus', + 'On' => 'Ein', + 'On (1)' => 'Ein (1)', + 'On (2)' => 'Ein (2)', + 'On (3)' => 'Ein (3)', + 'n/a' => '(nicht gesetzt)', + }, + }, + 'ViewInfoDuringExposure' => { + Description => 'Sucherinfo bei Belichtung', + PrintConv => { + 'Disable' => 'Nicht möglich', + 'Enable' => 'Möglich', + }, + }, + 'ViewfinderWarning' => { + Description => 'Warnsymbol im Sucher', + PrintConv => { + 'Off' => 'Aus', + 'On' => 'Ein', + }, + }, + 'ViewfinderWarnings' => { + PrintConv => { + 'ISO expansion' => 'ISO-Erweiterung', + }, + }, + 'ViewingMode2' => { + PrintConv => { + 'n/a' => '(nicht gesetzt)', + }, + }, + 'VignetteControl' => { + Description => 'Vignettierungskorrektur', + PrintConv => { + 'High' => 'Hoch', + 'Low' => 'Schwach', + 'Normal' => 'Mittel', + 'Off' => 'Aus', + 'On' => 'Ein', + }, + }, + 'VignetteControlIntensity' => 'Vignettierungskorrektur Stärke', + 'VignettingCorrection' => { + PrintConv => { + 'n/a' => '(nicht gesetzt)', + }, + }, + 'VirtualImageHeight' => 'Virtuelle Bildhöhe', + 'VirtualImageWidth' => 'Virtuelle Bildbreite', + 'VirtualPageUnits' => 'Virtuelle Seitenzahl', + 'VoiceMemo' => { + PrintConv => { + 'Off' => 'Aus', + 'On' => 'Ein', + }, + }, + 'Volume' => 'Band', + 'WBAdjColorTemp' => 'Weißabgleich Farbtemperaturkorrektur', + 'WBAdjLighting' => { + PrintConv => { + 'Daylight (cloudy)' => 'Tageslicht (2)', + 'Daylight (direct sunlight)' => 'Tageslicht (0)', + 'Daylight (shade)' => 'Tageslicht (1)', + 'Flash' => 'Blitz', + 'Incandescent' => 'Glühbirne', + 'None' => 'Keines', + }, + }, + 'WBBlueLevel' => 'Farbabgleich Blau', + 'WBBracketMode' => { + Description => 'Weißabgleich Belichtungsreihen-Modus', + PrintConv => { + 'Off' => 'Aus', + 'On (shift AB)' => 'Ein (AB-Verschiebung)', + 'On (shift GM)' => 'Ein (GM-Verschiebung)', + }, + }, + 'WBBracketShotNumber' => 'Weißabgleich-Belichtungsreihen-Bildnummer', + 'WBBracketValueAB' => 'Weißabgleich AB-Belichtungsreihen-Wert', + 'WBBracketValueGM' => 'Weißabgleich GM-Belichtungsreihen-Wert', + 'WBFineTuneActive' => { + Description => 'Weißabgleich Feinabstimmung aktiv', + PrintConv => { + 'No' => 'Nein', + 'Yes' => 'Ja', + }, + }, + 'WBFineTuneSaturation' => 'Weißabgleich Sättigung Feinabstimmung', + 'WBFineTuneTone' => 'Weißabgleich Farbton Feinabstimmung', + 'WBGreenLevel' => 'Farbabgleich Grün', + 'WBMediaImageSizeSetting' => { + Description => 'WB+Media/Bildgrößeneinstellung', + PrintConv => { + 'LCD monitor' => 'LCD-Monitor', + 'Rear LCD panel' => 'Hinteres LCD-Panel', + }, + }, + 'WBMode' => { + PrintConv => { + 'Auto' => 'Automatisch', + }, + }, + 'WBRedLevel' => 'Farbabgleich Rot', + 'WBShiftAB' => 'Weißabgleich AB-Korrektur', + 'WBShiftGM' => 'Weißabgleich GM-Korrektur', + 'WB_GBRGLevels' => 'Weißabgleich GBRG-Farbverteilung', + 'WB_GLevel' => 'Weißabgleich G-Farbverteilung', + 'WB_GLevel3000K' => 'Weißabgleich G-Farbverteilung 3000K', + 'WB_GLevel3300K' => 'Weißabgleich G-Farbverteilung 3300K', + 'WB_GLevel3600K' => 'Weißabgleich G-Farbverteilung 3600K', + 'WB_GLevel3900K' => 'Weißabgleich G-Farbverteilung 3900K', + 'WB_GLevel4000K' => 'Weißabgleich G-Farbverteilung 4000K', + 'WB_GLevel4300K' => 'Weißabgleich G-Farbverteilung 4300K', + 'WB_GLevel4500K' => 'Weißabgleich G-Farbverteilung 4500K', + 'WB_GLevel4800K' => 'Weißabgleich G-Farbverteilung 4800K', + 'WB_GLevel5300K' => 'Weißabgleich G-Farbverteilung 5300K', + 'WB_GLevel6000K' => 'Weißabgleich G-Farbverteilung 6000K', + 'WB_GLevel6600K' => 'Weißabgleich G-Farbverteilung 6600K', + 'WB_GLevel7500K' => 'Weißabgleich G-Farbverteilung 7500K', + 'WB_GRBGLevels' => 'Weißabgleich GRBG-Farbverteilung', + 'WB_GRGBLevels' => 'Weißabgleich GRGB-Farbverteilung', + 'WB_RBGGLevels' => 'Weißabgleich RBGG-Farbverteilung', + 'WB_RBLevels' => 'Weißabgleich RB-Farbverteilung', + 'WB_RBLevels3000K' => 'Weißabgleich RB-Farbverteilung 3000K', + 'WB_RBLevels3300K' => 'Weißabgleich RB-Farbverteilung 3300K', + 'WB_RBLevels3600K' => 'Weißabgleich RB-Farbverteilung 3600K', + 'WB_RBLevels3900K' => 'Weißabgleich RB-Farbverteilung 3800K', + 'WB_RBLevels4000K' => 'Weißabgleich RB-Farbverteilung 4000K', + 'WB_RBLevels4300K' => 'Weißabgleich RB-Farbverteilung 4300K', + 'WB_RBLevels4500K' => 'Weißabgleich RB-Farbverteilung 4500K', + 'WB_RBLevels4800K' => 'Weißabgleich RB-Farbverteilung 4800K', + 'WB_RBLevels5300K' => 'Weißabgleich RB-Farbverteilung 5300K', + 'WB_RBLevels6000K' => 'Weißabgleich RB-Farbverteilung 6000K', + 'WB_RBLevels6600K' => 'Weißabgleich RB-Farbverteilung 6600K', + 'WB_RBLevels7500K' => 'Weißabgleich RB-Farbverteilung 7500K', + 'WB_RBLevelsAuto' => 'Weißabgleich RB-Farbverteilung Automatik', + 'WB_RBLevelsCWB1' => 'Weißabgleich RB-Farbverteilung CWB1', + 'WB_RBLevelsCWB2' => 'Weißabgleich RB-Farbverteilung CWB2', + 'WB_RBLevelsCWB3' => 'Weißabgleich RB-Farbverteilung CWB3', + 'WB_RBLevelsCWB4' => 'Weißabgleich RB-Farbverteilung CWB4', + 'WB_RBLevelsCloudy' => 'Weißabgleich RB-Farbverteilung Bewölkt', + 'WB_RBLevelsCoolWhiteFluor' => 'Weißabgleich RB-Farbverteilung Neonlicht kaltweiß', + 'WB_RBLevelsDayWhiteFluor' => 'Weißabgleich RB-Farbverteilung Neonlicht neutralweiß', + 'WB_RBLevelsDaylightFluor' => 'Weißabgleich RB-Farbverteilung Neonlicht tageslichtweiß', + 'WB_RBLevelsEveningSunlight' => 'Weißabgleich RB-Farbverteilung Sonnenuntergang', + 'WB_RBLevelsFineWeather' => 'Weißabgleich RB-Farbverteilung Wolkenlos', + 'WB_RBLevelsShade' => 'Weißabgleich RB-Farbverteilung Schatten', + 'WB_RBLevelsTungsten' => 'Weißabgleich RB-Farbverteilung Glühbirne', + 'WB_RBLevelsUsed' => 'Weißabgleich RB-Farbverteilung verwendet', + 'WB_RBLevelsWhiteFluorescent' => 'Weißabgleich RB-Farbverteilung Neonlicht universalweiß', + 'WB_RGBGLevels' => 'Weißabgleich RGBG-Farbverteilung', + 'WB_RGBLevels' => 'Weißabgleich RGB-Farbverteilung', + 'WB_RGBLevelsCloudy' => 'Weißabgleich RGB-Farbverteilung Bewölkt', + 'WB_RGBLevelsDaylight' => 'Weißabgleich RGB-Farbverteilung Tageslicht', + 'WB_RGBLevelsFlash' => 'Weißabgleich RGB-Farbverteilung Blitz', + 'WB_RGBLevelsFluorescent' => 'Weißabgleich RGB-Farbverteilung Neonlicht', + 'WB_RGBLevelsShade' => 'Weißabgleich RGB-Farbverteilung Schatten', + 'WB_RGBLevelsTungsten' => 'Weißabgleich RGB-Farbverteilung Glühbirne', + 'WB_RGGBLevels' => 'Weißabgleich RGGB-Farbverteilung', + 'WB_RGGBLevelsAsShot' => 'Weißabgleich RGGB-Farbverteilung Aufnahme', + 'WB_RGGBLevelsAuto' => 'Weißabgleich RGGB-Farbverteilung Auto', + 'WB_RGGBLevelsCloudy' => 'Weißabgleich RGGB-Farbverteilung Bewölkt', + 'WB_RGGBLevelsCustom' => 'Weißabgleich RGGB-Farbverteilung Benutzerdefiniert', + 'WB_RGGBLevelsCustom1' => 'Weißabgleich RGGB-Farbverteilung Benutzerdefiniert 1', + 'WB_RGGBLevelsCustom2' => 'Weißabgleich RGGB-Farbverteilung Benutzerdefiniert 2', + 'WB_RGGBLevelsDaylight' => 'Weißabgleich RGGB-Farbverteilung Tageslicht', + 'WB_RGGBLevelsFlash' => 'Weißabgleich RGGB-Farbverteilung Blitz', + 'WB_RGGBLevelsFluorescent' => 'Weißabgleich RGGB-Farbverteilung Neonlicht', + 'WB_RGGBLevelsFluorescentD' => 'Weißabgleich RGGB-Farbverteilung Neonlicht D', + 'WB_RGGBLevelsFluorescentN' => 'Weißabgleich RGGB-Farbverteilung Neonlicht N', + 'WB_RGGBLevelsFluorescentW' => 'Weißabgleich RGGB-Farbverteilung Neonlicht W', + 'WB_RGGBLevelsKelvin' => 'Weißabgleich RGGB-Farbverteilung Kelvin', + 'WB_RGGBLevelsMeasured' => 'Weißabgleich RGGB-Farbverteilung Messung', + 'WB_RGGBLevelsPC1' => 'Weißabgleich RGGB-Farbverteilung PC1', + 'WB_RGGBLevelsPC2' => 'Weißabgleich RGGB-Farbverteilung PC2', + 'WB_RGGBLevelsPC3' => 'Weißabgleich RGGB-Farbverteilung PC3', + 'WB_RGGBLevelsShade' => 'Weißabgleich RGGB-Farbverteilung Schatten', + 'WB_RGGBLevelsTungsten' => 'Weißabgleich RGGB-Farbverteilung Glühbirne', + 'WB_RGGBLevelsUnknown' => 'Weißabgleich RGGB-Farbverteilung Unbekannt', + 'WB_RGGBLevelsUnknown10' => 'Weißabgleich RGGB-Farbverteilung Unbekannt 10', + 'WB_RGGBLevelsUnknown11' => 'Weißabgleich RGGB-Farbverteilung Unbekannt 11', + 'WB_RGGBLevelsUnknown12' => 'Weißabgleich RGGB-Farbverteilung Unbekannt 12', + 'WB_RGGBLevelsUnknown13' => 'Weißabgleich RGGB-Farbverteilung Unbekannt 13', + 'WB_RGGBLevelsUnknown14' => 'Weißabgleich RGGB-Farbverteilung Unbekannt 14', + 'WB_RGGBLevelsUnknown15' => 'Weißabgleich RGGB-Farbverteilung Unbekannt 15', + 'WB_RGGBLevelsUnknown16' => 'Weißabgleich RGGB-Farbverteilung Unbekannt 16', + 'WB_RGGBLevelsUnknown17' => 'Weißabgleich RGGB-Farbverteilung Unbekannt 17', + 'WB_RGGBLevelsUnknown18' => 'Weißabgleich RGGB-Farbverteilung Unbekannt 18', + 'WB_RGGBLevelsUnknown19' => 'Weißabgleich RGGB-Farbverteilung Unbekannt 19', + 'WB_RGGBLevelsUnknown2' => 'Weißabgleich RGGB-Farbverteilung Unbekannt 2', + 'WB_RGGBLevelsUnknown20' => 'Weißabgleich RGGB-Farbverteilung Unbekannt 20', + 'WB_RGGBLevelsUnknown3' => 'Weißabgleich RGGB-Farbverteilung Unbekannt 3', + 'WB_RGGBLevelsUnknown4' => 'Weißabgleich RGGB-Farbverteilung Unbekannt 4', + 'WB_RGGBLevelsUnknown5' => 'Weißabgleich RGGB-Farbverteilung Unbekannt 5', + 'WB_RGGBLevelsUnknown6' => 'Weißabgleich RGGB-Farbverteilung Unbekannt 6', + 'WB_RGGBLevelsUnknown7' => 'Weißabgleich RGGB-Farbverteilung Unbekannt 7', + 'WB_RGGBLevelsUnknown8' => 'Weißabgleich RGGB-Farbverteilung Unbekannt 8', + 'WB_RGGBLevelsUnknown9' => 'Weißabgleich RGGB-Farbverteilung Unbekannt 9', + 'WCSProfiles' => 'Windows Color System-Profil', + 'WangAnnotation' => 'Wang Anmerkung', + 'Warning' => 'Warnung', + 'Watermark' => 'Wasserzeichen', + 'WhiteBalance' => { + Description => 'Weißabgleich', + PrintConv => { + 'As Shot' => 'Aufnahme', + 'Auto' => 'Automatisch', + 'Black & White' => 'Schwarz/Weiß', + 'Cloudy' => 'Bewölkt', + 'Color Temperature/Color Filter' => 'Farbtemperatur/Farbfilter', + 'Cool White Fluorescent' => 'Neonlicht kaltweiß', + 'Custom' => 'Benutzerdefiniert', + 'Custom 1' => 'Benutzerdefiniert 1', + 'Custom 2' => 'Benutzerdefiniert 2', + 'Custom 3' => 'Benutzerdefiniert 3', + 'Custom 4' => 'Benutzerdefiniert 4', + 'Custom2' => 'Benutzerdefiniert 2', + 'Custom3' => 'Benutzerdefiniert 3', + 'Custom4' => 'Benutzerdefiniert 4', + 'Custom5' => 'Benutzerdefiniert 5', + 'Day White Fluorescent' => 'Neonlicht neutralweiß', + 'Daylight' => 'Tageslicht', + 'Daylight Fluorescent' => 'Neonlicht tageslichtweiß', + 'Flash' => 'Blitz', + 'Flash?' => 'Blitz', + 'Fluorescent' => 'Neonlicht', + 'Incandescent' => 'Glühbirne', + 'Living Room Warm White Fluorescent' => 'Neonlicht Wohnzimmer-warmweiß)', + 'Manual' => 'Manuell', + 'Manual Temperature (Kelvin)' => 'Manuelle Temperatur (Kelvin)', + 'Shade' => 'Schatten', + 'Tungsten' => 'Glühbirne', + 'Underwater' => 'Unterwasser', + 'Underwater 1 (Blue Water)' => 'Unterwasser 1 (blaues Wasser)', + 'Underwater 2 (Green Water)' => 'Unterwasser 2 (grünes Wasser)', + 'Unknown' => 'Unbekannt', + 'User-Selected' => 'Benutzerdefiniert', + 'Warm White Fluorescent' => 'Neonlicht warmweiß', + 'White Fluorescent' => 'Neonlicht universalweiß', + }, + }, + 'WhiteBalance2' => { + Description => 'Weißabgleich 2', + PrintConv => { + '3000K (Tungsten light)' => '3000K (Glühbirne)', + '3600K (Tungsten light-like)' => '3600K (ähnlich Glühbirne)', + '4000K (Cool white fluorescent)' => '4000K (Neonlicht kaltweiß)', + '4500K (Neutral white fluorescent)' => '4500K (Neonlicht neutralweiß)', + '5300K (Fine Weather)' => '5300K (Wolkenlos)', + '6000K (Cloudy)' => '6000K (Bewölkt)', + '6600K (Daylight fluorescent)' => '6600K (Neonlicht tageslichtweiß)', + '7500K (Fine Weather with Shade)' => '7500K (Sonne und Schatten)', + 'Auto' => 'Automatisch', + }, + }, + 'WhiteBalanceAdj' => { + Description => 'Weißabgleich Korrektur', + PrintConv => { + 'Auto' => 'Automatisch', + 'Cloudy' => 'Bewölkt', + 'Daylight' => 'Tageslicht', + 'Flash' => 'Blitz', + 'Fluorescent' => 'Neonlicht', + 'Off' => 'Aus', + 'On' => 'Ein', + 'Shade' => 'Schatten', + 'Tungsten' => 'Glühbirne', + }, + }, + 'WhiteBalanceAutoAdjustment' => { + Description => 'Weißabgleich automatische Abstimmung', + PrintConv => { + 'Off' => 'Aus', + 'On' => 'Ein', + }, + }, + 'WhiteBalanceBias' => 'Weißabgleich Bias', + 'WhiteBalanceBlue' => 'Farbabgleich Blau', + 'WhiteBalanceBracket' => 'Weißabgleichs-Belichtungsreihe', + 'WhiteBalanceBracketing' => { + Description => 'Weißabgleichs-Belichtungsreihe', + PrintConv => { + 'High' => 'Hoch', + 'Low' => 'Niedrig', + 'Off' => 'Aus', + }, + }, + 'WhiteBalanceComp' => 'Weißabgleichsausgleich', + 'WhiteBalanceFineTune' => 'Weißabgleichsfeineinstellung', + 'WhiteBalanceMatching' => 'Weißabgleich Übereinstimmung', + 'WhiteBalanceMode' => { + Description => 'Weißabgleich-Modus', + PrintConv => { + 'Auto (Cloudy)' => 'Automatisch (Bewölkt)', + 'Auto (Day White Fluorescent)' => 'Automatisch (Neonlicht neutralweiß)', + 'Auto (Daylight Fluorescent)' => 'Automatisch (Neonlicht tageslichtweiß)', + 'Auto (Daylight)' => 'Automatisch (Tageslicht)', + 'Auto (Flash)' => 'Automatisch (Blitz)', + 'Auto (Shade)' => 'Automatisch (Schatten)', + 'Auto (Tungsten)' => 'Automatisch (Glühbirne)', + 'Auto (White Fluorescent)' => 'Automatisch (Neonlicht universalweiß)', + 'Unknown' => 'Unbekannt', + 'User-Selected' => 'Benutzerdefiniert', + }, + }, + 'WhiteBalanceRed' => 'Farbabgleich Rot', + 'WhiteBalanceSet' => { + Description => 'Eingestellter Weißabgleich', + PrintConv => { + 'Auto' => 'Automatisch', + 'Cloudy' => 'Bewölkt', + 'Day White Fluorescent' => 'Neonlicht neutralweiß', + 'Daylight' => 'Tageslicht', + 'Daylight Fluorescent' => 'Neonlicht tageslichtweiß', + 'Flash' => 'Blitz', + 'Manual' => 'Manuell', + 'Set Color Temperature 1' => 'Farbtemperatur-Einstellung 1', + 'Set Color Temperature 2' => 'Farbtemperatur-Einstellung 2', + 'Set Color Temperature 3' => 'Farbtemperatur-Einstellung 3', + 'Shade' => 'Schatten', + 'Tungsten' => 'Glühbirne', + 'White Fluorescent' => 'Neonlicht universalweiß', + }, + }, + 'WhiteBalanceSetting' => { + Description => 'Weißabgleichs-Einstellung', + PrintConv => { + 'Color Temperature/Color Filter' => 'Farbtemperatur/Farbfilter', + 'Custom' => 'Benutzerdefiniert', + 'Preset' => 'Voreinstellung', + }, + }, + 'WhiteBalanceTable' => 'Weißabgleich Tabelle', + 'WhiteBalanceTemperature' => 'Weißabgleich Farbtemperatur', + 'WhiteBoard' => 'Whiteboard Funktion', + 'WhiteLevel' => 'Weißwert', + 'WhitePoint' => 'Weißpunkt-Chromatizität', + 'WhitePointX' => 'Weißpunkt X', + 'WhitePointY' => 'Weißpunkt Y', + 'Wide' => 'Breit', + 'WideFocusZone' => { + Description => 'Zone des großen AF-Messfeldes', + PrintConv => { + 'Center zone (horizontal orientation)' => 'Mittlere Zone (horizontale Ausrichtung)', + 'Center zone (vertical orientation)' => 'Mittlere Zone (vertikale Ausrichtung)', + 'Left zone' => 'Linke Zone', + 'No zone' => 'Keine Zone', + 'Right zone' => 'Rechte Zone', + }, + }, + 'WideRange' => { + PrintConv => { + 'Off' => 'Aus', + 'On' => 'Ein', + }, + }, + 'WidthResolution' => 'Horizontale Bildauflösung', + 'WorldTime' => 'Zeitzone', + 'WorldTimeLocation' => { + Description => 'Weltzeit-Position', + PrintConv => { + 'Destination' => 'Zielort', + 'Home' => 'Heimatort', + 'Hometown' => 'Heimatort', + }, + }, + 'Writer-Editor' => 'Verfasser der Beschreibung', + 'Writers' => 'Schreiber', + 'XMP' => 'XMP Metadaten', + 'XPAuthor' => 'XP Autor', + 'XPComment' => 'XP Kommentar', + 'XPKeywords' => 'XP Schlüsselwörter', + 'XPSubject' => 'XP Thema', + 'XPTitle' => 'XP Titel', + 'XResolution' => 'Horizontale Bildauflösung', + 'XYResolution' => 'XY Auflösung', + 'YCbCrCoefficients' => 'YCbCr-Koeffizienten', + 'YCbCrPositioning' => { + Description => 'Y und C Ausrichtung', + PrintConv => { + 'Centered' => 'Zentriert', + 'Co-sited' => 'Benachbart', + }, + }, + 'YCbCrSubSampling' => 'Subsampling Rate von Y bis C', + 'YResolution' => 'Vertikale Bildauflösung', + 'Year' => 'Jahr', + 'ZipCompression' => 'Zip Komprimierung', + 'ZoneMatching' => { + Description => 'Zonenabgleich', + PrintConv => { + 'High Key' => 'Hi', + 'ISO Setting Used' => 'Aus (ISO-Einstellung verwendet)', + 'Low Key' => 'Lo', + }, + }, + 'ZoneMatchingOn' => { + Description => 'Zonenabgleich', + PrintConv => { + 'Off' => 'Aus', + 'On' => 'Ein', + }, + }, + 'Zoom' => 'Zoom-Objektiv', + 'ZoomPos' => 'Zoom Position', + 'ZoomSourceWidth' => 'Vergrößerungs-Ursprungsgröße', + 'ZoomStepCount' => 'Zoom-Stufenzähler', + 'ZoomTargetWidth' => 'Vergrößerungs-Endgröße', + 'ZoomedPreviewImage' => 'Vergrößertes Vorschaubild', + 'ZoomedPreviewLength' => 'Vergößertes Vorschaubild-Datenlänge', + 'ZoomedPreviewSize' => 'Vergößertes Vorschaubild-Größe', + 'ZoomedPreviewStart' => 'Vergößertes Vorschaubild-Datenposition', +); + +1; # end + + +__END__ + +=head1 NAME + +Image::ExifTool::Lang::de.pm - ExifTool German language translations + +=head1 DESCRIPTION + +This file is used by Image::ExifTool to generate localized tag descriptions +and values. + +=head1 AUTHOR + +Copyright 2003-2019, Phil Harvey (phil at owl.phy.queensu.ca) + +This library is free software; you can redistribute it and/or modify it +under the same terms as Perl itself. + +=head1 ACKNOWLEDGEMENTS + +Thanks to Jens Duttke and Herbert Kauer for providing this translation. + +=head1 SEE ALSO + +L<Image::ExifTool(3pm)|Image::ExifTool>, +L<Image::ExifTool::TagInfoXML(3pm)|Image::ExifTool::TagInfoXML> + +=cut diff --git a/lib/Image/ExifTool/Lang/en_ca.pm b/lib/Image/ExifTool/Lang/en_ca.pm new file mode 100644 index 0000000..66f0559 --- /dev/null +++ b/lib/Image/ExifTool/Lang/en_ca.pm @@ -0,0 +1,1002 @@ +#------------------------------------------------------------------------------ +# File: en_ca.pm +# +# Description: ExifTool Canadian English language translations +# +# Notes: This file generated automatically by Image::ExifTool::TagInfoXML +#------------------------------------------------------------------------------ + +package Image::ExifTool::Lang::en_ca; + +use strict; +use vars qw($VERSION); + +$VERSION = '1.12'; + +%Image::ExifTool::Lang::en_ca::Translate = ( + 'AboveColor' => 'Above Colour', + 'AdvancedFilter' => { + PrintConv => { + 'Partial Color Blue' => 'Partial Colour Blue', + 'Partial Color Green' => 'Partial Colour Green', + 'Partial Color Orange' => 'Partial Colour Orange', + 'Partial Color Purple' => 'Partial Colour Purple', + 'Partial Color Red' => 'Partial Colour Red', + 'Partial Color Yellow' => 'Partial Colour Yellow', + 'Pop Color' => 'Pop Colour', + }, + }, + 'AdvancedSceneMode' => { + PrintConv => { + 'Color Select' => 'Colour Select', + }, + }, + 'AllColorFlatField1' => 'All Colour Flat Field 1', + 'AllColorFlatField2' => 'All Colour Flat Field 2', + 'AllColorFlatField3' => 'All Colour Flat Field 3', + 'Alpha' => { + PrintConv => { + 'Alpha Exists (W color component)' => 'Alpha Exists (W colour component)', + 'Alpha Exists (color not premultiplied)' => 'Alpha Exists (colour not premultiplied)', + 'Alpha Exists (color premultiplied)' => 'Alpha Exists (colour premultiplied)', + }, + }, + 'AlternateDuotoneColors' => 'Alternate Duotone Colours', + 'AlternateSpotColors' => 'Alternate Spot Colours', + 'ArtFilter' => { + PrintConv => { + 'Pale & Light Color' => 'Pale & Light Colour', + 'Pale & Light Color II' => 'Pale & Light Colour II', + 'Partial Color' => 'Partial Colour', + 'Partial Color II' => 'Partial Colour II', + 'Partial Color III' => 'Partial Colour III', + 'Watercolor' => 'Watercolour', + 'Watercolor I' => 'Watercolour I', + 'Watercolor II' => 'Watercolour II', + }, + }, + 'ArtFilterEffect' => { + PrintConv => { + 'Green Color Filter' => 'Green Colour Filter', + 'No Color Filter' => 'No Colour Filter', + 'Orange Color Filter' => 'Orange Colour Filter', + 'Pale & Light Color' => 'Pale & Light Colour', + 'Pale & Light Color II' => 'Pale & Light Colour II', + 'Partial Color' => 'Partial Colour', + 'Partial Color II' => 'Partial Colour II', + 'Partial Color III' => 'Partial Colour III', + 'Red Color Filter' => 'Red Colour Filter', + 'Watercolor' => 'Watercolour', + 'Watercolor I' => 'Watercolour I', + 'Watercolor II' => 'Watercolour II', + 'Yellow Color Filter' => 'Yellow Colour Filter', + }, + }, + 'AutoAFPointColorTracking' => 'Auto AF Point Colour Tracking', + 'BackgroundColor' => 'Background Colour', + 'BackgroundColorIndicator' => { + Description => 'Background Colour Indicator', + PrintConv => { + 'Specified Background Color' => 'Specified Background Colour', + 'Unspecified Background Color' => 'Unspecified Background Colour', + }, + }, + 'BackgroundColorValue' => 'Background Colour Value', + 'BasicColorImageSequence' => 'Basic Colour Image Sequence', + 'BelowColor' => 'Below Colour', + 'BestShotMode' => { + PrintConv => { + 'Water Color' => 'Water Colour', + }, + }, + 'BkColor' => 'Background Colour', + 'BluePaletteColorTableData' => 'Blue Palette Colour Table Data', + 'BluePaletteColorTableDescriptor' => 'Blue Palette Colour Table Descriptor', + 'BorderColor' => 'Border Colour', + 'CFAPlaneColor' => 'CFA Plane Colour', + 'CameraColorCalibration01' => 'Camera Colour Calibration 01', + 'CameraColorCalibration02' => 'Camera Colour Calibration 02', + 'CameraColorCalibration03' => 'Camera Colour Calibration 03', + 'CameraColorCalibration04' => 'Camera Colour Calibration 04', + 'CameraColorCalibration05' => 'Camera Colour Calibration 05', + 'CameraColorCalibration06' => 'Camera Colour Calibration 06', + 'CameraColorCalibration07' => 'Camera Colour Calibration 07', + 'CameraColorCalibration08' => 'Camera Colour Calibration 08', + 'CameraColorCalibration09' => 'Camera Colour Calibration 09', + 'CameraColorCalibration10' => 'Camera Colour Calibration 10', + 'CameraColorCalibration11' => 'Camera Colour Calibration 11', + 'CameraColorCalibration12' => 'Camera Colour Calibration 12', + 'CameraColorCalibration13' => 'Camera Colour Calibration 13', + 'CameraColorCalibration14' => 'Camera Colour Calibration 14', + 'CameraColorCalibration15' => 'Camera Colour Calibration 15', + 'CameraRawColorTone' => 'Camera Raw Colour Tone', + 'CanonColorInfo1' => 'Canon Colour Info 1', + 'CanonColorInfo2' => 'Canon Colour Info 2', + 'ChromaticityColorant' => 'Chromaticity Colourant', + 'CodingMethods' => { + PrintConv => { + 'JBIG color' => 'JBIG colour', + }, + }, + 'Color' => { + Description => 'Colour', + PrintConv => { + 'Color' => 'Colour', + }, + }, + 'ColorAberrationControl' => 'Colour Aberration Control', + 'ColorAdjustment' => 'Colour Adjustment', + 'ColorAdjustmentMode' => 'Colour Adjustment Mode', + 'ColorAverages' => 'Colour Averages', + 'ColorBW' => 'Colour BW', + 'ColorBalance' => 'Colour Balance', + 'ColorBalanceAdj' => 'Colour Balance Adj', + 'ColorBalanceBlue' => 'Colour Balance Blue', + 'ColorBalanceGreen' => 'Colour Balance Green', + 'ColorBalanceRed' => 'Colour Balance Red', + 'ColorBalanceUnknown' => 'Colour Balance Unknown', + 'ColorBalanceVersion' => 'Colour Balance Version', + 'ColorBitDepth' => 'Colour Bit Depth', + 'ColorBlur' => 'Colour Blur', + 'ColorBlurOn' => 'Colour Blur On', + 'ColorBoostLevel' => 'Colour Boost Level', + 'ColorBoostType' => 'Colour Boost Type', + 'ColorBooster' => 'Colour Booster', + 'ColorCalibrationMatrix' => 'Colour Calibration Matrix', + 'ColorCasts' => 'Colour Casts', + 'ColorCharacterization' => 'Colour Characterization', + 'ColorClass' => 'Colour Class', + 'ColorCompensationFilter' => 'Colour Compensation Filter', + 'ColorCompensationFilterCustom' => 'Colour Compensation Filter Custom', + 'ColorCompensationFilterSet' => 'Colour Compensation Filter Set', + 'ColorComponents' => 'Colour Components', + 'ColorControl' => 'Colour Control', + 'ColorCorrection' => 'Colour Correction', + 'ColorCreatorEffect' => 'Colour Creator Effect', + 'ColorDataVersion' => 'Colour Data Version', + 'ColorDescriptor' => 'Colour Descriptor', + 'ColorEffect' => 'Colour Effect', + 'ColorFieldCode' => 'Colour Field Code', + 'ColorFilter' => 'Colour Filter', + 'ColorGain' => 'Colour Gain', + 'ColorGroup' => 'Colour Group', + 'ColorHalftoningInfo' => 'Colour Halftoning Info', + 'ColorHue' => 'Colour Hue', + 'ColorImagePrintingFlag' => 'Colour Image Printing Flag', + 'ColorLabel' => 'Colour Label', + 'ColorMap' => 'Colour Map', + 'ColorMatrix' => 'Colour Matrix', + 'ColorMatrix1' => 'Colour Matrix 1', + 'ColorMatrix2' => 'Colour Matrix 2', + 'ColorMatrixA' => 'Colour Matrix A', + 'ColorMatrixAdobeRGB' => 'Colour Matrix Adobe RGB', + 'ColorMatrixB' => 'Colour Matrix B', + 'ColorMatrixNumber' => 'Colour Matrix Number', + 'ColorMatrixSRGB' => 'Colour Matrix sRGB', + 'ColorMode' => { + Description => 'Colour Mode', + PrintConv => { + 'Indexed Color' => 'Indexed Colour', + 'Natural color' => 'Natural colour', + 'Neutral Color' => 'Neutral Colour', + 'RGB Color' => 'RGB Colour', + 'Saturated Color' => 'Saturated Colour', + 'Vivid color' => 'Vivid colour', + }, + }, + 'ColorMoireReduction' => 'Colour Moire Reduction', + 'ColorMoireReductionMode' => 'Colour Moire Reduction Mode', + 'ColorNoiseReduction' => 'Colour Noise Reduction', + 'ColorNoiseReductionDetail' => 'Colour Noise Reduction Detail', + 'ColorNoiseReductionIntensity' => 'Colour Noise Reduction Intensity', + 'ColorNoiseReductionSharpness' => 'Colour Noise Reduction Sharpness', + 'ColorNoiseReductionSmoothness' => 'Colour Noise Reduction Smoothness', + 'ColorObjBackType' => 'Colour Obj Back Type', + 'ColorObjName' => 'Colour Obj Name', + 'ColorObjType' => 'Colour Obj Type', + 'ColorObjVersion' => 'Colour Obj Version', + 'ColorPalette' => 'Colour Palette', + 'ColorPlanes' => 'Colour Planes', + 'ColorPrimaries' => 'Colour Primaries', + 'ColorProfile' => 'Colour Profile', + 'ColorProfileSettings' => 'Colour Profile Settings', + 'ColorRangeLevels' => 'Colour Range Levels', + 'ColorRepresentation' => 'Colour Representation', + 'ColorReproduction' => 'Colour Reproduction', + 'ColorResolutionDepth' => 'Colour Resolution Depth', + 'ColorResponseUnit' => 'Colour Response Unit', + 'ColorSamplersResource' => 'Colour Samplers Resource', + 'ColorSamplersResource2' => 'Colour Samplers Resource 2', + 'ColorSaturationAdj' => 'Colour Saturation Adj', + 'ColorSequence' => 'Colour Sequence', + 'ColorSiting' => 'Colour Siting', + 'ColorSpace' => { + Description => 'Colour Space', + PrintConv => { + 'Embedded Color Profile' => 'Embedded Colour Profile', + 'Linked Color Profile' => 'Linked Colour Profile', + 'No color space specified' => 'No colour space specified', + 'Windows Color Space' => 'Windows Colour Space', + }, + }, + 'ColorSpaceData' => 'Colour Space Data', + 'ColorSpecApproximation' => 'Colour Spec Approximation', + 'ColorSpecData' => 'Colour Spec Data', + 'ColorSpecMethod' => { + Description => 'Colour Spec Method', + PrintConv => { + 'Vendor Color' => 'Vendor Colour', + }, + }, + 'ColorSpecPrecedence' => 'Colour Spec Precedence', + 'ColorSpecification' => 'Colour Specification', + 'ColorTable' => 'Colour Table', + 'ColorTempAsShot' => 'Colour Temp As Shot', + 'ColorTempAuto' => 'Colour Temp Auto', + 'ColorTempCloudy' => 'Colour Temp Cloudy', + 'ColorTempCustom' => 'Colour Temp Custom', + 'ColorTempCustom1' => 'Colour Temp Custom 1', + 'ColorTempCustom2' => 'Colour Temp Custom 2', + 'ColorTempDaylight' => 'Colour Temp Daylight', + 'ColorTempFlash' => 'Colour Temp Flash', + 'ColorTempFlashData' => 'Colour Temp Flash Data', + 'ColorTempFluorescent' => 'Colour Temp Fluorescent', + 'ColorTempFluorescentD' => 'Colour Temp Fluorescent D', + 'ColorTempFluorescentN' => 'Colour Temp Fluorescent N', + 'ColorTempFluorescentW' => 'Colour Temp Fluorescent W', + 'ColorTempKelvin' => 'Colour Temp Kelvin', + 'ColorTempMeasured' => 'Colour Temp Measured', + 'ColorTempPC1' => 'Colour Temp PC1', + 'ColorTempPC2' => 'Colour Temp PC2', + 'ColorTempPC3' => 'Colour Temp PC3', + 'ColorTempShade' => 'Colour Temp Shade', + 'ColorTempTungsten' => 'Colour Temp Tungsten', + 'ColorTempUnknown' => 'Colour Temp Unknown', + 'ColorTempUnknown10' => 'Colour Temp Unknown 10', + 'ColorTempUnknown11' => 'Colour Temp Unknown 11', + 'ColorTempUnknown12' => 'Colour Temp Unknown 12', + 'ColorTempUnknown13' => 'Colour Temp Unknown 13', + 'ColorTempUnknown14' => 'Colour Temp Unknown 14', + 'ColorTempUnknown15' => 'Colour Temp Unknown 15', + 'ColorTempUnknown16' => 'Colour Temp Unknown 16', + 'ColorTempUnknown17' => 'Colour Temp Unknown 17', + 'ColorTempUnknown18' => 'Colour Temp Unknown 18', + 'ColorTempUnknown19' => 'Colour Temp Unknown 19', + 'ColorTempUnknown2' => 'Colour Temp Unknown 2', + 'ColorTempUnknown20' => 'Colour Temp Unknown 20', + 'ColorTempUnknown21' => 'Colour Temp Unknown 21', + 'ColorTempUnknown22' => 'Colour Temp Unknown 22', + 'ColorTempUnknown23' => 'Colour Temp Unknown 23', + 'ColorTempUnknown24' => 'Colour Temp Unknown 24', + 'ColorTempUnknown25' => 'Colour Temp Unknown 25', + 'ColorTempUnknown26' => 'Colour Temp Unknown 26', + 'ColorTempUnknown27' => 'Colour Temp Unknown 27', + 'ColorTempUnknown28' => 'Colour Temp Unknown 28', + 'ColorTempUnknown29' => 'Colour Temp Unknown 29', + 'ColorTempUnknown3' => 'Colour Temp Unknown 3', + 'ColorTempUnknown30' => 'Colour Temp Unknown 30', + 'ColorTempUnknown4' => 'Colour Temp Unknown 4', + 'ColorTempUnknown5' => 'Colour Temp Unknown 5', + 'ColorTempUnknown6' => 'Colour Temp Unknown 6', + 'ColorTempUnknown7' => 'Colour Temp Unknown 7', + 'ColorTempUnknown8' => 'Colour Temp Unknown 8', + 'ColorTempUnknown9' => 'Colour Temp Unknown 9', + 'ColorTemperature' => 'Colour Temperature', + 'ColorTemperatureAdj' => 'Colour Temperature Adj', + 'ColorTemperatureAuto' => 'Colour Temperature Auto', + 'ColorTemperatureBG' => 'Colour Temperature BG', + 'ColorTemperatureCustom' => 'Colour Temperature Custom', + 'ColorTemperatureRG' => 'Colour Temperature RG', + 'ColorTemperatureSet' => 'Colour Temperature Set', + 'ColorTemperatureSetting' => { + Description => 'Colour Temperature Setting', + PrintConv => { + 'Color Filter' => 'Colour Filter', + }, + }, + 'ColorTone' => 'Colour Tone', + 'ColorToneAdj' => 'Colour Tone Adj', + 'ColorToneAuto' => 'Colour Tone Auto', + 'ColorToneFaithful' => 'Colour Tone Faithful', + 'ColorToneLandscape' => 'Colour Tone Landscape', + 'ColorToneMonochrome' => 'Colour Tone Monochrome', + 'ColorToneNeutral' => 'Colour Tone Neutral', + 'ColorTonePortrait' => 'Colour Tone Portrait', + 'ColorToneStandard' => 'Colour Tone Standard', + 'ColorToneUserDef1' => 'Colour Tone User Def 1', + 'ColorToneUserDef2' => 'Colour Tone User Def 2', + 'ColorToneUserDef3' => 'Colour Tone User Def 3', + 'ColorTransferFuncs' => 'Colour Transfer Funcs', + 'ColorTransform' => 'Colour Transform', + 'ColorTwistMatrix' => 'Colour Twist Matrix', + 'ColorType' => { + Description => 'Colour Type', + PrintConv => { + 'Color' => 'Colour', + 'Color Alpha' => 'Colour Alpha', + }, + }, + 'Colorant1Coordinates' => 'Colourant 1 Coordinates', + 'Colorant1Name' => 'Colourant 1 Name', + 'Colorant2Coordinates' => 'Colourant 2 Coordinates', + 'Colorant2Name' => 'Colourant 2 Name', + 'Colorant3Coordinates' => 'Colourant 3 Coordinates', + 'Colorant3Name' => 'Colourant 3 Name', + 'ColorantA' => 'Colourant A', + 'ColorantB' => 'Colourant B', + 'ColorantBlack' => 'Colourant Black', + 'ColorantBlue' => 'Colourant Blue', + 'ColorantCount' => 'Colourant Count', + 'ColorantCyan' => 'Colourant Cyan', + 'ColorantGray' => 'Colourant Gray', + 'ColorantGreen' => 'Colourant Green', + 'ColorantL' => 'Colourant L', + 'ColorantMagenta' => 'Colourant Magenta', + 'ColorantMode' => 'Colourant Mode', + 'ColorantOrder' => 'Colourant Order', + 'ColorantRed' => 'Colourant Red', + 'ColorantSwatchName' => 'Colourant Swatch Name', + 'ColorantTableOut' => 'Colourant Table Out', + 'ColorantTint' => 'Colourant Tint', + 'ColorantType' => 'Colourant Type', + 'ColorantYellow' => 'Colourant Yellow', + 'Colorants' => 'Colourants', + 'ColorimetricIntentImageState' => 'Colourimetric Intent Image State', + 'ColorimetricReference' => 'Colourimetric Reference', + 'Colorimetry' => 'Colourimetry', + 'ColorimetryCode' => 'Colourimetry Code', + 'Colors' => 'Colours', + 'Compression' => { + PrintConv => { + 'JBIG Color' => 'JBIG Colour', + }, + }, + 'ContrastMode' => { + PrintConv => { + 'Dynamic (Color Film)' => 'Dynamic (Colour Film)', + 'Dynamic Art (My Color)' => 'Dynamic Art (My Colour)', + 'Elegant (My Color)' => 'Elegant (My Colour)', + 'Nature (Color Film)' => 'Nature (Colour Film)', + 'Nostalgic (Color Film)' => 'Nostalgic (Colour Film)', + 'Retro (My Color)' => 'Retro (My Colour)', + 'Smooth (Color Film) or Pure (My Color)' => 'Smooth (Colour Film) or Pure (My Colour)', + 'Vibrant (Color Film) or Expressive (My Color)' => 'Vibrant (Colour Film) or Expressive (My Colour)', + }, + }, + 'CustomColorTone' => 'Custom Colour Tone', + 'D-LightingHQColorBoost' => 'D-Lighting HQ Colour Boost', + 'D-LightingHSColorBoost' => 'D-Lighting HS Colour Boost', + 'DefHilite' => 'Use Default Highlight Colour', + 'DefaultImageColor' => 'Default Image Colour', + 'DeltaType' => { + PrintConv => { + 'Color Addition' => 'Colour Addition', + 'Color Replacement' => 'Colour Replacement', + }, + }, + 'DigitalFilter01' => { + PrintConv => { + 'Color Filter' => 'Colour Filter', + 'Extract Color' => 'Extract Colour', + 'Invert Color' => 'Invert Colour', + 'Replace Color' => 'Replace Colour', + 'Unicolor Bold' => 'Unicolour Bold', + 'Water Color' => 'Water Colour', + }, + }, + 'DigitalFilter02' => { + PrintConv => { + 'Color Filter' => 'Colour Filter', + 'Extract Color' => 'Extract Colour', + 'Invert Color' => 'Invert Colour', + 'Water Color' => 'Water Colour', + }, + }, + 'DigitalFilter03' => { + PrintConv => { + 'Color Filter' => 'Colour Filter', + 'Extract Color' => 'Extract Colour', + 'Invert Color' => 'Invert Colour', + 'Water Color' => 'Water Colour', + }, + }, + 'DigitalFilter04' => { + PrintConv => { + 'Color Filter' => 'Colour Filter', + 'Extract Color' => 'Extract Colour', + 'Invert Color' => 'Invert Colour', + 'Water Color' => 'Water Colour', + }, + }, + 'DigitalFilter05' => { + PrintConv => { + 'Color Filter' => 'Colour Filter', + 'Extract Color' => 'Extract Colour', + 'Invert Color' => 'Invert Colour', + 'Water Color' => 'Water Colour', + }, + }, + 'DigitalFilter06' => { + PrintConv => { + 'Color Filter' => 'Colour Filter', + 'Extract Color' => 'Extract Colour', + 'Invert Color' => 'Invert Colour', + 'Water Color' => 'Water Colour', + }, + }, + 'DigitalFilter07' => { + PrintConv => { + 'Color Filter' => 'Colour Filter', + 'Extract Color' => 'Extract Colour', + 'Invert Color' => 'Invert Colour', + 'Water Color' => 'Water Colour', + }, + }, + 'DigitalFilter08' => { + PrintConv => { + 'Color Filter' => 'Colour Filter', + 'Extract Color' => 'Extract Colour', + 'Invert Color' => 'Invert Colour', + 'Water Color' => 'Water Colour', + }, + }, + 'DigitalFilter09' => { + PrintConv => { + 'Color Filter' => 'Colour Filter', + 'Extract Color' => 'Extract Colour', + 'Invert Color' => 'Invert Colour', + 'Water Color' => 'Water Colour', + }, + }, + 'DigitalFilter10' => { + PrintConv => { + 'Color Filter' => 'Colour Filter', + 'Extract Color' => 'Extract Colour', + 'Invert Color' => 'Invert Colour', + 'Water Color' => 'Water Colour', + }, + }, + 'DigitalFilter11' => { + PrintConv => { + 'Color Filter' => 'Colour Filter', + 'Extract Color' => 'Extract Colour', + 'Invert Color' => 'Invert Colour', + 'Water Color' => 'Water Colour', + }, + }, + 'DigitalFilter12' => { + PrintConv => { + 'Color Filter' => 'Colour Filter', + 'Extract Color' => 'Extract Colour', + 'Invert Color' => 'Invert Colour', + 'Water Color' => 'Water Colour', + }, + }, + 'DigitalFilter13' => { + PrintConv => { + 'Color Filter' => 'Colour Filter', + 'Extract Color' => 'Extract Colour', + 'Invert Color' => 'Invert Colour', + 'Water Color' => 'Water Colour', + }, + }, + 'DigitalFilter14' => { + PrintConv => { + 'Color Filter' => 'Colour Filter', + 'Extract Color' => 'Extract Colour', + 'Invert Color' => 'Invert Colour', + 'Water Color' => 'Water Colour', + }, + }, + 'DigitalFilter15' => { + PrintConv => { + 'Color Filter' => 'Colour Filter', + 'Extract Color' => 'Extract Colour', + 'Invert Color' => 'Invert Colour', + 'Water Color' => 'Water Colour', + }, + }, + 'DigitalFilter16' => { + PrintConv => { + 'Color Filter' => 'Colour Filter', + 'Extract Color' => 'Extract Colour', + 'Invert Color' => 'Invert Colour', + 'Water Color' => 'Water Colour', + }, + }, + 'DigitalFilter17' => { + PrintConv => { + 'Color Filter' => 'Colour Filter', + 'Extract Color' => 'Extract Colour', + 'Invert Color' => 'Invert Colour', + 'Water Color' => 'Water Colour', + }, + }, + 'DigitalFilter18' => { + PrintConv => { + 'Color Filter' => 'Colour Filter', + 'Extract Color' => 'Extract Colour', + 'Invert Color' => 'Invert Colour', + 'Water Color' => 'Water Colour', + }, + }, + 'DigitalFilter19' => { + PrintConv => { + 'Color Filter' => 'Colour Filter', + 'Extract Color' => 'Extract Colour', + 'Invert Color' => 'Invert Colour', + 'Water Color' => 'Water Colour', + }, + }, + 'DigitalFilter20' => { + PrintConv => { + 'Color Filter' => 'Colour Filter', + 'Extract Color' => 'Extract Colour', + 'Invert Color' => 'Invert Colour', + 'Water Color' => 'Water Colour', + }, + }, + 'DisplayUnits' => { + PrintConv => { + 'meters' => 'Metres', + }, + }, + 'EasyMode' => { + PrintConv => { + 'Color Accent' => 'Colour Accent', + 'Color Swap' => 'Colour Swap', + 'My Colors' => 'My Colours', + }, + }, + 'EmbeddedImageColorSpace' => 'Embedded Image Colour Space', + 'ExposureProgram' => { + PrintConv => { + 'Partial Color Blue' => 'Partial Colour Blue', + 'Partial Color Green' => 'Partial Colour Green', + 'Partial Color Red' => 'Partial Colour Red', + 'Partial Color Yellow' => 'Partial Colour Yellow', + 'Pop Color' => 'Pop Colour', + }, + }, + 'FaithfulRawColorTone' => 'Faithful Raw Colour Tone', + 'FaxProfile' => { + PrintConv => { + 'Lossless color and grayscale, L' => 'Lossless colour and grayscale, L', + 'Lossy color and grayscale, C' => 'Lossy colour and grayscale, C', + }, + }, + 'FgColor' => 'Foreground Colour', + 'FilmColorProcess' => 'Film Colour Process', + 'FilmMode' => { + PrintConv => { + 'Dynamic (color)' => 'Dynamic (colour)', + 'Nature (color)' => 'Nature (colour)', + 'Smooth (color)' => 'Smooth (colour)', + 'Standard (color)' => 'Standard (colour)', + }, + }, + 'FlagColor' => 'Flag Colour', + 'FlashColorFilter' => 'Flash Colour Filter', + 'FocalPlaneColorimetryEstimates' => 'Focal Plane Colourimetry Estimates', + 'GammaColorTone' => 'Gamma Colour Tone', + 'GenOpColor' => 'Gen Op Colour', + 'GenreID' => { + PrintConv => { + 'Books|Kids|Basic Concepts|Colors' => 'Books|Kids|Basic Concepts|Colours', + }, + }, + 'GreenPaletteColorTableData' => 'Green Palette Colour Table Data', + 'GreenPaletteColorTableDescriptor' => 'Green Palette Colour Table Descriptor', + 'HasColorMap' => 'Has Colour Map', + 'HighlightColorDistortReduct' => 'Highlight Colour Distort Reduct', + 'HiliteColor' => 'Highlight Colour', + 'ImageAlterationConstraints' => { + PrintConv => { + 'No Colorization' => 'No Colourization', + 'No De-Colorization' => 'No De-Colourization', + }, + }, + 'ImageColor' => 'Image Colour', + 'ImageColorIndicator' => { + Description => 'Image Colour Indicator', + PrintConv => { + 'Specified Image Color' => 'Specified Image Colour', + 'Unspecified Image Color' => 'Unspecified Image Colour', + }, + }, + 'ImageColorValue' => 'Image Colour Value', + 'ImageMedium' => { + PrintConv => { + 'Color hard copy' => 'Colour hard copy', + 'Color negative' => 'Colour negative', + 'Color reversal' => 'Colour reversal', + }, + }, + 'IndexedColorTableCount' => 'Indexed Colour Table Count', + 'InterchangeColorSpace' => 'Interchange Colour Space', + 'Isotherm1Color' => 'Isotherm 1 Colour', + 'Isotherm2Color' => 'Isotherm 2 Colour', + 'LandscapeRawColorTone' => 'Landscape Raw Colour Tone', + 'LargeBluePaletteColorTableData' => 'Large Blue Palette Colour Table Data', + 'LargeBluePaletteColorTableDescr' => 'Large Blue Palette Colour Table Descr', + 'LargeGreenPaletteColorTableData' => 'Large Green Palette Colour Table Data', + 'LargeGreenPaletteColorTableDescr' => 'Large Green Palette Colour Table Descr', + 'LargePaletteColorLookupTableUID' => 'Large Palette Colour Lookup Table UID', + 'LargeRedPaletteColorTableData' => 'Large Red Palette Colour Table Data', + 'LargeRedPaletteColorTableDescr' => 'Large Red Palette Colour Table Descr', + 'LayerBlendModes' => { + PrintConv => { + 'Color' => 'Colour', + 'Color Burn' => 'Colour Burn', + 'Color Dodge' => 'Colour Dodge', + 'Darker Color' => 'Darker Colour', + 'Lighter Color' => 'Lighter Colour', + }, + }, + 'MDColorTable' => 'MD Colour Table', + 'MDItemColorSpace' => 'MD Item Colour Space', + 'MagicFilter' => { + PrintConv => { + 'Pale & Light Color' => 'Pale & Light Colour', + 'Pale & Light Color II' => 'Pale & Light Colour II', + 'Partial Color' => 'Partial Colour', + 'Partial Color II' => 'Partial Colour II', + 'Partial Color III' => 'Partial Colour III', + 'Watercolor' => 'Watercolour', + 'Watercolor I' => 'Watercolour I', + 'Watercolor II' => 'Watercolour II', + }, + }, + 'MandatoryBackground' => { + PrintConv => { + 'Color Advisory, Image Mandatory' => 'Colour Advisory, Image Mandatory', + 'Color Mandatory, Image Advisory' => 'Colour Mandatory, Image Advisory', + 'Color and Image Advisory' => 'Colour and Image Advisory', + 'Color and Image Mandatory' => 'Colour and Image Mandatory', + }, + }, + 'MattColor' => 'Matt Colour', + 'MediaColor' => 'Media Colour', + 'ModifiedColorTemp' => 'Modified Colour Temp', + 'MonochromeColor' => 'Monochrome Colour', + 'MyColorMode' => { + Description => 'My Colour Mode', + PrintConv => { + 'Color Accent' => 'Colour Accent', + 'Color Swap' => 'Colour Swap', + }, + }, + 'NamedColor' => 'Named Colour', + 'NamedColor2' => 'Named Colour 2', + 'NeutralRawColorTone' => 'Neutral Raw Colour Tone', + 'NewColorType' => 'New Colour Type', + 'NumColors' => 'Num Colours', + 'NumImportantColors' => 'Num Important Colours', + 'OpColor' => 'Op Colour', + 'OverflowColor' => 'Overflow Colour', + 'PF25ColorMatrix' => 'PF25 Colour Matrix', + 'PaletteColorTableUID' => 'Palette Colour Table UID', + 'PaletteColors' => 'Palette Colours', + 'PhotoEffect' => { + PrintConv => { + 'My Color Data' => 'My Colour Data', + }, + }, + 'PhotometricInterpretation' => { + PrintConv => { + 'Color Filter Array' => 'Colour Filter Array', + }, + }, + 'Photoshop2ColorTable' => 'Photoshop 2 Colour Table', + 'PictureEffect' => { + PrintConv => { + 'Partial Color (blue)' => 'Partial Colour (blue)', + 'Partial Color (green)' => 'Partial Colour (green)', + 'Partial Color (red)' => 'Partial Colour (red)', + 'Partial Color (yellow)' => 'Partial Colour (yellow)', + 'Pop Color' => 'Pop Colour', + 'Water Color' => 'Water Colour', + 'Water Color 2' => 'Water Colour 2', + }, + }, + 'PictureEffect2' => { + PrintConv => { + 'Partial Color' => 'Partial Colour', + 'Pop Color' => 'Pop Colour', + 'Water Color' => 'Water Colour', + }, + }, + 'PictureIndexedColors' => 'Picture Indexed Colours', + 'PictureMode' => { + PrintConv => { + 'Color Creator' => 'Colour Creator', + 'Color Profile 1' => 'Colour Profile 1', + 'Color Profile 2' => 'Colour Profile 2', + 'Color Profile 3' => 'Colour Profile 3', + }, + }, + 'PictureType' => { + PrintConv => { + 'Bright(ly) Colored Fish' => 'Bright(ly) Coloured Fish', + }, + }, + 'PictureWizardColor' => 'Picture Wizard Colour', + 'PortraitRawColorTone' => 'Portrait Raw Colour Tone', + 'PresetWhiteBalance' => { + PrintConv => { + 'Color Temperature' => 'Colour Temperature', + }, + }, + 'PreviewColorSpace' => 'Preview Colour Space', + 'ProfileClass' => { + PrintConv => { + 'ColorSpace Conversion Profile' => 'ColourSpace Conversion Profile', + 'NamedColor Profile' => 'Named Colour Profile', + }, + }, + 'PseudoColorType' => 'Pseudo Colour Type', + 'QuantizationMethod' => { + PrintConv => { + 'Color Space Specific' => 'Colour Space Specific', + }, + }, + 'RGBBkCol' => 'Background Colour', + 'RGBFgCol' => 'Foreground Colour', + 'ROIDisplayColor' => 'ROI Display Colour', + 'RawColorAdj' => 'Raw Colour Adj', + 'RawDevArtFilter' => { + PrintConv => { + 'Pale & Light Color' => 'Pale & Light Colour', + 'Pale & Light Color II' => 'Pale & Light Colour II', + 'Partial Color' => 'Partial Colour', + 'Partial Color II' => 'Partial Colour II', + 'Partial Color III' => 'Partial Colour III', + 'Watercolor' => 'Watercolour', + 'Watercolor I' => 'Watercolour I', + 'Watercolor II' => 'Watercolour II', + }, + }, + 'RawDevColorSpace' => 'Raw Dev Colour Space', + 'RawDevMemoryColorEmphasis' => 'Raw Dev Memory Colour Emphasis', + 'RawDevSettings' => { + PrintConv => { + 'Color Space' => 'Colour Space', + 'WB Color Temp' => 'WB Colour Temp', + }, + }, + 'RawDevWhiteBalance' => { + PrintConv => { + 'Color Temperature' => 'Colour Temperature', + }, + }, + 'RedPaletteColorTableData' => 'Red Palette Colour Table Data', + 'RedPaletteColorTableDescriptor' => 'Red Palette Colour Table Descriptor', + 'ReflectionHardcopyOrigColorimetry' => 'Reflection Hardcopy Orig Colourimetry', + 'ReflectionPrintOutputColorimetry' => 'Reflection Print Output Colourimetry', + 'RenderingIntent' => { + PrintConv => { + 'Absolute Colorimetric (LCS_GM_ABS_COLORIMETRIC)' => 'Absolute Colourimetric (LCS_GM_ABS_COLORIMETRIC)', + 'ICC-Absolute Colorimetric' => 'ICC-Absolute Colourimetric', + 'Media-Relative Colorimetric' => 'Media-Relative Colourimetric', + }, + }, + 'RetouchHistory' => { + PrintConv => { + 'Color Custom' => 'Colour Custom', + 'Color Outline' => 'Colour Outline', + 'Color Sketch' => 'Colour Sketch', + 'Selective Color' => 'Selective Colour', + }, + }, + 'SBAInputImageColorspace' => 'SBA Input Image Colourspace', + 'SRGBRendering' => { + PrintConv => { + 'Absolute Colorimetric' => 'Absolute Colourimetric', + 'Relative Colorimetric' => 'Relative Colourimetric', + }, + }, + 'SceneBalanceAlgorithmCommand' => { + PrintConv => { + 'Neutral SBA Off, Color SBA Off' => 'Neutral SBA Off, Colour SBA Off', + 'Neutral SBA Off, Color SBA On' => 'Neutral SBA Off, Colour SBA On', + 'Neutral SBA On, Color SBA Off' => 'Neutral SBA On, Colour SBA Off', + 'Neutral SBA On, Color SBA On' => 'Neutral SBA On, Colour SBA On', + }, + }, + 'SceneColorimetryEstimates' => 'Scene Colourimetry Estimates', + 'SceneMode' => { + PrintConv => { + 'Color Effects' => 'Colour Effects', + 'My Color' => 'My Colour', + }, + }, + 'ScreenMinimumColorBitDepth' => 'Screen Minimum Colour Bit Depth', + 'SegmentedBlueColorTableData' => 'Segmented Blue Colour Table Data', + 'SegmentedGreenColorTableData' => 'Segmented Green Colour Table Data', + 'SegmentedRedColorTableData' => 'Segmented Red Colour Table Data', + 'SensingMethod' => { + PrintConv => { + 'Color sequential area' => 'Colour sequential area', + 'Color sequential linear' => 'Colour sequential linear', + 'One-chip color area' => 'One-chip colour area', + 'Three-chip color area' => 'Three-chip colour area', + 'Two-chip color area' => 'Two-chip colour area', + }, + }, + 'ShootingMode' => { + PrintConv => { + 'Color Effects' => 'Colour Effects', + 'My Color' => 'My Colour', + }, + }, + 'ShutterPresentationColorCIELabVal' => 'Shutter Presentation Colour CIE Lab Val', + 'SmartAlbumColor' => 'Smart Album Colour', + 'SpecialEffectsOpticalFilter' => { + PrintConv => { + 'Colored' => 'Coloured', + }, + }, + 'StandardRawColorTone' => 'Standard Raw Colour Tone', + 'StdOutputColorMode' => 'Std Output Colour Mode', + 'StreamColor' => 'Stream Colour', + 'SubfileType' => { + PrintConv => { + 'Color IW44' => 'Colour IW44', + }, + }, + 'SubimageColor' => 'Subimage Colour', + 'SwatchColorantA' => 'Swatch Colourant A', + 'SwatchColorantB' => 'Swatch Colourant B', + 'SwatchColorantBlack' => 'Swatch Colourant Black', + 'SwatchColorantBlue' => 'Swatch Colourant Blue', + 'SwatchColorantCyan' => 'Swatch Colourant Cyan', + 'SwatchColorantGray' => 'Swatch Colourant Gray', + 'SwatchColorantGreen' => 'Swatch Colourant Green', + 'SwatchColorantL' => 'Swatch Colourant L', + 'SwatchColorantMagenta' => 'Swatch Colourant Magenta', + 'SwatchColorantMode' => 'Swatch Colourant Mode', + 'SwatchColorantRed' => 'Swatch Colourant Red', + 'SwatchColorantSwatchName' => 'Swatch Colourant Swatch Name', + 'SwatchColorantTint' => 'Swatch Colourant Tint', + 'SwatchColorantType' => 'Swatch Colourant Type', + 'SwatchColorantYellow' => 'Swatch Colourant Yellow', + 'SwatchGroupsColorants' => 'Swatch Groups Colourants', + 'TestTarget' => { + PrintConv => { + 'Color Chart' => 'Colour Chart', + }, + }, + 'TextColor' => 'Text Colour', + 'ToneCurveColorSpace' => 'Tone Curve Colour Space', + 'ToningEffect' => { + PrintConv => { + 'Color' => 'Colour', + }, + }, + 'TypeOfOriginal' => { + PrintConv => { + 'Color Document' => 'Colour Document', + 'Color Print' => 'Colour Print', + }, + }, + 'UCRBG' => 'Under Colour Removal & Black Gen.', + 'USPTOOriginalContentType' => { + PrintConv => { + 'Color' => 'Colour', + }, + }, + 'UltrasoundColorDataPresent' => 'Ultrasound Colour Data Present', + 'UnderflowColor' => 'Underflow Colour', + 'Unsharp1Color' => 'Unsharp 1 Colour', + 'Unsharp2Color' => 'Unsharp 2 Colour', + 'Unsharp3Color' => 'Unsharp 3 Colour', + 'Unsharp4Color' => 'Unsharp 4 Colour', + 'VideoAlphaPremultipleColor' => 'Video Alpha Premultiple Colour', + 'VideoAlphaPremultipleColorA' => 'Video Alpha Premultiple Colour A', + 'VideoAlphaPremultipleColorB' => 'Video Alpha Premultiple Colour B', + 'VideoAlphaPremultipleColorBlack' => 'Video Alpha Premultiple Colour Black', + 'VideoAlphaPremultipleColorBlue' => 'Video Alpha Premultiple Colour Blue', + 'VideoAlphaPremultipleColorCyan' => 'Video Alpha Premultiple Colour Cyan', + 'VideoAlphaPremultipleColorGray' => 'Video Alpha Premultiple Colour Gray', + 'VideoAlphaPremultipleColorGreen' => 'Video Alpha Premultiple Colour Green', + 'VideoAlphaPremultipleColorL' => 'Video Alpha Premultiple Colour L', + 'VideoAlphaPremultipleColorMagenta' => 'Video Alpha Premultiple Colour Magenta', + 'VideoAlphaPremultipleColorMode' => 'Video Alpha Premultiple Colour Mode', + 'VideoAlphaPremultipleColorRed' => 'Video Alpha Premultiple Colour Red', + 'VideoAlphaPremultipleColorSwatchName' => 'Video Alpha Premultiple Colour Swatch Name', + 'VideoAlphaPremultipleColorTint' => 'Video Alpha Premultiple Colour Tint', + 'VideoAlphaPremultipleColorType' => 'Video Alpha Premultiple Colour Type', + 'VideoAlphaPremultipleColorYellow' => 'Video Alpha Premultiple Colour Yellow', + 'VideoColorKind' => 'Video Colour Kind', + 'VideoColorSpace' => 'Video Colour Space', + 'VisualColor' => { + Description => 'Visual Colour', + PrintConv => { + 'Color' => 'Colour', + }, + }, + 'WBAdjColorTemp' => 'WB Adj Colour Temp', + 'WBAdjLighting' => { + PrintConv => { + 'High Color Rendering Fluorescent (3700K)' => 'High Colour Rendering Fluorescent (1)', + 'High Color Rendering Fluorescent (5000K)' => 'High Colour Rendering Fluorescent (3)', + 'High Color Rendering Fluorescent (cool white)' => 'High Colour Rendering Fluorescent (2)', + 'High Color Rendering Fluorescent (daylight)' => 'High Colour Rendering Fluorescent (4)', + 'High Color Rendering Fluorescent (warm white)' => 'High Colour Rendering Fluorescent (0)', + 'Sodium Vapor Lamps' => 'Sodium Vapour Lamps', + 'Standard Fluorescent (high temperature mercury vapor)' => 'Standard Fluorescent (high temperature mercury vapour)', + }, + }, + 'WatercolorFilter' => 'Watercolour Filter', + 'WhiteBalance' => { + PrintConv => { + 'Color Filter' => 'Colour Filter', + 'Color Temperature' => 'Colour Temperature', + 'Color Temperature Enhancement' => 'Colour Temperature Enhancement', + 'Color Temperature/Color Filter' => 'Colour Temperature/Colour Filter', + }, + }, + 'WhiteBalance2' => { + PrintConv => { + 'Auto (Keep Warm Color Off)' => 'Auto (Keep Warm Colour Off)', + }, + }, + 'WhiteBalanceSet' => { + PrintConv => { + 'Set Color Temperature 1' => 'Set Colour Temperature 1', + 'Set Color Temperature 2' => 'Set Colour Temperature 2', + 'Set Color Temperature 3' => 'Set Colour Temperature 3', + }, + }, + 'WhiteBalanceSetting' => { + PrintConv => { + 'Color Temperature/Color Filter' => 'Colour Temperature/Colour Filter', + }, + }, + 'WorkColorSpace' => { + Description => 'Work Colour Space', + PrintConv => { + 'ColorMatch RGB' => 'ColourMatch RGB', + }, + }, + 'XMethod' => { + PrintConv => { + 'Color Closest Pixel and Alpha Linear Interpolation' => 'Colour Closest Pixel and Alpha Linear Interpolation', + 'Color Linear Interpolation and Alpha Closest Pixel' => 'Colour Linear Interpolation and Alpha Closest Pixel', + }, + }, + 'YMethod' => { + PrintConv => { + 'Color Closest Pixel and Alpha Linear Interpolation' => 'Colour Closest Pixel and Alpha Linear Interpolation', + 'Color Linear Interpolation and Alpha Closest Pixel' => 'Colour Linear Interpolation and Alpha Closest Pixel', + }, + }, +); + +1; # end + + +__END__ + +=head1 NAME + +Image::ExifTool::Lang::en_ca.pm - ExifTool Canadian English language translations + +=head1 DESCRIPTION + +This file is used by Image::ExifTool to generate localized tag descriptions +and values. + +=head1 AUTHOR + +Copyright 2003-2019, Phil Harvey (phil at owl.phy.queensu.ca) + +This library is free software; you can redistribute it and/or modify it +under the same terms as Perl itself. + +=head1 SEE ALSO + +L<Image::ExifTool(3pm)|Image::ExifTool>, +L<Image::ExifTool::TagInfoXML(3pm)|Image::ExifTool::TagInfoXML> + +=cut diff --git a/lib/Image/ExifTool/Lang/en_gb.pm b/lib/Image/ExifTool/Lang/en_gb.pm new file mode 100644 index 0000000..3b83ae9 --- /dev/null +++ b/lib/Image/ExifTool/Lang/en_gb.pm @@ -0,0 +1,1045 @@ +#------------------------------------------------------------------------------ +# File: en_gb.pm +# +# Description: ExifTool British English language translations +# +# Notes: This file generated automatically by Image::ExifTool::TagInfoXML +#------------------------------------------------------------------------------ + +package Image::ExifTool::Lang::en_gb; + +use strict; +use vars qw($VERSION); + +$VERSION = '1.13'; + +%Image::ExifTool::Lang::en_gb::Translate = ( + 'AboveColor' => 'Above Colour', + 'AdvancedFilter' => { + PrintConv => { + 'Partial Color Blue' => 'Partial Colour Blue', + 'Partial Color Green' => 'Partial Colour Green', + 'Partial Color Orange' => 'Partial Colour Orange', + 'Partial Color Purple' => 'Partial Colour Purple', + 'Partial Color Red' => 'Partial Colour Red', + 'Partial Color Yellow' => 'Partial Colour Yellow', + 'Pop Color' => 'Pop Colour', + }, + }, + 'AdvancedSceneMode' => { + PrintConv => { + 'Color Select' => 'Colour Select', + }, + }, + 'AllColorFlatField1' => 'All Colour Flat Field 1', + 'AllColorFlatField2' => 'All Colour Flat Field 2', + 'AllColorFlatField3' => 'All Colour Flat Field 3', + 'Alpha' => { + PrintConv => { + 'Alpha Exists (W color component)' => 'Alpha Exists (W colour component)', + 'Alpha Exists (color not premultiplied)' => 'Alpha Exists (colour not premultiplied)', + 'Alpha Exists (color premultiplied)' => 'Alpha Exists (colour premultiplied)', + }, + }, + 'AlternateDuotoneColors' => 'Alternate Duotone Colours', + 'AlternateSpotColors' => 'Alternate Spot Colours', + 'ArtFilter' => { + PrintConv => { + 'Pale & Light Color' => 'Pale & Light Colour', + 'Pale & Light Color II' => 'Pale & Light Colour II', + 'Partial Color' => 'Partial Colour', + 'Partial Color II' => 'Partial Colour II', + 'Partial Color III' => 'Partial Colour III', + 'Watercolor' => 'Watercolour', + 'Watercolor I' => 'Watercolour I', + 'Watercolor II' => 'Watercolour II', + }, + }, + 'ArtFilterEffect' => { + PrintConv => { + 'Green Color Filter' => 'Green Colour Filter', + 'No Color Filter' => 'No Colour Filter', + 'Orange Color Filter' => 'Orange Colour Filter', + 'Pale & Light Color' => 'Pale & Light Colour', + 'Pale & Light Color II' => 'Pale & Light Colour II', + 'Partial Color' => 'Partial Colour', + 'Partial Color II' => 'Partial Colour II', + 'Partial Color III' => 'Partial Colour III', + 'Red Color Filter' => 'Red Colour Filter', + 'Watercolor' => 'Watercolour', + 'Watercolor I' => 'Watercolour I', + 'Watercolor II' => 'Watercolour II', + 'Yellow Color Filter' => 'Yellow Colour Filter', + }, + }, + 'AudioIsInitialized' => 'Audio Is Initialised', + 'AutoAFPointColorTracking' => 'Auto AF Point Colour Tracking', + 'AutoLightingOptimizer' => 'Auto Lighting Optimiser', + 'AutoLightingOptimizerOn' => 'Auto Lighting Optimiser On', + 'BackgroundColor' => 'Background Colour', + 'BackgroundColorIndicator' => { + Description => 'Background Colour Indicator', + PrintConv => { + 'Specified Background Color' => 'Specified Background Colour', + 'Unspecified Background Color' => 'Unspecified Background Colour', + }, + }, + 'BackgroundColorValue' => 'Background Colour Value', + 'BasicColorImageSequence' => 'Basic Colour Image Sequence', + 'BelowColor' => 'Below Colour', + 'BestShotMode' => { + PrintConv => { + 'Water Color' => 'Water Colour', + }, + }, + 'BkColor' => 'Background Colour', + 'BluePaletteColorTableData' => 'Blue Palette Colour Table Data', + 'BluePaletteColorTableDescriptor' => 'Blue Palette Colour Table Descriptor', + 'BorderColor' => 'Border Colour', + 'CFAPlaneColor' => 'CFA Plane Colour', + 'CameraColorCalibration01' => 'Camera Colour Calibration 01', + 'CameraColorCalibration02' => 'Camera Colour Calibration 02', + 'CameraColorCalibration03' => 'Camera Colour Calibration 03', + 'CameraColorCalibration04' => 'Camera Colour Calibration 04', + 'CameraColorCalibration05' => 'Camera Colour Calibration 05', + 'CameraColorCalibration06' => 'Camera Colour Calibration 06', + 'CameraColorCalibration07' => 'Camera Colour Calibration 07', + 'CameraColorCalibration08' => 'Camera Colour Calibration 08', + 'CameraColorCalibration09' => 'Camera Colour Calibration 09', + 'CameraColorCalibration10' => 'Camera Colour Calibration 10', + 'CameraColorCalibration11' => 'Camera Colour Calibration 11', + 'CameraColorCalibration12' => 'Camera Colour Calibration 12', + 'CameraColorCalibration13' => 'Camera Colour Calibration 13', + 'CameraColorCalibration14' => 'Camera Colour Calibration 14', + 'CameraColorCalibration15' => 'Camera Colour Calibration 15', + 'CameraRawColorTone' => 'Camera Raw Colour Tone', + 'CanonColorInfo1' => 'Canon Colour Info 1', + 'CanonColorInfo2' => 'Canon Colour Info 2', + 'ChromaticityColorant' => 'Chromaticity Colourant', + 'CodingMethods' => { + PrintConv => { + 'JBIG color' => 'JBIG colour', + }, + }, + 'Color' => { + Description => 'Colour', + PrintConv => { + 'Color' => 'Colour', + }, + }, + 'ColorAberrationControl' => 'Colour Aberration Control', + 'ColorAdjustment' => 'Colour Adjustment', + 'ColorAdjustmentMode' => 'Colour Adjustment Mode', + 'ColorAverages' => 'Colour Averages', + 'ColorBW' => 'Colour BW', + 'ColorBalance' => 'Colour Balance', + 'ColorBalanceAdj' => 'Colour Balance Adj', + 'ColorBalanceBlue' => 'Colour Balance Blue', + 'ColorBalanceGreen' => 'Colour Balance Green', + 'ColorBalanceRed' => 'Colour Balance Red', + 'ColorBalanceUnknown' => 'Colour Balance Unknown', + 'ColorBalanceVersion' => 'Colour Balance Version', + 'ColorBitDepth' => 'Colour Bit Depth', + 'ColorBlur' => 'Colour Blur', + 'ColorBlurOn' => 'Colour Blur On', + 'ColorBoostLevel' => 'Colour Boost Level', + 'ColorBoostType' => 'Colour Boost Type', + 'ColorBooster' => 'Colour Booster', + 'ColorCalibrationMatrix' => 'Colour Calibration Matrix', + 'ColorCasts' => 'Colour Casts', + 'ColorCharacterization' => 'Colour Characterization', + 'ColorClass' => 'Colour Class', + 'ColorCompensationFilter' => 'Colour Compensation Filter', + 'ColorCompensationFilterCustom' => 'Colour Compensation Filter Custom', + 'ColorCompensationFilterSet' => 'Colour Compensation Filter Set', + 'ColorComponents' => 'Colour Components', + 'ColorControl' => 'Colour Control', + 'ColorCorrection' => 'Colour Correction', + 'ColorCreatorEffect' => 'Colour Creator Effect', + 'ColorDataVersion' => 'Colour Data Version', + 'ColorDescriptor' => 'Colour Descriptor', + 'ColorEffect' => 'Colour Effect', + 'ColorFieldCode' => 'Colour Field Code', + 'ColorFilter' => 'Colour Filter', + 'ColorGain' => 'Colour Gain', + 'ColorGroup' => 'Colour Group', + 'ColorHalftoningInfo' => 'Colour Halftoning Info', + 'ColorHue' => 'Colour Hue', + 'ColorImagePrintingFlag' => 'Colour Image Printing Flag', + 'ColorLabel' => 'Colour Label', + 'ColorMap' => 'Colour Map', + 'ColorMatrix' => 'Colour Matrix', + 'ColorMatrix1' => 'Colour Matrix 1', + 'ColorMatrix2' => 'Colour Matrix 2', + 'ColorMatrixA' => 'Colour Matrix A', + 'ColorMatrixAdobeRGB' => 'Colour Matrix Adobe RGB', + 'ColorMatrixB' => 'Colour Matrix B', + 'ColorMatrixNumber' => 'Colour Matrix Number', + 'ColorMatrixSRGB' => 'Colour Matrix sRGB', + 'ColorMode' => { + Description => 'Colour Mode', + PrintConv => { + 'Indexed Color' => 'Indexed Colour', + 'Natural color' => 'Natural colour', + 'Neutral Color' => 'Neutral Colour', + 'RGB Color' => 'RGB Colour', + 'Saturated Color' => 'Saturated Colour', + 'Vivid color' => 'Vivid colour', + }, + }, + 'ColorMoireReduction' => 'Colour Moire Reduction', + 'ColorMoireReductionMode' => 'Colour Moire Reduction Mode', + 'ColorNoiseReduction' => 'Colour Noise Reduction', + 'ColorNoiseReductionDetail' => 'Colour Noise Reduction Detail', + 'ColorNoiseReductionIntensity' => 'Colour Noise Reduction Intensity', + 'ColorNoiseReductionSharpness' => 'Colour Noise Reduction Sharpness', + 'ColorNoiseReductionSmoothness' => 'Colour Noise Reduction Smoothness', + 'ColorObjBackType' => 'Colour Obj Back Type', + 'ColorObjName' => 'Colour Obj Name', + 'ColorObjType' => 'Colour Obj Type', + 'ColorObjVersion' => 'Colour Obj Version', + 'ColorPalette' => 'Colour Palette', + 'ColorPlanes' => 'Colour Planes', + 'ColorPrimaries' => 'Colour Primaries', + 'ColorProfile' => 'Colour Profile', + 'ColorProfileSettings' => 'Colour Profile Settings', + 'ColorRangeLevels' => 'Colour Range Levels', + 'ColorRepresentation' => 'Colour Representation', + 'ColorReproduction' => 'Colour Reproduction', + 'ColorResolutionDepth' => 'Colour Resolution Depth', + 'ColorResponseUnit' => 'Colour Response Unit', + 'ColorSamplersResource' => 'Colour Samplers Resource', + 'ColorSamplersResource2' => 'Colour Samplers Resource 2', + 'ColorSaturationAdj' => 'Colour Saturation Adj', + 'ColorSequence' => 'Colour Sequence', + 'ColorSiting' => 'Colour Siting', + 'ColorSpace' => { + Description => 'Colour Space', + PrintConv => { + 'Embedded Color Profile' => 'Embedded Colour Profile', + 'Linked Color Profile' => 'Linked Colour Profile', + 'No color space specified' => 'No colour space specified', + 'Windows Color Space' => 'Windows Colour Space', + }, + }, + 'ColorSpaceData' => 'Colour Space Data', + 'ColorSpecApproximation' => 'Colour Spec Approximation', + 'ColorSpecData' => 'Colour Spec Data', + 'ColorSpecMethod' => { + Description => 'Colour Spec Method', + PrintConv => { + 'Vendor Color' => 'Vendor Colour', + }, + }, + 'ColorSpecPrecedence' => 'Colour Spec Precedence', + 'ColorSpecification' => 'Colour Specification', + 'ColorTable' => 'Colour Table', + 'ColorTempAsShot' => 'Colour Temp As Shot', + 'ColorTempAuto' => 'Colour Temp Auto', + 'ColorTempCloudy' => 'Colour Temp Cloudy', + 'ColorTempCustom' => 'Colour Temp Custom', + 'ColorTempCustom1' => 'Colour Temp Custom 1', + 'ColorTempCustom2' => 'Colour Temp Custom 2', + 'ColorTempDaylight' => 'Colour Temp Daylight', + 'ColorTempFlash' => 'Colour Temp Flash', + 'ColorTempFlashData' => 'Colour Temp Flash Data', + 'ColorTempFluorescent' => 'Colour Temp Fluorescent', + 'ColorTempFluorescentD' => 'Colour Temp Fluorescent D', + 'ColorTempFluorescentN' => 'Colour Temp Fluorescent N', + 'ColorTempFluorescentW' => 'Colour Temp Fluorescent W', + 'ColorTempKelvin' => 'Colour Temp Kelvin', + 'ColorTempMeasured' => 'Colour Temp Measured', + 'ColorTempPC1' => 'Colour Temp PC1', + 'ColorTempPC2' => 'Colour Temp PC2', + 'ColorTempPC3' => 'Colour Temp PC3', + 'ColorTempShade' => 'Colour Temp Shade', + 'ColorTempTungsten' => 'Colour Temp Tungsten', + 'ColorTempUnknown' => 'Colour Temp Unknown', + 'ColorTempUnknown10' => 'Colour Temp Unknown 10', + 'ColorTempUnknown11' => 'Colour Temp Unknown 11', + 'ColorTempUnknown12' => 'Colour Temp Unknown 12', + 'ColorTempUnknown13' => 'Colour Temp Unknown 13', + 'ColorTempUnknown14' => 'Colour Temp Unknown 14', + 'ColorTempUnknown15' => 'Colour Temp Unknown 15', + 'ColorTempUnknown16' => 'Colour Temp Unknown 16', + 'ColorTempUnknown17' => 'Colour Temp Unknown 17', + 'ColorTempUnknown18' => 'Colour Temp Unknown 18', + 'ColorTempUnknown19' => 'Colour Temp Unknown 19', + 'ColorTempUnknown2' => 'Colour Temp Unknown 2', + 'ColorTempUnknown20' => 'Colour Temp Unknown 20', + 'ColorTempUnknown21' => 'Colour Temp Unknown 21', + 'ColorTempUnknown22' => 'Colour Temp Unknown 22', + 'ColorTempUnknown23' => 'Colour Temp Unknown 23', + 'ColorTempUnknown24' => 'Colour Temp Unknown 24', + 'ColorTempUnknown25' => 'Colour Temp Unknown 25', + 'ColorTempUnknown26' => 'Colour Temp Unknown 26', + 'ColorTempUnknown27' => 'Colour Temp Unknown 27', + 'ColorTempUnknown28' => 'Colour Temp Unknown 28', + 'ColorTempUnknown29' => 'Colour Temp Unknown 29', + 'ColorTempUnknown3' => 'Colour Temp Unknown 3', + 'ColorTempUnknown30' => 'Colour Temp Unknown 30', + 'ColorTempUnknown4' => 'Colour Temp Unknown 4', + 'ColorTempUnknown5' => 'Colour Temp Unknown 5', + 'ColorTempUnknown6' => 'Colour Temp Unknown 6', + 'ColorTempUnknown7' => 'Colour Temp Unknown 7', + 'ColorTempUnknown8' => 'Colour Temp Unknown 8', + 'ColorTempUnknown9' => 'Colour Temp Unknown 9', + 'ColorTemperature' => 'Colour Temperature', + 'ColorTemperatureAdj' => 'Colour Temperature Adj', + 'ColorTemperatureAuto' => 'Colour Temperature Auto', + 'ColorTemperatureBG' => 'Colour Temperature BG', + 'ColorTemperatureCustom' => 'Colour Temperature Custom', + 'ColorTemperatureRG' => 'Colour Temperature RG', + 'ColorTemperatureSet' => 'Colour Temperature Set', + 'ColorTemperatureSetting' => { + Description => 'Colour Temperature Setting', + PrintConv => { + 'Color Filter' => 'Colour Filter', + }, + }, + 'ColorTone' => 'Colour Tone', + 'ColorToneAdj' => 'Colour Tone Adj', + 'ColorToneAuto' => 'Colour Tone Auto', + 'ColorToneFaithful' => 'Colour Tone Faithful', + 'ColorToneLandscape' => 'Colour Tone Landscape', + 'ColorToneMonochrome' => 'Colour Tone Monochrome', + 'ColorToneNeutral' => 'Colour Tone Neutral', + 'ColorTonePortrait' => 'Colour Tone Portrait', + 'ColorToneStandard' => 'Colour Tone Standard', + 'ColorToneUserDef1' => 'Colour Tone User Def 1', + 'ColorToneUserDef2' => 'Colour Tone User Def 2', + 'ColorToneUserDef3' => 'Colour Tone User Def 3', + 'ColorTransferFuncs' => 'Colour Transfer Funcs', + 'ColorTransform' => 'Colour Transform', + 'ColorTwistMatrix' => 'Colour Twist Matrix', + 'ColorType' => { + Description => 'Colour Type', + PrintConv => { + 'Color' => 'Colour', + 'Color Alpha' => 'Colour Alpha', + }, + }, + 'Colorant1Coordinates' => 'Colourant 1 Coordinates', + 'Colorant1Name' => 'Colourant 1 Name', + 'Colorant2Coordinates' => 'Colourant 2 Coordinates', + 'Colorant2Name' => 'Colourant 2 Name', + 'Colorant3Coordinates' => 'Colourant 3 Coordinates', + 'Colorant3Name' => 'Colourant 3 Name', + 'ColorantA' => 'Colourant A', + 'ColorantB' => 'Colourant B', + 'ColorantBlack' => 'Colourant Black', + 'ColorantBlue' => 'Colourant Blue', + 'ColorantCount' => 'Colourant Count', + 'ColorantCyan' => 'Colourant Cyan', + 'ColorantGray' => 'Colourant Gray', + 'ColorantGreen' => 'Colourant Green', + 'ColorantL' => 'Colourant L', + 'ColorantMagenta' => 'Colourant Magenta', + 'ColorantMode' => 'Colourant Mode', + 'ColorantOrder' => 'Colourant Order', + 'ColorantRed' => 'Colourant Red', + 'ColorantSwatchName' => 'Colourant Swatch Name', + 'ColorantTableOut' => 'Colourant Table Out', + 'ColorantTint' => 'Colourant Tint', + 'ColorantType' => 'Colourant Type', + 'ColorantYellow' => 'Colourant Yellow', + 'Colorants' => 'Colourants', + 'ColorimetricIntentImageState' => 'Colourimetric Intent Image State', + 'ColorimetricReference' => 'Colourimetric Reference', + 'Colorimetry' => 'Colourimetry', + 'ColorimetryCode' => 'Colourimetry Code', + 'Colors' => 'Colours', + 'Compression' => { + PrintConv => { + 'JBIG Color' => 'JBIG Colour', + }, + }, + 'ContrastMode' => { + PrintConv => { + 'Dynamic (Color Film)' => 'Dynamic (Colour Film)', + 'Dynamic Art (My Color)' => 'Dynamic Art (My Colour)', + 'Elegant (My Color)' => 'Elegant (My Colour)', + 'Nature (Color Film)' => 'Nature (Colour Film)', + 'Nostalgic (Color Film)' => 'Nostalgic (Colour Film)', + 'Retro (My Color)' => 'Retro (My Colour)', + 'Smooth (Color Film) or Pure (My Color)' => 'Smooth (Colour Film) or Pure (My Colour)', + 'Vibrant (Color Film) or Expressive (My Color)' => 'Vibrant (Colour Film) or Expressive (My Colour)', + }, + }, + 'CustomColorTone' => 'Custom Colour Tone', + 'D-LightingHQColorBoost' => 'D-Lighting HQ Colour Boost', + 'D-LightingHSColorBoost' => 'D-Lighting HS Colour Boost', + 'D-RangeOptimizerHighlight' => 'D-Range Optimiser Highlight', + 'D-RangeOptimizerMode' => 'D-Range Optimiser Mode', + 'D-RangeOptimizerShadow' => 'D-Range Optimiser Shadow', + 'D-RangeOptimizerValue' => 'D-Range Optimiser Value', + 'DateTimeDigitized' => 'Date/Time Digitised', + 'DefHilite' => 'Use Default Highlight Colour', + 'DefaultImageColor' => 'Default Image Colour', + 'DefineQuantizationTable' => 'Define Quantisation Table', + 'DeltaType' => { + PrintConv => { + 'Color Addition' => 'Colour Addition', + 'Color Replacement' => 'Colour Replacement', + }, + }, + 'DigitalFilter01' => { + PrintConv => { + 'Color Filter' => 'Colour Filter', + 'Extract Color' => 'Extract Colour', + 'Invert Color' => 'Invert Colour', + 'Replace Color' => 'Replace Colour', + 'Unicolor Bold' => 'Unicolour Bold', + 'Water Color' => 'Water Colour', + }, + }, + 'DigitalFilter02' => { + PrintConv => { + 'Color Filter' => 'Colour Filter', + 'Extract Color' => 'Extract Colour', + 'Invert Color' => 'Invert Colour', + 'Water Color' => 'Water Colour', + }, + }, + 'DigitalFilter03' => { + PrintConv => { + 'Color Filter' => 'Colour Filter', + 'Extract Color' => 'Extract Colour', + 'Invert Color' => 'Invert Colour', + 'Water Color' => 'Water Colour', + }, + }, + 'DigitalFilter04' => { + PrintConv => { + 'Color Filter' => 'Colour Filter', + 'Extract Color' => 'Extract Colour', + 'Invert Color' => 'Invert Colour', + 'Water Color' => 'Water Colour', + }, + }, + 'DigitalFilter05' => { + PrintConv => { + 'Color Filter' => 'Colour Filter', + 'Extract Color' => 'Extract Colour', + 'Invert Color' => 'Invert Colour', + 'Water Color' => 'Water Colour', + }, + }, + 'DigitalFilter06' => { + PrintConv => { + 'Color Filter' => 'Colour Filter', + 'Extract Color' => 'Extract Colour', + 'Invert Color' => 'Invert Colour', + 'Water Color' => 'Water Colour', + }, + }, + 'DigitalFilter07' => { + PrintConv => { + 'Color Filter' => 'Colour Filter', + 'Extract Color' => 'Extract Colour', + 'Invert Color' => 'Invert Colour', + 'Water Color' => 'Water Colour', + }, + }, + 'DigitalFilter08' => { + PrintConv => { + 'Color Filter' => 'Colour Filter', + 'Extract Color' => 'Extract Colour', + 'Invert Color' => 'Invert Colour', + 'Water Color' => 'Water Colour', + }, + }, + 'DigitalFilter09' => { + PrintConv => { + 'Color Filter' => 'Colour Filter', + 'Extract Color' => 'Extract Colour', + 'Invert Color' => 'Invert Colour', + 'Water Color' => 'Water Colour', + }, + }, + 'DigitalFilter10' => { + PrintConv => { + 'Color Filter' => 'Colour Filter', + 'Extract Color' => 'Extract Colour', + 'Invert Color' => 'Invert Colour', + 'Water Color' => 'Water Colour', + }, + }, + 'DigitalFilter11' => { + PrintConv => { + 'Color Filter' => 'Colour Filter', + 'Extract Color' => 'Extract Colour', + 'Invert Color' => 'Invert Colour', + 'Water Color' => 'Water Colour', + }, + }, + 'DigitalFilter12' => { + PrintConv => { + 'Color Filter' => 'Colour Filter', + 'Extract Color' => 'Extract Colour', + 'Invert Color' => 'Invert Colour', + 'Water Color' => 'Water Colour', + }, + }, + 'DigitalFilter13' => { + PrintConv => { + 'Color Filter' => 'Colour Filter', + 'Extract Color' => 'Extract Colour', + 'Invert Color' => 'Invert Colour', + 'Water Color' => 'Water Colour', + }, + }, + 'DigitalFilter14' => { + PrintConv => { + 'Color Filter' => 'Colour Filter', + 'Extract Color' => 'Extract Colour', + 'Invert Color' => 'Invert Colour', + 'Water Color' => 'Water Colour', + }, + }, + 'DigitalFilter15' => { + PrintConv => { + 'Color Filter' => 'Colour Filter', + 'Extract Color' => 'Extract Colour', + 'Invert Color' => 'Invert Colour', + 'Water Color' => 'Water Colour', + }, + }, + 'DigitalFilter16' => { + PrintConv => { + 'Color Filter' => 'Colour Filter', + 'Extract Color' => 'Extract Colour', + 'Invert Color' => 'Invert Colour', + 'Water Color' => 'Water Colour', + }, + }, + 'DigitalFilter17' => { + PrintConv => { + 'Color Filter' => 'Colour Filter', + 'Extract Color' => 'Extract Colour', + 'Invert Color' => 'Invert Colour', + 'Water Color' => 'Water Colour', + }, + }, + 'DigitalFilter18' => { + PrintConv => { + 'Color Filter' => 'Colour Filter', + 'Extract Color' => 'Extract Colour', + 'Invert Color' => 'Invert Colour', + 'Water Color' => 'Water Colour', + }, + }, + 'DigitalFilter19' => { + PrintConv => { + 'Color Filter' => 'Colour Filter', + 'Extract Color' => 'Extract Colour', + 'Invert Color' => 'Invert Colour', + 'Water Color' => 'Water Colour', + }, + }, + 'DigitalFilter20' => { + PrintConv => { + 'Color Filter' => 'Colour Filter', + 'Extract Color' => 'Extract Colour', + 'Invert Color' => 'Invert Colour', + 'Water Color' => 'Water Colour', + }, + }, + 'DisplayUnits' => { + PrintConv => { + 'meters' => 'Metres', + }, + }, + 'DriveMode' => { + PrintConv => { + 'D-Range Optimizer Bracketing High' => 'D-Range Optimiser Bracketing High', + 'D-Range Optimizer Bracketing Low' => 'D-Range Optimiser Bracketing Low', + }, + }, + 'DriveMode2' => { + PrintConv => { + 'D-Range Optimizer Bracketing High' => 'D-Range Optimiser Bracketing High', + 'D-Range Optimizer Bracketing Low' => 'D-Range Optimiser Bracketing Low', + }, + }, + 'DynamicRangeOptimizer' => 'Dynamic Range Optimiser', + 'DynamicRangeOptimizerBracket' => 'Dynamic Range Optimiser Bracket', + 'DynamicRangeOptimizerLevel' => 'Dynamic Range Optimiser Level', + 'DynamicRangeOptimizerMode' => 'Dynamic Range Optimiser Mode', + 'DynamicRangeOptimizerSetting' => 'Dynamic Range Optimiser Setting', + 'EasyMode' => { + PrintConv => { + 'Color Accent' => 'Colour Accent', + 'Color Swap' => 'Colour Swap', + 'My Colors' => 'My Colours', + }, + }, + 'EmbeddedImageColorSpace' => 'Embedded Image Colour Space', + 'ExposureProgram' => { + PrintConv => { + 'Partial Color Blue' => 'Partial Colour Blue', + 'Partial Color Green' => 'Partial Colour Green', + 'Partial Color Red' => 'Partial Colour Red', + 'Partial Color Yellow' => 'Partial Colour Yellow', + 'Pop Color' => 'Pop Colour', + }, + }, + 'FaithfulRawColorTone' => 'Faithful Raw Colour Tone', + 'FaxProfile' => { + PrintConv => { + 'Lossless color and grayscale, L' => 'Lossless colour and grayscale, L', + 'Lossy color and grayscale, C' => 'Lossy colour and grayscale, C', + }, + }, + 'FgColor' => 'Foreground Colour', + 'FileFormat' => { + PrintConv => { + 'JPEG (lossy/non-quantization toggled)' => 'JPEG (lossy/non-quantisation toggled)', + 'JPEG (non-quantization)' => 'JPEG (non-quantisation)', + }, + }, + 'FilmColorProcess' => 'Film Colour Process', + 'FilmMode' => { + PrintConv => { + 'Dynamic (color)' => 'Dynamic (colour)', + 'Nature (color)' => 'Nature (colour)', + 'Smooth (color)' => 'Smooth (colour)', + 'Standard (color)' => 'Standard (colour)', + }, + }, + 'FlagColor' => 'Flag Colour', + 'FlashColorFilter' => 'Flash Colour Filter', + 'FocalPlaneColorimetryEstimates' => 'Focal Plane Colourimetry Estimates', + 'GammaColorTone' => 'Gamma Colour Tone', + 'GenOpColor' => 'Gen Op Colour', + 'GenreID' => { + PrintConv => { + 'Books|Kids|Basic Concepts|Colors' => 'Books|Kids|Basic Concepts|Colours', + }, + }, + 'GreenPaletteColorTableData' => 'Green Palette Colour Table Data', + 'GreenPaletteColorTableDescriptor' => 'Green Palette Colour Table Descriptor', + 'HasColorMap' => 'Has Colour Map', + 'HighlightColorDistortReduct' => 'Highlight Colour Distort Reduct', + 'HiliteColor' => 'Highlight Colour', + 'ImageAlterationConstraints' => { + PrintConv => { + 'No Colorization' => 'No Colourization', + 'No De-Colorization' => 'No De-Colourization', + }, + }, + 'ImageColor' => 'Image Colour', + 'ImageColorIndicator' => { + Description => 'Image Colour Indicator', + PrintConv => { + 'Specified Image Color' => 'Specified Image Colour', + 'Unspecified Image Color' => 'Unspecified Image Colour', + }, + }, + 'ImageColorValue' => 'Image Colour Value', + 'ImageMedium' => { + PrintConv => { + 'Color hard copy' => 'Colour hard copy', + 'Color negative' => 'Colour negative', + 'Color reversal' => 'Colour reversal', + }, + }, + 'ImageOptimization' => 'Image Optimisation', + 'IndexedColorTableCount' => 'Indexed Colour Table Count', + 'InitializedDataSize' => 'Initialised Data Size', + 'InterchangeColorSpace' => 'Interchange Colour Space', + 'Isotherm1Color' => 'Isotherm 1 Colour', + 'Isotherm2Color' => 'Isotherm 2 Colour', + 'LandscapeRawColorTone' => 'Landscape Raw Colour Tone', + 'LargeBluePaletteColorTableData' => 'Large Blue Palette Colour Table Data', + 'LargeBluePaletteColorTableDescr' => 'Large Blue Palette Colour Table Descr', + 'LargeGreenPaletteColorTableData' => 'Large Green Palette Colour Table Data', + 'LargeGreenPaletteColorTableDescr' => 'Large Green Palette Colour Table Descr', + 'LargePaletteColorLookupTableUID' => 'Large Palette Colour Lookup Table UID', + 'LargeRedPaletteColorTableData' => 'Large Red Palette Colour Table Data', + 'LargeRedPaletteColorTableDescr' => 'Large Red Palette Colour Table Descr', + 'LayerBlendModes' => { + PrintConv => { + 'Color' => 'Colour', + 'Color Burn' => 'Colour Burn', + 'Color Dodge' => 'Colour Dodge', + 'Darker Color' => 'Darker Colour', + 'Lighter Color' => 'Lighter Colour', + }, + }, + 'MDColorTable' => 'MD Colour Table', + 'MDItemColorSpace' => 'MD Item Colour Space', + 'MagicFilter' => { + PrintConv => { + 'Pale & Light Color' => 'Pale & Light Colour', + 'Pale & Light Color II' => 'Pale & Light Colour II', + 'Partial Color' => 'Partial Colour', + 'Partial Color II' => 'Partial Colour II', + 'Partial Color III' => 'Partial Colour III', + 'Watercolor' => 'Watercolour', + 'Watercolor I' => 'Watercolour I', + 'Watercolor II' => 'Watercolour II', + }, + }, + 'MandatoryBackground' => { + PrintConv => { + 'Color Advisory, Image Mandatory' => 'Colour Advisory, Image Mandatory', + 'Color Mandatory, Image Advisory' => 'Colour Mandatory, Image Advisory', + 'Color and Image Advisory' => 'Colour and Image Advisory', + 'Color and Image Mandatory' => 'Colour and Image Mandatory', + }, + }, + 'MattColor' => 'Matt Colour', + 'MediaColor' => 'Media Colour', + 'ModifiedColorTemp' => 'Modified Colour Temp', + 'MonochromeColor' => 'Monochrome Colour', + 'MyColorMode' => { + Description => 'My Colour Mode', + PrintConv => { + 'Color Accent' => 'Colour Accent', + 'Color Swap' => 'Colour Swap', + }, + }, + 'NamedColor' => 'Named Colour', + 'NamedColor2' => 'Named Colour 2', + 'NeutralRawColorTone' => 'Neutral Raw Colour Tone', + 'NewColorType' => 'New Colour Type', + 'NumColors' => 'Num Colours', + 'NumImportantColors' => 'Num Important Colours', + 'OpColor' => 'Op Colour', + 'OverflowColor' => 'Overflow Colour', + 'PF25ColorMatrix' => 'PF25 Colour Matrix', + 'PaletteColorTableUID' => 'Palette Colour Table UID', + 'PaletteColors' => 'Palette Colours', + 'PhotoEffect' => { + PrintConv => { + 'My Color Data' => 'My Colour Data', + }, + }, + 'PhotometricInterpretation' => { + PrintConv => { + 'Color Filter Array' => 'Colour Filter Array', + }, + }, + 'Photoshop2ColorTable' => 'Photoshop 2 Colour Table', + 'PhotoshopFormat' => { + PrintConv => { + 'Optimized' => 'Optimised', + }, + }, + 'PictureEffect' => { + PrintConv => { + 'Partial Color (blue)' => 'Partial Colour (blue)', + 'Partial Color (green)' => 'Partial Colour (green)', + 'Partial Color (red)' => 'Partial Colour (red)', + 'Partial Color (yellow)' => 'Partial Colour (yellow)', + 'Pop Color' => 'Pop Colour', + 'Water Color' => 'Water Colour', + 'Water Color 2' => 'Water Colour 2', + }, + }, + 'PictureEffect2' => { + PrintConv => { + 'Partial Color' => 'Partial Colour', + 'Pop Color' => 'Pop Colour', + 'Water Color' => 'Water Colour', + }, + }, + 'PictureIndexedColors' => 'Picture Indexed Colours', + 'PictureMode' => { + PrintConv => { + 'Color Creator' => 'Colour Creator', + 'Color Profile 1' => 'Colour Profile 1', + 'Color Profile 2' => 'Colour Profile 2', + 'Color Profile 3' => 'Colour Profile 3', + }, + }, + 'PictureType' => { + PrintConv => { + 'Bright(ly) Colored Fish' => 'Bright(ly) Coloured Fish', + }, + }, + 'PictureWizardColor' => 'Picture Wizard Colour', + 'PortraitRawColorTone' => 'Portrait Raw Colour Tone', + 'PresetWhiteBalance' => { + PrintConv => { + 'Color Temperature' => 'Colour Temperature', + }, + }, + 'PreviewColorSpace' => 'Preview Colour Space', + 'ProfileClass' => { + PrintConv => { + 'ColorSpace Conversion Profile' => 'ColourSpace Conversion Profile', + 'NamedColor Profile' => 'Named Colour Profile', + }, + }, + 'PseudoColorType' => 'Pseudo Colour Type', + 'QuantizationDefault' => 'Quantisation Default', + 'QuantizationMethod' => { + Description => 'Quantisation Method', + PrintConv => { + 'Color Space Specific' => 'Colour Space Specific', + }, + }, + 'RGBBkCol' => 'Background Colour', + 'RGBFgCol' => 'Foreground Colour', + 'ROIDisplayColor' => 'ROI Display Colour', + 'RawColorAdj' => 'Raw Colour Adj', + 'RawDevArtFilter' => { + PrintConv => { + 'Pale & Light Color' => 'Pale & Light Colour', + 'Pale & Light Color II' => 'Pale & Light Colour II', + 'Partial Color' => 'Partial Colour', + 'Partial Color II' => 'Partial Colour II', + 'Partial Color III' => 'Partial Colour III', + 'Watercolor' => 'Watercolour', + 'Watercolor I' => 'Watercolour I', + 'Watercolor II' => 'Watercolour II', + }, + }, + 'RawDevColorSpace' => 'Raw Dev Colour Space', + 'RawDevMemoryColorEmphasis' => 'Raw Dev Memory Colour Emphasis', + 'RawDevSettings' => { + PrintConv => { + 'Color Space' => 'Colour Space', + 'WB Color Temp' => 'WB Colour Temp', + }, + }, + 'RawDevWhiteBalance' => { + PrintConv => { + 'Color Temperature' => 'Colour Temperature', + }, + }, + 'RedPaletteColorTableData' => 'Red Palette Colour Table Data', + 'RedPaletteColorTableDescriptor' => 'Red Palette Colour Table Descriptor', + 'ReflectionHardcopyOrigColorimetry' => 'Reflection Hardcopy Orig Colourimetry', + 'ReflectionPrintOutputColorimetry' => 'Reflection Print Output Colourimetry', + 'RenderingIntent' => { + PrintConv => { + 'Absolute Colorimetric (LCS_GM_ABS_COLORIMETRIC)' => 'Absolute Colourimetric (LCS_GM_ABS_COLORIMETRIC)', + 'ICC-Absolute Colorimetric' => 'ICC-Absolute Colourimetric', + 'Media-Relative Colorimetric' => 'Media-Relative Colourimetric', + }, + }, + 'RetouchHistory' => { + PrintConv => { + 'Color Custom' => 'Colour Custom', + 'Color Outline' => 'Colour Outline', + 'Color Sketch' => 'Colour Sketch', + 'Selective Color' => 'Selective Colour', + }, + }, + 'SBAInputImageColorspace' => 'SBA Input Image Colourspace', + 'SRGBRendering' => { + PrintConv => { + 'Absolute Colorimetric' => 'Absolute Colourimetric', + 'Relative Colorimetric' => 'Relative Colourimetric', + }, + }, + 'SceneBalanceAlgorithmCommand' => { + PrintConv => { + 'Neutral SBA Off, Color SBA Off' => 'Neutral SBA Off, Colour SBA Off', + 'Neutral SBA Off, Color SBA On' => 'Neutral SBA Off, Colour SBA On', + 'Neutral SBA On, Color SBA Off' => 'Neutral SBA On, Colour SBA Off', + 'Neutral SBA On, Color SBA On' => 'Neutral SBA On, Colour SBA On', + }, + }, + 'SceneColorimetryEstimates' => 'Scene Colourimetry Estimates', + 'SceneMode' => { + PrintConv => { + 'Color Effects' => 'Colour Effects', + 'My Color' => 'My Colour', + }, + }, + 'ScreenMinimumColorBitDepth' => 'Screen Minimum Colour Bit Depth', + 'SegmentedBlueColorTableData' => 'Segmented Blue Colour Table Data', + 'SegmentedGreenColorTableData' => 'Segmented Green Colour Table Data', + 'SegmentedRedColorTableData' => 'Segmented Red Colour Table Data', + 'SensingMethod' => { + PrintConv => { + 'Color sequential area' => 'Colour sequential area', + 'Color sequential linear' => 'Colour sequential linear', + 'One-chip color area' => 'One-chip colour area', + 'Three-chip color area' => 'Three-chip colour area', + 'Two-chip color area' => 'Two-chip colour area', + }, + }, + 'ShootingMode' => { + PrintConv => { + 'Color Effects' => 'Colour Effects', + 'My Color' => 'My Colour', + }, + }, + 'ShutterPresentationColorCIELabVal' => 'Shutter Presentation Colour CIE Lab Val', + 'SmartAlbumColor' => 'Smart Album Colour', + 'SpecialEffectsOpticalFilter' => { + PrintConv => { + 'Colored' => 'Coloured', + }, + }, + 'StandardRawColorTone' => 'Standard Raw Colour Tone', + 'StdOutputColorMode' => 'Std Output Colour Mode', + 'StreamColor' => 'Stream Colour', + 'SubSecTimeDigitized' => 'Sub Sec Time Digitised', + 'SubfileType' => { + PrintConv => { + 'Color IW44' => 'Colour IW44', + }, + }, + 'SubimageColor' => 'Subimage Colour', + 'SwatchColorantA' => 'Swatch Colourant A', + 'SwatchColorantB' => 'Swatch Colourant B', + 'SwatchColorantBlack' => 'Swatch Colourant Black', + 'SwatchColorantBlue' => 'Swatch Colourant Blue', + 'SwatchColorantCyan' => 'Swatch Colourant Cyan', + 'SwatchColorantGray' => 'Swatch Colourant Gray', + 'SwatchColorantGreen' => 'Swatch Colourant Green', + 'SwatchColorantL' => 'Swatch Colourant L', + 'SwatchColorantMagenta' => 'Swatch Colourant Magenta', + 'SwatchColorantMode' => 'Swatch Colourant Mode', + 'SwatchColorantRed' => 'Swatch Colourant Red', + 'SwatchColorantSwatchName' => 'Swatch Colourant Swatch Name', + 'SwatchColorantTint' => 'Swatch Colourant Tint', + 'SwatchColorantType' => 'Swatch Colourant Type', + 'SwatchColorantYellow' => 'Swatch Colourant Yellow', + 'SwatchGroupsColorants' => 'Swatch Groups Colourants', + 'TestTarget' => { + PrintConv => { + 'Color Chart' => 'Colour Chart', + }, + }, + 'TextColor' => 'Text Colour', + 'ToneCurveColorSpace' => 'Tone Curve Colour Space', + 'ToningEffect' => { + PrintConv => { + 'Color' => 'Colour', + }, + }, + 'TypeOfOriginal' => { + PrintConv => { + 'Color Document' => 'Colour Document', + 'Color Print' => 'Colour Print', + }, + }, + 'UCRBG' => 'Under Colour Removal & Black Gen.', + 'USPTOOriginalContentType' => { + PrintConv => { + 'Color' => 'Colour', + }, + }, + 'UltrasoundColorDataPresent' => 'Ultrasound Colour Data Present', + 'UnderflowColor' => 'Underflow Colour', + 'UninitializedDataSize' => 'Uninitialised Data Size', + 'Unsharp1Color' => 'Unsharp 1 Colour', + 'Unsharp2Color' => 'Unsharp 2 Colour', + 'Unsharp3Color' => 'Unsharp 3 Colour', + 'Unsharp4Color' => 'Unsharp 4 Colour', + 'VideoAlphaPremultipleColor' => 'Video Alpha Premultiple Colour', + 'VideoAlphaPremultipleColorA' => 'Video Alpha Premultiple Colour A', + 'VideoAlphaPremultipleColorB' => 'Video Alpha Premultiple Colour B', + 'VideoAlphaPremultipleColorBlack' => 'Video Alpha Premultiple Colour Black', + 'VideoAlphaPremultipleColorBlue' => 'Video Alpha Premultiple Colour Blue', + 'VideoAlphaPremultipleColorCyan' => 'Video Alpha Premultiple Colour Cyan', + 'VideoAlphaPremultipleColorGray' => 'Video Alpha Premultiple Colour Gray', + 'VideoAlphaPremultipleColorGreen' => 'Video Alpha Premultiple Colour Green', + 'VideoAlphaPremultipleColorL' => 'Video Alpha Premultiple Colour L', + 'VideoAlphaPremultipleColorMagenta' => 'Video Alpha Premultiple Colour Magenta', + 'VideoAlphaPremultipleColorMode' => 'Video Alpha Premultiple Colour Mode', + 'VideoAlphaPremultipleColorRed' => 'Video Alpha Premultiple Colour Red', + 'VideoAlphaPremultipleColorSwatchName' => 'Video Alpha Premultiple Colour Swatch Name', + 'VideoAlphaPremultipleColorTint' => 'Video Alpha Premultiple Colour Tint', + 'VideoAlphaPremultipleColorType' => 'Video Alpha Premultiple Colour Type', + 'VideoAlphaPremultipleColorYellow' => 'Video Alpha Premultiple Colour Yellow', + 'VideoColorKind' => 'Video Colour Kind', + 'VideoColorSpace' => 'Video Colour Space', + 'VisualColor' => { + Description => 'Visual Colour', + PrintConv => { + 'Color' => 'Colour', + }, + }, + 'WBAdjColorTemp' => 'WB Adj Colour Temp', + 'WBAdjLighting' => { + PrintConv => { + 'High Color Rendering Fluorescent (3700K)' => 'High Colour Rendering Fluorescent (1)', + 'High Color Rendering Fluorescent (5000K)' => 'High Colour Rendering Fluorescent (3)', + 'High Color Rendering Fluorescent (cool white)' => 'High Colour Rendering Fluorescent (2)', + 'High Color Rendering Fluorescent (daylight)' => 'High Colour Rendering Fluorescent (4)', + 'High Color Rendering Fluorescent (warm white)' => 'High Colour Rendering Fluorescent (0)', + 'Sodium Vapor Lamps' => 'Sodium Vapour Lamps', + 'Standard Fluorescent (high temperature mercury vapor)' => 'Standard Fluorescent (high temperature mercury vapour)', + }, + }, + 'WatercolorFilter' => 'Watercolour Filter', + 'WhiteBalance' => { + PrintConv => { + 'Color Filter' => 'Colour Filter', + 'Color Temperature' => 'Colour Temperature', + 'Color Temperature Enhancement' => 'Colour Temperature Enhancement', + 'Color Temperature/Color Filter' => 'Colour Temperature/Colour Filter', + }, + }, + 'WhiteBalance2' => { + PrintConv => { + 'Auto (Keep Warm Color Off)' => 'Auto (Keep Warm Colour Off)', + }, + }, + 'WhiteBalanceSet' => { + PrintConv => { + 'Set Color Temperature 1' => 'Set Colour Temperature 1', + 'Set Color Temperature 2' => 'Set Colour Temperature 2', + 'Set Color Temperature 3' => 'Set Colour Temperature 3', + }, + }, + 'WhiteBalanceSetting' => { + PrintConv => { + 'Color Temperature/Color Filter' => 'Colour Temperature/Colour Filter', + }, + }, + 'WorkColorSpace' => { + Description => 'Work Colour Space', + PrintConv => { + 'ColorMatch RGB' => 'ColourMatch RGB', + }, + }, + 'XMethod' => { + PrintConv => { + 'Color Closest Pixel and Alpha Linear Interpolation' => 'Colour Closest Pixel and Alpha Linear Interpolation', + 'Color Linear Interpolation and Alpha Closest Pixel' => 'Colour Linear Interpolation and Alpha Closest Pixel', + }, + }, + 'YMethod' => { + PrintConv => { + 'Color Closest Pixel and Alpha Linear Interpolation' => 'Colour Closest Pixel and Alpha Linear Interpolation', + 'Color Linear Interpolation and Alpha Closest Pixel' => 'Colour Linear Interpolation and Alpha Closest Pixel', + }, + }, +); + +1; # end + + +__END__ + +=head1 NAME + +Image::ExifTool::Lang::en_gb.pm - ExifTool British English language translations + +=head1 DESCRIPTION + +This file is used by Image::ExifTool to generate localized tag descriptions +and values. + +=head1 AUTHOR + +Copyright 2003-2019, Phil Harvey (phil at owl.phy.queensu.ca) + +This library is free software; you can redistribute it and/or modify it +under the same terms as Perl itself. + +=head1 SEE ALSO + +L<Image::ExifTool(3pm)|Image::ExifTool>, +L<Image::ExifTool::TagInfoXML(3pm)|Image::ExifTool::TagInfoXML> + +=cut diff --git a/lib/Image/ExifTool/Lang/es.pm b/lib/Image/ExifTool/Lang/es.pm new file mode 100644 index 0000000..cd4bd36 --- /dev/null +++ b/lib/Image/ExifTool/Lang/es.pm @@ -0,0 +1,4021 @@ +#------------------------------------------------------------------------------ +# File: es.pm +# +# Description: ExifTool Spanish language translations +# +# Notes: This file generated automatically by Image::ExifTool::TagInfoXML +#------------------------------------------------------------------------------ + +package Image::ExifTool::Lang::es; + +use strict; +use vars qw($VERSION); + +$VERSION = '1.15'; + +%Image::ExifTool::Lang::es::Translate = ( + 'AEAperture' => 'Aperture AE', + 'AELock' => 'Bloqueo AE', + 'AELockButton' => { + Description => 'Botón Bloqueo AE', + PrintConv => { + 'None' => 'Ninguno', + }, + }, + 'AELockButtonPlusDials' => { + PrintConv => { + 'None' => 'Ninguno', + }, + }, + 'AEMaxAperture2' => 'Apertura máxima AE 2', + 'AEMinAperture' => 'Apertura mínima AE', + 'AEProgramMode' => { + PrintConv => { + 'Landscape' => 'Paisaje', + 'Portrait' => 'Retrato', + 'Standard' => 'Estándar', + }, + }, + 'AESetting' => { + PrintConv => { + 'AE Lock' => 'Bloqueo AE', + 'Exposure Compensation' => 'Compensación Exposición', + }, + }, + 'AFAperture' => 'Apertura AF', + 'AFAreaHeight' => 'AF Alto Área', + 'AFAreaHeights' => 'AF Alto Área', + 'AFAreaIllumination' => { + PrintConv => { + 'Off' => 'Desactivado', + 'On' => 'Activado', + }, + }, + 'AFAreaMode' => { + Description => 'AF Modo Área', + PrintConv => { + 'Face Detect AF' => 'Detección Caras AF', + 'Multi-point AF or AI AF' => 'Multipunto AF o AI AF', + 'Off (Manual Focus)' => 'Desactivado (Enfoque Manual)', + 'Single-point AF' => 'Punto único AF)', + 'Zone AF' => 'Zona AF', + }, + }, + 'AFAreaWidth' => 'AF Ancho Área', + 'AFAreaWidths' => 'AF Ancho Área', + 'AFAssist' => { + PrintConv => { + 'Off' => 'Desactivado', + 'On' => 'Activado', + }, + }, + 'AFImageHeight' => 'AF Alto Imágen', + 'AFImageWidth' => 'AF Ancho Imágen', + 'AFMode' => 'Modo AF', + 'AFPoint' => { + Description => 'Punto AF', + PrintConv => { + 'Center' => 'Centro', + 'Face Detect' => 'Detección Caras', + 'Left' => 'Izquierda', + 'None' => 'Ninguno', + 'None (MF)' => 'Ninguno (MF)', + 'Right' => 'Derecha', + }, + }, + 'AFPointActivationArea' => { + Description => 'Area de Activación Punto AF', + PrintConv => { + 'Standard' => 'Estándar', + }, + }, + 'AFPointAreaExpansion' => { + Description => 'Area Expansion Punto AF', + PrintConv => { + 'Disable' => 'Desactivado', + }, + }, + 'AFPointAutoSelection' => 'Autoselección Punto AF', + 'AFPointBrightness' => { + Description => 'Brillo Punto AF', + PrintConv => { + 'Brighter' => 'Brillante', + 'High' => 'Alto', + 'Low' => 'Bajo', + }, + }, + 'AFPointDisplayDuringFocus' => { + Description => 'Mostrar Punto AF durante el enfoque', + PrintConv => { + 'Off' => 'Desactivado', + 'On' => 'Activado', + }, + }, + 'AFPointIllumination' => { + Description => 'Iluminación de Punto AF', + PrintConv => { + 'Brighter' => 'Brillante', + 'Off' => 'Desactivado', + 'On' => 'Activado', + }, + }, + 'AFPointMode' => 'Modo Punto AF', + 'AFPointPosition' => 'Posición Punto AF', + 'AFPointRegistration' => 'Registro de Puntos AF', + 'AFPointSelected' => { + Description => 'Punto AF Seleccionado', + PrintConv => { + 'None' => 'Ninguno', + }, + }, + 'AFPointSelected2' => 'Punto AF Seleccionado 2 ', + 'AFPointSelection' => 'Selección de Punto AF', + 'AFPointSelectionMethod' => 'Método Selección Punto AF', + 'AFPoints' => 'Punto AF', + 'AFPointsInFocus' => { + Description => 'Puntos AF en foco', + PrintConv => { + 'All' => 'Todo', + 'None' => 'Ninguno', + }, + }, + 'AFPointsInFocus1D' => 'Puntos AF en foco', + 'AFPointsInFocus5D' => { + Description => 'Puntos AF en foco 5D', + PrintConv => { + 'Bottom' => 'Abajo', + 'Center' => 'Centro', + 'Left' => 'Izquierda', + 'Lower-left' => 'Inferior izquierda', + 'Lower-right' => 'Inferior derecha', + 'Right' => 'Derecha', + 'Top' => 'Arriba', + 'Upper-left' => 'Superior izquierda', + 'Upper-right' => 'Superior derecha', + }, + }, + 'AFPointsSelected' => 'Puntos AF seleccionados', + 'AFPointsUnknown1' => { + PrintConv => { + 'All' => 'Todo', + }, + }, + 'AFPointsUsed' => 'Puntos AF utilizados', + 'AIServoTrackingSensitivity' => { + PrintConv => { + 'Fast' => 'Rápido', + 'Standard' => 'Estándar', + }, + }, + 'APEVersion' => 'Versión APE', + 'ARMIdentifier' => 'Identificador ARM', + 'ARMVersion' => 'Versión ARM', + 'AToB0' => 'A a B0', + 'AToB1' => 'A a B1', + 'AToB2' => 'A a B2', + 'ActionAdvised' => { + Description => 'Acción Aconsejada', + PrintConv => { + 'Object Kill' => 'Destruir Objecto', + 'Object Reference' => 'Referencia Objecto', + 'Object Replace' => 'Reemplazar Objecto', + 'Ojbect Append' => 'Añadir Objeto', + }, + }, + 'ActiveArea' => 'Área Activa', + 'ActiveD-Lighting' => { + PrintConv => { + 'High' => 'Alto', + 'Low' => 'Bajo', + 'Off' => 'Desactivado', + 'On' => 'Activado', + }, + }, + 'ActiveD-LightingMode' => { + PrintConv => { + 'High' => 'Alto', + 'Off' => 'Desactivado', + }, + }, + 'AddAspectRatioInfo' => { + PrintConv => { + 'Off' => 'Desactivado', + }, + }, + 'AddOriginalDecisionData' => { + PrintConv => { + 'Off' => 'Desactivado', + 'On' => 'Activado', + }, + }, + 'AdjustmentMode' => 'Modo Ajuste', + 'AdvancedRaw' => { + PrintConv => { + 'Off' => 'Desactivado', + 'On' => 'Activado', + }, + }, + 'AdvancedSceneMode' => { + PrintConv => { + 'Monochrome' => 'Monocromo', + 'Soft' => 'Suave', + }, + }, + 'Album' => 'Álbum', + 'AlphaByteCount' => 'Número Byte Alfa', + 'AlphaDataDiscard' => { + Description => 'Datos Alfa Descartados', + PrintConv => { + 'Flexbits Discarded' => 'FlexBits Descartado', + 'Full Resolution' => 'Resolución Total', + 'HighPass Frequency Data Discarded' => 'Datos Frecuencia High-Pass Descartados', + 'Highpass and LowPass Frequency Data Discarded' => 'Dato Frecuencia High-Pass y Low-Pass Descartados', + }, + }, + 'AlphaOffset' => 'Offset Alfa', + 'AmbienceSelection' => { + PrintConv => { + 'Brighter' => 'Brillante', + 'Cool' => 'Frío', + 'Darker' => 'Oscuro', + 'Intense' => 'Intenso', + 'Monochrome' => 'Monocromo', + 'Soft' => 'Suave', + 'Standard' => 'Estándar', + 'Vivid' => 'Vívido', + 'Warm' => 'Cálido', + }, + }, + 'AnalogBalance' => 'Balance Analógico', + 'Annotation' => 'Anotación', + 'Annotations' => 'Anotaciones', + 'Anti-Blur' => { + PrintConv => { + 'Off' => 'Desactivado', + }, + }, + 'AntiAliasStrength' => 'Potencia Relativa del Filtro Antialiasing', + 'Aperture' => 'Apertura', + 'ApertureRange' => 'Rango Apertura', + 'ApertureSetting' => 'Ajustes Apertura', + 'ApertureValue' => 'Apertura', + 'ApplicationRecordVersion' => 'Versión Registro Aplicación', + 'ArtMode' => { + PrintConv => { + 'Monochrome' => 'Monocromo', + 'Panorama' => 'Panoramica', + }, + }, + 'Artist' => 'Autor', + 'AsShotICCProfile' => 'Perfil ICC Captura', + 'AsShotNeutral' => 'Captura Neutral', + 'AsShotPreProfileMatrix' => 'Matriz Pre Perfil Captura', + 'AsShotProfileName' => 'Nombre Perfil Captura', + 'AsShotWhiteXY' => 'Captura Blanco X-Y', + 'Audio' => { + PrintConv => { + 'Yes' => 'Si', + }, + }, + 'AudioChannelType' => { + PrintConv => { + 'Other' => 'Otro', + }, + }, + 'AudioChannels' => 'Canales Audio', + 'AudioCodecID' => { + PrintConv => { + 'Unknown -' => 'Desconocido -', + }, + }, + 'AudioDuration' => 'Duración Audio', + 'AudioOutcue' => 'Cola Audio', + 'AudioSampleType' => { + PrintConv => { + 'Other' => 'Otro', + }, + }, + 'AudioSamplingRate' => 'Ratio Muestreo Audio', + 'AudioSamplingResolution' => 'Resolución Muestreo Audio', + 'AudioType' => { + Description => 'Tipo Audio', + PrintConv => { + 'Mono Actuality' => 'Actualidad (audio mono (1 canal))', + 'Mono Music' => 'Música transmitida por si misma (audio mono (1 canal))', + 'Mono Question and Answer Session' => 'Sesión pregunta y respuesta (audio mono (1 canal))', + 'Mono Raw Sound' => 'Sonido bruto (audio mono (1 canal))', + 'Mono Response to a Question' => 'Respuesta a una pregunta (audio mono (1 canal))', + 'Mono Scener' => 'Escena (audio mono (1 canal))', + 'Mono Voicer' => 'Voz (audio mono (1 canal))', + 'Mono Wrap' => 'Envolvente (audio mono (1 canal))', + 'Stereo Actuality' => 'Actualidad (audio estéreo (2 canales))', + 'Stereo Music' => 'Música transmitida por si misma (audio estéreo (2 canales))', + 'Stereo Question and Answer Session' => 'Sesión pregunta y respuesta (audio estéreo (2 canales))', + 'Stereo Raw Sound' => 'Sonido bruto (audio estéreo (2 canales))', + 'Stereo Response to a Question' => 'Respuesta a una pregunta (audio estéreo (2 canales))', + 'Stereo Scener' => 'Escena (audio estéreo (2 canales))', + 'Stereo Voicer' => 'Voz (audio estéreo (2 canales))', + 'Stereo Wrap' => 'Envolvente (audio estéreo (2 canales))', + 'Text Only' => 'Solo texto (sin dato de objeto)', + }, + }, + 'Author' => 'Autor', + 'AuthorsPosition' => 'Posición del Autor', + 'AutoAperture' => { + PrintConv => { + 'Off' => 'Desactivado', + 'On' => 'Activado', + }, + }, + 'AutoBracket' => 'Auto-horquillado', + 'AutoExposureBracketing' => { + PrintConv => { + 'Off' => 'Desactivado', + 'On' => 'Activado', + }, + }, + 'AutoFP' => { + PrintConv => { + 'Off' => 'Desactivado', + 'On' => 'Activado', + }, + }, + 'AutoLightingOptimizer' => { + PrintConv => { + 'Low' => 'Bajo', + 'Off' => 'Desactivado', + 'Standard' => 'Estándar', + 'Strong' => 'Fuerte', + }, + }, + 'AutoLightingOptimizerOn' => { + PrintConv => { + 'Yes' => 'Si', + }, + }, + 'AutoRedEye' => { + PrintConv => { + 'Off' => 'Desactivado', + 'On' => 'Activado', + }, + }, + 'AutoRotate' => { + PrintConv => { + 'None' => 'Ninguno', + 'Rotate 180' => 'Girado 180°', + 'Rotate 270 CW' => 'Girado 270° sentido reloj', + 'Rotate 90 CW' => 'Girado 90° sentido reloj', + }, + }, + 'AverageLevel' => 'Nivel Medio', + 'BToA0' => 'B a A0', + 'BToA1' => 'B a A1', + 'BToA2' => 'B a A2', + 'BackgroundColorIndicator' => 'Indicador Color Fondo', + 'BackgroundColorValue' => 'Valor Color Fondo', + 'BackgroundTiling' => { + PrintConv => { + 'Yes' => 'Si', + }, + }, + 'BadFaxLines' => 'Líneas Fax Malas', + 'BannerImageType' => { + PrintConv => { + 'None' => 'Ninguno', + }, + }, + 'BaselineExposure' => 'Exposición Base', + 'BaselineNoise' => 'Ruido Base', + 'BaselineSharpness' => 'Nitidez Base', + 'BatteryLevel' => 'Nivel Batería', + 'BatteryState' => { + PrintConv => { + 'Low' => 'Bajo', + }, + }, + 'BayerGreenSplit' => 'Mosaico Bayer Verde', + 'Beep' => { + PrintConv => { + 'High' => 'Alto', + 'Low' => 'Bajo', + 'Off' => 'Desactivado', + 'On' => 'Activado', + }, + }, + 'BeepPitch' => { + PrintConv => { + 'High' => 'Alto', + 'Low' => 'Bajo', + }, + }, + 'BestQualityScale' => 'Escala Mayor Calidad', + 'BestShotMode' => { + PrintConv => { + 'Beach' => 'Playa', + 'Fireworks' => 'Fuegos Artificiales', + 'Food' => 'Comida', + 'Monochrome' => 'Monocromo', + 'Portrait' => 'Retrato', + 'Snow' => 'Nieve', + 'Underwater' => 'Subacuatica', + }, + }, + 'BitsPerComponent' => 'Bits Por Componente', + 'BitsPerExtendedRunLength' => 'Bits Por "Run Length" Extendido', + 'BitsPerRunLength' => 'Bits Por "Run Length"', + 'BitsPerSample' => 'Número de Bits Por Muestra', + 'BlackLevel' => 'Nivel Negro', + 'BlackLevelDeltaH' => 'Nivel Negro Delta H', + 'BlackLevelDeltaV' => 'Nivel Negro Delta V', + 'BlackLevelRepeatDim' => 'Dimensión Repetición Nivel Negro', + 'BleachBypassToning' => { + PrintConv => { + 'Green' => 'Verde', + 'Orange' => 'Naranja', + 'Red' => 'Rojo', + 'Yellow' => 'Amarillo', + }, + }, + 'BlocksPerFrame' => 'Bloques por Imagen', + 'BlueBalance' => 'Balance de azules', + 'BlueMatrixColumn' => 'Columna Matriz Azul', + 'BlueTRC' => 'Curva Reproducción Tono Azul', + 'BlurControl' => { + PrintConv => { + 'High' => 'Alto', + 'Low' => 'Bajo', + }, + }, + 'BlurWarning' => { + PrintConv => { + 'None' => 'Ninguno', + }, + }, + 'BodyFirmwareVersion' => 'Versión Firmware del cuerpo de la cámara', + 'BracketMode' => { + PrintConv => { + 'Off' => 'Desactivado', + }, + }, + 'Brightness' => 'Brillo', + 'BrightnessValue' => 'Luminosidad', + 'By-line' => 'Creador', + 'By-lineTitle' => 'Puesto del Creador', + 'CFALayout' => { + Description => 'Distribución CFA', + PrintConv => { + 'Even columns offset down 1/2 row' => 'Distribución escalonada A: columnas pares son movidas hacia abajo 1/2 fila', + 'Even columns offset up 1/2 row' => 'Distribución escalonada B: columnas pares son movidas hacia arriba 1/2 fila', + 'Even rows offset left 1/2 column' => 'Distribución escalonada D: filas pares son movidas a la izquierda 1/2 columna', + 'Even rows offset right 1/2 column' => 'Distribución escalonada C: filas pares son movidas a la derecha 1/2 columna', + 'Rectangular' => 'Distribución Rectangular (o cuadrada)', + }, + }, + 'CFAPattern' => 'Patrón CFA', + 'CFAPattern2' => 'Patrón CFA 2', + 'CFAPlaneColor' => 'Color Plano CFA', + 'CFARepeatPatternDim' => 'Dimensión Patrón Repetición CFA', + 'CMMFlags' => 'Banderas CMM', + 'CMYKEquivalent' => 'CMYK Equivalente', + 'CPUType' => { + PrintConv => { + 'None' => 'Ninguno', + }, + }, + 'CalibrationDateTime' => 'Fecha y Hora Calibración', + 'CalibrationIlluminant1' => { + Description => 'Calibración Iluminación 1', + PrintConv => { + 'Cloudy' => 'Tiempo Nublado', + 'Cool White Fluorescent' => 'Fluorescente blanco cálido (W 3800 - 4500K)', + 'Day White Fluorescent' => 'Fluorescente blanco día (N 4600 - 5500K)', + 'Daylight' => 'Luz del día', + 'Daylight Fluorescent' => 'Fluorescente luz de día (D 5700 - 7100K)', + 'Fine Weather' => 'Buen tiempo', + 'Fluorescent' => 'Fluorescente', + 'ISO Studio Tungsten' => 'Tungsteno estudio ISO', + 'Other' => 'Otras Fuentes Luz', + 'Shade' => 'Sombrío', + 'Standard Light A' => 'Luz Estándar A', + 'Standard Light B' => 'Luz Estándar B', + 'Standard Light C' => 'Luz Estándar C', + 'Tungsten (Incandescent)' => 'Tungsteno (luz incandescente)', + 'Unknown' => 'Desconocido', + 'Warm White Fluorescent' => 'Fluorescente blanco cálido (L 2600 - 3250K)', + 'White Fluorescent' => 'Fluorescente blanco (WW 3250 - 3800K)', + }, + }, + 'CalibrationIlluminant2' => { + Description => 'Calibración Iluminación 2', + PrintConv => { + 'Cloudy' => 'Tiempo Nublado', + 'Cool White Fluorescent' => 'Fluorescente blanco cálido (W 3800 - 4500K)', + 'Day White Fluorescent' => 'Fluorescente blanco día (N 4600 - 5500K)', + 'Daylight' => 'Luz del día', + 'Daylight Fluorescent' => 'Fluorescente luz de día (D 5700 - 7100K)', + 'Fine Weather' => 'Buen tiempo', + 'Fluorescent' => 'Fluorescente', + 'ISO Studio Tungsten' => 'Tungsteno estudio ISO', + 'Other' => 'Otras Fuentes Luz', + 'Shade' => 'Sombrío', + 'Standard Light A' => 'Luz Estándar A', + 'Standard Light B' => 'Luz Estándar B', + 'Standard Light C' => 'Luz Estándar C', + 'Tungsten (Incandescent)' => 'Tungsteno (luz incandescente)', + 'Unknown' => 'Desconocido', + 'Warm White Fluorescent' => 'Fluorescente blanco cálido (L 2600 - 3250K)', + 'White Fluorescent' => 'Fluorescente blanco (WW 3250 - 3800K)', + }, + }, + 'CameraCalibration1' => 'Calibración Cámara 1', + 'CameraCalibration2' => 'Calibración Cámara 2', + 'CameraCalibrationSig' => 'Firma Calibración Cámara', + 'CameraISO' => 'Camara-ISO', + 'CameraOrientation' => { + Description => 'Orientación Cámara', + PrintConv => { + 'Rotate 270 CW' => 'Girado 270° sentido reloj', + 'Rotate 90 CW' => 'Girado 90° sentido reloj', + }, + }, + 'CameraSerialNumber' => 'Número Serie Cámara', + 'CameraTemperature' => 'Temperatura Cámara', + 'CameraType' => 'Tipo Cámara', + 'CameraType2' => 'Tipo Cámara', + 'CanonFileLength' => 'Tamaño Archivo', + 'CanonFlashMode' => { + PrintConv => { + 'Auto' => 'Automático', + 'External flash' => 'Flash Externo', + 'Off' => 'Desactivado', + 'On' => 'Activado', + 'Red-eye reduction' => 'Réducción ojos rojos', + 'Red-eye reduction (Auto)' => 'Réducción ojos rojos (Automático)', + 'Red-eye reduction (On)' => 'Réducción ojos rojos (Activado)', + }, + }, + 'CanonImageSize' => { + PrintConv => { + '1280x720 Movie' => 'Película 1280x720', + '1920x1080 Movie' => 'Película 1920x1080', + '640x480 Movie' => 'Película 640x480', + 'Large' => 'Ancho', + 'Medium' => 'Medio', + 'Medium 1' => 'Medio 1', + 'Medium 2' => 'Medio 2', + 'Medium 3' => 'Medio 3', + 'Small' => 'Pequeño', + 'Small 1' => 'Pequeño 1', + 'Small 2' => 'Pequeño 2', + 'Small 3' => 'Pequeño 3', + 'Small Movie' => 'Película Pequeña', + }, + }, + 'Caption-Abstract' => 'Título/Descripción', + 'CaptionWriter' => 'Autor del Pie de Foto', + 'Categories' => 'Categorías', + 'Category' => 'Categoría', + 'CellLength' => 'Alto Celda', + 'CellWidth' => 'Ancho Celda', + 'Certificate' => 'Certificado', + 'Channels' => 'Canales', + 'CharTarget' => 'Objetivo Caracter', + 'CharacterSet' => 'Conjunto de Caracteres', + 'ChromaBlurRadius' => 'Radio Mezcla Croma', + 'ChromaticAdaptation' => 'Adaptación Cromática', + 'Chromaticity' => 'Cromaticidad', + 'ChrominanceNR_TIFF_JPEG' => { + PrintConv => { + 'High' => 'Alto', + 'Low' => 'Bajo', + 'Off' => 'Desactivado', + }, + }, + 'ChrominanceNoiseReduction' => { + PrintConv => { + 'High' => 'Alto', + 'Low' => 'Bajo', + 'Off' => 'Desactivado', + }, + }, + 'City' => 'Ciudad', + 'ClassifyState' => 'Clasificar Estado', + 'CleanFaxData' => 'Datos Fax Claro', + 'ClipPath' => 'Camino Fragmento', + 'CodedCharacterSet' => 'Juego Caracteres Codificado', + 'ColorAberrationControl' => { + PrintConv => { + 'Off' => 'Desactivado', + 'On' => 'Activado', + }, + }, + 'ColorAdjustment' => 'Ajuste Color', + 'ColorAdjustmentMode' => { + Description => 'Modo Ajuste Color', + PrintConv => { + 'Off' => 'Apagado', + 'On' => 'Encendido', + }, + }, + 'ColorBalanceAdj' => { + PrintConv => { + 'Off' => 'Desactivado', + 'On' => 'Activado', + }, + }, + 'ColorBooster' => { + PrintConv => { + 'Off' => 'Desactivado', + 'On' => 'Activado', + }, + }, + 'ColorCalibrationMatrix' => 'Tabla Matriz Calibración Color', + 'ColorCharacterization' => 'Caracterización Color', + 'ColorComponents' => 'Componentes de Color', + 'ColorEffect' => { + PrintConv => { + 'Cool' => 'Frío', + 'Warm' => 'Cálido', + }, + }, + 'ColorFilter' => { + Description => 'Filtro de Color', + PrintConv => { + 'Green' => 'Verde', + 'Red' => 'Rojo', + 'Yellow' => 'Amarillo', + }, + }, + 'ColorMap' => 'Mapa Color', + 'ColorMatrix' => 'Matriz de Color', + 'ColorMatrix1' => 'Matriz Color 1', + 'ColorMatrix2' => 'Matriz Color 2', + 'ColorMatrixA' => 'Matriz de Color A', + 'ColorMatrixAdobeRGB' => 'Matriz de Color Adobe RGB', + 'ColorMatrixB' => 'Matriz de Color B', + 'ColorMatrixNumber' => 'Número de Matriz de Color', + 'ColorMatrixSRGB' => 'Matriz de Color SRGB', + 'ColorMode' => { + Description => 'Modo de Color', + PrintConv => { + 'Autumn Leaves' => 'Hojas de otoño', + 'B&W' => 'ByN', + 'Clear' => 'Claro', + 'Deep' => 'Profundo', + 'Evening' => 'Tarde', + 'Landscape' => 'Paisaje', + 'Light' => 'Luz', + 'Neutral' => 'Neutro', + 'Night View' => 'Vista nocturna', + 'Night View/Portrait' => 'Retrato noct.', + 'Portrait' => 'Retrato', + 'Standard' => 'Estándar', + 'Sunset' => 'Puesta sol', + 'Vivid' => 'Vívido', + }, + }, + 'ColorMoireReduction' => { + PrintConv => { + 'Off' => 'Desactivado', + 'On' => 'Activado', + }, + }, + 'ColorMoireReductionMode' => { + PrintConv => { + 'High' => 'Alto', + 'Low' => 'Bajo', + 'Off' => 'Desactivado', + }, + }, + 'ColorPalette' => 'Paleta Color', + 'ColorRepresentation' => { + Description => 'Representación Color', + PrintConv => { + '3 Components, Frame Sequential in Multiple Objects' => 'Tres componentes, Marco secuencial en múltiples objectos', + '3 Components, Frame Sequential in One Object' => 'Tres componentes, Marco secuencial en un único objeto', + '3 Components, Line Sequential' => 'Tres componentes, Línea secuencial', + '3 Components, Pixel Sequential' => 'Tres componentes, Pixel secuencial', + '3 Components, Single Frame' => 'Tres componentes, Marco simple', + '3 Components, Special Interleaving' => 'Tres componentes, Entrelazado especial', + '4 Components, Frame Sequential in Multiple Objects' => 'Cuatro componentes, Marco secuencial en múltiples objectos', + '4 Components, Frame Sequential in One Object' => 'Cuatro componentes, Marco secuencial en un único objeto', + '4 Components, Line Sequential' => 'Cuatro componentes, Línea secuencial', + '4 Components, Pixel Sequential' => 'Cuatro componentes, Pixel secuencial', + '4 Components, Single Frame' => 'Cuatro componentes, Marco simple', + '4 Components, Special Interleaving' => 'Cuatro componentes, Entrelazado especial', + 'Monochrome, Single Frame' => 'Monocromo, Marco simple', + 'No Image, Single Frame' => 'Sin imagen, Marco simple', + }, + }, + 'ColorResponseUnit' => 'Unidad Respuesta Color', + 'ColorSequence' => 'Representación de Color', + 'ColorSpace' => { + Description => 'Espacio Color', + PrintConv => { + 'ICC Profile' => 'Perfil ICC', + 'Monochrome' => 'Monocromo', + 'Uncalibrated' => 'Sin calibrar', + 'Wide Gamut RGB' => 'Gamut RVB Grande', + }, + }, + 'ColorSpaceData' => 'Espacio Color Datos', + 'ColorTable' => 'Tabla Color', + 'ColorTempAuto' => 'Temperatura Color Automática', + 'ColorTempCloudy' => 'Temperatura Color Nublado', + 'ColorTempCustom' => 'Temperatura Color Personalizada', + 'ColorTempCustom1' => 'Temperatura Color Personalizada 1', + 'ColorTempCustom2' => 'Temperatura Color Personalizada 2', + 'ColorTempDaylight' => 'Temperatura Color Luz de Día', + 'ColorTempFlash' => 'Temperatura Color Flash', + 'ColorTempFluorescent' => 'Temperatura Color Fluorescente', + 'ColorTempKelvin' => 'Temperatura Color Kelvin', + 'ColorTempMeasured' => 'Temperatura Color Medida', + 'ColorTempShade' => 'Temperatura Color Sombrío', + 'ColorTempTungsten' => 'Temperatura Color Tungsteno', + 'ColorTempUnknown' => 'Temperatura de Color Desconocida', + 'ColorTempUnknown10' => 'Temperatura de Color Desconocida 10', + 'ColorTempUnknown11' => 'Temperatura de Color Desconocida 11', + 'ColorTempUnknown12' => 'Temperatura de Color Desconocida 12', + 'ColorTempUnknown13' => 'Temperatura de Color Desconocida 13', + 'ColorTempUnknown14' => 'Temperatura de Color Desconocida 14', + 'ColorTempUnknown15' => 'Temperatura de Color Desconocida 15', + 'ColorTempUnknown16' => 'Temperatura de Color Desconocida 16', + 'ColorTempUnknown17' => 'Temperatura de Color Desconocida 17', + 'ColorTempUnknown18' => 'Temperatura de Color Desconocida 18', + 'ColorTempUnknown19' => 'Temperatura de Color Desconocida 19', + 'ColorTempUnknown2' => 'Temperatura de Color Desconocida 2', + 'ColorTempUnknown20' => 'Temperatura de Color Desconocida 20', + 'ColorTempUnknown3' => 'Temperatura de Color Desconocida 3', + 'ColorTempUnknown4' => 'Temperatura de Color Desconocida 4', + 'ColorTempUnknown5' => 'Temperatura de Color Desconocida 5', + 'ColorTempUnknown6' => 'Temperatura de Color Desconocida 6', + 'ColorTempUnknown7' => 'Temperatura de Color Desconocida 7', + 'ColorTempUnknown8' => 'Temperatura de Color Desconocida 8', + 'ColorTempUnknown9' => 'Temperatura de Color Desconocida 9', + 'ColorTemperature' => 'Temperatura de Color', + 'ColorTone' => { + Description => 'Tono de Color', + PrintConv => { + 'Normal' => 'Estándar', + }, + }, + 'ColorantOrder' => 'Orden Colorante', + 'ColorantTable' => 'Tabla Colorante', + 'ColorimetricReference' => 'Referencia Colorimétrica', + 'CommandDialsChangeMainSub' => { + PrintConv => { + 'Off' => 'Desactivado', + 'On' => 'Activado', + }, + }, + 'CommandDialsMenuAndPlayback' => { + PrintConv => { + 'Off' => 'Desactivado', + 'On' => 'Activado', + }, + }, + 'CommandDialsReverseRotation' => { + PrintConv => { + 'Yes' => 'Si', + }, + }, + 'CommanderGroupAMode' => { + PrintConv => { + 'Off' => 'Desactivado', + }, + }, + 'CommanderGroupBMode' => { + PrintConv => { + 'Off' => 'Desactivado', + }, + }, + 'CommanderInternalFlash' => { + PrintConv => { + 'Off' => 'Desactivado', + }, + }, + 'Comment' => 'Comentario', + 'Compatibility' => 'Compatibilidad', + 'Compilation' => { + PrintConv => { + 'Yes' => 'Si', + }, + }, + 'ComponentsConfiguration' => 'Configuración de Componentes', + 'Composer' => 'Compositor', + 'CompressedBitsPerPixel' => 'Modo Compresión Imagen', + 'CompressedSize' => 'Tamaño Comprimido', + 'Compression' => { + Description => 'Compresión', + PrintConv => { + 'JPEG' => 'Compresión JPEG', + 'JPEG (old-style)' => 'JPEG (estilo antiguo)', + 'Kodak DCR Compressed' => 'Compresión Kodak DCR', + 'Kodak KDC Compressed' => 'Compresión Kodak KDC', + 'Next' => 'Codificación NeXT 2-bit', + 'Nikon NEF Compressed' => 'Compresión Nikon NEF', + 'None' => 'Ninguno', + 'Pentax PEF Compressed' => 'Compresión Pentax PEF', + 'SGILog' => 'Codificación Log Luminancia SGI 32-bit', + 'SGILog24' => 'Codificación Log Luminancia SGI 24-bit', + 'Sony ARW Compressed' => 'Compresión Sony ARW', + 'Thunderscan' => 'Codificación ThunderScan 4-bit', + 'Uncompressed' => 'Sin comprimir', + }, + }, + 'CompressionFactor' => 'Factor de compresión', + 'CompressionLevel' => 'Nivel Compresión', + 'CompressionType' => { + Description => 'Tipo Compresión', + PrintConv => { + 'None' => 'Ninguno', + }, + }, + 'CompressorName' => 'Nombre Compresor', + 'Conductor' => 'Director', + 'Conductors' => 'Directores', + 'ConnectionSpaceIlluminant' => 'Iluminación Espacio Conexión', + 'ConsecutiveBadFaxLines' => 'Líneas Fax Malas Consecutivas', + 'Contact' => 'Contacto', + 'ContentLocationCode' => 'Código Localización Contenido', + 'ContentLocationName' => 'Nombre Localización Contenido', + 'ContinuousBracketing' => { + PrintConv => { + 'High' => 'Alto', + 'Low' => 'Bajo', + }, + }, + 'ContinuousDrive' => { + PrintConv => { + 'Continuous' => 'Continuo', + 'Continuous, High' => 'Continuo, Alto', + 'Continuous, Low' => 'Continuo, Bajo', + 'Continuous, Speed Priority' => 'Continuo, Prioridad Velocidad', + 'Movie' => 'Película', + 'Single' => 'Simple', + }, + }, + 'Contrast' => { + Description => 'Contraste', + PrintConv => { + 'High' => 'Alto', + 'Low' => 'Bajo', + 'Normal' => 'Estándar', + }, + }, + 'ContrastMode' => { + PrintConv => { + 'High' => 'Alto', + 'Low' => 'Bajo', + }, + }, + 'ContrastSetting' => 'Ajustes de Contraste', + 'CopyrightNotice' => 'Aviso Copyright', + 'Country' => 'País', + 'Country-PrimaryLocationCode' => 'Código País ISO', + 'Country-PrimaryLocationName' => 'País', + 'CountryCode' => 'Código País', + 'CreateDate' => 'Fecha y Hora de Datos Digital', + 'CreationDate' => 'Fecha Creación', + 'CreativeStyle' => { + PrintConv => { + 'Autumn Leaves' => 'Hojas de otoño', + 'B&W' => 'ByN', + 'Clear' => 'Claro', + 'Deep' => 'Profundo', + 'Landscape' => 'Paisaje', + 'Light' => 'Luz', + 'Neutral' => 'Neutro', + 'Night View/Portrait' => 'Retrato noct.', + 'Portrait' => 'Retrato', + 'Standard' => 'Estándar', + 'Sunset' => 'Puesta sol', + 'Vivid' => 'Vívido', + }, + }, + 'CreativeStyleSetting' => { + PrintConv => { + 'Landscape' => 'Paisaje', + 'Portrait' => 'Retrato', + 'Standard' => 'Estándar', + 'Vivid' => 'Vívido', + }, + }, + 'Creator' => 'Creador', + 'CreatorAddress' => 'Creador - Dirección', + 'CreatorCity' => 'Creador - Ciudad', + 'CreatorContactInfo' => 'Contacto Creador', + 'CreatorCountry' => 'Creador - País', + 'CreatorPostalCode' => 'Creador - Código Postal', + 'CreatorRegion' => 'Creador - Estado/Provincia', + 'CreatorWorkEmail' => 'Creador - Email(s)', + 'CreatorWorkTelephone' => 'Creador - Teléfono(s)', + 'CreatorWorkURL' => 'Creador - Website(s)', + 'Credit' => 'Proveedor', + 'CropActive' => { + PrintConv => { + 'Yes' => 'Si', + }, + }, + 'CropHeight' => 'Recorte Altura', + 'CropLeft' => 'Recorte Izquierda', + 'CropTop' => 'Recorte Arriba', + 'CropWidth' => 'Recorte Anchura', + 'CroppedImageHeight' => 'Alto Imágen Recortada', + 'CroppedImageLeft' => 'Izquierda Imágen Recortada', + 'CroppedImageTop' => 'Superior Imágen Recortada', + 'CroppedImageWidth' => 'Ancho Imágen Recortada', + 'CurrentICCProfile' => 'Perfil ICC Actual', + 'CurrentPreProfileMatrix' => 'Matriz Pre Perfil Actual', + 'Curves' => { + PrintConv => { + 'Off' => 'Desactivado', + 'On' => 'Activado', + }, + }, + 'CustomRendered' => { + Description => 'Proceso Imagen Personalizado', + PrintConv => { + 'Custom' => 'Proceso personalizado', + 'Normal' => 'Proceso normal', + }, + }, + 'CustomSaturation' => 'Saturación personalizada', + 'D-LightingHQ' => { + PrintConv => { + 'Off' => 'Desactivado', + 'On' => 'Activado', + }, + }, + 'D-LightingHQSelected' => { + PrintConv => { + 'Yes' => 'Si', + }, + }, + 'D-LightingHS' => { + PrintConv => { + 'Off' => 'Desactivado', + 'On' => 'Activado', + }, + }, + 'DNGBackwardVersion' => 'Versión Antigua DNG', + 'DNGLensInfo' => 'Distancia Focal Mínima', + 'DNGVersion' => 'Versión DNG', + 'DOF' => 'Profundidad de campo', + 'Data' => 'Datos', + 'DataCompressionMethod' => 'Proveedor/Propietario Algoritmo Compresión Datos', + 'DataImprint' => { + PrintConv => { + 'None' => 'Ninguno', + }, + }, + 'DataPackets' => ' Paquetes de Datos', + 'DataType' => 'Tipo Datos', + 'Date' => 'Fecha', + 'DateCreated' => 'Fecha Creación', + 'DateSent' => 'Fecha Envío', + 'DateStampMode' => { + PrintConv => { + 'Off' => 'Desactivado', + }, + }, + 'DateTimeDigitized' => 'Fecha y Hora Digital', + 'DateTimeOriginal' => 'Fecha y Hora de Datos Original', + 'DaylightSavings' => { + PrintConv => { + 'Yes' => 'Si', + }, + }, + 'DefaultBlackRender' => { + PrintConv => { + 'None' => 'Ninguno', + }, + }, + 'DefaultCropOrigin' => 'Origen Corte Defecto', + 'DefaultCropSize' => 'Tamaño Corte Defecto', + 'DefaultScale' => 'Escala por Defecto', + 'DerivedFromMaskMarkers' => { + PrintConv => { + 'All' => 'Todo', + 'None' => 'Ninguno', + }, + }, + 'Description' => 'Descripción', + 'Destination' => 'Destino', + 'DestinationDST' => { + PrintConv => { + 'Yes' => 'Si', + }, + }, + 'DeviceAttributes' => 'Atributos Dispositivo', + 'DeviceManufacturer' => 'Fabricante Dispositivo', + 'DeviceMfgDesc' => 'Descripción Fabricante Dispositivo', + 'DeviceModel' => 'Modelo Dispositivo', + 'DeviceModelDesc' => 'Descripción Modelo Dispositivo', + 'DeviceSettingDescription' => 'Descripción Ajustes Dispositivo', + 'DigitalCreationDate' => 'Fecha Creación Digital', + 'DigitalCreationTime' => 'Hora Creación Digital', + 'DigitalFilter01' => { + PrintConv => { + 'Monochrome' => 'Monocromo', + }, + }, + 'DigitalFilter02' => { + PrintConv => { + 'Monochrome' => 'Monocromo', + }, + }, + 'DigitalFilter03' => { + PrintConv => { + 'Monochrome' => 'Monocromo', + }, + }, + 'DigitalFilter04' => { + PrintConv => { + 'Monochrome' => 'Monocromo', + }, + }, + 'DigitalFilter05' => { + PrintConv => { + 'Monochrome' => 'Monocromo', + }, + }, + 'DigitalFilter06' => { + PrintConv => { + 'Monochrome' => 'Monocromo', + }, + }, + 'DigitalFilter07' => { + PrintConv => { + 'Monochrome' => 'Monocromo', + }, + }, + 'DigitalFilter08' => { + PrintConv => { + 'Monochrome' => 'Monocromo', + }, + }, + 'DigitalFilter09' => { + PrintConv => { + 'Monochrome' => 'Monocromo', + }, + }, + 'DigitalFilter10' => { + PrintConv => { + 'Monochrome' => 'Monocromo', + }, + }, + 'DigitalFilter11' => { + PrintConv => { + 'Monochrome' => 'Monocromo', + }, + }, + 'DigitalFilter12' => { + PrintConv => { + 'Monochrome' => 'Monocromo', + }, + }, + 'DigitalFilter13' => { + PrintConv => { + 'Monochrome' => 'Monocromo', + }, + }, + 'DigitalFilter14' => { + PrintConv => { + 'Monochrome' => 'Monocromo', + }, + }, + 'DigitalFilter15' => { + PrintConv => { + 'Monochrome' => 'Monocromo', + }, + }, + 'DigitalFilter16' => { + PrintConv => { + 'Monochrome' => 'Monocromo', + }, + }, + 'DigitalFilter17' => { + PrintConv => { + 'Monochrome' => 'Monocromo', + }, + }, + 'DigitalFilter18' => { + PrintConv => { + 'Monochrome' => 'Monocromo', + }, + }, + 'DigitalFilter19' => { + PrintConv => { + 'Monochrome' => 'Monocromo', + }, + }, + 'DigitalFilter20' => { + PrintConv => { + 'Monochrome' => 'Monocromo', + }, + }, + 'DigitalSignature' => 'Firma Digital', + 'DigitalZoom' => { + Description => 'Zoom Digital', + PrintConv => { + 'None' => 'Ninguno', + 'Off' => 'Desactivado', + }, + }, + 'DigitalZoomOn' => { + Description => 'Zoom Digital Encendido', + PrintConv => { + 'Off' => 'Apagado', + 'On' => 'Encendido', + }, + }, + 'DigitalZoomRatio' => 'Ratio Zoom Digital', + 'Directory' => 'Ubicación del Fichero', + 'DistortionControl' => { + PrintConv => { + 'Off' => 'Desactivado', + }, + }, + 'DistortionCorrection' => { + Description => 'Corrección Distorsión', + PrintConv => { + 'Off' => 'Desactivado', + 'On' => 'Activado', + }, + }, + 'DistortionCorrection2' => { + Description => 'Corrección Distorsión 2', + PrintConv => { + 'Off' => 'Desactivado', + 'On' => 'Activado', + }, + }, + 'DistortionCorrectionOn' => 'Corrección Distorsión Activada', + 'DocSecurity' => { + PrintConv => { + 'None' => 'Ninguno', + }, + }, + 'DocumentHistory' => 'Historial del Documento', + 'DocumentName' => 'Nombre Documento', + 'DocumentNotes' => 'Notas del Documento', + 'DotRange' => 'Intervalo Puntos', + 'DriveMode' => { + Description => 'Modo Entrada', + PrintConv => { + 'Off' => 'Desactivado', + }, + }, + 'Duration' => 'Duración', + 'DynamicRange' => { + PrintConv => { + 'Standard' => 'Estándar', + }, + }, + 'DynamicRangeOptimizer' => { + Description => 'Optim.gama diná', + PrintConv => { + 'Advanced Auto' => 'Avanzado Autom', + 'Advanced Lv1' => 'Avanzado Nvl.1', + 'Advanced Lv2' => 'Avanzado Nvl.2', + 'Advanced Lv3' => 'Avanzado Nvl.3', + 'Advanced Lv4' => 'Avanzado Nvl.4', + 'Advanced Lv5' => 'Avanzado Nvl.5', + 'Off' => 'Desactivado', + 'Standard' => 'Estándar', + }, + }, + 'DynamicRangeOptimizerBracket' => { + PrintConv => { + 'Low' => 'Bajo', + }, + }, + 'DynamicRangeOptimizerMode' => { + PrintConv => { + 'Standard' => 'Estándar', + }, + }, + 'DynamicRangeOptimizerSetting' => { + PrintConv => { + 'Standard' => 'Estándar', + }, + }, + 'EasyExposureCompensation' => { + PrintConv => { + 'Off' => 'Desactivado', + 'On' => 'Activado', + }, + }, + 'EasyMode' => { + PrintConv => { + 'Beach' => 'Playa', + 'Black & White' => 'Blanco y Negro', + 'Digital Macro' => 'Macro digital', + 'Easy' => 'Fácil', + 'Fireworks' => 'Fuegos Artificiales', + 'Fisheye Effect' => 'Efecto Ojo de Pez', + 'Flash Off' => 'Flash Desactivado', + 'Foliage' => 'Follaje', + 'Gray Scale' => 'Escala de Grises', + 'Indoor' => 'Interior', + 'Kids & Pets' => 'Niños y Mascotas', + 'Landscape' => 'Paisaje', + 'Monochrome' => 'Monocromo', + 'Neutral' => 'Neutro', + 'Night' => 'Nocturno', + 'Night Scene' => 'Escena Nocturna', + 'Night Snapshot' => 'Fotografía Nocturna', + 'Nostalgic' => 'Nostalgico', + 'Portrait' => 'Retrato', + 'Smile' => 'Sonrisa', + 'Snow' => 'Nieve', + 'Sports' => 'Deportes', + 'Sunset' => 'Puesta de sol', + 'Surface' => 'Superficie', + 'Underwater' => 'Subacuatica', + 'Vivid' => 'Vívido', + }, + }, + 'EdgeNoiseReduction' => { + PrintConv => { + 'Off' => 'Desactivado', + 'On' => 'Activado', + }, + }, + 'EditStatus' => 'Estado Edición', + 'EditorialUpdate' => { + Description => 'Actualización Editorial', + PrintConv => { + 'Additional language' => 'Idioma Adicional', + }, + }, + 'EffectiveMaxAperture' => 'Aperture Máxima Efectiva', + 'Emphasis' => { + PrintConv => { + 'None' => 'Ninguno', + }, + }, + 'EncodedBy' => 'Codificado por', + 'EncodingProcess' => 'Proceso de codificación', + 'EncodingSettings' => 'Ajustes de Codificación', + 'EncodingTime' => 'Hora de codificación', + 'EndPoints' => 'Puntos Finales', + 'EnhanceDarkTones' => { + PrintConv => { + 'Off' => 'Desactivado', + 'On' => 'Activado', + }, + }, + 'Enhancement' => { + PrintConv => { + 'Green' => 'Verde', + 'Red' => 'Rojo', + 'Underwater' => 'Subacuatica', + }, + }, + 'EnvelopeNumber' => 'Número Sobre', + 'EnvelopePriority' => { + Description => 'Prioridad Sobre', + PrintConv => { + '0 (reserved)' => '0 (reservada para uso futuro)', + '1 (most urgent)' => '1 (más urgente)', + '5 (normal urgency)' => '5 (urgencia normal)', + '8 (least urgent)' => '8 (menos urgente)', + '9 (user-defined priority)' => '9 (prioridad definida por el usuario)', + }, + }, + 'EnvelopeRecordVersion' => 'Versión Registro Sobre', + 'EquipmentVersion' => 'Versión Equipo', + 'ErrorCorrection' => 'Correción Error', + 'ErrorCorrectionType' => 'Tipo Corrección Error', + 'ExcursionTolerance' => { + Description => 'Tolerancia Excursión', + PrintConv => { + 'Allowed' => 'Puede ocurrir', + 'Not Allowed' => 'No Permitido (defecto)', + }, + }, + 'ExifCameraInfo' => 'Información Cámara Exif', + 'ExifImageHeight' => 'Alto Imagen', + 'ExifImageWidth' => 'Ancho Imagen', + 'ExifOffset' => 'Puntero Exif IFD', + 'ExifToolVersion' => 'Versión Exiftool', + 'ExifVersion' => 'Versión Exif', + 'ExpandFilm' => 'Película Expandida', + 'ExpandFilterLens' => 'Filtro Objetivo Expandida', + 'ExpandFlashLamp' => 'Lampara Flash Expandida', + 'ExpandLens' => 'Objetivo Expandido', + 'ExpandScanner' => 'Escaner Expandido', + 'ExpandSoftware' => 'Software Expandido', + 'ExpirationDate' => 'Fecha Expiración', + 'ExpirationTime' => 'Hora Expiración', + 'ExposureCompensation' => 'Compensación Exposición', + 'ExposureDelayMode' => { + PrintConv => { + 'Off' => 'Desactivado', + 'On' => 'Activado', + }, + }, + 'ExposureIndex' => 'Índice Exposición', + 'ExposureMode' => { + Description => 'Modo Exposición', + PrintConv => { + 'Aperture-priority AE' => 'Prioridad Aberture AE', + 'Auto' => 'Exposición automática', + 'Auto bracket' => 'Auto-horquillado', + 'Beach' => 'Playa', + 'Fireworks' => 'Fuegos Artificiales', + 'Food' => 'Comida', + 'Landscape' => 'Paisaje', + 'Manual' => 'Exposición manual', + 'Panorama' => 'Panoramica', + 'Portrait' => 'Retrato', + 'Program AE' => 'Programa AE', + 'Shutter speed priority AE' => 'Prioridad velocidad obturador AE', + 'Snow' => 'Nieve', + 'Underwater' => 'Subacuatica', + }, + }, + 'ExposureProgram' => { + Description => 'Programa Exposición', + PrintConv => { + 'Action (High speed)' => 'Programa acción (orientado a velocidad de obturación rápida)', + 'Aperture-priority AE' => 'Prioridad Apertura', + 'Creative (Slow speed)' => 'Programa creativo (orientado a profundidad de campo)', + 'Landscape' => 'Modo paisaje (para fotos de paisaje con el fondo en enfoque)', + 'Manual' => 'Exposición manual', + 'Not Defined' => 'No definido', + 'Portrait' => 'Modo retrato (para fotos de cerca con el fondo fuera de enfoque)', + 'Program AE' => 'Programa normal', + 'Shutter speed priority AE' => 'Prioridad obturador', + }, + }, + 'ExposureTime' => 'Tiempo de Exposición', + 'ExposureTime2' => 'Tiempo de Exposición 2', + 'Extender' => { + PrintConv => { + 'None' => 'Ninguno', + }, + }, + 'ExternalFlash' => { + Description => 'Flash Externo', + PrintConv => { + 'Off' => 'Desactivado', + 'On' => 'Activado', + }, + }, + 'ExternalFlashBounce' => { + PrintConv => { + 'Yes' => 'Si', + }, + }, + 'ExternalFlashMode' => { + PrintConv => { + 'Off' => 'Desactivado', + }, + }, + 'ExternalFlashZoom' => 'Zoom Flash Externo', + 'ExtraSamples' => 'Muestra Extra', + 'FNumber' => 'Número F', + 'FOV' => 'Angulo de Visión', + 'FaceDetectArea' => 'Area detección caras', + 'FaceDetectFrameSize' => 'Tamaño Area detección caras', + 'FaceOrientation' => { + PrintConv => { + 'Horizontal (normal)' => '0° (arriba/izquierda)', + 'Rotate 180' => 'Girado 180°', + 'Rotate 270 CW' => 'Girado 270° sentido reloj', + 'Rotate 90 CW' => 'Girado 90° sentido reloj', + }, + }, + 'FacesDetected' => 'Caras Detectadas', + 'FastSeek' => { + PrintConv => { + 'Yes' => 'Si', + }, + }, + 'FaxProfile' => { + PrintConv => { + 'Unknown' => 'Desconocido', + }, + }, + 'FaxRecvParams' => 'Parámetros Recepción Fax', + 'FaxRecvTime' => 'Hora Recepción Fax', + 'FaxSubAddress' => 'Subdirección Fax', + 'FileAccessDate' => 'Fecha y Hora de Acceso', + 'FileCreateDate' => 'Fecha y Hora de Creación', + 'FileFormat' => 'Formato Archivo', + 'FileLength' => 'Tamaño Archivo', + 'FileModifyDate' => 'Fecha Actualización', + 'FileName' => 'Nombre Archivo', + 'FileNumberMemory' => { + PrintConv => { + 'Off' => 'Desactivado', + 'On' => 'Activado', + }, + }, + 'FileNumberSequence' => { + PrintConv => { + 'Off' => 'Desactivado', + 'On' => 'Activado', + }, + }, + 'FileOwner' => 'Propietario del Archivo', + 'FilePermissions' => 'Permisos', + 'FileSize' => 'Tamaño Archivo', + 'FileSource' => { + Description => 'Fuente Archivo', + PrintConv => { + 'Digital Camera' => 'Cámara Digital', + 'Film Scanner' => 'Escaner Película', + 'Reflection Print Scanner' => 'Escaner de Reflexión', + }, + }, + 'FileType' => 'Tipo Archivo', + 'FileVersion' => 'Versión Formato Archivo', + 'Filename' => 'Nombre archivo', + 'FillOrder' => 'Orden Rellenado', + 'FilterEffect' => { + PrintConv => { + 'Green' => 'Verde', + 'None' => 'Ninguno', + 'Off' => 'Desactivado', + 'Orange' => 'Naranja', + 'Red' => 'Rojo', + 'Yellow' => 'Amarillo', + }, + }, + 'FilterEffectMonochrome' => { + PrintConv => { + 'Green' => 'Verde', + 'None' => 'Ninguno', + 'Orange' => 'Naranja', + 'Red' => 'Rojo', + 'Yellow' => 'Amarillo', + }, + }, + 'FilterEffectUnknown' => { + PrintConv => { + 'Green' => 'Verde', + 'None' => 'Ninguno', + 'Orange' => 'Naranja', + 'Red' => 'Rojo', + 'Yellow' => 'Amarillo', + }, + }, + 'FilterEffectUserDef1' => { + PrintConv => { + 'Green' => 'Verde', + 'None' => 'Ninguno', + 'Orange' => 'Naranja', + 'Red' => 'Rojo', + 'Yellow' => 'Amarillo', + }, + }, + 'FilterEffectUserDef2' => { + PrintConv => { + 'Green' => 'Verde', + 'None' => 'Ninguno', + 'Orange' => 'Naranja', + 'Red' => 'Rojo', + 'Yellow' => 'Amarillo', + }, + }, + 'FilterEffectUserDef3' => { + PrintConv => { + 'Green' => 'Verde', + 'None' => 'Ninguno', + 'Orange' => 'Naranja', + 'Red' => 'Rojo', + 'Yellow' => 'Amarillo', + }, + }, + 'FinderDisplayDuringExposure' => { + PrintConv => { + 'Off' => 'Desactivado', + 'On' => 'Activado', + }, + }, + 'FirmwareVersion' => 'Versión Firmware', + 'FixtureIdentifier' => 'Identificador Marca', + 'Flags' => { + PrintConv => { + 'Comment' => 'Comentario', + 'FileName' => 'Nombre de Archivo', + 'Text' => 'Texto', + }, + }, + 'Flash' => { + PrintConv => { + 'Auto, Did not fire' => 'Flash no disparado, modo automático', + 'Auto, Did not fire, Red-eye reduction' => 'Auto, Flash no disparado, modo reducción ojos rojos', + 'Auto, Fired' => 'Flash disparado, modo automático', + 'Auto, Fired, Red-eye reduction' => 'Flash disparado, modo automático, modo reducción ojos rojos', + 'Auto, Fired, Red-eye reduction, Return detected' => 'Flash disparado, modo automático, retorno luz detectado, modo reducción ojos rojos', + 'Auto, Fired, Red-eye reduction, Return not detected' => 'Flash disparado, modo automático, retorno luz no detectado, modo reducción ojos rojos', + 'Auto, Fired, Return detected' => 'Flash disparado, modo automático, retorno luz detectado', + 'Auto, Fired, Return not detected' => 'Flash disparado, modo automático, retorno luz no detectado', + 'Did not fire' => 'No se ha disparado el flash', + 'Fired' => 'Flash disparado', + 'Fired, Red-eye reduction' => 'Flash disparado, modo reducción ojos rojos', + 'Fired, Red-eye reduction, Return detected' => 'Flash disparado, modo reducción ojos rojos, retorno luz detectado', + 'Fired, Red-eye reduction, Return not detected' => 'Flash disparado, modo reducción ojos rojos, retorno luz no detectado', + 'Fired, Return detected' => 'Luz devuelta en captador detectada', + 'Fired, Return not detected' => 'Luz devuelta en captador no detectada', + 'No Flash' => 'Flash no disparado', + 'No flash function' => 'Sin función flash', + 'Off' => 'Desactivado', + 'Off, Did not fire' => 'Flash no disparado, modo flash forzado', + 'Off, Did not fire, Return not detected' => 'Apagado, flash no disparado, retorno luz no detectado', + 'Off, No flash function' => 'Apagado, sin función flash', + 'Off, Red-eye reduction' => 'Apagado, modo reducción ojos rojos', + 'On' => 'Activado', + 'On, Did not fire' => 'Encendido, flash no disparado', + 'On, Fired' => 'Flash disparado, modo flash forzardo', + 'On, Red-eye reduction' => 'Flash disparado, modo flash forzado, modo reducción ojos rojos', + 'On, Red-eye reduction, Return detected' => 'Flash disparado, modo flash forzado, modo reducción ojos rojos, retorno luz detectado', + 'On, Red-eye reduction, Return not detected' => 'Flash disparado, modo flash forzado, modo reducción ojos rojos, retorno luz no detectado', + 'On, Return detected' => 'Flash disparado, modo flash forzado, retorno luz detectado', + 'On, Return not detected' => 'Flash disparado, modo flash forzado, retorno luz no detectado', + }, + }, + 'FlashColorFilter' => { + PrintConv => { + 'None' => 'Ninguno', + 'Red' => 'Rojo', + 'Yellow' => 'Amarillo', + }, + }, + 'FlashCommanderMode' => { + PrintConv => { + 'Off' => 'Desactivado', + 'On' => 'Activado', + }, + }, + 'FlashControlMode' => { + Description => 'Modo Control Flash', + PrintConv => { + 'Off' => 'Desactivado', + 'Repeating Flash' => 'Flash Estroboscopico', + }, + }, + 'FlashDevice' => { + PrintConv => { + 'None' => 'Ninguno', + }, + }, + 'FlashEnergy' => 'Energía Flash', + 'FlashExposureComp' => 'Compensación Exposición Flash', + 'FlashExposureLock' => { + PrintConv => { + 'Off' => 'Desactivado', + 'On' => 'Activado', + }, + }, + 'FlashFired' => { + PrintConv => { + 'Yes' => 'Si', + }, + }, + 'FlashFocalLength' => 'Longitud Flash Flash', + 'FlashGroupAControlMode' => { + PrintConv => { + 'Off' => 'Desactivado', + }, + }, + 'FlashGroupBControlMode' => { + PrintConv => { + 'Off' => 'Desactivado', + }, + }, + 'FlashGroupCControlMode' => { + PrintConv => { + 'Off' => 'Desactivado', + }, + }, + 'FlashIntensity' => { + Description => 'Intensidad Flash', + PrintConv => { + 'High' => 'Alto', + 'Low' => 'Bajo', + }, + }, + 'FlashLevel' => { + PrintConv => { + 'Low' => 'Bajo', + }, + }, + 'FlashMeteringMode' => { + PrintConv => { + 'External Auto' => 'Externo Automatico', + 'External Manual' => 'Externo Manual', + 'Off' => 'Desactivado', + }, + }, + 'FlashMode' => { + Description => 'Modo Flash', + PrintConv => { + 'Auto' => 'Automático', + 'Disabled' => 'Desactivado', + 'Force' => 'Forzado', + 'Off' => 'Apagado', + 'On' => 'Encendido', + 'Red eye' => 'Ojos rojos', + }, + }, + 'FlashModel' => { + Description => 'Modelo Flash', + PrintConv => { + 'None' => 'Ninguno', + }, + }, + 'FlashOutput' => 'Flash Salida', + 'FlashRemoteControl' => 'Control Remote Flash', + 'FlashSerialNumber' => 'Número Serie Flash', + 'FlashSource' => { + PrintConv => { + 'None' => 'Ninguno', + }, + }, + 'FlashStatus' => { + PrintConv => { + 'Off' => 'Desactivado', + }, + }, + 'FlashType' => { + Description => 'Tipo Flash', + PrintConv => { + 'None' => 'Ninguno', + }, + }, + 'FlashWarning' => { + PrintConv => { + 'Off' => 'Desactivado', + 'On' => 'Activado', + }, + }, + 'FlashpixVersion' => 'Versión Flashpix Soportado', + 'FlickerReduce' => { + Description => 'Reducir Parpadeo', + PrintConv => { + 'Off' => 'Apagado', + 'On' => 'Encendido', + }, + }, + 'FlipHorizontal' => { + PrintConv => { + 'Yes' => 'Si', + }, + }, + 'FocalLength' => 'Distancia Focal Objetivo', + 'FocalLength35efl' => 'Longitud Focal (Conversión a 35 mm)', + 'FocalLengthIn35mmFormat' => 'Distancia Focal en Película de 35 mm', + 'FocalPlaneResolutionUnit' => { + Description => 'Unidad Resolución Plano Focal', + PrintConv => { + 'None' => 'Ninguno', + 'inches' => 'Pulgada', + 'um' => 'µm (Micrometro)', + }, + }, + 'FocalPlaneXResolution' => 'Resolución X Plano Focal', + 'FocalPlaneYResolution' => 'Resolución Y Plano Focal', + 'FocusContinuous' => { + PrintConv => { + 'Continuous' => 'Continuo', + 'Single' => 'Sencillo', + }, + }, + 'FocusMode' => { + Description => 'Modo Enfoque', + PrintConv => { + 'Continuous' => 'Continuo', + 'Manual Focus (3)' => 'Enfoque Manual (6)', + 'Manual Focus (6)' => 'Enfoque Manual (6)', + 'Single' => 'Simple', + }, + }, + 'FocusRange' => { + Description => 'Rango de Enfoque', + PrintConv => { + 'Close' => 'Próximo', + 'Infinity' => 'Infinito', + 'Not Known' => 'Desconocido', + 'Very Close' => 'Muy Próximo', + }, + }, + 'FocusSetting' => 'Ajuste Enfoque', + 'FocusTrackingLockOn' => { + PrintConv => { + 'Off' => 'Desactivado', + }, + }, + 'ForwardMatrix1' => 'Matriz Avance 1', + 'ForwardMatrix2' => 'Matriz Avance 2', + 'FrameRate' => 'Velocidad del Fotograma', + 'FrameSize' => 'Tamaño del Fotograma', + 'FreeByteCounts' => 'Número Bytes Libres', + 'FreeOffsets' => 'Offsets Libres', + 'FuncButton' => { + PrintConv => { + 'None' => 'Ninguno', + }, + }, + 'FuncButtonPlusDials' => { + PrintConv => { + 'None' => 'Ninguno', + }, + }, + 'GEModel' => 'Modelo', + 'GPSAltitude' => 'Altitud', + 'GPSAltitudeRef' => { + Description => 'Referencia Altitud', + PrintConv => { + 'Above Sea Level' => 'Nivel del Mar', + 'Below Sea Level' => 'Referencia Nivel del Mar (valor negativo)', + }, + }, + 'GPSAreaInformation' => 'Nombre de Zona GPS', + 'GPSDOP' => 'Precisión Medición', + 'GPSDateStamp' => 'Fecha GPS', + 'GPSDateTime' => 'Fecha y Hora GPS', + 'GPSDestBearing' => 'Orientación de Destino', + 'GPSDestBearingRef' => { + Description => 'Referencia para Orientación de Destino', + PrintConv => { + 'Magnetic North' => 'Dirección magnética', + 'True North' => 'Dirección real', + }, + }, + 'GPSDestDistance' => 'Distancia a Destino', + 'GPSDestDistanceRef' => { + Description => 'Referencia para Distancia a Destino', + PrintConv => { + 'Kilometers' => 'Kilómetros', + 'Miles' => 'Millas', + 'Nautical Miles' => 'Nudos', + }, + }, + 'GPSDestLatitude' => 'Latitud de Destino', + 'GPSDestLatitudeRef' => { + Description => 'Referencia para Latitud de Destino', + PrintConv => { + 'North' => 'Latitud norte', + 'South' => 'Latitud sur', + }, + }, + 'GPSDestLongitude' => 'Longitud de Destino', + 'GPSDestLongitudeRef' => { + Description => 'Referencia para Longitud de Destino', + PrintConv => { + 'East' => 'Longitud este', + 'West' => 'Longitud oeste', + }, + }, + 'GPSDifferential' => { + Description => 'Corrección Diferencial GPS', + PrintConv => { + 'Differential Corrected' => 'Corrección diferencial aplicada', + 'No Correction' => 'Medición sin corrección diferencial', + }, + }, + 'GPSImgDirection' => 'Dirección de Imagen', + 'GPSImgDirectionRef' => { + Description => 'Referencia para Dirección de Imagen', + PrintConv => { + 'Magnetic North' => 'Dirección magnética', + 'True North' => 'Dirección real', + }, + }, + 'GPSInfo' => 'Puntero IFD de Información GPS', + 'GPSLatitude' => 'Latitud', + 'GPSLatitudeRef' => { + Description => 'Latitud Norte o Sur', + PrintConv => { + 'North' => 'Latitud norte', + 'South' => 'Latitud sur', + }, + }, + 'GPSLongitude' => 'Longitud', + 'GPSLongitudeRef' => { + Description => 'Longitud Este u Oeste', + PrintConv => { + 'East' => 'Longitud Este', + 'West' => 'Longitud Oeste', + }, + }, + 'GPSMapDatum' => 'Dato Medición Geodésica Usado', + 'GPSMeasureMode' => { + Description => 'Modo Medición GPS', + PrintConv => { + '2-Dimensional Measurement' => 'Medición bidimensional', + '3-Dimensional Measurement' => 'Medición tridimensional', + }, + }, + 'GPSProcessingMethod' => 'Nombre del Método de Procesado GPS', + 'GPSSatellites' => 'Satélites GPS Usados para Medida', + 'GPSSpeed' => 'Velocidad del Receptor GPS', + 'GPSSpeedRef' => { + Description => 'Unidad Velocidad', + PrintConv => { + 'km/h' => 'Kilómetros por hora', + 'knots' => 'Nudos', + 'mph' => 'Millas por hora', + }, + }, + 'GPSStatus' => { + Description => 'Estado Receptor GPS', + PrintConv => { + 'Measurement Active' => 'Medición Activa', + 'Measurement Void' => 'Medición Vacía', + }, + }, + 'GPSTimeStamp' => 'Hora GPS (reloj atómico)', + 'GPSTrack' => 'Dirección de Movimiento', + 'GPSTrackRef' => { + Description => 'Referencia de Dirección de Movimiento', + PrintConv => { + 'Magnetic North' => 'Dirección magnética', + 'True North' => 'Dirección real', + }, + }, + 'GPSVersionID' => 'Versión Etiqueta GPS', + 'GainControl' => { + Description => 'Control Ganancia', + PrintConv => { + 'High gain down' => 'Atenuación alta', + 'High gain up' => 'Ganancia alta', + 'Low gain down' => 'Atenuación baja', + 'Low gain up' => 'Ganancia debil', + 'None' => 'Ninguno', + }, + }, + 'GammaCompensatedValue' => 'Valor Compensado Gamma', + 'Gapless' => { + PrintConv => { + 'Yes' => 'Si', + }, + }, + 'Genre' => { + Description => 'Género', + PrintConv => { + 'None' => 'Ninguno', + 'Other' => 'Otro', + }, + }, + 'GenreID' => 'ID Género', + 'GeoTiffAsciiParams' => 'Etiqueta Parámetros Ascii Geo', + 'GeoTiffDirectory' => 'Etiqueta Directorio Clave Geo', + 'GeoTiffDoubleParams' => 'Etiqueta Parámetros Doble Geo', + 'Gradation' => 'Luminosidad', + 'GrayResponseCurve' => 'Curva Respuesta Gris', + 'GrayResponseUnit' => { + Description => 'Unidad Respuesta Gris', + PrintConv => { + '0.0001' => 'Número representa la milésima de una unidad', + '0.001' => 'Número representa la centésima de una unidad', + '0.1' => 'Número representa la décima de una unidad', + '1e-05' => 'Número representa la diezmilésima de una unidad', + '1e-06' => 'Número representa la cienmilésima de una unidad', + }, + }, + 'GrayTRC' => 'Columna Matriz Gris', + 'GreenMatrixColumn' => 'Columna Matriz Verde', + 'GreenTRC' => 'Curva Reproducción Tono Verde', + 'GridDisplay' => { + PrintConv => { + 'Off' => 'Desactivado', + 'On' => 'Activado', + }, + }, + 'HCUsage' => 'Uso HC', + 'HDR' => { + Description => 'Auto HDR', + PrintConv => { + 'Off' => 'Desactivado', + }, + }, + 'HDRSmoothing' => { + PrintConv => { + 'Low' => 'Bajo', + 'Off' => 'Desactivado', + }, + }, + 'HalftoneHints' => 'Indicación Medio Tono', + 'HasAttachedImages' => 'Tiene Imagenes Adjuntas', + 'HasAudio' => 'Tiene Audio', + 'HasImage' => 'Tiene Imagen', + 'HasScript' => 'Tiene Script', + 'HasVideo' => 'Tiene Video', + 'Headline' => 'Titular', + 'HeightResolution' => 'Resolución Imagen Vertical', + 'HighISONoiseReduction' => { + Description => 'Reducción Ruido ISO Alta', + PrintConv => { + 'High' => 'Alto', + 'Low' => 'Bajo', + 'Off' => 'Desactivado', + 'On' => 'Activado', + 'Standard' => 'Estándar', + 'Strong' => 'Fuerte', + }, + }, + 'HighISONoiseReduction2' => { + PrintConv => { + 'Low' => 'Bajo', + }, + }, + 'Highlight' => 'Realce', + 'HighlightColorDistortReduct' => { + PrintConv => { + 'Standard' => 'Estándar', + }, + }, + 'HighlightTonePriority' => { + PrintConv => { + 'Off' => 'Desactivado', + 'On' => 'Activado', + }, + }, + 'HometownDST' => { + PrintConv => { + 'Yes' => 'Si', + }, + }, + 'HostComputer' => 'Ordenador Principal', + 'Hue' => { + Description => 'Tono', + PrintConv => { + 'None' => 'Ninguno', + }, + }, + 'HyperfocalDistance' => 'Distancia Hiperfocal', + 'ICCProfile' => 'Perfil ICC', + 'ICC_Profile' => 'Perfil Color Entrada ICC', + 'IDCCreativeStyle' => { + PrintConv => { + 'Landscape' => 'Retrato', + 'Neutral' => 'Neutro', + 'Standard' => 'Estándar', + 'Vivid' => 'Vívido', + }, + }, + 'IPTC-NAA' => 'Metadato IPTC-NAA', + 'IPTCBitsPerSample' => 'Número de Bits por Muestra', + 'IPTCImageHeight' => 'Número de Líneas', + 'IPTCImageRotation' => { + Description => 'Rotación Imagen', + PrintConv => { + '0' => 'Sin rotación', + '180' => 'Rotación 180 grados', + '270' => 'Rotación 270 grados', + '90' => 'Rotación 90 grados', + }, + }, + 'IPTCImageWidth' => 'Pixels por Línea', + 'IPTCPictureNumber' => 'Número Imagen', + 'IPTCPixelHeight' => 'Tamaño Pixel Perpendicular a Dirección Escaneo', + 'IPTCPixelWidth' => 'Tamaño Pixel en Dirección Escaneo', + 'ISO' => 'Ratio Velocidad ISO', + 'ISOAutoParameters' => { + PrintConv => { + 'Fast' => 'Rápido', + 'Standard' => 'Estándar', + }, + }, + 'ISOExpansion' => { + PrintConv => { + 'Off' => 'Desactivado', + }, + }, + 'ISOExpansion2' => { + PrintConv => { + 'Off' => 'Desactivado', + }, + }, + 'ISOSetting' => 'Ajuste ISO', + 'ISOSpeedExpansion' => { + PrintConv => { + 'Yes' => 'Si', + }, + }, + 'IT8Header' => 'Cabecera IT8', + 'Illumination' => { + PrintConv => { + 'Off' => 'Desactivado', + 'On' => 'Activado', + }, + }, + 'Image::ExifTool::AIFF::Comment' => 'Comentario AIFF', + 'ImageAuthentication' => { + PrintConv => { + 'Off' => 'Desactivado', + }, + }, + 'ImageByteCount' => 'Número Byte Imagen', + 'ImageColor' => { + PrintConv => { + 'Monochrome' => 'Monocromo', + }, + }, + 'ImageColorIndicator' => 'Indicador Color Imagen', + 'ImageColorValue' => 'Valor Color Imagen', + 'ImageDataDiscard' => { + Description => 'Datos Imagen Descartado', + PrintConv => { + 'Flexbits Discarded' => 'FlexBits Descartados', + 'Full Resolution' => 'Resolución Total', + 'HighPass Frequency Data Discarded' => 'Datos Frecuencia High-Pass Descartados', + 'Highpass and LowPass Frequency Data Discarded' => 'Dato Frecuencia High-Pass y Low-Pass Descartados', + }, + }, + 'ImageDepth' => 'Ancho Imagen', + 'ImageDescription' => 'Título Imagen', + 'ImageDustOff' => { + PrintConv => { + 'Off' => 'Desactivado', + 'On' => 'Activado', + }, + }, + 'ImageEditing' => { + PrintConv => { + 'None' => 'Ninguno', + }, + }, + 'ImageFileFormatAsDelivered' => { + PrintConv => { + 'Other' => 'Otro', + }, + }, + 'ImageHeight' => 'Alto Imagen', + 'ImageHistory' => 'Historia Imagen', + 'ImageID' => 'ID Imagen', + 'ImageInfo' => 'Info Imagen', + 'ImageLayer' => 'Capa Imagen', + 'ImageLength' => 'Longitud Imagen', + 'ImageNumber' => 'Número Imagen', + 'ImageOffset' => 'Offset Imagen', + 'ImageOrientation' => { + Description => 'Orientación Imagen', + PrintConv => { + 'Landscape' => 'Paisaje', + 'Portrait' => 'Retrato', + 'Square' => 'Cuadro', + }, + }, + 'ImageQuality' => { + PrintConv => { + 'High' => 'Alto', + 'Standard' => 'Estándar', + }, + }, + 'ImageResourceBlocks' => 'Bloques Recursos Imagen', + 'ImageReview' => { + PrintConv => { + 'Off' => 'Desactivado', + 'On' => 'Activado', + }, + }, + 'ImageRotated' => { + PrintConv => { + 'Yes' => 'Si', + }, + }, + 'ImageRotation' => { + PrintConv => { + 'None' => 'Ninguno', + }, + }, + 'ImageSize' => 'Tamaño de la Imagen', + 'ImageSourceData' => 'Datos Fuente Imagen', + 'ImageStabilization' => { + Description => 'Estabilización Imagen', + PrintConv => { + 'Off' => 'Desactivado', + 'On' => 'Activado', + }, + }, + 'ImageStabilizationSetting' => 'Ajustes Estabilización Imagen', + 'ImageStyle' => { + PrintConv => { + 'Landscape' => 'Paisaje', + 'Neutral' => 'Neutro', + 'Portrait' => 'Retrato', + 'Standard' => 'Estándar', + 'Vivid' => 'Vívido', + }, + }, + 'ImageTone' => { + PrintConv => { + 'Landscape' => 'Paisaje', + 'Monochrome' => 'Monocromo', + 'Portrait' => 'Retrato', + }, + }, + 'ImageType' => { + Description => 'Tipo Imagen', + PrintConv => { + 'Other' => 'Otro', + }, + }, + 'ImageUniqueID' => 'ID Único Imagen', + 'ImageWidth' => 'Ancho Imagen', + 'Index' => 'Índice', + 'Indexed' => 'Indizado', + 'IngredientsMaskMarkers' => { + PrintConv => { + 'All' => 'Todo', + 'None' => 'Ninguno', + }, + }, + 'InitialKey' => 'Clave inicial', + 'InkNames' => 'Nombres Tinta', + 'InkSet' => 'Conjunto Tinta', + 'Instructions' => 'Instrucciones', + 'IntellectualGenre' => 'Género Intelectual', + 'IntelligentContrast' => { + PrintConv => { + 'Off' => 'Desactivado', + 'On' => 'Activado', + 'n/a' => 'No Aplica', + }, + }, + 'IntelligentD-Range' => { + PrintConv => { + 'High' => 'Alto', + 'Low' => 'Bajo', + 'Standard' => 'Estándar', + }, + }, + 'IntelligentExposure' => { + PrintConv => { + 'High' => 'Alto', + 'Low' => 'Bajo', + 'Standard' => 'Estándar', + }, + }, + 'IntelligentResolution' => { + PrintConv => { + 'High' => 'Alto', + 'Low' => 'Bajo', + 'Standard' => 'Estándar', + }, + }, + 'IntensityStereo' => { + PrintConv => { + 'Off' => 'Desactivado', + 'On' => 'Activado', + }, + }, + 'InterchangeColorSpace' => { + PrintConv => { + 'CMY (K) Device Dependent' => 'Dispositivo dependiente CMY(K)', + 'RGB Device Dependent' => 'Dispositivo dependiente RGB', + }, + }, + 'IntergraphMatrix' => 'Etiqueta Matriz Intergráfica', + 'Interlace' => 'Entrelazado', + 'InternalFlash' => 'Flash Interno', + 'InternalFlashAE1' => 'Flash Interno AE1', + 'InternalFlashAE1_0' => 'Flash Interno', + 'InternalFlashAE2' => 'Flash Interno AE2', + 'InternalFlashAE2_0' => 'Flash Interno AE2', + 'InternalFlashMode' => { + Description => 'Modo Flash Interno', + PrintConv => { + 'Fired' => 'Activado', + }, + }, + 'InternalFlashTable' => 'Tabla Flash Interno', + 'InternalSerialNumber' => 'Número Serie Interno', + 'InteropIndex' => { + Description => 'Identificación Interoperabilidad', + PrintConv => { + 'R03 - DCF option file (Adobe RGB)' => 'R03: Archivo opción DCF (Adobe RGB)', + 'R98 - DCF basic file (sRGB)' => 'R98: Archivo básico DCF (sRGB)', + 'THM - DCF thumbnail file' => 'THM: Archivo miniatura DCF', + }, + }, + 'InteropOffset' => 'Etiqueta de Interoperabilidad', + 'InteropVersion' => 'Versión Interoperabilidad', + 'Is_Protected' => 'Está protegido', + 'Is_Trusted' => 'Es de confianza', + 'JFIFVersion' => 'Versión JFIF', + 'JPEGACTables' => 'Tablas AC JPEG', + 'JPEGDCTables' => 'Tablas DC JPEG', + 'JPEGLosslessPredictors' => 'Predictores Sin Perdidas JPEG', + 'JPEGPointTransforms' => 'Tranformadores Puntos JPEG', + 'JPEGProc' => 'Proc JPEG', + 'JPEGQTables' => 'Tablas Q JPEG', + 'JPEGQuality' => { + Description => 'Calidad', + PrintConv => { + 'Extra Fine' => 'Extrafina', + 'Fine' => 'Fina', + 'Standard' => 'Calidad estándar', + }, + }, + 'JPEGRestartInterval' => 'Intervalo Reinicio JPEG', + 'JPEGTables' => 'Tablas JPEG', + 'JobID' => 'ID del Trabajo', + 'JobTitle' => 'Cargo', + 'Keyword' => 'Palabras Clave', + 'Keywords' => 'Clave', + 'LCDIllumination' => { + PrintConv => { + 'Off' => 'Desactivado', + 'On' => 'Activado', + }, + }, + 'LCDIlluminationDuringBulb' => { + PrintConv => { + 'Off' => 'Desactivado', + 'On' => 'Activado', + }, + }, + 'LCHEditor' => { + PrintConv => { + 'Off' => 'Desactivado', + 'On' => 'Activado', + }, + }, + 'Language' => 'Idioma', + 'LanguageCode' => { + PrintConv => { + 'Neutral' => 'Neutro', + }, + }, + 'LanguageIdentifier' => 'Identificador Idioma', + 'LanguageList' => 'Lista de Idiomas', + 'LeafData' => 'Datos Hoja', + 'Lens' => 'Objetivo', + 'LensApertureRange' => 'Intervalo Apertura Objetivo', + 'LensFirmwareVersion' => 'Versión Firmware Objetivo', + 'LensID' => 'ID Objetivo', + 'LensIDNumber' => 'Número ID Objetivo', + 'LensInfo' => 'Información del Objetivo', + 'LensModel' => 'Modelo Objetivo', + 'LensProperties' => 'Propiedades Objetivo', + 'LensSerialNumber' => 'Número Serie Objetivo', + 'LensType' => { + Description => 'Tipo Objetivo', + PrintConv => { + 'None' => 'Ninguno', + }, + }, + 'LightSource' => { + Description => 'Fuente Luz', + PrintConv => { + 'Cloudy' => 'Tiempo Nublado', + 'Cool White Fluorescent' => 'Fluorescente blanco cálido (W 3800 - 4500K)', + 'Day White Fluorescent' => 'Fluorescente blanco día (N 4600 - 5500K)', + 'Daylight' => 'Luz del día', + 'Daylight Fluorescent' => 'Fluorescente luz de día (D 5700 - 7100K)', + 'Fine Weather' => 'Buen tiempo', + 'Fluorescent' => 'Fluorescente', + 'ISO Studio Tungsten' => 'Tungsteno estudio ISO', + 'Other' => 'Otras Fuentes Luz', + 'Shade' => 'Sombrío', + 'Standard Light A' => 'Luz Estándar A', + 'Standard Light B' => 'Luz Estándar B', + 'Standard Light C' => 'Luz Estándar C', + 'Tungsten (Incandescent)' => 'Tungsteno (luz incandescente)', + 'Unknown' => 'Desconocido', + 'Warm White Fluorescent' => 'Fluorescente blanco cálido (L 2600 - 3250K)', + 'White Fluorescent' => 'Fluorescente blanco (WW 3250 - 3800K)', + }, + }, + 'LightSourceSpecial' => { + Description => 'Fuente Luz Especial', + PrintConv => { + 'Off' => 'Apagado', + 'On' => 'Encendido', + }, + }, + 'Lightness' => 'Luminosidad', + 'LinearResponseLimit' => 'Límite Respuesta Lineal', + 'LinearizationTable' => 'Tabla Linearización', + 'Lit' => { + PrintConv => { + 'Yes' => 'Si', + }, + }, + 'LiveViewShooting' => { + PrintConv => { + 'Off' => 'Desactivado', + 'On' => 'Activado', + }, + }, + 'LocalizedCameraModel' => 'Modelo Cámara Traducido', + 'Location' => 'Localización', + 'LongExposureNoiseReduction' => { + Description => 'RR Exp.Larga', + PrintConv => { + 'Off' => 'Desactivado', + 'On' => 'Activado', + }, + }, + 'LookupTable' => 'Tabla de Consulta', + 'Luminance' => 'Luminancia', + 'LuminanceNoiseReduction' => { + PrintConv => { + 'High' => 'Alto', + 'Low' => 'Bajo', + 'Off' => 'Desactivado', + }, + }, + 'Lyrics' => 'Letras', + 'Lyrics_Synchronised' => 'Letras Sincronizadas', + 'MSStereo' => { + PrintConv => { + 'Off' => 'Desactivado', + 'On' => 'Activado', + }, + }, + 'Macro' => { + PrintConv => { + 'Off' => 'Apagado', + 'On' => 'Encendido', + 'View' => 'Vista', + }, + }, + 'MacroMode' => 'Modo Macro', + 'MainDialExposureComp' => { + PrintConv => { + 'Off' => 'Desactivado', + 'On' => 'Activado', + }, + }, + 'Make' => 'Marca', + 'MakeAndModel' => 'Marca y Modelo', + 'MakerNote' => 'Dato Privado DNG', + 'MakerNoteOffset' => 'Offset Maker Note', + 'MakerNoteSafety' => { + Description => 'Seguridad Maker Note', + PrintConv => { + 'Safe' => 'Seguro', + 'Unsafe' => 'No Seguro', + }, + }, + 'MakerNoteType' => 'Tipo Maker Note', + 'MakerNoteVersion' => 'Versión nota Fabricante', + 'MakerNotes' => 'Notas del Fabricante', + 'ManagedFromMaskMarkers' => { + PrintConv => { + 'All' => 'Todo', + 'None' => 'Ninguno', + }, + }, + 'ManifestReferenceMaskMarkers' => { + PrintConv => { + 'All' => 'Todo', + 'None' => 'Ninguno', + }, + }, + 'ManometerPressure' => 'Presión Manometrica', + 'ManometerReading' => 'Lectura Manometrica', + 'ManualFlashOutput' => { + PrintConv => { + 'Full' => 'Completo', + 'Low' => 'Bajo', + 'Medium' => 'Medio', + 'n/a' => 'No Aplica', + }, + }, + 'ManualFocusDistance' => 'Distancia Enfoque Manual', + 'Marker' => 'Marcador', + 'MaskedAreas' => 'Área Oculta', + 'MasterDocumentID' => 'ID de Documento Maestro', + 'Matteing' => 'Mate', + 'MaxAperture' => 'Máxima Apertura del Objetivo', + 'MaxApertureAtMaxFocal' => 'Apertura máxima a focal máxima', + 'MaxApertureAtMinFocal' => 'Apertura máxima a focal mínima', + 'MaxApertureValue' => 'Apertura Lente Máxima', + 'MaxFaces' => 'Máximo caras', + 'MaxFocalLength' => 'Longitud focal máxima', + 'MaxPacketSize' => 'Tamaño Máximo Paquete', + 'MaxSampleValue' => 'Valor Muestra Max', + 'MaximumDensityRange' => 'Rango Densidad Maxima', + 'Measurement' => 'Observador de Medida', + 'MeasurementBacking' => 'Apoyo de Medida', + 'MeasurementFlare' => 'Llama de Medida', + 'MeasurementGeometry' => { + Description => 'Geometría de Medida', + PrintConv => { + '0/45 or 45/0' => '0/45 o 45/0', + '0/d or d/0' => '0/d o d/0', + }, + }, + 'MeasurementIlluminant' => 'Iluminación de Medida', + 'MeasurementObserver' => 'Observador de Medida', + 'MediaBlackPoint' => 'Punto Negro Medio', + 'MediaWhitePoint' => 'Punto Blanco Medio', + 'MeteringMode' => { + Description => 'Modo Medición', + PrintConv => { + 'Average' => 'Promedio', + 'Center-weighted average' => 'Media ponderada al centro', + 'Multi-segment' => 'Multi-segmento', + 'Multi-spot' => 'Multi-puntual', + 'Other' => 'Otro', + 'Partial' => 'Parcial', + 'Spot' => 'Puntual', + 'Unknown' => 'Desconocido', + }, + }, + 'MinAperture' => 'Apertura mínima', + 'MinFocalLength' => 'Longitud focal mínima', + 'MinPacketSize' => 'Tamaño Mínimo Paquete', + 'MinSampleValue' => 'Valor Muestra Min', + 'MinoltaQuality' => { + PrintConv => { + 'Standard' => 'Estándar', + }, + }, + 'ModeDialPosition' => { + PrintConv => { + 'Panorama' => 'Panoramica', + }, + }, + 'Model' => 'Modelo', + 'Model2' => 'Modelo Equipamiento Entrada Imagen (2)', + 'ModelReleaseStatus' => { + PrintConv => { + 'None' => 'Ninguno', + }, + }, + 'ModelTiePoint' => 'Etiqueta Modelo Punto Lazo', + 'ModelTransform' => 'Etiqueta Modelo Transformación', + 'ModelingFlash' => { + PrintConv => { + 'Off' => 'Desactivado', + 'On' => 'Activado', + }, + }, + 'ModifiedBy' => 'Modificado por', + 'ModifiedPictureStyle' => { + PrintConv => { + 'High Saturation' => 'Saturación Alta', + 'Landscape' => 'Paisaje', + 'Low Saturation' => 'Saturación Baja', + 'Monochrome' => 'Monocromo', + 'Neutral' => 'Neutro', + 'None' => 'Ninguno', + 'Portrait' => 'Retrato', + 'Standard' => 'Estándar', + }, + }, + 'ModifiedSharpnessFreq' => { + PrintConv => { + 'High' => 'Alto', + 'Low' => 'Bajo', + 'Standard' => 'Estándar', + }, + }, + 'ModifiedToneCurve' => { + PrintConv => { + 'Standard' => 'Estándar', + }, + }, + 'ModifiedWhiteBalance' => { + PrintConv => { + 'Underwater' => 'Subacuatica', + }, + }, + 'ModifyDate' => 'Fecha y Hora de Cambio del Archivo', + 'MoireFilter' => { + PrintConv => { + 'Off' => 'Desactivado', + 'On' => 'Activado', + }, + }, + 'MonochromeFilterEffect' => { + PrintConv => { + 'Green' => 'Verde', + 'None' => 'Ninguno', + 'Orange' => 'Naranja', + 'Red' => 'Rojo', + 'Yellow' => 'Amarillo', + }, + }, + 'MonochromeLinear' => { + PrintConv => { + 'Yes' => 'Si', + }, + }, + 'MonochromeToning' => { + PrintConv => { + 'None' => 'Ninguno', + }, + }, + 'MonochromeToningEffect' => { + PrintConv => { + 'Green' => 'Verde', + 'None' => 'Ninguno', + }, + }, + 'MultiExposureAutoGain' => { + PrintConv => { + 'Off' => 'Desactivado', + 'On' => 'Activado', + }, + }, + 'MultiExposureMode' => { + PrintConv => { + 'Off' => 'Desactivado', + }, + }, + 'MultiFrameNoiseReduction' => { + Description => 'Reduc. ruido varios fotogr.', + PrintConv => { + 'None' => 'Ninguno', + 'Off' => 'Desactivado', + 'On' => 'Activado', + }, + }, + 'MultipleExposureMode' => 'Modo Exposición Múltiple', + 'MultipleExposureSet' => { + PrintConv => { + 'Off' => 'Desactivado', + 'On' => 'Activado', + }, + }, + 'Mute' => { + PrintConv => { + 'Off' => 'Desactivado', + 'On' => 'Activado', + }, + }, + 'MyColorMode' => { + PrintConv => { + 'Neutral' => 'Neutro', + 'Off' => 'Desactivado', + 'Vivid' => 'Vívido', + }, + }, + 'NDFilter' => { + PrintConv => { + 'Off' => 'Desactivado', + 'On' => 'Activado', + }, + }, + 'NSC_Description' => 'Descripción NSC', + 'Name' => 'Nombre', + 'NamedColor2' => 'Color Llamado 2', + 'NativeDisplayInfo' => 'Información Pantalla Nativa', + 'NewsPhotoVersion' => 'Versión Registro Foto Noticias', + 'Noise' => 'Ruido', + 'NoiseFilter' => { + PrintConv => { + 'High' => 'Alto', + 'Low' => 'Bajo', + 'Off' => 'Desactivado', + 'Standard' => 'Estándar', + }, + }, + 'NoiseReduction' => { + Description => 'Reducción Ruido', + PrintConv => { + 'Low' => 'Bajo', + 'Off' => 'Desactivado', + 'Standard' => 'Estándar', + }, + }, + 'NoiseReductionApplied' => 'Reducción Ruido Aplicada', + 'NominalMaxAperture' => 'Apertura máxima nominal', + 'NominalMinAperture' => 'Apertura mínima nominal', + 'NumAFPoints' => 'Número de Puntos AF', + 'NumChannels' => 'Número Canales', + 'NumColors' => 'Número de colores', + 'NumImportantColors' => 'Número Colores Importantes', + 'NumIndexEntries' => 'Número de Entradas de Índice', + 'NumSampleFrames' => 'Número de fotogramas', + 'NumberOfFrames' => 'Número de imágenes', + 'NumberofInks' => 'Número de Tintas', + 'OPIProxy' => 'Proxy OPI', + 'ObjectAttributeReference' => 'Género Intelectual', + 'ObjectCycle' => { + Description => 'Ciclo Objecto', + PrintConv => { + 'Both Morning and Evening' => 'Ambos', + 'Evening' => 'Tarde', + 'Morning' => 'Mañana', + }, + }, + 'ObjectFileType' => { + PrintConv => { + 'None' => 'Ninguno', + 'Unknown' => 'Desconocido', + }, + }, + 'ObjectName' => 'Título', + 'ObjectPreviewData' => 'Datos Previos del Objecto', + 'ObjectPreviewFileFormat' => 'Formato Archivo Previo de Objecto', + 'ObjectPreviewFileVersion' => 'Versión Formato Archivo Previo del Objecto', + 'ObjectTypeReference' => 'Referencia Tipo Objeto', + 'OffsetSchema' => 'Offset Esquema', + 'OperatingSystem' => { + Description => 'Sistema Operativo', + PrintConv => { + 'unknown' => 'desconocido', + }, + }, + 'OpticalZoomMode' => { + PrintConv => { + 'Standard' => 'Estándar', + }, + }, + 'OpticalZoomOn' => { + Description => 'Zoom Óptico Encendido', + PrintConv => { + 'Off' => 'Apagado', + 'On' => 'Encendido', + }, + }, + 'Opto-ElectricConvFactor' => 'Factor Conversión Optoeléctrico', + 'Orientation' => { + Description => 'Orientación de Imagen', + PrintConv => { + 'Horizontal (normal)' => '0° (arriba/izquierda)', + 'Mirror horizontal' => 'Invertir horizontal', + 'Mirror horizontal and rotate 270 CW' => 'Invertir horizontal y rotar 270° sentido reloj', + 'Mirror horizontal and rotate 90 CW' => 'Invertir horizontal y rotar 90° sentido reloj', + 'Mirror vertical' => 'Invertir vertical', + 'Rotate 180' => 'Girado 180°', + 'Rotate 270 CW' => 'Girado 270° sentido reloj', + 'Rotate 90 CW' => 'Girado 90° sentido reloj', + }, + }, + 'OriginPlatform' => { + PrintConv => { + 'Other' => 'Otro', + }, + }, + 'OriginalAlbumTitle' => 'Título Original Album', + 'OriginalArtist' => 'Artista original', + 'OriginalFileName' => 'Nombre archivo original', + 'OriginalLyricist' => 'Letrista Original', + 'OriginalRawFileData' => 'Dato Archivo Raw Original', + 'OriginalRawFileDigest' => 'Cifrado Archivo Raw Original', + 'OriginalRawFileName' => 'Nombre Archivo Raw Original', + 'OriginalReleaseYear' => 'Año Versión Original', + 'OriginalTransmissionReference' => 'Identificador de Trabajo', + 'OriginatingProgram' => 'Programa Originario', + 'OutputResponse' => 'Respuesta Salida', + 'Owner' => 'Propietario', + 'OwnerID' => 'ID del Propietario', + 'OwnerName' => 'Nombre del Propietario', + 'PF25ColorMatrix' => 'Matriz de Color PF25', + 'PackingMethod' => { + PrintConv => { + 'Best Compression' => 'Mejor Compresión', + 'Fast' => 'Rápido', + 'Fastest' => 'Mas Rápido', + 'Good Compression' => 'Buena Compresión', + 'Stored' => 'Almacenado', + }, + }, + 'Padding' => 'Margen Inferior', + 'PageName' => 'Nombre Página', + 'PageNumber' => 'Número Página', + 'PanoramaSize3D' => { + PrintConv => { + 'Standard' => 'Estándar', + }, + }, + 'Period' => 'Período', + 'PhotoEffect' => { + PrintConv => { + 'B&W' => 'Blanco y Negro', + 'Custom' => 'Personalizado', + 'Neutral' => 'Neutro', + 'Off' => 'Desactivado', + 'Vivid' => 'Vívido', + }, + }, + 'PhotoEffects' => { + PrintConv => { + 'Off' => 'Desactivado', + 'On' => 'Activado', + }, + }, + 'PhotoEffectsType' => { + PrintConv => { + 'None' => 'Ninguno', + }, + }, + 'PhotometricInterpretation' => { + Description => 'Interpretación Fotométrica', + PrintConv => { + 'BlackIsZero' => 'Negro es cero', + 'Color Filter Array' => 'CFA (Matriz Filtro Color)', + 'Pixar LogL' => 'CIE Log2(L) (Log luminancia)', + 'Pixar LogLuv' => 'CIE Log2(L)(u\',v\') (Log luminancia y crominancia)', + 'RGB Palette' => 'Paleta Color', + 'Transparency Mask' => 'Máscara de transparencia', + 'WhiteIsZero' => 'Blanco es cero', + }, + }, + 'PhotoshopAnnotations' => 'Anotaciones Photoshop', + 'PhotoshopFormat' => { + PrintConv => { + 'Standard' => 'Estándar', + }, + }, + 'PictInfo' => 'Info Imagen', + 'Picture' => 'Imágen', + 'PictureControl' => { + PrintConv => { + 'Off' => 'Desactivado', + 'On' => 'Activado', + }, + }, + 'PictureControlActive' => { + PrintConv => { + 'Off' => 'Desactivado', + 'On' => 'Activado', + }, + }, + 'PictureDescription' => 'Descripción Imágen', + 'PictureFinish' => { + PrintConv => { + 'Monochrome' => 'Monocromo', + 'Portrait' => 'Retrato', + }, + }, + 'PictureMode' => { + PrintConv => { + 'Beach' => 'Playa', + 'Fireworks' => 'Fuegos Artificiales', + 'Food' => 'Comida', + 'Green' => 'Verde', + 'Landscape' => 'Paisaje', + 'Panorama' => 'Panoramica', + 'Portrait' => 'Retrato', + 'Red' => 'Rojo', + 'Snow' => 'Nieve', + 'Soft' => 'Suave', + 'Standard' => 'Estándar', + 'Underwater' => 'Subacuatica', + 'Vivid' => 'Vívido', + 'Yellow' => 'Amarillo', + }, + }, + 'PictureModeBWFilter' => { + PrintConv => { + 'Green' => 'Verde', + 'Neutral' => 'Neutro', + 'Orange' => 'Naranja', + 'Red' => 'Rojo', + 'Yellow' => 'Amarillo', + }, + }, + 'PictureModeEffect' => { + PrintConv => { + 'High' => 'Alto', + 'Low' => 'Bajo', + 'Standard' => 'Estándar', + }, + }, + 'PictureModeTone' => { + PrintConv => { + 'Green' => 'Verde', + 'Neutral' => 'Neutro', + }, + }, + 'PictureStyle' => { + PrintConv => { + 'Faithful' => 'Fiel', + 'High Saturation' => 'Saturación Alta', + 'Landscape' => 'Paisaje', + 'Low Saturation' => 'Saturación Baja', + 'Monochrome' => 'Monocromo', + 'Neutral' => 'Neutro', + 'None' => 'Ninguno', + 'Portrait' => 'Retrato', + 'Standard' => 'Estándar', + }, + }, + 'PictureType' => { + Description => 'Tipo Imágen', + PrintConv => { + '32x32 PNG Icon' => 'Icono PNG 32x32', + 'Artist' => 'Artista', + 'Back Cover' => 'Cubierta Posterior', + 'Composer' => 'Compositor', + 'Conductor' => 'Director', + 'Front Cover' => 'Cubierta Frontal', + 'Illustration' => 'Ilustración', + 'Lyricist' => 'Letrista', + 'Media' => 'Soporte', + 'Other' => 'Otro', + 'Other Icon' => 'Otro Icono', + 'Performance' => 'Interpretación', + 'Recording Session' => 'Sesión Grabación', + }, + }, + 'PictureWizardMode' => { + PrintConv => { + 'Cool' => 'Frío', + 'Landscape' => 'Paisaje', + 'Portrait' => 'Retrato', + 'Standard' => 'Estándar', + 'Vivid' => 'Vívido', + }, + }, + 'PixelFormat' => 'Formato Pixel', + 'PixelIntensityRange' => 'Intervalo Intensidad Pixel', + 'PixelScale' => 'Etiqueta Escala Pixel Modelo', + 'PlanarConfiguration' => { + Description => 'Ajuste Datos Imagen', + PrintConv => { + 'Chunky' => 'Formato \'Chunky\' (Entrelazado)', + 'Planar' => 'Formato \'Planar\'', + }, + }, + 'Predictor' => { + PrintConv => { + 'Horizontal differencing' => 'Diferenciación Horizontal', + 'None' => 'No se usa esquema de predicción antes de codificar', + }, + }, + 'Preview0' => 'Previa 0', + 'Preview1' => 'Previa 1', + 'Preview2' => 'Previa 2', + 'PreviewApplicationName' => 'Nombre Aplicación Previa', + 'PreviewApplicationVersion' => 'Versión Aplicación Previa', + 'PreviewButton' => { + PrintConv => { + 'None' => 'Ninguno', + }, + }, + 'PreviewButtonPlusDials' => { + PrintConv => { + 'None' => 'Ninguno', + }, + }, + 'PreviewColorSpace' => { + Description => 'Espacio Color Previa', + PrintConv => { + 'Unknown' => 'Desconocido', + }, + }, + 'PreviewDateTime' => 'Fecha y Hora Previa', + 'PreviewImage' => 'Vista Previa', + 'PreviewImageLength' => 'Longitud Imagen Previa', + 'PreviewImageSize' => 'Tamaño Imagen Previa', + 'PreviewImageStart' => 'Inicio Imagen Previa', + 'PreviewImageValid' => { + PrintConv => { + 'Yes' => 'Si', + }, + }, + 'PreviewSettingsDigest' => 'Cifrado Configuración Previa', + 'PreviewSettingsName' => 'Nombre Configuración Previa', + 'PrimaryAFPoint' => 'Punto AF primario', + 'PrimaryChromaticities' => 'Cromaticidades de Colores Primarios', + 'PrimaryPlatform' => 'Plataforma Primaria', + 'ProcessingSoftware' => 'Tratamiendo de Software', + 'Producer' => 'Productor', + 'ProductID' => 'ID Producto', + 'ProfileCMMType' => 'Tipo Perfil CMM', + 'ProfileCalibrationSig' => 'Firma Perfil Calibración', + 'ProfileClass' => { + Description => 'Clase Perfil', + PrintConv => { + 'Abstract Profile' => 'Perfil Abstracto', + 'ColorSpace Conversion Profile' => 'Perfil Conversión Espacio Color', + 'DeviceLink Profile' => 'Perfil Dispositivo Conexión', + 'Display Device Profile' => 'Perfil Dispositivo Pantalla', + 'Input Device Profile' => 'Perfil Dispositivo Entrada', + 'NamedColor Profile' => 'Perfil Color Nombrado', + 'Nikon Input Device Profile (NON-STANDARD!)' => 'Perfil Nikon ("nkpf")', + 'Output Device Profile' => 'Perfil Dispositivo Salida', + }, + }, + 'ProfileConnectionSpace' => 'Espacio Conexión Perfil', + 'ProfileCopyright' => 'Copyright', + 'ProfileCreator' => 'Creador Perfil', + 'ProfileDateTime' => 'Fecha y Hora Perfil', + 'ProfileDescription' => 'Descripción Perfil', + 'ProfileDescriptionML' => 'Descripción Perfil ML', + 'ProfileEmbedPolicy' => { + Description => 'Perfil Política Incrustada', + PrintConv => { + 'Allow Copying' => 'Permitir copia', + 'Embed if Used' => 'Incrustar si se usa', + 'Never Embed' => 'Incrustado nunca', + 'No Restrictions' => 'Sin restricciones', + }, + }, + 'ProfileFileSignature' => 'Firma Archivo Perfil', + 'ProfileHueSatMapData1' => 'Perfil Matiz Sat. Mapa Dato 1', + 'ProfileHueSatMapData2' => 'Perfil Matiz Sat. Mapa Dato 2', + 'ProfileHueSatMapDims' => 'Divisiones Matiz', + 'ProfileID' => 'ID Perfil', + 'ProfileLookTableData' => 'Perfil Datos Tabla Consulta', + 'ProfileLookTableDims' => 'Divisiones Matiz', + 'ProfileName' => 'Nombre Perfil', + 'ProfileSequenceDesc' => 'Descripción Secuencia Perfil', + 'ProfileToneCurve' => 'Perfil Curva Tono', + 'ProfileVersion' => 'Versión Perfil', + 'ProgramMode' => { + PrintConv => { + 'None' => 'Ninguno', + 'Portrait' => 'Retrato', + }, + }, + 'ProgramVersion' => 'Versión Programa', + 'Projects' => 'Proyectos', + 'PromotionURL' => 'URL Promocional', + 'PropertyReleaseStatus' => { + PrintConv => { + 'None' => 'Ninguno', + }, + }, + 'Protect' => 'Protección', + 'ProtectionType' => 'Tipo Protección', + 'Provider' => 'Proveedor', + 'ProviderCopyright' => 'Copyright Proveedor', + 'Province-State' => 'Provincia/Estado', + 'Publisher' => 'Editor', + 'Quality' => { + Description => 'Calidad', + PrintConv => { + 'Compressed RAW' => 'cRAW', + 'Compressed RAW + JPEG' => 'cRAW+JPEG', + 'Extra Fine' => 'Extrafina', + 'Fine' => 'Fina', + 'High' => 'Alto', + 'Low' => 'Bajo', + 'Normal' => 'Calidad estándar', + 'RAW + JPEG' => 'RAW+JPEG', + 'Standard' => 'Estándar', + 'n/a' => 'no aplica', + }, + }, + 'QuantizationMethod' => { + Description => 'Método Cuantización', + PrintConv => { + 'AP Domestic Analogue' => 'AP Doméstico Análogo', + 'Color Space Specific' => 'Espacio Color Específico', + 'Compression Method Specific' => 'Método Compresión Específico', + 'Gamma Compensated' => 'Gamma Compensada', + 'IPTC Ref B' => 'IPTC ref "B"', + 'Linear Density' => 'Densidad lineal', + 'Linear Dot Percent' => 'Porcentaje Punto lineal', + 'Linear Reflectance/Transmittance' => 'Reflectancia/transmitancia lineal', + }, + }, + 'QuickShot' => { + Description => 'Disparo Rápido', + PrintConv => { + 'Off' => 'Apagado', + 'On' => 'Encendido', + }, + }, + 'RadioStationName' => 'Nombre Emisora Radio', + 'RadioStationOwner' => 'Propietario Emisora Radio', + 'RasterPadding' => 'Relleno Trama', + 'RasterizedCaption' => 'Título Rasterizado', + 'Rating' => { + Description => 'Clasificación', + PrintConv => { + 'none' => 'Ninguno', + }, + }, + 'RatingPercent' => 'Valoración en Porcentaje', + 'RawCustomSaturation' => 'Raw Saturación personalizada', + 'RawDataUniqueID' => 'ID Único Dato Raw', + 'RawDevAutoGradation' => { + PrintConv => { + 'Off' => 'Desactivado', + 'On' => 'Activado', + }, + }, + 'RawDevNoiseReduction' => { + PrintConv => { + 'Noise Filter' => 'Filtro ruido', + 'Noise Filter (ISO Boost)' => 'Filtro ruido (ISO Boost)', + 'Noise Reduction' => 'Reducción ruido', + }, + }, + 'RawDevPMPictureTone' => { + PrintConv => { + 'Green' => 'Verde', + 'Neutral' => 'Neutro', + }, + }, + 'RawDevPM_BWFilter' => { + PrintConv => { + 'Green' => 'Verde', + 'Neutral' => 'Neutro', + 'Orange' => 'Naranja', + 'Red' => 'Rojo', + 'Yellow' => 'Amarillo', + }, + }, + 'RawDevPictureMode' => { + PrintConv => { + 'Vivid' => 'Vívido', + }, + }, + 'RawDevSettings' => { + PrintConv => { + 'Noise Reduction' => 'Reducción ruido', + }, + }, + 'RawImageDigest' => 'Cifrado Imagen RAW', + 'RawJpgSize' => { + PrintConv => { + 'Medium' => 'Medio', + 'Medium 1' => 'Medio 1 ', + 'Medium 2' => 'Medio 2', + 'Medium 3' => 'Medio 3', + 'Postcard' => 'Tarjeta Postal', + 'Small 1' => 'Pequeño 1', + 'Small 2' => 'Pequeño 21', + 'Small 3' => 'Pequeño 3', + }, + }, + 'RecordMode' => 'Modo de Grabación', + 'RecordShutterRelease' => { + Description => 'Soltar Obturador Grabación', + PrintConv => { + 'Press start, press stop' => 'Pulsa para iniciar, pulsa para parar', + 'Record while down' => 'Grabar mientras se pulsa', + }, + }, + 'RecordedTrackNumber' => 'Número Pista grabada', + 'RecordingMode' => { + PrintConv => { + 'Panorama' => 'Panoramica', + 'Portrait' => 'Retrato', + }, + }, + 'RedEyeCorrection' => { + PrintConv => { + 'Off' => 'Desactivado', + }, + }, + 'RedEyeReduction' => { + PrintConv => { + 'Off' => 'Desactivado', + 'On' => 'Activado', + }, + }, + 'RedMatrixColumn' => 'Columna Matriz Rojo', + 'RedTRC' => 'Curva Reproducción Tono Rojo', + 'ReductionMatrix1' => 'Matriz Reducción 1', + 'ReductionMatrix2' => 'Matriz Reducción 2', + 'ReferenceBlackWhite' => 'Par de Valores de Referencia Blanco y Negro', + 'ReferenceDate' => 'Fecha Referencia', + 'ReferenceNumber' => 'Número Referencia', + 'ReferenceService' => 'Servicio Referencia', + 'RelatedImageFileFormat' => 'Formato Archivo Imagen Relacionado', + 'RelatedImageHeight' => 'Alto Imagen Relacionada', + 'RelatedImageWidth' => 'Ancho Imagen Relacionada', + 'RelatedSoundFile' => 'Archivo Audio Relacionado', + 'ReleaseButtonToUseDial' => { + PrintConv => { + 'Yes' => 'Si', + }, + }, + 'ReleaseDate' => 'Fecha Lanzamiento', + 'ReleaseTime' => 'Hora Lanzamiento', + 'RenderingIntent' => { + Description => 'Intento Interpretación', + PrintConv => { + 'ICC-Absolute Colorimetric' => 'Colorimétrica Absoluta', + 'Media-Relative Colorimetric' => 'Colorimétrica Relativa', + 'Saturation' => 'Saturación', + }, + }, + 'RenditionOfMaskMarkers' => { + PrintConv => { + 'All' => 'Todo', + 'None' => 'Ninguno', + }, + }, + 'ResampleParamsQuality' => { + PrintConv => { + 'High' => 'Alto', + 'Low' => 'Bajo', + }, + }, + 'Resaved' => { + Description => 'Regrabado', + PrintConv => { + 'Yes' => 'Si', + }, + }, + 'Reserved1' => 'Reservado 1', + 'Resolution' => 'Resolución', + 'ResolutionMode' => 'Modo Resolución', + 'ResolutionUnit' => { + Description => 'Unidad de Resolución de X e Y', + PrintConv => { + 'None' => 'Ninguno', + 'cm' => 'Píxeles/cm', + 'inches' => 'Pulgada', + }, + }, + 'RetouchHistory' => { + PrintConv => { + 'None' => 'Ninguno', + }, + }, + 'RevisionNumber' => 'Número Revisión', + 'Rotation' => { + Description => 'Rotación', + PrintConv => { + 'Rotate 180' => 'Girado 180°', + 'Rotate 270 CW' => 'Girado 270° sentido reloj', + 'Rotate 90 CW' => 'Girado 90° sentido reloj', + 'Rotated 180' => 'Girado 180°', + 'Rotated 270 CW' => 'Girado 270° sentido reloj', + 'Rotated 90 CW' => 'Girado 90° sentido reloj', + }, + }, + 'RowInterleaveFactor' => 'Factor Interpolar Fila', + 'RowsPerStrip' => 'Número de Filas por Tira', + 'SMaxSampleValue' => 'Valor Muestra Max S', + 'SMinSampleValue' => 'Valor Muestra Min S', + 'SRAWQuality' => { + PrintConv => { + 'n/a' => 'No Aplica', + }, + }, + 'SRActive' => { + PrintConv => { + 'Yes' => 'Si', + }, + }, + 'SampleFormat' => 'Formato Muestra', + 'SampleRate' => 'Frecuencia muestreo', + 'SampleSize' => 'Tamaño muestra', + 'SampleStructure' => { + Description => 'Estructura Muestreo', + PrintConv => { + 'CompressionDependent' => 'Definido dentro del proceso de compresión', + 'Orthogonal4-2-2Sampling' => 'Ortogonal con las frecuencias de muestreo en el ratio de 4:2:2:(4)', + 'OrthogonalConstangSampling' => 'Ortogonal con la mismas frecuencias de muestreo relativo en cada componente', + }, + }, + 'SamplesPerPixel' => 'Número de Componentes', + 'SanyoQuality' => { + Description => 'Calidad Sanyo', + PrintConv => { + 'Fine/High' => 'Fino/Alto', + 'Fine/Low' => 'Fino/Bajo', + 'Fine/Medium' => 'Fino/Medio', + 'Fine/Medium High' => 'Fino/Medio Alto', + 'Fine/Medium Low' => 'Fino/Medio bajo', + 'Fine/Super High' => 'Fino/Super Alto', + 'Fine/Very High' => 'Fino/Muy Alto', + 'Fine/Very Low' => 'Fino/Muy bajo', + 'Normal/High' => 'Normal/Alto', + 'Normal/Low' => 'Normal/Bajo', + 'Normal/Medium' => 'Normal/Medio', + 'Normal/Medium High' => 'Normal/Medio Alto', + 'Normal/Medium Low' => 'Normal/Medio bajo', + 'Normal/Super High' => 'Normal/Super Alto', + 'Normal/Very High' => 'Normal/Muy Alto', + 'Normal/Very Low' => 'Normal/Muy bajo', + 'Super Fine/High' => 'Super Fino/Alto', + 'Super Fine/Low' => 'Super Fino/Bajo', + 'Super Fine/Medium' => 'Super Fino/Medio', + 'Super Fine/Medium High' => 'Super Fino/Medio Alto', + 'Super Fine/Medium Low' => 'Super Fino/Medio Bajo', + 'Super Fine/Super High' => 'Super Fino/Super Alto', + 'Super Fine/Very High' => 'Super Fino/Muy Alto', + 'Super Fine/Very Low' => 'Super Fino/Muy Bajo', + }, + }, + 'SanyoThumbnail' => 'Miniatura Sanyo', + 'Saturation' => { + Description => 'Saturación', + PrintConv => { + 'High' => 'Alto', + 'Low' => 'Bajo', + 'None' => 'Ninguno', + 'None (B&W)' => 'Ninguna (N&B)', + 'Normal' => 'Estándar', + 'Vivid' => 'Vívido', + }, + }, + 'ScanImageEnhancer' => { + PrintConv => { + 'Off' => 'Desactivado', + 'On' => 'Activado', + }, + }, + 'ScanningDirection' => { + Description => 'Dirección Escaneo', + PrintConv => { + 'Bottom-Top, L-R' => 'Abajo a arriba, izquierda a derecha', + 'Bottom-Top, R-L' => 'Abajo a arriba, derecha a izquierda', + 'L-R, Bottom-Top' => 'Izquierda a derecha, abajo a arriba', + 'L-R, Top-Bottom' => 'Izquierda a derecha, arriba a abajo', + 'R-L, Bottom-Top' => 'Derecha a izquierda, abajo a arriba', + 'R-L, Top-Bottom' => 'Derecha a izquierda, arriba a abajo', + 'Top-Bottom, L-R' => 'Arriba a abajo, izquierda a derecha', + 'Top-Bottom, R-L' => 'Arriba a abajo, derecha a izquierda', + }, + }, + 'Scene' => 'Escena', + 'SceneCaptureType' => { + Description => 'Tipo Captura Escena', + PrintConv => { + 'Landscape' => 'Paisaje', + 'Night' => 'Escena nocturna', + 'Portrait' => 'Retrato', + 'Standard' => 'Estándar', + }, + }, + 'SceneMode' => { + Description => 'Selección de escena', + PrintConv => { + '3D Sweep Panorama' => '3D', + 'Anti Motion Blur' => 'Anti movimiento', + 'Beach' => 'Playa', + 'Cont. Priority AE' => 'AE prioridad cont.', + 'Fireworks' => 'Fuegos Artificiales', + 'Food' => 'Comida', + 'Handheld Night Shot' => 'Toma noct. manual', + 'Indoor' => 'Interior', + 'Landscape' => 'Paisaje', + 'Night Portrait' => 'Retrato noct.', + 'Night Scene' => 'Vista nocturna', + 'Night View/Portrait' => 'Vista/retrato nocturno', + 'Off' => 'Desactivado', + 'Panorama' => 'Panoramica', + 'Portrait' => 'Retrato', + 'Snow' => 'Nieve', + 'Sports' => 'Acción deportiva', + 'Standard' => 'Estándar', + 'Sunset' => 'Puesta sol', + 'Sweep Panorama' => 'Barrido panorámico', + 'Underwater' => 'Subacuatica', + 'Vivid' => 'Vívido', + }, + }, + 'SceneModeUsed' => { + PrintConv => { + 'Beach' => 'Playa', + 'Fireworks' => 'Fuegos Artificiales', + 'Landscape' => 'Paisaje', + 'Panorama' => 'Panoramica', + 'Portrait' => 'Retrato', + 'Snow' => 'Nieve', + }, + }, + 'SceneSelect' => { + Description => 'Selección Escena', + PrintConv => { + 'Lamp' => 'Lámpara', + 'Night' => 'Noche', + 'Off' => 'Apagado', + 'Sport' => 'Deporte', + 'User 1' => 'Usuario 1', + 'User 2' => 'Usuario 2', + }, + }, + 'SceneType' => { + Description => 'Tipo Escena', + PrintConv => { + 'Directly photographed' => 'Imagen fotografiada directamente', + }, + }, + 'Security' => { + PrintConv => { + 'None' => 'Ninguno', + }, + }, + 'SecurityClassification' => { + Description => 'Clasificación Seguridad', + PrintConv => { + 'Confidential' => 'Confidencial', + 'Restricted' => 'Restringida', + 'Secret' => 'Secreta', + 'Top Secret' => 'Alto secreto', + 'Unclassified' => 'Sin clasificar', + }, + }, + 'SelectableAFPoint' => 'Punto AF seleccionable', + 'SelfTimer' => { + Description => 'Temporizador Automático', + PrintConv => { + 'Off' => 'Apagado', + 'On' => 'Encendido', + }, + }, + 'SelfTimerMode' => 'Modo Automático', + 'SensingMethod' => { + Description => 'Método Sensor', + PrintConv => { + 'Color sequential area' => 'Sensor de color secuencial', + 'Color sequential linear' => 'Sensor lineal de color secuencial', + 'Monochrome area' => 'Sensor monocromo', + 'Monochrome linear' => 'Sensor lineal monocromo', + 'Not defined' => 'No definido', + 'One-chip color area' => 'Sensor monochip de color', + 'Three-chip color area' => 'Sensor tres chips de color', + 'Trilinear' => 'Sensor trilineal', + 'Two-chip color area' => 'Sensor bichip de color', + }, + }, + 'SensitivityType' => { + PrintConv => { + 'Unknown' => 'Desconocido', + }, + }, + 'SequenceShotInterval' => { + Description => 'Intervalo Disparo Secuencial', + PrintConv => { + '10 frames/s' => '10 cuadros/s', + '15 frames/s' => '15 cuadros/s', + '20 frames/s' => '20 cuadros/s', + '5 frames/s' => '5 cuadros/s', + }, + }, + 'SequentialShot' => { + Description => 'Disparo Secuencial', + PrintConv => { + 'Adjust Exposure' => 'Ajustar Exposición', + 'Best' => 'Mejor', + 'None' => 'Ninguno', + 'Standard' => 'Estándar', + }, + }, + 'SerialNumber' => 'Número Serie', + 'ServiceIdentifier' => 'Identificador Servicio', + 'ShadingCompensation' => 'Compensación de Sombreado', + 'ShadingCompensation2' => { + PrintConv => { + 'Off' => 'Desactivado', + 'On' => 'Activado', + }, + }, + 'Shadow' => 'Sombrío', + 'ShadowScale' => 'Escala Sombrío', + 'ShakeReduction' => { + PrintConv => { + 'Off' => 'Desactivado', + 'On' => 'Activado', + }, + }, + 'Sharpening' => { + PrintConv => { + 'High' => 'Alto', + 'Low' => 'Bajo', + }, + }, + 'Sharpness' => { + Description => 'Nitidez', + PrintConv => { + 'Hard' => 'Fuerte', + 'Normal' => 'Estándar', + 'Sharp' => 'Nitido', + 'Soft' => 'Suave', + }, + }, + 'SharpnessFrequency' => { + PrintConv => { + 'High' => 'Alto', + 'Highest' => 'Muy Alto', + 'Low' => 'Bajo', + 'Lowest' => 'Mas bajo', + 'Standard' => 'Estándar', + 'n/a' => 'No Aplica', + }, + }, + 'ShootingMode' => { + Description => 'Modo de Disparo', + PrintConv => { + 'Beach' => 'Playa', + 'Fireworks' => 'Fuegos Artificiales', + 'Food' => 'Comida', + 'Portrait' => 'Retrato', + 'Snow' => 'Nieve', + 'Underwater' => 'Subacuatica', + }, + }, + 'ShortDocumentID' => 'ID Corta del Documento', + 'Shutter-AELock' => 'Disparador Bloqueo AE', + 'ShutterCount' => 'Contador de disparos', + 'ShutterReleaseButtonAE-L' => { + PrintConv => { + 'Off' => 'Desactivado', + 'On' => 'Activado', + }, + }, + 'ShutterReleaseNoCFCard' => { + PrintConv => { + 'Yes' => 'Si', + }, + }, + 'ShutterSpeed' => 'Tiempo de Exposición', + 'ShutterSpeedValue' => 'Velocidad Obturación', + 'Signature_Name' => 'Firma', + 'SimilarityIndex' => 'Índice de Similitudes', + 'SingleFrameBracketing' => { + PrintConv => { + 'High' => 'Alto', + 'Low' => 'Bajo', + }, + }, + 'Site' => 'Sitio', + 'SlideShow' => { + PrintConv => { + 'Yes' => 'Si', + }, + }, + 'SlowShutter' => { + PrintConv => { + 'None' => 'Ninguno', + 'Off' => 'Desactivado', + 'On' => 'Activado', + }, + }, + 'SoftSkinEffect' => { + PrintConv => { + 'Low' => 'Bajo', + }, + }, + 'Software' => 'Programa Utilizado', + 'SoftwareVersion' => 'Versión Software', + 'SonyImageSize' => { + PrintConv => { + 'Standard' => 'Estándar', + }, + }, + 'SonyQuality' => { + PrintConv => { + 'Standard' => 'Estándar', + }, + }, + 'Source' => 'Fuente', + 'SpatialFrequencyResponse' => 'Respuesta Frecuencia Espacial', + 'SpecialEffectsOpticalFilter' => { + PrintConv => { + 'None' => 'Ninguno', + }, + }, + 'SpecialInstructions' => 'Instrucciones', + 'SpecialMode' => 'Modo Especial', + 'SpectralSensitivity' => 'Sensibilidad Espectral', + 'Speed' => { + PrintConv => { + 'Fast' => 'Rápido', + }, + }, + 'SpotMeteringMode' => { + PrintConv => { + 'AF Point' => 'Punto AF', + 'Center' => 'Centro', + }, + }, + 'State' => 'Estado', + 'StreamColor' => { + PrintConv => { + 'Monochrome' => 'Monocromo', + }, + }, + 'StreamType' => { + PrintConv => { + 'Binary' => 'Binario', + 'File Transfer' => 'Transferencia Archivo', + }, + }, + 'StripByteCounts' => 'Bytes por Tira Comprimida', + 'StripOffsets' => 'Localización Datos Imagen', + 'Sub-location' => 'Localización', + 'SubSecTime' => 'Subsegundos DateTime', + 'SubSecTimeDigitized' => 'Subsegundos DateTimeDigitized', + 'SubSecTimeOriginal' => 'Subsegundos DateTimeOriginal', + 'SubTileBlockSize' => 'Tamaño Bloque Submosaico', + 'SubfileType' => 'Nuevo Tipo Subarchivo', + 'SubimageColor' => { + PrintConv => { + 'Monochrome' => 'Monocromo', + }, + }, + 'Subject' => 'Sujeto', + 'SubjectArea' => 'Zona Sujeto', + 'SubjectDistance' => 'Distancia Sujeto', + 'SubjectDistanceRange' => { + Description => 'Intervalo Distancia Sujeto', + PrintConv => { + 'Close' => 'Vista cercana', + 'Distant' => 'Vista alejada', + 'Unknown' => 'Desconocido', + }, + }, + 'SubjectLocation' => 'Localización Sujeto', + 'SubjectProgram' => { + PrintConv => { + 'None' => 'Ninguno', + 'Portrait' => 'Retrato', + }, + }, + 'SubjectReference' => 'Código Sujeto', + 'Subsystem' => { + PrintConv => { + 'Unknown' => 'Desconocido', + }, + }, + 'Subtitle' => 'Subtitulo', + 'SubtitleDescription' => 'Descripción Subtitulo', + 'SuperimposedDisplay' => { + PrintConv => { + 'Off' => 'Desactivado', + 'On' => 'Activado', + }, + }, + 'SupplementalCategories' => 'Categoría Suplementaria', + 'SupplementalType' => { + Description => 'Tipo Suplemento', + PrintConv => { + 'Main Image' => 'No Definido', + 'Rasterized Caption' => 'Título Rasterizado', + 'Reduced Resolution Image' => 'Imagen resolución reducida', + }, + }, + 'SweepPanoramaSize' => { + PrintConv => { + 'Standard' => 'Estándar', + }, + }, + 'SwitchToRegisteredAFPoint' => 'Conmutación de Punto AF registrado', + 'SynchronizedLyricsType' => { + PrintConv => { + 'Other' => 'Otro', + }, + }, + 'T4Options' => 'Opciones T4', + 'T6Options' => 'Opciones T6', + 'TIFF-EPStandardID' => 'ID Estándar TIFF/EP', + 'Tagged' => { + PrintConv => { + 'Yes' => 'Si', + }, + }, + 'TargetPrinter' => 'Impresora Objetivo', + 'Technology' => { + Description => 'Tecnología', + PrintConv => { + 'Active Matrix Display' => 'Pantalla Matriz Activa', + 'Cathode Ray Tube Display' => 'Pantalla Tubo Rayos Catódicos', + 'Digital Camera' => 'Cámara Digital', + 'Dye Sublimation Printer' => 'Impresora Sublimación', + 'Electrophotographic Printer' => 'Impresora Electrofotográfica (Laser)', + 'Electrostatic Printer' => 'Impresora Electrostática', + 'Film Scanner' => 'Escaner Película', + 'Film Writer' => 'Impresora Película', + 'Flexography' => 'Flexografía', + 'Gravure' => 'Grabado', + 'Ink Jet Printer' => 'Impresora Inyección Tinta', + 'Offset Lithography' => 'Litografía Offset', + 'Passive Matrix Display' => 'Pantalla Matriz Pasiva', + 'Photo Image Setter' => 'Marco Foto', + 'Photographic Paper Printer' => 'Impresora Papel Fotográfico', + 'Projection Television' => 'Televisión Proyección', + 'Reflective Scanner' => 'Escaner Reflectivo', + 'Silkscreen' => 'Pantalla Sedosa', + 'Thermal Wax Printer' => 'Impresora Cera Termal', + 'Video Camera' => 'Videocámara', + 'Video Monitor' => 'Monitor Video', + }, + }, + 'Teleconverter' => { + PrintConv => { + 'None' => 'Ninguno', + }, + }, + 'Text' => 'Texto', + 'TextStamp' => { + PrintConv => { + 'On' => 'Activado', + }, + }, + 'Thresholding' => 'Umbral', + 'ThumbnailImage' => 'Miniatura', + 'ThumbnailImageSize' => 'Tamaño de la Vista en Miniatura', + 'TileByteCounts' => 'Número Byte Elemento', + 'TileDepth' => 'Ancho Elemento', + 'TileLength' => 'Largo Elemento', + 'TileOffsets' => 'Offsets Elemento', + 'TileWidth' => 'Ancho Elemento', + 'TimeCreated' => 'Hora Creación', + 'TimeScaleParamsQuality' => { + PrintConv => { + 'High' => 'Alto', + 'Low' => 'Bajo', + }, + }, + 'TimeSent' => 'Hora Envío', + 'TimeSignature' => { + PrintConv => { + 'other' => 'Otro', + }, + }, + 'TimeStamp' => 'Marca de Tiempo', + 'TimeStamp1' => 'Marca de Tiempo 1', + 'TimeZoneOffset' => 'Offset Zona Horaria', + 'Title' => 'Título', + 'ToneCurve' => { + PrintConv => { + 'Standard' => 'Estándar', + }, + }, + 'ToneCurveActive' => { + PrintConv => { + 'Yes' => 'Si', + }, + }, + 'ToningEffect' => { + PrintConv => { + 'Green' => 'Verde', + 'None' => 'Ninguno', + 'Red' => 'Rojo', + 'Yellow' => 'Amarillo', + }, + }, + 'ToningEffectMonochrome' => { + PrintConv => { + 'Green' => 'Verde', + 'None' => 'Ninguno', + }, + }, + 'ToningEffectUnknown' => { + PrintConv => { + 'Green' => 'Verde', + 'None' => 'Ninguno', + }, + }, + 'ToningEffectUserDef1' => { + PrintConv => { + 'Green' => 'Verde', + 'None' => 'Ninguno', + }, + }, + 'ToningEffectUserDef2' => { + PrintConv => { + 'Green' => 'Verde', + 'None' => 'Ninguno', + }, + }, + 'ToningEffectUserDef3' => { + PrintConv => { + 'Green' => 'Verde', + 'None' => 'Ninguno', + }, + }, + 'ToolName' => 'Nombre Herramienta', + 'ToolVersion' => 'Versión Herramienta', + 'TotalFrames' => 'Total Imagenes', + 'Track' => 'Pista', + 'TrackCreateDate' => 'Fecha creación Track', + 'TrackDefault' => 'Pista Defecto', + 'TrackForced' => 'Pista Forzada', + 'TrackHeaderVersion' => 'Versión cabecera Pista', + 'TrackID' => 'ID Pista', + 'TrackName' => 'Nombre Pista', + 'TrackNumber' => 'Número Pista', + 'TrackType' => 'Tipo Pista', + 'TrackUsed' => 'Pista utilizada', + 'Tracks' => 'Pistas', + 'TransferFunction' => 'Función Transferencia', + 'TransferRange' => 'Intervalo Transferencia', + 'Transformation' => { + Description => 'Transformación', + PrintConv => { + 'Mirror horizontal' => 'Invertir horizontal', + 'Mirror horizontal and rotate 270 CW' => 'Invertir horizontal y rotar 270° sentido reloj', + 'Mirror horizontal and rotate 90 CW' => 'Invertir horizontal y rotar 90° sentido reloj', + 'Mirror vertical' => 'Invertir vertical', + 'Rotate 180' => 'Girado 180°', + 'Rotate 270 CW' => 'Girado 270° sentido reloj', + 'Rotate 90 CW' => 'Girado 90° sentido reloj', + }, + }, + 'TransmissionReference' => 'Referencia de Transmisión', + 'TransparencyIndicator' => 'Indicador Transparencia', + 'TrapIndicator' => 'Indicador Tampa', + 'Type' => 'Tipo', + 'Uncompressed' => { + Description => 'Sin Comprimir', + PrintConv => { + 'Yes' => 'Si', + }, + }, + 'UncompressedSize' => 'Tamaño Descomprimido', + 'UniqueCameraModel' => 'Modelo Cámara Unico', + 'UniqueDocumentID' => 'ID de Documento Única', + 'UniqueFileIdentifier' => 'Identificador Unico Archivo', + 'UniqueObjectName' => 'Nombre Único de Objeto', + 'Unknown' => 'Desconocido', + 'Unsharp1Color' => { + PrintConv => { + 'Green' => 'Verde', + 'Red' => 'Rojo', + 'Yellow' => 'Amarillo', + }, + }, + 'Unsharp2Color' => { + PrintConv => { + 'Green' => 'Verde', + 'Red' => 'Rojo', + 'Yellow' => 'Amarillo', + }, + }, + 'Unsharp3Color' => { + PrintConv => { + 'Green' => 'Verde', + 'Red' => 'Rojo', + 'Yellow' => 'Amarillo', + }, + }, + 'Unsharp4Color' => { + PrintConv => { + 'Green' => 'Verde', + 'Red' => 'Rojo', + 'Yellow' => 'Amarillo', + }, + }, + 'UnsharpMask' => { + PrintConv => { + 'Off' => 'Desactivado', + 'On' => 'Activado', + }, + }, + 'Urgency' => { + Description => 'Urgencia', + PrintConv => { + '0 (reserved)' => '0 (reservado para futuro uso)', + '1 (most urgent)' => '1 (más urgente)', + '5 (normal urgency)' => '5 (urgencia normal)', + '8 (least urgent)' => '8 (menos urgente)', + '9 (user-defined priority)' => '9 (reservado para futuro uso)', + }, + }, + 'UserComment' => 'Comentarios Usuario', + 'UserDef1PictureStyle' => { + PrintConv => { + 'Landscape' => 'Paisaje', + 'Monochrome' => 'Monocromo', + 'Neutral' => 'Neutro', + 'Portrait' => 'Retrato', + 'Standard' => 'Estándar', + }, + }, + 'UserDef2PictureStyle' => { + PrintConv => { + 'Landscape' => 'Paisaje', + 'Monochrome' => 'Monocromo', + 'Neutral' => 'Neutro', + 'Portrait' => 'Retrato', + 'Standard' => 'Estándar', + }, + }, + 'UserDef3PictureStyle' => { + PrintConv => { + 'Landscape' => 'Paisaje', + 'Monochrome' => 'Monocromo', + 'Neutral' => 'Neutro', + 'Portrait' => 'Retrato', + 'Standard' => 'Estándar', + }, + }, + 'VR_0x66' => { + PrintConv => { + 'Off' => 'Desactivado', + }, + }, + 'ValidAFPoints' => 'Puntos AF validos', + 'Version' => 'Versión PrintIM', + 'VersionYear' => 'Año versión', + 'VibrationReduction' => { + PrintConv => { + 'Off' => 'Desactivado', + 'On' => 'Activado', + }, + }, + 'VideoAlphaMode' => { + PrintConv => { + 'None' => 'Ninguno', + }, + }, + 'VideoCardGamma' => 'Tarjeta Video Gamma', + 'VideoCompressor' => 'Video Compresor', + 'VideoFieldOrder' => { + PrintConv => { + 'Lower' => 'Inferior', + 'Progressive' => 'Progresivo', + 'Upper' => 'Superior', + }, + }, + 'VideoHeight' => 'Altura Video', + 'VideoPixelDepth' => { + PrintConv => { + '16-bit integer' => 'Entero 16-bits', + '24-bit integer' => 'Entero 24-bits', + '32-bit float' => 'Flotante 32-bits', + '32-bit integer' => 'Entero 32-bits', + '8-bit integer' => 'Entero 8-bits', + 'Other' => 'Otro', + }, + }, + 'VideoQuality' => { + PrintConv => { + 'Low' => 'Bajo', + 'Standard' => 'Estándar', + }, + }, + 'VideoWidth' => 'Ancho Video', + 'ViewCompressionFactor' => 'Ver Factor de compresión', + 'ViewfinderWarning' => { + PrintConv => { + 'Off' => 'Desactivado', + 'On' => 'Activado', + }, + }, + 'ViewfinderWarnings' => { + PrintConv => { + 'Monochrome' => 'Monocromo', + }, + }, + 'ViewingCondDesc' => 'Descripción en Condiciones de Visión', + 'ViewingCondIlluminant' => 'Iluminación en Condiciones de Visión', + 'ViewingCondIlluminantType' => 'Tipo Iluminación en Condiciones de Visión', + 'ViewingCondSurround' => 'Entorno en Condiciones de Visión', + 'ViewingConditions' => 'Iluminación en Condiciones de Visión', + 'VignetteControl' => { + PrintConv => { + 'High' => 'Alto', + 'Low' => 'Bajo', + 'Off' => 'Desactivado', + 'On' => 'Activado', + }, + }, + 'VoiceMemo' => { + Description => 'Notas Voz', + PrintConv => { + 'Off' => 'Apagado', + 'On' => 'Encendido', + }, + }, + 'WBAdjLighting' => { + PrintConv => { + 'None' => 'Ninguno', + }, + }, + 'WBBracketMode' => { + PrintConv => { + 'Off' => 'Desactivado', + }, + }, + 'WBFineTuneActive' => { + PrintConv => { + 'Yes' => 'Si', + }, + }, + 'WCSProfiles' => 'Perfil Sistema Color Windows', + 'WhiteBalance' => { + Description => 'Balance de Blancos', + PrintConv => { + 'Auto' => 'Automático', + 'Black & White' => 'Monocromo', + 'Cloudy' => 'Nublado', + 'Color Temperature/Color Filter' => 'Temperatura de color / Filtro de color', + 'Cool White Fluorescent' => 'Fluorescente blanco frío', + 'Custom' => 'Personalizado', + 'Custom 1' => 'Personalizado 1', + 'Custom 2' => 'Personalizado 2', + 'Custom 3' => 'Personalizado 3', + 'Custom 4' => 'Personalizado 4', + 'Day White Fluorescent' => 'Fluorescente blanco de día', + 'Daylight' => 'Luz de día', + 'Daylight Fluorescent' => 'Fluorescente luz de día', + 'Fluorescent' => 'Flourescente', + 'Manual' => 'Equilibrio del blanco manual', + 'Manual Temperature (Kelvin)' => 'Temperatura Manual (Kelvin)', + 'Shade' => 'Sombrío', + 'Tungsten' => 'Tungsteno', + 'Underwater' => 'Subacuatica', + 'Unknown' => 'Desconocido', + 'Warm White Fluorescent' => 'Fluorescente blanco cálido', + 'White Fluorescent' => 'Fluorescente blanco', + }, + }, + 'WhiteBalanceAdj' => { + PrintConv => { + 'Off' => 'Desactivado', + 'On' => 'Activado', + }, + }, + 'WhiteBalanceBracketing' => { + PrintConv => { + 'High' => 'Alto', + 'Low' => 'Bajo', + }, + }, + 'WhiteLevel' => 'Nivel Blanco', + 'WhitePoint' => 'Cromaticidad Punto Blanco', + 'WideRange' => { + Description => 'Intervalo Extendido', + PrintConv => { + 'Off' => 'Apagado', + 'On' => 'Encendido', + }, + }, + 'WidthResolution' => 'Resolución Imagen Horizontal', + 'Writer' => 'Escritor', + 'Writer-Editor' => 'Título/Descripción Escritor', + 'X3FillLight' => 'Luz Relleno X3', + 'XClipPathUnits' => 'Unidades Camino Fragmento X', + 'XMP' => 'Metadatos XMP', + 'XPosition' => 'Posición X', + 'XResolution' => 'Resolución Imagen Horizontal', + 'YCbCrCoefficients' => 'Coeficientes de Matriz de Tranformación de Espacio de Color', + 'YCbCrPositioning' => { + Description => 'Posicionamiento Y y C', + PrintConv => { + 'Centered' => 'Centrado', + 'Co-sited' => 'Vecino', + }, + }, + 'YCbCrSubSampling' => 'Ratio Submuestreo de Y a C', + 'YClipPathUnits' => 'Unidades Camino Fragmento Y', + 'YPosition' => 'Posición Y', + 'YResolution' => 'Resolución Imagen Vertical', + 'Year' => 'Año', + 'YearCreated' => 'Año Creación', + 'ZipCompressedSize' => 'Zip Tamaño Comprimido', + 'ZipCompression' => { + Description => 'Compresión Zip', + PrintConv => { + 'None' => 'Ninguno', + 'Reduced with compression factor 1' => 'Reducido con factor de compresión 1', + 'Reduced with compression factor 2' => 'Reducido con factor de compresión 2', + 'Reduced with compression factor 3' => 'Reducido con factor de compresión 3', + 'Reduced with compression factor 4' => 'Reducido con factor de compresión 4', + }, + }, + 'ZipUncompressedSize' => 'Zip Tamaño Descomprimido', + 'ZoneMatching' => { + Description => 'Zone matching', + PrintConv => { + 'High Key' => 'Alto', + 'ISO Setting Used' => 'Desactivado', + 'Low Key' => 'Bajo', + }, + }, + 'ZoneMatchingMode' => { + PrintConv => { + 'Standard' => 'Estándar', + }, + }, + 'ZoneMatchingOn' => { + PrintConv => { + 'Off' => 'Desactivado', + 'On' => 'Activado', + }, + }, + 'ZoomPos' => 'Posición Zoom', +); + +1; # end + + +__END__ + +=head1 NAME + +Image::ExifTool::Lang::es.pm - ExifTool Spanish language translations + +=head1 DESCRIPTION + +This file is used by Image::ExifTool to generate localized tag descriptions +and values. + +=head1 AUTHOR + +Copyright 2003-2019, Phil Harvey (phil at owl.phy.queensu.ca) + +This library is free software; you can redistribute it and/or modify it +under the same terms as Perl itself. + +=head1 ACKNOWLEDGEMENTS + +Thanks to Jens Duttke, Santiago del BrE<iacute>o GonzE<aacute>lez and Emilio +Sancha for providing this translation. + +=head1 SEE ALSO + +L<Image::ExifTool(3pm)|Image::ExifTool>, +L<Image::ExifTool::TagInfoXML(3pm)|Image::ExifTool::TagInfoXML> + +=cut diff --git a/lib/Image/ExifTool/Lang/fi.pm b/lib/Image/ExifTool/Lang/fi.pm new file mode 100644 index 0000000..b1e3117 --- /dev/null +++ b/lib/Image/ExifTool/Lang/fi.pm @@ -0,0 +1,2854 @@ +#------------------------------------------------------------------------------ +# File: fi.pm +# +# Description: ExifTool Finnish language translations +# +# Notes: This file generated automatically by Image::ExifTool::TagInfoXML +#------------------------------------------------------------------------------ + +package Image::ExifTool::Lang::fi; + +use strict; +use vars qw($VERSION); + +$VERSION = '1.02'; + +%Image::ExifTool::Lang::fi::Translate = ( + 'AEAperture' => 'AE-aukko', + 'AEBBracketValue' => 'AEB-haarukointiarvo', + 'AEBXv' => 'AEB-valotuksen korjaus', + 'AEExposureTime' => 'AE-valotusaika', + 'AEInfo' => 'Automaattivalotustiedot', + 'AELock' => { + Description => 'AE-lukitus', + PrintConv => { + 'Off' => 'Pois', + 'On' => 'Päällä', + }, + }, + 'AELockButton' => 'AE-lukituspainike', + 'AEMeteringMode' => 'AE-valotuksen mittaustapa', + 'AEMeteringSegments' => 'AE-mittaussegmentit', + 'AEProgramMode' => 'AE-ohjelmatapa', + 'AESetting' => 'AE-asetus', + 'AEXv' => 'AE-valotuksen korjaus', + 'AF-CPrioritySelection' => 'AF-C -esivalinnat', + 'AF-OnForMB-D10' => 'AF-ON -painike (MB-D10)', + 'AF-SPrioritySelection' => 'AF-S -esivalinnat', + 'AFActivation' => 'AF-aktivointi', + 'AFAdjustment' => 'AF-säätö', + 'AFAperture' => 'AF-aukko', + 'AFArea' => 'AF-alue', + 'AFAreaHeight' => 'AF-alueen korkeus', + 'AFAreaIllumination' => 'AF-alueen valaisu', + 'AFAreaMode' => 'AF-aluetarkennus', + 'AFAreaModeSetting' => 'AF-aluemittaustavan asetus', + 'AFAreaWidth' => 'AF-alueen leveys', + 'AFAreas' => 'AF-alueet', + 'AFAssist' => 'AF-apu', + 'AFAssistLamp' => { + PrintConv => { + 'Disabled and Not Required' => 'Deaktivoitu eikä tarpeen', + 'Disabled but Required' => 'Deaktivoitu mutta tarpeen', + 'Enabled but Not Used' => 'Aktivoitu muttei käytetty', + 'Fired' => 'Lauennut', + }, + }, + 'AFDefocus' => 'AF-defokus (poikkeama polttopisteestä)', + 'AFFineTune' => 'AF-hienosäätö', + 'AFImageHeight' => 'AF-kuvan korkeus', + 'AFImageWidth' => 'AF-kuvan leveys', + 'AFInfo' => 'Automaattitarkennustiedot', + 'AFInfo2' => 'AF-tiedot', + 'AFInfo2Version' => 'AF-tietojen versio', + 'AFIntegrationTime' => 'AF-integrointiaika', + 'AFMode' => 'AF-muoto', + 'AFPoint' => { + Description => 'AF-piste', + PrintConv => { + 'Bottom Center' => 'Alhaalla keskellä', + 'Bottom Left' => 'Alavasemmalla', + 'Bottom Right' => 'Alaoikealla', + 'Center' => 'Keskellä', + 'Center Left' => 'Keskellä vasemmalla', + 'Center Right' => 'Keskellä oikealla', + 'Far Left/Right of Center' => 'Kaukana vasemmalla/keskioikealla', + 'Far Left/Right of Center/Bottom' => 'Kaukana vasemmalla/keskioikealla/alhaalla', + 'Near Left/Right of Center' => 'Hieman vasemmalla/keskioikealla', + 'Near Upper/Left' => 'Hieman ylhäällä/vasemmalla', + 'Top Center' => 'Ylhäällä keskellä', + 'Top Left' => 'Ylävasemmalla', + 'Top Near-left' => 'Hieman ylävasemmalla', + 'Top Near-right' => 'Hieman yläoikealla', + 'Top Right' => 'Yläoikealla', + 'Upper Left' => 'Ylävasemmalla', + 'Upper Right' => 'Yläoikealla', + }, + }, + 'AFPointIllumination' => 'AF -pistevalaisu', + 'AFPointMode' => 'AF-pistetapa', + 'AFPointSelected' => { + Description => 'Valittu AF-piste', + PrintConv => { + 'Auto' => 'Automaattinen', + 'Automatic Tracking AF' => 'Automaattiseuranta-AF', + 'Bottom' => 'Alas', + 'Center' => 'Keskelle', + 'Face Detect AF' => 'Kasvojentunnistus-AF', + 'Fixed Center' => 'Kiinteästi keskustaan', + 'Left' => 'Vasemmalle', + 'Lower-left' => 'Alavasemmalle', + 'Lower-right' => 'Alaoikealle', + 'Mid-left' => 'Keskivasemmalle', + 'Mid-right' => 'Keskioikealle', + 'Right' => 'Oikealle', + 'Top' => 'Ylös', + 'Upper-left' => 'Ylävasemmalle', + 'Upper-right' => 'Yläoikealle', + }, + }, + 'AFPointSelected2' => 'Valittu AF-piste 2', + 'AFPointSelection' => 'AF-pistevalinnat', + 'AFPoints' => 'AF-pisteet', + 'AFPointsInFocus' => { + Description => 'Tarkennuksen AF-pisteet', + PrintConv => { + 'Bottom-center' => 'Alakeski', + 'Bottom-left' => 'Alavasen', + 'Bottom-right' => 'Alaoikea', + 'Center' => 'Keski', + 'Fixed Center or Multiple' => 'Kiinteästi keskellä tai useita', + 'Left' => 'Vasen', + 'None' => 'Ei yhtään', + 'Right' => 'Oikea', + 'Top-center' => 'Yläkeski', + 'Top-left' => 'Yläoikea', + 'Top-right' => 'Yläoikea', + }, + }, + 'AFPointsSelected' => 'Valitut AF-pisteet', + 'AFPointsUsed' => 'Käytetyt AF-pisteet', + 'AFPredictor' => 'Ennakoiva AF', + 'AFResponse' => 'Käytetty AF', + 'AFResult' => 'AF-tulos', + 'AFSearch' => { + Description => 'AF-haku', + PrintConv => { + 'Not Ready' => 'Ei valmis', + 'Ready' => 'Valmis', + }, + }, + 'ARMIdentifier' => 'ARM-tunnistin', + 'ARMVersion' => 'ARM-versio', + 'AToB0' => 'A - B0', + 'AToB1' => 'A - B1', + 'AToB2' => 'A - B2', + 'AccessoryType' => 'Lisälaitetyyppi', + 'ActionAdvised' => { + Description => 'Suositettava toiminto', + PrintConv => { + 'Object Kill' => 'Objektin tuhonta', + 'Object Reference' => 'Objektiviite', + 'Object Replace' => 'Objektin korvaus', + 'Ojbect Append' => 'Objektiliitäntä', + }, + }, + 'ActiveArea' => 'Aktiivialue', + 'ActiveD-Lighting' => 'Aktiivinen D-Lighting', + 'ActiveD-LightingMode' => 'Aktivoitu D-Lighting-tapa', + 'AdjustmentMode' => 'Säätötapa', + 'AdvancedRaw' => 'Edistynyt RAW', + 'AdvancedSceneMode' => { + Description => 'Edistynyt näkymätapa', + PrintConv => { + 'Auto' => 'Automaattinen', + 'Creative' => 'Luova', + 'Indoor/Architecture/Objects/HDR B&W' => 'Sisällä/arkkitehtuuri/kohteet', + 'Normal' => 'Normaali', + 'Outdoor/Illuminations/Flower/HDR Art' => 'Ulkona/valaistukset/kukka', + }, + }, + 'AlphaByteCount' => 'Alfa-tavujen määrä', + 'AlphaChannelsNames' => 'Alfa-kanavien nimet', + 'AlphaDataDiscard' => { + Description => 'Alfa-data hylätty', + PrintConv => { + 'Flexbits Discarded' => 'FlexBits hylätty', + 'Full Resolution' => 'Täysi resoluutio', + 'HighPass Frequency Data Discarded' => 'Ylipäästötaajuusdata hylätty', + 'Highpass and LowPass Frequency Data Discarded' => 'Yli- ja alipäästötaajuusdata hylätty', + }, + }, + 'AlphaOffset' => 'Alfa-siirtymä', + 'AnalogBalance' => 'Analoginen tasapaino', + 'AntiAliasStrength' => 'Kameran anti-alias -suotimen suhteellinen vahvuus', + 'Aperture' => 'Aukko', + 'ApertureRingUse' => 'Himmenninrenkaan käyttö', + 'ApertureValue' => 'Aukkoarvo', + 'ApplicationRecordVersion' => 'Sovellustietueen versio', + 'ArtFilter' => 'Taidesuodin', + 'Artist' => 'Kuvan luonut henkilö', + 'AsShotICCProfile' => 'Kuin kuvatessa -ICC-profiili', + 'AsShotNeutral' => 'Kuin kuvatessa -neutraali', + 'AsShotPreProfileMatrix' => 'Kuin kuvatessa -pre-profiilimatriisi', + 'AsShotProfileName' => 'Kuin kuvatessa -profiilin nimi', + 'AsShotWhiteXY' => 'Kuin kuvatessa -valkoinen X-Y', + 'Audio' => { + Description => 'Ääni', + PrintConv => { + 'No' => 'Ei', + 'Yes' => 'Kyllä', + }, + }, + 'AudioDuration' => 'Audion kesto', + 'AudioOutcue' => 'Audion lopetus', + 'AudioSamplingRate' => 'Audion näytetaajuus', + 'AudioSamplingResolution' => 'Audion näyteresoluutio', + 'AudioType' => { + Description => 'Audiotyyppi', + PrintConv => { + 'Mono Actuality' => 'Aktuaalisuus (monoaudio (1 kanava))', + 'Mono Music' => 'Musiikki, itsensä välittämä (monoaudio (1 kanava))', + 'Mono Question and Answer Session' => 'Kysymys- ja vastausistunto (monoaudio (1 kanava))', + 'Mono Raw Sound' => 'Raakaääni (monoaudio (1 kanava))', + 'Mono Response to a Question' => 'Vastaus kysymykseen (monoaudio (1 kanava))', + 'Mono Scener' => 'Kohtaus (monoaudio (1 kanava))', + 'Mono Voicer' => 'Ihmisääni (monoaudio (1 kanava))', + 'Mono Wrap' => 'Pakkaus (monoaudio (1 kanava))', + 'Stereo Actuality' => 'Aktuaalisuus (stereoaudio (2 kanavaa))', + 'Stereo Music' => 'Musiikki, itsensä välittämä (stereomono (2 kanavaa))', + 'Stereo Question and Answer Session' => 'Kysymys- ja vastausistunto (stereoaudio (2 kanavaa))', + 'Stereo Raw Sound' => 'Raakaääni (stereoaudio (2 kanavaa))', + 'Stereo Response to a Question' => 'Vastaus kysymykseen (stereoaudio (2 kanavaa))', + 'Stereo Scener' => 'Kohtaus (stereoaudio (2 kanavaa))', + 'Stereo Voicer' => 'Ihmisääni (stereoaudio (2 kanavaa))', + 'Stereo Wrap' => 'Pakkaus (stereoaudio (2 kanavaa))', + 'Text Only' => 'Vain teksti (ei objektidataa)', + }, + }, + 'Author' => 'Tekijä', + 'AutoAperture' => 'Himmenninrengas A:ssa', + 'AutoBracket' => 'Automaattihaarukointi', + 'AutoBracketSet' => 'Haarukointisarja', + 'AutoBracketing' => { + Description => 'Automaattinen haarukointi', + PrintConv => { + 'No flash & flash' => 'Ei salamaa & Salama', + 'Off' => 'Pois', + 'On' => 'Päällä', + }, + }, + 'AutoDistortionControl' => 'Automaattinen vääristymäkorjaus', + 'AutoExposureBracketing' => 'Automaattinen valotuksen haarukointi', + 'AutoFP' => 'Automaattinen FP', + 'AutoFocus' => { + Description => 'Automaattitarkennus', + PrintConv => { + 'Off' => 'Pois', + 'On' => 'Päällä', + }, + }, + 'AutoISO' => { + Description => 'Automaatti-ISO', + PrintConv => { + 'Off' => 'Pois', + 'On' => 'Päällä', + }, + }, + 'AutoRedEye' => 'Automaattinen punasilmien esto', + 'AutoRotate' => 'Automaattinen kuvankierto', + 'AuxiliaryLens' => 'Lisälinssi', + 'AvApertureSetting' => 'Av-aukkoasetus', + 'BToA0' => 'B - A0', + 'BToA1' => 'B - A1', + 'BToA2' => 'B - A2', + 'BWMode' => { + Description => 'M/V-muoto', + PrintConv => { + 'Off' => 'Pois', + 'On' => 'Päällä', + }, + }, + 'BackgroundColor' => 'Taustaväri', + 'BackgroundColorIndicator' => 'Taustavärin ilmaisin', + 'BackgroundColorValue' => 'Taustavärin arvo', + 'BadFaxLines' => 'Huonot faksirivit', + 'BaseExposureCompensation' => 'Valotuksen perussäätö', + 'BaseISO' => 'Perus-ISO', + 'BaselineExposure' => 'Valotuksen perusta', + 'BaselineNoise' => 'Kohinan perusta', + 'BaselineSharpness' => 'Terävyyden perusta', + 'BatteryLevel' => 'Pariston varaus', + 'BatteryOrder' => 'Paristojärjestys', + 'BayerGreenSplit' => 'Bayer Green Split -suodin', + 'Beep' => 'Äänimerkki', + 'BestQualityScale' => 'Parhaan laadun asteikko', + 'BestShotMode' => { + Description => 'Parhaan kuvan tapa', + PrintConv => { + 'Off' => 'Pois', + }, + }, + 'BitDepth' => 'Bittisyvyys', + 'BitsPerComponent' => 'Bittejä per komponentti', + 'BitsPerExtendedRunLength' => 'Bittejä per jatkettu jakson pituus', + 'BitsPerPixel' => 'Bittejä per pikseli', + 'BitsPerRunLength' => 'Bittejä per jakson pituus', + 'BitsPerSample' => 'Bittejä per näyte', + 'BlackLevel' => 'Mustan taso', + 'BlackLevel2' => 'Mustan taso 2', + 'BlackLevelDeltaH' => 'Mustan tason Delta H', + 'BlackLevelDeltaV' => 'Mustan tason Delta V', + 'BlackLevelRepeatDim' => 'Mustan tason toiston dimensio', + 'BlackMaskBottomBorder' => 'Mustan maskin alareuna', + 'BlackMaskLeftBorder' => 'Mustan maskin vasen reuna', + 'BlackMaskRightBorder' => 'Mustan maskin oikea reuna', + 'BlackMaskTopBorder' => 'Mustan maskin yläreuna', + 'BlackPoint' => 'Musta piste', + 'BlueBalance' => 'Sinitasapaino', + 'BlueMatrixColumn' => 'Sinisen matriisin sarake', + 'BlueTRC' => 'Sinisen toonin toistokäyrä', + 'BlueX' => 'Sininen X', + 'BlueY' => 'Sininen Y', + 'BlurWarning' => { + Description => 'Tärinävaroitus', + PrintConv => { + 'Blur Warning' => 'Tärinävaroitus', + 'None' => 'Ei mitään', + }, + }, + 'BodyFirmwareVersion' => 'Rungon laiteohjelmistoversio', + 'BorderID' => 'Kehyksen ID', + 'BorderLocation' => 'Kehyksen sijainti', + 'BorderName' => 'Kehyksen nimi', + 'BorderType' => 'Kehyksen tyyppi', + 'BordersVersion' => 'Kehysten versio', + 'BracketMode' => 'Haarukointitapa', + 'BracketSequence' => 'Haarukointijärjestys', + 'BracketShotNumber' => 'Haarukoinnin otosnumero', + 'BracketStep' => 'Haarukointiväli', + 'BracketValue' => 'Haarukointiarvo', + 'Brightness' => 'Kirkkaus', + 'BrightnessData' => 'Kirkkausdata', + 'BrightnessValue' => 'Kirkkausarvo', + 'BulbDuration' => 'Aikavalotuksen kesto', + 'BurstMode' => { + Description => 'Sarjatapa', + PrintConv => { + 'Infinite' => 'Ääretön', + 'Off' => 'Pois', + 'On' => 'Matala/korkea laatu', + 'Unlimited' => 'Rajaton', + }, + }, + 'By-line' => 'Tekijä', + 'By-lineTitle' => 'Tekijän ammattinimike', + 'CCDScanMode' => { + Description => 'CCD-skannaustapa', + PrintConv => { + 'Interlaced' => 'Lomitettu', + 'Progressive' => 'Progressiivinen', + }, + }, + 'CFALayout' => { + Description => 'CFA-sommitelma', + PrintConv => { + 'Even columns offset down 1/2 row' => 'Horjahtanut sommitelma A: parilliset sarakkeet siirtyneet alas 1/2 riviä', + 'Even columns offset up 1/2 row' => 'Horjahtanut sommitelma B: parilliset sarakkeet osiirtyneet ylös 1/2 riviä', + 'Even rows offset left 1/2 column' => 'Horjahtanut sommitelma D: parilliset rivit siirtyneet vasemmalle 1/2 saraketta', + 'Even rows offset right 1/2 column' => 'Horjahtanut sommitelma C: parilliset rivit siirtyneet oikealle 1/2 saraketta', + 'Rectangular' => 'Suorakulmainen (tai neliömäinen) sommitelma', + }, + }, + 'CFAPattern' => 'CFA-kuvio', + 'CFAPattern2' => 'CFA-kuvio 2', + 'CFAPlaneColor' => 'CFA-tasoväri', + 'CFARepeatPatternDim' => 'Toistuvan CFA-kuvion laajuus', + 'CLModeShootingSpeed' => 'Hidas jatkuva kuvaus (CL)', + 'CMContrast' => 'CM:n kontrasti', + 'CMExposureCompensation' => 'CM:n valotuksen säätö', + 'CMHue' => 'CM:n sävy', + 'CMMFlags' => 'CMM-liput', + 'CMSaturation' => 'CM:n värikylläisyys', + 'CMSharpness' => 'CM:n terävyys', + 'CMWhiteBalance' => 'CM:n valkotasapaino', + 'CMWhiteBalanceComp' => 'CM:n valkotasapainon säätö', + 'CMWhiteBalanceGrayPoint' => 'CM:n valkotasapainon harmaapiste', + 'CMYKEquivalent' => 'CMYK-vastaava', + 'CPUFirmwareVersion' => 'CPU-laiteohjelmistoversio', + 'CalibrationDateTime' => 'Kalibroinnin päiväysaika', + 'CalibrationIlluminant1' => { + Description => 'Valaistuksen kalibrointi 1', + PrintConv => { + 'Unknown' => 'Tuntematon', + }, + }, + 'CalibrationIlluminant2' => { + Description => 'Valaistuksen kalibrointi 2', + PrintConv => { + 'Unknown' => 'Tuntematon', + }, + }, + 'CameraCalibration1' => 'Kameran kalibrointi 1', + 'CameraCalibration2' => 'Kameran kalibrointi 2', + 'CameraCalibrationSig' => 'Kameran kalibrointitunniste', + 'CameraID' => 'Kameran ID', + 'CameraISO' => 'Kamera-ISO', + 'CameraOwner' => 'Kameran omistaja', + 'CameraParameters' => 'Kameran parametrit', + 'CameraSerialNumber' => 'Kameran rungon nro', + 'CameraSettings' => 'Kameran asetukset', + 'CameraSettingsVersion' => 'Kamera-asetusten versio', + 'CameraTemperature' => 'Kameran lämpötila', + 'CameraType' => 'Kameratyyppi', + 'CameraType2' => 'Kameratyyppi 2', + 'CanonAFInfo' => 'AF-info', + 'CanonAFInfo2' => 'AF-info (2)', + 'CanonFileInfo' => 'Tiedostoinfo', + 'CanonFileLength' => 'Tiedoston pituus', + 'CanonFirmwareVersion' => 'Laiteohjelmiston versio', + 'CanonFlags' => 'Canon-liput', + 'CanonImageType' => 'Kuvatyyppi', + 'CanonModelID' => 'Mallin ID', + 'Caption-Abstract' => 'Seloste/Kuvaus', + 'CaptureConditionsPAR' => 'PAR-kuvausolosuhteet', + 'CaptureDeviceFID' => 'Kuvauslaitteen FID', + 'CasioImageSize' => 'Casion kuvakoko', + 'Category' => 'Kategoria', + 'CellLength' => 'Kennon pituus', + 'CellWidth' => 'Kennon leveys', + 'CenterAFArea' => 'Keskialueen AF', + 'CharTarget' => 'Kirjainmerkin kohde', + 'CharacterSet' => 'Merkistö', + 'ChromaBlurRadius' => 'Kromaattisen sumeuden säde', + 'ChromaticAdaptation' => 'Kromaattinen adaptaatio', + 'Chromaticity' => 'Kromaattisuus', + 'City' => 'Kaupunki', + 'ClassifyState' => 'Luokitustila', + 'CleanFaxData' => 'Poista faksidata', + 'ClipPath' => 'Leikepolku', + 'CodedCharacterSet' => 'Koodattu merkistö', + 'ColorAberrationControl' => 'Väripoikkeaman hallinta', + 'ColorAdjustment' => 'Värien säätö', + 'ColorAdjustmentMode' => { + Description => 'Värin säätötapa', + PrintConv => { + 'Off' => 'Pois', + 'On' => 'Päällä', + }, + }, + 'ColorBalance' => 'Väritasapaino', + 'ColorBalanceAdj' => 'Väritasapainon säätö', + 'ColorBalanceBlue' => 'Väritasapaino sininen', + 'ColorBalanceGreen' => 'Väritasapaino vihreä', + 'ColorBalanceRed' => 'Väritasapaino punainen', + 'ColorBoostData' => 'Väritehostusdata', + 'ColorBoostLevel' => 'Väritehostustaso', + 'ColorBoostType' => 'Väritehostustyyppi', + 'ColorBooster' => 'Väritehostus', + 'ColorCalibrationMatrix' => 'Värien kalibrointimatriisitaulukko', + 'ColorCharacterization' => 'Värin luonnehdinta', + 'ColorCompensationFilter' => 'Värikorjailusuodin', + 'ColorControl' => 'Värisäätö', + 'ColorEffect' => { + Description => 'Väriefekti', + PrintConv => { + 'Black & White' => 'Musta & Valkoinen', + 'Cool' => 'Viileä', + 'Off' => 'Pois', + 'Sepia' => 'Seepia', + 'Warm' => 'Lämmin', + }, + }, + 'ColorFilter' => { + Description => 'Värisuodin', + PrintConv => { + 'Off' => 'Pois', + }, + }, + 'ColorGain' => 'Värien vahvistus', + 'ColorHue' => 'Värisävy', + 'ColorInfo' => 'Väritiedot', + 'ColorMap' => 'Värikartta', + 'ColorMatrix' => 'Värimatriisi', + 'ColorMatrix1' => 'Värimatriisi 1', + 'ColorMatrix2' => 'Värimatriisi 2', + 'ColorMatrixNumber' => 'Värimatriisin numero', + 'ColorMode' => { + Description => 'Värimuoto', + PrintConv => { + 'Autumn Leaves' => 'Syksyn lehdet', + 'B & W' => 'M & V', + 'B&W' => 'M&V', + 'Black & White' => 'Heleät värit', + 'Chrome' => 'Kellastunut', + 'Clear' => 'Selkeä', + 'Deep' => 'Syvä', + 'Evening' => 'Ilta', + 'Landscape' => 'Maisema', + 'Light' => 'Valoisa', + 'Natural' => 'Luonnollinen', + 'Natural color' => 'Luonnonvalo', + 'Natural sRGB' => 'Luonnollinen sRGB', + 'Natural+ sRGB' => 'Luonnollinen+ sRGB', + 'Neutral' => 'Neutraali', + 'Night Portrait' => 'Yön muotokuva', + 'Night Scene' => 'Yönäkymä', + 'Night View' => 'Iltanäkymä', + 'Night View/Portrait' => 'Yönäkymä', + 'Normal' => 'Normaali', + 'Off' => 'Pois', + 'Portrait' => 'Muotokuva', + 'Sepia' => 'Seepia', + 'Solarization' => 'Solarisaatio', + 'Standard' => 'Vakio', + 'Sunset' => 'Auringonlasku', + 'Vivid' => 'Heleät värit', + 'Vivid color' => 'Heleä väri', + }, + }, + 'ColorMoireReduction' => 'Värimoareen vaimennus', + 'ColorPalette' => 'Väripaletti', + 'ColorProfile' => 'Väriprofiili', + 'ColorRepresentation' => 'Väriesitys', + 'ColorReproduction' => 'Värientoisto', + 'ColorResponseUnit' => 'Värin vasteyksikkö', + 'ColorSamplersResource' => 'Värinäytteenotinresurssit', + 'ColorSequence' => 'Värien esitys', + 'ColorSpace' => { + Description => 'Väriavaruus', + PrintConv => { + 'ICC Profile' => 'ICC-profiili', + 'Uncalibrated' => 'Kalibroimaton', + 'Wide Gamut RGB' => 'Laaja Gamut RVB', + }, + }, + 'ColorTable' => 'Väritaulukko', + 'ColorTemperature' => 'Värilämpötila', + 'ColorTone' => 'Värisävy', + 'ColorToneFaithful' => 'Kohdeuskollinen värisävy', + 'ColorToneLandscape' => 'Maisemakuvan värisävy', + 'ColorToneNeutral' => 'Neutraali värisävy', + 'ColorTonePortrait' => 'Muotokuvan värisävy', + 'ColorToneStandard' => 'Vakiovärisävy', + 'ColorType' => 'Värityyppi', + 'ColorantOrder' => 'Väriainejärjestys', + 'ColorantTable' => 'Väriainetaulukko', + 'ColorimetricReference' => 'Kolorimetrinen referenssi', + 'Comment' => 'Kommentti', + 'ComponentsConfiguration' => 'Kunkin komponentin tarkoitus', + 'CompressedBitsPerPixel' => 'Kuvan pakkausmuoto', + 'CompressedImageSize' => 'Pakatun kuvan koko', + 'Compression' => 'Pakkausskeema', + 'CompressionRatio' => 'Pakkaussuhde', + 'ConnectionSpaceIlluminant' => 'Yhteystilan valaistus', + 'ConsecutiveBadFaxLines' => 'Peräkkäiset huonot faksirivit', + 'Contact' => 'Kontakti', + 'ContentLocationCode' => 'Sisällön sijaintikoodi', + 'ContentLocationName' => 'Sisällön sijaintinimi', + 'ContinuousBracketing' => 'Jatkuva haarukointi', + 'Contrast' => { + Description => 'Kontrasti', + PrintConv => { + 'Film Simulation' => 'Filminsimulaatio', + 'High' => 'Korkea', + 'Low' => 'Matala', + 'Medium High' => 'Korkeahko', + 'Medium Low' => 'Matalahko', + 'Normal' => 'Vakio', + }, + }, + 'ContrastAdjustment' => 'Kontrastin säätö', + 'ContrastCurve' => 'Kontrastikäyrä', + 'ContrastFaithful' => 'Kohdeuskollinen kontrasti', + 'ContrastLandscape' => 'Maisemakuvan kontrasti', + 'ContrastMonochrome' => 'Yksivärikuvan kontrasti', + 'ContrastNeutral' => 'Neutraali kontrasti', + 'ContrastPortrait' => 'Muotokuvan kontrasti', + 'ContrastSetting' => 'Kontrastiasetus', + 'ContrastStandard' => 'Vakiokontrasti', + 'ControlMode' => 'Ohjaustapa', + 'ConversionLens' => { + Description => 'Objektiivilisäke', + PrintConv => { + 'Macro' => 'Makro', + 'Off' => 'Pois', + 'Telephoto' => 'Tele', + 'Wide' => 'Laajakulma', + }, + }, + 'Converter' => 'Konvertteri', + 'Copyright' => 'Profiilin copyright', + 'CopyrightFlag' => 'Copyright-lippu', + 'CopyrightNotice' => 'Tekijänoikeusilmoitus', + 'CoringFilter' => 'Ydinsuodin', + 'CoringValues' => 'Ydinsuodatusarvot', + 'Country-PrimaryLocationCode' => 'ISO-maakoodi', + 'Country-PrimaryLocationName' => 'Maa', + 'CreateDate' => 'Digitaalisen datan luonnin päiväys ja aika', + 'CreationDate' => 'Luontipäivä', + 'CreativeStyle' => { + Description => 'Luova tyyli', + PrintConv => { + 'Autumn Leaves' => 'Syksyn lehdet', + 'B&W' => 'M&V', + 'Clear' => 'Selkeä', + 'Deep' => 'Syvä', + 'Landscape' => 'Maisema', + 'Light' => 'Valoisa', + 'Neutral' => 'Neutraali', + 'Night View/Portrait' => 'Yönäkymä', + 'Portrait' => 'Muotokuva', + 'Sepia' => 'Seepia', + 'Standard' => 'Vakio', + 'Sunset' => 'Auringonlasku', + 'Vivid' => 'Heleät värit', + }, + }, + 'CreatorAddress' => 'Tekijä - Osoite', + 'CreatorCity' => 'Tekijä - Kaupunki', + 'CreatorCountry' => 'Tekijä - Maa', + 'CreatorPostalCode' => 'Tekijä - Postinumero', + 'CreatorRegion' => 'Tekijä - Valtio/Provinssi', + 'CreatorWorkEmail' => 'Tekijä - email(it)', + 'CreatorWorkTelephone' => 'Tekijä - Puhelinnumero(t)', + 'CreatorWorkURL' => 'Tekijä - Web-sivusto(t)', + 'Credit' => 'Tarjoaja', + 'CropBottom' => 'Rajaus alhaalta', + 'CropData' => 'Rajausdata', + 'CropLeft' => 'Rajaus vasemmalta', + 'CropOutputHeight' => 'Rajaustuloksen korkeus', + 'CropOutputPixels' => 'Rajaustulokset pikselit', + 'CropOutputResolution' => 'Rajaustuloksen resoluutio', + 'CropOutputScale' => 'Rajaustuloksen mittasuhteet', + 'CropOutputWidth' => 'Rajaustuloksen leveys', + 'CropRight' => 'Rajaus oikealta', + 'CropScaledResolution' => 'Rajauksen skaalausresoluutio', + 'CropSourceResolution' => 'Rajauslähteen resoluutio', + 'CropTop' => 'Rajaus ylhäältä', + 'CurrentICCProfile' => 'Nykyinen ICC-profiili', + 'CurrentPreProfileMatrix' => 'Nykyinen pre-profiilimatriisi', + 'Curves' => 'Käyrät', + 'Custom1' => 'Mukautus 1', + 'Custom2' => 'Mukautus 2', + 'Custom3' => 'Mukautus 3', + 'Custom4' => 'Mukautus 4', + 'CustomRendered' => { + Description => 'Mukautettu kuvankäsittely', + PrintConv => { + 'Custom' => 'Mukautettu käsittely', + 'Normal' => 'Normaali käsittely', + }, + }, + 'CustomSaturation' => 'Mukautettu värikylläisyys', + 'D-LightingHQColorBoost' => 'D-Lighting HQ -väritehostus', + 'D-LightingHQHighlight' => 'D-Lighting HQ -valoalue', + 'D-LightingHQSelected' => 'Valittu D-Lighting HQ', + 'D-LightingHQShadow' => 'D-Lighting HQ -varjoalue', + 'D-LightingHSAdjustment' => 'D-Lighting HS -säätö', + 'D-LightingHSColorBoost' => 'D-Lighting HS -väritehostus', + 'DECPosition' => 'DEC-sijainti', + 'DNGBackwardVersion' => 'Edellinen DNG-versio', + 'DNGVersion' => 'DNG-versio', + 'DSPFirmwareVersion' => 'DSP-laiteohjelmistoversio', + 'DataDump' => 'Datadumppi', + 'DataImprint' => 'Datan sisällytys', + 'DataType' => 'Mattaus', + 'Date' => 'Päiväys', + 'DateCreated' => 'Luontipäiväys', + 'DateImprint' => 'Päiväysleima', + 'DateSent' => 'Lähetyspäivä', + 'DateStampMode' => 'Päiväysleiman muoto', + 'DateTime' => 'Päiväysaika', + 'DateTimeOriginal' => 'Alkuperäisen datan luonnin päiväys ja aika', + 'DealerIDNumber' => 'Myyjän ID-numero', + 'DefaultCropOrigin' => 'Oletusrajauksen alkuperä', + 'DefaultCropSize' => 'Oletusrajauskoko', + 'DefaultScale' => 'Oletusasteikko', + 'DeletedImageCount' => 'Poistettujen kuvien määrä', + 'Description' => 'Deskriptio', + 'Destination' => 'Kohde', + 'DestinationCity' => 'Kohdepaikkakunta', + 'DestinationCityCode' => 'Kohdepaikkakoodi', + 'DestinationDST' => { + Description => 'Kohteen kesäaika (DST)', + PrintConv => { + 'No' => 'Ei', + 'Yes' => 'Kyllä', + }, + }, + 'DevelopmentDynamicRange' => 'Dynamiikka-alueen kehitys', + 'DeviceAttributes' => 'Laiteattribuutit', + 'DeviceManufacturer' => 'Laitteen valmistaja', + 'DeviceMfgDesc' => 'Laitteen valmistajan kuvaus', + 'DeviceModel' => 'Laitteen malli', + 'DeviceModelDesc' => 'Laitemallin kuvaus', + 'DeviceSettingDescription' => 'Laiteasetusten kuvaus', + 'DigitalCreationDate' => 'Digitalisointipäiväys', + 'DigitalCreationTime' => 'Digitalisointiaika', + 'DigitalDEEHighlightAdj' => 'Digitaalinen DEE -vaalean pään säätö', + 'DigitalDEEShadowAdj' => 'Digitaalinen DEE-varjonsäätö', + 'DigitalDEEThreshold' => 'Digitaalinen DEE-kynnys', + 'DigitalEffectsName' => 'Digitaalisten efektien nimi', + 'DigitalEffectsType' => 'Digitaalisten efektien tyyppi', + 'DigitalEffectsVersion' => 'Digitaalisten efektien versio', + 'DigitalGEM' => 'Digitaalinen GEM', + 'DigitalGain' => 'Digitaalinen vahvistus', + 'DigitalICE' => 'Digitaalinen ICE', + 'DigitalROC' => 'Digitaalinen ROC', + 'DigitalZoom' => 'Digitaalinen zoom', + 'DigitalZoomOn' => { + Description => 'Digitaalinen zoom', + PrintConv => { + 'Off' => 'Pois', + 'On' => 'Päällä', + }, + }, + 'DigitalZoomRatio' => 'Digitaalinen zoomaussuhde', + 'DirectoryIndex' => 'Kansioindeksi', + 'DirectoryNumber' => 'Kansion numero', + 'DisplayAperture' => 'Aukon näyttö', + 'DisplayedUnitsX' => 'Vaakaresoluution yksikkö', + 'DisplayedUnitsY' => 'Pystyresoluution yksikkö', + 'DistortionCorrection' => 'Vääristymäkorjaus', + 'DocumentHistory' => 'Dokumentin historia', + 'DocumentName' => 'Dokumentin nimi', + 'DocumentNotes' => 'Dokumentin huomautukset', + 'DotRange' => 'Pisteiden määrä', + 'DriveMode' => 'Kuvaustapa', + 'DriveMode2' => 'Kuvaustapa 2', + 'DustRemovalData' => 'Pölynpoistodata', + 'DynamicAFArea' => 'Dynaamisen alueen AF', + 'DynamicRange' => { + Description => 'Dynamiikka-alue', + PrintConv => { + 'Standard' => 'Vakio', + 'Wide' => 'Laaja', + }, + }, + 'DynamicRangeExpansion' => { + Description => 'Dynamiikka-alueen laajennus', + PrintConv => { + 'Off' => 'Pois', + 'On' => 'Päällä', + }, + }, + 'DynamicRangeOptimizer' => { + Description => 'Dynamiikka-alueen optimointi', + PrintConv => { + 'Advanced Auto' => 'Edistynyt automatiikka', + 'Advanced Lv1' => 'Edistynyt taso 1', + 'Advanced Lv2' => 'Edistynyt taso 2', + 'Advanced Lv3' => 'Edistynyt taso 3', + 'Advanced Lv4' => 'Edistynyt taso 4', + 'Advanced Lv5' => 'Edistynyt taso 5', + 'Off' => 'Pois', + 'Standard' => 'Vakio', + }, + }, + 'DynamicRangeSetting' => { + Description => 'Dynamiikka-alueen säätö', + PrintConv => { + 'Film Simulation' => 'Filminsimulaatio', + 'Standard (100%)' => 'Vakio (100%)', + 'Wide1 (230%)' => 'Laaja 1 (230%)', + 'Wide2 (400%)' => 'Laaja 2 (400%)', + }, + }, + 'E-DialInProgram' => 'Säätökiekko ohjelmassa', + 'EVStepInfo' => 'EV-askeltiedot', + 'EVStepSize' => 'EV-askeleen koko', + 'EVSteps' => 'EV-askeleet', + 'EasyExposureCompensation' => 'Valotuksen pikakorjaus', + 'EasyMode' => 'Helppo tapa', + 'EdgeNoiseReduction' => 'Reunakohinan vaimennus', + 'EditStatus' => 'Editoinnin tila', + 'EditTagArray' => 'Muokkaa tagiryhmää', + 'EditorialUpdate' => { + Description => 'Sisällön päivitys', + PrintConv => { + 'Additional language' => 'Lisäkielet', + }, + }, + 'EffectiveLV' => 'Tehollinen valoarvo (LV)', + 'EffectiveMaxAperture' => 'Suurin tehollinen aukko', + 'Encoder' => 'Kooderi', + 'EncodingProcess' => 'Koodausmetodi', + 'EndPoints' => 'Loppupisteet', + 'EnhanceDarkTones' => 'Tummien sävyjen parantelu', + 'Enhancement' => { + Description => 'Parantelu', + PrintConv => { + 'Blue' => 'Sininen', + 'Flesh Tones' => 'Lihanvärinen', + 'Green' => 'Vihreä', + 'Off' => 'Pois', + 'Red' => 'Punainen', + }, + }, + 'EnhancerValues' => 'Korjainarvot', + 'EnvelopeNumber' => 'Pakkauksen numero', + 'EnvelopePriority' => { + Description => 'Pakkauksen prioriteetti', + PrintConv => { + '0 (reserved)' => '0 (varattu tulevaan käyttöön)', + '1 (most urgent)' => '1 (hyvin kiireellinen)', + '5 (normal urgency)' => '5 (normaali kiireellisyys)', + '8 (least urgent)' => '8 (lievän kiireellinen)', + '9 (user-defined priority)' => '9 (käyttäjän määrittämä prioriteetti)', + }, + }, + 'EnvelopeRecordVersion' => 'Pakkaustietueen versio', + 'EpsonImageHeight' => 'Epson-kuvan korkeus', + 'EpsonImageWidth' => 'Epson-kuvan leveys', + 'EpsonSoftware' => 'Epson-ohjelmisto', + 'Equipment' => 'Välineistön IFD-osoitin', + 'EquipmentVersion' => 'Välineistöversio', + 'ExcursionTolerance' => { + Description => 'Toleranssin ekskursio', + PrintConv => { + 'Allowed' => 'Voi toteutua', + 'Not Allowed' => 'Ei sallittu (oletus)', + }, + }, + 'ExifCameraInfo' => 'Exif-kameratiedot', + 'ExifImageHeight' => 'Kuvan korkeus', + 'ExifImageWidth' => 'Kuvan leveys', + 'ExifVersion' => 'Exif-versio', + 'ExitPupilPosition' => 'Lähtöpupillin sijainti', + 'ExpandFilm' => 'Filmilaajennus', + 'ExpandFilterLens' => 'Suodinlinssilaajennus', + 'ExpandFlashLamp' => 'Salamavalolaajennus', + 'ExpandLens' => 'Objektiivilaajennus', + 'ExpandScanner' => 'Skannerilaajennus', + 'ExpandSoftware' => 'Ohjelmistolaajennus', + 'ExpirationDate' => 'Päättymispäiväys', + 'ExpirationTime' => 'Päättymisaika', + 'Exposure' => 'Valotus', + 'ExposureBracketStepSize' => 'Valotuksen haarukointiväli', + 'ExposureBracketValue' => 'Valotushaarukoinnin arvo', + 'ExposureCompensation' => 'Valotuksen korjaus', + 'ExposureDelayMode' => 'Valotuksen viivetila', + 'ExposureDifference' => 'Valotusero', + 'ExposureIndex' => 'Valotusindeksi', + 'ExposureMode' => { + Description => 'Valotustapa', + PrintConv => { + 'Aperture Priority' => 'Aukon esivalinta', + 'Aperture-priority AE' => 'Aukon esivalinta AE', + 'Auto' => 'Automaattinen', + 'Auto bracket' => 'Automaattihaarukointi', + 'Landscape' => 'Maisema', + 'Manual' => 'Manuaalinen', + 'Night Scene / Twilight' => 'Yönäkymä', + 'Program' => 'Ohjelma', + 'Program AE' => 'Ohjelma-AE', + 'Program-shift' => 'Ohjelma-siirto', + 'Shutter Priority' => 'Ajan esivalinta', + 'Shutter speed priority AE' => 'Ajan esivalinta AE', + 'n/a' => 'Ei asetettu', + }, + }, + 'ExposureProgram' => { + Description => 'Valotusohjelma', + PrintConv => { + 'Action (High speed)' => 'Toimintaohjelma (painotettu suljinnopeutta)', + 'Aperture-priority AE' => 'Aukon esivalinta', + 'Creative (Slow speed)' => 'Luova ohjelma (painotettu syväterävyyttä)', + 'Landscape' => 'Maisemamoodi (maisemakuviin terävällä taustalla)', + 'Manual' => 'Manuaalinen', + 'Not Defined' => 'Ei määritetty', + 'Portrait' => 'Muotokuvamoodi (lähikuviin epäterävällä taustalla)', + 'Program AE' => 'Normaali ohjelma', + 'Shutter speed priority AE' => 'Ajan esivalinta', + }, + }, + 'ExposureTime' => 'Valotusaika', + 'ExposureTime2' => 'Valotusaika 2', + 'ExposureWarning' => { + Description => 'Valotusvaroitus', + PrintConv => { + 'Bad exposure' => 'Valotusvirhe', + 'Good' => 'OK', + }, + }, + 'ExtendedWBDetect' => { + Description => 'Laajennettu valkotas. tunnistus', + PrintConv => { + 'Off' => 'Pois', + 'On' => 'Päällä', + }, + }, + 'Extender' => 'Konvertteri', + 'ExtenderFirmwareVersion' => 'Konvertterin laiteohjelmistoversio', + 'ExtenderModel' => 'Konvertterimalli', + 'ExtenderSerialNumber' => 'Konvertterin sarjanumero', + 'ExternalFlash' => 'Ulkoinen salama', + 'ExternalFlashAE1' => 'Ulkoinen salama AE 1?', + 'ExternalFlashAE1_0' => 'Ulkoinen salama AE 1 (0)?', + 'ExternalFlashAE2' => 'Ulkoinen salama AE 2?', + 'ExternalFlashAE2_0' => 'Ulkoinen salama AE 2 (0)?', + 'ExternalFlashBounce' => { + Description => 'Ulkoisen salaman heijastus', + PrintConv => { + 'Bounce or Off' => 'Heijastus tai pois', + 'Direct' => 'Suora', + 'No' => 'Ei', + 'Yes' => 'Kyllä', + }, + }, + 'ExternalFlashExposureComp' => 'Ulkoisen salaman valotuksen säätö', + 'ExternalFlashFlags' => 'Ulkoisen salaman liput', + 'ExternalFlashGuideNumber' => 'Ulkoisen salaman ohjeluku?', + 'ExternalFlashMode' => 'Ulkoisen salaman tapa', + 'ExternalFlashZoom' => 'Ulkoisen salaman zoom', + 'ExtraSamples' => 'Lisänäytteet', + 'FNumber' => 'Aukkoarvo', + 'Face1Position' => 'Kasvojen 1 sijainti', + 'Face2Position' => 'Kasvojen 2 sijainti', + 'Face3Position' => 'Kasvojen 3 sijainti', + 'Face4Position' => 'Kasvojen 4 sijainti', + 'Face5Position' => 'Kasvojen 5 sijainti', + 'Face6Position' => 'Kasvojen 6 sijainti', + 'Face7Position' => 'Kasvojen 7 sijainti', + 'Face8Position' => 'Kasvojen 8 sijainti', + 'Face9Position' => 'Kasvojen 9 sijainti', + 'FaceDetect' => 'Kasvojen tunnistus', + 'FacePositions' => 'Kasvojen sijainnit', + 'FacesDetected' => 'Tunnistetut kasvot', + 'FaxRecvParams' => 'Faxin vastaanottoparametrit', + 'FaxRecvTime' => 'Faxin vastaanottoaika', + 'FaxSubAddress' => 'Faxin alaosoite', + 'FileFormat' => 'Tiedostomuoto', + 'FileIndex' => 'Tiedostoindeksi', + 'FileInfo' => 'Tiedostoinfot', + 'FileInfoVersion' => 'Tiedostoinfojen versio', + 'FileNumber' => 'Tiedoston numero', + 'FileNumberMemory' => 'Tiedostonumeromuisti', + 'FileNumberSequence' => 'Tiedostojen numerojärjestys', + 'FileSize' => 'Tiedoston koko', + 'FileSource' => { + Description => 'Tiedoston lähde', + PrintConv => { + 'Digital Camera' => 'Digitaalikamera', + 'Film Scanner' => 'Filmiskanneri', + 'Reflection Print Scanner' => 'Heijastava skanneri', + }, + }, + 'FileType' => 'Tiedostotyyppi', + 'Filename' => 'Tiedostonimi', + 'FillOrder' => 'Täyttöjärjestys', + 'FilmCategory' => 'Filmiluokka', + 'FilmGencode' => 'Filmin gencode', + 'FilmMode' => { + Description => 'Filmitila', + PrintConv => { + 'Dynamic (B&W)' => 'Dynaaminen (M&V)', + 'Dynamic (color)' => 'Dynaaminen (väri)', + 'F0/Standard (PROVIA)' => 'F0/vakio', + 'F1/Studio Portrait' => 'F1/studiomuotokuva', + 'F1a/Studio Portrait Enhanced Saturation' => 'F1a/studiomuotokuva laajennettu värikylläisyys', + 'F1b/Studio Portrait Smooth Skin Tone (ASTIA)' => 'F1b/studiomuotokuva pehmeä ihonväri', + 'F1c/Studio Portrait Increased Sharpness' => 'F1c/studiomuotokuva lisätty terävyys', + 'F3/Studio Portrait Ex' => 'F3/studiomuotokuva Ex', + 'Nature (color)' => 'Luonnollinen (väri)', + 'Nostalgic' => 'Nostalginen väri', + 'Smooth (B&W)' => 'Pehmeä (M&V)', + 'Smooth (color)' => 'Pehmeä (väri)', + 'Standard (B&W)' => 'Vakio (M&V)', + 'Standard (color)' => 'Vakio (väri)', + 'Vibrant' => 'Eloisa väri', + }, + }, + 'FilmProductCode' => 'Filmin tuotekoodi', + 'FilmType' => 'Filmityyppi', + 'Filter' => 'Suodin', + 'FilterEffect' => 'Suodinefekti', + 'FilterEffectMonochrome' => 'Yksivärisuodintehoste', + 'Firmware' => 'Laiteohjelmisto', + 'FirmwareDate' => 'Laiteohjelmiston päiväys', + 'FirmwareID' => 'Laiteohjelmiston ID', + 'FirmwareRevision' => 'Laiteohjelmiston revisio', + 'FirmwareVersion' => 'Laiteohjelmiston versio', + 'FixtureIdentifier' => 'Ominaisuuden tunnistin', + 'Flash' => { + Description => 'Salama', + PrintConv => { + 'Auto, Did not fire' => 'Salama ei lauennut, automaattimoodi', + 'Auto, Did not fire, Red-eye reduction' => 'Automaattinen, salama ei lauennut, punasilmien esto', + 'Auto, Fired' => 'Salama lauennut, automaattimoodi', + 'Auto, Fired, Red-eye reduction' => 'Salama lauennut, automaattimoodi, punasilmien estomoodi', + 'Auto, Fired, Red-eye reduction, Return detected' => 'Salama lauennut, automaattimoodi, heijastusvalo havaittu, punasilmien estomoodi', + 'Auto, Fired, Red-eye reduction, Return not detected' => 'Salama lauennut, automaattimoodi, heijastusvaloa ei havaittu, punasilmien estomoodi', + 'Auto, Fired, Return detected' => 'Salama lauennut, automaattimoodi. heijastusvalo havaittu', + 'Auto, Fired, Return not detected' => 'Salama lauennut, automaattimoodi, heijastusvaloa ei havaittu', + 'Fired' => 'Salama lauennut', + 'Fired, Red-eye reduction' => 'Salama lauennut, punasilmien estomoodi', + 'Fired, Red-eye reduction, Return detected' => 'Salama lauennut, punasilmien estomoodi, heijastusvalo havaittu', + 'Fired, Red-eye reduction, Return not detected' => 'Salama lauennut, punasilmien estomoodi, heijastusvaloa ei havaittu', + 'Fired, Return detected' => 'Strobo-salaman heijastus havaittu', + 'Fired, Return not detected' => 'Strobo-salaman heijastusta ei havaittu', + 'No Flash' => 'Salama ei lauennut', + 'No flash function' => 'Ei salamatoimintoa', + 'Off, Did not fire' => 'Salama ei lauennut, pakkosalamatila', + 'Off, Did not fire, Return not detected' => 'Pois, salama ei lauennut, heijastusta ei havaittu', + 'Off, No flash function' => 'Pois, ei salamatoimintoa', + 'Off, Red-eye reduction' => 'Pois, punasilmien esto', + 'On, Did not fire' => 'Päällä, salama ei lauennut', + 'On, Fired' => 'Salama lauennut, pakkosalamatila', + 'On, Red-eye reduction' => 'Salama lauennut, pakkosalamatila, punasilmien estomoodi', + 'On, Red-eye reduction, Return detected' => 'Salama lauennut, pakkosalamatila, punasilmien estomoodi, heijastusvalo havaittu', + 'On, Red-eye reduction, Return not detected' => 'Salama lauennut, pakkosalamatila, punasilmien estomoodi, heijastusvaloa ei havaittu', + 'On, Return detected' => 'Salama lauennut, pakkosalamatila, heijastusvalo havaittu', + 'On, Return not detected' => 'Salama lauennut, pakkosalamatila, heijastusvaloa ei havaittu', + }, + }, + 'FlashActivity' => 'Salaman toiminta', + 'FlashBias' => 'Salaman muutos', + 'FlashChargeLevel' => 'Salaman varaustila', + 'FlashCompensation' => 'Salaman säätö', + 'FlashControlMode' => 'Salaman ohjaustapa', + 'FlashDevice' => 'Salamalaite', + 'FlashDistance' => 'Salamaetäisyys', + 'FlashEnergy' => 'Salaman teho', + 'FlashExposureBracketValue' => 'Salamavalotuksen haarukoinnin arvo', + 'FlashExposureComp' => 'Salaman kirkkauden säätö', + 'FlashFired' => { + Description => 'Salama lauennut', + PrintConv => { + 'No' => 'Ei', + 'Yes' => 'Kyllä', + }, + }, + 'FlashFirmwareVersion' => 'Salaman laiteohjelmistoversio', + 'FlashFocalLength' => 'Salaman polttoväli', + 'FlashGuideNumber' => 'Salaman ohjeluku', + 'FlashInfoVersion' => 'Salaman tietojen versio', + 'FlashIntensity' => { + Description => 'Salaman teho', + PrintConv => { + 'High' => 'Korkea', + 'Low' => 'Matala', + 'Normal' => 'Normaali', + 'Strong' => 'Voimakas', + 'Weak' => 'Heikko', + }, + }, + 'FlashMetering' => 'Salamamittaus', + 'FlashMeteringSegments' => 'Salaman mittaussegmentit', + 'FlashMode' => { + Description => 'Salamatapa', + PrintConv => { + 'Auto' => 'Automaattinen', + 'Did Not Fire' => 'Ei lauennut', + 'Disabled' => 'Deaktivoitu', + 'Fired, Commander Mode' => 'Lauennut, pakkotapa', + 'Fired, External' => 'Lauennut, ulkoinen', + 'Fired, Manual' => 'Lauennut, manuaalinen', + 'Fired, TTL Mode' => 'Lauennut, TTL-tapa', + 'Force' => 'Pakkotapa', + 'Not Ready' => 'Ei valmis', + 'Off' => 'Pois (3)', + 'On' => 'Päällä (2)', + 'Red eye' => 'Punasilmien esto', + }, + }, + 'FlashModel' => { + Description => 'Salaman malli', + PrintConv => { + 'None' => 'Ei mitään', + }, + }, + 'FlashOptions' => 'Salamavalinnat', + 'FlashOutput' => 'Salaman teho', + 'FlashRemoteControl' => 'Salaman kaukosäätö', + 'FlashSerialNumber' => 'Salaman sarjanumero', + 'FlashSetting' => 'Salaman asetus', + 'FlashShutterSpeed' => 'Suljinaika salamakuvauksessa', + 'FlashStatus' => 'Salaman tila', + 'FlashSyncSpeed' => 'Salaman täsmäysaika', + 'FlashType' => { + Description => 'Salamatyyppi', + PrintConv => { + 'E-System' => 'E-järjestelmä', + 'None' => 'Ei mitään', + 'Simple E-System' => 'Yksinkertainen E-järjestelmä', + }, + }, + 'FlashWarning' => 'Salamavaroitus', + 'FlashpixVersion' => 'Tuettu Flashpix-versio', + 'FlickerReduce' => { + Description => 'Värinän vaimennus', + PrintConv => { + 'Off' => 'Pois', + 'On' => 'Päällä', + }, + }, + 'FlipHorizontal' => 'Kiepautus vaakatasossa', + 'FocalLength' => 'Polttoväli', + 'FocalLengthIn35mmFormat' => 'Polttoväli 35 mm filmikoolla', + 'FocalPlaneDiagonal' => 'Polttopistetason lävistäjä', + 'FocalPlaneResolutionUnit' => { + Description => 'Polttopistetason resoluutioyksikkö', + PrintConv => { + 'None' => 'Ei mitään', + 'inches' => 'Tuuma', + 'um' => 'µm (mikrometri)', + }, + }, + 'FocalPlaneXResolution' => 'Polttopistetason vaakaresoluutio', + 'FocalPlaneXSize' => 'Polttopistetason leveys', + 'FocalPlaneYResolution' => 'Polttopistetason pystyresoluutio', + 'FocalPlaneYSize' => 'Polttopistetason korkeus', + 'FocalType' => 'Objektiivityyppi', + 'Focus' => 'Tarkennusesivalinta', + 'FocusArea' => 'Tarkennusalue', + 'FocusAreaSelection' => 'Tarkennusalueen valinta', + 'FocusContinuous' => 'Jatkuva tarkennus', + 'FocusDistanceLower' => 'Lähitarkennus', + 'FocusDistanceUpper' => 'Kaukotarkennus', + 'FocusMode' => { + Description => 'Tarkennustapa', + PrintConv => { + 'Auto' => 'Automaattinen', + 'Manual' => 'Manuaalinen', + }, + }, + 'FocusMode2' => 'Tarkennustapa', + 'FocusPixel' => 'Tarkennuspikseli', + 'FocusPosition' => 'Polttopisteen paikka', + 'FocusProcess' => 'Tarkennusprosessi', + 'FocusRange' => { + Description => 'Tarkennusalue', + PrintConv => { + 'Macro' => 'Makro', + 'Normal' => 'Normaali', + }, + }, + 'FocusSetting' => 'Tarkennusasetus', + 'FocusStepCount' => 'Tarkennusaskelmäärä', + 'FocusWarning' => { + Description => 'Tarkennusvaroitus', + PrintConv => { + 'Good' => 'OK', + 'Out of focus' => 'Epätarkka', + }, + }, + 'FolderName' => 'Kansion nimi', + 'ForwardMatrix1' => 'Eteenpäin-matriisi 1', + 'ForwardMatrix2' => 'Eteenpäin-matriisi 2', + 'FrameHeight' => 'Ruudun korkeus', + 'FrameNumber' => 'Ruudun numero', + 'FrameWidth' => 'Ruudun leveys', + 'FreeByteCounts' => 'Vapaiden tavujen määrät', + 'FreeMemoryCardImages' => 'Muistikortilla tilaa', + 'FreeOffsets' => 'Vapaat siirtymät', + 'FujiFlashMode' => { + Description => 'Salamatila', + PrintConv => { + 'External' => 'Ulkoinen salama', + 'Off' => 'Pois', + 'On' => 'Päällä', + 'Red-eye reduction' => 'Punasilmäisyyden vähennys', + }, + }, + 'GEMInfo' => 'GEM-tiedot', + 'GEModel' => 'Malli', + 'GIFVersion' => 'GIF-versio', + 'GPSAltitude' => 'Korkeus', + 'GPSAltitudeRef' => { + Description => 'Viitekorkeus', + PrintConv => { + 'Above Sea Level' => 'Merenpinnan korkeus', + 'Below Sea Level' => 'Merenpinnan viitekorkeus (negatiivinen arvo)', + }, + }, + 'GPSAreaInformation' => 'GPS-alueen nimi', + 'GPSDOP' => 'Mittaustarkkuus', + 'GPSDateStamp' => 'GPS-päiväys', + 'GPSDestBearing' => 'Kohteen suuntima', + 'GPSDestBearingRef' => { + Description => 'Kohteen suuntiman viite', + PrintConv => { + 'Magnetic North' => 'Magneettinen suunta', + 'True North' => 'Todellinen suunta', + }, + }, + 'GPSDestDistance' => 'Etäisyys kohteeseen', + 'GPSDestDistanceRef' => { + Description => 'Viite etäisyydelle kohteeseen', + PrintConv => { + 'Kilometers' => 'Kilometriä', + 'Miles' => 'Mailia', + 'Nautical Miles' => 'Solmua', + }, + }, + 'GPSDestLatitude' => 'Kohteen leveysaste', + 'GPSDestLatitudeRef' => { + Description => 'Kohteen leveysasteen viite', + PrintConv => { + 'North' => 'Pohjoista leveyttä', + 'South' => 'Eteläistä leveyttä', + }, + }, + 'GPSDestLongitude' => 'Kohteen pituusaste', + 'GPSDestLongitudeRef' => { + Description => 'Kohteen pituusasteen viite', + PrintConv => { + 'East' => 'Itäistä pituutta', + 'West' => 'Läntistä pituutta', + }, + }, + 'GPSDifferential' => { + Description => 'GPS-differentiaalikorjaus', + PrintConv => { + 'Differential Corrected' => 'Differentiaalikorjausta käytetty', + 'No Correction' => 'Mittaus ilman differentiaalikorjausta', + }, + }, + 'GPSImgDirection' => 'Kuvan´ suunta', + 'GPSImgDirectionRef' => { + Description => 'Kuvan suunnan viite', + PrintConv => { + 'Magnetic North' => 'Magneettinen suunta', + 'True North' => 'Todellinen suunta', + }, + }, + 'GPSLatitude' => 'Leveysaste', + 'GPSLatitudeRef' => { + Description => 'Pohjoista tai eteläistä leveyttä', + PrintConv => { + 'North' => 'Pohjoista leveyttä', + 'South' => 'Eteläistä leveyttä', + }, + }, + 'GPSLongitude' => 'Pituusaste', + 'GPSLongitudeRef' => { + Description => 'Itäistä tai läntistä pituutta', + PrintConv => { + 'East' => 'Itäistä pituutta', + 'West' => 'Läntistä pituutta', + }, + }, + 'GPSMapDatum' => 'Käytetty geodeettinen karttadata', + 'GPSMeasureMode' => { + Description => 'GPS-mittaustapa', + PrintConv => { + '2-Dimensional Measurement' => '2-ulotteinen mittaus', + '3-Dimensional Measurement' => '3-ulotteinen mittaus', + }, + }, + 'GPSProcessingMethod' => 'GPS-prosessointimetodin nimi', + 'GPSSatellites' => 'Mittaukseen käytetyt GPS-satelliitit', + 'GPSSpeed' => 'GPS-vastaanottimen nopeus', + 'GPSSpeedRef' => { + Description => 'Nopeusyksikkö', + PrintConv => { + 'km/h' => 'Kilometriä per tunti', + 'knots' => 'Solmua', + 'mph' => 'Mailia per tunti', + }, + }, + 'GPSStatus' => { + Description => 'GPS-vastaanottimen tila', + PrintConv => { + 'Measurement Active' => 'Mittaus aktiivinen', + 'Measurement Void' => 'Mittaus virheellinen', + }, + }, + 'GPSTimeStamp' => 'GPS-aika (atomikello)', + 'GPSTrack' => 'Liikkeen suunta', + 'GPSTrackRef' => { + Description => 'Liikkeen suunnan viite', + PrintConv => { + 'Magnetic North' => 'Magneettinen suunta', + 'True North' => 'Todellinen suunta', + }, + }, + 'GPSVersionID' => 'GPS-tagin versio', + 'GainBase' => 'Perusvahvistus', + 'GainControl' => { + Description => 'Herkkyyden säätö', + PrintConv => { + 'High gain down' => 'Suuri valoisuuden vähennys', + 'High gain up' => 'Suuri valoisuuden lisäys', + 'Low gain down' => 'Pieni valoisuuden vähennys', + 'Low gain up' => 'Pieni valoisuuden lisäys', + 'None' => 'Ei mitään', + }, + }, + 'GammaCompensatedValue' => 'Kompensoidun gamman arvo', + 'GeoTiffAsciiParams' => 'Geo-ASCII -parametrien tagi', + 'GeoTiffDirectory' => 'Geo-avain -hakemiston tagi', + 'GeoTiffDoubleParams' => 'Geo-kaksoisparametrien tagi', + 'Gradation' => 'Porrastus', + 'GrayPoint' => 'Harmaapiste', + 'GrayResponseCurve' => 'Harmaan vastekäyrä', + 'GrayResponseUnit' => { + Description => 'Harmaan vasteyksikkö', + PrintConv => { + '0.0001' => 'Numero edustaa yksikön tuhannesosia', + '0.001' => 'Numero edustaa yksikön sadasosia', + '0.1' => 'Numero edustaa yksikön kymmenyksiä', + '1e-05' => 'Numero edustaa yksikön kymmenestuhannesosia', + '1e-06' => 'Numero edustaa yksikön sadastuhannesosia', + }, + }, + 'GrayScale' => 'Harmaa-asteikko', + 'GrayTRC' => 'Harmaan toonin toistokäyrä', + 'GreenMatrixColumn' => 'Vihreän matriisin sarake', + 'GreenTRC' => 'Vihreän toonin toistokäyrä', + 'GreenX' => 'Vihreä X', + 'GreenY' => 'Vihreä Y', + 'GridDisplay' => 'Ristikko', + 'HCUsage' => 'HC-käyttö', + 'HalftoneHints' => 'Puolisävyviitteet', + 'Headline' => 'Otsikko', + 'HighISONoiseReduction' => { + Description => 'Korkean ISO-tason kohinan vaimennus', + PrintConv => { + 'High' => 'Korkea', + 'Low' => 'Matala', + 'Minimal' => 'Minimaalinen', + 'Normal' => 'Normaali', + 'Off' => 'Pois', + }, + }, + 'Highlight' => 'Valoalue', + 'HighlightData' => 'Valoalueen data', + 'HighlightProtection' => 'Valoalueen suojaus', + 'HometownCity' => 'Kotiseutu', + 'HometownCityCode' => 'Kotiseutukoodi', + 'HometownDST' => { + Description => 'Kotiseudun kesäaika (DST)', + PrintConv => { + 'No' => 'Ei', + 'Yes' => 'Kyllä', + }, + }, + 'HostComputer' => 'Isäntätietokone', + 'Hue' => 'Sävy', + 'HueAdjustment' => 'Värisävyn säätö', + 'HueSetting' => 'Sävyn asetus', + 'HuffmanTable' => 'Huffman-taulukko', + 'ICCProfile' => 'ICC-profiili', + 'ICC_Profile' => 'ICC-syötteen väriprofiili', + 'IPTC-NAA' => 'IPTC-NAA -metadata', + 'IPTCBitsPerSample' => 'Bittien määrä per näyte', + 'IPTCData' => 'IPTC-data', + 'IPTCDigest' => 'IPTC-yhteenveto', + 'IPTCImageHeight' => 'Viivojen määrä', + 'IPTCImageRotation' => { + Description => 'Kuvan kierto', + PrintConv => { + '0' => 'Ei kiertoa', + '180' => '180 asteen kierto', + '270' => '270 asteen kierto', + '90' => '90 asteen kierto', + }, + }, + 'IPTCImageWidth' => 'Pikseleitä per viiva', + 'IPTCPictureNumber' => 'Kuvan numero', + 'IPTCPixelHeight' => 'Pikselikoko suorassa kulmassa skannaussuuntaan', + 'IPTCPixelWidth' => 'Pikselikoko skannaussuunnassa', + 'ISO' => 'ISO-herkkyys', + 'ISOAuto' => 'Automaattinen ISO', + 'ISODisplay' => 'ISO-näyttö', + 'ISOExpansion' => 'ISO-laajennus', + 'ISOFloor' => 'ISO-alaraja', + 'ISOInfo' => 'ISO-tiedot', + 'ISOSelection' => 'ISO-valinta', + 'ISOSetting' => 'ISO-asetus', + 'ISOValue' => 'ISO-arvo', + 'IT8Header' => 'IT8-ylätunniste', + 'Illumination' => 'Näytön valaisu', + 'ImageAdjustment' => 'Kuvan säätö', + 'ImageAreaOffset' => 'Kuva-alueen siirtymä', + 'ImageAuthentication' => { + Description => 'Kuvan aitoustodennus', + PrintConv => { + 'Off' => 'Pois', + 'On' => 'Päällä', + }, + }, + 'ImageBoundary' => 'Kuvan rajat', + 'ImageByteCount' => 'Kuvan tavumäärä', + 'ImageColorIndicator' => 'Kuvan värin ilmaisin', + 'ImageColorValue' => 'Kuvan värin arvo', + 'ImageCount' => 'Kuvamäärä', + 'ImageData' => 'Kuvadata', + 'ImageDataDiscard' => { + Description => 'Kuvadatan hylkäys', + PrintConv => { + 'Flexbits Discarded' => 'FlexBits hylätty', + 'Full Resolution' => 'Täysi resoluutio', + 'HighPass Frequency Data Discarded' => 'Ylipäästötaajuusdata hylätty', + 'Highpass and LowPass Frequency Data Discarded' => 'Yli- ja alipäästötaajuusdata hylätty', + }, + }, + 'ImageDataSize' => 'Kuvadatan koko', + 'ImageDepth' => 'Kuvan syvyys', + 'ImageDescription' => 'Kuvan otsake', + 'ImageDustOff' => 'Kuvan pölynpoisto', + 'ImageEditCount' => 'Kuvan prosessointimäärä', + 'ImageHeight' => 'Kuvan korkeus', + 'ImageHistory' => 'Kuvahistoria', + 'ImageID' => 'Kuvan ID', + 'ImageInfo' => 'Kuvatiedot', + 'ImageLayer' => 'Kuvataso', + 'ImageNumber' => 'Tiedostonumero', + 'ImageOffset' => 'Kuvan siirtrymä', + 'ImageOptimization' => 'Kuvan optimointi', + 'ImageOrientation' => { + Description => 'Kuvan suunta', + PrintConv => { + 'Landscape' => 'Vaakakuva', + 'Portrait' => 'Pystykuva', + 'Square' => 'Neliömäinen', + }, + }, + 'ImagePrintStatus' => 'Kuvan tulostuksen tila', + 'ImageProcessing' => 'Kuvan prosessointi', + 'ImageProcessingVersion' => 'Kuvaprosessoinnin versio', + 'ImageQuality' => 'Kuvan laatu', + 'ImageQuality2' => 'Kuvan laatu 2', + 'ImageReview' => 'Kuvan tarkastelu', + 'ImageReviewTime' => 'Kuvan katseluaika', + 'ImageRotationStatus' => 'Kuvan kierron tila', + 'ImageSize' => 'Kuvakoko', + 'ImageSourceData' => 'Kuvan lähdedata', + 'ImageSourceEK' => 'EK-kuvalähde', + 'ImageStabilization' => { + Description => 'Kuvanvakautus', + PrintConv => { + 'Best Shot' => 'Paras kuva', + 'Off' => 'Pois', + 'On' => 'Päällä', + 'On, Mode 1' => 'Päällä, tapa 1', + 'On, Mode 2' => 'Päällä, tapa 2', + }, + }, + 'ImageTone' => { + Description => 'Kuvamuoto', + PrintConv => { + 'Bleach Bypass' => 'Bleach bypass -esivalotus', + 'Bright' => 'Kirkas', + 'Landscape' => 'Maisema', + 'Monochrome' => 'Yksivärinen', + 'Muted' => 'Vaimennettu', + 'Natural' => 'Luonnollinen', + 'Portrait' => 'Muotokuva', + 'Reversal Film' => 'Kääntöfilmi', + 'Vibrant' => 'Eloisa', + }, + }, + 'ImageType' => 'Sivu', + 'ImageUniqueID' => 'Kuvan uniikki ID', + 'ImageWidth' => 'Kuvan leveys', + 'Indexed' => 'Indeksoitu', + 'InkNames' => 'Musteiden nimet', + 'InkSet' => 'Mustesarja', + 'IntellectualGenre' => 'Intellektuaalinen genre', + 'IntelligentAuto' => 'Intelligentti automatiikka', + 'IntergraphMatrix' => 'Intergraph-matriisi -tagi', + 'Interlace' => 'Lomitus', + 'InternalFlash' => { + Description => 'Sisäinen salama', + PrintConv => { + 'Off' => 'Pois', + 'On' => 'Päällä', + }, + }, + 'InternalFlashAE1' => 'Sisäinen salama AE 1?', + 'InternalFlashAE1_0' => 'Sisäinen salama AE 1 (0)?', + 'InternalFlashAE2' => 'Sisäinen salama AE 2?', + 'InternalFlashAE2_0' => 'Sisäinen salama AE 2 (0)?', + 'InternalFlashMode' => 'Sisäisen salaman tapa', + 'InternalFlashStrength' => 'Sisäisen salaman teho', + 'InternalFlashTable' => 'Sisäisen salaman taulukko', + 'InternalSerialNumber' => 'Sisäinen sarjanumero', + 'InteropIndex' => { + Description => 'Interoperabiliteetin identifiointi', + PrintConv => { + 'R03 - DCF option file (Adobe RGB)' => 'R03: DCF-valintatiedosto (Adobe RGB)', + 'R98 - DCF basic file (sRGB)' => 'R98: DCF-perustiedosto (sRGB)', + 'THM - DCF thumbnail file' => 'THM: DCF-näytekuvatiedosto', + }, + }, + 'InteropVersion' => 'Interoperabiliteetin versio', + 'IntervalLength' => 'Ajastusvälin pituus', + 'IntervalMode' => 'Ajastettu kuvaustapa', + 'IntervalNumber' => 'Ajastuksen numero', + 'JFIFVersion' => 'JFIF-versio', + 'JPEGACTables' => 'JPEG:n AC-taulukot', + 'JPEGDCTables' => 'JPEG:n DC-taulukot', + 'JPEGLosslessPredictors' => 'JPEG:n häviöttömät prediktorit', + 'JPEGPointTransforms' => 'JPEG:n pistemuunnot', + 'JPEGProc' => 'JPEG-proc', + 'JPEGQTables' => 'JPEG:n Q-taulukot', + 'JPEGQuality' => { + Description => 'JPEG-laatu', + PrintConv => { + 'Extra Fine' => 'Erityishieno', + 'Fine' => 'Hieno', + 'Standard' => 'Normaali', + 'n/a' => 'Ei asetettu', + }, + }, + 'JPEGRestartInterval' => 'JPEG:n uudelleenaloitusväli', + 'JPEGTables' => 'JPEG-taulukot', + 'JobID' => 'Työn ID', + 'Keyword' => 'Avainsana', + 'Keywords' => 'Avainsana', + 'LCDIllumination' => 'LCD:n valaisu', + 'Language' => 'Kieli', + 'LanguageIdentifier' => 'Kielen tunnistin', + 'LastFileNumber' => 'Viimeinen tiedostonumero', + 'LeafData' => 'Leaf-data', + 'Lens' => 'Objektiivi', + 'LensApertureRange' => 'Objektiivin aukkoalue', + 'LensDataVersion' => 'Objektiividatan versio', + 'LensDistortionParams' => 'Linssivääristymän parametrit', + 'LensFStops' => 'Objektiivin aukkoarvot', + 'LensFirmwareVersion' => 'Objektiivin laiteohjelmistoversio', + 'LensID' => 'Objektiivin ID', + 'LensIDNumber' => 'Objektiivin ID-numero', + 'LensInfo' => 'Objektiivin tiedot', + 'LensSerialNumber' => 'Objektiivin sarjanumero', + 'LensTemperature' => 'Objektiivin lämpötila', + 'LensType' => 'Objektiivityyppi', + 'LightCondition' => 'Valaistusolot', + 'LightReading' => 'Valolukema', + 'LightSource' => { + Description => 'Valonlähde', + PrintConv => { + 'Cloudy' => 'Pilvinen', + 'Cool White Fluorescent' => 'Viileä valkoinen loistelamppu (W 3900 - 4500K)', + 'Day White Fluorescent' => 'Valkoinen päivänvaloloistelamppu (N 4600 - 5400K)', + 'Daylight' => 'Päivänvalo', + 'Daylight Fluorescent' => 'Päivänvaloloistelamppu (D 5700 - 7100K)', + 'Fine Weather' => 'Pilvetön', + 'Flash' => 'Salama', + 'Fluorescent' => 'Loistevalo', + 'ISO Studio Tungsten' => 'ISO studiokeinovalo (hehkulamppu)', + 'Other' => 'Muu valonlähde', + 'Shade' => 'Varjo', + 'Standard Light A' => 'Standardivalo A', + 'Standard Light B' => 'Standardivalo B', + 'Standard Light C' => 'Standardivalo C', + 'Tungsten (Incandescent)' => 'Keinovalo (hehkulamppu)', + 'Unknown' => 'Tuntematon', + 'White Fluorescent' => 'Lämmin valkoinen loistelamppu (WW 3200 - 3700K)', + }, + }, + 'LightSourceSpecial' => { + Description => 'Erikoisvalonlähde', + PrintConv => { + 'Off' => 'Pois', + 'On' => 'Päällä', + }, + }, + 'LinearResponseLimit' => 'Lineaarisen vasteen raja', + 'LinearizationTable' => 'Linearisaatiotaulukko', + 'LiveViewAF' => 'Suoranäyttö-AF', + 'LocalizedCameraModel' => 'Lokalisoitu kameramalli', + 'Location' => 'Sijainti', + 'LongExposureNoiseReduction' => { + Description => 'Pitkien valotusten kohinan vaimennus', + PrintConv => { + 'Off' => 'Pois', + 'On' => 'Päällä', + 'n/a' => 'Ei asetettu', + }, + }, + 'LookupTable' => 'Hakutaulukko', + 'Luminance' => 'Luminanssi', + 'MB-D10BatteryType' => 'MB-D10 -paristotyyppi', + 'MB-D80Batteries' => 'MB-D80 -paristot', + 'MCUVersion' => 'MCU-versio', + 'Macro' => { + Description => 'Makro', + PrintConv => { + 'Off' => 'Pois', + 'On' => 'Päällä', + 'n/a' => 'Ei asetettu', + }, + }, + 'MacroMode' => { + Description => 'Makrotapa', + PrintConv => { + 'Off' => 'Pois', + 'On' => 'Päällä', + 'Super Macro' => 'Supermakro', + 'Tele-Macro' => 'Telemakro', + }, + }, + 'Magnification' => 'Suurennus', + 'Make' => 'Valmistaja', + 'MakeAndModel' => 'Valmistaja ja malli', + 'MakerNote' => 'DNG-erityistiedot', + 'MakerNoteOffset' => 'Valmistajatietojen siirtymä', + 'MakerNoteSafety' => { + Description => 'Valmistatietojen turvallisuus', + PrintConv => { + 'Safe' => 'Turvallinen', + 'Unsafe' => 'Turvaton', + }, + }, + 'MakerNoteType' => 'Valmistajatietojen tyyppi', + 'MakerNoteVersion' => 'Valmistajatietojen versio', + 'ManometerPressure' => 'Manometrin ilmaisema paine', + 'ManualFlash' => 'Manuaalinen salama', + 'ManualFlashOutput' => 'Salaman käsisäätö', + 'ManualFocusDistance' => 'Manuaalinen etäisyydensäätö', + 'ManufactureDate' => 'Valmistuspäiväys', + 'MaskedAreas' => 'Maskilliset alueet', + 'MasterDocumentID' => 'Alkuperäisdokumentin ID', + 'MasterGain' => 'Yleisvahvistus', + 'Matteing' => 'Mattaus', + 'MaxAperture' => 'Suurin aukko', + 'MaxApertureAtCurrentFocal' => 'Suurin aukko nykyisellä polttovälillä', + 'MaxApertureAtMaxFocal' => 'Suurin aukko pisimmällä polttovälillä', + 'MaxApertureAtMinFocal' => 'Suurin aukko lyhimmällä polttovälillä', + 'MaxApertureValue' => 'Objektiivin maksimiaukko', + 'MaxFocalLength' => 'Pisin polttoväli', + 'MaxSampleValue' => 'Näytteen maksimiarvo', + 'MaximumDensityRange' => 'Tiheyden maksimilaajuus', + 'MeasuredEV' => 'Mitattu EV', + 'MeasurementBacking' => 'Mittaustuenta', + 'MeasurementFlare' => 'Hajavalomittaus', + 'MeasurementGeometry' => 'Mittausgeometria', + 'MeasurementIlluminant' => 'Valaistusmittaus', + 'MeasurementObserver' => 'Mittauksen tarkkailija', + 'MediaBlackPoint' => 'Median musta piste', + 'MediaWhitePoint' => 'Median valkoinen piste', + 'Medium' => 'Keskikokoa', + 'MetadataNumber' => 'Metadatan määrä', + 'Metering' => 'Valonmittaus', + 'MeteringMode' => { + Description => 'Valonmittaustapa', + PrintConv => { + 'Average' => 'Keskiarvo', + 'Center-weighted average' => 'Keskustapainotteinen keskiarvo', + 'Multi-segment' => 'Monisegmenttimittaus', + 'Multi-spot' => 'Monipiste', + 'Other' => 'Muu', + 'Partial' => 'Osa-alue', + 'Pattern+AF' => 'Kuvio + AF', + 'Spot' => 'Pistemittaus', + 'Spot+Highlight control' => 'Pistemittaus + valoalueen säätö', + 'Spot+Shadow control' => 'Pistemittaus + varjoalueen säätö', + 'Unknown' => 'Tuntematon', + }, + }, + 'MeteringTime' => 'Mittausaika', + 'MinAperture' => 'Pienin aukko', + 'MinFocalLength' => 'Lyhin polttoväli', + 'MinSampleValue' => 'Näytteen minimiarvo', + 'MinoltaCameraSettings2' => 'Kameran asetukset 2', + 'MinoltaCameraSettings5D' => 'Kameran asetukset (5D)', + 'MinoltaCameraSettings7D' => 'Kamera-asetukset (7D)', + 'MinoltaMakerNote' => 'Minolta-valmistajatiedot', + 'MinoltaQuality' => { + Description => 'Kuvakoko', + PrintConv => { + 'Economy' => 'Taloudellinen', + 'Extra fine' => 'Erityishieno', + 'Fine' => 'Hieno', + 'Standard' => 'Normaali', + 'Super Fine' => 'Superhieno', + }, + }, + 'Model' => 'Malli', + 'Model2' => 'Kuvasyötelaitteen malli (2)', + 'ModelAndVersion' => 'Malli ja versio', + 'ModelTiePoint' => 'Sidospistemalli-tagi', + 'ModelTransform' => 'Muuntomalli-tagi', + 'ModelingFlash' => 'Mallinnussalama', + 'ModifiedDigitalGain' => 'Modifioitu digitaalinen vahvistus', + 'ModifiedInfo' => 'Modifioidut tiedot', + 'ModifiedParamFlag' => 'Modifioitu parametrilippu', + 'ModifiedPictureStyle' => 'Modifioitu kuvan tyyli', + 'ModifiedSaturation' => { + Description => 'Modifoitu värikylläisyys', + PrintConv => { + 'CM1 (Red Enhance)' => 'CM1 (punaisen parantelu)', + 'CM2 (Green Enhance)' => 'CM2 (vihreän parantelu)', + 'CM3 (Blue Enhance)' => 'CM3 (sinisen parantelu)', + 'CM4 (Skin Tones)' => 'CM4 (ihonvärin parantelu)', + 'Off' => 'Pois', + }, + }, + 'ModifiedSensorBlueLevel' => 'Modifioitu anturin sinitaso', + 'ModifiedSensorRedLevel' => 'Modifioitu anturin punataso', + 'ModifiedSharpness' => 'Modifioitu terävyys', + 'ModifiedToneCurve' => 'Modifioitu sävykäyrä', + 'ModifiedWhiteBalance' => 'Modifioitu valkotasapaino', + 'ModifiedWhiteBalanceBlue' => 'Modifioitu valkotasapainon sininen', + 'ModifiedWhiteBalanceRed' => 'Modifioitu valkotasapainon punainen', + 'ModifyDate' => 'Tiedostomuutoksen päiväys ja aika', + 'MultiExposure' => 'Monivalotusdata', + 'MultiExposureAutoGain' => 'Monivalotuksen automaattivalotus', + 'MultiExposureMode' => 'Monivalotustapa', + 'MultiExposureShots' => 'Monivalotusotoksia', + 'MultiExposureVersion' => 'Monivalotusdatan versio', + 'MultiSample' => 'Moninäyte', + 'MultiSelector' => 'Monivalitsin', + 'MultipleExposureSet' => 'Monivalotus', + 'MyColorMode' => 'Oma värimuoto', + 'NDFilter' => 'ND-suodin', + 'NEFLinearizationTable' => 'Linearisaatiotaulukko', + 'NamedColor2' => 'Nimetty väri 2', + 'NativeDisplayInfo' => 'Paikallisen näytön tiedot', + 'NativeResolutionUnit' => 'Paikallisen resoluution yksikkö', + 'NativeXResolution' => 'Paikallinen vaakaresoluutio', + 'NativeYResolution' => 'Paikallinen pystyresoluutio', + 'NikonCaptureData' => 'Nikon Capture -data', + 'NikonCaptureOffsets' => 'Nikon Capture -siirtymät', + 'NikonCaptureOutput' => 'Nikon Capture -tuotos', + 'NikonCaptureVersion' => 'Nikon Capture -versio', + 'NikonICCProfile' => 'Nikon ICC-profiilin osoitin', + 'NoMemoryCard' => 'Ei muistikorttia', + 'Noise' => 'Kohina', + 'NoiseFilter' => 'Kohinasuodin', + 'NoiseReduction' => { + Description => 'Kohinan vähennys', + PrintConv => { + 'High (+1)' => '+1 (korkea)', + 'Highest (+2)' => '+2 (korkein)', + 'Low' => 'Matala', + 'Low (-1)' => '-1 (matala)', + 'Lowest (-2)' => '-2 (matalin)', + 'Normal' => 'Vakio', + 'Off' => 'Pois', + 'On' => 'Päällä', + 'Standard' => '±0 (vakio)', + }, + }, + 'NoiseReductionApplied' => 'Suoritettu kohinan vähennys', + 'NoiseReductionData' => 'Kohinanvaimennusdata', + 'NoiseReductionIntensity' => 'Kohinanvaimennuksen voimakkuus', + 'NoiseReductionMethod' => 'Kohinanvaimennusmetodi', + 'NoiseReductionSharpness' => 'Kohinanvaimennuksen terävyys', + 'NumIndexEntries' => 'Indeksimerkintöjen määrä', + 'NumberOfChannels' => 'Kanavien määrä', + 'NumberofInks' => 'Musteiden numerot', + 'OPIProxy' => 'OPI-välipalvelin', + 'ObjectAttributeReference' => 'Intellektuaalinen genre', + 'ObjectCycle' => { + Description => 'Objektin sykli', + PrintConv => { + 'Both Morning and Evening' => 'Molempina', + 'Evening' => 'Iltaisin', + 'Morning' => 'Aamuisin', + }, + }, + 'ObjectDistance' => 'Kohteen etäisyys', + 'ObjectName' => 'Nimike', + 'ObjectPreviewData' => 'Objektidatan esikatseludata', + 'ObjectPreviewFileFormat' => 'Objektidatan esikatselun tiedostomuoto', + 'ObjectPreviewFileVersion' => 'Objektidatan esikatselun tiedostomuodon versio', + 'ObjectTypeReference' => 'Objektyypin viiteryhmä', + 'OffsetSchema' => 'Siirtymäskeema', + 'OlympusImageHeight' => 'Kuvan korkeus', + 'OlympusImageWidth' => 'Kuvan leveys', + 'OneTouchWB' => { + Description => 'Pikavalkotasapaino', + PrintConv => { + 'Off' => 'Pois', + 'On' => 'Päällä', + 'On (Preset)' => 'Päällä (esiasetus)', + }, + }, + 'OpticalZoomCode' => 'Optisen zoomin koodi', + 'OpticalZoomMode' => { + Description => 'Optinen zoomaustapa', + PrintConv => { + 'Extended' => 'Laajennettu', + 'Standard' => 'Vakio', + }, + }, + 'OpticalZoomOn' => { + Description => 'Optinen zoom', + PrintConv => { + 'Off' => 'Pois', + 'On' => 'Päällä', + }, + }, + 'Opto-ElectricConvFactor' => 'Optoelektrinen muuntokerroin', + 'OrderNumber' => 'Valokuva-CD:n ostotilausnumero', + 'Orientation' => { + Description => 'Kuvan suunta', + PrintConv => { + 'Horizontal (normal)' => '0° (ylä/vasen)', + 'Mirror horizontal' => '0° (ylä/oikea)', + 'Mirror horizontal and rotate 270 CW' => '90° myötäpäivään (vasen/ylä)', + 'Mirror horizontal and rotate 90 CW' => '90° vastapäivään (oikea/ala)', + 'Mirror vertical' => '180° (ala/vasen)', + 'Rotate 180' => '180° (ala/oikea)', + 'Rotate 270 CW' => '90° myötäpäivään (vasen/ala)', + 'Rotate 90 CW' => '90° vastapäivään (oikea/ylä)', + }, + }, + 'OriginalDecisionDataOffset' => 'Alkuperäisen ratkaisudatan siirtymä', + 'OriginalRawFileData' => 'Originaali raw-tiedoston data', + 'OriginalRawFileDigest' => 'Alkuperäisen raw-tiedoston tiivistelmä', + 'OriginalRawFileName' => 'Originaali raw-tiedoston nimi', + 'OriginalTransmissionReference' => 'Tehtävän tunnistin', + 'OriginatingProgram' => 'Luontiohjelma', + 'OutputImageHeight' => 'Tuotoskuvan korkeus', + 'OutputImageWidth' => 'Tuotoskuvan leveys', + 'OutputResolution' => 'Tuotoksen resoluutio', + 'OutputResponse' => 'Tuotosvaste', + 'OwnerID' => 'Omistajan ID', + 'OwnerName' => 'Omistajan nimi', + 'Padding' => 'Täyte', + 'PageName' => 'Sivun nimi', + 'PageNumber' => 'Sivunumero', + 'PanasonicExifVersion' => 'Panasonic-exif -versio', + 'PanasonicRawVersion' => 'Panasonic-RAW:n versio', + 'PanasonicTitle' => 'Otsikko', + 'PanoramaDirection' => 'Panoraaman suunta', + 'PanoramaMode' => 'Panoraamatapa', + 'PentaxImageSize' => { + Description => 'Pentax-kuvakoko', + PrintConv => { + '2304x1728 or 2592x1944' => '2304 x 1728 tai 2592 x 1944', + '2560x1920 or 2304x1728' => '2560 x 1920 tai 2304 x 1728', + '2816x2212 or 2816x2112' => '2816 x 2212 tai 2816 x 2112', + '3008x2008 or 3040x2024' => '3008 x 2008 tai 3040 x 2024', + 'Full' => 'Täysi', + }, + }, + 'PentaxVersion' => 'Pentax-versio', + 'People' => 'Ihmiset', + 'PeripheralLighting' => 'Oheislaitevalaistus', + 'PeripheralLightingSetting' => 'Oheislaitevalaistuksen asetus', + 'PeripheralLightingValue' => 'Oheislaitevalaistuksen arvo', + 'PhotoEffect' => 'Valokuvaefekti', + 'PhotoEffects' => 'Valokuvaefektit', + 'PhotoEffectsBlue' => 'Valokuvaefekti sininen', + 'PhotoEffectsData' => 'Valokuvaefektidata', + 'PhotoEffectsGreen' => 'Valokuvaefekti vihreä', + 'PhotoEffectsRed' => 'Valokuvaefekti punainen', + 'PhotoEffectsType' => 'Valokuvaefektityyppi', + 'PhotometricInterpretation' => { + Description => 'Pikseliskeema', + PrintConv => { + 'BlackIsZero' => 'Musta on nolla', + 'Color Filter Array' => 'CFA (värisuodinmatriisi)', + 'Pixar LogL' => 'CIE Log2(L) (Log-luminanssi)', + 'Pixar LogLuv' => 'CIE Log2(L)(u\',v\') (Log-luminanssi ja -krominanssi)', + 'RGB Palette' => 'Väripaletti', + 'Transparency Mask' => 'Läpinäkyvyysmaski', + 'WhiteIsZero' => 'Valkoinen on nolla', + }, + }, + 'PhotoshopBGRThumbnail' => 'Photoshopin BRG-näytekuva', + 'PhotoshopFormat' => 'Photoshop-muoto', + 'PhotoshopQuality' => 'Photoshop-laatu', + 'PictInfo' => 'Kuvatiedot', + 'PictureControl' => 'Kuvan optimointi', + 'PictureControlActive' => 'Kuvan käsittely aktivoitu', + 'PictureControlAdjust' => 'Kuvan optimoinnin säätö', + 'PictureControlBase' => 'Kuvan perusoptimointi', + 'PictureControlData' => 'Kuvan käsittely', + 'PictureControlMode' => 'Kuvan käsittelytapa', + 'PictureControlName' => 'Kuvan optimoinnin nimi', + 'PictureControlQuickAdjust' => 'Kuvan optimoinnin pikasäätö', + 'PictureControlVersion' => 'Kuvan optimoinnin versio', + 'PictureFinish' => 'Kuvan viimeistely', + 'PictureMode' => { + Description => 'Kuvausohjelma', + PrintConv => { + 'Anti-blur' => 'Epätarkkuden vähennys', + 'Aperture-priority AE' => 'Aukon esivalinta AE', + 'Auto' => 'Automaattinen', + 'Beach' => 'Hiekkaranta', + 'Beach & Snow' => 'Hiekkaranta & Lumi', + 'Fireworks' => 'Ilotulitus', + 'Flower' => 'Kukka', + 'Landscape' => 'Maisema', + 'Macro' => 'Lähikuva (Kukka)', + 'Manual' => 'Manuaalinen', + 'Museum' => 'Museo', + 'Natural Light' => 'Luonnonvalo', + 'Natural Light & Flash' => 'Luonnonvalo & Salama', + 'Night Scene' => 'Yö', + 'Party' => 'Juhlat', + 'Portrait' => 'Muotokuva', + 'Program AE' => 'Automaattinen valotusohjelma', + 'Shutter speed priority AE' => 'Ajan esivalinta AE', + 'Snow' => 'Lumi', + 'Sports' => 'Urheilu', + 'Sunset' => 'Auringonlasku', + 'Text' => 'Teksti', + 'Underwater' => 'Veden alla', + }, + }, + 'PictureMode2' => 'Kuvamuoto 2', + 'PictureModeBWFilter' => { + Description => 'BW-suodin -kuvamuoto', + PrintConv => { + 'Green' => 'Vihreä', + 'Neutral' => 'Neutraali', + 'Orange' => 'Oranssi', + 'Red' => 'Punainen', + 'Yellow' => 'Keltainen', + 'n/a' => 'E.s.', + }, + }, + 'PictureModeContrast' => 'Kontrastinen kuvamuoto', + 'PictureModeHue' => 'Sävykäs kuvamuoto?', + 'PictureModeSaturation' => 'Värikylläinen kuvamuoto', + 'PictureModeSharpness' => 'Terävä kuvamuoto', + 'PictureModeTone' => { + Description => 'Vivahteikas kuvamuoto', + PrintConv => { + 'Blue' => 'Sininen', + 'Green' => 'Vihreä', + 'Neutral' => 'Neutraali', + 'Purple' => 'Violetti', + 'Sepia' => 'Seepia', + 'n/a' => 'E.s.', + }, + }, + 'PictureStyle' => 'Kuvan tyyli', + 'PixelAspectRatio' => 'Pikselien kokosuhde', + 'PixelFormat' => 'Pikseliformaatti', + 'PixelIntensityRange' => 'Pikseli-intensiteetin alue', + 'PixelScale' => 'Pikseliasteikkomalli-tagi', + 'PlanarConfiguration' => { + Description => 'Kuvadatan järjestys', + PrintConv => { + 'Chunky' => 'Lohkoformaatti (lomitettu)', + 'Planar' => 'Tasoformaatti', + }, + }, + 'PlaybackMenusTime' => 'Toistovalikkojen aika', + 'PowerSource' => 'Virtalähde', + 'PreCaptureFrames' => 'Esiasetetut kehykset', + 'Predictor' => { + Description => 'Prediktori', + PrintConv => { + 'Horizontal differencing' => 'Horisontaalinen differointi', + 'None' => 'Prediktioskeemaa ei käytetty ennen koodausta', + }, + }, + 'Preview' => 'Esikatselu', + 'Preview0' => 'Esikatselu 0', + 'Preview1' => 'Esikatselu 1', + 'Preview2' => 'Esikatselu 2', + 'PreviewApplicationName' => 'Sovelluksen nimen esikatselu', + 'PreviewApplicationVersion' => 'Sovellusversion esikatselu', + 'PreviewColorSpace' => { + Description => 'Väriavaruuden esikatselu', + PrintConv => { + 'Unknown' => 'Tuntematon', + }, + }, + 'PreviewDateTime' => 'Päiväyksen ja ajan esikatselu', + 'PreviewImage' => 'Kuvan esikatselu', + 'PreviewImageBorders' => 'Kuvan reunojen esikatselu', + 'PreviewImageData' => 'Kuvadatan tarkastelu', + 'PreviewImageLength' => 'Kuvan pituuden esikatselu', + 'PreviewImageSize' => 'Kuvakoon esikatselu', + 'PreviewImageStart' => 'Esikatselukuvan alku', + 'PreviewImageValid' => { + Description => 'Kelvollinen esikatselukuva', + PrintConv => { + 'No' => 'Ei', + 'Yes' => 'Kyllä', + }, + }, + 'PreviewSettingsDigest' => 'Asetustiivistelmän esikatselu', + 'PreviewSettingsName' => 'Asetusten nimen esikatselu', + 'PrimaryAFPoint' => 'Ensisijainen AF-piste', + 'PrimaryChromaticities' => 'Päävärien kromaattisuudet', + 'PrimaryPlatform' => 'Primaari alusta', + 'PrintQuality' => 'Tulostuslaatu', + 'ProcessingInfo' => 'Prosessointitiedot', + 'ProcessingSoftware' => 'Prosessointiohjelmisto', + 'ProductID' => 'Tuotteen ID', + 'ProfileCMMType' => 'CMM-tyypin profiili', + 'ProfileCalibrationSig' => 'Profiilin kalibrointitunniste', + 'ProfileClass' => 'Profiilin luokka', + 'ProfileConnectionSpace' => 'Profiilin yhteystila', + 'ProfileCopyright' => 'Profiilin copyright', + 'ProfileCreator' => 'Profiilin luoja', + 'ProfileDateTime' => 'Profiilin päiväysaika', + 'ProfileDescription' => 'Profiilin kuvaus', + 'ProfileDescriptionML' => 'Monikieliprofiilin kuvaus', + 'ProfileEmbedPolicy' => { + Description => 'Profiilin upotusmenetelmä', + PrintConv => { + 'Allow Copying' => 'Salli kopiointi', + 'Embed if Used' => 'Upota jos käytössä', + 'Never Embed' => 'Älä koskaan upota', + 'No Restrictions' => 'Ei rajoituksia', + }, + }, + 'ProfileFileSignature' => 'Profiilidatan tunniste', + 'ProfileHueSatMapData1' => 'Profiilin Sävy Värik. -kartan data 1', + 'ProfileHueSatMapData2' => 'Profiilin Sävy Värik. -kartan data 2', + 'ProfileID' => 'Profiilin ID', + 'ProfileLookTableData' => 'Profiilin hakutaulukon data', + 'ProfileName' => 'Profiilin nimi', + 'ProfileSequenceDesc' => 'Profiilisarjan kuvaus', + 'ProfileToneCurve' => 'Profiilin toonin käyrä', + 'ProfileVersion' => 'Profiilin versio', + 'ProgramISO' => 'Ohjelma-ISO', + 'ProgramLine' => 'Valotusohjelma', + 'ProgramMode' => 'Ohjelman muoto', + 'ProgramShift' => 'Ohjelmasiirto', + 'ProgramVersion' => 'Ohjelmaversio', + 'ProgressiveScans' => 'Progressiiviset skannaukset', + 'Province-State' => 'Provinssi/Valtio', + 'Quality' => { + Description => 'Laatu', + PrintConv => { + 'Best' => 'Paras', + 'Better' => 'Parempi', + 'Compressed RAW' => 'Pakattu RAW', + 'Compressed RAW + JPEG' => 'Pakattu RAW + JPEG', + 'Economy' => 'Taloudellinen', + 'Extra Fine' => 'Erityishieno', + 'Fine' => 'Hieno', + 'Good' => 'Hyvä', + 'Normal' => 'Normaali', + 'Standard' => 'Vakio', + 'Super Fine' => 'Superhieno', + 'n/a' => 'Ei asetettu', + }, + }, + 'QualityMode' => { + Description => 'Kuvalaatu', + PrintConv => { + 'Economy' => 'Taloudellinen', + 'Fine' => 'Hieno', + 'Normal' => 'Normaali', + }, + }, + 'QuantizationMethod' => { + Description => 'Kvantisointimetodi', + PrintConv => { + 'AP Domestic Analogue' => 'AP domestinen analogia', + 'Color Space Specific' => 'Erityisväriavaruus', + 'Compression Method Specific' => 'Erityispakkausmetodi', + 'Gamma Compensated' => 'Kompensoitu gamma', + 'IPTC Ref B' => 'IPTC ref "B"', + 'Linear Density' => 'Lineaarinen tiheys', + 'Linear Dot Percent' => 'Lineaarinen pisteprosentti', + 'Linear Reflectance/Transmittance' => 'Lineaarinen heijastavuus/läpäisevyys', + }, + }, + 'QuickAdjust' => 'Pikasäätö', + 'QuickShot' => { + Description => 'Pikakuvaus', + PrintConv => { + 'Off' => 'Pois', + 'On' => 'Päällä', + }, + }, + 'ROCInfo' => 'ROC-tiedot', + 'RangeFinder' => 'Alue-etsin', + 'RasterPadding' => 'Rasteritäyte', + 'RasterizedCaption' => 'Rasteroitu seloste', + 'Rating' => 'Arvostelu', + 'RawDataOffset' => 'RAW-datan siirtymä', + 'RawDataUniqueID' => 'Raw-datan uniikki ID', + 'RawDevColorSpace' => 'Väriavaruus', + 'RawDevContrastValue' => 'Kontrastiarvo', + 'RawDevEditStatus' => { + Description => 'Editointitila', + PrintConv => { + 'Edited (Landscape)' => 'Studio (maisema)', + 'Edited (Portrait)' => 'Studio (muotokuva)', + 'Original' => 'Alkuperäinen', + }, + }, + 'RawDevEngine' => { + Description => 'Moottori', + PrintConv => { + 'Advanced High Speed' => 'Edistynyt suurnopeus', + 'High Function' => 'Hyvä suorituskyky', + 'High Speed' => 'Suurnopeus', + }, + }, + 'RawDevExposureBiasValue' => 'Valotuksen korjausarvo', + 'RawDevGrayPoint' => 'Harmaapiste', + 'RawDevMemoryColorEmphasis' => 'Muistivärin korostus', + 'RawDevNoiseReduction' => 'Kohinasuodin (ISO-tehostus)', + 'RawDevSaturationEmphasis' => 'Värikylläisyyden korostus', + 'RawDevSettings' => 'Kohinanvaimennus', + 'RawDevSharpnessValue' => 'Kontrastiarvo', + 'RawDevVersion' => 'RAW-kehityksen versio', + 'RawDevWBFineAdjustment' => 'Valkotasapainon hienosäätö', + 'RawDevWhiteBalanceValue' => 'Valkotasapainon arvo', + 'RawImageCenter' => 'RAW-kuvan keskusta', + 'RawImageDigest' => 'RAW-kuvan tiivistelmä', + 'RawImageHeight' => 'Kuvan korkeus', + 'RawImageSize' => 'RAW-kuvakoko', + 'RawImageWidth' => 'Kuvan leveys', + 'RawInfoVersion' => 'RAW Info -versio', + 'RecognizedFace1Age' => 'Tunnistettujen kasvojen 1 ikä', + 'RecognizedFace1Name' => 'Tunnistettujen kasvojen 1 nimi', + 'RecognizedFace1Position' => 'Tunnistettujen kasvojen 1 sijainti', + 'RecognizedFace2Age' => 'Tunnistettujen kasvojen 2 ikä', + 'RecognizedFace2Name' => 'Tunnistettujen kasvojen 2 nimi', + 'RecognizedFace2Position' => 'Tunnistettujen kasvojen 2 sijainti', + 'RecognizedFace3Age' => 'Tunnistettujen kasvojen 2 ikä', + 'RecognizedFace3Name' => 'Tunnistettujen kasvojen 3 nimi', + 'RecognizedFace3Position' => 'Tunnistettujen kasvojen 3 sijainti', + 'RecognizedFaceFlags' => 'Tunnistettujen kasvojen liput', + 'RecordMode' => { + Description => 'Tallennustapa', + PrintConv => { + 'Aperture Priority' => 'Aukon esivalinta', + 'Best Shot' => 'Paras kuva', + 'Manual' => 'Manuaalinen', + 'Movie' => 'Elokuva', + 'Movie (19)' => 'Elokuva (19)', + 'Program AE' => 'AE-ohjelma', + 'Shutter Priority' => 'Ajan esivalinta', + 'YouTube Movie' => 'YouTube-elokuva', + }, + }, + 'RecordShutterRelease' => { + Description => 'Laukaisujen tallennus', + PrintConv => { + 'Press start, press stop' => 'Aloitus painaen, lopetus painaen', + 'Record while down' => 'Tallennus laukaisin alhaalla', + }, + }, + 'RecordingMode' => 'Tallennustapa', + 'RedBalance' => 'Punatasapaino', + 'RedEyeCorrection' => 'Punasilmäkorjaus', + 'RedEyeData' => 'Punasilmädata', + 'RedMatrixColumn' => 'Punaisen matriisin sarake', + 'RedTRC' => 'Punaisen toonin toistokäyrä', + 'RedX' => 'Punainen X', + 'RedY' => 'Punainen Y', + 'ReductionMatrix1' => 'Reduktiomatriisi 1', + 'ReductionMatrix2' => 'Reduktiomatriisi 2', + 'ReferenceBlackWhite' => 'Musta ja valkoinen viitearvopari', + 'ReferenceDate' => 'Viitepäiväys', + 'ReferenceNumber' => 'Viitenumero', + 'ReferenceService' => 'Viitepalvelu', + 'RelatedImageFileFormat' => 'Kuvatiedoston muoto', + 'RelatedImageHeight' => 'Kuvan korkeus', + 'RelatedImageWidth' => 'Kuvan leveys', + 'RelatedSoundFile' => 'Asiaan liittyvä audiotiedosto', + 'ReleaseButtonToUseDial' => 'Käytä valitsinta vapauttaen painike', + 'ReleaseDate' => 'Julkaisupäiväys', + 'ReleaseMode' => 'Laukaisutapa', + 'ReleaseTime' => 'Julkaisuaika', + 'RemoteOnDuration' => 'Kaukolaukaisin', + 'RenderingIntent' => 'Muokkausmenetelmä', + 'Resaved' => { + Description => 'Tallennus uudelleen', + PrintConv => { + 'No' => 'Ei', + 'Yes' => 'Kyllä', + }, + }, + 'ResolutionMode' => 'Resoluutiomuoto', + 'ResolutionUnit' => 'X- ja Y-resoluution yksikkö', + 'RetouchHistory' => 'Korjailuhistoria', + 'ReverseIndicators' => 'Käänteiset ilmaisimet', + 'RevisionNumber' => 'Revision numero', + 'RollGuidElements' => 'Guid-elementtien vieritys', + 'Rotation' => { + Description => 'Kierto', + PrintConv => { + 'Horizontal (normal)' => 'Vaakatasossa (normaali)', + 'Rotate 270 CW' => 'Kierto 90° VP', + 'Rotate 90 CW' => 'Kierto 90° MP', + }, + }, + 'RowInterleaveFactor' => 'Rivin lomitusfaktori', + 'RowsPerStrip' => 'Rivien määrä per strippi', + 'SBAExposureRecord' => 'SBA-valotuksen tallennus', + 'SBAInputImageBitDepth' => 'SBA-syötekuvan bittisyvyys', + 'SBAInputImageColorspace' => 'SBA-syötekuvan väriavaruus', + 'SMaxSampleValue' => 'S-maksimiminäytteen arvo', + 'SMinSampleValue' => 'S-miniminäytteen arvo', + 'SRFocalLength' => 'Vakain (SR) eri polttoväleillä', + 'SRResult' => 'Kuvanvakain', + 'SampleFormat' => 'Näyteformaatti', + 'SampleStructure' => { + Description => 'Näytteiden rakenne', + PrintConv => { + 'CompressionDependent' => 'Määritetty pakkaustoiminnon yhteydessä', + 'Orthogonal4-2-2Sampling' => 'Toisistaan riippumattomat näytetaajuuksin suhteessa 4:2:2:(4)', + 'OrthogonalConstangSampling' => 'Toisistaan riippumattomat samoin suhteellisin näytetaajuuksin kussakin komponentissa', + }, + }, + 'SamplesPerPixel' => 'Komponenttien määrä', + 'SanyoQuality' => { + Description => 'Sanyo-laatu', + PrintConv => { + 'Fine/High' => 'Hieno/korkea', + 'Fine/Low' => 'Hieno/matala', + 'Fine/Medium' => 'Hieno/keskilaatu', + 'Fine/Medium High' => 'Hieno/korkeahko', + 'Fine/Medium Low' => 'Hieno/matalahko', + 'Fine/Super High' => 'Hieno/superkorkea', + 'Fine/Very High' => 'Hieno/hyvin korkea', + 'Fine/Very Low' => 'Hieno/hyvin matala', + 'Normal/High' => 'Normaali/korkea', + 'Normal/Low' => 'Normaali/matala', + 'Normal/Medium' => 'Normaali/keskilaatu', + 'Normal/Medium High' => 'Normaali/korkeahko', + 'Normal/Medium Low' => 'Normaali/matalahko', + 'Normal/Super High' => 'Normaali/superkorkea', + 'Normal/Very High' => 'Normaali/hyvin korkea', + 'Normal/Very Low' => 'Normaali/hyvin matala', + 'Super Fine/High' => 'Superhieno/korkea', + 'Super Fine/Low' => 'Superhieno/matala', + 'Super Fine/Medium' => 'Superhieno/keskilaatu', + 'Super Fine/Medium High' => 'Superhieno/korkeahko', + 'Super Fine/Medium Low' => 'Superhieno/matalahko', + 'Super Fine/Super High' => 'Superhieno/superkorkea', + 'Super Fine/Very High' => 'Superhieno/hyvin korkea', + 'Super Fine/Very Low' => 'Superhieno/hyvin matala', + }, + }, + 'SanyoThumbnail' => 'Sanyo-näytekuva', + 'Saturation' => { + Description => 'Värikylläisyys', + PrintConv => { + 'Film Simulation' => 'Filminsimulaatio', + 'High' => 'Korkea', + 'Low' => 'Matala', + 'Medium High' => 'Korkeahko', + 'Medium Low' => 'Matalahko', + 'None (B&W)' => 'Ei mitään (M&V)', + 'Normal' => 'Vakio', + }, + }, + 'SaturationFaithful' => 'Kohdeuskollinen värikylläisyys', + 'SaturationLandscape' => 'Maisemakuvan värikylläisyys', + 'SaturationNeutral' => 'Neutraali värikylläisyys', + 'SaturationPortrait' => 'Muotokuvan värikylläisyys', + 'SaturationSetting' => 'Värikylläisyyden sasetus', + 'SaturationStandard' => 'Vakiovärikylläisyys', + 'ScanImageEnhancer' => { + Description => 'Skannauskuvan parantelu', + PrintConv => { + 'Off' => 'Pois', + }, + }, + 'ScanningDirection' => { + Description => 'Skannaussuunta', + PrintConv => { + 'Bottom-Top, L-R' => 'Alhaalta ylös, vasemmalta oikealle', + 'Bottom-Top, R-L' => 'Alhaalta ylös, oikealta vasemmalle', + 'L-R, Bottom-Top' => 'Vasemmalta oikealle, alhaalta ylös', + 'L-R, Top-Bottom' => 'Vasemmalta oikealle, ylhäältä alas', + 'R-L, Bottom-Top' => 'Oikealta vasemmalle, alhaalta ylös', + 'R-L, Top-Bottom' => 'Oikealta vasemmalle, ylhäältä alas', + 'Top-Bottom, L-R' => 'Ylhäältä alas, vasemmalta oikealle', + 'Top-Bottom, R-L' => 'Ylhäältä alas, oikealta vasemmalle', + }, + }, + 'Scene' => 'Näyttämö', + 'SceneArea' => 'Näkymäalue?', + 'SceneAssist' => 'Näkymä-avustaja', + 'SceneCaptureType' => { + Description => 'Kuvatun näkymän tyyppi', + PrintConv => { + 'Landscape' => 'Maisema', + 'Night' => 'Yönäkymä', + 'Portrait' => 'Muotokuva', + 'Standard' => 'Standardi', + }, + }, + 'SceneDetect' => 'Kohtauksen tunnistus', + 'SceneMode' => { + Description => 'Näkymän muoto', + PrintConv => { + '2 in 1' => '2 1:ssä', + 'Auction' => 'Huutokauppa', + 'Auto' => 'Automaattinen', + 'Available Light' => 'Vallitseva valo', + 'Beach' => 'Hiekkaranta', + 'Beach & Snow' => 'Hiekkaranta&Lumi', + 'Behind Glass' => 'Lasin takaa', + 'Candle' => 'Kynttilä', + 'Children' => 'Lapset', + 'Cuisine' => 'Ateria', + 'Digital Image Stabilization' => 'Digitaalinen kuvanvakautus', + 'Documents' => 'Dokumentit', + 'Face Portrait' => 'Kasvokuva', + 'Fireworks' => 'Ilotulitus', + 'Food' => 'Ateria', + 'High Key' => 'High key -yläsävykuva', + 'Indoor' => 'Sisäkuva', + 'Landscape' => 'Maisema', + 'Landscape+Portrait' => 'Maisema+muotokuva', + 'Low Key' => 'Low key -alasävykuva', + 'Macro' => 'Makro', + 'Movie' => 'Elokuva', + 'Museum' => 'Museo', + 'My Mode' => 'Oma tapa', + 'Nature Macro' => 'Luontomakro', + 'Night Portrait' => 'Yön muotokuva', + 'Night Scene' => 'Iltanäkymä', + 'Night View/Portrait' => 'Iltanäkymä/Yön muotokuva', + 'Night+Portrait' => 'Yö+muotokuva', + 'Normal' => 'Normaali', + 'Panorama' => 'Panoraama', + 'Pet' => 'Lemmikki', + 'Portrait' => 'Muotokuva', + 'Self Portrait' => 'Omakuva', + 'Self Portrait+Self Timer' => 'Omakuva+itselaukaisin', + 'Self Protrait+Timer' => 'Omakuva+itselaukaisin', + 'Shoot & Select' => 'Kuvaa & Valitse', + 'Shoot & Select1' => 'Kuvaus&valinta 1', + 'Shoot & Select2' => 'Kuvaus&valinta 2', + 'Shooting Guide' => 'Kuvausopas', + 'Smile Shot' => 'Hymykuva', + 'Snow' => 'Lumi', + 'Sport' => 'Urheilu', + 'Sports' => 'Urheilutapahtuma', + 'Standard' => 'Vakio', + 'Sunset' => 'Auringonlasku', + 'Super Macro' => 'Supermakro', + 'Text' => 'Teksti', + 'Underwater Macro' => 'Veden alla makro', + 'Underwater Snapshot' => 'Veden alla tilannekuva', + 'Underwater Wide1' => 'Veden alla laaja 1', + 'Underwater Wide2' => 'Veden alla laaja 2', + 'Vivid' => 'Heleä', + }, + }, + 'SceneSelect' => { + Description => 'Näkymän valinta', + PrintConv => { + 'Lamp' => 'Lamppu', + 'Night' => 'Yö', + 'Off' => 'Pois', + 'Sport' => 'Urheilu', + 'User 1' => 'Käyttäjä 1', + 'User 2' => 'Käyttäjä 2', + }, + }, + 'SceneType' => { + Description => 'Näkymätyyppi', + PrintConv => { + 'Directly photographed' => 'Suoraan otettu valokuva', + }, + }, + 'SecurityClassification' => { + Description => 'Turvallisuusluokitus', + PrintConv => { + 'Confidential' => 'Luottamuksellinen', + 'Restricted' => 'Rajoitettu', + 'Secret' => 'Salainen', + 'Top Secret' => 'Huippusalainen', + 'Unclassified' => 'Ei luokiteltu', + }, + }, + 'SelfTimer' => { + Description => 'Itselaukaisin', + PrintConv => { + 'Off' => 'Pois', + 'On' => 'Päällä', + }, + }, + 'SelfTimerMode' => 'Itselaukaisumoodi', + 'SelfTimerShotCount' => 'Itselaukaisimen otosmäärä', + 'SelfTimerTime' => 'Itselaukaisimen viive', + 'SensingMethod' => { + Description => 'Mittausmetodi', + PrintConv => { + 'Color sequential area' => 'Peräkkäisvärialueen anturi', + 'Color sequential linear' => 'Peräkkäisvärien lineaarianturi', + 'Monochrome area' => 'Monokromialueen anturi', + 'Monochrome linear' => 'Monokromilineaarinen anturi', + 'Not defined' => 'Ei määritetty', + 'One-chip color area' => 'Yhden chipin värialueen anturi', + 'Three-chip color area' => 'Kolmen chipin värialueen anturi', + 'Trilinear' => 'Trilineaarinen anturi', + 'Two-chip color area' => 'Kahden chipin värialueen anturi', + }, + }, + 'SensitivityAdjust' => 'Herkkyyden asetus', + 'SensitivitySteps' => 'Herkkyysaskeleet', + 'SensorBlueLevel' => 'Anturin sinitaso', + 'SensorBottomBorder' => 'Anturin alareuna', + 'SensorHeight' => 'Anturin korkeus', + 'SensorLeftBorder' => 'Anturin vasen reuna', + 'SensorPixelSize' => 'Anturin pikselikoko', + 'SensorRedLevel' => 'Anturin punataso', + 'SensorRightBorder' => 'Anturin oikea reuna', + 'SensorTemperature' => 'Anturin lämpötila', + 'SensorTopBorder' => 'Anturin yläreuna', + 'SensorWidth' => 'Anturin leveys', + 'Sequence' => 'Järjestys', + 'SequenceNumber' => 'Järjestysnumero', + 'SequenceShotInterval' => { + Description => 'Sarjakuvauksen taajuus', + PrintConv => { + '10 frames/s' => '10 ruutua/s', + '15 frames/s' => '15 ruutua/s', + '20 frames/s' => '20 ruutua/s', + '5 frames/s' => '5 ruutua/s', + }, + }, + 'SequentialShot' => { + Description => 'Sarjakuvaus', + PrintConv => { + 'Adjust Exposure' => 'Valotuksen säätö', + 'Best' => 'Paras', + 'None' => 'Ei mitään', + 'Standard' => 'Vakio', + }, + }, + 'SerialNumber' => 'Sarjanumero', + 'SerialNumberFormat' => 'Sarjanumeron muoto', + 'ServiceIdentifier' => 'Palvelun tunnistin', + 'ShadingCompensation' => { + Description => 'Varjostumakorjaus', + PrintConv => { + 'Off' => 'Pois', + 'On' => 'Päällä', + }, + }, + 'Shadow' => 'Varjo', + 'ShadowProtection' => 'Varjoalueen suojaus ', + 'ShadowScale' => 'Varjoasteikko', + 'Sharpness' => { + Description => 'Terävyys', + PrintConv => { + 'Film Simulation' => 'Filminsimulaatio', + 'Hard' => 'Kova', + 'Hard2' => 'Kova 2', + 'Medium Hard' => 'Kovahko', + 'Medium Soft' => 'Pehmeähkö', + 'Normal' => 'Vakio', + 'Soft' => 'Pehmeä', + 'Soft2' => 'Pehmeä 2', + 'n/a' => 'E.s.', + }, + }, + 'SharpnessFactor' => 'Terävöintikerroin', + 'SharpnessFaithful' => 'Kohdeuskollinen terävyys', + 'SharpnessFreqTable' => 'Terävyyden taajuustaulukko', + 'SharpnessFrequency' => 'Terävyystaajuus', + 'SharpnessLandscape' => 'Maisemakuvan terävyys', + 'SharpnessMonochrome' => 'Yksivärikuvan terävyys', + 'SharpnessNeutral' => 'Neutraali terävyys', + 'SharpnessPortrait' => 'Muotokuvan terävyys', + 'SharpnessSetting' => 'Terävyysasetus', + 'SharpnessStandard' => 'Vakioterävyys', + 'SharpnessTable' => 'Terävyystaulukko', + 'ShootingInfoDisplay' => 'Kuvaustietojen näyttö', + 'ShootingMode' => 'IR-kauko-ohjaus', + 'ShortDocumentID' => 'Lyhyt dokumentin ID', + 'ShortOwnerName' => 'Omistajan lyhyt nimi', + 'ShotInfoVersion' => 'Otostietojen versio', + 'ShutterCount' => 'Laukaisumäärä', + 'ShutterReleaseButtonAE-L' => 'Laukaisin AE-L', + 'ShutterSpeedValue' => 'Suljinnopeuden arvo', + 'SimilarityIndex' => 'Yhtäläisyysindeksi', + 'Site' => 'Sivusto', + 'SlaveFlashMeteringSegments' => 'Orjasalaman mittaussegmentit', + 'SlowShutter' => 'Hidas suljin', + 'SlowSync' => { + Description => 'Hidas suljin', + PrintConv => { + 'Off' => 'Pois', + 'On' => 'Päällä', + }, + }, + 'Software' => 'Ohjelmisto', + 'SoftwareVersion' => 'Ohjelmistoversio', + 'Source' => 'Lähde', + 'SourceImageDirectory' => 'Lähdekuvan kansio', + 'SourceImageFileName' => 'Lähdekuvan tiedostonimi', + 'SourceImageVolumeName' => 'Lähdekuvan taltion nimi', + 'SpatialFrequencyResponse' => 'Spatiaalisen taajuuden vaste', + 'SpecialInstructions' => 'Ohjeet', + 'SpecialMode' => 'Erikoistapa', + 'SpectralSensitivity' => 'Spektraalinen herkkyys', + 'SpotFocusPointX' => 'Pistetarkennuksen piste X', + 'SpotFocusPointY' => 'Pistetarkennuksen piste Y', + 'SpotMeteringMode' => 'Pistemittaustapa', + 'StorageMethod' => 'Tallennusmetodi', + 'StraightenAngle' => 'Kuvan suoristus', + 'StripByteCounts' => 'Tavuja per pakattu strippi', + 'StripOffsets' => 'Kuvadatan sijainti', + 'Sub-location' => 'Sijainti', + 'SubSecTime' => 'DateTime sekunnin murto-osina', + 'SubSecTimeDigitized' => 'DateTimeDigitized sekunnin murto-osina', + 'SubSecTimeOriginal' => 'DateTimeOriginal sekunnin murto-osina', + 'SubTileBlockSize' => 'Alalaattalohkon koko', + 'Subject' => 'Aihe', + 'SubjectArea' => 'Kohdealue', + 'SubjectDistance' => 'Kohteen etäisyys', + 'SubjectDistanceRange' => { + Description => 'Objektiivin tarkennusetäisyys', + PrintConv => { + 'Close' => 'Lähikuva', + 'Distant' => 'Etäkuva', + 'Macro' => 'Makro', + 'Unknown' => 'Tuntematon', + }, + }, + 'SubjectLocation' => 'Kohteen sijainti', + 'SubjectProgram' => 'Kuvausohjelma', + 'SubjectReference' => 'Aiheen koodi', + 'SuperMacro' => { + Description => 'Supermakro', + PrintConv => { + 'Off' => 'Pois', + 'On (1)' => 'Päällä (1)', + 'On (2)' => 'Päällä (2)', + }, + }, + 'SupplementalCategories' => 'Täydentävä kategoria', + 'SupplementalType' => { + Description => 'Lisäystyyppi', + PrintConv => { + 'Main Image' => 'Ei asetettu', + 'Rasterized Caption' => 'Rasteroitu seloste', + 'Reduced Resolution Image' => 'Alennetun resoluution kuva', + }, + }, + 'SvISOSetting' => 'Sv-ISO-asetus', + 'T4Options' => 'Lisätyt täytebitit', + 'T6Options' => 'T6-valinnat', + 'TIFF-EPStandardID' => 'TIFF/EP-standardin ID', + 'TargetAperture' => 'Tavoiteaukko', + 'TargetExposureTime' => 'Tavoitevalotusaika', + 'TargetPrinter' => 'Kohdetulostin', + 'Technology' => { + Description => 'Teknologia', + PrintConv => { + 'Digital Camera' => 'Digitaalikamera', + 'Dye Sublimation Printer' => 'Lämpösublimaatiotulostin', + 'Electrophotographic Printer' => 'Lasertulostin', + 'Electrostatic Printer' => 'Sähköstaattinen tulostin', + 'Film Scanner' => 'Filmiskanneri', + 'Film Writer' => 'Filmitulostin', + 'Flexography' => 'Fleksografia', + 'Gravure' => 'Syväpaino', + 'Ink Jet Printer' => 'Mustesuihkutulostin', + 'Offset Lithography' => 'Offsetlitografia', + 'Photo CD' => 'Valokuva-CD', + 'Photo Image Setter' => 'Valokuvaimagesetteri', + 'Photographic Paper Printer' => 'Valokuvapaperitulostin', + 'Projection Television' => 'Projektiotelevisio', + 'Reflective Scanner' => 'Heijastusskanneri', + 'Silkscreen' => 'Silkkipaino', + 'Thermal Wax Printer' => 'Lämpövahatulostin', + 'Video Camera' => 'Videokamera', + 'Video Monitor' => 'Videomonitori', + }, + }, + 'Text' => 'Teksti', + 'TextInfo' => 'Tekstitiedot', + 'TextStamp' => { + Description => 'Tekstileimasin', + PrintConv => { + 'Off' => 'Päällä', + }, + }, + 'Thresholding' => 'Kynnystys', + 'ThumbnailImage' => 'Näytekuva', + 'ThumbnailImageValidArea' => 'Näytekuvan kelpaava alue', + 'TileByteCounts' => 'Ruutujen tavumäärät', + 'TileDepth' => 'Ruudun syvyys', + 'TileLength' => 'Ruudun pituus', + 'TileOffsets' => 'Ruutusiirtymät', + 'TileWidth' => 'Otsikon leveys', + 'Time' => 'Aika', + 'TimeCreated' => 'Luontiaika', + 'TimeSent' => 'Lähetysaika', + 'TimeSincePowerOn' => 'Virran päälläoloaika', + 'TimeStamp' => 'Aikaleima', + 'TimeZone' => 'Aikavyöhyke', + 'TimeZoneOffset' => 'Aikavyöhykkeen siirtymä', + 'TimerFunctionButton' => 'Ajastustoimintopainike', + 'Title' => 'Otsikko', + 'ToneComp' => 'Sävykorjailu', + 'ToneCurve' => 'Sävykäyrä', + 'ToneCurveMatching' => 'Sävykäyrän täsmäys', + 'ToneCurveTable' => 'Sävykäyrätaulukko', + 'ToneCurves' => 'Sävykäyrät', + 'ToningEffect' => 'Sävytysefekti', + 'ToningEffectMonochrome' => 'Yksivärisävytysefekti', + 'ToningSaturation' => 'Sävykylläisyys', + 'TransferFunction' => 'Muuntotoiminto', + 'TransferRange' => 'Siirtonopeus', + 'Transform' => 'Muunna', + 'Transformation' => { + Description => 'Muunto', + PrintConv => { + 'Mirror horizontal' => 'Peilaa vaakasuunnassa', + 'Mirror horizontal and rotate 270 CW' => 'Peilaa vaakasuunnassa ja kierrä 270° myötäpäivään', + 'Mirror horizontal and rotate 90 CW' => 'Peilaa vaakasuunnassa ja kierrä 90° myötäpäivään', + 'Mirror vertical' => 'Peilaa pystysuunnassa', + 'Rotate 180' => 'Kierrä 180°', + 'Rotate 270 CW' => 'Kierrä 90° myötäpäivään', + 'Rotate 90 CW' => 'Kierrä 90° myötäpäivään', + }, + }, + 'TransparencyIndicator' => 'Läpinäkyvyyden ilmaisin', + 'TravelDay' => 'Matkapäivä', + 'TvExposureTimeSetting' => 'Tv-valotusaikaasetus', + 'Type' => 'Tyyppi', + 'Uncompressed' => { + Description => 'Pakkaamaton', + PrintConv => { + 'No' => 'Ei', + 'Yes' => 'Kyllä', + }, + }, + 'UniqueCameraModel' => 'Uniikki kameramalli', + 'UniqueDocumentID' => 'Uniikin dokumentin ID', + 'Unknown' => 'Tuntematon', + 'Unsharp1Color' => 'Terävöinti 1 -väri', + 'Unsharp1HaloWidth' => 'Terävöinti 1 -halolaajuus', + 'Unsharp1Intensity' => 'Terävöinti 1 -voimakkuus', + 'Unsharp1Threshold' => 'Terävöinti 1 -kynnys', + 'Unsharp2Color' => 'Terävöinti 2 -väri', + 'Unsharp2HaloWidth' => 'Terävöinti 2 -halolaajuus', + 'Unsharp2Intensity' => 'Terävöinti 2 -voimakkuus', + 'Unsharp2Threshold' => 'Terävöinti 2 -kynnys', + 'Unsharp3Color' => 'Terävöinti 3 -väri', + 'Unsharp3HaloWidth' => 'Terävöinti 3 -halolaajuus', + 'Unsharp3Intensity' => 'Terävöinti 3 -voimakkuus', + 'Unsharp3Threshold' => 'Terävöinti 3 -kynnys', + 'Unsharp4Color' => 'Terävöinti 4 -väri', + 'Unsharp4HaloWidth' => 'Terävöinti 4 -halolaajuus', + 'Unsharp4Intensity' => 'Terävöinti 4 -voimakkuus', + 'Unsharp4Threshold' => 'Terävöinti 4 -kynnys', + 'UnsharpCount' => 'Terävöintimäärä', + 'UnsharpData' => 'Terävöintidata', + 'UnsharpMask' => 'Epäterävä maski', + 'Urgency' => { + Description => 'Kiireellisyys', + PrintConv => { + '0 (reserved)' => '0 (varattu tulevaan käyttöön)', + '1 (most urgent)' => '1 (hyvin kiireellinen)', + '5 (normal urgency)' => '5 (normaali kiirellisyys)', + '8 (least urgent)' => '8 (lievän kiireellinen)', + '9 (user-defined priority)' => '9 (varattu tulevaan käyttöön)', + }, + }, + 'UserComment' => 'Käyttäjän kommentti', + 'UserSelectGroupTitle' => 'Käyttäjän valitseman ryhmän otsikko', + 'VRDOffset' => 'VRD-siirtymä', + 'VRInfo' => 'Kuvanvakaimen tiedot', + 'VRInfoVersion' => 'VR- (kuvanvakain) tietojen versio', + 'ValidAFPoints' => 'Kelpaavat AF-pisteet', + 'VariProgram' => 'Kuvausohjelma', + 'Version' => 'Versio', + 'VibrationReduction' => 'Kuvanvakautus', + 'VideoCardGamma' => 'Grafiikkakortin gamma', + 'ViewfinderWarning' => 'Etsinvaroitus', + 'ViewingCondDesc' => 'Katseluolojen kuvaus', + 'VignetteControl' => { + Description => 'Vinjetoinnin korjaus', + PrintConv => { + 'High' => 'Korkea', + 'Low' => 'Matala', + 'Normal' => 'Normaali', + 'Off' => 'Pois', + }, + }, + 'VignetteControlIntensity' => 'Vinjetoinnin korjauksen voimakkuus', + 'VoiceMemo' => { + Description => 'Äänen tallennus', + PrintConv => { + 'Off' => 'Pois', + 'On' => 'Päällä', + }, + }, + 'WBAdjData' => 'Valkotaspainon säätödata', + 'WBBlueLevel' => 'Valkotas. sinisen taso', + 'WBBracketMode' => 'Valkotasapaino-haarukointitapa', + 'WBBracketValueAB' => 'Valkotasapainon AB-haarukointiarvo', + 'WBBracketValueGM' => 'Valkotasapainon GM-haarukointiarvo', + 'WBGreenLevel' => 'Vihreän taso', + 'WBMode' => { + Description => 'Valkotasapainotila', + PrintConv => { + 'Auto' => 'Automaattinen', + }, + }, + 'WBRedLevel' => 'Valkotas. punaisen taso', + 'WBShiftAB' => 'Valkotas. säätö keltainen/sininen', + 'WBShiftGM' => 'Valkotas. säätö vihreä/magenta', + 'WB_RBLevels' => 'Valkotasapaino punainen/sininen', + 'WB_RBLevelsAuto' => 'Valkotas. RB-tasot, automatiikka', + 'WB_RBLevelsCoolWhiteFluor' => 'Valkotas. RB-tasot, viileän valk. loistel.', + 'WB_RBLevelsDayWhiteFluor' => 'Valkotas. RB-tasot, valk. päivänvaloloistel.', + 'WB_RBLevelsDaylightFluor' => 'Valkotas. RB-tasot, päivänvaloloistel.', + 'WB_RBLevelsEveningSunlight' => 'Valkotas. RB-tasot, ilta-aurinko', + 'WB_RBLevelsFineWeather' => 'Valkotas. RB-tasot, kaunis sää', + 'WB_RBLevelsShade' => 'Valkotas. RB-tasot, varjo', + 'WB_RBLevelsTungsten' => 'Valkotas. RB-tasot, hehkulamppu', + 'WB_RBLevelsUsed' => 'Käytetyt valkotas. RB-tasot', + 'WB_RBLevelsWhiteFluorescent' => 'Valkotas. RB-tasot, valk. loistelamppu', + 'WB_RGGBLevelsCloudy' => 'Valkotasapainon RGGB-tasojen pilvinen', + 'WB_RGGBLevelsDaylight' => 'Valkotasapainon RGGB-tasojen päivänvalo', + 'WB_RGGBLevelsFlash' => 'Valkotasapainon RGGB-tasojen salama', + 'WB_RGGBLevelsFluorescentD' => 'Valkotasapainon RGGB-tasojen loistelamppu D', + 'WB_RGGBLevelsFluorescentN' => 'Valkotasapainon RGGB-tasojen loistelamppu N', + 'WB_RGGBLevelsFluorescentW' => 'Valkotasapainon RGGB-tasojen loistelamppu W', + 'WB_RGGBLevelsShade' => 'Valkotasapainon RGGB-tasojen varjo', + 'WB_RGGBLevelsTungsten' => 'Valkotasapainon RGGB-tasojen hehkulamppu', + 'Watermark' => 'Vesileima', + 'WatermarkType' => 'Vesileiman tyyppi', + 'WhiteBalance' => { + Description => 'Valkotasapaino', + PrintConv => { + 'Auto' => 'Automaattinen', + 'Cloudy' => 'Pilvinen', + 'Custom' => 'Mukautus', + 'Custom2' => 'Mukautus 2', + 'Custom3' => 'Mukautus 3', + 'Custom4' => 'Mukautus 4', + 'Day White Fluorescent' => 'Valkoinen päivänvaloloistelamppu', + 'Daylight' => 'Auringonvalo', + 'Daylight Fluorescent' => 'Päivänvaloloistelamppu', + 'Flash' => 'Salama', + 'Incandescent' => 'Hehkulamppu', + 'Living Room Warm White Fluorescent' => 'Asuinhuoneen lämmin valkoinen loistelamppu', + 'Manual' => 'Manuaalinen', + 'Warm White Fluorescent' => 'Lämmin valkoinen loistelamppu', + 'White Fluorescent' => 'Valkoinen loistelamppu', + }, + }, + 'WhiteBalance2' => { + Description => 'Valkotasapaino', + PrintConv => { + '3000K (Tungsten light)' => '3000 K (hehkulamppu)', + '3600K (Tungsten light-like)' => '3600 K (hehkulamppumainen valo)', + '4000K (Cool white fluorescent)' => '4000 K (viileän valkoinen loistelamppu)', + '4500K (Neutral white fluorescent)' => '4500 K (neutraali valkoinen loistelamppu)', + '5300K (Fine Weather)' => '5300 K (kaunis sää)', + '6000K (Cloudy)' => '6000 K (pilvinen)', + '6600K (Daylight fluorescent)' => '6600 K (päivänvaloloistelamppu)', + '7500K (Fine Weather with Shade)' => '7500 K (kaunis sää ja varjoja)', + 'Auto' => 'Automaattinen', + 'Custom WB 1' => 'Mukautettu valkotasapaino 1', + 'Custom WB 2' => 'Mukautettu valkotasapaino 2', + 'Custom WB 2900K' => 'Mukautettu valkotasapaino 2900 K', + 'Custom WB 3' => 'Mukautettu valkotasapaino 3', + 'Custom WB 4' => 'Mukautettu valkotasapaino 4', + 'Custom WB 5400K' => 'Mukautettu valkotasapaino 5400 K', + 'Custom WB 8000K' => 'Mukautettu valkotasapaino 8000 K', + }, + }, + 'WhiteBalanceAdj' => 'Väritasapainon säätö', + 'WhiteBalanceBias' => 'Valkotasapainon korjaus', + 'WhiteBalanceBlue' => 'Valkotasapaino sininen', + 'WhiteBalanceBracket' => 'Valkotasapainon haarukointi', + 'WhiteBalanceBracketing' => 'Valkotasapainohaarukointi', + 'WhiteBalanceComp' => 'Valkotasapainon säätö', + 'WhiteBalanceFineTune' => 'Valkotasapainon hienosäätö', + 'WhiteBalanceMatching' => 'Valkotasapainon täsmäys', + 'WhiteBalanceMode' => { + Description => 'Valkotasapainon muoto', + PrintConv => { + 'Auto (Cloudy)' => 'Automaattinen (pilvinen)', + 'Auto (Day White Fluorescent)' => 'Automaattinen (valkoinen päivänvaloloistelamppu)', + 'Auto (Daylight Fluorescent)' => 'Automaattinen (päivänvaloloistelamppu)', + 'Auto (Daylight)' => 'Automaattinen (auringonvalo)', + 'Auto (Flash)' => 'Automaattinen (salama)', + 'Auto (Shade)' => 'Automaattinen (varjo)', + 'Auto (Tungsten)' => 'Automaattinen (hehkulamppu)', + 'Auto (White Fluorescent)' => 'Automaattinen (valkoinen loistelamppu)', + 'Unknown' => 'Automaattinen (ei tunnistettu)', + 'User-Selected' => 'Itse valittu', + }, + }, + 'WhiteBalanceRed' => 'Valkotasapaino punainen', + 'WhiteBalanceSet' => 'Asetettu valkotasapaino', + 'WhiteBalanceTable' => 'Valkotasapainotaulukko', + 'WhiteBalanceTemperature' => 'Valkotaspainon lämpötila', + 'WhiteBoard' => 'Valkoinen pohja', + 'WhiteLevel' => 'Valkoinen taso', + 'WhitePoint' => 'Valkoinen piste', + 'WhitePointX' => 'Valkoinen piste X', + 'WhitePointY' => 'Valkoinen piste Y', + 'Wide' => 'Laaja', + 'WideFocusZone' => 'Laaja-alatarkennuksen alue', + 'WideRange' => { + Description => 'Laaja alue', + PrintConv => { + 'Off' => 'Pois', + 'On' => 'Päällä', + }, + }, + 'WorldTimeLocation' => { + Description => 'Maailmanaikasijainti', + PrintConv => { + 'Destination' => 'Kohde', + 'Home' => 'Koti', + 'Hometown' => 'Kotiseutu', + }, + }, + 'Writer-Editor' => 'Selosteen/Kuvatekstin kirjoittaja', + 'X3FillLight' => 'X3-täytevalo', + 'XClipPathUnits' => 'X-leikepolkuyksiköt', + 'XMP' => 'XMP-metadata', + 'XPosition' => 'X-sijainti', + 'XResolution' => 'Kuvan vaakaresoluutio', + 'YCbCrCoefficients' => 'Väriavaruuden muunnon matriisikertoimet', + 'YCbCrPositioning' => 'Y:n ja C:n sijoitus', + 'YCbCrSubSampling' => 'Suhteen Y - C subsamplaus', + 'YClipPathUnits' => 'Y-leikepolkuyksiköt', + 'YPosition' => 'Y-sijainti', + 'YResolution' => 'Kuvan pystyresoluutio', + 'ZoneMatching' => { + Description => 'Yli/alivalotuksen esto', + PrintConv => { + 'High Key' => 'Yläsävykuva', + 'ISO Setting Used' => 'Pois (käytetty ISO-asetusta)', + 'Low Key' => 'Alasävykuva', + }, + }, + 'Zoom' => 'Zoom-objektiivi', + 'ZoomSourceWidth' => 'Zoomauksen lähtökoko', + 'ZoomStepCount' => 'Zoom-askelmäärä', + 'ZoomTargetWidth' => 'Zoomauksen loppukoko', +); + +1; # end + + +__END__ + +=head1 NAME + +Image::ExifTool::Lang::fi.pm - ExifTool Finnish language translations + +=head1 DESCRIPTION + +This file is used by Image::ExifTool to generate localized tag descriptions +and values. + +=head1 AUTHOR + +Copyright 2003-2019, Phil Harvey (phil at owl.phy.queensu.ca) + +This library is free software; you can redistribute it and/or modify it +under the same terms as Perl itself. + +=head1 ACKNOWLEDGEMENTS + +Thanks to Jens Duttke and Jarkko ME<auml>kineva for providing this +translation. + +=head1 SEE ALSO + +L<Image::ExifTool(3pm)|Image::ExifTool>, +L<Image::ExifTool::TagInfoXML(3pm)|Image::ExifTool::TagInfoXML> + +=cut diff --git a/lib/Image/ExifTool/Lang/fr.pm b/lib/Image/ExifTool/Lang/fr.pm new file mode 100644 index 0000000..fdae02c --- /dev/null +++ b/lib/Image/ExifTool/Lang/fr.pm @@ -0,0 +1,4767 @@ +#------------------------------------------------------------------------------ +# File: fr.pm +# +# Description: ExifTool French language translations +# +# Notes: This file generated automatically by Image::ExifTool::TagInfoXML +#------------------------------------------------------------------------------ + +package Image::ExifTool::Lang::fr; + +use strict; +use vars qw($VERSION); + +$VERSION = '1.32'; + +%Image::ExifTool::Lang::fr::Translate = ( + 'AEAperture' => 'Ouverture AE', + 'AEBAutoCancel' => { + Description => 'Annulation bracketing auto', + PrintConv => { + 'Off' => 'Arrêt', + 'On' => 'Marche', + }, + }, + 'AEBSequence' => 'Séquence de bracketing', + 'AEBSequenceAutoCancel' => { + Description => 'Séquence auto AEB/annuler', + PrintConv => { + '-,0,+/Disabled' => '-,0,+/Désactivé', + '-,0,+/Enabled' => '-,0,+/Activé', + '0,-,+/Disabled' => '0,-,+/Désactivé', + '0,-,+/Enabled' => '0,-,+/Activé', + }, + }, + 'AEBShotCount' => 'Nombre de vues bracketées', + 'AEBXv' => 'Compensation d\'expo. auto en bracketing', + 'AEExposureTime' => 'Temps d\'exposition AE', + 'AEExtra' => 'Suppléments AE', + 'AEInfo' => 'Info sur l\'exposition auto', + 'AELock' => { + Description => 'Verrouillage AE', + PrintConv => { + 'Off' => 'Désactivé', + 'On' => 'Activé', + }, + }, + 'AEMaxAperture' => 'Ouverture maxi AE', + 'AEMaxAperture2' => 'Ouverture maxi AE (2)', + 'AEMeteringMode' => { + Description => 'Mode de mesure AE', + PrintConv => { + 'Multi-segment' => 'Multizone', + }, + }, + 'AEMeteringSegments' => 'Segments de mesure AE', + 'AEMinAperture' => 'Ouverture mini AE', + 'AEMinExposureTime' => 'Temps d\'exposition mini AE', + 'AEProgramMode' => { + Description => 'Mode programme AE', + PrintConv => { + 'Av, B or X' => 'Av, B ou X', + 'Candlelight' => 'Bougie', + 'DOF Program' => 'Programme PdC', + 'DOF Program (P-Shift)' => 'Programme PdC (décalage P)', + 'Hi-speed Program' => 'Programme grande vitesse', + 'Hi-speed Program (P-Shift)' => 'Programme grande vitesse (décalage P)', + 'Kids' => 'Enfants', + 'Landscape' => 'Paysage', + 'M, P or TAv' => 'M, P ou TAv', + 'MTF Program' => 'Programme FTM', + 'MTF Program (P-Shift)' => 'Programme FTM (décalage P)', + 'Museum' => 'Musée', + 'Night Scene' => 'Nocturne', + 'Night Scene Portrait' => 'Portrait nocturne', + 'No Flash' => 'Sans flash', + 'Pet' => 'Animaux de compagnie', + 'Sunset' => 'Coucher de soleil', + 'Surf & Snow' => 'Surf et neige', + 'Sv or Green Mode' => 'Sv ou mode vert', + 'Text' => 'Texte', + }, + }, + 'AEXv' => 'Compensation d\'exposition auto', + 'AE_ISO' => 'Sensibilité ISO AE', + 'AFAdjustment' => 'Ajustement AF', + 'AFAperture' => 'Ouverture AF', + 'AFAreaIllumination' => { + PrintConv => { + 'Off' => 'Désactivé', + 'On' => 'Activé', + }, + }, + 'AFAreaMode' => { + Description => 'Mode de zone AF', + PrintConv => { + '1-area' => 'Mise au point 1 zone', + '1-area (high speed)' => 'Mise au point 1 zone (haute vitesse)', + '3-area (center)?' => 'Mise au point 3 zones (au centre) ?', + '3-area (high speed)' => 'Mise au point 3 zones (haute vitesse)', + '3-area (left)?' => 'Mise au point 3 zones (à gauche) ?', + '3-area (right)?' => 'Mise au point 3 zones (à droite) ?', + '5-area' => 'Mise au point 5 zones', + '9-area' => 'Mise au point 9 zones', + 'Face Detect AF' => 'Dét. visage', + 'Spot Focusing' => 'Mise au point Spot', + 'Spot Mode Off' => 'Mode Spot désactivé', + 'Spot Mode On' => 'Mode Spot enclenché', + }, + }, + 'AFAssist' => { + Description => 'Faisceau d\'assistance AF', + PrintConv => { + 'Does not emit/Fires' => 'N\'émet pas/Se déclenche', + 'Emits/Does not fire' => 'Emet/Ne se déclenche pas', + 'Emits/Fires' => 'Emet/Se déclenche', + 'Off' => 'Désactivé', + 'On' => 'Activé', + 'Only ext. flash emits/Fires' => 'Flash ext émet/Se déclenche', + }, + }, + 'AFAssistBeam' => { + Description => 'Faisceau d\'assistance AF', + PrintConv => { + 'Does not emit' => 'Désactivé', + 'Emits' => 'Activé', + 'Only ext. flash emits' => 'Uniquement par flash ext.', + }, + }, + 'AFDefocus' => 'Défocalisation AF', + 'AFDuringLiveView' => { + Description => 'AF pendant la visée directe', + PrintConv => { + 'Disable' => 'Désactivé', + 'Enable' => 'Activé', + 'Live mode' => 'Mode visée directe', + 'Quick mode' => 'Mode rapide', + }, + }, + 'AFInfo' => 'Info autofocus', + 'AFInfo2' => 'Infos AF', + 'AFInfo2Version' => 'Version des infos AF', + 'AFIntegrationTime' => 'Temps d\'intégration AF', + 'AFMicroadjustment' => { + Description => 'Micro-ajustement de l\'AF', + PrintConv => { + 'Adjust all by same amount' => 'Ajuster idem tous obj', + 'Adjust by lens' => 'Ajuster par objectif', + 'Disable' => 'Désactivé', + }, + }, + 'AFMode' => 'Mode AF', + 'AFOnAELockButtonSwitch' => { + Description => 'Permutation touche AF/Mémo', + PrintConv => { + 'Disable' => 'Désactivé', + 'Enable' => 'Activé', + }, + }, + 'AFPoint' => { + Description => 'Point AF', + PrintConv => { + 'Bottom' => 'Bas', + 'Center' => 'Centre', + 'Far Left' => 'Extrême-gauche', + 'Far Right' => 'Extrême-droit', + 'Left' => 'Gauche', + 'Lower-left' => 'Bas-gauche', + 'Lower-right' => 'Bas-droit', + 'Mid-left' => 'Milieu gauche', + 'Mid-right' => 'Milieu droit', + 'None' => 'Aucune', + 'Right' => 'Droit', + 'Top' => 'Haut', + 'Upper-left' => 'Haut-gauche', + 'Upper-right' => 'Haut-droit', + }, + }, + 'AFPointActivationArea' => { + Description => 'Zone activation collimateurs AF', + PrintConv => { + 'Automatic expanded (max. 13)' => 'Expansion auto (13 max.)', + 'Expanded (TTL. of 7 AF points)' => 'Expansion (TTL 7 collimat.)', + 'Single AF point' => 'Un seul collimateur AF', + }, + }, + 'AFPointAreaExpansion' => { + Description => 'Extension de la zone AF', + PrintConv => { + 'Disable' => 'Désactivé', + 'Enable' => 'Activé', + 'Left/right AF points' => 'Activé (gauche/droite collimateurs autofocus d\'assistance)', + 'Surrounding AF points' => 'Activée (Collimateurs autofocus d\'assistance environnants)', + }, + }, + 'AFPointAutoSelection' => { + Description => 'Sélection des collimateurs automatique', + PrintConv => { + 'Control-direct:disable/Main:disable' => 'Contrôle rapide-Directe:désactivé/Principale:désactivé', + 'Control-direct:disable/Main:enable' => 'Contrôle rapide-Directe:désactivé/Principale:activé', + 'Control-direct:enable/Main:enable' => 'Contrôle rapide-Directe:activé/Principale:activé', + }, + }, + 'AFPointBrightness' => { + Description => 'Intensité d\'illumination AF', + PrintConv => { + 'Brighter' => 'Forte', + 'Normal' => 'Normale', + }, + }, + 'AFPointDisplayDuringFocus' => { + Description => 'Affichage de point AF pendant mise au point', + PrintConv => { + 'Off' => 'Désactivé', + 'On' => 'Activé', + 'On (when focus achieved)' => 'Activé (si mise au point effectuée)', + }, + }, + 'AFPointIllumination' => { + Description => 'Eclairage des collimateurs AF', + PrintConv => { + 'Brighter' => 'Plus brillant', + 'Off' => 'Désactivé', + 'On' => 'Activé', + 'On without dimming' => 'Activé sans atténuation', + }, + }, + 'AFPointMode' => 'Mode de mise au point AF', + 'AFPointRegistration' => { + Description => 'Validation du point AF', + PrintConv => { + 'Automatic' => 'Auto', + 'Bottom' => 'Bas', + 'Center' => 'Centre', + 'Extreme Left' => 'Extrême gauche', + 'Extreme Right' => 'Extrême droite', + 'Left' => 'Gauche', + 'Right' => 'Droit', + 'Top' => 'Haut', + }, + }, + 'AFPointSelected' => { + Description => 'Point AF sélectionné', + PrintConv => { + 'Automatic Tracking AF' => 'AF en suivi auto', + 'Bottom' => 'Bas', + 'Center' => 'Centre', + 'Face Detect AF' => 'AF en reconnaissance de visage', + 'Fixed Center' => 'Fixe au centre', + 'Left' => 'Gauche', + 'Lower-left' => 'Bas gauche', + 'Lower-right' => 'Bas droit', + 'Mid-left' => 'Milieu gauche', + 'Mid-right' => 'Milieu droit', + 'Right' => 'Droit', + 'Top' => 'Haut', + 'Upper-left' => 'Haut gauche', + 'Upper-right' => 'Haut droite', + }, + }, + 'AFPointSelected2' => 'Point AF sélectionné 2', + 'AFPointSelection' => 'Méthode sélect. collimateurs AF', + 'AFPointSelectionMethod' => { + Description => 'Méthode sélection collim. AF', + PrintConv => { + 'Multi-controller direct' => 'Multicontrôleur direct', + 'Normal' => 'Normale', + 'Quick Control Dial direct' => 'Molette AR directe', + }, + }, + 'AFPointSpotMetering' => { + Description => 'Nombre collimateurs/mesure spot', + PrintConv => { + '11/Active AF point' => '11/collimateur AF actif', + '11/Center AF point' => '11/collimateur AF central', + '45/Center AF point' => '45/collimateur AF central', + '9/Active AF point' => '9/collimateur AF actif', + }, + }, + 'AFPointsInFocus' => { + Description => 'Points AF nets', + PrintConv => { + 'All' => 'Tous', + 'Bottom' => 'Bas', + 'Bottom, Center' => 'Bas + centre', + 'Bottom-center' => 'Bas centre', + 'Bottom-left' => 'Bas gauche', + 'Bottom-right' => 'Bas droit', + 'Center' => 'Centre', + 'Center (horizontal)' => 'Centre (horizontal)', + 'Center (vertical)' => 'Centre (vertical)', + 'Center+Right' => 'Centre+droit', + 'Fixed Center or Multiple' => 'Centre fixe ou multiple', + 'Left' => 'Gauche', + 'Left+Center' => 'Gauch+centre', + 'Left+Right' => 'Gauche+droit', + 'Lower-left, Bottom' => 'Bas gauche + bas', + 'Lower-left, Mid-left' => 'Bas gauche + milieu gauche', + 'Lower-right, Bottom' => 'Bas droit + bas', + 'Lower-right, Mid-right' => 'Bas droit + milieu droit', + 'Mid-left' => 'Milieu gauche', + 'Mid-left, Center' => 'Milieu gauche + centre', + 'Mid-right' => 'Milieu droit', + 'Mid-right, Center' => 'Milieu droit + centre', + 'None' => 'Aucune', + 'None (MF)' => 'Aucune (MF)', + 'Right' => 'Droit', + 'Top' => 'Haut', + 'Top, Center' => 'Haut + centre', + 'Top-center' => 'Haut centre', + 'Top-left' => 'Haut gauche', + 'Top-right' => 'Haut droit', + 'Upper-left, Mid-left' => 'Haut gauche + milieu gauche', + 'Upper-left, Top' => 'Haut gauche + haut', + 'Upper-right, Mid-right' => 'Haut droit + milieu droit', + 'Upper-right, Top' => 'Haut droit + haut', + }, + }, + 'AFPointsSelected' => 'Points AF sélectionnés', + 'AFPointsUnknown1' => { + PrintConv => { + 'All' => 'Tous', + 'Central 9 points' => '9 points centraux', + }, + }, + 'AFPointsUnknown2' => 'Points AF inconnus 2', + 'AFPointsUsed' => { + Description => 'Points AF utilisés', + PrintConv => { + 'Bottom' => 'Bas', + 'Center' => 'Centre', + 'Mid-left' => 'Milieu gauche', + 'Mid-right' => 'Milieu droit', + 'Top' => 'Haut', + }, + }, + 'AFPredictor' => 'Prédicteur AF', + 'AFResponse' => 'Réponse AF', + 'AIServoContinuousShooting' => 'Priorité vit. méca. AI Servo', + 'AIServoImagePriority' => { + Description => '1er Servo Ai/2e priorité déclenchement', + PrintConv => { + '1: AF, 2: Drive speed' => 'Priorité AF/Priorité cadence vues', + '1: AF, 2: Tracking' => 'Priorité AF/Priorité suivi AF', + '1: Release, 2: Drive speed' => 'Déclenchement/Priorité cadence vues', + }, + }, + 'AIServoTrackingMethod' => { + Description => 'Méthode de suivi autofocus AI Servo', + PrintConv => { + 'Continuous AF track priority' => 'Priorité suivi AF en continu', + 'Main focus point priority' => 'Priorité point AF principal', + }, + }, + 'AIServoTrackingSensitivity' => { + Description => 'Sensibili. de suivi AI Servo', + PrintConv => { + 'Fast' => 'Rapide', + 'Medium Fast' => 'Moyenne rapide', + 'Medium Slow' => 'Moyenne lent', + 'Moderately fast' => 'Moyennement rapide', + 'Moderately slow' => 'Moyennement lent', + 'Slow' => 'Lent', + }, + }, + 'APEVersion' => 'Version APE', + 'ARMIdentifier' => 'Identificateur ARM', + 'ARMVersion' => 'Version ARM', + 'AToB0' => 'A à B0', + 'AToB1' => 'A à B1', + 'AToB2' => 'A à B2', + 'AccessoryType' => 'Type d\'accessoire', + 'ActionAdvised' => { + Description => 'Action conseillée', + PrintConv => { + 'Object Kill' => 'Destruction d\'objet', + 'Object Reference' => 'Référence d\'objet', + 'Object Replace' => 'Remplacement d\'objet', + 'Ojbect Append' => 'Ajout d\'objet', + }, + }, + 'ActiveArea' => 'Zone active', + 'ActiveD-Lighting' => { + PrintConv => { + 'Low' => 'Bas', + 'Normal' => 'Normale', + 'Off' => 'Désactivé', + 'On' => 'Activé', + }, + }, + 'ActiveD-LightingMode' => { + PrintConv => { + 'Low' => 'Bas', + 'Normal' => 'Normale', + 'Off' => 'Désactivé', + }, + }, + 'AddAspectRatioInfo' => { + Description => 'Ajouter info ratio d\'aspect', + PrintConv => { + 'Off' => 'Désactivé', + }, + }, + 'AddOriginalDecisionData' => { + Description => 'Aj. données décis. origine', + PrintConv => { + 'Off' => 'Désactivé', + 'On' => 'Activé', + }, + }, + 'AdditionalModelInformation' => 'Modèle d\'Information additionnel', + 'Address' => 'Adresse', + 'AdultContentWarning' => { + PrintConv => { + 'Unknown' => 'Inconnu', + }, + }, + 'AdvancedRaw' => { + PrintConv => { + 'Off' => 'Désactivé', + 'On' => 'Activé', + }, + }, + 'AdvancedSceneMode' => { + PrintConv => { + 'Color Select' => 'Désaturation partielle', + 'Cross Process' => 'Dévelop. croisé', + 'Dynamic Monochrome' => 'Monochrome dynamique', + 'Expressive' => 'Expressif', + 'High Dynamic' => 'Dynamique haute', + 'High Key' => 'Tons clairs', + 'Impressive Art' => 'Impressionisme', + 'Low Key' => 'Clair-obscur', + 'Miniature' => 'Effet miniature', + 'Retro' => 'Rétro', + 'Sepia' => 'Sépia', + 'Soft' => 'Mise au point douce', + 'Star' => 'Filtre étoile', + 'Toy Effect' => 'Effet jouet', + }, + }, + 'Advisory' => 'Adversité', + 'AnalogBalance' => 'Balance analogique', + 'Annotations' => 'Annotations Photoshop', + 'Anti-Blur' => { + PrintConv => { + 'Off' => 'Désactivé', + 'n/a' => 'Non établie', + }, + }, + 'AntiAliasStrength' => 'Puissance relative du filtre anticrénelage de l\'appareil', + 'Aperture' => 'Ouverture', + 'ApertureRange' => { + Description => 'Régler gamme d\'ouvertures', + PrintConv => { + 'Disable' => 'Désactivé', + 'Enable' => 'Activée', + }, + }, + 'ApertureRingUse' => { + Description => 'Utilisation de la bague de diaphragme', + PrintConv => { + 'Permitted' => 'Autorisée', + 'Prohibited' => 'Interdite', + }, + }, + 'ApertureValue' => 'Ouverture', + 'ApplicationRecordVersion' => 'Version d\'enregistrement', + 'ApplyShootingMeteringMode' => { + Description => 'Appliquer mode de prise de vue/de mesure', + PrintConv => { + 'Disable' => 'Désactivé', + 'Enable' => 'Activée', + }, + }, + 'Artist' => 'Artiste', + 'ArtworkCopyrightNotice' => 'Notice copyright de l\'Illustration', + 'ArtworkCreator' => 'Créateur de l\'Illustration', + 'ArtworkDateCreated' => 'Date de création de l\'Illustration', + 'ArtworkSource' => 'Source de l\'Illustration', + 'ArtworkSourceInventoryNo' => 'No d\'Inventaire du source de l\'Illustration', + 'ArtworkTitle' => 'Titre de l\'Illustration', + 'AsShotICCProfile' => 'Profil ICC à la prise de vue', + 'AsShotNeutral' => 'Balance neutre à la prise de vue', + 'AsShotPreProfileMatrix' => 'Matrice de pré-profil à la prise de vue', + 'AsShotProfileName' => 'Nom du profil du cliché', + 'AsShotWhiteXY' => 'Balance blanc X-Y à la prise de vue', + 'AssignFuncButton' => { + Description => 'Changer fonct. touche FUNC.', + PrintConv => { + 'Exposure comp./AEB setting' => 'Correct. expo/réglage AEB', + 'Image jump with main dial' => 'Saut image par molette principale', + 'Image quality' => 'Changer de qualité', + 'LCD brightness' => 'Luminosité LCD', + 'Live view function settings' => 'Réglages Visée par l’écran', + }, + }, + 'AssistButtonFunction' => { + Description => 'Touche de fonction rapide', + PrintConv => { + 'Av+/- (AF point by QCD)' => 'Av+/- (AF par mol. AR)', + 'FE lock' => 'Mémo expo. au flash', + 'Normal' => 'Normale', + 'Select HP (while pressing)' => 'Sélect. HP (en appuyant)', + 'Select Home Position' => 'Sélect. position origine', + }, + }, + 'Audio' => { + PrintConv => { + 'No' => 'Non', + 'Yes' => 'Oui', + }, + }, + 'AudioDuration' => 'Durée audio', + 'AudioOutcue' => 'Queue audio', + 'AudioSamplingRate' => 'Taux d\'échantillonnage audio', + 'AudioSamplingResolution' => 'Résolution d\'échantillonnage audio', + 'AudioType' => { + Description => 'Type audio', + PrintConv => { + 'Mono Actuality' => 'Actualité (audio mono (1 canal))', + 'Mono Music' => 'Musique, transmise par elle-même (audio mono (1 canal))', + 'Mono Question and Answer Session' => 'Question et réponse (audio mono (1 canal))', + 'Mono Raw Sound' => 'Son brut (audio mono (1 canal))', + 'Mono Response to a Question' => 'Réponse à une question (audio mono (1 canal))', + 'Mono Scener' => 'Scener (audio mono (1 canal))', + 'Mono Voicer' => 'Voix (audio mono (1 canal))', + 'Mono Wrap' => 'Wrap (audio mono (1 canal))', + 'Stereo Actuality' => 'Actualité (audio stéréo (2 canaux))', + 'Stereo Music' => 'Musique, transmise par elle-même (audio stéréo (2 canaux))', + 'Stereo Question and Answer Session' => 'Question et réponse (audio stéréo (2 canaux))', + 'Stereo Raw Sound' => 'Son brut (audio stéréo (2 canaux))', + 'Stereo Response to a Question' => 'Réponse à une question (audio stéréo (2 canaux))', + 'Stereo Scener' => 'Scener (audio stéréo (2 canaux))', + 'Stereo Voicer' => 'Voix (audio stéréo (2 canaux))', + 'Stereo Wrap' => 'Wrap (audio stéréo (2 canaux))', + 'Text Only' => 'Texte seul (pas de données d\'objet)', + }, + }, + 'Author' => 'Auteur', + 'AuthorsPosition' => 'Titre du créateur', + 'AutoAperture' => { + Description => 'Auto-diaph', + PrintConv => { + 'Off' => 'Désactivé', + 'On' => 'Activé', + }, + }, + 'AutoBracketing' => { + Description => 'Bracketing auto', + PrintConv => { + 'Off' => 'Désactivé', + 'On' => 'Activé', + }, + }, + 'AutoExposureBracketing' => { + PrintConv => { + 'Off' => 'Désactivé', + 'On' => 'Activé', + }, + }, + 'AutoFP' => { + PrintConv => { + 'Off' => 'Désactivé', + 'On' => 'Activé', + }, + }, + 'AutoFocus' => { + Description => 'Auto-Focus', + PrintConv => { + 'Off' => 'Désactivé', + 'On' => 'Activé', + }, + }, + 'AutoISO' => { + PrintConv => { + 'Off' => 'Désactivé', + 'On' => 'Activé', + }, + }, + 'AutoLightingOptimizer' => { + Description => 'Correction auto de luminosité', + PrintConv => { + 'Disable' => 'Désactivé', + 'Enable' => 'Actif', + 'Low' => 'Faible', + 'Off' => 'Désactivé', + 'Strong' => 'Importante', + 'n/a' => 'Non établie', + }, + }, + 'AutoLightingOptimizerOn' => { + PrintConv => { + 'No' => 'Non', + 'Yes' => 'Oui', + }, + }, + 'AutoRedEye' => { + PrintConv => { + 'Off' => 'Désactivé', + 'On' => 'Activé', + }, + }, + 'AutoRotate' => { + Description => 'Rotation automatique', + PrintConv => { + 'None' => 'Aucune', + 'Rotate 180' => '180° (bas/droit)', + 'Rotate 270 CW' => '90° sens horaire (gauche/bas)', + 'Rotate 90 CW' => '90° sens antihoraire (droit/haut)', + 'n/a' => 'Inconnu', + }, + }, + 'AuxiliaryLens' => 'Objectif Auxiliaire', + 'AvApertureSetting' => 'Réglage d\'ouverture Av', + 'AvSettingWithoutLens' => { + Description => 'Réglage Av sans objectif', + PrintConv => { + 'Disable' => 'Désactivé', + 'Enable' => 'Activé', + }, + }, + 'BToA0' => 'B à A0', + 'BToA1' => 'B à A1', + 'BToA2' => 'B à A2', + 'BWMode' => { + PrintConv => { + 'Off' => 'Désactivé', + 'On' => 'Activé', + }, + }, + 'BackgroundColorIndicator' => 'Indicateur de couleur d\'arrière-plan', + 'BackgroundColorValue' => 'Valeur de couleur d\'arrière-plan', + 'BackgroundTiling' => { + PrintConv => { + 'No' => 'Non', + 'Yes' => 'Oui', + }, + }, + 'BadFaxLines' => 'Mauvaises lignes de Fax', + 'BannerImageType' => { + PrintConv => { + 'None' => 'Aucune', + }, + }, + 'BaseExposureCompensation' => 'Compensation d\'exposition de base', + 'BaseURL' => 'URL de base', + 'BaselineExposure' => 'Exposition de base', + 'BaselineNoise' => 'Bruit de base', + 'BaselineSharpness' => 'Accentuation de base', + 'BatteryInfo' => 'Source d\'alimentation', + 'BatteryLevel' => 'Niveau de batterie', + 'BayerGreenSplit' => 'Séparation de vert Bayer', + 'Beep' => { + PrintConv => { + 'High' => 'Bruyant', + 'Low' => 'Calme', + 'Off' => 'Désactivé', + 'On' => 'Activé', + }, + }, + 'BestQualityScale' => 'Echelle de meilleure qualité', + 'BitsPerComponent' => 'Bits par composante', + 'BitsPerExtendedRunLength' => 'Bits par « Run Length » étendue', + 'BitsPerRunLength' => 'Bits par « Run Length »', + 'BitsPerSample' => 'Nombre de bits par échantillon', + 'BlackLevel' => 'Niveau noir', + 'BlackLevelDeltaH' => 'Delta H du niveau noir', + 'BlackLevelDeltaV' => 'Delta V du niveau noir', + 'BlackLevelRepeatDim' => 'Dimension de répétition du niveau noir', + 'BlackPoint' => 'Point noir', + 'BlueBalance' => 'Balance bleue', + 'BlueMatrixColumn' => 'Colonne de matrice bleue', + 'BlueTRC' => 'Courbe de reproduction des tons bleus', + 'BlurWarning' => { + PrintConv => { + 'None' => 'Aucune', + }, + }, + 'BodyBatteryADLoad' => 'Tension accu boîtier en charge', + 'BodyBatteryADNoLoad' => 'Tension accu boîtier à vide', + 'BodyBatteryState' => { + Description => 'État de accu boîtier', + PrintConv => { + 'Almost Empty' => 'Presque vide', + 'Empty or Missing' => 'Vide ou absent', + 'Full' => 'Plein', + 'Running Low' => 'En baisse', + }, + }, + 'BracketMode' => { + PrintConv => { + 'Off' => 'Désactivé', + }, + }, + 'BracketShotNumber' => { + Description => 'Numéro de cliché en bracketing', + PrintConv => { + '1 of 3' => '1 sur 3', + '1 of 5' => '1 sur 5', + '2 of 3' => '2 sur 3', + '2 of 5' => '2 sur 5', + '3 of 3' => '3 sur 3', + '3 of 5' => '3 sur 5', + '4 of 5' => '4 sur 5', + '5 of 5' => '5 sur 5', + 'n/a' => 'Non établie', + }, + }, + 'Brightness' => 'Luminosité', + 'BrightnessValue' => 'Luminosité', + 'BulbDuration' => 'Durée du pose longue', + 'BurstMode' => { + Description => 'Mode Rafale', + PrintConv => { + 'Infinite' => 'Infini', + 'Off' => 'Désactivé', + 'On' => 'Activé', + }, + }, + 'ButtonFunctionControlOff' => { + Description => 'Fonction de touche si Contrôle Rapide OFF', + PrintConv => { + 'Disable main, Control, Multi-control' => 'Désactivés principale, Contrôle rapide, Multicontrôleur', + 'Normal (enable)' => 'Normale (activée)', + }, + }, + 'By-line' => 'Créateur', + 'By-lineTitle' => 'Fonction du créateur', + 'CFALayout' => { + Description => 'Organisation CFA', + PrintConv => { + 'Even columns offset down 1/2 row' => 'Organisation décalée A : les colonnes paires sont décalées vers le bas d\'une demi-rangée.', + 'Even columns offset up 1/2 row' => 'Organisation décalée B : les colonnes paires sont décalées vers le haut d\'une demi-rangée.', + 'Even rows offset left 1/2 column' => 'Organisation décalée D : les rangées paires sont décalées vers la gauche d\'une demi-colonne.', + 'Even rows offset right 1/2 column' => 'Organisation décalée C : les rangées paires sont décalées vers la droite d\'une demi-colonne.', + 'Rectangular' => 'Plan rectangulaire (ou carré)', + }, + }, + 'CFAPattern' => 'Matrice de filtrage couleur', + 'CFAPattern2' => 'Modèle CFA 2', + 'CFAPlaneColor' => 'Couleur de plan CFA', + 'CFARepeatPatternDim' => 'Dimension du modèle de répétition CFA', + 'CMMFlags' => 'Drapeaux CMM', + 'CMYKEquivalent' => 'Equivalent CMJK', + 'CPUFirmwareVersion' => 'Version de firmware de CPU', + 'CPUType' => { + PrintConv => { + 'None' => 'Aucune', + }, + }, + 'CalibrationDateTime' => 'Date et heure de calibration', + 'CalibrationIlluminant1' => { + Description => 'Illuminant de calibration 1', + PrintConv => { + 'Cloudy' => 'Temps nuageux', + 'Cool White Fluorescent' => 'Fluorescente type soft', + 'Day White Fluorescent' => 'Fluorescente type blanc', + 'Daylight' => 'Lumière du jour', + 'Daylight Fluorescent' => 'Fluorescente type jour', + 'Fine Weather' => 'Beau temps', + 'Fluorescent' => 'Fluorescente', + 'ISO Studio Tungsten' => 'Tungstène studio ISO', + 'Other' => 'Autre source de lumière', + 'Shade' => 'Ombre', + 'Standard Light A' => 'Lumière standard A', + 'Standard Light B' => 'Lumière standard B', + 'Standard Light C' => 'Lumière standard C', + 'Tungsten (Incandescent)' => 'Tungstène (lumière incandescente)', + 'Unknown' => 'Inconnue', + 'Warm White Fluorescent' => 'Fluorescent blanc chaud', + 'White Fluorescent' => 'Fluorescent blanc', + }, + }, + 'CalibrationIlluminant2' => { + Description => 'Illuminant de calibration 2', + PrintConv => { + 'Cloudy' => 'Temps nuageux', + 'Cool White Fluorescent' => 'Fluorescente type soft', + 'Day White Fluorescent' => 'Fluorescente type blanc', + 'Daylight' => 'Lumière du jour', + 'Daylight Fluorescent' => 'Fluorescente type jour', + 'Fine Weather' => 'Beau temps', + 'Fluorescent' => 'Fluorescente', + 'ISO Studio Tungsten' => 'Tungstène studio ISO', + 'Other' => 'Autre source de lumière', + 'Shade' => 'Ombre', + 'Standard Light A' => 'Lumière standard A', + 'Standard Light B' => 'Lumière standard B', + 'Standard Light C' => 'Lumière standard C', + 'Tungsten (Incandescent)' => 'Tungstène (lumière incandescente)', + 'Unknown' => 'Inconnue', + 'Warm White Fluorescent' => 'Fluorescent blanc chaud', + 'White Fluorescent' => 'Fluorescent blanc', + }, + }, + 'CameraCalibration1' => 'Calibration d\'appareil 1', + 'CameraCalibration2' => 'Calibration d\'appareil 2', + 'CameraCalibrationSig' => 'Signature de calibration de l\'appareil', + 'CameraOrientation' => { + Description => 'Orientation de l\'image', + PrintConv => { + 'Horizontal (normal)' => '0° (haut/gauche)', + 'Rotate 270 CW' => '90° sens horaire (gauche/bas)', + 'Rotate 90 CW' => '90° sens antihoraire (droit/haut)', + }, + }, + 'CameraSerialNumber' => 'Numéro de série de l\'appareil', + 'CameraSettings' => 'Réglages de l\'appareil', + 'CameraTemperature' => 'Température de l\'appareil', + 'CameraType' => 'Type d\'objectif Pentax', + 'CanonExposureMode' => { + PrintConv => { + 'Aperture-priority AE' => 'Priorité ouverture', + 'Bulb' => 'Pose B', + 'Manual' => 'Manuelle', + 'Program AE' => 'Programme d\'exposition automatique', + 'Shutter speed priority AE' => 'Priorité vitesse', + }, + }, + 'CanonFirmwareVersion' => 'Version de firmware', + 'CanonFlashMode' => { + PrintConv => { + 'Off' => 'Désactivé', + 'On' => 'Activé', + 'Red-eye reduction' => 'Réduction yeux rouges', + }, + }, + 'CanonImageSize' => { + PrintConv => { + 'Large' => 'Grande', + 'Medium' => 'Moyenne', + 'Medium 1' => 'Moyenne 1', + 'Medium 2' => 'Moyenne 2', + 'Medium 3' => 'Moyenne 3', + 'Small' => 'Petite', + 'Small 1' => 'Petite 1', + 'Small 2' => 'Petite 2', + 'Small 3' => 'Petite 3', + }, + }, + 'Caption-Abstract' => 'Légende / Description', + 'CaptionWriter' => 'Rédacteur', + 'CaptureXResolutionUnit' => { + PrintConv => { + 'um' => 'µm (micromètre)', + }, + }, + 'CaptureYResolutionUnit' => { + PrintConv => { + 'um' => 'µm (micromètre)', + }, + }, + 'Categories' => 'Catégories', + 'Category' => 'Catégorie', + 'CellLength' => 'Longueur de cellule', + 'CellWidth' => 'Largeur de cellule', + 'CenterWeightedAreaSize' => { + PrintConv => { + 'Average' => 'Moyenne', + }, + }, + 'Certificate' => 'Certificat', + 'CharTarget' => 'Cible caractère', + 'CharacterSet' => 'Jeu de caractères', + 'ChromaBlurRadius' => 'Rayon de flou de chromatisme', + 'ChromaticAdaptation' => 'Adaptation chromatique', + 'Chromaticity' => 'Chromaticité', + 'ChrominanceNR_TIFF_JPEG' => { + PrintConv => { + 'Low' => 'Bas', + 'Off' => 'Désactivé', + }, + }, + 'ChrominanceNoiseReduction' => { + PrintConv => { + 'Low' => 'Bas', + 'Off' => 'Désactivé', + }, + }, + 'CircleOfConfusion' => 'Cercle de confusion', + 'City' => 'Ville', + 'ClassifyState' => 'État de classification', + 'CleanFaxData' => 'Données de Fax propres', + 'ClipPath' => 'Chemin de rognage', + 'CodedCharacterSet' => 'Jeu de caractères codé', + 'CollectionName' => 'Nom de collection', + 'ColorAberrationControl' => { + PrintConv => { + 'Off' => 'Désactivé', + 'On' => 'Activé', + }, + }, + 'ColorAdjustmentMode' => { + PrintConv => { + 'Off' => 'Désactivé', + 'On' => 'Activé', + }, + }, + 'ColorBalance' => 'Balance des couleurs', + 'ColorBalanceAdj' => { + PrintConv => { + 'Off' => 'Désactivé', + 'On' => 'Activé', + }, + }, + 'ColorBooster' => { + PrintConv => { + 'Off' => 'Désactivé', + 'On' => 'Activé', + }, + }, + 'ColorCalibrationMatrix' => 'Table de matrice de calibration de couleur', + 'ColorCharacterization' => 'Caractérisation de couleur', + 'ColorComponents' => 'Composants colorimétriques', + 'ColorEffect' => { + Description => 'Effet de couleurs', + PrintConv => { + 'Black & White' => 'Noir et blanc', + 'Cool' => 'Froide', + 'Off' => 'Désactivé', + 'Sepia' => 'Sépia', + 'Warm' => 'Chaude', + }, + }, + 'ColorFilter' => { + Description => 'Filtre de couleur', + PrintConv => { + 'Blue' => 'Bleu', + 'Green' => 'Vert', + 'Off' => 'Désactivé', + 'Red' => 'Rouge', + 'Yellow' => 'Jaune', + }, + }, + 'ColorHue' => 'Teinte de couleur', + 'ColorInfo' => 'Info couleur', + 'ColorMap' => 'Charte de couleur', + 'ColorMatrix1' => 'Matrice de couleur 1', + 'ColorMatrix2' => 'Matrice de couleur 2', + 'ColorMode' => { + Description => 'Mode colorimétrique', + PrintConv => { + 'Adobe RGB' => 'AdobeRVB', + 'Autumn Leaves' => 'Feuilles automne', + 'B&W' => 'Noir & Blanc', + 'Clear' => 'Lumineux', + 'Deep' => 'Profond', + 'Evening' => 'Soir', + 'Landscape' => 'Paysage', + 'Light' => 'Pastel', + 'Natural' => 'Naturel', + 'Neutral' => 'Neutre', + 'Night Scene' => 'Nocturne', + 'Night View' => 'Vision nocturne', + 'Night View/Portrait' => 'Portrait nocturne', + 'Normal' => 'Normale', + 'Off' => 'Désactivé', + 'RGB' => 'RVB', + 'Sunset' => 'Coucher de soleil', + 'Vivid' => 'Vives', + }, + }, + 'ColorMoireReduction' => { + PrintConv => { + 'Off' => 'Désactivé', + 'On' => 'Activé', + }, + }, + 'ColorMoireReductionMode' => { + PrintConv => { + 'Low' => 'Bas', + 'Off' => 'Désactivé', + }, + }, + 'ColorPalette' => 'Palette de couleur', + 'ColorRepresentation' => { + Description => 'Représentation de couleur', + PrintConv => { + '3 Components, Frame Sequential in Multiple Objects' => 'Trois composantes, Vue séquentielle dans différents objets', + '3 Components, Frame Sequential in One Object' => 'Trois composantes, Vue séquentielle dans un objet', + '3 Components, Line Sequential' => 'Trois composantes, Ligne séquentielle', + '3 Components, Pixel Sequential' => 'Trois composantes, Pixel séquentiel', + '3 Components, Single Frame' => 'Trois composantes, Vue unique', + '3 Components, Special Interleaving' => 'Trois composantes, Entrelacement spécial', + '4 Components, Frame Sequential in Multiple Objects' => 'Quatre composantes, Vue séquentielle dans différents objets', + '4 Components, Frame Sequential in One Object' => 'Quatre composantes, Vue séquentielle dans un objet', + '4 Components, Line Sequential' => 'Quatre composantes, Ligne séquentielle', + '4 Components, Pixel Sequential' => 'Quatre composantes, Pixel séquentiel', + '4 Components, Single Frame' => 'Quatre composantes, Vue unique', + '4 Components, Special Interleaving' => 'Quatre composantes, Entrelacement spécial', + 'Monochrome, Single Frame' => 'Monochrome, Vue unique', + 'No Image, Single Frame' => 'Pas d\'image, Vue unique', + }, + }, + 'ColorResponseUnit' => 'Unité de réponse couleur', + 'ColorSequence' => 'Séquence de couleur', + 'ColorSpace' => { + Description => 'Espace colorimétrique', + PrintConv => { + 'ICC Profile' => 'Profil ICC', + 'RGB' => 'RVB', + 'Uncalibrated' => 'Non calibré', + 'Wide Gamut RGB' => 'Wide Gamut RVB', + 'sRGB' => 'sRVB', + }, + }, + 'ColorSpaceData' => 'Espace de couleur de données', + 'ColorTable' => 'Tableau de couleurs', + 'ColorTemperature' => 'Température de couleur', + 'ColorTone' => { + Description => 'Teinte couleur', + PrintConv => { + 'Normal' => 'Normale', + }, + }, + 'ColorType' => { + PrintConv => { + 'RGB' => 'RVB', + }, + }, + 'ColorantOrder' => 'Ordre de colorant', + 'ColorantTable' => 'Table de colorant', + 'ColorimetricReference' => 'Référence colorimétrique', + 'CommandDialsChangeMainSub' => { + PrintConv => { + 'Off' => 'Désactivé', + 'On' => 'Activé', + }, + }, + 'CommandDialsMenuAndPlayback' => { + PrintConv => { + 'Off' => 'Désactivé', + 'On' => 'Activé', + }, + }, + 'CommandDialsReverseRotation' => { + PrintConv => { + 'No' => 'Non', + 'Yes' => 'Oui', + }, + }, + 'CommanderGroupAMode' => { + PrintConv => { + 'Manual' => 'Manuelle', + 'Off' => 'Désactivé', + }, + }, + 'CommanderGroupBMode' => { + PrintConv => { + 'Manual' => 'Manuelle', + 'Off' => 'Désactivé', + }, + }, + 'CommanderInternalFlash' => { + PrintConv => { + 'Manual' => 'Manuelle', + 'Off' => 'Désactivé', + }, + }, + 'Comment' => 'Commentaire', + 'Comments' => 'Commentaires', + 'Compilation' => { + PrintConv => { + 'No' => 'Non', + 'Yes' => 'Oui', + }, + }, + 'ComponentsConfiguration' => 'Signification de chaque composante', + 'CompressedBitsPerPixel' => 'Mode de compression d\'image', + 'Compression' => { + Description => 'Schéma de compression', + PrintConv => { + 'JBIG Color' => 'JBIG Couleur', + 'JPEG' => 'Compression JPEG', + 'JPEG (old-style)' => 'JPEG (ancien style)', + 'Kodak DCR Compressed' => 'Compression Kodak DCR', + 'Kodak KDC Compressed' => 'Compression Kodak KDC', + 'Next' => 'Encodage NeXT 2 bits', + 'Nikon NEF Compressed' => 'Compression Nikon NEF', + 'None' => 'Aucune', + 'Pentax PEF Compressed' => 'Compression Pentax PEF', + 'SGILog' => 'Encodage Log luminance SGI 32 bits', + 'SGILog24' => 'Encodage Log luminance SGI 24 bits', + 'Sony ARW Compressed' => 'Compression Sony ARW', + 'Thunderscan' => 'Encodage ThunderScan 4 bits', + 'Uncompressed' => 'Non compressé', + }, + }, + 'CompressionType' => { + PrintConv => { + 'None' => 'Aucune', + }, + }, + 'ConditionalFEC' => 'Compensation exposition flash', + 'ConnectionSpaceIlluminant' => 'Illuminant d\'espace de connexion', + 'ConsecutiveBadFaxLines' => 'Mauvaises lignes de Fax consécutives', + 'ContentLocationCode' => 'Code du lieu du contenu', + 'ContentLocationName' => 'Nom du lieu du contenu', + 'ContinuousDrive' => { + PrintConv => { + 'Movie' => 'Vidéo', + }, + }, + 'ContinuousShootingSpeed' => { + Description => 'Vitesse de prise de vues en continu', + PrintConv => { + 'Disable' => 'Désactivé', + 'Enable' => 'Activée', + }, + }, + 'ContinuousShotLimit' => { + Description => 'Limiter nombre de vues en continu', + PrintConv => { + 'Disable' => 'Désactivé', + 'Enable' => 'Activée', + }, + }, + 'Contrast' => { + Description => 'Contraste', + PrintConv => { + '+1 (medium high)' => '+1 (Assez fort)', + '+2 (high)' => '+2 (Forte)', + '+3 (very high)' => '+3 (Très fort)', + '-1 (medium low)' => '-1 (Assez faible)', + '-2 (low)' => '-2 (Faible)', + '-3 (very low)' => '-3 (Très faible)', + '0 (normal)' => '0 (Normale)', + 'High' => 'Dur', + 'Low' => 'Doux', + 'Medium High' => 'Moyen Haut', + 'Medium Low' => 'Moyen Faible', + 'Normal' => 'Normale', + 'n/a' => 'Non établie', + }, + }, + 'ContrastCurve' => 'Courbe de contraste', + 'Contributor' => 'Contributeur', + 'ControlMode' => { + PrintConv => { + 'n/a' => 'Non établie', + }, + }, + 'ConversionLens' => { + Description => 'Complément Optique', + PrintConv => { + 'Off' => 'Désactivé', + 'Telephoto' => 'Télé', + 'Wide' => 'Grand angulaire', + }, + }, + 'Copyright' => 'Propriétaire du copyright', + 'CopyrightNotice' => 'Mention de copyright', + 'CopyrightStatus' => { + PrintConv => { + 'Unknown' => 'Inconnu', + }, + }, + 'Country' => 'Pays', + 'Country-PrimaryLocationCode' => 'Code de pays ISO', + 'Country-PrimaryLocationName' => 'Pays', + 'CountryCode' => 'Code pays', + 'Coverage' => 'Couverture', + 'CreateDate' => 'Date de la création des données numériques', + 'CreationDate' => 'Date de création', + 'Creator' => 'Créateur', + 'CreatorAddress' => 'Adresse du créateur', + 'CreatorCity' => 'Lieu d\'Habitation du créateur', + 'CreatorContactInfo' => 'Contact créateur', + 'CreatorCountry' => 'Pays du créateur', + 'CreatorPostalCode' => 'Code postal du créateur', + 'CreatorRegion' => 'Région du créateur', + 'CreatorTool' => 'Outil de création', + 'CreatorWorkEmail' => 'Courriel professionnel du créateur', + 'CreatorWorkTelephone' => 'Téléphone professionnel créateur', + 'CreatorWorkURL' => 'URL professionnelle du créateur', + 'Credit' => 'Fournisseur', + 'CropActive' => { + PrintConv => { + 'No' => 'Non', + 'Yes' => 'Oui', + }, + }, + 'CropUnit' => { + PrintConv => { + 'inches' => 'Pouce', + }, + }, + 'CropUnits' => { + PrintConv => { + 'inches' => 'Pouce', + }, + }, + 'CurrentICCProfile' => 'Profil ICC actuel', + 'CurrentIPTCDigest' => 'Sommaire courant IPTC', + 'CurrentPreProfileMatrix' => 'Matrice de pré-profil actuelle', + 'Curves' => { + PrintConv => { + 'Off' => 'Désactivé', + 'On' => 'Activé', + }, + }, + 'CustomRendered' => { + Description => 'Traitement d\'image personnalisé', + PrintConv => { + 'Custom' => 'Traitement personnalisé', + 'Normal' => 'Traitement normal', + }, + }, + 'D-LightingHQ' => { + PrintConv => { + 'Off' => 'Désactivé', + 'On' => 'Activé', + }, + }, + 'D-LightingHQSelected' => { + PrintConv => { + 'No' => 'Non', + 'Yes' => 'Oui', + }, + }, + 'D-LightingHS' => { + PrintConv => { + 'Off' => 'Désactivé', + 'On' => 'Activé', + }, + }, + 'DNGBackwardVersion' => 'Version DNG antérieure', + 'DNGLensInfo' => 'Distance focale minimale', + 'DNGVersion' => 'Version DNG', + 'DOF' => 'Profondeur de champ', + 'DSPFirmwareVersion' => 'Version de firmware de DSP', + 'DataCompressionMethod' => 'Fournisseur/propriétaire de l\'algorithme de compression de données', + 'DataDump' => 'Vidage données', + 'DataImprint' => { + PrintConv => { + 'None' => 'Aucune', + 'Text' => 'Texte', + }, + }, + 'DataType' => 'Type de données', + 'DateCreated' => 'Date de création', + 'DateDisplayFormat' => { + Description => 'Format date', + PrintConv => { + 'D/M/Y' => 'Jour/Mois/Année', + 'M/D/Y' => 'Mois/Jour/Année', + 'Y/M/D' => 'Année/Mois/Jour', + }, + }, + 'DateSent' => 'Date d\'envoi', + 'DateStampMode' => { + PrintConv => { + 'Date & Time' => 'Date et heure', + 'Off' => 'Désactivé', + }, + }, + 'DateTime' => 'Date de modification du fichier', + 'DateTimeCreated' => 'Date/heure de création', + 'DateTimeDigitized' => 'Date/heure de la numérisation', + 'DateTimeOriginal' => 'Date de la création des données originales', + 'DaylightSavings' => { + Description => 'Heure d\'été', + PrintConv => { + 'No' => 'Non', + 'Yes' => 'Oui', + }, + }, + 'DefaultCropOrigin' => 'Origine de rognage par défaut', + 'DefaultCropSize' => 'Taille de rognage par défaut', + 'DefaultScale' => 'Echelle par défaut', + 'DeletedImageCount' => 'Compteur d\'images supprimées', + 'DestinationCity' => 'Ville de destination', + 'DestinationCityCode' => 'Code ville de destination', + 'DestinationDST' => { + Description => 'Heure d\'été de destination', + PrintConv => { + 'No' => 'Non', + 'Yes' => 'Oui', + }, + }, + 'DeviceAttributes' => 'Attributs d\'appareil', + 'DeviceManufacturer' => 'Fabricant de l\'appareil', + 'DeviceMfgDesc' => 'Description du fabricant d\'appareil', + 'DeviceModel' => 'Modèle de l\'appareil', + 'DeviceModelDesc' => 'Description du modèle d\'appareil', + 'DeviceSettingDescription' => 'Description des réglages du dispositif', + 'DialDirectionTvAv' => { + Description => 'Sens rotation molette Tv/Av', + PrintConv => { + 'Normal' => 'Normale', + 'Reversed' => 'Sens inversé', + }, + }, + 'DigitalCreationDate' => 'Date de numérisation', + 'DigitalCreationTime' => 'Heure de numérisation', + 'DigitalImageGUID' => 'GUID de l\'image numérique', + 'DigitalSourceFileType' => 'Type de fichier de la source numérique', + 'DigitalZoom' => { + Description => 'Zoom numérique', + PrintConv => { + 'None' => 'Aucune', + 'Off' => 'Désactivé', + }, + }, + 'DigitalZoomOn' => { + PrintConv => { + 'Off' => 'Désactivé', + 'On' => 'Activé', + }, + }, + 'DigitalZoomRatio' => 'Rapport de zoom numérique', + 'Directory' => 'Dossier', + 'DirectoryNumber' => 'Numéro de dossier', + 'DisplaySize' => { + PrintConv => { + 'Normal' => 'Normale', + }, + }, + 'DisplayUnits' => { + PrintConv => { + 'inches' => 'Pouce', + }, + }, + 'DisplayXResolutionUnit' => { + PrintConv => { + 'um' => 'µm (micromètre)', + }, + }, + 'DisplayYResolutionUnit' => { + PrintConv => { + 'um' => 'µm (micromètre)', + }, + }, + 'DisplayedUnitsX' => { + PrintConv => { + 'inches' => 'Pouce', + }, + }, + 'DisplayedUnitsY' => { + PrintConv => { + 'inches' => 'Pouce', + }, + }, + 'DistortionCorrection' => { + PrintConv => { + 'Off' => 'Désactivé', + 'On' => 'Activé', + }, + }, + 'DistortionCorrection2' => { + PrintConv => { + 'Off' => 'Désactivé', + 'On' => 'Activé', + }, + }, + 'DjVuVersion' => 'Version DjVu', + 'DocumentHistory' => 'Historique du document', + 'DocumentName' => 'Nom du document', + 'DocumentNotes' => 'Remarques sur le document', + 'DotRange' => 'Étendue de points', + 'DriveMode' => { + Description => 'Mode de prise de vue', + PrintConv => { + 'Burst' => 'Rafale', + 'Continuous' => 'Continu', + 'Continuous High' => 'Continu (ultrarapide)', + 'Continuous Shooting' => 'Prise de vues en continu', + 'Multiple Exposure' => 'Exposition multiple', + 'No Timer' => 'Pas de retardateur', + 'Off' => 'Désactivé', + 'Remote Control' => 'Télécommande', + 'Remote Control (3 s delay)' => 'Télécommande (retard 3 s)', + 'Self-timer (12 s)' => 'Retardateur (12 s)', + 'Self-timer (2 s)' => 'Retardateur (2 s)', + 'Self-timer Operation' => 'Retardateur', + 'Shutter Button' => 'Déclencheur', + 'Single Exposure' => 'Exposition unique', + 'Single-frame' => 'Vue par vue', + 'Single-frame Shooting' => 'Prise de vue unique', + }, + }, + 'DriveMode2' => { + Description => 'Exposition multiple', + PrintConv => { + 'Single-frame' => 'Vue par vue', + }, + }, + 'Duration' => 'Durée', + 'DynamicRangeExpansion' => { + Description => 'Expansion de la dynamique', + PrintConv => { + 'Off' => 'Désactivé', + 'On' => 'Activé', + }, + }, + 'DynamicRangeOptimizer' => { + Description => 'Optimiseur Dyna', + PrintConv => { + 'Advanced Auto' => 'Avancé Auto', + 'Advanced Lv1' => 'Avancé Niv1', + 'Advanced Lv2' => 'Avancé Niv2', + 'Advanced Lv3' => 'Avancé Niv3', + 'Advanced Lv4' => 'Avancé Niv4', + 'Advanced Lv5' => 'Avancé Niv5', + 'Auto' => 'Auto.', + 'Off' => 'Désactivé', + }, + }, + 'E-DialInProgram' => { + PrintConv => { + 'P Shift' => 'Décalage P', + 'Tv or Av' => 'Tv ou Av', + }, + }, + 'ETTLII' => { + PrintConv => { + 'Average' => 'Moyenne', + 'Evaluative' => 'Évaluative', + }, + }, + 'EVStepInfo' => 'Info de pas IL', + 'EVSteps' => { + Description => 'Pas IL', + PrintConv => { + '1/2 EV Steps' => 'Pas de 1/2 IL', + '1/3 EV Steps' => 'Pas de 1/3 IL', + }, + }, + 'EasyExposureCompensation' => { + PrintConv => { + 'Off' => 'Désactivé', + 'On' => 'Activé', + }, + }, + 'EasyMode' => { + PrintConv => { + 'Beach' => 'Plage', + 'Color Accent' => 'Couleur contrastée', + 'Color Swap' => 'Permuter couleur', + 'Fireworks' => 'Feu d\'artifice', + 'Foliage' => 'Feuillages', + 'Indoor' => 'Intérieur', + 'Kids & Pets' => 'Enfants & animaux', + 'Landscape' => 'Paysage', + 'Manual' => 'Manuelle', + 'Night' => 'Scène de nuit', + 'Night Snapshot' => 'Mode Nuit', + 'Snow' => 'Neige', + 'Sports' => 'Sport', + 'Super Macro' => 'Super macro', + 'Underwater' => 'Sous-marin', + }, + }, + 'EdgeNoiseReduction' => { + PrintConv => { + 'Off' => 'Désactivé', + 'On' => 'Activé', + }, + }, + 'EditStatus' => 'Statut d\'édition', + 'EditorialUpdate' => { + Description => 'Mise à jour éditoriale', + PrintConv => { + 'Additional language' => 'Langues supplémentaires', + }, + }, + 'EffectiveLV' => 'Indice de lumination effectif', + 'EffectiveMaxAperture' => 'Ouverture effective maxi de l\'Objectif', + 'Emphasis' => { + PrintConv => { + 'None' => 'Aucune', + }, + }, + 'EncodingProcess' => { + Description => 'Procédé de codage', + PrintConv => { + 'Baseline DCT, Huffman coding' => 'Baseline DCT, codage Huffman', + 'Extended sequential DCT, Huffman coding' => 'Extended sequential DCT, codage Huffman', + 'Extended sequential DCT, arithmetic coding' => 'Extended sequential DCT, codage arithmétique', + 'Lossless, Differential Huffman coding' => 'Lossless, codage Huffman différentiel', + 'Lossless, Huffman coding' => 'Lossless, codage Huffman', + 'Lossless, arithmetic coding' => 'Lossless, codage arithmétique', + 'Lossless, differential arithmetic coding' => 'Lossless, codage arithmétique différentiel', + 'Progressive DCT, Huffman coding' => 'Progressive DCT, codage Huffman', + 'Progressive DCT, arithmetic coding' => 'Progressive DCT, codage arithmétique', + 'Progressive DCT, differential Huffman coding' => 'Progressive DCT, codage Huffman différentiel', + 'Progressive DCT, differential arithmetic coding' => 'Progressive DCT, codage arithmétique différentiel', + 'Sequential DCT, differential Huffman coding' => 'Sequential DCT, codage Huffman différentiel', + 'Sequential DCT, differential arithmetic coding' => 'Sequential DCT, codage arithmétique différentiel', + }, + }, + 'Encryption' => 'Chiffrage', + 'EndPoints' => 'Points de terminaison', + 'EnhanceDarkTones' => { + PrintConv => { + 'Off' => 'Désactivé', + 'On' => 'Activé', + }, + }, + 'Enhancement' => { + PrintConv => { + 'Blue' => 'Bleu', + 'Green' => 'Vert', + 'Off' => 'Désactivé', + 'Red' => 'Rouge', + }, + }, + 'EnvelopeNumber' => 'Numéro d\'enveloppe', + 'EnvelopePriority' => { + Description => 'Priorité d\'enveloppe', + PrintConv => { + '0 (reserved)' => '0 (réservé pour utilisation future)', + '1 (most urgent)' => '1 (très urgent)', + '5 (normal urgency)' => '5 (normalement urgent)', + '8 (least urgent)' => '8 (moins urgent)', + '9 (user-defined priority)' => '9 (priorité définie par l\'utilisateur)', + }, + }, + 'EnvelopeRecordVersion' => 'Version d\'enregistrement', + 'Error' => 'Erreur', + 'Event' => 'Evenement', + 'ExcursionTolerance' => { + Description => 'Tolérance d\'excursion ', + PrintConv => { + 'Allowed' => 'Possible', + 'Not Allowed' => 'Non permis (défaut)', + }, + }, + 'ExifByteOrder' => 'Indicateur d\'ordre des octets Exif', + 'ExifCameraInfo' => 'Info d\'appareil photo Exif', + 'ExifImageHeight' => 'Hauteur d\'image', + 'ExifImageWidth' => 'Largeur d\'image', + 'ExifOffset' => 'Pointeur Exif IFD', + 'ExifToolVersion' => 'Version ExifTool', + 'ExifUnicodeByteOrder' => 'Indicateur d\'ordre des octets Unicode Exif', + 'ExifVersion' => 'Version Exif', + 'ExitPupilPosition' => 'Position de la pupille de sortie', + 'ExpandFilm' => 'Extension film', + 'ExpandFilterLens' => 'Extension lentille filtre', + 'ExpandFlashLamp' => 'Extension lampe flash', + 'ExpandLens' => 'Extension objectif', + 'ExpandScanner' => 'Extension Scanner', + 'ExpandSoftware' => 'Extension logiciel', + 'ExpirationDate' => 'Date d\'expiration', + 'ExpirationTime' => 'Heure d\'expiration', + 'ExposureBracketStepSize' => 'Intervalle de bracketing d\'exposition', + 'ExposureBracketValue' => 'Valeur Bracketing Expo', + 'ExposureCompensation' => 'Décalage d\'exposition', + 'ExposureDelayMode' => { + PrintConv => { + 'Off' => 'Désactivé', + 'On' => 'Activé', + }, + }, + 'ExposureDifference' => 'Correction d\'exposition', + 'ExposureIndex' => 'Indice d\'exposition', + 'ExposureLevelIncrements' => { + Description => 'Paliers de réglage d\'expo', + PrintConv => { + '1-stop set, 1/3-stop comp.' => 'Réglage 1 valeur, correction 1/3 val.', + '1/2 Stop' => 'Palier 1/2', + '1/2-stop set, 1/2-stop comp.' => 'Réglage 1/2 valeur, correction 1/2 val.', + '1/3 Stop' => 'Palier 1/3', + '1/3-stop set, 1/3-stop comp.' => 'Réglage 1/3 valeur, correction 1/3 val.', + }, + }, + 'ExposureMode' => { + Description => 'Mode d\'exposition', + PrintConv => { + 'Aperture Priority' => 'Priorité ouverture', + 'Aperture-priority AE' => 'Priorité ouverture', + 'Auto' => 'Exposition automatique', + 'Auto bracket' => 'Bracketting auto', + 'Bulb' => 'Pose B', + 'Landscape' => 'Paysage', + 'Manual' => 'Exposition manuelle', + 'Night Scene / Twilight' => 'Nocturne', + 'Shutter Priority' => 'Priorité vitesse', + 'Shutter speed priority AE' => 'Priorité vitesse', + }, + }, + 'ExposureModeInManual' => { + Description => 'Mode d\'exposition manuelle', + PrintConv => { + 'Center-weighted average' => 'Centrale pondérée', + 'Evaluative metering' => 'Mesure évaluativ', + 'Partial metering' => 'Partielle', + 'Specified metering mode' => 'Mode de mesure spécifié', + 'Spot metering' => 'Spot', + }, + }, + 'ExposureProgram' => { + Description => 'Programme d\'exposition', + PrintConv => { + 'Action (High speed)' => 'Programme action (orienté grandes vitesses d\'obturation)', + 'Aperture Priority' => 'Priorité ouverture', + 'Aperture-priority AE' => 'Priorité ouverture', + 'Creative (Slow speed)' => 'Programme créatif (orienté profondeur de champ)', + 'Landscape' => 'Mode paysage', + 'Manual' => 'Manuel', + 'Not Defined' => 'Non défini', + 'Portrait' => 'Mode portrait', + 'Program AE' => 'Programme normal', + 'Shutter Priority' => 'Priorité vitesse', + 'Shutter speed priority AE' => 'Priorité vitesse', + }, + }, + 'ExposureTime' => 'Temps de pose', + 'ExposureTime2' => 'Temps de pose 2', + 'ExtendedWBDetect' => { + PrintConv => { + 'Off' => 'Désactivé', + 'On' => 'Activé', + }, + }, + 'ExtenderStatus' => { + PrintConv => { + 'Attached' => 'Attaché', + 'Not attached' => 'Non attaché', + 'Removed' => 'Retiré', + }, + }, + 'ExternalFlash' => { + PrintConv => { + 'Off' => 'Désactivé', + 'On' => 'Activé', + }, + }, + 'ExternalFlashBounce' => { + Description => 'Réflexion flash externe', + PrintConv => { + 'Bounce' => 'Avec réflecteur', + 'No' => 'Non', + 'Yes' => 'Oui', + 'n/a' => 'Non établie', + }, + }, + 'ExternalFlashExposureComp' => { + Description => 'Compensation d\'exposition flash externe', + PrintConv => { + '-0.5' => '-0.5 IL', + '-1.0' => '-1.0 IL', + '-1.5' => '-1.5 IL', + '-2.0' => '-2.0 IL', + '-2.5' => '-2.5 IL', + '-3.0' => '-3.0 IL', + '0.0' => '0.0 IL', + '0.5' => '0.5 IL', + '1.0' => '1.0 IL', + 'n/a' => 'Non établie (éteint ou modes auto)', + 'n/a (Manual Mode)' => 'Non établie (mode manuel)', + }, + }, + 'ExternalFlashGuideNumber' => 'Nombre guide flash externe', + 'ExternalFlashMode' => { + Description => 'Segment de mesure flash esclave 3', + PrintConv => { + 'Off' => 'Désactivé', + 'On, Auto' => 'En service, auto', + 'On, Contrast-control Sync' => 'En service, synchro contrôle des contrastes', + 'On, Flash Problem' => 'En service, problème de flash', + 'On, High-speed Sync' => 'En service, synchro haute vitesse', + 'On, Manual' => 'En service, manuel', + 'On, P-TTL Auto' => 'En service, auto P-TTL', + 'On, Wireless' => 'En service, sans cordon', + 'On, Wireless, High-speed Sync' => 'En service, sans cordon, synchro haute vitesse', + 'n/a - Off-Auto-Aperture' => 'N/c - auto-diaph hors service', + }, + }, + 'ExtraSamples' => 'Echantillons supplémentaires', + 'FNumber' => 'Nombre F', + 'FOV' => 'Champ de vision', + 'FaceOrientation' => { + PrintConv => { + 'Horizontal (normal)' => '0° (haut/gauche)', + 'Rotate 180' => '180° (bas/droit)', + 'Rotate 270 CW' => '90° sens horaire (gauche/bas)', + 'Rotate 90 CW' => '90° sens antihoraire (droit/haut)', + }, + }, + 'FastSeek' => { + PrintConv => { + 'No' => 'Non', + 'Yes' => 'Oui', + }, + }, + 'FaxProfile' => { + PrintConv => { + 'Unknown' => 'Inconnu', + }, + }, + 'FaxRecvParams' => 'Paramètres de réception Fax', + 'FaxRecvTime' => 'Temps de réception Fax', + 'FaxSubAddress' => 'Sous-adresse Fax', + 'FileFormat' => 'Format de fichier', + 'FileInfo' => 'Infos Fichier', + 'FileInfoVersion' => 'Version des Infos Fichier', + 'FileModifyDate' => 'Date/heure de modification du fichier', + 'FileName' => 'Nom de fichier', + 'FileNumber' => 'Numéro de fichier', + 'FileNumberMemory' => { + PrintConv => { + 'Off' => 'Désactivé', + 'On' => 'Activé', + }, + }, + 'FileNumberSequence' => { + PrintConv => { + 'Off' => 'Désactivé', + 'On' => 'Activé', + }, + }, + 'FileSize' => 'Taille du fichier', + 'FileSource' => { + Description => 'Source du fichier', + PrintConv => { + 'Digital Camera' => 'Appareil photo numérique', + 'Film Scanner' => 'Scanner de film', + 'Reflection Print Scanner' => 'Scanner par réflexion', + }, + }, + 'FileType' => 'Type de fichier', + 'FileVersion' => 'Version de format de fichier', + 'Filename' => 'Nom du fichier ', + 'FillFlashAutoReduction' => { + Description => 'Mesure E-TTL', + PrintConv => { + 'Disable' => 'Désactivé', + 'Enable' => 'Activé', + }, + }, + 'FillOrder' => { + Description => 'Ordre de remplissage', + PrintConv => { + 'Normal' => 'Normale', + }, + }, + 'FilmMode' => { + Description => 'Mode Film', + PrintConv => { + 'Dynamic (B&W)' => 'Vives (N & Bà)', + 'Dynamic (color)' => 'Couleurs vives', + 'Nature (color)' => 'Couleurs naturelles', + 'Smooth (B&W)' => 'Pastel (N & B)', + 'Smooth (color)' => 'Couleurs pastel', + 'Standard (B&W)' => 'Normales (N & B)', + 'Standard (color)' => 'Couleurs normales', + }, + }, + 'FilterEffect' => { + Description => 'Effet de filtre', + PrintConv => { + 'Green' => 'Vert', + 'None' => 'Aucune', + 'Off' => 'Désactivé', + 'Red' => 'Rouge', + 'Yellow' => 'Jaune', + 'n/a' => 'Non établie', + }, + }, + 'FilterEffectMonochrome' => { + PrintConv => { + 'Green' => 'Vert', + 'None' => 'Aucune', + 'Red' => 'Rouge', + 'Yellow' => 'Jaune', + }, + }, + 'FinderDisplayDuringExposure' => { + Description => 'Affich. viseur pendant expo.', + PrintConv => { + 'Off' => 'Désactivé', + 'On' => 'Activé', + }, + }, + 'FirmwareVersion' => 'Version de firmware', + 'FixtureIdentifier' => 'Identificateur d\'installation', + 'Flash' => { + Description => 'Flash ', + PrintConv => { + 'Auto, Did not fire' => 'Flash non déclenché, mode auto', + 'Auto, Did not fire, Red-eye reduction' => 'Auto, flash non déclenché, mode réduction yeux rouges', + 'Auto, Fired' => 'Flash déclenché, mode auto', + 'Auto, Fired, Red-eye reduction' => 'Flash déclenché, mode auto, mode réduction yeux rouges, lumière renvoyée détectée', + 'Auto, Fired, Red-eye reduction, Return detected' => 'Flash déclenché, mode auto, lumière renvoyée détectée, mode réduction yeux rouges', + 'Auto, Fired, Red-eye reduction, Return not detected' => 'Flash déclenché, mode auto, lumière renvoyée non détectée, mode réduction yeux rouges', + 'Auto, Fired, Return detected' => 'Flash déclenché, mode auto, lumière renvoyée détectée', + 'Auto, Fired, Return not detected' => 'Flash déclenché, mode auto, lumière renvoyée non détectée', + 'Did not fire' => 'Flash non déclenché', + 'Fired' => 'Flash déclenché', + 'Fired, Red-eye reduction' => 'Flash déclenché, mode réduction yeux rouges', + 'Fired, Red-eye reduction, Return detected' => 'Flash déclenché, mode réduction yeux rouges, lumière renvoyée détectée', + 'Fired, Red-eye reduction, Return not detected' => 'Flash déclenché, mode réduction yeux rouges, lumière renvoyée non détectée', + 'Fired, Return detected' => 'Lumière renvoyée sur le capteur détectée', + 'Fired, Return not detected' => 'Lumière renvoyée sur le capteur non détectée', + 'No Flash' => 'Flash non déclenché', + 'No flash function' => 'Pas de fonction flash', + 'Off' => 'Désactivé', + 'Off, Did not fire' => 'Flash non déclenché, mode flash forcé', + 'Off, Did not fire, Return not detected' => 'Éteint, flash non déclenché, lumière renvoyée non détectée', + 'Off, No flash function' => 'Éteint, pas de fonction flash', + 'Off, Red-eye reduction' => 'Éteint, mode réduction yeux rouges', + 'On' => 'Activé', + 'On, Did not fire' => 'Hors service, flash non déclenché', + 'On, Fired' => 'Flash déclenché, mode flash forcé', + 'On, Red-eye reduction' => 'Flash déclenché, mode forcé, mode réduction yeux rouges', + 'On, Red-eye reduction, Return detected' => 'Flash déclenché, mode forcé, mode réduction yeux rouges, lumière renvoyée détectée', + 'On, Red-eye reduction, Return not detected' => 'Flash déclenché, mode forcé, mode réduction yeux rouges, lumière renvoyée non détectée', + 'On, Return detected' => 'Flash déclenché, mode flash forcé, lumière renvoyée détectée', + 'On, Return not detected' => 'Flash déclenché, mode flash forcé, lumière renvoyée non détectée', + }, + }, + 'FlashBias' => 'Décalage Flash', + 'FlashCommanderMode' => { + PrintConv => { + 'Off' => 'Désactivé', + 'On' => 'Activé', + }, + }, + 'FlashCompensation' => 'Compensation flash', + 'FlashControlMode' => { + Description => 'Mode de Contrôle du Flash', + PrintConv => { + 'Manual' => 'Manuelle', + 'Off' => 'Désactivé', + }, + }, + 'FlashDevice' => { + PrintConv => { + 'None' => 'Aucune', + }, + }, + 'FlashEnergy' => 'Énergie du flash', + 'FlashExposureBracketValue' => 'Valeur Bracketing Flash', + 'FlashExposureComp' => 'Compensation d\'exposition au flash', + 'FlashExposureCompSet' => 'Réglage de compensation d\'exposition au flash', + 'FlashExposureLock' => { + PrintConv => { + 'Off' => 'Désactivé', + 'On' => 'Activé', + }, + }, + 'FlashFired' => { + Description => 'Flash utilisé', + PrintConv => { + 'No' => 'Non', + 'Yes' => 'Oui', + }, + }, + 'FlashFiring' => { + Description => 'Émission de l\'éclair', + PrintConv => { + 'Does not fire' => 'Désactivé', + 'Fires' => 'Activé', + }, + }, + 'FlashFocalLength' => 'Focale Flash', + 'FlashFunction' => 'Fonction flash', + 'FlashGroupAControlMode' => { + PrintConv => { + 'Manual' => 'Manuelle', + 'Off' => 'Désactivé', + }, + }, + 'FlashGroupBControlMode' => { + PrintConv => { + 'Manual' => 'Manuelle', + 'Off' => 'Désactivé', + }, + }, + 'FlashGroupCControlMode' => { + PrintConv => { + 'Manual' => 'Manuelle', + 'Off' => 'Désactivé', + }, + }, + 'FlashInfo' => 'Information flash', + 'FlashInfoVersion' => 'Version de l\'info Flash', + 'FlashIntensity' => { + PrintConv => { + 'High' => 'Haut', + 'Low' => 'Bas', + 'Normal' => 'Normale', + 'Strong' => 'Forte', + }, + }, + 'FlashMeteringSegments' => 'Segments de mesure flash', + 'FlashMode' => { + Description => 'Mode flash', + PrintConv => { + 'Auto, Did not fire' => 'Auto, non déclenché', + 'Auto, Did not fire, Red-eye reduction' => 'Auto, non déclenché, réduction yeux rouges', + 'Auto, Fired' => 'Auto, déclenché', + 'Auto, Fired, Red-eye reduction' => 'Auto, déclenché, réduction yeux rouges', + 'Did Not Fire' => 'Eclair non-déclenché', + 'External, Auto' => 'Externe, auto', + 'External, Contrast-control Sync' => 'Externe, synchro contrôle des contrastes', + 'External, Flash Problem' => 'Externe, problème de flash ?', + 'External, High-speed Sync' => 'Externe, synchro haute vitesse', + 'External, Manual' => 'Externe, manuel', + 'External, P-TTL Auto' => 'Externe, P-TTL', + 'External, Wireless' => 'Externe, sans cordon', + 'External, Wireless, High-speed Sync' => 'Externe, sans cordon, synchro haute vitesse', + 'Fired, Commander Mode' => 'Eclair déclenché, Mode maître', + 'Fired, External' => 'Eclair déclenché, Exterieur', + 'Fired, Manual' => 'Eclair déclenché, Manuel', + 'Fired, TTL Mode' => 'Eclair déclenché, Mode TTL', + 'Internal' => 'Interne', + 'Normal' => 'Normale', + 'Off' => 'Désactivé', + 'Off, Did not fire' => 'Hors service', + 'On' => 'Activé', + 'On, Did not fire' => 'En service, non déclenché', + 'On, Fired' => 'En service', + 'On, Red-eye reduction' => 'En service, réduction yeux rouges', + 'On, Slow-sync' => 'En service, synchro lente', + 'On, Slow-sync, Red-eye reduction' => 'En service, synchro lente, réduction yeux rouges', + 'On, Soft' => 'En service, doux', + 'On, Trailing-curtain Sync' => 'En service, synchro 2e rideau', + 'On, Wireless (Control)' => 'En service, sans cordon (esclave)', + 'On, Wireless (Master)' => 'En service, sans cordon (maître)', + 'Red-eye Reduction' => 'Réduction yeux rouges', + 'Red-eye reduction' => 'Réduction yeux rouges', + 'Unknown' => 'Inconnu', + 'n/a - Off-Auto-Aperture' => 'N/c - auto-diaph hors service', + }, + }, + 'FlashModel' => { + Description => 'Modèle de Flash', + PrintConv => { + 'None' => 'Aucune', + }, + }, + 'FlashOptions' => { + Description => 'Options de flash', + PrintConv => { + 'Auto, Red-eye reduction' => 'Auto, réduction yeux rouges', + 'Normal' => 'Normale', + 'Red-eye reduction' => 'Réduction yeux rouges', + 'Slow-sync' => 'Synchro lente', + 'Slow-sync, Red-eye reduction' => 'Synchro lente, réduction yeux rouges', + 'Trailing-curtain Sync' => 'Synchro 2e rideau', + 'Wireless (Control)' => 'Sans cordon (contrôleur)', + 'Wireless (Master)' => 'Sans cordon (maître)', + }, + }, + 'FlashOptions2' => { + Description => 'Options de flash (2)', + PrintConv => { + 'Auto, Red-eye reduction' => 'Auto, réduction yeux rouges', + 'Normal' => 'Normale', + 'Red-eye reduction' => 'Réduction yeux rouges', + 'Slow-sync' => 'Synchro lente', + 'Slow-sync, Red-eye reduction' => 'Synchro lente, réduction yeux rouges', + 'Trailing-curtain Sync' => 'Synchro 2e rideau', + 'Wireless (Control)' => 'Sans cordon (contrôleur)', + 'Wireless (Master)' => 'Sans cordon (maître)', + }, + }, + 'FlashOutput' => 'Puissance de l\'éclair', + 'FlashRedEyeMode' => 'Flash mode anti-yeux rouges', + 'FlashReturn' => { + PrintConv => { + 'No return detection' => 'Pas de détection de retour', + 'Return detected' => 'Retour détecté', + 'Return not detected' => 'Retour non détecté', + }, + }, + 'FlashSetting' => 'Réglages Flash', + 'FlashStatus' => { + Description => 'Segment de mesure flash esclave 1', + PrintConv => { + 'External, Did not fire' => 'Externe, non déclenché', + 'External, Fired' => 'Externe, déclenché', + 'Internal, Did not fire' => 'Interne, non déclenché', + 'Internal, Fired' => 'Interne, déclenché', + 'Off' => 'Désactivé', + }, + }, + 'FlashSyncSpeedAv' => { + Description => 'Vitesse synchro en mode Av', + PrintConv => { + '1/200 Fixed' => '1/200 fixe', + '1/250 Fixed' => '1/250 fixe', + '1/300 Fixed' => '1/300 fixe', + }, + }, + 'FlashType' => { + Description => 'Type de flash', + PrintConv => { + 'Built-In Flash' => 'Intégré', + 'External' => 'Externe', + 'None' => 'Aucune', + }, + }, + 'FlashWarning' => { + PrintConv => { + 'Off' => 'Désactivé', + 'On' => 'Activé', + }, + }, + 'FlashpixVersion' => 'Version Flashpix supportée', + 'FlickerReduce' => { + PrintConv => { + 'Off' => 'Désactivé', + 'On' => 'Activé', + }, + }, + 'FlipHorizontal' => { + PrintConv => { + 'No' => 'Non', + 'Yes' => 'Oui', + }, + }, + 'FocalLength' => 'Focale de l\'objectif', + 'FocalLength35efl' => 'Focale de l\'objectif', + 'FocalLengthIn35mmFormat' => 'Distance focale sur film 35 mm', + 'FocalPlaneResolutionUnit' => { + Description => 'Unité de résolution de plan focal', + PrintConv => { + 'None' => 'Aucune', + 'inches' => 'Pouce', + 'um' => 'µm (micromètre)', + }, + }, + 'FocalPlaneXResolution' => 'Résolution X du plan focal', + 'FocalPlaneYResolution' => 'Résolution Y du plan focal', + 'Focus' => { + PrintConv => { + 'Manual' => 'Manuelle', + }, + }, + 'FocusContinuous' => { + PrintConv => { + 'Manual' => 'Manuelle', + }, + }, + 'FocusDistance' => 'Distance de mise au point', + 'FocusMode' => { + Description => 'Mode mise au point', + PrintConv => { + 'AF-C' => 'AF-C (prise de vue en rafale)', + 'AF-S' => 'AF-S (prise de vue unique)', + 'Auto, Continuous' => 'Auto, continue', + 'Auto, Focus button' => 'Bouton autofocus', + 'Continuous' => 'Auto, continue', + 'Infinity' => 'Infini', + 'Manual' => 'Manuelle', + 'Normal' => 'Normale', + 'Pan Focus' => 'Hyperfocale', + }, + }, + 'FocusMode2' => { + Description => 'Mode mise au point 2', + PrintConv => { + 'AF-C' => 'AF-C (prise de vue en rafale)', + 'AF-S' => 'AF-S (prise de vue unique)', + 'Manual' => 'Manuelle', + }, + }, + 'FocusModeSetting' => { + PrintConv => { + 'AF-C' => 'AF-C (prise de vue en rafale)', + 'AF-S' => 'AF-S (prise de vue unique)', + 'Manual' => 'Manuelle', + }, + }, + 'FocusPosition' => 'Distance de mise au point', + 'FocusRange' => { + PrintConv => { + 'Infinity' => 'Infini', + 'Manual' => 'Manuelle', + 'Normal' => 'Normale', + 'Pan Focus' => 'Hyperfocale', + 'Super Macro' => 'Super macro', + }, + }, + 'FocusTrackingLockOn' => { + PrintConv => { + 'Normal' => 'Normale', + 'Off' => 'Désactivé', + }, + }, + 'FocusingScreen' => 'Verre de visée', + 'ForwardMatrix1' => 'Matrice forward 1', + 'ForwardMatrix2' => 'Matrice forward 2', + 'FrameNumber' => 'Numéro de vue', + 'FrameRate' => 'Vitesse', + 'FrameSize' => 'Taille du cadre', + 'FreeByteCounts' => 'Nombre d\'octets libres', + 'FreeOffsets' => 'Offsets libres', + 'FujiFlashMode' => { + PrintConv => { + 'Off' => 'Désactivé', + 'On' => 'Activé', + 'Red-eye reduction' => 'Réduction yeux rouges', + }, + }, + 'GIFVersion' => 'Version GIF', + 'GPSAltitude' => 'Altitude', + 'GPSAltitudeRef' => { + Description => 'Référence d\'altitude', + PrintConv => { + 'Above Sea Level' => 'Au-dessus du niveau de la mer', + 'Below Sea Level' => 'Au-dessous du niveau de la mer', + }, + }, + 'GPSAreaInformation' => 'Nom de la zone GPS', + 'GPSDOP' => 'Précision de mesure', + 'GPSDateStamp' => 'Date GPS', + 'GPSDateTime' => 'Date/heure GPS (horloge atomique)', + 'GPSDestBearing' => 'Orientation de la destination', + 'GPSDestBearingRef' => { + Description => 'Référence de l\'orientation de la destination', + PrintConv => { + 'Magnetic North' => 'Nord magnétique', + 'True North' => 'Direction vraie', + }, + }, + 'GPSDestDistance' => 'Distance à la destination', + 'GPSDestDistanceRef' => { + Description => 'Référence de la distance à la destination', + PrintConv => { + 'Kilometers' => 'Kilomètres', + 'Nautical Miles' => 'Milles marins', + }, + }, + 'GPSDestLatitude' => 'Latitude de destination', + 'GPSDestLatitudeRef' => { + Description => 'Référence de la latitude de destination', + PrintConv => { + 'North' => 'Latitude nord', + 'South' => 'Latitude sud', + }, + }, + 'GPSDestLongitude' => 'Longitude de destination', + 'GPSDestLongitudeRef' => { + Description => 'Référence de la longitude de destination', + PrintConv => { + 'East' => 'Longitude est', + 'West' => 'Longitude ouest', + }, + }, + 'GPSDifferential' => { + Description => 'Correction différentielle GPS', + PrintConv => { + 'Differential Corrected' => 'Correction différentielle appliquée', + 'No Correction' => 'Mesure sans correction différentielle', + }, + }, + 'GPSImgDirection' => 'Direction de l\'image', + 'GPSImgDirectionRef' => { + Description => 'Référence pour la direction l\'image', + PrintConv => { + 'Magnetic North' => 'Direction magnétique', + 'True North' => 'Direction vraie', + }, + }, + 'GPSInfo' => 'Pointeur IFD d\'informations GPS', + 'GPSLatitude' => 'Latitude', + 'GPSLatitudeRef' => { + Description => 'Latitude nord ou sud', + PrintConv => { + 'North' => 'Latitude nord', + 'South' => 'Latitude sud', + }, + }, + 'GPSLongitude' => 'Longitude', + 'GPSLongitudeRef' => { + Description => 'Longitude est ou ouest', + PrintConv => { + 'East' => 'Longitude est', + 'West' => 'Longitude ouest', + }, + }, + 'GPSMapDatum' => 'Données de surveillance géodésique utilisées', + 'GPSMeasureMode' => { + Description => 'Mode de mesure GPS', + PrintConv => { + '2-D' => 'Mesure à deux dimensions', + '2-Dimensional' => 'Mesure à deux dimensions', + '2-Dimensional Measurement' => 'Mesure à deux dimensions', + '3-D' => 'Mesure à trois dimensions', + '3-Dimensional' => 'Mesure à trois dimensions', + '3-Dimensional Measurement' => 'Mesure à trois dimensions', + }, + }, + 'GPSPosition' => 'Position GPS', + 'GPSProcessingMethod' => 'Nom de la méthode de traitement GPS', + 'GPSSatellites' => 'Satellites GPS utilisés pour la mesure', + 'GPSSpeed' => 'Vitesse du récepteur GPS', + 'GPSSpeedRef' => { + Description => 'Unité de vitesse', + PrintConv => { + 'km/h' => 'Kilomètres par heure', + 'knots' => 'Nœuds', + 'mph' => 'Miles par heure', + }, + }, + 'GPSStatus' => { + Description => 'État du récepteur GPS', + PrintConv => { + 'Measurement Active' => 'Mesure active', + 'Measurement Void' => 'Mesure vide', + }, + }, + 'GPSTimeStamp' => 'Heure GPS (horloge atomique)', + 'GPSTrack' => 'Direction de déplacement', + 'GPSTrackRef' => { + Description => 'Référence pour la direction de déplacement', + PrintConv => { + 'Magnetic North' => 'Direction magnétique', + 'True North' => 'Direction vraie', + }, + }, + 'GPSVersionID' => 'Version de tag GPS', + 'GainControl' => { + Description => 'Contrôle de gain', + PrintConv => { + 'High gain down' => 'Forte atténuation', + 'High gain up' => 'Fort gain', + 'Low gain down' => 'Faible atténuation', + 'Low gain up' => 'Faible gain', + 'None' => 'Aucune', + }, + }, + 'GammaCompensatedValue' => 'Valeur de compensation gamma', + 'Gapless' => { + PrintConv => { + 'No' => 'Non', + 'Yes' => 'Oui', + }, + }, + 'GeoTiffAsciiParams' => 'Tag de paramètres Ascii GeoTiff', + 'GeoTiffDirectory' => 'Tag de répertoire de clé GeoTiff', + 'GeoTiffDoubleParams' => 'Tag de paramètres doubles GeoTiff', + 'Gradation' => 'Gradation', + 'GrayResponseCurve' => 'Courbe de réponse du gris', + 'GrayResponseUnit' => { + Description => 'Unité de réponse en gris', + PrintConv => { + '0.0001' => 'Le nombre représente des millièmes d\'unité', + '0.001' => 'Le nombre représente des centièmes d\'unité', + '0.1' => 'Le nombre représente des dixièmes d\'unité', + '1e-05' => 'Le nombre représente des dix-millièmes d\'unité', + '1e-06' => 'Le nombre représente des cent-millièmes d\'unité', + }, + }, + 'GrayTRC' => 'Courbe de reproduction des tons gris', + 'GreenMatrixColumn' => 'Colonne de matrice verte', + 'GreenTRC' => 'Courbe de reproduction des tons verts', + 'GridDisplay' => { + PrintConv => { + 'Off' => 'Désactivé', + 'On' => 'Activé', + }, + }, + 'GripBatteryADLoad' => 'Tension accu poignée en charge', + 'GripBatteryADNoLoad' => 'Tension accu poignée à vide', + 'GripBatteryState' => { + Description => 'État de accu poignée', + PrintConv => { + 'Almost Empty' => 'Presque vide', + 'Empty or Missing' => 'Vide ou absent', + 'Full' => 'Plein', + 'Running Low' => 'En baisse', + }, + }, + 'HCUsage' => 'Usage HC', + 'HDR' => { + Description => 'HDR auto', + PrintConv => { + 'Off' => 'Désactivée', + }, + }, + 'HalftoneHints' => 'Indications sur les demi-teintes', + 'Headline' => 'Titre principal', + 'HierarchicalSubject' => 'Sujet hiérarchique', + 'HighISONoiseReduction' => { + Description => 'Réduction du bruit en haute sensibilité ISO', + PrintConv => { + 'Auto' => 'Auto.', + 'High' => 'Fort', + 'Low' => 'Bas', + 'Normal' => 'Normale', + 'Off' => 'Désactivé', + 'On' => 'Activé', + 'Strong' => 'Importante', + 'Weak' => 'Faible', + 'Weakest' => 'La plus faible', + }, + }, + 'HighlightTonePriority' => { + Description => 'Priorité hautes lumières', + PrintConv => { + 'Disable' => 'Désactivée', + 'Enable' => 'Activée', + 'Off' => 'Désactivé', + 'On' => 'Activé', + }, + }, + 'History' => 'Récapitulatif', + 'HometownCity' => 'Ville de résidence', + 'HometownCityCode' => 'Code ville de résidence', + 'HometownDST' => { + Description => 'Heure d\'été de résidence', + PrintConv => { + 'No' => 'Non', + 'Yes' => 'Oui', + }, + }, + 'HostComputer' => 'Ordinateur hôte', + 'Hue' => 'Nuance', + 'HueAdjustment' => 'Teinte', + 'HyperfocalDistance' => 'Distance hyperfocale', + 'ICCProfile' => 'Profil ICC', + 'ICCProfileName' => 'Nom du profil ICC', + 'ICC_Profile' => 'Profil de couleur ICC d\'entrée', + 'ID3Size' => 'Taille ID3', + 'IPTC-NAA' => 'Métadonnées IPTC-NAA', + 'IPTCBitsPerSample' => 'Nombre de bits par échantillon', + 'IPTCImageHeight' => 'Nombre de lignes', + 'IPTCImageRotation' => { + Description => 'Rotation d\'image', + PrintConv => { + '0' => 'Pas de rotation', + '180' => 'Rotation de 180 degrés', + '270' => 'Rotation de 270 degrés', + '90' => 'Rotation de 90 degrés', + }, + }, + 'IPTCImageWidth' => 'Pixels par ligne', + 'IPTCPictureNumber' => 'Numéro d\'image', + 'IPTCPixelHeight' => 'Taille de pixel perpendiculairement à la direction de scan', + 'IPTCPixelWidth' => 'Taille de pixel dans la direction de scan', + 'ISO' => 'Sensibilité ISO', + 'ISOExpansion' => { + Description => 'Extension sensibilité ISO', + PrintConv => { + 'Off' => 'Arrêt', + 'On' => 'Marche', + }, + }, + 'ISOExpansion2' => { + PrintConv => { + 'Off' => 'Désactivé', + }, + }, + 'ISOFloor' => 'Seuil ISO', + 'ISOInfo' => 'Info ISO', + 'ISOSelection' => 'Choix ISO', + 'ISOSetting' => { + Description => 'Réglage ISO', + PrintConv => { + 'Manual' => 'Manuelle', + }, + }, + 'ISOSpeedExpansion' => { + Description => 'Extension de sensibilité ISO', + PrintConv => { + 'No' => 'Non', + 'Yes' => 'Oui', + }, + }, + 'ISOSpeedIncrements' => { + Description => 'Incréments de sensibilité ISO', + PrintConv => { + '1/3 Stop' => 'Palier 1/3', + }, + }, + 'ISOSpeedRange' => { + Description => 'Régler l\'extension de sensibilité ISO', + PrintConv => { + 'Disable' => 'Désactivé', + 'Enable' => 'Activée', + }, + }, + 'IT8Header' => 'En-tête IT8', + 'Identifier' => 'Identifiant', + 'Illumination' => { + PrintConv => { + 'Off' => 'Désactivé', + 'On' => 'Activé', + }, + }, + 'ImageAdjustment' => 'Ajustement Image', + 'ImageAreaOffset' => 'Décalage de zone d\'image', + 'ImageAuthentication' => { + Description => 'Authentication de l\'image', + PrintConv => { + 'Off' => 'Désactivé', + 'On' => 'Activé', + }, + }, + 'ImageBoundary' => 'Cadre Image', + 'ImageColorIndicator' => 'Indicateur de couleur d\'image', + 'ImageColorValue' => 'Valeur de couleur d\'image', + 'ImageCount' => 'Compteur d\'images', + 'ImageDataSize' => 'Taille de l\'image', + 'ImageDepth' => 'Profondeur d\'image', + 'ImageDescription' => 'Description d\'image', + 'ImageDustOff' => { + PrintConv => { + 'Off' => 'Désactivé', + 'On' => 'Activé', + }, + }, + 'ImageEditCount' => 'Compteur de traitement d\'image', + 'ImageEditing' => { + Description => 'Traitement de l\'image', + PrintConv => { + 'Cropped' => 'Recadré', + 'Digital Filter' => 'Filtre numérique', + 'Frame Synthesis?' => 'Synthèse de vue ?', + 'None' => 'Aucun', + }, + }, + 'ImageHeight' => 'Hauteur d\'image', + 'ImageHistory' => 'Historique de l\'image', + 'ImageID' => 'ID d\'image', + 'ImageLayer' => 'Couche image', + 'ImageNumber' => 'Numéro d\'image', + 'ImageOptimization' => 'Optimisation d\'image', + 'ImageOrientation' => { + Description => 'Orientation d\'image', + PrintConv => { + 'Landscape' => 'Paysage', + 'Square' => 'Carré', + }, + }, + 'ImageProcessing' => 'Retouche d\'image', + 'ImageQuality' => { + PrintConv => { + 'Normal' => 'Normale', + }, + }, + 'ImageReview' => { + PrintConv => { + 'Off' => 'Désactivé', + 'On' => 'Activé', + }, + }, + 'ImageRotated' => { + PrintConv => { + 'No' => 'Non', + 'Yes' => 'Oui', + }, + }, + 'ImageSize' => 'Taille de l\'Image', + 'ImageSourceData' => 'Données source d\'image', + 'ImageStabilization' => { + Description => 'Stabilisation d\'image', + PrintConv => { + 'Off' => 'Désactivé', + 'On' => 'Activé', + 'On, Mode 1' => 'Enclenché, Mode 1', + 'On, Mode 2' => 'Enclenché, Mode 2', + }, + }, + 'ImageTone' => { + Description => 'Ton de l\'image', + PrintConv => { + 'Bright' => 'Brillant', + 'Landscape' => 'Paysage', + 'Natural' => 'Naturel', + }, + }, + 'ImageType' => 'Type d\'image', + 'ImageUniqueID' => 'Identificateur unique d\'image', + 'ImageWidth' => 'Largeur d\'image', + 'Indexed' => 'Indexé', + 'InfoButtonWhenShooting' => { + Description => 'Touche INFO au déclenchement', + PrintConv => { + 'Displays camera settings' => 'Affiche les réglages en cours', + 'Displays shooting functions' => 'Affiche les fonctions', + }, + }, + 'InkNames' => 'Nom des encres', + 'InkSet' => 'Encrage', + 'IntellectualGenre' => 'Genre intellectuel', + 'IntelligentAuto' => 'Mode Auto intelligent', + 'IntensityStereo' => { + PrintConv => { + 'Off' => 'Désactivé', + 'On' => 'Activé', + }, + }, + 'InterchangeColorSpace' => { + PrintConv => { + 'CMY (K) Device Dependent' => 'CMY(K) dépendant de l\'appareil', + 'RGB Device Dependent' => 'RVB dépendant de l\'appareil', + }, + }, + 'IntergraphMatrix' => 'Tag de matrice intergraphe', + 'Interlace' => 'Entrelacement', + 'InternalFlash' => { + PrintConv => { + 'Fired' => 'Flash déclenché', + 'Manual' => 'Manuelle', + 'No' => 'Flash non déclenché', + 'Off' => 'Désactivé', + 'On' => 'Activé', + }, + }, + 'InternalFlashMode' => { + Description => 'Segment de mesure flash esclave 2', + PrintConv => { + 'Did not fire, (Unknown 0xf4)' => 'Hors service (inconnue 0xF4)', + 'Did not fire, Auto' => 'Hors service, auto', + 'Did not fire, Auto, Red-eye reduction' => 'Hors service, auto, réduction yeux rouges', + 'Did not fire, Normal' => 'Hors service, normal', + 'Did not fire, Red-eye reduction' => 'Hors service, réduction yeux rouges', + 'Did not fire, Slow-sync' => 'Hors service, synchro lente', + 'Did not fire, Slow-sync, Red-eye reduction' => 'Hors service, synchro lente, réduction yeux rouges', + 'Did not fire, Trailing-curtain Sync' => 'Hors service, synchro 2e rideau', + 'Did not fire, Wireless (Control)' => 'Hors service, sans cordon (contrôleur)', + 'Did not fire, Wireless (Master)' => 'Hors service, sans cordon (maître)', + 'Fired' => 'Activé', + 'Fired, Auto' => 'En service, auto', + 'Fired, Auto, Red-eye reduction' => 'En service, auto, réduction yeux rouges', + 'Fired, Red-eye reduction' => 'En service, réduction yeux rouges', + 'Fired, Slow-sync' => 'En service, synchro lente', + 'Fired, Slow-sync, Red-eye reduction' => 'En service, synchro lente, réduction yeux rouges', + 'Fired, Trailing-curtain Sync' => 'En service, synchro 2e rideau', + 'Fired, Wireless (Control)' => 'En service, sans cordon (contrôleur)', + 'Fired, Wireless (Master)' => 'En service, sans cordon (maître)', + 'n/a - Off-Auto-Aperture' => 'N/c - auto-diaph hors service', + }, + }, + 'InternalFlashStrength' => 'Segment de mesure flash esclave 4', + 'InternalSerialNumber' => 'Numéro de série interne', + 'InteropIndex' => { + Description => 'Identification d\'interopérabilité', + PrintConv => { + 'R03 - DCF option file (Adobe RGB)' => 'R03: fichier d\'option DCF (Adobe RGB)', + 'R98 - DCF basic file (sRGB)' => 'R98: fichier de base DCF (sRGB)', + 'THM - DCF thumbnail file' => 'THM: fichier de vignette DCF', + }, + }, + 'InteropOffset' => 'Indicateur d\'interfonctionnement', + 'InteropVersion' => 'Version d\'interopérabilité', + 'IptcLastEdited' => 'Dernière édition IPTC', + 'JFIFVersion' => 'Version JFIF', + 'JPEGACTables' => 'Tableaux AC JPEG', + 'JPEGDCTables' => 'Tableaux DC JPEG', + 'JPEGLosslessPredictors' => 'Prédicteurs JPEG sans perte', + 'JPEGPointTransforms' => 'Transformations de point JPEG', + 'JPEGProc' => 'Proc JPEG', + 'JPEGQTables' => 'Tableaux Q JPEG', + 'JPEGQuality' => { + Description => 'Qualité', + PrintConv => { + 'Extra Fine' => 'Extra fine', + 'Standard' => 'Normale', + }, + }, + 'JPEGRestartInterval' => 'Intervalle de redémarrage JPEG', + 'JPEGTables' => 'Tableaux JPEG', + 'JobID' => 'ID de la tâche', + 'JpgRecordedPixels' => { + Description => 'Pixels enregistrés JPEG', + PrintConv => { + '10 MP' => '10 Mpx', + '2 MP' => '2 Mpx', + '6 MP' => '6 Mpx', + }, + }, + 'Keyword' => 'Mots clé', + 'Keywords' => 'Mots-clés', + 'LC1' => 'Données d\'objectif', + 'LC10' => 'Données mv\' nv\'', + 'LC11' => 'Données AVC 1/EXP', + 'LC12' => 'Données mv1 Avminsif', + 'LC14' => 'Données UNT_12 UNT_6', + 'LC15' => 'Données d\'adaptation de flash incorporé', + 'LC2' => 'Code de distance', + 'LC3' => 'Valeur K', + 'LC4' => 'Données de correction d\'aberration à courte distance', + 'LC5' => 'Données de correction d\'aberration chromatique', + 'LC6' => 'Données d\'aberration d\'ouverture', + 'LC7' => 'Données de condition minimale de déclenchement AF', + 'LCDDisplayAtPowerOn' => { + Description => 'État LCD lors de l\'allumage', + PrintConv => { + 'Display' => 'Allumé', + 'Retain power off status' => 'État précédent', + }, + }, + 'LCDDisplayReturnToShoot' => { + Description => 'Affich. LCD -> Prise de vues', + PrintConv => { + 'Also with * etc.' => 'Aussi par * etc.', + 'With Shutter Button only' => 'Par déclencheur uniq.', + }, + }, + 'LCDIllumination' => { + PrintConv => { + 'Off' => 'Désactivé', + 'On' => 'Activé', + }, + }, + 'LCDIlluminationDuringBulb' => { + Description => 'Éclairage LCD pendant pose longue', + PrintConv => { + 'Off' => 'Désactivé', + 'On' => 'Activé', + }, + }, + 'LCDPanels' => { + Description => 'Ecran LCD supérieur/arrière', + PrintConv => { + 'ISO/File no.' => 'ISO/No. fichier', + 'ISO/Remain. shots' => 'ISO/Vues restantes', + 'Remain. shots/File no.' => 'Vues restantes/No. fichier', + 'Shots in folder/Remain. shots' => 'Vues dans dossier/Vues restantes', + }, + }, + 'LCHEditor' => { + PrintConv => { + 'Off' => 'Désactivé', + 'On' => 'Activé', + }, + }, + 'Language' => 'Langage', + 'LanguageIdentifier' => 'Identificateur de langue', + 'LastKeywordIPTC' => 'Dernier mot-clé IPTC', + 'LastKeywordXMP' => 'Dernier mot-clé XMP', + 'LeafData' => 'Données Leaf', + 'Lens' => 'Objectif ', + 'LensAFStopButton' => { + Description => 'Fonct. touche AF objectif', + PrintConv => { + 'AE lock' => 'Verrouillage AE', + 'AE lock while metering' => 'Verr. AE posemètre actif', + 'AF Stop' => 'Arrêt AF', + 'AF mode: ONE SHOT <-> AI SERVO' => 'Mode AF: ONE SHOT <-> AI SERVO', + 'AF point: M -> Auto / Auto -> Ctr.' => 'Colli: M -> Auto / Auto -> Ctr.', + 'AF point: M->Auto/Auto->ctr' => 'Collim.AF: M->Auto/Auto->ctr', + 'AF start' => 'Activation AF', + 'AF stop' => 'Arrêt AF', + 'IS start' => 'Activation stab. image', + 'Switch to registered AF point' => 'Activer le collimateur autofocus enregistré', + }, + }, + 'LensData' => 'Valeur K (LC3)', + 'LensDataVersion' => 'Version des Données Objectif', + 'LensDriveNoAF' => { + Description => 'Pilot. obj. si AF impossible', + PrintConv => { + 'Focus search off' => 'Pas de recherche du point', + 'Focus search on' => 'Recherche du point', + }, + }, + 'LensFStops' => 'Nombre de diaphs de l\'objectif', + 'LensID' => 'ID Lens', + 'LensIDNumber' => 'Numéro d\'Objectif', + 'LensInfo' => 'Informations sur l\'objectif', + 'LensKind' => 'Sorte d\'objectif / version (LC0)', + 'LensMake' => 'Fabricant d\'objectif', + 'LensModel' => 'Modèle d\'objectif', + 'LensSerialNumber' => 'Numéro de série objectif', + 'LensType' => 'Sorte d\'objectif', + 'LicenseType' => { + PrintConv => { + 'Unknown' => 'Inconnu', + }, + }, + 'LightReading' => 'Lecture de la lumière', + 'LightSource' => { + Description => 'Source de lumière', + PrintConv => { + 'Cloudy' => 'Temps nuageux', + 'Cool White Fluorescent' => 'Fluorescente type soft', + 'Day White Fluorescent' => 'Fluorescente type blanc', + 'Daylight' => 'Lumière du jour', + 'Daylight Fluorescent' => 'Fluorescente type jour', + 'Fine Weather' => 'Beau temps', + 'Fluorescent' => 'Fluorescente', + 'ISO Studio Tungsten' => 'Tungstène studio ISO', + 'Other' => 'Autre source de lumière', + 'Shade' => 'Ombre', + 'Standard Light A' => 'Lumière standard A', + 'Standard Light B' => 'Lumière standard B', + 'Standard Light C' => 'Lumière standard C', + 'Tungsten (Incandescent)' => 'Tungstène (lumière incandescente)', + 'Unknown' => 'Inconnue', + 'Warm White Fluorescent' => 'Fluorescent blanc chaud', + 'White Fluorescent' => 'Fluorescent blanc', + }, + }, + 'LightSourceSpecial' => { + PrintConv => { + 'Off' => 'Désactivé', + 'On' => 'Activé', + }, + }, + 'LightValue' => 'Luminosité', + 'Lightness' => 'Luminosité', + 'LinearResponseLimit' => 'Limite de réponse linéaire', + 'LinearizationTable' => 'Table de linéarisation', + 'Lit' => { + PrintConv => { + 'No' => 'Non', + 'Yes' => 'Oui', + }, + }, + 'LiveViewExposureSimulation' => { + Description => 'Simulation d\'exposition directe', + PrintConv => { + 'Disable (LCD auto adjust)' => 'Désactivée (réglage écran auto)', + 'Enable (simulates exposure)' => 'Activée (simulation exposition)', + }, + }, + 'LiveViewShooting' => { + PrintConv => { + 'Off' => 'Désactivé', + 'On' => 'Activé', + }, + }, + 'LocalizedCameraModel' => 'Nom traduit de modèle d\'appareil', + 'Location' => 'Lieu', + 'LockMicrophoneButton' => { + Description => 'Fonction de touche microphone', + PrintConv => { + 'Protect (hold:record memo)' => 'Protéger (maintien: enregistrement sonore)', + 'Record memo (protect:disable)' => 'Enregistrement sonore (protéger: désactivée)', + }, + }, + 'LongExposureNoiseReduction' => { + Description => 'Réduct. bruit longue expo.', + PrintConv => { + 'Off' => 'Arrêt', + 'On' => 'Marche', + }, + }, + 'LookupTable' => 'Table de correspondance', + 'LoopStyle' => { + PrintConv => { + 'Normal' => 'Normale', + }, + }, + 'LuminanceNoiseReduction' => { + PrintConv => { + 'Low' => 'Bas', + 'Off' => 'Désactivé', + }, + }, + 'MCUVersion' => 'Version MCU', + 'MIEVersion' => 'Version MIE', + 'MIMEType' => 'Type MIME', + 'MSStereo' => { + PrintConv => { + 'Off' => 'Désactivé', + 'On' => 'Activé', + }, + }, + 'Macro' => { + PrintConv => { + 'Manual' => 'Manuelle', + 'Normal' => 'Normale', + 'Off' => 'Désactivé', + 'On' => 'Activé', + 'Super Macro' => 'Super macro', + }, + }, + 'MacroMode' => { + Description => 'Mode Macro', + PrintConv => { + 'Normal' => 'Normale', + 'Off' => 'Désactivé', + 'On' => 'Activé', + 'Super Macro' => 'Super macro', + 'Tele-Macro' => 'Macro en télé', + }, + }, + 'MagnifiedView' => { + Description => 'Agrandissement en lecture', + PrintConv => { + 'Image playback only' => 'Lecture image uniquement', + 'Image review and playback' => 'Aff. inst. et lecture', + }, + }, + 'MainDialExposureComp' => { + PrintConv => { + 'Off' => 'Désactivé', + 'On' => 'Activé', + }, + }, + 'Make' => 'Fabricant', + 'MakeAndModel' => 'Fabricant et modèle', + 'MakerNote' => 'Données privées DNG', + 'MakerNoteSafety' => { + Description => 'Sécurité de note de fabricant', + PrintConv => { + 'Safe' => 'Sûre', + 'Unsafe' => 'Pas sûre', + }, + }, + 'MakerNoteVersion' => 'Version des informations spécifiques fabricant', + 'MakerNotes' => 'Notes fabricant', + 'ManualFlashOutput' => { + PrintConv => { + 'Low' => 'Bas', + 'n/a' => 'Non établie', + }, + }, + 'ManualFocusDistance' => 'Distance de Mise-au-point Manuelle', + 'ManualTv' => { + Description => 'Régl. Tv/Av manuel pour exp. M', + PrintConv => { + 'Tv=Control/Av=Main' => 'Tv=Contrôle rapide/Av=Principale', + 'Tv=Control/Av=Main w/o lens' => 'Tv=Contrôle rapide/Av=Principale sans objectif', + 'Tv=Main/Av=Control' => 'Tv=Principale/Av=Contrôle rapide', + 'Tv=Main/Av=Main w/o lens' => 'Tv=Principale/Av=Contrôle rapide sans objectif', + }, + }, + 'ManufactureDate' => 'Date de fabrication', + 'Marked' => 'Marqué', + 'MaskedAreas' => 'Zones masquées', + 'MasterDocumentID' => 'ID du document maître', + 'Matteing' => 'Matité', + 'MaxAperture' => 'Données Avmin', + 'MaxApertureAtMaxFocal' => 'Ouverture à la focale maxi', + 'MaxApertureAtMinFocal' => 'Ouverture à la focale mini', + 'MaxApertureValue' => 'Ouverture maximale de l\'objectif', + 'MaxAvailHeight' => 'Hauteur max Disponible', + 'MaxAvailWidth' => 'Largeur max Disponible', + 'MaxFocalLength' => 'Focale maxi', + 'MaxSampleValue' => 'Valeur maxi d\'échantillon', + 'MaxVal' => 'Valeur max', + 'MaximumDensityRange' => 'Etendue maximale de densité', + 'Measurement' => 'Observateur de mesure', + 'MeasurementBacking' => 'Support de mesure', + 'MeasurementFlare' => 'Flare de mesure', + 'MeasurementGeometry' => { + Description => 'Géométrie de mesure', + PrintConv => { + '0/45 or 45/0' => '0/45 ou 45/0', + '0/d or d/0' => '0/d ou d/0', + }, + }, + 'MeasurementIlluminant' => 'Illuminant de mesure', + 'MeasurementObserver' => 'Observateur de mesure', + 'MediaBlackPoint' => 'Point noir moyen', + 'MediaType' => { + PrintConv => { + 'Normal' => 'Normale', + }, + }, + 'MediaWhitePoint' => 'Point blanc moyen', + 'MenuButtonDisplayPosition' => { + Description => 'Position début touche menu', + PrintConv => { + 'Previous' => 'Précédente', + 'Previous (top if power off)' => 'Précédente (Haut si dés.)', + 'Top' => 'Haut', + }, + }, + 'MenuButtonReturn' => { + PrintConv => { + 'Previous' => 'Précédente', + 'Top' => 'Haut', + }, + }, + 'MetadataDate' => 'Date des metadonnées', + 'MeteringMode' => { + Description => 'Mode de mesure', + PrintConv => { + 'Average' => 'Moyenne', + 'Center-weighted average' => 'Centrale pondérée', + 'Evaluative' => 'Évaluative', + 'Multi-segment' => 'Multizone', + 'Multi-spot' => 'MultiSpot', + 'Other' => 'Autre', + 'Partial' => 'Partielle', + 'Unknown' => 'Inconnu', + }, + }, + 'MeteringMode2' => { + Description => 'Mode de mesure 2', + PrintConv => { + 'Multi-segment' => 'Multizone', + }, + }, + 'MeteringMode3' => { + Description => 'Mode de mesure (3)', + PrintConv => { + 'Multi-segment' => 'Multizone', + }, + }, + 'MinAperture' => 'Ouverture mini', + 'MinFocalLength' => 'Focale mini', + 'MinSampleValue' => 'Valeur mini d\'échantillon', + 'MinoltaQuality' => { + Description => 'Qualité', + PrintConv => { + 'Normal' => 'Normale', + }, + }, + 'MirrorLockup' => { + Description => 'Verrouillage du miroir', + PrintConv => { + 'Disable' => 'Désactivé', + 'Enable' => 'Activé', + 'Enable: Down with Set' => 'Activé: Retour par touche SET', + }, + }, + 'ModDate' => 'Date de modification', + 'Model' => 'Modèle d\'appareil photo', + 'Model2' => 'Modèle d\'équipement de prise de vue (2)', + 'ModelAge' => 'Age du modèle', + 'ModelTiePoint' => 'Tag de lien d modèle', + 'ModelTransform' => 'Tag de transformation de modèle', + 'ModelingFlash' => { + PrintConv => { + 'Off' => 'Désactivé', + 'On' => 'Activé', + }, + }, + 'ModifiedPictureStyle' => { + PrintConv => { + 'Landscape' => 'Paysage', + 'None' => 'Aucune', + }, + }, + 'ModifiedSaturation' => { + PrintConv => { + 'Off' => 'Désactivé', + }, + }, + 'ModifiedSharpnessFreq' => { + PrintConv => { + 'High' => 'Haut', + 'Highest' => 'Plus haut', + 'Low' => 'Doux', + 'n/a' => 'Non établie', + }, + }, + 'ModifiedToneCurve' => { + PrintConv => { + 'Manual' => 'Manuelle', + }, + }, + 'ModifiedWhiteBalance' => { + PrintConv => { + 'Cloudy' => 'Temps nuageux', + 'Daylight' => 'Lumière du jour', + 'Daylight Fluorescent' => 'Fluorescente type jour', + 'Fluorescent' => 'Fluorescente', + 'Shade' => 'Ombre', + 'Tungsten' => 'Tungstène (lumière incandescente)', + }, + }, + 'ModifyDate' => 'Date de modification de fichier', + 'MoireFilter' => { + PrintConv => { + 'Off' => 'Désactivé', + 'On' => 'Activé', + }, + }, + 'MonochromeFilterEffect' => { + PrintConv => { + 'Green' => 'Vert', + 'None' => 'Aucune', + 'Red' => 'Rouge', + 'Yellow' => 'Jaune', + }, + }, + 'MonochromeLinear' => { + PrintConv => { + 'No' => 'Non', + 'Yes' => 'Oui', + }, + }, + 'MonochromeToningEffect' => { + PrintConv => { + 'Blue' => 'Bleu', + 'Green' => 'Vert', + 'None' => 'Aucune', + }, + }, + 'MultiExposure' => 'Infos Surimpression', + 'MultiExposureAutoGain' => { + Description => 'Auto-expo des surimpressions', + PrintConv => { + 'Off' => 'Désactivé', + 'On' => 'Activé', + }, + }, + 'MultiExposureMode' => { + Description => 'Mode de surimpression', + PrintConv => { + 'Off' => 'Désactivé', + }, + }, + 'MultiExposureShots' => 'Nombre de prises de vue', + 'MultiExposureVersion' => 'Version Surimpression', + 'MultiFrameNoiseReduction' => { + Description => 'Réduc. bruit multi-photos', + PrintConv => { + 'Off' => 'Désactivée', + 'On' => 'Activé(e)', + }, + }, + 'MultipleExposureSet' => { + Description => 'Exposition multiple', + PrintConv => { + 'Off' => 'Désactivé', + 'On' => 'Activé', + }, + }, + 'Mute' => { + PrintConv => { + 'Off' => 'Désactivé', + 'On' => 'Activé', + }, + }, + 'MyColorMode' => { + PrintConv => { + 'Off' => 'Désactivé', + }, + }, + 'NDFilter' => { + PrintConv => { + 'Off' => 'Désactivé', + 'On' => 'Activé', + }, + }, + 'NEFCompression' => { + PrintConv => { + 'Uncompressed' => 'Non compressé', + }, + }, + 'NEFLinearizationTable' => 'Table de Linearization', + 'Name' => 'Nom', + 'NamedColor2' => 'Couleur nommée 2', + 'NativeDigest' => 'Sommaire natif', + 'NativeDisplayInfo' => 'Information sur l\'affichage natif', + 'NewsPhotoVersion' => 'Version d\'enregistrement news photo', + 'Nickname' => 'Surnom', + 'NikonCaptureData' => 'Données Nikon Capture', + 'NikonCaptureVersion' => 'Version Nikon Capture', + 'Noise' => 'Bruit', + 'NoiseFilter' => { + PrintConv => { + 'Low' => 'Bas', + 'Off' => 'Désactivé', + }, + }, + 'NoiseReduction' => { + Description => 'Réduction du bruit', + PrintConv => { + 'High (+1)' => '+1 (haut)', + 'Highest (+2)' => '+2 (le plus haut)', + 'Low' => 'Bas', + 'Low (-1)' => '-1 (bas)', + 'Lowest (-2)' => '-2 (le plus bas)', + 'Normal' => 'Normale', + 'Off' => 'Désactivé', + 'On' => 'Activé', + 'Standard' => '±0 (normal)', + }, + }, + 'NoiseReductionApplied' => 'Réduction de bruit appliquée', + 'NominalMaxAperture' => 'Ouverture maxi nominal', + 'NominalMinAperture' => 'Ouverture mini nominal', + 'NumIndexEntries' => 'Nombre d\'entrées d\'index', + 'NumberofInks' => 'Nombre d\'encres', + 'OECFColumns' => 'Colonnes OECF', + 'OECFNames' => 'Noms OECF', + 'OECFRows' => 'Lignes OECF', + 'OECFValues' => 'Valeurs OECF', + 'OPIProxy' => 'Proxy OPI', + 'ObjectAttributeReference' => 'Genre intellectuel', + 'ObjectCycle' => { + Description => 'Cycle d\'objet', + PrintConv => { + 'Both Morning and Evening' => 'Les deux', + 'Evening' => 'Soir', + 'Morning' => 'Matin', + }, + }, + 'ObjectFileType' => { + PrintConv => { + 'None' => 'Aucune', + 'Unknown' => 'Inconnu', + }, + }, + 'ObjectName' => 'Titre', + 'ObjectPreviewData' => 'Données de la miniature de l\'objet', + 'ObjectPreviewFileFormat' => 'Format de fichier de la miniature de l\'objet', + 'ObjectPreviewFileVersion' => 'Version de format de fichier de la miniature de l\'objet', + 'ObjectTypeReference' => 'Référence de type d\'objet', + 'OffsetSchema' => 'Schéma de décalage', + 'OldSubfileType' => 'Type du sous-fichier', + 'OneTouchWB' => { + PrintConv => { + 'Off' => 'Désactivé', + 'On' => 'Activé', + }, + }, + 'OpticalZoomMode' => { + Description => 'Mode Zoom optique', + PrintConv => { + 'Extended' => 'Optique EX', + 'Standard' => 'Normal', + }, + }, + 'OpticalZoomOn' => { + PrintConv => { + 'Off' => 'Désactivé', + 'On' => 'Activé', + }, + }, + 'Opto-ElectricConvFactor' => 'Facteur de conversion optoélectrique', + 'Orientation' => { + Description => 'Orientation de l\'image', + PrintConv => { + 'Horizontal (normal)' => '0° (haut/gauche)', + 'Mirror horizontal' => '0° (haut/droit)', + 'Mirror horizontal and rotate 270 CW' => '90° sens horaire (gauche/haut)', + 'Mirror horizontal and rotate 90 CW' => '90° sens antihoraire (droit/bas)', + 'Mirror vertical' => '180° (bas/gauche)', + 'Rotate 180' => '180° (bas/droit)', + 'Rotate 270 CW' => '90° sens horaire (gauche/bas)', + 'Rotate 90 CW' => '90° sens antihoraire (droit/haut)', + }, + }, + 'OriginalRawFileData' => 'Données du fichier raw d\'origine', + 'OriginalRawFileDigest' => 'Digest du fichier raw original', + 'OriginalRawFileName' => 'Nom du fichier raw d\'origine', + 'OriginalTransmissionReference' => 'Identificateur de tâche', + 'OriginatingProgram' => 'Programme d\'origine', + 'OtherImage' => 'Autre image', + 'OutputResponse' => 'Réponse de sortie', + 'Owner' => 'Propriétaire', + 'OwnerID' => 'ID du propriétaire', + 'OwnerName' => 'Nom du propriétaire', + 'PDFVersion' => 'Version PDF', + 'PEFVersion' => 'Version PEF', + 'Padding' => 'Remplissage', + 'PageName' => 'Nom de page', + 'PageNumber' => 'Page numéro', + 'PanasonicExifVersion' => 'Version Exif Panasonic', + 'PanasonicRawVersion' => 'Version Panasonic RAW', + 'PanasonicTitle' => 'Titre', + 'PentaxImageSize' => { + Description => 'Taille d\'image Pentax', + PrintConv => { + '2304x1728 or 2592x1944' => '2304 x 1728 ou 2592 x 1944', + '2560x1920 or 2304x1728' => '2560 x 1920 ou 2304 x 1728', + '2816x2212 or 2816x2112' => '2816 x 2212 ou 2816 x 2112', + '3008x2008 or 3040x2024' => '3008 x 2008 ou 3040 x 2024', + 'Full' => 'Pleine', + }, + }, + 'PentaxModelID' => 'Modèle Pentax', + 'PentaxVersion' => 'Version Pentax', + 'PeripheralLighting' => { + Description => 'Correction éclairage périphérique', + PrintConv => { + 'Off' => 'Désactiver', + 'On' => 'Activer', + }, + }, + 'PersonInImage' => 'Personnage sur l\'Image', + 'PhaseDetectAF' => 'Auto-Focus', + 'PhotoEffect' => { + PrintConv => { + 'Off' => 'Désactivé', + }, + }, + 'PhotoEffects' => { + PrintConv => { + 'Off' => 'Désactivé', + 'On' => 'Activé', + }, + }, + 'PhotoEffectsType' => { + PrintConv => { + 'None' => 'Aucune', + }, + }, + 'PhotometricInterpretation' => { + Description => 'Schéma de pixel', + PrintConv => { + 'BlackIsZero' => 'Zéro pour noir', + 'Color Filter Array' => 'CFA (Matrice de filtre de couleur)', + 'Pixar LogL' => 'CIE Log2(L) (Log luminance)', + 'Pixar LogLuv' => 'CIE Log2(L)(u\',v\') (Log luminance et chrominance)', + 'RGB' => 'RVB', + 'RGB Palette' => 'Palette RVB', + 'Transparency Mask' => 'Masque de transparence', + 'WhiteIsZero' => 'Zéro pour blanc', + }, + }, + 'PhotoshopAnnotations' => 'Annotations Photoshop', + 'PictureControl' => { + Description => 'Optimisation d\'image', + PrintConv => { + 'Off' => 'Désactivé', + 'On' => 'Activé', + }, + }, + 'PictureControlActive' => { + PrintConv => { + 'Off' => 'Désactivé', + 'On' => 'Activé', + }, + }, + 'PictureControlAdjust' => { + Description => 'Ajustement de l\'optimisation d\'image', + PrintConv => { + 'Default Settings' => 'Paramètres par défault', + 'Full Control' => 'Réglages manuels', + 'Quick Adjust' => 'Réglages rapides', + }, + }, + 'PictureControlBase' => 'Optimisation d\'image de base', + 'PictureControlName' => 'Nom de l\'optimisation d\'image', + 'PictureControlQuickAdjust' => 'Optimisation d\'image - Réglages rapides', + 'PictureControlVersion' => 'Version de l\'Optimisation d\'image', + 'PictureFinish' => { + PrintConv => { + 'Natural' => 'Naturel', + 'Night Scene' => 'Nocturne', + }, + }, + 'PictureMode' => { + Description => 'Mode d\'image', + PrintConv => { + '1/2 EV steps' => 'Pas de 1/2 IL', + '1/3 EV steps' => 'Pas de 1/3 IL', + 'Aperture Priority' => 'Priorité ouverture', + 'Aperture Priority, Off-Auto-Aperture' => 'Priorité ouverture (auto-diaph hors service)', + 'Aperture-priority AE' => 'Priorité ouverture', + 'Auto PICT (Landscape)' => 'Auto PICT (paysage)', + 'Auto PICT (Macro)' => 'Auto PICT (macro)', + 'Auto PICT (Portrait)' => 'Auto PICT (portrait)', + 'Auto PICT (Sport)' => 'Auto PICT (sport)', + 'Auto PICT (Standard)' => 'Auto PICT (standard)', + 'Autumn' => 'Automne', + 'Blur Reduction' => 'Réduction du flou', + 'Bulb' => 'Pose B', + 'Bulb, Off-Auto-Aperture' => 'Pose B (auto-diaph hors service)', + 'Candlelight' => 'Bougie', + 'DOF Program' => 'Programme PdC', + 'DOF Program (HyP)' => 'Programme PdC (Hyper-programme)', + 'Dark Pet' => 'Animal foncé', + 'Digital Filter' => 'Filtre numérique', + 'Fireworks' => 'Feux d\'artifice', + 'Flash X-Sync Speed AE' => 'Synchro X flash vitesse AE', + 'Food' => 'Nourriture', + 'Frame Composite' => 'Vue composite', + 'Green Mode' => 'Mode vert', + 'Half-length Portrait' => 'Portrait (buste)', + 'Hi-speed Program' => 'Programme grande vitesse', + 'Hi-speed Program (HyP)' => 'Programme grande vitesse (Hyper-programme)', + 'Kids' => 'Enfants', + 'Landscape' => 'Paysage', + 'Light Pet' => 'Animal clair', + 'MTF Program' => 'Programme FTM', + 'MTF Program (HyP)' => 'Programme FTM (Hyper-programme)', + 'Manual' => 'Manuelle', + 'Manual, Off-Auto-Aperture' => 'Manuel (auto-diaph hors service)', + 'Medium Pet' => 'Animal demi-teintes', + 'Museum' => 'Musée', + 'Natural Skin Tone' => 'Ton chair naturel', + 'Night Scene' => 'Nocturne', + 'Night Scene Portrait' => 'Portrait nocturne', + 'No Flash' => 'Sans flash', + 'Pet' => 'Animaux de compagnie', + 'Program' => 'Programme', + 'Program (HyP)' => 'Programme AE (Hyper-programme)', + 'Program AE' => 'Priorité vitesse', + 'Program Av Shift' => 'Décalage programme Av', + 'Program Tv Shift' => 'Décalage programme Tv', + 'Self Portrait' => 'Autoportrait', + 'Sensitivity Priority AE' => 'Priorité sensibilité AE', + 'Shutter & Aperture Priority AE' => 'Priorité vitesse et ouverture AE', + 'Shutter Speed Priority' => 'Priorité vitesse', + 'Shutter speed priority AE' => 'Priorité vitesse', + 'Snow' => 'Neige', + 'Soft' => 'Doux', + 'Sunset' => 'Coucher de soleil', + 'Surf & Snow' => 'Surf et neige', + 'Synchro Sound Record' => 'Enregistrement de son synchro', + 'Text' => 'Texte', + 'Underwater' => 'Sous-marine', + }, + }, + 'PictureMode2' => { + Description => 'Mode d\'image 2', + PrintConv => { + 'Aperture Priority' => 'Priorité ouverture', + 'Aperture Priority, Off-Auto-Aperture' => 'Priorité ouverture (auto-diaph hors service)', + 'Auto PICT' => 'Image auto', + 'Bulb' => 'Pose B', + 'Bulb, Off-Auto-Aperture' => 'Pose B (auto-diaph hors service)', + 'Flash X-Sync Speed AE' => 'Expo auto, vitesse de synchro flash X', + 'Green Mode' => 'Mode vert', + 'Manual' => 'Manuelle', + 'Manual, Off-Auto-Aperture' => 'Manuel (auto-diaph hors service)', + 'Program AE' => 'Programme AE', + 'Program Av Shift' => 'Décalage programme Av', + 'Program Tv Shift' => 'Décalage programme Tv', + 'Scene Mode' => 'Mode scène', + 'Sensitivity Priority AE' => 'Expo auto, priorité sensibilité', + 'Shutter & Aperture Priority AE' => 'Expo auto, priorité vitesse et ouverture', + 'Shutter Speed Priority' => 'Priorité vitesse', + }, + }, + 'PictureModeBWFilter' => { + PrintConv => { + 'Green' => 'Vert', + 'Red' => 'Rouge', + 'Yellow' => 'Jaune', + 'n/a' => 'Non établie', + }, + }, + 'PictureModeTone' => { + PrintConv => { + 'Blue' => 'Bleu', + 'Green' => 'Vert', + 'n/a' => 'Non établie', + }, + }, + 'PictureStyle' => { + Description => 'Style d\'image', + PrintConv => { + 'Faithful' => 'Fidèle', + 'High Saturation' => 'Saturation élevée', + 'Landscape' => 'Paysage', + 'Low Saturation' => 'Faible saturation', + 'Neutral' => 'Neutre', + 'None' => 'Aucune', + }, + }, + 'PixelIntensityRange' => 'Intervalle d\'intensité de pixel', + 'PixelScale' => 'Tag d\'échelle de pixel modèle', + 'PixelUnits' => { + PrintConv => { + 'Unknown' => 'Inconnu', + }, + }, + 'PlanarConfiguration' => { + Description => 'Arrangement des données image', + PrintConv => { + 'Chunky' => 'Format « chunky » (entrelacé)', + 'Planar' => 'Format « planar »', + }, + }, + 'PostalCode' => 'Code Postal', + 'PowerSource' => { + Description => 'Source d\'alimentation', + PrintConv => { + 'Body Battery' => 'Accu boîtier', + 'External Power Supply' => 'Alimentation externe', + 'Grip Battery' => 'Accu poignée', + }, + }, + 'Predictor' => { + Description => 'Prédicteur', + PrintConv => { + 'Horizontal differencing' => 'Différentiation horizontale', + 'None' => 'Aucun schéma de prédicteur utilisé avant l\'encodage', + }, + }, + 'Preview0' => 'Aperçu 0', + 'Preview1' => 'Aperçu 1', + 'Preview2' => 'Aperçu 2', + 'PreviewApplicationName' => 'Nom de l\'application d\'aperçu', + 'PreviewApplicationVersion' => 'Version de l\'application d\'aperçu', + 'PreviewColorSpace' => { + Description => 'Espace de couleur de l\'aperçu', + PrintConv => { + 'Unknown' => 'Inconnu', + }, + }, + 'PreviewDateTime' => 'Horodatage d\'aperçu', + 'PreviewImage' => 'Aperçu', + 'PreviewImageBorders' => 'Limites d\'image miniature', + 'PreviewImageData' => 'Données d\'image miniature', + 'PreviewImageLength' => 'Longueur d\'image miniature', + 'PreviewImageSize' => 'Taille d\'image miniature', + 'PreviewImageStart' => 'Début d\'image miniature', + 'PreviewImageValid' => { + PrintConv => { + 'No' => 'Non', + 'Yes' => 'Oui', + }, + }, + 'PreviewQuality' => { + PrintConv => { + 'Normal' => 'Normale', + }, + }, + 'PreviewSettingsDigest' => 'Digest des réglages d\'aperçu', + 'PreviewSettingsName' => 'Nom des réglages d\'aperçu', + 'PrimaryAFPoint' => { + PrintConv => { + 'Bottom' => 'Bas', + 'C6 (Center)' => 'C6 (Centre)', + 'Center' => 'Centre', + 'Mid-left' => 'Milieu gauche', + 'Mid-right' => 'Milieu droit', + 'Top' => 'Haut', + }, + }, + 'PrimaryChromaticities' => 'Chromaticité des couleurs primaires', + 'PrimaryPlatform' => 'Plateforme primaire', + 'ProcessingSoftware' => 'Logiciel de traitement', + 'Producer' => 'Producteur', + 'ProductID' => 'ID de produit', + 'ProductionCode' => 'L\'appareil est passé en SAV', + 'ProfileCMMType' => 'Type de profil CMM', + 'ProfileCalibrationSig' => 'Signature de calibration de profil', + 'ProfileClass' => { + Description => 'Classe de profil', + PrintConv => { + 'Abstract Profile' => 'Profil de résumé', + 'ColorSpace Conversion Profile' => 'Profil de conversion d\'espace de couleur', + 'DeviceLink Profile' => 'Profil de liaison', + 'Display Device Profile' => 'Profil d\'appareil d\'affichage', + 'Input Device Profile' => 'Profil d\'appareil d\'entrée', + 'NamedColor Profile' => 'Profil de couleur nommée', + 'Nikon Input Device Profile (NON-STANDARD!)' => 'Profil Nikon ("nkpf")', + 'Output Device Profile' => 'Profil d\'appareil de sortie', + }, + }, + 'ProfileConnectionSpace' => 'Espace de connexion de profil', + 'ProfileCopyright' => 'Copyright du profil', + 'ProfileCreator' => 'Créateur du profil', + 'ProfileDateTime' => 'Horodatage du profil', + 'ProfileDescription' => 'Description du profil', + 'ProfileDescriptionML' => 'Description de profil ML', + 'ProfileEmbedPolicy' => { + Description => 'Règles d\'usage du profil incluses', + PrintConv => { + 'Allow Copying' => 'Permet la copie', + 'Embed if Used' => 'Inclus si utilisé', + 'Never Embed' => 'Jamais inclus', + 'No Restrictions' => 'Pas de restriction', + }, + }, + 'ProfileFileSignature' => 'Signature de fichier de profil', + 'ProfileHueSatMapData1' => 'Données de profil teinte sat. 1', + 'ProfileHueSatMapData2' => 'Données de profil teinte sat. 2', + 'ProfileHueSatMapDims' => 'Divisions de teinte', + 'ProfileID' => 'ID du profil', + 'ProfileLookTableData' => 'Données de table de correspondance de profil', + 'ProfileLookTableDims' => 'Divisions de teinte', + 'ProfileName' => 'Nom du profil', + 'ProfileSequenceDesc' => 'Description de séquence du profil', + 'ProfileToneCurve' => 'Courbe de ton du profil', + 'ProfileVersion' => 'Version de profil', + 'ProgramISO' => 'Programme ISO', + 'ProgramLine' => { + Description => 'Ligne de programme', + PrintConv => { + 'Depth' => 'Priorité profondeur de champ', + 'Hi Speed' => 'Priorité grande vitesse', + 'MTF' => 'Priorité FTM', + 'Normal' => 'Normale', + }, + }, + 'ProgramMode' => { + PrintConv => { + 'None' => 'Aucune', + 'Sunset' => 'Coucher de soleil', + 'Text' => 'Texte', + }, + }, + 'ProgramShift' => 'Décalage Programme', + 'ProgramVersion' => 'Version du programme', + 'Protect' => 'Protéger', + 'Province-State' => 'État / Région', + 'Publisher' => 'Editeur', + 'Quality' => { + Description => 'Qualité', + PrintConv => { + 'Best' => 'La meilleure', + 'Better' => 'Meilleure', + 'Compressed RAW' => 'cRAW', + 'Compressed RAW + JPEG' => 'cRAW+JPEG', + 'Extra Fine' => 'Extra fine', + 'Good' => 'Bonne', + 'Low' => 'Bas', + 'Normal' => 'Normale', + 'RAW + JPEG' => 'RAW+JPEG', + }, + }, + 'QualityMode' => { + Description => 'Qualité', + PrintConv => { + 'Fine' => 'Haute', + 'Normal' => 'Normale', + }, + }, + 'QuantizationMethod' => { + Description => 'Méthode de quantification', + PrintConv => { + 'Color Space Specific' => 'Spécifique à l\'espace de couleur', + 'Compression Method Specific' => 'Spécifique à la méthode de compression', + 'Gamma Compensated' => 'Compensée gamma', + 'IPTC Ref B' => 'IPTC réf "B"', + 'Linear Density' => 'Densité linéaire', + 'Linear Dot Percent' => 'Pourcentage de point linéaire', + 'Linear Reflectance/Transmittance' => 'Réflectance/transmittance linéaire', + }, + }, + 'QuickAdjust' => 'Réglages rapides', + 'QuickControlDialInMeter' => { + Description => 'Molette de contrôle rapide en mesure', + PrintConv => { + 'AF point selection' => 'Sélection collimateur AF', + 'Exposure comp/Aperture' => 'Correction exposition/ouverture', + 'ISO speed' => 'Sensibilité ISO', + }, + }, + 'QuickShot' => { + PrintConv => { + 'Off' => 'Désactivé', + 'On' => 'Activé', + }, + }, + 'RAFVersion' => 'Version RAF', + 'RasterPadding' => 'Remplissage raster', + 'RasterizedCaption' => 'Légende rastérisée', + 'Rating' => 'Évaluation', + 'RatingPercent' => 'Rapport en pourcentage', + 'RawAndJpgRecording' => { + Description => 'Enregistrement RAW et JPEG', + PrintConv => { + 'JPEG (Best)' => 'JPEG (le meilleur)', + 'JPEG (Better)' => 'JPEG (meilleur)', + 'JPEG (Good)' => 'JPEG (bon)', + 'RAW (DNG, Best)' => 'RAW (DNG, le meilleur)', + 'RAW (DNG, Better)' => 'RAW (DNG, meilleur)', + 'RAW (DNG, Good)' => 'RAW (DNG, bon)', + 'RAW (PEF, Best)' => 'RAW (PEF, le meilleur)', + 'RAW (PEF, Better)' => 'RAW (PEF, meilleur)', + 'RAW (PEF, Good)' => 'RAW (PEF, bon)', + 'RAW+JPEG (DNG, Best)' => 'RAW+JPEG (DNG, le meilleur)', + 'RAW+JPEG (DNG, Better)' => 'RAW+JPEG (DNG, meilleur)', + 'RAW+JPEG (DNG, Good)' => 'RAW+JPEG (DNG, bon)', + 'RAW+JPEG (PEF, Best)' => 'RAW+JPEG (PEF, le meilleur)', + 'RAW+JPEG (PEF, Better)' => 'RAW+JPEG (PEF, meilleur)', + 'RAW+JPEG (PEF, Good)' => 'RAW+JPEG (PEF, bon)', + 'RAW+Large/Fine' => 'RAW+grande/fine', + 'RAW+Large/Normal' => 'RAW+grande/normale', + 'RAW+Medium/Fine' => 'RAW+moyenne/fine', + 'RAW+Medium/Normal' => 'RAW+moyenne/normale', + 'RAW+Small/Fine' => 'RAW+petite/fine', + 'RAW+Small/Normal' => 'RAW+petite/normale', + }, + }, + 'RawDataOffset' => 'Décalage données Raw', + 'RawDataUniqueID' => 'ID unique de données brutes', + 'RawDevAutoGradation' => { + PrintConv => { + 'Off' => 'Désactivé', + 'On' => 'Activé', + }, + }, + 'RawDevPMPictureTone' => { + PrintConv => { + 'Blue' => 'Bleu', + 'Green' => 'Vert', + }, + }, + 'RawDevPM_BWFilter' => { + PrintConv => { + 'Green' => 'Vert', + 'Red' => 'Rouge', + 'Yellow' => 'Jaune', + }, + }, + 'RawDevPictureMode' => { + PrintConv => { + 'Natural' => 'Naturel', + }, + }, + 'RawDevWhiteBalance' => { + PrintConv => { + 'Color Temperature' => 'Température de couleur', + }, + }, + 'RawImageCenter' => 'Centre Image RAW', + 'RawImageDigest' => 'Digest d\'image brute', + 'RawImageHeight' => 'Hauteur de l\'image brute', + 'RawImageSize' => 'Taille d\'image RAW', + 'RawImageWidth' => 'Largeur de l\'image brute', + 'RawJpgQuality' => { + PrintConv => { + 'Normal' => 'Normale', + }, + }, + 'RecordMode' => { + Description => 'Mode d\'enregistrement', + PrintConv => { + 'Aperture Priority' => 'Priorité ouverture', + 'Manual' => 'Manuelle', + 'Shutter Priority' => 'Priorité vitesse', + }, + }, + 'RecordingMode' => { + PrintConv => { + 'Landscape' => 'Paysage', + 'Manual' => 'Manuelle', + 'Night Scene' => 'Nocturne', + }, + }, + 'RedBalance' => 'Balance rouge', + 'RedEyeCorrection' => { + PrintConv => { + 'Automatic' => 'Auto', + 'Off' => 'Désactivé', + }, + }, + 'RedEyeReduction' => { + Description => 'Réduction yeux rouges', + PrintConv => { + 'Off' => 'Désactivé', + 'On' => 'Activé', + }, + }, + 'RedMatrixColumn' => 'Colonne de matrice rouge', + 'RedTRC' => 'Courbe de reproduction des tons rouges', + 'ReductionMatrix1' => 'Matrice de réduction 1', + 'ReductionMatrix2' => 'Matrice de réduction 2', + 'ReferenceBlackWhite' => 'Paire de valeurs de référence noir et blanc', + 'ReferenceDate' => 'Date de référence', + 'ReferenceNumber' => 'Numéro de référence', + 'ReferenceService' => 'Service de référence', + 'RelatedImageFileFormat' => 'Format de fichier image apparenté', + 'RelatedImageHeight' => 'Hauteur d\'image apparentée', + 'RelatedImageWidth' => 'Largeur d\'image apparentée', + 'RelatedSoundFile' => 'Fichier audio apparenté', + 'ReleaseButtonToUseDial' => { + PrintConv => { + 'No' => 'Non', + 'Yes' => 'Oui', + }, + }, + 'ReleaseDate' => 'Date de version', + 'ReleaseTime' => 'Heure de version', + 'RenderingIntent' => { + Description => 'Intention de rendu', + PrintConv => { + 'ICC-Absolute Colorimetric' => 'Colorimétrique absolu', + 'Media-Relative Colorimetric' => 'Colorimétrique relatif', + 'Perceptual' => 'Perceptif', + }, + }, + 'ResampleParamsQuality' => { + PrintConv => { + 'Low' => 'Bas', + }, + }, + 'Resaved' => { + PrintConv => { + 'No' => 'Non', + 'Yes' => 'Oui', + }, + }, + 'Resolution' => 'Résolution d\'image', + 'ResolutionUnit' => { + Description => 'Unité de résolution en X et Y', + PrintConv => { + 'None' => 'Aucune', + 'cm' => 'Pixels/cm', + 'inches' => 'Pouce', + }, + }, + 'RetouchHistory' => { + Description => 'Historique retouche', + PrintConv => { + 'None' => 'Aucune', + }, + }, + 'RevisionNumber' => 'Numéro de révision', + 'Rights' => 'Droits', + 'Rotation' => { + PrintConv => { + 'Rotate 270 CW' => 'Rotation à 270 ° - sens antihoraire', + 'Rotate 90 CW' => 'Rotation 90 ° - sens horaire', + }, + }, + 'RowInterleaveFactor' => 'Facteur d\'entrelacement des lignes', + 'RowsPerStrip' => 'Nombre de rangées par bande', + 'SMaxSampleValue' => 'Valeur maxi d\'échantillon S', + 'SMinSampleValue' => 'Valeur mini d\'échantillon S', + 'SPIFFVersion' => 'Version SPIFF', + 'SRAWQuality' => { + PrintConv => { + 'n/a' => 'Non établie', + }, + }, + 'SRActive' => { + Description => 'Réduction de bougé active', + PrintConv => { + 'No' => 'Non', + 'Yes' => 'Oui', + }, + }, + 'SRFocalLength' => 'Focale de réduction de bougé', + 'SRHalfPressTime' => 'Temps entre mesure et déclenchement', + 'SRResult' => { + Description => 'Stabilisation', + PrintConv => { + 'Not stabilized' => 'Non stabilisé', + }, + }, + 'SVGVersion' => 'Version SVG', + 'SafetyShift' => { + Description => 'Décalage de sécurité', + PrintConv => { + 'Disable' => 'Désactivé', + 'Enable (ISO speed)' => 'Activé (sensibilité ISO)', + 'Enable (Tv/Av)' => 'Activé (Tv/Av)', + }, + }, + 'SafetyShiftInAvOrTv' => { + Description => 'Décalage de sécurité Av ou Tv', + PrintConv => { + 'Disable' => 'Désactivé', + 'Enable' => 'Activé', + }, + }, + 'SampleFormat' => { + Description => 'Format d\'échantillon', + PrintConv => { + 'Complex int' => 'Entier complexe', + 'Float' => 'Réel à virgule flottante', + 'Signed' => 'Entier signé', + 'Undefined' => 'Non défini', + 'Unsigned' => 'Entier non signé', + }, + }, + 'SampleStructure' => { + Description => 'Structure d\'échantillonnage', + PrintConv => { + 'CompressionDependent' => 'Définie dans le processus de compression', + 'Orthogonal4-2-2Sampling' => 'Orthogonale, avec les fréquences d\'échantillonnage dans le rapport 4:2:2:(4)', + 'OrthogonalConstangSampling' => 'Orthogonale, avec les mêmes fréquences d\'échantillonnage relatives sur chaque composante', + }, + }, + 'SamplesPerPixel' => 'Nombre de composantes', + 'Saturation' => { + PrintConv => { + '+1 (medium high)' => '+1 (Assez fort)', + '+2 (high)' => '+2 (Forte)', + '+3 (very high)' => '+3 (Très fort)', + '+4 (highest)' => '+4', + '+4 (maximum)' => '+4', + '-1 (medium low)' => '-1 (Assez faible)', + '-2 (low)' => '-2 (Faible)', + '-3 (very low)' => '-3 (Très faible)', + '-4 (lowest)' => '-4', + '-4 (minimum)' => '-4', + '0 (normal)' => '0 (Normale)', + 'High' => 'Forte', + 'Low' => 'Faible', + 'None' => 'Non établie', + 'Normal' => 'Normale', + }, + }, + 'ScanImageEnhancer' => { + PrintConv => { + 'Off' => 'Désactivé', + 'On' => 'Activé', + }, + }, + 'ScanningDirection' => { + Description => 'Direction de scannage', + PrintConv => { + 'Bottom-Top, L-R' => 'De bas en haut, de gauche à droite', + 'Bottom-Top, R-L' => 'De bas en haut, de droite à gauche', + 'L-R, Bottom-Top' => 'De gauche à droite, de bas en haut', + 'L-R, Top-Bottom' => 'De gauche à droite, de haut en bas', + 'R-L, Bottom-Top' => 'De droite à gauche, de bas en haut', + 'R-L, Top-Bottom' => 'De droite à gauche, de haut en bas', + 'Top-Bottom, L-R' => 'De haut en bas, de gauche à droite', + 'Top-Bottom, R-L' => 'De haut en bas, de droite à gauche', + }, + }, + 'Scene' => 'Scène', + 'SceneAssist' => 'Assistant Scene', + 'SceneCaptureType' => { + Description => 'Type de capture de scène', + PrintConv => { + 'Landscape' => 'Paysage', + 'Night' => 'Scène de nuit', + }, + }, + 'SceneMode' => { + Description => 'Modes scène', + PrintConv => { + '3D Sweep Panorama' => '3D', + 'Anti Motion Blur' => 'Anti-flou de mvt', + 'Aperture Priority' => 'Priorité ouverture', + 'Auto' => 'Auto.', + 'Candlelight' => 'Bougie', + 'Cont. Priority AE' => 'AE priorité continue', + 'Handheld Night Shot' => 'Vue de nuit manuelle', + 'Landscape' => 'Paysage', + 'Manual' => 'Manuelle', + 'Night Portrait' => 'Portrait nocturne', + 'Night Scene' => 'Nocturne', + 'Night View/Portrait' => 'Vision/portrait nocturne', + 'Normal' => 'Normale', + 'Off' => 'Désactivé', + 'Shutter Priority' => 'Priorité vitesse', + 'Snow' => 'Neige', + 'Sunset' => 'Coucher de soleil', + 'Super Macro' => 'Super macro', + 'Sweep Panorama' => 'Panora. par balayage', + 'Text' => 'Texte', + }, + }, + 'SceneModeUsed' => { + PrintConv => { + 'Aperture Priority' => 'Priorité ouverture', + 'Candlelight' => 'Bougie', + 'Landscape' => 'Paysage', + 'Manual' => 'Manuelle', + 'Shutter Priority' => 'Priorité vitesse', + 'Snow' => 'Neige', + 'Sunset' => 'Coucher de soleil', + 'Text' => 'Texte', + }, + }, + 'SceneSelect' => { + PrintConv => { + 'Night' => 'Scène de nuit', + 'Off' => 'Désactivé', + }, + }, + 'SceneType' => { + Description => 'Type de scène', + PrintConv => { + 'Directly photographed' => 'Image photographiée directement', + }, + }, + 'SecurityClassification' => { + Description => 'Classement de sécurité', + PrintConv => { + 'Confidential' => 'Confidentiel', + 'Restricted' => 'Restreint', + 'Top Secret' => 'Top secret', + 'Unclassified' => 'Non classé', + }, + }, + 'SelectableAFPoint' => { + Description => 'Collimateurs AF sélectionnables', + PrintConv => { + '11 points' => '11 collimateurs', + '19 points' => '19 collimateurs', + '45 points' => '45 collimateurs', + 'Inner 9 points' => '9 collimateurs centraux', + 'Outer 9 points' => '9 collimateurs périphériques', + }, + }, + 'SelfTimer' => { + Description => 'Retardateur', + PrintConv => { + 'Off' => 'Désactivé', + 'On' => 'Activé', + }, + }, + 'SelfTimer2' => 'Retardateur (2)', + 'SelfTimerMode' => 'Mode auto-timer', + 'SensingMethod' => { + Description => 'Méthode de capture', + PrintConv => { + 'Color sequential area' => 'Capteur couleur séquentiel', + 'Color sequential linear' => 'Capteur couleur séquentiel linéaire', + 'Monochrome area' => 'Capteur monochrome', + 'Monochrome linear' => 'Capteur linéaire monochrome', + 'Not defined' => 'Non définie', + 'One-chip color area' => 'Capteur monochip couleur', + 'Three-chip color area' => 'Capteur trois chips couleur', + 'Trilinear' => 'Capteur trilinéaire', + 'Two-chip color area' => 'Capteur deux chips couleur', + }, + }, + 'SensitivityAdjust' => 'Réglage de sensibilité', + 'SensitivitySteps' => { + Description => 'Pas de sensibilité', + PrintConv => { + '1 EV Steps' => 'Pas de 1 IL', + 'As EV Steps' => 'Comme pas IL', + }, + }, + 'SensitivityType' => 'Type de sensibilité', + 'SensorCleaning' => { + PrintConv => { + 'Disable' => 'Désactivé', + 'Enable' => 'Activé', + }, + }, + 'SensorHeight' => 'Hauteur du capteur', + 'SensorPixelSize' => 'Taille des pixels du capteur', + 'SensorWidth' => 'Largeur du capteur', + 'SequenceNumber' => 'Numéro de Séquence', + 'SequentialShot' => { + PrintConv => { + 'None' => 'Aucune', + }, + }, + 'SerialNumber' => 'Numéro de série', + 'ServiceIdentifier' => 'Identificateur de service', + 'SetButtonCrossKeysFunc' => { + Description => 'Réglage touche SET/joypad', + PrintConv => { + 'Cross keys: AF point select' => 'Joypad:Sélec. collim. AF', + 'Normal' => 'Normale', + 'Set: Flash Exposure Comp' => 'SET:Cor expo flash', + 'Set: Parameter' => 'SET:Changer de paramètres', + 'Set: Picture Style' => 'SET:Style d’image', + 'Set: Playback' => 'SET:Lecture', + 'Set: Quality' => 'SET:Qualité', + }, + }, + 'SetButtonWhenShooting' => { + Description => 'Touche SET au déclenchement', + PrintConv => { + 'Change parameters' => 'Changer de paramètres', + 'Default (no function)' => 'Normal (désactivée)', + 'Disabled' => 'Désactivée', + 'Flash exposure compensation' => 'Correction expo flash', + 'ISO speed' => 'Sensibilité ISO', + 'Image playback' => 'Lecture de l\'image', + 'Image quality' => 'Changer de qualité', + 'Image size' => 'Taille d\'image', + 'LCD monitor On/Off' => 'Écran LCD On/Off', + 'Menu display' => 'Affichage du menu', + 'Normal (disabled)' => 'Normal (désactivée)', + 'Picture style' => 'Style d\'image', + 'Quick control screen' => 'Écran de contrôle rapide', + 'Record func. + media/folder' => 'Fonction enregistrement + média/dossier', + 'Record movie (Live View)' => 'Enr. vidéo (visée écran)', + 'White balance' => 'Balance des blancs', + }, + }, + 'SetFunctionWhenShooting' => { + Description => 'Touche SET au déclenchement', + PrintConv => { + 'Change Parameters' => 'Changer de paramètres', + 'Change Picture Style' => 'Style d\'image', + 'Change quality' => 'Changer de qualité', + 'Default (no function)' => 'Normal (désactivée)', + 'Image replay' => 'Lecture de l\'image', + 'Menu display' => 'Affichage du menu', + }, + }, + 'ShadingCompensation' => { + Description => 'Compensation de l\'ombrage', + PrintConv => { + 'Off' => 'Désactivé', + 'On' => 'Activé', + }, + }, + 'ShadingCompensation2' => { + PrintConv => { + 'Off' => 'Désactivé', + 'On' => 'Activé', + }, + }, + 'ShadowScale' => 'Echelle d\'ombre', + 'ShakeReduction' => { + Description => 'Réduction du bougé (réglage)', + PrintConv => { + 'Off' => 'Désactivé', + 'On' => 'Activé', + }, + }, + 'ShakeReductionInfo' => 'Stabilisation', + 'Sharpness' => { + Description => 'Accentuation', + PrintConv => { + '+1 (medium hard)' => '+1 (Assez dure)', + '+2 (hard)' => '+2 (Dure)', + '+3 (very hard)' => '+3 (Très dure)', + '+4 (hardest)' => '+4', + '+4 (maximum)' => '+4', + '-1 (medium soft)' => '-1 (Assez dure)', + '-2 (soft)' => '-2 (Douce)', + '-3 (very soft)' => '-3 (Très douce)', + '-4 (minimum)' => '-4', + '-4 (softest)' => '-4', + '0 (normal)' => '0 (Normale)', + 'Hard' => 'Dure', + 'Normal' => 'Normale', + 'Sharp' => 'Dure', + 'Soft' => 'Douce', + 'n/a' => 'Non établie', + }, + }, + 'SharpnessFrequency' => { + PrintConv => { + 'High' => 'Haut', + 'Highest' => 'Plus haut', + 'Low' => 'Doux', + 'n/a' => 'Non établie', + }, + }, + 'ShootingMode' => { + Description => 'Télécommande IR', + PrintConv => { + 'Aerial Photo' => 'Photo aérienne', + 'Aperture Priority' => 'Priorité ouverture', + 'Baby' => 'Bébé', + 'Beach' => 'Plage', + 'Candlelight' => 'Eclairage Bougie', + 'Color Effects' => 'Effets de couleurs', + 'Fireworks' => 'Feu d\'artifice', + 'Food' => 'Nourriture', + 'High Sensitivity' => 'Haute sensibilité', + 'High Speed Continuous Shooting' => 'Déclenchement continu à grande vitesse', + 'Intelligent Auto' => 'Mode Auto intelligent', + 'Intelligent ISO' => 'ISO Intelligent', + 'Manual' => 'Manuel', + 'Movie Preview' => 'Prévisualisation vidéo', + 'Night Portrait' => 'Portrait de nuit', + 'Normal' => 'Normale', + 'Panning' => 'Panoramique', + 'Panorama Assist' => 'Assistant Panorama', + 'Party' => 'Fête', + 'Pet' => 'Animal domestique', + 'Program' => 'Programme', + 'Scenery' => 'Paysage', + 'Shutter Priority' => 'Priorité vitesse', + 'Snow' => 'Neige', + 'Soft Skin' => 'Peau douce', + 'Starry Night' => 'Nuit étoilée', + 'Sunset' => 'Coucher de soleil', + 'Underwater' => 'Subaquatique', + }, + }, + 'ShortDocumentID' => 'ID court de document', + 'ShortReleaseTimeLag' => { + Description => 'Inertie au déclenchement réduite', + PrintConv => { + 'Disable' => 'Désactivé', + 'Enable' => 'Activé', + }, + }, + 'ShotInfoVersion' => 'Version des Infos prise de vue', + 'Shutter-AELock' => { + Description => 'Déclencheur/Touche verr. AE', + PrintConv => { + 'AE lock/AF' => 'Verrouillage AE/autofocus', + 'AE/AF, No AE lock' => 'AE/AF, pas de verrou. AE', + 'AF/AE lock' => 'Autofocus/verrouillage AE', + 'AF/AF lock' => 'Autofocus/verrouillage AF', + 'AF/AF lock, No AE lock' => 'AF/verr.AF, pas de verr.AE', + }, + }, + 'ShutterAELButton' => { + Description => 'Déclencheur/Touche verr. AE', + PrintConv => { + 'AE lock/AF' => 'Verrouillage AE/Autofocus', + 'AE/AF, No AE lock' => 'AE/AF, pas de verrou. AE', + 'AF/AE lock stop' => 'Autofocus/Verrouillage AE', + 'AF/AF lock, No AE lock' => 'AF/verr.AF, pas de verr.AE', + }, + }, + 'ShutterButtonAFOnButton' => { + Description => 'Déclencheur/Touche AF', + PrintConv => { + 'AE lock/Metering + AF start' => 'Mémo expo/lct. mesure+AF', + 'Metering + AF start' => 'Mesure + lancement AF', + 'Metering + AF start/AF stop' => 'Mesure + lancement/arrêt AF', + 'Metering + AF start/disable' => 'Lct. mesure+AF/désactivée', + 'Metering start/Meter + AF start' => 'Lct. mesure/lct. mesure+AF', + }, + }, + 'ShutterCount' => 'Comptage des déclenchements', + 'ShutterCurtainSync' => { + Description => 'Synchronisation du rideau', + PrintConv => { + '1st-curtain sync' => 'Synchronisation premier rideau', + '2nd-curtain sync' => 'Synchronisation deuxième rideau', + }, + }, + 'ShutterMode' => { + PrintConv => { + 'Aperture Priority' => 'Priorité ouverture', + }, + }, + 'ShutterReleaseButtonAE-L' => { + PrintConv => { + 'Off' => 'Désactivé', + 'On' => 'Activé', + }, + }, + 'ShutterReleaseNoCFCard' => { + Description => 'Déclench. obtur. sans carte', + PrintConv => { + 'No' => 'Non', + 'Yes' => 'Oui', + }, + }, + 'ShutterSpeed' => 'Temps de pose', + 'ShutterSpeedRange' => { + Description => 'Régler gamme de vitesses', + PrintConv => { + 'Disable' => 'Désactivé', + 'Enable' => 'Activée', + }, + }, + 'ShutterSpeedValue' => 'Vitesse d\'obturation', + 'SidecarForExtension' => 'Extension', + 'SimilarityIndex' => 'Indice de similarité', + 'SlaveFlashMeteringSegments' => 'Segments de mesure flash esclave', + 'SlideShow' => { + PrintConv => { + 'No' => 'Non', + 'Yes' => 'Oui', + }, + }, + 'SlowShutter' => { + Description => 'Vitesse d\'obturation lente', + PrintConv => { + 'Night Scene' => 'Nocturne', + 'None' => 'Aucune', + 'Off' => 'Désactivé', + 'On' => 'Activé', + }, + }, + 'SlowSync' => { + PrintConv => { + 'Off' => 'Désactivé', + 'On' => 'Activé', + }, + }, + 'Software' => 'Logiciel', + 'SpatialFrequencyResponse' => 'Réponse spatiale en fréquence', + 'SpecialEffectsOpticalFilter' => { + PrintConv => { + 'None' => 'Aucune', + }, + }, + 'SpectralSensitivity' => 'Sensibilité spectrale', + 'SpotMeterLinkToAFPoint' => { + Description => 'Mesure spot liée au collimateur AF', + PrintConv => { + 'Disable (use center AF point)' => 'Désactivée (utiliser collimateur AF central)', + 'Enable (use active AF point)' => 'Activé (utiliser collimateur AF actif)', + }, + }, + 'SpotMeteringMode' => { + PrintConv => { + 'Center' => 'Centre', + }, + }, + 'State' => 'État / Région', + 'StreamType' => { + PrintConv => { + 'Text' => 'Texte', + }, + }, + 'StripByteCounts' => 'Octets par bande compressée', + 'StripOffsets' => 'Emplacement des données image', + 'Sub-location' => 'Lieu', + 'SubSecCreateDate' => 'Date de la création des données numériques', + 'SubSecDateTimeOriginal' => 'Date de la création des données originales', + 'SubSecModifyDate' => 'Date de modification de fichier', + 'SubSecTime' => 'Fractions de seconde de DateTime', + 'SubSecTimeDigitized' => 'Fractions de seconde de DateTimeDigitized', + 'SubSecTimeOriginal' => 'Fractions de seconde de DateTimeOriginal', + 'SubTileBlockSize' => 'Taille de bloc de sous-tuile', + 'SubfileType' => 'Type du nouveau sous-fichier', + 'SubimageColor' => { + PrintConv => { + 'RGB' => 'RVB', + }, + }, + 'Subject' => 'Sujet', + 'SubjectArea' => 'Zone du sujet', + 'SubjectCode' => 'Code sujet', + 'SubjectDistance' => 'Distance du sujet', + 'SubjectDistanceRange' => { + Description => 'Intervalle de distance du sujet', + PrintConv => { + 'Close' => 'Vue rapprochée', + 'Distant' => 'Vue distante', + 'Unknown' => 'Inconnu', + }, + }, + 'SubjectLocation' => 'Zone du sujet', + 'SubjectProgram' => { + PrintConv => { + 'None' => 'Aucune', + 'Sunset' => 'Coucher de soleil', + 'Text' => 'Texte', + }, + }, + 'SubjectReference' => 'Code de sujet', + 'Subsystem' => { + PrintConv => { + 'Unknown' => 'Inconnu', + }, + }, + 'SuperMacro' => { + PrintConv => { + 'Off' => 'Désactivé', + }, + }, + 'SuperimposedDisplay' => { + Description => 'Affichage superposé', + PrintConv => { + 'Off' => 'Désactivé', + 'On' => 'Activé', + }, + }, + 'SupplementalCategories' => 'Catégorie d\'appoint', + 'SupplementalType' => { + Description => 'Type de supplément', + PrintConv => { + 'Main Image' => 'Non établi', + 'Rasterized Caption' => 'Titre rastérisé', + 'Reduced Resolution Image' => 'Image de résolution réduite', + }, + }, + 'SvISOSetting' => 'Réglage ISO Sv', + 'SwitchToRegisteredAFPoint' => { + Description => 'Activer collimateur enregistré', + PrintConv => { + 'Assist' => 'Touche d\'assistance', + 'Assist + AF' => 'Touche d\'assistance + touche AF', + 'Disable' => 'Désactivé', + 'Enable' => 'Activé', + 'Only while pressing assist' => 'Seulement en appuyant touche d\'assistance', + }, + }, + 'T4Options' => 'Bits de remplissage ajoutés', + 'T6Options' => 'Options T6', + 'TTL_DA_ADown' => 'Segment de mesure flash esclave 6', + 'TTL_DA_AUp' => 'Segment de mesure flash esclave 5', + 'TTL_DA_BDown' => 'Segment de mesure flash esclave 8', + 'TTL_DA_BUp' => 'Segment de mesure flash esclave 7', + 'Tagged' => { + PrintConv => { + 'No' => 'Non', + 'Yes' => 'Oui', + }, + }, + 'TargetPrinter' => 'Imprimante cible', + 'Technology' => { + Description => 'Technologie', + PrintConv => { + 'Active Matrix Display' => 'Afficheur à matrice active', + 'Cathode Ray Tube Display' => 'Afficheur à tube cathodique', + 'Digital Camera' => 'Appareil photo numérique', + 'Dye Sublimation Printer' => 'Imprimante à sublimation thermique', + 'Electrophotographic Printer' => 'Imprimante électrophotographique', + 'Electrostatic Printer' => 'Imprimante électrostatique', + 'Film Scanner' => 'Scanner de film', + 'Flexography' => 'Flexographie', + 'Ink Jet Printer' => 'Imprimante à jet d\'encre', + 'Offset Lithography' => 'Lithographie offset', + 'Passive Matrix Display' => 'Afficheur à matrice passive', + 'Photo CD' => 'CD photo', + 'Photo Image Setter' => 'Cadre photo', + 'Photographic Paper Printer' => 'Imprimante à papier photo', + 'Projection Television' => 'Téléviseur à projection', + 'Reflective Scanner' => 'Scanner à réflexion', + 'Silkscreen' => 'Ecran de soie', + 'Thermal Wax Printer' => 'Imprimante thermique à cire', + 'Video Camera' => 'Caméra vidéo', + 'Video Monitor' => 'Moniteur vidéo', + }, + }, + 'Teleconverter' => { + PrintConv => { + 'None' => 'Aucune', + }, + }, + 'Text' => 'Texte', + 'TextStamp' => { + PrintConv => { + 'Off' => 'Désactivé', + 'On' => 'Activé', + }, + }, + 'Thresholding' => 'Seuil', + 'ThumbnailHeight' => 'Hauteur de la vignette', + 'ThumbnailImage' => 'Vignette', + 'ThumbnailImageSize' => 'Taille des miniatures', + 'ThumbnailLength' => 'Longueur de la vignette', + 'ThumbnailOffset' => 'Décalage de la vignette', + 'ThumbnailWidth' => 'Hauteur de la vignette', + 'TileByteCounts' => 'Nombre d\'octets d\'élément', + 'TileDepth' => 'Profondeur d\'élément', + 'TileLength' => 'Longueur d\'élément', + 'TileOffsets' => 'Décalages d\'élément', + 'TileWidth' => 'Largeur d\'élément', + 'Time' => 'Heure', + 'TimeCreated' => 'Heure de création', + 'TimeScaleParamsQuality' => { + PrintConv => { + 'Low' => 'Bas', + }, + }, + 'TimeSent' => 'Heure d\'envoi', + 'TimeSincePowerOn' => 'Temps écoulé depuis la mise en marche', + 'TimeZone' => 'Fuseau horaire', + 'TimeZoneOffset' => 'Offset de zone de date', + 'TimerLength' => { + Description => 'Durée du retardateur', + PrintConv => { + 'Disable' => 'Désactivé', + 'Enable' => 'Activée', + }, + }, + 'Title' => 'Titre', + 'ToneComp' => 'Correction de tonalité', + 'ToneCurve' => { + Description => 'Courbe de ton', + PrintConv => { + 'Manual' => 'Manuelle', + }, + }, + 'ToneCurveActive' => { + PrintConv => { + 'No' => 'Non', + 'Yes' => 'Oui', + }, + }, + 'ToneCurves' => 'Courbes de ton', + 'ToningEffect' => { + Description => 'Virage', + PrintConv => { + 'Blue' => 'Bleu', + 'Green' => 'Vert', + 'None' => 'Aucune', + 'Red' => 'Rouge', + 'Yellow' => 'Jaune', + 'n/a' => 'Non établie', + }, + }, + 'ToningEffectMonochrome' => { + PrintConv => { + 'Blue' => 'Bleu', + 'Green' => 'Vert', + 'None' => 'Aucune', + }, + }, + 'ToningSaturation' => 'Saturation du virage', + 'TransferFunction' => 'Fonction de transfert', + 'TransferRange' => 'Intervalle de transfert', + 'Transformation' => { + PrintConv => { + 'Horizontal (normal)' => '0° (haut/gauche)', + 'Mirror horizontal' => '0° (haut/droit)', + 'Mirror horizontal and rotate 270 CW' => '90° sens horaire (gauche/haut)', + 'Mirror horizontal and rotate 90 CW' => '90° sens antihoraire (droit/bas)', + 'Mirror vertical' => '180° (bas/gauche)', + 'Rotate 180' => '180° (bas/droit)', + 'Rotate 270 CW' => '90° sens horaire (gauche/bas)', + 'Rotate 90 CW' => '90° sens antihoraire (droit/haut)', + }, + }, + 'TransmissionReference' => 'Référence transmission', + 'TransparencyIndicator' => 'Indicateur de transparence', + 'TrapIndicator' => 'Indicateur de piège', + 'Trapped' => { + Description => 'Piégé', + PrintConv => { + 'False' => 'Faux', + 'True' => 'Vrai', + 'Unknown' => 'Inconnu', + }, + }, + 'TravelDay' => 'Date du Voyage', + 'TvExposureTimeSetting' => 'Réglage de temps de pose Tv', + 'URL' => 'URL ', + 'USMLensElectronicMF' => { + Description => 'MF électronique à objectif USM', + PrintConv => { + 'Always turned off' => 'Toujours débrayé', + 'Disable after one-shot AF' => 'Désactivée après One-Shot AF', + 'Disable in AF mode' => 'Désactivée en mode AF', + 'Enable after one-shot AF' => 'Activée après AF One-Shot', + 'Turns off after one-shot AF' => 'Débrayé après One-Shot AF', + 'Turns on after one-shot AF' => 'Activé après One-Shot AF', + }, + }, + 'Uncompressed' => { + Description => 'Non.comprimé', + PrintConv => { + 'No' => 'Non', + 'Yes' => 'Oui', + }, + }, + 'UniqueCameraModel' => 'Nom unique de modèle d\'appareil', + 'UniqueDocumentID' => 'ID unique de document', + 'UniqueObjectName' => 'Nom Unique d\'Objet', + 'Unknown' => 'Inconnu', + 'Unsharp1Color' => { + PrintConv => { + 'Blue' => 'Bleu', + 'Green' => 'Vert', + 'RGB' => 'RVB', + 'Red' => 'Rouge', + 'Yellow' => 'Jaune', + }, + }, + 'Unsharp2Color' => { + PrintConv => { + 'Blue' => 'Bleu', + 'Green' => 'Vert', + 'RGB' => 'RVB', + 'Red' => 'Rouge', + 'Yellow' => 'Jaune', + }, + }, + 'Unsharp3Color' => { + PrintConv => { + 'Blue' => 'Bleu', + 'Green' => 'Vert', + 'RGB' => 'RVB', + 'Red' => 'Rouge', + 'Yellow' => 'Jaune', + }, + }, + 'Unsharp4Color' => { + PrintConv => { + 'Blue' => 'Bleu', + 'Green' => 'Vert', + 'RGB' => 'RVB', + 'Red' => 'Rouge', + 'Yellow' => 'Jaune', + }, + }, + 'UnsharpMask' => { + PrintConv => { + 'Off' => 'Désactivé', + 'On' => 'Activé', + }, + }, + 'Urgency' => { + Description => 'Urgence', + PrintConv => { + '0 (reserved)' => '0 (réservé pour utilisation future)', + '1 (most urgent)' => '1 (très urgent)', + '5 (normal urgency)' => '5 (normalement urgent)', + '8 (least urgent)' => '8 (moins urgent)', + '9 (user-defined priority)' => '9 (réservé pour utilisation future)', + }, + }, + 'UsableMeteringModes' => { + Description => 'Sélectionner modes de mesure', + PrintConv => { + 'Disable' => 'Désactivé', + 'Enable' => 'Activée', + }, + }, + 'UsableShootingModes' => { + Description => 'Sélectionner modes de prise de vue', + PrintConv => { + 'Disable' => 'Désactivé', + 'Enable' => 'Activée', + }, + }, + 'UsageTerms' => 'Conditions d\'Utilisation', + 'UserComment' => 'Commentaire utilisateur', + 'UserDef1PictureStyle' => { + PrintConv => { + 'Landscape' => 'Paysage', + }, + }, + 'UserDef2PictureStyle' => { + PrintConv => { + 'Landscape' => 'Paysage', + }, + }, + 'UserDef3PictureStyle' => { + PrintConv => { + 'Landscape' => 'Paysage', + }, + }, + 'VRDVersion' => 'Version VRD', + 'VRInfo' => 'Information stabilisateur', + 'VRInfoVersion' => 'Info Version VR', + 'VR_0x66' => { + PrintConv => { + 'Off' => 'Désactivé', + }, + }, + 'VariProgram' => 'Variprogramme', + 'VibrationReduction' => { + Description => 'Reduction des vibrations', + PrintConv => { + 'Off' => 'Désactivé', + 'On' => 'Activé', + 'n/a' => 'Non établie', + }, + }, + 'VideoCardGamma' => 'Gamma de la carte vidéo', + 'ViewInfoDuringExposure' => { + Description => 'Infos viseur pendant exposition', + PrintConv => { + 'Disable' => 'Désactivé', + 'Enable' => 'Activé', + }, + }, + 'ViewfinderWarning' => { + PrintConv => { + 'Off' => 'Désactivé', + 'On' => 'Activé', + }, + }, + 'ViewingCondDesc' => 'Description des conditions de visionnage', + 'ViewingCondIlluminant' => 'Illuminant des conditions de visionnage', + 'ViewingCondIlluminantType' => 'Type d\'illuminant des conditions de visionnage', + 'ViewingCondSurround' => 'Environnement des conditions de visionnage', + 'VignetteControl' => { + Description => 'Controle du vignettage', + PrintConv => { + 'High' => 'Haut', + 'Low' => 'Bas', + 'Normal' => 'Normale', + 'Off' => 'Désactivé', + 'On' => 'Activé', + }, + }, + 'VoiceMemo' => { + PrintConv => { + 'Off' => 'Désactivé', + 'On' => 'Activé', + }, + }, + 'WBAdjLighting' => { + PrintConv => { + 'Daylight (cloudy)' => 'Lumière du jour (2)', + 'Daylight (direct sunlight)' => 'Lumière du jour (0)', + 'Daylight (shade)' => 'Lumière du jour (1)', + 'None' => 'Aucune', + }, + }, + 'WBBlueLevel' => 'Niveau Bleu Balance des Blancs', + 'WBBracketMode' => { + PrintConv => { + 'Off' => 'Désactivé', + }, + }, + 'WBFineTuneActive' => { + PrintConv => { + 'No' => 'Non', + 'Yes' => 'Oui', + }, + }, + 'WBGreenLevel' => 'Niveau Vert Balance des Blancs', + 'WBMediaImageSizeSetting' => { + Description => 'Réglage de balance des blancs + taille d\'image', + PrintConv => { + 'LCD monitor' => 'Écran LCD', + 'Rear LCD panel' => 'Panneau LCD arrière', + }, + }, + 'WBRedLevel' => 'Niveau Rouge Balance des Blancs', + 'WBShiftAB' => 'Décalage Balance Blancs ambre-bleu', + 'WBShiftGM' => 'Décalage Balance Blancs vert-magenta', + 'WB_GBRGLevels' => 'Niveaux BB VBRV', + 'WB_GRBGLevels' => 'Niveaux BB VRBV', + 'WB_GRGBLevels' => 'Niveaux BB VRVB', + 'WB_RBGGLevels' => 'Niveaux BB RBVV', + 'WB_RBLevels' => 'Niveaux BB RB', + 'WB_RBLevels3000K' => 'Niveaux BB RB 3000K', + 'WB_RBLevels3300K' => 'Niveaux BB RB 3300K', + 'WB_RBLevels3600K' => 'Niveaux BB RB 3600K', + 'WB_RBLevels3900K' => 'Niveaux BB RB 3800K', + 'WB_RBLevels4000K' => 'Niveaux BB RB 4000K', + 'WB_RBLevels4300K' => 'Niveaux BB RB 4300K', + 'WB_RBLevels4500K' => 'Niveaux BB RB 4500K', + 'WB_RBLevels4800K' => 'Niveaux BB RB 4800K', + 'WB_RBLevels5300K' => 'Niveaux BB RB 5300K', + 'WB_RBLevels6000K' => 'Niveaux BB RB 6000K', + 'WB_RBLevels6600K' => 'Niveaux BB RB 6600K', + 'WB_RBLevels7500K' => 'Niveaux BB RB 7500K', + 'WB_RBLevelsCloudy' => 'Niveaux BB RB nuageux', + 'WB_RBLevelsShade' => 'Niveaux BB RB ombre', + 'WB_RBLevelsTungsten' => 'Niveaux BB RB tungstène', + 'WB_RGBGLevels' => 'Niveaux BB RVBV', + 'WB_RGBLevels' => 'Niveaux BB RVB', + 'WB_RGBLevelsCloudy' => 'Niveaux BB RVB nuageux', + 'WB_RGBLevelsDaylight' => 'Niveaux BB RVB lumière jour', + 'WB_RGBLevelsFlash' => 'Niveaux BB RVB flash', + 'WB_RGBLevelsFluorescent' => 'Niveaux BB RVB fluorescent', + 'WB_RGBLevelsShade' => 'Niveaux BB RVB ombre', + 'WB_RGBLevelsTungsten' => 'Niveaux BB RVB tungstène', + 'WB_RGGBLevels' => 'Niveaux BB RVVB', + 'WB_RGGBLevelsCloudy' => 'Niveaux BB RVVB nuageux', + 'WB_RGGBLevelsDaylight' => 'Niveaux BB RVVB lumière jour', + 'WB_RGGBLevelsFlash' => 'Niveaux BB RVVB flash', + 'WB_RGGBLevelsFluorescent' => 'Niveaux BB RVVB fluorescent', + 'WB_RGGBLevelsFluorescentD' => 'Niveaux BB RVVB fluorescent', + 'WB_RGGBLevelsFluorescentN' => 'Niveaux BB RVVB fluo N', + 'WB_RGGBLevelsFluorescentW' => 'Niveaux BB RVVB fluo W', + 'WB_RGGBLevelsShade' => 'Niveaux BB RVVB ombre', + 'WB_RGGBLevelsTungsten' => 'Niveaux BB RVVB tungstène', + 'WCSProfiles' => 'Profil Windows Color System', + 'Warning' => 'Attention', + 'WebStatement' => 'Relevé Web', + 'WhiteBalance' => { + Description => 'Balance des blancs', + PrintConv => { + 'Auto' => 'Equilibrage des blancs automatique', + 'Black & White' => 'Monochrome', + 'Cloudy' => 'Temps nuageux', + 'Color Temperature/Color Filter' => 'Temp. Couleur / Filtre couleur', + 'Cool White Fluorescent' => 'Fluorescente type soft', + 'Custom' => 'Personnalisée', + 'Custom 1' => 'Personnalisée 1', + 'Custom 2' => 'Personnalisée 2', + 'Custom 3' => 'Personnalisée 3', + 'Custom 4' => 'Personnalisée 4', + 'Day White Fluorescent' => 'Fluorescente type blanc', + 'Daylight' => 'Lumière du jour', + 'Daylight Fluorescent' => 'Fluorescente type jour', + 'Fluorescent' => 'Fluorescente', + 'Manual' => 'Manuelle', + 'Manual Temperature (Kelvin)' => 'Température de couleur (Kelvin)', + 'Shade' => 'Ombre', + 'Tungsten' => 'Tungstène (lumière incandescente)', + 'Unknown' => 'Inconnu', + 'User-Selected' => 'Sélectionnée par l\'utilisateur', + 'Warm White Fluorescent' => 'Fluorescent blanc chaud', + 'White Fluorescent' => 'Fluorescent blanc', + }, + }, + 'WhiteBalanceAdj' => { + PrintConv => { + 'Cloudy' => 'Temps nuageux', + 'Daylight' => 'Lumière du jour', + 'Fluorescent' => 'Fluorescente', + 'Off' => 'Désactivé', + 'On' => 'Activé', + 'Shade' => 'Ombre', + 'Tungsten' => 'Tungstène (lumière incandescente)', + }, + }, + 'WhiteBalanceBias' => 'Décalage de Balance des blancs', + 'WhiteBalanceFineTune' => 'Balance des blancs - Réglage fin', + 'WhiteBalanceMode' => { + Description => 'Mode de balance des blancs', + PrintConv => { + 'Auto (Cloudy)' => 'Auto (nuageux)', + 'Auto (Day White Fluorescent)' => 'Auto (fluo jour)', + 'Auto (Daylight Fluorescent)' => 'Auto (fluo lum. jour)', + 'Auto (Daylight)' => 'Auto (lumière du jour)', + 'Auto (Flash)' => 'Auto (flash)', + 'Auto (Shade)' => 'Auto (ombre)', + 'Auto (Tungsten)' => 'Auto (tungstène)', + 'Auto (White Fluorescent)' => 'Auto (fluo blanc)', + 'Unknown' => 'Inconnu', + 'User-Selected' => 'Sélectionnée par l\'utilisateur', + }, + }, + 'WhiteBalanceSet' => { + Description => 'Réglage de balance des blancs', + PrintConv => { + 'Cloudy' => 'Temps nuageux', + 'Day White Fluorescent' => 'Fluorescent blanc jour', + 'Daylight' => 'Lumière du jour', + 'Daylight Fluorescent' => 'Fluorescente type jour', + 'Manual' => 'Manuelle', + 'Set Color Temperature 1' => 'Température de couleur définie 1', + 'Set Color Temperature 2' => 'Température de couleur définie 2', + 'Set Color Temperature 3' => 'Température de couleur définie 3', + 'Shade' => 'Ombre', + 'Tungsten' => 'Tungstène (lumière incandescente)', + 'White Fluorescent' => 'Fluorescent blanc', + }, + }, + 'WhiteLevel' => 'Niveau blanc', + 'WhitePoint' => 'Chromaticité du point blanc', + 'WideRange' => { + PrintConv => { + 'Off' => 'Désactivé', + 'On' => 'Activé', + }, + }, + 'WorldTime' => 'Fuseau horaire', + 'WorldTimeLocation' => { + Description => 'Position en temps mondial', + PrintConv => { + 'Home' => 'Départ', + 'Hometown' => 'Résidence', + }, + }, + 'Writer-Editor' => 'Auteur de la légende / description', + 'XClipPathUnits' => 'Unités de chemin de rognage en X', + 'XMP' => 'Métadonnées XMP', + 'XPAuthor' => 'Auteur', + 'XPComment' => 'Commentaire', + 'XPKeywords' => 'Mots clé', + 'XPSubject' => 'Sujet', + 'XPTitle' => 'Titre', + 'XPosition' => 'Position en X', + 'XResolution' => 'Résolution d\'image horizontale', + 'YCbCrCoefficients' => 'Coefficients de la matrice de transformation de l\'espace de couleurs', + 'YCbCrPositioning' => { + Description => 'Positionnement Y et C', + PrintConv => { + 'Centered' => 'Centré', + 'Co-sited' => 'Côte à côte', + }, + }, + 'YCbCrSubSampling' => 'Rapport de sous-échantillonnage Y à C', + 'YClipPathUnits' => 'Unités de chemin de rognage en Y', + 'YPosition' => 'Position en Y', + 'YResolution' => 'Résolution d\'image verticale', + 'Year' => 'Année', + 'ZoneMatching' => { + Description => 'Ajustage de la zone', + PrintConv => { + 'High Key' => 'Hi', + 'ISO Setting Used' => 'Désactivée', + 'Low Key' => 'Lo', + }, + }, + 'ZoneMatchingOn' => { + PrintConv => { + 'Off' => 'Désactivé', + 'On' => 'Activé', + }, + }, +); + +1; # end + + +__END__ + +=head1 NAME + +Image::ExifTool::Lang::fr.pm - ExifTool French language translations + +=head1 DESCRIPTION + +This file is used by Image::ExifTool to generate localized tag descriptions +and values. + +=head1 AUTHOR + +Copyright 2003-2019, Phil Harvey (phil at owl.phy.queensu.ca) + +This library is free software; you can redistribute it and/or modify it +under the same terms as Perl itself. + +=head1 ACKNOWLEDGEMENTS + +Thanks to Jens Duttke, Bernard Guillotin, Jean Glasser, Jean Piquemal, Harry +Nizard and Alphonse Philippe for providing this translation. + +=head1 SEE ALSO + +L<Image::ExifTool(3pm)|Image::ExifTool>, +L<Image::ExifTool::TagInfoXML(3pm)|Image::ExifTool::TagInfoXML> + +=cut diff --git a/lib/Image/ExifTool/Lang/it.pm b/lib/Image/ExifTool/Lang/it.pm new file mode 100644 index 0000000..5a7ce8e --- /dev/null +++ b/lib/Image/ExifTool/Lang/it.pm @@ -0,0 +1,7918 @@ +#------------------------------------------------------------------------------ +# File: it.pm +# +# Description: ExifTool Italian language translations +# +# Notes: This file generated automatically by Image::ExifTool::TagInfoXML +#------------------------------------------------------------------------------ + +package Image::ExifTool::Lang::it; + +use strict; +use vars qw($VERSION); + +$VERSION = '1.13'; + +%Image::ExifTool::Lang::it::Translate = ( + 'A100DataOffset' => 'Offset dati A100', + 'AAFManufacturerID' => 'ID AAF produttore', + 'ACoordOfBottomRightCorner' => 'Una coord in basso a destra', + 'ACoordOfTopRightCorner' => 'Una coord in alto a destra', + 'AEAperture' => 'Apertura esposizione automatica', + 'AEBAutoCancel' => { + PrintConv => { + 'Off' => 'Spento', + }, + }, + 'AEBSequenceAutoCancel' => { + PrintConv => { + '-,0,+/Disabled' => '-,0,+/Disabilitato', + '-,0,+/Enabled' => '-,0,+/Abilitato', + '0,-,+/Disabled' => '0,-,+/Disabilitato', + '0,-,+/Enabled' => '0,-,+/Abilitato', + }, + }, + 'AEExposureTime' => 'Durata esposizione automatica', + 'AEFlags' => { + Description => 'Flag esposizione automatica', + PrintConv => { + 'AE lock' => 'Blocco esposizione automatica', + 'Aperture wide open' => 'Diaframma molto aperto', + 'Flash recommended?' => 'Flash consigliato?', + }, + }, + 'AELExposureIndicator' => { + PrintConv => { + 'Not Indicated' => 'Non indicato', + }, + }, + 'AELock' => { + Description => 'Blocco esposizione automatica', + PrintConv => { + 'Off' => 'Spento', + 'On' => 'Acceso', + }, + }, + 'AELockButton' => { + Description => 'Pulsante blocco esposizione automatica', + PrintConv => { + 'Flash Off' => 'Flash spento', + 'None' => 'Nessuno', + 'Preview' => 'Anteprima', + 'Virtual Horizon' => 'Orizzonte virtuale', + }, + }, + 'AELockButtonPlusDials' => { + PrintConv => { + 'Choose Image Area' => 'Seleziona area immagine', + 'None' => 'Nessuno', + }, + }, + 'AEMeteringMode' => { + PrintConv => { + 'Center-weighted average' => 'Media centrale ponderata', + 'Multi-segment' => 'Multi zona', + }, + }, + 'AEMicroadjustment' => { + PrintConv => { + 'Enable' => 'Abilita', + }, + }, + 'AEProgramMode' => { + PrintConv => { + 'Kids' => 'Bambini', + 'Landscape' => 'Orizzontale', + 'No Flash' => 'No flash', + 'Portrait' => 'Verticale', + 'Program' => 'Programma', + 'Sunset' => 'Tramonto', + 'Text' => 'Testo', + }, + }, + 'AESetting' => { + PrintConv => { + 'Exposure Compensation' => 'Compensazione esposizione', + }, + }, + 'AE_ISO' => 'ISO esposizione automatica', + 'AFAndMeteringButtons' => { + PrintConv => { + 'No function' => 'Nessuna funzione', + }, + }, + 'AFAperture' => 'Diaframma AF', + 'AFAreaIllumination' => { + PrintConv => { + 'Off' => 'Spento', + }, + }, + 'AFAreaMode' => { + Description => 'Modo AF', + PrintConv => { + 'Dynamic Area' => 'Area Dinamica', + 'Dynamic Area (closest subject)' => 'Area Dinamica più Vicina al Soggetto', + 'Group Dynamic' => 'Gruppo Dinamico', + 'Local' => 'Locale', + 'Off (Manual Focus)' => 'Spento (focus manuale)', + 'Single Area' => 'Area Singola', + }, + }, + 'AFAssist' => { + PrintConv => { + 'Off' => 'Spento', + }, + }, + 'AFDuringLiveView' => { + PrintConv => { + 'Enable' => 'Abilita', + 'Quick mode' => 'Modo veloce', + }, + }, + 'AFFineTune' => { + PrintConv => { + 'Off' => 'Spento', + }, + }, + 'AFIlluminator' => { + PrintConv => { + 'Off' => 'Spento', + 'n/a' => 'n/d', + }, + }, + 'AFInfo' => 'Modo AF', + 'AFMode' => { + Description => 'Modo AF', + PrintConv => { + 'Off' => 'Spento', + 'n/a' => 'n/d', + }, + }, + 'AFOnAELockButtonSwitch' => { + PrintConv => { + 'Enable' => 'Abilita', + }, + }, + 'AFPoint' => { + Description => 'Punto AF', + PrintConv => { + '(none)' => '(nessuno)', + 'Bottom' => 'Basso', + 'Center' => 'Centro', + 'Far Left' => 'Tutto a sinistra', + 'Far Right' => 'Tutto a destra', + 'Left' => 'Sinistra', + 'Lower-left' => 'Inferiore sinistro', + 'Lower-right' => 'Inferiore destro', + 'Mid-left' => 'Centro/Sinistra', + 'Mid-right' => 'Centro/Destra', + 'None' => 'Nessuno', + 'Right' => 'Destra', + 'Right (horizontal)' => 'Destra (orizzontale)', + 'Right (vertical)' => 'Destra (verticale)', + 'Top' => 'Alto', + 'Upper-left' => 'Superiore sinistro', + 'Upper-right' => 'Superiore destro', + }, + }, + 'AFPointActivationArea' => { + PrintConv => { + 'Expanded' => 'Espanso', + }, + }, + 'AFPointAreaExpansion' => { + PrintConv => { + 'Enable' => 'Abilita', + }, + }, + 'AFPointBrightness' => { + PrintConv => { + 'Low' => 'Basso', + 'Normal' => 'Normale', + }, + }, + 'AFPointDisplayDuringFocus' => { + PrintConv => { + 'Off' => 'Spento', + }, + }, + 'AFPointIllumination' => { + PrintConv => { + 'Off' => 'Spento', + }, + }, + 'AFPointMode' => { + PrintConv => { + 'Fixed Center' => 'Centro fisso', + 'Select' => 'Seleziona', + }, + }, + 'AFPointRegistration' => { + PrintConv => { + 'Bottom' => 'Basso', + 'Center' => 'Centro', + 'Extreme Left' => 'Tutto a Sinistra', + 'Extreme Right' => 'Tutto a Destra', + 'Left' => 'Sinistra', + 'Right' => 'Destra', + 'Top' => 'Alto', + }, + }, + 'AFPointSelected' => { + PrintConv => { + 'Bottom' => 'Basso', + 'Center' => 'Centro', + 'Far Left' => 'Tutto a sinistra', + 'Far Right' => 'Tutto a destra', + 'Fixed Center' => 'Centro fisso', + 'Left' => 'Sinistra', + 'None' => 'Nessuno', + 'Right' => 'Destra', + 'Top' => 'Alto', + }, + }, + 'AFPointSelected2' => { + PrintConv => { + 'Center' => 'Centro', + 'Left' => 'Sinistra', + 'Right' => 'Destra', + }, + }, + 'AFPointSelection' => { + PrintConv => { + '11 Points' => '11 punti', + }, + }, + 'AFPointSelectionMethod' => { + PrintConv => { + 'Normal' => 'Normale', + }, + }, + 'AFPoints' => { + PrintConv => { + 'Center' => 'Centro', + 'Left' => 'Sinistra', + 'Right' => 'Destra', + }, + }, + 'AFPointsInFocus' => { + Description => 'Punti a fuoco', + PrintConv => { + 'Bottom' => 'Basso', + 'Center' => 'Centro', + 'Far Left' => 'Tutto a sinistra', + 'Far Right' => 'Tutto a destra', + 'Left' => 'Sinistra', + 'Lower-left' => 'Inferiore sinistro', + 'Lower-right' => 'Inferiore destro', + 'None' => 'Nessuno', + 'Right' => 'Destra', + 'Top' => 'Alto', + 'Upper-left' => 'Superiore sinistro', + 'Upper-right' => 'Superiore destro', + }, + }, + 'AFPointsInFocus1D' => 'Punti a fuoco 1D', + 'AFPointsInFocus5D' => { + Description => 'Punti a fuoco 5D', + PrintConv => { + 'Center' => 'Centro', + 'Left' => 'Sinistra', + 'Right' => 'Destra', + }, + }, + 'AFPointsUnknown1' => { + PrintConv => { + 'Center' => 'Centro', + 'Left' => 'Sinistra', + 'Right' => 'Destra', + }, + }, + 'AFPointsUnknown2' => { + PrintConv => { + 'Center' => 'Centro', + 'Left' => 'Sinistra', + 'Right' => 'Destra', + }, + }, + 'AFPointsUsed' => { + PrintConv => { + 'Bottom' => 'Basso', + 'Center' => 'Centro', + 'Far Left' => 'Tutto a sinistra', + 'Far Right' => 'Tutto a destra', + 'Lower-left' => 'Inferiore sinistro', + 'Lower-right' => 'Inferiore destro', + 'Top' => 'Alto', + 'Upper-left' => 'Superiore sinistro', + 'Upper-right' => 'Superiore destro', + }, + }, + 'AFSearch' => { + PrintConv => { + 'Not Ready' => 'Non pronto', + 'Ready' => 'Pronto', + }, + }, + 'AFWithShutter' => { + PrintConv => { + 'Off' => 'Spento', + }, + }, + 'AIServoImagePriority' => { + PrintConv => { + '1: AF, 2: Drive speed' => '1: AF, 2: drive speed', + '1: AF, 2: Tracking' => '1: AF, 2: puntamento', + '1: Release, 2: Drive speed' => '1: rilascio, 2: drive speed', + '1: Release, 2: Tracking' => '1: rilascio, 2: puntamento', + }, + }, + 'AIServoTrackingSensitivity' => { + PrintConv => { + 'Fast' => 'Veloce', + }, + }, + 'APEVersion' => 'Versione APE', + 'ARMIdentifier' => 'ID ARM', + 'ARMVersion' => 'Versione ARM', + 'AToB0' => 'Da A a B0', + 'AToB1' => 'Da A a B1', + 'AToB2' => 'Da A a B2', + 'AberrationCorrectionDistance' => 'Distanza della correzione di aberrazione', + 'About' => 'Informazioni su', + 'AbsPeakAudioFilePath' => 'Percorso file audio del picco assoluto', + 'AbsoluteChannelDisplayScale' => 'Scala assoluta canale', + 'Abstract' => 'Sommario', + 'AbstractPriorCodeSequence' => 'Sequenza codice precedente astratto', + 'AbstractPriorValue' => 'Valore codice precedente astratto', + 'AccessDate' => 'Data di accesso', + 'AccessionNumber' => 'Numero di adesione', + 'AccessoryCode' => 'Codice accessorio', + 'AccessoryType' => 'Tipo accessorio', + 'AccountName' => 'Nome account', + 'AccountingReferenceNumber' => 'Riferimento contabile', + 'AcqreconRecordChecksum' => 'Checksum del record AcqRecon', + 'AcquiredImageAreaDoseProduct' => 'Dose prodotto dell\'area acquisita', + 'AcquisitionComments' => 'Commenti acquisizione', + 'AcquisitionContextDescription' => 'Descrizione contesto acquisizione', + 'AcquisitionContextSequence' => 'Sequenza contesto acquisizione', + 'AcquisitionContrast' => 'Contrasto acquisizione', + 'AcquisitionDate' => 'Data acquisizione', + 'AcquisitionDateTime' => 'Data/ora acquisizione', + 'AcquisitionDeviceProcessingCode' => 'Codice processo di acquisizione del dispositivo', + 'AcquisitionDeviceProcessingDescr' => 'Descrizione processo di acquisizione del dispositivo', + 'AcquisitionDeviceTypeCodeSequence' => 'Sequenza codici tipo di acquisizione del dispositivo', + 'AcquisitionDuration' => 'Durata acquisizione', + 'AcquisitionEndConditionData' => 'Dati condizione fine acquisizione', + 'AcquisitionGroupLength' => 'Lunghezza gruppo di acquisizione', + 'AcquisitionIndex' => 'Indice acquisizione', + 'AcquisitionMatrix' => 'Matrice acquisizione', + 'AcquisitionNumber' => 'Numero acquisizione', + 'AcquisitionProtocolDescription' => 'Descrizione protocollo di acquisizione', + 'AcquisitionProtocolName' => 'Nome protocollo di acquisizione', + 'AcquisitionStartCondition' => 'Condizione iniziale acquisizione', + 'AcquisitionStartConditionData' => 'Dati condizione iniziale acquisizione', + 'AcquisitionTerminationCondition' => 'Condizione finale acquisizione', + 'AcquisitionTime' => 'Ora acquisizione', + 'AcquisitionTimeDay' => 'Ora acquisizione - Giorno', + 'AcquisitionTimeMonth' => 'Ora acquisizione - Mese', + 'AcquisitionTimeSynchronized' => 'Ora acquisizione sincronizzata', + 'AcquisitionTimeYear' => 'Ora acquisizione - Anno', + 'AcquisitionTimeYearMonth' => 'Ora acquisizione - Anno mese', + 'AcquisitionTimeYearMonthDay' => 'Ora acquisizione - Anno mese giorno', + 'AcquisitionType' => 'Tipo acquisizione', + 'AcquisitionsInSeries' => 'Acquisizioni in serie', + 'AcquisitionsInStudy' => 'Acquisizioni in esame', + 'AcrossScanSpatialResolution' => 'Attraverso risoluzione di scansione spaziale', + 'ActionAdvised' => { + Description => 'Azione consigliata', + PrintConv => { + 'Object Append' => 'Allega oggetto', + 'Object Kill' => 'Distruzione oggetto', + 'Object Reference' => 'Riferimento oggetto', + 'Object Replace' => 'Sostituzione oggetto', + }, + }, + 'ActiveArea' => 'Area attiva', + 'ActiveD-Lighting' => { + Description => 'D-Lighting attivo', + PrintConv => { + 'Extra High' => 'Molto alto', + 'High' => 'Alto', + 'Low' => 'Basso', + 'Normal' => 'Normale', + 'Off' => 'Spento', + 'On' => 'Acceso', + }, + }, + 'ActiveD-LightingMode' => { + Description => 'Modalità D-Lighting attiva', + PrintConv => { + 'Extra High' => 'Molto alto', + 'High' => 'Alto', + 'Low' => 'Basso', + 'Normal' => 'Normale', + 'Off' => 'Spento', + 'Unchanged' => 'Immutato', + }, + }, + 'ActiveFormatDescriptor' => 'Descrittore formato attivo', + 'ActiveLinesperFrame' => 'Linee per quadro attuali', + 'ActiveSamplesperLine' => 'Linee per campione attuali', + 'ActiveSourceDiameter' => 'Diametro sorgente attuale', + 'ActiveSourceLength' => 'Lunghezza sorgente attuale', + 'ActiveState' => 'Stato attivo', + 'Actor' => 'Attore', + 'ActualCardiacTriggerDelayTime' => 'Tempo di ritardo corrente trigger cardiaco', + 'ActualCompensation' => 'Compensazione corrente', + 'ActualFrameDuration' => 'Durata frame attuale', + 'ActualHumanPerformersSequence' => 'Sequenza attuale esecutori umani', + 'ActualReceiveGainAnalog' => 'Guadagno analogico in ricezione attuale', + 'ActualReceiveGainDigital' => 'Guadagno digitale in ricezione attuale', + 'ActualRespiratoryTriggerDelayTime' => 'Tempo di ritardo corrente trigger respiratorio', + 'ActualSeriesDataTimeStamp' => 'Marca temporale serie di dati attuali', + 'Ad-ID' => 'ID Ad', + 'AdaptiveMapFormat' => 'Formato mappa adattativa', + 'AddAspectRatioInfo' => { + Description => 'Aggiunta info rapporto di aspetto', + PrintConv => { + 'Off' => 'Spento', + }, + }, + 'AddIntermediateSequence' => 'Aggiunta sequenza intermedia', + 'AddNearSequence' => 'Aggiunta sequenza vicina', + 'AddOriginalDecisionData' => { + Description => 'Aggiunta dati decisione originale', + PrintConv => { + 'Off' => 'Spento', + 'On' => 'Acceso', + }, + }, + 'AddOtherSequence' => 'Aggiunta altra sequenza', + 'AddPower' => 'Aggiunta potenza', + 'AdditionalDrugSequence' => 'Sequenza farmaci addizionali', + 'AdditionalModelInformation' => 'Ulteriori informazioni modello', + 'AdditionalPatientHistory' => 'Ulteriore storia del paziente', + 'Address' => 'Indirizzo', + 'AddressLine' => 'Linea indirizzo', + 'AddressNameValueSets' => 'Gruppi di valori nome indirizzo', + 'AddressSets' => 'Gruppi di indirizzi', + 'AddressTrial' => 'Studio indirizzo', + 'AdjustmentMode' => 'Modo adattamento', + 'AdministrationRouteCodeSequence' => 'Sequenza codici percorso di amministrazione', + 'AdmissionID' => 'ID ammissione', + 'AdmittingDate' => 'Data ammissione', + 'AdmittingDiagnosesCodeSequence' => 'Sequenza codici diagnosi ammissione', + 'AdmittingDiagnosesDescription' => 'Descrizioni diagnosi ammissione', + 'AdmittingTime' => 'Ora ammissione', + 'AdobeCMType' => 'Tipo Adobe CM', + 'AdoptedNeutral' => 'Adottato neutro', + 'AdultContentWarning' => { + Description => 'Avviso contenuto per adulti', + PrintConv => { + 'Adult Content Warning Required' => 'Avviso contenuto per adulti richiesto', + 'Not Required' => 'Non richiesto', + 'Unknown' => 'Sconosciuto', + }, + }, + 'AdvancedContentEncryption' => 'Crittografia avanzata del contenuto', + 'AdvancedMutualExcl' => 'Mutua esclusione avanzata', + 'AdvancedRaw' => { + Description => 'Raw avanzato', + PrintConv => { + 'Off' => 'Spento', + 'On' => 'Acceso', + }, + }, + 'AdvancedSceneMode' => { + Description => 'Modo scena avanzato', + PrintConv => { + 'Architecture' => 'Architettura', + 'Color Select' => 'Selezione colore', + 'Creative Macro' => 'Macro creativo', + 'Creative Night Scenery' => 'Scenario notturno creativo', + 'Creative Portrait' => 'Ritratto creativo', + 'Creative Scenery' => 'Scenario creativo', + 'Creative Sports' => 'Sport creativi', + 'Cross Process' => 'Cross process', + 'Dynamic Art' => 'Arte dinamica', + 'Dynamic Monochrome' => 'Monocromatico dinamico', + 'Elegant' => 'Elegante', + 'Expressive' => 'Espressivo', + 'Flower' => 'Fiore', + 'HDR Art' => 'HDR artistico', + 'HDR B&W' => 'HDR in bianco e nero', + 'High Dynamic' => 'High dynamic', + 'High Key' => 'High key', + 'Illuminations' => 'Illuminazioni', + 'Indoor Portrait' => 'Ritratto al chiuso', + 'Indoor Sports' => 'Sport al chiuso', + 'Low Key' => 'Low key', + 'Minature' => 'Minuatura', + 'Monochrome' => 'Monocromatico', + 'Nature' => 'Natura', + 'Objects' => 'Oggetti', + 'Off' => 'Spento', + 'Outdoor Portrait' => 'Ritratto all\'aperto', + 'Outdoor Sports' => 'Sport all\'aperto', + 'Pure' => 'Puro', + 'Retro' => 'Retrò', + 'Sepia' => 'Seppia', + 'Soft' => 'Morbido', + 'Star' => 'Stella', + 'Toy Effect' => 'Effetto giocattolo', + }, + }, + 'AdvancedSceneType' => 'Tipo scena avanzato', + 'AdvantageCompOverflow' => 'Overflow componente avanzato', + 'AdvantageCompUnderflow' => 'Underflow componente avanzato', + 'AdventRevision' => 'Revisione arrivo', + 'AdventScale' => 'Scala arrivo', + 'AdvertisingMaterialReference' => 'Riferimento materiale pubblicitario', + 'Advisory' => 'Consultivo', + 'AlbumArtistSortOrder' => 'Ordinamento album-artista', + 'AlbumSortOrder' => 'Ordinamento album', + 'AliasLayerMetadata' => 'Livello metadati alias', + 'AlphaByteCount' => 'Numero byte trasparenza', + 'AlphaDataDiscard' => { + Description => 'Scarto dati trasparenza', + PrintConv => { + 'Flexbits Discarded' => 'Flexbit scartati', + 'Full Resolution' => 'Risoluzione piena', + 'HighPass Frequency Data Discarded' => 'Dati in frequenza passa-alto scartati', + 'Highpass and LowPass Frequency Data Discarded' => 'Dati in frequenza passa-alto e passa-basso scartati', + }, + }, + 'AlphaInterlace' => { + PrintConv => { + 'Noninterlaced' => 'Non interlacciato', + }, + }, + 'AlphaOffset' => 'Scostamento trasparenza', + 'AlphaTransparency' => { + PrintConv => { + 'Not Inverted' => 'Non invertito', + }, + }, + 'AmbienceSelection' => { + PrintConv => { + 'Vivid' => 'Vivace', + }, + }, + 'AnalogBalance' => 'Bilanciamento analogico', + 'Annotation' => 'Annotazione', + 'Annotations' => 'Annotazioni', + 'Anti-Blur' => { + PrintConv => { + 'Off' => 'Spento', + 'n/a' => 'n/d', + }, + }, + 'AntiAliasStrength' => 'Forza antialiasing', + 'Aperture' => 'Diaframma', + 'ApertureDisplayed' => 'Diaframma mostrato', + 'ApertureRange' => { + PrintConv => { + 'Enable' => 'Abilita', + }, + }, + 'ApertureRingUse' => { + PrintConv => { + 'Prohibited' => 'Proibito', + }, + }, + 'ApertureValue' => 'Apertura diaframma', + 'AppleStoreCountry' => { + PrintConv => { + 'Italy' => 'Italia', + 'Japan' => 'Giappone', + 'Norway' => 'Norvegia', + 'Portugal' => 'Portogallo', + 'Sweden' => 'Svezia', + 'United Kingdom' => 'Regno Unito', + 'United States' => 'Stati Uniti', + }, + }, + 'ApplicationNotes' => 'Note applicazione', + 'ApplicationRecordVersion' => 'Versione Registrazione Applicazione', + 'ApplyShootingMeteringMode' => { + PrintConv => { + 'Enable' => 'Abilita', + }, + }, + 'ArtFilter' => { + PrintConv => { + 'Fish Eye' => 'Fish-eye', + 'Fragmented' => 'Frammentato', + 'Gentle Sepia' => 'Seppia leggero', + 'Off' => 'Spento', + 'Reflection' => 'Riflessione', + }, + }, + 'ArtFilterEffect' => { + PrintConv => { + 'Fish Eye' => 'Fish-eye', + 'Fragmented' => 'Frammentato', + 'Gentle Sepia' => 'Seppia leggero', + 'Off' => 'Spento', + 'Reflection' => 'Riflessione', + 'Star Light' => 'Luce stelle', + }, + }, + 'ArtMode' => { + PrintConv => { + 'Normal' => 'Normale', + }, + }, + 'Artist' => 'Persona che ha creato l\'immagine', + 'Artist2' => 'Artista 2', + 'ArtistURL' => 'URL artista', + 'AsShotICCProfile' => 'Profilo ICC allo scatto', + 'AsShotNeutral' => 'Neutrale allo scatto', + 'AsShotPreProfileMatrix' => 'Matrice pre-profilo allo scatto', + 'AsShotProfileName' => 'Nome profilo allo scatto', + 'AsShotWhiteXY' => 'Bilanciamento del bianco X-T allo scatto', + 'AspectRatio' => 'Rapporto immagine', + 'AspectRatioType' => { + Description => 'Tipo rapporto immagine', + PrintConv => { + 'Fixed' => 'Fisso', + }, + }, + 'AspectRatioX' => 'Rapporto immagine X', + 'AspectRatioY' => 'Rapporto immagine Y', + 'AssistButtonFunction' => { + PrintConv => { + 'Normal' => 'Normale', + }, + }, + 'Attachments' => 'Allegati', + 'Audio' => { + PrintConv => { + 'Yes' => 'Sì', + }, + }, + 'AudioAttributes' => { + Description => 'Attributi audio', + PrintConv => { + 'Encrypted' => 'Crittografato', + }, + }, + 'AudioBytes' => 'Byte audio', + 'AudioChannelType' => 'Tipo canale audio', + 'AudioChannels' => 'Canali audio', + 'AudioCodec' => 'Codec audio', + 'AudioCodecDescription' => 'Descrizione codec audio', + 'AudioCodecID' => { + Description => 'ID codec audio', + PrintConv => { + 'QDesign Music' => 'Musica QDesign', + 'Unknown -' => 'Sconosciuto -', + }, + }, + 'AudioCodecInfo' => 'Info codec audio', + 'AudioCodecName' => 'Nome codec audio', + 'AudioCompression' => 'Compressione audio', + 'AudioCompressionAlgorithm' => 'Algoritmo di compressione audio', + 'AudioFormat' => 'Formato audio', + 'AudioLayer' => 'Livello audio', + 'AudioStreamType' => { + PrintConv => { + 'Reserved' => 'Riservato', + }, + }, + 'AudioType' => { + Description => 'Tipo Audio', + PrintConv => { + 'Text Only' => 'Solo testo', + }, + }, + 'Author' => 'Autore', + 'AuthorsPosition' => 'Posizione dell\'autore', + 'AutoAperture' => { + PrintConv => { + 'Off' => 'Spento', + }, + }, + 'AutoBracketModeM' => { + PrintConv => { + 'Flash Only' => 'Solo flash', + }, + }, + 'AutoBracketSet' => { + PrintConv => { + 'Exposure' => 'Esposizione', + 'Flash Only' => 'Solo flash', + }, + }, + 'AutoBracketing' => { + PrintConv => { + 'Off' => 'Spento', + }, + }, + 'AutoDistortionControl' => { + PrintConv => { + 'Off' => 'Spento', + }, + }, + 'AutoExposureBracketing' => { + PrintConv => { + 'Off' => 'Spento', + }, + }, + 'AutoFP' => { + PrintConv => { + 'Off' => 'Spento', + }, + }, + 'AutoFocus' => { + PrintConv => { + 'Off' => 'Spento', + }, + }, + 'AutoISO' => { + PrintConv => { + 'Off' => 'Spento', + }, + }, + 'AutoLightingOptimizer' => { + PrintConv => { + 'Enable' => 'Abilita', + 'Low' => 'Basso', + 'Off' => 'Spento', + 'Strong' => 'Forte', + 'n/a' => 'n/d', + }, + }, + 'AutoLightingOptimizerOn' => { + PrintConv => { + 'Yes' => 'Sì', + }, + }, + 'AutoRedEye' => { + PrintConv => { + 'Off' => 'Spento', + }, + }, + 'AutoRotate' => { + PrintConv => { + 'None' => 'Nessuno', + 'Rotate 180' => 'Ruota di 180°', + 'Rotate 270 CW' => 'Ruota di 270° in senso orario', + 'Rotate 90 CW' => 'Ruota di 90° senso orario', + 'n/a' => 'n/d', + }, + }, + 'AuxiliaryLens' => 'Obiettivo Ausiliario', + 'AvSettingWithoutLens' => { + PrintConv => { + 'Enable' => 'Abilita', + }, + }, + 'AverageLevel' => 'Livello medio', + 'Azimuth' => { + PrintConv => { + 'NNW' => 'NNO', + }, + }, + 'BWMode' => { + PrintConv => { + 'Off' => 'Spento', + }, + }, + 'BackgroundColorIndicator' => { + Description => 'Indicatore colore di sfondo', + PrintConv => { + 'Specified Background Color' => 'Colore di sfondo specificato', + 'Unspecified Background Color' => 'Colore di sfondo non specificato', + }, + }, + 'BackgroundColorValue' => 'Valore colore di sfondo', + 'BackgroundTiling' => { + PrintConv => { + 'Yes' => 'Sì', + }, + }, + 'BadFaxLines' => 'Linee fax non valide', + 'BannerImageType' => { + PrintConv => { + 'None' => 'Nessuno', + }, + }, + 'BaselineExposure' => 'Esposizione di riferimento', + 'BaselineNoise' => 'Rumore di riferimento', + 'BaselineSharpness' => 'Nitidezza di riferimento', + 'BatteryLevel' => 'Livello batteria', + 'BatteryState' => { + PrintConv => { + 'Low' => 'Basso', + }, + }, + 'BeatsPerMinute' => 'Battiti al minuto', + 'Beep' => { + PrintConv => { + 'Low' => 'Basso', + 'Off' => 'Spento', + }, + }, + 'BeepPitch' => { + PrintConv => { + 'Low' => 'Basso', + 'Off' => 'Spento', + }, + }, + 'BeepVolume' => { + PrintConv => { + 'Off' => 'Spento', + }, + }, + 'BestQualityScale' => 'Scala qualità migliore', + 'BestShotMode' => { + PrintConv => { + 'Children' => 'Bambini', + 'Fireworks' => 'Fuochi artificiali', + 'Flower' => 'Fiore', + 'For YouTube' => 'Per YouTube', + 'For eBay' => 'Per eBay', + 'Off' => 'Spento', + 'Retro' => 'Retrò', + 'Scenery' => 'Paesaggio', + 'Short Movie' => 'Filmato breve', + 'Text' => 'Testo', + }, + }, + 'BitsPerComponent' => 'Bits per componente', + 'BitsPerExtendedRunLength' => 'Bit per rrun-length esteso', + 'BitsPerRunLength' => 'Bit per rrun-length', + 'BitsPerSample' => 'Numero di bit per componente', + 'BlackLevel' => 'Livello del nero', + 'BlackLevelDeltaH' => 'Livello del nero - Delta H', + 'BlackLevelDeltaV' => 'Livello del nero - Delta V', + 'BlackLevelRepeatDim' => 'Dim ripeti livello del nero', + 'BleachBypassToning' => { + PrintConv => { + 'Green' => 'Verde', + 'Off' => 'Spento', + 'Purple' => 'Porpora', + 'Red' => 'Rosso', + }, + }, + 'BlocksPerFrame' => 'Blocchi per frame', + 'BlueBalance' => 'Bilanciamento del blu', + 'BlueMatrixColumn' => 'Colonna della Matrice Blu', + 'BlueTRC' => 'Curva riproduzione tono blu', + 'BlurControl' => { + PrintConv => { + 'Low' => 'Basso', + 'Off' => 'Spento', + }, + }, + 'BlurWarning' => { + PrintConv => { + 'None' => 'Nessuno', + }, + }, + 'BracketMode' => { + PrintConv => { + 'Off' => 'Spento', + }, + }, + 'BracketShotNumber' => { + PrintConv => { + '1 of 2' => '1 di 5', + '1 of 3' => '1 di 3', + '1 of 5' => '1 di 2', + 'n/a' => 'n/d', + }, + }, + 'Brightness' => 'Luminosità', + 'BrightnessValue' => 'Valore di luminosità', + 'BuildDate' => 'Data compilazione', + 'BuildVersion' => 'Versione compilazione', + 'BurstMode' => { + PrintConv => { + 'Off' => 'Spento', + }, + }, + 'ButtonFunctionControlOff' => { + PrintConv => { + 'Normal (enable)' => 'Normale (abilitato)', + }, + }, + 'By-line' => 'Creatore', + 'By-lineTitle' => 'Titolo Creatore', + 'CCDScanMode' => { + PrintConv => { + 'Progressive' => 'Progressivo', + }, + }, + 'CFALayout' => { + Description => 'Layout CFA', + PrintConv => { + 'Even columns offset down 1/2 row' => 'Colonne pari giù di 1/2 riga', + 'Even columns offset up 1/2 row' => 'Colonne pari su di 1/2 riga', + 'Even rows offset down by 1/2 row, even columns offset left by 1/2 column' => 'Righe pari giù di 1/2 riga, colonne pari a sinistra di 1/2 colonna', + 'Even rows offset down by 1/2 row, even columns offset right by 1/2 column' => 'Righe pari giù di 1/2 riga, colonne pari a destra di 1/2 colonna', + 'Even rows offset left 1/2 column' => 'Righe pari a sinistra di 1/2 colonna', + 'Even rows offset right 1/2 column' => 'Righe pari a destra di 1/2 colonna', + 'Even rows offset up by 1/2 row, even columns offset left by 1/2 column' => 'Righe pari su 1/2 riga, colonne pari a sinistra di 1/2 colonna', + 'Even rows offset up by 1/2 row, even columns offset right by 1/2 column' => 'Righe pari su 1/2 riga, colonne pari a destra di 1/2 colonna', + 'Rectangular' => 'Rettangolare', + }, + }, + 'CFAPattern' => 'Pattern CFA', + 'CFAPattern2' => 'Pattern CFA 2', + 'CFAPlaneColor' => 'Piano colori CFA', + 'CFARepeatPatternDim' => 'Dim pattern ripetuto CFA', + 'CHMVersion' => 'Versione CHM', + 'CIP3DataFile' => 'File di dati CIP3', + 'CIP3Sheet' => 'Foglio CIP3', + 'CIP3Side' => 'Lato CIP3', + 'CMYKEquivalent' => 'CMYK equivalente', + 'CPUArchitecture' => 'Architettura CPU', + 'CPUByteOrder' => { + Description => 'Ordine byte CPU', + PrintConv => { + 'Big endian' => 'Big-endian', + 'Little endian' => 'Little-endian', + }, + }, + 'CPUCount' => 'Numero processori', + 'CPUSubtype' => { + Description => 'Sottotipo CPU', + PrintConv => { + 'ARM (all)' => 'ARM (tutti)', + 'HPPA (all)' => 'HPPA (tutti)', + 'MC680x0 (all)' => 'MC680x0 (tutti)', + 'MC88000 (all)' => 'MC88000 (tutti)', + 'MC98000 (all)' => 'MC98000 (tutti)', + 'MIPS (all)' => 'MIPS (tutti)', + 'NS32032 (all)' => 'NS32032 (tutti)', + 'NS32032 DPC (032 CPU)' => 'NS32032 DPC (CPU 032)', + 'NS32332 (all)' => 'NS32332 (tutti)', + 'NS32332 DPC (032 CPU)' => 'NS32332 DPC (CPU 032)', + 'PowerPC (all)' => 'PowerPC (tutti)', + 'RS6000 (all)' => 'RS6000 (tutti)', + 'RT (all)' => 'RT (tutti)', + 'SPARC (all)' => 'SPARC (tutti)', + 'VAX (all)' => 'VAX (tutti)', + 'i386 (all)' => 'i386 (tutti)', + 'i860 (all)' => 'i860 (tutti)', + 'i860 little (all)' => 'i860 little (tutti)', + }, + }, + 'CPUType' => { + Description => 'Tipo CPU', + PrintConv => { + 'Any' => 'Qualsiasi', + 'Axis Communications 32-bit embedded processor' => 'Processore integrato a 32 bit Axis Communications', + 'None' => 'Nessuno', + 'S/390 (old)' => 'S/390 (precedente)', + 'i860 big endian' => 'i860 big-endian', + 'i860 little endian' => 'i860 little-endian', + 'm32r (old)' => 'm32r (precedente)', + 'v850 (old)' => 'v850 (precedente)', + }, + }, + 'CalibrationDateTime' => 'Data/ora di calibrazione', + 'CalibrationIlluminant1' => { + Description => 'Calibration illuminazione 1', + PrintConv => { + 'Cloudy' => 'Nuvoloso', + 'Cool White Fluorescent' => 'Fluorescente a luce calda', + 'Day White Fluorescent' => 'Fluorescente a luce del giorno bianca', + 'Daylight' => 'Luce del giorno', + 'Daylight Fluorescent' => 'Fluorescente a luce del giorno', + 'Fine Weather' => 'Bel tempo', + 'Fluorescent' => 'Fluorescente', + 'ISO Studio Tungsten' => 'Tungsteno studio ISO', + 'Other' => 'Altra Sorgente di Luce', + 'Shade' => 'Ombrato', + 'Standard Light A' => 'Luce standard A', + 'Standard Light B' => 'Luce standard B', + 'Standard Light C' => 'Luce standard C', + 'Tungsten (Incandescent)' => 'Tungsteno (luce incandescente)', + 'Unknown' => 'Sconosciuto', + 'Warm White Fluorescent' => 'Luce fluorescente bianca calda', + 'White Fluorescent' => 'Fluorescente bianca', + }, + }, + 'CalibrationIlluminant2' => { + Description => 'Calibration illuminazione 2', + PrintConv => { + 'Cloudy' => 'Nuvoloso', + 'Cool White Fluorescent' => 'Fluorescente a luce calda', + 'Day White Fluorescent' => 'Fluorescente a luce del giorno bianca', + 'Daylight' => 'Luce del giorno', + 'Daylight Fluorescent' => 'Fluorescente a luce del giorno', + 'Fine Weather' => 'Bel tempo', + 'Fluorescent' => 'Fluorescente', + 'ISO Studio Tungsten' => 'Tungsteno studio ISO', + 'Other' => 'Altra Sorgente di Luce', + 'Shade' => 'Ombrato', + 'Standard Light A' => 'Luce standard A', + 'Standard Light B' => 'Luce standard B', + 'Standard Light C' => 'Luce standard C', + 'Tungsten (Incandescent)' => 'Tungsteno (luce incandescente)', + 'Unknown' => 'Sconosciuto', + 'Warm White Fluorescent' => 'Luce fluorescente bianca calda', + 'White Fluorescent' => 'Fluorescente bianca', + }, + }, + 'CameraAngle' => 'Angolo fotocamera', + 'CameraBody' => 'Corpo fotocamera', + 'CameraByteOrder' => 'Ordine byte fotocamera', + 'CameraCalibration1' => 'Calibrazione fotocamera 1', + 'CameraCalibration2' => 'Calibrazione fotocamera 2', + 'CameraCalibrationSig' => 'Segnale calibrazione fotocamera', + 'CameraColorCalibration01' => 'Calibrazione colore fotocamera 01', + 'CameraColorCalibration02' => 'Calibrazione colore fotocamera 02', + 'CameraColorCalibration03' => 'Calibrazione colore fotocamera 03', + 'CameraColorCalibration04' => 'Calibrazione colore fotocamera 04', + 'CameraColorCalibration05' => 'Calibrazione colore fotocamera 05', + 'CameraColorCalibration06' => 'Calibrazione colore fotocamera 06', + 'CameraColorCalibration07' => 'Calibrazione colore fotocamera 07', + 'CameraColorCalibration08' => 'Calibrazione colore fotocamera 08', + 'CameraColorCalibration09' => 'Calibrazione colore fotocamera 09', + 'CameraColorCalibration10' => 'Calibrazione colore fotocamera 10', + 'CameraColorCalibration11' => 'Calibrazione colore fotocamera 11', + 'CameraColorCalibration12' => 'Calibrazione colore fotocamera 12', + 'CameraColorCalibration13' => 'Calibrazione colore fotocamera 13', + 'CameraColorCalibration14' => 'Calibrazione colore fotocamera 14', + 'CameraColorCalibration15' => 'Calibrazione colore fotocamera 15', + 'CameraDateTime' => 'Data/ora fotocamera', + 'CameraDirection' => 'Direzione fotocamera', + 'CameraID' => 'ID fotocamera', + 'CameraISO' => 'ISO fotocamera', + 'CameraIdentifier' => 'Identificativo fotocamera', + 'CameraLabel' => 'Etichetta fotocamera', + 'CameraMaker' => 'Marca fotocamera', + 'CameraManufacturer' => 'Produttore fotocamera', + 'CameraModel' => 'Modello fotocamera', + 'CameraMotion' => 'Camera motion', + 'CameraMove' => 'Sposta fotocamera', + 'CameraName' => 'Nome fotocamera', + 'CameraObjBackType' => 'Nome oggetto nero fotocamera', + 'CameraObjName' => 'Nome oggetto fotocamera', + 'CameraObjType' => 'Tipo oggetto fotocamera', + 'CameraObjVersion' => 'Versione oggetto fotocamera', + 'CameraOrientation' => { + Description => 'Orientazione fotocamera', + PrintConv => { + 'Horizontal (normal)' => 'Orizzontale (normale)', + 'Rotate 180' => 'Ruota di 180°', + 'Rotate 270 CW' => 'Ruota di 270° in senso orario', + 'Rotate 90 CW' => 'Ruota di 90° senso orario', + }, + }, + 'CameraOwner' => 'Proprietario fotocamera', + 'CameraParameters' => 'Parametri fotocamera', + 'CameraProfile' => 'Profilo fotocamera', + 'CameraProfileDigest' => 'Sommario profilo fotocamera', + 'CameraProfileVersion' => 'Versione profilo fotocamera', + 'CameraSerialNumber' => 'Numero di serie fotocamera', + 'CameraSettingsVersion' => 'Versione impostazioni fotocamera', + 'CameraTemperature' => 'Temperatura fotocamera', + 'CameraTemperature2' => 'Temperatura fotocamera 2', + 'CameraTemperature3' => 'Temperatura fotocamera 3', + 'CameraTemperature4' => 'Temperatura fotocamera 4', + 'CameraTemperature5' => 'Temperatura fotocamera 5', + 'CameraType' => { + Description => 'Tipo fotocamera', + PrintConv => { + 'n/a' => 'n/d', + }, + }, + 'CameraType2' => 'Tipo fotocamera 2', + 'CanonExposureMode' => { + PrintConv => { + 'Aperture-priority AE' => 'Priorità diaframma', + 'Manual' => 'Manuale', + 'Program AE' => 'Programma AE', + 'Shutter speed priority AE' => 'Priorità otturatore AE', + }, + }, + 'CanonFlashMode' => { + PrintConv => { + 'External flash' => 'Flash esterno', + 'Off' => 'Spento', + 'Red-eye reduction' => 'Riduzione occhi rossi', + 'Red-eye reduction (Auto)' => 'Riduzione occhi rossi (auto)', + 'Red-eye reduction (On)' => 'Riduzione occhi rossi (attivo)', + }, + }, + 'CanonImageSize' => { + PrintConv => { + 'Postcard' => 'Cartolina', + }, + }, + 'Caption-Abstract' => 'Didascalia/descrizione', + 'CaptionWriter' => 'Autore della didascalia', + 'CardShutterLock' => { + PrintConv => { + 'Off' => 'Spento', + }, + }, + 'CasioQuality' => { + Description => 'Qualità Casio', + PrintConv => { + 'Normal' => 'Normale', + }, + }, + 'Categories' => { + Description => 'Categorie', + PrintConv => { + 'Events' => 'Eventi', + 'Scenery' => 'Paesaggio', + 'To Do' => 'Da fare', + }, + }, + 'Category' => 'Categoria', + 'CellLength' => 'Lunghezza cella', + 'CellWidth' => 'Larghezza cella', + 'CenterWeightedAreaSize' => { + PrintConv => { + 'Average' => 'Media', + }, + }, + 'ChExtra' => 'Larghezza aggiunta per caratteri non spaziatori', + 'Channel' => 'Canale', + 'ChannelID' => 'ID canale', + 'ChannelIdentificationCode' => 'Codice identificativo canale', + 'ChannelLabel' => 'Etichetta canale', + 'ChannelLength' => 'Lunghezza canale', + 'ChannelMode' => 'Modo canale', + 'ChannelNumber' => 'Numero canale', + 'ChannelPositions' => 'Posizioni canale', + 'ChannelStatus' => 'Stato canale', + 'ChannelStatusMode' => 'Modo stato canale', + 'ChannelTotalTime' => 'Tempo totale canale', + 'ChannelWidth' => 'Larghezza canale', + 'Channels' => 'Canali', + 'Chapter' => 'Capitolo', + 'ChapterPhysicalEquivalent' => { + PrintConv => { + 'Session' => 'Sessione', + 'Side' => 'Lato', + }, + }, + 'ChapterProcessTime' => { + PrintConv => { + 'For Duration of Chapter' => 'Per la durata del capitolo', + }, + }, + 'CharacterSet' => { + Description => 'Set di caratteri', + PrintConv => { + 'Windows, Arabic' => 'Windows, Arabo', + 'Windows, Chinese (Simplified)' => 'Windows, Cinese semplificato', + 'Windows, Cyrillic' => 'Windows, Cirillico', + 'Windows, Greek' => 'Windows, Greco', + 'Windows, Hebrew' => 'Windows, Ebraico', + 'Windows, Japan (Shift - JIS X-0208)' => 'Windows, Giappone (Shift - JIS X-0208)', + 'Windows, Korea (Shift - KSC 5601)' => 'Windows, Corea (Shift - KSC 5601)', + 'Windows, Latin2 (Eastern European)' => 'Windows, Latin2 (Europa orientale)', + 'Windows, Turkish' => 'Windows, Turco', + }, + }, + 'Characters' => 'Caratteri', + 'CharactersWithSpaces' => 'Caratteri con spazi', + 'Children' => 'Bambini', + 'ChromaBlurRadius' => 'Raggio sfocatura cromatica', + 'ChromaticAberrationCorrection' => { + PrintConv => { + 'Off' => 'Spento', + }, + }, + 'ChromaticAdaptation' => 'Adattamento cromatico', + 'Chromaticity' => 'Cromatismo', + 'ChrominanceNR_TIFF_JPEG' => { + PrintConv => { + 'Low' => 'Basso', + 'Off' => 'Spento', + }, + }, + 'ChrominanceNoiseReduction' => { + PrintConv => { + 'Low' => 'Basso', + 'Off' => 'Spento', + }, + }, + 'City' => 'Città', + 'ClassifyState' => 'Stato di Classificazione', + 'CleanFaxData' => { + Description => 'Dati fax precisi', + PrintConv => { + 'Clean' => 'Pulito', + 'Regenerated' => 'Rigenerato', + 'Unclean' => 'Sporco', + }, + }, + 'ClipPath' => 'Percoso clip', + 'CodePage' => { + PrintConv => { + 'Japanese (JIS 0208-1990 and 0121-1990)' => 'Giapponese (JIS 0208-1990 e 0121-1990)', + 'Russian/Cyrillic (KOI8-R)' => 'Russo/Cirillico (KOI8-R)', + }, + }, + 'CodeSize' => 'Dimensione codice', + 'CodedCharacterSet' => 'Impostazione Caratteri Codificati', + 'CodedContentScanningKind' => { + PrintConv => { + 'Mixed' => 'Misto', + 'Progressive' => 'Progressivo', + 'Unknown' => 'Sconosciuto', + }, + }, + 'CodingMethods' => { + Description => 'Metodi di codifica', + PrintConv => { + 'Baseline JPEG' => 'Linea di base JPEG', + 'JBIG color' => 'JBIG a colori', + 'Modified Huffman' => 'Huffman modificato', + 'Unspecified compression' => 'Compressione non specificata', + }, + }, + 'ColorAberrationControl' => { + PrintConv => { + 'Off' => 'Spento', + }, + }, + 'ColorAdjustmentMode' => { + PrintConv => { + 'Off' => 'Spento', + }, + }, + 'ColorBalance' => 'Bilanciamento Colore', + 'ColorBalanceAdj' => { + PrintConv => { + 'Off' => 'Spento', + }, + }, + 'ColorBooster' => { + PrintConv => { + 'Off' => 'Spento', + }, + }, + 'ColorCharacterization' => 'Caratterizzazione colore', + 'ColorClass' => { + PrintConv => { + '0 (None)' => '0 (Nessuno)', + '1 (Winner)' => '1 (Vincitore)', + }, + }, + 'ColorEffect' => { + PrintConv => { + 'Off' => 'Spento', + 'Sepia' => 'Seppia', + }, + }, + 'ColorFilter' => { + Description => 'Filtro colori', + PrintConv => { + 'Green' => 'Verde', + 'Off' => 'Spento', + 'Purple' => 'Porpora', + 'Red' => 'Rosso', + 'Sepia' => 'Seppia', + 'Yellow' => 'Giallo', + }, + }, + 'ColorHue' => 'Colore Hue', + 'ColorMap' => 'Mappa colore', + 'ColorMatrix1' => 'Matrice colore 1', + 'ColorMatrix2' => 'Matrice colore 2', + 'ColorMode' => { + Description => 'Modo colore', + PrintConv => { + 'Autumn Leaves' => 'Foglie d\'autunno', + 'B&W' => 'B/N', + 'Clear' => 'Trasparente', + 'Deep' => 'Cupa', + 'Evening' => 'Sera', + 'Grayscale' => 'Scala di grigi', + 'Landscape' => 'Orizzontale', + 'Light' => 'Chiara', + 'Neutral' => 'Neutra', + 'Night View' => 'Visione notturna', + 'Night View/Portrait' => 'Rit. notturno', + 'Normal' => 'Normale', + 'Off' => 'Spento', + 'Portrait' => 'Verticale', + 'RGB Color' => 'Colore RGB', + 'Saturated Color' => 'Colore saturato', + 'Sepia' => 'Seppia', + 'Sunset' => 'Tramonto', + 'Vivid' => 'Vivace', + 'Vivid color' => 'Colore vivace', + 'n/a' => 'n/d', + }, + }, + 'ColorMoireReduction' => { + PrintConv => { + 'Off' => 'Spento', + }, + }, + 'ColorMoireReductionMode' => { + PrintConv => { + 'Low' => 'Basso', + 'Off' => 'Spento', + }, + }, + 'ColorPalette' => 'Palette di Colore', + 'ColorProfile' => { + PrintConv => { + 'Not Embedded' => 'Non incorporato', + }, + }, + 'ColorRepresentation' => { + Description => 'Rappresentazione del Colore', + PrintConv => { + 'No Image, Single Frame' => 'Nessuna immagine, quadro singolo', + }, + }, + 'ColorResponseUnit' => 'Unità risposta colore', + 'ColorSequence' => 'Sequenza colori', + 'ColorSpace' => { + Description => 'Spazio colore', + PrintConv => { + 'Gray-scale' => 'Scala di grigi', + 'Grayscale' => 'Scala di grigi', + 'ICC Profile' => 'Profilo ICC', + 'Uncalibrated' => 'Non calibrato', + }, + }, + 'ColorSpaceData' => 'Dati Spazio Colore', + 'ColorSpecApproximation' => { + PrintConv => { + 'Not Specified' => 'Non specificato', + }, + }, + 'ColorSpecMethod' => { + PrintConv => { + 'Enumerated' => 'Enumerato', + }, + }, + 'ColorTable' => 'Tabella colore', + 'ColorTemperature' => 'Temperatura colore', + 'ColorTemperatureSetting' => { + PrintConv => { + 'Temperature' => 'Temperatura', + }, + }, + 'ColorTone' => { + PrintConv => { + 'Normal' => 'Normale', + }, + }, + 'ColorToneFaithful' => { + PrintConv => { + 'n/a' => 'n/d', + }, + }, + 'ColorToneLandscape' => { + PrintConv => { + 'n/a' => 'n/d', + }, + }, + 'ColorToneMonochrome' => { + PrintConv => { + 'n/a' => 'n/d', + }, + }, + 'ColorToneNeutral' => { + PrintConv => { + 'n/a' => 'n/d', + }, + }, + 'ColorTonePortrait' => { + PrintConv => { + 'n/a' => 'n/d', + }, + }, + 'ColorToneStandard' => { + PrintConv => { + 'n/a' => 'n/d', + }, + }, + 'ColorToneUnknown' => { + PrintConv => { + 'n/a' => 'n/d', + }, + }, + 'ColorToneUserDef1' => { + PrintConv => { + 'n/a' => 'n/d', + }, + }, + 'ColorToneUserDef2' => { + PrintConv => { + 'n/a' => 'n/d', + }, + }, + 'ColorToneUserDef3' => { + PrintConv => { + 'n/a' => 'n/d', + }, + }, + 'ColorType' => { + PrintConv => { + 'Grayscale' => 'Scala di grigi', + 'RGB with Alpha' => 'RGB con trasparenza', + }, + }, + 'ColorimetricReference' => 'Riferimento colorimetrico', + 'CommandDialsChangeMainSub' => { + PrintConv => { + 'Off' => 'Spento', + }, + }, + 'CommandDialsMenuAndPlayback' => { + PrintConv => { + 'Off' => 'Spento', + }, + }, + 'CommandDialsReverseRotation' => { + PrintConv => { + 'Yes' => 'Sì', + }, + }, + 'CommanderGroupAMode' => { + PrintConv => { + 'Auto Aperture' => 'Diaframma automatico', + 'Manual' => 'Manuale', + 'Off' => 'Spento', + }, + }, + 'CommanderGroupBMode' => { + PrintConv => { + 'Auto Aperture' => 'Diaframma automatico', + 'Manual' => 'Manuale', + 'Off' => 'Spento', + }, + }, + 'CommanderInternalFlash' => { + PrintConv => { + 'Manual' => 'Manuale', + 'Off' => 'Spento', + }, + }, + 'Comment' => 'Commento', + 'CommentTime' => 'Ora commento', + 'Comments' => 'Commenti', + 'CommercialURL' => 'URL pubblicitario', + 'CompanyName' => 'Nome azienda', + 'Compilation' => { + PrintConv => { + 'Yes' => 'Sì', + }, + }, + 'ComponentsConfiguration' => 'Configurazione componenti', + 'Composer' => 'Compositore', + 'ComposerSortOrder' => 'Ordinamento compositore', + 'CompositionAdjust' => { + PrintConv => { + 'Off' => 'Spento', + }, + }, + 'CompositionMode' => { + PrintConv => { + 'Replace' => 'Sostituisci', + }, + }, + 'Compressed' => { + PrintConv => { + 'False' => 'Falso', + }, + }, + 'CompressedBitsPerPixel' => 'Bit per pixel compressi', + 'Compression' => { + Description => 'Compressione', + PrintConv => { + 'Adobe Deflate' => 'Deflate Adobe', + 'JBIG B&W' => 'JBIG B&N', + 'JBIG Color' => 'JBIG a colori', + 'JPEG' => 'Compressione JPEG', + 'JPEG (old-style)' => 'JPEG (vecchio stile)', + 'Kodak DCR Compressed' => 'Kodak DCR compresso', + 'Kodak KDC Compressed' => 'Kodak KDC compresso', + 'Microsoft Document Imaging (MDI) Binary Level Codec' => 'Microsoft Document Imaging (MDI) - Codec a livello binario', + 'Microsoft Document Imaging (MDI) Progressive Transform Codec' => 'Microsoft Document Imaging (MDI) - Codec a trasformazione progressiva', + 'Microsoft Document Imaging (MDI) Vector' => 'Microsoft Document Imaging (MDI) - Vettore', + 'Next' => 'Codifica NeXT', + 'Nikon NEF Compressed' => 'Nikon NEF compresso', + 'None' => 'Nessuno', + 'Packed RAW' => 'RAW pacchettizzato', + 'Pentax PEF Compressed' => 'Pentax PEF compresso', + 'RLE Encoding' => 'Codifica RLE', + 'Samsung SRW Compressed' => 'Samsung SRW compresso', + 'Sony ARW Compressed' => 'Sony ARW compresso', + 'T4/Group 3 Fax' => 'Fax T4/Group 3', + 'T6/Group 4 Fax' => 'Fax T6/Group 4', + 'Uncompressed' => 'Non compresso', + }, + }, + 'CompressionLevel' => 'Livello di compressione', + 'CompressionType' => { + Description => 'Tipo compressione', + PrintConv => { + 'Little-endian, no compression' => 'Little-endian, senza compressione', + 'None' => 'Nessuno', + }, + }, + 'CompressorName' => 'Nome compressione', + 'ConditionalFEC' => 'Compensazione Esposizione Flash', + 'Conductor' => 'Direttore d\'orchestra', + 'ConsecutiveBadFaxLines' => 'Linee fax non valide consecutive', + 'Contact' => 'Contatto', + 'ContentEncodingType' => { + PrintConv => { + 'Encryption' => 'Crittografia', + }, + }, + 'ContentEncryptionAlgorithm' => { + PrintConv => { + 'Not Encrypted' => 'Non crittografato', + }, + }, + 'ContentLocationCode' => 'Codice ubicazione contenuto', + 'ContentLocationName' => 'Nome Ubicazione Contenuto', + 'ContentSignatureAlgorithm' => { + PrintConv => { + 'Not Signed' => 'Senza segno', + }, + }, + 'ContentSignatureHashAlgorithm' => { + PrintConv => { + 'Not Signed' => 'Senza segno', + }, + }, + 'ContinuousBracketing' => { + PrintConv => { + 'Low' => 'Basso', + }, + }, + 'ContinuousShootingSpeed' => { + PrintConv => { + 'Enable' => 'Abilita', + }, + }, + 'ContinuousShotLimit' => { + PrintConv => { + 'Enable' => 'Abilita', + }, + }, + 'Contrast' => { + Description => 'Contrasto', + PrintConv => { + 'High' => 'Alto', + 'Low' => 'Basso', + 'Normal' => 'Normale', + }, + }, + 'ContrastCurve' => 'Curva di contrasto', + 'ContrastDetectAF' => { + PrintConv => { + 'Off' => 'Spento', + }, + }, + 'ContrastFaithful' => { + PrintConv => { + 'n/a' => 'n/d', + }, + }, + 'ContrastHighlightShadowAdj' => { + PrintConv => { + 'Off' => 'Spento', + }, + }, + 'ContrastLandscape' => { + PrintConv => { + 'n/a' => 'n/d', + }, + }, + 'ContrastMode' => { + PrintConv => { + 'Elegant (My Color)' => 'Elegante (mio colore)', + 'Expressive' => 'Espressivo', + 'Low' => 'Basso', + 'Normal' => 'Normale', + 'Nostalgic (Color Film)' => 'Nostalgico (pellicola a colori)', + 'Retro' => 'Retrò', + 'Retro (My Color)' => 'Retro (colore personalizzato)', + }, + }, + 'ContrastMonochrome' => { + PrintConv => { + 'n/a' => 'n/d', + }, + }, + 'ContrastNeutral' => { + PrintConv => { + 'n/a' => 'n/d', + }, + }, + 'ContrastPortrait' => { + PrintConv => { + 'n/a' => 'n/d', + }, + }, + 'ContrastStandard' => { + PrintConv => { + 'n/a' => 'n/d', + }, + }, + 'ContrastUnknown' => { + PrintConv => { + 'n/a' => 'n/d', + }, + }, + 'ContrastUserDef1' => { + PrintConv => { + 'n/a' => 'n/d', + }, + }, + 'ContrastUserDef2' => { + PrintConv => { + 'n/a' => 'n/d', + }, + }, + 'ContrastUserDef3' => { + PrintConv => { + 'n/a' => 'n/d', + }, + }, + 'ControlDialSet' => { + PrintConv => { + 'Shutter Speed' => 'Tempo esposizione', + }, + }, + 'ControlMode' => { + PrintConv => { + 'Camera Local Control' => 'Controllo locale fotocamera', + 'n/a' => 'n/d', + }, + }, + 'ConversionLens' => { + PrintConv => { + 'Off' => 'Spento', + }, + }, + 'Converter' => 'Convertitore', + 'Copyright' => 'Titolare del copyright', + 'CopyrightFlag' => { + PrintConv => { + 'False' => 'Falso', + }, + }, + 'CopyrightNotice' => 'Info Copyright', + 'CopyrightStatus' => { + PrintConv => { + 'Not specified' => 'Non specificato', + 'Protected' => 'Protetto', + 'Public Domain' => 'Pubblico dominio', + 'Unknown' => 'Sconosciuto', + }, + }, + 'CopyrightURL' => 'URL copyright', + 'Country' => 'Paese', + 'Country-PrimaryLocationCode' => 'Codice ISO Nazione', + 'Country-PrimaryLocationName' => 'Nazione', + 'CreateDate' => 'Data di creazione', + 'CreationDate' => 'Data di creazione', + 'CreativeStyle' => { + PrintConv => { + 'Autumn Leaves' => 'Foglie d\'autunno', + 'B&W' => 'B/N', + 'Clear' => 'Trasparente', + 'Deep' => 'Cupa', + 'Landscape' => 'Orizzontale', + 'Light' => 'Chiara', + 'Neutral' => 'Neutra', + 'Night View/Portrait' => 'Rit. notturno', + 'Portrait' => 'Verticale', + 'Sepia' => 'Seppia', + 'Sunset' => 'Tramonto', + 'Vivid' => 'Vivace', + }, + }, + 'CreativeStyleSetting' => { + PrintConv => { + 'Landscape' => 'Orizzontale', + 'Sunset' => 'Tramonto', + 'Vivid' => 'Vivace', + }, + }, + 'Creator' => 'Creatore', + 'CreatorAddress' => 'Autore - Indirizzo', + 'CreatorAppID' => { + PrintConv => { + 'Unknown' => 'Sconosciuto', + }, + }, + 'CreatorCity' => 'Autore - Città', + 'CreatorCountry' => 'Autore - Nazione', + 'CreatorPostalCode' => 'Autore - Codice Postale', + 'CreatorRegion' => 'Autore - Stato/Provincia', + 'CreatorWorkEmail' => 'Autore - E.Mail', + 'CreatorWorkTelephone' => 'Autore - Numero di Telefono', + 'CreatorWorkURL' => 'Autore - Sito web', + 'Credit' => 'Fornitore', + 'CreditLineRequired' => { + PrintConv => { + 'Not Required' => 'Non richiesto', + }, + }, + 'CropActive' => { + PrintConv => { + 'Yes' => 'Sì', + }, + }, + 'CropUnit' => { + PrintConv => { + 'inches' => 'Pollici', + }, + }, + 'CropUnits' => { + PrintConv => { + 'inches' => 'Pollici', + }, + }, + 'CrossProcess' => { + PrintConv => { + 'Favorite 1' => 'Preferito 1', + 'Favorite 2' => 'Preferito 2', + 'Favorite 3' => 'Preferito 3', + 'Off' => 'Spento', + 'Random' => 'Casuale', + }, + }, + 'CurrentICCProfile' => 'Profilo ICC attuale', + 'CurrentPreProfileMatrix' => 'Matrice di pre-profilo attuale', + 'Curves' => { + PrintConv => { + 'Off' => 'Spento', + }, + }, + 'CustomRendered' => { + Description => 'Resa personalizzata', + PrintConv => { + 'Custom' => 'Personalizzata', + 'Normal' => 'Normale', + }, + }, + 'CustomWBError' => { + PrintConv => { + 'Error' => 'Errore', + }, + }, + 'D-LightingHQ' => { + PrintConv => { + 'Off' => 'Spento', + }, + }, + 'D-LightingHQSelected' => { + PrintConv => { + 'Yes' => 'Sì', + }, + }, + 'D-LightingHS' => { + PrintConv => { + 'Off' => 'Spento', + }, + }, + 'D-RangeOptimizerMode' => { + PrintConv => { + 'Manual' => 'Manuale', + 'Off' => 'Spento', + }, + }, + 'DECPosition' => { + PrintConv => { + 'Exposure' => 'Esposizione', + 'Saturation' => 'Saturazione', + }, + }, + 'DNGBackwardVersion' => 'Versione precedente DNG', + 'DNGLensInfo' => 'Informazioni lenti DNG', + 'DNGPrivateData' => 'Dati privati DNG', + 'DNGVersion' => 'Versione DNG', + 'DataImprint' => { + PrintConv => { + 'None' => 'Nessuno', + 'Text' => 'Testo', + }, + }, + 'DataType' => 'Tipo di dati', + 'Date' => 'Data', + 'DateCreated' => 'Data di creazione', + 'DateDisplayFormat' => { + Description => 'Formato Data', + PrintConv => { + 'D/M/Y' => 'Giorno/mese/anno', + 'M/D/Y' => 'Mese/giorno/anno', + 'Y/M/D' => 'Anno/mese/giorno', + }, + }, + 'DateImprint' => { + PrintConv => { + 'Off' => 'Spento', + }, + }, + 'DateSent' => 'Data d\'invio', + 'DateStampMode' => { + PrintConv => { + 'Off' => 'Spento', + }, + }, + 'DateTime' => 'Data/ora', + 'DateTimeOriginal' => 'Data/ora originale di creazione', + 'DaylightSavings' => { + PrintConv => { + 'Off' => 'Spento', + 'Yes' => 'Sì', + }, + }, + 'Decode' => 'Decodifica', + 'DefaultCropOrigin' => 'Ritaglio origine predefinito', + 'DefaultCropSize' => 'Ritaglio dimensione predefinito', + 'DefaultImageColor' => 'Colore immagine predefinito', + 'DefaultScale' => 'Scala predefinita', + 'DeletedImageCount' => 'Conteggio Immagini Cancellate', + 'DeltaType' => { + PrintConv => { + 'Absolute' => 'Assoluto', + }, + }, + 'Description' => 'Descrizione', + 'Destination' => 'Destinazione', + 'DestinationCity' => { + PrintConv => { + 'Jerusalem' => 'Gerusalemme', + 'Lisbon' => 'Lisbona', + 'London' => 'Londra', + 'Milan' => 'Milano', + 'Prague' => 'Praga', + 'Rome' => 'Roma', + 'Stockholm' => 'Stoccolma', + 'Tehran' => 'Teheran', + }, + }, + 'DestinationDST' => { + PrintConv => { + 'Yes' => 'Sì', + }, + }, + 'DeviceAttributes' => 'Attributi Dispositivo', + 'DeviceManufacturer' => 'Costruttore dispositivo', + 'DeviceMfgDesc' => 'Descrizione del Costruttore Dispositivo', + 'DeviceModel' => 'Modello Dispositivo', + 'DeviceModelDesc' => 'Descrizione Modello Dispositivo', + 'DeviceSettingDescription' => 'Descrizione impostazioni dispositivo', + 'DialDirectionTvAv' => { + PrintConv => { + 'Normal' => 'Normale', + 'Reversed' => 'Invertito', + }, + }, + 'DigitalCreationDate' => 'Data di creazione digitale', + 'DigitalCreationTime' => 'Ora di Creazione Digitale', + 'DigitalFilter01' => { + PrintConv => { + 'Fisheye' => 'Fish-eye', + 'Off' => 'Spento', + 'Posterization' => 'Posterizzazione', + 'Retro' => 'Retrò', + 'Shading' => 'Ombreggiatura', + 'Starburst' => 'Esplosione stellare', + }, + }, + 'DigitalFilter02' => { + PrintConv => { + 'Fisheye' => 'Fish-eye', + 'Off' => 'Spento', + 'Posterization' => 'Posterizzazione', + 'Retro' => 'Retrò', + 'Shading' => 'Ombreggiatura', + 'Starburst' => 'Esplosione stellare', + }, + }, + 'DigitalFilter03' => { + PrintConv => { + 'Fisheye' => 'Fish-eye', + 'Off' => 'Spento', + 'Posterization' => 'Posterizzazione', + 'Retro' => 'Retrò', + 'Shading' => 'Ombreggiatura', + 'Starburst' => 'Esplosione stellare', + }, + }, + 'DigitalFilter04' => { + PrintConv => { + 'Fisheye' => 'Fish-eye', + 'Off' => 'Spento', + 'Posterization' => 'Posterizzazione', + 'Retro' => 'Retrò', + 'Shading' => 'Ombreggiatura', + 'Starburst' => 'Esplosione stellare', + }, + }, + 'DigitalFilter05' => { + PrintConv => { + 'Fisheye' => 'Fish-eye', + 'Off' => 'Spento', + 'Posterization' => 'Posterizzazione', + 'Retro' => 'Retrò', + 'Shading' => 'Ombreggiatura', + 'Starburst' => 'Esplosione stellare', + }, + }, + 'DigitalFilter06' => { + PrintConv => { + 'Fisheye' => 'Fish-eye', + 'Off' => 'Spento', + 'Posterization' => 'Posterizzazione', + 'Retro' => 'Retrò', + 'Shading' => 'Ombreggiatura', + 'Starburst' => 'Esplosione stellare', + }, + }, + 'DigitalFilter07' => { + PrintConv => { + 'Fisheye' => 'Fish-eye', + 'Off' => 'Spento', + 'Posterization' => 'Posterizzazione', + 'Retro' => 'Retrò', + 'Shading' => 'Ombreggiatura', + 'Starburst' => 'Esplosione stellare', + }, + }, + 'DigitalFilter08' => { + PrintConv => { + 'Fisheye' => 'Fish-eye', + 'Off' => 'Spento', + 'Posterization' => 'Posterizzazione', + 'Retro' => 'Retrò', + 'Shading' => 'Ombreggiatura', + 'Starburst' => 'Esplosione stellare', + }, + }, + 'DigitalFilter09' => { + PrintConv => { + 'Fisheye' => 'Fish-eye', + 'Off' => 'Spento', + 'Posterization' => 'Posterizzazione', + 'Retro' => 'Retrò', + 'Shading' => 'Ombreggiatura', + 'Starburst' => 'Esplosione stellare', + }, + }, + 'DigitalFilter10' => { + PrintConv => { + 'Fisheye' => 'Fish-eye', + 'Off' => 'Spento', + 'Posterization' => 'Posterizzazione', + 'Retro' => 'Retrò', + 'Shading' => 'Ombreggiatura', + 'Starburst' => 'Esplosione stellare', + }, + }, + 'DigitalFilter11' => { + PrintConv => { + 'Fisheye' => 'Fish-eye', + 'Off' => 'Spento', + 'Posterization' => 'Posterizzazione', + 'Retro' => 'Retrò', + 'Shading' => 'Ombreggiatura', + 'Starburst' => 'Esplosione stellare', + }, + }, + 'DigitalFilter12' => { + PrintConv => { + 'Fisheye' => 'Fish-eye', + 'Off' => 'Spento', + 'Posterization' => 'Posterizzazione', + 'Retro' => 'Retrò', + 'Shading' => 'Ombreggiatura', + 'Starburst' => 'Esplosione stellare', + }, + }, + 'DigitalFilter13' => { + PrintConv => { + 'Fisheye' => 'Fish-eye', + 'Off' => 'Spento', + 'Posterization' => 'Posterizzazione', + 'Retro' => 'Retrò', + 'Shading' => 'Ombreggiatura', + 'Starburst' => 'Esplosione stellare', + }, + }, + 'DigitalFilter14' => { + PrintConv => { + 'Fisheye' => 'Fish-eye', + 'Off' => 'Spento', + 'Posterization' => 'Posterizzazione', + 'Retro' => 'Retrò', + 'Shading' => 'Ombreggiatura', + 'Starburst' => 'Esplosione stellare', + }, + }, + 'DigitalFilter15' => { + PrintConv => { + 'Fisheye' => 'Fish-eye', + 'Off' => 'Spento', + 'Posterization' => 'Posterizzazione', + 'Retro' => 'Retrò', + 'Shading' => 'Ombreggiatura', + 'Starburst' => 'Esplosione stellare', + }, + }, + 'DigitalFilter16' => { + PrintConv => { + 'Fisheye' => 'Fish-eye', + 'Off' => 'Spento', + 'Posterization' => 'Posterizzazione', + 'Retro' => 'Retrò', + 'Shading' => 'Ombreggiatura', + 'Starburst' => 'Esplosione stellare', + }, + }, + 'DigitalFilter17' => { + PrintConv => { + 'Fisheye' => 'Fish-eye', + 'Off' => 'Spento', + 'Posterization' => 'Posterizzazione', + 'Retro' => 'Retrò', + 'Shading' => 'Ombreggiatura', + 'Starburst' => 'Esplosione stellare', + }, + }, + 'DigitalFilter18' => { + PrintConv => { + 'Fisheye' => 'Fish-eye', + 'Off' => 'Spento', + 'Posterization' => 'Posterizzazione', + 'Retro' => 'Retrò', + 'Shading' => 'Ombreggiatura', + 'Starburst' => 'Esplosione stellare', + }, + }, + 'DigitalFilter19' => { + PrintConv => { + 'Fisheye' => 'Fish-eye', + 'Off' => 'Spento', + 'Posterization' => 'Posterizzazione', + 'Retro' => 'Retrò', + 'Shading' => 'Ombreggiatura', + 'Starburst' => 'Esplosione stellare', + }, + }, + 'DigitalFilter20' => { + PrintConv => { + 'Fisheye' => 'Fish-eye', + 'Off' => 'Spento', + 'Posterization' => 'Posterizzazione', + 'Retro' => 'Retrò', + 'Shading' => 'Ombreggiatura', + 'Starburst' => 'Esplosione stellare', + }, + }, + 'DigitalZoom' => { + Description => 'Zoom Digitale', + PrintConv => { + 'None' => 'Nessuno', + 'Off' => 'Spento', + }, + }, + 'DigitalZoomOn' => { + PrintConv => { + 'Off' => 'Spento', + }, + }, + 'DigitalZoomRatio' => 'Rapporto zoom digitale', + 'Directory' => 'Posizione file', + 'DisplayAllAFPoints' => { + PrintConv => { + 'Enable' => 'Abilita', + }, + }, + 'DisplaySize' => { + PrintConv => { + 'Normal' => 'Normale', + }, + }, + 'DisplayUnits' => { + PrintConv => { + 'inches' => 'Pollici', + }, + }, + 'DisplayedUnitsX' => { + PrintConv => { + 'inches' => 'Pollici', + }, + }, + 'DisplayedUnitsY' => { + PrintConv => { + 'inches' => 'Pollici', + }, + }, + 'DistortionControl' => { + PrintConv => { + 'Off' => 'Spento', + }, + }, + 'DistortionCorrection' => { + PrintConv => { + 'Off' => 'Spento', + 'n/a' => 'n/d', + }, + }, + 'DistortionCorrection2' => { + PrintConv => { + 'Off' => 'Spento', + }, + }, + 'DjVuVersion' => 'Versione DjVu', + 'DocSecurity' => { + PrintConv => { + 'None' => 'Nessuno', + }, + }, + 'DocumentHistory' => 'Cronologia documento', + 'DocumentName' => 'Nome documento', + 'DocumentNotes' => 'Note del Documento', + 'DotRange' => 'Intervallo puntuale', + 'DriveMode' => { + Description => 'Modalità esecuzione', + PrintConv => { + '10 s Timer' => 'Timer 10 s', + 'Off' => 'Spento', + 'Self-Timer 2 sec' => 'Autoscatto 2 sec', + 'Self-timer' => 'Autoscatto', + 'Self-timer (12 s)' => 'Autoscatto (12 s)', + 'Self-timer (2 s)' => 'Autoscatto (2 s)', + 'Self-timer 10 sec' => 'Autoscatto 10 sec', + 'Self-timer Operation' => 'Operazione autoscatto', + 'n/a' => 'n/d', + }, + }, + 'DriveMode2' => { + PrintConv => { + 'Self-timer (12 s)' => 'Autoscatto (12 s)', + 'Self-timer (2 s)' => 'Autoscatto (2 s)', + 'Self-timer 10 sec' => 'Autoscatto 10 sec', + 'Self-timer 2 sec' => 'Autoscatto 2 sec', + }, + }, + 'DriveModeSetting' => { + PrintConv => { + 'Self-timer 10 sec' => 'Autoscatto 10 sec', + }, + }, + 'DriveType' => { + PrintConv => { + 'Fixed Disk' => 'Disco fisso', + 'Unknown' => 'Sconosciuto', + }, + }, + 'DynamicRangeExpansion' => { + PrintConv => { + 'Off' => 'Spento', + }, + }, + 'DynamicRangeOptimizer' => { + Description => 'Ott.gamma din.', + PrintConv => { + 'Advanced Auto' => 'Avanz.autom.', + 'Advanced Lv1' => 'Liv.Avanzato 1', + 'Advanced Lv2' => 'Liv.Avanzato 2', + 'Advanced Lv3' => 'Liv.Avanzato 3', + 'Advanced Lv4' => 'Liv.Avanzato 4', + 'Advanced Lv5' => 'Liv.Avanzato 5', + 'Auto' => 'Automatico', + 'Off' => 'Spento', + }, + }, + 'DynamicRangeOptimizerBracket' => { + PrintConv => { + 'Low' => 'Basso', + 'Off' => 'Spento', + }, + }, + 'DynamicRangeOptimizerMode' => { + PrintConv => { + 'Off' => 'Spento', + }, + }, + 'DynamicRangeOptimizerSetting' => { + PrintConv => { + 'Off' => 'Spento', + }, + }, + 'DynamicRangeSetting' => { + PrintConv => { + 'Manual' => 'Manuale', + }, + }, + 'ETTLII' => { + PrintConv => { + 'Average' => 'Media', + }, + }, + 'EVSteps' => { + PrintConv => { + '1/2 EV Steps' => 'Step 1/2 EV', + '1/3 EV Steps' => 'Step 1/3 EV', + }, + }, + 'EXIFVersion' => 'Versione EXIF', + 'EXRAuto' => { + PrintConv => { + 'Manual' => 'Manuale', + }, + }, + 'EasyExposureComp' => { + PrintConv => { + 'Off' => 'Spento', + }, + }, + 'EasyExposureCompensation' => { + PrintConv => { + 'Off' => 'Spento', + }, + }, + 'EasyMode' => { + PrintConv => { + 'Fireworks' => 'Fuochi artificiali', + 'Fisheye Effect' => 'Effetto fish-eye', + 'Flash Off' => 'Flash spento', + 'Kids & Pets' => 'Bambini e animali dimestici', + 'Landscape' => 'Orizzontale', + 'Manual' => 'Manuale', + 'Night' => 'Scena notturna', + 'Nostalgic' => 'Nostalgico', + 'Portrait' => 'Verticale', + 'Quick Shot' => 'Scatto veloce', + 'Sepia' => 'Seppia', + 'Sunset' => 'Tramonto', + 'Vivid' => 'Vivace', + 'Zoom Blur' => 'Sfocatura zoom', + }, + }, + 'EdgeNoiseReduction' => { + PrintConv => { + 'Off' => 'Spento', + }, + }, + 'EditStatus' => 'Modifica Stato', + 'EditorialUpdate' => { + Description => 'Aggiornamento Editoriale', + PrintConv => { + 'Additional language' => 'Linguaggio addizionale', + }, + }, + 'EffectiveMaxAperture' => 'Diaframma massimo effettivo', + 'Elevation' => 'Elevazione', + 'Emphasis' => { + PrintConv => { + 'None' => 'Nessuno', + 'reserved' => 'riservato', + }, + }, + 'EncodedBy' => 'Codificato da', + 'EncodedPixelsDimensions' => 'Dimensioni pixel codificati', + 'EncodedUsing' => 'Codificato usando', + 'EncodedWith' => 'Codificato con', + 'Encoder' => 'Codificatore', + 'EncoderSettings' => 'Impostazioni codificatore', + 'EncoderVersion' => 'Versione codificatore', + 'Encoding' => { + Description => 'Codifica', + PrintConv => { + 'QDesign Music' => 'Musica QDesign', + 'Unknown -' => 'Sconosciuto -', + }, + }, + 'EncodingProcess' => 'Processo di codifica', + 'EncodingScheme' => 'Schema di codifica', + 'EncodingSettings' => 'Impostazioni di codifica', + 'EncodingTime' => 'Durata codifica', + 'Encryption' => 'Crittografia', + 'EndOfItems' => 'Fine elementi', + 'EndPoints' => 'Punti finali', + 'EndTime' => 'Ora fine', + 'EndUser' => 'Utente finale', + 'EndUserID' => 'ID utente finale', + 'EndUserName' => 'Nome utente finale', + 'EndingPage' => 'Pagina finale', + 'EnhanceDarkTones' => { + PrintConv => { + 'Off' => 'Spento', + }, + }, + 'Enhancement' => { + Description => 'Miglioramento', + PrintConv => { + 'Green' => 'Verde', + 'Off' => 'Spento', + 'Red' => 'Rosso', + 'Scenery' => 'Paesaggio', + }, + }, + 'EnhancementOrModificationDescription' => 'Descrizione miglioramento/modifica', + 'EntryPoint' => 'Punto d\'ingresso', + 'EnvelopePriority' => { + PrintConv => { + '0 (reserved)' => '0 (riservato)', + '1 (most urgent)' => '1 (molto urgente)', + '5 (normal urgency)' => '5 (urgenza normale)', + '8 (least urgent)' => '8 (meno urgente)', + '9 (user-defined priority)' => '9 (priorità definita dall\'utente)', + }, + }, + 'Error' => 'Errore', + 'ErrorCorrection' => 'Correzione errore', + 'ErrorCorrectionType' => 'Tipo correzione errore', + 'EthnicGroup' => 'Gruppo etnico', + 'Event' => 'Evento', + 'EventAbsoluteDuration' => 'Durata assoluta evento', + 'Events' => 'Eventi', + 'ExcursionTolerance' => { + PrintConv => { + 'Allowed' => 'Possibile', + 'Not Allowed' => 'Non permesso', + }, + }, + 'ExecutionStatus' => 'Stato esecuzione', + 'ExecutionStatusInfo' => 'Info stato esecuzione', + 'ExifByteOrder' => 'Ordine dei byte Exif', + 'ExifCameraInfo' => 'Info Exif fotocamera', + 'ExifImageHeight' => 'Altezza immagine Exif', + 'ExifImageWidth' => 'Larghezza immagine Exif', + 'ExifInfo2' => 'Info 2 Exif', + 'ExifOffset' => 'Puntatore Exif IFD', + 'ExifToolVersion' => 'Numero versione ExifTool', + 'ExifUnicodeByteOrder' => 'Ordine unicode dei byte Exif', + 'ExifVersion' => 'Versione Exif', + 'ExitPupilPosition' => 'Posizione pupilla d\'uscita', + 'ExpirationDate' => 'Data scadenza', + 'ExpirationTime' => 'Ora scadenza', + 'Expires' => 'Scade', + 'ExposedArea' => 'Area esposta', + 'Exposure' => 'Esposizione', + 'Exposure2012' => 'Esposizione 2012', + 'ExposureBracketValue' => 'Valore Esposizione a Forcella', + 'ExposureBracketingIndicatorLast' => { + PrintConv => { + 'Not Indicated' => 'Non indicato', + }, + }, + 'ExposureCompensation' => 'Compensazione esposizione', + 'ExposureCompensationMode' => 'Modo compensazione esposizione', + 'ExposureControlMode' => 'Modo controllo esposizione', + 'ExposureControlModeDescription' => 'Descrizione modo controllo esposizione', + 'ExposureDelayMode' => { + PrintConv => { + 'Off' => 'Spento', + }, + }, + 'ExposureDifference' => 'Differenza esposizione', + 'ExposureIndex' => 'Indice di esposizione', + 'ExposureIndicator' => { + PrintConv => { + 'Not Indicated' => 'Non indicato', + }, + }, + 'ExposureLevelIncrements' => { + PrintConv => { + '1/2 Stop' => '1/2 stop', + '1/3 Stop' => '1/3 stop', + }, + }, + 'ExposureMode' => { + Description => 'Modo esposizione', + PrintConv => { + 'Aperture Priority' => 'Priorità diaframma', + 'Aperture-priority AE' => 'Priorità diaframma', + 'Auto bracket' => 'A forcella automatica', + 'Fireworks' => 'Fuochi artificiali', + 'Landscape' => 'Orizzontale', + 'Manual' => 'Manuale', + 'Portrait' => 'Verticale', + 'Program' => 'Programma', + 'Program AE' => 'Programma AE', + 'Shutter Priority' => 'Priorità otturatore', + 'Shutter speed priority AE' => 'Priorità otturatore AE', + 'Sunset' => 'Tramonto', + 'n/a' => 'n/d', + }, + }, + 'ExposureModeInManual' => { + Description => 'Modo esposizione in manuale', + PrintConv => { + 'Center-weighted average' => 'Media centrale ponderata', + 'Partial metering' => 'Parziale', + }, + }, + 'ExposureModulationType' => 'Tipo modulazione esposizione', + 'ExposureProgram' => { + Description => 'Programma esposizione', + PrintConv => { + 'Action (High speed)' => 'Azione (alta velocità)', + 'Aperture Priority' => 'Priorità diaframma', + 'Aperture-priority AE' => 'Priorità diaframma', + 'Bulb' => 'Bulbo', + 'Creative (Slow speed)' => 'Creativo (bassa velocità)', + 'Landscape' => 'Orizzontale', + 'Manual' => 'Manuale', + 'Not Defined' => 'Non definito', + 'Portrait' => 'Verticale', + 'Posterization' => 'Posterizzazione', + 'Posterization B/W' => 'Posterizzazione B&N', + 'Program' => 'Programma', + 'Program AE' => 'Programma AE', + 'Retro Photo' => 'Foto retrò', + 'Shutter Priority' => 'Priorità otturatore', + 'Shutter speed priority AE' => 'Priorità otturatore AE', + 'Sunset' => 'Tramonto', + 'Sweep Panorama' => 'Panoramica ad arco', + }, + }, + 'ExposureSequence' => 'Sequenza esposizione', + 'ExposureStatus' => 'Stato esposizione', + 'ExposureTime' => 'Tempo esposizione', + 'ExposureTime2' => 'Tempo esposizione 2', + 'ExposureTimeInMicroSec' => 'Tempo esposizione in microsecondi', + 'ExposureTimeInMilliSec' => 'Tempo esposizione in millisecondi', + 'ExposureTuning' => 'Sintonizzazione esposizione', + 'ExposureUnknown' => 'Esposizione sconosciuta', + 'ExposureValue' => 'Valore esposizione', + 'ExtendedWBDetect' => { + PrintConv => { + 'Off' => 'Spento', + }, + }, + 'Extender' => { + PrintConv => { + 'None' => 'Nessuno', + }, + }, + 'ExtenderStatus' => { + PrintConv => { + 'Not attached' => 'Non applicabile', + 'Removed' => 'Rimosso', + }, + }, + 'ExtensionPersistence' => { + PrintConv => { + 'Potentially Invalidated By Modification' => 'Potenzialmente invalidato per modifica', + }, + }, + 'ExternalFlash' => { + Description => 'Flash esterno', + PrintConv => { + 'Off' => 'Spento', + }, + }, + 'ExternalFlashBounce' => { + PrintConv => { + 'Yes' => 'Sì', + 'n/a' => 'n/d', + }, + }, + 'ExternalFlashExposureComp' => { + PrintConv => { + 'n/a' => 'n/d', + }, + }, + 'ExternalFlashFirmware' => { + PrintConv => { + '1.01 (SB-800 or Metz 58 AF-1)' => '1.01 (SB-800 o Metz 58 AF-1)', + 'n/a' => 'n/d', + }, + }, + 'ExternalFlashFlags' => 'Flags Flash Esterno', + 'ExternalFlashMode' => { + PrintConv => { + 'Off' => 'Spento', + }, + }, + 'ExtraFlags' => { + PrintConv => { + '(none)' => '(nessuno)', + 'Fastest Algorithm' => 'Algoritmo più veloce', + }, + }, + 'ExtraSamples' => { + Description => 'Campioni extra', + PrintConv => { + 'Associated Alpha' => 'Associati alla trasparenza', + 'Unassociated Alpha' => 'Non associati alla trasparenza', + 'Unspecified' => 'Non specificati', + }, + }, + 'EyeStartAF' => { + PrintConv => { + 'Off' => 'Spento', + }, + }, + 'FEMicroadjustment' => { + PrintConv => { + 'Enable' => 'Abilita', + }, + }, + 'FNumber' => 'Numero F', + 'Face1Category' => { + PrintConv => { + 'Family' => 'Famiglia', + }, + }, + 'Face2Category' => { + PrintConv => { + 'Family' => 'Famiglia', + }, + }, + 'Face3Category' => { + PrintConv => { + 'Family' => 'Famiglia', + }, + }, + 'Face4Category' => { + PrintConv => { + 'Family' => 'Famiglia', + }, + }, + 'Face5Category' => { + PrintConv => { + 'Family' => 'Famiglia', + }, + }, + 'Face6Category' => { + PrintConv => { + 'Family' => 'Famiglia', + }, + }, + 'Face7Category' => { + PrintConv => { + 'Family' => 'Famiglia', + }, + }, + 'Face8Category' => { + PrintConv => { + 'Family' => 'Famiglia', + }, + }, + 'FaceDetection' => { + PrintConv => { + 'Off' => 'Spento', + }, + }, + 'FaceOrientation' => { + PrintConv => { + 'Horizontal (normal)' => 'Orizzontale (normale)', + 'Rotate 180' => 'Ruota di 180°', + 'Rotate 270 CW' => 'Ruota di 270° in senso orario', + 'Rotate 90 CW' => 'Ruota di 90° senso orario', + }, + }, + 'FacesDetected' => { + Description => 'Facce rimosse', + PrintConv => { + 'n/a' => 'n/d', + }, + }, + 'FacesRecognized' => 'Facce riconosciute', + 'FamilyName' => 'Nome famiglia', + 'FastSeek' => { + PrintConv => { + 'Yes' => 'Sì', + }, + }, + 'FaxNumber' => 'Numero di fax', + 'FaxProfile' => { + Description => 'Profilo fax', + PrintConv => { + 'Extended B&W lossless, F' => 'Bianco e nero esteso senza perdita, F', + 'Lossless JBIG B&W, J' => 'Senza perdita JBIG bianco e nero, J', + 'Lossless color and grayscale, L' => 'Senza perdita a colori e scala di grigi, L', + 'Lossy color and grayscale, C' => 'Con perdita a colori e scala di grigi, C', + 'Minimal B&W lossless, S' => 'Bianco e nero minimale con perdita, S', + 'Mixed raster content, M' => 'Contenuto raster misto, M', + 'Multi Profiles' => 'Profili multipli', + 'Profile T' => 'Profilo T', + 'Unknown' => 'Sconosciuto', + }, + }, + 'FaxRecvParams' => 'Parametri ricezione fax', + 'FaxRecvTime' => 'Ora ricezione fax', + 'FaxSubAddress' => 'Sotto-indirizzo fax', + 'FileAttributes' => { + PrintConv => { + 'Encrypted' => 'Crittografato', + 'Encrypted?' => 'Crittografato?', + 'Normal' => 'Normale', + 'Not indexed' => 'Non indicizzato', + 'Read-only' => 'Sola lettura', + 'System' => 'Sistema', + }, + }, + 'FileDescription' => 'Descrizione file', + 'FileDescriptors' => 'Descrittori file', + 'FileFlags' => { + Description => 'Attributi file', + PrintConv => { + 'Info inferred' => 'Info desunte', + 'Private build' => 'Compilazione privata', + 'Special build' => 'Compilazione speciale', + }, + }, + 'FileFlagsMask' => 'Maschera attributi file', + 'FileFormat' => { + Description => 'Formato file', + PrintConv => { + 'Ritzaus Bureau NITF version (RBNITF DTD)' => 'Versione Ritzaus Bureau NITF (RBNITF DTD)', + }, + }, + 'FileFunctionFlags' => { + PrintConv => { + 'Fragmented' => 'Frammentato', + }, + }, + 'FileID' => 'ID file', + 'FileIndex' => 'Indice file', + 'FileIndex2' => 'Indice file 2', + 'FileLength' => 'Dimensioni file', + 'FileModifyDate' => 'Data aggiornamento', + 'FileName' => 'Nome file', + 'FileNameLength' => 'Lunghezza nome file', + 'FileNumber' => 'Numero file', + 'FileNumberMemory' => { + PrintConv => { + 'Off' => 'Spento', + }, + }, + 'FileNumberSequence' => { + PrintConv => { + 'Off' => 'Spento', + }, + }, + 'FileOS' => 'OS del file', + 'FileOwner' => 'Proprietario del file', + 'FilePermissions' => 'Permessi file', + 'FileProfileVersion' => 'Versione profilo file', + 'FileSecurityReport' => 'Rapporto sicurezza file', + 'FileSequence' => 'Sequenza file', + 'FileSetID' => 'ID gruppo file', + 'FileSize' => 'Dimensione file', + 'FileSizeBytes' => 'Dimensione file in byte', + 'FileSource' => { + Description => 'Origine file', + PrintConv => { + 'Digital Camera' => 'Fotocamera digitale', + 'Film Scanner' => 'Scanner per pellicola', + 'Reflection Print Scanner' => 'Scanner a riflessione', + 'Sigma Digital Camera' => 'Fotocamera digitale Sigma', + }, + }, + 'FileSubtype' => 'Sottotipo file', + 'FileType' => 'Tipo di file', + 'FileURL' => 'URL file', + 'FileVersion' => 'Versione file', + 'FileVersionNumber' => 'Numero versione file', + 'Filename' => 'Nome file', + 'Files' => 'File', + 'FillFlashAutoReduction' => { + PrintConv => { + 'Enable' => 'Abilita', + }, + }, + 'FillOrder' => { + Description => 'Ordine riempimento', + PrintConv => { + 'Normal' => 'Normale', + 'Reversed' => 'Invertito', + }, + }, + 'FilmMode' => { + PrintConv => { + 'Nostalgic' => 'Nostalgico', + 'Standard (B&W)' => 'Standard (B&N)', + 'Standard (color)' => 'Standard (colori)', + 'n/a' => 'n/d', + }, + }, + 'FilterEffect' => { + Description => 'Effetto Filtro', + PrintConv => { + 'Green' => 'Verde', + 'None' => 'Nessuno', + 'Off' => 'Spento', + 'Orange' => 'Arancio', + 'Red' => 'Rosso', + 'Yellow' => 'Giallo', + 'n/a' => 'n/d', + }, + }, + 'FilterEffectFaithful' => { + PrintConv => { + 'n/a' => 'n/d', + }, + }, + 'FilterEffectLandscape' => { + PrintConv => { + 'n/a' => 'n/d', + }, + }, + 'FilterEffectMonochrome' => { + PrintConv => { + 'Green' => 'Verde', + 'None' => 'Nessuno', + 'Orange' => 'Arancio', + 'Red' => 'Rosso', + 'Yellow' => 'Giallo', + 'n/a' => 'n/d', + }, + }, + 'FilterEffectNeutral' => { + PrintConv => { + 'n/a' => 'n/d', + }, + }, + 'FilterEffectPortrait' => { + PrintConv => { + 'n/a' => 'n/d', + }, + }, + 'FilterEffectStandard' => { + PrintConv => { + 'n/a' => 'n/d', + }, + }, + 'FilterEffectUnknown' => { + PrintConv => { + 'Green' => 'Verde', + 'None' => 'Nessuno', + 'Red' => 'Rosso', + 'n/a' => 'n/d', + }, + }, + 'FilterEffectUserDef1' => { + PrintConv => { + 'Green' => 'Verde', + 'None' => 'Nessuno', + 'Red' => 'Rosso', + 'n/a' => 'n/d', + }, + }, + 'FilterEffectUserDef2' => { + PrintConv => { + 'Green' => 'Verde', + 'None' => 'Nessuno', + 'Red' => 'Rosso', + 'n/a' => 'n/d', + }, + }, + 'FilterEffectUserDef3' => { + PrintConv => { + 'Green' => 'Verde', + 'None' => 'Nessuno', + 'Red' => 'Rosso', + 'n/a' => 'n/d', + }, + }, + 'FinalFrameBlocks' => 'Blocchi frame finali', + 'FinderDisplayDuringExposure' => { + PrintConv => { + 'Off' => 'Spento', + }, + }, + 'FineSharpness' => { + PrintConv => { + 'Normal' => 'Normale', + 'Off' => 'Spento', + }, + }, + 'FirmwareDate' => 'Data firmware', + 'FirmwareID' => 'ID firmware', + 'FirmwareName' => 'Nome firmware', + 'FirmwareRevision' => 'Revisione firmware', + 'FirmwareRevision2' => 'Revisione 2 firmware', + 'FirmwareVersion' => 'Versione firmware', + 'FirstChar' => 'Primo carattere', + 'FirstObject' => 'Primo oggetto', + 'FirstObjectID' => 'ID primo oggetto', + 'FixtureIdentifier' => 'Identificatore d\'installazione', + 'Flags' => { + PrintConv => { + 'FileName' => 'Nome file', + 'Text' => 'Testo', + }, + }, + 'Flash' => { + PrintConv => { + 'Auto, Did not fire' => 'Auto, flash non emesso', + 'Auto, Did not fire, Red-eye reduction' => 'Auto, flash non emesso, riduzione occhi rossi', + 'Auto, Fired' => 'Auto, flash emesso', + 'Auto, Fired, Red-eye reduction' => 'Auto, flash emesso, riduzione occhi rossi', + 'Auto, Fired, Red-eye reduction, Return detected' => 'Auto, flash emesso, riduzione occhi rossi, luce di ritorno rilevata', + 'Auto, Fired, Red-eye reduction, Return not detected' => 'Auto, flash emesso, riduzione occhi rossi, luce di ritorno non rilevata', + 'Auto, Fired, Return detected' => 'Auto, flash emesso, luce di ritorno rilevata', + 'Auto, Fired, Return not detected' => 'Auto, flash emesso, luce di ritorno non rilevata', + 'Did not fire' => 'Flash non emesso', + 'Fired' => 'Emesso', + 'Fired, Red-eye reduction' => 'Emesso, riduzione occhi rossi', + 'Fired, Red-eye reduction, Return detected' => 'Emesso, riduzione occhi rossi, ritorno rilevato', + 'Fired, Red-eye reduction, Return not detected' => 'Emesso, riduzione occhi rossi, ritorno non rilevato', + 'Fired, Return detected' => 'Emesso, ritorno rilevato', + 'Fired, Return not detected' => 'Emesso, ritorno non rilevato', + 'Flash Fired' => 'Flash emesso', + 'No Flash' => 'Flash non emesso', + 'No flash function' => 'Nessuna funzione flash', + 'Off' => 'Flash non emesso, modalità flash forzata', + 'Off, Did not fire' => 'Flash non emesso, modalità flash forzata', + 'Off, Did not fire, Return not detected' => 'Off, Non emesso. Luce di ritorno non rilevata', + 'Off, No flash function' => 'Off, Nessuna funzione flash', + 'Off, Red-eye reduction' => 'Disattivato, riduzione occhi rossi', + 'On' => 'Flash emesso, modalità flash forzata', + 'On, Did not fire' => 'Attivato, non emesso', + 'On, Fired' => 'Attivato, emesso', + 'On, Red-eye reduction' => 'Attivato, riiduzione occhi rossi', + 'On, Red-eye reduction, Return detected' => 'Attivato, riiduzione occhi rossi, ritorno rilevato', + 'On, Red-eye reduction, Return not detected' => 'Attivato, riiduzione occhi rossi, ritorno non rilevato', + 'On, Return detected' => 'Attivato, ritorno rilevato', + 'On, Return not detected' => 'Attivato, ritorno non rilevato', + }, + }, + 'FlashBits' => { + PrintConv => { + 'External' => 'Esterno', + 'Manual' => 'Manuale', + }, + }, + 'FlashButtonFunction' => { + PrintConv => { + 'ISO speed' => 'Velocità ISO', + }, + }, + 'FlashColorFilter' => { + PrintConv => { + 'None' => 'Nessuno', + 'Red' => 'Rosso', + }, + }, + 'FlashCommanderMode' => { + Description => 'Modo Commander', + PrintConv => { + 'Off' => 'Spento', + }, + }, + 'FlashCompensation' => 'Compensazione flash', + 'FlashControl' => 'Controllo flash', + 'FlashControlBuilt-in' => { + PrintConv => { + 'Manual' => 'Manuale', + 'Repeating Flash' => 'Ripetizione flash', + }, + }, + 'FlashControlMode' => { + Description => 'Modo Controllo Flash', + PrintConv => { + 'Auto Aperture' => 'Diaframma automatico', + 'Manual' => 'Manuale', + 'Off' => 'Spento', + 'Repeating Flash' => 'Ripetizione flash', + }, + }, + 'FlashDevice' => { + PrintConv => { + 'External' => 'Esterno', + 'None' => 'Nessuno', + }, + }, + 'FlashEnergy' => 'Energia del flash', + 'FlashExposureBracketValue' => 'Valore Esposizione a Forcella Flash', + 'FlashExposureComp' => 'Compensazione Esposizione Flash', + 'FlashExposureIndicator' => { + PrintConv => { + 'Not Indicated' => 'Non indicato', + }, + }, + 'FlashExposureIndicatorLast' => { + PrintConv => { + 'Not Indicated' => 'Non indicato', + }, + }, + 'FlashExposureIndicatorNext' => { + PrintConv => { + 'Not Indicated' => 'Non indicato', + }, + }, + 'FlashExposureLock' => { + PrintConv => { + 'Off' => 'Spento', + }, + }, + 'FlashFired' => { + Description => 'Flash emesso', + PrintConv => { + 'External' => 'Esterno', + 'Yes' => 'Sì', + }, + }, + 'FlashFiring' => 'Emissione flash', + 'FlashFirmwareVersion' => 'Versione firmware flash', + 'FlashFocalLength' => 'Lunghezza focale flash', + 'FlashFunction' => { + Description => 'Funzione flash', + PrintConv => { + 'Manual' => 'Manuale', + }, + }, + 'FlashGNDistance' => { + PrintConv => { + 'n/a' => 'n/d', + }, + }, + 'FlashGroupAControlMode' => { + Description => 'Gruppo A Modo Controllo Flash', + PrintConv => { + 'Auto Aperture' => 'Diaframma automatico', + 'Manual' => 'Manuale', + 'Off' => 'Spento', + 'Repeating Flash' => 'Ripetizione flash', + }, + }, + 'FlashGroupBControlMode' => { + Description => 'Gruppo B Modo Controllo Flash', + PrintConv => { + 'Auto Aperture' => 'Diaframma automatico', + 'Manual' => 'Manuale', + 'Off' => 'Spento', + 'Repeating Flash' => 'Ripetizione flash', + }, + }, + 'FlashGroupCControlMode' => { + Description => 'Gruppo C Modo Controllo Flash', + PrintConv => { + 'Manual' => 'Manuale', + 'Off' => 'Spento', + 'Repeating Flash' => 'Ripetizione flash', + }, + }, + 'FlashInfoVersion' => 'Info Versione Flash', + 'FlashIntensity' => { + PrintConv => { + 'Low' => 'Basso', + 'Normal' => 'Normale', + 'Strong' => 'Forte', + }, + }, + 'FlashLevel' => { + Description => 'Livello flash', + PrintConv => { + 'Low' => 'Basso', + 'Normal' => 'Normale', + }, + }, + 'FlashMeteringMode' => { + PrintConv => { + 'Off' => 'Spento', + }, + }, + 'FlashMode' => { + Description => 'Modo flash', + PrintConv => { + 'Did Not Fire' => 'Non emesso', + 'Fired, Commander Mode' => 'Emesso, Modalità Commander', + 'Fired, External' => 'Emesso Esterno', + 'Fired, Manual' => 'Emesso, Manuale', + 'Fired, TTL Mode' => 'Emesso, Modalità TTL', + 'Flash Off' => 'Flash spento', + 'Normal' => 'Normale', + 'Not Ready' => 'Non pronto', + 'Off' => 'Spento', + 'Off, Did not fire' => 'Spendo, non emesso', + 'Off?' => 'Spento?', + 'Red eye' => 'Occhi rossi', + 'Red-Eye' => 'Occhi rossi', + 'Red-Eye?' => 'Occhi rossi?', + 'Red-eye' => 'Occhi rossi', + 'Red-eye Reduction' => 'Riduzione occhi rossi', + 'Red-eye reduction' => 'Riduzione occhi rossi', + 'Unknown' => 'Sconosciuta', + }, + }, + 'FlashModel' => { + Description => 'Modello flash', + PrintConv => { + 'None' => 'Nessuno', + }, + }, + 'FlashOptions' => { + Description => 'Opzioni flash', + PrintConv => { + 'Normal' => 'Normale', + 'Red-eye reduction' => 'Riduzione occhi rossi', + }, + }, + 'FlashOptions2' => { + Description => 'Opzioni 2 flash', + PrintConv => { + 'Normal' => 'Normale', + 'Red-eye reduction' => 'Riduzione occhi rossi', + }, + }, + 'FlashRemoteControl' => { + Description => 'Telecomando flash', + PrintConv => { + 'Off' => 'Spento', + }, + }, + 'FlashReturn' => 'Ritorno flash', + 'FlashSerialNumber' => 'Numero di serie del flash', + 'FlashSetting' => 'Impostazione flash', + 'FlashSource' => { + Description => 'Fonte flash', + PrintConv => { + 'External' => 'Esterno', + 'None' => 'Nessuno', + }, + }, + 'FlashStatus' => { + Description => 'Stato flash', + PrintConv => { + 'Off' => 'Spento', + 'Off (1)' => 'Spento (1)', + }, + }, + 'FlashSyncSpeed' => { + PrintConv => { + '1/250 s (auto FP)' => '1/250 s (piano focale auto)', + '1/320 s (auto FP)' => '1/320 s (piano focale auto)', + }, + }, + 'FlashSyncSpeedAv' => { + PrintConv => { + '1/200 Fixed' => '1/200 fisso', + '1/200-1/60 Auto' => '1/200-1/60 auto', + '1/250 Fixed' => '1/250 fisso', + '1/250-1/60 Auto' => '1/250-1/60 auto', + '1/300 Fixed' => '1/300 fisso', + '1/300-1/60 Auto' => '1/300-1/60 auto', + }, + }, + 'FlashType' => { + Description => 'Tipo di flash', + PrintConv => { + 'External' => 'Esterno', + 'None' => 'Nessuno', + 'Off' => 'Spento', + }, + }, + 'FlashVersion' => 'Versione del flash', + 'FlashWarning' => { + PrintConv => { + 'Off' => 'Spento', + }, + }, + 'FlashpixVersion' => 'Versione Flashpix', + 'FlickerReduce' => { + PrintConv => { + 'Off' => 'Spento', + }, + }, + 'FlipHorizontal' => { + PrintConv => { + 'Yes' => 'Sì', + }, + }, + 'FocalLength' => 'Lunghezza focale', + 'FocalLength35efl' => 'Lunghezza focale', + 'FocalLength35mm' => 'Lunghezza focale 35mm', + 'FocalLengthIn35mmFormat' => 'Lunghezza focale in formato 35mm', + 'FocalPlaneDiagonal' => 'Diagonale piano focale', + 'FocalPlaneResolutionUnit' => { + Description => 'Unità risoluzione piano focale', + PrintConv => { + 'None' => 'Nessuno', + 'inches' => 'pollici', + }, + }, + 'FocalPlaneXResolution' => 'Risoluzione X del piano focale', + 'FocalPlaneXSize' => 'Dimensione X del piano focale', + 'FocalPlaneXUnknown' => 'X del piano focale sconisciuta', + 'FocalPlaneYResolution' => 'Risoluzione Y del piano focale', + 'FocalPlaneYSize' => 'Dimensione Y del piano focale', + 'FocalPlaneYUnknown' => 'Y del piano focale sconisciuta', + 'FocalType' => { + PrintConv => { + 'Fixed' => 'Fisso', + }, + }, + 'Focus' => { + PrintConv => { + 'Manual' => 'Manuale', + }, + }, + 'FocusContinuous' => { + PrintConv => { + 'Manual' => 'Manuale', + }, + }, + 'FocusDisplayAIServoAndMF' => { + PrintConv => { + 'Enable' => 'Abilita', + }, + }, + 'FocusDistance' => 'Distanza fuoco', + 'FocusMode' => { + Description => 'Modalità messa a fuoco', + PrintConv => { + 'Manual' => 'Manuale', + 'Normal' => 'Normale', + 'n/a' => 'n/d', + }, + }, + 'FocusMode2' => { + Description => 'Modalità messa a fuoco 2', + PrintConv => { + 'Manual' => 'Manuale', + }, + }, + 'FocusModeSetting' => { + PrintConv => { + 'Manual' => 'Manuale', + }, + }, + 'FocusModeSwitch' => { + PrintConv => { + 'Manual' => 'Manuale', + }, + }, + 'FocusPos' => 'Posizione fuoco', + 'FocusPosition' => 'Posizione fuoco', + 'FocusRange' => { + PrintConv => { + 'Manual' => 'Manuale', + 'Normal' => 'Normale', + 'Not Known' => 'Sconosciuto', + 'Very Close' => 'Molto vicino', + }, + }, + 'FocusStatus' => { + PrintConv => { + 'Failed' => 'Fallito', + 'Not confirmed' => 'Non confermato', + }, + }, + 'FocusTrackingLockOn' => { + PrintConv => { + '1 (Short)' => '1 (Breve)', + '1 Short' => '1 breve', + 'Normal' => 'Normale', + 'Off' => 'Spento', + 'Short' => 'Breve', + }, + }, + 'FontFamily' => { + Description => 'Tipo di carattere', + PrintConv => { + 'Swiss' => 'Svizzera', + }, + }, + 'FontFileName' => 'Nome file carattere', + 'FontName' => 'Nome carattere', + 'FontSize' => 'Dimensioni carattere', + 'FontSubfamily' => 'Sottotipo di carattere', + 'FontSubfamilyID' => 'ID sottotipo di carattere', + 'FontType' => 'Tipo di carattere', + 'FontVersion' => 'Versione carattere', + 'FontWeight' => 'Peso carattere', + 'Fonts' => 'Caratteri', + 'For' => 'Per', + 'Format' => 'Formato', + 'ForwardMatrix1' => 'Matrice predittiva 1', + 'ForwardMatrix2' => 'Matrice predittiva 2', + 'FrameRate' => 'Frequenza fotogramma', + 'FrameSize' => 'Dimensioni fotogrammi', + 'FreeByteCounts' => 'Byte disponibili', + 'FreeOffsets' => 'Offset disponibili', + 'FujiFlashMode' => { + PrintConv => { + 'External' => 'Esterno', + 'Off' => 'Spento', + 'Red-eye reduction' => 'Riduzione occhi rossi', + }, + }, + 'FuncButton' => { + PrintConv => { + 'Flash Off' => 'Flash spento', + 'None' => 'Nessuno', + 'Preview' => 'Anteprima', + 'Virtual Horizon' => 'Orizzonte virtuale', + }, + }, + 'FuncButtonPlusDials' => { + PrintConv => { + 'Choose Image Area' => 'Seleziona area immagine', + 'None' => 'Nessuno', + }, + }, + 'FunctionButton' => { + PrintConv => { + 'Flash Off' => 'Flash spento', + }, + }, + 'GDALMetadata' => 'Metadati GDAL', + 'GDALNoData' => 'Nessun dato GDAL', + 'GIFVersion' => 'Versione GIF', + 'GPSAltitude' => 'Altitudine GPS', + 'GPSAltitudeRef' => { + Description => 'Riferimento altitudine GPS', + PrintConv => { + 'Above Sea Level' => 'Sul livello del mare', + 'Below Sea Level' => 'Sotto il livello del mare', + }, + }, + 'GPSAreaInformation' => 'Informazioni area GPS', + 'GPSDOP' => 'Precisione misurazione GPS', + 'GPSDateStamp' => 'Data GPS', + 'GPSDateTime' => 'Ora GPS (orologio atomico)', + 'GPSDestBearing' => 'Direzione destinazione GPS', + 'GPSDestBearingRef' => { + Description => 'Riferimento direzione destinazione GPS', + PrintConv => { + 'Magnetic North' => 'Nord magnetico', + 'True North' => 'Nord geografico', + }, + }, + 'GPSDestDistance' => 'Distanza destinazione GPS', + 'GPSDestDistanceRef' => { + Description => 'Riferimento distanza destinazione GPS', + PrintConv => { + 'Kilometers' => 'Chilometri', + 'Miles' => 'Miglia', + 'Nautical Miles' => 'Miglia nautiche', + }, + }, + 'GPSDestLatitude' => 'Latitudine destinazione GPS', + 'GPSDestLatitudeRef' => { + Description => 'Riferimento latitudine destinazione GPS', + PrintConv => { + 'North' => 'Nord', + 'South' => 'Sud', + }, + }, + 'GPSDestLongitude' => 'Longitudine destinazione GPS', + 'GPSDestLongitudeRef' => { + Description => 'Riferimento per longitudine di destinazione', + PrintConv => { + 'East' => 'Est', + 'West' => 'Ovest', + }, + }, + 'GPSDifferential' => { + Description => 'Correzione differenziale GPS', + PrintConv => { + 'Differential Corrected' => 'Correzione differenziale applicata', + 'No Correction' => 'Misurazione senza correzione differenziale', + }, + }, + 'GPSHPositioningError' => 'Errore posizionamento orizzontale GPS', + 'GPSImgDirection' => 'Direzione di immagine', + 'GPSImgDirectionRef' => { + Description => 'Riferimento per direzione di immagine', + PrintConv => { + 'Magnetic North' => 'Nord magnetico', + 'True North' => 'Nord geografico', + }, + }, + 'GPSInfo' => 'Puntatore GPS Info IFD', + 'GPSLatitude' => 'Latitudine', + 'GPSLatitudeRef' => { + Description => 'Latitudine Nord o Sud', + PrintConv => { + 'North' => 'Latitudine Nord', + 'South' => 'Latitudine Sud', + }, + }, + 'GPSLongitude' => 'Longitudine', + 'GPSLongitudeRef' => { + Description => 'Longitudine Est o Ovest', + PrintConv => { + 'East' => 'Longitudine Est', + 'West' => 'Longitudine Ovest', + }, + }, + 'GPSMapDatum' => 'Dati di rilevamento geodetico utilizzati', + 'GPSMeasureMode' => { + Description => 'Modalità misurazione GPS', + PrintConv => { + '2-Dimensional Measurement' => 'Misurazione 2D', + '3-Dimensional Measurement' => 'Misurazione tridimensionale', + }, + }, + 'GPSProcessingMethod' => 'Nome metodo di elaborazione GPS', + 'GPSSatellites' => 'Satelliti GPS usati per la misurazione', + 'GPSSpeed' => 'Velocità ricevitore GPS', + 'GPSSpeedRef' => { + Description => 'Unità velocità', + PrintConv => { + 'km/h' => 'Chilometri all\'ora', + 'knots' => 'Nodi', + 'mph' => 'Miglie all\'ora', + }, + }, + 'GPSStatus' => { + Description => 'Stato ricevitore GPS', + PrintConv => { + 'Measurement Active' => 'Misurazione in corso', + 'Measurement Void' => 'Interoperatività misurazione', + }, + }, + 'GPSTimeStamp' => 'Ora GPS (orologio atomico)', + 'GPSTrack' => 'Direzione di movimento', + 'GPSTrackRef' => { + Description => 'Riferimento per direzione di movimento', + PrintConv => { + 'Magnetic North' => 'Direzione magnetica', + 'True North' => 'Direzione effettiva', + }, + }, + 'GPSVersionID' => 'Versione tag GPS', + 'GTModelType' => { + PrintConv => { + 'Projected' => 'Proiettato', + }, + }, + 'GainControl' => { + Description => 'Controllo di Guadagno', + PrintConv => { + 'High gain down' => 'Diminuire il guadagno alto', + 'High gain up' => 'Aumentare il guadagno alto', + 'Low gain down' => 'Diminuire il guadagno basso', + 'Low gain up' => 'Aumentare il guadagno basso', + 'None' => 'Nessuno', + }, + }, + 'GammaCompensatedValue' => 'Valore di Compensazione Gamma', + 'Gapless' => { + PrintConv => { + 'Yes' => 'Sì', + }, + }, + 'Genre' => { + Description => 'Genere', + PrintConv => { + 'Acapella' => 'A cappella', + 'Acid Jazz' => 'Acid jazz', + 'Acid Punk' => 'Acid punk', + 'Acoustic' => 'Acustica', + 'Ambient' => 'Ambientale', + 'Avantgarde' => 'Avanguardia', + 'Ballad' => 'Ballata', + 'Bass' => 'Basso', + 'Big Band' => 'Big band', + 'Black Metal' => 'Black metal', + 'Booty Bass' => 'Basso booty', + 'Celtic' => 'Celtica', + 'Chamber Music' => 'Musica da camera', + 'Chorus' => 'Coro', + 'Christian Gangsta' => 'Gangsta cristiano', + 'Christian Rap' => 'Rap cristiano', + 'Christian Rock' => 'Rock cristiano', + 'Classic Rock' => 'Rock classico', + 'Classical' => 'Classica', + 'Club-House' => 'Club-house', + 'Comedy' => 'Commedia', + 'Contemporary C' => 'C contemporaneo', + 'Country' => 'Nazione', + 'Cover' => 'Copertina', + 'Dance Hall' => 'Dance hall', + 'Death Metal' => 'Death metal', + 'Drum & Bass' => 'Batteria e basso', + 'Drum Solo' => 'Batteria solo', + 'Duet' => 'Duetto', + 'Easy Listening' => 'Easy listening', + 'Electronic' => 'Elettronica', + 'Ethnic' => 'Etnica', + 'Euro-House' => 'Euro-house', + 'Euro-Techno' => 'Euro-techno', + 'Fast Fusion' => 'Fast fusion', + 'Folk-Rock' => 'Folk-rock', + 'Game' => 'Gioco', + 'Gothic' => 'Gotica', + 'Gothic Rock' => 'Rock gotico', + 'Hard Rock' => 'Hard rock', + 'Heavy Metal' => 'Heavy metal', + 'Hip-Hop' => 'Hip-hop', + 'Humour' => 'Umoristica', + 'Instrumental' => 'Strumentale', + 'Instrumental Pop' => 'Pop strumentale', + 'Instrumental Rock' => 'Rock strumentale', + 'Jazz+Funk' => 'Jazz+funk', + 'Latin' => 'Latina', + 'Lo-Fi' => 'Lo-fi', + 'Meditative' => 'Medidativa', + 'National Folk' => 'Folklore nazionale', + 'Native American' => 'Nativi americani', + 'New Age' => 'New age', + 'New Wave' => 'New wave', + 'Noise' => 'Rumore', + 'None' => 'Nessuno', + 'Oldies' => 'Vecchi successi', + 'Other' => 'Altro', + 'Polsk Punk' => 'Punk polacco', + 'Pop-Folk' => 'Pop-folk', + 'Pop/Funk' => 'Pop/funk', + 'Porn Groove' => 'Porn groove', + 'Power Ballad' => 'Power ballad', + 'Progressive Rock' => 'Progressive rock', + 'Psychadelic' => 'Psichedelica', + 'Psychedelic Rock' => 'Rock psichedelica', + 'Punk Rock' => 'Punk rock', + 'Retro' => 'Retrò', + 'Rhythmic Soul' => 'Rhythmic soul', + 'Rock & Roll' => 'Rock & roll', + 'Satire' => 'Satira', + 'Slow Jam' => 'Slow jam', + 'Slow Rock' => 'Slow rock', + 'Sound Clip' => 'Clip sonora', + 'Soundtrack' => 'Colonna sonora', + 'Southern Rock' => 'Southern rock', + 'Speech' => 'Parlato', + 'Symphonic Rock' => 'Rock sinfonico', + 'Symphony' => 'Sinfonia', + 'Techno-Industrial' => 'Techno-industrial', + 'Terror' => 'Terrore', + 'Thrash Metal' => 'Thrash metal', + 'Tribal' => 'Tribale', + 'Trip-Hop' => 'Trip-hop', + }, + }, + 'GenreID' => 'ID genere', + 'GeoTiffAsciiParams' => 'Parametri Geo Tiff Ascii', + 'GeoTiffDirectory' => 'Cartella Geo Tiff', + 'GeoTiffDoubleParams' => 'Parametri Geo Tiff Double', + 'GeogGeodeticDatum' => { + PrintConv => { + 'Lisbon' => 'Lisbona', + 'Stockholm 1938' => 'Stoccolma 1938', + }, + }, + 'GeogPrimeMeridian' => { + PrintConv => { + 'Lisbon' => 'Lisbona', + 'Rome' => 'Roma', + 'Stockholm' => 'Stoccolma', + }, + }, + 'GeographicType' => { + PrintConv => { + 'Greek' => 'Greco', + 'Lisbon' => 'Lisbona', + 'Stockholm 1938' => 'Stoccolma 1938', + }, + }, + 'Gradation' => { + Description => 'Ottimizzaz.', + PrintConv => { + 'Normal' => 'Normale', + 'n/a' => 'n/d', + }, + }, + 'GrayResponseCurve' => 'Curva di risposta Grigio', + 'GrayResponseUnit' => { + Description => 'Unità di risposta Grigio', + PrintConv => { + '1e-05' => '1e-005', + '1e-06' => '1e-006', + }, + }, + 'GrayTRC' => 'Curva Riproduzione Tono Grigio', + 'GreenMatrixColumn' => 'Colonna della Matrice Verde', + 'GreenTRC' => 'Curva Riproduziozne Tono Verde', + 'GridDisplay' => { + PrintConv => { + 'Off' => 'Spento', + }, + }, + 'Grouping' => 'Raggruppamento', + 'HCUsage' => { + Description => 'Uso HC', + PrintConv => { + 'Line Art' => 'Line art', + }, + }, + 'HDR' => { + Description => 'HDR auto', + PrintConv => { + 'Off' => 'Disattivata', + }, + }, + 'HDRSetting' => { + PrintConv => { + 'Off' => 'Spento', + }, + }, + 'HalftoneHints' => 'Suggerimenti mezzi toni', + 'HandlerType' => { + PrintConv => { + 'Text' => 'Testo', + }, + }, + 'Headline' => 'Intestazione', + 'HeightResolution' => 'Risoluzione altezza', + 'HighISONoiseReduction' => { + Description => 'Riduzione Rumore High ISO', + PrintConv => { + 'Auto' => 'Automatico', + 'High' => 'Hi', + 'Low' => 'Leggero', + 'Normal' => 'Normale', + 'Off' => 'Disattivata', + 'Strong' => 'Forte', + 'n/a' => 'n/d', + }, + }, + 'HighSpeedSync' => { + PrintConv => { + 'Off' => 'Spento', + }, + }, + 'HighlightTonePriority' => { + PrintConv => { + 'Enable' => 'Abilita', + 'Off' => 'Spento', + }, + }, + 'HometownCity' => { + PrintConv => { + 'Jerusalem' => 'Gerusalemme', + 'Lisbon' => 'Lisbona', + 'London' => 'Londra', + 'Milan' => 'Milano', + 'Prague' => 'Praga', + 'Rome' => 'Roma', + 'Stockholm' => 'Stoccolma', + 'Tehran' => 'Teheran', + }, + }, + 'HometownDST' => { + PrintConv => { + 'Yes' => 'Sì', + }, + }, + 'HostComputer' => 'Computer ospite', + 'HotKey' => { + PrintConv => { + '(none)' => '(nessuno)', + }, + }, + 'Hue' => { + Description => 'Tonalità', + PrintConv => { + 'None' => 'Nessuno', + 'Normal' => 'Normale', + }, + }, + 'HueAdjustment' => 'Regolazione Hue', + 'ICCProfile' => 'Profili ICC', + 'IDCCreativeStyle' => { + PrintConv => { + 'Camera Setting' => 'Impostazioni fotocamera', + 'Landscape' => 'Orizzontale', + 'Light' => 'Chiara', + 'Real' => 'Reale', + 'Sepia' => 'Seppia', + 'Sunset' => 'Tramonto', + 'Vivid' => 'Vivace', + }, + }, + 'INGRReserved' => 'Riseervato a INGR', + 'IPTC-NAA' => 'Metadati IPTC-NAA', + 'IPTCBitsPerSample' => 'Numero di Bits per Campione', + 'IPTCImageHeight' => 'Numero di linee', + 'IPTCImageRotation' => { + Description => 'Rotazione Immagine', + PrintConv => { + '0' => 'Nessuna rotazione', + '180' => 'Rotazione di 180 gradi', + '270' => 'Rotazione di 270 gradi', + '90' => 'Rotazione di 90 gradi', + }, + }, + 'IPTCImageWidth' => 'Pixels per linea', + 'IPTCPictureNumber' => 'Numero Immagine', + 'ISO' => 'Sensibilità ISO', + 'ISOAuto' => { + Description => 'ISO auto', + PrintConv => { + 'Off' => 'Spento', + }, + }, + 'ISOAutoParameters' => { + Description => 'Parametri ISO auto', + PrintConv => { + 'Fast' => 'Veloce', + }, + }, + 'ISODisplay' => { + PrintConv => { + 'Off' => 'Spento', + }, + }, + 'ISOExpansion' => { + PrintConv => { + 'Off' => 'Spento', + }, + }, + 'ISOExpansion2' => { + PrintConv => { + 'Off' => 'Spento', + }, + }, + 'ISOInfo' => 'Info ISO', + 'ISOSelection' => 'Selezione ISO', + 'ISOSensitivityStep' => 'Passo sensibilità ISO', + 'ISOSetting' => { + Description => 'Impostazione ISO', + PrintConv => { + '100 (Low)' => '100 (basso)', + 'Manual' => 'Manuale', + 'n/a' => 'n/d', + }, + }, + 'ISOSpeed' => 'Velocità ISO', + 'ISOSpeedExpansion' => { + PrintConv => { + 'Yes' => 'Sì', + }, + }, + 'ISOSpeedIncrements' => { + PrintConv => { + '1 Stop' => '1 stop', + '1/3 Stop' => '1/3 stop', + }, + }, + 'ISOSpeedLatitudeyyy' => 'Velocità ISO - Latitudine yyy', + 'ISOSpeedLatitudezzz' => 'Velocità ISO - Latitudine zzz', + 'ISOSpeedRange' => { + PrintConv => { + 'Enable' => 'Abilita', + }, + }, + 'ISOValue' => 'Valore ISO', + 'IT8Header' => 'Intestazione IT8', + 'Illumination' => { + PrintConv => { + 'Off' => 'Spento', + }, + }, + 'Image::ExifTool::AIFF::Comment' => 'Commento AIFF', + 'Image::ExifTool::EXE::CHM' => 'EXE CHM', + 'Image::ExifTool::EXE::ELF' => 'EXE ELF', + 'Image::ExifTool::EXE::MachO' => 'EXE MachO', + 'Image::ExifTool::EXE::Main' => 'EXE', + 'Image::ExifTool::EXE::PEF' => 'EXE PEF', + 'Image::ExifTool::EXE::PEString' => 'EXE PEString', + 'Image::ExifTool::EXE::PEVersion' => 'EXE PEVersion', + 'Image::ExifTool::Exif::Main' => 'Exif', + 'Image::ExifTool::FLAC::Main' => 'FLAC', + 'Image::ExifTool::Flash::Main' => 'Flash', + 'Image::ExifTool::Flash::Video' => 'Video flash', + 'Image::ExifTool::FlashPix::Main' => 'FlashPix', + 'Image::ExifTool::Font::Main' => 'Carattere', + 'Image::ExifTool::Font::Name' => 'Nome carattere', + 'Image::ExifTool::Font::PFM' => 'Carattere PFM', + 'Image::ExifTool::GPS::Main' => 'GPS', + 'Image::ExifTool::ID3::Private' => 'ID3 privato', + 'Image::ExifTool::ID3::v1' => 'ID3 v1', + 'Image::ExifTool::ID3::v1_Enh' => 'ID3 v1_Enh', + 'Image::ExifTool::ID3::v2_2' => 'ID3 v2_2', + 'Image::ExifTool::ID3::v2_3' => 'ID3 v2_3', + 'Image::ExifTool::ID3::v2_4' => 'ID3 v2_4', + 'Image::ExifTool::ITC::Main' => 'ITC', + 'Image::ExifTool::JFIF::Main' => 'JFIF', + 'Image::ExifTool::Kodak::DcMD' => 'Kodak DcMD', + 'Image::ExifTool::Kodak::Free' => 'Kodak Free', + 'Image::ExifTool::Kodak::KDC_IFD' => 'KDC_IFD Kodak', + 'Image::ExifTool::Kodak::Main' => 'Kodak', + 'Image::ExifTool::Microsoft::Stitch' => 'Microsoft Stitch', + 'Image::ExifTool::Olympus::AVI' => 'AVI Olympus', + 'Image::ExifTool::Olympus::Main' => 'Olympus', + 'Image::ExifTool::PSP::Creator' => 'Creatore PSP', + 'Image::ExifTool::PSP::Image' => 'Immagine PSP', + 'Image::ExifTool::PSP::Main' => 'PSP', + 'Image::ExifTool::PanasonicRaw::Main' => 'PanasonicRaw', + 'Image::ExifTool::PostScript::Main' => 'PostScript', + 'Image::ExifTool::PrintIM::Main' => 'PrintIM', + 'Image::ExifTool::Qualcomm::Main' => 'Qualcomm', + 'Image::ExifTool::QuickTime::Main' => 'QuickTime', + 'Image::ExifTool::RIFF::Main' => 'RIFF', + 'Image::ExifTool::Radiance::Main' => 'Radianza', + 'Image::ExifTool::Rawzor::Main' => 'Rawzor', + 'Image::ExifTool::Real::AudioV3' => 'Real AudioV3', + 'Image::ExifTool::Real::AudioV4' => 'Real AudioV4', + 'Image::ExifTool::Real::AudioV5' => 'Real AudioV5', + 'Image::ExifTool::Ricoh::AVI' => 'AVI Ricoh', + 'Image::ExifTool::Ricoh::FaceInfo' => 'FaceInfo Ricoh', + 'Image::ExifTool::Ricoh::FirmwareInfo' => 'Info firmware Ricoh', + 'Image::ExifTool::Ricoh::ImageInfo' => 'Info immagine Ricoh', + 'Image::ExifTool::Ricoh::Main' => 'Ricoh', + 'Image::ExifTool::Ricoh::RMETA' => 'RMETA Ricoh', + 'Image::ExifTool::Ricoh::SerialInfo' => 'Info seriale Ricoh', + 'Image::ExifTool::Ricoh::Subdir' => 'Sotto-cartella Ricoh', + 'Image::ExifTool::Ricoh::Text' => 'Testo Ricoh', + 'Image::ExifTool::Samsung::INFO' => 'Samsung INFO', + 'Image::ExifTool::Samsung::MP4' => 'Samsung MP4', + 'Image::ExifTool::Samsung::PictureWizard' => 'Samsung PictureWizard', + 'Image::ExifTool::Sanyo::Main' => 'Sanyo', + 'Image::ExifTool::Sigma::Main' => 'Sigma', + 'ImageAdjustment' => 'Regolazione Immagine', + 'ImageAlterationConstraints' => { + PrintConv => { + 'No Merging' => 'Nessuna fusione', + }, + }, + 'ImageAuthentication' => { + PrintConv => { + 'Off' => 'Spento', + }, + }, + 'ImageByteCount' => 'Numero di byte dell\'immagine', + 'ImageColorIndicator' => { + Description => 'Indicazione colore dell\'immagine', + PrintConv => { + 'Specified Image Color' => 'Colore immagine specificato', + 'Unspecified Image Color' => 'Colore immagine non specificato', + }, + }, + 'ImageColorValue' => 'Valore colore dell\'immagine', + 'ImageCount' => 'Conteggio Immagini', + 'ImageDataDiscard' => { + Description => 'Dati scartati dell\'immagine', + PrintConv => { + 'Flexbits Discarded' => 'Flexbit scartati', + 'Full Resolution' => 'Risoluzione completa', + 'HighPass Frequency Data Discarded' => 'Dati in frequenza passa-alto scartati', + 'Highpass and LowPass Frequency Data Discarded' => 'Dati in frequenza passa-alto e passa-basso scartati', + }, + }, + 'ImageDataSize' => 'Dimensione Dati Immagine', + 'ImageDepth' => 'Profondità Immagine', + 'ImageDescription' => 'Descrizione Immagine', + 'ImageDustOff' => { + PrintConv => { + 'Off' => 'Spento', + }, + }, + 'ImageEditing' => { + PrintConv => { + 'None' => 'Nessuno', + 'Resized' => 'Ridimensionato', + }, + }, + 'ImageHeight' => 'Altezza immagine', + 'ImageHistory' => 'Cronologia immagine', + 'ImageID' => 'ID Immagine', + 'ImageLayer' => 'Livello immagine', + 'ImageNumber' => 'Numero immagine', + 'ImageOffset' => 'Offset immagine', + 'ImageOptimization' => 'Ottimizzazione Immagine', + 'ImageOrientation' => { + Description => 'Orientamento Immagine', + PrintConv => { + 'Landscape' => 'Orizzontale', + 'Portrait' => 'Verticale', + 'Square' => 'Quadrata', + }, + }, + 'ImageQuality' => { + Description => 'Qualità Immagine', + PrintConv => { + 'Normal' => 'Normale', + }, + }, + 'ImageReview' => { + PrintConv => { + 'Off' => 'Spento', + }, + }, + 'ImageRotated' => { + PrintConv => { + 'Yes' => 'Sì', + }, + }, + 'ImageRotation' => { + PrintConv => { + 'None' => 'Nessuno', + }, + }, + 'ImageSize' => 'Dimensioni immagini', + 'ImageSourceData' => 'Dati origine immagine', + 'ImageStabilization' => { + Description => 'Stabilizzazione Immagine', + PrintConv => { + 'Off' => 'Spento', + 'Off (1)' => 'Spento (1)', + 'Off (2)' => 'Spento (2)', + 'n/a' => 'n/d', + }, + }, + 'ImageStabilizationSetting' => { + PrintConv => { + 'Off' => 'Spento', + }, + }, + 'ImageStyle' => { + PrintConv => { + 'Landscape' => 'Orizzontale', + 'Sunset' => 'Tramonto', + 'Vivid' => 'Vivace', + }, + }, + 'ImageTone' => { + PrintConv => { + 'Landscape' => 'Orizzontale', + 'Portrait' => 'Verticale', + 'Radiant' => 'Radiante', + }, + }, + 'ImageType' => { + Description => 'Tipo immagine', + PrintConv => { + 'Page' => 'Pagina', + 'Preview' => 'Anteprima', + }, + }, + 'ImageUniqueID' => 'ID unico immagine', + 'ImageVersion' => 'Versione immagine', + 'ImageWidth' => 'Larghezza immagine', + 'Index' => 'Indice', + 'Indexable' => { + PrintConv => { + 'False' => 'Falso', + }, + }, + 'Indexed' => { + Description => 'Indicizzato', + PrintConv => { + 'Indexed' => 'Indicizzato', + 'Not indexed' => 'Non indicizzato', + }, + }, + 'InfraredIlluminator' => { + PrintConv => { + 'Off' => 'Spento', + }, + }, + 'InitialDisplayEffect' => { + PrintConv => { + 'Off' => 'Spento', + }, + }, + 'InitialKey' => 'Chiave iniziale', + 'InitializedDataSize' => 'Dimensione dati inizializzati', + 'InkNames' => 'Nomi inchiostri', + 'InkSet' => { + Description => 'Gruppo inchiostri', + PrintConv => { + 'Not CMYK' => 'Non CMYK', + }, + }, + 'Instructions' => 'Istruzioni', + 'IntellectualGenre' => 'Genere Intellettuale', + 'IntelligentAuto' => { + PrintConv => { + 'Off' => 'Spento', + }, + }, + 'IntelligentContrast' => { + PrintConv => { + 'Off' => 'Spento', + 'n/a' => 'n/d', + }, + }, + 'IntelligentD-Range' => { + PrintConv => { + 'Low' => 'Basso', + 'Off' => 'Spento', + }, + }, + 'IntelligentExposure' => { + PrintConv => { + 'Low' => 'Basso', + 'Off' => 'Spento', + }, + }, + 'IntelligentResolution' => { + PrintConv => { + 'Extended' => 'Esteso', + 'Low' => 'Basso', + 'Off' => 'Spento', + }, + }, + 'IntensityStereo' => { + PrintConv => { + 'Off' => 'Spento', + }, + }, + 'Interlace' => { + Description => 'Interlacciamento', + PrintConv => { + 'Noninterlaced' => 'Non interlacciato', + 'Progressive' => 'Progressivo', + }, + }, + 'InterleavedField' => { + PrintConv => { + 'Even' => 'Pari', + }, + }, + 'InternalFlash' => { + PrintConv => { + 'Fired' => 'Flash emesso', + 'Manual' => 'Manuale', + 'No' => 'Flash non emesso', + 'Off' => 'Spento', + 'Repeating Flash' => 'Ripetizione flash', + }, + }, + 'InternalName' => 'Nome interno', + 'InternetRadioStationName' => 'Nome stazione radio internet', + 'InternetRadioStationOwner' => 'Proprietario stazione radio internet', + 'InternetRadioStationURL' => 'URL stazione radio internet', + 'InteropIndex' => { + Description => 'Identificazione interoperatività', + PrintConv => { + 'R03 - DCF option file (Adobe RGB)' => 'R03 - file opzioni DCF (Adobe RGB)', + 'R98 - DCF basic file (sRGB)' => 'R98 - file base DCF (sRGB)', + 'THM - DCF thumbnail file' => 'File miniatura THM - DCF', + }, + }, + 'InteropOffset' => 'Etichetta interoperatività', + 'InteropVersion' => 'Versione interoperatività', + 'InterpretedBy' => 'Interpetrato da', + 'InvolvedPeople' => 'Persone coinvolte', + 'Italic' => 'Corsivo', + 'JFIFVersion' => 'Versione JFIF', + 'JPEGACTables' => 'Tabelle JPEGAC', + 'JPEGDCTables' => 'Tabelle JPEGDC', + 'JPEGLosslessPredictors' => 'Predittori JPEG senza perdita', + 'JPEGPointTransforms' => 'Trasformazioni puntiali JPEG', + 'JPEGProc' => { + Description => 'Proc JPEG', + PrintConv => { + 'Baseline' => 'Linea di base', + 'Lossless' => 'Senza perdita', + }, + }, + 'JPEGQTables' => 'Tabelle JPEGQ', + 'JPEGQuality' => { + Description => 'Qualità', + PrintConv => { + 'Extra Fine' => 'Extra fine', + 'Standard' => 'Normale', + 'n/a' => 'n/d', + }, + }, + 'JPEGRestartInterval' => 'Intervallo riavvio JPEG', + 'JPEGTables' => 'Tabelle JPEG', + 'JobID' => 'ID processo', + 'JobName' => 'Nome processo', + 'JobRef' => 'Rif processo', + 'JobStatus' => 'Stato processo', + 'JpgFromRaw' => 'JPG da raw', + 'JpgFromRawLength' => 'Lunghezza JPG da raw', + 'JpgFromRawStart' => 'Inizio JPG da raw', + 'Keyword' => 'Parola chiave', + 'KeywordInfo' => 'Info parola chiave', + 'Keywords' => 'Parole chiave', + 'Kinds' => 'Tipi', + 'LCDIllumination' => { + PrintConv => { + 'Off' => 'Spento', + }, + }, + 'LCDIlluminationDuringBulb' => { + PrintConv => { + 'Off' => 'Spento', + }, + }, + 'LCHEditor' => { + PrintConv => { + 'Off' => 'Spento', + }, + }, + 'Language' => 'Lingua', + 'LanguageCode' => { + Description => 'Codice lingua', + PrintConv => { + 'Albanian' => 'Albanese', + 'Arabic' => 'Arabo', + 'Armenian' => 'Armeno', + 'Azeri' => 'Azero', + 'Basque' => 'Basco', + 'Belarusian' => 'Bielorusso', + 'Breton' => 'Bretone', + 'Bulgarian' => 'Bulgaro', + 'Catalan' => 'Catalano', + 'Chinese (Simplified)' => 'Cinese (semplificato)', + 'Chinese (Traditional)' => 'Cinese (tradizionale)', + 'Croato-Serbian (Latin)' => 'Serbo-croato (alfabeto latino)', + 'Czech' => 'Ceco', + 'Danish' => 'Danese', + 'Dutch' => 'Olandese', + 'Dutch (Belgian)' => 'Olandese (Belgio)', + 'English (Australian)' => 'Inglese (Australia)', + 'English (British)' => 'Inglese (Gran Bretagna)', + 'English (Canadian)' => 'Inglese (Canada)', + 'English (U.S.)' => 'Inglese (U.S.A.)', + 'Estonian' => 'Estone', + 'Farsi' => 'Persiano', + 'Finnish' => 'Finlandese', + 'French' => 'Francese', + 'French (Belgian)' => 'Francese (Belgio)', + 'French (Canadian)' => 'Francese (Canada)', + 'French (Swiss)' => 'Francese (Svizzera)', + 'Gaelic' => 'Gaelico', + 'Galician' => 'Galiziano', + 'Georgian' => 'Georgiano', + 'German' => 'Tedesco', + 'German (Austrian)' => 'Tedesco (Austria)', + 'German (Swiss)' => 'Tedesco (Svizzera)', + 'Greek' => 'Greco', + 'Hebrew' => 'Ebraico', + 'Hungarian' => 'Ungherese', + 'Icelandic' => 'Islandese', + 'Indonesian' => 'Indonesiano', + 'Invariant' => 'Invariante', + 'Italian' => 'Italiano', + 'Italian (Swiss)' => 'Italiano (Svizzera)', + 'Japanese' => 'Giapponese', + 'Kazak' => 'Kazako', + 'Korean' => 'Coreano', + 'Kyrgyz' => 'Kirghizo', + 'Latvian' => 'Lettone', + 'Lithuanian' => 'Lituano', + 'Macedonian' => 'Macedone', + 'Mongolian' => 'Mongolo', + 'Nepali' => 'Nepalese', + 'Neutral' => 'Neutrale', + 'Neutral 2' => 'Neutrale 2', + 'Norwegian (Bokml)' => 'Norvegese (Bokmål)', + 'Norwegian (Nynorsk)' => 'Norvegese (Nynorsk)', + 'Polish' => 'Polacco', + 'Portuguese' => 'Portogese', + 'Portuguese (Brazilian)' => 'Portoghese (Brasile)', + 'Process default' => 'Predefinita del processo', + 'Rhaeto-Romanic' => 'Reto-romanico', + 'Romanian' => 'Rumeno', + 'Russian' => 'Russo', + 'Sanskrit' => 'Sanscrito', + 'Serbo-Croatian (Cyrillic)' => 'Serbo-croato (cirillico)', + 'Slovak' => 'Slovacco', + 'Slovenian' => 'Sloveno', + 'Spanish (Castilian)' => 'Spagnolo (Castiglia)', + 'Spanish (Mexican)' => 'Spagnolo (Messico)', + 'Spanish (Modern)' => 'Spagnolo moderno', + 'Swedish' => 'Svedese', + 'Syriac' => 'Siriaco', + 'Turkish' => 'Turco', + 'Ukrainian' => 'Ucraino', + 'Uzbek' => 'Usbeco', + 'Vietnamese' => 'Vietnamita', + 'Welsh' => 'Gallese', + }, + }, + 'LanguageIdentifier' => 'Identificativo lingua', + 'LanguageList' => 'Lista lingue', + 'LanguageName' => 'Nome lingua', + 'LateralChromaticAberration' => { + PrintConv => { + 'Off' => 'Spento', + 'n/a' => 'n/d', + }, + }, + 'Layout' => { + PrintConv => { + 'Tiles' => 'Tasselli', + }, + }, + 'LegalCopyright' => 'Copyright legali', + 'LegalTrademarks' => 'Marchi legali', + 'Length' => 'Durata', + 'Lens' => 'Obiettivo', + 'Lens35efl' => 'Obiettivo', + 'LensDataVersion' => 'Versione Dati Obiettivo', + 'LensFStops' => 'F-Stops Obiettivo', + 'LensID' => { + Description => 'Obiettivo Utilizzato', + PrintConv => { + 'Ricoh Lens A16 24-85mm F3.5-5.5' => 'Obiettivo Ricoh A16 24-85mm F3.5-5.5', + 'Ricoh Lens P10 28-300mm F3.5-5.6 VC' => 'Obiettivo Ricoh P10 28-300mm F3.5-5.6 VC', + 'Ricoh Lens S10 24-70mm F2.5-4.4 VC' => 'Obiettivo Ricoh S10 24-70mm F2.5-4.4 VC', + }, + }, + 'LensIDNumber' => 'Numero ID Obiettivo', + 'LensInfo' => 'Informazioni obiettivo', + 'LensMake' => 'Marca obiettivo', + 'LensModel' => 'Modello obiettivo', + 'LensSerialNumber' => 'Numero di serie obiettivo', + 'LensShutterLock' => { + PrintConv => { + 'Off' => 'Spento', + }, + }, + 'LensSpec' => 'Obiettivo', + 'LensType' => { + Description => 'Tipo obiettivo', + PrintConv => { + '02 Standard Zoom 5-15mm F2.8-4.5' => '02 Zoom standard 5-15mm F2.8-4.5', + '04 Toy Lens Wide 6.3mm F7.1' => '04 Grandangolare toy 6.3mm F7.1', + '05 Toy Lens Telephoto 18mm F8' => '05 Teleobiettivo toy 18mm F8', + '1.4x Teleconverter' => 'Moltiplicatore di focale 1.4x', + 'None' => 'Nessuno', + 'Sigma 100-300mm F4 EX (APO (D) or D IF)' => 'Sigma 100-300mm F4 EX (APO (D) o D IF)', + }, + }, + 'LevelGaugePitch' => { + PrintConv => { + 'Off' => 'Spento', + }, + }, + 'LevelGaugeRoll' => { + PrintConv => { + 'Off' => 'Spento', + }, + }, + 'LevelOrientation' => { + PrintConv => { + 'Horizontal (normal)' => 'Orizzontale', + 'Rotate 180' => 'Ruota di 180°', + 'Rotate 270 CW' => 'Ruota di 270° in senso orario', + 'Rotate 90 CW' => 'Ruota di 90° senso orario', + }, + }, + 'License' => 'Licenza', + 'LicenseID' => 'ID licenza', + 'LicenseType' => { + PrintConv => { + 'Public Domain' => 'Pubblico dominio', + 'Unknown' => 'Sconosciuto', + }, + }, + 'LightCondition' => 'Condizione luce', + 'LightSource' => { + Description => 'Sorgente di luce', + PrintConv => { + 'Cloudy' => 'Nuvoloso', + 'Cool White Fluorescent' => 'Fluorescente a luce calda', + 'Day White Fluorescent' => 'Fluorescente a luce del giorno bianca', + 'Daylight' => 'Luce del giorno', + 'Daylight Fluorescent' => 'Fluorescente a luce del giorno', + 'Evening Sunlight' => 'Luce solare serale', + 'Fine Weather' => 'Bel tempo', + 'Fluorescent' => 'Fluorescente', + 'ISO Studio Tungsten' => 'Tungsteno studio ISO', + 'Other' => 'Altra Sorgente di Luce', + 'Shade' => 'Ombrato', + 'Standard Light A' => 'Luce standard A', + 'Standard Light B' => 'Luce standard B', + 'Standard Light C' => 'Luce standard C', + 'Tungsten (Incandescent)' => 'Tungsteno (luce incandescente)', + 'Unknown' => 'Sconosciuto', + 'Warm White Fluorescent' => 'Luce fluorescente bianca calda', + 'White Fluorescent' => 'Fluorescente bianca', + }, + }, + 'LightSourceSpecial' => { + PrintConv => { + 'Off' => 'Spento', + }, + }, + 'LightingMode' => { + PrintConv => { + 'Off' => 'Spento', + }, + }, + 'Lightness' => 'Luce', + 'Line' => 'Linea', + 'LineOrder' => { + PrintConv => { + 'Random Y' => 'Casuale Y', + }, + }, + 'LinearResponseLimit' => 'Limite risposta lineare', + 'LinearizationTable' => 'Tabella di linearizzazione', + 'Lines' => 'Linee', + 'LinkAEToAFPoint' => { + PrintConv => { + 'Off' => 'Spento', + }, + }, + 'LinkerVersion' => 'Versione linker', + 'Lit' => { + PrintConv => { + 'Yes' => 'Sì', + }, + }, + 'LiveViewAFMethod' => { + PrintConv => { + 'n/a' => 'n/d', + }, + }, + 'LiveViewAFSetting' => { + PrintConv => { + 'n/a' => 'n/d', + }, + }, + 'LiveViewFocusMode' => { + PrintConv => { + 'Manual' => 'Manuale', + 'n/a' => 'n/d', + }, + }, + 'LiveViewMetering' => { + PrintConv => { + 'n/a' => 'n/d', + }, + }, + 'LiveViewShooting' => { + PrintConv => { + 'Off' => 'Spento', + }, + }, + 'LocalDeltaType' => { + PrintConv => { + 'Absolute' => 'Assoluto', + }, + }, + 'LocalizedCameraModel' => 'Modello fotocamera localizzato', + 'Location' => 'Località', + 'LocationKind' => 'Tipo località', + 'LocationName' => 'Nome località', + 'LocationNote' => 'Note località', + 'LongDescription' => 'Descrizione estesa', + 'LongExposureNoiseReduction' => { + Description => 'Espososizione lunga riduzione rumore', + PrintConv => { + 'Off' => 'Spento', + 'Off (65535)' => 'Spento (65535)', + 'On' => 'Attivata', + 'n/a' => 'n/d', + }, + }, + 'LongExposureNoiseReduction2' => { + Description => 'Espososizione lunga riduzione rumore 2', + PrintConv => { + 'Off' => 'Spento', + }, + }, + 'LongText' => 'Testo lungo', + 'LoopStyle' => { + PrintConv => { + 'Normal' => 'Normale', + }, + }, + 'LuminanceNoiseReduction' => { + PrintConv => { + 'Low' => 'Basso', + 'Off' => 'Spento', + }, + }, + 'Lyricist' => 'Paroliere', + 'Lyrics' => 'Testo', + 'MCUVersion' => 'Versione MCU', + 'MDColorTable' => 'Tabella colori MD', + 'MDFileTag' => 'Tag file MD', + 'MDFileUnits' => 'Unità file MD', + 'MDLabName' => 'Nome lab MD', + 'MDPrepDate' => 'Data prep MD', + 'MDPrepTime' => 'Ora prep MD', + 'MDSampleInfo' => 'Info campione MD', + 'MDScalePixel' => 'Scala pixel MD', + 'MIEVersion' => 'Versione MIE', + 'MIMEType' => 'Tipo mime', + 'MIMETypeOfEncapsulatedDocument' => 'Tipo mime del documento incapsulato', + 'MSDocumentText' => 'Testo documento MS', + 'MSDocumentTextPosition' => 'Posizione testo documento MS', + 'MSPropertySetStorage' => 'Gruppo di memoria proprietà MS', + 'MSStereo' => { + PrintConv => { + 'Off' => 'Spento', + }, + }, + 'MachineType' => { + Description => 'Tipo macchina', + PrintConv => { + 'ARM little endian' => 'ARM little-endian', + 'Alpha AXP (old)' => 'Alpha AXP (precedente)', + 'EFI Byte Code' => 'Byte code EFI', + 'Intel 386 or later, and compatibles' => 'Intel 386 o successivo e compatibili', + 'MIPS little endian (R4000)' => 'MIPS little-endian (R4000)', + 'MIPS little endian WCI v2' => 'MIPS little-endian WCI v2', + 'MIPS with FPU' => 'MIPS con FPU', + 'MIPS16 with FPU' => 'MIPS16 con FPU', + 'Mitsubishi M32R little endian' => 'Mitsubishi M32R little-endian', + 'Motorola 68000 series' => 'Serie Motorola 68000', + 'PowerPC little endian' => 'PowerPC little-endian', + 'PowerPC with floating point support' => 'PowerPC con supporto numeri in in virgola mobile', + 'clr pure MSIL' => 'clr con MSIL puro', + }, + }, + 'Macro' => { + PrintConv => { + 'Manual' => 'Manuale', + 'Normal' => 'Normale', + 'Off' => 'Spento', + 'n/a' => 'n/d', + }, + }, + 'MacroLED' => { + PrintConv => { + 'Off' => 'Spento', + }, + }, + 'MacroMode' => { + PrintConv => { + 'Normal' => 'Normale', + 'Off' => 'Spento', + }, + }, + 'MagicFilter' => { + PrintConv => { + 'Fish Eye' => 'Fish-eye', + 'Fragmented' => 'Frammentato', + 'Gentle Sepia' => 'Seppia leggero', + 'Off' => 'Spento', + 'Reflection' => 'Riflessione', + }, + }, + 'MainDialExposureComp' => { + PrintConv => { + 'Off' => 'Spento', + }, + }, + 'Make' => 'Costruttore', + 'MakeAndModel' => 'Marca e Modello', + 'MakerNote' => 'Dati DNG Privati', + 'MakerNoteCanon' => 'Note marca Canon', + 'MakerNoteCasio' => 'Note marca Casio', + 'MakerNoteCasio2' => 'Note marca Casio 2', + 'MakerNoteFujiFilm' => 'Note marca Fuji Film', + 'MakerNoteGE' => 'Note marca GE', + 'MakerNoteGE2' => 'Note marca GE2', + 'MakerNoteHP' => 'Note marca HP', + 'MakerNoteHP2' => 'Note marca HP2', + 'MakerNoteHP4' => 'Note marca HP4', + 'MakerNoteHP6' => 'Note marca HP6', + 'MakerNoteHasselblad' => 'Note marca Hasselblad', + 'MakerNoteISL' => 'Note marca ISL', + 'MakerNoteJVC' => 'Note marca JVC', + 'MakerNoteJVCText' => 'Note marca JVC - Testo', + 'MakerNoteKodak10' => 'Note marca Kodak 10', + 'MakerNoteKodak1a' => 'Note marca Kodak 1a', + 'MakerNoteKodak1b' => 'Note marca Kodak 1b', + 'MakerNoteKodak2' => 'Note marca Kodak 2', + 'MakerNoteKodak3' => 'Note marca Kodak 3', + 'MakerNoteKodak4' => 'Note marca Kodak 4', + 'MakerNoteKodak5' => 'Note marca Kodak 5', + 'MakerNoteKodak6a' => 'Note marca Kodak 6a', + 'MakerNoteKodak6b' => 'Note marca Kodak 6b', + 'MakerNoteKodak7' => 'Note marca Kodak 7', + 'MakerNoteKodak8a' => 'Note marca Kodak 8a', + 'MakerNoteKodak8b' => 'Note marca Kodak 8b', + 'MakerNoteKodak9' => 'Note marca Kodak 9', + 'MakerNoteKodakUnknown' => 'Note marca Kodak sconosciuta', + 'MakerNoteKyocera' => 'Note marca Kyocera', + 'MakerNoteLeica' => 'Note marca Leica', + 'MakerNoteLeica2' => 'Note marca Leica 2', + 'MakerNoteLeica3' => 'Note marca Leica 3', + 'MakerNoteLeica4' => 'Note marca Leica 4', + 'MakerNoteLeica5' => 'Note marca Leica 5', + 'MakerNoteLeica6' => 'Note marca Leica 6', + 'MakerNoteMinolta' => 'Note marca Minolta', + 'MakerNoteMinolta2' => 'Note marca Minolta 2', + 'MakerNoteMinolta3' => 'Note marca Minolta 3', + 'MakerNoteNikon' => 'Note marca Nikon', + 'MakerNoteNikon2' => 'Note marca Nikon 2', + 'MakerNoteNikon3' => 'Note marca Nikon 3', + 'MakerNoteOlympus' => 'Note marca Olympus', + 'MakerNoteOlympus2' => 'Note marca Olympus 2', + 'MakerNotePanasonic' => 'Note marca Panasonic', + 'MakerNotePanasonic2' => 'Note marca Panasonic 2', + 'MakerNotePentax' => 'Note marca Pentax', + 'MakerNotePentax2' => 'Note marca Pentax 2', + 'MakerNotePentax3' => 'Note marca Pentax 3', + 'MakerNotePentax4' => 'Note marca Pentax 4', + 'MakerNotePentax5' => 'Note marca Pentax 5', + 'MakerNotePentax6' => 'Note marca Pentax 6', + 'MakerNotePhaseOne' => 'Note marca Phase One', + 'MakerNoteReconyx' => 'Note marca Reconyx', + 'MakerNoteRicoh' => 'Note marca Ricoh', + 'MakerNoteRicohText' => 'Note marca Ricoh - Testo', + 'MakerNoteSafety' => { + Description => 'Note marca Safety', + PrintConv => { + 'Safe' => 'Sicuro', + 'Unsafe' => 'Non sicuro', + }, + }, + 'MakerNoteSamsung1a' => 'Note marca Samsung 1a', + 'MakerNoteSamsung1b' => 'Note marca Samsung 1b', + 'MakerNoteSamsung2' => 'Note marca Samsung 2', + 'MakerNoteSanyo' => 'Note marca Sanyo', + 'MakerNoteSanyoC4' => 'Note marca Sanyo C4', + 'MakerNoteSanyoPatch' => 'Note marca Sanyo Patch', + 'MakerNoteSigma' => 'Note marca Sigma', + 'MakerNoteSony' => 'Note marca Sony', + 'MakerNoteSony2' => 'Note marca Sony 2', + 'MakerNoteSony3' => 'Note marca Sony 3', + 'MakerNoteSony4' => 'Note marca Sony 4', + 'MakerNoteSonyEricsson' => 'Note marca Sony Ericsson', + 'MakerNoteSonySRF' => 'Note marca Sony SRF', + 'MakerNoteUnknown' => 'Note marca sconosciuta', + 'MakerNoteUnknownText' => 'Note marca sconosciuta - Testo', + 'MakerNoteVersion' => 'Note Versione Costruttore', + 'MakerNotes' => 'Note produttore', + 'ManualFlashOutput' => { + PrintConv => { + 'Low' => 'Basso', + 'n/a' => 'n/d', + }, + }, + 'ManualFocusDistance' => 'Messa a Fuoco Manuale', + 'MarkerID' => 'ID marker', + 'MaskedAreas' => 'Aree mascherate', + 'MasterDocumentID' => 'ID Documento Principale', + 'Matteing' => 'Opacizzazione', + 'MaxAperture' => 'Massima apertura delle lenti', + 'MaxApertureAtMaxFocal' => 'Diaframma massimo alla focale massima', + 'MaxApertureAtMinFocal' => 'Diaframma massimo alla focale minima', + 'MaxApertureValue' => 'Diaframma massimo obiettivo', + 'MaxFocalLength' => 'Lunghezza focale massima', + 'MaxSampleValue' => 'Massimo valore campioni', + 'MeasurementGeometry' => { + PrintConv => { + '0/45 or 45/0' => '0/45 o 45/0', + '0/d or d/0' => '0/d o d/0', + }, + }, + 'MediaBlackPoint' => 'Media Punto Nero', + 'MediaType' => { + PrintConv => { + 'Normal (Music)' => 'Normale (musica)', + }, + }, + 'MediaWhitePoint' => 'Media Punto Bianco', + 'MenuButtonDisplayPosition' => { + PrintConv => { + 'Top' => 'Alto', + }, + }, + 'MenuButtonReturn' => { + PrintConv => { + 'Top' => 'Alto', + }, + }, + 'MeteringMode' => { + Description => 'Modalità misurazione', + PrintConv => { + 'Average' => 'Media', + 'Center-weighted Average' => 'Media centrale ponderata', + 'Center-weighted average' => 'Media centrale ponderata', + 'Multi-segment' => 'Multi-zona', + 'Multi-spot' => 'Multi-punto', + 'Other' => 'Altro', + 'Partial' => 'Parziale', + 'Spot' => 'Punto', + 'Unknown' => 'Sconosciuto', + }, + }, + 'MeteringMode2' => { + PrintConv => { + 'Center-weighted average' => 'Media centrale ponderata', + 'Multi-segment' => 'Multi zona', + }, + }, + 'MeteringMode3' => { + PrintConv => { + 'Center-weighted average' => 'Media centrale ponderata', + 'Multi-segment' => 'Multi zona', + }, + }, + 'MeteringTime' => { + PrintConv => { + 'No Limit' => 'Nessun limite', + }, + }, + 'MinFocalLength' => 'Lunghezza focale minima', + 'MinSampleValue' => 'Minimo valore campioni', + 'MiniatureFilterOrientation' => { + PrintConv => { + 'Horizontal' => 'Orizzontale', + 'Vertical' => 'Verticale', + }, + }, + 'MinoltaQuality' => { + Description => 'Qualità', + PrintConv => { + 'Normal' => 'Normale', + }, + }, + 'MirrorLockup' => { + PrintConv => { + 'Enable' => 'Abilita', + }, + }, + 'ModeNumber' => 'Numero modo', + 'Model' => 'Nome modello fotocamera', + 'Model2' => 'Modello 2', + 'ModelReleaseStatus' => { + PrintConv => { + 'None' => 'Nessuno', + 'Not Applicable' => 'Non applicabile', + }, + }, + 'ModelingFlash' => { + PrintConv => { + 'Off' => 'Spento', + }, + }, + 'ModifiedPictureStyle' => { + PrintConv => { + 'Landscape' => 'Orizzontale', + 'None' => 'Nessuno', + 'Portrait' => 'Verticale', + }, + }, + 'ModifiedSaturation' => { + PrintConv => { + 'Off' => 'Spento', + }, + }, + 'ModifiedSharpnessFreq' => { + PrintConv => { + 'Low' => 'Basso', + 'n/a' => 'n/d', + }, + }, + 'ModifiedToneCurve' => { + PrintConv => { + 'Manual' => 'Manuale', + }, + }, + 'ModifiedWhiteBalance' => { + PrintConv => { + 'Cloudy' => 'Nuvoloso', + 'Daylight' => 'Luce del giorno', + 'Daylight Fluorescent' => 'Fluorescente a luce del giorno', + 'Fluorescent' => 'Fluorescente', + 'Shade' => 'Ombrato', + 'Tungsten' => 'Tungsteno (luce incandescente)', + }, + }, + 'ModifyDate' => 'Data modifica', + 'MoireFilter' => { + Description => 'Filtro moire', + PrintConv => { + 'Off' => 'Spento', + }, + }, + 'MonitorDisplayOff' => { + PrintConv => { + 'Manual' => 'Manuale', + }, + }, + 'MonochromeFilterEffect' => { + PrintConv => { + 'Green' => 'Verde', + 'None' => 'Nessuno', + 'Orange' => 'Arancio', + 'Red' => 'Rosso', + 'Yellow' => 'Giallo', + }, + }, + 'MonochromeLinear' => { + PrintConv => { + 'Yes' => 'Sì', + }, + }, + 'MonochromeToning' => { + PrintConv => { + 'None' => 'Nessuno', + }, + }, + 'MonochromeToningEffect' => { + PrintConv => { + 'Green' => 'Verde', + 'None' => 'Nessuno', + 'Purple' => 'Porpora', + 'Sepia' => 'Seppia', + }, + }, + 'MultiBurstMode' => { + PrintConv => { + 'Off' => 'Spento', + }, + }, + 'MultiControllerWhileMetering' => { + PrintConv => { + 'Off' => 'Spento', + }, + }, + 'MultiExposure' => 'Dati Esposizione Multipla', + 'MultiExposureAutoGain' => { + Description => 'Guadagno Automatico Esposizione Multipla', + PrintConv => { + 'Off' => 'Spento', + }, + }, + 'MultiExposureMode' => { + Description => 'Modo Esposizione Multipla', + PrintConv => { + 'Off' => 'Spento', + }, + }, + 'MultiExposureShots' => 'Scatti Esposizione Multipla', + 'MultiExposureVersion' => 'Versione Dati Esposizione Multipla', + 'MultiFrameNoiseReduction' => { + Description => 'Riduz. distur. su più fotogr.', + PrintConv => { + 'None' => 'Nessuno', + 'Off' => 'Spento', + 'On' => 'Attivata', + 'n/a' => 'n/d', + }, + }, + 'MultiFunctionLock' => { + PrintConv => { + 'Off' => 'Spento', + }, + }, + 'MultiProfiles' => { + Description => 'Profili multipli', + PrintConv => { + 'JBIG2 Profile M' => 'JBIG2 TIFF FX', + 'N Layer Profile M' => 'Livello N profilo M', + 'Profile C' => 'Profilo C', + 'Profile F' => 'Profilo F', + 'Profile J' => 'Profilo J', + 'Profile L' => 'Profilo L', + 'Profile M' => 'Profilo M', + 'Profile S' => 'Profilo S', + 'Profile T' => 'Profilo T', + 'Resolution/Image Width' => 'Risoluzione/larghezza immagine', + 'Shared Data' => 'Dati condivisi', + }, + }, + 'MultiSelectorLiveView' => { + PrintConv => { + 'Not Used' => 'Non usato', + 'Reset' => 'Reimposta', + 'Zoom On/Off' => 'Zoon sì/no', + }, + }, + 'MultiSelectorPlaybackMode' => { + PrintConv => { + 'Choose Folder' => 'Seleziona cartella', + 'Thumbnail On/Off' => 'Thumbnail sì/no', + 'Zoom On/Off' => 'Zoon sì/no', + }, + }, + 'MultiSelectorShootMode' => { + PrintConv => { + 'Not Used' => 'Non usato', + }, + }, + 'MultipleExposureMode' => { + PrintConv => { + 'Off' => 'Spento', + }, + }, + 'MultipleExposureSet' => { + PrintConv => { + 'Off' => 'Spento', + }, + }, + 'MusicCDIdentifier' => 'Identificativo CD musicale', + 'MusicianCredits' => 'Info sul musicista', + 'Mute' => { + PrintConv => { + 'Off' => 'Spento', + }, + }, + 'MyColorMode' => { + PrintConv => { + 'Off' => 'Spento', + 'Sepia' => 'Seppia', + 'Vivid' => 'Vivace', + 'Vivid Blue' => 'Blu vivace', + 'Vivid Green' => 'Verde vivace', + }, + }, + 'NDFilter' => { + PrintConv => { + 'Off' => 'Spento', + 'n/a' => 'n/d', + }, + }, + 'NEFCompression' => { + Description => 'Compressione RAW', + PrintConv => { + 'Lossless' => 'Senza perdita', + 'Uncompressed' => 'Non compresso', + }, + }, + 'Name' => 'Nome', + 'NamedColor2' => 'Colore Chiamato 2', + 'NativeDisplayInfo' => 'Info Display Nativo', + 'NeutralDensityFilter' => { + PrintConv => { + 'Off' => 'Spento', + }, + }, + 'NikonCaptureData' => 'Dati Nikon Capture', + 'NikonCaptureVersion' => 'Versione Nikon Capture', + 'NoMemoryCard' => 'Scheda di memoria assente', + 'Noise' => 'Rumore', + 'NoiseFilter' => { + Description => 'Filtro rumore', + PrintConv => { + 'Low' => 'Basso', + 'Off' => 'Spento', + 'n/a' => 'n/d', + }, + }, + 'NoiseProfile' => 'Profilo rumore', + 'NoiseReduction' => { + Description => 'Riduzione rumore', + PrintConv => { + 'Low' => 'Basso', + 'Low (-1)' => 'Basso (-1)', + 'Noise Filter' => 'Filtro rumore', + 'Noise Reduction' => 'Riduzione rumore', + 'Normal' => 'Normale', + 'Off' => 'Spento', + 'Strong' => 'Forte', + 'n/a' => 'n/d', + }, + }, + 'NoiseReduction2' => { + Description => 'Riduzione rumore 2', + PrintConv => { + 'Noise Filter' => 'Filtro rumore', + 'Noise Reduction' => 'Riduzione rumore', + }, + }, + 'NoiseReductionApplied' => 'Riduzione rumore applicata', + 'NoiseReductionIntensity' => 'Intensità riduzione rumore', + 'NoiseReductionMethod' => { + Description => 'Metodo riduzione rumore', + PrintConv => { + 'Faster' => 'Più veloce', + }, + }, + 'NoiseReductionMode' => { + Description => 'Modo riduzione rumore', + PrintConv => { + 'Off' => 'Spento', + }, + }, + 'NoiseReductionValue' => 'Valore riduzione rumore', + 'Notes' => 'Note', + 'Now' => 'Adesso', + 'NumChannels' => 'Numero canali', + 'NumSampleFrames' => 'Numero fotogrammi campionamento', + 'NumberOfFocusPoints' => { + PrintConv => { + '11 Points' => '11 punti', + }, + }, + 'NumberofInks' => 'Numero di inchiostri', + 'OKButton' => { + PrintConv => { + 'Not Used' => 'Non usato', + 'Off' => 'Spento', + }, + }, + 'OPIProxy' => { + Description => 'Proxy OPI', + PrintConv => { + 'Higher resolution image does not exist' => 'Immagine a risoluzione maggiore non esistente', + 'Higher resolution image exists' => 'Immagine a risoluzione maggiore esistente', + }, + }, + 'OSVersion' => 'Versione OS', + 'Object' => 'Oggetto', + 'ObjectAttributeReference' => 'Genere intellettuale', + 'ObjectCycle' => { + Description => 'Ciclo oggetto', + PrintConv => { + 'Both Morning and Evening' => 'Entrambi', + 'Evening' => 'Sera', + 'Morning' => 'Mattino', + }, + }, + 'ObjectFileType' => { + Description => 'Tipo file oggetto', + PrintConv => { + 'Core file' => 'File core', + 'Demand paged executable' => 'Eseguibile paginato a richiesta', + 'Dynamic link editor' => 'Editor con collegamenti dinamici', + 'Dynamic link library' => 'Libreria a collegamento dinamico', + 'Dynamically bound bundle' => 'Pacchetto incorporato dinamicamente', + 'Dynamically bound shared library' => 'Libreria condivisa collegata dinamicamente', + 'Executable application' => 'Applicazione eseguibile', + 'Executable file' => 'File eseguibile', + 'Fixed VM shared library' => 'Libreria fissa VM condivisa', + 'Font' => 'Carattere', + 'None' => 'Nessuno', + 'Preloaded executable' => 'Eseguibile precaricato', + 'Relocatable file' => 'File rilocabile', + 'Relocatable object' => 'Oggetto rilocabile', + 'Shared library stub for static linking' => 'Stub libreria condivisa per il collegamenti statici', + 'Shared object file' => 'File con oggetti condivisi', + 'Static library' => 'Libreria statica', + 'Unknown' => 'Sconosciuto', + }, + }, + 'ObjectName' => 'Titolo', + 'ObjectPreviewFileFormat' => { + PrintConv => { + 'Ritzaus Bureau NITF version (RBNITF DTD)' => 'Versione Ritzaus Bureau NITF (RBNITF DTD)', + }, + }, + 'ObjectTypeReference' => 'Riferimento Tipo Oggetto', + 'OldSubfileType' => { + Description => 'Vecchio tipo sotto-file', + PrintConv => { + 'Full-resolution image' => 'Immagine con risoluzione originale', + 'Reduced-resolution image' => 'Immagine a risoluzione ridotta', + 'Single page of multi-page image' => 'Singola pagina di un\'immagine multi-pagina', + }, + }, + 'OneTouchWB' => { + PrintConv => { + 'Off' => 'Spento', + }, + }, + 'OpEndPic' => 'Fine immagine', + 'OpcodeList1' => 'Lista opcode 1', + 'OpcodeList2' => 'Lista opcode 2', + 'OpcodeList3' => 'Lista opcode 3', + 'OpticalZoomMode' => { + PrintConv => { + 'Extended' => 'Esteso', + }, + }, + 'OpticalZoomOn' => { + PrintConv => { + 'Off' => 'Spento', + }, + }, + 'Opto-ElectricConvFactor' => 'Fattore di conversione optoelettrica', + 'Orientation' => { + Description => 'Orientamento', + PrintConv => { + 'Horizontal (normal)' => 'Orizzontale (normale)', + 'Mirror horizontal' => 'Rifletti orizzontalmente', + 'Mirror horizontal and rotate 270 CW' => 'Rifletti orizzontalmente e ruota di 270° in senso orario', + 'Mirror horizontal and rotate 90 CW' => 'Rifletti orizzontalmente e ruota di 90° in senso orario', + 'Mirror vertical' => 'Rifletti verticalmente', + 'Rotate 180' => 'Ruota di 180°', + 'Rotate 270 CW' => 'Ruota di 270° in senso orario', + 'Rotate 90 CW' => 'Ruota di 90° senso orario', + 'Tiled' => 'Tassellato', + }, + }, + 'Origin' => 'Origine', + 'OriginCode' => 'Codice origine', + 'OriginPlatform' => { + Description => 'Piattaforma origine', + PrintConv => { + 'Print' => 'Stampa', + }, + }, + 'OriginalAlbum' => 'Album originale', + 'OriginalAlbumTitle' => 'Titolo album originale', + 'OriginalArtist' => 'Artista originale', + 'OriginalFileName' => 'Nome file originale', + 'OriginalLyricist' => 'Paroliere originale', + 'OriginalMedia' => { + PrintConv => { + 'False' => 'Falso', + }, + }, + 'OriginalRawFileData' => 'Dati file raw originale', + 'OriginalRawFileDigest' => 'Sommario file raw originale', + 'OriginalRawFileName' => 'Nome file raw originale', + 'OriginalReleaseTime' => 'Ora di rilascio originale', + 'OriginalReleaseYear' => 'Anno di rilascio originale', + 'OriginalTransmissionReference' => 'ID Lavoro', + 'OriginatingProgram' => 'Programma d\'origine', + 'OtherCodecDescription' => 'Descrizione altro codec', + 'OtherCodecName' => 'Nome altro codec', + 'OtherImageLength' => 'Altra lunghezza immagine', + 'OtherImageStart' => 'Altro inizio immagine', + 'OwnerID' => 'ID proprietario', + 'OwnerName' => 'Nome proprietario', + 'PEFVersion' => 'Versione PEF', + 'PEType' => 'Tipo PE', + 'PackingMethod' => { + PrintConv => { + 'Fast' => 'Veloce', + 'Fastest' => 'Massimamente veloce', + 'Normal' => 'Normale', + }, + }, + 'PageName' => 'Nome pagina', + 'PageNumber' => 'Numero pagina', + 'PanOrientation' => { + PrintConv => { + '[unused]' => '[non usato]', + }, + }, + 'PanasonicRawVersion' => 'Versione raw Panasonic', + 'PanasonicTitle' => 'Titolo Panasonic', + 'PanasonicTitle2' => 'Titolo Panasonic 2', + 'PanoramaSize3D' => { + Description => 'Dimensione panomara 3D', + PrintConv => { + 'Wide' => 'Ampio', + 'n/a' => 'n/d', + }, + }, + 'PartOfSet' => 'Parte del gruppo', + 'PaymentURL' => 'URL pagamento', + 'PeakValue' => 'Valore di picco', + 'PerformerSortOrder' => 'Ordinamento interprete', + 'PeripheralLighting' => { + PrintConv => { + 'Off' => 'Spento', + }, + }, + 'PeripheralLightingSetting' => { + PrintConv => { + 'Off' => 'Spento', + }, + }, + 'PhaseDetectAF' => { + PrintConv => { + 'Off' => 'Spento', + }, + }, + 'PhotoEffect' => { + PrintConv => { + 'Off' => 'Spento', + 'Sepia' => 'Seppia', + 'Vivid' => 'Vivace', + }, + }, + 'PhotoEffects' => { + PrintConv => { + 'Off' => 'Spento', + }, + }, + 'PhotoEffectsType' => { + PrintConv => { + 'None' => 'Nessuno', + 'Sepia' => 'Seppia', + 'Tinted' => 'Tinteggiato', + }, + }, + 'PhotoInfoPlayback' => { + PrintConv => { + 'Off' => 'Spento', + }, + }, + 'PhotometricInterpretation' => { + Description => 'Interpretazione fotometrica', + PrintConv => { + 'BlackIsZero' => 'Nero è zero', + 'Color Filter Array' => 'Array filtro colore', + 'Linear Raw' => 'Raw lineare', + 'Pixar LogL' => 'Pixar LogLuv', + 'Pixar LogLuv' => 'Pixar LogL', + 'RGB Palette' => 'Tavolozza RGB', + 'Transparency Mask' => 'Maschera trasparenza', + 'WhiteIsZero' => 'Bianco è zero', + }, + }, + 'PhotoshopFormat' => { + PrintConv => { + 'Progressive' => 'Progressivo', + }, + }, + 'Picture' => 'Immagine', + 'PictureControl' => { + PrintConv => { + 'Off' => 'Spento', + }, + }, + 'PictureControlActive' => { + PrintConv => { + 'Off' => 'Spento', + }, + }, + 'PictureControlAdjust' => { + PrintConv => { + 'Default Settings' => 'Impostazioni Predefinite', + 'Full Control' => 'Controllo completo', + 'Quick Adjust' => 'Regolazione rapida', + }, + }, + 'PictureDescription' => 'Descrizione immagine', + 'PictureEffect' => { + PrintConv => { + 'Off' => 'Spento', + 'Posterization' => 'Posterizzazione', + 'Posterization B/W' => 'Posterizzazione B&N', + 'Retro Photo' => 'Foto retrò', + }, + }, + 'PictureFinish' => { + PrintConv => { + 'Evening Scene' => 'Scena serale', + 'Portrait' => 'Verticale', + }, + }, + 'PictureFormat' => 'Formato immagine', + 'PictureMIMEType' => 'MIME type immagine', + 'PictureMode' => { + PrintConv => { + '1/2 EV steps' => 'Step 1/2 EV', + '1/3 EV steps' => 'Step 1/3 EV', + 'Aperture-priority AE' => 'Priorità diaframma', + 'Fireworks' => 'Fuochi artificiali', + 'Fisheye' => 'Fish-eye', + 'Flower' => 'Fiore', + 'Forest' => 'Foresta', + 'Green' => 'Verde', + 'Kids' => 'Bambini', + 'Landscape' => 'Orizzontale', + 'Manual' => 'Manuale', + 'No Flash' => 'No flash', + 'Portrait' => 'Verticale', + 'Program' => 'Programma', + 'Program (HyP)' => 'Programma (HyP)', + 'Program AE' => 'Programma AE', + 'Purple' => 'Porpora', + 'Quick Macro' => 'Macro veloce', + 'Red' => 'Rosso', + 'Sepia' => 'Seppia', + 'Shutter speed priority AE' => 'Priorità otturatore AE', + 'Sunset' => 'Tramonto', + 'Text' => 'Testo', + 'Vivid' => 'Vivace', + }, + }, + 'PictureMode2' => { + PrintConv => { + 'Aperture Priority' => 'Priorità diaframma', + 'Manual' => 'Manuale', + 'Program AE' => 'Programma AE', + 'Scene Mode' => 'Modo scena', + 'Shutter Speed Priority' => 'Priorità otturatore', + }, + }, + 'PictureModeBWFilter' => { + PrintConv => { + 'Green' => 'Verde', + 'Orange' => 'Arancio', + 'Red' => 'Rosso', + 'Yellow' => 'Giallo', + 'n/a' => 'n/d', + }, + }, + 'PictureModeEffect' => { + PrintConv => { + 'Low' => 'Basso', + 'n/a' => 'n/d', + }, + }, + 'PictureModeTone' => { + PrintConv => { + 'Green' => 'Verde', + 'Purple' => 'Porpora', + 'Sepia' => 'Seppia', + 'n/a' => 'n/d', + }, + }, + 'PictureStyle' => { + PrintConv => { + 'Landscape' => 'Orizzontale', + 'None' => 'Nessuno', + 'Portrait' => 'Verticale', + }, + }, + 'PictureType' => { + Description => 'Tipo immagine', + PrintConv => { + '32x32 PNG Icon' => 'Icona PNG 32x32', + 'Artist' => 'Artista', + 'Back Cover' => 'Retrocopertina', + 'Band Logo' => 'Logo band', + 'Bright(ly) Colored Fish' => 'Pesci dai vivaci colori', + 'Capture from Movie or Video' => 'Acquisizione da film o video', + 'Composer' => 'Compositore', + 'Conductor' => 'Direttore d\'orchestra', + 'Front Cover' => 'Copertina', + 'Illustration' => 'Illustrazione', + 'Lead Artist' => 'Artista principale', + 'Leaflet' => 'Volantino', + 'Lyricist' => 'Paroliere', + 'Other' => 'Altro', + 'Other Icon' => 'Altra icona', + 'Performance' => 'Interpretazione', + 'Publisher Logo' => 'Logo editore', + 'Recording Session' => 'Sessione registrazione', + 'Recording Studio or Location' => 'Studio/luogo registrazione', + }, + }, + 'PictureWizardMode' => { + PrintConv => { + 'Forest' => 'Foresta', + 'Landscape' => 'Orizzontale', + 'Retro' => 'Retrò', + 'Vivid' => 'Vivace', + 'n/a' => 'n/d', + }, + }, + 'PixelFormat' => { + Description => 'Formato pixel', + PrintConv => { + '112-bit 6 Channels Alpha' => '112-bit 6 canali trasparenza', + '112-bit 7 Channels' => '112-bit 7 canali', + '128-bit 7 Channels Alpha' => '128-bit 7 canali trasparenza', + '128-bit 8 Channels' => '128-bit 8 canali', + '128-bit PRGBA Float' => '128-bit PRGBA virgola mobile', + '128-bit RGB Float' => '128-bit RGB virgola mobile', + '128-bit RGBA Fixed Point' => '128-bit RGBA virgola fissa', + '128-bit RGBA Float' => '128-bit RGBA virgola mobile', + '144-bit 8 Channels Alpha' => '144-bit 8 canali trasparenza', + '16-bit Gray' => '16-bit grigio', + '16-bit Gray Half' => '16-bit grigio metà', + '24-bit 3 Channels' => '24-bit 3 canali', + '32-bit 3 Channels Alpha' => '32-bit 3 canali trasparenza', + '32-bit 4 Channels' => '32-bit 4 canali', + '32-bit Gray Fixed Point' => '32-bit punto grigio virgola fissa', + '32-bit Gray Float' => '32-bit punto grigio virgola mobile', + '40-bit 4 Channels Alpha' => '40-bit 4 canali trasparenza', + '40-bit 5 Channels' => '40-bit 5 canali', + '40-bit CMYK Alpha' => '40-bit CMYK trasparenza', + '48-bit 3 Channels' => '48-bit 3 canali', + '48-bit 5 Channels Alpha' => '48-bit 5 canali trasparenza', + '48-bit 6 Channels' => '48-bit 6 canali', + '48-bit RGB Fixed Point' => '48-bit RGB virgola fissa', + '48-bit RGB Half' => '48-bit RGB metà', + '56-bit 6 Channels Alpha' => '56-bit 6 canali trasparenza', + '56-bit 7 Channels' => '56-bit 7 canali', + '64-bit 3 Channels Alpha' => '64-bit 3 canali trasparenza', + '64-bit 4 Channels' => '64-bit 4 canali', + '64-bit 7 Channels Alpha' => '64-bit 7 canali trasparenza', + '64-bit 8 Channels' => '64-bit 8 canali', + '64-bit RGBA Fixed Point' => '64-bit RGBA virgola fissa', + '64-bit RGBA Half' => '64-bit RGBA mezzi toni', + '72-bit 8 Channels Alpha' => '72-bit 8 canali trasparenza', + '8-bit Gray' => '8-bit grigio', + '80-bit 4 Channels Alpha' => '80-bit 4 canali trasparenza', + '80-bit 5 Channels' => '80-bit 5 canali', + '80-bit CMYK Alpha' => '80-bit CMYK trasparenza', + '96-bit 5 Channels Alpha' => '96-bit 5 canali trasparenza', + '96-bit 6 Channels' => '96-bit 6 canali', + '96-bit RGB Fixed Point' => '96-bit RGB virgola fissa', + 'Black & White' => 'Bianco e nero', + }, + }, + 'PixelIntensityRange' => 'Intervallo intensità pixel', + 'PixelMagicJBIGOptions' => 'Opzioni Pixel Magic JBIG', + 'PixelScale' => 'Scala pixel', + 'PixelUnits' => { + PrintConv => { + 'Unknown' => 'Sconosciuto', + }, + }, + 'PlanarConfiguration' => { + Description => 'Configurazione planare', + PrintConv => { + 'Chunky' => 'Spezzettato', + 'Planar' => 'Planare', + }, + }, + 'PlayCounter' => 'Conteggio esecuzioni', + 'PlayGap' => { + PrintConv => { + 'No Gap' => 'Nessun salto', + }, + }, + 'PlaylistDelay' => 'Attesa playlist', + 'PortraitRefiner' => { + PrintConv => { + 'Off' => 'Spento', + }, + }, + 'Position' => 'Posizione', + 'PostScriptFontName' => 'Nome carattere PostScript', + 'PostprocessingFunction' => 'Funzione post-processamento', + 'PowerSource' => 'Fonte alimentazione', + 'PowerUpTime' => 'Ora accensione', + 'Predictor' => { + Description => 'Predittore', + PrintConv => { + 'Horizontal differencing' => 'Differenziazione orizzontale', + 'None' => 'Nessuno', + }, + }, + 'PredictorColumns' => 'Colonne predittore', + 'PredictorConstants' => 'Costanti predittore', + 'PredictorRows' => 'Righe predittore', + 'PreferredFamily' => 'Famiglia preferita', + 'PreferredSubfamily' => 'Sotto-famiglia preferita', + 'PreferredVolume' => 'Volume preferito', + 'Prefs' => 'Preferenze', + 'PresetWhiteBalance' => { + PrintConv => { + 'Camera Setting' => 'Impostazioni fotocamera', + 'Fluorescent' => 'Fluorescente', + 'Shade' => 'Ombrato', + }, + }, + 'PrevFileName' => 'Nome file precedente', + 'PrevSize' => 'Dimensione precedente', + 'PrevUID' => 'UID precedente', + 'Preview' => 'Anteprima', + 'Preview0' => 'Anteprima 0 ', + 'Preview1' => 'Anteprima 1 ', + 'Preview2' => 'Anteprima 2', + 'PreviewApplicationName' => 'Nome applicazione anteprima ', + 'PreviewApplicationVersion' => 'Versione applicazione anteprima ', + 'PreviewButton' => { + Description => 'Pulsante anteprima', + PrintConv => { + 'Flash Off' => 'Flash spento', + 'None' => 'Nessuno', + 'Preview' => 'Anteprima', + 'Virtual Horizon' => 'Orizzonte virtuale', + }, + }, + 'PreviewButtonPlusDials' => { + PrintConv => { + 'Choose Image Area' => 'Seleziona area immagine', + 'None' => 'Nessuno', + }, + }, + 'PreviewColorSpace' => { + Description => 'Spazio colore anteprima', + PrintConv => { + 'Gray Gamma 2.2' => 'Gamma grigio 2.2', + 'Unknown' => 'Sconosciuto', + }, + }, + 'PreviewDate' => 'Data anteprima', + 'PreviewDateTime' => 'Data ora anteprima', + 'PreviewDuration' => 'Durata anteprima', + 'PreviewIFD' => 'Anteprima Puntatore IFD', + 'PreviewImage' => 'Immagine anteprima', + 'PreviewImageBorders' => 'Bordi immagine anteprima', + 'PreviewImageData' => 'Altezza immagine anteprima', + 'PreviewImageHeight' => 'Altezza immagine anteprima', + 'PreviewImageLength' => 'Lunghezza immagine anteprima', + 'PreviewImageName' => 'Nome immagine anteprima', + 'PreviewImageSize' => 'Dimensioni immagine anteprima', + 'PreviewImageStart' => 'Inizio immagine anteprima', + 'PreviewImageType' => 'Tipo immagine anteprima', + 'PreviewImageValid' => { + Description => 'Immagine anteprima valida', + PrintConv => { + 'Yes' => 'Sì', + }, + }, + 'PreviewImageWidth' => 'Larghezza immagine anteprima', + 'PreviewInfo' => 'Info anteprima', + 'PreviewQuality' => { + Description => 'Qualtià anteprima', + PrintConv => { + 'Normal' => 'Normale', + }, + }, + 'PreviewSettingsDigest' => 'Sommario impostazioni anteprima', + 'PreviewSettingsName' => 'Nome impostazioni anteprima', + 'PrimaryAFPoint' => { + PrintConv => { + '(none)' => '(nessuno)', + 'Bottom' => 'Basso', + 'C6 (Center)' => 'C6 (Centro)', + 'Center' => 'Centro', + 'Far Left' => 'Tutto a sinistra', + 'Far Right' => 'Tutto a destra', + 'Lower-left' => 'Inferiore sinistro', + 'Lower-right' => 'Inferiore destro', + 'Mid-left' => 'Centro/sinistra', + 'Mid-right' => 'Centro/destra', + 'Top' => 'Alto', + 'Upper-left' => 'Superiore sinistro', + 'Upper-right' => 'Superiore destro', + }, + }, + 'PrimaryChromaticities' => 'Cromatismo dei colori primari', + 'PrimaryPlatform' => 'Piattaforma primaria', + 'PrintIM' => 'Stampa Image Matching', + 'PrintIMVersion' => 'Versione PrintIM', + 'PrintPriority' => 'Priorità stampa', + 'PrintQuality' => 'Qualità stampa', + 'PrintScale' => 'Scala stampa', + 'PrinterName' => 'Nome stampante', + 'Priority' => 'Priorità', + 'PrivateBuild' => 'Compilazione privata', + 'ProcessingSoftware' => 'Software di elaborazione', + 'ProducedNotice' => 'Note prodotte', + 'Product' => 'Prodotto', + 'ProductDescription' => 'Descrizione prodotto', + 'ProductID' => 'ID prodotto', + 'ProductName' => 'Nome prodotto', + 'ProductVersion' => 'Versione prodotto', + 'ProductVersionNumber' => 'Numero di versione prodotto', + 'Profession' => 'Professione', + 'Profile' => 'Profilo', + 'ProfileAndLevel' => 'Profilo e livello', + 'ProfileCMMType' => 'Tipo profilo CMM', + 'ProfileCalibrationSig' => 'Segn calibrazione profilo', + 'ProfileClass' => { + Description => 'Classe profilo', + PrintConv => { + 'Abstract Profile' => 'Profilo Astratto', + 'ColorSpace Conversion Profile' => 'Profilo Conversione Spazio Colore', + 'DeviceLink Profile' => 'Profilo Dispositivo di Collegamento', + 'Display Device Profile' => 'Profilo Dispositivo Visualizzazione', + 'Input Device Profile' => 'Profilo dispositivo di Input', + 'NamedColor Profile' => 'Profilo Colore Chiamato', + 'Nikon Input Device Profile (NON-STANDARD!)' => 'Profilo Nikon ("nkpf")', + 'Output Device Profile' => 'Profilo Dispositivo Output', + }, + }, + 'ProfileConnectionSpace' => 'Spazio connessione profilo', + 'ProfileCopyright' => 'Copyright profilo', + 'ProfileCreator' => 'Autore profilo', + 'ProfileDateTime' => 'Data/ora profilo', + 'ProfileDescription' => 'Descrizione del Profilo', + 'ProfileDescriptionML' => 'Descrizione profilo multilinguaggio.', + 'ProfileEmbedPolicy' => { + Description => 'Politica incorporamento profilo', + PrintConv => { + 'Allow Copying' => 'Permetti la copia', + 'Embed if Used' => 'Incorpora se usato', + 'Never Embed' => 'Non incorporare mai', + 'No Restrictions' => 'Nessuna restrizione', + }, + }, + 'ProfileFileSignature' => 'Firma file profilo', + 'ProfileID' => { + Description => 'ID profilo', + PrintConv => { + 'Not Specified' => 'Non specificato', + }, + }, + 'ProfileName' => 'Nome profilo', + 'ProfileSequenceDesc' => 'Descrizione della Sequenza del Profilo', + 'ProfileType' => { + Description => 'Tipo profilo', + PrintConv => { + 'Unspecified' => 'Non specificato', + }, + }, + 'ProfileVersion' => 'Versione profilo', + 'ProgID' => 'ID programma', + 'ProgramISO' => { + PrintConv => { + 'n/a' => 'n/d', + }, + }, + 'ProgramKind' => 'Tipo di programma', + 'ProgramLine' => { + PrintConv => { + 'Normal' => 'Normale', + }, + }, + 'ProgramMode' => { + Description => 'Modo programma', + PrintConv => { + 'None' => 'Nessuno', + 'Portrait' => 'Verticale', + 'Sunset' => 'Tramonto', + 'Text' => 'Testo', + }, + }, + 'ProgramName' => 'Nome programma', + 'ProgramNumber' => 'Numero programma', + 'ProgramVersion' => 'Versione programma', + 'ProgrammingGroupKind' => 'Tipo gruppo programmazione', + 'ProgrammingGroupTitle' => 'Titolo gruppo programmazione', + 'ProgressiveScans' => 'Scansioni progressive', + 'Project' => 'Progetto', + 'ProjectName' => 'Nome progetto', + 'ProjectNumber' => 'Numero progetto', + 'ProjectRef' => 'Rif progetto', + 'ProjectSet' => 'Set progetto', + 'ProjectedCSType' => { + Description => 'Tipo CS proiettato', + PrintConv => { + 'ETRS89 Poland CS2000 zone 5' => 'ETRS89 Poland CS2000 zona 5', + 'ETRS89 Poland CS2000 zone 7' => 'ETRS89 Poland CS2000 zona 7', + 'ETRS89 Poland CS2000 zone 8' => 'ETRS89 Poland CS2000 zona 8', + 'PSAD56 UTM zone 17S' => 'PSAD56 UTM zona 17S', + 'PSAD56 UTM zone 18N' => 'PSAD56 UTM zona 18N', + 'PSAD56 UTM zone 18S' => 'PSAD56 UTM zona 18S', + 'PSAD56 UTM zone 19N' => 'PSAD56 UTM zona 19N', + 'PSAD56 UTM zone 19S' => 'PSAD56 UTM zona 19S', + 'PSAD56 UTM zone 20N' => 'PSAD56 UTM zona 20N', + 'PSAD56 UTM zone 20S' => 'PSAD56 UTM zona 20S', + 'PSAD56 UTM zone 21N' => 'PSAD56 UTM zona 21N', + 'Pulkovo Gauss zone 10' => 'Pulkovo Gauss zona 10', + 'Pulkovo Gauss zone 11' => 'Pulkovo Gauss zona 11', + 'Pulkovo Gauss zone 12' => 'Pulkovo Gauss zona 12', + 'Pulkovo Gauss zone 13' => 'Pulkovo Gauss zona 13', + 'Pulkovo Gauss zone 14' => 'Pulkovo Gauss zona 14', + 'Pulkovo Gauss zone 15' => 'Pulkovo Gauss zona 15', + 'Pulkovo Gauss zone 16' => 'Pulkovo Gauss zona 16', + 'Pulkovo Gauss zone 17' => 'Pulkovo Gauss zona 17', + 'Pulkovo Gauss zone 18' => 'Pulkovo Gauss zona 18', + 'Pulkovo Gauss zone 19' => 'Pulkovo Gauss zona 19', + 'Pulkovo Gauss zone 20' => 'Pulkovo Gauss zona 20', + 'Pulkovo Gauss zone 21' => 'Pulkovo Gauss zona 21', + 'Pulkovo Gauss zone 22' => 'Pulkovo Gauss zona 22', + 'Pulkovo Gauss zone 23' => 'Pulkovo Gauss zona 23', + 'Pulkovo Gauss zone 24' => 'Pulkovo Gauss zona 24', + 'Pulkovo Gauss zone 25' => 'Pulkovo Gauss zona 25', + 'Pulkovo Gauss zone 26' => 'Pulkovo Gauss zona 26', + 'Pulkovo Gauss zone 27' => 'Pulkovo Gauss zona 27', + 'Pulkovo Gauss zone 28' => 'Pulkovo Gauss zona 28', + 'Pulkovo Gauss zone 29' => 'Pulkovo Gauss zona 29', + 'Pulkovo Gauss zone 30' => 'Pulkovo Gauss zona 30', + 'Pulkovo Gauss zone 31' => 'Pulkovo Gauss zona 31', + 'Pulkovo Gauss zone 32' => 'Pulkovo Gauss zona 32', + 'Pulkovo Gauss zone 4' => 'Pulkovo Gauss zona 4', + 'Pulkovo Gauss zone 5' => 'Pulkovo Gauss zona 5', + 'Pulkovo Gauss zone 6' => 'Pulkovo Gauss zona 6', + 'Pulkovo Gauss zone 7' => 'Pulkovo Gauss zona 7', + 'Pulkovo Gauss zone 8' => 'Pulkovo Gauss zona 8', + 'Pulkovo Gauss zone 9' => 'Pulkovo Gauss zona 9', + 'Sudan UTM zone 35N' => 'Sudan UTM zona 35N', + 'Sudan UTM zone 36N' => 'Sudan UTM zona 36N', + }, + }, + 'Projection' => 'Proiezione', + 'ProjectionAlgorithm' => 'Algoritmo proiezione', + 'ProjectionAngle' => 'Angolo proiezione', + 'Projects' => 'Progetti', + 'Properties' => 'Proprietà', + 'PropertyReleaseStatus' => { + PrintConv => { + 'None' => 'Nessuno', + 'Not Applicable' => 'Non applicabile', + }, + }, + 'Protect' => 'Proteggi', + 'Protected' => 'Protetto', + 'ProtocolName' => 'Nome protocollo', + 'Province-State' => 'Provincia/Stato', + 'PublicationDate' => 'Data pubblicazione', + 'PublicationName' => 'Nome pubblicazione', + 'PublicationSets' => 'Set pupplicazione', + 'Publisher' => 'Editore', + 'PublisherURL' => 'URL editore', + 'PurchaseDate' => 'Data acquisto', + 'PurchaserAccountName' => 'Nome account acquirente', + 'PurchaserAccountNumber' => 'Numero account acquirente', + 'PurchaserIdentificationKind' => 'Tipo identificazione acquirente', + 'PurchaserIdentificationValue' => 'Valore identificazione acquirente', + 'PurchasingDepartment' => 'Reparto acquirente', + 'PurchasingOrganizationName' => 'Nome organizzazione acquirente', + 'Purpose' => 'Scopo', + 'PurposeOfReferenceCodeSequence' => 'Scopo sequenza codici riferimento', + 'PyramidLevels' => 'Livelli piramite', + 'Quality' => { + Description => 'Qualità', + PrintConv => { + 'Compressed RAW' => 'RAW compresso', + 'Compressed RAW + JPEG' => 'RAW+JPEG compresso', + 'Extra Fine' => 'Extra fine', + 'Low' => 'Basso', + 'Normal' => 'Normale', + 'RAW + JPEG' => 'RAW+JPEG', + 'n/a' => 'n/d', + }, + }, + 'QualityControlImage' => 'Immagine controllo qualità', + 'QualityFlag' => 'Indicatore qualità', + 'QualityMode' => { + Description => 'Modo qualità', + PrintConv => { + 'Normal' => 'Normale', + }, + }, + 'Quantity' => 'Quantità', + 'QuantitySequence' => 'Sequenza quantità', + 'QuantizationDefault' => 'Default quantizzazione', + 'QuantizationMethod' => 'Metodo quantizzazione', + 'QueueStatus' => 'Stato coda', + 'QuickAdjust' => 'Regolazione rapida', + 'QuickControlDialInMeter' => { + PrintConv => { + 'ISO speed' => 'Velocità ISO', + }, + }, + 'QuickEdit' => 'Modifica velote', + 'QuickMaskInfo' => 'Info maschera veloce', + 'QuickShot' => { + Description => 'Scatto veloce', + PrintConv => { + 'Off' => 'Spento', + }, + }, + 'R2ABlueCtbl00' => 'R2 A blu Stbl 30', + 'R2ABlueCtbl01' => 'R2 A blu Stbl 29', + 'R2ABlueCtbl02' => 'R2 A blu Stbl 28', + 'R2ABlueCtbl03' => 'R2 A blu Stbl 27', + 'R2ABlueCtbl04' => 'R2 A blu Stbl 26', + 'R2ABlueCtbl05' => 'R2 A blu Stbl 25', + 'R2ABlueCtbl06' => 'R2 A blu Stbl 24', + 'R2ABlueCtbl07' => 'R2 A blu Stbl 23', + 'R2ABlueCtbl08' => 'R2 A blu Stbl 22', + 'R2ABlueCtbl09' => 'R2 A blu Stbl 21', + 'R2ABlueCtbl10' => 'R2 A blu Stbl 20', + 'R2ABlueCtbl11' => 'R2 A blu Stbl 19', + 'R2ABlueCtbl12' => 'R2 A blu Stbl 18', + 'R2ABlueCtbl13' => 'R2 A blu Stbl 17', + 'R2ABlueCtbl14' => 'R2 A blu Stbl 16', + 'R2ABlueCtbl15' => 'R2 A blu Stbl 15', + 'R2ABlueCtbl16' => 'R2 A blu Stbl 14', + 'R2ABlueCtbl17' => 'R2 A blu Stbl 13', + 'R2ABlueCtbl18' => 'R2 A blu Stbl 12', + 'R2ABlueCtbl19' => 'R2 A blu Stbl 11', + 'R2ABlueCtbl20' => 'R2 A blu Stbl 10', + 'R2ABlueCtbl21' => 'R2 A blu Stbl 09', + 'R2ABlueCtbl22' => 'R2 A blu Stbl 08', + 'R2ABlueCtbl23' => 'R2 A blu Stbl 07', + 'R2ABlueCtbl24' => 'R2 A blu Stbl 06', + 'R2ABlueCtbl25' => 'R2 A blu Stbl 05', + 'R2ABlueCtbl26' => 'R2 A blu Stbl 04', + 'R2ABlueCtbl27' => 'R2 A blu Stbl 03', + 'R2ABlueCtbl28' => 'R2 A blu Stbl 02', + 'R2ABlueCtbl29' => 'R2 A blu Stbl 01', + 'R2ABlueCtbl30' => 'R2 A blu Stbl 00', + 'R2ABlueCtbl31' => 'R2 A blu Ctbl 31', + 'R2ABlueStbl00' => 'R2 A blu Ctbl 30', + 'R2ABlueStbl01' => 'R2 A blu Ctbl 29', + 'R2ABlueStbl02' => 'R2 A blu Ctbl 28', + 'R2ABlueStbl03' => 'R2 A blu Ctbl 27', + 'R2ABlueStbl04' => 'R2 A blu Ctbl 26', + 'R2ABlueStbl05' => 'R2 A blu Ctbl 25', + 'R2ABlueStbl06' => 'R2 A blu Ctbl 24', + 'R2ABlueStbl07' => 'R2 A blu Ctbl 23', + 'R2ABlueStbl08' => 'R2 A blu Ctbl 22', + 'R2ABlueStbl09' => 'R2 A blu Ctbl 21', + 'R2ABlueStbl10' => 'R2 A blu Ctbl 20', + 'R2ABlueStbl11' => 'R2 A blu Ctbl 19', + 'R2ABlueStbl12' => 'R2 A blu Ctbl 18', + 'R2ABlueStbl13' => 'R2 A blu Ctbl 17', + 'R2ABlueStbl14' => 'R2 A blu Ctbl 16', + 'R2ABlueStbl15' => 'R2 A blu Ctbl 15', + 'R2ABlueStbl16' => 'R2 A blu Ctbl 14', + 'R2ABlueStbl17' => 'R2 A blu Ctbl 13', + 'R2ABlueStbl18' => 'R2 A blu Ctbl 12', + 'R2ABlueStbl19' => 'R2 A blu Ctbl 11', + 'R2ABlueStbl20' => 'R2 A blu Ctbl 10', + 'R2ABlueStbl21' => 'R2 A blu Ctbl 09', + 'R2ABlueStbl22' => 'R2 A blu Ctbl 08', + 'R2ABlueStbl23' => 'R2 A blu Ctbl 07', + 'R2ABlueStbl24' => 'R2 A blu Ctbl 06', + 'R2ABlueStbl25' => 'R2 A blu Ctbl 05', + 'R2ABlueStbl26' => 'R2 A blu Ctbl 04', + 'R2ABlueStbl27' => 'R2 A blu Ctbl 03', + 'R2ABlueStbl28' => 'R2 A blu Ctbl 02', + 'R2ABlueStbl29' => 'R2 A blu Ctbl 01', + 'R2ABlueStbl30' => 'R2 A blu Ctbl 00', + 'R2ABlueStbl31' => 'R2 A blu Stbl 31', + 'R2AGreenCtbl00' => 'R2 A verde Ctbl 00', + 'R2AGreenCtbl01' => 'R2 A verde Ctbl 01', + 'R2AGreenCtbl02' => 'R2 A verde Ctbl 02', + 'R2AGreenCtbl03' => 'R2 A verde Ctbl 03', + 'R2AGreenCtbl04' => 'R2 A verde Ctbl 04', + 'R2AGreenCtbl05' => 'R2 A verde Ctbl 05', + 'R2AGreenCtbl06' => 'R2 A verde Ctbl 06', + 'R2AGreenCtbl07' => 'R2 A verde Ctbl 07', + 'R2AGreenCtbl08' => 'R2 A verde Ctbl 08', + 'R2AGreenCtbl09' => 'R2 A verde Ctbl 09', + 'R2AGreenCtbl10' => 'R2 A verde Ctbl 10', + 'R2AGreenCtbl11' => 'R2 A verde Ctbl 11', + 'R2AGreenCtbl12' => 'R2 A verde Ctbl 12', + 'R2AGreenCtbl13' => 'R2 A verde Ctbl 13', + 'R2AGreenCtbl14' => 'R2 A verde Ctbl 14', + 'R2AGreenCtbl15' => 'R2 A verde Ctbl 15', + 'R2AGreenCtbl16' => 'R2 A verde Ctbl 16', + 'R2AGreenCtbl17' => 'R2 A verde Ctbl 17', + 'R2AGreenCtbl18' => 'R2 A verde Ctbl 18', + 'R2AGreenCtbl19' => 'R2 A verde Ctbl 19', + 'R2AGreenCtbl20' => 'R2 A verde Ctbl 20', + 'R2AGreenCtbl21' => 'R2 A verde Ctbl 21', + 'R2AGreenCtbl22' => 'R2 A verde Ctbl 22', + 'R2AGreenCtbl23' => 'R2 A verde Ctbl 23', + 'R2AGreenCtbl24' => 'R2 A verde Ctbl 24', + 'R2AGreenCtbl25' => 'R2 A verde Ctbl 25', + 'R2AGreenCtbl26' => 'R2 A verde Ctbl 26', + 'R2AGreenCtbl27' => 'R2 A verde Ctbl 27', + 'R2AGreenCtbl28' => 'R2 A verde Ctbl 28', + 'R2AGreenCtbl29' => 'R2 A verde Ctbl 29', + 'R2AGreenCtbl30' => 'R2 A verde Ctbl 30', + 'R2AGreenCtbl31' => 'R2 A verde Ctbl 31', + 'R2AGreenStbl00' => 'R2 A verde Stbl 00', + 'R2AGreenStbl01' => 'R2 A verde Stbl 01', + 'R2AGreenStbl02' => 'R2 A verde Stbl 02', + 'R2AGreenStbl03' => 'R2 A verde Stbl 03', + 'R2AGreenStbl04' => 'R2 A verde Stbl 04', + 'R2AGreenStbl05' => 'R2 A verde Stbl 05', + 'R2AGreenStbl06' => 'R2 A verde Stbl 06', + 'R2AGreenStbl07' => 'R2 A verde Stbl 07', + 'R2AGreenStbl08' => 'R2 A verde Stbl 08', + 'R2AGreenStbl09' => 'R2 A verde Stbl 09', + 'R2AGreenStbl10' => 'R2 A verde Stbl 10', + 'R2AGreenStbl11' => 'R2 A verde Stbl 11', + 'R2AGreenStbl12' => 'R2 A verde Stbl 12', + 'R2AGreenStbl13' => 'R2 A verde Stbl 13', + 'R2AGreenStbl14' => 'R2 A verde Stbl 14', + 'R2AGreenStbl15' => 'R2 A verde Stbl 15', + 'R2AGreenStbl16' => 'R2 A verde Stbl 16', + 'R2AGreenStbl17' => 'R2 A verde Stbl 17', + 'R2AGreenStbl18' => 'R2 A verde Stbl 18', + 'R2AGreenStbl19' => 'R2 A verde Stbl 19', + 'R2AGreenStbl20' => 'R2 A verde Stbl 20', + 'R2AGreenStbl21' => 'R2 A verde Stbl 21', + 'R2AGreenStbl22' => 'R2 A verde Stbl 22', + 'R2AGreenStbl23' => 'R2 A verde Stbl 23', + 'R2AGreenStbl24' => 'R2 A verde Stbl 24', + 'R2AGreenStbl25' => 'R2 A verde Stbl 25', + 'R2AGreenStbl26' => 'R2 A verde Stbl 26', + 'R2AGreenStbl27' => 'R2 A verde Stbl 27', + 'R2AGreenStbl28' => 'R2 A verde Stbl 28', + 'R2AGreenStbl29' => 'R2 A verde Stbl 29', + 'R2AGreenStbl30' => 'R2 A verde Stbl 30', + 'R2AGreenStbl31' => 'R2 A verde Stbl 31', + 'R2AHeight' => 'R2 A altezza', + 'R2AIntervals' => 'R2 A intervalli', + 'R2ARedCtbl00' => 'R2 A rosso Ctbl 00', + 'R2ARedCtbl01' => 'R2 A rosso Ctbl 01', + 'R2ARedCtbl02' => 'R2 A rosso Ctbl 02', + 'R2ARedCtbl03' => 'R2 A rosso Ctbl 03', + 'R2ARedCtbl04' => 'R2 A rosso Ctbl 04', + 'R2ARedCtbl05' => 'R2 A rosso Ctbl 05', + 'R2ARedCtbl06' => 'R2 A rosso Ctbl 06', + 'R2ARedCtbl07' => 'R2 A rosso Ctbl 07', + 'R2ARedCtbl08' => 'R2 A rosso Ctbl 08', + 'R2ARedCtbl09' => 'R2 A rosso Ctbl 09', + 'R2ARedCtbl10' => 'R2 A rosso Ctbl 10', + 'R2ARedCtbl11' => 'R2 A rosso Ctbl 11', + 'R2ARedCtbl12' => 'R2 A rosso Ctbl 12', + 'R2ARedCtbl13' => 'R2 A rosso Ctbl 13', + 'R2ARedCtbl14' => 'R2 A rosso Ctbl 14', + 'R2ARedCtbl15' => 'R2 A rosso Ctbl 15', + 'R2ARedCtbl16' => 'R2 A rosso Ctbl 16', + 'R2ARedCtbl17' => 'R2 A rosso Ctbl 17', + 'R2ARedCtbl18' => 'R2 A rosso Ctbl 18', + 'R2ARedCtbl19' => 'R2 A rosso Ctbl 19', + 'R2ARedCtbl20' => 'R2 A rosso Ctbl 20', + 'R2ARedCtbl21' => 'R2 A rosso Ctbl 21', + 'R2ARedCtbl22' => 'R2 A rosso Ctbl 22', + 'R2ARedCtbl23' => 'R2 A rosso Ctbl 23', + 'R2ARedCtbl24' => 'R2 A rosso Ctbl 24', + 'R2ARedCtbl25' => 'R2 A rosso Ctbl 25', + 'R2ARedCtbl26' => 'R2 A rosso Ctbl 26', + 'R2ARedCtbl27' => 'R2 A rosso Ctbl 27', + 'R2ARedCtbl28' => 'R2 A rosso Ctbl 28', + 'R2ARedCtbl29' => 'R2 A rosso Ctbl 29', + 'R2ARedCtbl30' => 'R2 A rosso Ctbl 30', + 'R2ARedCtbl31' => 'R2 A rosso Ctbl 31', + 'R2ARedStbl00' => 'R2 A rosso Stbl 00', + 'R2ARedStbl01' => 'R2 A rosso Stbl 01', + 'R2ARedStbl02' => 'R2 A rosso Stbl 02', + 'R2ARedStbl03' => 'R2 A rosso Stbl 03', + 'R2ARedStbl04' => 'R2 A rosso Stbl 04', + 'R2ARedStbl05' => 'R2 A rosso Stbl 05', + 'R2ARedStbl06' => 'R2 A rosso Stbl 06', + 'R2ARedStbl07' => 'R2 A rosso Stbl 07', + 'R2ARedStbl08' => 'R2 A rosso Stbl 08', + 'R2ARedStbl09' => 'R2 A rosso Stbl 09', + 'R2ARedStbl10' => 'R2 A rosso Stbl 10', + 'R2ARedStbl11' => 'R2 A rosso Stbl 11', + 'R2ARedStbl12' => 'R2 A rosso Stbl 12', + 'R2ARedStbl13' => 'R2 A rosso Stbl 13', + 'R2ARedStbl14' => 'R2 A rosso Stbl 14', + 'R2ARedStbl15' => 'R2 A rosso Stbl 15', + 'R2ARedStbl16' => 'R2 A rosso Stbl 16', + 'R2ARedStbl17' => 'R2 A rosso Stbl 17', + 'R2ARedStbl18' => 'R2 A rosso Stbl 18', + 'R2ARedStbl19' => 'R2 A rosso Stbl 19', + 'R2ARedStbl20' => 'R2 A rosso Stbl 20', + 'R2ARedStbl21' => 'R2 A rosso Stbl 21', + 'R2ARedStbl22' => 'R2 A rosso Stbl 22', + 'R2ARedStbl23' => 'R2 A rosso Stbl 23', + 'R2ARedStbl24' => 'R2 A rosso Stbl 24', + 'R2ARedStbl25' => 'R2 A rosso Stbl 25', + 'R2ARedStbl26' => 'R2 A rosso Stbl 26', + 'R2ARedStbl27' => 'R2 A rosso Stbl 27', + 'R2ARedStbl28' => 'R2 A rosso Stbl 28', + 'R2ARedStbl29' => 'R2 A rosso Stbl 29', + 'R2ARedStbl30' => 'R2 A rosso Stbl 30', + 'R2ARedStbl31' => 'R2 A rosso Stbl 31', + 'R2AWidth' => 'R2 A larghezza', + 'R2D65BlueCtbl00' => 'R2 D65 blu Ctbl 00', + 'R2D65BlueCtbl01' => 'R2 D65 blu Ctbl 01', + 'R2D65BlueCtbl02' => 'R2 D65 blu Ctbl 02', + 'R2D65BlueCtbl03' => 'R2 D65 blu Ctbl 03', + 'R2D65BlueCtbl04' => 'R2 D65 blu Ctbl 04', + 'R2D65BlueCtbl05' => 'R2 D65 blu Ctbl 05', + 'R2D65BlueCtbl06' => 'R2 D65 blu Ctbl 06', + 'R2D65BlueCtbl07' => 'R2 D65 blu Ctbl 07', + 'R2D65BlueCtbl08' => 'R2 D65 blu Ctbl 08', + 'R2D65BlueCtbl09' => 'R2 D65 blu Ctbl 09', + 'R2D65BlueCtbl10' => 'R2 D65 blu Ctbl 10', + 'R2D65BlueCtbl11' => 'R2 D65 blu Ctbl 11', + 'R2D65BlueCtbl12' => 'R2 D65 blu Ctbl 12', + 'R2D65BlueCtbl13' => 'R2 D65 blu Ctbl 13', + 'R2D65BlueCtbl14' => 'R2 D65 blu Ctbl 14', + 'R2D65BlueCtbl15' => 'R2 D65 blu Ctbl 15', + 'R2D65BlueCtbl16' => 'R2 D65 blu Ctbl 16', + 'R2D65BlueCtbl17' => 'R2 D65 blu Ctbl 17', + 'R2D65BlueCtbl18' => 'R2 D65 blu Ctbl 18', + 'R2D65BlueCtbl19' => 'R2 D65 blu Ctbl 19', + 'R2D65BlueCtbl20' => 'R2 D65 blu Ctbl 20', + 'R2D65BlueCtbl21' => 'R2 D65 blu Ctbl 21', + 'R2D65BlueCtbl22' => 'R2 D65 blu Ctbl 22', + 'R2D65BlueCtbl23' => 'R2 D65 blu Ctbl 23', + 'R2D65BlueCtbl24' => 'R2 D65 blu Ctbl 24', + 'R2D65BlueCtbl25' => 'R2 D65 blu Ctbl 25', + 'R2D65BlueCtbl26' => 'R2 D65 blu Ctbl 26', + 'R2D65BlueCtbl27' => 'R2 D65 blu Ctbl 27', + 'R2D65BlueCtbl28' => 'R2 D65 blu Ctbl 28', + 'R2D65BlueCtbl29' => 'R2 D65 blu Ctbl 29', + 'R2D65BlueCtbl30' => 'R2 D65 blu Ctbl 30', + 'R2D65BlueCtbl31' => 'R2 D65 blu Ctbl 31', + 'R2D65BlueStbl00' => 'R2 D65 blu Stbl 00', + 'R2D65BlueStbl01' => 'R2 D65 blu Stbl 01', + 'R2D65BlueStbl02' => 'R2 D65 blu Stbl 02', + 'R2D65BlueStbl03' => 'R2 D65 blu Stbl 03', + 'R2D65BlueStbl04' => 'R2 D65 blu Stbl 04', + 'R2D65BlueStbl05' => 'R2 D65 blu Stbl 05', + 'R2D65BlueStbl06' => 'R2 D65 blu Stbl 06', + 'R2D65BlueStbl07' => 'R2 D65 blu Stbl 07', + 'R2D65BlueStbl08' => 'R2 D65 blu Stbl 08', + 'R2D65BlueStbl09' => 'R2 D65 blu Stbl 09', + 'R2D65BlueStbl10' => 'R2 D65 blu Stbl 10', + 'R2D65BlueStbl11' => 'R2 D65 blu Stbl 11', + 'R2D65BlueStbl12' => 'R2 D65 blu Stbl 12', + 'R2D65BlueStbl13' => 'R2 D65 blu Stbl 13', + 'R2D65BlueStbl14' => 'R2 D65 blu Stbl 14', + 'R2D65BlueStbl15' => 'R2 D65 blu Stbl 15', + 'R2D65BlueStbl16' => 'R2 D65 blu Stbl 16', + 'R2D65BlueStbl17' => 'R2 D65 blu Stbl 17', + 'R2D65BlueStbl18' => 'R2 D65 blu Stbl 18', + 'R2D65BlueStbl19' => 'R2 D65 blu Stbl 19', + 'R2D65BlueStbl20' => 'R2 D65 blu Stbl 20', + 'R2D65BlueStbl21' => 'R2 D65 blu Stbl 21', + 'R2D65BlueStbl22' => 'R2 D65 blu Stbl 22', + 'R2D65BlueStbl23' => 'R2 D65 blu Stbl 23', + 'R2D65BlueStbl24' => 'R2 D65 blu Stbl 24', + 'R2D65BlueStbl25' => 'R2 D65 blu Stbl 25', + 'R2D65BlueStbl26' => 'R2 D65 blu Stbl 26', + 'R2D65BlueStbl27' => 'R2 D65 blu Stbl 27', + 'R2D65BlueStbl28' => 'R2 D65 blu Stbl 28', + 'R2D65BlueStbl29' => 'R2 D65 blu Stbl 29', + 'R2D65BlueStbl30' => 'R2 D65 blu Stbl 30', + 'R2D65BlueStbl31' => 'R2 D65 blu Stbl 31', + 'R2D65GreenCtbl00' => 'R2 D65 verde Ctbl 00', + 'R2D65GreenCtbl01' => 'R2 D65 verde Ctbl 01', + 'R2D65GreenCtbl02' => 'R2 D65 verde Ctbl 02', + 'R2D65GreenCtbl03' => 'R2 D65 verde Ctbl 03', + 'R2D65GreenCtbl04' => 'R2 D65 verde Ctbl 04', + 'R2D65GreenCtbl05' => 'R2 D65 verde Ctbl 05', + 'R2D65GreenCtbl06' => 'R2 D65 verde Ctbl 06', + 'R2D65GreenCtbl07' => 'R2 D65 verde Ctbl 07', + 'R2D65GreenCtbl08' => 'R2 D65 verde Ctbl 08', + 'R2D65GreenCtbl09' => 'R2 D65 verde Ctbl 09', + 'R2D65GreenCtbl10' => 'R2 D65 verde Ctbl 10', + 'R2D65GreenCtbl11' => 'R2 D65 verde Ctbl 11', + 'R2D65GreenCtbl12' => 'R2 D65 verde Ctbl 12', + 'R2D65GreenCtbl13' => 'R2 D65 verde Ctbl 13', + 'R2D65GreenCtbl14' => 'R2 D65 verde Ctbl 14', + 'R2D65GreenCtbl15' => 'R2 D65 verde Ctbl 15', + 'R2D65GreenCtbl16' => 'R2 D65 verde Ctbl 16', + 'R2D65GreenCtbl17' => 'R2 D65 verde Ctbl 17', + 'R2D65GreenCtbl18' => 'R2 D65 verde Ctbl 18', + 'R2D65GreenCtbl19' => 'R2 D65 verde Ctbl 19', + 'R2D65GreenCtbl20' => 'R2 D65 verde Ctbl 20', + 'R2D65GreenCtbl21' => 'R2 D65 verde Ctbl 21', + 'R2D65GreenCtbl22' => 'R2 D65 verde Ctbl 22', + 'R2D65GreenCtbl23' => 'R2 D65 verde Ctbl 23', + 'R2D65GreenCtbl24' => 'R2 D65 verde Ctbl 24', + 'R2D65GreenCtbl25' => 'R2 D65 verde Ctbl 25', + 'R2D65GreenCtbl26' => 'R2 D65 verde Ctbl 26', + 'R2D65GreenCtbl27' => 'R2 D65 verde Ctbl 27', + 'R2D65GreenCtbl28' => 'R2 D65 verde Ctbl 28', + 'R2D65GreenCtbl29' => 'R2 D65 verde Ctbl 29', + 'R2D65GreenCtbl30' => 'R2 D65 verde Ctbl 30', + 'R2D65GreenCtbl31' => 'R2 D65 verde Ctbl 31', + 'R2D65GreenStbl00' => 'R2 D65 verde Stbl 00', + 'R2D65GreenStbl01' => 'R2 D65 verde Stbl 01', + 'R2D65GreenStbl02' => 'R2 D65 verde Stbl 02', + 'R2D65GreenStbl03' => 'R2 D65 verde Stbl 03', + 'R2D65GreenStbl04' => 'R2 D65 verde Stbl 04', + 'R2D65GreenStbl05' => 'R2 D65 verde Stbl 05', + 'R2D65GreenStbl06' => 'R2 D65 verde Stbl 06', + 'R2D65GreenStbl07' => 'R2 D65 verde Stbl 07', + 'R2D65GreenStbl08' => 'R2 D65 verde Stbl 08', + 'R2D65GreenStbl09' => 'R2 D65 verde Stbl 09', + 'R2D65GreenStbl10' => 'R2 D65 verde Stbl 10', + 'R2D65GreenStbl11' => 'R2 D65 verde Stbl 11', + 'R2D65GreenStbl12' => 'R2 D65 verde Stbl 12', + 'R2D65GreenStbl13' => 'R2 D65 verde Stbl 13', + 'R2D65GreenStbl14' => 'R2 D65 verde Stbl 14', + 'R2D65GreenStbl15' => 'R2 D65 verde Stbl 15', + 'R2D65GreenStbl16' => 'R2 D65 verde Stbl 16', + 'R2D65GreenStbl17' => 'R2 D65 verde Stbl 17', + 'R2D65GreenStbl18' => 'R2 D65 verde Stbl 18', + 'R2D65GreenStbl19' => 'R2 D65 verde Stbl 19', + 'R2D65GreenStbl20' => 'R2 D65 verde Stbl 20', + 'R2D65GreenStbl21' => 'R2 D65 verde Stbl 21', + 'R2D65GreenStbl22' => 'R2 D65 verde Stbl 22', + 'R2D65GreenStbl23' => 'R2 D65 verde Stbl 23', + 'R2D65GreenStbl24' => 'R2 D65 verde Stbl 24', + 'R2D65GreenStbl25' => 'R2 D65 verde Stbl 25', + 'R2D65GreenStbl26' => 'R2 D65 verde Stbl 26', + 'R2D65GreenStbl27' => 'R2 D65 verde Stbl 27', + 'R2D65GreenStbl28' => 'R2 D65 verde Stbl 28', + 'R2D65GreenStbl29' => 'R2 D65 verde Stbl 29', + 'R2D65GreenStbl30' => 'R2 D65 verde Stbl 30', + 'R2D65GreenStbl31' => 'R2 D65 verde Stbl 31', + 'R2D65Height' => 'R2 D65 altezza', + 'R2D65Intervals' => 'R2 D65 intervalli', + 'R2D65RedCtbl00' => 'R2 D65 rosso Ctbl 00', + 'R2D65RedCtbl01' => 'R2 D65 rosso Ctbl 01', + 'R2D65RedCtbl02' => 'R2 D65 rosso Ctbl 02', + 'R2D65RedCtbl03' => 'R2 D65 rosso Ctbl 03', + 'R2D65RedCtbl04' => 'R2 D65 rosso Ctbl 04', + 'R2D65RedCtbl05' => 'R2 D65 rosso Ctbl 05', + 'R2D65RedCtbl06' => 'R2 D65 rosso Ctbl 06', + 'R2D65RedCtbl07' => 'R2 D65 rosso Ctbl 07', + 'R2D65RedCtbl08' => 'R2 D65 rosso Ctbl 08', + 'R2D65RedCtbl09' => 'R2 D65 rosso Ctbl 09', + 'R2D65RedCtbl10' => 'R2 D65 rosso Ctbl 10', + 'R2D65RedCtbl11' => 'R2 D65 rosso Ctbl 11', + 'R2D65RedCtbl12' => 'R2 D65 rosso Ctbl 12', + 'R2D65RedCtbl13' => 'R2 D65 rosso Ctbl 13', + 'R2D65RedCtbl14' => 'R2 D65 rosso Ctbl 14', + 'R2D65RedCtbl15' => 'R2 D65 rosso Ctbl 15', + 'R2D65RedCtbl16' => 'R2 D65 rosso Ctbl 16', + 'R2D65RedCtbl17' => 'R2 D65 rosso Ctbl 17', + 'R2D65RedCtbl18' => 'R2 D65 rosso Ctbl 18', + 'R2D65RedCtbl19' => 'R2 D65 rosso Ctbl 19', + 'R2D65RedCtbl20' => 'R2 D65 rosso Ctbl 20', + 'R2D65RedCtbl21' => 'R2 D65 rosso Ctbl 21', + 'R2D65RedCtbl22' => 'R2 D65 rosso Ctbl 22', + 'R2D65RedCtbl23' => 'R2 D65 rosso Ctbl 23', + 'R2D65RedCtbl24' => 'R2 D65 rosso Ctbl 24', + 'R2D65RedCtbl25' => 'R2 D65 rosso Ctbl 25', + 'R2D65RedCtbl26' => 'R2 D65 rosso Ctbl 26', + 'R2D65RedCtbl27' => 'R2 D65 rosso Ctbl 27', + 'R2D65RedCtbl28' => 'R2 D65 rosso Ctbl 28', + 'R2D65RedCtbl29' => 'R2 D65 rosso Ctbl 29', + 'R2D65RedCtbl30' => 'R2 D65 rosso Ctbl 30', + 'R2D65RedCtbl31' => 'R2 D65 rosso Ctbl 31', + 'R2D65RedStbl00' => 'R2 D65 rosso Stbl 00', + 'R2D65RedStbl01' => 'R2 D65 rosso Stbl 01', + 'R2D65RedStbl02' => 'R2 D65 rosso Stbl 02', + 'R2D65RedStbl03' => 'R2 D65 rosso Stbl 03', + 'R2D65RedStbl04' => 'R2 D65 rosso Stbl 04', + 'R2D65RedStbl05' => 'R2 D65 rosso Stbl 05', + 'R2D65RedStbl06' => 'R2 D65 rosso Stbl 06', + 'R2D65RedStbl07' => 'R2 D65 rosso Stbl 07', + 'R2D65RedStbl08' => 'R2 D65 rosso Stbl 08', + 'R2D65RedStbl09' => 'R2 D65 rosso Stbl 09', + 'R2D65RedStbl10' => 'R2 D65 rosso Stbl 10', + 'R2D65RedStbl11' => 'R2 D65 rosso Stbl 11', + 'R2D65RedStbl12' => 'R2 D65 rosso Stbl 12', + 'R2D65RedStbl13' => 'R2 D65 rosso Stbl 13', + 'R2D65RedStbl14' => 'R2 D65 rosso Stbl 14', + 'R2D65RedStbl15' => 'R2 D65 rosso Stbl 15', + 'R2D65RedStbl16' => 'R2 D65 rosso Stbl 16', + 'R2D65RedStbl17' => 'R2 D65 rosso Stbl 17', + 'R2D65RedStbl18' => 'R2 D65 rosso Stbl 18', + 'R2D65RedStbl19' => 'R2 D65 rosso Stbl 19', + 'R2D65RedStbl20' => 'R2 D65 rosso Stbl 20', + 'R2D65RedStbl21' => 'R2 D65 rosso Stbl 21', + 'R2D65RedStbl22' => 'R2 D65 rosso Stbl 22', + 'R2D65RedStbl23' => 'R2 D65 rosso Stbl 23', + 'R2D65RedStbl24' => 'R2 D65 rosso Stbl 24', + 'R2D65RedStbl25' => 'R2 D65 rosso Stbl 25', + 'R2D65RedStbl26' => 'R2 D65 rosso Stbl 26', + 'R2D65RedStbl27' => 'R2 D65 rosso Stbl 27', + 'R2D65RedStbl28' => 'R2 D65 rosso Stbl 28', + 'R2D65RedStbl29' => 'R2 D65 rosso Stbl 29', + 'R2D65RedStbl30' => 'R2 D65 rosso Stbl 30', + 'R2D65RedStbl31' => 'R2 D65 rosso Stbl 31', + 'R2D65Width' => 'R2 D65 larghezza', + 'R2TL84BlueCtbl00' => 'R2 TL84 blu Ctbl 00', + 'R2TL84BlueCtbl01' => 'R2 TL84 blu Ctbl 01', + 'R2TL84BlueCtbl02' => 'R2 TL84 blu Ctbl 02', + 'R2TL84BlueCtbl03' => 'R2 TL84 blu Ctbl 03', + 'R2TL84BlueCtbl04' => 'R2 TL84 blu Ctbl 04', + 'R2TL84BlueCtbl05' => 'R2 TL84 blu Ctbl 05', + 'R2TL84BlueCtbl06' => 'R2 TL84 blu Ctbl 06', + 'R2TL84BlueCtbl07' => 'R2 TL84 blu Ctbl 07', + 'R2TL84BlueCtbl08' => 'R2 TL84 blu Ctbl 08', + 'R2TL84BlueCtbl09' => 'R2 TL84 blu Ctbl 09', + 'R2TL84BlueCtbl10' => 'R2 TL84 blu Ctbl 10', + 'R2TL84BlueCtbl11' => 'R2 TL84 blu Ctbl 11', + 'R2TL84BlueCtbl12' => 'R2 TL84 blu Ctbl 12', + 'R2TL84BlueCtbl13' => 'R2 TL84 blu Ctbl 13', + 'R2TL84BlueCtbl14' => 'R2 TL84 blu Ctbl 14', + 'R2TL84BlueCtbl15' => 'R2 TL84 blu Ctbl 15', + 'R2TL84BlueCtbl16' => 'R2 TL84 blu Ctbl 16', + 'R2TL84BlueCtbl17' => 'R2 TL84 blu Ctbl 17', + 'R2TL84BlueCtbl18' => 'R2 TL84 blu Ctbl 18', + 'R2TL84BlueCtbl19' => 'R2 TL84 blu Ctbl 19', + 'R2TL84BlueCtbl20' => 'R2 TL84 blu Ctbl 20', + 'R2TL84BlueCtbl21' => 'R2 TL84 blu Ctbl 21', + 'R2TL84BlueCtbl22' => 'R2 TL84 blu Ctbl 22', + 'R2TL84BlueCtbl23' => 'R2 TL84 blu Ctbl 23', + 'R2TL84BlueCtbl24' => 'R2 TL84 blu Ctbl 24', + 'R2TL84BlueCtbl25' => 'R2 TL84 blu Ctbl 25', + 'R2TL84BlueCtbl26' => 'R2 TL84 blu Ctbl 26', + 'R2TL84BlueCtbl27' => 'R2 TL84 blu Ctbl 27', + 'R2TL84BlueCtbl28' => 'R2 TL84 blu Ctbl 28', + 'R2TL84BlueCtbl29' => 'R2 TL84 blu Ctbl 29', + 'R2TL84BlueCtbl30' => 'R2 TL84 blu Ctbl 30', + 'R2TL84BlueCtbl31' => 'R2 TL84 blu Ctbl 31', + 'R2TL84BlueStbl00' => 'R2 TL84 blu Stbl 00', + 'R2TL84BlueStbl01' => 'R2 TL84 blu Stbl 01', + 'R2TL84BlueStbl02' => 'R2 TL84 blu Stbl 02', + 'R2TL84BlueStbl03' => 'R2 TL84 blu Stbl 03', + 'R2TL84BlueStbl04' => 'R2 TL84 blu Stbl 04', + 'R2TL84BlueStbl05' => 'R2 TL84 blu Stbl 05', + 'R2TL84BlueStbl06' => 'R2 TL84 blu Stbl 06', + 'R2TL84BlueStbl07' => 'R2 TL84 blu Stbl 07', + 'R2TL84BlueStbl08' => 'R2 TL84 blu Stbl 08', + 'R2TL84BlueStbl09' => 'R2 TL84 blu Stbl 09', + 'R2TL84BlueStbl10' => 'R2 TL84 blu Stbl 10', + 'R2TL84BlueStbl11' => 'R2 TL84 blu Stbl 11', + 'R2TL84BlueStbl12' => 'R2 TL84 blu Stbl 12', + 'R2TL84BlueStbl13' => 'R2 TL84 blu Stbl 13', + 'R2TL84BlueStbl14' => 'R2 TL84 blu Stbl 14', + 'R2TL84BlueStbl15' => 'R2 TL84 blu Stbl 15', + 'R2TL84BlueStbl16' => 'R2 TL84 blu Stbl 16', + 'R2TL84BlueStbl17' => 'R2 TL84 blu Stbl 17', + 'R2TL84BlueStbl18' => 'R2 TL84 blu Stbl 18', + 'R2TL84BlueStbl19' => 'R2 TL84 blu Stbl 19', + 'R2TL84BlueStbl20' => 'R2 TL84 blu Stbl 20', + 'R2TL84BlueStbl21' => 'R2 TL84 blu Stbl 21', + 'R2TL84BlueStbl22' => 'R2 TL84 blu Stbl 22', + 'R2TL84BlueStbl23' => 'R2 TL84 blu Stbl 23', + 'R2TL84BlueStbl24' => 'R2 TL84 blu Stbl 24', + 'R2TL84BlueStbl25' => 'R2 TL84 blu Stbl 25', + 'R2TL84BlueStbl26' => 'R2 TL84 blu Stbl 26', + 'R2TL84BlueStbl27' => 'R2 TL84 blu Stbl 27', + 'R2TL84BlueStbl28' => 'R2 TL84 blu Stbl 28', + 'R2TL84BlueStbl29' => 'R2 TL84 blu Stbl 29', + 'R2TL84BlueStbl30' => 'R2 TL84 blu Stbl 30', + 'R2TL84BlueStbl31' => 'R2 TL84 blu Stbl 31', + 'R2TL84GreenCtbl00' => 'R2 TL84 verde Ctbl 00', + 'R2TL84GreenCtbl01' => 'R2 TL84 verde Ctbl 01', + 'R2TL84GreenCtbl02' => 'R2 TL84 verde Ctbl 02', + 'R2TL84GreenCtbl03' => 'R2 TL84 verde Ctbl 03', + 'R2TL84GreenCtbl04' => 'R2 TL84 verde Ctbl 04', + 'R2TL84GreenCtbl05' => 'R2 TL84 verde Ctbl 05', + 'R2TL84GreenCtbl06' => 'R2 TL84 verde Ctbl 06', + 'R2TL84GreenCtbl07' => 'R2 TL84 verde Ctbl 07', + 'R2TL84GreenCtbl08' => 'R2 TL84 verde Ctbl 08', + 'R2TL84GreenCtbl09' => 'R2 TL84 verde Ctbl 09', + 'R2TL84GreenCtbl10' => 'R2 TL84 verde Ctbl 10', + 'R2TL84GreenCtbl11' => 'R2 TL84 verde Ctbl 11', + 'R2TL84GreenCtbl12' => 'R2 TL84 verde Ctbl 12', + 'R2TL84GreenCtbl13' => 'R2 TL84 verde Ctbl 13', + 'R2TL84GreenCtbl14' => 'R2 TL84 verde Ctbl 14', + 'R2TL84GreenCtbl15' => 'R2 TL84 verde Ctbl 15', + 'R2TL84GreenCtbl16' => 'R2 TL84 verde Ctbl 16', + 'R2TL84GreenCtbl17' => 'R2 TL84 verde Ctbl 17', + 'R2TL84GreenCtbl18' => 'R2 TL84 verde Ctbl 18', + 'R2TL84GreenCtbl19' => 'R2 TL84 verde Ctbl 19', + 'R2TL84GreenCtbl20' => 'R2 TL84 verde Ctbl 20', + 'R2TL84GreenCtbl21' => 'R2 TL84 verde Ctbl 21', + 'R2TL84GreenCtbl22' => 'R2 TL84 verde Ctbl 22', + 'R2TL84GreenCtbl23' => 'R2 TL84 verde Ctbl 23', + 'R2TL84GreenCtbl24' => 'R2 TL84 verde Ctbl 24', + 'R2TL84GreenCtbl25' => 'R2 TL84 verde Ctbl 25', + 'R2TL84GreenCtbl26' => 'R2 TL84 verde Ctbl 26', + 'R2TL84GreenCtbl27' => 'R2 TL84 verde Ctbl 27', + 'R2TL84GreenCtbl28' => 'R2 TL84 verde Ctbl 28', + 'R2TL84GreenCtbl29' => 'R2 TL84 verde Ctbl 29', + 'R2TL84GreenCtbl30' => 'R2 TL84 verde Ctbl 30', + 'R2TL84GreenCtbl31' => 'R2 TL84 verde Ctbl 31', + 'R2TL84GreenStbl00' => 'R2 TL84 verde Stbl 00', + 'R2TL84GreenStbl01' => 'R2 TL84 verde Stbl 01', + 'R2TL84GreenStbl02' => 'R2 TL84 verde Stbl 02', + 'R2TL84GreenStbl03' => 'R2 TL84 verde Stbl 03', + 'R2TL84GreenStbl04' => 'R2 TL84 verde Stbl 04', + 'R2TL84GreenStbl05' => 'R2 TL84 verde Stbl 05', + 'R2TL84GreenStbl06' => 'R2 TL84 verde Stbl 06', + 'R2TL84GreenStbl07' => 'R2 TL84 verde Stbl 07', + 'R2TL84GreenStbl08' => 'R2 TL84 verde Stbl 08', + 'R2TL84GreenStbl09' => 'R2 TL84 verde Stbl 09', + 'R2TL84GreenStbl10' => 'R2 TL84 verde Stbl 10', + 'R2TL84GreenStbl11' => 'R2 TL84 verde Stbl 11', + 'R2TL84GreenStbl12' => 'R2 TL84 verde Stbl 12', + 'R2TL84GreenStbl13' => 'R2 TL84 verde Stbl 13', + 'R2TL84GreenStbl14' => 'R2 TL84 verde Stbl 14', + 'R2TL84GreenStbl15' => 'R2 TL84 verde Stbl 15', + 'R2TL84GreenStbl16' => 'R2 TL84 verde Stbl 16', + 'R2TL84GreenStbl17' => 'R2 TL84 verde Stbl 17', + 'R2TL84GreenStbl18' => 'R2 TL84 verde Stbl 18', + 'R2TL84GreenStbl19' => 'R2 TL84 verde Stbl 19', + 'R2TL84GreenStbl20' => 'R2 TL84 verde Stbl 20', + 'R2TL84GreenStbl21' => 'R2 TL84 verde Stbl 21', + 'R2TL84GreenStbl22' => 'R2 TL84 verde Stbl 22', + 'R2TL84GreenStbl23' => 'R2 TL84 verde Stbl 23', + 'R2TL84GreenStbl24' => 'R2 TL84 verde Stbl 24', + 'R2TL84GreenStbl25' => 'R2 TL84 verde Stbl 25', + 'R2TL84GreenStbl26' => 'R2 TL84 verde Stbl 26', + 'R2TL84GreenStbl27' => 'R2 TL84 verde Stbl 27', + 'R2TL84GreenStbl28' => 'R2 TL84 verde Stbl 28', + 'R2TL84GreenStbl29' => 'R2 TL84 verde Stbl 29', + 'R2TL84GreenStbl30' => 'R2 TL84 verde Stbl 30', + 'R2TL84GreenStbl31' => 'R2 TL84 verde Stbl 31', + 'R2TL84Height' => 'R2 TL84 altezza', + 'R2TL84Intervals' => 'R2 TL84 intervalli', + 'R2TL84RedCtbl00' => 'R2 TL84 rosso Ctbl 00', + 'R2TL84RedCtbl01' => 'R2 TL84 rosso Ctbl 01', + 'R2TL84RedCtbl02' => 'R2 TL84 rosso Ctbl 02', + 'R2TL84RedCtbl03' => 'R2 TL84 rosso Ctbl 03', + 'R2TL84RedCtbl04' => 'R2 TL84 rosso Ctbl 04', + 'R2TL84RedCtbl05' => 'R2 TL84 rosso Ctbl 05', + 'R2TL84RedCtbl06' => 'R2 TL84 rosso Ctbl 06', + 'R2TL84RedCtbl07' => 'R2 TL84 rosso Ctbl 07', + 'R2TL84RedCtbl08' => 'R2 TL84 rosso Ctbl 08', + 'R2TL84RedCtbl09' => 'R2 TL84 rosso Ctbl 09', + 'R2TL84RedCtbl10' => 'R2 TL84 rosso Ctbl 10', + 'R2TL84RedCtbl11' => 'R2 TL84 rosso Ctbl 11', + 'R2TL84RedCtbl12' => 'R2 TL84 rosso Ctbl 12', + 'R2TL84RedCtbl13' => 'R2 TL84 rosso Ctbl 13', + 'R2TL84RedCtbl14' => 'R2 TL84 rosso Ctbl 14', + 'R2TL84RedCtbl15' => 'R2 TL84 rosso Ctbl 15', + 'R2TL84RedCtbl16' => 'R2 TL84 rosso Ctbl 16', + 'R2TL84RedCtbl17' => 'R2 TL84 rosso Ctbl 17', + 'R2TL84RedCtbl18' => 'R2 TL84 rosso Ctbl 18', + 'R2TL84RedCtbl19' => 'R2 TL84 rosso Ctbl 19', + 'R2TL84RedCtbl20' => 'R2 TL84 rosso Ctbl 20', + 'R2TL84RedCtbl21' => 'R2 TL84 rosso Ctbl 21', + 'R2TL84RedCtbl22' => 'R2 TL84 rosso Ctbl 22', + 'R2TL84RedCtbl23' => 'R2 TL84 rosso Ctbl 23', + 'R2TL84RedCtbl24' => 'R2 TL84 rosso Ctbl 24', + 'R2TL84RedCtbl25' => 'R2 TL84 rosso Ctbl 25', + 'R2TL84RedCtbl26' => 'R2 TL84 rosso Ctbl 26', + 'R2TL84RedCtbl27' => 'R2 TL84 rosso Ctbl 27', + 'R2TL84RedCtbl28' => 'R2 TL84 rosso Ctbl 28', + 'R2TL84RedCtbl29' => 'R2 TL84 rosso Ctbl 29', + 'R2TL84RedCtbl30' => 'R2 TL84 rosso Ctbl 30', + 'R2TL84RedCtbl31' => 'R2 TL84 rosso Ctbl 31', + 'R2TL84RedStbl00' => 'R2 TL84 rosso Stbl 00', + 'R2TL84RedStbl01' => 'R2 TL84 rosso Stbl 01', + 'R2TL84RedStbl02' => 'R2 TL84 rosso Stbl 02', + 'R2TL84RedStbl03' => 'R2 TL84 rosso Stbl 03', + 'R2TL84RedStbl04' => 'R2 TL84 rosso Stbl 04', + 'R2TL84RedStbl05' => 'R2 TL84 rosso Stbl 05', + 'R2TL84RedStbl06' => 'R2 TL84 rosso Stbl 06', + 'R2TL84RedStbl07' => 'R2 TL84 rosso Stbl 07', + 'R2TL84RedStbl08' => 'R2 TL84 rosso Stbl 08', + 'R2TL84RedStbl09' => 'R2 TL84 rosso Stbl 09', + 'R2TL84RedStbl10' => 'R2 TL84 rosso Stbl 10', + 'R2TL84RedStbl11' => 'R2 TL84 rosso Stbl 11', + 'R2TL84RedStbl12' => 'R2 TL84 rosso Stbl 12', + 'R2TL84RedStbl13' => 'R2 TL84 rosso Stbl 13', + 'R2TL84RedStbl14' => 'R2 TL84 rosso Stbl 14', + 'R2TL84RedStbl15' => 'R2 TL84 rosso Stbl 15', + 'R2TL84RedStbl16' => 'R2 TL84 rosso Stbl 16', + 'R2TL84RedStbl17' => 'R2 TL84 rosso Stbl 17', + 'R2TL84RedStbl18' => 'R2 TL84 rosso Stbl 18', + 'R2TL84RedStbl19' => 'R2 TL84 rosso Stbl 19', + 'R2TL84RedStbl20' => 'R2 TL84 rosso Stbl 20', + 'R2TL84RedStbl21' => 'R2 TL84 rosso Stbl 21', + 'R2TL84RedStbl22' => 'R2 TL84 rosso Stbl 22', + 'R2TL84RedStbl23' => 'R2 TL84 rosso Stbl 23', + 'R2TL84RedStbl24' => 'R2 TL84 rosso Stbl 24', + 'R2TL84RedStbl25' => 'R2 TL84 rosso Stbl 25', + 'R2TL84RedStbl26' => 'R2 TL84 rosso Stbl 26', + 'R2TL84RedStbl27' => 'R2 TL84 rosso Stbl 27', + 'R2TL84RedStbl28' => 'R2 TL84 rosso Stbl 28', + 'R2TL84RedStbl29' => 'R2 TL84 rosso Stbl 29', + 'R2TL84RedStbl30' => 'R2 TL84 rosso Stbl 30', + 'R2TL84RedStbl31' => 'R2 TL84 rosso Stbl 31', + 'R2TL84Width' => 'R2 TL84 larghezza', + 'RAFVersion' => 'Versione RAF', + 'RGBCurveLimits' => 'Limiti curva RGB', + 'RGBCurvePoints' => 'Punti curva RGB', + 'RadialPosition' => 'Posizione radiale', + 'RandomIndexMetadata' => 'Indice casuale metadati', + 'RandomIndexMetadataV10' => 'Indice casuale metadati V10', + 'RangeFinder' => { + PrintConv => { + 'Off' => 'Spento', + }, + }, + 'RasterPadding' => { + PrintConv => { + 'Long Sector' => 'Settore lungo', + 'Long Word' => 'Parola lunga', + 'Sector' => 'Settore', + 'Word' => 'Parola', + }, + }, + 'RasterizedCaption' => 'Didascalia rasterizzata', + 'Rating' => { + Description => 'Valutazione', + PrintConv => { + 'Explicit' => 'Esplicito', + }, + }, + 'RatingPercent' => 'Valutazione percentuale', + 'RawAndJpgRecording' => { + Description => 'Registrazione raw e jpg', + PrintConv => { + 'Off' => 'Spento', + 'RAW (DNG, Best)' => 'RAW (DNG, migliore)', + 'RAW (DNG, Better)' => 'RAW (DNG, più buona)', + 'RAW (DNG, Good)' => 'RAW (DNG, buona)', + 'RAW (PEF, Best)' => 'RAW (PEF, migliore)', + 'RAW (PEF, Better)' => 'RAW (PEF, più buona)', + 'RAW (PEF, Good)' => 'RAW (PEF, buona)', + 'RAW+JPEG (DNG, Best)' => 'RAW+JPEG (DNG, migliore)', + 'RAW+JPEG (DNG, Better)' => 'RAW+JPEG (DNG, più buona)', + 'RAW+JPEG (DNG, Good)' => 'RAW+JPEG (DNG, buona)', + 'RAW+JPEG (PEF, Best)' => 'RAW+JPEG (PEF, migliore)', + 'RAW+JPEG (PEF, Better)' => 'RAW+JPEG (PEF, più buona)', + 'RAW+JPEG (PEF, Good)' => 'RAW+JPEG (PEF, buona)', + }, + }, + 'RawColorAdj' => { + PrintConv => { + 'Shot Settings' => 'Impostazioni scatto', + }, + }, + 'RawDataOffset' => 'Offset dati raw', + 'RawDataUniqueID' => 'ID unico dati raw', + 'RawDepth' => 'Profondità raw', + 'RawDevAutoGradation' => { + PrintConv => { + 'Off' => 'Spento', + }, + }, + 'RawDevEditStatus' => { + PrintConv => { + 'Original' => 'Originale', + }, + }, + 'RawDevNoiseReduction' => { + PrintConv => { + 'Noise Filter' => 'Filtro rumore', + 'Noise Reduction' => 'Riduzione rumore', + }, + }, + 'RawDevPMPictureTone' => { + PrintConv => { + 'Green' => 'Verde', + 'Purple' => 'Porpora', + 'Sepia' => 'Seppia', + }, + }, + 'RawDevPM_BWFilter' => { + PrintConv => { + 'Green' => 'Verde', + 'Orange' => 'Arancio', + 'Red' => 'Rosso', + 'Yellow' => 'Giallo', + }, + }, + 'RawDevPictureMode' => { + PrintConv => { + 'Sepia' => 'Seppia', + 'Vivid' => 'Vivace', + }, + }, + 'RawDevSettings' => { + PrintConv => { + 'Noise Reduction' => 'Riduzione rumore', + 'Saturation' => 'Saturazione', + 'Sharpness' => 'Nitidezza', + }, + }, + 'RawFile' => 'File raw', + 'RawFileName' => 'Nome file raw', + 'RawImageCenter' => 'Centro immagine raw', + 'RawImageDigest' => 'Sommario file raw', + 'RawImageFullSize' => 'Dimensione finale immagine raw', + 'RawImageHeight' => 'Altezza immagine raw', + 'RawImageMode' => 'Modo immagine raw', + 'RawImageSegmentation' => 'Segmentazione file raw', + 'RawImageSize' => 'Dimensione immagine raw', + 'RawImageWidth' => 'Larghezza immagine raw', + 'RawInfoVersion' => 'Info versione raw', + 'RawJpgHeight' => 'Altezza jpg raw', + 'RawJpgQuality' => { + Description => 'Qualità jpg raw', + PrintConv => { + 'Normal' => 'Normale', + }, + }, + 'RawJpgSize' => { + Description => 'Dimensione jpg raw', + PrintConv => { + 'Postcard' => 'Cartolina', + }, + }, + 'RawJpgWidth' => 'Larghezza jpg raw', + 'ReadStatus' => 'Stato lettura', + 'RecommendedExposureIndex' => 'Indice esposizione raccomandato', + 'RecordDisplay' => { + PrintConv => { + 'Horizontal' => 'Orizzontale', + }, + }, + 'RecordMode' => { + Description => 'Modo registrazione', + PrintConv => { + 'Aperture Priority' => 'Priorità diaframma', + 'Manual' => 'Manuale', + 'Program AE' => 'Programma AE', + 'Shutter Priority' => 'Priorità otturatore', + }, + }, + 'RecordShutterRelease' => { + PrintConv => { + 'Press start, press stop' => 'Premi start, premi stop', + }, + }, + 'RecordedFormat' => 'Formato registrato', + 'RecordingDates' => 'Date registrazioni', + 'RecordingLabelName' => 'Nome etichetta registrazione', + 'RecordingMode' => { + Description => 'Modo registrazione', + PrintConv => { + 'Landscape' => 'Orizzontale', + 'Manual' => 'Manuale', + 'Portrait' => 'Verticale', + }, + }, + 'RecordingTime' => 'Tempo registrazione', + 'RedAdjust' => 'Correzione rosso', + 'RedBalance' => 'Bilanciamento del rosso', + 'RedCurveLimits' => 'Limiti curva rosso', + 'RedCurvePoints' => 'Punti curva rosso', + 'RedEyeCorrection' => { + Description => 'Correzione occhi rossi', + PrintConv => { + 'Off' => 'Spento', + }, + }, + 'RedEyeInfo' => 'Info occhi rossi', + 'RedEyeReduction' => { + Description => 'Riduzione occhi rossi', + PrintConv => { + 'Off' => 'Spento', + }, + }, + 'RedGain' => 'Guadagno rosso', + 'RedHue' => 'Tinta rosso', + 'RedMatrixColumn' => 'Colonna matrice rosso', + 'RedPaletteColorTableData' => 'Dati tabella tavolozza colori rosso', + 'RedPaletteColorTableDescriptor' => 'Descrittore tabella tavolozza colori rosso', + 'RedPrimary' => 'Rosso primario', + 'RedSample' => 'Campione rosso', + 'RedSaturation' => 'Saturazione rosso', + 'RedTRC' => 'Curva riproduzione tono rosso', + 'ReductionMatrix1' => 'Matrice di riduzione 1', + 'ReductionMatrix2' => 'Matrice di riduzione 2', + 'Reference' => 'Riferimento', + 'Reference1' => 'Riferimento 1', + 'Reference2' => 'Riferimento 2', + 'Reference3' => 'Riferimento 3', + 'Reference4' => 'Riferimento 4', + 'Reference5' => 'Riferimento 5', + 'Reference6' => 'Riferimento 6', + 'ReferenceBlackWhite' => 'Coppia valori riferimento di bianco e nero', + 'ReferenceBlock' => 'Blocco di riferimento', + 'ReferenceChannels' => 'Canali di riferimento', + 'ReferenceCoordinates' => 'Coordinate di riferimento', + 'ReferenceDate' => 'Data di riferimento', + 'ReferenceNumber' => 'Numero di riferimento', + 'ReferencePixelPhysicalValueX' => 'Valore fisico valore X pixel di riferimento', + 'ReferencePixelPhysicalValueY' => 'Valore fisico valore Y pixel di riferimento', + 'ReferencePixelX0' => 'Pixel X0 di riferimento', + 'ReferencePixelY0' => 'Pixel Y0 di riferimento', + 'ReferencePriority' => 'Priorità riferimento', + 'ReferenceService' => 'Riferimento di servizio', + 'ReferenceToRecordedSound' => 'Riferimento a suono registrato', + 'ReferenceVirtual' => 'Riferimento virtuale', + 'Refresh' => 'Aggiorna', + 'RegionCode' => 'Codice regione', + 'RegionInfo' => 'Info regione', + 'RegionList' => 'Elenco regioni', + 'RegionName' => 'Nome regione', + 'RegionOfResidence' => 'Regione di residenza', + 'RelatedImageFileFormat' => 'Formato file immagine correlato', + 'RelatedImageHeight' => 'Numero delle righe dei dati immagine', + 'RelatedImageWidth' => 'Larghezza immagine correlata', + 'RelatedSoundFile' => 'File audio relativo', + 'Relation' => 'Relazione', + 'RelativeVolumeAdjustment' => 'Correzione relativa volume', + 'ReleaseButtonToUseDial' => { + PrintConv => { + 'Yes' => 'Sì', + }, + }, + 'ReleaseDate' => 'Data di rilascio', + 'ReleaseMode' => { + PrintConv => { + 'Normal' => 'Normale', + 'n/a' => 'n/d', + }, + }, + 'ReleaseTime' => 'Ora di rilascio', + 'RenderingIntent' => { + PrintConv => { + 'ICC-Absolute Colorimetric' => 'Colorimetrico Assoluto', + 'Media-Relative Colorimetric' => 'Colorimetrico Relativo', + 'Perceptual' => 'Percentuale', + 'Saturation' => 'Saturazione', + }, + }, + 'RenderingType3D' => 'Tipo resa 3D', + 'RepeatingFlashCount' => 'Conteggio ripetizione flash', + 'RepeatingFlashOutput' => 'Uscita ripetizione flash', + 'RepeatingFlashRate' => 'Frequenza ripetizione flash', + 'ReplyTo' => 'Rispondi a', + 'Resaved' => { + PrintConv => { + 'Yes' => 'Sì', + }, + }, + 'Reserved' => 'Riservato', + 'Reserved1' => 'Riservato 1', + 'Resolution' => 'Risoluzione', + 'ResolutionMode' => 'Modo risoluzione', + 'ResolutionUnit' => { + Description => 'Unità risoluzione', + PrintConv => { + 'None' => 'Nessuno', + 'inches' => 'Pollici', + }, + }, + 'ResonantNucleus' => 'Nucleo risonante', + 'ResourceID' => 'ID risorsa', + 'ResourceType' => 'Tipo risorsa', + 'Resources' => 'Risorse', + 'ResourcesNeeded' => 'Risorse richieste', + 'Restrictions' => 'Restrizioni', + 'ResultsID' => 'ID risultati', + 'RetouchHistory' => { + Description => 'Cronologia ritocco', + PrintConv => { + 'Fisheye' => 'Fish-eye', + 'None' => 'Nessuno', + 'Quick Retouch' => 'Ritocco veloce', + 'Red Eye' => 'Occhi rossi', + 'Red Intensifier' => 'Intensificatore rosso', + 'Resize' => 'Ridimensione', + 'Sepia' => 'Seppia', + 'Straighten' => 'Raddrizza', + }, + }, + 'RetouchInfo' => 'Info ritocco', + 'Reuse' => { + Description => 'Riutilizza', + PrintConv => { + 'Not Applicable' => 'Non applicabile', + }, + }, + 'ReverseIndicators' => 'Inverti indicatori', + 'ReversedByteOrder' => 'Ordine byte invertito', + 'Revision' => 'Revisione', + 'RevisionDate' => 'Data revisione', + 'RevisionNumber' => 'Numero revisione', + 'RicohDate' => 'Data Ricoh', + 'RicohImageHeight' => 'Altezza immagine Ricoh', + 'RicohImageWidth' => 'Larghezza immagine Ricoh', + 'RicohRDC2' => 'RDC2 Ricoh', + 'RightAscension' => 'Ascensione retta', + 'Robots' => 'Robot', + 'RoleName' => 'Nome ruolo', + 'RoomNumber' => 'Numero stanza', + 'RoomOrSuiteName' => 'Numero stanza/suite', + 'RootFormatVersion' => 'Versione formato radice', + 'Rotation' => { + Description => 'Rotazione', + PrintConv => { + 'Horizontal' => 'Orizzontale', + 'Horizontal (Normal)' => 'Orizzontale (normale)', + 'Horizontal (normal)' => 'Orizzontale (normale)', + 'Rotate 180' => 'Ruota di 180°', + 'Rotate 270 CW' => 'Ruota di 270° in senso orario', + 'Rotate 90 CW' => 'Ruota di 90° senso orario', + 'Rotated 180' => 'Ruotato di 180°', + 'Rotated 270 CW' => 'Ruotato di 270° in senso orario', + 'Rotated 90 CW' => 'Ruotato di 90° in senso orario', + }, + }, + 'RotationAngle' => 'Angolo rotazione', + 'RotationDirection' => 'Direzione rotazione', + 'RowsPerStrip' => 'Righe per striscia', + 'RunWindow' => { + PrintConv => { + 'Normal' => 'Normale', + 'Restore' => 'Ripristina', + }, + }, + 'SEMInfo' => 'Info SEM', + 'SPIFFVersion' => 'Versione SPIFF', + 'SRAWQuality' => { + PrintConv => { + 'n/a' => 'n/d', + }, + }, + 'SRActive' => { + PrintConv => { + 'Yes' => 'Sì', + }, + }, + 'SRGBRendering' => { + PrintConv => { + 'Saturation' => 'Saturazione', + }, + }, + 'SRResult' => { + PrintConv => { + 'Not ready' => 'Non pronto', + }, + }, + 'SVGVersion' => 'Versione SVG', + 'SafetyShiftInAvOrTv' => { + PrintConv => { + 'Enable' => 'Abilita', + }, + }, + 'SampleBits' => 'Bit campione', + 'SampleFormat' => { + Description => 'Formato campioni', + PrintConv => { + 'Complex float' => 'Virgola mobile immaginario', + 'Complex int' => 'Intero immaginario', + 'Float' => 'Virgola mobile', + 'Signed' => 'Con segno', + 'Undefined' => 'Non definito', + 'Unsigned' => 'Senza segno', + }, + }, + 'SampleIndex' => 'Indice campione', + 'SampleRate' => 'Frequenza campionamento', + 'SampleRate2' => 'Frequenza campionamento 2', + 'SampleSize' => 'Dimensione campione', + 'SampleSizes' => 'Dimensioni campione', + 'SampleStructure' => 'Struttura d\'esempio', + 'SampleText' => 'Testo d\'esempio', + 'SamplesPerPixel' => 'Campioni per pixel', + 'SamplesPerPixelUsed' => 'Campioni per pixel', + 'SamplingFrequency' => 'Frequenza campionamento', + 'Saturation' => { + Description => 'Saturazione', + PrintConv => { + 'High' => 'Alta', + 'Low' => 'Basso', + 'None' => 'Nessuno', + 'None (B&W)' => 'Nessuno (B&N)', + 'Normal' => 'Normale', + 'Vivid' => 'Vivace', + }, + }, + 'SaturationAdj' => 'Correzione saturazione', + 'SaturationFaithful' => { + PrintConv => { + 'n/a' => 'n/d', + }, + }, + 'SaturationLandscape' => { + PrintConv => { + 'n/a' => 'n/d', + }, + }, + 'SaturationMonochrome' => { + PrintConv => { + 'n/a' => 'n/d', + }, + }, + 'SaturationNeutral' => { + PrintConv => { + 'n/a' => 'n/d', + }, + }, + 'SaturationPortrait' => { + PrintConv => { + 'n/a' => 'n/d', + }, + }, + 'SaturationStandard' => { + PrintConv => { + 'n/a' => 'n/d', + }, + }, + 'SaturationUnknown' => { + PrintConv => { + 'n/a' => 'n/d', + }, + }, + 'SaturationUserDef1' => { + PrintConv => { + 'n/a' => 'n/d', + }, + }, + 'SaturationUserDef2' => { + PrintConv => { + 'n/a' => 'n/d', + }, + }, + 'SaturationUserDef3' => { + PrintConv => { + 'n/a' => 'n/d', + }, + }, + 'ScanImageEnhancer' => { + PrintConv => { + 'Off' => 'Spento', + }, + }, + 'ScanningDirection' => { + PrintConv => { + 'R-L, Bottom-Top' => 'D-S, basso-alto', + 'R-L, Top-Bottom' => 'D-S, alto-basso', + }, + }, + 'Scene' => 'Scena', + 'SceneArea' => 'Area scena', + 'SceneCaptureType' => { + Description => 'Tipo cattura scena', + PrintConv => { + 'Landscape' => 'Orizzontale', + 'Night' => 'Notte', + 'Portrait' => 'Verticale', + }, + }, + 'SceneMode' => { + Description => 'Modo scena', + PrintConv => { + '3D Sweep Panorama' => '3D', + 'Anti Motion Blur' => 'Riduz. sfocat. movim.', + 'Aperture Priority' => 'Priorità diaframma', + 'Auto' => 'Automatico', + 'Children' => 'Bambini', + 'Cont. Priority AE' => 'AE prior. avan.cont.', + 'Fireworks' => 'Fuochi artificiali', + 'Handheld Night Shot' => 'Foto nott. senza trepp.', + 'Landscape' => 'Orizzontale', + 'Manual' => 'Manuale', + 'Night Portrait' => 'Rit. notturno', + 'Night Scene' => 'Visione notturna', + 'Night View/Portrait' => 'Visione/Ritratto notturni', + 'Normal' => 'Normale', + 'Off' => 'Spento', + 'Portrait' => 'Verticale', + 'Program' => 'Programma', + 'Scenery' => 'Paesaggio', + 'Shutter Priority' => 'Priorità otturatore', + 'Sports' => 'Evento sportivo', + 'Sunset' => 'Tramonto', + 'Sweep Panorama' => 'Panoramica ad arco', + 'Text' => 'Testo', + 'Vivid' => 'Vivace', + 'n/a' => 'n/d', + }, + }, + 'SceneModeUsed' => { + Description => 'Modo scena usato', + PrintConv => { + 'Aperture Priority' => 'Priorità diaframma', + 'Children' => 'Bambini', + 'Fireworks' => 'Fuochi artificiali', + 'Landscape' => 'Orizzontale', + 'Manual' => 'Manuale', + 'Portrait' => 'Verticale', + 'Program' => 'Programma', + 'Shutter Priority' => 'Priorità otturatore', + 'Sunset' => 'Tramonto', + 'Text' => 'Testo', + }, + }, + 'SceneNumber' => 'Numero scena', + 'SceneSelect' => { + PrintConv => { + 'Night' => 'Scena notturna', + 'Off' => 'Spento', + }, + }, + 'SceneType' => { + Description => 'Tipo scena', + PrintConv => { + 'Directly photographed' => 'Immagine fotografata direttamente', + }, + }, + 'School' => 'Scuola', + 'ScreenTips' => { + PrintConv => { + 'Off' => 'Spento', + }, + }, + 'Section' => 'Sezione', + 'SectorSize' => 'Dimensione settore', + 'Security' => { + Description => 'Sicurezza', + PrintConv => { + 'None' => 'Nessuno', + }, + }, + 'SecurityClassification' => { + Description => 'Classificazione sicurezza', + PrintConv => { + 'Confidential' => 'Confidenziale', + 'Restricted' => 'Riservato', + 'Secret' => 'Segreto', + 'Top Secret' => 'Massima segretezza', + 'Unclassified' => 'Non classificato', + }, + }, + 'SelectAFAreaSelectMode' => { + PrintConv => { + 'Enable' => 'Abilita', + }, + }, + 'SelectableAFPoint' => { + PrintConv => { + '11 points' => '11 punti', + }, + }, + 'Selected' => 'Selezionato', + 'SelfTimer' => { + Description => 'Autoscatto', + PrintConv => { + 'Off' => 'Spento', + }, + }, + 'SelfTimer2' => 'Autoscatto 2', + 'SelfTimerInterval' => 'Intervallo autoscatto', + 'SelfTimerMode' => 'Modo autoscatto', + 'SelfTimerTime' => 'Tempo autoscatto', + 'SenderAddress' => 'Indirizzo mittente', + 'SenderName' => 'Nome mittente', + 'SensingMethod' => { + Description => 'Metodo misurazione esposimetrica', + PrintConv => { + 'Color sequential area' => 'Area sequenziale a colori', + 'Color sequential linear' => 'Lineare sequenziale a colori', + 'Not defined' => 'Non definito', + 'One-chip color area' => 'Sensore area a colori a un chip', + 'Three-chip color area' => 'Sensore area a colori a tre chip', + 'Trilinear' => 'Trilineare', + 'Two-chip color area' => 'Sensore area a colori a due chip', + }, + }, + 'Sensitivity' => 'Sensibilità', + 'SensitivityCalibrated' => 'Sensibilità calibrata', + 'SensitivitySteps' => { + Description => 'Passi sensibilità', + PrintConv => { + '1 EV Steps' => 'Step 1 EV', + }, + }, + 'SensitivityType' => { + Description => 'Tipo sensibilità', + PrintConv => { + 'ISO Speed' => 'Velocità ISO', + 'Recommended Exposure Index' => 'Indice esposizione raccomandato', + 'Recommended Exposure Index and ISO Speed' => 'Indice esposizione raccomandato e velocità ISO', + 'Standard Output Sensitivity' => 'Sensibilità predefinita uscita', + 'Standard Output Sensitivity and ISO Speed' => 'Sensibilità predefinita uscita e velocità ISO', + 'Standard Output Sensitivity and Recommended Exposure Index' => 'Sensibilità predefinita uscita e indice esposizione consigliato', + 'Standard Output Sensitivity, Recommended Exposure Index and ISO Speed' => 'Sensibilità predefinita uscita, indice esposizione consigliato e velocità ISO', + 'Unknown' => 'Sconosciuto', + }, + }, + 'SensorAreas' => 'Aree sensore', + 'SensorCleaning' => { + PrintConv => { + 'Enable' => 'Abilita', + }, + }, + 'SensorHeight' => 'Altezza sensore', + 'SensorID' => 'ID sensore', + 'SensorLeftBorder' => 'Bordo sinistro sensore', + 'SensorMode' => 'Modo sensore', + 'SensorPixelSize' => 'Dimensione pixel sensore', + 'SensorRedLevel' => 'Livello rosso sensore', + 'SensorSize' => 'Dimensione sensore', + 'SensorTemperature' => 'Temperatura sensore', + 'SensorTopBorder' => 'Bordo superiore sensore', + 'SensorType' => 'Tipo sensore', + 'SensorTypeCode' => 'Codice tipo sensore', + 'SensorWidth' => 'Larghezza sensore', + 'Sequence' => 'Sequenza', + 'SequenceName' => 'Nome sequenza', + 'SequenceNumber' => { + Description => 'Numero sequenza', + PrintConv => { + 'n/a' => 'n/d', + }, + }, + 'SequenceShotInterval' => { + PrintConv => { + '10 frames/s' => '10 frame/s', + }, + }, + 'SequentialShot' => { + PrintConv => { + 'None' => 'Nessuno', + }, + }, + 'SerialNumber' => 'Numero di serie', + 'SerialNumberFormat' => { + Description => 'Formato numero di serie', + PrintConv => { + 'Format 1' => 'Formato 1', + 'Format 2' => 'Formato 2', + }, + }, + 'ServiceID' => 'ID servizio', + 'ServiceIdentifier' => 'Identificativo servizio', + 'ServiceOrganizationName' => 'Nome organizzazione servizio', + 'SetButtonCrossKeysFunc' => { + PrintConv => { + 'Normal' => 'Normale', + }, + }, + 'SetButtonWhenShooting' => { + PrintConv => { + 'Change ISO speed' => 'Cambia velocità ISO', + 'Change parameters' => 'Cambia parametri', + 'ISO speed' => 'Velocità ISO', + 'Normal (disabled)' => 'Normale (disabilitato)', + 'White balance' => 'Bilanciamento del bianco', + }, + }, + 'SetCookie' => 'Imposta cookie', + 'SetFunctionWhenShooting' => { + PrintConv => { + 'Change Parameters' => 'Cambia parametri', + }, + }, + 'SetInfo' => 'Imposta info', + 'SetSubtitle' => 'Imposta sottotitoli', + 'ShadingCompensation' => { + Description => 'Compensazione ombreggiatura', + PrintConv => { + 'Off' => 'Spento', + }, + }, + 'ShadingCompensation2' => { + Description => 'Compensazione ombreggiatura 2', + PrintConv => { + 'Off' => 'Spento', + }, + }, + 'Shadow' => 'Ombra', + 'ShadowCorrection' => { + PrintConv => { + 'Normal' => 'Normale', + 'Off' => 'Spento', + 'Strong' => 'Forte', + }, + }, + 'ShadowScale' => 'Scala ombre', + 'Shadows' => 'Ombre', + 'ShakeReduction' => { + PrintConv => { + 'Off' => 'Spento', + 'Off (4)' => 'Spento (4)', + }, + }, + 'SharedData' => 'Dati condivisi', + 'Sharpening' => { + PrintConv => { + 'Low' => 'Basso', + 'Normal' => 'Normale', + 'Off' => 'Spento', + }, + }, + 'Sharpness' => { + Description => 'Nitidezza', + PrintConv => { + 'Hard' => 'Forte', + 'Normal' => 'Normale', + 'Soft' => 'Leggera', + 'n/a' => 'n/d', + }, + }, + 'SharpnessFaithful' => { + PrintConv => { + 'n/a' => 'n/d', + }, + }, + 'SharpnessFrequency' => { + PrintConv => { + 'Low' => 'Basso', + 'n/a' => 'n/d', + }, + }, + 'SharpnessLandscape' => { + PrintConv => { + 'n/a' => 'n/d', + }, + }, + 'SharpnessMonochrome' => { + PrintConv => { + 'n/a' => 'n/d', + }, + }, + 'SharpnessNeutral' => { + PrintConv => { + 'n/a' => 'n/d', + }, + }, + 'SharpnessPortrait' => { + PrintConv => { + 'n/a' => 'n/d', + }, + }, + 'SharpnessStandard' => { + PrintConv => { + 'n/a' => 'n/d', + }, + }, + 'SharpnessUnknown' => { + PrintConv => { + 'n/a' => 'n/d', + }, + }, + 'SharpnessUserDef1' => { + PrintConv => { + 'n/a' => 'n/d', + }, + }, + 'SharpnessUserDef2' => { + PrintConv => { + 'n/a' => 'n/d', + }, + }, + 'SharpnessUserDef3' => { + PrintConv => { + 'n/a' => 'n/d', + }, + }, + 'ShootingMode' => { + Description => 'Modo scatto', + PrintConv => { + 'Aperture Priority' => 'Priorità diaframma', + 'Fireworks' => 'Fuochi artificiali', + 'Manual' => 'Manuale', + 'Normal' => 'Normale', + 'Portrait' => 'Verticale', + 'Program' => 'Programma', + 'Scenery' => 'Paesaggio', + 'Shutter Priority' => 'Priorità otturatore', + 'Sunset' => 'Tramonto', + }, + }, + 'ShootingModeSetting' => { + Description => 'Impostazione modo scatto', + PrintConv => { + 'Self-timer' => 'Autoscatto', + }, + }, + 'ShortComment' => 'Commento breve', + 'ShortDescription' => 'Descrizione breve', + 'ShortDocumentID' => 'ID documento breve', + 'ShortReleaseTimeLag' => { + PrintConv => { + 'Enable' => 'Abilita', + }, + }, + 'ShotComment' => 'Commento scatto', + 'ShotCommentKind' => 'Tipo commento scatto', + 'ShotDate' => 'Data scatto', + 'ShotDay' => 'Giorno scatto', + 'ShotDescription' => 'Descrizione scatto', + 'ShotDuration' => 'Durata scatto', + 'ShotInfoVersion' => 'Info versione scatto', + 'ShotList' => 'Elenco scatti', + 'ShotLocation' => 'Posizione scatto', + 'ShotLocationSets' => 'Insiemi posizione scatto', + 'ShotName' => 'Nome scatto', + 'ShotNumber' => 'Numero scatto', + 'ShotSize' => 'Dimensione scatto', + 'ShutterCount' => 'Conteggio scatti', + 'ShutterMode' => { + PrintConv => { + 'Aperture Priority' => 'Priorità diaframma', + }, + }, + 'ShutterReleaseButtonAE-L' => { + PrintConv => { + 'Off' => 'Spento', + }, + }, + 'ShutterReleaseNoCFCard' => { + PrintConv => { + 'Yes' => 'Sì', + }, + }, + 'ShutterSpeed' => 'Tempo esposizione', + 'ShutterSpeedRange' => { + PrintConv => { + 'Enable' => 'Abilita', + }, + }, + 'ShutterSpeedValue' => 'Velocità otturatore', + 'SideNumber' => 'Numero lato', + 'Sidebars' => 'Barre laterali', + 'SimilarityIndex' => 'Indice di Somiglianza', + 'SingleFrameBracketing' => { + PrintConv => { + 'Low' => 'Basso', + }, + }, + 'Site' => 'Sito', + 'Size' => 'Dimensioni', + 'SlideShow' => { + PrintConv => { + 'Yes' => 'Sì', + }, + }, + 'SlowShutter' => { + PrintConv => { + 'None' => 'Nessuno', + 'Off' => 'Spento', + 'n/a' => 'n/d', + }, + }, + 'SlowSync' => { + PrintConv => { + 'Off' => 'Spento', + }, + }, + 'SmartRange' => { + PrintConv => { + 'Off' => 'Spento', + }, + }, + 'SmileShutter' => { + PrintConv => { + 'Off' => 'Spento', + }, + }, + 'Smoothness' => 'Arrotondamento', + 'Software' => 'Software utilizzato', + 'Source' => 'Origine', + 'SourceTitle' => 'Titolo fonte', + 'SourceTrackID' => 'ID traccia fonte', + 'SourceTrackIDs' => 'ID traccia fonte', + 'SourceType' => 'Tipo fonte', + 'SourceURL' => 'URL fonte', + 'SourceValue' => 'Valore fonte', + 'SpatialFrequencyResponse' => 'Risposta in frequenza spaziale', + 'SpecialBuild' => 'Compilazione speciale', + 'SpecialEffectMode' => { + PrintConv => { + 'Off' => 'Spento', + }, + }, + 'SpecialEffectSetting' => { + PrintConv => { + 'Off' => 'Spento', + }, + }, + 'SpecialEffectsOpticalFilter' => { + PrintConv => { + 'None' => 'Nessuno', + 'Star' => 'Stella', + }, + }, + 'SpecialInstructions' => 'Istruzioni', + 'SpectralSensitivity' => 'Sensibilità spettro', + 'Speed' => { + Description => 'Velocità', + PrintConv => { + 'Fast' => 'Veloce', + 'Medium' => 'Medio', + 'Slow' => 'Lento', + }, + }, + 'SpotMeteringMode' => { + PrintConv => { + 'Center' => 'Centro', + }, + }, + 'StandardOutputSensitivity' => 'Sensibilità predefinita uscita', + 'StartTime' => 'Ora inizio', + 'State' => 'Stato', + 'StorageMethod' => { + PrintConv => { + 'Linear' => 'Lineare', + }, + }, + 'StreamType' => { + PrintConv => { + 'File Transfer' => 'Trasferimento file', + 'Text' => 'Testo', + }, + }, + 'StretchMode' => { + PrintConv => { + 'Fixed length' => 'Lunghezza fissa', + }, + }, + 'StripByteCounts' => 'Byte per striscia', + 'StripOffsets' => 'Offset striscia', + 'StripRowCounts' => 'Numero righe striscia', + 'Sub-location' => 'Località', + 'SubSecCreateDate' => 'Data di creazione', + 'SubSecDateTimeOriginal' => 'Data/ora originali', + 'SubSecModifyDate' => 'Data modifica', + 'SubSecTime' => 'Sottosecondi ora', + 'SubSecTimeDigitized' => 'Sottosecondi ora digitalizzazione', + 'SubSecTimeOriginal' => 'Sottosecondi ora originale', + 'SubTileBlockSize' => 'Dimensione blocco sotto-tasselli', + 'SubfileType' => { + Description => 'Tipo sotto-file', + PrintConv => { + 'Full-resolution Image' => 'Immagine con risoluzione originale', + 'Reduced-resolution image' => 'Immagine a risoluzione ridotta', + 'Single page of multi-page image' => 'Singola pagina di un\'immagine multi-pagina', + 'Single page of multi-page reduced-resolution image' => 'Singola pagina di un\'immagine multi-pagina a risoluzione ridotta', + 'TIFF-FX mixed raster content' => 'Contenuto raster misto TIFF-FX', + 'TIFF/IT final page' => 'Pagina finale TIFF/IT', + 'Thumbnail image' => 'Miniatura', + 'Transparency mask' => 'Maschera trasparenza', + 'Transparency mask of multi-page image' => 'Maschera trasparenza di immagine multi-pagina', + 'Transparency mask of reduced-resolution image' => 'Maschera trasparenza di immagine a risoluzione ridotta', + 'Transparency mask of reduced-resolution multi-page image' => 'Maschera trasparenza di immagine multi-pagina a risoluzione ridotta', + 'invalid' => 'non valido', + }, + }, + 'SubimageColor' => { + PrintConv => { + 'RGB (uncalibrated)' => 'RGB (non calibrato)', + 'RGB with Opacity' => 'RGB con opacità', + 'RGB with Opacity (uncalibrated)' => 'RGB con opacità (non calibrato)', + }, + }, + 'Subject' => 'Soggetto', + 'SubjectArea' => 'Area soggetto', + 'SubjectCode' => 'Codice sottetto', + 'SubjectDistance' => 'Distanza soggetto', + 'SubjectDistanceRange' => { + Description => 'Intervallo distanza soggetto', + PrintConv => { + 'Close' => 'Vicino', + 'Distant' => 'Lontano', + 'Unknown' => 'Sconosciuto', + }, + }, + 'SubjectLocation' => 'Posizione soggetto', + 'SubjectName' => 'Nome soggetto', + 'SubjectProgram' => { + PrintConv => { + 'None' => 'Nessuno', + 'Portrait' => 'Verticale', + 'Sunset' => 'Tramonto', + 'Text' => 'Testo', + }, + }, + 'SubjectReference' => 'Codice Soggetto', + 'SubjectUnits' => { + PrintConv => { + 'radians' => 'Radianti', + }, + }, + 'Subsystem' => { + Description => 'Sottosistema', + PrintConv => { + 'EFI ROM' => 'ROM EFI', + 'EFI application' => 'Applicazione EFI', + 'EFI boot service' => 'Servizio di avvio EFI', + 'EFI runtime driver' => 'Driver a runtine EFI', + 'Native' => 'Nativo', + 'OS/2 command line' => 'Linea di comando OS/2', + 'POSIX command line' => 'Linea di comando POSIX', + 'Unknown' => 'Sconosciuto', + 'Windows command line' => 'Linea di comando Windows', + }, + }, + 'SubsystemVersion' => 'Versione sottosistema', + 'Subtitle' => 'Sottotitolo', + 'Suffix' => 'Suffisso', + 'SuggestedPalette' => 'Tavolozza suggerita', + 'Summary' => 'Sommario', + 'SuperMacro' => { + PrintConv => { + 'Off' => 'Spento', + }, + }, + 'SuperimposedDisplay' => { + PrintConv => { + 'Off' => 'Spento', + }, + }, + 'SupplementalCategories' => 'Categoria Supplementare', + 'SupplementalType' => { + PrintConv => { + 'Main Image' => 'Non impostato', + 'Rasterized Caption' => 'Didascalia rasterizzata', + 'Reduced Resolution Image' => 'Risoluzione immagine ridotta', + }, + }, + 'SurroundMode' => { + PrintConv => { + 'Not Dolby surround' => 'Non Dolby surround', + 'Not indicated' => 'Non indicato', + }, + }, + 'SweepPanoramaDirection' => { + Description => 'Direzione panoramica ad arco', + PrintConv => { + 'Left' => 'Sinistra', + 'Right' => 'Destra', + }, + }, + 'SweepPanoramaSize' => 'Dimensione panoramica ad arco', + 'SwitchToRegisteredAFPoint' => { + PrintConv => { + 'Enable' => 'Abilita', + }, + }, + 'SynchronizedLyricText' => 'Testo sincronizzato', + 'SystemNameOrNumber' => 'Nome/numero sistema', + 'T4Options' => { + Description => 'Opzioni T4', + PrintConv => { + '2-Dimensional encoding' => 'Codifica 2D', + 'Fill bits added' => 'Bit di riempimento aggiunti', + 'Uncompressed' => 'Non compresso', + }, + }, + 'T6Options' => { + Description => 'Opzioni T6', + PrintConv => { + 'Uncompressed' => 'Non compresso', + }, + }, + 'T82Options' => 'Opzioni T82', + 'T88Options' => 'Opzioni T88', + 'TIFFPreview' => 'Anteprima TIFF', + 'TIFFSummary' => 'Sommario TIFF', + 'TIFF_FXExtensions' => { + Description => 'Estensioni TIFF FX', + PrintConv => { + 'B&W JBIG2' => 'JBIG2 bianco e nero', + 'JBIG2 Profile M' => 'JBIG2 TIFF FX', + 'N Layer Profile M' => 'Livello N profilo M', + 'Resolution/Image Width' => 'Risoluzione/larghezza immagine', + 'Shared Data' => 'Dati condivisi', + }, + }, + 'Tagged' => { + PrintConv => { + 'Yes' => 'Sì', + }, + }, + 'TaggingTime' => 'Ora tag', + 'TargetDeltaType' => { + PrintConv => { + 'Absolute' => 'Assoluto', + }, + }, + 'TargetPrinter' => 'Stampante di destinazione', + 'Technology' => { + Description => 'Tecnologia', + PrintConv => { + 'Active Matrix Display' => 'Display a matrice attiva', + 'Cathode Ray Tube Display' => 'Monitor con Tubo a Raggi Catodici', + 'Digital Camera' => 'Fotocamera Digitale', + 'Dye Sublimation Printer' => 'Stampante a Sublimazione Termica', + 'Electrophotographic Printer' => 'Stampante Laser', + 'Electrostatic Printer' => 'Stampante Elettrostatica', + 'Film Scanner' => 'Scanner per Pellicola', + 'Ink Jet Printer' => 'Stampante Ink Jet', + 'Offset Lithography' => 'Litografía Offset', + 'Passive Matrix Display' => 'Display a Matrice passiva', + 'Photographic Paper Printer' => 'Stampante per Carta Fotografica', + 'Projection Television' => 'Proiettore televisivo', + 'Reflective Scanner' => 'Scanner a riflessione', + 'Thermal Wax Printer' => 'Stampante Thermal Wax', + }, + }, + 'Teleconverter' => { + PrintConv => { + 'None' => 'Nessuno', + }, + }, + 'Temperature' => 'Temperatura', + 'Template' => 'Modello', + 'TermsOfUse' => 'Termini di utilizzo', + 'TestTarget' => { + PrintConv => { + 'Grayscale' => 'Scala di grigi', + }, + }, + 'Text' => 'Testo', + 'TextColor' => 'Colore testo', + 'TextComments' => 'Testo commenti', + 'TextEncoding' => { + Description => 'Codifica testo', + PrintConv => { + 'n/a' => 'n/d', + }, + }, + 'TextFace' => { + Description => 'Aspetto testo', + PrintConv => { + 'Extend' => 'Estendi', + 'Italic' => 'Corsivo', + 'Shadow' => 'Ombra', + }, + }, + 'TextFont' => { + Description => 'Carattere testo', + PrintConv => { + 'System' => 'Sistema', + }, + }, + 'TextLayers' => 'Livelli testo', + 'TextSize' => 'Dimenione testo', + 'TextStamp' => { + PrintConv => { + 'Off' => 'Spento', + }, + }, + 'TextString' => 'Stringa testo', + 'TextValue' => 'Valore testo', + 'Thresholding' => { + Description => 'Soglia', + PrintConv => { + 'No dithering or halftoning' => 'Nessun dithering o resa a mezzi toni', + 'Randomized dither' => 'Dither casuale', + }, + }, + 'ThumbnailFileName' => 'Nome file miniatura', + 'ThumbnailFormat' => 'Formato miniatura', + 'ThumbnailHeight' => 'Miniatura', + 'ThumbnailImage' => 'Miniatura', + 'ThumbnailImageName' => 'Nome miniatura', + 'ThumbnailImageSize' => 'Dimensione miniatura', + 'ThumbnailImageType' => 'Tipo miniatura', + 'ThumbnailImageValidArea' => 'Area valida miniatura', + 'ThumbnailLength' => 'Dimensioni miniatura', + 'ThumbnailOffset' => 'Offset miniatura', + 'ThumbnailWidth' => 'Larghezza miniatura', + 'Thumbnails' => 'Miniature', + 'TileByteCounts' => 'Byte tassello', + 'TileDepth' => 'Profondità tassello', + 'TileLength' => 'Lunghezza tassello', + 'TileOffsets' => 'Offset tasselli', + 'TileWidth' => 'Larghezza tassello', + 'Tiles' => 'Tasselli', + 'Time' => 'Ora', + 'TimeCreated' => 'Ora di Creazione', + 'TimeSent' => 'Ora d\'invio', + 'TimeStamp' => 'Marcatura oraria', + 'TimeStamp1' => 'Marcatura oraria 1', + 'TimeZone' => 'Fuso orario', + 'TimeZoneCity' => { + Description => 'Città fuso orario', + PrintConv => { + 'London' => 'Londra', + 'Tehran' => 'Teheran', + 'n/a' => 'n/d', + }, + }, + 'TimeZoneCode' => 'Codice fuso orario', + 'TimeZoneInfo' => 'Info fuso orario', + 'TimeZoneOffset' => 'Scostamento fuso orario', + 'TimerFunctionButton' => { + PrintConv => { + 'Self-timer' => 'Autoscatto', + 'Shooting Mode' => 'Modo scatto', + 'White Balance' => 'Bilanciamento del bianco', + }, + }, + 'TimerLength' => { + PrintConv => { + 'Enable' => 'Abilita', + }, + }, + 'Tint' => 'Tinta', + 'Title' => 'Titolo', + 'Title2' => 'Titolo 2', + 'TitleKind' => 'Tipo titolo', + 'TitleLen' => 'Lungh titolo', + 'TitleNum' => 'Num titolo', + 'TitleOfParts' => 'Titolo parti', + 'TitleSortOrder' => 'Ordinamento titolo', + 'TitlesOfParts' => 'Titoli parti', + 'TitlesSets' => 'Insiemi di titoli', + 'ToDoTitle' => 'Titolo da fare', + 'ToneComp' => 'Compensazione Tono', + 'ToneCurve' => { + PrintConv => { + 'Manual' => 'Manuale', + }, + }, + 'ToneCurveActive' => { + PrintConv => { + 'Yes' => 'Sì', + }, + }, + 'ToneCurveName' => { + PrintConv => { + 'Linear' => 'Lineare', + 'Strong Contrast' => 'Contrasto elevato', + }, + }, + 'ToneCurveProperty' => { + PrintConv => { + 'Linear' => 'Lineare', + 'Shot Settings' => 'Impostazioni scatto', + }, + }, + 'ToningEffect' => { + PrintConv => { + 'Blue-green' => 'Blu-Verde', + 'Green' => 'Verde', + 'None' => 'Nessuno', + 'Purple' => 'Porpora', + 'Purple-blue' => 'Porpora-blu', + 'Red' => 'Rosso', + 'Red-purple' => 'Rosso-porpora', + 'Sepia' => 'Seppia', + 'Yellow' => 'Giallo', + 'n/a' => 'n/d', + }, + }, + 'ToningEffectFaithful' => { + PrintConv => { + 'n/a' => 'n/d', + }, + }, + 'ToningEffectLandscape' => { + PrintConv => { + 'n/a' => 'n/d', + }, + }, + 'ToningEffectMonochrome' => { + PrintConv => { + 'Green' => 'Verde', + 'None' => 'Nessuno', + 'Purple' => 'Porpora', + 'Sepia' => 'Seppia', + 'n/a' => 'n/d', + }, + }, + 'ToningEffectNeutral' => { + PrintConv => { + 'n/a' => 'n/d', + }, + }, + 'ToningEffectPortrait' => { + PrintConv => { + 'n/a' => 'n/d', + }, + }, + 'ToningEffectStandard' => { + PrintConv => { + 'n/a' => 'n/d', + }, + }, + 'ToningEffectUnknown' => { + PrintConv => { + 'Green' => 'Verde', + 'None' => 'Nessuno', + 'Purple' => 'Porpora', + 'Sepia' => 'Seppia', + 'n/a' => 'n/d', + }, + }, + 'ToningEffectUserDef1' => { + PrintConv => { + 'Green' => 'Verde', + 'None' => 'Nessuno', + 'Purple' => 'Porpora', + 'Sepia' => 'Seppia', + 'n/a' => 'n/d', + }, + }, + 'ToningEffectUserDef2' => { + PrintConv => { + 'Green' => 'Verde', + 'None' => 'Nessuno', + 'Purple' => 'Porpora', + 'Sepia' => 'Seppia', + 'n/a' => 'n/d', + }, + }, + 'ToningEffectUserDef3' => { + PrintConv => { + 'Green' => 'Verde', + 'None' => 'Nessuno', + 'Purple' => 'Porpora', + 'Sepia' => 'Seppia', + 'n/a' => 'n/d', + }, + }, + 'ToolName' => 'Nome strumento', + 'ToolVersion' => 'Versione strumento', + 'TotalFrames' => 'Frame totali', + 'Track' => 'Traccia', + 'TrackProperty' => { + PrintConv => { + 'Read only' => 'Sola lettura', + }, + }, + 'TransferFunction' => 'Funzione di trasferimento', + 'TransferRange' => 'Intervallo di trasferimento', + 'Transform' => { + PrintConv => { + 'Off' => 'Spento', + }, + }, + 'Transformation' => { + Description => 'Trasformazione', + PrintConv => { + 'Horizontal (normal)' => 'Orizzontale (normale)', + 'Mirror horizontal' => 'Rifletti orizzontalmente', + 'Mirror horizontal and rotate 270 CW' => 'Rifletti orizzontalmente e ruota di 270° in senso orario', + 'Mirror horizontal and rotate 90 CW' => 'Rifletti orizzontalmente e ruota di 90° in senso orario', + 'Mirror vertical' => 'Rifletti verticalmente', + 'Rotate 180' => 'Ruota di 180°', + 'Rotate 270 CW' => 'Ruota di 270° in senso orario', + 'Rotate 90 CW' => 'Ruota di 90° senso orario', + }, + }, + 'TransmissionReference' => 'Riferimento trasmissione', + 'TransparencyIndicator' => 'Indicatore trasparenza', + 'TrapIndicator' => 'Indicatore trap', + 'Trapped' => { + PrintConv => { + 'False' => 'Falso', + 'Unknown' => 'Sconosciuto', + }, + }, + 'TungstenAWB' => { + PrintConv => { + 'Strong Correction' => 'Correzione elevata', + }, + }, + 'TxFace' => 'Stile carattere testo', + 'TxFont' => 'Numero carattere', + 'TxSize' => 'Dimenione testo', + 'UIC1Tag' => 'Tag UIC1', + 'UIC2Tag' => 'Tag UIC2', + 'UIC3Tag' => 'Tag UIC3', + 'UIC4Tag' => 'Tag UIC4', + 'USPTOOriginalContentType' => { + PrintConv => { + 'Color' => 'Colore', + 'Grayscale' => 'Scala di grigi', + 'Text or Drawing' => 'Testo o disegno', + }, + }, + 'UV-IRFilterCorrection' => { + PrintConv => { + 'Not Active' => 'Non attivo', + }, + }, + 'Uncompressed' => { + Description => 'Non compresso', + PrintConv => { + 'Yes' => 'Sì', + }, + }, + 'UninitializedDataSize' => 'Dimensione dati non inizializzati', + 'UniqueCameraModel' => 'Modello unico fotocamera', + 'UniqueDocumentID' => 'ID Unico del Documento', + 'Units' => 'Unità', + 'Unknown' => 'Sconosciuto', + 'Unsharp1Color' => { + PrintConv => { + 'Green' => 'Verde', + 'Red' => 'Rosso', + 'Yellow' => 'Giallo', + }, + }, + 'Unsharp2Color' => { + PrintConv => { + 'Green' => 'Verde', + 'Red' => 'Rosso', + 'Yellow' => 'Giallo', + }, + }, + 'Unsharp3Color' => { + PrintConv => { + 'Green' => 'Verde', + 'Red' => 'Rosso', + 'Yellow' => 'Giallo', + }, + }, + 'Unsharp4Color' => { + PrintConv => { + 'Green' => 'Verde', + 'Red' => 'Rosso', + 'Yellow' => 'Giallo', + }, + }, + 'UnsharpMask' => { + PrintConv => { + 'Off' => 'Spento', + }, + }, + 'Urgency' => { + Description => 'Urgenza', + PrintConv => { + '0 (reserved)' => '0 (riservato)', + '1 (most urgent)' => '1 (molto urgente)', + '5 (normal urgency)' => '5 (urgenza normale)', + '8 (least urgent)' => '8 (meno urgent)e', + '9 (user-defined priority)' => '9 (riservato per usi futuri)', + }, + }, + 'UsableMeteringModes' => { + PrintConv => { + 'Enable' => 'Abilita', + }, + }, + 'UsableShootingModes' => { + PrintConv => { + 'Enable' => 'Abilita', + }, + }, + 'UserAccess' => { + PrintConv => { + 'Print' => 'Stampa', + }, + }, + 'UserComment' => 'Commento utente', + 'UserDef1PictureStyle' => { + PrintConv => { + 'Landscape' => 'Orizzontale', + 'Portrait' => 'Verticale', + }, + }, + 'UserDef2PictureStyle' => { + PrintConv => { + 'Landscape' => 'Orizzontale', + 'Portrait' => 'Verticale', + }, + }, + 'UserDef3PictureStyle' => { + PrintConv => { + 'Landscape' => 'Orizzontale', + 'Portrait' => 'Verticale', + }, + }, + 'UserDefinedText' => 'Testo personalizzato', + 'UserDefinedURL' => 'URL personalizzato', + 'VFDisplayIllumination' => { + PrintConv => { + 'Enable' => 'Abilita', + }, + }, + 'VRDVersion' => 'Versione VRD', + 'VRInfo' => 'Info Riduzione Vibrazione', + 'VRInfoVersion' => 'Info Versione VR', + 'VR_0x66' => { + PrintConv => { + 'Off' => 'Spento', + }, + }, + 'Value' => 'Valore', + 'VariousModes' => 'Modi vari', + 'VariousModes2' => 'Modi vari 2', + 'Version' => 'Numero versione immagine', + 'Version2' => 'Versione 2', + 'VersionBF' => 'Versione BF', + 'VersionCreateDate' => 'Data creazione versione', + 'VersionID' => 'ID versione', + 'VersionIdentifier' => 'Identificativo versione', + 'VersionInfo' => 'Info versione', + 'VersionModifyDate' => 'Data modifica versione', + 'VersionNumber' => 'Numero versione', + 'VersionNumberString' => 'Stringa numero versione', + 'VersionTitle' => 'Titolo versione', + 'VersionYear' => 'Anno versione', + 'Versions' => 'Versioni', + 'VerticalCSType' => { + PrintConv => { + 'Caspian Sea' => 'Mar Caspio', + 'WGS 84 ellipsoid' => 'Ellissoide WGS 84', + }, + }, + 'VerticalUnits' => 'Unità verticali', + 'VibrationReduction' => { + Description => 'Riduzione vibrazione', + PrintConv => { + 'Off' => 'Spento', + 'n/a' => 'n/d', + }, + }, + 'VideoAlphaMode' => { + PrintConv => { + 'None' => 'Nessuno', + }, + }, + 'VideoAttributes' => { + PrintConv => { + 'Encrypted' => 'Crittografato', + }, + }, + 'VideoBitrate' => 'Bitrate video', + 'VideoCardGamma' => 'Gamma della Scheda Video', + 'VideoCodec' => 'Codec video', + 'VideoCodecDescription' => 'Descrizione codec video', + 'VideoCodecID' => 'ID codec video', + 'VideoCodecInfo' => 'Info codec video', + 'VideoCodecName' => 'Nome codec video', + 'VideoFieldOrder' => { + PrintConv => { + 'Progressive' => 'Progressivo', + }, + }, + 'VideoQuality' => { + PrintConv => { + 'Low' => 'Basso', + }, + }, + 'VideoScanType' => { + PrintConv => { + 'Progressive' => 'Progressivo', + }, + }, + 'VideoStreamType' => { + PrintConv => { + 'Reserved' => 'Riservato', + }, + }, + 'ViewInfoDuringExposure' => { + PrintConv => { + 'Enable' => 'Abilita', + }, + }, + 'ViewfinderWarning' => { + PrintConv => { + 'Off' => 'Spento', + }, + }, + 'ViewingCondDesc' => 'Descrizione Condizioni di Visualizzazione', + 'ViewingMode2' => { + PrintConv => { + 'n/a' => 'n/d', + }, + }, + 'VignetteControl' => { + PrintConv => { + 'Low' => 'Basso', + 'Normal' => 'Normale', + 'Off' => 'Spento', + }, + }, + 'VignettingCorrection' => { + PrintConv => { + 'Off' => 'Spento', + 'n/a' => 'n/d', + }, + }, + 'VirtualImageHeight' => 'Altezza immagine virtuale', + 'VirtualImageWidth' => 'Larghezza immagine virtuale', + 'VirtualPageUnits' => 'Unità pagina virtuale', + 'VoiceMemo' => { + PrintConv => { + 'Off' => 'Spento', + }, + }, + 'WBAdjLighting' => { + PrintConv => { + 'Daylight (direct sunlight)' => 'Luce del giorno (0)', + 'Daylight (shade)' => 'Luce del giorno (1)', + 'Daylight (cloudy)' => 'Luce del giorno (2)', + 'None' => 'Nessuno', + }, + }, + 'WBBracketMode' => { + PrintConv => { + 'Off' => 'Spento', + }, + }, + 'WBFineTuneActive' => { + PrintConv => { + 'Yes' => 'Sì', + }, + }, + 'WCSProfiles' => 'Profilo Windows Color System', + 'WhiteBalance' => { + Description => 'Bilanciamento del bianco', + PrintConv => { + 'Auto' => 'Equilibrio del bianco automatico', + 'Black & White' => 'Monocromatico', + 'Cloudy' => 'Nuvoloso', + 'Color Temperature/Color Filter' => 'Temperatura colore / Filtro colore', + 'Cool White Fluorescent' => 'Fluorescente bianca fredda', + 'Custom' => 'Personalizzato', + 'Custom 1' => 'PERSONAL.1', + 'Custom 2' => 'PERSONAL.2', + 'Custom 3' => 'PERSONAL.3', + 'Custom 4' => 'PERSONAL.4', + 'Day White Fluorescent' => 'Fluorescente a luce del giorno bianca', + 'Daylight' => 'Luce del giorno', + 'Daylight Fluorescent' => 'Fluorescente a luce del giorno', + 'Fluorescent' => 'Fluorescente', + 'Manual' => 'Manuale', + 'Shade' => 'Ombrato', + 'Tungsten' => 'Tungsteno (luce incandescente)', + 'Unknown' => 'Sconosciuto', + 'Warm White Fluorescent' => 'Luce fluorescente bianca calda', + 'White Fluorescent' => 'Fluorescente bianca', + }, + }, + 'WhiteBalance2' => 'Bilanciamento del bianco 2', + 'WhiteBalanceAdj' => { + Description => 'Adattamento bilanciamento bianco', + PrintConv => { + 'Cloudy' => 'Nuvoloso', + 'Daylight' => 'Luce del giorno', + 'Fluorescent' => 'Fluorescente', + 'Off' => 'Spento', + 'Shade' => 'Ombrato', + 'Shot Settings' => 'Impostazioni scatto', + 'Tungsten' => 'Tungsteno (luce incandescente)', + }, + }, + 'WhiteBalanceAutoAdjustment' => { + Description => 'Adattamento automatico bilanciamento bianco', + PrintConv => { + 'Off' => 'Spento', + }, + }, + 'WhiteBalanceBracketing' => { + PrintConv => { + 'Low' => 'Basso', + 'Off' => 'Spento', + }, + }, + 'WhiteBalanceFineTune' => 'Regolazione Fine Bilanciamento Bianco', + 'WhiteBalanceMode' => { + PrintConv => { + 'Unknown' => 'Sconosciuto', + }, + }, + 'WhiteBalanceSet' => { + PrintConv => { + 'Cloudy' => 'Nuvoloso', + 'Daylight' => 'Luce del giorno', + 'Daylight Fluorescent' => 'Fluorescente a luce del giorno', + 'Manual' => 'Manuale', + 'Shade' => 'Ombrato', + 'Tungsten' => 'Tungsteno (luce incandescente)', + 'White Fluorescent' => 'Fluorescente bianca', + }, + }, + 'WhiteBalanceSetting' => { + PrintConv => { + 'Fluorescent (+1)' => 'Fluorescente (+1)', + 'Fluorescent (+2)' => 'Fluorescente (+2)', + 'Fluorescent (+3)' => 'Fluorescente (+3)', + 'Fluorescent (-1)' => 'Fluorescente (-1)', + 'Fluorescent (-2)' => 'Fluorescente (-2)', + 'Fluorescent (-3)' => 'Fluorescente (-3)', + 'Fluorescent (0)' => 'Fluorescente (0)', + 'Shade (+1)' => 'Ombrato (+1)', + 'Shade (+2)' => 'Ombrato (+2)', + 'Shade (+3)' => 'Ombrato (+3)', + 'Shade (-1)' => 'Ombrato (-1)', + 'Shade (-2)' => 'Ombrato (-2)', + 'Shade (-3)' => 'Ombrato (-3)', + 'Shade (0)' => 'Ombrato (0)', + }, + }, + 'WhiteLevel' => 'Livello bianco', + 'WhitePoint' => 'Punto bianco', + 'WideRange' => { + PrintConv => { + 'Off' => 'Spento', + }, + }, + 'WidthResolution' => 'Risoluzione larghezza', + 'Writer-Editor' => 'Autore Didascalia/Descrizione', + 'XMethod' => { + PrintConv => { + 'No Magnification' => 'Nessun ingrandimento', + }, + }, + 'XPAuthor' => 'Autore', + 'XPComment' => 'Commento XP', + 'XPKeywords' => 'Parole chiave XP', + 'XPSubject' => 'Soggetto XP', + 'XPTitle' => 'Titolo XP', + 'XPosition' => 'Posizione X', + 'XResolution' => 'Risoluzione orizzontale immagine', + 'YCbCrCoefficients' => 'Coefficienti matrice trasformazione spazio colori', + 'YCbCrPositioning' => { + Description => 'Posizionamento Y e C', + PrintConv => { + 'Centered' => 'Centrato', + 'Co-sited' => 'Affiancato', + }, + }, + 'YCbCrSubSampling' => 'Indice sottocampionamento da Y a C', + 'YMethod' => { + PrintConv => { + 'No Magnification' => 'Nessun ingrandimento', + }, + }, + 'YPosition' => 'Posizione Y', + 'YResolution' => 'Risoluzione verticale immagine', + 'Year' => 'Anno', + 'ZipCompression' => { + PrintConv => { + 'None' => 'Nessuno', + 'Reduced with compression factor 1' => 'Ridotto con fattore compressione 1', + 'Reduced with compression factor 2' => 'Ridotto con fattore compressione 2', + 'Reduced with compression factor 3' => 'Ridotto con fattore compressione 3', + 'Reduced with compression factor 4' => 'Ridotto con fattore compressione 4', + }, + }, + 'ZoneMatching' => { + Description => 'Adeguamento zona', + PrintConv => { + 'High Key' => 'Hi', + 'ISO Setting Used' => 'Impostazione ISO usata', + 'Low Key' => 'Lo', + }, + }, + 'ZoneMatchingMode' => { + PrintConv => { + 'Off' => 'Spento', + }, + }, + 'ZoneMatchingOn' => { + PrintConv => { + 'Off' => 'Spento', + }, + }, + 'ZoomCenter' => 'Centro zoom', + 'ZoomFactor' => 'Fattore di zoom', + 'ZoomPos' => 'Posizione zoom', + 'iTunesU' => 'ITunes U', +); + +1; # end + + +__END__ + +=head1 NAME + +Image::ExifTool::Lang::it.pm - ExifTool Italian language translations + +=head1 DESCRIPTION + +This file is used by Image::ExifTool to generate localized tag descriptions +and values. + +=head1 AUTHOR + +Copyright 2003-2019, Phil Harvey (phil at owl.phy.queensu.ca) + +This library is free software; you can redistribute it and/or modify it +under the same terms as Perl itself. + +=head1 ACKNOWLEDGEMENTS + +Thanks to Jens Duttke, Ferdinando Agovino, Emilio Dati and Michele Locati +for providing this translation. + +=head1 SEE ALSO + +L<Image::ExifTool(3pm)|Image::ExifTool>, +L<Image::ExifTool::TagInfoXML(3pm)|Image::ExifTool::TagInfoXML> + +=cut diff --git a/lib/Image/ExifTool/Lang/ja.pm b/lib/Image/ExifTool/Lang/ja.pm new file mode 100644 index 0000000..cabad53 --- /dev/null +++ b/lib/Image/ExifTool/Lang/ja.pm @@ -0,0 +1,5846 @@ +#------------------------------------------------------------------------------ +# File: ja.pm +# +# Description: ExifTool Japanese language translations +# +# Notes: This file generated automatically by Image::ExifTool::TagInfoXML +#------------------------------------------------------------------------------ + +package Image::ExifTool::Lang::ja; + +use strict; +use vars qw($VERSION); + +$VERSION = '1.23'; + +%Image::ExifTool::Lang::ja::Translate = ( + 'AEAperture' => 'AE絞り', + 'AEBAutoCancel' => { + Description => 'ブラケティング自動解除', + PrintConv => { + 'Off' => 'オフ', + 'On' => 'オン', + }, + }, + 'AEBBracketValue' => 'AEBブラケット値', + 'AEBSequence' => 'ブラケティング順序', + 'AEBSequenceAutoCancel' => { + Description => 'ブラケティング順序/自動解除', + PrintConv => { + '-,0,+/Disabled' => '-→0 →+/しない', + '-,0,+/Enabled' => '-→0 →+/する', + '0,-,+/Disabled' => '0 →-→+/しない', + '0,-,+/Enabled' => '0 →-→+/する', + }, + }, + 'AEBShotCount' => 'ブラケティング時の撮影枚数', + 'AEBXv' => 'AEブラケット 露出補正', + 'AEExposureTime' => 'AE露出時間', + 'AEExtra' => 'AE特別?', + 'AEInfo' => '自動露出情報', + 'AELock' => { + Description => 'AEロック', + PrintConv => { + 'Off' => 'オフ', + 'On' => 'オン', + }, + }, + 'AELockButton' => { + Description => 'AE-L/AF-L', + PrintConv => { + 'AE-L/AF Area' => 'AE-L/AFエリア', + 'AE-L/AF-L/AF Area' => 'AE-L/AF-L/AFエリア', + 'AF-L/AF Area' => 'AF-L/AFエリア', + 'AF-ON/AF Area' => 'AFオン/AFエリア', + 'FV Lock' => 'FVロック', + 'Focus Area Selection' => 'フォーカスエリア選択', + }, + }, + 'AEMaxAperture' => 'AE最大絞り', + 'AEMaxAperture2' => 'AE最大絞り(2)', + 'AEMeteringMode' => { + Description => 'AE測光モード', + PrintConv => { + 'Multi-segment' => 'パターン', + }, + }, + 'AEMeteringSegments' => '自動露出測光値', + 'AEMinAperture' => 'AE最小絞り', + 'AEMinExposureTime' => 'AE最小露出時間', + 'AEProgramMode' => { + Description => 'AEプログラムモード', + PrintConv => { + 'Av, B or X' => 'Av, BかX', + 'Candlelight' => 'キャンドルライト', + 'DOF Program' => '深度優先プログラム', + 'DOF Program (P-Shift)' => '深度優先プログラム(Pシフト)', + 'Hi-speed Program' => '高速優先プログラム', + 'Hi-speed Program (P-Shift)' => '高速優先プログラム(Pシフト)', + 'Kids' => 'キッズ', + 'Landscape' => '風景', + 'M, P or TAv' => 'M, PかTAv', + 'MTF Program' => 'MTF優先プログラム', + 'MTF Program (P-Shift)' => 'MTF優先プログラム(Pシフト)', + 'Macro' => 'マクロ', + 'Museum' => 'ミュージアム', + 'Night Scene' => '夜景', + 'Night Scene Portrait' => '人物、夜景', + 'No Flash' => 'フラッシュ無し', + 'Pet' => 'ペット', + 'Portrait' => 'ポートレート', + 'Sport' => 'スポーツ', + 'Standard' => 'スタンダード', + 'Sunset' => '夕日', + 'Surf & Snow' => 'サーフ&スノー', + 'Sv or Green Mode' => 'Svかグリーンモード', + 'Text' => 'テキスト', + }, + }, + 'AESetting' => { + Description => '自動露出設定', + PrintConv => { + 'Exposure Compensation' => '露出補正', + }, + }, + 'AEXv' => 'AE 露出補正', + 'AE_ISO' => 'AE ISO感度', + 'AF-CPrioritySelection' => { + Description => 'AF-Cプライオリティー選択', + PrintConv => { + 'Focus' => 'フォーカス', + 'Release' => 'レリーズ', + 'Release + Focus' => 'レリーズ+フォーカス', + }, + }, + 'AF-OnForMB-D10' => { + Description => 'MB-D10用AFオン', + PrintConv => { + 'AE Lock (hold)' => 'AEロック(ホールド)', + 'AE Lock (reset on release)' => 'AEロック(レリーズ時リセット)', + 'AE Lock Only' => 'AEロックのみ', + 'AE/AF Lock' => 'AE/AFロック', + 'AF Lock Only' => 'AFロックのみ', + 'AF-On' => 'AFオン', + 'Same as FUNC Button' => 'ファンクションボタンと同一', + }, + }, + 'AF-SPrioritySelection' => { + Description => 'AF-Sプライオリティー選択', + PrintConv => { + 'Focus' => 'フォーカス', + 'Release' => 'レリーズ', + }, + }, + 'AFActivation' => { + Description => 'AFアクティベーション', + PrintConv => { + 'AF-On Only' => 'AFオンのみ', + 'Shutter/AF-On' => 'シャッター/AFオン', + }, + }, + 'AFAdjustment' => 'AF微調整', + 'AFArea' => 'AFエリア', + 'AFAreaHeight' => 'AFエリア高さ', + 'AFAreaHeights' => 'AFエリア高さ', + 'AFAreaIllumination' => { + Description => 'AFエリアイルミネーション', + PrintConv => { + 'Auto' => 'オート', + 'Off' => 'オフ', + 'On' => 'オン', + }, + }, + 'AFAreaMode' => { + Description => 'AFエリアモード', + PrintConv => { + '1-area' => '1点', + '1-area (high speed)' => '高速1点', + '3-area (center)?' => '3点中央?', + '3-area (left)?' => '3点左?', + '3-area (right)?' => '3点右?', + '5-area' => '5点', + 'Auto-area' => '自動エリアAF', + 'Dynamic Area' => 'ダイナミックエリア', + 'Dynamic Area (closest subject)' => 'ダイナミック(重点主題)', + 'Dynamic Area (wide)' => 'ダイナミック(ワイド)', + 'Face Detect AF' => '顔優先', + 'Group Dynamic' => 'グループダイナミック', + 'Normal?' => 'ノーマル?', + 'Single Area' => 'シングルポイント', + 'Single Area (wide)' => 'シングルポイント(ワイド)', + 'Spot Focusing' => 'スポットフォーカス', + 'Spot Mode On' => 'スポットモードオン', + }, + }, + 'AFAreaModeSetting' => { + Description => 'AFエリアモード', + PrintConv => { + 'Closest Subject' => 'オートエリア', + 'Dynamic Area' => 'ダイナミックエリア', + 'Single Area' => 'シングルポイント', + }, + }, + 'AFAreaWidth' => 'AFエリア幅', + 'AFAreaWidths' => 'AFエリア幅', + 'AFAreas' => 'AFエリア', + 'AFAssist' => { + Description => 'AFアシスト', + PrintConv => { + 'Does not emit/Fires' => 'しない/する', + 'Emits/Does not fire' => 'する/しない', + 'Emits/Fires' => 'する/する', + 'Off' => 'オフ', + 'On' => 'オン', + 'Only ext. flash emits/Fires' => '外部ストロボのみする/する', + }, + }, + 'AFAssistBeam' => { + Description => 'AF補助光の投光', + PrintConv => { + 'Does not emit' => 'しない', + 'Emits' => 'する', + 'Only ext. flash emits' => '外部ストロボのみする', + }, + }, + 'AFDefocus' => 'AFぼけ量', + 'AFDuringLiveView' => { + Description => 'ライブビュー撮影中のAF', + PrintConv => { + 'Disable' => 'しない', + 'Enable' => 'する', + 'Live mode' => 'ライブモード', + 'Quick mode' => 'クイックモード', + }, + }, + 'AFFineTune' => 'AFファインチューン', + 'AFFineTuneAdj' => 'AFファインチューン', + 'AFImageHeight' => 'AF画像高さ', + 'AFImageWidth' => 'AF画像幅', + 'AFInfo' => 'AFモード', + 'AFInfo2' => 'AF情報', + 'AFInfo2Version' => 'AF情報バージョン', + 'AFIntegrationTime' => 'AF集積時間', + 'AFMicroadjustment' => { + Description => 'AFマイクロアジャストメント', + PrintConv => { + 'Adjust all by same amount' => '全レンズ一律調整', + 'Adjust by lens' => 'レンズごとに調整', + 'Disable' => 'しない', + }, + }, + 'AFMode' => 'AFモード', + 'AFOnAELockButtonSwitch' => { + Description => 'AF-ON/AEロックボタン入替', + PrintConv => { + 'Disable' => 'しない', + 'Enable' => 'する', + }, + }, + 'AFPoint' => { + Description => 'AF選択ポイント', + PrintConv => { + 'Auto AF point selection' => 'オートAFポイント選択', + 'Bottom' => '下', + 'Center' => '中央', + 'Face Detect' => '顔認識', + 'Left' => '左', + 'Manual AF point selection' => 'マニュアルAFポイント選択', + 'Mid-left' => '中央左', + 'Mid-right' => '中央右', + 'None' => '無し', + 'None (MF)' => '無し(MF)', + 'Right' => '右', + 'Top' => '上', + }, + }, + 'AFPointActivationArea' => { + Description => 'AFフレームの領域拡大', + PrintConv => { + 'Standard' => 'スタンダード', + }, + }, + 'AFPointAreaExpansion' => { + Description => '任意選択時のAFフレーム領域拡大', + PrintConv => { + 'Disable' => 'しない', + 'Enable' => 'する', + 'Left/right AF points' => 'する(左右1領域アシスト有効)', + 'Surrounding AF points' => 'する(周囲1領域アシスト有効)', + }, + }, + 'AFPointAutoSelection' => { + Description => 'AFフレーム自動選択の選択可否', + PrintConv => { + 'Control-direct:disable/Main:disable' => 'サブ電子ダイヤル直接:不可/メイン電子ダイヤル→不可', + 'Control-direct:disable/Main:enable' => 'サブ電子ダイヤル直接:不可/メイン電子ダイヤル→可', + 'Control-direct:enable/Main:enable' => 'サブ電子ダイヤル直接:可/メイン電子ダイヤル→可', + }, + }, + 'AFPointBrightness' => { + Description => 'AFフレーム点灯輝度', + PrintConv => { + 'Brighter' => '明るい', + 'Normal' => '標準', + }, + }, + 'AFPointDisplayDuringFocus' => { + Description => '測距時のAFフレーム表示', + PrintConv => { + 'Off' => 'しない', + 'On' => 'する', + 'On (when focus achieved)' => 'する(合焦時)', + }, + }, + 'AFPointIllumination' => { + Description => 'AFポイントイルミネーション', + PrintConv => { + 'Auto' => 'オート', + 'Off' => 'オフ', + 'On' => 'オン', + }, + }, + 'AFPointMode' => { + Description => 'AF測距点モード', + PrintConv => { + 'Auto' => 'オート', + }, + }, + 'AFPointRegistration' => { + Description => 'AFフレームの登録', + PrintConv => { + 'Automatic' => 'オート', + 'Bottom' => '下', + 'Center' => '中央', + 'Extreme Left' => '左端', + 'Extreme Right' => '右端', + 'Left' => '左', + 'Right' => '右', + 'Top' => '上', + }, + }, + 'AFPointSelected' => { + Description => 'AF測距点', + PrintConv => { + 'Auto' => 'オート', + 'Automatic Tracking AF' => '自動追尾', + 'Bottom' => '下', + 'Center' => '中央', + 'Face Detect AF' => '顔認識', + 'Fixed Center' => '中央固定', + 'Left' => '左', + 'Lower-left' => '左下', + 'Lower-right' => '右下', + 'Mid-left' => '中央左', + 'Mid-right' => '中央右', + 'Right' => '右', + 'Top' => '上', + 'Upper-left' => '左上', + 'Upper-right' => '右上', + }, + }, + 'AFPointSelected2' => { + Description => 'AF測距点選択2', + PrintConv => { + 'Auto' => 'オート', + }, + }, + 'AFPointSelection' => { + Description => 'AFポイント選択', + PrintConv => { + '11 Points' => '11点', + '51 Points' => '51点(3Dトラッキング)', + }, + }, + 'AFPointSelectionMethod' => { + Description => 'AFフレーム選択方法', + PrintConv => { + 'Multi-controller direct' => 'マルチコントローラーダイレクト', + 'Normal' => '標準', + 'Quick Control Dial direct' => 'サブ電子ダイヤルダイレクト', + }, + }, + 'AFPointSpotMetering' => 'AFフレーム数/スポット測光', + 'AFPoints' => 'AFポイント', + 'AFPointsInFocus' => { + Description => 'AF測距点', + PrintConv => { + 'All' => '全て', + 'Bottom' => '下', + 'Bottom, Center' => '下+中央', + 'Bottom-center' => '中央下', + 'Bottom-left' => '左下', + 'Bottom-right' => '右下', + 'Center' => '中央', + 'Center (horizontal)' => '中央(水平)', + 'Center (vertical)' => '中央(水平)', + 'Center+Right' => '中央+右', + 'Fixed Center or Multiple' => '中央固定または複数', + 'Left' => '左', + 'Left+Center' => '左+中央', + 'Left+Right' => '左+右', + 'Lower-left, Bottom' => '左下+下', + 'Lower-left, Mid-left' => '左下+中央左', + 'Lower-right, Bottom' => '右下+下', + 'Lower-right, Mid-right' => '右下+中央右', + 'Mid-left' => '中央左', + 'Mid-left, Center' => '中央左+中央', + 'Mid-right' => '中央右', + 'Mid-right, Center' => '中央右+中央', + 'None' => '無し', + 'None (MF)' => '無し(MF)', + 'Right' => '右', + 'Top' => '上', + 'Top, Center' => '上+中央', + 'Top-center' => '中央上', + 'Top-left' => '左上', + 'Top-right' => '右上', + 'Upper-left, Mid-left' => '左上+中央左', + 'Upper-left, Top' => '左上+上', + 'Upper-right, Mid-right' => '右上+中央右', + 'Upper-right, Top' => '右上+上', + }, + }, + 'AFPointsInFocus1D' => 'AF測距点(1D)', + 'AFPointsInFocus5D' => 'AF測距点', + 'AFPointsSelected' => 'AFポイント選択', + 'AFPointsUnknown2' => { + Description => 'AF測距点 未確認2?', + PrintConv => { + 'Auto' => 'オート', + }, + }, + 'AFPointsUsed' => { + Description => 'AF測距点', + PrintConv => { + 'Bottom' => '下', + 'Center' => '中央', + 'Mid-left' => '中央左', + 'Mid-right' => '中央右', + 'Top' => '上', + }, + }, + 'AFPredictor' => 'AF予測', + 'AFResponse' => 'AFレスポンス', + 'AFResult' => 'AF結果', + 'AFSearch' => { + Description => 'AFサーチ', + PrintConv => { + 'Not Ready' => '準備ができていない', + 'Ready' => '準備完了', + }, + }, + 'AIServoContinuousShooting' => 'AI SERVO 連続撮影・撮影速度優先', + 'AIServoImagePriority' => { + Description => 'AIサーボ1コマ目/2コマ目以降動作', + PrintConv => { + '1: AF, 2: Drive speed' => 'ピント優先/撮影速度優先', + '1: AF, 2: Tracking' => 'ピント優先/被写体追従優先', + '1: Release, 2: Drive speed' => 'レリーズ優先/撮影速度最優先', + }, + }, + 'AIServoTrackingMethod' => { + Description => 'AIサーボ時の測距点選択特性', + PrintConv => { + 'Continuous AF track priority' => '測距連続性優先', + 'Main focus point priority' => '測距中心優先', + }, + }, + 'AIServoTrackingSensitivity' => { + Description => 'AIサーボ時の被写体追従敏感度', + PrintConv => { + 'Fast' => '速い', + 'Slow' => '遅い', + 'Standard' => 'スタンダード', + }, + }, + 'APEVersion' => 'APEバージョン', + 'ARMIdentifier' => 'ARM識別子', + 'ARMVersion' => 'ARMバージョン', + 'AToB0' => 'AからB0', + 'AToB1' => 'AからB1', + 'AToB2' => 'AからB2', + 'AccessoryType' => 'アクセサリータイプ', + 'ActionAdvised' => '動作推奨', + 'ActiveArea' => 'アクティブ領域', + 'ActiveD-Lighting' => { + Description => 'アクティブDライティング', + PrintConv => { + 'High' => '高い', + 'Low' => 'ソフト', + 'Normal' => '標準', + 'Off' => 'オフ', + 'On' => 'オン', + }, + }, + 'ActiveD-LightingMode' => { + PrintConv => { + 'High' => '高い', + 'Low' => 'ソフト', + 'Normal' => '標準', + 'Off' => 'オフ', + }, + }, + 'AddAspectRatioInfo' => { + Description => 'アスペクト比情報の付加', + PrintConv => { + 'Off' => 'オフ', + }, + }, + 'AddOriginalDecisionData' => { + Description => 'オリジナル画像判定用データの付加', + PrintConv => { + 'Off' => 'オフ', + 'On' => 'オン', + }, + }, + 'AdjustmentMode' => '調整モード', + 'AdultContentWarning' => { + PrintConv => { + 'Unknown' => '不明', + }, + }, + 'AdvancedRaw' => { + Description => 'アドバンスRAW', + PrintConv => { + 'Off' => 'オフ', + 'On' => 'オン', + }, + }, + 'AdvancedSceneMode' => { + PrintConv => { + 'Auto' => 'インテリジェントオート', + }, + }, + 'Album' => 'アルバム', + 'AlphaByteCount' => 'アルファバイト数', + 'AlphaDataDiscard' => { + Description => 'アルファデータ破棄', + PrintConv => { + 'Flexbits Discarded' => 'フレックスビット破棄', + 'Full Resolution' => '完全な解像度', + 'HighPass Frequency Data Discarded' => 'ハイパス周波数データ破棄', + 'Highpass and LowPass Frequency Data Discarded' => 'ハイパスとローパス周波数データ破棄', + }, + }, + 'AlphaOffset' => 'アルファオフセット', + 'AnalogBalance' => 'アナログバランス', + 'Annotations' => 'フォトショップ注釈', + 'Anti-Blur' => { + PrintConv => { + 'Off' => 'オフ', + 'On (Continuous)' => 'オン(連写)', + 'On (Shooting)' => 'オン(撮影)', + 'n/a' => '該当無し', + }, + }, + 'AntiAliasStrength' => 'カメラのアンチエイリアスフィルタの相対的な強度', + 'Aperture' => '絞り', + 'ApertureRange' => { + Description => '絞り数値の制御範囲の設定', + PrintConv => { + 'Disable' => 'しない', + 'Enable' => 'する', + }, + }, + 'ApertureRingUse' => { + Description => '絞りリングの使用', + PrintConv => { + 'Permitted' => '許可', + 'Prohibited' => '禁止', + }, + }, + 'ApertureValue' => '絞り', + 'ApplicationRecordVersion' => 'アプリケーションレコードバージョン', + 'ApplyShootingMeteringMode' => { + Description => '撮影・測光モードの呼出', + PrintConv => { + 'Disable' => 'しない', + 'Enable' => 'する', + }, + }, + 'Artist' => '画像作成者', + 'AsShotICCProfile' => '撮影時ICCプロファイル', + 'AsShotNeutral' => 'ニュートラルショット', + 'AsShotPreProfileMatrix' => '撮影時プロファイルマトリックス', + 'AsShotProfileName' => '撮影時プロフィール名', + 'AsShotWhiteXY' => 'ホワイトX-Yショット', + 'AssignFuncButton' => { + Description => 'FUNC.ボタンの機能', + PrintConv => { + 'Exposure comp./AEB setting' => '露出補正/AEB設定', + 'Image jump with main dial' => 'メイン電子ダイヤル での画像送り', + 'Image quality' => '記録画質選択', + 'LCD brightness' => '液晶の明るさ', + 'Live view function settings' => 'ライブビュー機能設定', + }, + }, + 'AssistButtonFunction' => { + Description => 'アシストボタンの機能', + PrintConv => { + 'Av+/- (AF point by QCD)' => 'Av±(サブ電子:AFフレーム選択)', + 'FE lock' => 'FEロック', + 'Normal' => '標準', + 'Select HP (while pressing)' => 'HPに移動(押している間)', + 'Select Home Position' => 'HPに移動', + }, + }, + 'Audio' => { + Description => '音声', + PrintConv => { + 'No' => 'いいえ', + 'Yes' => 'はい', + }, + }, + 'AudioDuration' => 'オーディオ時間', + 'AudioOutcue' => 'オーディオ終了合図', + 'AudioSamplingRate' => 'オーディオサンプリングレート', + 'AudioSamplingResolution' => 'オーディオサンプリング解像度', + 'AudioType' => 'オーディオタイプ', + 'Author' => '作者', + 'AuthorsPosition' => '役職名', + 'AutoAperture' => { + Description => '自動絞り', + PrintConv => { + 'Off' => 'オフ', + 'On' => 'オン', + }, + }, + 'AutoBracket' => 'オートブラケット', + 'AutoBracketModeM' => { + Description => 'オートブラケット(モードM)', + PrintConv => { + 'Flash Only' => 'フラッシュのみ', + 'Flash/Aperture' => 'フラッシュ/絞り', + 'Flash/Speed' => 'フラッシュ/シャッター速度', + 'Flash/Speed/Aperture' => 'フラッシュ/シャッター速度/絞り', + }, + }, + 'AutoBracketOrder' => 'ブラケット順', + 'AutoBracketSet' => { + Description => 'オートブラケット設定', + PrintConv => { + 'AE & Flash' => '自動露出&フラッシュ', + 'AE Only' => '自動露出のみ', + 'Flash Only' => 'フラッシュのみ', + 'WB Bracketing' => 'ホワイトバランスブラケット', + }, + }, + 'AutoBracketing' => { + Description => 'オートブラケット', + PrintConv => { + 'No flash & flash' => 'フラッシュ無し&フラッシュ有り', + 'Off' => 'オフ', + 'On' => 'オン', + }, + }, + 'AutoExposureBracketing' => { + Description => 'フラッシュバイアス', + PrintConv => { + 'Off' => 'オフ', + 'On' => 'オン', + 'On (shot 1)' => 'オン(ショット1)', + 'On (shot 2)' => 'オン(ショット2)', + 'On (shot 3)' => 'オン(ショット3)', + }, + }, + 'AutoFP' => { + Description => 'オートFP', + PrintConv => { + 'Off' => 'オフ', + 'On' => 'オン', + }, + }, + 'AutoFocus' => { + Description => 'オートフォーカス', + PrintConv => { + 'Off' => 'オフ', + 'On' => 'オン', + }, + }, + 'AutoISO' => { + Description => 'ISOオート', + PrintConv => { + 'Off' => 'オフ', + 'On' => 'オン', + }, + }, + 'AutoISOMax' => 'ISOオート 最大感度', + 'AutoISOMinShutterSpeed' => 'ISOオート 最小シャッター速度', + 'AutoLightingOptimizer' => { + Description => 'オートライティングオプティマイザ', + PrintConv => { + 'Disable' => 'しない', + 'Enable' => 'する', + 'Low' => 'ソフト', + 'Off' => 'オフ', + 'Standard' => 'スタンダード', + 'Strong' => '強', + 'n/a' => '該当無し', + }, + }, + 'AutoLightingOptimizerOn' => { + PrintConv => { + 'No' => 'いいえ', + 'Yes' => 'はい', + }, + }, + 'AutoRedEye' => { + PrintConv => { + 'Off' => 'オフ', + 'On' => 'オン', + }, + }, + 'AutoRotate' => { + Description => '自動回転', + PrintConv => { + 'None' => '無し', + 'Rotate 180' => '180度回転', + 'Rotate 270 CW' => '270度回転 CW', + 'Rotate 90 CW' => '90度回転 CW', + 'n/a' => 'ソフトウェアで回転', + }, + }, + 'AuxiliaryLens' => '補助レンズ', + 'AvApertureSetting' => 'Av絞り設定', + 'AvSettingWithoutLens' => { + Description => 'レンズ未装着時の絞り数値設定', + PrintConv => { + 'Disable' => '不可', + 'Enable' => '可', + }, + }, + 'BToA0' => 'BからA0', + 'BToA1' => 'BからA1', + 'BToA2' => 'BからA2', + 'BWFilter' => '白黒フィルター', + 'BWMode' => { + Description => '白黒モード', + PrintConv => { + 'Off' => 'オフ', + 'On' => 'オン', + }, + }, + 'BabyAge' => '赤ちゃん/ペットの年齢', + 'BackgroundColorIndicator' => '背景色指標', + 'BackgroundColorValue' => '背景色値', + 'BackgroundTiling' => { + PrintConv => { + 'No' => 'いいえ', + 'Yes' => 'はい', + }, + }, + 'BadFaxLines' => '粗悪なFAX線', + 'BannerImageType' => { + PrintConv => { + 'None' => '無し', + }, + }, + 'BaseExposureCompensation' => '基本露出補正', + 'BaseISO' => 'ベース感度', + 'BaselineExposure' => 'ベースライン露出', + 'BaselineNoise' => 'ベースラインノイズ', + 'BaselineSharpness' => 'ベースラインシャープネス', + 'BatteryInfo' => '電源', + 'BatteryLevel' => 'バッテリーレベル', + 'BatteryOrder' => { + Description => 'バッテリー順', + PrintConv => { + 'Camera Battery First' => 'カメラのバッテリーを最初に使う', + 'MB-D10 First' => 'MB-D10のバッテリーを最初に使う', + }, + }, + 'BayerGreenSplit' => 'ベイヤーグリーン分割', + 'Beep' => { + Description => 'ビープ', + PrintConv => { + 'High' => '高い', + 'Low' => '低い', + 'Off' => 'オフ', + 'On' => 'オン', + }, + }, + 'BestQualityScale' => '高品質スケール', + 'BestShotMode' => { + Description => 'ベストショットモード', + PrintConv => { + 'Off' => 'オフ', + }, + }, + 'BitDepth' => 'ビット深度', + 'BitsPerComponent' => 'コンポーネントあたりビット', + 'BitsPerExtendedRunLength' => '拡張ランレングスあたりのビット', + 'BitsPerRunLength' => 'ランレングスあたりのビット', + 'BitsPerSample' => 'コンポーネントのビット数', + 'BlackLevel' => '黒レベル', + 'BlackLevel2' => '黒レベル2', + 'BlackLevelDeltaH' => '黒レベルデルタH', + 'BlackLevelDeltaV' => '黒レベルデルタV', + 'BlackLevelRepeatDim' => '黒レベル反復値', + 'BlackPoint' => '黒点', + 'BlueBalance' => 'ブルーバランス', + 'BlueMatrixColumn' => '青色マトリックス列', + 'BlueTRC' => '青色調増殖曲線', + 'BlurWarning' => { + Description => '手振れ警告', + PrintConv => { + 'Blur Warning' => '手振れ警告', + 'None' => '無し', + }, + }, + 'BodyBatteryADLoad' => '電源A/D本体起動時', + 'BodyBatteryADNoLoad' => '電源A/D本体オフ時', + 'BodyBatteryState' => '電源状態本体', + 'BodyFirmwareVersion' => '本体ファームウェアバージョン', + 'BracketMode' => { + Description => 'ブラケットモード', + PrintConv => { + 'Off' => 'オフ', + }, + }, + 'BracketSequence' => 'ブラケットシーケンス', + 'BracketShotNumber' => { + Description => 'ブラケットショット数', + PrintConv => { + 'n/a' => '該当無し', + }, + }, + 'BracketStep' => { + Description => 'ブラケットステップ', + PrintConv => { + '1 EV' => '1ステップ', + '1/3 EV' => '1/3ステップ', + '2/3 EV' => '2/3ステップ', + }, + }, + 'BracketValue' => 'ブラケット値', + 'Brightness' => 'ブライトネス', + 'BrightnessData' => 'ブライトネスデータ', + 'BrightnessValue' => 'ブライトネス', + 'BulbDuration' => 'バルブ時間', + 'BurstMode' => { + Description => 'ブラストモード', + PrintConv => { + 'Infinite' => '無限', + 'Off' => 'オフ', + 'On' => 'オン', + }, + }, + 'ButtonFunctionControlOff' => { + Description => 'サブ電子ダイヤル〈OFF〉時のボタン操作', + PrintConv => { + 'Disable main, Control, Multi-control' => 'メイン電子ダイヤル、サブ電子ダイヤル、マルチコントローラーは無効', + 'Normal (enable)' => '通常(有効)', + }, + }, + 'By-line' => '製作者', + 'By-lineTitle' => '製作者の職種', + 'CCDScanMode' => { + Description => 'CCDスキャンモード', + PrintConv => { + 'Interlaced' => 'インタレース', + 'Progressive' => 'プログレッシブ', + }, + }, + 'CFALayout' => 'CFAレイアウト', + 'CFAPattern' => 'CFAパターン', + 'CFAPattern2' => 'CFAパターン2', + 'CFAPlaneColor' => 'CFAプレーン色', + 'CFARepeatPatternDim' => 'CFA反復パターン特性', + 'CLModeShootingSpeed' => 'CLモード撮影速度', + 'CMContrast' => 'CMコントラスト', + 'CMExposureCompensation' => 'CM露出補正', + 'CMHue' => 'CM色相', + 'CMMFlags' => 'CMMフラグ', + 'CMSaturation' => 'CM彩度', + 'CMSharpness' => 'CMシャープネス', + 'CMWhiteBalance' => 'CMホワイトバランス', + 'CMWhiteBalanceComp' => 'CMホワイトバランス補正', + 'CMWhiteBalanceGrayPoint' => 'CMホワイトバランスグレーポイント', + 'CMYKEquivalent' => 'CMYK等価物', + 'CPUFirmwareVersion' => 'CPUファームウエアバージョン', + 'CPUType' => { + PrintConv => { + 'None' => '無し', + }, + }, + 'CalibrationDateTime' => 'キャリブレーション日時', + 'CalibrationIlluminant1' => { + Description => '光源キャリブレーション1', + PrintConv => { + 'Cloudy' => '曇り', + 'Cool White Fluorescent' => '白色蛍光灯', + 'Day White Fluorescent' => '昼白色蛍光灯', + 'Daylight' => '昼光', + 'Daylight Fluorescent' => '昼光色蛍光灯', + 'Fine Weather' => '良い天気', + 'Flash' => 'ストロボ', + 'Fluorescent' => '蛍光灯', + 'ISO Studio Tungsten' => 'ISOスタジオタングステン', + 'Other' => 'その他の光源', + 'Shade' => '日陰', + 'Standard Light A' => '標準ライトA', + 'Standard Light B' => '標準ライトB', + 'Standard Light C' => '標準ライトC', + 'Tungsten (Incandescent)' => 'タングステン(白熱灯)', + 'Unknown' => '不明', + 'Warm White Fluorescent' => '暖白光色蛍光灯', + 'White Fluorescent' => '温白色蛍光灯', + }, + }, + 'CalibrationIlluminant2' => { + Description => '光源キャリブレーション2', + PrintConv => { + 'Cloudy' => '曇り', + 'Cool White Fluorescent' => '白色蛍光灯', + 'Day White Fluorescent' => '昼白色蛍光灯', + 'Daylight' => '昼光', + 'Daylight Fluorescent' => '昼光色蛍光灯', + 'Fine Weather' => '良い天気', + 'Flash' => 'ストロボ', + 'Fluorescent' => '蛍光灯', + 'ISO Studio Tungsten' => 'ISOスタジオタングステン', + 'Other' => 'その他の光源', + 'Shade' => '日陰', + 'Standard Light A' => '標準ライトA', + 'Standard Light B' => '標準ライトB', + 'Standard Light C' => '標準ライトC', + 'Tungsten (Incandescent)' => 'タングステン(白熱灯)', + 'Unknown' => '不明', + 'Warm White Fluorescent' => '暖白光色蛍光灯', + 'White Fluorescent' => '温白色蛍光灯', + }, + }, + 'CameraCalibration1' => 'カメラキャリブレーション1', + 'CameraCalibration2' => 'カメラキャリブレーション2', + 'CameraCalibrationSig' => 'カメラキャリブレーションサイン', + 'CameraID' => 'カメラID', + 'CameraISO' => 'カメラISO', + 'CameraInfo' => 'ペンタックスモデル', + 'CameraOrientation' => { + Description => '画像の向き', + PrintConv => { + 'Horizontal (normal)' => '水平(標準)', + 'Rotate 270 CW' => '270度回転 CW', + 'Rotate 90 CW' => '90度回転 CW', + }, + }, + 'CameraParameters' => 'カメラパラメーター', + 'CameraSerialNumber' => 'カメラシリアル番号', + 'CameraSettings' => 'カメラ設定', + 'CameraSettingsVersion' => 'カメラ設定バージョン', + 'CameraTemperature' => 'カメラ温度', + 'CameraType' => { + Description => 'カメラタイプ', + PrintConv => { + 'Compact' => 'コンパクト', + 'DV Camera' => 'DVカメラ', + 'EOS High-end' => 'EOSハイエンド', + 'EOS Mid-range' => 'EOSミドルレンジ', + }, + }, + 'CameraType2' => 'カメラタイプ2', + 'CanonAFInfo' => 'AF情報', + 'CanonAFInfo2' => 'AF情報2', + 'CanonExposureMode' => { + Description => '露出モード', + PrintConv => { + 'Aperture-priority AE' => '絞り優先', + 'Bulb' => 'バルブ', + 'Depth-of-field AE' => '被写界深度AE', + 'Easy' => '簡単', + 'Manual' => 'マニュアル', + 'Program AE' => 'プログラムAE', + 'Shutter speed priority AE' => 'シャッター優先', + }, + }, + 'CanonFileInfo' => 'ファイル情報', + 'CanonFileLength' => 'ファイル長', + 'CanonFirmwareVersion' => 'ファームウェアバージョン', + 'CanonFlashMode' => { + Description => 'フラッシュモード', + PrintConv => { + 'Auto' => 'オート', + 'External flash' => '外付フラッシュ', + 'Off' => 'オフ', + 'On' => 'オン', + 'Red-eye reduction' => '赤目軽減', + 'Red-eye reduction (Auto)' => '赤目軽減(オート)', + 'Red-eye reduction (On)' => '赤目軽減(オン)', + 'Slow-sync' => 'スローシンクロ', + }, + }, + 'CanonFocalLength' => 'フォーカスタイプ', + 'CanonImageHeight' => '画像高さ', + 'CanonImageSize' => { + Description => 'イメージサイズ', + PrintConv => { + 'Large' => 'ラージ', + 'Medium' => 'ミドル', + 'Medium 1' => 'ミドル1', + 'Medium 2' => 'ミドル2', + 'Medium 3' => 'ミドル3', + 'Medium Movie' => 'ミディアム動画', + 'Postcard' => 'ハガキ', + 'Small' => 'スモール', + 'Small 1' => 'スモール1', + 'Small 2' => 'スモール2', + 'Small 3' => 'スモール3', + 'Small Movie' => 'スモール動画', + 'Widescreen' => 'ワイド画面', + }, + }, + 'CanonImageType' => 'イメージタイプ', + 'CanonImageWidth' => '画像幅', + 'CanonModelID' => 'モデルID', + 'Caption-Abstract' => '表題/説明', + 'CaptionWriter' => 'キャプション作成者', + 'CasioImageSize' => 'カシオイメージサイズ', + 'Categories' => 'カテゴリー', + 'Category' => 'カテゴリー', + 'CellLength' => 'セル長', + 'CellWidth' => 'セル幅', + 'CenterAFArea' => { + Description => '中央AFエリア', + PrintConv => { + 'Normal Zone' => 'ノーマルゾーン', + 'Wide Zone' => 'ワイドゾーン', + }, + }, + 'CenterWeightedAreaSize' => { + Description => '中央重点エリア', + PrintConv => { + 'Average' => '平均', + }, + }, + 'CharTarget' => '目的文字', + 'CharacterSet' => 'キャラクターセット', + 'ChromaBlurRadius' => '彩度ぼけ半径', + 'ChromaticAdaptation' => '色彩順応化', + 'Chromaticity' => '色度', + 'ChrominanceNR_TIFF_JPEG' => { + PrintConv => { + 'High' => '高い', + 'Low' => 'ソフト', + 'Off' => 'オフ', + }, + }, + 'ChrominanceNoiseReduction' => { + PrintConv => { + 'High' => '高い', + 'Low' => 'ソフト', + 'Off' => 'オフ', + }, + }, + 'City' => '都市', + 'ClassifyState' => '分類状態', + 'CleanFaxData' => '純粋なFAXデータ', + 'ClipPath' => 'クリップパス', + 'CodedCharacterSet' => 'キャラクタセットコード', + 'ColorAberrationControl' => { + Description => '色収差コントロール', + PrintConv => { + 'Off' => 'オフ', + 'On' => 'オン', + }, + }, + 'ColorAdjustment' => '色調整', + 'ColorAdjustmentMode' => { + Description => '色調整モード', + PrintConv => { + 'Off' => 'オフ', + 'On' => 'オン', + }, + }, + 'ColorBalance' => 'カラーバランス', + 'ColorBalanceAdj' => { + Description => 'カラーバランス調整', + PrintConv => { + 'Off' => 'オフ', + 'On' => 'オン', + }, + }, + 'ColorBalanceBlue' => 'カラーバランス青', + 'ColorBalanceGreen' => 'カラーバランス緑', + 'ColorBalanceRed' => 'カラーバランス赤', + 'ColorBoostData' => 'カラーブーストデータ', + 'ColorBoostLevel' => 'カラーブーストレベル1', + 'ColorBoostType' => { + Description => 'カラーブーストタイプ', + PrintConv => { + 'Nature' => '自然', + 'People' => '人々', + }, + }, + 'ColorBooster' => { + Description => 'カラーブースター', + PrintConv => { + 'Off' => 'オフ', + 'On' => 'オン', + }, + }, + 'ColorCalibrationMatrix' => 'カラーキャリブレーションマトリックステーブル', + 'ColorCharacterization' => 'カラー特徴描写', + 'ColorControl' => 'カラーコントロール', + 'ColorEffect' => { + Description => 'カラーエフェクト', + PrintConv => { + 'Black & White' => '白黒', + 'Cool' => '冷色', + 'Off' => 'オフ', + 'Sepia' => 'セピア', + 'Warm' => '暖色', + }, + }, + 'ColorFilter' => { + Description => 'カラーフィルター', + PrintConv => { + 'Black & White' => '白黒', + 'Blue' => '青', + 'Green' => '緑', + 'Off' => 'オフ', + 'Pink' => 'ピンク', + 'Purple' => '紫', + 'Red' => '赤', + 'Sepia' => 'セピア', + 'Yellow' => '黄色', + }, + }, + 'ColorGain' => 'カラーゲイン', + 'ColorHue' => '色相', + 'ColorInfo' => '色情報', + 'ColorMap' => 'カラーマップ', + 'ColorMatrix' => 'カラーマトリックス', + 'ColorMatrix1' => 'カラーマトリックス1', + 'ColorMatrix2' => 'カラーマトリックス2', + 'ColorMatrixNumber' => 'カラーマトリックス番号', + 'ColorMode' => { + Description => 'カラーモード', + PrintConv => { + 'Autumn Leaves' => '紅葉', + 'B & W' => '白黒', + 'B&W' => '白黒', + 'Black & White' => '白黒', + 'Chrome' => 'クローム', + 'Clear' => 'クリアー', + 'Deep' => 'ディープ', + 'Evening' => '夕焼け', + 'Landscape' => '風景', + 'Light' => 'ライト', + 'Natural' => 'ナチュラル', + 'Natural color' => 'ナチュラルカラー', + 'Natural sRGB' => 'ナチュラル sRGB', + 'Natural+ sRGB' => 'ナチュラル+ sRGB', + 'Neutral' => 'ニュートラル', + 'Night Portrait' => '人物夜景', + 'Night Scene' => '夜景', + 'Night View' => 'ナイトビュー', + 'Night View/Portrait' => '夜景/夜景ポートレート', + 'Normal' => 'ノーマル', + 'Off' => 'オフ', + 'Portrait' => 'ポートレート', + 'Sepia' => 'セピア', + 'Solarization' => 'ソラリゼーション', + 'Standard' => 'スタンダード', + 'Sunset' => '夕日', + 'Vivid' => 'ビビッド', + 'Vivid color' => 'ビビッドカラー', + }, + }, + 'ColorMoireReduction' => { + PrintConv => { + 'Off' => 'オフ', + 'On' => 'オン', + }, + }, + 'ColorMoireReductionMode' => { + Description => '色モアレリダクション', + PrintConv => { + 'High' => '高い', + 'Low' => 'ソフト', + 'Off' => 'オフ', + }, + }, + 'ColorPalette' => 'カラーパレット', + 'ColorProfile' => { + Description => 'カラープロフィール', + PrintConv => { + 'Embedded' => '埋め込み', + 'Not Embedded' => '埋め込み無し', + }, + }, + 'ColorRepresentation' => '色表現', + 'ColorReproduction' => '色再現', + 'ColorResponseUnit' => '色応答単位', + 'ColorSequence' => 'カラーシーケンス', + 'ColorSpace' => { + Description => '色空間', + PrintConv => { + 'ICC Profile' => 'ICCプロフィール', + 'Monochrome' => 'モノトーン', + 'Uncalibrated' => '未調整', + }, + }, + 'ColorSpaceData' => 'カラースペースデータ', + 'ColorTable' => 'カラーテーブル', + 'ColorTemperature' => '色温度', + 'ColorTone' => { + Description => 'カラートーン', + PrintConv => { + 'Normal' => '標準', + }, + }, + 'ColorToneFaithful' => 'カラートーン忠実設定', + 'ColorToneLandscape' => 'カラートーン風景', + 'ColorToneNeutral' => 'カラートーンニュートラル', + 'ColorTonePortrait' => 'カラートーンポートレート', + 'ColorToneStandard' => 'カラートーンスタンダード', + 'ColorToneUserDef1' => 'カラートーンユーザ設定1', + 'ColorToneUserDef2' => 'カラートーンユーザ設定2', + 'ColorToneUserDef3' => 'カラートーンユーザ設定3', + 'ColorantOrder' => '着色順', + 'ColorantTable' => '着色テーブル', + 'ColorimetricReference' => '比色分析参照', + 'CommandDials' => { + Description => 'コマンダーダイヤル', + PrintConv => { + 'Reversed (Main Aperture, Sub Shutter)' => 'リバース', + 'Standard (Main Shutter, Sub Aperture)' => 'デフォルト', + }, + }, + 'CommandDialsApertureSetting' => { + Description => 'コマンドダイヤルカスタマイズ 絞り設定', + PrintConv => { + 'Aperture Ring' => '絞りリング', + 'Sub-command Dial' => 'サブコントロールダイヤル', + }, + }, + 'CommandDialsChangeMainSub' => { + Description => 'コマンドダイヤルカスタマイズ メイン/サブ変更', + PrintConv => { + 'Off' => 'オフ', + 'On' => 'オン', + }, + }, + 'CommandDialsMenuAndPlayback' => { + Description => 'コマンドダイヤルカスタマイズ メニューと再生', + PrintConv => { + 'Off' => 'オフ', + 'On' => 'オン', + }, + }, + 'CommandDialsReverseRotation' => { + Description => 'コマンドダイヤルカスタマイズ 回転保持', + PrintConv => { + 'No' => 'いいえ', + 'Yes' => 'はい', + }, + }, + 'CommanderChannel' => 'コマンダーモード チャンネル', + 'CommanderGroupAManualOutput' => 'コマンダーモード グループA M 補正', + 'CommanderGroupAMode' => { + Description => 'コマンダーモード グループA モード', + PrintConv => { + 'Auto Aperture' => '自動絞り(AA)', + 'Manual' => 'マニュアル', + 'Off' => 'オフ', + }, + }, + 'CommanderGroupA_TTL-AAComp' => 'コマンダーモード 内蔵フラッシュ TTL/AA 補正', + 'CommanderGroupBManualOutput' => 'コマンダーモード グループB M 補正', + 'CommanderGroupBMode' => { + Description => 'コマンダーモード グループB モード', + PrintConv => { + 'Auto Aperture' => '自動絞り(AA)', + 'Manual' => 'マニュアル', + 'Off' => 'オフ', + }, + }, + 'CommanderGroupB_TTL-AAComp' => 'コマンダーモード グループB TTL/AA 補正', + 'CommanderInternalFlash' => { + Description => 'コマンダーモード 内蔵フラッシュ モード', + PrintConv => { + 'Manual' => 'マニュアル', + 'Off' => 'オフ', + }, + }, + 'CommanderInternalManualOutput' => 'コマンダーモード 内蔵フラッシュ M 補正', + 'CommanderInternalTTLComp' => 'コマンダーモード 内蔵フラッシュ TTL 補正', + 'Comment' => 'コメント', + 'Compilation' => { + PrintConv => { + 'No' => 'いいえ', + 'Yes' => 'はい', + }, + }, + 'ComponentsConfiguration' => '各構成要素の意味', + 'CompressedBitsPerPixel' => '画像圧縮モード', + 'CompressedImageSize' => '圧縮画像サイズ', + 'Compression' => { + Description => '圧縮計画', + PrintConv => { + 'JPEG' => 'JPEG圧縮率', + 'JPEG (old-style)' => 'JPEG (古い形式)', + 'None' => '無し', + 'Uncompressed' => '非圧縮', + }, + }, + 'CompressionRatio' => '圧縮率', + 'CompressionType' => { + PrintConv => { + 'None' => '無し', + }, + }, + 'ConditionalFEC' => 'フラッシュ露出補正', + 'ConnectionSpaceIlluminant' => '接続スペース光源', + 'ConsecutiveBadFaxLines' => '連続的に粗悪なFAX線', + 'Contact' => '連絡', + 'ContentLocationCode' => '内容位置コード', + 'ContentLocationName' => '内容位置名', + 'ContinuousDrive' => { + Description => 'ドライブモード', + PrintConv => { + 'Continuous' => '連続撮影', + 'Continuous, High' => '連写(High)', + 'Continuous, Low' => '連写(Low)', + 'Continuous, Speed Priority' => '高速連写', + 'Movie' => '動画', + 'Single' => '1コマ撮影', + }, + }, + 'ContinuousShootingSpeed' => { + Description => '連続撮影速度', + PrintConv => { + 'Disable' => 'しない', + 'Enable' => 'する', + }, + }, + 'ContinuousShotLimit' => { + Description => '連続撮影時の撮影枚数制限', + PrintConv => { + 'Disable' => 'しない', + 'Enable' => 'する', + }, + }, + 'Contrast' => { + Description => 'コントラスト', + PrintConv => { + '+1 (medium high)' => '+1 (少し高い)', + '+2 (high)' => '+2 (ハード)', + '+3 (very high)' => '+3 (かなり高い)', + '-1 (medium low)' => '-1 (少し低い)', + '-2 (low)' => '-2 (ソフト)', + '-3 (very low)' => '-3 (かなり低い)', + '0 (normal)' => '0 (スタンダード)', + 'Film Simulation' => 'フィルムシミュレーション', + 'High' => 'ハード', + 'Low' => 'ソフト', + 'Medium High' => '少し高い', + 'Medium Low' => '少し低い', + 'Normal' => 'スタンダード', + }, + }, + 'ContrastCurve' => 'コントラストカーブ', + 'ContrastFaithful' => 'コントラスト忠実設定', + 'ContrastLandscape' => 'コントラスト風景', + 'ContrastMonochrome' => 'コントラストモノクロ', + 'ContrastNeutral' => 'コントラストニュートラル', + 'ContrastPortrait' => 'コントラストポートレート', + 'ContrastSetting' => 'コントラスト設定', + 'ContrastStandard' => 'コントラストスタンダード', + 'ContrastUserDef1' => 'コントラストユーザ設定1', + 'ContrastUserDef2' => 'コントラストユーザ設定2', + 'ContrastUserDef3' => 'コントラストユーザ設定3', + 'ControlMode' => { + Description => 'コントロールモード', + PrintConv => { + 'Camera Local Control' => 'カメラローカルコントロール', + 'Computer Remote Control' => 'コンピュータリモートコントロール', + 'n/a' => '該当無し', + }, + }, + 'ConversionLens' => { + Description => 'コンバージョンレンズ', + PrintConv => { + 'Macro' => 'マクロ', + 'Off' => 'オフ', + 'Telephoto' => 'テレフォト', + 'Wide' => 'ワイド', + }, + }, + 'Converter' => 'コンバーター', + 'Copyright' => '版権所有者', + 'CopyrightNotice' => '著作権表示', + 'CopyrightStatus' => { + PrintConv => { + 'Unknown' => '不明', + }, + }, + 'CoringFilter' => 'コアリングフィルタ', + 'CoringValues' => 'コアリング値', + 'Country' => '国名', + 'Country-PrimaryLocationCode' => 'ISO国コード', + 'Country-PrimaryLocationName' => '国', + 'CountryCode' => '撮影国コード', + 'CreateDate' => 'デジタルデータ作成日時', + 'CreationDate' => '作成日時', + 'CreativeStyle' => { + Description => 'クリエイティブスタイル', + PrintConv => { + 'Autumn' => '秋', + 'Autumn Leaves' => '紅葉', + 'B&W' => '白黒', + 'Clear' => 'クリアー', + 'Deep' => 'ディープ', + 'Landscape' => '風景', + 'Light' => 'ライト', + 'Neutral' => 'ニュートラル', + 'Night View/Portrait' => '夜景/夜景ポートレート', + 'Portrait' => 'ポートレート', + 'Sepia' => 'セピア', + 'Standard' => 'スタンダード', + 'Sunset' => '夕日', + 'Vivid' => 'ビビッド', + }, + }, + 'Creator' => '製作者', + 'CreatorAddress' => 'クリエーター - 住所', + 'CreatorCity' => 'クリエーター - 街', + 'CreatorContactInfo' => '作成者のコン タクト先', + 'CreatorCountry' => 'クリエーター - 国', + 'CreatorPostalCode' => 'クリエーター - 郵便番号', + 'CreatorRegion' => 'クリエーター - 国/州', + 'CreatorWorkEmail' => 'クリエーター - 電子メール', + 'CreatorWorkTelephone' => 'クリエーター - 電話番号', + 'CreatorWorkURL' => 'クリエーター - WEBサイト', + 'Credit' => 'プロバイダー', + 'CropActive' => { + PrintConv => { + 'No' => 'いいえ', + 'Yes' => 'はい', + }, + }, + 'CropData' => 'クロップデータ', + 'CropHeight' => '最終高さ', + 'CropHiSpeed' => 'ハイスピードクロップ', + 'CropLeft' => '開始オフセットX', + 'CropTop' => '開始オフセットY', + 'CropWidth' => '最終幅', + 'CurrentICCProfile' => 'カレントICCプロファイル', + 'CurrentPreProfileMatrix' => 'カレントプロファイルマトリックス', + 'Curves' => { + Description => 'カーブ', + PrintConv => { + 'Off' => 'オフ', + 'On' => 'オン', + }, + }, + 'Custom1' => 'カスタム1', + 'Custom2' => 'カスタム2', + 'Custom3' => 'カスタム3', + 'Custom4' => 'カスタム4', + 'CustomRendered' => { + Description => 'カスタム画像処理', + PrintConv => { + 'Custom' => 'カスタム処理', + 'Normal' => '標準処理', + }, + }, + 'CustomSaturation' => 'カスタム彩度', + 'D-LightingHQ' => { + Description => 'DライティングHQ', + PrintConv => { + 'Off' => 'オフ', + 'On' => 'オン', + }, + }, + 'D-LightingHQColorBoost' => 'DライティングHQカラーブースト', + 'D-LightingHQHighlight' => 'DライティングHQハイライト', + 'D-LightingHQSelected' => { + Description => 'DライティングHQ選択', + PrintConv => { + 'No' => 'いいえ', + 'Yes' => 'はい', + }, + }, + 'D-LightingHQShadow' => 'DライティングHQシャドウ', + 'D-LightingHS' => { + Description => 'DライティングHS', + PrintConv => { + 'Off' => 'オフ', + 'On' => 'オン', + }, + }, + 'D-LightingHSAdjustment' => 'DライティングHS調整', + 'D-LightingHSColorBoost' => 'DライティングHSカラーブースト', + 'DECPosition' => { + Description => 'DEC位置', + PrintConv => { + 'Contrast' => 'コントラスト', + 'Exposure' => '露出', + 'Filter' => 'フィルター', + 'Saturation' => '彩度', + }, + }, + 'DNGBackwardVersion' => 'DNGバックワードバージョン', + 'DNGLensInfo' => 'レンズ情報', + 'DNGVersion' => 'DNGバージョン', + 'DSPFirmwareVersion' => 'DSPファームウエアバージョン', + 'DataCompressionMethod' => 'データ圧縮アルゴリズム プロバイダー/オーナー', + 'DataDump' => 'データダンプ', + 'DataImprint' => { + Description => 'データインプリント', + PrintConv => { + 'None' => '無し', + 'Text' => 'テキスト', + }, + }, + 'DataType' => '日付型', + 'Date' => '日付', + 'DateCreated' => '作成日付', + 'DateDisplayFormat' => { + Description => '日付形式', + PrintConv => { + 'D/M/Y' => '日/月/年', + 'M/D/Y' => '月/日/年', + 'Y/M/D' => '年/月/日', + }, + }, + 'DateSent' => '発送日付', + 'DateStampMode' => { + Description => '日付スタンプモード', + PrintConv => { + 'Date' => '日付', + 'Off' => 'オフ', + }, + }, + 'DateTime' => 'ファイル作成日時', + 'DateTimeOriginal' => 'オリジナルデータ作成日時', + 'DaylightSavings' => { + Description => '夏時間', + PrintConv => { + 'No' => 'オフ', + 'Yes' => 'オン', + }, + }, + 'DefaultCropOrigin' => 'デフォルト切取り基点', + 'DefaultCropSize' => 'デフォルト切取りサイズ', + 'DefaultScale' => 'デフォルトスケール', + 'DeletedImageCount' => '削除イメージカウント', + 'Description' => '説明', + 'Destination' => '宛先', + 'DestinationCity' => '目的地', + 'DestinationCityCode' => '目的地コード', + 'DestinationDST' => { + Description => '目的地DST', + PrintConv => { + 'No' => 'いいえ', + 'Yes' => 'はい', + }, + }, + 'DevelopmentDynamicRange' => '進化ダイナミックレンジ', + 'DeviceAttributes' => '機器属性', + 'DeviceManufacturer' => '機器メーカー', + 'DeviceMfgDesc' => '機器メーカー説明', + 'DeviceModel' => '機器モデル', + 'DeviceModelDesc' => '機器モデル説明', + 'DeviceSettingDescription' => 'デバイス設定の説明', + 'DialDirectionTvAv' => { + Description => 'Tv/Av値設定時のダイヤル回転', + PrintConv => { + 'Normal' => '通常', + 'Reversed' => '設定方向を反転', + }, + }, + 'DigitalCreationDate' => 'デジタル作成日付', + 'DigitalCreationTime' => 'デジタル作成時間', + 'DigitalGEM' => 'デジタルGEM', + 'DigitalICE' => 'デジタルICE', + 'DigitalROC' => 'デジタルROC', + 'DigitalZoom' => { + Description => 'デジタルズーム', + PrintConv => { + 'None' => '無し', + 'Off' => 'オフ', + 'Other' => '未確認', + }, + }, + 'DigitalZoomOn' => { + Description => 'デジタルズームオン', + PrintConv => { + 'Off' => 'オフ', + 'On' => 'オン', + }, + }, + 'DigitalZoomRatio' => 'デジタルズーム比率', + 'Directory' => 'ファイルの場所', + 'DirectoryIndex' => 'ディレクトリ索引', + 'DirectoryNumber' => 'ディレクトリ番号', + 'DisplayAperture' => '絞り表示', + 'DisplaySize' => { + PrintConv => { + 'Normal' => '標準', + }, + }, + 'DistortionCorrection' => { + Description => '歪曲修正', + PrintConv => { + 'Off' => 'オフ', + 'On' => 'オン', + }, + }, + 'DistortionCorrection2' => { + Description => '歪曲補正編集', + PrintConv => { + 'Off' => 'オフ', + 'On' => 'オン', + }, + }, + 'DjVuVersion' => 'DjVuバージョン', + 'DocumentHistory' => '文書履歴', + 'DocumentName' => 'ドキュメント名', + 'DocumentNotes' => '文書ノート', + 'DotRange' => 'ドット範囲', + 'DriveMode' => { + Description => 'ドライブモード', + PrintConv => { + 'Bracketing' => 'ブラケット', + 'Burst' => '高速連射', + 'Continuous' => '連続撮影', + 'Continuous High' => '連射 (Hi)', + 'Continuous Shooting' => '連続撮影', + 'HS continuous' => 'HS連写', + 'Interval' => 'インターバル', + 'Multiple Exposure' => '複数の露出', + 'No Timer' => 'タイマー無し', + 'Off' => 'オフ', + 'Remote Control' => 'リモコン', + 'Remote Control (3 s delay)' => 'リモコン (3秒後レリーズ)', + 'Self-timer' => 'セルフタイマー', + 'Self-timer (12 s)' => 'セルフタイマー (12秒)', + 'Self-timer (2 s)' => 'セルフタイマー (2秒)', + 'Self-timer Operation' => 'セルフタイマー', + 'Shutter Button' => 'シャッターボタン', + 'Single' => '1コマ撮影', + 'Single Exposure' => 'シングル露出', + 'Single Frame' => '1コマ撮影', + 'Single Shot' => '1コマ撮影', + 'Single-frame' => '1コマ撮影', + 'Single-frame Shooting' => '1コマ撮影', + 'UHS continuous' => 'UHS連写', + }, + }, + 'DriveMode2' => { + Description => '多重露光', + PrintConv => { + 'Single-frame' => '1コマ撮影', + }, + }, + 'DynamicAFArea' => { + Description => 'ダイナミックAFエリア', + PrintConv => { + '21 Points' => '21点', + '51 Points' => '51点', + '51 Points (3D-tracking)' => '51点(3Dトラッキング)', + '9 Points' => '9点', + }, + }, + 'DynamicRange' => { + Description => 'ダイナミックレンジ', + PrintConv => { + 'Standard' => 'スタンダード', + 'Wide' => 'ワイド', + }, + }, + 'DynamicRangeExpansion' => { + Description => 'ダイナミックレンジ拡大', + PrintConv => { + 'Off' => 'オフ', + 'On' => 'オン', + }, + }, + 'DynamicRangeOptimizer' => { + Description => 'Dレンジオプティマイザー', + PrintConv => { + 'Advanced Auto' => 'アドバンスオート', + 'Advanced Lv1' => 'アドバンスLv1', + 'Advanced Lv2' => 'アドバンスLv2', + 'Advanced Lv3' => 'アドバンスLv3', + 'Advanced Lv4' => 'アドバンスLv4', + 'Advanced Lv5' => 'アドバンスLv5', + 'Auto' => 'オート', + 'Off' => 'オフ', + 'Standard' => 'スタンダード', + }, + }, + 'DynamicRangeSetting' => 'ダイナミックレンジ設定', + 'E-DialInProgram' => { + Description => '電子ダイヤルプログラム', + PrintConv => { + 'P Shift' => 'Pシフト', + 'Tv or Av' => 'TvかAv', + }, + }, + 'ETTLII' => { + PrintConv => { + 'Average' => '平均', + 'Evaluative' => '評価', + }, + }, + 'EVStepInfo' => 'EVステップ情報', + 'EVStepSize' => { + Description => 'EVステップ', + PrintConv => { + '1/2 EV' => '1/2ステップ', + '1/3 EV' => '1/3ステップ', + }, + }, + 'EVSteps' => { + Description => '露出ステップ', + PrintConv => { + '1/2 EV Steps' => '1/2 EVステップ', + '1/3 EV Steps' => '1/3 EVステップ', + }, + }, + 'EasyExposureCompensation' => { + Description => '簡単な露出補正', + PrintConv => { + 'Off' => 'オフ', + 'On' => 'オン', + 'On (auto reset)' => 'オン(自動リセット)', + }, + }, + 'EasyMode' => { + Description => '簡単モード', + PrintConv => { + 'Aquarium' => '水族館', + 'Beach' => 'ビーチ', + 'Black & White' => '白黒', + 'Color Accent' => 'カラーアクセント', + 'Color Swap' => 'スイッチカラー', + 'Digital Macro' => 'デジタルマクロ', + 'Fast shutter' => '高速シャッター', + 'Fireworks' => '花火', + 'Flash Off' => 'フラッシュオフ', + 'Foliage' => '葉', + 'Full auto' => 'フルオート', + 'Gray Scale' => 'グレースケール', + 'ISO 3200' => 'ISO3200', + 'Indoor' => '室内', + 'Kids & Pets' => 'キッズ&ペット', + 'Landscape' => '風景', + 'Long Shutter' => '長秒シャッター', + 'Macro' => 'マクロ', + 'Manual' => 'マニュアル', + 'My Colors' => 'ワンポイントカラー', + 'Neutral' => 'ニュートラル', + 'Night' => '夜景', + 'Night Scene' => '夜景', + 'Night Snapshot' => 'ナイトスナップ', + 'Pan focus' => 'パンフォーカス', + 'Portrait' => 'ポートレート', + 'Sepia' => 'セピア', + 'Slow shutter' => 'スローシャッター', + 'Snow' => 'スノー', + 'Sports' => 'スポーツ', + 'Still Image' => '静止画像', + 'Sunset' => '夕焼け', + 'Super Macro' => 'スーパーマクロ', + 'Underwater' => '水中', + 'Vivid' => 'ビビッド', + }, + }, + 'EdgeNoiseReduction' => { + Description => 'エッジノイズリダクション', + PrintConv => { + 'Off' => 'オフ', + 'On' => 'オン', + }, + }, + 'EditStatus' => '編集状態', + 'EditorialUpdate' => { + Description => '更新編集', + PrintConv => { + 'Additional language' => '追加言語', + }, + }, + 'EffectiveLV' => '効果レベル', + 'Emphasis' => { + PrintConv => { + 'None' => '無し', + }, + }, + 'EncodingProcess' => 'JPEGの符号化処理', + 'EndPoints' => '末端', + 'EnhanceDarkTones' => { + PrintConv => { + 'Off' => 'オフ', + 'On' => 'オン', + }, + }, + 'Enhancement' => { + Description => '強度', + PrintConv => { + 'Blue' => '青', + 'Flesh Tones' => '肌調', + 'Green' => '緑', + 'Off' => 'オフ', + 'Red' => '赤', + }, + }, + 'Enhancer' => '増大値2', + 'EnhancerValues' => '増大値', + 'EnvelopeNumber' => 'エンベロープ数', + 'EnvelopePriority' => { + Description => 'エンベロープ優先度', + PrintConv => { + '0 (reserved)' => '0 (将来拡張用)', + '1 (most urgent)' => '1 (高い緊急性)', + '5 (normal urgency)' => '5 (普通の緊急性)', + '8 (least urgent)' => '8 (低い緊急性)', + '9 (user-defined priority)' => '9 (ユーザ定義優先度)', + }, + }, + 'EnvelopeRecordVersion' => 'エンベロープレコードバージョン', + 'EpsonImageHeight' => 'エプソン画像高', + 'EpsonImageWidth' => 'エプソン画像幅', + 'EpsonSoftware' => 'エプソンソフトウェア', + 'Equipment' => 'イクイップメントIFDポインター', + 'EquipmentVersion' => 'イクイップメントバージョン', + 'ExcursionTolerance' => '振幅許容範囲', + 'ExifCameraInfo' => 'Exifカメラ情報', + 'ExifImageHeight' => '画像高さ', + 'ExifImageWidth' => '画像幅', + 'ExifOffset' => 'Exif IFDへのポインタ', + 'ExifToolVersion' => 'ExifToolバージョン', + 'ExifVersion' => 'Exifバージョン', + 'ExpandFilm' => '拡張フイルム', + 'ExpandFilterLens' => '拡張レンズフィルター', + 'ExpandFlashLamp' => '拡張フラッシュランプ', + 'ExpandLens' => '拡張レンズ', + 'ExpandScanner' => '拡張スキャナー', + 'ExpandSoftware' => '拡張ソフト', + 'ExpirationDate' => '有効日付', + 'ExpirationTime' => '有効時間', + 'Exposure' => '露出', + 'ExposureBracketStepSize' => '露出ブラケットステップサイズ', + 'ExposureBracketValue' => '露出ブラケット値', + 'ExposureCompStepSize' => { + Description => '露出補正/ファインチューン', + PrintConv => { + '1 EV' => '1ステップ', + '1/2 EV' => '1/2ステップ', + '1/3 EV' => '1/3ステップ', + }, + }, + 'ExposureCompensation' => '露出補正値', + 'ExposureControlStepSize' => { + Description => '露出制御のEVステップ', + PrintConv => { + '1 EV' => '1ステップ', + '1/2 EV' => '1/2ステップ', + '1/3 EV' => '1/3ステップ', + }, + }, + 'ExposureDelayMode' => { + Description => '露出遅延モード', + PrintConv => { + 'Off' => 'オフ', + 'On' => 'オン', + }, + }, + 'ExposureDifference' => '露出差', + 'ExposureIndex' => '露出指標', + 'ExposureLevelIncrements' => { + Description => '露出制御のEVステップ', + PrintConv => { + '1-stop set, 1/3-stop comp.' => '設定1 露出補正1/3', + '1/2 Stop' => '1/2ステップ', + '1/2-stop set, 1/2-stop comp.' => '設定1/2 露出補正1/2', + '1/3 Stop' => '1/3ステップ', + '1/3-stop set, 1/3-stop comp.' => '設定1/3 露出補正1/3', + }, + }, + 'ExposureMode' => { + Description => '露光モード', + PrintConv => { + 'Aperture Priority' => '絞り優先', + 'Aperture-priority AE' => '絞り優先', + 'Auto' => '自動露出', + 'Auto bracket' => 'オートブラケット', + 'Bulb' => 'バルブ', + 'Landscape' => '風景', + 'Manual' => 'マニュアル露出', + 'Night Scene / Twilight' => '夜景', + 'Portrait' => 'ポートレート', + 'Program' => 'プログラム', + 'Program AE' => 'プログラムAE', + 'Program-shift' => 'プログラムシフト', + 'Shutter Priority' => 'シャッター優先', + 'Shutter speed priority AE' => 'シャッター優先', + 'n/a' => '未設定', + }, + }, + 'ExposureModeInManual' => { + Description => 'マニュアル露出時の測光モード', + PrintConv => { + 'Center-weighted average' => '中央重点', + 'Evaluative metering' => '評価測光', + 'Partial metering' => '部分', + 'Specified metering mode' => '設定測光モード', + 'Spot metering' => 'スポット', + }, + }, + 'ExposureProgram' => { + Description => '露出プログラム', + PrintConv => { + 'Action (High speed)' => 'スポーツモード(高速シャッター優先)', + 'Aperture Priority' => '絞り優先', + 'Aperture-priority AE' => '絞り優先', + 'Bulb' => 'バルブ', + 'Creative (Slow speed)' => 'クリエイティブプログラム(被写界深度優先)', + 'Landscape' => '風景モード', + 'Manual' => 'マニュアル', + 'Not Defined' => '未定義', + 'Portrait' => 'ポートレートモード', + 'Program' => 'プログラム', + 'Program AE' => 'ノーマルプログラム', + 'Shutter Priority' => 'シャッター優先', + 'Shutter speed priority AE' => 'シャッター優先', + }, + }, + 'ExposureTime' => '露出時間', + 'ExposureTime2' => '露出時間 2', + 'ExposureWarning' => { + Description => '露出警告', + PrintConv => { + 'Bad exposure' => '露出失敗', + 'Good' => '適正', + }, + }, + 'ExtendedWBDetect' => { + Description => '延長WB検出', + PrintConv => { + 'Off' => 'オフ', + 'On' => 'オン', + }, + }, + 'Extender' => 'エクステンダー', + 'ExtenderFirmwareVersion' => 'エクステンダーファームウェアバージョン', + 'ExtenderModel' => 'エクステンダーモデル', + 'ExtenderSerialNumber' => 'エクステンダーシリアル番号', + 'ExternalFlash' => { + Description => '外付フラッシュ', + PrintConv => { + 'Off' => 'オフ', + 'On' => 'オン', + }, + }, + 'ExternalFlashAE1' => '外付フラッシュAE1?', + 'ExternalFlashAE1_0' => '外付フラッシュAE1(0)?', + 'ExternalFlashAE2' => '外付フラッシュAE2?', + 'ExternalFlashAE2_0' => '外付フラッシュAE2(0)?', + 'ExternalFlashBounce' => { + Description => '外付フラッシュバウンス', + PrintConv => { + 'Bounce' => 'バウンス', + 'Bounce or Off' => 'バウンスかオフ', + 'Direct' => 'ダイレクト', + 'No' => 'いいえ', + 'Yes' => 'はい', + 'n/a' => '該当無し', + }, + }, + 'ExternalFlashExposureComp' => { + Description => '外付ストロボ露出補正', + PrintConv => { + 'n/a' => '未設定(オフかオートモード)', + 'n/a (Manual Mode)' => '未設定(マニュアルモード)', + }, + }, + 'ExternalFlashFlags' => '外付フラッシュフラグ', + 'ExternalFlashGuideNumber' => '外付フラッシュガイドナンバー?', + 'ExternalFlashMode' => { + Description => '外付フラッシュモード', + PrintConv => { + 'Off' => 'オフ', + 'On, Auto' => 'オン、オート', + 'On, Contrast-control Sync' => 'オン、光量比制御シンクロ', + 'On, Flash Problem' => 'オン、フラッシュの問題?', + 'On, High-speed Sync' => 'オン、ハイスピードシンクロ', + 'On, Manual' => 'オン、マニュアル', + 'On, P-TTL Auto' => 'オン、P-TTLオート', + 'On, Wireless' => 'オン、ワイヤレス', + 'On, Wireless, High-speed Sync' => 'オン、ワイヤレス、ハイスピードシンクロ', + 'n/a - Off-Auto-Aperture' => '該当なし-自動絞りオフ', + }, + }, + 'ExternalFlashZoom' => '外付フラッシュズーム', + 'ExtraSamples' => '特別サンプル', + 'FNumber' => 'F値', + 'Face0Position' => '顔0位置', + 'Face1Position' => '顔1位置', + 'Face2Position' => '顔2位置', + 'Face3Position' => '顔3位置', + 'Face4Position' => '顔4位置', + 'Face5Position' => '顔5位置', + 'Face6Position' => '顔6位置', + 'Face7Position' => '顔7位置', + 'Face8Position' => '顔8位置', + 'Face9Position' => '顔9位置', + 'FaceDetect' => { + Description => '顔認識', + PrintConv => { + 'Off' => 'オフ', + 'On' => 'オン', + }, + }, + 'FaceDetectArea' => '顔エリア', + 'FaceDetectFrameSize' => 'フレームサイズ', + 'FaceOrientation' => { + PrintConv => { + 'Horizontal (normal)' => '水平(標準)', + 'Rotate 180' => '180度回転', + 'Rotate 270 CW' => '270度回転 CW', + 'Rotate 90 CW' => '90度回転 CW', + }, + }, + 'FacesDetected' => '顔認識', + 'FastSeek' => { + PrintConv => { + 'No' => 'いいえ', + 'Yes' => 'はい', + }, + }, + 'FaxProfile' => { + PrintConv => { + 'Unknown' => '不明', + }, + }, + 'FaxRecvParams' => 'FAX受信パラメータ', + 'FaxRecvTime' => 'FAX受信時間', + 'FaxSubAddress' => 'FAXサブアドレス', + 'FileFormat' => 'ファイル形式', + 'FileIndex' => 'ファイル索引', + 'FileInfo' => 'ファイル情報', + 'FileInfoVersion' => 'ファイル情報バージョン', + 'FileModifyDate' => '更新日時', + 'FileName' => 'ファイル名', + 'FileNumber' => 'ファイル番号', + 'FileNumberMemory' => { + Description => 'ファイル番号メモリ', + PrintConv => { + 'Off' => 'オフ', + 'On' => 'オン', + }, + }, + 'FileNumberSequence' => { + Description => 'ファイル番号連番', + PrintConv => { + 'Off' => 'オフ', + 'On' => 'オン', + }, + }, + 'FileSize' => 'ファイルのサイズ', + 'FileSource' => { + Description => 'ファイルソース', + PrintConv => { + 'Digital Camera' => 'デジタルカメラ', + 'Film Scanner' => 'フィルムスキャナー', + 'Reflection Print Scanner' => '反射印刷スキャナー', + }, + }, + 'FileType' => 'ファイルタイプ', + 'FileVersion' => 'ファイル形式バージョン', + 'Filename' => 'ファイル名', + 'FillFlashAutoReduction' => { + Description => '日中シンクロ・ストロボ露出自動低減制御', + PrintConv => { + 'Disable' => 'しない', + 'Enable' => 'する', + }, + }, + 'FillOrder' => { + Description => 'フルオーダー', + PrintConv => { + 'Normal' => '標準', + }, + }, + 'FilmMode' => { + Description => 'フィルムモード', + PrintConv => { + 'Dynamic (B&W)' => 'ダイナミック(白黒)', + 'Dynamic (color)' => 'ダイナミック(カラー)', + 'Nature (color)' => 'ナチュラル(カラー)', + 'Smooth (B&W)' => '滑らか(白黒)', + 'Smooth (color)' => '滑らか(カラー)', + 'Standard (B&W)' => 'スタンダード(白黒)', + 'Standard (color)' => 'スタンダード(カラー)', + }, + }, + 'FilmType' => 'フィルムタイプ', + 'Filter' => { + Description => 'フィルター', + PrintConv => { + 'Off' => 'オフ', + }, + }, + 'FilterEffect' => { + Description => 'フィルター効果', + PrintConv => { + 'Green' => '緑', + 'None' => '無し', + 'Off' => 'オフ', + 'Orange' => 'オレンジ', + 'Red' => '赤', + 'Yellow' => '黄色', + 'n/a' => '該当無し', + }, + }, + 'FilterEffectMonochrome' => { + Description => 'モノクロフィルター効果', + PrintConv => { + 'Green' => '緑', + 'None' => '無し', + 'Orange' => 'オレンジ', + 'Red' => '赤', + 'Yellow' => '黄色', + }, + }, + 'FinderDisplayDuringExposure' => { + Description => '露光中のファインダー内表示', + PrintConv => { + 'Off' => 'オフ', + 'On' => 'オン', + }, + }, + 'FineTuneOptCenterWeighted' => '最適露出微調整 中央重点測光', + 'FineTuneOptMatrixMetering' => '最適露出微調整 分割測光', + 'FineTuneOptSpotMetering' => '最適露出微調整 スポット測光', + 'Firmware' => 'ファームウェア', + 'FirmwareDate' => 'ファームウェア日付', + 'FirmwareRevision' => 'ファームウェアリビジョン', + 'FirmwareVersion' => 'ファームウェアバージョン', + 'FixtureIdentifier' => 'フィクチャー識別子', + 'Flash' => { + Description => 'ストロボ', + PrintConv => { + 'Auto, Did not fire' => 'フラッシュ未発光、オートモード', + 'Auto, Did not fire, Red-eye reduction' => 'オート、フラッシュ未発光、赤目軽減モード', + 'Auto, Fired' => 'フラッシュ発光、オートモード', + 'Auto, Fired, Red-eye reduction' => 'フラッシュ発光、オートモード、赤目軽減モード', + 'Auto, Fired, Red-eye reduction, Return detected' => 'フラッシュ発光、オートモード、ストロボ光検知、赤目軽減モード', + 'Auto, Fired, Red-eye reduction, Return not detected' => 'フラッシュ発光、オートモード、ストロボ光未検知、赤目軽減モード', + 'Auto, Fired, Return detected' => 'フラッシュ発光、オートモード、ストロボ光検知', + 'Auto, Fired, Return not detected' => 'フラッシュ発光、オートモード、ストロボ光未検知', + 'Did not fire' => 'フラッシュ未発光', + 'Fired' => 'フラッシュ発光', + 'Fired, Red-eye reduction' => 'フラッシュ発光、赤目軽減モード', + 'Fired, Red-eye reduction, Return detected' => 'フラッシュ発光、赤目軽減モード、ストロボ光検知', + 'Fired, Red-eye reduction, Return not detected' => 'フラッシュ発光、赤目軽減モード、ストロボ光未検知', + 'Fired, Return detected' => 'ストロボ光検知', + 'Fired, Return not detected' => 'ストロボ光未検知', + 'No Flash' => 'フラッシュ未発光', + 'No flash function' => 'フラッシュ機能無し', + 'Off' => 'オフ', + 'Off, Did not fire' => 'フラッシュ未発光、強制発光モード', + 'Off, Did not fire, Return not detected' => 'オフ、フラッシュ未発光、ストロボ光未検知', + 'Off, No flash function' => 'オフ、フラッシュ機能無し', + 'Off, Red-eye reduction' => 'オフ、赤目軽減モード', + 'On' => 'オン', + 'On, Did not fire' => 'オン、フラッシュ未発光', + 'On, Fired' => 'フラッシュ発光、強制発光モード', + 'On, Red-eye reduction' => 'フラッシュ発光、強制発光モード、赤目軽減モード', + 'On, Red-eye reduction, Return detected' => 'フラッシュ発光、強制発光モード、赤目軽減モード、ストロボ光検知', + 'On, Red-eye reduction, Return not detected' => 'フラッシュ発光、強制発光モード、赤目軽減モード、ストロボ光未検知', + 'On, Return detected' => 'フラッシュ発光、強制発光モード、ストロボ光検知', + 'On, Return not detected' => 'フラッシュ発光、強制発光モード、ストロボ光未検知', + }, + }, + 'FlashActivity' => 'フラッシュ稼働', + 'FlashBias' => 'フラッシュバイアス', + 'FlashBits' => 'フラッシュ詳細', + 'FlashChargeLevel' => 'フラッシュチャージレベル', + 'FlashCommanderMode' => { + Description => 'コマンダーモード', + PrintConv => { + 'Off' => 'オフ', + 'On' => 'オン', + }, + }, + 'FlashCompensation' => 'フラッシュ補正', + 'FlashControlMode' => { + Description => 'フラッシュコントロールモード', + PrintConv => { + 'Auto Aperture' => '自動絞り(AA)', + 'Manual' => 'マニュアル', + 'Off' => 'オフ', + 'Repeating Flash' => 'リピーティングフラッシュ', + }, + }, + 'FlashDevice' => { + Description => 'フラッシュデバイス', + PrintConv => { + 'External' => '外付け', + 'Internal' => '内蔵', + 'Internal + External' => '内蔵+外付け', + 'None' => '無し', + }, + }, + 'FlashDistance' => 'フラッシュ強度', + 'FlashEnergy' => 'フラッシュ強度', + 'FlashExposureBracketValue' => 'フラッシュ露出ブラケット値', + 'FlashExposureComp' => 'フラッシュ露出補正', + 'FlashExposureCompSet' => 'ストロボ露出補正設定', + 'FlashExposureLock' => { + PrintConv => { + 'Off' => 'オフ', + 'On' => 'オン', + }, + }, + 'FlashFired' => { + Description => 'フラッシュ発光', + PrintConv => { + 'No' => 'いいえ', + 'Yes' => 'はい', + }, + }, + 'FlashFiring' => { + Description => 'ストロボの発光', + PrintConv => { + 'Does not fire' => 'しない', + 'Fires' => 'する', + }, + }, + 'FlashFirmwareVersion' => 'フラッシュファームウェアバージョン', + 'FlashFocalLength' => 'フラッシュ焦点距離', + 'FlashGroupACompensation' => 'グループAフラッシュ補正', + 'FlashGroupAControlMode' => { + Description => 'グループAフラッシュコントロールモード', + PrintConv => { + 'Auto Aperture' => '自動絞り(AA)', + 'Manual' => 'マニュアル', + 'Off' => 'オフ', + 'Repeating Flash' => 'リピーティングフラッシュ', + }, + }, + 'FlashGroupAOutput' => 'グループAフラッシュ出力', + 'FlashGroupBCompensation' => 'グループBフラッシュ補正', + 'FlashGroupBControlMode' => { + Description => 'グループBフラッシュコントロールモード', + PrintConv => { + 'Auto Aperture' => '自動絞り(AA)', + 'Manual' => 'マニュアル', + 'Off' => 'オフ', + 'Repeating Flash' => 'リピーティングフラッシュ', + }, + }, + 'FlashGroupBOutput' => 'グループBフラッシュ出力', + 'FlashGroupCCompensation' => 'グループCフラッシュ補正', + 'FlashGroupCControlMode' => { + Description => 'グループCフラッシュコントロールモード', + PrintConv => { + 'Auto Aperture' => '自動絞り(AA)', + 'Manual' => 'マニュアル', + 'Off' => 'オフ', + 'Repeating Flash' => 'リピーティングフラッシュ', + }, + }, + 'FlashGroupCOutput' => 'グループCフラッシュ出力', + 'FlashGuideNumber' => 'フラッシュガイドナンバー', + 'FlashInfo' => 'ストロボ情報', + 'FlashInfoVersion' => 'フラッシュ情報バージョン', + 'FlashIntensity' => { + Description => 'フラッシュ強度', + PrintConv => { + 'High' => '高い', + 'Low' => '低い', + 'Normal' => '標準', + 'Strong' => '強い', + 'Weak' => '弱い', + }, + }, + 'FlashLevel' => 'フラッシュ補正', + 'FlashMetering' => 'フラッシュ計測', + 'FlashMeteringSegments' => 'フラッシュ測光値', + 'FlashMode' => { + Description => 'フラッシュモード', + PrintConv => { + 'Auto' => 'オート', + 'Auto, Did not fire' => 'オート、発光無し', + 'Auto, Did not fire, Red-eye reduction' => 'オート、発光無し、赤目軽減', + 'Auto, Fired' => 'オート、発光', + 'Auto, Fired, Red-eye reduction' => 'オート、発光、赤目軽減', + 'Did Not Fire' => '発光禁止', + 'External, Auto' => '外付、オート', + 'External, Contrast-control Sync' => '外付、光量比制御シンクロ', + 'External, Flash Problem' => '外付、フラッシュの問題?', + 'External, High-speed Sync' => '外付、ハイスピードシンクロ', + 'External, Manual' => '外付、マニュアル', + 'External, P-TTL Auto' => '外付、P-TTL自動調光', + 'External, Wireless' => '外付、ワイヤレス', + 'External, Wireless, High-speed Sync' => '外付、ワイヤレス、ハイスピードシンクロ', + 'Fill flash' => '強制発光', + 'Fired, Commander Mode' => '発光、コマンダーモード', + 'Fired, External' => '発光、外付', + 'Fired, Manual' => '発光、マニュアル', + 'Fired, TTL Mode' => '発光、TTLモード', + 'Internal' => '内蔵', + 'Normal' => '標準', + 'Off' => 'オフ', + 'Off, Did not fire' => 'オフ', + 'Off?' => 'オフ?', + 'On' => 'オン', + 'On, Did not fire' => 'オン、発光無し', + 'On, Fired' => 'オン', + 'On, Red-eye reduction' => 'オン、赤目軽減', + 'On, Slow-sync' => 'オン、スローシンクロ', + 'On, Slow-sync, Red-eye reduction' => 'オン、スローシンクロ、赤目軽減', + 'On, Soft' => 'オン、ソフト', + 'On, Trailing-curtain Sync' => 'オン、後幕シンクロ', + 'On, Wireless (Control)' => 'オン、ワイヤレス (コントロール)', + 'On, Wireless (Master)' => 'オン、ワイヤレス (マスター)', + 'Rear flash sync' => 'リアフラッシュシンクロ', + 'Red-eye Reduction' => '赤目軽減', + 'Red-eye reduction' => '赤目軽減', + 'Unknown' => '不明', + 'Wireless' => 'ワイヤレス', + 'n/a - Off-Auto-Aperture' => '該当なし-自動絞りオフ', + }, + }, + 'FlashModel' => { + Description => 'フラッシュモデル', + PrintConv => { + 'None' => '無し', + }, + }, + 'FlashOptions' => { + Description => 'フラッシュオプション', + PrintConv => { + 'Auto' => 'オート', + 'Auto, Red-eye reduction' => 'オート、赤目軽減', + 'Normal' => '標準', + 'Red-eye reduction' => '赤目軽減', + 'Slow-sync' => 'スローシンクロ', + 'Slow-sync, Red-eye reduction' => 'スローシンクロ、赤目軽減', + 'Trailing-curtain Sync' => '後幕シンクロ', + 'Wireless (Control)' => 'ワイヤレス(コントロール発光)', + 'Wireless (Master)' => 'ワイヤレス(マスター発光)', + }, + }, + 'FlashOptions2' => { + Description => 'ストロボオプション(2)', + PrintConv => { + 'Auto' => 'オート', + 'Auto, Red-eye reduction' => 'オート、赤目軽減', + 'Normal' => '標準', + 'Red-eye reduction' => '赤目軽減', + 'Slow-sync' => 'スローシンクロ', + 'Slow-sync, Red-eye reduction' => 'スローシンクロ、赤目軽減', + 'Trailing-curtain Sync' => '後幕シンクロ', + 'Wireless (Control)' => 'ワイヤレス(コントロール発光)', + 'Wireless (Master)' => 'ワイヤレス(マスター発光)', + }, + }, + 'FlashOutput' => 'フラッシュ出力', + 'FlashRemoteControl' => 'フラッシュリモートコントロール', + 'FlashSerialNumber' => 'フラッシュシリアル番号', + 'FlashSetting' => 'フラッシュ設定', + 'FlashShutterSpeed' => 'フラッシュシャッター速度', + 'FlashStatus' => { + Description => 'ストロボ状態', + PrintConv => { + 'External, Did not fire' => '外付、未発光', + 'External, Fired' => '外付、発光', + 'Internal, Did not fire' => '内蔵、未発光', + 'Internal, Fired' => '内蔵、発光', + 'Off' => 'オフ', + }, + }, + 'FlashSyncSpeed' => 'フラッシュ同調速度', + 'FlashSyncSpeedAv' => { + Description => 'Avモード時のストロボ同調速度', + PrintConv => { + '1/200 Fixed' => '1/200秒固定', + '1/250 Fixed' => '1/250秒固定', + '1/300 Fixed' => '1/300秒固定', + 'Auto' => 'オート', + }, + }, + 'FlashType' => { + Description => 'フラッシュタイプ', + PrintConv => { + 'E-System' => 'E-システム', + 'None' => '無し', + 'Simple E-System' => 'シンプルE-システム', + }, + }, + 'FlashWarning' => { + Description => 'フラッシュ警告', + PrintConv => { + 'Off' => 'オフ', + 'On' => 'オン', + }, + }, + 'FlashpixVersion' => 'サポートフラッシュピックスバージョン', + 'FlickerReduce' => { + Description => 'フリッカー軽減', + PrintConv => { + 'Off' => 'オフ', + 'On' => 'オン', + }, + }, + 'FlipHorizontal' => { + Description => '横フリップ', + PrintConv => { + 'No' => 'いいえ', + 'Yes' => 'はい', + }, + }, + 'FocalLength' => 'レンズ焦点距離', + 'FocalLength35efl' => 'レンズ焦点距離', + 'FocalLengthIn35mmFormat' => '35mmフイルム換算焦点距離', + 'FocalPlaneDiagonal' => '焦点面対角線', + 'FocalPlaneResolutionUnit' => { + Description => '焦点面解像度単位', + PrintConv => { + 'None' => '無し', + 'inches' => 'インチ', + }, + }, + 'FocalPlaneXResolution' => '焦点面X解像度', + 'FocalPlaneXSize' => '焦点面Xサイズ', + 'FocalPlaneXUnknown' => '焦点面Xサイズ', + 'FocalPlaneYResolution' => '焦点面Y解像度', + 'FocalPlaneYSize' => '焦点面Yサイズ', + 'FocalPlaneYUnknown' => '焦点面Yサイズ', + 'FocalType' => { + Description => 'フォーカスタイプ', + PrintConv => { + 'Fixed' => '固定', + 'Zoom' => 'ズーム', + }, + }, + 'FocalUnits' => '焦点単位/mm', + 'Focus' => { + Description => 'フォーカス', + PrintConv => { + 'Manual' => 'マニュアル', + }, + }, + 'FocusArea' => 'フォーカスエリア', + 'FocusAreaSelection' => { + Description => 'フォーカスポイントラップアラウンド', + PrintConv => { + 'No Wrap' => 'ノーラップ', + 'Wrap' => 'ラップ', + }, + }, + 'FocusContinuous' => { + Description => '連続フォーカス', + PrintConv => { + 'Continuous' => '連続', + 'Manual' => 'マニュアル', + 'Single' => 'シングル', + }, + }, + 'FocusDistance' => '被写体距離', + 'FocusDistanceLower' => '焦点距離低部分', + 'FocusDistanceUpper' => '焦点距離高部分', + 'FocusMode' => { + Description => 'フォーカスモード', + PrintConv => { + 'AI Focus AF' => 'AIフォーカスAF', + 'AI Servo AF' => 'AIサーボAF', + 'Auto' => 'オート', + 'Auto, Continuous' => 'オート、コンティニュアス', + 'Auto, Focus button' => 'オート、フォーカスボタン', + 'Continuous' => '連写', + 'Continuous AF' => 'コンティニュアスAF', + 'Custom' => 'カスタム', + 'Infinity' => '無限遠', + 'Macro' => 'マクロ', + 'Macro (1)' => 'マクロ(1)', + 'Macro (2)' => 'マクロ(2)', + 'Manual' => 'マニュアル', + 'Manual Focus (3)' => 'マニュアルフォーカス(3)', + 'Manual Focus (6)' => 'マニュアルフォーカス(6)', + 'Multi AF' => 'マルチAF', + 'Normal' => '標準', + 'One-shot AF' => 'ワンショットAF', + 'Pan Focus' => 'パンフォーカス', + 'Sequential shooting AF' => 'シーケンシャルシューティングAF', + 'Single' => 'シングル', + 'Single AF' => 'シングルAF', + 'Super Macro' => 'スーパーマクロ', + }, + }, + 'FocusMode2' => 'フォーカスモード2', + 'FocusModeSetting' => { + Description => 'フォーカスモード', + PrintConv => { + 'Manual' => 'マニュアル', + }, + }, + 'FocusPixel' => '焦点解像度', + 'FocusPointWrap' => { + Description => 'フォーカスポイントラップアラウンド', + PrintConv => { + 'No Wrap' => 'ノーラップ', + 'Wrap' => 'ラップ', + }, + }, + 'FocusPosition' => 'フォーカス距離', + 'FocusProcess' => { + Description => 'フォーカスプロセス', + PrintConv => { + 'AF Not Used' => 'AF未使用', + 'AF Used' => 'AF使用', + }, + }, + 'FocusRange' => { + Description => 'フォーカスレンジ', + PrintConv => { + 'Auto' => 'オート', + 'Close' => '近景', + 'Far Range' => '遠景', + 'Infinity' => '無限遠', + 'Macro' => 'マクロ', + 'Manual' => 'マニュアル', + 'Middle Range' => '中間範囲', + 'Normal' => 'ノーマル', + 'Not Known' => '不明', + 'Pan Focus' => 'パンフォーカス', + 'Super Macro' => 'スーパーマクロ', + 'Very Close' => '近接', + }, + }, + 'FocusSetting' => 'フォーカス設定', + 'FocusStepCount' => 'フォーカスステップ数', + 'FocusStepInfinity' => '無限レンズステップ', + 'FocusStepNear' => 'ニアステップ数', + 'FocusTrackingLockOn' => { + Description => 'フォーカストラッキングとロックオン', + PrintConv => { + 'Long' => 'ロング', + 'Normal' => '標準', + 'Off' => 'オフ', + 'Short' => 'ショート', + }, + }, + 'FocusWarning' => { + Description => 'フォーカス警告', + PrintConv => { + 'Good' => 'ジャスピン', + 'Out of focus' => 'ピンボケ', + }, + }, + 'FocusingScreen' => 'フォーカシングスクリーン', + 'FolderName' => 'フォルダ名', + 'ForwardMatrix1' => '前行列1', + 'ForwardMatrix2' => '前行列2', + 'FrameHeight' => 'フレーム高', + 'FrameNumber' => 'フレーム番号', + 'FrameRate' => 'フレームレート', + 'FrameSize' => 'フレームサイズ', + 'FrameWidth' => 'フレーム幅', + 'FreeByteCounts' => 'フリーバイト数', + 'FreeMemoryCardImages' => 'フリーメモリーカードイメージ', + 'FreeOffsets' => 'フリーオフセット', + 'FujiFlashMode' => { + Description => 'フラッシュモード', + PrintConv => { + 'Auto' => 'オート', + 'External' => '外付フラッシュ', + 'Off' => 'オフ', + 'On' => 'オン', + 'Red-eye reduction' => '赤目軽減', + }, + }, + 'FunctionButton' => { + Description => 'FUNCボタン', + PrintConv => { + 'AF-area Mode' => 'AFエリアモード', + 'Center AF Area' => '中央AFエリア', + 'Center-weighted' => '中央重点測光', + 'FV Lock' => 'FVロック', + 'Flash Off' => 'フラッシュオフ', + 'Framing Grid' => 'フレーミンググリッド', + 'ISO Display' => 'ISO表示', + 'Matrix Metering' => '分割測光', + 'Spot Metering' => 'スポット測光', + }, + }, + 'GEMInfo' => 'GEM情報', + 'GEModel' => 'モデル', + 'GIFVersion' => 'GIFバージョン', + 'GPSAltitude' => '高度', + 'GPSAltitudeRef' => { + Description => '参照高度', + PrintConv => { + 'Above Sea Level' => '海水面', + 'Below Sea Level' => '参照海水面(負の値)', + }, + }, + 'GPSAreaInformation' => 'GPSエリアの名称', + 'GPSDOP' => '測定精度', + 'GPSDateStamp' => 'GPSデータ', + 'GPSDateTime' => 'GPS時間(原子時計)', + 'GPSDestBearing' => '目的地の方向', + 'GPSDestBearingRef' => { + Description => '目的地の方向の参照', + PrintConv => { + 'Magnetic North' => '磁気の方向', + 'True North' => '正常な方向', + }, + }, + 'GPSDestDistance' => '目的地の距離', + 'GPSDestDistanceRef' => { + Description => '目的地の距離の参照', + PrintConv => { + 'Kilometers' => 'キロメートル', + 'Miles' => 'マイル', + 'Nautical Miles' => 'ノット', + }, + }, + 'GPSDestLatitude' => '目的地の緯度', + 'GPSDestLatitudeRef' => { + Description => '目的地の緯度のための参照', + PrintConv => { + 'North' => '北緯', + 'South' => '南緯', + }, + }, + 'GPSDestLongitude' => '目的地の経度', + 'GPSDestLongitudeRef' => { + Description => '目的地の経度のための参照', + PrintConv => { + 'East' => '東経', + 'West' => '西経', + }, + }, + 'GPSDifferential' => { + Description => 'GPS誤差修正', + PrintConv => { + 'Differential Corrected' => '誤差修正あり', + 'No Correction' => '誤差修正無し', + }, + }, + 'GPSImgDirection' => 'イメージの方向', + 'GPSImgDirectionRef' => { + Description => '画像方向参照', + PrintConv => { + 'Magnetic North' => '磁気の方向', + 'True North' => '本当の方向', + }, + }, + 'GPSInfo' => 'GPS IFDへのポインタ', + 'GPSLatitude' => '緯度', + 'GPSLatitudeRef' => { + Description => '北緯または南緯', + PrintConv => { + 'North' => '北緯', + 'South' => '南緯', + }, + }, + 'GPSLongitude' => '経度', + 'GPSLongitudeRef' => { + Description => '東経または西経', + PrintConv => { + 'East' => '東経', + 'West' => '西経', + }, + }, + 'GPSMapDatum' => 'データが使った測地測量', + 'GPSMeasureMode' => { + Description => 'GPS測定モード', + PrintConv => { + '2-D' => '2次元測定', + '2-Dimensional' => '2次元測定', + '2-Dimensional Measurement' => '2次元測定', + '3-D' => '3次元測定', + '3-Dimensional' => '3次元測定', + '3-Dimensional Measurement' => '3次元測定', + }, + }, + 'GPSProcessingMethod' => 'GPS処理方法の名称', + 'GPSSatellites' => '測定のために使われたGPS衛星', + 'GPSSpeed' => 'GPS受信機のスピード', + 'GPSSpeedRef' => { + Description => 'スピード単位', + PrintConv => { + 'km/h' => '時速(km)', + 'knots' => 'ノット', + 'mph' => '時速(マイル)', + }, + }, + 'GPSStatus' => { + Description => 'GPS受信機ステータス', + PrintConv => { + 'Measurement Active' => '測定アクティブ', + 'Measurement Void' => '測定無効', + }, + }, + 'GPSTimeStamp' => 'GPS時間(原子時計)', + 'GPSTrack' => '動作方向', + 'GPSTrackRef' => { + Description => '動作方向の参照', + PrintConv => { + 'Magnetic North' => '磁気の方向', + 'True North' => '本当の方向', + }, + }, + 'GPSVersionID' => 'GPSタグバージョン', + 'GainBase' => '基本ゲイン', + 'GainControl' => { + Description => 'ゲインコントロール', + PrintConv => { + 'High gain down' => '高いゲインダウン', + 'High gain up' => '高いゲインアップ', + 'Low gain down' => '低いゲインダウン', + 'Low gain up' => '低いゲインアップ', + 'None' => '無し', + }, + }, + 'Gamma' => 'ガンマ', + 'GammaCompensatedValue' => 'ガンマ補償値', + 'Gamut' => '全域', + 'Gapless' => { + PrintConv => { + 'No' => 'いいえ', + 'Yes' => 'はい', + }, + }, + 'GeoTiffAsciiParams' => 'ジオアスキー設定タグ', + 'GeoTiffDirectory' => 'ジオキーディレクトリタグ', + 'GeoTiffDoubleParams' => 'ジオダブル設定タグ', + 'Gradation' => 'グラデーション', + 'GrayPoint' => 'グレーポイント', + 'GrayResponseCurve' => 'グレー反応曲線', + 'GrayResponseUnit' => { + Description => 'グレー反応単位', + PrintConv => { + '0.0001' => '単位の数は1000を表す', + '0.001' => '単位の数は100を表す', + '0.1' => '単位の数は10を表す', + '1e-05' => '単位の数は10-1000を表す', + '1e-06' => '単位の数は100-1000を表す', + }, + }, + 'GrayScale' => 'グレースケール', + 'GrayTRC' => '灰色調増殖曲線', + 'GreenMatrixColumn' => '緑色マトリックス列', + 'GreenTRC' => '緑色調増殖曲線', + 'GridDisplay' => { + Description => 'ビューファインダーグリッド表示', + PrintConv => { + 'Off' => 'オフ', + 'On' => 'オン', + }, + }, + 'GripBatteryADLoad' => '電源A/Dグリップ起動時', + 'GripBatteryADNoLoad' => '電源A/Dグリップオフ時', + 'GripBatteryState' => '電源状態グリップ', + 'HCUsage' => 'HC使用', + 'HDR' => { + Description => 'オートHDR', + PrintConv => { + 'Off' => '切', + }, + }, + 'HalftoneHints' => 'ハーフトーンヒント', + 'Headline' => 'ヘッドライン', + 'HeightResolution' => '高さ方向の画像解像度', + 'HighISONoiseReduction' => { + Description => '高感度ノイズリダクション', + PrintConv => { + '+2 (strong)' => '+2 (強)', + '-2 (weak)' => '-2 (弱)', + '-4 (weakest)' => '-4 (微弱)', + 'Auto' => 'オート', + 'High' => '高い', + 'Low' => 'ソフト', + 'Minimal' => '最小', + 'Normal' => '標準', + 'Off' => 'オフ', + 'On' => 'オン', + 'Standard' => 'スタンダード', + 'Strong' => '強', + 'Weak' => '弱', + 'Weakest' => '微弱', + }, + }, + 'Highlight' => 'ハイライト', + 'HighlightTonePriority' => { + Description => '高輝度側・階調優先', + PrintConv => { + 'Disable' => 'しない', + 'Enable' => 'する', + 'Off' => 'オフ', + 'On' => 'オン', + }, + }, + 'HometownCity' => '現在地', + 'HometownCityCode' => '現在地コード', + 'HometownDST' => { + Description => '現在地DST', + PrintConv => { + 'No' => 'いいえ', + 'Yes' => 'はい', + }, + }, + 'HostComputer' => 'ホストコンピューター', + 'Hue' => '色相', + 'HueAdjustment' => '色相調整', + 'HueSetting' => '色相設定', + 'ICCProfile' => 'ICCプロフィール', + 'ICC_Profile' => 'ICC入力色プロフィール', + 'IPTC-NAA' => 'IPTC-NAAメタデータ', + 'IPTCBitsPerSample' => 'サンプルあたりビット数', + 'IPTCData' => 'IPTCデータ', + 'IPTCImageHeight' => 'ライン数', + 'IPTCImageRotation' => 'イメージ回転', + 'IPTCImageWidth' => 'ラインあたりのピクセル数', + 'IPTCPictureNumber' => '写真番号', + 'IPTCPixelHeight' => 'スキャン方向垂直ピクセルサイズ', + 'IPTCPixelWidth' => 'スキャン方向ピクセルサイズ', + 'ISO' => 'ISOスピードレート', + 'ISO2' => 'ISO(2)', + 'ISOAuto' => 'ISOオート', + 'ISODisplay' => 'ISO表示', + 'ISOExpansion' => { + Description => 'ISO感度拡張', + PrintConv => { + 'Off' => 'オフ', + 'On' => 'オン', + }, + }, + 'ISOExpansion2' => { + Description => 'ISO拡大(2)', + PrintConv => { + 'Off' => 'オフ', + }, + }, + 'ISOFloor' => '最低感度', + 'ISOInfo' => 'ISO情報', + 'ISOSelection' => 'ISO選択', + 'ISOSetting' => { + Description => 'ISO設定', + PrintConv => { + 'Auto' => 'オート', + 'Manual' => 'マニュアル', + }, + }, + 'ISOSpeedExpansion' => { + Description => 'ISO感度拡張', + PrintConv => { + 'No' => 'いいえ', + 'Yes' => 'はい', + }, + }, + 'ISOSpeedIncrements' => { + Description => 'ISO感度ステップ値', + PrintConv => { + '1 Stop' => '1ステップ', + '1/3 Stop' => '1/3ステップ', + }, + }, + 'ISOSpeedRange' => { + Description => 'ISO感度の制御範囲の設定', + PrintConv => { + 'Disable' => 'しない', + 'Enable' => 'する', + }, + }, + 'ISOStepSize' => { + Description => 'ISO感度ステップ値', + PrintConv => { + '1 EV' => '1ステップ', + '1/2 EV' => '1/2ステップ', + '1/3 EV' => '1/3ステップ', + }, + }, + 'ISOValue' => 'ISO感度', + 'IT8Header' => 'IT8ヘッダー', + 'Illumination' => { + Description => 'イルミネーション', + PrintConv => { + 'Off' => 'オフ', + 'On' => 'オン', + }, + }, + 'Image::ExifTool::NikonCapture::RedEyeData' => 'Nikon Capture 赤目データ', + 'ImageAdjustment' => 'イメージ調整', + 'ImageAreaOffset' => 'イメージ領域オフセット', + 'ImageAuthentication' => { + Description => 'イメージ認証', + PrintConv => { + 'Off' => 'オフ', + 'On' => 'オン', + }, + }, + 'ImageBoundary' => 'イメージ境界線', + 'ImageByteCount' => '画像バイト数', + 'ImageColorIndicator' => '画像色指標', + 'ImageColorValue' => '画像色値', + 'ImageCount' => 'イメージカウント', + 'ImageDataDiscard' => { + Description => 'イメージデータ廃棄', + PrintConv => { + 'Flexbits Discarded' => 'フレックスビット破棄', + 'Full Resolution' => '完全な解像度', + 'HighPass Frequency Data Discarded' => 'ハイパス周波数データ破棄', + 'Highpass and LowPass Frequency Data Discarded' => 'ハイパスとローパス周波数データ破棄', + }, + }, + 'ImageDataSize' => 'イメージデータサイズ', + 'ImageDepth' => 'イメージの深さ', + 'ImageDescription' => 'イメージ説明', + 'ImageDustOff' => { + PrintConv => { + 'Off' => 'オフ', + 'On' => 'オン', + }, + }, + 'ImageEditCount' => '画像処理カウント', + 'ImageEditing' => { + Description => 'イメージ処理', + PrintConv => { + 'Cropped' => 'クロップ', + 'Digital Filter' => 'デジタルフィルター', + 'Frame Synthesis?' => 'フレーム合成?', + 'None' => '未処理', + }, + }, + 'ImageHeight' => '画像高さ', + 'ImageHistory' => '画像履歴', + 'ImageID' => 'イメージID', + 'ImageInfo' => '画像情報', + 'ImageLayer' => 'イメージレイヤー', + 'ImageNumber' => 'イメージ番号', + 'ImageNumber2' => 'イメージ番号(2)', + 'ImageOffset' => 'イメージオフセット', + 'ImageOptimization' => 'イメージ最適化', + 'ImageOrientation' => { + Description => 'イメージ方向', + PrintConv => { + 'Landscape' => 'ランドスケープ', + 'Portrait' => 'ポートレート', + 'Square' => '正方形', + }, + }, + 'ImageProcessing' => 'イメージ処理', + 'ImageProcessingVersion' => '画像処理バージョン', + 'ImageQuality' => { + Description => '画像品質', + PrintConv => { + 'High' => '高い', + 'Motion Picture' => '動画', + 'Normal' => '標準', + }, + }, + 'ImageQuality2' => 'イメージ品質2', + 'ImageResourceBlocks' => 'イメージリソースブロック', + 'ImageReview' => { + Description => '画像評価', + PrintConv => { + 'Off' => 'オフ', + 'On' => 'オン', + }, + }, + 'ImageReviewTime' => '自動オフタイマー 画像評価時間', + 'ImageRotated' => { + PrintConv => { + 'No' => 'いいえ', + 'Yes' => 'はい', + }, + }, + 'ImageSize' => 'イメージサイズ', + 'ImageSourceData' => 'イメージソースデータ', + 'ImageStabilization' => { + Description => 'イメージスタビライザー', + PrintConv => { + 'Best Shot' => 'ベストショット', + 'Off' => 'オフ', + 'On' => 'オン', + 'On, Mode 1' => 'オン、モード1', + 'On, Mode 2' => 'オン、モード2', + }, + }, + 'ImageTone' => { + Description => '画像仕上', + PrintConv => { + 'Bright' => '鮮やか', + 'Landscape' => '風景', + 'Monochrome' => 'モノトーン', + 'Natural' => 'ナチュラル', + 'Portrait' => 'ポートレート', + 'Vibrant' => '雅(MIYABI)', + }, + }, + 'ImageType' => 'ページ', + 'ImageUniqueID' => 'ユニークなイメージID', + 'ImageWidth' => '画像幅', + 'Index' => '目次', + 'Indexed' => 'インデックス', + 'InfoButtonWhenShooting' => { + Description => '撮影時のINFOボタン', + PrintConv => { + 'Displays camera settings' => 'カメラ設定内容を表示', + 'Displays shooting functions' => '撮影機能の設定状態を表示', + }, + }, + 'InitialZoomSetting' => { + Description => '初期ズーム設定', + PrintConv => { + 'High Magnification' => '高い拡大', + 'Low Magnification' => '低い拡大', + 'Medium Magnification' => '中間拡大', + }, + }, + 'InkNames' => 'インク名', + 'InkSet' => 'インクセット', + 'Instructions' => '詳細', + 'IntellectualGenre' => 'インテリジャンル', + 'IntelligentAuto' => 'インテリジェントオート', + 'IntensityStereo' => { + PrintConv => { + 'Off' => 'オフ', + 'On' => 'オン', + }, + }, + 'IntergraphMatrix' => '相互グラフマトリックスタグ', + 'Interlace' => 'インタレース', + 'InternalFlash' => { + Description => '内蔵フラッシュコントロール', + PrintConv => { + 'Commander Mode' => 'コマンダーモード', + 'Fired' => 'フラッシュ発光', + 'Manual' => 'マニュアル', + 'No' => 'フラッシュ未発光', + 'Off' => 'オフ', + 'On' => 'オン', + 'Repeating Flash' => 'リピーティングフラッシュ', + }, + }, + 'InternalFlashAE1' => '内蔵フラッシュAE1?', + 'InternalFlashAE1_0' => '内蔵フラッシュAE1(0)?', + 'InternalFlashAE2' => '内蔵フラッシュAE2?', + 'InternalFlashAE2_0' => '内蔵フラッシュAE2(0)?', + 'InternalFlashMode' => { + Description => '内蔵ストロボモード', + PrintConv => { + 'Did not fire, (Unknown 0xf4)' => 'オフ(未確認 0xF4?)', + 'Did not fire, Auto' => 'オフ、オート', + 'Did not fire, Auto, Red-eye reduction' => 'オフ、オート、赤目軽減', + 'Did not fire, Normal' => 'オフ、標準', + 'Did not fire, Red-eye reduction' => 'オフ、赤目軽減', + 'Did not fire, Slow-sync' => 'オフ、スローシンクロ', + 'Did not fire, Slow-sync, Red-eye reduction' => 'オフ、スローシンクロ、赤目軽減', + 'Did not fire, Trailing-curtain Sync' => 'オフ、後幕シンクロ', + 'Did not fire, Wireless (Control)' => 'オフ、ワイヤレス(コントロール発光)', + 'Did not fire, Wireless (Master)' => 'オフ、ワイヤレス(マスター発光)', + 'Fired' => 'オン', + 'Fired, Auto' => 'オン、オート', + 'Fired, Auto, Red-eye reduction' => 'オン、オート、赤目軽減', + 'Fired, Red-eye reduction' => 'オン、赤目軽減', + 'Fired, Slow-sync' => 'オン、スローシンクロ', + 'Fired, Slow-sync, Red-eye reduction' => 'オン、スローシンクロ、赤目軽減', + 'Fired, Trailing-curtain Sync' => 'オン、後幕シンクロ', + 'Fired, Wireless (Control)' => 'オン、ワイヤレス(コントロール発光)', + 'Fired, Wireless (Master)' => 'オン、ワイヤレス(マスター発光)', + 'n/a - Off-Auto-Aperture' => '該当なし-自動絞りオフ', + }, + }, + 'InternalFlashStrength' => '内蔵フラッシュ強度', + 'InternalFlashTable' => '内蔵フラッシュテーブル', + 'InternalSerialNumber' => '内部シリアル番号', + 'InteropIndex' => { + Description => 'インターオペラビリティID', + PrintConv => { + 'R03 - DCF option file (Adobe RGB)' => 'R03: DCFオプションファイル(Adobe RGB)', + 'R98 - DCF basic file (sRGB)' => 'R98: DCF基本ファイル(sRGB)', + 'THM - DCF thumbnail file' => 'THM: DCFサムネイルファイル', + }, + }, + 'InteropOffset' => '互換性IFDへのポインタ', + 'InteropVersion' => 'インターオペラビリティバージョン', + 'IntervalLength' => 'インターバル長', + 'IntervalMode' => 'インターバルモード', + 'IntervalNumber' => 'インターバル数', + 'JFIFVersion' => 'JFIFバージョン', + 'JPEGACTables' => 'JPEG AC テーブル', + 'JPEGDCTables' => 'JPEG DC テーブル', + 'JPEGLosslessPredictors' => 'JPEGロスレス予測', + 'JPEGPointTransforms' => 'JPEG位置変換', + 'JPEGProc' => 'JPEG処理', + 'JPEGQTables' => 'JPEG Q テーブル', + 'JPEGQuality' => { + Description => 'JPEG 品質', + PrintConv => { + 'Extra Fine' => 'エクストラファイン', + 'Fine' => 'ファイン', + 'Standard' => 'ノーマル', + 'n/a' => '未設定', + }, + }, + 'JPEGRestartInterval' => 'JPEG再開間隔', + 'JPEGTables' => 'JPEGテーブル', + 'JobID' => 'ジョブID', + 'JpgRecordedPixels' => 'JPEG記録サイズ', + 'Keyword' => 'キーワード', + 'Keywords' => 'キーワード', + 'LC1' => 'レンズデータ', + 'LC10' => 'Mv\' nv\' データ', + 'LC11' => 'AVC 1/EXP データ', + 'LC12' => 'Mv1 Avminsifデータ', + 'LC14' => 'UNT_12 UNT_6 データ', + 'LC15' => '統合フラッシュ最適エンドデータ', + 'LC2' => '距離コードデータ', + 'LC3' => 'K値(', + 'LC4' => '近距離収差訂正データ', + 'LC5' => '明色収差訂正データ', + 'LC6' => 'オープン収差データ', + 'LC7' => 'AF最低作動状態データ(LC7)', + 'LCDDisplayAtPowerOn' => { + Description => '電源スイッチ〈ON〉時の液晶点灯', + PrintConv => { + 'Display' => '点灯', + 'Retain power off status' => '電源〈OFF〉時の状態を保持', + }, + }, + 'LCDDisplayReturnToShoot' => { + Description => '液晶モニター表示中の撮影状態復帰', + PrintConv => { + 'Also with * etc.' => '*ボタンなどでも復帰', + 'With Shutter Button only' => 'シャッターボタンでのみ復帰', + }, + }, + 'LCDIllumination' => { + Description => 'LCDイルミネーション', + PrintConv => { + 'Off' => 'オフ', + 'On' => 'オン', + }, + }, + 'LCDIlluminationDuringBulb' => { + Description => 'バルブ撮影中の表示パネル照明', + PrintConv => { + 'Off' => 'オフ', + 'On' => 'オン', + }, + }, + 'LCDPanels' => '上面表示パネル/背面表示パネル', + 'LCHEditor' => { + Description => 'LCHエディター', + PrintConv => { + 'Off' => 'オフ', + 'On' => 'オン', + }, + }, + 'LanguageIdentifier' => '言語識別子', + 'LastFileNumber' => '最終ファイル番号', + 'LeafData' => 'リーフデータ', + 'Lens' => 'レンズ', + 'Lens35efl' => 'レンズ', + 'LensAFStopButton' => { + Description => 'レンズ・AFストップボタンの機能', + PrintConv => { + 'AE lock' => 'AEロック', + 'AE lock while metering' => 'AEロック(タイマー中)', + 'AF Stop' => 'AFストップ', + 'AF point: M->Auto/Auto->ctr' => '測距点 任意→自動/自動→中央', + 'AF start' => 'AFスタート', + 'AF stop' => 'AFストップ', + 'IS start' => '手ブレ補正機能作動', + 'One Shot <-> AI servo' => 'ワンショット/AIサーボ', + 'Switch to registered AF point' => '登録AFフレームへの切り換え', + }, + }, + 'LensApertureRange' => 'レンズ絞り範囲', + 'LensData' => 'K値(LC3)', + 'LensDistortionParams' => 'レンズ歪曲パラメータ', + 'LensDriveNoAF' => { + Description => 'AF測距不能時のレンズ動作', + PrintConv => { + 'Focus search off' => '駆動しない', + 'Focus search on' => 'サーチ駆動する', + }, + }, + 'LensFStops' => 'レンズF値', + 'LensFirmwareVersion' => 'レンズファームウェアバージョン', + 'LensID' => 'レンズID', + 'LensInfo' => 'レンズ情報', + 'LensKind' => 'レンズ種類/バージョン(LC0)', + 'LensProperties' => 'レンズ機能?', + 'LensSerialNumber' => 'レンズシリアル番号', + 'LensSpec' => 'レンズ', + 'LensTemperature' => 'レンズ温度', + 'LensType' => 'レンズタイプ', + 'LicenseType' => { + PrintConv => { + 'Unknown' => '不明', + }, + }, + 'LightCondition' => 'ライトコンディション', + 'LightReading' => 'ライトリーディング', + 'LightSource' => { + Description => '光源', + PrintConv => { + 'Cloudy' => '曇り', + 'Cool White Fluorescent' => '白色蛍光灯', + 'Custom 1-4' => 'カスタム1-4', + 'Day White Fluorescent' => '昼白色蛍光灯', + 'Daylight' => '昼光', + 'Daylight Fluorescent' => '昼光色蛍光灯', + 'Fine Weather' => '良い天気', + 'Flash' => 'ストロボ', + 'Fluorescent' => '蛍光灯', + 'ISO Studio Tungsten' => 'ISOスタジオタングステン', + 'Other' => 'その他の光源', + 'Shade' => '日陰', + 'Standard Light A' => '標準ライトA', + 'Standard Light B' => '標準ライトB', + 'Standard Light C' => '標準ライトC', + 'Tungsten (Incandescent)' => 'タングステン(白熱灯)', + 'Unknown' => '不明', + 'Warm White Fluorescent' => '暖白光色蛍光灯', + 'White Fluorescent' => '温白色蛍光灯', + }, + }, + 'LightSourceSpecial' => { + Description => '光源スペシャル', + PrintConv => { + 'Off' => 'オフ', + 'On' => 'オン', + }, + }, + 'Lightness' => '明度', + 'LinearResponseLimit' => '線型反応限界', + 'LinearizationTable' => '線形化テーブル', + 'Lit' => { + PrintConv => { + 'No' => 'いいえ', + 'Yes' => 'はい', + }, + }, + 'LiveViewExposureSimulation' => { + Description => 'ライブビュー露出シミュレーション', + PrintConv => { + 'Disable (LCD auto adjust)' => 'しない(適正表示)', + 'Enable (simulates exposure)' => 'する(撮影露出イメージ表示)', + }, + }, + 'LiveViewShooting' => { + PrintConv => { + 'Off' => 'オフ', + 'On' => 'オン', + }, + }, + 'LocalizedCameraModel' => '限定カメラモデル', + 'Location' => '撮影場所', + 'LockMicrophoneButton' => { + Description => 'プロテクト/録音ボタン タンの機能', + PrintConv => { + 'Protect (hold:record memo)' => 'プロテクト(長押しで録音)', + 'Record memo (protect:disable)' => '録音(プロテクト不可)', + }, + }, + 'LongExposureNoiseReduction' => { + Description => '長秒露光ノイズリダクション', + PrintConv => { + 'Auto' => 'オート', + 'Off' => 'オフ', + 'On' => 'オン', + 'n/a' => '未設定', + }, + }, + 'LookupTable' => 'ルックアップテーブル', + 'LoopStyle' => { + PrintConv => { + 'Normal' => '標準', + }, + }, + 'Luminance' => '輝度', + 'LuminanceNoiseReduction' => { + PrintConv => { + 'High' => '高い', + 'Low' => 'ソフト', + 'Off' => 'オフ', + }, + }, + 'MB-D10Batteries' => 'MB-D10電源タイプ', + 'MB-D10BatteryType' => 'MB-D10電源タイプ', + 'MB-D80Batteries' => 'MB-D80バッテリー', + 'MIEVersion' => 'MIEバージョン', + 'MIMEType' => 'MIMEタイプ', + 'MSStereo' => { + PrintConv => { + 'Off' => 'オフ', + 'On' => 'オン', + }, + }, + 'Macro' => { + Description => 'マクロ', + PrintConv => { + 'Macro' => 'マクロ', + 'Manual' => 'マニュアル', + 'Normal' => '標準', + 'Off' => 'オフ', + 'On' => 'オン', + 'Super Macro' => 'スーパーマクロ', + 'n/a' => '未設定', + }, + }, + 'MacroMode' => { + Description => 'マクロモード', + PrintConv => { + 'Macro' => 'マクロ', + 'Normal' => 'ノーマル', + 'Off' => 'オフ', + 'On' => 'オン', + 'Super Macro' => 'スーパーマクロ', + 'Tele-Macro' => 'テレマクロ', + }, + }, + 'MagnifiedView' => { + Description => '拡大ズーム表示', + PrintConv => { + 'Image playback only' => '再生時のみ', + 'Image review and playback' => '撮影直後と再生時', + }, + }, + 'MainDialExposureComp' => { + Description => 'Main Dial 露出補正', + PrintConv => { + 'Off' => 'オフ', + 'On' => 'オン', + }, + }, + 'Make' => 'メーカー', + 'MakeAndModel' => '作成とモデル', + 'MakerNote' => 'DNGプライベートデータ', + 'MakerNoteOffset' => 'メーカーノートオフセット', + 'MakerNoteSafety' => { + Description => 'メーカーノートセーフティ', + PrintConv => { + 'Safe' => '安全', + 'Unsafe' => '危険', + }, + }, + 'MakerNoteType' => 'メーカーノートタイプ', + 'MakerNoteVersion' => 'メーカーノートバージョン', + 'MakerNotes' => 'メーカーノート', + 'ManometerPressure' => '気圧計圧力', + 'ManometerReading' => '気圧計高度', + 'ManualFlash' => 'マニュアルフラッシュ', + 'ManualFlashOutput' => { + Description => 'マニュアルフラッシュ出力', + PrintConv => { + 'Low' => 'ソフト', + 'n/a' => '該当無し', + }, + }, + 'ManualFocusDistance' => 'マニュアルフォーカス距離', + 'ManualTv' => { + Description => 'マニュアル露出時Tv、Av値設定', + PrintConv => { + 'Tv=Control/Av=Main' => 'Tv値=サブ電子ダイヤル/Av値=メイン電子ダイヤル', + 'Tv=Main/Av=Control' => 'Tv値=メイン電子ダイヤル/Av値=サブ電子ダイヤル', + }, + }, + 'ManufactureDate' => '製造日付?', + 'MaskedAreas' => 'マスク領域', + 'MasterDocumentID' => 'マスタ文書ID', + 'MasterGain' => 'マスターゲイン', + 'Matteing' => 'マッチング', + 'MaxAperture' => '最大絞り', + 'MaxApertureAtCurrentFocal' => '現在焦点距離の最大絞り', + 'MaxApertureAtMaxFocal' => '最大焦点時最大絞り', + 'MaxApertureAtMinFocal' => '最小焦点時最大絞り', + 'MaxApertureValue' => '最大レンズ口径', + 'MaxContinuousRelease' => '最大連写レリーズ', + 'MaxFocalLength' => '最大焦点距離', + 'MaxSampleValue' => '最大サンプル値', + 'MaximumDensityRange' => '最大密度範囲', + 'MeasuredEV' => '計測EV', + 'Measurement' => '測定オブザーバー', + 'MeasurementBacking' => 'バック測定', + 'MeasurementFlare' => 'フレア測定', + 'MeasurementGeometry' => '幾何学測定', + 'MeasurementIlluminant' => '光源測定', + 'MeasurementObserver' => '測定オブザーバー', + 'MediaBlackPoint' => 'メディア黒点', + 'MediaType' => { + PrintConv => { + 'Movie' => '動画', + 'Normal' => '標準', + }, + }, + 'MediaWhitePoint' => 'メディア白点', + 'Medium' => 'ミドル', + 'MenuButtonDisplayPosition' => { + Description => 'メニューの表示位置', + PrintConv => { + 'Previous' => '直前のメニュー', + 'Previous (top if power off)' => '直前のメニュー(電源切で先頭)', + 'Top' => 'メニューの先頭', + }, + }, + 'MenuButtonReturn' => { + PrintConv => { + 'Previous' => '直前のメニュー', + 'Top' => '上', + }, + }, + 'Metering' => { + Description => '測光', + PrintConv => { + 'Center-weighted' => '中央重点', + 'Matrix' => '分割', + 'Spot' => 'スポット', + }, + }, + 'MeteringMode' => { + Description => '測光モード', + PrintConv => { + 'Average' => '平均', + 'Center-weighted average' => '中央重点', + 'Default' => 'デフォルト', + 'Evaluative' => '評価', + 'Multi-segment' => 'パターン', + 'Multi-spot' => 'マルチスポット', + 'Other' => 'その他', + 'Partial' => '部分', + 'Pattern+AF' => 'パターン+AF', + 'Spot' => 'スポット', + 'Spot+Highlight control' => 'スポット+ハイライトコントロール', + 'Spot+Shadow control' => 'スポット+シャドウコントロール', + 'Unknown' => '不明', + }, + }, + 'MeteringMode2' => { + Description => '測光モード2', + PrintConv => { + 'Multi-segment' => 'パターン', + }, + }, + 'MeteringMode3' => { + Description => '測光モード3', + PrintConv => { + 'Multi-segment' => 'パターン', + }, + }, + 'MeteringTime' => '自動オフタイマー メータオフ時間', + 'MinAperture' => '最小絞り', + 'MinFocalLength' => '最小焦点距離', + 'MinSampleValue' => '最小サンプル値', + 'MinoltaCameraSettings2' => 'カメラ設定2', + 'MinoltaCameraSettings5D' => 'カメラ設定(5D)', + 'MinoltaCameraSettings7D' => 'カメラ設定(7D)', + 'MinoltaDate' => '日付', + 'MinoltaImageSize' => { + Description => 'イメージサイズ', + PrintConv => { + 'Full' => 'フル', + 'Large' => 'ラージ', + 'Medium' => 'ミドル', + 'Small' => 'スモール', + }, + }, + 'MinoltaMakerNote' => 'ミノルタメーカーノート', + 'MinoltaModelID' => 'モデルID', + 'MinoltaQuality' => { + Description => 'イメージ品質', + PrintConv => { + 'Economy' => 'エコノミー', + 'Extra Fine' => 'エクストラファイン', + 'Extra fine' => 'エクストラファイン', + 'Fine' => 'ファイン', + 'Normal' => '標準', + 'Standard' => 'スタンダード', + 'Super Fine' => 'スーパーファイン', + }, + }, + 'MinoltaTime' => '時間', + 'MirrorLockup' => { + Description => 'ミラーアップ撮影', + PrintConv => { + 'Disable' => 'しない', + 'Enable' => 'する', + 'Enable: Down with Set' => 'する(SETボタンでダウン)', + }, + }, + 'Model' => '画像入力機器モデル', + 'Model2' => '画像入力機器モデル(2)', + 'ModelTiePoint' => 'モデル拘束ポイントタグ', + 'ModelTransform' => 'モデル変化タグ', + 'ModelingFlash' => { + Description => 'モデリングフラッシュ', + PrintConv => { + 'Off' => 'オフ', + 'On' => 'オン', + }, + }, + 'ModifiedPictureStyle' => { + PrintConv => { + 'CM Set 1' => 'CMセット1', + 'CM Set 2' => 'CMセット2', + 'Faithful' => '忠実設定', + 'High Saturation' => '高彩度', + 'Landscape' => '風景', + 'Low Saturation' => '低彩度', + 'Monochrome' => 'モノトーン', + 'Neutral' => 'ニュートラル', + 'None' => '無し', + 'Portrait' => 'ポートレート', + 'Standard' => 'スタンダード', + 'User Def. 1' => 'ユーザ設定1', + 'User Def. 2' => 'ユーザ設定2', + 'User Def. 3' => 'ユーザ設定3', + }, + }, + 'ModifiedSaturation' => { + Description => '彩度修正', + PrintConv => { + 'CM1 (Red Enhance)' => 'CM1 (赤増)', + 'CM2 (Green Enhance)' => 'CM2 (緑増)', + 'CM3 (Blue Enhance)' => 'CM3 (青増)', + 'CM4 (Skin Tones)' => 'CM4 (肌色増)', + 'Off' => 'オフ', + }, + }, + 'ModifiedSharpnessFreq' => { + PrintConv => { + 'High' => '高い', + 'Low' => 'ソフト', + 'Standard' => 'スタンダード', + 'n/a' => '該当無し', + }, + }, + 'ModifiedToneCurve' => { + PrintConv => { + 'Custom' => 'カスタム', + 'Manual' => 'マニュアル', + 'Standard' => 'スタンダード', + }, + }, + 'ModifiedWhiteBalance' => { + PrintConv => { + 'Auto' => 'オート', + 'Black & White' => '白黒', + 'Cloudy' => '曇り', + 'Custom' => 'カスタム', + 'Custom 1' => 'カスタム1', + 'Custom 2' => 'カスタム2', + 'Custom 3' => 'カスタム3', + 'Custom 4' => 'カスタム4', + 'Daylight' => '昼光', + 'Daylight Fluorescent' => '昼光色蛍光灯', + 'Flash' => 'ストロボ', + 'Fluorescent' => '蛍光灯', + 'Manual Temperature (Kelvin)' => 'マニュアル白熱灯(ケルビン)', + 'PC Set1' => 'PC設定1', + 'PC Set2' => 'PC設定2', + 'PC Set3' => 'PC設定3', + 'PC Set4' => 'PC設定4', + 'PC Set5' => 'PC設定5', + 'Shade' => '日陰', + 'Tungsten' => 'タングステン(白熱灯)', + 'Underwater' => '水中', + }, + }, + 'ModifyDate' => 'ファイル作成日時', + 'MoireFilter' => { + PrintConv => { + 'Off' => 'オフ', + 'On' => 'オン', + }, + }, + 'MonitorOffTime' => 'モニターオフ遅延時間', + 'MonochromeFilterEffect' => { + PrintConv => { + 'Green' => '緑', + 'None' => '無し', + 'Orange' => 'オレンジ', + 'Red' => '赤', + 'Yellow' => '黄色', + }, + }, + 'MonochromeLinear' => { + PrintConv => { + 'No' => 'いいえ', + 'Yes' => 'はい', + }, + }, + 'MonochromeToningEffect' => { + PrintConv => { + 'Blue' => '青', + 'Green' => '緑', + 'None' => '無し', + 'Purple' => '紫', + 'Sepia' => 'セピア', + }, + }, + 'MultiExposure' => '多重露出データ', + 'MultiExposureAutoGain' => { + Description => '多重露出自動ゲイン', + PrintConv => { + 'Off' => 'オフ', + 'On' => 'オン', + }, + }, + 'MultiExposureMode' => { + Description => '多重露出モード', + PrintConv => { + 'Image Overlay' => 'イメージオーバーレイ', + 'Multiple Exposure' => '多重露出', + 'Off' => 'オフ', + }, + }, + 'MultiExposureShots' => '多重露出ショット', + 'MultiExposureVersion' => '多重露出データバージョン', + 'MultiFrameNoiseReduction' => { + Description => 'マルチショットノイズリダクション', + PrintConv => { + 'Off' => '切', + 'On' => '入', + }, + }, + 'MultiSample' => 'マルチサンプル', + 'MultiSelector' => { + Description => 'マルチ選択', + PrintConv => { + 'Do Nothing' => '何もしない', + 'Reset Meter-off Delay' => 'メーターオフ遅延時間リセット', + }, + }, + 'MultiSelectorPlaybackMode' => { + Description => 'マルチ選択 再生モード', + PrintConv => { + 'Choose Folder' => 'フォルダー選択', + 'Thumbnail On/Off' => 'サムネイル オン/オフ', + 'View Histograms' => 'ヒストグラム表示', + 'Zoom On/Off' => 'ズーム オン/オフ', + }, + }, + 'MultiSelectorShootMode' => { + Description => 'マルチ選択 撮影モード', + PrintConv => { + 'Highlight Active Focus Point' => 'ハイライトアクティブフォーカスポイント', + 'Not Used' => '未使用', + 'Select Center Focus Point' => '中央フォーカスポイント選択', + }, + }, + 'MultipleExposureSet' => { + Description => '多重露出設定', + PrintConv => { + 'Off' => 'オフ', + 'On' => 'オン', + }, + }, + 'Mute' => { + PrintConv => { + 'Off' => 'オフ', + 'On' => 'オン', + }, + }, + 'MyColorMode' => { + Description => 'マイカラーモード', + PrintConv => { + 'B&W' => '白黒', + 'Color Accent' => 'カラーアクセント', + 'Color Swap' => 'スイッチカラー', + 'Custom' => 'カスタム', + 'Dark Skin Tone' => 'ダークスキン調', + 'Light Skin Tone' => 'ライトスカイ調', + 'Neutral' => 'ニュートラル', + 'Off' => 'オフ', + 'Positive Film' => 'ポジフィルム', + 'Sepia' => 'セピア', + 'Vivid' => 'ビビッド', + 'Vivid Blue' => 'ビビッド青', + 'Vivid Green' => 'ビビッド緑', + 'Vivid Red' => 'ビビッド赤', + }, + }, + 'MyColors' => 'マイカラーモード', + 'NDFilter' => { + Description => 'NDフィルター', + PrintConv => { + 'Off' => 'オフ', + 'On' => 'オン', + }, + }, + 'NEFCompression' => { + Description => 'RAW圧縮', + PrintConv => { + 'Lossless' => 'ロスレス', + 'Lossy (type 1)' => '圧縮(タイプ1)', + 'Lossy (type 2)' => '圧縮(タイプ2)', + 'Uncompressed' => '非圧縮', + }, + }, + 'NEFLinearizationTable' => '線形化表', + 'NamedColor2' => '色名称2', + 'NativeDisplayInfo' => 'ネイティブディスプレイ情報', + 'NewsPhotoVersion' => '報道写真レコードバージョン', + 'NikonCaptureData' => 'ニコンキャプチャーデータ', + 'NikonCaptureOffsets' => 'ニコンキャプチャーオフセット', + 'NikonCaptureVersion' => 'ニコンキャプチャーバージョン', + 'NoMemoryCard' => { + Description => 'メモリーカード無し', + PrintConv => { + 'Enable Release' => 'レリーズ可能', + 'Release Locked' => 'レリーズロック', + }, + }, + 'Noise' => 'ノイズ', + 'NoiseFilter' => { + Description => 'ピクチャーモードノイズフィルター', + PrintConv => { + 'High' => '高い', + 'Low' => 'ソフト', + 'Off' => 'オフ', + 'Standard' => 'スタンダード', + }, + }, + 'NoiseReduction' => { + Description => 'ノイズリダクション', + PrintConv => { + 'Auto' => 'オート', + 'Low' => '低い', + 'Normal' => '標準', + 'Off' => 'オフ', + 'On' => 'オン', + 'Standard' => 'スタンダード', + }, + }, + 'NoiseReduction2' => 'ノイズリダクション2', + 'NoiseReductionApplied' => '適用ノイズリダクション', + 'NoiseReductionData' => 'ノイズリダクションデータ', + 'NoiseReductionIntensity' => 'ノイズリダクション強度', + 'NoiseReductionMethod' => 'ノイズリダクション方法', + 'NoiseReductionSharpness' => 'ノイズリダクションシャープネス', + 'NominalMaxAperture' => '最大絞り', + 'NominalMinAperture' => '最小絞り', + 'NumAFPoints' => 'AFポイント番号', + 'NumIndexEntries' => 'インデックスエントリ数', + 'NumberofInks' => 'インク番号', + 'OPIProxy' => 'OPIプロキシー', + 'ObjectAttributeReference' => 'インテリジャンル', + 'ObjectCycle' => 'オブジェクトサイクル', + 'ObjectDistance' => '被写体との距離', + 'ObjectFileType' => { + PrintConv => { + 'None' => '無し', + 'Unknown' => '不明', + }, + }, + 'ObjectName' => 'タイトル', + 'ObjectPreviewData' => 'オブジェクトデータプレビューデータ', + 'ObjectPreviewFileFormat' => 'オブジェクトデータプレビューファイル形式', + 'ObjectPreviewFileVersion' => 'オブジェクトデータプレビューファイル形式バージョン', + 'ObjectTypeReference' => 'オブジェクトタイプ参照', + 'OffsetSchema' => 'オフセットの概要', + 'OlympusImageHeight' => 'イメージ高', + 'OlympusImageWidth' => 'イメージ幅', + 'OneTouchWB' => { + Description => 'ワンタッチホワイトバランス', + PrintConv => { + 'Off' => 'オフ', + 'On' => 'オン', + 'On (Preset)' => 'オン(プリセット)', + }, + }, + 'OpticalZoomCode' => '光学ズームコード', + 'OpticalZoomMode' => { + Description => '光学ズームモード', + PrintConv => { + 'Extended' => 'EX光学', + 'Standard' => 'スタンダード', + }, + }, + 'OpticalZoomOn' => { + Description => '光学ズームオン', + PrintConv => { + 'Off' => 'オフ', + 'On' => 'オン', + }, + }, + 'Opto-ElectricConvFactor' => '光電交換関数', + 'OrderNumber' => 'オーダー番号', + 'Orientation' => { + Description => '画像の向き', + PrintConv => { + 'Horizontal (normal)' => '水平(標準)', + 'Rotate 180' => '180度回転', + 'Rotate 270 CW' => '270度回転 CW', + 'Rotate 90 CW' => '90度回転 CW', + }, + }, + 'OriginalDecisionDataOffset' => 'オリジナル決定データオフセット', + 'OriginalRawFileData' => 'オリジナルRAWファイルデータ', + 'OriginalRawFileDigest' => 'オリジナルRAWファイル要約', + 'OriginalRawFileName' => 'オリジナルRAWファイル名', + 'OriginalTransmissionReference' => '作業識別子', + 'OriginatingProgram' => '開始プログラム', + 'OutputResponse' => '出力反応', + 'OwnerID' => 'オーナーID', + 'OwnerName' => 'オーナー名', + 'PEFVersion' => 'PEFバージョン', + 'Padding' => '引き伸ばし', + 'PageName' => 'ページ名', + 'PageNumber' => 'ページ番号', + 'PanasonicExifVersion' => 'パナソニックExifバージョン', + 'PanasonicRawVersion' => 'パナソニックRAWバージョン', + 'PanasonicTitle' => 'タイトル', + 'PanoramaDirection' => 'F値', + 'PanoramaMode' => 'パノラマモード', + 'PentaxImageSize' => 'ペンタックスイメージサイズ', + 'PentaxModelID' => 'ペンタックスモデル', + 'PentaxVersion' => 'ペンタックスバージョン', + 'People' => '人々', + 'PhaseDetectAF' => { + Description => 'オートフォーカス', + PrintConv => { + 'Off' => 'オフ', + 'On (51-point)' => 'オン', + }, + }, + 'PhotoEffect' => { + Description => '写真効果', + PrintConv => { + 'B&W' => '白黒', + 'Custom' => 'カスタム', + 'Neutral' => 'ニュートラル', + 'Off' => 'オフ', + 'Sepia' => 'セピア', + 'Vivid' => 'ビビッド', + }, + }, + 'PhotoEffects' => { + Description => 'フォトエフェクト', + PrintConv => { + 'Off' => 'オフ', + 'On' => 'オン', + }, + }, + 'PhotoEffectsBlue' => 'フォトエフェクト青', + 'PhotoEffectsData' => 'フォトエフェクトデータ', + 'PhotoEffectsGreen' => 'フォトエフェクト緑', + 'PhotoEffectsRed' => 'フォトエフェクト赤', + 'PhotoEffectsType' => { + Description => 'フォトエフェクトタイプ', + PrintConv => { + 'B&W' => '白黒', + 'None' => '無し', + 'Sepia' => 'セピア', + 'Tinted' => '淡調', + }, + }, + 'PhotoInfoPlayback' => { + Description => '写真情報/再生', + PrintConv => { + 'Info Left-right, Playback Up-down' => '情報<>/再生', + 'Info Up-down, Playback Left-right' => '情報/再生<>', + }, + }, + 'PhotometricInterpretation' => { + Description => 'ピクセル形式', + PrintConv => { + 'BlackIsZero' => '黒はゼロ', + 'Color Filter Array' => 'CFA (カラーフィルターマトリックス)', + 'Pixar LogL' => 'CIE Log2(L) (ログ輝度)', + 'Pixar LogLuv' => 'CIE Log2(L)(u\',v\') (ログ輝度と基準色)', + 'RGB Palette' => 'パレット色', + 'Transparency Mask' => '透明度マスク', + 'WhiteIsZero' => '白はゼロ', + }, + }, + 'PhotoshopAnnotations' => 'フォトショップ注釈', + 'PhotoshopFormat' => { + PrintConv => { + 'Standard' => 'スタンダード', + }, + }, + 'PictInfo' => '写真情報', + 'PictureControl' => { + Description => 'ピクチャーコントロール', + PrintConv => { + 'Off' => 'オフ', + 'On' => 'オン', + }, + }, + 'PictureControlActive' => { + PrintConv => { + 'Off' => 'オフ', + 'On' => 'オン', + }, + }, + 'PictureControlAdjust' => { + Description => 'ピクチャーコントロール調整', + PrintConv => { + 'Default Settings' => 'デフォルト設定', + 'Full Control' => 'フルコントロール', + 'Quick Adjust' => 'クイック調整', + }, + }, + 'PictureControlBase' => 'ピクチャーコントロールベース', + 'PictureControlName' => 'ピクチャーコントロール名', + 'PictureControlQuickAdjust' => 'ピクチャーコントロールクイック調整', + 'PictureControlVersion' => 'ピクチャーコントロールバージョン', + 'PictureFinish' => { + Description => 'ピクチャーフィニッシュ', + PrintConv => { + 'Monochrome' => 'モノトーン', + 'Natural' => 'ナチュラル', + 'Night Portrait' => '人物夜景', + 'Night Scene' => '夜景', + 'Portrait' => 'ポートレート', + }, + }, + 'PictureMode' => { + Description => 'ピクチャーモード', + PrintConv => { + '1/2 EV steps' => '1/2 EVステップ', + '1/3 EV steps' => '1/3 EVステップ', + 'Anti-blur' => '手振れ補正', + 'Aperture Priority' => '絞り優先', + 'Aperture Priority, Off-Auto-Aperture' => '絞り優先(自動絞りOFF)', + 'Aperture-priority AE' => '絞り優先', + 'Auto' => 'オート', + 'Auto PICT (Landscape)' => 'オートピクチャー(風景)', + 'Auto PICT (Macro)' => 'オートピクチャー(マクロ)', + 'Auto PICT (Portrait)' => 'オートピクチャー(ポートレート)', + 'Auto PICT (Sport)' => 'オートピクチャー(スポーツ)', + 'Auto PICT (Standard)' => 'オートピクチャー(標準)', + 'Autumn' => '秋', + 'Beach' => 'ビーチ', + 'Beach & Snow' => 'ビーチ&スノー', + 'Blur Reduction' => 'Digital SR', + 'Bulb' => 'バルブ', + 'Bulb, Off-Auto-Aperture' => 'バルブ(自動絞りOFF)', + 'Candlelight' => 'キャンドルライト', + 'DOF Program' => '深度優先プログラム', + 'DOF Program (HyP)' => '深度優先プログラム(ハイパープログラム)', + 'Dark Pet' => 'ペット黒色', + 'Digital Filter' => 'デジタルフィルター', + 'Fireworks' => '花火', + 'Flash X-Sync Speed AE' => 'ストロボ同調速度AE', + 'Flower' => '花', + 'Food' => '料理', + 'Frame Composite' => 'フレーム合成', + 'Green Mode' => 'グリーンモード', + 'Hi-speed Program' => '高速優先プログラム', + 'Hi-speed Program (HyP)' => '高速優先プログラム(ハイパープログラム)', + 'Illustrations' => 'イラスト', + 'Kids' => 'キッズ', + 'Landscape' => '風景', + 'Light Pet' => 'ペット白色', + 'MTF Program' => 'MTF優先プログラム', + 'MTF Program (HyP)' => 'MTF優先プログラム(ハイパープログラム)', + 'Macro' => 'マクロ', + 'Manual' => 'マニュアル', + 'Manual, Off-Auto-Aperture' => 'マニュアル(自動絞りOFF)', + 'Medium Pet' => 'ペット灰色', + 'Monotone' => 'モノトーン', + 'Museum' => '美術館', + 'Muted' => '弱める', + 'Natural' => 'ナチュラル', + 'Natural Light' => 'ナチュラルフォト', + 'Natural Light & Flash' => 'ナチュラルフォト&フラッシュ', + 'Natural Skin Tone' => '美肌', + 'Night Scene' => '夜景', + 'Night Scene Portrait' => '人物、夜景', + 'No Flash' => 'フラッシュ無し', + 'Panorama' => 'パノラマ', + 'Party' => 'パーティ', + 'Pet' => 'ペット', + 'Portrait' => 'ポートレート', + 'Program' => 'プログラム', + 'Program (HyP)' => 'プログラムAE(ハイパープログラム)', + 'Program AE' => 'プログラムAE', + 'Program Av Shift' => 'プログラムAvシフト', + 'Program Tv Shift' => 'プログラムTvシフト', + 'Self Portrait' => '自分撮り', + 'Sensitivity Priority AE' => '感度優先AE', + 'Sepia' => 'セピア', + 'Shutter & Aperture Priority AE' => 'シャッター&絞り優先AE', + 'Shutter Speed Priority' => 'シャッター優先', + 'Shutter speed priority AE' => 'シャッター優先', + 'Snow' => 'スノー', + 'Soft' => 'ソフト', + 'Sport' => 'スポーツ', + 'Sports' => 'スポーツ', + 'Standard' => 'スタンダード', + 'Sunset' => '夕日', + 'Surf & Snow' => 'サーフ&スノー', + 'Synchro Sound Record' => 'ボイスレコーディング', + 'Text' => 'テキスト', + 'Underwater' => '水中', + 'Vivid' => 'ビビッド', + }, + }, + 'PictureMode2' => { + Description => 'ピクチャーモード 2', + PrintConv => { + 'Aperture Priority' => '絞り優先', + 'Aperture Priority, Off-Auto-Aperture' => '絞り優先(自動絞りオフ)', + 'Auto PICT' => 'オートピクチャ', + 'Bulb' => 'バルブ', + 'Bulb, Off-Auto-Aperture' => 'バルブ(自動絞りオフ)', + 'Flash X-Sync Speed AE' => 'ストロボ同調速度AE', + 'Green Mode' => 'グリーンモード', + 'Manual' => 'マニュアル', + 'Manual, Off-Auto-Aperture' => 'マニュアル(自動絞りオフ)', + 'Program AE' => 'プログラムAE', + 'Program Av Shift' => 'プログラムAvシフト', + 'Program Tv Shift' => 'プログラムTvシフト', + 'Scene Mode' => 'シーンモード', + 'Sensitivity Priority AE' => '感度優先AE', + 'Shutter & Aperture Priority AE' => 'シャッター&絞り優先AE', + 'Shutter Speed Priority' => 'シャッター優先', + }, + }, + 'PictureModeBWFilter' => { + Description => 'ピクチャーモードBWフィルター', + PrintConv => { + 'Green' => '緑', + 'Neutral' => 'ニュートラル', + 'Orange' => 'オレンジ', + 'Red' => '赤', + 'Yellow' => '黄色', + 'n/a' => '該当無し', + }, + }, + 'PictureModeContrast' => 'ピクチャーモードコントラスト', + 'PictureModeHue' => 'ピクチャーモード色相?', + 'PictureModeSaturation' => 'ピクチャーモード彩度', + 'PictureModeSharpness' => 'ピクチャーモードシャープネス', + 'PictureModeTone' => { + Description => 'ピクチャーモードトーン', + PrintConv => { + 'Blue' => '青', + 'Green' => '緑', + 'Neutral' => 'ニュートラル', + 'Purple' => '紫', + 'Sepia' => 'セピア', + 'n/a' => '該当無し', + }, + }, + 'PictureStyle' => { + Description => 'ピクチャースタイル', + PrintConv => { + 'CM Set 1' => 'CMセット1', + 'CM Set 2' => 'CMセット2', + 'Faithful' => '忠実設定', + 'High Saturation' => '高彩度', + 'Landscape' => '風景', + 'Low Saturation' => '低彩度', + 'Monochrome' => 'モノトーン', + 'Neutral' => 'ニュートラル', + 'None' => '無し', + 'Portrait' => 'ポートレート', + 'Standard' => 'スタンダード', + 'User Def. 1' => 'ユーザ設定1', + 'User Def. 2' => 'ユーザ設定2', + 'User Def. 3' => 'ユーザ設定3', + }, + }, + 'PixelFormat' => { + Description => 'ピクセルフォーマット', + PrintConv => { + 'Black & White' => '白黒', + }, + }, + 'PixelIntensityRange' => 'ピクセル強度範囲', + 'PixelScale' => 'モデル画素スケールタグ', + 'PixelUnits' => { + PrintConv => { + 'Unknown' => '不明', + }, + }, + 'PlanarConfiguration' => { + Description => '画像データの並び', + PrintConv => { + 'Chunky' => '点順次形式 (重ね合わせ)', + 'Planar' => '平面形式', + }, + }, + 'PowerSource' => { + Description => '電源', + PrintConv => { + 'Body Battery' => '本体電源', + 'External Power Supply' => '外部電源', + 'Grip Battery' => 'バッテリーグリップ', + }, + }, + 'PreCaptureFrames' => 'プレキャプチャーフレーム', + 'Predictor' => '指標', + 'Preview' => 'プレビューIFDポインター', + 'Preview0' => 'プレビュー0', + 'Preview1' => 'プレビュー1', + 'Preview2' => 'プレビュー2', + 'PreviewApplicationName' => 'プレビューアプリケーション名', + 'PreviewApplicationVersion' => 'プレビューアプリケーションバージョン', + 'PreviewColorSpace' => { + Description => 'プレビュー色空間', + PrintConv => { + 'Unknown' => '不明', + }, + }, + 'PreviewDateTime' => 'プレビュー日時', + 'PreviewIFD' => 'プレビューIFDポインター', + 'PreviewImage' => 'プレビューイメージ', + 'PreviewImageBorders' => 'プレビュー画像境界', + 'PreviewImageData' => 'プレビュー画像データ', + 'PreviewImageLength' => 'プレビューイメージ容量', + 'PreviewImageSize' => 'プレビューイメージサイズ', + 'PreviewImageStart' => 'プレビューイメージ開始', + 'PreviewImageValid' => { + Description => '有効プレビュー画像', + PrintConv => { + 'No' => 'いいえ', + 'Yes' => 'はい', + }, + }, + 'PreviewQuality' => { + PrintConv => { + 'Economy' => 'エコノミー', + 'Fine' => 'ファイン', + 'Normal' => '標準', + 'Normal Movie' => '標準動画', + 'Superfine' => 'S.ファイン', + }, + }, + 'PreviewSettingsDigest' => 'プレビュー設定要約', + 'PreviewSettingsName' => 'プレビュー設定名', + 'PrimaryAFPoint' => { + Description => 'プライマリAFポイント', + PrintConv => { + 'Bottom' => '下', + 'C6 (Center)' => 'C6 (中央)', + 'Center' => '中央', + 'Mid-left' => '中央左', + 'Mid-right' => '中央右', + 'Top' => '上', + }, + }, + 'PrimaryChromaticities' => '原色色度', + 'PrimaryPlatform' => '主要プラットフォーム', + 'PrintIM' => 'プリントイメージマッチング', + 'ProcessingSoftware' => '処理ソフトウェア', + 'ProductID' => '製品ID', + 'ProductionCode' => 'カメラが修理されたか?', + 'ProfileCMMType' => 'CMMタイププロフィール', + 'ProfileCalibrationSig' => 'プロフィールキャリブレーションサイン', + 'ProfileClass' => { + Description => 'プロフィールクラス', + PrintConv => { + 'Abstract Profile' => '抜粋プロフィール', + 'ColorSpace Conversion Profile' => '色空間変換プロフィール', + 'DeviceLink Profile' => 'デバイスリンクプロフィール', + 'Display Device Profile' => '表示装置プロフィール', + 'Input Device Profile' => '入力装置プロフィール', + 'NamedColor Profile' => '色名称プロフィール', + 'Nikon Input Device Profile (NON-STANDARD!)' => 'ニコンプロフィール("nkpf")', + 'Output Device Profile' => '出力装置プロフィール', + }, + }, + 'ProfileConnectionSpace' => '接続スペースプロフィール', + 'ProfileCopyright' => 'プロフィール著作権', + 'ProfileCreator' => 'プロフィール製作者', + 'ProfileDateTime' => 'プロフィール日時', + 'ProfileDescription' => 'プロフィール説明', + 'ProfileDescriptionML' => 'プロフィール説明ML', + 'ProfileEmbedPolicy' => { + Description => 'プロフィール埋め込み方針', + PrintConv => { + 'Allow Copying' => 'コピー許可', + 'Embed if Used' => '埋め込み使用', + 'Never Embed' => '埋め込み禁止', + 'No Restrictions' => '無制限', + }, + }, + 'ProfileFileSignature' => 'プロフィールファイルシグネーチャ', + 'ProfileHueSatMapData1' => '色相Sat.マップデータプロフィール1', + 'ProfileHueSatMapData2' => '色相Sat.マップデータプロフィール2', + 'ProfileHueSatMapDims' => '色境界', + 'ProfileID' => 'プロフィールID', + 'ProfileLookTableData' => '表示テーブルデータプロフィール', + 'ProfileLookTableDims' => '色境界', + 'ProfileName' => 'プロフィール名', + 'ProfileSequenceDesc' => 'プロフィールシーケンス説明', + 'ProfileToneCurve' => 'トーンカーブプロフィール', + 'ProfileVersion' => 'プロフィールバージョン', + 'ProgramISO' => 'プログラムISO', + 'ProgramLine' => { + Description => 'プログラムライン', + PrintConv => { + 'Depth' => '深度優先', + 'Hi Speed' => '高速優先', + 'MTF' => 'MTF優先', + 'Normal' => 'ノーマル', + }, + }, + 'ProgramMode' => { + PrintConv => { + 'Night Portrait' => '人物夜景', + 'None' => '無し', + 'Portrait' => 'ポートレート', + 'Sports' => 'スポーツ', + 'Sunset' => '夕日', + 'Text' => 'テキスト', + }, + }, + 'ProgramShift' => 'プログラムシフト', + 'ProgramVersion' => 'プログラムバージョン', + 'Province-State' => '行政区/州', + 'Quality' => { + Description => '品質', + PrintConv => { + 'Best' => 'S.ファイン', + 'Better' => 'ファイン', + 'Compressed RAW' => 'cRAW', + 'Compressed RAW + JPEG' => 'cRAW+JPEG', + 'Economy' => 'エコノミー', + 'Extra Fine' => 'エクストラファイン', + 'Fine' => 'ファイン', + 'Good' => 'エコノミー', + 'Low' => '低画質', + 'Normal' => 'ノーマル', + 'Premium' => 'プレミアム', + 'RAW + JPEG' => 'RAW+JPEG', + 'Standard' => 'スタンダード', + 'n/a' => '未設定', + }, + }, + 'QualityMode' => { + Description => '品質モード', + PrintConv => { + 'Economy' => 'エコノミー', + 'Fine' => 'ファイン', + 'Normal' => 'ノーマル', + }, + }, + 'QuantizationMethod' => '量子化方法', + 'QuickAdjust' => 'クイック調整', + 'QuickControlDialInMeter' => { + Description => '測光タイマー中のサブ電子ダイヤル', + PrintConv => { + 'AF point selection' => 'AFフレーム選択', + 'Exposure comp/Aperture' => '露出補正/絞り数値', + 'ISO speed' => 'ISO感度', + }, + }, + 'QuickShot' => { + Description => 'クイックショット', + PrintConv => { + 'Off' => 'オフ', + 'On' => 'オン', + }, + }, + 'RAFVersion' => 'RAFバージョン', + 'ROCInfo' => 'ROC情報', + 'RasterPadding' => 'ラスタパディング', + 'RasterizedCaption' => 'ラスタ化表題', + 'Rating' => '格付け', + 'RatingPercent' => '格付け(%)', + 'RawAndJpgRecording' => { + Description => 'RAWとJPEG記録', + PrintConv => { + 'RAW+Large/Fine' => 'RAW+ラージ/ファイン', + 'RAW+Large/Normal' => 'RAW+ラージ/ノーマル', + 'RAW+Medium/Fine' => 'RAW+ミドル/ファイン', + 'RAW+Medium/Normal' => 'RAW+ミドル/ノーマル', + 'RAW+Small/Fine' => 'RAW+スモール/ファイン', + 'RAW+Small/Normal' => 'RAW+スモール/ノーマル', + }, + }, + 'RawColorAdj' => { + PrintConv => { + 'Custom' => 'カスタム', + 'Faithful' => '忠実設定', + }, + }, + 'RawDataOffset' => 'RAWデータオフセット', + 'RawDataUniqueID' => 'RAWデータユニークID', + 'RawDevAutoGradation' => { + PrintConv => { + 'Off' => 'オフ', + 'On' => 'オン', + }, + }, + 'RawDevColorSpace' => '色空間', + 'RawDevContrastValue' => 'コントラスト値', + 'RawDevEditStatus' => { + Description => '編集状態', + PrintConv => { + 'Edited (Landscape)' => 'スタジオ(風景)', + 'Edited (Portrait)' => 'スタジオ(ポートレート)', + 'Original' => 'オリジナル', + }, + }, + 'RawDevEngine' => { + Description => 'エンジン', + PrintConv => { + 'Advanced High Speed' => 'アドバンス高速', + 'High Function' => '高機能', + 'High Speed' => '高速', + }, + }, + 'RawDevExposureBiasValue' => '露出バイアス値', + 'RawDevGrayPoint' => 'グレーポイント', + 'RawDevMemoryColorEmphasis' => '記憶色強調', + 'RawDevNoiseReduction' => 'ノイズフィルター(増感)', + 'RawDevPMPictureTone' => { + PrintConv => { + 'Blue' => '青', + 'Green' => '緑', + 'Neutral' => 'ニュートラル', + 'Purple' => '紫', + 'Sepia' => 'セピア', + }, + }, + 'RawDevPM_BWFilter' => { + PrintConv => { + 'Green' => '緑', + 'Neutral' => 'ニュートラル', + 'Orange' => 'オレンジ', + 'Red' => '赤', + 'Yellow' => '黄色', + }, + }, + 'RawDevPictureMode' => { + PrintConv => { + 'Natural' => 'ナチュラル', + 'Sepia' => 'セピア', + 'Vivid' => 'ビビッド', + }, + }, + 'RawDevSaturationEmphasis' => '彩度強調', + 'RawDevSettings' => 'ノイズリダクション', + 'RawDevSharpnessValue' => 'コントラスト値', + 'RawDevVersion' => 'RAW展開バージョン', + 'RawDevWBFineAdjustment' => 'ホワイトバランス微調整', + 'RawDevWhiteBalance' => { + PrintConv => { + 'Color Temperature' => '色温度', + }, + }, + 'RawDevWhiteBalanceValue' => 'ホワイトバランス値', + 'RawImageCenter' => 'RAWイメージセンター', + 'RawImageDigest' => 'RAWイメージ要約', + 'RawImageHeight' => 'イメージ高さ', + 'RawImageSegmentation' => 'RAWイメージ部分番号', + 'RawImageSize' => 'RAWイメージサイズ', + 'RawImageWidth' => 'イメージ幅', + 'RawInfoVersion' => 'RAW情報バージョン', + 'RawJpgQuality' => { + Description => 'RAW JPEG 品質', + PrintConv => { + 'Economy' => 'エコノミー', + 'Fine' => 'ファイン', + 'Normal' => '標準', + 'Normal Movie' => '標準動画', + 'Superfine' => 'S.ファイン', + }, + }, + 'RawJpgSize' => { + Description => 'RAW JPEG サイズ', + PrintConv => { + 'Large' => 'ラージ', + 'Medium' => 'ミドル', + 'Medium 1' => 'ミドル1', + 'Medium 2' => 'ミドル2', + 'Medium 3' => 'ミドル3', + 'Medium Movie' => 'ミディアム動画', + 'Postcard' => 'ハガキ', + 'Small' => 'スモール', + 'Small Movie' => 'スモール動画', + 'Widescreen' => 'ワイド画面', + }, + }, + 'RecordMode' => { + Description => '記録モード', + PrintConv => { + 'Aperture Priority' => '絞り優先', + 'Best Shot' => 'ベストショット', + 'Manual' => 'マニュアル', + 'Movie' => '動画', + 'Movie (19)' => '動画(19)', + 'Program AE' => 'プログラムAE', + 'Shutter Priority' => 'シャッター優先', + 'YouTube Movie' => 'YouTube動画', + }, + }, + 'RecordShutterRelease' => 'レコードシャッターレリーズ', + 'RecordingMode' => { + Description => '記録モード', + PrintConv => { + 'Auto' => 'オート', + 'Landscape' => '風景', + 'Manual' => 'マニュアル', + 'Night Scene' => '夜景', + 'Panorama' => 'パノラマ', + 'Portrait' => 'ポートレート', + 'Single Shutter' => 'シングルシャッター', + }, + }, + 'RedBalance' => 'レッドバランス', + 'RedEyeCorrection' => { + PrintConv => { + 'Automatic' => 'オート', + 'Off' => 'オフ', + }, + }, + 'RedEyeData' => '赤目データ', + 'RedEyeReduction' => { + PrintConv => { + 'Off' => 'オフ', + 'On' => 'オン', + }, + }, + 'RedMatrixColumn' => '赤色マトリックス列', + 'RedTRC' => '赤色調増殖曲線', + 'ReductionMatrix1' => '縮小マトリックス1', + 'ReductionMatrix2' => '縮小マトリックス2', + 'ReferenceBlackWhite' => '白黒の基準値の一組', + 'ReferenceDate' => '参照日付', + 'ReferenceNumber' => '参照数', + 'ReferenceService' => '参照サービス', + 'RelatedImageFileFormat' => '関連イメージファイル形式', + 'RelatedImageHeight' => '関連イメージ高', + 'RelatedImageWidth' => '関連イメージ幅', + 'RelatedSoundFile' => '関連オーディオファイル', + 'ReleaseButtonToUseDial' => { + Description => 'レリーズボタンから使用ダイヤル', + PrintConv => { + 'No' => 'いいえ', + 'Yes' => 'はい', + }, + }, + 'ReleaseDate' => 'リリース日付', + 'ReleaseTime' => 'リリース時間', + 'RemoteOnDuration' => 'リモート持続時間', + 'RenderingIntent' => { + Description => '意思表現', + PrintConv => { + 'ICC-Absolute Colorimetric' => '絶対比色分析', + 'Media-Relative Colorimetric' => '相対比色分析', + 'Perceptual' => '知覚的', + 'Saturation' => '飽和', + }, + }, + 'RepeatingFlashCount' => 'リピーティングフラッシュ 時間', + 'RepeatingFlashOutput' => 'リピーティングフラッシュ 出力', + 'RepeatingFlashRate' => 'リピーティングフラッシュ 周波数', + 'ResampleParamsQuality' => { + PrintConv => { + 'High' => '高い', + 'Low' => 'ソフト', + }, + }, + 'Resaved' => { + Description => '予約', + PrintConv => { + 'No' => 'いいえ', + 'Yes' => 'はい', + }, + }, + 'ResolutionMode' => '解像度モード', + 'ResolutionUnit' => { + Description => 'XとY解像度単位', + PrintConv => { + 'None' => '無し', + 'cm' => 'ピクセル/cm', + 'inches' => 'インチ', + }, + }, + 'RetouchHistory' => { + Description => 'レタッチ履歴', + PrintConv => { + 'None' => '無し', + 'Sepia' => 'セピア', + }, + }, + 'ReverseIndicators' => '指標逆転', + 'Rotation' => { + Description => '回転', + PrintConv => { + 'Horizontal' => '水平(標準)', + 'Horizontal (Normal)' => '水平(標準)', + 'Horizontal (normal)' => '水平(標準)', + 'Rotate 180' => '180度回転', + 'Rotate 270 CW' => '270度回転 CW', + 'Rotate 90 CW' => '90度回転 CW', + 'Rotated 180' => '180度回転', + 'Rotated 270 CW' => '270度回転 CW', + 'Rotated 90 CW' => '90度回転 CW', + }, + }, + 'RowInterleaveFactor' => '列を挟む要因', + 'RowsPerStrip' => '1片の列数', + 'SMaxSampleValue' => 'S 最大サンプル値', + 'SMinSampleValue' => 'S 最小サンプル値', + 'SPIFFVersion' => 'SPIFFバージョン', + 'SRAWQuality' => { + PrintConv => { + 'n/a' => '該当無し', + }, + }, + 'SRActive' => { + Description => '手ぶれ補正状態', + PrintConv => { + 'No' => 'オフ', + 'Yes' => 'オン', + }, + }, + 'SRFocalLength' => 'SR焦点距離', + 'SRHalfPressTime' => 'シャッター半押し時間', + 'SRResult' => { + Description => 'SR効果', + PrintConv => { + 'Not stabilized' => 'なし', + }, + }, + 'SVGVersion' => 'SVGバージョン', + 'SafetyShift' => { + Description => 'セイフティシフト', + PrintConv => { + 'Disable' => 'しない', + 'Enable (ISO speed)' => 'する(ISO感度)', + 'Enable (Tv/Av)' => 'する(Tv/Av値)', + }, + }, + 'SafetyShiftInAvOrTv' => { + Description => 'セイフティシフトの設定', + PrintConv => { + 'Disable' => 'しない', + 'Enable' => 'する', + }, + }, + 'SampleFormat' => 'サンプル形式', + 'SampleStructure' => 'サンプリング構造', + 'SamplesPerPixel' => 'コンポーネント数', + 'SanyoQuality' => 'サンヨー品質', + 'SanyoThumbnail' => 'サンヨーサムネイル', + 'Saturation' => { + Description => '彩度', + PrintConv => { + '+1 (medium high)' => '+1 (少し高い)', + '+2 (high)' => '+2 (ハード)', + '+3 (very high)' => '+3 (かなり高い)', + '+4 (highest)' => '+4', + '+4 (maximum)' => '+4', + '-1 (medium low)' => '-1 (少し低い)', + '-2 (low)' => '-2 (ソフト)', + '-3 (very low)' => '-3 (かなり低い)', + '-4 (lowest)' => '-4', + '-4 (minimum)' => '-4', + '0 (normal)' => '0 (スタンダード)', + 'B&W' => '黒&白', + 'Film Simulation' => 'フィルムシミュレーション', + 'High' => '高い彩度', + 'Low' => '低い彩度', + 'Medium High' => '少し高い', + 'Medium Low' => '少し低い', + 'None' => '未設定', + 'None (B&W)' => '無し(黒&白)', + 'Normal' => '標準', + }, + }, + 'SaturationFaithful' => '彩度忠実設定', + 'SaturationLandscape' => '彩度風景', + 'SaturationNeutral' => '彩度ニュートラル', + 'SaturationPortrait' => '彩度ポートレート', + 'SaturationSetting' => '彩度設定', + 'SaturationStandard' => '彩度スタンダード', + 'SaturationUserDef1' => '彩度ユーザ設定1', + 'SaturationUserDef2' => '彩度ユーザ設定2', + 'SaturationUserDef3' => '彩度ユーザ設定3', + 'ScanImageEnhancer' => { + PrintConv => { + 'Off' => 'オフ', + 'On' => 'オン', + }, + }, + 'ScanningDirection' => '走査方向', + 'Scene' => '場面', + 'SceneArea' => 'シーンエリア?', + 'SceneAssist' => 'シーン調整', + 'SceneCaptureType' => { + Description => 'シーンキャプチャタイプ', + PrintConv => { + 'Landscape' => '風景', + 'Night' => '夜景', + 'Portrait' => 'ポートレート', + 'Standard' => 'スタンダード', + }, + }, + 'SceneDetect' => 'シーン検出', + 'SceneDetectData' => 'シーン検出データ?', + 'SceneMode' => { + Description => 'シーンモード', + PrintConv => { + '2 in 1' => '2イン1', + '3D Sweep Panorama' => '3D', + 'Aerial Photo' => '空撮', + 'Anti Motion Blur' => '人物ブレ軽減', + 'Aperture Priority' => '絞り優先', + 'Auction' => 'アクション', + 'Auto' => 'オート', + 'Auto+' => 'Auto アドバンス', + 'Available Light' => '自然光', + 'Baby' => '赤ちゃん', + 'Beach' => 'ビーチ', + 'Beach & Snow' => 'ビーチ&スノー', + 'Behind Glass' => 'ガラス越し', + 'Candle' => 'キャンドル', + 'Candlelight' => 'キャンドルライト', + 'Children' => '子供', + 'Color Effects' => 'カラーエフェクト', + 'Cont. Priority AE' => '連続撮影優先AE', + 'Cuisine' => '料理', + 'Digital Image Stabilization' => 'デジタル手振れ補正', + 'Documents' => '文書', + 'Face Portrait' => '寝顔', + 'Fireworks' => '花火', + 'Food' => '料理', + 'Handheld Night Shot' => '手持ち夜景', + 'High Key' => 'ハイキー', + 'High Sensitivity' => '高感度', + 'High Speed Continuous Shooting' => '高速連写', + 'Indoor' => '屋内撮影', + 'Intelligent Auto' => 'インテリジェントオート', + 'Intelligent ISO' => 'インテリジェントISO', + 'Landscape' => '風景', + 'Landscape+Portrait' => '風景+人物', + 'Low Key' => 'ローキー', + 'Macro' => 'マクロ', + 'Manual' => 'マニュアル', + 'Movie' => '動画', + 'Movie Preview' => '動画プレビュー', + 'Museum' => '美術館', + 'My Mode' => 'マイモード', + 'Nature Macro' => '自然マクロ', + 'Night Portrait' => '人物夜景', + 'Night Scene' => '夜景', + 'Night Scenery' => '夜景', + 'Night View/Portrait' => 'ナイトビュー/ポートレイト', + 'Night+Portrait' => '夜景+人物', + 'Normal' => 'ノーマル', + 'Off' => 'オフ', + 'Panning' => 'パンニング', + 'Panorama' => 'パノラマ', + 'Panorama Assist' => 'パノラマアシスト', + 'Party' => 'パーティ', + 'Pet' => 'ペット', + 'Portrait' => 'ポートレート', + 'Program' => 'プログラム', + 'Scenery' => '風景', + 'Self Portrait' => '自分撮り', + 'Self Portrait+Self Timer' => '自分撮り+セルフタイマー', + 'Self Protrait+Timer' => '自分撮り+セルフタイマー', + 'Shoot & Select' => 'ショット&セレクト', + 'Shoot & Select1' => 'ショット&セレクト1', + 'Shoot & Select2' => 'ショット&セレクト2', + 'Shooting Guide' => '撮影ガイド', + 'Shutter Priority' => 'シャッター優先', + 'Simple' => 'シンプル', + 'Smile Shot' => 'スマイルショット', + 'Snow' => 'スノー', + 'Soft Skin' => 'ソフトスキン', + 'Sport' => 'スポーツ', + 'Sports' => 'スポーツ', + 'Spot' => 'スポット', + 'Standard' => 'スタンダード', + 'Starry Night' => '星空', + 'Sunset' => '夕日', + 'Super Macro' => 'スーパーマクロ', + 'Sweep Panorama' => 'スイングパノラマ', + 'Text' => 'テキスト', + 'Underwater' => '水中', + 'Underwater Macro' => '水中マクロ', + 'Underwater Snapshot' => '水中スナップ', + 'Underwater Wide1' => '水中ワイド1', + 'Underwater Wide2' => '水中ワイド2', + 'Vivid' => 'ビビッド', + }, + }, + 'SceneModeUsed' => { + Description => 'シーンモード', + PrintConv => { + 'Aperture Priority' => '絞り優先', + 'Beach' => 'ビーチ', + 'Candlelight' => 'キャンドルライト', + 'Fireworks' => '花火', + 'Landscape' => '風景', + 'Macro' => 'マクロ', + 'Manual' => 'マニュアル', + 'Night Portrait' => '人物夜景', + 'Portrait' => 'ポートレート', + 'Program' => 'プログラム', + 'Shutter Priority' => 'シャッター優先', + 'Snow' => 'スノー', + 'Sunset' => '夕日', + 'Text' => 'テキスト', + }, + }, + 'SceneSelect' => { + Description => 'シーン選択', + PrintConv => { + 'Lamp' => 'ランプ', + 'Night' => '夜景', + 'Off' => 'オフ', + 'Sport' => 'スポーツ', + 'TV' => 'テレビ', + 'User 1' => 'ユーザー1', + 'User 2' => 'ユーザー2', + }, + }, + 'SceneType' => { + Description => 'シーンタイプ', + PrintConv => { + 'Directly photographed' => '直接撮影画像', + }, + }, + 'SecurityClassification' => { + Description => 'セキュリティ区分', + PrintConv => { + 'Confidential' => '機密文書', + 'Restricted' => '限定', + 'Secret' => '秘密', + 'Top Secret' => '最高機密', + 'Unclassified' => '未分類', + }, + }, + 'SelectableAFPoint' => { + Description => '任意選択可能なAFフレーム', + PrintConv => { + '11 points' => '11点', + '19 points' => '19点', + '45 points' => '45点', + 'Inner 9 points' => '9点(内側)', + 'Outer 9 points' => '9点(外側)', + }, + }, + 'SelfTimer' => { + Description => 'セルフタイマー長', + PrintConv => { + 'Off' => 'オフ', + 'On' => 'オン', + }, + }, + 'SelfTimer2' => 'セルフタイマー(2)', + 'SelfTimerMode' => 'セルフタイマーモード', + 'SelfTimerTime' => 'セルフタイマー遅延時間', + 'SensingMethod' => { + Description => 'センサー方式', + PrintConv => { + 'Color sequential area' => 'シーケンシャルカラーセンサー', + 'Color sequential linear' => 'シーケンシャルカラーラインセンサー', + 'Monochrome area' => 'モノクロエリアセンサー', + 'Monochrome linear' => 'モノクロラインセンサー', + 'Not defined' => '未定義', + 'One-chip color area' => '単板式カラーセンサー', + 'Three-chip color area' => '3板式カラーセンサー', + 'Trilinear' => '3ラインセンサー', + 'Two-chip color area' => '2板式カラーセンサー', + }, + }, + 'SensitivityAdjust' => '感度調節', + 'SensitivitySteps' => { + Description => '感度ステップ', + PrintConv => { + '1 EV Steps' => '1EVステップ', + 'As EV Steps' => '露出ステップに従う', + }, + }, + 'SensorCleaning' => { + PrintConv => { + 'Disable' => 'しない', + 'Enable' => 'する', + }, + }, + 'SensorHeight' => 'センサー高さ', + 'SensorImageHeight' => 'センサー高さ', + 'SensorImageWidth' => 'センサー幅', + 'SensorLeftBorder' => 'イメージ左部', + 'SensorPixelSize' => 'センサーピクセルサイズ', + 'SensorTemperature' => 'センサー温度', + 'SensorTopBorder' => 'イメージ上部', + 'SensorWidth' => 'センサー幅', + 'Sequence' => 'シーケンス', + 'SequenceNumber' => 'シーケンス番号', + 'SequenceShotInterval' => 'シーケンスショットインターバル', + 'SequentialShot' => { + Description => 'シーケンシャルショット', + PrintConv => { + 'None' => '無し', + 'Standard' => 'スタンダード', + }, + }, + 'SerialNumber' => 'シリアル番号', + 'SerialNumberFormat' => 'シリアル番号形式', + 'ServiceIdentifier' => 'サービス識別子', + 'SetButtonCrossKeysFunc' => { + Description => 'SETボタン/十字キー機能', + PrintConv => { + 'Cross keys: AF point select' => '十字キー:AFフレーム選択', + 'Normal' => '標準', + 'Set: Flash Exposure Comp' => 'SET:調光補正', + 'Set: Parameter' => 'SET:現像パラメーター選択', + 'Set: Picture Style' => 'SET:ピクチャースタイル', + 'Set: Playback' => 'SET:画像の再生', + 'Set: Quality' => 'SET:記録画質', + }, + }, + 'SetButtonWhenShooting' => { + Description => '撮影時のSETボタン', + PrintConv => { + 'Change parameters' => '現像パラメーター選択', + 'Default (no function)' => '通常(なし)', + 'Disabled' => '無効', + 'Flash exposure compensation' => '調光補正', + 'ISO speed' => 'ISO感度', + 'Image playback' => '画像再生', + 'Image quality' => '記録画質選択', + 'Image size' => '画像サイズ', + 'LCD monitor On/Off' => '液晶モニターの入/切', + 'Menu display' => 'メニュー表示', + 'Normal (disabled)' => '通常(無効)', + 'Picture style' => 'ピクチャースタイル', + 'Quick control screen' => 'クイック設定画面', + 'Record func. + media/folder' => '記録機能とメディア・フォルダ', + 'Record movie (Live View)' => '動画撮影(ライブビュー)', + 'White balance' => 'ホワイトバランス', + }, + }, + 'SetFunctionWhenShooting' => { + Description => '撮影時のセットボタン機能', + PrintConv => { + 'Change Parameters' => '現像パラメーター選択', + 'Change quality' => '記録画質選択', + 'Default (no function)' => '通常(なし)', + 'Image replay' => '画像の再生', + 'Menu display' => 'メニュー表示', + }, + }, + 'ShadingCompensation' => { + Description => '陰影修正', + PrintConv => { + 'Off' => 'オフ', + 'On' => 'オン', + }, + }, + 'ShadingCompensation2' => { + Description => '陰影補正編集', + PrintConv => { + 'Off' => 'オフ', + 'On' => 'オン', + }, + }, + 'Shadow' => 'シャドウ', + 'ShadowScale' => 'シャドウスケール', + 'Shadows' => 'シャドウ', + 'ShakeReduction' => { + Description => '手ぶれ補正(設定)', + PrintConv => { + 'Off' => 'オフ', + 'On' => 'オン', + }, + }, + 'ShakeReductionInfo' => 'SR効果', + 'Sharpness' => { + Description => 'シャープネス', + PrintConv => { + '+1 (medium hard)' => '+1 (少しハード)', + '+2 (hard)' => '+2 (ハード)', + '+3 (very hard)' => '+3 (かなりハード)', + '+4 (hardest)' => '+4', + '+4 (maximum)' => '+4', + '-1 (medium soft)' => '-1 (ミドルソフト)', + '-2 (soft)' => '-2 (ソフト)', + '-3 (very soft)' => '-3 (かなりソフト)', + '-4 (minimum)' => '-4', + '-4 (softest)' => '-4', + '0 (normal)' => '0 (ノーマル)', + 'Film Simulation' => 'フィルムシミュレーション', + 'Hard' => 'ハード', + 'Hard2' => 'ハード2', + 'Medium Hard' => 'ミドルハード', + 'Medium Soft' => 'ミドルソフト', + 'Normal' => 'ノーマル', + 'Sharp' => 'シャープ', + 'Soft' => 'ソフト', + 'Soft2' => 'ソフト2', + 'n/a' => '該当無し', + }, + }, 'SharpnessFactor' => 'シャープネス要因', + 'SharpnessFaithful' => 'シャープネス忠実設定', + 'SharpnessFrequency' => { + PrintConv => { + 'High' => '高い', + 'Low' => 'ソフト', + 'Standard' => 'スタンダード', + 'n/a' => '該当無し', + }, + }, + 'SharpnessLandscape' => 'シャープネス風景', + 'SharpnessMonochrome' => 'シャープネスモノクロ', + 'SharpnessNeutral' => 'シャープネスニュートラル', + 'SharpnessPortrait' => 'シャープネスポートレート', + 'SharpnessSetting' => 'シャープネス設定', + 'SharpnessStandard' => 'シャープネススタンダード', + 'SharpnessUserDef1' => 'シャープネスユーザ設定1', + 'SharpnessUserDef2' => 'シャープネスユーザ設定2', + 'SharpnessUserDef3' => 'シャープネスユーザ設定3', + 'ShootingInfoDisplay' => { + Description => '撮影情報表示', + PrintConv => { + 'Auto' => 'オート', + 'Manual (dark on light)' => '手動-黒地に白', + 'Manual (light on dark)' => '手動-白地に黒', + }, + }, + 'ShootingMode' => { + Description => '撮影モード', + PrintConv => { + 'Aerial Photo' => '空撮', + 'Aperture Priority' => '絞り優先', + 'Baby' => '赤ちゃん', + 'Beach' => 'ビーチ', + 'Candlelight' => 'キャンドルライト', + 'Clipboard' => 'メモ', + 'Color Effects' => 'カラーエフェクト', + 'Economy' => 'エコモード', + 'Fireworks' => '花火', + 'Food' => '料理', + 'High Sensitivity' => '高感度', + 'High Speed Continuous Shooting' => '高速連写', + 'Intelligent Auto' => 'インテリジェントオート', + 'Intelligent ISO' => 'インテリジェントISO', + 'Macro' => 'マクロ', + 'Manual' => 'マニュアル', + 'Movie Preview' => '動画プレビュー', + 'Night Portrait' => '人物夜景', + 'Night Scenery' => '夜景', + 'Normal' => '標準', + 'Panning' => 'パンニング', + 'Panorama Assist' => 'パノラマアシスト', + 'Party' => 'パーティ', + 'Pet' => 'ペット', + 'Portrait' => 'ポートレート', + 'Program' => 'プログラム', + 'Scenery' => '風景', + 'Self Portrait' => '自分撮り', + 'Shutter Priority' => 'シャッター優先', + 'Simple' => 'シンプル', + 'Snow' => 'スノー', + 'Soft Skin' => 'ソフトスキン', + 'Sports' => 'スポーツ', + 'Spot' => 'スポット', + 'Starry Night' => '星空', + 'Sunset' => '夕日', + 'Underwater' => '水中', + }, + }, + 'ShootingModeSetting' => { + Description => '撮影モード', + PrintConv => { + 'Continuous' => '連続撮影', + 'Delayed Remote' => '遅延リモート', + 'Quick-response Remote' => '即時リモート', + 'Self-timer' => 'セルフタイマー', + 'Single Frame' => '1コマ撮影', + }, + }, + 'ShortDocumentID' => '短文書ID', + 'ShortOwnerName' => '短いオーナー名', + 'ShortReleaseTimeLag' => { + Description => 'レリーズタイムラグ最速化', + PrintConv => { + 'Disable' => 'しない', + 'Enable' => 'する', + }, + }, + 'ShotInfoVersion' => 'ショット情報バージョン', + 'Shutter-AELock' => { + Description => 'シャッターボタン/AEロックボタン', + PrintConv => { + 'AE lock/AF' => 'AEロック/AF', + 'AE/AF, No AE lock' => 'AE/AF(AEロックなし)', + 'AF/AE lock' => 'AF/AEロック', + 'AF/AF lock' => 'AF/AFロック', + 'AF/AF lock, No AE lock' => 'AF/AFロック(AEロックなし)', + }, + }, + 'ShutterAELButton' => 'シャッターボタン/AEロックボタン', + 'ShutterButtonAFOnButton' => { + Description => 'シャッター/AF-ONボタン', + PrintConv => { + 'AE lock/Metering + AF start' => 'AEロック/測光・AF開始', + 'Metering + AF start' => '測光・AF開始', + 'Metering + AF start/AF stop' => '測光・AF開始/AFストップ', + 'Metering + AF start/disable' => '測光・AF開始/無効', + 'Metering start/Meter + AF start' => '測光開始/測光・AF開始', + }, + }, + 'ShutterCount' => 'シャッター回数', + 'ShutterCurtainSync' => { + Description => 'ストロボのシンクロタイミング', + PrintConv => { + '1st-curtain sync' => '先幕シンクロ', + '2nd-curtain sync' => '後幕シンクロ', + }, + }, + 'ShutterMode' => { + PrintConv => { + 'Aperture Priority' => '絞り優先', + 'Auto' => 'オート', + }, + }, + 'ShutterReleaseButtonAE-L' => { + Description => 'シャッターレリーズボタン AE-L', + PrintConv => { + 'Off' => 'オフ', + 'On' => 'オン', + }, + }, + 'ShutterReleaseNoCFCard' => { + Description => 'CFカード未装填時のレリーズ', + PrintConv => { + 'No' => 'いいえ', + 'Yes' => 'はい', + }, + }, + 'ShutterSpeed' => '露出時間', + 'ShutterSpeedRange' => { + Description => 'シャッター速度の制御範囲の設定', + PrintConv => { + 'Disable' => 'しない', + 'Enable' => 'する', + }, + }, + 'ShutterSpeedValue' => 'シャッタースピード', + 'SimilarityIndex' => '類似インデックス', + 'Site' => 'サイト', + 'SlaveFlashMeteringSegments' => 'スレーブフラッシュ測光値', + 'SlideShow' => { + PrintConv => { + 'No' => 'いいえ', + 'Yes' => 'はい', + }, + }, + 'SlowShutter' => { + Description => 'スローシャッター', + PrintConv => { + 'Night Scene' => '夜景', + 'None' => '無し', + 'Off' => 'オフ', + 'On' => 'オン', + }, + }, + 'SlowSync' => { + Description => 'スローシンクロ', + PrintConv => { + 'Off' => 'オフ', + 'On' => 'オン', + }, + }, + 'Software' => 'ソフトウェア', + 'SoftwareVersion' => 'ソフトウェアバージョン', + 'Source' => 'ソース', + 'SpatialFrequencyResponse' => '空間周波数特性', + 'SpecialEffectsOpticalFilter' => { + PrintConv => { + 'None' => '無し', + }, + }, + 'SpecialInstructions' => '手順', + 'SpecialMode' => 'スペシャルモード', + 'SpectralSensitivity' => 'スペクトル感度', + 'SpotFocusPointX' => 'スポットフォーカスポイントX', + 'SpotFocusPointY' => 'スポットフォーカスポイントY', + 'SpotMeterLinkToAFPoint' => { + Description => '測距点連動スポット測光', + PrintConv => { + 'Disable (use center AF point)' => 'しない(中央固定', + 'Enable (use active AF point)' => 'する(測距点連動)', + }, + }, + 'SpotMeteringMode' => { + Description => 'スポットメーターモード', + PrintConv => { + 'Center' => '中央', + }, + }, + 'State' => '都道府県名', + 'StoNits' => 'Stoニット', + 'StraightenAngle' => 'ストレートアングル', + 'StreamType' => { + PrintConv => { + 'Text' => 'テキスト', + }, + }, + 'StripByteCounts' => '圧縮片のバイト数', + 'StripOffsets' => '画像データ位置', + 'Sub-location' => '場所', + 'SubSecCreateDate' => 'デジタルデータ作成日時', + 'SubSecDateTimeOriginal' => 'オリジナルデータ作成日時', + 'SubSecModifyDate' => 'ファイル作成日時', + 'SubSecTime' => 'DateTimeサブ秒', + 'SubSecTimeDigitized' => 'DateTimeDigitizedサブ秒', + 'SubSecTimeOriginal' => 'DateTimeOriginalサブ秒', + 'SubTileBlockSize' => 'サブタイトルブロックサイズ', + 'SubfileType' => '新規サブファイルタイプ', + 'SubimageColor' => { + PrintConv => { + 'Monochrome' => 'モノトーン', + }, + }, + 'Subject' => 'サブジェクト', + 'SubjectArea' => '対象領域', + 'SubjectCode' => 'サブジェクトコード', + 'SubjectDistance' => '対象距離', + 'SubjectDistanceRange' => { + Description => '被写体距離範囲', + PrintConv => { + 'Close' => '近景', + 'Distant' => '遠景', + 'Macro' => 'マクロ', + 'Unknown' => '不明', + }, + }, + 'SubjectLocation' => '対象領域', + 'SubjectProgram' => { + Description => '被写体プログラム', + PrintConv => { + 'Night portrait' => '人物夜景', + 'None' => '無し', + 'Portrait' => 'ポートレート', + 'Sports action' => 'スポーツアクション', + 'Sunset' => '夕日', + 'Text' => 'テキスト', + }, + }, + 'SubjectReference' => 'サブジェクトコード', + 'Subsystem' => { + PrintConv => { + 'Unknown' => '不明', + }, + }, + 'SuperMacro' => { + Description => 'スーパーマクロ', + PrintConv => { + 'Off' => 'オフ', + 'On (1)' => 'オン(1)', + 'On (2)' => 'オン(2)', + }, + }, + 'SuperimposedDisplay' => { + Description => 'スーパーインポーズの表示', + PrintConv => { + 'Off' => 'オフ', + 'On' => 'オン', + }, + }, + 'SupplementalCategories' => '補足カテゴリー', + 'SupplementalType' => '補足タイプ', + 'SvISOSetting' => 'SVISO感度設定', + 'SwitchToRegisteredAFPoint' => { + Description => '登録AFフレームへの切り換え', + PrintConv => { + 'Disable' => 'しない', + 'Enable' => 'する', + }, + }, + 'T4Options' => 'T4オプション', + 'T6Options' => 'T6オプション', + 'TIFF-EPStandardID' => 'TIFF/EP標準ID', + 'TTL_DA_ADown' => 'TTL D/A Aチャンネル ダウン', + 'TTL_DA_AUp' => 'TTL D/A Aチャンネル アップ', + 'TTL_DA_BDown' => 'TTL D/A Bチャンネル ダウン', + 'TTL_DA_BUp' => 'TTL D/A Bチャンネル アップ', + 'Tagged' => { + PrintConv => { + 'No' => 'いいえ', + 'Yes' => 'はい', + }, + }, + 'TargetAperture' => 'ターゲット絞り', + 'TargetExposureTime' => 'ターゲット露出時間', + 'TargetPrinter' => '標的プリンタ', + 'Technology' => { + Description => 'テクノロジー', + PrintConv => { + 'Active Matrix Display' => 'アクティブマトリクス型ディスプレイ', + 'Cathode Ray Tube Display' => 'CRTディスプレイ', + 'Digital Camera' => 'デジタルカメラ', + 'Dye Sublimation Printer' => '昇華型プリンター', + 'Electrophotographic Printer' => '静電記録式プリンター', + 'Electrostatic Printer' => '静電気プリンター', + 'Film Scanner' => 'フイルムスキャナー', + 'Film Writer' => 'フィルムライター', + 'Flexography' => 'アニリン印刷', + 'Gravure' => 'グラビア印刷', + 'Ink Jet Printer' => 'インクジェットプリンター', + 'Offset Lithography' => 'オフセット印刷', + 'Passive Matrix Display' => '単純マトリクス型ディスプレイ', + 'Photo CD' => 'フォトCD', + 'Photo Image Setter' => 'フォトイメージセッター', + 'Photographic Paper Printer' => '印画紙プリンター', + 'Projection Television' => 'プロジェクションテレビ', + 'Reflective Scanner' => '反射スキャナ', + 'Silkscreen' => 'シルクスクリーン印刷', + 'Thermal Wax Printer' => '熱転写プリンター', + 'Video Camera' => 'ビデオカメラ', + 'Video Monitor' => 'ビデオモニター', + }, + }, + 'Teleconverter' => { + PrintConv => { + 'None' => '無し', + }, + }, + 'Text' => 'テキスト', + 'TextInfo' => 'テキスト情報', + 'TextStamp' => { + PrintConv => { + 'Off' => 'オフ', + 'On' => 'オン', + }, + }, + 'Thresholding' => '閾値化', + 'ThumbnailImage' => 'サムネイル画像', + 'ThumbnailImageSize' => 'サムネイルサイズ', + 'ThumbnailImageValidArea' => 'サムネイル画像有効領域', + 'TileByteCounts' => 'タイルのバイト数', + 'TileDepth' => 'タイルの深さ', + 'TileLength' => 'タイルの長さ', + 'TileOffsets' => 'タイルのオフセット', + 'TileWidth' => 'タイルの幅', + 'Time' => '時間', + 'TimeCreated' => '作成時間', + 'TimeScaleParamsQuality' => { + PrintConv => { + 'High' => '高い', + 'Low' => 'ソフト', + }, + }, + 'TimeSent' => '発送時間', + 'TimeSincePowerOn' => '電源オン経過時間', + 'TimeStamp' => 'タイムスタンプ', + 'TimeStamp1' => 'タイムスタンプ1', + 'TimeZone' => 'タイムゾーン', + 'TimeZoneOffset' => 'タイムゾーンオフセット', + 'TimerFunctionButton' => { + Description => 'ファンクションボタン', + PrintConv => { + 'ISO' => 'ISO感度', + 'Image Quality/Size' => '画像品質/サイズ', + 'Self-timer' => 'セルフタイマー', + 'Shooting Mode' => '撮影モード', + 'White Balance' => 'ホワイトバランス', + }, + }, + 'TimerLength' => { + Description => '各種タイマー保持時間', + PrintConv => { + 'Disable' => 'しない', + 'Enable' => 'する', + }, + }, + 'Title' => 'タイトル', + 'ToneComp' => 'トーン補正', + 'ToneCurve' => { + Description => 'トーンカーブ', + PrintConv => { + 'Custom' => 'カスタム', + 'Manual' => 'マニュアル', + 'Standard' => 'スタンダード', + }, + }, + 'ToneCurveActive' => { + PrintConv => { + 'No' => 'いいえ', + 'Yes' => 'はい', + }, + }, + 'ToneCurveName' => { + PrintConv => { + 'Custom' => 'カスタム', + }, + }, + 'ToneCurves' => 'トーンカーブ(s)', + 'ToningEffect' => { + Description => 'トーン効果', + PrintConv => { + 'B&W' => '白黒', + 'Blue' => '青', + 'Blue-green' => '青緑', + 'Cyanotype' => '青写真', + 'Green' => '緑', + 'None' => '無し', + 'Purple' => '紫', + 'Purple-blue' => '青紫', + 'Red' => '赤', + 'Red-purple' => '赤紫', + 'Sepia' => 'セピア', + 'Yellow' => '黄色', + 'n/a' => '該当無し', + }, + }, + 'ToningEffectMonochrome' => { + Description => 'モノクロトーン効果', + PrintConv => { + 'Blue' => '青', + 'Green' => '緑', + 'None' => '無し', + 'Purple' => '紫', + 'Sepia' => 'セピア', + }, + }, + 'ToningSaturation' => '彩度トーン', + 'TransferFunction' => '転送機能', + 'TransferRange' => '転送範囲', + 'Transformation' => { + Description => '変形', + PrintConv => { + 'Horizontal (normal)' => '水平(標準)', + 'Rotate 180' => '180度回転', + 'Rotate 270 CW' => '270度回転 CW', + 'Rotate 90 CW' => '90度回転 CW', + }, + }, + 'TransmissionReference' => '送信元記録', + 'TransparencyIndicator' => '透明度指標', + 'TrapIndicator' => 'トラップインジケーター', + 'Trapped' => { + PrintConv => { + 'Unknown' => '不明', + }, + }, + 'TravelDay' => 'トラベル日付', + 'TvExposureTimeSetting' => 'Tv露出時間設定', + 'Type' => 'タイプ', + 'USMLensElectronicMF' => { + Description => 'USMレンズの電子式手動フォーカス', + PrintConv => { + 'Disable after one-shot AF' => 'ワンショットAF作動後・不可', + 'Disable in AF mode' => 'AF時すべて不可', + 'Enable after one-shot AF' => 'ワンショットAF作動後・可', + }, + }, + 'Uncompressed' => { + Description => '非圧縮', + PrintConv => { + 'No' => 'いいえ', + 'Yes' => 'はい', + }, + }, + 'UniqueCameraModel' => 'ユニークカメラモデル', + 'UniqueDocumentID' => 'ユニーク文書ID', + 'UniqueObjectName' => 'ユニーク・ネーム・オブ・オブジェクト', + 'Unknown' => '不明', + 'Unsharp1Color' => { + Description => 'アンシャープ1カラー', + PrintConv => { + 'Blue' => '青', + 'Cyan' => 'シアン', + 'Green' => '緑', + 'Magenta' => 'マゼンダ', + 'Red' => '赤', + 'Yellow' => '黄色', + }, + }, + 'Unsharp1HaloWidth' => 'アンシャープ1円光幅', + 'Unsharp1Intensity' => 'アンシャープ1強度', + 'Unsharp1Threshold' => 'アンシャープ1起点', + 'Unsharp2Color' => { + Description => 'アンシャープ2カラー', + PrintConv => { + 'Blue' => '青', + 'Cyan' => 'シアン', + 'Green' => '緑', + 'Magenta' => 'マゼンダ', + 'Red' => '赤', + 'Yellow' => '黄色', + }, + }, + 'Unsharp2HaloWidth' => 'アンシャープ2円光幅', + 'Unsharp2Intensity' => 'アンシャープ2強度', + 'Unsharp2Threshold' => 'アンシャープ2起点', + 'Unsharp3Color' => { + Description => 'アンシャープ3カラー', + PrintConv => { + 'Blue' => '青', + 'Cyan' => 'シアン', + 'Green' => '緑', + 'Magenta' => 'マゼンダ', + 'Red' => '赤', + 'Yellow' => '黄色', + }, + }, + 'Unsharp3HaloWidth' => 'アンシャープ3円光幅', + 'Unsharp3Intensity' => 'アンシャープ3強度', + 'Unsharp3Threshold' => 'アンシャープ3起点', + 'Unsharp4Color' => { + Description => 'アンシャープ4カラー', + PrintConv => { + 'Blue' => '青', + 'Cyan' => 'シアン', + 'Green' => '緑', + 'Magenta' => 'マゼンダ', + 'Red' => '赤', + 'Yellow' => '黄色', + }, + }, + 'Unsharp4HaloWidth' => 'アンシャープ4円光幅', + 'Unsharp4Intensity' => 'アンシャープ4強度', + 'Unsharp4Threshold' => 'アンシャープ4起点', + 'UnsharpCount' => 'アンシャープカウント', + 'UnsharpData' => 'アンシャープデータ', + 'UnsharpMask' => { + Description => 'アンシャープマスク', + PrintConv => { + 'Off' => 'オフ', + 'On' => 'オン', + }, + }, + 'Urgency' => '緊急性', + 'UsableMeteringModes' => { + Description => '測光モードの限定', + PrintConv => { + 'Disable' => 'しない', + 'Enable' => 'する', + }, + }, + 'UsableShootingModes' => { + Description => '撮影モードの限定', + PrintConv => { + 'Disable' => 'しない', + 'Enable' => 'する', + }, + }, + 'UserComment' => 'ユーザーコメント', + 'UserDef1PictureStyle' => { + Description => 'ユーザ設定1 ピクチャースタイル', + PrintConv => { + 'Faithful' => '忠実設定', + 'Landscape' => '風景', + 'Monochrome' => 'モノトーン', + 'Neutral' => 'ニュートラル', + 'Portrait' => 'ポートレート', + 'Standard' => 'スタンダード', + }, + }, + 'UserDef2PictureStyle' => { + Description => 'ユーザ設定2 ピクチャースタイル', + PrintConv => { + 'Faithful' => '忠実設定', + 'Landscape' => '風景', + 'Monochrome' => 'モノトーン', + 'Neutral' => 'ニュートラル', + 'Portrait' => 'ポートレート', + 'Standard' => 'スタンダード', + }, + }, + 'UserDef3PictureStyle' => { + Description => 'ユーザ設定3 ピクチャースタイル', + PrintConv => { + 'Faithful' => '忠実設定', + 'Landscape' => '風景', + 'Monochrome' => 'モノトーン', + 'Neutral' => 'ニュートラル', + 'Portrait' => 'ポートレート', + 'Standard' => 'スタンダード', + }, + }, + 'VRDVersion' => 'VRDバージョン', + 'VRInfo' => 'VR(手振れ補正)情報', + 'VRInfoVersion' => 'VR情報バージョン', + 'VR_0x66' => { + PrintConv => { + 'Off' => 'オフ', + 'On (active)' => 'オン(アクティブ)', + 'On (normal)' => 'オン(ノーマル)', + }, + }, + 'ValidAFPoints' => '有効なAFポイント', + 'ValidBits' => 'ピクセルにつき有効なビット', + 'VariProgram' => 'バリプログラム', + 'Version' => 'バージョン', + 'VibrationReduction' => { + Description => '手振れ補正(VR)', + PrintConv => { + 'Off' => 'オフ', + 'On' => 'オン', + 'On (1)' => 'オン(1)', + 'On (2)' => 'オン(2)', + 'On (3)' => 'オン(3)', + 'n/a' => '該当無し', + }, + }, + 'VideoCardGamma' => 'ビデオカードガンマ', + 'ViewInfoDuringExposure' => { + Description => '露光中のファインダー内表示', + PrintConv => { + 'Disable' => 'しない', + 'Enable' => 'する', + }, + }, + 'ViewfinderWarning' => { + Description => 'ビューファインダー警告表示', + PrintConv => { + 'Off' => 'オフ', + 'On' => 'オン', + }, + }, + 'ViewingCondDesc' => '視聴状態説明', + 'ViewingCondIlluminant' => '視聴状態光源', + 'ViewingCondIlluminantType' => '視聴状態光源タイプ', + 'ViewingCondSurround' => '視聴状態周辺', + 'ViewingConditions' => '視聴状態光源', + 'VignetteControl' => { + Description => 'ビネットコントロール', + PrintConv => { + 'High' => '高い', + 'Low' => '低い', + 'Normal' => '標準', + 'Off' => 'オフ', + 'On' => 'オン', + }, + }, + 'VignetteControlIntensity' => 'ビネットコントロール強度', + 'VoiceMemo' => { + Description => 'ボイスメモ', + PrintConv => { + 'Off' => 'オフ', + 'On' => 'オン', + }, + }, + 'WBAdjData' => 'ホワイトバランス調整データ', + 'WBAdjLighting' => { + Description => 'ホワイトバランス調整、ライティング', + PrintConv => { + 'Daylight' => '昼光', + 'Flash' => 'ストロボ', + 'High Color Rendering Fluorescent (3700K)' => 'ハイカラーレンダリング蛍光灯 (1)', + 'High Color Rendering Fluorescent (5000K)' => 'ハイカラーレンダリング蛍光灯 (3)', + 'High Color Rendering Fluorescent (cool white)' => 'ハイカラーレンダリング蛍光灯 (2)', + 'High Color Rendering Fluorescent (daylight)' => 'ハイカラーレンダリング蛍光灯 (4)', + 'High Color Rendering Fluorescent (warm white)' => 'ハイカラーレンダリング蛍光灯 (0)', + 'Incandescent' => '電球', + 'None' => '無し', + 'Standard Fluorescent (3700K)' => '標準蛍光灯 (1)', + 'Standard Fluorescent (5000K)' => '標準蛍光灯 (3)', + 'Standard Fluorescent (6500K)' => '標準蛍光灯 (4)', + 'Standard Fluorescent (cool white)' => '標準蛍光灯 (2)', + 'Standard Fluorescent (high temperature mercury vapor)' => '標準蛍光灯 (5)', + 'Standard Fluorescent (warm white)' => '標準蛍光灯 (0)', + }, + }, + 'WBAdjMode' => { + Description => 'ホワイトバランス調整モード', + PrintConv => { + 'Calculate Automatically' => '自動計算', + 'Recorded Value' => '記録値', + 'Use Gray Point' => 'グレーポイント使用', + 'Use Temperature' => '温度使用', + }, + }, + 'WBAdjTemperature' => 'ホワイトバランス調整、色温度', + 'WBBlueLevel' => 'ホワイトバランス青レベル', + 'WBBracketMode' => { + Description => 'ホワイトバランスブラケットモード', + PrintConv => { + 'Off' => 'オフ', + 'On (shift AB)' => 'オン(シフトAB)', + 'On (shift GM)' => 'オン(シフトGM)', + }, + }, + 'WBBracketValueAB' => 'ホワイトバランスブラケット値AB', + 'WBBracketValueGM' => 'ホワイトバランスブラケット値GM', + 'WBFineTuneActive' => { + PrintConv => { + 'No' => 'いいえ', + 'Yes' => 'はい', + }, + }, + 'WBGreenLevel' => 'ホワイトバランス緑レベル', + 'WBMediaImageSizeSetting' => { + Description => 'WB/メディア・画像サイズの設定', + PrintConv => { + 'LCD monitor' => '液晶モニター', + 'Rear LCD panel' => '背面表示パネル', + }, + }, + 'WBMode' => { + Description => 'ホワイトバランスモード', + PrintConv => { + 'Auto' => 'オート', + }, + }, + 'WBRedLevel' => 'ホワイトバランス赤レベル', + 'WBShiftAB' => 'WB AB補正', + 'WBShiftGM' => 'WB GM補正', + 'WB_GBRGLevels' => 'WB GBRG レベル', + 'WB_GRBGLevels' => 'WB GRBG レベル', + 'WB_GRGBLevels' => 'WB GRGB レベル', + 'WB_RBGGLevels' => 'WB RBGG レベル', + 'WB_RBLevels' => 'WB RBレベル', + 'WB_RBLevels3000K' => 'WB RGGB3000Kレベル', + 'WB_RBLevels3300K' => 'WB RGGB3300Kレベル', + 'WB_RBLevels3600K' => 'WB RGGB3600Kレベル', + 'WB_RBLevels3900K' => 'WB RGGB3800Kレベル', + 'WB_RBLevels4000K' => 'WB RGGB4000Kレベル', + 'WB_RBLevels4300K' => 'WB RGGB4300Kレベル', + 'WB_RBLevels4500K' => 'WB RGGB4500Kレベル', + 'WB_RBLevels4800K' => 'WB RGGB4800Kレベル', + 'WB_RBLevels5300K' => 'WB RGGB5300Kレベル', + 'WB_RBLevels6000K' => 'WB RGGB6000Kレベル', + 'WB_RBLevels6600K' => 'WB RGGB6600Kレベル', + 'WB_RBLevels7500K' => 'WB RGGB7500Kレベル', + 'WB_RBLevelsAuto' => 'WB RB レベル オート', + 'WB_RBLevelsCloudy' => 'WB RB レベル 曇天', + 'WB_RBLevelsCoolWhiteFluor' => 'WB RB レベル 冷白蛍光灯', + 'WB_RBLevelsDayWhiteFluor' => 'WB RB レベル 昼白蛍光灯', + 'WB_RBLevelsDaylightFluor' => 'WB RB レベル 昼光蛍光灯', + 'WB_RBLevelsEveningSunlight' => 'WB RB レベル 夕日', + 'WB_RBLevelsFineWeather' => 'WB RB レベル 晴天', + 'WB_RBLevelsShade' => 'WB RB レベル 日陰', + 'WB_RBLevelsTungsten' => 'WB RB レベル 白熱灯', + 'WB_RBLevelsUsed' => 'WB RB レベル使用', + 'WB_RBLevelsWhiteFluorescent' => 'WB RB レベル 白蛍光灯', + 'WB_RGBGLevels' => 'WB RGBG レベル', + 'WB_RGBLevels' => 'WB RGB レベル', + 'WB_RGBLevelsCloudy' => 'WB RGB レベル 曇天', + 'WB_RGBLevelsDaylight' => 'WB RGB レベル 昼光', + 'WB_RGBLevelsFlash' => 'WB RGB レベル ストロボ', + 'WB_RGBLevelsFluorescent' => 'WB RGGB レベル 蛍光灯', + 'WB_RGBLevelsShade' => 'WB RGB レベル 日陰', + 'WB_RGBLevelsTungsten' => 'WB RGB レベル 白熱灯', + 'WB_RGGBLevels' => 'WB RGGB レベル', + 'WB_RGGBLevelsCloudy' => 'WB RGGB レベル 曇天', + 'WB_RGGBLevelsDaylight' => 'WB RGGB レベル 昼光', + 'WB_RGGBLevelsFlash' => 'WB RGGB レベル ストロボ', + 'WB_RGGBLevelsFluorescent' => 'WB RGGB レベル 蛍光灯', + 'WB_RGGBLevelsFluorescentD' => 'WB RGGB レベル 蛍光灯(D)', + 'WB_RGGBLevelsFluorescentN' => 'WB RGGB レベル 蛍光灯(N)', + 'WB_RGGBLevelsFluorescentW' => 'WB RGGB レベル 蛍光灯(W)', + 'WB_RGGBLevelsShade' => 'WB RGGB レベル 日陰', + 'WB_RGGBLevelsTungsten' => 'WB RGGB レベル 白熱灯', + 'WCSProfiles' => 'Windowsカラーシステムプロフィール', + 'WhiteBalance' => { + Description => 'ホワイトバランス', + PrintConv => { + 'Auto' => 'オート', + 'Black & White' => '白黒', + 'Cloudy' => '曇り', + 'Color Temperature/Color Filter' => '色温度マニュアル指定', + 'Cool White Fluorescent' => '白色蛍光灯', + 'Custom' => 'カスタム', + 'Custom 1' => 'カスタム1', + 'Custom 2' => 'カスタム2', + 'Custom 3' => 'カスタム3', + 'Custom 4' => 'カスタム4', + 'Custom2' => 'カスタム2', + 'Custom3' => 'カスタム3', + 'Custom4' => 'カスタム4', + 'Custom5' => 'カスタム5', + 'Day White Fluorescent' => '昼白色蛍光灯', + 'Daylight' => '昼光', + 'Daylight Fluorescent' => '昼光色蛍光灯', + 'Flash' => 'ストロボ', + 'Fluorescent' => '蛍光灯', + 'Incandescent' => '電球', + 'Kelvin' => 'ケルビン', + 'Living Room Warm White Fluorescent' => 'リビング暖白光色蛍光灯', + 'Manual' => 'マニュアル', + 'Manual Temperature (Kelvin)' => 'マニュアル白熱灯(ケルビン)', + 'PC Set1' => 'PC設定1', + 'PC Set2' => 'PC設定2', + 'PC Set3' => 'PC設定3', + 'PC Set4' => 'PC設定4', + 'PC Set5' => 'PC設定5', + 'Shade' => '日陰', + 'Tungsten' => 'タングステン(白熱灯)', + 'Underwater' => '水中', + 'Unknown' => '不明', + 'User-Selected' => 'ユーザ選択', + 'Warm White Fluorescent' => '暖白光色蛍光灯', + 'White Fluorescent' => '温白色蛍光灯', + }, + }, + 'WhiteBalance2' => { + Description => 'ホワイトバランス2', + PrintConv => { + '3000K (Tungsten light)' => '3000K (白熱電球)', + '3600K (Tungsten light-like)' => '3600K (白熱電球-like)', + '4000K (Cool white fluorescent)' => '4000K (蛍光灯1)', + '4500K (Neutral white fluorescent)' => '4500K (蛍光灯2)', + '5300K (Fine Weather)' => '5300K (晴天)', + '6000K (Cloudy)' => '6000K (曇り)', + '6600K (Daylight fluorescent)' => '6600K (蛍光灯3)', + '7500K (Fine Weather with Shade)' => '7500K (晴天と影)', + 'Auto' => 'オート', + 'Custom WB 1' => 'カスタムホワイトバランス1', + 'Custom WB 2' => 'カスタムホワイトバランス2', + 'Custom WB 2900K' => 'カスタムホワイトバランス2900K', + 'Custom WB 3' => 'カスタムホワイトバランス3', + 'Custom WB 4' => 'カスタムホワイトバランス4', + 'Custom WB 5400K' => 'カスタムホワイトバランス5400K', + 'Custom WB 8000K' => 'カスタムホワイトバランス8000K', + }, + }, + 'WhiteBalanceAdj' => { + Description => 'ホワイトバランス調整', + PrintConv => { + 'Auto' => 'オート', + 'Cloudy' => '曇り', + 'Daylight' => '昼光', + 'Flash' => 'ストロボ', + 'Fluorescent' => '蛍光灯', + 'Off' => 'オフ', + 'On' => 'オン', + 'Shade' => '日陰', + 'Tungsten' => 'タングステン(白熱灯)', + }, + }, + 'WhiteBalanceBias' => 'ホワイトバランスバイアス', + 'WhiteBalanceBracket' => 'ホワイトバランスブラケット', + 'WhiteBalanceComp' => 'ホワイトバランス補正', + 'WhiteBalanceFineTune' => 'ホワイトバランスファインチューン', + 'WhiteBalanceMode' => { + Description => 'ホワイトバランスモード', + PrintConv => { + 'Auto (Cloudy)' => 'オート(曇天)', + 'Auto (Day White Fluorescent)' => 'オート(昼白色蛍光灯)', + 'Auto (Daylight Fluorescent)' => 'オート(昼光色蛍光灯)', + 'Auto (Daylight)' => 'オート(昼光)', + 'Auto (Flash)' => 'オート(ストロボ)', + 'Auto (Shade)' => 'オート(日陰)', + 'Auto (Tungsten)' => 'オート(白熱灯)', + 'Auto (White Fluorescent)' => 'オート(白色蛍光灯)', + 'Unknown' => '不明', + 'User-Selected' => 'ユーザー選択', + }, + }, + 'WhiteBalanceSet' => { + Description => 'ホワイトバランス設定', + PrintConv => { + 'Auto' => 'オート', + 'Cloudy' => '曇り', + 'Day White Fluorescent' => '昼白色蛍光灯', + 'Daylight' => '昼光', + 'Daylight Fluorescent' => '昼光色蛍光灯', + 'Flash' => 'ストロボ', + 'Manual' => 'マニュアル', + 'Set Color Temperature 1' => '色温度設定1', + 'Set Color Temperature 2' => '色温度設定2', + 'Set Color Temperature 3' => '色温度設定3', + 'Shade' => '日陰', + 'Tungsten' => 'タングステン(白熱灯)', + 'White Fluorescent' => '温白色蛍光灯', + }, + }, + 'WhiteBalanceTemperature' => 'ホワイトバランス温度', + 'WhiteBoard' => 'ホワイトボード', + 'WhiteLevel' => '白レベル', + 'WhitePoint' => '白点色度', + 'Wide' => 'ワイド', + 'WideFocusZone' => 'ワイドフォーカスゾーン', + 'WideRange' => { + Description => 'ワイドレンジ', + PrintConv => { + 'Off' => 'オフ', + 'On' => 'オン', + }, + }, + 'WidthResolution' => '幅方向の画像解像度', + 'WorldTime' => 'タイムゾーン', + 'WorldTimeLocation' => { + Description => 'ワールドタイム位置', + PrintConv => { + 'Destination' => '目的地', + 'Home' => '自宅', + 'Hometown' => '現在地', + }, + }, + 'Writer-Editor' => '表題/説明の作家', + 'X3FillLight' => 'X3光を満たす', + 'XClipPathUnits' => 'Xクリップパス単位', + 'XMP' => 'XMPメタデータ', + 'XPAuthor' => '作者', + 'XPComment' => 'コメント', + 'XPKeywords' => 'キーワード', + 'XPSubject' => 'サブジェクト', + 'XPTitle' => 'タイトル', + 'XPosition' => 'X位置', + 'XResolution' => '画像幅の解像度', + 'YCbCrCoefficients' => 'カラースペース変化マトリックス係数', + 'YCbCrPositioning' => { + Description => 'YとCの位置', + PrintConv => { + 'Centered' => '中央', + 'Co-sited' => '相互配置', + }, + }, + 'YCbCrSubSampling' => 'YとCのサブサンプリング比率', + 'YClipPathUnits' => 'Yクリップパス単位', + 'YPosition' => 'Y位置', + 'YResolution' => '画像高さの解像度', + 'ZoneMatching' => { + Description => 'ゾーンマッチング', + PrintConv => { + 'High Key' => 'ハイキー', + 'ISO Setting Used' => 'オフ(ISO設定使用)', + 'Low Key' => 'ローキー', + }, + }, + 'ZoneMatchingOn' => { + Description => 'ゾーンマッチング', + PrintConv => { + 'Off' => 'オフ', + 'On' => 'オン', + }, + }, + 'Zoom' => 'ズーム', + 'ZoomSourceWidth' => 'ズームソース幅', + 'ZoomStepCount' => 'ズームステップ数', + 'ZoomTargetWidth' => 'ズームターゲット幅', +); + +1; # end + + +__END__ + +=head1 NAME + +Image::ExifTool::Lang::ja.pm - ExifTool Japanese language translations + +=head1 DESCRIPTION + +This file is used by Image::ExifTool to generate localized tag descriptions +and values. + +=head1 AUTHOR + +Copyright 2003-2019, Phil Harvey (phil at owl.phy.queensu.ca) + +This library is free software; you can redistribute it and/or modify it +under the same terms as Perl itself. + +=head1 ACKNOWLEDGEMENTS + +Thanks to Jens Duttke and Kazunari Nishina for providing this translation. + +=head1 SEE ALSO + +L<Image::ExifTool(3pm)|Image::ExifTool>, +L<Image::ExifTool::TagInfoXML(3pm)|Image::ExifTool::TagInfoXML> + +=cut diff --git a/lib/Image/ExifTool/Lang/ko.pm b/lib/Image/ExifTool/Lang/ko.pm new file mode 100644 index 0000000..16eb385 --- /dev/null +++ b/lib/Image/ExifTool/Lang/ko.pm @@ -0,0 +1,2330 @@ +#------------------------------------------------------------------------------ +# File: ko.pm +# +# Description: ExifTool Korean language translations +# +# Notes: This file generated automatically by Image::ExifTool::TagInfoXML +#------------------------------------------------------------------------------ + +package Image::ExifTool::Lang::ko; + +use strict; +use vars qw($VERSION); + +$VERSION = '1.06'; + +%Image::ExifTool::Lang::ko::Translate = ( + 'AELock' => { + Description => 'AE 고정', + PrintConv => { + 'Off' => '꺼짐', + 'On' => '켜짐', + }, + }, + 'AELockButton' => { + Description => 'AE-L/AF-L', + PrintConv => { + 'AE Lock (hold)' => 'AE 고정(유지)', + 'AE Lock Only' => 'AE 고정', + 'AE/AF Lock' => 'AE/AF 고정', + 'AF Lock Only' => 'AF 고정', + }, + }, + 'AF-CPrioritySelection' => { + Description => 'AF-C 선택 우선', + PrintConv => { + 'Focus' => '포커스', + 'Release' => '릴리즈', + 'Release + Focus' => '릴리즈 + 포커스', + }, + }, + 'AF-OnForMB-D10' => { + Description => 'MB-D10에서 AF-On', + PrintConv => { + 'AE Lock (hold)' => 'AE 고정 (유지)', + 'AE Lock (reset on release)' => 'AE 고정 (릴리즈때 리셋)', + 'AE Lock Only' => 'AE 고정', + 'AE/AF Lock' => 'AE/AF 고정', + 'AF Lock Only' => 'AF 고정', + 'AF-On' => 'AF-ON', + 'Same as FUNC Button' => 'FUNC 버튼과 같음', + }, + }, + 'AF-SPrioritySelection' => { + Description => 'AF-S 선택 우선', + PrintConv => { + 'Focus' => '포커스', + 'Release' => '릴리즈', + }, + }, + 'AFActivation' => { + Description => 'AF 작동', + PrintConv => { + 'AF-On Only' => 'AF-ON 고정', + 'Shutter/AF-On' => '셔터/AF-ON', + }, + }, + 'AFAperture' => 'AF 조리개', + 'AFAreaIllumination' => { + Description => 'AF 포인트 조명', + PrintConv => { + 'Auto' => '자동', + 'Off' => '꺼짐', + 'On' => '켜짐', + }, + }, + 'AFAreaMode' => { + Description => 'AF 영역 모드', + PrintConv => { + 'Auto-area' => '자동 영역 AF', + 'Dynamic Area' => '다이내믹 영역', + 'Dynamic Area (closest subject)' => '다이내믹 영역 (지근거리 우선)', + 'Dynamic Area (wide)' => '다이내믹 영역 (와이드)', + 'Group Dynamic' => '그룹 다이내믹', + 'Single Area' => '싱글 영역', + 'Single Area (wide)' => '싱글 영역 (와이드)', + }, + }, + 'AFAreaModeSetting' => { + Description => 'AF 영역 모드', + PrintConv => { + 'Closest Subject' => '접사', + 'Dynamic Area' => '다이내믹 영역', + 'Single Area' => '싱글 영역', + }, + }, + 'AFAssist' => { + Description => '내장 AF 보조광', + PrintConv => { + 'Off' => '꺼짐', + 'On' => '켜짐', + }, + }, + 'AFFineTune' => 'AF 미세 조정', + 'AFFineTuneAdj' => 'AF 미세 조정', + 'AFInfo' => 'AF 모드', + 'AFInfo2' => 'AF 정보', + 'AFInfo2Version' => 'AF 정보 버전', + 'AFMode' => 'AF 모드', + 'AFPoint' => { + Description => 'AF 포인트', + PrintConv => { + 'Bottom' => '하단', + 'Center' => '중앙', + 'Far Left' => '맨 좌측', + 'Far Right' => '맨 우측', + 'Left' => '왼쪽', + 'Lower-left' => '좌하단', + 'Lower-right' => '우하단', + 'Mid-left' => '왼쪽', + 'Mid-right' => '오른쪽', + 'Right' => '오른쪽', + 'Top' => '상단', + 'Upper-left' => '좌상단', + 'Upper-right' => '우상단', + }, + }, + 'AFPointIllumination' => { + Description => 'AF 포인트 조명', + PrintConv => { + 'Auto' => '자동', + 'Off' => '꺼짐', + 'On' => '켜짐', + }, + }, + 'AFPointMode' => { + PrintConv => { + 'Auto' => '자동', + }, + }, + 'AFPointSelected' => { + PrintConv => { + 'Auto' => '자동', + }, + }, + 'AFPointSelected2' => { + PrintConv => { + 'Auto' => '자동', + }, + }, + 'AFPointSelection' => { + Description => 'AF 포인트 선택', + PrintConv => { + '11 Points' => '11 포인트', + '51 Points' => '51 포인트', + }, + }, + 'AFPointsInFocus' => { + Description => '초점에서의 AF 포인트', + PrintConv => { + 'Far Left' => '맨 좌측', + 'Far Right' => '맨 우측', + 'Lower-left' => '좌하단', + 'Lower-right' => '우하단', + 'Upper-left' => '좌상단', + 'Upper-right' => '우상단', + }, + }, + 'AFPointsUnknown2' => { + PrintConv => { + 'Auto' => '자동', + }, + }, + 'AFPointsUsed' => { + Description => '사용된 AF 포인트', + PrintConv => { + 'Bottom' => '하단', + 'Center' => '중앙', + 'Far Left' => '맨 좌측', + 'Far Right' => '맨 우측', + 'Lower-left' => '좌하단', + 'Lower-right' => '우하단', + 'Top' => '상단', + 'Upper-left' => '좌상단', + 'Upper-right' => '우상단', + }, + }, + 'AFResponse' => 'AF 반응', + 'ActiveD-Lighting' => { + Description => '액티브 D-Lighting', + PrintConv => { + 'Off' => '꺼짐', + 'On' => '켜짐', + }, + }, + 'ActiveD-LightingMode' => { + PrintConv => { + 'Off' => '꺼짐', + }, + }, + 'AddAspectRatioInfo' => { + PrintConv => { + 'Off' => '꺼짐', + }, + }, + 'AddOriginalDecisionData' => { + PrintConv => { + 'Off' => '꺼짐', + 'On' => '켜짐', + }, + }, + 'AdvancedRaw' => { + PrintConv => { + 'Off' => '꺼짐', + 'On' => '켜짐', + }, + }, + 'Album' => '앨범', + 'Anti-Blur' => { + PrintConv => { + 'Off' => '꺼짐', + }, + }, + 'Aperture' => '조리개', + 'ApertureValue' => '조리개', + 'ApplicationRecordVersion' => '어플리케이션 기록 버전', + 'Artist' => '이미지를 만든 사람', + 'Author' => '작성자', + 'AuthorsPosition' => '직책', + 'AutoAperture' => { + PrintConv => { + 'Off' => '꺼짐', + 'On' => '켜짐', + }, + }, + 'AutoBracketModeM' => { + Description => '자동 브라케팅 (모드 M)', + PrintConv => { + 'Flash Only' => '플래시', + 'Flash/Aperture' => '플래시/조리개', + 'Flash/Speed' => '플래시/스피드', + 'Flash/Speed/Aperture' => '플래시/스피드/조리개', + }, + }, + 'AutoBracketOrder' => '브라케팅 순서', + 'AutoBracketSet' => { + Description => '자동 브라케팅 설정', + PrintConv => { + 'AE & Flash' => 'AE & 플래시', + 'AE Only' => 'AE 브라케팅', + 'Flash Only' => '플래시 브라케팅', + 'WB Bracketing' => 'WB 브라케팅', + }, + }, + 'AutoBracketing' => { + PrintConv => { + 'Off' => '꺼짐', + }, + }, + 'AutoExposureBracketing' => { + PrintConv => { + 'Off' => '꺼짐', + 'On' => '켜짐', + }, + }, + 'AutoFP' => { + Description => '자동 FP', + PrintConv => { + 'Off' => '꺼짐', + 'On' => '켜짐', + }, + }, + 'AutoFocus' => { + Description => '오토포커스', + PrintConv => { + 'Off' => '비활성', + 'On' => '활성', + }, + }, + 'AutoISO' => { + Description => '자동 ISO', + PrintConv => { + 'Off' => '꺼짐', + 'On' => '켜짐', + }, + }, + 'AutoISOMax' => '자동 ISO 최대 감도', + 'AutoISOMinShutterSpeed' => '자동 ISO 최소 셔터 속도', + 'AutoLightingOptimizer' => { + PrintConv => { + 'Off' => '꺼짐', + }, + }, + 'AutoRedEye' => { + PrintConv => { + 'Off' => '꺼짐', + 'On' => '켜짐', + }, + }, + 'AuxiliaryLens' => '보조 렌즈', + 'BWMode' => { + PrintConv => { + 'Off' => '꺼짐', + }, + }, + 'BatteryLevel' => '베터리 레벨', + 'BatteryOrder' => { + Description => '배터리 순서', + PrintConv => { + 'Camera Battery First' => '카메라 배터리 우선', + 'MB-D10 First' => 'MB-D10 배터리 우선', + }, + }, + 'Beep' => { + Description => '전자음', + PrintConv => { + 'High' => '크게', + 'Low' => '작게', + 'Off' => '꺼짐', + 'On' => '켜짐', + }, + }, + 'BitsPerSample' => '성분에 따른 비트 수', + 'BracketMode' => { + PrintConv => { + 'Off' => '꺼짐', + }, + }, + 'Brightness' => '밝기', + 'BrightnessValue' => '밝기', + 'BurstMode' => { + PrintConv => { + 'Off' => '꺼짐', + 'On' => '켜짐', + }, + }, + 'By-line' => '제작자', + 'CFAPattern' => 'CFA 패턴', + 'CLModeShootingSpeed' => 'CL 모드 촬영 속도', + 'CalibrationIlluminant1' => { + PrintConv => { + 'Cloudy' => '흐린 날씨', + 'Cool White Fluorescent' => '냉백색 형광등 (W 3800 - 4500K)', + 'Day White Fluorescent' => '주백색 형광등 (N 4600 - 5500K)', + 'Daylight' => '주광', + 'Daylight Fluorescent' => '주광색 형광등 (D 5700 - 7100K)', + 'Fine Weather' => '맑은 날씨', + 'Flash' => '플래시', + 'Fluorescent' => '형광등', + 'ISO Studio Tungsten' => 'ISO 스튜디오 텅스텐', + 'Other' => '기타 광원', + 'Shade' => '그늘', + 'Standard Light A' => '표준 광원 A', + 'Standard Light B' => '표준 광원 B', + 'Standard Light C' => '표준 광원 C', + 'Tungsten (Incandescent)' => '텅스텐 (백열등)', + 'Unknown' => '알 수 없음', + 'Warm White Fluorescent' => '따뜻한 흰색 형광 (L 2600 - 3250K)', + 'White Fluorescent' => '백색 형광등 (WW 3250 - 3800K)', + }, + }, + 'CalibrationIlluminant2' => { + PrintConv => { + 'Cloudy' => '흐린 날씨', + 'Cool White Fluorescent' => '냉백색 형광등 (W 3800 - 4500K)', + 'Day White Fluorescent' => '주백색 형광등 (N 4600 - 5500K)', + 'Daylight' => '주광', + 'Daylight Fluorescent' => '주광색 형광등 (D 5700 - 7100K)', + 'Fine Weather' => '맑은 날씨', + 'Flash' => '플래시', + 'Fluorescent' => '형광등', + 'ISO Studio Tungsten' => 'ISO 스튜디오 텅스텐', + 'Other' => '기타 광원', + 'Shade' => '그늘', + 'Standard Light A' => '표준 광원 A', + 'Standard Light B' => '표준 광원 B', + 'Standard Light C' => '표준 광원 C', + 'Tungsten (Incandescent)' => '텅스텐 (백열등)', + 'Unknown' => '알 수 없음', + 'Warm White Fluorescent' => '따뜻한 흰색 형광 (L 2600 - 3250K)', + 'White Fluorescent' => '백색 형광등 (WW 3250 - 3800K)', + }, + }, + 'CanonExposureMode' => { + PrintConv => { + 'Manual' => '수동', + }, + }, + 'CanonFlashMode' => { + PrintConv => { + 'Auto' => '자동', + 'Off' => '꺼짐', + 'On' => '켜짐', + }, + }, + 'Caption-Abstract' => '제목/설명', + 'CaptionWriter' => '캡션 작성자', + 'Categories' => '범주', + 'Category' => '범주', + 'CenterAFArea' => { + Description => '중앙 초점 영역', + PrintConv => { + 'Normal Zone' => '일반 영역', + 'Wide Zone' => '와이드 영역', + }, + }, + 'CenterWeightedAreaSize' => '중앙 중점 영역', + 'ChrominanceNR_TIFF_JPEG' => { + PrintConv => { + 'Off' => '꺼짐', + }, + }, + 'ChrominanceNoiseReduction' => { + PrintConv => { + 'Off' => '꺼짐', + }, + }, + 'City' => '도시', + 'CodedCharacterSet' => '코드된 캐릭터 세트', + 'ColorAberrationControl' => { + PrintConv => { + 'Off' => '꺼짐', + 'On' => '켜짐', + }, + }, + 'ColorBalance' => '컬러 밸런스', + 'ColorBalanceAdj' => { + PrintConv => { + 'Off' => '꺼짐', + 'On' => '켜짐', + }, + }, + 'ColorBooster' => { + PrintConv => { + 'Off' => '꺼짐', + 'On' => '켜짐', + }, + }, + 'ColorEffect' => { + PrintConv => { + 'Off' => '꺼짐', + 'Sepia' => '세피아', + }, + }, + 'ColorFilter' => { + Description => '색 필터', + PrintConv => { + 'Green' => '녹색', + 'Off' => '꺼짐', + 'Red' => '빨강', + 'Yellow' => '노랑', + }, + }, + 'ColorHue' => '색상 형식', + 'ColorMode' => { + Description => '컬러 모드', + PrintConv => { + 'Autumn Leaves' => '단풍', + 'B&W' => '흑백', + 'Clear' => '반투명', + 'Deep' => '진한', + 'Landscape' => '풍경', + 'Light' => '라이트', + 'Neutral' => '뉴트럴', + 'Night View' => '야경', + 'Night View/Portrait' => '야경 인물', + 'Off' => '꺼짐', + 'Portrait' => '인물', + 'Standard' => '표준', + 'Sunset' => '일몰', + 'Vivid' => '생생한', + }, + }, + 'ColorMoireReduction' => { + PrintConv => { + 'Off' => '꺼짐', + 'On' => '켜짐', + }, + }, + 'ColorMoireReductionMode' => { + PrintConv => { + 'Off' => '꺼짐', + }, + }, + 'ColorSpace' => { + Description => '색공간', + PrintConv => { + 'ICC Profile' => 'ICC 프로필', + 'Uncalibrated' => '조정되지 않음', + }, + }, + 'ColorTemperature' => '색 온도', + 'CommandDials' => { + Description => '커맨드 다이얼', + PrintConv => { + 'Reversed (Main Aperture, Sub Shutter)' => '역방향', + 'Standard (Main Shutter, Sub Aperture)' => '기본', + }, + }, + 'CommandDialsApertureSetting' => { + Description => '커맨드 다이얼 수정 조리개 설정', + PrintConv => { + 'Aperture Ring' => '조리개 링', + 'Sub-command Dial' => '서브 커맨드 다이얼', + }, + }, + 'CommandDialsChangeMainSub' => { + Description => '커맨드 다이얼 수정 매인/서브 교체', + PrintConv => { + 'Off' => '꺼짐', + 'On' => '켜짐', + }, + }, + 'CommandDialsMenuAndPlayback' => { + Description => '커맨드 다이얼 수정 매뉴와 재생', + PrintConv => { + 'Off' => '꺼짐', + 'On' => '켜짐', + }, + }, + 'CommandDialsReverseRotation' => { + Description => '커맨드 다이얼 수정 방향 전환', + PrintConv => { + 'No' => '아니오', + 'Yes' => '예', + }, + }, + 'CommanderChannel' => '커맨드모드 채널', + 'CommanderGroupAManualOutput' => '커맨드모드 그룹 A M Comp', + 'CommanderGroupAMode' => { + Description => '커맨드모드 그룹 A 모드', + PrintConv => { + 'Auto Aperture' => '자동 조리개 (AA)', + 'Manual' => '수동', + 'Off' => '꺼짐', + }, + }, + 'CommanderGroupA_TTL-AAComp' => '커맨드모드 그룹 A TTL/AA Comp', + 'CommanderGroupBManualOutput' => '커맨드모드 그룹 B M Comp', + 'CommanderGroupBMode' => { + Description => '커맨드모드 그룹 B 모드', + PrintConv => { + 'Auto Aperture' => '자동 조리개 (AA)', + 'Manual' => '수동', + 'Off' => '꺼짐', + }, + }, + 'CommanderGroupB_TTL-AAComp' => '커맨드모드 그룹 B TTL/AA Comp', + 'CommanderInternalFlash' => { + Description => '커맨드모드 내장 플래시 모드', + PrintConv => { + 'Manual' => '수동', + 'Off' => '꺼짐', + }, + }, + 'CommanderInternalManualOutput' => '커맨드모드 내장플래시 M Comp.', + 'CommanderInternalTTLComp' => '커맨드모드 내장플래시 TTL Comp', + 'Comment' => '코멘트', + 'ComponentsConfiguration' => '각 구성 요소의 의미', + 'CompressedBitsPerPixel' => '이미지 압축 모드', + 'Compression' => { + Description => '압축 설계', + PrintConv => { + 'JPEG' => 'JPEG 압축', + 'JPEG (old-style)' => 'JPEG (예전 스타일)', + 'Kodak DCR Compressed' => 'Kodak DCR 압축', + 'Kodak KDC Compressed' => 'Kodak KDC 압축', + 'Next' => 'NeXT 2-bit 인코딩', + 'Nikon NEF Compressed' => 'Nikon NEF 압축', + 'Pentax PEF Compressed' => 'Pentax PEF 압축', + 'SGILog' => 'SGI 32-bit Log 휘도 인코딩', + 'SGILog24' => 'SGI 24-bit Log 휘도 인코딩', + 'Sony ARW Compressed' => 'Sony ARW 압축', + 'Thunderscan' => 'ThunderScan 4-bit 인코딩', + 'Uncompressed' => '무압축', + }, + }, + 'Contact' => '연락처', + 'Contrast' => { + Description => '대비', + PrintConv => { + 'High' => '강하게', + 'Low' => '약하게', + 'Normal' => '표준', + }, + }, + 'ContrastCurve' => '대비 커브', + 'ConversionLens' => { + PrintConv => { + 'Off' => '꺼짐', + }, + }, + 'Copyright' => '저작권 소유자', + 'CopyrightNotice' => '저작권 공고', + 'Country' => '국명', + 'Country-PrimaryLocationName' => '국가', + 'CreateDate' => '디지털 데이터 생성 일시', + 'CreationDate' => '촬영 날짜', + 'Credit' => '정보', + 'Curves' => { + PrintConv => { + 'Off' => '꺼짐', + 'On' => '켜짐', + }, + }, + 'CustomRendered' => { + Description => '사용자 이미지 처리', + PrintConv => { + 'Custom' => '사용자 처리', + 'Normal' => '표준 처리', + }, + }, + 'D-LightingHQ' => { + PrintConv => { + 'Off' => '꺼짐', + 'On' => '켜짐', + }, + }, + 'D-LightingHS' => { + PrintConv => { + 'Off' => '꺼짐', + 'On' => '켜짐', + }, + }, + 'DataDump' => '데이터 덤프', + 'DateCreated' => '만들어진 날짜', + 'DateDisplayFormat' => { + Description => '날짜 형식', + PrintConv => { + 'D/M/Y' => '일/월/년', + 'M/D/Y' => '월/일/년', + 'Y/M/D' => '년/월/일', + }, + }, + 'DateStampMode' => { + PrintConv => { + 'Off' => '꺼짐', + }, + }, + 'DateTimeOriginal' => '원본 데이터 생성 일시', + 'DaylightSavings' => { + Description => '일광 시간 절약', + PrintConv => { + 'No' => '꺼짐', + 'Yes' => '켜짐', + }, + }, + 'DeletedImageCount' => '삭제된 이미지 카운트', + 'DeviceSettingDescription' => '장비 설정 설명', + 'DigitalZoom' => { + Description => '디지털 줌', + PrintConv => { + 'Off' => '꺼짐', + }, + }, + 'DigitalZoomRatio' => '디지털 줌 비율', + 'Directory' => '파일위치', + 'DirectoryNumber' => '디렉토리 숫자', + 'DistortionCorrection' => { + PrintConv => { + 'Off' => '꺼짐', + 'On' => '켜짐', + }, + }, + 'DistortionCorrection2' => { + PrintConv => { + 'Off' => '꺼짐', + 'On' => '켜짐', + }, + }, + 'DriveMode' => { + Description => '드라이브 모드', + PrintConv => { + 'Multiple Exposure' => '다중 노출', + 'Off' => '꺼짐', + }, + }, + 'DynamicAFArea' => { + Description => '다이내믹 AF 영역', + PrintConv => { + '21 Points' => '21 포인트', + '51 Points' => '51 포인트', + '51 Points (3D-tracking)' => '51포인트 (3D-트래킹)', + '9 Points' => '9 포인트', + }, + }, + 'DynamicRangeExpansion' => { + PrintConv => { + 'Off' => '꺼짐', + 'On' => '켜짐', + }, + }, + 'DynamicRangeOptimizer' => { + Description => 'D-레인지 최적화', + PrintConv => { + 'Advanced Auto' => '고급 자동', + 'Advanced Lv1' => '고급 레벨1', + 'Advanced Lv2' => '고급 레벨2', + 'Advanced Lv3' => '고급 레벨3', + 'Advanced Lv4' => '고급 레벨4', + 'Advanced Lv5' => '고급 레벨5', + 'Auto' => '자동', + 'Off' => '꺼짐', + 'Standard' => '표준', + }, + }, + 'EVStepSize' => { + Description => '노출 설정 간격', + PrintConv => { + '1/2 EV' => '1/2 스텝', + '1/3 EV' => '1/3 스텝', + }, + }, + 'EasyExposureCompensation' => { + Description => '쉬운 노출 보정', + PrintConv => { + 'Off' => '꺼짐', + 'On' => '켜짐', + 'On (auto reset)' => '켜짐 (자동 리셋)', + }, + }, + 'EasyMode' => { + PrintConv => { + 'Manual' => '수동', + }, + }, + 'EdgeNoiseReduction' => { + PrintConv => { + 'Off' => '꺼짐', + 'On' => '켜짐', + }, + }, + 'EffectiveMaxAperture' => '유효 최대 조리개', + 'EnhanceDarkTones' => { + PrintConv => { + 'Off' => '꺼짐', + 'On' => '켜짐', + }, + }, + 'Enhancement' => { + PrintConv => { + 'Green' => '녹색', + 'Off' => '꺼짐', + 'Red' => '빨강', + }, + }, + 'EnvelopeRecordVersion' => '압축 기록 버전', + 'ExifImageHeight' => '이미지 높이', + 'ExifImageWidth' => '이미지 넓이', + 'ExifOffset' => 'Exif IFD Pointer', + 'ExifVersion' => 'Exif 버전', + 'ExitPupilPosition' => '출구공 위치', + 'ExposureBracketValue' => '노출 브라케팅 값', + 'ExposureCompStepSize' => '노출보정/미세조정', + 'ExposureCompensation' => '노출 보정', + 'ExposureControlStepSize' => '노출 조정 EV 스텝', + 'ExposureDelayMode' => { + Description => '노출 대기 모드', + PrintConv => { + 'Off' => '꺼짐', + 'On' => '켜짐', + }, + }, + 'ExposureDifference' => '노출 보정', + 'ExposureIndex' => '노출 인덱스', + 'ExposureMode' => { + Description => '노출 모드', + PrintConv => { + 'Auto' => '자동 노출', + 'Auto bracket' => '오토 브라케스팅', + 'Manual' => '수동 노출', + }, + }, + 'ExposureProgram' => { + Description => '노출 프로그램', + PrintConv => { + 'Action (High speed)' => '스포츠 모드 (빠른 셔터 스피드에 편향됨)', + 'Aperture-priority AE' => '조리개 우선', + 'Bulb' => '벌브', + 'Creative (Slow speed)' => '독창적 프로그램 (피사계심도에 편향됨)', + 'Landscape' => '풍경 모드 (배경의 인포커스가 있는 풍경 사진)', + 'Manual' => '수동', + 'Not Defined' => '정의되지 않음', + 'Portrait' => '인물 모드 (배경의 아웃포커스가 있는 근접 사진)', + 'Program AE' => '보통 프로그램', + 'Shutter speed priority AE' => '셔터 우선', + }, + }, + 'ExposureTime' => '노출 시간', + 'ExtendedWBDetect' => { + PrintConv => { + 'Off' => '꺼짐', + 'On' => '켜짐', + }, + }, + 'ExternalFlash' => { + PrintConv => { + 'Off' => '꺼짐', + 'On' => '켜짐', + }, + }, + 'ExternalFlashFlags' => '외장 플래시 플래그', + 'ExternalFlashMode' => { + PrintConv => { + 'Off' => '꺼짐', + }, + }, + 'FNumber' => 'F 숫자', + 'FaceOrientation' => { + PrintConv => { + 'Horizontal (normal)' => '0° (위쪽/좌측)', + 'Rotate 180' => '180° (아래/우측)', + 'Rotate 270 CW' => '90° 시계방향 (좌측/아래)', + 'Rotate 90 CW' => '90° 반시계방향 (우측/위쪽)', + }, + }, + 'FileFormat' => '형식', + 'FileInfo' => '파일 정보', + 'FileInfoVersion' => '파일 정보 버전', + 'FileModifyDate' => '갱신 일자', + 'FileName' => '파일명', + 'FileNumber' => '파일 숫자', + 'FileNumberMemory' => { + PrintConv => { + 'Off' => '꺼짐', + 'On' => '켜짐', + }, + }, + 'FileNumberSequence' => { + Description => '파일명 연속 번호', + PrintConv => { + 'Off' => '꺼짐', + 'On' => '켜짐', + }, + }, + 'FileSize' => '파일크기', + 'FileSource' => { + Description => '파일 출처', + PrintConv => { + 'Digital Camera' => '디지털 카메라', + 'Film Scanner' => '필름 스캐너', + 'Reflection Print Scanner' => '반사 프린트 스캐너', + }, + }, + 'FileType' => '파일형식', + 'Filename' => '파일명', + 'FilmType' => '필름 형식', + 'Filter' => { + PrintConv => { + 'Off' => '꺼짐', + }, + }, + 'FilterEffect' => { + Description => '필터 효과', + PrintConv => { + 'Green' => '녹색', + 'Off' => '꺼짐', + 'Orange' => '주황', + 'Red' => '빨강', + 'Yellow' => '노랑', + 'n/a' => '설정 안됨', + }, + }, + 'FilterEffectMonochrome' => { + PrintConv => { + 'Green' => '녹색', + 'Orange' => '주황', + 'Red' => '빨강', + 'Yellow' => '노랑', + }, + }, + 'FinderDisplayDuringExposure' => { + PrintConv => { + 'Off' => '꺼짐', + 'On' => '켜짐', + }, + }, + 'FineTuneOptCenterWeighted' => '최적 노출 조정 중앙 중점', + 'FineTuneOptMatrixMetering' => '최적 노출 조정 평가 측광', + 'FineTuneOptSpotMetering' => '최적 노출 조정 스팟', + 'Flash' => { + Description => '플래시', + PrintConv => { + 'Auto, Did not fire' => '플래시 발광 안됨, 자동모드', + 'Auto, Did not fire, Red-eye reduction' => '자동, 발광안됨, 적목감소', + 'Auto, Fired' => '플래시 발광, 자동모드', + 'Auto, Fired, Red-eye reduction' => '플래시 발광, 자동모드, 적목감소모드', + 'Auto, Fired, Red-eye reduction, Return detected' => '플래시 발광, 자동모드, 복귀광 감지됨, 적목감소모드', + 'Auto, Fired, Red-eye reduction, Return not detected' => '플래시 발광, 자동모드, 복귀광 감지안됨, 적목감소모드', + 'Auto, Fired, Return detected' => '플래시 발광, 자동모드, 복귀광 감지됨', + 'Auto, Fired, Return not detected' => '플래시 발광, 자동모드, 복귀광 감지 안됨', + 'Did not fire' => '플래시가 점등하지 않았습니다', + 'Fired' => '플래시 발광', + 'Fired, Red-eye reduction' => '플래시 발광, 적목감소모드', + 'Fired, Red-eye reduction, Return detected' => '플래시 발광, 적목감소모드, 복귀광 감지됨', + 'Fired, Red-eye reduction, Return not detected' => '플래시 발광, 적목감소모드, 복귀광 감지 안됨', + 'Fired, Return detected' => '스트로브 복귀광 감지됨', + 'Fired, Return not detected' => '스트로브 복귀광 감지 안됨', + 'No Flash' => '플래시 발광 안됨', + 'No flash function' => '플래시 작동 없음', + 'Off, Did not fire' => '플래시 발광 안됨, 강제발광모드', + 'Off, Did not fire, Return not detected' => '꺼짐, 발광 안됨, 복귀광 감지 안됨', + 'Off, No flash function' => '꺼짐, 플래시 작동 없음', + 'Off, Red-eye reduction' => '꺼짐, 적목감소', + 'On, Did not fire' => '켜짐, 플래시 발광 안됨', + 'On, Fired' => '플래시 발광, 강제발광모드', + 'On, Red-eye reduction' => '플래시 발광, 강제발광모드, 적목감소모드', + 'On, Red-eye reduction, Return detected' => '플래시 발광, 강제발광모드, 적목감소모드, 복귀광 감지됨', + 'On, Red-eye reduction, Return not detected' => '플래시 발광, 강제발광모드, 적목감소모드, 복귀광 감지 안됨', + 'On, Return detected' => '플래시 발광, 강제발광모드, 복귀광 감지됨', + 'On, Return not detected' => '플래시 발광, 강제발광모드, 복귀광 감지 안됨', + }, + }, + 'FlashCommanderMode' => { + Description => '커맨더 모드', + PrintConv => { + 'Off' => '꺼짐', + 'On' => '켜짐', + }, + }, + 'FlashCompensation' => '플래시 보정', + 'FlashControlMode' => { + Description => '플래시 컨트롤 모드', + PrintConv => { + 'Auto Aperture' => '자동 조리개 (AA)', + 'Manual' => '수동', + 'Off' => '꺼짐', + 'Repeating Flash' => '리피팅 플래시', + }, + }, + 'FlashEnergy' => '플래시 에너지', + 'FlashExposureBracketValue' => '플래시 노출 브라케팅 값', + 'FlashExposureComp' => '플래시 노출 보정', + 'FlashExposureLock' => { + PrintConv => { + 'Off' => '꺼짐', + 'On' => '켜짐', + }, + }, + 'FlashFired' => '플래시 발광됨', + 'FlashFocalLength' => '플래시 초점 길이', + 'FlashGroupACompensation' => '그룹 A 플래시 보정', + 'FlashGroupAControlMode' => { + Description => '그룹 A 플래시 모드', + PrintConv => { + 'Auto Aperture' => '자동 조리개 (AA)', + 'Manual' => '수동', + 'Off' => '꺼짐', + 'Repeating Flash' => '리피팅 플래시', + }, + }, + 'FlashGroupAOutput' => '그룹 A 플래시 출력', + 'FlashGroupBCompensation' => '그룹 B 플래시 보정', + 'FlashGroupBControlMode' => { + Description => '그룹 B 플래시 모드', + PrintConv => { + 'Auto Aperture' => '자동 조리개 (AA)', + 'Manual' => '수동', + 'Off' => '꺼짐', + 'Repeating Flash' => '리피팅 플래시', + }, + }, + 'FlashGroupBOutput' => '그룹 B 플래시 출력', + 'FlashGroupCCompensation' => '그룹 C 플래시 보정', + 'FlashGroupCControlMode' => { + Description => '그룹 C 플래시 컨트롤 모드', + PrintConv => { + 'Auto Aperture' => '자동 조리개 (AA)', + 'Manual' => '수동', + 'Off' => '꺼짐', + 'Repeating Flash' => '리피팅 플래시', + }, + }, + 'FlashGroupCOutput' => '그룹 C 플래시 출력', + 'FlashInfoVersion' => '플래시 정보 버전', + 'FlashLevel' => '플래시 보정', + 'FlashMode' => { + Description => '플래시 모드', + PrintConv => { + 'Did Not Fire' => '발광 안됨', + 'Fired, Commander Mode' => '발광됨, 커맨더 모드', + 'Fired, External' => '발광됨, 외장', + 'Fired, Manual' => '발광됨, 수동', + 'Fired, TTL Mode' => '발광됨, TTL 모드', + }, + }, + 'FlashModel' => '플래시 모델', + 'FlashOptions' => { + PrintConv => { + 'Auto' => '자동', + }, + }, + 'FlashOptions2' => { + PrintConv => { + 'Auto' => '자동', + }, + }, + 'FlashOutput' => '플래시 출력', + 'FlashSetting' => '플래시 설정', + 'FlashShutterSpeed' => '플래시 셔터 스피드', + 'FlashStatus' => { + PrintConv => { + 'Off' => '꺼짐', + }, + }, + 'FlashSyncSpeed' => '플래시 동조 속도', + 'FlashSyncSpeedAv' => { + PrintConv => { + 'Auto' => '자동', + }, + }, + 'FlashType' => '플래시 형식', + 'FlashWarning' => { + Description => '플래시 경고', + PrintConv => { + 'Off' => '꺼짐', + 'On' => '켜짐', + }, + }, + 'FlashpixVersion' => '지원되는 Flashpix 버전', + 'FocalLength' => '초점 길이', + 'FocalLength35efl' => '초점거리 (35mm 변환)', + 'FocalLengthIn35mmFormat' => '35 mm 필름 환산 초점길이', + 'FocalPlaneResolutionUnit' => { + Description => '초점면 해상도 단위', + PrintConv => { + 'None' => '없음', + 'inches' => '인치', + 'um' => 'µm (마이크로미터)', + }, + }, + 'FocalPlaneXResolution' => '수평 해상도 초점면', + 'FocalPlaneYResolution' => '수직 해상도 초점면', + 'Focus' => { + Description => '포커스', + PrintConv => { + 'Manual' => '수동', + }, + }, + 'FocusArea' => 'AF 포인트 순환', + 'FocusAreaSelection' => { + Description => 'AF 포인트 순환', + PrintConv => { + 'No Wrap' => '꺼짐', + 'Wrap' => '켜짐', + }, + }, + 'FocusContinuous' => { + PrintConv => { + 'Manual' => '수동', + }, + }, + 'FocusDistance' => '초점 거리', + 'FocusMode' => { + Description => '초점모드', + PrintConv => { + 'Manual' => '수동', + }, + }, + 'FocusMode2' => { + PrintConv => { + 'Manual' => '수동', + }, + }, + 'FocusModeSetting' => { + Description => '초점 모드', + PrintConv => { + 'AF-A' => '자동 AF 서보', + 'AF-C' => '컨티뉴어스 AF 서보', + 'AF-S' => '싱글 AF 서보', + 'Manual' => '수동', + }, + }, + 'FocusPointWrap' => { + Description => '초점 포인트 순환', + PrintConv => { + 'No Wrap' => '순환 안함', + 'Wrap' => '순환', + }, + }, + 'FocusPosition' => '초점 위치', + 'FocusRange' => { + PrintConv => { + 'Auto' => '자동', + 'Manual' => '수동', + }, + }, + 'FocusTrackingLockOn' => { + Description => '초점 트래킹 Lock-On', + PrintConv => { + 'Long' => '길게', + 'Normal' => '표준', + 'Off' => '꺼짐', + 'Short' => '짧게', + }, + }, + 'FrameRate' => '프레임 비율', + 'FrameSize' => '프레임 크기', + 'FujiFlashMode' => { + PrintConv => { + 'Auto' => '자동', + }, + }, + 'FunctionButton' => { + Description => '펑션 버튼', + PrintConv => { + 'AF-area Mode' => 'AF 영역 모드 설정', + 'Center AF Area' => '중앙 초점 영역', + 'Center-weighted' => '중앙부 중점 측광', + 'FV Lock' => 'FV 고정', + 'Flash Off' => '플래시 OFF', + 'Framing Grid' => '격자선 표시', + 'ISO Display' => 'ISO 표시', + 'Matrix Metering' => '멀티 패턴 측광', + 'Spot Metering' => '스팟 측광', + }, + }, + 'GPSAltitude' => '고도', + 'GPSAltitudeRef' => { + Description => '고도 참조', + PrintConv => { + 'Above Sea Level' => '해면', + 'Below Sea Level' => '해면 참조(음수 값)', + }, + }, + 'GPSAreaInformation' => 'GPS 영역 이름', + 'GPSDOP' => '측정 정밀도', + 'GPSDateStamp' => 'GPS 날짜', + 'GPSDestBearing' => '목적지의 방위', + 'GPSDestBearingRef' => '목적지 방위의 기준', + 'GPSDestDistance' => '목적지까지의 거리', + 'GPSDestDistanceRef' => '목적지까지의 거리 단위', + 'GPSDestLatitude' => '목적지의 위도', + 'GPSDestLatitudeRef' => '목적지 위도의 기준', + 'GPSDestLongitude' => '목적지의 경도', + 'GPSDestLongitudeRef' => '목적지 경도의 기준', + 'GPSDifferential' => { + Description => 'GPS 편차 보정', + PrintConv => { + 'Differential Corrected' => '편차 보정 적용', + 'No Correction' => '편차 보정 없이 측정', + }, + }, + 'GPSImgDirection' => '이미지 방향', + 'GPSImgDirectionRef' => '이미지 방향의 기준', + 'GPSInfo' => 'GPS Info IFD Pointer', + 'GPSLatitude' => '위도', + 'GPSLatitudeRef' => { + Description => '북위 또는 남위', + PrintConv => { + 'North' => '북위', + 'South' => '남위', + }, + }, + 'GPSLongitude' => '경도', + 'GPSLongitudeRef' => { + Description => '동경 또는 서경', + PrintConv => { + 'East' => '동경', + 'West' => '서경', + }, + }, + 'GPSMapDatum' => '사용된 측지 데이터', + 'GPSMeasureMode' => { + Description => 'GPS 측정 모드', + PrintConv => { + '2-Dimensional Measurement' => '2-차원 측량(평면 측량)', + '3-Dimensional Measurement' => '3차원 측정', + }, + }, + 'GPSProcessingMethod' => 'GPS 처리 방식 이름', + 'GPSSatellites' => '측정에 사용된 GPS 위성', + 'GPSSpeed' => 'GPS 수신기 속도', + 'GPSSpeedRef' => { + Description => '속도 단위', + PrintConv => { + 'km/h' => '시간당 킬로미터', + 'knots' => '노트', + 'mph' => '시간당 마일', + }, + }, + 'GPSStatus' => { + Description => 'GPS 수신기 상태', + PrintConv => { + 'Measurement Active' => '진행 중인 측정', + 'Measurement Void' => '측정 상호 운용성', + }, + }, + 'GPSTimeStamp' => 'GPS 시간(원자 시계)', + 'GPSTrack' => '이동 방향', + 'GPSTrackRef' => { + Description => '이동 방향의 기준', + PrintConv => { + 'Magnetic North' => '자기 방향', + 'True North' => '실제 방향', + }, + }, + 'GPSVersionID' => 'GPS 태그 버전', + 'GainControl' => { + Description => '이득 제어', + PrintConv => { + 'High gain down' => '높은 이득 감소', + 'High gain up' => '높은 이득 증가', + 'Low gain down' => '적은 이득 감소', + 'Low gain up' => '적은 이득 증가', + 'None' => '없음', + }, + }, + 'Gamma' => '감마', + 'Gradation' => '계조', + 'GridDisplay' => { + Description => '격자 표시', + PrintConv => { + 'Off' => '꺼짐', + 'On' => '켜짐', + }, + }, + 'HDR' => { + Description => '자동 HDR', + PrintConv => { + 'Off' => '없음', + }, + }, + 'Headline' => '헤드라인', + 'HighISONoiseReduction' => { + Description => '고ISO에서 노이즈제거', + PrintConv => { + 'Auto' => '자동', + 'High' => '강함', + 'Low' => '약함', + 'Minimal' => '최소', + 'Normal' => '표준', + 'Off' => '꺼짐', + 'On' => '켜짐', + }, + }, + 'HighlightTonePriority' => { + PrintConv => { + 'Off' => '꺼짐', + 'On' => '켜짐', + }, + }, + 'Hue' => '색상', + 'HueAdjustment' => '색조', + 'ISO' => 'ISO 속도', + 'ISOAuto' => '자동 ISO', + 'ISODisplay' => 'ISO 표시', + 'ISOExpansion' => { + Description => 'ISO 확장', + PrintConv => { + 'Off' => '꺼짐', + }, + }, + 'ISOExpansion2' => { + Description => 'ISO 확장 (2)', + PrintConv => { + 'Off' => '꺼짐', + }, + }, + 'ISOInfo' => 'ISO 정보', + 'ISOSelection' => 'ISO 선택', + 'ISOSetting' => { + Description => 'ISO 설정', + PrintConv => { + 'Auto' => '자동', + 'Manual' => '수동', + }, + }, + 'ISOStepSize' => 'ISO 감도 스텝 수치', + 'Illumination' => { + Description => '조명', + PrintConv => { + 'Off' => '꺼짐', + 'On' => '켜짐', + }, + }, + 'ImageAdjustment' => '이미지 조정', + 'ImageAuthentication' => { + Description => '이미지 인증', + PrintConv => { + 'Off' => '꺼짐', + 'On' => '켜짐', + }, + }, + 'ImageBoundary' => '이미지 경계', + 'ImageCount' => '이미지 카운트', + 'ImageDataSize' => '이미지 데이터 크기', + 'ImageDustOff' => { + PrintConv => { + 'Off' => '꺼짐', + 'On' => '켜짐', + }, + }, + 'ImageHeight' => '이미지 높이', + 'ImageHistory' => '이미지 이력', + 'ImageNumber' => '이미지 숫자', + 'ImageOptimization' => '이미지 최적화', + 'ImageProcessing' => '이미지 처리', + 'ImageQuality' => '이미지 화질', + 'ImageReview' => { + Description => '이미지 미리보기', + PrintConv => { + 'Off' => '꺼짐', + 'On' => '켜짐', + }, + }, + 'ImageReviewTime' => '이미지 재생 시간', + 'ImageSize' => '이미지 크기', + 'ImageStabilization' => { + Description => '손떨림 보정', + PrintConv => { + 'Off' => '꺼짐', + 'On' => '켜짐', + }, + }, + 'ImageUniqueID' => '고유 이미지 ID', + 'ImageWidth' => '이미지 넓이', + 'Index' => '색인', + 'InitialZoomSetting' => { + Description => '이니셜 줌 설정', + PrintConv => { + 'High Magnification' => '큰 확대', + 'Low Magnification' => '작은 확대', + 'Medium Magnification' => '중간 확대', + }, + }, + 'Instructions' => '안내', + 'IntensityStereo' => { + PrintConv => { + 'Off' => '꺼짐', + 'On' => '켜짐', + }, + }, + 'InternalFlash' => { + Description => '내장플래시 컨트롤', + PrintConv => { + 'Commander Mode' => '커맨더 모드', + 'Manual' => '수동', + 'Off' => '꺼짐', + 'On' => '켜짐', + 'Repeating Flash' => '리피팅 플래시', + }, + }, + 'InternalFlashMode' => { + PrintConv => { + 'On' => '켜짐', + }, + }, + 'InteropIndex' => '상호운용성 증명', + 'InteropOffset' => '상호 운용성 태그', + 'InteropVersion' => '상호 운용성 버전', + 'JPEGQuality' => { + Description => '화질', + PrintConv => { + 'Extra Fine' => '엑스트라 파인', + 'Fine' => '파인', + 'Standard' => '표준화질', + }, + }, + 'Keyword' => '키워드', + 'Keywords' => '키워드', + 'LCDIllumination' => { + Description => 'LCD 조명', + PrintConv => { + 'Off' => '꺼짐', + 'On' => '켜짐', + }, + }, + 'LCDIlluminationDuringBulb' => { + PrintConv => { + 'Off' => '꺼짐', + 'On' => '켜짐', + }, + }, + 'LCHEditor' => { + PrintConv => { + 'Off' => '꺼짐', + 'On' => '켜짐', + }, + }, + 'Lens' => '렌즈', + 'LensDataVersion' => '렌즈 데이터 버전', + 'LensFStops' => '렌즈 F-숫자', + 'LensID' => '사용된 렌즈', + 'LensIDNumber' => '렌즈 ID 숫자', + 'LensInfo' => '렌즈 정보', + 'LensType' => '렌즈 형식', + 'LightSource' => { + Description => '광원 종류', + PrintConv => { + 'Cloudy' => '흐린 날씨', + 'Cool White Fluorescent' => '냉백색 형광등 (W 3800 - 4500K)', + 'Day White Fluorescent' => '주백색 형광등 (N 4600 - 5500K)', + 'Daylight' => '주광', + 'Daylight Fluorescent' => '주광색 형광등 (D 5700 - 7100K)', + 'Fine Weather' => '맑은 날씨', + 'Flash' => '플래시', + 'Fluorescent' => '형광등', + 'ISO Studio Tungsten' => 'ISO 스튜디오 텅스텐', + 'Other' => '기타 광원', + 'Shade' => '그늘', + 'Standard Light A' => '표준 광원 A', + 'Standard Light B' => '표준 광원 B', + 'Standard Light C' => '표준 광원 C', + 'Tungsten (Incandescent)' => '텅스텐 (백열등)', + 'Unknown' => '알 수 없음', + 'Warm White Fluorescent' => '따뜻한 흰색 형광 (L 2600 - 3250K)', + 'White Fluorescent' => '백색 형광등 (WW 3250 - 3800K)', + }, + }, + 'Lightness' => '명도', + 'LinearizationTable' => '선형도표', + 'LiveViewShooting' => { + PrintConv => { + 'Off' => '꺼짐', + 'On' => '켜짐', + }, + }, + 'Location' => '위치', + 'LongExposureNoiseReduction' => { + Description => '장시간 노출 NR', + PrintConv => { + 'Auto' => '자동', + 'Off' => '없음', + 'On' => '있음', + }, + }, + 'LuminanceNoiseReduction' => { + PrintConv => { + 'Off' => '꺼짐', + }, + }, + 'MB-D10Batteries' => 'MB-D10 배터리 형식', + 'MB-D10BatteryType' => 'MB-D10 배터리 형식', + 'MB-D80Batteries' => { + Description => 'MB-D80 배터리', + PrintConv => { + 'FR6 (AA Lithium)' => 'FR6 (AA 리튬)', + 'LR6 (AA Alkaline)' => 'LR6 (AA 알카라인)', + }, + }, + 'MCUVersion' => 'MCU 버전', + 'MSStereo' => { + PrintConv => { + 'Off' => '꺼짐', + 'On' => '켜짐', + }, + }, + 'Macro' => { + PrintConv => { + 'Manual' => '수동', + }, + }, + 'MacroMode' => { + PrintConv => { + 'Off' => '꺼짐', + 'On' => '켜짐', + }, + }, + 'MainDialExposureComp' => { + Description => '노출 보정', + PrintConv => { + 'Off' => '꺼짐', + 'On' => '켜짐', + }, + }, + 'Make' => '메이커', + 'MakerNote' => '제조사 노트', + 'MakerNoteVersion' => '제조사노트 버전', + 'MakerNotes' => '제조업체 정보', + 'ManualFlashOutput' => '내장 플래시 수동 출력', + 'ManualFocusDistance' => '수동 초점 거리', + 'MaxAperture' => '최대 렌즈 조리개', + 'MaxApertureAtMaxFocal' => '최대 초점길이에서 최대 조리개', + 'MaxApertureAtMinFocal' => '최소 초점길이에서 최대 조리개', + 'MaxApertureValue' => '최대 렌즈 조리개', + 'MaxContinuousRelease' => '최대 연사 릴리즈', + 'MaxFocalLength' => '최대 초점길이', + 'Metering' => { + Description => '측광', + PrintConv => { + 'Center-weighted' => '중앙부 중점', + 'Matrix' => '멀티패턴', + 'Spot' => '스팟', + }, + }, + 'MeteringMode' => { + Description => '측광 모드', + PrintConv => { + 'Average' => '평균', + 'Center-weighted average' => '중앙중점 평균', + 'Multi-segment' => '멀티 패턴', + 'Multi-spot' => '멀티 스팟', + 'Other' => '기타', + 'Partial' => '부분', + 'Spot' => '스팟', + 'Unknown' => '알 수 없음', + }, + }, + 'MeteringTime' => { + Description => '자동 측광 꺼짐 시간', + PrintConv => { + 'No Limit' => '무제한', + }, + }, + 'MinFocalLength' => '최소 초점길이', + 'Model' => '카메라 모델', + 'ModelingFlash' => { + Description => '최대', + PrintConv => { + 'Off' => '꺼짐', + 'On' => '켜짐', + }, + }, + 'ModifiedSaturation' => { + PrintConv => { + 'Off' => '꺼짐', + }, + }, + 'ModifiedToneCurve' => { + PrintConv => { + 'Manual' => '수동', + }, + }, + 'ModifiedWhiteBalance' => { + PrintConv => { + 'Auto' => '자동', + }, + }, + 'ModifyDate' => '파일 변경 날짜 및 시간', + 'MoireFilter' => { + PrintConv => { + 'Off' => '꺼짐', + 'On' => '켜짐', + }, + }, + 'MonitorOffTime' => '모니터 꺼짐 시간', + 'MonochromeFilterEffect' => { + PrintConv => { + 'Green' => '녹색', + 'Orange' => '주황', + 'Red' => '빨강', + 'Yellow' => '노랑', + }, + }, + 'MonochromeToningEffect' => { + PrintConv => { + 'Green' => '녹색', + }, + }, + 'MultiExposure' => '다중 노출 데이터', + 'MultiExposureAutoGain' => { + Description => '다중 노출 자동 게인', + PrintConv => { + 'Off' => '꺼짐', + 'On' => '켜짐', + }, + }, + 'MultiExposureMode' => { + Description => '다중노출 모드', + PrintConv => { + 'Image Overlay' => '이미지 오버레이', + 'Multiple Exposure' => '다중 노출', + 'Off' => '꺼짐', + }, + }, + 'MultiExposureShots' => '다중 노출 촬영', + 'MultiExposureVersion' => '다중 노출 데이터 버전', + 'MultiFrameNoiseReduction' => { + Description => '다중 프레임 노이즈 감쇄', + PrintConv => { + 'Off' => '없음', + 'On' => '있음', + }, + }, + 'MultiSelector' => { + Description => '멀티셀렉터', + PrintConv => { + 'Do Nothing' => '아무것도 안함', + 'Reset Meter-off Delay' => '노출계 꺼짐 시간 초기화', + }, + }, + 'MultiSelectorPlaybackMode' => { + Description => '멀티셀렉터 재생 모드', + PrintConv => { + 'Choose Folder' => '폴더 선택', + 'Thumbnail On/Off' => '섬네일 on/off', + 'View Histograms' => '히스토그램 표시', + 'Zoom On/Off' => '줌 on/off', + }, + }, + 'MultiSelectorShootMode' => { + Description => '멀티셀렉터 촬영 모드', + PrintConv => { + 'Highlight Active Focus Point' => '활성 초점 포인트 하이라이트', + 'Not Used' => '사용 안됨', + 'Select Center Focus Point' => '중앙 초점 포인트 선택', + }, + }, + 'MultipleExposureSet' => { + PrintConv => { + 'Off' => '꺼짐', + 'On' => '켜짐', + }, + }, + 'Mute' => { + PrintConv => { + 'Off' => '꺼짐', + 'On' => '켜짐', + }, + }, + 'MyColorMode' => { + PrintConv => { + 'Off' => '꺼짐', + }, + }, + 'NDFilter' => { + PrintConv => { + 'Off' => '꺼짐', + 'On' => '켜짐', + }, + }, + 'NEFCompression' => { + Description => 'RAW 압축', + PrintConv => { + 'Lossless' => '손실 없음', + 'Lossy (type 1)' => '손실됨 (타입 1)', + 'Lossy (type 2)' => '손실됨 (타입 2)', + 'Uncompressed' => '압축되지 않음', + }, + }, + 'NEFLinearizationTable' => '선형도표', + 'NikonCaptureData' => 'Nikon Capture 데이터', + 'NikonCaptureVersion' => 'Nikon Capture 버전', + 'NikonImageSize' => { + Description => '이미지 크기', + PrintConv => { + 'Large (10.0 M)' => '큰 (10.0M)', + 'Medium (5.6 M)' => '중간 (5.6M)', + 'Small (2.5 M)' => '작은 (2.5M)', + }, + }, + 'NoMemoryCard' => { + Description => '메모리카드 없을 경우', + PrintConv => { + 'Enable Release' => '릴리즈 허용', + 'Release Locked' => '릴리즈 잠금', + }, + }, + 'Noise' => '노이즈', + 'NoiseFilter' => { + PrintConv => { + 'Off' => '꺼짐', + }, + }, + 'NoiseReduction' => { + Description => '노이즈 제거', + PrintConv => { + 'Auto' => '자동', + 'Off' => '꺼짐', + 'On' => '켜짐', + }, + }, + 'OneTouchWB' => { + PrintConv => { + 'Off' => '꺼짐', + }, + }, + 'Opto-ElectricConvFactor' => '광전자 변환 계수', + 'Orientation' => { + Description => '이미지 위치', + PrintConv => { + 'Horizontal (normal)' => '0° (위쪽/좌측)', + 'Mirror horizontal' => '0° (위쪽/우측)', + 'Mirror horizontal and rotate 270 CW' => '90° 시계방향 (좌측/위쪽)', + 'Mirror horizontal and rotate 90 CW' => '90° 반시계방향 (우측/아래)', + 'Mirror vertical' => '180° (아래/좌측)', + 'Rotate 180' => '180° (아래/우측)', + 'Rotate 270 CW' => '90° 시계방향 (좌측/아래)', + 'Rotate 90 CW' => '90° 반시계방향 (우측/위쪽)', + }, + }, + 'PhaseDetectAF' => { + Description => '오토포커스', + PrintConv => { + 'Off' => '비활성', + 'On (51-point)' => '활성', + }, + }, + 'PhotoEffect' => { + PrintConv => { + 'Off' => '꺼짐', + }, + }, + 'PhotoEffects' => { + PrintConv => { + 'Off' => '꺼짐', + 'On' => '켜짐', + }, + }, + 'PhotoInfoPlayback' => { + Description => '사진 정보/재생', + PrintConv => { + 'Info Left-right, Playback Up-down' => '정보 <> / 재생', + 'Info Up-down, Playback Left-right' => '정보 / 재생 <>', + }, + }, + 'PhotometricInterpretation' => { + Description => '픽셀 형식', + PrintConv => { + 'BlackIsZero' => '블랙은 제로임', + 'RGB Palette' => '팔렛트 컬러', + 'Transparency Mask' => '투명 마스크', + 'WhiteIsZero' => '화이트는 제로임', + }, + }, + 'PictureControl' => { + Description => '픽쳐컨트롤', + PrintConv => { + 'Off' => '꺼짐', + 'On' => '켜짐', + }, + }, + 'PictureControlActive' => { + PrintConv => { + 'Off' => '꺼짐', + 'On' => '켜짐', + }, + }, + 'PictureControlAdjust' => { + Description => '픽쳐컨트롤 조정', + PrintConv => { + 'Default Settings' => '기본 설정', + 'Full Control' => '전체 제어', + 'Quick Adjust' => '빠른 조정', + }, + }, + 'PictureControlBase' => '픽쳐컨트롤 기초', + 'PictureControlName' => '픽쳐컨트롤 이름', + 'PictureControlQuickAdjust' => '픽쳐컨트롤 빠른 조정', + 'PictureControlVersion' => '픽쳐컨트롤 버전', + 'PictureMode' => { + PrintConv => { + 'Auto' => '자동', + 'Manual' => '수동', + }, + }, + 'PictureMode2' => { + PrintConv => { + 'Manual' => '수동', + }, + }, + 'PictureModeBWFilter' => { + PrintConv => { + 'Green' => '녹색', + 'Orange' => '주황', + 'Red' => '빨강', + 'Yellow' => '노랑', + }, + }, + 'PictureModeTone' => { + PrintConv => { + 'Green' => '녹색', + }, + }, + 'PlanarConfiguration' => { + Description => '이미지 데이터 정렬', + PrintConv => { + 'Chunky' => '청키 형식', + 'Planar' => '평면 형식', + }, + }, + 'Preview' => 'IFD 포인터 미리보기', + 'PreviewIFD' => 'IFD 포인터 미리보기', + 'PrimaryAFPoint' => { + PrintConv => { + 'Bottom' => '하단', + 'C6 (Center)' => 'C6 (중앙)', + 'Center' => '중앙', + 'Far Left' => '맨 좌측', + 'Far Right' => '맨 우측', + 'Lower-left' => '좌하단', + 'Lower-right' => '우하단', + 'Mid-left' => '왼쪽', + 'Mid-right' => '오른쪽', + 'Top' => '상단', + 'Upper-left' => '좌상단', + 'Upper-right' => '우상단', + }, + }, + 'PrimaryChromaticities' => '기본 색도', + 'ProgramShift' => '프로그램 쉬프트', + 'Province-State' => '도', + 'Quality' => { + Description => '화질', + PrintConv => { + 'Compressed RAW' => 'cRAW', + 'Compressed RAW + JPEG' => 'cRAW+JPEG', + 'Extra Fine' => '엑스트라 파인', + 'Fine' => '파인', + 'Low' => '저화질', + 'Normal' => '표준화질', + 'RAW + JPEG' => 'RAW+JPEG', + 'Standard' => '표준', + }, + }, + 'QuickAdjust' => '빠른 조정', + 'RawDevAutoGradation' => { + PrintConv => { + 'Off' => '꺼짐', + 'On' => '켜짐', + }, + }, + 'RawDevPMPictureTone' => { + PrintConv => { + 'Green' => '녹색', + }, + }, + 'RawDevPM_BWFilter' => { + PrintConv => { + 'Green' => '녹색', + 'Orange' => '주황', + 'Red' => '빨강', + 'Yellow' => '노랑', + }, + }, + 'RawImageCenter' => 'RAW 이미지 중앙', + 'RecordMode' => { + Description => '이미지 화질 모드', + PrintConv => { + 'Manual' => '수동', + }, + }, + 'RecordingMode' => { + PrintConv => { + 'Auto' => '자동', + 'Manual' => '수동', + }, + }, + 'RedEyeCorrection' => { + PrintConv => { + 'Off' => '꺼짐', + }, + }, + 'RedEyeReduction' => { + PrintConv => { + 'Off' => '꺼짐', + 'On' => '켜짐', + }, + }, + 'ReferenceBlackWhite' => '흑백 참조 값의 쌍', + 'RelatedImageFileFormat' => '관련 이미지 파일 형식', + 'RelatedImageHeight' => '관련 이미지 길이', + 'RelatedImageWidth' => '관련 이미지 너비', + 'RelatedSoundFile' => '연관된 오디오 파일', + 'ReleaseButtonToUseDial' => { + Description => '다이얼로 릴리즈 버튼 사용', + PrintConv => { + 'No' => '아니오', + 'Yes' => '예', + }, + }, + 'RemoteOnDuration' => '리모컨 지속 시간', + 'RepeatingFlashCount' => '리피팅 플래시 시간', + 'RepeatingFlashOutput' => '리피팅 플래시 출력', + 'RepeatingFlashRate' => '리피팅 플래시 간격', + 'ResolutionUnit' => { + Description => 'X 와 Y 해상도 단위', + PrintConv => { + 'None' => '없음', + 'cm' => '센티미터', + 'inches' => '인치', + }, + }, + 'RetouchHistory' => { + Description => '리터치 이력', + PrintConv => { + 'B & W' => '흑백', + 'Color Custom' => '커스텀 컬러', + 'Cyanotype' => '청사진', + 'Image Overlay' => '이미지 오버레이', + 'None' => '없음', + 'Sepia' => '세피아', + 'Sky Light' => '스카이 라이트', + 'Small Picture' => '스몰', + 'Trim' => '트리밍', + 'Warm Tone' => '따뜻한 톤', + }, + }, + 'ReverseIndicators' => '인디케이터 전환', + 'Rotation' => { + Description => '카메라 회전 방향', + PrintConv => { + 'Horizontal' => '0° (수평)', + 'Rotated 180' => '180° (상하반전)', + 'Rotated 270 CW' => '90° 좌회전', + 'Rotated 90 CW' => '90° 우회전', + }, + }, + 'RowsPerStrip' => '스트립 당 행의 수', + 'SamplesPerPixel' => '구성 요소 수', + 'Saturation' => { + Description => '채도', + PrintConv => { + 'High' => '고채도', + 'Low' => '저채도', + 'Normal' => '표준', + }, + }, + 'ScanImageEnhancer' => { + PrintConv => { + 'Off' => '꺼짐', + 'On' => '켜짐', + }, + }, + 'SceneAssist' => '보조 센서', + 'SceneCaptureType' => { + Description => '장면 기록 형식', + PrintConv => { + 'Landscape' => '풍경', + 'Night' => '야경', + 'Portrait' => '인물', + 'Standard' => '표준', + }, + }, + 'SceneMode' => { + Description => '장면 모드', + PrintConv => { + '3D Sweep Panorama' => '3D', + 'Anti Motion Blur' => '인물 흔들림 방지', + 'Auto' => '자동', + 'Cont. Priority AE' => '연속 촬영 우선 AE', + 'Handheld Night Shot' => '손으로 야간 촬영', + 'Landscape' => '풍경', + 'Macro' => '매크로', + 'Manual' => '수동', + 'Night Portrait' => '야경 인물', + 'Night Scene' => '야경', + 'Night View/Portrait' => '야경/인물', + 'Off' => '꺼짐', + 'Portrait' => '인물', + 'Sports' => '스포츠 액션', + 'Sunset' => '석양촬영', + 'Sweep Panorama' => '스위프 파노라마', + }, + }, + 'SceneModeUsed' => { + PrintConv => { + 'Manual' => '수동', + }, + }, + 'SceneType' => { + Description => '장면 형식', + PrintConv => { + 'Directly photographed' => '직접 촬영된 이미지', + }, + }, + 'SecurityClassification' => { + Description => '보안 분류', + PrintConv => { + 'Confidential' => '기밀', + 'Restricted' => '제한', + 'Secret' => '비밀', + 'Top Secret' => '1급비밀', + 'Unclassified' => '분류안됨', + }, + }, + 'SelfTimerMode' => '셀프 타이머 모드', + 'SelfTimerTime' => '셀프타이머', + 'SensingMethod' => { + Description => '검출 방식', + PrintConv => { + 'Color sequential area' => '색상 순차 영역 센서', + 'Color sequential linear' => '색상 순차 선형 센서', + 'Monochrome area' => '모노크롬 영역 센서', + 'Monochrome linear' => '모노크롬 선형 센서', + 'Not defined' => '정의되지 않음', + 'One-chip color area' => 'One-chip 색상 영역 센서', + 'Three-chip color area' => 'Three-chip 색상 영역 센서', + 'Trilinear' => 'Trilinear 센서', + 'Two-chip color area' => 'Two-chip 색상 영역 센서', + }, + }, + 'SensorPixelSize' => '센서 픽셀 크기', + 'SerialNumber' => '시리얼번호', + 'ShadingCompensation' => { + Description => '주변광량 보정', + PrintConv => { + 'Off' => '꺼짐', + 'On' => '켜짐', + }, + }, + 'ShadingCompensation2' => { + PrintConv => { + 'Off' => '꺼짐', + 'On' => '켜짐', + }, + }, + 'ShakeReduction' => { + PrintConv => { + 'Off' => '꺼짐', + 'On' => '켜짐', + }, + }, + 'Sharpness' => { + Description => '선명도', + PrintConv => { + 'Hard' => '강하게', + 'Normal' => '표준', + 'Soft' => '약하게', + }, + }, + 'ShootingInfoDisplay' => { + Description => '촬영 정보 표시', + PrintConv => { + 'Auto' => '자동', + 'Manual (dark on light)' => '수동 - 밝은배경에 어두움', + 'Manual (light on dark)' => '수동 - 어두운 배경에 밝음', + }, + }, + 'ShootingMode' => { + Description => '원격 리모컨', + PrintConv => { + 'Manual' => '수동', + }, + }, + 'ShootingModeSetting' => { + Description => '촬영 모드', + PrintConv => { + 'Continuous' => '연사', + 'Delayed Remote' => '촬영대기 리모컨', + 'Quick-response Remote' => '즉시촬영 리모컨', + 'Self-timer' => '셀프타이머', + 'Single Frame' => '싱글 프레임', + }, + }, + 'ShotInfoVersion' => '촬영 정보 버전', + 'ShutterCount' => '셔터 카운트', + 'ShutterMode' => { + PrintConv => { + 'Auto' => '자동', + }, + }, + 'ShutterReleaseButtonAE-L' => { + Description => '셔터 릴리즈 버튼 AE-L', + PrintConv => { + 'Off' => '꺼짐', + 'On' => '켜짐', + }, + }, + 'ShutterSpeed' => '노출 시간', + 'ShutterSpeedValue' => '셔터 속도', + 'SlowShutter' => { + PrintConv => { + 'Off' => '꺼짐', + 'On' => '켜짐', + }, + }, + 'SlowSync' => { + PrintConv => { + 'Off' => '꺼짐', + }, + }, + 'Software' => '소프트웨어', + 'Source' => '소스', + 'SpatialFrequencyResponse' => '공간 주파수 응답', + 'SpectralSensitivity' => '분광 감도', + 'State' => '도', + 'StripByteCounts' => '압축된 스트립 당 바이트', + 'StripOffsets' => '이미지 데이터 위치', + 'SubSecTime' => '일시 1/100 초', + 'SubSecTimeDigitized' => '디지털화 일시 1/100 초', + 'SubSecTimeOriginal' => '원본일시 1/100 초', + 'SubfileType' => '새로운 서브파일 형식', + 'SubjectArea' => '피사체 영역', + 'SubjectDistance' => '피사체의 거리', + 'SubjectDistanceRange' => { + Description => '피사체 거리 한계', + PrintConv => { + 'Close' => '근경', + 'Distant' => '원경', + 'Macro' => '매크로', + 'Unknown' => '알 수 없음', + }, + }, + 'SubjectLocation' => '피사체 위치', + 'SuperMacro' => { + PrintConv => { + 'Off' => '꺼짐', + }, + }, + 'SuperimposedDisplay' => { + PrintConv => { + 'Off' => '꺼짐', + 'On' => '켜짐', + }, + }, + 'SupplementalCategories' => '보충 범주', + 'TextStamp' => { + PrintConv => { + 'Off' => '꺼짐', + 'On' => '켜짐', + }, + }, + 'ThumbnailImage' => '축소 그림', + 'ThumbnailImageSize' => '갤러리 크기', + 'TimeZone' => '표준 시간대', + 'TimerFunctionButton' => { + Description => 'Fn 버튼', + PrintConv => { + 'ISO' => 'ISO 감도', + 'Image Quality/Size' => '이미지 화질/크기', + 'Self-timer' => '셀프타이머', + 'Shooting Mode' => '촬영 모드', + 'White Balance' => '화이트 밸런스', + }, + }, + 'Title' => '제목', + 'ToneComp' => '계조 보정', + 'ToneCurve' => { + PrintConv => { + 'Manual' => '수동', + }, + }, + 'ToningEffect' => { + Description => '조색 효과', + PrintConv => { + 'B&W' => '흑백', + 'Blue' => '블루', + 'Blue-green' => '블루-그린', + 'Green' => '녹색', + 'Purple-blue' => '퍼플-블루', + 'Red' => '빨강', + 'Red-purple' => '레드-퍼플', + 'Yellow' => '노랑', + 'n/a' => '설정 안됨', + }, + }, + 'ToningEffectMonochrome' => { + PrintConv => { + 'Green' => '녹색', + }, + }, + 'ToningSaturation' => '채도 조정', + 'TransferFunction' => '전송 기능', + 'TransmissionReference' => '전송 참조', + 'Uncompressed' => '압축되지 않음', + 'Unsharp1Color' => { + PrintConv => { + 'Green' => '녹색', + 'Red' => '빨강', + 'Yellow' => '노랑', + }, + }, + 'Unsharp2Color' => { + PrintConv => { + 'Green' => '녹색', + 'Red' => '빨강', + 'Yellow' => '노랑', + }, + }, + 'Unsharp3Color' => { + PrintConv => { + 'Green' => '녹색', + 'Red' => '빨강', + 'Yellow' => '노랑', + }, + }, + 'Unsharp4Color' => { + PrintConv => { + 'Green' => '녹색', + 'Red' => '빨강', + 'Yellow' => '노랑', + }, + }, + 'UnsharpMask' => { + PrintConv => { + 'Off' => '꺼짐', + 'On' => '켜짐', + }, + }, + 'Urgency' => '중요도', + 'UserComment' => '사용자 코멘트', + 'VRInfo' => '손떨림 보정 정보', + 'VRInfoVersion' => 'VR 정보 버전', + 'VR_0x66' => { + PrintConv => { + 'Off' => '꺼짐', + }, + }, + 'VariProgram' => '다중 프로그램', + 'VibrationReduction' => { + Description => '손떨림 보정', + PrintConv => { + 'Off' => '꺼짐', + 'On' => '켜짐', + }, + }, + 'ViewfinderWarning' => { + Description => '뷰파일더 경고', + PrintConv => { + 'Off' => '꺼짐', + 'On' => '켜짐', + }, + }, + 'VignetteControl' => { + Description => '비네팅 컨트롤', + PrintConv => { + 'High' => '높음', + 'Low' => '낮음', + 'Normal' => '표준', + 'Off' => '꺼짐', + 'On' => '켜짐', + }, + }, + 'WBBracketMode' => { + PrintConv => { + 'Off' => '꺼짐', + }, + }, + 'WBMode' => { + PrintConv => { + 'Auto' => '자동', + }, + }, + 'WhiteBalance' => { + Description => '화이트밸런스', + PrintConv => { + 'Auto' => '자동', + 'Black & White' => '흑백', + 'Cloudy' => '흐린날', + 'Color Temperature/Color Filter' => '색 온도 / 컬러 필터', + 'Cool White Fluorescent' => '차가운 백색 형광', + 'Custom' => '사용자 정의', + 'Custom 1' => '개인설정1', + 'Custom 2' => '개인설정2', + 'Custom 3' => '개인설정3', + 'Custom 4' => '개인설정4', + 'Day White Fluorescent' => '중성 백색 형광', + 'Daylight' => '맑은날', + 'Daylight Fluorescent' => '일광 형광', + 'Flash' => '플래시', + 'Fluorescent' => '형광등', + 'Manual' => '수동', + 'Shade' => '그늘', + 'Tungsten' => '백열등', + 'Unknown' => '알 수 없음', + 'Warm White Fluorescent' => '따뜻한 흰색 형광', + 'White Fluorescent' => '백색 형광등', + }, + }, + 'WhiteBalance2' => { + PrintConv => { + 'Auto' => '자동', + }, + }, + 'WhiteBalanceAdj' => { + PrintConv => { + 'Auto' => '자동', + 'Off' => '꺼짐', + 'On' => '켜짐', + }, + }, + 'WhiteBalanceFineTune' => '화이트밸런스 조정', + 'WhiteBalanceSet' => { + PrintConv => { + 'Auto' => '자동', + 'Manual' => '수동', + }, + }, + 'WhitePoint' => '흰색 점 색도', + 'WorldTime' => '표준 시간대', + 'Writer-Editor' => '캡션 작성자', + 'XResolution' => '수평 해상도', + 'YCbCrCoefficients' => '색상 공간 변환 매트릭스 계수', + 'YCbCrPositioning' => { + Description => 'Y and C 위치', + PrintConv => { + 'Centered' => '중앙', + 'Co-sited' => '주변', + }, + }, + 'YCbCrSubSampling' => 'Y->C 서브샘플링 비율', + 'YResolution' => '수직 해상도', + 'ZoneMatching' => { + Description => '영역 전환', + PrintConv => { + 'High Key' => 'Hi', + 'ISO Setting Used' => '없음', + 'Low Key' => 'Lo', + }, + }, + 'ZoneMatchingOn' => { + PrintConv => { + 'Off' => '꺼짐', + 'On' => '켜짐', + }, + }, +); + +1; # end + + +__END__ + +=head1 NAME + +Image::ExifTool::Lang::ko.pm - ExifTool Korean language translations + +=head1 DESCRIPTION + +This file is used by Image::ExifTool to generate localized tag descriptions +and values. + +=head1 AUTHOR + +Copyright 2003-2019, Phil Harvey (phil at owl.phy.queensu.ca) + +This library is free software; you can redistribute it and/or modify it +under the same terms as Perl itself. + +=head1 ACKNOWLEDGEMENTS + +Thanks to Jens Duttke and Jeong Beom Kim for providing this translation. + +=head1 SEE ALSO + +L<Image::ExifTool(3pm)|Image::ExifTool>, +L<Image::ExifTool::TagInfoXML(3pm)|Image::ExifTool::TagInfoXML> + +=cut diff --git a/lib/Image/ExifTool/Lang/nl.pm b/lib/Image/ExifTool/Lang/nl.pm new file mode 100644 index 0000000..88f8560 --- /dev/null +++ b/lib/Image/ExifTool/Lang/nl.pm @@ -0,0 +1,3222 @@ +#------------------------------------------------------------------------------ +# File: nl.pm +# +# Description: ExifTool Dutch language translations +# +# Notes: This file generated automatically by Image::ExifTool::TagInfoXML +#------------------------------------------------------------------------------ + +package Image::ExifTool::Lang::nl; + +use strict; +use vars qw($VERSION); + +$VERSION = '1.11'; + +%Image::ExifTool::Lang::nl::Translate = ( + 'AEBAutoCancel' => { + PrintConv => { + 'Off' => 'Uit', + 'On' => 'Aan', + }, + }, + 'AELock' => { + Description => 'AE-vergrendeling', + PrintConv => { + 'Off' => 'Uit', + 'On' => 'Aan', + }, + }, + 'AELockButton' => { + Description => 'AE-L/AF-L', + PrintConv => { + 'AE Lock (hold)' => 'AE-vergrendeling vast', + 'AE Lock Only' => 'AE-vergrendeling', + 'AE-L/AF Area' => 'AE-L/AF veld', + 'AE-L/AF-L/AF Area' => 'AE-L/AF-L/AF veld', + 'AE/AF Lock' => 'AE/AF-vergrendeling', + 'AF Lock Only' => 'AF-vergrendeling', + 'AF-L/AF Area' => 'AF-L/AF veld', + 'AF-ON/AF Area' => 'AF-ON/AF veld', + 'FV Lock' => 'FV-vergrendeling', + 'Focus Area Selection' => 'AF-veld', + }, + }, + 'AEMeteringMode' => { + PrintConv => { + 'Multi-segment' => 'Multi segment', + }, + }, + 'AEProgramMode' => { + PrintConv => { + 'Landscape' => 'Landschap', + 'Portrait' => 'Portret', + 'Standard' => 'Standaard', + }, + }, + 'AF-CPrioritySelection' => { + Description => 'Selectie AF-C-prioriteit', + PrintConv => { + 'Focus' => 'Scherpstelling', + 'Release' => 'Ontspannen', + 'Release + Focus' => 'Ontspannen + scherpstelling', + }, + }, + 'AF-OnForMB-D10' => { + Description => 'Functie AF-ON-knop MBD10', + PrintConv => { + 'AE Lock (hold)' => 'AE-vergrendeling (vast)', + 'AE Lock (reset on release)' => 'AE-vergr. (herstel na ontspan.)', + 'AE Lock Only' => 'AE-vergrendeling', + 'AE/AF Lock' => 'AE/AF-vergrendeling', + 'AF Lock Only' => 'AF-vergrendeling', + 'AF-On' => 'AF-ON', + 'Same as FUNC Button' => 'Zelfde als FUNC.-knop', + }, + }, + 'AF-SPrioritySelection' => { + Description => 'Selectie AF-S-prioriteit', + PrintConv => { + 'Focus' => 'Scherpstelling', + 'Release' => 'Ontspannen', + }, + }, + 'AFActivation' => { + Description => 'AF activering', + PrintConv => { + 'AF-On Only' => 'Alleen AF-ON', + 'Shutter/AF-On' => 'Ontspanknop/AF-ON', + }, + }, + 'AFAreaIllumination' => { + Description => 'AF-veld verlichting', + PrintConv => { + 'Auto' => 'Automatisch', + 'Off' => 'Uit', + 'On' => 'Aan', + }, + }, + 'AFAreaMode' => { + Description => 'AF-veldstand', + PrintConv => { + 'Auto-area' => 'Automatischveld AF', + 'Dynamic Area' => 'Dynamisch veld', + 'Single Area' => 'Enkelveld', + }, + }, + 'AFAreaModeSetting' => { + Description => 'AF-veldstand', + PrintConv => { + 'Closest Subject' => 'Dichtstbz. onderw.', + 'Dynamic Area' => 'Dynamisch veld', + 'Single Area' => 'Enkelveld', + }, + }, + 'AFAssist' => { + Description => 'AF-hulpverlichting', + PrintConv => { + 'Off' => 'Uit', + 'On' => 'Aan', + }, + }, + 'AFPoint' => { + PrintConv => { + 'None' => 'Geen', + }, + }, + 'AFPointActivationArea' => { + PrintConv => { + 'Standard' => 'Standaard', + }, + }, + 'AFPointBrightness' => { + PrintConv => { + 'Normal' => 'Normaal', + }, + }, + 'AFPointDisplayDuringFocus' => { + PrintConv => { + 'Off' => 'Uit', + 'On' => 'Aan', + }, + }, + 'AFPointIllumination' => { + Description => 'Verlichting scherpstelpunt', + PrintConv => { + 'Auto' => 'Automatisch', + 'Off' => 'Uit', + 'On' => 'Aan', + }, + }, + 'AFPointMode' => { + PrintConv => { + 'Auto' => 'Automatisch', + }, + }, + 'AFPointRegistration' => { + PrintConv => { + 'Automatic' => 'Automatisch', + }, + }, + 'AFPointSelected' => { + PrintConv => { + 'Auto' => 'Automatisch', + }, + }, + 'AFPointSelected2' => { + PrintConv => { + 'Auto' => 'Automatisch', + }, + }, + 'AFPointSelection' => { + Description => 'Selectie scherpstelpunt', + PrintConv => { + '11 Points' => '11 punten', + '51 Points' => '51 punten (3D-tracking)', + }, + }, + 'AFPointSelectionMethod' => { + PrintConv => { + 'Normal' => 'Normaal', + }, + }, + 'AFPointsInFocus' => { + PrintConv => { + 'None' => 'Geen', + }, + }, + 'AFPointsUnknown2' => { + PrintConv => { + 'Auto' => 'Automatisch', + }, + }, + 'AIServoTrackingSensitivity' => { + PrintConv => { + 'Standard' => 'Standaard', + }, + }, + 'APEVersion' => 'APE versie', + 'ARMIdentifier' => 'ARM herkenningscode', + 'ARMVersion' => 'ARM versie', + 'ActionAdvised' => { + Description => 'Actie advies', + PrintConv => { + 'Object Kill' => 'Object verwijderen', + 'Object Reference' => 'Object referentie', + 'Object Replace' => 'Object vervangen', + 'Ojbect Append' => 'Object toevoegen', + }, + }, + 'ActiveD-Lighting' => { + PrintConv => { + 'High' => 'Hoog', + 'Low' => 'Laag', + 'Normal' => 'Normaal', + 'Off' => 'Uit', + 'On' => 'Aan', + }, + }, + 'ActiveD-LightingMode' => { + PrintConv => { + 'High' => 'Hoog', + 'Low' => 'Laag', + 'Normal' => 'Normaal', + 'Off' => 'Uit', + }, + }, + 'AddAspectRatioInfo' => { + PrintConv => { + 'Off' => 'Uit', + }, + }, + 'AddOriginalDecisionData' => { + PrintConv => { + 'Off' => 'Uit', + 'On' => 'Aan', + }, + }, + 'AdultContentWarning' => { + PrintConv => { + 'Unknown' => 'Onbekend', + }, + }, + 'AdvancedRaw' => { + PrintConv => { + 'Off' => 'Uit', + 'On' => 'Aan', + }, + }, + 'AlphaByteCount' => 'Aantal alphagegevens in bytes', + 'AlphaDataDiscard' => { + Description => 'Afgedankte alphagegevens', + PrintConv => { + 'Flexbits Discarded' => 'Afgedankte flexbits', + 'Full Resolution' => 'Volledige resolutie', + 'HighPass Frequency Data Discarded' => 'Afgedankte hoogdoorlaat frequentiegegevens', + 'Highpass and LowPass Frequency Data Discarded' => 'Afgedankte hoogdoorlaat en laagdoorlaat frequentiegegevens', + }, + }, + 'AlphaOffset' => 'Alphaverplaatsing', + 'Anti-Blur' => { + PrintConv => { + 'Off' => 'Uit', + }, + }, + 'Aperture' => 'Diafragma', + 'ApertureValue' => 'Diafragma', + 'ApplicationRecordVersion' => 'Gegevensversie', + 'Artist' => 'Maker van de afbeelding', + 'AssistButtonFunction' => { + PrintConv => { + 'Normal' => 'Normaal', + }, + }, + 'Audio' => { + PrintConv => { + 'No' => 'Nee', + 'Yes' => 'Ja', + }, + }, + 'AudioDuration' => 'Audio duur', + 'AudioOutcue' => 'Audio eindaftiteling', + 'AudioSamplingRate' => 'Audio bemonsteringssnelheid', + 'AudioSamplingResolution' => 'Audio bemonsteringsresolutie', + 'AudioType' => { + Description => 'Type audio', + PrintConv => { + 'Mono Actuality' => 'Actualiteit (mono (1 kanaal) audio)', + 'Mono Music' => 'Muziek, zelf verstuurd (mono (1 kanaal) audio)', + 'Mono Question and Answer Session' => 'Vraag en antwoord sessie (mono (1 kanaal) audio)', + 'Mono Raw Sound' => 'Ruwe geluid (mono (1 kanaal) audio)', + 'Mono Response to a Question' => 'Beantwoord een vraag (mono (1 kanaal) audio)', + 'Mono Scener' => 'Toneel (mono (1 kanaal) audio)', + 'Mono Voicer' => 'Stem (mono (1 kanaals) audio)', + 'Mono Wrap' => 'Wrap (mono (1 kanaals) audio)', + 'Stereo Actuality' => 'Actualiteit (stereo (2 kanalen) audio)', + 'Stereo Music' => 'Muziek, zelf verstuurd (stereo (2 kanalen) audio)', + 'Stereo Question and Answer Session' => 'Vraag en antwoord sessie (stereo (2 kanalen) audio)', + 'Stereo Raw Sound' => 'Ruwe geluid (stereo (2 kanalen) audio)', + 'Stereo Response to a Question' => 'Beantwoord een vraag (stereo (2 kanalen) audio)', + 'Stereo Scener' => 'Toneel (stereo (2 kanaals) audio)', + 'Stereo Voicer' => 'Stem (stereo (2 kanaals) audio)', + 'Stereo Wrap' => 'Wrap (stereo (2 kanaals) audio)', + 'Text Only' => 'Alleen tekst (geen objectgegevens)', + }, + }, + 'Author' => 'Auteur', + 'AuthorsPosition' => 'Positie van de auteur', + 'AutoAperture' => { + PrintConv => { + 'Off' => 'Uit', + 'On' => 'Aan', + }, + }, + 'AutoBracketModeM' => { + Description => 'Auto bracketing (M-stand)', + PrintConv => { + 'Flash Only' => 'Alleen flits', + 'Flash/Aperture' => 'Flits/diafragma', + 'Flash/Speed' => 'Flits/sluitertijd', + 'Flash/Speed/Aperture' => 'Flits/sluitertijd/diafragma', + }, + }, + 'AutoBracketOrder' => 'Bracketingvolgorde', + 'AutoBracketSet' => { + Description => 'Inst. voor auto bracketing', + PrintConv => { + 'AE & Flash' => 'AE & flits', + 'AE Only' => 'Alleen AE', + 'Flash Only' => 'Alleen flits', + 'WB Bracketing' => 'Witbalans bracketing', + }, + }, + 'AutoBracketing' => { + PrintConv => { + 'Off' => 'Uit', + }, + }, + 'AutoExposureBracketing' => { + PrintConv => { + 'Off' => 'Uit', + 'On' => 'Aan', + }, + }, + 'AutoFP' => { + Description => 'Auto FP', + PrintConv => { + 'Off' => 'Uit', + 'On' => 'Aan', + }, + }, + 'AutoFocus' => { + PrintConv => { + 'Off' => 'Uit', + 'On' => 'Aan', + }, + }, + 'AutoISO' => { + Description => 'ISO auto', + PrintConv => { + 'Off' => 'Uit', + 'On' => 'Aan', + }, + }, + 'AutoISOMax' => 'ISO auto Maximale', + 'AutoISOMinShutterSpeed' => 'ISO auto Langste sluitertijd', + 'AutoLightingOptimizer' => { + PrintConv => { + 'Low' => 'Laag', + 'Off' => 'Uit', + 'Standard' => 'Standaard', + }, + }, + 'AutoLightingOptimizerOn' => { + PrintConv => { + 'No' => 'Nee', + 'Yes' => 'Ja', + }, + }, + 'AutoRedEye' => { + PrintConv => { + 'Off' => 'Uit', + 'On' => 'Aan', + }, + }, + 'AutoRotate' => { + PrintConv => { + 'None' => 'Geen', + 'Rotate 180' => '180° (onder/rechts)', + 'Rotate 270 CW' => 'Draai 270° met de klok mee', + 'Rotate 90 CW' => '90° tegen de klok in (rechts/boven)', + 'n/a' => 'Onbekend', + }, + }, + 'BWMode' => { + PrintConv => { + 'Off' => 'Uit', + }, + }, + 'BackgroundColorIndicator' => 'Achtergrond kleur indicator', + 'BackgroundColorValue' => 'Achtergrond kleur waarde', + 'BackgroundTiling' => { + PrintConv => { + 'No' => 'Nee', + 'Yes' => 'Ja', + }, + }, + 'BannerImageType' => { + PrintConv => { + 'None' => 'Geen', + }, + }, + 'BatteryLevel' => 'Batterij status', + 'BatteryOrder' => { + Description => 'Batterijvolgorde', + PrintConv => { + 'Camera Battery First' => 'Camerabatterij eerst', + 'MB-D10 First' => 'MB-D10 batterijen eerst', + }, + }, + 'Beep' => { + Description => 'Signaal', + PrintConv => { + 'High' => 'Hoog', + 'Low' => 'Laag', + 'Off' => 'Uit', + 'On' => 'Aan', + }, + }, + 'BitsPerSample' => 'Aantal Bits per component', + 'BlueMatrixColumn' => 'Blauwe matrixkolom', + 'BlueTRC' => 'Blauwe toon reproductie curve', + 'BlurWarning' => { + PrintConv => { + 'None' => 'Geen', + }, + }, + 'BracketMode' => { + PrintConv => { + 'Off' => 'Uit', + }, + }, + 'BracketStep' => { + PrintConv => { + '1 EV' => '1 stop', + '1/3 EV' => '1/3 stop', + '2/3 EV' => '2/3 stop', + }, + }, + 'Brightness' => 'Helderheid', + 'BrightnessValue' => 'Helderheid', + 'BurstMode' => { + PrintConv => { + 'Off' => 'Uit', + 'On' => 'Aan', + }, + }, + 'By-line' => 'Maker', + 'By-lineTitle' => 'Beroep van de maker', + 'CFAPattern' => 'Kleur filter matrix', + 'CFAPattern2' => 'Kleurfiltermatrix 2', + 'CFARepeatPatternDim' => 'Kleurfiltermatrix grootte', + 'CLModeShootingSpeed' => 'Opnamesnelheid', + 'CMMFlags' => 'CMM vlaggen', + 'CPUType' => { + PrintConv => { + 'None' => 'Geen', + }, + }, + 'CalibrationIlluminant1' => { + PrintConv => { + 'Cloudy' => 'Bewolkt', + 'Cool White Fluorescent' => 'Koel wit TL-licht', + 'Day White Fluorescent' => 'Daglicht wit TL-licht', + 'Daylight' => 'Daglicht', + 'Daylight Fluorescent' => 'Daglicht TL-licht', + 'Fine Weather' => 'Onbewolkt', + 'Flash' => 'Flits', + 'Fluorescent' => 'Fluoresceren', + 'ISO Studio Tungsten' => 'ISO studio kunstlicht (gloeilamp)', + 'Other' => 'Andere lichtbron', + 'Shade' => 'Schaduw', + 'Standard Light A' => 'Standaard licht A', + 'Standard Light B' => 'Standaard licht B', + 'Standard Light C' => 'Standaard licht C', + 'Tungsten (Incandescent)' => 'Kunstlicht (gloeilamp)', + 'Unknown' => 'Onbekend', + 'Warm White Fluorescent' => 'Warm wit TL-licht', + 'White Fluorescent' => 'Wit TL-licht', + }, + }, + 'CalibrationIlluminant2' => { + PrintConv => { + 'Cloudy' => 'Bewolkt', + 'Cool White Fluorescent' => 'Koel wit TL-licht', + 'Day White Fluorescent' => 'Daglicht wit TL-licht', + 'Daylight' => 'Daglicht', + 'Daylight Fluorescent' => 'Daglicht TL-licht', + 'Fine Weather' => 'Onbewolkt', + 'Flash' => 'Flits', + 'Fluorescent' => 'Fluoresceren', + 'ISO Studio Tungsten' => 'ISO studio kunstlicht (gloeilamp)', + 'Other' => 'Andere lichtbron', + 'Shade' => 'Schaduw', + 'Standard Light A' => 'Standaard licht A', + 'Standard Light B' => 'Standaard licht B', + 'Standard Light C' => 'Standaard licht C', + 'Tungsten (Incandescent)' => 'Kunstlicht (gloeilamp)', + 'Unknown' => 'Onbekend', + 'Warm White Fluorescent' => 'Warm wit TL-licht', + 'White Fluorescent' => 'Wit TL-licht', + }, + }, + 'CameraOrientation' => { + Description => 'Oriëntatie van de afbeelding', + PrintConv => { + 'Horizontal (normal)' => '0° (boven/links)', + 'Rotate 270 CW' => 'Draai 270° met de klok mee', + 'Rotate 90 CW' => '90° tegen de klok in (rechts/boven)', + }, + }, + 'CanonExposureMode' => { + PrintConv => { + 'Aperture-priority AE' => 'Diafragmaprioriteit', + 'Manual' => 'Handmatig', + 'Shutter speed priority AE' => 'Sluiterprioriteit', + }, + }, + 'CanonFlashMode' => { + PrintConv => { + 'Auto' => 'Automatisch', + 'Off' => 'Uit', + 'On' => 'Aan', + }, + }, + 'Caption-Abstract' => 'Titel/Beschrijving', + 'CaptionWriter' => 'Schrijver van het onderschrift', + 'CaptureXResolutionUnit' => { + PrintConv => { + 'um' => 'µm (micrometer)', + }, + }, + 'CaptureYResolutionUnit' => { + PrintConv => { + 'um' => 'µm (micrometer)', + }, + }, + 'Categories' => 'Categorieën', + 'Category' => 'Categorie', + 'CellLength' => 'Cel lengte', + 'CellWidth' => 'Cel breedte', + 'CenterAFArea' => { + Description => 'Centrale AF-veld', + PrintConv => { + 'Normal Zone' => 'Normaal', + 'Wide Zone' => 'Breed', + }, + }, + 'CenterWeightedAreaSize' => { + Description => 'Grootte meetgebied', + PrintConv => { + 'Average' => 'Gemiddeld', + }, + }, + 'CharacterSet' => 'Tekenset', + 'ChrominanceNR_TIFF_JPEG' => { + PrintConv => { + 'High' => 'Hoog', + 'Low' => 'Laag', + 'Off' => 'Uit', + }, + }, + 'ChrominanceNoiseReduction' => { + PrintConv => { + 'High' => 'Hoog', + 'Low' => 'Laag', + 'Off' => 'Uit', + }, + }, + 'City' => 'Plaats', + 'ClassifyState' => 'Rangschik status', + 'CodedCharacterSet' => 'Gecodeerde character set', + 'ColorAberrationControl' => { + PrintConv => { + 'Off' => 'Uit', + 'On' => 'Aan', + }, + }, + 'ColorAdjustmentMode' => { + PrintConv => { + 'Off' => 'Uit', + 'On' => 'Aan', + }, + }, + 'ColorBalanceAdj' => { + PrintConv => { + 'Off' => 'Uit', + 'On' => 'Aan', + }, + }, + 'ColorBooster' => { + PrintConv => { + 'Off' => 'Uit', + 'On' => 'Aan', + }, + }, + 'ColorEffect' => { + PrintConv => { + 'Off' => 'Uit', + }, + }, + 'ColorFilter' => { + Description => 'Kleurfilter', + PrintConv => { + 'Off' => 'Uit', + }, + }, + 'ColorMode' => { + Description => 'Instellingen', + PrintConv => { + 'Autumn Leaves' => 'Herfstbladeren', + 'B&W' => 'Zwart-wit', + 'Clear' => 'Doorzichtig', + 'Deep' => 'Diep', + 'Evening' => 'Avond', + 'Landscape' => 'Landschap', + 'Light' => 'Licht', + 'Neutral' => 'Neutraal', + 'Night View' => 'Nacht', + 'Night View/Portrait' => 'Nachtportret', + 'Normal' => 'Normaal', + 'Off' => 'Uit', + 'Portrait' => 'Portret', + 'Standard' => 'Standaard', + 'Sunset' => 'Zonsondergang', + 'Vivid' => 'Levendige kleuren', + }, + }, + 'ColorMoireReduction' => { + PrintConv => { + 'Off' => 'Uit', + 'On' => 'Aan', + }, + }, + 'ColorMoireReductionMode' => { + PrintConv => { + 'High' => 'Hoog', + 'Low' => 'Laag', + 'Off' => 'Uit', + }, + }, + 'ColorSpace' => { + Description => 'Kleur ruimte', + PrintConv => { + 'ICC Profile' => 'ICC-profiel', + 'Uncalibrated' => 'Niet vastgelegd', + }, + }, + 'ColorSpaceData' => 'Gegevenskleurenruimte', + 'ColorTable' => 'Kleur tabel', + 'ColorTemperature' => 'Kleurtemperatuur', + 'ColorTone' => { + PrintConv => { + 'Normal' => 'Normaal', + }, + }, + 'CommandDials' => { + Description => 'Instelschijven', + PrintConv => { + 'Reversed (Main Aperture, Sub Shutter)' => 'Verwissel hoofd/sec.', + 'Standard (Main Shutter, Sub Aperture)' => 'Standaard', + }, + }, + 'CommandDialsApertureSetting' => { + Description => 'Functie instelschijven inst. Instellen diafragma', + PrintConv => { + 'Aperture Ring' => 'Diafragmaring', + 'Sub-command Dial' => 'Secundaire instelschijf', + }, + }, + 'CommandDialsChangeMainSub' => { + Description => 'Functie instelschijven inst. Verwissel hoofd/secundair', + PrintConv => { + 'Off' => 'Uit', + 'On' => 'Aan', + }, + }, + 'CommandDialsMenuAndPlayback' => { + Description => 'Functie instelschijven inst. Menu’s en weergave', + PrintConv => { + 'Off' => 'Uit', + 'On' => 'Aan', + }, + }, + 'CommandDialsReverseRotation' => { + Description => 'Functie instelschijven inst. Rotatie omkeren', + PrintConv => { + 'No' => 'Nee', + 'Yes' => 'Ja', + }, + }, + 'CommanderChannel' => 'Commanderstand Kanaal', + 'CommanderGroupAManualOutput' => 'Commanderstand Groep A M Corrct', + 'CommanderGroupAMode' => { + Description => 'Commanderstand Groep A Stand', + PrintConv => { + 'Manual' => 'Handmatig', + 'Off' => 'Uit', + 'TTL' => 'DDL', + }, + }, + 'CommanderGroupA_TTL-AAComp' => 'Commanderstand Groep A DDL/AA Corrct', + 'CommanderGroupBManualOutput' => 'Commanderstand Groep B M Corrct', + 'CommanderGroupBMode' => { + Description => 'Commanderstand Groep B Stand', + PrintConv => { + 'Manual' => 'Handmatig', + 'Off' => 'Uit', + 'TTL' => 'DDL', + }, + }, + 'CommanderGroupB_TTL-AAComp' => 'Commanderstand Groep B DDL/AA Corrct', + 'CommanderInternalFlash' => { + Description => 'Commanderstand Ingb. flitsr Stand', + PrintConv => { + 'Manual' => 'Handmatig', + 'Off' => 'Uit', + 'TTL' => 'DDL', + }, + }, + 'CommanderInternalManualOutput' => 'Commanderstand Ingb. flitsr M Corrct', + 'CommanderInternalTTLComp' => 'Commanderstand Ingb. flitsr DDL Corrct', + 'Comment' => 'Kommentaar', + 'Compilation' => { + PrintConv => { + 'No' => 'Nee', + 'Yes' => 'Ja', + }, + }, + 'ComponentsConfiguration' => 'Betekenis van elke component', + 'CompressedBitsPerPixel' => 'Afbeelding compressie modus', + 'Compression' => { + Description => 'Compressie schema', + PrintConv => { + 'JPEG' => 'JPEG-compressie', + 'JPEG (old-style)' => 'JPEG (oude versie)', + 'Kodak DCR Compressed' => 'Kodak DCR gcomprimeerd', + 'Kodak KDC Compressed' => 'Kodak KDC gecomprimeerd', + 'Next' => 'NeXT 2-Bit codering', + 'Nikon NEF Compressed' => 'Nikon NEF gecomprimeerd', + 'None' => 'Geen', + 'Pentax PEF Compressed' => 'Pentax PEF gecomprimeerd', + 'SGILog' => 'SGI 32-Bit Log Luminance gecodeerd', + 'SGILog24' => 'SGI 24-Bit Log Luminance gecodeerd', + 'Sony ARW Compressed' => 'Sony ARW gecomprimeerd', + 'Thunderscan' => 'ThunderScan 4-Bit codering', + 'Uncompressed' => 'Niet gecomprimeerd', + }, + }, + 'CompressionType' => { + PrintConv => { + 'None' => 'Geen', + }, + }, + 'ConnectionSpaceIlluminant' => 'Witpunt van connectiekleurruimte', + 'ContentLocationCode' => 'Locatiecode van inhoud', + 'ContentLocationName' => 'Locatienaam van inhoud', + 'ContinuousDrive' => { + PrintConv => { + 'Continuous' => 'Continu', + }, + }, + 'Contrast' => { + Description => 'Kontrast', + PrintConv => { + 'High' => 'Hoog', + 'Low' => 'Laag', + 'Normal' => 'Normaal', + }, + }, + 'ConversionLens' => { + PrintConv => { + 'Off' => 'Uit', + }, + }, + 'Copyright' => 'Copyright houder', + 'CopyrightNotice' => 'Copyright vermelding', + 'CopyrightStatus' => { + PrintConv => { + 'Unknown' => 'Onbekend', + }, + }, + 'Country' => 'Land', + 'Country-PrimaryLocationCode' => 'ISO landcode', + 'Country-PrimaryLocationName' => 'Land', + 'CreateDate' => 'Datum van de originele data generatie', + 'CreationDate' => 'Opname datum', + 'Creator' => 'Maker', + 'CreatorAddress' => 'Maker - Adres', + 'CreatorCity' => 'Maker - Plaats', + 'CreatorCountry' => 'Maker - Land', + 'CreatorPostalCode' => 'Maker - Postcode', + 'CreatorRegion' => 'Maker - Provincie', + 'CreatorWorkEmail' => 'Maker - E-mail', + 'CreatorWorkTelephone' => 'Maker - Telefoonnummer', + 'CreatorWorkURL' => 'Maker - Website(s)', + 'Credit' => 'Leverancier', + 'CropActive' => { + PrintConv => { + 'No' => 'Nee', + 'Yes' => 'Ja', + }, + }, + 'Curves' => { + PrintConv => { + 'Off' => 'Uit', + 'On' => 'Aan', + }, + }, + 'CustomRendered' => { + Description => 'Gebruiker gedefineerde beeldverwerking', + PrintConv => { + 'Custom' => 'Gebruiker gedefineerd proces', + 'Normal' => 'Standaard proces', + }, + }, + 'D-LightingHQ' => { + PrintConv => { + 'Off' => 'Uit', + 'On' => 'Aan', + }, + }, + 'D-LightingHQSelected' => { + PrintConv => { + 'No' => 'Nee', + 'Yes' => 'Ja', + }, + }, + 'D-LightingHS' => { + PrintConv => { + 'Off' => 'Uit', + 'On' => 'Aan', + }, + }, + 'DataImprint' => { + PrintConv => { + 'None' => 'Geen', + }, + }, + 'DateCreated' => 'Opnamedatum', + 'DateSent' => 'Datum van zenden', + 'DateStampMode' => { + PrintConv => { + 'Off' => 'Uit', + }, + }, + 'DateTime' => 'Datum bestand wijziging', + 'DateTimeOriginal' => 'Datum van de originele data generatie', + 'DaylightSavings' => { + PrintConv => { + 'No' => 'Nee', + 'Yes' => 'Ja', + }, + }, + 'Description' => 'Beschrijving', + 'Destination' => 'Bestemming', + 'DestinationDST' => { + PrintConv => { + 'No' => 'Nee', + 'Yes' => 'Ja', + }, + }, + 'DeviceAttributes' => 'Apparaateigenschappen', + 'DeviceManufacturer' => 'Apparaatproducent', + 'DeviceMfgDesc' => 'Apparaatproducent kenmerk', + 'DeviceModel' => 'Apparaatmodel', + 'DeviceModelDesc' => 'Apparaatmodel kenmerk', + 'DeviceSettingDescription' => 'Toestelinstellingen', + 'DialDirectionTvAv' => { + PrintConv => { + 'Normal' => 'Normaal', + }, + }, + 'DigitalCreationDate' => 'Digitale opnamedatum', + 'DigitalCreationTime' => 'Digitaal opnametijdstip', + 'DigitalZoom' => { + Description => 'Digitaal zoomen', + PrintConv => { + 'None' => 'Geen', + 'Off' => 'Uit', + }, + }, + 'DigitalZoomOn' => { + PrintConv => { + 'Off' => 'Uit', + 'On' => 'Aan', + }, + }, + 'DigitalZoomRatio' => 'Digitale zoom factor', + 'Directory' => 'Plaats van het bestand', + 'DisplaySize' => { + PrintConv => { + 'Normal' => 'Normaal', + }, + }, + 'DisplayXResolutionUnit' => { + PrintConv => { + 'um' => 'µm (micrometer)', + }, + }, + 'DisplayYResolutionUnit' => { + PrintConv => { + 'um' => 'µm (micrometer)', + }, + }, + 'DistortionCorrection' => { + PrintConv => { + 'Off' => 'Uit', + 'On' => 'Aan', + }, + }, + 'DistortionCorrection2' => { + PrintConv => { + 'Off' => 'Uit', + 'On' => 'Aan', + }, + }, + 'DjVuVersion' => 'DjVu versie', + 'DocumentHistory' => 'Documentgeschiedenis', + 'DocumentName' => 'Document naam', + 'DocumentNotes' => 'Documentopmerkingen', + 'DriveMode' => { + Description => 'Ontspannermodus', + PrintConv => { + 'Continuous' => 'Continu', + 'Continuous Shooting' => 'Continu', + 'Off' => 'Uit', + 'Self-timer' => 'Zelfontspanner', + 'Self-timer Operation' => 'Zelfontspanner', + 'Single' => 'Enkel beeld', + 'Single Frame' => 'Enkel beeld', + 'Single Shot' => 'Enkel beeld', + 'Single-frame Shooting' => 'Enkel beeld', + }, + }, + 'DynamicAFArea' => { + Description => 'Dynamisch AF-veld', + PrintConv => { + '21 Points' => '21 punten', + '51 Points' => '51 punten', + '51 Points (3D-tracking)' => '51 punten (3D-tracking)', + '9 Points' => '9 punten', + }, + }, + 'DynamicRange' => { + PrintConv => { + 'Standard' => 'Standaard', + }, + }, + 'DynamicRangeExpansion' => { + PrintConv => { + 'Off' => 'Uit', + 'On' => 'Aan', + }, + }, + 'DynamicRangeOptimizer' => { + Description => 'Dyn.-bereikoptim', + PrintConv => { + 'Advanced Auto' => 'Geavancrd Auto', + 'Advanced Lv1' => 'Geavanceerd-1', + 'Advanced Lv2' => 'Geavanceerd-2', + 'Advanced Lv3' => 'Geavanceerd-3', + 'Advanced Lv4' => 'Geavanceerd-4', + 'Advanced Lv5' => 'Geavanceerd-5', + 'Auto' => 'Automatisch', + 'Off' => 'Uit', + 'Standard' => 'Standaard', + }, + }, + 'ETTLII' => { + PrintConv => { + 'Average' => 'Gemiddeld', + }, + }, + 'EVStepSize' => { + Description => 'LW stapgrootte', + PrintConv => { + '1/2 EV' => '1/2 stop', + '1/3 EV' => '1/3 stop', + }, + }, + 'EasyExposureCompensation' => { + Description => 'Eenv. belichtingscorrectie', + PrintConv => { + 'Off' => 'Uit', + 'On' => 'Aan', + 'On (auto reset)' => 'Aan (autoherstel)', + }, + }, + 'EasyMode' => { + PrintConv => { + 'Landscape' => 'Landschap', + 'Manual' => 'Handmatig', + 'Night' => 'Nachtscene', + 'Portrait' => 'Portret', + }, + }, + 'EdgeNoiseReduction' => { + PrintConv => { + 'Off' => 'Uit', + 'On' => 'Aan', + }, + }, + 'EditStatus' => 'Bewerkingsstatus', + 'EditorialUpdate' => { + Description => 'Redactionele bewerking', + PrintConv => { + 'Additional language' => 'Extra taal', + }, + }, + 'Emphasis' => { + PrintConv => { + 'None' => 'Geen', + }, + }, + 'EnhanceDarkTones' => { + PrintConv => { + 'Off' => 'Uit', + 'On' => 'Aan', + }, + }, + 'Enhancement' => { + PrintConv => { + 'Off' => 'Uit', + }, + }, + 'EnvelopeNumber' => 'Basisdatanummer', + 'EnvelopePriority' => { + Description => 'Prioriteit', + PrintConv => { + '0 (reserved)' => '0 (Gereserveerd voor toekomstig gebruik)', + '1 (most urgent)' => '1 (Meest belangrijk)', + '5 (normal urgency)' => '5 (Normaal)', + '8 (least urgent)' => '8 (Minst belangrijk)', + '9 (user-defined priority)' => '9 (Door gebruiker aangegeven prioriteit)', + }, + }, + 'EnvelopeRecordVersion' => 'Recordversie', + 'ExifCameraInfo' => 'Exif Camera-informatie', + 'ExifImageHeight' => 'Afbeelding hoogte', + 'ExifImageWidth' => 'Afbeelding breedte', + 'ExifOffset' => 'Exif IFD-wijzer', + 'ExifToolVersion' => 'ExifTool versie', + 'ExifVersion' => 'Exif versie', + 'ExpandFilm' => 'Breid film uit', + 'ExpandFilterLens' => 'Breid filterlens uit', + 'ExpandFlashLamp' => 'Breid flitser uit', + 'ExpandLens' => 'Breid objectief', + 'ExpandScanner' => 'Breid scanner uit', + 'ExpandSoftware' => 'Breid software uit', + 'ExpirationDate' => 'Verloopdatum', + 'ExpirationTime' => 'Verlooptijdstip', + 'ExposureCompStepSize' => { + Description => 'Stapgrootte belichtingscorr.', + PrintConv => { + '1 EV' => '1 stop', + '1/2 EV' => '1/2 stop', + '1/3 EV' => '1/3 stop', + }, + }, + 'ExposureCompensation' => 'Belichtingscorrectie', + 'ExposureControlStepSize' => { + Description => 'Stapgrootte inst. belichting', + PrintConv => { + '1 EV' => '1 stop', + '1/2 EV' => '1/2 stop', + '1/3 EV' => '1/3 stop', + }, + }, + 'ExposureDelayMode' => { + Description => 'Spiegelvoorontspanning', + PrintConv => { + 'Off' => 'Uit', + 'On' => 'Aan', + }, + }, + 'ExposureIndex' => 'Belichtingsindex', + 'ExposureLevelIncrements' => { + Description => 'Stapgrootte inst. belichting', + PrintConv => { + '1/2 Stop' => '1/2 stop', + '1/3 Stop' => '1/3 stop', + }, + }, + 'ExposureMode' => { + Description => 'Belichting modus', + PrintConv => { + 'Aperture Priority' => 'Diafragmaprioriteit', + 'Aperture-priority AE' => 'Diafragmaprioriteit', + 'Auto' => 'Automatische belichting', + 'Auto bracket' => 'Belichting serie', + 'Landscape' => 'Landschap', + 'Manual' => 'Handmatige belichting', + 'Portrait' => 'Portret', + 'Shutter Priority' => 'Sluiterprioriteit', + 'Shutter speed priority AE' => 'Sluiterprioriteit', + }, + }, + 'ExposureModeInManual' => { + PrintConv => { + 'Center-weighted average' => 'Centrum gemiddelde', + 'Partial metering' => 'Gedeelte', + }, + }, + 'ExposureProgram' => { + Description => 'Belichtingsprogramma', + PrintConv => { + 'Action (High speed)' => 'Actie programma (georiënteerd op snelle sluitertijden)', + 'Aperture Priority' => 'Diafragmaprioriteit', + 'Aperture-priority AE' => 'Diafragmaprioriteit', + 'Creative (Slow speed)' => 'Creatief programma (georiënteerd op scherptediepte)', + 'Landscape' => 'Landschap modus', + 'Manual' => 'Handmatig', + 'Not Defined' => 'Niet gedefinieerd', + 'Portrait' => 'Portret modus', + 'Program AE' => 'Normaal programma', + 'Shutter Priority' => 'Sluiterprioriteit', + 'Shutter speed priority AE' => 'Sluiterprioriteit', + }, + }, + 'ExposureTime' => 'Belichtingstijd', + 'ExposureTime2' => 'Belichtingstijd 2', + 'ExtendedWBDetect' => { + PrintConv => { + 'Off' => 'Uit', + 'On' => 'Aan', + }, + }, + 'ExternalFlash' => { + PrintConv => { + 'Off' => 'Uit', + 'On' => 'Aan', + }, + }, + 'ExternalFlashBounce' => { + PrintConv => { + 'No' => 'Nee', + 'Yes' => 'Ja', + }, + }, + 'ExternalFlashMode' => { + PrintConv => { + 'Off' => 'Uit', + }, + }, + 'ExtraSamples' => 'Extra componenten', + 'FNumber' => 'F waarde', + 'FaceOrientation' => { + PrintConv => { + 'Horizontal (normal)' => '0° (boven/links)', + 'Rotate 180' => '180° (onder/rechts)', + 'Rotate 270 CW' => 'Draai 270° met de klok mee', + 'Rotate 90 CW' => '90° tegen de klok in (rechts/boven)', + }, + }, + 'FastSeek' => { + PrintConv => { + 'No' => 'Nee', + 'Yes' => 'Ja', + }, + }, + 'FaxProfile' => { + PrintConv => { + 'Unknown' => 'Onbekend', + }, + }, + 'FaxRecvParams' => 'Fax ontvangst parameters', + 'FaxRecvTime' => 'Fax ontvangst tijd', + 'FaxSubAddress' => 'Fax sub adres', + 'FileFormat' => 'Fileformaat', + 'FileModifyDate' => 'Datum actualisering', + 'FileName' => 'Bestandnaam', + 'FileNumberMemory' => { + PrintConv => { + 'Off' => 'Uit', + 'On' => 'Aan', + }, + }, + 'FileNumberSequence' => { + Description => 'Opeenvolgende nummering', + PrintConv => { + 'Off' => 'Uit', + 'On' => 'Aan', + }, + }, + 'FileSize' => 'Bestandgrootte', + 'FileSource' => { + Description => 'Bestand bron', + PrintConv => { + 'Digital Camera' => 'Digitale camera', + 'Film Scanner' => 'Film scanner', + 'Reflection Print Scanner' => 'Scanner', + }, + }, + 'FileType' => 'Bestandtype', + 'FileVersion' => 'Fileformaat versie', + 'Filename' => 'Bestandnaam', + 'FillOrder' => { + Description => 'Vul volgorde', + PrintConv => { + 'Normal' => 'Normaal', + }, + }, + 'Filter' => { + PrintConv => { + 'Off' => 'Uit', + }, + }, + 'FilterEffect' => { + PrintConv => { + 'None' => 'Geen', + 'Off' => 'Uit', + }, + }, + 'FilterEffectMonochrome' => { + PrintConv => { + 'None' => 'Geen', + }, + }, + 'FinderDisplayDuringExposure' => { + PrintConv => { + 'Off' => 'Uit', + 'On' => 'Aan', + }, + }, + 'FineTuneOptCenterWeighted' => 'Fijnafst. voor opt. belichting Centrumgericht', + 'FineTuneOptMatrixMetering' => 'Fijnafst. voor opt. belichting Matrixmeting', + 'FineTuneOptSpotMetering' => 'Fijnafst. voor opt. belichting Spotmeting', + 'FixtureIdentifier' => 'Kenmerk', + 'Flash' => { + Description => 'Flits', + PrintConv => { + 'Auto, Did not fire' => 'Flits werd niet ontstoken, automodus', + 'Auto, Did not fire, Red-eye reduction' => 'Flits werd niet ontstoken, rode ogen reductie', + 'Auto, Fired' => 'Flits werd ontstoken, automodus', + 'Auto, Fired, Red-eye reduction' => 'Flits werd ontstoken, automodus, rode ogen reductie', + 'Auto, Fired, Red-eye reduction, Return detected' => 'Flits werd ontstoken, automodus, gereflecteerd flitslicht, rode ogen reductie', + 'Auto, Fired, Red-eye reduction, Return not detected' => 'Flits werd ontstoken, automodus, geen gereflecteerd flitslicht, rode ogen reductie', + 'Auto, Fired, Return detected' => 'Flits werd ontstoken, automodus, gereflecteerd flitslicht', + 'Auto, Fired, Return not detected' => 'Flits werd ontstoken, automodus, geen gereflecteerd flitslicht', + 'Did not fire' => 'Geen flits', + 'Fired' => 'Flits afgevuurd', + 'Fired, Red-eye reduction' => 'Flits werd ontstoken, Rode ogen reductie', + 'Fired, Red-eye reduction, Return detected' => 'Flits werd ontstoken, rode ogen reductie, gereflecteerd flitslicht', + 'Fired, Red-eye reduction, Return not detected' => 'Flits werd ontstoken, rode oen reductie, geen gereflecteerd flitslicht', + 'Fired, Return detected' => 'Gereflecteerd flitslicht gedetecteerd', + 'Fired, Return not detected' => 'Geen gereflecteerd flitslicht gedetecteerd', + 'No Flash' => 'Geen flits', + 'No flash function' => 'Geen flits functie', + 'Off' => 'Uit', + 'Off, Did not fire' => 'Flits werd niet ontstoken, flits onderdruk modus', + 'Off, Did not fire, Return not detected' => 'Gedeactiveerd, flits werd niet ontstoken, geen gereflecteerd flitslicht', + 'Off, No flash function' => 'Gedeactiveerd, geen flits functie', + 'Off, Red-eye reduction' => 'Gedeactiveerd, rode ogen reductie', + 'On' => 'Aan', + 'On, Did not fire' => 'Aan, flits werd niet ontstoken', + 'On, Fired' => 'Flits werd ontstoken, flits afdwing modus', + 'On, Red-eye reduction' => 'Flits werd ontstoken, flits afdwing modus, rode ogen reductie', + 'On, Red-eye reduction, Return detected' => 'Flits werd ontstoken, flits afdwing modus, rode ogen reductie, gereflecteerd flitslicht', + 'On, Red-eye reduction, Return not detected' => 'Flits werd ontstoken, flits afdwing modus, rode ogen reductie, geen gereflecteerd flitslicht', + 'On, Return detected' => 'Flits werd ontstoken, flits afdwing modus, gereflecteerd flitslicht gedetecteerd', + 'On, Return not detected' => 'Flits werd ontstoken, flits afdwing modus, geen gereflecteerd flitslicht gedetecteerd', + }, + }, + 'FlashCommanderMode' => { + PrintConv => { + 'Off' => 'Uit', + 'On' => 'Aan', + }, + }, + 'FlashCompensation' => 'Flitscorrectie', + 'FlashControlMode' => { + PrintConv => { + 'Manual' => 'Handmatig', + 'Off' => 'Uit', + 'Repeating Flash' => 'Stroboscopisch flitsen', + }, + }, + 'FlashDevice' => { + PrintConv => { + 'None' => 'Geen', + }, + }, + 'FlashEnergy' => 'Flits energie', + 'FlashExposureComp' => 'Flitscompensatie', + 'FlashExposureLock' => { + PrintConv => { + 'Off' => 'Uit', + 'On' => 'Aan', + }, + }, + 'FlashFired' => { + PrintConv => { + 'No' => 'Nee', + 'Yes' => 'Ja', + }, + }, + 'FlashGroupAControlMode' => { + PrintConv => { + 'Manual' => 'Handmatig', + 'Off' => 'Uit', + 'Repeating Flash' => 'Stroboscopisch flitsen', + }, + }, + 'FlashGroupBControlMode' => { + PrintConv => { + 'Manual' => 'Handmatig', + 'Off' => 'Uit', + 'Repeating Flash' => 'Stroboscopisch flitsen', + }, + }, + 'FlashGroupCControlMode' => { + PrintConv => { + 'Manual' => 'Handmatig', + 'Off' => 'Uit', + 'Repeating Flash' => 'Stroboscopisch flitsen', + }, + }, + 'FlashIntensity' => { + PrintConv => { + 'High' => 'Hoog', + 'Normal' => 'Normaal', + }, + }, + 'FlashLevel' => 'Flitscorrectie', + 'FlashMode' => { + PrintConv => { + 'Auto' => 'Automatisch', + 'Normal' => 'Normaal', + 'Off' => 'Uit', + 'On' => 'Aan', + 'Unknown' => 'Onbekend', + }, + }, + 'FlashModel' => { + PrintConv => { + 'None' => 'Geen', + }, + }, + 'FlashOptions' => { + PrintConv => { + 'Auto' => 'Automatisch', + 'Normal' => 'Normaal', + }, + }, + 'FlashOptions2' => { + PrintConv => { + 'Auto' => 'Automatisch', + 'Normal' => 'Normaal', + }, + }, + 'FlashShutterSpeed' => 'Langste sluitertijd bij flits', + 'FlashStatus' => { + PrintConv => { + 'Off' => 'Uit', + }, + }, + 'FlashSyncSpeed' => 'Flitssynchronisatie snelheid', + 'FlashSyncSpeedAv' => { + PrintConv => { + 'Auto' => 'Automatisch', + }, + }, + 'FlashType' => { + PrintConv => { + 'None' => 'Geen', + }, + }, + 'FlashWarning' => { + Description => 'Flitswaarschuwing', + PrintConv => { + 'Off' => 'Uit', + 'On' => 'Aan', + }, + }, + 'FlashpixVersion' => 'Ondersteunde Flashpix versie', + 'FlickerReduce' => { + PrintConv => { + 'Off' => 'Uit', + 'On' => 'Aan', + }, + }, + 'FlipHorizontal' => { + PrintConv => { + 'No' => 'Nee', + 'Yes' => 'Ja', + }, + }, + 'FocalLength' => 'Brandpuntafstand', + 'FocalLength35efl' => 'Brandpuntafstand', + 'FocalLengthIn35mmFormat' => 'Brandpuntafstand in 35 mm kleinbeeld formaat', + 'FocalPlaneResolutionUnit' => { + Description => 'Sensor resolutie eenheid', + PrintConv => { + 'None' => 'Geen', + 'inches' => 'inch', + 'um' => 'µm (micrometer)', + }, + }, + 'FocalPlaneXResolution' => 'Horizontale sensor resolutie', + 'FocalPlaneYResolution' => 'Verticale sensor resolutie', + 'Focus' => { + Description => 'Scherpstelling', + PrintConv => { + 'Manual' => 'Handmatig', + }, + }, + 'FocusArea' => 'Scherpstelveld', + 'FocusAreaSelection' => { + Description => 'Doorloop scherpstelpunt', + PrintConv => { + 'No Wrap' => 'Geen doorloop', + 'Wrap' => 'Doorloop', + }, + }, + 'FocusContinuous' => { + PrintConv => { + 'Continuous' => 'Continu', + 'Manual' => 'Handmatig', + }, + }, + 'FocusMode' => { + Description => 'Focus modus', + PrintConv => { + 'Auto' => 'Automatisch', + 'Continuous' => 'Continu', + 'Manual' => 'Handmatig', + 'Normal' => 'Normaal', + }, + }, + 'FocusMode2' => { + PrintConv => { + 'Manual' => 'Handmatig', + }, + }, + 'FocusModeSetting' => { + Description => 'Scherpstelstand', + PrintConv => { + 'AF-A' => 'Automatische AF', + 'AF-C' => 'Continue AF', + 'AF-S' => 'Enkelvoudige AF', + 'Manual' => 'Handmatig', + }, + }, + 'FocusPointWrap' => { + Description => 'Doorloop scherpstelpunt', + PrintConv => { + 'No Wrap' => 'Geen doorloop', + 'Wrap' => 'Doorloop', + }, + }, + 'FocusRange' => { + PrintConv => { + 'Auto' => 'Automatisch', + 'Manual' => 'Handmatig', + 'Normal' => 'Normaal', + }, + }, + 'FocusTrackingLockOn' => { + Description => 'Focus Tracking met Lock-On', + PrintConv => { + 'Long' => 'Lang', + 'Normal' => 'Normaal', + 'Off' => 'Uit', + 'Short' => 'Kort', + }, + }, + 'FrameRate' => 'Beeldwisselsnelheid', + 'FrameSize' => 'Beeldformaat', + 'FreeByteCounts' => 'Aantal bytes van het lege databereik', + 'FreeOffsets' => 'Vrije data posities', + 'FujiFlashMode' => { + PrintConv => { + 'Auto' => 'Automatisch', + }, + }, + 'FunctionButton' => { + Description => 'FUNC. knop', + PrintConv => { + 'AF-area Mode' => 'AF-veldstand', + 'Center AF Area' => 'Centrale AF-veld', + 'Center-weighted' => 'Centrumgericht', + 'FV Lock' => 'FV-vergrendeling', + 'Flash Off' => 'Flitser uit', + 'Framing Grid' => 'Rasterweergave', + 'ISO Display' => 'ISO-weergave', + 'Matrix Metering' => 'Matrixmeting', + 'Spot Metering' => 'Spotmeting', + }, + }, + 'GIFVersion' => 'GIF versie', + 'GPSAltitude' => 'Hoogte', + 'GPSAltitudeRef' => { + Description => 'Hoogte referentie', + PrintConv => { + 'Above Sea Level' => 'Zee spiegel', + 'Below Sea Level' => 'Zee spiegel referentie (negatieve waarde)', + }, + }, + 'GPSAreaInformation' => 'Naam van het GPS gebied', + 'GPSDOP' => 'Meet nauwkeurigheid', + 'GPSDateStamp' => 'GPS datum', + 'GPSDateTime' => 'GPS tijd (atoomklok)', + 'GPSDestBearing' => 'Motiefrichting', + 'GPSDestBearingRef' => { + Description => 'Referentie voor de motiefrichting', + PrintConv => { + 'Magnetic North' => 'Magnetische uitrichting', + 'True North' => 'Geografische uitrichting', + }, + }, + 'GPSDestDistance' => 'Afstand tot bestemming', + 'GPSDestDistanceRef' => { + Description => 'Referentie voor de afstand tot de bestemming', + PrintConv => { + 'Miles' => 'Mijlen', + 'Nautical Miles' => 'Knopen', + }, + }, + 'GPSDestLatitude' => 'Breedte van het doel', + 'GPSDestLatitudeRef' => { + Description => 'Referentie voor de breedte van het doel', + PrintConv => { + 'North' => 'Noordelijke breedte', + 'South' => 'Zuidelijke breedte', + }, + }, + 'GPSDestLongitude' => 'Lengtegraad van het doel', + 'GPSDestLongitudeRef' => { + Description => 'Referentie voor de lengte van het doel', + PrintConv => { + 'East' => 'Oostelijke lengte', + 'West' => 'Westlijke lengte', + }, + }, + 'GPSDifferential' => { + Description => 'GPS differentiaal correctie', + PrintConv => { + 'Differential Corrected' => 'Differentiaal correctie toegepast', + 'No Correction' => 'Meting zonder differentiaal correctie', + }, + }, + 'GPSImgDirection' => 'Richting van de afbeelding', + 'GPSImgDirectionRef' => { + Description => 'Referentie voor de uitrichting van de afbeelding', + PrintConv => { + 'Magnetic North' => 'Magnetische uitrichting', + 'True North' => 'Geografische uitrichting', + }, + }, + 'GPSInfo' => 'GPS Info IFD-wijzer', + 'GPSLatitude' => 'Breedte graad', + 'GPSLatitudeRef' => { + Description => 'Noord. of zuid. breedte', + PrintConv => { + 'North' => 'Noordelijke breedte', + 'South' => 'Zuidlijke breedte', + }, + }, + 'GPSLongitude' => 'Geografische lengte', + 'GPSLongitudeRef' => { + Description => 'Oost. of west. lengte', + PrintConv => { + 'East' => 'Oostlijke lengte', + 'West' => 'Westlijke lengte', + }, + }, + 'GPSMapDatum' => 'Geodatische datum', + 'GPSMeasureMode' => { + Description => 'GPS meet methode', + PrintConv => { + '2-D' => '2 dimensionale meting', + '2-Dimensional' => '2 dimensionale meting', + '2-Dimensional Measurement' => '2 dimensionale meting', + '3-D' => '3 dimensionale meting', + '3-Dimensional' => '3 dimensionale meting', + '3-Dimensional Measurement' => '3 dimensionale meting', + }, + }, + 'GPSProcessingMethod' => 'Naam van de GPS verwerk methode', + 'GPSSatellites' => 'Voor de meting gebruikte satellieten', + 'GPSSpeed' => 'Snelheid van de GPS ontvanger', + 'GPSSpeedRef' => { + Description => 'Snelheids eenheid', + PrintConv => { + 'km/h' => 'Kilometer per uur', + 'knots' => 'Knopen', + 'mph' => 'Mijl per uur', + }, + }, + 'GPSStatus' => { + Description => 'GPS ontvanger status', + PrintConv => { + 'Measurement Active' => 'Meting loopt', + 'Measurement Void' => 'Interoperabiliteit voor metingen', + }, + }, + 'GPSTimeStamp' => 'GPS tijd (atoomklok)', + 'GPSTrack' => 'Bewegingsrichting', + 'GPSTrackRef' => { + Description => 'Referentie voor de bewegingsrichting', + PrintConv => { + 'Magnetic North' => 'Magnetische uitrichting', + 'True North' => 'Geographische uitrichting', + }, + }, + 'GPSVersionID' => 'GPS tag versie', + 'GainControl' => { + Description => 'Belichtingsversterking', + PrintConv => { + 'High gain down' => 'Hoge helderheidsverminderring', + 'High gain up' => 'Hoge helderheidsvesterking', + 'Low gain down' => 'Kleine helderheidsverminderring', + 'Low gain up' => 'Kleine helderheidsvesterking', + 'None' => 'Geen', + }, + }, + 'Gapless' => { + PrintConv => { + 'No' => 'Nee', + 'Yes' => 'Ja', + }, + }, + 'Gradation' => 'Levendig', + 'GrayResponseUnit' => { + PrintConv => { + '0.0001' => 'Nummer stelt een 1000ste van een eenheid voor', + '0.001' => 'Nummer stelt een 100ste van een eenheid voor', + '0.1' => 'Nummer stelt een 10de van een eenheid voor', + '1e-05' => 'Nummer stelt een 10000ste van een eenheid voor', + '1e-06' => 'Nummer stelt een 100000ste van een eenheid voor', + }, + }, + 'GrayTRC' => 'Grijze toon reproductie curve', + 'GreenMatrixColumn' => 'Groene matrixkolom', + 'GreenTRC' => 'Groene toon reproductie curve', + 'GridDisplay' => { + Description => 'Rasterweergave in zoeker', + PrintConv => { + 'Off' => 'Uit', + 'On' => 'Aan', + }, + }, + 'HDR' => { + Description => 'Auto HDR', + PrintConv => { + 'Off' => 'Uit', + }, + }, + 'Headline' => 'Opschrift', + 'HeightResolution' => 'Beeldresolutie verticaal', + 'HighISONoiseReduction' => { + Description => 'NR bij hoge-ISO', + PrintConv => { + 'Auto' => 'Automatisch', + 'High' => 'Hi', + 'Low' => 'Laag', + 'Normal' => 'Normaal', + 'Off' => 'Uit', + 'On' => 'Aan', + 'Standard' => 'Standaard', + }, + }, + 'HighlightTonePriority' => { + PrintConv => { + 'Off' => 'Uit', + 'On' => 'Aan', + }, + }, + 'HometownDST' => { + PrintConv => { + 'No' => 'Nee', + 'Yes' => 'Ja', + }, + }, + 'Hue' => 'Kleurtoon', + 'ICCProfile' => 'ICC Profiel', + 'IPTC-NAA' => 'IPTC-NAA metadata', + 'ISO' => 'ISO gevoeligheid', + 'ISOAuto' => 'ISO auto', + 'ISODisplay' => 'ISO-weergave', + 'ISOExpansion' => { + PrintConv => { + 'Off' => 'Uit', + 'On' => 'Aan', + }, + }, + 'ISOExpansion2' => { + PrintConv => { + 'Off' => 'Uit', + }, + }, + 'ISOSetting' => { + PrintConv => { + 'Auto' => 'Automatisch', + 'Manual' => 'Handmatig', + }, + }, + 'ISOSpeedExpansion' => { + PrintConv => { + 'No' => 'Nee', + 'Yes' => 'Ja', + }, + }, + 'ISOSpeedIncrements' => { + Description => 'ISO-stapgrootte', + PrintConv => { + '1 Stop' => '1 stop', + '1/3 Stop' => '1/3 stop', + }, + }, + 'ISOStepSize' => { + Description => 'ISO-stapgrootte', + PrintConv => { + '1 EV' => '1 stop', + '1/2 EV' => '1/2 stop', + '1/3 EV' => '1/3 stop', + }, + }, + 'Illumination' => { + Description => 'Verlichting', + PrintConv => { + 'Off' => 'Uit', + 'On' => 'Aan', + }, + }, + 'ImageAuthentication' => { + PrintConv => { + 'Off' => 'Uit', + }, + }, + 'ImageByteCount' => 'Aantal beeldgegevens in bytes', + 'ImageColorIndicator' => 'Afbeelding kleur indicator', + 'ImageColorValue' => 'Afbeelding kleur waarde', + 'ImageDataDiscard' => { + Description => 'Afgedankte beeldgegevens', + PrintConv => { + 'Flexbits Discarded' => 'Afgedankte flexbits', + 'Full Resolution' => 'Volledige resolutie', + 'HighPass Frequency Data Discarded' => 'Afgedankte hoogdoorlaat frequentiegegevens', + 'Highpass and LowPass Frequency Data Discarded' => 'Afgedankte hoogdoorlaat en laagdoorlaat frequentiegegevens', + }, + }, + 'ImageDescription' => 'Afbeelding beschrijving', + 'ImageDustOff' => { + PrintConv => { + 'Off' => 'Uit', + 'On' => 'Aan', + }, + }, + 'ImageHeight' => 'Afbeeldingshoogte', + 'ImageHistory' => 'Afbeelding geschiedenis', + 'ImageNumber' => 'Afbeelding nummer', + 'ImageOffset' => 'Beeldverplaatsing', + 'ImageOrientation' => { + Description => 'Foto oriëntatie', + PrintConv => { + 'Landscape' => 'Landschap', + 'Portrait' => 'Portret', + 'Square' => 'Vierkant', + }, + }, + 'ImageQuality' => { + Description => 'Bldkwaliteit', + PrintConv => { + 'High' => 'Hoog', + 'Normal' => 'Normaal', + }, + }, + 'ImageQuality2' => 'Bldkwaliteit 2', + 'ImageReview' => { + Description => 'Beeld terugspelen', + PrintConv => { + 'Off' => 'Uit', + 'On' => 'Aan', + }, + }, + 'ImageReviewTime' => 'Timers uit Beeld terugspelen', + 'ImageRotated' => { + PrintConv => { + 'No' => 'Nee', + 'Yes' => 'Ja', + }, + }, + 'ImageSize' => 'Beeldformaat', + 'ImageStabilization' => { + PrintConv => { + 'Off' => 'Uit', + 'On' => 'Aan', + }, + }, + 'ImageTone' => { + PrintConv => { + 'Landscape' => 'Landschap', + 'Portrait' => 'Portret', + }, + }, + 'ImageType' => 'Beeldtype', + 'ImageUniqueID' => 'Uniek afbeeldings ID', + 'ImageWidth' => 'Afbeeldingsbreedte', + 'InitialZoomSetting' => { + Description => 'Aanvankelijke zoominstelling', + PrintConv => { + 'High Magnification' => 'Hoge zoom', + 'Low Magnification' => 'Lage zoom', + 'Medium Magnification' => 'Gemiddelde zoom', + }, + }, + 'Instructions' => 'Instructies', + 'IntellectualGenre' => 'Genre', + 'IntensityStereo' => { + PrintConv => { + 'Off' => 'Uit', + 'On' => 'Aan', + }, + }, + 'InternalFlash' => { + Description => 'Flitssturing ingeb. flitser', + PrintConv => { + 'Commander Mode' => 'Commanderstand', + 'Fired' => 'Flits afgevuurd', + 'Manual' => 'Handmatig', + 'No' => 'Geen flits', + 'Off' => 'Uit', + 'On' => 'Aan', + 'Repeating Flash' => 'Stroboscopisch flitsen', + 'TTL' => 'DDL', + }, + }, + 'InternalFlashMode' => { + PrintConv => { + 'On' => 'Aan', + }, + }, + 'InteropIndex' => { + Description => 'Interoperabiliteits Identificatie', + PrintConv => { + 'R03 - DCF option file (Adobe RGB)' => 'R03: DCF Optie formaat (Adobe RGB)', + 'R98 - DCF basic file (sRGB)' => 'R98: DCF Basis formaat (sRGB)', + 'THM - DCF thumbnail file' => 'THM: DCF Miniatuur formaat', + }, + }, + 'InteropOffset' => 'Interoperabiliteit-tag', + 'InteropVersion' => 'Interoperabiliteits versie', + 'JFIFVersion' => 'JFIF versie', + 'JPEGQuality' => { + Description => 'Beeldkwaliteit', + PrintConv => { + 'Extra Fine' => 'Extra fijn', + 'Fine' => 'Fijn', + 'Standard' => 'Normaal', + }, + }, + 'JobID' => 'ID van baan', + 'Keyword' => 'Trefwoorden', + 'Keywords' => 'Trefwoord', + 'LCDIllumination' => { + Description => 'LCD-verlichting', + PrintConv => { + 'Off' => 'Uit', + 'On' => 'Aan', + }, + }, + 'LCDIlluminationDuringBulb' => { + PrintConv => { + 'Off' => 'Uit', + 'On' => 'Aan', + }, + }, + 'LCHEditor' => { + PrintConv => { + 'Off' => 'Uit', + 'On' => 'Aan', + }, + }, + 'LanguageIdentifier' => 'Taalherkenning', + 'Lens' => 'Objectief', + 'LensInfo' => 'Lensgegevens', + 'LicenseType' => { + PrintConv => { + 'Unknown' => 'Onbekend', + }, + }, + 'LightSource' => { + Description => 'Lichtbron', + PrintConv => { + 'Cloudy' => 'Bewolkt', + 'Cool White Fluorescent' => 'Koel wit TL-licht', + 'Day White Fluorescent' => 'Daglicht wit TL-licht', + 'Daylight' => 'Daglicht', + 'Daylight Fluorescent' => 'Daglicht TL-licht', + 'Fine Weather' => 'Onbewolkt', + 'Flash' => 'Flits', + 'Fluorescent' => 'Fluoresceren', + 'ISO Studio Tungsten' => 'ISO studio kunstlicht (gloeilamp)', + 'Other' => 'Andere lichtbron', + 'Shade' => 'Schaduw', + 'Standard Light A' => 'Standaard licht A', + 'Standard Light B' => 'Standaard licht B', + 'Standard Light C' => 'Standaard licht C', + 'Tungsten (Incandescent)' => 'Kunstlicht (gloeilamp)', + 'Unknown' => 'Onbekend', + 'Warm White Fluorescent' => 'Warm wit TL-licht', + 'White Fluorescent' => 'Wit TL-licht', + }, + }, + 'LightSourceSpecial' => { + PrintConv => { + 'Off' => 'Uit', + 'On' => 'Aan', + }, + }, + 'Lightness' => 'Helderheid', + 'Lit' => { + PrintConv => { + 'No' => 'Nee', + 'Yes' => 'Ja', + }, + }, + 'LiveViewShooting' => { + PrintConv => { + 'Off' => 'Uit', + 'On' => 'Aan', + }, + }, + 'Location' => 'Lokatie', + 'LongExposureNoiseReduction' => { + Description => 'NR lang-belicht', + PrintConv => { + 'Auto' => 'Automatisch', + 'Off' => 'Uit', + 'On' => 'Aan', + }, + }, + 'LoopStyle' => { + PrintConv => { + 'Normal' => 'Normaal', + }, + }, + 'LuminanceNoiseReduction' => { + PrintConv => { + 'High' => 'Hoog', + 'Low' => 'Laag', + 'Off' => 'Uit', + }, + }, + 'MB-D10Batteries' => 'MB-D10 batterijen', + 'MB-D10BatteryType' => 'MB-D10 batterijen', + 'MB-D80Batteries' => 'MB-D80 batterijen', + 'MIEVersion' => 'MIE versie', + 'MSStereo' => { + PrintConv => { + 'Off' => 'Uit', + 'On' => 'Aan', + }, + }, + 'Macro' => { + PrintConv => { + 'Manual' => 'Handmatig', + 'Normal' => 'Normaal', + 'Off' => 'Uit', + 'On' => 'Aan', + }, + }, + 'MacroMode' => { + PrintConv => { + 'Normal' => 'Normaal', + 'Off' => 'Uit', + 'On' => 'Aan', + }, + }, + 'MainDialExposureComp' => { + Description => 'Main Dial Belichtingscorrectie', + PrintConv => { + 'Off' => 'Uit', + 'On' => 'Aan', + }, + }, + 'Make' => 'Fabrikant', + 'MakeAndModel' => 'Producent en model', + 'MakerNote' => 'Fabrikant informatie', + 'MakerNotes' => 'Wenken van de fabrikant', + 'ManualFlashOutput' => { + Description => 'Ingebouwde flitser Handmatig Sterkte', + PrintConv => { + 'Low' => 'Laag', + }, + }, + 'MasterDocumentID' => 'ID van hoofddocument', + 'MaxAperture' => 'Maximale lensopening', + 'MaxApertureValue' => 'Grootste diafragma', + 'MaxContinuousRelease' => 'Max. aant. continuopnamen', + 'MaxSampleValue' => 'Max sample waarde', + 'MediaBlackPoint' => 'Media zwartpunt', + 'MediaType' => { + PrintConv => { + 'Normal' => 'Normaal', + }, + }, + 'MediaWhitePoint' => 'Media Witpunt', + 'Metering' => { + Description => 'Lichtmeting', + PrintConv => { + 'Center-weighted' => 'Centrumgericht', + 'Matrix' => 'Matrixmeting', + }, + }, + 'MeteringMode' => { + Description => 'Belichting meet methode', + PrintConv => { + 'Average' => 'Gemiddeld', + 'Center-weighted average' => 'Centrum gemiddelde', + 'Multi-segment' => 'Multi segment', + 'Multi-spot' => 'MultiSpot', + 'Other' => 'Andere', + 'Partial' => 'Gedeelte', + 'Unknown' => 'Onbekend', + }, + }, + 'MeteringMode2' => { + PrintConv => { + 'Multi-segment' => 'Multi segment', + }, + }, + 'MeteringMode3' => { + PrintConv => { + 'Multi-segment' => 'Multi segment', + }, + }, + 'MeteringTime' => { + Description => 'Timers uit Belichtingsmeters', + PrintConv => { + 'No Limit' => 'Altijd aan', + }, + }, + 'MinSampleValue' => 'Min sample waarde', + 'MinoltaQuality' => { + PrintConv => { + 'Normal' => 'Normaal', + 'Standard' => 'Standaard', + }, + }, + 'Model' => 'Camera model', + 'Model2' => 'Camera model (2)', + 'ModelingFlash' => { + Description => 'Instellicht', + PrintConv => { + 'Off' => 'Uit', + 'On' => 'Aan', + }, + }, + 'ModifiedPictureStyle' => { + PrintConv => { + 'Landscape' => 'Landschap', + 'None' => 'Geen', + 'Portrait' => 'Portret', + 'Standard' => 'Standaard', + }, + }, + 'ModifiedSaturation' => { + PrintConv => { + 'Off' => 'Uit', + }, + }, + 'ModifiedSharpnessFreq' => { + PrintConv => { + 'High' => 'Hoog', + 'Low' => 'Laag', + 'Standard' => 'Standaard', + }, + }, + 'ModifiedToneCurve' => { + PrintConv => { + 'Manual' => 'Handmatig', + 'Standard' => 'Standaard', + }, + }, + 'ModifiedWhiteBalance' => { + PrintConv => { + 'Auto' => 'Automatisch', + 'Cloudy' => 'Bewolkt', + 'Daylight' => 'Daglicht', + 'Daylight Fluorescent' => 'Daglicht TL-licht', + 'Flash' => 'Flits', + 'Fluorescent' => 'Fluoresceren', + 'Shade' => 'Schaduw', + 'Tungsten' => 'Kunstlicht (gloeilamp)', + }, + }, + 'ModifyDate' => 'Datum bestand wijziging', + 'MoireFilter' => { + PrintConv => { + 'Off' => 'Uit', + 'On' => 'Aan', + }, + }, + 'MonitorOffTime' => 'Monitor uit', + 'MonochromeFilterEffect' => { + PrintConv => { + 'None' => 'Geen', + }, + }, + 'MonochromeLinear' => { + PrintConv => { + 'No' => 'Nee', + 'Yes' => 'Ja', + }, + }, + 'MonochromeToningEffect' => { + PrintConv => { + 'None' => 'Geen', + }, + }, + 'MultiExposureAutoGain' => { + PrintConv => { + 'Off' => 'Uit', + 'On' => 'Aan', + }, + }, + 'MultiExposureMode' => { + PrintConv => { + 'Off' => 'Uit', + }, + }, + 'MultiFrameNoiseReduction' => { + Description => 'Ruisond. Multi Frame', + PrintConv => { + 'Off' => 'Uit', + 'On' => 'Aan', + }, + }, + 'MultiSelector' => { + Description => 'Multi-selector', + PrintConv => { + 'Do Nothing' => 'Doe niets', + 'Reset Meter-off Delay' => 'Activeer lichtmeter', + }, + }, + 'MultiSelectorPlaybackMode' => { + Description => 'Centrale knop multiselector Weergavestand', + PrintConv => { + 'Choose Folder' => 'Map selecteren', + 'Thumbnail On/Off' => 'Miniatuur aan/uit', + 'View Histograms' => 'Histogrammen weergeven', + 'Zoom On/Off' => 'Zoom aan/uit', + }, + }, + 'MultiSelectorShootMode' => { + Description => 'Centrale knop multiselector Opnamestand', + PrintConv => { + 'Highlight Active Focus Point' => 'Actieve AF-punt markeren', + 'Not Used' => 'Geen functie', + 'Select Center Focus Point' => 'Middelste AF-punt selecteren', + }, + }, + 'MultipleExposureSet' => { + PrintConv => { + 'Off' => 'Uit', + 'On' => 'Aan', + }, + }, + 'Mute' => { + PrintConv => { + 'Off' => 'Uit', + 'On' => 'Aan', + }, + }, + 'MyColorMode' => { + PrintConv => { + 'Off' => 'Uit', + }, + }, + 'NDFilter' => { + PrintConv => { + 'Off' => 'Uit', + 'On' => 'Aan', + }, + }, + 'NEFCompression' => { + PrintConv => { + 'Uncompressed' => 'Niet gecomprimeerd', + }, + }, + 'NikonImageSize' => 'Beeldformaat', + 'NoMemoryCard' => { + Description => 'Geen geheugenkaart', + PrintConv => { + 'Enable Release' => 'Ontgrendel ontspanknop', + 'Release Locked' => 'Vergrendel ontspanknop', + }, + }, + 'Noise' => 'Ruis', + 'NoiseFilter' => { + PrintConv => { + 'High' => 'Hoog', + 'Low' => 'Laag', + 'Off' => 'Uit', + 'Standard' => 'Standaard', + }, + }, + 'NoiseReduction' => { + Description => 'Ruisreductie', + PrintConv => { + 'Auto' => 'Automatisch', + 'Normal' => 'Normaal', + 'Off' => 'Uit', + 'On' => 'Aan', + 'Standard' => 'Standaard', + }, + }, + 'ObjectAttributeReference' => 'Intellectuele genre', + 'ObjectCycle' => { + Description => 'Objectcyclus', + PrintConv => { + 'Both Morning and Evening' => 'Beide', + 'Evening' => 'Avond', + 'Morning' => 'Ochtend', + }, + }, + 'ObjectFileType' => { + PrintConv => { + 'None' => 'Geen', + 'Unknown' => 'Onbekend', + }, + }, + 'ObjectName' => 'Titel', + 'ObjectPreviewData' => 'Voorvertoning objectgegevens', + 'ObjectPreviewFileFormat' => 'Voorvertoning objectgegevens bestandsformaat', + 'ObjectPreviewFileVersion' => 'Voorvertoning objectgegevens bestandsformaatversie', + 'ObjectTypeReference' => 'Referentie van Object type', + 'OldSubfileType' => 'Subbestand type', + 'OneTouchWB' => { + PrintConv => { + 'Off' => 'Uit', + }, + }, + 'OpticalZoomMode' => { + PrintConv => { + 'Standard' => 'Standaard', + }, + }, + 'OpticalZoomOn' => { + PrintConv => { + 'Off' => 'Uit', + 'On' => 'Aan', + }, + }, + 'Opto-ElectricConvFactor' => 'Opto elektronische omreken factor', + 'Orientation' => { + Description => 'Oriëntatie van de afbeelding', + PrintConv => { + 'Horizontal (normal)' => '0° (boven/links)', + 'Mirror horizontal' => 'Horizontaal gespiegeld', + 'Mirror horizontal and rotate 270 CW' => 'Spiegel horizontaal en draai 270° met de klok mee', + 'Mirror horizontal and rotate 90 CW' => 'Spiegel horizontaal en draai 90° met de klok mee', + 'Mirror vertical' => 'Vertikaal gespiegeld', + 'Rotate 180' => '180° (onder/rechts)', + 'Rotate 270 CW' => 'Draai 270° met de klok mee', + 'Rotate 90 CW' => '90° tegen de klok in (rechts/boven)', + }, + }, + 'OriginalTransmissionReference' => 'Werknummer', + 'OriginatingProgram' => 'Oorspronkelijk programma', + 'OwnerID' => 'ID van eigenaar', + 'PEFVersion' => 'PEF versie', + 'Padding' => 'Plaatshouder', + 'PageName' => 'Pagina naam', + 'PageNumber' => 'Pagina nummer', + 'PhotoEffect' => { + PrintConv => { + 'Off' => 'Uit', + }, + }, + 'PhotoEffects' => { + PrintConv => { + 'Off' => 'Uit', + 'On' => 'Aan', + }, + }, + 'PhotoEffectsType' => { + PrintConv => { + 'None' => 'Geen', + }, + }, + 'PhotoInfoPlayback' => { + Description => 'Functie van multi-selector', + PrintConv => { + 'Info Left-right, Playback Up-down' => 'Info <> / Foto’s', + 'Info Up-down, Playback Left-right' => 'Info / Foto’s <>', + }, + }, + 'PhotometricInterpretation' => { + Description => 'Pixel schema', + PrintConv => { + 'BlackIsZero' => 'Zwart is nul', + 'Color Filter Array' => 'CFA (Kleur Filter Matrix)', + 'Pixar LogL' => 'CIE Log2(L) (Log Luminantie)', + 'Pixar LogLuv' => 'CIE Log2(L)(u\',v\') (Log Luminantie en Chrominantie)', + 'RGB Palette' => 'RGB palet', + 'Transparency Mask' => 'Transparent masker', + 'WhiteIsZero' => 'Wit is nul', + }, + }, + 'PhotoshopFormat' => { + PrintConv => { + 'Standard' => 'Standaard', + }, + }, + 'PictureControl' => { + PrintConv => { + 'Off' => 'Uit', + 'On' => 'Aan', + }, + }, + 'PictureControlActive' => { + PrintConv => { + 'Off' => 'Uit', + 'On' => 'Aan', + }, + }, + 'PictureFinish' => { + PrintConv => { + 'Portrait' => 'Portret', + }, + }, + 'PictureMode' => { + PrintConv => { + 'Aperture-priority AE' => 'Diafragmaprioriteit', + 'Auto' => 'Automatisch', + 'Landscape' => 'Landschap', + 'Manual' => 'Handmatig', + 'Portrait' => 'Portret', + 'Shutter speed priority AE' => 'Sluiterprioriteit', + 'Standard' => 'Standaard', + }, + }, + 'PictureMode2' => { + PrintConv => { + 'Aperture Priority' => 'Diafragmaprioriteit', + 'Manual' => 'Handmatig', + 'Shutter Speed Priority' => 'Sluiterprioriteit', + }, + }, + 'PictureStyle' => { + PrintConv => { + 'Landscape' => 'Landschap', + 'None' => 'Geen', + 'Portrait' => 'Portret', + 'Standard' => 'Standaard', + }, + }, + 'PixelFormat' => 'Pixelformaat', + 'PixelUnits' => { + PrintConv => { + 'Unknown' => 'Onbekend', + }, + }, + 'PlanarConfiguration' => { + Description => 'Afbeelding data arrangement', + PrintConv => { + 'Chunky' => 'Chunky Formaat (Interleaved)', + 'Planar' => 'Planar Formaat', + }, + }, + 'Predictor' => { + PrintConv => { + 'Horizontal differencing' => 'Horizontale differencering', + 'None' => 'Geen prodictor schema in gebruik', + }, + }, + 'PreviewColorSpace' => { + PrintConv => { + 'Unknown' => 'Onbekend', + }, + }, + 'PreviewImage' => 'Voorbeeld', + 'PreviewImageValid' => { + PrintConv => { + 'No' => 'Nee', + 'Yes' => 'Ja', + }, + }, + 'PreviewQuality' => { + PrintConv => { + 'Normal' => 'Normaal', + }, + }, + 'PrimaryChromaticities' => 'Chromaticiteit van primaire kleuren', + 'PrimaryPlatform' => 'Primaire platform', + 'ProcessingSoftware' => 'Verwerkingssoftware', + 'ProductID' => 'Produkt ID', + 'ProfileCMMType' => 'Profiel CMM-type', + 'ProfileClass' => { + Description => 'Profielklasse', + PrintConv => { + 'Abstract Profile' => 'Abstractprofiel', + 'ColorSpace Conversion Profile' => 'Kleurenruimteprofiel', + 'DeviceLink Profile' => 'Apparaatverbindingsprofiel', + 'Display Device Profile' => 'Beeldschermapparaatprofiel', + 'Input Device Profile' => 'Invoerapparaatprofiel', + 'NamedColor Profile' => 'Genoemd kleurenprofiel', + 'Nikon Input Device Profile (NON-STANDARD!)' => 'Nikonprofiel ("nkpf")', + 'Output Device Profile' => 'Uitvoerapparaatprofiel', + }, + }, + 'ProfileConnectionSpace' => 'Profielconnectieruimte', + 'ProfileCopyright' => 'Profielcopyright', + 'ProfileCreator' => 'Profielproducent', + 'ProfileDateTime' => 'Datum 1e aanmaak profiel', + 'ProfileDescription' => 'Profielbeschrijving', + 'ProfileDescriptionML' => 'Profielbeschrijving ML', + 'ProfileFileSignature' => 'Profiel filekenmerk', + 'ProfileID' => 'Profiel-ID', + 'ProfileSequenceDesc' => 'Profielvolgorde beschrijving', + 'ProfileVersion' => 'Profielversie', + 'ProgramLine' => { + PrintConv => { + 'Normal' => 'Normaal', + }, + }, + 'ProgramMode' => { + PrintConv => { + 'None' => 'Geen', + 'Portrait' => 'Portret', + }, + }, + 'ProgramVersion' => 'Programmaversie', + 'Province-State' => 'Provincie', + 'Quality' => { + Description => 'Beeldkwaliteit', + PrintConv => { + 'Compressed RAW' => 'cRAW', + 'Compressed RAW + JPEG' => 'cRAW+JPEG', + 'Extra Fine' => 'Extra fijn', + 'Fine' => 'Fijn', + 'High' => 'Hoog', + 'Low' => 'Laag', + 'Normal' => 'Normaal', + 'RAW + JPEG' => 'RAW+JPEG', + 'Standard' => 'Standaard', + }, + }, + 'QualityMode' => { + PrintConv => { + 'Normal' => 'Normaal', + }, + }, + 'QuickShot' => { + PrintConv => { + 'Off' => 'Uit', + 'On' => 'Aan', + }, + }, + 'RAFVersion' => 'RAF versie', + 'RasterizedCaption' => 'Gerasterde titel', + 'Rating' => 'Waardering', + 'RatingPercent' => 'Waardering in procent', + 'RawDevAutoGradation' => { + PrintConv => { + 'Off' => 'Uit', + 'On' => 'Aan', + }, + }, + 'RawJpgQuality' => { + PrintConv => { + 'Normal' => 'Normaal', + }, + }, + 'RecordMode' => { + Description => 'Opnamemodus', + PrintConv => { + 'Aperture Priority' => 'Diafragmaprioriteit', + 'Manual' => 'Handmatig', + 'Shutter Priority' => 'Sluiterprioriteit', + }, + }, + 'RecordingMode' => { + PrintConv => { + 'Auto' => 'Automatisch', + 'Landscape' => 'Landschap', + 'Manual' => 'Handmatig', + 'Portrait' => 'Portret', + }, + }, + 'RedEyeCorrection' => { + PrintConv => { + 'Automatic' => 'Automatisch', + 'Off' => 'Uit', + }, + }, + 'RedEyeReduction' => { + PrintConv => { + 'Off' => 'Uit', + 'On' => 'Aan', + }, + }, + 'RedMatrixColumn' => 'Rode matrixkolom', + 'RedTRC' => 'Rode toon reproductie curve', + 'ReferenceBlackWhite' => 'Zwart/wit referentie punten', + 'ReferenceDate' => 'Referentiedatum', + 'ReferenceNumber' => 'Referentienummer', + 'ReferenceService' => 'Referentieservice', + 'RelatedImageFileFormat' => 'Bestandsformaat van de afbeelding', + 'RelatedImageHeight' => 'Afbeeldingshoogte', + 'RelatedImageWidth' => 'Afbeeldingsbreedte', + 'RelatedSoundFile' => 'Bijbehorend audio bestand', + 'ReleaseButtonToUseDial' => { + Description => 'Knop loslaten voor instelsch.', + PrintConv => { + 'No' => 'Nee', + 'Yes' => 'Ja', + }, + }, + 'ReleaseDate' => 'Datum van vrijgave', + 'ReleaseTime' => 'Tijdstip van vrijgave', + 'RemoteOnDuration' => 'Afstandsbediening', + 'RenderingIntent' => { + Description => 'Rendermethode', + PrintConv => { + 'ICC-Absolute Colorimetric' => 'Absoluut colorimetrisch', + 'Media-Relative Colorimetric' => 'Relatieve colorimetrisch', + 'Perceptual' => 'Waarnemend', + 'Saturation' => 'Verzadiging', + }, + }, + 'RepeatingFlashCount' => 'Stroboscopisch flitsen Aantal', + 'RepeatingFlashOutput' => 'Stroboscopisch flitsen Sterkte', + 'RepeatingFlashRate' => 'Stroboscopisch flitsen Freq.', + 'ResampleParamsQuality' => { + PrintConv => { + 'High' => 'Hoog', + 'Low' => 'Laag', + }, + }, + 'Resaved' => { + PrintConv => { + 'No' => 'Nee', + 'Yes' => 'Ja', + }, + }, + 'ResolutionUnit' => { + Description => 'Eenheid van de X und Y resolutie', + PrintConv => { + 'None' => 'Geen', + 'cm' => 'centimeter', + }, + }, + 'RetouchHistory' => { + PrintConv => { + 'None' => 'Geen', + }, + }, + 'ReverseIndicators' => 'Aanduidingen omkeren', + 'Rotation' => { + PrintConv => { + 'Horizontal' => '0° (boven/links)', + 'Horizontal (Normal)' => '0° (boven/links)', + 'Horizontal (normal)' => '0° (boven/links)', + 'Rotate 180' => '180° (onder/rechts)', + 'Rotate 270 CW' => 'Draai 270° met de klok mee', + 'Rotate 90 CW' => '90° tegen de klok in (rechts/boven)', + 'Rotated 180' => '180° (onder/rechts)', + 'Rotated 270 CW' => 'Draai 270° met de klok mee', + 'Rotated 90 CW' => '90° tegen de klok in (rechts/boven)', + }, + }, + 'RowsPerStrip' => 'Aantal lijnen in de afbeelding', + 'SPIFFVersion' => 'SPIFF versie', + 'SRActive' => { + PrintConv => { + 'No' => 'Nee', + 'Yes' => 'Ja', + }, + }, + 'SVGVersion' => 'SVG versie', + 'SampleFormat' => { + Description => 'Sample Formaat', + PrintConv => { + 'Complex int' => 'Complexe integer', + 'Float' => 'Drijvende komma waarde', + 'Signed' => 'Integer met voorteken', + 'Undefined' => 'Niet gedefinierd', + 'Unsigned' => 'Integer zonder voorteken', + }, + }, + 'SamplesPerPixel' => 'Aantal van de componenten', + 'Saturation' => { + Description => 'Kleurverzadiging', + PrintConv => { + 'High' => 'Hoge kleurvezadiging', + 'Low' => 'Lage kleurverzadiging', + 'Normal' => 'Normaal', + }, + }, + 'ScanImageEnhancer' => { + PrintConv => { + 'Off' => 'Uit', + 'On' => 'Aan', + }, + }, + 'SceneCaptureType' => { + Description => 'Scene opname type', + PrintConv => { + 'Landscape' => 'Landschap', + 'Night' => 'Nachtscene', + 'Portrait' => 'Portret', + 'Standard' => 'Standaard', + }, + }, + 'SceneMode' => { + Description => 'Scènekeuze', + PrintConv => { + '3D Sweep Panorama' => '3D', + 'Anti Motion Blur' => 'Anti-bewegingswaas', + 'Aperture Priority' => 'Diafragmaprioriteit', + 'Auto' => 'Automatisch', + 'Cont. Priority AE' => 'Continuvoork. AE', + 'Handheld Night Shot' => 'Nachtopname uit hand', + 'Landscape' => 'Landschap', + 'Manual' => 'Handmatig', + 'Night Portrait' => 'Nachtportret', + 'Night Scene' => 'Nacht', + 'Night View/Portrait' => 'Nacht/portret', + 'Normal' => 'Normaal', + 'Off' => 'Uit', + 'Portrait' => 'Portret', + 'Shutter Priority' => 'Sluiterprioriteit', + 'Sports' => 'Sportactie', + 'Standard' => 'Standaard', + 'Sunset' => 'Zonsondergang', + 'Sweep Panorama' => 'Panorama d. beweg.', + }, + }, + 'SceneModeUsed' => { + PrintConv => { + 'Aperture Priority' => 'Diafragmaprioriteit', + 'Landscape' => 'Landschap', + 'Manual' => 'Handmatig', + 'Portrait' => 'Portret', + 'Shutter Priority' => 'Sluiterprioriteit', + }, + }, + 'SceneSelect' => { + PrintConv => { + 'Night' => 'Nachtscene', + 'Off' => 'Uit', + }, + }, + 'SceneType' => { + Description => 'Scene type', + PrintConv => { + 'Directly photographed' => 'Direkt opgenomen afbeelding', + }, + }, + 'SecurityClassification' => { + Description => 'Veiligheid classificering', + PrintConv => { + 'Confidential' => 'Vertrouwelijk', + 'Restricted' => 'Begrensd', + 'Secret' => 'Geheim', + 'Top Secret' => 'Streng geheim', + 'Unclassified' => 'Niet geclassificeerd', + }, + }, + 'SelfTimer' => { + PrintConv => { + 'Off' => 'Uit', + 'On' => 'Aan', + }, + }, + 'SelfTimerMode' => 'Zelfontspanner mode', + 'SelfTimerTime' => 'Vertraging zelfontspanner', + 'SensingMethod' => { + Description => 'Meet methode', + PrintConv => { + 'Color sequential area' => 'Color sequential area sensor', + 'Color sequential linear' => 'Kleur sequentiële lineaire sensor', + 'Monochrome area' => 'Monochrome sensor', + 'Monochrome linear' => 'Monochrome lineaire sensor', + 'Not defined' => 'Niet gedefineerd', + 'One-chip color area' => 'Één chip kleur sensor', + 'Three-chip color area' => 'Drie chip kleur sensor', + 'Trilinear' => 'Trilineaire sensor', + 'Two-chip color area' => 'Twee chip kleur sensor', + }, + }, + 'SequentialShot' => { + PrintConv => { + 'None' => 'Geen', + 'Standard' => 'Standaard', + }, + }, + 'SerialNumber' => 'Camera-ID', + 'ServiceIdentifier' => 'Service ID', + 'SetButtonCrossKeysFunc' => { + PrintConv => { + 'Normal' => 'Normaal', + }, + }, + 'ShadingCompensation' => { + Description => 'Schaduwcompensatie', + PrintConv => { + 'Off' => 'Uit', + 'On' => 'Aan', + }, + }, + 'ShadingCompensation2' => { + PrintConv => { + 'Off' => 'Uit', + 'On' => 'Aan', + }, + }, + 'ShakeReduction' => { + PrintConv => { + 'Off' => 'Uit', + 'On' => 'Aan', + }, + }, + 'Sharpness' => { + Description => 'Scherpte', + PrintConv => { + 'Hard' => '+', + 'Normal' => 'Normaal', + 'Soft' => 'Zacht', + }, + }, + 'SharpnessFrequency' => { + PrintConv => { + 'High' => 'Hoog', + 'Low' => 'Laag', + 'Standard' => 'Standaard', + }, + }, + 'ShootingInfoDisplay' => { + Description => 'Weergave opname-info', + PrintConv => { + 'Auto' => 'Automatisch', + 'Manual (dark on light)' => 'Handmatig - Donker op licht', + 'Manual (light on dark)' => 'Handmatig - Licht op donker', + }, + }, + 'ShootingMode' => { + Description => 'Opnamestand', + PrintConv => { + 'Aperture Priority' => 'Diafragmaprioriteit', + 'Manual' => 'Handmatig', + 'Normal' => 'Normaal', + 'Portrait' => 'Portret', + 'Shutter Priority' => 'Sluiterprioriteit', + }, + }, + 'ShootingModeSetting' => { + Description => 'Opnamestand', + PrintConv => { + 'Continuous' => 'Continu', + 'Delayed Remote' => 'Vertraagd op afstand', + 'Quick-response Remote' => 'Direct op afstand', + 'Self-timer' => 'Zelfontspanner', + 'Single Frame' => 'Enkel beeld', + }, + }, + 'ShortDocumentID' => 'Korte foto ID', + 'ShutterMode' => { + PrintConv => { + 'Aperture Priority' => 'Diafragmaprioriteit', + 'Auto' => 'Automatisch', + }, + }, + 'ShutterReleaseButtonAE-L' => { + Description => 'AE-vergr. ontspanknop', + PrintConv => { + 'Off' => 'Uit', + 'On' => 'Aan', + }, + }, + 'ShutterReleaseNoCFCard' => { + PrintConv => { + 'No' => 'Nee', + 'Yes' => 'Ja', + }, + }, + 'ShutterSpeed' => 'Belichtingstijd', + 'ShutterSpeedValue' => 'Belichtingstijd', + 'SimilarityIndex' => 'Fotogelijkheidsindex', + 'SlideShow' => { + PrintConv => { + 'No' => 'Nee', + 'Yes' => 'Ja', + }, + }, + 'SlowShutter' => { + PrintConv => { + 'None' => 'Geen', + 'Off' => 'Uit', + 'On' => 'Aan', + }, + }, + 'SlowSync' => { + PrintConv => { + 'Off' => 'Uit', + }, + }, + 'Software' => 'Gebruikte software', + 'Source' => 'Bron', + 'SpatialFrequencyResponse' => 'Spatial frequency response', + 'SpecialEffectsOpticalFilter' => { + PrintConv => { + 'None' => 'Geen', + }, + }, + 'SpecialInstructions' => 'Instructies', + 'SpectralSensitivity' => 'Spectrale gevoeligheid', + 'State' => 'Staat', + 'StripByteCounts' => 'Aantal bytes per gecomprimeerd afbeelding deel', + 'StripOffsets' => 'Positie van afbeelding data', + 'Sub-location' => 'Locatie', + 'SubSecCreateDate' => 'Datum van de originele data generatie', + 'SubSecDateTimeOriginal' => 'Datum van de originele data generatie', + 'SubSecModifyDate' => 'Datum bestand wijziging', + 'SubSecTime' => 'DateTime 1/100 seconden', + 'SubSecTimeDigitized' => 'DateTimeDigitized 1/100 seconden', + 'SubSecTimeOriginal' => 'DateTimeOriginal 1/100 seconden', + 'SubfileType' => 'Nieuw subbestand type', + 'Subject' => 'Onderwerp', + 'SubjectArea' => 'Positie hoofdobject', + 'SubjectDistance' => 'Object afstand', + 'SubjectDistanceRange' => { + Description => 'Objectief afstandsbereik', + PrintConv => { + 'Close' => 'Dichtbij', + 'Distant' => 'Verweg', + 'Unknown' => 'Onbekend', + }, + }, + 'SubjectLocation' => 'Positie hoofdobject', + 'SubjectProgram' => { + PrintConv => { + 'None' => 'Geen', + 'Portrait' => 'Portret', + }, + }, + 'SubjectReference' => 'Onderwerp code', + 'Subsystem' => { + PrintConv => { + 'Unknown' => 'Onbekend', + }, + }, + 'SuperMacro' => { + PrintConv => { + 'Off' => 'Uit', + }, + }, + 'SuperimposedDisplay' => { + PrintConv => { + 'Off' => 'Uit', + 'On' => 'Aan', + }, + }, + 'SupplementalCategories' => 'Aanvullende categorie', + 'T4Options' => 'Opvul bit toegevoegd', + 'T6Options' => 'T6 Opties', + 'Tagged' => { + PrintConv => { + 'No' => 'Nee', + 'Yes' => 'Ja', + }, + }, + 'TargetPrinter' => 'Doel Printer', + 'Technology' => { + Description => 'Technologie', + PrintConv => { + 'Active Matrix Display' => 'Actieve matrixdisplay', + 'Cathode Ray Tube Display' => 'CRT-beeldscherm', + 'Digital Camera' => 'Digitale camera', + 'Dye Sublimation Printer' => 'Dye sublimation printer', + 'Electrophotographic Printer' => 'Laserprinter', + 'Electrostatic Printer' => 'Electrostatische printer', + 'Film Scanner' => 'Filmscanner', + 'Film Writer' => 'Filmprinter', + 'Flexography' => 'Flexografie', + 'Gravure' => 'Fotogravure - koperdiepdruk', + 'Ink Jet Printer' => 'Inkjet printer', + 'Offset Lithography' => 'Offset Lithografie', + 'Passive Matrix Display' => 'Passieve matrixdisplay', + 'Photo CD' => 'Photo-CD', + 'Photo Image Setter' => 'Fotofilmbelichter', + 'Photographic Paper Printer' => 'Fotopapier printer', + 'Projection Television' => 'Projectietelevisie', + 'Reflective Scanner' => 'Reflectieve Scanner', + 'Thermal Wax Printer' => 'Thermische was printer', + 'Video Camera' => 'Videocamera', + 'Video Monitor' => 'Videomonitor', + }, + }, + 'Teleconverter' => { + PrintConv => { + 'None' => 'Geen', + }, + }, + 'TextStamp' => { + PrintConv => { + 'Off' => 'Uit', + 'On' => 'Aan', + }, + }, + 'ThumbnailImage' => 'Miniatuur', + 'ThumbnailImageSize' => 'Thumbnail formaat', + 'TimeCreated' => 'Opnametijdstip', + 'TimeScaleParamsQuality' => { + PrintConv => { + 'High' => 'Hoog', + 'Low' => 'Laag', + }, + }, + 'TimeSent' => 'Tijdstip van zenden', + 'TimerFunctionButton' => { + Description => 'Fn-knop', + PrintConv => { + 'ISO' => 'ISO-gevoeligheid', + 'Image Quality/Size' => 'Bldkwaliteit/-formaat', + 'Self-timer' => 'Zelfontspanner', + 'Shooting Mode' => 'Opnamestand', + 'White Balance' => 'Witbalans', + }, + }, + 'Title' => 'Titel', + 'ToneCurve' => { + PrintConv => { + 'Manual' => 'Handmatig', + 'Standard' => 'Standaard', + }, + }, + 'ToneCurveActive' => { + PrintConv => { + 'No' => 'Nee', + 'Yes' => 'Ja', + }, + }, + 'ToningEffect' => { + PrintConv => { + 'None' => 'Geen', + }, + }, + 'ToningEffectMonochrome' => { + PrintConv => { + 'None' => 'Geen', + }, + }, + 'TransferFunction' => 'Transformatie functie', + 'Transformation' => { + PrintConv => { + 'Horizontal (normal)' => '0° (boven/links)', + 'Mirror horizontal' => 'Horizontaal gespiegeld', + 'Mirror horizontal and rotate 270 CW' => 'Spiegel horizontaal en draai 270° met de klok mee', + 'Mirror horizontal and rotate 90 CW' => 'Spiegel horizontaal en draai 90° met de klok mee', + 'Mirror vertical' => 'Vertikaal gespiegeld', + 'Rotate 180' => '180° (onder/rechts)', + 'Rotate 270 CW' => 'Draai 270° met de klok mee', + 'Rotate 90 CW' => '90° tegen de klok in (rechts/boven)', + }, + }, + 'TransmissionReference' => 'Transmissiereferentie', + 'Trapped' => { + PrintConv => { + 'Unknown' => 'Onbekend', + }, + }, + 'Uncompressed' => { + Description => 'Niet gecomprimeerd', + PrintConv => { + 'No' => 'Nee', + 'Yes' => 'Ja', + }, + }, + 'UniqueDocumentID' => 'Uniek foto ID', + 'UniqueObjectName' => 'Unieke Naam van het Object', + 'Unknown' => 'Onbekend', + 'UnsharpMask' => { + PrintConv => { + 'Off' => 'Uit', + 'On' => 'Aan', + }, + }, + 'Urgency' => { + Description => 'Urgentie', + PrintConv => { + '0 (reserved)' => '0 (Gereserveerd voor toekomstig gebruik)', + '1 (most urgent)' => '1 (zeer dringend)', + '5 (normal urgency)' => '5 (dringend)', + '8 (least urgent)' => '8 (minst dringend)', + '9 (user-defined priority)' => '9 (Gereserveerd voor toekomstig gebruik)', + }, + }, + 'UserComment' => 'Gebruiker kommentaar', + 'UserDef1PictureStyle' => { + PrintConv => { + 'Landscape' => 'Landschap', + 'Portrait' => 'Portret', + 'Standard' => 'Standaard', + }, + }, + 'UserDef2PictureStyle' => { + PrintConv => { + 'Landscape' => 'Landschap', + 'Portrait' => 'Portret', + 'Standard' => 'Standaard', + }, + }, + 'UserDef3PictureStyle' => { + PrintConv => { + 'Landscape' => 'Landschap', + 'Portrait' => 'Portret', + 'Standard' => 'Standaard', + }, + }, + 'VRDVersion' => 'VRD versie', + 'VR_0x66' => { + PrintConv => { + 'Off' => 'Uit', + }, + }, + 'Version' => 'Versie', + 'VibrationReduction' => { + PrintConv => { + 'Off' => 'Uit', + 'On' => 'Aan', + }, + }, + 'ViewfinderWarning' => { + Description => 'Zoekerwaarschuwing', + PrintConv => { + 'Off' => 'Uit', + 'On' => 'Aan', + }, + }, + 'VignetteControl' => { + PrintConv => { + 'High' => 'Hoog', + 'Normal' => 'Normaal', + 'Off' => 'Uit', + 'On' => 'Aan', + }, + }, + 'VoiceMemo' => { + PrintConv => { + 'Off' => 'Uit', + 'On' => 'Aan', + }, + }, + 'WBAdjLighting' => { + PrintConv => { + 'Daylight (direct sunlight)' => 'Daglicht (0)', + 'Daylight (shade)' => 'Daglicht (1)', + 'Daylight (cloudy)' => 'Daglicht (2)', + 'Flash' => 'Flits', + 'None' => 'Geen', + }, + }, + 'WBBracketMode' => { + PrintConv => { + 'Off' => 'Uit', + }, + }, + 'WBFineTuneActive' => { + PrintConv => { + 'No' => 'Nee', + 'Yes' => 'Ja', + }, + }, + 'WBMode' => { + PrintConv => { + 'Auto' => 'Automatisch', + }, + }, + 'WCSProfiles' => 'Windows kleursysteemprofiel', + 'WhiteBalance' => { + Description => 'Witbalans', + PrintConv => { + 'Auto' => 'Automatisch', + 'Black & White' => 'Monochroom', + 'Cloudy' => 'Bewolkt', + 'Color Temperature/Color Filter' => 'Kleurtemperatuur / Kleurfilter', + 'Cool White Fluorescent' => 'Koelwit TL-licht', + 'Custom' => 'Eigen instel.', + 'Custom 1' => 'VOORKEUR 1', + 'Custom 2' => 'VOORKEUR 2', + 'Custom 3' => 'VOORKEUR 3', + 'Custom 4' => 'VOORKEUR 4', + 'Day White Fluorescent' => 'Daglicht wit TL-licht', + 'Daylight' => 'Daglicht', + 'Daylight Fluorescent' => 'Daglicht TL-licht', + 'Flash' => 'Flits', + 'Fluorescent' => 'Fluoresceren', + 'Manual' => 'Handmatig', + 'Shade' => 'Schaduw', + 'Tungsten' => 'Kunstlicht (gloeilamp)', + 'Unknown' => 'Onbekend', + 'Warm White Fluorescent' => 'Warm wit TL-licht', + 'White Fluorescent' => 'Wit TL-licht', + }, + }, + 'WhiteBalance2' => { + PrintConv => { + 'Auto' => 'Automatisch', + }, + }, + 'WhiteBalanceAdj' => { + PrintConv => { + 'Auto' => 'Automatisch', + 'Cloudy' => 'Bewolkt', + 'Daylight' => 'Daglicht', + 'Flash' => 'Flits', + 'Fluorescent' => 'Fluoresceren', + 'Off' => 'Uit', + 'On' => 'Aan', + 'Shade' => 'Schaduw', + 'Tungsten' => 'Kunstlicht (gloeilamp)', + }, + }, + 'WhiteBalanceMode' => { + PrintConv => { + 'Unknown' => 'Onbekend', + }, + }, + 'WhiteBalanceSet' => { + PrintConv => { + 'Auto' => 'Automatisch', + 'Cloudy' => 'Bewolkt', + 'Daylight' => 'Daglicht', + 'Daylight Fluorescent' => 'Daglicht TL-licht', + 'Flash' => 'Flits', + 'Manual' => 'Handmatig', + 'Shade' => 'Schaduw', + 'Tungsten' => 'Kunstlicht (gloeilamp)', + 'White Fluorescent' => 'Warm wit TL-licht', + }, + }, + 'WhitePoint' => 'Wit punt chromaticiteit', + 'WideRange' => { + PrintConv => { + 'Off' => 'Uit', + 'On' => 'Aan', + }, + }, + 'WidthResolution' => 'Beeldresolutie horizontaal', + 'Writer-Editor' => 'Titel/Beschrijving auteur', + 'XMP' => 'XMP metadata', + 'XPAuthor' => 'Auteur', + 'XPComment' => 'Kommentaar', + 'XPKeywords' => 'Trefwoorden', + 'XPSubject' => 'Onderwerp', + 'XPTitle' => 'Titel', + 'XPosition' => 'X positie', + 'XResolution' => 'Horizontale afbeelding resolutie', + 'YCbCrCoefficients' => 'YCbCr coëfficiënt', + 'YCbCrPositioning' => { + Description => 'Y en C positie', + PrintConv => { + 'Centered' => 'Gecentreerd', + 'Co-sited' => 'Naast liggend', + }, + }, + 'YCbCrSubSampling' => 'Subsampling ratio van Y tot C', + 'YPosition' => 'Y positie', + 'YResolution' => 'Vertikale afbeelding resolutie', + 'ZoneMatching' => { + Description => 'Zoneaanpassing', + PrintConv => { + 'High Key' => 'Hi', + 'ISO Setting Used' => 'Uit', + 'Low Key' => 'Lo', + }, + }, + 'ZoneMatchingOn' => { + PrintConv => { + 'Off' => 'Uit', + 'On' => 'Aan', + }, + }, +); + +1; # end + + +__END__ + +=head1 NAME + +Image::ExifTool::Lang::nl.pm - ExifTool Dutch language translations + +=head1 DESCRIPTION + +This file is used by Image::ExifTool to generate localized tag descriptions +and values. + +=head1 AUTHOR + +Copyright 2003-2019, Phil Harvey (phil at owl.phy.queensu.ca) + +This library is free software; you can redistribute it and/or modify it +under the same terms as Perl itself. + +=head1 ACKNOWLEDGEMENTS + +Thanks to Jens Duttke, Peter Moonen, Herman Beld and Peter van der Laan for +providing this translation. + +=head1 SEE ALSO + +L<Image::ExifTool(3pm)|Image::ExifTool>, +L<Image::ExifTool::TagInfoXML(3pm)|Image::ExifTool::TagInfoXML> + +=cut diff --git a/lib/Image/ExifTool/Lang/pl.pm b/lib/Image/ExifTool/Lang/pl.pm new file mode 100644 index 0000000..9ae665e --- /dev/null +++ b/lib/Image/ExifTool/Lang/pl.pm @@ -0,0 +1,1276 @@ +#------------------------------------------------------------------------------ +# File: pl.pm +# +# Description: ExifTool Polish language translations +# +# Notes: This file generated automatically by Image::ExifTool::TagInfoXML +#------------------------------------------------------------------------------ + +package Image::ExifTool::Lang::pl; + +use strict; +use vars qw($VERSION); + +$VERSION = '1.10'; + +%Image::ExifTool::Lang::pl::Translate = ( + 'A100DataOffset' => 'Przesunięcie danych A100', + 'AEAperture' => 'Priorytet AE', + 'AEExposureTime' => 'Czas ekspozycji AE', + 'AEInfo' => 'Informacja o automatycznej ekspozycji', + 'AELock' => { + Description => 'Blokada AE', + PrintConv => { + 'Off' => 'Wyłączona', + 'On' => 'Włączona', + }, + }, + 'AEMeteringMode' => 'Tryb pomiaru AE', + 'AEMeteringSegments' => 'Segmenty pomiaru AE', + 'AEProgramMode' => 'Tryb programu AE', + 'AFAdjustment' => 'Korekta AF', + 'AFInfo' => 'Informacje autofocusa', + 'AFIntegrationTime' => 'Czas integracji AF', + 'AFPoint' => { + PrintConv => { + 'None' => 'Brak', + }, + }, + 'AFPointMode' => 'Tryb Autofokusa', + 'AFPointSelected' => { + Description => 'Wybrany punkt AF', + PrintConv => { + 'Auto' => 'Automatyczny', + 'Automatic Tracking AF' => 'Śledzący AF', + 'Bottom' => 'Dolny', + 'Center' => 'Centralny', + 'Face Detect AF' => 'Wykrywanie twarzy', + 'Fixed Center' => 'Centralny', + 'Left' => 'Lewy', + 'Lower-left' => 'Dolny-lewy', + 'Lower-right' => 'Dolny-prawy', + 'Mid-left' => 'Środek-lewy', + 'Mid-right' => 'Środek-prawy', + 'Right' => 'Prawy', + 'Top' => 'Górny', + 'Upper-left' => 'Górny-lewy', + 'Upper-right' => 'Górny-prawy', + }, + }, + 'AFPointSelected2' => 'Wybrany punkt autofokusa 2', + 'AFPointsInFocus' => { + Description => 'Punkty AF w ostrości', + PrintConv => { + 'Bottom-center' => 'Dolny-centralny', + 'Bottom-left' => 'Dolny-lewy', + 'Bottom-right' => 'Dolny-prawy', + 'Center' => 'Centralny', + 'Fixed Center or Multiple' => 'Centralny lub wiele', + 'Left' => 'Lewy', + 'None' => 'Brak', + 'Right' => 'Prawy', + 'Top-center' => 'Górny-centralny', + 'Top-left' => 'Górny-lewy', + 'Top-right' => 'Górny-prawy', + }, + }, + 'AFPointsSelected' => 'Wybrane punkty AF', + 'AFPredictor' => 'Przewidujący AF', + 'Aperture' => 'Przysłona', + 'ApertureRingUse' => 'Użycie pierścienia przysłony', + 'ApertureValue' => 'Przysłona', + 'Artist' => 'Artysta', + 'Author' => 'Autor', + 'AuthorsPosition' => 'Pozycja autora', + 'AutoAperture' => 'Automatyczna przysłona', + 'AutoBracketing' => 'Bracketing automatyczny', + 'AutoRotate' => { + PrintConv => { + 'None' => 'Brak', + 'Rotate 180' => '180° (dół/prawo)', + 'Rotate 270 CW' => '90° CW (lewo/dół)', + 'Rotate 90 CW' => '90° CCW (prawo/góra)', + }, + }, + 'AvApertureSetting' => 'Ustawienia priorytetu przysłony Av', + 'BadFaxLines' => 'Uszkodzone wiersze transmisji Fax', + 'BannerImageType' => { + PrintConv => { + 'None' => 'Brak', + }, + }, + 'BaseExposureCompensation' => 'Podstawowa kompensacja ekspozycji', + 'BitsPerSample' => 'Liczba bitów na składnik', + 'BlackPoint' => 'Punkt czerni', + 'BlueBalance' => 'Balans niebieskiego', + 'BlurWarning' => { + PrintConv => { + 'None' => 'Brak', + }, + }, + 'BracketShotNumber' => 'Ilość zdjęć w bracketingu', + 'Brightness' => 'Jasność', + 'By-line' => 'Autor', + 'CFAPattern' => 'Wzorzec CFA', + 'CMMFlags' => 'Flagi CMM', + 'CPUFirmwareVersion' => 'Wersja firmware CPU', + 'CPUType' => { + PrintConv => { + 'None' => 'Brak', + }, + }, + 'CalibrationIlluminant1' => { + PrintConv => { + 'Cloudy' => 'Zachmurzone niebo', + 'Cool White Fluorescent' => 'Zimna biała jarzeniówka (W 3800 - 4500K)', + 'Day White Fluorescent' => 'Jarzeniówka z naturalnym białym światłem (N 4600 - 5500K)', + 'Daylight' => 'Światło dzienne', + 'Daylight Fluorescent' => 'Jarzeniówka dająca światło dzienne (D 5700 - 7100K)', + 'Fine Weather' => 'Dobra pogoda', + 'Flash' => 'Lampa błyskowa', + 'Fluorescent' => 'Jarzeniowy', + 'ISO Studio Tungsten' => 'ISO dla studyjnych lamp żarowych', + 'Other' => 'Inne źródło światła', + 'Shade' => 'Cień', + 'Standard Light A' => 'Standardowe światło A', + 'Standard Light B' => 'Standardowe światło B', + 'Standard Light C' => 'Standardowe światło C', + 'Tungsten (Incandescent)' => 'Światło żarowe', + 'Unknown' => 'Nieznane', + 'White Fluorescent' => 'Biała jarzeniówka (WW3250 - 3800K)', + }, + }, + 'CalibrationIlluminant2' => { + PrintConv => { + 'Cloudy' => 'Zachmurzone niebo', + 'Cool White Fluorescent' => 'Zimna biała jarzeniówka (W 3800 - 4500K)', + 'Day White Fluorescent' => 'Jarzeniówka z naturalnym białym światłem (N 4600 - 5500K)', + 'Daylight' => 'Światło dzienne', + 'Daylight Fluorescent' => 'Jarzeniówka dająca światło dzienne (D 5700 - 7100K)', + 'Fine Weather' => 'Dobra pogoda', + 'Flash' => 'Lampa błyskowa', + 'Fluorescent' => 'Jarzeniowy', + 'ISO Studio Tungsten' => 'ISO dla studyjnych lamp żarowych', + 'Other' => 'Inne źródło światła', + 'Shade' => 'Cień', + 'Standard Light A' => 'Standardowe światło A', + 'Standard Light B' => 'Standardowe światło B', + 'Standard Light C' => 'Standardowe światło C', + 'Tungsten (Incandescent)' => 'Światło żarowe', + 'Unknown' => 'Nieznane', + 'White Fluorescent' => 'Biała jarzeniówka (WW3250 - 3800K)', + }, + }, + 'CameraOrientation' => { + Description => 'Orientacja obrazu', + PrintConv => { + 'Horizontal (normal)' => '0° (góra/lewo)', + 'Rotate 270 CW' => '90° CW (lewo/dół)', + 'Rotate 90 CW' => '90° CCW (prawo/góra)', + }, + }, + 'CameraSettings' => 'Ustawienia aparatu', + 'CameraTemperature' => 'Temperatura aparatu', + 'Caption-Abstract' => 'Podpis', + 'CaptionWriter' => 'Autor podpisu', + 'Categories' => 'Kategorie', + 'Category' => 'Kategorie', + 'CellLength' => 'Długość komórki', + 'CellWidth' => 'Szerokość komórki', + 'City' => 'Miasto', + 'CleanFaxData' => { + Description => 'Poprawne wiersze transmisji Fax', + PrintConv => { + 'Clean' => 'Dobry', + 'Regenerated' => 'Ponowiony', + 'Unclean' => 'Niedobry', + }, + }, + 'ClipPath' => 'Ścieżka obcięcia', + 'CodingMethods' => { + Description => 'Metody kompresji', + PrintConv => { + 'Baseline JPEG' => 'JPEG podstawowa', + 'JBIG color' => 'JBIG kolor', + 'Modified Huffman' => 'Huffmana zmodyfikowana', + 'Modified MR' => 'Zmodyfikowany MR', + 'Modified Read' => 'Zmodyfikowany odczyt', + 'Unspecified compression' => 'Nie podane', + }, + }, + 'ColorFilter' => 'Filtr kolorowy', + 'ColorInfo' => 'Informacje o kolorze', + 'ColorMap' => 'Mapa kolorów', + 'ColorMatrix1' => 'Macierz kolorów 1', + 'ColorMatrix2' => 'Macierz kolorów 2', + 'ColorSpace' => { + Description => 'Informacja o przestrzeni barwowej', + PrintConv => { + 'Uncalibrated' => 'Nie skalibrowany', + }, + }, + 'ColorSpaceData' => 'Dane przestrzeni barw', + 'ColorTemperature' => 'Temperatura barwowa', + 'Comment' => 'Komentarz', + 'ComponentsConfiguration' => 'Znaczenie każdego komponentu', + 'CompressedBitsPerPixel' => 'Tryb kompresji obrazu', + 'Compression' => { + Description => 'Algorytm kompresji', + PrintConv => { + 'Epson ERF Compressed' => 'Skompresowany Epson ERF', + 'JBIG B&W' => 'JBIG Czarno Biały', + 'JBIG Color' => 'JBIG Kolorowy', + 'JPEG' => 'Kompresja JPEG', + 'JPEG (old-style)' => 'JPEG (w starym stylu)', + 'Kodak DCR Compressed' => 'Skompresowany Kodak DCR', + 'Kodak KDC Compressed' => 'Skompresowany Kodak KDC', + 'Next' => 'Kodowanie 2-bitowe NeXT', + 'Nikon NEF Compressed' => 'Skompresowany Nikon NEF', + 'None' => 'Brak', + 'Packed RAW' => 'Spakowany RAW', + 'Pentax PEF Compressed' => 'Skompresowany Pentax PEF', + 'SGILog' => 'Kodowanie 32-bitowe SGI Log Luminance', + 'SGILog24' => 'Kodowanie 24-bitowe SGI Log Luminance', + 'Samsung SRW Compressed' => 'Skompresowany Samsung SRW', + 'Sony ARW Compressed' => 'Skompresowany Sony ARW', + 'Thunderscan' => 'Kodowanie 4-bitowe ThunderScan', + 'Uncompressed' => 'Bez kompresji', + }, + }, + 'CompressionType' => { + PrintConv => { + 'None' => 'Brak', + }, + }, + 'ConsecutiveBadFaxLines' => 'Sekwencja uszkodzonych wierszy transmisji Fax', + 'Contrast' => { + Description => 'Kontrast', + PrintConv => { + 'High' => 'Ostre', + 'Low' => 'Miękkie', + 'Normal' => 'Standard', + }, + }, + 'Copyright' => 'Posiadacz praw autorskich', + 'CopyrightNotice' => 'Informacja o prawach autorskich', + 'Country' => 'Kraj', + 'Country-PrimaryLocationName' => 'Kraj', + 'CreateDate' => 'Data utworzenia', + 'CreationDate' => 'Data utworzenia', + 'Credit' => 'Podziękowania', + 'CropUnit' => { + PrintConv => { + 'inches' => 'Cal', + }, + }, + 'CropUnits' => { + PrintConv => { + 'inches' => 'Cal', + }, + }, + 'CustomRendered' => { + Description => 'Przetwarzanie zdjęć według ustawień własnych', + PrintConv => { + 'Custom' => 'Proces zdefiniowany przez użytkownika', + 'Normal' => 'Normalny proces', + }, + }, + 'DNGBackwardVersion' => 'Poprzednia wersja DNG', + 'DNGVersion' => 'Wersja DNG', + 'DSPFirmwareVersion' => 'Wersja firmware DSP', + 'DataDump' => 'Zrzut danych?', + 'DataImprint' => { + PrintConv => { + 'None' => 'Brak', + }, + }, + 'DataType' => 'Typ daty', + 'Date' => 'Data', + 'DateCreated' => 'Data utworzenia', + 'DateSent' => 'Wysłano datę', + 'DateTimeOriginal' => 'Pierwotna data i godzina', + 'Decode' => 'Zdekodowany', + 'DefaultImageColor' => 'Domyślny kolor w obrazie', + 'Description' => 'Opis', + 'DestinationCity' => 'Miasto przeznaczenia', + 'DestinationCityCode' => 'Kod miasta przeznaczenia', + 'DestinationDST' => { + Description => 'Czas letni miasta przeznaczenia', + PrintConv => { + 'No' => 'Nie', + 'Yes' => 'Tak', + }, + }, + 'DeviceAttributes' => 'Atrybuty urządzenia', + 'DeviceManufacturer' => 'Producent urządzenia', + 'DeviceModel' => 'Model urządzenia', + 'DeviceSettingDescription' => 'Opis ustawień urządzenia', + 'DigitalZoom' => 'Cyfrowy zoom', + 'DigitalZoomRatio' => 'Współczynnik cyfrowego zoomu', + 'Directory' => 'Lokalizacja pliku', + 'DisplayUnits' => { + PrintConv => { + 'inches' => 'Cal', + }, + }, + 'DisplayedUnitsX' => { + PrintConv => { + 'inches' => 'Cal', + }, + }, + 'DisplayedUnitsY' => { + PrintConv => { + 'inches' => 'Cal', + }, + }, + 'DocumentName' => 'Nazwa dokumentu', + 'DriveMode' => 'Tryb przesuwu', + 'DriveMode2' => 'Tryb zdjęć 2', + 'Duration' => 'Czas', + 'DynamicRangeExpansion' => { + Description => 'Rozszerzenie zakresu dynamiki', + PrintConv => { + 'Off' => 'Wyłączone', + 'On' => 'Włączone', + }, + }, + 'E-DialInProgram' => 'Program E-Dial', + 'EVStepInfo' => 'Informacja o krokach EV', + 'EVSteps' => 'Krok EV', + 'EffectiveLV' => 'Efektywne LV', + 'Emphasis' => { + PrintConv => { + 'None' => 'Brak', + }, + }, + 'EnvelopePriority' => { + PrintConv => { + '0 (reserved)' => '0 (zarezerwowane na przyszłość)', + '1 (most urgent)' => '1 (najpilniejszy)', + '5 (normal urgency)' => '5 (zwykły)', + '8 (least urgent)' => '8 (niezbyt pilny)', + '9 (user-defined priority)' => '9 (priorytet określony przez użytkownika)', + }, + }, + 'ExifImageHeight' => 'Wysokość obrazu', + 'ExifImageWidth' => 'Szerokość obrazu', + 'ExifOffset' => 'Wskaźnik Exif IFD', + 'ExifVersion' => 'Wersja Exif', + 'ExposureBracketStepSize' => 'Krok bracketingu ekspozycji', + 'ExposureCompensation' => 'Różnica ekspozycji', + 'ExposureIndex' => 'Wskaźnik ekspozycji', + 'ExposureMode' => { + Description => 'Tryb ekspozycji', + PrintConv => { + 'Auto' => 'Automatyczna ekspozycja', + 'Auto bracket' => 'Funkcja Autobracketing', + 'Manual' => 'Manualna ekspozycja', + }, + }, + 'ExposureProgram' => { + Description => 'Program ekspozycji', + PrintConv => { + 'Action (High speed)' => 'Program akcji', + 'Aperture-priority AE' => 'Priorytet przysłony', + 'Creative (Slow speed)' => 'Program kreatywny', + 'Landscape' => 'Krajobraz', + 'Manual' => 'Manualna ekspozycja', + 'Portrait' => 'Portret', + 'Program AE' => 'Normalny program', + 'Shutter speed priority AE' => 'Priorytet migawki', + }, + }, + 'ExposureTime' => 'Czas ekspozycji', + 'ExternalFlashExposureComp' => 'Kompensacja ekspozycji zewnetrznej lampy', + 'ExternalFlashGuideNumber' => 'Liczba przewodnia lampy zewnętrznej', + 'ExternalFlashMode' => 'Tryb lampy zewnętrznej', + 'FNumber' => 'Przysłona', + 'FaceOrientation' => { + PrintConv => { + 'Horizontal (normal)' => '0° (góra/lewo)', + 'Rotate 180' => '180° (dół/prawo)', + 'Rotate 270 CW' => '90° CW (lewo/dół)', + 'Rotate 90 CW' => '90° CCW (prawo/góra)', + }, + }, + 'FaxProfile' => { + Description => 'Profil faxu (rodzaj zawartości)', + PrintConv => { + 'Extended B&W lossless, F' => 'Rozszerzony cz.b. bezstratny, F', + 'Lossless JBIG B&W, J' => 'Bezstratny JBIG cz.b., J', + 'Lossless color and grayscale, L' => 'Bezstratne kolor i skala szarości, L', + 'Lossy color and grayscale, C' => 'Stratne kolor i skala szarości, C', + 'Minimal B&W lossless, S' => 'Minimalny cz.b. bezstratny, S', + 'Mixed raster content, M' => 'Raster — zawartość mieszana, M', + 'Multi Profiles' => 'Wiele profili', + 'Unknown' => 'Nieznany', + }, + }, + 'FileFormat' => 'Format', + 'FileModifyDate' => 'Data aktualizacji', + 'FileName' => 'Nazwa pliku', + 'FileSize' => 'Wielkość pliku', + 'FileSource' => { + Description => 'Źródło pliku', + PrintConv => { + 'Digital Camera' => 'DSC', + 'Film Scanner' => 'Skaner do materiałów transparentnych', + 'Reflection Print Scanner' => 'Skaner do zdjęć', + }, + }, + 'FileType' => 'Typ pliku', + 'Filename' => 'Nazwa pliku', + 'FillOrder' => { + Description => 'Kolejność wypełniania', + PrintConv => { + 'Normal' => 'Normalna', + 'Reversed' => 'Zajęte', + }, + }, + 'FilterEffectMonochrome' => { + PrintConv => { + 'None' => 'Brak', + }, + }, + 'Flash' => { + Description => 'Lampa', + PrintConv => { + 'Auto, Fired' => 'Włączony (Automatyczny błysk lampy)', + 'Auto, Fired, Red-eye reduction' => '"Włączony (Błysk automatyczny, Redukcja efektu czerwonych oczu)"', + 'Auto, Fired, Red-eye reduction, Return detected' => '"Włączony (Błysk automatyczny, Redukcja efektu czerwonych oczu, rejestracja światła odbitego)"', + 'Auto, Fired, Return detected' => '"Włączony (Automatyczny błysk lampy, rejestracja światła odbitego)"', + 'Did not fire' => 'Nie nastąpił błysk lampy', + 'Fired' => 'Nastąpił błysk lampy', + 'Fired, Red-eye reduction' => 'Włączony (Redukcja efektu czerwonych oczu)', + 'Fired, Red-eye reduction, Return detected' => '"Włączony (Redukcja efektu czerwonych oczu, rejestracja światła odbitego)"', + 'Fired, Return detected' => 'Włączony (Rejestracja światła odbitego)', + 'No Flash' => 'Brak funkcji lampy błyskowej', + 'On, Fired' => 'Włączony (Błysk dopełniający)', + 'On, Red-eye reduction' => '"Włączony (Błysk dopełniający, Redukcja efektu czerwonych oczu)"', + 'On, Red-eye reduction, Return detected' => '"Włączony (Błysk dopełniający, Redukcja efektu czerwonych oczu, rejestracja światła odbitego)"', + 'On, Return detected' => '"Włączony (Błysk dopełniający, rejestracja światła odbitego)"', + }, + }, + 'FlashDevice' => { + PrintConv => { + 'None' => 'Brak', + }, + }, + 'FlashEnergy' => 'Siła lampy błyskowej', + 'FlashExposureComp' => 'Kompensacja lampy', + 'FlashMeteringSegments' => 'Segmenty pomiaru błysku', + 'FlashMode' => 'Tryb lampy', + 'FlashModel' => { + PrintConv => { + 'None' => 'Brak', + }, + }, + 'FlashOptions' => 'Opcje lampy', + 'FlashStatus' => 'Stan lampy', + 'FlashType' => { + PrintConv => { + 'None' => 'Brak', + }, + }, + 'FlashpixVersion' => 'Obsługiwana wersja Flashpix', + 'FocalLength' => 'Ogniskowa', + 'FocalLength35efl' => 'Długość ogniskowej (w wartościach dla formatu małoobrazkowego)', + 'FocalLengthIn35mmFormat' => 'Długość ogniskowej dla aparatów małoobrazkowych', + 'FocalPlaneResolutionUnit' => { + Description => 'Jednostka rozdzielczości w płaszczyźnie ogniskowej', + PrintConv => { + 'None' => 'Brak', + 'inches' => 'Cal', + 'um' => 'µm (mikrometr)', + }, + }, + 'FocalPlaneXResolution' => 'Rozdzielczość w płaszczyźnie ogniskowej - oś x', + 'FocalPlaneYResolution' => 'Rozdzielczość w płaszczyźnie ogniskowej - oś y', + 'FocusMode' => 'Tryb ostrzenia', + 'FocusMode2' => 'Tryb Autofokusa 2', + 'FrameNumber' => 'Numer zdjęcia', + 'FrameRate' => 'Częstotliwość zmiany kadrów', + 'FrameSize' => 'Wielkość kadru', + 'FreeByteCounts' => 'Liczba wolnych bajtów', + 'FreeOffsets' => 'Wolne offsety', + 'GDALMetadata' => 'Metadane GDAL', + 'GDALNoData' => 'Brak danych GDAL', + 'GPSAltitude' => 'Wysokość', + 'GPSAltitudeRef' => { + Description => 'Wysokość odniesienia', + PrintConv => { + 'Above Sea Level' => 'Poziom morza', + 'Below Sea Level' => 'Względem poziomu morza (wartość ujemna)', + }, + }, + 'GPSAreaInformation' => 'Nazwa obszaru GPS', + 'GPSDOP' => 'Precyzja pomiaru', + 'GPSDateStamp' => 'Dane GPS', + 'GPSDestBearing' => 'Azymut punktu docelowego', + 'GPSDestBearingRef' => 'Wartość odniesienia dla azymutu punktu docelowego.', + 'GPSDestDistance' => 'Odległość do punktu docelowego.', + 'GPSDestDistanceRef' => 'Wartość odniesienia dla odległości do punktu docelowego.', + 'GPSDestLatitude' => 'Szerokość geograficzna punktu docelowego', + 'GPSDestLatitudeRef' => 'Wartość odniesienia dla szerokości geograficznej punktu docelowego.', + 'GPSDestLongitude' => 'Długość geograficzna punktu docelowego', + 'GPSDestLongitudeRef' => 'Wartość odniesienia dla długości geograficznej punktu docelowego.', + 'GPSDifferential' => { + Description => 'Różnicowa korekcja GPS', + PrintConv => { + 'Differential Corrected' => 'Zastosowanie korekcji różnicowej', + 'No Correction' => 'Pomiar bez korekcji różnicowej', + }, + }, + 'GPSHPositioningError' => 'Błąd poziomy wyznaczenia pozycji', + 'GPSImgDirection' => 'Kierunek obrazu', + 'GPSImgDirectionRef' => 'Wartość odniesienia dla kierunku obrazu', + 'GPSInfo' => 'Wskaźnik GPS Info IFD', + 'GPSLatitude' => 'Szerokość geograficzna', + 'GPSLatitudeRef' => { + Description => 'Szerokość geograficzna północna lub południowa', + PrintConv => { + 'North' => 'Szerokości północnej', + 'South' => 'Szerokości południowej', + }, + }, + 'GPSLongitude' => 'Długość geograficzna', + 'GPSLongitudeRef' => { + Description => 'Długość geograficzna wschodnia lub zachodnia', + PrintConv => { + 'East' => 'Długości wschodniej', + 'West' => 'Długości zachodniej', + }, + }, + 'GPSMapDatum' => 'Wykorzystane dane z badań geodezyjnych', + 'GPSMeasureMode' => { + Description => 'Tryb pomiaru GPS', + PrintConv => { + '3-Dimensional Measurement' => 'Pomiar 3-wymiarowy', + }, + }, + 'GPSProcessingMethod' => 'Nazwa metody przetwarzania GPS', + 'GPSSatellites' => 'Satelity GPS używane do pomiaru', + 'GPSSpeed' => 'Prędkość odbiornika GPS', + 'GPSSpeedRef' => { + Description => 'Jednostka prędkości', + PrintConv => { + 'km/h' => 'Kilometrów na godzinę', + 'knots' => 'Węzły', + 'mph' => 'Mil na godzinę', + }, + }, + 'GPSStatus' => { + Description => 'Stan odbiornika GPS', + PrintConv => { + 'Measurement Active' => 'Trwa pomiar', + 'Measurement Void' => 'Wzajemna niesprzeczność pomiarów', + }, + }, + 'GPSTimeStamp' => 'Czas GPS (zegar atomowy)', + 'GPSTrack' => 'Kierunek przesunięcia', + 'GPSTrackRef' => { + Description => 'Wartość odniesienia dla kierunku ruchu', + PrintConv => { + 'Magnetic North' => 'Kierunek strzałki magnetycznej', + 'True North' => 'Rzeczywisty kierunek', + }, + }, + 'GPSVersionID' => 'Wersja znacznika GPS', + 'GainControl' => { + Description => 'Sterowanie krokiem', + PrintConv => { + 'High gain down' => 'Z dużym krokiem do dołu', + 'High gain up' => 'Z dużym krokiem w górę', + 'Low gain down' => 'Z małym krokiem do dołu', + 'Low gain up' => 'Z małym krokiem w górę', + 'None' => 'Brak', + }, + }, + 'Genre' => 'Gatunek', + 'Gradation' => 'Gradacja', + 'GrayResponseCurve' => 'Krzywa odpowiedzi Szarości', + 'GrayResponseUnit' => 'Wielkość jednostki dla krzywej odpowiedzi szarości', + 'HalftoneHints' => 'Półtony', + 'Headline' => 'Nagłówek', + 'HighISONoiseReduction' => 'Redukcja szumu przy wysokim ISO', + 'HometownCity' => 'Miasto domowe', + 'HometownCityCode' => 'Kod miasta domowego', + 'HometownDST' => { + Description => 'Czas letni miasta domowego', + PrintConv => { + 'No' => 'Nie', + 'Yes' => 'Tak', + }, + }, + 'HostComputer' => 'Komputer użyty do wygenerowania obrazu', + 'Hue' => 'Barwa', + 'ICCProfile' => 'Profil ICC', + 'ISO' => 'Czułość ISO', + 'ISOFloor' => 'Minimalne ISO', + 'ISOSetting' => 'Ustawienia ISO', + 'ImageAreaOffset' => 'Przesunięcie obszaru obrazu', + 'ImageDescription' => 'Opis obrazu', + 'ImageEditCount' => 'Licznik przetworzonych zdjęć', + 'ImageHeight' => 'Wysokość obrazu', + 'ImageID' => 'Identyfikator obrazu', + 'ImageProcessing' => 'Przetwarzanie obrazu', + 'ImageSize' => 'Rozmiar zdjęcia', + 'ImageTone' => { + Description => 'Odcień zdjęcia', + PrintConv => { + 'Bright' => 'Jasny', + 'Landscape' => 'Krajobraz', + 'Monochrome' => 'Monochromatyczny', + 'Natural' => 'Naturalny', + 'Portrait' => 'Portret', + }, + }, + 'ImageType' => { + Description => 'Rodzaj obrazu', + PrintConv => { + 'Page' => 'Strona', + }, + }, + 'ImageUniqueID' => 'Unikalny kod ID zdjęcia', + 'ImageWidth' => 'Szerokość obrazu', + 'Index' => 'Indeks', + 'Indexed' => { + Description => 'Indeksowane', + PrintConv => { + 'Indexed' => 'Indeksowane', + 'Not indexed' => 'Nie indeksowane', + }, + }, + 'InkNames' => 'Nazwy tuszy', + 'InkSet' => { + Description => 'Zestaw tuszy', + PrintConv => { + 'Not CMYK' => 'Nie CMYK', + }, + }, + 'Instructions' => 'Instrukcje', + 'InternalFlashMode' => 'Tryb wewnętrznej lampy', + 'InternalFlashStrength' => 'Moc wewnętrznej lampy', + 'InteropIndex' => { + Description => 'Identyfikacja wzajemnej zgodności', + PrintConv => { + 'R03 - DCF option file (Adobe RGB)' => 'R03: Plik pomocniczy DCF (Adobe RGB)', + 'R98 - DCF basic file (sRGB)' => 'R98: Plik zasadniczy DCF (sRGB)', + 'THM - DCF thumbnail file' => 'THM: Plik miniatury DCF', + }, + }, + 'InteropOffset' => 'Znacznik wzajemnej zgodności', + 'InteropVersion' => 'Wersja wzajemnej zgodności', + 'JPEGProc' => { + PrintConv => { + 'Baseline' => 'JPEG Podstawowy', + 'Lossless' => 'Bezstratny', + }, + }, + 'JPEGQuality' => { + Description => 'Jakość', + PrintConv => { + 'Standard' => 'Standardowa jakość', + }, + }, + 'JPEGRestartInterval' => 'JPEG odstęp restartów', + 'Keywords' => 'Słowa kluczowe', + 'Lens' => 'Obiektyw', + 'LensID' => 'ID obiektywu', + 'LensInfo' => 'Informacja o obiektywie', + 'LensMake' => 'Producent obiektywu', + 'LensModel' => 'Model obiektywu', + 'LensSerialNumber' => 'Numer seryjny obiektywu', + 'LightReading' => 'Pomiar światła', + 'LightSource' => { + Description => 'Źródło światła', + PrintConv => { + 'Cloudy' => 'Zachmurzone niebo', + 'Cool White Fluorescent' => 'Zimna biała jarzeniówka (W 3800 - 4500K)', + 'Day White Fluorescent' => 'Jarzeniówka z naturalnym białym światłem (N 4600 - 5500K)', + 'Daylight' => 'Światło dzienne', + 'Daylight Fluorescent' => 'Jarzeniówka dająca światło dzienne (D 5700 - 7100K)', + 'Fine Weather' => 'Dobra pogoda', + 'Flash' => 'Lampa błyskowa', + 'Fluorescent' => 'Jarzeniowy', + 'ISO Studio Tungsten' => 'ISO dla studyjnych lamp żarowych', + 'Other' => 'Inne źródło światła', + 'Shade' => 'Cień', + 'Standard Light A' => 'Standardowe światło A', + 'Standard Light B' => 'Standardowe światło B', + 'Standard Light C' => 'Standardowe światło C', + 'Tungsten (Incandescent)' => 'Światło żarowe', + 'Unknown' => 'Nieznane', + 'White Fluorescent' => 'Biała jarzeniówka (WW3250 - 3800K)', + }, + }, + 'Lightness' => 'Jasność', + 'LocalizedCameraModel' => 'Lokalizowany model aparatu', + 'Location' => 'Miejsce', + 'Luminance' => 'Luminancja', + 'Macro' => 'Makro', + 'Make' => 'Producent', + 'MakeAndModel' => 'Producent i model', + 'MakerNote' => 'Prywatne dane DNG', + 'MakerNotes' => 'Dane producenta', + 'MaxAperture' => 'Maks. przysłona obiektywu', + 'MaxSampleValue' => 'Maksymalny rozmiar próbki', + 'MeasurementGeometry' => { + Description => 'Geometria pomiaru', + PrintConv => { + '0/45 or 45/0' => '0/45 lub 45/0', + '0/d or d/0' => '0/d lub d/0', + }, + }, + 'MediaBlackPoint' => 'Punkt czerni materiału', + 'MediaWhitePoint' => 'Punkt bieli materiału', + 'MeteringMode' => { + Description => 'Tryb pomiaru', + PrintConv => { + 'Average' => 'Średni', + 'Center-weighted average' => 'Centralnie ważony uśredniony', + 'Multi-segment' => 'Wzór', + 'Multi-spot' => 'Wielopunktowy', + 'Other' => 'Inne', + 'Partial' => 'Częściowy', + 'Spot' => 'Punktowy', + 'Unknown' => 'Nieznane', + }, + }, + 'MinSampleValue' => 'Minimalny rozmiar próbki', + 'ModeNumber' => 'Numer trybu', + 'Model' => 'Aparat', + 'ModifiedPictureStyle' => { + PrintConv => { + 'None' => 'Brak', + }, + }, + 'ModifyDate' => 'Data i godzina zmiany pliku', + 'MonochromeFilterEffect' => { + PrintConv => { + 'None' => 'Brak', + }, + }, + 'MonochromeToningEffect' => { + PrintConv => { + 'None' => 'Brak', + }, + }, + 'MultipleExposureSet' => 'Wielokrotna ekspozycja', + 'NEFCompression' => { + PrintConv => { + 'Uncompressed' => 'Bez kompresji', + }, + }, + 'NativeDisplayInfo' => 'Informacja o natywnym(?) wyświetlaczu', + 'Noise' => 'Szumy', + 'NoiseReduction' => { + Description => 'Redukcja szumów', + PrintConv => { + 'Off' => 'Wyłączona', + 'On' => 'Włączona', + }, + }, + 'NumberofInks' => 'Liczba tuszy', + 'ObjectFileType' => { + PrintConv => { + 'None' => 'Brak', + }, + }, + 'OldSubfileType' => { + Description => 'Stary typ podsekcji', + PrintConv => { + 'Full-resolution image' => 'Obraz w pełnej rozdzielczości', + 'Reduced-resolution image' => 'Obraz o zredukowanej rozdzielczości', + 'Single page of multi-page image' => 'Jedna strona obrazu wielostronicowego', + }, + }, + 'Opto-ElectricConvFactor' => 'Współczynnik przekształcenia optyczno-elektrycznego', + 'Orientation' => { + Description => 'Orientacja obrazu', + PrintConv => { + 'Horizontal (normal)' => '0° (góra/lewo)', + 'Mirror horizontal' => '0° (góra/prawo)', + 'Mirror horizontal and rotate 270 CW' => '90° CW (lewo/góra)', + 'Mirror horizontal and rotate 90 CW' => '90° CCW (prawo/dół)', + 'Mirror vertical' => '180° (dół/lewo)', + 'Rotate 180' => '180° (dół/prawo)', + 'Rotate 270 CW' => '90° CW (lewo/dół)', + 'Rotate 90 CW' => '90° CCW (prawo/góra)', + }, + }, + 'OwnerName' => 'Nazwa właściciela', + 'PageName' => 'Nazwa strony', + 'PageNumber' => 'Numer strony', + 'PentaxImageSize' => { + Description => 'Rozmiar obrazu Pentax\'a', + PrintConv => { + '2304x1728 or 2592x1944' => '2304 x 1728 lub 2592 x 1944', + '2560x1920 or 2304x1728' => '2560 x 1920 lub 2304 x 1728', + '2816x2212 or 2816x2112' => '2816 x 2212 lub 2816 x 2112', + '3008x2008 or 3040x2024' => '3008 x 2008 lub 3040 x 2024', + 'Full' => 'Pełny', + }, + }, + 'PentaxVersion' => 'Wersja Pentax\'a', + 'PhotoEffectsType' => { + PrintConv => { + 'None' => 'Brak', + }, + }, + 'PhotometricInterpretation' => { + Description => 'Schemat pikseli', + PrintConv => { + 'BlackIsZero' => 'Czarny jest zerem', + 'Color Filter Array' => 'CFA (Filtr kolorów matrycy)', + 'Pixar LogL' => 'CIE Log2(L) (Log luminancji)', + 'Pixar LogLuv' => 'CIE Log2(l)(u\',v\') (Log luminancji i chrominancji)', + 'RGB Palette' => 'Paleta kolorów', + 'Transparency Mask' => 'Maska przeźroczystości', + 'WhiteIsZero' => 'Biały jest zerem', + }, + }, + 'PictureMode' => 'Tryb obrazu', + 'PictureMode2' => 'Tryb obrazu 2', + 'PictureStyle' => { + PrintConv => { + 'None' => 'Brak', + }, + }, + 'PixelFormat' => { + Description => 'Format zapisu koloru', + PrintConv => { + '128-bit PRGBA Float' => '128-bitów PRGBA (zapis zmienno przecinkowy)', + '128-bit RGB Float' => '128-bitów RGB (zapis zmienno przecinkowy)', + '128-bit RGBA Float' => '128-bitów RGBA (zapis zmienno przecinkowy)', + '16-bit Gray' => '16-bitów Szarość', + '32-bit Gray Float' => '32-bity Szarość (zapis zmienno przecinkowy)', + '48-bit RGB Fixed Point' => '48-bitów RGB (zapis stałopozycyjny)', + '8-bit Gray' => '8-bitów Szarość', + '96-bit RGB Fixed Point' => '96-bitów RGB (zapis stałopozycyjny)', + 'Black & White' => 'Czarno Biały', + }, + }, + 'PlanarConfiguration' => { + Description => 'Układ danych obrazu', + PrintConv => { + 'Chunky' => 'Format "chunky" (z przeplotem)', + 'Planar' => 'Format "planar"', + }, + }, + 'PowerSource' => 'Zasilanie', + 'Predictor' => { + Description => 'Przelicznik', + PrintConv => { + 'Horizontal differencing' => 'W oparciu o różnicę w poziomie', + 'None' => 'Bez przelicznika', + }, + }, + 'Preview0' => 'Podgląd 0', + 'Preview1' => 'Podgląd 1', + 'Preview2' => 'Podgląd 2', + 'PreviewColorSpace' => { + PrintConv => { + 'Unknown' => 'Nieznany', + }, + }, + 'PreviewImage' => 'Podgląd', + 'PreviewImageBorders' => 'Ramka podglądu', + 'PreviewImageData' => 'Dane podglądu obrazu', + 'PreviewImageLength' => 'Długość miniatury z podglądem', + 'PreviewImageSize' => 'Rozmiar podglądu', + 'PreviewImageStart' => 'Początek miniatury z podglądem', + 'PrimaryChromaticities' => 'Tonalność kolorów podstawowych', + 'ProcessingSoftware' => 'Oprogramowanie wykorzystane do przetwarzania', + 'ProductID' => 'ID produktu', + 'ProfileCMMType' => 'Typ profilu CMM', + 'ProfileClass' => { + Description => 'Klasa profilu', + PrintConv => { + 'Abstract Profile' => 'Profil abstrakcyjny', + 'ColorSpace Conversion Profile' => 'Profil konwersji przestrzeni barw', + 'DeviceLink Profile' => 'Profil DeviceLink', + 'Display Device Profile' => 'Profil urządzenia wyświetlającego', + 'Input Device Profile' => 'Profil urządzenia wejściowego', + 'NamedColor Profile' => 'Nazwany profil kolorów', + 'Nikon Input Device Profile (NON-STANDARD!)' => 'Profil Nikon ("nkpf")', + 'Output Device Profile' => 'Profil urządzenia wyjściowego', + }, + }, + 'ProfileConnectionSpace' => 'Profil Connection Space', + 'ProfileDateTime' => 'Data i czas profilu', + 'ProfileDescription' => 'Opis profilu', + 'ProfileDescriptionML' => 'Wielojęzyczny opis profilu.', + 'ProfileSequenceDesc' => 'Opis sekwencji profilu', + 'ProfileType' => { + Description => 'Typ profilu', + PrintConv => { + 'Unspecified' => 'Nie podany', + }, + }, + 'ProfileVersion' => 'Wersja profilu', + 'ProgramLine' => 'Linia programu', + 'ProgramMode' => { + PrintConv => { + 'None' => 'Brak', + }, + }, + 'Province-State' => 'Region', + 'Quality' => { + Description => 'Jakość', + PrintConv => { + 'Best' => 'Najlepsza', + 'Better' => 'Lepsza', + 'Good' => 'Dobra', + 'Low' => 'Niska jakość', + 'Normal' => 'Standardowa jakość', + }, + }, + 'Rating' => 'Ocena', + 'RatingPercent' => 'Ocena procentowo', + 'RawImageSize' => 'Rozmiar obrazu RAW', + 'RecordMode' => 'Tryb zapisu', + 'RedBalance' => 'Balans czerwonego', + 'RedMatrixColumn' => 'Kolumna matrycy czerwieni', + 'RedTRC' => 'Krzywa reprodukcji czerwieni', + 'ReferenceBlackWhite' => 'Para wartości odniesienia dla czarno-białego obrazu', + 'RelatedImageFileFormat' => 'Format pliku powiązanego zdjęcia', + 'RelatedImageHeight' => 'Długość powiązanego zdjęcia', + 'RelatedImageWidth' => 'Szerokość powiązanego zdjęcia', + 'RelatedSoundFile' => 'Powiązany plik audio', + 'ResolutionUnit' => { + Description => 'Jednostka rozdzielczości X i Y', + PrintConv => { + 'None' => 'Brak', + 'cm' => 'centymetry', + 'inches' => 'Cal', + }, + }, + 'RetouchHistory' => { + PrintConv => { + 'None' => 'Brak', + }, + }, + 'Rotation' => { + Description => 'Obrót', + PrintConv => { + 'Horizontal' => '0° (góra/lewo)', + 'Horizontal (Normal)' => '0° (góra/lewo)', + 'Horizontal (normal)' => '0° (góra/lewo)', + 'Rotate 180' => '180° (dół/prawo)', + 'Rotate 270 CW' => '90° CW (lewo/dół)', + 'Rotate 90 CW' => '90° CCW (prawo/góra)', + 'Rotated 180' => '180° (dół/prawo)', + 'Rotated 270 CW' => '90° CW (lewo/dół)', + 'Rotated 90 CW' => '90° CCW (prawo/góra)', + }, + }, + 'RowsPerStrip' => 'Liczba rzędów w pasku', + 'SRFocalLength' => 'Długość fokalna SR', + 'SRResult' => 'Stabilizacja obrazu', + 'SampleFormat' => { + Description => 'Format próbki', + PrintConv => { + 'Float' => 'Zmienno przecinkowa', + 'Signed' => 'Całkowita ze znakiem', + 'Undefined' => 'Nie podano', + 'Unsigned' => 'Całkowita bez znaku', + }, + }, + 'SamplesPerPixel' => 'Liczba składników', + 'Saturation' => { + Description => 'Nasycenie', + PrintConv => { + 'High' => 'Wysokie nasycenie', + 'Low' => 'Niskie nasycenie', + 'Normal' => 'Standardowy', + }, + }, + 'SceneCaptureType' => { + Description => 'Ujęcie z programem tematycznym', + PrintConv => { + 'Landscape' => 'Krajobraz', + 'Night' => 'Sceny nocne', + 'Portrait' => 'Portret', + 'Standard' => 'Standardowy', + }, + }, + 'SceneMode' => { + Description => 'Tryby tematyczne', + PrintConv => { + 'Sunset' => 'Zachód słońca', + }, + }, + 'SceneType' => { + Description => 'Rodzaj sceny', + PrintConv => { + 'Directly photographed' => 'Zdjęcie uzyskane bezpośrednio', + }, + }, + 'SensingMethod' => { + Description => 'Metoda pomiaru', + PrintConv => { + 'Color sequential area' => 'Sekwencyjny sensor obszaru koloru', + 'Color sequential linear' => 'Sekwencyjny liniowy sensor koloru', + 'One-chip color area' => 'Jednoprocesorowy sensor obszaru koloru', + 'Three-chip color area' => 'Trójprocesorowy sensor obszaru koloru', + 'Trilinear' => 'Trój liniowy sensor', + 'Two-chip color area' => 'Dwuprocesorowy sensor obszaru koloru', + }, + }, + 'SensitivityAdjust' => 'Regulacja czułości', + 'SensitivitySteps' => 'Krok ustawienia czułości', + 'SequentialShot' => { + PrintConv => { + 'None' => 'Brak', + }, + }, + 'SerialNumber' => 'ID aparatu fotograficznego', + 'ServiceIdentifier' => 'Identyfikator usługi', + 'ShadingCompensation' => 'Kompensacja zacienienia', + 'Sharpness' => { + Description => 'Ostrość', + PrintConv => { + 'Hard' => 'Ostry', + 'Normal' => 'Standardowy', + 'Soft' => 'Miękki', + }, + }, + 'ShootingMode' => 'Tryb fotografowania', + 'ShutterCount' => 'Licznik migawki', + 'ShutterSpeed' => 'Czas ekspozycji', + 'ShutterSpeedValue' => 'Prędkość migawki', + 'SlaveFlashMeteringSegments' => 'Segmenty pomiarowe lampy podrzędnej', + 'SlowShutter' => { + PrintConv => { + 'None' => 'Brak', + }, + }, + 'Software' => 'Oprogramowanie', + 'Source' => 'Źródło', + 'SpatialFrequencyResponse' => 'Przestrzenno - częstotliwościowa charakterystyka', + 'SpecialEffectsOpticalFilter' => { + PrintConv => { + 'None' => 'Brak', + }, + }, + 'SpectralSensitivity' => 'Czułość spektralna', + 'State' => 'Region', + 'StripByteCounts' => 'Bajtów na skompresowany pasek', + 'StripOffsets' => 'Lokalizacja danych zdjęcia', + 'SubSecTime' => '"Data i godzina, subsekundy"', + 'SubSecTimeDigitized' => '"Cyfrowa data i godzina, subsekundy"', + 'SubSecTimeOriginal' => '"Pierwotna data i godzina, sub-sekundy"', + 'SubfileType' => { + Description => 'Typ podsekcji', + PrintConv => { + 'Full-resolution Image' => 'Obraz w pełnej rozdzielczości', + 'Reduced-resolution image' => 'Obraz o zredukowanej rozdzielczości', + 'Single page of multi-page image' => 'Jedna strona obrazu wielostronicowego', + 'Single page of multi-page reduced-resolution image' => 'Jedna strona obrazu wielostronicowego o zredukowanej rozdzielczości', + 'TIFF/IT final page' => 'Ostatnia strona TIFF/IT', + 'Transparency mask' => 'Maska przezroczystości', + 'Transparency mask of multi-page image' => 'Maska przezroczystości obrazu wielostronicowego', + 'Transparency mask of reduced-resolution image' => 'Maska przezroczystości obrazu o zredukowanej rozdzielczości', + 'Transparency mask of reduced-resolution multi-page image' => 'Maska przezroczystości obrazu wielostronicowego o zredukowanej rozdzielczości', + 'invalid' => 'Błędny', + }, + }, + 'SubjectArea' => 'Obszar obiektu', + 'SubjectDistance' => 'Odległość od obiektu', + 'SubjectDistanceRange' => { + Description => 'Zakres odległości do obiektu', + PrintConv => { + 'Close' => 'Zbliżenie', + 'Distant' => 'Odległy plan', + 'Macro' => 'Makro', + }, + }, + 'SubjectLocation' => 'Lokalizacja obiektu', + 'SubjectProgram' => { + PrintConv => { + 'None' => 'Brak', + }, + }, + 'SupplementalCategories' => 'Kategorie dodatkowe', + 'SvISOSetting' => 'Ustawienia ISO Sv', + 'T6Options' => { + PrintConv => { + 'Uncompressed' => 'Nieskompresowany', + }, + }, + 'TargetPrinter' => 'Docelowa drukarka', + 'Technology' => { + Description => 'Technologia', + PrintConv => { + 'Active Matrix Display' => 'Wyświetlacz z matrycą aktywną', + 'Cathode Ray Tube Display' => 'Wyświetlacz kineskopowy', + 'Digital Camera' => 'Aparat cyfrowy', + 'Dye Sublimation Printer' => 'Drukarka termosublimacyjna', + 'Electrophotographic Printer' => 'Drukarka laserowa', + 'Film Scanner' => 'Skaner do filmów', + 'Film Writer' => 'Zapis na filmie', + 'Ink Jet Printer' => 'Drukarka atramentowa', + 'Passive Matrix Display' => 'Wyświetlacz z matrycą pasywną', + 'Photo CD' => 'Foto-CD', + 'Photographic Paper Printer' => 'Drukarka z papierem fotograficznym', + 'Projection Television' => 'Projektor telewizyjny', + 'Reflective Scanner' => 'Skaner', + 'Video Camera' => 'Kamera wideo', + 'Video Monitor' => 'Monitor wideo', + }, + }, + 'Teleconverter' => { + PrintConv => { + 'None' => 'Brak', + }, + }, + 'Text' => 'Tekst', + 'Thresholding' => 'Progowanie', + 'ThumbnailImage' => 'Miniatura', + 'ThumbnailImageSize' => 'Rozmiar miniaturki', + 'TileByteCounts' => 'Liczba bajtów na kafelek', + 'TileLength' => 'Wysokość kafelka', + 'TileOffsets' => 'Przesunięcie kafelków', + 'TileWidth' => 'Szerokość kafelka', + 'Time' => 'Czas', + 'Title' => 'Tytuł', + 'ToneCurve' => 'Krzywa barwy', + 'ToneCurves' => 'Krzywe barwy', + 'ToningEffectMonochrome' => { + PrintConv => { + 'None' => 'Brak', + }, + }, + 'Track' => 'Ścieżka', + 'TransferFunction' => 'Funkcja transferu', + 'Transformation' => { + Description => 'Przekształcenie', + PrintConv => { + 'Horizontal (normal)' => '0° (góra/lewo)', + 'Mirror horizontal' => '0° (góra/prawo)', + 'Mirror horizontal and rotate 270 CW' => '90° CW (lewo/góra)', + 'Mirror horizontal and rotate 90 CW' => '90° CCW (prawo/dół)', + 'Mirror vertical' => '180° (dół/lewo)', + 'Rotate 180' => '180° (dół/prawo)', + 'Rotate 270 CW' => '90° CW (lewo/dół)', + 'Rotate 90 CW' => '90° CCW (prawo/góra)', + }, + }, + 'TransmissionReference' => 'Odnośnik transmisji', + 'TvExposureTimeSetting' => 'Ustawienia czasu ekspozycji TV', + 'Uncompressed' => 'Nieskompresowany', + 'UniqueCameraModel' => 'Unikatowy model aparatu', + 'Unknown' => 'Nieznany', + 'Urgency' => 'Priorytet', + 'UserComment' => 'Komentarz użytkownika', + 'VersionYear' => 'Rok wersji', + 'VideoCardGamma' => 'Gamma karty graficznej', + 'WBAdjLighting' => { + PrintConv => { + 'None' => 'Brak', + }, + }, + 'WB_RGGBLevelsCloudy' => 'Poziomy WB RGGB - zachmurzenie ', + 'WB_RGGBLevelsDaylight' => 'Poziomy WB RGGB - światło dzienne ', + 'WB_RGGBLevelsFlash' => 'Poziomy WB RGGB - lampa błyskowa ', + 'WB_RGGBLevelsFluorescentD' => 'Poziomy WB RGGB - światło fluorescencyjne ', + 'WB_RGGBLevelsFluorescentN' => 'Poziomy WB RGGB - światło fluorescencyjne N ', + 'WB_RGGBLevelsFluorescentW' => 'Poziomy WB RGGB - światło fluorescencyjne W ', + 'WB_RGGBLevelsShade' => 'Poziomy WB RGGB - cień ', + 'WB_RGGBLevelsTungsten' => 'Poziomy WB RGGB - światło żarowe ', + 'WhiteBalance' => { + Description => 'Balans bieli', + PrintConv => { + 'Auto' => 'Automatyczny balans bieli', + 'Black & White' => 'Monochromatyczny', + 'Cloudy' => 'Pochmurna pogoda', + 'Cool White Fluorescent' => 'Jarzeniówka z zimnym białym światłem', + 'Custom 1' => 'WŁASNE 1', + 'Custom 2' => 'WŁASNE 2', + 'Custom 3' => 'WŁASNE 3', + 'Custom 4' => 'WŁASNE 4', + 'Day White Fluorescent' => 'Jarzeniówka z naturalnym białym światłem', + 'Daylight' => 'Światło dzienne', + 'Daylight Fluorescent' => 'Jarzeniówka ze światłem dziennym', + 'Fluorescent' => 'Jarzeniowy', + 'Manual' => 'Manualny balans bieli', + 'Shade' => 'Cień', + 'Tungsten' => 'Światło żarówek', + }, + }, + 'WhiteBalanceMode' => { + Description => 'Tryb balansu bieli', + PrintConv => { + 'Auto (Cloudy)' => 'Automatyczny (zachmurzenie)', + 'Auto (Day White Fluorescent)' => 'Automatyczny (białe fluorescencyjne światło dzienne)', + 'Auto (Daylight Fluorescent)' => 'Automatyczny (fluorescencyjne światło dzienne)', + 'Auto (Daylight)' => 'Automatyczny (światło dzienne)', + 'Auto (Flash)' => 'Automatyczny (lampa błyskowa)', + 'Auto (Shade)' => 'Automatyczny (cień)', + 'Auto (Tungsten)' => 'Automatyczny (światło żarowe)', + 'Auto (White Fluorescent)' => 'Automatyczny (białe światło fluorescencyjne)', + 'Unknown' => 'Automatyczny (nie wykryty)', + 'User-Selected' => 'Użytkownika', + }, + }, + 'WhiteBalanceSet' => 'Ustawienie balansu bieli', + 'WhitePoint' => 'Chromatyczność białego punktu', + 'WorldTimeLocation' => { + Description => 'Miejsca czasu światowego', + PrintConv => { + 'Destination' => 'Przeznaczenie', + 'Hometown' => 'Miasto domowe', + }, + }, + 'Writer-Editor' => 'Autor podpisu', + 'XClipPathUnits' => 'Jednostki wzdłuż osi X dla ścieżki obcięcia', + 'XPosition' => 'Współrzędna X', + 'XResolution' => 'Rozdzielczość obrazu w poziomie', + 'YCbCrCoefficients' => 'Współczynniki matrycy transformacji przestrzeni barwowej', + 'YCbCrPositioning' => { + Description => 'Pozycje Y i C', + PrintConv => { + 'Centered' => 'Wyśrodkowane', + 'Co-sited' => 'Obok siebie (?)', + }, + }, + 'YCbCrSubSampling' => 'Współczynnik podpróbkowania(?) Y do C', + 'YClipPathUnits' => 'Jednostki wzdłuż osi Y dla ścieżki obcięcia', + 'YPosition' => 'Współrzędna Y', + 'YResolution' => 'Rozdzielczość obrazu w pionie', + 'Year' => 'Rok', +); + +1; # end + + +__END__ + +=head1 NAME + +Image::ExifTool::Lang::pl.pm - ExifTool Polish language translations + +=head1 DESCRIPTION + +This file is used by Image::ExifTool to generate localized tag descriptions +and values. + +=head1 AUTHOR + +Copyright 2003-2019, Phil Harvey (phil at owl.phy.queensu.ca) + +This library is free software; you can redistribute it and/or modify it +under the same terms as Perl itself. + +=head1 ACKNOWLEDGEMENTS + +Thanks to Jens Duttke, Przemyslaw Sulek and Kacper Perschke for providing +this translation. + +=head1 SEE ALSO + +L<Image::ExifTool(3pm)|Image::ExifTool>, +L<Image::ExifTool::TagInfoXML(3pm)|Image::ExifTool::TagInfoXML> + +=cut diff --git a/lib/Image/ExifTool/Lang/ru.pm b/lib/Image/ExifTool/Lang/ru.pm new file mode 100644 index 0000000..a9c08b6 --- /dev/null +++ b/lib/Image/ExifTool/Lang/ru.pm @@ -0,0 +1,768 @@ +#------------------------------------------------------------------------------ +# File: ru.pm +# +# Description: ExifTool Russian language translations +# +# Notes: This file generated automatically by Image::ExifTool::TagInfoXML +#------------------------------------------------------------------------------ + +package Image::ExifTool::Lang::ru; + +use strict; +use vars qw($VERSION); + +$VERSION = '1.04'; + +%Image::ExifTool::Lang::ru::Translate = ( + 'ActiveArea' => 'Активная область', + 'Album' => 'Альбом', + 'AnalogBalance' => 'Аналоговый баланс белого', + 'AntiAliasStrength' => 'Относительная сила сглаживающего фильтра сенсора', + 'Aperture' => 'Диафрагма', + 'ApertureValue' => 'Диафрагма', + 'Artist' => 'Исполнитель', + 'AsShotICCProfile' => 'ICC профиль снимка', + 'AsShotNeutral' => 'Нейтральный цвет при съёмке', + 'AsShotPreProfileMatrix' => 'Предварительная цветовая матрица снимка', + 'AsShotProfileName' => 'Имя профиля, ассоциированного со снимком', + 'AsShotWhiteXY' => 'Нейтральный цвет x,y', + 'Author' => 'Автор', + 'AuthorsPosition' => 'Должность автора', + 'BaselineExposure' => 'Базовая экспозиция', + 'BaselineNoise' => 'Базовый шум', + 'BaselineSharpness' => 'Базовая чёткость', + 'BayerGreenSplit' => 'Разделение зелёных каналов в матрице Байера', + 'BestQualityScale' => 'Масштаб с наилучшим качеством', + 'BitsPerSample' => 'Количество бит на компонент', + 'BlackLevel' => 'Уровень чёрного', + 'BlackLevelDeltaH' => 'Горизонтальное распределение уровня чёрного', + 'BlackLevelDeltaV' => 'Вертикальное распределение уровня чёрного', + 'BlackLevelRepeatDim' => 'Размер матрицы уровней чёрного', + 'Brightness' => 'Яркость', + 'By-line' => 'Автор', + 'CFALayout' => { + Description => 'Структура CFA', + PrintConv => { + 'Even columns offset down 1/2 row' => 'Смещённое расположение A: чётные столбцы смещены вниз на полпиксела', + 'Even columns offset up 1/2 row' => 'Смещённое расположение B: чётные столбцы смещены вверх на полпиксела', + 'Even rows offset left 1/2 column' => 'Смещённое расположение D: чётные строки смещены влево на полпиксела', + 'Even rows offset right 1/2 column' => 'Смещённое расположение C: чётные строки смещены вправо на полпиксела', + 'Rectangular' => 'Прямоугольное (или квадратное) расположение элементов', + }, + }, + 'CFAPattern' => 'CFA карта', + 'CalibrationIlluminant1' => { + Description => 'Калибровочный иллюминант №1', + PrintConv => { + 'Cloudy' => 'Облачность', + 'Cool White Fluorescent' => 'Флуоресцентный белый холодный (W 3800 - 4500K)', + 'Day White Fluorescent' => 'Флуоресцентный белый дневной', + 'Daylight' => 'Дневной свет', + 'Daylight Fluorescent' => 'Флуоресцентный белый дневного света (D 5700 - 7100K)', + 'Fine Weather' => 'Ясная погода', + 'Flash' => 'Вспышка', + 'Fluorescent' => 'Флуоресцентный', + 'ISO Studio Tungsten' => 'ISO для студийных ламп накаливания', + 'Other' => 'другой источник света', + 'Shade' => 'Тень', + 'Standard Light A' => 'Стандартный свет A', + 'Standard Light B' => 'Стандартный свет B', + 'Standard Light C' => 'Стандартный свет C', + 'Tungsten (Incandescent)' => 'Лампа накаливания (яркий свет)', + 'Unknown' => 'неизвестно', + 'Warm White Fluorescent' => 'Флуоресцентный теплый белый (L 2600 - 3250K)', + 'White Fluorescent' => 'Флуоресцентный белый (WW 3250 - 3800K)', + }, + }, + 'CalibrationIlluminant2' => { + Description => 'Калибровочный иллюминант №2', + PrintConv => { + 'Cloudy' => 'Облачность', + 'Cool White Fluorescent' => 'Флуоресцентный белый холодный (W 3800 - 4500K)', + 'Day White Fluorescent' => 'Флуоресцентный белый дневной', + 'Daylight' => 'Дневной свет', + 'Daylight Fluorescent' => 'Флуоресцентный белый дневного света (D 5700 - 7100K)', + 'Fine Weather' => 'Ясная погода', + 'Flash' => 'Вспышка', + 'Fluorescent' => 'Флуоресцентный', + 'ISO Studio Tungsten' => 'ISO для студийных ламп накаливания', + 'Other' => 'другой источник света', + 'Shade' => 'Тень', + 'Standard Light A' => 'Стандартный свет A', + 'Standard Light B' => 'Стандартный свет B', + 'Standard Light C' => 'Стандартный свет C', + 'Tungsten (Incandescent)' => 'Лампа накаливания (яркий свет)', + 'Unknown' => 'неизвестно', + 'Warm White Fluorescent' => 'Флуоресцентный теплый белый (L 2600 - 3250K)', + 'White Fluorescent' => 'Флуоресцентный белый (WW 3250 - 3800K)', + }, + }, + 'CameraCalibration1' => 'Калибровочная матрица фотоаппарата №1', + 'CameraCalibration2' => 'Калибровочная матрица фотоаппарата №2', + 'CameraCalibrationSig' => 'Сигнатура калибровки фотоаппарата', + 'CameraSerialNumber' => 'Серийный номер фотоаппарата', + 'Caption-Abstract' => 'Подпись', + 'CaptionWriter' => 'Автор подписи', + 'Categories' => 'Категории', + 'Category' => 'Категории', + 'ChromaBlurRadius' => 'Радиус сглаживания цветности', + 'City' => 'Город', + 'ColorEffect' => { + PrintConv => { + 'Sepia' => 'Сепия', + }, + }, + 'ColorFilter' => 'Цветовой фильтр', + 'ColorMatrix1' => 'Цветовая матрица №1', + 'ColorMatrix2' => 'Цветовая матрица №2', + 'ColorMode' => { + Description => 'ТворческийСтиль', + PrintConv => { + 'Autumn Leaves' => 'Осенние листья', + 'B&W' => 'Черно-белое', + 'Clear' => 'Прозрачный', + 'Deep' => 'Глубокий', + 'Landscape' => 'Пейзаж', + 'Light' => 'Бледный', + 'Neutral' => 'Нейтральный', + 'Night View' => 'Ночной вид', + 'Night View/Portrait' => 'Ночной портрет', + 'Portrait' => 'Портрет', + 'Standard' => 'Стандартное', + 'Sunset' => 'Закат', + 'Vivid' => 'Яркий цвет', + }, + }, + 'ColorSpace' => { + Description => 'Данные о цветовой среде', + PrintConv => { + 'ICC Profile' => 'Профиль ICC', + 'Uncalibrated' => 'Не калиброванный', + }, + }, + 'ColorTemperature' => 'Цветовая температура', + 'ColorimetricReference' => 'Колориметрический эталон', + 'Comment' => 'Комментарий', + 'ComponentsConfiguration' => 'Значение каждого компонента', + 'CompressedBitsPerPixel' => 'Режим сжатия изображения', + 'Compression' => { + Description => 'Схема сжатия', + PrintConv => { + 'JPEG' => 'JPEG сжатие', + 'Uncompressed' => 'без сжатия', + }, + }, + 'Contrast' => { + Description => 'Контрастность', + PrintConv => { + 'High' => 'Резко', + 'Low' => 'Мягко', + 'Normal' => 'Стандарт', + }, + }, + 'Copyright' => 'Владелец копирайта', + 'CopyrightNotice' => 'Уведомление об авторских правах', + 'Country' => 'Страна', + 'Country-PrimaryLocationName' => 'Страна', + 'CreateDate' => 'Дата создания', + 'CreationDate' => 'Дата создания', + 'Credit' => 'Фамилия', + 'CurrentICCProfile' => 'Текущий ICC профиль', + 'CurrentPreProfileMatrix' => 'Текущая предварительная цветовая матрица', + 'CustomRendered' => { + Description => 'Обработка снимков по персональным настройкам', + PrintConv => { + 'Custom' => '"Процесс, настроенный пользователем"', + 'Normal' => 'Нормальный процесс', + }, + }, + 'DNGBackwardVersion' => 'Совместимая версия DNG', + 'DNGLensInfo' => 'Минимальное фокусное расстояние', + 'DNGVersion' => 'Версия DNG', + 'DateCreated' => 'Дата создания', + 'DateTimeOriginal' => 'Исходная дата и время', + 'DefaultCropOrigin' => 'Положение обрезанного изображения по-умолчанию', + 'DefaultCropSize' => 'Размер обрезанного изображения по-умолчанию', + 'DefaultScale' => 'Стандартный масштаб', + 'DeviceSettingDescription' => 'Описание настроек устройства', + 'DigitalZoom' => 'Цифровой зум', + 'DigitalZoomRatio' => 'Показатель цифрового зума', + 'Directory' => '"Файл, размещение"', + 'DriveMode' => 'Режим спуска', + 'DynamicRangeOptimizer' => { + Description => 'Оптим.Д-диапаз.', + PrintConv => { + 'Advanced Auto' => 'Улучш.авто', + 'Advanced Lv1' => 'Улучш.уровень1', + 'Advanced Lv2' => 'Улучш.уровень2', + 'Advanced Lv3' => 'Улучш.уровень3', + 'Advanced Lv4' => 'Улучш.уровень4', + 'Advanced Lv5' => 'Улучш.уровень5', + 'Auto' => 'Авто', + 'Off' => 'Отключено', + 'Standard' => 'Стандартное', + }, + }, + 'ExifImageHeight' => 'Допустимая высота снимка', + 'ExifImageWidth' => 'Допустимая ширина снимка', + 'ExifOffset' => 'Exif IFD указатель', + 'ExifVersion' => 'Exif версия', + 'ExposureCompensation' => '"Экспозиция, калибровка"', + 'ExposureIndex' => '"Экспозиция, показатель"', + 'ExposureMode' => { + Description => '"Экспозиция, режим"', + PrintConv => { + 'Auto' => 'Автоэкспозиция', + 'Auto bracket' => 'Автобрэкетинг', + 'Manual' => 'Ручная экспозиция', + }, + }, + 'ExposureProgram' => { + Description => 'Экспозиция программная', + PrintConv => { + 'Action (High speed)' => 'Экшен/боевик', + 'Aperture-priority AE' => 'Приоритет диафрагмы', + 'Bulb' => 'Лампа', + 'Creative (Slow speed)' => 'Творческая программа', + 'Landscape' => 'Пейзаж', + 'Manual' => '"Экспозиция, ручная"', + 'Portrait' => 'Портрет', + 'Program AE' => 'Нормальная программа', + 'Shutter speed priority AE' => 'Приоритет выдержки', + }, + }, + 'ExposureTime' => 'Выдержка', + 'FNumber' => 'Диафрагма', + 'FaceOrientation' => { + PrintConv => { + 'Horizontal (normal)' => 'Положительное направление', + 'Rotate 180' => 'Поворот на 180°', + 'Rotate 270 CW' => 'Поворот на 270° по часовой стрелке', + 'Rotate 90 CW' => 'Поворот на 90° по часовой стрелке', + }, + }, + 'FileFormat' => 'Формат', + 'FileModifyDate' => 'Дата обновления', + 'FileName' => 'Имя файла', + 'FileSize' => 'Размер файла', + 'FileSource' => { + Description => 'Источник файла', + PrintConv => { + 'Digital Camera' => 'DSC', + 'Film Scanner' => 'Сканнер просвечивающего типа', + 'Reflection Print Scanner' => 'Сканнер отражающего типа', + }, + }, + 'FileType' => 'Тип файла', + 'Filename' => 'Имя файла', + 'Flash' => { + Description => 'Вспышка', + PrintConv => { + 'Auto, Fired' => 'Вкл. (автоматическая вспышка)', + 'Auto, Fired, Red-eye reduction' => '"Вкл. (автоматическая вспышка, снижение эффекта «красных глаз»)"', + 'Auto, Fired, Red-eye reduction, Return detected' => '"Вкл. (автоматическая вспышка, снижение эффекта «красных глаз», регистрация отраженного луча)"', + 'Auto, Fired, Return detected' => '"Вкл. (автоматическая вспышка, регистрация отраженного луча)"', + 'Did not fire' => 'Вспышка не сработала', + 'Fired' => 'Вспышка сработала', + 'Fired, Red-eye reduction' => 'Вкл. (снижение эффекта «красных глаз»)', + 'Fired, Red-eye reduction, Return detected' => '"Вкл. (снижение эффекта «красных глаз», регистрация отраженного луча)"', + 'Fired, Return detected' => 'Вкл. (регистрация отраженного луча)', + 'No Flash' => 'Нет функции вспышки', + 'On, Fired' => 'Вкл. (принудительная)', + 'On, Red-eye reduction' => '"Вкл. (принудительная, снижение эффекта «красных глаз»)"', + 'On, Red-eye reduction, Return detected' => '"Вкл. (принудительная, снижение эффекта «красных глаз», регистрация отраженного луча)"', + 'On, Return detected' => '"Вкл. (принудительная, регистрация отраженного луча)"', + }, + }, + 'FlashEnergy' => 'Мощность вспышки', + 'FlashExposureComp' => 'Коррекция вспышки', + 'FlashpixVersion' => 'Поддерживаемая версия Flashpix', + 'FocalLength' => 'Фокусное расстояние', + 'FocalLength35efl' => 'Фокусное расстояние (приведено к 35 мм)', + 'FocalLengthIn35mmFormat' => 'Фокусное расстояние для 35-мм фотопленки', + 'FocalPlaneResolutionUnit' => { + Description => 'Элемент разрешения в фокальной плоскости', + PrintConv => { + 'inches' => 'дюйм', + }, + }, + 'FocalPlaneXResolution' => 'Разрешение в фокальной плоскости по X', + 'FocalPlaneYResolution' => 'Разрешение в фокальной плоскости по Y', + 'FocusMode' => 'Фокусировка', + 'ForwardMatrix1' => 'Прямая матрица №1', + 'ForwardMatrix2' => 'Прямая матрица №2', + 'FrameRate' => 'Плотность кадров', + 'FrameSize' => '"Кадр, размер"', + 'GPSAltitude' => 'Высота', + 'GPSAltitudeRef' => { + Description => 'Определение по высоте', + PrintConv => { + 'Above Sea Level' => 'Уровень моря', + 'Below Sea Level' => 'Опорное значение уровня моря (негативное значение)', + }, + }, + 'GPSAreaInformation' => 'Название области GPS', + 'GPSDOP' => 'Точность измерения', + 'GPSDateStamp' => 'Дата GPS', + 'GPSDestBearing' => 'Азимут пункта назначения', + 'GPSDestBearingRef' => 'Опорная величина для азимута пункта назначения', + 'GPSDestDistance' => 'Расстояние до пункта назначения', + 'GPSDestDistanceRef' => 'Опорная величина расстояния до пункта назначения', + 'GPSDestLatitude' => 'Широта пункта назначения', + 'GPSDestLatitudeRef' => 'Опорная величина для широты пункта назначения', + 'GPSDestLongitude' => 'Долгота пункта назначения', + 'GPSDestLongitudeRef' => 'Опорная величина для долготы пункта назначения', + 'GPSDifferential' => { + Description => 'Дифференциальная коррекция GPS', + PrintConv => { + 'Differential Corrected' => 'Дифференциальная коррекция применена', + 'No Correction' => 'Измерение без дифференциальной коррекции', + }, + }, + 'GPSImgDirection' => 'Направление изображения', + 'GPSImgDirectionRef' => 'Опорная величина для направления изображения', + 'GPSInfo' => 'IFD указатель информации GPS', + 'GPSLatitude' => 'Широта', + 'GPSLatitudeRef' => { + Description => 'Северная или южная широта', + PrintConv => { + 'North' => 'Северная широта', + 'South' => 'Южная широта', + }, + }, + 'GPSLongitude' => 'Долгота', + 'GPSLongitudeRef' => { + Description => 'Восточная или западная долгота', + PrintConv => { + 'East' => 'Восточная долгота', + 'West' => 'Западная долгота', + }, + }, + 'GPSMapDatum' => 'Использованы данные геодезических исследований', + 'GPSMeasureMode' => { + Description => 'Режим измерения GPS', + PrintConv => { + '3-Dimensional Measurement' => '3-мерное измерение', + }, + }, + 'GPSProcessingMethod' => 'Название метода обработки GPS', + 'GPSSatellites' => '"Спутники GPS, используемые для измерения"', + 'GPSSpeed' => 'Скорость GPS-устройства', + 'GPSSpeedRef' => { + Description => 'Скоростной элемент', + PrintConv => { + 'km/h' => 'Километры в час', + 'knots' => 'Узлы', + 'mph' => 'Мили в час', + }, + }, + 'GPSStatus' => { + Description => 'Состояние GPS-устройства', + PrintConv => { + 'Measurement Active' => 'Производится измерение', + 'Measurement Void' => 'Взаимная совместимость измерений', + }, + }, + 'GPSTimeStamp' => 'GPS-время (атомные часы)', + 'GPSTrack' => 'Направление движения', + 'GPSTrackRef' => { + Description => 'Опорная величина направления движения', + PrintConv => { + 'Magnetic North' => 'Направление магнитной стрелки', + 'True North' => 'Истинное направление', + }, + }, + 'GPSVersionID' => 'Версия GPS-тэга', + 'GainControl' => { + Description => 'Управление шагом', + PrintConv => { + 'High gain down' => 'С большим шагом вниз', + 'High gain up' => 'С большим шагом вверх', + 'Low gain down' => 'С малым шагом вниз', + 'Low gain up' => 'С малым шагом вверх', + 'None' => 'Нет', + }, + }, + 'Gamma' => 'Гамма', + 'Gradation' => 'Впечатляющ.режим', + 'HDR' => { + Description => 'Авто HDR', + PrintConv => { + 'Off' => 'Отключено', + }, + }, + 'Headline' => 'Заголовок', + 'HighISONoiseReduction' => { + Description => 'NR высокого ISO', + PrintConv => { + 'Auto' => 'Авто', + 'High' => 'Hi', + 'Low' => 'Lo', + 'Normal' => 'Нормальная', + 'Off' => 'Отключено', + }, + }, + 'Hue' => 'Оттенок', + 'ISO' => 'Значение ISO', + 'ImageHeight' => 'Высота снимка', + 'ImageSize' => '"Снимок, размер"', + 'ImageStabilization' => { + PrintConv => { + 'CCD Shift' => 'Оптический стабилизатор', + 'High Sensitivity' => 'Движение объекта съёмки', + 'Off' => 'Выкл', + 'Off (1)' => 'Выкл (1)', + }, + }, + 'ImageUniqueID' => 'Уникальный ID-код снимка', + 'ImageWidth' => 'Ширина снимка', + 'Index' => 'Индекс', + 'Instructions' => 'Инструкции', + 'InteropIndex' => 'Идентификация взаимной совместимости', + 'InteropOffset' => 'Тэг взаимной совместимости', + 'InteropVersion' => 'Версия взаимной совместимости', + 'JPEGQuality' => { + Description => 'Качество изображения', + PrintConv => { + 'Extra Fine' => 'Сверхвысокое', + 'Fine' => 'Высокое', + 'Standard' => 'Стандартное качество', + }, + }, + 'Keywords' => 'Ключевые слова', + 'Lens' => 'Объектив', + 'LensInfo' => 'Информация об объективе', + 'LightSource' => { + Description => 'Источник света', + PrintConv => { + 'Cloudy' => 'Облачность', + 'Cool White Fluorescent' => 'Флуоресцентный белый холодный (W 3800 - 4500K)', + 'Day White Fluorescent' => 'Флуоресцентный белый дневной', + 'Daylight' => 'Дневной свет', + 'Daylight Fluorescent' => 'Флуоресцентный белый дневного света (D 5700 - 7100K)', + 'Fine Weather' => 'Ясная погода', + 'Flash' => 'Вспышка', + 'Fluorescent' => 'Флуоресцентный', + 'ISO Studio Tungsten' => 'ISO для студийных ламп накаливания', + 'Other' => 'другой источник света', + 'Shade' => 'Тень', + 'Standard Light A' => 'Стандартный свет A', + 'Standard Light B' => 'Стандартный свет B', + 'Standard Light C' => 'Стандартный свет C', + 'Tungsten (Incandescent)' => 'Лампа накаливания (яркий свет)', + 'Unknown' => 'неизвестно', + 'Warm White Fluorescent' => 'Флуоресцентный теплый белый (L 2600 - 3250K)', + 'White Fluorescent' => 'Флуоресцентный белый (WW 3250 - 3800K)', + }, + }, + 'Lightness' => 'Освещенность', + 'LinearResponseLimit' => 'Предел линейного отклика', + 'LinearizationTable' => 'Таблица линеаризации', + 'LocalizedCameraModel' => 'Локализованное название фотоаппарата', + 'Location' => 'Место съемки', + 'LongExposureNoiseReduction' => { + Description => 'NR долгой эксп.', + PrintConv => { + 'Off' => 'Отключено', + 'On' => 'Включено', + }, + }, + 'Make' => 'Изготовитель', + 'MakerNote' => 'Приватные данные DNG', + 'MakerNoteSafety' => { + Description => 'Безопасность «примечаний производителя»', + PrintConv => { + 'Safe' => 'Безопасно', + 'Unsafe' => 'Небезопасно', + }, + }, + 'MakerNotes' => 'Данные производителей', + 'MaskedAreas' => 'Неактивные области', + 'MaxAperture' => 'Макс. диафрагма объектива', + 'MeteringMode' => { + Description => 'Экспозамер', + PrintConv => { + 'Average' => 'Средний', + 'Center-weighted average' => 'Центрально-взвешенный средний', + 'Multi-segment' => 'Узор', + 'Multi-spot' => 'Многозональный', + 'Other' => 'Другое', + 'Partial' => 'Частичный', + 'Spot' => 'Точечный', + 'Unknown' => 'неизвестно', + }, + }, + 'Model' => 'Камера', + 'ModifyDate' => '"Файл, изменить дату и время"', + 'MultiFrameNoiseReduction' => { + Description => 'Многокадр. шумоподавл.', + PrintConv => { + 'Off' => 'Отключено', + 'On' => 'Включено', + }, + }, + 'NoiseReduction' => 'Шумоподавление', + 'NoiseReductionApplied' => 'Применённое шумоподавление', + 'Opto-ElectricConvFactor' => 'Фактор оптико-электрического преобразования', + 'Orientation' => { + Description => 'Ориентация', + PrintConv => { + 'Horizontal (normal)' => 'Положительное направление', + 'Rotate 180' => 'Поворот на 180°', + 'Rotate 270 CW' => 'Поворот на 270° по часовой стрелке', + 'Rotate 90 CW' => 'Поворот на 90° по часовой стрелке', + }, + }, + 'OriginalRawFileData' => 'Исходные данные raw-файла', + 'OriginalRawFileDigest' => 'Сигнатура исходного Raw-файла', + 'OriginalRawFileName' => 'Исходное имя Raw-файла', + 'PhotometricInterpretation' => 'Состав пиксела', + 'PlanarConfiguration' => { + Description => 'Организация данных изображения', + PrintConv => { + 'Chunky' => 'крупный формат', + 'Planar' => 'планарный формат', + }, + }, + 'PreviewApplicationName' => 'Имя приложения предпросмотра', + 'PreviewApplicationVersion' => 'Версия изображения предпросмотра', + 'PreviewColorSpace' => { + Description => 'Цветовое пространство предпросмотра', + PrintConv => { + 'Unknown' => 'Неизвестно', + }, + }, + 'PreviewDateTime' => 'Дата и время предпросмотра', + 'PreviewSettingsDigest' => 'Сигнатура настроек предпросмотра', + 'PreviewSettingsName' => 'Название настроек предпросмотра', + 'PrimaryChromaticities' => 'Тональность основных цветов', + 'ProfileCalibrationSig' => 'Сигнатура калибровки профиля', + 'ProfileCopyright' => 'Авторские права профиля', + 'ProfileEmbedPolicy' => { + Description => 'Политика внедрения профиля', + PrintConv => { + 'Allow Copying' => 'Разрешено копирование', + 'Embed if Used' => 'Внедрить если использован', + 'Never Embed' => 'Никогда не внедрять', + 'No Restrictions' => 'Нет ограничений', + }, + }, + 'ProfileHueSatMapData1' => 'Даные отображения оттенка/насыщенности №1', + 'ProfileHueSatMapData2' => 'Даные отображения оттенка/насыщенности №2', + 'ProfileHueSatMapDims' => 'Количество образцов оттенков', + 'ProfileLookTableData' => 'Данные таблицы просмотра', + 'ProfileLookTableDims' => 'Количество образцов оттенков', + 'ProfileName' => 'Имя профиля', + 'ProfileToneCurve' => 'Кривая яроксти профиля', + 'Province-State' => 'Область/район', + 'Quality' => { + Description => 'Качество изображения', + PrintConv => { + 'Compressed RAW' => 'cRAW', + 'Compressed RAW + JPEG' => 'cRAW+JPEG', + 'Extra Fine' => 'Сверхвысокое', + 'Fine' => 'Высокое', + 'Low' => 'Низкое качество', + 'Normal' => 'Стандартное качество', + 'RAW + JPEG' => 'RAW+JPEG', + 'Standard' => 'Стандартное', + }, + }, + 'RawDataUniqueID' => 'Уникальный идентификатор файла', + 'RawImageDigest' => 'Сигнатура RAW-файла', + 'RecordMode' => 'Режим записи', + 'ReductionMatrix1' => 'Матрица редукции №1', + 'ReductionMatrix2' => 'Матрица редукции 2', + 'ReferenceBlackWhite' => 'Пара опорных значений черного и белого', + 'RelatedImageFileFormat' => 'Формат файла связанного снимка', + 'RelatedImageHeight' => 'Длина связанного снимка', + 'RelatedImageWidth' => 'Ширина связанного снимка', + 'RelatedSoundFile' => 'Связанный аудио-файл', + 'ResolutionUnit' => { + Description => 'Элемент разрешения по X и Y', + PrintConv => { + 'cm' => 'сантиметры', + 'inches' => 'дюймы', + }, + }, + 'RowInterleaveFactor' => 'Ширина чередования строк', + 'RowsPerStrip' => 'Число рядов в полосе', + 'SamplesPerPixel' => 'Количество компонентов', + 'Saturation' => { + Description => 'Насыщенность', + PrintConv => { + 'High' => 'Высокая насыщенность', + 'Low' => 'Низкая насыщенность', + 'Normal' => 'Стандартный', + }, + }, + 'SceneCaptureType' => { + Description => 'Сюжетная программа', + PrintConv => { + 'Landscape' => 'Пейзаж', + 'Night' => 'Ночная съемка', + 'Portrait' => 'Портрет', + 'Standard' => 'Стандартный', + }, + }, + 'SceneMode' => { + Description => 'Выбор сцены', + PrintConv => { + '3D Sweep Panorama' => '3D', + 'Anti Motion Blur' => 'Устр. размыт. движ.', + 'Auto' => 'Авто', + 'Cont. Priority AE' => 'Непрер. приор. АЭ', + 'Handheld Night Shot' => 'Ночная съемка с рук', + 'Landscape' => 'Пейзаж', + 'Macro' => 'Макросъёмка', + 'Night Portrait' => 'Ночной портрет', + 'Night Scene' => 'Ночной вид', + 'Night View/Portrait' => 'Ночной вид/портрет', + 'Portrait' => 'Портрет', + 'Sports' => 'Спортивные сцены', + 'Sunset' => 'Закат', + 'Sweep Panorama' => 'Панорамный обзор', + }, + }, + 'SceneType' => { + Description => 'Тип сюжета', + PrintConv => { + 'Directly photographed' => 'Непосредственно полученный снимок', + }, + }, + 'SensingMethod' => { + Description => 'Метод регистрации', + PrintConv => { + 'Color sequential area' => 'Последовательный сенсор цветовой области', + 'Color sequential linear' => 'Последовательный линейный цветовой сенсор', + 'One-chip color area' => 'Однопроцессорный сенсор цветовой области', + 'Three-chip color area' => 'Трехпроцессорный сенсор цветовой области', + 'Trilinear' => 'Трехлинейный цветовой сенсор', + 'Two-chip color area' => 'Двухпроцессорный сенсор цветовой области', + }, + }, + 'SerialNumber' => 'ID-код фотокамеры', + 'ShadingCompensation' => 'Устранение теней', + 'ShadowScale' => 'Диапазон теней', + 'Sharpness' => { + Description => 'Резкость', + PrintConv => { + 'Hard' => 'Резкий', + 'Normal' => 'Стандартный', + 'Soft' => 'Мягкий', + }, + }, + 'ShootingMode' => 'Режим съемки', + 'ShutterSpeed' => 'Выдержка', + 'ShutterSpeedValue' => 'Выдержка', + 'Software' => 'Имя и версия ПО', + 'Source' => 'Источник', + 'SpatialFrequencyResponse' => 'Пространственная частотная характеристика', + 'SpectralSensitivity' => 'Спектральная чувствительность', + 'State' => 'Область', + 'StripByteCounts' => 'Байт на сжатую полосу', + 'StripOffsets' => 'Расположение данных изображения', + 'SubSecTime' => '"Дата и время, суб-секунды"', + 'SubSecTimeDigitized' => '"Дата и время цифровое, суб-секунды"', + 'SubSecTimeOriginal' => '"Дата и время исходное, суб-секунды"', + 'SubTileBlockSize' => 'Размер блока в тайле', + 'SubjectArea' => 'Область объекта', + 'SubjectDistance' => 'Расстояние до объекта', + 'SubjectDistanceRange' => { + Description => 'Диапазон расстояний до объекта', + PrintConv => { + 'Close' => 'Крупный план', + 'Distant' => 'Удаленный план', + 'Macro' => 'Макро', + }, + }, + 'SubjectLocation' => 'Расположение объекта', + 'SupplementalCategories' => 'Дополнительные категории', + 'ThumbnailImage' => 'Пиктограмма', + 'ThumbnailImageSize' => 'Размер пиктограмм', + 'Title' => 'Заголовок', + 'TransferFunction' => 'Функция переноса', + 'TransmissionReference' => 'Ссылка на источник', + 'UniqueCameraModel' => 'Уникальная модель фотоаппарата', + 'Urgency' => 'Приоритетность', + 'UserComment' => 'Комментарии пользователя', + 'WhiteBalance' => { + Description => 'Баланс белого', + PrintConv => { + 'Auto' => 'Автоматический баланс белого', + 'Black & White' => 'Монохром', + 'Cloudy' => 'Облачность', + 'Color Temperature/Color Filter' => 'Цветовая температура / Цветовой фильтр', + 'Cool White Fluorescent' => 'Флуоресцентный белый холодный', + 'Custom' => 'Пользователь', + 'Custom 1' => 'ПЕРСОНАЛЬНЫЙ 1', + 'Custom 2' => 'ПЕРСОНАЛЬНЫЙ 2', + 'Custom 3' => 'ПЕРСОНАЛЬНЫЙ 3', + 'Custom 4' => 'ПЕРСОНАЛЬНЫЙ 4', + 'Day White Fluorescent' => 'Флуоресцентный белый дневной', + 'Daylight' => 'Дневной свет', + 'Daylight Fluorescent' => 'Флуоресцентный дневной', + 'Flash' => 'Вспышка', + 'Fluorescent' => 'Флуоресцентный', + 'Manual' => 'Ручная настройка баланса белого', + 'Shade' => 'Тень', + 'Tungsten' => 'Лампа накаливания', + 'Unknown' => 'неизвестно', + 'Warm White Fluorescent' => 'Флуоресцентный теплый белый', + 'White Fluorescent' => 'Флуоресцентный белый', + }, + }, + 'WhiteLevel' => 'Уровень белого', + 'WhitePoint' => 'Цветность белой точки', + 'Writer-Editor' => 'Автор подписи', + 'YCbCrCoefficients' => 'Матричные коэффициенты преобразования цветовой среды', + 'YCbCrPositioning' => { + Description => 'Позиция по Y и C', + PrintConv => { + 'Centered' => 'центрованный', + 'Co-sited' => 'совпадающий по месту', + }, + }, + 'YCbCrSubSampling' => 'Коэффициент субдискретизации Y и C', + 'ZoneMatching' => { + Description => 'Соответствие областей', + PrintConv => { + 'High Key' => 'Hi', + 'ISO Setting Used' => 'Отключено', + 'Low Key' => 'Lo', + }, + }, +); + +1; # end + + +__END__ + +=head1 NAME + +Image::ExifTool::Lang::ru.pm - ExifTool Russian language translations + +=head1 DESCRIPTION + +This file is used by Image::ExifTool to generate localized tag descriptions +and values. + +=head1 AUTHOR + +Copyright 2003-2019, Phil Harvey (phil at owl.phy.queensu.ca) + +This library is free software; you can redistribute it and/or modify it +under the same terms as Perl itself. + +=head1 ACKNOWLEDGEMENTS + +Thanks to Jens Duttke, Sergey Shemetov, Dmitry Yerokhin and Anton Sukhinov +for providing this translation. + +=head1 SEE ALSO + +L<Image::ExifTool(3pm)|Image::ExifTool>, +L<Image::ExifTool::TagInfoXML(3pm)|Image::ExifTool::TagInfoXML> + +=cut diff --git a/lib/Image/ExifTool/Lang/sv.pm b/lib/Image/ExifTool/Lang/sv.pm new file mode 100644 index 0000000..6b4cf55 --- /dev/null +++ b/lib/Image/ExifTool/Lang/sv.pm @@ -0,0 +1,638 @@ +#------------------------------------------------------------------------------ +# File: sv.pm +# +# Description: ExifTool Swedish language translations +# +# Notes: This file generated automatically by Image::ExifTool::TagInfoXML +#------------------------------------------------------------------------------ + +package Image::ExifTool::Lang::sv; + +use strict; +use vars qw($VERSION); + +$VERSION = '1.05'; + +%Image::ExifTool::Lang::sv::Translate = ( + 'Aperture' => 'Bländare', + 'ApertureValue' => 'Bländare', + 'Artist' => 'Upphovsman', + 'Author' => 'Upphovsman', + 'AuthorsPosition' => 'Författarens befattning', + 'BitsPerSample' => 'Antal bitar per komponent', + 'Brightness' => 'Ljusstyrka', + 'By-line' => 'Upphovsman', + 'CFAPattern' => 'CFA-mönster', + 'CalibrationIlluminant1' => { + PrintConv => { + 'Cloudy' => 'Mulet', + 'Cool White Fluorescent' => 'Kalljusrör (W 3800 - 4500 k)', + 'Day White Fluorescent' => 'Dagljusrör, högdager (N 4600 - 5500k)', + 'Daylight' => 'Dagsljus', + 'Daylight Fluorescent' => 'Dagljusrör (D 5700 - 7100 k)', + 'Fine Weather' => 'Fint väder', + 'Flash' => 'Blixt', + 'Fluorescent' => 'Lysrörsbelysning', + 'ISO Studio Tungsten' => 'ISO tungsten studiobelysning', + 'Other' => 'Annan ljuskälla', + 'Shade' => 'Skugga', + 'Standard Light A' => 'Standardljus A', + 'Standard Light B' => 'Standardljus B', + 'Standard Light C' => 'Standardljus C', + 'Tungsten (Incandescent)' => 'Tungsten', + 'Unknown' => 'Okänt', + 'Warm White Fluorescent' => 'Varmt vitt fluorescerande (L 2600 - 3250k)', + 'White Fluorescent' => 'Vit lysrörsbelysning (WW 3250 - 3800 k)', + }, + }, + 'CalibrationIlluminant2' => { + PrintConv => { + 'Cloudy' => 'Mulet', + 'Cool White Fluorescent' => 'Kalljusrör (W 3800 - 4500 k)', + 'Day White Fluorescent' => 'Dagljusrör, högdager (N 4600 - 5500k)', + 'Daylight' => 'Dagsljus', + 'Daylight Fluorescent' => 'Dagljusrör (D 5700 - 7100 k)', + 'Fine Weather' => 'Fint väder', + 'Flash' => 'Blixt', + 'Fluorescent' => 'Lysrörsbelysning', + 'ISO Studio Tungsten' => 'ISO tungsten studiobelysning', + 'Other' => 'Annan ljuskälla', + 'Shade' => 'Skugga', + 'Standard Light A' => 'Standardljus A', + 'Standard Light B' => 'Standardljus B', + 'Standard Light C' => 'Standardljus C', + 'Tungsten (Incandescent)' => 'Tungsten', + 'Unknown' => 'Okänt', + 'Warm White Fluorescent' => 'Varmt vitt fluorescerande (L 2600 - 3250k)', + 'White Fluorescent' => 'Vit lysrörsbelysning (WW 3250 - 3800 k)', + }, + }, + 'Caption-Abstract' => 'Bildtext', + 'CaptionWriter' => 'Bildtextredigerare', + 'Categories' => 'Kategorier', + 'Category' => 'Kategorier', + 'City' => 'Ort', + 'ColorFilter' => 'Färgfilter', + 'ColorMode' => { + Description => 'Kreativa inst.', + PrintConv => { + 'Autumn Leaves' => 'Höstlöv', + 'B&W' => 'Svartvitt', + 'Clear' => 'Klart', + 'Deep' => 'Djupt', + 'Landscape' => 'Landskap', + 'Light' => 'Ljust', + 'Neutral' => 'Neutralt', + 'Night View' => 'Nattvy', + 'Night View/Portrait' => 'Nattporträtt', + 'Portrait' => 'Porträtt', + 'Sunset' => 'Solnedgång', + 'Vivid' => 'Levande färg', + }, + }, + 'ColorSpace' => { + Description => 'Färgområdesinformation', + PrintConv => { + 'ICC Profile' => 'ICC-profil', + 'Uncalibrated' => 'Ej kalibrerat', + }, + }, + 'ColorTemperature' => 'Färgtemperatur', + 'Comment' => 'Kommentar', + 'ComponentsConfiguration' => 'Enskilda komponenters betydelse', + 'CompressedBitsPerPixel' => 'Bildkomprimeringsläge', + 'Compression' => { + Description => 'Komprimeringsschema', + PrintConv => { + 'JPEG' => 'JPEG-komprimering', + 'Uncompressed' => 'Ingen komprimering', + }, + }, + 'Contrast' => { + Description => 'Kontrast', + PrintConv => { + 'High' => 'Hård', + 'Low' => 'Mjuk', + 'Normal' => 'Standard', + }, + }, + 'Copyright' => 'Copyright-innehavare', + 'CopyrightNotice' => 'Copyrightmeddelande', + 'Country' => 'Land', + 'Country-PrimaryLocationName' => 'Land', + 'CreateDate' => 'Skapat datum', + 'CreationDate' => 'Skapad datum', + 'Credit' => 'Medverkande', + 'CustomRendered' => { + Description => 'Anpassad bildbearbetning', + PrintConv => { + 'Custom' => 'Anpassad process', + 'Normal' => 'Normal process', + }, + }, + 'DateCreated' => 'Skapat datum', + 'DateTimeOriginal' => 'Ursprungligt datum & tid', + 'DeviceSettingDescription' => 'Beskrivning av enhetsinställning', + 'DigitalZoomRatio' => 'Digitalt zoomomfång', + 'Directory' => 'Filplats', + 'DriveMode' => 'Enhetsläge', + 'DynamicRangeOptimizer' => { + Description => 'Opt.av dyn.omr.', + PrintConv => { + 'Advanced Auto' => 'Avancerad auto', + 'Advanced Lv1' => 'Avancerad niv1', + 'Advanced Lv2' => 'Avancerad niv2', + 'Advanced Lv3' => 'Avancerad niv3', + 'Advanced Lv4' => 'Avancerad niv4', + 'Advanced Lv5' => 'Avancerad niv5', + 'Auto' => 'Automatisk', + 'Off' => 'Av', + }, + }, + 'ExifImageHeight' => 'Giltig bildhöjd', + 'ExifImageWidth' => 'Giltig bildbredd', + 'ExifOffset' => 'IFD-pekare för Exif', + 'ExifVersion' => 'Exif-version', + 'ExposureCompensation' => 'Exponeringsförskjutning', + 'ExposureIndex' => 'Exponeringsindex', + 'ExposureMode' => { + Description => 'Exponeringsläge', + PrintConv => { + 'Auto' => 'Automatisk exponering', + 'Auto bracket' => 'Automatisk alternativexponering', + 'Manual' => 'Manuell exponering', + }, + }, + 'ExposureProgram' => { + Description => 'Exponeringsprogram', + PrintConv => { + 'Action (High speed)' => 'Sport', + 'Aperture-priority AE' => 'Bländarprioritet', + 'Bulb' => 'Glödlampa', + 'Creative (Slow speed)' => 'Kreativ', + 'Landscape' => 'Liggande', + 'Manual' => 'Manuell exponering', + 'Portrait' => 'Stående', + 'Program AE' => 'Normalt program', + 'Shutter speed priority AE' => 'Slutarprioritet', + }, + }, + 'ExposureTime' => 'Exponeringstid', + 'FNumber' => 'Bländare', + 'FaceOrientation' => { + PrintConv => { + 'Horizontal (normal)' => 'Positiv riktning', + 'Rotate 90 CW' => 'Rotera 90° medurs', + }, + }, + 'FileFormat' => 'Format', + 'FileModifyDate' => 'Uppdateringsdatum', + 'FileName' => 'Filnamn', + 'FileSize' => 'Filstorlek', + 'FileSource' => { + Description => 'Filkälla', + PrintConv => { + 'Digital Camera' => 'DSC', + 'Film Scanner' => 'Skanner av transparent typ', + 'Reflection Print Scanner' => 'Skanner av reflextyp', + }, + }, + 'FileType' => 'Filtyp', + 'Filename' => 'Filnamn', + 'Flash' => { + Description => 'Blixt', + PrintConv => { + 'Auto, Fired' => 'PÅ (automatisk blixt)', + 'Auto, Fired, Red-eye reduction' => '"PÅ (automatisk blixt, reducering av röda ögon)"', + 'Auto, Fired, Red-eye reduction, Return detected' => '"PÅ (automatisk blixt, reducering av röda ögon, reflekterat ljus)"', + 'Auto, Fired, Return detected' => '"PÅ (automatisk blixt, reflekterat ljus)"', + 'Did not fire' => 'Blixten utlöstes inte', + 'Fired' => 'Blixten utlöstes', + 'Fired, Red-eye reduction' => 'PÅ (reducering av röda ögon)', + 'Fired, Red-eye reduction, Return detected' => '"PÅ (reducering av röda ögon, reflekterat ljus)"', + 'Fired, Return detected' => 'PÅ (reflekterat ljus)', + 'No Flash' => 'Ingen blixtfunktion', + 'On, Fired' => 'PÅ (upplättnad)', + 'On, Red-eye reduction' => '"PÅ (upplättnad, reducering av röda ögon)"', + 'On, Red-eye reduction, Return detected' => '"PÅ upplättnad reducering av röda ögon, reflekterat ljus)"', + 'On, Return detected' => '"PÅ (upplättnad, reflekterat ljus)"', + }, + }, + 'FlashEnergy' => 'Blixtenergi', + 'FlashExposureComp' => 'Blixtkompensering', + 'FlashpixVersion' => 'Flashpix-version som stöds', + 'FocalLength' => 'Brännvidd', + 'FocalLength35efl' => 'Brännvidd (i 35 mm format)', + 'FocalLengthIn35mmFormat' => 'Brännvidd för 35 mm-film', + 'FocalPlaneResolutionUnit' => { + PrintConv => { + 'inches' => 'tum', + }, + }, + 'FocusMode' => 'Fokustyp', + 'FrameRate' => 'Bildfrekvens', + 'FrameSize' => 'Bildstorlek', + 'GPSAltitude' => 'Höjd', + 'GPSAltitudeRef' => { + Description => 'Höjdreferens', + PrintConv => { + 'Above Sea Level' => 'Havsnivå', + 'Below Sea Level' => 'Havsnivåref. (negativt värde)', + }, + }, + 'GPSAreaInformation' => 'Namn på GPS-område', + 'GPSDOP' => 'Måttprecision', + 'GPSDateStamp' => 'GPS-datum', + 'GPSDestBearing' => 'Destination', + 'GPSDestBearingRef' => 'Referens för destination', + 'GPSDestDistance' => 'Avstånd till destination', + 'GPSDestDistanceRef' => 'Referens för avstånd till destination', + 'GPSDestLatitude' => 'Destinationsbredd', + 'GPSDestLatitudeRef' => 'Referens för destionationsbredd', + 'GPSDestLongitude' => 'Destionationslängd', + 'GPSDestLongitudeRef' => 'Referens för destinationslängd', + 'GPSDifferential' => { + Description => 'GPS-differentialkorrigering', + PrintConv => { + 'Differential Corrected' => 'Differentialkorrigering använd', + 'No Correction' => 'Mätning utan differentialkorrigering', + }, + }, + 'GPSImgDirection' => 'Bildriktning', + 'GPSImgDirectionRef' => 'Referens för bildriktning', + 'GPSInfo' => 'IFD-pekare för GPS-information', + 'GPSLatitude' => 'Bredd', + 'GPSLatitudeRef' => { + Description => 'Nordlig eller sydlig bredd', + PrintConv => { + 'North' => 'Nordlig bredd', + 'South' => 'Sydlig bredd', + }, + }, + 'GPSLongitude' => 'Längd', + 'GPSLongitudeRef' => { + Description => 'Östlig eller västlig längd', + PrintConv => { + 'East' => 'Östlig längd', + 'West' => 'Västlig längd', + }, + }, + 'GPSMapDatum' => 'Geodetiska mätningsdata använda', + 'GPSMeasureMode' => { + Description => 'GPS-mätningsläge', + PrintConv => { + '3-Dimensional Measurement' => '3D-mätning', + }, + }, + 'GPSProcessingMethod' => 'Namn på GPS-bearbetningsmetod', + 'GPSSatellites' => 'GPS-satelliter använda för mätning', + 'GPSSpeed' => 'Hastighet på GPS-mottagare', + 'GPSSpeedRef' => { + Description => 'Hastighetsenhet', + PrintConv => { + 'km/h' => 'Km/tim', + 'knots' => 'Knop', + 'mph' => 'Miles/tim', + }, + }, + 'GPSStatus' => { + Description => 'GPS-mottagarstatus', + PrintConv => { + 'Measurement Active' => 'Mätning pågår', + 'Measurement Void' => 'Mätningssamverkan', + }, + }, + 'GPSTimeStamp' => 'GPS-tid (atomur)', + 'GPSTrack' => 'Rörelseriktning', + 'GPSTrackRef' => { + Description => 'Referens för rörelseriktning', + PrintConv => { + 'Magnetic North' => 'Magnetisk riktning', + 'True North' => 'Verklig riktning', + }, + }, + 'GPSVersionID' => 'GPS tag version', + 'GainControl' => { + Description => 'Förstärkningskontroll', + PrintConv => { + 'High gain down' => 'Hög förstärkning ned', + 'High gain up' => 'Hög förstärkning upp', + 'Low gain down' => 'Låg förstärkning ned', + 'Low gain up' => 'Låg förstärkning upp', + 'None' => 'Ingen', + }, + }, + 'Gradation' => 'Effektfull', + 'HDR' => { + Description => 'Auto HDR', + PrintConv => { + 'Off' => 'Av', + }, + }, + 'Headline' => 'Rubrik', + 'HighISONoiseReduction' => { + Description => 'Hög-ISO brusred', + PrintConv => { + 'Auto' => 'Automatisk', + 'High' => 'Hög', + 'Low' => 'Låg', + 'Off' => 'Av', + }, + }, + 'Hue' => 'Nyans', + 'ICCProfile' => 'ICC profil', + 'ISO' => 'ISO värde', + 'ImageHeight' => 'Bildhöjd', + 'ImageSize' => 'Bildstorlek', + 'ImageUniqueID' => 'Unikt bild-ID', + 'ImageWidth' => 'Bildbredd', + 'Index' => 'Småbilder', + 'Instructions' => 'Instruktioner', + 'InteropIndex' => 'Interoperability Identification', + 'InteropOffset' => 'Interoperability tag', + 'InteropVersion' => 'Interoperability Version', + 'JPEGQuality' => { + Description => 'Bildkvalitet', + PrintConv => { + 'Extra Fine' => 'Extra fin', + 'Fine' => 'Fin', + 'Standard' => 'Standardkvalitet', + }, + }, + 'Keywords' => 'Nyckelord', + 'Lens' => 'Objektiv', + 'LensInfo' => 'Objektivinformation', + 'LightSource' => { + Description => 'Ljuskälla', + PrintConv => { + 'Cloudy' => 'Mulet', + 'Cool White Fluorescent' => 'Kalljusrör (W 3800 - 4500 k)', + 'Day White Fluorescent' => 'Dagljusrör, högdager (N 4600 - 5500k)', + 'Daylight' => 'Dagsljus', + 'Daylight Fluorescent' => 'Dagljusrör (D 5700 - 7100 k)', + 'Fine Weather' => 'Fint väder', + 'Flash' => 'Blixt', + 'Fluorescent' => 'Lysrörsbelysning', + 'ISO Studio Tungsten' => 'ISO tungsten studiobelysning', + 'Other' => 'Annan ljuskälla', + 'Shade' => 'Skugga', + 'Standard Light A' => 'Standardljus A', + 'Standard Light B' => 'Standardljus B', + 'Standard Light C' => 'Standardljus C', + 'Tungsten (Incandescent)' => 'Tungsten', + 'Unknown' => 'Okänt', + 'Warm White Fluorescent' => 'Varmt vitt fluorescerande (L 2600 - 3250k)', + 'White Fluorescent' => 'Vit lysrörsbelysning (WW 3250 - 3800 k)', + }, + }, + 'Lightness' => 'Ljushet', + 'Location' => 'Plats', + 'LongExposureNoiseReduction' => { + Description => 'Långexp.brusred', + PrintConv => { + 'Off' => 'Av', + 'On' => 'På', + }, + }, + 'Make' => 'Tillverkare', + 'MakerNotes' => 'Tillverkare', + 'MaxAperture' => 'Största bländare', + 'MeteringMode' => { + Description => 'Mätningstyp', + PrintConv => { + 'Average' => 'Genomsnitt', + 'Center-weighted average' => 'Centrumvägd genomsnittsmätning', + 'Multi-segment' => 'Mönster', + 'Multi-spot' => 'MultiSpot', + 'Other' => 'Annat', + 'Partial' => 'Delvis', + 'Unknown' => 'Okänt', + }, + }, + 'Model' => 'Kamera', + 'ModifyDate' => 'Filändringsdatum och -tid', + 'MultiFrameNoiseReduction' => { + Description => 'Multi Frame brusred.', + PrintConv => { + 'Off' => 'Av', + 'On' => 'På', + }, + }, + 'NoiseReduction' => 'Brusreducering', + 'Opto-ElectricConvFactor' => 'Optoelektrisk konverteringsfaktor', + 'Orientation' => { + Description => 'Orientering', + PrintConv => { + 'Horizontal (normal)' => 'Positiv riktning', + 'Rotate 90 CW' => 'Rotera 90° medurs', + }, + }, + 'PhotometricInterpretation' => 'Pixelsammansättning', + 'PlanarConfiguration' => { + Description => 'Bilddataordning', + PrintConv => { + 'Chunky' => 'Kompakt format', + 'Planar' => 'Planar format', + }, + }, + 'PrimaryChromaticities' => 'Kromaticitet för primärfärger', + 'Province-State' => 'Län/provins', + 'Quality' => { + Description => 'Bildkvalitet', + PrintConv => { + 'Compressed RAW' => 'cRAW', + 'Compressed RAW + JPEG' => 'cRAW+JPEG', + 'Extra Fine' => 'Extra fin', + 'Fine' => 'Fin', + 'Low' => 'Låg kvalitet', + 'Normal' => 'Standardkvalitet', + 'RAW + JPEG' => 'RAW+JPEG', + }, + }, + 'RecordMode' => 'Inspelningsläge', + 'ReferenceBlackWhite' => 'Par av svartvita referensvärden', + 'RelatedImageFileFormat' => 'Tillhörande bildfilsformat', + 'RelatedImageHeight' => 'Tillhörande bildlängd', + 'RelatedImageWidth' => 'Tillhörande bildbredd', + 'RelatedSoundFile' => 'Tillhörande ljudfil', + 'ResolutionUnit' => { + Description => 'Enhet för X- och Y-upplösning', + PrintConv => { + 'cm' => 'centimeter', + 'inches' => 'tum', + }, + }, + 'RowsPerStrip' => 'Antal rader', + 'SamplesPerPixel' => 'Antal komponenter', + 'Saturation' => { + Description => 'Mättnad', + PrintConv => { + 'High' => 'Hög mättnad', + 'Low' => 'Låg mättnad', + 'Normal' => 'Standard', + }, + }, + 'SceneCaptureType' => { + Description => 'Motivtyp', + PrintConv => { + 'Landscape' => 'Landskap', + 'Night' => 'Nattmotiv', + 'Portrait' => 'Porträtt', + }, + }, + 'SceneMode' => { + Description => 'Scenval', + PrintConv => { + '3D Sweep Panorama' => '3D', + 'Anti Motion Blur' => 'Anti-rörelseoskärpa', + 'Auto' => 'Automatisk', + 'Cont. Priority AE' => 'Kont. prioritet AE', + 'Handheld Night Shot' => 'Manuell nattbild', + 'Landscape' => 'Landskap', + 'Macro' => 'Makro', + 'Night Portrait' => 'Nattporträtt', + 'Night Scene' => 'Nattvy', + 'Night View/Portrait' => 'Nattvy/porträtt', + 'Portrait' => 'Porträtt', + 'Sports' => 'Sporthändelse', + 'Sunset' => 'Solnedgång', + 'Sweep Panorama' => 'Panorering', + }, + }, + 'SceneType' => { + Description => 'Motivtyp', + PrintConv => { + 'Directly photographed' => 'En direktfotograferad bild', + }, + }, + 'SensingMethod' => { + Description => 'Avkänningsmetod', + PrintConv => { + 'Color sequential area' => 'Color sequential area sensor', + 'Color sequential linear' => 'Color sequential linear sensor', + 'One-chip color area' => 'One-chip color area sensor', + 'Three-chip color area' => 'Three-chip color area sensor', + 'Trilinear' => 'Trilinear sensor', + 'Two-chip color area' => 'Two-chip color area sensor', + }, + }, + 'SerialNumber' => 'Kamera-ID', + 'ShadingCompensation' => 'Skuggkompensering', + 'Sharpness' => { + Description => 'Skärpa', + PrintConv => { + 'Hard' => 'Hård', + 'Normal' => 'Standard', + 'Soft' => 'Mjuk', + }, + }, + 'ShootingMode' => 'Fotograferingsläge', + 'ShutterSpeed' => 'Exponeringstid', + 'ShutterSpeedValue' => 'Slutartid', + 'Software' => 'Programvara', + 'Source' => 'Källa', + 'SpatialFrequencyResponse' => 'Frekvensomfång', + 'SpectralSensitivity' => 'Spektral känslighet', + 'State' => 'Län', + 'StripByteCounts' => 'Byte komprimerade', + 'StripOffsets' => 'Plats för bilddata', + 'SubSecTime' => 'DateTime subseconds', + 'SubSecTimeDigitized' => 'DateTimeDigitized subseconds', + 'SubSecTimeOriginal' => 'DateTimeOriginal subseconds', + 'SubjectArea' => 'Motivyta', + 'SubjectDistance' => 'Motivavstånd', + 'SubjectDistanceRange' => { + Description => 'Motivavstånd', + PrintConv => { + 'Close' => 'Nära håll', + 'Distant' => 'Långt håll', + 'Macro' => 'Makro', + }, + }, + 'SubjectLocation' => 'Motivets placering', + 'SupplementalCategories' => 'Tilläggskategorier', + 'ThumbnailImage' => 'Miniatyr', + 'ThumbnailImageSize' => 'Miniatyrstorlek', + 'Title' => 'Titel', + 'TransferFunction' => 'Överföringsfunktion', + 'TransmissionReference' => 'Sändningsreferens', + 'Urgency' => 'Prioritet', + 'UserComment' => 'Användarkommentarer', + 'WhiteBalance' => { + Description => 'Vitbalans', + PrintConv => { + 'Auto' => 'Automatisk vitbalans', + 'Black & White' => 'Monokrom', + 'Cloudy' => 'Mulet', + 'Color Temperature/Color Filter' => 'Färgtemperatur / Färgfilter', + 'Cool White Fluorescent' => 'Kalljusrör', + 'Custom' => 'Special', + 'Custom 1' => 'ANPASSNING1', + 'Custom 2' => 'ANPASSNING2', + 'Custom 3' => 'ANPASSNING3', + 'Custom 4' => 'ANPASSNING4', + 'Day White Fluorescent' => '"Dagljusrör, högdager"', + 'Daylight' => 'Dagsljus', + 'Daylight Fluorescent' => 'Dagljusrör', + 'Flash' => 'Blixt', + 'Fluorescent' => 'Lysrörsbelysning', + 'Manual' => 'Manuell vitbalans', + 'Shade' => 'Skugga', + 'Tungsten' => 'Glödlampa', + 'Unknown' => 'Okänt', + 'Warm White Fluorescent' => 'Varmt vitt fluorescerande', + 'White Fluorescent' => 'Vit lysrörsbelysning', + }, + }, + 'WhitePoint' => 'Vitpunktskromaticitet', + 'Writer-Editor' => 'Bildtextredigerare', + 'YCbCrCoefficients' => 'Koefficienter för färgområdesomvandling', + 'YCbCrPositioning' => { + Description => 'Y- och C-placering', + PrintConv => { + 'Centered' => 'Centrerad', + }, + }, + 'YCbCrSubSampling' => 'Subsampling ratio of Y to C', + 'ZoneMatching' => { + Description => 'Zonmatchning', + PrintConv => { + 'High Key' => 'Hög', + 'ISO Setting Used' => 'Av', + 'Low Key' => 'Låg', + }, + }, +); + +1; # end + + +__END__ + +=head1 NAME + +Image::ExifTool::Lang::sv.pm - ExifTool Swedish language translations + +=head1 DESCRIPTION + +This file is used by Image::ExifTool to generate localized tag descriptions +and values. + +=head1 AUTHOR + +Copyright 2003-2019, Phil Harvey (phil at owl.phy.queensu.ca) + +This library is free software; you can redistribute it and/or modify it +under the same terms as Perl itself. + +=head1 ACKNOWLEDGEMENTS + +Thanks to Jens Duttke and BjE<ouml>rn SE<ouml>derstrE<ouml>m for providing +this translation. + +=head1 SEE ALSO + +L<Image::ExifTool(3pm)|Image::ExifTool>, +L<Image::ExifTool::TagInfoXML(3pm)|Image::ExifTool::TagInfoXML> + +=cut diff --git a/lib/Image/ExifTool/Lang/tr.pm b/lib/Image/ExifTool/Lang/tr.pm new file mode 100644 index 0000000..9ded4d6 --- /dev/null +++ b/lib/Image/ExifTool/Lang/tr.pm @@ -0,0 +1,544 @@ +#------------------------------------------------------------------------------ +# File: tr.pm +# +# Description: ExifTool Turkish language translations +# +# Notes: This file generated automatically by Image::ExifTool::TagInfoXML +#------------------------------------------------------------------------------ + +package Image::ExifTool::Lang::tr; + +use strict; +use vars qw($VERSION); + +$VERSION = '1.04'; + +%Image::ExifTool::Lang::tr::Translate = ( + 'Album' => 'Albüm', + 'Aperture' => 'Açıklık', + 'ApertureValue' => 'Açıklık', + 'Artist' => 'Sanatçı', + 'Author' => 'Yazar', + 'AuthorsPosition' => 'Yazarın Pozisyonu', + 'BitsPerSample' => 'Komponent başına bit sayısı', + 'Brightness' => 'Parlaklık', + 'By-line' => 'Yazar', + 'CFAPattern' => 'CFA deseni', + 'CalibrationIlluminant1' => { + PrintConv => { + 'Cloudy' => 'Bulutlu Hava', + 'Cool White Fluorescent' => 'Soğuk beyaz floresan (W 3800 - 4500K)', + 'Day White Fluorescent' => 'Gün beyaz floresan (N 4600 - 5500K)', + 'Daylight' => 'Günışığı', + 'Daylight Fluorescent' => 'Günışığı floresan (D 5700 - 7100K)', + 'Fine Weather' => 'İyi hava', + 'Flash' => 'Flaş', + 'Fluorescent' => 'Floresan', + 'ISO Studio Tungsten' => 'ISO stüdyo tungsten', + 'Other' => 'Diğer ışık kaynağı', + 'Shade' => 'Gölge', + 'Standard Light A' => 'Standard Işık A', + 'Standard Light B' => 'Standard Işık B', + 'Standard Light C' => 'Standard Işık C', + 'Tungsten (Incandescent)' => 'Tungsten', + 'Unknown' => 'Bilinmeyen', + 'White Fluorescent' => 'Beyaz floresan (WW 3250 - 3800K)', + }, + }, + 'CalibrationIlluminant2' => { + PrintConv => { + 'Cloudy' => 'Bulutlu Hava', + 'Cool White Fluorescent' => 'Soğuk beyaz floresan (W 3800 - 4500K)', + 'Day White Fluorescent' => 'Gün beyaz floresan (N 4600 - 5500K)', + 'Daylight' => 'Günışığı', + 'Daylight Fluorescent' => 'Günışığı floresan (D 5700 - 7100K)', + 'Fine Weather' => 'İyi hava', + 'Flash' => 'Flaş', + 'Fluorescent' => 'Floresan', + 'ISO Studio Tungsten' => 'ISO stüdyo tungsten', + 'Other' => 'Diğer ışık kaynağı', + 'Shade' => 'Gölge', + 'Standard Light A' => 'Standard Işık A', + 'Standard Light B' => 'Standard Işık B', + 'Standard Light C' => 'Standard Işık C', + 'Tungsten (Incandescent)' => 'Tungsten', + 'Unknown' => 'Bilinmeyen', + 'White Fluorescent' => 'Beyaz floresan (WW 3250 - 3800K)', + }, + }, + 'Caption-Abstract' => 'Açıklama', + 'CaptionWriter' => 'Açıklama Yazarı', + 'Categories' => 'Kategoriler', + 'Category' => 'Kategoriler', + 'City' => 'Şehir', + 'ColorFilter' => 'Renk Filtresi', + 'ColorSpace' => { + Description => 'Renk alanı bilgisi', + PrintConv => { + 'Uncalibrated' => 'Kalibre edilmemiş', + }, + }, + 'ColorTemperature' => 'Renk Sıcaklığı', + 'Comment' => 'Yorum', + 'ComponentsConfiguration' => 'Her komponentin anlamı', + 'CompressedBitsPerPixel' => 'İmaj sıkıştıma modu', + 'Compression' => { + Description => 'Sıkıştırma planı', + PrintConv => { + 'JPEG' => 'JPEG Sıkıştırma', + 'Uncompressed' => 'Sıkıştırılmamış', + }, + }, + 'Contrast' => { + Description => 'Kontrast', + PrintConv => { + 'High' => 'Sert', + 'Low' => 'Yumuşak', + 'Normal' => 'Standard', + }, + }, + 'Copyright' => 'Telif hakkı sahibi', + 'CopyrightNotice' => 'Telif Hakkı Uyarısı', + 'Country' => 'Ülke', + 'Country-PrimaryLocationName' => 'Ülke', + 'CreateDate' => 'Oluşturma Tarihi', + 'CreationDate' => 'Yaratılış tarihi', + 'Credit' => 'Jenerik', + 'CustomRendered' => { + Description => 'Özel imaj işleme', + PrintConv => { + 'Custom' => 'Özel işlem', + 'Normal' => 'Normal işlem', + }, + }, + 'DateCreated' => 'Oluşturma Tarihi', + 'DateTimeOriginal' => 'Orjinal Tarih & Zaman', + 'DeviceSettingDescription' => 'Cihaz ayar tanımları', + 'DigitalZoom' => 'Dijital Zoom', + 'DigitalZoomRatio' => 'Dijital zoom oranı', + 'Directory' => 'Dosya Konumu', + 'DriveMode' => 'Sürüş Modu', + 'ExifImageHeight' => 'Geçerli imaj yüksekliği', + 'ExifImageWidth' => 'Geçerli imaj eni', + 'ExifOffset' => 'Exif IFD İmleci', + 'ExifVersion' => 'Exif sürüm', + 'ExposureCompensation' => 'Pozlama Sapması', + 'ExposureIndex' => 'Pozlama indeksi', + 'ExposureMode' => { + Description => 'Pozlama modu', + PrintConv => { + 'Auto' => 'Otomatik', + 'Auto bracket' => 'Otomatik çerçeve', + 'Manual' => 'Manuel pozlama', + }, + }, + 'ExposureProgram' => { + Description => 'Pozlama program', + PrintConv => { + 'Action (High speed)' => 'Hareket programı', + 'Aperture-priority AE' => 'Apertür önceliği', + 'Bulb' => 'Ampul', + 'Creative (Slow speed)' => 'Yaratıcı program', + 'Landscape' => 'Manzara', + 'Manual' => 'Manuel Pozlama', + 'Portrait' => 'Portre', + 'Program AE' => 'Normal program', + 'Shutter speed priority AE' => 'Deklanşör önceliği', + }, + }, + 'ExposureTime' => 'Poz süresi', + 'FNumber' => 'Açıklık', + 'FaceOrientation' => { + PrintConv => { + 'Horizontal (normal)' => 'Pozitif yön', + 'Rotate 90 CW' => 'Saat yönünde 90° döndür', + }, + }, + 'FileFormat' => 'Format', + 'FileModifyDate' => 'Güncellenen Tarih', + 'FileName' => 'Dosya adı', + 'FileSize' => 'Dosya boyutu', + 'FileSource' => { + Description => 'Dosya kaynağı', + PrintConv => { + 'Digital Camera' => 'DSC', + 'Film Scanner' => 'Transparan tip tarayıcı', + 'Reflection Print Scanner' => 'Refleks tipi tarayıcı', + }, + }, + 'FileType' => 'Dosya türü', + 'Filename' => 'Dosya adı', + 'Flash' => { + Description => 'Flaş', + PrintConv => { + 'Auto, Fired' => 'AÇIK (Otom-flaş)', + 'Auto, Fired, Red-eye reduction' => '"AÇIK (Otom-flaş, Kırmızı-Göz Azaltma)"', + 'Auto, Fired, Red-eye reduction, Return detected' => '"AÇIK (Otom-flaş, Kırmızı-Göz Azaltma, Geri dönen ışık bulundu)"', + 'Auto, Fired, Return detected' => '"AÇIK (Otom-flaş, Geri dönen ışık bulundu)"', + 'Did not fire' => 'Flaş patlamadı', + 'Fired' => 'Flaş patladı', + 'Fired, Red-eye reduction' => 'AÇIK (Kırmızı-Göz Azaltma)', + 'Fired, Red-eye reduction, Return detected' => '"AÇIK (Kırmızı-Göz Azaltma, Geri dönen ışık bulundu)"', + 'Fired, Return detected' => 'AÇIK (Geri dönen ışık bulundu)', + 'No Flash' => 'Flaş fonksiyonu yok', + 'On, Fired' => 'AÇIK (Doldurma)', + 'On, Red-eye reduction' => '"AÇIK (Doldurma, Kırmızı-Göz Önleme)"', + 'On, Red-eye reduction, Return detected' => '"AÇIK (Doldurma, Kırmızı-Göz Önleme, Geri dönen ışık bulundu)"', + 'On, Return detected' => '"AÇIK (Doldurma, Geri dönen ışık bulundu)"', + }, + }, + 'FlashEnergy' => 'Flaş enerjisi', + 'FlashExposureComp' => 'Flaş Telafisi', + 'FlashpixVersion' => 'Desteklenen Flashpix sürümü', + 'FocalLength' => 'Odak uzunluğu', + 'FocalLength35efl' => 'Odak Uzaklığı (35 mm dengi)', + 'FocalLengthIn35mmFormat' => '35mm filmde odak uzaklığı', + 'FocalPlaneResolutionUnit' => { + Description => 'Odak düzlemi çözünürlük birimi', + PrintConv => { + 'inches' => 'inç', + }, + }, + 'FocalPlaneXResolution' => 'Odak düzlemi X çözünürlüğü', + 'FocalPlaneYResolution' => 'Odak düzlemi Y çözünürlüğü', + 'FocusMode' => 'Odak modu', + 'FrameRate' => 'Kare Hızı', + 'FrameSize' => 'Kare Boyutu', + 'GPSAltitude' => 'Yükseklik', + 'GPSAltitudeRef' => { + Description => 'Yükselti referansı', + PrintConv => { + 'Above Sea Level' => 'Deniz düzeyi', + 'Below Sea Level' => 'Deniz düzeyi referansı (negatif değer)', + }, + }, + 'GPSAreaInformation' => 'GPS Alanının ismi', + 'GPSDOP' => 'Ölçüm hassaslığı', + 'GPSDateStamp' => 'GPS alanı', + 'GPSDestBearing' => 'Varış yönü', + 'GPSDestBearingRef' => 'Varış yönü için referans', + 'GPSDestDistance' => 'Varışa uzaklık', + 'GPSDestDistanceRef' => 'Varışa uzaklık için referans', + 'GPSDestLatitude' => 'Varışın enlemi', + 'GPSDestLatitudeRef' => 'Varışın enlemi için referans', + 'GPSDestLongitude' => 'Varışın boylamı', + 'GPSDestLongitudeRef' => 'Varışın boylamı için referans', + 'GPSDifferential' => { + Description => 'GPS diferansiyel düzeltme', + PrintConv => { + 'Differential Corrected' => 'Difrensiyel düzeltme uygulandı', + 'No Correction' => 'Difrensiyel düzeltme olmadan ölçüm', + }, + }, + 'GPSImgDirection' => 'İmajın yönü', + 'GPSImgDirectionRef' => 'İmajın yönü için referans', + 'GPSInfo' => 'GPS Info IDF İmleci', + 'GPSLatitude' => 'Enlem', + 'GPSLatitudeRef' => { + Description => 'Kuzey veya Güney Enlemi', + PrintConv => { + 'North' => 'Kuzey enlemi', + 'South' => 'Güney enlemi', + }, + }, + 'GPSLongitude' => 'Boylam', + 'GPSLongitudeRef' => { + Description => 'Doğu veya Batı Boylamı', + PrintConv => { + 'East' => 'Doğu boylamı', + 'West' => 'Batı boylamı', + }, + }, + 'GPSMapDatum' => 'Geodetik veri kullanıldı', + 'GPSMeasureMode' => { + Description => 'GPS ölçüm modu', + PrintConv => { + '3-Dimensional Measurement' => '3-boyutlu ölçüm', + }, + }, + 'GPSProcessingMethod' => 'GPS işlem metodunun ismi', + 'GPSSatellites' => 'Ölçüm için kullanılan GPS uyduları', + 'GPSSpeed' => 'GSP alıcının hızı', + 'GPSSpeedRef' => { + Description => 'Hız Ünitesi', + PrintConv => { + 'km/h' => 'km / saat', + 'knots' => 'Knot', + 'mph' => 'Mil / saat', + }, + }, + 'GPSStatus' => { + Description => 'GPS alıcı durumu', + PrintConv => { + 'Measurement Active' => 'İlerlemeli ölçüm', + 'Measurement Void' => 'Ölçü Birlikte İşlerliği', + }, + }, + 'GPSTimeStamp' => 'GPS saati (atomik saat)', + 'GPSTrack' => 'Hareket yönü', + 'GPSTrackRef' => { + Description => 'Hareket yönü için referans', + PrintConv => { + 'Magnetic North' => 'Manyetik yön', + 'True North' => 'Gerçek yön', + }, + }, + 'GPSVersionID' => 'GSP etiket sürümü', + 'GainControl' => { + Description => 'Kontrol Kazan', + PrintConv => { + 'High gain down' => 'Yüksek kazanç aşağı', + 'High gain up' => 'Yüksek kazanç yukarı', + 'Low gain down' => 'Düşek kazanç aşağı', + 'Low gain up' => 'Düşük kazanç yukarı', + 'None' => 'Hiçbiri', + }, + }, + 'Gradation' => 'Dereceleme', + 'Headline' => 'Başlık', + 'Hue' => 'Renk', + 'ICCProfile' => 'ICC Profili', + 'ISO' => 'ISO değeri', + 'ImageHeight' => 'İmaj yüksekliği', + 'ImageSize' => 'İmaj Boyutu', + 'ImageUniqueID' => 'Kendine has imaj ID', + 'ImageWidth' => 'İmaj genişliği', + 'Index' => 'İndeks', + 'Instructions' => 'Talimatlar', + 'InteropIndex' => 'Interoperabilite Tanımı', + 'InteropOffset' => 'Interoperabilite etiketi', + 'InteropVersion' => 'Interoperabilite Sürümü', + 'JPEGQuality' => { + PrintConv => { + 'Standard' => 'Standart Kalite', + }, + }, + 'Keywords' => 'Anahtar sözcükler', + 'Lens' => 'Objektif', + 'LensInfo' => 'Lens Bilgisi', + 'LightSource' => { + Description => 'Işık kaynağı', + PrintConv => { + 'Cloudy' => 'Bulutlu Hava', + 'Cool White Fluorescent' => 'Soğuk beyaz floresan (W 3800 - 4500K)', + 'Day White Fluorescent' => 'Gün beyaz floresan (N 4600 - 5500K)', + 'Daylight' => 'Günışığı', + 'Daylight Fluorescent' => 'Günışığı floresan (D 5700 - 7100K)', + 'Fine Weather' => 'İyi hava', + 'Flash' => 'Flaş', + 'Fluorescent' => 'Floresan', + 'ISO Studio Tungsten' => 'ISO stüdyo tungsten', + 'Other' => 'Diğer ışık kaynağı', + 'Shade' => 'Gölge', + 'Standard Light A' => 'Standard Işık A', + 'Standard Light B' => 'Standard Işık B', + 'Standard Light C' => 'Standard Işık C', + 'Tungsten (Incandescent)' => 'Tungsten', + 'Unknown' => 'Bilinmeyen', + 'White Fluorescent' => 'Beyaz floresan (WW 3250 - 3800K)', + }, + }, + 'Lightness' => 'Işık', + 'Location' => 'Mevki', + 'Make' => 'Üretici', + 'MakerNotes' => 'Üretici notları', + 'MaxAperture' => 'Maksimum lens açıklığı', + 'MeteringMode' => { + Description => 'Ölçü modu', + PrintConv => { + 'Average' => 'Ortalama', + 'Center-weighted average' => 'CenterWeightedAverage', + 'Multi-segment' => 'Desen', + 'Multi-spot' => 'Multispot', + 'Other' => 'Diğer', + 'Partial' => 'Kısmen', + 'Unknown' => 'Bilinmeyen', + }, + }, + 'Model' => 'Kamera', + 'ModifyDate' => 'Dosya değişim tarih ve zamanı', + 'NoiseReduction' => 'Parazit azaltımı', + 'Opto-ElectricConvFactor' => 'Optoelektrik çevrim faktörü', + 'Orientation' => { + Description => 'Yönelim', + PrintConv => { + 'Horizontal (normal)' => 'Pozitif yön', + 'Rotate 90 CW' => 'Saat yönünde 90° döndür', + }, + }, + 'PhotometricInterpretation' => 'Piksel kompozisyonu', + 'PlanarConfiguration' => { + Description => 'İmaj veri aranjmanı', + PrintConv => { + 'Chunky' => 'Chunky format', + 'Planar' => 'Planar format', + }, + }, + 'PrimaryChromaticities' => 'İlklerin kromatikleri', + 'Province-State' => 'Eyalet/Bölge', + 'Quality' => { + PrintConv => { + 'Low' => 'Düşük Kalite', + 'Normal' => 'Standart Kalite', + }, + }, + 'RecordMode' => 'Kayıt modu', + 'ReferenceBlackWhite' => 'Bir çift siyah ve beyaz referans değerleri', + 'RelatedImageFileFormat' => 'İlgili Görüntü Dosya Formatı', + 'RelatedImageHeight' => 'İlgili İmaj Yüksekliği', + 'RelatedImageWidth' => 'İlgili İmaj Genişliği', + 'RelatedSoundFile' => 'İlgili ses dosyası', + 'ResolutionUnit' => { + Description => 'X ve Y birim çözünürlüğü', + PrintConv => { + 'cm' => 'santimetre', + 'inches' => 'inç', + }, + }, + 'RowsPerStrip' => 'Şerit başına satır sayısı', + 'SamplesPerPixel' => 'Komponent sayısı', + 'Saturation' => { + Description => 'Doyma', + PrintConv => { + 'High' => 'Yüksek Doyma', + 'Low' => 'Düşük Doyma', + 'Normal' => 'Standard', + }, + }, + 'SceneCaptureType' => { + Description => 'Senaryo yakalama tipi', + PrintConv => { + 'Landscape' => 'Manzara', + 'Night' => 'Gece çekimi', + 'Portrait' => 'Portre', + }, + }, + 'SceneMode' => { + PrintConv => { + 'Sunset' => 'Günbatımı', + }, + }, + 'SceneType' => { + Description => 'Senaryo tipi', + PrintConv => { + 'Directly photographed' => 'Doğrudan fotograflanmış imaj', + }, + }, + 'SensingMethod' => { + Description => 'Alıcı metodu', + PrintConv => { + 'Color sequential area' => 'Renk ardaşık alan alıcısı', + 'Color sequential linear' => 'Renk ardışık çizgisel alıcı', + 'One-chip color area' => 'Tek-çip renk alanı alıcı', + 'Three-chip color area' => 'Üç-çip renk alanı alıcı', + 'Trilinear' => 'Triple çizgisel alıcı', + 'Two-chip color area' => 'İki-çip renk alanı alıcı', + }, + }, + 'SerialNumber' => 'Kamera ID', + 'ShadingCompensation' => 'Gölgelendirme Telafisi', + 'Sharpness' => { + Description => 'Keskinlik', + PrintConv => { + 'Hard' => 'Sert', + 'Normal' => 'Standard', + 'Soft' => 'Yumuşak', + }, + }, + 'ShootingMode' => 'Çekim Modu', + 'ShutterSpeed' => 'Poz süresi', + 'ShutterSpeedValue' => 'Deklanşör hızı', + 'Software' => 'Kullanılan yazılım', + 'Source' => 'Kaynak', + 'SpatialFrequencyResponse' => 'Uzaysal frekans cevabı', + 'SpectralSensitivity' => 'Uzaysal hassaslık', + 'State' => 'Eyalet', + 'StripByteCounts' => 'Sıkıştırılmış şerit başına bayt', + 'StripOffsets' => 'İmaj veri konumu', + 'SubSecTime' => 'TarihZaman altsaniyeler', + 'SubSecTimeDigitized' => 'TarihZamanDijitize altsaniyeler', + 'SubSecTimeOriginal' => 'TarihZamanOrjinal altsaniyeler', + 'SubjectArea' => 'Obje alanı', + 'SubjectDistance' => 'Obje uzaklığı', + 'SubjectDistanceRange' => { + Description => 'Obje uzaklık menzili', + PrintConv => { + 'Close' => 'Yakın görüntü', + 'Distant' => 'Uzak görüntü', + 'Macro' => 'Makro', + }, + }, + 'SubjectLocation' => 'Obje konumu', + 'SupplementalCategories' => 'Tamamlayıcı Kategoriler', + 'ThumbnailImage' => 'Küçük Resim', + 'ThumbnailImageSize' => 'Küçük resim boyutu', + 'Title' => 'Başlık', + 'TransferFunction' => 'Transfer fonksiyonu', + 'TransmissionReference' => 'İletim Başvurusu', + 'Urgency' => 'Acil', + 'UserComment' => 'Kullanıcı yorumları', + 'WhiteBalance' => { + Description => 'Beyaz ayarı', + PrintConv => { + 'Auto' => 'Otomatik beyaz ayarı', + 'Black & White' => 'Monokrom', + 'Cloudy' => 'Bulutlu hava', + 'Cool White Fluorescent' => 'Soğuk beyaz floresan', + 'Custom 1' => 'ÖZEL1', + 'Custom 2' => 'ÖZEL2', + 'Custom 3' => 'ÖZEL3', + 'Custom 4' => 'ÖZEL4', + 'Day White Fluorescent' => 'Gün beyaz floresan', + 'Daylight' => 'Günışığı', + 'Daylight Fluorescent' => 'Günışığı floresan', + 'Fluorescent' => 'Floresan', + 'Manual' => 'Elle beyaz ayarı', + 'Shade' => 'Gölge', + 'Tungsten' => 'Tungsten ışık', + }, + }, + 'WhitePoint' => 'Beya nokta kromatik', + 'Writer-Editor' => 'Açıklama Yazarı', + 'YCbCrCoefficients' => 'Renk alanı transformasyon matriks katsayısı', + 'YCbCrPositioning' => { + Description => 'Y ve C konumlama', + PrintConv => { + 'Centered' => 'Ortalanmış', + 'Co-sited' => 'Birlikte-konumlanmış', + }, + }, + 'YCbCrSubSampling' => 'Y den C\'ye alt örnekleme oranı', +); + +1; # end + + +__END__ + +=head1 NAME + +Image::ExifTool::Lang::tr.pm - ExifTool Turkish language translations + +=head1 DESCRIPTION + +This file is used by Image::ExifTool to generate localized tag descriptions +and values. + +=head1 AUTHOR + +Copyright 2003-2019, Phil Harvey (phil at owl.phy.queensu.ca) + +This library is free software; you can redistribute it and/or modify it +under the same terms as Perl itself. + +=head1 ACKNOWLEDGEMENTS + +Thanks to Jens Duttke, Hasan Yildirim and Cihan Ulusoy for providing this +translation. + +=head1 SEE ALSO + +L<Image::ExifTool(3pm)|Image::ExifTool>, +L<Image::ExifTool::TagInfoXML(3pm)|Image::ExifTool::TagInfoXML> + +=cut diff --git a/lib/Image/ExifTool/Lang/zh_cn.pm b/lib/Image/ExifTool/Lang/zh_cn.pm new file mode 100644 index 0000000..e5c1fe1 --- /dev/null +++ b/lib/Image/ExifTool/Lang/zh_cn.pm @@ -0,0 +1,1330 @@ +#------------------------------------------------------------------------------ +# File: zh_cn.pm +# +# Description: ExifTool Simplified Chinese language translations +# +# Notes: This file generated automatically by Image::ExifTool::TagInfoXML +#------------------------------------------------------------------------------ + +package Image::ExifTool::Lang::zh_cn; + +use strict; +use vars qw($VERSION); + +$VERSION = '1.08'; + +%Image::ExifTool::Lang::zh_cn::Translate = ( + 'AEProgramMode' => { + PrintConv => { + 'Landscape' => '风景', + 'Portrait' => '人物', + }, + }, + 'AFAreaIllumination' => { + PrintConv => { + 'Auto' => '自动', + }, + }, + 'AFPointIllumination' => { + PrintConv => { + 'Auto' => '自动', + }, + }, + 'AFPointMode' => { + PrintConv => { + 'Auto' => '自动', + }, + }, + 'AFPointRegistration' => { + PrintConv => { + 'Automatic' => '自动', + }, + }, + 'AFPointSelected' => { + PrintConv => { + 'Auto' => '自动', + }, + }, + 'AFPointSelected2' => { + PrintConv => { + 'Auto' => '自动', + }, + }, + 'AFPointsUnknown2' => { + PrintConv => { + 'Auto' => '自动', + }, + }, + 'APEVersion' => 'APE 版本', + 'AdultContentWarning' => { + PrintConv => { + 'Unknown' => '未知', + }, + }, + 'Album' => '相册', + 'Anti-Blur' => { + PrintConv => { + 'n/a' => '未设置', + }, + }, + 'Aperture' => '光圈数', + 'ApertureValue' => '光圈', + 'Artist' => '图像作者', + 'Author' => '作者', + 'AuthorsPosition' => '职位', + 'AutoLightingOptimizer' => { + PrintConv => { + 'n/a' => '未设置', + }, + }, + 'AutoRotate' => { + PrintConv => { + 'Rotate 180' => '180° (底/右)', + 'Rotate 270 CW' => '90° CW (左/底)', + 'Rotate 90 CW' => '90° CCW (右/上)', + 'n/a' => '未知', + }, + }, + 'BatteryLevel' => '电池电量', + 'BitsPerSample' => '每个组件的比特数', + 'BracketShotNumber' => { + PrintConv => { + 'n/a' => '未设置', + }, + }, + 'Brightness' => '亮度', + 'BrightnessValue' => '亮度', + 'By-line' => '作者', + 'CFAPattern' => 'CFA 模式', + 'CalibrationIlluminant1' => { + PrintConv => { + 'Cloudy' => '阴天', + 'Cool White Fluorescent' => '冷白色荧光灯(W3800-4500K)', + 'Day White Fluorescent' => '日光白色荧光灯(N4600-5500K)', + 'Daylight' => '太阳光', + 'Daylight Fluorescent' => '日光色荧光灯(D5700-7100K)', + 'Fine Weather' => '晴天', + 'Flash' => '闪光', + 'Fluorescent' => '荧光', + 'ISO Studio Tungsten' => 'ISO相室白炽灯', + 'Other' => '其他光源', + 'Shade' => '阴影', + 'Standard Light A' => '标准光A', + 'Standard Light B' => '标准光B', + 'Standard Light C' => '标准光C', + 'Tungsten (Incandescent)' => '白炽灯', + 'Unknown' => '未知', + 'Warm White Fluorescent' => '暖白荧光灯(L2600-3250K)', + 'White Fluorescent' => '白色荧光灯(WW3250-3800K)', + }, + }, + 'CalibrationIlluminant2' => { + PrintConv => { + 'Cloudy' => '阴天', + 'Cool White Fluorescent' => '冷白色荧光灯(W3800-4500K)', + 'Day White Fluorescent' => '日光白色荧光灯(N4600-5500K)', + 'Daylight' => '太阳光', + 'Daylight Fluorescent' => '日光色荧光灯(D5700-7100K)', + 'Fine Weather' => '晴天', + 'Flash' => '闪光', + 'Fluorescent' => '荧光', + 'ISO Studio Tungsten' => 'ISO相室白炽灯', + 'Other' => '其他光源', + 'Shade' => '阴影', + 'Standard Light A' => '标准光A', + 'Standard Light B' => '标准光B', + 'Standard Light C' => '标准光C', + 'Tungsten (Incandescent)' => '白炽灯', + 'Unknown' => '未知', + 'Warm White Fluorescent' => '暖白荧光灯(L2600-3250K)', + 'White Fluorescent' => '白色荧光灯(WW3250-3800K)', + }, + }, + 'CameraOrientation' => { + Description => '图像取向', + PrintConv => { + 'Horizontal (normal)' => '0° (上/左)', + 'Rotate 270 CW' => '90° CW (左/底)', + 'Rotate 90 CW' => '90° CCW (右/上)', + }, + }, + 'CanonExposureMode' => { + PrintConv => { + 'Aperture-priority AE' => '光圈优先', + 'Manual' => '手动', + 'Shutter speed priority AE' => '快门优先', + }, + }, + 'CanonFlashMode' => { + PrintConv => { + 'Auto' => '自动', + }, + }, + 'Caption-Abstract' => '说明', + 'CaptionWriter' => '说明作者', + 'CaptureXResolutionUnit' => { + PrintConv => { + 'um' => 'µm (微米)', + }, + }, + 'CaptureYResolutionUnit' => { + PrintConv => { + 'um' => 'µm (微米)', + }, + }, + 'Categories' => '类别', + 'Category' => '类别', + 'City' => '城市', + 'ColorEffect' => { + PrintConv => { + 'Sepia' => '怀旧深咖啡色', + }, + }, + 'ColorFilter' => '颜色滤镜', + 'ColorMode' => { + Description => '创意风格', + PrintConv => { + 'Autumn Leaves' => '红叶', + 'B&W' => '黑白', + 'Clear' => '清澈', + 'Deep' => '深色', + 'Landscape' => '风景', + 'Light' => '轻淡', + 'Neutral' => '中性', + 'Night View' => '夜景', + 'Night View/Portrait' => '夜晚肖像', + 'Portrait' => '人物', + 'Standard' => '标准', + 'Sunset' => '黄昏', + 'Vivid' => '生动色彩', + }, + }, + 'ColorSpace' => { + Description => '色彩空间信息', + PrintConv => { + 'ICC Profile' => '色彩特性文件', + 'Uncalibrated' => '自发', + }, + }, + 'ColorTemperature' => '色温', + 'CommanderGroupAMode' => { + PrintConv => { + 'Manual' => '手动', + }, + }, + 'CommanderGroupBMode' => { + PrintConv => { + 'Manual' => '手动', + }, + }, + 'CommanderInternalFlash' => { + PrintConv => { + 'Manual' => '手动', + }, + }, + 'Comment' => '注释', + 'ComponentsConfiguration' => '各分组的含义', + 'CompressedBitsPerPixel' => '图像压缩模式', + 'Compression' => { + Description => '压缩方案', + PrintConv => { + 'JPEG' => 'JEPG压缩率', + 'JPEG (old-style)' => 'JPEG (旧样式)', + 'Kodak DCR Compressed' => '柯达 DCR 压缩', + 'Kodak KDC Compressed' => '柯达 KDC 压缩', + 'Next' => 'NeXT 2比特编码', + 'Nikon NEF Compressed' => '尼康 NEF 压缩', + 'Pentax PEF Compressed' => '宾得 PEF 压缩', + 'SGILog' => 'SGI 32比特对数亮度编码', + 'SGILog24' => 'SGI 24比特对数亮度编码', + 'Sony ARW Compressed' => '索尼 ARW 压缩', + 'Thunderscan' => 'ThunderScan 4比特编码', + 'Uncompressed' => '未压缩', + }, + }, + 'Contrast' => { + Description => '对比度', + PrintConv => { + 'High' => '硬调', + 'Low' => '软调', + 'Normal' => '标准', + }, + }, + 'ControlMode' => { + PrintConv => { + 'n/a' => '未设置', + }, + }, + 'Copyright' => '专利拥有者', + 'CopyrightNotice' => '版权信息', + 'CopyrightStatus' => { + PrintConv => { + 'Unknown' => '未知', + }, + }, + 'Country' => '国家', + 'Country-PrimaryLocationName' => '国家', + 'CreateDate' => '数字数据产生的日期和时间', + 'Credit' => '作者', + 'CustomRendered' => { + Description => '用户自定义图像处理', + PrintConv => { + 'Custom' => '自定义处理', + 'Normal' => '普通模式', + }, + }, + 'DateCreated' => '创建日期', + 'DateTime' => '文件改变的日期和时间', + 'DateTimeOriginal' => '原始数据产生的日期和时间', + 'DeviceSettingDescription' => '设备设定说明', + 'DigitalZoom' => '数码变焦', + 'DigitalZoomRatio' => '数码变焦比', + 'Directory' => '文件存储位置', + 'DisplayXResolutionUnit' => { + PrintConv => { + 'um' => 'µm (微米)', + }, + }, + 'DisplayYResolutionUnit' => { + PrintConv => { + 'um' => 'µm (微米)', + }, + }, + 'DjVuVersion' => 'DjVu 版本', + 'DriveMode' => '驱动模式', + 'DynamicRangeOptimizer' => { + Description => '动态范围优化', + PrintConv => { + 'Advanced Auto' => '高级自动', + 'Advanced Lv1' => '高级优化程度 1', + 'Advanced Lv2' => '高级优化程度 2', + 'Advanced Lv3' => '高级优化程度 3', + 'Advanced Lv4' => '高级优化程度 4', + 'Advanced Lv5' => '高级优化程度 5', + 'Auto' => '自动', + 'Off' => '关', + 'Standard' => '标准', + }, + }, + 'EasyMode' => { + PrintConv => { + 'Landscape' => '风景', + 'Manual' => '手动', + 'Night' => '夜景', + 'Portrait' => '人物', + }, + }, + 'ExifImageHeight' => '像高', + 'ExifImageWidth' => '像宽', + 'ExifOffset' => 'Exif IFD 指针', + 'ExifToolVersion' => 'ExifTool 版本', + 'ExifVersion' => 'Exif 版本', + 'ExpandFilm' => '胶片扩展', + 'ExpandFilterLens' => '滤镜扩展', + 'ExpandFlashLamp' => '闪光灯扩展', + 'ExpandLens' => '镜头扩展', + 'ExpandScanner' => '扫描仪扩展', + 'ExpandSoftware' => '软件扩展', + 'ExposureCompensation' => '曝光偏差', + 'ExposureIndex' => '曝光索引', + 'ExposureMode' => { + Description => '曝光模式', + PrintConv => { + 'Aperture Priority' => '光圈优先', + 'Aperture-priority AE' => '光圈优先', + 'Auto' => '自动曝光', + 'Auto bracket' => '自动支架', + 'Landscape' => '风景', + 'Manual' => '手动曝光', + 'Portrait' => '人物', + 'Shutter Priority' => '快门优先', + 'Shutter speed priority AE' => '快门优先', + 'n/a' => '未设置', + }, + }, + 'ExposureProgram' => { + Description => '曝光程序', + PrintConv => { + 'Action (High speed)' => '运动摄影', + 'Aperture Priority' => '光圈优先', + 'Aperture-priority AE' => '光圈优先', + 'Creative (Slow speed)' => '创意摄影', + 'Landscape' => '风景', + 'Manual' => '手动', + 'Portrait' => '人物', + 'Program AE' => '一般程序', + 'Shutter Priority' => '快门优先', + 'Shutter speed priority AE' => '快门优先', + }, + }, + 'ExposureTime' => '曝光时间', + 'ExposureTime2' => '曝光时间 2', + 'ExternalFlashBounce' => { + PrintConv => { + 'n/a' => '未设置', + }, + }, + 'ExternalFlashExposureComp' => { + PrintConv => { + 'n/a' => '未设置 (Off or Auto Modes)', + 'n/a (Manual Mode)' => '未设置 (Manual Mode)', + }, + }, + 'FNumber' => '光圈数', + 'FaceOrientation' => { + PrintConv => { + 'Horizontal (normal)' => '0° (上/左)', + 'Rotate 180' => '180° (底/右)', + 'Rotate 270 CW' => '90° CW (左/底)', + 'Rotate 90 CW' => '90° CCW (右/上)', + }, + }, + 'FaxProfile' => { + PrintConv => { + 'Unknown' => '未知', + }, + }, + 'FileFormat' => '格式', + 'FileModifyDate' => '更新日期', + 'FileName' => '文件名', + 'FileSize' => '文件大小', + 'FileSource' => { + Description => '文件来源', + PrintConv => { + 'Digital Camera' => '数码相机', + 'Film Scanner' => '胶片扫描仪', + 'Reflection Print Scanner' => '反射型扫描仪', + }, + }, + 'FileType' => '文件格式', + 'FilterEffect' => { + PrintConv => { + 'n/a' => '未设置', + }, + }, + 'Flash' => { + Description => '闪光', + PrintConv => { + 'Auto, Fired' => '开 (自动闪光)', + 'Auto, Fired, Red-eye reduction' => '开 (自动闪光,减轻红眼)', + 'Auto, Fired, Red-eye reduction, Return detected' => '开 (强制闪光,减轻红眼,检测返回光)', + 'Auto, Fired, Return detected' => '开 (自动闪光,检测返回光)', + 'Did not fire' => '闪光灯未亮', + 'Fired' => '闪光灯亮', + 'Fired, Red-eye reduction' => '开 (减轻红眼)', + 'Fired, Red-eye reduction, Return detected' => '开 (减轻红眼,检测返回光)', + 'Fired, Return detected' => '开 (检测返回光)', + 'No Flash' => '无闪光功能', + 'On, Fired' => '开 (强制闪光)', + 'On, Red-eye reduction' => '开 (强制闪光(减轻红眼))', + 'On, Red-eye reduction, Return detected' => '开 (强制闪光,减轻红眼,检测返回光)', + 'On, Return detected' => '开 (强制闪光,检测返回光)', + }, + }, + 'FlashControlMode' => { + PrintConv => { + 'Manual' => '手动', + }, + }, + 'FlashEnergy' => '闪光强度', + 'FlashExposureComp' => '闪光补偿', + 'FlashGroupAControlMode' => { + PrintConv => { + 'Manual' => '手动', + }, + }, + 'FlashGroupBControlMode' => { + PrintConv => { + 'Manual' => '手动', + }, + }, + 'FlashGroupCControlMode' => { + PrintConv => { + 'Manual' => '手动', + }, + }, + 'FlashMode' => { + PrintConv => { + 'Auto' => '自动', + 'Unknown' => '未知', + }, + }, + 'FlashOptions' => { + PrintConv => { + 'Auto' => '自动', + }, + }, + 'FlashOptions2' => { + PrintConv => { + 'Auto' => '自动', + }, + }, + 'FlashSyncSpeedAv' => { + PrintConv => { + 'Auto' => '自动', + }, + }, + 'FlashpixVersion' => '支持的 Flashpix 版本', + 'FocalLength' => '焦距', + 'FocalLength35efl' => '焦点距离(35 mm 换算)', + 'FocalLengthIn35mmFormat' => '35 mm 换算镜头焦点距离', + 'FocalPlaneResolutionUnit' => { + Description => '焦平面分辨率单位', + PrintConv => { + 'inches' => '英寸', + 'um' => 'µm (微米)', + }, + }, + 'FocalPlaneXResolution' => '焦平面 X 分辨率', + 'FocalPlaneYResolution' => '焦平面 Y 分辨率', + 'Focus' => { + PrintConv => { + 'Manual' => '手动', + }, + }, + 'FocusContinuous' => { + PrintConv => { + 'Manual' => '手动', + }, + }, + 'FocusMode' => { + Description => '对焦模式', + PrintConv => { + 'Auto' => '自动', + 'Manual' => '手动', + }, + }, + 'FocusMode2' => { + PrintConv => { + 'Manual' => '手动', + }, + }, + 'FocusModeSetting' => { + PrintConv => { + 'Manual' => '手动', + }, + }, + 'FocusRange' => { + PrintConv => { + 'Auto' => '自动', + 'Manual' => '手动', + }, + }, + 'FrameRate' => '更新速率', + 'FrameSize' => '画面尺寸', + 'FreeByteCounts' => '空白字节数', + 'FujiFlashMode' => { + PrintConv => { + 'Auto' => '自动', + }, + }, + 'GIFVersion' => 'GIF 版本', + 'GPSAltitude' => '海拔高度', + 'GPSAltitudeRef' => { + Description => '高度基准', + PrintConv => { + 'Above Sea Level' => '海平面', + 'Below Sea Level' => '海拔(负值)', + }, + }, + 'GPSAreaInformation' => 'GPS区域名', + 'GPSDOP' => '测量精度', + 'GPSDateStamp' => 'GPS日期', + 'GPSDestBearing' => '目的地方位', + 'GPSDestBearingRef' => '目的地方位参照', + 'GPSDestDistance' => '离终点的距离', + 'GPSDestDistanceRef' => { + Description => '距目的地距离参照', + PrintConv => { + 'Kilometers' => '公里数', + 'Miles' => '英里数', + 'Nautical Miles' => '节数', + }, + }, + 'GPSDestLatitude' => '终点纬度', + 'GPSDestLatitudeRef' => { + Description => '目的地的北纬或南纬', + PrintConv => { + 'North' => '北纬', + 'South' => '南纬', + }, + }, + 'GPSDestLongitude' => '终点经度', + 'GPSDestLongitudeRef' => { + Description => '目的地的东经或西经', + PrintConv => { + 'East' => '东经', + 'West' => '西经', + }, + }, + 'GPSDifferential' => { + Description => 'GPS 差分校正', + PrintConv => { + 'Differential Corrected' => '差分校正定位', + 'No Correction' => '非差分校正测量', + }, + }, + 'GPSImgDirection' => '图像方向', + 'GPSImgDirectionRef' => '图像方向参照', + 'GPSInfo' => 'GPS Info IFD 指针', + 'GPSLatitude' => '纬度', + 'GPSLatitudeRef' => { + Description => '北纬或者南纬', + PrintConv => { + 'North' => '北纬', + 'South' => '南纬', + }, + }, + 'GPSLongitude' => '经度', + 'GPSLongitudeRef' => { + Description => '东经或者西经', + PrintConv => { + 'East' => '东经', + 'West' => '西经', + }, + }, + 'GPSMapDatum' => '使用的大地测量数据', + 'GPSMeasureMode' => { + Description => 'GPS测量模式', + PrintConv => { + '2-D' => '2维测量', + '2-Dimensional' => '2维测量', + '2-Dimensional Measurement' => '2维测量', + '3-D' => '3维测量', + '3-Dimensional' => '3维测量', + '3-Dimensional Measurement' => '3维测量', + }, + }, + 'GPSProcessingMethod' => '定位方式名称', + 'GPSSatellites' => '用于定位的 GPS 卫星信号', + 'GPSSpeed' => 'GPS接收器的速度', + 'GPSSpeedRef' => { + Description => '速度单位', + PrintConv => { + 'km/h' => '公里/小时', + 'knots' => '海里/小时', + 'mph' => '英里/小时', + }, + }, + 'GPSStatus' => { + Description => 'GPS 接收器状态', + PrintConv => { + 'Measurement Active' => '正在测量中', + 'Measurement Void' => '测量中断', + }, + }, + 'GPSTimeStamp' => 'GPS 时间(原子钟)', + 'GPSTrack' => '运动方向', + 'GPSTrackRef' => { + Description => '运动方向参照', + PrintConv => { + 'Magnetic North' => '磁场方向', + 'True North' => '真方向', + }, + }, + 'GPSVersionID' => 'GPS标签版本', + 'GainControl' => { + Description => '增益控制', + PrintConv => { + 'High gain down' => '强减少', + 'High gain up' => '强增益', + 'Low gain down' => '弱减少', + 'Low gain up' => '弱增益', + 'None' => '无', + }, + }, + 'Gamma' => '对比系数', + 'Gradation' => '灰阶', + 'HDR' => { + Description => '自动HDR', + PrintConv => { + 'Off' => '关', + }, + }, + 'Headline' => '标题', + 'HighISONoiseReduction' => { + Description => '高ISO降噪', + PrintConv => { + 'Auto' => '自动', + 'High' => '强', + 'Low' => '弱', + 'Normal' => '标准', + 'Off' => '关', + }, + }, + 'Hue' => '色相', + 'ICCProfile' => 'ICC 规范', + 'IPTC-NAA' => 'IPTC-NAA 元数据', + 'ISOSetting' => { + PrintConv => { + 'Auto' => '自动', + 'Manual' => '手动', + }, + }, + 'ImageDescription' => '图像标题', + 'ImageHeight' => '像高', + 'ImageOrientation' => { + PrintConv => { + 'Portrait' => '人物', + }, + }, + 'ImageSize' => '图像尺寸', + 'ImageTone' => { + PrintConv => { + 'Landscape' => '风景', + 'Portrait' => '人物', + }, + }, + 'ImageUniqueID' => '图像唯一标识', + 'ImageWidth' => '像宽', + 'Index' => '索引', + 'Instructions' => '指示', + 'InternalFlash' => { + PrintConv => { + 'Manual' => '手动', + }, + }, + 'InteropIndex' => { + Description => '互用标识', + PrintConv => { + 'THM - DCF thumbnail file' => 'THM: DCF 缩略图文件', + }, + }, + 'InteropOffset' => '互用指针', + 'InteropVersion' => '互用版本', + 'JFIFVersion' => 'JFIF 版本', + 'JPEGQuality' => { + Description => '图像质量', + PrintConv => { + 'Extra Fine' => '超精细', + 'Fine' => '精细', + 'Standard' => '标准画质', + 'n/a' => '未设置', + }, + }, + 'Keyword' => '关键词', + 'Keywords' => '关键字', + 'Lens' => '镜头', + 'LensInfo' => '镜头信息', + 'LensType' => '未设置', + 'LicenseType' => { + PrintConv => { + 'Unknown' => '未知', + }, + }, + 'LightSource' => { + Description => '光源', + PrintConv => { + 'Cloudy' => '阴天', + 'Cool White Fluorescent' => '冷白色荧光灯(W3800-4500K)', + 'Day White Fluorescent' => '日光白色荧光灯(N4600-5500K)', + 'Daylight' => '太阳光', + 'Daylight Fluorescent' => '日光色荧光灯(D5700-7100K)', + 'Fine Weather' => '晴天', + 'Flash' => '闪光', + 'Fluorescent' => '荧光', + 'ISO Studio Tungsten' => 'ISO相室白炽灯', + 'Other' => '其他光源', + 'Shade' => '阴影', + 'Standard Light A' => '标准光A', + 'Standard Light B' => '标准光B', + 'Standard Light C' => '标准光C', + 'Tungsten (Incandescent)' => '白炽灯', + 'Unknown' => '未知', + 'Warm White Fluorescent' => '暖白荧光灯(L2600-3250K)', + 'White Fluorescent' => '白色荧光灯(WW3250-3800K)', + }, + }, + 'Lightness' => '明暗度', + 'LongExposureNoiseReduction' => { + Description => '长时间曝光降噪', + PrintConv => { + 'Auto' => '自动', + 'Off' => '关', + 'On' => '开', + 'n/a' => '未设置', + }, + }, + 'MIEVersion' => 'MIE 版本', + 'Macro' => { + PrintConv => { + 'Manual' => '手动', + 'n/a' => '未设置', + }, + }, + 'Make' => '厂商', + 'MakerNote' => '厂商注释', + 'MakerNotes' => '制造商记录', + 'ManualFlashOutput' => { + PrintConv => { + 'n/a' => '未设置', + }, + }, + 'MaxAperture' => '镜头光圈最大值', + 'MaxApertureValue' => '最大镜头光圈', + 'MeteringMode' => { + Description => '测量方式', + PrintConv => { + 'Average' => '平均', + 'Center-weighted average' => '中央重点', + 'Multi-segment' => '分割测光', + 'Multi-spot' => '多点', + 'Other' => '其它', + 'Partial' => '部分测光', + 'Spot' => '点测光', + 'Unknown' => '未知', + }, + }, + 'Model' => '型号', + 'ModifiedPictureStyle' => { + PrintConv => { + 'Landscape' => '风景', + 'Portrait' => '人物', + }, + }, + 'ModifiedSharpnessFreq' => { + PrintConv => { + 'n/a' => '未设置', + }, + }, + 'ModifiedToneCurve' => { + PrintConv => { + 'Manual' => '手动', + }, + }, + 'ModifiedWhiteBalance' => { + PrintConv => { + 'Auto' => '自动', + 'Cloudy' => '阴天', + 'Daylight' => '太阳光', + 'Flash' => '闪光', + 'Fluorescent' => '荧光', + 'Shade' => '阴影', + }, + }, + 'ModifyDate' => '文件改变的日期和时间', + 'MultiFrameNoiseReduction' => { + Description => '多帧降噪', + PrintConv => { + 'Off' => '关', + 'On' => '开', + }, + }, + 'NEFCompression' => { + PrintConv => { + 'Uncompressed' => '未压缩', + }, + }, + 'Noise' => '噪声', + 'NoiseReduction' => { + Description => '减少噪声', + PrintConv => { + 'Auto' => '自动', + }, + }, + 'ObjectFileType' => { + PrintConv => { + 'Unknown' => '未知', + }, + }, + 'Opto-ElectricConvFactor' => '光电转换因子', + 'Orientation' => { + Description => '图像取向', + PrintConv => { + 'Horizontal (normal)' => '0° (上/左)', + 'Mirror horizontal' => '0° (上/右)', + 'Mirror horizontal and rotate 270 CW' => '90° CW (左/上)', + 'Mirror horizontal and rotate 90 CW' => '90° CCW (右/底)', + 'Mirror vertical' => '180° (底/左)', + 'Rotate 180' => '180° (底/右)', + 'Rotate 270 CW' => '90° CW (左/底)', + 'Rotate 90 CW' => '90° CCW (右/上)', + }, + }, + 'PEFVersion' => 'PEF 版本', + 'PageNumber' => '页数', + 'PhotometricInterpretation' => { + Description => '像素方案', + PrintConv => { + 'BlackIsZero' => '零黑色', + 'Color Filter Array' => 'CFA (颜色滤镜矩阵)', + 'Pixar LogL' => 'CIE Log2(L) (对数亮度)', + 'Pixar LogLuv' => 'CIE Log2(L)(u\',v\') (对数亮度和色度)', + 'RGB Palette' => '调色板颜色', + 'Transparency Mask' => '透明蒙板', + 'WhiteIsZero' => '零白色', + }, + }, + 'PictureFinish' => { + PrintConv => { + 'Portrait' => '人物', + }, + }, + 'PictureMode' => { + PrintConv => { + 'Aperture-priority AE' => '光圈优先', + 'Auto' => '自动', + 'Landscape' => '风景', + 'Manual' => '手动', + 'Portrait' => '人物', + 'Shutter speed priority AE' => '快门优先', + }, + }, + 'PictureMode2' => { + PrintConv => { + 'Aperture Priority' => '光圈优先', + 'Manual' => '手动', + 'Shutter Speed Priority' => '快门优先', + }, + }, + 'PictureModeBWFilter' => { + PrintConv => { + 'n/a' => '未设置', + }, + }, + 'PictureModeTone' => { + PrintConv => { + 'n/a' => '未设置', + }, + }, + 'PictureStyle' => { + PrintConv => { + 'Landscape' => '风景', + 'Portrait' => '人物', + }, + }, + 'PixelUnits' => { + PrintConv => { + 'Unknown' => '未知', + }, + }, + 'PlanarConfiguration' => { + Description => '图像数据排列', + PrintConv => { + 'Chunky' => '点顺序格式', + 'Planar' => '平面格式', + }, + }, + 'PreviewColorSpace' => { + PrintConv => { + 'Unknown' => '未知', + }, + }, + 'PrimaryChromaticities' => '原色色度坐标值', + 'ProgramMode' => { + PrintConv => { + 'Portrait' => '人物', + }, + }, + 'Province-State' => '州/省', + 'Quality' => { + Description => '图像质量', + PrintConv => { + 'Compressed RAW' => 'cRAW', + 'Compressed RAW + JPEG' => 'cRAW+JPEG', + 'Extra Fine' => '超精细', + 'Fine' => '精细', + 'Low' => '低画质', + 'Normal' => '标准画质', + 'RAW + JPEG' => 'RAW+JPEG', + 'Standard' => '标准', + 'n/a' => '未设置', + }, + }, + 'RAFVersion' => 'RAF 版本', + 'Rating' => '评分', + 'RatingPercent' => '百分比评级', + 'RecordMode' => { + Description => '记录模式', + PrintConv => { + 'Aperture Priority' => '光圈优先', + 'Manual' => '手动', + 'Shutter Priority' => '快门优先', + }, + }, + 'RecordingMode' => { + PrintConv => { + 'Auto' => '自动', + 'Landscape' => '风景', + 'Manual' => '手动', + 'Portrait' => '人物', + }, + }, + 'RedEyeCorrection' => { + PrintConv => { + 'Automatic' => '自动', + }, + }, + 'ReferenceBlackWhite' => '黑白参照值对', + 'RelatedImageFileFormat' => '相关图像文件格式', + 'RelatedImageHeight' => '相关图像高度', + 'RelatedImageWidth' => '相关图像宽度', + 'RelatedSoundFile' => '相关的音频文件', + 'ResolutionUnit' => { + Description => '图像高宽分辨率单位', + PrintConv => { + 'cm' => '像素/厘米', + 'inches' => '英寸', + }, + }, + 'Rotation' => { + PrintConv => { + 'Horizontal' => '0° (上/左)', + 'Horizontal (Normal)' => '0° (上/左)', + 'Horizontal (normal)' => '0° (上/左)', + 'Rotate 180' => '180° (底/右)', + 'Rotate 270 CW' => '90° CW (左/底)', + 'Rotate 90 CW' => '90° CCW (右/上)', + 'Rotated 180' => '180° (底/右)', + 'Rotated 270 CW' => '90° CW (左/底)', + 'Rotated 90 CW' => '90° CCW (右/上)', + }, + }, + 'RowsPerStrip' => '每条带的行数', + 'SPIFFVersion' => 'SPIFF 版本', + 'SRAWQuality' => { + PrintConv => { + 'n/a' => '未设置', + }, + }, + 'SVGVersion' => 'SVG 版本', + 'SamplesPerPixel' => '组件数', + 'Saturation' => { + Description => '饱和度', + PrintConv => { + 'High' => '高饱和度', + 'Low' => '低饱和度', + 'None' => '未设置', + 'Normal' => '标准', + }, + }, + 'SceneCaptureType' => { + Description => '取景类型', + PrintConv => { + 'Landscape' => '风景', + 'Night' => '夜景', + 'Portrait' => '人物', + 'Standard' => '标准', + }, + }, + 'SceneMode' => { + Description => '场景选择', + PrintConv => { + '3D Sweep Panorama' => '3D', + 'Anti Motion Blur' => '动作防抖', + 'Aperture Priority' => '光圈优先', + 'Auto' => '自动', + 'Cont. Priority AE' => '连续拍摄优先AE', + 'Handheld Night Shot' => '手持夜景拍摄', + 'Landscape' => '风景', + 'Macro' => '微距', + 'Manual' => '手动', + 'Night Portrait' => '夜晚肖像', + 'Night Scene' => '夜景', + 'Night View/Portrait' => '夜景/肖像', + 'Portrait' => '人物', + 'Shutter Priority' => '快门优先', + 'Sports' => '运动模式', + 'Sunset' => '夕阳', + 'Sweep Panorama' => '扫描全景', + }, + }, + 'SceneModeUsed' => { + PrintConv => { + 'Aperture Priority' => '光圈优先', + 'Landscape' => '风景', + 'Manual' => '手动', + 'Portrait' => '人物', + 'Shutter Priority' => '快门优先', + }, + }, + 'SceneSelect' => { + PrintConv => { + 'Night' => '夜景', + }, + }, + 'SceneType' => { + Description => '场景类型', + PrintConv => { + 'Directly photographed' => '直接拍摄的图像', + }, + }, + 'SensingMethod' => { + Description => '感应方法', + PrintConv => { + 'Color sequential area' => '色彩连续区感应器', + 'Color sequential linear' => '色彩连续线性感应器', + 'One-chip color area' => '单片色彩区感应器', + 'Three-chip color area' => '3 片色彩区传感器', + 'Trilinear' => '3 线传感器', + 'Two-chip color area' => '2 片色彩区传感器', + }, + }, + 'SerialNumber' => '照相机标识', + 'ShadingCompensation' => '阴影补偿', + 'Sharpness' => { + Description => '锐度', + PrintConv => { + 'Hard' => '强', + 'Normal' => '标准', + 'Soft' => '弱', + 'n/a' => '未设置', + }, + }, + 'SharpnessFrequency' => { + PrintConv => { + 'n/a' => '未设置', + }, + }, + 'ShootingInfoDisplay' => { + PrintConv => { + 'Auto' => '自动', + }, + }, + 'ShootingMode' => { + Description => '拍摄模式', + PrintConv => { + 'Aperture Priority' => '光圈优先', + 'Manual' => '手动', + 'Portrait' => '人物', + 'Shutter Priority' => '快门优先', + }, + }, + 'ShutterMode' => { + PrintConv => { + 'Aperture Priority' => '光圈优先', + 'Auto' => '自动', + }, + }, + 'ShutterSpeed' => '曝光时间', + 'ShutterSpeedValue' => '快门速度', + 'Software' => '使用软件', + 'Source' => '来源', + 'SpatialFrequencyResponse' => '空间频率响应', + 'SpectralSensitivity' => '光谱灵敏度', + 'State' => '州', + 'StripByteCounts' => '每压缩条带的字节数', + 'StripOffsets' => '图像数据位置', + 'SubSecCreateDate' => '数字数据产生的日期和时间', + 'SubSecDateTimeOriginal' => '原始数据产生的日期和时间', + 'SubSecModifyDate' => '文件改变的日期和时间', + 'SubSecTime' => '时间的次秒', + 'SubSecTimeDigitized' => '数字化时间的次秒', + 'SubSecTimeOriginal' => '原始时间的次秒', + 'Subject' => '主题', + 'SubjectArea' => '被摄对象区域', + 'SubjectDistance' => '目标距离', + 'SubjectDistanceRange' => { + Description => '被摄对象距离范围', + PrintConv => { + 'Close' => '近景', + 'Distant' => '远景', + 'Macro' => '微距', + 'Unknown' => '未知', + }, + }, + 'SubjectLocation' => '被摄对象位置', + 'SubjectProgram' => { + PrintConv => { + 'Portrait' => '人物', + }, + }, + 'Subsystem' => { + PrintConv => { + 'Unknown' => '未知', + }, + }, + 'SupplementalCategories' => '追加类别', + 'SupplementalType' => { + PrintConv => { + 'Main Image' => '未设置', + }, + }, + 'T4Options' => '未压缩', + 'T6Options' => 'T6 选项', + 'ThumbnailImage' => '缩略图', + 'ThumbnailImageSize' => '缩图尺寸', + 'Title' => '标题', + 'ToneCurve' => { + PrintConv => { + 'Manual' => '手动', + }, + }, + 'ToningEffect' => { + PrintConv => { + 'n/a' => '未设置', + }, + }, + 'TransferFunction' => '传送功能', + 'Transformation' => { + PrintConv => { + 'Horizontal (normal)' => '0° (上/左)', + 'Mirror horizontal' => '0° (上/右)', + 'Mirror horizontal and rotate 270 CW' => '90° CW (左/上)', + 'Mirror horizontal and rotate 90 CW' => '90° CCW (右/底)', + 'Mirror vertical' => '180° (底/左)', + 'Rotate 180' => '180° (底/右)', + 'Rotate 270 CW' => '90° CW (左/底)', + 'Rotate 90 CW' => '90° CCW (右/上)', + }, + }, + 'TransmissionReference' => '传输记录', + 'Trapped' => { + PrintConv => { + 'Unknown' => '未知', + }, + }, + 'Urgency' => '紧急度', + 'UserComment' => '用户注释', + 'UserDef1PictureStyle' => { + PrintConv => { + 'Landscape' => '风景', + 'Portrait' => '人物', + }, + }, + 'UserDef2PictureStyle' => { + PrintConv => { + 'Landscape' => '风景', + 'Portrait' => '人物', + }, + }, + 'UserDef3PictureStyle' => { + PrintConv => { + 'Landscape' => '风景', + 'Portrait' => '人物', + }, + }, + 'VRDVersion' => 'VRD 版本', + 'Version' => '版本', + 'VibrationReduction' => { + PrintConv => { + 'n/a' => '未设置', + }, + }, + 'WBAdjLighting' => { + PrintConv => { + 'Daylight (direct sunlight)' => '太阳光 (0)', + 'Daylight (shade)' => '太阳光 (1)', + 'Daylight (cloudy)' => '太阳光 (2)', + 'Flash' => '闪光', + }, + }, + 'WBMode' => { + PrintConv => { + 'Auto' => '自动', + }, + }, + 'WhiteBalance' => { + Description => '白平衡', + PrintConv => { + 'Auto' => '自动', + 'Black & White' => '黑白', + 'Cloudy' => '阴天', + 'Color Temperature/Color Filter' => '色温 / 彩色滤光片', + 'Cool White Fluorescent' => '白色荧光灯', + 'Custom' => '自定义', + 'Custom 1' => '自定义1', + 'Custom 2' => '自定义2', + 'Custom 3' => '自定义3', + 'Custom 4' => '自定义4', + 'Day White Fluorescent' => '日光白色荧光灯', + 'Daylight' => '太阳光', + 'Daylight Fluorescent' => '日光色荧光灯', + 'Flash' => '闪光', + 'Fluorescent' => '荧光', + 'Manual' => '手动', + 'Shade' => '阴影', + 'Tungsten' => '白炽灯', + 'Unknown' => '未知', + 'Warm White Fluorescent' => '暖白荧光灯', + 'White Fluorescent' => '白色荧光灯', + }, + }, + 'WhiteBalance2' => { + PrintConv => { + 'Auto' => '自动', + }, + }, + 'WhiteBalanceAdj' => { + PrintConv => { + 'Auto' => '自动', + 'Cloudy' => '阴天', + 'Daylight' => '太阳光', + 'Flash' => '闪光', + 'Fluorescent' => '荧光', + 'Shade' => '阴影', + }, + }, + 'WhiteBalanceMode' => { + PrintConv => { + 'Unknown' => '未知', + }, + }, + 'WhiteBalanceSet' => { + PrintConv => { + 'Auto' => '自动', + 'Cloudy' => '阴天', + 'Daylight' => '太阳光', + 'Flash' => '闪光', + 'Manual' => '手动', + 'Shade' => '阴影', + }, + }, + 'WhitePoint' => '白点色度', + 'Writer-Editor' => '说明作者', + 'XMP' => 'XMP 元数据', + 'XPAuthor' => '作者', + 'XPComment' => '注释', + 'XPKeywords' => '关键词', + 'XPSubject' => '主题', + 'XPTitle' => '标题', + 'YCbCrCoefficients' => '色彩空间变换矩阵系数', + 'YCbCrPositioning' => { + Description => 'YCC 像素结构(Y 和 C 的位置)', + PrintConv => { + 'Centered' => '中心的', + 'Co-sited' => '一致', + }, + }, + 'YCbCrSubSampling' => 'YCC 像素结构(Y 至 C 的子采样率)', + 'ZoneMatching' => { + Description => '区域匹配', + PrintConv => { + 'High Key' => '强', + 'ISO Setting Used' => '关', + 'Low Key' => '弱', + }, + }, +); + +1; # end + + +__END__ + +=head1 NAME + +Image::ExifTool::Lang::zh_cn.pm - ExifTool Simplified Chinese language translations + +=head1 DESCRIPTION + +This file is used by Image::ExifTool to generate localized tag descriptions +and values. + +=head1 AUTHOR + +Copyright 2003-2019, Phil Harvey (phil at owl.phy.queensu.ca) + +This library is free software; you can redistribute it and/or modify it +under the same terms as Perl itself. + +=head1 ACKNOWLEDGEMENTS + +Thanks to Jens Duttke and Haibing Zhong for providing this translation. + +=head1 SEE ALSO + +L<Image::ExifTool(3pm)|Image::ExifTool>, +L<Image::ExifTool::TagInfoXML(3pm)|Image::ExifTool::TagInfoXML> + +=cut diff --git a/lib/Image/ExifTool/Lang/zh_tw.pm b/lib/Image/ExifTool/Lang/zh_tw.pm new file mode 100644 index 0000000..0fc75eb --- /dev/null +++ b/lib/Image/ExifTool/Lang/zh_tw.pm @@ -0,0 +1,801 @@ +#------------------------------------------------------------------------------ +# File: zh_tw.pm +# +# Description: ExifTool Traditional Chinese language translations +# +# Notes: This file generated automatically by Image::ExifTool::TagInfoXML +#------------------------------------------------------------------------------ + +package Image::ExifTool::Lang::zh_tw; + +use strict; +use vars qw($VERSION); + +$VERSION = '1.06'; + +%Image::ExifTool::Lang::zh_tw::Translate = ( + 'Album' => '相簿', + 'Aperture' => '光圈', + 'ApertureValue' => '光圈', + 'Artist' => '影像建立者', + 'Author' => '作者', + 'AuthorsPosition' => '職位', + 'BatteryLevel' => '電池容量', + 'BitsPerSample' => '每個元件 bits 組成的數量', + 'Brightness' => '亮度', + 'BrightnessValue' => '亮度', + 'By-line' => '作者', + 'CFAPattern' => '彩色濾鏡陣列圖', + 'CFAPattern2' => 'CFA 模式 2', + 'CFARepeatPatternDim' => 'CFA 重複模式尺寸', + 'CalibrationIlluminant1' => { + PrintConv => { + 'Cloudy' => '多雲', + 'Cool White Fluorescent' => '冷白色熒光燈 (W 3800 - 4500K)', + 'Day White Fluorescent' => '日光白色熒光燈 (N 4600 - 5500K)', + 'Daylight' => '日光', + 'Daylight Fluorescent' => '日光熒光燈 (D 5700 - 7100K)', + 'Fine Weather' => '晴天', + 'Flash' => '閃光燈', + 'Fluorescent' => '日光燈', + 'ISO Studio Tungsten' => 'ISO 攝影棚鎢燈', + 'Other' => '其他光源', + 'Shade' => '陰天', + 'Standard Light A' => '標準燈光 A', + 'Standard Light B' => '標準燈光 B', + 'Standard Light C' => '標準燈光 C', + 'Tungsten (Incandescent)' => '鎢絲燈', + 'Unknown' => '未知', + 'Warm White Fluorescent' => '暖白螢光燈 (L 2600 - 3250K)', + 'White Fluorescent' => '白色熒光燈 (WW 3250 - 3800K)', + }, + }, + 'CalibrationIlluminant2' => { + PrintConv => { + 'Cloudy' => '多雲', + 'Cool White Fluorescent' => '冷白色熒光燈 (W 3800 - 4500K)', + 'Day White Fluorescent' => '日光白色熒光燈 (N 4600 - 5500K)', + 'Daylight' => '日光', + 'Daylight Fluorescent' => '日光熒光燈 (D 5700 - 7100K)', + 'Fine Weather' => '晴天', + 'Flash' => '閃光燈', + 'Fluorescent' => '日光燈', + 'ISO Studio Tungsten' => 'ISO 攝影棚鎢燈', + 'Other' => '其他光源', + 'Shade' => '陰天', + 'Standard Light A' => '標準燈光 A', + 'Standard Light B' => '標準燈光 B', + 'Standard Light C' => '標準燈光 C', + 'Tungsten (Incandescent)' => '鎢絲燈', + 'Unknown' => '未知', + 'Warm White Fluorescent' => '暖白螢光燈 (L 2600 - 3250K)', + 'White Fluorescent' => '白色熒光燈 (WW 3250 - 3800K)', + }, + }, + 'Caption-Abstract' => '說明', + 'CaptionWriter' => '說明作者', + 'Categories' => '類別', + 'Category' => '類別', + 'CellLength' => '元件長度', + 'CellWidth' => '元件寬度', + 'City' => '城市', + 'ColorEffect' => { + PrintConv => { + 'Sepia' => '懷舊深咖啡色', + }, + }, + 'ColorFilter' => '顏色濾鏡', + 'ColorMap' => '色彩地圖', + 'ColorMode' => { + Description => '風格設定', + PrintConv => { + 'Autumn Leaves' => '秋葉', + 'B&W' => '黑白', + 'Clear' => '透明', + 'Deep' => '深色', + 'Landscape' => '風景', + 'Light' => '淡色', + 'Neutral' => '中性', + 'Night View' => '夜景', + 'Night View/Portrait' => '夜間肖像', + 'Portrait' => '肖像', + 'Standard' => '標準', + 'Sunset' => '日落', + 'Vivid' => '鮮明色彩', + }, + }, + 'ColorResponseUnit' => '顏色反應單位', + 'ColorSpace' => { + Description => '色彩空間', + PrintConv => { + 'ICC Profile' => '色彩描述檔', + 'Uncalibrated' => '未校準', + }, + }, + 'ColorTemperature' => '色溫', + 'Comment' => '註解', + 'ComponentsConfiguration' => '每個組成部分的意義', + 'CompressedBitsPerPixel' => '影像壓縮模式', + 'Compression' => { + Description => '壓縮方式', + PrintConv => { + 'JPEG' => 'JPEG壓縮率', + 'JPEG (old-style)' => 'JPEG (舊式)', + 'Kodak DCR Compressed' => 'Kodak DCR 壓縮', + 'Kodak KDC Compressed' => 'Kodak KDC 壓縮', + 'Next' => 'NeXT 2-bit 編碼', + 'Nikon NEF Compressed' => 'Nikon NEF 壓縮', + 'Pentax PEF Compressed' => 'Pentax PEF 壓縮', + 'SGILog' => 'SGI 32-bit Log Luminance 編碼', + 'SGILog24' => 'SGI 24-bit Log Luminance 編碼', + 'Sony ARW Compressed' => 'Sony ARW 壓縮', + 'Thunderscan' => 'ThunderScan 4-bit 編碼', + 'Uncompressed' => '未壓縮', + }, + }, + 'Contrast' => { + Description => '對比', + PrintConv => { + 'High' => '硬', + 'Low' => '軟', + 'Normal' => '標準', + }, + }, + 'Copyright' => '版權擁有人', + 'CopyrightNotice' => '版權聲明', + 'Country' => '國家', + 'Country-PrimaryLocationName' => '國家', + 'CreateDate' => '數位化的日期時間', + 'CreationDate' => '建立日期', + 'Credit' => '作者', + 'CustomRendered' => { + Description => '自訂影像處理', + PrintConv => { + 'Custom' => '自訂程序', + 'Normal' => '正常程序', + }, + }, + 'DateCreated' => '建立日期', + 'DateTimeOriginal' => '原始影像日期時間', + 'DeviceSettingDescription' => '裝備設定說明', + 'DigitalZoom' => '數碼變焦', + 'DigitalZoomRatio' => '數位變焦比率', + 'Directory' => '儲存擋案位置', + 'DocumentName' => '文件名稱', + 'DriveMode' => '激勵模式', + 'DynamicRangeOptimizer' => { + Description => '動態範圍最佳化', + PrintConv => { + 'Advanced Auto' => '進階自動', + 'Advanced Lv1' => '進階等級 1', + 'Advanced Lv2' => '進階等級 2', + 'Advanced Lv3' => '進階等級 3', + 'Advanced Lv4' => '進階等級 4', + 'Advanced Lv5' => '進階等級 5', + 'Auto' => '自動', + 'Off' => '關閉', + 'Standard' => '標準', + }, + }, + 'ExifImageHeight' => '影像高度', + 'ExifImageWidth' => '影像寬度', + 'ExifOffset' => 'Exif IFD指針', + 'ExifVersion' => 'Exif 版本', + 'ExpandFilm' => '展開相片', + 'ExpandFilterLens' => '展開濾鏡', + 'ExpandFlashLamp' => '展開閃光燈', + 'ExpandLens' => '展開鏡頭', + 'ExpandScanner' => '展開掃描器', + 'ExpandSoftware' => '展開軟體', + 'ExposureCompensation' => '曝光補償', + 'ExposureIndex' => '曝光指數', + 'ExposureMode' => { + Description => '曝光模式', + PrintConv => { + 'Auto' => '自動曝光', + 'Auto bracket' => '自動包圍曝光', + 'Manual' => '手動曝光', + }, + }, + 'ExposureProgram' => { + Description => '拍攝模式', + PrintConv => { + 'Action (High speed)' => '動態模式 (高速快門)', + 'Aperture-priority AE' => '光圈優先', + 'Creative (Slow speed)' => '景深優先', + 'Landscape' => '風景模式', + 'Manual' => '手動', + 'Not Defined' => '未定義', + 'Portrait' => '肖像模式 (背景在焦距以外的特寫照片)', + 'Program AE' => '正常', + 'Shutter speed priority AE' => '快門優先', + }, + }, + 'ExposureTime' => '曝光時間', + 'ExtraSamples' => '額外的樣本', + 'FNumber' => '光圈', + 'FaceOrientation' => { + PrintConv => { + 'Horizontal (normal)' => '0° (頂端/左邊)', + 'Rotate 180' => '180° (底部/右邊)', + 'Rotate 270 CW' => '90° CW (左邊/底部)', + 'Rotate 90 CW' => '90° CCW (右邊/頂端)', + }, + }, + 'FaxRecvParams' => '傳真接收參數', + 'FaxRecvTime' => '傳真接收時間', + 'FaxSubAddress' => '傳真附屬地址', + 'FileFormat' => '格式', + 'FileModifyDate' => '更新日期', + 'FileName' => '檔案名稱', + 'FileSize' => '檔案大小', + 'FileSource' => { + Description => '檔案來源', + PrintConv => { + 'Digital Camera' => '數位相機', + 'Film Scanner' => '底片掃描器', + 'Reflection Print Scanner' => '反射列印掃描器', + }, + }, + 'FileType' => '檔案格式', + 'Filename' => '檔案名稱', + 'FillOrder' => '填寫訂單', + 'Flash' => { + Description => '閃光燈', + PrintConv => { + 'Auto, Did not fire' => '閃光燈未擊發, 自動模式', + 'Auto, Did not fire, Red-eye reduction' => '自動, 閃光燈未擊發, 防紅眼模式', + 'Auto, Fired' => '閃光燈擊發, 自動模式', + 'Auto, Fired, Red-eye reduction' => '閃光燈擊發, 自動模式, 防紅眼模式', + 'Auto, Fired, Red-eye reduction, Return detected' => '閃光燈擊發, 自動模式, 偵測到反射光, 防紅眼模式', + 'Auto, Fired, Red-eye reduction, Return not detected' => '閃光燈擊發, 自動模式, 未偵測到反射光, 防紅眼模式', + 'Auto, Fired, Return detected' => '閃光燈擊發, 自動模式, 偵測到反射光', + 'Auto, Fired, Return not detected' => '閃光燈擊發, 自動模式, 未偵測到反射光', + 'Did not fire' => '閃光燈未亮', + 'Fired' => '閃光燈擊發', + 'Fired, Red-eye reduction' => '閃光燈擊發, 防紅眼模式', + 'Fired, Red-eye reduction, Return detected' => '閃光燈擊發, 防紅眼模式, 偵測到反射光', + 'Fired, Red-eye reduction, Return not detected' => '閃光燈擊發, 防紅眼模式, 未偵測到反射光', + 'Fired, Return detected' => '偵測到 Strobe 反射光', + 'Fired, Return not detected' => '未偵測到 Strobe 反射光', + 'No Flash' => '閃光燈未擊發', + 'No flash function' => '沒有閃光功能', + 'Off, Did not fire' => '閃光燈未擊發, 強制閃光模式', + 'Off, Did not fire, Return not detected' => '關閉, 閃光燈未擊發, 反射未偵測', + 'Off, No flash function' => '關閉, 沒有閃光功能', + 'Off, Red-eye reduction' => '關閉, 防紅眼模式', + 'On, Did not fire' => '開啟, 閃光燈未擊發', + 'On, Fired' => '閃光燈擊發, 強制閃光模式', + 'On, Red-eye reduction' => '閃光燈擊發, 強制閃光模式, 防紅眼模式', + 'On, Red-eye reduction, Return detected' => '閃光燈擊發, 強制閃光模式, 防紅眼模式, 偵測到反射光', + 'On, Red-eye reduction, Return not detected' => '閃光燈擊發, 強制閃光模式, 防紅眼模式, 未偵測到反射光', + 'On, Return detected' => '閃光燈擊發, 強制閃光模式, 偵測到反射光', + 'On, Return not detected' => '閃光燈擊發, 強制閃光模式, 未偵測到反射光', + }, + }, + 'FlashEnergy' => '閃光能量', + 'FlashExposureComp' => '閃光補償', + 'FlashpixVersion' => '支援 Flashpix 版本', + 'FocalLength' => '焦距', + 'FocalLength35efl' => '焦距(35mm換算)', + 'FocalLengthIn35mmFormat' => '35mm 相機等效焦距', + 'FocalPlaneResolutionUnit' => { + Description => '焦平面分辨率單位', + PrintConv => { + 'None' => '無', + 'inches' => '英吋', + 'um' => 'µm (微米)', + }, + }, + 'FocalPlaneXResolution' => 'X軸焦平面分辨率', + 'FocalPlaneYResolution' => 'Y軸焦平面分辨率', + 'FocusMode' => '對焦模式', + 'FrameRate' => '書面速率', + 'FrameSize' => '畫面尺寸', + 'GPSAltitude' => '海拔高度', + 'GPSAltitudeRef' => { + Description => '海拔高度參考', + PrintConv => { + 'Above Sea Level' => '海平面', + 'Below Sea Level' => '海平面參考(負值)', + }, + }, + 'GPSAreaInformation' => 'GPS區域名稱', + 'GPSDOP' => '測量精度', + 'GPSDateStamp' => 'GPS 日期', + 'GPSDestBearing' => '目的地方位', + 'GPSDestBearingRef' => { + Description => '目的地方位依據', + PrintConv => { + 'Magnetic North' => '磁性的方位', + 'True North' => '真實的方位', + }, + }, + 'GPSDestDistance' => '目的地距離', + 'GPSDestDistanceRef' => { + Description => '目的地距離依據', + PrintConv => { + 'Kilometers' => '公里', + 'Miles' => '英里', + 'Nautical Miles' => '節', + }, + }, + 'GPSDestLatitude' => '目的地緯度', + 'GPSDestLatitudeRef' => { + Description => '目的地的緯度依據', + PrintConv => { + 'North' => '北緯', + 'South' => '南緯', + }, + }, + 'GPSDestLongitude' => '目的地經度', + 'GPSDestLongitudeRef' => { + Description => '目的地的經度依據', + PrintConv => { + 'East' => '東經', + 'West' => '西經', + }, + }, + 'GPSDifferential' => { + Description => 'GPS 定位偏差修正', + PrintConv => { + 'Differential Corrected' => '定位偏差修正', + 'No Correction' => '無定位偏差修正', + }, + }, + 'GPSImgDirection' => '影像方位', + 'GPSImgDirectionRef' => { + Description => '影像方位依據', + PrintConv => { + 'Magnetic North' => '磁性的方位 ', + 'True North' => '真實的方位', + }, + }, + 'GPSInfo' => 'GPS Info IFD指針', + 'GPSLatitude' => '緯度', + 'GPSLatitudeRef' => { + Description => '北/南緯', + PrintConv => { + 'North' => '北緯', + 'South' => '南緯', + }, + }, + 'GPSLongitude' => '經度', + 'GPSLongitudeRef' => { + Description => '東/西經', + PrintConv => { + 'East' => '東經', + 'West' => '西經', + }, + }, + 'GPSMapDatum' => '使用大地測量數據', + 'GPSMeasureMode' => { + Description => 'GPS 測量模式', + PrintConv => { + '2-Dimensional Measurement' => '2-三維測量', + '3-Dimensional Measurement' => '3-三維測量', + }, + }, + 'GPSProcessingMethod' => 'GPS處理名稱', + 'GPSSatellites' => '用於測量的全球衛星定位系統衛星', + 'GPSSpeed' => 'GPS 接收機的速度', + 'GPSSpeedRef' => { + Description => '速度單位', + PrintConv => { + 'km/h' => '時速', + 'knots' => '節', + 'mph' => '英里', + }, + }, + 'GPSStatus' => { + Description => 'GPS接收機的狀態', + PrintConv => { + 'Measurement Active' => '測量有效', + 'Measurement Void' => '測量無效', + }, + }, + 'GPSTimeStamp' => 'GPS 時間 (原子鐘)', + 'GPSTrack' => '移動方位', + 'GPSTrackRef' => { + Description => '移動方位依據', + PrintConv => { + 'Magnetic North' => '磁性的方位 ', + 'True North' => '真實的方位', + }, + }, + 'GPSVersionID' => 'GPS 標籤版本', + 'GainControl' => { + Description => '增益控制', + PrintConv => { + 'High gain down' => '高衰減', + 'High gain up' => '高增益', + 'Low gain down' => '低衰減', + 'Low gain up' => '低增益', + 'None' => '無', + }, + }, + 'Gamma' => '對比系數', + 'Gradation' => '灰階', + 'GrayResponseCurve' => '灰色反應曲線', + 'GrayResponseUnit' => '灰色反應單位', + 'HDR' => { + Description => 'Auto HDR', + PrintConv => { + 'Off' => '關閉', + }, + }, + 'Headline' => '標題', + 'HighISONoiseReduction' => { + Description => '高 ISO 雜訊消除', + PrintConv => { + 'Auto' => '自動', + 'High' => '高', + 'Low' => '低', + 'Normal' => '一般', + 'Off' => '關閉', + }, + }, + 'HostComputer' => '主機', + 'Hue' => '色相', + 'ICCProfile' => 'ICC 色彩設定檔', + 'IPTC-NAA' => 'IPTC-NAA 元資料', + 'ImageDescription' => '影像標題', + 'ImageHeight' => '影像高度', + 'ImageHistory' => '影像歷史', + 'ImageNumber' => '影像編號', + 'ImageSize' => '影像尺寸', + 'ImageSourceData' => '影像來源資料', + 'ImageUniqueID' => '獨特的影像ID', + 'ImageWidth' => '影像寬度', + 'Index' => '索引', + 'Instructions' => '說明', + 'Interlace' => '交錯', + 'InteropIndex' => '互通性鑑定', + 'InteropOffset' => '互用標記', + 'InteropVersion' => '互通性版本', + 'JPEGQuality' => { + Description => '影像品質', + PrintConv => { + 'Extra Fine' => '超精細', + 'Fine' => '精細', + 'Standard' => '標準品質', + }, + }, + 'Keyword' => '關鍵字', + 'Keywords' => '關鍵字', + 'Lens' => '鏡頭', + 'LensInfo' => '鏡頭資訊', + 'LightSource' => { + Description => '光源', + PrintConv => { + 'Cloudy' => '多雲', + 'Cool White Fluorescent' => '冷白色熒光燈 (W 3800 - 4500K)', + 'Day White Fluorescent' => '日光白色熒光燈 (N 4600 - 5500K)', + 'Daylight' => '日光', + 'Daylight Fluorescent' => '日光熒光燈 (D 5700 - 7100K)', + 'Fine Weather' => '晴天', + 'Flash' => '閃光燈', + 'Fluorescent' => '日光燈', + 'ISO Studio Tungsten' => 'ISO 攝影棚鎢燈', + 'Other' => '其他光源', + 'Shade' => '陰天', + 'Standard Light A' => '標準燈光 A', + 'Standard Light B' => '標準燈光 B', + 'Standard Light C' => '標準燈光 C', + 'Tungsten (Incandescent)' => '鎢絲燈', + 'Unknown' => '未知', + 'Warm White Fluorescent' => '暖白螢光燈 (L 2600 - 3250K)', + 'White Fluorescent' => '白色熒光燈 (WW 3250 - 3800K)', + }, + }, + 'Lightness' => '明暗度', + 'Location' => '地址', + 'LongExposureNoiseReduction' => { + Description => '消除長曝雜訊', + PrintConv => { + 'Off' => '關閉', + 'On' => '開啟', + }, + }, + 'Make' => '製造商', + 'MakerNote' => '製造商註解', + 'MakerNotes' => '製造商記錄', + 'MaxAperture' => '鏡頭光圈最大值', + 'MaxApertureValue' => '鏡頭最大光圈', + 'MaxSampleValue' => '大樣品值', + 'MeteringMode' => { + Description => '測光模式', + PrintConv => { + 'Average' => '平均測光', + 'Center-weighted average' => '中央重點平均測光', + 'Multi-segment' => '評價測光', + 'Multi-spot' => '多點測光', + 'Other' => '其他', + 'Partial' => '局部測光', + 'Spot' => '點測光', + 'Unknown' => '未知', + }, + }, + 'MinSampleValue' => '小樣品值', + 'Model' => '相機型號', + 'Model2' => '第二影像輸入設備', + 'ModifyDate' => '檔案建立日期及時間', + 'MultiFrameNoiseReduction' => { + Description => '多框雜訊消除', + PrintConv => { + 'Off' => '關閉', + 'On' => '開啟', + }, + }, + 'Noise' => '雜訊', + 'NoiseReduction' => '雜訊抑制', + 'Opto-ElectricConvFactor' => '光電轉換因子', + 'Orientation' => { + Description => '影像的方向', + PrintConv => { + 'Horizontal (normal)' => '0° (頂端/左邊)', + 'Mirror horizontal' => '0° (頂端/右邊)', + 'Mirror horizontal and rotate 270 CW' => '90° CW (左邊/頂端)', + 'Mirror horizontal and rotate 90 CW' => '90° CCW (右邊/底部)', + 'Mirror vertical' => '180° (底部/左邊)', + 'Rotate 180' => '180° (底部/右邊)', + 'Rotate 270 CW' => '90° CW (左邊/底部)', + 'Rotate 90 CW' => '90° CCW (右邊/頂端)', + }, + }, + 'Padding' => '填充', + 'PageName' => '名稱', + 'PageNumber' => '頁次', + 'PhotometricInterpretation' => { + Description => '像素格式', + PrintConv => { + 'BlackIsZero' => '黑色為零', + 'Color Filter Array' => 'CFA (彩色濾光片矩陣)', + 'RGB Palette' => '調色板的顏色', + 'Transparency Mask' => '透明遮罩', + 'WhiteIsZero' => '白色為零', + }, + }, + 'PlanarConfiguration' => { + Description => '影像資料編排方式', + PrintConv => { + 'Chunky' => 'Chunky 格式 (交錯型)', + 'Planar' => 'Planar 格式 (平面型)', + }, + }, + 'Predictor' => { + Description => '預測', + PrintConv => { + 'Horizontal differencing' => '水平區別', + 'None' => '沒有使用過預測編碼方案', + }, + }, + 'PrimaryChromaticities' => '預選的色度', + 'ProcessingSoftware' => '處理軟體', + 'Province-State' => '州/省', + 'Quality' => { + Description => '影像品質', + PrintConv => { + 'Compressed RAW' => 'cRAW', + 'Compressed RAW + JPEG' => 'cRAW+JPEG', + 'Extra Fine' => '超精細', + 'Fine' => '精細', + 'Low' => '低品質', + 'Normal' => '標準品質', + 'RAW + JPEG' => 'RAW+JPEG', + 'Standard' => '標準', + }, + }, + 'Rating' => '評分', + 'RatingPercent' => '評分的百分比', + 'RecordMode' => '記錄模式', + 'ReferenceBlackWhite' => '對黑色和白色的參考價值', + 'RelatedImageFileFormat' => '相關的影像檔案格式', + 'RelatedImageHeight' => '相關的影像高度', + 'RelatedImageWidth' => '相關的影像寬度', + 'RelatedSoundFile' => '相關的音頻檔案', + 'ResolutionUnit' => { + Description => '寬與高的單位', + PrintConv => { + 'None' => '無', + 'cm' => '公分', + 'inches' => '英吋', + }, + }, + 'RowsPerStrip' => '每條列數', + 'SamplesPerPixel' => '元件數量', + 'Saturation' => { + Description => '飽和度', + PrintConv => { + 'High' => '高飽和度', + 'Low' => '低飽和度', + 'Normal' => '標準', + }, + }, + 'SceneCaptureType' => { + Description => '場景擷取類型', + PrintConv => { + 'Landscape' => '風景', + 'Night' => '夜景', + 'Portrait' => '肖像', + 'Standard' => '標準', + }, + }, + 'SceneMode' => { + Description => '場景選擇', + PrintConv => { + '3D Sweep Panorama' => '3D', + 'Anti Motion Blur' => '防止移動模糊', + 'Auto' => '自動', + 'Cont. Priority AE' => '連拍優先AE', + 'Handheld Night Shot' => '手持夜拍', + 'Landscape' => '風景', + 'Macro' => '超近拍攝', + 'Night Portrait' => '夜間肖像', + 'Night Scene' => '夜景', + 'Night View/Portrait' => '夜景/肖像', + 'Portrait' => '肖像', + 'Sports' => '運動場面', + 'Sunset' => '夕陽', + 'Sweep Panorama' => '全景攝影', + }, + }, + 'SceneType' => { + Description => '場景類型', + PrintConv => { + 'Directly photographed' => '直接拍攝的影像', + }, + }, + 'SecurityClassification' => { + Description => '安全分類', + PrintConv => { + 'Confidential' => '秘密', + 'Restricted' => '限制', + 'Secret' => '機密', + 'Top Secret' => '最高機密', + 'Unclassified' => '未分類', + }, + }, + 'SelfTimerMode' => '倒數自拍模式', + 'SensingMethod' => { + Description => '感測器類型', + PrintConv => { + 'Color sequential area' => '連續彩色感測器', + 'Color sequential linear' => '連續彩色線性感測器', + 'Monochrome area' => '單色感測器', + 'Monochrome linear' => '單色線性感測器', + 'Not defined' => '未定義', + 'One-chip color area' => '單晶片彩色感測器', + 'Three-chip color area' => '三晶片彩色感測器', + 'Trilinear' => '三線性感測器', + 'Two-chip color area' => '雙晶片彩色感測器', + }, + }, + 'SerialNumber' => '照相機ID', + 'ShadingCompensation' => '陰影補償', + 'Sharpness' => { + Description => '銳利度', + PrintConv => { + 'Hard' => '硬', + 'Normal' => '標準', + 'Soft' => '軟', + }, + }, + 'ShootingMode' => '拍攝模式', + 'ShutterSpeed' => '曝光時間', + 'ShutterSpeedValue' => '快門', + 'Software' => '軟體', + 'Source' => '來源', + 'SpatialFrequencyResponse' => '空間頻率響應', + 'SpectralSensitivity' => '光譜靈敏度', + 'State' => '州', + 'StripByteCounts' => '此資料區段的容量', + 'StripOffsets' => '影像資料位址', + 'SubSecTime' => '日期時間秒', + 'SubSecTimeDigitized' => '數位化的日期時間秒', + 'SubSecTimeOriginal' => '原始影像日期時間秒', + 'SubfileType' => '新的 subfile 類型', + 'Subject' => '主旨', + 'SubjectArea' => '主題地區', + 'SubjectDistance' => '主體距離範圍', + 'SubjectDistanceRange' => { + Description => '主體距離範圍', + PrintConv => { + 'Close' => '近', + 'Distant' => '遠', + 'Macro' => '微距', + 'Unknown' => '未知', + }, + }, + 'SubjectLocation' => '主題位置', + 'SupplementalCategories' => '補充類別', + 'T4Options' => '未壓縮', + 'ThumbnailImage' => '縮略圖', + 'ThumbnailImageSize' => '縮圖尺寸', + 'Title' => '標題', + 'TransferFunction' => '傳遞函數', + 'TransmissionReference' => '傳輸附註', + 'Urgency' => '緊急度', + 'UserComment' => '使用者註解', + 'WhiteBalance' => { + Description => '白平衡', + PrintConv => { + 'Auto' => '自動', + 'Black & White' => '黑白', + 'Cloudy' => '多雲', + 'Color Temperature/Color Filter' => '色溫 / 彩色濾鏡', + 'Cool White Fluorescent' => '冷白色螢光燈', + 'Custom' => '自設', + 'Custom 1' => '用戶自定1', + 'Custom 2' => '用戶自定2', + 'Custom 3' => '用戶自定3', + 'Custom 4' => '用戶自定4', + 'Day White Fluorescent' => '日光白色螢光燈', + 'Daylight' => '日光', + 'Daylight Fluorescent' => '日光色螢光燈', + 'Flash' => '閃光燈', + 'Fluorescent' => '熒光燈', + 'Manual' => '手動', + 'Shade' => '陰天', + 'Tungsten' => '白熾燈', + 'Warm White Fluorescent' => '暖白螢光燈', + 'White Fluorescent' => '白色熒光燈', + }, + }, + 'WhitePoint' => '白點色度', + 'Writer-Editor' => '說明作者', + 'XMP' => 'XMP 元資料', + 'XPosition' => 'X 位置', + 'XResolution' => '水平解析度', + 'YCbCrCoefficients' => '顏色空間變化矩陣系數', + 'YCbCrPositioning' => { + Description => 'Y 及 C 的設定', + PrintConv => { + 'Centered' => '中心', + 'Co-sited' => '一致', + }, + }, + 'YCbCrSubSampling' => 'Y 到 C 的抽樣比率', + 'YPosition' => 'Y 位置', + 'YResolution' => '垂直解析度', + 'ZoneMatching' => { + Description => '區域匹配', + PrintConv => { + 'High Key' => '高', + 'ISO Setting Used' => '關閉', + 'Low Key' => '低', + }, + }, +); + +1; # end + + +__END__ + +=head1 NAME + +Image::ExifTool::Lang::zh_tw.pm - ExifTool Traditional Chinese language translations + +=head1 DESCRIPTION + +This file is used by Image::ExifTool to generate localized tag descriptions +and values. + +=head1 AUTHOR + +Copyright 2003-2019, Phil Harvey (phil at owl.phy.queensu.ca) + +This library is free software; you can redistribute it and/or modify it +under the same terms as Perl itself. + +=head1 ACKNOWLEDGEMENTS + +Thanks to Jens Duttke and MikeF for providing this translation. + +=head1 SEE ALSO + +L<Image::ExifTool(3pm)|Image::ExifTool>, +L<Image::ExifTool::TagInfoXML(3pm)|Image::ExifTool::TagInfoXML> + +=cut diff --git a/lib/Image/ExifTool/Leaf.pm b/lib/Image/ExifTool/Leaf.pm new file mode 100644 index 0000000..2bdb3fc --- /dev/null +++ b/lib/Image/ExifTool/Leaf.pm @@ -0,0 +1,517 @@ +#------------------------------------------------------------------------------ +# File: Leaf.pm +# +# Description: Read Creo Leaf EXIF meta information +# +# Revisions: 09/28/2005 - P. Harvey Created +#------------------------------------------------------------------------------ + +package Image::ExifTool::Leaf; + +use strict; +use vars qw($VERSION); +use Image::ExifTool qw(:DataAccess :Utils); +use Image::ExifTool::Exif; + +$VERSION = '1.07'; + +sub ProcessLeaf($$$); + +%Image::ExifTool::Leaf::Main = ( + PROCESS_PROC => \&ProcessLeaf, + GROUPS => { 0 => 'Leaf', 2 => 'Camera' }, + NOTES => q{ + These tags are found in .MOS images from Leaf digital camera backs as + written by Creo Leaf Capture. They exist within the Leaf-specific directory + structure of EXIF tag 0x8606. The tables below list observed Leaf tags, + however ExifTool will extract any tags found in the Leaf directories even if + they don't appear in these tables. + }, + icc_camera_profile => { + Name => 'ICC_Profile', + SubDirectory => { + TagTable => 'Image::ExifTool::ICC_Profile::Main', + }, + }, + icc_rgb_ws_profile => { + Name => 'RGB_Profile', + SubDirectory => { + TagTable => 'Image::ExifTool::ICC_Profile::Main', + }, + }, + camera_profile => { + Name => 'CameraProfile', + SubDirectory => { + TagTable => 'Image::ExifTool::Leaf::CameraProfile', + }, + }, + JPEG_preview_data => { + %Image::ExifTool::previewImageTagInfo, + Groups => { 2 => 'Preview' }, + }, + JPEG_preview_info => 'PreviewInfo', + icc_camera_to_tone_space_flow => { + Name => 'ToneSpaceFlow', + Description => 'ICC To Tone Space Flow', + Format => 'int16u', + }, + icc_camera_to_tone_matrix => { + Name => 'ToneMatrix', + Description => 'ICC To Tone Matrix', + Format => 'int8u', + Binary => 1, + }, + PDA_histogram_data => { + Name => 'PDAHistogram', + Binary => 1, + }, + pattern_ratation_angle => { + Name => 'PatternAngle', + Description => 'Pattern Rotation Angle', + Format => 'int16u', + Notes => '"ratation" is not a typo', + }, + back_serial_number => { + Name => 'BackSerial', + Description => 'Back Serial Number', + PrintConv => '$val =~ s/ .*//s; $val', + }, + image_offset => { Format => 'int16u' }, +); + +%Image::ExifTool::Leaf::CameraProfile = ( + PROCESS_PROC => \&ProcessLeaf, + GROUPS => { 0 => 'Leaf', 2 => 'Camera' }, + CamProf_version => 'CameraProfileVersion', + CamProf_name => 'CameraName', + CamProf_type => 'CameraType', + CamProf_back_type => 'CameraBackType', + CamProf_back_type => { + Name => 'CameraBackType', + }, + CamProf_capture_profile => { + SubDirectory => { + TagTable => 'Image::ExifTool::Leaf::CaptureProfile', + }, + }, + CamProf_image_profile => { + SubDirectory => { + TagTable => 'Image::ExifTool::Leaf::ImageProfile', + }, + }, +); + +%Image::ExifTool::Leaf::CaptureProfile = ( + PROCESS_PROC => \&ProcessLeaf, + GROUPS => { 0 => 'Leaf', 2 => 'Image' }, + CaptProf_version => {}, + CaptProf_name => {}, + CaptProf_type => {}, + CaptProf_back_type => {}, + CaptProf_serial_number => { + Name => 'CaptureSerial', + Description => 'Capture Serial Number', + PrintConv => '$val =~ s/ .*//s; $val', + }, + CaptProf_image_offset => {}, + CaptProf_luminance_consts => {}, + CaptProf_xy_offset_info => 'XYOffsetInfo', + CaptProf_color_matrix => {}, + CaptProf_reconstruction_type=> {}, + CaptProf_image_fields => {}, + CaptProf_image_bounds => {}, + CaptProf_number_of_planes => {}, + CaptProf_raw_data_rotation => {}, + CaptProf_color_averages => {}, + CaptProf_mosaic_pattern => {}, + CaptProf_dark_correction_type=>{}, + CaptProf_right_dark_rect => {}, + CaptProf_left_dark_rect => {}, + CaptProf_center_dark_rect => {}, + CaptProf_CCD_rect => {}, + CaptProf_CCD_valid_rect => {}, + CaptProf_CCD_video_rect => {}, +); + +%Image::ExifTool::Leaf::ImageProfile = ( + PROCESS_PROC => \&ProcessLeaf, + GROUPS => { 0 => 'Leaf', 2 => 'Image' }, + ImgProf_version => {}, + ImgProf_name => {}, + ImgProf_type => {}, + ImgProf_back_type => {}, + ImgProf_shoot_setup => { + SubDirectory => { + TagTable => 'Image::ExifTool::Leaf::ShootSetup', + }, + }, + ImgProf_image_status => {}, + ImgProf_rotation_angle => {}, +); + +%Image::ExifTool::Leaf::ShootSetup = ( + PROCESS_PROC => \&ProcessLeaf, + GROUPS => { 0 => 'Leaf', 2 => 'Image' }, + ShootObj_version => {}, + ShootObj_name => {}, + ShootObj_type => {}, + ShootObj_back_type => {}, + ShootObj_capture_setup => { + SubDirectory => { + TagTable => 'Image::ExifTool::Leaf::CaptureSetup', + }, + }, + ShootObj_color_setup => { + SubDirectory => { + TagTable => 'Image::ExifTool::Leaf::ColorSetup', + }, + }, + ShootObj_save_setup => { + SubDirectory => { + TagTable => 'Image::ExifTool::Leaf::SaveSetup', + }, + }, + ShootObj_camera_setup => { + SubDirectory => { + TagTable => 'Image::ExifTool::Leaf::CameraSetup', + }, + }, + ShootObj_look_header => { + SubDirectory => { + TagTable => 'Image::ExifTool::Leaf::LookHeader', + }, + }, +); + +%Image::ExifTool::Leaf::CaptureSetup = ( + PROCESS_PROC => \&ProcessLeaf, + GROUPS => { 0 => 'Leaf', 2 => 'Image' }, + CaptureObj_version => {}, + CaptureObj_name => {}, + CaptureObj_type => {}, + CaptureObj_back_type => {}, + CaptureObj_neutals => { + SubDirectory => { + TagTable => 'Image::ExifTool::Leaf::Neutrals', + }, + }, + CaptureObj_selection => { + SubDirectory => { + TagTable => 'Image::ExifTool::Leaf::Selection', + }, + }, + CaptureObj_tone_curve => { + SubDirectory => { + TagTable => 'Image::ExifTool::Leaf::ToneCurve', + }, + }, + CaptureObj_sharpness => { + SubDirectory => { + TagTable => 'Image::ExifTool::Leaf::Sharpness', + }, + }, + CaptureObj_single_quality => {}, + CaptureObj_Multi_quality => {}, +); + +%Image::ExifTool::Leaf::Neutrals = ( + PROCESS_PROC => \&ProcessLeaf, + GROUPS => { 0 => 'Leaf', 2 => 'Image' }, + NeutObj_version => {}, + NeutObj_name => {}, + NeutObj_type => {}, + NeutObj_back_type => {}, + NeutObj_neutrals => {}, + NeutObj_color_casts => {}, + NeutObj_shadow_end_points => {}, + NeutObj_highlight_end_points => {}, +); + +%Image::ExifTool::Leaf::Selection = ( + PROCESS_PROC => \&ProcessLeaf, + GROUPS => { 0 => 'Leaf', 2 => 'Image' }, + SelObj_version => {}, + SelObj_name => {}, + SelObj_type => {}, + SelObj_back_type => {}, + SelObj_rect => {}, + SelObj_resolution => {}, + SelObj_scale => {}, + SelObj_locks => {}, + SelObj_orientation => {}, +); + +%Image::ExifTool::Leaf::ToneCurve = ( + PROCESS_PROC => \&ProcessLeaf, + GROUPS => { 0 => 'Leaf', 2 => 'Image' }, + ToneObj_version => {}, + ToneObj_name => {}, + ToneObj_type => {}, + ToneObj_back_type => {}, + ToneObj_npts => {}, + ToneObj_tones => {}, + ToneObj_gamma => {}, +); + +%Image::ExifTool::Leaf::Sharpness = ( + PROCESS_PROC => \&ProcessLeaf, + GROUPS => { 0 => 'Leaf', 2 => 'Image' }, + SharpObj_version => {}, + SharpObj_name => {}, + SharpObj_type => {}, + SharpObj_back_type => {}, + SharpObj_sharp_method => {}, + SharpObj_data_len => {}, + SharpObj_sharp_info => {}, +); + +%Image::ExifTool::Leaf::ColorSetup = ( + PROCESS_PROC => \&ProcessLeaf, + GROUPS => { 0 => 'Leaf', 2 => 'Image' }, + ColorObj_version => {}, + ColorObj_name => {}, + ColorObj_type => {}, + ColorObj_back_type => {}, + ColorObj_has_ICC => {}, + ColorObj_input_profile => {}, + ColorObj_output_profile => {}, + ColorObj_color_mode => {}, + ColorObj_color_type => {}, +); + +%Image::ExifTool::Leaf::SaveSetup = ( + PROCESS_PROC => \&ProcessLeaf, + GROUPS => { 0 => 'Leaf', 2 => 'Other' }, + SaveObj_version => {}, + SaveObj_name => {}, + SaveObj_type => {}, + SaveObj_back_type => {}, + SaveObj_leaf_auto_active=> {}, + SaveObj_leaf_hot_folder => {}, + SaveObj_leaf_output_file_type => {}, + SaveObj_leaf_auto_base_name => {}, + SaveObj_leaf_save_selection => {}, + SaveObj_leaf_open_proc_HDR => {}, + SaveObj_std_auto_active => {}, + SaveObj_std_hot_folder => {}, + SaveObj_std_output_file_type => {}, + SaveObj_std_output_color_mode => {}, + SaveObj_std_output_bit_depth => {}, + SaveObj_std_base_name => {}, + SaveObj_std_save_selection => {}, + SaveObj_std_oxygen => {}, + SaveObj_std_open_in_photoshop => {}, + SaveObj_std_scaled_output => {}, + SaveObj_std_sharpen_output => {}, +); + +%Image::ExifTool::Leaf::CameraSetup = ( + PROCESS_PROC => \&ProcessLeaf, + GROUPS => { 0 => 'Leaf', 2 => 'Camera' }, + CameraObj_version => {}, + CameraObj_name => {}, + CameraObj_type => {}, + CameraObj_back_type => {}, + CameraObj_ISO_speed => {}, + CameraObj_strobe => {}, + CameraObj_camera_type => {}, + CameraObj_lens_type => {}, + CameraObj_lens_ID => {}, +); + +%Image::ExifTool::Leaf::LookHeader = ( + PROCESS_PROC => \&ProcessLeaf, + GROUPS => { 0 => 'Leaf', 2 => 'Other' }, + LookHead_version => {}, + LookHead_name => {}, + LookHead_type => {}, + LookHead_back_type => {}, +); + +# tag table for any unknown Leaf directories +%Image::ExifTool::Leaf::Unknown = ( + PROCESS_PROC => \&ProcessLeaf, + GROUPS => { 0 => 'Leaf', 2 => 'Unknown' }, +); + +# table for Leaf SubIFD entries +%Image::ExifTool::Leaf::SubIFD = ( + GROUPS => { 0 => 'MakerNotes', 1 => 'LeafSubIFD', 2 => 'Image'}, + WRITE_PROC => \&Image::ExifTool::Exif::WriteExif, + NOTES => q{ + Leaf writes a TIFF-format sub-IFD inside IFD0 of a MOS image. No tags in + this sub-IFD are currently known, except for tags 0x8602 and 0x8606 which + really shouldn't be here anyway (so they don't appear in the table below) + because they duplicate references to the same data from tags with the same + ID in IFD0. + }, +); + +# prepare Leaf tables by generating tag 'Name' and table 'NOTES' +{ + my @tableList = ( 'Image::ExifTool::Leaf::Main' ); + my ($tag, %doneTable); + # keep prefix in tag name of common tags + my %keepPrefix = ( Version=>1, Name=>1, Type=>1, BackType=>1 ); + while (@tableList) { + my $table = shift @tableList; + next if $doneTable{$table}; + my $prefix = ($table =~ /::Main$/) ? undef : ''; + $doneTable{$table} = 1; + no strict 'refs'; + $table = \%$table; + use strict 'refs'; + foreach $tag (keys %$table) { + my $tagInfo = $$table{$tag}; + next unless ref $tagInfo eq 'HASH'; + next if $tag eq 'GROUPS'; + if (defined $prefix and not $prefix) { + ($prefix = $tag) =~ s/_.*//; + } + unless ($$tagInfo{Name}) { + my $name; + ($name = $tag) =~ s/_(.)/\U$1/g; + if ($prefix) { + $name =~ s/^$prefix//; + $name = $prefix . $name if $keepPrefix{$name}; + } + $$tagInfo{Name} = ucfirst($name); + } + next unless $$tagInfo{SubDirectory}; + my $subTable = $tagInfo->{SubDirectory}->{TagTable}; + next unless $subTable =~ /::Leaf::/; + push @tableList, $subTable; + } + next unless $prefix; + $$table{NOTES} = "All B<Tag ID>'s in the following table have a " . + "leading '${prefix}_' which\nhas been removed.\n"; + } +} + +#------------------------------------------------------------------------------ +# Process Leaf information +# Inputs: 0) ExifTool object reference +# 1) Reference to directory information hash +# 2) Pointer to tag table for this directory +# Returns: 1 on success, otherwise returns 0 and sets a Warning +sub ProcessLeaf($$$) +{ + my ($et, $dirInfo, $tagTablePtr) = @_; + my $dataPt = $$dirInfo{DataPt}; + my $dirStart = $$dirInfo{DirStart} || 0; + my $dirLen = $$dirInfo{DirLen} || $$dirInfo{DataLen} - $dirStart; + my $dirEnd = $dirStart + $dirLen; + my $verbose = $et->Options('Verbose'); + my $pos = $dirStart; + my $hdrLen = 52; # header length for PKTS information + my $success; + + $verbose and $et->VerboseDir('Leaf'); + for (;;) { + last if $pos + $hdrLen > $dirEnd; + my $header = substr($$dataPt, $pos, $hdrLen); + last unless substr($header, 0, 4) eq 'PKTS'; + $success = 1; + my $size = Get32u(\$header, 48); + $pos += $hdrLen; + if ($pos + $size > $dirEnd) { + $et->Warn('Truncated Leaf data'); + last; + } + my $tag = substr($header, 8, 40); + $tag =~ s/\0.*//s; + next unless $tag; + my $tagInfo = $et->GetTagInfo($tagTablePtr, $tag); + # generate tag info for unknown tags + my $val; + if ($tagInfo and $$tagInfo{Format}) { + $val = ReadValue($dataPt, $pos, $$tagInfo{Format}, undef, $size); + } else { + $val = substr($$dataPt, $pos, $size); + } + unless ($tagInfo) { + my $name = ucfirst($tag); + $name =~ s/_(.)/\U$1/g; + if ($val =~ /^PKTS\0\0\0\x01/) { + # also unpack unknown directories + $tagInfo = { + Name => $name, + SubDirectory => { TagTable => 'Image::ExifTool::Leaf::Unknown' }, + }; + } elsif ($tagTablePtr ne \%Image::ExifTool::Leaf::Main or + $et->Options('Unknown')) + { + $tagInfo = { + Name => $name, + Writable => 0, + PrintConv => 'length($val) > 60 ? substr($val,0,55) . "[...]" : $val', + }; + # make tags in main table unknown because they tend to be binary + $$tagInfo{Unknown} = 1 if $tagTablePtr eq \%Image::ExifTool::Leaf::Main; + } + $tagInfo and AddTagToTable($tagTablePtr, $tag, $tagInfo); + } + if ($verbose) { + $et->VerboseInfo($tag, $tagInfo, + Table => $tagTablePtr, + Value => $val, + DataPt => $dataPt, + DataPos => $$dirInfo{DataPos}, + Size => $size, + Start => $pos, + ); + } + if ($tagInfo) { + if ($$tagInfo{SubDirectory}) { + my %subdirInfo = ( + DataPt => $dataPt, + DirLen => $size, + DirStart => $pos, + DataPos => $$dirInfo{DataPos}, + DirName => 'Leaf PKTS', + ); + my $subTable = GetTagTable($tagInfo->{SubDirectory}->{TagTable}); + $et->ProcessDirectory(\%subdirInfo, $subTable); + } else { + $val =~ tr/\n/ /; # translate newlines to spaces + $val =~ s/\0+$//; # remove null terminators + $et->FoundTag($tagInfo, $val); + } + } + $pos += $size; + } + $success or $et->Warn('Bad format Leaf data'); + return $success; +} + +1; # end + +__END__ + +=head1 NAME + +Image::ExifTool::Leaf - Read Creo Leaf EXIF meta information + +=head1 SYNOPSIS + +This module is loaded automatically by Image::ExifTool when required. + +=head1 DESCRIPTION + +This module contains definitions required by Image::ExifTool to interpret +meta information from Leaf digital camera backs written by Creo Leaf +Capture. + +=head1 AUTHOR + +Copyright 2003-2019, Phil Harvey (phil at owl.phy.queensu.ca) + +This library is free software; you can redistribute it and/or modify it +under the same terms as Perl itself. + +=head1 SEE ALSO + +L<Image::ExifTool::TagNames/Leaf Tags>, +L<Image::ExifTool(3pm)|Image::ExifTool> + +=cut diff --git a/lib/Image/ExifTool/Lytro.pm b/lib/Image/ExifTool/Lytro.pm new file mode 100644 index 0000000..9c2d447 --- /dev/null +++ b/lib/Image/ExifTool/Lytro.pm @@ -0,0 +1,213 @@ +#------------------------------------------------------------------------------ +# File: Lytro.pm +# +# Description: Read Lytro LFP files +# +# Revisions: 2014-07-17 - P. Harvey Created +# +# References: 1) http://optics.miloush.net/lytro/TheFileFormat.aspx +#------------------------------------------------------------------------------ + +package Image::ExifTool::Lytro; + +use strict; +use vars qw($VERSION); +use Image::ExifTool qw(:DataAccess :Utils); +use Image::ExifTool::Import; + +$VERSION = '1.03'; + +sub ExtractTags($$$); + +# Lytro LFP tags (ref PH) +%Image::ExifTool::Lytro::Main = ( + GROUPS => { 2 => 'Camera' }, + VARS => { NO_ID => 1 }, + NOTES => q{ + Tag definitions for Lytro Light Field Picture (LFP) files. ExifTool + extracts the full JSON metadata blocks, as well as breaking them down into + individual tags. All available tags are extracted from the JSON metadata, + even if they don't appear in the table below. + }, + JSONMetadata => { + Notes => 'the full JSON-format metadata blocks', + Binary => 1, + List => 1, + }, + EmbeddedImage => { + Notes => 'JPEG image embedded in LFP files written by Lytro Desktop', + Groups => { 2 => 'Preview' }, + Binary => 1, + }, + Type => { Name => 'CameraType' }, + CameraMake => { Name => 'Make' }, + CameraModel => { Name => 'Model', Description => 'Camera Model Name' }, + CameraSerialNumber => { Name => 'SerialNumber'}, + CameraFirmware => { Name => 'FirmwareVersion'}, + DevicesAccelerometerSampleArrayTime => { Name => 'AccelerometerTime'}, + DevicesAccelerometerSampleArrayX => { Name => 'AccelerometerX'}, + DevicesAccelerometerSampleArrayY => { Name => 'AccelerometerY'}, + DevicesAccelerometerSampleArrayZ => { Name => 'AccelerometerZ'}, + DevicesClockZuluTime => { + Name => 'DateTimeOriginal', + Groups => { 2 => 'Time' }, + ValueConv => 'require Image::ExifTool::XMP; Image::ExifTool::XMP::ConvertXMPDate($val)', + PrintConv => '$self->ConvertDateTime($val)', + }, + DevicesLensFNumber => { + Name => 'FNumber', + PrintConv => 'Image::ExifTool::Exif::PrintFNumber($val)', + }, + DevicesLensFocalLength => { + Name => 'FocalLength', + ValueConv => '$val * 1000', # convert from metres to mm + PrintConv => 'sprintf("%.1f mm",$val)', + }, + DevicesLensTemperature => { + Name => 'LensTemperature', + PrintConv => 'sprintf("%.1f C",$val)', + }, + DevicesSocTemperature => { + Name => 'SocTemperature', + PrintConv => 'sprintf("%.1f C",$val)', + }, + DevicesShutterFrameExposureDuration => { + Name => 'FrameExposureTime', + PrintConv => 'Image::ExifTool::Exif::PrintExposureTime($val)', + }, + DevicesShutterPixelExposureDuration => { + Name => 'ExposureTime', + PrintConv => 'Image::ExifTool::Exif::PrintExposureTime($val)', + }, + DevicesSensorPixelPitch => { + Name => 'FocalPlaneXResolution', + Notes => 'Y resolution is the same as X resolution', + ValueConv => '25.4 / $val / 1000', # convert from metres to pixels/inch + }, + DevicesSensorSensorSerial => { Name => 'SensorSerialNumber'}, + DevicesSensorIso => { Name => 'ISO' }, + ImageLimitExposureBias => { Groups => { 2 => 'Image' }, PrintConv => 'sprintf("%+.1f", $val)' }, + ImageModulationExposureBias => { Groups => { 2 => 'Image' }, PrintConv => 'sprintf("%+.1f", $val)' }, + ImageOrientation => { + Name => 'Orientation', + Groups => { 2 => 'Image' }, + PrintConv => { + 1 => 'Horizontal (normal)', + }, + }, +); + +#------------------------------------------------------------------------------ +# Extract tags from a parsed JSON hash +# Inputs: 0) ExifTool ref, 1) tag hash ref, 2) base tag name +sub ExtractTags($$$) +{ + my ($et, $meta, $parent) = @_; + ref $meta eq 'HASH' or $et->Warn('Invalid LFP metadata'), return; + my ($key, $val, $name, $tagTablePtr); + foreach $key (sort keys %$meta) { + my $tag = $parent . ucfirst($key); + foreach $val (ref $$meta{$key} eq 'ARRAY' ? @{$$meta{$key}} : $$meta{$key}) { + ref $val eq 'HASH' and ExtractTags($et, $val, $tag), next; + $tagTablePtr or $tagTablePtr = GetTagTable('Image::ExifTool::Lytro::Main'); + unless ($$tagTablePtr{$tag}) { + ($name = $tag) =~ s/[^-_a-zA-Z0-9](.?)/\U$1/g; + $name =~ s/ParametersVendorContentComLytroTags//; + my %tagInfo; + $tagInfo{Groups} = { 2 => 'Image' } unless $name =~ s/^Devices//; + $tagInfo{List} = 1 if ref $$meta{$key} eq 'ARRAY'; + $tagInfo{Name} = $name; + my $str = $tag eq $name ? '' : " as $name"; + $et->VPrint(0, " [adding $tag$str]\n"); + AddTagToTable($tagTablePtr, $tag, \%tagInfo); + } + $et->HandleTag($tagTablePtr, $tag, $val); + } + } +} + +#------------------------------------------------------------------------------ +# Process segments from a Lytro LFP image +# Inputs: 0) ExifTool object reference, 1) dirInfo reference +# Returns: 1 on success, 0 if this wasn't a valid Lytro image +sub ProcessLFP($$) +{ + my ($et, $dirInfo) = @_; + my $raf = $$dirInfo{RAF}; + my $verbose = $et->Options('Verbose'); + my ($buff, $id); + + # validate the Lytro file header + return 0 unless $raf->Read($buff, 16) == 16 and $buff =~ /^\x89LFP\x0d\x0a\x1a\x0a/; + $et->SetFileType(); # set the FileType tag + SetByteOrder('MM'); + my $tagTablePtr = GetTagTable('Image::ExifTool::Lytro::Main'); + while ($raf->Read($buff, 16) == 16) { + $buff =~ /^\x89LF/ or $et->Warn('LFP format error'), last; + my $size = Get32u(\$buff, 12); + $size & 0x80000000 and $et->Warn('Invalid LFP segment size'), last; + $raf->Read($id, 80) == 80 or $et->Warn('Truncated LFP segment'), last; # ignore the sha1 + if ($verbose) { + $id =~ s/\0.*//s; + $et->VPrint(0, substr($buff,1,3), " segment ($size bytes, $id)\n"); + } + if ($size > 20000000) { + $raf->Seek($size, 1) or $et->Warn('Seek error in LFP file'), last; + } else { + $raf->Read($buff,$size) == $size or $et->Warn('Truncated LFP data'), last; + $et->VerboseDump(\$buff, Addr=>$raf->Tell()-$size); + if ($buff =~ /^\{\s+"/) { # JSON metadata? + pos($buff) = 0; + $et->HandleTag($tagTablePtr, 'JSONMetadata', $buff); + my $meta = Image::ExifTool::Import::ReadJSONObject(undef, \$buff); + ExtractTags($et, $meta, ''); + } elsif ($buff =~ /^\xff\xd8\xff/) { # embedded JPEG image? + $et->HandleTag($tagTablePtr, 'EmbeddedImage', $buff); + } + } + # skip padding if necessary + my $pad = 16 - ($size % 16); + $raf->Seek($pad, 1) if $pad != 16; + } + return 1; +} + +1; # end + +__END__ + +=head1 NAME + +Image::ExifTool::Lytro - Read Lytro LFP files + +=head1 SYNOPSIS + +This module is used by Image::ExifTool + +=head1 DESCRIPTION + +This module contains routines required by Image::ExifTool to read metadata +from Lytro Light Field Picture (LFP) files. + +=head1 AUTHOR + +Copyright 2003-2019, Phil Harvey (phil at owl.phy.queensu.ca) + +This library is free software; you can redistribute it and/or modify it +under the same terms as Perl itself. + +=head1 REFERENCES + +=over 4 + +=item L<http://optics.miloush.net/lytro/TheFileFormat.aspx> + +=back + +=head1 SEE ALSO + +L<Image::ExifTool::TagNames/Lytro Tags>, +L<Image::ExifTool(3pm)|Image::ExifTool> + +=cut + diff --git a/lib/Image/ExifTool/M2TS.pm b/lib/Image/ExifTool/M2TS.pm new file mode 100644 index 0000000..613e532 --- /dev/null +++ b/lib/Image/ExifTool/M2TS.pm @@ -0,0 +1,730 @@ +#------------------------------------------------------------------------------ +# File: M2TS.pm +# +# Description: Read M2TS (AVCHD) meta information +# +# Revisions: 2009/07/03 - P. Harvey Created +# +# References: 1) http://neuron2.net/library/mpeg2/iso13818-1.pdf +# 2) http://www.blu-raydisc.com/Assets/Downloadablefile/BD-RE_Part3_V2.1_WhitePaper_080406-15271.pdf +# 3) http://www.videohelp.com/forum/archive/reading-avchd-playlist-files-bdmv-playlist-mpl-t358888.html +# 4) http://en.wikipedia.org/wiki/MPEG_transport_stream +# 5) http://www.dunod.com/documents/9782100493463/49346_DVB.pdf +# 6) http://trac.handbrake.fr/browser/trunk/libhb/stream.c +# 7) http://ieeexplore.ieee.org/stamp/stamp.jsp?arnumber=04560141 +# 8) http://www.w6rz.net/xport.zip +# +# Notes: Variable names containing underlines are the same as in ref 1. +# +# Glossary: PES = Packetized Elementary Stream +# PAT = Program Association Table +# PMT = Program Map Table +# PCR = Program Clock Reference +# PID = Packet Identifier +# +# To Do: - parse PCR to obtain average bitrates? +#------------------------------------------------------------------------------ + +package Image::ExifTool::M2TS; + +use strict; +use vars qw($VERSION); +use Image::ExifTool qw(:DataAccess :Utils); + +$VERSION = '1.16'; + +# program map table "stream_type" lookup (ref 6/1) +my %streamType = ( + 0x00 => 'Reserved', + 0x01 => 'MPEG-1 Video', + 0x02 => 'MPEG-2 Video', + 0x03 => 'MPEG-1 Audio', + 0x04 => 'MPEG-2 Audio', + 0x05 => 'ISO 13818-1 private sections', + 0x06 => 'ISO 13818-1 PES private data', + 0x07 => 'ISO 13522 MHEG', + 0x08 => 'ISO 13818-1 DSM-CC', + 0x09 => 'ISO 13818-1 auxiliary', + 0x0A => 'ISO 13818-6 multi-protocol encap', + 0x0B => 'ISO 13818-6 DSM-CC U-N msgs', + 0x0C => 'ISO 13818-6 stream descriptors', + 0x0D => 'ISO 13818-6 sections', + 0x0E => 'ISO 13818-1 auxiliary', + 0x0F => 'MPEG-2 AAC Audio', + 0x10 => 'MPEG-4 Video', + 0x11 => 'MPEG-4 LATM AAC Audio', + 0x12 => 'MPEG-4 generic', + 0x13 => 'ISO 14496-1 SL-packetized', + 0x14 => 'ISO 13818-6 Synchronized Download Protocol', + # 0x15-0x7F => 'ISO 13818-1 Reserved', + 0x1b => 'H.264 Video', + 0x80 => 'DigiCipher II Video', + 0x81 => 'A52/AC-3 Audio', + 0x82 => 'HDMV DTS Audio', + 0x83 => 'LPCM Audio', + 0x84 => 'SDDS Audio', + 0x85 => 'ATSC Program ID', + 0x86 => 'DTS-HD Audio', + 0x87 => 'E-AC-3 Audio', + 0x8a => 'DTS Audio', + 0x91 => 'A52b/AC-3 Audio', + 0x92 => 'DVD_SPU vls Subtitle', + 0x94 => 'SDDS Audio', + 0xa0 => 'MSCODEC Video', + 0xea => 'Private ES (VC-1)', + # 0x80-0xFF => 'User Private', +); + +# "table_id" values (ref 5) +my %tableID = ( + 0x00 => 'Program Association', + 0x01 => 'Conditional Access', + 0x02 => 'Program Map', + 0x03 => 'Transport Stream Description', + 0x40 => 'Actual Network Information', + 0x41 => 'Other Network Information', + 0x42 => 'Actual Service Description', + 0x46 => 'Other Service Description', + 0x4a => 'Bouquet Association', + 0x4e => 'Actual Event Information - Present/Following', + 0x4f => 'Other Event Information - Present/Following', + 0x50 => 'Actual Event Information - Schedule', #(also 0x51-0x5f) + 0x60 => 'Other Event Information - Schedule', # (also 0x61-0x6f) + 0x70 => 'Time/Date', + 0x71 => 'Running Status', + 0x72 => 'Stuffing', + 0x73 => 'Time Offset', + 0x7e => 'Discontinuity Information', + 0x7f => 'Selection Information', + # 0x80-0xfe => 'User Defined', +); + +# PES stream ID's for which a syntax field does not exist +my %noSyntax = ( + 0xbc => 1, # program_stream_map + 0xbe => 1, # padding_stream + 0xbf => 1, # private_stream_2 + 0xf0 => 1, # ECM_stream + 0xf1 => 1, # EMM_stream + 0xf2 => 1, # DSMCC_stream + 0xf8 => 1, # ITU-T Rec. H.222.1 type E stream + 0xff => 1, # program_stream_directory +); + +# information extracted from the MPEG-2 transport stream +%Image::ExifTool::M2TS::Main = ( + GROUPS => { 2 => 'Video' }, + VARS => { NO_ID => 1 }, + NOTES => q{ + The MPEG-2 transport stream is used as a container for many different + audio/video formats (including AVCHD). This table lists information + extracted from M2TS files. + }, + VideoStreamType => { + PrintHex => 1, + PrintConv => \%streamType, + SeparateTable => 'StreamType', + }, + AudioStreamType => { + PrintHex => 1, + PrintConv => \%streamType, + SeparateTable => 'StreamType', + }, + Duration => { + Notes => q{ + the -fast option may be used to avoid scanning to the end of file to + calculate the Duration + }, + ValueConv => '$val / 27000000', # (clock is 27MHz) + PrintConv => 'ConvertDuration($val)', + }, + # the following tags are for documentation purposes only + _AC3 => { SubDirectory => { TagTable => 'Image::ExifTool::M2TS::AC3' } }, + _H264 => { SubDirectory => { TagTable => 'Image::ExifTool::H264::Main' } }, +); + +# information extracted from AC-3 audio streams +%Image::ExifTool::M2TS::AC3 = ( + GROUPS => { 1 => 'AC3', 2 => 'Audio' }, + VARS => { NO_ID => 1 }, + NOTES => 'Tags extracted from AC-3 audio streams.', + AudioSampleRate => { + PrintConv => { + 0 => '48000', + 1 => '44100', + 2 => '32000', + }, + }, + AudioBitrate => { + PrintConvColumns => 2, + ValueConv => { + 0 => 32000, + 1 => 40000, + 2 => 48000, + 3 => 56000, + 4 => 64000, + 5 => 80000, + 6 => 96000, + 7 => 112000, + 8 => 128000, + 9 => 160000, + 10 => 192000, + 11 => 224000, + 12 => 256000, + 13 => 320000, + 14 => 384000, + 15 => 448000, + 16 => 512000, + 17 => 576000, + 18 => 640000, + 32 => '32000 max', + 33 => '40000 max', + 34 => '48000 max', + 35 => '56000 max', + 36 => '64000 max', + 37 => '80000 max', + 38 => '96000 max', + 39 => '112000 max', + 40 => '128000 max', + 41 => '160000 max', + 42 => '192000 max', + 43 => '224000 max', + 44 => '256000 max', + 45 => '320000 max', + 46 => '384000 max', + 47 => '448000 max', + 48 => '512000 max', + 49 => '576000 max', + 50 => '640000 max', + }, + PrintConv => 'ConvertBitrate($val)', + }, + SurroundMode => { + PrintConv => { + 0 => 'Not indicated', + 1 => 'Not Dolby surround', + 2 => 'Dolby surround', + }, + }, + AudioChannels => { + PrintConvColumns => 2, + PrintConv => { + 0 => '1 + 1', + 1 => 1, + 2 => 2, + 3 => 3, + 4 => '2/1', + 5 => '3/1', + 6 => '2/2', + 7 => '3/2', + 8 => 1, + 9 => '2 max', + 10 => '3 max', + 11 => '4 max', + 12 => '5 max', + 13 => '6 max', + }, + }, +); + +#------------------------------------------------------------------------------ +# Extract information from AC-3 audio stream +# Inputs: 0) ExifTool ref, 1) data ref +# Reference: http://www.atsc.org/standards/a_52b.pdf +sub ParseAC3Audio($$) +{ + my ($et, $dataPt) = @_; + if ($$dataPt =~ /\x0b\x77..(.)/sg) { + my $sampleRate = ord($1) >> 6; + my $tagTablePtr = GetTagTable('Image::ExifTool::M2TS::AC3'); + $et->HandleTag($tagTablePtr, AudioSampleRate => $sampleRate); + } +} + +#------------------------------------------------------------------------------ +# Extract information from AC-3 stream descriptor +# Inputs: 0) ExifTool ref, 1) data ref +# Reference: http://www.atsc.org/standards/a_52b.pdf +# Note: This information is duplicated in the Audio stream, but it +# is somewhat easier to extract it from the descriptor instead +sub ParseAC3Descriptor($$) +{ + my ($et, $dataPt) = @_; + return if length $$dataPt < 3; + my @v = unpack('C3', $$dataPt); + my $tagTablePtr = GetTagTable('Image::ExifTool::M2TS::AC3'); + # $et->HandleTag($tagTablePtr, 'AudioSampleRate', $v[0] >> 5); + $et->HandleTag($tagTablePtr, 'AudioBitrate', $v[1] >> 2); + $et->HandleTag($tagTablePtr, 'SurroundMode', $v[1] & 0x03); + $et->HandleTag($tagTablePtr, 'AudioChannels', ($v[2] >> 1) & 0x0f); + # don't (yet) decode any more (language codes, etc) +} + +#------------------------------------------------------------------------------ +# Parse PID stream data +# Inputs: 0) Exiftool ref, 1) PID number, 2) PID type, 3) PID name, 4) data ref +# Returns: 0=stream parsed OK, +# 1=stream parsed but we want to parse more of these, +# -1=can't parse yet because we don't know the type +sub ParsePID($$$$$) +{ + my ($et, $pid, $type, $pidName, $dataPt) = @_; + # can't parse until we know the type (Program Map Table may be later in the stream) + return -1 unless defined $type; + my $verbose = $et->Options('Verbose'); + if ($verbose > 1) { + my $out = $et->Options('TextOut'); + printf $out "Parsing stream 0x%.4x (%s)\n", $pid, $pidName; + $et->VerboseDump($dataPt); + } + my $more = 0; + if ($type == 0x01 or $type == 0x02) { + # MPEG-1/MPEG-2 Video + require Image::ExifTool::MPEG; + Image::ExifTool::MPEG::ParseMPEGAudioVideo($et, $dataPt); + } elsif ($type == 0x03 or $type == 0x04) { + # MPEG-1/MPEG-2 Audio + require Image::ExifTool::MPEG; + Image::ExifTool::MPEG::ParseMPEGAudio($et, $dataPt); + } elsif ($type == 0x1b) { + # H.264 Video + require Image::ExifTool::H264; + $more = Image::ExifTool::H264::ParseH264Video($et, $dataPt); + # force parsing additional H264 frames with ExtractEmbedded option + if ($$et{OPTIONS}{ExtractEmbedded}) { + $more = 1; + } elsif (not $$et{OPTIONS}{Validate}) { + $et->WarnOnce('The ExtractEmbedded option may find more tags in the video data',3); + } + } elsif ($type == 0x81 or $type == 0x87 or $type == 0x91) { + # AC-3 audio + ParseAC3Audio($et, $dataPt); + } + return $more; +} + +#------------------------------------------------------------------------------ +# Extract information from a M2TS file +# Inputs: 0) ExifTool object reference, 1) DirInfo reference +# Returns: 1 on success, 0 if this wasn't a valid M2TS file +sub ProcessM2TS($$) +{ + my ($et, $dirInfo) = @_; + my $raf = $$dirInfo{RAF}; + my ($buff, $pLen, $upkPrefix, $j, $fileType, $eof); + my (%pmt, %pidType, %data, %sectLen); + my ($startTime, $endTime, $backScan, $maxBack); + my $verbose = $et->Options('Verbose'); + my $out = $et->Options('TextOut'); + + # read first packet + return 0 unless $raf->Read($buff, 8) == 8; + # test for magic number (sync byte is the only thing we can safely check) + return 0 unless $buff =~ /^(....)?\x47/s; + unless ($1) { + $pLen = 188; # no timecode + $fileType = 'M2T'; # (just as a way to tell there is no timecode) + $upkPrefix = 'N'; + } else { + $pLen = 192; # 188-byte transport packet + leading 4-byte timecode (ref 4) + $upkPrefix = 'x4N'; + } + my $prePos = $pLen - 188; # byte position of packet prefix + my $readSize = 64 * $pLen; # read 64 packets at once + $raf->Seek(0,0); # rewind to start + $raf->Read($buff, $readSize) >= $pLen * 4 or return 0; # require at least 4 packets + # validate the sync byte in the next 3 packets + for ($j=1; $j<4; ++$j) { + return 0 unless substr($buff, $prePos + $pLen * $j, 1) eq 'G'; # (0x47) + } + $et->SetFileType($fileType); + SetByteOrder('MM'); + my $tagTablePtr = GetTagTable('Image::ExifTool::M2TS::Main'); + + # PID lookup strings (will add to this with entries from program map table) + my %pidName = ( + 0 => 'Program Association Table', + 1 => 'Conditional Access Table', + 2 => 'Transport Stream Description Table', + 0x1fff => 'Null Packet', + ); + my %didPID = ( 1 => 0, 2 => 0, 0x1fff => 0 ); + my %needPID = ( 0 => 1 ); # lookup for stream PID's that we still need to parse + my $pEnd = 0; + my $i = 0; + + # parse packets from MPEG-2 Transport Stream + for (;;) { + + unless (%needPID) { + last unless defined $startTime; + # seek backwards to find last PCR + if (defined $backScan) { + last if defined $endTime; + $backScan -= $pLen; + last if $backScan < $maxBack; + } else { + undef $endTime; + last if $et->Options('FastScan'); + $verbose and print "[Starting backscan for last PCR]\n"; + # calculate position of last complete packet + my $fwdPos = $raf->Tell(); + $raf->Seek(0, 2) or last; + my $fsize = $raf->Tell(); + my $nPack = int($fsize / $pLen); + $backScan = ($nPack - 1) * $pLen - $fsize; + # set limit on how far back we will go + $maxBack = $fwdPos - $fsize; + $maxBack = -256000 if $maxBack < -256000; + } + $raf->Seek($backScan, 2) or last; + } + my $pos = $pEnd; + # read more if necessary + if ($pos + $pLen > length $buff) { + $raf->Read($buff, $readSize) >= $pLen or $eof = 1, last; + $pos = $pEnd = 0; + } + $pEnd += $pLen; + # decode the packet prefix + $pos += $prePos; + my $prefix = unpack("x${pos}N", $buff); # (use unpack instead of Get32u for speed) + # validate sync byte + unless (($prefix & 0xff000000) == 0x47000000) { + $et->Warn('M2TS synchronization error') unless defined $backScan; + last; + } + # my $transport_error_indicator = $prefix & 0x00800000; + my $payload_unit_start_indicator = $prefix & 0x00400000; + # my $transport_priority = $prefix & 0x00200000; + my $pid =($prefix & 0x001fff00) >> 8; # packet ID + # my $transport_scrambling_control = $prefix & 0x000000c0; + my $adaptation_field_exists = $prefix & 0x00000020; + my $payload_data_exists = $prefix & 0x00000010; + # my $continuity_counter = $prefix & 0x0000000f; + + if ($verbose > 1) { + print $out "Transport packet $i:\n"; + ++$i; + $et->VerboseDump(\$buff, Len => $pLen, Addr => $i * $pLen, Start => $pos - $prePos); + my $str = $pidName{$pid} ? " ($pidName{$pid})" : ''; + printf $out " Timecode: 0x%.4x\n", Get32u(\$buff, $pos - $prePos) if $pLen == 192; + printf $out " Packet ID: 0x%.4x$str\n", $pid; + printf $out " Start Flag: %s\n", $payload_unit_start_indicator ? 'Yes' : 'No'; + } + + $pos += 4; + # handle adaptation field + if ($adaptation_field_exists) { + my $len = Get8u(\$buff, $pos++); + $pos + $len > $pEnd and $et->Warn('Invalid adaptation field length'), last; + # read PCR value for calculation of Duration + if ($len > 6) { + my $flags = Get8u(\$buff, $pos); + if ($flags & 0x10) { # PCR_flag + # combine 33-bit program_clock_reference_base and 9-bit extension + my $pcrBase = Get32u(\$buff, $pos + 1); + my $pcrExt = Get16u(\$buff, $pos + 5); + # ignore separate programs (PID's) and store just the + # first and last timestamps found in the file (is this OK?) + $endTime = 300 * (2 * $pcrBase + ($pcrExt >> 15)) + ($pcrExt & 0x01ff); + $startTime = $endTime unless defined $startTime; + } + } + $pos += $len; + } + + # all done with this packet unless it carries a payload + # or if we are just looking for the last timestamp + next unless $payload_data_exists and not defined $backScan; + + # decode payload data + if ($pid == 0 or # program association table + defined $pmt{$pid}) # program map table(s) + { + # must interpret pointer field if payload_unit_start_indicator is set + my $buf2; + if ($payload_unit_start_indicator) { + # skip to start of section + my $pointer_field = Get8u(\$buff, $pos); + $pos += 1 + $pointer_field; + $pos >= $pEnd and $et->Warn('Bad pointer field'), last; + $buf2 = substr($buff, $pEnd-$pLen, $pLen); + $pos -= $pEnd - $pLen; + } else { + # not the start of a section + next unless $sectLen{$pid}; + my $more = $sectLen{$pid} - length($data{$pid}); + my $size = $pLen - $pos; + $size = $more if $size > $more; + $data{$pid} .= substr($buff, $pos, $size); + next unless $size == $more; + # we have the complete section now, so put into $buf2 for parsing + $buf2 = $data{$pid}; + $pos = 0; + delete $data{$pid}; + delete $sectLen{$pid}; + } + my $slen = length($buf2); # section length + $pos + 8 > $slen and $et->Warn('Truncated payload'), last; + # validate table ID + my $table_id = Get8u(\$buf2, $pos); + my $name = ($tableID{$table_id} || sprintf('Unknown (0x%x)',$table_id)) . ' Table'; + my $expectedID = $pid ? 0x02 : 0x00; + unless ($table_id == $expectedID) { + $verbose > 1 and print $out " (skipping $name)\n"; + delete $needPID{$pid}; + $didPID{$pid} = 1; + next; + } + # validate section syntax indicator for parsed tables (PAT, PMT) + my $section_syntax_indicator = Get8u(\$buf2, $pos + 1) & 0xc0; + $section_syntax_indicator == 0x80 or $et->Warn("Bad $name"), last; + my $section_length = Get16u(\$buf2, $pos + 1) & 0x0fff; + $section_length > 1021 and $et->Warn("Invalid $name length"), last; + if ($slen < $section_length + 3) { # (3 bytes for table_id + section_length) + # must wait until we have the full section + $data{$pid} = substr($buf2, $pos); + $sectLen{$pid} = $section_length + 3; + next; + } + my $program_number = Get16u(\$buf2, $pos + 3); + my $section_number = Get8u(\$buf2, $pos + 6); + my $last_section_number = Get8u(\$buf2, $pos + 7); + if ($verbose > 1) { + print $out " $name length: $section_length\n"; + print $out " Program No: $program_number\n" if $pid; + printf $out " Stream ID: 0x%x\n", $program_number if not $pid; + print $out " Section No: $section_number\n"; + print $out " Last Sect.: $last_section_number\n"; + } + my $end = $pos + $section_length + 3 - 4; # (don't read 4-byte CRC) + $pos += 8; + if ($pid == 0) { + # decode PAT (Program Association Table) + while ($pos <= $end - 4) { + my $program_number = Get16u(\$buf2, $pos); + my $program_map_PID = Get16u(\$buf2, $pos + 2) & 0x1fff; + $pmt{$program_map_PID} = $program_number; # save our PMT PID's + my $str = "Program $program_number Map"; + $pidName{$program_map_PID} = $str; + $needPID{$program_map_PID} = 1 unless $didPID{$program_map_PID}; + $verbose and printf $out " PID(0x%.4x) --> $str\n", $program_map_PID; + $pos += 4; + } + } else { + # decode PMT (Program Map Table) + $pos + 4 > $slen and $et->Warn('Truncated PMT'), last; + my $pcr_pid = Get16u(\$buf2, $pos) & 0x1fff; + my $program_info_length = Get16u(\$buf2, $pos + 2) & 0x0fff; + my $str = "Program $program_number Clock Reference"; + $pidName{$pcr_pid} = $str; + $verbose and printf $out " PID(0x%.4x) --> $str\n", $pcr_pid; + $pos += 4; + $pos + $program_info_length > $slen and $et->Warn('Truncated program info'), last; + # dump program information descriptors if verbose + if ($verbose > 1) { for ($j=0; $j<$program_info_length-2; ) { + my $descriptor_tag = Get8u(\$buf2, $pos + $j); + my $descriptor_length = Get8u(\$buf2, $pos + $j + 1); + $j += 2; + last if $j + $descriptor_length > $program_info_length; + my $desc = substr($buf2, $pos+$j, $descriptor_length); + $j += $descriptor_length; + $desc =~ s/([\x00-\x1f\x80-\xff])/sprintf("\\x%.2x",ord $1)/eg; + printf $out " Program Descriptor: Type=0x%.2x \"$desc\"\n", $descriptor_tag; + }} + $pos += $program_info_length; # skip descriptors (for now) + while ($pos <= $end - 5) { + my $stream_type = Get8u(\$buf2, $pos); + my $elementary_pid = Get16u(\$buf2, $pos + 1) & 0x1fff; + my $es_info_length = Get16u(\$buf2, $pos + 3) & 0x0fff; + my $str = $streamType{$stream_type}; + $str or $str = ($stream_type < 0x7f ? 'Reserved' : 'Private'); + $str = sprintf('%s (0x%.2x)', $str, $stream_type); + $str = "Program $program_number $str"; + $verbose and printf $out " PID(0x%.4x) --> $str\n", $elementary_pid; + if ($str =~ /(Audio|Video)/) { + unless ($pidName{$elementary_pid}) { + $et->HandleTag($tagTablePtr, $1 . 'StreamType', $stream_type) + } + # we want to parse all Audio and Video streams + $needPID{$elementary_pid} = 1 unless $didPID{$elementary_pid}; + } + # save PID type and name string + $pidName{$elementary_pid} = $str; + $pidType{$elementary_pid} = $stream_type; + $pos += 5; + $pos + $es_info_length > $slen and $et->Warn('Truncated ES info'), $pos = $end, last; + # parse elementary stream descriptors + for ($j=0; $j<$es_info_length-2; ) { + my $descriptor_tag = Get8u(\$buf2, $pos + $j); + my $descriptor_length = Get8u(\$buf2, $pos + $j + 1); + $j += 2; + last if $j + $descriptor_length > $es_info_length; + my $desc = substr($buf2, $pos+$j, $descriptor_length); + $j += $descriptor_length; + if ($verbose > 1) { + my $dstr = $desc; + $dstr =~ s/([\x00-\x1f\x80-\xff])/sprintf("\\x%.2x",ord $1)/eg; + printf $out " ES Descriptor: Type=0x%.2x \"$dstr\"\n", $descriptor_tag; + } + # parse type-specific descriptor information (once) + unless ($didPID{$pid}) { + if ($descriptor_tag == 0x81) { # AC-3 + ParseAC3Descriptor($et, \$desc); + } + } + } + $pos += $es_info_length; + } + } + # $pos = $end + 4; # skip CRC + + } elsif (not defined $didPID{$pid}) { + + # save data from the start of each elementary stream + if ($payload_unit_start_indicator) { + if (defined $data{$pid}) { + # we must have a whole section, so parse now + my $more = ParsePID($et, $pid, $pidType{$pid}, $pidName{$pid}, \$data{$pid}); + # start fresh even if we couldn't process this PID yet + delete $data{$pid}; + unless ($more) { + delete $needPID{$pid}; + $didPID{$pid} = 1; + next; + } + # set flag indicating we found this PID but we still want more + $needPID{$pid} = -1; + } + # check for a PES header + next if $pos + 6 > $pEnd; + my $start_code = Get32u(\$buff, $pos); + next unless ($start_code & 0xffffff00) == 0x00000100; + my $stream_id = $start_code & 0xff; + if ($verbose > 1) { + my $pes_packet_length = Get16u(\$buff, $pos + 4); + printf $out " Stream ID: 0x%.2x\n", $stream_id; + print $out " Packet Len: $pes_packet_length\n"; + } + $pos += 6; + unless ($noSyntax{$stream_id}) { + next if $pos + 3 > $pEnd; + # validate PES syntax + my $syntax = Get8u(\$buff, $pos) & 0xc0; + $syntax == 0x80 or $et->Warn('Bad PES syntax'), next; + # skip PES header + my $pes_header_data_length = Get8u(\$buff, $pos + 2); + $pos += 3 + $pes_header_data_length; + next if $pos >= $pEnd; + } + $data{$pid} = substr($buff, $pos, $pEnd-$pos); + } else { + next unless defined $data{$pid}; + # accumulate data for each elementary stream + $data{$pid} .= substr($buff, $pos, $pEnd-$pos); + } + # save only the first 256 bytes of most streams, except for + # unknown or H.264 streams where we save 1 kB + my $saveLen = (not $pidType{$pid} or $pidType{$pid} == 0x1b) ? 1024 : 256; + if (length($data{$pid}) >= $saveLen) { + my $more = ParsePID($et, $pid, $pidType{$pid}, $pidName{$pid}, \$data{$pid}); + next if $more < 0; # wait for program map table (hopefully not too long) + delete $data{$pid}; + $more and $needPID{$pid} = -1, next; # parse more of these + delete $needPID{$pid}; + $didPID{$pid} = 1; + } + next; + } + if ($needPID{$pid}) { + # we found and parsed a section with this PID, so + # delete from the lookup of PID's we still need to parse + delete $needPID{$pid}; + $didPID{$pid} = 1; + } + } + + # calculate Duration if available + if (defined $startTime and defined $endTime and $startTime != $endTime) { + $endTime += 0x80000000 * 1200 if $startTime > $endTime; # handle 33-bit wrap + $et->HandleTag($tagTablePtr, 'Duration', $endTime - $startTime); + } + + if ($verbose) { + my @need; + foreach (keys %needPID) { + push @need, sprintf('0x%.2x',$_) if $needPID{$_} > 0; + } + if (@need) { + @need = sort @need; + print $out "End of file. Missing PID(s): @need\n"; + } else { + my $what = $eof ? 'of file' : 'scan'; + print $out "End $what. All PID's parsed.\n"; + } + } + + # parse any remaining partial PID streams + my $pid; + foreach $pid (sort keys %data) { + ParsePID($et, $pid, $pidType{$pid}, $pidName{$pid}, \$data{$pid}); + delete $data{$pid}; + } + return 1; +} + +1; # end + +__END__ + +=head1 NAME + +Image::ExifTool::M2TS - Read M2TS (AVCHD) meta information + +=head1 SYNOPSIS + +This module is used by Image::ExifTool + +=head1 DESCRIPTION + +This module contains routines required by Image::ExifTool to extract +information from MPEG-2 transport streams, such as those used by AVCHD +video. + +=head1 AUTHOR + +Copyright 2003-2019, Phil Harvey (phil at owl.phy.queensu.ca) + +This library is free software; you can redistribute it and/or modify it +under the same terms as Perl itself. + +=head1 REFERENCES + +=over 4 + +=item L<http://neuron2.net/library/mpeg2/iso13818-1.pdf> + +=item L<http://www.blu-raydisc.com/Assets/Downloadablefile/BD-RE_Part3_V2.1_WhitePaper_080406-15271.pdf> + +=item L<http://www.videohelp.com/forum/archive/reading-avchd-playlist-files-bdmv-playlist-mpl-t358888.html> + +=item L<http://en.wikipedia.org/wiki/MPEG_transport_stream> + +=item L<http://www.dunod.com/documents/9782100493463/49346_DVB.pdf> + +=item L<http://trac.handbrake.fr/browser/trunk/libhb/stream.c> + +=item L<http://ieeexplore.ieee.org/stamp/stamp.jsp?arnumber=04560141> + +=item L<http://www.w6rz.net/xport.zip> + +=back + +=head1 SEE ALSO + +L<Image::ExifTool::TagNames/M2TS Tags>, +L<Image::ExifTool(3pm)|Image::ExifTool> + +=cut + diff --git a/lib/Image/ExifTool/MIE.pm b/lib/Image/ExifTool/MIE.pm new file mode 100644 index 0000000..4ff45fb --- /dev/null +++ b/lib/Image/ExifTool/MIE.pm @@ -0,0 +1,2568 @@ +#------------------------------------------------------------------------------ +# File: MIE.pm +# +# Description: Read/write MIE meta information +# +# Revisions: 11/18/2005 - P. Harvey Created +#------------------------------------------------------------------------------ + +package Image::ExifTool::MIE; + +use strict; +use vars qw($VERSION %tableDefaults); +use Image::ExifTool qw(:DataAccess :Utils); +use Image::ExifTool::Exif; +use Image::ExifTool::GPS; + +$VERSION = '1.47'; + +sub ProcessMIE($$); +sub ProcessMIEGroup($$$); +sub WriteMIEGroup($$$); +sub CheckMIE($$$); +sub GetLangInfo($$); + +# local variables +my $hasZlib; # 1=Zlib available, 0=no Zlib +my %mieCode; # reverse lookup for MIE format names +my $doneMieMap; # flag indicating we added user-defined groups to %mieMap + +# MIE format codes +my %mieFormat = ( + 0x00 => 'undef', + 0x10 => 'MIE', + 0x18 => 'MIE', + 0x20 => 'string', # ASCII (ISO 8859-1) + 0x28 => 'utf8', + 0x29 => 'utf16', + 0x2a => 'utf32', + 0x30 => 'string_list', + 0x38 => 'utf8_list', + 0x39 => 'utf16_list', + 0x3a => 'utf32_list', + 0x40 => 'int8u', + 0x41 => 'int16u', + 0x42 => 'int32u', + 0x43 => 'int64u', + 0x48 => 'int8s', + 0x49 => 'int16s', + 0x4a => 'int32s', + 0x4b => 'int64s', + 0x52 => 'rational32u', + 0x53 => 'rational64u', + 0x5a => 'rational32s', + 0x5b => 'rational64s', + 0x61 => 'fixed16u', + 0x62 => 'fixed32u', + 0x69 => 'fixed16s', + 0x6a => 'fixed32s', + 0x72 => 'float', + 0x73 => 'double', + 0x80 => 'free', +); + +# map of MIE directory locations +my %mieMap = ( + 'MIE-Meta' => 'MIE', + 'MIE-Audio' => 'MIE-Meta', + 'MIE-Camera' => 'MIE-Meta', + 'MIE-Doc' => 'MIE-Meta', + 'MIE-Geo' => 'MIE-Meta', + 'MIE-Image' => 'MIE-Meta', + 'MIE-MakerNotes' => 'MIE-Meta', + 'MIE-Preview' => 'MIE-Meta', + 'MIE-Thumbnail' => 'MIE-Meta', + 'MIE-Video' => 'MIE-Meta', + 'MIE-Flash' => 'MIE-Camera', + 'MIE-Lens' => 'MIE-Camera', + 'MIE-Orient' => 'MIE-Camera', + 'MIE-Extender' => 'MIE-Lens', + 'MIE-GPS' => 'MIE-Geo', + 'MIE-UTM' => 'MIE-Geo', + 'MIE-Canon' => 'MIE-MakerNotes', + EXIF => 'MIE-Meta', + XMP => 'MIE-Meta', + IPTC => 'MIE-Meta', + ICC_Profile => 'MIE-Meta', + ID3 => 'MIE-Meta', + CanonVRD => 'MIE-Canon', + IFD0 => 'EXIF', + IFD1 => 'IFD0', + ExifIFD => 'IFD0', + GPS => 'IFD0', + SubIFD => 'IFD0', + GlobParamIFD => 'IFD0', + PrintIM => 'IFD0', + InteropIFD => 'ExifIFD', + MakerNotes => 'ExifIFD', +); + +# convenience variables for common tagInfo entries +my %binaryConv = ( + Writable => 'undef', + Binary => 1, +); +my %dateInfo = ( + Shift => 'Time', + PrintConv => '$self->ConvertDateTime($val)', + PrintConvInv => '$self->InverseDateTime($val)', +); +my %noYes = ( 0 => 'No', 1 => 'Yes' ); +my %offOn = ( 0 => 'Off', 1 => 'On' ); + +# default entries for MIE tag tables +%tableDefaults = ( + PROCESS_PROC => \&ProcessMIE, + WRITE_PROC => \&ProcessMIE, + CHECK_PROC => \&CheckMIE, + LANG_INFO => \&GetLangInfo, + WRITABLE => 'string', + PREFERRED => 1, +); + +# MIE info +%Image::ExifTool::MIE::Main = ( + %tableDefaults, + GROUPS => { 1 => 'MIE-Main' }, + WRITE_GROUP => 'MIE-Main', + NOTES => q{ + MIE is a flexible format which may be used as a stand-alone meta information + format, for encapsulation of other files and information, or as a trailer + appended to other file formats. The tables below represent currently + defined MIE tags, however ExifTool will also extract any other information + present in a MIE file. + + When writing MIE information, some special features are supported: + + 1) String values may be written as ASCII (ISO 8859-1) or UTF-8. ExifTool + automatically detects the presence of wide characters and treats the string + appropriately. Internally, UTF-8 text may be converted to UTF-16 or UTF-32 + and stored in this format in the file if it is more compact. + + 2) All MIE string-value tags support localized text. Localized values are + written by adding a language/country code to the tag name in the form + C<TAG-xx_YY>, where C<TAG> is the tag name, C<xx> is a 2-character lower + case ISO 639-1 language code, and C<YY> is a 2-character upper case ISO + 3166-1 alpha 2 country code (eg. C<Title-en_US>). But as usual, the user + interface is case-insensitive, and ExifTool will write the correct case to + the file. + + 3) Some numerical MIE tags allow units of measurement to be specified. For + these tags, units may be added in brackets immediately following the value + (eg. C<55(mi/h)>). If no units are specified, the default units are + written. + + 4) ExifTool writes compressed metadata to MIE files if the Compress (-z) + option is used and Compress::Zlib is available. + + See L<http://owl.phy.queensu.ca/~phil/exiftool/MIE1.1-20070121.pdf> for the + official MIE specification. + }, + '0Type' => { + Name => 'SubfileType', + Notes => q{ + the capitalized common extension for this type of file. If the extension + has a dot-3 abbreviation, then the longer version is used here. For + instance, JPEG and TIFF are used, not JPG and TIF + }, + }, + '0Vers' => { + Name => 'MIEVersion', + Notes => 'version 1.1 is assumed if not specified', + }, + '1Directory' => { + Name => 'SubfileDirectory', + Notes => 'original directory for the file', + }, + '1Name' => { + Name => 'SubfileName', + Notes => 'the file name, including extension if it exists', + }, + '2MIME' => { Name => 'SubfileMIMEType' }, + Meta => { + SubDirectory => { + TagTable => 'Image::ExifTool::MIE::Meta', + DirName => 'MIE-Meta', + }, + }, + data => { + Name => 'SubfileData', + Notes => 'the subfile data', + %binaryConv, + }, + rsrc => { + Name => 'SubfileResource', + Notes => 'subfile resource fork if it exists', + %binaryConv, + }, + zmd5 => { + Name => 'MD5Digest', + Notes => q{ + 16-byte MD5 digest written in binary form or as a 32-character hex-encoded + ASCII string. Value is an MD5 digest of the entire 0MIE group as it would be + with the digest value itself set to all null bytes + }, + }, + zmie => { + Name => 'TrailerSignature', + Writable => 'undef', + Notes => q{ + used as the last element in the main "0MIE" group to identify a MIE trailer + when appended to another type of file. ExifTool will create this tag if set + to any value, but always with an empty data block + }, + ValueConvInv => '""', # data block must be empty + }, +); + +# MIE meta information group +%Image::ExifTool::MIE::Meta = ( + %tableDefaults, + GROUPS => { 1 => 'MIE-Meta', 2 => 'Image' }, + WRITE_GROUP => 'MIE-Meta', + Audio => { + SubDirectory => { + TagTable => 'Image::ExifTool::MIE::Audio', + DirName => 'MIE-Audio', + }, + }, + Camera => { + SubDirectory => { + TagTable => 'Image::ExifTool::MIE::Camera', + DirName => 'MIE-Camera', + }, + }, + Document => { + SubDirectory => { + TagTable => 'Image::ExifTool::MIE::Doc', + DirName => 'MIE-Doc', + }, + }, + EXIF => { + SubDirectory => { + TagTable => 'Image::ExifTool::Exif::Main', + ProcessProc => \&Image::ExifTool::ProcessTIFF, + WriteProc => \&Image::ExifTool::WriteTIFF, + }, + }, + Geo => { + SubDirectory => { + TagTable => 'Image::ExifTool::MIE::Geo', + DirName => 'MIE-Geo', + }, + }, + ICCProfile => { + Name => 'ICC_Profile', + SubDirectory => { TagTable => 'Image::ExifTool::ICC_Profile::Main' }, + }, + ID3 => { SubDirectory => { TagTable => 'Image::ExifTool::ID3::Main' } }, + IPTC => { SubDirectory => { TagTable => 'Image::ExifTool::IPTC::Main' } }, + Image => { + SubDirectory => { + TagTable => 'Image::ExifTool::MIE::Image', + DirName => 'MIE-Image', + }, + }, + MakerNotes => { + SubDirectory => { + TagTable => 'Image::ExifTool::MIE::MakerNotes', + DirName => 'MIE-MakerNotes', + }, + }, + Preview => { + SubDirectory => { + TagTable => 'Image::ExifTool::MIE::Preview', + DirName => 'MIE-Preview', + }, + }, + Thumbnail => { + SubDirectory => { + TagTable => 'Image::ExifTool::MIE::Thumbnail', + DirName => 'MIE-Thumbnail', + }, + }, + Video => { + SubDirectory => { + TagTable => 'Image::ExifTool::MIE::Video', + DirName => 'MIE-Video', + }, + }, + XMP => { SubDirectory => { TagTable => 'Image::ExifTool::XMP::Main' } }, +); + +# MIE document information +%Image::ExifTool::MIE::Doc = ( + %tableDefaults, + GROUPS => { 1 => 'MIE-Doc', 2 => 'Document' }, + WRITE_GROUP => 'MIE-Doc', + NOTES => 'Information describing the main document, image or file.', + Author => { Groups => { 2 => 'Author' } }, + Comment => { }, + Contributors=> { Groups => { 2 => 'Author' }, List => 1 }, + Copyright => { Groups => { 2 => 'Author' } }, + CreateDate => { Groups => { 2 => 'Time' }, %dateInfo }, + EMail => { Name => 'Email', Groups => { 2 => 'Author' } }, + Keywords => { List => 1 }, + ModifyDate => { Groups => { 2 => 'Time' }, %dateInfo }, + OriginalDate=> { + Name => 'DateTimeOriginal', + Description => 'Date/Time Original', + Groups => { 2 => 'Time' }, + %dateInfo, + }, + Phone => { Name => 'PhoneNumber', Groups => { 2 => 'Author' } }, + References => { List => 1 }, + Software => { }, + Title => { }, + URL => { }, +); + +# MIE geographic information +%Image::ExifTool::MIE::Geo = ( + %tableDefaults, + GROUPS => { 1 => 'MIE-Geo', 2 => 'Location' }, + WRITE_GROUP => 'MIE-Geo', + NOTES => 'Information related to geographic location.', + Address => { }, + City => { }, + Country => { }, + GPS => { + SubDirectory => { + TagTable => 'Image::ExifTool::MIE::GPS', + DirName => 'MIE-GPS', + }, + }, + PostalCode => { }, + State => { Notes => 'state or province' }, + UTM => { + SubDirectory => { + TagTable => 'Image::ExifTool::MIE::UTM', + DirName => 'MIE-UTM', + }, + }, +); + +# MIE GPS information +%Image::ExifTool::MIE::GPS = ( + %tableDefaults, + GROUPS => { 1 => 'MIE-GPS', 2 => 'Location' }, + WRITE_GROUP => 'MIE-GPS', + Altitude => { + Name => 'GPSAltitude', + Writable => 'rational64s', + Units => [ qw(m ft) ], + Notes => q{'m' above sea level unless 'ft' specified}, + }, + Bearing => { + Name => 'GPSDestBearing', + Writable => 'rational64s', + Units => [ qw(deg deg{mag}) ], + Notes => q{'deg' CW from true north unless 'deg{mag}' specified}, + }, + Datum => { Name => 'GPSMapDatum', Notes => 'WGS-84 assumed if not specified' }, + Differential => { + Name => 'GPSDifferential', + Writable => 'int8u', + PrintConv => { + 0 => 'No Correction', + 1 => 'Differential Corrected', + }, + }, + Distance => { + Name => 'GPSDestDistance', + Writable => 'rational64s', + Units => [ qw(km mi nmi) ], + Notes => q{'km' unless 'mi' or 'nmi' specified}, + }, + Heading => { + Name => 'GPSTrack', + Writable => 'rational64s', + Units => [ qw(deg deg{mag}) ], + Notes => q{'deg' CW from true north unless 'deg{mag}' specified}, + }, + Latitude => { + Name => 'GPSLatitude', + Writable => 'rational64s', + Count => -1, + Notes => q{ + 1 to 3 numbers: degrees, minutes then seconds. South latitudes are stored + as all negative numbers, but may be entered as positive numbers with a + trailing 'S' for convenience. For example, these are all equivalent: "-40 + -30", "-40.5", "40 30 0.00 S" + }, + ValueConv => 'Image::ExifTool::GPS::ToDegrees($val, 1)', + ValueConvInv => 'Image::ExifTool::GPS::ToDMS($self, $val, 0)', + PrintConv => 'Image::ExifTool::GPS::ToDMS($self, $val, 1, "N")', + PrintConvInv => 'Image::ExifTool::GPS::ToDegrees($val, 1)', + }, + Longitude => { + Name => 'GPSLongitude', + Writable => 'rational64s', + Count => -1, + Notes => q{ + 1 to 3 numbers: degrees, minutes then seconds. West longitudes are + negative, but may be entered as positive numbers with a trailing 'W' + }, + ValueConv => 'Image::ExifTool::GPS::ToDegrees($val, 1)', + ValueConvInv => 'Image::ExifTool::GPS::ToDMS($self, $val, 0)', + PrintConv => 'Image::ExifTool::GPS::ToDMS($self, $val, 1, "E")', + PrintConvInv => 'Image::ExifTool::GPS::ToDegrees($val, 1)', + }, + MeasureMode => { + Name => 'GPSMeasureMode', + Writable => 'int8u', + PrintConv => { 2 => '2-D', 3 => '3-D' }, + }, + Satellites => 'GPSSatellites', + Speed => { + Name => 'GPSSpeed', + Writable => 'rational64s', + Units => [ qw(km/h mi/h m/s kn) ], + Notes => q{'km/h' unless 'mi/h', 'm/s' or 'kn' specified}, + }, + DateTime => { Name => 'GPSDateTime', Groups => { 2 => 'Time' }, %dateInfo }, +); + +# MIE UTM information +%Image::ExifTool::MIE::UTM = ( + %tableDefaults, + GROUPS => { 1 => 'MIE-UTM', 2 => 'Location' }, + WRITE_GROUP => 'MIE-UTM', + Datum => { Name => 'UTMMapDatum', Notes => 'WGS-84 assumed if not specified' }, + Easting => { Name => 'UTMEasting' }, + Northing => { Name => 'UTMNorthing' }, + Zone => { Name => 'UTMZone', Writable => 'int8s' }, +); + +# MIE image information +%Image::ExifTool::MIE::Image = ( + %tableDefaults, + GROUPS => { 1 => 'MIE-Image', 2 => 'Image' }, + WRITE_GROUP => 'MIE-Image', + '0Type' => { Name => 'FullSizeImageType', Notes => 'JPEG if not specified' }, + '1Name' => { Name => 'FullSizeImageName' }, + BitDepth => { Name => 'BitDepth', Writable => 'int16u' }, + ColorSpace => { Notes => 'standard ColorSpace values are "sRGB" and "Adobe RGB"' }, + Components => { + Name => 'ComponentsConfiguration', + Notes => 'string composed of R, G, B, Y, Cb and Cr', + }, + Compression => { Name => 'CompressionRatio', Writable => 'rational32u' }, + ImageSize => { + Writable => 'int16u', + Count => -1, + Notes => '2 or 3 values, for number of XY or XYZ pixels', + PrintConv => '$val=~tr/ /x/;$val', + PrintConvInv => '$val=~tr/x/ /;$val', + }, + Resolution => { + Writable => 'rational64u', + Units => [ qw(/in /cm /deg /arcmin /arcsec), '' ], + Count => -1, + Notes => q{ + 1 to 3 values. A single value for equal resolution in all directions, or + separate X, Y and Z values if necessary. Units are '/in' unless '/cm', + '/deg', '/arcmin', '/arcsec' or '' specified + }, + PrintConv => '$val=~tr/ /x/;$val', + PrintConvInv => '$val=~tr/x/ /;$val', + }, + data => { + Name => 'FullSizeImage', + Groups => { 2 => 'Preview' }, + %binaryConv, + RawConv => '$self->ValidateImage(\$val,$tag)', + }, +); + +# MIE preview image +%Image::ExifTool::MIE::Preview = ( + %tableDefaults, + GROUPS => { 1 => 'MIE-Preview', 2 => 'Image' }, + WRITE_GROUP => 'MIE-Preview', + '0Type' => { Name => 'PreviewImageType', Notes => 'JPEG if not specified' }, + '1Name' => { Name => 'PreviewImageName' }, + ImageSize => { + Name => 'PreviewImageSize', + Writable => 'int16u', + Count => -1, + Notes => '2 or 3 values, for number of XY or XYZ pixels', + PrintConv => '$val=~tr/ /x/;$val', + PrintConvInv => '$val=~tr/x/ /;$val', + }, + data => { + Name => 'PreviewImage', + Groups => { 2 => 'Preview' }, + %binaryConv, + RawConv => '$self->ValidateImage(\$val,$tag)', + }, +); + +# MIE thumbnail image +%Image::ExifTool::MIE::Thumbnail = ( + %tableDefaults, + GROUPS => { 1 => 'MIE-Thumbnail', 2 => 'Image' }, + WRITE_GROUP => 'MIE-Thumbnail', + '0Type' => { Name => 'ThumbnailImageType', Notes => 'JPEG if not specified' }, + '1Name' => { Name => 'ThumbnailImageName' }, + ImageSize => { + Name => 'ThumbnailImageSize', + Writable => 'int16u', + Count => -1, + Notes => '2 or 3 values, for number of XY or XYZ pixels', + PrintConv => '$val=~tr/ /x/;$val', + PrintConvInv => '$val=~tr/x/ /;$val', + }, + data => { + Name => 'ThumbnailImage', + Groups => { 2 => 'Preview' }, + %binaryConv, + RawConv => '$self->ValidateImage(\$val,$tag)', + }, +); + +# MIE audio information +%Image::ExifTool::MIE::Audio = ( + %tableDefaults, + GROUPS => { 1 => 'MIE-Audio', 2 => 'Audio' }, + WRITE_GROUP => 'MIE-Audio', + NOTES => q{ + For the Audio group (and any other group containing a 'data' element), tags + refer to the contained data if present, otherwise they refer to the main + SubfileData. The C<0Type> and C<1Name> elements should exist only if C<data> + is present. + }, + '0Type' => { Name => 'RelatedAudioFileType', Notes => 'MP3 if not specified' }, + '1Name' => { Name => 'RelatedAudioFileName' }, + SampleBits => { Writable => 'int16u' }, + Channels => { Writable => 'int8u' }, + Compression => { Name => 'AudioCompression' }, + Duration => { Writable => 'rational64u', PrintConv => 'ConvertDuration($val)' }, + SampleRate => { Writable => 'int32u' }, + data => { Name => 'RelatedAudioFile', %binaryConv }, +); + +# MIE video information +%Image::ExifTool::MIE::Video = ( + %tableDefaults, + GROUPS => { 1 => 'MIE-Video', 2 => 'Video' }, + WRITE_GROUP => 'MIE-Video', + '0Type' => { Name => 'RelatedVideoFileType', Notes => 'MOV if not specified' }, + '1Name' => { Name => 'RelatedVideoFileName' }, + Codec => { }, + Duration => { Writable => 'rational64u', PrintConv => 'ConvertDuration($val)' }, + data => { Name => 'RelatedVideoFile', %binaryConv }, +); + +# MIE camera information +%Image::ExifTool::MIE::Camera = ( + %tableDefaults, + GROUPS => { 1 => 'MIE-Camera', 2 => 'Camera' }, + WRITE_GROUP => 'MIE-Camera', + Brightness => { Writable => 'int8s' }, + ColorTemperature=> { Writable => 'int32u' }, + ColorBalance => { + Writable => 'rational64u', + Count => 3, + Notes => 'RGB scaling factors', + }, + Contrast => { Writable => 'int8s' }, + DigitalZoom => { Writable => 'rational64u' }, + ExposureComp => { Name => 'ExposureCompensation', Writable => 'rational64s' }, + ExposureMode => { }, + ExposureTime => { + Writable => 'rational64u', + PrintConv => 'Image::ExifTool::Exif::PrintExposureTime($val)', + PrintConvInv => '$val', + }, + Flash => { + SubDirectory => { + TagTable => 'Image::ExifTool::MIE::Flash', + DirName => 'MIE-Flash', + }, + }, + FirmwareVersion => { }, + FocusMode => { }, + ISO => { Writable => 'int16u' }, + ISOSetting => { + Writable => 'int16u', + Notes => '0 = Auto, otherwise manual ISO speed setting', + }, + ImageNumber => { Writable => 'int32u' }, + ImageQuality => { Notes => 'Economy, Normal, Fine, Super Fine or Raw' }, + ImageStabilization => { Writable => 'int8u', %offOn }, + Lens => { + SubDirectory => { + TagTable => 'Image::ExifTool::MIE::Lens', + DirName => 'MIE-Lens', + }, + }, + Make => { }, + MeasuredEV => { Writable => 'rational64s' }, + Model => { }, + OwnerName => { }, + Orientation => { + SubDirectory => { + TagTable => 'Image::ExifTool::MIE::Orient', + DirName => 'MIE-Orient', + }, + }, + Saturation => { Writable => 'int8s' }, + SensorSize => { + Writable => 'rational64u', + Count => 2, + Notes => 'width and height of active sensor area in mm', + }, + SerialNumber => { }, + Sharpness => { Writable => 'int8s' }, + ShootingMode => { }, +); + +# Camera orientation information +%Image::ExifTool::MIE::Orient = ( + %tableDefaults, + GROUPS => { 1 => 'MIE-Orient', 2 => 'Camera' }, + WRITE_GROUP => 'MIE-Orient', + NOTES => 'These tags describe the camera orientation.', + Azimuth => { + Writable => 'rational64s', + Units => [ qw(deg deg{mag}) ], + Notes => q{'deg' CW from true north unless 'deg{mag}' specified}, + }, + Declination => { Writable => 'rational64s' }, + Elevation => { Writable => 'rational64s' }, + RightAscension => { Writable => 'rational64s' }, + Rotation => { + Writable => 'rational64s', + Notes => 'CW rotation angle of camera about lens axis', + }, +); + +# MIE camera lens information +%Image::ExifTool::MIE::Lens = ( + %tableDefaults, + GROUPS => { 1 => 'MIE-Lens', 2 => 'Camera' }, + WRITE_GROUP => 'MIE-Lens', + NOTES => q{ + All recorded lens parameters (focal length, aperture, etc) include the + effects of the extender if present. + }, + Extender => { + SubDirectory => { + TagTable => 'Image::ExifTool::MIE::Extender', + DirName => 'MIE-Extender', + }, + }, + FNumber => { Writable => 'rational64u' }, + FocalLength => { Writable => 'rational64u', Notes => 'all focal lengths in mm' }, + FocusDistance => { + Writable => 'rational64u', + Units => [ qw(m ft) ], + Notes => q{'m' unless 'ft' specified}, + }, + Make => { Name => 'LensMake' }, + MaxAperture => { Writable => 'rational64u' }, + MaxApertureAtMaxFocal => { Writable => 'rational64u' }, + MaxFocalLength => { Writable => 'rational64u' }, + MinAperture => { Writable => 'rational64u' }, + MinFocalLength => { Writable => 'rational64u' }, + Model => { Name => 'LensModel' }, + OpticalZoom => { Writable => 'rational64u' }, + SerialNumber => { Name => 'LensSerialNumber' }, +); + +# MIE lens extender information +%Image::ExifTool::MIE::Extender = ( + %tableDefaults, + GROUPS => { 1 => 'MIE-Extender', 2 => 'Camera' }, + WRITE_GROUP => 'MIE-Extender', + Magnification => { Name => 'ExtenderMagnification', Writable => 'rational64s' }, + Make => { Name => 'ExtenderMake' }, + Model => { Name => 'ExtenderModel' }, + SerialNumber => { Name => 'ExtenderSerialNumber' }, +); + +# MIE camera flash information +%Image::ExifTool::MIE::Flash = ( + %tableDefaults, + GROUPS => { 1 => 'MIE-Flash', 2 => 'Camera' }, + WRITE_GROUP => 'MIE-Flash', + ExposureComp => { Name => 'FlashExposureComp', Writable => 'rational64s' }, + Fired => { Name => 'FlashFired', Writable => 'int8u', PrintConv => \%noYes }, + GuideNumber => { Name => 'FlashGuideNumber' }, + Make => { Name => 'FlashMake' }, + Mode => { Name => 'FlashMode' }, + Model => { Name => 'FlashModel' }, + SerialNumber => { Name => 'FlashSerialNumber' }, + Type => { Name => 'FlashType', Notes => '"Internal" or "External"' }, +); + +# MIE maker notes information +%Image::ExifTool::MIE::MakerNotes = ( + %tableDefaults, + GROUPS => { 1 => 'MIE-MakerNotes' }, + WRITE_GROUP => 'MIE-MakerNotes', + NOTES => q{ + MIE maker notes are contained within separate groups for each manufacturer + to avoid name conflicts. + }, + Canon => { + SubDirectory => { + TagTable => 'Image::ExifTool::MIE::Canon', + DirName => 'MIE-Canon', + }, + }, + Casio => { SubDirectory => { TagTable => 'Image::ExifTool::MIE::Unknown' } }, + FujiFilm => { SubDirectory => { TagTable => 'Image::ExifTool::MIE::Unknown' } }, + Kodak => { SubDirectory => { TagTable => 'Image::ExifTool::MIE::Unknown' } }, + KonicaMinolta=>{ SubDirectory => { TagTable => 'Image::ExifTool::MIE::Unknown' } }, + Nikon => { SubDirectory => { TagTable => 'Image::ExifTool::MIE::Unknown' } }, + Olympus => { SubDirectory => { TagTable => 'Image::ExifTool::MIE::Unknown' } }, + Panasonic => { SubDirectory => { TagTable => 'Image::ExifTool::MIE::Unknown' } }, + Pentax => { SubDirectory => { TagTable => 'Image::ExifTool::MIE::Unknown' } }, + Ricoh => { SubDirectory => { TagTable => 'Image::ExifTool::MIE::Unknown' } }, + Sigma => { SubDirectory => { TagTable => 'Image::ExifTool::MIE::Unknown' } }, + Sony => { SubDirectory => { TagTable => 'Image::ExifTool::MIE::Unknown' } }, +); + +# MIE Canon-specific information +%Image::ExifTool::MIE::Canon = ( + %tableDefaults, + GROUPS => { 1 => 'MIE-Canon' }, + WRITE_GROUP => 'MIE-Canon', + VRD => { + Name => 'CanonVRD', + SubDirectory => { TagTable => 'Image::ExifTool::CanonVRD::Main' }, + }, +); + +%Image::ExifTool::MIE::Unknown = ( + PROCESS_PROC => \&ProcessMIE, + GROUPS => { 1 => 'MIE-Unknown' }, +); + +#------------------------------------------------------------------------------ +# Add user-defined MIE groups to %mieMap +# Inputs: none; Returns: nothing, but sets $doneMieMap flag +sub UpdateMieMap() +{ + $doneMieMap = 1; # set flag so we only do this once + return unless %Image::ExifTool::UserDefined; + my ($tableName, @tables, %doneTable, $tagID); + # get list of top-level MIE tables with user-defined tags + foreach $tableName (keys %Image::ExifTool::UserDefined) { + next unless $tableName =~ /^Image::ExifTool::MIE::/; + my $userTable = $Image::ExifTool::UserDefined{$tableName}; + my $tagTablePtr = GetTagTable($tableName) or next; + # copy the WRITE_GROUP from the actual table + $$userTable{WRITE_GROUP} = $$tagTablePtr{WRITE_GROUP}; + # add to list of tables to process + $doneTable{$tableName} = 1; + push @tables, [$tableName, $userTable]; + } + # recursively add all user-defined groups to MIE map + while (@tables) { + my ($tableName, $tagTablePtr) = @{shift @tables}; + my $parent = $$tagTablePtr{WRITE_GROUP}; + $parent or warn("No WRITE_GROUP for $tableName\n"), next; + $mieMap{$parent} or warn("$parent is not in MIE map\n"), next; + foreach $tagID (TagTableKeys($tagTablePtr)) { + my $tagInfo = $$tagTablePtr{$tagID}; + next unless ref $tagInfo eq 'HASH' and $$tagInfo{SubDirectory}; + my $subTableName = $tagInfo->{SubDirectory}->{TagTable}; + my $subTablePtr = GetTagTable($subTableName) or next; + # only care about MIE tables + next unless $$subTablePtr{PROCESS_PROC} and + $$subTablePtr{PROCESS_PROC} eq \&ProcessMIE; + my $group = $$subTablePtr{WRITE_GROUP}; + $group or warn("No WRITE_GROUP for $subTableName\n"), next; + if ($mieMap{$group} and $mieMap{$group} ne $parent) { + warn("$group already has different parent ($mieMap{$group})\n"), next; + } + $mieMap{$group} = $parent; # add to map + # process tables within this one too + $doneTable{$subTableName} and next; + $doneTable{$subTableName} = 1; + push @tables, [$subTableName, $subTablePtr]; + } + } +} + +#------------------------------------------------------------------------------ +# Get localized version of tagInfo hash +# Inputs: 0) tagInfo hash ref, 1) locale code (eg. "en_CA") +# Returns: new tagInfo hash ref, or undef if invalid +sub GetLangInfo($$) +{ + my ($tagInfo, $langCode) = @_; + # check for properly formatted language code + return undef unless $langCode =~ /^[a-z]{2}([-_])[A-Z]{2}$/; + # use '_' as a separator, but recognize '_' or '-' + $langCode =~ tr/-/_/ if $1 eq '-'; + # can only set locale on string types + return undef if $$tagInfo{Writable} and $$tagInfo{Writable} ne 'string'; + return Image::ExifTool::GetLangInfo($tagInfo, $langCode); +} + +#------------------------------------------------------------------------------ +# return true if we have Zlib::Compress +# Inputs: 0) ExifTool object ref, 1) verb for what you want to do with the info +# Returns: 1 if Zlib available, 0 otherwise +sub HasZlib($$) +{ + unless (defined $hasZlib) { + $hasZlib = eval { require Compress::Zlib }; + unless ($hasZlib) { + $hasZlib = 0; + $_[0]->Warn("Install Compress::Zlib to $_[1] compressed information"); + } + } + return $hasZlib; +} + +#------------------------------------------------------------------------------ +# Get format code for MIE group element with current byte order +# Inputs: 0) [optional] true to convert result to chr() +# Returns: format code +sub MIEGroupFormat(;$) +{ + my $chr = shift; + my $format = GetByteOrder() eq 'MM' ? 0x10 : 0x18; + return $chr ? chr($format) : $format; +} + +#------------------------------------------------------------------------------ +# ReadValue() with added support for UTF formats (utf8, utf16 and utf32) +# Inputs: 0) data reference, 1) value offset, 2) format string, +# 3) number of values (or undef to use all data) +# 4) valid data length relative to offset, 5) returned rational ref +# Returns: converted value, or undefined if data isn't there +# or list of values in list context +# Notes: all string formats are converted to UTF8 +sub ReadMIEValue($$$$$;$) +{ + my ($dataPt, $offset, $format, $count, $size, $ratPt) = @_; + my $val; + if ($format =~ /^(utf(8|16|32)|string)/) { + if ($1 eq 'utf8' or $1 eq 'string') { + # read the 8-bit string + $val = substr($$dataPt, $offset, $size); + # (as of ExifTool 7.62, leave string values unconverted) + } else { + # convert to UTF8 + my $fmt; + if (GetByteOrder() eq 'MM') { + $fmt = ($1 eq 'utf16') ? 'n' : 'N'; + } else { + $fmt = ($1 eq 'utf16') ? 'v' : 'V'; + } + my @unpk = unpack("x$offset$fmt$size",$$dataPt); + if ($] >= 5.006001) { + $val = pack('C0U*', @unpk); + } else { + $val = Image::ExifTool::PackUTF8(@unpk); + } + } + # truncate at null unless this is a list + # (strings shouldn't have a null, but just in case) + $val =~ s/\0.*//s unless $format =~ /_list$/; + } else { + $format = 'undef' if $format eq 'free'; # read 'free' as 'undef' + return ReadValue($dataPt, $offset, $format, $count, $size, $ratPt); + } + return $val; +} + +#------------------------------------------------------------------------------ +# validate raw values for writing +# Inputs: 0) ExifTool object ref, 1) tagInfo hash ref, 2) raw value ref +# Returns: error string or undef (and possibly changes value) on success +sub CheckMIE($$$) +{ + my ($et, $tagInfo, $valPtr) = @_; + my $format = $$tagInfo{Writable} || $tagInfo->{Table}->{WRITABLE}; + my $err; + + return 'No writable format' if not $format or $format eq '1'; + # handle units if supported by this tag + my $ulist = $$tagInfo{Units}; + if ($ulist and $$valPtr =~ /(.*)\((.*)\)$/) { + my ($val, $units) = ($1, $2); + ($units) = grep /^$units$/i, @$ulist; + defined $units or return 'Allowed units: (' . join('|', @$ulist) . ')'; + $err = Image::ExifTool::CheckValue(\$val, $format, $$tagInfo{Count}); + # add units back onto value + $$valPtr = "$val($units)" unless $err; + } elsif ($format !~ /^(utf|string|undef)/ and $$valPtr =~ /\)$/) { + return 'Units not supported'; + } else { + if ($format eq 'string' and $$et{OPTIONS}{Charset} ne 'UTF8' and + $$valPtr =~ /[\x80-\xff]/) + { + # convert from Charset to UTF-8 + $$valPtr = $et->Encode($$valPtr,'UTF8'); + } + $err = Image::ExifTool::CheckValue($valPtr, $format, $$tagInfo{Count}); + } + return $err; +} + +#------------------------------------------------------------------------------ +# Rewrite a MIE directory +# Inputs: 0) ExifTool object reference, 1) DirInfo reference, 2) tag table ptr +# Returns: undef on success, otherwise error message (empty message if nothing to write) +sub WriteMIEGroup($$$) +{ + my ($et, $dirInfo, $tagTablePtr) = @_; + my $outfile = $$dirInfo{OutFile}; + my $dirName = $$dirInfo{DirName}; + my $toWrite = $$dirInfo{ToWrite} || ''; + my $raf = $$dirInfo{RAF}; + my $verbose = $et->Options('Verbose'); + my $optCompress = $et->Options('Compress'); + my $out = $et->Options('TextOut'); + my ($msg, $err, $ok, $sync, $delGroup); + my $tag = ''; + my $deletedTag = ''; + + # count each MIE directory found and make name for this specific instance + my ($grp1, %isWriting); + my $cnt = $$et{MIE_COUNT}; + my $grp = $tagTablePtr->{GROUPS}->{1}; + my $n = $$cnt{'MIE-Main'} || 0; + if ($grp eq 'MIE-Main') { + $$cnt{$grp} = ++$n; + ($grp1 = $grp) =~ s/MIE-/MIE$n-/; + } else { + ($grp1 = $grp) =~ s/MIE-/MIE$n-/; + my $m = $$cnt{$grp1} = ($$cnt{$grp1} || 0) + 1; + $isWriting{"$grp$m"} = 1; # eg. 'MIE-Doc2' + $isWriting{$grp1} = 1; # eg. 'MIE1-Doc' + $grp1 .= $m; + } + # build lookup for all valid group names for this MIE group + $isWriting{$grp} = 1; # eg. 'MIE-Doc' + $isWriting{$grp1} = 1; # eg. 'MIE1-Doc2' + $isWriting{"MIE$n"} = 1; # eg. 'MIE1' + + # determine if we are deleting this group + if (%{$$et{DEL_GROUP}}) { + $delGroup = 1 if $$et{DEL_GROUP}{MIE} or + $$et{DEL_GROUP}{$grp} or + $$et{DEL_GROUP}{$grp1} or + $$et{DEL_GROUP}{"MIE$n"}; + } + + # prepare lookups and lists for writing + my $newTags = $et->GetNewTagInfoHash($tagTablePtr); + my ($addDirs, $editDirs) = $et->GetAddDirHash($tagTablePtr, $dirName); + my @editTags = sort keys %$newTags, keys %$editDirs; + $verbose and print $out $raf ? 'Writing' : 'Creating', " $grp1:\n"; + + # loop through elements in MIE group + MieElement: for (;;) { + my ($format, $tagLen, $valLen, $units, $oldHdr, $buff); + my $lastTag = $tag; + if ($raf) { + # read first 4 bytes of element header + my $n = $raf->Read($oldHdr, 4); + if ($n != 4) { + last if $n or defined $sync; + undef $raf; # all done reading + $ok = 1; + } + } + if ($raf) { + ($sync, $format, $tagLen, $valLen) = unpack('aC3', $oldHdr); + $sync eq '~' or $msg = 'Invalid sync byte', last; + + # read tag name + if ($tagLen) { + $raf->Read($tag, $tagLen) == $tagLen or last; + $oldHdr .= $tag; # add tag to element header + $et->Warn("MIE tag '${tag}' out of sequence") if $tag lt $lastTag; + # separate units from tag name if they exist + $units = $1 if $tag =~ s/\((.*)\)$//; + } else { + $tag = ''; + } + + # get multi-byte value length if necessary + if ($valLen > 252) { + # calculate number of bytes in extended DataLength + my $n = 1 << (256 - $valLen); + $raf->Read($buff, $n) == $n or last; + $oldHdr .= $buff; # add to old header + my $fmt = 'int' . ($n * 8) . 'u'; + $valLen = ReadValue(\$buff, 0, $fmt, 1, $n); + if ($valLen > 0x7fffffff) { + $msg = "Can't write $tag (DataLength > 2GB not yet supported)"; + last; + } + } + # don't rewrite free bytes or information in deleted groups + if ($format eq 0x80 or ($delGroup and $tagLen and ($format & 0xf0) != 0x10)) { + $raf->Seek($valLen, 1) or $msg = 'Seek error', last; + if ($verbose > 1) { + my $free = ($format eq 0x80) ? ' free' : ''; + print $out " - $grp1:$tag ($valLen$free bytes)\n"; + } + ++$$et{CHANGED} if $delGroup; + next; + } + } else { + # no more elements to read + $tagLen = $valLen = 0; + $tag = ''; + } +# +# write necessary new tags and process directories +# + while (@editTags) { + last if $tagLen and $editTags[0] gt $tag; + # we are writing the new tag now + my ($newVal, $writable, $oldVal, $newFormat, $compress); + my $newTag = shift @editTags; + my $newInfo = $$editDirs{$newTag}; + if ($newInfo) { + # create the new subdirectory or rewrite existing non-MIE directory + my $subTablePtr = GetTagTable($newInfo->{SubDirectory}->{TagTable}); + unless ($subTablePtr) { + $et->Warn("No tag table for $newTag $$newInfo{Name}"); + next; + } + my %subdirInfo; + my $isMieGroup = ($$subTablePtr{WRITE_PROC} and + $$subTablePtr{WRITE_PROC} eq \&ProcessMIE); + + if ($newTag eq $tag) { + # make sure that either both or neither old and new tags are MIE groups + if ($isMieGroup xor ($format & 0xf3) == 0x10) { + $et->Warn("Tag '${tag}' not expected type"); + next; # don't write our new tag + } + # uncompress existing directory into $oldVal since we are editing it + if ($format & 0x04) { + last unless HasZlib($et, 'edit'); + $raf->Read($oldVal, $valLen) == $valLen or last MieElement; + my $stat; + my $inflate = Compress::Zlib::inflateInit(); + $inflate and ($oldVal, $stat) = $inflate->inflate($oldVal); + unless ($inflate and $stat == Compress::Zlib::Z_STREAM_END()) { + $msg = "Error inflating $tag"; + last MieElement; + } + $compress = 1; + $valLen = length $oldVal; # uncompressed value length + } + } else { + # don't create this directory unless necessary + next unless $$addDirs{$newTag}; + } + + if ($isMieGroup) { + my $hdr; + if ($newTag eq $tag) { + # rewrite existing directory later unless it was compressed + last unless $compress; + # rewrite directory to '$newVal' + $newVal = ''; + %subdirInfo = ( + OutFile => \$newVal, + RAF => new File::RandomAccess(\$oldVal), + ); + } elsif ($optCompress and not $$dirInfo{IsCompressed}) { + # write to memory so we can compress the new MIE group + $compress = 1; + %subdirInfo = ( + OutFile => \$newVal, + ); + } else { + $hdr = '~' . MIEGroupFormat(1) . chr(length($newTag)) . + "\0" . $newTag; + %subdirInfo = ( + OutFile => $outfile, + ToWrite => $toWrite . $hdr, + ); + } + $subdirInfo{DirName} = $newInfo->{SubDirectory}->{DirName} || $newTag; + $subdirInfo{Parent} = $dirName; + # don't compress elements of an already compressed group + $subdirInfo{IsCompressed} = $$dirInfo{IsCompressed} || $compress; + $msg = WriteMIEGroup($et, \%subdirInfo, $subTablePtr); + last MieElement if $msg; + # message is defined but empty if nothing was written + if (defined $msg) { + undef $msg; # not a problem if nothing was written + next; + } elsif (not $compress) { + # group was written already + $toWrite = ''; + next; + } elsif (length($newVal) <= 4) { # terminator only? + $verbose and print $out "Deleted compressed $grp1 (empty)\n"; + next MieElement if $newTag eq $tag; # deleting the directory + next; # not creating the new directory + } + $writable = 'undef'; + $newFormat = MIEGroupFormat(); + } else { + if ($newTag eq $tag) { + unless ($compress) { + # read and edit existing directory + $raf->Read($oldVal, $valLen) == $valLen or last MieElement; + } + %subdirInfo = ( + DataPt => \$oldVal, + DataLen => $valLen, + DirName => $$newInfo{Name}, + DataPos => $$dirInfo{IsCompressed} ? undef : $raf->Tell() - $valLen, + DirStart=> 0, + DirLen => $valLen, + ); + # write Compact subdirectories if we will compress the data + if (($compress or $optCompress or $$dirInfo{IsCompressed}) and + eval { require Compress::Zlib }) + { + $subdirInfo{Compact} = 1; + $subdirInfo{ReadOnly} = 1; # because XMP is not writable in place + } + } + $subdirInfo{Parent} = $dirName; + my $writeProc = $newInfo->{SubDirectory}->{WriteProc}; + # reset processed lookup to avoid errors in case of multiple EXIF blocks + $$et{PROCESSED} = { }; + $newVal = $et->WriteDirectory(\%subdirInfo, $subTablePtr, $writeProc); + if (defined $newVal) { + if ($newVal eq '') { + next MieElement if $newTag eq $tag; # deleting the directory + next; # not creating the new directory + } + } else { + next unless defined $oldVal; + $newVal = $oldVal; # just copy over the old directory + } + $writable = 'undef'; + $newFormat = 0x00; # all other directories are 'undef' format + } + } else { + + # get the new tag information + $newInfo = $$newTags{$newTag}; + my $nvHash = $et->GetNewValueHash($newInfo); + my @newVals; + + # write information only to specified group + my $writeGroup = $$nvHash{WriteGroup}; + last unless $isWriting{$writeGroup}; + + # if tag existed, must decide if we want to overwrite the value + if ($newTag eq $tag) { + my $isOverwriting; + my $isList = $$newInfo{List}; + if ($isList) { + last if $$nvHash{CreateOnly}; + $isOverwriting = -1; # force processing list elements individually + } else { + $isOverwriting = $et->IsOverwriting($nvHash); + last unless $isOverwriting; + } + my ($val, $cmpVal); + if ($isOverwriting < 0 or $verbose > 1) { + # check to be sure we can uncompress the value if necessary + HasZlib($et, 'edit') or last if $format & 0x04; + # read the old value + $raf->Read($oldVal, $valLen) == $valLen or last MieElement; + # uncompress if necessary + if ($format & 0x04) { + my $stat; + my $inflate = Compress::Zlib::inflateInit(); + # must save original compressed value in case we decide + # not to overwrite it later + $cmpVal = $oldVal; + $inflate and ($oldVal, $stat) = $inflate->inflate($oldVal); + unless ($inflate and $stat == Compress::Zlib::Z_STREAM_END()) { + $msg = "Error inflating $tag"; + last MieElement; + } + $valLen = length $oldVal; # update value length + } + # convert according to specified format + my $formatStr = $mieFormat{$format & 0xfb} || 'undef'; + $val = ReadMIEValue(\$oldVal, 0, $formatStr, undef, $valLen); + if ($isOverwriting < 0 and defined $val) { + # handle list values individually + if ($isList) { + my (@vals, $v); + if ($formatStr =~ /_list$/) { + @vals = split "\0", $val; + } else { + @vals = $val; + } + # keep any list items that we aren't overwriting + foreach $v (@vals) { + next if $et->IsOverwriting($nvHash, $v); + push @newVals, $v; + } + } else { + # test to see if we really want to overwrite the value + $isOverwriting = $et->IsOverwriting($nvHash, $val); + } + } + } + if ($isOverwriting) { + # skip the old value if we didn't read it already + unless (defined $oldVal) { + $raf->Seek($valLen, 1) or $msg = 'Seek error'; + } + if ($verbose > 1) { + $val .= "($units)" if defined $units; + $et->VerboseValue("- $grp1:$$newInfo{Name}", $val); + } + $deletedTag = $tag; # remember that we deleted this tag + ++$$et{CHANGED}; # we deleted the old value + } else { + if (defined $oldVal) { + # write original compressed value + $oldVal = $cmpVal if defined $cmpVal; + } else { + $raf->Read($oldVal, $valLen) == $valLen or last MieElement; + } + # write the old value now + Write($outfile, $toWrite, $oldHdr, $oldVal) or $err = 1; + $toWrite = ''; + next MieElement; + } + unless (@newVals) { + # unshift the new tag info to write it later + unshift @editTags, $newTag; + next MieElement; # get next element from file + } + } else { + # write new value if creating, or if List and list existed, or + # if tag was previously deleted + next unless $$nvHash{IsCreating} or + (($newTag eq $lastTag and ($$newInfo{List} or $deletedTag eq $lastTag) + and not $$nvHash{EditOnly})); + } + # get the new value to write (undef to delete) + push @newVals, $et->GetNewValue($nvHash); + next unless @newVals; + $writable = $$newInfo{Writable} || $$tagTablePtr{WRITABLE}; + if ($writable eq 'string') { + # join multiple values into a single string + $newVal = join "\0", @newVals; + # write string as UTF-8,16 or 32 if value contains valid UTF-8 codes + require Image::ExifTool::XMP; + my $isUTF8 = Image::ExifTool::XMP::IsUTF8(\$newVal); + if ($isUTF8 > 0) { + $writable = 'utf8'; + # write UTF-16 or UTF-32 if it is more compact + my $to = $isUTF8 > 1 ? 'UCS4' : 'UCS2'; + my $tmp = Image::ExifTool::Decode(undef,$newVal,'UTF8',undef,$to); + if (length $tmp < length $newVal) { + $newVal = $tmp; + $writable = ($isUTF8 > 1) ? 'utf32' : 'utf16'; + } + } + # write as a list if we have multiple values + $writable .= '_list' if @newVals > 1; + } else { + # should only be one element in the list + $newVal = shift @newVals; + } + $newFormat = $mieCode{$writable}; + unless (defined $newFormat) { + $msg = "Bad format '${writable}' for $$newInfo{Name}"; + next MieElement; + } + } + + # write the new or edited element + while (defined $newFormat) { + my $valPt = \$newVal; + # remove units from value and add to tag name if supported by this tag + if ($$newInfo{Units}) { + my $val2; + if ($$valPt =~ /(.*)\((.*)\)$/) { + $val2 = $1; + $newTag .= "($2)"; + } else { + $val2 = $$valPt; + # add default units + my $ustr = '(' . $newInfo->{Units}->[0] . ')'; + $newTag .= $ustr; + $$valPt .= $ustr; + } + $valPt = \$val2; + } + # convert value if necessary + if ($writable !~ /^(utf|string|undef)/) { + my $val3 = WriteValue($$valPt, $writable, $$newInfo{Count}); + defined $val3 or $et->Warn("Error writing $newTag"), last; + $valPt = \$val3; + } + my $len = length $$valPt; + # compress value before writing if required + if (($compress or $optCompress) and not $$dirInfo{IsCompressed} and + HasZlib($et, 'write')) + { + my $deflate = Compress::Zlib::deflateInit(); + my $val4; + if ($deflate) { + $val4 = $deflate->deflate($$valPt); + $val4 .= $deflate->flush() if defined $val4; + } + if (defined $val4) { + my $len4 = length $val4; + my $saved = $len - $len4; + # only use compressed data if it is smaller + if ($saved > 0) { + $verbose and print $out " [$newTag compression saved $saved bytes]\n"; + $newFormat |= 0x04; # set compressed bit + $len = $len4; # set length + $valPt = \$val4; # set value pointer + } elsif ($verbose) { + print $out " [$newTag compression saved $saved bytes -- written uncompressed]\n"; + } + } else { + $et->Warn("Error deflating $newTag (written uncompressed)"); + } + } + # calculate the DataLength code + my $extLen; + if ($len < 253) { + $extLen = ''; + } elsif ($len < 65536) { + $extLen = Set16u($len); + $len = 255; + } elsif ($len <= 0x7fffffff) { + $extLen = Set32u($len); + $len = 254; + } else { + $et->Warn("Can't write $newTag (DataLength > 2GB not yet suppported)"); + last; # don't write this tag + } + # write this element (with leading MIE group element if not done already) + my $hdr = $toWrite . '~' . chr($newFormat) . chr(length $newTag); + Write($outfile, $hdr, chr($len), $newTag, $extLen, $$valPt) or $err = 1; + $toWrite = ''; + # we changed a tag unless just editing a subdirectory + unless ($$editDirs{$newTag}) { + $et->VerboseValue("+ $grp1:$$newInfo{Name}", $newVal); + ++$$et{CHANGED}; + } + last; # didn't want to loop anyway + } + next MieElement if defined $oldVal; + } +# +# rewrite existing element or descend into uncompressed MIE group +# + # all done this MIE group if we reached the terminator element + unless ($tagLen) { + # skip over existing terminator data (if any) + last if $valLen and not $raf->Seek($valLen, 1); + $ok = 1; + # write group terminator if necessary + unless ($toWrite) { + # write end-of-group terminator element + my $term = "~\0\0\0"; + unless ($$dirInfo{Parent}) { + # write extended terminator for file-level group + my $len = ref $outfile eq 'SCALAR' ? length($$outfile) : tell $outfile; + $len += 10; # include length of terminator itself + if ($len and $len <= 0x7fffffff) { + $term = "~\0\0\x06" . Set32u($len) . MIEGroupFormat(1) . "\x04"; + } + } + Write($outfile, $term) or $err = 1; + } + last; + } + + # descend into existing uncompressed MIE group + if ($format == 0x10 or $format == 0x18) { + my ($subTablePtr, $dirName); + my $tagInfo = $et->GetTagInfo($tagTablePtr, $tag); + if ($tagInfo and $$tagInfo{SubDirectory}) { + $dirName = $tagInfo->{SubDirectory}->{DirName}; + my $subTable = $tagInfo->{SubDirectory}->{TagTable}; + $subTablePtr = $subTable ? GetTagTable($subTable) : $tagTablePtr; + } else { + $subTablePtr = GetTagTable('Image::ExifTool::MIE::Unknown'); + } + my $hdr = '~' . chr($format) . chr(length $tag) . "\0" . $tag; + my %subdirInfo = ( + DirName => $dirName || $tag, + RAF => $raf, + ToWrite => $toWrite . $hdr, + OutFile => $outfile, + Parent => $dirName, + IsCompressed => $$dirInfo{IsCompressed}, + ); + my $oldOrder = GetByteOrder(); + SetByteOrder($format & 0x08 ? 'II' : 'MM'); + $msg = WriteMIEGroup($et, \%subdirInfo, $subTablePtr); + SetByteOrder($oldOrder); + last if $msg; + if (defined $msg) { + undef $msg; # no problem if nothing written + } else { + $toWrite = ''; + } + next; + } + # just copy existing element + my $oldVal; + $raf->Read($oldVal, $valLen) == $valLen or last; + if ($toWrite) { + Write($outfile, $toWrite) or $err = 1; + $toWrite = ''; + } + Write($outfile, $oldHdr, $oldVal) or $err = 1; + } + # return error message + if ($err) { + $msg = 'Error writing file'; + } elsif (not $ok and not $msg) { + $msg = 'Unexpected end of file'; + } elsif (not $msg and $toWrite) { + $msg = ''; # flag for nothing written + $verbose and print $out "Deleted $grp1 (empty)\n"; + } + return $msg; +} + +#------------------------------------------------------------------------------ +# Process MIE directory +# Inputs: 0) ExifTool object reference, 1) DirInfo reference, 2) tag table ref +# Returns: undef on success, or error message if there was a problem +# Notes: file pointer is positioned at the MIE end on entry +sub ProcessMIEGroup($$$) +{ + my ($et, $dirInfo, $tagTablePtr) = @_; + my $raf = $$dirInfo{RAF}; + my $verbose = $et->Options('Verbose'); + my $out = $et->Options('TextOut'); + my $notUTF8 = ($$et{OPTIONS}{Charset} ne 'UTF8'); + my ($msg, $buff, $ok, $oldIndent, $mime); + my $lastTag = ''; + + # get group 1 names: $grp doesn't have numbers (eg. 'MIE-Doc'), + # and $grp1 does (eg. 'MIE1-Doc1') + my $cnt = $$et{MIE_COUNT}; + my $grp1 = $tagTablePtr->{GROUPS}->{1}; + my $n = $$cnt{'MIE-Main'} || 0; + if ($grp1 eq 'MIE-Main') { + $$cnt{$grp1} = ++$n; + $grp1 =~ s/MIE-/MIE$n-/ if $n > 1; + } else { + $grp1 =~ s/MIE-/MIE$n-/ if $n > 1; + $$cnt{$grp1} = ($$cnt{$grp1} || 0) + 1; + $grp1 .= $$cnt{$grp1} if $$cnt{$grp1} > 1; + } + # set group1 name for all tags extracted from this group + $$et{SET_GROUP1} = $grp1; + + if ($verbose) { + $oldIndent = $$et{INDENT}; + $$et{INDENT} .= '| '; + $et->VerboseDir($grp1); + } + my $wasCompressed = $$dirInfo{WasCompressed}; + + # process all MIE elements + for (;;) { + $raf->Read($buff, 4) == 4 or last; + my ($sync, $format, $tagLen, $valLen) = unpack('aC3', $buff); + $sync eq '~' or $msg = 'Invalid sync byte', last; + + # read tag name + my ($tag, $units); + if ($tagLen) { + $raf->Read($tag, $tagLen) == $tagLen or last; + $et->Warn("MIE tag '${tag}' out of sequence") if $tag lt $lastTag; + $lastTag = $tag; + # separate units from tag name if they exist + $units = $1 if $tag =~ s/\((.*)\)$//; + } else { + $tag = ''; + } + + # get multi-byte value length if necessary + if ($valLen > 252) { + my $n = 1 << (256 - $valLen); + $raf->Read($buff, $n) == $n or last; + my $fmt = 'int' . ($n * 8) . 'u'; + $valLen = ReadValue(\$buff, 0, $fmt, 1, $n); + if ($valLen > 0x7fffffff) { + $msg = "Can't read $tag (DataLength > 2GB not yet supported)"; + last; + } + } + + # all done if we reached the group terminator + unless ($tagLen) { + # skip over terminator data block + $ok = 1 unless $valLen and not $raf->Seek($valLen, 1); + last; + } + + # get tag information hash unless this is free space + my ($tagInfo, $value); + while ($format != 0x80) { + $tagInfo = $et->GetTagInfo($tagTablePtr, $tag); + last if $tagInfo; + # extract tags with locale code + if ($tag =~ /\W/) { + if ($tag =~ /^(\w+)-([a-z]{2}_[A-Z]{2})$/) { + my ($baseTag, $langCode) = ($1, $2); + $tagInfo = $et->GetTagInfo($tagTablePtr, $baseTag); + $tagInfo = GetLangInfo($tagInfo, $langCode) if $tagInfo; + last if $tagInfo; + } else { + $et->Warn('Invalid MIE tag name'); + last; + } + } + # extract unknown tags if specified + $tagInfo = { + Name => $tag, + Writable => 0, + PrintConv => 'length($val) > 60 ? substr($val,0,55) . "[...]" : $val', + }; + AddTagToTable($tagTablePtr, $tag, $tagInfo); + last; + } + + # read value and uncompress if necessary + my $formatStr = $mieFormat{$format & 0xfb} || 'undef'; + if ($tagInfo or ($formatStr eq 'MIE' and $format & 0x04)) { + $raf->Read($value, $valLen) == $valLen or last; + if ($format & 0x04) { + if ($verbose) { + print $out "$$et{INDENT}\[Tag '${tag}' $valLen bytes compressed]\n"; + } + next unless HasZlib($et, 'decode'); + my $stat; + my $inflate = Compress::Zlib::inflateInit(); + $inflate and ($value, $stat) = $inflate->inflate($value); + unless ($inflate and $stat == Compress::Zlib::Z_STREAM_END()) { + $et->Warn("Error inflating $tag"); + next; + } + $valLen = length $value; + $wasCompressed = 1; + } + } + + # process this tag + if ($formatStr eq 'MIE') { + # process MIE directory + my ($subTablePtr, $dirName); + if ($tagInfo and $$tagInfo{SubDirectory}) { + $dirName = $tagInfo->{SubDirectory}->{DirName}; + my $subTable = $tagInfo->{SubDirectory}->{TagTable}; + $subTablePtr = $subTable ? GetTagTable($subTable) : $tagTablePtr; + } else { + $subTablePtr = GetTagTable('Image::ExifTool::MIE::Unknown'); + } + if ($verbose) { + my $order = ', byte order ' . GetByteOrder(); + $et->VerboseInfo($tag, $tagInfo, Size => $valLen, Extra => $order); + } + my %subdirInfo = ( + DirName => $dirName || $tag, + RAF => $raf, + Parent => $$dirInfo{DirName}, + WasCompressed => $wasCompressed, + ); + # read from uncompressed data instead if necessary + $subdirInfo{RAF} = new File::RandomAccess(\$value) if $valLen; + + my $oldOrder = GetByteOrder(); + SetByteOrder($format & 0x08 ? 'II' : 'MM'); + $msg = ProcessMIEGroup($et, \%subdirInfo, $subTablePtr); + SetByteOrder($oldOrder); + $$et{SET_GROUP1} = $grp1; # restore this group1 name + last if $msg; + } else { + # process MIE data format types + if ($tagInfo) { + my $rational; + # extract tag value + my $val = ReadMIEValue(\$value, 0, $formatStr, undef, $valLen, \$rational); + unless (defined $val) { + $et->Warn("Error reading $tag value"); + $val = '<err>'; + } + # save type or mime type + $mime = $val if $tag eq '0Type' or $tag eq '2MIME'; + if ($verbose) { + my $count; + my $s = Image::ExifTool::FormatSize($formatStr); + if ($s and $formatStr !~ /^(utf|string|undef)/) { + $count = $valLen / $s; + } + $et->VerboseInfo($lastTag, $tagInfo, + DataPt => \$value, + DataPos => $wasCompressed ? undef : $raf->Tell() - $valLen, + Size => $valLen, + Format => $formatStr, + Value => $val, + Count => $count, + ); + } + if ($$tagInfo{SubDirectory}) { + my $subTablePtr = GetTagTable($tagInfo->{SubDirectory}->{TagTable}); + my %subdirInfo = ( + DirName => $$tagInfo{Name}, + DataPt => \$value, + DataLen => $valLen, + DirStart=> 0, + DirLen => $valLen, + Parent => $$dirInfo{DirName}, + WasCompressed => $wasCompressed, + ); + # set DataPos and Base for uncompressed information only + unless ($wasCompressed) { + $subdirInfo{DataPos} = 0; # (relative to Base) + $subdirInfo{Base} = $raf->Tell() - $valLen; + } + # reset PROCESSED lookup for each MIE directory + # (there is no possibility of double-processing a MIE directory) + $$et{PROCESSED} = { }; + my $processProc = $tagInfo->{SubDirectory}->{ProcessProc}; + delete $$et{SET_GROUP1}; + delete $$et{NO_LIST}; + $et->ProcessDirectory(\%subdirInfo, $subTablePtr, $processProc); + $$et{SET_GROUP1} = $grp1; + $$et{NO_LIST} = 1; + } else { + # convert to specified character set if necessary + if ($notUTF8 and $formatStr =~ /^(utf|string)/) { + $val = $et->Decode($val, 'UTF8'); + } + if ($formatStr =~ /_list$/) { + # split list value into separate strings + my @vals = split "\0", $val; + $val = \@vals; + } + if (defined $units) { + $val = "@$val" if ref $val; # convert string list to number list + # add units to value if specified + $val .= "($units)" if defined $units; + } + my $key = $et->FoundTag($tagInfo, $val); + $$et{RATIONAL}{$key} = $rational if defined $rational and defined $key; + } + } else { + # skip over unknown information or free bytes + $raf->Seek($valLen, 1) or $msg = 'Seek error', last; + $verbose and $et->VerboseInfo($tag, undef, Size => $valLen); + } + } + } + # modify MIME type if necessary + $mime and not $$dirInfo{Parent} and $et->ModifyMimeType($mime); + + $ok or $msg or $msg = 'Unexpected end of file'; + $verbose and $$et{INDENT} = $oldIndent; + return $msg; +} + +#------------------------------------------------------------------------------ +# Read/write a MIE file +# Inputs: 0) ExifTool object reference, 1) DirInfo reference +# Returns: 1 on success, 0 if this wasn't a valid MIE file, or -1 on write error +# - process as a trailer if "Trailer" flag set in dirInfo +sub ProcessMIE($$) +{ + my ($et, $dirInfo) = @_; + return 1 unless defined $et; + my $raf = $$dirInfo{RAF}; + my $outfile = $$dirInfo{OutFile}; + my ($buff, $err, $msg, $pos, $end, $isCreating); + my $numDocs = 0; +# +# process as a trailer (from end of file) if specified +# + if ($$dirInfo{Trailer}) { + my $offset = $$dirInfo{Offset} || 0; # offset from end of file + $raf->Seek(-10 - $offset, 2) or return 0; + for (;;) { + # read and validate last 10 bytes + $raf->Read($buff, 10) == 10 or last; + last unless $buff =~ /~\0\0\x06.{4}(\x10|\x18)(\x04)$/s or + $buff =~ /(\x10|\x18)(\x08)$/s; + SetByteOrder($1 eq "\x10" ? 'MM' : 'II'); + my $len = ($2 eq "\x04") ? Get32u(\$buff, 4) : Get64u(\$buff, 0); + my $curPos = $raf->Tell() or last; + last if $len < 12 or $len > $curPos; + # validate element header if 8-byte offset was used + if ($2 eq "\x08") { + last if $len < 14; + $raf->Seek($curPos - 14, 0) and $raf->Read($buff, 4) or last; + last unless $buff eq "~\0\0\x0a"; + } + # looks like a good group, so remember start position + $pos = $curPos - $len; + $end = $curPos unless $end; + # seek to 10 bytes from end of previous group + $raf->Seek($pos - 10, 0) or last; + } + # seek to start of first MIE group + return 0 unless defined $pos and $raf->Seek($pos, 0); + # update DataPos and DirLen for ProcessTrailers() + $$dirInfo{DataPos} = $pos; + $$dirInfo{DirLen} = $end - $pos; + if ($outfile and $$et{DEL_GROUP}{MIE}) { + # delete the trailer + $et->VPrint(0," Deleting MIE trailer\n"); + ++$$et{CHANGED}; + return 1; + } elsif ($et->Options('Verbose') or $$et{HTML_DUMP}) { + $et->DumpTrailer($dirInfo); + } + } +# +# loop through all documents in MIE file +# + for (;;) { + # look for "0MIE" group element + my $num = $raf->Read($buff, 8); + if ($num == 8) { + # verify file identifier + if ($buff =~ /^~(\x10|\x18)\x04(.)0MIE/s) { + SetByteOrder($1 eq "\x10" ? 'MM' : 'II'); + my $len = ord($2); + # skip extended DataLength if it exists + if ($len > 252 and not $raf->Seek(1 << (256 - $len), 1)) { + $msg = 'Seek error'; + last; + } + } else { + return 0 unless $numDocs; # not a MIE file + if ($buff =~ /^~/) { + $msg = 'Non-standard file-level MIE element'; + } else { + $msg = 'Invalid MIE file-level data'; + } + } + } elsif ($numDocs) { + last unless $num; # OK, all done with file + $msg = 'Truncated MIE element header'; + } else { + return 0 if $num or not $outfile; + # we have the ability to create a MIE file from scratch + $buff = ''; # start from nothing + # set byte order according to preferences + $et->SetPreferredByteOrder(); + $isCreating = 1; + } + if ($msg) { + last if $$dirInfo{Trailer}; # allow other trailers after MIE + if ($outfile) { + $et->Error($msg); + } else { + $et->Warn($msg); + } + last; + } + # this is a new MIE document -- increment document count + unless ($numDocs) { + # this is a valid MIE file (unless a trailer on another file) + $et->SetFileType(); + $$et{NO_LIST} = 1; # handle lists ourself + $$et{MIE_COUNT} = { }; + undef $hasZlib; + } + ++$numDocs; + + # process the MIE groups recursively, beginning with the main MIE group + my $tagTablePtr = GetTagTable('Image::ExifTool::MIE::Main'); + + my %subdirInfo = ( + DirName => 'MIE', + RAF => $raf, + OutFile => $outfile, + # don't define Parent so WriteMIEGroup() writes extended terminator + ); + if ($outfile) { + # generate lookup for MIE format codes if not done already + unless (%mieCode) { + foreach (keys %mieFormat) { + $mieCode{$mieFormat{$_}} = $_; + } + } + # update %mieMap with user-defined MIE groups + UpdateMieMap() unless $doneMieMap; + # initialize write directories, with MIE tags taking priority + # (note that this may re-initialize directories when writing trailer + # to another type of image, but this is OK because we are done writing + # the other format by the time we start writing the trailer) + $et->InitWriteDirs(\%mieMap, 'MIE'); + $subdirInfo{ToWrite} = '~' . MIEGroupFormat(1) . "\x04\xfe0MIE\0\0\0\0"; + $msg = WriteMIEGroup($et, \%subdirInfo, $tagTablePtr); + if ($msg) { + $et->Error($msg); + $err = 1; + last; + } elsif (defined $msg and $isCreating) { + last; + } + } else { + $msg = ProcessMIEGroup($et, \%subdirInfo, $tagTablePtr); + if ($msg) { + $et->Warn($msg); + last; + } + } + } + delete $$et{NO_LIST}; + delete $$et{MIE_COUNT}; + delete $$et{SET_GROUP1}; + return $err ? -1 : 1; +} + +1; # end + +__END__ + +=head1 NAME + +Image::ExifTool::MIE - Read/write MIE meta information + +=head1 SYNOPSIS + +This module is used by Image::ExifTool + +=head1 DESCRIPTION + +This module contains routines required by Image::ExifTool to read and write +information in MIE files. + +=head1 WHAT IS MIE? + +MIE stands for "Meta Information Encapsulation". The MIE format is an +extensible, dedicated meta information format which supports storage of +binary as well as textual meta information. MIE can be used to encapsulate +meta information from many sources and bundle it together with any type of +file. + +=head2 Features + +Below is very subjective score card comparing the features of a number of +common file and meta information formats, and comparing them to MIE. The +following features are rated for each format with a score of 0 to 10: + + 1) Extensible (can incorporate user-defined information). + 2) Meaningful tag ID's (hint to meaning of unknown information). + 3) Sequential read/write ability (streamable). + 4) Hierarchical information structure. + 5) Easy to implement reader/writer/editor. + 6) Order of information well defined. + 7) Large data lengths supported: >64kB (+5) and >4GB (+5). + 8) Localized text strings. + 9) Multiple documents in a single file. + 10) Compact format doesn't squander disk space or bandwidth. + 11) Compressed meta information supported. + 12) Relocatable data elements (ie. no fixed offsets). + 13) Binary meta information (+7) with variable byte order (+3). + 14) Mandatory tags not required (an unnecessary complication). + 15) Append information to end of file without editing. + + Feature number Total + Format 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 Score + ------ --------------------------------------------- ----- + MIE 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 150 + PDF 10 10 0 10 0 0 10 0 10 10 10 0 7 10 10 97 + PNG 10 10 10 0 8 0 5 10 0 10 10 10 0 10 0 93 + XMP 10 10 10 10 2 0 10 10 10 0 0 10 0 10 0 92 + AIFF 0 5 10 10 10 0 5 0 0 10 0 10 7 10 0 77 + RIFF 0 5 10 10 10 0 5 0 0 10 0 10 7 10 0 77 + JPEG 10 0 10 0 10 0 0 0 0 10 0 10 7 10 0 67 + EPS 10 10 10 0 0 0 10 0 10 0 0 5 0 10 0 65 + CIFF 0 0 0 10 10 0 5 0 0 10 0 10 10 10 0 65 + TIFF 0 0 0 10 5 10 5 0 10 10 0 0 10 0 0 60 + EXIF 0 0 0 10 5 10 0 0 0 10 0 0 10 0 0 45 + IPTC 0 0 10 0 8 0 0 0 0 10 0 10 7 0 0 45 + +By design, MIE ranks highest by a significant margin. Other formats with +reasonable scores are PDF, PNG and XMP, but each has significant weak +points. What may be surprising is that TIFF, EXIF and IPTC rank so low. + +As well as scoring high in all these features, the MIE format has the unique +ability to encapsulate any other type of file, and provides a non-invasive +method of adding meta information to a file. The meta information is +logically separated from the original file data, which is extremely +important because meta information is routinely lost when files are edited. + +Also, the MIE format supports multiple files by simple concatenation, +enabling all kinds of wonderful features such as linear databases, edit +histories or non-intrusive file updates. This ability can also be leveraged +to allow MIE-format trailers to be added to some other file types. + +=head1 MIE 1.1 FORMAT SPECIFICATION (2007-01-21) + +=head2 File Structure + +A MIE file consists of a series of MIE elements. A MIE element may contain +either data or a group of MIE elements, providing a hierarchical format for +storing data. Each MIE element is identified by a human-readable tag name, +and may store data from zero to 2^64-1 bytes in length. + +=head2 File Signature + +The first element in the MIE file must be an uncompressed MIE group element +with a tag name of "0MIE". This restriction allows the first 8 bytes of a +MIE file to be used to identify a MIE format file. The following table +lists the two possible initial byte sequences for a MIE-format file (the +first for big-endian, and the second for little-endian byte ordering): + + Byte Number: 0 1 2 3 4 5 6 7 + + C Characters: ~ \x10 \x04 ? 0 M I E + or ~ \x18 \x04 ? 0 M I E + + Hexadecimal: 7e 10 04 ? 30 4d 49 45 + or 7e 18 04 ? 30 4d 49 45 + + Decimal: 126 16 4 ? 48 77 73 69 + or 126 24 4 ? 48 77 73 69 + +Note that byte 1 may have one of the two possible values (0x10 or 0x18), and +byte 3 may have any value (0x00 to 0xff). + +=head2 Element Structure + + 1 byte SyncByte = 0x7e (decimal 126, character '~') + 1 byte FormatCode (see below) + 1 byte TagLength (T) + 1 byte DataLength (gives D if DataLength < 253) + T bytes TagName (T given by TagLength) + 2 bytes DataLength2 [exists only if DataLength == 255 (0xff)] + 4 bytes DataLength4 [exists only if DataLength == 254 (0xfe)] + 8 bytes DataLength8 [exists only if DataLength == 253 (0xfd)] + D bytes DataBlock (D given by DataLength) + +The minimum element length is 4 bytes (for a group terminator). The maximum +DataBlock size is 2^64-1 bytes. TagLength and DataLength are unsigned +integers, and the byte ordering for multi-byte DataLength fields is +specified by the containing MIE group element. The SyncByte is byte +aligned, so no padding is added to align on an N-byte boundary. + +=head3 FormatCode + +The format code is a bitmask that defines the format of the data: + + 7654 3210 + ++++ ---- FormatType + ---- +--- TypeModifier + ---- -+-- Compressed + ---- --++ FormatSize + +=over 4 + +=item FormatType (bitmask 0xf0): + + 0x00 - other (or unknown) data + 0x10 - MIE group + 0x20 - text string + 0x30 - list of null-separated text strings + 0x40 - integer + 0x50 - rational + 0x60 - fixed point + 0x70 - floating point + 0x80 - free space + +=item TypeModifier (bitmask 0x08): + +Modifies the meaning of certain FormatTypes (0x00-0x60): + + 0x08 - other data sensitive to MIE group byte order + 0x18 - MIE group with little-endian byte ordering + 0x28 - UTF encoded text string + 0x38 - UTF encoded text string list + 0x48 - signed integer + 0x58 - signed rational (denominator is always unsigned) + 0x68 - signed fixed-point + +=item Compressed (bitmask 0x04): + +If this bit is set, the data block is compressed using Zlib deflate. An +entire MIE group may be compressed, with the exception of file-level groups. + +=item FormatSize (bitmask 0x03): + +Gives the byte size of each data element: + + 0x00 - 8 bits (1 byte) + 0x01 - 16 bits (2 bytes) + 0x02 - 32 bits (4 bytes) + 0x03 - 64 bits (8 bytes) + +The number of bytes in a single value for this format is given by +2**FormatSize (or 1 << FormatSize). The number of values is the data length +divided by this number of bytes. It is an error if the data length is not +an even multiple of the format size in bytes. + +=back + +The following is a list of all currently defined MIE FormatCode values for +uncompressed data (add 0x04 to each value for compressed data): + + 0x00 - other data (insensitive to MIE group byte order) (1) + 0x01 - other 16-bit data (may be byte swapped) + 0x02 - other 32-bit data (may be byte swapped) + 0x03 - other 64-bit data (may be byte swapped) + 0x08 - other data (sensitive to MIE group byte order) (1) + 0x10 - MIE group with big-endian values (1) + 0x18 - MIE group with little-endian values (1) + 0x20 - ASCII (ISO 8859-1) string (2,3) + 0x28 - UTF-8 string (2,3,4) + 0x29 - UTF-16 string (2,3,4) + 0x2a - UTF-32 string (2,3,4) + 0x30 - ASCII (ISO 8859-1) string list (3,5) + 0x38 - UTF-8 string list (3,4,5) + 0x39 - UTF-16 string list (3,4,5) + 0x3a - UTF-32 string list (3,4,5) + 0x40 - unsigned 8-bit integer + 0x41 - unsigned 16-bit integer + 0x42 - unsigned 32-bit integer + 0x43 - unsigned 64-bit integer (6) + 0x48 - signed 8-bit integer + 0x49 - signed 16-bit integer + 0x4a - signed 32-bit integer + 0x4b - signed 64-bit integer (6) + 0x52 - unsigned 32-bit rational (16-bit numerator then denominator) (7) + 0x53 - unsigned 64-bit rational (32-bit numerator then denominator) (7) + 0x5a - signed 32-bit rational (denominator is unsigned) (7) + 0x5b - signed 64-bit rational (denominator is unsigned) (7) + 0x61 - unsigned 16-bit fixed-point (high 8 bits is integer part) (8) + 0x62 - unsigned 32-bit fixed-point (high 16 bits is integer part) (8) + 0x69 - signed 16-bit fixed-point (high 8 bits is signed integer) (8) + 0x6a - signed 32-bit fixed-point (high 16 bits is signed integer) (8) + 0x72 - 32-bit IEEE float (not recommended for portability reasons) + 0x73 - 64-bit IEEE double (not recommended for portability reasons) (6) + 0x80 - free space (value data does not contain useful information) + +Notes: + +=over 4 + +=item 1. + +The byte ordering specified by the MIE group TypeModifier applies to the MIE +group element as well as all elements within the group. Data for all +FormatCodes except 0x08 (other data, sensitive to byte order) may be +transferred between MIE groups with different byte order by byte swapping +the uncompressed data according to the specified data format. The following +list illustrates the byte-swapping pattern, based on FormatSize, for all +format types except rational (FormatType 0x50). + + FormatSize Change in Byte Sequence + -------------- ----------------------------------- + 0x00 (8 bits) 0 1 2 3 4 5 6 7 --> 0 1 2 3 4 5 6 7 (no change) + 0x01 (16 bits) 0 1 2 3 4 5 6 7 --> 1 0 3 2 5 4 7 6 + 0x02 (32 bits) 0 1 2 3 4 5 6 7 --> 3 2 1 0 7 6 5 4 + 0x03 (64 bits) 0 1 2 3 4 5 6 7 --> 7 6 5 4 3 2 1 0 + +Rational values consist of two integers, so they are swapped as the next +lower FormatSize. For example, a 32-bit rational (FormatSize 0x02, and +FormatCode 0x52 or 0x5a) is swapped as two 16-bit values (ie. as if it had +FormatSize 0x01). + +=item 2. + +The TagName of a string element may have an 6-character suffix to indicate a +specific locale. (eg. "Title-en_US", or "Keywords-de_DE"). + +=item 3. + +Text strings are not normally null terminated, however they may be padded +with one or more null characters to the end of the data block to allow +strings to be edited within fixed-length data blocks. Newlines in the text +are indicated by a single LF (0x0a) character. + +=item 4. + +UTF strings must not begin with a byte order mark (BOM) since the byte order +and byte size are specified by the MIE format. If a BOM is found, it should +be treated as a zero-width non-breaking space. + +=item 5. + +A list of text strings separated by null characters. These lists must not +be null padded or null terminated, since this would be interpreted as +additional zero-length strings. For ASCII and UTF-8 strings, the null +character is a single zero (0x00) byte. For UTF-16 or UTF-32 strings, the +null character is 2 or 4 zero bytes respectively. + +=item 6. + +64-bit integers and doubles are subject to the specified byte ordering for +both 32-bit words and bytes within these words. For instance, the high +order byte is always the first byte if big-endian, and the eighth byte if +little-endian. This means that some swapping is always necessary for these +values on systems where the byte order differs from the word order (eg. some +ARM systems), regardless of the endian-ness of the stored values. + +=item 7. + +Rational values are treated as two separate integers. The numerator always +comes first regardless of the byte ordering. In a signed rational value, +only the numerator is signed. The denominator of all rational values is +unsigned (eg. a signed 64-bit rational of 0x80000000/0x80000000 evaluates to +-1, not +1). + +=item 8. + +32-bit fixed point values are converted to floating point by treating them +as an integer and dividing by an appropriate value. eg) + + 16-bit fixed value = 16-bit integer value / 256.0 + 32-bit fixed value = 32-bit integer value / 65536.0 + +=back + +=head3 TagLength + +Gives the length of the TagName string. Any value between 0 and 255 is +valid, but the TagLength of 0 is valid only for the MIE group terminator. + +=head3 DataLength + +DataLength is an unsigned byte that gives the number of bytes in the data +block. A value between 0 and 252 gives the data length directly, and +numbers from 253 to 255 are reserved for extended DataLength codes. Codes +of 255, 254 and 253 indicate that the element contains an additional 2, 4 or +8 byte unsigned integer representing the data length. + + 0-252 - length of data block + 255 (0xff) - use DataLength2 + 254 (0xfe) - use DataLength4 + 253 (0xfd) - use DataLength8 + +A DataLength of zero is valid for any element except a compressed MIE group. +A zero DataLength for an uncompressed MIE group indicates that the group +length is unknown. For other elements, a zero length indicates there is no +associated data. A terminator element must have a DataLength of 0, 6 or 10, +and may not use an extended DataLength. + +=head3 TagName + +The TagName string is 0 to 255 bytes long, and is composed of the ASCII +characters A-Z, a-z, 0-9 and underline ('_'). Also, a dash ('-') is used to +separate the language/country code in the TagName of a localized text +string, and a units string (possibly containing other ASCII characters) may +be appear in brackets at the end of the TagName. The TagName string is NOT +null terminated. A MIE element with a tag string of zero length is reserved +for the group terminator. + +MIE elements are sorted alphabetically by TagName within each group. +Multiple elements with the same TagName are allowed, even within the same +group. + +TagNames should be meaningful. Case is significant. Words should be +lowercase with an uppercase first character, and acronyms should be all +upper case. The underline ("_") is provided to allow separation of two +acronyms or two numbers, but it shouldn't be used unless necessary. No +separation is necessary between an acronym and a word (eg. "ISOSetting"). + +All TagNames should start with an uppercase letter. An exception to this +rule allows tags to begin with a digit (0-9) if they must come before other +tags in the sort order, or a lowercase letter (a-z) if they must come after. +For instance, the '0Type' element begins with a digit so it comes before, +and the 'data' element begins with a lowercase letter so that it comes after +meta information tags in the main "0MIE" group. + +Tag names for localized text strings have an 6-character suffix with the +following format: The first character is a dash ('-'), followed by a +2-character lower case ISO 639-1 language code, then an underline ('_'), and +ending with a 2-character upper case ISO 3166-1 alpha 2 country code. (eg. +"-en_US", "-en_GB", "-de_DE" or "-fr_FR". Note that "GB", and not "UK" is +the code for Great Britain, although "UK" should be recognized for +compatibility reasons.) The suffix is included when sorting the tags +alphabetically, so the default locale (with no tag-name suffix) always comes +first. If the country is unknown or not applicable, a country code of "XX" +should be used. + +Tags with numerical values may allow units of measurement to be specified. +The units string is stored in brackets at the end of the tag name, and is +composed of zero or more ASCII characters in the range 0x21 to 0x7d, +excluding the bracket characters 0x28 and 0x29. (eg. "Resolution(/cm)" or +"SpecificHeat(J/kg.K)".) See L<Image::ExifTool::MIEUnits> for details. Unit +strings are not localized, and may not be used in combination with localized +text strings. + +Sets of tags which would require a common prefix should be added in a +separate MIE group instead of adding the prefix to all tag names. For +example, instead of these TagName's: + + ExternalFlashType + ExternalFlashSerialNumber + ExternalFlashFired + +one would instead designate a separate "ExternalFlash" MIE group to contain +the following elements: + + Type + SerialNumber + Fired + +=head3 DataLength2/4/8 + +These extended DataLength fields exist only if DataLength is 255, 254 or +253, and are respectively 2, 4 or 8 byte unsigned integers giving the data +block length. One of these values must be used if the data block is larger +than 252 bytes, but they may be used if desired for smaller blocks too +(although this may add a few unnecessary bytes to the MIE element). + +=head3 DataBlock + +The data value for the MIE element. The format of the data is given by the +FormatCode. For MIE group elements, the data includes all contained +elements and the group terminator. + +=head2 MIE groups + +All MIE data elements must be contained within a group. A group begins with +a MIE group element, and ends with a group terminator. Groups may be nested +in a hierarchy to arbitrary depth. + +A MIE group element is identified by a format code of 0x10 (big endian byte +ordering) or 0x18 (little endian). The group terminator is distinguished by +a zero TagLength (it is the only element allowed to have a zero TagLength), +and has a FormatCode of 0x00. + +The MIE group element is permitted to have a zero DataLength only if the +data is uncompressed. This special value indicates that the group length is +unknown (otherwise the minimum value for DataLength is 4, corresponding the +the minimum group size which includes a terminator of at least 4 bytes). If +DataLength is zero, all elements in the group must be parsed until the group +terminator is found. If non-zero, DataLength includes the length of all +elements contained within the group, including the group terminator. Use of +a non-zero DataLength is encouraged because it allows readers quickly skip +over entire MIE groups. For compressed groups DataLength must be non-zero, +and is the length of the compressed group data (which includes the +compressed group terminator). + +=head3 Group Terminator + +The group terminator has a FormatCode and TagLength of zero. The terminator +DataLength must be 0, 6 or 10 bytes, and extended DataLength codes may not +be used. With a zero DataLength, the byte sequence for a terminator is "7e +00 00 00" (hex). With a DataLength of 6 or 10 bytes, the terminator data +block contains information about the length and byte ordering of the +preceding group. This additional information is recommended for file-level +groups, and is used in multi-document MIE files and MIE trailers to allow +the file to be scanned backwards from the end. (This may also allow some +documents to be recovered if part of the file is corrupted.) The structure +of this optional terminator data block is as follows: + + 4 or 8 bytes GroupLength (unsigned integer) + 1 byte ByteOrder (0x10 or 0x18, same as MIE group) + 1 byte GroupLengthSize (0x04 or 0x08) + +The ByteOrder and GroupLengthSize values give the byte ordering and size of +the GroupLength integer. The GroupLength value is the total length of the +entire MIE group ending with this terminator, including the opening MIE +group element and the terminator itself. + +=head3 File-level MIE groups + +File-level MIE groups may NOT be compressed. + +All elements in a MIE file are contained within a special group with a +TagName of "0MIE". The purpose of the "OMIE" group is to provide a unique +signature at the start of the file, and to encapsulate information allowing +files to be easily combined. The "0MIE" group must be terminated like any +other group, but it is recommended that the terminator of a file-level group +include the optional data block (defined above) to provide information about +the group length and byte order. + +It is valid to have more than one "0MIE" group at the file level, allowing +multiple documents in a single MIE file. Furthermore, the MIE structure +enables multi-document files to be generated by simply concatenating two or +more MIE files. + +=head2 Scanning Backwards through a MIE File + +The steps below give an algorithm to quickly locate the last document in a +MIE file: + +=over 4 + +=item 1. + +Read the last 10 bytes of the file. (Note that a valid MIE file may be as +short as 12 bytes long, but a file this length contains only an an empty MIE +group.) + +=item 2. + +If the last byte of the file is zero, then it is not possible to scan +backward through the file, so the file must be scanned from the beginning. +Otherwise, proceed to the next step. + +=item 3. + +If the last byte is 4 or 8, the terminator contains information about the +byte ordering and length of the group. Otherwise, stop here because this +isn't a valid MIE file. + +=item 4. + +The next-to-last byte must be either 0x10 indicating big-endian byte +ordering or 0x18 for little-endian ordering, otherwise this isn't a valid +MIE file. + +=item 5. + +The value of the preceding 4 or 8 bytes gives the length of the complete +file-level MIE group (GroupLength). This length includes both the leading +MIE group element and the terminator element itself. The value is an +unsigned integer with a byte length given in step 3), and a byte order from +step 4). From the current file position (at the end of the data read in +step 1), seek backward by this number of bytes to find the start of the MIE +group element for this document. + +=back + +This algorithm may be repeated again beginning at this point in the file to +locate the next-to-last document, etc. + +The table below lists all 5 valid patterns for the last 14 bytes of a +file-level MIE group, with all numbers in hex. The comments indicate the +length and byte ordering of GroupLength (xx) if available: + + ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? 7e 00 00 00 - (no GroupLength) + ?? ?? ?? ?? 7e 00 00 06 xx xx xx xx 10 04 - 4 bytes, big endian + ?? ?? ?? ?? 7e 00 00 06 xx xx xx xx 18 04 - 4 bytes, little endian + 7e 00 00 0a xx xx xx xx xx xx xx xx 10 08 - 8 bytes, big endian + 7e 00 00 0a xx xx xx xx xx xx xx xx 18 08 - 8 bytes, little endian + +=head2 Trailer Signature + +The MIE format may be used for trailer information appended to other types +of files. When this is done, a signature must appear at the end of the main +MIE group to uniquely identify the MIE format trailer. To achieve this, a +"zmie" trailer signature is written as the last element in the main "0MIE" +group. This element has a FormatCode of 0, a TagLength of 4, a DataLength +of 0, and a TagName of "zmie". With this signature, the hex byte sequence +"7e 00 04 00 7a 6d 69 65" appears immediately before the final group +terminator, and the last 22 bytes of the trailer correspond to one of the +following 4 patterns (where the trailer length is given by "xx", as above): + + ?? ?? ?? ?? 7e 00 04 00 7a 6d 69 65 7e 00 00 06 xx xx xx xx 10 04 + ?? ?? ?? ?? 7e 00 04 00 7a 6d 69 65 7e 00 00 06 xx xx xx xx 18 04 + 7e 00 04 00 7a 6d 69 65 7e 00 00 0a xx xx xx xx xx xx xx xx 10 08 + 7e 00 04 00 7a 6d 69 65 7e 00 00 0a xx xx xx xx xx xx xx xx 18 08 + +Note that the zero-DataLength terminator may not be used here because the +trailer length must be known for seeking backwards from the end of the file. + +Multiple trailers may be appended to the same file using this technique. + +=head2 MIE Data Values + +MIE data values for a given tag are usually not restricted to a specific +FormatCode. Any value may be represented in any appropriate format, +including numbers represented in string (ASCII or UTF) form. + +It is preferred that closely related values with the same format are written +to a single tag instead of using multiple tags. This improves localization +of like values and decreases MIE element overhead. For instance, instead of +separate ImageWidth and ImageHeight tags, a single ImageSize tag is defined. + +Tags which may take on a discrete set of values should have meaningful +values if possible. This improves the extensibility of the format and +allows a more reasonable interpretation of unrecognized values. + +=head3 Numerical Representation + +Integer and floating point numbers may be represented in binary or string +form. In string form, integers are a series of digits with an optional +leading sign (eg. "[+|-]DDDDDD"), and multiple values are separated by a +single space character (eg. "23 128 -32"). Floating point numbers are +similar but may also contain a decimal point and/or a signed exponent with a +leading 'e' character (eg. "[+|-]DD[.DDDDDD][e(+|-)EEE]"). The string "inf" +is used to represent infinity. One advantage of numerical strings is that +they can have an arbitrarily high precision because the possible number of +significant digits is virtually unlimited. + +Note that numerical values may have associated units of measurement which +are specified in the L</TagName> string. + +=head3 Date/Time Format + +All MIE dates are strings in the form "YYYY:mm:dd HH:MM:SS.ss+HH:MM". The +fractional seconds (".ss") are optional, and if included may contain any +number of significant digits (unlike all other fields which are a fixed +number of digits and must be padded with leading zeros if necessary). The +timezone ("+HH:MM" or "-HH:MM") is recommended but not required. If not +given, the local system timezone is assumed. + +=head2 MIME Type + +The basic MIME type for a MIE file is "application/x-mie", however the +specific MIME type depends on the type of subfile, and is obtained by adding +"x-mie-" to the MIME type of the subfile. For example, with a subfile of +type "image/jpeg", the MIE file MIME type is "image/x-mie-jpeg". But note +that the "x-" is not duplicated if the subfile MIME type already starts with +"x-". So a subfile with MIME type "image/x-raw" is contained within a MIE +file of type "image/x-mie-raw", not "image/x-mie-x-raw". In the case of +multiple documents in a MIE file, the MIME type is taken from the first +document. Regardless of the subfile type, all MIE-format files should have +a filename extension of ".MIE". + +=head2 Levels of Support + +Basic MIE reader/writer applications may choose not to provide support for +some advanced features of the MIE format. Features which may not be +supported by all software are: + +=over 4 + +=item Compression + +Software not supporting compression must ignore compressed elements and +groups, but should be able to process the remaining information. + +=item Large data lengths + +Some software may limit the maximum size of a MIE group or element. +Historically, a limit of 2GB may be imposed by some systems. However, +8-byte data lengths should be supported by all applications provided the +value doesn't exceed the system limit. (eg. For systems with a 2GB limit, +8-byte data lengths should be supported if the upper 17 bits are all zero.) +If a data length above the system limit is encountered, it may be necessary +for the application to stop processing if it can not seek to the next +element in the file. + +=back + +=head1 EXAMPLES + +This section gives examples for working with MIE information using ExifTool. + +=head2 Encapsulating Information with Data in a MIE File + +The following command encapsulates any file recognized by ExifTool inside a +MIE file, and initializes MIE tags from information within the file: + + exiftool -o new.mie -tagsfromfile FILE '-mie:all<all' \ + '-subfilename<filename' '-subfiletype<filetype' \ + '-subfilemimetype<mimetype' '-subfiledata<=FILE' + +where C<FILE> is the name of the file. + +For unrecognized files, this command may be used: + + exiftool -o new.mie -subfilename=FILE -subfiletype=TYPE \ + -subfilemimetype=MIME '-subfiledata<=FILE' + +where C<TYPE> and C<MIME> represent the source file type and MIME type +respectively. + +=head2 Adding a MIE Trailer to a File + +The MIE format may also be used to store information in a trailer appended +to another type of file. Beware that trailers may not be compatible with +all file formats, but JPEG and TIFF are two formats where additional trailer +information doesn't create any problems for normal parsing of the file. +Also note that this technique has the disadvantage that trailer information +is commonly lost if the file is subsequently edited by other software. + +Creating a MIE trailer with ExifTool is a two-step process since ExifTool +can't currently be used to add a MIE trailer directly. The example below +illustrates the steps for adding a MIE trailer with a small preview image +(C<small.jpg>) to a destination JPEG image (C<dst.jpg>). + +Step 1) Create a MIE file with a TrailerSignature containing the desired +information: + + exiftool -o new.mie -trailersignature=1 -tagsfromfile small.jpg \ + '-previewimagetype<filetype' '-previewimagesize<imagesize' \ + '-previewimagename<filename' '-previewimage<=small.jpg' + +Step 2) Append the MIE information to another file. In Unix, this can be +done with the 'cat' command: + + cat new.mie >> dst.jpg + +Once added, ExifTool may be used to edit or delete a MIE trailer in a JPEG +or TIFF image. + +=head2 Multiple MIE Documents in a Single File + +The MIE specification allows multiple MIE documents (or trailers) to exist +in a single file. A file like this may be created by simply concatenating +MIE documents. ExifTool may be used to access information in a specific +document by adding a copy number to the MIE group name. For example: + + # write the Author tag in the second MIE document + exiftool -mie2:author=phil test.mie + + # delete the first MIE document from a file + exiftool -mie1:all= test.mie + +=head2 Units of Measurement + +Some MIE tags allow values to be specified in different units of +measurement. In the MIE file format these units are combined with the tag +name, but when using ExifTool they are specified in brackets after the +value: + + exiftool -mie:gpsaltitude='7500(ft)' test.mie + +If no units are provided, the default units are written. + +=head2 Localized Text + +Localized text values are accessed by adding a language/country code to the +tag name. For example: + + exiftool -comment-en_us='this is a comment' test.mie + +=head1 REVISIONS + + 2010-04-05 - Fixed "Format Size" Note 7 to give the correct number of bits + in the example rational value + 2007-01-21 - Specified LF character (0x0a) for text newline sequence + 2007-01-19 - Specified ISO 8859-1 character set for extended ASCII codes + 2007-01-01 - Improved wording of Step 5 for scanning backwards in MIE file + 2006-12-30 - Added EXAMPLES section and note about UTF BOM + 2006-12-20 - MIE 1.1: Changed meaning of TypeModifier bit (0x08) for + unknown data (FormatType 0x00), and documented byte swapping + 2006-12-14 - MIE 1.0: Added Data Values and Numerical Representations + sections, and added ability to specify units in tag names + 2006-11-09 - Added Levels of Support section + 2006-11-03 - Added Trailer Signature + 2005-11-18 - Original specification created + +=head1 AUTHOR + +Copyright 2003-2019, Phil Harvey (phil at owl.phy.queensu.ca) + +This library is free software; you can redistribute it and/or modify it +under the same terms as Perl itself. The MIE format itself is also +copyright Phil Harvey, and is covered by the same free-use license. + +=head1 REFERENCES + +=over 4 + +=item L<http://owl.phy.queensu.ca/~phil/exiftool/MIE1.1-20070121.pdf> + +=back + +=head1 SEE ALSO + +L<Image::ExifTool::TagNames/MIE Tags>, L<Image::ExifTool::MIEUnits>, +L<Image::ExifTool(3pm)|Image::ExifTool> + +=cut + diff --git a/lib/Image/ExifTool/MIEUnits.pod b/lib/Image/ExifTool/MIEUnits.pod new file mode 100644 index 0000000..81efefc --- /dev/null +++ b/lib/Image/ExifTool/MIEUnits.pod @@ -0,0 +1,377 @@ + +=head1 NAME + +Image::ExifTool::MIEUnits - MIE units documentation + +=head1 DESCRIPTION + +The MIE format allows units of measurement to be specified in brackets at +the end of a MIE tag name (eg. "Volume(m3)"). This document describes the +standard MIE units abbreviations. + +=head1 SYNTAX + +The units string may contain any ASCII characters in the range 0x21 ('!') to +0x7d ('}'), excepting the bracket characters (0x28 and 0x29). An empty +string is allowed, and indicates a dimensionless value. L<Standard +units|/STANDARD UNITS> should be used where possible. In the standard +units, an underline ('_') is used to indicate a subscript, and multiple +words may be separated with a hyphen ('-'). + +Exponents should be positive, and require no separator (eg. "m2" for square +meters). L<Prefixes|/PREFIXES> may be added to the standard units (eg. +"cm") except when the resulting name conflicts with another standard unit. + +Multiplication is indicated by '.', and division by '/'. Reciprocal units +(ie. the multiplicative inverse) are obtained through division rather than +the use of negative exponents (eg. "/in", not "in-1"). In MIE units, +multiplication has precedence over division, so everything to the right of a +'/' is in the denominator. (See L</EXAMPLES> for a few examples.) + +Below is a table summarizing the special characters used in MIE units +strings. + + . multiplication + / division (used for negative exponents) + - word separator + _ subscript + {} annotation + [] used to avoid name conflicts if necessary + 0-9 exponentiation + +=head1 STANDARD UNITS + + dimensionless + [G] Newtonian constant of gravitation (unclassified) + [g] standard acceleration of free fall (acceleration) + [h] Planck constant (action) + [k] Boltzmann constant (unclassified) + {cfu} colony forming units (number) + {rbc} red blood cell count (number) + {tbl} tablets (number) + {tot} particles total count (number) + % percent (fraction) + 10^N the number ten for arbitrary powers (number) + A Ampere (electric current) + a year (time) + a_g mean Gregorian year (time) + a_j mean Julian year (time) + a_t tropical year (time) + acr acre, U.S. (area) + acr_br acre, British (area) + Ao Angstrom (length) + APL-U APL unit (biologic activity of anticardiolipin IgA) + ar are (area) + arb-U arbitrary unit (arbitrary) + arcmin minute of arc (plane angle) + arcsec second of arc (plane angle) + atm standard atmosphere (pressure) + att technical atmosphere (pressure) + AU astronomic unit (length) + b barn (action area) + B bel (level) + B-kW bel kilowatt (power level) + B-mV bel millivolt (electric potential level) + B-SPL bel sound pressure (pressure level) + B-uV bel microvolt (electric potential level) + B-V bel volt (electric potential level) + B-W bel watt (power level) + bar bar (pressure) + bbl barrel (fluid volume) + Bd baud (signal transmission rate) + bdsk-U Bodansky unit (biologic activity of phosphatase) + beth-U Bethesda unit (biologic activity of factor VIII inhibitor) + bf board foot (volume) + Bi Biot (electric current) + bit bit (amount of information) + Bq Becquerel (radioactivity) + Btu British thermal unit (energy) + Btu_39 British thermal unit at 39 degF (energy) + Btu_59 British thermal unit at 59 degF (energy) + Btu_60 British thermal unit at 60 degF (energy) + Btu_IT international table British thermal unit (energy) + Btu_m mean British thermal unit (energy) + Btu_th thermochemical British thermal unit (energy) + bu bushel, U.S. (dry volume) + bu_br bushel, British (volume) + By byte (amount of information) + C Coulomb (electric charge) + c velocity of light (velocity) + cal calorie (energy) + Cal nutrition label Calories (energy) + cal_15 calorie at 15 degC (energy) + cal_20 calorie at 20 degC (energy) + cal_IT international table calorie (energy) + cal_m mean calorie (energy) + cal_th thermochemical calorie (energy) + car_Au carat of gold alloys (mass fraction) + car_m metric carat (mass) + cd candela (luminous intensity) + Cel degree Celsius (temperature) + Ch Charriere (gauge of catheters) + ch Gunter's chain, U.S. (length) + ch_br Gunter's chain, British (length) + Ci Curie (radioactivity) + cicero cicero (length) + circ circle (plane angle) + cml circular mil, international (area) + cr cord, international (volume) + crd_us cord, U.S. (fluid volume) + cup_us cup (volume) + d day (time) + deg degree (plane angle) + deg{mag} degree from magnetic north (plane angle) + degF degree Fahrenheit (temperature) + didot didot (length) + diop diopter (refraction of a lens) + dpt dry pint, U.S. (dry volume) + dqt dry quart, U.S. (dry volume) + dr dram (mass) + dr_ap dram, apothecary (mass) + drp drop (volume) + dye-U Dye unit (biologic activity of amylase) + dyn dyne (force) + e elementary charge (electric charge) + eps_0 permittivity of vacuum (electric permittivity) + eq equivalents (amount of substance) + erg erg (energy) + eV electronvolt (energy) + F Farad (electric capacitance) + fdr fluid dram, U.S. (fluid volume) + fdr_br fluid dram, British (volume) + foz fluid ounce, U.S. (fluid volume) + foz_br fluid ounce, British (volume) + ft foot, international (length) + ft_br foot, British (length) + ft_us foot, U.S. (length) + fth fathom, international (length) + fth_br fathom, British (length) + fth_us fathom, U.S. (length) + fur furlong, U.S. (length) + G Gauss (magnetic flux density) + g gram (mass) + g.m/{H-B} gram meter per heartbeat (prop. to ventricular stroke work) + g% gram percent (mass fraction) + Gal Gal (acceleration) + gal gallon, U.S. (fluid volume) + gal_br gallon, British (volume) + gal_wi historical winchester gallon (dry volume) + Gb Gilbert (magnetic tension) + gf gram-force (force) + gil gill, U.S. (fluid volume) + gil_br gill, British (volume) + gon gon (plane angle) + GPL-U GPL unit (biologic activity of anticardiolipin IgG) + gr grain (mass) + Gy Gray (energy dose) + H Henry (inductance) + h hour (time) + hd hand, international (height of horses) + hnsf-U Hounsfield unit (x-ray attenuation) + HP horsepower (power) + hp_C homeopathic potency of centesimal series (homeopathic potency) + hp_X homeopathic potency of decimal series (homeopathic potency) + HPF high power field (view area in microscope) + Hz Herz (frequency) + in inch, international (length) + in_br inch, British (length) + in_us inch, U.S. (length) + in-H2O inch of water column (pressure) + in-Hg inch of mercury column (pressure) + iU international unit (arbitrary) + J Joule (energy) + K Kelvin (temperature) + ka-U King-Armstrong unit (biologic activity of phosphatase) + kat katal (catalytic activity) + kg{wet-tis} kilogram of wet tissue (mass) + kn knot, international (velocity) + kn_br knot, British (velocity) + knk-U Kunkel unit (arbitrary biologic activity) + Ky Kayser (lineic number) + l liter (volume) + L liter (volume) + lb pound (mass) + lb_ap pound, apothecary (mass) + lb_tr pound, troy (mass) + lbf pound force (force) + lcwt long hunderdweight (mass) + ligne ligne (length) + lk link for Gunter's chain, U.S. (length) + lk_br link for Gunter's chain, British (length) + lm lumen (luminous flux) + Lmb Lambert (brightness) + lne line (length) + LPF low power field (view area in microscope) + lton long ton (mass) + lx lux (illuminance) + ly light-year (length) + m meter (length) + m_e electron mass (mass) + m_p proton mass (mass) + m-H2O meter of water column (pressure) + m-Hg meter of mercury column (pressure) + mclg-U Mac Lagan unit (arbitrary biologic activity) + mesh mesh, international (lineic number) + MET metabolic equivalent (metabolic cost of physical activity) + mg{creat} milligram of creatinine (mass) + mho mho (electric conductance) + mi mile, international (statute mile) (length) + mi_br mile, British (length) + mi_us mile, U.S. (length) + mil mil, international (length) + mil_us mil, U.S. (length) + min minute (time) + min_br minim, British (volume) + min_us minim, U.S. (fluid volume) + mo month (time) + mo_g mean Gregorian month (time) + mo_j mean Julian month (time) + mo_s synodal month (time) + mol mole (amount of substance) + MPL-U MPL unit (biologic activity of anticardiolipin IgM) + mu_0 permeability of vacuum (magnetic permeability) + Mx Maxwell (flux of magnetic induction) + N Newton (force) + nmi nautical mile, international (length) + nmi_br nautical mile, British (length) + Np neper (level) + Oe Oersted (magnetic field intensity) + Ohm Ohm (electric resistance) + osm osmole of dissolved particles (amount of substance) + oz ounce (mass) + oz_ap ounce, apothecary (mass) + oz_tr ounce, troy (mass) + P Poise (dynamic viscosity) + Pa Pascal (pressure) + pc parsec (length) + pc_br pace (length) + pca pica (length) + pca_pr Printer's pica (length) + pH pH (acidity) + ph phot (illuminance) + pi the number pi (number) + pied pied (length) + pk peck, U.S. (dry volume) + pk_br peck, British (volume) + pnt point (length) + pnt_pr Printer's point (length) + pouce pouce (length) + ppb parts per billion (fraction) + ppm parts per million (fraction) + ppth parts per thousand (fraction) + pptr parts per trillion (fraction) + PRU peripheral vascular resistance unit (fluid resistance) + psi pound per square inch (pressure) + pt pint, U.S. (fluid volume) + pt_br pint, British (volume) + pwt_tr pennyweight (mass) + qt quart, U.S. (fluid volume) + qt_br quart, British (volume) + R Roentgen (ion dose) + rad radian (plane angle) + RAD radiation absorbed dose (energy dose) + rch Ramden's chain, U.S. (length) + rd rod, U.S. (length) + rd_br rod, British (length) + REM radiation equivalent man (dose equivalent) + rlk_us link for Ramden's chain (length) + s second (time) + S Siemens (electric conductance) + sb stilb (lum. intensity density) + sc_ap scruple, apothecary (mass) + sct section (area) + scwt short hundredweight (mass) + smgy-U Somogyi unit (biologic activity of amylase) + sph spere (solid angle) + sr streadian (solid angle) + st stere (volume) + St Stokes (kinematic viscosity) + ston short ton (mass) + stone stone (mass) + Sv Sievert (dose equivalent) + Sv-U Svedberg unit (sedimentation coefficient) + T Tesla (magnetic flux density) + t tonne (mass) + tb-U tuberculin unit (biologic activity of tuberculin) + tbs tablespoon, U.S. (volume) + todd-U Todd unit (biologic activity antistreptolysin O) + tsp teaspoon, U.S. (volume) + twp township (area) + u unified atomic mass unit (mass) + U Unit (catalytic activity) + USP-U U.S. Pharmacopeia unit (arbitrary) + V Volt (electric potential) + W Watt (power) + Wb Weber (magnetic flux) + wk week (time) + yd yard, international (length) + yd_br yard, British (length) + yd_us yard, U.S. (length) + +=head1 PREFIXES + +Standard SI prefixes: + + y yocto (10^-24) + z zepto (10^-21) + a atto (10^-18) + f femto (10^-15) + p pico (10^-12) + n nano (10^-9) + u micro (10^-6) + m milli (10^-3) + c centi (10^-2) + d deci (10^-1) + da deka (10) + h hecto (10^2) + k kilo (10^3) + G giga (10^9) + M mega (10^6) + T tera (10^12) + P peta (10^15) + E exa (10^18) + Z zetta (10^21) + Y yotta (10^24) + +Binary power prefixes: + + Ki kibi (2^10) + Mi mebi (2^20) + Gi gibi (2^30) + Ti tebi (2^40) + +=head1 EXAMPLES + +A few examples of combined units strings: + + /cm3 per cubic centimeter + in2 square inches + kg.m/s2 Newtons (N) + m3/kg.s2 units of [G] + 10^100 googols + +=head1 HISTORY + + 2006-12-14 - PH Created + +=head1 AUTHOR + +Copyright 2003-2019, Phil Harvey (phil at owl.phy.queensu.ca) + +This library is free software; you can redistribute it and/or modify it +under the same terms as Perl itself. + +=head1 REFERENCES + +=over 4 + +=item L<http://aurora.regenstrief.org/UCUM/> + +=back + +=head1 SEE ALSO + +L<Image::ExifTool::MIE(3pm)|Image::ExifTool::MIE>, +L<Image::ExifTool(3pm)|Image::ExifTool> + +=cut diff --git a/lib/Image/ExifTool/MIFF.pm b/lib/Image/ExifTool/MIFF.pm new file mode 100644 index 0000000..c1df916 --- /dev/null +++ b/lib/Image/ExifTool/MIFF.pm @@ -0,0 +1,279 @@ +#------------------------------------------------------------------------------ +# File: MIFF.pm +# +# Description: Read Magick Image File Format meta information +# +# Revisions: 06/10/2005 - P. Harvey Created +# +# References: 1) http://www.imagemagick.org/script/miff.php +# 2) http://www.cs.uni.edu/Help/ImageMagick/www/miff.html +#------------------------------------------------------------------------------ + +package Image::ExifTool::MIFF; + +use strict; +use vars qw($VERSION); +use Image::ExifTool qw(:DataAccess :Utils); + +$VERSION = '1.07'; + +# MIFF chunks +%Image::ExifTool::MIFF::Main = ( + GROUPS => { 2 => 'Image' }, + NOTES => q{ + The MIFF (Magick Image File Format) format allows aribrary tag names to be + used. Only the standard tag names are listed below, however ExifTool will + decode any tags found in the image. + }, + 'background-color' => 'BackgroundColor', + 'blue-primary' => 'BluePrimary', + 'border-color' => 'BorderColor', + 'matt-color' => 'MattColor', + class => 'Class', + colors => 'Colors', + colorspace => 'ColorSpace', + columns => 'ImageWidth', + compression => 'Compression', + delay => 'Delay', + depth => 'Depth', + dispose => 'Dispose', + gamma => 'Gamma', + 'green-primary' => 'GreenPrimary', + id => 'ID', + iterations => 'Iterations', + label => 'Label', + matte => 'Matte', + montage => 'Montage', + packets => 'Packets', + page => 'Page', + # profile tags. Note the SubDirectory is not used by ProcessMIFF(), + # but is inserted for documentation purposes only + 'profile-APP1' => [ + # [this list is just for the sake of the documentation] + { + Name => 'APP1_Profile', + SubDirectory => { + TagTable => 'Image::ExifTool::Exif::Main', + }, + }, + { + Name => 'APP1_Profile', + SubDirectory => { + TagTable => 'Image::ExifTool::XMP::Main', + }, + }, + ], + 'profile-exif' => { # haven't seen this, but it would make sense - PH + Name => 'EXIF_Profile', + SubDirectory => { + TagTable => 'Image::ExifTool::Exif::Main', + }, + }, + 'profile-icc' => { + Name => 'ICC_Profile', + SubDirectory => { + TagTable => 'Image::ExifTool::ICC_Profile::Main', + }, + }, + 'profile-iptc' => { + Name => 'IPTC_Profile', + SubDirectory => { + TagTable => 'Image::ExifTool::Photoshop::Main', + }, + }, + 'profile-xmp' => { # haven't seen this, but it would make sense - PH + Name => 'XMP_Profile', + SubDirectory => { + TagTable => 'Image::ExifTool::XMP::Main', + }, + }, + 'red-primary' => 'RedPrimary', + 'rendering-intent' => 'RenderingIntent', + resolution => 'Resolution', + rows => 'ImageHeight', + scene => 'Scene', + signature => 'Signature', + units => 'Units', + 'white-point' => 'WhitePoint', +); + +#------------------------------------------------------------------------------ +# Extract meta information from a MIFF image +# Inputs: 0) ExifTool object reference, 1) dirInfo reference +# Returns: 1 on success, 0 if this wasn't a valid MIFF image +sub ProcessMIFF($$) +{ + my ($et, $dirInfo) = @_; + my $raf = $$dirInfo{RAF}; + my $verbose = $$et{OPTIONS}{Verbose}; + my ($hdr, $buff); + + # validate the MIFF file (note: MIFF files _may_ begin with other + # characters, but this starting sequence is strongly suggested.) + return 0 unless $raf->Read($hdr, 14) == 14; + return 0 unless $hdr eq 'id=ImageMagick'; + $et->SetFileType(); # set the FileType tag + + # set end-of-line character sequence to read to end of the TEXT + # section for new-type MIFF files (text ends with Colon+Ctrl-Z) + # Old MIFF files end with Colon+Linefeed, so this will likely + # slurp those entire files, which will be slower, but will work + # OK except that the profile information won't be decoded + local $/ = ":\x1a"; + + my $mode = ''; + my @profiles; + if ($raf->ReadLine($buff)) { + chomp $buff; # remove end-of-line chars + my $tagTablePtr = GetTagTable('Image::ExifTool::MIFF::Main'); + my @entries = split ' ', $buff; + unshift @entries, $hdr; # put the ID back in + my ($tag, $val); + foreach (@entries) { + if ($mode eq 'com') { + $mode = '' if /\}$/; + next; + } elsif (/^\{/) { + $mode = 'com'; # read to the end of the comment + next; + } + if ($mode eq 'val') { + $val .= " $_"; # join back together with a space + next unless /\}$/; + $mode = ''; + $val =~ s/(^\{|\}$)//g; # remove braces + } elsif (/(.+)=(.+)/) { + ($tag, $val) = ($1, $2); + if ($val =~ /^\{/) { + $mode = 'val'; # read to the end of the value data + next; + } + } elsif (/^:/) { + # this could be the end of an old-style MIFF file + last; + } else { + # something we don't recognize -- stop parsing here + $et->Warn('Unrecognized MIFF data'); + last; + } + my $tagInfo = $et->GetTagInfo($tagTablePtr, $tag); + unless ($tagInfo) { + $tagInfo = { Name => $tag }; + AddTagToTable($tagTablePtr, $tag, $tagInfo); + } + $verbose and $et->VerboseInfo($tag, $tagInfo, + Table => $tagTablePtr, + DataPt => \$val, + ); + # handle profile tags specially + if ($tag =~ /^profile-(.*)/) { + push @profiles, [$1, $val]; + } else { + $et->FoundTag($tagInfo, $val); + } + } + } + + # process profile information + foreach (@profiles) { + my ($type, $len) = @{$_}; + unless ($len =~ /^\d+$/) { + $et->Warn("Invalid length for $type profile"); + last; # don't try to read the rest + } + unless ($raf->Read($buff, $len) == $len) { + $et->Warn("Error reading $type profile ($len bytes)"); + next; + } + my $processed = 0; + my %dirInfo = ( + Parent => 'PNG', + DataPt => \$buff, + DataPos => $raf->Tell() - $len, + DataLen => $len, + DirStart => 0, + DirLen => $len, + ); + if ($type eq 'icc') { + # ICC Profile information + my $tagTablePtr = GetTagTable('Image::ExifTool::ICC_Profile::Main'); + $processed = $et->ProcessDirectory(\%dirInfo, $tagTablePtr); + } elsif ($type eq 'iptc') { + if ($buff =~ /^8BIM/) { + # Photoshop information + my $tagTablePtr = GetTagTable('Image::ExifTool::Photoshop::Main'); + $processed = $et->ProcessDirectory(\%dirInfo, $tagTablePtr); + } + # I haven't seen 'exif' or 'xmp' profile types yet, but I have seen them + # in newer PNG files so presumably they are possible here as well - PH + } elsif ($type eq 'APP1' or $type eq 'exif' or $type eq 'xmp') { + if ($buff =~ /^$Image::ExifTool::exifAPP1hdr/) { + # APP1 EXIF + my $hdrLen = length($Image::ExifTool::exifAPP1hdr); + $dirInfo{DirStart} += $hdrLen; + $dirInfo{DirLen} -= $hdrLen; + # use the usual position for EXIF data: 12 bytes from start of file + # (this may be wrong, but I can't see where the PNG stores this information) + $dirInfo{Base} = 12; # this is the usual value + $processed = $et->ProcessTIFF(\%dirInfo); + } elsif ($buff =~ /^$Image::ExifTool::xmpAPP1hdr/) { + # APP1 XMP + my $hdrLen = length($Image::ExifTool::xmpAPP1hdr); + my $tagTablePtr = GetTagTable('Image::ExifTool::XMP::Main'); + $dirInfo{DirStart} += $hdrLen; + $dirInfo{DirLen} -= $hdrLen; + $processed = $et->ProcessDirectory(\%dirInfo, $tagTablePtr); + } + } + unless ($processed) { + $et->Warn("Unknown MIFF $type profile data"); + if ($verbose) { + $et->VerboseDir($type, 0, $len); + $et->VerboseDump(\$buff); + } + } + } + return 1; +} + +1; # end + +__END__ + +=head1 NAME + +Image::ExifTool::MIFF - Read Magick Image File Format meta information + +=head1 SYNOPSIS + +This module is used by Image::ExifTool + +=head1 DESCRIPTION + +This module contains routines required by Image::ExifTool to read MIFF +(Magick Image File Format) images. + +=head1 AUTHOR + +Copyright 2003-2019, Phil Harvey (phil at owl.phy.queensu.ca) + +This library is free software; you can redistribute it and/or modify it +under the same terms as Perl itself. + +=head1 REFERENCES + +=over 4 + +=item L<http://www.imagemagick.org/script/miff.php> + +=item L<http://www.cs.uni.edu/Help/ImageMagick/www/miff.html> + +=back + +=head1 SEE ALSO + +L<Image::ExifTool::TagNames/MIFF Tags>, +L<Image::ExifTool(3pm)|Image::ExifTool> + +=cut + diff --git a/lib/Image/ExifTool/MNG.pm b/lib/Image/ExifTool/MNG.pm new file mode 100644 index 0000000..472b891 --- /dev/null +++ b/lib/Image/ExifTool/MNG.pm @@ -0,0 +1,684 @@ +#------------------------------------------------------------------------------ +# File: MNG.pm +# +# Description: MNG and JNG meta information tags +# +# Revisions: 06/23/2005 - P. Harvey Created +# +# References: 1) http://www.libpng.org/pub/mng/ +#------------------------------------------------------------------------------ + +package Image::ExifTool::MNG; + +use strict; +use vars qw($VERSION); +use Image::ExifTool qw(:DataAccess :Utils); + +$VERSION = '1.00'; + +# MNG chunks +%Image::ExifTool::MNG::Main = ( + GROUPS => { 2 => 'Image' }, + NOTES => q{ + This table contains definitions for tags found in MNG and JNG images. MNG + is a superset of PNG and JNG, so a MNG image may contain any of these tags + as well as any PNG tags. Conversely, only some of these tags are valid for + JNG images. + }, + BACK => { + Name => 'Background', + SubDirectory => { TagTable => 'Image::ExifTool::MNG::Background' }, + }, + BASI => { + Name => 'BasisObject', + SubDirectory => { TagTable => 'Image::ExifTool::MNG::BasisObject' }, + }, + CLIP => { + Name => 'ClipObjects', + SubDirectory => { TagTable => 'Image::ExifTool::MNG::ClipObjects' }, + }, + CLON => { + Name => 'CloneObject', + SubDirectory => { TagTable => 'Image::ExifTool::MNG::CloneObject' }, + }, + DBYK => { + Name => 'DropByKeyword', + Binary => 1, + }, + DEFI => { + Name => 'DefineObject', + SubDirectory => { TagTable => 'Image::ExifTool::MNG::DefineObject' }, + }, + DHDR => { + Name => 'DeltaPNGHeader', + SubDirectory => { TagTable => 'Image::ExifTool::MNG::DeltaPNGHeader' }, + }, + DISC => { + Name => 'DiscardObjects', + ValueConv => 'join(" ",unpack("n*",$val))', + }, + DROP => { + Name => 'DropChunks', + ValueConv => 'join(" ",$val=~/..../g)', + }, +# ENDL + eXPi => { + Name => 'ExportImage', + SubDirectory => { TagTable => 'Image::ExifTool::MNG::ExportImage' }, + }, + fPRI => { + Name => 'FramePriority', + SubDirectory => { TagTable => 'Image::ExifTool::MNG::FramePriority' }, + }, + FRAM => { + Name => 'Frame', + Binary => 1, + }, +# IJNG +# IPNG +# JDAA (JNG) +# JDAT (JNG) + JHDR => { # (JNG) + Name => 'JNGHeader', + SubDirectory => { TagTable => 'Image::ExifTool::MNG::JNGHeader' }, + }, +# JSEP (JNG) + LOOP => { + Name => 'Loop', + SubDirectory => { TagTable => 'Image::ExifTool::MNG::Loop' }, + }, + MAGN => { + Name => 'MagnifyObject', + SubDirectory => { TagTable => 'Image::ExifTool::MNG::MagnifyObject' }, + }, +# MEND + MHDR => { + Name => 'MNGHeader', + SubDirectory => { TagTable => 'Image::ExifTool::MNG::MNGHeader' }, + }, + MOVE => { + Name => 'MoveObjects', + SubDirectory => { TagTable => 'Image::ExifTool::MNG::MoveObjects' }, + }, + nEED => { + Name => 'ResourcesNeeded', + Binary => 1, + }, + ORDR => { + Name => 'OrderingRestrictions', + Binary => 1, + }, + PAST => { + Name => 'PasteImage', + SubDirectory => { TagTable => 'Image::ExifTool::MNG::PasteImage' }, + }, + pHYg => { + Name => 'GlobalPixelSize', + SubDirectory => { TagTable => 'Image::ExifTool::PNG::PhysicalPixel' }, + }, + PPLT => { + Name => 'PartialPalette', + Binary => 1, + }, + PROM => { + Name => 'PromoteParent', + SubDirectory => { TagTable => 'Image::ExifTool::MNG::PromoteParent' }, + }, + SAVE => { + Name => 'SaveObjects', + Binary => 1, + }, + SEEK => { + Name => 'SeekPoint', + ValueConv => '$val=~s/\0.*//s; $val', + }, + SHOW => { + Name => 'ShowObjects', + SubDirectory => { TagTable => 'Image::ExifTool::MNG::ShowObjects' }, + }, + TERM => { + Name => 'TerminationAction', + SubDirectory => { TagTable => 'Image::ExifTool::MNG::TerminationAction' }, + }, +); + +# MNG MHDR chunk +%Image::ExifTool::MNG::MNGHeader = ( + PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData, + GROUPS => { 2 => 'Image' }, + FORMAT => 'int32u', + 0 => 'ImageWidth', + 1 => 'ImageHeight', + 2 => 'TicksPerSecond', + 3 => 'NominalLayerCount', + 4 => 'NominalFrameCount', + 5 => 'NominalPlayTime', + 6 => { + Name => 'SimplicityProfile', + PrintConv => 'sprintf("0x%.8x", $val)', + }, +); + +# MNG BASI chunk +%Image::ExifTool::MNG::BasisObject = ( + PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData, + GROUPS => { 2 => 'Image' }, + 0 => { + Name => 'ImageWidth', + Format => 'int32u', + }, + 4 => { + Name => 'ImageHeight', + Format => 'int32u', + }, + 8 => 'BitDepth', + 9 => { + Name => 'ColorType', + RawConv => '$Image::ExifTool::PNG::colorType = $val', + PrintConv => { + 0 => 'Grayscale', + 2 => 'RGB', + 3 => 'Palette', + 4 => 'Grayscale with Alpha', + 6 => 'RGB with Alpha', + }, + }, + 10 => { + Name => 'Compression', + PrintConv => { 0 => 'Deflate/Inflate' }, + }, + 11 => { + Name => 'Filter', + PrintConv => { 0 => 'Adaptive' }, + }, + 12 => { + Name => 'Interlace', + PrintConv => { 0 => 'Noninterlaced', 1 => 'Adam7 Interlace' }, + }, + 13 => { + Name => 'RedSample', + Format => 'int32u', + }, + 17 => { + Name => 'GreenSample', + Format => 'int32u', + }, + 21 => { + Name => 'BlueSample', + Format => 'int32u', + }, + 25 => { + Name => 'AlphaSample', + Format => 'int32u', + }, + 26 => 'Viewable', +); + +# MNG LOOP chunk +%Image::ExifTool::MNG::Loop = ( + PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData, + GROUPS => { 2 => 'Image' }, + 0 => 'NestLevel', + 1 => { + Name => 'IterationCount', + Format => 'int32u', + }, + 5 => { + Name => 'TerminationCondition', + PrintConv => { + 0 => 'Deterministic, not cacheable', + 1 => 'Decoder discretion, not cacheable', + 2 => 'User discretion, not cacheable', + 3 => 'External signal, not cacheable', + 4 => 'Deterministic, cacheable', + 5 => 'Decoder discretion, cacheable', + 6 => 'User discretion, cacheable', + 7 => 'External signal, cacheable', + }, + }, + 6 => { + Name => 'IterationMinMax', + Format => 'int32u[2]', + }, + 14 => { + Name => 'SignalNumber', + Format => 'int32u', + }, +); + +# MNG DEFI chunk +%Image::ExifTool::MNG::DefineObject = ( + PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData, + GROUPS => { 2 => 'Image' }, + 0 => { + Name => 'ObjectID', + Format => 'int16u', + }, + 2 => 'DoNotShow', + 3 => 'ConcreteFlag', + 4 => { + Name => 'XYLocation', + Format => 'int32u[2]', + }, + 12 => { + Name => 'ClippingBoundary', + Format => 'int32u[4]', + }, +); + +# MNG CLON chunk +%Image::ExifTool::MNG::CloneObject = ( + PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData, + GROUPS => { 2 => 'Image' }, + 0 => { + Name => 'SourceID', + Format => 'int16u', + }, + 2 => { + Name => 'CloneID', + Format => 'int16u', + }, + 4 => { + Name => 'CloneType', + PrintConv => { 0 => 'Full', 1 => 'Parital', 2 => 'Renumber object' }, + }, + 5 => 'DoNotShow', + 6 => 'ConcreteFlag', + 7 => { + Name => 'LocalDeltaType', + PrintConv => { 0 => 'Absolute', 1 => 'Relative' }, + }, + 8 => { + Name => 'DeltaXY', + Format => 'int32u[2]', + }, +); + +# MNG PAST chunk +%Image::ExifTool::MNG::PasteImage = ( + PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData, + GROUPS => { 2 => 'Image' }, + 0 => { + Name => 'DestinationID', + Format => 'int16u', + }, + 2 => { + Name => 'TargetDeltaType', + PrintConv => { 0 => 'Absolute', 1 => 'Relative' }, + }, + 3 => { + Name => 'TargetXY', + Format => 'int32u[2]', + }, + 11 => { + Name => 'SourceID', + Format => 'int16u', + }, + 13 => { + Name => 'CompositionMode', + PrintConv => { 0 => 'Over', 1 => 'Replace', 2 => 'Under' }, + }, + 14 => { + Name => 'Orientation', + PrintConv => { + 0 => 'Same as source', + 2 => 'Flipped left-right, then up-down', + 4 => 'Flipped left-right', + 6 => 'Flipped up-down', + 8 => 'Tiled', + }, + }, + 15 => { + Name => 'OffsetOrigin', + PrintConv => { 0 => 'Desination Origin', 1 => 'Target Origin' }, + }, + 16 => { + Name => 'OffsetXY', + Format => 'int32u[2]', + }, + 24 => { + Name => 'BoundaryOrigin', + PrintConv => { 0 => 'Desination Origin', 1 => 'Target Origin' }, + }, + 25 => { + Name => 'PastClippingBoundary', + Format => 'int32u[4]', + }, +); + +my %magMethod = ( + 0 => 'No Magnification', + 1 => 'Pixel Replication', + 2 => 'Linear Interpolation', + 3 => 'Closest Pixel', + 4 => 'Color Linear Interpolation and Alpha Closest Pixel', + 5 => 'Color Closest Pixel and Alpha Linear Interpolation', +); + +# MNG MAGN chunk +%Image::ExifTool::MNG::MagnifyObject = ( + PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData, + GROUPS => { 2 => 'Image' }, + 0 => { + Name => 'FirstObjectID', + Format => 'int16u', + }, + 2 => { + Name => 'LastObjectID', + Format => 'int16u', + }, + 4 => { + Name => 'XMethod', + PrintConv => \%magMethod, + }, + 5 => { + Name => 'XMag', + Format => 'int16u', + }, + 7 => { + Name => 'YMag', + Format => 'int16u', + }, + 9 => { + Name => 'LeftMag', + Format => 'int16u', + }, + 11 => { + Name => 'RightMag', + Format => 'int16u', + }, + 13 => { + Name => 'TopMag', + Format => 'int16u', + }, + 15 => { + Name => 'BottomMag', + Format => 'int16u', + }, + 17 => { + Name => 'YMethod', + PrintConv => \%magMethod, + }, +); + +# MNG TERM chunk +%Image::ExifTool::MNG::TerminationAction = ( + PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData, + GROUPS => { 2 => 'Image' }, + 0 => { + Name => 'TerminationAction', + PrintConv => { + 0 => 'Show Last Frame', + 1 => 'Display Nothing', + 2 => 'Show First Frame', + 3 => 'Repeat Sequence', + }, + }, + 1 => { + Name => 'IterationEndAction', + PrintConv => { + 0 => 'Show Last Frame', + 1 => 'Display Nothing', + 2 => 'Show First Frame', + }, + }, + 2 => { + Name => 'Delay', + Format => 'int32u', + }, + 6 => { + Name => 'IterationMax', + Format => 'int32u', + }, +); + +# MNG BACK chunk +%Image::ExifTool::MNG::Background = ( + PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData, + GROUPS => { 2 => 'Image' }, + 0 => { + Name => 'BackgroundColor', + Format => 'int16u[3]', + }, + 6 => { + Name => 'MandatoryBackground', + PrintConv => { + 0 => 'Color and Image Advisory', + 1 => 'Color Mandatory, Image Advisory', + 2 => 'Color Advisory, Image Mandatory', + 3 => 'Color and Image Mandatory', + }, + }, + 7 => { + Name => 'BackgroundImageID', + Format => 'int16u', + }, + 9 => { + Name => 'BackgroundTiling', + PrintConv => { 0 => 'No', 1 => 'Yes' }, + }, +); + +# MNG MOVE chunk +%Image::ExifTool::MNG::MoveObjects = ( + PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData, + GROUPS => { 2 => 'Image' }, + 0 => { + Name => 'FirstObject', + Format => 'int16u', + }, + 2 => { + Name => 'LastObject', + Format => 'int16u', + }, + 4 => { + Name => 'DeltaType', + PrintConv => { 0 => 'Absolute', 1 => 'Relative' }, + }, + 5 => { + Name => 'DeltaXY', + Format => 'int32u[2]', + }, +); + +# MNG CLIP chunk +%Image::ExifTool::MNG::ClipObjects = ( + PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData, + GROUPS => { 2 => 'Image' }, + 0 => { + Name => 'FirstObject', + Format => 'int16u', + }, + 2 => { + Name => 'LastObject', + Format => 'int16u', + }, + 4 => { + Name => 'DeltaType', + PrintConv => { 0 => 'Absolute', 1 => 'Relative' }, + }, + 5 => { + Name => 'ClipBoundary', + Format => 'int32u[4]', + }, +); + +# MNG SHOW chunk +%Image::ExifTool::MNG::ShowObjects = ( + PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData, + GROUPS => { 2 => 'Image' }, + 0 => { + Name => 'FirstObject', + Format => 'int16u', + }, + 2 => { + Name => 'LastObject', + Format => 'int16u', + }, + 4 => 'ShowMode', +); + +# MNG eXPI chunk +%Image::ExifTool::MNG::ExportImage = ( + PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData, + GROUPS => { 2 => 'Image' }, + 0 => { + Name => 'SnapshotID', + Format => 'int16u', + }, + 2 => { + Name => 'SnapshotName', + Format => 'string', + }, +); + +# MNG fPRI chunk +%Image::ExifTool::MNG::FramePriority = ( + PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData, + GROUPS => { 2 => 'Image' }, + 0 => { + Name => 'DeltaType', + PrintConv => { 0 => 'Absolute', 1 => 'Relative' }, + }, + 2 => 'Priority', +); + +# MNG DHDR chunk +%Image::ExifTool::MNG::DeltaPNGHeader = ( + PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData, + GROUPS => { 2 => 'Image' }, + 0 => { + Name => 'ObjectID', + Format => 'int16u', + }, + 2 => { + Name => 'ImageType', + PrintConv => { + 0 => 'Unspecified', + 1 => 'PNG', + 2 => 'JNG', + }, + }, + 3 => { + Name => 'DeltaType', + PrintConv => { + 0 => 'Full Replacement', + 1 => 'Pixel Addition', + 2 => 'Alpha Addition', + 3 => 'Color Addition', + 4 => 'Pixel Replacement', + 5 => 'Alpha Replacement', + 6 => 'Color Replacement', + 7 => 'No Change', + }, + }, + 4 => { + Name => 'BlockSize', + Format => 'int32u[2]', + }, + 12 => { + Name => 'BlockLocation', + Format => 'int32u[2]', + }, +); + +# MNG PROM chunk +%Image::ExifTool::MNG::PromoteParent = ( + PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData, + GROUPS => { 2 => 'Image' }, + 0 => 'NewColorType', + 1 => 'NewBitDepth', + 2 => { + Name => 'FillMethod', + PrintConv => { 0 => 'Bit Replication', 1 => 'Zero Fill' }, + }, +); + +# JNG JHDR chunk +%Image::ExifTool::MNG::JNGHeader = ( + PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData, + GROUPS => { 2 => 'Image' }, + 0 => { + Name => 'ImageWidth', + Format => 'int32u', + }, + 4 => { + Name => 'ImageHeight', + Format => 'int32u', + }, + 8 => { + Name => 'ColorType', + PrintConv => { + 8 => 'Gray', + 10 => 'Color', + 12 => 'Gray Alpha', + 14 => 'Color Alpha', + }, + }, + 9 => 'BitDepth', + 10 => { + Name => 'Compression', + PrintConv => { 8 => 'Huffman-coded baseline JPEG' }, + }, + 11 => { + Name => 'Interlace', + PrintConv => { 0 => 'Sequential', 8 => 'Progressive' }, + }, + 12 => 'AlphaBitDepth', + 13 => { + Name => 'AlphaCompression', + PrintConv => { + 0 => 'MNG Grayscale IDAT', + 8 => 'JNG 8-bit Grayscale JDAA', + }, + }, + 14 => { + Name => 'AlphaFilter', + PrintConv => { 0 => 'Adaptive MNG (N/A for JPEG)' }, + }, + 15 => { + Name => 'AlphaInterlace', + PrintConv => { 0 => 'Noninterlaced' }, + }, +); + +1; # end + +__END__ + +=head1 NAME + +Image::ExifTool::MNG - MNG and JNG meta information tags + +=head1 SYNOPSIS + +This module is used by Image::ExifTool + +=head1 DESCRIPTION + +This module contains definitions required by Image::ExifTool to read MNG +(Multi-image Network Graphics) and JNG (JPEG Network Graphics) images. + +=head1 AUTHOR + +Copyright 2003-2019, Phil Harvey (phil at owl.phy.queensu.ca) + +This library is free software; you can redistribute it and/or modify it +under the same terms as Perl itself. + +=head1 REFERENCES + +=over 4 + +=item L<http://www.libpng.org/pub/mng/> + +=back + +=head1 SEE ALSO + +L<Image::ExifTool::TagNames/MNG Tags>, +L<Image::ExifTool::TagNames/PNG Tags>, +L<Image::ExifTool(3pm)|Image::ExifTool> + +=cut + diff --git a/lib/Image/ExifTool/MOI.pm b/lib/Image/ExifTool/MOI.pm new file mode 100644 index 0000000..b06fa00 --- /dev/null +++ b/lib/Image/ExifTool/MOI.pm @@ -0,0 +1,158 @@ +#------------------------------------------------------------------------------ +# File: MOI.pm +# +# Description: Read MOI meta information +# +# Revisions: 2014/12/15 - P. Harvey Created +# +# References: 1) https://en.wikipedia.org/wiki/MOI_(file_format) +#------------------------------------------------------------------------------ + +package Image::ExifTool::MOI; + +use strict; +use vars qw($VERSION); +use Image::ExifTool qw(:DataAccess :Utils); + +$VERSION = '1.02'; + +# MOI tags (ref 1) +%Image::ExifTool::MOI::Main = ( + GROUPS => { 2 => 'Video' }, + PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData, + NOTES => q{ + MOI files store information about associated MOD or TOD files, and are + written by some JVC, Canon and Panasonic camcorders. + }, + 0x00 => { Name => 'MOIVersion', Format => 'string[2]' }, + # 0x02 => { Name => 'MOIFileSize', Format => 'int32u' }, + 0x06 => { + Name => 'DateTimeOriginal', + Format => 'undef[8]', + Groups => { 2 => 'Time' }, + ValueConv => sub { + my $val = shift; + return undef unless length($val) >= 8; + my @v = unpack('nCCCCn', $val); + $v[5] /= 1000; + return sprintf('%.4d:%.2d:%.2d %.2d:%.2d:%06.3f', @v); + }, + PrintConv => '$self->ConvertDateTime($val)', + }, + 0x0e => { + Name => 'Duration', + Format => 'int32u', + ValueConv => '$val / 1000', + PrintConv => 'ConvertDuration($val)', + }, + 0x80 => { + Name => 'AspectRatio', + Format => 'int8u', + PrintConv => q{ + my $lo = ($val & 0x0f); + my $hi = ($val >> 4); + my $aspect; + if ($lo < 2) { + $aspect = '4:3'; + } elsif ($lo == 4 or $lo == 5) { + $aspect = '16:9'; + } else { + $aspect = 'Unknown'; + } + if ($hi == 4) { + $aspect .= ' NTSC'; + } elsif ($hi == 5) { + $aspect .= ' PAL'; + } + return $aspect; + }, + }, + 0x84 => { + Name => 'AudioCodec', + Format => 'int16u', + Groups => { 2 => 'Audio' }, + PrintHex => 1, + PrintConv => { + 0x00c1 => 'AC3', + 0x4001 => 'MPEG', + }, + }, + 0x86 => { + Name => 'AudioBitrate', + Format => 'int8u', + Groups => { 2 => 'Audio' }, + ValueConv => '$val * 16000 + 48000', + PrintConv => 'ConvertBitrate($val)', + }, + 0xda => { + Name => 'VideoBitrate', + Format => 'int16u', + PrintHex => 1, + ValueConv => { + 0x5896 => '8500000', + 0x813d => '5500000', + }, + PrintConv => 'ConvertBitrate($val)', + }, +); + +#------------------------------------------------------------------------------ +# Validate and extract metadata from MOI file +# Inputs: 0) ExifTool ref, 1) dirInfo ref +# Returns: 1 on success, 0 if this wasn't a valid MOI file +sub ProcessMOI($$) +{ + my ($et, $dirInfo) = @_; + my $raf = $$dirInfo{RAF}; + my $buff; + # read enough to allow skipping over run-in if it exists + $raf->Read($buff, 256) == 256 and $buff =~ /^V6/ or return 0; + if (defined $$et{VALUE}{FileSize}) { + my $size = unpack('x2N', $buff); + $size == $$et{VALUE}{FileSize} or return 0; + } + $et->SetFileType(); + SetByteOrder('MM'); + my $tagTablePtr = GetTagTable('Image::ExifTool::MOI::Main'); + return $et->ProcessBinaryData({ DataPt => \$buff }, $tagTablePtr); +} + +1; # end + +__END__ + +=head1 NAME + +Image::ExifTool::MOI - Read MOI meta information + +=head1 SYNOPSIS + +This module is used by Image::ExifTool + +=head1 DESCRIPTION + +This module contains definitions required by Image::ExifTool to read meta +information from MOI files. + +=head1 AUTHOR + +Copyright 2003-2019, Phil Harvey (phil at owl.phy.queensu.ca) + +This library is free software; you can redistribute it and/or modify it +under the same terms as Perl itself. + +=head1 REFERENCES + +=over 4 + +=item L<https://en.wikipedia.org/wiki/MOI_(file_format)> + +=back + +=head1 SEE ALSO + +L<Image::ExifTool::TagNames/MOI Tags>, +L<Image::ExifTool(3pm)|Image::ExifTool> + +=cut + diff --git a/lib/Image/ExifTool/MPC.pm b/lib/Image/ExifTool/MPC.pm new file mode 100644 index 0000000..773fd7c --- /dev/null +++ b/lib/Image/ExifTool/MPC.pm @@ -0,0 +1,156 @@ +#------------------------------------------------------------------------------ +# File: MPC.pm +# +# Description: Read Musepack audio meta information +# +# Revisions: 11/14/2006 - P. Harvey Created +# +# References: 1) http://www.musepack.net/ +#------------------------------------------------------------------------------ + +package Image::ExifTool::MPC; + +use strict; +use vars qw($VERSION); +use Image::ExifTool qw(:DataAccess :Utils); +use Image::ExifTool::FLAC; + +$VERSION = '1.01'; + +# MPC metadata blocks +%Image::ExifTool::MPC::Main = ( + PROCESS_PROC => \&Image::ExifTool::FLAC::ProcessBitStream, + GROUPS => { 2 => 'Audio' }, + NOTES => q{ + Tags used in Musepack (MPC) audio files. ExifTool also extracts ID3 and APE + information from these files. + }, + 'Bit032-063' => 'TotalFrames', + 'Bit080-081' => { + Name => 'SampleRate', + PrintConv => { + 0 => 44100, + 1 => 48000, + 2 => 37800, + 3 => 32000, + }, + }, + 'Bit084-087' => { + Name => 'Quality', + PrintConv => { + 1 => 'Unstable/Experimental', + 5 => '0', + 6 => '1', + 7 => '2 (Telephone)', + 8 => '3 (Thumb)', + 9 => '4 (Radio)', + 10 => '5 (Standard)', + 11 => '6 (Xtreme)', + 12 => '7 (Insane)', + 13 => '8 (BrainDead)', + 14 => '9', + 15 => '10', + }, + }, + 'Bit088-093' => 'MaxBand', + 'Bit096-111' => 'ReplayGainTrackPeak', + 'Bit112-127' => 'ReplayGainTrackGain', + 'Bit128-143' => 'ReplayGainAlbumPeak', + 'Bit144-159' => 'ReplayGainAlbumGain', + 'Bit179' => { + Name => 'FastSeek', + PrintConv => { 0 => 'No', 1 => 'Yes' }, + }, + 'Bit191' => { + Name => 'Gapless', + PrintConv => { 0 => 'No', 1 => 'Yes' }, + }, + 'Bit216-223' => { + Name => 'EncoderVersion', + PrintConv => '$val =~ s/(\d)(\d)(\d)$/$1.$2.$3/; $val', + }, +); + +#------------------------------------------------------------------------------ +# Extract information from an MPC file +# Inputs: 0) ExifTool object reference, 1) dirInfo reference +# - Just looks for MPC trailer if FileType is already set +# Returns: 1 on success, 0 if this wasn't a valid MPC file +sub ProcessMPC($$) +{ + my ($et, $dirInfo) = @_; + + # must first check for leading ID3 information + unless ($$et{DoneID3}) { + require Image::ExifTool::ID3; + Image::ExifTool::ID3::ProcessID3($et, $dirInfo) and return 1; + } + my $raf = $$dirInfo{RAF}; + my $buff; + + # check MPC signature + $raf->Read($buff, 32) == 32 and $buff =~ /^MP\+(.)/s or return 0; + my $vers = ord($1) & 0x0f; + $et->SetFileType(); + + # extract audio information (currently only from version 7 MPC files) + if ($vers == 0x07) { + SetByteOrder('II'); + my $pos = $raf->Tell() - 32; + if ($et->Options('Verbose')) { + $et->VPrint(0, "MPC Header (32 bytes):\n"); + $et->VerboseDump(\$buff, DataPos => $pos); + } + my $tagTablePtr = GetTagTable('Image::ExifTool::MPC::Main'); + my %dirInfo = ( DataPt => \$buff, DataPos => $pos ); + $et->ProcessDirectory(\%dirInfo, $tagTablePtr); + } else { + $et->Warn('Audio info currently not extracted from this version MPC file'); + } + + # process APE trailer if it exists + require Image::ExifTool::APE; + Image::ExifTool::APE::ProcessAPE($et, $dirInfo); + + return 1; +} + +1; # end + +__END__ + +=head1 NAME + +Image::ExifTool::MPC - Read Musepack audio meta information + +=head1 SYNOPSIS + +This module is used by Image::ExifTool + +=head1 DESCRIPTION + +This module contains definitions required by Image::ExifTool to extract meta +information from Musepack (MPC) audio files. + +=head1 AUTHOR + +Copyright 2003-2019, Phil Harvey (phil at owl.phy.queensu.ca) + +This library is free software; you can redistribute it and/or modify it +under the same terms as Perl itself. + +=head1 REFERENCES + +=over 4 + +=item L<http://www.musepack.net/> + +=back + +=head1 SEE ALSO + +L<Image::ExifTool::TagNames/MPC Tags>, +L<Image::ExifTool(3pm)|Image::ExifTool> + +=cut + diff --git a/lib/Image/ExifTool/MPEG.pm b/lib/Image/ExifTool/MPEG.pm new file mode 100644 index 0000000..787ac2f --- /dev/null +++ b/lib/Image/ExifTool/MPEG.pm @@ -0,0 +1,735 @@ +#------------------------------------------------------------------------------ +# File: MPEG.pm +# +# Description: Read MPEG-1 and MPEG-2 meta information +# +# Revisions: 05/11/2006 - P. Harvey Created +# +# References: 1) http://www.mp3-tech.org/ +# 2) http://www.getid3.org/ +# 3) http://dvd.sourceforge.net/dvdinfo/dvdmpeg.html +# 4) http://ffmpeg.org/ +# 5) http://sourceforge.net/projects/mediainfo/ +#------------------------------------------------------------------------------ + +package Image::ExifTool::MPEG; + +use strict; +use vars qw($VERSION); +use Image::ExifTool qw(:DataAccess :Utils); + +$VERSION = '1.16'; + +%Image::ExifTool::MPEG::Audio = ( + GROUPS => { 2 => 'Audio' }, + 'Bit11-12' => { + Name => 'MPEGAudioVersion', + RawConv => '$self->{MPEG_Vers} = $val', + PrintConv => { + 0 => 2.5, + 2 => 2, + 3 => 1, + }, + }, + 'Bit13-14' => { + Name => 'AudioLayer', + RawConv => '$self->{MPEG_Layer} = $val', + PrintConv => { + 1 => 3, + 2 => 2, + 3 => 1, + }, + }, + # Bit 15 indicates CRC protection + 'Bit16-19' => [ + { + Name => 'AudioBitrate', + Condition => '$self->{MPEG_Vers} == 3 and $self->{MPEG_Layer} == 3', + Notes => 'version 1, layer 1', + PrintConvColumns => 3, + ValueConv => { + 0 => 'free', + 1 => 32000, + 2 => 64000, + 3 => 96000, + 4 => 128000, + 5 => 160000, + 6 => 192000, + 7 => 224000, + 8 => 256000, + 9 => 288000, + 10 => 320000, + 11 => 352000, + 12 => 384000, + 13 => 416000, + 14 => 448000, + }, + PrintConv => 'ConvertBitrate($val)', + }, + { + Name => 'AudioBitrate', + Condition => '$self->{MPEG_Vers} == 3 and $self->{MPEG_Layer} == 2', + Notes => 'version 1, layer 2', + PrintConvColumns => 3, + ValueConv => { + 0 => 'free', + 1 => 32000, + 2 => 48000, + 3 => 56000, + 4 => 64000, + 5 => 80000, + 6 => 96000, + 7 => 112000, + 8 => 128000, + 9 => 160000, + 10 => 192000, + 11 => 224000, + 12 => 256000, + 13 => 320000, + 14 => 384000, + }, + PrintConv => 'ConvertBitrate($val)', + }, + { + Name => 'AudioBitrate', + Condition => '$self->{MPEG_Vers} == 3 and $self->{MPEG_Layer} == 1', + Notes => 'version 1, layer 3', + PrintConvColumns => 3, + ValueConv => { + 0 => 'free', + 1 => 32000, + 2 => 40000, + 3 => 48000, + 4 => 56000, + 5 => 64000, + 6 => 80000, + 7 => 96000, + 8 => 112000, + 9 => 128000, + 10 => 160000, + 11 => 192000, + 12 => 224000, + 13 => 256000, + 14 => 320000, + }, + PrintConv => 'ConvertBitrate($val)', + }, + { + Name => 'AudioBitrate', + Condition => '$self->{MPEG_Vers} != 3 and $self->{MPEG_Layer} == 3', + Notes => 'version 2 or 2.5, layer 1', + PrintConvColumns => 3, + ValueConv => { + 0 => 'free', + 1 => 32000, + 2 => 48000, + 3 => 56000, + 4 => 64000, + 5 => 80000, + 6 => 96000, + 7 => 112000, + 8 => 128000, + 9 => 144000, + 10 => 160000, + 11 => 176000, + 12 => 192000, + 13 => 224000, + 14 => 256000, + }, + PrintConv => 'ConvertBitrate($val)', + }, + { + Name => 'AudioBitrate', + Condition => '$self->{MPEG_Vers} != 3 and $self->{MPEG_Layer}', + Notes => 'version 2 or 2.5, layer 2 or 3', + PrintConvColumns => 3, + ValueConv => { + 0 => 'free', + 1 => 8000, + 2 => 16000, + 3 => 24000, + 4 => 32000, + 5 => 40000, + 6 => 48000, + 7 => 56000, + 8 => 64000, + 9 => 80000, + 10 => 96000, + 11 => 112000, + 12 => 128000, + 13 => 144000, + 14 => 160000, + }, + PrintConv => 'ConvertBitrate($val)', + }, + ], + 'Bit20-21' => [ + { + Name => 'SampleRate', + Condition => '$self->{MPEG_Vers} == 3', + Notes => 'version 1', + PrintConv => { + 0 => 44100, + 1 => 48000, + 2 => 32000, + }, + }, + { + Name => 'SampleRate', + Condition => '$self->{MPEG_Vers} == 2', + Notes => 'version 2', + PrintConv => { + 0 => 22050, + 1 => 24000, + 2 => 16000, + }, + }, + { + Name => 'SampleRate', + Condition => '$self->{MPEG_Vers} == 0', + Notes => 'version 2.5', + PrintConv => { + 0 => 11025, + 1 => 12000, + 2 => 8000, + }, + }, + ], + # Bit 22 - padding flag + # Bit 23 - private bit + 'Bit24-25' => { + Name => 'ChannelMode', + RawConv => '$self->{MPEG_Mode} = $val', + PrintConv => { + 0 => 'Stereo', + 1 => 'Joint Stereo', + 2 => 'Dual Channel', + 3 => 'Single Channel', + }, + }, + 'Bit26' => { + Name => 'MSStereo', + Condition => '$self->{MPEG_Layer} == 1', + Notes => 'layer 3', + PrintConv => { 0 => 'Off', 1 => 'On' }, + }, + 'Bit27' => { + Name => 'IntensityStereo', + Condition => '$self->{MPEG_Layer} == 1', + Notes => 'layer 3', + PrintConv => { 0 => 'Off', 1 => 'On' }, + }, + 'Bit26-27' => { + Name => 'ModeExtension', + Condition => '$self->{MPEG_Layer} > 1', + Notes => 'layer 1 or 2', + PrintConv => { + 0 => 'Bands 4-31', + 1 => 'Bands 8-31', + 2 => 'Bands 12-31', + 3 => 'Bands 16-31', + }, + }, + 'Bit28' => { + Name => 'CopyrightFlag', + PrintConv => { + 0 => 'False', + 1 => 'True', + }, + }, + 'Bit29' => { + Name => 'OriginalMedia', + PrintConv => { + 0 => 'False', + 1 => 'True', + }, + }, + 'Bit30-31' => { + Name => 'Emphasis', + PrintConv => { + 0 => 'None', + 1 => '50/15 ms', + 2 => 'reserved', + 3 => 'CCIT J.17', + }, + }, +); + +%Image::ExifTool::MPEG::Video = ( + GROUPS => { 2 => 'Video' }, + 'Bit00-11' => 'ImageWidth', + 'Bit12-23' => 'ImageHeight', + 'Bit24-27' => { + Name => 'AspectRatio', + ValueConv => { + 1 => 1, + 2 => 0.6735, + 3 => 0.7031, + 4 => 0.7615, + 5 => 0.8055, + 6 => 0.8437, + 7 => 0.8935, + 8 => 0.9157, + 9 => 0.9815, + 10 => 1.0255, + 11 => 1.0695, + 12 => 1.0950, + 13 => 1.1575, + 14 => 1.2015, + }, + PrintConv => { + 1 => '1:1', + 0.6735 => '0.6735', + 0.7031 => '16:9, 625 line, PAL', + 0.7615 => '0.7615', + 0.8055 => '0.8055', + 0.8437 => '16:9, 525 line, NTSC', + 0.8935 => '0.8935', + 0.9157 => '4:3, 625 line, PAL, CCIR601', + 0.9815 => '0.9815', + 1.0255 => '1.0255', + 1.0695 => '1.0695', + 1.0950 => '4:3, 525 line, NTSC, CCIR601', + 1.1575 => '1.1575', + 1.2015 => '1.2015', + }, + }, + 'Bit28-31' => { + Name => 'FrameRate', + ValueConv => { + 1 => 23.976, + 2 => 24, + 3 => 25, + 4 => 29.97, + 5 => 30, + 6 => 50, + 7 => 59.94, + 8 => 60, + }, + PrintConv => '"$val fps"', + }, + 'Bit32-49' => { + Name => 'VideoBitrate', + ValueConv => '$val eq 0x3ffff ? "Variable" : $val * 400', + PrintConv => 'ConvertBitrate($val)', + }, + # these tags not very interesting + #'Bit50' => 'MarkerBit', + #'Bit51-60' => 'VBVBufferSize', + #'Bit61' => 'ConstrainedParamFlag', + #'Bit62' => 'IntraQuantMatrixFlag', +); + +%Image::ExifTool::MPEG::Xing = ( + GROUPS => { 2 => 'Audio' }, + VARS => { NO_ID => 1 }, + NOTES => 'These tags are extracted from the Xing/Info frame.', + 1 => { Name => 'VBRFrames' }, + 2 => { Name => 'VBRBytes' }, + 3 => { Name => 'VBRScale' }, + 4 => { Name => 'Encoder' }, + 5 => { Name => 'LameVBRQuality' }, + 6 => { Name => 'LameQuality' }, + 7 => { # (for documentation only) + Name => 'LameHeader', + SubDirectory => { TagTable => 'Image::ExifTool::MPEG::Lame' }, + }, +); + +# Lame header tags (ref 5) +%Image::ExifTool::MPEG::Lame = ( + PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData, + GROUPS => { 2 => 'Audio' }, + NOTES => 'Tags extracted from Lame 3.90 or later header.', + 9 => { + Name => 'LameMethod', + Mask => 0x0f, + PrintConv => { + 1 => 'CBR', + 2 => 'ABR', + 3 => 'VBR (old/rh)', + 4 => 'VBR (new/mtrh)', + 5 => 'VBR (old/rh)', + 6 => 'VBR', + 8 => 'CBR (2-pass)', + 9 => 'ABR (2-pass)', + }, + }, + 10 => { + Name => 'LameLowPassFilter', + ValueConv => '$val * 100', + PrintConv => '($val / 1000) . " kHz"', + }, + # 19 - EncodingFlags + 20 => { + Name => 'LameBitrate', + ValueConv => '$val * 1000', + PrintConv => 'ConvertBitrate($val)', + }, + 24 => { + Name => 'LameStereoMode', + Mask => 0x1c, + PrintConv => { + 0 => 'Mono', + 1 => 'Stereo', + 2 => 'Dual Channels', + 3 => 'Joint Stereo', + 4 => 'Forced Joint Stereo', + 6 => 'Auto', + 7 => 'Intensity Stereo', + }, + }, +); + +# composite tags +%Image::ExifTool::MPEG::Composite = ( + Duration => { + Groups => { 2 => 'Video' }, + Require => { + 0 => 'FileSize', + }, + Desire => { + 1 => 'ID3Size', + 2 => 'MPEG:AudioBitrate', + 3 => 'MPEG:VideoBitrate', + 4 => 'MPEG:VBRFrames', + 5 => 'MPEG:SampleRate', + 6 => 'MPEG:MPEGAudioVersion', + }, + Priority => -1, # (don't want to replace any other Duration tag) + ValueConv => q{ + if ($val[4] and defined $val[5] and defined $val[6]) { + # calculate from number of VBR audio frames + my $mfs = $prt[5] / ($val[6] == 3 ? 144 : 72); + # calculate using VBR length + return 8 * $val[4] / $mfs; + } + # calculate duration as file size divided by total bitrate + # (note: this is only approximate!) + return undef unless $val[2] or $val[3]; + return undef if $val[2] and not $val[2] =~ /^\d+$/; + return undef if $val[3] and not $val[3] =~ /^\d+$/; + return (8 * ($val[0] - ($val[1]||0))) / (($val[2]||0) + ($val[3]||0)); + }, + PrintConv => 'ConvertDuration($val) . " (approx)"', + }, + AudioBitrate => { + Groups => { 2 => 'Audio' }, + Notes => 'calculated for variable-bitrate MPEG audio', + Require => { + 0 => 'MPEG:MPEGAudioVersion', + 1 => 'MPEG:SampleRate', + 2 => 'MPEG:VBRBytes', + 3 => 'MPEG:VBRFrames', + }, + ValueConv => q{ + return undef unless $val[3]; + my $mfs = $prt[1] / ($val[0] == 3 ? 144 : 72); + return $mfs * $val[2] / $val[3]; + }, + PrintConv => 'ConvertBitrate($val)', + }, +); + +# add our composite tags +Image::ExifTool::AddCompositeTags('Image::ExifTool::MPEG'); + + +#------------------------------------------------------------------------------ +# Process information in an MPEG audio or video frame header +# Inputs: 0) ExifTool object ref, 1) tag table ref, 2-N) list of 32-bit data words +sub ProcessFrameHeader($$@) +{ + my ($et, $tagTablePtr, @data) = @_; + my $tag; + foreach $tag (sort keys %$tagTablePtr) { + next unless $tag =~ /^Bit(\d{2})-?(\d{2})?/; + my ($b1, $b2) = ($1, $2 || $1); + my $index = int($b1 / 32); + my $word = $data[$index]; + my $mask = 0; + foreach (0 .. ($b2 - $b1)) { + $mask += (1 << $_); + } + my $val = ($word >> (31 + 32*$index - $b2)) & $mask; + $et->HandleTag($tagTablePtr, $tag, $val); + } +} + +#------------------------------------------------------------------------------ +# Read MPEG audio frame header +# Inputs: 0) ExifTool object reference, 1) Reference to audio data +# 2) flag set if we are trying to recognized MP3 file only +# Returns: 1 on success, 0 if no audio header was found +sub ParseMPEGAudio($$;$) +{ + my ($et, $buffPt, $mp3) = @_; + my ($word, $pos); + my $ext = $$et{FILE_EXT} || ''; + + for (;;) { + # find frame sync + return 0 unless $$buffPt =~ m{(\xff.{3})}sg; + $word = unpack('N', $1); # get audio frame header word + unless (($word & 0xffe00000) == 0xffe00000) { + pos($$buffPt) = pos($$buffPt) - 2; # next possible location for frame sync + next; + } + # validate header as much as possible + if (($word & 0x180000) == 0x080000 or # 01 is a reserved version ID + ($word & 0x060000) == 0x000000 or # 00 is a reserved layer description + ($word & 0x00f000) == 0x000000 or # 0000 is the "free" bitrate index + ($word & 0x00f000) == 0x00f000 or # 1111 is a bad bitrate index + ($word & 0x000c00) == 0x000c00 or # 11 is a reserved sampling frequency + ($word & 0x000003) == 0x000002 or # 10 is a reserved emphasis + (($mp3 and ($word & 0x060000) != 0x020000))) # must be layer 3 for MP3 + { + # give up easily unless this really should be an MP3 file + return 0 unless $ext eq 'MP3'; + pos($$buffPt) = pos($$buffPt) - 1; + next; + } + $pos = pos($$buffPt); + last; + } + # set file type if not done already + $et->SetFileType(); + + my $tagTablePtr = GetTagTable('Image::ExifTool::MPEG::Audio'); + ProcessFrameHeader($et, $tagTablePtr, $word); + + # extract the VBR information (ref MP3::Info) + my ($v, $m) = ($$et{MPEG_Vers}, $$et{MPEG_Mode}); + while (defined $v and defined $m) { + my $len = length $$buffPt; + $pos += $v == 3 ? ($m == 3 ? 17 : 32) : ($m == 3 ? 9 : 17); + last if $pos + 8 > $len; + my $buff = substr($$buffPt, $pos, 8); + last unless $buff =~ /^(Xing|Info)/; + my $xingTable = GetTagTable('Image::ExifTool::MPEG::Xing'); + my $vbrScale; + my $flags = unpack('x4N', $buff); + my $isVBR = ($buff !~ /^Info/); # Info frame is not VBR (ref 5) + $pos += 8; + if ($flags & 0x01) { # VBRFrames + last if $pos + 4 > $len; + $et->HandleTag($xingTable, 1, unpack("x${pos}N", $$buffPt)) if $isVBR; + $pos += 4; + } + if ($flags & 0x02) { # VBRBytes + last if $pos + 4 > $len; + $et->HandleTag($xingTable, 2, unpack("x${pos}N", $$buffPt)) if $isVBR; + $pos += 4; + } + if ($flags & 0x04) { # VBR_TOC + last if $pos + 100 > $len; + # (ignore toc for now) + $pos += 100; + } + if ($flags & 0x08) { # VBRScale + last if $pos + 4 > $len; + $vbrScale = unpack("x${pos}N", $$buffPt); + $et->HandleTag($xingTable, 3, $vbrScale) if $isVBR; + $pos += 4; + } + # process Lame header (ref 5) + if ($flags & 0x10) { # Lame + last if $pos + 348 > $len; + } elsif ($pos + 4 <= $len) { + my $lib = substr($$buffPt, $pos, 4); + unless ($lib eq 'LAME' or $lib eq 'GOGO') { + # attempt to identify other encoders + my $n; + if (index($$buffPt, 'RCA mp3PRO Encoder') >= 0) { + $lib = 'RCA mp3PRO'; + } elsif (($n = index($$buffPt, 'THOMSON mp3PRO Encoder')) >= 0) { + $lib = 'Thomson mp3PRO'; + $n += 22; + $lib .= ' ' . substr($$buffPt, $n, 6) if length($$buffPt) - $n >= 6; + } elsif (index($$buffPt, 'MPGE') >= 0) { + $lib = 'Gogo (<3.0)'; + } else { + last; + } + $et->HandleTag($xingTable, 4, $lib); + last; + } + } + my $lameLen = $len - $pos; + last if $lameLen < 9; + my $enc = substr($$buffPt, $pos, 9); + if ($enc ge 'LAME3.90') { + $et->HandleTag($xingTable, 4, $enc); + if ($vbrScale <= 100) { + $et->HandleTag($xingTable, 5, int((100 - $vbrScale) / 10)); + $et->HandleTag($xingTable, 6, (100 - $vbrScale) % 10); + } + my %dirInfo = ( + DataPt => $buffPt, + DirStart => $pos, + DirLen => length($$buffPt) - $pos, + ); + my $subTablePtr = GetTagTable('Image::ExifTool::MPEG::Lame'); + $et->ProcessDirectory(\%dirInfo, $subTablePtr); + } else { + $et->HandleTag($xingTable, 4, substr($$buffPt, $pos, 20)); + } + last; # (didn't want to loop anyway) + } + + return 1; +} + +#------------------------------------------------------------------------------ +# Read MPEG video frame header +# Inputs: 0) ExifTool object reference, 1) Reference to video data +# Returns: 1 on success, 0 if no video header was found +sub ProcessMPEGVideo($$) +{ + my ($et, $buffPt) = @_; + + return 0 unless length $$buffPt >= 4; + my ($w1, $w2) = unpack('N2', $$buffPt); + # validate as much as possible + if (($w1 & 0x000000f0) == 0x00000000 or # 0000 is a forbidden aspect ratio + ($w1 & 0x000000f0) == 0x000000f0 or # 1111 is a reserved aspect ratio + ($w1 & 0x0000000f) == 0 or # frame rate must be 1-8 + ($w1 & 0x0000000f) > 8) + { + return 0; + } + # set file type if not done already + $et->SetFileType('MPEG') unless $$et{VALUE}{FileType}; + + my $tagTablePtr = GetTagTable('Image::ExifTool::MPEG::Video'); + ProcessFrameHeader($et, $tagTablePtr, $w1, $w2); + return 1; +} + +#------------------------------------------------------------------------------ +# Read MPEG audio and video frame headers +# Inputs: 0) ExifTool object reference, 1) Reference to audio/video data +# Returns: 1 on success, 0 if no video header was found +# To Do: Properly parse MPEG streams: +# 0xb7 - sequence end +# 0xb9 - end code +# 0xba - pack start code +# 0xbb - system header +# 0xbc - program map <-- should parse this +# 0xbd - private stream 1 --> for VOB, this contains sub-streams: +# 0x20-0x3f - pictures +# 0x80-0x87 - audio (AC3,DTS,SDDS) +# 0xa0-0xa7 - audio (LPCM) +# 0xbe - padding +# 0xbf - private stream 2 +# 0xc0-0xdf - audio stream +# 0xe0-0xef - video stream +sub ParseMPEGAudioVideo($$) +{ + my ($et, $buffPt) = @_; + my (%found, $didHdr); + my $rtnVal = 0; + my %proc = ( audio => \&ParseMPEGAudio, video => \&ProcessMPEGVideo ); + + delete $$et{AudioBitrate}; + delete $$et{VideoBitrate}; + + while ($$buffPt =~ /\0\0\x01(\xb3|\xc0)/g) { + my $type = $1 eq "\xb3" ? 'video' : 'audio'; + unless ($didHdr) { + # make sure we didn't miss an audio frame sync before this (eg. MP3 file) + # (the last byte of the 4-byte MP3 audio frame header word may be zero, + # but the 2nd last must be non-zero, so we need only check to pos-3) + my $buff = substr($$buffPt, 0, pos($$buffPt) - 3); + $found{audio} = 1 if ParseMPEGAudio($et, \$buff); + $didHdr = 1; + } + next if $found{$type}; + my $len = length($$buffPt) - pos($$buffPt); + last if $len < 4; + $len > 256 and $len = 256; + my $dat = substr($$buffPt, pos($$buffPt), $len); + # process MPEG audio or video + if (&{$proc{$type}}($et, \$dat)) { + $rtnVal = 1; + $found{$type} = 1; + # done if we found audio and video + last if scalar(keys %found) == 2; + } + } + return $rtnVal; +} + +#------------------------------------------------------------------------------ +# Read information from an MPEG file +# Inputs: 0) ExifTool object reference, 1) Directory information reference +# Returns: 1 on success, 0 if this wasn't a valid MPEG file +sub ProcessMPEG($$) +{ + my ($et, $dirInfo) = @_; + my $raf = $$dirInfo{RAF}; + my $buff; + + $raf->Read($buff, 4) == 4 or return 0; + return 0 unless $buff =~ /^\0\0\x01[\xb0-\xbf]/; + $et->SetFileType(); + + $raf->Seek(0,0); + $raf->Read($buff, 65536*4) or return 0; + + return ParseMPEGAudioVideo($et, \$buff); +} + +1; # end + +__END__ + +=head1 NAME + +Image::ExifTool::MPEG - Read MPEG-1 and MPEG-2 meta information + +=head1 SYNOPSIS + +This module is used by Image::ExifTool + +=head1 DESCRIPTION + +This module contains definitions required by Image::ExifTool to read MPEG-1 +and MPEG-2 audio/video files. + +=head1 NOTES + +Since ISO charges money for the official MPEG specification, this module is +based on unofficial sources which may be incomplete, inaccurate or outdated. + +=head1 AUTHOR + +Copyright 2003-2019, Phil Harvey (phil at owl.phy.queensu.ca) + +This library is free software; you can redistribute it and/or modify it +under the same terms as Perl itself. + +=head1 REFERENCES + +=over 4 + +=item L<http://www.mp3-tech.org/> + +=item L<http://www.getid3.org/> + +=item L<http://dvd.sourceforge.net/dvdinfo/dvdmpeg.html> + +=item L<http://ffmpeg.org/> + +=item L<http://sourceforge.net/projects/mediainfo/> + +=back + +=head1 SEE ALSO + +L<Image::ExifTool::TagNames/MPEG Tags>, +L<MP3::Info(3pm)|MP3::Info>, +L<Image::ExifTool(3pm)|Image::ExifTool> + +=cut + diff --git a/lib/Image/ExifTool/MPF.pm b/lib/Image/ExifTool/MPF.pm new file mode 100644 index 0000000..9b22801 --- /dev/null +++ b/lib/Image/ExifTool/MPF.pm @@ -0,0 +1,288 @@ +#------------------------------------------------------------------------------ +# File: MPF.pm +# +# Description: Read Multi-Picture Format information +# +# Revisions: 06/12/2009 - P. Harvey Created +# +# References: 1) http://www.cipa.jp/std/documents/e/DC-007_E.pdf +#------------------------------------------------------------------------------ + +package Image::ExifTool::MPF; + +use strict; +use vars qw($VERSION); +use Image::ExifTool qw(:DataAccess :Utils); +use Image::ExifTool::Exif; + +$VERSION = '1.14'; + +sub ProcessMPImageList($$$); + +# Tags found in APP2 MPF segment in JPEG images +%Image::ExifTool::MPF::Main = ( + GROUPS => { 0 => 'MPF', 1 => 'MPF0', 2 => 'Image'}, + NOTES => q{ + These tags are part of the CIPA Multi-Picture Format specification, and are + found in the APP2 "MPF" segment of JPEG images. MPImage data referenced + from this segment is stored as a JPEG trailer. The MPF tags are not + writable, however the MPF segment may be deleted as a group (with "MPF:All") + but then the JPEG trailer should also be deleted (with "Trailer:All"). See + L<http://www.cipa.jp/std/documents/e/DC-007_E.pdf> for the official + specification. + }, + 0xb000 => 'MPFVersion', + 0xb001 => 'NumberOfImages', + 0xb002 => { + Name => 'MPImageList', + SubDirectory => { + TagTable => 'Image::ExifTool::MPF::MPImage', + ProcessProc => \&ProcessMPImageList, + }, + }, + 0xb003 => { + Name => 'ImageUIDList', + Binary => 1, + }, + 0xb004 => 'TotalFrames', + 0xb101 => 'MPIndividualNum', + 0xb201 => { + Name => 'PanOrientation', + PrintHex => 1, + Notes => 'long integer is split into 4 bytes', + ValueConv => 'join(" ",unpack("C*",pack("N",$val)))', + PrintConv => [ + '"$val rows"', + '"$val columns"', + { + 0 => '[unused]', + 1 => 'Start at top right', + 2 => 'Start at top left', + 3 => 'Start at bottom left', + 4 => 'Start at bottom right', + }, + { + 0x01 => 'Left to right', + 0x02 => 'Right to left', + 0x03 => 'Top to bottom', + 0x04 => 'Bottom to top', + 0x10 => 'Clockwise', + 0x20 => 'Counter clockwise', + 0x30 => 'Zigzag (row start)', + 0x40 => 'Zigzag (column start)', + }, + ], + }, + 0xb202 => 'PanOverlapH', + 0xb203 => 'PanOverlapV', + 0xb204 => 'BaseViewpointNum', + 0xb205 => 'ConvergenceAngle', + 0xb206 => 'BaselineLength', + 0xb207 => 'VerticalDivergence', + 0xb208 => 'AxisDistanceX', + 0xb209 => 'AxisDistanceY', + 0xb20a => 'AxisDistanceZ', + 0xb20b => 'YawAngle', + 0xb20c => 'PitchAngle', + 0xb20d => 'RollAngle', +); + +# Tags found in MPImage structure +%Image::ExifTool::MPF::MPImage = ( + PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData, + #WRITE_PROC => \&Image::ExifTool::WriteBinaryData, + #CHECK_PROC => \&Image::ExifTool::CheckBinaryData, + #WRITABLE => 1, + GROUPS => { 0 => 'MPF', 1 => 'MPImage', 2 => 'Image'}, + NOTES => q{ + The first MPF "Large Thumbnail" image is extracted as PreviewImage, and the + rest of the embedded MPF images are extracted as MPImage#. The + ExtractEmbedded (-ee) option may be used to extract information from these + embedded images. + }, + 0.1 => { + Name => 'MPImageFlags', + Format => 'int32u', + Mask => 0xf8000000, + PrintConv => { BITMASK => { + 2 => 'Representative image', + 3 => 'Dependent child image', + 4 => 'Dependent parent image', + }}, + }, + 0.2 => { + Name => 'MPImageFormat', + Format => 'int32u', + Mask => 0x07000000, + PrintConv => { + 0 => 'JPEG', + }, + }, + 0.3 => { + Name => 'MPImageType', + Format => 'int32u', + Mask => 0x00ffffff, + PrintHex => 1, + PrintConv => { + 0x000000 => 'Undefined', + 0x010001 => 'Large Thumbnail (VGA equivalent)', + 0x010002 => 'Large Thumbnail (full HD equivalent)', + 0x020001 => 'Multi-frame Panorama', + 0x020002 => 'Multi-frame Disparity', + 0x020003 => 'Multi-angle', + 0x030000 => 'Baseline MP Primary Image', + }, + }, + 4 => { + Name => 'MPImageLength', + Format => 'int32u', + }, + 8 => { + Name => 'MPImageStart', + Format => 'int32u', + IsOffset => '$val', + }, + 12 => { + Name => 'DependentImage1EntryNumber', + Format => 'int16u', + }, + 14 => { + Name => 'DependentImage2EntryNumber', + Format => 'int16u', + }, +); + +# extract MP Images as composite tags +%Image::ExifTool::MPF::Composite = ( + GROUPS => { 2 => 'Preview' }, + MPImage => { + Require => { + 0 => 'MPImageStart', + 1 => 'MPImageLength', + 2 => 'MPImageType', + }, + Notes => q{ + the first MPF "Large Thumbnail" is extracted as PreviewImage, and the rest + of the embedded MPF images are extracted as MPImage#. The ExtractEmbedded + option may be used to extract information from these embedded images. + }, + # extract all MPF images (not just one) + RawConv => q{ + require Image::ExifTool::MPF; + @grps = $self->GetGroup($$val{0}); # set groups from input tag + Image::ExifTool::MPF::ExtractMPImages($self); + }, + }, +); + +# add our composite tags +Image::ExifTool::AddCompositeTags('Image::ExifTool::MPF'); + +#------------------------------------------------------------------------------ +# Extract all MP images +# Inputs: 0) ExifTool object ref +# Returns: undef +sub ExtractMPImages($) +{ + my $et = shift; + my $ee = $et->Options('ExtractEmbedded'); + my $saveBinary = $et->Options('Binary'); + my ($i, $didPreview, $xtra); + + for ($i=1; $xtra or not defined $xtra; ++$i) { + # run through MP images in the same order they were extracted + $xtra = defined $$et{VALUE}{"MPImageStart ($i)"} ? " ($i)" : ''; + my $off = $et->GetValue("MPImageStart$xtra", 'ValueConv'); + my $len = $et->GetValue("MPImageLength$xtra", 'ValueConv'); + if ($off and $len) { + my $type = $et->GetValue("MPImageType$xtra", 'ValueConv'); + my $tag = "MPImage$i"; + # store first "Large Thumbnail" as a PreviewImage + if (not $didPreview and $type and ($type & 0x0f0000) == 0x010000) { + $tag = 'PreviewImage'; + $didPreview = 1; + } + $et->Options('Binary', 1) if $ee; + my $val = Image::ExifTool::Exif::ExtractImage($et, $off, $len, $tag); + $et->Options('Binary', $saveBinary) if $ee; + next unless defined $val; + unless ($Image::ExifTool::Extra{$tag}) { + AddTagToTable(\%Image::ExifTool::Extra, $tag, { + Name => $tag, + Groups => { 0 => 'Composite', 1 => 'Composite', 2 => 'Preview'}, + }); + } + my $key = $et->FoundTag($tag, $val, $et->GetGroup("MPImageStart$xtra")); + # extract information from MP images if ExtractEmbedded option used + if ($ee) { + my $oldBase = $$et{BASE}; + $$et{BASE} = $off; + $$et{DOC_NUM} = $i; + $et->ExtractInfo($val, { ReEntry => 1 }); + delete $$et{DOC_NUM}; + $$et{BASE} = $oldBase; + } + } + } + return undef; +} + +#------------------------------------------------------------------------------ +# Process MP Entry list +# Inputs: 0) ExifTool object ref, 1) dirInfo ref, 2) tag table ref +# Returns: 1 on success +sub ProcessMPImageList($$$) +{ + my ($et, $dirInfo, $tagTablePtr) = @_; + my $num = int($$dirInfo{DirLen} / 16); # (16 bytes per MP Entry) + $$dirInfo{DirLen} = 16; + my ($i, $success); + my $oldG1 = $$et{SET_GROUP1}; + for ($i=0; $i<$num; ++$i) { + $$et{SET_GROUP1} = '+' . ($i + 1); + $success = $et->ProcessBinaryData($dirInfo, $tagTablePtr); + $$dirInfo{DirStart} += 16; + } + $$et{SET_GROUP1} = $oldG1; + return $success; +} + +1; # end + +__END__ + +=head1 NAME + +Image::ExifTool::MPF - Read Multi-Picture Format information + +=head1 SYNOPSIS + +This module is used by Image::ExifTool + +=head1 DESCRIPTION + +This module contains tag definitions and routines to read Multi-Picture +Format (MPF) information from JPEG images. + +=head1 AUTHOR + +Copyright 2003-2019, Phil Harvey (phil at owl.phy.queensu.ca) + +This library is free software; you can redistribute it and/or modify it +under the same terms as Perl itself. + +=head1 REFERENCES + +=over 4 + +=item L<http://www.cipa.jp/std/documents/e/DC-007_E.pdf> + +=back + +=head1 SEE ALSO + +L<Image::ExifTool::TagNames/MPF Tags>, +L<Image::ExifTool(3pm)|Image::ExifTool> + +=cut + diff --git a/lib/Image/ExifTool/MWG.pm b/lib/Image/ExifTool/MWG.pm new file mode 100644 index 0000000..ffbd774 --- /dev/null +++ b/lib/Image/ExifTool/MWG.pm @@ -0,0 +1,765 @@ +#------------------------------------------------------------------------------ +# File: MWG.pm +# +# Description: Metadata Working Group support +# +# Revisions: 2009/10/21 - P. Harvey Created +# +# References: 1) http://www.metadataworkinggroup.org/ +#------------------------------------------------------------------------------ + +package Image::ExifTool::MWG; + +use strict; +use vars qw($VERSION); +use Image::ExifTool qw(:DataAccess :Utils); +use Image::ExifTool::Exif; +use Image::ExifTool::XMP; + +$VERSION = '1.22'; + +sub RecoverTruncatedIPTC($$$); +sub ListToString($); +sub StringToList($$); +sub OverwriteStringList($$$$); + +my $mwgLoaded; # flag set if we alreaded Load()ed the MWG tags + +# MWG Composite tags +%Image::ExifTool::MWG::Composite = ( + GROUPS => { 0 => 'Composite', 1 => 'MWG', 2 => 'Image' }, + VARS => { NO_ID => 1 }, + NOTES => q{ + The table below lists special Composite tags which are used to access other + tags based on the MWG 2.0 recommendations. These tags are only accessible + when explicitly loaded, but this is done automatically by the exiftool + application if MWG is specified as a group for any tag on the command line, + or manually with the C<-use MWG> option. Via the API, the MWG Composite + tags are loaded by calling "C<Image::ExifTool::MWG::Load()>". + + When reading, the value of each MWG tag is B<Derived From> the specified + tags based on the MWG guidelines. When writing, the appropriate associated + tags are written. The value of the IPTCDigest tag is updated automatically + when the IPTC is changed if either the IPTCDigest tag didn't exist + beforehand or its value agreed with the original IPTC digest (indicating + that the XMP is synchronized with the IPTC). IPTC information is written + only if the original file contained IPTC. + + Loading the MWG module activates "strict MWG conformance mode", which has + the effect of causing EXIF, IPTC and XMP in non-standard locations to be + ignored when reading, as per the MWG recommendations. Instead, a "Warning" + tag is generated when non-standard metadata is encountered. This feature + may be disabled by setting C<$Image::ExifTool::MWG::strict = 0> in the + L<ExifTool config file|../config.html> (or from your Perl script when using the API). Note + that the behaviour when writing is not changed: ExifTool always creates new + records only in the standard location, but writes new tags to any + EXIF/IPTC/XMP records that exist. + + Contrary to the EXIF specification, the MWG recommends that EXIF "ASCII" + string values be stored as UTF-8. To honour this, the exiftool application + sets the default internal EXIF string encoding to "UTF8" when the MWG module + is loaded, but via the API this must be done manually by setting the + CharsetEXIF option. + + A complication of the MWG specification is that although the MWG:Creator + property may consist of multiple values, the associated EXIF tag + (EXIF:Artist) is only a simple string. To resolve this discrepancy the MWG + recommends a technique which allows a list of values to be stored in a + string by using a semicolon-space separator (with quotes around values if + necessary). When the MWG module is loaded, ExifTool automatically + implements this policy and changes EXIF:Artist to a list-type tag. + }, + Keywords => { + Flags => ['Writable','List'], + Desire => { + 0 => 'IPTC:Keywords', # (64-character limit) + 1 => 'XMP-dc:Subject', + 2 => 'CurrentIPTCDigest', + 3 => 'IPTCDigest', + }, + RawConv => q{ + return $val[1] if not defined $val[2] or (defined $val[1] and + (not defined $val[3] or $val[2] eq $val[3])); + return Image::ExifTool::MWG::RecoverTruncatedIPTC($val[0], $val[1], 64); + }, + DelCheck => 'Image::ExifTool::MWG::ReconcileIPTCDigest($self)', + WriteCheck => 'Image::ExifTool::MWG::ReconcileIPTCDigest($self)', + WriteAlso => { + # only write Keywords if IPTC exists (eg. set EditGroup option) + 'IPTC:Keywords' => '$opts{EditGroup} = 1; $val', + 'XMP-dc:Subject' => '$val', + }, + }, + Description => { + Writable => 1, + Desire => { + 0 => 'EXIF:ImageDescription', + 1 => 'IPTC:Caption-Abstract', # (2000-character limit) + 2 => 'XMP-dc:Description', + 3 => 'CurrentIPTCDigest', + 4 => 'IPTCDigest', + }, + RawConv => q{ + return $val[0] if defined $val[0] and $val[0] !~ /^ *$/; + return $val[2] if not defined $val[3] or (defined $val[2] and + (not defined $val[4] or $val[3] eq $val[4])); + return Image::ExifTool::MWG::RecoverTruncatedIPTC($val[1], $val[2], 2000); + }, + DelCheck => 'Image::ExifTool::MWG::ReconcileIPTCDigest($self)', + WriteCheck => 'Image::ExifTool::MWG::ReconcileIPTCDigest($self)', + WriteAlso => { + 'EXIF:ImageDescription' => '$val', + 'IPTC:Caption-Abstract' => '$opts{EditGroup} = 1; $val', + 'XMP-dc:Description' => '$val', + }, + }, + DateTimeOriginal => { + Description => 'Date/Time Original', + Groups => { 2 => 'Time' }, + Notes => '"creation date of the intellectual content being shown" - MWG', + Writable => 1, + Shift => 0, # don't shift this tag + Desire => { + 0 => 'Composite:SubSecDateTimeOriginal', + 1 => 'EXIF:DateTimeOriginal', + 2 => 'IPTC:DateCreated', + 3 => 'IPTC:TimeCreated', + 4 => 'XMP-photoshop:DateCreated', + 5 => 'CurrentIPTCDigest', + 6 => 'IPTCDigest', + }, + # must check for validity in RawConv to avoid hiding a same-named tag, + # but IPTC dates use a ValueConv so we need to derive the value there + RawConv => q{ + (defined $val[0] or defined $val[1] or $val[2] or + (defined $val[4] and (not defined $val[5] or not defined $val[6] + or $val[5] eq $val[6]))) ? $val : undef + }, + ValueConv => q{ + return $val[0] if defined $val[0] and $val[0] !~ /^[: ]*$/; + return $val[1] if defined $val[1] and $val[1] !~ /^[: ]*$/; + return $val[4] if not defined $val[5] or (defined $val[4] and + (not defined $val[6] or $val[5] eq $val[6])); + return $val[3] ? "$val[2] $val[3]" : $val[2] if $val[2]; + return undef; + }, + PrintConv => '$self->ConvertDateTime($val)', + PrintConvInv => '$self->InverseDateTime($val,undef,1)', + DelCheck => 'Image::ExifTool::MWG::ReconcileIPTCDigest($self)', + WriteCheck => 'Image::ExifTool::MWG::ReconcileIPTCDigest($self)', + WriteAlso => { + # set EXIF date/time values according to PrintConv option instead + # of defaulting to Type=ValueConv to allow reformatting to be applied + 'Composite:SubSecDateTimeOriginal' => 'delete $opts{Type}; $val', + 'IPTC:DateCreated' => '$opts{EditGroup} = 1; $val', + 'IPTC:TimeCreated' => '$opts{EditGroup} = 1; $val', + 'XMP-photoshop:DateCreated' => '$val', + }, + }, + CreateDate => { + Groups => { 2 => 'Time' }, + Notes => '"creation date of the digital representation" - MWG', + Writable => 1, + Shift => 0, # don't shift this tag + Desire => { + 0 => 'Composite:SubSecCreateDate', + 1 => 'EXIF:CreateDate', + 2 => 'IPTC:DigitalCreationDate', + 3 => 'IPTC:DigitalCreationTime', + 4 => 'XMP-xmp:CreateDate', + 5 => 'CurrentIPTCDigest', + 6 => 'IPTCDigest', + }, + RawConv => q{ + (defined $val[0] or defined $val[1] or $val[2] or + (defined $val[4] and (not defined $val[5] or not defined $val[6] + or $val[5] eq $val[6]))) ? $val : undef + }, + ValueConv => q{ + return $val[0] if defined $val[0] and $val[0] !~ /^[: ]*$/; + return $val[1] if defined $val[1] and $val[1] !~ /^[: ]*$/; + return $val[4] if not defined $val[5] or (defined $val[4] and + (not defined $val[6] or $val[5] eq $val[6])); + return $val[3] ? "$val[2] $val[3]" : $val[2] if $val[2]; + return undef; + }, + PrintConv => '$self->ConvertDateTime($val)', + PrintConvInv => '$self->InverseDateTime($val,undef,1)', + DelCheck => 'Image::ExifTool::MWG::ReconcileIPTCDigest($self)', + WriteCheck => 'Image::ExifTool::MWG::ReconcileIPTCDigest($self)', + WriteAlso => { + 'Composite:SubSecCreateDate' => 'delete $opts{Type}; $val', + 'IPTC:DigitalCreationDate' => '$opts{EditGroup} = 1; $val', + 'IPTC:DigitalCreationTime' => '$opts{EditGroup} = 1; $val', + 'XMP-xmp:CreateDate' => '$val', + }, + }, + ModifyDate => { + Groups => { 2 => 'Time' }, + Notes => '"modification date of the digital image file" - MWG', + Writable => 1, + Shift => 0, # don't shift this tag + Desire => { + 0 => 'Composite:SubSecModifyDate', + 1 => 'EXIF:ModifyDate', + 2 => 'XMP-xmp:ModifyDate', + 3 => 'CurrentIPTCDigest', + 4 => 'IPTCDigest', + }, + RawConv => q{ + return $val[0] if defined $val[0] and $val[0] !~ /^[: ]*$/; + return $val[1] if defined $val[1] and $val[1] !~ /^[: ]*$/; + return $val[2] if not defined $val[3] or not defined $val[4] or $val[3] eq $val[4]; + return undef; + }, + PrintConv => '$self->ConvertDateTime($val)', + PrintConvInv => '$self->InverseDateTime($val,undef,1)', + # return empty string from check routines so this tag will never be set + # (only WriteAlso tags are written), the only difference is a -v2 message + DelCheck => '""', + WriteCheck => '""', + WriteAlso => { + 'Composite:SubSecModifyDate' => 'delete $opts{Type}; $val', + 'XMP-xmp:ModifyDate' => '$val', + }, + }, + Orientation => { + Writable => 1, + Require => 'EXIF:Orientation', + ValueConv => '$val', + PrintConv => \%Image::ExifTool::Exif::orientation, + DelCheck => '""', + WriteCheck => '""', + WriteAlso => { + 'EXIF:Orientation' => '$val', + }, + }, + Rating => { + Writable => 1, + Require => 'XMP-xmp:Rating', + ValueConv => '$val', + DelCheck => '""', + WriteCheck => '""', + WriteAlso => { + 'XMP-xmp:Rating' => '$val', + }, + }, + Copyright => { + Groups => { 2 => 'Author' }, + Writable => 1, + Desire => { + 0 => 'EXIF:Copyright', + 1 => 'IPTC:CopyrightNotice', # (128-character limit) + 2 => 'XMP-dc:Rights', + 3 => 'CurrentIPTCDigest', + 4 => 'IPTCDigest', + }, + RawConv => q{ + return $val[0] if defined $val[0] and $val[0] !~ /^ *$/; + return $val[2] if not defined $val[3] or (defined $val[2] and + (not defined $val[4] or $val[3] eq $val[4])); + return Image::ExifTool::MWG::RecoverTruncatedIPTC($val[1], $val[2], 128); + }, + DelCheck => 'Image::ExifTool::MWG::ReconcileIPTCDigest($self)', + WriteCheck => 'Image::ExifTool::MWG::ReconcileIPTCDigest($self)', + WriteAlso => { + 'EXIF:Copyright' => q{ + # encode if necessary (not automatic because Format is 'undef') + my $enc = $self->Options('CharsetEXIF'); + if ($enc) { + my $v = $val; + $self->Encode($v,$enc); + return $v; + } + return $val; + }, + 'IPTC:CopyrightNotice' => '$opts{EditGroup} = 1; $val', + 'XMP-dc:Rights' => '$val', + }, + }, + Creator => { + Groups => { 2 => 'Author' }, + Flags => ['Writable','List'], + Desire => { + 0 => 'EXIF:Artist', + 1 => 'IPTC:By-line', # (32-character limit) + 2 => 'XMP-dc:Creator', + 3 => 'CurrentIPTCDigest', + 4 => 'IPTCDigest', + }, + RawConv => q{ + return $val[0] if defined $val[0] and $val[0] !~ /^ *$/; + return $val[2] if not defined $val[3] or (defined $val[2] and + (not defined $val[4] or $val[3] eq $val[4])); + return Image::ExifTool::MWG::RecoverTruncatedIPTC($val[1], $val[2], 32); + }, + DelCheck => 'Image::ExifTool::MWG::ReconcileIPTCDigest($self)', + WriteCheck => 'Image::ExifTool::MWG::ReconcileIPTCDigest($self)', + WriteAlso => { + 'EXIF:Artist' => '$val', + 'IPTC:By-line' => '$opts{EditGroup} = 1; $val', + 'XMP-dc:Creator' => '$val', + }, + }, + Country => { + Groups => { 2 => 'Location' }, + Writable => 1, + Desire => { + 0 => 'IPTC:Country-PrimaryLocationName', # (64-character limit) + 1 => 'XMP-photoshop:Country', + 2 => 'XMP-iptcExt:LocationShownCountryName', + 3 => 'CurrentIPTCDigest', + 4 => 'IPTCDigest', + }, + RawConv => q{ + my $xmpVal = $val[2] || $val[1]; + return $xmpVal if not defined $val[3] or (defined $xmpVal and + (not defined $val[4] or $val[3] eq $val[4])); + return Image::ExifTool::MWG::RecoverTruncatedIPTC($val[0], $xmpVal, 64); + }, + DelCheck => 'Image::ExifTool::MWG::ReconcileIPTCDigest($self)', + WriteCheck => 'Image::ExifTool::MWG::ReconcileIPTCDigest($self)', + WriteAlso => { + 'IPTC:Country-PrimaryLocationName' => '$opts{EditGroup} = 1; $val', + 'XMP-photoshop:Country' => '$val', # (legacy) + 'XMP-iptcExt:LocationShownCountryName' => '$val', + }, + }, + State => { + Groups => { 2 => 'Location' }, + Writable => 1, + Desire => { + 0 => 'IPTC:Province-State', # (32-character limit) + 1 => 'XMP-photoshop:State', + 2 => 'XMP-iptcExt:LocationShownProvinceState', + 3 => 'CurrentIPTCDigest', + 4 => 'IPTCDigest', + }, + RawConv => q{ + my $xmpVal = $val[2] || $val[1]; + return $xmpVal if not defined $val[3] or (defined $xmpVal and + (not defined $val[4] or $val[3] eq $val[4])); + return Image::ExifTool::MWG::RecoverTruncatedIPTC($val[0], $xmpVal, 32); + }, + DelCheck => 'Image::ExifTool::MWG::ReconcileIPTCDigest($self)', + WriteCheck => 'Image::ExifTool::MWG::ReconcileIPTCDigest($self)', + WriteAlso => { + 'IPTC:Province-State' => '$opts{EditGroup} = 1; $val', + 'XMP-photoshop:State' => '$val', # (legacy) + 'XMP-iptcExt:LocationShownProvinceState' => '$val', + }, + }, + City => { + Groups => { 2 => 'Location' }, + Writable => 1, + Desire => { + 0 => 'IPTC:City', # (32-character limit) + 1 => 'XMP-photoshop:City', + 2 => 'XMP-iptcExt:LocationShownCity', + 3 => 'CurrentIPTCDigest', + 4 => 'IPTCDigest', + }, + RawConv => q{ + my $xmpVal = $val[2] || $val[1]; + return $xmpVal if not defined $val[3] or (defined $xmpVal and + (not defined $val[4] or $val[3] eq $val[4])); + return Image::ExifTool::MWG::RecoverTruncatedIPTC($val[0], $xmpVal, 32); + }, + DelCheck => 'Image::ExifTool::MWG::ReconcileIPTCDigest($self)', + WriteCheck => 'Image::ExifTool::MWG::ReconcileIPTCDigest($self)', + WriteAlso => { + 'IPTC:City' => '$opts{EditGroup} = 1; $val', + 'XMP-photoshop:City' => '$val', # (legacy) + 'XMP-iptcExt:LocationShownCity' => '$val', + }, + }, + Location => { + Groups => { 2 => 'Location' }, + Writable => 1, + Desire => { + 0 => 'IPTC:Sub-location', # (32-character limit) + 1 => 'XMP-iptcCore:Location', + 2 => 'XMP-iptcExt:LocationShownSublocation', + 3 => 'CurrentIPTCDigest', + 4 => 'IPTCDigest', + }, + RawConv => q{ + my $xmpVal = $val[2] || $val[1]; + return $xmpVal if not defined $val[3] or (defined $xmpVal and + (not defined $val[4] or $val[3] eq $val[4])); + return Image::ExifTool::MWG::RecoverTruncatedIPTC($val[0], $xmpVal, 32); + }, + DelCheck => 'Image::ExifTool::MWG::ReconcileIPTCDigest($self)', + WriteCheck => 'Image::ExifTool::MWG::ReconcileIPTCDigest($self)', + WriteAlso => { + 'IPTC:Sub-location' => '$opts{EditGroup} = 1; $val', + 'XMP-iptcCore:Location' => '$val', # (legacy) + 'XMP-iptcExt:LocationShownSublocation' => '$val', + }, + }, +); + +# MWG XMP structures +my %sExtensions = ( + STRUCT_NAME => 'MWG Extensions', + NAMESPACE => undef, # variable namespace + NOTES => q{ + This structure may contain any top-level XMP tags, but none have been + pre-defined in ExifTool. Since no flattened tags have been pre-defined, + RegionExtensions is writable only as a structure (eg. + C<{xmp-dc:creator=me,rating=5}>). Fields for this structure are identified + using the standard ExifTool tag name (with optional leading group name, + and/or trailing language code, and/or trailing C<#> symbol to disable print + conversion). + }, +); +my %sRegionStruct = ( + STRUCT_NAME => 'MWG RegionStruct', + NAMESPACE => 'mwg-rs', + Area => { Struct => \%Image::ExifTool::XMP::sArea }, + Type => { + PrintConv => { + Face => 'Face', + Pet => 'Pet', + Focus => 'Focus', + BarCode => 'BarCode', + }, + }, + Name => { }, + Description => { }, + FocusUsage => { + PrintConv => { + EvaluatedUsed => 'Evaluated, Used', + EvaluatedNotUsed => 'Evaluated, Not Used', + NotEvaluatedNotUsed => 'Not Evaluated, Not Used', + }, + }, + BarCodeValue=> { }, + Extensions => { Struct => \%sExtensions }, + Rotation => { # (observed in LR6 XMP) + Writable => 'real', + Notes => 'not part of MWG 2.0 spec', + }, + seeAlso => { Namespace => 'rdfs', Resource => 1 }, +); +my %sKeywordStruct; +%sKeywordStruct = ( + STRUCT_NAME => 'MWG KeywordStruct', + NAMESPACE => 'mwg-kw', + Keyword => { }, + Applied => { Writable => 'boolean' }, + Children => { Struct => \%sKeywordStruct, List => 'Bag' }, +); + +# MWG 2.0 XMP region namespace tags +%Image::ExifTool::MWG::Regions = ( + %Image::ExifTool::XMP::xmpTableDefaults, + GROUPS => { 0 => 'XMP', 1 => 'XMP-mwg-rs', 2 => 'Image' }, + NAMESPACE => 'mwg-rs', + NOTES => q{ + Image region metadata defined by the MWG 2.0 specification. These tags + may be accessed without the need to load the MWG Composite tags above. See + L<http://www.metadataworkinggroup.org/> for the official specification. + }, + Regions => { + Name => 'RegionInfo', + FlatName => 'Region', + Struct => { + STRUCT_NAME => 'MWG RegionInfo', + NAMESPACE => 'mwg-rs', + RegionList => { + FlatName => 'Region', + Struct => \%sRegionStruct, + List => 'Bag', + }, + AppliedToDimensions => { Struct => \%Image::ExifTool::XMP::sDimensions }, + }, + }, + RegionsRegionList => { Flat => 1, Name => 'RegionList' }, +); + +# MWG 2.0 XMP hierarchical keyword namespace tags +%Image::ExifTool::MWG::Keywords = ( + %Image::ExifTool::XMP::xmpTableDefaults, + GROUPS => { 0 => 'XMP', 1 => 'XMP-mwg-kw', 2 => 'Image' }, + NAMESPACE => 'mwg-kw', + NOTES => q{ + Hierarchical keywords metadata defined by the MWG 2.0 specification. + ExifTool unrolls keyword structures to an arbitrary depth of 6 to allow + individual levels to be accessed with different tag names, and to avoid + infinite recursion. See L<http://www.metadataworkinggroup.org/> for the + official specification. + }, + # arbitrarily define only the first 6 levels of the keyword hierarchy + Keywords => { + Name => 'KeywordInfo', + Struct => { + STRUCT_NAME => 'MWG KeywordInfo', + NAMESPACE => 'mwg-kw', + Hierarchy => { Struct => \%sKeywordStruct, List => 'Bag' }, + }, + }, + KeywordsHierarchy => { Name => 'HierarchicalKeywords', Flat => 1 }, + KeywordsHierarchyKeyword => { Name => 'HierarchicalKeywords1', Flat => 1 }, + KeywordsHierarchyApplied => { Name => 'HierarchicalKeywords1Applied', Flat => 1 }, + KeywordsHierarchyChildren => { Name => 'HierarchicalKeywords1Children', Flat => 1 }, + KeywordsHierarchyChildrenKeyword => { Name => 'HierarchicalKeywords2', Flat => 1 }, + KeywordsHierarchyChildrenApplied => { Name => 'HierarchicalKeywords2Applied', Flat => 1 }, + KeywordsHierarchyChildrenChildren => { Name => 'HierarchicalKeywords2Children', Flat => 1 }, + KeywordsHierarchyChildrenChildrenKeyword => { Name => 'HierarchicalKeywords3', Flat => 1 }, + KeywordsHierarchyChildrenChildrenApplied => { Name => 'HierarchicalKeywords3Applied', Flat => 1 }, + KeywordsHierarchyChildrenChildrenChildren => { Name => 'HierarchicalKeywords3Children', Flat => 1 }, + KeywordsHierarchyChildrenChildrenChildrenKeyword => { Name => 'HierarchicalKeywords4', Flat => 1 }, + KeywordsHierarchyChildrenChildrenChildrenApplied => { Name => 'HierarchicalKeywords4Applied', Flat => 1 }, + KeywordsHierarchyChildrenChildrenChildrenChildren => { Name => 'HierarchicalKeywords4Children', Flat => 1 }, + KeywordsHierarchyChildrenChildrenChildrenChildrenKeyword => { Name => 'HierarchicalKeywords5', Flat => 1 }, + KeywordsHierarchyChildrenChildrenChildrenChildrenApplied => { Name => 'HierarchicalKeywords5Applied', Flat => 1 }, + KeywordsHierarchyChildrenChildrenChildrenChildrenChildren => { Name => 'HierarchicalKeywords5Children', Flat => 1, NoSubStruct => 1 }, # break infinite recursion + KeywordsHierarchyChildrenChildrenChildrenChildrenChildrenKeyword => { Name => 'HierarchicalKeywords6', Flat => 1 }, + KeywordsHierarchyChildrenChildrenChildrenChildrenChildrenApplied => { Name => 'HierarchicalKeywords6Applied', Flat => 1 }, +); + +# MWG 2.0 XMP collections namespace tags +%Image::ExifTool::MWG::Collections = ( + %Image::ExifTool::XMP::xmpTableDefaults, + GROUPS => { 0 => 'XMP', 1 => 'XMP-mwg-coll', 2 => 'Image' }, + NAMESPACE => 'mwg-coll', + NOTES => q{ + Collections metadata defined by the MWG 2.0 specification. See + L<http://www.metadataworkinggroup.org/> for the official specification. + }, + Collections => { + FlatName => '', + List => 'Bag', + Struct => { + STRUCT_NAME => 'MWG CollectionInfo', + NAMESPACE => 'mwg-coll', + CollectionName => { }, + CollectionURI => { }, + }, + }, +); + + +#------------------------------------------------------------------------------ +# Load the MWG Composite tags +sub Load() +{ + return if $mwgLoaded; + + # add our composite tags + Image::ExifTool::AddCompositeTags('Image::ExifTool::MWG'); + # must also add to lookup so we can write them + # (since MWG tags aren't in the tag lookup by default) + Image::ExifTool::AddTagsToLookup(\%Image::ExifTool::MWG::Composite, + 'Image::ExifTool::Composite'); + + # modify EXIF:Artist to behave as a list-type tag + my $artist = $Image::ExifTool::Exif::Main{0x13b}; + $$artist{List} = 1; + $$artist{IsOverwriting} = \&OverwriteStringList; + $$artist{RawConv} = \&StringToList; + + # enable MWG strict mode if not set already + # (causes non-standard EXIF, IPTC and XMP to be ignored) + $Image::ExifTool::MWG::strict = 1 unless defined $Image::ExifTool::MWG::strict; + + $mwgLoaded = 1; +} + +#------------------------------------------------------------------------------ +# Change a list of values to a string using MWG rules +# Inputs: 0)reference to list of values +# Returns: string of values (and may reformat list entries) +sub ListToString($) +{ + my $vals = shift; + foreach (@$vals) { + # double all quotes in value and quote the value if it begins + # with a quote or contains a semicolon-space separator + if (/^"/ or /; /) { + s/"/""/g; # double all quotes + $_ = qq{"$_"}; # quote the value + } + } + return join('; ', @$vals); +} + +#------------------------------------------------------------------------------ +# Change a string value to a list of values using MWG rules +# Inputs: 0) string of values, 1) ExifTool ref +# Returns: value or list reference if more than one value +# Notes: Sets Warning tag on error +sub StringToList($$) +{ + my ($str, $et) = @_; + my (@vals, $inQuotes); + my @t = split '; ', $str, -1; + foreach (@t) { + my $wasQuotes = $inQuotes; + $inQuotes = 1 if not $inQuotes and s/^"//; + if ($inQuotes) { + # remove the last quote and reset the inQuotes flag if + # the value ended in an odd number of quotes + $inQuotes = 0 if s/((^|[^"])("")*)"$/$1/; + s/""/"/g; # un-double the contained quotes + } + if ($wasQuotes) { + # previous separator was quoted, so concatinate with previous value + $vals[-1] .= '; ' . $_; + } else { + push @vals, $_; + } + } + $et->Warn('Incorrectly quoted MWG string-list value') if $inQuotes; + return @vals > 1 ? \@vals : $vals[0]; +} + +#------------------------------------------------------------------------------ +# Handle logic for overwriting EXIF string-type list tag +# Inputs: 0) ExifTool ref, 1) new value hash ref, +# 2) old string value (or undef if it didn't exist), 3) new value ref +# Returns: 1 and sets the new value for the tag +sub OverwriteStringList($$$$) +{ + local $_; + my ($et, $nvHash, $val, $newValuePt) = @_; + my (@new, $delIndex); + if ($$nvHash{DelValue} and defined $val) { + # preserve specified old values + my $old = StringToList($val, $et); + my @old = ref $old eq 'ARRAY' ? @$old : $old; + if (@{$$nvHash{DelValue}}) { + my %del; + $del{$_} = 1 foreach @{$$nvHash{DelValue}}; + foreach (@old) { + $del{$_} or push(@new, $_), next; + $delIndex or $delIndex = scalar @new; + } + } else { + push @new, @old; + } + } + # add new values (at location of deleted values, if any) + if ($$nvHash{Value}) { + if (defined $delIndex) { + splice @new, $delIndex, 0, @{$$nvHash{Value}}; + } else { + push @new, @{$$nvHash{Value}}; + } + } + if (@new) { + # convert back to string format + $$newValuePt = ListToString(\@new); + } else { + $$newValuePt = undef; # delete the tag + } + return 1; +} + +#------------------------------------------------------------------------------ +# Reconcile IPTC digest after writing an MWG tag +# Inputs: 0) ExifTool object ref +# Returns: empty string +sub ReconcileIPTCDigest($) +{ + my $et = shift; + + # set new value for IPTCDigest if not done already + unless ($Image::ExifTool::Photoshop::iptcDigestInfo and + $$et{NEW_VALUE}{$Image::ExifTool::Photoshop::iptcDigestInfo}) + { + # write new IPTCDigest only if it doesn't exist or + # is the same as the digest of the original IPTC + my @a; # (capture warning messages) + @a = $et->SetNewValue('Photoshop:IPTCDigest', 'old', Protected => 1, DelValue => 1); + @a = $et->SetNewValue('Photoshop:IPTCDigest', 'new', Protected => 1); + } + return ''; +} + +#------------------------------------------------------------------------------ +# Recover strings which were truncated by IPTC dataset length limit +# Inputs: 0) IPTC value, 1) XMP value, 2) length limit +# Notes: handles the case where IPTC and/or XMP values are lists +sub RecoverTruncatedIPTC($$$) +{ + my ($iptc, $xmp, $limit) = @_; + + return $iptc unless defined $xmp; + if (ref $iptc) { + $xmp = [ $xmp ] unless ref $xmp; + my ($i, @vals); + for ($i=0; $i<@$iptc; ++$i) { + push @vals, RecoverTruncatedIPTC($$iptc[$i], $$xmp[$i], $limit); + } + return \@vals; + } elsif (defined $iptc and length $iptc == $limit) { + $xmp = $$xmp[0] if ref $xmp; # take first element of list + return $xmp if length $xmp > $limit and $iptc eq substr($xmp, 0, $limit); + } + return $iptc; +} + +1; # end + +__END__ + +=head1 NAME + +Image::ExifTool::MWG - Metadata Working Group support + +=head1 SYNOPSIS + + # enable MWG Composite tags + use Image::ExifTool::MWG; + Image::ExifTool::MWG::Load(); + + # enable MWG strict mode + $Image::ExifTool::MWG::strict = 1; + + # disable MWG strict mode + $Image::ExifTool::MWG::strict = 0; + +=head1 DESCRIPTION + +The MWG module contains Composite tag definitions which are designed to +simplify implementation of the Metadata Working Group guidelines. These +special MWG Composite tags are enabled by calling the Load() method: + + use Image::ExifTool::MWG; + Image::ExifTool::MWG::Load(); + +By default, loading the MWG Composite tags enables "strict MWG conformance" +unless previously enabled or disabled by the user. In this mode, ExifTool +will generate a Warning instead of extracting EXIF, IPTC and XMP from +non-standard locations. The strict mode may be disabled or enabled at any +time by setting the MWG "strict" flag to 0 or 1. eg) + + $Image::ExifTool::MWG::strict = 0; + +This module also contains the MWG XMP tags which are loaded automatically by +ExifTool as required, and are independent of the MWG Composite tags which +must be loaded explicitly as described above. + +=head1 AUTHOR + +Copyright 2003-2019, Phil Harvey (phil at owl.phy.queensu.ca) + +This library is free software; you can redistribute it and/or modify it +under the same terms as Perl itself. + +=head1 REFERENCES + +=over 4 + +=item L<http://www.metadataworkinggroup.org/> + +=back + +=head1 SEE ALSO + +L<Image::ExifTool::TagNames/MWG Tags>, +L<Image::ExifTool(3pm)|Image::ExifTool> + +=cut diff --git a/lib/Image/ExifTool/MXF.pm b/lib/Image/ExifTool/MXF.pm new file mode 100644 index 0000000..f7c4540 --- /dev/null +++ b/lib/Image/ExifTool/MXF.pm @@ -0,0 +1,3031 @@ +#------------------------------------------------------------------------------ +# File: MXF.pm +# +# Description: Read MXF meta information +# +# Revisions: 2010/12/15 - P. Harvey Created +# +# References: 1) http://sourceforge.net/projects/mxflib/ +# 2) http://www.aafassociation.org/downloads/whitepapers/MXFPhysicalview.pdf +# 3) http://archive.nlm.nih.gov/pubs/pearson/MJ2_Metadata2005.pdf +# 4) http://www.aafassociation.org/downloads/specifications/AMWA-AS-03-Delivery-Spec-1_0.pdf +# 5) http://paul-sampson.ca/private/s385m.pdf +# 6) http://avwiki.nl/documents/eg41.pdf +# 7) http://avwiki.nl/documents/eg42.pdf +# 8) http://rhea.tele.ucl.ac.be:8081/Plone/Members/egoray/thesaurus-dictionnaire-metadata/ +# a) S335M Dictionary structure.pdf +# b) S330M UMID.PDF +# 9) http://www.smpte-ra.org/mdd/RP210v12-publication-20100623.xls +# 10) http://www.amwa.tv/downloads/specifications/aafobjectspec-v1.1.pdf +# 11) http://www.mog-solutions.com/img_upload/PDF/XML%20Schema%20for%20MXF%20Metadata.pdf +# 12) http://www.freemxf.org/freemxf_board/viewtopic.php?p=545&sid=00a5c17e07d828c1e93ecdbaed3076f7 +# +# Notes: 1) The alternate language support is dependent on the serialization +# sequence. Specifically the InstanceUID's must come before any +# text in an alternate language set, and these sets must come +# after the language definitions. +# +# 2) UTF-16 surrogate pairs are not handled properly. +# +# 3) This code is not tested for files larger than 2 GB, +# but in theory this should be OK with 64-bit Perl. +#------------------------------------------------------------------------------ + +package Image::ExifTool::MXF; + +use strict; +use vars qw($VERSION); +use Image::ExifTool qw(:DataAccess :Utils); +use Image::ExifTool::GPS; + +$VERSION = '1.08'; + +sub ProcessPrimer($$$); +sub ProcessLocalSet($$$); +sub ConvLatLon($); +sub ReadMXFValue($$$); +sub SetGroups($$;$$); +sub ConvertDurations($$); + +# list of currently decoded MXF value types +my %knownType = ( + Alt => 1, Lon => 1, UL => 1, + AUID => 1, PackageID => 1, UMID => 1, + BatchOfUL => 1, Position => 1, 'UTF-16' => 1, + Boolean => 1, ProductVersion => 1, UUID => 1, + GUID => 1, StrongReference => 1, VersionType => 1, + Hex => 1, StrongReferenceArray => 1, WeakReference => 1, + Label => 1, StrongReferenceBatch => 1, + Lat => 1, Timestamp => 1, + Length => 1, UID => 1, +); + +# common tag info parameters +my %header = ( + IsHeader => 1, + SubDirectory => { + TagTable => 'Image::ExifTool::MXF::Header', + ProcessProc => \&Image::ExifTool::ProcessBinaryData, + }, +); +my %localSet = ( + SubDirectory => { TagTable => 'Image::ExifTool::MXF::Main' }, +); +my %timestamp = ( + Type => 'Timestamp', + Groups => { 2 => 'Time' }, + PrintConv => '$self->ConvertDateTime($val)', +); +my %geoLat = ( + Groups => { 2 => 'Location' }, + PrintConv => 'Image::ExifTool::GPS::ToDMS($self, $val, 1, "N")', +); +my %geoLon = ( + Groups => { 2 => 'Location' }, + PrintConv => 'Image::ExifTool::GPS::ToDMS($self, $val, 1, "E")', +); +my %geoLatLon = ( + Groups => { 2 => 'Location' }, + PrintConv => q{ + my ($lat, $lon) = split ' ', $val; + $lat = Image::ExifTool::GPS::ToDMS($self, $lat, 1, 'N'); + $lon = Image::ExifTool::GPS::ToDMS($self, $lon, 1, 'E'); + return "$lat, $lon"; + }, +); +my %duration = ( + IsDuration => 1, # flag used to correct durations by the appropriate EditRate + RawConv => '$val > 1e18 ? undef : $val', # (all 0xff's) + PrintConv => 'ConvertDuration($val)', +); + +# ComponentDataDefinition values +my %componentDataDef = ( + PrintConv => { + '060e2b34.0401.0101.01030201.01000000' => 'SMPTE 12M Timecode Track', + '060e2b34.0401.0101.01030201.02000000' => 'SMPTE 12M Timecode Track with active user bits', + '060e2b34.0401.0101.01030201.03000000' => 'SMPTE 309M Timecode Track', + '060e2b34.0401.0101.01030201.10000000' => 'Descriptive Metadata Track', + '060e2b34.0401.0101.01030202.01000000' => 'Picture Essence Track', + '060e2b34.0401.0101.01030202.02000000' => 'Sound Essence Track', + '060e2b34.0401.0101.01030202.03000000' => 'Data Essence Track', + }, +); + +# MXF tags (ref 1) +# Note: The Binary flag is automatically set for all Unknown tags with unknown Type +%Image::ExifTool::MXF::Main = ( + GROUPS => { 2 => 'Video' }, + VARS => { NO_LOOKUP => 1, NO_ID => 1 }, # tag ID's are too bulky + NOTES => q{ + Tags extracted from Material Exchange Format files. Tag ID's are not listed + because they are bulky 16-byte binary values. + }, + # '060a2b34.0101.0101.01010100.00000000' => { Name => 'UMIDVideo', Type => 'Node' }, + # '060a2b34.0101.0101.01010110.00000000' => { Name => 'UMIDVideo', Unknown => 1 }, + # '060a2b34.0101.0101.01010111.00000000' => { Name => 'UMIDVideo', Unknown => 1 }, + # '060a2b34.0101.0101.01010112.00000000' => { Name => 'UMIDVideo', Unknown => 1 }, + # '060a2b34.0101.0101.01010120.00000000' => { Name => 'UMIDVideo', Unknown => 1 }, + # '060a2b34.0101.0101.01010121.00000000' => { Name => 'UMIDVideo', Unknown => 1 }, + # '060a2b34.0101.0101.01010122.00000000' => { Name => 'UMIDVideo', Unknown => 1 }, + # '060a2b34.0101.0101.01010200.00000000' => { Name => 'UMIDAudio', Type => 'Node' }, + # '060a2b34.0101.0101.01010210.00000000' => { Name => 'UMIDAudio', Unknown => 1 }, + # '060a2b34.0101.0101.01010211.00000000' => { Name => 'UMIDAudio', Unknown => 1 }, + # '060a2b34.0101.0101.01010212.00000000' => { Name => 'UMIDAudio', Unknown => 1 }, + # '060a2b34.0101.0101.01010220.00000000' => { Name => 'UMIDAudio', Unknown => 1 }, + # '060a2b34.0101.0101.01010221.00000000' => { Name => 'UMIDAudio', Unknown => 1 }, + # '060a2b34.0101.0101.01010222.00000000' => { Name => 'UMIDAudio', Unknown => 1 }, + # '060a2b34.0101.0101.01010300.00000000' => { Name => 'UMIDData', Type => 'Node' }, + # '060a2b34.0101.0101.01010310.00000000' => { Name => 'UMIDData', Unknown => 1 }, + # '060a2b34.0101.0101.01010311.00000000' => { Name => 'UMIDData', Unknown => 1 }, + # '060a2b34.0101.0101.01010312.00000000' => { Name => 'UMIDData', Unknown => 1 }, + # '060a2b34.0101.0101.01010320.00000000' => { Name => 'UMIDData', Unknown => 1 }, + # '060a2b34.0101.0101.01010321.00000000' => { Name => 'UMIDData', Unknown => 1 }, + # '060a2b34.0101.0101.01010322.00000000' => { Name => 'UMIDData', Unknown => 1 }, + # '060a2b34.0101.0101.01010400.00000000' => { Name => 'UMIDSystem', Type => 'Node' }, + # '060a2b34.0101.0101.01010410.00000000' => { Name => 'UMIDSystem', Unknown => 1 }, + # '060a2b34.0101.0101.01010411.00000000' => { Name => 'UMIDSystem', Unknown => 1 }, + # '060a2b34.0101.0101.01010412.00000000' => { Name => 'UMIDSystem', Unknown => 1 }, + # '060a2b34.0101.0101.01010420.00000000' => { Name => 'UMIDSystem', Unknown => 1 }, + # '060a2b34.0101.0101.01010421.00000000' => { Name => 'UMIDSystem', Unknown => 1 }, + # '060a2b34.0101.0101.01010422.00000000' => { Name => 'UMIDSystem', Unknown => 1 }, + + # '060e2b34.0101.0101.00000000.00000000' => { Name => 'Elements', Type => 'Node' }, + # '060e2b34.0101.0101.01000000.00000000' => { Name => 'Identifiers', Type => 'Node' }, + # '060e2b34.0101.0101.01010000.00000000' => { Name => 'GloballyUniqueIdentifiers', Type => 'Node' }, + # '060e2b34.0101.0101.01011000.00000000' => { Name => 'InternationalBroadcastingOrganizationIdentifiers', Type => 'Node' }, + '060e2b34.0101.0101.01011001.00000000' => { Name => 'OrganizationID', Format => 'string' }, + # '060e2b34.0101.0101.01011003.00000000' => { Name => 'ProgramIdentifiers', Type => 'Node' }, + '060e2b34.0101.0101.01011003.01000000' => { Name => 'UPID', Unknown => 1 }, + '060e2b34.0101.0101.01011003.02000000' => { Name => 'UPN', Unknown => 1 }, + # '060e2b34.0101.0101.01011004.00000000' => { Name => 'PhysicalMediaIdentifiers', Type => 'Node' }, + # '060e2b34.0101.0101.01011004.01000000' => { Name => 'TapeIdentifiers', Type => 'Node' }, + '060e2b34.0101.0101.01011004.01010000' => { Name => 'IBTN', Unknown => 1 }, + # '060e2b34.0101.0101.01011100.00000000' => { Name => 'InternationalStandardIdentifiers', Type => 'Node' }, + '060e2b34.0101.0101.01011101.00000000' => { Name => 'ISAN', Unknown => 1 }, + '060e2b34.0101.0101.01011102.00000000' => { Name => 'ISBN', Unknown => 1 }, + '060e2b34.0101.0101.01011103.00000000' => { Name => 'ISSN', Unknown => 1 }, + '060e2b34.0101.0101.01011104.00000000' => { Name => 'ISWC', Unknown => 1 }, + '060e2b34.0101.0101.01011105.00000000' => { Name => 'ISMN', Unknown => 1 }, + '060e2b34.0101.0101.01011106.00000000' => { Name => 'ISCI', Unknown => 1 }, + '060e2b34.0101.0101.01011107.00000000' => { Name => 'ISRC', Unknown => 1 }, + '060e2b34.0101.0101.01011108.00000000' => { Name => 'ISRN', Unknown => 1 }, + '060e2b34.0101.0101.01011109.00000000' => { Name => 'ISBD', Unknown => 1 }, + '060e2b34.0101.0101.0101110a.00000000' => { Name => 'ISTC', Unknown => 1 }, + # '060e2b34.0101.0101.01011300.00000000' => { Name => 'InternationalStandardCompoundIdentifiers', Type => 'Node' }, + '060e2b34.0101.0101.01011301.00000000' => { Name => 'SICI', Unknown => 1 }, + '060e2b34.0101.0101.01011302.00000000' => { Name => 'BICI', Unknown => 1 }, + '060e2b34.0101.0101.01011303.00000000' => { Name => 'AICI', Unknown => 1 }, + '060e2b34.0101.0101.01011304.00000000' => { Name => 'PII', Unknown => 1 }, + # '060e2b34.0101.0101.01011500.00000000' => { Name => 'ObjectIdentifiers', Type => 'Node' }, + '060e2b34.0101.0101.01011501.00000000' => { Name => 'DOI', Unknown => 1 }, + '060e2b34.0101.0101.01011502.00000000' => { Name => 'InstanceUID', Type => 'GUID', Unknown => 1 }, + '060e2b34.0101.0101.01011510.00000000' => { Name => 'PackageID', Type => 'PackageID', Unknown => 1 }, + # '060e2b34.0101.0101.01012000.00000000' => { Name => 'DeviceIdentifiers', Type => 'Node' }, + '060e2b34.0101.0101.01012001.00000000' => { Name => 'DeviceDesignation', Format => 'string' }, + '060e2b34.0101.0101.01012003.00000000' => { Name => 'DeviceModel', Format => 'string' }, + '060e2b34.0101.0101.01012004.00000000' => { Name => 'DeviceSerialNumber', Format => 'string' }, + # '060e2b34.0101.0101.01020000.00000000' => { Name => 'GloballyUniqueLocators', Type => 'Node' }, + # '060e2b34.0101.0101.01020100.00000000' => { Name => 'UniformResourceLocators', Type => 'Node' }, + '060e2b34.0101.0101.01020101.00000000' => { Name => 'URL', Format => 'string' }, + '060e2b34.0101.0101.01020101.01000000' => { Name => 'URL', Type => 'UTF-16' }, + '060e2b34.0101.0101.01020102.00000000' => { Name => 'PURL', Format => 'string' }, + '060e2b34.0101.0101.01020103.00000000' => { Name => 'URN', Format => 'string' }, + # '060e2b34.0101.0101.01030000.00000000' => { Name => 'LocallyUniqueIdentifiers', Type => 'Node' }, + # '060e2b34.0101.0101.01030100.00000000' => { Name => 'AdministrativeIdentifiers', Type => 'Node' }, + '060e2b34.0101.0101.01030101.00000000' => { Name => 'TransmissionID', Format => 'string' }, + '060e2b34.0101.0101.01030102.00000000' => { Name => 'ArchiveID', Format => 'string' }, + '060e2b34.0101.0101.01030103.00000000' => { Name => 'ItemID', Format => 'string' }, + '060e2b34.0101.0101.01030104.00000000' => { Name => 'AccountingReferenceNumber', Format => 'string' }, + '060e2b34.0101.0101.01030105.00000000' => { Name => 'TrafficID', Format => 'string' }, + # '060e2b34.0101.0101.01030200.00000000' => { Name => 'LocalPhysicalMediaIdentifiers', Type => 'Node' }, + # '060e2b34.0101.0101.01030201.00000000' => { Name => 'LocalFilmID', Type => 'Node' }, + '060e2b34.0101.0101.01030201.01000000' => { Name => 'ReelOrRollNumber', Format => 'string' }, + # '060e2b34.0101.0101.01030202.00000000' => { Name => 'LocalTapeIdentifiers', Type => 'Node' }, + '060e2b34.0101.0101.01030202.01000000' => { Name => 'LocalTapeNumber', Format => 'string' }, + # '060e2b34.0101.0101.01030300.00000000' => { Name => 'LocalObjectIdentifiers', Type => 'Node' }, + '060e2b34.0101.0101.01030301.00000000' => { Name => 'LUID', Format => 'int32u' }, + '060e2b34.0101.0101.01030302.01000000' => { Name => 'PackageName', Type => 'UTF-16' }, + # '060e2b34.0101.0101.01040000.00000000' => { Name => 'LocallyUniqueLocators', Type => 'Node' }, + # '060e2b34.0101.0101.01040100.00000000' => { Name => 'MediaLocators', Type => 'Node' }, + '060e2b34.0101.0101.01040101.00000000' => { Name => 'LocalFilePath', Format => 'string' }, + # '060e2b34.0101.0101.01040700.00000000' => { Name => 'FilmLocators', Type => 'Node' }, + '060e2b34.0101.0101.01040701.00000000' => { Name => 'EdgeCode', Format => 'string' }, + '060e2b34.0101.0101.01040702.00000000' => { Name => 'FrameCode', Format => 'string' }, + '060e2b34.0101.0101.01040703.00000000' => { Name => 'KeyCode', Type => 'KeyCode', Unknown => 1 }, + '060e2b34.0101.0101.01040704.00000000' => { Name => 'InkNumber', Format => 'string' }, + # '060e2b34.0101.0101.01041000.00000000' => { Name => 'ProxyLocators', Type => 'Node' }, + '060e2b34.0101.0101.01041001.00000000' => { Name => 'KeyText', Format => 'string' }, + '060e2b34.0101.0101.01041002.00000000' => { Name => 'KeyFrame', Format => 'string' }, + '060e2b34.0101.0101.01041003.00000000' => { Name => 'KeySound', Format => 'string' }, + '060e2b34.0101.0101.01041004.00000000' => { Name => 'KeyDataOrProgram', Format => 'string' }, + # '060e2b34.0101.0101.01050000.00000000' => { Name => 'Titles', Type => 'Node' }, + '060e2b34.0101.0101.01050100.00000000' => { Name => 'TitleKind', Format => 'string' }, + '060e2b34.0101.0101.01050200.00000000' => { Name => 'MainTitle', Format => 'string' }, + '060e2b34.0101.0101.01050300.00000000' => { Name => 'SecondaryTitle', Format => 'string' }, + '060e2b34.0101.0101.01050400.00000000' => { Name => 'SeriesNumber', Format => 'string' }, + '060e2b34.0101.0101.01050500.00000000' => { Name => 'EpisodeNumber', Format => 'string' }, + '060e2b34.0101.0101.01050600.00000000' => { Name => 'SceneNumber', Format => 'string' }, + '060e2b34.0101.0101.01050700.00000000' => { Name => 'TakeNumber', Format => 'int16u' }, + # '060e2b34.0101.0101.01100000.00000000' => { Name => 'IntellectualPropertyRightsIdentifiers', Type => 'Node' }, + # '060e2b34.0101.0101.01100100.00000000' => { Name => 'SUISACISACIPI', Type => 'Node' }, + '060e2b34.0101.0101.01100101.00000000' => { Name => 'CISACLegalEntityID', Unknown => 1 }, + # '060e2b34.0101.0101.01100200.00000000' => { Name => 'AGICOAIdentifers', Type => 'Node' }, + '060e2b34.0101.0101.01100201.00000000' => { Name => 'AGICOAID', Unknown => 1 }, + # '060e2b34.0101.0101.02000000.00000000' => { Name => 'ADMINISTRATION', Type => 'Node' }, + # '060e2b34.0101.0101.02010000.00000000' => { Name => 'Supplier', Type => 'Node' }, + '060e2b34.0101.0101.02010100.00000000' => { Name => 'SourceOrganization', Format => 'string' }, + '060e2b34.0101.0101.02010200.00000000' => { Name => 'SupplyContractNumber', Format => 'string' }, + '060e2b34.0101.0101.02010300.00000000' => { Name => 'OriginalProducerName', Format => 'string' }, + # '060e2b34.0101.0101.02020000.00000000' => { Name => 'Product', Type => 'Node' }, + '060e2b34.0101.0101.02020100.00000000' => { Name => 'TotalEpisodeCount', Format => 'int16u' }, + # '060e2b34.0101.0101.02050000.00000000' => { Name => 'Rights', Type => 'Node' }, + # '060e2b34.0101.0101.02050100.00000000' => { Name => 'Copyright', Type => 'Node' }, + '060e2b34.0101.0101.02050101.00000000' => { Name => 'CopyrightStatus', Format => 'string' }, + '060e2b34.0101.0101.02050102.00000000' => { Name => 'CopyrightOwnerName', Format => 'string' }, + # '060e2b34.0101.0101.02050200.00000000' => { Name => 'IntellectualRights', Type => 'Node' }, + '060e2b34.0101.0101.02050201.00000000' => { Name => 'IntellectualPropertyDescription', Format => 'string' }, + '060e2b34.0101.0101.02050202.00000000' => { Name => 'IntellectualPropertyRights', Format => 'string' }, + # '060e2b34.0101.0101.02050300.00000000' => { Name => 'LegalPersonalities', Type => 'Node' }, + '060e2b34.0101.0101.02050301.00000000' => { Name => 'Rightsholder', Format => 'string' }, + '060e2b34.0101.0101.02050302.00000000' => { Name => 'RightsManagementAuthority', Format => 'string' }, + '060e2b34.0101.0101.02050303.00000000' => { Name => 'InterestedPartyName', Format => 'string' }, + # '060e2b34.0101.0101.02050400.00000000' => { Name => 'IntellectualPropertyRightsOptions', Type => 'Node' }, + '060e2b34.0101.0101.02050401.00000000' => { Name => 'MaximumUseCount', Format => 'int16u' }, + '060e2b34.0101.0101.02050402.00000000' => { Name => 'LicenseOptionsDescription', Format => 'string' }, + # '060e2b34.0101.0101.02060000.00000000' => { Name => 'FinancialInformation', Type => 'Node' }, + # '060e2b34.0101.0101.02060100.00000000' => { Name => 'Currencies', Type => 'Node' }, + '060e2b34.0101.0101.02060101.00000000' => { Name => 'CurrencyCode', Format => 'string' }, + # '060e2b34.0101.0101.02060200.00000000' => { Name => 'PaymentsAndCosts', Type => 'Node' }, + '060e2b34.0101.0101.02060201.00000000' => { Name => 'RoyaltyPaymentInformation', Format => 'string' }, + # '060e2b34.0101.0101.02060300.00000000' => { Name => 'Income', Type => 'Node' }, + '060e2b34.0101.0101.02060301.00000000' => { Name => 'RoyaltyIncomeInformation', Format => 'string' }, + # '060e2b34.0101.0101.02070000.00000000' => { Name => 'AccessControl', Type => 'Node' }, + '060e2b34.0101.0101.02070100.00000000' => { Name => 'RestrictionsonUse', Format => 'string' }, + '060e2b34.0101.0101.02070200.00000000' => { Name => 'ExCCIData', Type => 'DataBlock', Unknown => 1 }, + # '060e2b34.0101.0101.02080000.00000000' => { Name => 'Security', Type => 'Node' }, + # '060e2b34.0101.0101.02080100.00000000' => { Name => 'SystemAccess', Type => 'Node' }, + '060e2b34.0101.0101.02080101.00000000' => { Name => 'UserName', Format => 'string' }, + '060e2b34.0101.0101.02080101.01000000' => { Name => 'UserName', Type => 'UTF-16' }, + '060e2b34.0101.0101.02080102.00000000' => { Name => 'Password', Format => 'string' }, + '060e2b34.0101.0101.02080102.01000000' => { Name => 'Password', Type => 'UTF-16' }, + # '060e2b34.0101.0101.02090000.00000000' => { Name => 'Encryption', Type => 'Node' }, + # '060e2b34.0101.0101.02090100.00000000' => { Name => 'FilmEncryption', Type => 'Node' }, + # '060e2b34.0101.0101.02090101.00000000' => { Name => 'ScramblingKeys', Type => 'Node' }, + '060e2b34.0101.0101.02090101.01000000' => { Name => 'ScramblingKeyKind', Format => 'string' }, + '060e2b34.0101.0101.02090101.02000000' => { Name => 'ScramblingKeyValue', Format => 'int8u' }, + # '060e2b34.0101.0101.02100000.00000000' => { Name => 'PublicationOutlet', Type => 'Node' }, + # '060e2b34.0101.0101.02100100.00000000' => { Name => 'Broadcast', Type => 'Node' }, + # '060e2b34.0101.0101.02100101.00000000' => { Name => 'Broadcaster', Type => 'Node' }, + '060e2b34.0101.0101.02100101.01000000' => { Name => 'BroadcastOrganizationName', Format => 'string' }, + '060e2b34.0101.0101.02100101.02000000' => { Name => 'BroadcastChannel', Format => 'string' }, + '060e2b34.0101.0101.02100101.03000000' => { Name => 'BroadcastMediumKind', Format => 'string' }, + '060e2b34.0101.0101.02100101.05000000' => { Name => 'BroadcastRegion', Format => 'string' }, + # '060e2b34.0101.0101.02200000.00000000' => { Name => 'BroadcastAndRepeatInformation', Type => 'Node' }, + # '060e2b34.0101.0101.02200100.00000000' => { Name => 'BroadcastFlags', Type => 'Node' }, + '060e2b34.0101.0101.02200101.00000000' => { Name => 'FirstBroadcastFlag', Type => 'Boolean' }, + # '060e2b34.0101.0101.02200200.00000000' => { Name => 'RepeatNumbers', Type => 'Node' }, + '060e2b34.0101.0101.02200201.00000000' => { Name => 'CurrentRepeatNumber', Format => 'int16u' }, + '060e2b34.0101.0101.02200202.00000000' => { Name => 'PreviousRepeatNumber', Format => 'int16u' }, + # '060e2b34.0101.0101.02200300.00000000' => { Name => 'Ratings', Type => 'Node' }, + '060e2b34.0101.0101.02200301.00000000' => { Name => 'AudienceRating', Format => 'int32u' }, + '060e2b34.0101.0101.02200302.00000000' => { Name => 'AudienceReach', Format => 'int32u' }, + # '060e2b34.0101.0101.02300000.00000000' => { Name => 'ParticipatingParties', Type => 'Node' }, + # '060e2b34.0101.0101.02300100.00000000' => { Name => 'IndividualsAndGroups', Type => 'Node' }, + '060e2b34.0101.0101.02300101.00000000' => { Name => 'NatureOfPersonality', Format => 'string' }, + # '060e2b34.0101.0101.02300102.00000000' => { Name => 'Production', Type => 'Node' }, + '060e2b34.0101.0101.02300102.01000000' => { Name => 'ContributionStatus', Format => 'string' }, + # '060e2b34.0101.0101.02300103.00000000' => { Name => 'SupportAndAdministrationDetails', Type => 'Node' }, + '060e2b34.0101.0101.02300103.01000000' => { Name => 'SupportOrAdministrationStatus', Format => 'string' }, + # '060e2b34.0101.0101.02300200.00000000' => { Name => 'OrganizationsAndPublicBodies', Type => 'Node' }, + '060e2b34.0101.0101.02300201.00000000' => { Name => 'OrganizationKind', Format => 'string' }, + # '060e2b34.0101.0101.02300202.00000000' => { Name => 'ProductionOrganizationOrPublicBody', Type => 'Node' }, + '060e2b34.0101.0101.02300202.01000000' => { Name => 'ProductionOrganizationRole', Format => 'string' }, + # '060e2b34.0101.0101.02300203.00000000' => { Name => 'SupportAndAdministrationOrganizationOrPublicBody', Type => 'Node' }, + '060e2b34.0101.0101.02300203.01000000' => { Name => 'SupportOrganizationRole', Format => 'string' }, + # '060e2b34.0101.0101.02300500.00000000' => { Name => 'JobFunctionInformation', Type => 'Node' }, + '060e2b34.0101.0101.02300501.00000000' => { Name => 'JobFunctionName', Format => 'string' }, + '060e2b34.0101.0101.02300502.00000000' => { Name => 'RoleName', Format => 'string' }, + # '060e2b34.0101.0101.02300600.00000000' => { Name => 'ContactInformation', Type => 'Node' }, + '060e2b34.0101.0101.02300601.00000000' => { Name => 'ContactKind', Format => 'string' }, + '060e2b34.0101.0101.02300602.00000000' => { Name => 'ContactDepartmentName', Format => 'string' }, + # '060e2b34.0101.0101.02300603.00000000' => { Name => 'PersonOrOrganizationDetails', Type => 'Node' }, + # '060e2b34.0101.0101.02300603.01000000' => { Name => 'PersonNames', Type => 'Node' }, + '060e2b34.0101.0101.02300603.01010000' => { Name => 'FamilyName', Format => 'string' }, + '060e2b34.0101.0101.02300603.01020000' => { Name => 'FirstGivenName', Format => 'string' }, + '060e2b34.0101.0101.02300603.01030000' => { Name => 'SecondGivenName', Format => 'string' }, + '060e2b34.0101.0101.02300603.01040000' => { Name => 'ThirdGivenName', Format => 'string' }, + # '060e2b34.0101.0101.02300603.02000000' => { Name => 'GroupNames', Type => 'Node' }, + '060e2b34.0101.0101.02300603.02010000' => { Name => 'MainName', Format => 'string' }, + '060e2b34.0101.0101.02300603.02020000' => { Name => 'SupplementaryName', Format => 'string' }, + # '060e2b34.0101.0101.02300603.03000000' => { Name => 'OrganizationNames', Type => 'Node' }, + '060e2b34.0101.0101.02300603.03010000' => { Name => 'OrganizationMainName', Format => 'string' }, + '060e2b34.0101.0101.02300603.03020000' => { Name => 'SupplementaryOrganizationName', Format => 'string' }, + # '060e2b34.0101.0101.03000000.00000000' => { Name => 'Interpretive', Type => 'Node' }, + # '060e2b34.0101.0101.03010000.00000000' => { Name => 'Fundamental', Type => 'Node' }, + # '060e2b34.0101.0101.03010100.00000000' => { Name => 'CountriesAndLanguages', Type => 'Node' }, + # '060e2b34.0101.0101.03010101.00000000' => { Name => 'CountryAndRegionCodes', Type => 'Node' }, + '060e2b34.0101.0101.03010101.01000000' => { Name => 'ISO3166CountryCode', Format => 'string' }, + # '060e2b34.0101.0101.03010102.00000000' => { Name => 'LanguageCodes', Type => 'Node' }, + '060e2b34.0101.0101.03010102.01000000' => { Name => 'ISO639-1LanguageCode', Format => 'string' }, + # '060e2b34.0101.0101.03010201.00000000' => { Name => 'SystemInterpretations', Type => 'Node' }, + '060e2b34.0101.0101.03010201.01000000' => { Name => 'OperatingSystemInterpretations', Format => 'int8u' }, + '060e2b34.0101.0101.03010201.02000000' => { + Name => 'ByteOrder', #PH (was int16s, but I have seen "II") + Format => 'string', + PrintConv => { + II => 'Little-endian (Intel, II)', + MM => 'Big-endian (Motorola, MM)', + }, + }, + '060e2b34.0101.0101.03010201.03000000' => { Name => 'EssenceIsIdentified', Type => 'Boolean' }, + # '060e2b34.0101.0101.03010300.00000000' => { Name => 'FundamentalDimensions', Type => 'Node' }, + # '060e2b34.0101.0101.03010301.00000000' => { Name => 'Length', Type => 'Node' }, + '060e2b34.0101.0101.03010301.01000000' => { Name => 'LengthSystemName', Format => 'string' }, + '060e2b34.0101.0101.03010301.02000000' => { Name => 'LengthUnitKind', Format => 'string' }, + # '060e2b34.0101.0101.03010302.00000000' => { Name => 'Angles', Type => 'Node' }, + '060e2b34.0101.0101.03010302.01000000' => { Name => 'AngularUnitKind', Format => 'string' }, + # '060e2b34.0101.0101.03010303.00000000' => { Name => 'Time', Type => 'Node' }, + '060e2b34.0101.0101.03010303.01000000' => { Name => 'TimeSystemOffset', Format => 'string' }, + '060e2b34.0101.0101.03010303.02000000' => { Name => 'TimeUnitKind', Format => 'string' }, + # '060e2b34.0101.0101.03010304.00000000' => { Name => 'Mass', Type => 'Node' }, + # '060e2b34.0101.0101.03010305.00000000' => { Name => 'Energy', Type => 'Node' }, + # '060e2b34.0101.0101.03020000.00000000' => { Name => 'HumanAssignedDescriptors', Type => 'Node' }, + # '060e2b34.0101.0101.03020100.00000000' => { Name => 'Categorization', Type => 'Node' }, + # '060e2b34.0101.0101.03020101.00000000' => { Name => 'ContentClassification', Type => 'Node' }, + '060e2b34.0101.0101.03020101.01000000' => { Name => 'ContentCodingSystem', Format => 'string' }, + '060e2b34.0101.0101.03020101.02000000' => { Name => 'ProgramKind', Format => 'string' }, + '060e2b34.0101.0101.03020101.03000000' => { Name => 'Genre', Format => 'string' }, + '060e2b34.0101.0101.03020101.04000000' => { Name => 'TargetAudience', Format => 'string' }, + # '060e2b34.0101.0101.03020102.00000000' => { Name => 'CatalogingAndIndexing', Type => 'Node' }, + '060e2b34.0101.0101.03020102.01000000' => { Name => 'CatalogDataStatus', Format => 'string' }, + '060e2b34.0101.0101.03020102.02000000' => { Name => 'ThesaurusName', Format => 'string' }, + '060e2b34.0101.0101.03020102.03000000' => { Name => 'Theme', Format => 'string' }, + '060e2b34.0101.0101.03020102.04000000' => { Name => 'ContentClassification', Format => 'string' }, + '060e2b34.0101.0101.03020102.05000000' => { Name => 'Keywords', Format => 'string' }, + '060e2b34.0101.0101.03020102.06000000' => { Name => 'KeyFrames', Format => 'string' }, + '060e2b34.0101.0101.03020102.07000000' => { Name => 'KeySounds', Format => 'string' }, + '060e2b34.0101.0101.03020102.08000000' => { Name => 'KeyData', Format => 'string' }, + # '060e2b34.0101.0101.03020106.00000000' => { Name => 'TextualDescription', Type => 'Node' }, + '060e2b34.0101.0101.03020106.01000000' => { Name => 'Abstract', Format => 'string' }, + '060e2b34.0101.0101.03020106.02000000' => { Name => 'Purpose', Format => 'string' }, + '060e2b34.0101.0101.03020106.03000000' => { Name => 'Description', Format => 'string' }, + '060e2b34.0101.0101.03020106.04000000' => { Name => 'ColorDescriptor', Format => 'string' }, + '060e2b34.0101.0101.03020106.05000000' => { Name => 'FormatDescriptor', Format => 'string' }, + # '060e2b34.0101.0101.03020107.00000000' => { Name => 'Stratum', Type => 'Node' }, + '060e2b34.0101.0101.03020107.01000000' => { Name => 'StratumKind', Format => 'string' }, + # '060e2b34.0101.0101.03020200.00000000' => { Name => 'Assessments', Type => 'Node' }, + # '060e2b34.0101.0101.03020201.00000000' => { Name => 'Awards', Type => 'Node' }, + '060e2b34.0101.0101.03020201.01000000' => { Name => 'IndividualAwardName', Format => 'string' }, + '060e2b34.0101.0101.03020201.02000000' => { Name => 'ProgramAwardName', Format => 'string' }, + # '060e2b34.0101.0101.03020202.00000000' => { Name => 'QualitativeValues', Type => 'Node' }, + '060e2b34.0101.0101.03020202.01000000' => { Name => 'AssetValue', Format => 'string' }, + '060e2b34.0101.0101.03020202.02000000' => { Name => 'ContentValue', Format => 'string' }, + '060e2b34.0101.0101.03020202.03000000' => { Name => 'CulturalValue', Format => 'string' }, + '060e2b34.0101.0101.03020202.04000000' => { Name => 'AestheticValue', Format => 'string' }, + '060e2b34.0101.0101.03020202.05000000' => { Name => 'HistoricalValue', Format => 'string' }, + '060e2b34.0101.0101.03020202.06000000' => { Name => 'TechnicalValue', Format => 'string' }, + '060e2b34.0101.0101.03020202.07000000' => { Name => 'OtherValues', Format => 'string' }, + # '060e2b34.0101.0101.03020300.00000000' => { Name => 'TechnicalCommentsAndDescriptions', Type => 'Node' }, + # '060e2b34.0101.0101.03020301.00000000' => { Name => 'ObjectCommentsAndDescriptions', Type => 'Node' }, + # '060e2b34.0101.0101.03030000.00000000' => { Name => 'Machine-AssignedOrComputedDescriptions', Type => 'Node' }, + # '060e2b34.0101.0101.03030100.00000000' => { Name => 'AutomatedCategorization', Type => 'Node' }, + # '060e2b34.0101.0101.03030101.00000000' => { Name => 'AutomatedContentClassification', Type => 'Node' }, + # '060e2b34.0101.0101.03030102.00000000' => { Name => 'AutomatedCatalogingAndIndexing', Type => 'Node' }, + '060e2b34.0101.0101.03030102.01000000' => { Name => 'CatalogDataStatus', Format => 'string' }, + '060e2b34.0101.0101.03030102.02000000' => { Name => 'CatalogingSystemName', Format => 'string' }, + '060e2b34.0101.0101.03030102.06000000' => { Name => 'ComputedKeywords', Format => 'string' }, + '060e2b34.0101.0101.03030102.07000000' => { Name => 'ComputedKeyFrames', Format => 'string' }, + '060e2b34.0101.0101.03030102.08000000' => { Name => 'ComputedKeySounds', Format => 'string' }, + '060e2b34.0101.0101.03030102.09000000' => { Name => 'ComputedKeyData', Format => 'string' }, + # '060e2b34.0101.0101.03030106.00000000' => { Name => 'ComputedTextualDescription', Type => 'Node' }, + # '060e2b34.0101.0101.03030107.00000000' => { Name => 'AutomatedStratum', Type => 'Node' }, + '060e2b34.0101.0101.03030107.01000000' => { Name => 'ComputedStratumKind', Format => 'string' }, + # '060e2b34.0101.0101.03030300.00000000' => { Name => 'ComputedTechnicalCommentsAndDescriptions', Type => 'Node' }, + # '060e2b34.0101.0101.03030301.00000000' => { Name => 'ComputedObjectCommentsAndDescriptions', Type => 'Node' }, + # '060e2b34.0101.0101.04000000.00000000' => { Name => 'PARAMETRIC', Type => 'Node' }, + # '060e2b34.0101.0101.04010000.00000000' => { Name => 'VideoAndImageEssenceCharacteristics', Type => 'Node' }, + # '060e2b34.0101.0101.04010100.00000000' => { Name => 'FundamentalImageCharacteristics', Type => 'Node' }, + # '060e2b34.0101.0101.04010101.00000000' => { Name => 'AspectRatios', Type => 'Node' }, + '060e2b34.0101.0101.04010101.01000000' => { Name => 'PresentationAspectRatio', Format => 'rational64s' }, + '060e2b34.0101.0101.04010101.02000000' => { Name => 'CaptureAspectRatio', Format => 'string' }, + # '060e2b34.0101.0101.04010200.00000000' => { Name => 'ImageSourceCharacteristics', Type => 'Node' }, + # '060e2b34.0101.0101.04010201.00000000' => { Name => 'Opto-ElectronicFormulation', Type => 'Node' }, + # '060e2b34.0101.0101.04010201.01000000' => { Name => 'TransferCharacteristics', Type => 'Node' }, + '060e2b34.0101.0101.04010201.01010000' => { Name => 'CaptureGammaEquation', Format => 'string' }, + '060e2b34.0101.0101.04010201.01010100' => { Name => 'CaptureGammaEquation', Format => 'rational64s' }, + '060e2b34.0101.0101.04010201.01020000' => { Name => 'LumaEquation', Format => 'string' }, + '060e2b34.0101.0101.04010201.01030000' => { Name => 'ColorimetryCode', Format => 'string' }, + '060e2b34.0101.0101.04010201.01040000' => { Name => 'SignalFormCode', Format => 'string' }, + # '060e2b34.0101.0101.04010300.00000000' => { Name => 'VideoAndImageScanningParameters', Type => 'Node' }, + # '060e2b34.0101.0101.04010301.00000000' => { Name => 'TemporalParameters', Type => 'Node' }, + '060e2b34.0101.0101.04010301.01000000' => { Name => 'ColorFieldCode', Format => 'int8u' }, + '060e2b34.0101.0101.04010301.02000000' => { Name => 'FieldRate', Format => 'int16u' }, + '060e2b34.0101.0101.04010301.03000000' => { Name => 'FrameRate', Format => 'int16u' }, + '060e2b34.0101.0101.04010301.04000000' => { Name => 'FrameLayout', Format => 'int8u' }, + '060e2b34.0101.0101.04010301.05000000' => { Name => 'SamplingStructureCode', Format => 'string' }, + # '060e2b34.0101.0101.04010302.00000000' => { Name => 'VerticalParameters', Type => 'Node' }, + '060e2b34.0101.0101.04010302.01000000' => { Name => 'TotalLinesperFrame', Format => 'int16u' }, + '060e2b34.0101.0101.04010302.02000000' => { Name => 'ActiveLinesperFrame', Format => 'int16u' }, + '060e2b34.0101.0101.04010302.03000000' => { Name => 'LeadingLines', Format => 'int32s' }, + '060e2b34.0101.0101.04010302.04000000' => { Name => 'TrailingLines', Format => 'int32s' }, + # '060e2b34.0101.0101.04010303.00000000' => { Name => 'HorizontalParameters', Type => 'Node' }, + # '060e2b34.0101.0101.04010400.00000000' => { Name => 'AnalogVideoCodingCharacteristics', Type => 'Node' }, + '060e2b34.0101.0101.04010401.00000000' => { Name => 'AnalogVideoSystemName', Format => 'string' }, + # '060e2b34.0101.0101.04010500.00000000' => { Name => 'DigitalVideoAndImageCodingParameters', Type => 'Node' }, + # '060e2b34.0101.0101.04010501.00000000' => { Name => 'DigitalVideoAndImageSamplingParameters', Type => 'Node' }, + '060e2b34.0101.0101.04010501.01000000' => { Name => 'LuminanceSampleRate', Format => 'int8u' }, + '060e2b34.0101.0101.04010501.02000000' => { Name => 'ActiveSamplesperLine', Format => 'int16u' }, + '060e2b34.0101.0101.04010501.03000000' => { Name => 'TotalSamplesperLine', Format => 'int16u' }, + '060e2b34.0101.0101.04010501.04000000' => { Name => 'SamplingHierarchyCode', Format => 'string' }, + '060e2b34.0101.0101.04010501.05000000' => { Name => 'HorizontalSubsampling', Format => 'int32u' }, + '060e2b34.0101.0101.04010501.06000000' => { Name => 'ColorSiting', Format => 'int8u' }, + '060e2b34.0101.0101.04010501.07000000' => { Name => 'SampledHeight', Format => 'int32u' }, + '060e2b34.0101.0101.04010501.08000000' => { Name => 'SampledWidth', Format => 'int32u' }, + '060e2b34.0101.0101.04010501.09000000' => { Name => 'SampledXOffset', Format => 'int32s' }, + '060e2b34.0101.0101.04010501.0a000000' => { Name => 'SampledYOffset', Format => 'int32s' }, + '060e2b34.0101.0101.04010501.0b000000' => { Name => 'DisplayHeight', Format => 'int32u' }, + '060e2b34.0101.0101.04010501.0c000000' => { Name => 'DisplayWidth', Format => 'int32u' }, + '060e2b34.0101.0101.04010501.0d000000' => { Name => 'DisplayXOffset', Format => 'int32s' }, + '060e2b34.0101.0101.04010501.0e000000' => { Name => 'DisplayYOffset', Format => 'int32s' }, + '060e2b34.0101.0101.04010501.0f000000' => { Name => 'FilteringCode', Format => 'string' }, + # '060e2b34.0101.0101.04010502.00000000' => { Name => 'DigitalVideoAndImageStorageParameters', Type => 'Node' }, + '060e2b34.0101.0101.04010502.01000000' => { Name => 'ImageHeight', Format => 'int32u' }, # (renamed from StoredHeight) + '060e2b34.0101.0101.04010502.02000000' => { Name => 'ImageWidth', Format => 'int32u' }, # (renamed from StoredWidth) + # '060e2b34.0101.0101.04010503.00000000' => { Name => 'DigitalQuantizationAndLevelParameters', Type => 'Node' }, + '060e2b34.0101.0101.04010503.01000000' => { Name => 'BitsPerPixel', Format => 'int8u' }, + '060e2b34.0101.0101.04010503.02000000' => { Name => 'RoundingMethodCode', Format => 'string' }, + '060e2b34.0101.0101.04010503.03000000' => { Name => 'BlackReferenceLevel', Format => 'int32u' }, + '060e2b34.0101.0101.04010503.04000000' => { Name => 'WhiteReferenceLevel', Format => 'int32u' }, + # '060e2b34.0101.0101.04010600.00000000' => { Name => 'DigitalVideoAndImageCompressionParameters', Type => 'Node' }, + # '060e2b34.0101.0101.04010602.00000000' => { Name => 'MPEGCodingParameters', Type => 'Node' }, + # '060e2b34.0101.0101.04010602.01000000' => { Name => 'MPEG-2CodingParameters', Type => 'Node' }, + '060e2b34.0101.0101.04010602.01010000' => { Name => 'FieldFrameTypeCode', Format => 'string' }, + # '060e2b34.0101.0101.04010800.00000000' => { Name => 'Film-to-VideoCharacteristics', Type => 'Node' }, + # '060e2b34.0101.0101.04010801.00000000' => { Name => 'FilmPulldownCharacteristics', Type => 'Node' }, + '060e2b34.0101.0101.04010801.01000000' => { Name => 'PulldownSequence', Type => 'PulldownKind', Unknown => 1 }, + '060e2b34.0101.0101.04010801.02000000' => { Name => 'PulldownFieldDominance', Type => 'Boolean' }, + '060e2b34.0101.0101.04010801.03000000' => { Name => 'VideoAndFilmFrameRelationship', Format => 'int8u' }, + # '060e2b34.0101.0101.04010802.00000000' => { Name => 'FilmFrameRates', Type => 'Node' }, + '060e2b34.0101.0101.04010802.01000000' => { Name => 'CaptureFilmFrameRate', Format => 'string' }, + '060e2b34.0101.0101.04010802.02000000' => { Name => 'TransferFilmFrameRate', Format => 'string' }, + # '060e2b34.0101.0101.04011000.00000000' => { Name => 'ImageTestParameters', Type => 'Node' }, + # '060e2b34.0101.0101.04011001.00000000' => { Name => 'VideoTestParameters', Type => 'Node' }, + '060e2b34.0101.0101.04011001.01000000' => { Name => 'VideoTestParameter', Format => 'string' }, + '060e2b34.0101.0101.04011001.02000000' => { Name => 'VideoTestResult', Format => 'float' }, + '060e2b34.0101.0101.04011001.03000000' => { Name => 'VideoTestResult', Format => 'int32u' }, + # '060e2b34.0101.0101.04011002.00000000' => { Name => 'FilmTestParameters', Type => 'Node' }, + '060e2b34.0101.0101.04011002.01000000' => { Name => 'FilmTestParameter', Format => 'string' }, + '060e2b34.0101.0101.04011002.02000000' => { Name => 'FilmTestResult', Format => 'float' }, + '060e2b34.0101.0101.04011002.03000000' => { Name => 'FilmTestResult', Type => 'SIMSBF', Unknown => 1, Groups => { 2 => 'Time' } }, + # '060e2b34.0101.0101.04020000.00000000' => { Name => 'AudioEssenceCharacteristics', Type => 'Node' }, + # '060e2b34.0101.0101.04020100.00000000' => { Name => 'FundamentalAudioCharacteristics', Type => 'Node' }, + # '060e2b34.0101.0101.04020101.00000000' => { Name => 'AudioFormulation', Type => 'Node' }, + '060e2b34.0101.0101.04020101.01000000' => { Name => 'ElectrospatialFormulation', Format => 'int8u', Groups => { 2 => 'Audio' } }, + '060e2b34.0101.0101.04020101.02000000' => { Name => 'FilteringApplied', Format => 'string', Groups => { 2 => 'Audio' } }, + '060e2b34.0101.0101.04020101.03000000' => { Name => 'AudioReferenceLevel', Format => 'int8s', Groups => { 2 => 'Audio' } }, + # '060e2b34.0101.0101.04020101.10000000' => { Name => 'AudioMix', Type => 'Node' }, + '060e2b34.0101.0101.04020101.10010000' => { Name => 'AudioMonoChannelCount', Format => 'int8u', Groups => { 2 => 'Audio' } }, + '060e2b34.0101.0101.04020101.10020000' => { Name => 'AudioStereoChannelCount', Format => 'int8u', Groups => { 2 => 'Audio' } }, + # '060e2b34.0101.0101.04020200.00000000' => { Name => 'AnalogAudioCodingParameters', Type => 'Node' }, + '060e2b34.0101.0101.04020201.00000000' => { Name => 'AnalogSystem', Format => 'string', Groups => { 2 => 'Audio' } }, + # '060e2b34.0101.0101.04020300.00000000' => { Name => 'DigitalAudioCodingParameters', Type => 'Node' }, + # '060e2b34.0101.0101.04020301.00000000' => { Name => 'DigitalSamplingParameters', Type => 'Node' }, + '060e2b34.0101.0101.04020301.01000000' => { Name => 'AudioSampleRate', Format => 'int8u', Groups => { 2 => 'Audio' } }, + # '060e2b34.0101.0101.04020302.00000000' => { Name => 'DigitalAudioStorageParameters', Type => 'Node' }, + # '060e2b34.0101.0101.04020303.00000000' => { Name => 'DigitalAudioQuantizationAndLevelParameters', Type => 'Node' }, + '060e2b34.0101.0101.04020303.01000000' => { Name => 'BitsPerSample', Format => 'int8u', Groups => { 2 => 'Audio' } }, + '060e2b34.0101.0101.04020303.02000000' => { Name => 'RoundingLaw', Format => 'string', Groups => { 2 => 'Audio' } }, + '060e2b34.0101.0101.04020303.03000000' => { Name => 'Dither', Format => 'string', Groups => { 2 => 'Audio' } }, + # '060e2b34.0101.0101.04020400.00000000' => { Name => 'DigitalAudioCompressionParameters', Type => 'Node' }, + # '060e2b34.0101.0101.04020403.00000000' => { Name => 'MPEGAudioCodingParameters', Type => 'Node' }, + # '060e2b34.0101.0101.04020403.01000000' => { Name => 'MPEG-1AudioCodingParameters', Type => 'Node' }, + # '060e2b34.0101.0101.04020800.00000000' => { Name => 'FilmSoundSource', Type => 'Node' }, + '060e2b34.0101.0101.04020801.00000000' => { Name => 'OpticalTrack', Format => 'string' }, + '060e2b34.0101.0101.04020802.00000000' => { Name => 'MagneticTrack', Format => 'string' }, + # '060e2b34.0101.0101.04021000.00000000' => { Name => 'AudioTestParameters', Type => 'Node' }, + '060e2b34.0101.0101.04021001.00000000' => { Name => 'Signal-to-NoiseRatio', Format => 'float', Groups => { 2 => 'Audio' } }, + '060e2b34.0101.0101.04021002.00000000' => { Name => 'Weighting', Format => 'string', Groups => { 2 => 'Audio' } }, + # '060e2b34.0101.0101.04030000.00000000' => { Name => 'DataEssenceCharacteristics', Type => 'Node' }, + # '060e2b34.0101.0101.04030100.00000000' => { Name => 'FundamentalDataEssenceParameters', Type => 'Node' }, + # '060e2b34.0101.0101.04030200.00000000' => { Name => 'AnalogDataEssenceCodingParameters', Type => 'Node' }, + '060e2b34.0101.0101.04030201.00000000' => { Name => 'AnalogDataCodingKind', Format => 'string' }, + # '060e2b34.0101.0101.04030300.00000000' => { Name => 'DigitalDataEssenceCodingParameters', Type => 'Node' }, + # '060e2b34.0101.0101.04031000.00000000' => { Name => 'DataEssenceTestParameters', Type => 'Node' }, + # '060e2b34.0101.0101.04040000.00000000' => { Name => 'MetadataCharacteristics', Type => 'Node' }, + # '060e2b34.0101.0101.04040100.00000000' => { Name => 'FundamentalMetadataCharacteristics', Type => 'Node' }, + # '060e2b34.0101.0101.04040101.00000000' => { Name => 'TimecodeCharacteristics', Type => 'Node' }, + '060e2b34.0101.0101.04040101.01000000' => { Name => 'TimecodeKind', Format => 'string' }, + '060e2b34.0101.0101.04040101.02000000' => { Name => 'TimecodeTimebase', Format => 'int8u' }, + '060e2b34.0101.0101.04040101.03000000' => { Name => 'TimecodeUserBitsFlag', Type => 'Boolean' }, + '060e2b34.0101.0101.04040101.04000000' => { Name => 'IncludeSync', Type => 'Boolean' }, + '060e2b34.0101.0101.04040101.05000000' => { Name => 'DropFrame', Type => 'Boolean' }, + # '060e2b34.0101.0101.04040200.00000000' => { Name => 'AnalogMetadataCodingCharacteristics', Type => 'Node' }, + '060e2b34.0101.0101.04040201.00000000' => { Name => 'TimecodeSourceKind', Format => 'int8u' }, + '060e2b34.0101.0101.04040202.00000000' => { Name => 'AnalogMetadataCarrier', Format => 'string' }, + # '060e2b34.0101.0101.04040300.00000000' => { Name => 'DigitalMetadataCodingCharacteristics', Type => 'Node' }, + '060e2b34.0101.0101.04040301.00000000' => { Name => 'DigitalMetadataCarrier', Format => 'string' }, + # '060e2b34.0101.0101.04041000.00000000' => { Name => 'MetadataTestParameters', Type => 'Node' }, + # '060e2b34.0101.0101.04050000.00000000' => { Name => 'MonitoringAndControlCharacteristics', Type => 'Node' }, + # '060e2b34.0101.0101.04050100.00000000' => { Name => 'FundamentalMonitoringAndControlCharacteristics', Type => 'Node' }, + # '060e2b34.0101.0101.04050200.00000000' => { Name => 'AnalogMonitoringAndControlCodingCharacteristics', Type => 'Node' }, + '060e2b34.0101.0101.04050201.00000000' => { Name => 'AnalogMonitoringAndControlCodingKind', Format => 'string' }, + # '060e2b34.0101.0101.04050300.00000000' => { Name => 'DigitalMonitoringAndControlCodingParameters', Type => 'Node' }, + # '060e2b34.0101.0101.04050301.00000000' => { Name => 'DigitalMonitoringAndControlSamplingParameters', Type => 'Node' }, + # '060e2b34.0101.0101.04051000.00000000' => { Name => 'MonitoringAndControlTestParameters', Type => 'Node' }, + # '060e2b34.0101.0101.04060000.00000000' => { Name => 'GeneralCodingCharacteristics', Type => 'Node' }, + # '060e2b34.0101.0101.04060100.00000000' => { Name => 'GeneralEssenceCodingCharacteristics', Type => 'Node' }, + '060e2b34.0101.0101.04060101.00000000' => { Name => 'SampleRate', Format => 'rational64s' }, + '060e2b34.0101.0101.04060102.00000000' => { Name => 'EssenceLength', Type => 'Length', %duration }, + # '060e2b34.0101.0101.04080000.00000000' => { Name => 'ObjectCharacteristics', Type => 'Node' }, + # '060e2b34.0101.0101.04100000.00000000' => { Name => 'MediumCharacteristics', Type => 'Node' }, + # '060e2b34.0101.0101.04100100.00000000' => { Name => 'StorageMediumParameters', Type => 'Node' }, + # '060e2b34.0101.0101.04100101.00000000' => { Name => 'TapeMediumParameters', Type => 'Node' }, + # '060e2b34.0101.0101.04100102.00000000' => { Name => 'DiscMediumParameters', Type => 'Node' }, + # '060e2b34.0101.0101.04100103.00000000' => { Name => 'FilmMediumParameters', Type => 'Node' }, + # '060e2b34.0101.0101.04100103.01000000' => { Name => 'GenericFilmMediumParameters', Type => 'Node' }, + '060e2b34.0101.0101.04100103.01010000' => { Name => 'FilmColorProcess', Format => 'string' }, + '060e2b34.0101.0101.04100103.01020000' => { Name => 'EdgeCodeFormat', Type => 'EdgeType', Unknown => 1 }, + '060e2b34.0101.0101.04100103.01040000' => { Name => 'FilmFormatName', Format => 'string' }, + '060e2b34.0101.0101.04100103.01050000' => { Name => 'FilmStockKind', Format => 'string' }, + '060e2b34.0101.0101.04100103.01060000' => { Name => 'FilmStockManufacturerName', Format => 'string' }, + # '060e2b34.0101.0101.04100103.02000000' => { Name => 'SpecificFilmMediumParameters', Type => 'Node' }, + '060e2b34.0101.0101.04100103.02010000' => { Name => 'PhysicalMediaLength', Type => 'UIMSBF', Unknown => 1, Groups => { 2 => 'Time' } }, + '060e2b34.0101.0101.04100103.02020000' => { Name => 'FilmCaptureAperture', Format => 'string' }, + # '060e2b34.0101.0101.04200000.00000000' => { Name => 'DeviceCharacteristics', Type => 'Node' }, + # '060e2b34.0101.0101.04200100.00000000' => { Name => 'CameraCharacteristics', Type => 'Node' }, + # '060e2b34.0101.0101.04200101.00000000' => { Name => 'ImageCharacteristics', Type => 'Node' }, + '060e2b34.0101.0101.04200101.01000000' => { Name => 'ImageCategory', Format => 'string' }, + # '060e2b34.0101.0101.04200102.01000000' => { Name => 'ImageDevices', Type => 'Node' }, + '060e2b34.0101.0101.04200102.01010000' => { Name => 'ImageSourceDeviceKind', Format => 'string' }, + # '060e2b34.0101.0101.04200200.00000000' => { Name => 'OpticalCharacteristics', Type => 'Node' }, + # '060e2b34.0101.0101.04200201.00000000' => { Name => 'OpticalTestParameters', Type => 'Node' }, + # '060e2b34.0101.0101.04200201.01000000' => { Name => 'OpticalDeviceParameters', Type => 'Node' }, + '060e2b34.0101.0101.04200201.01010000' => { Name => 'OpticalTestParameterName', Format => 'string' }, + '060e2b34.0101.0101.04200201.01020000' => { Name => 'OpticalTestResult', Format => 'float' }, + '060e2b34.0101.0101.04200201.01030000' => { Name => 'OpticalTestResult', Format => 'int32s' }, + # '060e2b34.0101.0101.04200300.00000000' => { Name => 'MicrophoneCharacteristics', Type => 'Node' }, + '060e2b34.0101.0101.04200301.00000000' => { Name => 'SensorType', Format => 'string' }, + '060e2b34.0101.0101.04200302.00000000' => { Name => 'PolarCharacteristic', Format => 'string' }, + # '060e2b34.0101.0101.05000000.00000000' => { Name => 'PROCESS', Type => 'Node' }, + # '060e2b34.0101.0101.05010000.00000000' => { Name => 'GeneralProcessIndicators', Type => 'Node' }, + # '060e2b34.0101.0101.05010100.00000000' => { Name => 'ProcessFundamentals', Type => 'Node' }, + '060e2b34.0101.0101.05010101.00000000' => { Name => 'IntegrationIndication', Format => 'string' }, + '060e2b34.0101.0101.05010102.00000000' => { Name => 'EventIndication', Format => 'string' }, + '060e2b34.0101.0101.05010103.00000000' => { Name => 'QualityFlag', Type => 'Boolean' }, + '060e2b34.0101.0101.05010105.00000000' => { Name => 'PhysicalInstanceKind', Format => 'string' }, + # '060e2b34.0101.0101.05010200.00000000' => { Name => 'ContentCapture', Type => 'Node' }, + '060e2b34.0101.0101.05010201.00000000' => { Name => 'DigitalOrAnalogOrigination', Format => 'string' }, + # '060e2b34.0101.0101.05010202.00000000' => { Name => 'VideoOrImageCaptureProcess', Type => 'Node' }, + # '060e2b34.0101.0101.05010203.00000000' => { Name => 'FilmCaptureProcess', Type => 'Node' }, + # '060e2b34.0101.0101.05010204.00000000' => { Name => 'AudioCaptureProcess', Type => 'Node' }, + '060e2b34.0101.0101.05010204.01000000' => { Name => 'MicrophonePlacementTechniques', Format => 'string', Groups => { 2 => 'Audio' } }, + # '060e2b34.0101.0101.05010205.00000000' => { Name => 'DataCaptureProcess', Type => 'Node' }, + # '060e2b34.0101.0101.05010300.00000000' => { Name => 'Manipulation', Type => 'Node' }, + '060e2b34.0101.0101.05010301.00000000' => { Name => 'SimpleFlaggingCount', Format => 'int16u' }, + '060e2b34.0101.0101.05010302.00000000' => { Name => 'CopyCount', Format => 'int8u' }, + '060e2b34.0101.0101.05010303.00000000' => { Name => 'CloneCount', Format => 'int8u' }, + '060e2b34.0101.0101.05010304.00000000' => { Name => 'Work-in-ProgressFlag', Type => 'Boolean' }, + # '060e2b34.0101.0101.05020000.00000000' => { Name => 'CompressionProcessing', Type => 'Node' }, + # '060e2b34.0101.0101.05020100.00000000' => { Name => 'VideoOrImageCompression', Type => 'Node' }, + '060e2b34.0101.0101.05020101.00000000' => { Name => 'VideoOrImageCompressionAlgorithm', Format => 'string' }, + # '060e2b34.0101.0101.05020102.00000000' => { Name => 'MPEGProcessing', Type => 'Node' }, + # '060e2b34.0101.0101.05020102.01000000' => { Name => 'MPEG-2Processing', Type => 'Node' }, + '060e2b34.0101.0101.05020102.01010000' => { Name => 'SplicingMetadata', Unknown => 1 }, + # '060e2b34.0101.0101.05020200.00000000' => { Name => 'AudioCompression', Type => 'Node' }, + '060e2b34.0101.0101.05020201.00000000' => { Name => 'AudioCompressionAlgorithm', Format => 'string', Groups => { 2 => 'Audio' } }, + # '060e2b34.0101.0101.05020300.00000000' => { Name => 'DataEssenceCompression', Type => 'Node' }, + # '060e2b34.0101.0101.05020400.00000000' => { Name => 'MetadataCompression', Type => 'Node' }, + # '060e2b34.0101.0101.05030000.00000000' => { Name => 'NoiseReductionProcessing', Type => 'Node' }, + # '060e2b34.0101.0101.05030100.00000000' => { Name => 'VideoNoiseReduction', Type => 'Node' }, + '060e2b34.0101.0101.05030101.00000000' => { Name => 'VideoNoiseReductionAlgorithm', Format => 'string' }, + # '060e2b34.0101.0101.05030200.00000000' => { Name => 'AudioNoiseReduction', Type => 'Node' }, + '060e2b34.0101.0101.05030201.00000000' => { Name => 'AudioNoiseReductionAlgorithm', Format => 'string', Groups => { 2 => 'Audio' } }, + # '060e2b34.0101.0101.05200000.00000000' => { Name => 'EnhancementOrModification', Type => 'Node' }, + # '060e2b34.0101.0101.05200100.00000000' => { Name => 'ImageEssenceProcessing', Type => 'Node' }, + '060e2b34.0101.0101.05200101.00000000' => { Name => 'EnhancementOrModificationDescription', Format => 'string' }, + # '060e2b34.0101.0101.05200200.00000000' => { Name => 'VideoProcessOrSettings', Type => 'Node' }, + '060e2b34.0101.0101.05200201.00000000' => { Name => 'VideoDeviceKind', Format => 'string' }, + '060e2b34.0101.0101.05200202.00000000' => { Name => 'VideoDeviceParameterName', Format => 'string' }, + '060e2b34.0101.0101.05200203.00000000' => { Name => 'VideoDeviceParameterSetting', Format => 'string' }, + # '060e2b34.0101.0101.05200300.00000000' => { Name => 'AudioEssenceProcessing', Type => 'Node' }, + '060e2b34.0101.0101.05200301.00000000' => { Name => 'AudioEnhancementOrModificationDescription', Format => 'string', Groups => { 2 => 'Audio' } }, + '060e2b34.0101.0101.05200302.00000000' => { Name => 'AudioFirstMix-DownProcess', Format => 'string', Groups => { 2 => 'Audio' } }, + # '060e2b34.0101.0101.05200400.00000000' => { Name => 'AudioProcessorSettings', Type => 'Node' }, + '060e2b34.0101.0101.05200401.00000000' => { Name => 'AudioDeviceKind', Format => 'string', Groups => { 2 => 'Audio' } }, + '060e2b34.0101.0101.05200402.00000000' => { Name => 'AudioDeviceParameter', Format => 'string', Groups => { 2 => 'Audio' } }, + '060e2b34.0101.0101.05200403.00000000' => { Name => 'AudioDeviceParameterSetting', Format => 'string', Groups => { 2 => 'Audio' } }, + # '060e2b34.0101.0101.05200500.00000000' => { Name => 'DataEssenceProcessing', Type => 'Node' }, + '060e2b34.0101.0101.05200501.00000000' => { Name => 'DataEnhancementOrModificationDescription', Format => 'string' }, + # '060e2b34.0101.0101.05200600.00000000' => { Name => 'DataProcessorSettings', Type => 'Node' }, + '060e2b34.0101.0101.05200601.00000000' => { Name => 'DataDeviceKind', Format => 'string' }, + '060e2b34.0101.0101.05200602.00000000' => { Name => 'DataDeviceParameterName', Format => 'string' }, + '060e2b34.0101.0101.05200603.00000000' => { Name => 'DataDeviceParameterSetting', Format => 'string' }, + # '060e2b34.0101.0101.05200700.00000000' => { Name => 'MetadataProcessing', Type => 'Node' }, + # '060e2b34.0101.0101.05200800.00000000' => { Name => 'MetadataProcessorSettings', Type => 'Node' }, + # '060e2b34.0101.0101.05300000.00000000' => { Name => 'EditingInformation', Type => 'Node' }, + # '060e2b34.0101.0101.05300100.00000000' => { Name => 'EditingVersionInformation', Type => 'Node' }, + # '060e2b34.0101.0101.05300200.00000000' => { Name => 'EditingDecisionInformation', Type => 'Node' }, + '060e2b34.0101.0101.05300201.00000000' => { Name => 'DefaultFadeType', Type => 'FadeType', Unknown => 1 }, + # '060e2b34.0101.0101.05300300.00000000' => { Name => 'EditingMatteInformation', Type => 'Node' }, + # '060e2b34.0101.0101.05300400.00000000' => { Name => 'EditingEventInformation', Type => 'Node' }, + '060e2b34.0101.0101.05300401.00000000' => { Name => 'ActiveState', Type => 'Boolean' }, + # '060e2b34.0101.0101.05300500.00000000' => { Name => 'EditingEffectInformation', Type => 'Node' }, + '060e2b34.0101.0101.05300501.00000000' => { Name => 'Fade-InType', Type => 'FadeType', Unknown => 1 }, + '060e2b34.0101.0101.05300502.00000000' => { Name => 'Fade-OutType', Type => 'FadeType', Unknown => 1 }, + '060e2b34.0101.0101.05300503.00000000' => { Name => 'SpeedChangeEffectFlag', Type => 'Boolean' }, + '060e2b34.0101.0101.05300504.00000000' => { Name => 'InputSegmentCount', Format => 'int32s' }, + '060e2b34.0101.0101.05300505.00000000' => { Name => 'Bypass', Format => 'int32u' }, + # '060e2b34.0101.0101.05300600.00000000' => { Name => 'EditingWebInformation', Type => 'Node' }, + # '060e2b34.0101.0101.05300700.00000000' => { Name => 'EditingUserNotes', Type => 'Node' }, + # '060e2b34.0101.0101.05400000.00000000' => { Name => 'ProcessingHistory', Type => 'Node' }, + # '060e2b34.0101.0101.05400100.00000000' => { Name => 'VideoCompressionHistory', Type => 'Node' }, + '060e2b34.0101.0101.05400101.00000000' => { Name => 'VideoCompressionAlgorithm', Format => 'string' }, + '060e2b34.0101.0101.05400102.00000000' => { Name => 'MPEGVideoRecodingDataset', Unknown => 1 }, + # '060e2b34.0101.0101.05400200.00000000' => { Name => 'AudioCompressionHistory', Type => 'Node' }, + '060e2b34.0101.0101.05400201.00000000' => { Name => 'UpstreamAudioCompressionAlgorithm', Format => 'string', Groups => { 2 => 'Audio' } }, + '060e2b34.0101.0101.05400202.00000000' => { Name => 'MPEGAudioRecodingDataset', Unknown => 1, Groups => { 2 => 'Audio' } }, + # '060e2b34.0101.0101.05400300.00000000' => { Name => 'DataCompressionHistory', Type => 'Node' }, + # '060e2b34.0101.0101.05400400.00000000' => { Name => 'MetadataCompressionHistory', Type => 'Node' }, + # '060e2b34.0101.0101.06000000.00000000' => { Name => 'RELATIONAL', Type => 'Node' }, + # '060e2b34.0101.0101.06010000.00000000' => { Name => 'GenericRelationships', Type => 'Node' }, + # '060e2b34.0101.0101.06010100.00000000' => { Name => 'EssenceAndMetadataRelationships', Type => 'Node' }, + # '060e2b34.0101.0101.06010101.00000000' => { Name => 'EssenceToEssenceRelationships', Type => 'Node' }, + # '060e2b34.0101.0101.06010102.00000000' => { Name => 'MetadataToEssenceRelationships', Type => 'Node' }, + # '060e2b34.0101.0101.06010103.00000000' => { Name => 'MetadataToMetadataRelationships', Type => 'Node' }, + # '060e2b34.0101.0101.06010104.00000000' => { Name => 'ObjectToObjectRelationships', Type => 'Node' }, + # '060e2b34.0101.0101.06010105.00000000' => { Name => 'MetadataToObjectRelationships', Type => 'Node' }, + # '060e2b34.0101.0101.06020000.00000000' => { Name => 'RelatedProductionMaterial', Type => 'Node' }, + '060e2b34.0101.0101.06020100.00000000' => { Name => 'ProgramSupportMaterialReference', Format => 'string' }, + '060e2b34.0101.0101.06020200.00000000' => { Name => 'AdvertisingMaterialReference', Format => 'string' }, + '060e2b34.0101.0101.06020300.00000000' => { Name => 'ProgramCommercialMaterialReference', Format => 'string' }, + # '060e2b34.0101.0101.06080000.00000000' => { Name => 'StreamAndStorageRelationships', Type => 'Node' }, + # '060e2b34.0101.0101.06080100.00000000' => { Name => 'StreamRelationships', Type => 'Node' }, + # '060e2b34.0101.0101.06080200.00000000' => { Name => 'StorageRelationships', Type => 'Node' }, + '060e2b34.0101.0101.06080201.00000000' => { Name => 'ContiguousDataFlag', Type => 'Boolean' }, + # '060e2b34.0101.0101.06100000.00000000' => { Name => 'NumericalSequence', Type => 'Node' }, + '060e2b34.0101.0101.06100100.00000000' => { Name => 'PositionInSequence', Format => 'int32u' }, + '060e2b34.0101.0101.06100200.00000000' => { Name => 'RelativePositionInSequenceOffset', Format => 'int32s' }, + '060e2b34.0101.0101.06100300.00000000' => { Name => 'RelativePositionInSequenceName', Format => 'string' }, + # '060e2b34.0101.0101.07000000.00000000' => { Name => 'SPATIO-TEMPORAL', Type => 'Node' }, + # '060e2b34.0101.0101.07010000.00000000' => { Name => 'PositionAndSpaceVectors', Type => 'Node' }, + # '060e2b34.0101.0101.07010100.00000000' => { Name => 'PositionalSystemInformation', Type => 'Node' }, + '060e2b34.0101.0101.07010101.00000000' => { Name => 'ImageCoordinateSystem', Format => 'string' }, + '060e2b34.0101.0101.07010102.00000000' => { Name => 'MapDatumUsed', Format => 'string' }, + # '060e2b34.0101.0101.07010200.00000000' => { Name => 'PositionalInformation', Type => 'Node' }, + # '060e2b34.0101.0101.07010201.00000000' => { Name => 'AbsolutePosition', Type => 'Node' }, + # '060e2b34.0101.0101.07010201.01000000' => { Name => 'LocalDatumAbsolutePosition', Type => 'Node' }, + '060e2b34.0101.0101.07010201.01010000' => { Name => 'LocalDatumAbsolutePositionAccuracy', Format => 'float' }, + # '060e2b34.0101.0101.07010201.02000000' => { Name => 'DeviceAbsolutePosition', Type => 'Node' }, + '060e2b34.0101.0101.07010201.02010000' => { Name => 'DeviceAbsolutePositionalAccuracy', Format => 'float' }, + '060e2b34.0101.0101.07010201.02020000' => { Name => 'DeviceAltitude', Format => 'float', Groups => { 2 => 'Location' }, PrintConv => '$val m' }, + '060e2b34.0101.0101.07010201.02020100' => { Name => 'DeviceAltitude', Type => 'Alt', Groups => { 2 => 'Location' }, PrintConv => '$val m' }, + '060e2b34.0101.0101.07010201.02040000' => { Name => 'DeviceLatitude', Format => 'float', %geoLat }, + '060e2b34.0101.0101.07010201.02040100' => { Name => 'DeviceLatitude', Type => 'Lat', %geoLat }, + '060e2b34.0101.0101.07010201.02060000' => { Name => 'DeviceLongitude', Format => 'float', %geoLon }, + '060e2b34.0101.0101.07010201.02060100' => { Name => 'DeviceLongitude', Type => 'Lon', %geoLon }, + '060e2b34.0101.0101.07010201.02100000' => { Name => 'DeviceXDimension', Format => 'float' }, + '060e2b34.0101.0101.07010201.02110000' => { Name => 'DeviceYDimension', Format => 'float' }, + # '060e2b34.0101.0101.07010201.03000000' => { Name => 'SubjectAbsolutePosition', Type => 'Node' }, + '060e2b34.0101.0101.07010201.03010000' => { Name => 'FramePositionalAccuracy', Format => 'float' }, + '060e2b34.0101.0101.07010201.03020000' => { Name => 'FrameCenterLatitude', Format => 'double', %geoLat }, + '060e2b34.0101.0101.07010201.03030000' => { Name => 'FrameCenterLatitude', Format => 'string', %geoLat, ValueConv => \&ConvLatLon }, + '060e2b34.0101.0101.07010201.03040000' => { Name => 'FrameCenterLongitude', Format => 'double', %geoLon }, + '060e2b34.0101.0101.07010201.03050000' => { Name => 'FrameCenterLongitude', Format => 'string', %geoLon, ValueConv => \&ConvLatLon }, + '060e2b34.0101.0101.07010201.03060000' => { Name => 'FrameCenterLatitudeLongitude', Format => 'string', %geoLatLon, ValueConv => \&ConvLatLon }, + # '060e2b34.0101.0101.07010202.00000000' => { Name => 'RelativePosition', Type => 'Node' }, + # '060e2b34.0101.0101.07010202.01000000' => { Name => 'LocalDatumRelativePosition', Type => 'Node' }, + '060e2b34.0101.0101.07010202.01010000' => { Name => 'LocalDatumRelativePositionAccuracy', Format => 'float' }, + # '060e2b34.0101.0101.07010202.02000000' => { Name => 'DeviceRelativePosition', Type => 'Node' }, + '060e2b34.0101.0101.07010202.02010000' => { Name => 'DeviceRelativePositionalAccuracy', Format => 'float' }, + '060e2b34.0101.0101.07010202.02020000' => { Name => 'DeviceRelativePositionX', Format => 'float' }, + '060e2b34.0101.0101.07010202.02030000' => { Name => 'DeviceRelativePositionY', Format => 'float' }, + '060e2b34.0101.0101.07010202.02040000' => { Name => 'DeviceRelativePositionZ', Format => 'float' }, + # '060e2b34.0101.0101.07010202.03000000' => { Name => 'SubjectRelativePosition', Type => 'Node' }, + '060e2b34.0101.0101.07010202.03010000' => { Name => 'SubjectRelativePositionalAccuracy', Format => 'float' }, + # '060e2b34.0101.0101.07010203.00000000' => { Name => 'ImagePositionalInformation', Type => 'Node' }, + '060e2b34.0101.0101.07010203.01000000' => { Name => 'PositionWithinViewportImageXCoordinate', Format => 'int16s' }, + '060e2b34.0101.0101.07010203.02000000' => { Name => 'PositionWithinViewportImageYCoordinate', Format => 'int16s' }, + '060e2b34.0101.0101.07010203.03000000' => { Name => 'SourceImageCenterXCoordinate', Format => 'int16s' }, + '060e2b34.0101.0101.07010203.04000000' => { Name => 'SourceImageCenterYCoordinate', Format => 'int16s' }, + '060e2b34.0101.0101.07010203.05000000' => { Name => 'ViewportImageCenterCCoordinate', Format => 'int16s' }, + '060e2b34.0101.0101.07010203.06000000' => { Name => 'ViewportImageCenterYCoordinate', Format => 'int16s' }, + # '060e2b34.0101.0101.07010300.00000000' => { Name => 'RateAndDirectionOfPositionalChange', Type => 'Node' }, + # '060e2b34.0101.0101.07010301.00000000' => { Name => 'AbsoluteRateAndDirectionOfPositionalChange', Type => 'Node' }, + # '060e2b34.0101.0101.07010301.01000000' => { Name => 'DeviceRateAndDirectionOfPositionalChange', Type => 'Node' }, + '060e2b34.0101.0101.07010301.01010000' => { Name => 'DeviceAbsoluteSpeed', Format => 'float' }, + '060e2b34.0101.0101.07010301.01020000' => { Name => 'DeviceAbsoluteHeading', Format => 'float' }, + # '060e2b34.0101.0101.07010301.02000000' => { Name => 'SubjectRateAndDirectionOfPositionalChange', Type => 'Node' }, + '060e2b34.0101.0101.07010301.02010000' => { Name => 'SubjectAbsoluteSpeed', Format => 'float' }, + '060e2b34.0101.0101.07010301.02020000' => { Name => 'SubjectAbsoluteHeading', Format => 'float' }, + # '060e2b34.0101.0101.07010302.00000000' => { Name => 'RelativeRateAndDirectionOfPositionalChange', Type => 'Node' }, + # '060e2b34.0101.0101.07010302.01000000' => { Name => 'DeviceRelativeRateAndDirectionOfPositionalChange', Type => 'Node' }, + '060e2b34.0101.0101.07010302.01010000' => { Name => 'DeviceRelativeSpeed', Format => 'float' }, + '060e2b34.0101.0101.07010302.01020000' => { Name => 'DeviceRelativeHeading', Format => 'float' }, + # '060e2b34.0101.0101.07010302.02000000' => { Name => 'SubjectRelativeRateAndDirectionOfPositionalChange', Type => 'Node' }, + '060e2b34.0101.0101.07010302.02010000' => { Name => 'SubjectRelativeSpeed', Format => 'float' }, + '060e2b34.0101.0101.07010302.02020000' => { Name => 'SubjectRelativeHeading', Format => 'float' }, + # '060e2b34.0101.0101.07010800.00000000' => { Name => 'DistanceMeasurements', Type => 'Node' }, + # '060e2b34.0101.0101.07010801.00000000' => { Name => 'DeviceToSubjectDistance', Type => 'Node' }, + '060e2b34.0101.0101.07010801.01000000' => { Name => 'SlantRange', Format => 'float' }, + # '060e2b34.0101.0101.07010900.00000000' => { Name => 'Dimensions', Type => 'Node' }, + # '060e2b34.0101.0101.07010901.00000000' => { Name => 'DeviceDimensions', Type => 'Node' }, + # '060e2b34.0101.0101.07010902.00000000' => { Name => 'SubjectDimensions', Type => 'Node' }, + '060e2b34.0101.0101.07010902.01000000' => { Name => 'TargetWidth', Format => 'float' }, + # '060e2b34.0101.0101.07010903.00000000' => { Name => 'LocationDimensions', Type => 'Node' }, + # '060e2b34.0101.0101.07010904.00000000' => { Name => 'MediaDimensions', Type => 'Node' }, + # '060e2b34.0101.0101.07010904.01000000' => { Name => 'ImageDimensions', Type => 'Node' }, + # '060e2b34.0101.0101.07010904.01010000' => { Name => 'Pan-and-ScanImageDimensions', Type => 'Node' }, + '060e2b34.0101.0101.07010904.01010100' => { Name => 'ViewportHeight', Format => 'int16u' }, + '060e2b34.0101.0101.07010904.01010200' => { Name => 'ViewportWidth', Format => 'int16u' }, + # '060e2b34.0101.0101.07011000.00000000' => { Name => 'AngularSpecifications', Type => 'Node' }, + # '060e2b34.0101.0101.07011001.00000000' => { Name => 'DeviceAngles', Type => 'Node' }, + '060e2b34.0101.0101.07011001.01000000' => { Name => 'SensorRollAngle', Format => 'float' }, + '060e2b34.0101.0101.07011001.02000000' => { Name => 'AngleToNorth', Format => 'float' }, + '060e2b34.0101.0101.07011001.03000000' => { Name => 'ObliquityAngle', Format => 'float' }, + # '060e2b34.0101.0101.07011002.00000000' => { Name => 'SubjectAngles', Type => 'Node' }, + # '060e2b34.0101.0101.07012000.00000000' => { Name => 'AbstractLocations', Type => 'Node' }, + # '060e2b34.0101.0101.07012001.00000000' => { Name => 'PlaceNames', Type => 'Node' }, + # '060e2b34.0101.0101.07012001.01000000' => { Name => 'AbstractNames', Type => 'Node' }, + '060e2b34.0101.0101.07012001.01010000' => { Name => 'PlaceKeyword', Format => 'string' }, + # '060e2b34.0101.0101.07012001.02000000' => { Name => 'CountryCodes', Type => 'Node' }, + '060e2b34.0101.0101.07012001.02010000' => { Name => 'ObjectCountryCode', Format => 'string' }, + '060e2b34.0101.0101.07012001.02020000' => { Name => 'ShootingCountryCode', Format => 'string' }, + '060e2b34.0101.0101.07012001.02030000' => { Name => 'SettingCountryCode', Format => 'string' }, + '060e2b34.0101.0101.07012001.02040000' => { Name => 'CopyrightLicenseCountryCode', Format => 'string' }, + '060e2b34.0101.0101.07012001.02050000' => { Name => 'IntellectualPropertyLicenseCountryCode', Format => 'string' }, + # '060e2b34.0101.0101.07012001.03000000' => { Name => 'Regions', Type => 'Node' }, + '060e2b34.0101.0101.07012001.03010000' => { Name => 'ObjectRegionCode', Format => 'string' }, + '060e2b34.0101.0101.07012001.03020000' => { Name => 'ShootingRegionCode', Format => 'string' }, + '060e2b34.0101.0101.07012001.03030000' => { Name => 'SettingRegionCode', Format => 'string' }, + '060e2b34.0101.0101.07012001.03040000' => { Name => 'CopyrightLicenseRegionCode', Format => 'string' }, + '060e2b34.0101.0101.07012001.03050000' => { Name => 'IntellectualPropertyLicenseRegionCode', Format => 'string' }, + # '060e2b34.0101.0101.07012001.04000000' => { Name => 'Addresses', Type => 'Node' }, + # '060e2b34.0101.0101.07012001.04010000' => { Name => 'PostalAddresses', Type => 'Node' }, + '060e2b34.0101.0101.07012001.04010100' => { Name => 'RoomNumber', Format => 'string' }, + '060e2b34.0101.0101.07012001.04010200' => { Name => 'StreetNumber', Format => 'string' }, + '060e2b34.0101.0101.07012001.04010300' => { Name => 'StreetName', Format => 'string' }, + '060e2b34.0101.0101.07012001.04010400' => { Name => 'PostalTown', Format => 'string' }, + '060e2b34.0101.0101.07012001.04010500' => { Name => 'CityName', Format => 'string' }, + '060e2b34.0101.0101.07012001.04010600' => { Name => 'StateOrProvinceOrCountyName', Format => 'string' }, + '060e2b34.0101.0101.07012001.04010700' => { Name => 'PostalCode', Format => 'string' }, + '060e2b34.0101.0101.07012001.04010800' => { Name => 'CountryName', Format => 'string' }, + # '060e2b34.0101.0101.07012001.04020000' => { Name => 'SettingAddresses', Type => 'Node' }, + '060e2b34.0101.0101.07012001.04020100' => { Name => 'SettingRoomNumber', Format => 'string' }, + '060e2b34.0101.0101.07012001.04020200' => { Name => 'SettingStreetNumberOrBuildingName', Format => 'string' }, + '060e2b34.0101.0101.07012001.04020300' => { Name => 'SettingStreetName', Format => 'string' }, + '060e2b34.0101.0101.07012001.04020400' => { Name => 'SettingTownName', Format => 'string' }, + '060e2b34.0101.0101.07012001.04020500' => { Name => 'SettingCityName', Format => 'string' }, + '060e2b34.0101.0101.07012001.04020600' => { Name => 'SettingStateOrProvinceOrCountyName', Format => 'string' }, + '060e2b34.0101.0101.07012001.04020700' => { Name => 'SettingPostalCode', Format => 'string' }, + '060e2b34.0101.0101.07012001.04020800' => { Name => 'SettingCountryName', Format => 'string' }, + # '060e2b34.0101.0101.07012001.10030000' => { Name => 'ElectronicAddressInformation', Type => 'Node' }, + '060e2b34.0101.0101.07012001.10030100' => { Name => 'TelephoneNumber', Format => 'string' }, + '060e2b34.0101.0101.07012001.10030200' => { Name => 'FaxNumber', Format => 'string' }, + '060e2b34.0101.0101.07012001.10030300' => { Name => 'E-mailAddress', Format => 'string' }, + # '060e2b34.0101.0101.07012002.00000000' => { Name => 'PlaceDescriptions', Type => 'Node' }, + '060e2b34.0101.0101.07012002.01000000' => { Name => 'SettingDescription', Format => 'string' }, + # '060e2b34.0101.0101.07020000.00000000' => { Name => 'Temporal', Type => 'Node' }, + # '060e2b34.0101.0101.07020100.00000000' => { Name => 'DatesAndTimes', Type => 'Node' }, + # '060e2b34.0101.0101.07020101.00000000' => { Name => 'GeneralDatesAndTimes', Type => 'Node' }, + # '060e2b34.0101.0101.07020101.01000000' => { Name => 'UserDateTime', Type => 'Node' }, + '060e2b34.0101.0101.07020101.01010000' => { Name => 'UTCUserDateTime', Format => 'string', Groups => { 2 => 'Time' } }, + '060e2b34.0101.0101.07020101.01020000' => { Name => 'LocalUserDateTime', Format => 'string', Groups => { 2 => 'Time' } }, + '060e2b34.0101.0101.07020101.01030000' => { Name => 'SMPTE309MUserDateTime', Type => 'UILSBF', Unknown => 1, Groups => { 2 => 'Time' } }, + '060e2b34.0101.0101.07020101.01040000' => { Name => 'SMPTE12MUserDateTime', Type => 'UILSBF', Unknown => 1, Groups => { 2 => 'Time' } }, + # '060e2b34.0101.0101.07020102.00000000' => { Name => 'AbsoluteDatesAndTimes', Type => 'Node' }, + # '060e2b34.0101.0101.07020102.01000000' => { Name => 'MaterialStartTrueDateTime', Type => 'Node' }, + '060e2b34.0101.0101.07020102.01010000' => { Name => 'UTCStartDateTime', Format => 'string', Groups => { 2 => 'Time' } }, + '060e2b34.0101.0101.07020102.01020000' => { Name => 'LocalStartDateTime', Format => 'string', Groups => { 2 => 'Time' } }, + # '060e2b34.0101.0101.07020102.02000000' => { Name => 'MaterialStartTimeAddress', Type => 'Node' }, + '060e2b34.0101.0101.07020102.02010000' => { Name => 'TimecodeStartDateTime', Type => 'UILSBF', Unknown => 1, Groups => { 2 => 'Time' } }, + # '060e2b34.0101.0101.07020102.03000000' => { Name => 'MaterialEndTrueDateTime', Type => 'Node' }, + '060e2b34.0101.0101.07020102.03010000' => { Name => 'UTCEndDateTime', Format => 'string', Groups => { 2 => 'Time' } }, + '060e2b34.0101.0101.07020102.03020000' => { Name => 'LocalEndDateTime', Format => 'string', Groups => { 2 => 'Time' } }, + # '060e2b34.0101.0101.07020102.04000000' => { Name => 'MaterialEndTimeAddress', Type => 'Node' }, + '060e2b34.0101.0101.07020102.04010000' => { Name => 'TimecodeEndDateTime', Type => 'UILSBF', Unknown => 1, Groups => { 2 => 'Time' } }, + # '060e2b34.0101.0101.07020102.05000000' => { Name => 'MaterialOccurrenceTrueDateTime', Type => 'Node' }, + '060e2b34.0101.0101.07020102.05010000' => { Name => 'UTCLastModifyDate', Format => 'string', Groups => { 2 => 'Time' } }, + '060e2b34.0101.0101.07020102.05020000' => { Name => 'LocalLastModifyDate', Format => 'string', Groups => { 2 => 'Time' } }, + # '060e2b34.0101.0101.07020102.06000000' => { Name => 'MaterialOccurrenceTimeAddress', Type => 'Node' }, + '060e2b34.0101.0101.07020102.06010000' => { Name => 'TimecodeLastModifyDate', Type => 'UILSBF', Unknown => 1, Groups => { 2 => 'Time' } }, + # '060e2b34.0101.0101.07020102.07000000' => { Name => 'EventStartTrueDateTime', Type => 'Node' }, + '060e2b34.0101.0101.07020102.07010000' => { Name => 'UTCEventStartDateTime', Format => 'string', Groups => { 2 => 'Time' } }, + '060e2b34.0101.0101.07020102.07020000' => { Name => 'LocalEventStartDateTime', Format => 'string', Groups => { 2 => 'Time' } }, + # '060e2b34.0101.0101.07020102.08000000' => { Name => 'EventStartTimeAddress', Type => 'Node' }, + '060e2b34.0101.0101.07020102.08010000' => { Name => 'TimecodeEventStartDateTime', Type => 'UILSBF', Unknown => 1, Groups => { 2 => 'Time' } }, + # '060e2b34.0101.0101.07020102.09000000' => { Name => 'EventEndTrueDateTime', Type => 'Node' }, + '060e2b34.0101.0101.07020102.09010000' => { Name => 'UTCEventEndDateTime', Format => 'string', Groups => { 2 => 'Time' } }, + '060e2b34.0101.0101.07020102.09020000' => { Name => 'LocalEventEndDateTime', Format => 'string', Groups => { 2 => 'Time' } }, + # '060e2b34.0101.0101.07020102.0a000000' => { Name => 'EventEndTimeAddress', Type => 'Node' }, + '060e2b34.0101.0101.07020102.0a010000' => { Name => 'TimecodeEventEndDateTime', Type => 'UILSBF', Unknown => 1, Groups => { 2 => 'Time' } }, + # '060e2b34.0101.0101.07020103.00000000' => { Name => 'RelativeTimes', Type => 'Node' }, + # '060e2b34.0101.0101.07020103.01000000' => { Name => 'MaterialStartRelativeTimes', Type => 'Node' }, + '060e2b34.0101.0101.07020103.01010000' => { Name => 'StartTimeRelativeToReference', Format => 'string' }, + '060e2b34.0101.0101.07020103.01020000' => { Name => 'StartTimecodeRelativeToReference', Type => 'UILSBF', Unknown => 1, Groups => { 2 => 'Time' } }, + # '060e2b34.0101.0101.07020103.02000000' => { Name => 'MaterialEndRelativeTimes', Type => 'Node' }, + '060e2b34.0101.0101.07020103.02010000' => { Name => 'MaterialEndTimeOffset', Format => 'string' }, + '060e2b34.0101.0101.07020103.02020000' => { Name => 'MaterialEndTimecodeOffset', Type => 'UILSBF', Unknown => 1, Groups => { 2 => 'Time' } }, + # '060e2b34.0101.0101.07020103.03000000' => { Name => 'EventStartRelativeTimes', Type => 'Node' }, + '060e2b34.0101.0101.07020103.03010000' => { Name => 'EventStartTimeOffset', Format => 'string' }, + '060e2b34.0101.0101.07020103.03020000' => { Name => 'EventStartTimecodeOffset', Type => 'UILSBF', Unknown => 1, Groups => { 2 => 'Time' } }, + # '060e2b34.0101.0101.07020103.04000000' => { Name => 'EventEndRelativeTimes', Type => 'Node' }, + '060e2b34.0101.0101.07020103.04010000' => { Name => 'EventEndTimeOffset', Format => 'string' }, + '060e2b34.0101.0101.07020103.04020000' => { Name => 'EventEndTimecodeOffset', Type => 'UILSBF', Unknown => 1, Groups => { 2 => 'Time' } }, + # '060e2b34.0101.0101.07020103.10000000' => { Name => 'Offsets', Type => 'Node' }, + # '060e2b34.0101.0101.07020103.10010000' => { Name => 'MaterialOffsets', Type => 'Node' }, + '060e2b34.0101.0101.07020103.10010100' => { Name => 'FrameCountOffset', Format => 'int32u' }, + # '060e2b34.0101.0101.07020108.00000000' => { Name => 'SettingDateAndTime', Type => 'Node' }, + '060e2b34.0101.0101.07020108.01000000' => { Name => 'TimePeriodName', Format => 'string' }, + # '060e2b34.0101.0101.07020110.00000000' => { Name => 'ProcessDateTime', Type => 'Node' }, + # '060e2b34.0101.0101.07020110.01000000' => { Name => 'CreateDate', Type => 'Node' }, + '060e2b34.0101.0101.07020110.01010000' => { Name => 'LocalCreationDateTime', Format => 'string', Groups => { 2 => 'Time' } }, + '060e2b34.0101.0101.07020110.01020000' => { Name => 'TimecodeCreationDateTime', Type => 'UILSBF', Unknown => 1, Groups => { 2 => 'Time' } }, + # '060e2b34.0101.0101.07020110.02000000' => { Name => 'ModifyDate', Type => 'Node' }, + '060e2b34.0101.0101.07020110.02010000' => { Name => 'LocalModifyDate', Format => 'string', Groups => { 2 => 'Time' } }, + '060e2b34.0101.0101.07020110.02020000' => { Name => 'TimecodeModifyDate', Type => 'UILSBF', Unknown => 1, Groups => { 2 => 'Time' } }, + # '060e2b34.0101.0101.07020200.00000000' => { Name => 'Durations', Type => 'Node' }, + # '060e2b34.0101.0101.07020201.00000000' => { Name => 'AbsoluteDurations', Type => 'Node' }, + # '060e2b34.0101.0101.07020201.01000000' => { Name => 'EditTimelineDurations', Type => 'Node' }, + '060e2b34.0101.0101.07020201.01010000' => { Name => 'FrameCount', Format => 'int32u' }, + # '060e2b34.0101.0101.07020201.01040000' => { Name => 'VideoDurations', Type => 'Node' }, + # '060e2b34.0101.0101.07020201.01050000' => { Name => 'AudioDurations', Type => 'Node' }, + # '060e2b34.0101.0101.07020201.02000000' => { Name => 'MaterialAbsoluteDurations', Type => 'Node' }, + '060e2b34.0101.0101.07020201.02010000' => { Name => 'MaterialAbsoluteDuration', Format => 'string' }, + '060e2b34.0101.0101.07020201.02020000' => { Name => 'MaterialAbsoluteDuration', Type => 'UILSBF', Unknown => 1, Groups => { 2 => 'Time' } }, + '060e2b34.0101.0101.07020201.02030000' => { Name => 'TextlessBlackDuration', Format => 'int32u' }, + # '060e2b34.0101.0101.07020201.03000000' => { Name => 'EventAbsoluteDurations', Type => 'Node' }, + '060e2b34.0101.0101.07020201.03010000' => { Name => 'EventAbsoluteDurationFrameCount', Format => 'int32u' }, + '060e2b34.0101.0101.07020201.03020000' => { Name => 'EventAbsoluteDuration', Format => 'string' }, + '060e2b34.0101.0101.07020201.03030000' => { Name => 'EventAbsoluteDuration', Type => 'UILSBF', Unknown => 1, Groups => { 2 => 'Time' } }, + # '060e2b34.0101.0101.07020202.00000000' => { Name => 'RelativeScalingDurations', Type => 'Node' }, + # '060e2b34.0101.0101.07020300.00000000' => { Name => 'Delay', Type => 'Node' }, + # '060e2b34.0101.0101.07020301.00000000' => { Name => 'EncodingAndDecoding', Type => 'Node' }, + # '060e2b34.0101.0101.07020301.01000000' => { Name => 'CodecDelay', Type => 'Node' }, + # '060e2b34.0101.0101.07020301.02000000' => { Name => 'EncodingDelay', Type => 'Node' }, + # '060e2b34.0101.0101.07020301.03000000' => { Name => 'DecodingDelay', Type => 'Node' }, + '060e2b34.0101.0101.07020301.03010000' => { Name => 'BufferDelay', Unknown => 1 }, + # '060e2b34.0101.0101.07020500.00000000' => { Name => 'Latency', Type => 'Node' }, + # '060e2b34.0101.0101.07020600.00000000' => { Name => 'ShutterCharacteristics', Type => 'Node' }, + # '060e2b34.0101.0101.07020601.00000000' => { Name => 'ShutterCharacteristics', Type => 'Node' }, + # '060e2b34.0101.0101.07020601.01000000' => { Name => 'ShutterSpeed', Type => 'Node' }, + # '060e2b34.0101.0101.07020601.02000000' => { Name => 'ShutterGating', Type => 'Node' }, + # '060e2b34.0101.0101.0d000000.00000000' => { Name => 'UserOrganizationRegisteredForPublicUse', Type => 'Node' }, + # '060e2b34.0101.0101.0d010000.00000000' => { Name => 'AAFAssociation', Type => 'Node' }, + # '060e2b34.0101.0101.0d010100.00000000' => { Name => 'AAFAttributes', Type => 'Node' }, + # '060e2b34.0101.0101.0d010101.00000000' => { Name => 'AAFInformationAttributes', Type => 'Node' }, + # '060e2b34.0101.0101.0d010101.01000000' => { Name => 'AAFInformationAttributesVersion1', Type => 'Node' }, + # '060e2b34.0101.0101.0d010101.01010000' => { Name => 'EnumeratedAttributes', Type => 'Node' }, + + # tags from ref 4 (untested) + '060e2b34.0101.0101.0d010401.03010100' => { Name => 'ProgramIdentifier', Type => 'UTF-16' }, + '060e2b34.0101.0101.0d010401.03010200' => { Name => 'ProgramIdentifierString', Type => 'UTF-16' }, + '060e2b34.0101.0101.0d010401.03010300' => { Name => 'ShimName', Type => 'UTF-16' }, + '060e2b34.0101.0101.0d010401.03010400' => { Name => 'SignalStandard', Type => 'UTF-16' }, + '060e2b34.0101.0101.0d010401.03010500' => { Name => 'IntendedAFD', Type => 'UTF-16' }, + '060e2b34.0101.0101.0d010401.03010600' => { Name => 'SlateTitle', Type => 'UTF-16' }, + '060e2b34.0101.0101.0d010401.03010700' => { Name => 'NOLACode', Type => 'UTF-16' }, + '060e2b34.0101.0101.0d010401.03010800' => { Name => 'Rating', Type => 'UTF-16' }, + '060e2b34.0101.0101.0d010401.03010900' => { Name => 'NielsenStreamIdentifier', Type => 'UTF-16' }, + + # '060e2b34.0101.0101.0d0b0100.00000000' => { Name => 'ProductionFramework', Type => 'Node' }, + '060e2b34.0101.0101.0d0b0101.00000000' => { Name => 'IsRecording', Type => 'Boolean' }, + '060e2b34.0101.0101.0d0b0102.00000000' => { Name => 'IsLiveProduction', Type => 'Boolean' }, + '060e2b34.0101.0101.0d0b0103.00000000' => { Name => 'IsLiveTransmission', Type => 'Boolean' }, + '060e2b34.0101.0101.0d0b0104.00000000' => { Name => 'IsDubbed', Type => 'Boolean' }, + '060e2b34.0101.0101.0d0b0105.00000000' => { Name => 'IsVoiceover', Type => 'Boolean' }, + '060e2b34.0101.0101.0d0b0106.00000000' => { Name => 'HasAudioWatermark', Type => 'Boolean', Groups => { 2 => 'Audio' } }, + '060e2b34.0101.0101.0d0b0107.00000000' => { Name => 'AudioWatermarkKind', Type => 'UTF-16', Groups => { 2 => 'Audio' } }, + '060e2b34.0101.0101.0d0b0108.00000000' => { Name => 'HasVideoWatermark', Type => 'Boolean' }, + '060e2b34.0101.0101.0d0b0109.00000000' => { Name => 'VideoWatermarkKind', Type => 'UTF-16' }, + # '060e2b34.0101.0101.0d0b0200.00000000' => { Name => 'Subtitling', Type => 'Node' }, + '060e2b34.0101.0101.0d0b0201.00000000' => { Name => 'SubtitlesPresent', Type => 'Boolean' }, + # '060e2b34.0101.0101.0d0b0300.00000000' => { Name => 'CaptionTitles', Type => 'Node' }, + '060e2b34.0101.0101.0d0b0301.00000000' => { Name => 'CaptionTitles', Type => 'Boolean' }, + '060e2b34.0101.0101.0d0b0302.00000000' => { Name => 'CaptionsViaTeletext', Type => 'Boolean' }, + '060e2b34.0101.0101.0d0b0303.00000000' => { Name => 'TextlessMaterial', Type => 'Boolean' }, + # '060e2b34.0101.0101.0d0b0400.00000000' => { Name => 'AudioParameters', Type => 'Node' }, + '060e2b34.0101.0101.0d0b0401.00000000' => { Name => 'AudioReferenceLevel', Format => 'string', Groups => { 2 => 'Audio' } }, + # '060e2b34.0101.0101.0d0b0500.00000000' => { Name => 'StorageMedia', Type => 'Node' }, + '060e2b34.0101.0101.0d0b0501.00000000' => { Name => 'StorageDeviceKind', Type => 'UTF-16' }, + '060e2b34.0101.0101.0d0b0502.00000000' => { Name => 'StorageMediaKind', Type => 'UTF-16' }, + '060e2b34.0101.0101.0d0b0503.00000000' => { Name => 'StorageMediaID', Type => 'UTF-16' }, + # '060e2b34.0101.0101.0d0b0600.00000000' => { Name => 'BroadcastScheduleInformation', Type => 'Node' }, + '060e2b34.0101.0101.0d0b0601.00000000' => { Name => 'BroadcastDate', %timestamp }, + '060e2b34.0101.0101.0d0b0602.00000000' => { Name => 'BroadcastTime', %timestamp }, + '060e2b34.0101.0101.0d0b0603.00000000' => { Name => 'IsRepeat', Type => 'Boolean' }, + '060e2b34.0101.0101.0d0b0604.00000000' => { Name => 'FirstTransmissionInfo', Type => 'UTF-16' }, + '060e2b34.0101.0101.0d0b0605.00000000' => { Name => 'TeletextSubtitlesAvailable', Type => 'Boolean' }, + '060e2b34.0101.0101.0d0b0606.00000000' => { Name => 'SeasonEpisodeNumber', Format => 'string' }, + '060e2b34.0101.0101.0d0b0607.00000000' => { Name => 'SeasonEpisodeTitle', Format => 'string' }, + '060e2b34.0101.0101.0d0b0608.00000000' => { Name => 'EPGProgramSynopsis', Type => 'UTF-16' }, + # '060e2b34.0101.0101.0d0b0700.00000000' => { Name => 'Classification', Type => 'Node' }, + '060e2b34.0101.0101.0d0b0701.00000000' => { Name => 'ContentClassification', Type => 'UTF-16' }, + '060e2b34.0101.0101.0d0b0702.00000000' => { Name => 'DVBParentalRating', Type => 'UTF-16' }, + '060e2b34.0101.0101.0d0b0703.00000000' => { Name => 'ContentMaturityRating', Type => 'UTF-16' }, + '060e2b34.0101.0101.0d0b0704.00000000' => { Name => 'ContentMaturityDescription', Type => 'UTF-16' }, + '060e2b34.0101.0101.0d0b0705.00000000' => { Name => 'ContentMaturityGraphic', Type => 'UTF-16' }, + # '060e2b34.0101.0101.0d0b0800.00000000' => { Name => 'Contract', Type => 'Node' }, + '060e2b34.0101.0101.0d0b0801.00000000' => { Name => 'ContractEntity', Type => 'UTF-16' }, + '060e2b34.0101.0101.0d0b0802.00000000' => { Name => 'ContractTypeLink', Type => 'UTF-16' }, + # '060e2b34.0101.0101.0d0b0900.00000000' => { Name => 'Rights', Type => 'Node' }, + '060e2b34.0101.0101.0d0b0901.00000000' => { Name => 'ConsumerRightsToCopy', Type => 'UTF-16' }, + '060e2b34.0101.0101.0d0b0902.00000000' => { Name => 'BroadcasterRightsToCopy', Type => 'UTF-16' }, + # '060e2b34.0101.0101.0d0b0a00.00000000' => { Name => 'ProductionKeyPeople', Type => 'Node' }, + '060e2b34.0101.0101.0d0b0a01.00000000' => { Name => 'DirectorName', Type => 'UTF-16' }, + '060e2b34.0101.0101.0d0b0a02.00000000' => { Name => 'ProducerName', Type => 'UTF-16' }, + '060e2b34.0101.0101.0d0b0a03.00000000' => { Name => 'FemaleLeadActressName', Type => 'UTF-16' }, + '060e2b34.0101.0101.0d0b0a04.00000000' => { Name => 'MaleLeadActorName', Type => 'UTF-16' }, + '060e2b34.0101.0101.0d0b0a05.00000000' => { Name => 'PresenterName', Type => 'UTF-16' }, + '060e2b34.0101.0101.0d0b0a06.00000000' => { Name => 'MainSponsorName', Type => 'UTF-16' }, + '060e2b34.0101.0101.0d0b0a07.00000000' => { Name => 'VoiceTalentName', Type => 'UTF-16' }, + # '060e2b34.0101.0101.0d0b0b00.00000000' => { Name => 'Address', Type => 'Node' }, + '060e2b34.0101.0101.0d0b0b01.00000000' => { Name => 'PostboxNumber', Type => 'UTF-16' }, + '060e2b34.0101.0101.0d0b0b02.00000000' => { Name => 'PostCodeForPostbox', Type => 'UTF-16' }, + # '060e2b34.0101.0101.0e000000.00000000' => { Name => 'PrivateUse', Type => 'Node' }, + # '060e2b34.0101.0101.0e010000.00000000' => { Name => 'MISBSystems', Type => 'Node' }, + # '060e2b34.0101.0101.0e010100.00000000' => { Name => 'MISBSystemsStreams', Type => 'Node' }, + # '060e2b34.0101.0101.0e010200.00000000' => { Name => 'MISBSystemsAttributes', Type => 'Node' }, + # '060e2b34.0101.0101.0e010300.00000000' => { Name => 'MISBSystemsComposites', Type => 'Node' }, + # '060e2b34.0101.0101.0e010400.00000000' => { Name => 'MISBSystemsIdentifiers', Type => 'Node' }, + # '060e2b34.0101.0101.0e020000.00000000' => { Name => 'ASPA', Type => 'Node' }, + # '060e2b34.0101.0101.0e020100.00000000' => { Name => 'ASPAStreams', Type => 'Node' }, + # '060e2b34.0101.0101.0e020200.00000000' => { Name => 'ASPAAttributes', Type => 'Node' }, + # '060e2b34.0101.0101.0e020201.00000000' => { Name => 'ASPARelationalAttributes', Type => 'Node' }, + # '060e2b34.0101.0101.0e020202.00000000' => { Name => 'ASPAInformationAttributes', Type => 'Node' }, + # '060e2b34.0101.0101.0e020300.00000000' => { Name => 'ASPAComposites', Type => 'Node' }, + # '060e2b34.0101.0101.0e020400.00000000' => { Name => 'ASPAIdentifiers', Type => 'Node' }, + # '060e2b34.0101.0101.0e030000.00000000' => { Name => 'MISBClassified', Type => 'Node' }, + # '060e2b34.0101.0101.0e030100.00000000' => { Name => 'MISBClassifiedStreams', Type => 'Node' }, + # '060e2b34.0101.0101.0e030200.00000000' => { Name => 'MISBClassifiedAttributes', Type => 'Node' }, + # '060e2b34.0101.0101.0e030300.00000000' => { Name => 'MISBClassifiedComposites', Type => 'Node' }, + # '060e2b34.0101.0101.0e030400.00000000' => { Name => 'MISBClassifiedIdentifiers', Type => 'Node' }, + # '060e2b34.0101.0101.0f000000.00000000' => { Name => 'EXPERIMENTALMETADATA', Type => 'Node' }, + # '060e2b34.0101.0101.43000000.00000000' => { Name => 'Legacy315M', Type => 'Node' }, + '060e2b34.0101.0102.01011003.03000000' => { Name => 'ProgramNumber', Format => 'string' }, + '060e2b34.0101.0102.01011503.00000000' => { Name => 'DefinitionObjectID', Type => 'AUID', Unknown => 1 }, + '060e2b34.0101.0102.01012005.00000000' => { Name => 'IEEEDeviceID', Format => 'int8u' }, + '060e2b34.0101.0102.01030106.00000000' => { Name => 'ProjectNumber', Format => 'string' }, + '060e2b34.0101.0102.01030201.02000000' => { Name => 'EdgeCodeHeader', Type => 'DataValue', Unknown => 1 }, + # '060e2b34.0101.0102.01030400.00000000' => { Name => 'NetworkAndStreamIdentifiers', Type => 'Node' }, + '060e2b34.0101.0102.01030401.00000000' => { Name => 'ChannelHandle', Format => 'int16s' }, + '060e2b34.0101.0102.01040102.00000000' => { Name => 'PhysicalMediaLocation', Format => 'string' }, + '060e2b34.0101.0102.01040102.01000000' => { Name => 'MediaLocation', Type => 'UTF-16' }, + '060e2b34.0101.0102.01040103.00000000' => { Name => 'TrackNumber', Format => 'int32u' }, + # '060e2b34.0101.0102.01040900.00000000' => { Name => 'SynchronizationLocators', Type => 'Node' }, + '060e2b34.0101.0102.01040901.00000000' => { Name => 'EdgeCodeStart', Type => 'Position', %duration }, + '060e2b34.0101.0102.01050800.00000000' => { Name => 'VersionTitle', Format => 'string' }, + # '060e2b34.0101.0102.01070000.00000000' => { Name => 'LocalIdentifiers', Type => 'Node' }, + # '060e2b34.0101.0102.01070100.00000000' => { Name => 'PackageIdentifiers', Type => 'Node' }, + '060e2b34.0101.0102.01070101.00000000' => { Name => 'TrackID', Format => 'int32u' }, + '060e2b34.0101.0102.01070102.00000000' => { Name => 'TrackName', Format => 'string' }, + '060e2b34.0101.0102.01070102.01000000' => { Name => 'TrackName', Type => 'UTF-16' }, + '060e2b34.0101.0102.01070102.03000000' => { Name => 'DefinitionObjectName', Format => 'string' }, + '060e2b34.0101.0102.01070102.03010000' => { Name => 'DefinitionObjectName', Type => 'UTF-16' }, + '060e2b34.0101.0102.01070103.00000000' => { Name => 'ContentPackageMetadataLink', Format => 'int8u' }, + '060e2b34.0101.0102.01070104.00000000' => { Name => 'DefinedName', Format => 'string' }, + '060e2b34.0101.0102.01070104.01000000' => { Name => 'DefinedName', Type => 'UTF-16' }, + # '060e2b34.0101.0102.010a0000.00000000' => { Name => 'OrganizationIdentifiers', Type => 'Node' }, + # '060e2b34.0101.0102.010a0100.00000000' => { Name => 'ManufacturerIdentifiers', Type => 'Node' }, + # '060e2b34.0101.0102.010a0101.00000000' => { Name => 'ManufacturerIdentifiers', Type => 'Node' }, + '060e2b34.0101.0102.010a0101.01000000' => { Name => 'DeviceManufacturerName', Format => 'string' }, + '060e2b34.0101.0102.010a0101.01010000' => { Name => 'DeviceManufacturerName', Type => 'UTF-16' }, + '060e2b34.0101.0102.010a0101.03000000' => { Name => 'ManufacturerID', Type => 'AUID', Unknown => 1 }, + '060e2b34.0101.0102.010a0102.00000000' => { Name => 'IEEEManufacturerID', Type => 'Hex' }, + '060e2b34.0101.0102.010a0103.00000000' => { Name => 'AAFManufacturerID', Type => 'AUID', Unknown => 1 }, + '060e2b34.0101.0102.02010400.00000000' => { Name => 'SupplyingDepartmentName', Format => 'string' }, + '060e2b34.0101.0102.02200303.00000000' => { Name => 'AudienceShare', Format => 'float' }, + '060e2b34.0101.0102.02200304.00000000' => { Name => 'AudienceAppreciation', Format => 'float' }, + '060e2b34.0101.0102.02300603.01050000' => { Name => 'Salutation', Format => 'string' }, + '060e2b34.0101.0102.02300603.01060000' => { Name => 'HonorsAndQualifications', Format => 'string' }, + # '060e2b34.0101.0102.03010200.00000000' => { Name => 'DataInterpretationsAndDefinitions', Type => 'Node' }, + '060e2b34.0101.0102.03010201.04000000' => { Name => 'ObjectModelVersion', Format => 'int32u' }, + '060e2b34.0101.0102.03010201.05000000' => { Name => 'SDKVersion', Type => 'VersionType' }, + # '060e2b34.0101.0102.03010202.00000000' => { Name => 'PropertyDefinitions', Type => 'Node' }, + '060e2b34.0101.0102.03010202.01000000' => { Name => 'IsOptional', Type => 'Boolean' }, + '060e2b34.0101.0102.03010202.02000000' => { Name => 'IsSearchable', Type => 'Boolean' }, + # '060e2b34.0101.0102.03010202.03000000' => { Name => 'PropertyDefaults', Type => 'Node' }, + '060e2b34.0101.0102.03010202.03010000' => { Name => 'UseDefaultValue', Type => 'Boolean' }, + '060e2b34.0101.0102.03010202.03020000' => { Name => 'DefaultDataValue', Type => 'Indirect', Unknown => 1 }, + # '060e2b34.0101.0102.03010203.00000000' => { Name => 'TypeDefinition', Type => 'Node' }, + '060e2b34.0101.0102.03010203.01000000' => { Name => 'Size', Format => 'int8u' }, + '060e2b34.0101.0102.03010203.02000000' => { Name => 'IsSigned', Type => 'Boolean' }, + '060e2b34.0101.0102.03010203.03000000' => { Name => 'ElementCount', Format => 'int32u' }, + '060e2b34.0101.0102.03010203.04000000' => { Name => 'ElementNameList', Type => 'UTF-16' }, + '060e2b34.0101.0102.03010203.05000000' => { Name => 'TypeDefinitionElementValueList', Format => 'int64s' }, + '060e2b34.0101.0102.03010203.06000000' => { Name => 'MemberNameList', Type => 'UTF-16' }, + '060e2b34.0101.0102.03010203.07000000' => { Name => 'ExtendibleElementNameList', Type => 'UTF-16' }, + '060e2b34.0101.0102.03010203.08000000' => { Name => 'TypeDefinitionExtendibleElementValues', Type => 'AUIDArray', Unknown => 1 }, + '060e2b34.0101.0102.03010203.0b000000' => { Name => 'TargetSet', Type => 'AUIDArray', Unknown => 1 }, + # '060e2b34.0101.0102.03010210.00000000' => { Name => 'KLVInterpretations', Type => 'Node' }, + '060e2b34.0101.0102.03010210.01000000' => { Name => 'FillerData', Format => 'undef', Unknown => 1 }, + '060e2b34.0101.0102.03010210.02000000' => { Name => 'KLVDataValue', Type => 'Opaque', Unknown => 1 }, + '060e2b34.0101.0102.03010210.03000000' => { Name => 'PackageKLVData', Type => 'StrongReferenceArray', Unknown => 1 }, + '060e2b34.0101.0102.03010210.04000000' => { Name => 'ComponentKLVData', Type => 'StrongReferenceArray', Unknown => 1 }, + '060e2b34.0101.0102.03020102.09000000' => { Name => 'AssignedCategoryName', Format => 'string' }, + '060e2b34.0101.0102.03020102.09010000' => { Name => 'AssignedCategoryName', Type => 'UTF-16' }, + '060e2b34.0101.0102.03020102.0a000000' => { Name => 'AssignedCategoryValue', Format => 'string' }, + '060e2b34.0101.0102.03020102.0a010000' => { Name => 'AssignedCategoryValue', Type => 'UTF-16' }, + '060e2b34.0101.0102.03020102.0b000000' => { Name => 'ShotList', Format => 'string' }, + '060e2b34.0101.0102.03020102.0c000000' => { Name => 'PackageUserComments', Type => 'StrongReferenceArray', Unknown => 1 }, + '060e2b34.0101.0102.03020102.0d000000' => { Name => 'Cue-InWords', Format => 'string' }, + '060e2b34.0101.0102.03020102.0e000000' => { Name => 'Cue-OutWords', Format => 'string' }, + '060e2b34.0101.0102.03020301.01000000' => { Name => 'ObjectKind', Format => 'string' }, + '060e2b34.0101.0102.03020301.01010000' => { Name => 'ObjectKind', Type => 'UTF-16' }, + '060e2b34.0101.0102.03020301.02000000' => { Name => 'ObjectDescription', Format => 'string' }, + '060e2b34.0101.0102.03020301.02010000' => { Name => 'ObjectDescription', Type => 'UTF-16' }, + # '060e2b34.0101.0102.03020400.00000000' => { Name => 'DescriptiveNames', Type => 'Node' }, + # '060e2b34.0101.0102.03020401.01000000' => { Name => 'GenericObjectNames', Type => 'Node' }, + '060e2b34.0101.0102.03020401.01010000' => { Name => 'ObjectName', Format => 'string' }, + '060e2b34.0101.0102.03020401.02010000' => { Name => 'MetadataItemName', Type => 'UTF-16' }, + # '060e2b34.0101.0102.03020500.00000000' => { Name => 'EditorialCommentsAndDescriptions', Type => 'Node' }, + '060e2b34.0101.0102.03020501.00000000' => { Name => 'ShotCommentKind', Format => 'string' }, + '060e2b34.0101.0102.03020502.00000000' => { Name => 'ShotComment', Format => 'string' }, + '060e2b34.0101.0102.03030301.01000000' => { Name => 'ComputedObjectKind', Format => 'string' }, + '060e2b34.0101.0102.03030301.01010000' => { Name => 'ComputedObjectKind', Type => 'UTF-16' }, + '060e2b34.0101.0102.03030301.02000000' => { Name => 'VersionNumberString', Format => 'string' }, + '060e2b34.0101.0102.03030301.02010000' => { Name => 'VersionNumberString', Type => 'UTF-16' }, + '060e2b34.0101.0102.03030301.03000000' => { Name => 'VersionNumber', Type => 'VersionType' }, + # '060e2b34.0101.0102.03030302.00000000' => { Name => 'DerivedSummaryInformation', Type => 'Node' }, + '060e2b34.0101.0102.03030302.01000000' => { Name => 'WAVESummary', Type => 'DataValue', Unknown => 1 }, + '060e2b34.0101.0102.03030302.02000000' => { Name => 'AIFCSummary', Type => 'DataValue', Unknown => 1 }, + '060e2b34.0101.0102.03030302.03000000' => { Name => 'TIFFSummary', Type => 'DataValue', Unknown => 1 }, + '060e2b34.0101.0102.04010101.03000000' => { Name => 'ViewportAspectRatio', Format => 'rational64s' }, + '060e2b34.0101.0102.04010201.01010200' => { Name => 'CaptureGammaEquation', Type => 'UL', Unknown => 1 }, + '060e2b34.0101.0102.04010201.01030100' => { Name => 'ColorimetryCode', Type => 'ColorimetryCode', Unknown => 1 }, + '060e2b34.0101.0102.04010201.01100000' => { Name => 'PresentationGammaEquation', Format => 'string' }, + '060e2b34.0101.0102.04010201.01100100' => { Name => 'PresentationGammaEquation', Type => 'PresentationGamma', Unknown => 1 }, + '060e2b34.0101.0102.04010301.06000000' => { Name => 'FieldDominance', Format => 'int8u' }, + '060e2b34.0101.0102.04010302.05000000' => { Name => 'VideoLineMap', Format => 'int32s' }, + '060e2b34.0101.0102.04010401.01000000' => { Name => 'AnalogVideoSystemName', Type => 'VideoSignalType', Unknown => 1 }, + '060e2b34.0101.0102.04010501.10000000' => { Name => 'VerticalSub-sampling', Format => 'int32u' }, + '060e2b34.0101.0102.04010503.01010000' => { Name => 'BitsPerPixel', Format => 'int32u' }, + '060e2b34.0101.0102.04010503.05000000' => { Name => 'ColorRangeLevels', Format => 'int32u' }, + '060e2b34.0101.0102.04010503.06000000' => { Name => 'PixelLayout', Type => 'RGBALayout', Unknown => 1 }, + '060e2b34.0101.0102.04010503.07000000' => { Name => 'AlphaSampleDepth', Format => 'int32u' }, + '060e2b34.0101.0102.04010503.08000000' => { Name => 'Palette', Type => 'DataValue', Unknown => 1 }, + '060e2b34.0101.0102.04010503.09000000' => { Name => 'PaletteLayout', Type => 'RGBALayout', Unknown => 1 }, + '060e2b34.0101.0102.04010503.0a000000' => { Name => 'ComponentDepth', Format => 'int32u' }, + '060e2b34.0101.0102.04010601.00000000' => { Name => 'VideoCodingSchemeID', Type => 'AUID', Unknown => 1 }, + '060e2b34.0101.0102.04010802.03000000' => { Name => 'RoundedCaptureFilmFrameRate', Format => 'int32u' }, + '060e2b34.0101.0102.04020301.02000000' => { Name => 'AudioAverageBitrate', Format => 'float', PrintConv => 'ConvertBitrate($val)', Groups => { 2 => 'Audio' } }, + '060e2b34.0101.0102.04020301.03000000' => { Name => 'AudioFixedBitrateFlag', Type => 'Boolean', Groups => { 2 => 'Audio' } }, + '060e2b34.0101.0102.04020401.00000000' => { Name => 'CodingLawKind', Format => 'string' }, + '060e2b34.0101.0102.04020402.00000000' => { Name => 'AudioCodingSchemeID', Type => 'AUID', Unknown => 1, Groups => { 2 => 'Audio' } }, + '060e2b34.0101.0102.04020403.01010000' => { Name => 'LayerNumber', Format => 'int8u' }, + '060e2b34.0101.0102.04040101.02010000' => { Name => 'TimecodeTimebase', Format => 'rational64s' }, + '060e2b34.0101.0102.04040101.02060000' => { Name => 'RoundedTimecodeTimebase', Format => 'int16u' }, + # '060e2b34.0101.0102.04070000.00000000' => { Name => 'GeneralEssenceAndDataParameters', Type => 'Node' }, + '060e2b34.0101.0102.04070100.00000000' => { Name => 'ComponentDataDefinition', Type => 'WeakReference', %componentDataDef }, + '060e2b34.0101.0102.04070200.00000000' => { Name => 'StreamData', Type => 'DataStream', Unknown => 1 }, + '060e2b34.0101.0102.04070300.00000000' => { Name => 'TimecodeStreamData', Type => 'DataStream', Unknown => 1 }, + '060e2b34.0101.0102.04090101.00000000' => { Name => 'RecordedFormat', Type => 'UTF-16' }, + '060e2b34.0101.0102.04100101.01000000' => { Name => 'TapeShellKind', Format => 'string' }, + '060e2b34.0101.0102.04100101.01010000' => { Name => 'TapeShellKind', Type => 'UTF-16' }, + '060e2b34.0101.0102.04100101.02000000' => { Name => 'TapeFormulation', Format => 'string' }, + '060e2b34.0101.0102.04100101.02010000' => { Name => 'TapeFormulation', Type => 'UTF-16' }, + '060e2b34.0101.0102.04100101.03000000' => { Name => 'TapeCapacity', Format => 'int32u' }, + '060e2b34.0101.0102.04100101.04000000' => { Name => 'TapeManufacturer', Format => 'string' }, + '060e2b34.0101.0102.04100101.04010000' => { Name => 'TapeManufacturer', Type => 'UTF-16' }, + '060e2b34.0101.0102.04100101.05000000' => { Name => 'TapeStock', Format => 'string' }, + '060e2b34.0101.0102.04100101.05010000' => { Name => 'TapeStock', Type => 'UTF-16' }, + '060e2b34.0101.0102.04100101.06000000' => { Name => 'TapeBatchNumber', Format => 'string' }, + '060e2b34.0101.0102.04100101.06010000' => { Name => 'TapeBatchNumber', Type => 'UTF-16' }, + '060e2b34.0101.0102.04100103.01030000' => { Name => 'PerforationsPerFrame', Format => 'int8u' }, + '060e2b34.0101.0102.04100103.01030100' => { Name => 'PerforationsPerFrame', Format => 'rational64s' }, + '060e2b34.0101.0102.04100103.01040100' => { Name => 'FilmFormatName', Type => 'UTF-16' }, + '060e2b34.0101.0102.04100103.01040200' => { Name => 'FilmFormatName', Type => 'FilmFormat', Unknown => 1 }, + '060e2b34.0101.0102.04100103.01050100' => { Name => 'FilmStockKind', Type => 'UTF-16' }, + '060e2b34.0101.0102.04100103.01060100' => { Name => 'FilmStockManufacturerName', Type => 'UTF-16' }, + '060e2b34.0101.0102.04100103.01070000' => { Name => 'FilmBatchNumber', Format => 'string' }, + '060e2b34.0101.0102.04100103.01070100' => { Name => 'FilmBatchNumber', Type => 'UTF-16' }, + '060e2b34.0101.0102.04100103.01080000' => { Name => 'FilmGauge', Type => 'FilmType', Unknown => 1 }, + '060e2b34.0101.0102.04100103.01090000' => { Name => 'EdgeCodeFilmGauge', Type => 'FilmType', Unknown => 1 }, + '060e2b34.0101.0102.04100103.02030000' => { Name => 'ExposedAspectRatio', Format => 'rational64s' }, + # '060e2b34.0101.0102.04180000.00000000' => { Name => 'MemoryStorageCharacteristics', Type => 'Node' }, + # '060e2b34.0101.0102.04180100.00000000' => { Name => 'MemoryStorageAlignmentCharacteristics', Type => 'Node' }, + '060e2b34.0101.0102.04180101.00000000' => { Name => 'ImageAlignmentOffset', Format => 'int32u' }, + '060e2b34.0101.0102.04180102.00000000' => { Name => 'ImageStartOffset', Format => 'int32u' }, + '060e2b34.0101.0102.04180103.00000000' => { Name => 'ImageEndOffset', Format => 'int32u' }, + '060e2b34.0101.0102.04180104.00000000' => { Name => 'PaddingBits', Format => 'int16s' }, + '060e2b34.0101.0102.04200201.01040000' => { Name => 'FocalLength', Format => 'float', PrintConv => 'sprintf("%.1f mm",$val)' }, + '060e2b34.0101.0102.04200201.01050000' => { Name => 'SensorSize', Format => 'string' }, + '060e2b34.0101.0102.04200201.01060000' => { Name => 'FNumber', Format => 'float' }, + '060e2b34.0101.0102.04200201.01070000' => { Name => 'SensorTypeCode', Format => 'string' }, + '060e2b34.0101.0102.04200201.01080000' => { Name => 'FieldOfViewHorizontal', Format => 'float' }, + '060e2b34.0101.0102.04200201.01090000' => { Name => 'AnamorphicLensCharacteristic', Format => 'string' }, + # '060e2b34.0101.0102.05020103.00000000' => { Name => 'JPEGProcessing', Type => 'Node' }, + # '060e2b34.0101.0102.05020103.01000000' => { Name => 'TIFFJPEGProcessing', Type => 'Node' }, + '060e2b34.0101.0102.05020103.01010000' => { Name => 'UniformDataFlag', Type => 'Boolean' }, + '060e2b34.0101.0102.05020103.01020000' => { Name => 'JPEGTableID', Type => 'JPEGTableIDType', Unknown => 1 }, + # '060e2b34.0101.0102.05020103.02000000' => { Name => 'JFIF_JPEGProcessing', Type => 'Node' }, + '060e2b34.0101.0102.05200102.00000000' => { Name => 'AlphaTransparency', Format => 'int8u', + PrintConv => { 0 => 'Not Inverted', 1 => 'Inverted' }, + }, + # '060e2b34.0101.0102.05200701.00000000' => { Name => 'ModificationInformation', Type => 'Node' }, + '060e2b34.0101.0102.05200701.01000000' => { Name => 'GenerationID', Type => 'AUID', Unknown => 1 }, + '060e2b34.0101.0102.05200701.02000000' => { Name => 'ApplicationSupplierName', Format => 'string' }, + '060e2b34.0101.0102.05200701.02010000' => { Name => 'ApplicationSupplierName', Type => 'UTF-16' }, + '060e2b34.0101.0102.05200701.03000000' => { Name => 'ApplicationName', Format => 'string' }, + '060e2b34.0101.0102.05200701.03010000' => { Name => 'ApplicationName', Type => 'UTF-16' }, + '060e2b34.0101.0102.05200701.04000000' => { Name => 'ApplicationVersionNumber', Type => 'ProductVersion' }, + '060e2b34.0101.0102.05200701.05000000' => { Name => 'ApplicationVersionString', Format => 'string' }, + '060e2b34.0101.0102.05200701.05010000' => { Name => 'ApplicationVersionString', Type => 'UTF-16' }, + '060e2b34.0101.0102.05200701.06000000' => { Name => 'ApplicationPlatform', Format => 'string' }, + '060e2b34.0101.0102.05200701.06010000' => { Name => 'ApplicationPlatform', Type => 'UTF-16' }, + '060e2b34.0101.0102.05200701.07000000' => { Name => 'ApplicationProductID', Type => 'AUID', Unknown => 1 }, + '060e2b34.0101.0102.05200701.08000000' => { Name => 'LinkedGenerationID', Type => 'AUID', Unknown => 1 }, + '060e2b34.0101.0102.05200701.09000000' => { Name => 'ContainerVersion', Type => 'ProductVersion' }, + '060e2b34.0101.0102.05200701.0a000000' => { Name => 'ToolkitVersion', Type => 'ProductVersion' }, + # '060e2b34.0101.0102.05200900.00000000' => { Name => 'CodeProcessorSettings', Type => 'Node' }, + '060e2b34.0101.0102.05200901.00000000' => { Name => 'Plug-InCategoryID', Type => 'AUID', Unknown => 1 }, + '060e2b34.0101.0102.05200902.00000000' => { Name => 'Plug-InPlatformID', Type => 'AUID', Unknown => 1 }, + '060e2b34.0101.0102.05200903.00000000' => { Name => 'MinimumSupportedPlatformVersion', Type => 'VersionType' }, + '060e2b34.0101.0102.05200904.00000000' => { Name => 'MaximumSupportedPlatformVersion', Type => 'VersionType' }, + '060e2b34.0101.0102.05200905.00000000' => { Name => 'Plug-InEngineID', Type => 'AUID', Unknown => 1 }, + '060e2b34.0101.0102.05200906.00000000' => { Name => 'MinimumSupportedEngineVersion', Type => 'VersionType' }, + '060e2b34.0101.0102.05200907.00000000' => { Name => 'MaximumSupportedEngineVersion', Type => 'VersionType' }, + '060e2b34.0101.0102.05200908.00000000' => { Name => 'Plug-InAPIID', Type => 'AUID', Unknown => 1 }, + '060e2b34.0101.0102.05200909.00000000' => { Name => 'MinimumAPIVersion', Type => 'VersionType' }, + '060e2b34.0101.0102.0520090a.00000000' => { Name => 'MaximumAPIVersion', Type => 'VersionType' }, + '060e2b34.0101.0102.0520090b.00000000' => { Name => 'Software-OnlySupportFlag', Type => 'Boolean' }, + '060e2b34.0101.0102.0520090c.00000000' => { Name => 'HardwareAcceleratorFlag', Type => 'Boolean' }, + '060e2b34.0101.0102.0520090d.00000000' => { Name => 'Plug-InLocatorSet', Type => 'StrongReferenceArray', Unknown => 1 }, + '060e2b34.0101.0102.0520090e.00000000' => { Name => 'AuthenticationFlag', Type => 'Boolean' }, + '060e2b34.0101.0102.0520090f.00000000' => { Name => 'AssociatedMetadataDefinition', Type => 'AUID', Unknown => 1 }, + '060e2b34.0101.0102.05300402.00000000' => { Name => 'EventTrackEditRate', Format => 'rational64s' }, + '060e2b34.0101.0102.05300403.00000000' => { Name => 'DefaultFadeEditRate', Format => 'rational64s' }, + '060e2b34.0101.0102.05300404.00000000' => { Name => 'EditingEventComment', Format => 'string' }, + '060e2b34.0101.0102.05300404.01000000' => { Name => 'EditingEventComment', Type => 'UTF-16' }, + '060e2b34.0101.0102.05300405.00000000' => { Name => 'EditRate', Format => 'rational64s' }, + '060e2b34.0101.0102.05300506.00000000' => { Name => 'OperationDefinitionID', Type => 'WeakReference', Unknown => 1 }, + '060e2b34.0101.0102.05300507.00000000' => { Name => 'Value', Type => 'Indirect', Unknown => 1 }, + '060e2b34.0101.0102.05300508.00000000' => { Name => 'EditHint', Type => 'EditHintType', Unknown => 1 }, + '060e2b34.0101.0102.05300509.00000000' => { Name => 'OperationDataDefinition', Type => 'WeakReference', Unknown => 1 }, + '060e2b34.0101.0102.0530050a.00000000' => { Name => 'OperationCategory', Type => 'AUID', Unknown => 1 }, + '060e2b34.0101.0102.0530050b.00000000' => { Name => 'DisplayUnits', Format => 'string' }, + '060e2b34.0101.0102.0530050b.01000000' => { Name => 'DisplayUnits', Type => 'UTF-16' }, + '060e2b34.0101.0102.0530050c.00000000' => { Name => 'BypassOverride', Format => 'int32u' }, + '060e2b34.0101.0102.0530050d.00000000' => { Name => 'TimepointValue', Type => 'Indirect', Unknown => 1 }, + '060e2b34.0101.0102.05300601.00000000' => { Name => 'BeginAnchor', Format => 'string' }, + '060e2b34.0101.0102.05300601.01000000' => { Name => 'BeginAnchor', Type => 'UTF-16' }, + '060e2b34.0101.0102.05300602.00000000' => { Name => 'EndAnchor', Format => 'string' }, + '060e2b34.0101.0102.05300602.01000000' => { Name => 'EndAnchor', Type => 'UTF-16' }, + # '060e2b34.0101.0102.05401000.00000000' => { Name => 'TransferHistory', Type => 'Node' }, + # '060e2b34.0101.0102.05401001.00000000' => { Name => 'ImageTransferHistory', Type => 'Node' }, + '060e2b34.0101.0102.05401001.01000000' => { Name => 'FilmToVideoTransferDirection', Type => 'PulldownDirection', Unknown => 1 }, + '060e2b34.0101.0102.05401001.02000000' => { Name => 'FilmToVideoTransferKind', Type => 'PulldownKind', Unknown => 1 }, + '060e2b34.0101.0102.05401001.03000000' => { Name => 'FilmToVideoTransferPhase', Type => 'PhaseFrameType', Unknown => 1 }, + '060e2b34.0101.0102.06010101.01000000' => { Name => 'TeletextSubtitlesFlag', Type => 'Boolean' }, + '060e2b34.0101.0102.06010101.02000000' => { Name => 'SubtitleDatafileFlag', Type => 'Boolean' }, + '060e2b34.0101.0102.06010101.03000000' => { Name => 'ClosedCaptionSubtitlesFlag', Type => 'Boolean' }, + '060e2b34.0101.0102.06010102.01000000' => { Name => 'SampleIndex', Type => 'DataStream', Unknown => 1 }, + '060e2b34.0101.0102.06010103.01000000' => { Name => 'SourcePackageID', Type => 'PackageID', Unknown => 1 }, + '060e2b34.0101.0102.06010103.02000000' => { Name => 'SourceTrackID', Format => 'int32u' }, + '060e2b34.0101.0102.06010103.03000000' => { Name => 'RelativeScope', Format => 'int32u' }, + '060e2b34.0101.0102.06010103.04000000' => { Name => 'RelativeTrack', Format => 'int32u' }, + # '060e2b34.0101.0102.06010104.01000000' => { Name => 'WeakReferences', Type => 'Node' }, + '060e2b34.0101.0102.06010104.01010000' => { Name => 'ObjectClass', Type => 'WeakReference', Unknown => 1 }, + '060e2b34.0101.0102.06010104.01020000' => { Name => 'EssenceContainerFormat', Type => 'WeakReference', Unknown => 1 }, + '060e2b34.0101.0102.06010104.01030000' => { Name => 'CodecDefinition', Type => 'WeakReference', Unknown => 1 }, + '060e2b34.0101.0102.06010104.01040000' => { Name => 'ParameterDefinition', Type => 'WeakReference', Unknown => 1 }, + '060e2b34.0101.0102.06010104.01050000' => { Name => 'Interpolation', Type => 'WeakReference', Unknown => 1 }, + '060e2b34.0101.0102.06010104.01060000' => { Name => 'ParameterDataType', Type => 'WeakReference', Unknown => 1 }, + '060e2b34.0101.0102.06010104.01070000' => { Name => 'CodecEssenceDescriptor', Type => 'WeakReference', Unknown => 1 }, + # '060e2b34.0101.0102.06010104.02000000' => { Name => 'StrongReferences', Type => 'Node' }, + '060e2b34.0101.0102.06010104.02010000' => { Name => 'ContentStorage', Type => 'StrongReference', Unknown => 1 }, + '060e2b34.0101.0102.06010104.02020000' => { Name => 'Dictionary', Type => 'StrongReference', Unknown => 1 }, + '060e2b34.0101.0102.06010104.02030000' => { Name => 'EssenceDescription', Type => 'StrongReference', Unknown => 1 }, + '060e2b34.0101.0102.06010104.02040000' => { Name => 'Sequence', Type => 'StrongReference', Unknown => 1 }, + '060e2b34.0101.0102.06010104.02050000' => { Name => 'TransitionEffect', Type => 'StrongReference', Unknown => 1 }, + '060e2b34.0101.0102.06010104.02060000' => { Name => 'EffectRendering', Type => 'StrongReference', Unknown => 1 }, + '060e2b34.0101.0102.06010104.02070000' => { Name => 'InputSegment', Type => 'StrongReference', Unknown => 1 }, + '060e2b34.0101.0102.06010104.02080000' => { Name => 'StillFrame', Type => 'StrongReference', Unknown => 1 }, + '060e2b34.0101.0102.06010104.02090000' => { Name => 'Selected', Type => 'StrongReference', Unknown => 1 }, + '060e2b34.0101.0102.06010104.020a0000' => { Name => 'Annotation', Type => 'StrongReference', Unknown => 1 }, + '060e2b34.0101.0102.06010104.020b0000' => { Name => 'ManufacturerInformationObject', Type => 'StrongReference', Unknown => 1 }, + # '060e2b34.0101.0102.06010104.03000000' => { Name => 'WeakReferencesBatches', Type => 'Node' }, + '060e2b34.0101.0102.06010104.03010000' => { Name => 'CodecEssenceKinds', Type => 'WeakReferenceBatch', Unknown => 1 }, + '060e2b34.0101.0102.06010104.03020000' => { Name => 'OperationParameters', Type => 'WeakReferenceBatch', Unknown => 1 }, + # '060e2b34.0101.0102.06010104.04000000' => { Name => 'WeakReferencesArrays', Type => 'Node' }, + '060e2b34.0101.0102.06010104.04010000' => { Name => 'DegradedEffects', Type => 'WeakReferenceArray', Unknown => 1 }, + # '060e2b34.0101.0102.06010104.05000000' => { Name => 'StrongReferencesBatches', Type => 'Node' }, + '060e2b34.0101.0102.06010104.05010000' => { Name => 'Packages', Type => 'StrongReferenceBatch', Unknown => 1 }, + '060e2b34.0101.0102.06010104.05020000' => { Name => 'EssenceData', Type => 'StrongReferenceBatch', Unknown => 1 }, + '060e2b34.0101.0102.06010104.05030000' => { Name => 'OperationDefinitions', Type => 'StrongReferenceBatch', Unknown => 1 }, + '060e2b34.0101.0102.06010104.05040000' => { Name => 'ParameterDefinitions', Type => 'StrongReferenceBatch', Unknown => 1 }, + '060e2b34.0101.0102.06010104.05050000' => { Name => 'DataDefinitions', Type => 'StrongReferenceBatch', Unknown => 1 }, + '060e2b34.0101.0102.06010104.05060000' => { Name => 'Plug-InDefinitions', Type => 'StrongReferenceBatch', Unknown => 1 }, + '060e2b34.0101.0102.06010104.05070000' => { Name => 'CodecDefinitions', Type => 'StrongReferenceBatch', Unknown => 1 }, + '060e2b34.0101.0102.06010104.05080000' => { Name => 'ContainerDefinitions', Type => 'StrongReferenceBatch', Unknown => 1 }, + '060e2b34.0101.0102.06010104.05090000' => { Name => 'InterpolationDefinitions', Type => 'StrongReferenceBatch', Unknown => 1 }, + # '060e2b34.0101.0102.06010104.06000000' => { Name => 'StrongReferencesArrays', Type => 'Node' }, + '060e2b34.0101.0102.06010104.06010000' => { Name => 'AvailableRepresentations', Type => 'StrongReferenceArray', Unknown => 1 }, + '060e2b34.0101.0102.06010104.06020000' => { Name => 'InputSegments', Type => 'StrongReferenceArray', Unknown => 1 }, + '060e2b34.0101.0102.06010104.06030000' => { Name => 'EssenceLocators', Type => 'StrongReferenceArray', Unknown => 1 }, + '060e2b34.0101.0102.06010104.06040000' => { Name => 'IdentificationList', Type => 'StrongReferenceArray', Unknown => 1 }, + '060e2b34.0101.0102.06010104.06050000' => { Name => 'Tracks', Type => 'StrongReferenceArray', Unknown => 1 }, + '060e2b34.0101.0102.06010104.06060000' => { Name => 'ControlPointList', Type => 'StrongReferenceArray', Unknown => 1 }, + '060e2b34.0101.0102.06010104.06070000' => { Name => 'PackageTracks', Type => 'StrongReferenceArray', Unknown => 1 }, + '060e2b34.0101.0102.06010104.06080000' => { Name => 'Alternates', Type => 'StrongReferenceArray', Unknown => 1 }, + '060e2b34.0101.0102.06010104.06090000' => { Name => 'ComponentsInSequence', Type => 'StrongReferenceArray', Unknown => 1 }, + '060e2b34.0101.0102.06010104.060a0000' => { Name => 'Parameters', Type => 'StrongReferenceBatch', Unknown => 1 }, + # '060e2b34.0101.0102.06010106.00000000' => { Name => 'EssenceToObjectRelationships', Type => 'Node' }, + '060e2b34.0101.0102.06010106.01000000' => { Name => 'LinkedPackageID', Type => 'PackageID', Unknown => 1 }, + # '060e2b34.0101.0102.06010107.00000000' => { Name => 'ObjectDictionaryToMetadataRelationships', Type => 'Node' }, + '060e2b34.0101.0102.06010107.01000000' => { Name => 'ParentClass', Type => 'WeakReference', Unknown => 1 }, + '060e2b34.0101.0102.06010107.02000000' => { Name => 'Properties', Type => 'StrongReferenceBatch', Unknown => 1 }, + '060e2b34.0101.0102.06010107.03000000' => { Name => 'IsConcrete', Type => 'Boolean' }, + '060e2b34.0101.0102.06010107.04000000' => { Name => 'PropertyType', Type => 'WeakReference', Unknown => 1 }, + '060e2b34.0101.0102.06010107.05000000' => { Name => 'LocalID', Format => 'int16u' }, + '060e2b34.0101.0102.06010107.06000000' => { Name => 'IsUniqueIdentifier', Type => 'Boolean' }, + '060e2b34.0101.0102.06010107.07000000' => { Name => 'ClassDefinitions', Type => 'StrongReferenceBatch', Unknown => 1 }, + '060e2b34.0101.0102.06010107.08000000' => { Name => 'TypeDefinitions', Type => 'StrongReferenceBatch', Unknown => 1 }, + '060e2b34.0101.0102.06010107.09000000' => { Name => 'TargetClassOfStrongReference', Type => 'WeakReference', Unknown => 1 }, + '060e2b34.0101.0102.06010107.0a000000' => { Name => 'TargetClassOfWeakReference', Type => 'WeakReference', Unknown => 1 }, + '060e2b34.0101.0102.06010107.0b000000' => { Name => 'EnumerationUnderlyingIntegerType', Type => 'WeakReference', Unknown => 1 }, + '060e2b34.0101.0102.06010107.0c000000' => { Name => 'FixedArrayElementType', Type => 'WeakReference', Unknown => 1 }, + '060e2b34.0101.0102.06010107.0d000000' => { Name => 'VariableArrayElementType', Type => 'WeakReference', Unknown => 1 }, + '060e2b34.0101.0102.06010107.0e000000' => { Name => 'SetElementType', Type => 'WeakReference', Unknown => 1 }, + '060e2b34.0101.0102.06010107.0f000000' => { Name => 'StringElementType', Type => 'WeakReference', Unknown => 1 }, + '060e2b34.0101.0102.06010107.10000000' => { Name => 'StreamElementType', Type => 'WeakReference', Unknown => 1 }, + '060e2b34.0101.0102.06010107.11000000' => { Name => 'MemberTypes', Type => 'WeakReferenceArray', Unknown => 1 }, + '060e2b34.0101.0102.06010107.12000000' => { Name => 'RenamedType', Type => 'WeakReference', Unknown => 1 }, + '060e2b34.0101.0102.06010107.13000000' => { Name => 'DictionaryIdentifier', Type => 'AUID', Unknown => 1 }, + '060e2b34.0101.0102.06010107.14000000' => { Name => 'DictionaryDescription', Format => 'string' }, + '060e2b34.0101.0102.06010107.14010000' => { Name => 'DictionaryDescription', Type => 'UTF-16' }, + # '060e2b34.0101.0102.06080101.00000000' => { Name => 'ContinuityCounts', Type => 'Node' }, + '060e2b34.0101.0102.06080101.01000000' => { Name => 'BlockContinuityCount', Format => 'int16u' }, + # '060e2b34.0101.0102.06080102.00000000' => { Name => 'StreamPositionalRelationships', Type => 'Node' }, + '060e2b34.0101.0102.06080102.01000000' => { Name => 'StreamPositionIndicator', Format => 'int8u' }, + # '060e2b34.0101.0102.06080202.00000000' => { Name => 'StorageOffsets', Type => 'Node' }, + '060e2b34.0101.0102.07020103.01030000' => { Name => 'Origin', Format => 'int64s', %duration }, + '060e2b34.0101.0102.07020103.01040000' => { Name => 'StartTimeRelativeToReference', Format => 'int64s', %duration }, + '060e2b34.0101.0102.07020103.01050000' => { Name => 'StartTimecode', Format => 'int64s', %duration }, + '060e2b34.0101.0102.07020103.01060000' => { Name => 'CutPoint', Format => 'int64s', %duration }, + '060e2b34.0101.0102.07020103.03030000' => { Name => 'EventStart', Type => 'Position', %duration }, + # '060e2b34.0101.0102.07020103.10020000' => { Name => 'EditOffsets', Type => 'Node' }, + '060e2b34.0101.0102.07020103.10020100' => { Name => 'ControlPointTime', Format => 'rational64s' }, + '060e2b34.0101.0102.07020110.01030000' => { Name => 'CreateDate', %timestamp }, + '060e2b34.0101.0102.07020110.02030000' => { Name => 'ModifyDate', %timestamp }, + '060e2b34.0101.0102.07020110.02040000' => { Name => 'ContainerLastModifyDate', %timestamp }, + '060e2b34.0101.0102.07020110.02050000' => { Name => 'PackageLastModifyDate', %timestamp }, + '060e2b34.0101.0102.07020201.01030000' => { Name => 'Duration', Type => 'Length', %duration }, + '060e2b34.0101.0102.07020201.01050100' => { Name => 'DefaultFadeDuration', Type => 'Length', %duration }, + '060e2b34.0101.0102.07020201.01050200' => { Name => 'Fade-InDuration', Type => 'Length', %duration }, + '060e2b34.0101.0102.07020201.01050300' => { Name => 'Fade-OutDuration', Type => 'Length', %duration }, + '060e2b34.0101.0102.0d010101.01010100' => { Name => 'TapeFormat', Type => 'TapeFormatType', Unknown => 1 }, + '060e2b34.0101.0103.01011001.01000000' => { Name => 'OrganizationID', Type => 'UTF-16' }, + '060e2b34.0101.0103.01011504.00000000' => { Name => 'GlobalNumber', Format => 'string' }, + '060e2b34.0101.0103.01012007.00000000' => { Name => 'DeviceIDKind', Format => 'string' }, + '060e2b34.0101.0103.01012008.00000000' => { Name => 'DeviceKind', Format => 'string' }, + '060e2b34.0101.0103.01012008.02000000' => { Name => 'DeviceKindCode', Format => 'string' }, + # '060e2b34.0101.0103.01012100.00000000' => { Name => 'PlatformIdentifiers', Type => 'Node' }, + '060e2b34.0101.0103.01012101.00000000' => { Name => 'PlatformDesignation', Format => 'string' }, + '060e2b34.0101.0103.01012102.00000000' => { Name => 'PlatformModel', Format => 'string' }, + '060e2b34.0101.0103.01012103.00000000' => { Name => 'PlatformSerialNumber', Format => 'string' }, + '060e2b34.0101.0103.01030107.00000000' => { Name => 'LocalTargetID', Format => 'string' }, + # '060e2b34.0101.0103.01030203.00000000' => { Name => 'DiskIdentifiers', Type => 'Node' }, + # '060e2b34.0101.0103.01030203.01000000' => { Name => 'MagneticDisks', Type => 'Node' }, + '060e2b34.0101.0103.01030203.01010000' => { Name => 'MagneticDiskNumber', Format => 'string' }, + # '060e2b34.0101.0103.01030203.02000000' => { Name => 'OpticalDiscs', Type => 'Node' }, + '060e2b34.0101.0103.01030203.02010000' => { Name => 'OpticalDiscNumber', Format => 'string' }, + '060e2b34.0101.0103.01030402.00000000' => { Name => 'StreamID', Format => 'int8u' }, + '060e2b34.0101.0103.01030403.00000000' => { Name => 'TransportStreamID', Format => 'int16u' }, + # '060e2b34.0101.0103.01030500.00000000' => { Name => 'OrganizationalProgramIdentifiers', Type => 'Node' }, + '060e2b34.0101.0103.01030501.00000000' => { Name => 'OrganizationalProgramNumber', Format => 'string' }, + '060e2b34.0101.0103.01030501.01000000' => { Name => 'OrganizationalProgramNumber', Type => 'UTF-16' }, + # '060e2b34.0101.0103.01030600.00000000' => { Name => 'MetadataIdentifiers', Type => 'Node' }, + '060e2b34.0101.0103.01030601.00000000' => { Name => 'ItemDesignatorID', Type => 'SMPTE336M', Unknown => 1 }, + '060e2b34.0101.0103.01040101.01000000' => { Name => 'LocalFilePath', Type => 'UTF-16' }, + '060e2b34.0101.0103.01050101.00000000' => { Name => 'TitleKind', Type => 'UTF-16' }, + '060e2b34.0101.0103.01050201.00000000' => { Name => 'MainTitle', Type => 'UTF-16' }, + '060e2b34.0101.0103.01050301.00000000' => { Name => 'SecondaryTitle', Type => 'UTF-16' }, + '060e2b34.0101.0103.01050401.00000000' => { Name => 'SeriesNumber', Type => 'UTF-16' }, + '060e2b34.0101.0103.01050501.00000000' => { Name => 'EpisodeNumber', Type => 'UTF-16' }, + '060e2b34.0101.0103.01050601.00000000' => { Name => 'SceneNumber', Type => 'UTF-16' }, + '060e2b34.0101.0103.01050801.00000000' => { Name => 'VersionTitle', Type => 'UTF-16' }, + '060e2b34.0101.0103.01050900.00000000' => { Name => 'MissionID', Format => 'string' }, + '060e2b34.0101.0103.01050901.00000000' => { Name => 'MissionID', Type => 'UTF-16' }, + # '060e2b34.0101.0103.01100300.00000000' => { Name => 'MusicIndustryIdentifiers', Type => 'Node' }, + '060e2b34.0101.0103.01100301.00000000' => { Name => 'RecordingLabelName', Format => 'string' }, + '060e2b34.0101.0103.01100301.01000000' => { Name => 'RecordingLabelName', Type => 'UTF-16' }, + '060e2b34.0101.0103.01100302.00000000' => { Name => 'CollectionName', Format => 'string' }, + '060e2b34.0101.0103.01100302.01000000' => { Name => 'CollectionName', Type => 'UTF-16' }, + '060e2b34.0101.0103.01100303.00000000' => { Name => 'OriginCode', Format => 'string' }, + '060e2b34.0101.0103.01100304.00000000' => { Name => 'MainCatalogNumber', Format => 'string' }, + '060e2b34.0101.0103.01100305.00000000' => { Name => 'CatalogPrefixNumber', Format => 'string' }, + '060e2b34.0101.0103.01100306.00000000' => { Name => 'SideNumber', Format => 'string' }, + '060e2b34.0101.0103.01100307.00000000' => { Name => 'RecordedTrackNumber', Format => 'string' }, + '060e2b34.0101.0103.02020200.00000000' => { Name => 'SeriesinaSeriesGroupCount', Format => 'int16u' }, + '060e2b34.0101.0103.02020300.00000000' => { Name => 'ProgrammingGroupKind', Format => 'string' }, + # '060e2b34.0101.0103.02030000.00000000' => { Name => 'Purchaser', Type => 'Node' }, + '060e2b34.0101.0103.02030100.00000000' => { Name => 'PurchasingOrganizationName', Format => 'string' }, + '060e2b34.0101.0103.02030200.00000000' => { Name => 'SalesContractNumber', Format => 'string' }, + '060e2b34.0101.0103.02030400.00000000' => { Name => 'PurchasingDepartment', Format => 'string' }, + # '060e2b34.0101.0103.02040000.00000000' => { Name => 'ContractDescriptions', Type => 'Node' }, + '060e2b34.0101.0103.02040100.00000000' => { Name => 'ContractType', Format => 'string' }, + '060e2b34.0101.0103.02040101.00000000' => { Name => 'ContractTypeCode', Format => 'string' }, + '060e2b34.0101.0103.02040200.00000000' => { Name => 'ContractClauseDescription', Format => 'string' }, + '060e2b34.0101.0103.02040300.00000000' => { Name => 'ContractLineCode', Format => 'string' }, + '060e2b34.0101.0103.02040301.00000000' => { Name => 'ContractLineName', Format => 'string' }, + '060e2b34.0101.0103.02040400.00000000' => { Name => 'ContractTermsOfBusiness', Format => 'string' }, + '060e2b34.0101.0103.02040500.00000000' => { Name => 'ContractInstallmentPercentage', Format => 'float' }, + '060e2b34.0101.0103.02040600.00000000' => { Name => 'Jurisdiction', Format => 'string' }, + '060e2b34.0101.0103.02050101.01000000' => { Name => 'CopyrightStatus', Type => 'UTF-16' }, + '060e2b34.0101.0103.02050102.01000000' => { Name => 'CopyrightOwnerName', Type => 'UTF-16' }, + '060e2b34.0101.0103.02050201.01000000' => { Name => 'IntellectualPropertyDescription', Type => 'UTF-16' }, + '060e2b34.0101.0103.02050202.01000000' => { Name => 'IntellectualPropertyRights', Type => 'UTF-16' }, + '060e2b34.0101.0103.02050301.01000000' => { Name => 'Rightsholder', Type => 'UTF-16' }, + '060e2b34.0101.0103.02050302.01000000' => { Name => 'RightsManagementAuthority', Type => 'UTF-16' }, + '060e2b34.0101.0103.02050403.00000000' => { Name => 'RightsConditionDescription', Format => 'string' }, + '060e2b34.0101.0103.02050403.01000000' => { Name => 'RightsConditionDescription', Type => 'UTF-16' }, + '060e2b34.0101.0103.02060101.01000000' => { Name => 'CurrencyName', Format => 'string' }, + '060e2b34.0101.0103.02060202.00000000' => { Name => 'TotalPayment', Format => 'string' }, + '060e2b34.0101.0103.02060203.00000000' => { Name => 'PayeeAccountName', Format => 'string' }, + '060e2b34.0101.0103.02060204.00000000' => { Name => 'PayeeAccountNumber', Format => 'string' }, + '060e2b34.0101.0103.02060205.00000000' => { Name => 'PayeeAccountSortCode', Format => 'string' }, + '060e2b34.0101.0103.02060302.00000000' => { Name => 'TotalIncome', Format => 'string' }, + '060e2b34.0101.0103.02060303.00000000' => { Name => 'PayerAccountName', Format => 'string' }, + '060e2b34.0101.0103.02060304.00000000' => { Name => 'PayerAccountNumber', Format => 'string' }, + '060e2b34.0101.0103.02060305.00000000' => { Name => 'PayerAccountSortCode', Format => 'string' }, + # '060e2b34.0101.0103.02080200.00000000' => { Name => 'Classification', Type => 'Node' }, + '060e2b34.0101.0103.02080201.00000000' => { Name => 'SecurityClassification', Format => 'string' }, + '060e2b34.0101.0103.02080202.00000000' => { Name => 'SecurityClassificationCaveats', Format => 'string' }, + '060e2b34.0101.0103.02080203.00000000' => { Name => 'ClassifiedBy', Format => 'string' }, + '060e2b34.0101.0103.02080204.00000000' => { Name => 'ClassificationReason', Format => 'string' }, + '060e2b34.0101.0103.02080205.00000000' => { Name => 'DeclassificationDate', Format => 'string', Groups => { 2 => 'Time' } }, + '060e2b34.0101.0103.02080206.00000000' => { Name => 'DerivedFrom', Format => 'string' }, + '060e2b34.0101.0103.02080207.00000000' => { Name => 'ClassificationComment', Format => 'string' }, + '060e2b34.0101.0103.02080208.00000000' => { Name => 'ClassificationAndMarkingSystem', Format => 'string' }, + '060e2b34.0101.0103.02100101.01010000' => { Name => 'BroadcastOrganizationName', Type => 'UTF-16' }, + '060e2b34.0101.0103.02100101.02010000' => { Name => 'BroadcastServiceName', Type => 'UTF-16' }, + '060e2b34.0101.0103.02100101.03020000' => { Name => 'BroadcastMediumCode', Format => 'string' }, + '060e2b34.0101.0103.02100101.04010000' => { Name => 'BroadcastRegion', Type => 'UTF-16' }, + '060e2b34.0101.0103.02300101.01000000' => { Name => 'NatureOfPersonality', Type => 'UTF-16' }, + '060e2b34.0101.0103.02300102.01010000' => { Name => 'ContributionStatus', Type => 'UTF-16' }, + '060e2b34.0101.0103.02300103.01010000' => { Name => 'SupportOrAdministrationStatus', Type => 'UTF-16' }, + '060e2b34.0101.0103.02300201.01000000' => { Name => 'OrganizationKind', Type => 'UTF-16' }, + '060e2b34.0101.0103.02300202.01010000' => { Name => 'ProductionOrganizationRole', Type => 'UTF-16' }, + '060e2b34.0101.0103.02300203.01010000' => { Name => 'SupportOrganizationRole', Type => 'UTF-16' }, + '060e2b34.0101.0103.02300501.01000000' => { Name => 'JobFunctionName', Type => 'UTF-16' }, + '060e2b34.0101.0103.02300501.02000000' => { Name => 'JobFunctionCode', Format => 'string' }, + '060e2b34.0101.0103.02300502.01000000' => { Name => 'RoleName', Type => 'UTF-16' }, + '060e2b34.0101.0103.02300503.00000000' => { Name => 'JobTitle', Format => 'string' }, + '060e2b34.0101.0103.02300503.01000000' => { Name => 'JobTitle', Type => 'UTF-16' }, + '060e2b34.0101.0103.02300601.01000000' => { Name => 'ContactKind', Type => 'UTF-16' }, + '060e2b34.0101.0103.02300602.01000000' => { Name => 'ContactDepartmentName', Type => 'UTF-16' }, + '060e2b34.0101.0103.02300603.01010100' => { Name => 'FamilyName', Type => 'UTF-16' }, + '060e2b34.0101.0103.02300603.01020100' => { Name => 'FirstGivenName', Type => 'UTF-16' }, + '060e2b34.0101.0103.02300603.01030100' => { Name => 'SecondGivenName', Type => 'UTF-16' }, + '060e2b34.0101.0103.02300603.01040100' => { Name => 'ThirdGivenName', Type => 'UTF-16' }, + '060e2b34.0101.0103.02300603.01070000' => { Name => 'PersonDescription', Format => 'string' }, + '060e2b34.0101.0103.02300603.01070100' => { Name => 'PersonDescription', Type => 'UTF-16' }, + '060e2b34.0101.0103.02300603.02010100' => { Name => 'MainName', Type => 'UTF-16' }, + '060e2b34.0101.0103.02300603.02020100' => { Name => 'SupplementaryName', Type => 'UTF-16' }, + '060e2b34.0101.0103.02300603.03010100' => { Name => 'OrganizationMainName', Type => 'UTF-16' }, + '060e2b34.0101.0103.02300603.03020100' => { Name => 'SupplementaryOrganizationName', Type => 'UTF-16' }, + '060e2b34.0101.0103.03010101.02000000' => { Name => 'RegionCode', Format => 'string' }, + # '060e2b34.0101.0103.03010101.10000000' => { Name => 'CountryAndRegionNames', Type => 'Node' }, + '060e2b34.0101.0103.03010101.10010000' => { Name => 'CountryName', Format => 'string' }, + '060e2b34.0101.0103.03010101.10010100' => { Name => 'CountryName', Type => 'UTF-16' }, + '060e2b34.0101.0103.03010101.10020000' => { Name => 'RegionName', Format => 'string' }, + '060e2b34.0101.0103.03010101.10020100' => { Name => 'RegionName', Type => 'UTF-16' }, + # '060e2b34.0101.0103.03010102.10000000' => { Name => 'LanguageNames', Type => 'Node' }, + '060e2b34.0101.0103.03010102.10010000' => { Name => 'LanguageName', Format => 'string' }, + '060e2b34.0101.0103.03010102.10010100' => { Name => 'LanguageName', Type => 'UTF-16' }, + '060e2b34.0101.0103.03010210.05000000' => { Name => 'TerminatingFillerData', Format => 'int8u' }, + '060e2b34.0101.0103.03010303.03000000' => { Name => 'TimingBiasCorrection', Format => 'float' }, + '060e2b34.0101.0103.03010303.04000000' => { Name => 'TimingBiasCorrectionDescription', Format => 'string' }, + '060e2b34.0101.0103.03020101.03010000' => { Name => 'Genre', Type => 'UTF-16' }, + '060e2b34.0101.0103.03020101.04010000' => { Name => 'TargetAudience', Type => 'UTF-16' }, + '060e2b34.0101.0103.03020101.10000000' => { Name => 'ProgramMaterialClassificationCode', Format => 'string' }, + '060e2b34.0101.0103.03020102.03010000' => { Name => 'Theme', Type => 'UTF-16' }, + '060e2b34.0101.0103.03020102.04010000' => { Name => 'SubjectName', Format => 'string' }, + '060e2b34.0101.0103.03020102.04020000' => { Name => 'SubjectName', Type => 'UTF-16' }, + '060e2b34.0101.0103.03020102.05010000' => { Name => 'Keywords', Type => 'UTF-16' }, + '060e2b34.0101.0103.03020102.0f000000' => { Name => 'KeyFrameSampleCount', Format => 'int32u' }, + '060e2b34.0101.0103.03020106.01010000' => { Name => 'Abstract', Type => 'UTF-16' }, + '060e2b34.0101.0103.03020106.02010000' => { Name => 'Purpose', Type => 'UTF-16' }, + '060e2b34.0101.0103.03020106.03010000' => { Name => 'Description', Type => 'UTF-16' }, + '060e2b34.0101.0103.03020106.04010000' => { Name => 'ColorDescriptor', Type => 'UTF-16' }, + '060e2b34.0101.0103.03020106.05010000' => { Name => 'FormatDescriptor', Type => 'UTF-16' }, + '060e2b34.0101.0103.03020106.06000000' => { Name => 'IntentDescriptor', Format => 'string' }, + '060e2b34.0101.0103.03020106.06010000' => { Name => 'IntentDescriptor', Type => 'UTF-16' }, + '060e2b34.0101.0103.03020106.07000000' => { Name => 'TextualDescriptionKind', Format => 'string' }, + '060e2b34.0101.0103.03020106.07010000' => { Name => 'TextualDescriptionKind', Type => 'UTF-16' }, + '060e2b34.0101.0103.03020201.03000000' => { Name => 'FestivalName', Format => 'string' }, + '060e2b34.0101.0103.03020301.02020000' => { Name => 'ObjectDescriptionCode', Format => 'string' }, + # '060e2b34.0101.0103.03020302.00000000' => { Name => 'GeneralComments', Type => 'Node' }, + '060e2b34.0101.0103.03020302.01000000' => { Name => 'DescriptionKind', Format => 'string' }, + '060e2b34.0101.0103.03020302.01010000' => { Name => 'DescriptionKind', Type => 'UTF-16' }, + '060e2b34.0101.0103.03020302.02000000' => { Name => 'DescriptiveComment', Format => 'string' }, + '060e2b34.0101.0103.03020302.02010000' => { Name => 'DescriptiveComment', Type => 'UTF-16' }, + # '060e2b34.0101.0103.03020401.00000000' => { Name => 'ObjectNames', Type => 'Node' }, + # '060e2b34.0101.0103.03020600.00000000' => { Name => 'Human-AssignedContextDescriptions', Type => 'Node' }, + '060e2b34.0101.0103.03020601.00000000' => { Name => 'ContextDescription', Format => 'string' }, + '060e2b34.0101.0103.03030102.06010000' => { Name => 'ComputedKeywords', Type => 'UTF-16' }, + '060e2b34.0101.0103.03030301.04000000' => { Name => 'ObjectIdentificationConfidence', Format => 'int16u' }, + '060e2b34.0101.0103.03030301.05000000' => { Name => 'ObjectHorizontalAverageDimension', Format => 'int32u' }, + '060e2b34.0101.0103.03030301.06000000' => { Name => 'ObjectVerticalAverageDimension', Format => 'int32u' }, + '060e2b34.0101.0103.03030301.07000000' => { Name => 'ObjectAreaDimension', Format => 'int32u' }, + '060e2b34.0101.0103.04010101.04000000' => { Name => 'HorizontalActionSafePercentage', Format => 'float' }, + '060e2b34.0101.0103.04010101.05000000' => { Name => 'VerticalActionSafePercentage', Format => 'float' }, + '060e2b34.0101.0103.04010101.06000000' => { Name => 'HorizontalGraphicsSafePercentage', Format => 'float' }, + '060e2b34.0101.0103.04010101.07000000' => { Name => 'VerticalGraphicsSafePercentage', Format => 'float' }, + '060e2b34.0101.0103.04010101.08000000' => { Name => 'PerceivedDisplayFormatName', Format => 'string' }, + '060e2b34.0101.0103.04010101.08010000' => { Name => 'PerceivedDisplayFormatCode', Format => 'string' }, + '060e2b34.0101.0103.04010201.01050000' => { Name => 'VideoColorKind', Format => 'string' }, + '060e2b34.0101.0103.04010301.07000000' => { Name => 'PictureDisplayRate', Format => 'int16u' }, + '060e2b34.0101.0103.04010501.11000000' => { Name => 'VideoAverageBitrate', Format => 'float', PrintConv => 'ConvertBitrate($val)' }, + '060e2b34.0101.0103.04010501.12000000' => { Name => 'VideoFixedBitrate', Type => 'Boolean' }, + # '060e2b34.0101.0103.04010b00.00000000' => { Name => 'VideoFileFormats', Type => 'Node' }, + '060e2b34.0101.0103.04010b01.00000000' => { Name => 'DigitalVideoFileFormat', Format => 'string' }, + '060e2b34.0101.0103.04020401.01000000' => { Name => 'CodingLawName', Format => 'string' }, + '060e2b34.0101.0103.04020402.01000000' => { Name => 'AudioCodingSchemeCode', Format => 'string', Groups => { 2 => 'Audio' } }, + '060e2b34.0101.0103.04020402.02000000' => { Name => 'AudioCodingSchemeName', Format => 'string', Groups => { 2 => 'Audio' } }, + '060e2b34.0101.0103.04030301.00000000' => { Name => 'DigitalEncodingBitrate', Format => 'int32u', PrintConv => 'ConvertBitrate($val)' }, + '060e2b34.0101.0103.04030302.00000000' => { Name => 'DataEssenceCodingID', Type => 'AUID', Unknown => 1 }, + # '060e2b34.0101.0103.040f0000.00000000' => { Name => 'StorageCharacteristics', Type => 'Node' }, + '060e2b34.0101.0103.040f0100.00000000' => { Name => 'StorageKind', Format => 'string' }, + '060e2b34.0101.0103.040f0101.00000000' => { Name => 'StorageKind', Type => 'UTF-16' }, + '060e2b34.0101.0103.040f0102.00000000' => { Name => 'StorageKindCode', Format => 'string' }, + # '060e2b34.0101.0103.04100101.10000000' => { Name => 'TapeMediumFundamentalParameters', Type => 'Node' }, + '060e2b34.0101.0103.04100101.10010000' => { Name => 'TapePartitionCapacity', Format => 'int64u' }, + # '060e2b34.0101.0103.04100102.01000000' => { Name => 'DiscMediumFundamentalParameters', Type => 'Node' }, + '060e2b34.0101.0103.04100102.02000000' => { Name => 'DiscPartitionCapacity', Format => 'int64u' }, + '060e2b34.0101.0103.04200201.01040100' => { Name => 'FocalLength', Format => 'int32u', ValueConv => '$val/10' }, + '060e2b34.0101.0103.04200201.01080100' => { Name => 'FieldOfViewHorizontal', Format => 'int16u', ValueConv => '$val/10' }, + '060e2b34.0101.0103.04200201.010a0000' => { Name => 'FieldOfViewVertical', Format => 'int16u', ValueConv => '$val/10' }, + # '060e2b34.0101.0103.04300000.00000000' => { Name => 'SystemCharacteristics', Type => 'Node' }, + '060e2b34.0101.0103.04300100.00000000' => { Name => 'SystemNameOrNumber', Format => 'string' }, + '060e2b34.0101.0103.05010104.00000000' => { Name => 'LogoFlag', Type => 'Boolean' }, + '060e2b34.0101.0103.05010106.00000000' => { Name => 'GraphicKind', Format => 'string' }, + '060e2b34.0101.0103.05010107.00000000' => { Name => 'GraphicUsageKind', Format => 'string' }, + '060e2b34.0101.0103.05010401.00000000' => { Name => 'SignatureTuneFlag', Type => 'Boolean' }, + '060e2b34.0101.0103.05010402.00000000' => { Name => 'BackgroundMusicFlag', Type => 'Boolean' }, + # '060e2b34.0101.0103.06030000.00000000' => { Name => 'RelatedProductionContent', Type => 'Node' }, + # '060e2b34.0101.0103.06030500.00000000' => { Name => 'RelatedTextualContent', Type => 'Node' }, + '060e2b34.0101.0103.06030501.00000000' => { Name => 'ProductionScriptReference', Format => 'string' }, + '060e2b34.0101.0103.06030501.01000000' => { Name => 'ProductionScriptReference', Type => 'UTF-16' }, + '060e2b34.0101.0103.06030502.00000000' => { Name => 'TranscriptReference', Format => 'string' }, + '060e2b34.0101.0103.06030502.01000000' => { Name => 'TranscriptReference', Type => 'UTF-16' }, + '060e2b34.0101.0103.07010103.00000000' => { Name => 'HorizontalDatum', Format => 'string' }, + '060e2b34.0101.0103.07010104.00000000' => { Name => 'VerticalDatum', Format => 'string' }, + '060e2b34.0101.0103.07010201.02040200' => { Name => 'DeviceLatitude', Format => 'double', %geoLat }, + '060e2b34.0101.0103.07010201.02060200' => { Name => 'DeviceLongitude', Format => 'double', %geoLon }, + '060e2b34.0101.0103.07010201.03020200' => { Name => 'FrameCenterLatitude', Format => 'double', %geoLat }, + '060e2b34.0101.0103.07010201.03040200' => { Name => 'FrameCenterLongitude', Format => 'double', %geoLon }, + '060e2b34.0101.0103.07010201.03070000' => { Name => 'CornerLatitudePoint1', Format => 'string', %geoLat, ValueConv => \&ConvLatLon }, + '060e2b34.0101.0103.07010201.03070100' => { Name => 'CornerLatitudePoint1', Format => 'double', %geoLat }, + '060e2b34.0101.0103.07010201.03080000' => { Name => 'CornerLatitudePoint2', Format => 'string', %geoLat }, + '060e2b34.0101.0103.07010201.03080100' => { Name => 'CornerLatitudePoint2', Format => 'double', %geoLat }, + '060e2b34.0101.0103.07010201.03090000' => { Name => 'CornerLatitudePoint3', Format => 'string', %geoLat }, + '060e2b34.0101.0103.07010201.03090100' => { Name => 'CornerLatitudePoint3', Format => 'double', %geoLat }, + '060e2b34.0101.0103.07010201.030a0000' => { Name => 'CornerLatitudePoint4', Format => 'string' }, + '060e2b34.0101.0103.07010201.030a0100' => { Name => 'CornerLatitudePoint4', Format => 'double', %geoLat }, + '060e2b34.0101.0103.07010201.030b0000' => { Name => 'CornerLongitudePoint1', Format => 'string' }, + '060e2b34.0101.0103.07010201.030b0100' => { Name => 'CornerLongitudePoint1', Format => 'double', %geoLon }, + '060e2b34.0101.0103.07010201.030c0000' => { Name => 'CornerLongitudePoint2', Format => 'string' }, + '060e2b34.0101.0103.07010201.030c0100' => { Name => 'CornerLongitudePoint2', Format => 'double', %geoLon }, + '060e2b34.0101.0103.07010201.030d0000' => { Name => 'CornerLongitudePoint3', Format => 'string' }, + '060e2b34.0101.0103.07010201.030d0100' => { Name => 'CornerLongitudePoint3', Format => 'double', %geoLon }, + '060e2b34.0101.0103.07010201.030e0000' => { Name => 'CornerLongitudePoint4', Format => 'string' }, + '060e2b34.0101.0103.07010201.030e0100' => { Name => 'CornerLongitudePoint4', Format => 'double', %geoLon }, + '060e2b34.0101.0103.07010801.02000000' => { Name => 'SubjectDistance', Format => 'float' }, + '060e2b34.0101.0103.07012001.01010100' => { Name => 'PlaceKeyword', Type => 'UTF-16' }, + '060e2b34.0101.0103.07012001.02010100' => { Name => 'ObjectCountryCode', Type => 'UTF-16' }, + '060e2b34.0101.0103.07012001.02060000' => { Name => 'ObjectCountryCodeMethod', Format => 'string' }, + '060e2b34.0101.0103.07012001.02070000' => { Name => 'CountryCodeMethod', Format => 'string' }, + '060e2b34.0101.0103.07012001.02080000' => { Name => 'Non-USClassifyingCountryCode', Format => 'string' }, + '060e2b34.0101.0103.07012001.02090000' => { Name => 'ReleasableCountryCode', Format => 'string' }, + '060e2b34.0101.0103.07012001.03010100' => { Name => 'ObjectRegionName', Type => 'UTF-16' }, + '060e2b34.0101.0103.07012001.03020100' => { Name => 'ShootingRegionName', Type => 'UTF-16' }, + '060e2b34.0101.0103.07012001.03030100' => { Name => 'SettingRegionName', Type => 'UTF-16' }, + '060e2b34.0101.0103.07012001.03040100' => { Name => 'CopyrightLicenseRegionName', Type => 'UTF-16' }, + '060e2b34.0101.0103.07012001.03050100' => { Name => 'IntellectualPropertyLicenseRegionName', Type => 'UTF-16' }, + '060e2b34.0101.0103.07012001.04010101' => { Name => 'RoomNumber', Type => 'UTF-16' }, + '060e2b34.0101.0103.07012001.04010201' => { Name => 'StreetNumber', Type => 'UTF-16' }, + '060e2b34.0101.0103.07012001.04010301' => { Name => 'StreetName', Type => 'UTF-16' }, + '060e2b34.0101.0103.07012001.04010401' => { Name => 'PostalTown', Type => 'UTF-16' }, + '060e2b34.0101.0103.07012001.04010501' => { Name => 'CityName', Type => 'UTF-16' }, + '060e2b34.0101.0103.07012001.04010601' => { Name => 'StateOrProvinceOrCountyName', Type => 'UTF-16' }, + '060e2b34.0101.0103.07012001.04010701' => { Name => 'PostalCode', Type => 'UTF-16' }, + '060e2b34.0101.0103.07012001.04010801' => { Name => 'CountryName', Type => 'UTF-16' }, + '060e2b34.0101.0103.07012001.04020101' => { Name => 'SettingRoomNumber', Type => 'UTF-16' }, + '060e2b34.0101.0103.07012001.04020201' => { Name => 'SettingStreetNumberOrBuildingName', Type => 'UTF-16' }, + '060e2b34.0101.0103.07012001.04020301' => { Name => 'SettingStreetName', Type => 'UTF-16' }, + '060e2b34.0101.0103.07012001.04020401' => { Name => 'SettingTownName', Type => 'UTF-16' }, + '060e2b34.0101.0103.07012001.04020501' => { Name => 'SettingCityName', Type => 'UTF-16' }, + '060e2b34.0101.0103.07012001.04020601' => { Name => 'SettingStateOrProvinceOrCountyName', Type => 'UTF-16' }, + '060e2b34.0101.0103.07012001.04020701' => { Name => 'SettingPostalCode', Type => 'UTF-16' }, + '060e2b34.0101.0103.07012001.04020801' => { Name => 'SettingCountryName', Type => 'UTF-16' }, + '060e2b34.0101.0103.07012001.10030101' => { Name => 'TelephoneNumber', Type => 'UTF-16' }, + '060e2b34.0101.0103.07012001.10030201' => { Name => 'FaxNumber', Type => 'UTF-16' }, + '060e2b34.0101.0103.07012001.10030301' => { Name => 'E-mailAddress', Type => 'UTF-16' }, + '060e2b34.0101.0103.07012002.01010000' => { Name => 'SettingDescription', Type => 'UTF-16' }, + '060e2b34.0101.0103.07020101.01050000' => { Name => 'POSIXMicroseconds', Format => 'int64u' }, + # '060e2b34.0101.0103.07020103.10030000' => { Name => 'EventOffsets', Type => 'Node' }, + '060e2b34.0101.0103.07020103.10030100' => { Name => 'EventElapsedTimeToStart', Format => 'string' }, + '060e2b34.0101.0103.07020103.10030200' => { Name => 'EventElapsedTimeToEnd', Format => 'string' }, + '060e2b34.0101.0104.01011002.00000000' => { Name => 'OrganizationIDKind', Format => 'string' }, + '060e2b34.0101.0104.01011002.01000000' => { Name => 'OrganizationIDKind', Type => 'UTF-16' }, + # '060e2b34.0101.0104.01020200.00000000' => { Name => 'RegistryLocators', Type => 'Node' }, + '060e2b34.0101.0104.01020201.00000000' => { Name => 'SMPTEUL', Type => 'UL', Unknown => 1 }, + # '060e2b34.0101.0104.01020210.00000000' => { Name => 'RegistryLocatorGroups', Type => 'Node' }, + # '060e2b34.0101.0104.01020210.01000000' => { Name => 'RegistryLocatorOrderedGroup', Type => 'Node' }, + '060e2b34.0101.0104.01020210.01010000' => { Name => 'EssenceContainerArray', Type => 'Array of UL', Unknown => 1 }, + '060e2b34.0101.0104.01030404.00000000' => { Name => 'EssenceStreamID', Format => 'int32u' }, + '060e2b34.0101.0104.01030405.00000000' => { Name => 'IndexStreamID', Format => 'int32u' }, + '060e2b34.0101.0104.01050a00.00000000' => { Name => 'WorkingTitle', Format => 'string' }, + '060e2b34.0101.0104.01050a01.00000000' => { Name => 'WorkingTitle', Type => 'UTF-16' }, + '060e2b34.0101.0104.01050b00.00000000' => { Name => 'OriginalTitle', Format => 'string' }, + '060e2b34.0101.0104.01050b01.00000000' => { Name => 'OriginalTitle', Type => 'UTF-16' }, + '060e2b34.0101.0104.01050c00.00000000' => { Name => 'ClipNumber', Format => 'string' }, + '060e2b34.0101.0104.01050c01.00000000' => { Name => 'ClipNumber', Type => 'UTF-16' }, + '060e2b34.0101.0104.01070105.00000000' => { Name => 'DescriptiveMetadataTrackIDs', Format => 'int32u' }, + # '060e2b34.0101.0104.01080000.00000000' => { Name => 'GenericIdentifiers', Type => 'Node' }, + '060e2b34.0101.0104.01080100.00000000' => { Name => 'IdentifierKind', Format => 'string' }, + '060e2b34.0101.0104.01080200.00000000' => { Name => 'IdentifierValue', Format => 'int8u' }, + # '060e2b34.0101.0104.010a0200.00000000' => { Name => 'GeneralOrganizationIdentifiers', Type => 'Node' }, + '060e2b34.0101.0104.010a0201.00000000' => { Name => 'OrganizationCode', Format => 'string' }, + '060e2b34.0101.0104.010a0201.01000000' => { Name => 'OrganizationCode', Type => 'UTF-16' }, + '060e2b34.0101.0104.02010500.00000000' => { Name => 'SupplierIdentificationKind', Format => 'string' }, + '060e2b34.0101.0104.02010600.00000000' => { Name => 'SupplierIdentificationValue', Format => 'string' }, + '060e2b34.0101.0104.02010700.00000000' => { Name => 'SupplierAccountNumber', Format => 'string' }, + '060e2b34.0101.0104.02010800.00000000' => { Name => 'SupplierAccountName', Format => 'string' }, + '060e2b34.0101.0104.02010801.00000000' => { Name => 'SupplierAccountName', Type => 'UTF-16' }, + '060e2b34.0101.0104.02020400.00000000' => { Name => 'EpisodeStartNumber', Format => 'int16u' }, + '060e2b34.0101.0104.02020500.00000000' => { Name => 'EpisodeEndNumber', Format => 'int16u' }, + '060e2b34.0101.0104.02030500.00000000' => { Name => 'PurchaserIdentificationKind', Format => 'string' }, + '060e2b34.0101.0104.02030600.00000000' => { Name => 'PurchaserIdentificationValue', Format => 'string' }, + '060e2b34.0101.0104.02030700.00000000' => { Name => 'PurchaserAccountNumber', Format => 'string' }, + '060e2b34.0101.0104.02030800.00000000' => { Name => 'PurchaserAccountName', Format => 'string' }, + '060e2b34.0101.0104.02030801.00000000' => { Name => 'PurchaserAccountName', Type => 'UTF-16' }, + '060e2b34.0101.0104.02040102.00000000' => { Name => 'ContractType', Type => 'UTF-16' }, + '060e2b34.0101.0104.02040201.00000000' => { Name => 'ContractClauseDescription', Type => 'UTF-16' }, + '060e2b34.0101.0104.02040302.00000000' => { Name => 'ContractLineName', Type => 'UTF-16' }, + '060e2b34.0101.0104.02040401.00000000' => { Name => 'ContractTermsOfBusiness', Type => 'UTF-16' }, + '060e2b34.0101.0104.02040601.00000000' => { Name => 'Jurisdiction', Type => 'UTF-16' }, + '060e2b34.0101.0104.02060102.00000000' => { Name => 'TotalCurrencyAmount', Format => 'double' }, + '060e2b34.0101.0104.02060103.00000000' => { Name => 'InstallmentNumber', Format => 'int16u' }, + # '060e2b34.0101.0104.020a0000.00000000' => { Name => 'IdentifiersAndLocatorsAdministrationAuthorities', Type => 'Node' }, + '060e2b34.0101.0104.020a0100.00000000' => { Name => 'IdentifierIssuingAuthority', Format => 'string' }, + # '060e2b34.0101.0104.02100200.00000000' => { Name => 'Publication', Type => 'Node' }, + # '060e2b34.0101.0104.02100201.00000000' => { Name => 'GeneralPublication', Type => 'Node' }, + '060e2b34.0101.0104.02100201.01000000' => { Name => 'PublishingOrganizationName', Format => 'string' }, + '060e2b34.0101.0104.02100201.01010000' => { Name => 'PublishingOrganizationName', Type => 'UTF-16' }, + '060e2b34.0101.0104.02100201.02000000' => { Name => 'PublishingServiceName', Format => 'string' }, + '060e2b34.0101.0104.02100201.02010000' => { Name => 'PublishingServiceName', Type => 'UTF-16' }, + '060e2b34.0101.0104.02100201.03000000' => { Name => 'PublishingMediumName', Format => 'string' }, + '060e2b34.0101.0104.02100201.03010000' => { Name => 'PublishingMediumName', Type => 'UTF-16' }, + '060e2b34.0101.0104.02100201.04000000' => { Name => 'PublishingRegionName', Format => 'string' }, + '060e2b34.0101.0104.02100201.04010000' => { Name => 'PublishingRegionName', Type => 'UTF-16' }, + '060e2b34.0101.0104.02300603.01050100' => { Name => 'Salutation', Type => 'UTF-16' }, + '060e2b34.0101.0104.02300603.01060100' => { Name => 'HonorsAndQualifications', Type => 'UTF-16' }, + '060e2b34.0101.0104.02300603.01080000' => { Name => 'OtherGivenNames', Format => 'string' }, + '060e2b34.0101.0104.02300603.01080100' => { Name => 'OtherGivenNames', Type => 'UTF-16' }, + '060e2b34.0101.0104.02300603.01090000' => { Name => 'AlternateName', Format => 'string' }, + '060e2b34.0101.0104.02300603.01090100' => { Name => 'AlternateName', Type => 'UTF-16' }, + # '060e2b34.0101.0104.03010102.02000000' => { Name => 'TextLanguageCodes', Type => 'Node' }, + '060e2b34.0101.0104.03010102.02010000' => { Name => 'ISO639TextLanguageCode', Format => 'string', LanguageCode => 1 }, + '060e2b34.0101.0104.03010102.02020000' => { Name => 'ISO639CaptionsLanguageCode', Format => 'string' }, + # '060e2b34.0101.0104.03010102.03000000' => { Name => 'SpokenLanguageCodes', Type => 'Node' }, + '060e2b34.0101.0104.03010102.03010000' => { Name => 'PrimarySpokenLanguageCode', Format => 'string' }, + '060e2b34.0101.0104.03010102.03020000' => { Name => 'SecondarySpokenLanguageCode', Format => 'string' }, + '060e2b34.0101.0104.03010102.03030000' => { Name => 'PrimaryOriginalLanguageCode', Format => 'string' }, + '060e2b34.0101.0104.03010102.03040000' => { Name => 'SecondaryOriginalLanguageCode', Format => 'string' }, + '060e2b34.0101.0104.03010201.06000000' => { Name => 'MajorVersion', Format => 'int16u' }, + '060e2b34.0101.0104.03010201.07000000' => { Name => 'MinorVersion', Format => 'int16u' }, + '060e2b34.0101.0104.03010201.08000000' => { Name => 'SectorSize', Format => 'int32u' }, + '060e2b34.0101.0104.03010203.09000000' => { Name => 'ElementLength', Format => 'int32u' }, + '060e2b34.0101.0104.03020102.02010000' => { Name => 'ThesaurusName', Type => 'UTF-16' }, + '060e2b34.0101.0104.03020102.0d010000' => { Name => 'Cue-InWords', Type => 'UTF-16' }, + '060e2b34.0101.0104.03020102.0e010000' => { Name => 'Cue-OutWords', Type => 'UTF-16' }, + '060e2b34.0101.0104.03020102.10000000' => { Name => 'KeypointKind', Format => 'string' }, + '060e2b34.0101.0104.03020102.10010000' => { Name => 'KeypointKind', Type => 'UTF-16' }, + '060e2b34.0101.0104.03020102.11000000' => { Name => 'KeypointValue', Format => 'string' }, + '060e2b34.0101.0104.03020102.11010000' => { Name => 'KeypointValue', Type => 'UTF-16' }, + '060e2b34.0101.0104.03020201.03010000' => { Name => 'FestivalName', Type => 'UTF-16' }, + '060e2b34.0101.0104.03020201.04000000' => { Name => 'AwardName', Format => 'string' }, + '060e2b34.0101.0104.03020201.04010000' => { Name => 'AwardName', Type => 'UTF-16' }, + '060e2b34.0101.0104.03020201.05000000' => { Name => 'AwardCategory', Format => 'string' }, + '060e2b34.0101.0104.03020201.05010000' => { Name => 'AwardCategory', Type => 'UTF-16' }, + '060e2b34.0101.0104.03020503.00000000' => { Name => 'SlateInformation', Type => 'UTF-16' }, + '060e2b34.0101.0104.04020301.04000000' => { Name => 'LockedIndicator', Type => 'Boolean' }, + '060e2b34.0101.0104.04020303.04000000' => { Name => 'BitsPerAudioSample', Format => 'int32u', Groups => { 2 => 'Audio' } }, + '060e2b34.0101.0104.04030101.00000000' => { Name => 'CaptionKind', Format => 'string' }, + '060e2b34.0101.0104.04030101.01000000' => { Name => 'CaptionKind', Type => 'UTF-16' }, + # '060e2b34.0101.0104.04040400.00000000' => { Name => 'IndexingMetadataCodingCharacteristics', Type => 'Node' }, + # '060e2b34.0101.0104.04040401.00000000' => { Name => 'IntraEditUnitIndexing', Type => 'Node' }, + '060e2b34.0101.0104.04040401.01000000' => { Name => 'SliceCount', Format => 'int8u' }, + '060e2b34.0101.0104.04040401.02000000' => { Name => 'SliceNumber', Format => 'int8u' }, + '060e2b34.0101.0104.04040401.03000000' => { Name => 'ElementDelta', Format => 'int32u' }, + '060e2b34.0101.0104.04040401.04000000' => { Name => 'PositionTableIndexing', Format => 'int8s' }, + '060e2b34.0101.0104.04040401.05000000' => { Name => 'SliceOffsetList', Type => 'UInt32Array', Unknown => 1 }, + '060e2b34.0101.0104.04040401.08000000' => { Name => 'PosTableArray', Unknown => 1 }, + # '060e2b34.0101.0104.04040402.00000000' => { Name => 'InterEditUnitIndexing', Type => 'Node' }, + '060e2b34.0101.0104.04040402.01000000' => { Name => 'StreamOffset', Format => 'int64u' }, + '060e2b34.0101.0104.04040402.02000000' => { Name => 'EditUnitFlags', Format => 'int8u' }, + '060e2b34.0101.0104.04040402.03000000' => { Name => 'TemporalOffset', Format => 'int8s' }, + '060e2b34.0101.0104.04040402.04000000' => { Name => 'AnchorOffset', Format => 'int8s' }, + # '060e2b34.0101.0104.04060200.00000000' => { Name => 'GeneralEssenceContainerCharacteristics', Type => 'Node' }, + '060e2b34.0101.0104.04060201.00000000' => { Name => 'EditUnitLength', Format => 'int32u' }, + # '060e2b34.0101.0104.04060800.00000000' => { Name => 'GeneralMetadataCodingCharacteristics', Type => 'Node' }, + # '060e2b34.0101.0104.04060900.00000000' => { Name => 'GeneralMetadataContainerCharacteristics', Type => 'Node' }, + '060e2b34.0101.0104.04060901.00000000' => { Name => 'HeaderByteCount', Format => 'int64u' }, + '060e2b34.0101.0104.04060902.00000000' => { Name => 'IndexByteCount', Format => 'int64u' }, + # '060e2b34.0101.0104.04061000.00000000' => { Name => 'GeneralDataCodingCharacteristics', Type => 'Node' }, + '060e2b34.0101.0104.04061001.00000000' => { Name => 'PackLength', Format => 'int32u' }, + # '060e2b34.0101.0104.04200102.00000000' => { Name => 'ImagerCharacteristics', Type => 'Node' }, + '060e2b34.0101.0104.05010101.01000000' => { Name => 'IntegrationIndication', Type => 'UTF-16' }, + '060e2b34.0101.0104.05010102.01000000' => { Name => 'EventIndication', Type => 'UTF-16' }, + '060e2b34.0101.0104.05010107.01000000' => { Name => 'GraphicUsageKind', Type => 'UTF-16' }, + '060e2b34.0101.0104.06010104.01080000' => { Name => 'PrimaryPackage', Type => 'WeakReference', Unknown => 1 }, + # '060e2b34.0101.0104.06010104.02400000' => { Name => 'StrongReferencingToDescriptiveMetadataSets', Type => 'Node' }, + '060e2b34.0101.0104.06010104.03030000' => { Name => 'DescriptiveMetadataSets', Type => 'WeakReferenceBatch', Unknown => 1 }, + '060e2b34.0101.0104.06010104.04020000' => { Name => 'DescriptiveMetadataSetReferences', Type => 'WeakReferenceArray', Unknown => 1 }, + # '060e2b34.0101.0104.06010104.05400000' => { Name => 'StrongReferencesToDescriptiveMetadataBatches', Type => 'Node' }, + '060e2b34.0101.0104.06010104.060b0000' => { Name => 'FileDescriptors', Type => 'StrongReferenceArray', Unknown => 1 }, + '060e2b34.0101.0104.06080102.01010000' => { Name => 'StreamPositionIndicator', Format => 'int16u' }, + '060e2b34.0101.0104.06080102.01020000' => { Name => 'StreamPositionIndicator', Format => 'int32u' }, + '060e2b34.0101.0104.06080102.01030000' => { Name => 'StreamPositionIndicator', Format => 'int64u' }, + '060e2b34.0101.0104.06080202.01000000' => { Name => 'OffsetToMetadata', Format => 'int32s' }, + '060e2b34.0101.0104.06080202.01010000' => { Name => 'OffsetToMetadata', Format => 'int64s' }, + '060e2b34.0101.0104.06080202.02000000' => { Name => 'OffsetToIndexTable', Format => 'int32s' }, + '060e2b34.0101.0104.06080202.02010000' => { Name => 'OffsetToIndexTable', Format => 'int64s' }, + # '060e2b34.0101.0104.06090000.00000000' => { Name => 'DataRelationships', Type => 'Node' }, + # '060e2b34.0101.0104.06090200.00000000' => { Name => 'LocalDataRelationships', Type => 'Node' }, + # '060e2b34.0101.0104.06090201.00000000' => { Name => 'DataOffsets', Type => 'Node' }, + '060e2b34.0101.0104.06090201.01000000' => { Name => 'ByteOffset', Format => 'int64u' }, + '060e2b34.0101.0104.06090201.02000000' => { Name => 'ReversePlay', Format => 'int64u' }, + # '060e2b34.0101.0104.06101000.00000000' => { Name => 'RelativeNumericalSequences', Type => 'Node' }, + '060e2b34.0101.0104.06101001.00000000' => { Name => 'FirstNumberInSequence', Format => 'int32u' }, + '060e2b34.0101.0104.06101001.01000000' => { Name => 'FirstNumberInSequence', Format => 'int64u' }, + '060e2b34.0101.0104.06101002.00000000' => { Name => 'PreviousNumberInSequence', Format => 'int32u' }, + '060e2b34.0101.0104.06101002.01000000' => { Name => 'PreviousNumberInSequence', Format => 'int64u' }, + '060e2b34.0101.0104.06101003.00000000' => { Name => 'CurrentNumberInSequence', Format => 'int32u' }, + '060e2b34.0101.0104.06101003.01000000' => { Name => 'CurrentNumberInSequence', Format => 'int64u' }, + '060e2b34.0101.0104.06101004.00000000' => { Name => 'NextNumberInSequence', Format => 'int32u' }, + '060e2b34.0101.0104.06101004.01000000' => { Name => 'NextNumberInSequence', Format => 'int64u' }, + '060e2b34.0101.0104.06101005.00000000' => { Name => 'LastNumberInSequence', Format => 'int32u' }, + '060e2b34.0101.0104.06101005.01000000' => { Name => 'LastNumberInSequence', Format => 'int64u' }, + # '060e2b34.0101.0104.07012001.10000000' => { Name => 'ElectronicAddressVarieties', Type => 'Node' }, + '060e2b34.0101.0104.07012001.10030400' => { Name => 'CentralTelephoneNumber', Format => 'string' }, + '060e2b34.0101.0104.07012001.10030500' => { Name => 'MobileTelephoneNumber', Format => 'string' }, + '060e2b34.0101.0104.07012001.10030600' => { Name => 'URL', Format => 'string' }, + '060e2b34.0101.0104.07012002.02000000' => { Name => 'LocationDescription', Format => 'string' }, + '060e2b34.0101.0104.07012002.02010000' => { Name => 'LocationDescription', Type => 'UTF-16' }, + '060e2b34.0101.0104.07012002.03000000' => { Name => 'LocationKind', Format => 'string' }, + '060e2b34.0101.0104.07012002.03010000' => { Name => 'LocationKind', Type => 'UTF-16' }, + '060e2b34.0101.0104.07020102.07010100' => { Name => 'UTCEventStartDateTime', %timestamp }, + '060e2b34.0101.0104.07020102.07020100' => { Name => 'LocalEventStartDateTime', %timestamp }, + '060e2b34.0101.0104.07020102.09010100' => { Name => 'UTCEventEndDateTime', %timestamp }, + '060e2b34.0101.0104.07020102.09020100' => { Name => 'LocalEventEndDateTime', %timestamp }, + '060e2b34.0101.0104.07020103.01070000' => { Name => 'KeyTimePoint', Format => 'int64u' }, + '060e2b34.0101.0104.07020108.01010000' => { Name => 'TimePeriodName', Type => 'UTF-16' }, + '060e2b34.0101.0104.07020108.02000000' => { Name => 'SettingDateTime', %timestamp }, + # '060e2b34.0101.0104.07020120.00000000' => { Name => 'AdministrativeDateTime', Type => 'Node' }, + '060e2b34.0101.0104.07020120.01000000' => { Name => 'ContractDateTime', %timestamp }, + '060e2b34.0101.0104.07020120.02000000' => { Name => 'RightsStartDateTime', %timestamp }, + '060e2b34.0101.0104.07020120.03000000' => { Name => 'RightsStopDateTime', %timestamp }, + '060e2b34.0101.0104.07020120.04000000' => { Name => 'PaymentDueDateTime', %timestamp }, + # '060e2b34.0101.0105.01010500.00000000' => { Name => 'UMIDPicture', Type => 'Node' }, + # '060e2b34.0101.0105.01010600.00000000' => { Name => 'UMIDMultiPicture', Type => 'Node' }, + # '060e2b34.0101.0105.01010800.00000000' => { Name => 'UMIDSound', Type => 'Node' }, + # '060e2b34.0101.0105.01010900.00000000' => { Name => 'UMIDMultiSound', Type => 'Node' }, + # '060e2b34.0101.0105.01010b00.00000000' => { Name => 'UMIDSingleData', Type => 'Node' }, + # '060e2b34.0101.0105.01010c00.00000000' => { Name => 'UMIDMultiData', Type => 'Node' }, + # '060e2b34.0101.0105.01010d00.00000000' => { Name => 'UMIDMixed', Type => 'Node' }, + # '060e2b34.0101.0105.01010f00.00000000' => { Name => 'UMIDGeneral', Type => 'Node' }, + '060e2b34.0101.0105.01011508.00000000' => { Name => 'ClipID', Type => 'UMID' }, + '060e2b34.0101.0105.01012008.01000000' => { Name => 'DeviceKind', Type => 'UTF-16' }, + '060e2b34.0101.0105.0101200c.00000000' => { Name => 'DeviceAssetNumber', Format => 'string' }, + '060e2b34.0101.0105.01020202.00000000' => { Name => 'IdentificationUL', Type => 'UL', Unknown => 1 }, + '060e2b34.0101.0105.01020203.00000000' => { Name => 'OperationalPatternUL', Type => 'UL', Unknown => 1 }, + # '060e2b34.0101.0105.01020210.02000000' => { Name => 'RegistryLocatorUnorderedGroups', Type => 'Node' }, + '060e2b34.0101.0105.01020210.02010000' => { Name => 'EssenceContainers', Type => 'BatchOfUL', Unknown => 1 }, + '060e2b34.0101.0105.01020210.02020000' => { Name => 'DescriptiveMetadataSchemes', Type => 'BatchOfUL', Unknown => 1 }, + '060e2b34.0101.0105.01030108.00000000' => { Name => 'ProjectName', Format => 'string' }, + '060e2b34.0101.0105.01030108.01000000' => { Name => 'ProjectName', Type => 'UTF-16' }, + '060e2b34.0101.0105.01030602.00000000' => { Name => 'LocalTagValue', Format => 'int16u' }, + '060e2b34.0101.0105.01030603.00000000' => { Name => 'LocalTagUniqueID', Type => 'AUID', Unknown => 1 }, + '060e2b34.0101.0105.01050d00.00000000' => { Name => 'BrandMainTitle', Format => 'string' }, + '060e2b34.0101.0105.01050d01.00000000' => { Name => 'BrandMainTitle', Type => 'UTF-16' }, + '060e2b34.0101.0105.01050e00.00000000' => { Name => 'BrandOriginalTitle', Format => 'string' }, + '060e2b34.0101.0105.01050e01.00000000' => { Name => 'BrandOriginalTitle', Type => 'UTF-16' }, + '060e2b34.0101.0105.01050f00.00000000' => { Name => 'FrameworkTitle', Format => 'string' }, + '060e2b34.0101.0105.01050f01.00000000' => { Name => 'FrameworkTitle', Type => 'UTF-16' }, + '060e2b34.0101.0105.01070106.00000000' => { Name => 'SourceTrackIDs', Format => 'int32u' }, + '060e2b34.0101.0105.01070107.00000000' => { Name => 'ShotTrackIDs', Format => 'int32u' }, + '060e2b34.0101.0105.02020301.00000000' => { Name => 'ProgrammingGroupKind', Type => 'UTF-16' }, + '060e2b34.0101.0105.02020600.00000000' => { Name => 'ProgrammingGroupTitle', Format => 'string' }, + '060e2b34.0101.0105.02020601.00000000' => { Name => 'ProgrammingGroupTitle', Type => 'UTF-16' }, + '060e2b34.0101.0105.020a0101.00000000' => { Name => 'IdentifierIssuingAuthority', Type => 'UTF-16' }, + '060e2b34.0101.0105.02300603.010a0000' => { Name => 'LinkingName', Format => 'string' }, + '060e2b34.0101.0105.02300603.010a0100' => { Name => 'LinkingName', Type => 'UTF-16' }, + '060e2b34.0101.0105.02300603.010b0000' => { Name => 'NameSuffix', Format => 'string' }, + '060e2b34.0101.0105.02300603.010b0100' => { Name => 'NameSuffix', Type => 'UTF-16' }, + '060e2b34.0101.0105.02300603.010c0000' => { Name => 'FormerFamilyName', Format => 'string' }, + '060e2b34.0101.0105.02300603.010c0100' => { Name => 'FormerFamilyName', Type => 'UTF-16' }, + '060e2b34.0101.0105.02300603.010d0000' => { Name => 'Nationality', Format => 'string' }, + '060e2b34.0101.0105.02300603.010d0100' => { Name => 'Nationality', Type => 'UTF-16' }, + '060e2b34.0101.0105.02300603.010e0000' => { Name => 'Citizenship', Format => 'string' }, + '060e2b34.0101.0105.02300603.010e0100' => { Name => 'Citizenship', Type => 'UTF-16' }, + '060e2b34.0101.0105.03010102.02030000' => { Name => 'FrameworkTextLanguageCode', Format => 'string', LanguageCode => 1 }, + '060e2b34.0101.0105.03010201.09000000' => { Name => 'KAGSize', Format => 'int32u' }, + '060e2b34.0101.0105.03010201.0a000000' => { Name => 'ReversedByteOrder', Type => 'Boolean' }, + # '060e2b34.0101.0105.0301020a.00000000' => { Name => 'NameValueConstructInterpretations', Type => 'Node' }, + '060e2b34.0101.0105.0301020a.01000000' => { Name => 'ItemName', Format => 'string' }, + '060e2b34.0101.0105.0301020a.01010000' => { Name => 'ItemName', Type => 'UTF-16' }, + '060e2b34.0101.0105.0301020a.02000000' => { Name => 'ItemValue', Format => 'string' }, + '060e2b34.0101.0105.0301020a.02010000' => { Name => 'ItemValue', Type => 'UTF-16' }, + # '060e2b34.0101.0105.03010220.00000000' => { Name => 'XMLConstructsAndInterpretations', Type => 'Node' }, + '060e2b34.0101.0105.03010220.01000000' => { Name => 'XMLDocumentText', Type => 'Indirect', Unknown => 1 }, + '060e2b34.0101.0105.03010220.01010000' => { Name => 'XMLDocumentText', Format => 'string' }, + '060e2b34.0101.0105.03010220.01020000' => { Name => 'XMLDocumentText', Type => 'UTF-16' }, + '060e2b34.0101.0105.03010220.01030000' => { Name => 'XMLDocumentText', Type => 'ByteStream', Unknown => 1 }, + '060e2b34.0101.0105.03020102.15000000' => { Name => 'FrameworkThesaurusName', Format => 'string' }, + '060e2b34.0101.0105.03020102.15010000' => { Name => 'FrameworkThesaurusName', Type => 'UTF-16' }, + '060e2b34.0101.0105.03020106.08000000' => { Name => 'GroupSynopsis', Format => 'string' }, + '060e2b34.0101.0105.03020106.08010000' => { Name => 'GroupSynopsis', Type => 'UTF-16' }, + '060e2b34.0101.0105.03020106.09000000' => { Name => 'AnnotationSynopsis', Format => 'string' }, + '060e2b34.0101.0105.03020106.09010000' => { Name => 'AnnotationSynopsis', Type => 'UTF-16' }, + '060e2b34.0101.0105.03020106.0a000000' => { Name => 'AnnotationDescription', Format => 'string' }, + '060e2b34.0101.0105.03020106.0a010000' => { Name => 'AnnotationDescription', Type => 'UTF-16' }, + '060e2b34.0101.0105.03020106.0b000000' => { Name => 'ScriptingKind', Format => 'string' }, + '060e2b34.0101.0105.03020106.0b010000' => { Name => 'ScriptingKind', Type => 'UTF-16' }, + '060e2b34.0101.0105.03020106.0c000000' => { Name => 'ScriptingText', Format => 'string' }, + '060e2b34.0101.0105.03020106.0c010000' => { Name => 'ScriptingText', Type => 'UTF-16' }, + '060e2b34.0101.0105.03020106.0d000000' => { Name => 'ShotDescription', Format => 'string' }, + '060e2b34.0101.0105.03020106.0d010000' => { Name => 'ShotDescription', Type => 'UTF-16' }, + '060e2b34.0101.0105.03020106.0e000000' => { Name => 'AnnotationKind', Format => 'string' }, + '060e2b34.0101.0105.03020106.0e010000' => { Name => 'AnnotationKind', Type => 'UTF-16' }, + '060e2b34.0101.0105.03020106.0f000000' => { Name => 'RelatedMaterialDescription', Format => 'string' }, + '060e2b34.0101.0105.03020106.0f010000' => { Name => 'RelatedMaterialDescription', Type => 'UTF-16' }, + '060e2b34.0101.0105.03020504.00000000' => { Name => 'ClipKind', Type => 'UTF-16' }, + # '060e2b34.0101.0105.03030310.00000000' => { Name => 'DeviceCommentsAndDescriptions', Type => 'Node' }, + '060e2b34.0101.0105.03030310.01000000' => { Name => 'DeviceUsageDescription', Format => 'string' }, + '060e2b34.0101.0105.03030310.01010000' => { Name => 'DeviceUsageDescription', Type => 'UTF-16' }, + '060e2b34.0101.0105.04010302.07000000' => { Name => 'DisplayF2Offset', Format => 'int32s' }, + '060e2b34.0101.0105.04010302.08000000' => { Name => 'StoredF2Offset', Format => 'int32s' }, + '060e2b34.0101.0105.04010302.09000000' => { Name => 'ActiveFormatDescriptor', Format => 'int8u' }, + '060e2b34.0101.0105.04010302.0a000000' => { Name => 'LineNumber', Format => 'int32u' }, + # '060e2b34.0101.0105.04010404.00000000' => { Name => 'VideoScanningCharacteristics', Type => 'Node' }, + '060e2b34.0101.0105.04010404.01000000' => { Name => 'ScanningDirection', Format => 'int8u' }, + '060e2b34.0101.0105.04010503.0b000000' => { Name => 'ComponentMaximumRef', Format => 'int32u' }, + '060e2b34.0101.0105.04010503.0c000000' => { Name => 'ComponentMinimumRef', Format => 'int32u' }, + '060e2b34.0101.0105.04010503.0d000000' => { Name => 'AlphaMaximumRef', Format => 'int32u' }, + '060e2b34.0101.0105.04010503.0e000000' => { Name => 'AlphaMinimumRef', Format => 'int32u' }, + # '060e2b34.0101.0105.04010504.00000000' => { Name => 'DigitalVideoAndImageSignalTypeIdentifiers', Type => 'Node' }, + '060e2b34.0101.0105.04010504.01000000' => { Name => 'VideoPayloadIdentifier', Format => 'int8u' }, + '060e2b34.0101.0105.04010504.02000000' => { Name => 'VideoPayloadIdentifier2002', Format => 'int8u' }, + '060e2b34.0101.0105.04010602.01020000' => { Name => 'SingleSequenceFlag', Type => 'Boolean' }, + '060e2b34.0101.0105.04010602.01030000' => { Name => 'ConstantBPictureFlag', Type => 'Boolean' }, + '060e2b34.0101.0105.04010602.01040000' => { Name => 'CodedContentScanningKind', Type => 'int8u', + PrintConv => { 0 => 'Unknown', 1 => 'Progressive', 2 => 'Interlaced', 3 => 'Mixed' }, + }, + '060e2b34.0101.0105.04010602.01050000' => { Name => 'LowDelayIndicator', Type => 'Boolean' }, + '060e2b34.0101.0105.04010602.01060000' => { Name => 'ClosedGOPIndicator', Type => 'Boolean' }, + '060e2b34.0101.0105.04010602.01070000' => { Name => 'IdenticalGOPIndicator', Type => 'Boolean' }, + '060e2b34.0101.0105.04010602.01080000' => { Name => 'MaximumGOPSize', Format => 'int16u' }, + '060e2b34.0101.0105.04010602.01090000' => { Name => 'MaximumBPictureCount', Format => 'int16u' }, + '060e2b34.0101.0105.04010602.010a0000' => { Name => 'ProfileAndLevel', Format => 'int8u' }, + '060e2b34.0101.0105.04010602.010b0000' => { Name => 'Bitrate', Format => 'int32u', PrintConv => 'ConvertBitrate($val)' }, + '060e2b34.0101.0105.04020101.04000000' => { Name => 'ChannelCount', Format => 'int32u', Groups => { 2 => 'Audio' } }, + '060e2b34.0101.0105.04020301.01010000' => { Name => 'AudioSampleRate', Format => 'rational64s', Groups => { 2 => 'Audio' } }, + '060e2b34.0101.0105.04020301.05000000' => { Name => 'PeakEnvelope', Format => 'int8u', Groups => { 2 => 'Audio' } }, + '060e2b34.0101.0105.04020301.0e000000' => { Name => 'PeakEnvelopeData', Type => 'Stream', Unknown => 1, Groups => { 2 => 'Audio' } }, + '060e2b34.0101.0105.04020302.01000000' => { Name => 'BlockAlign', Format => 'int16u' }, + '060e2b34.0101.0105.04020302.02000000' => { Name => 'SequenceOffset', Format => 'int8u' }, + '060e2b34.0101.0105.04020302.03000000' => { Name => 'BlockStartOffset', Format => 'int16u' }, + '060e2b34.0101.0105.04020302.05000000' => { Name => 'FileSecurityReport', Format => 'int32u' }, + '060e2b34.0101.0105.04020302.06000000' => { Name => 'FileSecurityWave', Format => 'int32u' }, + '060e2b34.0101.0105.04020303.05000000' => { Name => 'AverageBytesPerSecond', Format => 'int32u', Groups => { 2 => 'Audio' } }, + # '060e2b34.0101.0105.04020500.00000000' => { Name => 'DigitalAudioProcessingParameters', Type => 'Node' }, + # '060e2b34.0101.0105.04020501.00000000' => { Name => 'AES-3ProcessingParameters', Type => 'Node' }, + '060e2b34.0101.0105.04020501.01000000' => { Name => 'AuxiliaryBitsMode', Format => 'int8u' }, + '060e2b34.0101.0105.04020501.02000000' => { Name => 'ChannelStatusMode', Format => 'undef', + RawConv => 'length($val) > 8 ? join(" ",unpack("x8C*",$val)) : undef', + # convert just the first value for now + PrintConv => [{ + 0 => 'No Channel Status Data', + 1 => 'AES3 Minimum', + 2 => 'AES3 Standard', + 3 => 'Fixed 24 Bytes in FixedChannelStatusData', + 4 => 'Stream of Data in MXF Header Metadata', + 5 => 'Stream of Data Multiplexed within MXF Body', + }], + }, + '060e2b34.0101.0105.04020501.03000000' => { Name => 'FixedChannelStatusData', Type => 'Array of bytes', Unknown => 1 }, + '060e2b34.0101.0105.04020501.04000000' => { Name => 'UserDataMode', Type => 'EnumeratedArray', Unknown => 1 }, + '060e2b34.0101.0105.04020501.05000000' => { Name => 'FixedUserData', Type => 'Array of bytes', Unknown => 1 }, + '060e2b34.0101.0105.04020501.06000000' => { Name => 'Emphasis', Format => 'int8u' }, + # '060e2b34.0101.0105.04020502.00000000' => { Name => 'BWFProcessingParameters', Type => 'Node' }, + '060e2b34.0101.0105.04020502.01000000' => { Name => 'BextCodingHistory', Format => 'string' }, + '060e2b34.0101.0105.04020502.01010000' => { Name => 'BextCodingHistory', Type => 'UTF-16' }, + '060e2b34.0101.0105.04020502.02000000' => { Name => 'QltyBasicData', Format => 'string' }, + '060e2b34.0101.0105.04020502.02010000' => { Name => 'QltyBasicData', Type => 'UTF-16' }, + '060e2b34.0101.0105.04020502.03000000' => { Name => 'QltyStartOfModulation', Format => 'string' }, + '060e2b34.0101.0105.04020502.03010000' => { Name => 'QltyStartOfModulation', Type => 'UTF-16' }, + '060e2b34.0101.0105.04020502.04000000' => { Name => 'QltyQualityEvent', Format => 'string' }, + '060e2b34.0101.0105.04020502.04010000' => { Name => 'QltyQualityEvent', Type => 'UTF-16' }, + '060e2b34.0101.0105.04020502.05000000' => { Name => 'QltyEndOfModulation', Format => 'string' }, + '060e2b34.0101.0105.04020502.05010000' => { Name => 'QltyEndOfModulation', Type => 'UTF-16' }, + '060e2b34.0101.0105.04020502.06000000' => { Name => 'QltyQualityParameter', Format => 'string' }, + '060e2b34.0101.0105.04020502.06010000' => { Name => 'QltyQualityParameter', Type => 'UTF-16' }, + '060e2b34.0101.0105.04020502.07000000' => { Name => 'QltyOperatorComment', Format => 'string' }, + '060e2b34.0101.0105.04020502.07010000' => { Name => 'QltyOperatorComment', Type => 'UTF-16' }, + '060e2b34.0101.0105.04020502.08000000' => { Name => 'QltyCueSheet', Format => 'string' }, + '060e2b34.0101.0105.04020502.08010000' => { Name => 'QltyCueSheet', Type => 'UTF-16' }, + # '060e2b34.0101.0105.04020700.00000000' => { Name => 'GeneralProcessingParameters', Type => 'Node' }, + '060e2b34.0101.0105.04020701.00000000' => { Name => 'DialNorm', Format => 'int8s' }, + '060e2b34.0101.0105.04030302.00000000' => { Name => 'DataEssenceCoding', Type => 'Label' }, + # '060e2b34.0101.0105.04040102.00000000' => { Name => 'GeneralDateTimeCodingCharacteristics', Type => 'Node' }, + '060e2b34.0101.0105.04040102.01000000' => { Name => 'DateTimeRate', Format => 'rational64s', Groups => { 2 => 'Time' } }, + '060e2b34.0101.0105.04040102.02000000' => { Name => 'DateTimeDropFrameFlag', Type => 'Boolean', Groups => { 2 => 'Time' } }, + '060e2b34.0101.0105.04040102.03000000' => { Name => 'DateTimeEmbeddedFlag', Type => 'Boolean', Groups => { 2 => 'Time' } }, + '060e2b34.0101.0105.04040102.04000000' => { Name => 'DateTimeKind', Type => 'UL', Unknown => 1, Groups => { 2 => 'Time' } }, + '060e2b34.0101.0105.04040401.06000000' => { Name => 'DeltaEntryArray', Type => 'ArrayOfDeltaEntry', Unknown => 1 }, + '060e2b34.0101.0105.04040401.07000000' => { Name => 'PositionTableCount', Format => 'int8u' }, + '060e2b34.0101.0105.04040401.08000000' => { Name => 'PositionTable', Type => 'ArrayOfRational', Unknown => 1 }, + '060e2b34.0101.0105.04040402.05000000' => { Name => 'IndexEntryArray', Type => 'ArrayOfIndexEntry', Unknown => 1 }, + '060e2b34.0101.0105.04050113.00000000' => { Name => 'SignalStandard', Format => 'int8u' }, + '060e2b34.0101.0105.04070101.00000000' => { Name => 'DataDefinition', Type => 'UL', Unknown => 1 }, + # '060e2b34.0101.0105.04090000.00000000' => { Name => 'FormatCharacteristics', Type => 'Node' }, + '060e2b34.0101.0105.04090100.00000000' => { Name => 'RecordedFormat', Format => 'string' }, + '060e2b34.0101.0105.05010302.01000000' => { Name => 'GenerationCopyNumber', Format => 'int16u' }, + '060e2b34.0101.0105.05010303.01000000' => { Name => 'GenerationCloneNumber', Format => 'int16u' }, + # '060e2b34.0101.0105.05010400.00000000' => { Name => 'MusicFlags', Type => 'Node' }, + '060e2b34.0101.0105.05010403.00000000' => { Name => 'ThemeMusicFlag', Type => 'Boolean' }, + '060e2b34.0101.0105.05010404.00000000' => { Name => 'InsertMusicFlag', Type => 'Boolean' }, + '060e2b34.0101.0105.05300406.00000000' => { Name => 'IndexEditRate', Format => 'rational64s' }, + '060e2b34.0101.0105.06010103.05000000' => { Name => 'LinkedTrackID', Format => 'int32u' }, + '060e2b34.0101.0105.06010104.01020100' => { Name => 'EssenceContainerFormat', Type => 'UL', Unknown => 1 }, + '060e2b34.0101.0105.06010104.01030100' => { Name => 'CodecDefinition', Type => 'UL', Unknown => 1 }, + '060e2b34.0101.0105.06010104.020c0000' => { Name => 'DescriptiveMetadataFramework', Type => 'StrongReference', Unknown => 1 }, + '060e2b34.0101.0105.06010104.02400500' => { Name => 'GroupSet', Type => 'StrongReference', Unknown => 1 }, + '060e2b34.0101.0105.06010104.02401c00' => { Name => 'BankDetailsSet', Type => 'StrongReference', Unknown => 1 }, + '060e2b34.0101.0105.06010104.02401d00' => { Name => 'ImageFormatSet', Type => 'StrongReference', Unknown => 1 }, + '060e2b34.0101.0105.06010104.02402000' => { Name => 'ProcessingSet', Type => 'StrongReference', Unknown => 1 }, + '060e2b34.0101.0105.06010104.02402100' => { Name => 'ProjectSet', Type => 'StrongReference', Unknown => 1 }, + '060e2b34.0101.0105.06010104.02402200' => { Name => 'ContactsListSet', Type => 'StrongReference', Unknown => 1 }, + # '060e2b34.0101.0105.06010104.02402300' => { Name => 'CueWordsSets', Type => 'Node' }, + '060e2b34.0101.0105.06010104.02402301' => { Name => 'AnnotationCueWordsSet', Type => 'StrongReference', Unknown => 1 }, + '060e2b34.0101.0105.06010104.02402302' => { Name => 'ShotCueWordsSet', Type => 'StrongReference', Unknown => 1 }, + # '060e2b34.0101.0105.06010104.03400000' => { Name => 'WeakReferencingToDescriptiveMetadataSets', Type => 'Node' }, + # '060e2b34.0101.0105.06010104.03401300' => { Name => 'ParticipantRoleSets', Type => 'Node' }, + '060e2b34.0101.0105.06010104.03401301' => { Name => 'AwardParticipantSets', Type => 'GlobalReferenceBatch (Participant)', Unknown => 1 }, + '060e2b34.0101.0105.06010104.03401302' => { Name => 'ContractParticipantSets', Type => 'GlobalReferenceBatch (Participant)', Unknown => 1 }, + '060e2b34.0101.0105.06010104.03401400' => { Name => 'PersonSets', Type => 'GlobalReferenceBatch (Participant)', Unknown => 1 }, + # '060e2b34.0101.0105.06010104.03401500' => { Name => 'OrganizationSets', Type => 'Node' }, + '060e2b34.0101.0105.06010104.03401501' => { Name => 'ParticipantOrganizationSets', Type => 'GlobalReferenceBatch (Organisation)', Unknown => 1 }, + '060e2b34.0101.0105.06010104.03401502' => { Name => 'PersonOrganizationSets', Type => 'GlobalReferenceBatch (Organisation)', Unknown => 1 }, + '060e2b34.0101.0105.06010104.03401600' => { Name => 'LocationSets', Type => 'GlobalReferenceBatch (Location)', Unknown => 1 }, + '060e2b34.0101.0105.06010104.05400400' => { Name => 'TitlesSets', Type => 'StrongReferenceBatch', Unknown => 1 }, + '060e2b34.0101.0105.06010104.05400500' => { Name => 'GroupSets', Type => 'StrongReferenceBatch', Unknown => 1 }, + '060e2b34.0101.0105.06010104.05400600' => { Name => 'IdentificationSets', Type => 'StrongReferenceBatch', Unknown => 1 }, + '060e2b34.0101.0105.06010104.05400700' => { Name => 'EpisodicItemSets', Type => 'StrongReferenceBatch', Unknown => 1 }, + '060e2b34.0101.0105.06010104.05400800' => { Name => 'BrandingSets', Type => 'StrongReferenceBatch', Unknown => 1 }, + '060e2b34.0101.0105.06010104.05400900' => { Name => 'EventSets', Type => 'StrongReferenceBatch', Unknown => 1 }, + '060e2b34.0101.0105.06010104.05400a00' => { Name => 'PublicationSets', Type => 'StrongReferenceBatch', Unknown => 1 }, + '060e2b34.0101.0105.06010104.05400b00' => { Name => 'AwardSets', Type => 'StrongReferenceBatch', Unknown => 1 }, + '060e2b34.0101.0105.06010104.05400c00' => { Name => 'CaptionDescriptionSets', Type => 'StrongReferenceBatch', Unknown => 1 }, + '060e2b34.0101.0105.06010104.05400d00' => { Name => 'AnnotationSets', Type => 'StrongReferenceBatch', Unknown => 1 }, + # '060e2b34.0101.0105.06010104.05400e00' => { Name => 'SettingPeriodSets', Type => 'Node' }, + '060e2b34.0101.0105.06010104.05400e01' => { Name => 'ProductionSettingPeriodSets', Type => 'StrongReferenceBatch', Unknown => 1 }, + '060e2b34.0101.0105.06010104.05400e02' => { Name => 'SceneSettingPeriodSets', Type => 'StrongReferenceBatch', Unknown => 1 }, + '060e2b34.0101.0105.06010104.05400f00' => { Name => 'ScriptingSets', Type => 'StrongReferenceBatch', Unknown => 1 }, + '060e2b34.0101.0105.06010104.05401000' => { Name => 'ClassificationSets', Type => 'StrongReferenceBatch', Unknown => 1 }, + # '060e2b34.0101.0105.06010104.05401100' => { Name => 'ShotSets', Type => 'Node' }, + '060e2b34.0101.0105.06010104.05401101' => { Name => 'SceneShotSets', Type => 'StrongReferenceBatch', Unknown => 1 }, + '060e2b34.0101.0105.06010104.05401102' => { Name => 'ClipShotSets', Type => 'StrongReferenceBatch', Unknown => 1 }, + '060e2b34.0101.0105.06010104.05401200' => { Name => 'KeyPointSets', Type => 'StrongReferenceBatch', Unknown => 1 }, + '060e2b34.0101.0105.06010104.05401300' => { Name => 'ShotParticipantRoleSets', Type => 'StrongReferenceBatch', Unknown => 1 }, + '060e2b34.0101.0105.06010104.05401400' => { Name => 'ShotPersonSets', Type => 'StrongReferenceBatch', Unknown => 1 }, + '060e2b34.0101.0105.06010104.05401500' => { Name => 'OrganizationSets', Type => 'StrongReferenceBatch', Unknown => 1 }, + '060e2b34.0101.0105.06010104.05401600' => { Name => 'ShotLocationSets', Type => 'StrongReferenceBatch', Unknown => 1 }, + '060e2b34.0101.0105.06010104.05401700' => { Name => 'AddressSets', Type => 'StrongReferenceBatch', Unknown => 1 }, + '060e2b34.0101.0105.06010104.05401800' => { Name => 'CommunicationSets', Type => 'StrongReferenceBatch', Unknown => 1 }, + '060e2b34.0101.0105.06010104.05401900' => { Name => 'ContractSets', Type => 'StrongReferenceBatch', Unknown => 1 }, + '060e2b34.0101.0105.06010104.05401a00' => { Name => 'RightsSets', Type => 'StrongReferenceBatch', Unknown => 1 }, + '060e2b34.0101.0105.06010104.05401b00' => { Name => 'PaymentsSets', Type => 'StrongReferenceBatch', Unknown => 1 }, + '060e2b34.0101.0105.06010104.05401e00' => { Name => 'DeviceParametersSets', Type => 'StrongReferenceBatch', Unknown => 1 }, + # '060e2b34.0101.0105.06010104.05401f00' => { Name => 'NameValueSets', Type => 'Node' }, + '060e2b34.0101.0105.06010104.05401f01' => { Name => 'ClassificationNameValueSets', Type => 'StrongReferenceBatch', Unknown => 1 }, + '060e2b34.0101.0105.06010104.05401f02' => { Name => 'ContactNameValueSets', Type => 'StrongReferenceBatch', Unknown => 1 }, + '060e2b34.0101.0105.06010104.05401f03' => { Name => 'DeviceParameterNameValueSets', Type => 'StrongReferenceBatch', Unknown => 1 }, + '060e2b34.0101.0105.06010104.060c0000' => { Name => 'MetadataServerLocators', Type => 'StrongReferenceArray', Unknown => 1 }, + '060e2b34.0101.0105.06010104.060d0000' => { Name => 'RelatedMaterialLocators', Type => 'StrongReferenceArray', Unknown => 1 }, + '060e2b34.0101.0105.06010107.15000000' => { Name => 'LocalTagEntries', Type => 'LocalTagEntryBatch', Unknown => 1 }, + '060e2b34.0101.0105.06100400.00000000' => { Name => 'TotalNumberInSequence', Format => 'int32u' }, + '060e2b34.0101.0105.07012001.04011100' => { Name => 'RoomOrSuiteName', Format => 'string' }, + '060e2b34.0101.0105.07012001.04011101' => { Name => 'RoomOrSuiteName', Type => 'UTF-16' }, + '060e2b34.0101.0105.07012001.04011200' => { Name => 'BuildingName', Format => 'string' }, + '060e2b34.0101.0105.07012001.04011201' => { Name => 'BuildingName', Type => 'UTF-16' }, + '060e2b34.0101.0105.07012001.10030601' => { Name => 'URL', Type => 'UTF-16' }, + # '060e2b34.0101.0105.07020102.07100000' => { Name => 'DefinedEventStartTrueDateTime', Type => 'Node' }, + '060e2b34.0101.0105.07020102.07100100' => { Name => 'LocalFestivalDateTime', Format => 'string', Groups => { 2 => 'Time' } }, + '060e2b34.0101.0105.07020103.01090000' => { Name => 'ShotStartPosition', Type => 'Position', %duration }, + '060e2b34.0101.0105.07020103.010a0000' => { Name => 'IndexingStartPosition', Type => 'Position', %duration }, + '060e2b34.0101.0105.07020103.010b0000' => { Name => 'EventOrigin', Type => 'Position', %duration }, + '060e2b34.0101.0105.07020108.03000000' => { Name => 'SettingPeriodDescription', Format => 'string' }, + '060e2b34.0101.0105.07020108.03010000' => { Name => 'SettingPeriodDescription', Type => 'UTF-16' }, + '060e2b34.0101.0105.07020201.01020000' => { Name => 'IndexDuration', Type => 'Length', %duration }, + '060e2b34.0101.0105.07020201.02040000' => { Name => 'ShotDuration', Type => 'Length', %duration }, + # '060e2b34.0101.0105.0d020000.00000000' => { Name => 'EBU_UER', Type => 'Node' }, + # '060e2b34.0101.0105.0d030000.00000000' => { Name => 'Pro-MPEGForum', Type => 'Node' }, + # '060e2b34.0101.0106.0e040000.00000000' => { Name => 'Avid', Type => 'Node' }, + # '060e2b34.0101.0106.0e050000.00000000' => { Name => 'CNN', Type => 'Node' }, + # '060e2b34.0101.0106.0e050100.00000000' => { Name => 'CNNMediaIdentifiers', Type => 'Node' }, + # '060e2b34.0101.0106.0e050101.00000000' => { Name => 'CNNLegacyMediaIdentifiers', Type => 'Node' }, + # '060e2b34.0101.0106.0e050200.00000000' => { Name => 'CNNAttributes', Type => 'Node' }, + # '060e2b34.0101.0106.0e050201.00000000' => { Name => 'CNNRelationalAttributes', Type => 'Node' }, + # '060e2b34.0101.0106.0e050202.00000000' => { Name => 'CNNInformationAttributes', Type => 'Node' }, + # '060e2b34.0101.0106.0e050300.00000000' => { Name => 'CNNMetadataSets', Type => 'Node' }, + # '060e2b34.0101.0106.0e060000.00000000' => { Name => 'Sony', Type => 'Node' }, + '060e2b34.0101.0107.01011509.00000000' => { Name => 'ExtendedClipID', Type => 'UMID' }, + '060e2b34.0101.0107.0101150a.00000000' => { Name => 'ClipIDArray', Type => 'UMID Array', Unknown => 1 }, + '060e2b34.0101.0107.0101150b.00000000' => { Name => 'ExtendedClipIDArray', Type => 'UMID Array', Unknown => 1 }, + '060e2b34.0101.0107.01040104.00000000' => { Name => 'TrackNumberBatch', Format => 'int32u' }, + '060e2b34.0101.0107.03010102.02110000' => { Name => 'ExtendedTextLanguageCode', Format => 'string', LanguageCode => 1 }, + '060e2b34.0101.0107.03010102.02120000' => { Name => 'ExtendedCaptionsLanguageCode', Format => 'string' }, + '060e2b34.0101.0107.03010102.02130000' => { Name => 'FrameworkExtendedTextLanguageCode', Format => 'string', LanguageCode => 1 }, + '060e2b34.0101.0107.03010102.03110000' => { Name => 'PrimaryExtendedSpokenLanguageCode', Format => 'string' }, + '060e2b34.0101.0107.03010102.03120000' => { Name => 'SecondaryExtendedSpokenLanguageCode', Format => 'string' }, + '060e2b34.0101.0107.03010102.03130000' => { Name => 'OriginalExtendedSpokenPrimaryLanguageCode', Format => 'string' }, + '060e2b34.0101.0107.03010102.03140000' => { Name => 'SecondaryOriginalExtendedSpokenLanguageCode', Format => 'string' }, + '060e2b34.0101.0107.03010210.06000000' => { Name => 'KLVMetadataSequence', Type => 'Sequence of KLV packets', Unknown => 1 }, + '060e2b34.0101.0107.03010210.07000000' => { Name => 'PackageAttributes', Type => 'StrongReferenceArray', Unknown => 1 }, + '060e2b34.0101.0107.03010210.08000000' => { Name => 'ComponentAttributes', Type => 'StrongReferenceArray', Unknown => 1 }, + # '060e2b34.0101.0107.03010220.02000000' => { Name => 'XMLBiMConstructsInMultipleStreams', Type => 'Node' }, + # '060e2b34.0101.0107.03010220.02010000' => { Name => 'MPEG7BiMDecoderInitFrames', Type => 'Node' }, + '060e2b34.0101.0107.03010220.02010100' => { Name => 'MPEG7BiMDecoderInitFrame1', Type => 'ByteStream', Unknown => 1 }, + '060e2b34.0101.0107.03010220.02010200' => { Name => 'MPEG7BiMDecoderInitFrame2', Type => 'ByteStream', Unknown => 1 }, + '060e2b34.0101.0107.03010220.02010300' => { Name => 'MPEG7BiMDecoderInitFrame3', Type => 'ByteStream', Unknown => 1 }, + '060e2b34.0101.0107.03010220.02010400' => { Name => 'MPEG7BiMDecoderInitFrame4', Type => 'ByteStream', Unknown => 1 }, + '060e2b34.0101.0107.03010220.02010500' => { Name => 'MPEG7BiMDecoderInitFrame5', Type => 'ByteStream', Unknown => 1 }, + '060e2b34.0101.0107.03010220.02010600' => { Name => 'MPEG7BiMDecoderInitFrame6', Type => 'ByteStream', Unknown => 1 }, + '060e2b34.0101.0107.03010220.02010700' => { Name => 'MPEG7BiMDecoderInitFrame7', Type => 'ByteStream', Unknown => 1 }, + '060e2b34.0101.0107.03010220.02010800' => { Name => 'MPEG7BiMDecoderInitFrame8', Type => 'ByteStream', Unknown => 1 }, + # '060e2b34.0101.0107.03010220.02020000' => { Name => 'MPEG7BiMAccessUnitFrames', Type => 'Node' }, + '060e2b34.0101.0107.03010220.02020100' => { Name => 'MPEG7BiMAccessUnitFrame1', Type => 'ByteStream', Unknown => 1 }, + '060e2b34.0101.0107.03010220.02020200' => { Name => 'MPEG7BiMAccessUnitFrame2', Type => 'ByteStream', Unknown => 1 }, + '060e2b34.0101.0107.03010220.02020300' => { Name => 'MPEG7BiMAccessUnitFrame3', Type => 'ByteStream', Unknown => 1 }, + '060e2b34.0101.0107.03010220.02020400' => { Name => 'MPEG7BiMAccessUnitFrame4', Type => 'ByteStream', Unknown => 1 }, + '060e2b34.0101.0107.03010220.02020500' => { Name => 'MPEG7BiMAccessUnitFrame5', Type => 'ByteStream', Unknown => 1 }, + '060e2b34.0101.0107.03010220.02020600' => { Name => 'MPEG7BiMAccessUnitFrame6', Type => 'ByteStream', Unknown => 1 }, + '060e2b34.0101.0107.03010220.02020700' => { Name => 'MPEG7BiMAccessUnitFrame7', Type => 'ByteStream', Unknown => 1 }, + '060e2b34.0101.0107.03010220.02020800' => { Name => 'MPEG7BiMAccessUnitFrame8', Type => 'ByteStream', Unknown => 1 }, + '060e2b34.0101.0107.03020102.16000000' => { Name => 'ComponentUserComments', Type => 'StrongReferenceArray', Unknown => 1 }, + '060e2b34.0101.0107.03020501.01000000' => { Name => 'ShotCommentKind', Type => 'UTF-16' }, + '060e2b34.0101.0107.03020502.01000000' => { Name => 'ShotComment', Type => 'UTF-16' }, + # '060e2b34.0101.0107.04010202.00000000' => { Name => 'SensorParameters', Type => 'Node' }, + '060e2b34.0101.0107.04010202.01000000' => { Name => 'SensorMode', Format => 'string' }, + '060e2b34.0101.0107.04020101.05000000' => { Name => 'ChannelAssignment', Type => 'UL', Unknown => 1 }, + '060e2b34.0101.0107.04040402.06000000' => { Name => 'ContentPackageIndexArray', Type => 'ArrayOfIndexEntry', Unknown => 1 }, + # '060e2b34.0101.0107.04040403.00000000' => { Name => 'VideoIndexParameters', Type => 'Node' }, + '060e2b34.0101.0107.04040403.01000000' => { Name => 'VideoIndexArray', Type => 'Array of bytes', Unknown => 1 }, + '060e2b34.0101.0107.04060202.00000000' => { Name => 'ApproximateImageContainerSize', Format => 'int32u' }, + '060e2b34.0101.0107.04060801.00000000' => { Name => 'MetadataEncodingSchemeCode', Format => 'string' }, + '060e2b34.0101.0107.04090200.00000000' => { Name => 'MIMEMediaType', Format => 'string' }, + '060e2b34.0101.0107.04090201.00000000' => { Name => 'MIMEMediaType', Type => 'UTF-16' }, + '060e2b34.0101.0107.04200201.010a0100' => { Name => 'FieldOfViewVerticalFP', Format => 'float' }, + '060e2b34.0101.0107.05010108.00000000' => { Name => 'PackageUsageKind', Type => 'AUID', Unknown => 1 }, + '060e2b34.0101.0107.06010103.06000000' => { Name => 'ChannelID', Format => 'int32u' }, + '060e2b34.0101.0107.06010103.07000000' => { Name => 'ChannelIDs', Format => 'int32u' }, + '060e2b34.0101.0107.06010104.01090000' => { Name => 'KLVDataType', Type => 'WeakReference', Unknown => 1 }, + '060e2b34.0101.0107.06010104.03040000' => { Name => 'KLVDataParentProperties', Type => 'WeakReferenceBatch', Unknown => 1 }, + '060e2b34.0101.0107.06010104.03050000' => { Name => 'TaggedValueParentProperties', Type => 'WeakReferenceBatch', Unknown => 1 }, + '060e2b34.0101.0107.06010104.03401303' => { Name => 'AnnotationParticipantSets', Type => 'GlobalReferenceBatch', Unknown => 1 }, + '060e2b34.0101.0107.06010104.050a0000' => { Name => 'KLVDataDefinitions', Type => 'StrongReferenceBatch', Unknown => 1 }, + '060e2b34.0101.0107.06010104.050b0000' => { Name => 'TaggedValueDefinitions', Type => 'StrongReferenceBatch', Unknown => 1 }, + '060e2b34.0101.0107.06010104.05401f04' => { Name => 'AddressNameValueSets', Type => 'StrongReferenceBatch', Unknown => 1 }, + '060e2b34.0101.0107.07010201.02300000' => { Name => 'NMEADocumentText', Format => 'string' }, + '060e2b34.0101.0107.07011001.04000000' => { Name => 'PlatformRollAngle', Format => 'float' }, + '060e2b34.0101.0107.07011001.05000000' => { Name => 'PlatformPitchAngle', Format => 'float' }, + '060e2b34.0101.0107.07011001.06000000' => { Name => 'PlatformHeadingAngle', Format => 'float' }, + '060e2b34.0101.0107.07012001.04011300' => { Name => 'AddressLine', Format => 'string' }, + '060e2b34.0101.0107.07012001.04011301' => { Name => 'AddressLine', Type => 'UTF-16' }, + '060e2b34.0101.0107.07012001.04011400' => { Name => 'PlaceName', Format => 'string' }, + '060e2b34.0101.0107.07012001.04011401' => { Name => 'PlaceName', Type => 'UTF-16' }, + '060e2b34.0101.0107.07012001.04011500' => { Name => 'GeographicalCoordinates', Type => '12-byte Spatial Coordinate', Unknown => 1 }, + '060e2b34.0101.0107.07012001.04011600' => { Name => 'AstronomicalBodyName', Format => 'string' }, + '060e2b34.0101.0107.07012001.04011601' => { Name => 'AstronomicalBodyName', Type => 'UTF-16' }, + '060e2b34.0101.0107.07020102.08020000' => { Name => 'TimecodeArray', Type => 'Array of timecodes', Unknown => 1 }, + '060e2b34.0101.0107.07020103.010c0000' => { Name => 'MarkIn', Type => 'Position', %duration }, + '060e2b34.0101.0107.07020103.010d0000' => { Name => 'UserPosition', Type => 'Position', %duration }, + '060e2b34.0101.0107.07020103.02030000' => { Name => 'MarkOut', Type => 'Position', %duration }, + '060e2b34.0101.0107.07020110.01040000' => { Name => 'ClipCreationDateTime', %timestamp }, + '060e2b34.0101.0107.07020201.02050000' => { Name => 'VideoClipDuration', Format => 'int32u' }, + # '060e2b34.0101.0107.0d040000.00000000' => { Name => 'BBC', Type => 'Node' }, + # '060e2b34.0101.0107.0d050000.00000000' => { Name => 'IRT', Type => 'Node' }, + # '060e2b34.0101.0107.0e070000.00000000' => { Name => 'IdeasUnlimitedTV', Type => 'Node' }, + # '060e2b34.0101.0107.0e080000.00000000' => { Name => 'IPV', Type => 'Node' }, + # '060e2b34.0101.0107.0e090000.00000000' => { Name => 'Dolby', Type => 'Node' }, + # '060e2b34.0101.0108.01011540.00000000' => { Name => 'GloballyUniqueObjectIdentifiers', Type => 'Node' }, + # '060e2b34.0101.0108.01011540.01000000' => { Name => 'GloballyUniqueHumanIdentifiers', Type => 'Node' }, + '060e2b34.0101.0108.01011540.01010000' => { Name => 'ParticipantID', Type => 'UID', Unknown => 1 }, + '060e2b34.0101.0108.01011540.01020000' => { Name => 'ContactID', Type => 'UID', Unknown => 1 }, + '060e2b34.0101.0108.01020104.00000000' => { Name => 'DefaultNamespaceURI', Format => 'string' }, + '060e2b34.0101.0108.01020104.01000000' => { Name => 'DefaultNamespaceURI', Type => 'UTF-16' }, + '060e2b34.0101.0108.01020105.00000000' => { Name => 'NamespaceURI', Format => 'string' }, + '060e2b34.0101.0108.01020105.01000000' => { Name => 'NamespaceURI', Type => 'UTF-16' }, + '060e2b34.0101.0108.01020106.00000000' => { Name => 'NamespaceURIs', Format => 'string' }, + '060e2b34.0101.0108.01020106.01000000' => { Name => 'NamespaceURIs', Type => 'UTF-16' }, + '060e2b34.0101.0108.01030604.00000000' => { Name => 'HTMLDOCTYPE', Format => 'string' }, + '060e2b34.0101.0108.01030604.01000000' => { Name => 'HTMLDOCTYPE', Type => 'UTF-16' }, + '060e2b34.0101.0108.01030605.00000000' => { Name => 'NamespacePrefix', Format => 'string' }, + '060e2b34.0101.0108.01030605.01000000' => { Name => 'NamespacePrefix', Type => 'UTF-16' }, + '060e2b34.0101.0108.01030606.00000000' => { Name => 'NamespacePrefixes', Format => 'string' }, + '060e2b34.0101.0108.01030606.01000000' => { Name => 'NamespacePrefixes', Type => 'UTF-16' }, + '060e2b34.0101.0108.02050404.00000000' => { Name => 'RightsComment', Format => 'string' }, + '060e2b34.0101.0108.02050404.01000000' => { Name => 'RightsComment', Type => 'UTF-16' }, + '060e2b34.0101.0108.03020201.06000000' => { Name => 'NominationCategory', Format => 'string' }, + '060e2b34.0101.0108.03020201.06010000' => { Name => 'NominationCategory', Type => 'UTF-16' }, + '060e2b34.0101.0108.04020301.06000000' => { Name => 'PeakEnvelopeVersion', Format => 'int32u' }, + '060e2b34.0101.0108.04020301.07000000' => { Name => 'PeakEnvelopeFormat', Format => 'int32u' }, + '060e2b34.0101.0108.04020301.08000000' => { Name => 'PointsPerPeakValue', Format => 'int32u' }, + '060e2b34.0101.0108.04020301.09000000' => { Name => 'PeakEnvelopeBlockSize', Format => 'int32u' }, + '060e2b34.0101.0108.04020301.0a000000' => { Name => 'PeakChannelCount', Format => 'int32u' }, + '060e2b34.0101.0108.04020301.0b000000' => { Name => 'PeakFrameCount', Format => 'int32u' }, + '060e2b34.0101.0108.04020301.0c000000' => { Name => 'PeakOfPeaksPosition', Type => 'Position', %duration }, + '060e2b34.0101.0108.04020301.0d000000' => { Name => 'PeakEnvelopeTimestamp', Format => 'int32u' }, + '060e2b34.0101.0108.04020301.0e000000' => { Name => 'PeakEnvelopeData', Type => 'Stream', Unknown => 1 }, + '060e2b34.0101.0108.04060802.00000000' => { Name => 'RIFFChunkID', Format => 'int32u' }, + '060e2b34.0101.0108.04060903.00000000' => { Name => 'RIFFChunkLength', Format => 'int32u' }, + '060e2b34.0101.0108.04070400.00000000' => { Name => 'RIFFChunkData', Type => 'DataStream', Unknown => 1 }, + '060e2b34.0101.0108.04090300.00000000' => { Name => 'MIMECharSet', Format => 'string' }, + '060e2b34.0101.0108.04090301.00000000' => { Name => 'MIMECharSet', Type => 'UTF-16' }, + '060e2b34.0101.0108.04090400.00000000' => { Name => 'MIMEEncoding', Format => 'string' }, + '060e2b34.0101.0108.04090401.00000000' => { Name => 'MIMEEncoding', Type => 'UTF-16' }, + '060e2b34.0101.0108.06010103.08000000' => { Name => 'MonoSourceTrackIDs', Format => 'int32u' }, + '060e2b34.0101.0108.06010104.010a0000' => { Name => 'CompositionRendering', Type => 'PackageID', Unknown => 1 }, + '060e2b34.0101.0108.06010104.03401304' => { Name => 'CaptionsDescriptionParticipantSets', Type => 'GlobalReferenceBatch', Unknown => 1 }, + '060e2b34.0101.0108.06010104.05400d01' => { Name => 'EventAnnotationSets', Type => 'StrongReferenceBatch', Unknown => 1 }, + '060e2b34.0101.0108.06010104.060e0000' => { Name => 'ScriptingLocators', Type => 'StrongReferenceArray', Unknown => 1 }, + '060e2b34.0101.0108.06010104.060f0000' => { Name => 'UnknownBWFChunks', Type => 'StrongReferenceArray', Unknown => 1 }, + # '060e2b34.0101.0108.0e0a0000.00000000' => { Name => 'SnellAndWilcox', Type => 'Node' }, + '060e2b34.0101.0109.01011511.00000000' => { Name => 'CryptographicContextID', Type => 'UUID', Unknown => 1 }, + '060e2b34.0101.0109.01012101.01000000' => { Name => 'PlatformDesignation', Type => 'UTF-16' }, + '060e2b34.0101.0109.01030107.01000000' => { Name => 'LocalTargetID', Type => 'UTF-16' }, + '060e2b34.0101.0109.01030109.00000000' => { Name => 'NITFLayerTargetID', Format => 'string' }, + '060e2b34.0101.0109.01030109.01000000' => { Name => 'NITFLayerTargetID', Type => 'UTF-16' }, + '060e2b34.0101.0109.01030302.00000000' => { Name => 'PackageName', Format => 'string' }, + '060e2b34.0101.0109.01030406.00000000' => { Name => 'RP217DataStreamPID', Format => 'int16u' }, + '060e2b34.0101.0109.01030407.00000000' => { Name => 'RP217VideoStreamPID', Format => 'int16u' }, + '060e2b34.0101.0109.02010101.00000000' => { Name => 'SourceOrganization', Type => 'UTF-16' }, + '060e2b34.0101.0109.02010301.00000000' => { Name => 'OriginalProducerName', Type => 'UTF-16' }, + '060e2b34.0101.0109.02080201.01000000' => { Name => 'SecurityClassification', Type => 'UTF-16' }, + '060e2b34.0101.0109.02080202.01000000' => { Name => 'SecurityClassificationCaveats', Type => 'UTF-16' }, + '060e2b34.0101.0109.02080207.01000000' => { Name => 'ClassificationComment', Type => 'UTF-16' }, + # '060e2b34.0101.0109.02090200.00000000' => { Name => 'DataEncryption', Type => 'Node' }, + # '060e2b34.0101.0109.02090201.00000000' => { Name => 'DataEncryptionAlgorithms', Type => 'Node' }, + # '060e2b34.0101.0109.02090202.00000000' => { Name => 'DataHashingAlgorithms', Type => 'Node' }, + # '060e2b34.0101.0109.02090300.00000000' => { Name => 'DigitalCinemaEncryption', Type => 'Node' }, + # '060e2b34.0101.0109.02090301.00000000' => { Name => 'DigitalCinemaEncryptionAlgorithms', Type => 'Node' }, + '060e2b34.0101.0109.02090301.01000000' => { Name => 'CipherAlgorithm', Type => 'UL', Unknown => 1 }, + '060e2b34.0101.0109.02090301.02000000' => { Name => 'CryptographicKeyID', Type => 'UUID', Unknown => 1 }, + '060e2b34.0101.0109.02090301.03000000' => { Name => 'EncryptedSourceValue', Type => 'DataValue', Unknown => 1 }, + # '060e2b34.0101.0109.02090302.00000000' => { Name => 'DigitalCinemaHashingAlgorithms', Type => 'Node' }, + '060e2b34.0101.0109.02090302.01000000' => { Name => 'MICAlgorithm', Type => 'UL', Unknown => 1 }, + '060e2b34.0101.0109.02090302.02000000' => { Name => 'MIC', Type => 'DataValue', Unknown => 1 }, + '060e2b34.0101.0109.03010102.01010000' => { Name => 'ISO639-1LanguageCode', Type => 'UTF-16' }, + '060e2b34.0101.0109.03020106.10000000' => { Name => 'JFIFMarkerDescription', Format => 'string' }, + '060e2b34.0101.0109.03020106.10010000' => { Name => 'JFIFMarkerDescription', Type => 'UTF-16' }, + '060e2b34.0101.0109.03020106.11000000' => { Name => 'HTMLMetaDescription', Format => 'string' }, + '060e2b34.0101.0109.03020106.11010000' => { Name => 'HTMLMetaDescription', Type => 'UTF-16' }, + '060e2b34.0101.0109.03020401.02000000' => { Name => 'MetadataItemName', Format => 'string' }, + '060e2b34.0101.0109.04010201.01060000' => { Name => 'ColorPrimaries', Format => 'string' }, + '060e2b34.0101.0109.04010201.01060100' => { Name => 'ColorPrimaries', Type => 'ColorPrimariesType', Unknown => 1 }, + '060e2b34.0101.0109.04060203.00000000' => { Name => 'ProductFormat', Format => 'string' }, + '060e2b34.0101.0109.04060203.01000000' => { Name => 'ProductFormat', Type => 'UTF-16' }, + '060e2b34.0101.0109.04061002.00000000' => { Name => 'SourceLength', Format => 'int64u' }, + '060e2b34.0101.0109.04200102.01010100' => { Name => 'ImageSourceDeviceKind', Type => 'UTF-16' }, + '060e2b34.0101.0109.06010102.02000000' => { Name => 'SourceContainerFormat', Type => 'UL', Unknown => 1 }, + '060e2b34.0101.0109.06010102.03000000' => { Name => 'SourceKey', Type => 'UL', Unknown => 1 }, + '060e2b34.0101.0109.06010103.09000000' => { Name => 'DynamicSourcePackageID', Type => 'PackageID', Unknown => 1 }, + '060e2b34.0101.0109.06010103.0a000000' => { Name => 'DynamicSourceTrackIDs', Format => 'int32u' }, + '060e2b34.0101.0109.06010103.0b000000' => { Name => 'SourceIndex', Type => 'Indirect', Unknown => 1 }, + '060e2b34.0101.0109.06010103.0c000000' => { Name => 'SourceSpecies', Type => 'Indirect', Unknown => 1 }, + '060e2b34.0101.0109.06010103.0d000000' => { Name => 'SourceValue', Type => 'Indirect', Unknown => 1 }, + '060e2b34.0101.0109.06010104.020d0000' => { Name => 'CryptographicContextObject', Type => 'StrongReference', Unknown => 1 }, + '060e2b34.0101.0109.06010104.06100000' => { Name => 'Sub-descriptors', Type => 'StrongReferenceArray', Unknown => 1 }, + '060e2b34.0101.0109.06010106.02000000' => { Name => 'EncryptedTrackFileID', Type => 'UUID', Unknown => 1 }, + '060e2b34.0101.0109.06010106.03000000' => { Name => 'CryptographicContextLink', Type => 'UUID', Unknown => 1 }, + '060e2b34.0101.0109.06090201.03000000' => { Name => 'PlaintextOffset', Format => 'int64u' }, + '060e2b34.0101.0109.06100500.00000000' => { Name => 'TripletSequenceNumber', Format => 'int64u' }, + '060e2b34.0101.0109.07010201.030f0000' => { Name => 'BoundingRectangle', Type => 'Geographic Rectangle', Unknown => 1 }, + '060e2b34.0101.0109.07010201.03100000' => { Name => 'GeographicLocation', Type => 'Geographic Polygon', Unknown => 1 }, + '060e2b34.0101.0109.07010201.03110000' => { Name => 'GeographicPolygonCoordinates', Type => 'Array of GeographicCoordinate', Unknown => 1 }, + '060e2b34.0101.0109.07010201.03120000' => { Name => 'GeographicAreaNorthwest', Type => 'GeographicCoordinate', Unknown => 1 }, + '060e2b34.0101.0109.07010201.03130000' => { Name => 'GeographicAreaSoutheast', Type => 'GeographicCoordinate', Unknown => 1 }, + '060e2b34.0101.0109.07010201.03140000' => { Name => 'GeographicAreaSourceDatum', Format => 'string' }, + '060e2b34.0101.0109.07010201.03150000' => { Name => 'GeographicPolygonSourceDatum', Format => 'string' }, + '060e2b34.0101.0109.07012001.02070100' => { Name => 'CountryCodeMethod', Type => 'UTF-16' }, + '060e2b34.0101.0109.07012001.02080100' => { Name => 'ClassifyingCountryCode', Type => 'UTF-16' }, + '060e2b34.0101.0109.07012001.02090100' => { Name => 'ReleasableCountryCode', Type => 'UTF-16' }, + '060e2b34.0101.0109.07020102.01010100' => { Name => 'UTCStartDateTime', Type => 'UTF-16', Groups => { 2 => 'Time' } }, + '060e2b34.0101.0109.07020102.01030000' => { Name => 'UTCInstantDateTime', Format => 'string', Groups => { 2 => 'Time' } }, + '060e2b34.0101.0109.07020102.01030100' => { Name => 'UTCInstantDateTime', Type => 'UTF-16', Groups => { 2 => 'Time' } }, + '060e2b34.0101.0109.07020102.05010100' => { Name => 'UTCLastModifyDate', Type => 'UTF-16', Groups => { 2 => 'Time' } }, + '060e2b34.0101.0109.07020501.00000000' => { Name => 'ToleranceMode', Type => 'ToleranceModeType', Unknown => 1 }, + '060e2b34.0101.0109.07020502.00000000' => { Name => 'ToleranceWindow', Type => 'Indirect', Unknown => 1 }, + '060e2b34.0101.0109.07020503.00000000' => { Name => 'ToleranceInterpolationMethod', Type => 'WeakReferenceInterpolationDefinition', Unknown => 1 }, + # '060e2b34.0101.0109.0d060000.00000000' => { Name => 'ARIB', Type => 'Node' }, + # '060e2b34.0101.0109.0d070000.00000000' => { Name => 'AMIA', Type => 'Node' }, + # '060e2b34.0101.0109.0e0b0000.00000000' => { Name => 'OmneonVideoNetworks', Type => 'Node' }, + # '060e2b34.0101.0109.0e0c0000.00000000' => { Name => 'AscentMediaGroup', Type => 'Node' }, + # '060e2b34.0101.0109.0e0c0100.00000000' => { Name => 'Published', Type => 'Node' }, + # '060e2b34.0101.0109.0e0d0000.00000000' => { Name => 'Quantel', Type => 'Node' }, + # '060e2b34.0101.0109.0e0e0000.00000000' => { Name => 'Panasonic', Type => 'Node' }, + '060e2b34.0101.010a.04010502.03000000' => { Name => 'VBILineCount', Format => 'int16u' }, + '060e2b34.0101.010a.04010502.04000000' => { Name => 'StoredVBILineNumber', Format => 'int16u' }, + '060e2b34.0101.010a.04010502.05000000' => { Name => 'VBIWrappingType', Format => 'int8u' }, + '060e2b34.0101.010a.04010502.06000000' => { Name => 'VBIPayloadSampleCount', Format => 'int16u' }, + '060e2b34.0101.010a.04010502.07000000' => { Name => 'VBIPayloadByteArray', Format => 'int8u' }, + '060e2b34.0101.010a.04010502.08000000' => { Name => 'ANCPacketCount', Format => 'int16u' }, + '060e2b34.0101.010a.04010502.09000000' => { Name => 'StoredANCLineNumber', Format => 'int16u' }, + '060e2b34.0101.010a.04010502.0a000000' => { Name => 'ANCWrappingType', Format => 'int8u' }, + '060e2b34.0101.010a.04010502.0b000000' => { Name => 'ANCPayloadSampleCount', Format => 'int16u' }, + '060e2b34.0101.010a.04010502.0c000000' => { Name => 'ANCPayloadByteArray', Format => 'int8u' }, + '060e2b34.0101.010a.04010503.0f000000' => { Name => 'VBIPayloadSampleCoding', Format => 'int8u' }, + '060e2b34.0101.010a.04010503.10000000' => { Name => 'ANCPayloadSampleCoding', Format => 'int8u' }, + # '060e2b34.0101.010a.04010603.00000000' => { Name => 'JPEG2000CodingParameters', Type => 'Node' }, + '060e2b34.0101.010a.04010603.01000000' => { Name => 'Rsiz', Format => 'int16u' }, + '060e2b34.0101.010a.04010603.02000000' => { Name => 'Xsiz', Format => 'int32u' }, + '060e2b34.0101.010a.04010603.03000000' => { Name => 'Ysiz', Format => 'int32u' }, + '060e2b34.0101.010a.04010603.04000000' => { Name => 'XOsiz', Format => 'int32u' }, + '060e2b34.0101.010a.04010603.05000000' => { Name => 'YOsiz', Format => 'int32u' }, + '060e2b34.0101.010a.04010603.06000000' => { Name => 'XTsiz', Format => 'int32u' }, + '060e2b34.0101.010a.04010603.07000000' => { Name => 'YTsiz', Format => 'int32u' }, + '060e2b34.0101.010a.04010603.08000000' => { Name => 'XTOsiz', Format => 'int32u' }, + '060e2b34.0101.010a.04010603.09000000' => { Name => 'YTOsiz', Format => 'int32u' }, + '060e2b34.0101.010a.04010603.0a000000' => { Name => 'Csiz', Format => 'int16u' }, + '060e2b34.0101.010a.04010603.0b000000' => { Name => 'PictureComponentSizing', Type => 'J2K ComponentSizingArray', Unknown => 1 }, + '060e2b34.0101.010a.04010603.0c000000' => { Name => 'CodingStyleDefault', Type => 'J2K CodingStyleDefault', Unknown => 1 }, + '060e2b34.0101.010a.04010603.0d000000' => { Name => 'QuantizationDefault', Type => 'J2K QuantizationDefault', Unknown => 1 }, + '060e2b34.0101.010a.04020403.01020000' => { Name => 'MPEGAudioBitrate', Format => 'int32u', PrintConv => 'ConvertBitrate($val)', Groups => { 2 => 'Audio' } }, + '060e2b34.0101.010a.04060204.00000000' => { Name => 'CBEStartOffset', Format => 'int64u' }, + '060e2b34.0101.010a.04060205.00000000' => { Name => 'VBEEndOffset', Format => 'int64u' }, + '060e2b34.0101.010a.06010104.02100000' => { Name => 'SubDescriptor', Unknown => 1 }, + '060e2b34.0101.010a.06010104.06100000' => { Name => 'SubDescriptors', Unknown => 1 }, + '060e2b34.0101.010a.06010107.16000000' => { Name => 'RootMetaDictionary', Type => 'StrongReference', Unknown => 1 }, + '060e2b34.0101.010a.06010107.17000000' => { Name => 'RootPreface', Type => 'StrongReference', Unknown => 1 }, + '060e2b34.0101.010a.06010107.18000000' => { Name => 'RootObjectDirectory', Type => 'Array of bytes', Unknown => 1 }, + '060e2b34.0101.010a.06010107.19000000' => { Name => 'RootFormatVersion', Format => 'int32u' }, + '060e2b34.0101.010a.07010201.03160000' => { Name => 'FrameCenterElevation', Format => 'float' }, + '060e2b34.0101.010a.07020103.010e0000' => { Name => 'PackageMarkInPosition', Type => 'Position', %duration }, + '060e2b34.0101.010a.07020103.02040000' => { Name => 'PackageMarkOutPosition', Type => 'Position', %duration }, + # '060e2b34.0101.010a.0d080000.00000000' => { Name => 'PBS', Type => 'Node' }, + # '060e2b34.0101.010a.0e0f0000.00000000' => { Name => 'GrassValley', Type => 'Node' }, + # '060e2b34.0101.010a.0e100000.00000000' => { Name => 'DoremiLabs', Type => 'Node' }, + # '060e2b34.0101.010a.0e110000.00000000' => { Name => 'EVSBroadcastEquipment', Type => 'Node' }, + # '060e2b34.0101.010a.0e120000.00000000' => { Name => 'TurnerBroadcastingSystem', Type => 'Node' }, + '060e2b34.0101.010c.0101110b.00000000' => { Name => 'Ad-ID', Unknown => 1 }, + '060e2b34.0101.010c.01011512.00000000' => { Name => 'ResourceID', Type => 'UUID', Unknown => 1 }, + '060e2b34.0101.010c.01011513.00000000' => { Name => 'AncillaryResourceID', Type => 'UUID', Unknown => 1 }, + '060e2b34.0101.010c.01020210.02030000' => { Name => 'ApplicationSchemeBatch', Type => 'BatchOfUL', Unknown => 1 }, + # '060e2b34.0101.010c.02100202.00000000' => { Name => 'RegisterPublicationInformation', Type => 'Node' }, + '060e2b34.0101.010c.02100202.01000000' => { Name => 'RegisterKind', Type => 'RegisterType', Unknown => 1 }, + '060e2b34.0101.010c.02100202.02000000' => { Name => 'RegisterVersion', Type => 'Hex' }, + '060e2b34.0101.010c.02100202.03000000' => { Name => 'RegisterEditorName', Type => 'UTF-16' }, + '060e2b34.0101.010c.02100202.04000000' => { Name => 'RegisterStatusKind', Type => 'RegisterStatusType', Unknown => 1 }, + # '060e2b34.0101.010c.02100203.00000000' => { Name => 'RegisterItem', Type => 'Node' }, + '060e2b34.0101.010c.02100203.01000000' => { Name => 'RegisterItemName', Type => 'UTF-16' }, + '060e2b34.0101.010c.02100203.02000000' => { Name => 'RegisterItemDefinition', Type => 'UTF-16' }, + '060e2b34.0101.010c.02100203.03000000' => { Name => 'RegisterItemSymbol', Type => 'SymbolType', Unknown => 1 }, + '060e2b34.0101.010c.02100203.04000000' => { Name => 'RegisterItemDefiningDocumentName', Type => 'UTF-16' }, + '060e2b34.0101.010c.02100203.05000000' => { Name => 'RegisterItemUL', Type => 'UniversalLabelType', Unknown => 1 }, + '060e2b34.0101.010c.02100203.06000000' => { Name => 'RegisterItemNotes', Type => 'UTF-16' }, + '060e2b34.0101.010c.02100203.07000000' => { Name => 'RegisterItemIntroductionVersion', Format => 'int8u' }, + '060e2b34.0101.010c.02100203.08000000' => { Name => 'RegisterItemHierarchyLevel', Format => 'int16u' }, + # '060e2b34.0101.010c.02100203.09000000' => { Name => 'RegisterWildcardFlag', Type => 'Node' }, + '060e2b34.0101.010c.02100203.0a000000' => { Name => 'RegisterEntryStatus', Type => 'EntryStatusType', Unknown => 1 }, + # '060e2b34.0101.010c.02100204.00000000' => { Name => 'RegisterAdministration', Type => 'Node' }, + '060e2b34.0101.010c.02100204.01000000' => { Name => 'RegisterAction', Type => 'UTF-16' }, + '060e2b34.0101.010c.02100204.02000000' => { Name => 'RegisterApproverName', Type => 'UTF-16' }, + '060e2b34.0101.010c.02100204.03000000' => { Name => 'RegisterCreationTime', %timestamp }, + '060e2b34.0101.010c.02100204.04000000' => { Name => 'RegistrantName', Type => 'UTF-16' }, + '060e2b34.0101.010c.02100204.05000000' => { Name => 'RegisterItemOriginatorName', Type => 'UTF-16' }, + '060e2b34.0101.010c.02100204.06000000' => { Name => 'RegisterUserName', Type => 'UTF-16' }, + '060e2b34.0101.010c.02100204.07000000' => { Name => 'RegisterUserTime', %timestamp }, + '060e2b34.0101.010c.02100204.08000000' => { Name => 'RegisterAdministrationNotes', Type => 'UTF-16' }, + '060e2b34.0101.010c.04010101.09000000' => { Name => 'AFDAndBarData', Unknown => 1 }, + '060e2b34.0101.010c.04010101.0a000000' => { Name => 'PanScanInformation', Unknown => 1 }, + # '060e2b34.0101.010c.04010604.00000000' => { Name => 'VC-1PictureEssenceDescriptors', Type => 'Node' }, + '060e2b34.0101.010c.04010604.01000000' => { Name => 'VC-1InitializationMetadata', Type => 'DataStream', Unknown => 1 }, + '060e2b34.0101.010c.04010604.02000000' => { Name => 'VC-1SingleSequence', Type => 'Boolean' }, + '060e2b34.0101.010c.04010604.03000000' => { Name => 'VC-1CodedContentType', Format => 'int8u' }, + '060e2b34.0101.010c.04010604.04000000' => { Name => 'VC-1IdenticalGOP', Type => 'Boolean' }, + '060e2b34.0101.010c.04010604.05000000' => { Name => 'VC-1MaximumGOP', Format => 'int16u' }, + '060e2b34.0101.010c.04010604.06000000' => { Name => 'VC-1BPictureCount', Format => 'int16u' }, + '060e2b34.0101.010c.04010604.07000000' => { Name => 'VC-1AverageBitrate', Format => 'int32u', PrintConv => 'ConvertBitrate($val)' }, + '060e2b34.0101.010c.04010604.08000000' => { Name => 'VC-1MaximumBitrate', Format => 'int32u', PrintConv => 'ConvertBitrate($val)' }, + '060e2b34.0101.010c.04010604.09000000' => { Name => 'VC-1Profile', Format => 'int8u' }, + '060e2b34.0101.010c.04010604.0a000000' => { Name => 'VC-1Level', Format => 'int8u' }, + '060e2b34.0101.010c.04020501.07000000' => { Name => 'LinkedTimecodeTrackID', Type => 'UInt32Array', Unknown => 1 }, + '060e2b34.0101.010c.04020501.08000000' => { Name => 'SMPTE337MDataStreamNumber', Format => 'int8u' }, + '060e2b34.0101.010c.04060803.00000000' => { Name => 'ApplicationScheme', Type => 'UL', Unknown => 1 }, + '060e2b34.0101.010c.04060804.00000000' => { Name => 'DescriptiveMetadataScheme', Type => 'UL', Unknown => 1 }, + '060e2b34.0101.010c.04090500.00000000' => { Name => 'UCSEncoding', Type => 'UTF-16' }, + '060e2b34.0101.010c.05200701.0b000000' => { Name => 'LinkedApplicationPlug-InInstanceID', Type => 'WeakReference', Unknown => 1 }, + '060e2b34.0101.010c.05200701.0c000000' => { Name => 'LinkedDescriptiveFrameworkPlug-InID', Type => 'WeakReference', Unknown => 1 }, + '060e2b34.0101.010c.05200701.0d000000' => { Name => 'ApplicationPlug-InInstanceID', Type => 'UUID', Unknown => 1 }, + '060e2b34.0101.010c.05200701.0e000000' => { Name => 'DescriptiveMetadataPlug-InID', Type => 'UUID', Unknown => 1 }, + '060e2b34.0101.010c.05200701.0f000000' => { Name => 'ApplicationEnvironmentID', Type => 'UTF-16' }, + '060e2b34.0101.010c.05200701.10000000' => { Name => 'DescriptiveMetadataApplicationEnvironmentID', Type => 'UTF-16' }, + '060e2b34.0101.010c.05200701.11000000' => { Name => 'LinkedDescriptiveObjectPlug-InID', Type => 'WeakReference', Unknown => 1 }, + '060e2b34.0101.010c.06010103.0e000000' => { Name => 'TimebaseReferenceTrackID', Format => 'int32u' }, + '060e2b34.0101.010c.06010104.010b0000' => { Name => 'ObjectClassDefinition', Type => 'AUID', Unknown => 1 }, + '060e2b34.0101.010c.06010104.020e0000' => { Name => 'ApplicationPlug-InBatch', Type => 'StrongReference', Unknown => 1 }, + '060e2b34.0101.010c.06010104.020f0000' => { Name => 'PackageMarker', Type => 'StrongReference', Unknown => 1 }, + '060e2b34.0101.010c.06010104.02100000' => { Name => 'PackageTimelineMarkerRef', Type => 'StrongReference', Unknown => 1 }, + '060e2b34.0101.010c.06010104.02110000' => { Name => 'RegisterAdministrationObject', Type => 'StrongReference', Unknown => 1 }, + '060e2b34.0101.010c.06010104.02120000' => { Name => 'RegisterEntryAdministrationObject', Type => 'StrongReference', Unknown => 1 }, + '060e2b34.0101.010c.06010104.03060000' => { Name => 'GenericPayloads', Type => 'WeakReferenceBatch', Unknown => 1 }, + '060e2b34.0101.010c.06010104.06110000' => { Name => 'RegisterEntryArray', Type => 'StrongReferenceArray', Unknown => 1 }, + '060e2b34.0101.010c.06010104.06120000' => { Name => 'RegisterAdministrationArray', Type => 'StrongReferenceArray', Unknown => 1 }, + '060e2b34.0101.010c.06010104.06130000' => { Name => 'ApplicationInformationArray', Type => 'StrongReferenceArray', Unknown => 1 }, + '060e2b34.0101.010c.06010104.06140000' => { Name => 'RegisterChildEntryArray', Type => 'StrongReferenceArray', Unknown => 1 }, + '060e2b34.0101.010c.07020101.01060000' => { Name => 'RegisterReleaseDateTime', %timestamp }, + '060e2b34.0101.010c.07020101.01070000' => { Name => 'RegisterItemStatusChangeDateTime', %timestamp }, + # '060e2b34.0101.010c.0d090000.00000000' => { Name => 'ASC', Type => 'Node' }, + # '060e2b34.0101.010c.0d0a0000.00000000' => { Name => 'AES', Type => 'Node' }, + # '060e2b34.0101.010c.0d0b0000.00000000' => { Name => 'DutchGuild', Type => 'Node' }, + # '060e2b34.0101.010c.0e130000.00000000' => { Name => 'NLTechnologyLLC', Type => 'Node' }, + # '060e2b34.0101.010c.0e140000.00000000' => { Name => 'HarrisCorporation', Type => 'Node' }, + + # data types (not used as tag ID's, right?) + # '060e2b34.0104.0101.01010100.00000000' => { Name => 'UInt8' }, + # '060e2b34.0104.0101.01010200.00000000' => { Name => 'UInt16' }, + # '060e2b34.0104.0101.01010300.00000000' => { Name => 'UInt32' }, + # '060e2b34.0104.0101.01010400.00000000' => { Name => 'UInt64' }, + # '060e2b34.0104.0101.01010500.00000000' => { Name => 'Int8' }, + # '060e2b34.0104.0101.01010600.00000000' => { Name => 'Int16' }, + # '060e2b34.0104.0101.01010700.00000000' => { Name => 'Int32' }, + # '060e2b34.0104.0101.01010800.00000000' => { Name => 'Int64' }, + # '060e2b34.0104.0101.01012001.00000000' => { Name => 'Position' }, + # '060e2b34.0104.0101.01012002.00000000' => { Name => 'LengthType' }, + # '060e2b34.0104.0101.01030100.00000000' => { Name => 'AUID' }, + # '060e2b34.0104.0101.01030200.00000000' => { Name => 'PackageID' }, + # '060e2b34.0104.0101.01040100.00000000' => { Name => 'Boolean' }, + # '060e2b34.0104.0101.01100100.00000000' => { Name => 'UTF16' }, + # '060e2b34.0104.0101.01100200.00000000' => { Name => 'UTF16String' }, + # '060e2b34.0104.0101.01100300.00000000' => { Name => 'ISO7' }, + # '060e2b34.0104.0101.01100400.00000000' => { Name => 'ISO7String' }, + # '060e2b34.0104.0101.01200500.00000000' => { Name => 'UTF7String' }, + # '060e2b34.0104.0101.01300100.00000000' => { Name => 'UMID' }, + # '060e2b34.0104.0101.0201010e.00000000' => { Name => 'RGBACode' }, + # '060e2b34.0104.0101.02010125.00000000' => { Name => 'ChannelStatusModeType' }, + # '060e2b34.0104.0101.03010100.00000000' => { Name => 'Rational' }, + # '060e2b34.0104.0101.03010101.00000000' => { Name => 'Numerator' }, + # '060e2b34.0104.0101.03010102.00000000' => { Name => 'Denominator' }, + # '060e2b34.0104.0101.03010200.00000000' => { Name => 'ProductVersionType' }, + # '060e2b34.0104.0101.03010201.00000000' => { Name => 'Major' }, + # '060e2b34.0104.0101.03010202.00000000' => { Name => 'Minor' }, + # '060e2b34.0104.0101.03010203.00000000' => { Name => 'Patch' }, + # '060e2b34.0104.0101.03010204.00000000' => { Name => 'Build' }, + # '060e2b34.0104.0101.03010205.00000000' => { Name => 'Release' }, + # '060e2b34.0104.0101.03010300.00000000' => { Name => 'VersionType' }, + # '060e2b34.0104.0101.03010400.00000000' => { Name => 'RGBALayoutItem' }, + # '060e2b34.0104.0101.03010501.00000000' => { Name => 'Year' }, + # '060e2b34.0104.0101.03010502.00000000' => { Name => 'Month' }, + # '060e2b34.0104.0101.03010503.00000000' => { Name => 'Day' }, + # '060e2b34.0104.0101.03010601.00000000' => { Name => 'Hours' }, + # '060e2b34.0104.0101.03010602.00000000' => { Name => 'Minutes' }, + # '060e2b34.0104.0101.03010603.00000000' => { Name => 'Seconds' }, + # '060e2b34.0104.0101.03010604.00000000' => { Name => 'msBy4' }, + # '060e2b34.0104.0101.03010700.00000000' => { Name => 'Timestamp' }, + # '060e2b34.0104.0101.04010100.00000000' => { Name => 'UInt8Array' }, + # '060e2b34.0104.0101.04010300.00000000' => { Name => 'Int32Array' }, + # '060e2b34.0104.0101.04010400.00000000' => { Name => 'Int64Array' }, + # '060e2b34.0104.0101.04010600.00000000' => { Name => 'AUIDArray' }, + # '060e2b34.0104.0101.04020100.00000000' => { Name => 'RGBALayout' }, + # '060e2b34.0104.0101.04020200.00000000' => { Name => 'RationalArray' }, + # '060e2b34.0104.0101.04030200.00000000' => { Name => 'UInt32Batch' }, + # '060e2b34.0104.0101.04100100.00000000' => { Name => 'DataValue' }, + # '060e2b34.0104.0101.04100200.00000000' => { Name => 'Stream' }, + # '060e2b34.0104.0101.04100300.00000000' => { Name => 'Indirect' }, + # '060e2b34.0104.0101.04100400.00000000' => { Name => 'Opaque' }, + # '060e2b34.0104.0101.05010000.00000000' => { Name => 'WeakRef' }, + # '060e2b34.0104.0101.05020000.00000000' => { Name => 'StrongRef' }, + # '060e2b34.0104.0101.05021400.00000000' => { Name => 'StrongReferenceTrack' }, + # '060e2b34.0104.0101.05060500.00000000' => { Name => 'StrongReferenceVectorTrack' }, + # '060e2b34.0204.0107.0d010301.027e0100' => { Name => 'EncryptedTriplet' }, + + '060e2b34.0205.0101.0d010201.01020100' => { Name => 'OpenHeader', %header }, + '060e2b34.0205.0101.0d010201.01020200' => { Name => 'ClosedHeader', %header }, + '060e2b34.0205.0101.0d010201.01020300' => { Name => 'OpenCompleteHeader', %header }, + '060e2b34.0205.0101.0d010201.01020400' => { Name => 'ClosedCompleteHeader', %header }, + '060e2b34.0205.0101.0d010201.01030100' => { Name => 'OpenBodyPartition', Unknown => 1 }, + '060e2b34.0205.0101.0d010201.01030200' => { Name => 'ClosedBodyPartition', Unknown => 1 }, + '060e2b34.0205.0101.0d010201.01030300' => { Name => 'OpenCompleteBodyPartition', Unknown => 1 }, + '060e2b34.0205.0101.0d010201.01030400' => { Name => 'ClosedCompleteBodyPartition', Unknown => 1 }, + '060e2b34.0205.0101.0d010201.01040200' => { Name => 'Footer', Unknown => 1 }, + '060e2b34.0205.0101.0d010201.01040400' => { Name => 'CompleteFooter', Unknown => 1 }, + + '060e2b34.0205.0101.0d010201.01050100' => { Name => 'Primer', SubDirectory => { TagTable => 'Image::ExifTool::MXF::Main', ProcessProc => \&ProcessPrimer } }, + + '060e2b34.0205.0101.0d010201.01110000' => { Name => 'RandomIndexMetadataV10', Type => 'FixedPack', Unknown => 1 }, + '060e2b34.0205.0101.0d010201.01110100' => { Name => 'RandomIndexMetadata', Type => 'FixedPack', Unknown => 1 }, + '060e2b34.0206.0101.0d010200.00000000' => { Name => 'PartitionMetadata', Type => 'FixedPack', Unknown => 1 }, + + '060e2b34.0253.0101.0d010101.01010200' => { Name => 'StructuralComponent', %localSet }, + '060e2b34.0253.0101.0d010101.01010f00' => { Name => 'SequenceSet', %localSet }, + # Note: SourceClip is actually a local set, but it isn't decoded because it has a Duration + # tag which gets confused with the other Duration tags (also, my technique of determining + # the corresponding EditRate doesn't seem to work for this Duration) + '060e2b34.0253.0101.0d010101.01011100' => { Name => 'SourceClip', Unknown => 1 }, + '060e2b34.0253.0101.0d010101.01011400' => { Name => 'TimecodeComponent', %localSet }, + '060e2b34.0253.0101.0d010101.01011800' => { Name => 'ContentStorageSet', %localSet }, + '060e2b34.0253.0101.0d010101.01012300' => { Name => 'EssenceContainerDataSet', %localSet }, + '060e2b34.0253.0101.0d010101.01012500' => { Name => 'FileDescriptor', %localSet }, + '060e2b34.0253.0101.0d010101.01012700' => { Name => 'GenericPictureEssenceDescriptor', %localSet }, + '060e2b34.0253.0101.0d010101.01012800' => { Name => 'CDCIEssenceDescriptor', %localSet }, + '060e2b34.0253.0101.0d010101.01012900' => { Name => 'RGBAEssenceDescriptor', %localSet }, + '060e2b34.0253.0101.0d010101.01012f00' => { Name => 'Preface', %localSet }, + '060e2b34.0253.0101.0d010101.01013000' => { Name => 'Identification', %localSet }, + '060e2b34.0253.0101.0d010101.01013200' => { Name => 'NetworkLocator', %localSet }, + '060e2b34.0253.0101.0d010101.01013300' => { Name => 'TextLocator', %localSet }, + '060e2b34.0253.0101.0d010101.01013400' => { Name => 'GenericPackage', %localSet }, + '060e2b34.0253.0101.0d010101.01013600' => { Name => 'MaterialPackage', %localSet }, + '060e2b34.0253.0101.0d010101.01013700' => { Name => 'SourcePackage', %localSet }, + '060e2b34.0253.0101.0d010101.01013800' => { Name => 'GenericTrack', %localSet }, + '060e2b34.0253.0101.0d010101.01013900' => { Name => 'EventTrack', %localSet }, + '060e2b34.0253.0101.0d010101.01013a00' => { Name => 'StaticTrack', %localSet }, + '060e2b34.0253.0101.0d010101.01013b00' => { Name => 'Track', %localSet }, + '060e2b34.0253.0101.0d010101.01014100' => { Name => 'DMSegment', %localSet }, + '060e2b34.0253.0101.0d010101.01014200' => { Name => 'GenericSoundEssenceDescriptor', %localSet }, + '060e2b34.0253.0101.0d010101.01014300' => { Name => 'GenericDataEssenceDescriptor', %localSet }, + '060e2b34.0253.0101.0d010101.01014400' => { Name => 'MultipleDescriptor', %localSet }, + '060e2b34.0253.0101.0d010101.01014500' => { Name => 'DMSourceClip', %localSet }, + '060e2b34.0253.0101.0d010101.01014700' => { Name => 'AES3PCMDescriptor', %localSet }, + '060e2b34.0253.0101.0d010101.01014800' => { Name => 'WaveAudioDescriptor', %localSet }, + '060e2b34.0253.0101.0d010101.01015100' => { Name => 'MPEG2VideoDescriptor', %localSet }, + '060e2b34.0253.0101.0d010101.01015a00' => { Name => 'JPEG2000PictureSubDescriptor', %localSet }, + '060e2b34.0253.0101.0d010101.01015b00' => { Name => 'VBIDataDescriptor', %localSet }, + # ignore the index table sets because they contain no useful metadata + '060e2b34.0253.0101.0d010201.01100000' => { Name => 'V10IndexTableSegment', Unknown => 1 }, + '060e2b34.0253.0101.0d010201.01100100' => { Name => 'IndexTableSegment', Unknown => 1 }, + '060e2b34.0253.0101.0d010400.00000000' => { Name => 'DMSet', %localSet }, + '060e2b34.0253.0101.0d010401.00000000' => { Name => 'DMFramework', %localSet }, + + # DMS1 local sets (ref 12) + '060e2b34.0253.0101.0d010401.01010100' => { Name => 'ProductionFramework', %localSet }, + '060e2b34.0253.0101.0d010401.01010200' => { Name => 'ClipFramework', %localSet }, + '060e2b34.0253.0101.0d010401.01010300' => { Name => 'SceneFramework', %localSet }, + '060e2b34.0253.0101.0d010401.01100100' => { Name => 'Titles', %localSet }, + '060e2b34.0253.0101.0d010401.01110100' => { Name => 'Identification', %localSet }, + '060e2b34.0253.0101.0d010401.01120100' => { Name => 'GroupRelationship', %localSet }, + '060e2b34.0253.0101.0d010401.01130100' => { Name => 'Branding', %localSet }, + '060e2b34.0253.0101.0d010401.01140100' => { Name => 'Event', %localSet }, + '060e2b34.0253.0101.0d010401.01140200' => { Name => 'Publication', %localSet }, + '060e2b34.0253.0101.0d010401.01150100' => { Name => 'Award', %localSet }, + '060e2b34.0253.0101.0d010401.01160100' => { Name => 'CaptionDescription', %localSet }, + '060e2b34.0253.0101.0d010401.01170100' => { Name => 'Annotation', %localSet }, + '060e2b34.0253.0101.0d010401.01170200' => { Name => 'SettingPeriod', %localSet }, + '060e2b34.0253.0101.0d010401.01170300' => { Name => 'Scripting', %localSet }, + '060e2b34.0253.0101.0d010401.01170400' => { Name => 'Classification', %localSet }, + '060e2b34.0253.0101.0d010401.01170500' => { Name => 'Shot', %localSet }, + '060e2b34.0253.0101.0d010401.01170600' => { Name => 'KeyPoint', %localSet }, + '060e2b34.0253.0101.0d010401.01170800' => { Name => 'CueWords', %localSet }, + '060e2b34.0253.0101.0d010401.01180100' => { Name => 'Participant', %localSet }, + '060e2b34.0253.0101.0d010401.01190100' => { Name => 'ContactsList', %localSet }, + '060e2b34.0253.0101.0d010401.011a0200' => { Name => 'Person', %localSet }, + '060e2b34.0253.0101.0d010401.011a0300' => { Name => 'Organisation', %localSet }, + '060e2b34.0253.0101.0d010401.011a0400' => { Name => 'Location', %localSet }, + '060e2b34.0253.0101.0d010401.011b0100' => { Name => 'Address', %localSet }, + '060e2b34.0253.0101.0d010401.011b0200' => { Name => 'Communications', %localSet }, + '060e2b34.0253.0101.0d010401.011c0100' => { Name => 'Contract', %localSet }, + '060e2b34.0253.0101.0d010401.011c0200' => { Name => 'Rights', %localSet }, + '060e2b34.0253.0101.0d010401.011d0100' => { Name => 'PictureFormat', %localSet }, + '060e2b34.0253.0101.0d010401.011e0100' => { Name => 'DeviceParameters', %localSet }, + '060e2b34.0253.0101.0d010401.011f0100' => { Name => 'NameValue', %localSet }, + '060e2b34.0253.0101.0d010401.01200100' => { Name => 'Processing', %localSet }, + '060e2b34.0253.0101.0d010401.01200200' => { Name => 'Projects', %localSet }, + + '060e2b34.0253.0101.0d010401.02010000' => { Name => 'CryptographicFramework', %localSet }, + '060e2b34.0253.0101.0d010401.02020000' => { Name => 'CryptographicContext', %localSet }, + + '060e2b34.0253.0101.7f000000.00000000' => { Name => 'DefaultObject', Unknown => 1 }, + '060e2b34.0401.0107.02090201.01000000' => { Name => 'CipherAlgorithmAES128CBC', Type => 'Label', Unknown => 1 }, + '060e2b34.0401.0107.02090202.01000000' => { Name => 'HMACAlgorithmSHA1128', Type => 'Label', Unknown => 1 }, + '060e2b34.0401.0107.0d010301.020b0100' => { Name => 'EncryptedContainerLabel', Type => 'Label', Unknown => 1 }, + '060e2b34.0401.0107.0d010401.02010100' => { Name => 'CryptographicFrameworkLabel', Type => 'Label', Unknown => 1 }, +); + +# header information +%Image::ExifTool::MXF::Header = ( + GROUPS => { 2 => 'Video' }, + PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData, + 0 => { + Name => 'MXFVersion', + Format => 'int16u[2]', + ValueConv => '$val =~ tr/ /./; $val', + }, + # 4 - int32u: KAGSize + # 8 - int64u: bytes from first header + # 16 - int64u: bytes from previous partition + 24 => { # bytes to footer from start of header + Name => 'FooterPosition', + Format => 'int64u', + RawConv => '$$self{MXFInfo}{FooterPos} = $val; undef', + }, + 32 => { # number of bytes in header, beginning at the start of the Primer + Name => 'HeaderSize', + Format => 'int64u', + # use this opportinity to also save our header type + RawConv => q{ + $$self{MXFInfo}{HeaderType} = $$self{DIR_NAME}; + $$self{MXFInfo}{HeaderSize} = $val; + return undef; # I don't think anyone would care about this + }, + }, + # ...plus more stuff we don't care about +); + +#------------------------------------------------------------------------------ +# Convert 16 bytes to UL format +# Inputs: 0) 16-byte value +# Returns: UL string +sub UL($) +{ + return join('.', unpack('H8H4H4H8H8', shift));; +} + +#------------------------------------------------------------------------------ +# Convert latitude and/or longitude in [d]ddmmss(N|S|E|W) format +# Inputs: 0) string value to convert +# Returns: numerical lat and/or long +sub ConvLatLon($) +{ + my $val = shift; + my (@convVal, $ne); + foreach $ne ('NS','EW') { + next unless $val =~ /(\d{2,3})(\d{2})(\d{2})([$ne])/; + push @convVal, $1 + ($2 + $3 / 60) / 60 * (($4 eq 'N' or $4 eq 'E') ? 1 : -1); + } + return join ' ', @convVal; +} + +#------------------------------------------------------------------------------ +# Read MXF-specific Format types +# Inputs: 0) ExifTool ref, 1) value, 2) MXF value type +# Returns: formatted value +# Note: All types recognized here should be defined in the %knownType lookup +sub ReadMXFValue($$$) +{ + my ($et, $val, $type) = @_; + my $len = length($val); + local $_; + + if ($type eq 'UTF-16') { + $val = $et->Decode($val, 'UCS2'); # (until we handle UTF-16 properly) + } elsif ($type eq 'ProductVersion') { + my @a = unpack('n*', $val); + push @a, 0 while @a < 5; + $a[4] = { 0 => 'unknown', 1 => 'released', 2 => 'debug', 3 => 'patched', + 4 => 'beta', 5 => 'private build' }->{$a[4]} || "unknown $a[4]"; + $val = join('.', @a[0..3]) . ' ' . $a[4]; + } elsif ($type eq 'VersionType') { + $val = join('.',unpack('C*',$val)); + } elsif ($type eq 'Timestamp') { + my @a = unpack('nC*',$val); + my @max = (3000,12,31,24,59,59,249); + foreach (@a) { + last unless @max and $_ <= $max[0]; + shift @max; + } + if (@max) { + $val = 'Invalid (0x' . unpack('H*',$val) . ')'; + } else { + $a[6] *= 4; + $val = sprintf('%.4d:%.2d:%.2d %.2d:%.2d:%.2d.%.3d', @a); + } + } elsif ($type eq 'Position' or $type eq 'Length') { + $val = Get64u(\$val, 0); + } elsif ($type eq 'Boolean') { + $val = $val eq "\0" ? 'False' : 'True'; + } elsif ($type =~ /^(Alt|Lat|Lon)$/ and $len == 4) { + # split into nibbles after swapping byte order (see reference 8b) + $val = unpack('H*', pack('N', unpack('V', $val))); + if ($type eq 'Alt') { + # drop satellite information and only support altitudes up to +/-99999 m + $val = "$val (from earth centre)" unless $val =~ s/^[abc]..// or $val =~ s/^[def]../-/; + } else { + $val =~ s/(...)/$1./; # insert decimal point after 3rd character + if ($type eq 'Lat') { + $val =~ s/^f/-/; # south with first digit = 0 + } else { + $val =~ s/^e/-/; # east with first digit = 0 + $val =~ s/^f/-1/; # east with first digit = 1 + } + } + } elsif ($type =~ /(Array|Batch)/ and $len > 16) { + my ($count, $size) = unpack('NN', $val); + # validate data length + $len == 8 + $count * $size or $et->WarnOnce("Bad array or batch size"); + my ($i, @a); + for ($i=0; $i<$count; ++$i) { + my $pos = 8 + $i * $size; + last if $pos + $size > $len; + push @a, substr($val, $pos, $size); + } + if ($type =~ /^StrongReference/) { + $_ = join('-', unpack('H8H4H4H4H12', $_)) foreach @a; + } elsif ($type eq 'BatchOfUL' or $type =~ /^WeakReference/) { + $_ = ReadMXFValue($et, $_, 'UL') foreach @a; + } + $val = \@a; + } elsif ($len == 32) { + # 32-byte types include UMID, PackageID + $val = join('.', unpack('H8H4H4H8', $val)) . ' ' . + join(' ', unpack('x12H2H6', $val)) . ' ' . + join('-', unpack('x16H8H4H4H4H12', $val)); + } elsif ($len == 16) { + # convert remaining 16-byte known types as GUID or UL + # - this covers all UID's, UL, Label, WeakReference, StrongReference + if ($type eq 'UL' or $type eq 'WeakReference') { + # reverse high/low word if a reversed GUID is stored in a UL type + # (see ref 8b, section 5.5.8) + # - a GUID will have high bit of byte 8 set (reversed, this is in byte 0) + return UL($val) unless unpack('C', $val) & 0x80; + $val = substr($val, 8) . substr($val, 0, 8); + } + $val = join('-', unpack('H8H4H4H4H12', $val)); # compact GUID format + } else { + # Note: a 64-byte extended UMID contains date/time, GPS coordinates, etc, + # which would could be decoded here (ref 8b, section 5)... + $val = unpack('H*', $val); + } + return $val; +} + +#------------------------------------------------------------------------------ +# Process MXF Primer (to build lookup for translating local tag ID's) +# Inputs: 0) ExifTool ref, 1) dirInfo ref, 2) tag table ref +# Returns: 1 on success +sub ProcessPrimer($$$) +{ + my ($et, $dirInfo, $tagTablePtr) = @_; + my $dataPt = $$dirInfo{DataPt}; + my $end = $$dirInfo{DirLen}; + return 0 unless $end > 8; + my $count = Get32u($dataPt, 0); + my $size = Get32u($dataPt, 4); + return 0 unless $size >= 18; + $et->VerboseDir('MXF Primer', $count); + my $verbose = $et->Options('Verbose'); + my $primer = $$et{MXFInfo}{Primer}; + my $pos = 8; + my $i; + for ($i=0; $i<$count; ++$i) { + last if $pos + $size > $end; + my $local = Get16u($dataPt, $pos); + my $global = UL(substr($$dataPt, $pos + 2, 16)); + $pos += $size; + # save this entry in the primer lookup table + $$primer{$local} = $global; + # print lookup details in verbose mode + next unless $verbose; + my $indx = $i . ')'; + $indx .= ' ' if length($indx) < 3; + $et->VPrint(0, sprintf(" | $indx 0x%.4x => '${global}'\n", $local)); + } + return 1; +} + +#------------------------------------------------------------------------------ +# Read tags from an MXF local set +# Inputs: 0) ExifTool ref, 1) dirInfo ref, 2) tag table ref +# Returns: 1 on success +sub ProcessLocalSet($$$) +{ + my ($et, $dirInfo, $tagTablePtr) = @_; + local $_; + my $dataPt = $$dirInfo{DataPt}; + my $dataPos = $$dirInfo{DataPos}; + my $end = $$dirInfo{DirLen}; + my $mxfInfo = $$et{MXFInfo}; + my $primer = $$mxfInfo{Primer}; + my (@strongRef, @groups, $instance, $editRate, $trackID, $langCode, $textLang); + + $et->VerboseDir('MXF LocalSet', undef, $end); + + # loop through all tags in this local set + my $pos = 0; + while ($pos + 4 < $end) { + my $loc = Get16u($dataPt, $pos); # get key (local tag ID) + my $len = Get16u($dataPt, $pos + 2); # get length + $pos += 4; + last if $pos + $len > $end; + my $tag = $$primer{$loc}; + my ($extra, $val, $type, $langInfo); + if ($tag and $$tagTablePtr{$tag}) { + $extra = sprintf(', Local 0x%.4x', $loc); + } else { + $tag = $loc; + # $et->WarnOnce('Missing local key for at least one tag'); + $extra = ', NOT IN PRIMER!'; + } + my $tagInfo = $$tagTablePtr{$tag}; + # handle our MXF-specific format types + if ($tagInfo) { + $type = $$tagInfo{Type}; + if ($type and $knownType{$type}) { + $val = ReadMXFValue($et, substr($$dataPt, $pos, $len), $type); + push @strongRef, (ref $val ? @$val : $val) if $type =~ /^StrongReference/; + # remember instance UID of this local set + if ($$tagInfo{Name} eq 'InstanceUID') { + $instance = $val; + # set language code for text + # (only works if InstanceUID comes before text) + $textLang = $$mxfInfo{$instance}{LangCode} if $$mxfInfo{$instance}; + } elsif ($type eq 'UTF-16' and $textLang) { + $langInfo = Image::ExifTool::GetLangInfo($tagInfo, $textLang); + } + } + } + # get tagInfo ref the standard way to handle Unknown tags + $tagInfo = $langInfo || $et->GetTagInfo($tagTablePtr, $tag); + # set Binary flag to extract all unknown-format tags as Binary data + if ($tagInfo and $$tagInfo{Unknown} and not defined $$tagInfo{Binary}) { + $$tagInfo{Binary} = not ($$tagInfo{Format} or ($type and $knownType{$type})); + } + my $key = $et->HandleTag($tagTablePtr, $tag, $val, + Extra => $extra, + TagInfo => $tagInfo, + DataPt => $dataPt, + DataPos => $dataPos, + Start => $pos, + Size => $len, + ProcessProc => \&ProcessLocalSet, + ); + $pos += $len; + next unless $key; + # save information to allow later fixup of durations and group1 names + # (necessary because we don't have all the information we need + # to do this on the fly when the file is parsed linearly) + push @groups, $$et{TAG_EXTRA}{$key}; + next unless $tagInfo; + my $name = $$tagInfo{Name}; + if ($$tagInfo{IsDuration}) { + $$mxfInfo{FixDuration}{$key} = 1; + } elsif ($$tagInfo{LanguageCode}) { + $langCode = $$et{VALUE}{$key}; + } elsif ($name eq 'EditRate') { + $editRate = $$et{VALUE}{$key}; + } elsif ($name =~ /TrackID$/) { + $trackID = $$et{VALUE}{$key}; + unless ($$mxfInfo{Group1}{$trackID}) { + # save lookup to convert TrackID to our group 1 name + $$mxfInfo{Group1}{$trackID} = 'Track' . ++$$mxfInfo{NumTracks}; + } + } + } + + # save object information now that we know the instance UID + if ($instance) { + my $objInfo = $$mxfInfo{$instance}; + if ($objInfo) { + push @{$$objInfo{StrongRef}}, @strongRef; + push @{$$objInfo{Groups}}, @groups; + } else { + $objInfo = $$mxfInfo{$instance} = { + StrongRef => \@strongRef, + Groups => \@groups, + }; + } + # save instance UID's in groups hash (used to remove duplicates later) + $$_{UID} = $instance foreach @groups; + $$objInfo{Name} = $$et{DIR_NAME}; + $$objInfo{TrackID} = $trackID if defined $trackID; + $$objInfo{EditRate} = $editRate if $editRate; + if ($langCode) { + $$objInfo{LangCode} = $langCode; + } else { + $langCode = $$objInfo{LangCode}; + } + if ($langCode) { + # pre-set language code in all children + my $ul; + foreach $ul (@{$$objInfo{StrongRef}}) { + my $obj = $$mxfInfo{$ul}; + $obj or $obj = $$mxfInfo{$ul} = { StrongRef => [], Groups => [], Name => 'XXX' }; + $$obj{LangCode} = $langCode; + } + } + # save instance UID's of Preface's + push @{$$mxfInfo{Preface}}, $instance if $$et{DIR_NAME} eq 'Preface'; + } + return 1; +} + +#------------------------------------------------------------------------------ +# Walk MXF tree to set group names +# Inputs: 0) MXF information hash ref, 1) object instance UID, +# 2) path information hash ref (only for group 5 names), 3) track ID number +# Notes: also generates lookup table for EditRate based on group 1 name +# and the instance UID of the SequenceSet with the preferred Duration value +sub SetGroups($$;$$) +{ + my ($mxfInfo, $instance, $pathInfo, $trackID) = @_; + my $objInfo = $$mxfInfo{$instance}; + return unless $objInfo and not $$objInfo{DidGroups}; + $$objInfo{DidGroups} = 1; # avoid reprocessing this object + $trackID = $$objInfo{TrackID} if defined $$objInfo{TrackID}; + my ($ul, $g1, $g5, $groups, $path, $nameCount, $setSource); + # generate group 1 name for different tracks + if (defined $trackID) { + $$objInfo{TrackID} = $trackID; + $g1 = $$mxfInfo{Group1}{$trackID}; + # build a lookup to determine edit rates based on group 1 name + my $editRate = $$objInfo{EditRate}; + $$mxfInfo{EditRate}{$g1} = $editRate if defined $editRate; + # save the TimeCodeComponent instance UID (for determining Duration later) + if ($$objInfo{Name} eq 'TimecodeComponent') { + my $inWhat = $$mxfInfo{InSource} ? 'Source' : 'Other'; + $$mxfInfo{BestDuration}{$inWhat} = $instance; + } + } + # set flag if we are in the SourcePackage (contains our preferred TimecodeComponent) + my $name = $$objInfo{Name}; + $setSource = $$mxfInfo{InSource} = 1 if $name eq 'SourcePackage'; + + # generate group 5 path names if requested + if ($pathInfo) { + $nameCount = $$pathInfo{NameCount} || { }; + $path = $$pathInfo{Path}; + $$nameCount{$name} = ($$nameCount{$name} || 0) + 1; + push @$path, $name . $$nameCount{$name}; + $g5 = join '-', @$path; + $$pathInfo{NameCount} = { }; # use new name count for child objects + } + foreach $groups (@{$$objInfo{Groups}}) { + $$groups{G1} = $g1 if $g1; + $$groups{G5} = $g5 if $g5; + } + # walk through remaining objects in tree + foreach $ul (@{$$objInfo{StrongRef}}) { + SetGroups($mxfInfo, $ul, $pathInfo, $trackID); + } + if ($pathInfo) { + pop @$path; + $$pathInfo{NameCount} = $nameCount; + } + delete $$mxfInfo{InSource} if $setSource; +} + +#------------------------------------------------------------------------------ +# Convert all duration values to seconds +# Inputs: 0) ExifTool object ref, 1) MXF information hash ref +sub ConvertDurations($$) +{ + my ($et, $mxfInfo) = @_; + my $valueHash = $$et{VALUE}; + my $infoHash = $$et{TAG_INFO}; + my $tagExtra = $$et{TAG_EXTRA}; + my $editHash = $$mxfInfo{EditRate}; + my ($tag, $key, $i); + foreach $tag (keys %{$$mxfInfo{FixDuration}}) { + # loop through all instances of this tag name + for ($i=0, $key=$tag; ; ++$i, $key="$tag ($i)") { + my $tagInfo = $$infoHash{$key} or last; + next unless $$tagInfo{IsDuration}; # test IsDuration flag to be sure + my $g1 = $$tagExtra{$key}{G1} or next; + my $editRate = $$editHash{$g1}; + $$valueHash{$key} /= $editRate if $editRate; + } + } +} + +#------------------------------------------------------------------------------ +# Read information in a MXF file +# Inputs: 0) ExifTool ref, 1) dirInfo ref +# Returns: 1 on success, 0 if this wasn't a valid MXF file +sub ProcessMXF($$) +{ + my ($et, $dirInfo) = @_; + my $raf = $$dirInfo{RAF}; + my $verbose = $et->Options('Verbose'); + my $unknown = $et->Options('Unknown'); + my ($buff, $preface, $n, $headerEnd, $footerPos); + + # read enough to allow skipping over run-in if it exists + $raf->Read($buff, 65547) or return 0; + $buff =~ /\x06\x0e\x2b\x34\x02\x05\x01\x01\x0d\x01\x02/g or return 0; + my $start = pos($buff) - 11; + + $et->SetFileType(); + SetByteOrder('MM'); + $raf->Seek($start, 0) or $et->Warn('Seek error'), return 1; + my $tagTablePtr = GetTagTable('Image::ExifTool::MXF::Main'); + + # determine header length and type + + # initialize MXF information lookups + my %mxfInfo = ( + Primer => { }, # convert local keys to global UL + Group1 => { }, # group 1 names base on TrackID + NumTracks => 0, # counts number of tracks in file + FixDuration => { }, # names of all Duration tags that need fixing + Preface => [ ], # instance UID's for all Preface objects + ); + $$et{MXFInfo} = \%mxfInfo; + + # set group 1 name for all tags (so we can overwrite with track number later) + $$et{SET_GROUP1} = 'MXF'; + + for (;;) { + my $pos = $raf->Tell(); + # did we just finish parsing the header partition? + if ($headerEnd and $pos >= $headerEnd) { + # all done if it was a closed and complete header + last if $mxfInfo{HeaderType} eq 'ClosedCompleteHeader' and not $verbose; + undef $headerEnd; # (only test this once) + # skip directly to footer if possible + if ($footerPos and $footerPos > $pos and (not $verbose or not $unknown)) { + $et->VPrint(0, "[Skipping to footer. Use Unknown option to parse body partitions]\n"); + $raf->Seek($footerPos, 0) or last; + $pos = $footerPos; + } + } + # read the next KLV Key and first byte of Value + $raf->Read($buff, 17) == 17 or last; + my $tag = substr($buff, 0, 16); # get KLV Key (global tag ID) + my $len = Get8u(\$buff, 16); # get KLV Length + my $n; + if ($len >= 0x80) { + $n = $len & 0x7f; + $raf->Read($buff, $n) == $n or last; + $len = 0; + foreach $b (unpack 'C*', $buff) { + $len = $len * 256 + $b; + } + } else { + $n = 0; + } + # convert tag ID to ASCII UL notation + my $ul = UL($tag); + my $tagInfo = $$tagTablePtr{$ul}; + if (not $tagInfo and $ul =~ /^060e2b34\.0253\.0101\.(0d|0f)/ and + ($1 eq '0d' or $verbose or $unknown)) + { + # generate some unknown set tags automatically + my $name = $1 eq '0d' ? 'UserOrganizationPublicUse' : 'Experimental'; + $tagInfo = { Name => $name, %localSet }; + AddTagToTable($tagTablePtr, $ul, $tagInfo); + } + my ($val, $dataPt); + if ($tagInfo and not $$tagInfo{Unknown} and $len < 10000000) { + # save information about header/footer positions for skipping over body partitions + if ($$tagInfo{Name} eq 'Primer' and $mxfInfo{HeaderSize}) { + # footer position relative to header start and only valid if non-zero + $footerPos = $start + $mxfInfo{FooterPos} if $mxfInfo{FooterPos}; + # header length is relative to start of Primer + $headerEnd = $pos + $mxfInfo{HeaderSize}; + } elsif ($$tagInfo{IsHeader}) { + # save position of header start to allow calculation of footer position + $start = $pos; + } + $raf->Read($buff, $len) == $len or last; # get KLV Value + $dataPt = \$buff; + my $type = $$tagInfo{Type}; + $val = ReadMXFValue($et, $buff, $type) if $type and $knownType{$type}; + } elsif (($tagInfo and (not $$tagInfo{Unknown} or $unknown)) or $verbose) { + if ($tagInfo) { + # set Binary flag to extract all unknown-format tags as Binary data + if ($$tagInfo{Unknown} and not defined $$tagInfo{Binary}) { + my $type = $$tagInfo{Type}; + $$tagInfo{Binary} = not ($$tagInfo{Format} or ($type and $knownType{$type})); + } + } else { + my $id = unpack 'H*', $tag; + $tagInfo = { + Name => "MXF_$id", + Description => "MXF $id", + }; + # note: don't add unknown tags to table because we don't + # want them to be extracted with the Unknown option + } + # read the first 64kB max + my $n = $len < 65536 ? $len : 65536; + $raf->Read($val, $n) == $n or last; + $dataPt = \$val; + my $more = $len - $n; + $raf->Seek($more, 1) or last if $more; + } else { + $raf->Seek($len, 1) or last; # skip this value + next; + } + $et->HandleTag($tagTablePtr, $ul, $val, + TagInfo => $tagInfo, + DataPt => $dataPt, + DataPos => $pos + 17 + $n, + Size => $len, + ProcessProc => \&ProcessLocalSet, + ); + } + # walk entire MXF object tree to fix family 1 group names + my ($pathInfo, $tag, %did, %bestDur); + $pathInfo = { Path => [ 'MXF' ] } if $et->Options('SavePath'); + foreach $preface (@{$mxfInfo{Preface}}) { + SetGroups(\%mxfInfo, $preface, $pathInfo); + } + # convert Duration values to seconds based on the appropriate EditRate + ConvertDurations($et, \%mxfInfo); + + # remove tags to keep only the one from the most recent instance of the object + my $tagExtra = $$et{TAG_EXTRA}; + my $fileOrder = $$et{FILE_ORDER}; + # also determine our best Duration value + if ($mxfInfo{BestDuration}) { + my $instance = $mxfInfo{BestDuration}{Source} || $mxfInfo{BestDuration}{Other}; + $instance and $bestDur{"Duration $instance"} = 1; + } + # process tags in reverse order to preserve the last found of each identical tag + foreach $tag (sort { $$fileOrder{$b} <=> $$fileOrder{$a} } keys %$tagExtra) { + my $instance = $$tagExtra{$tag}{UID} or next; + delete $$tagExtra{$tag}{UID}; # (no longer needed) + $tag =~ /^(\S+)/; # get tag name without index number + my $utag = "$1 $instance"; # instance-specific tag name + if ($did{$utag}) { + Image::ExifTool::DeleteTag($et, $tag); # delete the duplicate + } else { + $did{$utag} = 1; + if ($bestDur{$utag}) { + # save best duration value + my $val = $$et{VALUE}{$tag}; + $et->HandleTag($tagTablePtr, '060e2b34.0101.0102.07020201.01030000', $val); + } + } + } + + # clean up and return + delete $$et{SET_GROUP1}; + delete $$et{MXFInfo}; + return 1; +} + +1; # end + +__END__ + +=head1 NAME + +Image::ExifTool::MXF - Read MXF meta information + +=head1 SYNOPSIS + +This module is used by Image::ExifTool + +=head1 DESCRIPTION + +This module contains definitions required by Image::ExifTool to read meta +information from MXF (Material Exchange Format) files. + +=head1 AUTHOR + +Copyright 2003-2019, Phil Harvey (phil at owl.phy.queensu.ca) + +This library is free software; you can redistribute it and/or modify it +under the same terms as Perl itself. + +=head1 REFERENCES + +=over 4 + +=item L<http://sourceforge.net/projects/mxflib/> + +=item L<http://www.aafassociation.org/downloads/whitepapers/MXFPhysicalview.pdf> + +=item L<http://archive.nlm.nih.gov/pubs/pearson/MJ2_Metadata2005.pdf> + +=item L<http://www.aafassociation.org/downloads/specifications/AMWA-AS-03-Delivery-Spec-1_0.pdf> + +=item L<http://paul-sampson.ca/private/s385m.pdf> + +=item L<http://avwiki.nl/documents/eg41.pdf> + +=item L<http://avwiki.nl/documents/eg42.pdf> + +=item L<http://www.amwa.tv/downloads/specifications/aafobjectspec-v1.1.pdf> + +=item L<http://www.smpte-ra.org/mdd/RP210v12-publication-20100623.xls> + +=item L<http://rhea.tele.ucl.ac.be:8081/Plone/Members/egoray/thesaurus-dictionnaire-metadata/> + +=item L<http://www.mog-solutions.com/img_upload/PDF/XML%20Schema%20for%20MXF%20Metadata.pdf> + +=item L<http://www.freemxf.org/freemxf_board/viewtopic.php?p=545&sid=00a5c17e07d828c1e93ecdbaed3076f7> + +=back + +=head1 SEE ALSO + +L<Image::ExifTool::TagNames/MXF Tags>, +L<Image::ExifTool(3pm)|Image::ExifTool> + +=cut + diff --git a/lib/Image/ExifTool/MacOS.pm b/lib/Image/ExifTool/MacOS.pm new file mode 100644 index 0000000..55fed5b --- /dev/null +++ b/lib/Image/ExifTool/MacOS.pm @@ -0,0 +1,568 @@ +#------------------------------------------------------------------------------ +# File: MacOS.pm +# +# Description: Read/write MacOS system tags +# +# Revisions: 2017/03/01 - P. Harvey Created +#------------------------------------------------------------------------------ + +package Image::ExifTool::MacOS; +use strict; +use vars qw($VERSION); +use Image::ExifTool qw(:DataAccess :Utils); + +$VERSION = '1.07'; + +sub MDItemLocalTime($); + +my %mdDateInfo = ( + ValueConv => \&MDItemLocalTime, + PrintConv => '$self->ConvertDateTime($val)', +); + +# "mdls" tags (ref PH) +%Image::ExifTool::MacOS::MDItem = ( + WRITE_PROC => \&Image::ExifTool::DummyWriteProc, + VARS => { NO_ID => 1 }, + GROUPS => { 0 => 'File', 1 => 'MacOS', 2 => 'Other' }, + NOTES => q{ + MDItem tags are extracted using the "mdls" utility. They are extracted if + any "MDItem*" tag or the MacOS group is specifically requested, or by + setting the L<MDItemTags API option|../ExifTool.html#MDItemTags> to 1 or the L<RequestAll API option|../ExifTool.html#RequestAll> to 2 or + higher. Note that these tags do not necessarily reflect the current + metadata of a file -- it may take some time for the MacOS mdworker daemon to + index the file after the metadata changes. + }, + MDItemFinderComment => { + Writable => 1, + WritePseudo => 1, + Protected => 1, # (all writable pseudo tags must be protected) + }, + MDItemFSLabel => { + Writable => 1, + WritePseudo => 1, + Protected => 1, # (all writable pseudo tags must be protected) + Notes => 'label number: 0-7', + WriteCheck => '$val =~ /^[0-7]$/ ? undef : "Not an integer in the range 0-7"', + }, + MDItemFSCreationDate => { + Writable => 1, + WritePseudo => 1, + DelCheck => q{"Can't delete"}, + Protected => 1, # (all writable pseudo tags must be protected) + Shift => 'Time', # (but not supported yet) + Notes => q{ + file creation date. Requires "setfile" for writing. Note that when + reading, it may take a few seconds after writing a file before this value + reflects the change. However, L<FileCreateDate|Extra.html> is updated immediately + }, + Groups => { 2 => 'Time' }, + ValueConv => \&MDItemLocalTime, + ValueConvInv => '$val', + PrintConv => '$self->ConvertDateTime($val)', + PrintConvInv => '$self->InverseDateTime($val)', + }, + MDItemAcquisitionMake => { Groups => { 2 => 'Camera' } }, + MDItemAcquisitionModel => { Groups => { 2 => 'Camera' } }, + MDItemAltitude => { Groups => { 2 => 'Location' } }, + MDItemAperture => { Groups => { 2 => 'Camera' } }, + MDItemAuthors => { Groups => { 2 => 'Author' } }, + MDItemBitsPerSample => { Groups => { 2 => 'Image' } }, + MDItemCity => { Groups => { 2 => 'Location' } }, + MDItemColorSpace => { Groups => { 2 => 'Image' } }, + MDItemComment => { }, + MDItemContentCreationDate => { Groups => { 2 => 'Time' }, %mdDateInfo }, + MDItemContentModificationDate => { Groups => { 2 => 'Time' }, %mdDateInfo }, + MDItemContentType => { }, + MDItemContentTypeTree => { }, + MDItemContributors => { }, + MDItemCopyright => { Groups => { 2 => 'Author' } }, + MDItemCountry => { Groups => { 2 => 'Location' } }, + MDItemCreator => { Groups => { 2 => 'Document' } }, + MDItemDateAdded => { Groups => { 2 => 'Time' }, %mdDateInfo }, + MDItemDescription => { }, + MDItemDisplayName => { }, + MDItemDownloadedDate => { Groups => { 2 => 'Time' }, %mdDateInfo }, + MDItemEncodingApplications => { }, + MDItemEXIFGPSVersion => { Groups => { 2 => 'Location' } }, + MDItemEXIFVersion => { }, + MDItemExposureMode => { Groups => { 2 => 'Camera' } }, + MDItemExposureProgram => { Groups => { 2 => 'Camera' } }, + MDItemExposureTimeSeconds => { Groups => { 2 => 'Camera' } }, + MDItemFlashOnOff => { Groups => { 2 => 'Camera' } }, + MDItemFNumber => { Groups => { 2 => 'Camera' } }, + MDItemFocalLength => { Groups => { 2 => 'Camera' } }, + MDItemFSContentChangeDate => { Groups => { 2 => 'Time' }, %mdDateInfo }, + MDItemFSCreatorCode => { Groups => { 2 => 'Author' } }, + MDItemFSFinderFlags => { }, + MDItemFSHasCustomIcon => { }, + MDItemFSInvisible => { }, + MDItemFSIsExtensionHidden => { }, + MDItemFSIsStationery => { }, + MDItemFSName => { }, + MDItemFSNodeCount => { }, + MDItemFSOwnerGroupID => { }, + MDItemFSOwnerUserID => { }, + MDItemFSSize => { }, + MDItemFSTypeCode => { }, + MDItemGPSDateStamp => { Groups => { 2 => 'Time' } }, + MDItemGPSStatus => { Groups => { 2 => 'Location' } }, + MDItemGPSTrack => { Groups => { 2 => 'Location' } }, + MDItemHasAlphaChannel => { Groups => { 2 => 'Image' } }, + MDItemImageDirection => { Groups => { 2 => 'Location' } }, + MDItemISOSpeed => { Groups => { 2 => 'Camera' } }, + MDItemKeywords => { }, + MDItemKind => { }, + MDItemLastUsedDate => { Groups => { 2 => 'Time' }, %mdDateInfo }, + MDItemLatitude => { Groups => { 2 => 'Location' } }, + MDItemLogicalSize => { }, + MDItemLongitude => { Groups => { 2 => 'Location' } }, + MDItemNumberOfPages => { }, + MDItemOrientation => { Groups => { 2 => 'Image' } }, + MDItemOriginApplicationIdentifier => { }, + MDItemOriginMessageID => { }, + MDItemOriginSenderDisplayName => { }, + MDItemOriginSenderHandle => { }, + MDItemOriginSubject => { }, + MDItemPageHeight => { Groups => { 2 => 'Image' } }, + MDItemPageWidth => { Groups => { 2 => 'Image' } }, + MDItemPhysicalSize => { Groups => { 2 => 'Image' } }, + MDItemPixelCount => { Groups => { 2 => 'Image' } }, + MDItemPixelHeight => { Groups => { 2 => 'Image' } }, + MDItemPixelWidth => { Groups => { 2 => 'Image' } }, + MDItemProfileName => { Groups => { 2 => 'Image' } }, + MDItemRedEyeOnOff => { Groups => { 2 => 'Camera' } }, + MDItemResolutionHeightDPI => { Groups => { 2 => 'Image' } }, + MDItemResolutionWidthDPI => { Groups => { 2 => 'Image' } }, + MDItemSecurityMethod => { }, + MDItemSpeed => { Groups => { 2 => 'Location' } }, + MDItemStateOrProvince => { Groups => { 2 => 'Location' } }, + MDItemTimestamp => { Groups => { 2 => 'Time' } }, # (time only) + MDItemTitle => { }, + MDItemUseCount => { }, + MDItemUsedDates => { Groups => { 2 => 'Time' }, %mdDateInfo }, + MDItemUserTags => { + List => 1, + Writable => 1, + WritePseudo => 1, + Protected => 1, # (all writable pseudo tags must be protected) + Notes => q{ + requires "tag" utility for writing -- install with "brew install tag". Note + that user tags may not contain a comma, and that duplicate user tags will + not be written + }, + }, + MDItemVersion => { }, + MDItemWhereFroms => { }, + MDItemWhiteBalance => { Groups => { 2 => 'Image' } }, + # tags used by Apple Mail on .emlx files + com_apple_mail_dateReceived => { Name => 'AppleMailDateReceived', Groups => { 2 => 'Time' }, %mdDateInfo }, + com_apple_mail_flagged => { Name => 'AppleMailFlagged' }, + com_apple_mail_messageID => { Name => 'AppleMailMessageID' }, + com_apple_mail_priority => { Name => 'AppleMailPriority' }, + com_apple_mail_read => { Name => 'AppleMailRead' }, + com_apple_mail_repliedTo => { Name => 'AppleMailRepliedTo' }, + MDItemAccountHandles => { }, + MDItemAccountIdentifier => { }, + MDItemAuthorEmailAddresses => { }, + MDItemBundleIdentifier => { }, + MDItemContentCreationDate_Ranking=>{Groups=> { 2 => 'Time' }, %mdDateInfo }, + MDItemDateAdded_Ranking => { Groups => { 2 => 'Time' }, %mdDateInfo }, + MDItemEmailConversationID => { }, + MDItemIdentifier => { }, + MDItemInterestingDate_Ranking => { Groups => { 2 => 'Time' }, %mdDateInfo }, + MDItemIsApplicationManaged => { }, + MDItemIsExistingThread => { }, + MDItemIsLikelyJunk => { }, + MDItemMailboxes => { }, + MDItemMailDateReceived_Ranking=> { Groups => { 2 => 'Time' }, %mdDateInfo }, + MDItemPrimaryRecipientEmailAddresses => { }, + MDItemRecipients => { }, + MDItemSubject => { }, +); + +# "xattr" tags +%Image::ExifTool::MacOS::XAttr = ( + WRITE_PROC => \&Image::ExifTool::DummyWriteProc, + GROUPS => { 0 => 'File', 1 => 'MacOS', 2 => 'Other' }, + VARS => { NO_ID => 1 }, # (id's are too long) + NOTES => q{ + XAttr tags are extracted using the "xattr" utility. They are extracted if + any "XAttr*" tag or the MacOS group is specifically requested, or by setting + the L<XAttrTags API option|../ExifTool.html#XAttrTags> to 1 or the L<RequestAll API option|../ExifTool.html#RequestAll> to 2 or higher. + }, + 'com.apple.FinderInfo' => { + Name => 'XAttrFinderInfo', + ConvertBinary => 1, + # ref https://opensource.apple.com/source/CarbonHeaders/CarbonHeaders-9A581/Finder.h + ValueConv => q{ + my @a = unpack('a4a4n3x10nx2N', $$val); + tr/\0//d, $_="'${_}'" foreach @a[0,1]; + return "@a"; + }, + PrintConv => q{ + $val =~ s/^('.*?') ('.*?') //s or return $val; + my ($type, $creator) = ($1, $2); + my ($flags, $y, $x, $exFlags, $putAway) = split ' ', $val; + my $label = ($flags >> 1) & 0x07; + my $flags = DecodeBits((($exFlags<<16) | $flags) & 0xfff1, { + 0 => 'OnDesk', + 6 => 'Shared', + 7 => 'HasNoInits', + 8 => 'Inited', + 10 => 'CustomIcon', + 11 => 'Stationery', + 12 => 'NameLocked', + 13 => 'HasBundle', + 14 => 'Invisible', + 15 => 'Alias', + # extended flags + 22 => 'HasRoutingInfo', + 23 => 'ObjectBusy', + 24 => 'CustomBadge', + 31 => 'ExtendedFlagsValid', + }); + my $str = "Type=$type Creator=$creator Flags=$flags Label=$label Pos=($x,$y)"; + $str .= " Putaway=$putAway" if $putAway; + return $str; + }, + }, + 'com.apple.quarantine' => { + Name => 'XAttrQuarantine', + Writable => 1, + WritePseudo => 1, + WriteCheck => '"May only delete this tag"', + Protected => 1, + Notes => q{ + quarantine information for files downloaded from the internet. May only be + deleted when writing + }, + # ($a[1] is the time when the quarantine tag was set) + PrintConv => q{ + my @a = split /;/, $val; + $a[0] = 'Flags=' . $a[0]; + $a[1] = 'set at ' . ConvertUnixTime(hex $a[1]); + $a[2] = 'by ' . $a[2]; + return join ' ', @a; + }, + PrintConvInv => '$val', + }, + 'com.apple.metadata:kMDItemDownloadedDate' => { + Name => 'XAttrMDItemDownloadedDate', + Groups => { 2 => 'Time' }, + }, + 'com.apple.metadata:kMDItemFinderComment' => { Name => 'XAttrMDItemFinderComment' }, + 'com.apple.metadata:kMDItemWhereFroms' => { Name => 'XAttrMDItemWhereFroms' }, + 'com.apple.metadata:kMDLabel' => { Name => 'XAttrMDLabel', Binary => 1 }, + 'com.apple.ResourceFork' => { Name => 'XAttrResourceFork', Binary => 1 }, +); + +#------------------------------------------------------------------------------ +# Convert OS MDItem time string to standard EXIF-formatted local time +# Inputs: 0) time string (eg. "2017-02-21 17:21:43 +0000") +# Returns: EXIF-formatted local time string with timezone +sub MDItemLocalTime($) +{ + my $val = shift; + $val =~ tr/-/:/; + $val =~ s/ ?([-+]\d{2}):?(\d{2})/$1:$2/; + # convert from UTC to local time + if ($val =~ /\+00:00$/) { + my $time = Image::ExifTool::GetUnixTime($val); + $val = Image::ExifTool::ConvertUnixTime($time, 1) if $time; + } + return $val; +} + +#------------------------------------------------------------------------------ +# Set MacOS MDItem and XAttr tags from new tag values +# Inputs: 0) Exiftool ref, 1) file name, 2) list of tags to set +# Returns: 1=something was set OK, 0=didn't try, -1=error (and warning set) +# Notes: There may be errors even if 1 is returned +sub SetMacOSTags($$$) +{ + my ($et, $file, $setTags) = @_; + my $result = 0; + my $tag; + + foreach $tag (@$setTags) { + my ($nvHash, $f, $v, $attr, $cmd, $err, $silentErr); + my $val = $et->GetNewValue($tag, \$nvHash); + next unless $nvHash; + my $overwrite = $et->IsOverwriting($nvHash); + unless ($$nvHash{TagInfo}{List}) { + next unless $overwrite; + if ($overwrite < 0) { + my $operation = $$nvHash{Shift} ? 'Shifting' : 'Conditional replacement'; + $et->Warn("$operation of $tag not yet supported"); + next; + } + } + if ($tag eq 'MDItemFSCreationDate' or $tag eq 'FileCreateDate') { + ($f = $file) =~ s/'/'\\''/g; + # convert to local time if value has a time zone + if ($val =~ /[-+Z]/) { + my $time = Image::ExifTool::GetUnixTime($val, 1); + $val = Image::ExifTool::ConvertUnixTime($time, 1) if $time; + } + $val =~ s{(\d{4}):(\d{2}):(\d{2})}{$2/$3/$1}; # reformat for setfile + $cmd = "setfile -d '${val}' '${f}'"; + } elsif ($tag eq 'MDItemUserTags') { + # (tested with "tag" version 0.9.0) + ($f = $file) =~ s/'/'\\''/g; + my @vals = $et->GetNewValue($nvHash); + if ($overwrite < 0 and @{$$nvHash{DelValue}}) { + # delete specified tags + my @dels = @{$$nvHash{DelValue}}; + s/'/'\\''/g foreach @dels; + my $del = join ',', @dels; + $err = system "tag -r '${del}' '${f}'>/dev/null 2>&1"; + unless ($err) { + $et->VerboseValue("- $tag", $del); + $result = 1; + undef $err if @vals; # more to do if there are tags to add + } + } + unless (defined $err) { + # add new tags, or overwrite or delete existing tags + s/'/'\\''/g foreach @vals; + my $opt = $overwrite > 0 ? '-s' : '-a'; + $val = @vals ? join(',', @vals) : ''; + $cmd = "tag $opt '${val}' '${f}'"; + $et->VPrint(1," - $tag = (all)\n") if $overwrite > 0; + undef $val if $val eq ''; + } + } elsif ($tag eq 'XAttrQuarantine') { + ($f = $file) =~ s/'/'\\''/g; + $cmd = "xattr -d com.apple.quarantine '${f}'"; + $silentErr = 256; # (will get this error if attribute doesn't exist) + } else { + ($f = $file) =~ s/(["\\])/\\$1/g; # escape necessary characters for script + $f =~ s/'/'"'"'/g; + if ($tag eq 'MDItemFinderComment') { + # (write finder comment using osascript instead of xattr + # because it is more work to construct the necessary bplist) + $val = '' unless defined $val; # set to empty string instead of deleting + $v = $et->Encode($val, 'UTF8'); + $v =~ s/(["\\])/\\$1/g; + $v =~ s/'/'"'"'/g; + $attr = 'comment'; + } else { # $tag eq 'MDItemFSLabel' + $v = $val ? 8 - $val : 0; # convert from label to label index (0 for no label) + $attr = 'label index'; + } + $cmd = qq(osascript -e 'set fp to POSIX file "$f" as alias' -e \\ + 'tell application "Finder" to set $attr of file fp to "$v"'); + } + if (defined $cmd) { + $err = system $cmd . '>/dev/null 2>&1'; # (pipe all output to /dev/null) + } + if (not $err) { + $et->VerboseValue("+ $tag", $val) if defined $val; + $result = 1; + } elsif (not $silentErr or $err != $silentErr) { + $cmd =~ s/ .*//s; + $et->Warn(qq{Error $err running "$cmd" to set $tag}); + $result = -1 unless $result; + } + } + return $result; +} + +#------------------------------------------------------------------------------ +# Extract MacOS metadata item tags +# Inputs: 0) ExifTool object ref, 1) file name +sub ExtractMDItemTags($$) +{ + local $_; + my ($et, $file) = @_; + my ($fn, $tag, $val, $tmp); + + ($fn = $file) =~ s/([`"\$\\])/\\$1/g; # escape necessary characters + $et->VPrint(0, '(running mdls)'); + my @mdls = `mdls "$fn" 2> /dev/null`; # get MacOS metadata + if ($? or not @mdls) { + $et->Warn('Error running "mdls" to extract MDItem tags'); + return; + } + my $tagTablePtr = GetTagTable('Image::ExifTool::MacOS::MDItem'); + $$et{INDENT} .= '| '; + $et->VerboseDir('MDItem'); + foreach (@mdls) { + chomp; + if (ref $val ne 'ARRAY') { + s/^k?(\w+)\s*= // or next; + $tag = $1; + $_ eq '(' and $val = [ ], next; # (start of a list) + $_ = '' if $_ eq '(null)'; + s/^"// and s/"$//; # remove quotes if they exist + $val = $_; + } elsif ($_ eq ')') { # (end of a list) + $_ = $$val[0]; + next unless defined $_; + } else { + # add item to list + s/^ //; # remove leading spaces + s/,$//; # remove trailing comma + $_ = '' if $_ eq '(null)'; + s/^"// and s/"$//; # remove quotes if they exist + s/\\"/"/g; # un-escape quotes + $_ = $et->Decode($_, 'UTF8'); + push @$val, $_; + next; + } + # add to Extra tags if not done already + unless ($$tagTablePtr{$tag}) { + # check for a date/time format + my %tagInfo; + %tagInfo = ( + Groups => { 2 => 'Time' }, + ValueConv => \&MDItemLocalTime, + PrintConv => '$self->ConvertDateTime($val)', + ) if /^\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}/; + # change tags like "com_apple_mail_xxx" to "AppleMailXxx" + ($tmp = $tag) =~ s/^com_//; # remove leading "com_" + $tmp =~ s/_([a-z])/\u$1/g; # use CamelCase + $tagInfo{Name} = Image::ExifTool::MakeTagName($tmp); + $tagInfo{List} = 1 if ref $val eq 'ARRAY'; + $tagInfo{Groups}{2} = 'Audio' if $tag =~ /Audio/; + $tagInfo{Groups}{2} = 'Author' if $tag =~ /(Copyright|Author)/; + $et->VPrint(0, " [adding $tag]\n"); + AddTagToTable($tagTablePtr, $tag, \%tagInfo); + } + $val = $et->Decode($val, 'UTF8') unless ref $val; + $et->HandleTag($tagTablePtr, $tag, $val); + undef $val; + } + $$et{INDENT} =~ s/\| $//; +} + +#------------------------------------------------------------------------------ +# Extract MacOS extended attribute tags +# Inputs: 0) ExifTool object ref, 1) file name +sub ExtractXAttrTags($$) +{ + local $_; + my ($et, $file) = @_; + my ($fn, $tag, $val, $warn); + + ($fn = $file) =~ s/([`"\$\\])/\\$1/g; # escape necessary characters + $et->VPrint(0, '(running xattr)'); + my @xattr = `xattr -lx "$fn" 2> /dev/null`; # get MacOS extended attributes + if ($? or not @xattr) { + $? and $et->Warn('Error running "xattr" to extract XAttr tags'); + return; + } + my $tagTablePtr = GetTagTable('Image::ExifTool::MacOS::XAttr'); + $$et{INDENT} .= '| '; + $et->VerboseDir('XAttr'); + push @xattr, ''; # (for a list terminator) + foreach (@xattr) { + chomp; + if (s/^[\dA-Fa-f]{8}//) { + $tag or $warn = 1, next; + s/\|.*//; + tr/ //d; + (/[^\dA-Fa-f]/ or length($_) & 1) and $warn = 2, next; + $val = '' unless defined $val; + $val .= pack('H*', $_); + next; + } elsif ($tag and defined $val) { + # add to our table if necessary + unless ($$tagTablePtr{$tag}) { + my $name; + # generate tag name from attribute name + if ($tag =~ /^com\.apple\.(.*)$/) { + ($name = $1) =~ s/^metadata:_?k//; + } else { + ($name = $tag) =~ s/[.:]([a-z])/\U$1/g; + } + $name = 'XAttr' . ucfirst $name; + my %tagInfo = ( Name => $name ); + $tagInfo{Groups} = { 2 => 'Time' } if $tag=~/Date$/; + $et->VPrint(0, " [adding $tag]\n"); + AddTagToTable($tagTablePtr, $tag, \%tagInfo); + } + if ($val =~ /^bplist0/) { + my %dirInfo = ( DataPt => \$val ); + require Image::ExifTool::PLIST; + if (Image::ExifTool::PLIST::ProcessBinaryPLIST($et, \%dirInfo, $tagTablePtr)) { + next if ref $dirInfo{Value} eq 'HASH'; + $val = $dirInfo{Value} + } else { + $et->Warn("Error decoding $$tagTablePtr{$tag}{Name}"); + next; + } + } + if (not ref $val and ($val =~ /\0/ or length($val) > 200) or $tag eq 'XAttrMDLabel') { + my $buff = $val; + $val = \$buff; + } + $et->HandleTag($tagTablePtr, $tag, $val); + undef $tag; + undef $val; + } + next unless length; + s/:$// or $warn = 3, next; # attribute name must have trailing ":" + defined $val and $warn = 4, undef $val; + # remove random ID after kMDLabel in tag ID + ($tag = $_) =~ s/^com.apple.metadata:kMDLabel_.*/com.apple.metadata:kMDLabel/s; + } + $warn and $et->Warn(qq{Error $warn parsing "xattr" output}); + $$et{INDENT} =~ s/\| $//; +} + +#------------------------------------------------------------------------------ +# Extract MacOS file creation date/time +# Inputs: 0) ExifTool object ref, 1) file name +sub GetFileCreateDate($$) +{ + local $_; + my ($et, $file) = @_; + my ($fn, $tag, $val, $tmp); + + ($fn = $file) =~ s/([`"\$\\])/\\$1/g; # escape necessary characters + $et->VPrint(0, '(running stat)'); + my $time = `stat -f '%SB' -t '%Y:%m:%d %H:%M:%S%z' "$fn" 2> /dev/null`; + if ($? or not $time or $time !~ s/([-+]\d{2})(\d{2})\s*$/$1:$2/) { + $et->Warn('Error running "stat" to extract FileCreateDate'); + return; + } + $$et{SET_GROUP1} = 'MacOS'; + $et->FoundTag(FileCreateDate => $time); + delete $$et{SET_GROUP1}; +} + +1; # end + +__END__ + +=head1 NAME + +Image::ExifTool::MacOS - Read/write MacOS system tags + +=head1 SYNOPSIS + +This module is used by Image::ExifTool + +=head1 DESCRIPTION + +This module contains definitions required by Image::ExifTool to extract +MDItem* and XAttr* tags on MacOS systems using the "mdls" and "xattr" +utilities respectively. Writable tags use "xattr", "setfile" or "osascript" +for writing. + +=head1 AUTHOR + +Copyright 2003-2019, Phil Harvey (phil at owl.phy.queensu.ca) + +This library is free software; you can redistribute it and/or modify it +under the same terms as Perl itself. + +=head1 SEE ALSO + +L<Image::ExifTool::TagNames/MacOS Tags>, +L<Image::ExifTool(3pm)|Image::ExifTool> + +=cut + diff --git a/lib/Image/ExifTool/MakerNotes.pm b/lib/Image/ExifTool/MakerNotes.pm new file mode 100644 index 0000000..92c61aa --- /dev/null +++ b/lib/Image/ExifTool/MakerNotes.pm @@ -0,0 +1,1818 @@ +#------------------------------------------------------------------------------ +# File: MakerNotes.pm +# +# Description: Read and write EXIF maker notes +# +# Revisions: 11/11/2004 - P. Harvey Created +#------------------------------------------------------------------------------ + +package Image::ExifTool::MakerNotes; + +use strict; +use vars qw($VERSION); +use Image::ExifTool qw(:DataAccess); +use Image::ExifTool::Exif; + +sub ProcessUnknown($$$); +sub ProcessUnknownOrPreview($$$); +sub ProcessCanon($$$); +sub ProcessGE2($$$); +sub ProcessKodakPatch($$$); +sub WriteUnknownOrPreview($$$); +sub FixLeicaBase($$;$); + +$VERSION = '2.08'; + +my $debug; # set to 1 to enable debugging code + +# conditional list of maker notes +# Notes: +# - This is NOT a normal tag table! +# - All byte orders are now specified because we can now +# write maker notes into a file with different byte ordering! +# - Put these in alphabetical order to make TagNames documentation nicer. +@Image::ExifTool::MakerNotes::Main = ( + # decide which MakerNotes to use (based on camera make/model) + { + Name => 'MakerNoteApple', + Condition => '$$valPt =~ /^Apple iOS\0/', + SubDirectory => { + TagTable => 'Image::ExifTool::Apple::Main', + Start => '$valuePtr + 14', + Base => '$start - 14', + ByteOrder => 'Unknown', + }, + }, + { + # this maker notes starts with a standard TIFF header at offset 0x0a + # (must check Nikon signature first because Nikon Capture NX can generate + # NEF images containing Nikon maker notes from JPEG images of any camera model) + Name => 'MakerNoteNikon', + Condition => '$$valPt=~/^Nikon\x00\x02/', + SubDirectory => { + TagTable => 'Image::ExifTool::Nikon::Main', + Start => '$valuePtr + 18', + Base => '$start - 8', + ByteOrder => 'Unknown', + }, + }, + { + Name => 'MakerNoteCanon', + # (starts with an IFD) + Condition => '$$self{Make} =~ /^Canon/', + SubDirectory => { + TagTable => 'Image::ExifTool::Canon::Main', + ProcessProc => \&ProcessCanon, + ByteOrder => 'Unknown', + }, + }, + { + Name => 'MakerNoteCasio', + # do negative lookahead assertion just to get tags + # in a nice order for documentation + # (starts with an IFD) + Condition => '$$self{Make}=~/^CASIO/ and $$valPt!~/^(QVC|DCI)\0/', + SubDirectory => { + TagTable => 'Image::ExifTool::Casio::Main', + ByteOrder => 'Unknown', + }, + }, + { + Name => 'MakerNoteCasio2', + # (starts with "QVC\0" [Casio] or "DCI\0" [Concord]) + # (also found in AVI and MOV videos) + Condition => '$$valPt =~ /^(QVC|DCI)\0/', + SubDirectory => { + TagTable => 'Image::ExifTool::Casio::Type2', + Start => '$valuePtr + 6', + ByteOrder => 'Unknown', + FixBase => 1, # necessary for AVI and MOV videos + }, + }, + { + Name => 'MakerNoteDJI', + Condition => '$$self{Make} eq "DJI" and $$valPt !~ /^...\@AMBA/s', + SubDirectory => { + TagTable => 'Image::ExifTool::DJI::Main', + Start => '$valuePtr', + ByteOrder => 'Unknown', + }, + }, + { + Name => 'MakerNoteFLIR', + # (starts with IFD, Make is 'FLIR Systems AB' or 'FLIR Systems') + Condition => '$$self{Make} =~ /^FLIR Systems/', + SubDirectory => { + TagTable => 'Image::ExifTool::FLIR::Main', + Start => '$valuePtr', + ByteOrder => 'Unknown', + }, + }, + { + # The Fuji maker notes use a structure similar to a self-contained + # TIFF file, but with "FUJIFILM" instead of the standard TIFF header + Name => 'MakerNoteFujiFilm', + # (starts with "FUJIFILM" -- also used by some Leica, Minolta and Sharp models) + # (GE FujiFilm models start with "GENERALE") + Condition => '$$valPt =~ /^(FUJIFILM|GENERALE)/', + SubDirectory => { + TagTable => 'Image::ExifTool::FujiFilm::Main', + # there is an 8-byte maker tag (FUJIFILM) we must skip over + OffsetPt => '$valuePtr+8', + # the pointers are relative to the subdirectory start + # (before adding the offsetPt) - PH + Base => '$start', + ByteOrder => 'LittleEndian', + }, + }, + { + Name => 'MakerNoteGE', + Condition => '$$valPt =~ /^GE(\0\0|NIC\0)/', + SubDirectory => { + TagTable => 'Image::ExifTool::GE::Main', + Start => '$valuePtr + 18', + FixBase => 1, + AutoFix => 1, + ByteOrder => 'Unknown', + }, + }, + { + Name => 'MakerNoteGE2', + Condition => '$$valPt =~ /^GE\x0c\0\0\0\x16\0\0\0/', + # Note: we will get a "Maker notes could not be parsed" warning when writing + # these maker notes because they aren't currently supported for writing + SubDirectory => { + TagTable => 'Image::ExifTool::FujiFilm::Main', + ProcessProc => \&ProcessGE2, + Start => '$valuePtr + 12', + Base => '$start - 6', + ByteOrder => 'LittleEndian', + # hard patch for crazy offsets + FixOffsets => '$valuePtr -= 210 if $tagID >= 0x1303', + }, + }, + { + Name => 'MakerNoteHasselblad', + Condition => '$$self{Make} eq "Hasselblad"', + SubDirectory => { + TagTable => 'Image::ExifTool::Unknown::Main', + ByteOrder => 'Unknown', + Start => '$valuePtr', + Base => 0, # (avoids warnings since maker notes are not self-contained) + }, + }, + # (the GE X5 has really messed up EXIF-like maker notes starting with + # "GENIC\x0c\0" --> currently not decoded) + { + Name => 'MakerNoteHP', # PhotoSmart 720 (also Vivitar 3705, 3705B and 3715) + Condition => '$$valPt =~ /^(Hewlett-Packard|Vivitar)/', + SubDirectory => { + TagTable => 'Image::ExifTool::HP::Main', + ProcessProc => \&ProcessUnknown, + ByteOrder => 'Unknown', + }, + }, + { + Name => 'MakerNoteHP2', # PhotoSmart E427 + # (this type of maker note also used by BenQ, Mustek, Sanyo, Traveler and Vivitar) + Condition => '$$valPt =~ /^610[\0-\4]/', + NotIFD => 1, + SubDirectory => { + TagTable => 'Image::ExifTool::HP::Type2', + Start => '$valuePtr', + ByteOrder => 'LittleEndian', + }, + }, + { + Name => 'MakerNoteHP4', # PhotoSmart M627 + Condition => '$$valPt =~ /^IIII\x04\0/', + NotIFD => 1, + SubDirectory => { + TagTable => 'Image::ExifTool::HP::Type4', + Start => '$valuePtr', + ByteOrder => 'LittleEndian', + }, + }, + { + Name => 'MakerNoteHP6', # PhotoSmart M425, M525 and M527 + Condition => '$$valPt =~ /^IIII\x06\0/', + NotIFD => 1, + SubDirectory => { + TagTable => 'Image::ExifTool::HP::Type6', + Start => '$valuePtr', + ByteOrder => 'LittleEndian', + }, + }, + { + Name => 'MakerNoteISL', # (used in Samsung GX20 samples) + Condition => '$$valPt =~ /^ISLMAKERNOTE000\0/', + # this maker notes starts with a TIFF-like header at offset 0x10 + SubDirectory => { + TagTable => 'Image::ExifTool::Unknown::Main', + Start => '$valuePtr + 24', + Base => '$start - 8', + ByteOrder => 'Unknown', + }, + }, + { + Name => 'MakerNoteJVC', + Condition => '$$valPt=~/^JVC /', + SubDirectory => { + TagTable => 'Image::ExifTool::JVC::Main', + Start => '$valuePtr + 4', + ByteOrder => 'Unknown', + }, + }, + { + Name => 'MakerNoteJVCText', + Condition => '$$self{Make}=~/^(JVC|Victor)/ and $$valPt=~/^VER:/', + NotIFD => 1, + SubDirectory => { + TagTable => 'Image::ExifTool::JVC::Text', + }, + }, + { + Name => 'MakerNoteKodak1a', + Condition => '$$self{Make}=~/^EASTMAN KODAK/ and $$valPt=~/^KDK INFO/', + NotIFD => 1, + SubDirectory => { + TagTable => 'Image::ExifTool::Kodak::Main', + Start => '$valuePtr + 8', + ByteOrder => 'BigEndian', + }, + }, + { + Name => 'MakerNoteKodak1b', + Condition => '$$self{Make}=~/^EASTMAN KODAK/ and $$valPt=~/^KDK/', + NotIFD => 1, + SubDirectory => { + TagTable => 'Image::ExifTool::Kodak::Main', + Start => '$valuePtr + 8', + ByteOrder => 'LittleEndian', + }, + }, + { + # used by various Kodak, HP, Pentax and Minolta models + Name => 'MakerNoteKodak2', + Condition => q{ + $$valPt =~ /^.{8}Eastman Kodak/s or + $$valPt =~ /^\x01\0[\0\x01]\0\0\0\x04\0[a-zA-Z]{4}/ + }, + NotIFD => 1, + SubDirectory => { + TagTable => 'Image::ExifTool::Kodak::Type2', + ByteOrder => 'BigEndian', + }, + }, + { + # not much to key on here, but we know the + # upper byte of the year should be 0x07: + Name => 'MakerNoteKodak3', + Condition => q{ + $$self{Make} =~ /^EASTMAN KODAK/ and + $$valPt =~ /^(?!MM|II).{12}\x07/s and + $$valPt !~ /^(MM|II|AOC)/ + }, + NotIFD => 1, + SubDirectory => { + TagTable => 'Image::ExifTool::Kodak::Type3', + ByteOrder => 'BigEndian', + }, + }, + { + Name => 'MakerNoteKodak4', + Condition => q{ + $$self{Make} =~ /^Eastman Kodak/ and + $$valPt =~ /^.{41}JPG/s and + $$valPt !~ /^(MM|II|AOC)/ + }, + NotIFD => 1, + SubDirectory => { + TagTable => 'Image::ExifTool::Kodak::Type4', + ByteOrder => 'BigEndian', + }, + }, + { + Name => 'MakerNoteKodak5', + Condition => q{ + $$self{Make}=~/^EASTMAN KODAK/ and + ($$self{Model}=~/CX(4200|4230|4300|4310|6200|6230)/ or + # try to pick up similar models we haven't tested yet + $$valPt=~/^\0(\x1a\x18|\x3a\x08|\x59\xf8|\x14\x80)\0/) + }, + NotIFD => 1, + SubDirectory => { + TagTable => 'Image::ExifTool::Kodak::Type5', + ByteOrder => 'BigEndian', + }, + }, + { + Name => 'MakerNoteKodak6a', + Condition => q{ + $$self{Make}=~/^EASTMAN KODAK/ and + $$self{Model}=~/DX3215/ + }, + NotIFD => 1, + SubDirectory => { + TagTable => 'Image::ExifTool::Kodak::Type6', + ByteOrder => 'BigEndian', + }, + }, + { + Name => 'MakerNoteKodak6b', + Condition => q{ + $$self{Make}=~/^EASTMAN KODAK/ and + $$self{Model}=~/DX3700/ + }, + NotIFD => 1, + SubDirectory => { + TagTable => 'Image::ExifTool::Kodak::Type6', + ByteOrder => 'LittleEndian', + }, + }, + { + Name => 'MakerNoteKodak7', + # look for something that looks like a serial number + # (confirmed serial numbers have the format KXXXX########, but we also + # accept other strings from sample images that may be serial numbers) + Condition => q{ + $$self{Make}=~/Kodak/i and + $$valPt =~ /^[CK][A-Z\d]{3} ?[A-Z\d]{1,2}\d{2}[A-Z\d]\d{4}[ \0]/ + }, + NotIFD => 1, + SubDirectory => { + TagTable => 'Image::ExifTool::Kodak::Type7', + ByteOrder => 'LittleEndian', + }, + }, + { + Name => 'MakerNoteKodak8a', + # IFD-format maker notes: look for reasonable number of + # entries and check format and count of first IFD entry + Condition => q{ + $$self{Make}=~/Kodak/i and + ($$valPt =~ /^\0[\x02-\x7f]..\0[\x01-\x0c]\0\0/s or + $$valPt =~ /^[\x02-\x7f]\0..[\x01-\x0c]\0..\0\0/s) + }, + SubDirectory => { + TagTable => 'Image::ExifTool::Kodak::Type8', + ProcessProc => \&ProcessUnknown, + ByteOrder => 'Unknown', + }, + }, + { + Name => 'MakerNoteKodak8b', + # these maker notes have an extra 2 bytes after the entry count + # (this is handled by the patch). Also, the IFD uses a Format 13, + # which is some 2-byte format (not Float, as decoded by ExifTool) + # - written by the PixPro AZ251, AZ361, AZ262, AZ521 + Condition => q{ + $$self{Make}=~/Kodak/i and + $$valPt =~ /^MM\0\x2a\0\0\0\x08\0.\0\0/ + }, + SubDirectory => { + TagTable => 'Image::ExifTool::Kodak::Type8', + ProcessProc => \&ProcessKodakPatch, + ByteOrder => 'BigEndian', + Start => '$valuePtr + 8', + Base => '$start - 8', + }, + }, + { + Name => 'MakerNoteKodak8c', + # TIFF-format maker notes + Condition => q{ + $$self{Make}=~/Kodak/i and + $$valPt =~ /^(MM\0\x2a\0\0\0\x08|II\x2a\0\x08\0\0\0)/ + }, + SubDirectory => { + TagTable => 'Image::ExifTool::Kodak::Type8', + ProcessProc => \&ProcessUnknown, + ByteOrder => 'Unknown', + Start => '$valuePtr + 8', + Base => '$start - 8', + }, + }, + { + Name => 'MakerNoteKodak9', + # test header and Kodak:DateTimeOriginal + Condition => '$$valPt =~ m{^IIII[\x02\x03]\0.{14}\d{4}/\d{2}/\d{2} }s', + NotIFD => 1, + SubDirectory => { + TagTable => 'Image::ExifTool::Kodak::Type9', + ByteOrder => 'LittleEndian', + }, + }, + { + Name => 'MakerNoteKodak10', + # yet another type of Kodak IFD-format maker notes: + # this type begins with a byte order indicator, + # followed immediately by the IFD + Condition => q{ + $$self{Make}=~/Kodak/i and + $$valPt =~ /^(MM\0[\x02-\x7f]|II[\x02-\x7f]\0)/ + }, + SubDirectory => { + TagTable => 'Image::ExifTool::Kodak::Type10', + ProcessProc => \&ProcessUnknown, + ByteOrder => 'Unknown', + Start => '$valuePtr + 2', + }, + }, + { + Name => 'MakerNoteKodak11', + # these maker notes have a 4-byte entry count + # - written by the PixPro S-1 (Note: Make is "JK Imaging, Ltd.", so check Model for "Kodak") + Condition => q{ + $$self{Model}=~/(Kodak|PixPro)/i and + $$valPt =~ /^II\x2a\0\x08\0\0\0.\0\0\0/s + }, + SubDirectory => { + TagTable => 'Image::ExifTool::Kodak::Type11', + ProcessProc => \&ProcessKodakPatch, + ByteOrder => 'LittleEndian', + Start => '$valuePtr + 8', + Base => '$start - 8', + }, + }, + { + Name => 'MakerNoteKodak12', + # these maker notes have a 4-byte entry count + # - written by the PixPro AZ901 (Note: Make is "JK Imaging, Ltd.", so check Model for "Kodak") + Condition => q{ + $$self{Model}=~/(Kodak|PixPro)/i and + $$valPt =~ /^MM\0\x2a\0\0\0\x08\0\0\0./s + }, + SubDirectory => { + TagTable => 'Image::ExifTool::Kodak::Type11', + ProcessProc => \&ProcessKodakPatch, + ByteOrder => 'BigEndian', + Start => '$valuePtr + 8', + Base => '$start - 8', + }, + }, + { + Name => 'MakerNoteKodakUnknown', + Condition => '$$self{Make}=~/Kodak/i and $$valPt!~/^AOC\0/', + NotIFD => 1, + SubDirectory => { + TagTable => 'Image::ExifTool::Kodak::Unknown', + ByteOrder => 'BigEndian', + }, + }, + { + Name => 'MakerNoteKyocera', + # (starts with "KYOCERA") + Condition => '$$valPt =~ /^KYOCERA/', + SubDirectory => { + TagTable => 'Image::ExifTool::Unknown::Main', + Start => '$valuePtr + 22', + Base => '$start + 2', + EntryBased => 1, + ByteOrder => 'Unknown', + }, + }, + { + Name => 'MakerNoteMinolta', + Condition => q{ + $$self{Make}=~/^(Konica Minolta|Minolta)/i and + $$valPt !~ /^(MINOL|CAMER|MLY0|KC|\+M\+M|\xd7)/ + }, + SubDirectory => { + TagTable => 'Image::ExifTool::Minolta::Main', + ByteOrder => 'Unknown', + }, + }, + { + # the DiMAGE E323 (MINOL) and E500 (CAMER), and some models + # of Mustek, Pentax, Ricoh and Vivitar (CAMER). + Name => 'MakerNoteMinolta2', + Condition => '$$valPt =~ /^(MINOL|CAMER)\0/ and $$self{OlympusCAMER} = 1', + SubDirectory => { + # these models use Olympus tags in the range 0x200-0x221 plus 0xf00 + TagTable => 'Image::ExifTool::Olympus::Main', + Start => '$valuePtr + 8', + ByteOrder => 'Unknown', + }, + }, + { + # /^MLY0/ - DiMAGE G400, G500, G530, G600 + # /^KC/ - Revio KD-420Z, DiMAGE E203 + # /^+M+M/ - DiMAGE E201 + # /^\xd7/ - DiMAGE RD3000 + Name => 'MakerNoteMinolta3', + Condition => '$$self{Make} =~ /^(Konica Minolta|Minolta)/i', + Binary => 1, + Notes => 'not EXIF-based', + }, + { + Name => 'MakerNoteMotorola', + Condition => '$$valPt=~/^MOT\0/', + SubDirectory => { + TagTable => 'Image::ExifTool::Motorola::Main', + Start => '$valuePtr + 8', + Base => '$start - 8', + ByteOrder => 'Unknown', + }, + }, + { + # older Nikon maker notes + Name => 'MakerNoteNikon2', + Condition => '$$valPt=~/^Nikon\x00\x01/', + SubDirectory => { + TagTable => 'Image::ExifTool::Nikon::Type2', + Start => '$valuePtr + 8', + ByteOrder => 'LittleEndian', + }, + }, + { + # headerless Nikon maker notes + Name => 'MakerNoteNikon3', + Condition => '$$self{Make}=~/^NIKON/i', + SubDirectory => { + TagTable => 'Image::ExifTool::Nikon::Main', + ByteOrder => 'Unknown', # most are little-endian, but D1 is big + }, + }, + { + Name => 'MakerNoteNintendo', + # (starts with an IFD) + Condition => '$$self{Make} eq "Nintendo"', + SubDirectory => { + TagTable => 'Image::ExifTool::Nintendo::Main', + ByteOrder => 'Unknown', + }, + }, + { + Name => 'MakerNoteOlympus', + # (if Make is 'SEIKO EPSON CORP.', starts with "EPSON\0") + # (if Make is 'OLYMPUS OPTICAL CO.,LTD' or 'OLYMPUS CORPORATION', + # starts with "OLYMP\0") + Condition => '$$valPt =~ /^(OLYMP|EPSON)\0/', + SubDirectory => { + TagTable => 'Image::ExifTool::Olympus::Main', + Start => '$valuePtr + 8', + ByteOrder => 'Unknown', + }, + }, + { + Name => 'MakerNoteOlympus2', + # new Olympus maker notes start with "OLYMPUS\0" + Condition => '$$valPt =~ /^OLYMPUS\0/', + SubDirectory => { + TagTable => 'Image::ExifTool::Olympus::Main', + Start => '$valuePtr + 12', + Base => '$start - 12', + ByteOrder => 'Unknown', + }, + }, + { + Name => 'MakerNoteLeica', + # (starts with "LEICA\0\0\0") + Condition => '$$self{Make} eq "LEICA"', + SubDirectory => { + # many Leica models use the same format as Panasonic + TagTable => 'Image::ExifTool::Panasonic::Main', + Start => '$valuePtr + 8', + ByteOrder => 'Unknown', + }, + }, + { + Name => 'MakerNoteLeica2', # used by the M8 + # (starts with "LEICA\0\0\0") + Condition => '$$self{Make} =~ /^Leica Camera AG/ and $$valPt =~ /^LEICA\0\0\0/', + SubDirectory => { + TagTable => 'Image::ExifTool::Panasonic::Leica2', + # (the offset base is different in JPEG and DNG images, but we + # can copy makernotes from one to the other, so we need special + # logic to decide which base to apply) + ProcessProc => \&FixLeicaBase, + Start => '$valuePtr + 8', + Base => '$start', # (- 8 for DNG images!) + ByteOrder => 'Unknown', + }, + }, + { + Name => 'MakerNoteLeica3', # used by the R8 and R9 + # (starts with IFD) + Condition => q{ + $$self{Make} =~ /^Leica Camera AG/ and $$valPt !~ /^LEICA/ and + $$self{Model} ne "S2" and $$self{Model} ne "LEICA M (Typ 240)" + }, + SubDirectory => { + TagTable => 'Image::ExifTool::Panasonic::Leica3', + Start => '$valuePtr', + ByteOrder => 'Unknown', + }, + }, + { + Name => 'MakerNoteLeica4', # used by the M9/M-Monochrom + # (M9 and M Monochrom start with "LEICA0\x03\0") + Condition => '$$self{Make} =~ /^Leica Camera AG/ and $$valPt =~ /^LEICA0/', + SubDirectory => { + TagTable => 'Image::ExifTool::Panasonic::Leica4', + Start => '$valuePtr + 8', + Base => '$start - 8', # (yay! Leica fixed the M8 problem) + ByteOrder => 'Unknown', + }, + }, + { + Name => 'MakerNoteLeica5', # used by the X1/X2/X VARIO/T/X-U + # (X1 starts with "LEICA\0\x01\0", Make is "LEICA CAMERA AG") + # (X2 starts with "LEICA\0\x05\0", Make is "LEICA CAMERA AG") + # (X VARIO starts with "LEICA\0\x04\0", Make is "LEICA CAMERA AG") + # (T (Typ 701) starts with "LEICA\0\0x6", Make is "LEICA CAMERA AG") + # (X (Typ 113) starts with "LEICA\0\0x7", Make is "LEICA CAMERA AG") + # (X-U (Typ 113) starts with "LEICA\0\x10\0", Make is "LEICA CAMERA AG") + Condition => '$$valPt =~ /^LEICA\0[\x01\x04\x05\x06\x07\x10\x1a]\0/', + SubDirectory => { + TagTable => 'Image::ExifTool::Panasonic::Leica5', + Start => '$valuePtr + 8', + Base => '$start - 8', + ByteOrder => 'Unknown', + }, + }, + { + Name => 'MakerNoteLeica6', # used by the S2, M (Typ 240) and S (Typ 006) + # (starts with "LEICA\0\x02\xff", Make is "Leica Camera AG", but test the + # model names separately because the maker notes data may not be loaded + # at the time this is tested if they are in a JPEG trailer. Also, this + # header is used by the M Monochrom (Type 246), with different offsets.) + Condition => q{ + ($$self{Make} eq 'Leica Camera AG' and ($$self{Model} eq 'S2' or + $$self{Model} eq 'LEICA M (Typ 240)' or $$self{Model} eq 'LEICA S (Typ 006)')) + }, + DataTag => 'LeicaTrailer', # (generates fixup name for this tag) + LeicaTrailer => 1, # flag to special-case this tag in the Exif code + SubDirectory => { + TagTable => 'Image::ExifTool::Panasonic::Leica6', + Start => '$valuePtr + 8', + ByteOrder => 'Unknown', + # NOTE: Leica uses absolute file offsets when this maker note is stored + # as a JPEG trailer -- this case is handled by ProcessLeicaTrailer in + # Panasonic.pm, and any "Base" defined here is ignored for this case. + # ExifTool may also create S2/M maker notes inside the APP1 segment when + # copying from other files, and for this the normal EXIF offsets are used, + # Base should not be defined! + }, + }, + { + Name => 'MakerNoteLeica7', # used by the M Monochrom (Typ 246) + # (starts with "LEICA\0\x02\xff", Make is "Leica Camera AG") + Condition => '$$valPt =~ /^LEICA\0\x02\xff/', + DataTag => 'LeicaTrailer', # (generates fixup name for this tag) + LeicaTrailer => 1, # flag to special-case this tag in the Exif code + SubDirectory => { + TagTable => 'Image::ExifTool::Panasonic::Leica6', + Start => '$valuePtr + 8', + ByteOrder => 'Unknown', + Base => '-$base', # uses absolute file offsets (not based on TIFF header offset) + }, + }, + { + Name => 'MakerNoteLeica8', # used by the Q (Type 116) + # (Q (Typ 116) starts with "LEICA\0\x08\0", Make is "LEICA CAMERA AG") + # (SL (Typ 601) and CL start with "LEICA\0\x09\0", Make is "LEICA CAMERA AG") + Condition => '$$valPt =~ /^LEICA\0[\x08\x09]\0/', + SubDirectory => { + TagTable => 'Image::ExifTool::Panasonic::Leica5', + Start => '$valuePtr + 8', + ByteOrder => 'Unknown', + }, + }, + { + Name => 'MakerNoteLeica9', # used by the M10/S + # (M10 and S start with "LEICA0\x02\0") + Condition => '$$self{Make} =~ /^Leica Camera AG/ and $$valPt =~ /^LEICA\0\x02\0/', + SubDirectory => { + TagTable => 'Image::ExifTool::Panasonic::Leica9', + Start => '$valuePtr + 8', + Base => '$start - 8', + ByteOrder => 'Unknown', + }, + }, + { + Name => 'MakerNoteLeica10', # used by the D-Lux7 + Condition => '$$valPt =~ /^LEICA CAMERA AG\0/', + SubDirectory => { + TagTable => 'Image::ExifTool::Panasonic::Main', + Start => '$valuePtr + 18', + ByteOrder => 'Unknown', + }, + }, + { + Name => 'MakerNotePanasonic', + # (starts with "Panasonic\0") + Condition => '$$valPt=~/^Panasonic/ and $$self{Model} ne "DC-FT7"', + SubDirectory => { + TagTable => 'Image::ExifTool::Panasonic::Main', + Start => '$valuePtr + 12', + ByteOrder => 'Unknown', + }, + }, + { + Name => 'MakerNotePanasonic2', + # (starts with "Panasonic\0") + Condition => '$$self{Make}=~/^Panasonic/ and $$valPt=~/^MKE/', + SubDirectory => { + TagTable => 'Image::ExifTool::Panasonic::Type2', + ByteOrder => 'LittleEndian', + }, + }, + { + Name => 'MakerNotePanasonic3', # (DC-FT7) + # (starts with "Panasonic\0") + Condition => '$$valPt=~/^Panasonic/', + SubDirectory => { + TagTable => 'Image::ExifTool::Panasonic::Main', + Start => '$valuePtr + 12', + Base => 12, # crazy! + ByteOrder => 'Unknown', + }, + }, + { + Name => 'MakerNotePentax', + # (starts with "AOC\0", but so does MakerNotePentax3) + # (also used by some Samsung models) + Condition => q{ + $$valPt=~/^AOC\0/ and + $$self{Model} !~ /^PENTAX Optio ?[34]30RS\s*$/ + }, + SubDirectory => { + TagTable => 'Image::ExifTool::Pentax::Main', + # process as Unknown maker notes because the start offset and + # byte ordering are so variable + ProcessProc => \&ProcessUnknown, + # offsets can be totally whacky for Pentax maker notes, + # so attempt to fix the offset base if possible + FixBase => 1, + ByteOrder => 'Unknown', + }, + }, + { + Name => 'MakerNotePentax2', + # (starts with an IFD) + # Casio-like maker notes used only by the Optio 330 and 430 + Condition => '$$self{Make}=~/^Asahi/ and $$valPt!~/^AOC\0/', + SubDirectory => { + TagTable => 'Image::ExifTool::Pentax::Type2', + ProcessProc => \&ProcessUnknown, + FixBase => 1, + ByteOrder => 'Unknown', + }, + }, + { + Name => 'MakerNotePentax3', + # (starts with "AOC\0", like the more common Pentax maker notes) + # Casio maker notes used only by the Optio 330RS and 430RS + Condition => '$$self{Make}=~/^Asahi/', + SubDirectory => { + TagTable => 'Image::ExifTool::Casio::Type2', + ProcessProc => \&ProcessUnknown, + FixBase => 1, + ByteOrder => 'Unknown', + }, + }, + { + Name => 'MakerNotePentax4', + # (starts with 3 or 4 digits) + # HP2-like text-based maker notes used by Optio E20 + Condition => '$$self{Make}=~/^PENTAX/ and $$valPt=~/^\d{3}/', + NotIFD => 1, + SubDirectory => { + TagTable => 'Image::ExifTool::Pentax::Type4', + Start => '$valuePtr', + ByteOrder => 'LittleEndian', + }, + }, + { + Name => 'MakerNotePentax5', + # (starts with "PENTAX \0") + # used by cameras such as the Q, Optio S1, RS1500 and WG-1 + Condition => '$$valPt=~/^PENTAX \0/', + SubDirectory => { + TagTable => 'Image::ExifTool::Pentax::Main', + Start => '$valuePtr + 10', + Base => '$start - 10', + ByteOrder => 'Unknown', + }, + }, + { + Name => 'MakerNotePentax6', + # (starts with "S1\0\0\0\0\0\0\x0c\0\0\0") + Condition => '$$valPt=~/^S1\0{6}\x0c\0{3}/', + SubDirectory => { + TagTable => 'Image::ExifTool::Pentax::S1', + Start => '$valuePtr + 12', + Base => '$start - 12', + ByteOrder => 'Unknown', + }, + }, + { + Name => 'MakerNotePhaseOne', + # Starts with: 'IIIITwaR' or 'IIIICwaR' (have seen both written by P25) + # (have also seen code which expects 'MMMMRawT') + Condition => q{ + return undef unless $$valPt =~ /^(IIII.waR|MMMMRaw.)/s; + $self->OverrideFileType($$self{TIFF_TYPE} = 'IIQ') if $count > 1000000; + return 1; + }, + NotIFD => 1, + IsPhaseOne => 1, # flag to rebuild these differently + SubDirectory => { TagTable => 'Image::ExifTool::PhaseOne::Main' }, + PutFirst => 1, # place immediately after TIFF header + }, + { + Name => 'MakerNoteReconyx', + Condition => q{ + $$valPt =~ /^\x01\xf1([\x02\x03]\x00)?/ and + ($1 or $$self{Make} eq "RECONYX") + }, + SubDirectory => { + TagTable => 'Image::ExifTool::Reconyx::Main', + ByteOrder => 'Little-endian', + }, + }, + { + Name => 'MakerNoteReconyx2', + Condition => '$$valPt =~ /^RECONYXUF\0/', + SubDirectory => { + TagTable => 'Image::ExifTool::Reconyx::Type2', + ByteOrder => 'Little-endian', + }, + }, + { + Name => 'MakerNoteReconyx3', + Condition => '$$valPt =~ /^RECONYXH2\0/', + SubDirectory => { + TagTable => 'Image::ExifTool::Reconyx::Type3', + ByteOrder => 'Little-endian', + }, + }, + { + Name => 'MakerNoteRicohPentax', + # used by cameras such as the Ricoh GR III + Condition => '$$valPt=~/^RICOH\0(II|MM)/', + SubDirectory => { + TagTable => 'Image::ExifTool::Pentax::Main', + Start => '$valuePtr + 8', + Base => '$start - 8', + ByteOrder => 'Unknown', + }, + }, + { + Name => 'MakerNoteRicoh', + # (my test R50 image starts with " \x02\x01" - PH) + Condition => q{ + $$self{Make} =~ /^(PENTAX )?RICOH/ and + $$valPt =~ /^(Ricoh| |MM\0\x2a|II\x2a\0)/i and + $$valPt !~ /^(MM\0\x2a\0\0\0\x08\0.\0\0|II\x2a\0\x08\0\0\0.\0\0\0)/s and + $$self{Model} ne 'RICOH WG-M1' + }, + SubDirectory => { + TagTable => 'Image::ExifTool::Ricoh::Main', + Start => '$valuePtr + 8', + ByteOrder => 'Unknown', + }, + }, + { + Name => 'MakerNoteRicoh2', + # (the Ricoh HZ15 starts with "MM\0\x2a" and the Pentax XG-1 starts with "II\x2a\0", + # but an extra 2 bytes of padding after the IFD entry count prevents these from + # being processed as a standard IFD. Note that the offsets for the HZ15 are all + # zeros, but they seem to be mostly OK for the XG-1) + Condition => q{ + $$self{Make} =~ /^(PENTAX )?RICOH/ and ($$self{Model} eq 'RICOH WG-M1' or + $$valPt =~ /^(MM\0\x2a\0\0\0\x08\0.\0\0|II\x2a\0\x08\0\0\0.\0\0\0)/s) + }, + SubDirectory => { + TagTable => 'Image::ExifTool::Ricoh::Type2', + Start => '$valuePtr + 8', + Base => '$start - 8', + ByteOrder => 'Unknown', + ProcessProc => \&ProcessKodakPatch, + }, + }, + { + Name => 'MakerNoteRicohText', + Condition => '$$self{Make}=~/^RICOH/', + NotIFD => 1, + SubDirectory => { + TagTable => 'Image::ExifTool::Ricoh::Text', + ByteOrder => 'Unknown', + }, + }, + { + Name => 'MakerNoteSamsung1a', + # Samsung STMN maker notes WITHOUT PreviewImage + Condition => '$$valPt =~ /^STMN\d{3}.\0{4}/s', + Binary => 1, + Notes => 'Samsung "STMN" maker notes without PreviewImage', + }, + { + Name => 'MakerNoteSamsung1b', + # Samsung STMN maker notes WITH PreviewImage + Condition => '$$valPt =~ /^STMN\d{3}/', + SubDirectory => { + TagTable => 'Image::ExifTool::Samsung::Main', + }, + }, + { + Name => 'MakerNoteSamsung2', + # Samsung EXIF-format maker notes ( + Condition => q{ + uc $$self{Make} eq 'SAMSUNG' and ($$self{TIFF_TYPE} eq 'SRW' or + $$valPt=~/^(\0.\0\x01\0\x07\0{3}\x04|.\0\x01\0\x07\0\x04\0{3})0100/s) + }, + SubDirectory => { + TagTable => 'Image::ExifTool::Samsung::Type2', + # Samsung is very inconsistent here, and uses absolute offsets for some + # models and relative offsets for others, so process as Unknown + ProcessProc => \&ProcessUnknown, + FixBase => 1, + ByteOrder => 'Unknown', + }, + }, + { + Name => 'MakerNoteSanyo', + # (starts with "SANYO\0") + Condition => '$$self{Make}=~/^SANYO/ and $$self{Model}!~/^(C4|J\d|S\d)\b/', + SubDirectory => { + TagTable => 'Image::ExifTool::Sanyo::Main', + Validate => '$val =~ /^SANYO/', + Start => '$valuePtr + 8', + ByteOrder => 'Unknown', + }, + }, + { + Name => 'MakerNoteSanyoC4', + # The C4 offsets are wrong by 12, so they must be fixed + Condition => '$$self{Make}=~/^SANYO/ and $$self{Model}=~/^C4\b/', + SubDirectory => { + TagTable => 'Image::ExifTool::Sanyo::Main', + Validate => '$val =~ /^SANYO/', + Start => '$valuePtr + 8', + FixBase => 1, + ByteOrder => 'Unknown', + }, + }, + { + Name => 'MakerNoteSanyoPatch', + # The J1, J2, J4, S1, S3 and S4 offsets are completely screwy + Condition => '$$self{Make}=~/^SANYO/', + SubDirectory => { + TagTable => 'Image::ExifTool::Sanyo::Main', + Validate => '$val =~ /^SANYO/', + Start => '$valuePtr + 8', + ByteOrder => 'Unknown', + FixOffsets => 'Image::ExifTool::Sanyo::FixOffsets($valuePtr, $valEnd, $size, $tagID, $wFlag)', + }, + }, + { + Name => 'MakerNoteSigma', + # (starts with "SIGMA\0") + Condition => '$$self{Make}=~/^(SIGMA|FOVEON)/', + SubDirectory => { + TagTable => 'Image::ExifTool::Sigma::Main', + Validate => '$val =~ /^(SIGMA|FOVEON)/', + Start => '$valuePtr + 10', + ByteOrder => 'Unknown', + }, + }, + { + Name => 'MakerNoteSony', + # (starts with "SONY DSC \0" or "SONY CAM \0") + # (TF1 starts with "\0\0SONY PIC\0") + # (Hasselblad models start with "VHAB \0") + Condition => '$$valPt=~/^(SONY (DSC|CAM|MOBILE)|\0\0SONY PIC\0|VHAB \0)/', + SubDirectory => { + TagTable => 'Image::ExifTool::Sony::Main', + Start => '$valuePtr + 12', + ByteOrder => 'Unknown', + }, + }, + { + Name => 'MakerNoteSony2', + # (starts with "SONY PI\0" -- DSC-S650/S700/S750) + Condition => '$$valPt=~/^SONY PI\0/ and $$self{OlympusCAMER}=1', + SubDirectory => { + TagTable => 'Image::ExifTool::Olympus::Main', + Start => '$valuePtr + 12', + ByteOrder => 'Unknown', + }, + }, + { + Name => 'MakerNoteSony3', + # (starts with "PREMI\0" -- DSC-S45/S500) + Condition => '$$valPt=~/^(PREMI)\0/ and $$self{OlympusCAMER}=1', + SubDirectory => { + TagTable => 'Image::ExifTool::Olympus::Main', + Start => '$valuePtr + 8', + ByteOrder => 'Unknown', + }, + }, + { + Name => 'MakerNoteSony4', + # (starts with "SONY PIC\0" -- DSC-H200/J20/W370/W510, MHS-TS20) + Condition => '$$valPt=~/^SONY PIC\0/', + SubDirectory => { TagTable => 'Image::ExifTool::Sony::PIC' }, + }, + { + Name => 'MakerNoteSony5', # used in SR2 and ARW images + Condition => '$$self{Make}=~/^SONY/ and $$valPt!~/^\x01\x00/', + Condition => q{ + ($$self{Make}=~/^SONY/ or ($$self{Make}=~/^HASSELBLAD/ and + $$self{Model}=~/^(HV|Stellar|Lusso|Lunar)/)) and $$valPt!~/^\x01\x00/ + }, + SubDirectory => { + TagTable => 'Image::ExifTool::Sony::Main', + Start => '$valuePtr', + ByteOrder => 'Unknown', + }, + }, + { + Name => 'MakerNoteSonyEricsson', + Condition => '$$valPt =~ /^SEMC MS\0/', + SubDirectory => { + TagTable => 'Image::ExifTool::Sony::Ericsson', + Start => '$valuePtr + 20', + Base => '$start - 8', + ByteOrder => 'Unknown', + }, + }, + { + Name => 'MakerNoteSonySRF', + Condition => '$$self{Make}=~/^SONY/', + SubDirectory => { + TagTable => 'Image::ExifTool::Sony::SRF', + Start => '$valuePtr', + ByteOrder => 'Unknown', + }, + }, + { + Name => 'MakerNoteUnknownText', + Condition => '$$valPt =~ /^[\x09\x0d\x0a\x20-\x7e]+\0*$/', + Notes => 'unknown text-based maker notes', + # show as binary if it is too long + ValueConv => 'length($val) > 64 ? \$val : $val', + ValueConvInv => '$val', + }, + { + Name => 'MakerNoteUnknownBinary', + # "LSI1\0" - SilverFast + Condition => '$$valPt =~ /^LSI1\0/', + Notes => 'unknown binary maker notes', + Binary => 1, + }, + { + Name => 'MakerNoteUnknown', + PossiblePreview => 1, + SubDirectory => { + TagTable => 'Image::ExifTool::Unknown::Main', + ProcessProc => \&ProcessUnknownOrPreview, + WriteProc => \&WriteUnknownOrPreview, + ByteOrder => 'Unknown', + FixBase => 2, + }, + }, +); + +# insert writable properties so we can write our maker notes +my $tagInfo; +foreach $tagInfo (@Image::ExifTool::MakerNotes::Main) { + $$tagInfo{Writable} = 'undef'; + $$tagInfo{Format} = 'undef', # (make sure we don't convert this when reading) + $$tagInfo{WriteGroup} = 'ExifIFD'; + $$tagInfo{Groups} = { 1 => 'MakerNotes' }; + next unless $$tagInfo{SubDirectory}; + # make all SubDirectory tags block-writable + $$tagInfo{Binary} = 1, + $$tagInfo{MakerNotes} = 1; +} + +#------------------------------------------------------------------------------ +# Get normal offset of value data from end of maker note IFD +# Inputs: 0) ExifTool object reference +# Returns: Array: 0) relative flag (undef for no change) +# 1) normal offset from end of IFD to first value (empty if unknown) +# 2-N) other possible offsets used by some models +# Notes: Directory size should be validated before calling this routine +sub GetMakerNoteOffset($) +{ + my $et = shift; + # figure out where we expect the value data based on camera type + my $make = $$et{Make}; + my $model = $$et{Model}; + my ($relative, @offsets); + + # normally value data starts 4 bytes after end of directory, so this is the default. + # offsets of 0 and 4 are always allowed even if not specified, + # but the first offset specified is the one used when writing + if ($make =~ /^Canon/) { + push @offsets, ($model =~ /\b(20D|350D|REBEL XT|Kiss Digital N)\b/) ? 6 : 4; + # some Canon models (FV-M30, Optura50, Optura60) leave 24 unused bytes + # at the end of the IFD (2 spare IFD entries?) + push @offsets, 28 if $model =~ /\b(FV\b|OPTURA)/; + # some Canon PowerShot models leave 12 unused bytes + push @offsets, 16 if $model =~ /(PowerShot|IXUS|IXY)/; + } elsif ($make =~ /^CASIO/) { + # Casio AVI and MOV images use no padding, and their JPEG's use 4, + # except some models like the EX-S770,Z65,Z70,Z75 and Z700 which use 16, + # and the EX-Z35 which uses 2 (grrrr...) + push @offsets, $$et{FILE_TYPE} =~ /^(RIFF|MOV)$/ ? 0 : (4, 16, 2); + } elsif ($make =~ /^(General Imaging Co.|GEDSC IMAGING CORP.)/i) { + push @offsets, 0; + } elsif ($make =~ /^KYOCERA/) { + push @offsets, 12; + } elsif ($make =~ /^Leica Camera AG/) { + if ($model eq 'S2') { + # lots of empty space before first value in S2 images + push @offsets, 4, ($$et{FILE_TYPE} eq 'JPEG' ? 286 : 274); + } elsif ($model eq 'LEICA M MONOCHROM (Typ 246)') { + push @offsets, 4, 130; + } elsif ($model eq 'LEICA M (Typ 240)') { + push @offsets, 4, 118; + } elsif ($model =~ /^(R8|R9|M8)\b/) { + push @offsets, 6; + } else { + push @offsets, 4; + } + } elsif ($make =~ /^OLYMPUS/ and $model =~ /^E-(1|300|330)\b/) { + push @offsets, 16; + } elsif ($make =~ /^OLYMPUS/ and + # these Olympus models are just weird + $model =~ /^(C2500L|C-1Z?|C-5000Z|X-2|C720UZ|C725UZ|C150|C2Z|E-10|E-20|FerrariMODEL2003|u20D|u10D)\b/) + { + # no expected offset --> determine offset empirically via FixBase() + } elsif ($make =~ /^(Panasonic|JVC)\b/) { + push @offsets, 0; + } elsif ($make =~ /^SONY/) { + # earlier DSLR and "PREMI" models use an offset of 4 + if ($model =~ /^(DSLR-.*|SLT-A(33|35|55V)|NEX-(3|5|C3|VG10E))$/ or + $$et{OlympusCAMER}) + { + push @offsets, 4; + } else { + push @offsets, 0; + } + } elsif ($$et{TIFF_TYPE} eq 'SRW' and $make eq 'SAMSUNG' and $model eq 'EK-GN120') { + push @offsets, 40; # patch to read most of the maker notes, but breaks PreviewIFD + } elsif ($make eq 'FUJIFILM') { + # some models have offset of 6, so allow that too (A345,A350,A360,A370) + push @offsets, 4, 6; + } elsif ($make =~ /^TOSHIBA/) { + # similar to Canon, can also have 24 bytes of padding + push @offsets, 0, 24; + } elsif ($make =~ /^PENTAX/) { + push @offsets, 4; + # the Pentax addressing mode is determined automatically, but + # sometimes the algorithm gets it wrong, but Pentax always uses + # absolute addressing, so force it to be absolute + $relative = 0; + } elsif ($make =~ /^Konica Minolta/i) { + # patch for DiMAGE X50, Xg, Z2 and Z10 + push @offsets, 4, -16; + } elsif ($make =~ /^Minolta/) { + # patch for DiMAGE 7, X20 and Z1 + push @offsets, 4, -8, -12; + } else { + push @offsets, 4; # the normal offset + } + return ($relative, @offsets); +} + +#------------------------------------------------------------------------------ +# Get hash of value offsets / block sizes +# Inputs: 0) Data pointer, 1) offset to start of directory, +# 2) hash ref to return value pointers based on tag ID +# Returns: 0) hash reference: keys are offsets, values are block sizes +# 1) same thing, but with keys adjusted for value-based offsets +# Notes: Directory size should be validated before calling this routine +# - calculates MIN and MAX offsets in entry-based hash +sub GetValueBlocks($$;$) +{ + my ($dataPt, $dirStart, $tagPtr) = @_; + my $numEntries = Get16u($dataPt, $dirStart); + my ($index, $valPtr, %valBlock, %valBlkAdj, $end); + for ($index=0; $index<$numEntries; ++$index) { + my $entry = $dirStart + 2 + 12 * $index; + my $format = Get16u($dataPt, $entry+2); + last if $format < 1 or $format > 13; + my $count = Get32u($dataPt, $entry+4); + my $size = $count * $Image::ExifTool::Exif::formatSize[$format]; + next if $size <= 4; + $valPtr = Get32u($dataPt, $entry+8); + $tagPtr and $$tagPtr{Get16u($dataPt, $entry)} = $valPtr; + # save location and size of longest block at this offset + unless (defined $valBlock{$valPtr} and $valBlock{$valPtr} > $size) { + $valBlock{$valPtr} = $size; + } + # adjust for case of value-based offsets + $valPtr += 12 * $index; + unless (defined $valBlkAdj{$valPtr} and $valBlkAdj{$valPtr} > $size) { + $valBlkAdj{$valPtr} = $size; + my $end = $valPtr + $size; + if (defined $valBlkAdj{MIN}) { + # save minimum only if it has a value of 12 or greater + $valBlkAdj{MIN} = $valPtr if $valBlkAdj{MIN} < 12 or $valBlkAdj{MIN} > $valPtr; + $valBlkAdj{MAX} = $end if $valBlkAdj{MAX} > $end; + } else { + $valBlkAdj{MIN} = $valPtr; + $valBlkAdj{MAX} = $end; + } + } + } + return(\%valBlock, \%valBlkAdj); +} + +#------------------------------------------------------------------------------ +# Fix base for value offsets in maker notes IFD (if necessary) +# Inputs: 0) ExifTool object ref, 1) DirInfo hash ref +# Return: amount of base shift (and $dirInfo Base and DataPos are updated, +# FixedBy is set if offsets fixed, and Relative or EntryBased may be set) +sub FixBase($$) +{ + local $_; + my ($et, $dirInfo) = @_; + # don't fix base if fixing offsets individually or if we don't want to fix them + return 0 if $$dirInfo{FixOffsets} or $$dirInfo{NoFixBase}; + + my $dataPt = $$dirInfo{DataPt}; + my $dataPos = $$dirInfo{DataPos}; + my $dirStart = $$dirInfo{DirStart} || 0; + my $entryBased = $$dirInfo{EntryBased}; + my $dirName = $$dirInfo{DirName}; + my $fixBase = $et->Options('FixBase'); + my $setBase = (defined $fixBase and $fixBase ne '') ? 1 : 0; + my ($fix, $fixedBy, %tagPtr); + + # get hash of value block positions + my ($valBlock, $valBlkAdj) = GetValueBlocks($dataPt, $dirStart, \%tagPtr); + return 0 unless %$valBlock; + # get sorted list of value offsets + my @valPtrs = sort { $a <=> $b } keys %$valBlock; +# +# handle special case of Canon maker notes with TIFF footer containing original offset +# + if ($$et{Make} =~ /^Canon/ and $$dirInfo{DirLen} > 8) { + my $footerPos = $dirStart + $$dirInfo{DirLen} - 8; + my $footer = substr($$dataPt, $footerPos, 8); + if ($footer =~ /^(II\x2a\0|MM\0\x2a)/ and # check for TIFF footer + substr($footer,0,2) eq GetByteOrder()) # validate byte ordering + { + my $oldOffset = Get32u(\$footer, 4); + my $newOffset = $dirStart + $dataPos; + if ($setBase) { + $fix = $fixBase; + } else { + $fix = $newOffset - $oldOffset; + return 0 unless $fix; + # Picasa and ACDSee have a bug where they update other offsets without + # updating the TIFF footer (PH - 2009/02/25), so test for this case: + # validate Canon maker note footer fix by checking offset of last value + my $maxPt = $valPtrs[-1] + $$valBlock{$valPtrs[-1]}; + # compare to end of maker notes, taking 8-byte footer into account + my $endDiff = $dirStart + $$dirInfo{DirLen} - ($maxPt - $dataPos) - 8; + # ignore footer offset only if end difference is exactly correct + # (allow for possible padding byte, although I have never seen this) + if (not $endDiff or $endDiff == 1) { + $et->Warn('Canon maker note footer may be invalid (ignored)',1); + return 0; + } + } + $et->Warn("Adjusted $dirName base by $fix",1); + $$dirInfo{FixedBy} = $fix; + $$dirInfo{Base} += $fix; + $$dirInfo{DataPos} -= $fix; + return $fix; + } + } +# +# analyze value offsets to see if they need fixing. The first task is to determine +# the minimum valid offset used (this is tricky, because we have to weed out bad +# offsets written by some cameras) +# + my $minPt = $$dirInfo{MinOffset} = $valPtrs[0]; # if life were simple, this would be it + my $ifdLen = 2 + 12 * Get16u($$dirInfo{DataPt}, $dirStart); + my $ifdEnd = $dirStart + $ifdLen; + my ($relative, @offsets) = GetMakerNoteOffset($et); + my $makeDiff = $offsets[0]; + my $verbose = $et->Options('Verbose'); + my ($diff, $shift); + + # calculate expected minimum value offset + my $expected = $dataPos + $ifdEnd + (defined $makeDiff ? $makeDiff : 4); + $debug and print "$expected expected\n"; + + # zero our counters + my ($countNeg12, $countZero, $countOverlap) = (0, 0, 0); + my ($valPtr, $last); + foreach $valPtr (@valPtrs) { + printf("%d - %d (%d)\n", $valPtr, $valPtr + $$valBlock{$valPtr}, + $valPtr - ($last || 0)) if $debug; + if (defined $last) { + my $gap = $valPtr - $last; + if ($gap == 0 or $gap == 1) { + ++$countZero; + } elsif ($gap == -12 and not $entryBased) { + # you get this when value offsets are relative to the IFD entry + ++$countNeg12; + } elsif ($gap < 0) { + # any other negative difference indicates overlapping values + ++$countOverlap if $valPtr; # (but ignore zero value pointers) + } elsif ($gap >= $ifdLen) { + # ignore previous minimum if we took a jump to near the expected value + # (some values can be stored before the IFD) + $minPt = $valPtr if abs($valPtr - $expected) <= 4; + } + # an offset less than 12 is surely garbage, so ignore it + $minPt = $valPtr if $minPt < 12; + } + $last = $valPtr + $$valBlock{$valPtr}; + } + # could this IFD be using entry-based offsets? + if ((($countNeg12 > $countZero and $$valBlkAdj{MIN} >= $ifdLen - 2) or + ($$valBlkAdj{MIN} == $ifdLen - 2 or $$valBlkAdj{MIN} == $ifdLen + 2) + ) and $$valBlkAdj{MAX} <= $$dirInfo{DirLen}-2) + { + # looks like these offsets are entry-based, so use the offsets + # which have been correcting for individual entry position + $entryBased = 1; + $verbose and $et->Warn("$dirName offsets are entry-based",1); + } else { + # calculate offset difference from end of IFD to first value + $diff = ($minPt - $dataPos) - $ifdEnd; + $shift = 0; + $countOverlap and $et->Warn("Overlapping $dirName values",1); + if ($entryBased) { + $et->Warn("$dirName offsets do NOT look entry-based",1); + undef $entryBased; + undef $relative; + } + # use PrintIM tag to do special check for correct absolute offsets + if ($tagPtr{0xe00}) { + my $ptr = $tagPtr{0xe00} - $dataPos; + return 0 if $ptr > 0 and $ptr <= length($$dataPt) - 8 and + substr($$dataPt, $ptr, 8) eq "PrintIM\0"; + } + # allow a range of reasonable differences for Unknown maker notes + if ($$dirInfo{FixBase} and $$dirInfo{FixBase} == 2) { + return 0 if $diff >=0 and $diff <= 24; + } + # ******** (used for testing to extract differences) ******** + # $et->FoundTag('Diff', $diff); + # $et->FoundTag('MakeDiff',$makeDiff); + } +# +# handle entry-based offsets +# + if ($entryBased) { + $debug and print "--> entry-based!\n"; + # most of my entry-based samples have first value immediately + # after last IFD entry (ie. no padding or next IFD pointer) + $makeDiff = 0; + push @offsets, 4; # but some do have a next IFD pointer + # corrected entry-based offsets are relative to start of first entry + my $expected = 12 * Get16u($$dirInfo{DataPt}, $dirStart); + $diff = $$valBlkAdj{MIN} - $expected; + # set up directory to read values with entry-based offsets + # (ignore everything and set base to start of first entry) + $shift = $dataPos + $dirStart + 2; + $$dirInfo{Base} += $shift; + $$dirInfo{DataPos} -= $shift; + $$dirInfo{EntryBased} = 1; + $$dirInfo{Relative} = 1; # entry-based offsets are relative + delete $$dirInfo{FixBase}; # no automatic base fix + undef $fixBase unless $setBase; + } +# +# return without doing shift if offsets look OK +# + unless ($setBase) { + # don't try to fix offsets for whacky cameras + return $shift unless defined $makeDiff; + # normal value data starts 4 bytes after IFD, but allow 0 or 4... + return $shift if $diff == 0 or $diff == 4; + # also check for allowed make-specific differences + foreach (@offsets) { + return $shift if $diff == $_; + } + } +# +# apply the fix, or issue a warning +# + # use default padding of 4 bytes unless already specified + $makeDiff = 4 unless defined $makeDiff; + $fix = $makeDiff - $diff; # assume standard diff for this make + + if ($$dirInfo{FixBase}) { + # set flag if offsets are relative (base is at or above directory start) + if ($dataPos - $fix + $dirStart <= 0) { + $$dirInfo{Relative} = (defined $relative) ? $relative : 1; + } + if ($setBase) { + $fixedBy = $fixBase; + $fix += $fixBase; + } + } elsif (defined $fixBase) { + $fix = $fixBase if $fixBase ne ''; + $fixedBy = $fix; + } else { + # print warning unless difference looks reasonable + if ($diff < 0 or $diff > 16 or ($diff & 0x01)) { + $et->Warn("Possibly incorrect maker notes offsets (fix by $fix?)",1); + } + # don't do the fix (but we already adjusted base if entry-based) + return $shift; + } + if (defined $fixedBy) { + $et->Warn("Adjusted $dirName base by $fixedBy",1); + $$dirInfo{FixedBy} = $fixedBy; + } + $$dirInfo{Base} += $fix; + $$dirInfo{DataPos} -= $fix; + return $fix + $shift; +} + +#------------------------------------------------------------------------------ +# Find start of IFD in unknown maker notes +# Inputs: 0) reference to directory information +# Returns: offset to IFD on success, undefined otherwise +# - dirInfo may contain TagInfo reference for tag associated with directory +# - on success, updates DirStart, DirLen, Base and DataPos in dirInfo +# - also sets Relative flag in dirInfo if offsets are relative to IFD +# Note: Changes byte ordering! +sub LocateIFD($$) +{ + my ($et, $dirInfo) = @_; + my $dataPt = $$dirInfo{DataPt}; + my $dirStart = $$dirInfo{DirStart} || 0; + # (ignore MakerNotes DirLen since sometimes this is incorrect) + my $size = $$dirInfo{DataLen} - $dirStart; + my $dirLen = defined $$dirInfo{DirLen} ? $$dirInfo{DirLen} : $size; + my $tagInfo = $$dirInfo{TagInfo}; + my $ifdOffsetPos; + # the IFD should be within the first 32 bytes + # (Kyocera sets the current record at 22 bytes) + my ($firstTry, $lastTry) = (0, 32); + + # make sure Base and DataPos are defined + $$dirInfo{Base} or $$dirInfo{Base} = 0; + $$dirInfo{DataPos} or $$dirInfo{DataPos} = 0; +# +# use tag information (if provided) to determine directory location +# + if ($tagInfo and $$tagInfo{SubDirectory}) { + my $subdir = $$tagInfo{SubDirectory}; + unless ($$subdir{ProcessProc} and + ($$subdir{ProcessProc} eq \&ProcessUnknown or + $$subdir{ProcessProc} eq \&ProcessUnknownOrPreview)) + { + # look for the IFD at the "Start" specified in our SubDirectory information + my $valuePtr = $dirStart; + my $newStart = $dirStart; + if (defined $$subdir{Start}) { + #### eval Start ($valuePtr) + $newStart = eval($$subdir{Start}); + } + if ($$subdir{Base}) { + # calculate subdirectory start relative to $base for eval + my $start = $newStart + $$dirInfo{DataPos}; + my $base = $$dirInfo{Base} || 0; + #### eval Base ($start,$base) + my $baseShift = eval($$subdir{Base}); + # shift directory base (note: we may do this again below + # if an OffsetPt is defined, but that doesn't matter since + # the base shift is relative to DataPos, which we set too) + $$dirInfo{Base} += $baseShift; + $$dirInfo{DataPos} -= $baseShift; + # this is a relative directory if Base depends on $start + if ($$subdir{Base} =~ /\$start\b/) { + $$dirInfo{Relative} = 1; + # hack to fix Leica quirk + if ($$subdir{ProcessProc} and $$subdir{ProcessProc} eq \&FixLeicaBase) { + my $oldStart = $$dirInfo{DirStart}; + $$dirInfo{DirStart} = $newStart; + FixLeicaBase($et, $dirInfo); + $$dirInfo{DirStart} = $oldStart; + } + } + } + # add offset to the start of the directory if necessary + if ($$subdir{OffsetPt}) { + if ($$subdir{ByteOrder} =~ /^Little/i) { + SetByteOrder('II'); + } elsif ($$subdir{ByteOrder} =~ /^Big/i) { + SetByteOrder('MM'); + } else { + warn "Can't have variable byte ordering for SubDirectories using OffsetPt\n"; + return undef; + } + #### eval OffsetPt ($valuePtr) + $ifdOffsetPos = eval($$subdir{OffsetPt}) - $dirStart; + } + # pinpoint position to look for this IFD + $firstTry = $lastTry = $newStart - $dirStart; + } + } +# +# scan for something that looks like an IFD +# + if ($dirLen >= 14 + $firstTry) { # minimum size for an IFD + my $offset; +IFD_TRY: for ($offset=$firstTry; $offset<=$lastTry; $offset+=2) { + last if $offset + 14 > $dirLen; # 14 bytes is minimum size for an IFD + my $pos = $dirStart + $offset; +# +# look for a standard TIFF header (Nikon uses it, others may as well), +# + if (SetByteOrder(substr($$dataPt, $pos, 2)) and + Get16u($dataPt, $pos + 2) == 0x2a) + { + $ifdOffsetPos = 4; + } + if (defined $ifdOffsetPos) { + # get pointer to IFD + my $ptr = Get32u($dataPt, $pos + $ifdOffsetPos); + if ($ptr >= $ifdOffsetPos + 4 and $ptr + $offset + 14 <= $dirLen) { + # shift directory start and shorten dirLen accordingly + $$dirInfo{DirStart} += $ptr + $offset; + $$dirInfo{DirLen} -= $ptr + $offset; + # shift pointer base to the start of the TIFF header + my $shift = $$dirInfo{DataPos} + $dirStart + $offset; + $$dirInfo{Base} += $shift; + $$dirInfo{DataPos} -= $shift; + $$dirInfo{Relative} = 1; # set "relative offsets" flag + return $ptr + $offset; + } + undef $ifdOffsetPos; + } +# +# look for a standard IFD (starts with 2-byte entry count) +# + my $num = Get16u($dataPt, $pos); + next unless $num; + # number of entries in an IFD should be between 1 and 255 + if (!($num & 0xff)) { + # lower byte is zero -- byte order could be wrong + ToggleByteOrder(); + $num >>= 8; + } elsif ($num & 0xff00) { + # upper byte isn't zero -- not an IFD + next; + } + my $bytesFromEnd = $size - ($offset + 2 + 12 * $num); + if ($bytesFromEnd < 4) { + next unless $bytesFromEnd == 2 or $bytesFromEnd == 0; + } + # do a quick validation of all format types + my $index; + for ($index=0; $index<$num; ++$index) { + my $entry = $pos + 2 + 12 * $index; + my $format = Get16u($dataPt, $entry+2); + my $count = Get32u($dataPt, $entry+4); + unless ($format) { + # patch for buggy Samsung NX200 JPEG MakerNotes entry count + if ($num == 23 and $index == 21 and $$et{Make} eq 'SAMSUNG') { + Set16u(21, $dataPt, $pos); # really 21 IFD entries! + $et->Warn('Fixed incorrect Makernote entry count', 1); + last; + } + # allow everything to be zero if not first entry + # because some manufacturers pad with null entries + next unless $count or $index == 0; + # patch for Canon EOS 40D firmware 1.0.4 bug: allow zero format for last entry + next if $index==$num-1 and $$et{Model}=~/EOS 40D/; + } + # patch for Sony cameras like the DSC-P10 that have invalid MakerNote entries + next if $num == 12 and $$et{Make} eq 'SONY' and $index >= 8; + # (would like to verify tag ID, but some manufactures don't + # sort entries in order of tag ID so we don't have much of + # a handle to verify this field) + # verify format + next IFD_TRY if $format < 1 or $format > 13; + # count must be reasonable (can't test for zero count because + # cameras like the 1DmkIII use this value) + next IFD_TRY if $count & 0xff000000; + # extra tests to avoid mis-identifying Samsung makernotes (GT-I9000, etc) + next unless $num == 1; + my $valueSize = $count * $Image::ExifTool::Exif::formatSize[$format]; + if ($valueSize > 4) { + next IFD_TRY if $valueSize > $size; + my $valuePtr = Get32u($dataPt, $entry+8); + next IFD_TRY if $valuePtr > 0x10000; + } + } + $$dirInfo{DirStart} += $offset; # update directory start + $$dirInfo{DirLen} -= $offset; + return $offset; # success!! + } + } + return undef; +} + +#------------------------------------------------------------------------------ +# Fix base offset for Leica maker notes +# Inputs: 0) ExifTool object ref, 1) dirInfo ref, 2) tag table ref +# Returns: 1 on success, and updates $dirInfo if necessary for new directory +sub FixLeicaBase($$;$) +{ + my ($et, $dirInfo, $tagTablePtr) = @_; + my $dataPt = $$dirInfo{DataPt}; + my $dirStart = $$dirInfo{DirStart} || 0; + # get hash of value block positions + my ($valBlock, $valBlkAdj) = GetValueBlocks($dataPt, $dirStart); + if (%$valBlock) { + # get sorted list of value offsets + my @valPtrs = sort { $a <=> $b } keys %$valBlock; + my $numEntries = Get16u($dataPt, $dirStart); + my $diff = $valPtrs[0] - ($numEntries * 12 + 4); + if ($diff > 8) { + $$dirInfo{Base} -= 8; + $$dirInfo{DataPos} += 8; + } + } + my $success = 1; + if ($tagTablePtr) { + $success = Image::ExifTool::Exif::ProcessExif($et, $dirInfo, $tagTablePtr); + } + return $success; +} + +#------------------------------------------------------------------------------ +# Process Canon maker notes +# Inputs: 0) ExifTool object ref, 1) dirInfo ref, 2) tag table ref +# Returns: 1 on success +sub ProcessCanon($$$) +{ + my ($et, $dirInfo, $tagTablePtr) = @_; + # identify Canon MakerNote footer in HtmlDump + # (this code moved from FixBase so it also works for Adobe MakN in DNG images) + if ($$et{HTML_DUMP} and $$dirInfo{DirLen} > 8) { + my $dataPos = $$dirInfo{DataPos}; + my $dirStart = $$dirInfo{DirStart} || 0; + my $footerPos = $dirStart + $$dirInfo{DirLen} - 8; + my $footer = substr(${$$dirInfo{DataPt}}, $footerPos, 8); + if ($footer =~ /^(II\x2a\0|MM\0\x2a)/ and substr($footer,0,2) eq GetByteOrder()) { + my $oldOffset = Get32u(\$footer, 4); + my $newOffset = $dirStart + $dataPos; + my $str = sprintf('Original maker note offset: 0x%.4x', $oldOffset); + if ($oldOffset != $newOffset) { + $str .= sprintf("\nCurrent maker note offset: 0x%.4x", $newOffset); + } + my $filePos = ($$dirInfo{Base} || 0) + $dataPos + $footerPos; + $et->HDump($filePos, 8, '[Canon MakerNotes footer]', $str); + } + } + # process as normal + return Image::ExifTool::Exif::ProcessExif($et, $dirInfo, $tagTablePtr); +} + +#------------------------------------------------------------------------------ +# Process GE type 2 maker notes +# Inputs: 0) ExifTool object ref, 1) DirInfo ref, 2) tag table ref +# Returns: 1 on success +sub ProcessGE2($$$) +{ + my ($et, $dirInfo, $tagTablePtr) = @_; + my $dataPt = $$dirInfo{DataPt} or return 0; + my $dirStart = $$dirInfo{DirStart} || 0; + + # these maker notes are missing the IFD entry count, but they + # always have 25 entries, so write the entry count manually + Set16u(25, $dataPt, $dirStart); + return Image::ExifTool::Exif::ProcessExif($et, $dirInfo, $tagTablePtr); +} + +#------------------------------------------------------------------------------ +# Process broken Kodak type 8b maker notes +# Inputs: 0) ExifTool object ref, 1) DirInfo ref, 2) tag table ref +# Returns: 1 on success +sub ProcessKodakPatch($$$) +{ + my ($et, $dirInfo, $tagTablePtr) = @_; + my $dataPt = $$dirInfo{DataPt} or return 0; + my $dirStart = $$dirInfo{DirStart} || 0; + + # these maker notes have an 2 extra null bytes either before or after the entry count, + # so fix this by making a 2-byte entry count just before the first IFD entry + return 0 unless $$dirInfo{DirLen} >= 4; + my $t1 = Get16u($dataPt,$dirStart); + my $t2 = Get16u($dataPt,$dirStart+2); + Set16u($t1 || $t2, $dataPt, $dirStart+2); + $$dirInfo{DirStart} += 2; + return Image::ExifTool::Exif::ProcessExif($et, $dirInfo, $tagTablePtr); +} + +#------------------------------------------------------------------------------ +# Process unknown maker notes or PreviewImage +# Inputs: 0) ExifTool object ref, 1) dirInfo ref, 2) tag table ref +# Returns: 1 on success, and updates $dirInfo if necessary for new directory +sub ProcessUnknownOrPreview($$$) +{ + my ($et, $dirInfo, $tagTablePtr) = @_; + my $dataPt = $$dirInfo{DataPt}; + my $dirStart = $$dirInfo{DirStart}; + my $dirLen = $$dirInfo{DirLen}; + # check to see if this is a preview image + if ($dirLen > 6 and substr($$dataPt, $dirStart, 3) eq "\xff\xd8\xff") { + $et->VerboseDir('PreviewImage'); + if ($$et{HTML_DUMP}) { + my $pos = $$dirInfo{DataPos} + $$dirInfo{Base} + $dirStart; + $et->HDump($pos, $dirLen, '(MakerNotes:PreviewImage data)', "Size: $dirLen bytes") + } + $et->FoundTag('PreviewImage', substr($$dataPt, $dirStart, $dirLen)); + return 1; + } + return ProcessUnknown($et, $dirInfo, $tagTablePtr); +} + +#------------------------------------------------------------------------------ +# Write unknown maker notes or PreviewImage +# Inputs: 0) ExifTool object ref, 1) dirInfo ref, 2) tag table ref +# Returns: directory data, '' to delete, or undef on error +sub WriteUnknownOrPreview($$$) +{ + my ($et, $dirInfo, $tagTablePtr) = @_; + my $dataPt = $$dirInfo{DataPt}; + my $dirStart = $$dirInfo{DirStart}; + my $dirLen = $$dirInfo{DirLen}; + my $newVal; + # check to see if this is a preview image + if ($dirLen > 6 and substr($$dataPt, $dirStart, 3) eq "\xff\xd8\xff") { + if ($$et{NEW_VALUE}{$Image::ExifTool::Extra{PreviewImage}}) { + # write or delete new preview (if deleted, it can't currently be added back again) + $newVal = $et->GetNewValue('PreviewImage') || ''; + if ($et->Options('Verbose') > 1) { + $et->VerboseValue("- MakerNotes:PreviewImage", substr($$dataPt, $dirStart, $dirLen)); + $et->VerboseValue("+ MakerNotes:PreviewImage", $newVal) if $newVal; + } + ++$$et{CHANGED}; + } else { + $newVal = substr($$dataPt, $dirStart, $dirLen); + } + } else { + # rewrite MakerNote IFD + $newVal = Image::ExifTool::Exif::WriteExif($et, $dirInfo, $tagTablePtr); + } + return $newVal; +} + +#------------------------------------------------------------------------------ +# Process unknown maker notes assuming it is in EXIF IFD format +# Inputs: 0) ExifTool object ref, 1) dirInfo ref, 2) tag table ref +# Returns: 1 on success, and updates $dirInfo if necessary for new directory +sub ProcessUnknown($$$) +{ + my ($et, $dirInfo, $tagTablePtr) = @_; + my $success = 0; + + my $loc = LocateIFD($et, $dirInfo); + if (defined $loc) { + $$et{UnknownByteOrder} = GetByteOrder(); + if ($et->Options('Verbose') > 1) { + my $out = $et->Options('TextOut'); + my $indent = $$et{INDENT}; + $indent =~ s/\| $/ /; + printf $out "${indent}Found IFD at offset 0x%.4x in maker notes:\n", + $$dirInfo{DirStart} + $$dirInfo{DataPos} + $$dirInfo{Base}; + } + $success = Image::ExifTool::Exif::ProcessExif($et, $dirInfo, $tagTablePtr); + } else { + $$et{UnknownByteOrder} = ''; # indicates we tried but didn't set byte order + $et->Warn("Unrecognized $$dirInfo{DirName}", 1); + } + return $success; +} + + +1; # end + +__END__ + +=head1 NAME + +Image::ExifTool::MakerNotes - Read and write EXIF maker notes + +=head1 SYNOPSIS + +This module is required by Image::ExifTool. + +=head1 DESCRIPTION + +This module contains definitions required by Image::ExifTool to interpret +maker notes in EXIF information. + +=head1 AUTHOR + +Copyright 2003-2019, Phil Harvey (phil at owl.phy.queensu.ca) + +This library is free software; you can redistribute it and/or modify it +under the same terms as Perl itself. + +=head1 SEE ALSO + +L<Image::ExifTool::TagNames(3pm)|Image::ExifTool::TagNames>, +L<Image::ExifTool(3pm)|Image::ExifTool> + +=cut diff --git a/lib/Image/ExifTool/Matroska.pm b/lib/Image/ExifTool/Matroska.pm new file mode 100644 index 0000000..9840a5c --- /dev/null +++ b/lib/Image/ExifTool/Matroska.pm @@ -0,0 +1,933 @@ +#------------------------------------------------------------------------------ +# File: Matroska.pm +# +# Description: Read meta information from Matroska multimedia files +# +# Revisions: 05/26/2010 - P. Harvey Created +# +# References: 1) http://www.matroska.org/technical/specs/index.html +#------------------------------------------------------------------------------ + +package Image::ExifTool::Matroska; + +use strict; +use vars qw($VERSION); +use Image::ExifTool qw(:DataAccess :Utils); + +$VERSION = '1.09'; + +my %noYes = ( 0 => 'No', 1 => 'Yes' ); + +# Matroska tags +# Note: The tag ID's in the Matroska documentation include the length designation +# (the upper bits), which is not included in the tag ID's below +%Image::ExifTool::Matroska::Main = ( + GROUPS => { 2 => 'Video' }, + VARS => { NO_LOOKUP => 1 }, # omit tags from lookup + NOTES => q{ + The following tags are extracted from Matroska multimedia container files. + This container format is used by file types such as MKA, MKV, MKS and WEBM. + For speed, ExifTool extracts tags only up to the first Cluster unless the + Verbose (-v) or Unknown = 2 (-U) option is used. See + L<http://www.matroska.org/technical/specs/index.html> for the official + Matroska specification. + }, + # supported Format's: signed, unsigned, float, date, string, utf8 + # (or undef by default) +# +# EBML Header +# + 0xa45dfa3 => { + Name => 'EBMLHeader', + SubDirectory => { TagTable => 'Image::ExifTool::Matroska::Main' }, + }, + 0x286 => { Name => 'EBMLVersion', Format => 'unsigned' }, + 0x2f7 => { Name => 'EBMLReadVersion', Format => 'unsigned' }, + 0x2f2 => { Name => 'EBMLMaxIDLength', Format => 'unsigned', Unknown => 1 }, + 0x2f3 => { Name => 'EBMLMaxSizeLength', Format => 'unsigned', Unknown => 1 }, + 0x282 => { + Name => 'DocType', + Format => 'string', + # override FileType for "webm" files + RawConv => '$self->OverrideFileType("WEBM") if $val eq "webm"; $val', + }, + 0x287 => { Name => 'DocTypeVersion', Format => 'unsigned' }, + 0x285 => { Name => 'DocTypeReadVersion',Format => 'unsigned' }, +# +# General +# + 0x3f => { Name => 'CRC-32', Binary => 1, Unknown => 1 }, + 0x6c => { Name => 'Void', NoSave => 1, Unknown => 1 }, +# +# Signature +# + 0xb538667 => { + Name => 'SignatureSlot', + SubDirectory => { TagTable => 'Image::ExifTool::Matroska::Main' }, + }, + 0x3e8a => { Name => 'SignatureAlgo', Format => 'unsigned' }, + 0x3e9a => { Name => 'SignatureHash', Format => 'unsigned' }, + 0x3ea5 => { Name =>'SignaturePublicKey',Binary => 1, Unknown => 1 }, + 0x3eb5 => { Name => 'Signature', Binary => 1, Unknown => 1 }, + 0x3e5b => { + Name => 'SignatureElements', + SubDirectory => { TagTable => 'Image::ExifTool::Matroska::Main' }, + }, + 0x3e7b => { + Name => 'SignatureElementList', + SubDirectory => { TagTable => 'Image::ExifTool::Matroska::Main' }, + }, + 0x2532 => { Name => 'SignedElement', Binary => 1, Unknown => 1 }, +# +# Segment +# + 0x8538067 => { + Name => 'SegmentHeader', + SubDirectory => { TagTable => 'Image::ExifTool::Matroska::Main' }, + }, + 0x14d9b74 => { + Name => 'SeekHead', + SubDirectory => { TagTable => 'Image::ExifTool::Matroska::Main' }, + }, + 0xdbb => { + Name => 'Seek', + SubDirectory => { TagTable => 'Image::ExifTool::Matroska::Main' }, + }, + 0x13ab => { Name => 'SeekID', Binary => 1, Unknown => 1 }, + 0x13ac => { Name => 'SeekPosition', Format => 'unsigned', Unknown => 1 }, +# +# Segment Info +# + 0x549a966 => { + Name => 'Info', + SubDirectory => { TagTable => 'Image::ExifTool::Matroska::Main' }, + }, + 0x33a4 => { Name => 'SegmentUID', Binary => 1, Unknown => 1 }, + 0x3384 => { Name => 'SegmentFileName', Format => 'utf8' }, + 0x1cb923 => { Name => 'PrevUID', Binary => 1, Unknown => 1 }, + 0x1c83ab => { Name => 'PrevFileName', Format => 'utf8' }, + 0x1eb923 => { Name => 'NextUID', Binary => 1, Unknown => 1 }, + 0x1e83bb => { Name => 'NextFileName', Format => 'utf8' }, + 0x0444 => { Name => 'SegmentFamily', Binary => 1, Unknown => 1 }, + 0x2924 => { + Name => 'ChapterTranslate', + SubDirectory => { TagTable => 'Image::ExifTool::Matroska::Main' }, + }, + 0x29fc => { Name => 'ChapterTranslateEditionUID',Format => 'unsigned', Unknown => 1 }, + 0x29bf => { + Name => 'ChapterTranslateCodec', + Format => 'unsigned', + PrintConv => { 0 => 'Matroska Script', 1 => 'DVD Menu' }, + }, + 0x29a5 => { Name => 'ChapterTranslateID',Binary => 1, Unknown => 1 }, + 0xad7b1 => { + Name => 'TimecodeScale', + Format => 'unsigned', + RawConv => '$$self{TimecodeScale} = $val', + ValueConv => '$val / 1e9', + PrintConv => '($val * 1000) . " ms"', + }, + 0x489 => { + Name => 'Duration', + Format => 'float', + ValueConv => '$$self{TimecodeScale} ? $val * $$self{TimecodeScale} / 1e9 : $val', + PrintConv => '$$self{TimecodeScale} ? ConvertDuration($val) : $val', + }, + 0x461 => { + Name => 'DateTimeOriginal', # called "DateUTC" by the spec + Description => 'Date/Time Original', + Groups => { 2 => 'Time' }, + Format => 'date', + PrintConv => '$self->ConvertDateTime($val)', + }, + 0x3ba9 => { Name => 'Title', Format => 'utf8' }, + 0xd80 => { Name => 'MuxingApp', Format => 'utf8' }, + 0x1741 => { Name => 'WritingApp', Format => 'utf8' }, +# +# Cluster +# + 0xf43b675 => { + Name => 'Cluster', + SubDirectory => { TagTable => 'Image::ExifTool::Matroska::Main' }, + }, + 0x67 => { + Name => 'TimeCode', + Format => 'unsigned', + Unknown => 1, + ValueConv => '$$self{TimecodeScale} ? $val * $$self{TimecodeScale} / 1e9 : $val', + PrintConv => '$$self{TimecodeScale} ? ConvertDuration($val) : $val', + }, + 0x1854 => { + Name => 'SilentTracks', + SubDirectory => { TagTable => 'Image::ExifTool::Matroska::Main' }, + }, + 0x18d7 => { Name => 'SilentTrackNumber',Format => 'unsigned' }, + 0x27 => { Name => 'Position', Format => 'unsigned' }, + 0x2b => { Name => 'PrevSize', Format => 'unsigned' }, + 0x23 => { Name => 'SimpleBlock', NoSave => 1, Unknown => 1 }, + 0x20 => { + Name => 'BlockGroup', + SubDirectory => { TagTable => 'Image::ExifTool::Matroska::Main' }, + }, + 0x21 => { Name => 'Block', NoSave => 1, Unknown => 1 }, + 0x22 => { Name => 'BlockVirtual', NoSave => 1, Unknown => 1 }, + 0x35a1 => { + Name => 'BlockAdditions', + SubDirectory => { TagTable => 'Image::ExifTool::Matroska::Main' }, + }, + 0x26 => { + Name => 'BlockMore', + SubDirectory => { TagTable => 'Image::ExifTool::Matroska::Main' }, + }, + 0x6e => { Name => 'BlockAddID', Format => 'unsigned', Unknown => 1 }, + 0x25 => { Name => 'BlockAdditional', NoSave => 1, Unknown => 1 }, + 0x1b => { + Name => 'BlockDuration', + Format => 'unsigned', + Unknown => 1, + ValueConv => '$$self{TimecodeScale} ? $val * $$self{TimecodeScale} / 1e9 : $val', + PrintConv => '$$self{TimecodeScale} ? "$val s" : $val', + }, + 0x7a => { Name => 'ReferencePriority',Format => 'unsigned', Unknown => 1 }, + 0x7b => { + Name => 'ReferenceBlock', + Format => 'signed', + Unknown => 1, + ValueConv => '$$self{TimecodeScale} ? $val * $$self{TimecodeScale} / 1e9 : $val', + PrintConv => '$$self{TimecodeScale} ? "$val s" : $val', + }, + 0x7d => { Name => 'ReferenceVirtual', Format => 'signed', Unknown => 1 }, + 0x24 => { Name => 'CodecState', Binary => 1, Unknown => 1 }, + 0x0e => { + Name => 'Slices', + SubDirectory => { TagTable => 'Image::ExifTool::Matroska::Main' }, + }, + 0x68 => { + Name => 'TimeSlice', + SubDirectory => { TagTable => 'Image::ExifTool::Matroska::Main' }, + }, + 0x4c => { Name => 'LaceNumber', Format => 'unsigned', Unknown => 1 }, + 0x4d => { Name => 'FrameNumber', Format => 'unsigned', Unknown => 1 }, + 0x4b => { Name => 'BlockAdditionalID',Format => 'unsigned', Unknown => 1 }, + 0x4e => { Name => 'Delay', Format => 'unsigned', Unknown => 1 }, + 0x4f => { Name => 'ClusterDuration', Format => 'unsigned', Unknown => 1 }, + 0x2f => { Name => 'EncryptedBlock', NoSave => 1, Unknown => 1 }, +# +# Tracks +# + 0x654ae6b => { + Name => 'Tracks', + SubDirectory => { TagTable => 'Image::ExifTool::Matroska::Main' }, + }, + 0x2e => { + Name => 'TrackEntry', + SubDirectory => { TagTable => 'Image::ExifTool::Matroska::Main' }, + }, + 0x57 => { Name => 'TrackNumber', Format => 'unsigned' }, + 0x33c5 => { Name => 'TrackUID', Format => 'unsigned', Unknown => 1 }, + 0x03 => { + Name => 'TrackType', + Format => 'unsigned', + PrintHex => 1, + # remember types of all tracks encountered, as well as the current track type + RawConv => '$$self{TrackTypes}{$val} = 1; $$self{TrackType} = $val', + PrintConv => { + 0x01 => 'Video', + 0x02 => 'Audio', + 0x03 => 'Complex', # (audio+video) + 0x10 => 'Logo', + 0x11 => 'Subtitle', + 0x12 => 'Buttons', + 0x20 => 'Control', + }, + }, + 0x39 => { Name => 'TrackUsed', Format => 'unsigned', PrintConv => \%noYes }, + 0x08 => { Name => 'TrackDefault', Format => 'unsigned', PrintConv => \%noYes }, + 0x15aa => { Name => 'TrackForced', Format => 'unsigned', PrintConv => \%noYes }, + 0x1c => { + Name => 'TrackLacing', + Format => 'unsigned', + Unknown => 1, + PrintConv => \%noYes, + }, + 0x2de7 => { Name => 'MinCache', Format => 'unsigned', Unknown => 1 }, + 0x2df8 => { Name => 'MaxCache', Format => 'unsigned', Unknown => 1 }, + 0x3e383 => [ + { + Name => 'VideoFrameRate', + Condition => '$$self{TrackType} and $$self{TrackType} == 0x01', + Format => 'unsigned', + ValueConv => '$val ? 1e9 / $val : 0', + PrintConv => 'int($val * 1000 + 0.5) / 1000', + },{ + Name => 'DefaultDuration', + Format => 'unsigned', + ValueConv => '$val / 1e9', + PrintConv => '($val * 1000) . " ms"', + } + ], + 0x3314f => { Name => 'TrackTimecodeScale',Format => 'float' }, + 0x137f => { Name => 'TrackOffset', Format => 'signed', Unknown => 1 }, + 0x15ee => { Name => 'MaxBlockAdditionID',Format => 'unsigned', Unknown => 1 }, + 0x136e => { Name => 'TrackName', Format => 'utf8' }, + 0x2b59c => { Name => 'TrackLanguage', Format => 'string' }, + 0x06 => [ + { + Name => 'VideoCodecID', + Condition => '$$self{TrackType} and $$self{TrackType} == 0x01', + Format => 'string', + },{ + Name => 'AudioCodecID', + Condition => '$$self{TrackType} and $$self{TrackType} == 0x02', + Format => 'string', + },{ + Name => 'CodecID', + Format => 'string', + } + ], + 0x23a2 => { Name => 'CodecPrivate', Binary => 1, Unknown => 1 }, + 0x58688 => [ + { + Name => 'VideoCodecName', + Condition => '$$self{TrackType} and $$self{TrackType} == 0x01', + Format => 'utf8', + },{ + Name => 'AudioCodecName', + Condition => '$$self{TrackType} and $$self{TrackType} == 0x02', + Format => 'utf8', + },{ + Name => 'CodecName', + Format => 'utf8', + } + ], + 0x3446 => { Name => 'TrackAttachmentUID',Format => 'unsigned' }, + 0x1a9697=>{ Name => 'CodecSettings', Format => 'utf8' }, + 0x1b4040=>{ Name => 'CodecInfoURL', Format => 'string' }, + 0x6b240 =>{ Name => 'CodecDownloadURL', Format => 'string' }, + 0x2a => { Name => 'CodecDecodeAll', Format => 'unsigned', PrintConv => \%noYes }, + 0x2fab => { Name => 'TrackOverlay', Format => 'unsigned', Unknown => 1 }, + 0x2624 => { + Name => 'TrackTranslate', + SubDirectory => { TagTable => 'Image::ExifTool::Matroska::Main' }, + }, + 0x26fc => { Name => 'TrackTranslateEditionUID',Format => 'unsigned', Unknown => 1 }, + 0x26bf => { + Name => 'TrackTranslateCodec', + Format => 'unsigned', + PrintConv => { 0 => 'Matroska Script', 1 => 'DVD Menu' }, + }, + 0x26a5 => { Name => 'TrackTranslateTrackID', Binary => 1, Unknown => 1 }, +# +# Video +# + 0x60 => { + Name => 'Video', + SubDirectory => { TagTable => 'Image::ExifTool::Matroska::Main' }, + }, + 0x1a => { + Name => 'VideoScanType', + Format => 'unsigned', + PrintConv => { + 0 => 'Progressive', + 1 => 'Interlaced', + }, + }, + 0x13b8 => { + Name => 'Stereo3DMode', + Format => 'unsigned', + Printconv => { + 0 => 'Mono', + 1 => 'Right Eye', + 2 => 'Left Eye', + 3 => 'Both Eyes', + }, + }, + 0x30 => { Name => 'ImageWidth', Format => 'unsigned' }, + 0x3a => { Name => 'ImageHeight', Format => 'unsigned' }, + 0x14aa => { Name => 'CropBottom', Format => 'unsigned' }, + 0x14bb => { Name => 'CropTop', Format => 'unsigned' }, + 0x14cc => { Name => 'CropLeft', Format => 'unsigned' }, + 0x14dd => { Name => 'CropRight', Format => 'unsigned' }, + 0x14b0 => { Name => 'DisplayWidth', Format => 'unsigned' }, + 0x14ba => { Name => 'DisplayHeight', Format => 'unsigned' }, + 0x14b2 => { + Name => 'DisplayUnit', + Format => 'unsigned', + PrintConv => { + 0 => 'Pixels', + 1 => 'cm', + 2 => 'inches', + }, + }, + 0x14b3 => { + Name => 'AspectRatioType', + Format => 'unsigned', + PrintConv => { + 0 => 'Free Resizing', + 1 => 'Keep Aspect Ratio', + 2 => 'Fixed', + }, + }, + 0xeb524 => { Name => 'ColorSpace', Binary => 1, Unknown => 1 }, + 0xfb523 => { Name => 'Gamma', Format => 'float' }, + 0x383e3 => { Name => 'FrameRate', Format => 'float' }, +# +# Audio +# + 0x61 => { + Name => 'Audio', + SubDirectory => { TagTable => 'Image::ExifTool::Matroska::Main' }, + }, + 0x35 => { Name => 'AudioSampleRate', Format => 'float', Groups => { 2 => 'Audio' } }, + 0x38b5 => { Name => 'OutputAudioSampleRate',Format => 'float', Groups => { 2 => 'Audio' } }, + 0x1f => { Name => 'AudioChannels', Format => 'unsigned', Groups => { 2 => 'Audio' } }, + 0x3d7b => { + Name => 'ChannelPositions', + Binary => 1, + Unknown => 1, + Groups => { 2 => 'Audio' }, + }, + 0x2264 => { Name => 'AudioBitsPerSample', Format => 'unsigned', Groups => { 2 => 'Audio' } }, +# +# Content Encoding +# + 0x2d80 => { + Name => 'ContentEncodings', + SubDirectory => { TagTable => 'Image::ExifTool::Matroska::Main' }, + }, + 0x2240 => { + Name => 'ContentEncoding', + SubDirectory => { TagTable => 'Image::ExifTool::Matroska::Main' }, + }, + 0x1031 => { Name => 'ContentEncodingOrder', Format => 'unsigned', Unknown => 1 }, + 0x1032 => { Name => 'ContentEncodingScope', Format => 'unsigned', Unknown => 1 }, + 0x1033 => { + Name => 'ContentEncodingType', + Format => 'unsigned', + PrintConv => { 0 => 'Compression', 1 => 'Encryption' }, + }, + 0x1034 => { + Name => 'ContentCompression', + SubDirectory => { TagTable => 'Image::ExifTool::Matroska::Main' }, + }, + 0x254 => { + Name => 'ContentCompressionAlgorithm', + Format => 'unsigned', + PrintConv => { + 0 => 'zlib', + 1 => 'bzlib', + 2 => 'lzo1x', + 3 => 'Header Stripping', + }, + }, + 0x255 => { Name => 'ContentCompressionSettings',Binary => 1, Unknown => 1 }, + 0x1035 => { + Name => 'ContentEncryption', + SubDirectory => { TagTable => 'Image::ExifTool::Matroska::Main' }, + }, + 0x7e1 => { + Name => 'ContentEncryptionAlgorithm', + Format => 'unsigned', + PrintConv => { + 0 => 'Not Encrypted', + 1 => 'DES', + 2 => '3DES', + 3 => 'Twofish', + 4 => 'Blowfish', + 5 => 'AES', + }, + }, + 0x7e2 => { Name => 'ContentEncryptionKeyID',Binary => 1, Unknown => 1 }, + 0x7e3 => { Name => 'ContentSignature', Binary => 1, Unknown => 1 }, + 0x7e4 => { Name => 'ContentSignatureKeyID', Binary => 1, Unknown => 1 }, + 0x7e5 => { + Name => 'ContentSignatureAlgorithm', + Format => 'unsigned', + PrintConv => { + 0 => 'Not Signed', + 1 => 'RSA', + }, + }, + 0x7e6 => { + Name => 'ContentSignatureHashAlgorithm', + Format => 'unsigned', + PrintConv => { + 0 => 'Not Signed', + 1 => 'SHA1-160', + 2 => 'MD5', + }, + }, +# +# Cues +# + 0xc53bb6b => { + Name => 'Cues', + SubDirectory => { TagTable => 'Image::ExifTool::Matroska::Main' }, + }, + 0x3b => { + Name => 'CuePoint', + SubDirectory => { TagTable => 'Image::ExifTool::Matroska::Main' }, + }, + 0x33 => { + Name => 'CueTime', + Format => 'unsigned', + Unknown => 1, + ValueConv => '$$self{TimecodeScale} ? $val * $$self{TimecodeScale} / 1e9 : $val', + PrintConv => '$$self{TimecodeScale} ? ConvertDuration($val) : $val', + }, + 0x37 => { + Name => 'CueTrackPositions', + SubDirectory => { TagTable => 'Image::ExifTool::Matroska::Main' }, + }, + 0x77 => { Name => 'CueTrack', Format => 'unsigned', Unknown => 1 }, + 0x71 => { Name => 'CueClusterPosition',Format => 'unsigned', Unknown => 1 }, + 0x1378 => { Name => 'CueBlockNumber', Format => 'unsigned', Unknown => 1 }, + 0x6a => { Name => 'CueCodecState', Format => 'unsigned', Unknown => 1 }, + 0x5b => { + Name => 'CueReference', + SubDirectory => { TagTable => 'Image::ExifTool::Matroska::Main' }, + }, + 0x16 => { + Name => 'CueRefTime', + Format => 'unsigned', + Unknown => 1, + ValueConv => '$$self{TimecodeScale} ? $val * $$self{TimecodeScale} / 1e9 : $val', + PrintConv => '$$self{TimecodeScale} ? ConvertDuration($val) : $val', + }, + 0x17 => { Name => 'CueRefCluster', Format => 'unsigned', Unknown => 1 }, + 0x135f=> { Name => 'CueRefNumber', Format => 'unsigned', Unknown => 1 }, + 0x6b => { Name => 'CueRefCodecState', Format => 'unsigned', Unknown => 1 }, +# +# Attachments +# + 0x941a469 => { + Name => 'Attachments', + SubDirectory => { TagTable => 'Image::ExifTool::Matroska::Main' }, + }, + 0x21a7 => { + Name => 'AttachedFile', + SubDirectory => { TagTable => 'Image::ExifTool::Matroska::Main' }, + }, + 0x67e => { Name => 'AttachedFileDescription',Format => 'utf8' }, + 0x66e => { Name => 'AttachedFileName', Format => 'utf8' }, + 0x660 => { Name => 'AttachedFileMIMEType', Format => 'string' }, + 0x65c => { Name => 'AttachedFileData', Binary => 1 }, + 0x6ae => { Name => 'AttachedFileUID', Format => 'unsigned' }, + 0x675 => { Name => 'AttachedFileReferral', Binary => 1, Unknown => 1 }, +# +# Chapters +# + 0x43a770 => { + Name => 'Chapters', + SubDirectory => { TagTable => 'Image::ExifTool::Matroska::Main' }, + }, + 0x5b9 => { + Name => 'EditionEntry', + SubDirectory => { TagTable => 'Image::ExifTool::Matroska::Main' }, + }, + 0x5bc => { Name => 'EditionUID', Format => 'unsigned', Unknown => 1 }, + 0x5bd => { Name => 'EditionFlagHidden', Format => 'unsigned', Unknown => 1 }, + 0x5db => { Name => 'EditionFlagDefault',Format => 'unsigned', Unknown => 1 }, + 0x5dd => { Name => 'EditionFlagOrdered',Format => 'unsigned', Unknown => 1 }, + 0x36 => { + Name => 'ChapterAtom', + SubDirectory => { TagTable => 'Image::ExifTool::Matroska::Main' }, + }, + 0x33c4 => { Name => 'ChapterUID', Format => 'unsigned', Unknown => 1 }, + 0x11 => { + Name => 'ChapterTimeStart', + Groups => { 1 => 'Chapter#' }, + Format => 'unsigned', + ValueConv => '$val / 1e9', + PrintConv => 'ConvertDuration($val)', + }, + 0x12 => { + Name => 'ChapterTimeEnd', + Format => 'unsigned', + ValueConv => '$val / 1e9', + PrintConv => 'ConvertDuration($val)', + }, + 0x18 => { Name => 'ChapterFlagHidden', Format => 'unsigned', Unknown => 1 }, + 0x598 => { Name => 'ChapterFlagEnabled',Format => 'unsigned', Unknown => 1 }, + 0x2e67=> { Name => 'ChapterSegmentUID', Binary => 1, Unknown => 1 }, + 0x2ebc=> { Name => 'ChapterSegmentEditionUID', Binary => 1, Unknown => 1 }, + 0x23c3 => { + Name => 'ChapterPhysicalEquivalent', + Format => 'unsigned', + PrintConv => { + 10 => 'Index', + 20 => 'Track', + 30 => 'Session', + 40 => 'Layer', + 50 => 'Side', + 60 => 'CD / DVD', + 70 => 'Set / Package', + }, + }, + 0x0f => { + Name => 'ChapterTrack', + SubDirectory => { TagTable => 'Image::ExifTool::Matroska::Main' }, + }, + 0x09 => { Name => 'ChapterTrackNumber', Format => 'unsigned', Unknown => 1 }, + 0x00 => { + Name => 'ChapterDisplay', + SubDirectory => { TagTable => 'Image::ExifTool::Matroska::Main' }, + }, + 0x05 => { Name => 'ChapterString', Format => 'utf8' }, + 0x37c => { Name => 'ChapterLanguage', Format => 'string' }, + 0x37e => { Name => 'ChapterCountry', Format => 'string' }, + 0x2944 => { + Name => 'ChapterProcess', + SubDirectory => { TagTable => 'Image::ExifTool::Matroska::Main' }, + }, + 0x2955 => { + Name => 'ChapterProcessCodecID', + Format => 'unsigned', + Unknown => 1, + PrintConv => { 0 => 'Matroska', 1 => 'DVD' }, + }, + 0x50d => { Name => 'ChapterProcessPrivate', Binary => 1, Unknown => 1 }, + 0x2911 => { + Name => 'ChapterProcessCommand', + SubDirectory => { TagTable => 'Image::ExifTool::Matroska::Main' }, + }, + 0x2922 => { + Name => 'ChapterProcessTime', + Format => 'unsigned', + Unknown => 1, + PrintConv => { + 0 => 'For Duration of Chapter', + 1 => 'Before Chapter', + 2 => 'After Chapter', + }, + }, + 0x2933 => { Name => 'ChapterProcessData', Binary => 1, Unknown => 1 }, +# +# Tags +# + 0x254c367 => { + Name => 'Tags', + SubDirectory => { TagTable => 'Image::ExifTool::Matroska::Main' }, + }, + 0x3373 => { + Name => 'Tag', + SubDirectory => { TagTable => 'Image::ExifTool::Matroska::Main' }, + }, + 0x23c0 => { + Name => 'Targets', + SubDirectory => { TagTable => 'Image::ExifTool::Matroska::Main' }, + }, + 0x28ca => { Name => 'TargetTypeValue', Format => 'unsigned' }, + 0x23ca => { Name => 'TargetType', Format => 'string' }, + 0x23c5 => { Name => 'TagTrackUID', Format => 'unsigned', Unknown => 1 }, + 0x23c9 => { Name => 'TagEditionUID', Format => 'unsigned', Unknown => 1 }, + 0x23c4 => { Name => 'TagChapterUID', Format => 'unsigned', Unknown => 1 }, + 0x23c6 => { Name => 'TagAttachmentUID', Format => 'unsigned', Unknown => 1 }, + 0x27c8 => { + Name => 'SimpleTag', + SubDirectory => { TagTable => 'Image::ExifTool::Matroska::Main' }, + }, + 0x5a3 => { Name => 'TagName', Format => 'utf8' }, + 0x47a => { Name => 'TagLanguage', Format => 'string' }, + 0x484 => { Name => 'TagDefault', Format => 'unsigned', PrintConv => \%noYes }, + 0x487 => { Name => 'TagString', Format => 'utf8' }, + 0x485 => { Name => 'TagBinary', Binary => 1 }, +# +# Spherical Video V2 (untested) +# + 0x7670 => { + Name => 'Projection', + SubDirectory => { TagTable => 'Image::ExifTool::Matroska::Projection' }, + }, +); + +# Spherical video v2 projection tags (ref https://github.com/google/spatial-media/blob/master/docs/spherical-video-v2-rfc.md) +%Image::ExifTool::Matroska::Projection = ( + GROUPS => { 2 => 'Video' }, + VARS => { NO_LOOKUP => 1 }, # omit tags from lookup + NOTES => q{ + Projection tags defined by the Spherical Video V2 specification. See + L<https://github.com/google/spatial-media/blob/master/docs/spherical-video-v2-rfc.md> + for the specification. + }, + 0x7671 => { + Name => 'ProjectionType', + Format => 'unsigned', + DataMember => 'ProjectionType', + RawConv => '$$self{ProjectionType} = $val', + PrintConv => { + 0 => 'Rectangular', + 1 => 'Equirectangular', + 2 => 'Cubemap', + 3 => 'Mesh', + }, + }, + 0x7672 => [{ + Name => 'EquirectangularProj', + Condition => '$$self{ProjectionType} == 1', + SubDirectory => { TagTable => 'Image::ExifTool::QuickTime::equi' }, + },{ + Name => 'CubemapProj', + Condition => '$$self{ProjectionType} == 2', + SubDirectory => { TagTable => 'Image::ExifTool::QuickTime::cbmp' }, + }], + 0x7673 => { Name => 'ProjectionPosYaw', Format => 'float' }, + 0x7674 => { Name => 'ProjectionPosPitch', Format => 'float' }, + 0x7675 => { Name => 'ProjectionPosRoll', Format => 'float' }, +); + +#------------------------------------------------------------------------------ +# Get variable-length Matroska integer +# Inputs: 0) data buffer, 1) position in data +# Returns: integer value and updates position, -1 for unknown/reserved value, +# or undef if no data left +sub GetVInt($$) +{ + return undef if $_[1] >= length $_[0]; + my $val = ord(substr($_[0], $_[1]++)); + my $num = 0; + unless ($val) { + return undef if $_[1] >= length $_[0]; + $val = ord(substr($_[0], $_[1]++)); + return undef unless $val; # can't be this large! + $num += 7; # 7 more bytes to read (we just read one) + } + my $mask = 0x7f; + while ($val == ($val & $mask)) { + $mask >>= 1; + ++$num; + } + $val = ($val & $mask); + my $unknown = ($val == $mask); + return undef if $_[1] + $num > length $_[0]; + while ($num) { + my $b = ord(substr($_[0], $_[1]++)); + $unknown = 0 if $b != 0xff; + $val = $val * 256 + $b; + --$num; + } + return $unknown ? -1 : $val; +} + +#------------------------------------------------------------------------------ +# Read information from a Matroska multimedia file (MKV, MKA, MKS) +# Inputs: 0) ExifTool object reference, 1) Directory information reference +# Returns: 1 on success, 0 if this wasn't a valid Matroska file +sub ProcessMKV($$) +{ + my ($et, $dirInfo) = @_; + my $raf = $$dirInfo{RAF}; + my ($buff, $buf2, @dirEnd, $trackIndent, %trackTypes); + + $raf->Read($buff, 4) == 4 or return 0; + return 0 unless $buff =~ /^\x1a\x45\xdf\xa3/; + + # read in 64kB blocks (already read 4 bytes) + $raf->Read($buff, 65532) or return 0; + my $dataLen = length $buff; + my ($pos, $dataPos) = (0, 4); + + # verify header length + my $hlen = GetVInt($buff, $pos); + return 0 unless $hlen and $hlen > 0; + $pos + $hlen > $dataLen and $et->Warn('Truncated Matroska header'), return 1; + $et->SetFileType(); + SetByteOrder('MM'); + my $tagTablePtr = GetTagTable('Image::ExifTool::Matroska::Main'); + + # set flag to process entire file (otherwise we stop at the first Cluster) + my $verbose = $et->Options('Verbose'); + my $processAll = ($verbose or $et->Options('Unknown') > 1); + $$et{TrackTypes} = \%trackTypes; # store Track types reference + my $oldIndent = $$et{INDENT}; + my $chapterNum = 0; + + # loop over all Matroska elements + for (;;) { + while (@dirEnd and $pos + $dataPos >= $dirEnd[-1][0]) { + pop @dirEnd; + # use INDENT to decide whether or not we are done this Track element + delete $$et{SET_GROUP1} if $trackIndent and $trackIndent eq $$et{INDENT}; + $$et{INDENT} = substr($$et{INDENT}, 0, -2); + } + # read more if we are getting close to the end of our buffer + # (24 more bytes should be enough to read this element header) + if ($pos + 24 > $dataLen and $raf->Read($buf2, 65536)) { + $buff = substr($buff, $pos) . $buf2; + undef $buf2; + $dataPos += $pos; + $dataLen = length $buff; + $pos = 0; + } + my $tag = GetVInt($buff, $pos); + last unless defined $tag and $tag >= 0; + my $size = GetVInt($buff, $pos); + last unless defined $size; + my $unknownSize; + $size < 0 and $unknownSize = 1, $size = 1e20; + if (@dirEnd and $pos + $dataPos + $size > $dirEnd[-1][0]) { + $et->Warn("Invalid or corrupted $dirEnd[-1][1] master element"); + $pos = $dirEnd[-1][0] - $dataPos; + if ($pos < 0 or $pos > $dataLen) { + $buff = ''; + $dataPos += $pos; + $dataLen = 0; + $pos = 0; + $raf->Seek($dataPos, 0) or last; + } + next; + } + my $tagInfo = $et->GetTagInfo($tagTablePtr, $tag); + # just fall through into the contained EBML elements + if ($tagInfo and $$tagInfo{SubDirectory}) { + # stop processing at first cluster unless we are in verbose mode + last if $$tagInfo{Name} eq 'Cluster' and not $processAll; + $$et{INDENT} .= '| '; + $et->VerboseDir($$tagTablePtr{$tag}{Name}, undef, $size); + push @dirEnd, [ $pos + $dataPos + $size, $$tagInfo{Name} ]; + if ($$tagInfo{Name} eq 'ChapterAtom') { + $$et{SET_GROUP1} = 'Chapter' . (++$chapterNum); + $trackIndent = $$et{INDENT}; + } + next; + } + last if $unknownSize; + if ($pos + $size > $dataLen) { + # how much more do we need to read? + my $more = $pos + $size - $dataLen; + # just skip unknown and large data blocks + if (not $tagInfo or $more > 10000000) { + # don't try to skip very large blocks unless LargeFileSupport is enabled + last if $more > 0x80000000 and not $et->Options('LargeFileSupport'); + $raf->Seek($more, 1) or last; + $buff = ''; + $dataPos += $dataLen + $more; + $dataLen = 0; + $pos = 0; + next; + } else { + # read data in multiples of 64kB + $more = (int($more / 65536) + 1) * 65536; + if ($raf->Read($buf2, $more)) { + $buff = substr($buff, $pos) . $buf2; + undef $buf2; + $dataPos += $pos; + $dataLen = length $buff; + $pos = 0; + } + last if $pos + $size > $dataLen; + } + } + unless ($tagInfo) { + # ignore the element + $pos += $size; + next; + } + my $val; + if ($$tagInfo{Format}) { + my $fmt = $$tagInfo{Format}; + if ($fmt eq 'string' or $fmt eq 'utf8') { + ($val = substr($buff, $pos, $size)) =~ s/\0.*//s; + $val = $et->Decode($val, 'UTF8') if $fmt eq 'utf8'; + } elsif ($fmt eq 'float') { + if ($size == 4) { + $val = GetFloat(\$buff, $pos); + } elsif ($size == 8) { + $val = GetDouble(\$buff, $pos); + } else { + $et->Warn("Illegal float size ($size)"); + } + } else { + my @vals = unpack("x${pos}C$size", $buff); + $val = 0; + if ($fmt eq 'signed' or $fmt eq 'date') { + my $over = 1; + foreach (@vals) { + $val = $val * 256 + $_; + $over *= 256; + } + # interpret negative numbers + $val -= $over if $vals[0] & 0x80; + # convert dates (nanoseconds since 2001:01:01) + if ($fmt eq 'date') { + my $t = $val / 1e9; + my $f = $t - int($t); # fractional seconds + $f =~ s/^\d+//; # remove leading zero + # (8 leap days between 1970 and 2001) + $t += (((2001-1970)*365+8)*24*3600); + $val = Image::ExifTool::ConvertUnixTime($t) . $f . 'Z'; + } + } else { # must be unsigned + $val = $val * 256 + $_ foreach @vals; + } + } + # set group1 to Track/Chapter number + if ($$tagInfo{Name} eq 'TrackNumber') { + $$et{SET_GROUP1} = 'Track' . $val; + $trackIndent = $$et{INDENT}; + } + } + my %parms = ( + DataPt => \$buff, + DataPos => $dataPos, + Start => $pos, + Size => $size, + ); + if ($$tagInfo{NoSave}) { + $et->VerboseInfo($tag, $tagInfo, Value => $val, %parms) if $verbose; + } else { + $et->HandleTag($tagTablePtr, $tag, $val, %parms); + } + $pos += $size; # step to next element + } + $$et{INDENT} = $oldIndent; + delete $$et{SET_GROUP1}; + # override file type if necessary based on existing track types + unless ($trackTypes{0x01} or $trackTypes{0x03}) { # video or complex? + if ($trackTypes{0x02}) { # audio? + $et->OverrideFileType('MKA'); + } elsif ($trackTypes{0x11}) { # subtitle? + $et->OverrideFileType('MKS'); + } + } + return 1; +} + +1; # end + +__END__ + +=head1 NAME + +Image::ExifTool::Matroska - Read meta information from Matroska files + +=head1 SYNOPSIS + +This module is used by Image::ExifTool + +=head1 DESCRIPTION + +This module contains definitions required by Image::ExifTool to read meta +information from Matroska multimedia files (MKA, MKV, MKS and WEBM). + +=head1 AUTHOR + +Copyright 2003-2019, Phil Harvey (phil at owl.phy.queensu.ca) + +This library is free software; you can redistribute it and/or modify it +under the same terms as Perl itself. + +=head1 REFERENCES + +=over 4 + +=item L<http://www.matroska.org/technical/specs/index.html> + +=back + +=head1 SEE ALSO + +L<Image::ExifTool::TagNames/Matroska Tags>, +L<Image::ExifTool(3pm)|Image::ExifTool> + +=cut diff --git a/lib/Image/ExifTool/Microsoft.pm b/lib/Image/ExifTool/Microsoft.pm new file mode 100644 index 0000000..4104fa6 --- /dev/null +++ b/lib/Image/ExifTool/Microsoft.pm @@ -0,0 +1,906 @@ +#------------------------------------------------------------------------------ +# File: Microsoft.pm +# +# Description: Definitions for custom Microsoft tags +# +# Revisions: 2010/10/01 - P. Harvey Created +# 2011/10/05 - PH Added ProcessXtra() +# +# References: 1) http://research.microsoft.com/en-us/um/redmond/groups/ivm/hdview/hdmetadataspec.htm +#------------------------------------------------------------------------------ + +package Image::ExifTool::Microsoft; + +use strict; +use vars qw($VERSION); +use Image::ExifTool qw(:DataAccess :Utils); +use Image::ExifTool::XMP; + +$VERSION = '1.20'; + +sub ProcessXtra($$$); + +# tags written by Microsoft HDView (ref 1) +%Image::ExifTool::Microsoft::Stitch = ( + PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData, + WRITE_PROC => \&Image::ExifTool::WriteBinaryData, + CHECK_PROC => \&Image::ExifTool::CheckBinaryData, + WRITABLE => 1, + FORMAT => 'float', + FIRST_ENTRY => 0, + GROUPS => { 0 => 'MakerNotes', 2 => 'Image' }, + NOTES => q{ + Information found in the Microsoft custom EXIF tag 0x4748, as written by + Windows Live Photo Gallery. + }, + 0 => { + Name => 'PanoramicStitchVersion', + Format => 'int32u', + }, + 1 => { + Name => 'PanoramicStitchCameraMotion', + Format => 'int32u', + PrintConv => { + 2 => 'Rigid Scale', + 3 => 'Affine', + 4 => '3D Rotation', + 5 => 'Homography', + }, + }, + 2 => { + Name => 'PanoramicStitchMapType', + Format => 'int32u', + PrintConv => { + 0 => 'Perspective', + 1 => 'Horizontal Cylindrical', + 2 => 'Horizontal Spherical', + 257 => 'Vertical Cylindrical', + 258 => 'Vertical Spherical', + }, + }, + 3 => 'PanoramicStitchTheta0', + 4 => 'PanoramicStitchTheta1', + 5 => 'PanoramicStitchPhi0', + 6 => 'PanoramicStitchPhi1', +); + +# Microsoft Photo schema properties (MicrosoftPhoto) (ref PH) +%Image::ExifTool::Microsoft::XMP = ( + %Image::ExifTool::XMP::xmpTableDefaults, + GROUPS => { 0 => 'XMP', 1 => 'XMP-microsoft', 2 => 'Image' }, + NAMESPACE => 'MicrosoftPhoto', + TABLE_DESC => 'XMP Microsoft', + VARS => { NO_ID => 1 }, + NOTES => q{ + Microsoft Photo 1.0 schema XMP tags. This is likely not a complete list, + but represents tags which have been observed in sample images. The actual + namespace prefix is "MicrosoftPhoto", but ExifTool shortens this in the + family 1 group name. + }, + CameraSerialNumber => { }, + DateAcquired => { Groups => { 2 => 'Time' }, %Image::ExifTool::XMP::dateTimeInfo }, + FlashManufacturer => { }, + FlashModel => { }, + LastKeywordIPTC => { List => 'Bag' }, + LastKeywordXMP => { List => 'Bag' }, + LensManufacturer => { }, + LensModel => { Avoid => 1 }, + Rating => { + Name => 'RatingPercent', + Notes => q{ + XMP-xmp:Rating values of 1,2,3,4 and 5 stars correspond to RatingPercent + values of 1,25,50,75 and 99 respectively + }, + }, + CreatorAppId => { Name => 'CreatorAppID' }, + CreatorOpenWithUIOptions => { }, + ItemSubType => { }, +); + +# Microsoft Photo 1.1 schema properties (MP1 - written as 'prefix0' by MSPhoto) (ref PH) +%Image::ExifTool::Microsoft::MP1 = ( + %Image::ExifTool::XMP::xmpTableDefaults, + GROUPS => { 0 => 'XMP', 1 => 'XMP-MP1', 2 => 'Image' }, + NAMESPACE => 'MP1', + TABLE_DESC => 'XMP Microsoft Photo', + VARS => { NO_ID => 1 }, + NOTES => q{ + Microsoft Photo 1.1 schema XMP tags which have been observed. + }, + PanoramicStitchCameraMotion => { + PrintConv => { + 'RigidScale' => 'Rigid Scale', + 'Affine' => 'Affine', + '3DRotation' => '3D Rotation', + 'Homography' => 'Homography', + }, + }, + PanoramicStitchMapType => { + PrintConv => { + 'Perspective' => 'Perspective', + 'Horizontal-Cylindrical' => 'Horizontal Cylindrical', + 'Horizontal-Spherical' => 'Horizontal Spherical', + 'Vertical-Cylindrical' => 'Vertical Cylindrical', + 'Vertical-Spherical' => 'Vertical Spherical', + }, + }, + PanoramicStitchPhi0 => { Writable => 'real' }, + PanoramicStitchPhi1 => { Writable => 'real' }, + PanoramicStitchTheta0 => { Writable => 'real' }, + PanoramicStitchTheta1 => { Writable => 'real' }, + WhiteBalance0 => { Writable => 'real' }, + WhiteBalance1 => { Writable => 'real' }, + WhiteBalance2 => { Writable => 'real' }, + Brightness => { Avoid => 1 }, + Contrast => { Avoid => 1 }, + CameraModelID => { Avoid => 1 }, + ExposureCompensation => { Avoid => 1 }, + PipelineVersion => { }, + StreamType => { }, +); + +# Microsoft Photo 1.2 schema properties (MP) (ref PH) +# (also ref http://msdn.microsoft.com/en-us/library/windows/desktop/ee719905(v=vs.85).aspx) +my %sRegions = ( + STRUCT_NAME => 'Microsoft Regions', + NAMESPACE => 'MPReg', + NOTES => q{ + Note that PersonLiveIdCID element is called PersonLiveCID according to the + Microsoft specification, but in practice their software actually writes + PersonLiveIdCID, so ExifTool uses this too. + }, + Rectangle => { }, + PersonDisplayName => { }, + PersonEmailDigest => { }, + PersonLiveIdCID => { }, # (see http://130.15.24.88/exiftool/forum/index.php?topic=4274.msg20368#msg20368) + PersonSourceID => { }, +); +%Image::ExifTool::Microsoft::MP = ( + %Image::ExifTool::XMP::xmpTableDefaults, + GROUPS => { 0 => 'XMP', 1 => 'XMP-MP', 2 => 'Image' }, + NAMESPACE => 'MP', + TABLE_DESC => 'XMP Microsoft Photo', + VARS => { NO_ID => 1 }, + NOTES => q{ + Microsoft Photo 1.2 schema XMP tags which have been observed. + }, + RegionInfo => { + Name => 'RegionInfoMP', + Struct => { + STRUCT_NAME => 'Microsoft RegionInfo', + NAMESPACE => 'MPRI', + Regions => { Struct => \%sRegions, List => 'Bag' }, + DateRegionsValid => { + Writable => 'date', + Shift => 'Time', + Groups => { 2 => 'Time'}, + PrintConv => '$self->ConvertDateTime($val)', + PrintConvInv => '$self->InverseDateTime($val,undef,1)', + }, + }, + }, + # remove "MP" from tag name (was added only to avoid conflict with XMP-mwg-rs:RegionInfo) + RegionInfoRegions => { Flat => 1, Name => 'RegionInfoRegions' }, + RegionInfoDateRegionsValid => { Flat => 1, Name => 'RegionInfoDateRegionsValid' }, + # shorten flattened Regions tag names to make them easier to use + RegionInfoRegionsRectangle => { Flat => 1, Name => 'RegionRectangle' }, + RegionInfoRegionsPersonDisplayName => { Flat => 1, Name => 'RegionPersonDisplayName' }, + RegionInfoRegionsPersonEmailDigest => { Flat => 1, Name => 'RegionPersonEmailDigest' }, + RegionInfoRegionsPersonLiveIdCID => { Flat => 1, Name => 'RegionPersonLiveIdCID' }, + RegionInfoRegionsPersonSourceID => { Flat => 1, Name => 'RegionPersonSourceID' }, +); + +# Xtra tags written in MP4 files written by Microsoft Windows Media Player +# (ref http://msdn.microsoft.com/en-us/library/windows/desktop/dd562330(v=VS.85).aspx) +# Note: These tags are closely related to tags in Image::ExifTool::ASF::ExtendedDescr +# and Image::ExifTool::WTV::Metadata +%Image::ExifTool::Microsoft::Xtra = ( + PROCESS_PROC => \&ProcessXtra, + GROUPS => { 0 => 'QuickTime', 2 => 'Video' }, + VARS => { NO_ID => 1 }, + NOTES => q{ + Tags extracted from the Microsoft "Xtra" atom of QuickTime videos. Tag ID's + are not shown because some are unruly GUID's. + }, + Abstract => { }, + AcquisitionTime => { Groups => { 2 => 'Time' } }, + AcquisitionTimeDay => { Groups => { 2 => 'Time' } }, + AcquisitionTimeMonth => { Groups => { 2 => 'Time' } }, + AcquisitionTimeYear => { Groups => { 2 => 'Time' } }, + AcquisitionTimeYearMonth => { Groups => { 2 => 'Time' } }, + AcquisitionTimeYearMonthDay => { Groups => { 2 => 'Time' } }, + AlbumArtistSortOrder => { }, + AlbumID => { }, + AlbumIDAlbumArtist => { }, + AlbumTitleSortOrder => { }, + AlternateSourceURL => { }, + AudioBitrate => { }, + AudioFormat => { }, + Author => { Groups => { 2 => 'Author' } }, + AuthorSortOrder => { }, + AverageLevel => { }, + Bitrate => { }, + BuyNow => { }, + BuyTickets => { }, + CallLetters => { }, + CameraManufacturer => { }, + CameraModel => { }, + CDTrackEnabled => { }, + Channels => { }, + chapterNum => { }, + Comment => { }, + ContentDistributorDuration => { }, + Copyright => { Groups => { 2 => 'Author' } }, + Count => { }, + CurrentBitrate => { }, + Description => { }, + DisplayArtist => { }, + DLNAServerUDN => { }, + DLNASourceURI => { }, + DRMKeyID => { }, + DRMIndividualizedVersion => { }, + DTCPIPHost => { }, + DTCPIPPort => { }, + Duration => { }, + DVDID => { }, + Event => { }, + FileSize => { }, + FileType => { }, + FourCC => { }, + FormatTag => { }, + FrameRate => { }, + Frequency => { }, + IsNetworkFeed => { }, + Is_Protected => 'IsProtected', + IsVBR => { }, + LeadPerformer => { }, + LibraryID => { }, + LibraryName => { }, + Location => { }, + MediaContentTypes => { }, + MediaType => { }, + ModifiedBy => { }, + MoreInfo => { }, + PartOfSet => { }, + PeakValue => { }, + PixelAspectRatioX => { }, + PixelAspectRatioY => { }, + PlaylistIndex => { }, + Provider => { }, + ProviderLogoURL => { }, + ProviderURL => { }, + RadioBand => { }, + RadioFormat => { }, + RatingOrg => { }, + RecordingTime => { Groups => { 2 => 'Time' } }, + RecordingTimeDay => { Groups => { 2 => 'Time' } }, + RecordingTimeMonth => { Groups => { 2 => 'Time' } }, + RecordingTimeYear => { Groups => { 2 => 'Time' } }, + RecordingTimeYearMonth => { Groups => { 2 => 'Time' } }, + RecordingTimeYearMonthDay => { Groups => { 2 => 'Time' } }, + ReleaseDate => { Groups => { 2 => 'Time' } }, + ReleaseDateDay => { Groups => { 2 => 'Time' } }, + ReleaseDateMonth => { Groups => { 2 => 'Time' } }, + ReleaseDateYear => { Groups => { 2 => 'Time' } }, + ReleaseDateYearMonth => { Groups => { 2 => 'Time' } }, + ReleaseDateYearMonthDay => { Groups => { 2 => 'Time' } }, + RequestState => { }, + ShadowFilePath => { }, + SourceURL => { }, + Subject => { }, + SyncState => { }, + Sync01 => { }, + Sync02 => { }, + Sync03 => { }, + Sync04 => { }, + Sync05 => { }, + Sync06 => { }, + Sync07 => { }, + Sync08 => { }, + Sync09 => { }, + Sync10 => { }, + Sync11 => { }, + Sync12 => { }, + Sync13 => { }, + Sync14 => { }, + Sync15 => { }, + Sync16 => { }, + SyncOnly => { }, + Temporary => { }, + Title => { }, + titleNum => { }, + TitleSortOrder => { }, + TotalDuration => { }, + TrackingID => { }, + UserCustom1 => { }, + UserCustom2 => { }, + UserEffectiveRating => { }, + UserLastPlayedTime => { }, + UserPlayCount => { }, + UserPlaycountAfternoon => { }, + UserPlaycountEvening => { }, + UserPlaycountMorning => { }, + UserPlaycountNight => { }, + UserPlaycountWeekday => { }, + UserPlaycountWeekend => { }, + UserRating => { }, + UserServiceRating => { }, + VideoBitrate => { }, + VideoFormat => { }, + 'WM/AlbumArtist' => 'AlbumArtist', + 'WM/AlbumCoverURL' => 'AlbumCoverURL', + 'WM/AlbumTitle' => 'AlbumTitle', + 'WM/BeatsPerMinute' => 'BeatsPerMinute', + 'WM/Category' => 'Category', + 'WM/Composer' => 'Composer', + 'WM/Conductor' => 'Conductor', + 'WM/ContentDistributor' => 'ContentDistributor', + 'WM/ContentDistributorType' => 'ContentDistributorType', + 'WM/ContentGroupDescription'=> 'ContentGroupDescription', + 'WM/Director' => 'Director', + 'WM/EncodingTime' => { + Name => 'EncodingTime', + Groups => { 2 => 'Time' }, + PrintConv => '$self->ConvertDateTime($val)', + }, + 'WM/Genre' => 'Genre', + 'WM/GenreID' => 'GenreID', + 'WM/InitialKey' => 'InitialKey', + 'WM/Language' => 'Language', + 'WM/Lyrics' => 'Lyrics', + 'WM/MCDI' => 'MCDI', + 'WM/MediaClassPrimaryID' => { + Name => 'MediaClassPrimaryID', + PrintConv => { #http://msdn.microsoft.com/en-us/library/windows/desktop/dd757960(v=vs.85).aspx + 'D1607DBC-E323-4BE2-86A1-48A42A28441E' => 'Music', + 'DB9830BD-3AB3-4FAB-8A37-1A995F7FF74B' => 'Video', + '01CD0F29-DA4E-4157-897B-6275D50C4F11' => 'Audio (not music)', + 'FCF24A76-9A57-4036-990D-E35DD8B244E1' => 'Other (not audio or video)', + }, + }, + 'WM/MediaClassSecondaryID' => { + Name => 'MediaClassSecondaryID', + PrintConv => { #http://msdn.microsoft.com/en-us/library/windows/desktop/dd757960(v=vs.85).aspx + 'E0236BEB-C281-4EDE-A36D-7AF76A3D45B5' => 'Audio Book', + '3A172A13-2BD9-4831-835B-114F6A95943F' => 'Spoken Word', + '6677DB9B-E5A0-4063-A1AD-ACEB52840CF1' => 'Audio News', + '1B824A67-3F80-4E3E-9CDE-F7361B0F5F1B' => 'Talk Show', + '1FE2E091-4E1E-40CE-B22D-348C732E0B10' => 'Video News', + 'D6DE1D88-C77C-4593-BFBC-9C61E8C373E3' => 'Web-based Video', + '00033368-5009-4AC3-A820-5D2D09A4E7C1' => 'Sound Clip from Game', + 'F24FF731-96FC-4D0F-A2F5-5A3483682B1A' => 'Song from Game', + 'E3E689E2-BA8C-4330-96DF-A0EEEFFA6876' => 'Music Video', + 'B76628F4-300D-443D-9CB5-01C285109DAF' => 'Home Movie', + 'A9B87FC9-BD47-4BF0-AC4F-655B89F7D868' => 'Feature Film', + 'BA7F258A-62F7-47A9-B21F-4651C42A000E' => 'TV Show', + '44051B5B-B103-4B5C-92AB-93060A9463F0' => 'Corporate Video', + '0B710218-8C0C-475E-AF73-4C41C0C8F8CE' => 'Home Video from Pictures', + '00000000-0000-0000-0000-000000000000' => 'Unknown Content', #PH + }, + }, + 'WM/MediaOriginalBroadcastDateTime' => { + Name => 'MediaOriginalBroadcastDateTime', + Groups => { 2 => 'Time' }, + PrintConv => '$self->ConvertDateTime($val)', + }, + 'WM/MediaOriginalChannel' => 'MediaOriginalChannel', + 'WM/MediaStationName' => 'MediaStationName', + 'WM/Mood' => 'Mood', + 'WM/OriginalAlbumTitle' => 'OriginalAlbumTitle', + 'WM/OriginalArtist' => 'OriginalArtist', + 'WM/OriginalLyricist' => 'OriginalLyricist', + 'WM/ParentalRating' => 'ParentalRating', + 'WM/PartOfSet' => 'PartOfSet', + 'WM/Period' => 'Period', + 'WM/Producer' => 'Producer', + 'WM/ProtectionType' => 'ProtectionType', + 'WM/Provider' => 'Provider', + 'WM/ProviderRating' => 'ProviderRating', + 'WM/ProviderStyle' => 'ProviderStyle', + 'WM/Publisher' => 'Publisher', + 'WM/SharedUserRating' => 'SharedUserRating', + 'WM/SubscriptionContentID' => 'SubscriptionContentID', + 'WM/SubTitle' => 'Subtitle', + 'WM/SubTitleDescription' => 'SubtitleDescription', + 'WM/TrackNumber' => 'TrackNumber', + 'WM/UniqueFileIdentifier' => 'UniqueFileIdentifier', + 'WM/VideoFrameRate' => 'VideoFrameRate', + 'WM/VideoHeight' => 'VideoHeight', + 'WM/VideoWidth' => 'VideoWidth', + 'WM/WMCollectionGroupID' => 'WMCollectionGroupID', + 'WM/WMCollectionID' => 'WMCollectionID', + 'WM/WMContentID' => 'WMContentID', + 'WM/WMShadowFileSourceDRMType' => 'WMShadowFileSourceDRMType', + 'WM/WMShadowFileSourceFileType' => 'WMShadowFileSourceFileType', + 'WM/Writer' => 'Writer', + 'WM/Year' => { Name => 'Year', Groups => { 2 => 'Time' } }, + + # I can't find documentation for the following tags in videos, + # but the tag ID's correspond to Microsoft property GUID+ID's + # References: + # http://msdn.microsoft.com/en-us/library/cc251929%28v=prot.10%29.aspx + # http://multi-rename-script.googlecode.com/svn-history/r4/trunk/plugins/ShellDetails/ShellDetails.ini + # I have observed only 1 so far: + '{2CBAA8F5-D81F-47CA-B17A-F8D822300131} 100' => { + Name => 'DateAcquired', + Groups => { 2 => 'Time' }, + PrintConv => '$self->ConvertDateTime($val)', + }, + # the following have not yet been observed... + '{B725F130-47EF-101A-A5F1-02608C9EEBAC} 10' => 'Name', + '{B725F130-47EF-101A-A5F1-02608C9EEBAC} 12' => 'Size', + '{B725F130-47EF-101A-A5F1-02608C9EEBAC} 4' => 'Type', + '{B725F130-47EF-101A-A5F1-02608C9EEBAC} 14' => { + Name => 'DateModified', + Groups => { 2 => 'Time' }, + PrintConv => '$self->ConvertDateTime($val)', + }, + '{B725F130-47EF-101A-A5F1-02608C9EEBAC} 15' => { + Name => 'DateCreated', + Groups => { 2 => 'Time' }, + PrintConv => '$self->ConvertDateTime($val)', + }, + '{B725F130-47EF-101A-A5F1-02608C9EEBAC} 16' => { + Name => 'DateAccessed', + Groups => { 2 => 'Time' }, + PrintConv => '$self->ConvertDateTime($val)', + }, + '{B725F130-47EF-101A-A5F1-02608C9EEBAC} 13' => 'Attributes', + '{D8C3986F-813B-449C-845D-87B95D674ADE} 2' => 'Status', + '{9B174B34-40FF-11D2-A27E-00C04FC30871} 4' => 'Owner', + '{F29F85E0-4FF9-1068-AB91-08002B27B3D9} 4' => { + Name => 'Author', + Groups => { 2 => 'Author' }, + }, + '{F29F85E0-4FF9-1068-AB91-08002B27B3D9} 2' => 'Title', + '{F29F85E0-4FF9-1068-AB91-08002B27B3D9} 3' => 'Subject', + '{D5CDD502-2E9C-101B-9397-08002B2CF9AE} 2' => 'Category', + '{F29F85E0-4FF9-1068-AB91-08002B27B3D9} 14' => 'Pages', + '{F29F85E0-4FF9-1068-AB91-08002B27B3D9} 6' => 'Comments', + '{64440492-4C8B-11D1-8B70-080036B11A03} 11' => { + Name => 'Copyright', + Groups => { 2 => 'Author' }, + }, + '{56A3372E-CE9C-11D2-9F0E-006097C686F6} 2' => 'Artist', + '{56A3372E-CE9C-11D2-9F0E-006097C686F6} 4' => 'AlbumTitle', + '{56A3372E-CE9C-11D2-9F0E-006097C686F6} 5' => { + Name => 'Year', + Groups => { 2 => 'Time' }, + }, + '{56A3372E-CE9C-11D2-9F0E-006097C686F6} 7' => 'TrackNumber', + '{56A3372E-CE9C-11D2-9F0E-006097C686F6} 11' => 'Genre', + '{64440490-4C8B-11D1-8B70-080036B11A03} 3' => 'Duration', + '{64440490-4C8B-11D1-8B70-080036B11A03} 4' => 'Bitrate', + '{AEAC19E4-89AE-4508-B9B7-BB867ABEE2ED} 2' => 'Protected', + '{14B81DA1-0135-4D31-96D9-6CBFC9671A99} 272' => 'CameraModel', + '{14B81DA1-0135-4D31-96D9-6CBFC9671A99} 36867' => { + Name => 'DatePictureTaken', + Groups => { 2 => 'Time' }, + PrintConv => '$self->ConvertDateTime($val)', + }, + '{6444048F-4C8B-11D1-8B70-080036B11A03} 13' => 'Dimensions', + '{6444048F-4C8B-11D1-8B70-080036B11A03} 3' => 'Untitled0', + '{6444048F-4C8B-11D1-8B70-080036B11A03} 4' => 'Untitled1', + '{6D748DE2-8D38-4CC3-AC60-F009B057C557} 2' => 'EpisodeName', + '{6D748DE2-8D38-4CC3-AC60-F009B057C557} 3' => 'ProgramDescription', + '{F29F85E0-4FF9-1068-AB91-08002B27B3D9} 12' => 'Untitled2', + '{64440490-4C8B-11D1-8B70-080036B11A03} 6' => 'AudioSampleSize', + '{64440490-4C8B-11D1-8B70-080036B11A03} 5' => 'AudioSampleRate', + '{64440490-4C8B-11D1-8B70-080036B11A03} 7' => 'Channels', + '{D5CDD502-2E9C-101B-9397-08002B2CF9AE} 15' => 'Company', + '{0CEF7D53-FA64-11D1-A203-0000F81FEDEE} 3' => 'Description', + '{0CEF7D53-FA64-11D1-A203-0000F81FEDEE} 4' => 'FileVersion', + '{0CEF7D53-FA64-11D1-A203-0000F81FEDEE} 7' => 'ProductName', + '{0CEF7D53-FA64-11D1-A203-0000F81FEDEE} 8' => 'ProductVersion', + '{F29F85E0-4FF9-1068-AB91-08002B27B3D9} 5' => 'Keywords', + '{28636AA6-953D-11D2-B5D6-00C04FD918D0} 11' => 'Type', + '{6D24888F-4718-4BDA-AFED-EA0FB4386CD8} 100' => 'OfflineStatus', + '{A94688B6-7D9F-4570-A648-E3DFC0AB2B3F} 100' => 'OfflineAvailability', + '{28636AA6-953D-11D2-B5D6-00C04FD918D0} 9' => 'PerceivedType', + '{1E3EE840-BC2B-476C-8237-2ACD1A839B22} 3' => 'Kinds', + '{56A3372E-CE9C-11D2-9F0E-006097C686F6} 36' => 'Conductors', + '{64440492-4C8B-11D1-8B70-080036B11A03} 9' => 'Rating', + '{14B81DA1-0135-4D31-96D9-6CBFC9671A99} 271' => 'CameraMaker', + '{F29F85E0-4FF9-1068-AB91-08002B27B3D9} 18' => 'ProgramName', + '{293CA35A-09AA-4DD2-B180-1FE245728A52} 100' => 'Duration', + '{BFEE9149-E3E2-49A7-A862-C05988145CEC} 100' => 'IsOnline', + '{315B9C8D-80A9-4EF9-AE16-8E746DA51D70} 100' => 'IsRecurring', + '{F6272D18-CECC-40B1-B26A-3911717AA7BD} 100' => 'Location', + '{D55BAE5A-3892-417A-A649-C6AC5AAAEAB3} 100' => 'OptionalAttendeeAddresses', + '{09429607-582D-437F-84C3-DE93A2B24C3C} 100' => 'OptionalAttendees', + '{744C8242-4DF5-456C-AB9E-014EFB9021E3} 100' => 'OrganizerAddress', + '{AAA660F9-9865-458E-B484-01BC7FE3973E} 100' => 'OrganizerName', + '{72FC5BA4-24F9-4011-9F3F-ADD27AFAD818} 100' => 'ReminderTime', + '{0BA7D6C3-568D-4159-AB91-781A91FB71E5} 100' => 'RequiredAttendeeAddresses', + '{B33AF30B-F552-4584-936C-CB93E5CDA29F} 100' => 'RequiredAttendees', + '{00F58A38-C54B-4C40-8696-97235980EAE1} 100' => 'Resources', + '{5BF396D4-5EB2-466F-BDE9-2FB3F2361D6E} 100' => 'Free-busyStatus', + '{9B174B35-40FF-11D2-A27E-00C04FC30871} 3' => 'TotalSize', + '{E3E0584C-B788-4A5A-BB20-7F5A44C9ACDD} 9' => 'AccountName', + '{28636AA6-953D-11D2-B5D6-00C04FD918D0} 5' => 'Computer', + '{9AD5BADB-CEA7-4470-A03D-B84E51B9949E} 100' => 'Anniversary', + '{CD102C9C-5540-4A88-A6F6-64E4981C8CD1} 100' => 'AssistantsName', + '{9A93244D-A7AD-4FF8-9B99-45EE4CC09AF6} 100' => 'AssistantsPhone', + '{176DC63C-2688-4E89-8143-A347800F25E9} 47' => 'Birthday', + '{730FB6DD-CF7C-426B-A03F-BD166CC9EE24} 100' => 'BusinessAddress', + '{402B5934-EC5A-48C3-93E6-85E86A2D934E} 100' => 'BusinessCity', + '{B0B87314-FCF6-4FEB-8DFF-A50DA6AF561C} 100' => 'BusinessCountry-Region', + '{BC4E71CE-17F9-48D5-BEE9-021DF0EA5409} 100' => 'BusinessPOBox', + '{E1D4A09E-D758-4CD1-B6EC-34A8B5A73F80} 100' => 'BusinessPostalCode', + '{446F787F-10C4-41CB-A6C4-4D0343551597} 100' => 'BusinessStateOrProvince', + '{DDD1460F-C0BF-4553-8CE4-10433C908FB0} 100' => 'BusinessStreet', + '{91EFF6F3-2E27-42CA-933E-7C999FBE310B} 100' => 'BusinessFax', + '{56310920-2491-4919-99CE-EADB06FAFDB2} 100' => 'BusinessHomePage', + '{6A15E5A0-0A1E-4CD7-BB8C-D2F1B0C929BC} 100' => 'BusinessPhone', + '{BF53D1C3-49E0-4F7F-8567-5A821D8AC542} 100' => 'CallbackNumber', + '{8FDC6DEA-B929-412B-BA90-397A257465FE} 100' => 'CarPhone', + '{D4729704-8EF1-43EF-9024-2BD381187FD5} 100' => 'Children', + '{8589E481-6040-473D-B171-7FA89C2708ED} 100' => 'CompanyMainPhone', + '{FC9F7306-FF8F-4D49-9FB6-3FFE5C0951EC} 100' => 'Department', + '{F8FA7FA3-D12B-4785-8A4E-691A94F7A3E7} 100' => 'E-mailAddress', + '{38965063-EDC8-4268-8491-B7723172CF29} 100' => 'E-mail2', + '{644D37B4-E1B3-4BAD-B099-7E7C04966ACA} 100' => 'E-mail3', + '{84D8F337-981D-44B3-9615-C7596DBA17E3} 100' => 'E-mailList', + '{CC6F4F24-6083-4BD4-8754-674D0DE87AB8} 100' => 'E-mailDisplayName', + '{F1A24AA7-9CA7-40F6-89EC-97DEF9FFE8DB} 100' => 'FileAs', + '{14977844-6B49-4AAD-A714-A4513BF60460} 100' => 'FirstName', + '{635E9051-50A5-4BA2-B9DB-4ED056C77296} 100' => 'FullName', + '{3C8CEE58-D4F0-4CF9-B756-4E5D24447BCD} 100' => 'Gender', + '{176DC63C-2688-4E89-8143-A347800F25E9} 70' => 'GivenName', + '{5DC2253F-5E11-4ADF-9CFE-910DD01E3E70} 100' => 'Hobbies', + '{98F98354-617A-46B8-8560-5B1B64BF1F89} 100' => 'HomeAddress', + '{176DC63C-2688-4E89-8143-A347800F25E9} 65' => 'HomeCity', + '{08A65AA1-F4C9-43DD-9DDF-A33D8E7EAD85} 100' => 'HomeCountry-Region', + '{7B9F6399-0A3F-4B12-89BD-4ADC51C918AF} 100' => 'HomePOBox', + '{8AFCC170-8A46-4B53-9EEE-90BAE7151E62} 100' => 'HomePostalCode', + '{C89A23D0-7D6D-4EB8-87D4-776A82D493E5} 100' => 'HomeStateOrProvince', + '{0ADEF160-DB3F-4308-9A21-06237B16FA2A} 100' => 'HomeStreet', + '{660E04D6-81AB-4977-A09F-82313113AB26} 100' => 'HomeFax', + '{176DC63C-2688-4E89-8143-A347800F25E9} 20' => 'HomePhone', + '{D68DBD8A-3374-4B81-9972-3EC30682DB3D} 100' => 'IMAddresses', + '{F3D8F40D-50CB-44A2-9718-40CB9119495D} 100' => 'Initials', + '{176DC63C-2688-4E89-8143-A347800F25E9} 6' => 'JobTitle', + '{97B0AD89-DF49-49CC-834E-660974FD755B} 100' => 'Label', + '{8F367200-C270-457C-B1D4-E07C5BCD90C7} 100' => 'LastName', + '{C0AC206A-827E-4650-95AE-77E2BB74FCC9} 100' => 'MailingAddress', + '{176DC63C-2688-4E89-8143-A347800F25E9} 71' => 'MiddleName', + '{176DC63C-2688-4E89-8143-A347800F25E9} 35' => 'CellPhone', + '{176DC63C-2688-4E89-8143-A347800F25E9} 74' => 'Nickname', + '{176DC63C-2688-4E89-8143-A347800F25E9} 7' => 'OfficeLocation', + '{508161FA-313B-43D5-83A1-C1ACCF68622C} 100' => 'OtherAddress', + '{6E682923-7F7B-4F0C-A337-CFCA296687BF} 100' => 'OtherCity', + '{8F167568-0AAE-4322-8ED9-6055B7B0E398} 100' => 'OtherCountry-Region', + '{8B26EA41-058F-43F6-AECC-4035681CE977} 100' => 'OtherPOBox', + '{95C656C1-2ABF-4148-9ED3-9EC602E3B7CD} 100' => 'OtherPostalCode', + '{71B377D6-E570-425F-A170-809FAE73E54E} 100' => 'OtherStateOrProvince', + '{FF962609-B7D6-4999-862D-95180D529AEA} 100' => 'OtherStreet', + '{D6304E01-F8F5-4F45-8B15-D024A6296789} 100' => 'Pager', + '{176DC63C-2688-4E89-8143-A347800F25E9} 69' => 'PersonalTitle', + '{C8EA94F0-A9E3-4969-A94B-9C62A95324E0} 100' => 'City', + '{E53D799D-0F3F-466E-B2FF-74634A3CB7A4} 100' => 'Country-Region', + '{DE5EF3C7-46E1-484E-9999-62C5308394C1} 100' => 'POBox', + '{18BBD425-ECFD-46EF-B612-7B4A6034EDA0} 100' => 'PostalCode', + '{F1176DFE-7138-4640-8B4C-AE375DC70A6D} 100' => 'StateOrProvince', + '{63C25B20-96BE-488F-8788-C09C407AD812} 100' => 'Street', + '{176DC63C-2688-4E89-8143-A347800F25E9} 48' => 'PrimaryE-mail', + '{176DC63C-2688-4E89-8143-A347800F25E9} 25' => 'PrimaryPhone', + '{7268AF55-1CE4-4F6E-A41F-B6E4EF10E4A9} 100' => 'Profession', + '{9D2408B6-3167-422B-82B0-F583B7A7CFE3} 100' => 'Spouse', + '{176DC63C-2688-4E89-8143-A347800F25E9} 73' => 'Suffix', + '{AAF16BAC-2B55-45E6-9F6D-415EB94910DF} 100' => 'TTY-TTDPhone', + '{C554493C-C1F7-40C1-A76C-EF8C0614003E} 100' => 'Telex', + '{E3E0584C-B788-4A5A-BB20-7F5A44C9ACDD} 18' => 'Webpage', + '{D5CDD502-2E9C-101B-9397-08002B2CF9AE} 27' => 'Status', + '{D5CDD502-2E9C-101B-9397-08002B2CF9AE} 26' => 'ContentType', + '{43F8D7B7-A444-4F87-9383-52271C9B915C} 100' => { + Name => 'DateArchived', + Groups => { 2 => 'Time' }, + PrintConv => '$self->ConvertDateTime($val)', + }, + '{72FAB781-ACDA-43E5-B155-B2434F85E678} 100' => { + Name => 'DateCompleted', + Groups => { 2 => 'Time' }, + PrintConv => '$self->ConvertDateTime($val)', + }, + '{14B81DA1-0135-4D31-96D9-6CBFC9671A99} 18258' => { + Name => 'DateImported', + Groups => { 2 => 'Time' }, + PrintConv => '$self->ConvertDateTime($val)', + }, + '{276D7BB0-5B34-4FB0-AA4B-158ED12A1809} 100' => 'ClientID', + '{F334115E-DA1B-4509-9B3D-119504DC7ABB} 100' => 'Contributors', + '{F29F85E0-4FF9-1068-AB91-08002B27B3D9} 11' => 'LastPrinted', + '{F29F85E0-4FF9-1068-AB91-08002B27B3D9} 13' => { + Name => 'DateLastSaved', + Groups => { 2 => 'Time' }, + PrintConv => '$self->ConvertDateTime($val)', + }, + '{1E005EE6-BF27-428B-B01C-79676ACD2870} 100' => 'Division', + '{E08805C8-E395-40DF-80D2-54F0D6C43154} 100' => 'DocumentID', + '{D5CDD502-2E9C-101B-9397-08002B2CF9AE} 7' => 'Slides', + '{F29F85E0-4FF9-1068-AB91-08002B27B3D9} 10' => 'TotalEditingTime', + '{F29F85E0-4FF9-1068-AB91-08002B27B3D9} 15' => 'WordCount', + '{3F8472B5-E0AF-4DB2-8071-C53FE76AE7CE} 100' => 'DueDate', + '{C75FAA05-96FD-49E7-9CB4-9F601082D553} 100' => 'EndDate', + '{28636AA6-953D-11D2-B5D6-00C04FD918D0} 12' => 'FileCount', + '{41CF5AE0-F75A-4806-BD87-59C7D9248EB9} 100' => 'WindowsFileName', + '{67DF94DE-0CA7-4D6F-B792-053A3E4F03CF} 100' => 'FlagColor', + '{E3E0584C-B788-4A5A-BB20-7F5A44C9ACDD} 12' => 'FlagStatus', + '{9B174B35-40FF-11D2-A27E-00C04FC30871} 2' => 'SpaceFree', + '{6444048F-4C8B-11D1-8B70-080036B11A03} 7' => 'BitDepth', + '{6444048F-4C8B-11D1-8B70-080036B11A03} 5' => 'HorizontalResolution', + '{6444048F-4C8B-11D1-8B70-080036B11A03} 6' => 'VerticalResolution', + '{E3E0584C-B788-4A5A-BB20-7F5A44C9ACDD} 11' => 'Importance', + '{F23F425C-71A1-4FA8-922F-678EA4A60408} 100' => 'IsAttachment', + '{5CDA5FC8-33EE-4FF3-9094-AE7BD8868C4D} 100' => 'IsDeleted', + '{5DA84765-E3FF-4278-86B0-A27967FBDD03} 100' => 'HasFlag', + '{A6F360D2-55F9-48DE-B909-620E090A647C} 100' => 'IsCompleted', + '{346C8BD1-2E6A-4C45-89A4-61B78E8E700F} 100' => 'Incomplete', + '{E3E0584C-B788-4A5A-BB20-7F5A44C9ACDD} 10' => 'ReadStatus', + '{EF884C5B-2BFE-41BB-AAE5-76EEDF4F9902} 100' => 'Shared', + '{D0A04F0A-462A-48A4-BB2F-3706E88DBD7D} 100' => { + Name => 'Creator', + Groups => { 2 => 'Author' }, + }, + '{F7DB74B4-4287-4103-AFBA-F1B13DCD75CF} 100' => { + Name => 'Date', + Groups => { 2 => 'Time' }, + PrintConv => '$self->ConvertDateTime($val)', + }, + '{B725F130-47EF-101A-A5F1-02608C9EEBAC} 2' => 'FolderName', + '{E3E0584C-B788-4A5A-BB20-7F5A44C9ACDD} 6' => 'FolderPath', + '{DABD30ED-0043-4789-A7F8-D013A4736622} 100' => 'Folder', + '{D4D0AA16-9948-41A4-AA85-D97FF9646993} 100' => 'Participants', + '{E3E0584C-B788-4A5A-BB20-7F5A44C9ACDD} 7' => 'Path', + '{DEA7C82C-1D89-4A66-9427-A4E3DEBABCB1} 100' => 'ContactNames', + '{95BEB1FC-326D-4644-B396-CD3ED90E6DDF} 100' => 'EntryType', + '{D5CDD502-2E9C-101B-9397-08002B2CF9AE} 28' => 'Language', + '{5CBF2787-48CF-4208-B90E-EE5E5D420294} 23' => { + Name => 'DateVisited', + Groups => { 2 => 'Time' }, + PrintConv => '$self->ConvertDateTime($val)', + }, + '{5CBF2787-48CF-4208-B90E-EE5E5D420294} 21' => 'Description', + '{B9B4B3FC-2B51-4A42-B5D8-324146AFCF25} 3' => 'LinkStatus', + '{B9B4B3FC-2B51-4A42-B5D8-324146AFCF25} 2' => 'LinkTarget', + '{5CBF2787-48CF-4208-B90E-EE5E5D420294} 2' => 'URL', + '{2E4B640D-5019-46D8-8881-55414CC5CAA0} 100' => 'MediaCreated', + '{DE41CC29-6971-4290-B472-F59F2E2F31E2} 100' => { + Name => 'DateReleased', + Groups => { 2 => 'Time' }, + PrintConv => '$self->ConvertDateTime($val)', + }, + '{64440492-4C8B-11D1-8B70-080036B11A03} 36' => 'EncodedBy', + '{64440492-4C8B-11D1-8B70-080036B11A03} 22' => 'Producers', + '{64440492-4C8B-11D1-8B70-080036B11A03} 30' => 'Publisher', + '{56A3372E-CE9C-11D2-9F0E-006097C686F6} 38' => 'Subtitle', + '{64440492-4C8B-11D1-8B70-080036B11A03} 34' => 'UserWebURL', + '{64440492-4C8B-11D1-8B70-080036B11A03} 23' => 'Writers', + '{E3E0584C-B788-4A5A-BB20-7F5A44C9ACDD} 21' => 'Attachments', + '{E3E0584C-B788-4A5A-BB20-7F5A44C9ACDD} 2' => 'BccAddresses', + '{E3E0584C-B788-4A5A-BB20-7F5A44C9ACDD} 3' => 'BccNames', + '{E3E0584C-B788-4A5A-BB20-7F5A44C9ACDD} 4' => 'CcAddresses', + '{E3E0584C-B788-4A5A-BB20-7F5A44C9ACDD} 5' => 'CcNames', + '{DC8F80BD-AF1E-4289-85B6-3DFC1B493992} 100' => 'ConversationID', + '{E3E0584C-B788-4A5A-BB20-7F5A44C9ACDD} 20' => { + Name => 'DateReceived', + Groups => { 2 => 'Time' }, + PrintConv => '$self->ConvertDateTime($val)', + }, + '{E3E0584C-B788-4A5A-BB20-7F5A44C9ACDD} 19' => { + Name => 'DateSent', + Groups => { 2 => 'Time' }, + PrintConv => '$self->ConvertDateTime($val)', + }, + '{E3E0584C-B788-4A5A-BB20-7F5A44C9ACDD} 13' => 'FromAddresses', + '{E3E0584C-B788-4A5A-BB20-7F5A44C9ACDD} 14' => 'FromNames', + '{9C1FCF74-2D97-41BA-B4AE-CB2E3661A6E4} 8' => 'HasAttachments', + '{0BE1C8E7-1981-4676-AE14-FDD78F05A6E7} 100' => 'SenderAddress', + '{0DA41CFA-D224-4A18-AE2F-596158DB4B3A} 100' => 'SenderName', + '{E3E0584C-B788-4A5A-BB20-7F5A44C9ACDD} 15' => 'Store', + '{E3E0584C-B788-4A5A-BB20-7F5A44C9ACDD} 16' => 'ToAddresses', + '{BCCC8A3C-8CEF-42E5-9B1C-C69079398BC7} 100' => 'ToDoTitle', + '{E3E0584C-B788-4A5A-BB20-7F5A44C9ACDD} 17' => 'ToNames', + '{FDF84370-031A-4ADD-9E91-0D775F1C6605} 100' => 'Mileage', + '{56A3372E-CE9C-11D2-9F0E-006097C686F6} 13' => 'AlbumArtist', + '{56A3372E-CE9C-11D2-9F0E-006097C686F6} 35' => 'Beats-per-minute', + '{64440492-4C8B-11D1-8B70-080036B11A03} 19' => 'Composers', + '{56A3372E-CE9C-11D2-9F0E-006097C686F6} 34' => 'InitialKey', + '{56A3372E-CE9C-11D2-9F0E-006097C686F6} 39' => 'Mood', + '{56A3372E-CE9C-11D2-9F0E-006097C686F6} 37' => 'PartOfSet', + '{64440492-4C8B-11D1-8B70-080036B11A03} 31' => 'Period', + '{4776CAFA-BCE4-4CB1-A23E-265E76D8EB11} 100' => 'Color', + '{64440492-4C8B-11D1-8B70-080036B11A03} 21' => 'ParentalRating', + '{10984E0A-F9F2-4321-B7EF-BAF195AF4319} 100' => 'ParentalRatingReason', + '{9B174B35-40FF-11D2-A27E-00C04FC30871} 5' => 'SpaceUsed', + '{D35F743A-EB2E-47F2-A286-844132CB1427} 100' => 'ExifVersion', + '{14B81DA1-0135-4D31-96D9-6CBFC9671A99} 18248' => 'Event', + '{14B81DA1-0135-4D31-96D9-6CBFC9671A99} 37380' => 'ExposureBias', + '{14B81DA1-0135-4D31-96D9-6CBFC9671A99} 34850' => 'ExposureProgram', + '{14B81DA1-0135-4D31-96D9-6CBFC9671A99} 33434' => 'ExposureTime', + '{14B81DA1-0135-4D31-96D9-6CBFC9671A99} 33437' => 'F-stop', + '{14B81DA1-0135-4D31-96D9-6CBFC9671A99} 37385' => 'FlashMode', + '{14B81DA1-0135-4D31-96D9-6CBFC9671A99} 37386' => 'FocalLength', + '{A0E74609-B84D-4F49-B860-462BD9971F98} 100' => 'FocalLength35mm', + '{14B81DA1-0135-4D31-96D9-6CBFC9671A99} 34855' => 'ISOSpeed', + '{E6DDCAF7-29C5-4F0A-9A68-D19412EC7090} 100' => 'LensMaker', + '{E1277516-2B5F-4869-89B1-2E585BD38B7A} 100' => 'LensModel', + '{14B81DA1-0135-4D31-96D9-6CBFC9671A99} 37384' => 'LightSource', + '{08F6D7C2-E3F2-44FC-AF1E-5AA5C81A2D3E} 100' => 'MaxAperture', + '{14B81DA1-0135-4D31-96D9-6CBFC9671A99} 37383' => 'MeteringMode', + '{14B81DA1-0135-4D31-96D9-6CBFC9671A99} 274' => 'Orientation', + '{6D217F6D-3F6A-4825-B470-5F03CA2FBE9B} 100' => 'ProgramMode', + '{49237325-A95A-4F67-B211-816B2D45D2E0} 100' => 'Saturation', + '{14B81DA1-0135-4D31-96D9-6CBFC9671A99} 37382' => 'SubjectDistance', + '{EE3D3D8A-5381-4CFA-B13B-AAF66B5F4EC9} 100' => 'WhiteBalance', + '{9C1FCF74-2D97-41BA-B4AE-CB2E3661A6E4} 5' => 'Priority', + '{39A7F922-477C-48DE-8BC8-B28441E342E3} 100' => 'Project', + '{6D748DE2-8D38-4CC3-AC60-F009B057C557} 7' => 'ChannelNumber', + '{6D748DE2-8D38-4CC3-AC60-F009B057C557} 12' => 'ClosedCaptioning', + '{6D748DE2-8D38-4CC3-AC60-F009B057C557} 13' => 'Rerun', + '{6D748DE2-8D38-4CC3-AC60-F009B057C557} 14' => 'SAP', + '{4684FE97-8765-4842-9C13-F006447B178C} 100' => 'BroadcastDate', + '{A5477F61-7A82-4ECA-9DDE-98B69B2479B3} 100' => 'RecordingTime', + '{6D748DE2-8D38-4CC3-AC60-F009B057C557} 5' => 'StationCallSign', + '{1B5439E7-EBA1-4AF8-BDD7-7AF1D4549493} 100' => 'StationName', + '{560C36C0-503A-11CF-BAA1-00004C752A9A} 2' => 'AutoSummary', + '{560C36C0-503A-11CF-BAA1-00004C752A9A} 3' => 'Summary', + '{49691C90-7E17-101A-A91C-08002B2ECDA9} 3' => 'SearchRanking', + '{F8D3F6AC-4874-42CB-BE59-AB454B30716A} 100' => 'Sensitivity', + '{EF884C5B-2BFE-41BB-AAE5-76EEDF4F9902} 200' => 'SharedWith', + '{668CDFA5-7A1B-4323-AE4B-E527393A1D81} 100' => 'Source', + '{48FD6EC8-8A12-4CDF-A03E-4EC5A511EDDE} 100' => 'StartDate', + '{D37D52C6-261C-4303-82B3-08B926AC6F12} 100' => 'BillingInformation', + '{084D8A0A-E6D5-40DE-BF1F-C8820E7C877C} 100' => 'Complete', + '{08C7CC5F-60F2-4494-AD75-55E3E0B5ADD0} 100' => 'TaskOwner', + '{28636AA6-953D-11D2-B5D6-00C04FD918D0} 14' => 'TotalFileSize', + '{0CEF7D53-FA64-11D1-A203-0000F81FEDEE} 9' => 'LegalTrademarks', + '{64440491-4C8B-11D1-8B70-080036B11A03} 10' => 'VideoCompression', + '{64440492-4C8B-11D1-8B70-080036B11A03} 20' => 'Directors', + '{64440491-4C8B-11D1-8B70-080036B11A03} 8' => 'DataRate', + '{64440491-4C8B-11D1-8B70-080036B11A03} 4' => 'FrameHeight', + '{64440491-4C8B-11D1-8B70-080036B11A03} 6' => 'FrameRate', + '{64440491-4C8B-11D1-8B70-080036B11A03} 3' => 'FrameWidth', + '{64440491-4C8B-11D1-8B70-080036B11A03} 43' => 'TotalBitrate', +); + +#------------------------------------------------------------------------------ +# Extract information from Xtra MP4 atom +# Inputs: 0) ExifTool object ref, 1) dirInfo ref, 2) tag table ref +# Returns: 1 on success +# Reference: http://code.google.com/p/mp4v2/ [since removed from trunk] +sub ProcessXtra($$$) +{ + my ($et, $dirInfo, $tagTablePtr) = @_; + my $dataPt = $$dirInfo{DataPt}; + my $dataPos = $$dirInfo{Base} || 0; + my $dataLen = $$dirInfo{DataLen}; + my $pos = 0; + $et->VerboseDir('Xtra', 0, $dataLen); + for (;;) { + last if $pos + 4 > $dataLen; + my $size = Get32u($dataPt, $pos); # (includes $size word) + last if $size < 8 or $pos + $size > $dataLen; + my $tagLen = Get32u($dataPt, $pos + 4); + last if $tagLen + 18 > $size; + my $tag = substr($$dataPt, $pos + 8, $tagLen); + # (version flags according to the reference, but looks more like a count - PH) + my $count = Get32u($dataPt, $pos + $tagLen + 8); + my ($i, $valPos, $valLen, $valType, $val, $format, @vals); + # point to start of first value (after 4-byte length and 2-byte type) + $valPos = $pos + $tagLen + 18; + for ($i=0; ;) { + # (stored value includes size of $valLen and $valType, so subtract 6) + $valLen = Get32u($dataPt, $valPos - 6) - 6; + my $more = $pos + $size - $valPos - $valLen; + last if $more < 0; + $valType = Get16u($dataPt, $valPos - 2); + $val = substr($$dataPt, $valPos, $valLen); + # Note: all dumb Microsoft values are little-endian inside a big-endian-format file + SetByteOrder('II'); + if ($valType == 8) { + $format = 'Unicode'; + $val = $et->Decode($val, 'UCS2'); + } elsif ($valType == 19 and $valLen == 8) { + $format = 'int64u'; + $val = Get64u(\$val, 0); + } elsif ($valType == 21 and $valLen == 8) { + $format = 'date'; + $val = Get64u(\$val, 0); + # convert time from 100 ns intervals since Jan 1, 1601 + $val = $val * 1e-7 - 11644473600 if $val; + # (the Nikon S100 uses UTC timezone, same as ASF - PH) + $val = Image::ExifTool::ConvertUnixTime($val) . 'Z'; + } elsif ($valType == 72 and $valLen == 16) { + $format = 'GUID'; + $val = uc unpack('H*',pack('NnnNN',unpack('VvvNN',$val))); + $val =~ s/(.{8})(.{4})(.{4})(.{4})/$1-$2-$3-$4-/; + } elsif ($valType == 65 && $valLen > 4) { #PH (empirical) + $format = 'variant'; + require Image::ExifTool::FlashPix; + my $vPos = $valPos; # (necessary because ReadFPXValue updates this) + # read entry as a VT_VARIANT (use FlashPix module for this) + $val = Image::ExifTool::FlashPix::ReadFPXValue($et, $dataPt, $vPos, + Image::ExifTool::FlashPix::VT_VARIANT(), $valPos+$valLen, 1); + } else { + $format = "Unknown($valType)"; + } + SetByteOrder('MM'); # back to native QuickTime byte ordering + last if ++$i >= $count or $more < 6; + push @vals, $val; + undef $val; + $valPos += $valLen + 6; # step to next value + } + if (@vals) { + push @vals, $val if defined $val; + $val = \@vals; + $valPos = $pos + $tagLen + 18; + $valLen = $size - 18 - $tagLen; + } + if ($tagLen > 0 and $valLen > 0) { + my $tagInfo = $et->GetTagInfo($tagTablePtr, $tag); + unless ($tagInfo) { + # generate tag information for unrecognized tags + my $name = $tag; + $name =~ s{^WM/}{}; + # $name =~ tr/-_A-Za-z0-9//dc; + if ($name =~ /^[-\w]+$/) { + $tagInfo = { Name => ucfirst($name) }; + AddTagToTable($tagTablePtr, $tag, $tagInfo); + $et->VPrint(0, $$et{INDENT}, "[adding Microsoft:$tag]\n"); + } + } + $et->HandleTag($tagTablePtr, $tag, $val, + TagInfo => $tagInfo, + DataPt => $dataPt, + DataPos => $dataPos, + Start => $valPos, + Size => $valLen, + Format => $format, + Extra => " count=$count type=$valType", + ); + } + $pos += $size; # step to next entry + } + return 1; +} + +1; # end + +__END__ + +=head1 NAME + +Image::ExifTool::Microsoft - Definitions for custom Microsoft tags + +=head1 SYNOPSIS + +This module is used by Image::ExifTool + +=head1 DESCRIPTION + +This module contains definitions required by Image::ExifTool to interpret +Microsoft-specific EXIF and XMP tags. + +=head1 AUTHOR + +Copyright 2003-2019, Phil Harvey (phil at owl.phy.queensu.ca) + +This library is free software; you can redistribute it and/or modify it +under the same terms as Perl itself. + +=head1 REFERENCES + +=over 4 + +=item L<http://research.microsoft.com/en-us/um/redmond/groups/ivm/hdview/hdmetadataspec.htm> + +=back + +=head1 SEE ALSO + +L<Image::ExifTool::TagNames/Microsoft Tags>, +L<Image::ExifTool(3pm)|Image::ExifTool> + +=cut + diff --git a/lib/Image/ExifTool/Minolta.pm b/lib/Image/ExifTool/Minolta.pm new file mode 100644 index 0000000..9b11355 --- /dev/null +++ b/lib/Image/ExifTool/Minolta.pm @@ -0,0 +1,3048 @@ +#------------------------------------------------------------------------------ +# File: Minolta.pm +# +# Description: Minolta EXIF maker notes tags +# +# Revisions: 04/06/2004 - P. Harvey Created +# 09/09/2005 - P. Harvey Added ability to write MRW files +# +# References: 1) http://www.dalibor.cz/minolta/makernote.htm +# 2) Jay Al-Saadi private communication (testing with A2) +# 3) Shingo Noguchi, PhotoXP (http://www.daifukuya.com/photoxp/) +# 5) http://www.cybercom.net/~dcoffin/dcraw/ +# 6) Pedro Corte-Real private communication +# 7) ExifTool forum post by bronek (http://www.cpanforum.com/posts/1118) +# 8) http://www.chauveau-central.net/mrw-format/ +# 9) CPAN Forum post by 'geve' (http://www.cpanforum.com/threads/2168) +# 10) http://homepage3.nifty.com/kamisaka/makernote/makernote_km.htm +# 11) http://www.dyxum.com/dforum/forum_posts.asp?TID=6371&PN=1 and +# http://www.dyxum.com/dAdmin/lenses/MakerNoteList_Public.asp?stro=makr +# http://dyxum.com/dforum/forum_posts.asp?TID=23435&PN=2 +# 12) http://www.minolta-forum.de/forum/index.php?showtopic=14914 +# 13) http://www.mhohner.de/minolta/lenses.php +# 14) Jeffery Small private communication (tests with 7D) +# 15) http://homepage3.nifty.com/kamisaka/makernote/makernote_sony.htm +# 16) Thomas Kassner private communication +# 17) Mladen Sever private communication +# 18) Olaf Ulrich private communication +# 19) Lukasz Stelmach private communication +# 20) Igal Milchtaich private communication (A100 firmware 1.04) +# 21) Jean-Michel Dubois private communication +# 22) http://www.mi-fo.de/forum/index.php?act=attach&type=post&id=6024 +# 23) Marcin Krol private communication +# 24) http://cpanforum.com/threads/12291 +# 26) http://u88.n24.queensu.ca/exiftool/forum/index.php/topic,3521.0.html +# 27) http://u88.n24.queensu.ca/exiftool/forum/index.php/topic,3833.0.html +# 28) Michael Reitinger private communication (RX100) +# 29) http://u88.n24.queensu.ca/exiftool/forum/index.php/topic,4086.0.html +# IB) Iliah Borg private communication (LibRaw) +# JD) Jens Duttke private communication +# JR) Jos Roost private communication +# NJ) Niels Kristian Bech Jensen private communication +#------------------------------------------------------------------------------ + +package Image::ExifTool::Minolta; + +use strict; +use vars qw($VERSION %minoltaLensTypes %minoltaTeleconverters %minoltaColorMode + %sonyColorMode %minoltaSceneMode %afStatusInfo %metabonesID); +use Image::ExifTool qw(:DataAccess :Utils); +use Image::ExifTool::Exif; + +$VERSION = '2.72'; + +# Full list of product codes for Sony-compatible Minolta lenses +# (ref http://www.kb.sony.com/selfservice/documentLink.do?externalId=C1000570) +# NOTE: Unfortunately, these product codes sometimes do not match the first 4 +# digits of the lens ID +# 2578 AF 16mm F2.8 FISH-EYE +# 2579 AF 20mm F2.8 +# 2641 AF 20mm F2.8 NEW +# 2566 AF 24mm F2.8 +# 2642 AF 24mm F2.8 NEW +# 2596 AF 28mm F2 +# 2668 AF 28mm F2 NEW +# 2557 AF 28mm F2.8 +# 2591 AF 35mm F1.4 G +# 2666 AF 35mm F1.4 G NEW +# 2597 AF 35mm F2 +# 2667 AF 35mm F2 NEW +# 2562 AF 50mm F1.4 +# 2662 AF 50mm F1.4 NEW +# 2550 AF 50mm F1.7 +# 2613 AF 50mm F1.7 NEW +# 2592 AF 85mm F1.4 +# 2629 AF 85mm F1.4 G +# 2677 AF 85mm F1.4 G (D) +# 2689 AF 85mm F1.4 G (D) Limited +# 2598 AF 100mm F2 +# 2648 AF 100mm F2.8 SOFT +# 2556 AF 135mm F2.8 +# 2656 STF 135mm F2.8 [T4.5] +# 2593 AF APO 20 0mm F2.8 +# 2612 High Speed AF APO 200mm F2.8 G +# 2563 AF APO 300mm F2.8 +# 2608 High Speed AF APO 300mm F2.8 G +# 2674 AF APO 300mm F2.8 G(D) SSM +# 2640 AF APO 300mm F4 G +# 2651 AF APO 400mm F4.5 G +# 2572 AF REFLEX 500mm F8 +# 2565 AF APO 600mm F4 +# 2609 High Speed AF APO 600mm F4 G +# 2564 AF MACRO 50mm F2.8 +# 2638 AF MACRO 50mm F2.8 NEW +# 2675 AF MACRO 50mm F2.8 (D) +# 2646 AF MACRO 50mm F3.5 +# 2581 AF MACRO 100mm F2.8 +# 2639 AF MACRO 100mm F2.8 NEW +# 2676 AF MACRO 100mm F2.8 (D) +# 2658 AF APO TE LE MACRO 200mm F4 G +# 2594 AF MACRO ZOOM 1x-3x F1.7-2.8 +# 2695 AF 17-35mm F2.8-4 (D) +# 2654 AF 17-35mm F3.5 G +# 2657 AF 20-35mm F3.5-4.5 +# 2558 AF 24-50mm F4 +# 2632 AF 24-50mm F4 NEW +# 2636 AF 24-85mm F3.5-4.5 +# 2660 AF 24-85mm F3.5-4.5 NEW +# 2672 AF 24-105mm F3.5-4.5 (D) +# 2620 AF 28-70mm F2.8 G +# 2696 AF 28-75mm F2.8 (D) +# 2659 AF 28-80mm F3.5-5.6 +# 2670 AF 28-80mm F3.5-5.6 II +# 2683 AF 28-80mm F3.5-5.6 (D) +# 2633 AF 28-80mm F4-5.6 +# 2552 AF 28-85mm F3.5-4.5 +# 2586 AF 28-85mm F3.5-4.5 NEW +# 2692 AF 28-100mm F3.5-5.6 (D) +# 2635 AF 28-105mm F3.5-4.5 +# 2661 AF 28-105mm F3.5-4.5 NEW +# 2553 AF 28-135mm F4-4.5 +# 2551 AF 35-70mm F4 +# 2643 AF 35-70mm F3.5-4.5 +# 2652 AF 35-70mm F3.5-4.5 NEW +# 2605 AF 35-80mm F4-5.6 +# 2671 AF 35-80mm F4.5-5.6 II +# 2554 AF 35-105mm F3.5-4.5 +# 2585 AF 35-105mm F3.5-4.5 +# 2682 AF APO 70-200mm F2.8 G (D) SSM +# 2588 AF 70-210mm F4.5-5.6 +# 2555 AF 70-210mm F4 +# 2634 AF 70-210mm F4.5-5.6 NEW +# 2669 AF 70-210mm F4.5-5.6 II +# 2561 AF 75-300mm F4.5-5.6 +# 2649 AF 75-300mm F4.5-5.6 NEW +# 2665 AF 75-300mm F4.5-5.6 II +# 2684 AF 75-300mm F4.5-5.6 (D) +# 2589 AF APO 80-200mm F2.8 +# 2628 High-Speed AF APO 80-200mm F2.8 G +# 2604 AF 80-200mm F4.5-5.6 +# 2560 AF 100-200mm F4.5 +# 2606 AF 100-300mm F4.5-5.6 +# 2631 AF APO 100-300mm F4.5-5.6 +# 2681 AF APO 100-300mm F4.5-5.6 (D) +# 2644 AF APO 100-400mm F4.5-6.7 +# 2618 AF Xi 28-80mm F4-5.6 +# 2615 AF Xi 28-105mm F3.5-4.5 +# 2624 AF PZ 35-80mm F4-5.6 +# 2616 AF Xi 35-200mm F4.5-5.6 +# 2619 AF Xi 80-200mm F4.5-5.6 +# 2621 AF Xi 100-300mm F4.5-5.6 +# 2698 AF DT 11-18mm F4.5-5.6 (D) +# 2697 AF DT 18-70mm F3.5-5.6 (D) +# 2699 AF DT 18-200mm F3.5-6.3 (D) +# 2590 1.4x TELE CONVERTER APO +# 2601 2x TELE CONVERTER APO +# 2610 1.4x TELE CONVERTER APO II +# 2611 2x TELE CONVERTER APO II +# 2687 1.4x TELE CONVERTER APO (D) +# 2688 2x TELE CONVERTER APO (D) + +# high bytes in Sony LensID's identifying Metabones adapters and high bytes of Canon LensID's +%metabonesID = ( + # 0xef00 is used by Metabones, Fotodiox, Sigma and Viltrox adapters (JR) + 0xef00 => \ 'Canon EF Adapter', # with Canon LensID 0x00xx + 0xf000 => 0xef00, # with Canon LensID 0x01xx + 0xf100 => 0xef00, # with Canon LensID 0x02xx + 0xff00 => 0xef00, # with Canon LensID 0x10xx + 0x7700 => \ 'Metabones Speed Booster', # with Canon LensID 0x00xx + 0x7800 => 0x7700, # with Canon LensID 0x01xx + 0x7900 => 0x7700, # with Canon LensID 0x02xx + 0x8700 => 0x7700, # with Canon LensID 0x10xx + 0xbc00 => \ 'Metabones Speed Booster Ultra', # with Canon LensID 0x00xx + 0xbd00 => 0xbc00, # with Canon LensID 0x01xx + 0xbe00 => 0xbc00, # with Canon LensID 0x02xx + 0xcc00 => 0xbc00, # with Canon LensID 0x10xx +); + +# lens ID numbers (ref 3) +# ("New" and "II" appear in brackets if original version also has this LensType) +%minoltaLensTypes = ( + Notes => q{ + Decimal values have been added to differentiate lenses which would otherwise + have the same LensType, and are used by the Composite LensID tag when + attempting to identify the specific lens model. "New" or "II" appear in + brackets if the original version of the lens has the same LensType. Special + logic is employed to identify the attached lens when a Metabones Canon EF + adapter is used. + }, + OTHER => sub { + my ($val, $inv) = @_; + return undef if $inv; + my $id = $val & 0xff00; + # Note: Metabones Smart Adapter firmware versions before 31 kill + # the high byte for 2-byte Canon LensType values, so the reported lens + # will be incorrect for these + my $mb = $metabonesID{$id}; + if ($mb) { + ref $mb or $id = $mb, $mb = $metabonesID{$id}; + require Image::ExifTool::Canon; + my $lens = $Image::ExifTool::Canon::canonLensTypes{$val - $id}; + return "$lens + $$mb" if $lens; + } elsif ($val >= 0x4900) { # test for Sigma MC-11 SA-E adapter with Sigma SA-mount lens + require Image::ExifTool::Sigma; + my $lens = $Image::ExifTool::Sigma::sigmaLensTypes{$val - 0x4900}; + return "$lens + MC-11 SA-E" if $lens; + } + return undef; + }, + 0 => 'Minolta AF 28-85mm F3.5-4.5 New', # New added (ref 13/18) + 1 => 'Minolta AF 80-200mm F2.8 HS-APO G', # white + 2 => 'Minolta AF 28-70mm F2.8 G', + 3 => 'Minolta AF 28-80mm F4-5.6', + 4 => 'Minolta AF 85mm F1.4G', #exiv2 0.23 + 5 => 'Minolta AF 35-70mm F3.5-4.5 [II]', # (original and II, ref 13) + 6 => 'Minolta AF 24-85mm F3.5-4.5 [New]', # (original and New, ref 13) + # 7 => 'AF 100-400mm F4.5-6.7 (D)', ?? + 7 => 'Minolta AF 100-300mm F4.5-5.6 APO [New] or 100-400mm or Sigma Lens', + 7.1 => 'Minolta AF 100-400mm F4.5-6.7 APO', #JD + 7.2 => 'Sigma AF 100-300mm F4 EX DG IF', #JD + 8 => 'Minolta AF 70-210mm F4.5-5.6 [II]', # (original and II, ref 13) + 9 => 'Minolta AF 50mm F3.5 Macro', + 10 => 'Minolta AF 28-105mm F3.5-4.5 [New]', # (original and New, ref 13) + 11 => 'Minolta AF 300mm F4 HS-APO G', + 12 => 'Minolta AF 100mm F2.8 Soft Focus', + 13 => 'Minolta AF 75-300mm F4.5-5.6 (New or II)', # (II and New, ref 13) + 14 => 'Minolta AF 100-400mm F4.5-6.7 APO', + 15 => 'Minolta AF 400mm F4.5 HS-APO G', + 16 => 'Minolta AF 17-35mm F3.5 G', + 17 => 'Minolta AF 20-35mm F3.5-4.5', + 18 => 'Minolta AF 28-80mm F3.5-5.6 II', + 19 => 'Minolta AF 35mm F1.4 G', # G added (ref 18), but not New as per ref 13 + 20 => 'Minolta/Sony 135mm F2.8 [T4.5] STF', + # 20 => 'Sony 135mm F2.8 [T4.5] STF (SAL135F28)', (ref JR) + 22 => 'Minolta AF 35-80mm F4-5.6 II', # II added (ref 13) + 23 => 'Minolta AF 200mm F4 Macro APO G', + 24 => 'Minolta/Sony AF 24-105mm F3.5-4.5 (D) or Sigma or Tamron Lens', + # 24 => 'Sony 24-105mm F3.5-4.5 (SAL24105)', (ref JR) + 24.1 => 'Sigma 18-50mm F2.8', + 24.2 => 'Sigma 17-70mm F2.8-4.5 (D)', + 24.3 => 'Sigma 20-40mm F2.8 EX DG Aspherical IF', #JD/22 + 24.4 => 'Sigma 18-200mm F3.5-6.3 DC', #22 + 24.5 => 'Sigma DC 18-125mm F4-5,6 D', #exiv2 0.23 + # 24.6 => 'Tamron SP AF 28-75mm F2.8 XR Di (IF) Macro', #JD + 24.6 => 'Tamron SP AF 28-75mm F2.8 XR Di LD Aspherical [IF] Macro', #NJ (Model A09) + 25 => 'Minolta AF 100-300mm F4.5-5.6 APO (D) or Sigma Lens', + 25.1 => 'Sigma 100-300mm F4 EX (APO (D) or D IF)', #JD + 25.2 => 'Sigma 70mm F2.8 EX DG Macro', #JD + 25.3 => 'Sigma 20mm F1.8 EX DG Aspherical RF', #19 + 25.4 => 'Sigma 30mm F1.4 EX DC', #21/27 + 25.5 => 'Sigma 24mm F1.8 EX DG ASP Macro', #Florian Knorn + # 25 - also seen for an "old Sigma 50mm Macro" (forum2833) + 27 => 'Minolta AF 85mm F1.4 G (D)', # added (D) (ref 13) + 28 => 'Minolta/Sony AF 100mm F2.8 Macro (D) or Tamron Lens', + # 28 => 'Sony 100mm F2.8 Macro (SAL100M28)', (ref 18/JR) + 28.1 => 'Tamron SP AF 90mm F2.8 Di Macro', #JD (Model 272E) + 28.2 => 'Tamron SP AF 180mm F3.5 Di LD [IF] Macro', #27 (Model B01) ("SP" moved - ref JR) + 29 => 'Minolta/Sony AF 75-300mm F4.5-5.6 (D)', # Sony added (ref 13) + # 29 => 'Sony 75-300mm F4.5-5.6 (SAL75300)', (ref JR) + 30 => 'Minolta AF 28-80mm F3.5-5.6 (D) or Sigma Lens', + 30.1 => 'Sigma AF 10-20mm F4-5.6 EX DC', #JD + 30.2 => 'Sigma AF 12-24mm F4.5-5.6 EX DG', + 30.3 => 'Sigma 28-70mm EX DG F2.8', #16 + 30.4 => 'Sigma 55-200mm F4-5.6 DC', #JD + 31 => 'Minolta/Sony AF 50mm F2.8 Macro (D) or F3.5', + # 31 => 'Sony 50mm F2.8 Macro (SAL50M28)', (ref JR) + 31.1 => 'Minolta/Sony AF 50mm F3.5 Macro', + 32 => 'Minolta/Sony AF 300mm F2.8 G or 1.5x Teleconverter', #13/18 + # 32 => 'Minolta AF 300mm F2.8 APO G (D) SSM', (ref 13) ("APO" added - ref JR) + # 32 => 'Sony 300mm F2.8 G (SAL300F28G)', (ref 18/JR) + 33 => 'Minolta/Sony AF 70-200mm F2.8 G', + # 33 => 'Sony 70-200mm F2.8 G (SAL70200G)', (ref JR) + # 33 => 'Minolta AF 70-200mm F2.8 APO G (D) SSM' (ref 13) ("APO" added - ref JR) + 35 => 'Minolta AF 85mm F1.4 G (D) Limited', + 36 => 'Minolta AF 28-100mm F3.5-5.6 (D)', + 38 => 'Minolta AF 17-35mm F2.8-4 (D)', # (Konica Minolta, ref 13) + 39 => 'Minolta AF 28-75mm F2.8 (D)', # (Konica Minolta, ref 13) + 40 => 'Minolta/Sony AF DT 18-70mm F3.5-5.6 (D)', # (Konica Minolta, ref 13) + # 40 => 'Sony DT 18-70mm F3.5-5.6 (SAL1870)', (ref JR) + #40.1 => 'Sony AF DT 18-200mm F3.5-6.3', #11 (anomaly? - PH) + 41 => 'Minolta/Sony AF DT 11-18mm F4.5-5.6 (D) or Tamron Lens', # (Konica Minolta, ref 13) + # 41 => 'Sony DT 11-18mm F4.5-5.6 (SAL1118)', (ref JR) + 41.1 => 'Tamron SP AF 11-18mm F4.5-5.6 Di II LD Aspherical IF', #JD (Model A13) + 42 => 'Minolta/Sony AF DT 18-200mm F3.5-6.3 (D)', # Sony added (ref 13) (Konica Minolta, ref 13) + # 42 => 'Sony DT 18-200mm F3.5-6.3 (SAL18200)', (ref JR) + 43 => 'Sony 35mm F1.4 G (SAL35F14G)', # changed from Minolta to Sony (ref 13/18/JR) (but ref 11 shows both!) + 44 => 'Sony 50mm F1.4 (SAL50F14)', # changed from Minolta to Sony (ref 13/18/JR) + 45 => 'Carl Zeiss Planar T* 85mm F1.4 ZA (SAL85F14Z)', #JR + 46 => 'Carl Zeiss Vario-Sonnar T* DT 16-80mm F3.5-4.5 ZA (SAL1680Z)', #JR + 47 => 'Carl Zeiss Sonnar T* 135mm F1.8 ZA (SAL135F18Z)', #JR + 48 => 'Carl Zeiss Vario-Sonnar T* 24-70mm F2.8 ZA SSM (SAL2470Z) or ZA SSM II', #11/JR + 48.1 => 'Carl Zeiss Vario-Sonnar T* 24-70mm F2.8 ZA SSM II (SAL2470Z2)', #JR + 49 => 'Sony DT 55-200mm F4-5.6 (SAL55200)', #JD/JR + 50 => 'Sony DT 18-250mm F3.5-6.3 (SAL18250)', #11/JR + 51 => 'Sony DT 16-105mm F3.5-5.6 (SAL16105)', #11/JR + #51.1 => 'Sony AF DT 55-200mm F4-5.5', #11 (anomaly? - PH) + 52 => 'Sony 70-300mm F4.5-5.6 G SSM (SAL70300G) or G SSM II or Tamron Lens', #JD + 52.1 => 'Sony 70-300mm F4.5-5.6 G SSM II (SAL70300G2)', #JR + 52.2 => 'Tamron SP 70-300mm F4-5.6 Di USD', #JR,NJ (Model A005) + 53 => 'Sony 70-400mm F4-5.6 G SSM (SAL70400G)', #17(/w correction by Stephen Bishop)/JR + 54 => 'Carl Zeiss Vario-Sonnar T* 16-35mm F2.8 ZA SSM (SAL1635Z) or ZA SSM II', #17/JR + 54.1 => 'Carl Zeiss Vario-Sonnar T* 16-35mm F2.8 ZA SSM II (SAL1635Z2)', #JR + 55 => 'Sony DT 18-55mm F3.5-5.6 SAM (SAL1855) or SAM II', #PH + 55.1 => 'Sony DT 18-55mm F3.5-5.6 SAM II (SAL18552)', #JR + 56 => 'Sony DT 55-200mm F4-5.6 SAM (SAL55200-2)', #22/JR + 57 => 'Sony DT 50mm F1.8 SAM (SAL50F18) or Tamron Lens or Commlite CM-EF-NEX adapter', #22/JR + 57.1 => 'Tamron SP AF 60mm F2 Di II LD [IF] Macro 1:1', # (Model G005) (ref http://u88.n24.queensu.ca/exiftool/forum/index.php/topic,3858.0.html) + 57.2 => 'Tamron 18-270mm F3.5-6.3 Di II PZD', #27 (Model B008) + # (note: the Commlite CM-EF-NEX adapter also appears to give LensType 57, ref JR) + 58 => 'Sony DT 30mm F2.8 Macro SAM (SAL30M28)', #22/JR + 59 => 'Sony 28-75mm F2.8 SAM (SAL2875)', #21/JR + 60 => 'Carl Zeiss Distagon T* 24mm F2 ZA SSM (SAL24F20Z)', #17/JR + 61 => 'Sony 85mm F2.8 SAM (SAL85F28)', #17/JR + 62 => 'Sony DT 35mm F1.8 SAM (SAL35F18)', #PH/JR + 63 => 'Sony DT 16-50mm F2.8 SSM (SAL1650)', #17/JR + 64 => 'Sony 500mm F4 G SSM (SAL500F40G)', #29 + 65 => 'Sony DT 18-135mm F3.5-5.6 SAM (SAL18135)', #JR + 66 => 'Sony 300mm F2.8 G SSM II (SAL300F28G2)', #29 + 67 => 'Sony 70-200mm F2.8 G SSM II (SAL70200G2)', #JR + 68 => 'Sony DT 55-300mm F4.5-5.6 SAM (SAL55300)', #29 + 69 => 'Sony 70-400mm F4-5.6 G SSM II (SAL70400G2)', #JR + 70 => 'Carl Zeiss Planar T* 50mm F1.4 ZA SSM (SAL50F14Z)', #JR + 128 => 'Tamron or Sigma Lens (128)', + 128.1 => 'Tamron AF 18-200mm F3.5-6.3 XR Di II LD Aspherical [IF] Macro', #JR (Model A14) + # was 128.1 => 'Tamron 18-200mm F3.5-6.3', + 128.2 => 'Tamron AF 28-300mm F3.5-6.3 XR Di LD Aspherical [IF] Macro', #JR (Model A061) + # was 128.2 => 'Tamron 28-300mm F3.5-6.3', + 128.3 => 'Tamron 80-300mm F3.5-6.3', + 128.4 => 'Tamron AF 28-200mm F3.8-5.6 XR Di Aspherical [IF] Macro', #JD (Model A031) + # also Tamron AF 28-200mm F3.8-5.6 Aspherical', #IB (Model 71D) + # and 'Tamron AF 28-200mm F3.8-5.6 LD Aspherical [IF] Super', #IB (Model 171D) + 128.5 => 'Tamron SP AF 17-35mm F2.8-4 Di LD Aspherical IF', #JD (Model A05) + 128.6 => 'Sigma AF 50-150mm F2.8 EX DC APO HSM II', #JD + 128.7 => 'Sigma 10-20mm F3.5 EX DC HSM', #11 (Model 202-205) + 128.8 => 'Sigma 70-200mm F2.8 II EX DG APO MACRO HSM', #24 + 128.9 => 'Sigma 10mm F2.8 EX DC HSM Fisheye', #Florian Knorn + # (yes, '128.10'. My condolences to typed languages that use this database - PH) + '128.10' => 'Sigma 50mm F1.4 EX DG HSM', #Florian Knorn (Model A014, ref IB) + '128.11' => 'Sigma 85mm F1.4 EX DG HSM', #27 + '128.12' => 'Sigma 24-70mm F2.8 IF EX DG HSM', #27 + '128.13' => 'Sigma 18-250mm F3.5-6.3 DC OS HSM', #27 + '128.14' => 'Sigma 17-50mm F2.8 EX DC HSM', #Exiv2 + '128.15' => 'Sigma 17-70mm F2.8-4 DC Macro HSM', #JR (OS Model C013, ref IB) + '128.16' => 'Sigma 150mm F2.8 EX DG OS HSM APO Macro', #Marcus Holland-Moritz + '128.17' => 'Sigma 150-500mm F5-6.3 APO DG OS HSM', #IB + '128.18' => 'Tamron AF 28-105mm F4-5.6 [IF]', #IB (Model 179D) + '128.19' => 'Sigma 35mm F1.4 DG HSM', #JR + '128.20' => 'Sigma 18-35mm F1.8 DC HSM', #JR (Model A013, ref IB) + '128.21' => 'Sigma 50-500mm F4.5-6.3 APO DG OS HSM', #JR + '128.22' => 'Sigma 24-105mm F4 DG HSM | A', #JR (013) + '128.23' => 'Sigma 30mm F1.4', #IB + '128.24' => 'Sigma 35mm F1.4 DG HSM | A', #IB/JR (012) + '128.25' => 'Sigma 105mm F2.8 EX DG OS HSM Macro', #IB + '128.26' => 'Sigma 180mm F2.8 EX DG OS HSM APO Macro', #IB + '128.27' => 'Sigma 18-300mm F3.5-6.3 DC Macro HSM | C', #IB/JR (014) + '128.28' => 'Sigma 18-50mm F2.8-4.5 DC HSM', #IB + 129 => 'Tamron Lens (129)', + 129.1 => 'Tamron 200-400mm F5.6 LD', #12 (LD ref 23) + 129.2 => 'Tamron 70-300mm F4-5.6 LD', #12 + 131 => 'Tamron 20-40mm F2.7-3.5 SP Aspherical IF', #23 (Model 266D) + 135 => 'Vivitar 28-210mm F3.5-5.6', #16 + 136 => 'Tokina EMZ M100 AF 100mm F3.5', #JD + 137 => 'Cosina 70-210mm F2.8-4 AF', #11 + 138 => 'Soligor 19-35mm F3.5-4.5', #11 + 139 => 'Tokina AF 28-300mm F4-6.3', #IB + 142 => 'Voigtlander 70-300mm F4.5-5.6', #JD + 146 => 'Voigtlander Macro APO-Lanthar 125mm F2.5 SL', #JD + 194 => 'Tamron SP AF 17-50mm F2.8 XR Di II LD Aspherical [IF]', #23 (Model A16) + 202 => 'Tamron SP AF 70-200mm F2.8 Di LD [IF] Macro', #JR (Model A001) (see also 255.7) + 203 => 'Tamron SP 70-200mm F2.8 Di USD', #JR (Model A009) + 204 => 'Tamron SP 24-70mm F2.8 Di USD', #JR (Model A007) + 212 => 'Tamron 28-300mm F3.5-6.3 Di PZD', #JR (Model A010) + 213 => 'Tamron 16-300mm F3.5-6.3 Di II PZD Macro', #JR (Model B016) + 214 => 'Tamron SP 150-600mm F5-6.3 Di USD', #JR (Model A011) + 215 => 'Tamron SP 15-30mm F2.8 Di USD', #JR (Model A012) + 216 => 'Tamron SP 45mm F1.8 Di USD', #forum8320 (F013) + 217 => 'Tamron SP 35mm F1.8 Di USD', #forum8320 (F012) + 218 => 'Tamron SP 90mm F2.8 Di Macro 1:1 USD (F017)', #JR (Model F017) + 220 => 'Tamron SP 150-600mm F5-6.3 Di USD G2', #forum8846 (Model A022) + 224 => 'Tamron SP 90mm F2.8 Di Macro 1:1 USD (F004)', #JR (Model F004) + 255 => 'Tamron Lens (255)', + 255.1 => 'Tamron SP AF 17-50mm F2.8 XR Di II LD Aspherical', # (Model A16) + 255.2 => 'Tamron AF 18-250mm F3.5-6.3 XR Di II LD', #JD (Model A18?) + #? 225.2 => 'Tamron AF 18-250mm F3.5-6.3 Di II LD Aspherical [IF] Macro', #JR (Model A18) + 255.3 => 'Tamron AF 55-200mm F4-5.6 Di II LD Macro', # (Model A15) (added "LD Macro", ref 23) + 255.4 => 'Tamron AF 70-300mm F4-5.6 Di LD Macro 1:2', # (Model A17) + 255.5 => 'Tamron SP AF 200-500mm F5.0-6.3 Di LD IF', # (Model A08) + 255.6 => 'Tamron SP AF 10-24mm F3.5-4.5 Di II LD Aspherical IF', #22 (Model B001) + 255.7 => 'Tamron SP AF 70-200mm F2.8 Di LD IF Macro', #22 (Model A001) + 255.8 => 'Tamron SP AF 28-75mm F2.8 XR Di LD Aspherical IF', #24 (Model A09) + 255.9 => 'Tamron AF 90-300mm F4.5-5.6 Telemacro', #Fredrik Agert + 18688 => 'Sigma MC-11 SA-E Mount Converter with not-supported Sigma lens', + # The MC-11 SA-E Mount Converter uses this 18688 offset for not-supported SIGMA mount lenses. + # The MC-11 EF-E Mount Converter uses the 61184 offset for not-supported CANON mount lenses, as also used by Metabones. + # Both MC-11 SA-E and EF-E Mount Converters use the 504xx LensType2 values for supported SA-mount or EF-mount Sigma lenses. + 25501 => 'Minolta AF 50mm F1.7', #7 + 25511 => 'Minolta AF 35-70mm F4 or Other Lens', + 25511.1 => 'Sigma UC AF 28-70mm F3.5-4.5', #12/16(HighSpeed-AF) + 25511.2 => 'Sigma AF 28-70mm F2.8', #JD + 25511.3 => 'Sigma M-AF 70-200mm F2.8 EX Aspherical', #12 + 25511.4 => 'Quantaray M-AF 35-80mm F4-5.6', #JD + 25511.5 => 'Tokina 28-70mm F2.8-4.5 AF', #IB + 25521 => 'Minolta AF 28-85mm F3.5-4.5 or Other Lens', # not New (ref 18) + 25521.1 => 'Tokina 19-35mm F3.5-4.5', #3 + 25521.2 => 'Tokina 28-70mm F2.8 AT-X', #7 + 25521.3 => 'Tokina 80-400mm F4.5-5.6 AT-X AF II 840', #JD + 25521.4 => 'Tokina AF PRO 28-80mm F2.8 AT-X 280', #JD + 25521.5 => 'Tokina AT-X PRO [II] AF 28-70mm F2.6-2.8 270', #24 (original + II versions) + 25521.6 => 'Tamron AF 19-35mm F3.5-4.5', #JD (Model A10) + 25521.7 => 'Angenieux AF 28-70mm F2.6', #JD + 25521.8 => 'Tokina AT-X 17 AF 17mm F3.5', #27 + 25521.9 => 'Tokina 20-35mm F3.5-4.5 II AF', #IB + 25531 => 'Minolta AF 28-135mm F4-4.5 or Sigma Lens', + 25531.1 => 'Sigma ZOOM-alpha 35-135mm F3.5-4.5', #16 + 25531.2 => 'Sigma 28-105mm F2.8-4 Aspherical', #JD + 25531.3 => 'Sigma 28-105mm F4-5.6 UC', #JR + 25541 => 'Minolta AF 35-105mm F3.5-4.5', #13 + 25551 => 'Minolta AF 70-210mm F4 Macro or Sigma Lens', + 25551.1 => 'Sigma 70-210mm F4-5.6 APO', #7 + 25551.2 => 'Sigma M-AF 70-200mm F2.8 EX APO', #6 + 25551.3 => 'Sigma 75-200mm F2.8-3.5', #22 + 25561 => 'Minolta AF 135mm F2.8', + 25571 => 'Minolta/Sony AF 28mm F2.8', # Sony added (ref 18) + # 25571 => 'Sony 28mm F2.8 (SAL28F28)', (ref 18/JR) + 25581 => 'Minolta AF 24-50mm F4', + 25601 => 'Minolta AF 100-200mm F4.5', + 25611 => 'Minolta AF 75-300mm F4.5-5.6 or Sigma Lens', #13 + 25611.1 => 'Sigma 70-300mm F4-5.6 DL Macro', #12 (also DG version ref 27, and APO version ref JR) + 25611.2 => 'Sigma 300mm F4 APO Macro', #3/7 + 25611.3 => 'Sigma AF 500mm F4.5 APO', #JD + 25611.4 => 'Sigma AF 170-500mm F5-6.3 APO Aspherical', #JD + 25611.5 => 'Tokina AT-X AF 300mm F4', #JD + 25611.6 => 'Tokina AT-X AF 400mm F5.6 SD', #22 + 25611.7 => 'Tokina AF 730 II 75-300mm F4.5-5.6', #JD + 25611.8 => 'Sigma 800mm F5.6 APO', #http://u88.n24.queensu.ca/exiftool/forum/index.php/topic,3472.0.html + 25611.9 => 'Sigma AF 400mm F5.6 APO Macro', #27 + '25611.10' => 'Sigma 1000mm F8 APO', #JR + 25621 => 'Minolta AF 50mm F1.4 [New]', # original and New, not Sony (ref 13/18) + 25631 => 'Minolta AF 300mm F2.8 APO or Sigma Lens', # changed G to APO (ref 13) + 25631.1 => 'Sigma AF 50-500mm F4-6.3 EX DG APO', #JD + 25631.2 => 'Sigma AF 170-500mm F5-6.3 APO Aspherical', #JD (also DG version, ref 27) + 25631.3 => 'Sigma AF 500mm F4.5 EX DG APO', #JD + 25631.4 => 'Sigma 400mm F5.6 APO', #22 + 25641 => 'Minolta AF 50mm F2.8 Macro or Sigma Lens', + 25641.1 => 'Sigma 50mm F2.8 EX Macro', #11 + 25651 => 'Minolta AF 600mm F4 APO', # ("APO" added - ref JR) + 25661 => 'Minolta AF 24mm F2.8 or Sigma Lens', + 25661.1 => 'Sigma 17-35mm F2.8-4 EX Aspherical', #http://u88.n24.queensu.ca/exiftool/forum/index.php/topic,3789.msg17679.html#msg17679 + 25721 => 'Minolta/Sony AF 500mm F8 Reflex', + # 25721 => 'Sony 500mm F8 Reflex (SAL500F80)', (ref JR) + 25781 => 'Minolta/Sony AF 16mm F2.8 Fisheye or Sigma Lens', # Sony added (ref 13/18) + # 25781 => 'Sony 16mm F2.8 Fisheye (SAL16F28)', (ref 18/JR) + 25781.1 => 'Sigma 8mm F4 EX [DG] Fisheye', + 25781.2 => 'Sigma 14mm F3.5', + 25781.3 => 'Sigma 15mm F2.8 Fisheye', #JD (writes 16mm to EXIF) + 25791 => 'Minolta/Sony AF 20mm F2.8 or Tokina Lens', # Sony added (ref 11) + # 25791 => 'Sony 20mm F2.8 (SAL20F28)', (ref JR) + 25791.1 => 'Tokina AT-X Pro DX 11-16mm F2.8', #http://u88.n24.queensu.ca/exiftool/forum/index.php/topic,3593.0.html + 25811 => 'Minolta AF 100mm F2.8 Macro [New] or Sigma or Tamron Lens', # not Sony (ref 13/18) + 25811.1 => 'Sigma AF 90mm F2.8 Macro', #JD + 25811.2 => 'Sigma AF 105mm F2.8 EX [DG] Macro', #JD + 25811.3 => 'Sigma 180mm F5.6 Macro', + 25811.4 => 'Sigma 180mm F3.5 EX DG Macro', #http://u88.n24.queensu.ca/exiftool/forum/index.php/topic,3789.msg17679.html#msg17679 + 25811.5 => 'Tamron 90mm F2.8 Macro', + 25851 => 'Beroflex 35-135mm F3.5-4.5', #16 + 25858 => 'Minolta AF 35-105mm F3.5-4.5 New or Tamron Lens', + 25858.1 => 'Tamron 24-135mm F3.5-5.6', # (Model 190D) + 25881 => 'Minolta AF 70-210mm F3.5-4.5', + 25891 => 'Minolta AF 80-200mm F2.8 APO or Tokina Lens', # black + 25891.1 => 'Tokina 80-200mm F2.8', + # 25901 - Note: only get this with older 1.4x and lenses with 5-digit LensTypes (ref 27) + # 25901 - also "Minolta AF 200mm F2.8 HS-APO G + Minolta AF 1.4x APO" + 25901 => 'Minolta AF 200mm F2.8 G APO + Minolta AF 1.4x APO or Other Lens + 1.4x', #26 + 25901.1 => 'Minolta AF 600mm F4 HS-APO G + Minolta AF 1.4x APO', #27 + 25911 => 'Minolta AF 35mm F1.4', #(from Sony list) (not G as per ref 13) + 25921 => 'Minolta AF 85mm F1.4 G (D)', + 25931 => 'Minolta AF 200mm F2.8 APO', # (not "G", see 26121 - ref JR) + 25941 => 'Minolta AF 3x-1x F1.7-2.8 Macro', + 25961 => 'Minolta AF 28mm F2', + 25971 => 'Minolta AF 35mm F2 [New]', #13 + 25981 => 'Minolta AF 100mm F2', + # 26011 - Note: only get this with older 2x and lenses with 5-digit LensTypes (ref 27) + # 26011 - also "Minolta AF 200mm F2.8 HS-APO G + Minolta AF 2x APO" + 26011 => 'Minolta AF 200mm F2.8 G APO + Minolta AF 2x APO or Other Lens + 2x', #26 + 26011.1 => 'Minolta AF 600mm F4 HS-APO G + Minolta AF 2x APO', #27 + 26041 => 'Minolta AF 80-200mm F4.5-5.6', + 26051 => 'Minolta AF 35-80mm F4-5.6', #(from Sony list) + 26061 => 'Minolta AF 100-300mm F4.5-5.6', # not (D) (ref 13/18) + 26071 => 'Minolta AF 35-80mm F4-5.6', #13 + 26081 => 'Minolta AF 300mm F2.8 HS-APO G', # HS-APO added (ref 13/18) + 26091 => 'Minolta AF 600mm F4 HS-APO G', + 26121 => 'Minolta AF 200mm F2.8 HS-APO G', + 26131 => 'Minolta AF 50mm F1.7 New', + 26151 => 'Minolta AF 28-105mm F3.5-4.5 xi', # xi, not Power Zoom (ref 13/18) + 26161 => 'Minolta AF 35-200mm F4.5-5.6 xi', # xi, not Power Zoom (ref 13/18) + 26181 => 'Minolta AF 28-80mm F4-5.6 xi', # xi, not Power Zoom (ref 13/18) + 26191 => 'Minolta AF 80-200mm F4.5-5.6 xi', # xi, not Power Zoom (ref 13/18) + 26201 => 'Minolta AF 28-70mm F2.8 G', #11 + 26211 => 'Minolta AF 100-300mm F4.5-5.6 xi', # xi, not Power Zoom (ref 13/18) + 26241 => 'Minolta AF 35-80mm F4-5.6 Power Zoom', + 26281 => 'Minolta AF 80-200mm F2.8 HS-APO G', #11 ("HS-APO" added, white, probably same as 1, non-HS is 25891 - ref JR) + 26291 => 'Minolta AF 85mm F1.4 New', + 26311 => 'Minolta/Sony AF 100-300mm F4.5-5.6 APO', #11 + 26321 => 'Minolta AF 24-50mm F4 New', + 26381 => 'Minolta AF 50mm F2.8 Macro New', + 26391 => 'Minolta AF 100mm F2.8 Macro', + 26411 => 'Minolta/Sony AF 20mm F2.8 New', # Sony added (ref 13) + 26421 => 'Minolta AF 24mm F2.8 New', + 26441 => 'Minolta AF 100-400mm F4.5-6.7 APO', #11 + 26621 => 'Minolta AF 50mm F1.4 New', + 26671 => 'Minolta AF 35mm F2 New', + 26681 => 'Minolta AF 28mm F2 New', + 26721 => 'Minolta AF 24-105mm F3.5-4.5 (D)', #11 + # 30464: newer firmware versions of the Speed Booster report type 30464 (=0x7700) + # - this is the base to which the Canon LensType is added + 30464 => 'Metabones Canon EF Speed Booster', #Metabones (to this, add Canon LensType) + 45671 => 'Tokina 70-210mm F4-5.6', #22 + 45701 => 'Tamron AF 35-135mm F3.5-4.5', #IB (model 40d) + 45711 => 'Vivitar 70-210mm F4.5-5.6', #IB + 45741 => '2x Teleconverter or Tamron or Tokina Lens', #18 + 45741.1 => 'Tamron SP AF 90mm F2.5', #JD + 45741.2 => 'Tokina RF 500mm F8.0 x2', #JD + 45741.3 => 'Tokina 300mm F2.8 x2', + 45751 => '1.4x Teleconverter', #18 + 45851 => 'Tamron SP AF 300mm F2.8 LD IF', #11 + 45861 => 'Tamron SP AF 35-105mm F2.8 LD Aspherical IF', #Fredrik Agert + 45871 => 'Tamron AF 70-210mm F2.8 SP LD', #Fabio Suprani + # 48128: the Speed Booster Ultra appears to report type 48128 (=0xbc00) + # - this is the base to which the Canon LensType is added + 48128 => 'Metabones Canon EF Speed Booster Ultra', #JR (to this, add Canon LensType) + # 61184: older firmware versions of both the Speed Booster and the Smart Adapter + # report type 61184 (=0xef00), and add only the lower byte of the Canon LensType (ref JR). + # For newer firmware versions this is only used by the Smart Adapter, and + # the full Canon LensType code is added - PH + # the metabones adapter translates Canon L -> G, II -> II, USM -> SSM, IS -> OSS (ref JR) + # This offset is used by Metabones, Fotodiox, Sigma MC-11 EF-E and Viltrox Canon EF adapters. + 61184 => 'Canon EF Adapter', #JR (to this, add Canon LensType) + # 65280 = 0xff00 + 65280 => 'Sigma 16mm F2.8 Filtermatic Fisheye', #IB + # all M42-type lenses give a value of 65535 (and FocalLength=0, FNumber=1) + 65535 => 'E-Mount, T-Mount, Other Lens or no lens', #JD/JR +# +# Sony E-type lenses (NOTE: these should be kept in sync with %sonyLensTypes2 of Sony.pm) +# + 65535.1 => 'Sony E 16mm F2.8', #PH (32784 - SEL16F28) + 65535.2 => 'Sony E 18-55mm F3.5-5.6 OSS', #PH (32785 - SEL1855) + 65535.3 => 'Sony E 55-210mm F4.5-6.3 OSS', #PH (32786 - SEL55210) + 65535.4 => 'Sony E 18-200mm F3.5-6.3 OSS', #PH (32787 - SEL18200) + 65535.5 => 'Sony E 30mm F3.5 Macro', #JR (32788 - SEL30M35) + 65535.6 => 'Sony E 24mm F1.8 ZA', #PH (32789 - SEL24F18Z) + 65535.7 => 'Sony E 50mm F1.8 OSS', #PH (32790 - SEL50F18) + 65535.8 => 'Sony E 16-70mm F4 ZA OSS', #JR (32791 - SEL1670Z) + 65535.9 => 'Sony E 10-18mm F4 OSS', #PH (32792 - SEL1018) + '65535.10' => 'Sony E PZ 16-50mm F3.5-5.6 OSS', #PH (32793 - SELP1650) + '65535.11' => 'Sony FE 35mm F2.8 ZA', #JR (32794 - SEL35F28Z) + '65535.12' => 'Sony FE 24-70mm F4 ZA OSS', #JR (32795 - SEL2470Z) + '65535.13' => 'Sony FE 85mm F1.8', #JR (32796 - SEL85F18) + '65535.14' => 'Sony E 18-200mm F3.5-6.3 OSS LE', #JR (32797 or 0 - SEL18200LE) + '65535.15' => 'Sony E 20mm F2.8', #PH (32798 - SEL20F28) + '65535.16' => 'Sony E 35mm F1.8 OSS', #JR (32799 - SEL35F18) + '65535.17' => 'Sony E PZ 18-105mm F4 G OSS', #JR (32800 - SELP18105G) + '65535.18' => 'Sony FE 12-24mm F4 G', #JR (32801 - SEL1224G) + '65535.19' => 'Sony FE 90mm F2.8 Macro G OSS', #JR (32802 - SEL90M28G) + '65535.20' => 'Sony E 18-50mm F4-5.6', #JR (32803 - SEL1850) + '65535.21' => 'Sony FE 24mm F1.4 GM', #IB (32804 - SEL24F14GM) + '65535.22' => 'Sony FE 24-105mm F4 G OSS', #IB (32805 - SEL24105G) + '65535.23' => 'Sony E PZ 18-200mm F3.5-6.3 OSS', #JR (32807 - SELP18200) + '65535.24' => 'Sony FE 55mm F1.8 ZA', #JR (32808 - SEL55F18Z) + '65535.25' => 'Sony FE 70-200mm F4 G OSS', #JR (32810 - SEL70200G) + '65535.26' => 'Sony FE 16-35mm F4 ZA OSS', #JR (32811 - SEL1635Z) + '65535.27' => 'Sony FE 50mm F2.8 Macro', #JR (32812 - SEL50M28) + '65535.28' => 'Sony FE 28-70mm F3.5-5.6 OSS', #JR (32813 - SEL2870) + '65535.29' => 'Sony FE 35mm F1.4 ZA', #JR (32814 - SEL35F14Z) + '65535.30' => 'Sony FE 24-240mm F3.5-6.3 OSS', #JR (32815 - SEL24240) + '65535.31' => 'Sony FE 28mm F2', #JR (32816 - SEL28F20) + '65535.32' => 'Sony FE PZ 28-135mm F4 G OSS', #JR (32817 - SELP28135G) + '65535.33' => 'Sony FE 100mm F2.8 STF GM OSS', #JR (32819 - SEL100F28GM, uses 33076 when set to 0.57m - 1.0m range) + '65535.34' => 'Sony E PZ 18-110mm F4 G OSS', #JR (32820 - SELP18110G) + '65535.35' => 'Sony FE 24-70mm F2.8 GM', #JR (32821 - SEL2470GM) + '65535.36' => 'Sony FE 50mm F1.4 ZA', #JR (32822 - SEL50F14Z) + '65535.37' => 'Sony FE 85mm F1.4 GM', #JR (32823 - SEL85F14GM) + '65535.38' => 'Sony FE 50mm F1.8', #JR (32824 - SEL50F18F with trailing "F" as compared to 32790) + '65535.39' => 'Sony FE 21mm F2.8 (SEL28F20 + SEL075UWC)', #JR (32826 - SEL28F20 + SEL075UWC Ultra-wide converter) + '65535.40' => 'Sony FE 16mm F3.5 Fisheye (SEL28F20 + SEL057FEC)', #JR (32827 - SEL28F20 + SEL057FEC Fisheye converter) + '65535.41' => 'Sony FE 70-300mm F4.5-5.6 G OSS', #JR (32828 - SEL70300G) + '65535.42' => 'Sony FE 100-400mm F4.5-5.6 GM OSS', #JR (32829 - SEL100400GM) + '65535.43' => 'Sony FE 70-200mm F2.8 GM OSS', #JR (32830 - SEL70200GM) + '65535.44' => 'Sony FE 16-35mm F2.8 GM', #JR (32831 - SEL1635GM) + '65535.45' => 'Sony FE 400mm F2.8 GM OSS', #IB (32848 - SEL400F28GM) + '65535.46' => 'Sony E 18-135mm F3.5-5.6 OSS', #JR (32849 - SEL18135) + '65535.47' => 'Sony FE 135mm F1.8 GM', #IB (32850 - SEL135F18GM) + '65535.48' => 'Sony FE 70-200mm F2.8 GM OSS + 1.4X Teleconverter', #JR (33072 - SEL70200GM + SEL14TC) + '65535.49' => 'Sony FE 70-200mm F2.8 GM OSS + 2X Teleconverter', #JR (33073 - SEL70200GM + SEL20TC) + '65535.50' => 'Sony FE 100-400mm F4.5-5.6 GM OSS + 1.4X Teleconverter', #JR (33077 - SEL100400GM + SEL14TC) + '65535.51' => 'Sony FE 100-400mm F4.5-5.6 GM OSS + 2X Teleconverter', #JR (33078 - SEL100400GM + SEL20TC) + '65535.52' => 'Sony FE 400mm F2.8 GM OSS + 1.4X Teleconverter', #IB (33079 - SEL400F28GM + SEL14TC) + '65535.53' => 'Sony FE 400mm F2.8 GM OSS + 2X Teleconverter', #JR (33080 - SEL400F28GM + SEL20TC) +# +# 3rd party E lenses +# + '65535.54' => 'Samyang AF 50mm F1.4 FE', #JR (32789) + '65535.55' => 'Samyang AF 14mm F2.8 FE', #JR (32790 and 51505) + '65535.56' => 'Samyang AF 24mm F2.8', #JR (32794) + '65535.57' => 'Samyang AF 35mm F2.8 FE', #PH (51505) + '65535.58' => 'Samyang AF 35mm F1.4', #IB (51507) + '65535.59' => 'Sigma 19mm F2.8 [EX] DN', #JR (0) + '65535.60' => 'Sigma 30mm F2.8 [EX] DN', #JR (0) + '65535.61' => 'Sigma 60mm F2.8 DN', #JR (0) + '65535.62' => 'Sigma 30mm F1.4 DC DN | C', #IB (50480) (016) + '65535.63' => 'Sigma 85mm F1.4 DG HSM | A', #JR (50499) (018) + '65535.64' => 'Sigma 16mm F1.4 DC DN | C', #JR (50503) (017) + '65535.65' => 'Sigma 105mm F1.4 DG HSM | A', #IB (50507) (018) + '65535.66' => 'Sigma 56mm F1.4 DC DN | C', #JR (50508) (018) + '65535.67' => 'Sigma 70-200mm F2.8 DG OS HSM | S',#IB (50512) (018) + '65535.68' => 'Sigma 70mm F2.8 DG MACRO | A', #JR (50513) (018) + '65535.69' => 'Tamron 18-200mm F3.5-6.3 Di III VC', #JR (0 - Model B011) + '65535.70' => 'Tamron 28-75mm F2.8 Di III RXD', #JR (49457 - Model A036) + '65535.71' => 'Tokina Firin 20mm F2 FE MF', #JR (0) + '65535.72' => 'Voigtlander SUPER WIDE-HELIAR 15mm F4.5 III', #JR (50992) + '65535.73' => 'Voigtlander HELIAR-HYPER WIDE 10mm F5.6', #IB (50993) + '65535.74' => 'Voigtlander ULTRA WIDE-HELIAR 12mm F5.6 III', #IB (50994) + '65535.75' => 'Voigtlander MACRO APO-LANTHAR 65mm F2 Aspherical', #JR (50995) + '65535.76' => 'Voigtlander NOKTON 40mm F1.2 Aspherical', #JR (50996) + '65535.77' => 'Voigtlander NOKTON classic 35mm F1.4', #JR (50997) + '65535.78' => 'Voigtlander MACRO APO-LANTHAR 110mm F2.5', #JR (50998) + '65535.79' => 'Voigtlander COLOR-SKOPAR 21mm F3.5 Aspherical', #IB (50999) + '65535.80' => 'Voigtlander NOKTON 50mm F1.2 Aspherical', #IB (51000) + '65535.81' => 'Zeiss Touit 12mm F2.8', #JR (49201 or 0) + '65535.82' => 'Zeiss Touit 32mm F1.8', #JR (49202 or 0) + '65535.83' => 'Zeiss Touit 50mm F2.8 Macro', #JR (49203 or 0) + '65535.84' => 'Zeiss Batis 25mm F2', #JR (49216) + '65535.85' => 'Zeiss Batis 85mm F1.8', #JR (49217) + '65535.86' => 'Zeiss Batis 18mm F2.8', #IB (49218) + '65535.87' => 'Zeiss Batis 135mm F2.8', #IB (49219) + '65535.88' => 'Zeiss Batis 40mm F2 CF', #JR (49220) + '65535.89' => 'Zeiss Loxia 50mm F2', #JR (49232 or 0) + '65535.90' => 'Zeiss Loxia 35mm F2', #JR (49233 or 0) + '65535.91' => 'Zeiss Loxia 21mm F2.8', #JR (49234) + '65535.92' => 'Zeiss Loxia 85mm F2.4', #JR (49235) + '65535.93' => 'Zeiss Loxia 25mm F2.4', #JR (49236) +# +# other lenses +# + '65535.94' => 'Arax MC 35mm F2.8 Tilt+Shift', #JD + '65535.95' => 'Arax MC 80mm F2.8 Tilt+Shift', #JD + '65535.96' => 'Zenitar MF 16mm F2.8 Fisheye M42', #JD + '65535.97' => 'Samyang 500mm Mirror F8.0', #19 + '65535.98' => 'Pentacon Auto 135mm F2.8', #19 + '65535.99' => 'Pentacon Auto 29mm F2.8', #19 + '65535.100' => 'Helios 44-2 58mm F2.0', #19 +); + +%minoltaTeleconverters = ( + 0x00 => 'None', + 0x04 => 'Minolta/Sony AF 1.4x APO (D) (0x04)', # (Andy Johnson, A77 APO and APO D) + 0x05 => 'Minolta/Sony AF 2x APO (D) (0x05)', # (Andy Johnson, A77 APO D) + 0x48 => 'Minolta/Sony AF 2x APO (D)', + # 0x48 => 'Sony 2x Teleconverter (SAL20TC)', (ref JR) + 0x50 => 'Minolta AF 2x APO II', + 0x60 => 'Minolta AF 2x APO',#26 + 0x88 => 'Minolta/Sony AF 1.4x APO (D)', + # 0x88 => 'Sony 1.4x Teleconverter (SAL14TC)', (ref JR) + 0x90 => 'Minolta AF 1.4x APO II', + 0xa0 => 'Minolta AF 1.4x APO',#26 +); + +%minoltaColorMode = ( + 0 => 'Natural color', + 1 => 'Black & White', + 2 => 'Vivid color', + 3 => 'Solarization', + 4 => 'Adobe RGB', + 5 => 'Sepia', #10 + 9 => 'Natural', #10 + 12 => 'Portrait', #10 + 13 => 'Natural sRGB', + 14 => 'Natural+ sRGB', + 15 => 'Landscape', #10 + 16 => 'Evening', #10 + 17 => 'Night Scene', #10 + 18 => 'Night Portrait', #10 + 0x84 => 'Embed Adobe RGB', +); + +%sonyColorMode = ( #15 + 0 => 'Standard', + 1 => 'Vivid', #PH + 2 => 'Portrait', + 3 => 'Landscape', + 4 => 'Sunset', + 5 => 'Night View/Portrait', #(portrait if flash is on) + 6 => 'B&W', + 7 => 'Adobe RGB', + 12 => 'Neutral', # Sony + 13 => 'Clear', #JR (NC) + 14 => 'Deep', #JR + 15 => 'Light', #JR (NC) + 16 => 'Autumn Leaves', #JR (NC) + 17 => 'Sepia', #JR + 100 => 'Neutral', #JD + 101 => 'Clear', #JD + 102 => 'Deep', #JD + 103 => 'Light', #JD + 104 => 'Night View', #JD + 105 => 'Autumn Leaves', #JD + 0xffffffff => 'n/a', #PH +); + +%minoltaSceneMode = ( + 0 => 'Standard', + 1 => 'Portrait', + 2 => 'Text', + 3 => 'Night Scene', + 4 => 'Sunset', + 5 => 'Sports', + 6 => 'Landscape', + 7 => 'Night Portrait', #JD + 8 => 'Macro', + 9 => 'Super Macro', + 16 => 'Auto', # (RX100 'Intelligent Auto' - PH) + 17 => 'Night View/Portrait', + 18 => 'Sweep Panorama', #PH (SLT-A55V) + 19 => 'Handheld Night Shot', #PH + 20 => 'Anti Motion Blur', #PH + 21 => 'Cont. Priority AE', #PH + 22 => 'Auto+', + 23 => '3D Sweep Panorama', #PH (SLT-A55V) + 24 => 'Superior Auto', #28 + 25 => 'High Sensitivity', #28 + 26 => 'Fireworks', #28 + 27 => 'Food', #28 + 28 => 'Pet', #28 + 33 => 'HDR', #JR + 0xffff => 'n/a', #PH +); + +# tag information for AFStatus tags (ref 20) +%afStatusInfo = ( + Format => 'int16s', + # 0=in focus, -32768=out of focus, -ve=front focus, +ve=back focus + PrintConvColumns => 2, + PrintConv => { + 0 => 'In Focus', + -32768 => 'Out of Focus', + OTHER => sub { + my ($val, $inv) = @_; + $inv and $val =~ /([-+]?\d+)/, return $1; + return $val < 0 ? "Front Focus ($val)" : "Back Focus (+$val)"; + }, + }, +); + +my %exposureIndicator = ( + 0 => 'Not Indicated', + 1 => 'Under Scale', + 119 => 'Bottom of Scale', + 120 => '-2.0', + 121 => '-1.7', + 122 => '-1.5', + 123 => '-1.3', + 124 => '-1.0', + 125 => '-0.7', + 126 => '-0.5', + 127 => '-0.3', + 128 => '0', + 129 => '+0.3', + 130 => '+0.5', + 131 => '+0.7', + 132 => '+1.0', + 133 => '+1.3', + 134 => '+1.5', + 135 => '+1.7', + 136 => '+2.0', + 253 => 'Top of Scale', + 254 => 'Over Scale', +); + +my %onOff = ( 0 => 'On', 1 => 'Off' ); +my %offOn = ( 0 => 'Off', 1 => 'On' ); + +# Minolta tag table +%Image::ExifTool::Minolta::Main = ( + WRITE_PROC => \&Image::ExifTool::Exif::WriteExif, + CHECK_PROC => \&Image::ExifTool::Exif::CheckExif, + WRITABLE => 1, + GROUPS => { 0 => 'MakerNotes', 2 => 'Camera' }, + 0x0000 => { + Name => 'MakerNoteVersion', + Writable => 'undef', + Count => 4, + }, + 0x0001 => { + Name => 'MinoltaCameraSettingsOld', + SubDirectory => { + TagTable => 'Image::ExifTool::Minolta::CameraSettings', + ByteOrder => 'BigEndian', + }, + }, + 0x0003 => { + Name => 'MinoltaCameraSettings', + # These camera settings are different for the DiMAGE X31 + Condition => '$self->{Model} ne "DiMAGE X31"', + SubDirectory => { + TagTable => 'Image::ExifTool::Minolta::CameraSettings', + ByteOrder => 'BigEndian', + }, + }, + 0x0004 => { #8 + Name => 'MinoltaCameraSettings7D', + SubDirectory => { + TagTable => 'Image::ExifTool::Minolta::CameraSettings7D', + ByteOrder => 'BigEndian', + }, + }, + 0x0010 => { #20 (count: 256) + Name => 'CameraInfoA100', + Condition => '$$self{Model} eq "DSLR-A100"', + SubDirectory => { + TagTable => 'Image::ExifTool::Minolta::CameraInfoA100', + ByteOrder => 'LittleEndian', + }, + }, + # it appears that image stabilization is on if this tag exists (ref 2), + # but it is an 8kB binary data block! + 0x0018 => [ + { + Name => 'ISInfoA100', + Condition => '$self->{Model} eq "DSLR-A100"', + SubDirectory => { + TagTable => 'Image::ExifTool::Minolta::ISInfoA100', + ByteOrder => 'BigEndian', + }, + },{ + Name => 'ImageStabilization', + Condition => '$self->{Model} =~ /^DiMAGE (A1|A2|X1)$/', + Notes => q{ + a block of binary data which exists in DiMAGE A2 (and A1/X1?) images only if + image stabilization is enabled + }, + ValueConv => '"On"', + }, + ], + 0x0020 => { + Name => 'WBInfoA100', + Condition => '$$self{Model} eq "DSLR-A100"', + Notes => 'currently decoded only for the Sony A100', + SubDirectory => { + TagTable => 'Image::ExifTool::Minolta::WBInfoA100', + ByteOrder => 'BigEndian', + }, + }, + 0x0040 => { + Name => 'CompressedImageSize', + Writable => 'int32u', + }, + 0x0081 => { + # JPEG preview found in DiMAGE 7 images + %Image::ExifTool::previewImageTagInfo, + Groups => { 2 => 'Preview' }, + Permanent => 1, # don't add this to a file + }, + 0x0088 => { + Name => 'PreviewImageStart', + Flags => 'IsOffset', + OffsetPair => 0x0089, # point to associated byte count + DataTag => 'PreviewImage', + Writable => 'int32u', + WriteGroup => 'MakerNotes', + Protected => 2, + # Note: Sony also uses this tag in A100 ARW images, but it points + # to the same data as JpgFromRaw + }, + 0x0089 => { + Name => 'PreviewImageLength', + OffsetPair => 0x0088, # point to associated offset + DataTag => 'PreviewImage', + Writable => 'int32u', + WriteGroup => 'MakerNotes', + Protected => 2, + }, + 0x0100 => { #10 + Name => 'SceneMode', + Writable => 'int32u', + PrintConv => \%minoltaSceneMode, + }, + 0x0101 => [ + { + Name => 'ColorMode', + Condition => '$self->{Make} !~ /^SONY/', + Priority => 0, # Other ColorMode is more reliable for A2 + Writable => 'int32u', + PrintConv => \%minoltaColorMode, + }, + { #15 + Name => 'ColorMode', + Writable => 'int32u', + Notes => 'Sony models', + PrintConv => \%sonyColorMode, + }, + ], + 0x0102 => { + Name => 'MinoltaQuality', + Writable => 'int32u', + # PrintConv strings conform with Minolta reference manual (ref NJ) + # (note that Minolta calls an uncompressed TIFF image "Super fine") + PrintConv => { + 0 => 'Raw', + 1 => 'Super Fine', + 2 => 'Fine', + 3 => 'Standard', + 4 => 'Economy', + 5 => 'Extra fine', + }, + }, + # (0x0103 is the same as 0x0102 above) -- this is true for some + # cameras (A2/7Hi), but not others - PH + 0x0103 => [ + { + Name => 'MinoltaQuality', + Writable => 'int32u', + Condition => '$self->{Model} =~ /^DiMAGE (A2|7Hi)$/', + Notes => 'quality for DiMAGE A2/7Hi', + Priority => 0, # lower priority because this doesn't work for A200 + PrintConv => { #NJ + 0 => 'Raw', + 1 => 'Super Fine', + 2 => 'Fine', + 3 => 'Standard', + 4 => 'Economy', + 5 => 'Extra fine', + }, + }, + { #PH + Name => 'MinoltaImageSize', + Writable => 'int32u', + Condition => '$self->{Model} !~ /^DiMAGE A200$/', + Notes => 'image size for other models except A200', + PrintConv => { + 1 => '1600x1200', + 2 => '1280x960', + 3 => '640x480', + 5 => '2560x1920', + 6 => '2272x1704', + 7 => '2048x1536', + }, + }, + ], + 0x0104 => { #14 + Name => 'FlashExposureComp', + Description => 'Flash Exposure Compensation', + Writable => 'rational64s', + }, + 0x0105 => { #10 + Name => 'Teleconverter', + Writable => 'int32u', + PrintHex => 1, + PrintConv => \%minoltaTeleconverters, + }, + 0x0107 => { #8 + Name => 'ImageStabilization', + Writable => 'int32u', + PrintConv => { + 1 => 'Off', + 5 => 'On', + }, + }, + 0x0109 => { #20 + Name => 'RawAndJpgRecording', + Writable => 'int32u', + PrintConv => \%offOn, + }, + 0x010a => { + Name => 'ZoneMatching', + Writable => 'int32u', + PrintConv => { + 0 => 'ISO Setting Used', + 1 => 'High Key', + 2 => 'Low Key', + }, + }, + 0x010b => { + Name => 'ColorTemperature', + Writable => 'int32u', + }, + 0x010c => { #3 (Alpha 7) + Name => 'LensType', + Writable => 'int32u', + SeparateTable => 1, + ValueConvInv => 'int($val)', # (must truncate decimal part) + PrintConv => \%minoltaLensTypes, + }, + # 0x010e - WhiteBalance according to ref #10 + 0x0111 => { #20 + Name => 'ColorCompensationFilter', + Writable => 'int32s', + Notes => 'ranges from -2 for green to +2 for magenta', + }, + 0x0112 => { #PH (from Sony tags, NC) + Name => 'WhiteBalanceFineTune', + Format => 'int32s', + Writable => 'int32u', + }, + 0x0113 => { #PH + Name => 'ImageStabilization', + Condition => '$self->{Model} eq "DSLR-A100"', + Notes => 'valid for Sony A100 only', + Writable => 'int32u', + PrintConv => \%offOn, + }, + 0x0114 => [ + { #8 + Name => 'MinoltaCameraSettings5D', + Condition => '$self->{Model} =~ /^(DYNAX 5D|MAXXUM 5D|ALPHA SWEET)/', + SubDirectory => { + TagTable => 'Image::ExifTool::Minolta::CameraSettings5D', + ByteOrder => 'BigEndian', + }, + }, + { #PH + Name => 'CameraSettingsA100', + Condition => '$self->{Model} eq "DSLR-A100"', + SubDirectory => { + TagTable => 'Image::ExifTool::Minolta::CameraSettingsA100', + ByteOrder => 'BigEndian', # required because order differs for ARW and JPG images + }, + }, + ], + 0x0115 => { #20 + Name => 'WhiteBalance', + Writable => 'int32u', + PrintHex => 1, + PrintConv => { + 0x00 => 'Auto', + 0x01 => 'Color Temperature/Color Filter', + 0x10 => 'Daylight', + 0x20 => 'Cloudy', + 0x30 => 'Shade', + 0x40 => 'Tungsten', + 0x50 => 'Flash', + 0x60 => 'Fluorescent', + 0x70 => 'Custom', + }, + }, + 0x0e00 => { + Name => 'PrintIM', + Description => 'Print Image Matching', + Writable => 0, + SubDirectory => { + TagTable => 'Image::ExifTool::PrintIM::Main', + }, + }, + 0x0f00 => { + Name => 'MinoltaCameraSettings2', + Writable => 0, + Binary => 1, + }, +); + +%Image::ExifTool::Minolta::CameraSettings = ( + PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData, + WRITE_PROC => \&Image::ExifTool::WriteBinaryData, + CHECK_PROC => \&Image::ExifTool::CheckBinaryData, + WRITABLE => 1, + PRIORITY => 0, # not as reliable as other tags + GROUPS => { 0 => 'MakerNotes', 2 => 'Camera' }, + FORMAT => 'int32u', + FIRST_ENTRY => 0, + NOTES => q{ + There is some variability in CameraSettings information between different + models (and sometimes even between different firmware versions), so this + information may not be as reliable as it should be. Because of this, tags + in the following tables are set to lower priority to prevent them from + superseding the values of same-named tags in other locations when duplicate + tags are disabled. + }, + 1 => { + Name => 'ExposureMode', + PrintConv => { + 0 => 'Program', + 1 => 'Aperture Priority', + 2 => 'Shutter Priority', + 3 => 'Manual', + }, + }, + 2 => { + Name => 'FlashMode', + PrintConv => { + 0 => 'Fill flash', + 1 => 'Red-eye reduction', + 2 => 'Rear flash sync', + 3 => 'Wireless', + 4 => 'Off?', #PH + }, + }, + 3 => { + Name => 'WhiteBalance', + PrintConv => 'Image::ExifTool::Minolta::ConvertWhiteBalance($val)', + }, + 4 => { + Name => 'MinoltaImageSize', + PrintConv => { + 0 => 'Full', + 1 => '1600x1200', + 2 => '1280x960', + 3 => '640x480', + 6 => '2080x1560', #PH (A2) + 7 => '2560x1920', #PH (A2) + 8 => '3264x2176', #PH (A2) + }, + }, + 5 => { + Name => 'MinoltaQuality', + PrintConv => { #NJ + 0 => 'Raw', + 1 => 'Super Fine', + 2 => 'Fine', + 3 => 'Standard', + 4 => 'Economy', + 5 => 'Extra Fine', + }, + }, + 6 => { + Name => 'DriveMode', + PrintConv => { + 0 => 'Single', + 1 => 'Continuous', + 2 => 'Self-timer', + 4 => 'Bracketing', + 5 => 'Interval', + 6 => 'UHS continuous', + 7 => 'HS continuous', + }, + }, + 7 => { + Name => 'MeteringMode', + PrintConv => { + 0 => 'Multi-segment', + 1 => 'Center-weighted average', + 2 => 'Spot', + }, + }, + 8 => { + Name => 'ISO', + ValueConv => '2 ** (($val-48)/8) * 100', + ValueConvInv => '48 + 8*log($val/100)/log(2)', + PrintConv => 'int($val + 0.5)', + PrintConvInv => '$val', + }, + 9 => { + Name => 'ExposureTime', + ValueConv => '2 ** ((48-$val)/8)', + ValueConvInv => '48 - 8*log($val)/log(2)', + PrintConv => 'Image::ExifTool::Exif::PrintExposureTime($val)', + PrintConvInv => 'Image::ExifTool::Exif::ConvertFraction($val)', + }, + 10 => { + Name => 'FNumber', + ValueConv => '2 ** (($val-8)/16)', + ValueConvInv => '8 + 16*log($val)/log(2)', + PrintConv => 'sprintf("%.1f",$val)', + PrintConvInv => '$val', + }, + 11 => { + Name => 'MacroMode', + PrintConv => { + 0 => 'Off', + 1 => 'On', + }, + }, + 12 => { + Name => 'DigitalZoom', + PrintConv => { + 0 => 'Off', + 1 => 'Electronic magnification', + 2 => '2x', + }, + }, + 13 => { + Name => 'ExposureCompensation', + ValueConv => '$val/3 - 2', + ValueConvInv => '($val + 2) * 3', + PrintConv => 'Image::ExifTool::Exif::PrintFraction($val)', + PrintConvInv => 'Image::ExifTool::Exif::ConvertFraction($val)', + }, + 14 => { + Name => 'BracketStep', + PrintConv => { + 0 => '1/3 EV', + 1 => '2/3 EV', + 2 => '1 EV', + }, + }, + 16 => 'IntervalLength', + 17 => 'IntervalNumber', + 18 => { + Name => 'FocalLength', + ValueConv => '$val / 256', + ValueConvInv => '$val * 256', + PrintConv => 'sprintf("%.1f mm",$val)', + PrintConvInv => '$val=~s/\s*mm$//;$val', + }, + 19 => { + Name => 'FocusDistance', + ValueConv => '$val / 1000', + ValueConvInv => '$val * 1000', + PrintConv => '$val ? "$val m" : "inf"', + PrintConvInv => '$val eq "inf" ? 0 : $val =~ s/\s*m$//, $val', + }, + 20 => { + Name => 'FlashFired', + PrintConv => { + 0 => 'No', + 1 => 'Yes', + }, + }, + 21 => { + Name => 'MinoltaDate', + Groups => { 2 => 'Time' }, + Shift => 'Time', + ValueConv => 'sprintf("%4d:%.2d:%.2d",$val>>16,($val&0xff00)>>8,$val&0xff)', + ValueConvInv => 'my @a=($val=~/(\d+):(\d+):(\d+)/); @a ? ($a[0]<<16)+($a[1]<<8)+$a[2] : undef', + }, + 22 => { + Name => 'MinoltaTime', + Groups => { 2 => 'Time' }, + Shift => 'Time', + ValueConv => 'sprintf("%.2d:%.2d:%.2d",$val>>16,($val&0xff00)>>8,$val&0xff)', + ValueConvInv => 'my @a=($val=~/(\d+):(\d+):(\d+)/); @a ? ($a[0]<<16)+($a[1]<<8)+$a[2] : undef', + }, + 23 => { + Name => 'MaxAperture', + ValueConv => '2 ** (($val-8)/16)', + ValueConvInv => '8 + 16*log($val)/log(2)', + PrintConv => 'sprintf("%.1f",$val)', + PrintConvInv => '$val', + }, + 26 => { + Name => 'FileNumberMemory', + PrintConv => \%offOn, + }, + 27 => 'LastFileNumber', + 28 => { + Name => 'ColorBalanceRed', + ValueConv => '$val / 256', + ValueConvInv => '$val * 256', + }, + 29 => { + Name => 'ColorBalanceGreen', + ValueConv => '$val / 256', + ValueConvInv => '$val * 256', + }, + 30 => { + Name => 'ColorBalanceBlue', + ValueConv => '$val / 256', + ValueConvInv => '$val * 256', + }, + 31 => { + Name => 'Saturation', + ValueConv => '$val - ($self->{Model}=~/DiMAGE A2/ ? 5 : 3)', + ValueConvInv => '$val + ($self->{Model}=~/DiMAGE A2/ ? 5 : 3)', + %Image::ExifTool::Exif::printParameter, + }, + 32 => { + Name => 'Contrast', + ValueConv => '$val - ($self->{Model}=~/DiMAGE A2/ ? 5 : 3)', + ValueConvInv => '$val + ($self->{Model}=~/DiMAGE A2/ ? 5 : 3)', + %Image::ExifTool::Exif::printParameter, + }, + 33 => { + Name => 'Sharpness', + PrintConv => { + 0 => 'Hard', + 1 => 'Normal', + 2 => 'Soft', + }, + }, + 34 => { + Name => 'SubjectProgram', + PrintConv => { + 0 => 'None', + 1 => 'Portrait', + 2 => 'Text', + 3 => 'Night portrait', + 4 => 'Sunset', + 5 => 'Sports action', + }, + }, + 35 => { + Name => 'FlashExposureComp', + Description => 'Flash Exposure Compensation', + ValueConv => '($val - 6) / 3', + ValueConvInv => '$val * 3 + 6', + PrintConv => 'Image::ExifTool::Exif::PrintFraction($val)', + PrintConvInv => 'Image::ExifTool::Exif::ConvertFraction($val)', + }, + 36 => { + Name => 'ISOSetting', + PrintConv => { + 0 => 100, + 1 => 200, + 2 => 400, + 3 => 800, + 4 => 'Auto', + 5 => 64, + }, + }, + 37 => { + Name => 'MinoltaModelID', + PrintConv => { + 0 => 'DiMAGE 7, X1, X21 or X31', + 1 => 'DiMAGE 5', + 2 => 'DiMAGE S304', + 3 => 'DiMAGE S404', + 4 => 'DiMAGE 7i', + 5 => 'DiMAGE 7Hi', + 6 => 'DiMAGE A1', + 7 => 'DiMAGE A2 or S414', + }, + }, + 38 => { + Name => 'IntervalMode', + PrintConv => { + 0 => 'Still Image', + 1 => 'Time-lapse Movie', + }, + }, + 39 => { + Name => 'FolderName', + PrintConv => { + 0 => 'Standard Form', + 1 => 'Data Form', + }, + }, + 40 => { + Name => 'ColorMode', + PrintConv => { + 0 => 'Natural color', + 1 => 'Black & White', + 2 => 'Vivid color', + 3 => 'Solarization', + 4 => 'Adobe RGB', + }, + }, + 41 => { + Name => 'ColorFilter', + ValueConv => '$val - ($self->{Model}=~/DiMAGE A2/ ? 5 : 3)', + ValueConvInv => '$val + ($self->{Model}=~/DiMAGE A2/ ? 5 : 3)', + }, + 42 => 'BWFilter', + 43 => { + Name => 'InternalFlash', + PrintConv => { + 0 => 'No', + 1 => 'Fired', + }, + }, + 44 => { + Name => 'Brightness', + ValueConv => '$val/8 - 6', + ValueConvInv => '($val + 6) * 8', + }, + 45 => 'SpotFocusPointX', + 46 => 'SpotFocusPointY', + 47 => { + Name => 'WideFocusZone', + PrintConv => { + 0 => 'No zone', + 1 => 'Center zone (horizontal orientation)', + 2 => 'Center zone (vertical orientation)', + 3 => 'Left zone', + 4 => 'Right zone', + }, + }, + 48 => { + Name => 'FocusMode', + PrintConv => { + 0 => 'AF', + 1 => 'MF', + }, + }, + 49 => { + Name => 'FocusArea', + PrintConv => { + 0 => 'Wide Focus (normal)', + 1 => 'Spot Focus', + }, + }, + 50 => { + Name => 'DECPosition', + PrintConv => { + 0 => 'Exposure', + 1 => 'Contrast', + 2 => 'Saturation', + 3 => 'Filter', + }, + }, + # 7Hi only: + 51 => { + Name => 'ColorProfile', + Condition => '$self->{Model} eq "DiMAGE 7Hi"', + Notes => 'DiMAGE 7Hi only', + PrintConv => { + 0 => 'Not Embedded', + 1 => 'Embedded', + }, + }, + # (the following may be entry 51 for other models?) + 52 => { + Name => 'DataImprint', + Condition => '$self->{Model} eq "DiMAGE 7Hi"', + Notes => 'DiMAGE 7Hi only', + PrintConv => { + 0 => 'None', + 1 => 'YYYY/MM/DD', + 2 => 'MM/DD/HH:MM', + 3 => 'Text', + 4 => 'Text + ID#', + }, + }, + 63 => { #9 + Name => 'FlashMetering', + PrintConv => { + 0 => 'ADI (Advanced Distance Integration)', + 1 => 'Pre-flash TTL', + 2 => 'Manual flash control', + }, + }, +); + +# Camera settings used by the 7D (ref 8) +%Image::ExifTool::Minolta::CameraSettings7D = ( + PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData, + WRITE_PROC => \&Image::ExifTool::WriteBinaryData, + CHECK_PROC => \&Image::ExifTool::CheckBinaryData, + WRITABLE => 1, + PRIORITY => 0, + GROUPS => { 0 => 'MakerNotes', 2 => 'Camera' }, + FORMAT => 'int16u', + FIRST_ENTRY => 0, + 0x00 => { + Name => 'ExposureMode', + PrintConv => { + 0 => 'Program', + 1 => 'Aperture Priority', + 2 => 'Shutter Priority', + 3 => 'Manual', + 4 => 'Auto', + 5 => 'Program-shift A', + 6 => 'Program-shift S', + }, + }, + 0x02 => { #PH + Name => 'MinoltaImageSize', + PrintConv => { + 0 => 'Large', + 1 => 'Medium', + 2 => 'Small', + }, + }, + 0x03 => { + Name => 'MinoltaQuality', + PrintConv => { + 0 => 'RAW', + 16 => 'Fine', #PH + 32 => 'Normal', #PH + 34 => 'RAW+JPEG', + 48 => 'Economy', #PH + }, + }, + 0x04 => { + Name => 'WhiteBalance', + PrintConv => { + 0 => 'Auto', + 1 => 'Daylight', + 2 => 'Shade', + 3 => 'Cloudy', + 4 => 'Tungsten', + 5 => 'Fluorescent', + 0x100 => 'Kelvin', + 0x200 => 'Manual', + }, + }, + 0x0e => { + Name => 'FocusMode', + PrintConv => { + 0 => 'AF-S', + 1 => 'AF-C', + # Note: these two are reversed in ref 8 + 3 => 'Manual', #JD + 4 => 'AF-A', #JD + }, + }, + 0x10 => { + Name => 'AFPoints', + PrintConv => { + 0 => '(none)', + BITMASK => { + 0 => 'Center', + 1 => 'Top', + 2 => 'Top-right', + 3 => 'Right', + 4 => 'Bottom-right', + 5 => 'Bottom', + 6 => 'Bottom-left', + 7 => 'Left', + 8 => 'Top-left', + }, + }, + }, + 0x15 => { + Name => 'Flash', + PrintConv => \%offOn, + }, + 0x16 => { #10 + Name => 'FlashMode', + PrintConv => { + 0 => 'Normal', + 1 => 'Red-eye reduction', + 2 => 'Rear flash sync', + }, + }, + 0x1c => { + Name => 'ISOSetting', + PrintConv => { + 0 => 'Auto', #10 + 1 => 100, + 3 => 200, + 4 => 400, + 5 => 800, + 6 => 1600, + 7 => 3200, + }, + }, + 0x1e => { + Name => 'ExposureCompensation', + Format => 'int16s', + ValueConv => '$val / 24', + ValueConvInv => '$val * 24', + PrintConv => 'Image::ExifTool::Exif::PrintFraction($val)', + PrintConvInv => 'Image::ExifTool::Exif::ConvertFraction($val)', + }, + 0x25 => { + Name => 'ColorSpace', + PrintConv => { + 0 => 'Natural sRGB', + 1 => 'Natural+ sRGB', + 4 => 'Adobe RGB', + }, + }, + 0x26 => { + Name => 'Sharpness', + ValueConv => '$val - 10', + ValueConvInv => '$val + 10', + }, + 0x27 => { + Name => 'Contrast', + ValueConv => '$val - 10', + ValueConvInv => '$val + 10', + }, + 0x28 => { + Name => 'Saturation', + ValueConv => '$val - 10', + ValueConvInv => '$val + 10', + }, + 0x2d => 'FreeMemoryCardImages', + 0x3f => { + Format => 'int16s', + Name => 'ColorTemperature', + ValueConv => '$val * 100', + ValueConvInv => '$val / 100', + }, + 0x40 => { #10 + Name => 'HueAdjustment', + ValueConv => '$val - 10', + ValueConvInv => '$val + 10', + }, + 0x46 => { + Name => 'Rotation', + PrintConv => { + 72 => 'Horizontal (normal)', + 76 => 'Rotate 90 CW', + 82 => 'Rotate 270 CW', + }, + }, + 0x47 => { + Name => 'FNumber', + ValueConv => '2 ** (($val-8)/16)', + ValueConvInv => '8 + 16*log($val)/log(2)', + PrintConv => 'sprintf("%.1f",$val)', + PrintConvInv => '$val', + }, + 0x48 => { + Name => 'ExposureTime', + ValueConv => '2 ** ((48-$val)/8)', + ValueConvInv => '48 - 8*log($val)/log(2)', + PrintConv => 'Image::ExifTool::Exif::PrintExposureTime($val)', + PrintConvInv => 'Image::ExifTool::Exif::ConvertFraction($val)', + }, + 0x4a => 'FreeMemoryCardImages', + 0x5e => { + Name => 'ImageNumber', + Notes => q{ + this information may appear at index 98 (0x62), depending on firmware + version + }, + ValueConv => '$val + 1', + ValueConvInv => '$val - 1', + }, + 0x60 => { + Name => 'NoiseReduction', + PrintConv => \%offOn, + }, + 0x62 => { + Name => 'ImageNumber2', + ValueConv => '$val + 1', + ValueConvInv => '$val - 1', + }, + 0x71 => { + Name => 'ImageStabilization', + PrintConv => \%offOn, + }, + 0x75 => { + Name => 'ZoneMatchingOn', + PrintConv => \%offOn, + }, +); + +# Camera settings used by the 5D (ref 8) +%Image::ExifTool::Minolta::CameraSettings5D = ( + PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData, + WRITE_PROC => \&Image::ExifTool::WriteBinaryData, + CHECK_PROC => \&Image::ExifTool::CheckBinaryData, + WRITABLE => 1, + PRIORITY => 0, + GROUPS => { 0 => 'MakerNotes', 2 => 'Camera' }, + FORMAT => 'int16u', + FIRST_ENTRY => 0, + 0x0a => { + Name => 'ExposureMode', + PrintConv => { + 0 => 'Program', + 1 => 'Aperture Priority', + 2 => 'Shutter Priority', + 3 => 'Manual', + 4 => 'Auto?', + 4131 => 'Connected Copying?', + }, + }, + 0x0c => { #PH + Name => 'MinoltaImageSize', + PrintConv => { + 0 => 'Large', + 1 => 'Medium', + 2 => 'Small', + }, + }, + 0x0d => { + Name => 'MinoltaQuality', + PrintConv => { + 0 => 'RAW', + 16 => 'Fine', #PH + 32 => 'Normal', #PH + 34 => 'RAW+JPEG', + 48 => 'Economy', #PH + }, + }, + 0x0e => { + Name => 'WhiteBalance', + PrintConv => { + 0 => 'Auto', + 1 => 'Daylight', + 2 => 'Cloudy', + 3 => 'Shade', + 4 => 'Tungsten', + 5 => 'Fluorescent', + 6 => 'Flash', + 0x100 => 'Kelvin', + 0x200 => 'Manual', + }, + }, + # 0x0f-0x11 something to do with WB RGB levels as shot? (PH) + # 0x12-0x17 RGB levels for other WB modes (with G missing)? (PH) + 0x1f => { #PH + Name => 'Flash', + PrintConv => { + 0 => 'Did not fire', + 1 => 'Fired', + }, + }, + 0x20 => { #10 + Name => 'FlashMode', + PrintConv => { + 0 => 'Normal', + 1 => 'Red-eye reduction', + 2 => 'Rear flash sync', + }, + }, + 0x25 => { + Name => 'MeteringMode', + PrintConv => { + 0 => 'Multi-segment', + 1 => 'Center-weighted average', + 2 => 'Spot', + }, + }, + 0x26 => { + Name => 'ISOSetting', + PrintConv => { + 0 => 'Auto', + 1 => 100, + 3 => 200, + 4 => 400, + 5 => 800, + 6 => 1600, + 7 => 3200, + 8 => '200 (Zone Matching High)', + 10 => '80 (Zone Matching Low)', + }, + }, +# looks wrong: +# 0x28 => { #10 +# Name => 'ExposureCompensation', +# ValueConv => '$val / 24', +# ValueConvInv => '$val * 24', +# }, + 0x2f => { #10 + Name => 'ColorSpace', + PrintConv => { + 0 => 'Natural sRGB', + 1 => 'Natural+ sRGB', + 2 => 'Monochrome', + 4 => 'Adobe RGB (ICC)', + 5 => 'Adobe RGB', + }, + }, + 0x30 => { + Name => 'Sharpness', + ValueConv => '$val - 10', + ValueConvInv => '$val + 10', + }, + 0x31 => { + Name => 'Contrast', + ValueConv => '$val - 10', + ValueConvInv => '$val + 10', + }, + 0x32 => { + Name => 'Saturation', + ValueConv => '$val - 10', + ValueConvInv => '$val + 10', + }, + 0x35 => { #PH + Name => 'ExposureTime', + ValueConv => '2 ** ((48-$val)/8)', + ValueConvInv => '48 - 8*log($val)/log(2)', + PrintConv => 'Image::ExifTool::Exif::PrintExposureTime($val)', + PrintConvInv => 'Image::ExifTool::Exif::ConvertFraction($val)', + }, + 0x36 => { #PH + Name => 'FNumber', + ValueConv => '2 ** (($val-8)/16)', + ValueConvInv => '8 + 16*log($val)/log(2)', + PrintConv => 'sprintf("%.1f",$val)', + PrintConvInv => '$val', + }, + 0x37 => 'FreeMemoryCardImages', + # 0x38 definitely not related to exposure comp as in ref 8 (PH) + 0x49 => { #PH + Name => 'ColorTemperature', + Format => 'int16s', + ValueConv => '$val * 100', + ValueConvInv => '$val / 100', + }, + 0x4a => { #10 + Name => 'HueAdjustment', + ValueConv => '$val - 10', + ValueConvInv => '$val + 10', + }, + 0x50 => { + Name => 'Rotation', + PrintConv => { + 72 => 'Horizontal (normal)', + 76 => 'Rotate 90 CW', + 82 => 'Rotate 270 CW', + }, + }, + 0x53 => { + Name => 'ExposureCompensation', + ValueConv => '$val / 100 - 3', + ValueConvInv => '($val + 3) * 100', + PrintConv => 'Image::ExifTool::Exif::PrintFraction($val)', + PrintConvInv => 'Image::ExifTool::Exif::ConvertFraction($val)', + }, + 0x54 => 'FreeMemoryCardImages', + 0x65 => { #10 + Name => 'Rotation', + PrintConv => { + 0 => 'Horizontal (normal)', + 1 => 'Rotate 90 CW', + 2 => 'Rotate 270 CW', + }, + }, + # 0x66 maybe program mode or some setting like this? (PH) + 0x6e => { #10 + Name => 'ColorTemperature', + Format => 'int16s', + ValueConv => '$val * 100', + ValueConvInv => '$val / 100', + }, + 0x71 => { #10 + Name => 'PictureFinish', + PrintConv => { + 0 => 'Natural', + 1 => 'Natural+', + 2 => 'Portrait', + 3 => 'Wind Scene', + 4 => 'Evening Scene', + 5 => 'Night Scene', + 6 => 'Night Portrait', + 7 => 'Monochrome', + 8 => 'Adobe RGB', + 9 => 'Adobe RGB (ICC)', + }, + }, + # 0x95 FlashStrength? (PH) + # 0xa4 similar information to 0x27, except with different values + 0xae => { + Name => 'ImageNumber', + ValueConv => '$val + 1', + ValueConvInv => '$val - 1', + }, + 0xb0 => { + Name => 'NoiseReduction', + PrintConv => \%offOn, + }, + 0xbd => { + Name => 'ImageStabilization', + PrintConv => \%offOn, + }, +); + +# Camera settings used by the Sony DSLR-A100 (ref 20) +%Image::ExifTool::Minolta::CameraInfoA100 = ( + PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData, + WRITE_PROC => \&Image::ExifTool::WriteBinaryData, + CHECK_PROC => \&Image::ExifTool::CheckBinaryData, + NOTES => 'Camera information for the Sony DSLR-A100.', + WRITABLE => 1, + PRIORITY => 0, # may not be as reliable as other information + GROUPS => { 0 => 'MakerNotes', 2 => 'Camera' }, + FIRST_ENTRY => 0, + 0x01 => { #PH + Name => 'AFSensorActive', + PrintConv => { + 0 => 'Top-right', + 1 => 'Bottom-right', + 2 => 'Bottom', + 3 => 'Middle Horizontal', + 4 => 'Center Vertical', + 5 => 'Top', + 6 => 'Top-left', + 7 => 'Bottom-left', + }, + }, + 0x02 => { + Name => 'AFStatusActiveSensor', + %afStatusInfo, + Notes => q{ + the focus status at shutter release. May not reflect the status after + focusing if the image is focused then recomposed + }, + }, + 0x04 => { Name => 'AFStatusTop-right', %afStatusInfo }, + 0x06 => { Name => 'AFStatusBottom-right', %afStatusInfo }, + 0x08 => { Name => 'AFStatusBottom', %afStatusInfo }, + 0x0a => { + Name => 'AFStatusMiddleHorizontal', + %afStatusInfo, + Notes => q{ + any of the three horizontal sensors at the middle of the focus frame: Left, + Center or Right + }, + }, + 0x0c => { Name => 'AFStatusCenterVertical', %afStatusInfo }, + 0x0e => { Name => 'AFStatusTop', %afStatusInfo }, + 0x10 => { Name => 'AFStatusTop-left', %afStatusInfo }, + 0x12 => { Name => 'AFStatusBottom-left', %afStatusInfo }, + 0x14 => { + Name => 'FocusLocked', + # (Focus can be locked in all modes other than Manual and Continuous, + # and the latter can be overridden by pushing the Spot AF button) + PrintConv => { + 0 => 'Manual Focus', + 4 => 'No', + 16 => 'Continuous Focus', + 64 => 'Yes', + }, + }, + 0x15 => { + Name => 'AFPoint', + PrintConvColumns => 2, + PrintConv => { + 0 => 'Auto', + 1 => 'Center', + 2 => 'Top', + 3 => 'Top-right', + 4 => 'Right', + 5 => 'Bottom-right', + 6 => 'Bottom', + 7 => 'Bottom-left', + 8 => 'Left', + 9 => 'Top-left', + }, + }, + 0x16 => { + Name => 'AFMode', + PrintConv => { + 0 => 'DMF', + 1 => 'AF-S', + 2 => 'AF-C', + 3 => 'AF-A', + }, + }, + 0x2d => { Name => 'AFStatusLeft', %afStatusInfo }, + 0x2f => { Name => 'AFStatusCenterHorizontal',%afStatusInfo }, + 0x31 => { Name => 'AFStatusRight', %afStatusInfo }, + 0x33 => { + Name => 'AFAreaMode', + PrintConv => { + 0 => 'Wide', + 1 => 'Local', + 2 => 'Spot', + }, + }, +); + +# Image stabilization inforamtion used by the Sony DSLR-A100 (ref 20) +%Image::ExifTool::Minolta::ISInfoA100 = ( + PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData, + WRITE_PROC => \&Image::ExifTool::WriteBinaryData, + CHECK_PROC => \&Image::ExifTool::CheckBinaryData, + NOTES => 'Image stabilization information for the Sony DSLR-A100.', + WRITABLE => 1, + PRIORITY => 0, # may not be as reliable as other information + GROUPS => { 0 => 'MakerNotes', 2 => 'Camera' }, + FIRST_ENTRY => 0, + 0 => { + Name => 'ImageStabilization', + Format => 'int16u', + PrintHex => 1, + PrintConv => { + 0x0000 => 'Off', + 0x2784 => 'On', + }, + }, +); + +# Camera settings used by the Sony DSLR-A100 (ref PH) +%Image::ExifTool::Minolta::CameraSettingsA100 = ( + PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData, + WRITE_PROC => \&Image::ExifTool::WriteBinaryData, + CHECK_PROC => \&Image::ExifTool::CheckBinaryData, + NOTES => 'Camera settings information for the Sony DSLR-A100.', + WRITABLE => 1, + PRIORITY => 0, # may not be as reliable as other information + GROUPS => { 0 => 'MakerNotes', 2 => 'Camera' }, + FORMAT => 'int16u', + FIRST_ENTRY => 0, + 0x00 => { #15 + Name => 'ExposureMode', + PrintHex => 1, + PrintConv => { + 0 => 'Program', + 1 => 'Aperture Priority', + 2 => 'Shutter Priority', + 3 => 'Manual', + 4 => 'Auto', + 5 => 'Program Shift A', #20 + 6 => 'Program Shift S', #20 + 0x1013 => 'Portrait', + 0x1023 => 'Sports', #20 + 0x1033 => 'Sunset', #20 + 0x1043 => 'Night View/Portrait', #20 + 0x1053 => 'Landscape', + 0x1083 => 'Macro', #20 + }, + }, + 0x01 => { #15 + Name => 'ExposureCompensationSetting', + # (differs from ExposureCompensation for exposure bracketing shots, ref 20) + ValueConv => '$val / 100 - 3', + ValueConvInv => 'int(($val + 3) * 100 + 0.5)', + }, + 0x05 => { #20 (requires external flash) + Name => 'HighSpeedSync', + PrintConv => \%offOn, + }, + 0x06 => { #20 + Name => 'ShutterSpeedSetting', + Notes => 'used only in M and S exposure modes', + ValueConv => '$val ? 2 ** (6 - $val/8) : 0', + ValueConvInv => '$val ? int((6 - log($val) / log(2)) * 8 + 0.5) : 0', + PrintConv => '$val ? Image::ExifTool::Exif::PrintExposureTime($val) : "Bulb"', + PrintConvInv => 'lc($val) eq "bulb" ? 0 : Image::ExifTool::Exif::ConvertFraction($val)', + }, + 0x07 => { #20 + Name => 'ApertureSetting', + Notes => 'used only in M and A exposure modes', + ValueConv => '2 ** (($val/8 - 1) / 2)', + ValueConvInv => 'int((log($val) * 2 / log(2) + 1) * 8 + 0.5)', + PrintConv => 'Image::ExifTool::Exif::PrintFNumber($val)', + PrintConvInv => '$val', + }, + 0x08 => { #20 + Name => 'ExposureTime', + ValueConv => '$val ? 2 ** (6 - $val/8) : 0', + ValueConvInv => '$val ? int((6 - log($val) / log(2)) * 8 + 0.5) : 0', + PrintConv => '$val ? Image::ExifTool::Exif::PrintExposureTime($val) : "Bulb"', + PrintConvInv => 'lc($val) eq "bulb" ? 0 : Image::ExifTool::Exif::ConvertFraction($val)', + }, + 0x09 => { #15/20 + Name => 'FNumber', + ValueConv => '2 ** (($val/8 - 1) / 2)', + ValueConvInv => 'int((log($val) * 2 / log(2) + 1) * 8 + 0.5)', + PrintConv => 'Image::ExifTool::Exif::PrintFNumber($val)', + PrintConvInv => '$val', + }, + 0x0a => { #20 + Name => 'DriveMode2', # (one of these is probably DriveModeSetting like Sony - PH) + PrintHex => 1, + PrintConv => { + 0x000 => 'Self-timer 10 sec', + 0x001 => 'Continuous', + 0x302 => 'Single-frame Bracketing Low', + 0x702 => 'Single-frame Bracketing High', + 0x303 => 'Continous Bracketing Low', + 0x703 => 'Continuous Bracketing High', + 0x004 => 'Self-timer 2 sec', + 0x005 => 'Single Frame', + 0x008 => 'White Balance Bracketing Low', + 0x009 => 'White Balance Bracketing High', + }, + }, + 0x0b => { #15 + Name => 'WhiteBalance', + PrintHex => 1, + PrintConv => { + 0 => 'Auto', + 1 => 'Daylight', + 2 => 'Cloudy', + 3 => 'Shade', + 4 => 'Tungsten', + 5 => 'Fluorescent', + 6 => 'Flash', + 0x100 => 'Kelvin', + 0x200 => 'Manual', + }, + }, + 0x0c => { #20 + Name => 'FocusMode', + PrintConv => { + 0 => 'AF-S', + 1 => 'AF-C', + 4 => 'AF-A', + 5 => 'Manual', + 6 => 'DMF', + }, + }, + 0x0d => { #20 + Name => 'AFPointSelected', # (v8.88: renamed from LocalAFAreaPoint) + # (9-point centre-cross AF system, ref JR) + PrintConv => { + 1 => 'Center', + 2 => 'Top', + 3 => 'Top-right', + 4 => 'Right', + 5 => 'Bottom-right', + 6 => 'Bottom', + 7 => 'Bottom-left', + 8 => 'Left', + 9 => 'Top-left', + }, + }, + 0x0e => { #20 + Name => 'AFAreaMode', + PrintConv => { + 0 => 'Wide', + 1 => 'Local', + 2 => 'Spot', + }, + }, + 0x0f => { #20 + Name => 'FlashMode', + PrintConv => { + 0 => 'Auto', + 2 => 'Rear Sync', + 3 => 'Wireless', + 4 => 'Fill Flash', + }, + }, + 0x10 => { #20 + Name => 'FlashExposureCompSet', + Description => 'Flash Exposure Comp. Setting', + # (may differ from FlashExposureComp for flash bracketing shots) + ValueConv => '$val / 100 - 3', + ValueConvInv => 'int(($val + 3) * 100 + 0.5)', + }, + 0x12 => { #15/20 + Name => 'MeteringMode', + PrintConv => { + 0 => 'Multi-segment', + 1 => 'Center-weighted average', + 2 => 'Spot', + }, + }, + 0x13 => { #15/20 + Name => 'ISOSetting', + PrintConv => { + 0 => 'Auto', + 48 => 100, + 56 => 200, + 64 => 400, + 72 => 800, + 80 => 1600, + 174 => '80 (Zone Matching Low)', + 184 => '200 (Zone Matching High)', + }, + }, + 0x14 => { #15/20 + Name => 'ZoneMatchingMode', + PrintConv => { + 0 => 'Off', + 1 => 'Standard', + 2 => 'Advanced', + }, + }, + 0x15 => { #15/20 + Name => 'DynamicRangeOptimizer', + # this and the Sony tag 0xb025 DynamicRangeOptimizer give the actual mode + # applied to the image. The Minolta CameraSettingsA100 0x0027 tag gives + # the setting. There is a longish list of scenarios in which, regardless + # of the latter, DRO is not applied (ref 20) + Notes => 'as applied to image', + PrintConv => { + 0 => 'Off', + 1 => 'Standard', + 2 => 'Advanced', + }, + }, + 0x16 => { #15 + Name => 'ColorMode', + PrintConv => { + 0 => 'Standard', + 1 => 'Vivid', + 2 => 'Portrait', + 3 => 'Landscape', + 4 => 'Sunset', + 5 => 'Night Scene', + 7 => 'B&W', + 8 => 'Adobe RGB', + }, + }, + 0x17 => { # 15/20 + Name => 'ColorSpace', + PrintConv => { + 0 => 'sRGB', + 2 => 'B&W', #PH (A100) + 5 => 'Adobe RGB', + }, + }, + 0x18 => { #15 + Name => 'Sharpness', + ValueConv => '$val - 10', + ValueConvInv => '$val + 10', + %Image::ExifTool::Exif::printParameter, + }, + 0x19 => { #15 + Name => 'Contrast', + ValueConv => '$val - 10', + ValueConvInv => '$val + 10', + %Image::ExifTool::Exif::printParameter, + }, + 0x1a => { #15 + Name => 'Saturation', + ValueConv => '$val - 10', + ValueConvInv => '$val + 10', + %Image::ExifTool::Exif::printParameter, + }, + 0x1c => { #20 + Name => 'FlashMetering', + PrintConv => { + 0 => 'ADI (Advanced Distance Integration)', + 1 => 'Pre-flash TTL', + }, + }, + 0x1d => { #20 + Name => 'PrioritySetupShutterRelease', + PrintConv => { + 0 => 'AF', + 1 => 'Release', + }, + }, + 0x1e => { #PH + Name => 'DriveMode', + PrintConv => { + 0 => 'Single Frame', + 1 => 'Continuous', + 2 => 'Self-timer', + 3 => 'Continuous Bracketing', + 4 => 'Single-Frame Bracketing', + 5 => 'White Balance Bracketing', + }, + }, + 0x1f => { #20 + Name => 'SelfTimerTime', + PrintConv => { + 0 => '10 s', + 4 => '2 s', + }, + }, + 0x20 => { #20 + Name => 'ContinuousBracketing', + PrintHex => 1, + PrintConv => { + 0x303 => 'Low', + 0x703 => 'High', + }, + }, + 0x21 => { #20 + Name => 'SingleFrameBracketing', + PrintHex => 1, + PrintConv => { + 0x302 => 'Low', + 0x702 => 'High', + }, + }, + 0x22 => { #20 + Name => 'WhiteBalanceBracketing', + PrintHex => 1, + PrintConv => { + 0x08 => 'Low', + 0x09 => 'High', + }, + }, + 0x023 => { #20 + Name => 'WhiteBalanceSetting', + PrintHex => 1, + # (not sure what bit 0x8000 indicates) + PrintConv => { + 0 => 'Auto', + 1 => 'Preset', + 2 => 'Custom', + 3 => 'Color Temperature/Color Filter', + 0x8001 => 'Preset', + 0x8002 => 'Custom', + 0x8003 => 'Color Temperature/Color Filter', + }, + }, + 0x24 => { #20 + Name => 'PresetWhiteBalance', + PrintConv => { + 1 => 'Daylight', + 2 => 'Cloudy', + 3 => 'Shade', + 4 => 'Tungsten', + 5 => 'Fluorescent', + 6 => 'Flash', + }, + }, + 0x25 => { #20 + Name => 'ColorTemperatureSetting', + PrintConv => { + 0 => 'Temperature', + 2 => 'Color Filter', + }, + }, + 0x26 => { #20 + Name => 'CustomWBSetting', + PrintConv => { + 0 => 'Setup', + 1 => 'Recall', + }, + }, + 0x27 => { #20 + Name => 'DynamicRangeOptimizerSetting', + Notes => 'as set in camera', + PrintConv => { + 0 => 'Off', + 1 => 'Standard', + 2 => 'Advanced', + }, + }, + 0x32 => 'FreeMemoryCardImages', #20 + 0x34 => 'CustomWBRedLevel', #20 + 0x35 => 'CustomWBGreenLevel', #20 + 0x36 => 'CustomWBBlueLevel', #20 + 0x37 => { #20 + Name => 'CustomWBError', + PrintConv => { + 0 => 'OK', + 1 => 'Error', + }, + }, + 0x38 => { #20 + Name => 'WhiteBalanceFineTune', + Format => 'int16s', + }, + 0x39 => { #20 + Name => 'ColorTemperature', + ValueConv => '$val * 100', + ValueConvInv => '$val / 100', + }, + 0x3a => { #20 + Name => 'ColorCompensationFilter', + Format => 'int16s', + Notes => 'ranges from -2 for green to +2 for magenta', + }, + 0x3b => { #20 + Name => 'SonyImageSize', + PrintConv => { + 0 => 'Standard', + 1 => 'Medium', + 2 => 'Small', + }, + }, + 0x3c => { #20 + Name => 'SonyQuality', + PrintConv => { + 0 => 'RAW', + 32 => 'Fine', + 34 => 'RAW + JPEG', + 48 => 'Standard', + }, + }, + 0x3d => { #20 + Name => 'InstantPlaybackTime', + PrintConv => '"$val s"', + PrintConvInv => '$val=~s/\s*s//; $val', + }, + 0x3e => { #20 + Name => 'InstantPlaybackSetup', + PrintConv => { + 0 => 'Image and Information', + 1 => 'Image Only', + # 2 appears to be unused + 3 => 'Image and Histogram', + }, + }, + 0x3f => { #PH + Name => 'NoiseReduction', + PrintConv => \%offOn, + }, + 0x40 => { #20 + Name => 'EyeStartAF', + PrintConv => \%onOff, + }, + 0x41 => { #20 + Name => 'RedEyeReduction', + PrintConv => \%offOn, + }, + 0x42 => { #20 + Name => 'FlashDefault', + PrintConv => { + 0 => 'Auto', + 1 => 'Fill Flash', + }, + }, + 0x43 => { #20 + Name => 'AutoBracketOrder', + PrintConv => { + 0 => '0 - +', + 1 => '- 0 +', + }, + }, + 0x44 => { #20 + Name => 'FocusHoldButton', + PrintConv => { + 0 => 'Focus Hold', + 1 => 'DOF Preview', + }, + }, + 0x45 => { #20 + Name => 'AELButton', + PrintConv => { + 0 => 'Hold', + 1 => 'Toggle', + 2 => 'Spot Hold', + 3 => 'Spot Toggle', + }, + }, + 0x46 => { #20 + Name => 'ControlDialSet', + PrintConv => { + 0 => 'Shutter Speed', + 1 => 'Aperture', + }, + }, + 0x47 => { #20 + Name => 'ExposureCompensationMode', + PrintConv => { + 0 => 'Ambient and Flash', + 1 => 'Ambient Only', + }, + }, + 0x48 => { #20 + Name => 'AFAssist', + PrintConv => \%onOff, + }, + 0x49 => { #20 + Name => 'CardShutterLock', + PrintConv => \%onOff, + }, + 0x4a => { #20 + Name => 'LensShutterLock', + PrintConv => \%onOff, + }, + 0x4b => { #20 + Name => 'AFAreaIllumination', + PrintConv => { + 0 => '0.3 s', + 1 => '0.6 s', + 2 => 'Off', + }, + }, + 0x4c => { #20 + Name => 'MonitorDisplayOff', + PrintConv => { + 0 => 'Automatic', + 1 => 'Manual', + }, + }, + 0x4d => { #20 + Name => 'RecordDisplay', + PrintConv => { + 0 => 'Auto Rotate', + 1 => 'Horizontal', + }, + }, + 0x4e => { #20 + Name => 'PlayDisplay', + PrintConv => { + 0 => 'Auto Rotate', + 1 => 'Manual Rotate', + }, + }, + 0x50 => { #20 + Name => 'ExposureIndicator', + SeparateTable => 'ExposureIndicator', + PrintConv => \%exposureIndicator, + }, + 0x51 => { #20 + Name => 'AELExposureIndicator', + Notes => 'also indicates exposure for next shot when bracketing', + SeparateTable => 'ExposureIndicator', + PrintConv => \%exposureIndicator, + }, + 0x52 => { #20 + Name => 'ExposureBracketingIndicatorLast', + Notes => 'indicator for last shot when bracketing', + SeparateTable => 'ExposureIndicator', + PrintConv => \%exposureIndicator, + }, + 0x53 => { #20 + Name => 'MeteringOffScaleIndicator', + Notes => 'two flashing triangles when under or over metering scale', + PrintConv => { + 0 => 'Within Range', + 1 => 'Under/Over Range', + 255 => 'Out of Range', + }, + }, + 0x54 => { #20 + Name => 'FlashExposureIndicator', + SeparateTable => 'ExposureIndicator', + PrintConv => \%exposureIndicator, + }, + 0x55 => { #20 + Name => 'FlashExposureIndicatorNext', + Notes => 'indicator for next shot when bracketing', + SeparateTable => 'ExposureIndicator', + PrintConv => \%exposureIndicator, + }, + 0x56 => { #20 + Name => 'FlashExposureIndicatorLast', + Notes => 'indicator for last shot when bracketing', + SeparateTable => 'ExposureIndicator', + PrintConv => \%exposureIndicator, + }, + 0x58 => { #20 + Name => 'FocusModeSwitch', + PrintConv => { + 0 => 'AF', + 1 => 'MF', + }, + }, + 0x59 => { #20 + Name => 'FlashType', + PrintConv => { + 0 => 'Off', + 1 => 'Built-in', # (also when built-in flash is a trigger in wireless mode) + 2 => 'External', + }, + }, + 0x5a => { #15 + Name => 'Rotation', + PrintConv => { + 0 => 'Horizontal (Normal)', + 1 => 'Rotate 270 CW', + 2 => 'Rotate 90 CW', + }, + }, + 0x5b => { #20 + Name => 'AELock', + PrintConv => \%offOn, + }, + 0x57 => { #15 + Name => 'ImageStabilization', + PrintConv => \%offOn, + }, + 0x5e => { #15 + Name => 'ColorTemperature', + ValueConv => '$val * 100', + ValueConvInv => '$val / 100', + }, + 0x5f => { #20 + Name => 'ColorCompensationFilter', + Format => 'int16s', + Notes => 'ranges from -2 for green to +2 for magenta', + }, + 0x60 => { #20 + Name => 'BatteryState', + PrintConv => { + 3 => 'Very Low', + 4 => 'Low', + 5 => 'Half Full', + 6 => 'Sufficient Power Remaining', + }, + }, +); + +# white balance information stored by the Sony DSLR-A100 (ref 20) +%Image::ExifTool::Minolta::WBInfoA100 = ( + PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData, + WRITE_PROC => \&Image::ExifTool::WriteBinaryData, + CHECK_PROC => \&Image::ExifTool::CheckBinaryData, + NOTES => 'White balance information for the Sony DSLR-A100.', + WRITABLE => 1, + GROUPS => { 0 => 'MakerNotes', 2 => 'Camera' }, + FIRST_ENTRY => 0, + PRIORITY => 0, + 0x0e => { + Name => 'DriveMode', + PrintConv => { + 0 => 'Self-timer 10 sec', + 1 => 'Continuous', + 2 => 'Single-frame Exposure Bracketing', + 3 => 'Continuous Exposure Bracketing', + 4 => 'Self-Timer 2 sec', + 5 => 'Single Frame', + 8 => 'White Balance Bracketing Low', + 9 => 'White Balance Bracketing High', + }, + }, + 0x10 => { + Name => 'Rotation', + PrintConv => { + 0 => 'Horizontal (normal)', + 1 => 'Rotate 270 CW', + 2 => 'Rotate 90 CW', + }, + }, + 0x14 => { + Name => 'ImageStabilizationSetting', + PrintConv => { 0 => 'Off', 1 => 'On' }, + }, + 0x15 => { + Name => 'DynamicRangeOptimizerMode', + PrintConv => { + 0 => 'Off', + 1 => 'Standard', + 2 => 'Advanced', + }, + }, + 0x2a => { + Name => 'ExposureCompensationMode', + PrintConv => { + 0 => 'Ambient and Flash', + 1 => 'Ambient Only', + }, + }, + 0x2b => 'WBBracketShotNumber', + 0x2c => { + Name => 'WhiteBalanceBracketing', + PrintConv => { + 0 => 'Off', + 1 => 'Low', + 2 => 'High', + }, + }, + 0x2d => 'ExposureBracketShotNumber', + 0x31 => { + Name => 'FlashFunction', + Format => 'int16u', + PrintHex => 1, + PrintConv => { + 0x0000 => 'No flash', + 0x0300 => 'Built-in flash', + # (the following refers to an external flash) + 0x1205 => 'Manual', + 0x120e => 'Strobe', + #0x122e => ? + 0x128e => 'Fill flash, Pre-flash TTL', + 0x12ae => 'Bounce flash', + 0x140e => 'Rear sync, ADI', + 0x148e => 'Fill flash, ADI', + 0x1580 => 'Wireless', + # 0x17ae => ? + 0x178e => 'HSS', + }, + }, + 0x34 => { + Name => 'ExposureMode', + Format => 'int16u', + PrintHex => 1, + PrintConvColumns => 2, + PrintConv => { + 0x0000 => 'Program', + 0x0001 => 'Aperture Priority', + 0x0002 => 'Shutter Priority', + 0x0003 => 'Manual', + 0x0004 => 'Auto', + 0x0005 => 'Program Shift A', + 0x0006 => 'Program Shift S', + 0x1013 => 'Portrait', + 0x1023 => 'Sports', + 0x1033 => 'Sunset', + 0x1043 => 'Night View/Portrait', + 0x1053 => 'Landscape', + 0x1083 => 'Macro', + }, + }, + 0x36 => { + Name => 'ColorMode', + Format => 'int16u', + PrintConv => { + 0x00 => 'Standard', + 0x01 => 'Vivid', + 0x02 => 'Portrait', + 0x03 => 'Landscape', + 0x04 => 'Sunset', + 0x05 => 'Night View', + 0x07 => 'B&W', + 0x08 => 'Adobe RGB', + }, + }, + 0x38 => { + Name => 'AverageLV', + Format => 'int16u', + Notes => 'arithmetic mean of the readings from the 40 honeycomb segments', + ValueConv => '($val-106)/8', + ValueConvInv => '$val * 8 + 106', + }, + # 0x3a - int16u: Approx FocusDistance in metres (0x0f50=inf) + 0x3c => { + Name => 'FrameNumber', + # Numbers > 1 appear in continuous and continuous bracketing drive modes, + # as well as WB bracketing. + }, + 0x96 => { Name => 'WB_RGBLevels', Format => 'int16u[3]' }, + 0xae => { Name => 'WB_GBRGLevels', Format => 'int16u[4]' }, + 0xc0 => { + Name => 'WB_RedLevelsTungsten', + Notes => '7 values for adjustments of -3 through +3', + Format => 'int16u[7]', + }, + 0xce => { Name => 'WB_BlueLevelsTungsten', Format => 'int16u[7]' }, + 0xdc => { Name => 'WB_RedLevelsDaylight', Format => 'int16u[7]' }, + 0xea => { Name => 'WB_BlueLevelsDaylight', Format => 'int16u[7]' }, + 0xf8 => { Name => 'WB_RedLevelsCloudy', Format => 'int16u[7]' }, + 0x106 => { Name => 'WB_BlueLevelsCloudy', Format => 'int16u[7]' }, + 0x114 => { Name => 'WB_RedLevelsFlash', Format => 'int16u[7]' }, + 0x122 => { Name => 'WB_BlueLevelsFlash', Format => 'int16u[7]' }, + 0x14c => { + Name => 'WB_RedLevelsFluorescent', + Format => 'int16u[7]', + Notes => q{ + white balance red presets for fluorescent -2 through +4: -2=Fluorescent, + -1=WhiteFluorescent, 0=CoolWhiteFluorescent, +1=DayWhiteFluorescent and + +3=DaylightFluorescent + }, + }, + 0x15a => { Name => 'WB_BlueLevelsFluorescent', Format => 'int16u[7]' }, + 0x168 => { Name => 'WB_RedLevelsShade', Format => 'int16u[7]' }, + 0x176 => { Name => 'WB_BlueLevelsShade', Format => 'int16u[7]' }, + 0x188 => { Name => 'WB_RedLevel6500K', Format => 'int16u' }, + 0x18a => { Name => 'WB_BlueLevel6500K', Format => 'int16u' }, + 0x18c => { Name => 'WB_RedLevelCustom', Format => 'int16u' }, + 0x18e => { Name => 'WB_BlueLevelCustom', Format => 'int16u' }, + 0x198 => { Name => 'WB_RedLevel3500K', Format => 'int16u' }, + 0x19a => { Name => 'WB_BlueLevel3500K', Format => 'int16u' }, + 0x1be => { + Name => 'WB_RedLevelsKelvin', + Format => 'int16u[75]', + Notes => 'values for 2500-9900 K, in increments of 100 K', + }, + 0x254 => { Name => 'WB_BlueLevelsKelvin', Format => 'int16u[75]' }, + 0x304 => { Name => 'WB_RBLevelsFlash', Format => 'int16u[2]' }, + 0x308 => { Name => 'WB_RBLevelsCoolWhiteF', Format => 'int16u[2]' }, + 0x3e8 => { Name => 'WB_RBLevelsTungsten', Format => 'int16u[2]' }, + 0x3ec => { Name => 'WB_RBLevelsDaylight', Format => 'int16u[2]' }, + 0x3f0 => { Name => 'WB_RBLevelsCloudy', Format => 'int16u[2]' }, + 0x3f4 => { Name => 'WB_RBLevelsFlash', Format => 'int16u[2]' }, + 0x3fc => { Name => 'WB_RedLevelsFluorescent', Format => 'int16u[7]' }, + 0x40a => { Name => 'WB_BlueLevelsFluorescent', Format => 'int16u[7]' }, + 0x418 => { Name => 'WB_RBLevelsShade', Format => 'int16u[2]' }, + 0x420 => { Name => 'WB_RBLevels6500K', Format => 'int16u[2]' }, + 0x424 => { Name => 'WB_RBLevelsCustom', Format => 'int16u[2]' }, + 0x430 => { Name => 'WB_RBLevels3500K', Format => 'int16u[2]' }, + 0x528 => { Name => 'WB_RBLevelsDaylight', Format => 'int16u[2]' }, + 0x546 => { Name => 'WB_RGBLevels', Format => 'int16u[3]' }, + 0x628 => { + Name => 'AEMeteringSegments', + Format => 'int8u[40]', + Notes => q{ + metering values from the 40 honeycomb segments, converted to LV. The first + value is for the outer cell, then the values are given row by row, from top + to bottom, with each row scanned left-to-right. The 21st value is the + middle cell, which gives the spot metering + }, + ValueConv => sub { join ' ', map( { ($_ - 106) / 8 } split(' ',$_[0]) ) }, + ValueConvInv => sub { join ' ', map( { int($_ * 8 + 106.5) } split(' ',$_[0]) ) }, + }, + 0x690 => { + Name => 'MeasuredLV', + Notes => 'measured light value based on MeteringMode', + ValueConv => '($val-106)/8', + ValueConvInv => '$val * 8 + 106', + }, + 0x691 => { + Name => 'BrightnessValue', + ValueConv => '($val-106)/8', + ValueConvInv => '$val * 8 + 106', + }, + # 0x87f - int8u: 33mm Equivalent magnification (FocusDistance = (1.5 * $val + 1) * FocalLength) (255=inf) + 0x104c => { # (9600 bytes: 4 sets of 40x30 int16u values in the range 0-8191) + Name => 'TiffMeteringImage', + Format => 'undef[9600]', + Notes => q{ + 13-bit RBGG (?) 40x30 pixels, presumably metering info, converted to a 16-bit + TIFF image; + }, + ValueConv => sub { + my ($val, $et) = @_; + return undef unless length $val >= 9600; + return \ "Binary data 7404 bytes" unless $et->Options('Binary'); + my @dat = unpack('n*', $val); # for Big-endian + # TIFF header for a 16-bit RGB 10dpi 40x30 image + $val = Image::ExifTool::MakeTiffHeader(40,30,3,16,10); + # re-order data to RGB pixels + my ($i, @val); + for ($i=0; $i<40*30; ++$i) { + # data is 13-bit (max 8191), shift left to fill 16 bits + # (typically, this gives a very dark image since the data should + # really be anti-logged to convert from EV to perceived brightness) +# push @val, $dat[$i]<<3, $dat[$i+2400]<<3, $dat[$i+1200]<<3; + push @val, int(5041.1*log($dat[$i]+1)/log(2)), int(5041.1*log($dat[$i+2400]+1)/log(2)), int(5041.1*log($dat[$i+1200]+1)/log(2)); + } + $val .= pack('v*', @val); # add TIFF strip data + return \$val; + }, + }, + 0x49b8 => { + Name => 'ExposureTime', + ValueConv => '$val ? 2 ** (6 - $val/8) : 0', + ValueConvInv => '$val ? int((6 - log($val) / log(2)) * 8 + 0.5) : 0', + PrintConv => '$val ? Image::ExifTool::Exif::PrintExposureTime($val) : "Bulb"', + PrintConvInv => 'lc($val) eq "bulb" ? 0 : Image::ExifTool::Exif::ConvertFraction($val)', + }, + 0x49ba => { + Name => 'ISO', + ValueConv => '2 ** (($val-48)/8) * 100', + ValueConvInv => '48 + 8*log($val/100)/log(2)', + PrintConv => 'int($val + 0.5)', + PrintConvInv => '$val', + }, + 0x49bb => { # (http://u88.n24.queensu.ca/exiftool/forum/index.php/topic,3688.0.html) + # if this value is the 35mm equivalent magnification, then the formula could + # be (1.5 * 2**($val/16-5)+1) * FocalLength, but this tends to underestimate + # distance by about 18% (ref 20) (255=inf) + Name => 'FocusDistance', + ValueConv => '2**(($val-126)/16)', + ValueConvInv => 'log($val)/log(2)*16+126', + PrintConv => '$val > 266 ? "inf" : sprintf("%.2f m", $val)', + PrintConvInv => '$val=~s/ ?m//; $val=~/inf/i ? 267 : $val', + }, + 0x49bd => { + Name => 'LensType', + Format => 'int16uRev', + SeparateTable => 1, + ValueConvInv => 'int($val)', # (must truncate decimal part) + PrintConv => \%minoltaLensTypes, + }, + 0x49c0 => { + Name => 'ExposureCompensation', # (in exposure bracketing, this is the actual value used) + Format => 'int8s', + ValueConv => '$val / 8', + ValueConvInv => '$val * 8', + PrintConv => '$val ? sprintf("%+.1f",$val) : 0', + PrintConvInv => 'Image::ExifTool::Exif::ConvertFraction($val)', + }, + 0x49c1 => { + Name => 'FlashExposureComp', + Description => 'Flash Exposure Compensation', + Format => 'int8s', + ValueConv => '$val / 8', + ValueConvInv => '$val * 8', + PrintConv => '$val ? sprintf("%+.1f",$val) : 0', + PrintConvInv => 'Image::ExifTool::Exif::ConvertFraction($val)', + }, + 0x49c2 => { + Name => 'ImageStabilization', + PrintConv => \%offOn, + }, + 0x49c3 => { + Name => 'BrightnessValue', + ValueConv => '($val-106)/8', + ValueConvInv => '$val * 8 + 106', + }, + 0x49c5 => { + Name => 'MaxAperture', + ValueConv => '2 ** (($val-8)/16)', + ValueConvInv => '8 + 16*log($val)/log(2)', + PrintConv => 'sprintf("%.1f",$val)', + PrintConvInv => '$val', + }, + # 0x49c6 - gives focal length using same formula as 0x49bb + 0x49c7 => { + Name => 'FNumber', + ValueConv => '2 ** (($val-8)/16)', + ValueConvInv => '8 + 16*log($val)/log(2)', + PrintConv => 'sprintf("%.1f",$val)', + PrintConvInv => '$val', + }, + 0x49dc => { + Name => 'InternalSerialNumber', + Format => 'string[12]', + }, +); + +# tags in Konica Minolta MOV videos (ref PH) +# (similar information in Kodak,Minolta,Nikon,Olympus,Pentax and Sanyo videos) +%Image::ExifTool::Minolta::MOV1 = ( + PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData, + GROUPS => { 0 => 'MakerNotes', 2 => 'Camera' }, + FIRST_ENTRY => 0, + NOTES => q{ + This information is found in MOV videos from some Konica Minolta models such + as the DiMage Z10 and X50. + }, + 0 => { + Name => 'Make', + Format => 'string[32]', + }, + 0x20 => { + Name => 'ModelType', + Format => 'string[8]', + }, + # (01 00 at offset 0x28) + 0x2e => { + Name => 'ExposureTime', + Format => 'int32u', + ValueConv => '$val ? 10 / $val : 0', + PrintConv => 'Image::ExifTool::Exif::PrintExposureTime($val)', + }, + 0x32 => { + Name => 'FNumber', + Format => 'rational64u', + PrintConv => 'sprintf("%.1f",$val)', + }, + 0x3a => { + Name => 'ExposureCompensation', + Format => 'rational64s', + PrintConv => 'Image::ExifTool::Exif::PrintFraction($val)', + }, + # 0x4c => 'WhiteBalance', ? + 0x50 => { + Name => 'FocalLength', + Format => 'rational64u', + PrintConv => 'sprintf("%.1f mm",$val)', + }, +); + +# tags in Minolta MOV videos (ref PH) +# (similar information in Kodak,Minolta,Nikon,Olympus,Pentax and Sanyo videos) +%Image::ExifTool::Minolta::MOV2 = ( + PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData, + GROUPS => { 0 => 'MakerNotes', 2 => 'Camera' }, + FIRST_ENTRY => 0, + NOTES => q{ + This information is found in MOV videos from some Minolta models such as the + DiMAGE X and Xt. + }, + 0 => { + Name => 'Make', + Format => 'string[32]', + }, + 0x18 => { + Name => 'ModelType', + Format => 'string[8]', + }, + # (01 00 at offset 0x20) + 0x26 => { + Name => 'ExposureTime', + Format => 'int32u', + ValueConv => '$val ? 10 / $val : 0', + PrintConv => 'Image::ExifTool::Exif::PrintExposureTime($val)', + }, + 0x2a => { + Name => 'FNumber', + Format => 'rational64u', + PrintConv => 'sprintf("%.1f",$val)', + }, + 0x32 => { + Name => 'ExposureCompensation', + Format => 'rational64s', + PrintConv => 'Image::ExifTool::Exif::PrintFraction($val)', + }, + # 0x44 => 'WhiteBalance', ? + 0x48 => { + Name => 'FocalLength', + Format => 'rational64u', + PrintConv => 'sprintf("%.1f mm",$val)', + }, +); + +# more tags in Minolta MOV videos (ref PH) +%Image::ExifTool::Minolta::MMA = ( + PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData, + GROUPS => { 0 => 'MakerNotes', 2 => 'Camera' }, + NOTES => q{ + This information is found in MOV videos from Minolta models such as the + DiMAGE A2, S414 and 7Hi. + }, + 0 => { + Name => 'Make', + Format => 'string[20]', + }, + 20 => { + Name => 'SoftwareVersion', + Format => 'string[16]', + }, +); + +# basic Minolta white balance lookup +my %minoltaWhiteBalance = ( + 0 => 'Auto', + 1 => 'Daylight', + 2 => 'Cloudy', + 3 => 'Tungsten', + 5 => 'Custom', + 7 => 'Fluorescent', + 8 => 'Fluorescent 2', + 11 => 'Custom 2', + 12 => 'Custom 3', + # the following come from tests with the A2 (ref 2) + 0x0800000 => 'Auto', + 0x1800000 => 'Daylight', + 0x2800000 => 'Cloudy', + 0x3800000 => 'Tungsten', + 0x4800000 => 'Flash', + 0x5800000 => 'Fluorescent', + 0x6800000 => 'Shade', + 0x7800000 => 'Custom1', + 0x8800000 => 'Custom2', + 0x9800000 => 'Custom3', +); + +#------------------------------------------------------------------------------ +# PrintConv for Minolta white balance +sub ConvertWhiteBalance($) +{ + my $val = shift; + my $printConv = $minoltaWhiteBalance{$val}; + unless (defined $printConv) { + if ($val & 0xffff0000) { + # the A2 values can be shifted by +- 3 settings, where + # each setting adds or subtracts 0x0010000 (ref 2) + my $type = ($val & 0xff000000) + 0x800000; + if ($minoltaWhiteBalance{$type}) { + $printConv = $minoltaWhiteBalance{$type} . + sprintf("%+.8g", ($val - $type) / 0x10000); + } else { + $printConv = sprintf("Unknown (0x%x)", $val); + } + } else { + $printConv = sprintf("Unknown ($val)"); + } + } + return $printConv; +} + +1; # end + +__END__ + +=head1 NAME + +Image::ExifTool::Minolta - Minolta EXIF maker notes tags + +=head1 SYNOPSIS + +This module is loaded automatically by Image::ExifTool when required. + +=head1 DESCRIPTION + +This module contains definitions required by Image::ExifTool to interpret +Minolta and Konica-Minolta maker notes in EXIF information, and to read +and write Minolta RAW (MRW) images. + +=head1 AUTHOR + +Copyright 2003-2019, Phil Harvey (phil at owl.phy.queensu.ca) + +This library is free software; you can redistribute it and/or modify it +under the same terms as Perl itself. + +=head1 REFERENCES + +=over 4 + +=item L<http://www.dalibor.cz/minolta/makernote.htm> + +=item L<http://www.cybercom.net/~dcoffin/dcraw/> + +=back + +=head1 ACKNOWLEDGEMENTS + +Thanks to Jay Al-Saadi, Niels Kristian Bech Jensen, Shingo Noguchi, Pedro +Corte-Real, Jeffery Small, Jens Duttke, Thomas Kassner, Mladen Sever, Olaf +Ulrich, Lukasz Stelmach, Igal Milchtaich, Jos Roost and Michael Reitinger +for the information they provided, and for everyone who helped with the +LensType list. + +=head1 SEE ALSO + +L<Image::ExifTool::TagNames/Minolta Tags>, +L<Image::ExifTool(3pm)|Image::ExifTool> + +=cut diff --git a/lib/Image/ExifTool/MinoltaRaw.pm b/lib/Image/ExifTool/MinoltaRaw.pm new file mode 100644 index 0000000..1b5d115 --- /dev/null +++ b/lib/Image/ExifTool/MinoltaRaw.pm @@ -0,0 +1,535 @@ +#------------------------------------------------------------------------------ +# File: MinoltaRaw.pm +# +# Description: Read/write Konica-Minolta RAW (MRW) meta information +# +# Revisions: 03/11/2006 - P. Harvey Split out from Minolta.pm +# +# References: 1) http://www.cybercom.net/~dcoffin/dcraw/ +# 2) http://www.chauveau-central.net/mrw-format/ +# 3) Igal Milchtaich private communication (A100) +#------------------------------------------------------------------------------ + +package Image::ExifTool::MinoltaRaw; + +use strict; +use vars qw($VERSION); +use Image::ExifTool qw(:DataAccess :Utils); +use Image::ExifTool::Minolta; + +$VERSION = '1.15'; + +sub ProcessMRW($$;$); +sub WriteMRW($$;$); + +# Minolta MRW tags +%Image::ExifTool::MinoltaRaw::Main = ( + GROUPS => { 0 => 'MakerNotes', 2 => 'Camera' }, + PROCESS_PROC => \&Image::ExifTool::MinoltaRaw::ProcessMRW, + WRITE_PROC => \&Image::ExifTool::MinoltaRaw::WriteMRW, + NOTES => 'These tags are used in Minolta RAW format (MRW) images.', + "\0TTW" => { # TIFF Tags + Name => 'MinoltaTTW', + SubDirectory => { + TagTable => 'Image::ExifTool::Exif::Main', + # this EXIF information starts with a TIFF header + ProcessProc => \&Image::ExifTool::ProcessTIFF, + WriteProc => \&Image::ExifTool::WriteTIFF, + }, + }, + "\0PRD" => { # Raw Picture Dimensions + Name => 'MinoltaPRD', + SubDirectory => { TagTable => 'Image::ExifTool::MinoltaRaw::PRD' }, + }, + "\0WBG" => { # White Balance Gains + Name => 'MinoltaWBG', + SubDirectory => { TagTable => 'Image::ExifTool::MinoltaRaw::WBG' }, + }, + "\0RIF" => { # Requested Image Format + Name => 'MinoltaRIF', + SubDirectory => { TagTable => 'Image::ExifTool::MinoltaRaw::RIF' }, + }, + # "\0CSA" is padding +); + +# Minolta MRW PRD information (ref 2) +%Image::ExifTool::MinoltaRaw::PRD = ( + PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData, + WRITE_PROC => \&Image::ExifTool::WriteBinaryData, + CHECK_PROC => \&Image::ExifTool::CheckBinaryData, + WRITABLE => 1, + GROUPS => { 0 => 'MakerNotes', 2 => 'Camera' }, + FIRST_ENTRY => 0, + 0 => { + Name => 'FirmwareID', + Format => 'string[8]', + }, + 8 => { + Name => 'SensorHeight', + Format => 'int16u', + }, + 10 => { + Name => 'SensorWidth', + Format => 'int16u', + }, + 12 => { + Name => 'ImageHeight', + Format => 'int16u', + }, + 14 => { + Name => 'ImageWidth', + Format => 'int16u', + }, + 16 => { + Name => 'RawDepth', + Format => 'int8u', + }, + 17 => { + Name => 'BitDepth', + Format => 'int8u', + }, + 18 => { + Name => 'StorageMethod', + Format => 'int8u', + PrintConv => { + 82 => 'Padded', + 89 => 'Linear', + }, + }, + 23 => { + Name => 'BayerPattern', + Format => 'int8u', + PrintConv => { + # 0 - seen in some Sony A850 ARW images + 1 => 'RGGB', + 4 => 'GBRG', + }, + }, +); + +# Minolta MRW WBG information (ref 2) +%Image::ExifTool::MinoltaRaw::WBG = ( + PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData, + WRITE_PROC => \&Image::ExifTool::WriteBinaryData, + CHECK_PROC => \&Image::ExifTool::CheckBinaryData, + WRITABLE => 1, + GROUPS => { 0 => 'MakerNotes', 2 => 'Camera' }, + FIRST_ENTRY => 0, + 0 => { + Name => 'WBScale', + Format => 'int8u[4]', + }, + 4 => [ + { + Condition => '$$self{Model} =~ /DiMAGE A200\b/', + Name => 'WB_GBRGLevels', + Format => 'int16u[4]', + Notes => 'DiMAGE A200', + }, + { + Name => 'WB_RGGBLevels', + Format => 'int16u[4]', + Notes => 'other models', + }, + ], +); + +# Minolta MRW RIF information (ref 2) +%Image::ExifTool::MinoltaRaw::RIF = ( + PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData, + WRITE_PROC => \&Image::ExifTool::WriteBinaryData, + CHECK_PROC => \&Image::ExifTool::CheckBinaryData, + WRITABLE => 1, + GROUPS => { 0 => 'MakerNotes', 2 => 'Image' }, + FIRST_ENTRY => 0, + 1 => { + Name => 'Saturation', + Format => 'int8s', + }, + 2 => { + Name => 'Contrast', + Format => 'int8s', + }, + 3 => { + Name => 'Sharpness', + Format => 'int8s', + }, + 4 => { + Name => 'WBMode', + PrintConv => 'Image::ExifTool::MinoltaRaw::ConvertWBMode($val)', + }, + 5 => { + Name => 'ProgramMode', + PrintConv => { + 0 => 'None', + 1 => 'Portrait', + 2 => 'Text', + 3 => 'Night Portrait', + 4 => 'Sunset', + 5 => 'Sports', + # have seen these values in Sony ARW images: - PH + # 7, 128, 129, 160 + }, + }, + 6 => { + Name => 'ISOSetting', + RawConv => '$val == 255 ? undef : $val', + PrintConv => { #3 + 0 => 'Auto', + 48 => 100, + 56 => 200, + 64 => 400, + 72 => 800, + 80 => 1600, + 174 => '80 (Zone Matching Low)', + 184 => '200 (Zone Matching High)', + OTHER => sub { + my ($val, $inv) = @_; + return int(2 ** (($val-48)/8) * 100 + 0.5) unless $inv; + # (must check for zero below in inverse conversion) + return 48 + 8*log($val/100)/log(2) if Image::ExifTool::IsFloat($val) and $val != 0; + return undef; + }, + }, + #ValueConv => '2 ** (($val-48)/8) * 100', + #ValueConvInv => '48 + 8*log($val/100)/log(2)', + #PrintConv => 'int($val + 0.5)', + #PrintConvInv => '$val', + }, + 7 => [ + { + Name => 'ColorMode', + Condition => '$$self{Make} !~ /^SONY/', + Priority => 0, + Writable => 'int32u', + PrintConv => \%Image::ExifTool::Minolta::minoltaColorMode, + }, + { #3 + Name => 'ColorMode', + Condition => '$$self{Model} eq "DSLR-A100"', + Writable => 'int32u', + Notes => 'Sony A100', + Priority => 0, + PrintHex => 1, + PrintConv => \%Image::ExifTool::Minolta::sonyColorMode, + }, + ], + # NOTE: some of these WB_RBLevels may apply to other models too... + 8 => { #3 + Name => 'WB_RBLevelsTungsten', + Condition => '$$self{Model} eq "DSLR-A100"', + Format => 'int16u[2]', + Notes => 'these WB_RBLevels currently decoded only for the Sony A100', + }, + 12 => { #3 + Name => 'WB_RBLevelsDaylight', + Condition => '$$self{Model} eq "DSLR-A100"', + Format => 'int16u[2]', + }, + 16 => { #3 + Name => 'WB_RBLevelsCloudy', + Condition => '$$self{Model} eq "DSLR-A100"', + Format => 'int16u[2]', + }, + 20 => { #3 + Name => 'WB_RBLevelsCoolWhiteF', + Condition => '$$self{Model} eq "DSLR-A100"', + Format => 'int16u[2]', + }, + 24 => { #3 + Name => 'WB_RBLevelsFlash', + Condition => '$$self{Model} eq "DSLR-A100"', + Format => 'int16u[2]', + }, + 28 => { #3 + Name => 'WB_RBLevelsUnknown', + Condition => '$$self{Model} eq "DSLR-A100"', + Format => 'int16u[2]', + Unknown => 1, + }, + 32 => { #3 + Name => 'WB_RBLevelsShade', + Condition => '$$self{Model} eq "DSLR-A100"', + Format => 'int16u[2]', + }, + 36 => { #3 + Name => 'WB_RBLevelsDaylightF', + Condition => '$$self{Model} eq "DSLR-A100"', + Format => 'int16u[2]', + }, + 40 => { #3 + Name => 'WB_RBLevelsDayWhiteF', + Condition => '$$self{Model} eq "DSLR-A100"', + Format => 'int16u[2]', + }, + 44 => { #3 + Name => 'WB_RBLevelsWhiteF', + Condition => '$$self{Model} eq "DSLR-A100"', + Format => 'int16u[2]', + }, + 56 => { + Name => 'ColorFilter', + Condition => '$$self{Make} !~ /^SONY/', + Format => 'int8s', + Notes => 'Minolta models', + }, + 57 => 'BWFilter', + 58 => { + Name => 'ZoneMatching', + Condition => '$$self{Make} !~ /^SONY/', + Priority => 0, + Notes => 'Minolta models', + PrintConv => { + 0 => 'ISO Setting Used', + 1 => 'High Key', + 2 => 'Low Key', + }, + }, + 59 => { + Name => 'Hue', + Format => 'int8s', + }, + 60 => { + Name => 'ColorTemperature', + Condition => '$$self{Make} !~ /^SONY/', + Notes => 'Minolta models', + ValueConv => '$val * 100', + ValueConvInv => '$val / 100', + }, + 74 => { #3 + Name => 'ZoneMatching', + Condition => '$$self{Make} =~ /^SONY/', + Priority => 0, + Notes => 'Sony models', + PrintConv => { + 0 => 'ISO Setting Used', + 1 => 'High Key', + 2 => 'Low Key', + }, + }, + 76 => { #3 + Name => 'ColorTemperature', + Condition => '$$self{Model} eq "DSLR-A100"', + Notes => 'A100', + ValueConv => '$val * 100', + ValueConvInv => '$val / 100', + PrintConv => '$val ? $val : "Auto"', + PrintConvInv => '$val=~/Auto/i ? 0 : $val', + }, + 77 => { #3 + Name => 'ColorFilter', + Condition => '$$self{Model} eq "DSLR-A100"', + Notes => 'A100', + }, + 78 => { #3 + Name => 'ColorTemperature', + Condition => '$$self{Model} =~ /^DSLR-A(200|700)$/', + Notes => 'A200 and A700', + ValueConv => '$val * 100', + ValueConvInv => '$val / 100', + PrintConv => '$val ? $val : "Auto"', + PrintConvInv => '$val=~/Auto/i ? 0 : $val', + }, + 79 => { #3 + Name => 'ColorFilter', + Condition => '$$self{Model} =~ /^DSLR-A(200|700)$/', + Notes => 'A200 and A700', + }, + 80 => { #3 + Name => 'RawDataLength', + Condition => '$$self{Model} eq "DSLR-A100"', + Format => 'int32u', + Notes => 'A100', + Writable => 0, + }, +); + +#------------------------------------------------------------------------------ +# PrintConv for WBMode +sub ConvertWBMode($) +{ + my $val = shift; + my %mrwWB = ( + 0 => 'Auto', + 1 => 'Daylight', + 2 => 'Cloudy', + 3 => 'Tungsten', + 4 => 'Flash/Fluorescent', + 5 => 'Fluorescent', + 6 => 'Shade', + 7 => 'User 1', + 8 => 'User 2', + 9 => 'User 3', + 10 => 'Temperature', + ); + my $lo = $val & 0x0f; + my $wbstr = $mrwWB{$lo} || "Unknown ($lo)"; + my $hi = $val >> 4; + $wbstr .= ' (' . ($hi - 8) . ')' if $hi >= 6 and $hi <=12; + return $wbstr; +} + +#------------------------------------------------------------------------------ +# Write MRW directory (eg. in ARW images) +# Inputs: 0) ExifTool object ref, 1) dirInfo ref, 2) optional tag table ref +# Returns: new MRW data or undef on error +sub WriteMRW($$;$) +{ + my ($et, $dirInfo, $tagTablePtr) = @_; + $et or return 1; # allow dummy access + my $buff = ''; + $$dirInfo{OutFile} = \$buff; + ProcessMRW($et, $dirInfo, $tagTablePtr) > 0 or undef $buff; + return $buff; +} + +#------------------------------------------------------------------------------ +# Read or write Minolta MRW file +# Inputs: 0) ExifTool object ref, 1) dirInfo ref, 2) optional tag table ref +# Returns: 1 on success, 0 if this wasn't a valid MRW file, or -1 on write error +# Notes: File pointer must be set to start of MRW in RAF upon entry +sub ProcessMRW($$;$) +{ + my ($et, $dirInfo, $tagTablePtr) = @_; + my $raf = $$dirInfo{RAF}; + my $outfile = $$dirInfo{OutFile}; + my $verbose = $et->Options('Verbose'); + my $out = $et->Options('TextOut'); + my ($data, $err, $outBuff); + + if ($$dirInfo{DataPt}) { + # make a RAF object for MRW information extracted from other file types + $raf = new File::RandomAccess($$dirInfo{DataPt}); + # MRW information in DNG images may not start at beginning of data block + $raf->Seek($$dirInfo{DirStart}, 0) if $$dirInfo{DirStart}; + } + $raf->Read($data,8) == 8 or return 0; + # "\0MRM" for big-endian (MRW images), and + # "\0MRI" for little-endian (MRWInfo in ARW images) + $data =~ /^\0MR([MI])/ or return 0; + my $hdr = "\0MR$1"; + SetByteOrder($1 . $1); + $et->SetFileType(); + $tagTablePtr = GetTagTable('Image::ExifTool::MinoltaRaw::Main'); + if ($outfile) { + $et->InitWriteDirs('TIFF'); # use same write dirs as TIFF + $outBuff = ''; + } + my $pos = $raf->Tell(); + my $offset = Get32u(\$data, 4) + $pos; + my $rtnVal = 1; + $verbose and printf $out " [MRW Data Offset: 0x%x]\n", $offset; + # loop through MRW segments (ref 1) + while ($pos < $offset) { + $raf->Read($data,8) == 8 or $err = 1, last; + $pos += 8; + my $tag = substr($data, 0, 4); + my $len = Get32u(\$data, 4); + if ($verbose) { + print $out "MRW ",$et->Printable($tag)," segment ($len bytes):\n"; + if ($verbose > 2) { + $raf->Read($data,$len) == $len and $raf->Seek($pos,0) or $err = 1, last; + $et->VerboseDump(\$data); + } + } + my $tagInfo = $et->GetTagInfo($tagTablePtr, $tag); + if ($tagInfo and $$tagInfo{SubDirectory}) { + my $subTable = GetTagTable($tagInfo->{SubDirectory}->{TagTable}); + my $buff; + # save shift for values stored with wrong base offset + $$et{MRW_WrongBase} = -($raf->Tell()); + $raf->Read($buff, $len) == $len or $err = 1, last; + my %subdirInfo = ( + DataPt => \$buff, + DataLen => $len, + DataPos => $pos, + DirStart => 0, + DirLen => $len, + DirName => $$tagInfo{Name}, + Parent => 'MRW', + NoTiffEnd => 1, # no end-of-TIFF check + ); + if ($outfile) { + my $writeProc = $tagInfo->{SubDirectory}->{WriteProc}; + my $val = $et->WriteDirectory(\%subdirInfo, $subTable, $writeProc); + if (defined $val and length $val) { + # pad to an even 4 bytes (can't hurt, and it seems to be the standard) + $val .= "\0" x (4 - (length($val) & 0x03)) if length($val) & 0x03; + $outBuff .= $tag . Set32u(length $val) . $val; + } elsif (not defined $val) { + $outBuff .= $data . $buff; # copy over original information + } + } else { + my $processProc = $tagInfo->{SubDirectory}->{ProcessProc}; + $et->ProcessDirectory(\%subdirInfo, $subTable, $processProc); + } + } elsif ($outfile) { + # add this segment to the output buffer + my $buff; + $raf->Read($buff, $len) == $len or $err = 1, last; + $outBuff .= $data . $buff; + } else { + # skip this segment + $raf->Seek($pos+$len, 0) or $err = 1, last; + } + $pos += $len; + } + $pos == $offset or $err = 1; # meta information length check + + if ($outfile) { + # write the file header then the buffered meta information + Write($outfile, $hdr, Set32u(length $outBuff), $outBuff) or $rtnVal = -1; + # copy over image data + while ($raf->Read($outBuff, 65536)) { + Write($outfile, $outBuff) or $rtnVal = -1; + } + # Sony IDC utility corrupts MRWInfo when writing ARW images, + # so make this a minor error for these images + $err and $et->Error("MRW format error", $$et{TIFF_TYPE} eq 'ARW'); + } else { + $err and $et->Warn("MRW format error"); + } + return $rtnVal; +} + +1; # end + +__END__ + +=head1 NAME + +Image::ExifTool::MinoltaRaw - Read/write Konica-Minolta RAW (MRW) information + +=head1 SYNOPSIS + +This module is loaded automatically by Image::ExifTool when required. + +=head1 DESCRIPTION + +This module contains definitions required by Image::ExifTool to read and +write Konica-Minolta RAW (MRW) images. + +=head1 AUTHOR + +Copyright 2003-2019, Phil Harvey (phil at owl.phy.queensu.ca) + +This library is free software; you can redistribute it and/or modify it +under the same terms as Perl itself. + +=head1 REFERENCES + +=over 4 + +=item L<http://www.cybercom.net/~dcoffin/dcraw/> + +=item L<http://www.chauveau-central.net/mrw-format/> + +=back + +=head1 SEE ALSO + +L<Image::ExifTool::TagNames/MinoltaRaw Tags>, +L<Image::ExifTool::Minolta(3pm)|Image::ExifTool::Minolta>, +L<Image::ExifTool(3pm)|Image::ExifTool> + +=cut diff --git a/lib/Image/ExifTool/Motorola.pm b/lib/Image/ExifTool/Motorola.pm new file mode 100644 index 0000000..b0d2612 --- /dev/null +++ b/lib/Image/ExifTool/Motorola.pm @@ -0,0 +1,62 @@ +#------------------------------------------------------------------------------ +# File: Motorola.pm +# +# Description: Read Motorola meta information +# +# Revisions: 2015/10/29 - P. Harvey Created +#------------------------------------------------------------------------------ + +package Image::ExifTool::Motorola; + +use strict; +use vars qw($VERSION); +use Image::ExifTool::Exif; + +$VERSION = '1.00'; + +# Motorola makernotes tags (ref PH) +%Image::ExifTool::Motorola::Main = ( + WRITE_PROC => \&Image::ExifTool::Exif::WriteExif, + CHECK_PROC => \&Image::ExifTool::Exif::CheckExif, + GROUPS => { 0 => 'MakerNotes', 2 => 'Camera' }, + WRITABLE => 1, + # 0x5570 - some sort of picture mode (auto,hdr) + # 0x6400 - HDR? (OFF,ON) + # 0x6410 - HDR? (NO,YES) + # 0x6420 - only exists in HDR images + 0x665e => { Name => 'Sensor', Writable => 'string' }, # (eg. "BACK,IMX230") + # 0x6700 - serial number? + 0x6705 => { Name => 'ManufactureDate', Writable => 'string' }, # (NC, eg. "03Jun2015") + # 0x6706 - serial number? +); + +1; # end + +__END__ + +=head1 NAME + +Image::ExifTool::Motorola - Read Motorola meta information + +=head1 SYNOPSIS + +This module is loaded automatically by Image::ExifTool when required. + +=head1 DESCRIPTION + +This module contains the definitions to read meta information from Motorola +cell phone images. + +=head1 AUTHOR + +Copyright 2003-2019, Phil Harvey (phil at owl.phy.queensu.ca) + +This library is free software; you can redistribute it and/or modify it +under the same terms as Perl itself. + +=head1 SEE ALSO + +L<Image::ExifTool::TagNames/Motorola Tags>, +L<Image::ExifTool(3pm)|Image::ExifTool> + +=cut diff --git a/lib/Image/ExifTool/Nikon.pm b/lib/Image/ExifTool/Nikon.pm new file mode 100644 index 0000000..bd6e8c7 --- /dev/null +++ b/lib/Image/ExifTool/Nikon.pm @@ -0,0 +1,9506 @@ +#------------------------------------------------------------------------------ +# File: Nikon.pm +# +# Description: Nikon EXIF maker notes tags +# +# Revisions: 12/09/2003 - P. Harvey Created +# 05/17/2004 - P. Harvey Added information from Joseph Heled +# 09/21/2004 - P. Harvey Changed tag 2 to ISOUsed & added PrintConv +# 12/01/2004 - P. Harvey Added default PRINT_CONV +# 01/01/2005 - P. Harvey Decode preview image and preview IFD +# 03/35/2005 - T. Christiansen additions +# 05/10/2005 - P. Harvey Decode encrypted lens data +# [ongoing] - P. Harvey Constantly decoding new information +# +# References: 1) http://park2.wakwak.com/~tsuruzoh/Computer/Digicams/exif-e.html +# 2) Joseph Heled private communication (tests with D70) +# 3) Thomas Walter private communication (tests with Coolpix 5400) +# 4) http://www.cybercom.net/~dcoffin/dcraw/ +# 5) Brian Ristuccia private communication (tests with D70) +# 6) Danek Duvall private communication (tests with D70) +# 7) Tom Christiansen private communication (tests with D70) +# 8) Robert Rottmerhusen private communication +# 9) http://members.aol.com/khancock/pilot/nbuddy/ +# 10) Werner Kober private communication (D2H, D2X, D100, D70, D200, D90) +# 11) http://www.rottmerhusen.com/objektives/lensid/thirdparty.html +# 12) http://libexif.sourceforge.net/internals/mnote-olympus-tag_8h-source.html +# 13) Roger Larsson private communication (tests with D200) +# 14) http://homepage3.nifty.com/kamisaka/makernote/makernote_nikon.htm (2007/09/15) +# 15) http://tomtia.plala.jp/DigitalCamera/MakerNote/index.asp +# 16) Jeffrey Friedl private communication (D200 with firmware update) +# 17) http://www.wohlberg.net/public/software/photo/nstiffexif/ +# and Brendt Wohlberg private communication +# 18) Anonymous user private communication (D70, D200, D2x) +# 19) Bruce Stevens private communication +# 20) Vladimir Sauta private communication (D80) +# 21) Gregor Dorlars private communication (D300) +# 22) Tanel Kuusk private communication +# 23) Alexandre Naaman private communication (D3) +# 24) Geert De Soete private communication +# 26) Bozi (http://www.cpanforum.com/posts/8983) +# 27) Jens Kriese private communication +# 28) Warren Hatch private communication (D3v2.00 with SB-800 and SB-900) +# 29) Anonymous contribution 2011/05/25 (D700, D7000) +# 30) http://u88.n24.queensu.ca/exiftool/forum/index.php/topic,3833.30.html +# 31) Michael Relt private communication +# 32) Stefan http://u88.n24.queensu.ca/exiftool/forum/index.php/topic,4494.0.html +# 34) Stewart Bennett private communication (D4S, D810) +# 35) David Puschel private communication +# IB) Iliah Borg private communication (LibRaw) +# JD) Jens Duttke private communication +# NJ) Niels Kristian Bech Jensen private communication +#------------------------------------------------------------------------------ + +package Image::ExifTool::Nikon; + +use strict; +use vars qw($VERSION %nikonLensIDs %nikonTextEncoding); +use Image::ExifTool qw(:DataAccess :Utils); +use Image::ExifTool::Exif; +use Image::ExifTool::GPS; + +$VERSION = '3.60'; + +sub LensIDConv($$$); +sub ProcessNikonAVI($$$); +sub ProcessNikonMOV($$$); +sub FormatString($); +sub ProcessNikonCaptureEditVersions($$$); +sub PrintAFPoints($$); +sub PrintAFPointsInv($$); +sub PrintAFPointsGrid($$); +sub PrintAFPointsGridInv($$$); +sub GetAFPointGrid($$;$); + +# nikon lens ID numbers (ref 8/11) +%nikonLensIDs = ( + Notes => q{ + The Nikon LensID is constructed as a Composite tag from the raw hex values + of 8 other tags: LensIDNumber, LensFStops, MinFocalLength, MaxFocalLength, + MaxApertureAtMinFocal, MaxApertureAtMaxFocal, MCUVersion and LensType, in + that order. (source: + L<http://www.rottmerhusen.com/objektives/lensid/thirdparty.html>.) Multiple + lenses with the same LensID are differentiated by decimal values in the list + below. The user-defined "Lenses" list may be used to specify the lens for + ExifTool to choose in these cases (see the + L<sample config file|../config.html> for details). + }, + OTHER => \&LensIDConv, + # Note: Sync this list with Robert's Perl version at + # http://www.rottmerhusen.com/objektives/lensid/files/exif/fmountlens.p.txt + # (hex digits must be uppercase in keys below) + '01 58 50 50 14 14 02 00' => 'AF Nikkor 50mm f/1.8', + '01 58 50 50 14 14 05 00' => 'AF Nikkor 50mm f/1.8', + '02 42 44 5C 2A 34 02 00' => 'AF Zoom-Nikkor 35-70mm f/3.3-4.5', + '02 42 44 5C 2A 34 08 00' => 'AF Zoom-Nikkor 35-70mm f/3.3-4.5', + '03 48 5C 81 30 30 02 00' => 'AF Zoom-Nikkor 70-210mm f/4', + '04 48 3C 3C 24 24 03 00' => 'AF Nikkor 28mm f/2.8', + '05 54 50 50 0C 0C 04 00' => 'AF Nikkor 50mm f/1.4', + '06 54 53 53 24 24 06 00' => 'AF Micro-Nikkor 55mm f/2.8', + '07 40 3C 62 2C 34 03 00' => 'AF Zoom-Nikkor 28-85mm f/3.5-4.5', + '08 40 44 6A 2C 34 04 00' => 'AF Zoom-Nikkor 35-105mm f/3.5-4.5', + '09 48 37 37 24 24 04 00' => 'AF Nikkor 24mm f/2.8', + '0A 48 8E 8E 24 24 03 00' => 'AF Nikkor 300mm f/2.8 IF-ED', + '0A 48 8E 8E 24 24 05 00' => 'AF Nikkor 300mm f/2.8 IF-ED N', + '0B 48 7C 7C 24 24 05 00' => 'AF Nikkor 180mm f/2.8 IF-ED', + '0D 40 44 72 2C 34 07 00' => 'AF Zoom-Nikkor 35-135mm f/3.5-4.5', + '0E 48 5C 81 30 30 05 00' => 'AF Zoom-Nikkor 70-210mm f/4', + '0F 58 50 50 14 14 05 00' => 'AF Nikkor 50mm f/1.8 N', + '10 48 8E 8E 30 30 08 00' => 'AF Nikkor 300mm f/4 IF-ED', + '11 48 44 5C 24 24 08 00' => 'AF Zoom-Nikkor 35-70mm f/2.8', + '11 48 44 5C 24 24 15 00' => 'AF Zoom-Nikkor 35-70mm f/2.8', #Jakob Dettner + '12 48 5C 81 30 3C 09 00' => 'AF Nikkor 70-210mm f/4-5.6', + '13 42 37 50 2A 34 0B 00' => 'AF Zoom-Nikkor 24-50mm f/3.3-4.5', + '14 48 60 80 24 24 0B 00' => 'AF Zoom-Nikkor 80-200mm f/2.8 ED', + '15 4C 62 62 14 14 0C 00' => 'AF Nikkor 85mm f/1.8', + '17 3C A0 A0 30 30 0F 00' => 'Nikkor 500mm f/4 P ED IF', + '17 3C A0 A0 30 30 11 00' => 'Nikkor 500mm f/4 P ED IF', + '18 40 44 72 2C 34 0E 00' => 'AF Zoom-Nikkor 35-135mm f/3.5-4.5 N', + '1A 54 44 44 18 18 11 00' => 'AF Nikkor 35mm f/2', + '1B 44 5E 8E 34 3C 10 00' => 'AF Zoom-Nikkor 75-300mm f/4.5-5.6', + '1C 48 30 30 24 24 12 00' => 'AF Nikkor 20mm f/2.8', + '1D 42 44 5C 2A 34 12 00' => 'AF Zoom-Nikkor 35-70mm f/3.3-4.5 N', + '1E 54 56 56 24 24 13 00' => 'AF Micro-Nikkor 60mm f/2.8', + '1F 54 6A 6A 24 24 14 00' => 'AF Micro-Nikkor 105mm f/2.8', + '20 48 60 80 24 24 15 00' => 'AF Zoom-Nikkor 80-200mm f/2.8 ED', + '21 40 3C 5C 2C 34 16 00' => 'AF Zoom-Nikkor 28-70mm f/3.5-4.5', + '22 48 72 72 18 18 16 00' => 'AF DC-Nikkor 135mm f/2', + '23 30 BE CA 3C 48 17 00' => 'Zoom-Nikkor 1200-1700mm f/5.6-8 P ED IF', + '24 48 60 80 24 24 1A 02' => 'AF Zoom-Nikkor 80-200mm f/2.8D ED', + '25 48 44 5C 24 24 1B 02' => 'AF Zoom-Nikkor 35-70mm f/2.8D', + '25 48 44 5C 24 24 3A 02' => 'AF Zoom-Nikkor 35-70mm f/2.8D', + '25 48 44 5C 24 24 52 02' => 'AF Zoom-Nikkor 35-70mm f/2.8D', + '26 40 3C 5C 2C 34 1C 02' => 'AF Zoom-Nikkor 28-70mm f/3.5-4.5D', + '27 48 8E 8E 24 24 1D 02' => 'AF-I Nikkor 300mm f/2.8D IF-ED', + '27 48 8E 8E 24 24 F1 02' => 'AF-I Nikkor 300mm f/2.8D IF-ED + TC-14E', + '27 48 8E 8E 24 24 E1 02' => 'AF-I Nikkor 300mm f/2.8D IF-ED + TC-17E', + '27 48 8E 8E 24 24 F2 02' => 'AF-I Nikkor 300mm f/2.8D IF-ED + TC-20E', + '28 3C A6 A6 30 30 1D 02' => 'AF-I Nikkor 600mm f/4D IF-ED', + '28 3C A6 A6 30 30 F1 02' => 'AF-I Nikkor 600mm f/4D IF-ED + TC-14E', + '28 3C A6 A6 30 30 E1 02' => 'AF-I Nikkor 600mm f/4D IF-ED + TC-17E', + '28 3C A6 A6 30 30 F2 02' => 'AF-I Nikkor 600mm f/4D IF-ED + TC-20E', + '2A 54 3C 3C 0C 0C 26 02' => 'AF Nikkor 28mm f/1.4D', + '2B 3C 44 60 30 3C 1F 02' => 'AF Zoom-Nikkor 35-80mm f/4-5.6D', + '2C 48 6A 6A 18 18 27 02' => 'AF DC-Nikkor 105mm f/2D', + '2D 48 80 80 30 30 21 02' => 'AF Micro-Nikkor 200mm f/4D IF-ED', + '2E 48 5C 82 30 3C 22 02' => 'AF Nikkor 70-210mm f/4-5.6D', + '2E 48 5C 82 30 3C 28 02' => 'AF Nikkor 70-210mm f/4-5.6D', + '2F 48 30 44 24 24 29 02.1' => 'AF Zoom-Nikkor 20-35mm f/2.8D IF', + '30 48 98 98 24 24 24 02' => 'AF-I Nikkor 400mm f/2.8D IF-ED', + '30 48 98 98 24 24 F1 02' => 'AF-I Nikkor 400mm f/2.8D IF-ED + TC-14E', + '30 48 98 98 24 24 E1 02' => 'AF-I Nikkor 400mm f/2.8D IF-ED + TC-17E', + '30 48 98 98 24 24 F2 02' => 'AF-I Nikkor 400mm f/2.8D IF-ED + TC-20E', + '31 54 56 56 24 24 25 02' => 'AF Micro-Nikkor 60mm f/2.8D', + '32 54 6A 6A 24 24 35 02.1' => 'AF Micro-Nikkor 105mm f/2.8D', + '33 48 2D 2D 24 24 31 02' => 'AF Nikkor 18mm f/2.8D', + '34 48 29 29 24 24 32 02' => 'AF Fisheye Nikkor 16mm f/2.8D', + '35 3C A0 A0 30 30 33 02' => 'AF-I Nikkor 500mm f/4D IF-ED', + '35 3C A0 A0 30 30 F1 02' => 'AF-I Nikkor 500mm f/4D IF-ED + TC-14E', + '35 3C A0 A0 30 30 E1 02' => 'AF-I Nikkor 500mm f/4D IF-ED + TC-17E', + '35 3C A0 A0 30 30 F2 02' => 'AF-I Nikkor 500mm f/4D IF-ED + TC-20E', + '36 48 37 37 24 24 34 02' => 'AF Nikkor 24mm f/2.8D', + '37 48 30 30 24 24 36 02' => 'AF Nikkor 20mm f/2.8D', + '38 4C 62 62 14 14 37 02' => 'AF Nikkor 85mm f/1.8D', + '3A 40 3C 5C 2C 34 39 02' => 'AF Zoom-Nikkor 28-70mm f/3.5-4.5D', + '3B 48 44 5C 24 24 3A 02' => 'AF Zoom-Nikkor 35-70mm f/2.8D N', + '3C 48 60 80 24 24 3B 02' => 'AF Zoom-Nikkor 80-200mm f/2.8D ED', #NJ + '3D 3C 44 60 30 3C 3E 02' => 'AF Zoom-Nikkor 35-80mm f/4-5.6D', + '3E 48 3C 3C 24 24 3D 02' => 'AF Nikkor 28mm f/2.8D', + '3F 40 44 6A 2C 34 45 02' => 'AF Zoom-Nikkor 35-105mm f/3.5-4.5D', + '41 48 7C 7C 24 24 43 02' => 'AF Nikkor 180mm f/2.8D IF-ED', + '42 54 44 44 18 18 44 02' => 'AF Nikkor 35mm f/2D', + '43 54 50 50 0C 0C 46 02' => 'AF Nikkor 50mm f/1.4D', + '44 44 60 80 34 3C 47 02' => 'AF Zoom-Nikkor 80-200mm f/4.5-5.6D', + '45 40 3C 60 2C 3C 48 02' => 'AF Zoom-Nikkor 28-80mm f/3.5-5.6D', + '46 3C 44 60 30 3C 49 02' => 'AF Zoom-Nikkor 35-80mm f/4-5.6D N', + '47 42 37 50 2A 34 4A 02' => 'AF Zoom-Nikkor 24-50mm f/3.3-4.5D', + '48 48 8E 8E 24 24 4B 02' => 'AF-S Nikkor 300mm f/2.8D IF-ED', + '48 48 8E 8E 24 24 F1 02' => 'AF-S Nikkor 300mm f/2.8D IF-ED + TC-14E', + '48 48 8E 8E 24 24 E1 02' => 'AF-S Nikkor 300mm f/2.8D IF-ED + TC-17E', + '48 48 8E 8E 24 24 F2 02' => 'AF-S Nikkor 300mm f/2.8D IF-ED + TC-20E', + '49 3C A6 A6 30 30 4C 02' => 'AF-S Nikkor 600mm f/4D IF-ED', + '49 3C A6 A6 30 30 F1 02' => 'AF-S Nikkor 600mm f/4D IF-ED + TC-14E', + '49 3C A6 A6 30 30 E1 02' => 'AF-S Nikkor 600mm f/4D IF-ED + TC-17E', + '49 3C A6 A6 30 30 F2 02' => 'AF-S Nikkor 600mm f/4D IF-ED + TC-20E', + '4A 54 62 62 0C 0C 4D 02' => 'AF Nikkor 85mm f/1.4D IF', + '4B 3C A0 A0 30 30 4E 02' => 'AF-S Nikkor 500mm f/4D IF-ED', + '4B 3C A0 A0 30 30 F1 02' => 'AF-S Nikkor 500mm f/4D IF-ED + TC-14E', + '4B 3C A0 A0 30 30 E1 02' => 'AF-S Nikkor 500mm f/4D IF-ED + TC-17E', + '4B 3C A0 A0 30 30 F2 02' => 'AF-S Nikkor 500mm f/4D IF-ED + TC-20E', + '4C 40 37 6E 2C 3C 4F 02' => 'AF Zoom-Nikkor 24-120mm f/3.5-5.6D IF', + '4D 40 3C 80 2C 3C 62 02' => 'AF Zoom-Nikkor 28-200mm f/3.5-5.6D IF', + '4E 48 72 72 18 18 51 02' => 'AF DC-Nikkor 135mm f/2D', + '4F 40 37 5C 2C 3C 53 06' => 'IX-Nikkor 24-70mm f/3.5-5.6', + '50 48 56 7C 30 3C 54 06' => 'IX-Nikkor 60-180mm f/4-5.6', + '53 48 60 80 24 24 57 02' => 'AF Zoom-Nikkor 80-200mm f/2.8D ED', + '53 48 60 80 24 24 60 02' => 'AF Zoom-Nikkor 80-200mm f/2.8D ED', + '54 44 5C 7C 34 3C 58 02' => 'AF Zoom-Micro Nikkor 70-180mm f/4.5-5.6D ED', + '54 44 5C 7C 34 3C 61 02' => 'AF Zoom-Micro Nikkor 70-180mm f/4.5-5.6D ED', + '56 48 5C 8E 30 3C 5A 02' => 'AF Zoom-Nikkor 70-300mm f/4-5.6D ED', + '59 48 98 98 24 24 5D 02' => 'AF-S Nikkor 400mm f/2.8D IF-ED', + '59 48 98 98 24 24 F1 02' => 'AF-S Nikkor 400mm f/2.8D IF-ED + TC-14E', + '59 48 98 98 24 24 E1 02' => 'AF-S Nikkor 400mm f/2.8D IF-ED + TC-17E', + '59 48 98 98 24 24 F2 02' => 'AF-S Nikkor 400mm f/2.8D IF-ED + TC-20E', + '5A 3C 3E 56 30 3C 5E 06' => 'IX-Nikkor 30-60mm f/4-5.6', + '5B 44 56 7C 34 3C 5F 06' => 'IX-Nikkor 60-180mm f/4.5-5.6', + '5D 48 3C 5C 24 24 63 02' => 'AF-S Zoom-Nikkor 28-70mm f/2.8D IF-ED', + '5E 48 60 80 24 24 64 02' => 'AF-S Zoom-Nikkor 80-200mm f/2.8D IF-ED', + '5F 40 3C 6A 2C 34 65 02' => 'AF Zoom-Nikkor 28-105mm f/3.5-4.5D IF', + '60 40 3C 60 2C 3C 66 02' => 'AF Zoom-Nikkor 28-80mm f/3.5-5.6D', #(http://www.exif.org/forum/topic.asp?TOPIC_ID=16) + '61 44 5E 86 34 3C 67 02' => 'AF Zoom-Nikkor 75-240mm f/4.5-5.6D', + '63 48 2B 44 24 24 68 02' => 'AF-S Nikkor 17-35mm f/2.8D IF-ED', + '64 00 62 62 24 24 6A 02' => 'PC Micro-Nikkor 85mm f/2.8D', + '65 44 60 98 34 3C 6B 0A' => 'AF VR Zoom-Nikkor 80-400mm f/4.5-5.6D ED', + '66 40 2D 44 2C 34 6C 02' => 'AF Zoom-Nikkor 18-35mm f/3.5-4.5D IF-ED', + '67 48 37 62 24 30 6D 02' => 'AF Zoom-Nikkor 24-85mm f/2.8-4D IF', + '68 42 3C 60 2A 3C 6E 06' => 'AF Zoom-Nikkor 28-80mm f/3.3-5.6G', + '69 48 5C 8E 30 3C 6F 06' => 'AF Zoom-Nikkor 70-300mm f/4-5.6G', + '6A 48 8E 8E 30 30 70 02' => 'AF-S Nikkor 300mm f/4D IF-ED', + '6B 48 24 24 24 24 71 02' => 'AF Nikkor ED 14mm f/2.8D', + '6D 48 8E 8E 24 24 73 02' => 'AF-S Nikkor 300mm f/2.8D IF-ED II', + '6E 48 98 98 24 24 74 02' => 'AF-S Nikkor 400mm f/2.8D IF-ED II', + '6F 3C A0 A0 30 30 75 02' => 'AF-S Nikkor 500mm f/4D IF-ED II', + '70 3C A6 A6 30 30 76 02' => 'AF-S Nikkor 600mm f/4D IF-ED II', + '72 48 4C 4C 24 24 77 00' => 'Nikkor 45mm f/2.8 P', + '74 40 37 62 2C 34 78 06' => 'AF-S Zoom-Nikkor 24-85mm f/3.5-4.5G IF-ED', + '75 40 3C 68 2C 3C 79 06' => 'AF Zoom-Nikkor 28-100mm f/3.5-5.6G', + '76 58 50 50 14 14 7A 02' => 'AF Nikkor 50mm f/1.8D', + '77 48 5C 80 24 24 7B 0E' => 'AF-S VR Zoom-Nikkor 70-200mm f/2.8G IF-ED', + '78 40 37 6E 2C 3C 7C 0E' => 'AF-S VR Zoom-Nikkor 24-120mm f/3.5-5.6G IF-ED', + '79 40 3C 80 2C 3C 7F 06' => 'AF Zoom-Nikkor 28-200mm f/3.5-5.6G IF-ED', + '7A 3C 1F 37 30 30 7E 06.1' => 'AF-S DX Zoom-Nikkor 12-24mm f/4G IF-ED', + '7B 48 80 98 30 30 80 0E' => 'AF-S VR Zoom-Nikkor 200-400mm f/4G IF-ED', + '7D 48 2B 53 24 24 82 06' => 'AF-S DX Zoom-Nikkor 17-55mm f/2.8G IF-ED', + '7F 40 2D 5C 2C 34 84 06' => 'AF-S DX Zoom-Nikkor 18-70mm f/3.5-4.5G IF-ED', + '80 48 1A 1A 24 24 85 06' => 'AF DX Fisheye-Nikkor 10.5mm f/2.8G ED', + '81 54 80 80 18 18 86 0E' => 'AF-S VR Nikkor 200mm f/2G IF-ED', + '82 48 8E 8E 24 24 87 0E' => 'AF-S VR Nikkor 300mm f/2.8G IF-ED', + '83 00 B0 B0 5A 5A 88 04' => 'FSA-L2, EDG 65, 800mm F13 G', + '89 3C 53 80 30 3C 8B 06' => 'AF-S DX Zoom-Nikkor 55-200mm f/4-5.6G ED', + '8A 54 6A 6A 24 24 8C 0E' => 'AF-S VR Micro-Nikkor 105mm f/2.8G IF-ED', #10 + # when the TC-20 III 2x teleconverter is used with the above lens, the following have been observed: + # 8A 4D 6A 6A 24 24 8C 0E + # 8A 4E 6A 6A 24 24 8C 0E + # 8A 50 6A 6A 24 24 8C 0E + # 8A 51 6A 6A 24 24 8C 0E + # 8A 52 6A 6A 24 24 8C 0E + # 8A 53 6A 6A 24 24 8C 0E + # 8A 54 6A 6A 24 24 8C 0E (same as without the TC) + '8B 40 2D 80 2C 3C 8D 0E' => 'AF-S DX VR Zoom-Nikkor 18-200mm f/3.5-5.6G IF-ED', + '8B 40 2D 80 2C 3C FD 0E' => 'AF-S DX VR Zoom-Nikkor 18-200mm f/3.5-5.6G IF-ED [II]', #20 + '8C 40 2D 53 2C 3C 8E 06' => 'AF-S DX Zoom-Nikkor 18-55mm f/3.5-5.6G ED', + '8D 44 5C 8E 34 3C 8F 0E' => 'AF-S VR Zoom-Nikkor 70-300mm f/4.5-5.6G IF-ED', #10 + '8F 40 2D 72 2C 3C 91 06' => 'AF-S DX Zoom-Nikkor 18-135mm f/3.5-5.6G IF-ED', + '90 3B 53 80 30 3C 92 0E' => 'AF-S DX VR Zoom-Nikkor 55-200mm f/4-5.6G IF-ED', + '92 48 24 37 24 24 94 06' => 'AF-S Zoom-Nikkor 14-24mm f/2.8G ED', + '93 48 37 5C 24 24 95 06' => 'AF-S Zoom-Nikkor 24-70mm f/2.8G ED', + '94 40 2D 53 2C 3C 96 06' => 'AF-S DX Zoom-Nikkor 18-55mm f/3.5-5.6G ED II', #10 (D40) + '95 4C 37 37 2C 2C 97 02' => 'PC-E Nikkor 24mm f/3.5D ED', + '95 00 37 37 2C 2C 97 06' => 'PC-E Nikkor 24mm f/3.5D ED', #JD + '96 48 98 98 24 24 98 0E' => 'AF-S VR Nikkor 400mm f/2.8G ED', + '97 3C A0 A0 30 30 99 0E' => 'AF-S VR Nikkor 500mm f/4G ED', + '98 3C A6 A6 30 30 9A 0E' => 'AF-S VR Nikkor 600mm f/4G ED', + '99 40 29 62 2C 3C 9B 0E' => 'AF-S DX VR Zoom-Nikkor 16-85mm f/3.5-5.6G ED', + '9A 40 2D 53 2C 3C 9C 0E' => 'AF-S DX VR Zoom-Nikkor 18-55mm f/3.5-5.6G', + '9B 54 4C 4C 24 24 9D 02' => 'PC-E Micro Nikkor 45mm f/2.8D ED', + '9B 00 4C 4C 24 24 9D 06' => 'PC-E Micro Nikkor 45mm f/2.8D ED', + '9C 54 56 56 24 24 9E 06' => 'AF-S Micro Nikkor 60mm f/2.8G ED', + '9D 54 62 62 24 24 9F 02' => 'PC-E Micro Nikkor 85mm f/2.8D', + '9D 00 62 62 24 24 9F 06' => 'PC-E Micro Nikkor 85mm f/2.8D', + '9E 40 2D 6A 2C 3C A0 0E' => 'AF-S DX VR Zoom-Nikkor 18-105mm f/3.5-5.6G ED', #PH/10 + '9F 58 44 44 14 14 A1 06' => 'AF-S DX Nikkor 35mm f/1.8G', #27 + 'A0 54 50 50 0C 0C A2 06' => 'AF-S Nikkor 50mm f/1.4G', + 'A1 40 18 37 2C 34 A3 06' => 'AF-S DX Nikkor 10-24mm f/3.5-4.5G ED', + 'A2 48 5C 80 24 24 A4 0E' => 'AF-S Nikkor 70-200mm f/2.8G ED VR II', + 'A3 3C 29 44 30 30 A5 0E' => 'AF-S Nikkor 16-35mm f/4G ED VR', + 'A4 54 37 37 0C 0C A6 06' => 'AF-S Nikkor 24mm f/1.4G ED', + 'A5 40 3C 8E 2C 3C A7 0E' => 'AF-S Nikkor 28-300mm f/3.5-5.6G ED VR', + 'A6 48 8E 8E 24 24 A8 0E' => 'AF-S Nikkor 300mm f/2.8G IF-ED VR II', + 'A7 4B 62 62 2C 2C A9 0E' => 'AF-S DX Micro Nikkor 85mm f/3.5G ED VR', + 'A8 48 80 98 30 30 AA 0E' => 'AF-S Zoom-Nikkor 200-400mm f/4G IF-ED VR II', #http://u88.n24.queensu.ca/exiftool/forum/index.php/topic,3218.msg15495.html#msg15495 + 'A9 54 80 80 18 18 AB 0E' => 'AF-S Nikkor 200mm f/2G ED VR II', + 'AA 3C 37 6E 30 30 AC 0E' => 'AF-S Nikkor 24-120mm f/4G ED VR', + 'AC 38 53 8E 34 3C AE 0E' => 'AF-S DX Nikkor 55-300mm f/4.5-5.6G ED VR', + 'AD 3C 2D 8E 2C 3C AF 0E' => 'AF-S DX Nikkor 18-300mm f/3.5-5.6G ED VR', + 'AE 54 62 62 0C 0C B0 06' => 'AF-S Nikkor 85mm f/1.4G', + 'AF 54 44 44 0C 0C B1 06' => 'AF-S Nikkor 35mm f/1.4G', + 'B0 4C 50 50 14 14 B2 06' => 'AF-S Nikkor 50mm f/1.8G', + 'B1 48 48 48 24 24 B3 06' => 'AF-S DX Micro Nikkor 40mm f/2.8G', #27 + 'B2 48 5C 80 30 30 B4 0E' => 'AF-S Nikkor 70-200mm f/4G ED VR', #35 + 'B3 4C 62 62 14 14 B5 06' => 'AF-S Nikkor 85mm f/1.8G', + 'B4 40 37 62 2C 34 B6 0E' => 'AF-S Zoom-Nikkor 24-85mm f/3.5-4.5G IF-ED VR', #30 + 'B5 4C 3C 3C 14 14 B7 06' => 'AF-S Nikkor 28mm f/1.8G', #30 + 'B6 3C B0 B0 3C 3C B8 0E' => 'AF-S VR Nikkor 800mm f/5.6E FL ED', + 'B6 3C B0 B0 3C 3C B8 4E' => 'AF-S VR Nikkor 800mm f/5.6E FL ED', #PH + 'B7 44 60 98 34 3C B9 0E' => 'AF-S Nikkor 80-400mm f/4.5-5.6G ED VR', + 'B8 40 2D 44 2C 34 BA 06' => 'AF-S Nikkor 18-35mm f/3.5-4.5G ED', + 'A0 40 2D 74 2C 3C BB 0E' => 'AF-S DX Nikkor 18-140mm f/3.5-5.6G ED VR', #PH + 'A1 54 55 55 0C 0C BC 06' => 'AF-S Nikkor 58mm f/1.4G', #IB + 'A2 40 2D 53 2C 3C BD 0E' => 'AF-S DX Nikkor 18-55mm f/3.5-5.6G VR II', + 'A4 40 2D 8E 2C 40 BF 0E' => 'AF-S DX Nikkor 18-300mm f/3.5-6.3G ED VR', + 'A5 4C 44 44 14 14 C0 06' => 'AF-S Nikkor 35mm f/1.8G ED', #35 ("ED" ref 11) + 'A6 48 98 98 24 24 C1 0E' => 'AF-S Nikkor 400mm f/2.8E FL ED VR', + 'A7 3C 53 80 30 3C C2 0E' => 'AF-S DX Nikkor 55-200mm f/4-5.6G ED VR II', #IB + 'A8 48 8E 8E 30 30 C3 4E' => 'AF-S Nikkor 300mm f/4E PF ED VR', #35 + 'A8 48 8E 8E 30 30 C3 0E' => 'AF-S Nikkor 300mm f/4E PF ED VR', #30 + 'A9 4C 31 31 14 14 C4 06' => 'AF-S Nikkor 20mm f/1.8G ED', #30 + 'AA 48 37 5C 24 24 C5 4E' => 'AF-S Nikkor 24-70mm f/2.8E ED VR', + 'AA 48 37 5C 24 24 C5 0E' => 'AF-S Nikkor 24-70mm f/2.8E ED VR', + 'AB 3C A0 A0 30 30 C6 4E' => 'AF-S Nikkor 500mm f/4E FL ED VR', + 'AC 3C A6 A6 30 30 C7 4E' => 'AF-S Nikkor 600mm f/4E FL ED VR', #PH + 'AD 48 28 60 24 30 C8 4E' => 'AF-S DX Nikkor 16-80mm f/2.8-4E ED VR', + 'AD 48 28 60 24 30 C8 0E' => 'AF-S DX Nikkor 16-80mm f/2.8-4E ED VR', #PH + 'AE 3C 80 A0 3C 3C C9 4E' => 'AF-S Nikkor 200-500mm f/5.6E ED VR', #PH + 'AE 3C 80 A0 3C 3C C9 0E' => 'AF-S Nikkor 200-500mm f/5.6E ED VR', + 'A0 40 2D 53 2C 3C CA 8E' => 'AF-P DX Nikkor 18-55mm f/3.5-5.6G', #Yang You pvt communication + 'A0 40 2D 53 2C 3C CA 0E' => 'AF-P DX Nikkor 18-55mm f/3.5-5.6G VR', #PH + 'AF 4C 37 37 14 14 CC 06' => 'AF-S Nikkor 24mm f/1.8G ED', #IB + 'A2 38 5C 8E 34 40 CD 86' => 'AF-P DX Nikkor 70-300mm f/4.5-6.3G VR', #PH + 'A3 38 5C 8E 34 40 CE 8E' => 'AF-P DX Nikkor 70-300mm f/4.5-6.3G ED VR', + 'A3 38 5C 8E 34 40 CE 0E' => 'AF-P DX Nikkor 70-300mm f/4.5-6.3G ED', + 'A4 48 5C 80 24 24 CF 4E' => 'AF-S Nikkor 70-200mm f/2.8E FL ED VR', + 'A4 48 5C 80 24 24 CF 0E' => 'AF-S Nikkor 70-200mm f/2.8E FL ED VR', + 'A5 54 6A 6A 0C 0C D0 46' => 'AF-S Nikkor 105mm f/1.4E ED', #IB + 'A5 54 6A 6A 0C 0C D0 06' => 'AF-S Nikkor 105mm f/1.4E ED', #IB + 'A6 48 2F 2F 30 30 D1 46' => 'PC Nikkor 19mm f/4E ED', + 'A6 48 2F 2F 30 30 D1 06' => 'PC Nikkor 19mm f/4E ED', + 'A7 40 11 26 2C 34 D2 46' => 'AF-S Fisheye Nikkor 8-15mm f/3.5-4.5E ED', + 'A7 40 11 26 2C 34 D2 06' => 'AF-S Fisheye Nikkor 8-15mm f/3.5-4.5E ED', + 'A8 38 18 30 34 3C D3 8E' => 'AF-P DX Nikkor 10-20mm f/4.5-5.6G VR', #Yang You pvt communication + 'A8 38 18 30 34 3C D3 0E' => 'AF-P DX Nikkor 10-20mm f/4.5-5.6G VR', + 'A9 48 7C 98 30 30 D4 4E' => 'AF-S Nikkor 180-400mm f/4E TC1.4 FL ED VR', #IB + 'A9 48 7C 98 30 30 D4 0E' => 'AF-S Nikkor 180-400mm f/4E TC1.4 FL ED VR', + 'AA 48 88 A4 3C 3C D5 4E' => 'AF-S Nikkor 180-400mm f/4E TC1.4 FL ED VR + 1.4x TC', #IB + 'AA 48 88 A4 3C 3C D5 0E' => 'AF-S Nikkor 180-400mm f/4E TC1.4 FL ED VR + 1.4x TC', + 'AB 44 5C 8E 34 3C D6 CE' => 'AF-P Nikkor 70-300mm f/4.5-5.6E ED VR', + 'AB 44 5C 8E 34 3C D6 0E' => 'AF-P Nikkor 70-300mm f/4.5-5.6E ED VR', + 'AC 54 3C 3C 0C 0C D7 46' => 'AF-S Nikkor 28mm f/1.4E ED', + 'AC 54 3C 3C 0C 0C D7 06' => 'AF-S Nikkor 28mm f/1.4E ED', + 'AD 3C A0 A0 3C 3C D8 0E' => 'AF-S Nikkor 500mm f/5.6E PF ED VR', + 'AD 3C A0 A0 3C 3C D8 4E' => 'AF-S Nikkor 500mm f/5.6E PF ED VR', + '01 00 00 00 00 00 02 00' => 'TC-16A', + '01 00 00 00 00 00 08 00' => 'TC-16A', + '00 00 00 00 00 00 F1 0C' => 'TC-14E [II] or Sigma APO Tele Converter 1.4x EX DG or Kenko Teleplus PRO 300 DG 1.4x', + '00 00 00 00 00 00 F2 18' => 'TC-20E [II] or Sigma APO Tele Converter 2x EX DG or Kenko Teleplus PRO 300 DG 2.0x', + '00 00 00 00 00 00 E1 12' => 'TC-17E II', + 'FE 47 00 00 24 24 4B 06' => 'Sigma 4.5mm F2.8 EX DC HSM Circular Fisheye', #JD + '26 48 11 11 30 30 1C 02' => 'Sigma 8mm F4 EX Circular Fisheye', + '79 40 11 11 2C 2C 1C 06' => 'Sigma 8mm F3.5 EX Circular Fisheye', #JD + 'DC 48 19 19 24 24 4B 06' => 'Sigma 10mm F2.8 EX DC HSM Fisheye', + 'C2 4C 24 24 14 14 4B 06' => 'Sigma 14mm F1.8 DG HSM | A', #IB + '48 48 24 24 24 24 4B 02' => 'Sigma 14mm F2.8 EX Aspherical HSM', + '02 3F 24 24 2C 2C 02 00' => 'Sigma 14mm F3.5', + '26 48 27 27 24 24 1C 02' => 'Sigma 15mm F2.8 EX Diagonal Fisheye', + 'EA 48 27 27 24 24 1C 02' => 'Sigma 15mm F2.8 EX Diagonal Fisheye', #30 + '26 58 31 31 14 14 1C 02' => 'Sigma 20mm F1.8 EX DG Aspherical RF', + '79 54 31 31 0C 0C 4B 06' => 'Sigma 20mm F1.4 DG HSM | A', #Rolf Probst + '26 58 37 37 14 14 1C 02' => 'Sigma 24mm F1.8 EX DG Aspherical Macro', + 'E1 58 37 37 14 14 1C 02' => 'Sigma 24mm F1.8 EX DG Aspherical Macro', + '02 46 37 37 25 25 02 00' => 'Sigma 24mm F2.8 Super Wide II Macro', + '26 58 3C 3C 14 14 1C 02' => 'Sigma 28mm F1.8 EX DG Aspherical Macro', + '48 54 3E 3E 0C 0C 4B 06' => 'Sigma 30mm F1.4 EX DC HSM', + 'F8 54 3E 3E 0C 0C 4B 06' => 'Sigma 30mm F1.4 EX DC HSM', #JD + '91 54 44 44 0C 0C 4B 06' => 'Sigma 35mm F1.4 DG HSM', #30 + 'DE 54 50 50 0C 0C 4B 06' => 'Sigma 50mm F1.4 EX DG HSM', + '88 54 50 50 0C 0C 4B 06' => 'Sigma 50mm F1.4 DG HSM | A', + '02 48 50 50 24 24 02 00' => 'Sigma Macro 50mm F2.8', #http://u88.n24.queensu.ca/exiftool/forum/index.php/topic,4027.0.html + '32 54 50 50 24 24 35 02' => 'Sigma Macro 50mm F2.8 EX DG', + 'E3 54 50 50 24 24 35 02' => 'Sigma Macro 50mm F2.8 EX DG', #http://u88.n24.queensu.ca/exiftool/forum/index.php/topic,3215.0.html + '79 48 5C 5C 24 24 1C 06' => 'Sigma Macro 70mm F2.8 EX DG', #JD + '9B 54 62 62 0C 0C 4B 06' => 'Sigma 85mm F1.4 EX DG HSM', + 'C8 54 62 62 0C 0C 4B 46' => 'Sigma 85mm F1.4 DG HSM | A', #JamiBradley + '02 48 65 65 24 24 02 00' => 'Sigma Macro 90mm F2.8', + '32 54 6A 6A 24 24 35 02.2' => 'Sigma Macro 105mm F2.8 EX DG', #JD + 'E5 54 6A 6A 24 24 35 02' => 'Sigma Macro 105mm F2.8 EX DG', + '97 48 6A 6A 24 24 4B 0E' => 'Sigma Macro 105mm F2.8 EX DG OS HSM', + '48 48 76 76 24 24 4B 06' => 'Sigma APO Macro 150mm F2.8 EX DG HSM', + 'F5 48 76 76 24 24 4B 06' => 'Sigma APO Macro 150mm F2.8 EX DG HSM', #24 + '99 48 76 76 24 24 4B 0E' => 'Sigma APO Macro 150mm F2.8 EX DG OS HSM', #(Christian Hesse) + '48 4C 7C 7C 2C 2C 4B 02' => 'Sigma APO Macro 180mm F3.5 EX DG HSM', + '48 4C 7D 7D 2C 2C 4B 02' => 'Sigma APO Macro 180mm F3.5 EX DG HSM', + '94 48 7C 7C 24 24 4B 0E' => 'Sigma APO Macro 180mm F2.8 EX DG OS HSM', #MichaelTapes (HSM from ref 8) + '48 54 8E 8E 24 24 4B 02' => 'Sigma APO 300mm F2.8 EX DG HSM', + 'FB 54 8E 8E 24 24 4B 02' => 'Sigma APO 300mm F2.8 EX DG HSM', #26 + '26 48 8E 8E 30 30 1C 02' => 'Sigma APO Tele Macro 300mm F4', + '02 2F 98 98 3D 3D 02 00' => 'Sigma APO 400mm F5.6', + '26 3C 98 98 3C 3C 1C 02' => 'Sigma APO Tele Macro 400mm F5.6', + '02 37 A0 A0 34 34 02 00' => 'Sigma APO 500mm F4.5', #19 + '48 44 A0 A0 34 34 4B 02' => 'Sigma APO 500mm F4.5 EX HSM', + 'F1 44 A0 A0 34 34 4B 02' => 'Sigma APO 500mm F4.5 EX DG HSM', + '02 34 A0 A0 44 44 02 00' => 'Sigma APO 500mm F7.2', + '02 3C B0 B0 3C 3C 02 00' => 'Sigma APO 800mm F5.6', + '48 3C B0 B0 3C 3C 4B 02' => 'Sigma APO 800mm F5.6 EX HSM', + '9E 38 11 29 34 3C 4B 06' => 'Sigma 8-16mm F4.5-5.6 DC HSM', + 'A1 41 19 31 2C 2C 4B 06' => 'Sigma 10-20mm F3.5 EX DC HSM', + '48 3C 19 31 30 3C 4B 06' => 'Sigma 10-20mm F4-5.6 EX DC HSM', + 'F9 3C 19 31 30 3C 4B 06' => 'Sigma 10-20mm F4-5.6 EX DC HSM', #JD + '48 38 1F 37 34 3C 4B 06' => 'Sigma 12-24mm F4.5-5.6 EX DG Aspherical HSM', + 'F0 38 1F 37 34 3C 4B 06' => 'Sigma 12-24mm F4.5-5.6 EX DG Aspherical HSM', + '96 38 1F 37 34 3C 4B 06' => 'Sigma 12-24mm F4.5-5.6 II DG HSM', #Jurgen Sahlberg + 'C1 48 24 37 24 24 4B 46' => 'Sigma 14-24mm F2.8 DG HSM | A', #30 + '26 40 27 3F 2C 34 1C 02' => 'Sigma 15-30mm F3.5-4.5 EX DG Aspherical DF', + '48 48 2B 44 24 30 4B 06' => 'Sigma 17-35mm F2.8-4 EX DG Aspherical HSM', + '26 54 2B 44 24 30 1C 02' => 'Sigma 17-35mm F2.8-4 EX Aspherical', + '9D 48 2B 50 24 24 4B 0E' => 'Sigma 17-50mm F2.8 EX DC OS HSM', + '8F 48 2B 50 24 24 4B 0E' => 'Sigma 17-50mm F2.8 EX DC OS HSM', #http://dev.exiv2.org/boards/3/topics/1747 + '7A 47 2B 5C 24 34 4B 06' => 'Sigma 17-70mm F2.8-4.5 DC Macro Asp. IF HSM', + '7A 48 2B 5C 24 34 4B 06' => 'Sigma 17-70mm F2.8-4.5 DC Macro Asp. IF HSM', + '7F 48 2B 5C 24 34 1C 06' => 'Sigma 17-70mm F2.8-4.5 DC Macro Asp. IF', + '8E 3C 2B 5C 24 30 4B 0E' => 'Sigma 17-70mm F2.8-4 DC Macro OS HSM | C', + 'A0 48 2A 5C 24 30 4B 0E' => 'Sigma 17-70mm F2.8-4 DC Macro OS HSM', #http://u88.n24.queensu.ca/exiftool/forum/index.php/topic,5170.0.html + '8B 4C 2D 44 14 14 4B 06' => 'Sigma 18-35mm F1.8 DC HSM', #30/NJ + '26 40 2D 44 2B 34 1C 02' => 'Sigma 18-35mm F3.5-4.5 Aspherical', + '26 48 2D 50 24 24 1C 06' => 'Sigma 18-50mm F2.8 EX DC', + '7F 48 2D 50 24 24 1C 06' => 'Sigma 18-50mm F2.8 EX DC Macro', #NJ + '7A 48 2D 50 24 24 4B 06' => 'Sigma 18-50mm F2.8 EX DC Macro', + 'F6 48 2D 50 24 24 4B 06' => 'Sigma 18-50mm F2.8 EX DC Macro', + 'A4 47 2D 50 24 34 4B 0E' => 'Sigma 18-50mm F2.8-4.5 DC OS HSM', + '26 40 2D 50 2C 3C 1C 06' => 'Sigma 18-50mm F3.5-5.6 DC', + '7A 40 2D 50 2C 3C 4B 06' => 'Sigma 18-50mm F3.5-5.6 DC HSM', + '26 40 2D 70 2B 3C 1C 06' => 'Sigma 18-125mm F3.5-5.6 DC', + 'CD 3D 2D 70 2E 3C 4B 0E' => 'Sigma 18-125mm F3.8-5.6 DC OS HSM', + '26 40 2D 80 2C 40 1C 06' => 'Sigma 18-200mm F3.5-6.3 DC', + 'FF 40 2D 80 2C 40 4B 06' => 'Sigma 18-200mm F3.5-6.3 DC', #30 + '7A 40 2D 80 2C 40 4B 0E' => 'Sigma 18-200mm F3.5-6.3 DC OS HSM', + 'ED 40 2D 80 2C 40 4B 0E' => 'Sigma 18-200mm F3.5-6.3 DC OS HSM', #JD + '90 40 2D 80 2C 40 4B 0E' => 'Sigma 18-200mm F3.5-6.3 II DC OS HSM', #JohnHelour + 'A5 40 2D 88 2C 40 4B 0E' => 'Sigma 18-250mm F3.5-6.3 DC OS HSM', + # LensFStops varies with FocalLength for this lens (ref 2): + '92 2C 2D 88 2C 40 4B 0E' => 'Sigma 18-250mm F3.5-6.3 DC Macro OS HSM', #2 + # '92 2C 2D 88 2C 40 4B 0E' (250mm) + # '92 2B 2D 88 2C 40 4B 0E' (210mm) + # '92 2C 2D 88 2C 40 4B 0E' (185mm) + # '92 2D 2D 88 2C 40 4B 0E' (155mm) + # '92 2E 2D 88 2C 40 4B 0E' (130mm) + # '92 2F 2D 88 2C 40 4B 0E' (105mm) + # '92 30 2D 88 2C 40 4B 0E' (90mm) + # '92 32 2D 88 2C 40 4B 0E' (75mm) + # '92 33 2D 88 2C 40 4B 0E' (62mm) + # '92 35 2D 88 2C 40 4B 0E' (52mm) + # '92 37 2D 88 2C 40 4B 0E' (44mm) + # '92 39 2D 88 2C 40 4B 0E' (38mm) + # '92 3A 2D 88 2C 40 4B 0E' (32mm) + # '92 3E 2D 88 2C 40 4B 0E' (22mm) + # '92 40 2D 88 2C 40 4B 0E' (18mm) + '26 48 31 49 24 24 1C 02' => 'Sigma 20-40mm F2.8', + '02 3A 37 50 31 3D 02 00' => 'Sigma 24-50mm F4-5.6 UC', + '26 48 37 56 24 24 1C 02' => 'Sigma 24-60mm F2.8 EX DG', + 'B6 48 37 56 24 24 1C 02' => 'Sigma 24-60mm F2.8 EX DG', + 'A6 48 37 5C 24 24 4B 06' => 'Sigma 24-70mm F2.8 IF EX DG HSM', #JD + 'C9 48 37 5C 24 24 4B 4E' => 'Sigma 24-70mm F2.8 DG OS HSM | A', #30 + '26 54 37 5C 24 24 1C 02' => 'Sigma 24-70mm F2.8 EX DG Macro', + '67 54 37 5C 24 24 1C 02' => 'Sigma 24-70mm F2.8 EX DG Macro', + 'E9 54 37 5C 24 24 1C 02' => 'Sigma 24-70mm F2.8 EX DG Macro', + '26 40 37 5C 2C 3C 1C 02' => 'Sigma 24-70mm F3.5-5.6 Aspherical HF', + '8A 3C 37 6A 30 30 4B 0E' => 'Sigma 24-105mm F4 DG OS HSM', #IB + '26 54 37 73 24 34 1C 02' => 'Sigma 24-135mm F2.8-4.5', + '02 46 3C 5C 25 25 02 00' => 'Sigma 28-70mm F2.8', + '26 54 3C 5C 24 24 1C 02' => 'Sigma 28-70mm F2.8 EX', + '26 48 3C 5C 24 24 1C 06' => 'Sigma 28-70mm F2.8 EX DG', + '79 48 3C 5C 24 24 1C 06' => 'Sigma 28-70mm F2.8 EX DG', #30 ("D" removed) + '26 48 3C 5C 24 30 1C 02' => 'Sigma 28-70mm F2.8-4 DG', + '02 3F 3C 5C 2D 35 02 00' => 'Sigma 28-70mm F3.5-4.5 UC', + '26 40 3C 60 2C 3C 1C 02' => 'Sigma 28-80mm F3.5-5.6 Mini Zoom Macro II Aspherical', + '26 40 3C 65 2C 3C 1C 02' => 'Sigma 28-90mm F3.5-5.6 Macro', + '26 48 3C 6A 24 30 1C 02' => 'Sigma 28-105mm F2.8-4 Aspherical', + '26 3E 3C 6A 2E 3C 1C 02' => 'Sigma 28-105mm F3.8-5.6 UC-III Aspherical IF', + '26 40 3C 80 2C 3C 1C 02' => 'Sigma 28-200mm F3.5-5.6 Compact Aspherical Hyperzoom Macro', + '26 40 3C 80 2B 3C 1C 02' => 'Sigma 28-200mm F3.5-5.6 Compact Aspherical Hyperzoom Macro', + '26 3D 3C 80 2F 3D 1C 02' => 'Sigma 28-300mm F3.8-5.6 Aspherical', + '26 41 3C 8E 2C 40 1C 02' => 'Sigma 28-300mm F3.5-6.3 DG Macro', + 'E6 41 3C 8E 2C 40 1C 02' => 'Sigma 28-300mm F3.5-6.3 DG Macro', #http://u88.n24.queensu.ca/exiftool/forum/index.php/topic,3301.0.html + '26 40 3C 8E 2C 40 1C 02' => 'Sigma 28-300mm F3.5-6.3 Macro', + '02 3B 44 61 30 3D 02 00' => 'Sigma 35-80mm F4-5.6', + '02 40 44 73 2B 36 02 00' => 'Sigma 35-135mm F3.5-4.5 a', + 'CC 4C 50 68 14 14 4B 06' => 'Sigma 50-100mm F1.8 DC HSM | A', #30 + '7A 47 50 76 24 24 4B 06' => 'Sigma 50-150mm F2.8 EX APO DC HSM', + 'FD 47 50 76 24 24 4B 06' => 'Sigma 50-150mm F2.8 EX APO DC HSM II', + '98 48 50 76 24 24 4B 0E' => 'Sigma 50-150mm F2.8 EX APO DC OS HSM', #30 + '48 3C 50 A0 30 40 4B 02' => 'Sigma 50-500mm F4-6.3 EX APO RF HSM', + '9F 37 50 A0 34 40 4B 0E' => 'Sigma 50-500mm F4.5-6.3 DG OS HSM', #16 + '26 3C 54 80 30 3C 1C 06' => 'Sigma 55-200mm F4-5.6 DC', + '7A 3B 53 80 30 3C 4B 06' => 'Sigma 55-200mm F4-5.6 DC HSM', + '48 54 5C 80 24 24 4B 02' => 'Sigma 70-200mm F2.8 EX APO IF HSM', + '7A 48 5C 80 24 24 4B 06' => 'Sigma 70-200mm F2.8 EX APO DG Macro HSM II', + 'EE 48 5C 80 24 24 4B 06' => 'Sigma 70-200mm F2.8 EX APO DG Macro HSM II', #JD + '9C 48 5C 80 24 24 4B 0E' => 'Sigma 70-200mm F2.8 EX DG OS HSM', #Rolando Ruzic + '02 46 5C 82 25 25 02 00' => 'Sigma 70-210mm F2.8 APO', #JD + '02 40 5C 82 2C 35 02 00' => 'Sigma APO 70-210mm F3.5-4.5', + '26 3C 5C 82 30 3C 1C 02' => 'Sigma 70-210mm F4-5.6 UC-II', + '26 3C 5C 8E 30 3C 1C 02' => 'Sigma 70-300mm F4-5.6 DG Macro', + '56 3C 5C 8E 30 3C 1C 02' => 'Sigma 70-300mm F4-5.6 APO Macro Super II', + 'E0 3C 5C 8E 30 3C 4B 06' => 'Sigma 70-300mm F4-5.6 APO DG Macro HSM', #22 + 'A3 3C 5C 8E 30 3C 4B 0E' => 'Sigma 70-300mm F4-5.6 DG OS', + '02 37 5E 8E 35 3D 02 00' => 'Sigma 75-300mm F4.5-5.6 APO', + '02 3A 5E 8E 32 3D 02 00' => 'Sigma 75-300mm F4.0-5.6', + '77 44 61 98 34 3C 7B 0E' => 'Sigma 80-400mm F4.5-5.6 EX OS', + '77 44 60 98 34 3C 7B 0E' => 'Sigma 80-400mm F4.5-5.6 APO DG D OS', + '48 48 68 8E 30 30 4B 02' => 'Sigma APO 100-300mm F4 EX IF HSM', + 'F3 48 68 8E 30 30 4B 02' => 'Sigma APO 100-300mm F4 EX IF HSM', + '48 54 6F 8E 24 24 4B 02' => 'Sigma APO 120-300mm F2.8 EX DG HSM', + '7A 54 6E 8E 24 24 4B 02' => 'Sigma APO 120-300mm F2.8 EX DG HSM', + 'FA 54 6E 8E 24 24 4B 02' => 'Sigma APO 120-300mm F2.8 EX DG HSM', #http://u88.n24.queensu.ca/exiftool/forum/index.php/topic,2787.0.html + 'CF 38 6E 98 34 3C 4B 0E' => 'Sigma APO 120-400mm F4.5-5.6 DG OS HSM', + 'C3 34 68 98 38 40 4B 4E' => 'Sigma 100-400mm F5-6.3 DG OS HSM | C', #JR (017) + '8D 48 6E 8E 24 24 4B 0E' => 'Sigma 120-300mm F2.8 DG OS HSM Sports', + '26 44 73 98 34 3C 1C 02' => 'Sigma 135-400mm F4.5-5.6 APO Aspherical', + 'CE 34 76 A0 38 40 4B 0E' => 'Sigma 150-500mm F5-6.3 DG OS APO HSM', #JD + '81 34 76 A6 38 40 4B 0E' => 'Sigma 150-600mm F5-6.3 DG OS HSM | S', #Jaap Voets + '82 34 76 A6 38 40 4B 0E' => 'Sigma 150-600mm F5-6.3 DG OS HSM | C', + '26 40 7B A0 34 40 1C 02' => 'Sigma APO 170-500mm F5-6.3 Aspherical RF', + 'A7 49 80 A0 24 24 4B 06' => 'Sigma APO 200-500mm F2.8 EX DG', + '48 3C 8E B0 3C 3C 4B 02' => 'Sigma APO 300-800mm F5.6 EX DG HSM', +# + '00 47 25 25 24 24 00 02' => 'Tamron SP AF 14mm f/2.8 Aspherical (IF) (69E)', + 'E8 4C 44 44 14 14 DF 0E' => 'Tamron SP 35mm f/1.8 Di VC USD (F012)', #35 + 'E7 4C 4C 4C 14 14 DF 0E' => 'Tamron SP 45mm f/1.8 Di VC USD (F013)', + 'F4 54 56 56 18 18 84 06' => 'Tamron SP AF 60mm f/2.0 Di II Macro 1:1 (G005)', #24 + '1E 5D 64 64 20 20 13 00' => 'Tamron SP AF 90mm f/2.5 (52E)', + '20 5A 64 64 20 20 14 00' => 'Tamron SP AF 90mm f/2.5 Macro (152E)', + '22 53 64 64 24 24 E0 02' => 'Tamron SP AF 90mm f/2.8 Macro 1:1 (72E)', + '32 53 64 64 24 24 35 02' => 'Tamron SP AF 90mm f/2.8 [Di] Macro 1:1 (172E/272E)', + 'F8 55 64 64 24 24 84 06' => 'Tamron SP AF 90mm f/2.8 Di Macro 1:1 (272NII)', + 'F8 54 64 64 24 24 DF 06' => 'Tamron SP AF 90mm f/2.8 Di Macro 1:1 (272NII)', + 'FE 54 64 64 24 24 DF 0E' => 'Tamron SP 90mm f/2.8 Di VC USD Macro 1:1 (F004)', #Jurgen Sahlberg + 'E4 54 64 64 24 24 DF 0E' => 'Tamron SP 90mm f/2.8 Di VC USD Macro 1:1 (F017)', #Rolf Probst + '00 4C 7C 7C 2C 2C 00 02' => 'Tamron SP AF 180mm f/3.5 Di Model (B01)', + '21 56 8E 8E 24 24 14 00' => 'Tamron SP AF 300mm f/2.8 LD-IF (60E)', + '27 54 8E 8E 24 24 1D 02' => 'Tamron SP AF 300mm f/2.8 LD-IF (360E)', + 'E1 40 19 36 2C 35 DF 4E' => 'Tamron 10-24mm f/3.5-4.5 Di II VC HLD (B023)', + 'F6 3F 18 37 2C 34 84 06' => 'Tamron SP AF 10-24mm f/3.5-4.5 Di II LD Aspherical (IF) (B001)', + 'F6 3F 18 37 2C 34 DF 06' => 'Tamron SP AF 10-24mm f/3.5-4.5 Di II LD Aspherical (IF) (B001)', #30 + '00 36 1C 2D 34 3C 00 06' => 'Tamron SP AF 11-18mm f/4.5-5.6 Di II LD Aspherical (IF) (A13)', + 'E9 48 27 3E 24 24 DF 0E' => 'Tamron SP 15-30mm f/2.8 Di VC USD (A012)', #IB + 'CA 48 27 3E 24 24 DF 4E' => 'Tamron SP 15-30mm f/2.8 Di VC USD G2 (A041)', #IB + 'EA 40 29 8E 2C 40 DF 0E' => 'Tamron AF 16-300mm f/3.5-6.3 Di II VC PZD (B016)', + '07 46 2B 44 24 30 03 02' => 'Tamron SP AF 17-35mm f/2.8-4 Di LD Aspherical (IF) (A05)', + 'CB 3C 2B 44 24 31 DF 46' => 'Tamron 17-35mm f/2.8-4 Di OSD (A037)', #IB + '00 53 2B 50 24 24 00 06' => 'Tamron SP AF 17-50mm f/2.8 XR Di II LD Aspherical (IF) (A16)', #PH + '00 54 2B 50 24 24 00 06' => 'Tamron SP AF 17-50mm f/2.8 XR Di II LD Aspherical (IF) (A16NII)', + 'FB 54 2B 50 24 24 84 06' => 'Tamron SP AF 17-50mm f/2.8 XR Di II LD Aspherical (IF) (A16NII)', #http://u88.n24.queensu.ca/exiftool/forum/index.php/topic,3787.0.html + 'F3 54 2B 50 24 24 84 0E' => 'Tamron SP AF 17-50mm f/2.8 XR Di II VC LD Aspherical (IF) (B005)', + '00 3F 2D 80 2B 40 00 06' => 'Tamron AF 18-200mm f/3.5-6.3 XR Di II LD Aspherical (IF) (A14)', + '00 3F 2D 80 2C 40 00 06' => 'Tamron AF 18-200mm f/3.5-6.3 XR Di II LD Aspherical (IF) Macro (A14)', + '00 40 2D 80 2C 40 00 06' => 'Tamron AF 18-200mm f/3.5-6.3 XR Di II LD Aspherical (IF) Macro (A14NII)', #NJ + 'FC 40 2D 80 2C 40 DF 06' => 'Tamron AF 18-200mm f/3.5-6.3 XR Di II LD Aspherical (IF) Macro (A14NII)', #PH (NC) + 'E6 40 2D 80 2C 40 DF 0E' => 'Tamron AF 18-200mm f/3.5-6.3 Di II VC (B018)', #Tanel + '00 40 2D 88 2C 40 62 06' => 'Tamron AF 18-250mm f/3.5-6.3 Di II LD Aspherical (IF) Macro (A18)', + '00 40 2D 88 2C 40 00 06' => 'Tamron AF 18-250mm f/3.5-6.3 Di II LD Aspherical (IF) Macro (A18NII)', #JD + 'F5 40 2C 8A 2C 40 40 0E' => 'Tamron AF 18-270mm f/3.5-6.3 Di II VC LD Aspherical (IF) Macro (B003)', + 'F0 3F 2D 8A 2C 40 DF 0E' => 'Tamron AF 18-270mm f/3.5-6.3 Di II VC PZD (B008)', + 'E0 40 2D 98 2C 41 DF 4E' => 'Tamron AF 18-400mm f/3.5-6.3 Di II VC HLD (B028)', + '07 40 2F 44 2C 34 03 02' => 'Tamron AF 19-35mm f/3.5-4.5 (A10)', + '07 40 30 45 2D 35 03 02' => 'Tamron AF 19-35mm f/3.5-4.5 (A10)', + '00 49 30 48 22 2B 00 02' => 'Tamron SP AF 20-40mm f/2.7-3.5 (166D)', + '0E 4A 31 48 23 2D 0E 02' => 'Tamron SP AF 20-40mm f/2.7-3.5 (166D)', + 'FE 48 37 5C 24 24 DF 0E' => 'Tamron SP 24-70mm f/2.8 Di VC USD (A007)', #24 + 'CE 47 37 5C 25 25 DF 4E' => 'Tamron SP 24-70mm f/2.8 Di VC USD G2 (A032)', #forum9110 + '45 41 37 72 2C 3C 48 02' => 'Tamron SP AF 24-135mm f/3.5-5.6 AD Aspherical (IF) Macro (190D)', + '33 54 3C 5E 24 24 62 02' => 'Tamron SP AF 28-75mm f/2.8 XR Di LD Aspherical (IF) Macro (A09)', + 'FA 54 3C 5E 24 24 84 06' => 'Tamron SP AF 28-75mm f/2.8 XR Di LD Aspherical (IF) Macro (A09NII)', #JD + 'FA 54 3C 5E 24 24 DF 06' => 'Tamron SP AF 28-75mm f/2.8 XR Di LD Aspherical (IF) Macro (A09NII)', + '10 3D 3C 60 2C 3C D2 02' => 'Tamron AF 28-80mm f/3.5-5.6 Aspherical (177D)', + '45 3D 3C 60 2C 3C 48 02' => 'Tamron AF 28-80mm f/3.5-5.6 Aspherical (177D)', + '00 48 3C 6A 24 24 00 02' => 'Tamron SP AF 28-105mm f/2.8 LD Aspherical IF (176D)', + '4D 3E 3C 80 2E 3C 62 02' => 'Tamron AF 28-200mm f/3.8-5.6 XR Aspherical (IF) Macro (A03N)', + '0B 3E 3D 7F 2F 3D 0E 00' => 'Tamron AF 28-200mm f/3.8-5.6 (71D)', + '0B 3E 3D 7F 2F 3D 0E 02' => 'Tamron AF 28-200mm f/3.8-5.6D (171D)', + '12 3D 3C 80 2E 3C DF 02' => 'Tamron AF 28-200mm f/3.8-5.6 AF Aspherical LD (IF) (271D)', + '4D 41 3C 8E 2B 40 62 02' => 'Tamron AF 28-300mm f/3.5-6.3 XR Di LD Aspherical (IF) (A061)', + '4D 41 3C 8E 2C 40 62 02' => 'Tamron AF 28-300mm f/3.5-6.3 XR LD Aspherical (IF) (185D)', + 'F9 40 3C 8E 2C 40 40 0E' => 'Tamron AF 28-300mm f/3.5-6.3 XR Di VC LD Aspherical (IF) Macro (A20)', + '00 47 53 80 30 3C 00 06' => 'Tamron AF 55-200mm f/4-5.6 Di II LD (A15)', + 'F7 53 5C 80 24 24 84 06' => 'Tamron SP AF 70-200mm f/2.8 Di LD (IF) Macro (A001)', + 'FE 53 5C 80 24 24 84 06' => 'Tamron SP AF 70-200mm f/2.8 Di LD (IF) Macro (A001)', + 'F7 53 5C 80 24 24 40 06' => 'Tamron SP AF 70-200mm f/2.8 Di LD (IF) Macro (A001)', + # 'FE 54 5C 80 24 24 DF 0E' => 'Tamron SP AF 70-200mm f/2.8 Di VC USD (A009)', + 'FE 54 5C 80 24 24 DF 0E' => 'Tamron SP 70-200mm f/2.8 Di VC USD (A009)', #NJ + 'E2 47 5C 80 24 24 DF 4E' => 'Tamron SP 70-200mm f/2.8 Di VC USD G2 (A025)', #forum9549 + '69 48 5C 8E 30 3C 6F 02' => 'Tamron AF 70-300mm f/4-5.6 LD Macro 1:2 (572D/772D)', + '69 47 5C 8E 30 3C 00 02' => 'Tamron AF 70-300mm f/4-5.6 Di LD Macro 1:2 (A17N)', + '00 48 5C 8E 30 3C 00 06' => 'Tamron AF 70-300mm f/4-5.6 Di LD Macro 1:2 (A17NII)', #JD + 'F1 47 5C 8E 30 3C DF 0E' => 'Tamron SP 70-300mm f/4-5.6 Di VC USD (A005)', + 'CF 47 5C 8E 31 3D DF 0E' => 'Tamron SP 70-300mm f/4-5.6 Di VC USD (A030)', #forum9773 + 'EB 40 76 A6 38 40 DF 0E' => 'Tamron SP AF 150-600mm f/5-6.3 VC USD (A011)', + 'E3 40 76 A6 38 40 DF 4E' => 'Tamron SP 150-600mm f/5-6.3 Di VC USD G2', #30 + '20 3C 80 98 3D 3D 1E 02' => 'Tamron AF 200-400mm f/5.6 LD IF (75D)', + '00 3E 80 A0 38 3F 00 02' => 'Tamron SP AF 200-500mm f/5-6.3 Di LD (IF) (A08)', + '00 3F 80 A0 38 3F 00 02' => 'Tamron SP AF 200-500mm f/5-6.3 Di (A08)', +# + '00 40 2B 2B 2C 2C 00 02' => 'Tokina AT-X 17 AF PRO (AF 17mm f/3.5)', + '00 47 44 44 24 24 00 06' => 'Tokina AT-X M35 PRO DX (AF 35mm f/2.8 Macro)', + '00 54 68 68 24 24 00 02' => 'Tokina AT-X M100 AF PRO D (AF 100mm f/2.8 Macro)', + '27 48 8E 8E 30 30 1D 02' => 'Tokina AT-X 304 AF (AF 300mm f/4.0)', + '00 54 8E 8E 24 24 00 02' => 'Tokina AT-X 300 AF PRO (AF 300mm f/2.8)', + '12 3B 98 98 3D 3D 09 00' => 'Tokina AT-X 400 AF SD (AF 400mm f/5.6)', + '00 40 18 2B 2C 34 00 06' => 'Tokina AT-X 107 AF DX Fisheye (AF 10-17mm f/3.5-4.5)', + '00 48 1C 29 24 24 00 06' => 'Tokina AT-X 116 PRO DX (AF 11-16mm f/2.8)', + '7A 48 1C 29 24 24 7E 06' => 'Tokina AT-X 116 PRO DX II (AF 11-16mm f/2.8)', + '7A 48 1C 30 24 24 7E 06' => 'Tokina AT-X 11-20 F2.8 PRO DX (AF 11-20mm f/2.8)', + '00 3C 1F 37 30 30 00 06' => 'Tokina AT-X 124 AF PRO DX (AF 12-24mm f/4)', + '7A 3C 1F 37 30 30 7E 06.2' => 'Tokina AT-X 124 AF PRO DX II (AF 12-24mm f/4)', + '7A 3C 1F 3C 30 30 7E 06' => 'Tokina AT-X 12-28 PRO DX (AF 12-28mm f/4)', + '00 48 29 3C 24 24 00 06' => 'Tokina AT-X 16-28 AF PRO FX (AF 16-28mm f/2.8)', + '00 48 29 50 24 24 00 06' => 'Tokina AT-X 165 PRO DX (AF 16-50mm f/2.8)', + '00 40 2A 72 2C 3C 00 06' => 'Tokina AT-X 16.5-135 DX (AF 16.5-135mm F3.5-5.6)', + '00 3C 2B 44 30 30 00 06' => 'Tokina AT-X 17-35 F4 PRO FX (AF 17-35mm f/4)', + '2F 40 30 44 2C 34 29 02.2' => 'Tokina AF 193 (AF 19-35mm f/3.5-4.5)', + '2F 48 30 44 24 24 29 02.2' => 'Tokina AT-X 235 AF PRO (AF 20-35mm f/2.8)', + '2F 40 30 44 2C 34 29 02.1' => 'Tokina AF 235 II (AF 20-35mm f/3.5-4.5)', + '00 48 37 5C 24 24 00 06' => 'Tokina AT-X 24-70 F2.8 PRO FX (AF 24-70mm f/2.8)', + '00 40 37 80 2C 3C 00 02' => 'Tokina AT-X 242 AF (AF 24-200mm f/3.5-5.6)', + '25 48 3C 5C 24 24 1B 02.1' => 'Tokina AT-X 270 AF PRO II (AF 28-70mm f/2.6-2.8)', + '25 48 3C 5C 24 24 1B 02.2' => 'Tokina AT-X 287 AF PRO SV (AF 28-70mm f/2.8)', + '07 48 3C 5C 24 24 03 00' => 'Tokina AT-X 287 AF (AF 28-70mm f/2.8)', + '07 47 3C 5C 25 35 03 00' => 'Tokina AF 287 SD (AF 28-70mm f/2.8-4.5)', + '07 40 3C 5C 2C 35 03 00' => 'Tokina AF 270 II (AF 28-70mm f/3.5-4.5)', + '00 48 3C 60 24 24 00 02' => 'Tokina AT-X 280 AF PRO (AF 28-80mm f/2.8)', + '25 44 44 8E 34 42 1B 02' => 'Tokina AF 353 (AF 35-300mm f/4.5-6.7)', + '00 48 50 72 24 24 00 06' => 'Tokina AT-X 535 PRO DX (AF 50-135mm f/2.8)', + '00 3C 5C 80 30 30 00 0E' => 'Tokina AT-X 70-200 F4 FX VCM-S (AF 70-200mm f/4)', + '00 48 5C 80 30 30 00 0E' => 'Tokina AT-X 70-200 F4 FX VCM-S (AF 70-200mm f/4)', + '12 44 5E 8E 34 3C 09 00' => 'Tokina AF 730 (AF 75-300mm F4.5-5.6)', + '14 54 60 80 24 24 0B 00' => 'Tokina AT-X 828 AF (AF 80-200mm f/2.8)', + '24 54 60 80 24 24 1A 02' => 'Tokina AT-X 828 AF PRO (AF 80-200mm f/2.8)', + '24 44 60 98 34 3C 1A 02' => 'Tokina AT-X 840 AF-II (AF 80-400mm f/4.5-5.6)', + '00 44 60 98 34 3C 00 02' => 'Tokina AT-X 840 D (AF 80-400mm f/4.5-5.6)', + '14 48 68 8E 30 30 0B 00' => 'Tokina AT-X 340 AF (AF 100-300mm f/4)', +# + '06 3F 68 68 2C 2C 06 00' => 'Cosina AF 100mm F3.5 Macro', + '07 36 3D 5F 2C 3C 03 00' => 'Cosina AF Zoom 28-80mm F3.5-5.6 MC Macro', + '07 46 3D 6A 25 2F 03 00' => 'Cosina AF Zoom 28-105mm F2.8-3.8 MC', + '12 36 5C 81 35 3D 09 00' => 'Cosina AF Zoom 70-210mm F4.5-5.6 MC Macro', + '12 39 5C 8E 34 3D 08 02' => 'Cosina AF Zoom 70-300mm F4.5-5.6 MC Macro', + '12 3B 68 8D 3D 43 09 02' => 'Cosina AF Zoom 100-300mm F5.6-6.7 MC Macro', +# + '12 38 69 97 35 42 09 02' => 'Promaster Spectrum 7 100-400mm F4.5-6.7', +# + '00 40 31 31 2C 2C 00 00' => 'Voigtlander Color Skopar 20mm F3.5 SLII Aspherical', + '00 48 3C 3C 24 24 00 00' => 'Voigtlander Color Skopar 28mm F2.8 SL II', + '00 54 48 48 18 18 00 00' => 'Voigtlander Ultron 40mm F2 SLII Aspherical', + '00 54 55 55 0C 0C 00 00' => 'Voigtlander Nokton 58mm F1.4 SLII', + '00 40 64 64 2C 2C 00 00' => 'Voigtlander APO-Lanthar 90mm F3.5 SLII Close Focus', +# + '00 40 2D 2D 2C 2C 00 00' => 'Carl Zeiss Distagon T* 3.5/18 ZF.2', + '00 48 32 32 24 24 00 00' => 'Carl Zeiss Distagon T* 2.8/21 ZF.2', + '00 54 38 38 18 18 00 00' => 'Carl Zeiss Distagon T* 2/25 ZF.2', + '00 54 3C 3C 18 18 00 00' => 'Carl Zeiss Distagon T* 2/28 ZF.2', + '00 54 44 44 0C 0C 00 00' => 'Carl Zeiss Distagon T* 1.4/35 ZF.2', + '00 54 44 44 18 18 00 00' => 'Carl Zeiss Distagon T* 2/35 ZF.2', + '00 54 50 50 0C 0C 00 00' => 'Carl Zeiss Planar T* 1.4/50 ZF.2', + '00 54 50 50 18 18 00 00' => 'Carl Zeiss Makro-Planar T* 2/50 ZF.2', + '00 54 62 62 0C 0C 00 00' => 'Carl Zeiss Planar T* 1.4/85 ZF.2', + '00 54 68 68 18 18 00 00' => 'Carl Zeiss Makro-Planar T* 2/100 ZF.2', + '00 54 72 72 18 18 00 00' => 'Carl Zeiss Apo Sonnar T* 2/135 ZF.2', + '00 54 53 53 0C 0C 00 00' => 'Zeiss Otus 1.4/55', #IB + '01 54 62 62 0C 0C 00 00' => 'Zeiss Otus 1.4/85', + '52 54 44 44 18 18 00 00' => 'Zeiss Milvus 35mm f/2', + '53 54 50 50 0C 0C 00 00' => 'Zeiss Milvus 50mm f/1.4', #IB + '54 54 50 50 18 18 00 00' => 'Zeiss Milvus 50mm f/2 Macro', + '55 54 62 62 0C 0C 00 00' => 'Zeiss Milvus 85mm f/1.4', #IB + '56 54 68 68 18 18 00 00' => 'Zeiss Milvus 100mm f/2 Macro', +# + '00 54 56 56 30 30 00 00' => 'Coastal Optical Systems 60mm 1:4 UV-VIS-IR Macro Apo', +# + 'BF 4E 26 26 1E 1E 01 04' => 'Irix 15mm f/2.4 Firefly', #30 + 'BF 3C 1B 1B 30 30 01 04' => 'Irix 11mm f/4 Firefly', #30 +# + '4A 40 11 11 2C 0C 4D 02' => 'Samyang 8mm f/3.5 Fish-Eye CS', + '4A 48 24 24 24 0C 4D 02.1' => 'Samyang 10mm f/2.8 ED AS NCS CS', + '4A 48 1E 1E 24 0C 4D 02' => 'Samyang 12mm f/2.8 ED AS NCS Fish-Eye', #Jurgen Sahlberg + '4A 48 24 24 24 0C 4D 02.2' => 'Samyang AE 14mm f/2.8 ED AS IF UMC', #http://u88.n24.queensu.ca/exiftool/forum/index.php/topic,3150.0.html + '4A 4C 24 24 1E 6C 4D 06' => 'Samyang 14mm f/2.4 Premium', + '4A 54 29 29 18 0C 4D 02' => 'Samyang 16mm f/2.0 ED AS UMC CS', #Jon Bloom (by email) + '4A 60 36 36 0C 0C 4D 02' => 'Samyang 24mm f/1.4 ED AS UMC', + '4A 60 44 44 0C 0C 4D 02' => 'Samyang 35mm f/1.4 AS UMC', + '4A 60 62 62 0C 0C 4D 02' => 'Samyang AE 85mm f/1.4 AS IF UMC', #http://u88.n24.queensu.ca/exiftool/forum/index.php/topic,2888.0.html +# + '9A 4C 50 50 14 14 9C 06' => 'Yongnuo YN50mm F1.8N', +# + '02 40 44 5C 2C 34 02 00' => 'Exakta AF 35-70mm 1:3.5-4.5 MC', +# + '07 3E 30 43 2D 35 03 00' => 'Soligor AF Zoom 19-35mm 1:3.5-4.5 MC', + '03 43 5C 81 35 35 02 00' => 'Soligor AF C/D Zoom UMCS 70-210mm 1:4.5', + '12 4A 5C 81 31 3D 09 00' => 'Soligor AF C/D Auto Zoom+Macro 70-210mm 1:4-5.6 UMCS', + '12 36 69 97 35 42 09 00' => 'Soligor AF Zoom 100-400mm 1:4.5-6.7 MC', +# + '00 00 00 00 00 00 00 01' => 'Manual Lens No CPU', +# + '00 00 48 48 53 53 00 01' => 'Loreo 40mm F11-22 3D Lens in a Cap 9005', #PH + '00 47 10 10 24 24 00 00' => 'Fisheye Nikkor 8mm f/2.8 AiS', + '00 47 3C 3C 24 24 00 00' => 'Nikkor 28mm f/2.8 AiS', #35 + # '00 54 44 44 0C 0C 00 00' => 'Nikkor 35mm f/1.4 AiS', comment out in favour of Zeiss with same ID because this lens is rare (requires CPU upgrade) + '00 57 50 50 14 14 00 00' => 'Nikkor 50mm f/1.8 AI', #35 + '00 48 50 50 18 18 00 00' => 'Nikkor H 50mm f/2', + '00 48 68 68 24 24 00 00' => 'Series E 100mm f/2.8', + '00 4C 6A 6A 20 20 00 00' => 'Nikkor 105mm f/2.5 AiS', + '00 48 80 80 30 30 00 00' => 'Nikkor 200mm f/4 AiS', + '00 40 11 11 2C 2C 00 00' => 'Samyang 8mm f/3.5 Fish-Eye', + '00 58 64 64 20 20 00 00' => 'Soligor C/D Macro MC 90mm f/2.5', +); + +# text encoding used in LocationInfo (ref PH) +%nikonTextEncoding = ( + 0 => 'n/a', + 1 => 'UTF8', + # UTF16 is a guess here: it could also be Unicode or JIS, + # but I chose UTF16 due to the similarity with the QuickTime stringEncoding + 2 => 'UTF16', +); + +# flash firmware decoding (ref JD) +my %flashFirmware = ( + '0 0' => 'n/a', + '1 1' => '1.01 (SB-800 or Metz 58 AF-1)', + '1 3' => '1.03 (SB-800)', + '2 1' => '2.01 (SB-800)', + '2 4' => '2.04 (SB-600)', + '2 5' => '2.05 (SB-600)', + '3 1' => '3.01 (SU-800 Remote Commander)', + '4 1' => '4.01 (SB-400)', + '4 2' => '4.02 (SB-400)', + '4 4' => '4.04 (SB-400)', + '5 1' => '5.01 (SB-900)', + '5 2' => '5.02 (SB-900)', + '6 1' => '6.01 (SB-700)', #http://u88.n24.queensu.ca/exiftool/forum/index.php/topic,5034.0.html + '7 1' => '7.01 (SB-910)', #PH + OTHER => sub { + my ($val, $inv) = @_; + return sprintf('%d.%.2d (Unknown model)', split(' ', $val)) unless $inv; + return "$1 $2" if $val =~ /(\d+)\.(\d+)/; + return '0 0'; + }, +); + +# flash Guide Number (GN) distance settings (ref 28) +my %flashGNDistance = ( + 0 => 0, 19 => '2.8 m', + 1 => '0.1 m', 20 => '3.2 m', + 2 => '0.2 m', 21 => '3.6 m', + 3 => '0.3 m', 22 => '4.0 m', + 4 => '0.4 m', 23 => '4.5 m', + 5 => '0.5 m', 24 => '5.0 m', + 6 => '0.6 m', 25 => '5.6 m', + 7 => '0.7 m', 26 => '6.3 m', + 8 => '0.8 m', 27 => '7.1 m', + 9 => '0.9 m', 28 => '8.0 m', + 10 => '1.0 m', 29 => '9.0 m', + 11 => '1.1 m', 30 => '10.0 m', + 12 => '1.3 m', 31 => '11.0 m', + 13 => '1.4 m', 32 => '13.0 m', + 14 => '1.6 m', 33 => '14.0 m', + 15 => '1.8 m', 34 => '16.0 m', + 16 => '2.0 m', 35 => '18.0 m', + 17 => '2.2 m', 36 => '20.0 m', + 18 => '2.5 m', 255 => 'n/a', +); + +# flash color filter values (ref 28) +my %flashColorFilter = ( + 0x00 => 'None', + 1 => 'FL-GL1 or SZ-2FL Fluorescent', # (green) (SZ model ref PH) + 2 => 'FL-GL2', + 9 => 'TN-A1 or SZ-2TN Incandescent', # (orange) (SZ model ref PH) + 10 => 'TN-A2', + 65 => 'Red', + 66 => 'Blue', + 67 => 'Yellow', + 68 => 'Amber', +); + +# flash control mode values (ref JD) +my %flashControlMode = ( + 0x00 => 'Off', + 0x01 => 'iTTL-BL', + 0x02 => 'iTTL', + 0x03 => 'Auto Aperture', + 0x04 => 'Automatic', #28 + 0x05 => 'GN (distance priority)', #28 (Guide Number, but called "GN" in manual) + 0x06 => 'Manual', + 0x07 => 'Repeating Flash', +); + +my %retouchValues = ( #PH + 0 => 'None', + 3 => 'B & W', + 4 => 'Sepia', + 5 => 'Trim', + 6 => 'Small Picture', + 7 => 'D-Lighting', + 8 => 'Red Eye', + 9 => 'Cyanotype', + 10 => 'Sky Light', + 11 => 'Warm Tone', + 12 => 'Color Custom', + 13 => 'Image Overlay', + 14 => 'Red Intensifier', + 15 => 'Green Intensifier', + 16 => 'Blue Intensifier', + 17 => 'Cross Screen', + 18 => 'Quick Retouch', + 19 => 'NEF Processing', + 23 => 'Distortion Control', + 25 => 'Fisheye', + 26 => 'Straighten', + 29 => 'Perspective Control', + 30 => 'Color Outline', + 31 => 'Soft Filter', + 32 => 'Resize', #31 + 33 => 'Miniature Effect', + 34 => 'Skin Softening', # (S9200) + 35 => 'Selected Frame', #31 (frame exported from MOV) + 37 => 'Color Sketch', #31 + 38 => 'Selective Color', # (S9200) + 39 => 'Glamour', # (S3500) + 40 => 'Drawing', # (S9200) + 44 => 'Pop', # (S3500) + 45 => 'Toy Camera Effect 1', # (S3500) + 46 => 'Toy Camera Effect 2', # (S3500) + 47 => 'Cross Process (red)', # (S3500) + 48 => 'Cross Process (blue)', # (S3500) + 49 => 'Cross Process (green)', # (S3500) + 50 => 'Cross Process (yellow)', # (S3500) + 51 => 'Super Vivid', # (S3500) + 52 => 'High-contrast Monochrome', # (S3500) + 53 => 'High Key', # (S3500) + 54 => 'Low Key', # (S3500) +); + +# AF point indices for models with 51 focus points, eg. D3 (ref JD/PH) +# A1 A2 A3 A4 A5 A6 A7 A8 A9 +# B1 B2 B3 B4 B5 B6 B7 B8 B9 B10 B11 +# C1 C2 C3 C4 C5 C6 C7 C8 C9 C10 C11 +# D1 D2 D3 D4 D5 D6 D7 D8 D9 D10 D11 +# E1 E2 E3 E4 E5 E6 E7 E8 E9 +my %afPoints51 = ( + 1 => 'C6', 11 => 'C5', 21 => 'C9', 31 => 'C11',41 => 'A2', 51 => 'D1', + 2 => 'B6', 12 => 'B5', 22 => 'B9', 32 => 'B11',42 => 'D3', + 3 => 'A5', 13 => 'A4', 23 => 'A8', 33 => 'D11',43 => 'E2', + 4 => 'D6', 14 => 'D5', 24 => 'D9', 34 => 'C4', 44 => 'C2', + 5 => 'E5', 15 => 'E4', 25 => 'E8', 35 => 'B4', 45 => 'B2', + 6 => 'C7', 16 => 'C8', 26 => 'C10',36 => 'A3', 46 => 'A1', + 7 => 'B7', 17 => 'B8', 27 => 'B10',37 => 'D4', 47 => 'D2', + 8 => 'A6', 18 => 'A7', 28 => 'A9', 38 => 'E3', 48 => 'E1', + 9 => 'D7', 19 => 'D8', 29 => 'D10',39 => 'C3', 49 => 'C1', + 10 => 'E6', 20 => 'E7', 30 => 'E9', 40 => 'B3', 50 => 'B1', +); + +# AF point indices for models with 39 focus points, eg. D7000 (ref 29) +# A1 A2 A3 +# B1 B2 B3 B4 B5 B6 B7 B8 B9 B10 B11 +# C1 C2 C3 C4 C5 C6 C7 C8 C9 C10 C11 +# D1 D2 D3 D4 D5 D6 D7 D8 D9 D10 D11 +# E1 E2 E3 +my %afPoints39 = ( + 1 => 'C6', 11 => 'C5', 21 => 'D9', 31 => 'C3', + 2 => 'B6', 12 => 'B5', 22 => 'C10',32 => 'B3', + 3 => 'A2', 13 => 'A1', 23 => 'B10',33 => 'D3', + 4 => 'D6', 14 => 'D5', 24 => 'D10',34 => 'C2', + 5 => 'E2', 15 => 'E1', 25 => 'C11',35 => 'B2', + 6 => 'C7', 16 => 'C8', 26 => 'B11',36 => 'D2', + 7 => 'B7', 17 => 'B8', 27 => 'D11',37 => 'C1', + 8 => 'A3', 18 => 'D8', 28 => 'C4', 38 => 'B1', + 9 => 'D7', 19 => 'C9', 29 => 'B4', 39 => 'D1', + 10 => 'E3', 20 => 'B9', 30 => 'D4', +); + +# AF point indices for models with 135 focus points, eg. 1J1 (ref PH) +# - 9 rows (A-I) with 15 columns (1-15), center is E8 +# - odd columns, columns 2 and 14, and the remaining corner points are +# not used in 41-point mode +my %afPoints135 = ( + 1 => 'E8', 28 => 'E10', 55 => 'E13', 82 => 'E6', 109 => 'E3', + 2 => 'D8', 29 => 'D10', 56 => 'D13', 83 => 'D6', 110 => 'D3', + 3 => 'C8', 30 => 'C10', 57 => 'C13', 84 => 'C6', 111 => 'C3', + 4 => 'B8', 31 => 'B10', 58 => 'B13', 85 => 'B6', 112 => 'B3', + 5 => 'A8', 32 => 'A10', 59 => 'A13', 86 => 'A6', 113 => 'A3', + 6 => 'F8', 33 => 'F10', 60 => 'F13', 87 => 'F6', 114 => 'F3', + 7 => 'G8', 34 => 'G10', 61 => 'G13', 88 => 'G6', 115 => 'G3', + 8 => 'H8', 35 => 'H10', 62 => 'H13', 89 => 'H6', 116 => 'H3', + 9 => 'I8', 36 => 'I10', 63 => 'I13', 90 => 'I6', 117 => 'I3', + 10 => 'E9', 37 => 'E11', 64 => 'E14', 91 => 'E5', 118 => 'E2', + 11 => 'D9', 38 => 'D11', 65 => 'D14', 92 => 'D5', 119 => 'D2', + 12 => 'C9', 39 => 'C11', 66 => 'C14', 93 => 'C5', 120 => 'C2', + 13 => 'B9', 40 => 'B11', 67 => 'B14', 94 => 'B5', 121 => 'B2', + 14 => 'A9', 41 => 'A11', 68 => 'A14', 95 => 'A5', 122 => 'A2', + 15 => 'F9', 42 => 'F11', 69 => 'F14', 96 => 'F5', 123 => 'F2', + 16 => 'G9', 43 => 'G11', 70 => 'G14', 97 => 'G5', 124 => 'G2', + 17 => 'H9', 44 => 'H11', 71 => 'H14', 98 => 'H5', 125 => 'H2', + 18 => 'I9', 45 => 'I11', 72 => 'I14', 99 => 'I5', 126 => 'I2', + 19 => 'E7', 46 => 'E12', 73 => 'E15', 100 => 'E4', 127 => 'E1', + 20 => 'D7', 47 => 'D12', 74 => 'D15', 101 => 'D4', 128 => 'D1', + 21 => 'C7', 48 => 'C12', 75 => 'C15', 102 => 'C4', 129 => 'C1', + 22 => 'B7', 49 => 'B12', 76 => 'B15', 103 => 'B4', 130 => 'B1', + 23 => 'A7', 50 => 'A12', 77 => 'A15', 104 => 'A4', 131 => 'A1', + 24 => 'F7', 51 => 'F12', 78 => 'F15', 105 => 'F4', 132 => 'F1', + 25 => 'G7', 52 => 'G12', 79 => 'G15', 106 => 'G4', 133 => 'G1', + 26 => 'H7', 53 => 'H12', 80 => 'H15', 107 => 'H4', 134 => 'H1', + 27 => 'I7', 54 => 'I12', 81 => 'I15', 108 => 'I4', 135 => 'I1', +); + +# AF point indices for models with 153 focus points, eg. D5,D500 (ref PH) +# - 9 rows (A-I) with 17 columns (1-17), center is E9 +# - 55 of these are selectable cross points (odd rows and columns 1,3,4,6,7,9,11,12,14,15,17) +my %afPoints153 = ( + 1 => 'E9', 32 => 'A8', 63 => 'I13', 94 => 'B17', 125 => 'H4', + 2 => 'D9', 33 => 'F8', 64 => 'E14', 95 => 'A17', 126 => 'I4', + 3 => 'C9', 34 => 'G8', 65 => 'D14', 96 => 'F17', 127 => 'E3', + 4 => 'B9', 35 => 'H8', 66 => 'C14', 97 => 'G17', 128 => 'D3', + 5 => 'A9', 36 => 'I8', 67 => 'B14', 98 => 'H17', 129 => 'C3', + 6 => 'F9', 37 => 'E7', 68 => 'A14', 99 => 'I17', 130 => 'B3', + 7 => 'G9', 38 => 'D7', 69 => 'F14', 100 => 'E6', 131 => 'A3', + 8 => 'H9', 39 => 'C7', 70 => 'G14', 101 => 'D6', 132 => 'F3', + 9 => 'I9', 40 => 'B7', 71 => 'H14', 102 => 'C6', 133 => 'G3', + 10 => 'E10', 41 => 'A7', 72 => 'I14', 103 => 'B6', 134 => 'H3', + 11 => 'D10', 42 => 'F7', 73 => 'E15', 104 => 'A6', 135 => 'I3', + 12 => 'C10', 43 => 'G7', 74 => 'D15', 105 => 'F6', 136 => 'E2', + 13 => 'B10', 44 => 'H7', 75 => 'C15', 106 => 'G6', 137 => 'D2', + 14 => 'A10', 45 => 'I7', 76 => 'B15', 107 => 'H6', 138 => 'C2', + 15 => 'F10', 46 => 'E12', 77 => 'A15', 108 => 'I6', 139 => 'B2', + 16 => 'G10', 47 => 'D12', 78 => 'F15', 109 => 'E5', 140 => 'A2', + 17 => 'H10', 48 => 'C12', 79 => 'G15', 110 => 'D5', 141 => 'F2', + 18 => 'I10', 49 => 'B12', 80 => 'H15', 111 => 'C5', 142 => 'G2', + 19 => 'E11', 50 => 'A12', 81 => 'I15', 112 => 'B5', 143 => 'H2', + 20 => 'D11', 51 => 'F12', 82 => 'E16', 113 => 'A5', 144 => 'I2', + 21 => 'C11', 52 => 'G12', 83 => 'D16', 114 => 'F5', 145 => 'E1', + 22 => 'B11', 53 => 'H12', 84 => 'C16', 115 => 'G5', 146 => 'D1', + 23 => 'A11', 54 => 'I12', 85 => 'B16', 116 => 'H5', 147 => 'C1', + 24 => 'F11', 55 => 'E13', 86 => 'A16', 117 => 'I5', 148 => 'B1', + 25 => 'G11', 56 => 'D13', 87 => 'F16', 118 => 'E4', 149 => 'A1', + 26 => 'H11', 57 => 'C13', 88 => 'G16', 119 => 'D4', 150 => 'F1', + 27 => 'I11', 58 => 'B13', 89 => 'H16', 120 => 'C4', 151 => 'G1', + 28 => 'E8', 59 => 'A13', 90 => 'I16', 121 => 'B4', 152 => 'H1', + 29 => 'D8', 60 => 'F13', 91 => 'E17', 122 => 'A4', 153 => 'I1', + 30 => 'C8', 61 => 'G13', 92 => 'D17', 123 => 'F4', + 31 => 'B8', 62 => 'H13', 93 => 'C17', 124 => 'G4', +); + +my %cropHiSpeed = ( #IB + 0 => 'Off', + 1 => '1.3x Crop', # (1.3x Crop, Large) + 2 => 'DX Crop', + 3 => '5:4 Crop', + 4 => '3:2 Crop', + 6 => '16:9 Crop', + 9 => 'DX Movie Crop', # (DX during movie recording, Large) + 11 => 'FX Uncropped', + 12 => 'DX Uncropped', + 17 => '1:1 Crop', + OTHER => sub { + my ($val, $inv, $conv) = @_; + return undef if $inv; + my @a = split ' ', $val; + return "Unknown ($val)" unless @a == 7; + $a[0] = $$conv{$a[0]} || "Unknown ($a[0])"; + return "$a[0] ($a[1]x$a[2] cropped to $a[3]x$a[4] at pixel $a[5],$a[6])"; + }, +); + +my %offOn = ( 0 => 'Off', 1 => 'On' ); + +# common attributes for writable BinaryData directories +my %binaryDataAttrs = ( + PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData, + WRITE_PROC => \&Image::ExifTool::WriteBinaryData, + CHECK_PROC => \&Image::ExifTool::CheckBinaryData, + WRITABLE => 1, + FIRST_ENTRY => 0, +); + +# Nikon maker note tags +%Image::ExifTool::Nikon::Main = ( + PROCESS_PROC => \&Image::ExifTool::Nikon::ProcessNikon, + WRITE_PROC => \&Image::ExifTool::Nikon::ProcessNikon, + CHECK_PROC => \&Image::ExifTool::Exif::CheckExif, + WRITABLE => 1, + GROUPS => { 0 => 'MakerNotes', 2 => 'Camera' }, + PRINT_CONV => \&FormatString, + 0x0001 => { #2 + # the format differs for different models. for D70, this is a string '0210', + # but for the E775 it is binary: "\x00\x01\x00\x00" + Name => 'MakerNoteVersion', + Writable => 'undef', + Count => 4, + # convert to string if binary + ValueConv => '$_=$val; /^[\x00-\x09]/ and $_=join("",unpack("CCCC",$_)); $_', + ValueConvInv => '$val', + PrintConv => '$_=$val;s/^(\d{2})/$1\./;s/^0//;$_', + PrintConvInv => '$_=$val;s/\.//;"0$_"', + }, + 0x0002 => { + # this is the ISO actually used by the camera + # (may be different than ISO setting if auto) + Name => 'ISO', + Writable => 'int16u', + Count => 2, + Priority => 0, # the EXIF ISO is more reliable + Groups => { 2 => 'Image' }, + # D300 sets this to undef with 4 zero bytes when LO ISO is used - PH + RawConv => '$val eq "\0\0\0\0" ? undef : $val', + # first number is 1 for "Hi ISO" modes (H0.3, H0.7 and H1.0 on D80) - PH + PrintConv => '$_=$val;s/^0 //;s/^1 (\d+)/Hi $1/;$_', + PrintConvInv => '$_=$val;/^\d+/ ? "0 $_" : (s/Hi ?//i ? "1 $_" : $_)', + }, + # Note: we attempt to fix the case of these string values (typically written in all caps) + 0x0003 => { Name => 'ColorMode', Writable => 'string' }, + 0x0004 => { Name => 'Quality', Writable => 'string' }, + 0x0005 => { Name => 'WhiteBalance', Writable => 'string' }, + 0x0006 => { Name => 'Sharpness', Writable => 'string' }, + 0x0007 => { Name => 'FocusMode', Writable => 'string' }, + # FlashSetting (better named FlashSyncMode, ref 28) values: + # "Normal", "Slow", "Rear Slow", "RED-EYE", "RED-EYE SLOW" + 0x0008 => { Name => 'FlashSetting', Writable => 'string' }, + # FlashType observed values: + # internal: "Built-in,TTL", "Built-in,RPT", "Comdr.", "NEW_TTL" + # external: "Optional,TTL", "Optional,RPT", "Optional,M", "Comdr." + # both: "Built-in,TTL&Comdr." + # no flash: "" + 0x0009 => { Name => 'FlashType', Writable => 'string' }, #2 (count varies by model - PH) + # 0x000a - rational values: 5.6 to 9.33 - found in Coolpix models - PH + # (seems constant for a given camera model, but not correlated with scale factor) + 0x000b => { #2 + Name => 'WhiteBalanceFineTune', + Writable => 'int16s', + Count => -1, # older models write 1 value, newer DSLR's write 2 - PH + }, + 0x000c => { # (D1X) + Name => 'WB_RBLevels', + Writable => 'rational64u', + Count => 4, # (not sure what the last 2 values are for) + }, + 0x000d => { #15 + Name => 'ProgramShift', + Writable => 'undef', + Count => 4, + ValueConv => 'my ($a,$b,$c)=unpack("c3",$val); $c ? $a*($b/$c) : 0', + ValueConvInv => q{ + my $a = int($val*6 + ($val>0 ? 0.5 : -0.5)); + $a<-128 or $a>127 ? undef : pack("c4",$a,1,6,0); + }, + PrintConv => 'Image::ExifTool::Exif::PrintFraction($val)', + PrintConvInv => 'Image::ExifTool::Exif::ConvertFraction($val)', + }, + 0x000e => { + Name => 'ExposureDifference', + Writable => 'undef', + Count => 4, + ValueConv => 'my ($a,$b,$c)=unpack("c3",$val); $c ? $a*($b/$c) : 0', + ValueConvInv => q{ + my $a = int($val*12 + ($val>0 ? 0.5 : -0.5)); + $a<-128 or $a>127 ? undef : pack("c4",$a,1,12,0); + }, + PrintConv => '$val ? sprintf("%+.1f",$val) : 0', + PrintConvInv => '$val', + }, + 0x000f => { Name => 'ISOSelection', Writable => 'string' }, #2 + 0x0010 => { + Name => 'DataDump', + Writable => 0, + Binary => 1, + }, + 0x0011 => { + Name => 'PreviewIFD', + Groups => { 1 => 'PreviewIFD', 2 => 'Image' }, + Flags => 'SubIFD', + SubDirectory => { + TagTable => 'Image::ExifTool::Nikon::PreviewIFD', + Start => '$val', + }, + }, + 0x0012 => { #2 (camera setting: combination of command dial and menus - PH) + Name => 'FlashExposureComp', + Description => 'Flash Exposure Compensation', + Writable => 'undef', + Count => 4, + # (includes the built-in compensation for FlashType "Built-in,TTL&Comdr.") + Notes => q{ + may be set even if flash does not fire. Does not include the effect of + flash bracketing. + }, + ValueConv => 'my ($a,$b,$c)=unpack("c3",$val); $c ? $a*($b/$c) : 0', + ValueConvInv => q{ + my $a = int($val*6 + ($val>0 ? 0.5 : -0.5)); + $a<-128 or $a>127 ? undef : pack("c4",$a,1,6,0); + }, + PrintConv => 'Image::ExifTool::Exif::PrintFraction($val)', + PrintConvInv => 'Image::ExifTool::Exif::ConvertFraction($val)', + }, + # D70 - another ISO tag + 0x0013 => { #2 + Name => 'ISOSetting', + Writable => 'int16u', + Count => 2, + PrintConv => '$_=$val;s/^0 //;$_', + PrintConvInv => '"0 $val"', + }, + 0x0014 => [ + { #4 + Name => 'ColorBalanceA', + Condition => '$format eq "undef" and $count == 2560', + SubDirectory => { + TagTable => 'Image::ExifTool::Nikon::ColorBalanceA', + ByteOrder => 'BigEndian', + }, + }, + { #IB + Name => 'NRWData', + Condition => '$$valPt =~ /^NRW 0100/', + Drop => 1, # 'Drop' because it is large and not found in JPEG images + SubDirectory => { + TagTable => 'Image::ExifTool::Nikon::ColorBalanceB', + }, + }, + { #IB + Name => 'NRWData', + Condition => '$$valPt =~ /^NRW /', + Drop => 1, # 'Drop' because it is large and not found in JPEG images + SubDirectory => { + TagTable => 'Image::ExifTool::Nikon::ColorBalanceC', + }, + }, + ], + # 0x0015 - string[8]: "AUTO " + # D70 Image boundary?? top x,y bot-right x,y + 0x0016 => { #2 + Name => 'ImageBoundary', + Writable => 'int16u', + Count => 4, + }, + 0x0017 => { #28 + Name => 'ExternalFlashExposureComp', #PH (setting from external flash unit) + Writable => 'undef', + Count => 4, + ValueConv => 'my ($a,$b,$c)=unpack("c3",$val); $c ? $a*($b/$c) : 0', + ValueConvInv => q{ + my $a = int($val*6 + ($val>0 ? 0.5 : -0.5)); + $a<-128 or $a>127 ? undef : pack("c4",$a,1,6,0); + }, + PrintConv => 'Image::ExifTool::Exif::PrintFraction($val)', + PrintConvInv => 'Image::ExifTool::Exif::ConvertFraction($val)', + }, + 0x0018 => { #5 + Name => 'FlashExposureBracketValue', + Writable => 'undef', + Count => 4, + ValueConv => 'my ($a,$b,$c)=unpack("c3",$val); $c ? $a*($b/$c) : 0', + ValueConvInv => q{ + my $a = int($val*6 + ($val>0 ? 0.5 : -0.5)); + $a<-128 or $a>127 ? undef : pack("c4",$a,1,6,0); + }, + PrintConv => 'sprintf("%.1f",$val)', + PrintConvInv => '$val', + }, + 0x0019 => { #5 + Name => 'ExposureBracketValue', + Writable => 'rational64s', + PrintConv => 'Image::ExifTool::Exif::PrintFraction($val)', + PrintConvInv => 'Image::ExifTool::Exif::ConvertFraction($val)', + }, + 0x001a => { #PH + Name => 'ImageProcessing', + Writable => 'string', + }, + 0x001b => { #15 + Name => 'CropHiSpeed', + Writable => 'int16u', + Count => 7, + PrintConv => \%cropHiSpeed, + }, + 0x001c => { #28 (D3 "the application of CSb6 to the selected metering mode") + Name => 'ExposureTuning', + Writable => 'undef', + Count => 3, + ValueConv => 'my ($a,$b,$c)=unpack("c3",$val); $c ? $a*($b/$c) : 0', + ValueConvInv => q{ + my $a = int($val*6 + ($val>0 ? 0.5 : -0.5)); + $a<-128 or $a>127 ? undef : pack("c3",$a,1,6); + }, + PrintConv => 'Image::ExifTool::Exif::PrintFraction($val)', + PrintConvInv => 'Image::ExifTool::Exif::ConvertFraction($val)', + }, + 0x001d => { #4 + Name => 'SerialNumber', + # Note: this has been known to change even if the serial number on the body + # stays the same if some parts of the camera were replaced by Nikon service + Writable => 'string', + Protected => 1, + Notes => q{ + this value is used as a key to decrypt other information -- writing this tag + causes the other information to be re-encrypted with the new key + }, + PrintConv => undef, # disable default PRINT_CONV + }, + 0x001e => { #14 + Name => 'ColorSpace', + Writable => 'int16u', + PrintConv => { + 1 => 'sRGB', + 2 => 'Adobe RGB', + }, + }, + 0x001f => { #PH + Name => 'VRInfo', + SubDirectory => { TagTable => 'Image::ExifTool::Nikon::VRInfo' }, + }, + 0x0020 => { #16 + Name => 'ImageAuthentication', + Writable => 'int8u', + PrintConv => \%offOn, + }, + 0x0021 => { #PH + Name => 'FaceDetect', + SubDirectory => { TagTable => 'Image::ExifTool::Nikon::FaceDetect' }, + }, + 0x0022 => { #21 + Name => 'ActiveD-Lighting', + Writable => 'int16u', + PrintConv => { + 0 => 'Off', + 1 => 'Low', + 3 => 'Normal', + 5 => 'High', + 7 => 'Extra High', #10 + 8 => 'Extra High 1', #PH + 9 => 'Extra High 2', #PH + 10 => 'Extra High 3', #PH + 11 => 'Extra High 4', #PH + 0xffff => 'Auto', #10 + }, + }, + 0x0023 => [ + { #PH (D300, but also found in D3,D3S,D3X,D90,D300S,D700,D3000,D5000) + Name => 'PictureControlData', + Condition => '$$valPt =~ /^01/', + Writable => 'undef', + Permanent => 0, + Flags => [ 'Binary', 'Protected' ], + SubDirectory => { TagTable => 'Image::ExifTool::Nikon::PictureControl' }, + },{ #28 + Name => 'PictureControlData', + Condition => '$$valPt =~ /^02/', + Writable => 'undef', + Permanent => 0, + Flags => [ 'Binary', 'Protected' ], + SubDirectory => { TagTable => 'Image::ExifTool::Nikon::PictureControl2' }, + },{ + Name => 'PictureControlData', + Condition => '$$valPt =~ /^03/', + Writable => 'undef', + Permanent => 0, + Flags => [ 'Binary', 'Protected' ], + SubDirectory => { TagTable => 'Image::ExifTool::Nikon::PictureControl3' }, + },{ + Name => 'PictureControlData', + Writable => 'undef', + Permanent => 0, + Flags => [ 'Binary', 'Protected' ], + SubDirectory => { TagTable => 'Image::ExifTool::Nikon::PictureControlUnknown' }, + }, + ], + 0x0024 => { #JD + Name => 'WorldTime', + SubDirectory => { + TagTable => 'Image::ExifTool::Nikon::WorldTime', + # (CaptureNX does flip the byte order of this record) + }, + }, + 0x0025 => { #PH + Name => 'ISOInfo', + SubDirectory => { + TagTable => 'Image::ExifTool::Nikon::ISOInfo', + ByteOrder => 'BigEndian', + }, + }, + 0x002a => { #23 (this tag added with D3 firmware 1.10 -- also written by Nikon utilities) + Name => 'VignetteControl', + Writable => 'int16u', + PrintConv => { + 0 => 'Off', + 1 => 'Low', + 3 => 'Normal', + 5 => 'High', + }, + }, + 0x002b => { #PH + Name => 'DistortInfo', + SubDirectory => { + TagTable => 'Image::ExifTool::Nikon::DistortInfo', + }, + }, + 0x002c => { #29 (D7000) + Name => 'UnknownInfo', + SubDirectory => { + TagTable => 'Image::ExifTool::Nikon::UnknownInfo', + ByteOrder => 'BigEndian', #(NC) + }, + }, + # 0x2d - "512 0 0","512 3 10","512 1 14",... + 0x0032 => { #PH + Name => 'UnknownInfo2', + SubDirectory => { + TagTable => 'Image::ExifTool::Nikon::UnknownInfo2', + ByteOrder => 'BigEndian', #(NC) + }, + }, + 0x0034 => { #forum9646 + Name => 'ShutterMode', + Writable => 'int16u', + PrintConv => { + 0 => 'Mechanical', + 16 => 'Electronic', + # 33 => ? seen for 1J2 + 48 => 'Electronic Front Curtain', + }, + }, + 0x0035 => { #32 + Name => 'HDRInfo', + SubDirectory => { TagTable => 'Image::ExifTool::Nikon::HDRInfo' }, + }, + 0x0037 => { #XavierJubier + Name => 'MechanicalShutterCount', + Writable => 'int32u', + }, + 0x0039 => { + Name => 'LocationInfo', + SubDirectory => { TagTable => 'Image::ExifTool::Nikon::LocationInfo' }, + }, + 0x003d => { #IB + Name => 'BlackLevel', + Writable => 'int16u', + Count => 4, + # (may need to divide by 4 for some images, eg. D3300/D5300, 12 bit - ref IB) + }, + 0x004f => { #IB (D850) + Name => 'ColorTemperatureAuto', + Writable => 'int16u', + }, + 0x0080 => { Name => 'ImageAdjustment', Writable => 'string' }, + 0x0081 => { Name => 'ToneComp', Writable => 'string' }, #2 + 0x0082 => { Name => 'AuxiliaryLens', Writable => 'string' }, + 0x0083 => { + Name => 'LensType', + Writable => 'int8u', + # credit to Tom Christiansen (ref 7) for figuring this out... + PrintConv => q[$_ = $val ? Image::ExifTool::DecodeBits($val, + { + 0 => 'MF', + 1 => 'D', + 2 => 'G', + 3 => 'VR', + 4 => '1', #PH + # bit 5 set for FT-1 adapter? - PH + 6 => 'E', #PH (electromagnetic aperture mechanism) + # bit 7 set for AF-P lenses? - PH + }) : 'AF'; + # remove commas and change "D G" to just "G" + s/,//g; s/\bD G\b/G/; + s/ E\b// and s/^(G )?/E /; # put "E" at the start instead of "G" + s/ 1// and $_ = "1 $_"; # put "1" at start + return $_; + ], + PrintConvInv => q[ + my $bits = 0; + $bits |= 0x01 if $val =~ /\bMF\b/i; # bit 0 + $bits |= 0x02 if $val =~ /\bD\b/i; # bit 1 + $bits |= 0x06 if $val =~ /\bG\b/i; # bits 1 and 2 + $bits |= 0x08 if $val =~ /\bVR\b/i; # bit 3 + $bits |= 0x10 if $val =~ /\b1\b/; # bit 4 + $bits |= 0x46 if $val =~ /\bE\b/i; # bits 1, 2 and 6 + return $bits; + ], + }, + 0x0084 => { #2 + Name => "Lens", + Writable => 'rational64u', + Count => 4, + # short focal, long focal, aperture at short focal, aperture at long focal + PrintConv => \&Image::ExifTool::Exif::PrintLensInfo, + PrintConvInv => \&Image::ExifTool::Exif::ConvertLensInfo, + }, + 0x0085 => { + Name => 'ManualFocusDistance', + Writable => 'rational64u', + }, + 0x0086 => { + Name => 'DigitalZoom', + Writable => 'rational64u', + }, + 0x0087 => { #5 + Name => 'FlashMode', + Writable => 'int8u', + PrintConv => { + 0 => 'Did Not Fire', + 1 => 'Fired, Manual', #14 + 3 => 'Not Ready', #28 + 7 => 'Fired, External', #14 + 8 => 'Fired, Commander Mode', + 9 => 'Fired, TTL Mode', + }, + }, + 0x0088 => [ + { + Name => 'AFInfo', + Condition => '$$self{Model} =~ /^NIKON D/i', + SubDirectory => { + TagTable => 'Image::ExifTool::Nikon::AFInfo', + ByteOrder => 'BigEndian', + }, + }, + { + Name => 'AFInfo', + SubDirectory => { + TagTable => 'Image::ExifTool::Nikon::AFInfo', + ByteOrder => 'LittleEndian', + }, + }, + ], + 0x0089 => { #5 + Name => 'ShootingMode', + Writable => 'int16u', + # the meaning of bit 5 seems to change: For the D200 it indicates "Auto ISO" - PH + Notes => 'for the D70, Bit 5 = Unused LE-NR Slowdown', + # credit to Tom Christiansen (ref 7) for figuring this out... + # The (new?) bit 5 seriously complicates our life here: after firmwareB's + # 1.03, bit 5 turns on when you ask for BUT DO NOT USE the long-range + # noise reduction feature, probably because even not using it, it still + # slows down your drive operation to 50% (1.5fps max not 3fps). But no + # longer does !$val alone indicate single-frame operation. - TC, D70 + # The following comments are from Warren Hatch: + # Bits 4,6,8 indicate bracketing mode. + # - all 0's => Bracketing Off + # - bit 4 on with bits 6,8 off => Exposure Bracketing On + # - bits 4,6 on => WB bracketing On + # - 4,8 on => ADL Bracketing On + # Bit 2 gives tethered status: Off=>Not Tethered; On=Tethered. + # - that this simply indicates a camera is connected via a cord to a PC + # (doesn't necessarily mean that the shutter was tripped by the computer) + # Bits 0,1,3,7,9 relate to how the shutter is tripped in concert with the + # Release Mode dial [although I cannot cause bit 7 to flip with any of my gear and + # I suspect it is no longer used for the D500]. Regardless, the ReleaseMode tag + # offers a superior decoding of this information for the D4s, D810 and D500. + # Bit 5 indicates whether or not AutoISO is enabled. + PrintConv => q[ + $_ = ''; + unless ($val & 0x87) { + return 'Single-Frame' unless $val; + $_ = 'Single-Frame, '; + } + return $_ . Image::ExifTool::DecodeBits($val, + { + 0 => 'Continuous', + 1 => 'Delay', + 2 => 'PC Control', + 3 => 'Self-timer', #forum6281 (NC) + 4 => 'Exposure Bracketing', + 5 => $$self{Model}=~/D70\b/ ? 'Unused LE-NR Slowdown' : 'Auto ISO', + 6 => 'White-Balance Bracketing', + 7 => 'IR Control', + 8 => 'D-Lighting Bracketing', #forum6281 (NC) + }); + ], + }, + # 0x008a - called "AutoBracketRelease" by ref 15 [but this seems wrong] + # values: 0,255 (when writing NEF only), or 1,2 (when writing JPEG or JPEG+NEF) + # --> makes odd, repeating pattern in sequential NEF images (ref 28) + 0x008b => { #8 + Name => 'LensFStops', + ValueConv => 'my ($a,$b,$c)=unpack("C3",$val); $c ? $a*($b/$c) : 0', + ValueConvInv => 'my $a=int($val*12+0.5);$a<256 ? pack("C4",$a,1,12,0) : undef', + PrintConv => 'sprintf("%.2f", $val)', + PrintConvInv => '$val', + Writable => 'undef', + Count => 4, + }, + 0x008c => { + Name => 'ContrastCurve', #JD + Writable => 'undef', + Flags => [ 'Binary', 'Protected' ], + }, + # ColorHue: MODE1/MODE1a=sRGB, MODE2=Adobe RGB, MODE3a=more saturated sRGB + # --> should really be called ColorSpace or ColorMode, but that would conflict with other tags + 0x008d => { Name => 'ColorHue' , Writable => 'string' }, #2 + # SceneMode takes on the following values: PORTRAIT, PARTY/INDOOR, NIGHT PORTRAIT, + # BEACH/SNOW, LANDSCAPE, SUNSET, NIGHT SCENE, MUSEUM, FIREWORKS, CLOSE UP, COPY, + # BACK LIGHT, PANORAMA ASSIST, SPORT, DAWN/DUSK + 0x008f => { Name => 'SceneMode', Writable => 'string' }, #2 + # LightSource shows 3 values COLORED SPEEDLIGHT NATURAL. + # (SPEEDLIGHT when flash goes. Have no idea about difference between other two.) + 0x0090 => { Name => 'LightSource', Writable => 'string' }, #2 + 0x0091 => [ #18 + { #PH + Condition => '$$valPt =~ /^0209/', + Name => 'ShotInfoD40', + SubDirectory => { + TagTable => 'Image::ExifTool::Nikon::ShotInfoD40', + DecryptStart => 4, + DecryptLen => 748, + ByteOrder => 'BigEndian', + }, + }, + { + Condition => '$$valPt =~ /^0208/', + Name => 'ShotInfoD80', + SubDirectory => { + TagTable => 'Image::ExifTool::Nikon::ShotInfoD80', + DecryptStart => 4, + DecryptLen => 765, + # (Capture NX can change the makernote byte order, but this stays big-endian) + ByteOrder => 'BigEndian', + }, + }, + { #PH (D90, firmware 1.00) + Condition => '$$valPt =~ /^0213/', + Name => 'ShotInfoD90', + SubDirectory => { + TagTable => 'Image::ExifTool::Nikon::ShotInfoD90', + DecryptStart => 4, + DecryptLen => 0x398, + ByteOrder => 'BigEndian', + }, + }, + { #PH (D3, firmware 0.37 and 1.00) + Condition => '$$valPt =~ /^0210/ and $count == 5399', + Name => 'ShotInfoD3a', + SubDirectory => { + TagTable => 'Image::ExifTool::Nikon::ShotInfoD3a', + DecryptStart => 4, + DecryptLen => 0x318, + ByteOrder => 'BigEndian', + }, + }, + { #PH (D3, firmware 1.10, 2.00 and 2.01 [count 5408], and 2.02 [count 5412]) + Condition => '$$valPt =~ /^0210/ and ($count == 5408 or $count == 5412)', + Name => 'ShotInfoD3b', + SubDirectory => { + TagTable => 'Image::ExifTool::Nikon::ShotInfoD3b', + DecryptStart => 4, + DecryptLen => 0x321, + ByteOrder => 'BigEndian', + }, + }, + { #PH (D3X, firmware 1.00) + Condition => '$$valPt =~ /^0214/ and $count == 5409', + Name => 'ShotInfoD3X', + SubDirectory => { + TagTable => 'Image::ExifTool::Nikon::ShotInfoD3X', + DecryptStart => 4, + DecryptLen => 0x323, + ByteOrder => 'BigEndian', + }, + }, + { #PH (D3S, firmware 0.16 and 1.00) + Condition => '$$valPt =~ /^0218/ and ($count == 5356 or $count == 5388)', + Name => 'ShotInfoD3S', + SubDirectory => { + TagTable => 'Image::ExifTool::Nikon::ShotInfoD3S', + DecryptStart => 4, + DecryptLen => 0x2e9, + ByteOrder => 'BigEndian', + }, + }, + { #JD (D300, firmware 0.25 and 1.00) + # D3 and D300 use the same version number, but the length is different + Condition => '$$valPt =~ /^0210/ and $count == 5291', + Name => 'ShotInfoD300a', + SubDirectory => { + TagTable => 'Image::ExifTool::Nikon::ShotInfoD300a', + DecryptStart => 4, + DecryptLen => 813, + ByteOrder => 'BigEndian', + }, + }, + { #PH (D300, firmware version 1.10) + # yet again the same ShotInfoVersion for different data + Condition => '$$valPt =~ /^0210/ and $count == 5303', + Name => 'ShotInfoD300b', + SubDirectory => { + TagTable => 'Image::ExifTool::Nikon::ShotInfoD300b', + DecryptStart => 4, + DecryptLen => 825, + ByteOrder => 'BigEndian', + }, + }, + { #PH (D300S, firmware version 1.00) + # yet again the same ShotInfoVersion for different data + Condition => '$$valPt =~ /^0216/ and $count == 5311', + Name => 'ShotInfoD300S', + SubDirectory => { + TagTable => 'Image::ExifTool::Nikon::ShotInfoD300S', + DecryptStart => 4, + DecryptLen => 827, + ByteOrder => 'BigEndian', + }, + }, + # 0225 - D600 + { #29 (D700 firmware version 1.02f) + Condition => '$$valPt =~ /^0212/ and $count == 5312', + Name => 'ShotInfoD700', + SubDirectory => { + TagTable => 'Image::ExifTool::Nikon::ShotInfoD700', + DecryptStart => 4, + DecryptLen => 0x358, + ByteOrder => 'BigEndian', + }, + }, + { #PH (D800 firmware 1.01a) + Condition => '$$valPt =~ /^0222/', + Name => 'ShotInfoD800', + SubDirectory => { + TagTable => 'Image::ExifTool::Nikon::ShotInfoD800', + DecryptStart => 4, + DecryptLen => 0x720, + ByteOrder => 'BigEndian', + }, + }, + { #28 (D810 firmware 1.01) + Condition => '$$valPt =~ /^0233/', + Name => 'ShotInfoD810', + SubDirectory => { + TagTable => 'Image::ExifTool::Nikon::ShotInfoD810', + DecryptStart => 4, + DecryptLen => 0x36f4 + 12, + DecryptMore => 'Get32u(\$data, 0x84) + 12', + ByteOrder => 'LittleEndian', + }, + }, + { #28 (D850 firmware 1.00b) + Condition => '$$valPt =~ /^0243/', + Name => 'ShotInfoD850', + SubDirectory => { + TagTable => 'Image::ExifTool::Nikon::ShotInfoD850', + DecryptStart => 4, + # initially only decrypt enough to extract CustomSettingsOffset + DecryptLen => 0x58, + # then decrypt through to the end of the custom settings + DecryptMore => 'Get32u(\$data, 0x58) + 90 + 4', + ByteOrder => 'LittleEndian', + }, + }, + # 0217 - D3000 + # 0219 - D3100 + # 0224 - D3200 + { #PH + Condition => '$$valPt =~ /^0215/ and $count == 6745', + Name => 'ShotInfoD5000', + SubDirectory => { + TagTable => 'Image::ExifTool::Nikon::ShotInfoD5000', + DecryptStart => 4, + DecryptLen => 0x39a, + ByteOrder => 'BigEndian', + }, + }, + { #PH + Condition => '$$valPt =~ /^0221/ and $count == 8902', + Name => 'ShotInfoD5100', + SubDirectory => { + TagTable => 'Image::ExifTool::Nikon::ShotInfoD5100', + DecryptStart => 4, + DecryptLen => 0x430, + ByteOrder => 'BigEndian', + }, + }, + { #PH + Condition => '$$valPt =~ /^0226/ and $count == 11587', + Name => 'ShotInfoD5200', + SubDirectory => { + TagTable => 'Image::ExifTool::Nikon::ShotInfoD5200', + DecryptStart => 4, + DecryptLen => 0xd00, + ByteOrder => 'BigEndian', + }, + }, + { #29 (D7000 firmware version 1.01b) + Condition => '$$valPt =~ /^0220/', + Name => 'ShotInfoD7000', + SubDirectory => { + TagTable => 'Image::ExifTool::Nikon::ShotInfoD7000', + DecryptStart => 4, + DecryptLen => 0x448, + ByteOrder => 'BigEndian', + }, + }, + { # (D4 firmware version 1.00g) + Condition => '$$valPt =~ /^0223/', + Name => 'ShotInfoD4', + SubDirectory => { + TagTable => 'Image::ExifTool::Nikon::ShotInfoD4', + DecryptStart => 4, + DecryptLen => 0x789, + ByteOrder => 'BigEndian', + }, + }, + { # (D4S firmware version 1.00d and 1.01a) + Condition => '$$valPt =~ /^0231/', + Name => 'ShotInfoD4S', + SubDirectory => { + TagTable => 'Image::ExifTool::Nikon::ShotInfoD4S', + DecryptStart => 4, + DecryptLen => 0x3697, + ByteOrder => 'LittleEndian', + }, + }, + { #28 (D5 firmware version 1.10a) + Condition => '$$valPt =~ /^0238/', + Name => 'ShotInfoD5', + SubDirectory => { + TagTable => 'Image::ExifTool::Nikon::ShotInfoD500', + DecryptStart => 4, + DecryptLen => 0x2c24 + 12, + DecryptMore => 'Get32u(\$data, 0xa0) + 12', + ByteOrder => 'LittleEndian', + }, + }, + { # (D500 firmware version 1.00) + Condition => '$$valPt =~ /^0239/', + Name => 'ShotInfoD500', + SubDirectory => { + TagTable => 'Image::ExifTool::Nikon::ShotInfoD500', + DecryptStart => 4, + DecryptLen => 0x2cb2 + 4, + DecryptMore => 'Get32u(\$data, 0xa0) + 12', + ByteOrder => 'LittleEndian', + }, + }, + { # (D610 firmware version 1.00) + Condition => '$$valPt =~ /^0232/', + Name => 'ShotInfoD610', + SubDirectory => { + TagTable => 'Image::ExifTool::Nikon::ShotInfoD610', + DecryptStart => 4, + DecryptLen => 0x7ff, + ByteOrder => 'BigEndian', + }, + }, + { # D7100=0227, Z6/Z7=0800 + Condition => '$$valPt =~ /^0[28]/', + Name => 'ShotInfo02xx', + SubDirectory => { + TagTable => 'Image::ExifTool::Nikon::ShotInfo', + ProcessProc => \&Image::ExifTool::Nikon::ProcessNikonEncrypted, + WriteProc => \&Image::ExifTool::Nikon::ProcessNikonEncrypted, + DecryptStart => 4, + DecryptLen => 0x251, + ByteOrder => 'BigEndian', + }, + }, + { + Name => 'ShotInfoUnknown', + Writable => 0, + SubDirectory => { + TagTable => 'Image::ExifTool::Nikon::ShotInfo', + ByteOrder => 'BigEndian', + }, + }, + ], + 0x0092 => { #2 + Name => 'HueAdjustment', + Writable => 'int16s', + }, + # 0x0093 - ref 15 calls this Saturation, but this is wrong - PH + 0x0093 => { #21 + Name => 'NEFCompression', + Writable => 'int16u', + PrintConv => { + 1 => 'Lossy (type 1)', # (older models) + 2 => 'Uncompressed', #JD - D100 (even though TIFF compression is set!) + 3 => 'Lossless', + 4 => 'Lossy (type 2)', + 5 => 'Striped packed 12 bits', #IB + 6 => 'Uncompressed (reduced to 12 bit)', #IB + 7 => 'Unpacked 12 bits', #IB (padded to 16) + 8 => 'Small', #IB + 9 => 'Packed 12 bits', #IB (2 pixels in 3 bytes) + }, + }, + 0x0094 => { Name => 'Saturation', Writable => 'int16s' }, + 0x0095 => { Name => 'NoiseReduction', Writable => 'string' }, # ("Off" or "FPNR"=long exposure NR) + 0x0096 => { + Name => 'NEFLinearizationTable', # same table as DNG LinearizationTable (ref JD) + Writable => 'undef', + Flags => [ 'Binary', 'Protected' ], + }, + 0x0097 => [ #4 + # (NOTE: these are byte-swapped by NX when byte order changes) + { + Condition => '$$valPt =~ /^0100/', # (D100 and Coolpix models) + Name => 'ColorBalance0100', + SubDirectory => { + Start => '$valuePtr + 72', + TagTable => 'Image::ExifTool::Nikon::ColorBalance1', + }, + }, + { + Condition => '$$valPt =~ /^0102/', # (D2H) + Name => 'ColorBalance0102', + SubDirectory => { + Start => '$valuePtr + 10', + TagTable => 'Image::ExifTool::Nikon::ColorBalance2', + }, + }, + { + Condition => '$$valPt =~ /^0103/', # (D70/D70s) + Name => 'ColorBalance0103', + # D70: at file offset 'tag-value + base + 20', 4 16 bits numbers, + # v[0]/v[1] , v[2]/v[3] are the red/blue multipliers. + SubDirectory => { + Start => '$valuePtr + 20', + TagTable => 'Image::ExifTool::Nikon::ColorBalance3', + }, + }, + { + Condition => '$$valPt =~ /^0205/', # (D50) + Name => 'ColorBalance0205', + SubDirectory => { + TagTable => 'Image::ExifTool::Nikon::ColorBalance2', + ProcessProc => \&Image::ExifTool::Nikon::ProcessNikonEncrypted, + WriteProc => \&Image::ExifTool::Nikon::ProcessNikonEncrypted, + DecryptStart => 4, + DecryptLen => 22, # 284 bytes encrypted, but don't need to decrypt it all + DirOffset => 14, + }, + }, + { # (D3/D3X/D300/D700=0209,D300S=0212,D3S=0214) + Condition => '$$valPt =~ /^02(09|12|14)/', + Name => 'ColorBalance0209', + SubDirectory => { + TagTable => 'Image::ExifTool::Nikon::ColorBalance4', + ProcessProc => \&Image::ExifTool::Nikon::ProcessNikonEncrypted, + WriteProc => \&Image::ExifTool::Nikon::ProcessNikonEncrypted, + DecryptStart => 284, + DecryptLen => 18, # 324 bytes encrypted, but don't need to decrypt it all + DirOffset => 10, + }, + }, + { # (D2X/D2Xs=0204,D2Hs=0206,D200=0207,D40/D40X/D80=0208,D60=0210) + Condition => '$$valPt =~ /^02(\d{2})/ and $1 < 11', + Name => 'ColorBalance02', + SubDirectory => { + TagTable => 'Image::ExifTool::Nikon::ColorBalance2', + ProcessProc => \&Image::ExifTool::Nikon::ProcessNikonEncrypted, + WriteProc => \&Image::ExifTool::Nikon::ProcessNikonEncrypted, + DecryptStart => 284, + DecryptLen => 14, # don't need to decrypt it all + DirOffset => 6, + }, + }, + { + Condition => '$$valPt =~ /^0211/', # (D90/D5000) + Name => 'ColorBalance0211', + SubDirectory => { + TagTable => 'Image::ExifTool::Nikon::ColorBalance4', + ProcessProc => \&Image::ExifTool::Nikon::ProcessNikonEncrypted, + WriteProc => \&Image::ExifTool::Nikon::ProcessNikonEncrypted, + DecryptStart => 284, + DecryptLen => 24, # don't need to decrypt it all + DirOffset => 16, + }, + }, + { + Condition => '$$valPt =~ /^0213/', # (D3000) + Name => 'ColorBalance0213', + SubDirectory => { + TagTable => 'Image::ExifTool::Nikon::ColorBalance2', + ProcessProc => \&Image::ExifTool::Nikon::ProcessNikonEncrypted, + WriteProc => \&Image::ExifTool::Nikon::ProcessNikonEncrypted, + DecryptStart => 284, + DecryptLen => 18, # don't need to decrypt it all + DirOffset => 10, + }, + }, + { # (D3100=0215,D7000/D5100=0216,D4/D800/D3200=0217) + Condition => '$$valPt =~ /^021[567]/', + Name => 'ColorBalance0215', + SubDirectory => { + TagTable => 'Image::ExifTool::Nikon::ColorBalance4', + ProcessProc => \&Image::ExifTool::Nikon::ProcessNikonEncrypted, + WriteProc => \&Image::ExifTool::Nikon::ProcessNikonEncrypted, + DecryptStart => 284, + DecryptLen => 12, # don't need to decrypt it all + DirOffset => 4, + }, + }, + { # (D5200/D7100=0218, D5300=0219, D610/Df=0220, D3300=0221, CoolpixA=0601) + Name => 'ColorBalanceUnknown02', + Condition => '$$valPt =~ /^0[26]/', + SubDirectory => { + TagTable => 'Image::ExifTool::Nikon::ColorBalanceUnknown', + ProcessProc => \&Image::ExifTool::Nikon::ProcessNikonEncrypted, + DecryptStart => 284, + DecryptLen => 10, # (arbitrary) + }, + }, + { # (1J1/1J2/1V1=0400, 1V2=0401, 1J3/1S1=0402, 1AW1=0403, Z6/Z7=0800) + Name => 'ColorBalanceUnknown04', + Condition => '$$valPt =~ /^0[48]/', + SubDirectory => { + TagTable => 'Image::ExifTool::Nikon::ColorBalanceUnknown', + ProcessProc => \&Image::ExifTool::Nikon::ProcessNikonEncrypted, + DecryptStart => 4, + DecryptLen => 10, # (arbitrary) + }, + }, + { + # (CoolpixP7700/P7800=0500, CoolpixP330/P520=0502) + Name => 'ColorBalanceUnknown', + SubDirectory => { TagTable => 'Image::ExifTool::Nikon::ColorBalanceUnknown' }, + }, + ], + 0x0098 => [ + { #8 + Condition => '$$valPt =~ /^0100/', # D100, D1X - PH + Name => 'LensData0100', + SubDirectory => { TagTable => 'Image::ExifTool::Nikon::LensData00' }, + }, + { #8 + Condition => '$$valPt =~ /^0101/', # D70, D70s - PH + Name => 'LensData0101', + SubDirectory => { TagTable => 'Image::ExifTool::Nikon::LensData01' }, + }, + # note: this information is encrypted if the version is 02xx + { #8 + # 0201 - D200, D2Hs, D2X and D2Xs + # 0202 - D40, D40X and D80 + # 0203 - D300 + Condition => '$$valPt =~ /^020[1-3]/', + Name => 'LensData0201', + SubDirectory => { + TagTable => 'Image::ExifTool::Nikon::LensData01', + ProcessProc => \&Image::ExifTool::Nikon::ProcessNikonEncrypted, + WriteProc => \&Image::ExifTool::Nikon::ProcessNikonEncrypted, + DecryptStart => 4, + }, + }, + { #PH + Condition => '$$valPt =~ /^0204/', # D90, D7000 + Name => 'LensData0204', + SubDirectory => { + TagTable => 'Image::ExifTool::Nikon::LensData0204', + ProcessProc => \&Image::ExifTool::Nikon::ProcessNikonEncrypted, + WriteProc => \&Image::ExifTool::Nikon::ProcessNikonEncrypted, + DecryptStart => 4, + }, + }, + { + Condition => '$$valPt =~ /^040[01]/', # 0=1J1/1V1, 1=1J2 + Name => 'LensData0400', + SubDirectory => { + TagTable => 'Image::ExifTool::Nikon::LensData0400', + ProcessProc => \&Image::ExifTool::Nikon::ProcessNikonEncrypted, + WriteProc => \&Image::ExifTool::Nikon::ProcessNikonEncrypted, + DecryptStart => 4, + }, + }, + { + Condition => '$$valPt =~ /^0402/', # 1J3/1S1/1V2 + Name => 'LensData0402', + SubDirectory => { + TagTable => 'Image::ExifTool::Nikon::LensData0402', + ProcessProc => \&Image::ExifTool::Nikon::ProcessNikonEncrypted, + WriteProc => \&Image::ExifTool::Nikon::ProcessNikonEncrypted, + DecryptStart => 4, + }, + }, + { + Condition => '$$valPt =~ /^0403/', # 1J4,1J5 + Name => 'LensData0403', + SubDirectory => { + TagTable => 'Image::ExifTool::Nikon::LensData0403', + ProcessProc => \&Image::ExifTool::Nikon::ProcessNikonEncrypted, + WriteProc => \&Image::ExifTool::Nikon::ProcessNikonEncrypted, + DecryptStart => 4, + }, + }, + { + Condition => '$$valPt =~ /^0800/', # Z6/Z7 + Name => 'LensData0800', + SubDirectory => { + TagTable => 'Image::ExifTool::Nikon::LensData0800', + ProcessProc => \&Image::ExifTool::Nikon::ProcessNikonEncrypted, + WriteProc => \&Image::ExifTool::Nikon::ProcessNikonEncrypted, + DecryptStart => 4, + ByteOrder => 'LittleEndian', + }, + }, + { + Name => 'LensDataUnknown', + SubDirectory => { + TagTable => 'Image::ExifTool::Nikon::LensDataUnknown', + ProcessProc => \&Image::ExifTool::Nikon::ProcessNikonEncrypted, + WriteProc => \&Image::ExifTool::Nikon::ProcessNikonEncrypted, + DecryptStart => 4, + }, + }, + ], + 0x0099 => { #2/15 + Name => 'RawImageCenter', + Writable => 'int16u', + Count => 2, + }, + 0x009a => { #10 + Name => 'SensorPixelSize', + Writable => 'rational64u', + Count => 2, + PrintConv => '$val=~s/ / x /;"$val um"', + PrintConvInv => '$val=~tr/a-zA-Z/ /;$val', + }, + 0x009c => { #14 + # L2/L3 has these modes (from owner's manual): - PH + # Portrait Assist: FACE-PRIORITY AF,PORTRAIT,PORTRAIT LEFT,PORTRAIT RIGHT, + # PORTRAIT CLOSE-UP,PORTRAIT COUPLE,PORTRAIT-FIGURE + # Landscape Assist:LANDSCAPE,SCENIC VIEW,ARCHITECTURE,GROUP RIGHT,GROUP LEFT + # Sports Assist: SPORTS,SPORT SPECTATOR,SPORT COMPOSITE + # P7100 has test modes: - PH + # CREATIVE MONOCHROME,PAINTING,CROSS PROCESS,SOFT,NOSTALGIC SEPIA, + # HIGH KEY,LOW KEY,SELECTIVE COLOR,ZOOM EXPOSURE EXP.,DEFOCUS DURING + Name => 'SceneAssist', + Writable => 'string', + }, + 0x009e => { #JD + Name => 'RetouchHistory', + Writable => 'int16u', + Count => 10, + # trim off extra "None" values + ValueConv => '$val=~s/( 0)+$//; $val', + ValueConvInv => 'my $n=($val=~/ \d+/g);$n < 9 ? $val . " 0" x (9-$n) : $val', + PrintConvColumns => 2, + PrintConv => [ + \%retouchValues, + \%retouchValues, + \%retouchValues, + \%retouchValues, + \%retouchValues, + \%retouchValues, + \%retouchValues, + \%retouchValues, + \%retouchValues, + \%retouchValues, + ], + }, + 0x00a0 => { Name => 'SerialNumber', Writable => 'string' }, #2 + 0x00a2 => { # size of compressed image data plus EOI segment (ref 10) + Name => 'ImageDataSize', + Writable => 'int32u', + }, + # 0x00a3 - int8u: 0 (All DSLR's but D1,D1H,D1X,D100) + # 0x00a4 - version number found only in NEF images from DSLR models except the + # D1,D1X,D2H and D100. Value is "0200" for all available samples except images + # edited by Nikon Capture Editor 4.3.1 W and 4.4.2 which have "0100" - PH + 0x00a5 => { #15 + Name => 'ImageCount', + Writable => 'int32u', + }, + 0x00a6 => { #15 + Name => 'DeletedImageCount', + Writable => 'int32u', + }, + # the sum of 0xa5 and 0xa6 is equal to 0xa7 ShutterCount (D2X,D2Hs,D2H,D200, ref 10) + 0x00a7 => { # Number of shots taken by camera so far (ref 2) + Name => 'ShutterCount', + Writable => 'int32u', + Protected => 1, + PrintConv => '$val == 4294965247 ? "n/a" : $val', + PrintConvInv => '$val eq "n/a" ? 4294965247 : $val', + Notes => q{ + includes both mechanical and electronic shutter activations for models with + this feature. This value is used as a key to decrypt other information, and + writing this tag causes the other information to be re-encrypted with the + new key + }, + }, + 0x00a8 => [#JD + { + Name => 'FlashInfo0100', + Condition => '$$valPt =~ /^010[01]/', + SubDirectory => { TagTable => 'Image::ExifTool::Nikon::FlashInfo0100' }, + }, + { + Name => 'FlashInfo0102', + Condition => '$$valPt =~ /^0102/', + SubDirectory => { TagTable => 'Image::ExifTool::Nikon::FlashInfo0102' }, + }, + { + Name => 'FlashInfo0103', + # (0104 for D7000, 0105 for D800) + Condition => '$$valPt =~ /^010[345]/', + SubDirectory => { TagTable => 'Image::ExifTool::Nikon::FlashInfo0103' }, + }, + { + Name => 'FlashInfo0106', # (Df, D610, D3300, D5300, D7100, Coolpix A) + Condition => '$$valPt =~ /^0106/', + SubDirectory => { TagTable => 'Image::ExifTool::Nikon::FlashInfo0106' }, + }, + { + Name => 'FlashInfo0107', # (0107 for D4S/D750/D810/D5500/D7200, 0108 for D5/D500/D3400) + Condition => '$$valPt =~ /^010[78]/', + SubDirectory => { TagTable => 'Image::ExifTool::Nikon::FlashInfo0107' }, + }, + { + Name => 'FlashInfoUnknown', + SubDirectory => { TagTable => 'Image::ExifTool::Nikon::FlashInfoUnknown' }, + }, + ], + 0x00a9 => { Name => 'ImageOptimization',Writable => 'string' },#2 + 0x00aa => { Name => 'Saturation', Writable => 'string' }, #2 + 0x00ab => { Name => 'VariProgram', Writable => 'string' }, #2 (scene mode for DSLR's - PH) + 0x00ac => { Name => 'ImageStabilization',Writable=> 'string' }, #14 + 0x00ad => { Name => 'AFResponse', Writable => 'string' }, #14 + 0x00b0 => [{ #PH + Name => 'MultiExposure', + Condition => '$$valPt =~ /^0100/', + SubDirectory => { + TagTable => 'Image::ExifTool::Nikon::MultiExposure', + # Note: this endianness varies with model, but Nikon software may change + # metadata endianness (although it is unknown how it affects this record), + # so for now don't specify ByteOrder although it may be wrong if the + # file is rewritten by Nikon software --> see comments for FileInfo + }, + },{ + Name => 'MultiExposure', + Condition => '$$valPt =~ /^0101/', + SubDirectory => { + TagTable => 'Image::ExifTool::Nikon::MultiExposure', + ByteOrder => 'LittleEndian', + }, + }], + 0x00b1 => { #14/PH/JD (D80) + Name => 'HighISONoiseReduction', + Writable => 'int16u', + PrintConv => { + 0 => 'Off', + 1 => 'Minimal', # for high ISO (>800) when setting is "Off" + 2 => 'Low', # Low,Normal,High take effect for ISO > 400 + 3 => 'Medium Low', + 4 => 'Normal', + 5 => 'Medium High', + 6 => 'High', + }, + }, + # 0x00b2 (string: "NORMAL ", 0xc3's, 0xff's or 0x20's) + 0x00b3 => { #14 + Name => 'ToningEffect', + Writable => 'string', + }, + 0x00b6 => { #PH + Name => 'PowerUpTime', + Groups => { 2 => 'Time' }, + Shift => 'Time', + # not clear whether "powered up" means "turned on" or "power applied" - PH + Notes => 'date/time when camera was last powered up', + Writable => 'undef', + # must use RawConv so byte order is correct + RawConv => sub { + my $val = shift; + return $val if length $val < 7; + my $shrt = GetByteOrder() eq 'II' ? 'v' : 'n'; + my @date = unpack("${shrt}C5", $val); + return sprintf('%.4d:%.2d:%.2d %.2d:%.2d:%.2d', @date); + }, + RawConvInv => sub { + my $val = shift; + my $shrt = GetByteOrder() eq 'II' ? 'v' : 'n'; + my @date = ($val =~ /\d+/g); + return pack("${shrt}C6", @date, 0); + }, + PrintConv => '$self->ConvertDateTime($val)', + PrintConvInv => '$self->InverseDateTime($val,0)', + }, + 0x00b7 => { #JD + Name => 'AFInfo2', + # (this structure may be byte swapped when rewritten by CaptureNX) + SubDirectory => { TagTable => 'Image::ExifTool::Nikon::AFInfo2' }, + }, + 0x00b8 => [{ #PH + Name => 'FileInfo', + # unfortunately, some newer models write this as little-endian + # (and CaptureNX can change the byte order of the maker notes, + # but leaves this structure unchanged) + # - it will be an ongoing pain to keep this list of models up-to-date, + # so if only one ordering yields valid DirectoryNumber and FileNumber values, + # use it, otherwise default to a-priori knowledge of the camera model + # (assume that a valid DirectoryNumber is 100-999, and a valid FileNumber + # is 0000-9999, although I have some samples with a DirectoryNumber of 99) + Condition => q{ + if (length($$valPt) >= 0) { + my ($dir, $file) = unpack('x6vv', $$valPt); + my $littleEndian = ($dir >= 100 and $dir <= 999 and $file <= 9999); + ($dir, $file) = unpack('x6nn', $$valPt); + my $bigEndian = ($dir >= 100 and $dir <= 999 and $file <= 9999); + return $littleEndian if $littleEndian xor $bigEndian; + } + return $$self{Model} =~ /^NIKON (D4S|D750|D810|D3300|D5200|D5300|D5500|D7100)$/; + }, + SubDirectory => { + TagTable => 'Image::ExifTool::Nikon::FileInfo', + ByteOrder => 'LittleEndian', + }, + },{ + Name => 'FileInfo', + SubDirectory => { + TagTable => 'Image::ExifTool::Nikon::FileInfo', + ByteOrder => 'BigEndian', + }, + }], + 0x00b9 => { #28 + Name => 'AFTune', + SubDirectory => { TagTable => 'Image::ExifTool::Nikon::AFTune' }, + }, + # 0x00ba - custom curve data? (ref 28?) (only in NEF images) + 0x00bb => { #forum6281 + Name => 'RetouchInfo', + SubDirectory => { TagTable => 'Image::ExifTool::Nikon::RetouchInfo' }, + }, + # 0x00bc - NEFThumbnail? (forum6281) + 0x00bd => { #PH (P6000) + Name => 'PictureControlData', + Writable => 'undef', + Permanent => 0, + Flags => [ 'Binary', 'Protected' ], + SubDirectory => { TagTable => 'Image::ExifTool::Nikon::PictureControl' }, + }, + 0x00c3 => { + Name => 'BarometerInfo', + SubDirectory => { + TagTable => 'Image::ExifTool::Nikon::BarometerInfo', + # (little-endian in II EXIF, big-endian in MOV) + }, + }, + 0x0e00 => { + Name => 'PrintIM', + Description => 'Print Image Matching', + Writable => 0, + SubDirectory => { + TagTable => 'Image::ExifTool::PrintIM::Main', + }, + }, + # 0x0e01 - In D70 NEF files produced by Nikon Capture, the data for this tag extends 4 bytes + # past the end of the maker notes. Very odd. I hope these 4 bytes aren't useful because + # they will get lost by any utility that blindly copies the maker notes (not ExifTool) - PH + 0x0e01 => { + Name => 'NikonCaptureData', + Writable => 'undef', + Permanent => 0, + # (Drop because may be too large for JPEG images) + Flags => [ 'Binary', 'Protected', 'Drop' ], + Notes => q{ + this data is dropped when copying Nikon MakerNotes since it may be too large + to fit in the EXIF segment of a JPEG image, but it may be copied as a block + into existing Nikon MakerNotes later if desired + }, + SubDirectory => { + DirName => 'NikonCapture', + TagTable => 'Image::ExifTool::NikonCapture::Main', + }, + }, + # 0x0e05 written by Nikon Capture to NEF files, values of 1 and 2 - PH + 0x0e09 => { #12 + Name => 'NikonCaptureVersion', + Writable => 'string', + PrintConv => undef, + }, + # 0x0e0e is in D70 Nikon Capture files (not out-of-the-camera D70 files) - PH + 0x0e0e => { #PH + Name => 'NikonCaptureOffsets', + SubDirectory => { + TagTable => 'Image::ExifTool::Nikon::CaptureOffsets', + Validate => '$val =~ /^0100/', + Start => '$valuePtr + 4', + }, + }, + 0x0e10 => { #17 + Name => 'NikonScanIFD', + Groups => { 1 => 'NikonScan', 2 => 'Image' }, + Flags => 'SubIFD', + SubDirectory => { + TagTable => 'Image::ExifTool::Nikon::Scan', + Start => '$val', + }, + }, + 0x0e13 => [{ # PH/http://u88.n24.queensu.ca/exiftool/forum/index.php/topic,2737.0.html + Name => 'NikonCaptureEditVersions', + Condition => '$self->Options("ExtractEmbedded")', + Notes => q{ + the ExtractEmbedded option may be used to decode settings from the stored + edit versions, otherwise this is extracted as a binary data block + }, + Writable => 'undef', + Permanent => 0, + Drop => 1, # (may be too large for JPEG images) + SubDirectory => { + DirName => 'NikonCaptureEditVersions', + TagTable => 'Image::ExifTool::NikonCapture::Main', + ProcessProc => \&ProcessNikonCaptureEditVersions, + WriteProc => sub { return undef }, # (writing not yet supported) + }, + },{ + Name => 'NikonCaptureEditVersions', + Writable => 'undef', + Permanent => 0, + Flags => [ 'Binary', 'Protected', 'Drop' ], + }], + 0x0e1d => { #JD + Name => 'NikonICCProfile', + Flags => [ 'Binary', 'Protected' ], + Writable => 'undef', # must be defined here so tag will be extracted if specified + WriteCheck => q{ + require Image::ExifTool::ICC_Profile; + return Image::ExifTool::ICC_Profile::ValidateICC(\$val); + }, + SubDirectory => { + DirName => 'NikonICCProfile', + TagTable => 'Image::ExifTool::ICC_Profile::Main', + }, + }, + 0x0e1e => { #PH + Name => 'NikonCaptureOutput', + Writable => 'undef', + Permanent => 0, + Flags => [ 'Binary', 'Protected' ], + SubDirectory => { + TagTable => 'Image::ExifTool::Nikon::CaptureOutput', + Validate => '$val =~ /^0100/', + }, + }, + 0x0e22 => { #28 + Name => 'NEFBitDepth', + Writable => 'int16u', + Count => 4, + Protected => 1, + PrintConv => { + '0 0 0 0' => 'n/a (JPEG)', + '8 8 8 0' => '8 x 3', # TIFF RGB + '16 16 16 0' => '16 x 3', # TIFF 16-bit RGB + '12 0 0 0' => 12, + '14 0 0 0' => 14, + }, + }, +); + +# NikonScan IFD entries (ref 17) +%Image::ExifTool::Nikon::Scan = ( + WRITE_PROC => \&Image::ExifTool::Exif::WriteExif, + CHECK_PROC => \&Image::ExifTool::Exif::CheckExif, + WRITE_GROUP => 'NikonScan', + WRITABLE => 1, + GROUPS => { 0 => 'MakerNotes', 1 => 'NikonScan', 2 => 'Image' }, + VARS => { MINOR_ERRORS => 1 }, # this IFD is non-essential and often corrupted + NOTES => 'This information is written by the Nikon Scan software.', + 0x02 => { Name => 'FilmType', Writable => 'string', }, + 0x40 => { Name => 'MultiSample', Writable => 'string' }, + 0x41 => { Name => 'BitDepth', Writable => 'int16u' }, + 0x50 => { + Name => 'MasterGain', + Writable => 'rational64s', + PrintConv => 'sprintf("%.2f",$val)', + PrintConvInv => '$val', + }, + 0x51 => { + Name => 'ColorGain', + Writable => 'rational64s', + Count => 3, + PrintConv => 'sprintf("%.2f %.2f %.2f",split(" ",$val))', + PrintConvInv => '$val', + }, + 0x60 => { + Name => 'ScanImageEnhancer', + Writable => 'int32u', + PrintConv => \%offOn, + }, + 0x100 => { Name => 'DigitalICE', Writable => 'string' }, + 0x110 => { + Name => 'ROCInfo', + SubDirectory => { TagTable => 'Image::ExifTool::Nikon::ROC' }, + }, + 0x120 => { + Name => 'GEMInfo', + SubDirectory => { TagTable => 'Image::ExifTool::Nikon::GEM' }, + }, + 0x200 => { Name => 'DigitalDEEShadowAdj', Writable => 'int32u' }, + 0x201 => { Name => 'DigitalDEEThreshold', Writable => 'int32u' }, + 0x202 => { Name => 'DigitalDEEHighlightAdj',Writable => 'int32u' }, +); + +# ref 17 +%Image::ExifTool::Nikon::ROC = ( + %binaryDataAttrs, + FORMAT => 'int32u', + GROUPS => { 0 => 'MakerNotes', 1 => 'NikonScan', 2 => 'Image' }, + 0 => { + Name => 'DigitalROC', + ValueConv => '$val / 10', + ValueConvInv => 'int($val * 10)', + }, +); + +# ref 17 +%Image::ExifTool::Nikon::GEM = ( + %binaryDataAttrs, + FORMAT => 'int32u', + GROUPS => { 0 => 'MakerNotes', 1 => 'NikonScan', 2 => 'Image' }, + 0 => { + Name => 'DigitalGEM', + ValueConv => '$val<95 ? $val/20-1 : 4', + ValueConvInv => '$val == 4 ? 95 : int(($val + 1) * 20)', + }, +); + +# Vibration Reduction information - PH (D300) +%Image::ExifTool::Nikon::VRInfo = ( + %binaryDataAttrs, + GROUPS => { 0 => 'MakerNotes', 2 => 'Camera' }, + # NOTE: Must set ByteOrder in SubDirectory if any multi-byte integer tags added + 0 => { + Name => 'VRInfoVersion', + Format => 'undef[4]', + Writable => 0, + }, + 4 => { + Name => 'VibrationReduction', + PrintConv => { + 0 => 'n/a', # (1V1 with a non-VR lens) + 1 => 'On', + 2 => 'Off', + }, + }, + # 5 - values: 0, 1 (VR On), 2 (VR Off) + 6 => { + Name => 'VRMode', + PrintConv => { + 0 => 'Normal', # (Z7 gives this value for "off" - PH) + 1 => 'On (1)', #PH (NC) + 2 => 'Active', # (1J1) + 3 => 'Sport', #PH (Z7) + }, + }, + # 7 - values: 0, 1 +); + +# Face detection information - PH (S8100) +%Image::ExifTool::Nikon::FaceDetect = ( + %binaryDataAttrs, + GROUPS => { 0 => 'MakerNotes', 2 => 'Image' }, + FORMAT => 'int16u', + DATAMEMBER => [ 0x03 ], + 0x01 => { + Name => 'FaceDetectFrameSize', + Format => 'int16u[2]', + }, + 0x03 => { + Name => 'FacesDetected', + DataMember => 'FacesDetected', + RawConv => '$$self{FacesDetected} = $val', + }, + 0x04 => { + Name => 'Face1Position', + Format => 'int16u[4]', + RawConv => '$$self{FacesDetected} < 1 ? undef : $val', + Notes => q{ + top, left, width and height of face detect area in coordinates of + FaceDetectFrameSize + }, + }, + 0x08 => { + Name => 'Face2Position', + Format => 'int16u[4]', + RawConv => '$$self{FacesDetected} < 2 ? undef : $val', + }, + 0x0c => { + Name => 'Face3Position', + Format => 'int16u[4]', + RawConv => '$$self{FacesDetected} < 3 ? undef : $val', + }, + 0x10 => { + Name => 'Face4Position', + Format => 'int16u[4]', + RawConv => '$$self{FacesDetected} < 4 ? undef : $val', + }, + 0x14 => { + Name => 'Face5Position', + Format => 'int16u[4]', + RawConv => '$$self{FacesDetected} < 5 ? undef : $val', + }, + 0x18 => { + Name => 'Face6Position', + Format => 'int16u[4]', + RawConv => '$$self{FacesDetected} < 6 ? undef : $val', + }, + 0x1c => { + Name => 'Face7Position', + Format => 'int16u[4]', + RawConv => '$$self{FacesDetected} < 7 ? undef : $val', + }, + 0x20 => { + Name => 'Face8Position', + Format => 'int16u[4]', + RawConv => '$$self{FacesDetected} < 8 ? undef : $val', + }, + 0x24 => { + Name => 'Face9Position', + Format => 'int16u[4]', + RawConv => '$$self{FacesDetected} < 9 ? undef : $val', + }, + 0x28 => { + Name => 'Face10Position', + Format => 'int16u[4]', + RawConv => '$$self{FacesDetected} < 10 ? undef : $val', + }, + 0x2c => { + Name => 'Face11Position', + Format => 'int16u[4]', + RawConv => '$$self{FacesDetected} < 11 ? undef : $val', + }, + 0x30 => { + Name => 'Face12Position', + Format => 'int16u[4]', + RawConv => '$$self{FacesDetected} < 12 ? undef : $val', + }, +); + +# Picture Control information - PH (D300,P6000) +%Image::ExifTool::Nikon::PictureControl = ( + %binaryDataAttrs, + GROUPS => { 0 => 'MakerNotes', 2 => 'Camera' }, + # NOTE: Must set ByteOrder in SubDirectory if any multi-byte integer tags added + 0 => { + Name => 'PictureControlVersion', + Format => 'undef[4]', + Writable => 0, + }, + 4 => { + Name => 'PictureControlName', + Format => 'string[20]', + # make lower case with a leading capital for each word + PrintConv => \&FormatString, + PrintConvInv => 'uc($val)', + }, + 24 => { + Name => 'PictureControlBase', + Format => 'string[20]', + PrintConv => \&FormatString, + PrintConvInv => 'uc($val)', + }, + # beginning at byte 44, there is some interesting information. + # here are the observed bytes for each PictureControlMode: + # 44 45 46 47 48 49 50 51 52 53 54 55 56 57 + # STANDARD 00 01 00 00 00 80 83 80 80 80 80 ff ff ff + # NEUTRAL 03 c2 00 00 00 ff 82 80 80 80 80 ff ff ff + # VIVID 00 c3 00 00 00 80 84 80 80 80 80 ff ff ff + # MONOCHROME 06 4d 00 01 02 ff 82 80 80 ff ff 80 80 ff + # Neutral2 03 c2 01 00 02 ff 80 7f 81 00 7f ff ff ff (custom) + # (note that up to 9 different custom picture controls can be stored) + # --> bytes 44 and 45 are swapped if CaptureNX changes the byte order + # + 48 => { #21 + Name => 'PictureControlAdjust', + PrintConv => { + 0 => 'Default Settings', + 1 => 'Quick Adjust', + 2 => 'Full Control', + }, + }, + 49 => { + Name => 'PictureControlQuickAdjust', + # settings: -2 to +2 (n/a for Neutral and Monochrome modes) + DelValue => 0xff, + ValueConv => '$val - 0x80', + ValueConvInv => '$val + 0x80', + PrintConv => 'Image::ExifTool::Nikon::PrintPC($val)', + PrintConvInv => 'Image::ExifTool::Nikon::PrintPCInv($val)', + }, + 50 => { + Name => 'Sharpness', + # settings: 0 to 9, Auto + ValueConv => '$val - 0x80', + ValueConvInv => '$val + 0x80', + PrintConv => 'Image::ExifTool::Nikon::PrintPC($val,"No Sharpening","%d")', + PrintConvInv => 'Image::ExifTool::Nikon::PrintPCInv($val)', + }, + 51 => { + Name => 'Contrast', + # settings: -3 to +3, Auto + ValueConv => '$val - 0x80', + ValueConvInv => '$val + 0x80', + PrintConv => 'Image::ExifTool::Nikon::PrintPC($val)', + PrintConvInv => 'Image::ExifTool::Nikon::PrintPCInv($val)', + }, + 52 => { + Name => 'Brightness', + # settings: -1 to +1 + ValueConv => '$val - 0x80', + ValueConvInv => '$val + 0x80', + PrintConv => 'Image::ExifTool::Nikon::PrintPC($val)', + PrintConvInv => 'Image::ExifTool::Nikon::PrintPCInv($val)', + }, + 53 => { + Name => 'Saturation', + # settings: -3 to +3, Auto (n/a for Monochrome mode) + DelValue => 0xff, + ValueConv => '$val - 0x80', + ValueConvInv => '$val + 0x80', + PrintConv => 'Image::ExifTool::Nikon::PrintPC($val)', + PrintConvInv => 'Image::ExifTool::Nikon::PrintPCInv($val)', + }, + 54 => { + Name => 'HueAdjustment', + # settings: -3 to +3 (n/a for Monochrome mode) + DelValue => 0xff, + ValueConv => '$val - 0x80', + ValueConvInv => '$val + 0x80', + PrintConv => 'Image::ExifTool::Nikon::PrintPC($val,"None")', + PrintConvInv => 'Image::ExifTool::Nikon::PrintPCInv($val)', + }, + 55 => { + Name => 'FilterEffect', + # settings: Off,Yellow,Orange,Red,Green (n/a for color modes) + DelValue => 0xff, + PrintHex => 1, + PrintConv => { + 0x80 => 'Off', + 0x81 => 'Yellow', + 0x82 => 'Orange', + 0x83 => 'Red', + 0x84 => 'Green', + 0xff => 'n/a', + }, + }, + 56 => { + Name => 'ToningEffect', + # settings: B&W,Sepia,Cyanotype,Red,Yellow,Green,Blue-Green,Blue, + # Purple-Blue,Red-Purple (n/a for color modes) + DelValue => 0xff, + PrintHex => 1, + PrintConvColumns => 2, + PrintConv => { + 0x80 => 'B&W', + 0x81 => 'Sepia', + 0x82 => 'Cyanotype', + 0x83 => 'Red', + 0x84 => 'Yellow', + 0x85 => 'Green', + 0x86 => 'Blue-green', + 0x87 => 'Blue', + 0x88 => 'Purple-blue', + 0x89 => 'Red-purple', + 0xff => 'n/a', + # 0x04 - seen for D810 (PH) + }, + }, + 57 => { #21 + Name => 'ToningSaturation', + # settings: B&W,Sepia,Cyanotype,Red,Yellow,Green,Blue-Green,Blue, + # Purple-Blue,Red-Purple (n/a unless ToningEffect is used) + DelValue => 0xff, + ValueConv => '$val - 0x80', + ValueConvInv => '$val + 0x80', + PrintConv => '$val==0x7f ? "n/a" : $val', + PrintConvInv => 'Image::ExifTool::Nikon::PrintPCInv($val)', + }, +); + +# Picture Control information V2 (ref 28) +%Image::ExifTool::Nikon::PictureControl2 = ( + %binaryDataAttrs, + GROUPS => { 0 => 'MakerNotes', 2 => 'Camera' }, + # NOTE: Must set ByteOrder in SubDirectory if any multi-byte integer tags added + 0 => { + Name => 'PictureControlVersion', + Format => 'undef[4]', + Writable => 0, + }, + 4 => { + Name => 'PictureControlName', + Format => 'string[20]', + # make lower case with a leading capital for each word + PrintConv => \&FormatString, + PrintConvInv => 'uc($val)', + }, + 24 => { + Name => 'PictureControlBase', + Format => 'string[20]', + PrintConv => \&FormatString, + PrintConvInv => 'uc($val)', + }, + # beginning at byte 44, there is some interesting information. + # here are the observed bytes for each PictureControlMode: + # 44 45 46 47 48 49 50 51 52 53 54 55 56 57 + # STANDARD 00 01 00 00 00 80 83 80 80 80 80 ff ff ff + # NEUTRAL 03 c2 00 00 00 ff 82 80 80 80 80 ff ff ff + # VIVID 00 c3 00 00 00 80 84 80 80 80 80 ff ff ff + # MONOCHROME 06 4d 00 01 02 ff 82 80 80 ff ff 80 80 ff + # Neutral2 03 c2 01 00 02 ff 80 7f 81 00 7f ff ff ff (custom) + # (note that up to 9 different custom picture controls can be stored) + # --> bytes 44 and 45 are swapped if CaptureNX changes the byte order + # + 48 => { #21 + Name => 'PictureControlAdjust', + PrintConv => { + 0 => 'Default Settings', + 1 => 'Quick Adjust', + 2 => 'Full Control', + }, + }, + 49 => { + Name => 'PictureControlQuickAdjust', + # settings: -2 to +2 (n/a for Neutral and Monochrome modes) + DelValue => 0xff, + ValueConv => '$val - 0x80', + ValueConvInv => '$val + 0x80', + PrintConv => 'Image::ExifTool::Nikon::PrintPC($val)', + PrintConvInv => 'Image::ExifTool::Nikon::PrintPCInv($val)', + }, + 51 => { + Name => 'Sharpness', + DelValue => 0xff, + ValueConv => '$val - 0x80', + ValueConvInv => '$val + 0x80', + PrintConv => 'Image::ExifTool::Nikon::PrintPC($val,"None","%.2f",4)', + PrintConvInv => 'Image::ExifTool::Nikon::PrintPCInv($val,4)', + }, + 53 => { + Name => 'Clarity', + DelValue => 0xff, + ValueConv => '$val - 0x80', + ValueConvInv => '$val + 0x80', + PrintConv => 'Image::ExifTool::Nikon::PrintPC($val,"None","%.2f",4)', + PrintConvInv => 'Image::ExifTool::Nikon::PrintPCInv2($val,4)', + }, + 55 => { + Name => 'Contrast', + DelValue => 0xff, + ValueConv => '$val - 0x80', + ValueConvInv => '$val + 0x80', + PrintConv => 'Image::ExifTool::Nikon::PrintPC($val,"None","%.2f",4)', + PrintConvInv => 'Image::ExifTool::Nikon::PrintPCInv($val,4)', + }, + 57 => { #21 + Name => 'Brightness', + # settings: -1 to +1 + ValueConv => '$val - 0x80', + ValueConvInv => '$val + 0x80', + PrintConv => 'Image::ExifTool::Nikon::PrintPC($val,undef,"%.2f",4)', + PrintConvInv => 'Image::ExifTool::Nikon::PrintPCInv($val,4)', + }, + 59 => { + Name => 'Saturation', + DelValue => 0xff, + ValueConv => '$val - 0x80', + ValueConvInv => '$val + 0x80', + PrintConv => 'Image::ExifTool::Nikon::PrintPC($val,"None","%.2f",4)', + PrintConvInv => 'Image::ExifTool::Nikon::PrintPCInv($val,4)', + }, + 61 => { + Name => 'Hue', + DelValue => 0xff, + ValueConv => '$val - 0x80', + ValueConvInv => '$val + 0x80', + PrintConv => 'Image::ExifTool::Nikon::PrintPC($val,"None","%.2f",4)', + PrintConvInv => 'Image::ExifTool::Nikon::PrintPCInv($val)', + }, + 63 => { + Name => 'FilterEffect', + # settings: Off,Yellow,Orange,Red,Green (n/a for color modes) + DelValue => 0xff, + PrintHex => 1, + PrintConv => { + 0x80 => 'Off', + 0x81 => 'Yellow', + 0x82 => 'Orange', + 0x83 => 'Red', + 0x84 => 'Green', + 0xff => 'n/a', + }, + }, + 64 => { + Name => 'ToningEffect', + # settings: B&W,Sepia,Cyanotype,Red,Yellow,Green,Blue-Green,Blue, + # Purple-Blue,Red-Purple (n/a for color modes) + DelValue => 0xff, + PrintHex => 1, + PrintConvColumns => 2, + PrintConv => { + 0x80 => 'B&W', + 0x81 => 'Sepia', + 0x82 => 'Cyanotype', + 0x83 => 'Red', + 0x84 => 'Yellow', + 0x85 => 'Green', + 0x86 => 'Blue-green', + 0x87 => 'Blue', + 0x88 => 'Purple-blue', + 0x89 => 'Red-purple', + 0xff => 'n/a', + }, + }, + 65 => { + Name => 'ToningSaturation', + DelValue => 0xff, + ValueConv => '$val - 0x80', #$val == 0x7f (n/a) for "B&W" + ValueConvInv => '$val + 0x80', + PrintConv => 'Image::ExifTool::Nikon::PrintPC($val,"None","%.2f",4)', + PrintConvInv => 'Image::ExifTool::Nikon::PrintPCInv($val,4)', + + }, +); + +# Picture Control information V3 (ref PH, Z7) +%Image::ExifTool::Nikon::PictureControl3 = ( + %binaryDataAttrs, + GROUPS => { 0 => 'MakerNotes', 2 => 'Camera' }, + # NOTE: Must set ByteOrder in SubDirectory if any multi-byte integer tags added + 0 => { + Name => 'PictureControlVersion', + Format => 'undef[4]', + Writable => 0, + }, + 8 => { + Name => 'PictureControlName', + Format => 'string[20]', + # make lower case with a leading capital for each word + PrintConv => \&FormatString, + PrintConvInv => 'uc($val)', + }, + # 48 - looks like PictureControl2 byte 45 + 28 => { + Name => 'PictureControlBase', + Format => 'string[20]', + PrintConv => \&FormatString, + PrintConvInv => 'uc($val)', + }, + 54 => { # (NC) + Name => 'PictureControlAdjust', + PrintConv => { + 0 => 'Default Settings', + 1 => 'Quick Adjust', + 2 => 'Full Control', + }, + }, + 55 => { # (NC) + Name => 'PictureControlQuickAdjust', + DelValue => 0xff, + ValueConv => '$val - 0x80', + ValueConvInv => '$val + 0x80', + PrintConv => 'Image::ExifTool::Nikon::PrintPC($val)', + PrintConvInv => 'Image::ExifTool::Nikon::PrintPCInv($val)', + }, + 57 => { + Name => 'Sharpness', + DelValue => 0xff, + ValueConv => '$val - 0x80', + ValueConvInv => '$val + 0x80', + PrintConv => 'Image::ExifTool::Nikon::PrintPC($val,"None","%.2f",4)', + PrintConvInv => 'Image::ExifTool::Nikon::PrintPCInv($val,4)', + }, + 59 => { + Name => 'MidRangeSharpness', + DelValue => 0xff, + ValueConv => '$val - 0x80', + ValueConvInv => '$val + 0x80', + PrintConv => 'Image::ExifTool::Nikon::PrintPC($val,"None","%.2f",4)', + PrintConvInv => 'Image::ExifTool::Nikon::PrintPCInv($val,4)', + }, + 61 => { + Name => 'Clarity', + DelValue => 0xff, + ValueConv => '$val - 0x80', + ValueConvInv => '$val + 0x80', + PrintConv => 'Image::ExifTool::Nikon::PrintPC($val,"None","%.2f",4)', + PrintConvInv => 'Image::ExifTool::Nikon::PrintPCInv2($val,4)', + }, + 63 => { + Name => 'Contrast', + DelValue => 0xff, + ValueConv => '$val - 0x80', + ValueConvInv => '$val + 0x80', + PrintConv => 'Image::ExifTool::Nikon::PrintPC($val,"None","%.2f",4)', + PrintConvInv => 'Image::ExifTool::Nikon::PrintPCInv($val,4)', + }, + 65 => { #21 + Name => 'Brightness', + ValueConv => '$val - 0x80', + ValueConvInv => '$val + 0x80', + PrintConv => 'Image::ExifTool::Nikon::PrintPC($val,undef,"%.2f",4)', + PrintConvInv => 'Image::ExifTool::Nikon::PrintPCInv($val,4)', + }, + 67 => { + Name => 'Saturation', + DelValue => 0xff, + ValueConv => '$val - 0x80', + ValueConvInv => '$val + 0x80', + PrintConv => 'Image::ExifTool::Nikon::PrintPC($val,"None","%.2f",4)', + PrintConvInv => 'Image::ExifTool::Nikon::PrintPCInv($val,4)', + }, + 69 => { + Name => 'Hue', + DelValue => 0xff, + ValueConv => '$val - 0x80', + ValueConvInv => '$val + 0x80', + PrintConv => 'Image::ExifTool::Nikon::PrintPC($val,"None","%.2f",4)', + PrintConvInv => 'Image::ExifTool::Nikon::PrintPCInv($val)', + }, + 71 => { # (NC) + Name => 'FilterEffect', + DelValue => 0xff, + PrintHex => 1, + PrintConv => { + 0x80 => 'Off', + 0x81 => 'Yellow', + 0x82 => 'Orange', + 0x83 => 'Red', + 0x84 => 'Green', + 0xff => 'n/a', + }, + }, + 72 => { # (NC) + Name => 'ToningEffect', + DelValue => 0xff, + PrintHex => 1, + PrintConvColumns => 2, + PrintConv => { + 0x80 => 'B&W', + 0x81 => 'Sepia', + 0x82 => 'Cyanotype', + 0x83 => 'Red', + 0x84 => 'Yellow', + 0x85 => 'Green', + 0x86 => 'Blue-green', + 0x87 => 'Blue', + 0x88 => 'Purple-blue', + 0x89 => 'Red-purple', + 0xff => 'n/a', + }, + }, + 73 => { # (NC) + Name => 'ToningSaturation', + DelValue => 0xff, + ValueConv => '$val - 0x80', + ValueConvInv => '$val + 0x80', + PrintConv => 'Image::ExifTool::Nikon::PrintPC($val,"None","%.2f",4)', + PrintConvInv => 'Image::ExifTool::Nikon::PrintPCInv($val,4)', + + }, +); + +# Unknown Picture Control information +%Image::ExifTool::Nikon::PictureControlUnknown = ( + %binaryDataAttrs, + GROUPS => { 0 => 'MakerNotes', 2 => 'Camera' }, + # NOTE: Must set ByteOrder in SubDirectory if any multi-byte integer tags added + 0 => { + Name => 'PictureControlVersion', + Format => 'undef[4]', + Writable => 0, + }, +); + +# World Time information - JD (D300) +%Image::ExifTool::Nikon::WorldTime = ( + %binaryDataAttrs, + GROUPS => { 0 => 'MakerNotes', 2 => 'Time' }, + 0 => { + Name => 'TimeZone', + Format => 'int16s', + PrintConv => q{ + my $sign = $val < 0 ? '-' : '+'; + my $h = int(abs($val) / 60); + sprintf("%s%.2d:%.2d", $sign, $h, abs($val)-60*$h); + }, + PrintConvInv => q{ + $val =~ /([-+]?)(\d+):(\d+)/ or return undef; + return $1 . ($2 * 60 + $3); + }, + }, + 2 => { + Name => 'DaylightSavings', + PrintConv => { 0 => 'No', 1 => 'Yes' }, + }, + 3 => { + Name => 'DateDisplayFormat', + PrintConv => { + 0 => 'Y/M/D', + 1 => 'M/D/Y', + 2 => 'D/M/Y', + }, + }, +); + +# ISO information - PH (D300) +%Image::ExifTool::Nikon::ISOInfo = ( + %binaryDataAttrs, + GROUPS => { 0 => 'MakerNotes', 2 => 'Camera' }, + 0 => { + Name => 'ISO', + Notes => 'val = 100 * 2**(raw/12-5)', + Priority => 0, # because people like to see rounded-off values if they exist + ValueConv => '100*exp(($val/12-5)*log(2))', + ValueConvInv => '(log($val/100)/log(2)+5)*12', + PrintConv => 'int($val + 0.5)', + PrintConvInv => '$val', + }, + # 1 - 0x01 + # 2 - 0x0c (probably the ISO divisor above) + # 3 - 0x00 + 4 => { + Name => 'ISOExpansion', + Format => 'int16u', + PrintHex => 1, + PrintConvColumns => 2, + PrintConv => { + 0x000 => 'Off', + 0x101 => 'Hi 0.3', + 0x102 => 'Hi 0.5', + 0x103 => 'Hi 0.7', + 0x104 => 'Hi 1.0', + 0x105 => 'Hi 1.3', # (Hi 1.3-1.7 may be possible with future models) + 0x106 => 'Hi 1.5', + 0x107 => 'Hi 1.7', + 0x108 => 'Hi 2.0', #(NC) - D3 should have this mode + 0x109 => 'Hi 2.3', #IB + 0x10a => 'Hi 2.5', #IB + 0x10b => 'Hi 2.7', #IB + 0x10c => 'Hi 3.0', #IB + 0x10d => 'Hi 3.3', #IB + 0x10e => 'Hi 3.5', #IB + 0x10f => 'Hi 3.7', #IB + 0x110 => 'Hi 4.0', #IB + 0x111 => 'Hi 4.3', #IB + 0x112 => 'Hi 4.5', #IB + 0x113 => 'Hi 4.7', #IB + 0x114 => 'Hi 5.0', #IB + 0x201 => 'Lo 0.3', + 0x202 => 'Lo 0.5', + 0x203 => 'Lo 0.7', + 0x204 => 'Lo 1.0', + }, + }, + # bytes 6-11 same as 0-4 in my samples (why is this duplicated?) + 6 => { + Name => 'ISO2', + Notes => 'val = 100 * 2**(raw/12-5)', + ValueConv => '100*exp(($val/12-5)*log(2))', + ValueConvInv => '(log($val/100)/log(2)+5)*12', + PrintConv => 'int($val + 0.5)', + PrintConvInv => '$val', + }, + # 7 - 0x01 + # 8 - 0x0c (probably the ISO divisor above) + # 9 - 0x00 + 10 => { + Name => 'ISOExpansion2', + Format => 'int16u', + PrintHex => 1, + PrintConvColumns => 2, + PrintConv => { + 0x000 => 'Off', + 0x101 => 'Hi 0.3', + 0x102 => 'Hi 0.5', + 0x103 => 'Hi 0.7', + 0x104 => 'Hi 1.0', + 0x105 => 'Hi 1.3', # (Hi 1.3-1.7 may be possible with future models) + 0x106 => 'Hi 1.5', + 0x107 => 'Hi 1.7', + 0x108 => 'Hi 2.0', #(NC) - D3 should have this mode + 0x201 => 'Lo 0.3', + 0x202 => 'Lo 0.5', + 0x203 => 'Lo 0.7', + 0x204 => 'Lo 1.0', + }, + }, + # bytes 12-13: 00 00 +); + +# distortion information - PH (D5000) +%Image::ExifTool::Nikon::DistortInfo = ( + %binaryDataAttrs, + GROUPS => { 0 => 'MakerNotes', 2 => 'Camera' }, + # NOTE: Must set ByteOrder in SubDirectory if any multi-byte integer tags added + 0 => { + Name => 'DistortionVersion', + Format => 'undef[4]', + Writable => 0, + Unknown => 1, + }, + 4 => { + Name => 'AutoDistortionControl', + PrintConv => { + 0 => 'Off', + 1 => 'On', + 2 => 'On (underwater)', # (1AW1) + }, + }, +); + +# unknown information - PH (D7000) +%Image::ExifTool::Nikon::UnknownInfo = ( + %binaryDataAttrs, + FORMAT => 'int32u', + GROUPS => { 0 => 'MakerNotes', 2 => 'Camera' }, + 0 => { + Name => 'UnknownInfoVersion', + Condition => '$$valPt =~ /^\d{4}/', + Format => 'undef[4]', + Writable => 0, + Unknown => 1, + }, + # (bytes 6/7 and 8/9 are swapped if CaptureNX changes the byte order) +); + +# more unknown information - PH (D7000) +%Image::ExifTool::Nikon::UnknownInfo2 = ( + %binaryDataAttrs, + FORMAT => 'int32u', + GROUPS => { 0 => 'MakerNotes', 2 => 'Camera' }, + 0 => { + Name => 'UnknownInfo2Version', + Condition => '$$valPt =~ /^\d{4}/', + Format => 'undef[4]', + Writable => 0, + Unknown => 1, + }, + # (byte 4 may be changed from 1 to 0 when rewritten by CaptureNX) +); + +# Nikon AF information (ref 13) +%Image::ExifTool::Nikon::AFInfo = ( + %binaryDataAttrs, + GROUPS => { 0 => 'MakerNotes', 2 => 'Camera' }, + 0 => { + Name => 'AFAreaMode', + PrintConv => { + 0 => 'Single Area', + 1 => 'Dynamic Area', + 2 => 'Dynamic Area (closest subject)', + 3 => 'Group Dynamic', + 4 => 'Single Area (wide)', + 5 => 'Dynamic Area (wide)', + }, + }, + 1 => { + Name => 'AFPoint', + Notes => 'in some focus modes this value is not meaningful', + PrintConvColumns => 2, + PrintConv => { + 0 => 'Center', + 1 => 'Top', + 2 => 'Bottom', + 3 => 'Mid-left', + 4 => 'Mid-right', + 5 => 'Upper-left', + 6 => 'Upper-right', + 7 => 'Lower-left', + 8 => 'Lower-right', + 9 => 'Far Left', + 10 => 'Far Right', + # (have also seen values of 11 and 12 when AFPointsInFocus is "(none)" - PH S3500) + }, + }, + 2 => { + Name => 'AFPointsInFocus', + Format => 'int16u', + PrintConvColumns => 2, + PrintConv => { + 0 => '(none)', + 0x7ff => 'All 11 Points', + BITMASK => { + 0 => 'Center', + 1 => 'Top', + 2 => 'Bottom', + 3 => 'Mid-left', + 4 => 'Mid-right', + 5 => 'Upper-left', + 6 => 'Upper-right', + 7 => 'Lower-left', + 8 => 'Lower-right', + 9 => 'Far Left', + 10 => 'Far Right', + }, + }, + }, +); + +# Nikon AF information for D3 and D300 (ref JD) +%Image::ExifTool::Nikon::AFInfo2 = ( + %binaryDataAttrs, + GROUPS => { 0 => 'MakerNotes', 2 => 'Camera' }, + DATAMEMBER => [ 0, 4, 6 ], + NOTES => "These tags are written by Nikon DSLR's which have the live view feature.", + # NOTE: Must set ByteOrder in SubDirectory if any multi-byte integer tags added + 0 => { + Name => 'AFInfo2Version', + Format => 'undef[4]', + Writable => 0, + RawConv => '$$self{AFInfo2Version} = $val', + }, + 4 => { #PH + Name => 'ContrastDetectAF', + RawConv => '$$self{ContrastDetectAF} = $val', + PrintConv => { + %offOn, + 2 => 'On (2)', #PH (Z7) + }, + Notes => 'this is Off for the hybrid AF used in Nikon 1 models', + }, + 5 => [ + { + Name => 'AFAreaMode', + Condition => 'not $$self{ContrastDetectAF}', + Notes => 'ContrastDetectAF Off', + PrintConv => { + 0 => 'Single Area', # (called "Single Point" in manual - PH) + 1 => 'Dynamic Area', #PH + 2 => 'Dynamic Area (closest subject)', #PH + 3 => 'Group Dynamic', #PH + 4 => 'Dynamic Area (9 points)', #JD/28 + 5 => 'Dynamic Area (21 points)', #28 + 6 => 'Dynamic Area (51 points)', #28 + 7 => 'Dynamic Area (51 points, 3D-tracking)', #PH/28 + 8 => 'Auto-area', + 9 => 'Dynamic Area (3D-tracking)', #PH (D5000 "3D-tracking (11 points)") + 10 => 'Single Area (wide)', #PH + 11 => 'Dynamic Area (wide)', #PH + 12 => 'Dynamic Area (wide, 3D-tracking)', #PH + 13 => 'Group Area', #PH + 14 => 'Dynamic Area (25 points)', #PH + 15 => 'Dynamic Area (72 points)', #PH + 16 => 'Group Area (HL)', #28 + 17 => 'Group Area (VL)', #28 + 128 => 'Single', #PH (1J1,1J2,1J3,1J4,1S1,1S2,1V2,1V3) + 129 => 'Auto (41 points)', #PH (1J1,1J2,1J3,1J4,1S1,1S2,1V1,1V2,1V3,AW1) + 130 => 'Subject Tracking (41 points)', #PH (1J1,1J4,1J3) + 131 => 'Face Priority (41 points)', #PH (1J1,1J3,1S1,1V2,AW1) + # 134 - seen for 1V1[PhaseDetectAF=0] (PH) + # 135 - seen for 1J2[PhaseDetectAF=4] (PH) + 192 => 'Pinpoint', #PH (NC) + 193 => 'Single', #PH (NC) + 195 => 'Wide (S)', #PH (NC) + 196 => 'Wide (L)', #PH (NC) + 197 => 'Auto', #PH (NC) + }, + }, + { #PH (D3/D90/D5000) + Name => 'AFAreaMode', + Notes => 'ContrastDetectAF On', + PrintConv => { + 0 => 'Contrast-detect', # (D3) + 1 => 'Contrast-detect (normal area)', # (D90/D5000) + # (D90 and D5000 give value of 2 when set to 'Face Priority' and + # 'Subject Tracking', but I didn't have a face to shoot at or a + # moving subject to track so perhaps this value changes dynamically) + 2 => 'Contrast-detect (wide area)', # (D90/D5000) + 3 => 'Contrast-detect (face priority)', # (ViewNX) + 4 => 'Contrast-detect (subject tracking)', # (ViewNX) + 128 => 'Single', #PH (1V3) + 129 => 'Auto (41 points)', #PH (NC) + 130 => 'Subject Tracking (41 points)', #PH (NC) + 131 => 'Face Priority (41 points)', #PH (NC) + 192 => 'Pinpoint', #PH (Z7) + 193 => 'Single', #PH (Z7) (AF-S?) + 194 => 'Dynamic', #PH (Z7) + 195 => 'Wide (S)', #PH (Z7) + 196 => 'Wide (L)', #PH (Z7) + 197 => 'Auto', #PH (Z7) + 198 => 'Auto (198)', #PH (Z7) (focus lock with AF-C maybe?) + 199 => 'Auto (focus lock)', #PH (Z7, AF-S) + }, + }, + ], + 6 => { + Name => 'PhaseDetectAF', #JD(AutoFocus), PH(PhaseDetectAF) + Notes => 'PrimaryAFPoint and AFPointsUsed below are only valid when this is On', + RawConv => '$$self{PhaseDetectAF} = $val', + PrintConv => { + # [observed AFAreaMode values in square brackets for each PhaseDetectAF value] + 0 => 'Off', + 1 => 'On (51-point)', #PH + 2 => 'On (11-point)', #PH + 3 => 'On (39-point)', #29 (D7000) + 4 => 'On (73-point)', #PH (1J1[128/129],1J2[128/129/135],1J3/1S1/1V2[128/129/131],1V1[129],AW1[129/131]) + 5 => 'On (5)', #PH (1S2[128/129], 1J4/1V3[129]) + 6 => 'On (105-point)', #PH (1J4/1V3[128/130]) + 7 => 'On (153-point)', #PH (D5/D500/D850) + 8 => 'On (8)', #PH (Z7) + }, + }, + 7 => [ + { #PH/JD + Name => 'PrimaryAFPoint', + Condition => '$$self{PhaseDetectAF} < 2', + Notes => q{ + models with 51-point AF -- 5 rows (A-E) and 11 columns (1-11): D3, D3S, D3X, + D4, D4S, D300, D300S, D700, D800, D800e and D810 + }, + PrintConvColumns => 5, + PrintConv => { + 0 => '(none)', + %afPoints51, + 1 => 'C6 (Center)', # (add " (Center)" to central point) + }, + }, + { #10 + Name => 'PrimaryAFPoint', + Notes => 'models with 11-point AF: D90, D3000, D3100, D5000 and D5100', + Condition => '$$self{PhaseDetectAF} == 2', + PrintConvColumns => 2, + PrintConv => { + 0 => '(none)', + 1 => 'Center', + 2 => 'Top', + 3 => 'Bottom', + 4 => 'Mid-left', + 5 => 'Upper-left', + 6 => 'Lower-left', + 7 => 'Far Left', + 8 => 'Mid-right', + 9 => 'Upper-right', + 10 => 'Lower-right', + 11 => 'Far Right', + }, + }, + { #29 + Name => 'PrimaryAFPoint', + Condition => '$$self{PhaseDetectAF} == 3', + Notes => 'models with 39-point AF: D600 and D7000', + PrintConvColumns => 5, + PrintConv => { + 0 => '(none)', + %afPoints39, + 1 => 'C6 (Center)', # (add " (Center)" to central point) + }, + }, + { #PH + Name => 'PrimaryAFPoint', + Condition => '$$self{PhaseDetectAF} == 4', + Notes => 'Nikon 1 models with older 135-point AF and 73-point phase-detect AF', + PrintConvColumns => 5, + PrintConv => { + 0 => '(none)', + %afPoints135, + 1 => 'E8 (Center)', # (add " (Center)" to central point) + }, + }, + { #PH (NC) + Name => 'PrimaryAFPoint', + Condition => '$$self{PhaseDetectAF} == 5', + Notes => q{ + Nikon 1 models with newer 135-point AF and 73-point phase-detect AF -- 9 + rows (B-J) and 15 columns (1-15), inside a grid of 11 rows by 15 columns. + The points are numbered sequentially, with F8 at the center + }, + PrintConv => { + 0 => '(none)', + 82 => 'F8 (Center)', + OTHER => sub { + my ($val, $inv) = @_; + return GetAFPointGrid($val, 15, $inv); + }, + }, + }, + { #PH + Name => 'PrimaryAFPoint', + Condition => '$$self{PhaseDetectAF} == 6', + Notes => q{ + Nikon 1 models with 171-point AF and 105-point phase-detect AF -- 9 rows + (B-J) and 19 columns (2-20), inside a grid of 11 rows by 21 columns. The + points are numbered sequentially, with F11 at the center + }, + PrintConv => { + 0 => '(none)', + #22 => 'B2 (Top-left)', + #40 => 'B20 (Top-right)', + 115 => 'F11 (Center)', + #190 => 'J2 (Bottom-left)', + #208 => 'J20 (Bottom-right)', + OTHER => sub { + my ($val, $inv) = @_; + return GetAFPointGrid($val, 21, $inv); + }, + }, + }, + { #PH + Name => 'PrimaryAFPoint', + Condition => '$$self{PhaseDetectAF} == 7 and $$self{AFInfo2Version} eq "0100"', + Notes => q{ + Nikon models with 153-point AF -- 9 rows (A-I) and 17 columns (1-17): D5, + D500 and D850 + }, + PrintConvColumns => 5, + PrintConv => { + 0 => '(none)', + %afPoints153, + 1 => 'E9 (Center)', + }, + }, + { #PH (Z7) (NC) + Name => 'PrimaryAFPoint', + Condition => '$$self{PhaseDetectAF} == 8 and $$self{AFInfo2Version} =~ /^03/', + Notes => q{ + Nikon models with 493-point AF -- 17 rows (A-Q) and 29 columns (1-29), I15 + at the center + }, + PrintConv => { + 0 => '(none)', + 246 => 'I15 (Center)', + OTHER => sub { + my ($val, $inv) = @_; + return GetAFPointGrid($val, 29, $inv); + }, + }, + }, + { + Name => 'PrimaryAFPoint', + Condition => '$$self{AFInfo2Version} eq "0100"', + Notes => 'future models?...', + PrintConv => { + 0 => '(none)', + 1 => 'Center', + }, + }, + ], + 8 => [ + { #JD/PH + Name => 'AFPointsUsed', + Condition => '$$self{PhaseDetectAF} < 2', + Notes => q{ + models with 51-point AF -- 5 rows: A1-9, B1-11, C1-11, D1-11, E1-9. Center + point is C6 + }, + Format => 'undef[7]', + ValueConv => 'join(" ", unpack("H2"x7, $val))', + ValueConvInv => '$val=~tr/ //d; pack("H*",$val)', + PrintConv => sub { PrintAFPoints(shift, \%afPoints51); }, + PrintConvInv => sub { PrintAFPointsInv(shift, \%afPoints51); }, + }, + { #10 + Name => 'AFPointsUsed', + Condition => '$$self{PhaseDetectAF} == 2', + Notes => 'models with 11-point AF', + # read as int16u in little-endian byte order + Format => 'undef[2]', + ValueConv => 'unpack("v",$val)', + ValueConvInv => 'pack("v",$val)', + PrintConvColumns => 2, + PrintConv => { + 0 => '(none)', + 0x7ff => 'All 11 Points', + BITMASK => { + 0 => 'Center', + 1 => 'Top', + 2 => 'Bottom', + 3 => 'Mid-left', + 4 => 'Upper-left', + 5 => 'Lower-left', + 6 => 'Far Left', + 7 => 'Mid-right', + 8 => 'Upper-right', + 9 => 'Lower-right', + 10 => 'Far Right', + }, + }, + }, + { #29/PH + Name => 'AFPointsUsed', + Condition => '$$self{PhaseDetectAF} == 3', + Notes => q{ + models with 39-point AF -- 5 rows: A1-3, B1-11, C1-11, D1-11, E1-3. Center + point is C6 + }, + Format => 'undef[5]', + ValueConv => 'join(" ", unpack("H2"x5, $val))', + ValueConvInv => '$val=~tr/ //d; pack("H*",$val)', + PrintConv => sub { PrintAFPoints(shift, \%afPoints39); }, + PrintConvInv => sub { PrintAFPointsInv(shift, \%afPoints39); }, + }, + { #PH (1AW1,1J1,1J2,1J3,1S1,1V1,1V2) + Name => 'AFPointsUsed', + Condition => '$$self{PhaseDetectAF} == 4', + Notes => q{ + older models with 135-point AF -- 9 rows (A-I) and 15 columns (1-15). + Center point is E8. The odd-numbered columns, columns 2 and 14, and the + remaining corner points are not used for 41-point AF mode + }, + Format => 'undef[17]', + ValueConv => 'join(" ", unpack("H2"x17, $val))', + ValueConvInv => '$val=~tr/ //d; pack("H*",$val)', + PrintConv => sub { PrintAFPoints(shift, \%afPoints135); }, + PrintConvInv => sub { PrintAFPointsInv(shift, \%afPoints135); }, + }, + { #PH (1S2) + Name => 'AFPointsUsed', + Condition => '$$self{PhaseDetectAF} == 5', + Notes => q{ + newer models with 135-point AF -- 9 rows (B-J) and 15 colums (1-15). Center + point is F8 + }, + Format => 'undef[21]', + ValueConv => 'join(" ", unpack("H2"x21, $val))', + ValueConvInv => '$val=~tr/ //d; pack("H*",$val)', + PrintConv => sub { PrintAFPointsGrid(shift, 15); }, + PrintConvInv => sub { PrintAFPointsGridInv(shift, 15, 21); }, + }, + { #PH (1J4,1V3) + Name => 'AFPointsUsed', + Condition => '$$self{PhaseDetectAF} == 6', + Notes => q{ + models with 171-point AF -- 9 rows (B-J) and 19 columns (2-20). Center + point is F10 + }, + Format => 'undef[29]', + ValueConv => 'join(" ", unpack("H2"x29, $val))', + ValueConvInv => '$val=~tr/ //d; pack("H*",$val)', + PrintConv => sub { PrintAFPointsGrid(shift, 21); }, + PrintConvInv => sub { PrintAFPointsGridInv(shift, 21, 29); }, + }, + { #PH (D5,D500) + Name => 'AFPointsUsed', + Condition => '$$self{PhaseDetectAF} == 7', + Notes => q{ + models with 153-point AF -- 9 rows (A-I) and 17 columns (1-17). Center + point is E9 + }, + Format => 'undef[20]', + ValueConv => 'join(" ", unpack("H2"x20, $val))', + ValueConvInv => '$val=~tr/ //d; pack("H*",$val)', + PrintConv => sub { PrintAFPoints(shift, \%afPoints153); }, + PrintConvInv => sub { PrintAFPointsInv(shift, \%afPoints153); }, + }, + { #PH (Z7) (NC) + Name => 'AFPointsUsed', + Condition => '$$self{PhaseDetectAF} == 8', + Notes => q{ + models with 493-point AF -- 17 rows (A-Q) and 29 columns (1-29). Center + point is I15 + }, + Format => 'undef[62]', + ValueConv => 'join(" ", unpack("H2"x62, $val))', + ValueConvInv => '$val=~tr/ //d; pack("H*",$val)', + PrintConv => sub { PrintAFPointsGrid(shift, 29); }, + PrintConvInv => sub { PrintAFPointsGridInv(shift, 29, 62); }, + }, + { #PH + Name => 'AFPointsUsed', + Format => 'undef[7]', + ValueConv => 'join(" ", unpack("H2"x7, $val))', + ValueConvInv => '$val=~tr/ //d; pack("H*",$val)', + PrintConv => '"Unknown ($val)"', + PrintConvInv => '$val=~s/Unknown \\((.*)\\)/$1/; $val', + }, + ], + 0x10 => { #PH (D90 and D5000) + Name => 'AFImageWidth', + Condition => '$$self{AFInfo2Version} eq "0100"', + Format => 'int16u', + RawConv => '$val ? $val : undef', + Notes => 'this and the following tags are valid only for contrast-detect AF', + }, + 0x12 => { #PH + Name => 'AFImageHeight', + Condition => '$$self{AFInfo2Version} eq "0100"', + Format => 'int16u', + RawConv => '$val ? $val : undef', + }, + 0x14 => { #PH + Name => 'AFAreaXPosition', + Condition => '$$self{AFInfo2Version} eq "0100"', + Notes => 'center of AF area in AFImage coordinates', + Format => 'int16u', + RawConv => '$val ? $val : undef', + }, + 0x16 => { #PH + Name => 'AFAreaYPosition', + Condition => '$$self{AFInfo2Version} eq "0100"', + Format => 'int16u', + RawConv => '$val ? $val : undef', + }, + # AFAreaWidth/Height for the D90 and D5000: + # 352x288 (AF normal area), + # 704x576 (AF face priority, wide area, subject tracking) + 0x18 => { #PH + Name => 'AFAreaWidth', + Condition => '$$self{AFInfo2Version} eq "0100"', + Format => 'int16u', + Notes => 'size of AF area in AFImage coordinates', + RawConv => '$val ? $val : undef', + }, + 0x1a => { #PH + Name => 'AFAreaHeight', + Condition => '$$self{AFInfo2Version} eq "0100"', + Format => 'int16u', + RawConv => '$val ? $val : undef', + }, + 0x1c => { #PH + Name => 'ContrastDetectAFInFocus', + Condition => '$$self{AFInfo2Version} eq "0100"', + PrintConv => { 0 => 'No', 1 => 'Yes' }, + }, + # 0x1d - always zero (with or without live view) + 0x2a => { #PH (Z7) + Name => 'AFImageWidth', + Condition => '$$self{AFInfo2Version} =~ /^03/', + Format => 'int16u', + RawConv => '$val ? $val : undef', + }, + 0x2c => { #PH (Z7) + Name => 'AFImageHeight', + Condition => '$$self{AFInfo2Version} =~ /^03/', + Format => 'int16u', + RawConv => '$val ? $val : undef', + }, + 0x2e => { #PH (Z7) + Name => 'AFAreaXPosition', + Condition => '$$self{ContrastDetectAF} == 2 and $$self{AFInfo2Version} =~ /^03/', + Format => 'int16u', + }, + 0x30 => { #PH (Z7) + Name => 'AFAreaYPosition', + Condition => '$$self{ContrastDetectAF} == 2 and $$self{AFInfo2Version} =~ /^03/', + Format => 'int16u', + }, + 0x32 => { #PH (Z7) + Name => 'AFAreaWidth', + Condition => '$$self{AFInfo2Version} =~ /^03/', + Format => 'int16u', + RawConv => '$val ? $val : undef', + }, + 0x34 => { #PH (Z7) + Name => 'AFAreaHeight', + Condition => '$$self{AFInfo2Version} =~ /^03/', + Format => 'int16u', + RawConv => '$val ? $val : undef', + }, + 0x44 => [ + { + Name => 'PrimaryAFPoint', + Condition => '$$self{PhaseDetectAF} == 7 and $$self{AFInfo2Version} eq "0101"', + PrintConvColumns => 5, + PrintConv => { + 0 => '(none)', + %afPoints153, + 1 => 'E9 (Center)', + }, + }, + { #PH + Name => 'PrimaryAFPoint', + Notes => 'D3500', + Condition => '$$self{PhaseDetectAF} == 2 and $$self{AFInfo2Version} eq "0101"', + PrintConvColumns => 2, + PrintConv => { + 0 => '(none)', + 1 => 'Center', + 2 => 'Top', + 3 => 'Bottom', + 4 => 'Mid-left', + 5 => 'Upper-left', + 6 => 'Lower-left', + 7 => 'Far Left', + 8 => 'Mid-right', + 9 => 'Upper-right', + 10 => 'Lower-right', + 11 => 'Far Right', + }, + }, + { + Name => 'PrimaryAFPoint', + Condition => '$$self{AFInfo2Version} eq "0101"', + Notes => 'future models?...', + Priority => 0, + PrintConv => { + 0 => '(none)', + 1 => 'Center', + }, + }, + ], + 0x46 => { + Name => 'AFImageWidth', + Condition => '$$self{ContrastDetectAF} == 1 and $$self{AFInfo2Version} eq "0101"', + Format => 'int16u', + RawConv => '$val ? $val : undef', + Notes => 'this and the following tags are valid only for contrast-detect AF', + }, + 0x48 => { + Name => 'AFImageHeight', + Condition => '$$self{ContrastDetectAF} == 1 and $$self{AFInfo2Version} eq "0101"', + Format => 'int16u', + RawConv => '$val ? $val : undef', + }, + 0x4a => { + Name => 'AFAreaXPosition', + Condition => '$$self{ContrastDetectAF} == 1 and $$self{AFInfo2Version} eq "0101"', + Notes => 'center of AF area in AFImage coordinates', + Format => 'int16u', + RawConv => '$val ? $val : undef', + }, + 0x4c => { + Name => 'AFAreaYPosition', + Condition => '$$self{ContrastDetectAF} == 1 and $$self{AFInfo2Version} eq "0101"', + Format => 'int16u', + RawConv => '$val ? $val : undef', + }, + 0x4e => { + Name => 'AFAreaWidth', + Condition => '$$self{ContrastDetectAF} == 1 and $$self{AFInfo2Version} eq "0101"', + Format => 'int16u', + Notes => 'size of AF area in AFImage coordinates', + RawConv => '$val ? $val : undef', + }, + 0x50 => { + Name => 'AFAreaHeight', + Condition => '$$self{ContrastDetectAF} == 1 and $$self{AFInfo2Version} eq "0101"', + Format => 'int16u', + RawConv => '$val ? $val : undef', + }, + 0x52 => { + Name => 'ContrastDetectAFInFocus', + Condition => '$$self{ContrastDetectAF} == 1 and $$self{AFInfo2Version} eq "0101"', + PrintConv => { 0 => 'No', 1 => 'Yes' }, + }, +); + +# Nikon AF fine-tune information (ref 28) +%Image::ExifTool::Nikon::AFTune = ( + %binaryDataAttrs, + GROUPS => { 0 => 'MakerNotes', 2 => 'Camera' }, + 0 => { + Name => 'AFFineTune', + PrintConv => { + 0 => 'Off', + # (don't know what the difference between 1 and 2 is) + 1 => 'On (1)', + 2 => 'On (2)', + }, + }, + 1 => { + Name => 'AFFineTuneIndex', + Notes => 'index of saved lens', + PrintConv => '$val == 255 ? "n/a" : $val', + PrintConvInv => '$val eq "n/a" ? 255 : $val', + }, + 2 => { + Name => 'AFFineTuneAdj', + Priority => 0, # so other value takes priority if it exists + Notes => 'may only be valid for saved lenses', + Format => 'int8s', + PrintConv => '$val > 0 ? "+$val" : $val', + PrintConvInv => '$val', + }, +); + +# Nikon NEF processing information (ref forum6281) +%Image::ExifTool::Nikon::RetouchInfo = ( + %binaryDataAttrs, + FORMAT => 'int8s', + GROUPS => { 0 => 'MakerNotes', 2 => 'Camera' }, + DATAMEMBER => [ 0 ], + 0 => { + Name => 'RetouchInfoVersion', + Format => 'undef[4]', + Writable => 0, + RawConv => '$$self{RetouchInfoVersion} = $val', + }, + # 4 - RetouchExposureComp (+$val/6 or -$val/6?) + 5 => { + Name => 'RetouchNEFProcessing', + Condition => '$$self{RetouchInfoVersion} ge "0200"', + PrintConv => { + -1 => 'Off', + 1 => 'On', + }, + }, +); + +# Nikon File information - D60, D3 and D300 (ref PH) +%Image::ExifTool::Nikon::FileInfo = ( + %binaryDataAttrs, + GROUPS => { 0 => 'MakerNotes', 2 => 'Image' }, + FORMAT => 'int16u', + 0 => { + Name => 'FileInfoVersion', + Format => 'undef[4]', + Writable => 0, + }, + 2 => 'MemoryCardNumber', + 3 => { + Name => 'DirectoryNumber', + PrintConv => 'sprintf("%.3d", $val)', + PrintConvInv => '$val', + }, + 4 => { + Name => 'FileNumber', + PrintConv => 'sprintf("%.4d", $val)', + PrintConvInv => '$val', + }, +); + +# ref PH +%Image::ExifTool::Nikon::BarometerInfo = ( + %binaryDataAttrs, + GROUPS => { 0 => 'MakerNotes', 2 => 'Location' }, + 0 => { + Name => 'BarometerInfoVersion', + Format => 'undef[4]', + Writable => 0, + }, + 6 => { + Name => 'Altitude', + Format => 'int32s', + PrintConv => '"$val m"', # (always stored as metres) + PrintConvInv => '$val=~s/\s*m$//; $val', + }, + # 10: int16u - values: 0 (display in metres?), 18 (display in feet?) +); + +# ref PH +%Image::ExifTool::Nikon::CaptureOffsets = ( + PROCESS_PROC => \&ProcessNikonCaptureOffsets, + GROUPS => { 0 => 'MakerNotes', 2 => 'Camera' }, + 1 => 'IFD0_Offset', + 2 => 'PreviewIFD_Offset', + 3 => 'SubIFD_Offset', +); + +# ref PH (Written by capture NX) +%Image::ExifTool::Nikon::CaptureOutput = ( + %binaryDataAttrs, + FORMAT => 'int32u', + GROUPS => { 0 => 'MakerNotes', 2 => 'Image' }, + # 1 = 1 + 2 => 'OutputImageWidth', + 3 => 'OutputImageHeight', + 4 => 'OutputResolution', + # 5 = 1 +); + +# ref IB +%Image::ExifTool::Nikon::ColorBalanceA = ( + %binaryDataAttrs, + FORMAT => 'int16u', + GROUPS => { 0 => 'MakerNotes', 2 => 'Camera' }, + 624 => { #4 + Name => 'WB_RBLevels', + Notes => 'as shot', #IB + Format => 'int16u[2]', + Protected => 1, + }, + 626 => { + Name => 'WB_RBLevelsAuto', + Format => 'int16u[2]', + Protected => 1, + }, + 628 => { + Name => 'WB_RBLevelsDaylight', + Notes => 'red/blue levels for 0,+3,+2,+1,-1,-2,-3', + Format => 'int16u[14]', + Protected => 1, + }, + 642 => { + Name => 'WB_RBLevelsIncandescent', + Format => 'int16u[14]', + Protected => 1, + }, + 656 => { + Name => 'WB_RBLevelsFluorescent', + Format => 'int16u[6]', + Notes => 'red/blue levels for fluorescent W,N,D', + Protected => 1, + }, + 662 => { + Name => 'WB_RBLevelsCloudy', + Format => 'int16u[14]', + Protected => 1, + }, + 676 => { + Name => 'WB_RBLevelsFlash', + Format => 'int16u[14]', + Protected => 1, + }, + 690 => { + Name => 'WB_RBLevelsShade', + Condition => '$$self{Model} ne "E8700"', + Notes => 'not valid for E8700', + Format => 'int16u[14]', + Protected => 1, + }, +); + +my %nrwLevels = ( + Format => 'int32u[4]', + Protected => 1, + ValueConv => 'my @a=split " ",$val;$a[0]*=2;$a[3]*=2;"@a"', + ValueConvInv => 'my @a=split " ",$val;$a[0]/=2;$a[3]/=2;"@a"', +); + +# (ref IB) +%Image::ExifTool::Nikon::ColorBalanceB = ( + %binaryDataAttrs, + GROUPS => { 0 => 'MakerNotes', 2 => 'Camera' }, + NOTES => 'Color balance tags used by the P6000.', + 0x0004 => { + Name => 'ColorBalanceVersion', + Format => 'undef[4]', + }, + 0x13e8 => { Name => 'WB_RGGBLevels', %nrwLevels }, + 0x13f8 => { Name => 'WB_RGGBLevelsDaylight', %nrwLevels }, + 0x1408 => { Name => 'WB_RGGBLevelsCloudy', %nrwLevels }, + 0x1428 => { Name => 'WB_RGGBLevelsTungsten', %nrwLevels }, + 0x1438 => { Name => 'WB_RGGBLevelsFluorescentW',%nrwLevels }, + 0x1448 => { Name => 'WB_RGGBLevelsFlash', %nrwLevels }, + 0x1468 => { Name => 'WB_RGGBLevelsCustom', %nrwLevels, Notes => 'all zero if preset WB not used' }, + 0x1478 => { Name => 'WB_RGGBLevelsAuto', %nrwLevels }, +); + +# (ref IB) +%Image::ExifTool::Nikon::ColorBalanceC = ( + %binaryDataAttrs, + GROUPS => { 0 => 'MakerNotes', 2 => 'Camera' }, + DATAMEMBER => [ 4 ], + NOTES => 'Color balance tags used by the P1000, P7000, P7100 and B700.', + 0x0004 => { + Name => 'ColorBalanceVersion', + Format => 'undef[4]', + RawConv => '$$self{ColorBalanceVersion} = $val', + }, + 0x0020 => { Name => 'BlackLevel', Format => 'int16u' }, + 0x0038 => { Name => 'WB_RGGBLevels', %nrwLevels }, + 0x004c => { Name => 'WB_RGGBLevelsDaylight', %nrwLevels }, + 0x0060 => { Name => 'WB_RGGBLevelsCloudy', %nrwLevels }, + 0x0074 => { + Name => 'WB_RGGBLevelsShade', + Condition => '$$self{ColorBalanceVersion} ge "0104"', + Notes => 'valid only for some models', + %nrwLevels, + }, + 0x0088 => { Name => 'WB_RGGBLevelsTungsten', %nrwLevels }, + 0x009c => { Name => 'WB_RGGBLevelsFluorescentW',%nrwLevels }, + 0x00b0 => { Name => 'WB_RGGBLevelsFluorescentN',%nrwLevels }, + 0x00c4 => { Name => 'WB_RGGBLevelsFluorescentD',%nrwLevels }, + 0x00d8 => { Name => 'WB_RGGBLevelsHTMercury', %nrwLevels }, + 0x0100 => { Name => 'WB_RGGBLevelsCustom', %nrwLevels, Notes => 'all zero if preset WB not used' }, + 0x0114 => { Name => 'WB_RGGBLevelsAuto', %nrwLevels }, +); + +# ref 4 +%Image::ExifTool::Nikon::ColorBalance1 = ( + %binaryDataAttrs, + FORMAT => 'int16u', + GROUPS => { 0 => 'MakerNotes', 2 => 'Camera' }, + 0 => { + Name => 'WB_RBGGLevels', + Format => 'int16u[4]', + Protected => 1, + }, +); + +# ref 4 +%Image::ExifTool::Nikon::ColorBalance2 = ( + %binaryDataAttrs, + FORMAT => 'int16u', + GROUPS => { 0 => 'MakerNotes', 2 => 'Camera' }, + NOTES => 'This information is encrypted for most camera models.', + 0 => { + Name => 'WB_RGGBLevels', + Format => 'int16u[4]', + Protected => 1, + }, +); + +# ref 4 +%Image::ExifTool::Nikon::ColorBalance3 = ( + %binaryDataAttrs, + FORMAT => 'int16u', + GROUPS => { 0 => 'MakerNotes', 2 => 'Camera' }, + 0 => { + Name => 'WB_RGBGLevels', + Format => 'int16u[4]', + Protected => 1, + }, +); + +# ref 4 +%Image::ExifTool::Nikon::ColorBalance4 = ( + %binaryDataAttrs, + FORMAT => 'int16u', + GROUPS => { 0 => 'MakerNotes', 2 => 'Camera' }, + 0 => { + Name => 'WB_GRBGLevels', + Format => 'int16u[4]', + Protected => 1, + }, +); + +%Image::ExifTool::Nikon::ColorBalanceUnknown = ( + %binaryDataAttrs, + GROUPS => { 0 => 'MakerNotes', 2 => 'Camera' }, + 0 => { + Name => 'ColorBalanceVersion', + Format => 'undef[4]', + }, +); + +%Image::ExifTool::Nikon::Type2 = ( + WRITE_PROC => \&Image::ExifTool::Exif::WriteExif, + CHECK_PROC => \&Image::ExifTool::Exif::CheckExif, + WRITABLE => 1, + GROUPS => { 0 => 'MakerNotes', 2 => 'Camera' }, + 0x0003 => 'Quality', + 0x0004 => 'ColorMode', + 0x0005 => 'ImageAdjustment', + 0x0006 => 'CCDSensitivity', + 0x0007 => 'WhiteBalance', + 0x0008 => 'Focus', + 0x000A => 'DigitalZoom', + 0x000B => 'Converter', +); + +# these are standard EXIF tags, but they are duplicated here so we can +# set the family 0 group to 'MakerNotes' and set the MINOR_ERRORS flag +%Image::ExifTool::Nikon::PreviewIFD = ( + WRITE_PROC => \&Image::ExifTool::Exif::WriteExif, + CHECK_PROC => \&Image::ExifTool::Exif::CheckExif, + GROUPS => { 0 => 'MakerNotes', 1 => 'PreviewIFD', 2 => 'Image'}, + VARS => { MINOR_ERRORS => 1 }, # this IFD is non-essential and often corrupted + # (these tags are priority 0 by default because PreviewIFD is flagged in LOW_PRIORITY_DIR) + 0xfe => { # (not used by Nikon, but SRW images also use this table) + Name => 'SubfileType', + DataMember => 'SubfileType', + RawConv => '$$self{SubfileType} = $val', + PrintConv => \%Image::ExifTool::Exif::subfileType, + }, + 0x103 => { + Name => 'Compression', + SeparateTable => 'EXIF Compression', + PrintConv => \%Image::ExifTool::Exif::compression, + }, + 0x11a => 'XResolution', + 0x11b => 'YResolution', + 0x128 => { + Name => 'ResolutionUnit', + PrintConv => { + 1 => 'None', + 2 => 'inches', + 3 => 'cm', + }, + }, + 0x201 => { + Name => 'PreviewImageStart', + Flags => [ 'IsOffset', 'Permanent' ], + OffsetPair => 0x202, + DataTag => 'PreviewImage', + Writable => 'int32u', + WriteGroup => 'MakerNotes', + Protected => 2, + }, + 0x202 => { + Name => 'PreviewImageLength', + Flags => 'Permanent' , + OffsetPair => 0x201, + DataTag => 'PreviewImage', + Writable => 'int32u', + WriteGroup => 'MakerNotes', + Protected => 2, + }, + 0x213 => { + Name => 'YCbCrPositioning', + PrintConv => { + 1 => 'Centered', + 2 => 'Co-sited', + }, + }, +); + +# these are duplicated enough times to make it worthwhile to define them centrally +my %nikonApertureConversions = ( + ValueConv => '2**($val/24)', + ValueConvInv => '$val>0 ? 24*log($val)/log(2) : 0', + PrintConv => 'sprintf("%.1f",$val)', + PrintConvInv => '$val', +); + +my %nikonFocalConversions = ( + ValueConv => '5 * 2**($val/24)', + ValueConvInv => '$val>0 ? 24*log($val/5)/log(2) : 0', + PrintConv => 'sprintf("%.1f mm",$val)', + PrintConvInv => '$val=~s/\s*mm$//;$val', +); + +# Version 100 Nikon lens data +%Image::ExifTool::Nikon::LensData00 = ( + %binaryDataAttrs, + NOTES => 'This structure is used by the D100, and D1X with firmware version 1.1.', + GROUPS => { 0 => 'MakerNotes', 2 => 'Camera' }, + # NOTE: Must set ByteOrder in SubDirectory if any multi-byte integer tags added + 0x00 => { + Name => 'LensDataVersion', + Format => 'undef[4]', + Writable => 0, + }, + 0x06 => { #8 + Name => 'LensIDNumber', + Notes => 'see LensID values below', + }, + 0x07 => { #8 + Name => 'LensFStops', + ValueConv => '$val / 12', + ValueConvInv => '$val * 12', + PrintConv => 'sprintf("%.2f", $val)', + PrintConvInv => '$val', + }, + 0x08 => { #8/9 + Name => 'MinFocalLength', + %nikonFocalConversions, + }, + 0x09 => { #8/9 + Name => 'MaxFocalLength', + %nikonFocalConversions, + }, + 0x0a => { #8 + Name => 'MaxApertureAtMinFocal', + %nikonApertureConversions, + }, + 0x0b => { #8 + Name => 'MaxApertureAtMaxFocal', + %nikonApertureConversions, + }, + 0x0c => 'MCUVersion', #8 (MCU = Micro Controller Unit) +); + +# Nikon lens data (note: needs decrypting if LensDataVersion is 020x) +%Image::ExifTool::Nikon::LensData01 = ( + %binaryDataAttrs, + NOTES => q{ + Nikon encrypts the LensData information below if LensDataVersion is 0201 or + higher, but the decryption algorithm is known so the information can be + extracted. + }, + GROUPS => { 0 => 'MakerNotes', 2 => 'Camera' }, + # NOTE: Must set ByteOrder in SubDirectory if any multi-byte integer tags added + 0x00 => { + Name => 'LensDataVersion', + Format => 'string[4]', + Writable => 0, + }, + 0x04 => { #8 + Name => 'ExitPupilPosition', + ValueConv => '$val ? 2048 / $val : $val', + ValueConvInv => '$val ? 2048 / $val : $val', + PrintConv => 'sprintf("%.1f mm",$val)', + PrintConvInv => '$val=~s/\s*mm$//; $val', + }, + 0x05 => { #8 + Name => 'AFAperture', + %nikonApertureConversions, + }, + 0x08 => { #8 + # this seems to be 2 values: the upper nibble gives the far focus + # range and the lower nibble gives the near focus range. The values + # are in the range 1-N, where N is lens-dependent. A value of 0 for + # the far focus range indicates infinity. (ref JD) + Name => 'FocusPosition', + PrintConv => 'sprintf("0x%02x", $val)', + PrintConvInv => '$val', + }, + 0x09 => { #8/9 + # With older AF lenses this does not work... (ref 13) + # eg) AF Nikkor 50mm f/1.4 => 48 (0x30) + # AF Zoom-Nikkor 35-105mm f/3.5-4.5 => @35mm => 15 (0x0f), @105mm => 141 (0x8d) + Notes => 'this focus distance is approximate, and not very accurate for some lenses', + Name => 'FocusDistance', + ValueConv => '0.01 * 10**($val/40)', # in m + ValueConvInv => '$val>0 ? 40*log($val*100)/log(10) : 0', + PrintConv => '$val ? sprintf("%.2f m",$val) : "inf"', + PrintConvInv => '$val eq "inf" ? 0 : $val =~ s/\s*m$//, $val', + }, + 0x0a => { #8/9 + Name => 'FocalLength', + Priority => 0, + %nikonFocalConversions, + }, + 0x0b => { #8 + Name => 'LensIDNumber', + Notes => 'see LensID values below', + }, + 0x0c => { #8 + Name => 'LensFStops', + ValueConv => '$val / 12', + ValueConvInv => '$val * 12', + PrintConv => 'sprintf("%.2f", $val)', + PrintConvInv => '$val', + }, + 0x0d => { #8/9 + Name => 'MinFocalLength', + %nikonFocalConversions, + }, + 0x0e => { #8/9 + Name => 'MaxFocalLength', + %nikonFocalConversions, + }, + 0x0f => { #8 + Name => 'MaxApertureAtMinFocal', + %nikonApertureConversions, + }, + 0x10 => { #8 + Name => 'MaxApertureAtMaxFocal', + %nikonApertureConversions, + }, + 0x11 => 'MCUVersion', #8 (MCU = Micro Controller Unit) + 0x12 => { #8 + Name => 'EffectiveMaxAperture', + %nikonApertureConversions, + }, +); + +# Nikon lens data (note: needs decrypting) +%Image::ExifTool::Nikon::LensData0204 = ( + %binaryDataAttrs, + NOTES => q{ + Nikon encrypts the LensData information below if LensDataVersion is 0201 or + higher, but the decryption algorithm is known so the information can be + extracted. + }, + GROUPS => { 0 => 'MakerNotes', 2 => 'Camera' }, + # NOTE: Must set ByteOrder in SubDirectory if any multi-byte integer tags added + 0x00 => { + Name => 'LensDataVersion', + Format => 'string[4]', + Writable => 0, + }, + 0x04 => { #8 + Name => 'ExitPupilPosition', + ValueConv => '$val ? 2048 / $val : $val', + ValueConvInv => '$val ? 2048 / $val : $val', + PrintConv => 'sprintf("%.1f mm",$val)', + PrintConvInv => '$val=~s/\s*mm$//; $val', + }, + 0x05 => { #8 + Name => 'AFAperture', + %nikonApertureConversions, + }, + 0x08 => { #8 + # this seems to be 2 values: the upper nibble gives the far focus + # range and the lower nibble gives the near focus range. The values + # are in the range 1-N, where N is lens-dependent. A value of 0 for + # the far focus range indicates infinity. (ref JD) + Name => 'FocusPosition', + PrintConv => 'sprintf("0x%02x", $val)', + PrintConvInv => '$val', + }, + # --> extra byte at position 0x09 in this version of LensData (PH) + 0x0a => { #8/9 + # With older AF lenses this does not work... (ref 13) + # eg) AF Nikkor 50mm f/1.4 => 48 (0x30) + # AF Zoom-Nikkor 35-105mm f/3.5-4.5 => @35mm => 15 (0x0f), @105mm => 141 (0x8d) + Notes => 'this focus distance is approximate, and not very accurate for some lenses', + Name => 'FocusDistance', + ValueConv => '0.01 * 10**($val/40)', # in m + ValueConvInv => '$val>0 ? 40*log($val*100)/log(10) : 0', + PrintConv => '$val ? sprintf("%.2f m",$val) : "inf"', + PrintConvInv => '$val eq "inf" ? 0 : $val =~ s/\s*m$//, $val', + }, + 0x0b => { #8/9 + Name => 'FocalLength', + Priority => 0, + %nikonFocalConversions, + }, + 0x0c => { #8 + Name => 'LensIDNumber', + Notes => 'see LensID values below', + }, + 0x0d => { #8 + Name => 'LensFStops', + ValueConv => '$val / 12', + ValueConvInv => '$val * 12', + PrintConv => 'sprintf("%.2f", $val)', + PrintConvInv => '$val', + }, + 0x0e => { #8/9 + Name => 'MinFocalLength', + %nikonFocalConversions, + }, + 0x0f => { #8/9 + Name => 'MaxFocalLength', + %nikonFocalConversions, + }, + 0x10 => { #8 + Name => 'MaxApertureAtMinFocal', + %nikonApertureConversions, + }, + 0x11 => { #8 + Name => 'MaxApertureAtMaxFocal', + %nikonApertureConversions, + }, + 0x12 => 'MCUVersion', #8 (MCU = Micro Controller Unit) + 0x13 => { #8 + Name => 'EffectiveMaxAperture', + %nikonApertureConversions, + }, +); + +# Nikon lens data version 0400 (note: needs decrypting) (ref PH) +%Image::ExifTool::Nikon::LensData0400 = ( + %binaryDataAttrs, + GROUPS => { 0 => 'MakerNotes', 2 => 'Camera' }, + NOTES => 'Tags extracted from the encrypted lens data of the Nikon 1J1/1V1/1J2.', + 0x00 => { + Name => 'LensDataVersion', + Format => 'string[4]', + Writable => 0, + }, + 0x18a => { #PH + Name => 'LensModel', + Format => 'string[64]', + }, +); + +# Nikon lens data version 0402 (note: needs decrypting) (ref PH) +%Image::ExifTool::Nikon::LensData0402 = ( + %binaryDataAttrs, + GROUPS => { 0 => 'MakerNotes', 2 => 'Camera' }, + NOTES => 'Tags extracted from the encrypted lens data of the Nikon 1J3/1S1/1V2.', + 0x00 => { + Name => 'LensDataVersion', + Format => 'string[4]', + Writable => 0, + }, + 0x18b => { #PH + Name => 'LensModel', + Format => 'string[64]', + }, +); + +# Nikon lens data version 0403 (note: needs decrypting) (ref PH) +%Image::ExifTool::Nikon::LensData0403 = ( + %binaryDataAttrs, + GROUPS => { 0 => 'MakerNotes', 2 => 'Camera' }, + NOTES => 'Tags extracted from the encrypted lens data of the Nikon 1J4/1J5.', + 0x00 => { + Name => 'LensDataVersion', + Format => 'string[4]', + Writable => 0, + }, + 0x2ac => { #PH + Name => 'LensModel', + Format => 'string[64]', + }, +); + +# Nikon Z lens data (note: needs decrypting) (ref PH, based on LensData0204) +%Image::ExifTool::Nikon::LensData0800 = ( + %binaryDataAttrs, + NOTES => 'Tags found in the encrypted LensData from cameras such as the Z6 and Z7.', + GROUPS => { 0 => 'MakerNotes', 2 => 'Camera' }, + DATAMEMBER => [ 0x03, 0x2f ], + 0x00 => { + Name => 'LensDataVersion', + Format => 'string[4]', + Writable => 0, + }, + 0x03 => { # look forward to see if new old data exists... + Name => 'OldLensData', + Format => 'undef[17]', + RawConv => '$$self{OldLensData} = 1 unless $val =~ /^.\0+$/s; undef', + Hidden => 1, + }, + 0x04 => { + Name => 'ExitPupilPosition', + Condition => '$$self{OldLensData}', + ValueConv => '$val ? 2048 / $val : $val', + ValueConvInv => '$val ? 2048 / $val : $val', + PrintConv => 'sprintf("%.1f mm",$val)', + PrintConvInv => '$val=~s/\s*mm$//; $val', + }, + 0x05 => { + Name => 'AFAperture', + Condition => '$$self{OldLensData}', + %nikonApertureConversions, + }, + # --> another extra byte at position 0x08 in this version of LensData (PH) + 0x09 => { + Name => 'FocusPosition', + Condition => '$$self{OldLensData}', + PrintConv => 'sprintf("0x%02x", $val)', + PrintConvInv => '$val', + }, + 0x0b => { + Notes => 'this focus distance is approximate, and not very accurate for some lenses', + Name => 'FocusDistance', + Condition => '$$self{OldLensData}', + ValueConv => '0.01 * 10**($val/40)', # in m + ValueConvInv => '$val>0 ? 40*log($val*100)/log(10) : 0', + PrintConv => '$val ? sprintf("%.2f m",$val) : "inf"', + PrintConvInv => '$val eq "inf" ? 0 : $val =~ s/\s*m$//, $val', + }, + 0x0c => { + Name => 'FocalLength', + Condition => '$$self{OldLensData}', + Priority => 0, + %nikonFocalConversions, + }, + 0x0d => { + Name => 'LensIDNumber', + Condition => '$$self{OldLensData}', + Notes => 'see LensID values below', + }, + 0x0e => { + Name => 'LensFStops', + Condition => '$$self{OldLensData}', + ValueConv => '$val / 12', + ValueConvInv => '$val * 12', + PrintConv => 'sprintf("%.2f", $val)', + PrintConvInv => '$val', + }, + 0x0f => { + Name => 'MinFocalLength', + Condition => '$$self{OldLensData}', + %nikonFocalConversions, + }, + 0x10 => { + Name => 'MaxFocalLength', + Condition => '$$self{OldLensData}', + %nikonFocalConversions, + }, + 0x11 => { + Name => 'MaxApertureAtMinFocal', + Condition => '$$self{OldLensData}', + %nikonApertureConversions, + }, + 0x12 => { + Name => 'MaxApertureAtMaxFocal', + Condition => '$$self{OldLensData}', + %nikonApertureConversions, + }, + 0x13 => { + Name => 'MCUVersion', + Condition => '$$self{OldLensData}', + }, + 0x14 => { + Name => 'EffectiveMaxAperture', + Condition => '$$self{OldLensData}', + %nikonApertureConversions, + }, +# +# ---- new LensData tags used by Nikkor Z lenses ---- (ref PH) +# + 0x2f => { # look forward to see if new lens data exists... + Name => 'NewLensData', + Format => 'undef[17]', + RawConv => '$$self{NewLensData} = 1 unless $val =~ /^.\0+$/s; undef', + Hidden => 1, + }, + #0x30 => { + # Name => 'LensID', ? (NC) + # Condition => '$$self{NewLensData}', + # Format => 'int16u', + # PrintConv => { + # 1 => 'Nikkor Z 24-70mm f/4 S', + # 4 => 'Nikkor Z 35mm f/1.8 S', + # 9 => 'Nikkor Z 50mm f/1.8 S', + # }, + #}, + 0x36 => { + Name => 'MaxAperture', + Condition => '$$self{NewLensData}', + Format => 'int16u', + Priority => 0, + ValueConv => '2**($val/384-1)', + ValueConvInv => '384*(log($val)/log(2)+1)', + PrintConv => 'sprintf("%.1f",$val)', + PrintConvInv => '$val', + }, + 0x38 => { + Name => 'FNumber', + Condition => '$$self{NewLensData}', + Format => 'int16u', + Priority => 0, + ValueConv => '2**($val/384-1)', + ValueConvInv => '384*(log($val)/log(2)+1)', + PrintConv => 'sprintf("%.1f",$val)', + PrintConvInv => '$val', + }, + 0x3c => { + Name => 'FocalLength', + Condition => '$$self{NewLensData}', + Format => 'int16u', + Priority => 0, + PrintConv => '"$val mm"', + PrintConvInv => '$val=~s/\s*mm$//;$val', + }, +); + +# Unknown Nikon lens data (note: data may need decrypting after byte 4) +%Image::ExifTool::Nikon::LensDataUnknown = ( + PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData, + FIRST_ENTRY => 0, + GROUPS => { 0 => 'MakerNotes', 2 => 'Camera' }, + 0x00 => { + Name => 'LensDataVersion', + Format => 'string[4]', + }, +); + +# shot information (encrypted in some cameras) - ref 18 +%Image::ExifTool::Nikon::ShotInfo = ( + %binaryDataAttrs, + GROUPS => { 0 => 'MakerNotes', 2 => 'Camera' }, + DATAMEMBER => [ 0 ], + NOTES => q{ + This information is encrypted for ShotInfoVersion 02xx, and some tags are + only valid for specific models. + }, + 0x00 => { + Name => 'ShotInfoVersion', + Format => 'string[4]', + Writable => 0, + RawConv => '$$self{ShotInfoVersion} = $val; $val =~ /^\d+$/ ? $val : undef', + }, + 0x04 => { + Name => 'FirmwareVersion', + Format => 'string[5]', + Writable => 0, + RawConv => '$val =~ /^\d\.\d+.$/ ? $val : undef', + }, + 0x10 => { + Name => 'DistortionControl', + Condition => '$$self{Model} =~ /P6000\b/', + Notes => 'P6000', + PrintConv => \%offOn, + }, + 0x66 => { + Name => 'VR_0x66', + Condition => '$$self{ShotInfoVersion} eq "0204"', + Format => 'int8u', + Unknown => 1, + Notes => 'D2X, D2Xs (unverified)', + PrintConv => { + 0 => 'Off', + 1 => 'On (normal)', + 2 => 'On (active)', + }, + }, + # 6a, 6e not correct for 0103 (D70), 0207 (D200) + 0x6a => { + Name => 'ShutterCount', + Condition => '$$self{ShotInfoVersion} eq "0204"', + Format => 'int32u', + Priority => 0, + Notes => 'D2X, D2Xs', + }, + 0x6e => { + Name => 'DeletedImageCount', + Condition => '$$self{ShotInfoVersion} eq "0204"', + Format => 'int32u', + Priority => 0, + Notes => 'D2X, D2Xs', + }, + 0x75 => { #JD + Name => 'VibrationReduction', + Condition => '$$self{ShotInfoVersion} eq "0207"', + Format => 'int8u', + Notes => 'D200', + PrintConv => { + 0 => 'Off', + # (not sure what the different values represent, but values + # of 1 and 2 have even been observed for non-VR lenses!) + 1 => 'On (1)', #PH + 2 => 'On (2)', #PH + 3 => 'On (3)', #PH (rare -- only seen once) + }, + }, + 0x82 => { # educated guess, needs verification + Name => 'VibrationReduction', + Condition => '$$self{ShotInfoVersion} eq "0204"', + Format => 'int8u', + Notes => 'D2X, D2Xs', + PrintConv => { + 0 => 'Off', + 1 => 'On', + }, + }, + # 0xac - int16u[600] TiffMeteringImage1: 30x20 image (ShotInfoVersion 0800, ref JR) + 0x157 => { #JD + Name => 'ShutterCount', + Condition => '$$self{ShotInfoVersion} eq "0205"', + Format => 'undef[2]', + Priority => 0, + Notes => 'D50', + # treat as a 2-byte big-endian integer + ValueConv => 'unpack("n", $val)', + ValueConvInv => 'pack("n",$val)', + }, + 0x1ae => { #JD + Name => 'VibrationReduction', + Condition => '$$self{ShotInfoVersion} eq "0205"', + Format => 'int8u', + Notes => 'D50', + PrintHex => 1, + PrintConv => { + 0x00 => 'n/a', + 0x0c => 'Off', + 0x0f => 'On', + }, + }, + 0x24d => { #PH + Name => 'ShutterCount', + Condition => '$$self{ShotInfoVersion} eq "0211"', + Notes => 'D60', + Format => 'int32u', + Priority => 0, + }, + # note: DecryptLen currently set to 0x251 + + # 0x55c - int16u[2400] TiffMeteringImage2: 60x40 image (ShotInfoVersion 0800, ref JR) + # 0x181c - int16u[1200] TiffMeteringImage?: 60x20 image for some NEF's (ShotInfoVersion 0800, ref JR) + # 0x217c - int16u[2400] TiffMeteringImage3: 60x40 image (ShotInfoVersion 0800, ref JR) + # 0x3d9c - int16u[2400] TiffMeteringImage4: 60x40 image (ShotInfoVersion 0800, ref JR) + # 0x59c0 - TiffMeteringImageWidth (ShotInfoVersion 0800, ref JR) + # 0x59c2 - TiffMeteringImageHeight (ShotInfoVersion 0800, ref JR) + # 0x59c4 - int16u[1800] TiffMeteringImage5: 30x20 RGB image (ShotInfoVersion 0800, ref JR) +); + +# shot information for D40 and D40X (encrypted) - ref PH +%Image::ExifTool::Nikon::ShotInfoD40 = ( + PROCESS_PROC => \&Image::ExifTool::Nikon::ProcessNikonEncrypted, + WRITE_PROC => \&Image::ExifTool::Nikon::ProcessNikonEncrypted, + CHECK_PROC => \&Image::ExifTool::CheckBinaryData, + VARS => { ID_LABEL => 'Index' }, + IS_SUBDIR => [ 729 ], + WRITABLE => 1, + FIRST_ENTRY => 0, + GROUPS => { 0 => 'MakerNotes', 2 => 'Camera' }, + NOTES => 'These tags are extracted from encrypted data in D40 and D40X images.', + 0x00 => { + Name => 'ShotInfoVersion', + Format => 'string[4]', + Writable => 0, + }, + 582 => { + Name => 'ShutterCount', + Format => 'int32u', + Priority => 0, + }, + 586.1 => { #JD + Name => 'VibrationReduction', + Mask => 0x08, + PrintConv => { 0 => 'Off', 1 => 'On' }, + }, + 729 => { #JD + Name => 'CustomSettingsD40', + Format => 'undef[12]', + SubDirectory => { + TagTable => 'Image::ExifTool::NikonCustom::SettingsD40', + }, + }, + # note: DecryptLen currently set to 748 +); + +# shot information for D80 (encrypted) - ref JD +%Image::ExifTool::Nikon::ShotInfoD80 = ( + PROCESS_PROC => \&Image::ExifTool::Nikon::ProcessNikonEncrypted, + WRITE_PROC => \&Image::ExifTool::Nikon::ProcessNikonEncrypted, + CHECK_PROC => \&Image::ExifTool::CheckBinaryData, + VARS => { ID_LABEL => 'Index' }, + IS_SUBDIR => [ 748 ], + WRITABLE => 1, + FIRST_ENTRY => 0, + GROUPS => { 0 => 'MakerNotes', 2 => 'Camera' }, + NOTES => 'These tags are extracted from encrypted data in D80 images.', + 0x00 => { + Name => 'ShotInfoVersion', + Format => 'string[4]', + Writable => 0, + }, + 586 => { + Name => 'ShutterCount', + Format => 'int32u', + Priority => 0, + }, + # split 590 into a few different tags + 590.1 => { + Name => 'Rotation', + Mask => 0x07, + PrintConv => { + 0 => 'Horizontal', + 1 => 'Rotate 270 CW', + 2 => 'Rotate 90 CW', + 3 => 'Rotate 180', + }, + }, + 590.2 => { + Name => 'VibrationReduction', + Mask => 0x18, + PrintConv => { + 0 => 'Off', + 3 => 'On', + }, + }, + 590.3 => { + Name => 'FlashFired', + Mask => 0xe0, + PrintConv => { BITMASK => { + 1 => 'Internal', + 2 => 'External', + }}, + }, + 708 => { + Name => 'NikonImageSize', + Mask => 0xf0, + PrintConv => { + 0 => 'Large (10.0 M)', + 1 => 'Medium (5.6 M)', + 2 => 'Small (2.5 M)', + }, + }, + 708.1 => { + Name => 'ImageQuality', + Mask => 0x0f, + PrintConv => { + 0 => 'NEF (RAW)', + 1 => 'JPEG Fine', + 2 => 'JPEG Normal', + 3 => 'JPEG Basic', + 4 => 'NEF (RAW) + JPEG Fine', + 5 => 'NEF (RAW) + JPEG Normal', + 6 => 'NEF (RAW) + JPEG Basic', + }, + }, + 748 => { #JD + Name => 'CustomSettingsD80', + Format => 'undef[17]', + SubDirectory => { + TagTable => 'Image::ExifTool::NikonCustom::SettingsD80', + }, + }, + # note: DecryptLen currently set to 765 +); + +# shot information for D90 (encrypted) - ref PH +%Image::ExifTool::Nikon::ShotInfoD90 = ( + PROCESS_PROC => \&Image::ExifTool::Nikon::ProcessNikonEncrypted, + WRITE_PROC => \&Image::ExifTool::Nikon::ProcessNikonEncrypted, + CHECK_PROC => \&Image::ExifTool::CheckBinaryData, + VARS => { ID_LABEL => 'Index' }, + IS_SUBDIR => [ 0x374 ], + WRITABLE => 1, + FIRST_ENTRY => 0, + GROUPS => { 0 => 'MakerNotes', 2 => 'Camera' }, + NOTES => q{ + These tags are extracted from encrypted data in images from the D90 with + firmware 1.00. + }, + 0x00 => { + Name => 'ShotInfoVersion', + Format => 'string[4]', + Writable => 0, + }, + 0x04 => { + Name => 'FirmwareVersion', + Format => 'string[5]', + Writable => 0, + }, + 0x2b5 => { #JD (same value found at offset 0x39, 0x2bf, 0x346) + Name => 'ISO2', + ValueConv => '100*exp(($val/12-5)*log(2))', + ValueConvInv => '(log($val/100)/log(2)+5)*12', + PrintConv => 'int($val + 0.5)', + PrintConvInv => '$val', + }, + 0x2d5 => { + Name => 'ShutterCount', + Format => 'int32u', + Priority => 0, + }, + 0x374 => { + Name => 'CustomSettingsD90', + Format => 'undef[36]', + SubDirectory => { + TagTable => 'Image::ExifTool::NikonCustom::SettingsD90', + }, + }, + # note: DecryptLen currently set to 0x398 +); + +# shot information for the D3 firmware 0.37 and 1.00 (encrypted) - ref PH +%Image::ExifTool::Nikon::ShotInfoD3a = ( + PROCESS_PROC => \&Image::ExifTool::Nikon::ProcessNikonEncrypted, + WRITE_PROC => \&Image::ExifTool::Nikon::ProcessNikonEncrypted, + CHECK_PROC => \&Image::ExifTool::CheckBinaryData, + VARS => { ID_LABEL => 'Index' }, + IS_SUBDIR => [ 0x301 ], + WRITABLE => 1, + FIRST_ENTRY => 0, + GROUPS => { 0 => 'MakerNotes', 2 => 'Camera' }, + NOTES => q{ + These tags are extracted from encrypted data in images from the D3 with + firmware 1.00 and earlier. + }, + 0x00 => { + Name => 'ShotInfoVersion', + Format => 'string[4]', + Writable => 0, + }, + 0x256 => { #JD (same value found at offset 0x26b) + Name => 'ISO2', + ValueConv => '100*exp(($val/12-5)*log(2))', + ValueConvInv => '(log($val/100)/log(2)+5)*12', + PrintConv => 'int($val + 0.5)', + PrintConvInv => '$val', + }, + 0x276 => { #JD + Name => 'ShutterCount', + Format => 'int32u', + Priority => 0, + }, + 723.1 => { + Name => 'NikonImageSize', + Mask => 0x18, + PrintConv => { + 0 => 'Large', + 1 => 'Medium', + 2 => 'Small', + }, + }, + 723.2 => { + Name => 'ImageQuality', + Mask => 0x07, + PrintConv => { + 0 => 'NEF (RAW) + JPEG Fine', + 1 => 'NEF (RAW) + JPEG Norm', + 2 => 'NEF (RAW) + JPEG Basic', + 3 => 'NEF (RAW)', + 4 => 'TIF (RGB)', + 5 => 'JPEG Fine', + 6 => 'JPEG Normal', + 7 => 'JPEG Basic', + }, + }, + 0x301 => { #(NC) + Name => 'CustomSettingsD3', + Format => 'undef[24]', + SubDirectory => { + TagTable => 'Image::ExifTool::NikonCustom::SettingsD3', + }, + }, + # note: DecryptLen currently set to 0x318 +); + +# shot information for the D3 firmware 1.10, 2.00 and 2.01 (encrypted) - ref PH +%Image::ExifTool::Nikon::ShotInfoD3b = ( + PROCESS_PROC => \&Image::ExifTool::Nikon::ProcessNikonEncrypted, + WRITE_PROC => \&Image::ExifTool::Nikon::ProcessNikonEncrypted, + CHECK_PROC => \&Image::ExifTool::CheckBinaryData, + VARS => { ID_LABEL => 'Index' }, + IS_SUBDIR => [ 0x30a ], + WRITABLE => 1, + FIRST_ENTRY => 0, + GROUPS => { 0 => 'MakerNotes', 2 => 'Camera' }, + DATAMEMBER => [ 4 ], + NOTES => q{ + These tags are extracted from encrypted data in images from the D3 with + firmware 1.10, 2.00, 2.01 and 2.02. + }, + 0x00 => { + Name => 'ShotInfoVersion', + Format => 'string[4]', + Writable => 0, + }, + 0x04 => { + Name => 'FirmwareVersion', + Format => 'string[5]', + Writable => 0, + RawConv => '$$self{FirmwareVersion} = $val', + }, + 0x10 => { #28 + Name => 'ImageArea', + PrintConv => { + 0 => 'FX (36.0 x 23.9 mm)', + 1 => 'DX (23.5 x 15.6 mm)', + 2 => '5:4 (30.0 x 23.9 mm)', + }, + }, + 0x25d => { + Name => 'ISO2', + ValueConv => '100*exp(($val/12-5)*log(2))', + ValueConvInv => '(log($val/100)/log(2)+5)*12', + PrintConv => 'int($val + 0.5)', + PrintConvInv => '$val', + }, + 0x27d => { + Name => 'ShutterCount', + Condition => '$$self{FirmwareVersion} =~ /^1.01/', + Notes => 'firmware 1.10', + Format => 'int32u', + Priority => 0, + }, + 0x27f => { + Name => 'ShutterCount', + Condition => '$$self{FirmwareVersion} =~ /^2.0/', + Notes => 'firmware 2.00, 2.01 and 2.02', + Format => 'int32u', + Priority => 0, + }, + 732.1 => { #28 + Name => 'NikonImageSize', + Mask => 0x18, + PrintConv => { + 0 => 'Large', + 1 => 'Medium', + 2 => 'Small', + }, + }, + 732.2 => { #28 + Name => 'ImageQuality', + Mask => 0x07, + PrintConv => { + 0 => 'NEF (RAW) + JPEG Fine', + 1 => 'NEF (RAW) + JPEG Norm', + 2 => 'NEF (RAW) + JPEG Basic', + 3 => 'NEF (RAW)', + 4 => 'TIF (RGB)', + 5 => 'JPEG Fine', + 6 => 'JPEG Normal', + 7 => 'JPEG Basic', + }, + }, + 0x28a => { #28 + Name => 'PreFlashReturnStrength', + Notes => 'valid in TTL and TTL-BL flash control modes', + # this is used to set the flash power using this relationship + # for the SB-800 and SB-900: + # $val < 140 ? 2**(0.08372*$val-12.352) : $val + }, + 0x30a => { # tested with firmware 2.00 + Name => 'CustomSettingsD3', + Format => 'undef[24]', + SubDirectory => { + TagTable => 'Image::ExifTool::NikonCustom::SettingsD3', + }, + }, + # note: DecryptLen currently set to 0x321 +); + +# shot information for the D3X firmware 1.00 (encrypted) - ref PH +%Image::ExifTool::Nikon::ShotInfoD3X = ( + PROCESS_PROC => \&Image::ExifTool::Nikon::ProcessNikonEncrypted, + WRITE_PROC => \&Image::ExifTool::Nikon::ProcessNikonEncrypted, + CHECK_PROC => \&Image::ExifTool::CheckBinaryData, + VARS => { ID_LABEL => 'Index' }, + IS_SUBDIR => [ 0x30b ], + WRITABLE => 1, + FIRST_ENTRY => 0, + GROUPS => { 0 => 'MakerNotes', 2 => 'Camera' }, + NOTES => q{ + These tags are extracted from encrypted data in images from the D3X with + firmware 1.00. + }, + 0x00 => { + Name => 'ShotInfoVersion', + Format => 'string[4]', + Writable => 0, + }, + 0x04 => { + Name => 'FirmwareVersion', + Format => 'string[5]', + Writable => 0, + }, + 0x25d => { + Name => 'ISO2', + ValueConv => '100*exp(($val/12-5)*log(2))', + ValueConvInv => '(log($val/100)/log(2)+5)*12', + PrintConv => 'int($val + 0.5)', + PrintConvInv => '$val', + }, + 0x280 => { + Name => 'ShutterCount', + Format => 'int32u', + Priority => 0, + }, + 0x30b => { #(NC) + Name => 'CustomSettingsD3X', + Format => 'undef[24]', + SubDirectory => { + TagTable => 'Image::ExifTool::NikonCustom::SettingsD3', + }, + }, + # note: DecryptLen currently set to 0x323 +); + +# shot information for the D3S firmware 0.16 and 1.00 (encrypted) - ref PH +%Image::ExifTool::Nikon::ShotInfoD3S = ( + PROCESS_PROC => \&Image::ExifTool::Nikon::ProcessNikonEncrypted, + WRITE_PROC => \&Image::ExifTool::Nikon::ProcessNikonEncrypted, + CHECK_PROC => \&Image::ExifTool::CheckBinaryData, + VARS => { ID_LABEL => 'Index' }, + IS_SUBDIR => [ 0x2ce ], + WRITABLE => 1, + FIRST_ENTRY => 0, + GROUPS => { 0 => 'MakerNotes', 2 => 'Camera' }, + NOTES => q{ + These tags are extracted from encrypted data in images from the D3S with + firmware 1.00 and earlier. + }, + 0x00 => { + Name => 'ShotInfoVersion', + Format => 'string[4]', + Writable => 0, + }, + 0x04 => { + Name => 'FirmwareVersion', + Format => 'string[5]', + Writable => 0, + }, + 0x10 => { #28 + Name => 'ImageArea', + PrintConv => { + 0 => 'FX (36x24)', + 1 => 'DX (24x16)', + 2 => '5:4 (30x24)', + 3 => '1.2x (30x20)', + }, + }, + 0x221 => { + Name => 'ISO2', + ValueConv => '100*exp(($val/12-5)*log(2))', + ValueConvInv => '(log($val/100)/log(2)+5)*12', + PrintConv => 'int($val + 0.5)', + PrintConvInv => '$val', + }, + 0x242 => { + Name => 'ShutterCount', + Format => 'int32u', + Priority => 0, + }, + 0x2ce => { #(NC) + Name => 'CustomSettingsD3S', + Format => 'undef[27]', + SubDirectory => { + TagTable => 'Image::ExifTool::NikonCustom::SettingsD3', + }, + }, + # note: DecryptLen currently set to 0x2e9 +); + +# shot information for the D300 firmware 1.00 (encrypted) - ref JD +%Image::ExifTool::Nikon::ShotInfoD300a = ( + PROCESS_PROC => \&Image::ExifTool::Nikon::ProcessNikonEncrypted, + WRITE_PROC => \&Image::ExifTool::Nikon::ProcessNikonEncrypted, + CHECK_PROC => \&Image::ExifTool::CheckBinaryData, + VARS => { ID_LABEL => 'Index' }, + IS_SUBDIR => [ 790 ], + WRITABLE => 1, + FIRST_ENTRY => 0, + GROUPS => { 0 => 'MakerNotes', 2 => 'Camera' }, + NOTES => q{ + These tags are extracted from encrypted data in images from the D300 with + firmware 1.00 and earlier. + }, + 0x00 => { + Name => 'ShotInfoVersion', + Format => 'string[4]', + Writable => 0, + }, + 604 => { + Name => 'ISO2', + ValueConv => '100*exp(($val/12-5)*log(2))', + ValueConvInv => '(log($val/100)/log(2)+5)*12', + PrintConv => 'int($val + 0.5)', + PrintConvInv => '$val', + }, + 633 => { + Name => 'ShutterCount', + Format => 'int32u', + Priority => 0, + }, + 721 => { #PH + Name => 'AFFineTuneAdj', + Format => 'int16u', + PrintHex => 1, + PrintConvColumns => 3, + # thanks to Neil Nappe for the samples to decode this!... + # (have seen various unknown values here when flash is enabled, but + # these are yet to be decoded: 0x2e,0x619,0xd0d,0x103a,0x2029 - PH) + PrintConv => { + 0x403e => '+20', + 0x303e => '+19', + 0x203e => '+18', + 0x103e => '+17', + 0x003e => '+16', + 0xe03d => '+15', + 0xc03d => '+14', + 0xa03d => '+13', + 0x803d => '+12', + 0x603d => '+11', + 0x403d => '+10', + 0x203d => '+9', + 0x003d => '+8', + 0xc03c => '+7', + 0x803c => '+6', + 0x403c => '+5', + 0x003c => '+4', + 0x803b => '+3', + 0x003b => '+2', + 0x003a => '+1', + 0x0000 => '0', + 0x00c6 => '-1', + 0x00c5 => '-2', + 0x80c5 => '-3', + 0x00c4 => '-4', + 0x40c4 => '-5', + 0x80c4 => '-6', + 0xc0c4 => '-7', + 0x00c3 => '-8', + 0x20c3 => '-9', + 0x40c3 => '-10', + 0x60c3 => '-11', + 0x80c3 => '-12', + 0xa0c3 => '-13', + 0xc0c3 => '-14', + 0xe0c3 => '-15', + 0x00c2 => '-16', + 0x10c2 => '-17', + 0x20c2 => '-18', + 0x30c2 => '-19', + 0x40c2 => '-20', + }, + }, + 790 => { + Name => 'CustomSettingsD300', + Format => 'undef[24]', + SubDirectory => { + TagTable => 'Image::ExifTool::NikonCustom::SettingsD3', + }, + }, + # note: DecryptLen currently set to 813 +); + +# shot information for the D300 firmware 1.10 (encrypted) - ref PH +%Image::ExifTool::Nikon::ShotInfoD300b = ( + PROCESS_PROC => \&Image::ExifTool::Nikon::ProcessNikonEncrypted, + WRITE_PROC => \&Image::ExifTool::Nikon::ProcessNikonEncrypted, + CHECK_PROC => \&Image::ExifTool::CheckBinaryData, + VARS => { ID_LABEL => 'Index' }, + DATAMEMBER => [ 4 ], + IS_SUBDIR => [ 802 ], + WRITABLE => 1, + FIRST_ENTRY => 0, + GROUPS => { 0 => 'MakerNotes', 2 => 'Camera' }, + NOTES => q{ + These tags are extracted from encrypted data in images from the D300 with + firmware 1.10. + }, + 0x00 => { + Name => 'ShotInfoVersion', + Format => 'string[4]', + Writable => 0, + }, + 0x04 => { #PH + Name => 'FirmwareVersion', + DataMember => 'FirmwareVersion', + Format => 'string[5]', + Writable => 0, + RawConv => '$$self{FirmwareVersion} = $val', + }, + 613 => { + Name => 'ISO2', + ValueConv => '100*exp(($val/12-5)*log(2))', + ValueConvInv => '(log($val/100)/log(2)+5)*12', + PrintConv => 'int($val + 0.5)', + PrintConvInv => '$val', + }, + 644 => { + Name => 'ShutterCount', + Format => 'int32u', + Priority => 0, + }, + 732 => [{ + Name => 'AFFineTuneAdj', + Condition => '$$self{FirmwareVersion} eq "1.10B"', + Notes => 'firmware version 1.10B', + Format => 'int16u', + PrintHex => 1, + PrintConvColumns => 3, + # thanks to Michael Tapes for the samples to decode this!... + PrintConv => { + 0xe03e => '+20', + 0xc83e => '+19', + 0xb03e => '+18', + 0x983e => '+17', + 0x803e => '+16', + 0x683e => '+15', + 0x503e => '+14', + 0x383e => '+13', + 0x203e => '+12', + 0x083e => '+11', + 0xe03d => '+10', + 0xb03d => '+9', + 0x803d => '+8', + 0x503d => '+7', + 0x203d => '+6', + 0xe03c => '+5', + 0x803c => '+4', + 0x203c => '+3', + 0x803b => '+2', + 0x803a => '+1', + 0x0000 => '0', + 0x80c6 => '-1', + 0x80c5 => '-2', + 0x20c4 => '-3', + 0x80c4 => '-4', + 0xe0c4 => '-5', + 0x20c3 => '-6', + 0x50c3 => '-7', + 0x80c3 => '-8', + 0xb0c3 => '-9', + 0xe0c3 => '-10', + 0x08c2 => '-11', + 0x20c2 => '-12', + 0x38c2 => '-13', + 0x50c2 => '-14', + 0x68c2 => '-15', + 0x80c2 => '-16', + 0x98c2 => '-17', + 0xb0c2 => '-18', + 0xc8c2 => '-19', + 0xe0c2 => '-20', + }, + },{ + Name => 'AFFineTuneAdj', + Notes => 'other versions', + Format => 'int16u', + PrintHex => 1, + PrintConvColumns => 3, + # thanks to Stuart Solomon for the samples to decode this!... + PrintConv => { + 0x903e => '+20', + 0x7c3e => '+19', + 0x683e => '+18', + 0x543e => '+17', + 0x403e => '+16', + 0x2c3e => '+15', + 0x183e => '+14', + 0x043e => '+13', + 0xe03d => '+12', + 0xb83d => '+11', + 0x903d => '+10', + 0x683d => '+9', + 0x403d => '+8', + 0x183d => '+7', + 0xe03c => '+6', + 0x903c => '+5', + 0x403c => '+4', + 0xe03b => '+3', + 0x403b => '+2', + 0x403a => '+1', + 0x0000 => '0', + 0x40c6 => '-1', + 0x40c5 => '-2', + 0xe0c5 => '-3', + 0x40c4 => '-4', + 0x90c4 => '-5', + 0xe0c4 => '-6', + 0x18c3 => '-7', + 0x40c3 => '-8', + 0x68c3 => '-9', + 0x90c3 => '-10', + 0xb8c3 => '-11', + 0xe0c3 => '-12', + 0x04c2 => '-13', + 0x18c2 => '-14', + 0x2cc2 => '-15', + 0x40c2 => '-16', + 0x54c2 => '-17', + 0x68c2 => '-18', + 0x7cc2 => '-19', + 0x90c2 => '-20', + }, + }], + 802 => { + Name => 'CustomSettingsD300', + Format => 'undef[24]', + SubDirectory => { + TagTable => 'Image::ExifTool::NikonCustom::SettingsD3', + }, + }, + # note: DecryptLen currently set to 825 +); + +# shot information for the D300S firmware 1.00 (encrypted) - ref PH +%Image::ExifTool::Nikon::ShotInfoD300S = ( + PROCESS_PROC => \&Image::ExifTool::Nikon::ProcessNikonEncrypted, + WRITE_PROC => \&Image::ExifTool::Nikon::ProcessNikonEncrypted, + CHECK_PROC => \&Image::ExifTool::CheckBinaryData, + VARS => { ID_LABEL => 'Index' }, + IS_SUBDIR => [ 804 ], + WRITABLE => 1, + FIRST_ENTRY => 0, + GROUPS => { 0 => 'MakerNotes', 2 => 'Camera' }, + NOTES => q{ + These tags are extracted from encrypted data in images from the D300S with + firmware 1.00. + }, + 0x00 => { + Name => 'ShotInfoVersion', + Format => 'string[4]', + Writable => 0, + }, + 0x04 => { + Name => 'FirmwareVersion', + Format => 'string[5]', + Writable => 0, + }, + 613 => { + Name => 'ISO2', + ValueConv => '100*exp(($val/12-5)*log(2))', + ValueConvInv => '(log($val/100)/log(2)+5)*12', + PrintConv => 'int($val + 0.5)', + PrintConvInv => '$val', + }, + 646 => { + Name => 'ShutterCount', + Format => 'int32u', + Priority => 0, + }, + 804 => { #(NC) + Name => 'CustomSettingsD300S', + Format => 'undef[24]', + SubDirectory => { + TagTable => 'Image::ExifTool::NikonCustom::SettingsD3', + }, + }, + # note: DecryptLen currently set to 827 +); + +# shot information for the D700 firmware 1.02f (encrypted) - ref 29 +%Image::ExifTool::Nikon::ShotInfoD700 = ( + PROCESS_PROC => \&Image::ExifTool::Nikon::ProcessNikonEncrypted, + WRITE_PROC => \&Image::ExifTool::Nikon::ProcessNikonEncrypted, + CHECK_PROC => \&Image::ExifTool::CheckBinaryData, + VARS => { ID_LABEL => 'Index' }, + IS_SUBDIR => [ 804 ], + WRITABLE => 1, + FIRST_ENTRY => 0, + GROUPS => { 0 => 'MakerNotes', 2 => 'Camera' }, + NOTES => q{ + These tags are extracted from encrypted data in images from the D700 with + firmware 1.02f. + }, + 0x00 => { + Name => 'ShotInfoVersion', + Format => 'string[4]', + Writable => 0, + }, + 0x04 => { + Name => 'FirmwareVersion', + Format => 'string[5]', + Writable => 0, + }, + 613 => { # 0x265 + Name => 'ISO2', + ValueConv => '100*exp(($val/12-5)*log(2))', + ValueConvInv => '(log($val/100)/log(2)+5)*12', + PrintConv => 'int($val + 0.5)', + PrintConvInv => '$val', + }, + 0x287 => { + Name => 'ShutterCount', + Format => 'int32u', + Priority => 0, + }, + 804 => { # 0x324 (NC) + Name => 'CustomSettingsD700', + Format => 'undef[48]', + SubDirectory => { + TagTable => 'Image::ExifTool::NikonCustom::SettingsD700', + }, + }, + # note: DecryptLen currently set to 852 +); + +# shot information for the D5000 firmware 1.00 (encrypted) - ref PH +%Image::ExifTool::Nikon::ShotInfoD5000 = ( + PROCESS_PROC => \&Image::ExifTool::Nikon::ProcessNikonEncrypted, + WRITE_PROC => \&Image::ExifTool::Nikon::ProcessNikonEncrypted, + CHECK_PROC => \&Image::ExifTool::CheckBinaryData, + VARS => { ID_LABEL => 'Index' }, + IS_SUBDIR => [ 0x378 ], + WRITABLE => 1, + FIRST_ENTRY => 0, + GROUPS => { 0 => 'MakerNotes', 2 => 'Camera' }, + NOTES => q{ + These tags are extracted from encrypted data in images from the D5000 with + firmware 1.00. + }, + 0x00 => { + Name => 'ShotInfoVersion', + Format => 'string[4]', + Writable => 0, + }, + 0x04 => { + Name => 'FirmwareVersion', + Format => 'string[5]', + Writable => 0, + }, + 0x2b5 => { # (also found at 0x2c0) + Name => 'ISO2', + ValueConv => '100*exp(($val/12-5)*log(2))', + ValueConvInv => '(log($val/100)/log(2)+5)*12', + PrintConv => 'int($val + 0.5)', + PrintConvInv => '$val', + }, + 0x2d6 => { + Name => 'ShutterCount', + Format => 'int32u', + Priority => 0, + }, + 0x378 => { + Name => 'CustomSettingsD5000', + Format => 'undef[34]', + SubDirectory => { + TagTable => 'Image::ExifTool::NikonCustom::SettingsD5000', + }, + }, + # note: DecryptLen currently set to 0x39a +); + +# shot information for the D5100 firmware 1.00f (encrypted) - ref PH +%Image::ExifTool::Nikon::ShotInfoD5100 = ( + PROCESS_PROC => \&Image::ExifTool::Nikon::ProcessNikonEncrypted, + WRITE_PROC => \&Image::ExifTool::Nikon::ProcessNikonEncrypted, + CHECK_PROC => \&Image::ExifTool::CheckBinaryData, + VARS => { ID_LABEL => 'Index' }, + IS_SUBDIR => [ 0x407 ], + WRITABLE => 1, + FIRST_ENTRY => 0, + GROUPS => { 0 => 'MakerNotes', 2 => 'Camera' }, + 0x00 => { + Name => 'ShotInfoVersion', + Format => 'string[4]', + Writable => 0, + }, + 0x04 => { + Name => 'FirmwareVersion', + Format => 'string[5]', + Writable => 0, + }, + 0x321 => { + Name => 'ShutterCount', + Format => 'int32u', + Priority => 0, + }, + 0x407 => { + Name => 'CustomSettingsD5100', + Format => 'undef[34]', + SubDirectory => { + TagTable => 'Image::ExifTool::NikonCustom::SettingsD5100', + }, + }, + # note: DecryptLen currently set to 0x430 +); + +# shot information for the D5200 firmware 1.00 (encrypted) - ref PH +%Image::ExifTool::Nikon::ShotInfoD5200 = ( + PROCESS_PROC => \&Image::ExifTool::Nikon::ProcessNikonEncrypted, + WRITE_PROC => \&Image::ExifTool::Nikon::ProcessNikonEncrypted, + CHECK_PROC => \&Image::ExifTool::CheckBinaryData, + VARS => { ID_LABEL => 'Index' }, + IS_SUBDIR => [ 0xcd5 ], + WRITABLE => 1, + FIRST_ENTRY => 0, + GROUPS => { 0 => 'MakerNotes', 2 => 'Camera' }, + 0x00 => { + Name => 'ShotInfoVersion', + Format => 'string[4]', + Writable => 0, + }, + 0x04 => { + Name => 'FirmwareVersion', + Format => 'string[5]', + Writable => 0, + }, + # 0x101 - 2=VR Off, 3=VR On + # 0x13d - 0=VR On, 1=VR Off + 0xbd8 => { + Name => 'ShutterCount', + Format => 'int32u', + Priority => 0, + }, + # 0xcd2 - 12=VR Off, 15=VR On + 0xcd5 => { + Name => 'CustomSettingsD5200', + Format => 'undef[34]', + SubDirectory => { + TagTable => 'Image::ExifTool::NikonCustom::SettingsD5200', + }, + }, + # note: DecryptLen currently set to 0xd00 +); + +# shot information for the D7000 firmware 1.01d (encrypted) - ref 29 +%Image::ExifTool::Nikon::ShotInfoD7000 = ( + PROCESS_PROC => \&Image::ExifTool::Nikon::ProcessNikonEncrypted, + WRITE_PROC => \&Image::ExifTool::Nikon::ProcessNikonEncrypted, + CHECK_PROC => \&Image::ExifTool::CheckBinaryData, + VARS => { ID_LABEL => 'Index' }, + IS_SUBDIR => [ 1028 ], + WRITABLE => 1, + FIRST_ENTRY => 0, + GROUPS => { 0 => 'MakerNotes', 2 => 'Camera' }, + NOTES => q{ + These tags are extracted from encrypted data in images from the D7000 with + firmware 1.01b. + }, + 0x00 => { + Name => 'ShotInfoVersion', + Format => 'string[4]', + Writable => 0, + }, + 0x04 => { + Name => 'FirmwareVersion', + Format => 'string[5]', + Writable => 0, + }, + #613 => { + # Name => 'ISO2', + # ValueConv => '100*exp(($val/12-5)*log(2))', + # ValueConvInv => '(log($val/100)/log(2)+5)*12', + # PrintConv => 'int($val + 0.5)', + # PrintConvInv => '$val', + #}, + 0x320 => { # 800 + Name => 'ShutterCount', + Format => 'int32u', + Priority => 0, + }, + 0x404 => { # 1028 (NC) + Name => 'CustomSettingsD7000', + Format => 'undef[48]', + SubDirectory => { + TagTable => 'Image::ExifTool::NikonCustom::SettingsD7000', + }, + }, +); + +# shot information for the D800 firmware 1.01a (encrypted) - ref PH +%Image::ExifTool::Nikon::ShotInfoD800 = ( + PROCESS_PROC => \&Image::ExifTool::Nikon::ProcessNikonEncrypted, + WRITE_PROC => \&Image::ExifTool::Nikon::ProcessNikonEncrypted, + CHECK_PROC => \&Image::ExifTool::CheckBinaryData, + VARS => { ID_LABEL => 'Index' }, + IS_SUBDIR => [ 0x6ec ], + WRITABLE => 1, + FIRST_ENTRY => 0, + GROUPS => { 0 => 'MakerNotes', 2 => 'Camera' }, + NOTES => 'These tags are extracted from encrypted data in images from the D800.', + 0x00 => { + Name => 'ShotInfoVersion', + Format => 'string[4]', + Writable => 0, + }, + 0x04 => { + Name => 'FirmwareVersion', + Format => 'string[5]', + Writable => 0, + }, + 0x4c0 => { + Name => 'RepeatingFlashOutputExternal', + ValueConv => '2 ** (-$val/6)', + ValueConvInv => '$val > 0 ? -6*log($val)/log(2) : 0', + PrintConv => 'Image::ExifTool::Exif::PrintExposureTime($val)', + PrintConvInv => 'Image::ExifTool::Exif::ConvertFraction($val)', + }, + 0x4c2 => { + Name => 'RepeatingFlashRateExternal', + DelValue => 0, + RawConv => '$val || undef', + PrintConv => '"$val Hz"', + PrintConvInv => '$val=~/(\d+)/; $1 || 0', + }, + 0x4c3 => { + Name => 'RepeatingFlashCountExternal', + DelValue => 0, + RawConv => '$val || undef', + }, + 0x4d2 => { + Name => 'FlashExposureComp2', + Notes => 'includes the effect of flash bracketing', + Format => 'int8s', + ValueConv => '-$val/6', + ValueConvInv => '-6 * $val', + PrintConv => 'Image::ExifTool::Exif::PrintFraction($val)', + PrintConvInv => 'Image::ExifTool::Exif::ConvertFraction($val)', + }, + # 0x4d4 - FEC again, doesn't include bracketing this time (internal?) +# (not fully decoded, and duplicated in custom settings) +# 0x4d9 => { +# Name => 'FlashControlBuilt-in', +# PrintConv => { +# 1 => 'TTL', +# 6 => 'Manual', +# 7 => 'Repeating Flash', +# }, +# }, + 0x4da => { + Name => 'RepeatingFlashRateBuilt-in', + DelValue => 0, + RawConv => '$val || undef', + PrintConv => '"$val Hz"', + PrintConvInv => '$val=~/(\d+)/; $1 || 0', + }, + 0x4db => { + Name => 'RepeatingFlashCountBuilt-in', + DelValue => 0, + RawConv => '$val || undef', + }, +# 1294.1 => { # (0x4dc) +# Name => 'FlashModeBuilt-in', +# Mask => 0x0f, +# PrintConv => { +# 0 => 'Front-curtain Sync', +# 1 => 'Red-eye Reduction', +# 2 => 'Redy-eye Reduction with Slow Sync', +# 3 => 'Slow Sync', +# 4 => 'Rear-curtain Sync', +# 5 => 'Rear-curtain Sync 2', # got this in P exposure mode +# }, +# }, +# 1294.2 => { # (0x4dc) +# Name => 'ExposureMode2', +# Mask => 0xf0, +# PrintConv => { +# 0 => 'Program', +# 1 => 'Aperture Priority', +# 3 => 'Manual', +# }, +# }, + # 0x511 - related to FlashSyncSpeed + 0x51c => 'SequenceNumber', + # 0x4ba+0x63 - interesting + # 0x4ba+0x68 - general downward trend + # 0x4ba+0x7b - FlashControlBuilt-in: 8=TTL, 72=Manual +# (not reliable) +# 1346.1 => { # (0x542) +# Name => 'RepeatingFlashOutputBuilt-in', +# DelValue => 112, +# Mask => 0xfc, +# RawConv => '$val == 0x1c ? undef : 2 ** ($val/3-7)', +# ValueConvInv => '$val > 0 ? (log($val)/log(2)+7)*3 : 0', +# PrintConv => 'Image::ExifTool::Exif::PrintExposureTime($val)', +# PrintConvInv => 'Image::ExifTool::Exif::ConvertFraction($val)', +# }, + 0x5fb => { + Name => 'ShutterCount', + Format => 'int32u', + }, + 0x6ec => { + Name => 'CustomSettingsD800', + Format => 'undef[48]', + SubDirectory => { + TagTable => 'Image::ExifTool::NikonCustom::SettingsD800', + }, + }, + # note: DecryptLen currently set to 0x720 +); + +# shot information for the D5 firmware 1.10a and D500 firmware 1.01 (encrypted) - ref 28 +%Image::ExifTool::Nikon::ShotInfoD500 = ( + PROCESS_PROC => \&Image::ExifTool::Nikon::ProcessNikonEncrypted, + WRITE_PROC => \&Image::ExifTool::Nikon::ProcessNikonEncrypted, + CHECK_PROC => \&Image::ExifTool::CheckBinaryData, + VARS => { ID_LABEL => 'Index' }, + DATAMEMBER => [ 0x04, 0x10, 0x14, 0x2c, 0x50, 0x58, 0xa0, 0xb0, + 0x07b0, 0x086c, 0x0e7c, 0x0eea, 0x2c23 ], + IS_SUBDIR => [ 0x0eeb ], + WRITABLE => 1, + FIRST_ENTRY => 0, + GROUPS => { 0 => 'MakerNotes', 2 => 'Camera' }, + NOTES => 'These tags are extracted from encrypted data in images from the D5 and D500.', + 0x00 => { + Name => 'ShotInfoVersion', + Format => 'string[4]', + Writable => 0, + }, + 0x04 => { + Name => 'FirmwareVersion', + DataMember => 'FirmwareVersion', + Format => 'string[5]', + Writable => 0, + RawConv => '$$self{FirmwareVersion} = $val', + }, + 0x10 => { + Name => 'RotationInfoOffset', + DataMember => 'RotationInfoOffset', + Format => 'int32u', + Writable => 0, + RawConv => '$$self{RotationInfoOffset} = $val || 0x10000000; $val', # (ignore if 0) + }, + 0x14 => { + Name => 'JPGInfoOffset', + DataMember => 'JPGInfoOffset', + Format => 'int32u', + Writable => 0, + RawConv => '$$self{JPGInfoOffset} = $val || 0x10000000; $val', # (ignore if 0) + }, + 0x2c => { + Name => 'BracketingInfoOffset', + DataMember => 'BracketingInfoOffset', + Format => 'int32u', + Writable => 0, + RawConv => '$$self{BracketingInfoOffset} = $val || 0x10000000; $val', # (ignore if 0) + }, + 0x50 => { + Name => 'ShootingMenuOffset', + DataMember => 'ShootingMenuOffset', + Format => 'int32u', + Writable => 0, + RawConv => '$$self{ShootingMenuOffset} = $val || 0x10000000; $val', # (ignore if 0) + }, + 0x58 => { + Name => 'CustomSettingsOffset', + DataMember => 'CustomSettingsOffset', + Format => 'int32u', + Writable => 0, + RawConv => '$$self{CustomSettingsOffset} = $val || 0x10000000; $val', # (ignore if 0) + }, + 0xa0 => { + Name => 'OrientationOffset', + DataMember => 'OrientationOffset', + Format => 'int32u', + Writable => 0, + RawConv => '$$self{OrientationOffset} = $val || 0x10000000; $val', # (ignore if 0) + }, +# +# Tag ID's below are the offsets for a D500 JPEG image, but these offsets change +# for various image types according to the offset table above +# +### 0xb0 - RotationInfo start + 0xb0 => { + Name => 'Hook1', + Hidden => 1, + RawConv => 'undef', + # account for variable location of Rotation data + Hook => '$varSize = $$self{RotationInfoOffset} - 0xb0', + }, + 0xca => { + Name => 'Rotation', + Mask => 0x03, + PrintConv => { + 0 => 'Horizontal', + 1 => 'Rotate 270 CW', + 2 => 'Rotate 90 CW', + 3 => 'Rotate 180', + }, + }, + 0x05e2 => { + Name => 'FlickerReductionIndicator', + Mask => 0x01, + PrintConv => { 0 => 'On', 1 => 'Off' }, + }, +### 0x07b0 - JPEGInfo start + 0x07b0 => { + Name => 'Hook2', + Hidden => 1, + RawConv => 'undef', + # account for variable location of Shooting Menu data + Hook => '$varSize = $$self{JPGInfoOffset} - 0x07b0', + }, + 0x07d4 => { + Name => 'JPGCompression', + Mask => 0x01, + PrintConv => { + 0 => 'Size Priority', + 1 => 'Optimal Quality', + }, + }, +### 0x0830 - ? start +### 0x086c - BracketingInfo start + 0x086c => { + Name => 'Hook3', + Hidden => 1, + RawConv => 'undef', + # account for variable location of Shooting Menu data + Hook => '$varSize = $$self{BracketingInfoOffset} - 0x086c', + }, + 0x087b => { + Name => 'AEBracketingSteps', + Condition => '$$self{FILE_TYPE} ne "TIFF"', # (covers NEF and TIFF) + Mask => 0xff, + PrintHex => 1, + PrintConvColumns => 2, + PrintConv => { + 0x00 => 'AE Bracketing Disabled', + 0x20 => 'AE Bracketing Disabled', + 0x30 => 'AE Bracketing Disabled', + 0x40 => 'AE Bracketing Disabled', + 0x50 => 'AE Bracketing Disabled', + 0x81 => '+3F0.3', + 0x82 => '-3F0.3', + 0x83 => '+2F0.3', + 0x84 => '-2F0.3', + 0x85 => '3F0.3', + 0x86 => '5F0.3', + 0x87 => '7F0.3', + 0x88 => '9F0.3', + 0x91 => '+3F0.5', + 0x92 => '-3F0.5', + 0x93 => '+2F0.5', + 0x94 => '-2F0.5', + 0x95 => '3F0.5', + 0x96 => '5F0.5', + 0x97 => '7F0.5', + 0x98 => '9F0.5', + 0xa1 => '+3F0.7', + 0xa2 => '-3F0.7', + 0xa3 => '+2F0.7', + 0xa4 => '-2F0.7', + 0xa5 => '3F0.7', + 0xa6 => '5F0.7', + 0xa7 => '7F0.7', + 0xa8 => '9F0.7', + 0xb1 => '+3F1', + 0xb2 => '-3F1', + 0xb3 => '+2F1', + 0xb4 => '-2F1', + 0xb5 => '3F1', + 0xb6 => '5F1', + 0xb7 => '7F1', + 0xb8 => '9F1', + 0xc1 => '+3F2', + 0xc2 => '-3F2', + 0xc3 => '+2F2', + 0xc4 => '-2F2', + 0xc5 => '3F2', + 0xc6 => '5F2', + 0xd1 => '+3F3', + 0xd2 => '-3F3', + 0xd3 => '+2F3', + 0xd4 => '-2F3', + 0xd5 => '3F3', + 0xd6 => '5F3', + }, + }, + 0x087c => { + Name => 'WBBracketingSteps', + Condition => '$$self{FILE_TYPE} ne "TIFF"', # (covers NEF and TIFF) + Mask => 0xff, + PrintHex => 1, + PrintConvColumns => 2, + PrintConv => { + 0x00 => 'WB Bracketing Disabled', + 0x01 => 'b3F 1', + 0x02 => 'A3F 1', + 0x03 => 'b2F 1', + 0x04 => 'A2F 1', + 0x05 => '3F 1', + 0x06 => '5F 1', + 0x07 => '7F 1', + 0x08 => '9F 1', + 0x10 => '0F 2', + 0x11 => 'b3F 2', + 0x12 => 'A3F 2', + 0x13 => 'b2F 2', + 0x14 => 'A2F 2', + 0x15 => '3F 2', + 0x16 => '5F 2', + 0x17 => '7F 2', + 0x18 => '9F 2', + 0x20 => '0F 3', + 0x21 => 'b3F 3', + 0x22 => 'A3F 3', + 0x23 => 'b2F 3', + 0x24 => 'A2F 3', + 0x25 => '3F 3', + 0x26 => '5F 3', + 0x27 => '7F 3', + 0x28 => '9F 3', + 0x22 => 'A3F 3', + 0x23 => 'b2F 3', + 0x24 => 'A2F 3', + 0x25 => '3F 3', + 0x26 => '5F 3', + 0x27 => '7F 3', + 0x28 => '9F 3', + }, + }, + 0x0883 => { + Name => 'ADLBracketingStep', + Mask => 0xf0, + PrintConv => { + 0 => 'Off', + 1 => 'Low', + 2 => 'Normal', + 3 => 'High', + 4 => 'Extra High', + 8 => 'Auto', + }, + }, + 0x0884 => { + Name => 'ADLBracketingType', + Mask => 0x0f, + PrintConv => { + 0 => 'Off', + 1 => '2 Shots', + 2 => '3 Shots', + 3 => '4 Shots', + 4 => '5 Shots', + }, + }, +### 0x0887 - ? start +### 0x089f - ? start +### 0x0929 - ? start +### 0x09c9 - ? start +### 0x0ac5 - ? start +### 0x0bc1 - ? start +### 0x0cbd - ? start +### 0x0d98 - ? start +### 0x0e7d - ShootingMenuOffset start + 0x0e7c => { + Name => 'Hook4', + Hidden => 1, + RawConv => 'undef', + # account for variable location of Shooting Menu data + Hook => '$varSize = $$self{ShootingMenuOffset} - 0x0e7d', + }, + 0x0e7d => { + Name => 'PhotoShootingMenuBank', + Mask => 0x03, + PrintConv => { + 0 => 'A', + 1 => 'B', + 2 => 'C', + 3 => 'D', + }, + }, + 0x0e7f => { + Name => 'PrimarySlot', + Condition => '$$self{Model} =~ /\bD500\b/', + Notes => 'D500 only', + Mask => 0x80, + PrintConv => { + 0 => 'XQD Card', + 1 => 'SD Card', + }, + }, + 0x0e81 => { + Name => 'ISOAutoShutterTime', + Mask => 0x3f, + PrintConv => { + 0 => '1/4000 s', + 1 => '1/3200 s', + 2 => '1/2500 s', + 3 => '1/2000 s', + 4 => '1/1600 s', + 5 => '1/1250 s', + 6 => '1/1000 s', + 7 => '1/800 s', + 8 => '1/640 s', + 9 => '1/500 s', + 10 => '1/400 s', + 11 => '1/320 s', + 12 => '1/250 s', + 13 => '1/200 s', + 14 => '1/160 s', + 15 => '1/125 s', + 16 => '1/100 s', + 17 => '1/80 s', + 18 => '1/60 s', + 19 => '1/50 s', + 20 => '1/40 s', + 21 => '1/30 s', + 22 => '1/15 s', + 23 => '1/8 s', + 24 => '1/4 s', + 25 => '1/2 s', + 26 => '1 s', + 27 => '2 s', + 28 => '4 s', + 29 => '8 s', + 30 => '15 s', + 31 => '30 s', + 32 => 'Auto (Slowest)', + 33 => 'Auto (Slower)', + 34 => 'Auto', + 35 => 'Auto (Faster)', + 36 => 'Auto (Fastest)', + }, + }, + 0x0e82 => { + Name => 'ISOAutoHiLimit', + Mask => 0xff, + PrintHex => 1, + PrintConv => { + 0x24 => 'ISO 200', + 0x26 => 'ISO 250', + 0x27 => 'ISO 280', + 0x28 => 'ISO 320', + 0x2a => 'ISO 400', + 0x2c => 'ISO 500', + 0x2d => 'ISO 560', + 0x2e => 'ISO 640', + 0x30 => 'ISO 800', + 0x32 => 'ISO 1000', + 0x33 => 'ISO 1100', + 0x34 => 'ISO 1250', + 0x36 => 'ISO 1600', + 0x38 => 'ISO 2000', + 0x39 => 'ISO 2200', + 0x3a => 'ISO 2500', + 0x3c => 'ISO 3200', + 0x3e => 'ISO 4000', + 0x3f => 'ISO 4500', + 0x40 => 'ISO 5000', + 0x42 => 'ISO 6400', + 0x44 => 'ISO 8000', + 0x45 => 'ISO 9000', + 0x46 => 'ISO 10000', + 0x48 => 'ISO 12800', + 0x4a => 'ISO 16000', + 0x4b => 'ISO 18000', + 0x4c => 'ISO 20000', + 0x4e => 'ISO 25600', + 0x50 => 'ISO 32000', + 0x51 => 'ISO 36000', + 0x52 => 'ISO 40000', + 0x54 => 'ISO 51200', + 0x56 => 'ISO Hi 0.3', + 0x57 => 'ISO Hi 0.5', + 0x58 => 'ISO Hi 0.7', + 0x5a => 'ISO Hi 1.0', + 0x60 => 'ISO Hi 2.0', + 0x66 => 'ISO Hi 3.0', + 0x6c => 'ISO Hi 4.0', + 0x72 => 'ISO Hi 5.0', + }, + }, + 0x0e84 => { + Name => 'FlickerReduction', + Mask => 0x20, + PrintConv => { + 0 => 'Enable', + 1 => 'Disable', + }, + }, + 3716.1 => { # (0x0e84) + Name => 'PhotoShootingMenuBankImageArea', + Mask => 0x07, + PrintConv => { + 0 => 'FX (36x24)', + 1 => 'DX (24x16)', + 2 => '5:4 (30x24)', + 3 => '1.2x (30x20)', + 4 => '1.3x (18x12)', + }, + }, +### 0x0ec4 - ? start +### 0x0eeb - CustomSettings start + 0x0eea => { + Name => 'Hook5', + Hidden => 1, + RawConv => 'undef', + # account for variable location of CustomSettings data + Hook => '$varSize = $$self{CustomSettingsOffset} - 0x0eeb', + }, + 0x0eeb => [{ + Name => 'CustomSettingsD5', + Condition => '$$self{Model} =~ /\bD5\b/', + Format => 'undef[90]', + SubDirectory => { + TagTable => 'Image::ExifTool::NikonCustom::SettingsD5', + }, + },{ + Name => 'CustomSettingsD500', + Format => 'undef[90]', + SubDirectory => { + TagTable => 'Image::ExifTool::NikonCustom::SettingsD500', + }, + }], +# 0x0f68 => { #this decode works, but involves more bits than should be necessary +# Name => 'ShutterTrigger', +# Mask => 0xff, +# PrintConv => { +# 0 => 'Timer', +# 15 => 'Cable Release/Remote', +# 195 => 'Shutter Button', +# }, +# }, +### 0x2c24 - OrientationInfo start (D5 firmware 1.10b) + 0x2c23 => { + Name => 'Hook6', + Hidden => 1, + RawConv => 'undef', + # account for variable location of OrientationInfo data + Hook => '$varSize = $$self{OrientationOffset} - 0x2c24', + }, + 0x2c24 => { + Name => 'RollAngle', + Format => 'fixed32u', + Notes => 'converted to degrees of clockwise camera roll', + ValueConv => '$val <= 180 ? $val : $val - 360', + ValueConvInv => '$val >= 0 ? $val : $val + 360', + PrintConv => 'sprintf("%.1f", $val)', + PrintConvInv => '$val', + }, + 0x2c28 => { + Name => 'PitchAngle', + Format => 'fixed32u', + Notes => 'converted to degrees of upward camera tilt', + ValueConv => '$val <= 180 ? $val : $val - 360', + ValueConvInv => '$val >= 0 ? $val : $val + 360', + PrintConv => 'sprintf("%.1f", $val)', + PrintConvInv => '$val', + }, + 0x2c2c => { + Name => 'YawAngle', + Format => 'fixed32u', + Notes => 'the camera yaw angle when shooting in portrait orientation', + ValueConv => '$val <= 180 ? $val : $val - 360', + ValueConvInv => '$val >= 0 ? $val : $val + 360', + PrintConv => 'sprintf("%.1f", $val)', + PrintConvInv => '$val', + }, + # note: DecryptLen currently set to OrientationOffset + 12 + + # (not sure about how this moves around) + #0x2cb2 => { + # Name => 'ExtendedPhotoShootingBanks', + # Mask => 0x01, + # PrintConv => { + # 0 => 'On', + # 1 => 'Off', + # }, + #}, + # don't decode this because it is duplicate information and moves around with firmware versions + #0x2ea2 => { + # Name => 'Rotation', + # Condition => '$$self{Model} =~ /\bD500\b/ and $$self{FirmwareVersion} =~ /^1.1/', + # Notes => 'D500 firmware 1.1x', + # Mask => 0x30, + # PrintConv => { + # 0 => 'Horizontal', + # 1 => 'Rotate 270 CW', + # 2 => 'Rotate 90 CW', + # 3 => 'Rotate 180', + # }, + #}, +); +# shot information for the D610 firmware 1.00 (encrypted) - ref PH +%Image::ExifTool::Nikon::ShotInfoD610 = ( + PROCESS_PROC => \&Image::ExifTool::Nikon::ProcessNikonEncrypted, + WRITE_PROC => \&Image::ExifTool::Nikon::ProcessNikonEncrypted, + CHECK_PROC => \&Image::ExifTool::CheckBinaryData, + VARS => { ID_LABEL => 'Index' }, + IS_SUBDIR => [ 0x07cf ], + WRITABLE => 1, + FIRST_ENTRY => 0, + GROUPS => { 0 => 'MakerNotes', 2 => 'Camera' }, + NOTES => 'These tags are extracted from encrypted data in images from the D610.', + 0x00 => { + Name => 'ShotInfoVersion', + Format => 'string[4]', + Writable => 0, + }, + 0x04 => { + Name => 'FirmwareVersion', + Format => 'string[5]', + Writable => 0, + }, + 0x07cf => { + Name => 'CustomSettingsD610', + Format => 'undef[48]', + SubDirectory => { + TagTable => 'Image::ExifTool::NikonCustom::SettingsD610', + }, + }, + # note: DecryptLen currently set to 0x7ff +); + +# shot information for the D810 firmware 1.00(PH)/1.01 (encrypted) - ref 28 +%Image::ExifTool::Nikon::ShotInfoD810 = ( + PROCESS_PROC => \&Image::ExifTool::Nikon::ProcessNikonEncrypted, + WRITE_PROC => \&Image::ExifTool::Nikon::ProcessNikonEncrypted, + CHECK_PROC => \&Image::ExifTool::CheckBinaryData, + VARS => { ID_LABEL => 'Index' }, + DATAMEMBER => [ 0x04, 0x24, 0x40, 0x84, 0x01d0, 0x175e, 0x185d ], + IS_SUBDIR => [ 0x18ab ], + WRITABLE => 1, + FIRST_ENTRY => 0, + GROUPS => { 0 => 'MakerNotes', 2 => 'Camera' }, + NOTES => 'These tags are extracted from encrypted data in images from the D810.', + 0x00 => { + Name => 'ShotInfoVersion', + Format => 'string[4]', + Writable => 0, + }, + 0x04 => { + Name => 'FirmwareVersion', + DataMember => 'FirmwareVersion', + Format => 'string[5]', + Writable => 0, + RawConv => '$$self{FirmwareVersion} = $val', + }, + # 0x0c - number of entries in offset table (= 0x21) + # 0x10 - int32u[val 0x0c]: offset table + 0x24 => { + Name => 'BracketingOffset', + DataMember => 'BracketingOffset', + Format => 'int32u', + Writable => 0, + RawConv => '$$self{BracketingOffset} = $val', + }, + 0x40 => { + Name => 'CustomSettingsOffset', # (relative offset from start of ShotInfo data) + DataMember => 'CustomSettingsOffset', + Format => 'int32u', + Writable => 0, + RawConv => '$$self{CustomSettingsOffset} = $val', + }, + 0x84 => { + Name => 'OrientationOffset', + DataMember => 'OrientationOffset', + Format => 'int32u', + Writable => 0, + RawConv => '$$self{OrientationOffset} = $val', + }, + 0x01d0 => { + Name => 'SecondarySlotFunction', + Mask => 0x03, + PrintConv => { + 0 => 'Overflow', + 2 => 'Backup', + 3 => 'NEF Primary + JPG Secondary', + }, + Hook => '$varSize = $$self{BracketingOffset} - 0x1747', + }, + 0x1756 => { + Name => 'AEBracketingSteps', + Mask => 0xff, + PrintHex => 1, + PrintConvColumns => 2, + PrintConv => { + 0x00 => 'AE Bracketing Disabled', + 0x20 => 'AE Bracketing Disabled', + 0x30 => 'AE Bracketing Disabled', + 0x40 => 'AE Bracketing Disabled', + 0x50 => 'AE Bracketing Disabled', + 0x81 => '+3F0.3', + 0x82 => '-3F0.3', + 0x83 => '+2F0.3', + 0x84 => '-2F0.3', + 0x85 => '3F0.3', + 0x86 => '5F0.3', + 0x87 => '7F0.3', + 0x88 => '9F0.3', + 0x91 => '+3F0.5', + 0x92 => '-3F0.5', + 0x93 => '+2F0.5', + 0x94 => '-2F0.5', + 0x95 => '3F0.5', + 0x96 => '5F0.5', + 0x97 => '7F0.5', + 0x98 => '9F0.5', + 0xa1 => '+3F0.7', + 0xa2 => '-3F0.7', + 0xa3 => '+2F0.7', + 0xa4 => '-2F0.7', + 0xa5 => '3F0.7', + 0xa6 => '5F0.7', + 0xa7 => '7F0.7', + 0xa8 => '9F0.7', + 0xb1 => '+3F1', + 0xb2 => '-3F1', + 0xb3 => '+2F1', + 0xb4 => '-2F1', + 0xb5 => '3F1', + 0xb6 => '5F1', + 0xb7 => '7F1', + 0xb8 => '9F1', + 0xc1 => '+3F2', + 0xc2 => '-3F2', + 0xc3 => '+2F2', + 0xc4 => '-2F2', + 0xc5 => '3F2', + 0xc6 => '5F2', + 0xd1 => '+3F3', + 0xd2 => '-3F3', + 0xd3 => '+2F3', + 0xd4 => '-2F3', + 0xd5 => '3F3', + 0xd6 => '5F3', + }, + }, + 0x1757 => { + Name => 'WBBracketingSteps', + Condition => '$$self{FILE_TYPE} ne "TIFF"', # (covers NEF and TIFF) + Mask => 0xff, + PrintHex => 1, + PrintConvColumns => 2, + PrintConv => { + 0x00 => 'WB Bracketing Disabled', + 0x01 => 'b3F 1', + 0x02 => 'A3F 1', + 0x03 => 'b2F 1', + 0x04 => 'A2F 1', + 0x05 => '3F 1', + 0x06 => '5F 1', + 0x07 => '7F 1', + 0x08 => '9F 1', + 0x10 => '0F 2', + 0x11 => 'b3F 2', + 0x12 => 'A3F 2', + 0x13 => 'b2F 2', + 0x14 => 'A2F 2', + 0x15 => '3F 2', + 0x16 => '5F 2', + 0x17 => '7F 2', + 0x18 => '9F 2', + 0x20 => '0F 3', + 0x21 => 'b3F 3', + 0x22 => 'A3F 3', + 0x23 => 'b2F 3', + 0x24 => 'A2F 3', + 0x25 => '3F 3', + 0x26 => '5F 3', + 0x27 => '7F 3', + 0x28 => '9F 3', + 0x22 => 'A3F 3', + 0x23 => 'b2F 3', + 0x24 => 'A2F 3', + 0x25 => '3F 3', + 0x26 => '5F 3', + 0x27 => '7F 3', + 0x28 => '9F 3', + }, + }, + 0x175e => { + Name => 'D810MeteringMode', + Mask => 0x03, + PrintConv => { + 0 => 'Matrix', + 1 => 'Center', + 2 => 'Spot', + 3 => 'Highlight' + }, + Hook => '$varSize = $$self{CustomSettingsOffset} - 0x18ab', + }, + 0x18ab => { # (actual offset adjusted by Hook above) + Name => 'CustomSettingsD810', + Notes => 'actual offset determined by CustomSettingsOffset', + Format => 'undef[53]', + SubDirectory => { + TagTable => 'Image::ExifTool::NikonCustom::SettingsD810', + }, + }, + 0x185c => { + Name => 'ISOAutoShutterTime', + Mask => 0x3f, + PrintConv => { + 0 => '1/4000 s', + 1 => '1/3200 s', + 2 => '1/2500 s', + 3 => '1/2000 s', + 4 => '1/1600 s', + 5 => '1/1250 s', + 6 => '1/1000 s', + 7 => '1/800 s', + 8 => '1/640 s', + 9 => '1/500 s', + 10 => '1/400 s', + 11 => '1/320 s', + 12 => '1/250 s', + 13 => '1/200 s', + 14 => '1/160 s', + 15 => '1/125 s', + 16 => '1/100 s', + 17 => '1/80 s', + 18 => '1/60 s', + 19 => '1/50 s', + 20 => '1/40 s', + 21 => '1/30 s', + 22 => '1/15 s', + 23 => '1/8 s', + 24 => '1/4 s', + 25 => '1/2 s', + 26 => '1 s', + 27 => '2 s', + 28 => '4 s', + 29 => '8 s', + 30 => '15 s', + 31 => '30 s', + 32 => 'Auto (Slowest)', + 33 => 'Auto (Slower)', + 34 => 'Auto', + 35 => 'Auto (Faster)', + 36 => 'Auto (Fastest)', + }, + }, + 0x185d => { + Name => 'ISOAutoHiLimit', + Mask => 0xff, + PrintHex => 1, + Hook => '$varSize = $$self{OrientationOffset} - 0x36f4', + PrintConv => { + 0x24 => 'ISO 200', + 0x26 => 'ISO 250', + 0x27 => 'ISO 280', + 0x28 => 'ISO 320', + 0x2a => 'ISO 400', + 0x2c => 'ISO 500', + 0x2d => 'ISO 560', + 0x2e => 'ISO 640', + 0x30 => 'ISO 800', + 0x32 => 'ISO 1000', + 0x33 => 'ISO 1100', + 0x34 => 'ISO 1250', + 0x36 => 'ISO 1600', + 0x38 => 'ISO 2000', + 0x39 => 'ISO 2200', + 0x3a => 'ISO 2500', + 0x3c => 'ISO 3200', + 0x3e => 'ISO 4000', + 0x3f => 'ISO 4500', + 0x40 => 'ISO 5000', + 0x42 => 'ISO 6400', + 0x44 => 'ISO 8000', + 0x45 => 'ISO 9000', + 0x46 => 'ISO 10000', + 0x48 => 'ISO 12800', + 0x4a => 'ISO 16000', + 0x4b => 'ISO 18000', + 0x4c => 'ISO 20000', + 0x4e => 'ISO 25600', + 0x50 => 'ISO 32000', + 0x51 => 'ISO 36000', + 0x52 => 'ISO 40000', + 0x54 => 'ISO 51200', + 0x56 => 'ISO Hi 0.3', + 0x57 => 'ISO Hi 0.5', + 0x58 => 'ISO Hi 0.7', + 0x5a => 'ISO Hi 1.0', + 0x60 => 'ISO Hi 2.0', + 0x66 => 'ISO Hi 3.0', + 0x6c => 'ISO Hi 4.0', + 0x72 => 'ISO Hi 5.0', + }, + }, + 0x36f4 => { + Name => 'RollAngle', + Format => 'fixed32u', + Notes => 'converted to degrees of clockwise camera roll', + ValueConv => '$val <= 180 ? $val : $val - 360', + ValueConvInv => '$val >= 0 ? $val : $val + 360', + PrintConv => 'sprintf("%.1f", $val)', + PrintConvInv => '$val', + }, + 0x36f8 => { + Name => 'PitchAngle', + Format => 'fixed32u', + Notes => 'converted to degrees of upward camera tilt', + ValueConv => '$val <= 180 ? $val : $val - 360', + ValueConvInv => '$val >= 0 ? $val : $val + 360', + PrintConv => 'sprintf("%.1f", $val)', + PrintConvInv => '$val', + }, + 0x36fc => { + Name => 'YawAngle', + Format => 'fixed32u', + Notes => 'the camera yaw angle when shooting in portrait orientation', + ValueConv => '$val <= 180 ? $val : $val - 360', + ValueConvInv => '$val >= 0 ? $val : $val + 360', + PrintConv => 'sprintf("%.1f", $val)', + PrintConvInv => '$val', + }, + # note: DecryptLen currently set to OrientationOffset + 12 + + # (moves around too much and doesn't fit cleanly in the offset table) + #0x38be => { + # Name => 'Rotation', + # Condition => '$$self{FirmwareVersion} =~ /^1.0/', + # Mask => 0x30, + # PrintConv => { + # 0 => 'Horizontal', + # 1 => 'Rotate 270 CW', + # 2 => 'Rotate 90 CW', + # 3 => 'Rotate 180', + # }, + #}, +); + +# shot information for the D850 firmware 1.00b (encrypted) - ref 28 +%Image::ExifTool::Nikon::ShotInfoD850 = ( + PROCESS_PROC => \&Image::ExifTool::Nikon::ProcessNikonEncrypted, + WRITE_PROC => \&Image::ExifTool::Nikon::ProcessNikonEncrypted, + CHECK_PROC => \&Image::ExifTool::CheckBinaryData, + VARS => { ID_LABEL => 'Index' }, + DATAMEMBER => [ 0x04, 0x58, 0x0fbf ], + IS_SUBDIR => [ 0x1038 ], + WRITABLE => 1, + FIRST_ENTRY => 0, + GROUPS => { 0 => 'MakerNotes', 2 => 'Camera' }, + NOTES => 'These tags are extracted from encrypted data in images from the D850.', + 0x00 => { + Name => 'ShotInfoVersion', + Format => 'string[4]', + Writable => 0, + }, + 0x04 => { + Name => 'FirmwareVersion', + DataMember => 'FirmwareVersion', + Format => 'string[5]', + Writable => 0, + RawConv => '$$self{FirmwareVersion} = $val', + }, + 0x58 => { + Name => 'CustomSettingsOffset', # (relative offset from start of ShotInfo data) + DataMember => 'CustomSettingsOffset', + Format => 'int32u', + Writable => 0, + RawConv => '$$self{CustomSettingsOffset} = $val', + }, + 0x0791 => { + Name => 'PhotoShootingMenuBankImageArea', + Mask => 0x07, + PrintConv => { + 0 => 'FX (36x24)', + 1 => 'DX (24x16)', + 2 => '5:4 (30x24)', + 3 => '1.2x (30x20)', + 4 => '1:1 (24x24)', + }, + }, + 0x0fbd => { + Name => 'PhotoShootingMenuBank', + Condition => '$$self{FILE_TYPE} eq "JPEG"', + Notes => 'valid for JPEG images only', + Mask => 0x03, + PrintConv => { + 0 => 'A', + 1 => 'B', + 2 => 'C', + 3 => 'D', + }, + }, + 0x0fbf => { + Name => 'PrimarySlot', + Mask => 0x80, + PrintConv => { + 0 => 'XQD Card', + 1 => 'SD Card', + }, + Hook => '$varSize = $$self{CustomSettingsOffset} - 0x1038', + }, + 0x1038 => { + Name => 'CustomSettingsD850', + Format => 'undef[90]', + SubDirectory => { + TagTable => 'Image::ExifTool::NikonCustom::SettingsD850', + }, + }, + # note: DecryptLen currently set to 94 bytes after CustomSettingsOffset +); +# shot information for the D4 firmware 1.00g (ref PH) +%Image::ExifTool::Nikon::ShotInfoD4 = ( + PROCESS_PROC => \&Image::ExifTool::Nikon::ProcessNikonEncrypted, + WRITE_PROC => \&Image::ExifTool::Nikon::ProcessNikonEncrypted, + CHECK_PROC => \&Image::ExifTool::CheckBinaryData, + VARS => { ID_LABEL => 'Index' }, + IS_SUBDIR => [ 0x0751 ], + WRITABLE => 1, + FIRST_ENTRY => 0, + GROUPS => { 0 => 'MakerNotes', 2 => 'Camera' }, + NOTES => q{ + These tags are extracted from encrypted data in images from the D4. + }, + 0x00 => { + Name => 'ShotInfoVersion', + Format => 'string[4]', + Writable => 0, + }, + 0x04 => { + Name => 'FirmwareVersion', + Format => 'string[5]', + Writable => 0, + }, + 0x0751 => { #PH (NC) + Name => 'CustomSettingsD4', + # (seems to work for 1.00g and 1.02b) + Format => 'undef[56]', + SubDirectory => { TagTable => 'Image::ExifTool::NikonCustom::SettingsD4' }, + }, + # note: DecryptLen currently set to 0x789 +); + +# shot information for the D4S firmware 1.01a (ref 28, encrypted) +%Image::ExifTool::Nikon::ShotInfoD4S = ( + PROCESS_PROC => \&Image::ExifTool::Nikon::ProcessNikonEncrypted, + WRITE_PROC => \&Image::ExifTool::Nikon::ProcessNikonEncrypted, + CHECK_PROC => \&Image::ExifTool::CheckBinaryData, + VARS => { ID_LABEL => 'Index' }, + DATAMEMBER => [ 4 ], + IS_SUBDIR => [ 0x189d, 0x193d ], + WRITABLE => 1, + FIRST_ENTRY => 0, + GROUPS => { 0 => 'MakerNotes', 2 => 'Camera' }, + NOTES => q{ + These tags are extracted from encrypted data in images from the D4S. + }, + 0x00 => { + Name => 'ShotInfoVersion', + Format => 'string[4]', + Writable => 0, + }, + 0x04 => { + Name => 'FirmwareVersion', + DataMember => 'FirmwareVersion', + Format => 'string[5]', + Writable => 0, + RawConv => '$$self{FirmwareVersion} = $val', + }, + 0x01d0 => { + Name => 'SecondarySlotFunction', + Mask => 0x03, + PrintConv => { + 0 => 'Overflow', + 2 => 'Backup', + 3 => 'NEF Primary + JPG Secondary', + }, + }, + 0x174c => { + Name => 'AEBracketingSteps', + Mask => 0xff, + PrintHex => 1, + PrintConvColumns => 2, + PrintConv => { + 0x00 => 'AE Bracketing Disabled', + 0x20 => 'AE Bracketing Disabled', + 0x30 => 'AE Bracketing Disabled', + 0x40 => 'AE Bracketing Disabled', + 0x50 => 'AE Bracketing Disabled', + 0x81 => '+3F0.3', + 0x82 => '-3F0.3', + 0x83 => '+2F0.3', + 0x84 => '-2F0.3', + 0x85 => '3F0.3', + 0x86 => '5F0.3', + 0x87 => '7F0.3', + 0x88 => '9F0.3', + 0x91 => '+3F0.5', + 0x92 => '-3F0.5', + 0x93 => '+2F0.5', + 0x94 => '-2F0.5', + 0x95 => '3F0.5', + 0x96 => '5F0.5', + 0x97 => '7F0.5', + 0x98 => '9F0.5', + 0xa1 => '+3F0.7', + 0xa2 => '-3F0.7', + 0xa3 => '+2F0.7', + 0xa4 => '-2F0.7', + 0xa5 => '3F0.7', + 0xa6 => '5F0.7', + 0xa7 => '7F0.7', + 0xa8 => '9F0.7', + 0xb1 => '+3F1', + 0xb2 => '-3F1', + 0xb3 => '+2F1', + 0xb4 => '-2F1', + 0xb5 => '3F1', + 0xb6 => '5F1', + 0xb7 => '7F1', + 0xb8 => '9F1', + 0xc1 => '+3F2', + 0xc2 => '-3F2', + 0xc3 => '+2F2', + 0xc4 => '-2F2', + 0xc5 => '3F2', + 0xc6 => '5F2', + 0xd1 => '+3F3', + 0xd2 => '-3F3', + 0xd3 => '+2F3', + 0xd4 => '-2F3', + 0xd5 => '3F3', + 0xd6 => '5F3', + }, + }, + 0x174d => { + Name => 'WBBracketingSteps', + Condition => '$$self{FILE_TYPE} ne "TIFF"', # (covers NEF and TIFF) + Mask => 0xff, + PrintHex => 1, + PrintConvColumns => 2, + PrintConv => { + 0x00 => 'WB Bracketing Disabled', + 0x01 => 'b3F 1', + 0x02 => 'A3F 1', + 0x03 => 'b2F 1', + 0x04 => 'A2F 1', + 0x05 => '3F 1', + 0x06 => '5F 1', + 0x07 => '7F 1', + 0x08 => '9F 1', + 0x10 => '0F 2', + 0x11 => 'b3F 2', + 0x12 => 'A3F 2', + 0x13 => 'b2F 2', + 0x14 => 'A2F 2', + 0x15 => '3F 2', + 0x16 => '5F 2', + 0x17 => '7F 2', + 0x18 => '9F 2', + 0x20 => '0F 3', + 0x21 => 'b3F 3', + 0x22 => 'A3F 3', + 0x23 => 'b2F 3', + 0x24 => 'A2F 3', + 0x25 => '3F 3', + 0x26 => '5F 3', + 0x27 => '7F 3', + 0x28 => '9F 3', + 0x22 => 'A3F 3', + 0x23 => 'b2F 3', + 0x24 => 'A2F 3', + 0x25 => '3F 3', + 0x26 => '5F 3', + 0x27 => '7F 3', + 0x28 => '9F 3', + }, + }, + 0x184d => { + Name => 'ReleaseMode', + Mask => 0xff, + PrintConv => { + 0 => 'Single Frame', + 1 => 'Continuous High Speed', + 3 => 'Continuous Low Speed', + 4 => 'Timer', + 32 => 'Mirror-Up', + 64 => 'Quiet', + }, + }, + 0x189d => { #PH (NC) + Name => 'CustomSettingsD4S', + Condition => '$$self{FirmwareVersion} =~ /^1.00/', + Notes => 'firmware version 1.00', + Format => 'undef[56]', + SubDirectory => { TagTable => 'Image::ExifTool::NikonCustom::SettingsD4' }, + }, + 0x18c2 => { # CSf1-c (no idea why it is so far away from the rest of the settings) + Name => 'MultiSelectorLiveViewMode', + Groups => { 1 => 'NikonCustom' }, + Condition => '$$self{FirmwareVersion} !~ /^1.00/', + Mask => 0xc0, + PrintConv => { + 0 => 'Reset', + 1 => 'Zoom', + 3 => 'None', + }, + }, + 0x18ea => { + Name => 'ISOAutoShutterTime', + Mask => 0x3f, + PrintConv => { + 0 => '1/4000 s', + 1 => '1/3200 s', + 2 => '1/2500 s', + 3 => '1/2000 s', + 4 => '1/1600 s', + 5 => '1/1250 s', + 6 => '1/1000 s', + 7 => '1/800 s', + 8 => '1/640 s', + 9 => '1/500 s', + 10 => '1/400 s', + 11 => '1/320 s', + 12 => '1/250 s', + 13 => '1/200 s', + 14 => '1/160 s', + 15 => '1/125 s', + 16 => '1/100 s', + 17 => '1/80 s', + 18 => '1/60 s', + 19 => '1/50 s', + 20 => '1/40 s', + 21 => '1/30 s', + 22 => '1/15 s', + 23 => '1/8 s', + 24 => '1/4 s', + 25 => '1/2 s', + 26 => '1 s', + 27 => '2 s', + 28 => '4 s', + 29 => '8 s', + 30 => '15 s', + 31 => '30 s', + 32 => 'Auto (Slowest)', + 33 => 'Auto (Slower)', + 34 => 'Auto', + 35 => 'Auto (Faster)', + 36 => 'Auto (Fastest)', + }, + }, + 0x18eb => { + Name => 'ISOAutoHiLimit', + Mask => 0xff, + PrintHex => 1, + PrintConv => { + 0x24 => 'ISO 200', + 0x26 => 'ISO 250', + 0x27 => 'ISO 280', + 0x28 => 'ISO 320', + 0x2a => 'ISO 400', + 0x2c => 'ISO 500', + 0x2d => 'ISO 560', + 0x2e => 'ISO 640', + 0x30 => 'ISO 800', + 0x32 => 'ISO 1000', + 0x33 => 'ISO 1100', + 0x34 => 'ISO 1250', + 0x36 => 'ISO 1600', + 0x38 => 'ISO 2000', + 0x39 => 'ISO 2200', + 0x3a => 'ISO 2500', + 0x3c => 'ISO 3200', + 0x3e => 'ISO 4000', + 0x3f => 'ISO 4500', + 0x40 => 'ISO 5000', + 0x42 => 'ISO 6400', + 0x44 => 'ISO 8000', + 0x45 => 'ISO 9000', + 0x46 => 'ISO 10000', + 0x48 => 'ISO 12800', + 0x4a => 'ISO 16000', + 0x4b => 'ISO 18000', + 0x4c => 'ISO 20000', + 0x4e => 'ISO 25600', + 0x50 => 'ISO 32000', + 0x51 => 'ISO 36000', + 0x52 => 'ISO 40000', + 0x54 => 'ISO 51200', + 0x56 => 'ISO Hi 0.3', + 0x57 => 'ISO Hi 0.5', + 0x58 => 'ISO Hi 0.7', + 0x5a => 'ISO Hi 1.0', + 0x60 => 'ISO Hi 2.0', + 0x66 => 'ISO Hi 3.0', + 0x6c => 'ISO Hi 4.0', + 0x72 => 'ISO Hi 5.0', + }, + }, + 0x193d => { + Name => 'CustomSettingsD4S', + Condition => '$$self{FirmwareVersion} !~ /^1.00/', + Notes => 'firmware version 1.01', + Format => 'undef[56]', + SubDirectory => { TagTable => 'Image::ExifTool::NikonCustom::SettingsD4' }, + }, +# 0x1978 => { #this decode works, but involves more bits than should be necessary +# Name => 'ShutterTrigger', +# Mask => 0xff, +# PrintConv => { +# 0 => 'Timer', +# 15 => 'Cable Release/Remote', +# 195 => 'Shutter Button', +# }, +# }, + 0x350b => { + Name => 'RollAngle', + Format => 'fixed32u', + Notes => 'converted to degrees of clockwise camera roll', + ValueConv => '$val < 180 ? -$val : 360 - $val', + ValueConvInv => '$val <= 0 ? -$val : 360 - $val', + PrintConv => 'sprintf("%.1f", $val)', + PrintConvInv => '$val', + }, + 0x350f => { + Name => 'PitchAngle', + Format => 'fixed32u', + Notes => 'converted to degrees of upward camera tilt', + ValueConv => '$val <= 180 ? $val : $val - 360', + ValueConvInv => '$val >= 0 ? $val : $val + 360', + PrintConv => 'sprintf("%.1f", $val)', + PrintConvInv => '$val', + }, + 0x3513 => { + Name => 'YawAngle', + Format => 'fixed32u', + Notes => 'the camera yaw angle when shooting in portrait orientation', + ValueConv => '$val <= 180 ? $val : $val - 360', + ValueConvInv => '$val >= 0 ? $val : $val + 360', + PrintConv => 'sprintf("%.1f", $val)', + PrintConvInv => '$val', + }, + 0x3693 => { + Name => 'Rotation', + Mask => 0x30, + PrintConv => { + 0 => 'Horizontal', + 1 => 'Rotate 270 CW', + 2 => 'Rotate 90 CW', + 3 => 'Rotate 180', + }, + }, + # note: DecryptLen currently set to 0x3697 +); + +# Flash information (ref JD) +%Image::ExifTool::Nikon::FlashInfo0100 = ( + %binaryDataAttrs, + DATAMEMBER => [ 9.2, 15, 16 ], + GROUPS => { 0 => 'MakerNotes', 2 => 'Camera' }, + NOTES => q{ + These tags are used by the D2H, D2Hs, D2X, D2Xs, D50, D70, D70s, D80 and + D200. + }, + # NOTE: Must set ByteOrder in SubDirectory if any multi-byte integer tags added + 0 => { + Name => 'FlashInfoVersion', + Format => 'string[4]', + Writable => 0, + }, + 4 => { #PH + Name => 'FlashSource', + PrintConv => { + 0 => 'None', + 1 => 'External', + 2 => 'Internal', + }, + }, + # 5 - values: 46,48,50,54,78 + 6 => { + Format => 'int8u[2]', + Name => 'ExternalFlashFirmware', + SeparateTable => 'FlashFirmware', + PrintConv => \%flashFirmware, + }, + 8 => { + Name => 'ExternalFlashFlags', + PrintConv => { 0 => '(none)', + BITMASK => { + 0 => 'Fired', #28 + 2 => 'Bounce Flash', #PH + 4 => 'Wide Flash Adapter', + 5 => 'Dome Diffuser', #28 + }, + }, + }, + 9.1 => { + Name => 'FlashCommanderMode', + Mask => 0x80, + PrintConv => { 0 => 'Off', 1 => 'On' }, + }, + 9.2 => { + Name => 'FlashControlMode', + Mask => 0x7f, + DataMember => 'FlashControlMode', + RawConv => '$$self{FlashControlMode} = $val', + PrintConv => \%flashControlMode, + SeparateTable => 'FlashControlMode', + }, + 10 => [ + { + Name => 'FlashOutput', + Condition => '$$self{FlashControlMode} >= 0x06', + ValueConv => '2 ** (-$val/6)', + ValueConvInv => '$val>0 ? -6*log($val)/log(2) : 0', + PrintConv => '$val>0.99 ? "Full" : sprintf("%.0f%%",$val*100)', + PrintConvInv => '$val=~/(\d+)/ ? $1/100 : 1', + }, + { + Name => 'FlashCompensation', + Format => 'int8s', + Priority => 0, + ValueConv => '-$val/6', + ValueConvInv => '-6 * $val', + PrintConv => 'Image::ExifTool::Exif::PrintFraction($val)', + PrintConvInv => 'Image::ExifTool::Exif::ConvertFraction($val)', + }, + ], + 11 => { + Name => 'FlashFocalLength', + RawConv => '$val ? $val : undef', + PrintConv => '"$val mm"', + PrintConvInv => '$val=~/(\d+)/; $1 || 0', + }, + 12 => { + Name => 'RepeatingFlashRate', + RawConv => '$val ? $val : undef', + PrintConv => '"$val Hz"', + PrintConvInv => '$val=~/(\d+)/; $1 || 0', + }, + 13 => { + Name => 'RepeatingFlashCount', + RawConv => '$val ? $val : undef', + }, + 14 => { #PH + Name => 'FlashGNDistance', + SeparateTable => 1, + PrintConv => \%flashGNDistance, + }, + 15 => { + Name => 'FlashGroupAControlMode', + Mask => 0x0f, + DataMember => 'FlashGroupAControlMode', + RawConv => '$$self{FlashGroupAControlMode} = $val', + PrintConv => \%flashControlMode, + SeparateTable => 'FlashControlMode', + }, + 16 => { + Name => 'FlashGroupBControlMode', + Mask => 0x0f, + DataMember => 'FlashGroupBControlMode', + RawConv => '$$self{FlashGroupBControlMode} = $val', + PrintConv => \%flashControlMode, + SeparateTable => 'FlashControlMode', + }, + 17 => [ + { + Name => 'FlashGroupAOutput', + Condition => '$$self{FlashGroupAControlMode} >= 0x06', + ValueConv => '2 ** (-$val/6)', + ValueConvInv => '$val>0 ? -6*log($val)/log(2) : 0', + PrintConv => '$val>0.99 ? "Full" : sprintf("%.0f%%",$val*100)', + PrintConvInv => '$val=~/(\d+)/ ? $1/100 : 1', + }, + { + Name => 'FlashGroupACompensation', + Format => 'int8s', + ValueConv => '-$val/6', + ValueConvInv => '-6 * $val', + PrintConv => '$val ? sprintf("%+.1f",$val) : 0', + PrintConvInv => '$val', + }, + ], + 18 => [ + { + Name => 'FlashGroupBOutput', + Condition => '$$self{FlashGroupBControlMode} >= 0x06', + ValueConv => '2 ** (-$val/6)', + ValueConvInv => '$val>0 ? -6*log($val)/log(2) : 0', + PrintConv => '$val>0.99 ? "Full" : sprintf("%.0f%%",$val*100)', + PrintConvInv => '$val=~/(\d+)/ ? $1/100 : 1', + }, + { + Name => 'FlashGroupBCompensation', + Format => 'int8s', + ValueConv => '-$val/6', + ValueConvInv => '-6 * $val', + PrintConv => '$val ? sprintf("%+.1f",$val) : 0', + PrintConvInv => '$val', + }, + ], +); + +# Flash information for D40, D40x, D3 and D300 (ref JD) +%Image::ExifTool::Nikon::FlashInfo0102 = ( + %binaryDataAttrs, + DATAMEMBER => [ 9.2, 16.1, 17.1, 17.2 ], + GROUPS => { 0 => 'MakerNotes', 2 => 'Camera' }, + NOTES => q{ + These tags are used by the D3 (firmware 1.x), D40, D40X, D60 and D300 + (firmware 1.00). + }, + # NOTE: Must set ByteOrder in SubDirectory if any multi-byte integer tags added + 0 => { + Name => 'FlashInfoVersion', + Format => 'string[4]', + Writable => 0, + }, + 4 => { #PH + Name => 'FlashSource', + PrintConv => { + 0 => 'None', + 1 => 'External', + 2 => 'Internal', + }, + }, + # 5 - values: 46,48,50,54,78 + 6 => { + Format => 'int8u[2]', + Name => 'ExternalFlashFirmware', + SeparateTable => 'FlashFirmware', + PrintConv => \%flashFirmware, + }, + 8 => { + Name => 'ExternalFlashFlags', + PrintConv => { BITMASK => { + 0 => 'Fired', #28 + 2 => 'Bounce Flash', #PH + 4 => 'Wide Flash Adapter', + 5 => 'Dome Diffuser', #28 + }}, + }, + 9.1 => { + Name => 'FlashCommanderMode', + Mask => 0x80, + PrintConv => { 0 => 'Off', 1 => 'On' }, + }, + 9.2 => { + Name => 'FlashControlMode', + Mask => 0x7f, + DataMember => 'FlashControlMode', + RawConv => '$$self{FlashControlMode} = $val', + PrintConv => \%flashControlMode, + SeparateTable => 'FlashControlMode', + }, + 10 => [ + { + Name => 'FlashOutput', + Condition => '$$self{FlashControlMode} >= 0x06', + ValueConv => '2 ** (-$val/6)', + ValueConvInv => '$val>0 ? -6*log($val)/log(2) : 0', + PrintConv => '$val>0.99 ? "Full" : sprintf("%.0f%%",$val*100)', + PrintConvInv => '$val=~/(\d+)/ ? $1/100 : 1', + }, + { + Name => 'FlashCompensation', + # this is the compensation from the camera (0x0012) for "Built-in" FlashType, or + # the compensation from the external unit (0x0017) for "Optional" FlashType - PH + Format => 'int8s', + Priority => 0, + ValueConv => '-$val/6', + ValueConvInv => '-6 * $val', + PrintConv => 'Image::ExifTool::Exif::PrintFraction($val)', + PrintConvInv => 'Image::ExifTool::Exif::ConvertFraction($val)', + }, + ], + 12 => { + Name => 'FlashFocalLength', + RawConv => '$val ? $val : undef', + PrintConv => '"$val mm"', + PrintConvInv => '$val=~/(\d+)/; $1 || 0', + }, + 13 => { + Name => 'RepeatingFlashRate', + RawConv => '$val ? $val : undef', + PrintConv => '"$val Hz"', + PrintConvInv => '$val=~/(\d+)/; $1 || 0', + }, + 14 => { + Name => 'RepeatingFlashCount', + RawConv => '$val ? $val : undef', + }, + 15 => { #PH + Name => 'FlashGNDistance', + SeparateTable => 1, + PrintConv => \%flashGNDistance, + }, + 16.1 => { + Name => 'FlashGroupAControlMode', + Mask => 0x0f, + Notes => 'note: group A tags may apply to the built-in flash settings for some models', + DataMember => 'FlashGroupAControlMode', + RawConv => '$$self{FlashGroupAControlMode} = $val', + PrintConv => \%flashControlMode, + SeparateTable => 'FlashControlMode', + }, + 17.1 => { + Name => 'FlashGroupBControlMode', + Mask => 0xf0, + Notes => 'note: group B tags may apply to group A settings for some models', + DataMember => 'FlashGroupBControlMode', + RawConv => '$$self{FlashGroupBControlMode} = $val', + PrintConv => \%flashControlMode, + SeparateTable => 'FlashControlMode', + }, + 17.2 => { #PH + Name => 'FlashGroupCControlMode', + Mask => 0x0f, + Notes => 'note: group C tags may apply to group B settings for some models', + DataMember => 'FlashGroupCControlMode', + RawConv => '$$self{FlashGroupCControlMode} = $val', + PrintConv => \%flashControlMode, + SeparateTable => 'FlashControlMode', + }, + 18 => [ + { + Name => 'FlashGroupAOutput', + Condition => '$$self{FlashGroupAControlMode} >= 0x06', + ValueConv => '2 ** (-$val/6)', + ValueConvInv => '$val>0 ? -6*log($val)/log(2) : 0', + PrintConv => '$val>0.99 ? "Full" : sprintf("%.0f%%",$val*100)', + PrintConvInv => '$val=~/(\d+)/ ? $1/100 : 1', + }, + { + Name => 'FlashGroupACompensation', + Format => 'int8s', + ValueConv => '-$val/6', + ValueConvInv => '-6 * $val', + PrintConv => '$val ? sprintf("%+.1f",$val) : 0', + PrintConvInv => '$val', + }, + ], + 19 => [ + { + Name => 'FlashGroupBOutput', + Condition => '$$self{FlashGroupBControlMode} >= 0x60', + ValueConv => '2 ** (-$val/6)', + ValueConvInv => '$val>0 ? -6*log($val)/log(2) : 0', + PrintConv => '$val>0.99 ? "Full" : sprintf("%.0f%%",$val*100)', + PrintConvInv => '$val=~/(\d+)/ ? $1/100 : 1', + }, + { + Name => 'FlashGroupBCompensation', + Format => 'int8s', + ValueConv => '-$val/6', + ValueConvInv => '-6 * $val', + PrintConv => '$val ? sprintf("%+.1f",$val) : 0', + PrintConvInv => '$val', + }, + ], + 20 => [ #PH + { + Name => 'FlashGroupCOutput', + Condition => '$$self{FlashGroupCControlMode} >= 0x06', + ValueConv => '2 ** (-$val/6)', + ValueConvInv => '$val>0 ? -6*log($val)/log(2) : 0', + PrintConv => '$val>0.99 ? "Full" : sprintf("%.0f%%",$val*100)', + PrintConvInv => '$val=~/(\d+)/ ? $1/100 : 1', + }, + { + Name => 'FlashGroupCCompensation', + Format => 'int8s', + ValueConv => '-$val/6', + ValueConvInv => '-6 * $val', + PrintConv => '$val ? sprintf("%+.1f",$val) : 0', + PrintConvInv => '$val', + }, + ], +); + +# Flash information for D90 and D700 (ref PH) +# - confirmed in detail for D800 (0105) - PH +%Image::ExifTool::Nikon::FlashInfo0103 = ( + %binaryDataAttrs, + DATAMEMBER => [ 9.2, 17.1, 18.1, 18.2 ], + GROUPS => { 0 => 'MakerNotes', 2 => 'Camera' }, + NOTES => q{ + These tags are used by the D3 (firmware 2.x), D3X, D3S, D4, D90, D300 + (firmware 1.10), D300S, D600, D700, D800, D3000, D3100, D3200, D5000, D5100, + D5200, D7000. + }, + # NOTE: Must set ByteOrder in SubDirectory if any multi-byte integer tags added + 0 => { + Name => 'FlashInfoVersion', + Format => 'string[4]', + Writable => 0, + }, + 4 => { #PH + Name => 'FlashSource', + PrintConv => { + 0 => 'None', + 1 => 'External', + 2 => 'Internal', + }, + }, + # 5 - values: 46,48,50,54,78 + 6 => { + Format => 'int8u[2]', + Name => 'ExternalFlashFirmware', + SeparateTable => 'FlashFirmware', + PrintConv => \%flashFirmware, + }, + 8 => { + Name => 'ExternalFlashFlags', + PrintConv => { BITMASK => { + 0 => 'Fired', #28 + 2 => 'Bounce Flash', #PH + 4 => 'Wide Flash Adapter', + 5 => 'Dome Diffuser', #28 + }}, + }, + 9.1 => { + Name => 'FlashCommanderMode', + Mask => 0x80, + PrintConv => { 0 => 'Off', 1 => 'On' }, + }, + 9.2 => { + Name => 'FlashControlMode', + Mask => 0x7f, + DataMember => 'FlashControlMode', + RawConv => '$$self{FlashControlMode} = $val', + PrintConv => \%flashControlMode, + SeparateTable => 'FlashControlMode', + }, + 10 => [ + { + Name => 'FlashOutput', + Condition => '$$self{FlashControlMode} >= 0x06', + ValueConv => '2 ** (-$val/6)', + ValueConvInv => '$val>0 ? -6*log($val)/log(2) : 0', + PrintConv => '$val>0.99 ? "Full" : sprintf("%.0f%%",$val*100)', + PrintConvInv => '$val=~/(\d+)/ ? $1/100 : 1', + }, + { + Name => 'FlashCompensation', + # this is the compensation from the camera (0x0012) for "Built-in" FlashType, or + # the compensation from the external unit (0x0017) for "Optional" FlashType - PH + Format => 'int8s', + Priority => 0, + ValueConv => '-$val/6', + ValueConvInv => '-6 * $val', + PrintConv => 'Image::ExifTool::Exif::PrintFraction($val)', + PrintConvInv => 'Image::ExifTool::Exif::ConvertFraction($val)', + }, + ], + 12 => { #JD + Name => 'FlashFocalLength', + RawConv => '($val and $val != 255) ? $val : undef', + PrintConv => '"$val mm"', + PrintConvInv => '$val=~/(\d+)/; $1 || 0', + }, + 13 => { #JD + Name => 'RepeatingFlashRate', + RawConv => '($val and $val != 255) ? $val : undef', + PrintConv => '"$val Hz"', + PrintConvInv => '$val=~/(\d+)/; $1 || 0', + }, + 14 => { #JD + Name => 'RepeatingFlashCount', + RawConv => '($val and $val != 255) ? $val : undef', + }, + 15 => { #28 + Name => 'FlashGNDistance', + SeparateTable => 1, + PrintConv => \%flashGNDistance, + }, + 16 => { #28 + Name => 'FlashColorFilter', + SeparateTable => 1, + PrintConv => \%flashColorFilter, + }, + 17.1 => { + Name => 'FlashGroupAControlMode', + Mask => 0x0f, + Notes => 'note: group A tags may apply to the built-in flash settings for some models', + DataMember => 'FlashGroupAControlMode', + RawConv => '$$self{FlashGroupAControlMode} = $val', + PrintConv => \%flashControlMode, + SeparateTable => 'FlashControlMode', + }, + 18.1 => { + Name => 'FlashGroupBControlMode', + Mask => 0xf0, + Notes => 'note: group B tags may apply to group A settings for some models', + DataMember => 'FlashGroupBControlMode', + RawConv => '$$self{FlashGroupBControlMode} = $val', + PrintConv => \%flashControlMode, + SeparateTable => 'FlashControlMode', + }, + 18.2 => { #PH + Name => 'FlashGroupCControlMode', + Mask => 0x0f, + Notes => 'note: group C tags may apply to group B settings for some models', + DataMember => 'FlashGroupCControlMode', + RawConv => '$$self{FlashGroupCControlMode} = $val', + PrintConv => \%flashControlMode, + SeparateTable => 'FlashControlMode', + }, + 0x13 => [ + { + Name => 'FlashGroupAOutput', + Condition => '$$self{FlashGroupAControlMode} >= 0x06', + ValueConv => '2 ** (-$val/6)', + ValueConvInv => '$val>0 ? -6*log($val)/log(2) : 0', + PrintConv => '$val>0.99 ? "Full" : sprintf("%.0f%%",$val*100)', + PrintConvInv => '$val=~/(\d+)/ ? $1/100 : 1', + }, + { + Name => 'FlashGroupACompensation', + Format => 'int8s', + ValueConv => '-$val/6', + ValueConvInv => '-6 * $val', + PrintConv => '$val ? sprintf("%+.1f",$val) : 0', + PrintConvInv => '$val', + }, + ], + 0x14 => [ + { + Name => 'FlashGroupBOutput', + Condition => '$$self{FlashGroupBControlMode} >= 0x60', + ValueConv => '2 ** (-$val/6)', + ValueConvInv => '$val>0 ? -6*log($val)/log(2) : 0', + PrintConv => '$val>0.99 ? "Full" : sprintf("%.0f%%",$val*100)', + PrintConvInv => '$val=~/(\d+)/ ? $1/100 : 1', + }, + { + Name => 'FlashGroupBCompensation', + Format => 'int8s', + ValueConv => '-$val/6', + ValueConvInv => '-6 * $val', + PrintConv => '$val ? sprintf("%+.1f",$val) : 0', + PrintConvInv => '$val', + }, + ], + 0x15 => [ #PH + { + Name => 'FlashGroupCOutput', + Condition => '$$self{FlashGroupCControlMode} >= 0x06', + ValueConv => '2 ** (-$val/6)', + ValueConvInv => '$val>0 ? -6*log($val)/log(2) : 0', + PrintConv => '$val>0.99 ? "Full" : sprintf("%.0f%%",$val*100)', + PrintConvInv => '$val=~/(\d+)/ ? $1/100 : 1', + }, + { + Name => 'FlashGroupCCompensation', + Format => 'int8s', + ValueConv => '-$val/6', + ValueConvInv => '-6 * $val', + PrintConv => '$val ? sprintf("%+.1f",$val) : 0', + PrintConvInv => '$val', + }, + ], + 0x1b => { #PH + Name => 'ExternalFlashCompensation', + Format => 'int8s', + Priority => 0, + ValueConv => '-$val/6', + ValueConvInv => '-6 * $val', + PrintConv => 'Image::ExifTool::Exif::PrintFraction($val)', + PrintConvInv => 'Image::ExifTool::Exif::ConvertFraction($val)', + }, + 0x1d => { #PH + Name => 'FlashExposureComp3', + Format => 'int8s', + # (does not include the built-in compensation for FlashType "Built-in,TTL&Comdr.") + Notes => 'does not include the effect of flash bracketing', + Priority => 0, + ValueConv => '-$val/6', + ValueConvInv => '-6 * $val', + PrintConv => 'Image::ExifTool::Exif::PrintFraction($val)', + PrintConvInv => 'Image::ExifTool::Exif::ConvertFraction($val)', + }, + 0x27 => { #PH (same as ShotInfoD800 0x4d2 but also valid for repeating flash) + Name => 'FlashExposureComp4', + Format => 'int8s', + Notes => 'includes the effect of flash bracketing. Valid for repeating flash', + Priority => 0, + ValueConv => '-$val/6', + ValueConvInv => '-6 * $val', + PrintConv => 'Image::ExifTool::Exif::PrintFraction($val)', + PrintConvInv => 'Image::ExifTool::Exif::ConvertFraction($val)', + }, + # 0x2b - related to flash power (PH, D800, 96=full,62=1/4,2=1/128) +); + +# Flash information for the D7100 (ref PH) +# (this is VERY similar to FlashInfo0107, but there are a few differences that +# would need to be resolved if these two definitions were to be combined) +%Image::ExifTool::Nikon::FlashInfo0106 = ( + %binaryDataAttrs, + GROUPS => { 0 => 'MakerNotes', 2 => 'Camera' }, + DATAMEMBER => [ 9.2, 17.1, 18.1, 18.2 ], + NOTES => 'These tags are used by the Df, D610, D3300, D5300, D7100 and Coolpix A.', + # NOTE: Must set ByteOrder in SubDirectory if any multi-byte integer tags added + 0 => { + Name => 'FlashInfoVersion', + Format => 'string[4]', + Writable => 0, + }, + 4 => { + Name => 'FlashSource', + PrintConv => { + 0 => 'None', + 1 => 'External', + 2 => 'Internal', + }, + }, + 6 => { + Format => 'int8u[2]', + Name => 'ExternalFlashFirmware', + SeparateTable => 'FlashFirmware', + PrintConv => \%flashFirmware, + }, + 8 => { + Name => 'ExternalFlashFlags', + PrintConv => { BITMASK => { + 0 => 'Fired', + 2 => 'Bounce Flash', + 4 => 'Wide Flash Adapter', + 5 => 'Dome Diffuser', # (NC, not true for the SB-910 anyway) + # 7 - ? (set for SB-910 when an advanced option is used, eg. diff pattern) + }}, + }, + 9.1 => { # (NC) + Name => 'FlashCommanderMode', + Mask => 0x80, + PrintConv => { 0 => 'Off', 1 => 'On' }, + }, + 9.2 => { + Name => 'FlashControlMode', + Mask => 0x7f, + DataMember => 'FlashControlMode', + RawConv => '$$self{FlashControlMode} = $val', + PrintConv => \%flashControlMode, + SeparateTable => 'FlashControlMode', + }, + # 10 - similar to 0x27 but zero sometimes when I don't think it should be + 12 => { + Name => 'FlashFocalLength', + Notes => 'only valid if flash pattern is "Standard Illumination"', + RawConv => '($val and $val != 255) ? $val : undef', + PrintConv => '"$val mm"', + PrintConvInv => '$val=~/(\d+)/; $1 || 0', + }, + 13 => { + Name => 'RepeatingFlashRate', + RawConv => '($val and $val != 255) ? $val : undef', + PrintConv => '"$val Hz"', + PrintConvInv => '$val=~/(\d+)/; $1 || 0', + }, + 14 => { + Name => 'RepeatingFlashCount', + RawConv => '($val and $val != 255) ? $val : undef', + }, + 15 => { # (NC) + Name => 'FlashGNDistance', + SeparateTable => 1, + PrintConv => \%flashGNDistance, + }, + 16 => { + Name => 'FlashColorFilter', + SeparateTable => 1, + PrintConv => \%flashColorFilter, + }, + 17.1 => { + Name => 'FlashGroupAControlMode', + Mask => 0x0f, + DataMember => 'FlashGroupAControlMode', + RawConv => '$$self{FlashGroupAControlMode} = $val', + PrintConv => \%flashControlMode, + SeparateTable => 'FlashControlMode', + }, + 18.1 => { + Name => 'FlashGroupBControlMode', + Mask => 0xf0, + DataMember => 'FlashGroupBControlMode', + RawConv => '$$self{FlashGroupBControlMode} = $val', + PrintConv => \%flashControlMode, + SeparateTable => 'FlashControlMode', + }, + 18.2 => { + Name => 'FlashGroupCControlMode', + Mask => 0x0f, + DataMember => 'FlashGroupCControlMode', + RawConv => '$$self{FlashGroupCControlMode} = $val', + PrintConv => \%flashControlMode, + SeparateTable => 'FlashControlMode', + }, + # 0x13 - same as 0x28 but not zero when flash group A is Off + # 0x14 - same as 0x29 but not zero when flash group B is Off + # 0x15 - same as 0x2a but not zero when flash group B is Off + # 0x1a - changes with illumination pattern (0=normal,1=narrow,2=wide), but other values seen + # 0x26 - changes when diffuser is used + 0x27 => [ + { + Name => 'FlashOutput', + Condition => '$$self{FlashControlMode} >= 0x06', + ValueConv => '2 ** (-$val/6)', + ValueConvInv => '$val>0 ? -6*log($val)/log(2) : 0', + PrintConv => '$val>0.99 ? "Full" : sprintf("%.0f%%",$val*100)', + PrintConvInv => '$val=~/(\d+)/ ? $1/100 : 1', + }, + { + Name => 'FlashCompensation', + Format => 'int8s', + Priority => 0, + ValueConv => '-$val/6', + ValueConvInv => '-6 * $val', + PrintConv => 'Image::ExifTool::Exif::PrintFraction($val)', + PrintConvInv => 'Image::ExifTool::Exif::ConvertFraction($val)', + }, + ], + 0x28 => [ + { + Name => 'FlashGroupAOutput', + Condition => '$$self{FlashGroupAControlMode} >= 0x06', + ValueConv => '2 ** (-$val/6)', + ValueConvInv => '$val>0 ? -6*log($val)/log(2) : 0', + PrintConv => '$val>0.99 ? "Full" : sprintf("%.0f%%",$val*100)', + PrintConvInv => '$val=~/(\d+)/ ? $1/100 : 1', + }, + { + Name => 'FlashGroupACompensation', + Format => 'int8s', + ValueConv => '-$val/6', + ValueConvInv => '-6 * $val', + PrintConv => '$val ? sprintf("%+.1f",$val) : 0', + PrintConvInv => '$val', + }, + ], + 0x29 => [ + { + Name => 'FlashGroupBOutput', + Condition => '$$self{FlashGroupBControlMode} >= 0x60', + ValueConv => '2 ** (-$val/6)', + ValueConvInv => '$val>0 ? -6*log($val)/log(2) : 0', + PrintConv => '$val>0.99 ? "Full" : sprintf("%.0f%%",$val*100)', + PrintConvInv => '$val=~/(\d+)/ ? $1/100 : 1', + }, + { + Name => 'FlashGroupBCompensation', + Format => 'int8s', + ValueConv => '-$val/6', + ValueConvInv => '-6 * $val', + PrintConv => '$val ? sprintf("%+.1f",$val) : 0', + PrintConvInv => '$val', + }, + ], + 0x2a => [ + { + Name => 'FlashGroupCOutput', + Condition => '$$self{FlashGroupCControlMode} >= 0x06', + ValueConv => '2 ** (-$val/6)', + ValueConvInv => '$val>0 ? -6*log($val)/log(2) : 0', + PrintConv => '$val>0.99 ? "Full" : sprintf("%.0f%%",$val*100)', + PrintConvInv => '$val=~/(\d+)/ ? $1/100 : 1', + }, + { + Name => 'FlashGroupCCompensation', + Format => 'int8s', + ValueConv => '-$val/6', + ValueConvInv => '-6 * $val', + PrintConv => '$val ? sprintf("%+.1f",$val) : 0', + PrintConvInv => '$val', + }, + ], +); + +# Flash information for the D4S/D750/D810/D5500/D7200 (0107) +# and D5/D500/D850/D3400 (0108) (ref 28) +%Image::ExifTool::Nikon::FlashInfo0107 = ( + %binaryDataAttrs, + GROUPS => { 0 => 'MakerNotes', 2 => 'Camera' }, + DATAMEMBER => [ 17.1, 18.1, 18.2 ], + NOTES => q{ + These tags are used by the D4S, D750, D810, D5500, D7200 (FlashInfoVersion + 0107) and the D5, D500, D850 and D3400 (FlashInfoVersion 0108). + }, + # NOTE: Must set ByteOrder in SubDirectory if any multi-byte integer tags added + 0 => { + Name => 'FlashInfoVersion', + Format => 'string[4]', + Writable => 0, + }, + 4 => { + Name => 'FlashSource', + PrintConv => { + 0 => 'None', + 1 => 'External', + 2 => 'Internal', + }, + }, + 6 => { + Format => 'int8u[2]', + Name => 'ExternalFlashFirmware', + SeparateTable => 'FlashFirmware', + PrintConv => \%flashFirmware, + }, + 8.1 => { + Name => 'ExternalFlashZoomOverride', + Mask => 0x80, + Notes => 'indicates that the user has overridden the flash zoom distance', + PrintConv => { 0 => 'No', 1 => 'Yes' }, + }, + 8.2 => { + Name => 'ExternalFlashStatus', + Mask => 0x01, + PrintConv => { + 0 => 'Flash Not Attached', + 1 => 'Flash Attached', + }, + }, + 9.1 => { + Name => 'ExternalFlashReadyState', + Mask => 0x07, + PrintConv => { + 0 => 'n/a', + 1 => 'Ready', + 6 => 'Not Ready', + }, + }, + 10 => { + Name => 'FlashCompensation', + # this is the compensation from the camera (0x0012) for "Built-in" FlashType, or + # the compensation from the external unit (0x0017) for "Optional" FlashType - PH + Format => 'int8s', + Priority => 0, + ValueConv => '-$val/6', + ValueConvInv => '-6 * $val', + PrintConv => 'Image::ExifTool::Exif::PrintFraction($val)', + PrintConvInv => 'Image::ExifTool::Exif::ConvertFraction($val)', + }, + 12 => { + Name => 'FlashFocalLength', + Notes => 'only valid if flash pattern is "Standard Illumination"', + RawConv => '($val and $val != 255) ? $val : undef', + PrintConv => '"$val mm"', + PrintConvInv => '$val=~/(\d+)/; $1 || 0', + }, + 13 => { + Name => 'RepeatingFlashRate', + RawConv => '($val and $val != 255) ? $val : undef', + PrintConv => '"$val Hz"', + PrintConvInv => '$val=~/(\d+)/; $1 || 0', + }, + 14 => { + Name => 'RepeatingFlashCount', + RawConv => '($val and $val != 255) ? $val : undef', + }, + 15 => { + Name => 'FlashGNDistance', + SeparateTable => 1, + PrintConv => \%flashGNDistance, + }, + 17.1 => { #PH + Name => 'FlashGroupAControlMode', + Mask => 0x0f, + Notes => 'note: group A tags may apply to the built-in flash settings for some models', + DataMember => 'FlashGroupAControlMode', + RawConv => '$$self{FlashGroupAControlMode} = $val', + PrintConv => \%flashControlMode, + SeparateTable => 'FlashControlMode', + }, + 18.1 => { #PH + Name => 'FlashGroupBControlMode', + Mask => 0xf0, + Notes => 'note: group B tags may apply to group A settings for some models', + DataMember => 'FlashGroupBControlMode', + RawConv => '$$self{FlashGroupBControlMode} = $val', + PrintConv => \%flashControlMode, + SeparateTable => 'FlashControlMode', + }, + 18.2 => { #PH + Name => 'FlashGroupCControlMode', + Mask => 0x0f, + Notes => 'note: group C tags may apply to group B settings for some models', + DataMember => 'FlashGroupCControlMode', + RawConv => '$$self{FlashGroupCControlMode} = $val', + PrintConv => \%flashControlMode, + SeparateTable => 'FlashControlMode', + }, + # 0x13 - very similar to 0x28 + # 0x18 or 0x19 may indicate flash illumination pattern (Standard, Center-weighted, Even) + 0x28 => [ #PH + { + Name => 'FlashGroupAOutput', + Condition => '$$self{FlashGroupAControlMode} >= 0x06', + ValueConv => '2 ** (-$val/6)', + ValueConvInv => '$val>0 ? -6*log($val)/log(2) : 0', + PrintConv => '$val>0.99 ? "Full" : sprintf("%.0f%%",$val*100)', + PrintConvInv => '$val=~/(\d+)/ ? $1/100 : 1', + }, + { + Name => 'FlashGroupACompensation', + Format => 'int8s', + ValueConv => '-$val/6', + ValueConvInv => '-6 * $val', + PrintConv => '$val ? sprintf("%+.1f",$val) : 0', + PrintConvInv => '$val', + }, + ], + 0x29 => [ #PH + { + Name => 'FlashGroupBOutput', + Condition => '$$self{FlashGroupBControlMode} >= 0x60', + ValueConv => '2 ** (-$val/6)', + ValueConvInv => '$val>0 ? -6*log($val)/log(2) : 0', + PrintConv => '$val>0.99 ? "Full" : sprintf("%.0f%%",$val*100)', + PrintConvInv => '$val=~/(\d+)/ ? $1/100 : 1', + }, + { + Name => 'FlashGroupBCompensation', + Format => 'int8s', + ValueConv => '-$val/6', + ValueConvInv => '-6 * $val', + PrintConv => '$val ? sprintf("%+.1f",$val) : 0', + PrintConvInv => '$val', + }, + ], + 0x2a => [ #PH + { + Name => 'FlashGroupCOutput', + Condition => '$$self{FlashGroupCControlMode} >= 0x06', + ValueConv => '2 ** (-$val/6)', + ValueConvInv => '$val>0 ? -6*log($val)/log(2) : 0', + PrintConv => '$val>0.99 ? "Full" : sprintf("%.0f%%",$val*100)', + PrintConvInv => '$val=~/(\d+)/ ? $1/100 : 1', + }, + { + Name => 'FlashGroupCCompensation', + Format => 'int8s', + ValueConv => '-$val/6', + ValueConvInv => '-6 * $val', + PrintConv => '$val ? sprintf("%+.1f",$val) : 0', + PrintConvInv => '$val', + }, + ], +); + +# Unknown Flash information +%Image::ExifTool::Nikon::FlashInfoUnknown = ( + %binaryDataAttrs, + GROUPS => { 0 => 'MakerNotes', 2 => 'Camera' }, + 0 => { + Name => 'FlashInfoVersion', + Format => 'string[4]', + Writable => 0, + }, +); + +# Multi exposure / image overlay information (ref PH) +%Image::ExifTool::Nikon::MultiExposure = ( + %binaryDataAttrs, + FORMAT => 'int32u', + GROUPS => { 0 => 'MakerNotes', 2 => 'Camera' }, + 0 => { + Name => 'MultiExposureVersion', + Format => 'string[4]', + Writable => 0, + }, + 1 => { + Name => 'MultiExposureMode', + PrintConv => { + 0 => 'Off', + 1 => 'Multiple Exposure', + 2 => 'Image Overlay', + 3 => 'HDR', #31 + }, + }, + 2 => 'MultiExposureShots', + 3 => { + Name => 'MultiExposureAutoGain', + PrintConv => \%offOn, + }, +); + +# HDR information (ref 32) +%Image::ExifTool::Nikon::HDRInfo = ( + %binaryDataAttrs, + GROUPS => { 0 => 'MakerNotes', 2 => 'Image' }, + # NOTE: Must set ByteOrder in SubDirectory if any multi-byte integer tags added + 0 => { + Name => 'HDRInfoVersion', + Format => 'string[4]', + }, + 4 => { + Name => 'HDR', + PrintConv => { + 0 => 'Off', + 1 => 'On', + 48 => 'Auto', #PH (NC) + }, + }, + 5 => { + Name => 'HDRLevel', + PrintConv => { + 0 => 'Auto', + 1 => '1 EV', + 2 => '2 EV', + 3 => '3 EV', + # 5 - seen for 1J4 + 255 => 'n/a', #PH + }, + }, + 6 => { + Name => 'HDRSmoothing', + PrintConv => { + 0 => 'Off', + 1 => 'Normal', + 2 => 'Low', + 3 => 'High', + 48 => 'Auto', #PH (NC) + 255 => 'n/a', #PH + }, + }, + 7 => { #PH (P330, HDRInfoVersion=0101) + Name => 'HDRLevel2', + PrintConv => { + 0 => 'Auto', + 1 => '1 EV', + 2 => '2 EV', + 3 => '3 EV', + 255 => 'n/a', + }, + }, +); + +# location information (ref PH) +%Image::ExifTool::Nikon::LocationInfo = ( + %binaryDataAttrs, + DATAMEMBER => [ 4 ], + GROUPS => { 0 => 'MakerNotes', 2 => 'Location' }, + NOTES => 'Tags written by some Nikon GPS-equipped cameras like the AW100.', + 0 => { + Name => 'LocationInfoVersion', + Format => 'undef[4]', + }, + 4 => { + Name => 'TextEncoding', + DataMember => 'TextEncoding', + RawConv => q{ + $$self{TextEncoding} = $Image::ExifTool::Nikon::nikonTextEncoding{$val} if $val; + return $val; + }, + PrintConv => \%Image::ExifTool::Nikon::nikonTextEncoding, + }, + # (the CountryCode and Location tag names chosen to correspond with XMP::iptcCore) + 5 => { + Name => 'CountryCode', + Format => 'undef[3]', + ValueConv => '$val=~s/\0.*//s; $val', # truncate at null + ValueConvInv => '$val', + }, + 8 => 'POILevel', #forum5782 + 9 => { + Name => 'Location', + Format => 'undef[70]', + RawConv => '$$self{TextEncoding} ? $self->Decode($val,$$self{TextEncoding},"MM") : $val', + RawConvInv => '$$self{TextEncoding} ? $self->Encode($val,$$self{TextEncoding},"MM") : $val', + }, +); + +# extra info found in IFD0 of NEF files (ref PH, Z6/Z7) +%Image::ExifTool::Nikon::NEFInfo = ( + GROUPS => { 0 => 'MakerNotes', 2 => 'Camera' }, + NOTES => q{ + As-yet unknown information found in SubIFD1 tag 0xc7d5 of NEF images from + cameras such as the Z6 and Z7, and NRW images from some Coolpix cameras. + }, + # 0x01 - undef[12] + # 0x02 - undef[148] + # 0x03 - undef[284] + # 0x04 - undef[148,212] + # 0x05 - undef[84] + # 0x06 - undef[116] + # 0x07 - undef[104] + # 0x08 - undef[24] + # 0x09 - undef[36] +); + +# tags in Nikon QuickTime videos (PH - observations with Coolpix S3) +# (similar information in Kodak,Minolta,Nikon,Olympus,Pentax and Sanyo videos) +%Image::ExifTool::Nikon::MOV = ( + PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData, + GROUPS => { 0 => 'MakerNotes', 2 => 'Camera' }, + FIRST_ENTRY => 0, + NOTES => q{ + This information is found in MOV and QT videos from some Nikon cameras. + }, + 0x00 => { + Name => 'Make', + Format => 'string[24]', + }, + 0x18 => { + Name => 'Model', + Description => 'Camera Model Name', + Format => 'string[8]', + }, + # (01 00 at offset 0x20) + 0x26 => { + Name => 'ExposureTime', + Format => 'int32u', + ValueConv => '$val ? 10 / $val : 0', + PrintConv => 'Image::ExifTool::Exif::PrintExposureTime($val)', + }, + 0x2a => { + Name => 'FNumber', + Format => 'rational64u', + PrintConv => 'sprintf("%.1f",$val)', + }, + 0x32 => { + Name => 'ExposureCompensation', + Format => 'rational64s', + PrintConv => 'Image::ExifTool::Exif::PrintFraction($val)', + }, + 0x44 => { + Name => 'WhiteBalance', + Format => 'int16u', + PrintConv => { + 0 => 'Auto', + 1 => 'Daylight', + 2 => 'Shade', + 3 => 'Fluorescent', #2 + 4 => 'Tungsten', + 5 => 'Manual', + }, + }, + 0x48 => { + Name => 'FocalLength', + Format => 'rational64u', + PrintConv => 'sprintf("%.1f mm",$val)', + }, + 0xaf => { + Name => 'Software', + Format => 'string[16]', + }, + 0xdf => { # (this is a guess ... could also be offset 0xdb) + Name => 'ISO', + Format => 'int16u', + RawConv => '$val < 50 ? undef : $val', # (not valid for Coolpix L10) + }, +); + +# Nikon metadata in AVI videos (PH) +%Image::ExifTool::Nikon::AVI = ( + NOTES => 'Nikon-specific RIFF tags found in AVI videos.', + GROUPS => { 0 => 'MakerNotes', 2 => 'Video' }, + nctg => { + Name => 'NikonTags', + SubDirectory => { TagTable => 'Image::ExifTool::Nikon::AVITags' }, + }, + ncth => { + Name => 'ThumbnailImage', + Groups => { 2 => 'Preview' }, + Binary => 1, + }, + ncvr => { + Name => 'NikonVers', + SubDirectory => { TagTable => 'Image::ExifTool::Nikon::AVIVers' }, + }, + ncvw => { + Name => 'PreviewImage', + Groups => { 2 => 'Preview' }, + RawConv => 'length($val) ? $val : undef', + Binary => 1, + }, +); + +# version information in AVI videos (PH) +%Image::ExifTool::Nikon::AVIVers = ( + GROUPS => { 0 => 'MakerNotes', 2 => 'Video' }, + PROCESS_PROC => \&ProcessNikonAVI, + FORMAT => 'string', + 0x01 => 'MakerNoteType', + 0x02 => { + Name => 'MakerNoteVersion', + Format => 'int8u', + ValueConv => 'my @a = reverse split " ", $val; join ".", @a;', + }, +); + +# tags in AVI videos (PH) +%Image::ExifTool::Nikon::AVITags = ( + GROUPS => { 0 => 'MakerNotes', 2 => 'Camera' }, + PROCESS_PROC => \&ProcessNikonAVI, + FORMAT => 'string', + NOTES => q{ + These tags and the AVIVer tags below are found in proprietary-format records + of Nikon AVI videos. + }, + 0x03 => 'Make', + 0x04 => 'Model', + 0x05 => { + Name => 'Software', + Format => 'undef', + ValueConv => '$val =~ tr/\0//d; $val', + }, + 0x06 => 'Equipment', # "NIKON DIGITAL CAMERA" + 0x07 => { # (guess) + Name => 'Orientation', + Format => 'int16u', + Groups => { 2 => 'Image' }, + PrintConv => \%Image::ExifTool::Exif::orientation, + }, + 0x08 => { + Name => 'ExposureTime', + Format => 'rational64u', + Groups => { 2 => 'Image' }, + PrintConv => 'Image::ExifTool::Exif::PrintExposureTime($val)', + }, + 0x09 => { + Name => 'FNumber', + Format => 'rational64u', + Groups => { 2 => 'Image' }, + PrintConv => 'sprintf("%.1f",$val)', + }, + 0x0a => { + Name => 'ExposureCompensation', + Format => 'rational64s', + Groups => { 2 => 'Image' }, + PrintConv => 'Image::ExifTool::Exif::PrintFraction($val)', + }, + 0x0b => { + Name => 'MaxApertureValue', + Format => 'rational64u', + ValueConv => '2 ** ($val / 2)', + PrintConv => 'sprintf("%.1f",$val)', + }, + 0x0c => { + Name => 'MeteringMode', # (guess) + Format => 'int16u', + PrintConv => { + 0 => 'Unknown', + 1 => 'Average', + 2 => 'Center-weighted average', + 3 => 'Spot', + 4 => 'Multi-spot', + 5 => 'Multi-segment', + 6 => 'Partial', + 255 => 'Other', + }, + }, + 0x0d => { # val: 0 + Name => 'Nikon_AVITags_0x000d', + Format => 'int16u', + Flags => [ 'Hidden', 'Unknown' ], + }, + 0x0e => { # val: 0 + Name => 'Nikon_AVITags_0x000e', + Format => 'int16u', + Flags => [ 'Hidden', 'Unknown' ], + }, + 0x0f => { + Name => 'FocalLength', + Format => 'rational64u', + PrintConv => 'sprintf("%.1f mm",$val)', + }, + 0x10 => { + Name => 'XResolution', + Format => 'rational64u', + Groups => { 2 => 'Image' }, + }, + 0x11 => { + Name => 'YResolution', + Format => 'rational64u', + Groups => { 2 => 'Image' }, + }, + 0x12 => { + Name => 'ResolutionUnit', + Format => 'int16u', + Groups => { 2 => 'Image' }, + PrintConv => { + 1 => 'None', + 2 => 'inches', + 3 => 'cm', + }, + }, + 0x13 => { + Name => 'DateTimeOriginal', # (guess) + Description => 'Date/Time Original', + Groups => { 2 => 'Time' }, + PrintConv => '$self->ConvertDateTime($val)', + }, + 0x14 => { + Name => 'CreateDate', # (guess) + Groups => { 2 => 'Time' }, + PrintConv => '$self->ConvertDateTime($val)', + }, + 0x15 => { + Name => 'Nikon_AVITags_0x0015', + Format => 'int16u', + Flags => [ 'Hidden', 'Unknown' ], + }, + 0x16 => { + Name => 'Duration', + Format => 'rational64u', + PrintConv => '"$val s"', + }, + 0x17 => { # val: 1 + Name => 'Nikon_AVITags_0x0017', + Format => 'int16u', + Flags => [ 'Hidden', 'Unknown' ], + }, + 0x18 => 'FocusMode', + 0x19 => { # vals: -5, -2, 3, 5, 6, 8, 11, 12, 14, 20, 22 + Name => 'Nikon_AVITags_0x0019', + Format => 'int32s', + Flags => [ 'Hidden', 'Unknown' ], + }, + 0x1b => { # vals: 1 (640x480), 1.25 (320x240) + Name => 'DigitalZoom', + Format => 'rational64u', + }, + 0x1c => { # (same as Nikon_0x000a) + Name => 'Nikon_AVITags_0x001c', + Format => 'rational64u', + Flags => [ 'Hidden', 'Unknown' ], + }, + 0x1d => 'ColorMode', + 0x1e => { # string[8] - val: "AUTO" + Name => 'Sharpness', # (guess, could also be ISOSelection) + }, + 0x1f => { # string[16] - val: "AUTO" + Name => 'WhiteBalance', # (guess, could also be ImageAdjustment) + }, + 0x20 => { # string[4] - val: "OFF" + Name => 'NoiseReduction', # (guess) + }, + 0x801a => { # val: 0 (why is the 0x8000 bit set in the ID?) + Name => 'Nikon_AVITags_0x801a', + Format => 'int32s', + Flags => [ 'Hidden', 'Unknown' ], + } +); + +# Nikon NCDT atoms (ref PH) +%Image::ExifTool::Nikon::NCDT = ( + GROUPS => { 0 => 'MakerNotes', 1 => 'Nikon', 2 => 'Video' }, + NOTES => q{ + Nikon-specific QuickTime tags found in the NCDT atom of MOV videos from + various Nikon models. + }, + NCHD => { + Name => 'MakerNoteVersion', + Format => 'undef', + ValueConv => q{ + $val =~ s/\0$//; # remove trailing null + $val =~ s/([\0-\x1f])/'.'.ord($1)/ge; + $val =~ s/\./ /; return $val; + }, + }, + NCTG => { + Name => 'NikonTags', + SubDirectory => { TagTable => 'Image::ExifTool::Nikon::NCTG' }, + }, + NCTH => { + Name => 'ThumbnailImage', + Groups => { 2 => 'Preview' }, + Format => 'undef', + Binary => 1, + }, + NCVW => { + Name => 'PreviewImage', + Groups => { 2 => 'Preview' }, + Format => 'undef', + Binary => 1, + }, + NCDB => { # (often 0 bytes long, or 4 null bytes) + Name => 'NikonNCDB', + SubDirectory => { TagTable => 'Image::ExifTool::Nikon::NCDB' }, + }, + NCM1 => { + Name => 'PreviewImage1', + Groups => { 2 => 'Preview' }, + Format => 'undef', + Binary => 1, + RawConv => 'length $val ? $val : undef', + }, + NCM2 => { #PH (guess - have only seen 0 bytes) + Name => 'PreviewImage2', + Groups => { 2 => 'Preview' }, + Format => 'undef', + Binary => 1, + RawConv => 'length $val ? $val : undef', + }, +); + +# Nikon NCDB tags from MOV videos (ref PH) +%Image::ExifTool::Nikon::NCDB = ( + GROUPS => { 0 => 'MakerNotes', 1 => 'Nikon', 2 => 'Video' }, + # the following probably contain encrypted data -- look into decryping these! + # OP01 - 320 bytes, starts with "0200" (D600,D610,D810,D3200,D5200) + # - 638 bytes, starts with "0200" (D7100) + # OP02 - 2048 bytes, starts with "0200" (D810) +); + +# Nikon NCTG tags from MOV videos (ref PH) +%Image::ExifTool::Nikon::NCTG = ( + PROCESS_PROC => \&ProcessNikonMOV, + GROUPS => { 0 => 'MakerNotes', 2 => 'Camera' }, + NOTES => q{ + These tags are found in proprietary-format records of the NCTG atom in MOV + videos from some Nikon cameras. + }, + 0x01 => 'Make', + 0x02 => 'Model', + 0x03 => 'Software', + 0x11 => { + Name => 'CreateDate', #(guess, but matches QuickTime CreateDate) + Groups => { 2 => 'Time' }, + PrintConv => '$self->ConvertDateTime($val)', + }, + 0x12 => { + Name => 'DateTimeOriginal', #(guess, but time is 1 sec before tag 0x11) + Description => 'Date/Time Original', + Groups => { 2 => 'Time' }, + PrintConv => '$self->ConvertDateTime($val)', + }, + 0x13 => { + Name => 'FrameCount', + # int32u[2]: "467 0", "1038 0", "1127 0" + ValueConv => '$val =~ s/ 0$//; $val', # (not sure what the extra "0" is for) + }, + # 0x14 - int32u[2]: "0 0" + # 0x15 - int32u[2]: "0 0" + 0x16 => { + Name => 'FrameRate', + Groups => { 2 => 'Video' }, + PrintConv => 'int($val * 1000 + 0.5) / 1000', + }, + # 0x17 - rational62u: same value as FrameRate + # 0x18 - int16u: 1, 2 + 0x19 => { + Name => 'TimeZone', + Groups => { 2 => 'Time' }, + }, + # 0x21 - int16u: 1, 2 + 0x22 => { + Name => 'FrameWidth', + Groups => { 2 => 'Video' }, + }, + 0x23 => { + Name => 'FrameHeight', + Groups => { 2 => 'Video' }, + }, + # 0x24 - int16u: 1, 2 + # 0x31 - int16u: 0, 1, 2 + 0x32 => { #(guess) + Name => 'AudioChannels', + Groups => { 2 => 'Audio' }, + }, + 0x33 => { + Name => 'AudioBitsPerSample', + Groups => { 2 => 'Audio' }, + }, + 0x34 => { + Name => 'AudioSampleRate', + Groups => { 2 => 'Audio' }, + }, + # 0x101 - int16u[4]: "160 120 1280 720", "160 120 3840 2160" + # 0x102 - int16u[8]: "640 360 0 0 0 0 0 0", "640 360 1920 1080 0 0 0 0" + # 0x1001 - int16s: 0 + 0x1002 => { + Name => 'NikonDateTime', #? + Groups => { 2 => 'Time' }, + PrintConv => '$self->ConvertDateTime($val)', + }, + # 0x1011 - int32u: 0 + # 0x1012 - int32u: 0 + 0x1013 => { #HayoBaan + Name => 'ElectronicVR', + PrintConv => \%offOn, + }, + # 0x1014 - int16u: 1 + # 0x1021 - int32u[32]: all zeros +# +# 0x110**** tags correspond to 0x**** tags in Exif::Main +# + 0x110829a => { #34 + Name => 'ExposureTime', + PrintConv => 'Image::ExifTool::Exif::PrintExposureTime($val)', + }, + 0x110829d => { #34 + Name => 'FNumber', + PrintConv => 'Image::ExifTool::Exif::PrintFNumber($val)', + }, + 0x1108822 => { + Name => 'ExposureProgram', + PrintConv => { + 0 => 'Not Defined', + 1 => 'Manual', + 2 => 'Program AE', + 3 => 'Aperture-priority AE', + 4 => 'Shutter speed priority AE', + 5 => 'Creative (Slow speed)', + 6 => 'Action (High speed)', + 7 => 'Portrait', + 8 => 'Landscape', + # 9 => 'Bulb', # (non-standard Canon value) + }, + }, + 0x1109204 => { + Name => 'ExposureCompensation', + PrintConv => 'Image::ExifTool::Exif::PrintFraction($val)', + }, + 0x1109207 => { + Name => 'MeteringMode', + PrintConv => { + 0 => 'Unknown', + 1 => 'Average', + 2 => 'Center-weighted average', + 3 => 'Spot', + 4 => 'Multi-spot', + 5 => 'Multi-segment', + 6 => 'Partial', + 255 => 'Other', + }, + }, + 0x110920a => { #34 + Name => 'FocalLength', + PrintConv => 'sprintf("%.1f mm",$val)', + }, + 0x110a431 => 'SerialNumber', + 0x110a432 => { + Name => 'LensInfo', + PrintConv => \&Image::ExifTool::Exif::PrintLensInfo, + }, + 0x110a433 => 'LensMake', + 0x110a434 => 'LensModel', + 0x110a435 => 'LensSerialNumber', +# +# 0x120**** tags correspond to 0x**** tags in GPS::Main +# + 0x1200000 => { + Name => 'GPSVersionID', + Groups => { 1 => 'GPS', 2 => 'Location' }, + PrintConv => '$val =~ tr/ /./; $val', + }, + 0x1200001 => { + Name => 'GPSLatitudeRef', + Groups => { 1 => 'GPS', 2 => 'Location' }, + PrintConv => { + N => 'North', + S => 'South', + }, + }, + 0x1200002 => { + Name => 'GPSLatitude', + Groups => { 1 => 'GPS', 2 => 'Location' }, + ValueConv => q{ + require Image::ExifTool::GPS; + Image::ExifTool::GPS::ToDegrees($val); + }, + PrintConv => 'Image::ExifTool::GPS::ToDMS($self, $val, 1)', + }, + 0x1200003 => { + Name => 'GPSLongitudeRef', + Groups => { 1 => 'GPS', 2 => 'Location' }, + PrintConv => { + E => 'East', + W => 'West', + }, + }, + 0x1200004 => { + Name => 'GPSLongitude', + Groups => { 1 => 'GPS', 2 => 'Location' }, + ValueConv => q{ + require Image::ExifTool::GPS; + Image::ExifTool::GPS::ToDegrees($val); + }, + PrintConv => 'Image::ExifTool::GPS::ToDMS($self, $val, 1)', + }, + 0x1200005 => { + Name => 'GPSAltitudeRef', + Groups => { 1 => 'GPS', 2 => 'Location' }, + PrintConv => { + 0 => 'Above Sea Level', + 1 => 'Below Sea Level', + }, + }, + 0x1200006 => { + Name => 'GPSAltitude', + Groups => { 1 => 'GPS', 2 => 'Location' }, + PrintConv => '$val =~ /^(inf|undef)$/ ? $val : "$val m"', + }, + 0x1200007 => { + Name => 'GPSTimeStamp', + Groups => { 1 => 'GPS', 2 => 'Time' }, + ValueConv => q{ + require Image::ExifTool::GPS; + Image::ExifTool::GPS::ConvertTimeStamp($val); + }, + PrintConv => 'Image::ExifTool::GPS::PrintTimeStamp($val)', + }, + 0x1200008 => { + Name => 'GPSSatellites', + Groups => { 1 => 'GPS', 2 => 'Location' }, + }, + 0x1200010 => { + Name => 'GPSImgDirectionRef', + Groups => { 1 => 'GPS', 2 => 'Location' }, + PrintConv => { + M => 'Magnetic North', + T => 'True North', + }, + }, + 0x1200011 => { + Name => 'GPSImgDirection', + Groups => { 1 => 'GPS', 2 => 'Location' }, + }, + 0x1200012 => { + Name => 'GPSMapDatum', + Groups => { 1 => 'GPS', 2 => 'Location' }, + }, + 0x120001d => { + Name => 'GPSDateStamp', + Groups => { 1 => 'GPS', 2 => 'Time' }, + ValueConv => 'Image::ExifTool::Exif::ExifDate($val)', + }, +# +# 0x200**** tags correspond to 0x**** tags in Nikon::Main +# (must be duplicated here so tagInfo "Table" entry will point to correct table. +# Also there would be a problem with the PRINT_CONV from the Main table) +# + 0x2000001 => { + Name => 'MakerNoteVersion', + PrintConv => '$_=$val;s/^(\d{2})/$1\./;s/^0//;$_', + }, + 0x2000005 => 'WhiteBalance', + 0x2000007 => { Name => 'FocusMode', Writable => 'string' }, #34 + 0x200000b => 'WhiteBalanceFineTune', + 0x200001b => { + Name => 'CropHiSpeed', + Writable => 'int16u', + Count => 7, + PrintConv => \%cropHiSpeed, + }, + 0x200001e => { + Name => 'ColorSpace', + PrintConv => { + 1 => 'sRGB', + 2 => 'Adobe RGB', + }, + }, + 0x200001f => { + Name => 'VRInfo', + SubDirectory => { TagTable => 'Image::ExifTool::Nikon::VRInfo' }, + }, + 0x2000022 => { + Name => 'ActiveD-Lighting', + Writable => 'int16u', + PrintConv => { + 0 => 'Off', + 1 => 'Low', + 3 => 'Normal', + 5 => 'High', + 7 => 'Extra High', + 8 => 'Extra High 1', + 9 => 'Extra High 2', + 10 => 'Extra High 3', + 11 => 'Extra High 4', + 0xffff => 'Auto', + }, + }, + 0x2000023 => [ + { #PH (D300, but also found in D3,D3S,D3X,D90,D300S,D700,D3000,D5000) + Name => 'PictureControlData', + Condition => '$$valPt =~ /^01/', + Writable => 'undef', + Permanent => 0, + Flags => [ 'Binary', 'Protected' ], + SubDirectory => { TagTable => 'Image::ExifTool::Nikon::PictureControl' }, + },{ #28 + Name => 'PictureControlData', + Condition => '$$valPt =~ /^02/', + Writable => 'undef', + Permanent => 0, + Flags => [ 'Binary', 'Protected' ], + SubDirectory => { TagTable => 'Image::ExifTool::Nikon::PictureControl2' }, + },{ + Name => 'PictureControlData', + Condition => '$$valPt =~ /^03/', + Writable => 'undef', + Permanent => 0, + Flags => [ 'Binary', 'Protected' ], + SubDirectory => { TagTable => 'Image::ExifTool::Nikon::PictureControl3' }, + },{ + Name => 'PictureControlData', + Writable => 'undef', + Permanent => 0, + Flags => [ 'Binary', 'Protected' ], + SubDirectory => { TagTable => 'Image::ExifTool::Nikon::PictureControlUnknown' }, + }, + ], + 0x2000024 => { + Name => 'WorldTime', + SubDirectory => { TagTable => 'Image::ExifTool::Nikon::WorldTime' }, + }, + 0x2000025 => { #34 + Name => 'ISOInfo', + SubDirectory => { + TagTable => 'Image::ExifTool::Nikon::ISOInfo', + ByteOrder => 'BigEndian', # (BigEndian even for D810, which is a little-endian camera) + }, + }, + 0x200002a => { #23 (this tag added with D3 firmware 1.10 -- also written by Nikon utilities) + Name => 'VignetteControl', + Writable => 'int16u', + PrintConv => { + 0 => 'Off', + 1 => 'Low', + 3 => 'Normal', + 5 => 'High', + }, + }, + 0x200002c => { + Name => 'UnknownInfo', + SubDirectory => { TagTable => 'Image::ExifTool::Nikon::UnknownInfo' }, + }, + # 0x200002d - int16u[3]: "512 0 0" + 0x2000032 => { + Name => 'UnknownInfo2', + SubDirectory => { TagTable => 'Image::ExifTool::Nikon::UnknownInfo2' }, + }, + 0x2000039 => { + Name => 'LocationInfo', + SubDirectory => { TagTable => 'Image::ExifTool::Nikon::LocationInfo' }, + }, + # 0x200003f - rational64s[2]: "0 0" + # 0x2000042 - undef[6]: "0100\x03\0" + # 0x2000043 - undef[12]: all zeros + 0x2000083 => { + Name => 'LensType', + # credit to Tom Christiansen (ref 7) for figuring this out... + PrintConv => q[$_ = $val ? Image::ExifTool::DecodeBits($val, + { + 0 => 'MF', + 1 => 'D', + 2 => 'G', + 3 => 'VR', + }) : 'AF'; + # remove commas and change "D G" to just "G" + s/,//g; s/\bD G\b/G/; $_ + ], + }, + 0x2000084 => { + Name => "Lens", + # short focal, long focal, aperture at short focal, aperture at long focal + PrintConv => \&Image::ExifTool::Exif::PrintLensInfo, + }, + 0x2000087 => { + Name => 'FlashMode', + Writable => 'int8u', + PrintConv => { + 0 => 'Did Not Fire', + 1 => 'Fired, Manual', #14 + 3 => 'Not Ready', #28 + 7 => 'Fired, External', #14 + 8 => 'Fired, Commander Mode', + 9 => 'Fired, TTL Mode', + }, + }, + 0x2000098 => [ + { #8 + Condition => '$$valPt =~ /^0100/', # D100, D1X - PH + Name => 'LensData0100', + SubDirectory => { TagTable => 'Image::ExifTool::Nikon::LensData00' }, + }, + { #8 + Condition => '$$valPt =~ /^0101/', # D70, D70s - PH + Name => 'LensData0101', + SubDirectory => { TagTable => 'Image::ExifTool::Nikon::LensData01' }, + }, + # note: this information is encrypted if the version is 02xx + { #8 + # 0201 - D200, D2Hs, D2X and D2Xs + # 0202 - D40, D40X and D80 + # 0203 - D300 + Condition => '$$valPt =~ /^020[1-3]/', + Name => 'LensData0201', + SubDirectory => { + TagTable => 'Image::ExifTool::Nikon::LensData01', + ProcessProc => \&Image::ExifTool::Nikon::ProcessNikonEncrypted, + WriteProc => \&Image::ExifTool::Nikon::ProcessNikonEncrypted, + DecryptStart => 4, + }, + }, + { #PH + Condition => '$$valPt =~ /^0204/', # D90, D7000 + Name => 'LensData0204', + SubDirectory => { + TagTable => 'Image::ExifTool::Nikon::LensData0204', + ProcessProc => \&Image::ExifTool::Nikon::ProcessNikonEncrypted, + WriteProc => \&Image::ExifTool::Nikon::ProcessNikonEncrypted, + DecryptStart => 4, + }, + }, + { + Condition => '$$valPt =~ /^040[01]/', # 0=1J1/1V1, 1=1J2 + Name => 'LensData0400', + SubDirectory => { + TagTable => 'Image::ExifTool::Nikon::LensData0400', + ProcessProc => \&Image::ExifTool::Nikon::ProcessNikonEncrypted, + WriteProc => \&Image::ExifTool::Nikon::ProcessNikonEncrypted, + DecryptStart => 4, + }, + }, + { + Condition => '$$valPt =~ /^0402/', # 1J3/1S1/1V2 + Name => 'LensData0402', + SubDirectory => { + TagTable => 'Image::ExifTool::Nikon::LensData0402', + ProcessProc => \&Image::ExifTool::Nikon::ProcessNikonEncrypted, + WriteProc => \&Image::ExifTool::Nikon::ProcessNikonEncrypted, + DecryptStart => 4, + }, + }, + { + Condition => '$$valPt =~ /^0403/', # 1J4,1J5 + Name => 'LensData0403', + SubDirectory => { + TagTable => 'Image::ExifTool::Nikon::LensData0403', + ProcessProc => \&Image::ExifTool::Nikon::ProcessNikonEncrypted, + WriteProc => \&Image::ExifTool::Nikon::ProcessNikonEncrypted, + DecryptStart => 4, + }, + }, + { + Condition => '$$valPt =~ /^0800/', # Z6/Z7 + Name => 'LensData0800', + SubDirectory => { + TagTable => 'Image::ExifTool::Nikon::LensData0800', + ProcessProc => \&Image::ExifTool::Nikon::ProcessNikonEncrypted, + WriteProc => \&Image::ExifTool::Nikon::ProcessNikonEncrypted, + DecryptStart => 4, + ByteOrder => 'LittleEndian', + }, + }, + { + Name => 'LensDataUnknown', + SubDirectory => { + TagTable => 'Image::ExifTool::Nikon::LensDataUnknown', + ProcessProc => \&Image::ExifTool::Nikon::ProcessNikonEncrypted, + WriteProc => \&Image::ExifTool::Nikon::ProcessNikonEncrypted, + DecryptStart => 4, + }, + }, + ], + 0x20000a7 => { # Number of shots taken by camera so far (ref 2) + Name => 'ShutterCount', + PrintConv => '$val == 4294965247 ? "n/a" : $val', + }, + 0x20000a8 => [ + { + Name => 'FlashInfo0100', + Condition => '$$valPt =~ /^010[01]/', + SubDirectory => { TagTable => 'Image::ExifTool::Nikon::FlashInfo0100' }, + }, + { + Name => 'FlashInfo0102', + Condition => '$$valPt =~ /^0102/', + SubDirectory => { TagTable => 'Image::ExifTool::Nikon::FlashInfo0102' }, + }, + { + Name => 'FlashInfo0103', + # (0104 for D7000, 0105 for D800) + Condition => '$$valPt =~ /^010[345]/', + SubDirectory => { TagTable => 'Image::ExifTool::Nikon::FlashInfo0103' }, + }, + { + Name => 'FlashInfo0106', # (0106 for D7100) + Condition => '$$valPt =~ /^0106/', + SubDirectory => { TagTable => 'Image::ExifTool::Nikon::FlashInfo0106' }, + }, + { + Name => 'FlashInfo0107', # (0107 for D4S/D750/D810/D5500/D7200, 0108 for D5/D500/D3400) + Condition => '$$valPt =~ /^010[78]/', + SubDirectory => { TagTable => 'Image::ExifTool::Nikon::FlashInfo0107' }, + }, + { + Name => 'FlashInfoUnknown', + SubDirectory => { TagTable => 'Image::ExifTool::Nikon::FlashInfoUnknown' }, + }, + ], + 0x20000ab => { Name => 'VariProgram', Writable => 'string' }, #2 (scene mode for DSLR's - PH) + 0x20000b1 => { #34 + Name => 'HighISONoiseReduction', + Writable => 'int16u', + PrintConv => { + 0 => 'Off', + 1 => 'Minimal', # for high ISO (>800) when setting is "Off" + 2 => 'Low', # Low,Normal,High take effect for ISO > 400 + 3 => 'Medium Low', + 4 => 'Normal', + 5 => 'Medium High', + 6 => 'High', + }, + }, + 0x20000b7 => { + Name => 'AFInfo2', + SubDirectory => { TagTable => 'Image::ExifTool::Nikon::AFInfo2' }, + }, + # 0x20000c0 - undef[8] + 0x20000c3 => { + Name => 'BarometerInfo', + SubDirectory => { + TagTable => 'Image::ExifTool::Nikon::BarometerInfo', + # (little-endian in II EXIF, big-endian in MOV) + }, + }, +); + +# Nikon composite tags +%Image::ExifTool::Nikon::Composite = ( + GROUPS => { 2 => 'Camera' }, + LensSpec => { + Require => { + 0 => 'Nikon:Lens', + 1 => 'Nikon:LensType', + }, + ValueConv => '"$val[0] $val[1]"', + PrintConv => '"$prt[0] $prt[1]"', + }, + LensID => { + SeparateTable => 'Nikon LensID', # print values in a separate table + Require => { + 0 => 'Nikon:LensIDNumber', + 1 => 'LensFStops', + 2 => 'MinFocalLength', + 3 => 'MaxFocalLength', + 4 => 'MaxApertureAtMinFocal', + 5 => 'MaxApertureAtMaxFocal', + 6 => 'MCUVersion', + 7 => 'Nikon:LensType', + }, + # construct lens ID string as per ref 11 + ValueConv => 'sprintf("%.2X"." %.2X"x7, @raw)', + PrintConv => \%nikonLensIDs, + }, + AutoFocus => { + Require => { + 0 => 'Nikon:PhaseDetectAF', + 1 => 'Nikon:ContrastDetectAF', + }, + ValueConv => '($val[0] or $val[1]) ? 1 : 0', + PrintConv => \%offOn, + }, +); + +# add our composite tags +Image::ExifTool::AddCompositeTags('Image::ExifTool::Nikon'); + +#------------------------------------------------------------------------------ +# Process Nikon AVI tags (D5000 videos) +# Inputs: 0) ExifTool object ref, 1) dirInfo ref, 2) tag table ref +# Returns: 1 on success +sub ProcessNikonAVI($$$) +{ + my ($et, $dirInfo, $tagTablePtr) = @_; + my $dataPt = $$dirInfo{DataPt}; + my $pos = $$dirInfo{DirStart} || 0; + my $dirEnd = $pos + $$dirInfo{DirLen}; + $et->VerboseDir($dirInfo, undef, $$dirInfo{DirLen}); + SetByteOrder('II'); + while ($pos + 4 <= $dirEnd) { + my $tag = Get16u($dataPt, $pos); + my $size = Get16u($dataPt, $pos + 2); + $pos += 4; + last if $pos + $size > $dirEnd; + $et->HandleTag($tagTablePtr, $tag, undef, + DataPt => $dataPt, + Start => $pos, + Size => $size, + ); + $pos += $size; + } + return 1; +} + +#------------------------------------------------------------------------------ +# Print conversion for Nikon AF points +# Inputs: 0) value to convert (as a string of hex bytes), +# 1) lookup for AF point bit number (starting at 1) +sub PrintAFPoints($$) +{ + my ($val, $afPoints) = @_; + my ($i, $j, @points); + $val =~ tr/ //d; # remove spaces from hex string + my @dat = unpack 'C*', pack 'H*', $val; # convert to array of bytes + # loop through all bytes to find active AF points + for ($i=0; $i<=@dat; ++$i) { + next unless $dat[$i]; + for ($j=0; $j<8; ++$j) { + next unless $dat[$i] & (1 << $j); + my $point = $$afPoints{$i*8 + $j + 1}; + push @points, $point if defined $point; + } + } + return '(none)' unless @points; + # sort the points and return as comma-separated string + return join ',', sort { + return $a cmp $b if length($a) == length($b); + return substr($a,0,1).'0'.substr($a,1,1) cmp $b if length($a) == 2; + return $a cmp substr($b,0,1).'0'.substr($b,1,1); + } @points; +} + +#------------------------------------------------------------------------------ +# Inverse print conversion for AF points +# Inputs: 0) AF point string, 1) AF point lookup +# Returns: AF point data as a string of hex bytes +sub PrintAFPointsInv($$) +{ + my ($val, $afPoints) = @_; + my @points = ($val =~ /[A-Za-z]\d+/g); + my $size = int((scalar(keys %$afPoints) + 7) / 8); + my @dat = (0) x $size; + if (@points) { + my (%bitNum, $point); + $bitNum{$$afPoints{$_}} = $_ foreach keys %$afPoints; # build reverse lookup + foreach $point (@points) { + my $bitNum = $bitNum{uc $point} or next; + my $byte = int(($bitNum - 1) / 8); + $dat[$byte] |= (1 << (($bitNum - 1) % 8)); + } + } + return join(" ", unpack("H2"x$size, pack('C*', @dat))); +} + +#------------------------------------------------------------------------------ +# Get AF point name for grid-type AF +# Inputs: 0) AF point number, 1) number of columns, 2) true for inverse conversion +# Returns: AF point name, or undef +sub GetAFPointGrid($$;$) +{ + my ($val, $ncol, $inv) = @_; + if ($inv) { + return undef unless $val =~ /^([A-J])(\d+)$/i; + return (ord(uc($1))-65) * $ncol + $2 - 1; + } else { + my $row = int(($val + 0.5) / $ncol); + my $col = $val - $ncol * $row + 1; + return chr(65+$row) . $col; + } +} + +#------------------------------------------------------------------------------ +# Print conversion for grid-type AF points +# Inputs: 0) value to convert (as a string of hex bytes), +# 1) number of columns in grid +sub PrintAFPointsGrid($$) +{ + my ($val, $ncol) = @_; + my ($i, $j, @points); + $val =~ tr/ //d; # remove spaces from hex string + my @dat = unpack 'C*', pack 'H*', $val; # convert to array of bytes + # loop through all bytes to find active AF points + for ($i=0; $i<@dat; ++$i) { + next unless $dat[$i]; + for ($j=0; $j<8; ++$j) { + next unless $dat[$i] & (1 << $j); + my $point = GetAFPointGrid($i*8 + $j, $ncol); + push @points, $point if defined $point; + } + } + return '(none)' unless @points; + return join ',', @points; # return as comma-separated string +} + +#------------------------------------------------------------------------------ +# Inverse print conversion for AF points +# Inputs: 0) AF point string, 1) number of columns, 2) size of data +# Returns: AF point data as a string of hex bytes +sub PrintAFPointsGridInv($$$) +{ + my ($val, $ncol, $size) = @_; + my @points = ($val =~ /[A-Za-z]\d+/g); + my @dat = (0) x $size; + foreach (@points) { + my $n = GetAFPointGrid($_, $ncol, 1); + next unless defined $n; + my $byte = int($n / 8); + next if $byte > $size; + $dat[$byte] |= (1 << ($n - $byte * 8)); + } + return join(" ", unpack("H2"x$size, pack('C*', @dat))); +} + +#------------------------------------------------------------------------------ +# Print PictureControl value +# Inputs: 0) value (with 0x80 subtracted), +# 1) 'Normal' (0 value) string (default 'Normal') +# 2) format string for numbers (default '%+d'), 3) v2 divisor +# Returns: PrintConv value +sub PrintPC($;$$$) +{ + my ($val, $norm, $fmt, $div) = @_; + return $norm || 'Normal' if $val == 0; + return 'n/a' if $val == 0x7f; + return 'Auto' if $val == -128; + # -127 = custom curve created in Camera Control Pro (show as "User" by D3) - ref 28 + return 'User' if $val == -127; #28 + return sprintf($fmt || '%+d', $val / ($div || 1)); +} + +#------------------------------------------------------------------------------ +# Inverse of PrintPC +# Inputs: 0) PrintConv value (after subracting 0x80 from raw value), 1) v2 divisor +# Returns: unconverted value +# Notes: raw values: 0=Auto, 1=User, 0xff=n/a, ... 0x7f=-1, 0x80=0, 0x81=1, ... +sub PrintPCInv($;$) +{ + my ($val, $div) = @_; + return $val * ($div || 1) if $val =~ /^[-+]?\d+(\.\d+)?$/; + return 0x7f if $val =~ /n\/a/i; + return -128 if $val =~ /auto/i; + return -127 if $val =~ /user/i; #28 + return 0; +} + +#------------------------------------------------------------------------------ +# Convert unknown LensID values +# Inputs: 0) value, 1) flag for inverse conversion, 2) PrintConv hash ref +sub LensIDConv($$$) +{ + my ($val, $inv, $conv) = @_; + return undef if $inv; + # multiple lenses with the same LensID are distinguished by decimal values + if ($$conv{"$val.1"}) { + my ($i, @vals, @user); + for ($i=1; ; ++$i) { + my $lens = $$conv{"$val.$i"} or last; + if ($Image::ExifTool::userLens{$lens}) { + push @user, $lens; + } else { + push @vals, $lens; + } + } + return join(' or ', @user) if @user; + return join(' or ', @vals); + } + # Sigma has been changing the LensID on some new lenses + # and with some Sigma lenses the LensFStops changes! (argh!) + my $pat = $val; + $pat =~ s/^\w+ \w+/.. ../; + my @ids = sort grep /^$pat$/, keys %$conv; + if (@ids) { + # first try different LensFStops (2nd value) + ($pat = $val) =~ s/ \w+/ ../; + my @good = grep /^$pat$/, @ids; + return $$conv{$good[0]} if @good; + # then try different LensType (1st value) + ($pat = $val) =~ s/^\w+/../; + @good = grep /^$pat$/, @ids; + return "Unknown ($val) $$conv{$good[0]} ?" if @good; + } + return undef; +} + +#------------------------------------------------------------------------------ +# Clean up formatting of string values +# Inputs: 0) string value +# Returns: formatted string value +# - removes trailing spaces and changes case to something more sensible +sub FormatString($) +{ + my $str = shift; + # limit string length (can be very long for some unknown tags) + if (length($str) > 60) { + $str = substr($str,0,55) . "[...]"; + } else { + $str =~ s/\s+$//; # remove trailing white space + # Don't change case of non-words (no vowels) + if ($str =~ /[AEIOUY]/) { + # change all letters but the first to lower case, + # but only in words containing a vowel + if ($str =~ s/\b([AEIOUY])([A-Z]+)/$1\L$2/g) { + $str =~ s/\bAf\b/AF/; # patch for "AF" + # patch for a number of models that write improper string + # terminator for ImageStabilization (VR-OFF, VR-ON) + $str =~ s/ +.$//s; + } + if ($str =~ s/\b([A-Z])([A-Z]*[AEIOUY][A-Z]*)/$1\L$2/g) { + $str =~ s/\bRaw\b/RAW/; # patch for "RAW" + } + } + } + return $str; +} + +#------------------------------------------------------------------------------ +# decoding tables from ref 4 +my @xlat = ( + [ 0xc1,0xbf,0x6d,0x0d,0x59,0xc5,0x13,0x9d,0x83,0x61,0x6b,0x4f,0xc7,0x7f,0x3d,0x3d, + 0x53,0x59,0xe3,0xc7,0xe9,0x2f,0x95,0xa7,0x95,0x1f,0xdf,0x7f,0x2b,0x29,0xc7,0x0d, + 0xdf,0x07,0xef,0x71,0x89,0x3d,0x13,0x3d,0x3b,0x13,0xfb,0x0d,0x89,0xc1,0x65,0x1f, + 0xb3,0x0d,0x6b,0x29,0xe3,0xfb,0xef,0xa3,0x6b,0x47,0x7f,0x95,0x35,0xa7,0x47,0x4f, + 0xc7,0xf1,0x59,0x95,0x35,0x11,0x29,0x61,0xf1,0x3d,0xb3,0x2b,0x0d,0x43,0x89,0xc1, + 0x9d,0x9d,0x89,0x65,0xf1,0xe9,0xdf,0xbf,0x3d,0x7f,0x53,0x97,0xe5,0xe9,0x95,0x17, + 0x1d,0x3d,0x8b,0xfb,0xc7,0xe3,0x67,0xa7,0x07,0xf1,0x71,0xa7,0x53,0xb5,0x29,0x89, + 0xe5,0x2b,0xa7,0x17,0x29,0xe9,0x4f,0xc5,0x65,0x6d,0x6b,0xef,0x0d,0x89,0x49,0x2f, + 0xb3,0x43,0x53,0x65,0x1d,0x49,0xa3,0x13,0x89,0x59,0xef,0x6b,0xef,0x65,0x1d,0x0b, + 0x59,0x13,0xe3,0x4f,0x9d,0xb3,0x29,0x43,0x2b,0x07,0x1d,0x95,0x59,0x59,0x47,0xfb, + 0xe5,0xe9,0x61,0x47,0x2f,0x35,0x7f,0x17,0x7f,0xef,0x7f,0x95,0x95,0x71,0xd3,0xa3, + 0x0b,0x71,0xa3,0xad,0x0b,0x3b,0xb5,0xfb,0xa3,0xbf,0x4f,0x83,0x1d,0xad,0xe9,0x2f, + 0x71,0x65,0xa3,0xe5,0x07,0x35,0x3d,0x0d,0xb5,0xe9,0xe5,0x47,0x3b,0x9d,0xef,0x35, + 0xa3,0xbf,0xb3,0xdf,0x53,0xd3,0x97,0x53,0x49,0x71,0x07,0x35,0x61,0x71,0x2f,0x43, + 0x2f,0x11,0xdf,0x17,0x97,0xfb,0x95,0x3b,0x7f,0x6b,0xd3,0x25,0xbf,0xad,0xc7,0xc5, + 0xc5,0xb5,0x8b,0xef,0x2f,0xd3,0x07,0x6b,0x25,0x49,0x95,0x25,0x49,0x6d,0x71,0xc7 ], + [ 0xa7,0xbc,0xc9,0xad,0x91,0xdf,0x85,0xe5,0xd4,0x78,0xd5,0x17,0x46,0x7c,0x29,0x4c, + 0x4d,0x03,0xe9,0x25,0x68,0x11,0x86,0xb3,0xbd,0xf7,0x6f,0x61,0x22,0xa2,0x26,0x34, + 0x2a,0xbe,0x1e,0x46,0x14,0x68,0x9d,0x44,0x18,0xc2,0x40,0xf4,0x7e,0x5f,0x1b,0xad, + 0x0b,0x94,0xb6,0x67,0xb4,0x0b,0xe1,0xea,0x95,0x9c,0x66,0xdc,0xe7,0x5d,0x6c,0x05, + 0xda,0xd5,0xdf,0x7a,0xef,0xf6,0xdb,0x1f,0x82,0x4c,0xc0,0x68,0x47,0xa1,0xbd,0xee, + 0x39,0x50,0x56,0x4a,0xdd,0xdf,0xa5,0xf8,0xc6,0xda,0xca,0x90,0xca,0x01,0x42,0x9d, + 0x8b,0x0c,0x73,0x43,0x75,0x05,0x94,0xde,0x24,0xb3,0x80,0x34,0xe5,0x2c,0xdc,0x9b, + 0x3f,0xca,0x33,0x45,0xd0,0xdb,0x5f,0xf5,0x52,0xc3,0x21,0xda,0xe2,0x22,0x72,0x6b, + 0x3e,0xd0,0x5b,0xa8,0x87,0x8c,0x06,0x5d,0x0f,0xdd,0x09,0x19,0x93,0xd0,0xb9,0xfc, + 0x8b,0x0f,0x84,0x60,0x33,0x1c,0x9b,0x45,0xf1,0xf0,0xa3,0x94,0x3a,0x12,0x77,0x33, + 0x4d,0x44,0x78,0x28,0x3c,0x9e,0xfd,0x65,0x57,0x16,0x94,0x6b,0xfb,0x59,0xd0,0xc8, + 0x22,0x36,0xdb,0xd2,0x63,0x98,0x43,0xa1,0x04,0x87,0x86,0xf7,0xa6,0x26,0xbb,0xd6, + 0x59,0x4d,0xbf,0x6a,0x2e,0xaa,0x2b,0xef,0xe6,0x78,0xb6,0x4e,0xe0,0x2f,0xdc,0x7c, + 0xbe,0x57,0x19,0x32,0x7e,0x2a,0xd0,0xb8,0xba,0x29,0x00,0x3c,0x52,0x7d,0xa8,0x49, + 0x3b,0x2d,0xeb,0x25,0x49,0xfa,0xa3,0xaa,0x39,0xa7,0xc5,0xa7,0x50,0x11,0x36,0xfb, + 0xc6,0x67,0x4a,0xf5,0xa5,0x12,0x65,0x7e,0xb0,0xdf,0xaf,0x4e,0xb3,0x61,0x7f,0x2f ] +); + +# Decrypt Nikon data block (ref 4) +# Inputs: 0) reference to data block, 1) serial number key, 2) shutter count key +# 4) optional start offset (default 0) +# 5) optional number of bytes to decode (default to the end of the data) +# Returns: data block with specified data decrypted +sub Decrypt($$$;$$) +{ + my ($dataPt, $serial, $count, $start, $len) = @_; + my ($i, $dat); + + $start or $start = 0; + my $maxLen = length($$dataPt) - $start; + $len = $maxLen if not defined $len or $len > $maxLen; + return $$dataPt if $len <= 0; + my $key = 0; + for ($i=0; $i<4; ++$i) { + $key ^= ($count >> ($i*8)) & 0xff; + } + my $ci = $xlat[0][$serial & 0xff]; + my $cj = $xlat[1][$key]; + my $ck = 0x60; + my @data = unpack("x${start}C$len", $$dataPt); + foreach $dat (@data) { + $cj = ($cj + $ci * $ck) & 0xff; + $ck = ($ck + 1) & 0xff; + $dat ^= $cj; + } + my $end = $start + $len; + my $pre = $start ? substr($$dataPt, 0, $start) : ''; + my $post = $end < length($$dataPt) ? substr($$dataPt, $end) : ''; + return $pre . pack('C*',@data) . $post; +} + +#------------------------------------------------------------------------------ +# Get serial number for use as a decryption key +# Inputs: 0) ExifTool object ref, 1) serial number string +# Returns: serial key integer or undef if no serial number provided +sub SerialKey($$) +{ + my ($et, $serial) = @_; + # use serial number as key if integral + return $serial if not defined $serial or $serial =~ /^\d+$/; + return 0x22 if $$et{Model} =~ /\bD50$/; # D50 (ref 8) + return 0x60; # D200 (ref 10), D40X (ref PH), etc +} + +#------------------------------------------------------------------------------ +# Read Nikon NCTG tags in MOV videos +# Inputs: 0) ExifTool object ref, 1) dirInfo ref, 2) tag table ref +# Returns: 1 on success +sub ProcessNikonMOV($$$) +{ + my ($et, $dirInfo, $tagTablePtr) = @_; + my $dataPt = $$dirInfo{DataPt}; + my $dataPos = $$dirInfo{DataPos}; + my %needTags = ( 0x110a431 => 0, 0x20000a7 => undef ); # needed for decryption + $et->VerboseDir($$dirInfo{DirName}, 0, $$dirInfo{DirLen}); + my $pass; + # do two passes so we can pre-scan for necessary decryption keys + for ($pass=0; $pass<2; ++$pass) { + my $pos = $$dirInfo{DirStart}; + my $end = $pos + $$dirInfo{DirLen}; + while ($pos + 8 < $end) { + my $tag = Get32u($dataPt, $pos); + my $fmt = Get16u($dataPt, $pos + 4); # (same format code as EXIF) + my $count = Get16u($dataPt, $pos + 6); + $pos += 8; + my $fmtStr = $Image::ExifTool::Exif::formatName[$fmt]; + unless ($fmtStr) { + $et->Warn(sprintf("Unknown format ($fmt) for $$dirInfo{DirName} tag 0x%x",$tag)) if $pass; + last; + } + my $size = $count * $Image::ExifTool::Exif::formatSize[$fmt]; + if ($pos + $size > $end) { + $et->Warn(sprintf("Truncated data for $$dirInfo{DirName} tag 0x%x",$tag)) if $pass; + last; + } + if ($pass) { + my $rational; + my $val = ReadValue($dataPt, $pos, $fmtStr, $count, $size, \$rational); + my $key = $et->HandleTag($tagTablePtr, $tag, $val, + DataPt => $dataPt, + DataPos => $dataPos, + Format => $fmtStr, + Start => $pos, + Size => $size, + ); + $$et{RATIONAL}{$key} = $rational if $rational and $key; + } elsif (exists $needTags{$tag}) { + $needTags{$tag} = ReadValue($dataPt, $pos, $fmtStr, $count, $size); + $$et{NikonSerialKey} = SerialKey($et, $needTags{0x110a431}); + $$et{NikonCountKey} = $needTags{0x20000a7}; + } + $pos += $size; # is this padded to an even offset???? + } + } + return 1; +} + +#------------------------------------------------------------------------------ +# Read/Write Nikon Encrypted data block +# Inputs: 0) ExifTool object ref, 1) dirInfo ref, 2) tag table ref +# Returns: 1 on success when reading, or new directory when writing (IsWriting set) +sub ProcessNikonEncrypted($$$) +{ + my ($et, $dirInfo, $tagTablePtr) = @_; + $et or return 1; # allow dummy access + my $serial = $$et{NikonSerialKey}; + my $count = $$et{NikonCountKey}; + unless (defined $serial and defined $count and $serial =~ /^\d+$/ and $count =~ /^\d+$/) { + if (defined $serial or defined $count) { + my $msg; + if (defined $serial and defined $count) { + $msg = $serial =~ /^\d+$/ ? 'invalid ShutterCount' : 'invalid SerialNumber'; + } else { + $msg = defined $serial ? 'no ShutterCount' : 'no SerialNumber'; + } + $et->Warn("Can't decrypt Nikon information ($msg key)"); + } + delete $$et{NikonSerialKey}; + delete $$et{NikonCountKey}; + return 0; + } + my $verbose = $$dirInfo{IsWriting} ? 0 : $et->Options('Verbose'); + my $tagInfo = $$dirInfo{TagInfo}; + my $dirStart = $$dirInfo{DirStart}; + my $data = substr(${$$dirInfo{DataPt}}, $dirStart, $$dirInfo{DirLen}); + + my ($start, $len, $more, $offset, $byteOrder, $recrypt, $newSerial, $newCount); + + # must re-encrypt when writing if serial number or shutter count changes + if ($$dirInfo{IsWriting}) { + if ($$et{NewNikonSerialKey}) { + $newSerial = $$et{NewNikonSerialKey}; + $recrypt = 1; + } + if ($$et{NewNikonCountKey}) { + $newCount = $$et{NewNikonCountKey}; + $recrypt = 1; + } + } + if ($tagInfo and $$tagInfo{SubDirectory}) { + $start = $$tagInfo{SubDirectory}{DecryptStart}; + # may decrypt only part of the information to save time + if ($verbose < 3 and $et->Options('Unknown') < 2 and not $recrypt) { + $len = $$tagInfo{SubDirectory}{DecryptLen}; + $more = $$tagInfo{SubDirectory}{DecryptMore}; + } + $offset = $$tagInfo{SubDirectory}{DirOffset}; + $byteOrder = $$tagInfo{SubDirectory}{ByteOrder}; + } + $start or $start = 0; + if (defined $offset) { + # offset, if specified, is relative to start of encrypted data + $offset += $start; + } else { + $offset = 0; + } + my $maxLen = length($data) - $start; + # decrypt all the data unless DecryptLen is given + unless ($len and $len < $maxLen) { + $len = $maxLen; + undef $more; # (can't decrypt more than this) + } + + $data = Decrypt(\$data, $serial, $count, $start, $len); + + # set appropriate byte ordering before evaluating DecryptMore + my $oldOrder = GetByteOrder(); + SetByteOrder($byteOrder) if $byteOrder; + + if ($more) { + #### eval DecryptMore ($data) + my $moreLen = eval $more; + $moreLen = $maxLen if $moreLen > $maxLen; + # re-decrypt with new length + if ($len < $moreLen) { + $len = $moreLen; + $data = substr(${$$dirInfo{DataPt}}, $dirStart, $$dirInfo{DirLen}); + $data = Decrypt(\$data, $serial, $count, $start, $len); + } + } + if ($verbose > 2) { + $et->VerboseDir("Decrypted $$tagInfo{Name}"); + $et->VerboseDump(\$data, + Prefix => $$et{INDENT} . ' ', + # (remove this because it is useful to have decrypted offsets start at 0) + #DataPos => $dirStart + $$dirInfo{DataPos} + ($$dirInfo{Base} || 0), + ); + } + # process the decrypted information + my %subdirInfo = ( + DataPt => \$data, + DirStart => $offset, + DirLen => length($data) - $offset, + DirName => $$dirInfo{DirName}, + DataPos => $$dirInfo{DataPos} + $dirStart, + Base => $$dirInfo{Base}, + ); + my $rtnVal; + if ($$dirInfo{IsWriting}) { + my $changed = $$et{CHANGED}; + $rtnVal = $et->WriteBinaryData(\%subdirInfo, $tagTablePtr); + # must re-encrypt if serial number or shutter count changes + if ($recrypt) { + $serial = $newSerial if defined $newSerial; + $count = $newCount if defined $newCount; + ++$$et{CHANGED}; + } + if ($changed == $$et{CHANGED}) { + undef $rtnVal; # nothing changed so use original data + } else { + # add back any un-encrypted data at start + $rtnVal = substr($data, 0, $offset) . $rtnVal if $offset; + # re-encrypt data (symmetrical algorithm) + $rtnVal = Decrypt(\$rtnVal, $serial, $count, $start, $len); + } + } else { + $rtnVal = $et->ProcessBinaryData(\%subdirInfo, $tagTablePtr); + } + SetByteOrder($oldOrder); + return $rtnVal; +} + +#------------------------------------------------------------------------------ +# Pre-scan EXIF directory to extract specific tags +# Inputs: 0) ExifTool object ref, 1) dirInfo ref, 2) required tagID hash ref +# Returns: 1 if directory was scanned successfully +sub PrescanExif($$$) +{ + my ($et, $dirInfo, $tagHash) = @_; + my $dataPt = $$dirInfo{DataPt}; + my $dataPos = $$dirInfo{DataPos} || 0; + my $dataLen = $$dirInfo{DataLen}; + my $dirStart = $$dirInfo{DirStart} || 0; + my $base = $$dirInfo{Base} || 0; + my $raf = $$dirInfo{RAF}; + my ($index, $numEntries, $data, $buff); + + # get number of entries in IFD + if ($dirStart >= 0 and $dirStart <= $dataLen-2) { + $numEntries = Get16u($dataPt, $dirStart); + # reset $numEntries to read from file if necessary + undef $numEntries if $dirStart + 2 + 12 * $numEntries > $dataLen; + } + # read IFD from file if necessary + unless ($numEntries) { + $raf or return 0; + $dataPos += $dirStart; # read data from the start of the directory + $raf->Seek($dataPos + $base, 0) and $raf->Read($data, 2) == 2 or return 0; + $numEntries = Get16u(\$data, 0); + my $len = 12 * $numEntries; + $raf->Read($buff, $len) == $len or return 0; + $data .= $buff; + # update variables for the newly loaded IFD (already updated dataPos) + $dataPt = \$data; + $dataLen = length $data; + $dirStart = 0; + } + # loop through necessary IFD entries + my ($lastTag) = sort { $b <=> $a } keys %$tagHash; # (reverse sort) + for ($index=0; $index<$numEntries; ++$index) { + my $entry = $dirStart + 2 + 12 * $index; + my $tagID = Get16u($dataPt, $entry); + last if $tagID > $lastTag; # (assuming tags are in order) + next unless exists $$tagHash{$tagID}; # only extract required tags + my $format = Get16u($dataPt, $entry+2); + next if $format < 1 or $format > 13; + my $count = Get32u($dataPt, $entry+4); + my $size = $count * $Image::ExifTool::Exif::formatSize[$format]; + my $formatStr = $Image::ExifTool::Exif::formatName[$format]; + my $valuePtr = $entry + 8; # pointer to value within $$dataPt + if ($size > 4) { + next if $size > 0x1000000; # set a reasonable limit on data size (16MB) + $valuePtr = Get32u($dataPt, $valuePtr); + # convert offset to pointer in $$dataPt + # (don't yet handle EntryBased or FixOffsets) + $valuePtr -= $dataPos; + if ($valuePtr < 0 or $valuePtr+$size > $dataLen) { + next unless $raf and $raf->Seek($base + $valuePtr + $dataPos,0) and + $raf->Read($buff,$size) == $size; + $$tagHash{$tagID} = ReadValue(\$buff,0,$formatStr,$count,$size); + next; + } + } + $$tagHash{$tagID} = ReadValue($dataPt,$valuePtr,$formatStr,$count,$size); + } + return 1; +} + +#------------------------------------------------------------------------------ +# Process Nikon Capture history data +# Inputs: 0) ExifTool object ref, 1) dirInfo ref, 2) tag table ref +# Returns: 1 on success +sub ProcessNikonCaptureEditVersions($$$) +{ + my ($et, $dirInfo, $tagTablePtr) = @_; + require Image::ExifTool::NikonCapture; + return Image::ExifTool::NikonCapture::ProcessNikonCaptureEditVersions($et, $dirInfo, $tagTablePtr); +} + +#------------------------------------------------------------------------------ +# Process Nikon Capture Offsets IFD (ref PH) +# Inputs: 0) ExifTool object ref, 1) dirInfo ref, 2) tag table ref +# Returns: 1 on success +# Notes: This isn't a normal IFD, but is close... +sub ProcessNikonCaptureOffsets($$$) +{ + my ($et, $dirInfo, $tagTablePtr) = @_; + my $dataPt = $$dirInfo{DataPt}; + my $dirStart = $$dirInfo{DirStart}; + my $dirLen = $$dirInfo{DirLen}; + my $success = 0; + return 0 unless $dirLen > 2; + my $count = Get16u($dataPt, $dirStart); + return 0 unless $count and $count * 12 + 2 <= $dirLen; + if ($et->Options('Verbose')) { + $et->VerboseDir('NikonCaptureOffsets', $count); + } + my $index; + for ($index=0; $index<$count; ++$index) { + my $pos = $dirStart + 12 * $index + 2; + my $tagID = Get32u($dataPt, $pos); + my $value = Get32u($dataPt, $pos + 4); + $et->HandleTag($tagTablePtr, $tagID, $value, + Index => $index, + DataPt => $dataPt, + Start => $pos, + Size => 12, + ) and $success = 1; + } + return $success; +} + +#------------------------------------------------------------------------------ +# Read/write Nikon MakerNotes directory +# Inputs: 0) ExifTool object ref, 1) dirInfo ref, 2) tag table ref +# Returns: 1 on success, otherwise returns 0 and sets a Warning when reading +# or new directory when writing (IsWriting set in dirInfo) +sub ProcessNikon($$$) +{ + my ($et, $dirInfo, $tagTablePtr) = @_; + $et or return 1; # allow dummy access + + # pre-scan IFD to get SerialNumber (0x001d) and ShutterCount (0x00a7) for use in decryption + my %needTags = ( 0x001d => 0, 0x00a7 => undef ); + PrescanExif($et, $dirInfo, \%needTags); + $$et{NikonSerialKey} = SerialKey($et, $needTags{0x001d}); + $$et{NikonCountKey} = $needTags{0x00a7}; + + # process Nikon makernotes + my $rtnVal; + if ($$dirInfo{IsWriting}) { + # get new decryptino keys if they are being changed + my $serial = $et->GetNewValue($Image::ExifTool::Nikon::Main{0x001d}); + my $count = $et->GetNewValue($Image::ExifTool::Nikon::Main{0x00a7}); + $$et{NewNikonSerialKey} = SerialKey($et, $serial); + $$et{NewNikonCountKey} = $count; + $rtnVal = Image::ExifTool::Exif::WriteExif($et, $dirInfo, $tagTablePtr); + delete $$et{NewNikonSerialKey}; + delete $$et{NewNikonCountKey}; + } else { + $rtnVal = Image::ExifTool::Exif::ProcessExif($et, $dirInfo, $tagTablePtr); + } + delete $$et{NikonSerialKey}; + delete $$et{NikonCountKey}; + return $rtnVal; +} + +1; # end + +__END__ + +=head1 NAME + +Image::ExifTool::Nikon - Nikon EXIF maker notes tags + +=head1 SYNOPSIS + +This module is loaded automatically by Image::ExifTool when required. + +=head1 DESCRIPTION + +This module contains definitions required by Image::ExifTool to interpret +Nikon maker notes in EXIF information. + +=head1 AUTHOR + +Copyright 2003-2019, Phil Harvey (phil at owl.phy.queensu.ca) + +This library is free software; you can redistribute it and/or modify it +under the same terms as Perl itself. + +=head1 REFERENCES + +=over 4 + +=item L<http://park2.wakwak.com/~tsuruzoh/Computer/Digicams/exif-e.html> + +=item L<http://www.cybercom.net/~dcoffin/dcraw/> + +=item L<http://members.aol.com/khancock/pilot/nbuddy/> + +=item L<http://www.rottmerhusen.com/objektives/lensid/thirdparty.html> + +=item L<http://homepage3.nifty.com/kamisaka/makernote/makernote_nikon.htm> + +=item L<http://www.wohlberg.net/public/software/photo/nstiffexif/> + +=item (...plus lots of testing with Best Buy store demos!) + +=back + +=head1 ACKNOWLEDGEMENTS + +Thanks to Joseph Heled, Thomas Walter, Brian Ristuccia, Danek Duvall, Tom +Christiansen, Robert Rottmerhusen, Werner Kober, Roger Larsson, Jens Duttke, +Gregor Dorlars, Neil Nappe, Alexandre Naaman, Brendt Wohlberg and Warren +Hatch for their help figuring out some Nikon tags, and to everyone who +helped contribute to the LensID list. + +=head1 SEE ALSO + +L<Image::ExifTool::TagNames/Nikon Tags>, +L<Image::ExifTool::TagNames/NikonCapture Tags>, +L<Image::ExifTool(3pm)|Image::ExifTool> + +=cut diff --git a/lib/Image/ExifTool/NikonCapture.pm b/lib/Image/ExifTool/NikonCapture.pm new file mode 100644 index 0000000..a9ac0b5 --- /dev/null +++ b/lib/Image/ExifTool/NikonCapture.pm @@ -0,0 +1,940 @@ +#------------------------------------------------------------------------------ +# File: NikonCapture.pm +# +# Description: Read/write Nikon Capture information +# +# Revisions: 11/08/2005 - P. Harvey Created +# 10/10/2008 - P. Harvey Updated for Capture NX 2 +# 16/04/2011 - P. Harvey Decode NikonCaptureEditVersions +# +# References: 1) http://www.cybercom.net/~dcoffin/dcraw/ +# IB) Iliah Borg private communication (LibRaw) +#------------------------------------------------------------------------------ + +package Image::ExifTool::NikonCapture; + +use strict; +use vars qw($VERSION); +use Image::ExifTool qw(:DataAccess :Utils); +use Image::ExifTool::Exif; + +$VERSION = '1.14'; + +sub ProcessNikonCapture($$$); + +# common print conversions +my %offOn = ( 0 => 'Off', 1 => 'On' ); +my %noYes = ( 0 => 'No', 1 => 'Yes' ); +my %unsharpColor = ( + 0 => 'RGB', + 1 => 'Red', + 2 => 'Green', + 3 => 'Blue', + 4 => 'Yellow', + 5 => 'Magenta', + 6 => 'Cyan', +); + +# Nikon Capture data (ref PH) +%Image::ExifTool::NikonCapture::Main = ( + PROCESS_PROC => \&ProcessNikonCapture, + WRITE_PROC => \&WriteNikonCapture, + CHECK_PROC => \&Image::ExifTool::Exif::CheckExif, + GROUPS => { 0 => 'MakerNotes', 2 => 'Image' }, + NOTES => q{ + This information is written by the Nikon Capture software in tag 0x0e01 of + the maker notes of NEF images. + }, + # 0x007ddc9d contains contrast information + 0x008ae85e => { + Name => 'LCHEditor', + Writable => 'int8u', + PrintConv => \%offOn, + }, + 0x0c89224b => { + Name => 'ColorAberrationControl', + Writable => 'int8u', + PrintConv => \%offOn, + }, + 0x116fea21 => { + Name => 'HighlightData', + SubDirectory => { + TagTable => 'Image::ExifTool::NikonCapture::HighlightData', + }, + }, + 0x2175eb78 => { + Name => 'D-LightingHQ', + Writable => 'int8u', + PrintConv => \%offOn, + }, + 0x2fc08431 => { + Name => 'StraightenAngle', + Writable => 'double', + }, + 0x374233e0 => { + Name => 'CropData', + SubDirectory => { + TagTable => 'Image::ExifTool::NikonCapture::CropData', + }, + }, + 0x39c456ac => { + Name => 'PictureCtrl', + SubDirectory => { + TagTable => 'Image::ExifTool::NikonCapture::PictureCtrl', + }, + }, + 0x3cfc73c6 => { + Name => 'RedEyeData', + SubDirectory => { + TagTable => 'Image::ExifTool::NikonCapture::RedEyeData', + }, + }, + 0x3d136244 => { + Name => 'EditVersionName', + Writable => 'string', # (null terminated) + }, + # 0x3e726567 added when I rotated by 90 degrees + 0x416391c6 => { + Name => 'QuickFix', + Writable => 'int8u', + PrintConv => \%offOn, + }, + 0x56a54260 => { + Name => 'Exposure', + SubDirectory => { + TagTable => 'Image::ExifTool::NikonCapture::Exposure', + }, + }, + 0x5f0e7d23 => { + Name => 'ColorBooster', + Writable => 'int8u', + PrintConv => \%offOn, + }, + 0x6a6e36b6 => { + Name => 'D-LightingHQSelected', + Writable => 'int8u', + PrintConv => \%noYes, + }, + 0x753dcbc0 => { + Name => 'NoiseReduction', + Writable => 'int8u', + PrintConv => \%offOn, + }, + 0x76a43200 => { + Name => 'UnsharpMask', + Writable => 'int8u', + PrintConv => \%offOn, + }, + 0x76a43201 => { + Name => 'Curves', + Writable => 'int8u', + PrintConv => \%offOn, + }, + 0x76a43202 => { + Name => 'ColorBalanceAdj', + Writable => 'int8u', + PrintConv => \%offOn, + }, + 0x76a43203 => { + Name => 'AdvancedRaw', + Writable => 'int8u', + PrintConv => \%offOn, + }, + 0x76a43204 => { + Name => 'WhiteBalanceAdj', + Writable => 'int8u', + PrintConv => \%offOn, + }, + 0x76a43205 => { + Name => 'VignetteControl', + Writable => 'int8u', + PrintConv => \%offOn, + }, + 0x76a43206 => { + Name => 'FlipHorizontal', + Writable => 'int8u', + PrintConv => \%noYes, + }, + 0x76a43207 => { # rotation angle in degrees + Name => 'Rotation', + Writable => 'int16u', + }, + 0x083a1a25 => { + Name => 'HistogramXML', + Writable => 'undef', + Binary => 1, + AdjustSize => 4, # patch Nikon bug + }, + 0x84589434 => { + Name => 'BrightnessData', + SubDirectory => { + TagTable => 'Image::ExifTool::NikonCapture::Brightness', + }, + }, + # 0x88f55e48 - related to QuickFix + 0x890ff591 => { + Name => 'D-LightingHQData', + SubDirectory => { + TagTable => 'Image::ExifTool::NikonCapture::DLightingHQ', + }, + }, + 0x926f13e0 => { + Name => 'NoiseReductionData', + SubDirectory => { + TagTable => 'Image::ExifTool::NikonCapture::NoiseReduction', + }, + }, + 0x9ef5f6e0 => { + Name => 'IPTCData', + SubDirectory => { + TagTable => 'Image::ExifTool::IPTC::Main', + }, + }, + # 0xa7264a72 - related to QuickFix + 0xab5eca5e => { + Name => 'PhotoEffects', + Writable => 'int8u', + PrintConv => \%offOn, + }, + 0xac6bd5c0 => { + Name => 'VignetteControlIntensity', + Writable => 'int16s', + }, + 0xb0384e1e => { + Name => 'PhotoEffectsData', + SubDirectory => { + TagTable => 'Image::ExifTool::NikonCapture::PhotoEffects', + }, + }, + 0xb999a36f => { + Name => 'ColorBoostData', + SubDirectory => { + TagTable => 'Image::ExifTool::NikonCapture::ColorBoost', + }, + }, + 0xbf3c6c20 => { + Name => 'WBAdjData', + SubDirectory => { + TagTable => 'Image::ExifTool::NikonCapture::WBAdjData', + }, + }, + 0xce5554aa => { + Name => 'D-LightingHS', + Writable => 'int8u', + PrintConv => \%offOn, + }, + 0xe2173c47 => { + Name => 'PictureControl', + Writable => 'int8u', + PrintConv => \%offOn, + }, + 0xe37b4337 => { + Name => 'D-LightingHSData', + SubDirectory => { + TagTable => 'Image::ExifTool::NikonCapture::DLightingHS', + }, + }, + 0xe42b5161 => { + Name => 'UnsharpData', + SubDirectory => { + TagTable => 'Image::ExifTool::NikonCapture::UnsharpData', + }, + }, + 0xe9651831 => { + Name => 'PhotoEffectHistoryXML', + Binary => 1, + Writable => 'undef', + }, + 0xfe28a44f => { + Name => 'AutoRedEye', + Writable => 'int8u', + PrintConv => \%offOn, # (have seen a value of 28 here for older software?) + }, + 0xfe443a45 => { + Name => 'ImageDustOff', + Writable => 'int8u', + PrintConv => \%offOn, + }, +); + +%Image::ExifTool::NikonCapture::UnsharpData = ( + PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData, + WRITE_PROC => \&Image::ExifTool::WriteBinaryData, + CHECK_PROC => \&Image::ExifTool::CheckBinaryData, + WRITABLE => 1, + FORMAT => 'int8u', + FIRST_ENTRY => 0, + GROUPS => { 0 => 'MakerNotes', 2 => 'Image' }, + 0 => 'UnsharpCount', + 19 => { Name => 'Unsharp1Color', Format => 'int16u', PrintConv => \%unsharpColor }, + 23 => { Name => 'Unsharp1Intensity', Format => 'int16u' }, + 25 => { Name => 'Unsharp1HaloWidth', Format => 'int16u' }, + 27 => 'Unsharp1Threshold', + 46 => { Name => 'Unsharp2Color', Format => 'int16u', PrintConv => \%unsharpColor }, + 50 => { Name => 'Unsharp2Intensity', Format => 'int16u' }, + 52 => { Name => 'Unsharp2HaloWidth', Format => 'int16u' }, + 54 => 'Unsharp2Threshold', + 73 => { Name => 'Unsharp3Color', Format => 'int16u', PrintConv => \%unsharpColor }, + 77 => { Name => 'Unsharp3Intensity', Format => 'int16u' }, + 79 => { Name => 'Unsharp3HaloWidth', Format => 'int16u' }, + 81 => 'Unsharp3Threshold', + 100 => { Name => 'Unsharp4Color', Format => 'int16u', PrintConv => \%unsharpColor }, + 104 => { Name => 'Unsharp4Intensity', Format => 'int16u' }, + 106 => { Name => 'Unsharp4HaloWidth', Format => 'int16u' }, + 108 => 'Unsharp4Threshold', + # there could be more, but I grow bored of this... :P +); + +%Image::ExifTool::NikonCapture::DLightingHS = ( + PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData, + WRITE_PROC => \&Image::ExifTool::WriteBinaryData, + CHECK_PROC => \&Image::ExifTool::CheckBinaryData, + WRITABLE => 1, + FORMAT => 'int32u', + FIRST_ENTRY => 0, + GROUPS => { 0 => 'MakerNotes', 2 => 'Image' }, + 0 => 'D-LightingHSAdjustment', + 1 => 'D-LightingHSColorBoost', +); + +%Image::ExifTool::NikonCapture::DLightingHQ = ( + PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData, + WRITE_PROC => \&Image::ExifTool::WriteBinaryData, + CHECK_PROC => \&Image::ExifTool::CheckBinaryData, + WRITABLE => 1, + FORMAT => 'int32u', + FIRST_ENTRY => 0, + GROUPS => { 0 => 'MakerNotes', 2 => 'Image' }, + 0 => 'D-LightingHQShadow', + 1 => 'D-LightingHQHighlight', + 2 => 'D-LightingHQColorBoost', +); + +%Image::ExifTool::NikonCapture::ColorBoost = ( + PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData, + WRITE_PROC => \&Image::ExifTool::WriteBinaryData, + CHECK_PROC => \&Image::ExifTool::CheckBinaryData, + WRITABLE => 1, + FORMAT => 'int8u', + FIRST_ENTRY => 0, + GROUPS => { 0 => 'MakerNotes', 2 => 'Image' }, + 0 => { + Name => 'ColorBoostType', + PrintConv => { + 0 => 'Nature', + 1 => 'People', + }, + }, + 1 => { + Name => 'ColorBoostLevel', + Format => 'int32u', + }, +); + +%Image::ExifTool::NikonCapture::WBAdjData = ( + PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData, + WRITE_PROC => \&Image::ExifTool::WriteBinaryData, + CHECK_PROC => \&Image::ExifTool::CheckBinaryData, + WRITABLE => 1, + FORMAT => 'int8u', + FIRST_ENTRY => 0, + GROUPS => { 0 => 'MakerNotes', 2 => 'Image' }, + 0x00 => { + Name => 'WBAdjRedBalance', + Format => 'double', + }, + 0x08 => { + Name => 'WBAdjBlueBalance', + Format => 'double', + }, + 0x10 => { + Name => 'WBAdjMode', + PrintConv => { + 1 => 'Use Gray Point', + 2 => 'Recorded Value', + 3 => 'Use Temperature', + 4 => 'Calculate Automatically', + 5 => 'Auto2', #IB + 6 => 'Underwater', #IB + 7 => 'Auto1', + }, + }, + 0x14 => { #IB + Name => 'WBAdjLighting', + Format => 'int16u', + PrintHex => 1, + PrintConv => { + 0x000 => 'None', + 0x100 => 'Incandescent', + 0x200 => 'Daylight (direct sunlight)', + 0x201 => 'Daylight (shade)', + 0x202 => 'Daylight (cloudy)', + 0x300 => 'Standard Fluorescent (warm white)', + 0x301 => 'Standard Fluorescent (3700K)', + 0x302 => 'Standard Fluorescent (cool white)', + 0x303 => 'Standard Fluorescent (5000K)', + 0x304 => 'Standard Fluorescent (daylight)', + 0x305 => 'Standard Fluorescent (high temperature mercury vapor)', + 0x400 => 'High Color Rendering Fluorescent (warm white)', + 0x401 => 'High Color Rendering Fluorescent (3700K)', + 0x402 => 'High Color Rendering Fluorescent (cool white)', + 0x403 => 'High Color Rendering Fluorescent (5000K)', + 0x404 => 'High Color Rendering Fluorescent (daylight)', + 0x500 => 'Flash', + 0x501 => 'Flash (FL-G1 filter)', + 0x502 => 'Flash (FL-G2 filter)', + 0x503 => 'Flash (TN-A1 filter)', + 0x504 => 'Flash (TN-A2 filter)', + 0x600 => 'Sodium Vapor Lamps', + # 0x1002 => seen for WBAdjMode modes of Underwater and Calculate Automatically + }, + }, + 0x18 => { + Name => 'WBAdjTemperature', + Format => 'int16u', + }, + 0x25 => { + Name => 'WBAdjTint', + Format => 'int32s', + }, +); + +%Image::ExifTool::NikonCapture::PhotoEffects = ( + PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData, + WRITE_PROC => \&Image::ExifTool::WriteBinaryData, + CHECK_PROC => \&Image::ExifTool::CheckBinaryData, + WRITABLE => 1, + FORMAT => 'int8u', + FIRST_ENTRY => 0, + GROUPS => { 0 => 'MakerNotes', 2 => 'Image' }, + 0 => { + Name => 'PhotoEffectsType', + PrintConv => { + 0 => 'None', + 1 => 'B&W', + 2 => 'Sepia', + 3 => 'Tinted', + }, + }, + 4 => { + Name => 'PhotoEffectsRed', + Format => 'int16s', + }, + 6 => { + Name => 'PhotoEffectsGreen', + Format => 'int16s', + }, + 8 => { + Name => 'PhotoEffectsBlue', + Format => 'int16s', + }, +); + +%Image::ExifTool::NikonCapture::Brightness = ( + PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData, + WRITE_PROC => \&Image::ExifTool::WriteBinaryData, + CHECK_PROC => \&Image::ExifTool::CheckBinaryData, + WRITABLE => 1, + FORMAT => 'int8u', + FIRST_ENTRY => 0, + GROUPS => { 0 => 'MakerNotes', 2 => 'Image' }, + 0 => { + Name => 'BrightnessAdj', + Format => 'double', + ValueConv => '$val * 50', + ValueConvInv => '$val / 50', + }, + 8 => { + Name => 'EnhanceDarkTones', + PrintConv => \%offOn, + }, +); + +%Image::ExifTool::NikonCapture::NoiseReduction = ( + PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData, + WRITE_PROC => \&Image::ExifTool::WriteBinaryData, + CHECK_PROC => \&Image::ExifTool::CheckBinaryData, + WRITABLE => 1, + FORMAT => 'int8u', + FIRST_ENTRY => 0, + GROUPS => { 0 => 'MakerNotes', 2 => 'Image' }, + 0x04 => { + Name => 'EdgeNoiseReduction', + PrintConv => \%offOn, + }, + 0x05 => { + Name => 'ColorMoireReductionMode', + PrintConv => { + 0 => 'Off', + 1 => 'Low', + 2 => 'Medium', + 3 => 'High', + }, + }, + 0x09 => { + Name => 'NoiseReductionIntensity', + Format => 'int32u', + }, + 0x0d => { + Name => 'NoiseReductionSharpness', + Format => 'int32u', + }, + 0x11 => { + Name => 'NoiseReductionMethod', + Format => 'int16u', + PrintConv => { + 0 => 'Faster', + 1 => 'Better Quality', + 2 => 'Better Quality 2013', + }, + }, + 0x15 => { + Name => 'ColorMoireReduction', + PrintConv => \%offOn, + }, + 0x17 => { + Name => 'NoiseReduction', + PrintConv => \%offOn, + }, + 0x18 => { + Name => 'ColorNoiseReductionIntensity', + Format => 'int32u', + }, + 0x1c => { + Name => 'ColorNoiseReductionSharpness', + Format => 'int32u', + }, +); + +%Image::ExifTool::NikonCapture::CropData = ( + PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData, + WRITE_PROC => \&Image::ExifTool::WriteBinaryData, + CHECK_PROC => \&Image::ExifTool::CheckBinaryData, + WRITABLE => 1, + FORMAT => 'int8u', + FIRST_ENTRY => 0, + GROUPS => { 0 => 'MakerNotes', 2 => 'Image' }, + 0x1e => { + Name => 'CropLeft', + Format => 'double', + ValueConv => '$val / 2', + ValueConvInv => '$val * 2', + }, + 0x26 => { + Name => 'CropTop', + Format => 'double', + ValueConv => '$val / 2', + ValueConvInv => '$val * 2', + }, + 0x2e => { + Name => 'CropRight', + Format => 'double', + ValueConv => '$val / 2', + ValueConvInv => '$val * 2', + }, + 0x36 => { + Name => 'CropBottom', + Format => 'double', + ValueConv => '$val / 2', + ValueConvInv => '$val * 2', + }, + 0x8e => { + Name => 'CropOutputWidthInches', + Format => 'double', + }, + 0x96 => { + Name => 'CropOutputHeightInches', + Format => 'double', + }, + 0x9e => { + Name => 'CropScaledResolution', + Format => 'double', + }, + 0xae => { + Name => 'CropSourceResolution', + Format => 'double', + ValueConv => '$val / 2', + ValueConvInv => '$val * 2', + }, + 0xb6 => { + Name => 'CropOutputResolution', + Format => 'double', + }, + 0xbe => { + Name => 'CropOutputScale', + Format => 'double', + }, + 0xc6 => { + Name => 'CropOutputWidth', + Format => 'double', + }, + 0xce => { + Name => 'CropOutputHeight', + Format => 'double', + }, + 0xd6 => { + Name => 'CropOutputPixels', + Format => 'double', + }, +); + +%Image::ExifTool::NikonCapture::PictureCtrl = ( + PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData, + WRITE_PROC => \&Image::ExifTool::WriteBinaryData, + CHECK_PROC => \&Image::ExifTool::CheckBinaryData, + WRITABLE => 1, + FORMAT => 'int8u', + FIRST_ENTRY => 0, + GROUPS => { 0 => 'MakerNotes', 2 => 'Image' }, + 0x00 => { + Name => 'PictureControlActive', + PrintConv => \%offOn, + }, + 0x13 => { + Name => 'PictureControlMode', + Format => 'string[16]', + }, + # 0x29 changes with Hue and Sharpening + 0x2a => { + Name => 'QuickAdjust', + ValueConv => '$val - 128', + ValueConvInv => '$val + 128', + }, + 0x2b => { + Name => 'SharpeningAdj', + ValueConv => '$val ? $val - 128 : "Auto"', + ValueConvInv => '$val=~/\d/ ? $val + 128 : 0', + }, + 0x2c => { + Name => 'ContrastAdj', + ValueConv => '$val ? $val - 128 : "Auto"', + ValueConvInv => '$val=~/\d/ ? $val + 128 : 0', + }, + 0x2d => { + Name => 'BrightnessAdj', + ValueConv => '$val ? $val - 128 : "Auto"', # no "Auto" mode (yet) for this setting + ValueConvInv => '$val=~/\d/ ? $val + 128 : 0', + }, + 0x2e => { + Name => 'SaturationAdj', + ValueConv => '$val ? $val - 128 : "Auto"', + ValueConvInv => '$val=~/\d/ ? $val + 128 : 0', + }, + 0x2f => { + Name => 'HueAdj', + ValueConv => '$val - 128', + ValueConvInv => '$val + 128', + }, + # 0x37 changed from 0 to 2 when Picture Control is enabled (and no active DLighting) +); + +%Image::ExifTool::NikonCapture::RedEyeData = ( + PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData, + WRITE_PROC => \&Image::ExifTool::WriteBinaryData, + CHECK_PROC => \&Image::ExifTool::CheckBinaryData, + WRITABLE => 1, + FORMAT => 'int8u', + FIRST_ENTRY => 0, + GROUPS => { 0 => 'MakerNotes', 2 => 'Image' }, + 0 => { + Name => 'RedEyeCorrection', + PrintConv => { + 0 => 'Off', + 1 => 'Automatic', + 2 => 'Click on Eyes', + }, + }, +); + +%Image::ExifTool::NikonCapture::Exposure = ( + PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData, + WRITE_PROC => \&Image::ExifTool::WriteBinaryData, + CHECK_PROC => \&Image::ExifTool::CheckBinaryData, + WRITABLE => 1, + FORMAT => 'int8u', + FIRST_ENTRY => 0, + GROUPS => { 0 => 'MakerNotes', 2 => 'Image' }, + 0x00 => { + Name => 'ExposureAdj', + Format => 'int16s', + ValueConv => '$val / 100', + ValueConvInv => '$val * 100', + }, + 0x12 => { + Name => 'ExposureAdj2', + Format => 'double', + PrintConv => 'sprintf("%.4f", $val)', + PrintConvInv => '$val', + }, + 0x24 => { + Name => 'ActiveD-Lighting', + PrintConv => \%offOn, + }, + 0x25 => { + Name => 'ActiveD-LightingMode', + PrintConv => { + 0 => 'Unchanged', + 1 => 'Off', + 2 => 'Low', + 3 => 'Normal', + 4 => 'High', + 6 => 'Extra High', + 7 => 'Extra High 1', + 8 => 'Extra High 2', + }, + }, +); + +%Image::ExifTool::NikonCapture::HighlightData = ( + PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData, + WRITE_PROC => \&Image::ExifTool::WriteBinaryData, + CHECK_PROC => \&Image::ExifTool::CheckBinaryData, + WRITABLE => 1, + FORMAT => 'int8s', + FIRST_ENTRY => 0, + GROUPS => { 0 => 'MakerNotes', 2 => 'Image' }, + 0 => 'ShadowProtection', + 1 => 'SaturationAdj', + 6 => 'HighlightProtection', +); + +#------------------------------------------------------------------------------ +# write Nikon Capture data (ref 1) +# Inputs: 0) ExifTool object reference, 1) reference to directory information +# 2) pointer to tag table +# Returns: 1 on success +sub WriteNikonCapture($$$) +{ + my ($et, $dirInfo, $tagTablePtr) = @_; + $et or return 1; # allow dummy access to autoload this package + + # no need to edit this information unless necessary + unless ($$et{EDIT_DIRS}{MakerNotes} or $$et{EDIT_DIRS}{IPTC}) { + return undef; + } + my $dataPt = $$dirInfo{DataPt}; + my $dirStart = $$dirInfo{DirStart}; + my $dirLen = $$dirInfo{DirLen}; + if ($dirLen < 22) { + $et->Warn('Short Nikon Capture Data',1); + return undef; + } + # make sure the capture data is properly contained + SetByteOrder('II'); + my $tagID = Get32u($dataPt, $dirStart); + # sometimes size includes 18 header bytes, and other times it doesn't (eg. ViewNX 2.1.1) + my $size = Get32u($dataPt, $dirStart + 18); + my $pad = $dirLen - $size - 18; + unless ($tagID == 0x7a86a940 and ($pad >= 0 or $pad == -18)) { + $et->Warn('Unrecognized Nikon Capture Data header'); + return undef; + } + # determine if there is any data after this block + if ($pad > 0) { + $pad = substr($$dataPt, $dirStart + 18 + $size, $pad); + $dirLen = $size + 18; + } else { + $pad = ''; + } + my $outBuff = ''; + my $pos; + my $newTags = $et->GetNewTagInfoHash($tagTablePtr); + my $dirEnd = $dirStart + $dirLen; + + # loop through all entries in the Nikon Capture data + for ($pos=$dirStart+22; $pos+22<$dirEnd; $pos+=22+$size) { + $tagID = Get32u($dataPt, $pos); + $size = Get32u($dataPt, $pos + 18) - 4; + last if $size < 0 or $pos + 22 + $size > $dirEnd; + my $tagInfo = $et->GetTagInfo($tagTablePtr, $tagID); + if ($tagInfo) { + my $newVal; + if ($$tagInfo{SubDirectory}) { + # rewrite the subdirectory + my %subdirInfo = ( + DataPt => $dataPt, + DirStart => $pos + 22, + DirLen => $size, + ); + my $subTable = GetTagTable($tagInfo->{SubDirectory}->{TagTable}); + # ignore minor errors in IPTC since there is typically trailing garbage + my $oldSetting = $et->Options('IgnoreMinorErrors'); + $$tagInfo{Name} =~ /IPTC/ and $et->Options(IgnoreMinorErrors => 1); + # rewrite the directory + $newVal = $et->WriteDirectory(\%subdirInfo, $subTable); + # restore our original options + $et->Options(IgnoreMinorErrors => $oldSetting); + } elsif ($$newTags{$tagID}) { + # get new value for this tag if we are writing it + my $format = $$tagInfo{Format} || $$tagInfo{Writable}; + my $oldVal = ReadValue($dataPt,$pos+22,$format,1,$size); + my $nvHash = $et->GetNewValueHash($tagInfo); + if ($et->IsOverwriting($nvHash, $oldVal)) { + my $val = $et->GetNewValue($tagInfo); + $newVal = WriteValue($val, $$tagInfo{Writable}) if defined $val; + if (defined $newVal and length $newVal) { + ++$$et{CHANGED}; + } else { + undef $newVal; + $et->Warn("Can't delete $$tagInfo{Name}"); + } + } + } + if (defined $newVal) { + next unless length $newVal; # don't write zero length information + # write the new value + $outBuff .= substr($$dataPt, $pos, 18); + $outBuff .= Set32u(length($newVal) + 4); + $outBuff .= $newVal; + next; + } + } + # rewrite the existing information + $outBuff .= substr($$dataPt, $pos, 22 + $size); + } + unless ($pos == $dirEnd) { + if ($pos == $dirEnd - 4) { + # it seems that sometimes (NX2) the main block size is wrong by 4 bytes + # (did they forget to include the size word?) + $outBuff .= substr($$dataPt, $pos, 4); + } else { + $et->Warn('Nikon Capture Data improperly terminated',1); + return undef; + } + } + # add the header and return the new directory + return substr($$dataPt, $dirStart, 18) . + Set32u(length($outBuff) + 4) . + $outBuff . $pad; +} + +#------------------------------------------------------------------------------ +# process Nikon Capture data (ref 1) +# Inputs: 0) ExifTool object ref, 1) dirInfo ref, 2) tag table ref +# Returns: 1 on success +sub ProcessNikonCaptureEditVersions($$$) +{ + my ($et, $dirInfo, $tagTablePtr) = @_; + my $dataPt = $$dirInfo{DataPt}; + my $dirStart = $$dirInfo{DirStart}; + my $dirLen = $$dirInfo{DirLen}; + my $dirEnd = $dirStart + $dirLen; + my $verbose = $et->Options('Verbose'); + SetByteOrder('II'); + return 0 unless $dirLen > 4; + my $num = Get32u($dataPt, $dirStart); + my $pos = $dirStart + 4; + $verbose and $et->VerboseDir('NikonCaptureEditVersions', $num); + while ($num) { + last if $pos + 4 > $dirEnd; + my $len = Get32u($dataPt, $pos); + last if $pos + $len + 4 > $dirEnd; + my %dirInfo = ( + DirName => 'NikonCapture', + Parent => 'NikonCaptureEditVersions', + DataPt => $dataPt, + DirStart => $pos + 4, + DirLen => $len, + ); + $$et{DOC_NUM} = ++$$et{DOC_COUNT}; + $et->ProcessDirectory(\%dirInfo, $tagTablePtr); + --$num; + $pos += $len + 4; + } + delete $$et{DOC_NUM}; + return 1; +} + +#------------------------------------------------------------------------------ +# process Nikon Capture data (ref 1) +# Inputs: 0) ExifTool object ref, 1) dirInfo ref, 2) tag table ref +# Returns: 1 on success +sub ProcessNikonCapture($$$) +{ + my ($et, $dirInfo, $tagTablePtr) = @_; + my $dataPt = $$dirInfo{DataPt}; + my $dirStart = $$dirInfo{DirStart}; + my $dirLen = $$dirInfo{DirLen}; + my $dirEnd = $dirStart + $dirLen; + my $verbose = $et->Options('Verbose'); + my $success = 0; + SetByteOrder('II'); + $verbose and $et->VerboseDir('NikonCapture', 0, $dirLen); + my $pos; + for ($pos=$dirStart+22; $pos+22<$dirEnd; ) { + my $tagID = Get32u($dataPt, $pos); + my $size = Get32u($dataPt, $pos + 18) - 4; + $pos += 22; + last if $size < 0 or $pos + $size > $dirEnd; + my $tagInfo = $et->GetTagInfo($tagTablePtr, $tagID); + if ($tagInfo or $verbose) { + my ($format, $value); + # (note that Writable will be 0 for Unknown tags) + $tagInfo and $format = ($$tagInfo{Format} || $$tagInfo{Writable}); + # generate a reasonable default format type for short values + if (not $format and ($size == 1 or $size == 2 or $size == 4)) { + $format = 'int' . ($size * 8) . 'u'; + } + if ($format) { + my $count = 1; + if ($format eq 'string' or $format eq 'undef') { + # patch Nikon bug in size of some values (HistogramXML) + $size += $$tagInfo{AdjustSize} if $tagInfo and $$tagInfo{AdjustSize}; + $count = $size; + } + $value = ReadValue($dataPt,$pos,$format,$count,$size); + } elsif ($size == 1) { + $value = substr($$dataPt, $pos, $size); + } + $et->HandleTag($tagTablePtr, $tagID, $value, + DataPt => $dataPt, + DataPos => $$dirInfo{DataPos}, + Base => $$dirInfo{Base}, + Start => $pos, + Size => $size, + ) and $success = 1; + } + $pos += $size; + } + return $success; +} + +1; # end + +__END__ + +=head1 NAME + +Image::ExifTool::NikonCapture - Read/write Nikon Capture information + +=head1 SYNOPSIS + +This module is loaded automatically by Image::ExifTool when required. + +=head1 DESCRIPTION + +This module contains routines to read and write Nikon Capture information in +the maker notes of NEF images. + +=head1 AUTHOR + +Copyright 2003-2019, Phil Harvey (phil at owl.phy.queensu.ca) + +This library is free software; you can redistribute it and/or modify it +under the same terms as Perl itself. + +=head1 REFERENCES + +=over 4 + +=item L<http://www.cybercom.net/~dcoffin/dcraw/> + +=back + +=head1 SEE ALSO + +L<Image::ExifTool::TagNames/NikonCapture Tags>, +L<Image::ExifTool::TagNames/Nikon Tags>, +L<Image::ExifTool(3pm)|Image::ExifTool> + +=cut diff --git a/lib/Image/ExifTool/NikonCustom.pm b/lib/Image/ExifTool/NikonCustom.pm new file mode 100644 index 0000000..6bf8168 --- /dev/null +++ b/lib/Image/ExifTool/NikonCustom.pm @@ -0,0 +1,9554 @@ +#------------------------------------------------------------------------------ +# File: NikonCustom.pm +# +# Description: Read and write Nikon Custom settings +# +# Revisions: 2009/11/25 - P. Harvey Created +# +# References: 1) Warren Hatch private communication (D3 with SB-800 and SB-900) +# 2) Anonymous contribution 2011/05/25 (D700, D7000) +# JD) Jens Duttke private communication +#------------------------------------------------------------------------------ + +package Image::ExifTool::NikonCustom; + +use strict; +use vars qw($VERSION); + +$VERSION = '1.17'; + +my %offOn = ( 0 => 'Off', 1 => 'On' ); +my %onOff = ( 0 => 'On', 1 => 'Off' ); +my %noYes = ( 0 => 'No', 1 => 'Yes' ); + +# custom settings for the D80 (encrypted) - ref JD +%Image::ExifTool::NikonCustom::SettingsD80 = ( + PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData, + WRITE_PROC => \&Image::ExifTool::WriteBinaryData, + CHECK_PROC => \&Image::ExifTool::CheckBinaryData, + WRITABLE => 1, + FIRST_ENTRY => 0, + GROUPS => { 0 => 'MakerNotes', 2 => 'Camera' }, + NOTES => 'Custom settings for the Nikon D80.', + 0.1 => { # CS1 + Name => 'Beep', + Mask => 0x80, + PrintConv => \%onOff, + }, + 0.2 => { # CS4 + Name => 'AFAssist', + Mask => 0x40, + PrintConv => \%onOff, + }, + 0.3 => { # CS5 + Name => 'NoMemoryCard', + Mask => 0x20, + PrintConv => { + 0 => 'Release Locked', + 1 => 'Enable Release', + }, + }, + 0.4 => { # CS6 + Name => 'ImageReview', + Mask => 0x10, + PrintConv => \%onOff, + }, + 0.5 => { # CS17 + Name => 'Illumination', + Mask => 0x08, + PrintConv => \%offOn, + }, + 0.6 => { # CS11 + Name => 'MainDialExposureComp', + Mask => 0x04, + PrintConv => \%offOn, + }, + 0.7 => { # CS10 + Name => 'EVStepSize', + Mask => 0x01, + PrintConv => { + 0 => '1/3 EV', + 1 => '1/2 EV', + }, + }, + 1.1 => { # CS7 + Name => 'AutoISO', + Mask => 0x40, + PrintConv => \%offOn, + }, + 1.2 => { # CS7-a + Name => 'AutoISOMax', + Mask => 0x30, + PrintConv => { + 0 => 200, + 1 => 400, + 2 => 800, + 3 => 1600, + }, + }, + 1.3 => { # CS7-b + Name => 'AutoISOMinShutterSpeed', + Mask => 0x0f, + PrintConvColumns => 2, + PrintConv => { + 0 => '1/125 s', + 1 => '1/100 s', + 2 => '1/80 s', + 3 => '1/60 s', + 4 => '1/40 s', + 5 => '1/30 s', + 6 => '1/15 s', + 7 => '1/8 s', + 8 => '1/4 s', + 9 => '1/2 s', + 10 => '1 s', + }, + }, + 2.1 => { # CS13 + Name => 'AutoBracketSet', + Mask => 0xc0, + PrintConv => { + 0 => 'AE & Flash', + 1 => 'AE Only', + 2 => 'Flash Only', + 3 => 'WB Bracketing', + }, + }, + 2.2 => { # CS14 + Name => 'AutoBracketOrder', + Mask => 0x20, + PrintConv => { + 0 => '0,-,+', + 1 => '-,0,+', + }, + }, + 3.1 => { # CS27 + Name => 'MonitorOffTime', + Mask => 0xe0, + PrintConv => { + 0 => '5 s', + 1 => '10 s', + 2 => '20 s', + 3 => '1 min', + 4 => '5 min', + 5 => '10 min', + }, + }, + 3.2 => { # CS28 + Name => 'MeteringTime', + Mask => 0x1c, + PrintConv => { + 0 => '4 s', + 1 => '6 s', + 2 => '8 s', + 3 => '16 s', + 4 => '30 s', + 5 => '30 min', + }, + }, + 3.3 => { # CS29 + Name => 'SelfTimerTime', + Mask => 0x03, + PrintConv => { + 0 => '2 s', + 1 => '5 s', + 2 => '10 s', + 3 => '20 s', + }, + }, + 4.1 => { # CS18 + Name => 'AELockButton', + Mask => 0x1e, + PrintConv => { + 0 => 'AE/AF Lock', + 1 => 'AE Lock Only', + 2 => 'AF Lock Only', + 3 => 'AE Lock (hold)', + 4 => 'AF-ON', + 5 => 'FV Lock', + 6 => 'Focus Area Selection', + 7 => 'AE-L/AF-L/AF Area', + 8 => 'AE-L/AF Area', + 9 => 'AF-L/AF Area', + 10 => 'AF-ON/AF Area', + }, + }, + 4.2 => { # CS19 + Name => 'AELock', + Mask => 0x01, + PrintConv => \%offOn, + }, + 4.3 => { # CS30 + Name => 'RemoteOnDuration', + Mask => 0xc0, + PrintConv => { + 0 => '1 min', + 1 => '5 min', + 2 => '10 min', + 3 => '15 min', + }, + }, + 5.1 => { # CS15 + Name => 'CommandDials', + Mask => 0x80, + PrintConv => { + 0 => 'Standard (Main Shutter, Sub Aperture)', + 1 => 'Reversed (Main Aperture, Sub Shutter)', + }, + }, + 5.2 => { # CS16 + Name => 'FunctionButton', + Mask => 0x78, + PrintConv => { + 0 => 'ISO Display', + 1 => 'Framing Grid', + 2 => 'AF-area Mode', + 3 => 'Center AF Area', + 4 => 'FV Lock', + 5 => 'Flash Off', + 6 => 'Matrix Metering', + 7 => 'Center-weighted', + 8 => 'Spot Metering', + }, + }, + 6.1 => { # CS8 + Name => 'GridDisplay', + Mask => 0x80, + PrintConv => \%offOn, + }, + 6.2 => { # CS9 + Name => 'ViewfinderWarning', + Mask => 0x40, + PrintConv => \%onOff, + }, + 6.3 => { # CS12 + Name => 'CenterWeightedAreaSize', + Mask => 0x0c, + PrintConv => { + 0 => '6 mm', + 1 => '8 mm', + 2 => '10 mm', + }, + }, + 6.4 => { # CS31 + Name => 'ExposureDelayMode', + Mask => 0x20, + PrintConv => \%offOn, + }, + 6.5 => { # CS32 + Name => 'MB-D80Batteries', + Mask => 0x03, + PrintConv => { + 0 => 'LR6 (AA Alkaline)', + 1 => 'HR6 (AA Ni-MH)', + 2 => 'FR6 (AA Lithium)', + 3 => 'ZR6 (AA Ni-Mg)', + }, + }, + 7.1 => { # CS23 + Name => 'FlashWarning', + Mask => 0x80, + PrintConv => \%onOff, + }, + 7.2 => { # CS24 + Name => 'FlashShutterSpeed', + Mask => 0x78, + ValueConv => '2 ** ($val - 6)', + ValueConvInv => '$val>0 ? int(log($val)/log(2)+6+0.5) : 0', + PrintConv => 'Image::ExifTool::Exif::PrintExposureTime($val)', + PrintConvInv => 'Image::ExifTool::Exif::ConvertFraction($val)', + }, + 7.3 => { # CS25 + Name => 'AutoFP', + Mask => 0x04, + PrintConv => \%offOn, + }, + 7.4 => { # CS26 + Name => 'ModelingFlash', + Mask => 0x02, + PrintConv => \%offOn, + }, + 8.1 => { # CS22 + Name => 'InternalFlash', + Mask => 0xc0, + PrintConv => { + 0 => 'TTL', + 1 => 'Manual', + 2 => 'Repeating Flash', + 3 => 'Commander Mode', + }, + }, + 8.2 => { # CS22-a + Name => 'ManualFlashOutput', + Mask => 0x07, + ValueConv => '2 ** (-$val)', + ValueConvInv => '$val > 0 ? -log($val)/log(2) : 0', + PrintConv => q{ + return 'Full' if $val > 0.99; + Image::ExifTool::Exif::PrintExposureTime($val); + }, + PrintConvInv => '$val=~/F/i ? 1 : Image::ExifTool::Exif::ConvertFraction($val)', + }, + 9.1 => { # CS22-b + Name => 'RepeatingFlashOutput', + Mask => 0x70, + ValueConv => '2 ** (-$val-2)', + ValueConvInv => '$val > 0 ? int(-log($val)/log(2)-2+0.5) : 0', + PrintConv => 'Image::ExifTool::Exif::PrintExposureTime($val)', + PrintConvInv => 'Image::ExifTool::Exif::ConvertFraction($val)', + }, + 9.2 => { # CS22-c + Name => 'RepeatingFlashCount', + Mask => 0x0f, + ValueConv => '$val < 10 ? $val + 1 : 5 * ($val - 7)', + ValueConvInv => '$val <= 10 ? $val - 1 : $val / 5 + 7', + }, + 10.1 => { # CS22-d + Name => 'RepeatingFlashRate', + Mask => 0xf0, + ValueConv => '$val < 10 ? $val + 1 : 10 * ($val - 8)', + ValueConvInv => 'int(($val <= 10 ? $val - 1 : $val / 10 + 8) + 0.5)', + PrintConv => '"$val Hz"', + PrintConvInv => '$val=~/(\d+)/; $1 || 0', + }, + 10.2 => { # CS22-n + Name => 'CommanderChannel', + Mask => 0x03, + ValueConv => '$val + 1', + ValueConvInv => '$val - 1', + }, + 11.1 => { # CS22-e + Name => 'CommanderInternalFlash', + Mask => 0xc0, + PrintConv => { + 0 => 'TTL', + 1 => 'Manual', + 2 => 'Off', + }, + }, + 11.2 => { # CS22-h + Name => 'CommanderGroupAMode', + Mask => 0x30, + PrintConv => { + 0 => 'TTL', + 1 => 'Auto Aperture', + 2 => 'Manual', + 3 => 'Off', + }, + }, + 11.3 => { # CS22-k + Name => 'CommanderGroupBMode', + Mask => 0x0c, + PrintConv => { + 0 => 'TTL', + 1 => 'Auto Aperture', + 2 => 'Manual', + 3 => 'Off', + }, + }, + 12.1 => { # CS22-f + Name => 'CommanderInternalTTLComp', + Mask => 0x1f, + ValueConv => '($val - 9) / 3', + ValueConvInv => '$val * 3 + 9', + PrintConv => '$val ? sprintf("%+.1f",$val) : 0', + PrintConvInv => '$val', + }, + 12.2 => { # CS22-g + Name => 'CommanderInternalManualOutput', + Mask => 0xe0, + ValueConv => '2 ** (-$val)', + ValueConvInv => '$val > 0 ? int(-log($val)/log(2)+0.5) : 0', + PrintConv => q{ + return 'Full' if $val > 0.99; + Image::ExifTool::Exif::PrintExposureTime($val); + }, + PrintConvInv => '$val=~/F/i ? 1 : Image::ExifTool::Exif::ConvertFraction($val)', + }, + 13.1 => { # CS22-i + Name => 'CommanderGroupA_TTL-AAComp', + Mask => 0x1f, + ValueConv => '($val - 9) / 3', + ValueConvInv => '$val * 3 + 9', + PrintConv => '$val ? sprintf("%+.1f",$val) : 0', + PrintConvInv => '$val', + }, + 13.2 => { # CS22-j + Name => 'CommanderGroupAManualOutput', + Mask => 0xe0, + ValueConv => '2 ** (-$val)', + ValueConvInv => '$val > 0 ? int(-log($val)/log(2)+0.5) : 0', + PrintConv => q{ + return 'Full' if $val > 0.99; + Image::ExifTool::Exif::PrintExposureTime($val); + }, + PrintConvInv => '$val=~/F/i ? 1 : Image::ExifTool::Exif::ConvertFraction($val)', + }, + 14.1 => { # CS22-l + Name => 'CommanderGroupB_TTL-AAComp', + Mask => 0x1f, + ValueConv => '($val - 9) / 3', + ValueConvInv => '$val * 3 + 9', + PrintConv => '$val ? sprintf("%+.1f",$val) : 0', + PrintConvInv => '$val', + }, + 14.2 => { # CS22-m + Name => 'CommanderGroupBManualOutput', + Mask => 0xe0, + ValueConv => '2 ** (-$val)', + ValueConvInv => '$val > 0 ? int(-log($val)/log(2)+0.5) : 0', + PrintConv => q{ + return 'Full' if $val > 0.99; + Image::ExifTool::Exif::PrintExposureTime($val); + }, + PrintConvInv => '$val=~/F/i ? 1 : Image::ExifTool::Exif::ConvertFraction($val)', + }, + 15.1 => { # CS3 + Name => 'CenterAFArea', + Mask => 0x80, + PrintConv => { + 0 => 'Normal Zone', + 1 => 'Wide Zone', + }, + }, + 15.2 => { # CS20 + Name => 'FocusAreaSelection', + Mask => 0x04, + PrintConv => { + 0 => 'No Wrap', + 1 => 'Wrap', + }, + }, + 15.3 => { # CS21 + Name => 'AFAreaIllumination', + Mask => 0x03, + PrintConv => { + 0 => 'Auto', + 1 => 'Off', + 2 => 'On', + }, + }, + 16.1 => { # CS2 + Name => 'AFAreaModeSetting', + Mask => 0xc0, + PrintConv => { + 0 => 'Single Area', + 1 => 'Dynamic Area', + 2 => 'Auto-area', + }, + }, +); + +# custom settings for the D40 (encrypted) - ref JD +%Image::ExifTool::NikonCustom::SettingsD40 = ( + PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData, + WRITE_PROC => \&Image::ExifTool::WriteBinaryData, + CHECK_PROC => \&Image::ExifTool::CheckBinaryData, + WRITABLE => 1, + FIRST_ENTRY => 0, + GROUPS => { 0 => 'MakerNotes', 2 => 'Camera' }, + NOTES => 'Custom settings for the Nikon D40.', + 0.1 => { # CS1 + Name => 'Beep', + Mask => 0x80, + PrintConv => \%onOff, + }, + 0.2 => { # CS9 + Name => 'AFAssist', + Mask => 0x40, + PrintConv => \%onOff, + }, + 0.3 => { # CS6 + Name => 'NoMemoryCard', + Mask => 0x20, + PrintConv => { + 0 => 'Release Locked', + 1 => 'Enable Release', + }, + }, + 0.4 => { # CS7 + Name => 'ImageReview', + Mask => 0x10, + PrintConv => \%onOff, + }, + 1.1 => { # CS10-a + Name => 'AutoISO', + Mask => 0x80, + PrintConv => \%offOn, + }, + 1.2 => { # CS10-b + Name => 'AutoISOMax', + Mask => 0x30, + PrintConv => { + 1 => 400, + 2 => 800, + 3 => 1600, + }, + }, + 1.3 => { # CS10-c + Name => 'AutoISOMinShutterSpeed', + Mask => 0x07, + PrintConvColumns => 2, + PrintConv => { + 0 => '1/125 s', + 1 => '1/60 s', + 2 => '1/30 s', + 3 => '1/15 s', + 4 => '1/8 s', + 5 => '1/4 s', + 6 => '1/2 s', + 7 => '1 s', + }, + }, + 2.1 => { # CS15-b + Name => 'ImageReviewTime', + Mask => 0x07, + PrintConv => { + 0 => '4 s', + 1 => '8 s', + 2 => '20 s', + 3 => '1 min', + 4 => '10 min', + }, + }, + 3.1 => { # CS15-a + Name => 'MonitorOffTime', + Mask => 0xe0, + PrintConv => { + 0 => '4 s', + 1 => '8 s', + 2 => '20 s', + 3 => '1 min', + 4 => '10 min', + }, + }, + 3.2 => { # CS15-c + Name => 'MeteringTime', + Mask => 0x1c, + PrintConv => { + 0 => '4 s', + 1 => '8 s', + 2 => '20 s', + 3 => '1 min', + 4 => '30 min', + }, + }, + 3.3 => { # CS16 + Name => 'SelfTimerTime', + Mask => 0x03, + PrintConv => { + 0 => '2 s', + 1 => '5 s', + 2 => '10 s', + 3 => '20 s', + }, + }, + 3.4 => { # CS17 + Name => 'RemoteOnDuration', + Mask => 0xc0, + PrintConv => { + 0 => '1 min', + 1 => '5 min', + 2 => '10 min', + 3 => '15 min', + }, + }, + 4.1 => { # CS12 + Name => 'AELockButton', + Mask => 0x0e, + PrintConv => { + 0 => 'AE/AF Lock', + 1 => 'AE Lock Only', + 2 => 'AF Lock Only', + 3 => 'AE Lock (hold)', + 4 => 'AF-ON', + }, + }, + 4.2 => { # CS13 + Name => 'AELock', + Mask => 0x01, + PrintConv => \%offOn, + }, + 5.1 => { # CS4 + Name => 'ShootingModeSetting', + Mask => 0x70, + PrintConv => { + 0 => 'Single Frame', + 1 => 'Continuous', + 2 => 'Self-timer', + 3 => 'Delayed Remote', + 4 => 'Quick-response Remote', + }, + }, + 5.2 => { # CS11 + Name => 'TimerFunctionButton', + Mask => 0x07, + PrintConv => { + 0 => 'Shooting Mode', + 1 => 'Image Quality/Size', + 2 => 'ISO', + 3 => 'White Balance', + 4 => 'Self-timer', + }, + }, + 6.1 => { # CS5 + Name => 'Metering', + Mask => 0x03, + PrintConv => { + 0 => 'Matrix', + 1 => 'Center-weighted', + 2 => 'Spot', + }, + }, + 8.1 => { # CS14-a + Name => 'InternalFlash', + Mask => 0x10, + PrintConv => { + 0 => 'TTL', + 1 => 'Manual', + }, + }, + 8.2 => { # CS14-b + Name => 'ManualFlashOutput', + Mask => 0x07, + ValueConv => '2 ** (-$val)', + ValueConvInv => '$val > 0 ? -log($val)/log(2) : 0', + PrintConv => q{ + return 'Full' if $val > 0.99; + Image::ExifTool::Exif::PrintExposureTime($val); + }, + PrintConvInv => '$val=~/F/i ? 1 : Image::ExifTool::Exif::ConvertFraction($val)', + }, + 9 => { # CS8 + Name => 'FlashLevel', + Format => 'int8s', + ValueConv => '$val / 6', + ValueConvInv => '$val * 6', + PrintConv => 'sprintf("%+.1f",$val)', + PrintConvInv => '$val', + }, + 10.1 => { # CS2 + Name => 'FocusModeSetting', + # (may differ from FocusMode if lens switch is set to Manual) + Mask => 0xc0, + PrintConv => { + 0 => 'Manual', + 1 => 'AF-S', + 2 => 'AF-C', + 3 => 'AF-A', + }, + }, + 11.1 => { # CS3 + Name => 'AFAreaModeSetting', + # (may differ from AFAreaMode for Manual focus) + Mask => 0x30, + PrintConv => { + 0 => 'Single Area', + 1 => 'Dynamic Area', + 2 => 'Closest Subject', + }, + } +); + +# D90 custom settings (ref PH) +%Image::ExifTool::NikonCustom::SettingsD90 = ( + PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData, + WRITE_PROC => \&Image::ExifTool::WriteBinaryData, + CHECK_PROC => \&Image::ExifTool::CheckBinaryData, + WRITABLE => 1, + FIRST_ENTRY => 0, + GROUPS => { 0 => 'MakerNotes', 2 => 'Camera' }, + NOTES => 'Custom settings for the D90.', + # Missing: + # CSe2 RepeatingFlashRate (needs verification) + # CommanderInternalFlash, CommanderGroupAMode, CommanderGroupBMode, + # CommanderChannel, CommanderInternalManualOutput, + # CommanderGroupAManualOutput, CommanderGroupBManualOutput + # CommanderGroupA_TTL-AAComp, CommanderGroupB_TTL-AAComp, + # CSe4 AutoBracketSet (some values need verification) + # CSf2 OKButton ("Not Used" value needs verification) + # CSf5-b CommandDialsChangeMainSub + # CSf5-c CommandDialsMenuAndPlayback + 0.1 => { # CSf1 + Name => 'LightSwitch', + Mask => 0x08, + PrintConv => { + 0 => 'LCD Backlight', + 1 => 'LCD Backlight and Shooting Information', + }, + }, + 2.1 => { # CSa1 + Name => 'AFAreaModeSetting', + Mask => 0x60, + PrintConv => { + 0 => 'Single Area', + 1 => 'Dynamic Area', + 2 => 'Auto-area', + 3 => '3D-tracking (11 points)', + }, + }, + 2.2 => { # CSa2 + Name => 'CenterFocusPoint', + Mask => 0x10, + PrintConv => { + 0 => 'Normal Zone', + 1 => 'Wide Zone', + }, + }, + 2.3 => { # CSa3 + Name => 'AFAssist', + Mask => 0x01, + PrintConv => \%onOff, + }, + 2.4 => { # CSa4 + Name => 'AFPointIllumination', + Mask => 0x06, + PrintConv => { + 0 => 'Auto', + 1 => 'On', + 2 => 'Off', + }, + }, + 2.5 => { # CSa5 + Name => 'FocusPointWrap', + Mask => 0x08, + PrintConv => { + 0 => 'No Wrap', + 1 => 'Wrap', + }, + }, + 3.1 => { # CSa6 + Name => 'AELockForMB-D80', + Mask => 0x1c, + PrintConv => { + 0 => 'AE Lock Only', + 1 => 'AF Lock Only', + 2 => 'AE Lock (hold)', + 3 => 'AF-On', + 4 => 'FV Lock', + 5 => 'Focus Point Selection', + 7 => 'AE/AF Lock', + }, + }, + 3.2 => { # CSd12 + Name => 'MB-D80BatteryType', + Mask => 0x03, + PrintConv => { + 0 => 'LR6 (AA alkaline)', + 1 => 'HR6 (AA Ni-MH)', + 2 => 'FR6 (AA lithium)', + 3 => 'ZR6 (AA Ni-Mn)', + }, + }, + 4.1 => { # CSd1 + Name => 'Beep', + Mask => 0x40, + PrintConv => \%offOn, + }, + 4.2 => { # CSd2 + Name => 'GridDisplay', + Mask => 0x02, + PrintConv => \%offOn, + }, + 4.3 => { # CSd3 + Name => 'ISODisplay', + Mask => 0x0c, + PrintConv => { + 0 => 'Show ISO/Easy ISO', + 1 => 'Show ISO Sensitivity', + 3 => 'Show Frame Count', + }, + }, + 4.4 => { # CSd4 + Name => 'ViewfinderWarning', + Mask => 0x01, + PrintConv => \%onOff, + }, + 4.5 => { # CSf6 + Name => 'NoMemoryCard', + Mask => 0x20, + PrintConv => { + 0 => 'Release Locked', + 1 => 'Enable Release', + }, + }, + 5.1 => { # CSd5 + Name => 'ScreenTips', + Mask => 0x04, + PrintConv => \%offOn, + }, + 5.2 => { # CSd7 + Name => 'FileNumberSequence', + Mask => 0x08, + PrintConv => \%onOff, + }, + 5.3 => { # CSd8 + Name => 'ShootingInfoDisplay', + Mask => 0xc0, + PrintConv => { + 0 => 'Auto', + 2 => 'Manual (dark on light)', + 3 => 'Manual (light on dark)', + }, + }, + 5.4 => { # CSd9 + Name => 'LCDIllumination', + Mask => 0x20, + PrintConv => \%offOn, + }, + 6.1 => { # CSb2 + Name => 'EasyExposureComp', + Mask => 0x01, + PrintConv => \%offOn, + }, + 6.2 => { # CSf7 + Name => 'ReverseIndicators', + Mask => 0x80, + PrintConv => { + 0 => '+ 0 -', + 1 => '- 0 +', + }, + }, + 7.1 => { # CSb1 + Name => 'ExposureControlStepSize', + Mask => 0x40, + PrintConv => { + 0 => '1/3 EV', + 1 => '1/2 EV', + }, + }, + 8.1 => { # CSb3 + Name => 'CenterWeightedAreaSize', + Mask => 0x60, + PrintConv => { + 0 => '6 mm', + 1 => '8 mm', + 2 => '10 mm', + }, + }, + 8.2 => { # CSb4-a + Name => 'FineTuneOptMatrixMetering', + Mask => 0x0f, + ValueConv => '($val > 0x7 ? $val - 0x10 : $val) / 6', + ValueConvInv => 'int($val*6+($val>0?0.5:-0.5))', + PrintConv => '$val ? sprintf("%+.2f", $val) : 0', + PrintConvInv => 'Image::ExifTool::Exif::ConvertFraction($val)', + }, + 9.1 => { # CSb4-b + Name => 'FineTuneOptCenterWeighted', + Mask => 0xf0, + ValueConv => '($val > 0x7 ? $val - 0x10 : $val) / 6', + ValueConvInv => 'int($val*6+($val>0?0.5:-0.5))', + PrintConv => '$val ? sprintf("%+.2f", $val) : 0', + PrintConvInv => 'Image::ExifTool::Exif::ConvertFraction($val)', + }, + 9.2 => { # CSb4-c + Name => 'FineTuneOptSpotMetering', + Mask => 0x0f, + ValueConv => '($val > 0x7 ? $val - 0x10 : $val) / 6', + ValueConvInv => 'int($val*6+($val>0?0.5:-0.5))', + PrintConv => '$val ? sprintf("%+.2f", $val) : 0', + PrintConvInv => 'Image::ExifTool::Exif::ConvertFraction($val)', + }, + 11.1 => { # CSd6 + Name => 'CLModeShootingSpeed', + Mask => 0x07, + PrintConv => '"$val fps"', + PrintConvInv => '$val=~s/\s*fps//i; $val', + }, + 11.2 => { # CSd10 + Name => 'ExposureDelayMode', + Mask => 0x40, + PrintConv => \%offOn, + }, + 13.1 => { # CSe4 + Name => 'AutoBracketSet', + Mask => 0xe0, #(NC) + PrintConv => { + 0 => 'AE & Flash', # default + 1 => 'AE Only', + 2 => 'Flash Only', #(NC) + 3 => 'WB Bracketing', #(NC) + 4 => 'Active D-Lighting', #(NC) + }, + }, + 13.2 => { # CSe6 + Name => 'AutoBracketOrder', + Mask => 0x10, + PrintConv => { + 0 => '0,-,+', + 1 => '-,0,+', + }, + }, + 14.1 => { # CSf3 + Name => 'FuncButton', + Mask => 0x78, + PrintConv => { + 1 => 'Framing Grid', + 2 => 'AF-area Mode', + 3 => 'Center Focus Point', + 4 => 'FV Lock', # default + 5 => 'Flash Off', + 6 => 'Matrix Metering', + 7 => 'Center-weighted Metering', + 8 => 'Spot Metering', + 9 => 'My Menu Top', + 10 => '+ NEF (RAW)', + }, + }, + 16.1 => { # CSf2 + Name => 'OKButton', + Mask => 0x18, + PrintConv => { + 1 => 'Select Center Focus Point', + 2 => 'Highlight Active Focus Point', + 3 => 'Not Used', #(NC) + 0 => 'Not Used', #(NC) + }, + }, + 17.1 => { # CSf4 + Name => 'AELockButton', + Mask => 0x38, + PrintConv => { + 0 => 'AE/AF Lock', + 1 => 'AE Lock Only', + 2 => 'AF Lock Only', #(NC) + 3 => 'AE Lock (hold)', #(NC) + 4 => 'AF-ON', #(NC) + 5 => 'FV Lock', #(NC) + }, + }, + 18.1 => { # CSf5-a + Name => 'CommandDialsReverseRotation', + Mask => 0x80, + PrintConv => \%noYes, + }, + 18.2 => { # CSc1 + Name => 'ShutterReleaseButtonAE-L', + Mask => 0x02, + PrintConv => \%offOn, + }, + 19.1 => { # CSc2 + Name => 'MeteringTime', + Mask => 0xf0, + PrintConvColumns => 2, + PrintConv => { + 0 => '4 s', + 1 => '6 s', # default + 2 => '8 s', + 3 => '16 s', + 4 => '30 s', + 5 => '1 min', + 6 => '5 min', + 7 => '10 min', + 8 => '30 min', + }, + }, + 19.2 => { # CSc5 + Name => 'RemoteOnDuration', + Mask => 0x03, + PrintConv => { + 0 => '1 min', + 1 => '5 min', + 2 => '10 min', + 3 => '15 min', + }, + }, + 20.1 => { # CSc3-a + Name => 'SelfTimerTime', + Mask => 0xc0, + PrintConv => { + 0 => '2 s', + 1 => '5 s', + 2 => '10 s', # default + 3 => '20 s', + }, + }, + 20.2 => { # CSc3-b + Name => 'SelfTimerShotCount', + Mask => 0x1e, + }, + 21.1 => { # CSc4-a + Name => 'PlaybackMonitorOffTime', + Mask => 0x1c, + PrintConv => { + 0 => '4 s', + 1 => '10 s', # default + 2 => '20 s', + 3 => '1 min', + 4 => '5 min', + 5 => '10 min', + }, + }, + 21.2 => { # CSc4-d + Name => 'ImageReviewTime', + Mask => 0xe0, + PrintConv => { + 0 => '4 s', # default + 1 => '10 s', + 2 => '20 s', + 3 => '1 min', + 4 => '5 min', + 5 => '10 min', + }, + }, + 22.1 => { # CSc4-b + Name => 'MenuMonitorOffTime', + Mask => 0xe0, + PrintConv => { + 0 => '4 s', + 1 => '10 s', + 2 => '20 s', # default + 3 => '1 min', + 4 => '5 min', + 5 => '10 min', + }, + }, + 22.2 => { # CSc4-c + Name => 'ShootingInfoMonitorOffTime', + Mask => 0x1c, + PrintConv => { + 0 => '4 s', + 1 => '10 s', # default + 2 => '20 s', + 3 => '1 min', + 4 => '5 min', + 5 => '10 min', + }, + }, + 23.1 => { # CSe1 + Name => 'FlashShutterSpeed', + Mask => 0x0f, + PrintConvColumns => 2, + PrintConv => { + 0 => '1/60 s', # default + 1 => '1/30 s', + 2 => '1/15 s', + 3 => '1/8 s', + 4 => '1/4 s', + 5 => '1/2 s', + 6 => '1 s', + 7 => '2 s', + 8 => '4 s', + 9 => '8 s', + 10 => '15 s', + 11 => '30 s', + }, + }, + 24.1 => { # CSe2-a + Name => 'InternalFlash', + Mask => 0xc0, + PrintConv => { + 0 => 'TTL', + 1 => 'Manual', + 2 => 'Repeating Flash', + 3 => 'Commander Mode', + }, + }, + 24.2 => { # CSe2-b + Name => 'ManualFlashOutput', + Mask => 0x1f, + ValueConv => '2 ** (-$val/3)', + ValueConvInv => '$val > 0 ? -3*log($val)/log(2) : 0', + PrintConv => q{ + return 'Full' if $val > 0.99; + Image::ExifTool::Exif::PrintExposureTime($val); + }, + PrintConvInv => '$val=~/F/i ? 1 : Image::ExifTool::Exif::ConvertFraction($val)', + }, + 25.1 => { # CSe2-ca + Name => 'RepeatingFlashOutput', + Mask => 0x70, + ValueConv => '2 ** (-$val-2)', + ValueConvInv => '$val > 0 ? int(-log($val)/log(2)-2+0.5) : 0', + PrintConv => 'Image::ExifTool::Exif::PrintExposureTime($val)', + PrintConvInv => 'Image::ExifTool::Exif::ConvertFraction($val)', + }, + 25.2 => { # CSe2-cb + Name => 'RepeatingFlashCount', + Mask => 0x0f, + ValueConv => '$val < 10 ? $val + 1 : 5 * ($val - 7)', + ValueConvInv => '$val <= 10 ? $val - 1 : $val / 5 + 7', + }, + 26.1 => { # CSe2-cc (NC) + Name => 'RepeatingFlashRate', + Mask => 0xf0, + ValueConv => '$val < 10 ? $val + 1 : 10 * ($val - 8)', + ValueConvInv => 'int(($val <= 10 ? $val - 1 : $val / 10 + 8) + 0.5)', + PrintConv => '"$val Hz"', + PrintConvInv => '$val=~/(\d+)/; $1 || 0', + }, + 31.1 => { # CSd11 + Name => 'FlashWarning', + Mask => 0x80, + PrintConv => \%onOff, + }, + 31.2 => { # CSe2-ea + Name => 'CommanderInternalTTLComp', + Mask => 0x1f, + ValueConv => '($val - 9) / 3', + ValueConvInv => '$val * 3 + 9', + PrintConv => '$val ? sprintf("%+.1f",$val) : 0', + PrintConvInv => '$val', + }, + 31.3 => { # CSe3 + Name => 'ModelingFlash', + Mask => 0x20, + PrintConv => \%onOff, + }, + 31.4 => { # CSe5 + Name => 'AutoFP', + Mask => 0x40, + PrintConv => \%offOn, + }, + 32.1 => { # CSe2-eb + Name => 'CommanderGroupA_TTLComp', + Mask => 0x1f, + ValueConv => '($val - 9) / 3', + ValueConvInv => '$val * 3 + 9', + PrintConv => '$val ? sprintf("%+.1f",$val) : 0', + PrintConvInv => '$val', + }, + 33.1 => { # CSe2-ec + Name => 'CommanderGroupB_TTLComp', + Mask => 0x1f, + ValueConv => '($val - 9) / 3', + ValueConvInv => '$val * 3 + 9', + PrintConv => '$val ? sprintf("%+.1f",$val) : 0', + PrintConvInv => '$val', + }, + 34.1 => { # CSa7 + Name => 'LiveViewAF', + Mask => 0xc0, + PrintConv => { + 0 => 'Face Priority', #(NC) + 1 => 'Wide Area', + 2 => 'Normal Area', + }, + }, +); + +# D300 (ref JD) and D3 (ref 1/PH) custom settings +%Image::ExifTool::NikonCustom::SettingsD3 = ( + PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData, + WRITE_PROC => \&Image::ExifTool::WriteBinaryData, + CHECK_PROC => \&Image::ExifTool::CheckBinaryData, + WRITABLE => 1, + FIRST_ENTRY => 0, + GROUPS => { 0 => 'MakerNotes', 2 => 'Camera' }, + NOTES => 'Custom settings for the D3, D3S, D3X, D300 and D300S.', + # these settings have been decoded using the D3 and D300, and + # extrapolated to the other models, but these haven't yet been + # verified, and the following custom settings are missing: + # CSf1-d (D3X,D3S) MultiSelectorLiveView + # CSf1 (D300S) LightSwitch + 0.1 => { #1 + Name => 'CustomSettingsBank', + Mask => 0x03, + PrintConv => { + 0 => 'A', + 1 => 'B', + 2 => 'C', + 3 => 'D', + }, + }, + 0.2 => { #1 + Name => 'CustomSettingsAllDefault', + Notes => '"No" if any custom setting for this bank was changed from the default', + Mask => 0x80, + PrintConv => { 0 => 'Yes', 1 => 'No' }, + }, + 1.1 => { # CSa1 + Name => 'AF-CPrioritySelection', + Mask => 0xc0, + PrintConv => { + 0 => 'Release', + 1 => 'Release + Focus', + 2 => 'Focus', + }, + }, + 1.2 => { # CSa2 + Name => 'AF-SPrioritySelection', + Mask => 0x20, + PrintConv => { + 0 => 'Focus', + 1 => 'Release', + }, + }, + 1.3 => { # CSa8 + Name => 'AFPointSelection', + Mask => 0x10, + PrintConv => { + 0 => '51 Points', + 1 => '11 Points', + }, + }, + 1.4 => { # CSa3 + Name => 'DynamicAFArea', + Mask => 0x0c, + PrintConv => { + 0 => '9 Points', + 1 => '21 Points', + 2 => '51 Points', + 3 => '51 Points (3D-tracking)', + }, + }, + 1.5 => { # CSa4 + Name => 'FocusTrackingLockOn', + Condition => '$$self{Model} !~ /D3S\b/', + Notes => 'not D3S', + Mask => 0x03, + PrintConv => { + 0 => 'Long', + 1 => 'Normal', + 2 => 'Short', + 3 => 'Off', + }, + }, + 2.1 => { # CSa5 + Name => 'AFActivation', + Mask => 0x80, + PrintConv => { + 0 => 'Shutter/AF-On', + 1 => 'AF-On Only', + }, + }, + 2.2 => { # CSa7 + Name => 'FocusPointWrap', + Mask => 0x08, + PrintConv => { + 0 => 'No Wrap', + 1 => 'Wrap', + }, + }, + 2.3 => [ # CSa6 + { + Name => 'AFPointIllumination', + Condition => '$$self{Model} =~ /D3[SX]?\b/', + Notes => 'D3', + Mask => 0x60, + PrintConv => { + 0 => 'On in Continuous Shooting and Manual Focusing', + 1 => 'On During Manual Focusing', + 2 => 'On in Continuous Shooting Modes', + 3 => 'Off', + }, + }, + { + Name => 'AFPointIllumination', + Notes => 'D300', + Mask => 0x06, + PrintConv => { + 0 => 'Auto', + 1 => 'Off', + 2 => 'On', + }, + }, + ], + 2.4 => { # CSa6-b (D3, added by firmware update) + Name => 'AFPointBrightness', + Condition => '$$self{Model} =~ /D3[SX]?\b/', + Notes => 'D3 only', + Mask => 0x06, + PrintConv => { + 0 => 'Low', + 1 => 'Normal', + 2 => 'High', + 3 => 'Extra High', + }, + }, + 2.5 => { # CSa9 (D300) + Name => 'AFAssist', + Condition => '$$self{Model} =~ /D300S?\b/', + Notes => 'D300 only', + Mask => 0x01, + PrintConv => \%onOff, + }, + 3.1 => { # CSa9 (D3) + Name => 'AFOnButton', + Condition => '$$self{Model} =~ /D3[SX]?\b/', + Notes => 'D3 only', + Mask => 0x07, + PrintConv => { + 0 => 'AF On', + 1 => 'AE/AF Lock', + 2 => 'AE Lock Only', + 3 => 'AE Lock (reset on release)', + 4 => 'AE Lock (hold)', + 5 => 'AF Lock Only', + }, + }, + 3.2 => { # CSa10 (D3) + Name => 'VerticalAFOnButton', + Condition => '$$self{Model} =~ /D3[SX]?\b/', + Notes => 'D3 only', + Mask => 0x70, + PrintConv => { + 0 => 'AF On', + 1 => 'AE/AF Lock', + 2 => 'AE Lock Only', + 3 => 'AE Lock (reset on release)', + 4 => 'AE Lock (hold)', + 5 => 'AF Lock Only', + 7 => 'Same as AF On', + }, + }, + 3.3 => { # CSa10 (D300) + Name => 'AF-OnForMB-D10', + Condition => '$$self{Model} =~ /D300S?\b/', + Notes => 'D300 only', + Mask => 0x70, + PrintConv => { + 0 => 'AF-On', + 1 => 'AE/AF Lock', + 2 => 'AE Lock Only', + 3 => 'AE Lock (reset on release)', + 4 => 'AE Lock (hold)', + 5 => 'AF Lock Only', + 6 => 'Same as FUNC Button', + }, + }, + 4.1 => { # CSa4 (D3S) + Name => 'FocusTrackingLockOn', + Condition => '$$self{Model} =~ /D3S\b/', + Notes => 'D3S only', + Mask => 0x07, + PrintConv => { + 0 => '5 (Long)', + 1 => '4', + 2 => '3 (Normal)', + 3 => '2', + 4 => '1 (Short)', + 5 => 'Off', + }, + }, + 4.2 => { # CSf7 (D3S) + Name => 'AssignBktButton', + Condition => '$$self{Model} =~ /D3S\b/', + Notes => 'D3S only', + Mask => 0x08, + PrintConv => { + 0 => 'Auto Bracketing', + 1 => 'Multiple Exposure', + }, + }, + 4.3 => { # CSf1-c (D3S) (ref 1) + Name => 'MultiSelectorLiveView', + Condition => '$$self{Model} =~ /D3S\b/', + Notes => 'D3S only', + Mask => 0xc0, + PrintConv => { + 0 => 'Reset', + 1 => 'Zoom On/Off', + 2 => 'Start Movie Recording', + 3 => 'Not Used', + }, + }, + 4.4 => { # CSf1-c2 (D3S) (ref 1) + Name => 'InitialZoomLiveView', + Condition => '$$self{Model} =~ /D3S\b/', + Notes => 'D3S only', + Mask => 0x30, + PrintConv => { + 0 => 'Low Magnification', + 1 => 'Medium Magnification', + 2 => 'High Magnification', + }, + }, + 6.1 => { # CSb1 + Name => 'ISOStepSize', + Mask => 0xc0, + PrintConv => { + 0 => '1/3 EV', + 1 => '1/2 EV', + 2 => '1 EV', + }, + }, + 6.2 => { # CSb2 + Name => 'ExposureControlStepSize', + Mask => 0x30, + PrintConv => { + 0 => '1/3 EV', + 1 => '1/2 EV', + 2 => '1 EV', + }, + }, + 6.3 => { # CSb3 + Name => 'ExposureCompStepSize', + Mask => 0x0c, + PrintConv => { + 0 => '1/3 EV', + 1 => '1/2 EV', + 2 => '1 EV', + }, + }, + 6.4 => { # CSb4 + Name => 'EasyExposureCompensation', + Mask => 0x03, + PrintConv => { + 0 => 'Off', + 1 => 'On', + 2 => 'On (auto reset)', + }, + }, + 7.1 => [ # CSb5 + { + Name => 'CenterWeightedAreaSize', + Condition => '$$self{Model} =~ /D3[SX]?\b/', + Notes => 'D3', + Mask => 0xe0, + PrintConv => { + 0 => '8 mm', + 1 => '12 mm', + 2 => '15 mm', + 3 => '20 mm', + 4 => 'Average', + }, + }, + { + Name => 'CenterWeightedAreaSize', + Notes => 'D300', + Mask => 0xe0, + PrintConv => { + 0 => '6 mm', + 1 => '8 mm', + 2 => '10 mm', + 3 => '13 mm', + 4 => 'Average', + }, + }, + ], + 7.2 => { # CSb6-b + Name => 'FineTuneOptCenterWeighted', + Mask => 0x0f, + ValueConv => '($val > 0x7 ? $val - 0x10 : $val) / 6', + ValueConvInv => 'int($val*6+($val>0?0.5:-0.5))', + PrintConv => '$val ? sprintf("%+.2f", $val) : 0', + PrintConvInv => 'Image::ExifTool::Exif::ConvertFraction($val)', + }, + 8.1 => { # CSb6-a + Name => 'FineTuneOptMatrixMetering', + Mask => 0xf0, + ValueConv => '($val > 0x7 ? $val - 0x10 : $val) / 6', + ValueConvInv => 'int($val*6+($val>0?0.5:-0.5))', + PrintConv => '$val ? sprintf("%+.2f", $val) : 0', + PrintConvInv => 'Image::ExifTool::Exif::ConvertFraction($val)', + }, + 8.2 => { # CSb6-c + Name => 'FineTuneOptSpotMetering', + Mask => 0x0f, + ValueConv => '($val > 0x7 ? $val - 0x10 : $val) / 6', + ValueConvInv => 'int($val*6+($val>0?0.5:-0.5))', + PrintConv => '$val ? sprintf("%+.2f", $val) : 0', + PrintConvInv => 'Image::ExifTool::Exif::ConvertFraction($val)', + }, + 9.1 => { # CSf1-a, CSf2-a (D300S) + Name => 'MultiSelectorShootMode', + Mask => 0xc0, + PrintConv => { + 0 => 'Select Center Focus Point', + 1 => 'Highlight Active Focus Point', + 2 => 'Not Used', + }, + }, + 9.2 => { # CSf1-b, CSf2-b (D300S) + Name => 'MultiSelectorPlaybackMode', + Condition => '$$self{Model} !~ /D3S\b/', + Notes => 'all models except D3S', # (not confirmed for D3X) + Mask => 0x30, + PrintConv => { + 0 => 'Thumbnail On/Off', + 1 => 'View Histograms', + 2 => 'Zoom On/Off', + 3 => 'Choose Folder', + }, + }, + 9.3 => [ # CSf1-b2, CSf2-b2 (D300S) + { + Name => 'InitialZoomSetting', + Condition => '$$self{Model} =~ /D3[SX]?\b/', + Notes => 'D3', + Mask => 0x0c, + PrintConv => { #1 + 0 => 'High Magnification', + 1 => 'Medium Magnification', + 2 => 'Low Magnification', + }, + }, + { + Name => 'InitialZoomSetting', + Notes => 'D300', + Mask => 0x0c, + PrintConv => { #JD + 0 => 'Low Magnification', + 1 => 'Medium Magnification', + 2 => 'High Magnification', + }, + }, + ], + 9.4 => { # CSf2 (D300,D3), CSf3 (D300S) + Name => 'MultiSelector', + Mask => 0x01, + PrintConv => { + 0 => 'Do Nothing', + 1 => 'Reset Meter-off Delay', + }, + }, + 10.1 => { # CSd9 (D300,D3S), CSd10 (D300S), CSd8 (D3) + Name => 'ExposureDelayMode', + Mask => 0x40, + PrintConv => \%offOn, + }, + 10.2 => { # CSd4 (D300), CDs5 (D300S), CSd2-a (D3) + Name => 'CLModeShootingSpeed', + Mask => 0x07, + PrintConv => '"$val fps"', + PrintConvInv => '$val=~s/\s*fps//i; $val', + }, + 10.3 => { # (D3 CSd2-b) + Name => 'CHModeShootingSpeed', + Condition => '$$self{Model} =~ /D3[SX]?\b/', + Notes => 'D3 only', + Mask => 0x30, + PrintConv => { + 0 => '9 fps', + 1 => '10 fps', + 2 => '11 fps', + }, + }, + 11 => { # CSd5 (D300), CSd6 (D300S), CSd3 (D3) + Name => 'MaxContinuousRelease', + # values: 1-100 (D300), 1-130 (D3) + }, + 12.1 => { # CSf10, CSf11 (D3S,D300S) + Name => 'ReverseIndicators', + Mask => 0x20, + PrintConv => { + 0 => '+ 0 -', + 1 => '- 0 +', + }, + }, + 12.2 => [ # CSd6 (D300), CSd7 (D300S), CSd4 (D3) + { + Name => 'FileNumberSequence', + Condition => '$$self{Model} =~ /D3[SX]?\b/', + Notes => 'D3', + Mask => 0x02, + PrintConv => \%onOff, + }, + { + Name => 'FileNumberSequence', + Notes => 'D300', + Mask => 0x08, + PrintConv => \%onOff, + }, + ], + 12.3 => { # CSd5-a (D3) + Name => 'RearDisplay', + Condition => '$$self{Model} =~ /D3[SX]?\b/', + Notes => 'D3 only', + Mask => 0x80, + PrintConv => { + 0 => 'ISO', + 1 => 'Exposures Remaining', + }, + }, + 12.4 => { # CSd5-b (D3) + Name => 'ViewfinderDisplay', + Condition => '$$self{Model} =~ /D3[SX]?\b/', + Notes => 'D3 only', + Mask => 0x40, + PrintConv => { + 0 => 'Frame Count', + 1 => 'Exposures Remaining', + }, + }, + 12.5 => { # CSd11 (D300), CSd12 (D300S) + Name => 'BatteryOrder', + Condition => '$$self{Model} =~ /D300S?\b/', + Notes => 'D300 only', + Mask => 0x04, + PrintConv => { + 0 => 'MB-D10 First', + 1 => 'Camera Battery First', + }, + }, + 12.6 => { # CSd10 (D300), CSd11 (D300S) + Name => 'MB-D10Batteries', + Condition => '$$self{Model} =~ /D300S?\b/', + Notes => 'D300 only', + Mask => 0x03, + PrintConv => { + 0 => 'LR6 (AA alkaline)', + 1 => 'HR6 (AA Ni-MH)', + 2 => 'FR6 (AA lithium)', + 3 => 'ZR6 (AA Ni-Mn)', + }, + }, + 12.7 => { # CSd7 (D3S), CSd4, (D300S) + Name => 'ScreenTips', + Condition => '$$self{Model} =~ /(D3S|D300S)\b/', + Mask => 0x10, + PrintConv => \%onOff, + }, + 13.1 => { # CSd1 + Name => 'Beep', + Mask => 0xc0, + PrintConv => { + 0 => 'High', + 1 => 'Low', + 2 => 'Off', + }, + }, + 13.2 => { # CSd7 (D300), CSd8 (D300S), CSd6 (D3) + Name => 'ShootingInfoDisplay', + Mask => 0x30, + PrintConv => { + 0 => 'Auto', #JD (D300) + 1 => 'Auto', #1 (D3) + 2 => 'Manual (dark on light)', + 3 => 'Manual (light on dark)', + }, + }, + 13.3 => { # CSd2 (D300) + Name => 'GridDisplay', + Condition => '$$self{Model} =~ /D300S?\b/', + Notes => 'D300 only', + Mask => 0x02, + PrintConv => \%offOn, + }, + 13.4 => { # CSd3 (D300) + Name => 'ViewfinderWarning', + Condition => '$$self{Model} =~ /D300S?\b/', + Notes => 'D300 only', + Mask => 0x01, + PrintConv => \%onOff, + }, + 13.5 => { # CSf1-b (D3S) (ref 1) + Name => 'MultiSelectorPlaybackMode', + Condition => '$$self{Model} =~ /D3S\b/', + Notes => 'D3S only', + Mask => 0x03, + PrintConv => { + 0 => 'Thumbnail On/Off', + 1 => 'View Histograms', + 2 => 'Zoom On/Off', + }, + }, + 14.1 => [ # CSf5-a (ref 1), CSf6-a (D300S) + { + Name => 'PreviewButton', + Condition => '$$self{Model} =~ /D3[SX]?\b/', + Notes => 'D3', + Mask => 0xf8, + PrintConv => { + 0 => 'None', + 1 => 'Preview', + 2 => 'FV Lock', + 3 => 'AE/AF Lock', + 4 => 'AE Lock Only', + 5 => 'AE Lock (reset on release)', + 6 => 'AE Lock (hold)', + 7 => 'AF Lock Only', + 8 => 'Flash Off', + 9 => 'Bracketing Burst', + 10 => 'Matrix Metering', + 11 => 'Center-weighted Metering', + 12 => 'Spot Metering', + 13 => 'Virtual Horizon', + # 14 not used + 15 => 'Playback', + 16 => 'My Menu Top', + }, + }, + { #PH + Name => 'FuncButton', + Notes => 'D300', + Mask => 0xf8, + PrintConv => { + 0 => 'None', + 1 => 'Preview', + 2 => 'FV Lock', + 3 => 'AE/AF Lock', + 4 => 'AE Lock Only', + 5 => 'AE Lock (reset on release)', + 6 => 'AE Lock (hold)', + 7 => 'AF Lock Only', + # 8 not used + 9 => 'Flash Off', + 10 => 'Bracketing Burst', + 11 => 'Matrix Metering', + 12 => 'Center-weighted Metering', + 13 => 'Spot Metering', + 14 => 'Playback', #PH (guess) + 15 => 'My Menu Top', #PH (guess) + 16 => '+ NEF (RAW)', #PH (guess) + }, + }, + ], + 14.2 => [ # CSf5-b (PH,NC), CSf6-b (D300S) + { + Name => 'PreviewButtonPlusDials', + Condition => '$$self{Model} =~ /D3[SX]?\b/', + Notes => 'D3', + Mask => 0x07, + PrintConv => { + 0 => 'None', + 1 => 'Choose Image Area (FX/DX/5:4)', + 2 => 'One Step Speed/Aperture', + 3 => 'Choose Non-CPU Lens Number', + # n/a 4 => 'Focus Point Selection', + 5 => 'Choose Image Area (FX/DX)', + 6 => 'Shooting Bank Menu', + 7 => 'Dynamic AF Area', #PH (D3S,D3X,NC) + }, + }, + { #PH + Name => 'FuncButtonPlusDials', + Notes => 'D300', + Mask => 0x07, + PrintConv => { + 0 => 'None', + 2 => 'One Step Speed/Aperture', + 3 => 'Choose Non-CPU Lens Number', + 5 => 'Auto Bracketing', + 6 => 'Dynamic AF Area', + }, + }, + ], + 15.1 => [ # CSf4-a (ref 1), CSf5-a (D300S) + { + Name => 'FuncButton', + Condition => '$$self{Model} =~ /D3[SX]?\b/', + Notes => 'D3', + Mask => 0xf8, + PrintConv => { + 0 => 'None', + 1 => 'Preview', + 2 => 'FV Lock', + 3 => 'AE/AF Lock', + 4 => 'AE Lock Only', + 5 => 'AE Lock (reset on release)', + 6 => 'AE Lock (hold)', + 7 => 'AF Lock Only', + 8 => 'Flash Off', + 9 => 'Bracketing Burst', + 10 => 'Matrix Metering', + 11 => 'Center-weighted Metering', + 12 => 'Spot Metering', + 13 => 'Virtual Horizon', + # 14 not used + 15 => 'Playback', + 16 => 'My Menu Top', + }, + }, + { #PH + Name => 'PreviewButton', + Notes => 'D300', + Mask => 0xf8, + PrintConv => { + 0 => 'None', + 1 => 'Preview', + 2 => 'FV Lock', + 3 => 'AE/AF Lock', + 4 => 'AE Lock Only', + 5 => 'AE Lock (reset on release)', + 6 => 'AE Lock (hold)', + 7 => 'AF Lock Only', + # 8 not used + 9 => 'Flash Off', + 10 => 'Bracketing Burst', + 11 => 'Matrix Metering', + 12 => 'Center-weighted Metering', + 13 => 'Spot Metering', + 14 => 'Playback', #PH (guess) + 15 => 'My Menu Top', #PH (guess) + 16 => '+ NEF (RAW)', #PH (guess) + }, + }, + ], + 15.2 => [ # CSf4-b (ref 1), CSf5-b (D300S) + { + Name => 'FuncButtonPlusDials', + Condition => '$$self{Model} =~ /D3[SX]?\b/', + Notes => 'D3', + Mask => 0x07, + PrintConv => { + 0 => 'None', + 1 => 'Choose Image Area (FX/DX/5:4)', + 2 => 'One Step Speed/Aperture', + 3 => 'Choose Non-CPU Lens Number', + 4 => 'Focus Point Selection', #(NC) + 5 => 'Choose Image Area (FX/DX)', + 6 => 'Shooting Bank Menu', + 7 => 'Dynamic AF Area', #PH (D3S,D3X,NC) + }, + }, + { #PH + Name => 'PreviewButtonPlusDials', + Notes => 'D300', + Mask => 0x07, + PrintConv => { + 0 => 'None', + 2 => 'One Step Speed/Aperture', + 3 => 'Choose Non-CPU Lens Number', + 5 => 'Auto Bracketing', + 6 => 'Dynamic AF Area', + }, + }, + ], + 16.1 => [ # CSf6-a (ref 1), CSf7-a (D300S) + { + Name => 'AELockButton', + Condition => '$$self{Model} =~ /D3[SX]?\b/', + Notes => 'D3', + Mask => 0xf8, + PrintConv => { + 0 => 'None', + 1 => 'Preview', + 2 => 'FV Lock', + 3 => 'AE/AF Lock', + 4 => 'AE Lock Only', + 5 => 'AE Lock (reset on release)', + 6 => 'AE Lock (hold)', + 7 => 'AF Lock Only', + 8 => 'Flash Off', + 9 => 'Bracketing Burst', + 10 => 'Matrix Metering', + 11 => 'Center-weighted Metering', + 12 => 'Spot Metering', + 13 => 'Virtual Horizon', + 14 => 'AF On', # (AE-L/AF-L button only) + 15 => 'Playback', + 16 => 'My Menu Top', + }, + }, + { #PH + Name => 'AELockButton', + Notes => 'D300', + Mask => 0xf8, + PrintConv => { + 0 => 'None', + 1 => 'Preview', + 2 => 'FV Lock', + 3 => 'AE/AF Lock', + 4 => 'AE Lock Only', + 5 => 'AE Lock (reset on release)', + 6 => 'AE Lock (hold)', + 7 => 'AF Lock Only', + 8 => 'AF On', # (AE-L/AF-L button only) + 9 => 'Flash Off', + 10 => 'Bracketing Burst', + 11 => 'Matrix Metering', + 12 => 'Center-weighted Metering', + 13 => 'Spot Metering', + 14 => 'Playback', #PH (guess) + 15 => 'My Menu Top', #PH (guess) + 16 => '+ NEF (RAW)', #PH (guess) + }, + }, + ], + 16.2 => [ # CSf6-b (ref 1), CSf7-b (D300S) + { + Name => 'AELockButtonPlusDials', + Condition => '$$self{Model} =~ /D3[SX]?\b/', + Notes => 'D3', + Mask => 0x07, + PrintConv => { + 0 => 'None', + 1 => 'Choose Image Area (FX/DX/5:4)', + 2 => 'One Step Speed/Aperture', + 3 => 'Choose Non-CPU Lens Number', + # n/c 4 => 'Focus Point Selection', #(NC) + 5 => 'Choose Image Area (FX/DX)', + 6 => 'Shooting Bank Menu', + 7 => 'Dynamic AF Area', #PH (D3S,D3X,NC) + }, + }, + { #PH + Name => 'AELockButtonPlusDials', + Notes => 'D300', + Mask => 0x07, + PrintConv => { + 0 => 'None', + # n/a 2 => 'One Step Speed/Aperture', + 3 => 'Choose Non-CPU Lens Number', + 5 => 'Auto Bracketing', #(NC) + 6 => 'Dynamic AF Area', + }, + }, + ], + 17.1 => { # CSf7-a, CSf8-a (D3S,D300S) + Name => 'CommandDialsReverseRotation', + Mask => 0x80, + PrintConv => \%noYes, + }, + 17.2 => { # CSf7-b, CSf8-b (D3S,D300S) + Name => 'CommandDialsChangeMainSub', + Mask => 0x40, + PrintConv => \%offOn, + }, + 17.3 => { # CSf7-c, CSf8-c (D3S,D300S) + Name => 'CommandDialsApertureSetting', + Mask => 0x20, + PrintConv => { + 0 => 'Sub-command Dial', + 1 => 'Aperture Ring', + }, + }, + 17.4 => { # CSf7-d, CSf8-d (D3S,D300S) + Name => 'CommandDialsMenuAndPlayback', + Mask => 0x10, + PrintConv => \%offOn, + }, + 17.5 => { # CSd8 (D300,D3S), CSd9 (D300S), CSd7 (D3) + Name => 'LCDIllumination', + Mask => 0x08, + PrintConv => \%offOn, + }, + 17.6 => { # CSf3, CSf4 (D300S) + Name => 'PhotoInfoPlayback', + Mask => 0x04, + PrintConv => { + 0 => 'Info Up-down, Playback Left-right', + 1 => 'Info Left-right, Playback Up-down', + }, + }, + 17.7 => { # CSc1 + Name => 'ShutterReleaseButtonAE-L', + Mask => 0x02, + PrintConv => \%offOn, + }, + 17.8 => { # CSf8, CSf9 (D3S,D300S) + Name => 'ReleaseButtonToUseDial', + Mask => 0x01, + PrintConv => \%noYes, + }, + 18.1 => { # CSc3 + Name => 'SelfTimerTime', + Mask => 0x18, + PrintConv => { + 0 => '2 s', + 1 => '5 s', + 2 => '10 s', + 3 => '20 s', + }, + }, + 18.2 => { # CSc4 + Name => 'MonitorOffTime', + # NOTE: The D3S and D300S have separate settings for Playback, + # Image Review, Menus, and Information Display times + Mask => 0x07, + PrintConv => { + 0 => '10 s', + 1 => '20 s', + 2 => '1 min', + 3 => '5 min', + 4 => '10 min', + }, + }, + 20.1 => [ # CSe1 + { + Name => 'FlashSyncSpeed', + Condition => '$$self{Model} =~ /D3[SX]?\b/', + Notes => 'D3', + Mask => 0xe0, + PrintConv => { + 0 => '1/250 s (auto FP)', + 1 => '1/250 s', + 2 => '1/200 s', + 3 => '1/160 s', + 4 => '1/125 s', + 5 => '1/100 s', + 6 => '1/80 s', + 7 => '1/60 s', + }, + }, + { + Name => 'FlashSyncSpeed', + Notes => 'D300', + Mask => 0xf0, + PrintConv => { + 0 => '1/320 s (auto FP)', + 1 => '1/250 s (auto FP)', + 2 => '1/250 s', + 3 => '1/200 s', + 4 => '1/160 s', + 5 => '1/125 s', + 6 => '1/100 s', + 7 => '1/80 s', + 8 => '1/60 s', + }, + }, + ], + 20.2 => { # CSe2 + Name => 'FlashShutterSpeed', + Mask => 0x0f, + PrintConvColumns => 2, + PrintConv => { + 0 => '1/60 s', + 1 => '1/30 s', + 2 => '1/15 s', + 3 => '1/8 s', + 4 => '1/4 s', + 5 => '1/2 s', + 6 => '1 s', + 7 => '2 s', + 8 => '4 s', + 9 => '8 s', + 10 => '15 s', + 11 => '30 s', + }, + }, + 21.1 => [{ # CSe5 (D300), CSe4 (D3) + Name => 'AutoBracketSet', + Condition => '$$self{Model} !~ /(D3S|D300S)\b/', + Notes => 'D3 and D300', + Mask => 0xc0, + PrintConv => { + 0 => 'AE & Flash', + 1 => 'AE Only', + 2 => 'Flash Only', + 3 => 'WB Bracketing', + }, + },{ # CSe4 (D3S) (NC for D300S) + Name => 'AutoBracketSet', + Notes => 'D3S and D300S', + Mask => 0xe0, + PrintConv => { + 0 => 'AE & Flash', + 1 => 'AE Only', + 2 => 'Flash Only', + 3 => 'WB Bracketing', + # D3S/D300S have an "ADL Bracketing" setting - PH + 4 => 'ADL Bracketing', + }, + }], + 21.2 => [{ # CSe6 (D300), CSe5 (D3) + Name => 'AutoBracketModeM', + Condition => '$$self{Model} !~ /(D3S|D300S)\b/', + Notes => 'D3 and D300', + Mask => 0x30, + PrintConv => { + 0 => 'Flash/Speed', + 1 => 'Flash/Speed/Aperture', + 2 => 'Flash/Aperture', + 3 => 'Flash Only', + }, + },{ # CSe5 (D3S) + Name => 'AutoBracketModeM', + Notes => 'D3S and D300S', + Mask => 0x18, + PrintConv => { + 0 => 'Flash/Speed', + 1 => 'Flash/Speed/Aperture', + 2 => 'Flash/Aperture', + 3 => 'Flash Only', + }, + }], + 21.3 => [{ # CSe7 (D300), CSe6 (D3) + Name => 'AutoBracketOrder', + Condition => '$$self{Model} !~ /(D3S|D300S)\b/', + Notes => 'D3 and D300', + Mask => 0x08, + PrintConv => { + 0 => '0,-,+', + 1 => '-,0,+', + }, + },{ # CSe6 (D3S) + Name => 'AutoBracketOrder', + Notes => 'D3S and D300S', + Mask => 0x04, + PrintConv => { + 0 => '0,-,+', + 1 => '-,0,+', + }, + }], + 21.4 => { # CSe4 (D300), CSe3 (D3) + Name => 'ModelingFlash', + Mask => 0x01, + PrintConv => \%onOff, + }, + 22.1 => { # CSf9, CSf10 (D3S,D300S) + Name => 'NoMemoryCard', + Mask => 0x80, + PrintConv => { + 0 => 'Release Locked', + 1 => 'Enable Release', + }, + }, + 22.2 => { # CSc2 + Name => 'MeteringTime', + Mask => 0x0f, + PrintConvColumns => 2, + PrintConv => { + 0 => '4 s', + 1 => '6 s', + 2 => '8 s', + 3 => '16 s', + 4 => '30 s', + 5 => '1 min', + 6 => '5 min', + 7 => '10 min', + 8 => '30 min', + 9 => 'No Limit', + }, + }, + 23.1 => { # CSe3 + Name => 'InternalFlash', + Mask => 0xc0, + PrintConv => { + 0 => 'TTL', + 1 => 'Manual', + 2 => 'Repeating Flash', + 3 => 'Commander Mode', + }, + }, + 25.1 => { #1 CSc4-d (D3S) + Name => 'ImageReviewTime', + Mask => 0xe0, + PrintConv => { + 0 => '4 s', + 1 => '10 s', + 2 => '20 s', + 3 => '1 min', + 4 => '5 min', + 5 => '10 min', + }, + }, + 25.2 => { #1 CSc4-a (D3S) + Name => 'PlaybackMonitorOffTime', + Mask => 0x1c, + PrintConv => { + 0 => '4 s', + 1 => '10 s', + 2 => '20 s', + 3 => '1 min', + 4 => '5 min', + 5 => '10 min', + }, + }, + 26.1 => { #1 CSc4-b (D3S) + Name => 'MenuMonitorOffTime', + Mask => 0xe0, + PrintConv => { + 0 => '4 s', + 1 => '10 s', + 2 => '20 s', + 3 => '1 min', + 4 => '5 min', + 5 => '10 min', + }, + }, + 26.2 => { #1 CSc4-c (D3S) + Name => 'ShootingInfoMonitorOffTime', + Mask => 0x1c, + PrintConv => { + 0 => '4 s', + 1 => '10 s', + 2 => '20 s', + 3 => '1 min', + 4 => '5 min', + 5 => '10 min', + }, + }, +); + +# D700 custom settings (ref 2) +%Image::ExifTool::NikonCustom::SettingsD700 = ( + PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData, + WRITE_PROC => \&Image::ExifTool::WriteBinaryData, + CHECK_PROC => \&Image::ExifTool::CheckBinaryData, + WRITABLE => 1, + FIRST_ENTRY => 0, + DATAMEMBER => [ 16.1 ], + GROUPS => { 0 => 'MakerNotes', 2 => 'Camera' }, + NOTES => 'Custom settings for the D700.', + 0.1 => { #1 + Name => 'CustomSettingsBank', + Mask => 0x03, + PrintConv => { + 0 => 'A', + 1 => 'B', + 2 => 'C', + 3 => 'D', + }, + }, + 0.2 => { #1 + Name => 'CustomSettingsAllDefault', + Notes => '"No" if any custom setting for this bank was changed from the default', + Mask => 0x80, + PrintConv => { 0 => 'Yes', 1 => 'No' }, + }, + 1.1 => { # CSa1 + Name => 'AF-CPrioritySelection', + Mask => 0xc0, + PrintConv => { + 0 => 'Release', + 1 => 'Release + Focus', + 2 => 'Focus', + }, + }, + 1.2 => { # CSa2 + Name => 'AF-SPrioritySelection', + Mask => 0x20, + PrintConv => { + 0 => 'Focus', + 1 => 'Release', + }, + }, + 1.3 => { # CSa8 + Name => 'AFPointSelection', + Mask => 0x10, + PrintConv => { + 0 => '51 Points', + 1 => '11 Points', + }, + }, + 1.4 => { # CSa3 + Name => 'DynamicAFArea', + Mask => 0x0c, + PrintConv => { + 0 => '9 Points', + 1 => '21 Points', + 2 => '51 Points', + 3 => '51 Points (3D-tracking)', + }, + }, + 2.1 => { # CSa5 + Name => 'AFActivation', + Mask => 0x80, + PrintConv => { + 0 => 'Shutter/AF-On', + 1 => 'AF-On Only', + }, + }, + 2.2 => { # CSa7 + Name => 'FocusPointWrap', + Mask => 0x08, + PrintConv => { + 0 => 'No Wrap', + 1 => 'Wrap', + }, + }, + 2.3 => { # CSa6 + Name => 'AFPointIllumination', + Mask => 0x06, + PrintConv => { + 0 => 'Auto', + 1 => 'Off', + 2 => 'On', + }, + }, + 2.4 => { # CSa9 + Name => 'AFAssist', + Mask => 0x01, + PrintConv => \%onOff, + }, + 3.1 => { # CSa4 + Name => 'FocusTrackingLockOn', + Mask => 0x07, + PrintConv => { + 0 => '3 Normal', + 1 => '4', + 2 => '5 Long', + 3 => '2', + 4 => '1 Short', + 5 => 'Off', + }, + }, + 3.2 => { # CSa10 + Name => 'AF-OnForMB-D10', + Mask => 0x70, + PrintConv => { + 0 => 'AF-On', + 1 => 'AE/AF Lock', + 2 => 'AE Lock Only', + 3 => 'AE Lock (reset on release)', + 4 => 'AE Lock (hold)', + 5 => 'AF Lock Only', + 6 => 'Same as FUNC Button', + }, + }, + 4.1 => { # CSb1 + Name => 'ISOStepSize', + Mask => 0xc0, + PrintConv => { + 0 => '1/3 EV', + 1 => '1/2 EV', + 2 => '1 EV', + }, + }, + 4.2 => { # CSb2 + Name => 'ExposureControlStepSize', + Mask => 0x30, + PrintConv => { + 0 => '1/3 EV', + 1 => '1/2 EV', + 2 => '1 EV', + }, + }, + 4.3 => { # CSb3 + Name => 'ExposureCompStepSize', + Mask => 0x0c, + PrintConv => { + 0 => '1/3 EV', + 1 => '1/2 EV', + 2 => '1 EV', + }, + }, + 4.4 => { # CSb4 + Name => 'EasyExposureCompensation', + Mask => 0x03, + PrintConv => { + 0 => 'Off', + 1 => 'On', + 2 => 'On (auto reset)', + }, + }, + 5.1 => { # CSb5 + Name => 'CenterWeightedAreaSize', + Mask => 0x70, + PrintConv => { + 0 => '8 mm', + 1 => '12 mm', + 2 => '15 mm', + 3 => '20 mm', + 4 => 'Average', + }, + }, + 6.1 => { # CSb6-a + Name => 'FineTuneOptMatrixMetering', + Mask => 0xf0, + ValueConv => '($val > 0x7 ? $val - 0x10 : $val) / 6', + ValueConvInv => 'int($val*6+($val>0?0.5:-0.5))', + PrintConv => '$val ? sprintf("%+.2f", $val) : 0', + PrintConvInv => 'Image::ExifTool::Exif::ConvertFraction($val)', + }, + 6.2 => { # CSb6-c + Name => 'FineTuneOptSpotMetering', + Mask => 0x0f, + ValueConv => '($val > 0x7 ? $val - 0x10 : $val) / 6', + ValueConvInv => 'int($val*6+($val>0?0.5:-0.5))', + PrintConv => '$val ? sprintf("%+.2f", $val) : 0', + PrintConvInv => 'Image::ExifTool::Exif::ConvertFraction($val)', + }, + 7.1 => { # CSc1 + Name => 'ShutterReleaseButtonAE-L', + Mask => 0x80, + PrintConv => \%offOn, + }, + 7.2 => { # CSc3 + Name => 'SelfTimerTime', + Mask => 0x30, + PrintConv => { + 0 => '2 s', + 1 => '5 s', + 2 => '10 s', + 3 => '20 s', + }, + }, + 7.3 => { # CSc2 + Name => 'MeteringTime', + Mask => 0x0f, + PrintConvColumns => 2, + PrintConv => { + 0 => '4 s', + 1 => '6 s', + 2 => '8 s', + 3 => '16 s', + 4 => '30 s', + 5 => '1 min', + 6 => '5 min', + 7 => '10 min', + 8 => '30 min', + 9 => 'No Limit', + }, + }, + 8.1 => { # CSc4-a + Name => 'PlaybackMonitorOffTime', + Mask => 0x38, + PrintConv => { + 0 => '4 s', + 1 => '10 s', + 2 => '20 s', + 3 => '1 min', + 4 => '5 min', + 5 => '10 min', + }, + }, + 8.2 => { # CSc4-b + Name => 'MenuMonitorOffTime', + Mask => 0x07, + PrintConv => { + 0 => '4 s', + 1 => '10 s', + 2 => '20 s', + 3 => '1 min', + 4 => '5 min', + 5 => '10 min', + }, + }, + 9.1 => { # CSc4-c + Name => 'ShootingInfoMonitorOffTime', + Mask => 0x38, + PrintConv => { + 0 => '4 s', + 1 => '10 s', + 2 => '20 s', + 3 => '1 min', + 4 => '5 min', + 5 => '10 min', + }, + }, + 9.2 => { # CSc4-d + Name => 'ImageReviewTime', + Mask => 0x07, + PrintConv => { + 0 => '4 s', + 1 => '10 s', + 2 => '20 s', + 3 => '1 min', + 4 => '5 min', + 5 => '10 min', + }, + }, + 10.1 => { # CSd1 + Name => 'Beep', + Mask => 0xc0, + PrintConv => { + 0 => 'High', + 1 => 'Low', + 2 => 'Off', + }, + }, + 10.2 => { # CSd7 + Name => 'ShootingInfoDisplay', + Mask => 0x30, + PrintConv => { + 0 => 'Auto', #JD (D300) + 1 => 'Auto', #1 (D3) + 2 => 'Manual (dark on light)', + 3 => 'Manual (light on dark)', + }, + }, + 10.3 => { # CSd8 + Name => 'LCDIllumination', + Mask => 0x08, + PrintConv => \%offOn, + }, + 10.4 => { # CSd9 + Name => 'ExposureDelayMode', + Mask => 0x04, + PrintConv => \%offOn, + }, + 10.5 => { # CSd2 + Name => 'GridDisplay', + Mask => 0x02, + PrintConv => \%offOn, + }, + 11.1 => { # CSd6 + Name => 'FileNumberSequence', + Mask => 0x40, + PrintConv => \%onOff, + }, + 11.2 => { # CSd4 + Name => 'CLModeShootingSpeed', + Mask => 0x07, + PrintConv => '"$val fps"', + PrintConvInv => '$val=~s/\s*fps//i; $val', + }, + 12 => { # CSd5 + Name => 'MaxContinuousRelease', + # values: 1-100 + }, + 13.1 => { # CSd3 + Name => 'ScreenTips', + Mask => 0x08, + PrintConv => \%onOff, + }, + 13.2 => { # CSd11 + Name => 'BatteryOrder', + Mask => 0x04, + PrintConv => { + 0 => 'MB-D10 First', + 1 => 'Camera Battery First', + }, + }, + 13.3 => { # CSd10 + Name => 'MB-D10BatteryType', + Mask => 0x03, + PrintConv => { + 0 => 'LR6 (AA alkaline)', + 1 => 'HR6 (AA Ni-MH)', + 2 => 'FR6 (AA lithium)', + 3 => 'ZR6 (AA Ni-Mn)', + }, + }, + 15.1 => { # CSe1 + Name => 'FlashSyncSpeed', + Mask => 0xf0, + PrintConv => { + 0 => '1/320 s (auto FP)', + 1 => '1/250 s (auto FP)', + 2 => '1/250 s', + 3 => '1/200 s', + 4 => '1/160 s', + 5 => '1/125 s', + 6 => '1/100 s', + 7 => '1/80 s', + 8 => '1/60 s', + }, + }, + 15.2 => { # CSe2 + Name => 'FlashShutterSpeed', + Mask => 0x0f, + PrintConvColumns => 2, + PrintConv => { + 0 => '1/60 s', + 1 => '1/30 s', + 2 => '1/15 s', + 3 => '1/8 s', + 4 => '1/4 s', + 5 => '1/2 s', + 6 => '1 s', + 7 => '2 s', + 8 => '4 s', + 9 => '8 s', + 10 => '15 s', + 11 => '30 s', + }, + }, + 16.1 => { # CSe3 + Name => 'FlashControlBuilt-in', + # Note If set the Manual, Repeating Flash, Commander Mode + # does not decode the detail settings. + Mask => 0xc0, + RawConv => '$$self{FlashControlBuiltin} = $val', + PrintConv => { + 0 => 'TTL', + 1 => 'Manual', + 2 => 'Repeating Flash', + 3 => 'Commander Mode', + }, + }, + 16.2 => { # CSe3-b + Name => 'ManualFlashOutput', + Condition => '$$self{FlashControlBuiltin} == 1', + Mask => 0x1f, + ValueConv => '2 ** (-$val/3)', + ValueConvInv => '$val > 0 ? -3*log($val)/log(2) : 0', + PrintConv => q{ + return 'Full' if $val > 0.99; + Image::ExifTool::Exif::PrintExposureTime($val); + }, + PrintConvInv => '$val=~/F/i ? 1 : Image::ExifTool::Exif::ConvertFraction($val)', + }, + 17.1 => { # CSe3-ca + Name => 'RepeatingFlashOutput', + Condition => '$$self{FlashControlBuiltin} == 2', + Mask => 0x70, + ValueConv => '2 ** (-$val-2)', + ValueConvInv => '$val > 0 ? int(-log($val)/log(2)-2+0.5) : 0', + PrintConv => 'Image::ExifTool::Exif::PrintExposureTime($val)', + PrintConvInv => 'Image::ExifTool::Exif::ConvertFraction($val)', + }, + 17.2 => { # CSe3-cb + Name => 'RepeatingFlashCount', + Condition => '$$self{FlashControlBuiltin} == 2', + Mask => 0x0f, + ValueConv => '$val < 10 ? $val + 1 : 5 * ($val - 7)', + ValueConvInv => '$val <= 10 ? $val - 1 : $val / 5 + 7', + }, + 18.1 => { # CSe3-cc (NC) + Name => 'RepeatingFlashRate', + Condition => '$$self{FlashControlBuiltin} == 2', + Mask => 0xf0, + ValueConv => '$val < 10 ? $val + 1 : 10 * ($val - 8)', + ValueConvInv => 'int(($val <= 10 ? $val - 1 : $val / 10 + 8) + 0.5)', + PrintConv => '"$val Hz"', + PrintConvInv => '$val=~/(\d+)/; $1 || 0', + }, + 18.2 => { # CSe3-dd + Name => 'CommanderInternalTTLChannel', + Condition => '$$self{FlashControlBuiltin} == 3', + Mask => 0x03, + PrintConv => { + 0 => '1 ch', + 1 => '2 ch', + 2 => '3 ch', + 3 => '4 ch', + }, + }, + 20.1 => { # CSe3-da + Name => 'CommanderInternalTTLCompBuiltin', + Condition => '$$self{FlashControlBuiltin} == 3', + Mask => 0x1f, + ValueConv => '($val - 9) / 3', + ValueConvInv => '$val * 3 + 9', + PrintConv => '$val ? sprintf("%+.1f",$val) : 0', + PrintConvInv => '$val', + }, + 21.1 => { # CSe3-db + Name => 'CommanderInternalTTLCompGroupA', + Condition => '$$self{FlashControlBuiltin} == 3', + Mask => 0x1f, + ValueConv => '($val - 9) / 3', + ValueConvInv => '$val * 3 + 9', + PrintConv => '$val ? sprintf("%+.1f",$val) : 0', + PrintConvInv => '$val', + }, + 22.1 => { # CSe3-dc + Name => 'CommanderInternalTTLCompGroupB', + Condition => '$$self{FlashControlBuiltin} == 3', + Mask => 0x1f, + ValueConv => '($val - 9) / 3', + ValueConvInv => '$val * 3 + 9', + PrintConv => '$val ? sprintf("%+.1f",$val) : 0', + PrintConvInv => '$val', + }, + 26.1 => { # CSe5 + Name => 'AutoBracketSet', + Mask => 0xc0, + PrintConv => { + 0 => 'AE & Flash', + 1 => 'AE Only', + 2 => 'Flash Only', + 3 => 'WB Bracketing', + }, + }, + 26.2 => { # CSe6 + Name => 'AutoBracketModeM', + Mask => 0x30, + PrintConv => { + 0 => 'Flash/Speed', + 1 => 'Flash/Speed/Aperture', + 2 => 'Flash/Aperture', + 3 => 'Flash Only', + }, + }, + 26.3 => { # CSe7 + Name => 'AutoBracketOrder', + Mask => 0x08, + PrintConv => { + 0 => '0,-,+', + 1 => '-,0,+', + }, + }, + 26.4 => { # CSe4 + Name => 'ModelingFlash', + Mask => 0x01, + PrintConv => \%onOff, + }, + 27.1 => { # CSf2-a + Name => 'MultiSelectorShootMode', + Mask => 0xc0, + PrintConv => { + 0 => 'Select Center Focus Point', + 1 => 'Highlight Active Focus Point', + 2 => 'Not Used', + }, + }, + 27.2 => { # CSf2-b + Name => 'MultiSelectorPlaybackMode', + Mask => 0x30, + PrintConv => { + 0 => 'Thumbnail On/Off', + 1 => 'View Histograms', + 2 => 'Zoom On/Off', + 3 => 'Choose Folder', + }, + }, + 27.3 => { # CSf2-b2 + Name => 'InitialZoomSetting', + Mask => 0x0c, + PrintConv => { #1 + 0 => 'Low Magnification', + 1 => 'Medium Magnification', + 2 => 'High Magnification', + }, + }, + 27.4 => { # CSf3 + Name => 'MultiSelector', + Mask => 0x01, + PrintConv => { + 0 => 'Do Nothing', + 1 => 'Reset Meter-off Delay', + }, + }, + 28.1 => { # CSf5-a + Name => 'FuncButton', + Mask => 0xf8, + PrintConv => { + 0 => 'None', + 1 => 'Preview', + 2 => 'FV Lock', + 3 => 'AE/AF Lock', + 4 => 'AE Lock Only', + 5 => 'AE Lock (reset on release)', + 6 => 'AE Lock (hold)', + 7 => 'AF Lock Only', + # 8 not used + 9 => 'Flash Off', + 10 => 'Bracketing Burst', + 11 => 'Matrix Metering', + 12 => 'Center-weighted Metering', + 13 => 'Spot Metering', + 14 => 'My Menu Top', + 15 => 'Live View', + 16 => '+ NEF (RAW)', + 17 => 'Virtual Horizon', + }, + }, + 29.1 => { # CSf6-a + Name => 'PreviewButton', + Mask => 0xf8, + PrintConv => { + 0 => 'None', + 1 => 'Preview', + 2 => 'FV Lock', + 3 => 'AE/AF Lock', + 4 => 'AE Lock Only', + 5 => 'AE Lock (reset on release)', + 6 => 'AE Lock (hold)', + 7 => 'AF Lock Only', + 8 => 'AF-ON', + 9 => 'Flash Off', + 10 => 'Bracketing Burst', + 11 => 'Matrix Metering', + 12 => 'Center-weighted Metering', + 13 => 'Spot Metering', + 14 => 'My Menu Top', + 15 => 'Live View', + 16 => '+ NEF (RAW)', + 17 => 'Virtual Horizon', + }, + }, + 30.1 => { # CSf7-a + Name => 'AELockButton', + Notes => 'D300', + Mask => 0xf8, + PrintConv => { + 0 => 'None', + 1 => 'Preview', + 2 => 'FV Lock', + 3 => 'AE/AF Lock', + 4 => 'AE Lock Only', + 5 => 'AE Lock (reset on release)', + 6 => 'AE Lock (hold)', + 7 => 'AF Lock Only', + 8 => 'AF-ON', + 9 => 'Flash Off', + 10 => 'Bracketing Burst', + 11 => 'Matrix Metering', + 12 => 'Center-weighted Metering', + 13 => 'Spot Metering', + 14 => 'My Menu Top', + 15 => 'Live View', + 16 => '+ NEF (RAW)', + 17 => 'Virtual Horizon', + }, + }, + 31.1 => { # CSf5-b + Name => 'FuncButtonPlusDials', + Mask => 0x70, + PrintConv => { + 0 => 'None', + 1 => 'Choose Image Area', + 2 => 'One Step Speed/Aperture', + 3 => 'Choose Non-CPU Lens Number', + # n/a 4 => 'Focus Point Selection', + 5 => 'Auto bracketing', + 6 => 'Dynamic AF Area', + 7 => 'Shutter speed & Aperture lock', + }, + }, + 31.2 => { # CSf6-b + Name => 'PreviewButtonPlusDials', + Mask => 0x07, + PrintConv => { + 0 => 'None', + 1 => 'Choose Image Area', + 2 => 'One Step Speed/Aperture', + 3 => 'Choose Non-CPU Lens Number', + # n/a 4 => 'Focus Point Selection', + 5 => 'Auto bracketing', + 6 => 'Dynamic AF Area', + 7 => 'Shutter speed & Aperture lock', + }, + }, + 32.1 => { # CSf7-b + Name => 'AELockButtonPlusDials', + Mask => 0x70, + Prinonv => { + 0 => 'None', + 1 => 'Choose Image Area', + 2 => 'One Step Speed/Aperture', + 3 => 'Choose Non-CPU Lens Number', + # n/a 4 => 'Focus Point Selection', + 5 => 'Auto bracketing', + 6 => 'Dynamic AF Area', + 7 => 'Shutter speed & Aperture lock', + }, + }, + 33.1 => { # CSf9-a + Name => 'CommandDialsReverseRotation', + Mask => 0x80, + PrintConv => \%noYes, + }, + 33.2 => { # CSf9-b + Name => 'CommandDialsChangeMainSub', + Mask => 0x40, + PrintConv => \%offOn, + }, + 33.3 => { # CSf9-c + Name => 'CommandDialsApertureSetting', + Mask => 0x20, + PrintConv => { + 0 => 'Sub-command Dial', + 1 => 'Aperture Ring', + }, + }, + 33.4 => { # CSf9-d + Name => 'CommandDialsMenuAndPlayback', + Mask => 0x10, + PrintConv => \%offOn, + }, + 33.5 => { # CSf12 + Name => 'ReverseIndicators', + Mask => 0x08, + PrintConv => { + 0 => '+ 0 -', + 1 => '- 0 +', + }, + }, + 33.6 => { # CSf4 + Name => 'PhotoInfoPlayback', + Mask => 0x04, + PrintConv => \%offOn, + }, + 33.7 => { # CSf11 + Name => 'NoMemoryCard', + Mask => 0x02, + PrintConv => { + 0 => 'Release Locked', + 1 => 'Enable Release', + }, + }, + 33.8 => { # CSf10 + Name => 'ReleaseButtonToUseDial', + Mask => 0x01, + PrintConv => \%noYes, + }, +); + +# D800 custom settings (ref PH) +%Image::ExifTool::NikonCustom::SettingsD800 = ( + PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData, + WRITE_PROC => \&Image::ExifTool::WriteBinaryData, + CHECK_PROC => \&Image::ExifTool::CheckBinaryData, + WRITABLE => 1, + FIRST_ENTRY => 0, + DATAMEMBER => [ 23.1 ], + GROUPS => { 0 => 'MakerNotes', 2 => 'Camera' }, + NOTES => 'Custom settings for the D800 and D800E.', + 12.1 => { # CSe5 + Name => 'AutoBracketingSet', + Mask => 0xe0, #(NC) + PrintConv => { + 0 => 'AE & Flash', # default + 1 => 'AE Only', #(NC) + 2 => 'Flash Only', + 3 => 'WB Bracketing', #(NC) + 4 => 'Active D-Lighting', #(NC) + }, + }, + 12.2 => { # CSe7 + Name => 'AutoBracketOrder', + Mask => 0x10, + PrintConv => { + 0 => '0,-,+', + 1 => '-,0,+', + }, + }, + 12.3 => { # CSe6 + Name => 'AutoBracketingMode', + Mask => 0x0c, + PrintConv => { + 0 => 'Flash/Speed', + 1 => 'Flash/Speed/Aperture', + 2 => 'Flash/Aperture', + 3 => 'Flash Only', + }, + }, + # 21 - 100 (MaxContinuousRelease?) + 22.1 => { # CSe1 + Name => 'FlashSyncSpeed', + Mask => 0xf0, + PrintConv => { + 0 => '1/320 s (auto FP)', + 1 => '1/250 s (auto FP)', + 2 => '1/250 s', + 3 => '1/200 s', + 4 => '1/160 s', + 5 => '1/125 s', + 6 => '1/100 s', + 7 => '1/80 s', + 8 => '1/60 s', + }, + }, + 22.2 => { # CSe2 + Name => 'FlashShutterSpeed', + Mask => 0x0f, + PrintConvColumns => 2, + PrintConv => { + 0 => '1/60 s', + 1 => '1/30 s', + 2 => '1/15 s', + 3 => '1/8 s', + 4 => '1/4 s', + 5 => '1/2 s', + 6 => '1 s', + 7 => '2 s', + 8 => '4 s', + 9 => '8 s', + 10 => '15 s', + 11 => '30 s', + }, + }, + 23.1 => { # CSe3 + Name => 'FlashControlBuilt-in', + Mask => 0xc0, + RawConv => '$$self{FlashControlBuiltin} = $val', + PrintConv => { + 0 => 'TTL', + 1 => 'Manual', + 2 => 'Repeating Flash', + 3 => 'Commander Mode', + }, + }, + 23.2 => { # CSe3-b + Name => 'ManualFlashOutput', + Condition => '$$self{FlashControlBuiltin} == 1', + Mask => 0x1f, + ValueConv => '2 ** (-$val/3)', + ValueConvInv => '$val > 0 ? -3*log($val)/log(2) : 0', + PrintConv => q{ + return 'Full' if $val > 0.99; + Image::ExifTool::Exif::PrintExposureTime($val); + }, + PrintConvInv => '$val=~/F/i ? 1 : Image::ExifTool::Exif::ConvertFraction($val)', + }, + 24.1 => { # CSe3-ca + Name => 'RepeatingFlashOutput', + Condition => '$$self{FlashControlBuiltin} == 2', + Mask => 0x70, + ValueConv => '2 ** (-$val-2)', + ValueConvInv => '$val > 0 ? int(-log($val)/log(2)-2+0.5) : 0', + PrintConv => 'Image::ExifTool::Exif::PrintExposureTime($val)', + PrintConvInv => 'Image::ExifTool::Exif::ConvertFraction($val)', + }, + 24.2 => { # CSe3-cb + Name => 'RepeatingFlashCount', + Condition => '$$self{FlashControlBuiltin} == 2', + Mask => 0x0f, + ValueConv => '$val < 10 ? $val + 1 : 5 * ($val - 7)', + ValueConvInv => '$val <= 10 ? $val - 1 : $val / 5 + 7', + }, + 25.1 => { # CSe3-cc + Name => 'RepeatingFlashRate', + Condition => '$$self{FlashControlBuiltin} == 2', + Mask => 0xf0, + ValueConv => '$val < 10 ? $val + 1 : 10 * ($val - 8)', + ValueConvInv => 'int(($val <= 10 ? $val - 1 : $val / 10 + 8) + 0.5)', + PrintConv => '"$val Hz"', + PrintConvInv => '$val=~/(\d+)/; $1 || 0', + }, + 25.2 => { # CSe3 + Name => 'CommanderChannel', + Mask => 0x03, + ValueConv => '$val + 1', + ValueConvInv => '$val - 1', + }, + 27.1 => { # CSe3 + Name => 'CommanderInternalFlash', + Mask => 0xc0, + PrintConv => { + 0 => 'TTL', + 1 => 'Manual', + 2 => 'Off', + }, + }, + 27.2 => { # CSe3 + Name => 'CommanderInternalManualOutput', + Mask => 0x1f, + ValueConv => '2 ** (-$val/3)', + ValueConvInv => '$val > 0 ? int(-log($val)/log(2) * 3 + 0.5): 0', + PrintConv => q{ + return 'Full' if $val > 0.99; + Image::ExifTool::Exif::PrintExposureTime($val); + }, + PrintConvInv => '$val=~/F/i ? 1 : Image::ExifTool::Exif::ConvertFraction($val)', + }, + 28.1 => { # CSe3 + Name => 'CommanderGroupAMode', + Mask => 0xc0, + PrintConv => { + 0 => 'TTL', + 1 => 'Auto Aperture', + 2 => 'Manual', + 3 => 'Off', + }, + }, + 28.2 => { # CSe3 + Name => 'CommanderGroupAManualOutput', + Mask => 0x1f, + ValueConv => '2 ** (-$val/3)', + ValueConvInv => '$val > 0 ? int(-log($val)/log(2) * 3 + 0.5): 0', + PrintConv => q{ + return 'Full' if $val > 0.99; + Image::ExifTool::Exif::PrintExposureTime($val); + }, + PrintConvInv => '$val=~/F/i ? 1 : Image::ExifTool::Exif::ConvertFraction($val)', + }, + 29.1 => { # CSe3 + Name => 'CommanderGroupBMode', + Mask => 0xc0, + PrintConv => { + 0 => 'TTL', + 1 => 'Auto Aperture', + 2 => 'Manual', + 3 => 'Off', + }, + }, + 29.2 => { # CSe3 + Name => 'CommanderGroupBManualOutput', + Mask => 0x1f, + ValueConv => '2 ** (-$val/3)', + ValueConvInv => '$val > 0 ? int(-log($val)/log(2) * 3 + 0.5): 0', + PrintConv => q{ + return 'Full' if $val > 0.99; + Image::ExifTool::Exif::PrintExposureTime($val); + }, + PrintConvInv => '$val=~/F/i ? 1 : Image::ExifTool::Exif::ConvertFraction($val)', + }, + 30.1 => { # CSe4 + Name => 'ModelingFlash', + Mask => 0x20, + PrintConv => \%onOff, + }, + 30.2 => { # CSe3 + Name => 'CommanderInternalTTLComp', + Mask => 0x1f, + ValueConv => '($val - 9) / 3', + ValueConvInv => '$val * 3 + 9', + PrintConv => '$val ? sprintf("%+.1f",$val) : 0', + PrintConvInv => '$val', + }, + 31.1 => { # CSe3 + Name => 'CommanderGroupA_TTL-AAComp', + Mask => 0x1f, + ValueConv => '($val - 9) / 3', + ValueConvInv => '$val * 3 + 9', + PrintConv => '$val ? sprintf("%+.1f",$val) : 0', + PrintConvInv => '$val', + }, + 32.1 => { # CSe3 + Name => 'CommanderGroupB_TTL-AAComp', + Mask => 0x1f, + ValueConv => '($val - 9) / 3', + ValueConvInv => '$val * 3 + 9', + PrintConv => '$val ? sprintf("%+.1f",$val) : 0', + PrintConvInv => '$val', + }, + # 47 - related to flash +); + +# D5 custom settings (ref 1) +%Image::ExifTool::NikonCustom::SettingsD5 = ( + PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData, + WRITE_PROC => \&Image::ExifTool::WriteBinaryData, + CHECK_PROC => \&Image::ExifTool::CheckBinaryData, + WRITABLE => 1, + FIRST_ENTRY => 0, + GROUPS => { 0 => 'MakerNotes', 2 => 'Camera' }, + NOTES => 'Custom settings for the D5.', + 0.1 => { + Name => 'CustomSettingsBank', + Mask => 0x03, + PrintConv => { + 0 => 'A', + 1 => 'B', + 2 => 'C', + 3 => 'D', + }, + }, + 1.1 => { #CSa1 + Name => 'AF-CPrioritySelection', + Mask => 0xc0, + PrintConv => { + 0 => 'Release', + 1 => 'Release + Focus', + 2 => 'Focus', + 3 => 'Focus + Release', + }, + }, + 1.2 => { # CSa6 + Name => 'NumberOfFocusPoints', + Mask => 0x10, + PrintConv => { + 0 => '55 Points', + 1 => '15 Points', + }, + }, + 1.3 => { # CSa4 + Name => 'Three-DTrackingFaceDetection', + Mask => 0x08, + PrintConv => { + 0 => 'Off', + 1 => 'On', + }, + }, + 1.4 => { # CSa2 + Name => 'AF-SPrioritySelection', + Mask => 0x20, + PrintConv => { + 0 => 'Focus', + 1 => 'Release', + }, + }, + 1.5 => { # CSa3-a + Name => 'BlockShotAFResponse', + Mask => 0x07, + #values 1-5 + }, + 2.1 => { # CSa11 + Name => 'FocusPointWrap', + Mask => 0x08, + PrintConv => { + 0 => 'No Wrap', + 1 => 'Wrap', + }, + }, + 2.2 => { # CSa12-d + Name => 'AFPointBrightness', + Mask => 0x06, + PrintConv => { + 0 => 'Auto', + 1 => 'On', + 2 => 'Off', + }, + }, + 4.1 => { # CSd3 + Name => 'ISODisplay', + Mask => 0x08, + PrintConv => { + 0 => 'Show ISO Sensitivity', + 1 => 'Show Frame Count', + }, + }, + 4.2 => { # CSd8 + Name => 'GridDisplay', + Mask => 0x02, + PrintConv => \%onOff, + }, + 5.1 => { # CSd9 + Name => 'LCDIllumination', + Mask => 0x20, + PrintConv => \%offOn, + }, + 5.2 => { # CSd6 + Name => 'ElectronicFront-CurtainShutter', + Mask => 0x08, + PrintConv => \%offOn, + }, + 6.1 => { # CSf7 + Name => 'ReverseIndicators', + Mask => 0x80, + PrintConv => { + 0 => '+ 0 -', + 1 => '- 0 +', + }, + }, + 6.2 => { # CSf4-a + Name => 'CommandDialsReverseRotation', + Mask => 0x18, + PrintConv => { + 0 => 'No', + 1 => 'Shutter Speed & Aperture', + 2 => 'Exposure Compensation', + 3 => 'Exposure Compensation, Shutter Speed & Aperture', + }, + }, + 6.3 => { # CSb4 + Name => 'EasyExposureCompensation', + Mask => 0x03, + PrintConv => { + 0 => 'Off', + 1 => 'On', + 2 => 'On (auto reset)', + }, + }, + 7.1 => { # CSb2 + Name => 'ExposureControlStepSize', + Mask => 0xc0, + PrintConv => { + 0 => '1/3 EV', + 1 => '1/2 EV', + 2 => '1 EV', + }, + }, + 7.2 => { # CSb1 + Name => 'ISOStepSize', + Mask => 0x30, + PrintConv => { + 0 => '1/3 EV', + 1 => '1/2 EV', + 2 => '1 EV', + }, + }, + 7.3 => { # CSb3 + Name => 'ExposureCompStepSize', + Mask => 0x0c, + PrintConv => { + 0 => '1/3 EV', + 1 => '1/2 EV', + 2 => '1 EV', + }, + }, + 8.1 => { # CSb6 + Name => 'CenterWeightedAreaSize', + Mask => 0xe0, + PrintConv => { + 0 => '8 mm', + 1 => '12 mm', + 2 => '15 mm', + 3 => '20 mm', + 4 => 'Average', + }, + }, + 8.2 => { # CSb7-a + Name => 'FineTuneOptMatrixMetering', + Mask => 0x0f, + ValueConv => '($val > 0x7 ? $val - 0x10 : $val) / 6', + ValueConvInv => 'int($val*6+($val>0?0.5:-0.5))', + PrintConv => '$val ? sprintf("%+.2f", $val) : 0', + PrintConvInv => 'Image::ExifTool::Exif::ConvertFraction($val)', + }, + 9.1 => { # CSb7-b + Name => 'FineTuneOptCenterWeighted', + Mask => 0xf0, + ValueConv => '($val > 0x7 ? $val - 0x10 : $val) / 6', + ValueConvInv => 'int($val*6+($val>0?0.5:-0.5))', + PrintConv => '$val ? sprintf("%+.2f", $val) : 0', + PrintConvInv => 'Image::ExifTool::Exif::ConvertFraction($val)', + }, + 9.2 => { # CSb7-c + Name => 'FineTuneOptSpotMetering', + Mask => 0x0f, + ValueConv => '($val > 0x7 ? $val - 0x10 : $val) / 6', + ValueConvInv => 'int($val*6+($val>0?0.5:-0.5))', + PrintConv => '$val ? sprintf("%+.2f", $val) : 0', + PrintConvInv => 'Image::ExifTool::Exif::ConvertFraction($val)', + }, + 10.1 => { # CSf2-a + Name => 'MultiSelectorShootMode', + Mask => 0xe0, + PrintConv => { + 0 => 'Select Center Focus Point (Reset)', + 1 => 'Zoom On/Off', # this is the documented (and actual) default value, but the choice does not appear on the camera menu + 2 => 'Preset Focus Point (Pre)', + 4 => 'Not Used (None)', + }, + }, +# 10.2 => { # CSf2-b # moved from the D500 position to Nikon_ShotInfoD5_0x0ab1 with the Mask and PrintConv as specified below. Further research required. +# Name => 'MultiSelectorPlaybackMode', +# Mask => 0x70, +# PrintConv => { +# 0 => 'Zoom On/Off', +# 1 => 'Choose Folder', +# 6 => 'Thumbnail On/Off', +# 7 => 'View Histograms', +# }, +# }, + 10.3 => { # CSf5 + Name => 'MultiSelector', + Mask => 0x01, + PrintConv => { + 0 => 'Do Nothing', + 1 => 'Reset Meter-off Delay', + }, + }, + 11.1 => { # CSd5 + Name => 'ExposureDelayMode', + Mask => 0xc0, + PrintConv => { + 0 => 'Off', + 1 => '1 s', + 2 => '2 s', + 3 => '3 s', + }, + }, + 11.2 => { # CSd1 + Name => 'CLModeShootingSpeed', + Mask => 0x0f, + PrintConv => '"$val fps"', + PrintConvInv => '$val=~s/\s*fps//i; $val', + }, + 12.1 => { # CSd2 + Name => 'MaxContinuousRelease', + # values: 1-100 + }, + 13.1 => { # CSe7 + Name => 'AutoBracketOrder', + Mask => 0x10, + PrintConv => { + 0 => '0,-,+', + 1 => '-,0,+', + }, + }, + 13.2 => { # CSe6 + Name => 'AutoBracketModeM', + Mask => 0x0c, + PrintConv => { + 0 => 'Flash/Speed', + 1 => 'Flash/Speed/Aperture', + 2 => 'Flash/Aperture', + 3 => 'Flash Only', + }, + }, + 14.1 => { # CSf1-c + Name => 'Func1Button', + Mask => 0x3f, + PrintConv => { + 0 => 'None', + 1 => 'Preview', + 2 => 'FV Lock', + 3 => 'AE/AF Lock', + 4 => 'AE Lock Only', + 5 => 'AE Lock (reset on release)', + 6 => 'AE Lock (hold)', + 7 => 'AF Lock Only', + 8 => 'AF-On', + 10 => 'Bracketing Burst', + 11 => 'Matrix Metering', + 12 => 'Center-weighted Metering', + 13 => 'Spot Metering', + 14 => 'Playback', + 15 => 'My Menu Top Item', + 16 => '+NEF(RAW)', + 17 => 'Virtual Horizon', + 19 => 'Grid Display', + 20 => 'My Menu', + 21 => 'Disable Synchronized Release', + 22 => 'Remote Release Only', + 26 => 'Flash Disable/Enable', + 27 => 'Highlight-weighted Metering', + 36 => 'AF-Area Mode (Single)', + 37 => 'AF-Area Mode (Dynamic Area 25 Points)', + 38 => 'AF-Area Mode (Dynamic Area 72 Points)', + 39 => 'AF-Area Mode (Dynamic Area 152 Points)', + 40 => 'AF-Area Mode (Group Area AF)', + 41 => 'AF-Area Mode (Auto Area AF)', + 42 => 'AF-Area Mode + AF-On (Single)', + 43 => 'AF-Area Mode + AF-On (Dynamic Area 25 Points)', + 44 => 'AF-Area Mode + AF-On (Dynamic Area 72 Points)', + 45 => 'AF-Area Mode + AF-On (Dynamic Area 152 Points)', + 46 => 'AF-Area Mode + AF-On (Group Area AF)', + 47 => 'AF-Area Mode + AF-On (Auto Area AF)', + 49 => 'Sync Release (Master Only)', + 50 => 'Sync Release (Remote Only)', + }, + }, + 15.1 => { # CSf1-a + Name => 'PreviewButton', + Mask => 0x3f, + PrintConv => { + 0 => 'None', + 1 => 'Preview', + 2 => 'FV Lock', + 3 => 'AE/AF Lock', + 4 => 'AE Lock Only', + 5 => 'AE Lock (reset on release)', + 6 => 'AE Lock (hold)', + 7 => 'AF Lock Only', + 8 => 'AF-On', + 10 => 'Bracketing Burst', + 11 => 'Matrix Metering', + 12 => 'Center-weighted Metering', + 13 => 'Spot Metering', + 14 => 'Playback', + 15 => 'My Menu Top Item', + 16 => '+NEF(RAW)', + 17 => 'Virtual Horizon', + 19 => 'Grid Display', + 20 => 'My Menu', + 21 => 'Disable Synchronized Release', + 22 => 'Remote Release Only', + 26 => 'Flash Disable/Enable', + 27 => 'Highlight-weighted Metering', + 36 => 'AF-Area Mode (Single)', + 37 => 'AF-Area Mode (Dynamic Area 25 Points)', + 38 => 'AF-Area Mode (Dynamic Area 72 Points)', + 39 => 'AF-Area Mode (Dynamic Area 152 Points)', + 40 => 'AF-Area Mode (Group Area AF)', + 41 => 'AF-Area Mode (Auto Area AF)', + 42 => 'AF-Area Mode + AF-On (Single)', + 43 => 'AF-Area Mode + AF-On (Dynamic Area 25 Points)', + 44 => 'AF-Area Mode + AF-On (Dynamic Area 72 Points)', + 45 => 'AF-Area Mode + AF-On (Dynamic Area 152 Points)', + 46 => 'AF-Area Mode + AF-On (Group Area AF)', + 47 => 'AF-Area Mode + AF-On (Auto Area AF)', + 49 => 'Sync Release (Master Only)', + 50 => 'Sync Release (Remote Only)', + }, + }, + 16.1 => { # CSf1-p + Name => 'AssignBktButton', + Mask => 0x07, + PrintConv => { + 0 => 'Auto Bracketing', + 1 => 'Multiple Exposure', + 2 => 'HDR (high dynamic range)', + 3 => 'None', + }, + }, + 18.1 => { # CSf4-b + Name => 'CommandDialsChangeMainSub', + Mask => 0xe0, + PrintConv => { + 0 => 'Autofocus Off, Exposure Off', + 1 => 'Autofocus Off, Exposure On', + 2 => 'Autofocus Off, Exposure On (Mode A)', + 4 => 'Autofocus On, Exposure Off', + 5 => 'Autofocus On, Exposure On', + 6 => 'Autofocus On, Exposure On (Mode A)', + }, + }, + 18.2 => { # CSf4-d + Name => 'CommandDialsMenuAndPlayback', + Mask => 0x18, + PrintConv => { + 0 => 'On', + 1 => 'Off', + 2 => 'On (Image Review Excluded)', + }, + }, + 18.3 => { # CSf4-c + Name => 'CommandDialsApertureSetting', + Mask => 0x04, + PrintConv => { + 0 => 'Sub-command Dial', + 1 => 'Aperture Ring', + }, + }, + 18.4 => { # CSf6 + Name => 'ReleaseButtonToUseDial', + Mask => 0x01, + PrintConv => \%noYes, + }, + 19.1 => { # CSc2 + Name => 'StandbyTimer', + Mask => 0xf0, + PrintConv => { + 0 => '4 s', + 1 => '6 s', + 3 => '10 s', + 5 => '30 s', + 6 => '1 min', + 7 => '5 min', + 8 => '10 min', + 9 => '30 min', + 10 => 'No Limit', + }, + }, + 20.1 => { # CSc3-a + Name => 'SelfTimerTime', + Mask => 0xc0, + PrintConv => { + 0 => '2 s', + 1 => '5 s', + 2 => '10 s', + 3 => '20 s', + }, + }, + 20.2 => { # CSc3-c + Name => 'SelfTimerShotInterval', + Mask => 0x30, + PrintConv => { + 0 => '0.5 s', + 1 => '1 s', + 2 => '2 s', + 3 => '3 s', + }, + }, + 20.3 => { # CSc3-b + Name => 'SelfTimerShotCount', + Mask => 0x0f, + }, + 21.1 => { # CSc4-d + Name => 'ImageReviewMonitorOffTime', + Mask => 0xe0, + PrintConv => { + 0 => '2 s', + 1 => '4 s', + 3 => '10 s', + 4 => '20 s', + 5 => '1 min', + 6 => '5 min', + 7 => '10 min', + }, + }, + 21.2 => { # CSc4-e + Name => 'LiveViewMonitorOffTime', + Mask => 0x1c, + PrintConv => { + 1 => '5 min', + 2 => '10 min', + 3 => '15 min', + 4 => '20 min', + 5 => '30 min', + 6 => 'No Limit', + }, + }, + 22.1 => { # CSc4-b + Name => 'MenuMonitorOffTime', + Mask => 0xe0, + PrintConv => { + 0 => '4 s', + 2 => '10 s', + 4 => '20 s', + 5 => '1 min', + 6 => '5 min', + 7 => '10 min', + }, + }, + 22.2 => { # CSc4-c + Name => 'ShootingInfoMonitorOffTime', + Mask => 0x1c, + PrintConv => { + 0 => '4 s', + 2 => '10 s', + 4 => '20 s', + 5 => '1 min', + 6 => '5 min', + 7 => '10 min', + }, + }, + 23.1 => { # CSe1 + Name => 'FlashSyncSpeed', + Mask => 0xf0, + PrintConv => { + 2 => '1/250 s (auto FP)', + 3 => '1/250 s', + 5 => '1/200 s', + 6 => '1/160 s', + 7 => '1/125 s', + 8 => '1/100 s', + 9 => '1/80 s', + 10 => '1/60 s', + }, + }, + 23.2 => { # CSe2 + Name => 'FlashShutterSpeed', + Mask => 0x0f, + PrintConvColumns => 2, + PrintConv => { + 0 => '1/60 s', + 1 => '1/30 s', + 2 => '1/15 s', + 3 => '1/8 s', + 4 => '1/4 s', + 5 => '1/2 s', + 6 => '1 s', + 7 => '2 s', + 8 => '4 s', + 9 => '8 s', + 10 => '15 s', + 11 => '30 s', + }, + }, + 31.1 => { # CSe5 + Name => 'ModelingFlash', + Mask => 0x20, + PrintConv => \%onOff, + }, + 36.1 => { # CSc4-a + Name => 'PlaybackMonitorOffTime', + Mask => 0xe0, + PrintConv => { + 0 => '4 s', + 1 => '10 s', + 2 => '20 s', + 3 => '1 min', + 4 => '5 min', + 5 => '10 min', + }, + }, + 37.1 => { # CSf2-c + Name => 'MultiSelectorLiveView', + Mask => 0xc0, + PrintConv => { + 0 => 'Reset', + 1 => 'Zoom', + 3 => 'Not Used', + }, + }, + 38.1 => { # CSf3-a + Name => 'ShutterSpeedLock', + Mask => 0x80, + PrintConv => \%offOn, + }, + 38.2 => { # CSf3-b + Name => 'ApertureLock', + Mask => 0x40, + PrintConv => \%offOn, + }, + 38.3 => { # CSg1-h + Name => 'MovieShutterButton', + Mask => 0x10, + PrintConv => { + 0 => 'Take Photo', + 1 => 'Record Movies', + }, + }, + 38.4 => { # CSe3 + Name => 'FlashExposureCompArea', + Mask => 0x04, + PrintConv => { + 0 => 'Entire Frame', + 1 => 'Background Only', + }, + }, + 38.5 => { # CSe4 + Name => 'AutoFlashISOSensitivity', + Mask => 0x02, + PrintConv => { + 0 => 'Subject and Background', + 1 => 'Subject Only', + }, + }, + 41.1 => { # CSg1-c + Name => 'MovieFunc1Button', + Mask => 0xf0, + PrintConv => { + 0 => 'None', + 2 => 'Power Aperture (close)', + 3 => 'Index Marking', + 4 => 'View Photo Shooting Info', + 11 => 'Exposure Compensation -', + }, + }, + 41.2 => { # CSg1-a + Name => 'MoviePreviewButton', + Mask => 0x0f, + PrintConv => { + 0 => 'None', + 1 => 'Power Aperture (open)', + 3 => 'Index Marking', + 4 => 'View Photo Shooting Info', + 10 => 'Exposure Compensation +', + }, + }, + 42.1 => { # CSf1-d + Name => 'Func1ButtonPlusDials', + Mask => 0x0f, + PrintConv => { + 0 => 'None', + 1 => 'Choose Image Area', + 2 => 'Shutter Speed & Aperture Lock', + 3 => 'One Step Speed / Aperture', + 4 => 'Choose Non-CPU Lens Number', + 5 => 'Active D-Lighting', + 7 => 'Photo Shooting Menu Bank', + 8 => 'Exposure Delay Mode', + }, + }, + 43.1 => { # CSf1-b + Name => 'PreviewButtonPlusDials', + Mask => 0x0f, + PrintConv => { + 0 => 'None', + 1 => 'Choose Image Area', + 2 => 'Shutter Speed & Aperture Lock', + 3 => 'One Step Speed / Aperture', + 4 => 'Choose Non-CPU Lens Number', + 5 => 'Active D-Lighting', + 7 => 'Photo Shooting Menu Bank', # new with D500 + 8 => 'Exposure Delay Mode', + }, + }, + 45.1 => { # CSf1-q + Name => 'AssignMovieRecordButtonPlusDials', + Mask => 0x0f, + PrintConv => { + 0 => 'None', + 1 => 'Choose Image Area', + 2 => 'Shutter Speed & Aperture Lock', + 7 => 'Photo Shooting Menu Bank', + 11 => 'Exposure Mode', + }, + }, + 46.1 => { # CSb7-d + Name => 'FineTuneOptHighlightWeighted', + Mask => 0x0f, + ValueConv => '($val > 0x7 ? $val - 0x10 : $val) / 6', + ValueConvInv => 'int($val*6+($val>0?0.5:-0.5))', + PrintConv => '$val ? sprintf("%+.2f", $val) : 0', + PrintConvInv => 'Image::ExifTool::Exif::ConvertFraction($val)', + }, + 47.1 => { # CSa12-b + Name => 'DynamicAreaAFDisplay', + Mask => 0x80, + PrintConv => \%offOn, + }, + 47.2 => { # CSa12-a + Name => 'AFPointIllumination', + Mask => 0x40, + PrintConv => { + 0 => 'Off', + 1 => 'On During Manual Focusing', + }, + }, + 47.3 => { # CSa7 + Name => 'StoreByOrientation', + Mask => 0x18, + PrintConv => { + 0 => 'Off', + 1 => 'Focus Point', + 2 => 'Focus Point and AF-area Mode', + }, + }, + 48.1 => { # CSb5 + Name => 'MatrixMetering', + Mask => 0x80, + PrintConv => { + 0 => 'Face Detection On', + 1 => 'Face Detection Off', + }, + }, + 48.2 => { # CSf8 + Name => 'LiveViewButtonOptions', + Mask => 0x30, + PrintConv => { + 0 => 'Enable', + 1 => 'Enable (Standby Timer Active)', # new with D500 + 2 => 'Disable', + }, + }, + 48.3 => { # CSa10 + Name => 'AFModeRestrictions', + Mask => 0x03, + PrintConv => { + 0 => 'No Restrictions', + 1 => 'AF-C', + 2 => 'AF-S', + }, + }, + 49.1 => { # CSa9 + Name => 'LimitAFAreaModeSelection', + Mask => 0x7e, + PrintConv => { + 0 => 'No Restrictions', + BITMASK => { + 0 => 'Auto-area', + 1 => 'Group-area', + 2 => '3D-tracking', + 3 => 'Dynamic area (153 points)', + 4 => 'Dynamic area (72 points)', + 5 => 'Dynamic area (25 points)', + }, + }, + }, + 52.1 => { # CSf1-r + Name => 'LensFocusFunctionButtons', + Mask => 0x3f, + PrintConv => { + 3 => 'AE/AF Lock', + 4 => 'AE Lock Only', + 7 => 'AF Lock Only', + 8 => 'AF-On', + 24 => 'Preset Focus Point', + 26 => 'Flash Disable/Enable', + 36 => 'AF-Area Mode (Single)', + 37 => 'AF-Area Mode (Dynamic Area 25 Points)', + 38 => 'AF-Area Mode (Dynamic Area 72 Points)', + 39 => 'AF-Area Mode (Dynamic Area 152 Points)', + 40 => 'AF-Area Mode (Group Area AF)', + 41 => 'AF-Area Mode (Auto Area AF)', + 42 => 'AF-Area Mode + AF-On (Single)', + 43 => 'AF-Area Mode + AF-On (Dynamic Area 25 Points)', + 44 => 'AF-Area Mode + AF-On (Dynamic Area 72 Points)', + 45 => 'AF-Area Mode + AF-On (Dynamic Area 152 Points)', + 46 => 'AF-Area Mode + AF-On (Group Area AF)', + 47 => 'AF-Area Mode + AF-On (Auto Area AF)', + 49 => 'Sync Release (Master Only)', + 50 => 'Sync Release (Remote Only)', + }, + }, + 66.1 => { # CSf1-o + Name => 'VerticalMultiSelector', + Mask => 0xff, + PrintHex => 1, + PrintConv => { + 0x00 => 'Same as Multi-Selector with Info(U/D) & Playback(R/L)', + 0x08 => 'Same as Multi-Selector with Info(R/L) & Playback(U/D)', + 0x80 => 'Focus Point Selection', + }, + }, + 67.1 => { # CSf1-g + Name => 'VerticalFuncButton', + Mask => 0x3f, + PrintConv => { + 0 => 'None', + 1 => 'Preview', + 2 => 'FV Lock', + 3 => 'AE/AF Lock', + 4 => 'AE Lock Only', + 5 => 'AE Lock (reset on release)', + 6 => 'AE Lock (hold)', + 7 => 'AF Lock Only', + 8 => 'AF-On', + 10 => 'Bracketing Burst', + 11 => 'Matrix Metering', + 12 => 'Center-weighted Metering', + 13 => 'Spot Metering', + 14 => 'Playback', + 15 => 'My Menu Top Item', + 16 => '+NEF(RAW)', + 17 => 'Virtual Horizon', + 18 => 'Reset Focus Point', + 19 => 'Grid Display', + 20 => 'My Menu', + 22 => 'Remote Release Only', + 23 => 'Preset Focus Point', + 26 => 'Flash Disable/Enable', + 27 => 'Highlight-weighted Metering', + 36 => 'AF-Area Mode (Single)', + 37 => 'AF-Area Mode (Dynamic Area 25 Points)', + 38 => 'AF-Area Mode (Dynamic Area 72 Points)', + 39 => 'AF-Area Mode (Dynamic Area 152 Points)', + 40 => 'AF-Area Mode (Group Area AF)', + 41 => 'AF-Area Mode (Auto Area AF)', + 42 => 'AF-Area Mode + AF-On (Single)', + 43 => 'AF-Area Mode + AF-On (Dynamic Area 25 Points)', + 44 => 'AF-Area Mode + AF-On (Dynamic Area 72 Points)', + 45 => 'AF-Area Mode + AF-On (Dynamic Area 152 Points)', + 46 => 'AF-Area Mode + AF-On (Group Area AF)', + 47 => 'AF-Area Mode + AF-On (Auto Area AF)', + 49 => 'Sync Release (Master Only)', + 50 => 'Sync Release (Remote Only)', + 54 => 'Highlight Active Focus Point', + }, + }, + 68.1 => { # CSf1-h + Name => 'VerticalFuncPlusDials', + Mask => 0x0f, + PrintConv => { + 0 => 'None', + 1 => 'Choose Image Area', + 2 => 'Shutter Speed & Aperture Lock', + 3 => 'One Step Speed / Aperture', + 4 => 'Choose Non-CPU Lens Number', + 5 => 'Active D-Lighting', + 7 => 'Photo Shooting Menu Bank', + 8 => 'Exposure Delay Mode', + 10 => 'ISO Sensitivity', + 11 => 'Exposure Mode', + 12 => 'Exposure Compensation', + 13 => 'Metering', + }, + }, + 70.1 => { # CSf1-j + Name => 'AF-OnButton', + Mask => 0x3f, + PrintConv => { + 0 => 'None', + 3 => 'AE/AF Lock', + 4 => 'AE Lock Only', + 5 => 'AE Lock (reset on release)', + 6 => 'AE Lock (hold)', + 7 => 'AF Lock Only', + 8 => 'AF-On', + 36 => 'AF-Area Mode (Single)', + 37 => 'AF-Area Mode (Dynamic Area 25 Points)', + 38 => 'AF-Area Mode (Dynamic Area 72 Points)', + 39 => 'AF-Area Mode (Dynamic Area 152 Points)', + 40 => 'AF-Area Mode (Group Area AF)', + 41 => 'AF-Area Mode (Auto Area AF)', + 42 => 'AF-Area Mode + AF-On (Single)', + 43 => 'AF-Area Mode + AF-On (Dynamic Area 25 Points)', + 44 => 'AF-Area Mode + AF-On (Dynamic Area 72 Points)', + 45 => 'AF-Area Mode + AF-On (Dynamic Area 152 Points)', + 46 => 'AF-Area Mode + AF-On (Group Area AF)', + 47 => 'AF-Area Mode + AF-On (Auto Area AF)', + }, + }, + 71.1 => { # CSf1-k + Name => 'SubSelector', + Mask => 0x80, + PrintConv => { + 0 => 'Focus Point Selection', + 1 => 'Same as MultiSelector', + }, + }, + 72.1 => { # CSf1-l + Name => 'SubSelectorCenter', + Mask => 0x3f, + PrintConv => { + 0 => 'None', + 1 => 'Preview', + 2 => 'FV Lock', + 3 => 'AE/AF Lock', + 4 => 'AE Lock Only', + 5 => 'AE Lock (reset on release)', + 6 => 'AE Lock (hold)', + 7 => 'AF Lock Only', + 8 => 'AF-On', + 10 => 'Bracketing Burst', + 11 => 'Matrix Metering', + 12 => 'Center-weighted Metering', + 13 => 'Spot Metering', + 14 => 'Playback', + 15 => 'My Menu Top Item', + 16 => '+NEF(RAW)', + 17 => 'Virtual Horizon', + 18 => 'Reset Focus Point', + 19 => 'Grid Display', + 20 => 'My Menu', + 22 => 'Remote Release Only', + 23 => 'Preset Focus Point', + 26 => 'Flash Disable/Enable', + 27 => 'Highlight-weighted Metering', + 36 => 'AF-Area Mode (Single)', + 37 => 'AF-Area Mode (Dynamic Area 25 Points)', + 38 => 'AF-Area Mode (Dynamic Area 72 Points)', + 39 => 'AF-Area Mode (Dynamic Area 152 Points)', + 40 => 'AF-Area Mode (Group Area AF)', + 41 => 'AF-Area Mode (Auto Area AF)', + 42 => 'AF-Area Mode + AF-On (Single)', + 43 => 'AF-Area Mode + AF-On (Dynamic Area 25 Points)', + 44 => 'AF-Area Mode + AF-On (Dynamic Area 72 Points)', + 45 => 'AF-Area Mode + AF-On (Dynamic Area 152 Points)', + 46 => 'AF-Area Mode + AF-On (Group Area AF)', + 47 => 'AF-Area Mode + AF-On (Auto Area AF)', + 49 => 'Sync Release (Master Only)', + 50 => 'Sync Release (Remote Only)', + 54 => 'Highlight Active Focus Point', + }, + }, + 73.1 => { # CSf1-m + Name => 'SubSelectorPlusDials', + Mask => 0x0f, + PrintConv => { + 0 => 'None', + 1 => 'Choose Image Area', + 2 => 'Shutter Speed & Aperture Lock', + 4 => 'Choose Non-CPU Lens Number', + 7 => 'Photo Shooting Menu Bank', + }, + }, + 74.1 => { # CSg1-f + Name => 'AssignMovieSubselector', + Mask => 0xf0, + PrintConv => { + 0 => 'None', + 3 => 'Index Marking', + 4 => 'View Photo Shooting Info', + 5 => 'AE/AF Lock', + 6 => 'AE Lock (Only)', + 7 => 'AE Lock (Hold)', + 8 => 'AF Lock (Only)', + }, + }, + 75.1 => { # CSg1-d + Name => 'AssignMovieFunc1ButtonPlusDials', + Mask => 0x10, + PrintConv => { + 0 => 'None', + 1 => 'Choose Image Area', + }, + }, + 75.2 => { # CSg1-b + Name => 'AssignMoviePreviewButtonPlusDials', + Mask => 0x01, + PrintConv => { + 0 => 'None', + 1 => 'Choose Image Area (DX/1.3x)', + }, + }, + 76.1 => { # CSg1-g + Name => 'AssignMovieSubselectorPlusDials', + Mask => 0x10, + PrintConv => { + 0 => 'None', + 1 => 'Choose Image Area', + }, + }, + 77.1 => { # CSd4 + Name => 'SyncReleaseMode', # new with D500 + Mask => 0x80, + PrintConv => { + 0 => 'No Sync', + 1 => 'Sync', + }, + }, + 78.1 => { # CSa5 + Name => 'Three-DTrackingWatchArea', # new with D500 + Mask => 0x80, + PrintConv => { + 0 => 'Wide', + 1 => 'Normal', + }, + }, + 78.2 => { # CSa3-b + Name => 'SubjectMotion', + Mask => 0x60, + PrintConv => { + 0 => 'Steady', + 1 => 'Middle', + 2 => 'Erratic', + }, + }, + 78.3 => { # CSa8 + Name => 'AFActivation', + Mask => 0x08, + PrintConv => { + 0 => 'Shutter/AF-On', + 1 => 'AF-On Only', + }, + }, + 78.4 => { # CSc1 + Name => 'ShutterReleaseButtonAE-L', + Mask => 0x03, + PrintConv => { + 0 => 'Off', + 1 => 'On (Half Press)', + 2 => 'On (Burst Mode)' + }, + }, + 79.1 => { # CSf1-n + Name => 'VerticalAFOnButton', + Mask => 0x7f, + PrintConv => { + 0 => 'None', + 3 => 'AE/AF Lock', + 4 => 'AE Lock Only', + 5 => 'AE Lock (reset on release)', + 6 => 'AE Lock (hold)', + 7 => 'AF Lock Only', + 8 => 'AF-On', + 36 => 'AF-Area Mode (Single)', + 37 => 'AF-Area Mode (Dynamic Area 25 Points)', + 38 => 'AF-Area Mode (Dynamic Area 72 Points)', + 39 => 'AF-Area Mode (Dynamic Area 152 Points)', + 40 => 'AF-Area Mode (Group Area AF)', + 41 => 'AF-Area Mode (Auto Area AF)', + 42 => 'AF-Area Mode + AF-On (Single)', + 43 => 'AF-Area Mode + AF-On (Dynamic Area 25 Points)', + 44 => 'AF-Area Mode + AF-On (Dynamic Area 72 Points)', + 45 => 'AF-Area Mode + AF-On (Dynamic Area 152 Points)', + 46 => 'AF-Area Mode + AF-On (Group Area AF)', + 47 => 'AF-Area Mode + AF-On (Auto Area AF)', + 100 => 'Same as AF-On', + }, + }, + 80.1 => { # CSf1-e + Name => 'Func2Button', + Mask => 0x3f, + PrintConv => { + 0 => 'None', + 1 => 'Preview', + 2 => 'FV Lock', + 3 => 'AE/AF Lock', + 4 => 'AE Lock Only', + 5 => 'AE Lock (reset on release)', + 6 => 'AE Lock (hold)', + 7 => 'AF Lock Only', + 8 => 'AF-On', + 10 => 'Bracketing Burst', + 11 => 'Matrix Metering', + 12 => 'Center-weighted Metering', + 13 => 'Spot Metering', + 14 => 'Playback', + 15 => 'My Menu Top Item', + 16 => '+NEF(RAW)', + 17 => 'Virtual Horizon', + 19 => 'Grid Display', + 20 => 'My Menu', + 21 => 'Disable Synchronized Release', + 22 => 'Remote Release Only', + 26 => 'Flash Disable/Enable', + 27 => 'Highlight-weighted Metering', + 36 => 'AF-Area Mode (Single)', + 37 => 'AF-Area Mode (Dynamic Area 25 Points)', + 38 => 'AF-Area Mode (Dynamic Area 72 Points)', + 39 => 'AF-Area Mode (Dynamic Area 152 Points)', + 40 => 'AF-Area Mode (Group Area AF)', + 41 => 'AF-Area Mode (Auto Area AF)', + 42 => 'AF-Area Mode + AF-On (Single)', + 43 => 'AF-Area Mode + AF-On (Dynamic Area 25 Points)', + 44 => 'AF-Area Mode + AF-On (Dynamic Area 72 Points)', + 45 => 'AF-Area Mode + AF-On (Dynamic Area 152 Points)', + 46 => 'AF-Area Mode + AF-On (Group Area AF)', + 47 => 'AF-Area Mode + AF-On (Auto Area AF)', + 49 => 'Sync Release (Master Only)', + 50 => 'Sync Release (Remote Only)', + }, + }, + 81.1 => { # CSf1-f + Name => 'Func2ButtonPlusDials', + Mask => 0x0f, + PrintConv => { + 0 => 'None', + 1 => 'Choose Image Area', + 2 => 'Shutter Speed & Aperture Lock', + 3 => 'One Step Speed / Aperture', + 4 => 'Choose Non-CPU Lens Number', + 5 => 'Active D-Lighting', + 7 => 'Photo Shooting Menu Bank', + 8 => 'Exposure Delay Mode', + }, + }, + 82.1 => { # CSg1-e + Name => 'AssignMovieFunc2Button', + Mask => 0x70, + PrintConv => { + 0 => 'None', + 3 => 'Index Marking', + 4 => 'View Photo Shooting Info', + }, + }, + 83.1 => { # CSf1-i + Name => 'Func3Button', + Mask => 0x03, + PrintConv => { + 0 => 'None', + 1 => 'Voice Memo', + 2 => 'Rating', + 3 => 'Connect To Network', + }, + }, +); + +# D500 custom settings (ref 1) +%Image::ExifTool::NikonCustom::SettingsD500 = ( + PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData, + WRITE_PROC => \&Image::ExifTool::WriteBinaryData, + CHECK_PROC => \&Image::ExifTool::CheckBinaryData, + WRITABLE => 1, + FIRST_ENTRY => 0, + GROUPS => { 0 => 'MakerNotes', 2 => 'Camera' }, + NOTES => 'Custom settings for the D500.', + 0.1 => { + Name => 'CustomSettingsBank', + Mask => 0x03, + PrintConv => { + 0 => 'A', + 1 => 'B', + 2 => 'C', + 3 => 'D', + }, + }, + 1.1 => { #CSa1 + Name => 'AF-CPrioritySelection', + Mask => 0xc0, + PrintConv => { + 0 => 'Release', + 1 => 'Release + Focus', + 2 => 'Focus', + 3 => 'Focus + Release', + }, + }, + 1.2 => { # CSa6 + Name => 'NumberOfFocusPoints', + Mask => 0x10, + PrintConv => { + 0 => '55 Points', + 1 => '15 Points', + }, + }, + 1.3 => { # CSa4 + Name => 'Three-DTrackingFaceDetection', + Mask => 0x08, + PrintConv => \%offOn, + }, + 1.4 => { # CSa2 + Name => 'AF-SPrioritySelection', + Mask => 0x20, + PrintConv => { + 0 => 'Focus', + 1 => 'Release', + }, + }, + 1.5 => { # CSa3-a + Name => 'BlockShotAFResponse', + Mask => 0x07, + #values 1-5 + }, + 2.1 => { # CSa11 + Name => 'FocusPointWrap', + Mask => 0x08, + PrintConv => { + 0 => 'No Wrap', + 1 => 'Wrap', + }, + }, + 2.2 => { # CSa12-c + Name => 'AFPointBrightness', + Mask => 0x06, + PrintConv => { + 0 => 'Auto', + 1 => 'On', + 2 => 'Off', + }, + }, + 4.1 => { # CSd3 + Name => 'ISODisplay', + Mask => 0x08, + PrintConv => { + 0 => 'Show ISO Sensitivity', + 1 => 'Show Frame Count', + }, + }, + 4.2 => { # CSd8 + Name => 'GridDisplay', + Mask => 0x02, + PrintConv => \%onOff, + }, + 5.1 => { # CSd9 + Name => 'LCDIllumination', + Mask => 0x20, + PrintConv => \%offOn, + }, + 5.2 => { # CSd6 + Name => 'ElectronicFront-CurtainShutter', + Mask => 0x08, + PrintConv => \%offOn, + }, + 6.1 => { # CSf7 + Name => 'ReverseIndicators', + Mask => 0x80, + PrintConv => { + 0 => '+ 0 -', + 1 => '- 0 +', + }, + }, + 6.2 => { # CSf4-a + Name => 'CommandDialsReverseRotation', + Mask => 0x18, + PrintConv => { + 0 => 'No', + 1 => 'Shutter Speed & Aperture', + 2 => 'Exposure Compensation', + 3 => 'Exposure Compensation, Shutter Speed & Aperture', + }, + }, + 6.3 => { # CSb4 + Name => 'EasyExposureCompensation', + Mask => 0x03, + PrintConv => { + 0 => 'Off', + 1 => 'On', + 2 => 'On (auto reset)', + }, + }, + 7.1 => { # CSb2 + Name => 'ExposureControlStepSize', + Mask => 0xc0, + PrintConv => { + 0 => '1/3 EV', + 1 => '1/2 EV', + 2 => '1 EV', + }, + }, + 7.2 => { # CSb1 + Name => 'ISOStepSize', + Mask => 0x30, + PrintConv => { + 0 => '1/3 EV', + 1 => '1/2 EV', + 2 => '1 EV', + }, + }, + 7.3 => { # CSb3 + Name => 'ExposureCompStepSize', + Mask => 0x0c, + PrintConv => { + 0 => '1/3 EV', + 1 => '1/2 EV', + 2 => '1 EV', + }, + }, + 8.1 => { # CSb6 + Name => 'CenterWeightedAreaSize', + Mask => 0xe0, + PrintConv => { + 0 => '6 mm', + 1 => '8 mm', + 2 => '10 mm', + 3 => '13 mm', + 4 => 'Average', + }, + }, + 8.2 => { # CSb7-a + Name => 'FineTuneOptMatrixMetering', + Mask => 0x0f, + ValueConv => '($val > 0x7 ? $val - 0x10 : $val) / 6', + ValueConvInv => 'int($val*6+($val>0?0.5:-0.5))', + PrintConv => '$val ? sprintf("%+.2f", $val) : 0', + PrintConvInv => 'Image::ExifTool::Exif::ConvertFraction($val)', + }, + 9.1 => { # CSb7-b + Name => 'FineTuneOptCenterWeighted', + Mask => 0xf0, + ValueConv => '($val > 0x7 ? $val - 0x10 : $val) / 6', + ValueConvInv => 'int($val*6+($val>0?0.5:-0.5))', + PrintConv => '$val ? sprintf("%+.2f", $val) : 0', + PrintConvInv => 'Image::ExifTool::Exif::ConvertFraction($val)', + }, + 9.2 => { # CSb7-c + Name => 'FineTuneOptSpotMetering', + Mask => 0x0f, + ValueConv => '($val > 0x7 ? $val - 0x10 : $val) / 6', + ValueConvInv => 'int($val*6+($val>0?0.5:-0.5))', + PrintConv => '$val ? sprintf("%+.2f", $val) : 0', + PrintConvInv => 'Image::ExifTool::Exif::ConvertFraction($val)', + }, + 10.1 => { # CSf2-a + Name => 'MultiSelectorShootMode', + Mask => 0xe0, #same offset and settings as D810 but with a different decoding + PrintConv => { + 0 => 'Select Center Focus Point (Reset)', + 2 => 'Preset Focus Point (Pre)', + 3 => 'Highlight Active Focus Point', + 4 => 'Not Used (None)', + }, + }, + 10.2 => { # CSf2-b #same offset and settings as D810 but with a different decoding + Name => 'MultiSelectorPlaybackMode', + Mask => 0x0c, + PrintConv => { + 0 => 'Thumbnail On/Off', + 1 => 'View Histograms', + 2 => 'Zoom On/Off', + 3 => 'Choose Folder', + }, + }, + 10.3 => { # CSf5 + Name => 'MultiSelector', + Mask => 0x01, + PrintConv => { + 0 => 'Do Nothing', + 1 => 'Reset Meter-off Delay', + }, + }, + 11.1 => { # CSd5 + Name => 'ExposureDelayMode', + Mask => 0xc0, + PrintConv => { + 0 => 'Off', + 1 => '1 s', + 2 => '2 s', + 3 => '3 s', + }, + }, + 11.2 => { # CSd1 + Name => 'CLModeShootingSpeed', + Mask => 0x0f, + PrintConv => '"$val fps"', + PrintConvInv => '$val=~s/\s*fps//i; $val', + }, + 12.1 => { # CSd2 + Name => 'MaxContinuousRelease', + # values: 1-100 + }, + 13.1 => { # CSe7 + Name => 'AutoBracketOrder', + Mask => 0x10, + PrintConv => { + 0 => '0,-,+', + 1 => '-,0,+', + }, + }, + 13.2 => { # CSe6 + Name => 'AutoBracketModeM', + Mask => 0x0c, + PrintConv => { + 0 => 'Flash/Speed', + 1 => 'Flash/Speed/Aperture', + 2 => 'Flash/Aperture', + 3 => 'Flash Only', + }, + }, + 14.1 => { # CSf1-c + Name => 'Func1Button', + Mask => 0x3f, + PrintConv => { + 0 => 'None', + 1 => 'Preview', + 2 => 'FV Lock', + 3 => 'AE/AF Lock', + 4 => 'AE Lock Only', + 5 => 'AE Lock (reset on release)', + 6 => 'AE Lock (hold)', + 7 => 'AF Lock Only', + 8 => 'AF-On', + 10 => 'Bracketing Burst', + 11 => 'Matrix Metering', + 12 => 'Center-weighted Metering', + 13 => 'Spot Metering', + 14 => 'Playback', + 15 => 'My Menu Top Item', + 16 => '+NEF(RAW)', + 17 => 'Virtual Horizon', + 19 => 'Grid Display', + 20 => 'My Menu', + 22 => 'Remote Release Only', + 26 => 'Flash Disable/Enable', + 27 => 'Highlight-weighted Metering', + 36 => 'AF-Area Mode (Single)', + 37 => 'AF-Area Mode (Dynamic Area 25 Points)', + 38 => 'AF-Area Mode (Dynamic Area 72 Points)', + 39 => 'AF-Area Mode (Dynamic Area 152 Points)', + 40 => 'AF-Area Mode (Group Area AF)', + 41 => 'AF-Area Mode (Auto Area AF)', + 42 => 'AF-Area Mode + AF-On (Single)', + 43 => 'AF-Area Mode + AF-On (Dynamic Area 25 Points)', + 44 => 'AF-Area Mode + AF-On (Dynamic Area 72 Points)', + 45 => 'AF-Area Mode + AF-On (Dynamic Area 152 Points)', + 46 => 'AF-Area Mode + AF-On (Group Area AF)', + 47 => 'AF-Area Mode + AF-On (Auto Area AF)', + 49 => 'Sync Release (Master Only)', + 50 => 'Sync Release (Remote Only)', + }, + }, + 15.1 => { # CSf1-a + Name => 'PreviewButton', + Mask => 0x3f, + PrintConv => { + 0 => 'None', + 1 => 'Preview', + 2 => 'FV Lock', + 3 => 'AE/AF Lock', + 4 => 'AE Lock Only', + 5 => 'AE Lock (reset on release)', + 6 => 'AE Lock (hold)', + 7 => 'AF Lock Only', + 8 => 'AF-On', + 10 => 'Bracketing Burst', + 11 => 'Matrix Metering', + 12 => 'Center-weighted Metering', + 13 => 'Spot Metering', + 14 => 'Playback', + 15 => 'My Menu Top Item', + 16 => '+NEF(RAW)', + 17 => 'Virtual Horizon', + 19 => 'Grid Display', + 20 => 'My Menu', +# 21 => 'Disable Synchronized Release', # removed with D500 + 22 => 'Remote Release Only', + 26 => 'Flash Disable/Enable', + 27 => 'Highlight-weighted Metering', + 36 => 'AF-Area Mode (Single)', # new with D500 + 37 => 'AF-Area Mode (Dynamic Area 25 Points)', # new with D500 + 38 => 'AF-Area Mode (Dynamic Area 72 Points)', # new with D500 + 39 => 'AF-Area Mode (Dynamic Area 152 Points)', # new with D500 + 40 => 'AF-Area Mode (Group Area AF)', # new with D500 + 41 => 'AF-Area Mode (Auto Area AF)', # new with D500 + 42 => 'AF-Area Mode + AF-On (Single)', # new with D500 + 43 => 'AF-Area Mode + AF-On (Dynamic Area 25 Points)', # new with D500 + 44 => 'AF-Area Mode + AF-On (Dynamic Area 72 Points)', # new with D500 + 45 => 'AF-Area Mode + AF-On (Dynamic Area 152 Points)',# new with D500 + 46 => 'AF-Area Mode + AF-On (Group Area AF)', # new with D500 + 47 => 'AF-Area Mode + AF-On (Auto Area AF)', # new with D500 + 49 => 'Sync Release (Master Only)', # new with D500 + 50 => 'Sync Release (Remote Only)', # new with D500 + }, + }, + 16.1 => { # CSf1-j + Name => 'AssignBktButton', + Mask => 0x07, + PrintConv => { + 0 => 'Auto Bracketing', + 1 => 'Multiple Exposure', + 2 => 'HDR (high dynamic range)', + 3 => 'None', + }, + }, + 18.1 => { # CSf4-b + Name => 'CommandDialsChangeMainSub', + Mask => 0xe0, + PrintConv => { + 0 => 'Autofocus Off, Exposure Off', + 1 => 'Autofocus Off, Exposure On', + 2 => 'Autofocus Off, Exposure On (Mode A)', + 4 => 'Autofocus On, Exposure Off', + 5 => 'Autofocus On, Exposure On', + 6 => 'Autofocus On, Exposure On (Mode A)', + }, + }, + 18.2 => { # CSf4-d + Name => 'CommandDialsMenuAndPlayback', + Mask => 0x18, + PrintConv => { + 0 => 'On', + 1 => 'Off', + 2 => 'On (Image Review Excluded)', + }, + }, + 18.3 => { # CSf4-c + Name => 'CommandDialsApertureSetting', + Mask => 0x04, + PrintConv => { + 0 => 'Sub-command Dial', + 1 => 'Aperture Ring', + }, + }, + 18.4 => { # CSf6 + Name => 'ReleaseButtonToUseDial', + Mask => 0x01, + PrintConv => \%noYes, + }, + 19.1 => { # CSc2 + Name => 'StandbyTimer', + Mask => 0xf0, + PrintConv => { + 0 => '4 s', + 1 => '6 s', + 3 => '10 s', + 5 => '30 s', + 6 => '1 min', + 7 => '5 min', + 8 => '10 min', + 9 => '30 min', + 10 => 'No Limit', + }, + }, + 20.1 => { # CSc3-a + Name => 'SelfTimerTime', + Mask => 0xc0, + PrintConv => { + 0 => '2 s', + 1 => '5 s', + 2 => '10 s', + 3 => '20 s', + }, + }, + 20.2 => { # CSc3-c + Name => 'SelfTimerShotInterval', + Mask => 0x30, + PrintConv => { + 0 => '0.5 s', + 1 => '1 s', + 2 => '2 s', + 3 => '3 s', + }, + }, + 20.3 => { # CSc3-b + Name => 'SelfTimerShotCount', + Mask => 0x0f, + }, + 21.1 => { # CSc4-d + Name => 'ImageReviewMonitorOffTime', + Mask => 0xe0, + PrintConv => { + 0 => '2 s', + 1 => '4 s', + 3 => '10 s', + 4 => '20 s', + 5 => '1 min', + 6 => '5 min', + 7 => '10 min', + }, + }, + 21.2 => { # CSc4-e + Name => 'LiveViewMonitorOffTime', + Mask => 0x1c, + PrintConv => { + 1 => '5 min', + 2 => '10 min', + 3 => '15 min', + 4 => '20 min', + 5 => '30 min', + 6 => 'No Limit', + }, + }, + 22.1 => { # CSc4-b + Name => 'MenuMonitorOffTime', + Mask => 0xe0, + PrintConv => { + 0 => '4 s', + 2 => '10 s', + 4 => '20 s', + 5 => '1 min', + 6 => '5 min', + 7 => '10 min', + }, + }, + 22.2 => { # CSc4-c + Name => 'ShootingInfoMonitorOffTime', + Mask => 0x1c, + PrintConv => { + 0 => '4 s', + 2 => '10 s', + 4 => '20 s', + 5 => '1 min', + 6 => '5 min', + 7 => '10 min', + }, + }, + 23.1 => { # CSe1 + Name => 'FlashSyncSpeed', + Mask => 0xf0, + PrintConv => { + 2 => '1/250 s (auto FP)', + 3 => '1/250 s', + 5 => '1/200 s', + 6 => '1/160 s', + 7 => '1/125 s', + 8 => '1/100 s', + 9 => '1/80 s', + 10 => '1/60 s', + }, + }, + 23.2 => { # CSe2 + Name => 'FlashShutterSpeed', + Mask => 0x0f, + PrintConvColumns => 2, + PrintConv => { + 0 => '1/60 s', + 1 => '1/30 s', + 2 => '1/15 s', + 3 => '1/8 s', + 4 => '1/4 s', + 5 => '1/2 s', + 6 => '1 s', + 7 => '2 s', + 8 => '4 s', + 9 => '8 s', + 10 => '15 s', + 11 => '30 s', + }, + }, + 31.1 => { # CSe5 + Name => 'ModelingFlash', + Mask => 0x20, + PrintConv => \%onOff, + }, + 36.1 => { # CSc4-a + Name => 'PlaybackMonitorOffTime', + Mask => 0xe0, + PrintConv => { + 0 => '4 s', + 1 => '10 s', + 2 => '20 s', + 3 => '1 min', + 4 => '5 min', + 5 => '10 min', + }, + }, + 37.1 => { # CSf2-c + Name => 'MultiSelectorLiveView', + Mask => 0xc0, + PrintConv => { + 0 => 'Reset', + 1 => 'Zoom', + 3 => 'Not Used', + }, + }, + 38.1 => { # CSf3-a + Name => 'ShutterSpeedLock', + Mask => 0x80, + PrintConv => \%offOn, + }, + 38.2 => { # CSf3-b + Name => 'ApertureLock', + Mask => 0x40, + PrintConv => \%offOn, + }, + 38.3 => { # CSg1-h + Name => 'MovieShutterButton', + Mask => 0x10, + PrintConv => { + 0 => 'Take Photo', + 1 => 'Record Movies', + }, + }, + 38.4 => { # CSe3 + Name => 'FlashExposureCompArea', + Mask => 0x04, + PrintConv => { + 0 => 'Entire Frame', + 1 => 'Background Only', + }, + }, + 38.5 => { # CSe4 + Name => 'AutoFlashISOSensitivity', + Mask => 0x02, + PrintConv => { + 0 => 'Subject and Background', + 1 => 'Subject Only', + }, + }, + 41.1 => { # CSg1-c + Name => 'MovieFunc1Button', + Mask => 0xf0, + PrintConv => { + 0 => 'None', + 2 => 'Power Aperture (close)', + 3 => 'Index Marking', + 4 => 'View Photo Shooting Info', + 11 => 'Exposure Compensation -', + }, + }, + 41.2 => { # CSg1-a + Name => 'MoviePreviewButton', + Mask => 0x0f, + PrintConv => { + 0 => 'None', + 1 => 'Power Aperture (open)', + 3 => 'Index Marking', + 4 => 'View Photo Shooting Info', + 10 => 'Exposure Compensation +', + }, + }, + 42.1 => { # CSf1-d + Name => 'Func1ButtonPlusDials', + Mask => 0x0f, + PrintConv => { + 0 => 'None', + 1 => 'Choose Image Area (DX/1.3x)', + 2 => 'Shutter Speed & Aperture Lock', + 3 => 'One Step Speed / Aperture', + 4 => 'Choose Non-CPU Lens Number', + 5 => 'Active D-Lighting', + 7 => 'Photo Shooting Menu Bank', + 8 => 'Exposure Delay Mode', + }, + }, + 43.1 => { # CSf1-b + Name => 'PreviewButtonPlusDials', + Mask => 0x0f, + PrintConv => { + 0 => 'None', + 1 => 'Choose Image Area (DX/1.3x)', + 2 => 'Shutter Speed & Aperture Lock', + 3 => 'One Step Speed / Aperture', + 4 => 'Choose Non-CPU Lens Number', + 5 => 'Active D-Lighting', + 7 => 'Photo Shooting Menu Bank', # new with D500 + 8 => 'Exposure Delay Mode', + }, + }, + 45.1 => { # CSf1-k + Name => 'AssignMovieRecordButtonPlusDials', + Mask => 0x0f, + PrintConv => { + 0 => 'None', + 1 => 'Choose Image Area (DX/1.3x)', + 2 => 'Shutter Speed & Aperture Lock', + 7 => 'Photo Shooting Menu Bank', + 11 => 'Exposure Mode', + }, + }, + 46.1 => { # CSb7-d + Name => 'FineTuneOptHighlightWeighted', + Mask => 0x0f, + ValueConv => '($val > 0x7 ? $val - 0x10 : $val) / 6', + ValueConvInv => 'int($val*6+($val>0?0.5:-0.5))', + PrintConv => '$val ? sprintf("%+.2f", $val) : 0', + PrintConvInv => 'Image::ExifTool::Exif::ConvertFraction($val)', + }, + 47.1 => { # CSa12-b + Name => 'DynamicAreaAFDisplay', + Mask => 0x80, + PrintConv => \%offOn, + }, + 47.2 => { # CSa12-a + Name => 'AFPointIllumination', + Mask => 0x40, + PrintConv => { + 0 => 'Off', + 1 => 'On During Manual Focusing', + }, + }, + 47.3 => { # CSa7 + Name => 'StoreByOrientation', + Mask => 0x18, + PrintConv => { + 0 => 'Off', + 1 => 'Focus Point', + 2 => 'Focus Point and AF-area Mode', + }, + }, + 47.4 => { # CSa12-c + Name => 'GroupAreaAFIllumination', + Mask => 0x04, + PrintConv => { + 0 => 'Squares', + 1 => 'Dots', + }, + }, + 48.1 => { # CSb5 + Name => 'MatrixMetering', + Mask => 0x80, + PrintConv => { + 0 => 'Face Detection On', + 1 => 'Face Detection Off', + }, + }, + 48.2 => { # CSf8 + Name => 'LiveViewButtonOptions', + Mask => 0x30, + PrintConv => { + 0 => 'Enable', + 1 => 'Enable (Standby Timer Active)', # new with D500 + 2 => 'Disable', + }, + }, + 48.3 => { # CSa10 + Name => 'AFModeRestrictions', + Mask => 0x03, + PrintConv => { + 0 => 'No Restrictions', + 1 => 'AF-C', + 2 => 'AF-S', + }, + }, + 49.1 => { # CSa9 + Name => 'LimitAFAreaModeSelection', + Mask => 0x7e, + PrintConv => { + 0 => 'No Restrictions', + BITMASK => { + 0 => 'Auto-area', + 1 => 'Group-area', + 2 => '3D-tracking', + 3 => 'Dynamic area (153 points)', + 4 => 'Dynamic area (72 points)', + 5 => 'Dynamic area (25 points)', + }, + }, + }, + 52.1 => { # CSf1-l + Name => 'LensFocusFunctionButtons', + Mask => 0x3f, + PrintConv => { + 3 => 'AE/AF Lock', + 4 => 'AE Lock Only', + 7 => 'AF Lock Only', + 8 => 'AF-On', + 24 => 'Preset Focus Point', + 26 => 'Flash Disable/Enable', + 36 => 'AF-Area Mode (Single)', + 37 => 'AF-Area Mode (Dynamic Area 25 Points)', + 38 => 'AF-Area Mode (Dynamic Area 72 Points)', + 39 => 'AF-Area Mode (Dynamic Area 152 Points)', + 40 => 'AF-Area Mode (Group Area AF)', + 41 => 'AF-Area Mode (Auto Area AF)', + 42 => 'AF-Area Mode + AF-On (Single)', + 43 => 'AF-Area Mode + AF-On (Dynamic Area 25 Points)', + 44 => 'AF-Area Mode + AF-On (Dynamic Area 72 Points)', + 45 => 'AF-Area Mode + AF-On (Dynamic Area 152 Points)', + 46 => 'AF-Area Mode + AF-On (Group Area AF)', + 47 => 'AF-Area Mode + AF-On (Auto Area AF)', + 49 => 'Sync Release (Master Only)', + 50 => 'Sync Release (Remote Only)', + }, + }, + 66.1 => { # CSf10-d + Name => 'VerticalMultiSelector', + Mask => 0xff, + PrintHex => 1, + PrintConv => { + 0x00 => 'Same as Multi-Selector with Info(U/D) & Playback(R/L)', + 0x08 => 'Same as Multi-Selector with Info(R/L) & Playback(U/D)', + 0x80 => 'Focus Point Selection', + }, + }, + 67.1 => { # CSf10-a + Name => 'AssignMB-D17FuncButton', + Mask => 0x3f, + PrintConv => { + 0 => 'None', + 1 => 'Preview', + 2 => 'FV Lock', + 3 => 'AE/AF Lock', + 4 => 'AE Lock Only', + 5 => 'AE Lock (reset on release)', + 6 => 'AE Lock (hold)', + 7 => 'AF Lock Only', + 8 => 'AF-On', + 10 => 'Bracketing Burst', + 11 => 'Matrix Metering', + 12 => 'Center-weighted Metering', + 13 => 'Spot Metering', + 14 => 'Playback', + 15 => 'My Menu Top Item', + 16 => '+NEF(RAW)', + 17 => 'Virtual Horizon', + 18 => 'Reset Focus Point', + 19 => 'Grid Display', + 20 => 'My Menu', + 22 => 'Remote Release Only', + 23 => 'Preset Focus Point', + 26 => 'Flash Disable/Enable', + 27 => 'Highlight-weighted Metering', + 36 => 'AF-Area Mode (Single)', + 37 => 'AF-Area Mode (Dynamic Area 25 Points)', + 38 => 'AF-Area Mode (Dynamic Area 72 Points)', + 39 => 'AF-Area Mode (Dynamic Area 152 Points)', + 40 => 'AF-Area Mode (Group Area AF)', + 41 => 'AF-Area Mode (Auto Area AF)', + 42 => 'AF-Area Mode + AF-On (Single)', + 43 => 'AF-Area Mode + AF-On (Dynamic Area 25 Points)', + 44 => 'AF-Area Mode + AF-On (Dynamic Area 72 Points)', + 45 => 'AF-Area Mode + AF-On (Dynamic Area 152 Points)', + 46 => 'AF-Area Mode + AF-On (Group Area AF)', + 47 => 'AF-Area Mode + AF-On (Auto Area AF)', + 49 => 'Sync Release (Master Only)', + 50 => 'Sync Release (Remote Only)', + 54 => 'Highlight Active Focus Point', + }, + }, + 68.1 => { # CSf10-b + Name => 'AssignMB-D17FuncButtonPlusDials', + Mask => 0x0f, + PrintConv => { + 0 => 'None', + 1 => 'Choose Image Area (DX/1.3x)', + 2 => 'Shutter Speed & Aperture Lock', + 3 => 'One Step Speed / Aperture', + 4 => 'Choose Non-CPU Lens Number', + 5 => 'Active D-Lighting', + 7 => 'Photo Shooting Menu Bank', + 8 => 'Exposure Delay Mode', + 10 => 'ISO Sensitivity', + 11 => 'Exposure Mode', + 12 => 'Exposure Compensation', + 13 => 'Metering Mode', + }, + }, + 70.1 => { # CSf1-f + Name => 'AF-OnButton', + Mask => 0x3f, + PrintConv => { + 0 => 'None', + 3 => 'AE/AF Lock', + 4 => 'AE Lock Only', + 5 => 'AE Lock (reset on release)', + 6 => 'AE Lock (hold)', + 7 => 'AF Lock Only', + 8 => 'AF-On', + 36 => 'AF-Area Mode (Single)', + 37 => 'AF-Area Mode (Dynamic Area 25 Points)', + 38 => 'AF-Area Mode (Dynamic Area 72 Points)', + 39 => 'AF-Area Mode (Dynamic Area 152 Points)', + 40 => 'AF-Area Mode (Group Area AF)', + 41 => 'AF-Area Mode (Auto Area AF)', + 42 => 'AF-Area Mode + AF-On (Single)', + 43 => 'AF-Area Mode + AF-On (Dynamic Area 25 Points)', + 44 => 'AF-Area Mode + AF-On (Dynamic Area 72 Points)', + 45 => 'AF-Area Mode + AF-On (Dynamic Area 152 Points)', + 46 => 'AF-Area Mode + AF-On (Group Area AF)', + 47 => 'AF-Area Mode + AF-On (Auto Area AF)', + }, + }, + 71.1 => { # CSf1-g + Name => 'SubSelector', + Mask => 0x80, + PrintConv => { + 0 => 'Focus Point Selection', + 1 => 'Same as MultiSelector', + }, + }, + 72.1 => { # CSf1-h + Name => 'SubSelectorCenter', + Mask => 0x3f, + PrintConv => { + 0 => 'None', + 1 => 'Preview', + 2 => 'FV Lock', + 3 => 'AE/AF Lock', + 4 => 'AE Lock Only', + 5 => 'AE Lock (reset on release)', + 6 => 'AE Lock (hold)', + 7 => 'AF Lock Only', + 8 => 'AF-On', + 10 => 'Bracketing Burst', + 11 => 'Matrix Metering', + 12 => 'Center-weighted Metering', + 13 => 'Spot Metering', + 14 => 'Playback', + 15 => 'My Menu Top Item', + 16 => '+NEF(RAW)', + 17 => 'Virtual Horizon', + 18 => 'Reset Focus Point', + 19 => 'Grid Display', + 20 => 'My Menu', + 22 => 'Remote Release Only', + 23 => 'Preset Focus Point', + 26 => 'Flash Disable/Enable', + 27 => 'Highlight-weighted Metering', + 36 => 'AF-Area Mode (Single)', + 37 => 'AF-Area Mode (Dynamic Area 25 Points)', + 38 => 'AF-Area Mode (Dynamic Area 72 Points)', + 39 => 'AF-Area Mode (Dynamic Area 152 Points)', + 40 => 'AF-Area Mode (Group Area AF)', + 41 => 'AF-Area Mode (Auto Area AF)', + 42 => 'AF-Area Mode + AF-On (Single)', + 43 => 'AF-Area Mode + AF-On (Dynamic Area 25 Points)', + 44 => 'AF-Area Mode + AF-On (Dynamic Area 72 Points)', + 45 => 'AF-Area Mode + AF-On (Dynamic Area 152 Points)', + 46 => 'AF-Area Mode + AF-On (Group Area AF)', + 47 => 'AF-Area Mode + AF-On (Auto Area AF)', + 49 => 'Sync Release (Master Only)', + 50 => 'Sync Release (Remote Only)', + 54 => 'Highlight Active Focus Point', + }, + }, + 73.1 => { # CSf1-i + Name => 'SubSelectorPlusDials', + Mask => 0x0f, + PrintConv => { + 0 => 'None', + 1 => 'Choose Image Area (DX/1.3x)', + 2 => 'Shutter Speed & Aperture Lock', + 4 => 'Choose Non-CPU Lens Number', + 7 => 'Photo Shooting Menu Bank', + }, + }, + 74.1 => { # CSg1-f + Name => 'AssignMovieSubselector', + Mask => 0xf0, + PrintConv => { + 0 => 'None', + 3 => 'Index Marking', + 4 => 'View Photo Shooting Info', + 5 => 'AE/AF Lock', + 6 => 'AE Lock (Only)', + 7 => 'AE Lock (Hold)', + 8 => 'AF Lock (Only)', + }, + }, + 75.1 => { # CSg1-d + Name => 'AssignMovieFunc1ButtonPlusDials', + Mask => 0x10, + PrintConv => { + 0 => 'None', + 1 => 'Choose Image Area (DX/1.3x)', + }, + }, + 75.2 => { # CSg1-b + Name => 'AssignMoviePreviewButtonPlusDials', + Mask => 0x01, + PrintConv => { + 0 => 'None', + 1 => 'Choose Image Area (DX/1.3x)', + }, + }, + 76.1 => { # CSg1-g + Name => 'AssignMovieSubselectorPlusDials', + Mask => 0x10, + PrintConv => { + 0 => 'None', + 1 => 'Choose Image Area (DX/1.3x)', + }, + }, + 77.1 => { # CSd4 + Name => 'SyncReleaseMode', # new with D500 + Mask => 0x80, + PrintConv => { + 0 => 'No Sync', + 1 => 'Sync', + }, + }, + 78.1 => { # CSa5 + Name => 'Three-DTrackingWatchArea', # new with D500 + Mask => 0x80, + PrintConv => { + 0 => 'Wide', + 1 => 'Normal', + }, + }, + 78.2 => { # CSa3-b + Name => 'SubjectMotion', + Mask => 0x60, + PrintConv => { + 0 => 'Steady', + 1 => 'Middle', + 2 => 'Erratic', + }, + }, + 78.3 => { # CSa8 + Name => 'AFActivation', + Mask => 0x08, + PrintConv => { + 0 => 'Shutter/AF-On', + 1 => 'AF-On Only', + }, + }, + 78.4 => { # CSc1 + Name => 'ShutterReleaseButtonAE-L', + Mask => 0x03, + PrintConv => { + 0 => 'Off', + 1 => 'On (Half Press)', + 2 => 'On (Burst Mode)' + }, + }, + 79.1 => { # CSf10-c + Name => 'AssignMB-D17AF-OnButton', + Mask => 0x7f, + PrintConv => { + 0 => 'None', + 3 => 'AE/AF Lock', + 4 => 'AE Lock Only', + 5 => 'AE Lock (reset on release)', + 6 => 'AE Lock (hold)', + 7 => 'AF Lock Only', + 8 => 'AF-On', + 36 => 'AF-Area Mode (Single)', + 37 => 'AF-Area Mode (Dynamic Area 25 Points)', + 38 => 'AF-Area Mode (Dynamic Area 72 Points)', + 39 => 'AF-Area Mode (Dynamic Area 152 Points)', + 40 => 'AF-Area Mode (Group Area AF)', + 41 => 'AF-Area Mode (Auto Area AF)', + 42 => 'AF-Area Mode + AF-On (Single)', + 43 => 'AF-Area Mode + AF-On (Dynamic Area 25 Points)', + 44 => 'AF-Area Mode + AF-On (Dynamic Area 72 Points)', + 45 => 'AF-Area Mode + AF-On (Dynamic Area 152 Points)', + 46 => 'AF-Area Mode + AF-On (Group Area AF)', + 47 => 'AF-Area Mode + AF-On (Auto Area AF)', + 100 => 'Same as Camera AF-On Button', + }, + }, + 80.1 => { # CSf1-e + Name => 'Func2Button', + Mask => 0x3f, + PrintConv => { + 0 => 'None', + 15 => 'My Menu Top Item', + 20 => 'My Menu', + 55 => 'Rating', + }, + }, + 82.1 => { # CSg1-e + Name => 'AssignMovieFunc2Button', + Mask => 0x70, + PrintConv => { + 0 => 'None', + 3 => 'Index Marking', + 4 => 'View Photo Shooting Info', + }, + }, +); + +# D610 custom settings (ref forum6942) +%Image::ExifTool::NikonCustom::SettingsD610 = ( + PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData, + WRITE_PROC => \&Image::ExifTool::WriteBinaryData, + CHECK_PROC => \&Image::ExifTool::CheckBinaryData, + WRITABLE => 1, + FIRST_ENTRY => 0, + GROUPS => { 0 => 'MakerNotes', 2 => 'Camera' }, + NOTES => 'Custom settings for the D610.', + 0.1 => { #CSa1 + Name => 'AF-CPrioritySelection', + Mask => 0x80, + PrintConv => { + 0 => 'Release', + 1 => 'Focus', + }, + }, + 0.2 => { #CSa2 + Name => 'AF-SPrioritySelection', + Mask => 0x20, + PrintConv => { + 0 => 'Release', + 1 => 'Focus', + }, + }, + 0.3 => { # CSa6 + Name => 'NumberOfFocusPoints', + Mask => 0x10, + PrintConv => { + 0 => '39 Points', + 1 => '11 Points', + }, + }, + 0.4 => { # CSa3 + Name => 'FocusTrackingLockOn', + Mask => 0x07, + PrintConv => { + 0 => 'Off', + 1 => '1 Short', + 2 => '2', + 3 => '3 Normal', + 4 => '4', + 5 => '5 Long', + }, + }, + 1.1 => { # CSa5 + Name => 'FocusPointWrap', + Mask => 0x08, + PrintConv => { + 0 => 'No Wrap', + 1 => 'Wrap', + }, + }, + 1.2 => { # CSa4 + Name => 'AFPointIllumination', + Mask => 0x06, + PrintConv => { + 0 => 'Auto', + 1 => 'On', + 2 => 'Off', + }, + }, + 1.3 => { # CSa7 + Name => 'AFAssist', + Mask => 0x01, + PrintConv => \%onOff, + }, + 5.1 => { # CSb3 + Name => 'EasyExposureCompensation', + Mask => 0x03, + PrintConv => { + 0 => 'Off', + 1 => 'On', + 2 => 'On Auto Reset', + }, + }, + 6.1 => { # CSb2 + Name => 'ExposureControlStep', + Mask => 0x40, + PrintConv => { + 0 => '1/3 EV', + 1 => '1/2 EV', + }, + }, + 6.2 => { # CSb1 + Name => 'ISOSensitivityStep', + Mask => 0x10, + PrintConv => { + 0 => '1/3 EV', + 1 => '1/2 EV', + }, + }, + 7.1 => { # CSb4 + Name => 'CenterWeightedAreaSize', + Mask => 0xe0, + PrintConv => { + 0 => '8 mm', + 1 => '12 mm', + 2 => '15 mm', + 3 => '20 mm', + 4 => 'Average', + }, + }, + 7.2 => { # CSb5-a + Name => 'FineTuneOptMatrixMetering', + Mask => 0x0f, + ValueConv => '($val > 0x7 ? $val - 0x10 : $val) / 6', + ValueConvInv => 'int($val*6+($val>0?0.5:-0.5))', + PrintConv => '$val ? sprintf("%+.2f", $val) : 0', + PrintConvInv => 'Image::ExifTool::Exif::ConvertFraction($val)', + }, + 8.1 => { # CSb5-b + Name => 'FineTuneOptCenterWeighted', + Mask => 0xf0, + ValueConv => '($val > 0x7 ? $val - 0x10 : $val) / 6', + ValueConvInv => 'int($val*6+($val>0?0.5:-0.5))', + PrintConv => '$val ? sprintf("%+.2f", $val) : 0', + PrintConvInv => 'Image::ExifTool::Exif::ConvertFraction($val)', + }, + 8.2 => { # CSb5-c + Name => 'FineTuneOptSpotMetering', + Mask => 0x0f, + ValueConv => '($val > 0x7 ? $val - 0x10 : $val) / 6', + ValueConvInv => 'int($val*6+($val>0?0.5:-0.5))', + PrintConv => '$val ? sprintf("%+.2f", $val) : 0', + PrintConvInv => 'Image::ExifTool::Exif::ConvertFraction($val)', + }, + 17.1 => { # CSc1 + Name => 'ShutterReleaseButtonAE-L', + Mask => 0x02, + PrintConv => \%offOn, + }, + 18.1 => { # CSc2 + Name => 'StandbyTimer', + Mask => 0xf0, + PrintConv => { + 0 => '4 s', + 1 => '6 s', + 2 => '10 s', + 3 => '30 s', + 4 => '1 min', + 5 => '5 min', + 6 => '10 min', + 7 => '30 min', + 8 => 'No Limit', + }, + }, + 18.2 => { # CSc5 + Name => 'RemoteOnDuration', + Mask => 0x03, + PrintConv => { + 0 => '1 min', + 1 => '5 min', + 2 => '10 min', + 3 => '20 min', + }, + }, + 19.1 => { # CSc3-a + Name => 'SelfTimerTime', + Mask => 0xc0, + PrintConv => { + 0 => '2 s', + 1 => '5 s', + 2 => '10 s', + 3 => '20 s', + }, + }, + 19.2 => { # CSc3-c + Name => 'SelfTimerShotInterval', + Mask => 0x30, + PrintConv => { + 0 => '0.5 s', + 1 => '1 s', + 2 => '2 s', + 3 => '3 s', + }, + }, + 19.3 => { # CSc3-b + Name => 'SelfTimerShotCount', + Mask => 0x0f, + }, + 20.1 => { # CSc4-d + Name => 'ImageReviewMonitorOffTime', + Mask => 0xe0, + PrintConv => { + 0 => '2 s', + 1 => '4 s', + 2 => '10 s', + 3 => '20 s', + 4 => '1 min', + 5 => '5 min', + 6 => '10 min', + }, + }, + 20.2 => { # CSc4-e + Name => 'LiveViewMonitorOffTime', + Mask => 0x1c, + PrintConv => { + 0 => '5 min', + 1 => '10 min', + 2 => '15 min', + 3 => '20 min', + 4 => '30 min', + 5 => 'No Limit', + }, + }, + 21.1 => { # CSc4-b + Name => 'MenuMonitorOffTime', + Mask => 0xe0, + PrintConv => { + 0 => '4 s', + 1 => '10 s', + 2 => '20 s', # default + 3 => '1 min', + 4 => '5 min', + 5 => '10 min', + }, + }, + 21.2 => { # CSc4-c + Name => 'ShootingInfoMonitorOffTime', + Mask => 0x1c, + PrintConv => { + 0 => '4 s', + 1 => '10 s', # default + 2 => '20 s', + 3 => '1 min', + 4 => '5 min', + 5 => '10 min', + }, + }, + 35.1 => { # CSc4-a + Name => 'PlaybackMonitorOffTime', + Mask => 0xe0, + PrintConv => { + 0 => '4 s', + 1 => '10 s', + 2 => '20 s', + 3 => '1 min', + 4 => '5 min', + 5 => '10 min', + }, + }, +); + +# D810 custom settings (ref 1) +%Image::ExifTool::NikonCustom::SettingsD810 = ( + PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData, + WRITE_PROC => \&Image::ExifTool::WriteBinaryData, + CHECK_PROC => \&Image::ExifTool::CheckBinaryData, + WRITABLE => 1, + FIRST_ENTRY => 0, + DATAMEMBER => [ 24.1 ], + GROUPS => { 0 => 'MakerNotes', 2 => 'Camera' }, + NOTES => 'Custom settings for the D810.', + 0.1 => { # CSf1 + Name => 'LightSwitch', + Mask => 0x08, + PrintConv => { + 0 => 'LCD Backlight', + 1 => 'LCD Backlight and Shooting Information', + }, + }, + 0.2 => { + Name => 'CustomSettingsBank', + Mask => 0x03, + PrintConv => { + 0 => 'A', + 1 => 'B', + 2 => 'C', + 3 => 'D', + }, + }, + 1.1 => { #CSa1 + Name => 'AF-CPrioritySelection', + Mask => 0xc0, + PrintConv => { + 0 => 'Release', + 1 => 'Release + Focus', + 2 => 'Focus', + }, + }, + 1.2 => { # CSa2 + Name => 'AF-SPrioritySelection', + Mask => 0x20, + PrintConv => { + 0 => 'Focus', + 1 => 'Release', + }, + }, + 1.3 => { # CSa7 + Name => 'AFPointSelection', + Mask => 0x10, + PrintConv => { + 0 => '51 Points', + 1 => '11 Points', + }, + }, + 1.4 => { # CSa3 + Name => 'FocusTrackingLockOn', + Mask => 0x07, + PrintConv => { + 0 => 'Off', + 1 => '1 (Short)', + 2 => '2', + 3 => '3 (Normal)', + 4 => '4', + 5 => '5 (Long)', + }, + }, + 2.1 => { # CSa4 + Name => 'AFActivation', + Mask => 0x80, + PrintConv => { + 0 => 'Shutter/AF-On', + 1 => 'AF-On Only', + }, + }, + 2.2 => { # CSa7 + Name => 'FocusPointWrap', + Mask => 0x08, + PrintConv => { + 0 => 'No Wrap', + 1 => 'Wrap', + }, + }, + 2.3 => { # CSa6 + Name => 'AFPointBrightness', + Mask => 0x06, + PrintConv => { + 0 => 'Auto', + 1 => 'On', + 2 => 'Off', + }, + }, + 2.4 => { # CSa10 + Name => 'AFAssist', + Mask => 0x01, + PrintConv => \%onOff, + }, + 3.1 => { # CSd13 + Name => 'BatteryOrder', + Mask => 0x40, + PrintConv => { + 0 => 'MB-D12 First', + 1 => 'Camera Battery First', + }, + }, + 3.2 => { # CSd12 + Name => 'MB-D12BatteryType', + Mask => 0x03, + PrintConv => { + 0 => 'LR6 (AA alkaline)', + 1 => 'HR6 (AA Ni-MH)', + 2 => 'FR6 (AA lithium)', + }, + }, + 4.1 => { # CSd1-b + Name => 'Pitch', + Mask => 0x40, + PrintConv => { 0 => 'High', 1 => 'Low' }, + }, + 4.2 => { # CSf11 + Name => 'NoMemoryCard', + Mask => 0x20, + PrintConv => { + 0 => 'Release Locked', + 1 => 'Enable Release', + }, + }, + 4.3 => { # CSd8 + Name => 'ISODisplay', + Mask => 0x0c, + PrintConv => { + 0 => 'Show ISO/Easy ISO', + 1 => 'Show ISO Sensitivity', + 3 => 'Show Frame Count', + }, + }, + 4.4 => { # CSd7 + Name => 'GridDisplay', + Mask => 0x02, + PrintConv => \%onOff, + }, + 5.1 => { # CSd10 + Name => 'ShootingInfoDisplay', + Mask => 0xc0, + PrintConv => { + 0 => 'Not Set', # observed on a new camera prior to applying a setting for the first time + 1 => 'Auto', + 2 => 'Manual (dark on light)', + 3 => 'Manual (light on dark)', + }, + }, + 5.2 => { # CSd11 + Name => 'LCDIllumination', + Mask => 0x20, + PrintConv => \%offOn, + }, + 5.3 => { # CSd5 + Name => 'ElectronicFront-CurtainShutter', + Mask => 0x08, + PrintConv => \%offOn, + }, + 5.4 => { # CSd9 + Name => 'ScreenTips', + Mask => 0x04, + PrintConv => \%offOn, + }, + 5.5 => { # CSd1-a + Name => 'Beep', + Mask => 0x03, + PrintConv => { + 0 => 'Off', + 1 => 'Low', + 2 => 'Medium', + 3 => 'High', + }, + }, + 6.1 => { # CSf12 + Name => 'ReverseIndicators', + Mask => 0x80, + PrintConv => { + 0 => '+ 0 -', + 1 => '- 0 +', + }, + }, + 6.2 => { # CSf9-a + Name => 'CommandDialsReverseRotation', + Mask => 0x18, + PrintConv => { + 0 => 'No', + 1 => 'Shutter Speed & Aperture', + 2 => 'Exposure Compensation', + 3 => 'Exposure Compensation, Shutter Speed & Aperture', + }, + }, + 6.3 => { # CSb4 + Name => 'EasyExposureCompensation', + Mask => 0x03, + PrintConv => { + 0 => 'Off', + 1 => 'On', + 2 => 'On (auto reset)', + }, + }, + 7.1 => { # CSb2 + Name => 'ExposureControlStepSize', + Mask => 0xc0, + PrintConv => { + 0 => '1/3 EV', + 1 => '1/2 EV', + 2 => '1 EV', + }, + }, + 7.2 => { # CSb1 + Name => 'ISOStepSize', + Mask => 0x30, + PrintConv => { + 0 => '1/3 EV', + 1 => '1/2 EV', + 2 => '1 EV', + }, + }, + 7.3 => { # CSb3 + Name => 'ExposureCompStepSize', + Mask => 0x0c, + PrintConv => { + 0 => '1/3 EV', + 1 => '1/2 EV', + 2 => '1 EV', + }, + }, + 8.1 => { # CSb6 + Name => 'CenterWeightedAreaSize', + Mask => 0xe0, + PrintConv => { + 0 => '8 mm', + 1 => '12 mm', + 2 => '15 mm', + 3 => '20 mm', + 4 => 'Average', + }, + }, + 8.2 => { # CSb7-a + Name => 'FineTuneOptMatrixMetering', + Mask => 0x0f, + ValueConv => '($val > 0x7 ? $val - 0x10 : $val) / 6', + ValueConvInv => 'int($val*6+($val>0?0.5:-0.5))', + PrintConv => '$val ? sprintf("%+.2f", $val) : 0', + PrintConvInv => 'Image::ExifTool::Exif::ConvertFraction($val)', + }, + 9.1 => { # CSb7-b + Name => 'FineTuneOptCenterWeighted', + Mask => 0xf0, + ValueConv => '($val > 0x7 ? $val - 0x10 : $val) / 6', + ValueConvInv => 'int($val*6+($val>0?0.5:-0.5))', + PrintConv => '$val ? sprintf("%+.2f", $val) : 0', + PrintConvInv => 'Image::ExifTool::Exif::ConvertFraction($val)', + }, + 9.2 => { # CSb7-c + Name => 'FineTuneOptSpotMetering', + Mask => 0x0f, + ValueConv => '($val > 0x7 ? $val - 0x10 : $val) / 6', + ValueConvInv => 'int($val*6+($val>0?0.5:-0.5))', + PrintConv => '$val ? sprintf("%+.2f", $val) : 0', + PrintConvInv => 'Image::ExifTool::Exif::ConvertFraction($val)', + }, + 10.1 => { # CSf2-a + Name => 'MultiSelectorShootMode', + Mask => 0xc0, + PrintConv => { + 0 => 'Select Center Focus Point (Reset)', + 1 => 'Highlight Active Focus Point', + 2 => 'Preset Focus Point (Pre)', + 3 => 'Not Used (None)', + }, + }, + 10.2 => { # CSf2-b + Name => 'MultiSelectorPlaybackMode', + Mask => 0x30, + PrintConv => { + 0 => 'Thumbnail On/Off', + 1 => 'View Histograms', + 2 => 'Zoom On/Off', + 3 => 'Choose Folder', + }, + }, + 10.3 => { # CSf3 + Name => 'MultiSelector', + Mask => 0x01, + PrintConv => { + 0 => 'Do Nothing', + 1 => 'Reset Meter-off Delay', + }, + }, + 11.1 => { # CSd4 + Name => 'ExposureDelayMode', + Mask => 0xc0, + PrintConv => { + 0 => 'Off', + 1 => '1 s', + 2 => '2 s', + 3 => '3 s', + }, + }, + 11.2 => { # CSd2 + Name => 'CLModeShootingSpeed', + Mask => 0x0f, + PrintConv => '"$val fps"', + PrintConvInv => '$val=~s/\s*fps//i; $val', + }, + 12.1 => { # CSd3 + Name => 'MaxContinuousRelease', + # values: 1-100 + }, + 13.1 => { # CSe6 + Name => 'AutoBracketSet', + Mask => 0xe0, + PrintConv => { + 0 => 'AE & Flash', + 1 => 'AE Only', + 2 => 'Flash Only', + 3 => 'WB Bracketing', + 4 => 'Active D-Lighting', + }, + }, + 13.2 => { # CSe8 + Name => 'AutoBracketOrder', + Mask => 0x10, + PrintConv => { + 0 => '0,-,+', + 1 => '-,0,+', + }, + }, + 13.3 => { # CSe7 + Name => 'AutoBracketModeM', + Mask => 0x0c, + PrintConv => { + 0 => 'Flash/Speed', + 1 => 'Flash/Speed/Aperture', + 2 => 'Flash/Aperture', + 3 => 'Flash Only', + }, + }, + 14.1 => { # CSf4-a + Name => 'FuncButton', + Mask => 0x1f, + PrintConv => { + 0 => 'None', + 1 => 'Preview', + 2 => 'FV Lock', + 3 => 'AE/AF Lock', + 4 => 'AE Lock Only', + 5 => 'AE Lock (reset on release)', + 6 => 'AE Lock (hold)', + 7 => 'AF Lock Only', + 8 => 'AF-On', + 10 => 'Bracketing Burst', + 11 => 'Matrix Metering', + 12 => 'Center-weighted Metering', + 13 => 'Spot Metering', + 14 => 'Playback', + 15 => 'My Menu Top Item', + 16 => '+NEF(RAW)', + 17 => 'Virtual Horizon', + 19 => 'Grid Display', # values 19 and 20 are swapped from the D4s encodings + 20 => 'My Menu', + 21 => 'Disable Synchronized Release', + 22 => 'Remote Release Only', + 26 => 'Flash Disable/Enable', + 27 => 'Highlight-weighted Metering', # new value with D810 + }, + }, + 15.1 => { # CSf5-a + Name => 'PreviewButton', + Mask => 0x1f, + PrintConv => { + 0 => 'None', + 1 => 'Preview', + 2 => 'FV Lock', + 3 => 'AE/AF Lock', + 4 => 'AE Lock Only', + 5 => 'AE Lock (reset on release)', + 6 => 'AE Lock (hold)', + 7 => 'AF Lock Only', + 8 => 'AF-On', + 10 => 'Bracketing Burst', + 11 => 'Matrix Metering', + 12 => 'Center-weighted Metering', + 13 => 'Spot Metering', + 14 => 'Playback', + 15 => 'My Menu Top Item', + 16 => '+NEF(RAW)', + 17 => 'Virtual Horizon', + 19 => 'Grid Display', # values 19 and 20 are swapped from the D4s encodings + 20 => 'My Menu', + 21 => 'Disable Synchronized Release', + 22 => 'Remote Release Only', + 26 => 'Flash Disable/Enable', + 27 => 'Highlight-weighted Metering', # new value with D810 + }, + }, + 16.1 => { # CSf8 + Name => 'AssignBktButton', + Mask => 0x07, + PrintConv => { + 0 => 'Auto Bracketing', + 1 => 'Multiple Exposure', + 2 => 'HDR (high dynamic range)', + 3 => 'None', + }, + }, + 17.1 => { # CSf6-a + Name => 'AELockButton', + Mask => 0x1f, + PrintConv => { + 0 => 'None', + 1 => 'Preview', + 2 => 'FV Lock', + 3 => 'AE/AF Lock', + 4 => 'AE Lock Only', + 5 => 'AE Lock (reset on release)', + 6 => 'AE Lock (hold)', + 7 => 'AF Lock Only', + 8 => 'AF-On', + 10 => 'Bracketing Burst', + 11 => 'Matrix Metering', + 12 => 'Center-weighted Metering', + 13 => 'Spot Metering', + 14 => 'Playback', + 15 => 'My Menu Top Item', + 16 => '+NEF(RAW)', + 17 => 'Virtual Horizon', + 19 => 'Grid Display', # values 19 and 20 are swapped from the D4s encodings + 20 => 'My Menu', + 21 => 'Disable Synchronized Release', + 22 => 'Remote Release Only', + 26 => 'Flash Disable/Enable', + 27 => 'Highlight-weighted Metering', # new value with D810 + }, + }, + 18.1 => { # CSf9-b + Name => 'CommandDialsChangeMainSub', + Mask => 0xe0, + PrintConv => { + 0 => 'Autofocus Off, Exposure Off', + 1 => 'Autofocus Off, Exposure On', + 2 => 'Autofocus Off, Exposure On (Mode A)', + 4 => 'Autofocus On, Exposure Off', + 5 => 'Autofocus On, Exposure On', + 6 => 'Autofocus On, Exposure On (Mode A)', + }, + }, + 18.2 => { # CSf9-d + Name => 'CommandDialsMenuAndPlayback', + Mask => 0x18, + PrintConv => { + 0 => 'On', + 1 => 'Off', + 2 => 'On (Image Review Excluded)', + }, + }, + 18.3 => { # CSf9-c + Name => 'CommandDialsApertureSetting', + Mask => 0x04, + PrintConv => { + 0 => 'Sub-command Dial', + 1 => 'Aperture Ring', + }, + }, + 18.4 => { # CSc1 + Name => 'ShutterReleaseButtonAE-L', + Mask => 0x02, + PrintConv => \%offOn, + }, + 18.5 => { # CSf10 + Name => 'ReleaseButtonToUseDial', + Mask => 0x01, + PrintConv => \%noYes, + }, + 19.1 => { # CSc2 + Name => 'StandbyTimer', + Mask => 0xf0, + PrintConv => { + 0 => '4 s', + 1 => '6 s', + 3 => '10 s', + 5 => '30 s', + 6 => '1 min', + 7 => '5 min', + 8 => '10 min', + 9 => '30 min', + 10 => 'No Limit', #1 + }, + }, + 20.1 => { # CSc3-a + Name => 'SelfTimerTime', + Mask => 0xc0, + PrintConv => { + 0 => '2 s', + 1 => '5 s', + 2 => '10 s', + 3 => '20 s', + }, + }, + 20.2 => { # CSc3-c + Name => 'SelfTimerShotInterval', + Mask => 0x30, + PrintConv => { + 0 => '0.5 s', + 1 => '1 s', + 2 => '2 s', + 3 => '3 s', + }, + }, + 20.3 => { # CSc3-b + Name => 'SelfTimerShotCount', + Mask => 0x0f, + }, + 21.1 => { # CSc4-d + Name => 'ImageReviewMonitorOffTime', # note: decode changed from D4s + Mask => 0xe0, + PrintConv => { + 0 => '2 s', + 1 => '4 s', + 3 => '10 s', + 4 => '20 s', + 5 => '1 min', + 6 => '5 min', + 7 => '10 min', + }, + }, + 21.2 => { # CSc4-e # note: decode changed from D4s + Name => 'LiveViewMonitorOffTime', + Mask => 0x1c, + PrintConv => { + 1 => '5 min', + 2 => '10 min', + 3 => '15 min', + 4 => '20 min', + 5 => '30 min', + 6 => 'No Limit', + }, + }, + 22.1 => { # CSc4-b # note: decode changed from D4s + Name => 'MenuMonitorOffTime', + Mask => 0xe0, + PrintConv => { + 0 => '4 s', + 2 => '10 s', + 4 => '20 s', + 5 => '1 min', + 6 => '5 min', + 7 => '10 min', + }, + }, + 22.2 => { # CSc4-c # note: decode changed from D4s + Name => 'ShootingInfoMonitorOffTime', + Mask => 0x1c, + PrintConv => { + 0 => '4 s', + 2 => '10 s', + 4 => '20 s', + 5 => '1 min', + 6 => '5 min', + 7 => '10 min', + }, + }, + 23.1 => { # CSe1 + Name => 'FlashSyncSpeed', + Mask => 0xf0, + PrintConv => { + 0 => '1/320 s (auto FP)', + 2 => '1/250 s (auto FP)', + 3 => '1/250 s', + 5 => '1/200 s', + 6 => '1/160 s', + 7 => '1/125 s', + 8 => '1/100 s', + 9 => '1/80 s', + 10 => '1/60 s', + }, + }, + 23.2 => { # CSe2 + Name => 'FlashShutterSpeed', + Mask => 0x0f, + PrintConvColumns => 2, + PrintConv => { + 0 => '1/60 s', + 1 => '1/30 s', + 2 => '1/15 s', + 3 => '1/8 s', + 4 => '1/4 s', + 5 => '1/2 s', + 6 => '1 s', + 7 => '2 s', + 8 => '4 s', + 9 => '8 s', + 10 => '15 s', + 11 => '30 s', + }, + }, + 24.1 => { # CSe3 + Name => 'FlashControlBuilt-in', + Mask => 0xc0, + RawConv => '$$self{FlashControlBuiltin} = $val', + PrintConv => { + 0 => 'TTL', + 1 => 'Manual', + 2 => 'Repeating Flash', + 3 => 'Commander Mode', + }, + }, + 31.1 => { # CSe5 + Name => 'ModelingFlash', + Mask => 0x20, + PrintConv => \%onOff, + }, + 36.1 => { # CSc4-a + Name => 'PlaybackMonitorOffTime', + Mask => 0xe0, + PrintConv => { + 0 => '4 s', + 1 => '10 s', + 2 => '20 s', + 3 => '1 min', + 4 => '5 min', + 5 => '10 min', + }, + }, + 37.1 => { # CSf2-c + Name => 'MultiSelectorLiveView', + Mask => 0xc0, + PrintConv => { + 0 => 'Reset', + 1 => 'Zoom', + 3 => 'Not Used', + }, + }, + 38.1 => { # CSf7-a + Name => 'ShutterSpeedLock', + Mask => 0x80, + PrintConv => \%offOn, + }, + 38.2 => { # CSf7-b + Name => 'ApertureLock', + Mask => 0x40, + PrintConv => \%offOn, + }, + 38.3 => { # CSg4 + Name => 'MovieShutterButton', + Mask => 0x20, + PrintConv => { + 0 => 'Take Photo', + 1 => 'Record Movies', + }, + }, + 38.4 => { # CSe4 + Name => 'FlashExposureCompArea', + Mask => 0x04, + PrintConv => { + 0 => 'Entire frame', + 1 => 'Background only', + }, + }, + 40.1 => { # CSg3 + Name => 'MovieAELockButtonAssignment', + Mask => 0x0f, + PrintConv => { + 0 => 'None', + 3 => 'Index Marking', + 4 => 'View Photo Shooting Info', + 5 => 'AE/AF Lock', + 6 => 'AE Lock Only', + 7 => 'AE Lock (hold)', + 8 => 'AF Lock Only', + }, + }, + 41.1 => { # CSg1 + Name => 'MovieFunctionButton', + Mask => 0x70, + PrintConv => { + 0 => 'None', + 1 => 'Power Aperture (open)', # bit '02' is also toggled on for this setting + 3 => 'Index Marking', + 4 => 'View Photo Shooting Info', + }, + }, + 41.2 => { # CSg2 + Name => 'MoviePreviewButton', + Mask => 0x07, + PrintConv => { + 0 => 'None', + 2 => 'Power Aperture (open)', # bit '10' is also toggled on for this setting + 3 => 'Index Marking', + 4 => 'View Photo Shooting Info', + }, + }, + 42.1 => { # CSf4-b + Name => 'FuncButtonPlusDials', + Mask => 0x0f, + PrintConv => { + 0 => 'None', + 1 => 'Choose Image Area (FX/DX/5:4)', + 2 => 'Shutter Speed & Aperture Lock', + 3 => 'One Step Speed / Aperture', + 4 => 'Choose Non-CPU Lens Number', + 5 => 'Active D-Lighting', + 8 => 'Exposure Delay Mode', + }, + }, + 43.1 => { # CSf5-b + Name => 'PreviewButtonPlusDials', + Mask => 0x0f, + PrintConv => { + 0 => 'None', + 1 => 'Choose Image Area (FX/DX/5:4)', + 2 => 'Shutter Speed & Aperture Lock', + 3 => 'One Step Speed / Aperture', + 4 => 'Choose Non-CPU Lens Number', + 5 => 'Active D-Lighting', + 8 => 'Exposure Delay Mode', + }, + }, + 44.1 => { # CSf6-b + Name => 'AELockButtonPlusDials', + Mask => 0x0f, + PrintConv => { + 0 => 'None', + 1 => 'Choose Image Area (FX/DX/5:4)', + 2 => 'Shutter Speed & Aperture Lock', + 4 => 'Choose Non-CPU Lens Number', + 8 => 'Exposure Delay Mode', + }, + }, + 45.1 => { # CSf13 + Name => 'AssignMovieRecordButton', + Mask => 0x0f, + PrintConv => { + 0 => 'None', + 1 => 'Choose Image Area (FX/DX/5:4)', + 2 => 'Shutter Speed & Aperture Lock', + 9 => 'White Balance', + 10 => 'ISO Sensitivity', + }, + }, + 46.1 => { # CSb7-d + Name => 'FineTuneOptHighlightWeighted', + Mask => 0x0f, + ValueConv => '($val > 0x7 ? $val - 0x10 : $val) / 6', + ValueConvInv => 'int($val*6+($val>0?0.5:-0.5))', + PrintConv => '$val ? sprintf("%+.2f", $val) : 0', + PrintConvInv => 'Image::ExifTool::Exif::ConvertFraction($val)', + }, + 47.1 => { # CSa5-b + Name => 'DynamicAreaAFDisplay', + Mask => 0x80, + PrintConv => \%offOn, + }, + 47.2 => { # CSa5-a # moved with D810 + Name => 'AFPointIllumination', + Mask => 0x40, + PrintConv => { + 0 => 'Off', + 1 => 'On During Manual Focusing', + }, + }, + 47.3 => { # CSa9 + Name => 'StoreByOrientation', + Mask => 0x18, + PrintConv => { + 0 => 'Off', + 1 => 'Focus Point', + 2 => 'Focus Point and AF-area mode', + }, + }, + 47.4 => { # CSa5-c + Name => 'GroupAreaAFIllumination', + Mask => 0x04, + PrintConv => { + 0 => 'Squares', # moved with D810 + 1 => 'Dots', + }, + }, + 48.1 => { # CSb5 + Name => 'MatrixMetering', + Mask => 0x80, + PrintConv => { + 0 => 'Face Detection On', + 1 => 'Face Detection Off', + }, + }, + 48.2 => { # CSf14 + Name => 'LiveViewButtonOptions', + Mask => 0x30, + PrintConv => { + 0 => 'Enable', + 2 => 'Disable', + }, + }, + 48.3 => { # CSa12 + Name => 'AFModeRestrictions', + Mask => 0x03, + PrintConv => { + 0 => 'No Restrictions', + 1 => 'AF-C', + 2 => 'AF-S', + }, + }, + 49.1 => { # CSa11 + Name => 'LimitAFAreaModeSelection', + Mask => 0x7e, + PrintConv => { + 0 => 'No Restrictions', + BITMASK => { + 0 => 'Auto-area', + 1 => 'Group-area', + 2 => '3D-tracking', + 3 => 'Dynamic area (51 points)', + 4 => 'Dynamic area (21 points)', + 5 => 'Dynamic area (9 points)', + }, + }, + }, + 50.1 => { # CSf15 + Name => 'AF-OnForMB-D12', + Mask => 0x07, + PrintConv => { + 0 => 'AE/AF Lock', + 1 => 'AE Lock Only', + 2 => 'AF Lock Only', + 3 => 'AE Lock (hold)', + 4 => 'AE Lock (reset)', + 5 => 'AF-On', + 6 => 'FV Lock', + 7 => 'Same As Fn Button', + }, + }, + 51.1 => { # CSf16 + Name => 'AssignRemoteFnButton', + Mask => 0x1f, + PrintConv => { + 0 => 'None', + 1 => 'Preview', + 2 => 'FV Lock', + 3 => 'AE/AF Lock', + 4 => 'AE Lock Only', + 5 => 'AE Lock (reset on release)', + 7 => 'AF Lock Only', + 8 => 'AF-On', + 16 => '+NEF(RAW)', + 25 => 'Live View', + 26 => 'Flash Disable/Enable', + }, + }, + 52.1 => { # CSf17 + Name => 'LensFocusFunctionButtons', + Mask => 0x3f, + PrintConv => { + 3 => 'AE/AF Lock', + 4 => 'AE Lock Only', + 7 => 'AF Lock Only', + 21 => 'Disable Synchronized Release', + 22 => 'Remote Release Only', + 24 => 'Preset focus Point', + 26 => 'Flash Disable/Enable', + 32 => 'AF-Area Mode: Single-point AF', + 33 => 'AF-Area Mode: Dynamic-area AF (9 points)', + 34 => 'AF-Area Mode: Dynamic-area AF (21 points)', + 35 => 'AF-Area Mode: Dynamic-area AF (51 points)', + 36 => 'AF-Area Mode: Group-area AF', + 37 => 'AF-Area Mode: Auto area AF', + }, + }, +); + +# D850 custom settings (ref 1) +%Image::ExifTool::NikonCustom::SettingsD850 = ( + PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData, + WRITE_PROC => \&Image::ExifTool::WriteBinaryData, + CHECK_PROC => \&Image::ExifTool::CheckBinaryData, + WRITABLE => 1, + FIRST_ENTRY => 0, + GROUPS => { 0 => 'MakerNotes', 2 => 'Camera' }, + NOTES => 'Custom settings for the D850.', + 0.2 => { + Name => 'CustomSettingsBank', + Mask => 0x03, + PrintConv => { + 0 => 'A', + 1 => 'B', + 2 => 'C', + 3 => 'D', + }, + }, + 1.1 => { #CSa1 + Name => 'AF-CPrioritySelection', + Mask => 0xc0, + PrintConv => { + 0 => 'Release', + 1 => 'Release + Focus', + 2 => 'Focus', + 3 => 'Focus + Release', + }, + }, + 1.2 => { # CSa2 + Name => 'AF-SPrioritySelection', + Mask => 0x20, + PrintConv => { + 0 => 'Focus', + 1 => 'Release', + }, + }, + 1.3 => { # CSa6 + Name => 'AFPointSelection', + Mask => 0x10, + PrintConv => { + 0 => '55 Points', + 1 => '15 Points', + }, + }, + 1.4 => { # CSa4 + Name => 'Three-DTrackingFaceDetection', + Mask => 0x08, + PrintConv => \%offOn, + }, + 1.5 => { # CSa3-a + Name => 'BlockShotAFResponse', + Mask => 0x07, + PrintConv => { + 1 => '1 (Quick)', + 2 => '2', + 3 => '3 (Normal)', + 4 => '4', + 5 => '5 (Delay)', + }, + }, + 2.1 => { # CSa11 + Name => 'FocusPointWrap', + Mask => 0x08, + PrintConv => { + 0 => 'No Wrap', + 1 => 'Wrap', + }, + }, + 2.2 => { # CSa12-a + Name => 'AFPointBrightness', + Mask => 0x06, + PrintConv => { + 0 => 'Auto', + 1 => 'On', + 2 => 'Off', + }, + }, + 4.1 => { # CSd3 + Name => 'ISODisplay', + Mask => 0x08, + PrintConv => { + 0 => 'Show ISO Sensitivity', + 1 => 'Show Frame Count', + }, + }, + 4.2 => { # CSd9 + Name => 'GridDisplay', + Mask => 0x02, + PrintConv => \%onOff, + }, + 5.1 => { # CSd10 + Name => 'LCDIllumination', + Mask => 0x20, + PrintConv => \%offOn, + }, + 5.2 => { # CSd6 + Name => 'ElectronicFront-CurtainShutter', + Mask => 0x08, + PrintConv => \%offOn, + }, + 6.1 => { # CSf7 + Name => 'ReverseIndicators', + Mask => 0x80, + PrintConv => { + 0 => '+ 0 -', + 1 => '- 0 +', + }, + }, + 6.2 => { # CSf4-a + Name => 'CommandDialsReverseRotation', + Mask => 0x18, + PrintConv => { + 0 => 'No', + 1 => 'Shutter Speed & Aperture', + 2 => 'Exposure Compensation', + 3 => 'Exposure Compensation, Shutter Speed & Aperture', + }, + }, + 6.3 => { # CSb4 + Name => 'EasyExposureCompensation', + Mask => 0x03, + PrintConv => { + 0 => 'Off', + 1 => 'On', + 2 => 'On (Auto Reset)', + }, + }, + 7.1 => { # CSb2 + Name => 'ExposureControlStepSize', + Mask => 0xc0, + PrintConv => { + 0 => '1/3 EV', + 1 => '1/2 EV', + 2 => '1 EV', + }, + }, + 7.2 => { # CSb1 + Name => 'ISOStepSize', + Mask => 0x30, + PrintConv => { + 0 => '1/3 EV', + 1 => '1/2 EV', + 2 => '1 EV', + }, + }, + 7.3 => { # CSb3 + Name => 'ExposureCompStepSize', + Mask => 0x0c, + PrintConv => { + 0 => '1/3 EV', + 1 => '1/2 EV', + 2 => '1 EV', + }, + }, + 8.1 => { # CSb6 + Name => 'CenterWeightedAreaSize', + Mask => 0xe0, + PrintConv => { + 0 => '8 mm', + 1 => '12 mm', + 2 => '15 mm', + 3 => '20 mm', + 4 => 'Average', + }, + }, + 8.2 => { # CSb7-a + Name => 'FineTuneOptMatrixMetering', + Mask => 0x0f, + ValueConv => '($val > 0x7 ? $val - 0x10 : $val) / 6', + ValueConvInv => 'int($val*6+($val>0?0.5:-0.5))', + PrintConv => '$val ? sprintf("%+.2f", $val) : 0', + PrintConvInv => 'Image::ExifTool::Exif::ConvertFraction($val)', + }, + 9.1 => { # CSb7-b + Name => 'FineTuneOptCenterWeighted', + Mask => 0xf0, + ValueConv => '($val > 0x7 ? $val - 0x10 : $val) / 6', + ValueConvInv => 'int($val*6+($val>0?0.5:-0.5))', + PrintConv => '$val ? sprintf("%+.2f", $val) : 0', + PrintConvInv => 'Image::ExifTool::Exif::ConvertFraction($val)', + }, + 9.2 => { # CSb7-c + Name => 'FineTuneOptSpotMetering', + Mask => 0x0f, + ValueConv => '($val > 0x7 ? $val - 0x10 : $val) / 6', + ValueConvInv => 'int($val*6+($val>0?0.5:-0.5))', + PrintConv => '$val ? sprintf("%+.2f", $val) : 0', + PrintConvInv => 'Image::ExifTool::Exif::ConvertFraction($val)', + }, + 10.1 => { # CSf2-a + Name => 'MultiSelectorShootMode', + Mask => 0xe0, + PrintConv => { + 0 => 'Select Center Focus Point (Reset)', + 2 => 'Preset Focus Point (Pre)', + 3 => 'Highlight Active Focus Point', + 4 => 'Not Used (None)', + }, + }, + 10.2 => { # CSf2-b + Name => 'MultiSelectorPlaybackMode', + Mask => 0x0c, + PrintConv => { + 0 => 'Thumbnail On/Off', + 1 => 'View Histograms', + 2 => 'Zoom On/Off', + 3 => 'Choose Folder', + }, + }, + 10.3 => { # CSf5 + Name => 'MultiSelector', + Mask => 0x01, + PrintConv => { + 0 => 'Do Nothing', + 1 => 'Reset Meter-off Delay', + }, + }, + 11.1 => { # CSd5 + Name => 'ExposureDelayMode', + Mask => 0xe0, + PrintConv => { + 0 => 'Off', + 1 => '0.2 s', #new with the D850 + 2 => '0.5 s', #new with the D850 + 3 => '1 s', + 4 => '2 s', + 5 => '3 s', + }, + }, + 11.2 => { # CSd1 + Name => 'CLModeShootingSpeed', + Mask => 0x0f, + PrintConv => '"$val fps"', + PrintConvInv => '$val=~s/\s*fps//i; $val', + }, + 12.1 => { # CSd2 + Name => 'MaxContinuousRelease', + # values: 1-100 + }, + 13.1 => { # CSe7 + Name => 'AutoBracketOrder', + Mask => 0x10, + PrintConv => { + 0 => '0,-,+', + 1 => '-,0,+', + }, + }, + 13.2 => { # CSe6 + Name => 'AutoBracketModeM', + Mask => 0x0c, + PrintConv => { + 0 => 'Flash/Speed', + 1 => 'Flash/Speed/Aperture', + 2 => 'Flash/Aperture', + 3 => 'Flash Only', + }, + }, + 14.1 => { # CSf1-c + Name => 'Func1Button', + Mask => 0x3f, + PrintConv => { + 0 => 'None', + 1 => 'Preview', + 2 => 'FV Lock', + 3 => 'AE/AF Lock', + 4 => 'AE Lock Only', + 5 => 'AE Lock (reset on release)', + 6 => 'AE Lock (hold)', + 7 => 'AF Lock Only', + 8 => 'AF-On', + 10 => 'Bracketing Burst', + 11 => 'Matrix Metering', + 12 => 'Center-weighted Metering', + 13 => 'Spot Metering', + 14 => 'Playback', + 15 => 'My Menu Top Item', + 16 => '+NEF(RAW)', + 17 => 'Virtual Horizon', + 19 => 'Grid Display', + 20 => 'My Menu', + 22 => 'Remote Release Only', + 26 => 'Flash Disable/Enable', + 27 => 'Highlight-weighted Metering', + 36 => 'AF-Area Mode (Single)', + 37 => 'AF-Area Mode (Dynamic Area 25 Points)', + 38 => 'AF-Area Mode (Dynamic Area 72 Points)', + 39 => 'AF-Area Mode (Dynamic Area 153 Points)', + 40 => 'AF-Area Mode (Group Area AF)', + 41 => 'AF-Area Mode (Auto Area AF)', + 42 => 'AF-Area Mode + AF-On (Single)', + 43 => 'AF-Area Mode + AF-On (Dynamic Area 25 Points)', + 44 => 'AF-Area Mode + AF-On (Dynamic Area 72 Points)', + 45 => 'AF-Area Mode + AF-On (Dynamic Area 153 Points)', + 46 => 'AF-Area Mode + AF-On (Group Area AF)', + 47 => 'AF-Area Mode + AF-On (Auto Area AF)', + 49 => 'Sync Release (Master Only)', + 50 => 'Sync Release (Remote Only)', + 56 => 'AF-Area Mode (Dynamic Area 9 Points)', + 57 => 'AF-Area Mode + AF-On (Dynamic Area 9 Points)', + }, + }, + 15.1 => { # CSf1-a + Name => 'PreviewButton', + Mask => 0x3f, + PrintConv => { + 0 => 'None', + 1 => 'Preview', + 2 => 'FV Lock', + 3 => 'AE/AF Lock', + 4 => 'AE Lock Only', + 5 => 'AE Lock (reset on release)', + 6 => 'AE Lock (hold)', + 7 => 'AF Lock Only', + 8 => 'AF-On', + 10 => 'Bracketing Burst', + 11 => 'Matrix Metering', + 12 => 'Center-weighted Metering', + 13 => 'Spot Metering', + 14 => 'Playback', + 15 => 'My Menu Top Item', + 16 => '+NEF(RAW)', + 17 => 'Virtual Horizon', + 19 => 'Grid Display', + 20 => 'My Menu', + 22 => 'Remote Release Only', + 26 => 'Flash Disable/Enable', + 27 => 'Highlight-weighted Metering', + 36 => 'AF-Area Mode (Single)', + 37 => 'AF-Area Mode (Dynamic Area 25 Points)', + 38 => 'AF-Area Mode (Dynamic Area 72 Points)', + 39 => 'AF-Area Mode (Dynamic Area 153 Points)', + 40 => 'AF-Area Mode (Group Area AF)', + 41 => 'AF-Area Mode (Auto Area AF)', + 42 => 'AF-Area Mode + AF-On (Single)', + 43 => 'AF-Area Mode + AF-On (Dynamic Area 25 Points)', + 44 => 'AF-Area Mode + AF-On (Dynamic Area 72 Points)', + 45 => 'AF-Area Mode + AF-On (Dynamic Area 153 Points)', + 46 => 'AF-Area Mode + AF-On (Group Area AF)', + 47 => 'AF-Area Mode + AF-On (Auto Area AF)', + 49 => 'Sync Release (Master Only)', + 50 => 'Sync Release (Remote Only)', + 56 => 'AF-Area Mode (Dynamic Area 9 Points)', + 57 => 'AF-Area Mode + AF-On (Dynamic Area 9 Points)', + }, + }, + 16.1 => { # CSf1-j + Name => 'AssignBktButton', + Mask => 0x07, + PrintConv => { + 0 => 'Auto Bracketing', + 1 => 'Multiple Exposure', + 2 => 'HDR (high dynamic range)', + 3 => 'None', + }, + }, + 18.1 => { # CSf4-b + Name => 'CommandDialsChangeMainSub', + Mask => 0xe0, + PrintConv => { + 0 => 'Autofocus Off, Exposure Off', + 1 => 'Autofocus Off, Exposure On', + 2 => 'Autofocus Off, Exposure On (Mode A)', + 4 => 'Autofocus On, Exposure Off', + 5 => 'Autofocus On, Exposure On', + 6 => 'Autofocus On, Exposure On (Mode A)', + }, + }, + 18.2 => { # CSf4-d + Name => 'CommandDialsMenuAndPlayback', + Mask => 0x18, + PrintConv => { + 0 => 'On', + 1 => 'Off', + 2 => 'On (Image Review Excluded)', + }, + }, + 18.3 => { # CSf4-c + Name => 'CommandDialsApertureSetting', + Mask => 0x04, + PrintConv => { + 0 => 'Sub-command Dial', + 1 => 'Aperture Ring', + }, + }, + 18.4 => { # CSf6 + Name => 'ReleaseButtonToUseDial', + Mask => 0x01, + PrintConv => \%noYes, + }, + 19.1 => { # CSc2 + Name => 'StandbyTimer', + Mask => 0xf0, + PrintConv => { + 0 => '4 s', + 1 => '6 s', + 3 => '10 s', + 5 => '30 s', + 6 => '1 min', + 7 => '5 min', + 8 => '10 min', + 9 => '30 min', + 10 => 'No Limit', + }, + }, + 20.1 => { # CSc3-a + Name => 'SelfTimerTime', + Mask => 0xc0, + PrintConv => { + 0 => '2 s', + 1 => '5 s', + 2 => '10 s', + 3 => '20 s', + }, + }, + 20.2 => { # CSc3-c + Name => 'SelfTimerShotInterval', + Mask => 0x30, + PrintConv => { + 0 => '0.5 s', + 1 => '1 s', + 2 => '2 s', + 3 => '3 s', + }, + }, + 20.3 => { # CSc3-b + Name => 'SelfTimerShotCount', + Mask => 0x0f, + }, + 21.1 => { # CSc4-d + Name => 'ImageReviewMonitorOffTime', + Mask => 0xe0, + PrintConv => { + 0 => '2 s', + 1 => '4 s', + 3 => '10 s', + 4 => '20 s', + 5 => '1 min', + 6 => '5 min', + 7 => '10 min', + }, + }, + 21.2 => { # CSc4-e + Name => 'LiveViewMonitorOffTime', + Mask => 0x1c, + PrintConv => { + 1 => '5 min', + 2 => '10 min', + 3 => '15 min', + 4 => '20 min', + 5 => '30 min', + 6 => 'No Limit', + }, + }, + 22.1 => { # CSc4-b + Name => 'MenuMonitorOffTime', + Mask => 0xe0, + PrintConv => { + 0 => '4 s', + 2 => '10 s', + 4 => '20 s', + 5 => '1 min', + 6 => '5 min', + 7 => '10 min', + }, + }, + 22.2 => { # CSc4-c + Name => 'ShootingInfoMonitorOffTime', + Mask => 0x1c, + PrintConv => { + 0 => '4 s', + 2 => '10 s', + 4 => '20 s', + 5 => '1 min', + 6 => '5 min', + 7 => '10 min', + }, + }, + 23.1 => { # CSe1 + Name => 'FlashSyncSpeed', + Mask => 0xf0, + PrintConv => { + 2 => '1/250 s (auto FP)', + 3 => '1/250 s', + 5 => '1/200 s', + 6 => '1/160 s', + 7 => '1/125 s', + 8 => '1/100 s', + 9 => '1/80 s', + 10 => '1/60 s', + }, + }, + 23.2 => { # CSe2 + Name => 'FlashShutterSpeed', + Mask => 0x0f, + PrintConvColumns => 2, + PrintConv => { + 0 => '1/60 s', + 1 => '1/30 s', + 2 => '1/15 s', + 3 => '1/8 s', + 4 => '1/4 s', + 5 => '1/2 s', + 6 => '1 s', + 7 => '2 s', + 8 => '4 s', + 9 => '8 s', + 10 => '15 s', + 11 => '30 s', + }, + }, + 31.1 => { # CSe5 + Name => 'ModelingFlash', + Mask => 0x20, + PrintConv => \%onOff, + }, + 36.1 => { # CSc4-a + Name => 'PlaybackMonitorOffTime', + Mask => 0xe0, + PrintConv => { + 0 => '4 s', + 1 => '10 s', + 2 => '20 s', + 3 => '1 min', + 4 => '5 min', + 5 => '10 min', + }, + }, + 37.1 => { # CSf2-c + Name => 'MultiSelectorLiveView', + Mask => 0xc0, + PrintConv => { + 0 => 'Reset', + 1 => 'Zoom', + 3 => 'Not Used', + }, + }, + 38.1 => { # CSf3-a + Name => 'ShutterSpeedLock', + Mask => 0x80, + PrintConv => \%offOn, + }, + 38.2 => { # CSf3-b + Name => 'ApertureLock', + Mask => 0x40, + PrintConv => \%offOn, + }, + 38.3 => { # CSg1-h + Name => 'MovieShutterButton', + Mask => 0x10, + PrintConv => { + 0 => 'Take Photo', + 1 => 'Record Movies', + }, + }, + 38.4 => { # CSe3 + Name => 'FlashExposureCompArea', + Mask => 0x04, + PrintConv => { + 0 => 'Entire Frame', + 1 => 'Background Only', + }, + }, + 38.5 => { # CSe4 + Name => 'AutoFlashISOSensitivity', + Mask => 0x02, + PrintConv => { + 0 => 'Subject and Background', + 1 => 'Subject Only', + }, + }, + 41.1 => { # CSg1-c + Name => 'MovieFunc1Button', + Mask => 0xf0, + PrintConv => { + 0 => 'None', + 2 => 'Power Aperture (close)', + 3 => 'Index Marking', + 4 => 'View Photo Shooting Info', + 11 => 'Exposure Compensation -', + }, + }, + 41.2 => { # CSg1-a + Name => 'MoviePreviewButton', + Mask => 0x0f, + PrintConv => { + 0 => 'None', + 1 => 'Power Aperture (open)', + 3 => 'Index Marking', + 4 => 'View Photo Shooting Info', + 10 => 'Exposure Compensation +', + }, + }, + 42.1 => { # CSf1-d + Name => 'Func1ButtonPlusDials', + Mask => 0x0f, + PrintConv => { + 0 => 'None', + 1 => 'Choose Image Area', + 2 => 'Shutter Speed & Aperture Lock', + 3 => 'One Step Speed / Aperture', + 4 => 'Choose Non-CPU Lens Number', + 5 => 'Active D-Lighting', + 7 => 'Photo Shooting Menu Bank', + 8 => 'Exposure Delay Mode', + }, + }, + 43.1 => { # CSf1-b + Name => 'PreviewButtonPlusDials', + Mask => 0x0f, + PrintConv => { + 0 => 'None', + 1 => 'Choose Image Area', + 2 => 'Shutter Speed & Aperture Lock', + 3 => 'One Step Speed / Aperture', + 4 => 'Choose Non-CPU Lens Number', + 5 => 'Active D-Lighting', + 7 => 'Photo Shooting Menu Bank', + 8 => 'Exposure Delay Mode', + }, + }, + 45.1 => { # CSf1-k + Name => 'AssignMovieRecordButtonPlusDials', + Mask => 0x0f, + PrintConv => { + 0 => 'None', + 1 => 'Choose Image Area', + 2 => 'Shutter Speed & Aperture Lock', + 7 => 'Photo Shooting Menu Bank', + 11 => 'Exposure Mode', + }, + }, + 46.1 => { # CSb7-d + Name => 'FineTuneOptHighlightWeighted', + Mask => 0x0f, + ValueConv => '($val > 0x7 ? $val - 0x10 : $val) / 6', + ValueConvInv => 'int($val*6+($val>0?0.5:-0.5))', + PrintConv => '$val ? sprintf("%+.2f", $val) : 0', + PrintConvInv => 'Image::ExifTool::Exif::ConvertFraction($val)', + }, + 47.1 => { # CSa12-c + Name => 'DynamicAreaAFDisplay', + Mask => 0x80, + PrintConv => \%offOn, + }, + 47.2 => { # CSa12-b + Name => 'AFPointIllumination', + Mask => 0x40, + PrintConv => { + 0 => 'Off', + 1 => 'On During Manual Focusing', + }, + }, + 47.3 => { # CSa7 + Name => 'StoreByOrientation', + Mask => 0x18, + PrintConv => { + 0 => 'Off', + 1 => 'Focus Point', + 2 => 'Focus Point and AF-area Mode', + }, + }, + 48.1 => { # CSb5 + Name => 'MatrixMetering', + Mask => 0x80, + PrintConv => { + 0 => 'Face Detection On', + 1 => 'Face Detection Off', + }, + }, + 48.2 => { # CSf8 + Name => 'LiveViewButtonOptions', + Mask => 0x30, + PrintConv => { + 0 => 'Enable', + 1 => 'Enable (Standby Timer Active)', + 2 => 'Disable', + }, + }, + 48.3 => { # CSa10 + Name => 'AFModeRestrictions', + Mask => 0x03, + PrintConv => { + 0 => 'No Restrictions', + 1 => 'AF-C', + 2 => 'AF-S', + }, + }, + 49.1 => { # CSa9 + Name => 'LimitAFAreaModeSelection', #note that 'Dynamic area (9 points)' can be selected from the camera menu but the setting is not writen to the EXIF data. + Mask => 0x7e, #...This AF Mode was addded to the D5 firmware several months after the camera's initial release which may help explain the inconsistency. + PrintConv => { + 0 => 'No Restrictions', + BITMASK => { + 0 => 'Auto-area', + 1 => 'Group-area', + 2 => '3D-tracking', + 3 => 'Dynamic area (153 points)', + 4 => 'Dynamic area (72 points)', + 5 => 'Dynamic area (25 points)', + }, + }, + }, + 52.1 => { # CSf1-l + Name => 'LensFocusFunctionButtons', + Mask => 0x3f, + PrintConv => { + 3 => 'AE/AF Lock', + 4 => 'AE Lock Only', + 7 => 'AF Lock Only', + 8 => 'AF-On', + 24 => 'Preset Focus Point', + 26 => 'Flash Disable/Enable', + 36 => 'AF-Area Mode (Single)', + 37 => 'AF-Area Mode (Dynamic Area 25 Points)', + 38 => 'AF-Area Mode (Dynamic Area 72 Points)', + 39 => 'AF-Area Mode (Dynamic Area 153 Points)', + 40 => 'AF-Area Mode (Group Area AF)', + 41 => 'AF-Area Mode (Auto Area AF)', + 42 => 'AF-Area Mode + AF-On (Single)', + 43 => 'AF-Area Mode + AF-On (Dynamic Area 25 Points)', + 44 => 'AF-Area Mode + AF-On (Dynamic Area 72 Points)', + 45 => 'AF-Area Mode + AF-On (Dynamic Area 153 Points)', + 46 => 'AF-Area Mode + AF-On (Group Area AF)', + 47 => 'AF-Area Mode + AF-On (Auto Area AF)', + 49 => 'Sync Release (Master Only)', + 50 => 'Sync Release (Remote Only)', + 56 => 'AF-Area Mode (Dynamic Area 9 Points)', + 57 => 'AF-Area Mode + AF-On (Dynamic Area 9 Points)', + }, + }, + 66.1 => { # CSf10-d + Name => 'VerticalMultiSelector', + Mask => 0xff, + PrintHex => 1, + PrintConv => { + 0x00 => 'Same as Multi-Selector with Info(U/D) & Playback(R/L)', + 0x08 => 'Same as Multi-Selector with Info(R/L) & Playback(U/D)', + 0x80 => 'Focus Point Selection', + }, + }, + 67.1 => { # CSf10-a + Name => 'AssignMB-D18FuncButton', + Mask => 0x3f, + PrintConv => { + 0 => 'None', + 1 => 'Preview', + 2 => 'FV Lock', + 3 => 'AE/AF Lock', + 4 => 'AE Lock Only', + 5 => 'AE Lock (reset on release)', + 6 => 'AE Lock (hold)', + 7 => 'AF Lock Only', + 8 => 'AF-On', + 10 => 'Bracketing Burst', + 11 => 'Matrix Metering', + 12 => 'Center-weighted Metering', + 13 => 'Spot Metering', + 14 => 'Playback', + 15 => 'My Menu Top Item', + 16 => '+NEF(RAW)', + 17 => 'Virtual Horizon', + 18 => 'Reset Focus Point', + 19 => 'Grid Display', + 20 => 'My Menu', + 22 => 'Remote Release Only', + 23 => 'Preset Focus Point', + 26 => 'Flash Disable/Enable', + 27 => 'Highlight-weighted Metering', + 36 => 'AF-Area Mode (Single)', + 37 => 'AF-Area Mode (Dynamic Area 25 Points)', + 38 => 'AF-Area Mode (Dynamic Area 72 Points)', + 39 => 'AF-Area Mode (Dynamic Area 153 Points)', + 40 => 'AF-Area Mode (Group Area AF)', + 41 => 'AF-Area Mode (Auto Area AF)', + 42 => 'AF-Area Mode + AF-On (Single)', + 43 => 'AF-Area Mode + AF-On (Dynamic Area 25 Points)', + 44 => 'AF-Area Mode + AF-On (Dynamic Area 72 Points)', + 45 => 'AF-Area Mode + AF-On (Dynamic Area 153 Points)', + 46 => 'AF-Area Mode + AF-On (Group Area AF)', + 47 => 'AF-Area Mode + AF-On (Auto Area AF)', + 49 => 'Sync Release (Master Only)', + 50 => 'Sync Release (Remote Only)', + 54 => 'Highlight Active Focus Point', + 56 => 'AF-Area Mode (Dynamic Area 9 Points)', + 57 => 'AF-Area Mode + AF-On (Dynamic Area 9 Points)', + }, + }, + 68.1 => { # CSf10-b + Name => 'AssignMB-D18FuncButtonPlusDials', + Mask => 0x0f, + PrintConv => { + 0 => 'None', + 1 => 'Choose Image Area', + 2 => 'Shutter Speed & Aperture Lock', + 3 => 'One Step Speed / Aperture', + 4 => 'Choose Non-CPU Lens Number', + 5 => 'Active D-Lighting', + 7 => 'Photo Shooting Menu Bank', + 8 => 'Exposure Delay Mode', + 10 => 'ISO Sensitivity', + 11 => 'Exposure Mode', + 12 => 'Exposure Compensation', + 13 => 'Metering Mode', + }, + }, + 70.1 => { # CSf1-f + Name => 'AF-OnButton', + Mask => 0x3f, + PrintConv => { + 0 => 'None', + 3 => 'AE/AF Lock', + 4 => 'AE Lock Only', + 5 => 'AE Lock (reset on release)', + 6 => 'AE Lock (hold)', + 7 => 'AF Lock Only', + 8 => 'AF-On', + 36 => 'AF-Area Mode (Single)', + 37 => 'AF-Area Mode (Dynamic Area 25 Points)', + 38 => 'AF-Area Mode (Dynamic Area 72 Points)', + 39 => 'AF-Area Mode (Dynamic Area 153 Points)', + 40 => 'AF-Area Mode (Group Area AF)', + 41 => 'AF-Area Mode (Auto Area AF)', + 42 => 'AF-Area Mode + AF-On (Single)', + 43 => 'AF-Area Mode + AF-On (Dynamic Area 25 Points)', + 44 => 'AF-Area Mode + AF-On (Dynamic Area 72 Points)', + 45 => 'AF-Area Mode + AF-On (Dynamic Area 153 Points)', + 46 => 'AF-Area Mode + AF-On (Group Area AF)', + 47 => 'AF-Area Mode + AF-On (Auto Area AF)', + 56 => 'AF-Area Mode (Dynamic Area 9 Points)', + 57 => 'AF-Area Mode + AF-On (Dynamic Area 9 Points)', + }, + }, + 71.1 => { # CSf1-g + Name => 'SubSelector', + Mask => 0x80, + PrintConv => { + 0 => 'Focus Point Selection', + 1 => 'Same as MultiSelector', + }, + }, + 72.1 => { # CSf1-h + Name => 'SubSelectorCenter', + Mask => 0x3f, + PrintConv => { + 0 => 'None', + 1 => 'Preview', + 2 => 'FV Lock', + 3 => 'AE/AF Lock', + 4 => 'AE Lock Only', + 5 => 'AE Lock (reset on release)', + 6 => 'AE Lock (hold)', + 7 => 'AF Lock Only', + 8 => 'AF-On', + 10 => 'Bracketing Burst', + 11 => 'Matrix Metering', + 12 => 'Center-weighted Metering', + 13 => 'Spot Metering', + 14 => 'Playback', + 15 => 'My Menu Top Item', + 16 => '+NEF(RAW)', + 17 => 'Virtual Horizon', + 18 => 'Reset Focus Point', + 19 => 'Grid Display', + 20 => 'My Menu', + 22 => 'Remote Release Only', + 23 => 'Preset Focus Point', + 26 => 'Flash Disable/Enable', + 27 => 'Highlight-weighted Metering', + 36 => 'AF-Area Mode (Single)', + 37 => 'AF-Area Mode (Dynamic Area 25 Points)', + 38 => 'AF-Area Mode (Dynamic Area 72 Points)', + 39 => 'AF-Area Mode (Dynamic Area 153 Points)', + 40 => 'AF-Area Mode (Group Area AF)', + 41 => 'AF-Area Mode (Auto Area AF)', + 42 => 'AF-Area Mode + AF-On (Single)', + 43 => 'AF-Area Mode + AF-On (Dynamic Area 25 Points)', + 44 => 'AF-Area Mode + AF-On (Dynamic Area 72 Points)', + 45 => 'AF-Area Mode + AF-On (Dynamic Area 153 Points)', + 46 => 'AF-Area Mode + AF-On (Group Area AF)', + 47 => 'AF-Area Mode + AF-On (Auto Area AF)', + 49 => 'Sync Release (Master Only)', + 50 => 'Sync Release (Remote Only)', + 54 => 'Highlight Active Focus Point', + 56 => 'AF-Area Mode (Dynamic Area 9 Points)', + 57 => 'AF-Area Mode + AF-On (Dynamic Area 9 Points)', + }, + }, + 73.1 => { # CSf1-i + Name => 'SubSelectorPlusDials', + Mask => 0x0f, + PrintConv => { + 0 => 'None', + 1 => 'Choose Image Area', + 2 => 'Shutter Speed & Aperture Lock', + 4 => 'Choose Non-CPU Lens Number', + 7 => 'Photo Shooting Menu Bank', + }, + }, + 74.1 => { # CSg1-f + Name => 'AssignMovieSubselector', + Mask => 0xf0, + PrintConv => { + 0 => 'None', + 3 => 'Index Marking', + 4 => 'View Photo Shooting Info', + 5 => 'AE/AF Lock', + 6 => 'AE Lock (Only)', + 7 => 'AE Lock (Hold)', + 8 => 'AF Lock (Only)', + }, + }, + 75.1 => { # CSg1-d + Name => 'AssignMovieFunc1ButtonPlusDials', + Mask => 0x10, + PrintConv => { + 0 => 'None', + 1 => 'Choose Image Area', + }, + }, + 75.2 => { # CSg1-b + Name => 'AssignMoviePreviewButtonPlusDials', + Mask => 0x01, + PrintConv => { + 0 => 'None', + 1 => 'Choose Image Area', + }, + }, + 76.1 => { # CSg1-g + Name => 'AssignMovieSubselectorPlusDials', + Mask => 0x10, + PrintConv => { + 0 => 'None', + 1 => 'Choose Image Area', + }, + }, + 77.1 => { # CSd4 + Name => 'SyncReleaseMode', + Mask => 0x80, + PrintConv => { + 0 => 'No Sync', + 1 => 'Sync', + }, + }, + 77.2 => { # CSd11 (new with D850) + Name => 'ContinuousModeLiveView', + Mask => 0x40, + PrintConv => \%offOn, + }, + 78.1 => { # CSa5 + Name => 'Three-DTrackingWatchArea', + Mask => 0x80, + PrintConv => { + 0 => 'Wide', + 1 => 'Normal', + }, + }, + 78.2 => { # CSa3-b + Name => 'SubjectMotion', + Mask => 0x60, + PrintConv => { + 0 => 'Steady', + 1 => 'Middle', + 2 => 'Erratic', + }, + }, + 78.3 => { # CSa8 + Name => 'AFActivation', + Mask => 0x08, + PrintConv => { + 0 => 'Shutter/AF-On', + 1 => 'AF-On Only', + }, + }, + 78.4 => { # CSc1 + Name => 'ShutterReleaseButtonAE-L', + Mask => 0x03, + PrintConv => { + 0 => 'Off', + 1 => 'On (Half Press)', + 2 => 'On (Burst Mode)' + }, + }, + 79.1 => { # CSf10-c + Name => 'AssignMB-D18AF-OnButton', + Mask => 0x7f, + PrintConv => { + 0 => 'None', + 3 => 'AE/AF Lock', + 4 => 'AE Lock Only', + 5 => 'AE Lock (reset on release)', + 6 => 'AE Lock (hold)', + 7 => 'AF Lock Only', + 8 => 'AF-On', + 36 => 'AF-Area Mode (Single)', + 37 => 'AF-Area Mode (Dynamic Area 25 Points)', + 38 => 'AF-Area Mode (Dynamic Area 72 Points)', + 39 => 'AF-Area Mode (Dynamic Area 153 Points)', + 40 => 'AF-Area Mode (Group Area AF)', + 41 => 'AF-Area Mode (Auto Area AF)', + 42 => 'AF-Area Mode + AF-On (Single)', + 43 => 'AF-Area Mode + AF-On (Dynamic Area 25 Points)', + 44 => 'AF-Area Mode + AF-On (Dynamic Area 72 Points)', + 45 => 'AF-Area Mode + AF-On (Dynamic Area 153 Points)', + 46 => 'AF-Area Mode + AF-On (Group Area AF)', + 47 => 'AF-Area Mode + AF-On (Auto Area AF)', + 56 => 'AF-Area Mode (Dynamic Area 9 Points)', + 57 => 'AF-Area Mode + AF-On (Dynamic Area 9 Points)', + 100 => 'Same as Camera AF-On Button', + }, + }, + 80.1 => { # CSf1-e + Name => 'Func2Button', + Mask => 0x3f, + PrintConv => { + 0 => 'None', + 15 => 'My Menu Top Item', + 20 => 'My Menu', + 55 => 'Rating', + }, + }, + 82.1 => { # CSg1-e + Name => 'AssignMovieFunc2Button', + Mask => 0x70, + PrintConv => { + 0 => 'None', + 3 => 'Index Marking', + 4 => 'View Photo Shooting Info', + }, + }, +); + +# D5000 custom settings (ref PH) +%Image::ExifTool::NikonCustom::SettingsD5000 = ( + PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData, + WRITE_PROC => \&Image::ExifTool::WriteBinaryData, + CHECK_PROC => \&Image::ExifTool::CheckBinaryData, + WRITABLE => 1, + FIRST_ENTRY => 0, + GROUPS => { 0 => 'MakerNotes', 2 => 'Camera' }, + NOTES => 'Custom settings for the D5000.', + # Missing/Incomplete settings: + # CSd7 - LiveViewDisplayOptions [couldn't find in data - try again with live view shots] + 0.1 => { # CSa1 + Name => 'AFAreaModeSetting', + Mask => 0x60, + PrintConv => { + 0 => 'Single Area', + 1 => 'Dynamic Area', + 2 => 'Auto-area', + 3 => '3D-tracking (11 points)', + }, + }, + 0.2 => { # CSa2 + Name => 'AFAssist', + Mask => 0x01, + PrintConv => \%onOff, + }, + 2.1 => { # CSd1 + Name => 'Beep', + Mask => 0xc0, + PrintConv => { + 0 => 'Off', + 1 => 'Low', + 2 => 'High', + }, + }, + 2.2 => { # CSd2 + Name => 'GridDisplay', + Mask => 0x02, + PrintConv => \%onOff, + }, + 2.3 => { # CSd3 + Name => 'ISODisplay', + Mask => 0x08, + PrintConv => \%onOff, + }, + 2.4 => { # CSf4 + Name => 'NoMemoryCard', + Mask => 0x20, + PrintConv => { + 0 => 'Release Locked', + 1 => 'Enable Release', + }, + }, + 3.1 => { # CSd4 + Name => 'FileNumberSequence', + Mask => 0x08, + PrintConv => \%onOff, + }, + 4.1 => { # CSa4 + Name => 'RangeFinder', + Mask => 0x10, + PrintConv => \%offOn, + }, + 4.2 => { # CSd6 + Name => 'DateImprint', + Mask => 0x08, + PrintConv => \%offOn, + }, + 4.3 => { # CSf5 + Name => 'ReverseIndicators', + Mask => 0x80, + PrintConv => { + 0 => '+ 0 -', + 1 => '- 0 +', + }, + }, + 5.1 => { # CSb1 + Name => 'EVStepSize', + Mask => 0x40, + PrintConv => { + 0 => '1/3 EV', + 1 => '1/2 EV', + }, + }, + 9.1 => { # CSd5 + Name => 'ExposureDelayMode', + Mask => 0x40, + PrintConv => \%offOn, + }, + 11.1 => { # CSe2 + Name => 'AutoBracketSet', + Mask => 0xc0, + PrintConv => { + 0 => 'Exposure', + # (NOTE: the following are reversed in the D5100 -- is this correct?) + 1 => 'Active D-Lighting', #(NC) + 2 => 'WB Bracketing', + }, + }, + 12.1 => { # CSf1 + Name => 'TimerFunctionButton', + Mask => 0x38, + PrintConv => { + 0 => 'Self-timer', + 1 => 'Release Mode', + 2 => 'Image Quality/Size', #(NC) + 3 => 'ISO', #(NC) + 4 => 'White Balance', #(NC) + 5 => 'Active D-Lighting', #(NC) + 6 => '+ NEF (RAW)', + 7 => 'Auto Bracketing', + }, + }, + 15.1 => { # CSf2 + Name => 'AELockButton', + Mask => 0x38, + PrintConv => { + 0 => 'AE/AF Lock', + 1 => 'AE Lock Only', #(NC) + 2 => 'AF Lock Only', #(NC) + 3 => 'AE Lock (hold)', + 4 => 'AF-ON', + }, + }, + 16.1 => { # CSc1 + Name => 'ShutterReleaseButtonAE-L', + Mask => 0x02, + PrintConv => \%offOn, + }, + 16.2 => { # CSf3 + Name => 'CommandDialsReverseRotation', + Mask => 0x80, + PrintConv => \%noYes, + }, + 17.1 => { # CSc2-c + Name => 'MeteringTime', + Mask => 0x70, + PrintConv => { + 0 => '4 s', + 1 => '8 s', + 2 => '20 s', + 3 => '1 min', + 4 => '30 min', + }, + }, + 17.2 => { # CSc4 + Name => 'RemoteOnDuration', + Mask => 0x03, + PrintConv => { + 0 => '1 min', + 1 => '5 min', + 2 => '10 min', + 3 => '15 min', + }, + }, + 18.1 => { # CSc3-a + Name => 'SelfTimerTime', + Mask => 0xc0, + PrintConv => { + 0 => '2 s', + 1 => '5 s', + 2 => '10 s', + 3 => '20 s', + }, + }, + 18.2 => { # CSc3-b + Name => 'SelfTimerShotCount', + Mask => 0x1e, + }, + 19.1 => { # CSc2-b + Name => 'ImageReviewTime', + Mask => 0xe0, + PrintConv => { + 0 => '4 s', + 1 => '8 s', + 2 => '20 s', + 3 => '1 min', + 4 => '10 min', + }, + }, + 20.1 => { # CSc2-a + Name => 'PlaybackMenusTime', + Mask => 0xe0, + PrintConv => { + 0 => '8 s', + 1 => '12 s', + 2 => '20 s', + 3 => '1 min', + 4 => '10 min', + }, + }, + 22.1 => { # CSe1-a + Name => 'InternalFlash', + Mask => 0xc0, + PrintConv => { + 0 => 'TTL', + 1 => 'Manual', + }, + }, + 22.2 => { # CSe1-b + Name => 'ManualFlashOutput', + Mask => 0x1f, + ValueConv => '2 ** (-$val/3)', + ValueConvInv => '$val > 0 ? -3*log($val)/log(2) : 0', + PrintConv => q{ + return 'Full' if $val > 0.99; + Image::ExifTool::Exif::PrintExposureTime($val); + }, + PrintConvInv => '$val=~/F/i ? 1 : Image::ExifTool::Exif::ConvertFraction($val)', + }, + 32.1 => { # CSa3 + Name => 'LiveViewAF', + Mask => 0x60, + PrintConv => { + 0 => 'Face Priority', + 1 => 'Wide Area', + 2 => 'Normal Area', + 3 => 'Subject Tracking', + }, + }, +); + +# D5100 custom settings (ref PH) +%Image::ExifTool::NikonCustom::SettingsD5100 = ( + PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData, + WRITE_PROC => \&Image::ExifTool::WriteBinaryData, + CHECK_PROC => \&Image::ExifTool::CheckBinaryData, + WRITABLE => 1, + FIRST_ENTRY => 0, + GROUPS => { 0 => 'MakerNotes', 2 => 'Camera' }, + NOTES => 'Custom settings for the D5100.', + 0.1 => { # CSa1 + Name => 'AF-CPrioritySelection', + Mask => 0x80, + PrintConv => { + 0 => 'Release', + 1 => 'Focus', + }, + }, + 1.1 => { # CSa2 + Name => 'AFAssist', + Mask => 0x01, + PrintConv => \%onOff, + }, + 3.1 => { # CSd1 + Name => 'Beep', + Mask => 0xc0, + PrintConv => { + 0 => 'Off', + 1 => 'Low', + 2 => 'High', + }, + }, + 3.2 => { # CSf4 + Name => 'NoMemoryCard', + Mask => 0x20, + PrintConv => { + 0 => 'Release Locked', + 1 => 'Enable Release', + }, + }, + 3.3 => { # CSd2 + Name => 'ISODisplay', + Mask => 0x08, + PrintConv => \%onOff, + }, + 4.1 => { # CSd3 + Name => 'FileNumberSequence', + Mask => 0x08, + PrintConv => \%onOff, + }, + 5.1 => { # CSa3 + Name => 'RangeFinder', + Mask => 0x10, + PrintConv => \%offOn, + }, + # (it looks like CSd5 DateImprint is not stored) + 5.2 => { # CSf5 + Name => 'ReverseIndicators', + Mask => 0x80, + PrintConv => { + 0 => '+ 0 -', + 1 => '- 0 +', + }, + }, + 6.1 => { # CSb1 + Name => 'EVStepSize', + Mask => 0x40, + PrintConv => { + 0 => '1/3 EV', + 1 => '1/2 EV', + }, + }, + 10.1 => { # CSd4 + Name => 'ExposureDelayMode', + Mask => 0x40, + PrintConv => \%offOn, + }, + 12.1 => { # CSe2 + Name => 'AutoBracketSet', + Mask => 0xc0, + PrintConv => { + 0 => 'Exposure', + # (NOTE: the following are reversed from the D5000 -- is D5000 correct?) + 1 => 'WB Bracketing', + 2 => 'Active D-Lighting', + }, + }, + 13.1 => { # CSf1 + Name => 'TimerFunctionButton', + Mask => 0x38, + PrintConv => { + 0 => 'Self-timer', + 1 => 'Release Mode', + 2 => 'Image Quality/Size', + 3 => 'ISO', + 4 => 'White Balance', + 5 => 'Active D-Lighting', + 6 => '+ NEF (RAW)', + 7 => 'Auto Bracketing', + }, + }, + 16.1 => { # CSf2 + Name => 'AELockButton', + Mask => 0x38, + PrintConv => { + 0 => 'AE/AF Lock', + 1 => 'AE Lock Only', + 2 => 'AF Lock Only', + 3 => 'AE Lock (hold)', + 4 => 'AF-ON', + }, + }, + 17.1 => { # CSc1 + Name => 'ShutterReleaseButtonAE-L', + Mask => 0x02, + PrintConv => \%offOn, + }, + 17.2 => { # CSf3 + Name => 'CommandDialsReverseRotation', + Mask => 0x80, + PrintConv => \%noYes, + }, + 18.1 => { # CSc2-d + Name => 'MeteringTime', + Mask => 0x70, + PrintConv => { + 0 => '4 s', + 1 => '8 s', + 2 => '20 s', #(NC) + 3 => '1 min', + 4 => '30 min', #(NC) + }, + }, + 18.2 => { # CSc4 + Name => 'RemoteOnDuration', + Mask => 0x03, + PrintConv => { + 0 => '1 min', + 1 => '5 min', + 2 => '10 min', #(NC) + 3 => '20 min', # (but picture in manual shows 15 min) + }, + }, + 19.1 => { # CSc3-a + Name => 'SelfTimerTime', + Mask => 0xc0, + PrintConv => { + 0 => '2 s', + 1 => '5 s', + 2 => '10 s', + 3 => '20 s', + }, + }, + 19.2 => { # CSc3-b + Name => 'SelfTimerShotCount', + Mask => 0x0f, + }, + 20.1 => { # CSc2-b + Name => 'ImageReviewTime', + Mask => 0xe0, + PrintConv => { + 0 => '4 s', + 1 => '8 s', #(NC) + 2 => '20 s', + 3 => '1 min', #(NC) + 4 => '10 min', #(NC) + }, + }, + 20.2 => { # CSc2-c + Name => 'LiveViewMonitorOffTime', + Mask => 0x1c, + PrintConv => { + 0 => '3 min', + 1 => '5 min', #(NC) + 2 => '10 min', + 3 => '15 min', #(NC) + 4 => '20 min', #(NC) + 5 => '30 min', #(NC) + }, + }, + 21.1 => { # CSc2-a + Name => 'PlaybackMenusTime', + Mask => 0xe0, + PrintConv => { + 0 => '8 s', #(NC) + 1 => '12 s', + 2 => '20 s', + 3 => '1 min', + 4 => '10 min', #(NC) + }, + }, + 23.1 => { # CSe1-a + Name => 'InternalFlash', + Mask => 0xc0, + PrintConv => { + 0 => 'TTL', + 1 => 'Manual', + }, + }, + 23.1 => { # CSe1-b + Name => 'ManualFlashOutput', + Mask => 0x1f, + ValueConv => '2 ** (-$val/3)', + ValueConvInv => '$val > 0 ? -3*log($val)/log(2) : 0', + PrintConv => q{ + return 'Full' if $val > 0.99; + Image::ExifTool::Exif::PrintExposureTime($val); + }, + PrintConvInv => '$val=~/F/i ? 1 : Image::ExifTool::Exif::ConvertFraction($val)', + }, +); + +# D5200 custom settings (ref PH) +%Image::ExifTool::NikonCustom::SettingsD5200 = ( + PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData, + WRITE_PROC => \&Image::ExifTool::WriteBinaryData, + CHECK_PROC => \&Image::ExifTool::CheckBinaryData, + WRITABLE => 1, + FIRST_ENTRY => 0, + GROUPS => { 0 => 'MakerNotes', 2 => 'Camera' }, + NOTES => 'Custom settings for the D5200.', + 0.1 => { # CSa1 + Name => 'AF-CPrioritySelection', + Mask => 0x80, + PrintConv => { + 0 => 'Release', + 1 => 'Focus', + }, + }, + 0.2 => { # CSa2 + Name => 'NumberOfFocusPoints', + Mask => 0x10, + PrintConv => { + 0 => '39 Points', + 1 => '11 Points', + }, + }, + 1.1 => { # CSa3 + Name => 'AFAssist', + Mask => 0x01, + PrintConv => \%onOff, + }, + 3.1 => { # CSd1 + Name => 'Beep', + Mask => 0xc0, + PrintConv => { + 0 => 'Off', + 1 => 'Low', + 2 => 'High', + }, + }, + 3.2 => { # CSf4 + Name => 'NoMemoryCard', + Mask => 0x20, + PrintConv => { + 0 => 'Release Locked', + 1 => 'Enable Release', + }, + }, + 3.3 => { # CSd3 + Name => 'ISODisplay', + Mask => 0x08, + PrintConv => \%onOff, + }, + 4.1 => { # CSd3 + Name => 'FileNumberSequence', + Mask => 0x08, + PrintConv => \%onOff, + }, + 5.1 => { # CSa4 + Name => 'RangeFinder', + Mask => 0x04, + PrintConv => \%offOn, + }, + 5.2 => { # CSf3-a + Name => 'ReverseExposureCompDial', + Mask => 0x10, + PrintConv => \%noYes, + }, + 5.3 => { # CSf3-b + Name => 'ReverseShutterSpeedAperture', + Mask => 0x08, + PrintConv => \%noYes, + }, + 5.4 => { # CSf5 + Name => 'ReverseIndicators', + Mask => 0x80, + PrintConv => { + 0 => '+ 0 -', + 1 => '- 0 +', + }, + }, + 6.1 => { # CSb1 + Name => 'EVStepSize', + Mask => 0x40, # (bit 0x04 also changes) + PrintConv => { + 0 => '1/3 EV', + 1 => '1/2 EV', + }, + }, + 10.1 => { # CSd5 + Name => 'ExposureDelayMode', + Mask => 0x40, + PrintConv => { 0 => 'Off', 1 => 'On' }, + }, + 12.1 => { # CSe2 + Name => 'AutoBracketSet', + Mask => 0xc0, + PrintConv => { + 0 => 'Exposure', + # (NOTE: the following are reversed from the D5000 -- is D5000 correct?) + 1 => 'WB Bracketing', + 2 => 'Active D-Lighting', + }, + }, + 13.1 => { # CSf1 + Name => 'FunctionButton', + Mask => 0x1f, + PrintConv => { + 3 => 'AE/AF Lock', + 4 => 'AE Lock Only', + 6 => 'AE Lock (hold)', + 7 => 'AF Lock Only', + 8 => 'AF-ON', + 16 => '+ NEF (RAW)', + 18 => 'Active D-Lighting', + 25 => 'Live View', + 26 => 'Image Quality', + 27 => 'ISO', + 28 => 'White Balance', + 29 => 'HDR', + 30 => 'Auto Bracketing', + 31 => 'AF-area Mode', + }, + }, + 16.1 => { # CSf2 + Name => 'AELockButton', + Mask => 0x0f, + PrintConv => { + 3 => 'AE/AF Lock', + 4 => 'AE Lock Only', + 6 => 'AE Lock (hold)', + 7 => 'AF Lock Only', + 8 => 'AF-ON', + }, + }, + 17.1 => { # CSc1 + Name => 'ShutterReleaseButtonAE-L', + Mask => 0x02, + PrintConv => \%offOn, + }, + 18.1 => { # CSc2-d + Name => 'StandbyTimer', + Mask => 0xe0, + PrintConv => { + 0 => '4 s', + 1 => '8 s', + 2 => '20 s', + 3 => '1 min', + 4 => '30 min', + }, + }, + 18.2 => { # CSc4 + Name => 'RemoteOnDuration', + Mask => 0x03, + PrintConv => { + 0 => '1 min', + 1 => '5 min', + 2 => '10 min', + 3 => '15 min', + }, + }, + 19.1 => { # CSc3-a + Name => 'SelfTimerTime', + Mask => 0xc0, + PrintConv => { + 0 => '2 s', + 1 => '5 s', + 2 => '10 s', + 3 => '20 s', + }, + }, + 19.2 => { # CSc3-b + Name => 'SelfTimerShotCount', + Mask => 0x0f, + }, + 20.1 => { # CSc2-b + Name => 'ImageReviewTime', + Mask => 0xe0, + PrintConv => { + 1 => '4 s', + 2 => '8 s', + 4 => '20 s', + 5 => '1 min', + 7 => '10 min', + }, + }, + 20.2 => { # CSc2-c + Name => 'LiveViewMonitorOffTime', + Mask => 0x1c, + PrintConv => { + 1 => '5 min', + 2 => '10 min', + 3 => '15 min', + 4 => '20 min', + 5 => '30 min', + }, + }, + 21.1 => { # CSc2-a + Name => 'PlaybackMenusTime', + Mask => 0xe0, + PrintConv => { + 1 => '8 s', + 4 => '20 s', + 5 => '1 min', + 6 => '5 min', + 7 => '10 min', + }, + }, + 23.1 => { # CSe1-a + Name => 'InternalFlash', + Mask => 0xc0, + PrintConv => { + 0 => 'TTL', + 1 => 'Manual', + }, + }, + 23.2 => { # CSe1-b + Name => 'ManualFlashOutput', + Mask => 0x1f, + ValueConv => '2 ** (-$val/3)', + ValueConvInv => '$val > 0 ? -3*log($val)/log(2) : 0', + PrintConv => q{ + return 'Full' if $val > 0.99; + Image::ExifTool::Exif::PrintExposureTime($val); + }, + PrintConvInv => '$val=~/F/i ? 1 : Image::ExifTool::Exif::ConvertFraction($val)', + }, +); + +# D7000 custom settings (ref 2) +%Image::ExifTool::NikonCustom::SettingsD7000 = ( + PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData, + WRITE_PROC => \&Image::ExifTool::WriteBinaryData, + CHECK_PROC => \&Image::ExifTool::CheckBinaryData, + WRITABLE => 1, + FIRST_ENTRY => 0, + DATAMEMBER => [ 23.1 ], + GROUPS => { 0 => 'MakerNotes', 2 => 'Camera' }, + NOTES => 'Custom settings for the D7000.', + 0.1 => { # CSa1 + Name => 'AF-CPrioritySelection', + Mask => 0x80, + PrintConv => { + 0 => 'Release', + 1 => 'Focus', + }, + }, + 0.2 => { # CSa2 + Name => 'AF-SPrioritySelection', + Mask => 0x20, + PrintConv => { + 0 => 'Focus', + 1 => 'Release', + }, + }, + 0.3 => { # CSa6 + Name => 'NumberOfFocusPoints', + Mask => 0x10, + PrintConv => { + 0 => '39 Points', + 1 => '11 Points', + }, + }, + 0.4 => { # CSa3 + Name => 'FocusTrackingLockOn', + Mask => 0x07, + PrintConv => { + 0 => 'Off', + 1 => '1 Short', + 2 => '2', + 3 => '3 Normal', + 4 => '4', + 5 => '5 Long', + }, + }, + 1.1 => { # CSa5 + Name => 'FocusPointWrap', + Mask => 0x08, + PrintConv => { + 0 => 'No Wrap', + 1 => 'Wrap', + }, + }, + 1.2 => { # CSa4 + Name => 'AFPointIllumination', + Mask => 0x06, + PrintConv => { + 0 => 'Auto', + 1 => 'On', + 2 => 'Off', + }, + }, + 1.3 => { # CSa7 + Name => 'AFAssist', + Mask => 0x01, + PrintConv => \%onOff, + }, + 2.1 => { # CSd14 + Name => 'BatteryOrder', + Mask => 0x40, + PrintConv => { + 0 => 'MB-D11 First', + 1 => 'Camera Battery First', + }, + }, + 2.2 => { # CSa10 + Name => 'AF-OnForMB-D11', + Mask => 0x1c, + PrintConv => { + 0 => 'AE/AF Lock', + 1 => 'AE Lock Only', + 2 => 'AF Lock Only', + 3 => 'AE Lock (hold)', + 4 => 'AF-ON', + 5 => 'FV Lock', + 6 => 'Same as FUNC Button', + }, + }, + 2.3 => { # CSd13 + Name => 'MB-D11BatteryType', + Mask => 0x03, + PrintConv => { + 0 => 'LR6 (AA alkaline)', + 1 => 'Ni-MH (AA Ni-MH)', + 2 => 'FR6 (AA lithium)', + }, + }, + 3.1 => { # CSd1-b + Name => 'BeepPitch', + Mask => 0xc0, + PrintConv => { + 0 => 'Off', + 1 => 'Low', + 2 => 'High', + }, + }, + 3.2 => { # CSf8 + Name => 'NoMemoryCard', + Mask => 0x20, + PrintConv => { + 0 => 'Release Locked', + 1 => 'Enable Release', + }, + }, + 3.3 => { # CSd3 + Name => 'ISODisplay', + Mask => 0x0c, + PrintConv => { + 0 => 'Show ISO/Easy ISO', + 1 => 'Show ISO Sensitivity', + 3 => 'Show Frame Count', + }, + }, + 3.4 => { # CSd2 + Name => 'GridDisplay', + Mask => 0x02, + PrintConv => \%onOff, + }, + 3.5 => { # CSd4 + Name => 'ViewfinderWarning', + Mask => 0x01, + PrintConv => \%onOff, + }, + 4.1 => { # CSd9 + Name => 'ShootingInfoDisplay', + Mask => 0xc0, + PrintConv => { + 0 => 'Auto', + 2 => 'Manual (dark on light)', + 3 => 'Manual (light on dark)', + }, + }, + 4.2 => { # CSd10 + Name => 'LCDIllumination', + Mask => 0x20, + PrintConv => \%offOn, + }, + 4.3 => { # CSd8 + Name => 'FileNumberSequence', + Mask => 0x08, + PrintConv => \%onOff, + }, + 4.4 => { # CSd5 + Name => 'ScreenTips', + Mask => 0x04, + PrintConv => \%offOn, + }, + 4.5 => { # CSd1-a + Name => 'BeepVolume', + Mask => 0x03, + PrintConv => { + 0 => 'Off', + 1 => '1', + 2 => '2', + 3 => '3', + }, + }, + 5.1 => { # CSf9 + Name => 'ReverseIndicators', + Mask => 0x80, + PrintConv => { + 0 => '+ 0 -', + 1 => '- 0 +', + }, + }, + 5.2 => { # CSb3 + Name => 'EasyExposureCompensation', + Mask => 0x03, + PrintConv => { + 0 => 'Off', + 1 => 'On', + 2 => 'On Auto Reset', + }, + }, + 6.1 => { # CSb2 + Name => 'ExposureControlStep', + Mask => 0x40, + PrintConv => { + 0 => '1/3 EV', + 1 => '1/2 EV', + }, + }, + 6.2 => { # CSb1 + Name => 'ISOSensitivityStep', + Mask => 0x10, + PrintConv => { + 0 => '1/3 EV', + 1 => '1/2 EV', + }, + }, + 7.1 => { # CSb4 + Name => 'CenterWeightedAreaSize', + Mask => 0xe0, + PrintConv => { + 0 => '6 mm', + 1 => '8 mm', + 2 => '10 mm', + 3 => '13 mm', + 4 => 'Average', + }, + }, + 10.1 => { # CSd11 + Name => 'ExposureDelayMode', + Mask => 0x40, + PrintConv => \%offOn, + }, + 10.2 => { # CSd6 + Name => 'CLModeShootingSpeed', + Mask => 0x07, + PrintConv => '"$val fps"', + PrintConvInv => '$val=~s/\s*fps//i; $val', + }, + 11 => { # CSd7 + Name => 'MaxContinuousRelease', + # values: 1-100 + }, + 12.1 => { # CSe5 + Name => 'AutoBracketSet', + Mask => 0xe0, #(NC) + PrintConv => { + 0 => 'AE & Flash', # default + 1 => 'AE Only', + 2 => 'Flash Only', #(NC) + 3 => 'WB Bracketing', #(NC) + 4 => 'Active D-Lighting', #(NC) + }, + }, + 12.2 => { # CSe6 + Name => 'AutoBracketOrder', + Mask => 0x10, + PrintConv => { + 0 => '0,-,+', + 1 => '-,0,+', + }, + }, + 13.1 => { # CSf3 + Name => 'FuncButton', + Mask => 0xf8, + PrintConv => { + 0 => 'Grid Display', + 1 => 'FV Lock', + 2 => 'Flash Off', + 3 => 'Matrix Metering', + 4 => 'Center-weighted Metering', + 5 => 'Spot Metering', + 6 => 'My Menu Top', + 7 => '+ NEF (RAW)', + 8 => 'Active D-Lighting', + 9 => 'Preview', + 10 => 'AE/AF Lock', + 11 => 'AE Lock Only', + 12 => 'AF Lock Only', + 13 => 'AE Lock (hold)', + 14 => 'Bracketing Burst', + 15 => 'Playback', + 16 => '1EV Step Speed/Aperture', + 17 => 'Choose Non-CPU Lens', + 18 => 'Virtual Horizon', + 19 => 'Start Movie Recording', + }, + }, + 14.1 => { # CSf4 + Name => 'PreviewButton', + Mask => 0xf8, + PrintConv => { + 0 => 'Grid Display', + 1 => 'FV Lock', + 2 => 'Flash Off', + 3 => 'Matrix Metering', + 4 => 'Center-weighted Metering', + 5 => 'Spot Metering', + 6 => 'My Menu Top', + 7 => '+ NEF (RAW)', + 8 => 'Active D-Lighting', + 9 => 'Preview', + 10 => 'AE/AF Lock', + 11 => 'AE Lock Only', + 12 => 'AF Lock Only', + 13 => 'AE Lock (hold)', + 14 => 'Bracketing Burst', + 15 => 'Playback', + 16 => '1EV Step Speed/Aperture', + 17 => 'Choose Non-CPU Lens', + 18 => 'Virtual Horizon', + 19 => 'Start Movie Recording', + }, + }, + 16.1 => { # CSf5 + Name => 'AELockButton', + Mask => 0x38, + PrintConv => { + 0 => 'AE/AF Lock', + 1 => 'AE Lock Only', + 2 => 'AF Lock Only', + 3 => 'AE Lock (hold)', + 4 => 'AF-ON', + 5 => 'FV Lock', + }, + }, + 15.1 => { # CSf2 + Name => 'OKButton', + Mask => 0x18, + PrintConv => { + 1 => 'Select Center Focus Point', + 2 => 'Highlight Active Focus Point', + 3 => 'Not Used', #(NC) + 0 => 'Off', #(NC) + }, + }, + 17.1 => { # CSf6-a + Name => 'CommandDialsReverseRotation', + Mask => 0x80, + PrintConv => \%noYes, + }, + 17.2 => { # CSf6-b + Name => 'CommandDialsChangeMainSub', + Mask => 0x60, + PrintConv => { + 0 => 'Off', + 1 => 'On', + 2 => 'On (A mode only)', + }, + }, + 17.3 => { # CSf6-c + Name => 'CommandDialsApertureSetting', + Mask => 0x04, + PrintConv => { + 0 => 'Sub-command Dial', + 1 => 'Aperture Ring', + }, + }, + 17.4 => { # CSf6-d + Name => 'CommandDialsMenuAndPlayback', + Mask => 0x18, + PrintConv => { + 0 => 'On', + 2 => 'On (Image Review Exclude)', + 1 => 'Off', + }, + }, + 17.5 => { # CSc1 + Name => 'ShutterReleaseButtonAE-L', + Mask => 0x02, + PrintConv => \%offOn, + }, + 17.6 => { # CSf7 + Name => 'ReleaseButtonToUseDial', + Mask => 0x01, + PrintConv => \%noYes, + }, + 18.1 => { # CSc2 + Name => 'MeteringTime', + Mask => 0xf0, + PrintConvColumns => 2, + PrintConv => { + 0 => '4 s', + 1 => '6 s', # default + 2 => '8 s', + 3 => '16 s', + 4 => '30 s', + 5 => '1 min', + 6 => '5 min', + 7 => '10 min', + 8 => '30 min', + 9 => 'No Limit', + }, + }, + 18.2 => { # CSc5 + Name => 'RemoteOnDuration', + Mask => 0x03, + PrintConv => { + 0 => '1 min', + 1 => '5 min', + 2 => '10 min', + 3 => '15 min', + }, + }, + 19.1 => { # CSc3-a + Name => 'SelfTimerTime', + Mask => 0xc0, + PrintConv => { + 0 => '2 s', + 1 => '5 s', + 2 => '10 s', # default + 3 => '20 s', + }, + }, + 19.2 => { # CSc3-c + Name => 'SelfTimerInterval', + Mask => 0x30, + PrintConv => { + 0 => '0.5 s', + 1 => '1 s', + 2 => '2 s', # default + 3 => '3 s', + }, + }, + 19.3 => { # CSc3-b + Name => 'SelfTimerShotCount', + Mask => 0x0f, + }, + 20.1 => { # CSc4-d + Name => 'ImageReviewTime', + Mask => 0xe0, + PrintConv => { #(NC) + 0 => '4 s', + 1 => '10 s', # default + 2 => '20 s', + 3 => '1 min', + 4 => '5 min', + 5 => '10 min', + }, + }, + 20.2 => { # CSc4-e + Name => 'LiveViewMonitorOffTime', + Mask => 0x1c, + PrintConv => { #(NC) + 0 => '4 s', + 1 => '10 s', # default + 2 => '20 s', + 3 => '1 min', + 4 => '5 min', + 5 => '10 min', + }, + }, + 21.1 => { # CSc4-b + Name => 'MenuMonitorOffTime', + Mask => 0xe0, + PrintConv => { + 0 => '4 s', + 1 => '10 s', # default + 2 => '20 s', + 3 => '1 min', + 4 => '5 min', + 5 => '10 min', + }, + }, + 21.2 => { # CSc4-c + Name => 'ShootingInfoMonitorOffTime', + Mask => 0x1c, + PrintConv => { #(NC) + 0 => '4 s', + 1 => '10 s', # default + 2 => '20 s', + 3 => '1 min', + 4 => '5 min', + 5 => '10 min', + }, + }, + 22.1 => { # CSe1 + Name => 'FlashSyncSpeed', + Mask => 0xf0, + PrintConv => { + 0 => '1/320 s (auto FP)', + 1 => '1/250 s (auto FP)', + 2 => '1/250 s', + 3 => '1/200 s', + 4 => '1/160 s', + 5 => '1/125 s', + 6 => '1/100 s', + 7 => '1/80 s', + 8 => '1/60 s', + }, + }, + 22.2 => { # CSe2 + Name => 'FlashShutterSpeed', + Mask => 0x0f, + PrintConvColumns => 2, + PrintConv => { + 0 => '1/60 s', + 1 => '1/30 s', + 2 => '1/15 s', + 3 => '1/8 s', + 4 => '1/4 s', + 5 => '1/2 s', + 6 => '1 s', + 7 => '2 s', + 8 => '4 s', + 9 => '8 s', + 10 => '15 s', + 11 => '30 s', + }, + }, + 23.1 => { # CSe3 + Name => 'FlashControlBuilt-in', + Mask => 0xc0, + RawConv => '$$self{FlashControlBuiltin} = $val', + PrintConv => { + 0 => 'TTL', + 1 => 'Manual', + 2 => 'Repeating Flash', + 3 => 'Commander Mode', + }, + }, + 23.2 => { # CSe3-b + Name => 'ManualFlashOutput', + Condition => '$$self{FlashControlBuiltin} == 1', + Mask => 0x1f, + ValueConv => '2 ** (-$val/3)', + ValueConvInv => '$val > 0 ? -3*log($val)/log(2) : 0', + PrintConv => q{ + return 'Full' if $val > 0.99; + Image::ExifTool::Exif::PrintExposureTime($val); + }, + PrintConvInv => '$val=~/F/i ? 1 : Image::ExifTool::Exif::ConvertFraction($val)', + }, + 24.1 => { # CSe3-ca + Name => 'RepeatingFlashOutput', + Condition => '$$self{FlashControlBuiltin} == 2', + Mask => 0x70, + ValueConv => '2 ** (-$val-2)', + ValueConvInv => '$val > 0 ? int(-log($val)/log(2)-2+0.5) : 0', + PrintConv => 'Image::ExifTool::Exif::PrintExposureTime($val)', + PrintConvInv => 'Image::ExifTool::Exif::ConvertFraction($val)', + }, + 24.2 => { # CSe3-cb + Name => 'RepeatingFlashCount', + Condition => '$$self{FlashControlBuiltin} == 2', + Mask => 0x0f, + ValueConv => '$val < 10 ? $val + 1 : 5 * ($val - 7)', + ValueConvInv => '$val <= 10 ? $val - 1 : $val / 5 + 7', + }, + 25.1 => { # CSe3-cc (NC) + Name => 'RepeatingFlashRate', + Condition => '$$self{FlashControlBuiltin} == 2', + Mask => 0xf0, + ValueConv => '$val < 10 ? $val + 1 : 10 * ($val - 8)', + ValueConvInv => 'int(($val <= 10 ? $val - 1 : $val / 10 + 8) + 0.5)', + PrintConv => '"$val Hz"', + PrintConvInv => '$val=~/(\d+)/; $1 || 0', + }, + 26.1 => { # CSe3-da + Name => 'CommanderInternalTTLCompBuiltin', + Condition => '$$self{FlashControlBuiltin} == 3', + Mask => 0x1f, + ValueConv => '($val - 9) / 3', + ValueConvInv => '$val * 3 + 9', + PrintConv => '$val ? sprintf("%+.1f",$val) : 0', + PrintConvInv => '$val', + }, + 27.1 => { # CSe3-db + Name => 'CommanderInternalTTLCompGroupA', + Condition => '$$self{FlashControlBuiltin} == 3', + Mask => 0x1f, + ValueConv => '($val - 9) / 3', + ValueConvInv => '$val * 3 + 9', + PrintConv => '$val ? sprintf("%+.1f",$val) : 0', + PrintConvInv => '$val', + }, + 28.1 => { # CSe3-dc + Name => 'CommanderInternalTTLCompGroupB', + Condition => '$$self{FlashControlBuiltin} == 3', + Mask => 0x1f, + ValueConv => '($val - 9) / 3', + ValueConvInv => '$val * 3 + 9', + PrintConv => '$val ? sprintf("%+.1f",$val) : 0', + PrintConvInv => '$val', + }, + 30.1 => { # CSd11 + Name => 'FlashWarning', + Mask => 0x80, + PrintConv => \%onOff, + }, + 30.2 => { # CSe4 + Name => 'ModelingFlash', + Mask => 0x20, + PrintConv => \%onOff, + }, + 34.1 => { # CSa8-b + Name => 'LiveViewAFAreaMode', + Mask => 0x60, + PrintConv => { + 0 => 'Face-Priority', + 1 => 'NormalArea', + 2 => 'WideArea', + 3 => 'SubjectTracking', + }, + }, + 34.2 => { # CSa8-a + Name => 'LiveViewAFMode', + Mask => 0x02, + PrintConv => { + 0 => 'AF-C', + 1 => 'AF-F', + }, + }, + 35.1 => { # CSc4-a + Name => 'PlaybackMonitorOffTime', + Mask => 0xe0, + PrintConv => { + 0 => '4 s', + 1 => '10 s', # default + 2 => '20 s', + 3 => '1 min', + 4 => '5 min', + 5 => '10 min', + }, + }, +); + +# D4/D4S custom settings (ref 1, decoded from D4S) +%Image::ExifTool::NikonCustom::SettingsD4 = ( + PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData, + WRITE_PROC => \&Image::ExifTool::WriteBinaryData, + CHECK_PROC => \&Image::ExifTool::CheckBinaryData, + WRITABLE => 1, + FIRST_ENTRY => 0, + GROUPS => { 0 => 'MakerNotes', 2 => 'Camera' }, + NOTES => 'Custom settings for the D4 and D4S.', + 0.1 => { + Name => 'CustomSettingsBank', + Mask => 0x03, + PrintConv => { + 0 => 'A', + 1 => 'B', + 2 => 'C', + 3 => 'D', + }, + }, + 1.1 => { #CSa1 + Name => 'AF-CPrioritySelection', + Mask => 0xc0, + PrintConv => { + 0 => 'Release', + 1 => 'Release + Focus', + 2 => 'Focus', + 3 => 'Focus + Release', + }, + }, + 1.2 => { # CSa2 + Name => 'AF-SPrioritySelection', + Mask => 0x20, + PrintConv => { + 0 => 'Focus', + 1 => 'Release', + }, + }, + 1.3 => { # CSa7 + Name => 'AFPointSelection', + Mask => 0x10, + PrintConv => { + 0 => '51 Points', + 1 => '11 Points', + }, + }, + 1.4 => { # CSa3 + Name => 'FocusTrackingLockOn', + Mask => 0x07, + PrintConv => { + 0 => 'Off', + 1 => '1 (Short)', + 2 => '2', + 3 => '3 (Normal)', + 4 => '4', + 5 => '5 (Long)', + }, + }, + 2.1 => { # CSa4 + Name => 'AFActivation', + Mask => 0x80, + PrintConv => { + 0 => 'Shutter/AF-On', + 1 => 'AF-On Only', + }, + }, + 2.2 => { # CSa6 + Name => 'FocusPointWrap', + Mask => 0x08, + PrintConv => { + 0 => 'No Wrap', + 1 => 'Wrap', + }, + }, + 4.1 => { # CSd1-b + Name => 'Pitch', + Mask => 0x40, + PrintConv => { 0 => 'High', 1 => 'Low' }, + }, + 4.2 => { # CSf12 + Name => 'NoMemoryCard', + Mask => 0x20, + PrintConv => { + 0 => 'Release Locked', + 1 => 'Enable Release', + }, + }, + 4.3 => { # CSd6 + Name => 'GridDisplay', + Mask => 0x02, + PrintConv => \%onOff, + }, + 5.1 => { # CSd9 + Name => 'ShootingInfoDisplay', + Mask => 0xc0, + PrintConv => { + # 0 - seen for D4 (PH) + 1 => 'Auto', + 2 => 'Manual (dark on light)', + 3 => 'Manual (light on dark)', + }, + }, + 5.2 => { # CSd10 + Name => 'LCDIllumination', + Mask => 0x20, + PrintConv => \%offOn, + }, + 5.3 => { # CSd8 + Name => 'ScreenTips', + Mask => 0x04, + PrintConv => \%offOn, + }, + 5.4 => { # CSd1-a + Name => 'Beep', + Mask => 0x03, + PrintConv => { + 0 => 'Off', + 1 => 'Low', + 2 => 'Medium', + 3 => 'High', + }, + }, + 6.1 => { # CSf13 + Name => 'ReverseIndicators', + Mask => 0x80, + PrintConv => { + 0 => '+ 0 -', + 1 => '- 0 +', + }, + }, + 6.2 => { # CSd7-a + Name => 'RearDisplay', + Mask => 0x40, + PrintConv => { + 0 => 'ISO', + 1 => 'Exposures Remaining', + }, + }, + 6.3 => { # CSd7-b + Name => 'ViewfinderDisplay', + Mask => 0x20, + PrintConv => { + 0 => 'Frame Count', + 1 => 'Exposures Remaining', + }, + }, + 6.4 => { # CSd10-a + Name => 'CommandDialsReverseRotation', + Mask => 0x18, + PrintConv => { + 0 => 'No', + 1 => 'Shutter Speed & Aperture', + 2 => 'Exposure Compensation', + 3 => 'Exposure Compensation, Shutter Speed & Aperture', + }, + }, + 6.5 => { # CSb4 + Name => 'EasyExposureCompensation', + Mask => 0x03, + PrintConv => { + 0 => 'Off', + 1 => 'On', + 2 => 'On (auto reset)', + }, + }, + 7.1 => { # CSb2 + Name => 'ExposureControlStepSize', + Mask => 0xc0, + PrintConv => { + 0 => '1/3 EV', + 1 => '1/2 EV', + 2 => '1 EV', + }, + }, + 7.2 => { # CSb1 + Name => 'ISOStepSize', + Mask => 0x30, + PrintConv => { + 0 => '1/3 EV', + 1 => '1/2 EV', + 2 => '1 EV', + }, + }, + 7.3 => { # CSb3 + Name => 'ExposureCompStepSize', + Mask => 0x0c, + PrintConv => { + 0 => '1/3 EV', + 1 => '1/2 EV', + 2 => '1 EV', + }, + }, + 8.1 => { # CSb6 (CSb5 for D4) + Name => 'CenterWeightedAreaSize', + Mask => 0xe0, + PrintConv => { + 0 => '8 mm', + 1 => '12 mm', + 2 => '15 mm', + 3 => '20 mm', + 4 => 'Average', + }, + }, + 8.2 => { # CSb7-a + Name => 'FineTuneOptMatrixMetering', + Mask => 0x0f, + ValueConv => '($val > 0x7 ? $val - 0x10 : $val) / 6', + ValueConvInv => 'int($val*6+($val>0?0.5:-0.5))', + PrintConv => '$val ? sprintf("%+.2f", $val) : 0', + PrintConvInv => 'Image::ExifTool::Exif::ConvertFraction($val)', + }, + 9.1 => { # CSb7-b + Name => 'FineTuneOptCenterWeighted', + Mask => 0xf0, + ValueConv => '($val > 0x7 ? $val - 0x10 : $val) / 6', + ValueConvInv => 'int($val*6+($val>0?0.5:-0.5))', + PrintConv => '$val ? sprintf("%+.2f", $val) : 0', + PrintConvInv => 'Image::ExifTool::Exif::ConvertFraction($val)', + }, + 9.2 => { # CSb7-c + Name => 'FineTuneOptSpotMetering', + Mask => 0x0f, + ValueConv => '($val > 0x7 ? $val - 0x10 : $val) / 6', + ValueConvInv => 'int($val*6+($val>0?0.5:-0.5))', + PrintConv => '$val ? sprintf("%+.2f", $val) : 0', + PrintConvInv => 'Image::ExifTool::Exif::ConvertFraction($val)', + }, + 10.1 => { # CSf1-a + Name => 'MultiSelectorShootMode', + Mask => 0xc0, + PrintConv => { + 0 => 'Select Center Focus Point (Reset)', + 2 => 'Preset Focus Point (Pre)', + 3 => 'Not Used (None)', + }, + }, + 10.2 => { # CSf1-b + Name => 'MultiSelectorPlaybackMode', + Mask => 0x30, + PrintConv => { + 0 => 'Thumbnail On/Off', + 1 => 'View Histograms', + 2 => 'Zoom On/Off', + 3 => 'Choose Folder', + }, + }, + 10.3 => { # CSf2 + Name => 'MultiSelector', + Mask => 0x01, + PrintConv => { + 0 => 'Do Nothing', + 1 => 'Reset Meter-off Delay', + }, + }, + 11.1 => { # CSd4 + Name => 'ExposureDelayMode', + Mask => 0xc0, + PrintConv => { + 0 => 'Off', + 1 => '1 s', + 2 => '2 s', + 3 => '3 s', + }, + }, + 11.2 => { # CSd2-a + Name => 'CHModeShootingSpeed', + Mask => 0x10, + PrintConv => { + 0 => '10 fps', + 1 => '11 fps', + }, + }, + 11.3 => { # CSd2-b + Name => 'CLModeShootingSpeed', + Mask => 0x0f, + PrintConv => '"$val fps"', + PrintConvInv => '$val=~s/\s*fps//i; $val', + }, + 12 => { # CSd3 + Name => 'MaxContinuousRelease', + # values: 1-200 + }, + 13.1 => { # CSe6 + Name => 'AutoBracketSet', + Mask => 0xe0, + PrintConv => { + 0 => 'AE & Flash', + 1 => 'AE Only', + 2 => 'Flash Only', + 3 => 'WB Bracketing', + 4 => 'Active D-Lighting', + }, + }, + 13.2 => { # CSe8 + Name => 'AutoBracketOrder', + Mask => 0x10, + PrintConv => { + 0 => '0,-,+', + 1 => '-,0,+', + }, + }, + 13.3 => { # CSe7 + Name => 'AutoBracketModeM', + Mask => 0x0c, + PrintConv => { + 0 => 'Flash/Speed', + 1 => 'Flash/Speed/Aperture', + 2 => 'Flash/Aperture', + 3 => 'Flash Only', + }, + }, + 14.1 => { # CSf3-a + Name => 'FuncButton', + Mask => 0xf8, + PrintConv => { + 0 => 'None', + 1 => 'Preview', + 2 => 'FV Lock', + 3 => 'AE/AF Lock', + 4 => 'AE Lock Only', + 5 => 'AE Lock (reset on release)', + 6 => 'AE Lock (hold)', + 7 => 'AF Lock Only', + 8 => 'AF-On', + 10 => 'Bracketing Burst', + 11 => 'Matrix Metering', + 12 => 'Center-weighted Metering', + 13 => 'Spot Metering', + 14 => 'Playback', + 15 => 'My Menu Top Item', + 16 => '+NEF(RAW)', + 17 => 'Virtual Horizon', + 18 => 'My Menu', + 20 => 'Grid Display', + 21 => 'Disable Synchronized Release', + 22 => 'Remote Release Only', + 26 => 'Flash Disable/Enable', + }, + }, + 14.2 => { # CSf3-b + Name => 'FuncButtonPlusDials', + Mask => 0x07, + PrintConv => { + 0 => 'None', + 1 => 'Choose Image Area (FX/DX/5:4)', + 2 => 'Shutter Speed & Aperture Lock', + 3 => 'One Step Speed / Aperture', + 4 => 'Choose Non-CPU Lens Number', + 5 => 'Active D-Lighting', + 6 => 'Shooting Bank Menu', + }, + }, + 15.1 => { # CSf4-a + Name => 'PreviewButton', + Mask => 0xf8, + PrintConv => { + 0 => 'None', + 1 => 'Preview', + 2 => 'FV Lock', + 3 => 'AE/AF Lock', + 4 => 'AE Lock Only', + 5 => 'AE Lock (reset on release)', + 6 => 'AE Lock (hold)', + 7 => 'AF Lock Only', + 8 => 'AF-On', + 10 => 'Bracketing Burst', + 11 => 'Matrix Metering', + 12 => 'Center-weighted Metering', + 13 => 'Spot Metering', + 14 => 'Playback', + 15 => 'My Menu Top Item', + 16 => '+NEF(RAW)', + 17 => 'Virtual Horizon', + 18 => 'My Menu', + 20 => 'Grid Display', + 21 => 'Disable Synchronized Release', + 22 => 'Remote Release Only', + 26 => 'Flash Disable/Enable', + }, + }, + 15.2 => { # CSf4-b + Name => 'PreviewButtonPlusDials', + Mask => 0x07, + PrintConv => { + 0 => 'None', + 1 => 'Choose Image Area (FX/DX/5:4)', + 2 => 'Shutter Speed & Aperture Lock', + 3 => 'One Step Speed / Aperture', + 4 => 'Choose Non-CPU Lens Number', + 5 => 'Active D-Lighting', + 6 => 'Shooting Bank Menu', + }, + }, + 16.1 => { # CSf9 + Name => 'AssignBktButton', + Mask => 0x07, + PrintConv => { + 0 => 'Auto Bracketing', + 1 => 'Multiple Exposure', + 2 => 'HDR (high dynamic range)', + 3 => 'None', + }, + }, + 18.1 => { # CSf10-b + Name => 'CommandDialsChangeMainSub', + Mask => 0xe0, + PrintConv => { + 0 => 'Autofocus Off, Exposure Off', + 1 => 'Autofocus Off, Exposure On', + 2 => 'Autofocus Off, Exposure On (Mode A)', + 4 => 'Autofocus On, Exposure Off', + 5 => 'Autofocus On, Exposure On', + 6 => 'Autofocus On, Exposure On (Mode A)', + }, + }, + 18.2 => { # CSf10-d + Name => 'CommandDialsMenuAndPlayback', + Mask => 0x18, + PrintConv => { + 0 => 'On', + 1 => 'Off', + 2 => 'On (Image Review Excluded)', + }, + }, + 18.3 => { # CSf10-c + Name => 'CommandDialsApertureSetting', + Mask => 0x04, + PrintConv => { + 0 => 'Sub-command Dial', + 1 => 'Aperture Ring', + }, + }, + 18.4 => { # CSc1 + Name => 'ShutterReleaseButtonAE-L', + Mask => 0x02, + PrintConv => \%offOn, + }, + 18.5 => { # CSf11 + Name => 'ReleaseButtonToUseDial', + Mask => 0x01, + PrintConv => \%noYes, + }, + 19.1 => { # CSc2 + Name => 'StandbyTimer', + Mask => 0xf0, + PrintConv => { + 0 => '4 s', + 1 => '6 s', + 3 => '10 s', + 5 => '30 s', + 6 => '1 min', + 7 => '5 min', + 8 => '10 min', + 9 => '30 min', + }, + }, + 20.1 => { # CSc3-a + Name => 'SelfTimerTime', + Mask => 0xc0, + PrintConv => { + 0 => '2 s', + 1 => '5 s', + 2 => '10 s', + 3 => '20 s', + }, + }, + 20.2 => { # CSc3-b + Name => 'SelfTimerShotCount', + Mask => 0x0f, + }, + 20.3 => { # CSc3-c + Name => 'SelfTimerShotInterval', + Mask => 0x30, + PrintConv => { + 0 => '0.5 s', + 1 => '1 s', + 2 => '2 s', + 3 => '3 s', + }, + }, + 21.1 => { # CSc4-d + Name => 'ImageReviewMonitorOffTime', + Mask => 0xe0, + PrintConv => { + 0 => '2 s', + 1 => '4 s', + 2 => '10 s', + 3 => '20 s', + 4 => '1 min', + 5 => '5 min', + 6 => '10 min', + + }, + }, + 21.2 => { # CSc4-e + Name => 'LiveViewMonitorOffTime', + Mask => 0x1c, + PrintConv => { + 0 => '5 min', + 1 => '10 min', + 2 => '15 min', + 3 => '20 min', + 4 => '30 min', + 5 => 'No Limit', + }, + }, + 22.1 => { # CSc4-b + Name => 'MenuMonitorOffTime', + Mask => 0xe0, + PrintConv => { + 0 => '4 s', + 1 => '10 s', + 2 => '20 s', + 3 => '1 min', + 4 => '5 min', + 5 => '10 min', + }, + }, + 22.2 => { # CSc4-c + Name => 'ShootingInfoMonitorOffTime', + Mask => 0x1c, + PrintConv => { + 0 => '4 s', + 1 => '10 s', + 2 => '20 s', + 3 => '1 min', + 4 => '5 min', + 5 => '10 min', + }, + }, + 23.1 => { # CSe1 + Name => 'FlashSyncSpeed', + Mask => 0xf0, + PrintConv => { + # 0x00 - seen for D4 (PH) + 1 => '1/250 s (auto FP)', + 2 => '1/250 s', + 3 => '1/200 s', + 4 => '1/160 s', + 5 => '1/125 s', + 6 => '1/100 s', + 7 => '1/80 s', + 8 => '1/60 s', + }, + }, + 23.2 => { # CSe2 + Name => 'FlashShutterSpeed', + Mask => 0x0f, + PrintConvColumns => 2, + PrintConv => { + 0 => '1/60 s', + 1 => '1/30 s', + 2 => '1/15 s', + 3 => '1/8 s', + 4 => '1/4 s', + 5 => '1/2 s', + 6 => '1 s', + 7 => '2 s', + 8 => '4 s', + 9 => '8 s', + 10 => '15 s', + 11 => '30 s', + }, + }, + 31.1 => { # CSe5 + Name => 'ModelingFlash', + Mask => 0x20, + PrintConv => \%onOff, + }, + 36.1 => { # CSc4-a + Name => 'PlaybackMonitorOffTime', + Mask => 0xe0, + PrintConv => { + 0 => '4 s', + 1 => '10 s', + 2 => '20 s', + 3 => '1 min', + 4 => '5 min', + 5 => '10 min', + }, + }, + 37.1 => { # CSf15 + Name => 'PlaybackZoom', + Mask => 0x01, + PrintConv => { + 0 => 'Use Separate Zoom Buttons', + 1 => 'Use Either Zoom Button with Command Dial', + }, + }, + 38.1 => { # CSf8-a + Name => 'ShutterSpeedLock', + Mask => 0x80, + PrintConv => \%offOn, + }, + 38.2 => { # CSf8-b + Name => 'ApertureLock', + Mask => 0x40, + PrintConv => \%offOn, + }, + 38.3 => { # CSg4 + Name => 'MovieShutterButton', + Mask => 0x30, + PrintConv => { + 0 => 'Take Photo', + 1 => 'Record Movies', + 2 => 'Live Frame Grab', + }, + }, + 38.4 => { # CSe4 + Name => 'FlashExposureCompArea', + Mask => 0x04, + PrintConv => { + 0 => 'Entire frame', + 1 => 'Background only', + }, + }, + 41.1 => { # CSg1-a + Name => 'MovieFunctionButton', + Mask => 0x70, + PrintConv => { + 0 => 'None', + 1 => 'Power Aperture (open)', # bit '02' is also toggled on for this setting + 3 => 'Index Marking', + 4 => 'View Photo Shooting Info', + }, + }, + 41.2 => { # CSg2-a + Name => 'MoviePreviewButton', + Mask => 0x07, + PrintConv => { + 0 => 'None', + 2 => 'Power Aperture (open)', # bit '10' is also toggled on for this setting + 3 => 'Index Marking', + 4 => 'View Photo Shooting Info', + }, + }, + 42.1 => { # CSf14 + Name => 'VerticalMultiSelector', + Mask => 0x60, + PrintConv => { + 0 => 'Same as Multi-Selector with Info(U/D) & Playback(R/L)', + 1 => 'Same as Multi-Selector with Info(R/L) & Playback(U/D)', + 2 => 'Focus Point Selection', + }, + }, + 42.2 => { # CSf7-a + Name => 'VerticalFuncButton', + Mask => 0x1f, + PrintConv => { + 0 => 'None', + 1 => 'Preview', + 2 => 'FV Lock', + 3 => 'AE/AF Lock', + 4 => 'AE Lock Only', + 5 => 'AE Lock (reset on release)', + 6 => 'AE Lock (hold)', + 7 => 'AF Lock Only', + 10 => 'Bracketing Burst', + 11 => 'Matrix Metering', + 12 => 'Center-weighted Metering', + 13 => 'Spot Metering', + 14 => 'Playback', + 15 => 'My Menu Top Item', + 16 => '+NEF(RAW)', + 17 => 'Virtual Horizon', + 18 => 'My Menu', + 20 => 'Grid Display', + 26 => 'Flash Disable/Enable', + }, + }, + 43.1 => { # CSf7-b + Name => 'VerticalFuncButtonPlusDials', + Mask => 0xf0, + PrintConv => { + 0 => 'None', + 1 => 'Choose Image Area (FX/DX/5:4)', + 2 => 'Shutter Speed & Aperture Lock', + 3 => 'One Step Speed / Aperture', + 4 => 'Choose Non-CPU Lens Number', + 5 => 'Active D-Lighting', + 6 => 'Shooting Bank Menu', + 7 => 'ISO Sensitivity', + 8 => 'Exposure Mode', + 9 => 'Exposure Compensation', + 10 => 'Metering', + }, + }, + 43.2 => { # CSf16 + Name => 'AssignMovieRecordButton', + Mask => 0x07, + PrintConv => { + 0 => 'None', + 1 => 'Choose Image Area (FX/DX/5:4)', + 2 => 'Shutter Speed & Aperture Lock', + 3 => 'ISO Sensitivity', + 4 => 'Shooting Bank Menu', + }, + }, + 46.1 => { # CSa5-c + Name => 'DynamicAreaAFDisplay', + Mask => 0x80, + PrintConv => \%offOn, + }, + 46.2 => { # CSa5-a + Name => 'AFPointIllumination', + Mask => 0x60, + PrintConv => { + 0 => 'Off', + 1 => 'On in Continuous Shooting Modes', + 2 => 'On During Manual Focusing', + 3 => 'On in Continuous Shooting and Manual Focusing', + }, + }, + 46.3 => { # CSa10 (D4 is slightly different -- needs checking) + Name => 'StoreByOrientation', + Mask => 0x18, + PrintConv => { + 0 => 'Off', + 1 => 'Focus Point', + 2 => 'Focus Point and AF-area mode', + }, + }, + 46.4 => { # CSa5-d + Name => 'GroupAreaAFIllumination', + Mask => 0x04, + PrintConv => { + 0 => 'Squares', + 1 => 'Dots', + }, + }, + 46.5 => { # CSa5-b + Name => 'AFPointBrightness', + Mask => 0x03, + PrintConv => { + 0 => 'Low', + 1 => 'Normal', + 2 => 'High', + 3 => 'Extra High', + }, + }, + 47.1 => { # CSa8 + Name => 'AFOnButton', + Mask => 0x70, + PrintConv => { + 0 => 'AF On', + 1 => 'AE/AF Lock', + 2 => 'AE Lock Only', + 3 => 'AE Lock (reset on release)', + 4 => 'AE Lock (hold)', + 5 => 'AF Lock Only', + 6 => 'None', + }, + }, + 47.2 => { # CSa9 + Name => 'VerticalAFOnButton', + Mask => 0x07, + PrintConv => { + 0 => 'Same as AF On', + 1 => 'AF On', + 2 => 'AE/AF Lock', + 3 => 'AE Lock Only', + 4 => 'AE Lock (reset on release)', + 5 => 'AE Lock (hold)', + 6 => 'AF Lock Only', + 7 => 'None', + }, + }, + 48.1 => { # CSf5 + Name => 'SubSelectorAssignment', + Mask => 0x80, + PrintConv => { + 0 => 'Focus Point Selection', + 1 => 'Same As Multi-selector', + }, + }, + 48.2 => { # CSg3-a + Name => 'MovieSubSelectorAssignment', + Mask => 0x07, + PrintConv => { + 0 => 'None', + 1 => 'Index Marking', + 2 => 'AE/AF Lock', + 3 => 'AE Lock Only', + 4 => 'AE Lock (hold)', + 5 => 'AF Lock Only', + 6 => 'View Photo Shooting Info', + }, + }, + 49.1 => { # CSf6-a + Name => 'SubSelector', + Mask => 0xf8, + PrintConv => { + 0 => 'None', + 1 => 'Preview', + 2 => 'FV Lock', + 3 => 'AE/AF Lock', + 4 => 'AE Lock Only', + 5 => 'AE Lock (reset on release)', + 6 => 'AE Lock (hold)', + 7 => 'AF Lock Only', + 8 => 'AF-On', + # 9 - seen for D4 (PH) + 10 => 'Bracketing Burst', + 11 => 'Matrix Metering', + 12 => 'Center-weighted Metering', + 13 => 'Spot Metering', + 14 => 'Playback', + 15 => 'My Menu Top Item', + 16 => '+NEF(RAW)', + 17 => 'Virtual Horizon', + 18 => 'My Menu', + 19 => 'Reset', # value appears to be specific to this control at this time + 20 => 'Grid Display', + 21 => 'Disable Synchronized Release', + 22 => 'Remote Release Only', + 23 => 'Preview', # value appears to be specific to this control at this time + 26 => 'Flash Disable/Enable', + }, + }, + 49.2 => { # CSf6-b + Name => 'SubSelectorPlusDials', + Mask => 0x07, + PrintConv => { + # (not all values from CSf3-b/CSf4-b are available for CSf6-b) + 0 => 'None', + 1 => 'Choose Image Area (FX/DX/5:4)', + 2 => 'Shutter Speed & Aperture Lock', + # 3 => 'One Step Speed / Aperture', # (not available) + 4 => 'Choose Non-CPU Lens Number', + # 5 => 'Active D-Lighting', # (not available) + 6 => 'Shooting Bank Menu', + }, + }, + 50.1 => { # CSb5 + Name => 'MatrixMetering', + Condition => '$$self{Model} =~ /\bD4S/', + Notes => 'D4S only', + Mask => 0x80, + PrintConv => { + 0 => 'Face Detection On', + 1 => 'Face Detection Off', + }, + }, + 50.2 => { # CSf17 + Name => 'LiveViewButtonOptions', + Condition => '$$self{Model} =~ /\bD4S/', + Notes => 'D4S only', + Mask => 0x30, + PrintConv => { + 0 => 'Enable', + 1 => 'Enable (standby time active)', + 2 => 'Disable', + }, + }, + 50.3 => { # CSa12 + Name => 'AFModeRestrictions', + Condition => '$$self{Model} =~ /\bD4S/', + Notes => 'D4S only', + Mask => 0x03, + PrintConv => { + 0 => 'Off', + 1 => 'AF-C', + 2 => 'AF-S', + }, + }, + 51.1 => { # CSa11 + Name => 'LimitAFAreaModeSelection', + Condition => '$$self{Model} =~ /\bD4S/', + Notes => 'D4S only', + Mask => 0x7e, + PrintConv => { + 0 => 'No Restrictions', + BITMASK => { + 0 => 'Auto-area', + 1 => 'Group-area', + 2 => '3D-tracking', + 3 => 'Dynamic area (51 points)', + 4 => 'Dynamic area (21 points)', + 5 => 'Dynamic area (9 points)', + }, + }, + }, + 52.1 => { # CSg1-b + Name => 'MovieFunctionButtonPlusDials', + Mask => 0x10, + PrintConv => { + 0 => 'None', + 1 => 'Choose Image Area', + }, + }, + 52.2 => { # CSg2-b + Name => 'MoviePreviewButtonPlusDials', + Mask => 0x01, + PrintConv => { + 0 => 'None', + 1 => 'Choose Image Area', + }, + }, + 53.1 => { # CSg3-b + Name => 'MovieSubSelectorAssignmentPlusDials', + Mask => 0x10, + PrintConv => { + 0 => 'None', + 1 => 'Choose Image Area', + }, + }, + 54.1 => { # CSf18 + Name => 'AssignRemoteFnButton', + Condition => '$$self{Model} =~ /\bD4S/', + Notes => 'D4S only', + Mask => 0x1f, + PrintConv => { + 0 => 'None', + 1 => 'Preview', + 2 => 'FV Lock', + 3 => 'AE/AF Lock', + 4 => 'AE Lock Only', + 5 => 'AE Lock (reset on release)', + 7 => 'AF Lock Only', + 8 => 'AF-On', + 16 => '+NEF(RAW)', + 25 => 'Live View', + 26 => 'Flash Disable/Enable', + }, + }, + 55.1 => { # CSf19 + Name => 'LensFocusFunctionButtons', + Condition => '$$self{Model} =~ /\bD4S/', + Notes => 'D4S only', + Mask => 0x3f, + PrintConv => { + 3 => 'AE/AF Lock', + 4 => 'AE Lock Only', + 7 => 'AF Lock Only', + 21 => 'Disable Synchronized Release', + 22 => 'Remote Release Only', + 24 => 'Preset focus Point', + 26 => 'Flash Disable/Enable', + 32 => 'AF-Area Mode: Single-point AF', + 33 => 'AF-Area Mode: Dynamic-area AF (9 points)', + 34 => 'AF-Area Mode: Dynamic-area AF (21 points)', + 35 => 'AF-Area Mode: Dynamic-area AF (51 points)', + 36 => 'AF-Area Mode: Group-area AF', + 37 => 'AF-Area Mode: Auto area AF', + }, + }, +); + +1; # end + +__END__ + +=head1 NAME + +Image::ExifTool::NikonCustom - Read and Write Nikon custom settings + +=head1 SYNOPSIS + +This module is loaded automatically by Image::ExifTool when required. + +=head1 DESCRIPTION + +The Nikon custom functions are very specific to the camera model (and +sometimes even change with firmware version). The information is stored as +unformatted binary data in the ShotInfo record of the Nikon MakerNotes. +This module contains the definitions necessary for Image::ExifTool to decode +this information. + +=head1 AUTHOR + +Copyright 2003-2019, Phil Harvey (phil at owl.phy.queensu.ca) + +This library is free software; you can redistribute it and/or modify it +under the same terms as Perl itself. + +=head1 ACKNOWLEDGEMENTS + +Thanks to Jens Duttke and Warren Hatch for their help decoding the D300 and +D3 custom settings. And thanks to the customer service personnel at Best +Buy for not bugging me while I spent lots of time playing with their +cameras. + +=head1 SEE ALSO + +L<Image::ExifTool::TagNames/Nikon Tags>, +L<Image::ExifTool(3pm)|Image::ExifTool> + +=cut diff --git a/lib/Image/ExifTool/Nintendo.pm b/lib/Image/ExifTool/Nintendo.pm new file mode 100644 index 0000000..8644c4d --- /dev/null +++ b/lib/Image/ExifTool/Nintendo.pm @@ -0,0 +1,128 @@ +#------------------------------------------------------------------------------ +# File: Nintendo.pm +# +# Description: Nintendo EXIF maker notes tags +# +# Revisions: 2014/03/25 - P. Harvey Created +# +# References: 1) http://3dbrew.org/wiki/MPO +#------------------------------------------------------------------------------ + +package Image::ExifTool::Nintendo; + +use strict; +use vars qw($VERSION); +use Image::ExifTool::Exif; + +$VERSION = '1.00'; + +%Image::ExifTool::Nintendo::Main = ( + GROUPS => { 0 => 'MakerNotes', 2 => 'Camera' }, + WRITE_PROC => \&Image::ExifTool::Exif::WriteExif, + CHECK_PROC => \&Image::ExifTool::Exif::CheckExif, + WRITABLE => 1, + # 0x1000 - undef[28] + # 0x1001 - undef[8] + # 0x1100 - undef[80] (found in MPO files) + 0x1101 => { + Name => 'CameraInfo', + SubDirectory => { + TagTable => 'Image::ExifTool::Nintendo::CameraInfo', + ByteOrder => 'Little-endian', + }, + }, +); + +# Nintendo MPO info (ref 1) +%Image::ExifTool::Nintendo::CameraInfo = ( + GROUPS => { 0 => 'MakerNotes', 2 => 'Image' }, + PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData, + WRITE_PROC => \&Image::ExifTool::WriteBinaryData, + CHECK_PROC => \&Image::ExifTool::CheckBinaryData, + WRITABLE => 1, + PRIORITY => 0, + FORMAT => 'int8u', + FIRST_ENTRY => 0, + 0x00 => { # "3DS1" + Name => 'ModelID', + Format => 'undef[4]', + }, + # 0x04 - int32u: 1,2,4,5 + 0x08 => { + Name => 'TimeStamp', + Format => 'int32u', + Groups => { 2 => 'Time' }, + Shift => 'Time', + # zero time is 2000/01/01 (10957 days after Unix time zero) + ValueConv => 'ConvertUnixTime($val + 10957 * 24 * 3600)', + ValueConvInv => 'GetUnixTime($val) - 10957 * 24 * 3600', + PrintConv => '$self->ConvertDateTime($val)', + PrintConvInv => '$self->InverseDateTime($val)', + }, + # 0x10 - int32u: title ID low + # 0x14 - int32u: flags + 0x18 => { + Name => 'InternalSerialNumber', + Groups => { 2 => 'Camera' }, + Format => 'undef[4]', + ValueConv => '"0x" . unpack("H*",$val)', + ValueConvInv => '$val=~s/^0x//; pack("H*",$val)', + }, + 0x28 => { + Name => 'Parallax', + Format => 'float', + PrintConv => 'sprintf("%.2f", $val)', + PrintConvInv => '$val', + }, + 0x30 => { + Name => 'Category', + Format => 'int16u', + PrintHex => 1, + PrintConv => { + 0x0000 => '(none)', + 0x1000 => 'Mii', + 0x2000 => 'Man', + 0x4000 => 'Woman', + }, + }, + # 0x32 - int16u: filter +); + +1; # end + +__END__ + +=head1 NAME + +Image::ExifTool::Nintendo - Nintendo EXIF maker notes tags + +=head1 SYNOPSIS + +This module is loaded automatically by Image::ExifTool when required. + +=head1 DESCRIPTION + +This module contains definitions required by Image::ExifTool to +interpret Nintendo maker notes EXIF meta information. + +=head1 AUTHOR + +Copyright 2003-2019, Phil Harvey (phil at owl.phy.queensu.ca) + +This library is free software; you can redistribute it and/or modify it +under the same terms as Perl itself. + +=head1 REFERENCES + +=over 4 + +=item L<http://3dbrew.org/wiki/MPO> + +=back + +=head1 SEE ALSO + +L<Image::ExifTool::TagNames/Nintendo Tags>, +L<Image::ExifTool(3pm)|Image::ExifTool> + +=cut diff --git a/lib/Image/ExifTool/OOXML.pm b/lib/Image/ExifTool/OOXML.pm new file mode 100644 index 0000000..78ea0b3 --- /dev/null +++ b/lib/Image/ExifTool/OOXML.pm @@ -0,0 +1,409 @@ +#------------------------------------------------------------------------------ +# File: OOXML.pm +# +# Description: Read Office Open XML+ZIP files +# +# Revisions: 2009/10/31 - P. Harvey Created +#------------------------------------------------------------------------------ + +package Image::ExifTool::OOXML; + +use strict; +use vars qw($VERSION); +use Image::ExifTool qw(:DataAccess :Utils); +use Image::ExifTool::XMP; +use Image::ExifTool::ZIP; + +$VERSION = '1.07'; + +# test for recognized OOXML document extensions +my %isOOXML = ( + DOCX => 1, DOCM => 1, + DOTX => 1, DOTM => 1, + POTX => 1, POTM => 1, + PPSX => 1, PPSM => 1, + PPTX => 1, PPTM => 1, THMX => 1, + XLAM => 1, + XLSX => 1, XLSM => 1, XLSB => 1, + XLTX => 1, XLTM => 1, +); + +# generate reverse lookup for file type based on MIME +my %fileType; +{ + my $type; + foreach $type (keys %isOOXML) { + $fileType{$Image::ExifTool::mimeType{$type}} = $type; + } +} + +# XML attributes to queue +my %queuedAttrs; +my %queueAttrs = ( + fmtid => 1, + pid => 1, + name => 1, +); + +# keep track of items in a vector (to accumulate as a list) +my $vectorCount; +my @vectorVals; + +# Office Open XML tags +%Image::ExifTool::OOXML::Main = ( + GROUPS => { 0 => 'XML', 1 => 'XML', 2 => 'Document' }, + PROCESS_PROC => \&Image::ExifTool::XMP::ProcessXMP, + VARS => { NO_ID => 1 }, + NOTES => q{ + The Office Open XML (OOXML) format was introduced with Microsoft Office 2007 + and is used by file types such as DOCX, PPTX and XLSX. These are + essentially ZIP archives containing XML files. The table below lists some + tags which have been observed in OOXML documents, but ExifTool will extract + any tags found from XML files of the OOXML document properties ("docProps") + directory. + + B<Tips:> + + 1) Structural ZIP tags may be ignored (if desired) with C<--ZIP:all> on the + command line. + + 2) Tags may be grouped by their document number in the ZIP archive with the + C<-g3> or C<-G3> option. + }, + # These tags all have 1:1 correspondence with FlashPix tags except for: + # OOXML FlashPix + # --------------- ------------- + # DocSecurity Security + # Application Software + # dc:Description Comments + # dc:Creator Author + Application => { }, + AppVersion => { }, + category => { }, + Characters => { }, + CharactersWithSpaces => { }, + CheckedBy => { }, + Client => { }, + Company => { }, + created => { + Name => 'CreateDate', + Groups => { 2 => 'Time' }, + Format => 'date', + PrintConv => '$self->ConvertDateTime($val)', + }, + createdType => { Hidden => 1, RawConv => 'undef' }, # ignore this XML type name + DateCompleted => { + Groups => { 2 => 'Time' }, + Format => 'date', + PrintConv => '$self->ConvertDateTime($val)', + }, + Department => { }, + Destination => { }, + Disposition => { }, + Division => { }, + DocSecurity => { + # (http://msdn.microsoft.com/en-us/library/documentformat.openxml.extendedproperties.documentsecurity.aspx) + PrintConv => { + 0 => 'None', + 1 => 'Password protected', + 2 => 'Read-only recommended', + 4 => 'Read-only enforced', + 8 => 'Locked for annotations', + }, + }, + DocumentNumber=> { }, + Editor => { Groups => { 2 => 'Author'} }, + ForwardTo => { }, + Group => { }, + HeadingPairs=> { }, + HiddenSlides=> { }, + HyperlinkBase=>{ }, + HyperlinksChanged => { PrintConv => { 'false' => 'No', 'true' => 'Yes' } }, + keywords => { }, + Language => { }, + lastModifiedBy => { Groups => { 2 => 'Author'} }, + lastPrinted => { + Groups => { 2 => 'Time' }, + Format => 'date', + PrintConv => '$self->ConvertDateTime($val)', + }, + Lines => { }, + LinksUpToDate=>{ PrintConv => { 'false' => 'No', 'true' => 'Yes' } }, + Mailstop => { }, + Manager => { }, + Matter => { }, + MMClips => { }, + modified => { + Name => 'ModifyDate', + Groups => { 2 => 'Time' }, + Format => 'date', + PrintConv => '$self->ConvertDateTime($val)', + }, + modifiedType=> { Hidden => 1, RawConv => 'undef' }, # ignore this XML type name + Notes => { }, + Office => { }, + Owner => { Groups => { 2 => 'Author'} }, + Pages => { }, + Paragraphs => { }, + PresentationFormat => { }, + Project => { }, + Publisher => { }, + Purpose => { }, + ReceivedFrom=> { }, + RecordedBy => { }, + RecordedDate=> { + Groups => { 2 => 'Time' }, + Format => 'date', + PrintConv => '$self->ConvertDateTime($val)', + }, + Reference => { }, + revision => { Name => 'RevisionNumber' }, + ScaleCrop => { PrintConv => { 'false' => 'No', 'true' => 'Yes' } }, + SharedDoc => { PrintConv => { 'false' => 'No', 'true' => 'Yes' } }, + Slides => { }, + Source => { }, + Status => { }, + TelephoneNumber => { }, + Template => { }, + TitlesOfParts=>{ }, + TotalTime => { + Name => 'TotalEditTime', + PrintConv => 'ConvertTimeSpan($val, 60)', + }, + Typist => { }, + Words => { }, +); + +#------------------------------------------------------------------------------ +# Generate a tag ID for this XML tag +# Inputs: 0) tag property name list ref +# Returns: tagID and outtermost interesting namespace (or '' if no namespace) +sub GetTagID($) +{ + my $props = shift; + my ($tag, $prop, $namespace); + foreach $prop (@$props) { + # split name into namespace and property name + # (Note: namespace can be '' for property qualifiers) + my ($ns, $nm) = ($prop =~ /(.*?):(.*)/) ? ($1, $2) : ('', $prop); + next if $ns eq 'vt'; # ignore 'vt' properties + if (defined $tag) { + $tag .= ucfirst($nm); # add to tag name + } elsif ($prop ne 'Properties' and $prop ne 'cp:coreProperties' and + $prop ne 'property') + { + $tag = $nm; + # save namespace of first property to contribute to tag name + $namespace = $ns unless $namespace; + } + } + return ($tag, $namespace || ''); +} + +#------------------------------------------------------------------------------ +# We found an XMP property name/value +# Inputs: 0) ExifTool object ref, 1) tag table ref +# 2) reference to array of XMP property names (last is current property) +# 3) property value, 4) attribute hash ref (not used here) +# Returns: 1 if valid tag was found +sub FoundTag($$$$;$) +{ + my ($et, $tagTablePtr, $props, $val, $attrs) = @_; + return 0 unless @$props; + my $verbose = $et->Options('Verbose'); + + my $tag = $$props[-1]; + $et->VPrint(0, " | - Tag '", join('/',@$props), "'\n") if $verbose > 1; + + # un-escape XML character entities + $val = Image::ExifTool::XMP::UnescapeXML($val); + # convert OOXML-escaped characters (eg. "_x0000d_" is a newline) + $val =~ s/_x([0-9a-f]{4})_/Image::ExifTool::PackUTF8(hex($1))/gie; + # convert from UTF8 to ExifTool Charset + $val = $et->Decode($val, 'UTF8'); + # queue this attribute for later if necessary + if ($queueAttrs{$tag}) { + $queuedAttrs{$tag} = $val; + return 0; + } + my $ns; + ($tag, $ns) = GetTagID($props); + if (not $tag) { + # all properties are in ignored namespaces + # so 'name' from our queued attributes for the tag + my $name = $queuedAttrs{name} or return 0; + $name =~ s/(^| )([a-z])/$1\U$2/g; # start words with uppercase + ($tag = $name) =~ tr/-_a-zA-Z0-9//dc; + return 0 unless length $tag; + unless ($$tagTablePtr{$tag}) { + my %tagInfo = ( + Name => $tag, + Description => $name, + ); + # format as a date/time value if type is 'vt:filetime' + if ($$props[-1] eq 'vt:filetime') { + $tagInfo{Groups} = { 2 => 'Time' }, + $tagInfo{Format} = 'date', + $tagInfo{PrintConv} = '$self->ConvertDateTime($val)'; + } + $et->VPrint(0, " | [adding $tag]\n") if $verbose; + AddTagToTable($tagTablePtr, $tag, \%tagInfo); + } + } elsif ($tag eq 'xmlns') { + # ignore namespaces (for now) + return 0; + } elsif (ref $Image::ExifTool::XMP::Main{$ns} eq 'HASH' and + $Image::ExifTool::XMP::Main{$ns}{SubDirectory}) + { + # use standard XMP table if it exists + my $table = $Image::ExifTool::XMP::Main{$ns}{SubDirectory}{TagTable}; + no strict 'refs'; + if ($table and %$table) { + $tagTablePtr = Image::ExifTool::GetTagTable($table); + } + } elsif (@$props > 2 and grep /^vt:vector$/, @$props) { + # handle vector properties (accumulate as lists) + if ($$props[-1] eq 'vt:size') { + $vectorCount = $val; + undef @vectorVals; + return 0; + } elsif ($$props[-1] eq 'vt:baseType') { + return 0; # ignore baseType + } elsif ($vectorCount) { + --$vectorCount; + if ($vectorCount) { + push @vectorVals, $val; + return 0; + } + $val = [ @vectorVals, $val ] if @vectorVals; + # Note: we will lose any improper-sized vector elements here + } + } + # add any unknown tags to table + if ($$tagTablePtr{$tag}) { + my $tagInfo = $$tagTablePtr{$tag}; + if (ref $tagInfo eq 'HASH') { + # reformat date/time values + my $fmt = $$tagInfo{Format} || $$tagInfo{Writable} || ''; + $val = Image::ExifTool::XMP::ConvertXMPDate($val) if $fmt eq 'date'; + } + } else { + $et->VPrint(0, " [adding $tag]\n") if $verbose; + AddTagToTable($tagTablePtr, $tag, { Name => ucfirst $tag }); + } + # save the tag + $et->HandleTag($tagTablePtr, $tag, $val); + + # start fresh for next tag + undef $vectorCount; + undef %queuedAttrs; + + return 1; +} + +#------------------------------------------------------------------------------ +# Extract information from an OOXML file +# Inputs: 0) ExifTool object reference, 1) dirInfo reference +# Returns: 1 +# Notes: Upon entry to this routine, the file type has already been verified +# and the dirInfo hash contains 2 elements unique to this process proc: +# MIME - mime type of main document from "[Content_Types].xml" +# ZIP - reference to Archive::Zip object for this file +sub ProcessDOCX($$) +{ + my ($et, $dirInfo) = @_; + my $zip = $$dirInfo{ZIP}; + my $tagTablePtr = GetTagTable('Image::ExifTool::OOXML::Main'); + my $mime = $$dirInfo{MIME} || $Image::ExifTool::mimeType{DOCX}; + + # set the file type ('DOCX' by default) + my $fileType = $fileType{$mime}; + if ($fileType) { + # THMX is a special case because its contents.main MIME types is PPTX + if ($fileType eq 'PPTX' and $$et{FILE_EXT} and $$et{FILE_EXT} eq 'THMX') { + $fileType = 'THMX'; + } + } else { + $et->VPrint(0, "Unrecognized MIME type: $mime\n"); + # get MIME type according to file extension + $fileType = $$et{FILE_EXT}; + # default to 'DOCX' if this isn't a known OOXML extension + $fileType = 'DOCX' unless $fileType and $isOOXML{$fileType}; + } + $et->SetFileType($fileType); + + # must catch all Archive::Zip warnings + local $SIG{'__WARN__'} = \&Image::ExifTool::ZIP::WarnProc; + # extract meta information from all files in ZIP "docProps" directory + my $docNum = 0; + my @members = $zip->members(); + my $member; + foreach $member (@members) { + # get filename of this ZIP member + my $file = $member->fileName(); + next unless defined $file; + $et->VPrint(0, "File: $file\n"); + # set the document number and extract ZIP tags + $$et{DOC_NUM} = ++$docNum; + Image::ExifTool::ZIP::HandleMember($et, $member); + # process only XML and JPEG/WMF thumbnail images in "docProps" directory + next unless $file =~ m{^docProps/(.*\.xml|(thumbnail\.(jpe?g|wmf)))$}i; + # get the file contents (CAREFUL! $buff MUST be local since we hand off a value ref) + my ($buff, $status) = $zip->contents($member); + $status and $et->Warn("Error extracting $file"), next; + # extract docProps/thumbnail.(jpg|mwf) as PreviewImage|PreviewMWF + if ($file =~ /\.(jpe?g|wmf)$/i) { + my $tag = $file =~ /\.wmf$/i ? 'PreviewWMF' : 'PreviewImage'; + $et->FoundTag($tag, \$buff); + next; + } + # process XML files (docProps/app.xml, docProps/core.xml, docProps/custom.xml) + my %dirInfo = ( + DataPt => \$buff, + DirLen => length $buff, + DataLen => length $buff, + XMPParseOpts => { + FoundProc => \&FoundTag, + }, + ); + $et->ProcessDirectory(\%dirInfo, $tagTablePtr); + undef $buff; # (free memory now) + } + delete $$et{DOC_NUM}; + return 1; +} + +1; # end + +__END__ + +=head1 NAME + +Image::ExifTool::OOXML - Read Office Open XML+ZIP files + +=head1 SYNOPSIS + +This module is used by Image::ExifTool + +=head1 DESCRIPTION + +This module contains definitions required by Image::ExifTool to extract meta +information from Office Open XML files. This is the format of Word, Excel +and PowerPoint files written by Microsoft Office 2007 -- essentially ZIP +archives of XML files. + +=head1 AUTHOR + +Copyright 2003-2019, Phil Harvey (phil at owl.phy.queensu.ca) + +This library is free software; you can redistribute it and/or modify it +under the same terms as Perl itself. + +=head1 SEE ALSO + +L<Image::ExifTool::TagNames/OOXML Tags>, +L<Image::ExifTool::TagNames/FlashPix Tags>, +L<Image::ExifTool(3pm)|Image::ExifTool> + +=cut + diff --git a/lib/Image/ExifTool/Ogg.pm b/lib/Image/ExifTool/Ogg.pm new file mode 100644 index 0000000..0cc498d --- /dev/null +++ b/lib/Image/ExifTool/Ogg.pm @@ -0,0 +1,240 @@ +#------------------------------------------------------------------------------ +# File: Ogg.pm +# +# Description: Read Ogg meta information +# +# Revisions: 2011/07/13 - P. Harvey Created (split from Vorbis.pm) +# 2016/07/14 - PH Added Ogg Opus support +# +# References: 1) http://www.xiph.org/vorbis/doc/ +# 2) http://flac.sourceforge.net/ogg_mapping.html +# 3) http://www.theora.org/doc/Theora.pdf +#------------------------------------------------------------------------------ + +package Image::ExifTool::Ogg; + +use strict; +use vars qw($VERSION); +use Image::ExifTool qw(:DataAccess :Utils); + +$VERSION = '1.02'; + +my $MAX_PACKETS = 2; # maximum packets to scan from each stream at start of file + +# Information types recognizedi in Ogg files +%Image::ExifTool::Ogg::Main = ( + NOTES => q{ + ExifTool extracts the following types of information from Ogg files. See + L<http://www.xiph.org/vorbis/doc/> for the Ogg specification. + }, + # (these are for documentation purposes only, and aren't used by the code below) + vorbis => { SubDirectory => { TagTable => 'Image::ExifTool::Vorbis::Main' } }, + theora => { SubDirectory => { TagTable => 'Image::ExifTool::Theora::Main' } }, + Opus => { SubDirectory => { TagTable => 'Image::ExifTool::Opus::Main' } }, + FLAC => { SubDirectory => { TagTable => 'Image::ExifTool::FLAC::Main' } }, + ID3 => { SubDirectory => { TagTable => 'Image::ExifTool::ID3::Main' } }, +); + +#------------------------------------------------------------------------------ +# Process Ogg packet +# Inputs: 0) ExifTool object ref, 1) data ref +# Returns: 1 on success +sub ProcessPacket($$) +{ + my ($et, $dataPt) = @_; + my $rtnVal = 0; + if ($$dataPt =~ /^(.)(vorbis|theora)/s or $$dataPt =~ /^(OpusHead|OpusTags)/) { + my ($tag, $type, $pos) = $2 ? (ord($1), ucfirst($2), 7) : ($1, 'Opus', 8); + # this is an OGV file if it contains Theora video + $et->OverrideFileType('OGV') if $type eq 'Theora' and $$et{FILE_TYPE} eq 'OGG'; + $et->OverrideFileType('OPUS') if $type eq 'Opus' and $$et{FILE_TYPE} eq 'OGG'; + my $tagTablePtr = GetTagTable("Image::ExifTool::${type}::Main"); + my $tagInfo = $et->GetTagInfo($tagTablePtr, $tag); + return 0 unless $tagInfo and $$tagInfo{SubDirectory}; + my $subdir = $$tagInfo{SubDirectory}; + my %dirInfo = ( + DataPt => $dataPt, + DirName => $$tagInfo{Name}, + DirStart => $pos, + ); + my $table = GetTagTable($$subdir{TagTable}); + # set group1 so Theoris comments can be distinguised from Vorbis comments + $$et{SET_GROUP1} = $type if $type eq 'Theora'; + SetByteOrder($$subdir{ByteOrder}) if $$subdir{ByteOrder}; + $rtnVal = $et->ProcessDirectory(\%dirInfo, $table); + SetByteOrder('II'); + delete $$et{SET_GROUP1}; + } + return $rtnVal; +} + +#------------------------------------------------------------------------------ +# Extract information from an Ogg file +# Inputs: 0) ExifTool object reference, 1) dirInfo reference +# Returns: 1 on success, 0 if this wasn't a valid Ogg file +sub ProcessOGG($$) +{ + my ($et, $dirInfo) = @_; + + # must first check for leading/trailing ID3 information + unless ($$et{DoneID3}) { + require Image::ExifTool::ID3; + Image::ExifTool::ID3::ProcessID3($et, $dirInfo) and return 1; + } + my $raf = $$dirInfo{RAF}; + my $verbose = $et->Options('Verbose'); + my $out = $et->Options('TextOut'); + my ($success, $page, $packets, $streams, $stream) = (0,0,0,0,''); + my ($buff, $flag, %val, $numFlac, %streamPage); + + for (;;) { + # must read ahead to next page to see if it is a continuation + # (this code would be a lot simpler if the continuation flag + # was on the leading instead of the trailing page!) + if ($raf and $raf->Read($buff, 28) == 28) { + # validate magic number + unless ($buff =~ /^OggS/) { + $success and $et->Warn('Lost synchronization'); + last; + } + unless ($success) { + # set file type and initialize on first page + $success = 1; + $et->SetFileType(); + SetByteOrder('II'); + } + $flag = Get8u(\$buff, 5); # page flag + $stream = Get32u(\$buff, 14); # stream serial number + if ($flag & 0x02) { + ++$streams; # count start-of-stream pages + $streamPage{$stream} = $page = 0; + } else { + $page = $streamPage{$stream}; + } + ++$packets unless $flag & 0x01; # keep track of packet count + } else { + # all done unless we have to process our last packet + last unless %val; + ($stream) = sort keys %val; # take a stream + $flag = 0; # no continuation + undef $raf; # flag for done reading + } + + if (defined $numFlac) { + # stop to process FLAC headers if we hit the end of file + last unless $raf; + --$numFlac; # one less header packet to read + } else { + # can finally process previous packet from this stream + # unless this is a continuation page + if (defined $val{$stream} and not $flag & 0x01) { + ProcessPacket($et, \$val{$stream}); + delete $val{$stream}; + # only read the first $MAX_PACKETS packets from each stream + if ($packets > $MAX_PACKETS * $streams or not defined $raf) { + last unless %val; # all done (success!) + } + } + # stop processing Ogg if we have scanned enough packets + last if $packets > $MAX_PACKETS * $streams and not %val; + } + + # continue processing the current page + my $pageNum = Get32u(\$buff, 18); # page sequence number + my $nseg = Get8u(\$buff, 26); # number of segments + # calculate total data length + my $dataLen = Get8u(\$buff, 27); + if ($nseg) { + $raf->Read($buff, $nseg-1) == $nseg-1 or last; + my @segs = unpack('C*', $buff); + # could check that all these (but the last) are 255... + foreach (@segs) { $dataLen += $_ } + } + if (defined $page) { + if ($page == $pageNum) { + $streamPage{$stream} = ++$page; + } else { + $et->Warn('Missing page(s) in Ogg file'); + undef $page; + delete $streamPage{$stream}; + } + } + # read page data + $raf->Read($buff, $dataLen) == $dataLen or last; + if ($verbose > 1) { + printf $out "Page %d, stream 0x%x, flag 0x%x (%d bytes)\n", + $pageNum, $stream, $flag, $dataLen; + $et->VerboseDump(\$buff, DataPos => $raf->Tell() - $dataLen); + } + if (defined $val{$stream}) { + $val{$stream} .= $buff; # add this continuation page + } elsif (not $flag & 0x01) { # ignore remaining pages of a continued packet + # ignore the first page of any packet we aren't parsing + if ($buff =~ /^(.(vorbis|theora)|Opus(Head|Tags))/s) { + $val{$stream} = $buff; # save this page + } elsif ($buff =~ /^\x7fFLAC..(..)/s) { + $numFlac = unpack('n',$1); + $val{$stream} = substr($buff, 9); + } + } + if (defined $numFlac) { + # stop to process FLAC headers if we have them all + last if $numFlac <= 0; + } elsif (defined $val{$stream} and $flag & 0x04) { + # process Ogg packet now if end-of-stream bit is set + ProcessPacket($et, \$val{$stream}); + delete $val{$stream}; + } + } + if (defined $numFlac and defined $val{$stream}) { + # process FLAC headers as if it was a complete FLAC file + require Image::ExifTool::FLAC; + my %dirInfo = ( RAF => new File::RandomAccess(\$val{$stream}) ); + Image::ExifTool::FLAC::ProcessFLAC($et, \%dirInfo); + } + return $success; +} + +1; # end + +__END__ + +=head1 NAME + +Image::ExifTool::Ogg - Read Ogg meta information + +=head1 SYNOPSIS + +This module is used by Image::ExifTool + +=head1 DESCRIPTION + +This module contains definitions required by Image::ExifTool to extract meta +information from Ogg bitstream container files. + +=head1 AUTHOR + +Copyright 2003-2019, Phil Harvey (phil at owl.phy.queensu.ca) + +This library is free software; you can redistribute it and/or modify it +under the same terms as Perl itself. + +=head1 REFERENCES + +=over 4 + +=item L<http://www.xiph.org/vorbis/doc/> + +=item L<http://flac.sourceforge.net/ogg_mapping.html> + +=item L<http://www.theora.org/doc/Theora.pdf> + +=back + +=head1 SEE ALSO + +L<Image::ExifTool::TagNames/Ogg Tags>, +L<Image::ExifTool(3pm)|Image::ExifTool> + +=cut + diff --git a/lib/Image/ExifTool/Olympus.pm b/lib/Image/ExifTool/Olympus.pm new file mode 100644 index 0000000..f22a243 --- /dev/null +++ b/lib/Image/ExifTool/Olympus.pm @@ -0,0 +1,4037 @@ +#------------------------------------------------------------------------------ +# File: Olympus.pm +# +# Description: Olympus/Epson EXIF maker notes tags +# +# Revisions: 12/09/2003 - P. Harvey Created +# 11/11/2004 - P. Harvey Added Epson support +# +# References: 1) http://park2.wakwak.com/~tsuruzoh/Computer/Digicams/exif-e.html +# 2) http://www.cybercom.net/~dcoffin/dcraw/ +# 3) http://www.ozhiker.com/electronics/pjmt/jpeg_info/olympus_mn.html +# 4) Markku HŠnninen private communication (tests with E-1) +# 5) RŽmi Guyomarch from http://forums.dpreview.com/forums/read.asp?forum=1022&message=12790396 +# 6) Frank Ledwon private communication (tests with E/C-series cameras) +# 7) Michael Meissner private communication +# 8) Shingo Noguchi, PhotoXP (http://www.daifukuya.com/photoxp/) +# 9) Mark Dapoz private communication +# 10) Lilo Huang private communication (E-330) +# 11) http://olypedia.de/Olympus_Makernotes (May 30, 2013) +# 12) Ioannis Panagiotopoulos private communication (E-510) +# 13) Chris Shaw private communication (E-3) +# 14) Viktor Lushnikov private communication (E-400) +# 15) Yrjo Rauste private communication (E-30) +# 16) Godfrey DiGiorgi private communcation (E-P1) + http://forums.dpreview.com/forums/read.asp?message=33187567 +# 17) Martin Hibers private communication +# 18) Tomasz Kawecki private communication +# 19) Brad Grier private communication +# 22) Herbert Kauer private communication +# 23) Daniel Pollock private communication (PEN-F) +# IB) Iliah Borg private communication (LibRaw) +# NJ) Niels Kristian Bech Jensen private communication +#------------------------------------------------------------------------------ + +package Image::ExifTool::Olympus; + +use strict; +use vars qw($VERSION); +use Image::ExifTool qw(:DataAccess :Utils); +use Image::ExifTool::Exif; +use Image::ExifTool::APP12; + +$VERSION = '2.57'; + +sub PrintLensInfo($$$); + +my %offOn = ( 0 => 'Off', 1 => 'On' ); + +# lookup for Olympus LensType values +# (as of ExifTool 9.15, this was the complete list of chipped lenses at www.four-thirds.org) +my %olympusLensTypes = ( + Notes => q{ + The numerical values below are given in hexadecimal. (Prior to ExifTool + 9.15 these were in decimal.) + }, + '0 00 00' => 'None', + # Olympus lenses (also Kenko Tokina) + '0 01 00' => 'Olympus Zuiko Digital ED 50mm F2.0 Macro', + '0 01 01' => 'Olympus Zuiko Digital 40-150mm F3.5-4.5', #8 + '0 01 10' => 'Olympus M.Zuiko Digital ED 14-42mm F3.5-5.6', #PH (E-P1 pre-production) + '0 02 00' => 'Olympus Zuiko Digital ED 150mm F2.0', + '0 02 10' => 'Olympus M.Zuiko Digital 17mm F2.8 Pancake', #PH (E-P1 pre-production) + '0 03 00' => 'Olympus Zuiko Digital ED 300mm F2.8', + '0 03 10' => 'Olympus M.Zuiko Digital ED 14-150mm F4.0-5.6 [II]', #11 (The second version of this lens seems to have the same lens ID number as the first version #NJ) + '0 04 10' => 'Olympus M.Zuiko Digital ED 9-18mm F4.0-5.6', #11 + '0 05 00' => 'Olympus Zuiko Digital 14-54mm F2.8-3.5', + '0 05 01' => 'Olympus Zuiko Digital Pro ED 90-250mm F2.8', #9 + '0 05 10' => 'Olympus M.Zuiko Digital ED 14-42mm F3.5-5.6 L', #11 (E-PL1) + '0 06 00' => 'Olympus Zuiko Digital ED 50-200mm F2.8-3.5', + '0 06 01' => 'Olympus Zuiko Digital ED 8mm F3.5 Fisheye', #9 + '0 06 10' => 'Olympus M.Zuiko Digital ED 40-150mm F4.0-5.6', #PH + '0 07 00' => 'Olympus Zuiko Digital 11-22mm F2.8-3.5', + '0 07 01' => 'Olympus Zuiko Digital 18-180mm F3.5-6.3', #6 + '0 07 10' => 'Olympus M.Zuiko Digital ED 12mm F2.0', #PH + '0 08 01' => 'Olympus Zuiko Digital 70-300mm F4.0-5.6', #7 (seen as release 1 - PH) + '0 08 10' => 'Olympus M.Zuiko Digital ED 75-300mm F4.8-6.7', #PH + '0 09 10' => 'Olympus M.Zuiko Digital 14-42mm F3.5-5.6 II', #PH (E-PL2) + '0 10 01' => 'Kenko Tokina Reflex 300mm F6.3 MF Macro', #NJ + '0 10 10' => 'Olympus M.Zuiko Digital ED 12-50mm F3.5-6.3 EZ', #PH + '0 11 10' => 'Olympus M.Zuiko Digital 45mm F1.8', #17 + '0 12 10' => 'Olympus M.Zuiko Digital ED 60mm F2.8 Macro', #NJ + '0 13 10' => 'Olympus M.Zuiko Digital 14-42mm F3.5-5.6 II R', #PH/NJ + '0 14 10' => 'Olympus M.Zuiko Digital ED 40-150mm F4.0-5.6 R', #19 + # '0 14 10.1' => 'Olympus M.Zuiko Digital ED 14-150mm F4.0-5.6 II', #11 (questionable & unconfirmed -- all samples I can find are '0 3 10' - PH) + '0 15 00' => 'Olympus Zuiko Digital ED 7-14mm F4.0', + '0 15 10' => 'Olympus M.Zuiko Digital ED 75mm F1.8', #PH + '0 16 10' => 'Olympus M.Zuiko Digital 17mm F1.8', #NJ + '0 17 00' => 'Olympus Zuiko Digital Pro ED 35-100mm F2.0', #7 + '0 18 00' => 'Olympus Zuiko Digital 14-45mm F3.5-5.6', + '0 18 10' => 'Olympus M.Zuiko Digital ED 75-300mm F4.8-6.7 II', #NJ + '0 19 10' => 'Olympus M.Zuiko Digital ED 12-40mm F2.8 Pro', #PH + '0 20 00' => 'Olympus Zuiko Digital 35mm F3.5 Macro', #9 + '0 20 10' => 'Olympus M.Zuiko Digital ED 40-150mm F2.8 Pro', #NJ + '0 21 10' => 'Olympus M.Zuiko Digital ED 14-42mm F3.5-5.6 EZ', #NJ + '0 22 00' => 'Olympus Zuiko Digital 17.5-45mm F3.5-5.6', #9 + '0 22 10' => 'Olympus M.Zuiko Digital 25mm F1.8', #NJ + '0 23 00' => 'Olympus Zuiko Digital ED 14-42mm F3.5-5.6', #PH + '0 23 10' => 'Olympus M.Zuiko Digital ED 7-14mm F2.8 Pro', #NJ + '0 24 00' => 'Olympus Zuiko Digital ED 40-150mm F4.0-5.6', #PH + '0 24 10' => 'Olympus M.Zuiko Digital ED 300mm F4.0 IS Pro', #NJ + '0 25 10' => 'Olympus M.Zuiko Digital ED 8mm F1.8 Fisheye Pro', #NJ + '0 26 10' => 'Olympus M.Zuiko Digital ED 12-100mm F4.0 IS Pro', #IB/NJ + '0 27 10' => 'Olympus M.Zuiko Digital ED 30mm F3.5 Macro', #IB/NJ + '0 28 10' => 'Olympus M.Zuiko Digital ED 25mm F1.2 Pro', #IB/NJ + '0 29 10' => 'Olympus M.Zuiko Digital ED 17mm F1.2 Pro', #IB + '0 30 00' => 'Olympus Zuiko Digital ED 50-200mm F2.8-3.5 SWD', #7 + '0 30 10' => 'Olympus M.Zuiko Digital ED 45mm F1.2 Pro', #IB + '0 31 00' => 'Olympus Zuiko Digital ED 12-60mm F2.8-4.0 SWD', #7 + '0 32 00' => 'Olympus Zuiko Digital ED 14-35mm F2.0 SWD', #PH + '0 32 10' => 'Olympus M.Zuiko Digital ED 12-200mm F3.5-6.3', #IB + '0 33 00' => 'Olympus Zuiko Digital 25mm F2.8', #PH + '0 34 00' => 'Olympus Zuiko Digital ED 9-18mm F4.0-5.6', #7 + '0 35 00' => 'Olympus Zuiko Digital 14-54mm F2.8-3.5 II', #PH + # Sigma lenses + '1 01 00' => 'Sigma 18-50mm F3.5-5.6 DC', #8 + '1 01 10' => 'Sigma 30mm F2.8 EX DN', #NJ + '1 02 00' => 'Sigma 55-200mm F4.0-5.6 DC', + '1 02 10' => 'Sigma 19mm F2.8 EX DN', #NJ + '1 03 00' => 'Sigma 18-125mm F3.5-5.6 DC', + '1 03 10' => 'Sigma 30mm F2.8 DN | A', #NJ + '1 04 00' => 'Sigma 18-125mm F3.5-5.6 DC', #7 + '1 04 10' => 'Sigma 19mm F2.8 DN | A', #NJ + '1 05 00' => 'Sigma 30mm F1.4 EX DC HSM', #10 + '1 05 10' => 'Sigma 60mm F2.8 DN | A', #NJ + '1 06 00' => 'Sigma APO 50-500mm F4.0-6.3 EX DG HSM', #6 + '1 06 10' => 'Sigma 30mm F1.4 DC DN | C', #NJ + '1 07 00' => 'Sigma Macro 105mm F2.8 EX DG', #PH + '1 07 10' => 'Sigma 16mm F1.4 DC DN | C (017)', #IB + '1 08 00' => 'Sigma APO Macro 150mm F2.8 EX DG HSM', #PH + '1 09 00' => 'Sigma 18-50mm F2.8 EX DC Macro', #NJ + '1 10 00' => 'Sigma 24mm F1.8 EX DG Aspherical Macro', #PH + '1 11 00' => 'Sigma APO 135-400mm F4.5-5.6 DG', #11 + '1 12 00' => 'Sigma APO 300-800mm F5.6 EX DG HSM', #11 + '1 13 00' => 'Sigma 30mm F1.4 EX DC HSM', #11 + '1 14 00' => 'Sigma APO 50-500mm F4.0-6.3 EX DG HSM', #11 + '1 15 00' => 'Sigma 10-20mm F4.0-5.6 EX DC HSM', #11 + '1 16 00' => 'Sigma APO 70-200mm F2.8 II EX DG Macro HSM', #11 + '1 17 00' => 'Sigma 50mm F1.4 EX DG HSM', #11 + # Panasonic/Leica lenses + '2 01 00' => 'Leica D Vario Elmarit 14-50mm F2.8-3.5 Asph.', #11 + '2 01 10' => 'Lumix G Vario 14-45mm F3.5-5.6 Asph. Mega OIS', #16 + '2 02 00' => 'Leica D Summilux 25mm F1.4 Asph.', #11 + '2 02 10' => 'Lumix G Vario 45-200mm F4.0-5.6 Mega OIS', #16 + '2 03 00' => 'Leica D Vario Elmar 14-50mm F3.8-5.6 Asph. Mega OIS', #11 + '2 03 01' => 'Leica D Vario Elmar 14-50mm F3.8-5.6 Asph.', #14 (L10 kit) + '2 03 10' => 'Lumix G Vario HD 14-140mm F4.0-5.8 Asph. Mega OIS', #16 + '2 04 00' => 'Leica D Vario Elmar 14-150mm F3.5-5.6', #13 + '2 04 10' => 'Lumix G Vario 7-14mm F4.0 Asph.', #PH (E-P1 pre-production) + '2 05 10' => 'Lumix G 20mm F1.7 Asph.', #16 + '2 06 10' => 'Leica DG Macro-Elmarit 45mm F2.8 Asph. Mega OIS', #PH + '2 07 10' => 'Lumix G Vario 14-42mm F3.5-5.6 Asph. Mega OIS', #NJ + '2 08 10' => 'Lumix G Fisheye 8mm F3.5', #PH + '2 09 10' => 'Lumix G Vario 100-300mm F4.0-5.6 Mega OIS', #11 + '2 10 10' => 'Lumix G 14mm F2.5 Asph.', #17 + '2 11 10' => 'Lumix G 12.5mm F12 3D', #NJ (H-FT012) + '2 12 10' => 'Leica DG Summilux 25mm F1.4 Asph.', #NJ + '2 13 10' => 'Lumix G X Vario PZ 45-175mm F4.0-5.6 Asph. Power OIS', #NJ + '2 14 10' => 'Lumix G X Vario PZ 14-42mm F3.5-5.6 Asph. Power OIS', #NJ + '2 15 10' => 'Lumix G X Vario 12-35mm F2.8 Asph. Power OIS', #PH + '2 16 10' => 'Lumix G Vario 45-150mm F4.0-5.6 Asph. Mega OIS', #NJ + '2 17 10' => 'Lumix G X Vario 35-100mm F2.8 Power OIS', #PH + '2 18 10' => 'Lumix G Vario 14-42mm F3.5-5.6 II Asph. Mega OIS', #NJ + '2 19 10' => 'Lumix G Vario 14-140mm F3.5-5.6 Asph. Power OIS', #NJ + '2 20 10' => 'Lumix G Vario 12-32mm F3.5-5.6 Asph. Mega OIS', #NJ + '2 21 10' => 'Leica DG Nocticron 42.5mm F1.2 Asph. Power OIS', #NJ + '2 22 10' => 'Leica DG Summilux 15mm F1.7 Asph.', #NJ + '2 23 10' => 'Lumix G Vario 35-100mm F4.0-5.6 Asph. Mega OIS', #NJ + '2 24 10' => 'Lumix G Macro 30mm F2.8 Asph. Mega OIS', #NJ + '2 25 10' => 'Lumix G 42.5mm F1.7 Asph. Power OIS', #NJ + '2 26 10' => 'Lumix G 25mm F1.7 Asph.', #NJ + '2 27 10' => 'Leica DG Vario-Elmar 100-400mm F4.0-6.3 Asph. Power OIS', #NJ + '2 28 10' => 'Lumix G Vario 12-60mm F3.5-5.6 Asph. Power OIS', #NJ + '3 01 00' => 'Leica D Vario Elmarit 14-50mm F2.8-3.5 Asph.', #11 + '3 02 00' => 'Leica D Summilux 25mm F1.4 Asph.', #11 + # Tamron lenses + '5 01 10' => 'Tamron 14-150mm F3.5-5.8 Di III', #NJ (model C001) +); + +# lookup for Olympus camera types (ref PH) +my %olympusCameraTypes = ( + Notes => q{ + These values are currently decoded only for Olympus models. Models with + Olympus-style maker notes from other brands such as Acer, BenQ, Hitachi, HP, + Premier, Konica-Minolta, Maginon, Ricoh, Rollei, SeaLife, Sony, Supra, + Vivitar are not listed. + }, + D4028 => 'X-2,C-50Z', + D4029 => 'E-20,E-20N,E-20P', + D4034 => 'C720UZ', + D4040 => 'E-1', + D4041 => 'E-300', + D4083 => 'C2Z,D520Z,C220Z', + D4106 => 'u20D,S400D,u400D', + D4120 => 'X-1', + D4122 => 'u10D,S300D,u300D', + D4125 => 'AZ-1', + D4141 => 'C150,D390', + D4193 => 'C-5000Z', + D4194 => 'X-3,C-60Z', + D4199 => 'u30D,S410D,u410D', + D4205 => 'X450,D535Z,C370Z', + D4210 => 'C160,D395', + D4211 => 'C725UZ', + D4213 => 'FerrariMODEL2003', + D4216 => 'u15D', + D4217 => 'u25D', + D4220 => 'u-miniD,Stylus V', + D4221 => 'u40D,S500,uD500', + D4231 => 'FerrariMODEL2004', + D4240 => 'X500,D590Z,C470Z', + D4244 => 'uD800,S800', + D4256 => 'u720SW,S720SW', + D4261 => 'X600,D630,FE5500', + D4262 => 'uD600,S600', + D4301 => 'u810/S810', # (yes, "/". Olympus is not consistent in the notation) + D4302 => 'u710,S710', + D4303 => 'u700,S700', + D4304 => 'FE100,X710', + D4305 => 'FE110,X705', + D4310 => 'FE-130,X-720', + D4311 => 'FE-140,X-725', + D4312 => 'FE150,X730', + D4313 => 'FE160,X735', + D4314 => 'u740,S740', + D4315 => 'u750,S750', + D4316 => 'u730/S730', + D4317 => 'FE115,X715', + D4321 => 'SP550UZ', + D4322 => 'SP510UZ', + D4324 => 'FE170,X760', + D4326 => 'FE200', + D4327 => 'FE190/X750', # (also SX876) + D4328 => 'u760,S760', + D4330 => 'FE180/X745', # (also SX875) + D4331 => 'u1000/S1000', + D4332 => 'u770SW,S770SW', + D4333 => 'FE240/X795', + D4334 => 'FE210,X775', + D4336 => 'FE230/X790', + D4337 => 'FE220,X785', + D4338 => 'u725SW,S725SW', + D4339 => 'FE250/X800', + D4341 => 'u780,S780', + D4343 => 'u790SW,S790SW', + D4344 => 'u1020,S1020', + D4346 => 'FE15,X10', + D4348 => 'FE280,X820,C520', + D4349 => 'FE300,X830', + D4350 => 'u820,S820', + D4351 => 'u1200,S1200', + D4352 => 'FE270,X815,C510', + D4353 => 'u795SW,S795SW', + D4354 => 'u1030SW,S1030SW', + D4355 => 'SP560UZ', + D4356 => 'u1010,S1010', + D4357 => 'u830,S830', + D4359 => 'u840,S840', + D4360 => 'FE350WIDE,X865', + D4361 => 'u850SW,S850SW', + D4362 => 'FE340,X855,C560', + D4363 => 'FE320,X835,C540', + D4364 => 'SP570UZ', + D4366 => 'FE330,X845,C550', + D4368 => 'FE310,X840,C530', + D4370 => 'u1050SW,S1050SW', + D4371 => 'u1060,S1060', + D4372 => 'FE370,X880,C575', + D4374 => 'SP565UZ', + D4377 => 'u1040,S1040', + D4378 => 'FE360,X875,C570', + D4379 => 'FE20,X15,C25', + D4380 => 'uT6000,ST6000', + D4381 => 'uT8000,ST8000', + D4382 => 'u9000,S9000', + D4384 => 'SP590UZ', + D4385 => 'FE3010,X895', + D4386 => 'FE3000,X890', + D4387 => 'FE35,X30', + D4388 => 'u550WP,S550WP', + D4390 => 'FE5000,X905', + D4391 => 'u5000', + D4392 => 'u7000,S7000', + D4396 => 'FE5010,X915', + D4397 => 'FE25,X20', + D4398 => 'FE45,X40', + D4401 => 'XZ-1', + D4402 => 'uT6010,ST6010', + D4406 => 'u7010,S7010 / u7020,S7020', + D4407 => 'FE4010,X930', + D4408 => 'X560WP', + D4409 => 'FE26,X21', + D4410 => 'FE4000,X920,X925', + D4411 => 'FE46,X41,X42', + D4412 => 'FE5020,X935', + D4413 => 'uTough-3000', + D4414 => 'StylusTough-6020', + D4415 => 'StylusTough-8010', + D4417 => 'u5010,S5010', + D4418 => 'u7040,S7040', + D4419 => 'u9010,S9010', + D4423 => 'FE4040', + D4424 => 'FE47,X43', + D4426 => 'FE4030,X950', + D4428 => 'FE5030,X965,X960', + D4430 => 'u7030,S7030', + D4432 => 'SP600UZ', + D4434 => 'SP800UZ', + D4439 => 'FE4020,X940', + D4442 => 'FE5035', + D4448 => 'FE4050,X970', + D4450 => 'FE5050,X985', + D4454 => 'u-7050', + D4464 => 'T10,X27', + D4470 => 'FE5040,X980', + D4472 => 'TG-310', + D4474 => 'TG-610', + D4476 => 'TG-810', + D4478 => 'VG145,VG140,D715', + D4479 => 'VG130,D710', + D4480 => 'VG120,D705', + D4482 => 'VR310,D720', + D4484 => 'VR320,D725', + D4486 => 'VR330,D730', + D4488 => 'VG110,D700', + D4490 => 'SP-610UZ', + D4492 => 'SZ-10', + D4494 => 'SZ-20', + D4496 => 'SZ-30MR', + D4498 => 'SP-810UZ', + D4500 => 'SZ-11', + D4504 => 'TG-615', + D4508 => 'TG-620', + D4510 => 'TG-820', + D4512 => 'TG-1', + D4516 => 'SH-21', + D4519 => 'SZ-14', + D4520 => 'SZ-31MR', + D4521 => 'SH-25MR', + D4523 => 'SP-720UZ', + D4529 => 'VG170', + D4531 => 'XZ-2', + D4535 => 'SP-620UZ', + D4536 => 'TG-320', + D4537 => 'VR340,D750', + D4538 => 'VG160,X990,D745', + D4541 => 'SZ-12', + D4545 => 'VH410', + D4546 => 'XZ-10', #IB + D4547 => 'TG-2', + D4548 => 'TG-830', + D4549 => 'TG-630', + D4550 => 'SH-50', + D4553 => 'SZ-16,DZ-105', + D4562 => 'SP-820UZ', + D4566 => 'SZ-15', + D4572 => 'STYLUS1', + D4574 => 'TG-3', + D4575 => 'TG-850', + D4579 => 'SP-100EE', + D4580 => 'SH-60', + D4581 => 'SH-1', + D4582 => 'TG-835', + D4585 => 'SH-2 / SH-3', + D4586 => 'TG-4', + D4587 => 'TG-860', + D4591 => 'TG-870', + D4593 => 'TG-5', #IB + D4809 => 'C2500L', + D4842 => 'E-10', + D4856 => 'C-1', + D4857 => 'C-1Z,D-150Z', + DCHC => 'D500L', + DCHT => 'D600L / D620L', + K0055 => 'AIR-A01', + S0003 => 'E-330', + S0004 => 'E-500', + S0009 => 'E-400', + S0010 => 'E-510', + S0011 => 'E-3', + S0013 => 'E-410', + S0016 => 'E-420', + S0017 => 'E-30', + S0018 => 'E-520', + S0019 => 'E-P1', + S0023 => 'E-620', + S0026 => 'E-P2', + S0027 => 'E-PL1', + S0029 => 'E-450', + S0030 => 'E-600', + S0032 => 'E-P3', + S0033 => 'E-5', + S0034 => 'E-PL2', + S0036 => 'E-M5', + S0038 => 'E-PL3', + S0039 => 'E-PM1', + S0040 => 'E-PL1s', + S0042 => 'E-PL5', + S0043 => 'E-PM2', + S0044 => 'E-P5', + S0045 => 'E-PL6', + S0046 => 'E-PL7', #IB + S0047 => 'E-M1', + S0051 => 'E-M10', + S0052 => 'E-M5MarkII', #IB + S0059 => 'E-M10MarkII', + S0061 => 'PEN-F', #forum7005 + S0065 => 'E-PL8', + S0067 => 'E-M1MarkII', + S0068 => 'E-M10MarkIII', + S0076 => 'E-PL9', #IB + S0080 => 'E-M1X', #IB + SR45 => 'D220', + SR55 => 'D320L', + SR83 => 'D340L', + SR85 => 'C830L,D340R', + SR852 => 'C860L,D360L', + SR872 => 'C900Z,D400Z', + SR874 => 'C960Z,D460Z', + SR951 => 'C2000Z', + SR952 => 'C21', + SR953 => 'C21T.commu', + SR954 => 'C2020Z', + SR955 => 'C990Z,D490Z', + SR956 => 'C211Z', + SR959 => 'C990ZS,D490Z', + SR95A => 'C2100UZ', + SR971 => 'C100,D370', + SR973 => 'C2,D230', + SX151 => 'E100RS', + SX351 => 'C3000Z / C3030Z', + SX354 => 'C3040Z', + SX355 => 'C2040Z', + SX357 => 'C700UZ', + SX358 => 'C200Z,D510Z', + SX374 => 'C3100Z,C3020Z', + SX552 => 'C4040Z', + SX553 => 'C40Z,D40Z', + SX556 => 'C730UZ', + SX558 => 'C5050Z', + SX571 => 'C120,D380', + SX574 => 'C300Z,D550Z', + SX575 => 'C4100Z,C4000Z', + SX751 => 'X200,D560Z,C350Z', + SX752 => 'X300,D565Z,C450Z', + SX753 => 'C750UZ', + SX754 => 'C740UZ', + SX755 => 'C755UZ', + SX756 => 'C5060WZ', + SX757 => 'C8080WZ', + SX758 => 'X350,D575Z,C360Z', + SX759 => 'X400,D580Z,C460Z', + SX75A => 'AZ-2ZOOM', + SX75B => 'D595Z,C500Z', + SX75C => 'X550,D545Z,C480Z', + SX75D => 'IR-300', + SX75F => 'C55Z,C5500Z', + SX75G => 'C170,D425', + SX75J => 'C180,D435', + SX771 => 'C760UZ', + SX772 => 'C770UZ', + SX773 => 'C745UZ', + SX774 => 'X250,D560Z,C350Z', + SX775 => 'X100,D540Z,C310Z', + SX776 => 'C460ZdelSol', + SX777 => 'C765UZ', + SX77A => 'D555Z,C315Z', + SX851 => 'C7070WZ', + SX852 => 'C70Z,C7000Z', + SX853 => 'SP500UZ', + SX854 => 'SP310', + SX855 => 'SP350', + SX873 => 'SP320', + SX875 => 'FE180/X745', # (also D4330) + SX876 => 'FE190/X750', # (also D4327) +# other brands +# 4MP9Q3 => 'Camera 4MP-9Q3' +# 4MP9T2 => 'BenQ DC C420 / Camera 4MP-9T2' +# 5MP9Q3 => 'Camera 5MP-9Q3', +# 5MP9X9 => 'Camera 5MP-9X9', +# '5MP-9T'=> 'Camera 5MP-9T3', +# '5MP-9Y'=> 'Camera 5MP-9Y2', +# '6MP-9U'=> 'Camera 6MP-9U9', +# 7MP9Q3 => 'Camera 7MP-9Q3', +# '8MP-9U'=> 'Camera 8MP-9U4', +# CE5330 => 'Acer CE-5330', +# 'CP-853'=> 'Acer CP-8531', +# CS5531 => 'Acer CS5531', +# DC500 => 'SeaLife DC500', +# DC7370 => 'Camera 7MP-9GA', +# DC7371 => 'Camera 7MP-9GM', +# DC7371 => 'Hitachi HDC-751E', +# DC7375 => 'Hitachi HDC-763E / Rollei RCP-7330X / Ricoh Caplio RR770 / Vivitar ViviCam 7330', +# 'DC E63'=> 'BenQ DC E63+', +# 'DC P86'=> 'BenQ DC P860', +# DS5340 => 'Maginon Performic S5 / Premier 5MP-9M7', +# DS5341 => 'BenQ E53+ / Supra TCM X50 / Maginon X50 / Premier 5MP-9P8', +# DS5346 => 'Premier 5MP-9Q2', +# E500 => 'Konica Minolta DiMAGE E500', +# MAGINO => 'Maginon X60', +# Mz60 => 'HP Photosmart Mz60', +# Q3DIGI => 'Camera 5MP-9Q3', +# SLIMLI => 'Supra Slimline X6', +# V8300s => 'Vivitar V8300s', +); + +# ArtFilter, ArtFilterEffect and MagicFilter values (ref PH) +my %filters = ( + 0 => 'Off', + 1 => 'Soft Focus', # (XZ-1) + 2 => 'Pop Art', # (SZ-10 magic filter 1,SZ-31MR,E-M5,E-PL3) + 3 => 'Pale & Light Color', + 4 => 'Light Tone', + 5 => 'Pin Hole', # (SZ-10 magic filter 2,SZ-31MR,E-PL3) + 6 => 'Grainy Film', + 9 => 'Diorama', + 10 => 'Cross Process', + 12 => 'Fish Eye', # (SZ-10 magic filter 3) + 13 => 'Drawing', # (SZ-10 magic filter 4) + 14 => 'Gentle Sepia', # (E-5) + 15 => 'Pale & Light Color II', #forum6269 ('Tender Light' ref 11) + 16 => 'Pop Art II', #11 (E-PL3 "(dark)" - PH) + 17 => 'Pin Hole II', #11 (E-PL3 "(color 2)" - PH) + 18 => 'Pin Hole III', #11 (E-M5, E-PL3 "(color 3)" - PH) + 19 => 'Grainy Film II', #11 + 20 => 'Dramatic Tone', # (XZ-1,SZ-31MR) + 21 => 'Punk', # (SZ-10 magic filter 6) + 22 => 'Soft Focus 2', # (SZ-10 magic filter 5) + 23 => 'Sparkle', # (SZ-10 magic filter 7) + 24 => 'Watercolor', # (SZ-10 magic filter 8) + 25 => 'Key Line', # (E-M5) + 26 => 'Key Line II', #forum6269 + 27 => 'Miniature', # (SZ-31MR) + 28 => 'Reflection', # (TG-820,SZ-31MR) + 29 => 'Fragmented', # (TG-820,SZ-31MR) + 31 => 'Cross Process II', #forum6269 + 32 => 'Dramatic Tone II', #forum6269 (Dramatic Tone B&W for E-M5) + 33 => 'Watercolor I', # ('Watercolor I' for EM-1 ref forum6269, 'Watercolor II' for E-PM2 ref PH) + 34 => 'Watercolor II', #forum6269 + 35 => 'Diorama II', #forum6269 + 36 => 'Vintage', #forum6269 + 37 => 'Vintage II', #forum6269 + 38 => 'Vintage III', #forum6269 + 39 => 'Partial Color', #forum6269 + 40 => 'Partial Color II', #forum6269 + 41 => 'Partial Color III', #forum6269 +); + +my %toneLevelType = ( + 0 => '0', + -31999 => 'Highlights', + -31998 => 'Shadows', + -31997 => 'Midtones', +); + +# tag information for WAV "Index" tags +my %indexInfo = ( + Format => 'int32u', + RawConv => '$val == 0xffffffff ? undef : $val', + ValueConv => '$val / 1000', + PrintConv => 'ConvertDuration($val)', +); + +# Olympus tags +%Image::ExifTool::Olympus::Main = ( + WRITE_PROC => \&Image::ExifTool::Exif::WriteExif, + CHECK_PROC => \&Image::ExifTool::Exif::CheckExif, + WRITABLE => 1, + GROUPS => { 0 => 'MakerNotes', 2 => 'Camera' }, +# +# Tags 0x0000 through 0x0103 are the same as Konica/Minolta cameras (ref 3) +# (removed 0x0101-0x0103 because they weren't supported by my samples - PH) +# + 0x0000 => { + Name => 'MakerNoteVersion', + Writable => 'undef', + }, + 0x0001 => { + Name => 'MinoltaCameraSettingsOld', + SubDirectory => { + TagTable => 'Image::ExifTool::Minolta::CameraSettings', + ByteOrder => 'BigEndian', + }, + }, + 0x0003 => { + Name => 'MinoltaCameraSettings', + SubDirectory => { + TagTable => 'Image::ExifTool::Minolta::CameraSettings', + ByteOrder => 'BigEndian', + }, + }, + 0x0040 => { + Name => 'CompressedImageSize', + Writable => 'int32u', + }, + 0x0081 => { + Name => 'PreviewImageData', + Binary => 1, + Writable => 0, + }, + 0x0088 => { + Name => 'PreviewImageStart', + Flags => 'IsOffset', + OffsetPair => 0x0089, # point to associated byte count + DataTag => 'PreviewImage', + Writable => 0, + Protected => 2, + }, + 0x0089 => { + Name => 'PreviewImageLength', + OffsetPair => 0x0088, # point to associated offset + DataTag => 'PreviewImage', + Writable => 0, + Protected => 2, + }, + 0x0100 => { + Name => 'ThumbnailImage', + Groups => { 2 => 'Preview' }, + Writable => 'undef', + WriteCheck => '$self->CheckImage(\$val)', + Binary => 1, + }, + 0x0104 => { Name => 'BodyFirmwareVersion', Writable => 'string' }, #11 +# +# end Konica/Minolta tags +# + 0x0200 => { + Name => 'SpecialMode', + Notes => q{ + 3 numbers: 1. Shooting mode: 0=Normal, 2=Fast, 3=Panorama; + 2. Sequence Number; 3. Panorama Direction: 1=Left-right, + 2=Right-left, 3=Bottom-Top, 4=Top-Bottom + }, + Writable => 'int32u', + Count => 3, + PrintConv => sub { #3 + my $val = shift; + my @v = split ' ', $val; + return $val unless @v >= 3; + my @v0 = ('Normal','Unknown (1)','Fast','Panorama'); + my @v2 = ('(none)','Left to Right','Right to Left','Bottom to Top','Top to Bottom'); + $val = $v0[$v[0]] || "Unknown ($v[0])"; + $val .= ", Sequence: $v[1]"; + $val .= ', Panorama: ' . ($v2[$v[2]] || "Unknown ($v[2])"); + return $val; + }, + }, + 0x0201 => { + Name => 'Quality', + Writable => 'int16u', + Notes => q{ + Quality values are decoded based on the CameraType tag. All types + represent SQ, HQ and SHQ as sequential integers, but in general + SX-type cameras start with a value of 0 for SQ while others start + with 1 + }, + # These values are different for different camera types + # (can't have Condition based on CameraType because it isn't known + # when this tag is extracted) + PrintConv => sub { + my ($val, $self) = @_; + my %t1 = ( # all SX camera types except SX151 + 0 => 'SQ (Low)', + 1 => 'HQ (Normal)', + 2 => 'SHQ (Fine)', + 6 => 'RAW', #PH - C5050WZ + ); + my %t2 = ( # all other types (except D4322, ref 22) + 1 => 'SQ (Low)', + 2 => 'HQ (Normal)', + 3 => 'SHQ (Fine)', + 4 => 'RAW', + 5 => 'Medium-Fine', #PH + 6 => 'Small-Fine', #PH + 33 => 'Uncompressed', #PH - C2100Z + ); + my $conv = $self->{CameraType} =~ /^(SX(?!151\b)|D4322)/ ? \%t1 : \%t2; + return $$conv{$val} ? $$conv{$val} : "Unknown ($val)"; + }, + # (no PrintConvInv because we don't know CameraType at write time) + }, + 0x0202 => { + Name => 'Macro', + Writable => 'int16u', + PrintConv => { + 0 => 'Off', + 1 => 'On', + 2 => 'Super Macro', #6 + }, + }, + 0x0203 => { #6 + Name => 'BWMode', + Description => 'Black And White Mode', + Writable => 'int16u', + PrintConv => { + 0 => 'Off', + 1 => 'On', + 6 => '(none)', #22 + }, + }, + 0x0204 => { + Name => 'DigitalZoom', + Writable => 'rational64u', + PrintConv => '$val=~/\./ or $val.=".0"; $val', + PrintConvInv => '$val', + }, + 0x0205 => { #6 + Name => 'FocalPlaneDiagonal', + Writable => 'rational64u', + PrintConv => '"$val mm"', + PrintConvInv => '$val=~s/\s*mm$//;$val', + }, + 0x0206 => { Name => 'LensDistortionParams', Writable => 'int16s', Count => 6 }, #6 + 0x0207 => { #PH (was incorrectly FirmwareVersion, ref 1/3) + Name => 'CameraType', + Condition => '$$valPt ne "NORMAL"', # FE240, SP510, u730 and u1000 write this + Writable => 'string', + DataMember => 'CameraType', + RawConv => '$self->{CameraType} = $val', + SeparateTable => 'CameraType', + ValueConv => '$val =~ s/\s+$//; $val', # ("SX151 " has trailing space) + ValueConvInv => '$val', + PrintConv => \%olympusCameraTypes, + Priority => 0, + # 'NORMAL' for some models: u730,SP510UZ,u1000,FE240 + }, + 0x0208 => { + Name => 'TextInfo', + SubDirectory => { + TagTable => 'Image::ExifTool::Olympus::TextInfo', + }, + }, + 0x0209 => { + Name => 'CameraID', + Format => 'string', # this really should have been a string + }, + 0x020b => { Name => 'EpsonImageWidth', Writable => 'int16u' }, #PH + 0x020c => { Name => 'EpsonImageHeight', Writable => 'int16u' }, #PH + 0x020d => { Name => 'EpsonSoftware', Writable => 'string' }, #PH + 0x0280 => { #PH + %Image::ExifTool::previewImageTagInfo, + Groups => { 2 => 'Preview' }, + Notes => 'found in ERF and JPG images from some Epson models', + Format => 'undef', + Writable => 'int8u', + }, + 0x0300 => { Name => 'PreCaptureFrames', Writable => 'int16u' }, #6 + 0x0301 => { Name => 'WhiteBoard', Writable => 'int16u' }, #11 + 0x0302 => { #6 + Name => 'OneTouchWB', + Writable => 'int16u', + PrintConv => { + 0 => 'Off', + 1 => 'On', + 2 => 'On (Preset)', + }, + }, + 0x0303 => { Name => 'WhiteBalanceBracket', Writable => 'int16u' }, #11 + 0x0304 => { Name => 'WhiteBalanceBias', Writable => 'int16u' }, #11 + # 0x0305 => 'PrintMatching', ? #11 + 0x0401 => { #IB + Name => 'BlackLevel', + Condition => '$format eq "int32u" and $count == 4', + Writable => 'int32u', + Count => 4, + Notes => 'found in Epson ERF images', + }, + # 0x0402 - BitCodedAutoFocus (ref 11) + 0x0403 => { #11 + Name => 'SceneMode', + Writable => 'int16u', + PrintConvColumns => 2, + PrintConv => { + 0 => 'Normal', + 1 => 'Standard', + 2 => 'Auto', + 3 => 'Intelligent Auto', #PH (guess, u7040) + 4 => 'Portrait', + 5 => 'Landscape+Portrait', + 6 => 'Landscape', + 7 => 'Night Scene', + 8 => 'Night+Portrait', + 9 => 'Sport', + 10 => 'Self Portrait', + 11 => 'Indoor', + 12 => 'Beach & Snow', + 13 => 'Beach', + 14 => 'Snow', + 15 => 'Self Portrait+Self Timer', + 16 => 'Sunset', + 17 => 'Cuisine', + 18 => 'Documents', + 19 => 'Candle', + 20 => 'Fireworks', + 21 => 'Available Light', + 22 => 'Vivid', + 23 => 'Underwater Wide1', + 24 => 'Underwater Macro', + 25 => 'Museum', + 26 => 'Behind Glass', + 27 => 'Auction', + 28 => 'Shoot & Select1', + 29 => 'Shoot & Select2', + 30 => 'Underwater Wide2', + 31 => 'Digital Image Stabilization', + 32 => 'Face Portrait', + 33 => 'Pet', + 34 => 'Smile Shot', + 35 => 'Quick Shutter', + 43 => 'Hand-held Starlight', #PH (SH-21) + 100 => 'Panorama', #PH (SH-21) + 101 => 'Magic Filter', #PH + 103 => 'HDR', #PH (XZ-2) + }, + }, + 0x0404 => { Name => 'SerialNumber', Writable => 'string' }, #PH (D595Z, C7070WZ) + 0x0405 => { Name => 'Firmware', Writable => 'string' }, #11 + 0x0e00 => { # (AFFieldCoord for models XZ-2 and XZ-10, ref 11) + Name => 'PrintIM', + Description => 'Print Image Matching', + Writable => 0, + SubDirectory => { + TagTable => 'Image::ExifTool::PrintIM::Main', + }, + }, + 0x0f00 => { + Name => 'DataDump', + Writable => 0, + Binary => 1, + }, + 0x0f01 => { #6 + Name => 'DataDump2', + Writable => 0, + Binary => 1, + }, + 0x0f04 => { + Name => 'ZoomedPreviewStart', + # NOTE: this tag is currently not updated properly when the image is rewritten! + OffsetPair => 0xf05, + DataTag => 'ZoomedPreviewImage', + Writable => 'int32u', + Protected => 2, + }, + 0x0f05 => { + Name => 'ZoomedPreviewLength', + OffsetPair => 0xf04, + DataTag => 'ZoomedPreviewImage', + Writable => 'int32u', + Protected => 2, + }, + 0x0f06 => { + Name => 'ZoomedPreviewSize', + Writable => 'int16u', + Count => 2, + }, + 0x1000 => { #6 + Name => 'ShutterSpeedValue', + Writable => 'rational64s', + Priority => 0, + ValueConv => 'abs($val)<100 ? 2**(-$val) : 0', + ValueConvInv => '$val>0 ? -log($val)/log(2) : -100', + PrintConv => 'Image::ExifTool::Exif::PrintExposureTime($val)', + PrintConvInv => 'Image::ExifTool::Exif::ConvertFraction($val)', + }, + 0x1001 => { #6 + Name => 'ISOValue', + Writable => 'rational64s', + Priority => 0, + ValueConv => '100 * 2 ** ($val - 5)', + ValueConvInv => '$val>0 ? log($val/100)/log(2)+5 : 0', + PrintConv => 'int($val * 100 + 0.5) / 100', + PrintConvInv => '$val', + }, + 0x1002 => { #6 + Name => 'ApertureValue', + Writable => 'rational64s', + Priority => 0, + ValueConv => '2 ** ($val / 2)', + ValueConvInv => '$val>0 ? 2*log($val)/log(2) : 0', + PrintConv => 'sprintf("%.1f",$val)', + PrintConvInv => '$val', + }, + 0x1003 => { #6 + Name => 'BrightnessValue', + Writable => 'rational64s', + Priority => 0, + }, + 0x1004 => { #3 + Name => 'FlashMode', + Writable => 'int16u', + PrintConv => { + 2 => 'On', #PH + 3 => 'Off', #PH + }, + }, + 0x1005 => { #6 + Name => 'FlashDevice', + Writable => 'int16u', + PrintConv => { + 0 => 'None', + 1 => 'Internal', + 4 => 'External', + 5 => 'Internal + External', + }, + }, + 0x1006 => { #6 + Name =>'ExposureCompensation', + Writable => 'rational64s', + }, + 0x1007 => { Name => 'SensorTemperature',Writable => 'int16s' }, #6 (E-10, E-20 and C2500L - numbers usually around 30-40) + 0x1008 => { Name => 'LensTemperature', Writable => 'int16s' }, #6 + 0x1009 => { Name => 'LightCondition', Writable => 'int16u' }, #11 + 0x100a => { #11 + Name => 'FocusRange', + Writable => 'int16u', + PrintConv => { + 0 => 'Normal', + 1 => 'Macro', + }, + }, + 0x100b => { #6 + Name => 'FocusMode', + Writable => 'int16u', + PrintConv => { + 0 => 'Auto', + 1 => 'Manual', + }, + }, + 0x100c => { #6 + Name => 'ManualFocusDistance', + Writable => 'rational64u', + PrintConv => '"$val mm"', #11 + PrintConvInv => '$val=~s/\s*mm$//; $val', + }, + 0x100d => { Name => 'ZoomStepCount', Writable => 'int16u' }, #6 + 0x100e => { Name => 'FocusStepCount', Writable => 'int16u' }, #6 + 0x100f => { #6 + Name => 'Sharpness', + Writable => 'int16u', + Priority => 0, + PrintConv => { + 0 => 'Normal', + 1 => 'Hard', + 2 => 'Soft', + }, + }, + 0x1010 => { Name => 'FlashChargeLevel', Writable => 'int16u' }, #6 + 0x1011 => { #3 + Name => 'ColorMatrix', + Writable => 'int16u', + Format => 'int16s', + Count => 9, + }, + 0x1012 => { Name => 'BlackLevel', Writable => 'int16u', Count => 4 }, #3 + 0x1013 => { #11 + Name => 'ColorTemperatureBG', + Writable => 'int16u', + Unknown => 1, # (doesn't look like a temperature) + }, + 0x1014 => { #11 + Name => 'ColorTemperatureRG', + Writable => 'int16u', + Unknown => 1, # (doesn't look like a temperature) + }, + 0x1015 => { #6 + Name => 'WBMode', + Writable => 'int16u', + Count => 2, + PrintConvColumns => 2, + PrintConv => { + '1' => 'Auto', + '1 0' => 'Auto', + '1 2' => 'Auto (2)', + '1 4' => 'Auto (4)', + '2 2' => '3000 Kelvin', + '2 3' => '3700 Kelvin', + '2 4' => '4000 Kelvin', + '2 5' => '4500 Kelvin', + '2 6' => '5500 Kelvin', + '2 7' => '6500 Kelvin', + '2 8' => '7500 Kelvin', + '3 0' => 'One-touch', + }, + }, + 0x1017 => { #2 + Name => 'RedBalance', + Writable => 'int16u', + Count => 2, + ValueConv => '$val=~s/ .*//; $val / 256', + ValueConvInv => '$val*=256;"$val 64"', + }, + 0x1018 => { #2 + Name => 'BlueBalance', + Writable => 'int16u', + Count => 2, + ValueConv => '$val=~s/ .*//; $val / 256', + ValueConvInv => '$val*=256;"$val 64"', + }, + 0x1019 => { Name => 'ColorMatrixNumber', Writable => 'int16u' }, #11 + # 0x101a is same as CameraID ("OLYMPUS DIGITAL CAMERA") for C2500L - PH + 0x101a => { Name => 'SerialNumber', Writable => 'string' }, #3 + 0x101b => { #11 + Name => 'ExternalFlashAE1_0', + Writable => 'int32u', + Unknown => 1, # (what are these?) + }, + 0x101c => { Name => 'ExternalFlashAE2_0', Writable => 'int32u', Unknown => 1 }, #11 + 0x101d => { Name => 'InternalFlashAE1_0', Writable => 'int32u', Unknown => 1 }, #11 + 0x101e => { Name => 'InternalFlashAE2_0', Writable => 'int32u', Unknown => 1 }, #11 + 0x101f => { Name => 'ExternalFlashAE1', Writable => 'int32u', Unknown => 1 }, #11 + 0x1020 => { Name => 'ExternalFlashAE2', Writable => 'int32u', Unknown => 1 }, #11 + 0x1021 => { Name => 'InternalFlashAE1', Writable => 'int32u', Unknown => 1 }, #11 + 0x1022 => { Name => 'InternalFlashAE2', Writable => 'int32u', Unknown => 1 }, #11 + 0x1023 => { Name => 'FlashExposureComp', Writable => 'rational64s' }, #6 + 0x1024 => { Name => 'InternalFlashTable', Writable => 'int16u' }, #11 + 0x1025 => { Name => 'ExternalFlashGValue', Writable => 'rational64s' }, #11 + 0x1026 => { #6 + Name => 'ExternalFlashBounce', + Writable => 'int16u', + PrintConv => { + 0 => 'No', + 1 => 'Yes', + }, + }, + 0x1027 => { Name => 'ExternalFlashZoom', Writable => 'int16u' }, #6 + 0x1028 => { Name => 'ExternalFlashMode', Writable => 'int16u' }, #6 + 0x1029 => { #3 + Name => 'Contrast', + Writable => 'int16u', + PrintConv => { #PH (works with E1) + 0 => 'High', + 1 => 'Normal', + 2 => 'Low', + }, + }, + 0x102a => { Name => 'SharpnessFactor', Writable => 'int16u' }, #3 + 0x102b => { Name => 'ColorControl', Writable => 'int16u', Count => 6 }, #3 + 0x102c => { Name => 'ValidBits', Writable => 'int16u', Count => 2 }, #3 + 0x102d => { Name => 'CoringFilter', Writable => 'int16u' }, #3 + 0x102e => { Name => 'OlympusImageWidth', Writable => 'int32u' }, #PH + 0x102f => { Name => 'OlympusImageHeight', Writable => 'int32u' }, #PH + 0x1030 => { Name => 'SceneDetect', Writable => 'int16u' }, #11 + 0x1031 => { #11 + Name => 'SceneArea', + Writable => 'int32u', + Count => 8, + Unknown => 1, # (numbers don't make much sense?) + }, + # 0x1032 HAFFINAL? #11 + 0x1033 => { #11 + Name => 'SceneDetectData', + Writable => 'int32u', + Count => 720, + Binary => 1, + Unknown => 1, # (but what does it mean?) + }, + 0x1034 => { Name => 'CompressionRatio', Writable => 'rational64u' }, #3 + 0x1035 => { #6 + Name => 'PreviewImageValid', + Writable => 'int32u', + PrintConv => { 0 => 'No', 1 => 'Yes' }, + }, + 0x1036 => { #6 + Name => 'PreviewImageStart', + Flags => 'IsOffset', + OffsetPair => 0x1037, # point to associated byte count + DataTag => 'PreviewImage', + Writable => 'int32u', + WriteGroup => 'MakerNotes', + Protected => 2, + }, + 0x1037 => { #6 + # (may contain data from multiple previews - PH, FE320) + Name => 'PreviewImageLength', + OffsetPair => 0x1036, # point to associated offset + DataTag => 'PreviewImage', + Writable => 'int32u', + WriteGroup => 'MakerNotes', + Protected => 2, + }, + 0x1038 => { Name => 'AFResult', Writable => 'int16u' }, #11 + 0x1039 => { #6 + Name => 'CCDScanMode', + Writable => 'int16u', + PrintConv => { + 0 => 'Interlaced', + 1 => 'Progressive', + }, + }, + 0x103a => { #6 + Name => 'NoiseReduction', + Writable => 'int16u', + PrintConv => \%offOn, + }, + 0x103b => { Name => 'FocusStepInfinity', Writable => 'int16u' }, #6 + 0x103c => { Name => 'FocusStepNear', Writable => 'int16u' }, #6 + 0x103d => { Name => 'LightValueCenter', Writable => 'rational64s' }, #11 + 0x103e => { Name => 'LightValuePeriphery', Writable => 'rational64s' }, #11 + 0x103f => { #11 + Name => 'FieldCount', + Writable => 'int16u', + Unknown => 1, # (but what does it mean?) + }, +# +# Olympus really screwed up the format of the following subdirectories (for the +# E-1 and E-300 anyway). Not only is the subdirectory value data not included in +# the size, but also the count is 2 bytes short for the subdirectory itself +# (presumably the Olympus programmers forgot about the 2-byte entry count at the +# start of the subdirectory). This mess is straightened out and these subdirs +# are written properly when ExifTool rewrites the file. Note that this problem +# has been fixed by Olympus in the new-style IFD maker notes since a standard +# SubIFD offset value is used. As written by the camera, the old style +# directories have format 'undef' or 'string', and the new style has format +# 'ifd'. However, some older versions of exiftool may have rewritten the new +# style as 'int32u', so handle both cases. - PH +# + 0x2010 => [ #PH + { + Name => 'Equipment', + Condition => '$format ne "ifd" and $format ne "int32u"', + NestedHtmlDump => 2, # (so HtmlDump doesn't show these as double-referenced) + SubDirectory => { + TagTable => 'Image::ExifTool::Olympus::Equipment', + ByteOrder => 'Unknown', + }, + }, + { + Name => 'EquipmentIFD', + Groups => { 1 => 'MakerNotes' }, # SubIFD needs group 1 set + Flags => 'SubIFD', + FixFormat => 'ifd', + SubDirectory => { + TagTable => 'Image::ExifTool::Olympus::Equipment', + Start => '$val', + }, + }, + ], + 0x2020 => [ #PH + { + Name => 'CameraSettings', + Condition => '$format ne "ifd" and $format ne "int32u"', + NestedHtmlDump => 2, + SubDirectory => { + TagTable => 'Image::ExifTool::Olympus::CameraSettings', + ByteOrder => 'Unknown', + }, + }, + { + Name => 'CameraSettingsIFD', + Groups => { 1 => 'MakerNotes' }, + Flags => 'SubIFD', + FixFormat => 'ifd', + SubDirectory => { + TagTable => 'Image::ExifTool::Olympus::CameraSettings', + Start => '$val', + }, + }, + ], + 0x2030 => [ #PH + { + Name => 'RawDevelopment', + Condition => '$format ne "ifd" and $format ne "int32u"', + NestedHtmlDump => 2, + SubDirectory => { + TagTable => 'Image::ExifTool::Olympus::RawDevelopment', + ByteOrder => 'Unknown', + }, + }, + { + Name => 'RawDevelopmentIFD', + Groups => { 1 => 'MakerNotes' }, + Flags => 'SubIFD', + FixFormat => 'ifd', + SubDirectory => { + TagTable => 'Image::ExifTool::Olympus::RawDevelopment', + Start => '$val', + }, + }, + ], + 0x2031 => [ #11 + { + Name => 'RawDev2', + Condition => '$format ne "ifd" and $format ne "int32u"', + NestedHtmlDump => 2, + SubDirectory => { + TagTable => 'Image::ExifTool::Olympus::RawDevelopment2', + ByteOrder => 'Unknown', + }, + }, + { + Name => 'RawDev2IFD', + Groups => { 1 => 'MakerNotes' }, + Flags => 'SubIFD', + FixFormat => 'ifd', + SubDirectory => { + TagTable => 'Image::ExifTool::Olympus::RawDevelopment2', + Start => '$val', + }, + }, + ], + 0x2040 => [ #PH + { + Name => 'ImageProcessing', + Condition => '$format ne "ifd" and $format ne "int32u"', + NestedHtmlDump => 2, + SubDirectory => { + TagTable => 'Image::ExifTool::Olympus::ImageProcessing', + ByteOrder => 'Unknown', + }, + }, + { + Name => 'ImageProcessingIFD', + Groups => { 1 => 'MakerNotes' }, + Flags => 'SubIFD', + FixFormat => 'ifd', + SubDirectory => { + TagTable => 'Image::ExifTool::Olympus::ImageProcessing', + Start => '$val', + }, + }, + ], + 0x2050 => [ #PH + { + Name => 'FocusInfo', + Condition => '$format ne "ifd" and $format ne "int32u" and not $$self{OlympusCAMER}', + NestedHtmlDump => 2, + SubDirectory => { + TagTable => 'Image::ExifTool::Olympus::FocusInfo', + ByteOrder => 'Unknown', + }, + }, + { + Name => 'FocusInfoIFD', + Condition => 'not $$self{OlympusCAMER}', + Groups => { 1 => 'MakerNotes' }, + Flags => 'SubIFD', + FixFormat => 'ifd', + SubDirectory => { + TagTable => 'Image::ExifTool::Olympus::FocusInfo', + Start => '$val', + }, + }, + { + # ASCII-based camera parameters if makernotes starts with "CAMER\0" + # (or for Sony models starting with "SONY PI\0" or "PREMI\0") + Name => 'CameraParameters', + Writable => 'undef', + Binary => 1, + }, + ], + 0x2100 => [ + { #11 + Name => 'Olympus2100', + Condition => '$format ne "ifd" and $format ne "int32u"', + NestedHtmlDump => 2, + SubDirectory => { + TagTable => 'Image::ExifTool::Olympus::FETags', + ByteOrder => 'Unknown', + }, + }, + { #PH + Name => 'Olympus2100IFD', + Groups => { 1 => 'MakerNotes' }, + Flags => 'SubIFD', + FixFormat => 'ifd', + SubDirectory => { + TagTable => 'Image::ExifTool::Olympus::FETags', + ByteOrder => 'Unknown', + Start => '$val', + }, + }, + ], + 0x2200 => [ + { #11 + Name => 'Olympus2200', + Condition => '$format ne "ifd" and $format ne "int32u"', + NestedHtmlDump => 2, + SubDirectory => { + TagTable => 'Image::ExifTool::Olympus::FETags', + ByteOrder => 'Unknown', + }, + }, + { #PH + Name => 'Olympus2200IFD', + Groups => { 1 => 'MakerNotes' }, + Flags => 'SubIFD', + FixFormat => 'ifd', + SubDirectory => { + TagTable => 'Image::ExifTool::Olympus::FETags', + ByteOrder => 'Unknown', + Start => '$val', + }, + }, + ], + 0x2300 => [ + { #11 + Name => 'Olympus2300', + Condition => '$format ne "ifd" and $format ne "int32u"', + NestedHtmlDump => 2, + SubDirectory => { + TagTable => 'Image::ExifTool::Olympus::FETags', + ByteOrder => 'Unknown', + }, + }, + { #PH + Name => 'Olympus2300IFD', + Groups => { 1 => 'MakerNotes' }, + Flags => 'SubIFD', + FixFormat => 'ifd', + SubDirectory => { + TagTable => 'Image::ExifTool::Olympus::FETags', + ByteOrder => 'Unknown', + Start => '$val', + }, + }, + ], + 0x2400 => [ + { #11 + Name => 'Olympus2400', + Condition => '$format ne "ifd" and $format ne "int32u"', + NestedHtmlDump => 2, + SubDirectory => { + TagTable => 'Image::ExifTool::Olympus::FETags', + ByteOrder => 'Unknown', + }, + }, + { #PH + Name => 'Olympus2400IFD', + Groups => { 1 => 'MakerNotes' }, + Flags => 'SubIFD', + FixFormat => 'ifd', + SubDirectory => { + TagTable => 'Image::ExifTool::Olympus::FETags', + ByteOrder => 'Unknown', + Start => '$val', + }, + }, + ], + 0x2500 => [ + { #11 + Name => 'Olympus2500', + Condition => '$format ne "ifd" and $format ne "int32u"', + NestedHtmlDump => 2, + SubDirectory => { + TagTable => 'Image::ExifTool::Olympus::FETags', + ByteOrder => 'Unknown', + }, + }, + { #PH + Name => 'Olympus2500IFD', + Groups => { 1 => 'MakerNotes' }, + Flags => 'SubIFD', + FixFormat => 'ifd', + SubDirectory => { + TagTable => 'Image::ExifTool::Olympus::FETags', + ByteOrder => 'Unknown', + Start => '$val', + }, + }, + ], + 0x2600 => [ + { #11 + Name => 'Olympus2600', + Condition => '$format ne "ifd" and $format ne "int32u"', + NestedHtmlDump => 2, + SubDirectory => { + TagTable => 'Image::ExifTool::Olympus::FETags', + ByteOrder => 'Unknown', + }, + }, + { #PH + Name => 'Olympus2600IFD', + Groups => { 1 => 'MakerNotes' }, + Flags => 'SubIFD', + FixFormat => 'ifd', + SubDirectory => { + TagTable => 'Image::ExifTool::Olympus::FETags', + ByteOrder => 'Unknown', + Start => '$val', + }, + }, + ], + 0x2700 => [ + { #11 + Name => 'Olympus2700', + Condition => '$format ne "ifd" and $format ne "int32u"', + NestedHtmlDump => 2, + SubDirectory => { + TagTable => 'Image::ExifTool::Olympus::FETags', + ByteOrder => 'Unknown', + }, + }, + { #PH + Name => 'Olympus2700IFD', + Groups => { 1 => 'MakerNotes' }, + Flags => 'SubIFD', + FixFormat => 'ifd', + SubDirectory => { + TagTable => 'Image::ExifTool::Olympus::FETags', + ByteOrder => 'Unknown', + Start => '$val', + }, + }, + ], + 0x2800 => [ + { #11 + Name => 'Olympus2800', + Condition => '$format ne "ifd" and $format ne "int32u"', + NestedHtmlDump => 2, + SubDirectory => { + TagTable => 'Image::ExifTool::Olympus::FETags', + ByteOrder => 'Unknown', + }, + }, + { #PH + Name => 'Olympus2800IFD', + Groups => { 1 => 'MakerNotes' }, + Flags => 'SubIFD', + FixFormat => 'ifd', + SubDirectory => { + TagTable => 'Image::ExifTool::Olympus::FETags', + ByteOrder => 'Unknown', + Start => '$val', + }, + }, + ], + 0x2900 => [ + { #11 + Name => 'Olympus2900', + Condition => '$format ne "ifd" and $format ne "int32u"', + NestedHtmlDump => 2, + SubDirectory => { + TagTable => 'Image::ExifTool::Olympus::FETags', + ByteOrder => 'Unknown', + }, + }, + { #PH + Name => 'Olympus2900IFD', + Groups => { 1 => 'MakerNotes' }, + Flags => 'SubIFD', + FixFormat => 'ifd', + SubDirectory => { + TagTable => 'Image::ExifTool::Olympus::FETags', + ByteOrder => 'Unknown', + Start => '$val', + }, + }, + ], + 0x3000 => [ + { #6 + Name => 'RawInfo', + Condition => '$format ne "ifd" and $format ne "int32u"', + NestedHtmlDump => 2, + SubDirectory => { + TagTable => 'Image::ExifTool::Olympus::RawInfo', + ByteOrder => 'Unknown', + }, + }, + { #PH + Name => 'RawInfoIFD', + Groups => { 1 => 'MakerNotes' }, + Flags => 'SubIFD', + FixFormat => 'ifd', + SubDirectory => { + TagTable => 'Image::ExifTool::Olympus::RawInfo', + Start => '$val', + }, + }, + ], + 0x4000 => [ #PH + { + Name => 'MainInfo', + Condition => '$format ne "ifd" and $format ne "int32u"', + NestedHtmlDump => 2, + SubDirectory => { + TagTable => 'Image::ExifTool::Olympus::Main', + ByteOrder => 'Unknown', + }, + }, + { + Name => 'MainInfoIFD', + Groups => { 1 => 'MakerNotes' }, + Flags => 'SubIFD', + FixFormat => 'ifd', + SubDirectory => { + TagTable => 'Image::ExifTool::Olympus::Main', + Start => '$val', + }, + }, + ], + 0x5000 => [ #PH + { + Name => 'UnknownInfo', + Condition => '$format ne "ifd" and $format ne "int32u"', + NestedHtmlDump => 2, + SubDirectory => { + TagTable => 'Image::ExifTool::Olympus::UnknownInfo', + ByteOrder => 'Unknown', + }, + }, + { + Name => 'UnknownInfoIFD', + Groups => { 1 => 'MakerNotes' }, + Flags => 'SubIFD', + FixFormat => 'ifd', + SubDirectory => { + TagTable => 'Image::ExifTool::Olympus::UnknownInfo', + Start => '$val', + }, + }, + ], +); + +# TextInfo tags +%Image::ExifTool::Olympus::TextInfo = ( + PROCESS_PROC => \&Image::ExifTool::APP12::ProcessAPP12, + NOTES => q{ + This information is in text format (similar to APP12 information, but with + spaces instead of linefeeds). Below are tags which have been observed, but + any information found here will be extracted, even if the tag is not listed. + }, + GROUPS => { 0 => 'MakerNotes', 1 => 'Olympus', 2 => 'Image' }, + Resolution => { }, + Type => { + Name => 'CameraType', + Groups => { 2 => 'Camera' }, + DataMember => 'CameraType', + RawConv => '$self->{CameraType} = $val', + SeparateTable => 'CameraType', + PrintConv => \%olympusCameraTypes, + }, +); + +# Olympus Equipment IFD +%Image::ExifTool::Olympus::Equipment = ( + WRITE_PROC => \&Image::ExifTool::Exif::WriteExif, + CHECK_PROC => \&Image::ExifTool::Exif::CheckExif, + WRITABLE => 1, + GROUPS => { 0 => 'MakerNotes', 2 => 'Camera' }, + 0x000 => { #PH + Name => 'EquipmentVersion', + Writable => 'undef', + RawConv => '$val=~s/\0+$//; $val', # (may be null terminated) + Count => 4, + }, + 0x100 => { #6 + Name => 'CameraType2', + Writable => 'string', + Count => 6, + SeparateTable => 'CameraType', + PrintConv => \%olympusCameraTypes, + }, + 0x101 => { #PH + Name => 'SerialNumber', + Writable => 'string', + Count => 32, + PrintConv => '$val=~s/\s+$//;$val', + PrintConvInv => 'pack("A31",$val)', # pad with spaces to 31 chars + }, + 0x102 => { #6 + Name => 'InternalSerialNumber', + Notes => '16 digits: 0-3=model, 4=year, 5-6=month, 8-12=unit number', + Writable => 'string', + Count => 32, + }, + 0x103 => { #6 + Name => 'FocalPlaneDiagonal', + Writable => 'rational64u', + PrintConv => '"$val mm"', + PrintConvInv => '$val=~s/\s*mm$//;$val', + }, + 0x104 => { #6 + Name => 'BodyFirmwareVersion', + Writable => 'int32u', + PrintConv => '$val=sprintf("%x",$val);$val=~s/(.{3})$/\.$1/;$val', + PrintConvInv => '$val=sprintf("%.3f",$val);$val=~s/\.//;hex($val)', + }, + 0x201 => { #6 + Name => 'LensType', + Writable => 'int8u', + Count => 6, + Notes => q{ + 6 numbers: 0. Make, 1. Unknown, 2. Model, 3. Sub-model, 4-5. Unknown. Only + the Make, Model and Sub-model are used to identify the lens type + }, + SeparateTable => 'LensType', + # Have seen these values for the unknown numbers: + # 1: 0 + # 4: 0, 2(Olympus lenses for which I have also seen 0 for this number) + # 5: 0, 16(new Lumix lenses) + ValueConv => 'my @a=split(" ",$val); sprintf("%x %.2x %.2x",@a[0,2,3])', + # set unknown values to zero when writing + ValueConvInv => 'my @a=split(" ",$val); hex($a[0])." 0 ".hex($a[1])." ".hex($a[2])." 0 0"', + PrintConv => \%olympusLensTypes, + }, + # apparently the first 3 digits of the lens s/n give the type (ref 4): + # 010 = 50macro + # 040 = EC-14 + # 050 = 14-54 + # 060 = 50-200 + # 080 = EX-25 + # 101 = FL-50 + # 272 = EC-20 #7 + 0x202 => { #PH + Name => 'LensSerialNumber', + Writable => 'string', + Count => 32, + PrintConv => '$val=~s/\s+$//;$val', + PrintConvInv => 'pack("A31",$val)', # pad with spaces to 31 chars + }, + 0x203 => { Name => 'LensModel', Writable => 'string' }, #17 + 0x204 => { #6 + Name => 'LensFirmwareVersion', + Writable => 'int32u', + PrintConv => '$val=sprintf("%x",$val);$val=~s/(.{3})$/\.$1/;$val', + PrintConvInv => '$val=sprintf("%.3f",$val);$val=~s/\.//;hex($val)', + }, + 0x205 => { #11 + Name => 'MaxApertureAtMinFocal', + Writable => 'int16u', + ValueConv => '$val ? sqrt(2)**($val/256) : 0', + ValueConvInv => '$val>0 ? int(512*log($val)/log(2)+0.5) : 0', + PrintConv => 'sprintf("%.1f",$val)', + PrintConvInv => '$val', + }, + 0x206 => { #5 + Name => 'MaxApertureAtMaxFocal', + Writable => 'int16u', + ValueConv => '$val ? sqrt(2)**($val/256) : 0', + ValueConvInv => '$val>0 ? int(512*log($val)/log(2)+0.5) : 0', + PrintConv => 'sprintf("%.1f",$val)', + PrintConvInv => '$val', + }, + 0x207 => { Name => 'MinFocalLength', Writable => 'int16u' }, #PH + 0x208 => { Name => 'MaxFocalLength', Writable => 'int16u' }, #PH + 0x20a => { #9 + Name => 'MaxAperture', # (at current focal length) + Writable => 'int16u', + ValueConv => '$val ? sqrt(2)**($val/256) : 0', + ValueConvInv => '$val>0 ? int(512*log($val)/log(2)+0.5) : 0', + PrintConv => 'sprintf("%.1f",$val)', + PrintConvInv => '$val', + }, + 0x20b => { #11 + Name => 'LensProperties', + Writable => 'int16u', + PrintConv => 'sprintf("0x%x",$val)', + PrintConvInv => '$val', + }, + 0x301 => { #6 + Name => 'Extender', + Writable => 'int8u', + Count => 6, + Notes => q{ + 6 numbers: 0. Make, 1. Unknown, 2. Model, 3. Sub-model, 4-5. Unknown. Only + the Make and Model are used to identify the extender + }, + ValueConv => 'my @a=split(" ",$val); sprintf("%x %.2x",@a[0,2])', + ValueConvInv => 'my @a=split(" ",$val); hex($a[0])." 0 ".hex($a[1])." 0 0 0"', + PrintConv => { + '0 00' => 'None', + '0 04' => 'Olympus Zuiko Digital EC-14 1.4x Teleconverter', + '0 08' => 'Olympus EX-25 Extension Tube', + '0 10' => 'Olympus Zuiko Digital EC-20 2.0x Teleconverter', #7 + }, + }, + 0x302 => { Name => 'ExtenderSerialNumber', Writable => 'string', Count => 32 }, #4 + 0x303 => { Name => 'ExtenderModel', Writable => 'string' }, #9 + 0x304 => { #6 + Name => 'ExtenderFirmwareVersion', + Writable => 'int32u', + PrintConv => '$val=sprintf("%x",$val);$val=~s/(.{3})$/\.$1/;$val', + PrintConvInv => '$val=sprintf("%.3f",$val);$val=~s/\.//;hex($val)', + }, + 0x403 => { #http://dev.exiv2.org/issues/870 + Name => 'ConversionLens', + Writable => 'string', + # (observed values: '','TCON','FCON','WCON') + }, + 0x1000 => { #6 + Name => 'FlashType', + Writable => 'int16u', + PrintConv => { + 0 => 'None', + 2 => 'Simple E-System', + 3 => 'E-System', + 4 => 'E-System (body powered)', #forum9740 + }, + }, + 0x1001 => { #6 + Name => 'FlashModel', + Writable => 'int16u', + PrintConvColumns => 2, + PrintConv => { + 0 => 'None', + 1 => 'FL-20', # (or subtronic digital or Inon UW flash, ref 11) + 2 => 'FL-50', # (or Metzblitz+SCA or Cullmann 34, ref 11) + 3 => 'RF-11', + 4 => 'TF-22', + 5 => 'FL-36', + 6 => 'FL-50R', #11 (or Metz mecablitz digital) + 7 => 'FL-36R', #11 + 9 => 'FL-14', #11 + 11 => 'FL-600R', #11 + 13 => 'FL-LM3', #forum9740 + 15 => 'FL-900R', #7 + }, + }, + 0x1002 => { #6 + Name => 'FlashFirmwareVersion', + Writable => 'int32u', + PrintConv => '$val=sprintf("%x",$val);$val=~s/(.{3})$/\.$1/;$val', + PrintConvInv => '$val=sprintf("%.3f",$val);$val=~s/\.//;hex($val)', + }, + 0x1003 => { Name => 'FlashSerialNumber', Writable => 'string', Count => 32 }, #4 +); + +# Olympus camera settings IFD +%Image::ExifTool::Olympus::CameraSettings = ( + WRITE_PROC => \&Image::ExifTool::Exif::WriteExif, + CHECK_PROC => \&Image::ExifTool::Exif::CheckExif, + WRITABLE => 1, + GROUPS => { 0 => 'MakerNotes', 2 => 'Camera' }, + 0x000 => { #PH + Name => 'CameraSettingsVersion', + Writable => 'undef', + RawConv => '$val=~s/\0+$//; $val', # (may be null terminated) + Count => 4, + }, + 0x100 => { #6 + Name => 'PreviewImageValid', + Writable => 'int32u', + PrintConv => { 0 => 'No', 1 => 'Yes' }, + }, + 0x101 => { #PH + Name => 'PreviewImageStart', + Flags => 'IsOffset', + OffsetPair => 0x102, + DataTag => 'PreviewImage', + Writable => 'int32u', + WriteGroup => 'MakerNotes', + Protected => 2, + }, + 0x102 => { #PH + Name => 'PreviewImageLength', + OffsetPair => 0x101, + DataTag => 'PreviewImage', + Writable => 'int32u', + WriteGroup => 'MakerNotes', + Protected => 2, + }, + 0x200 => { #4 + Name => 'ExposureMode', + Writable => 'int16u', + PrintConv => { + 1 => 'Manual', + 2 => 'Program', #6 + 3 => 'Aperture-priority AE', + 4 => 'Shutter speed priority AE', + 5 => 'Program-shift', #6 + } + }, + 0x201 => { #6 + Name => 'AELock', + Writable => 'int16u', + PrintConv => \%offOn, + }, + 0x202 => { #PH/4 + Name => 'MeteringMode', + Writable => 'int16u', + PrintConv => { + 2 => 'Center-weighted average', + 3 => 'Spot', + 5 => 'ESP', + 261 => 'Pattern+AF', #6 + 515 => 'Spot+Highlight control', #6 + 1027 => 'Spot+Shadow control', #6 + }, + }, + 0x203 => { Name => 'ExposureShift', Writable => 'rational64s' }, #11 (some models only) + 0x204 => { #11 (XZ-1) + Name => 'NDFilter', + PrintConv => \%offOn, + }, + 0x300 => { #6 + Name => 'MacroMode', + Writable => 'int16u', + PrintConv => { + 0 => 'Off', + 1 => 'On', + 2 => 'Super Macro', #11 + }, + }, + 0x301 => { #6 + Name => 'FocusMode', + Writable => 'int16u', + Count => -1, + Notes => '1 or 2 values', + PrintConv => [{ + 0 => 'Single AF', + 1 => 'Sequential shooting AF', + 2 => 'Continuous AF', + 3 => 'Multi AF', + 4 => 'Face detect', #11 + 10 => 'MF', + }, { + 0 => '(none)', + BITMASK => { #11 + 0 => 'S-AF', + 2 => 'C-AF', + 4 => 'MF', + 5 => 'Face detect', + 6 => 'Imager AF', + 7 => 'Live View Magnification Frame', + 8 => 'AF sensor', + }, + }], + }, + 0x302 => { #6 + Name => 'FocusProcess', + Writable => 'int16u', + Count => -1, + Notes => '1 or 2 values', + PrintConv => [{ + 0 => 'AF Not Used', + 1 => 'AF Used', + }], + # 2nd value written only by some models (u1050SW, u9000, uT6000, uT6010, + # uT8000, E-30, E-420, E-450, E-520, E-620, E-P1 and E-P2): - PH + # observed values when "AF Not Used": 0, 16 + # observed values when "AF Used": 64, 96(face detect on), 256 + }, + 0x303 => { #6 + Name => 'AFSearch', + Writable => 'int16u', + PrintConv => { + 0 => 'Not Ready', + 1 => 'Ready', + }, + }, + 0x304 => { #PH/4 + Name => 'AFAreas', + Notes => 'coordinates range from 0 to 255', + Writable => 'int32u', + Count => 64, + PrintConv => 'Image::ExifTool::Olympus::PrintAFAreas($val)', + }, + 0x0305 => { #PH + Name => 'AFPointSelected', + Notes => 'coordinates expressed as a percent', + Writable => 'rational64s', + Count => 5, + ValueConv => '$val =~ s/\S* //; $val', # ignore first undefined value + ValueConvInv => '"undef $val"', + PrintConv => q{ + return 'n/a' if $val =~ /undef/; + sprintf("(%d%%,%d%%) (%d%%,%d%%)", map {$_ * 100} split(" ",$val)); + }, + PrintConvInv => q{ + return 'undef undef undef undef' if $val eq 'n/a'; + my @nums = $val =~ /\d+(?:\.\d+)?/g; + return undef unless @nums == 4; + join ' ', map {$_ / 100} @nums; + }, + }, + 0x306 => { #11 + Name => 'AFFineTune', + Writable => 'int8u', + PrintConv => { 0 => 'Off', 1 => 'On' }, + }, + 0x307 => { #15 + Name => 'AFFineTuneAdj', + Format => 'int16s', + Count => 3, # not sure what the 3 values mean + }, + 0x400 => { #6 + Name => 'FlashMode', + Writable => 'int16u', + PrintConv => { + 0 => 'Off', + BITMASK => { + 0 => 'On', + 1 => 'Fill-in', + 2 => 'Red-eye', + 3 => 'Slow-sync', + 4 => 'Forced On', + 5 => '2nd Curtain', + }, + }, + }, + 0x401 => { Name => 'FlashExposureComp', Writable => 'rational64s' }, #6 + # 0x402 - FlashMode? bit0=TTL, bit1=auto, bit2=SuperFP (ref 11) + 0x403 => { #11 + Name => 'FlashRemoteControl', + Writable => 'int16u', + PrintHex => 1, + PrintConvColumns => 2, + PrintConv => { + 0 => 'Off', + 0x01 => 'Channel 1, Low', + 0x02 => 'Channel 2, Low', + 0x03 => 'Channel 3, Low', + 0x04 => 'Channel 4, Low', + 0x09 => 'Channel 1, Mid', + 0x0a => 'Channel 2, Mid', + 0x0b => 'Channel 3, Mid', + 0x0c => 'Channel 4, Mid', + 0x11 => 'Channel 1, High', + 0x12 => 'Channel 2, High', + 0x13 => 'Channel 3, High', + 0x14 => 'Channel 4, High', + }, + }, + 0x404 => { #11 + Name => 'FlashControlMode', + Writable => 'int16u', + Count => -1, + Notes => '3 or 4 values', + PrintConv => [{ + 0 => 'Off', + 3 => 'TTL', + 4 => 'Auto', + 5 => 'Manual', + }], + }, + 0x405 => { #11 + Name => 'FlashIntensity', + Writable => 'rational64s', + Count => -1, + Notes => '3 or 4 values', + PrintConv => { + OTHER => sub { shift }, + 'undef undef undef' => 'n/a', + 'undef undef undef undef' => 'n/a (x4)', + }, + }, + 0x406 => { #11 + Name => 'ManualFlashStrength', + Writable => 'rational64s', + Count => -1, + Notes => '3 or 4 values', + PrintConv => { + OTHER => sub { shift }, + 'undef undef undef' => 'n/a', + 'undef undef undef undef' => 'n/a (x4)', + }, + }, + 0x500 => { #6 + Name => 'WhiteBalance2', + Writable => 'int16u', + PrintConv => { + 0 => 'Auto', + 1 => 'Auto (Keep Warm Color Off)', #IB + 16 => '7500K (Fine Weather with Shade)', + 17 => '6000K (Cloudy)', + 18 => '5300K (Fine Weather)', + 20 => '3000K (Tungsten light)', + 21 => '3600K (Tungsten light-like)', + 22 => 'Auto Setup', #IB + 23 => '5500K (Flash)', #IB + 33 => '6600K (Daylight fluorescent)', + 34 => '4500K (Neutral white fluorescent)', + 35 => '4000K (Cool white fluorescent)', + 36 => 'White Fluorescent', #IB + 48 => '3600K (Tungsten light-like)', + 67 => 'Underwater', #IB + 256 => 'One Touch WB 1', #IB + 257 => 'One Touch WB 2', #IB + 258 => 'One Touch WB 3', #IB + 259 => 'One Touch WB 4', #IB + 512 => 'Custom WB 1', #IB + 513 => 'Custom WB 2', #IB + 514 => 'Custom WB 3', #IB + 515 => 'Custom WB 4', #IB + }, + }, + 0x501 => { #PH/4 + Name => 'WhiteBalanceTemperature', + Writable => 'int16u', + PrintConv => '$val ? $val : "Auto"', + PrintConvInv => '$val=~/^\d+$/ ? $val : 0', + }, + 0x502 => { #PH/4 + Name => 'WhiteBalanceBracket', + Writable => 'int16s', + }, + 0x503 => { #PH/4/6 + Name => 'CustomSaturation', + Writable => 'int16s', + Count => 3, + Notes => '3 numbers: 1. CS Value, 2. Min, 3. Max', + PrintConv => q{ + my ($a,$b,$c)=split ' ',$val; + if ($self->{Model} =~ /^E-1\b/) { + $a-=$b; $c-=$b; + return "CS$a (min CS0, max CS$c)"; + } else { + return "$a (min $b, max $c)"; + } + }, + }, + 0x504 => { #PH/4 + Name => 'ModifiedSaturation', + Writable => 'int16u', + PrintConv => { + 0 => 'Off', + 1 => 'CM1 (Red Enhance)', + 2 => 'CM2 (Green Enhance)', + 3 => 'CM3 (Blue Enhance)', + 4 => 'CM4 (Skin Tones)', + }, + }, + 0x505 => { #PH/4 + Name => 'ContrastSetting', + Writable => 'int16s', + Count => 3, + Notes => 'value, min, max', + PrintConv => 'my @v=split " ",$val; "$v[0] (min $v[1], max $v[2])"', + PrintConvInv => '$val=~tr/-0-9 //dc;$val', + }, + 0x506 => { #PH/4 + Name => 'SharpnessSetting', + Writable => 'int16s', + Count => 3, + Notes => 'value, min, max', + PrintConv => 'my @v=split " ",$val; "$v[0] (min $v[1], max $v[2])"', + PrintConvInv => '$val=~tr/-0-9 //dc;$val', + }, + 0x507 => { #PH/4 + Name => 'ColorSpace', + Writable => 'int16u', + PrintConv => { #6 + 0 => 'sRGB', + 1 => 'Adobe RGB', + 2 => 'Pro Photo RGB', + }, + }, + 0x509 => { #6 + Name => 'SceneMode', + Writable => 'int16u', + PrintConvColumns => 2, + PrintConv => { + 0 => 'Standard', + 6 => 'Auto', #6 + 7 => 'Sport', + 8 => 'Portrait', + 9 => 'Landscape+Portrait', + 10 => 'Landscape', + 11 => 'Night Scene', + 12 => 'Self Portrait', #11 + 13 => 'Panorama', #6 + 14 => '2 in 1', #11 + 15 => 'Movie', #11 + 16 => 'Landscape+Portrait', #6 + 17 => 'Night+Portrait', + 18 => 'Indoor', #11 (Party - PH) + 19 => 'Fireworks', + 20 => 'Sunset', + 21 => 'Beauty Skin', #PH + 22 => 'Macro', + 23 => 'Super Macro', #11 + 24 => 'Food', #11 + 25 => 'Documents', + 26 => 'Museum', + 27 => 'Shoot & Select', #11 + 28 => 'Beach & Snow', + 29 => 'Self Protrait+Timer', #11 + 30 => 'Candle', + 31 => 'Available Light', #11 + 32 => 'Behind Glass', #11 + 33 => 'My Mode', #11 + 34 => 'Pet', #11 + 35 => 'Underwater Wide1', #6 + 36 => 'Underwater Macro', #6 + 37 => 'Shoot & Select1', #11 + 38 => 'Shoot & Select2', #11 + 39 => 'High Key', + 40 => 'Digital Image Stabilization', #6 + 41 => 'Auction', #11 + 42 => 'Beach', #11 + 43 => 'Snow', #11 + 44 => 'Underwater Wide2', #6 + 45 => 'Low Key', #6 + 46 => 'Children', #6 + 47 => 'Vivid', #11 + 48 => 'Nature Macro', #6 + 49 => 'Underwater Snapshot', #11 + 50 => 'Shooting Guide', #11 + 54 => 'Face Portrait', #11 + 57 => 'Bulb', #11 + 59 => 'Smile Shot', #11 + 60 => 'Quick Shutter', #11 + 63 => 'Slow Shutter', #11 + 64 => 'Bird Watching', #11 + 65 => 'Multiple Exposure', #11 + 66 => 'e-Portrait', #11 + 67 => 'Soft Background Shot', #11 + 142 => 'Hand-held Starlight', #PH (SH-21) + 154 => 'HDR', #PH (XZ-2) + }, + }, + 0x50a => { #PH/4/6 + Name => 'NoiseReduction', + Writable => 'int16u', + PrintConv => { + 0 => '(none)', + BITMASK => { + 0 => 'Noise Reduction', + 1 => 'Noise Filter', + 2 => 'Noise Filter (ISO Boost)', + 3 => 'Auto', #11 + }, + }, + }, + 0x50b => { #6 + Name => 'DistortionCorrection', + Writable => 'int16u', + PrintConv => \%offOn, + }, + 0x50c => { #PH/4 + Name => 'ShadingCompensation', + Writable => 'int16u', + PrintConv => \%offOn, + }, + 0x50d => { Name => 'CompressionFactor', Writable => 'rational64u' }, #PH/4 + 0x50f => { #6 + Name => 'Gradation', + Writable => 'int16s', + Notes => '3 or 4 values', + Count => -1, + Relist => [ [0..2], 3 ], # join values 0-2 for PrintConv + PrintConv => [{ + '0 0 0' => 'n/a', #PH (?) + '-1 -1 1' => 'Low Key', + '0 -1 1' => 'Normal', + '1 -1 1' => 'High Key', + },{ + 0 => 'User-Selected', + 1 => 'Auto-Override', + }], + }, + 0x520 => { #6 + Name => 'PictureMode', + Writable => 'int16u', + Notes => '1 or 2 values', + Count => -1, + PrintConv => [{ + 1 => 'Vivid', + 2 => 'Natural', + 3 => 'Muted', + 4 => 'Portrait', + 5 => 'i-Enhance', #11 + 6 => 'e-Portrait', #23 + 7 => 'Color Creator', #23 + 9 => 'Color Profile 1', #23 + 10 => 'Color Profile 2', #23 + 11 => 'Color Profile 3', #23 + 12 => 'Monochrome Profile 1', #23 + 13 => 'Monochrome Profile 2', #23 + 14 => 'Monochrome Profile 3', #23 + 256 => 'Monotone', + 512 => 'Sepia', + }], + }, + 0x521 => { #6 + Name => 'PictureModeSaturation', + Writable => 'int16s', + Count => 3, + Notes => 'value, min, max', + PrintConv => 'my @v=split " ",$val; "$v[0] (min $v[1], max $v[2])"', + PrintConvInv => '$val=~tr/-0-9 //dc;$val', + }, + 0x522 => { #6 + Name => 'PictureModeHue', + Writable => 'int16s', + Unknown => 1, # (needs verification) + }, + 0x523 => { #6 + Name => 'PictureModeContrast', + Writable => 'int16s', + Count => 3, + Notes => 'value, min, max', + PrintConv => 'my @v=split " ",$val; "$v[0] (min $v[1], max $v[2])"', + PrintConvInv => '$val=~tr/-0-9 //dc;$val', + }, + 0x524 => { #6 + Name => 'PictureModeSharpness', + # verified as the Sharpness setting in the Picture Mode menu for the E-410 + Writable => 'int16s', + Count => 3, + Notes => 'value, min, max', + PrintConv => 'my @v=split " ",$val; "$v[0] (min $v[1], max $v[2])"', + PrintConvInv => '$val=~tr/-0-9 //dc;$val', + }, + 0x525 => { #6 + Name => 'PictureModeBWFilter', + Writable => 'int16s', + PrintConvColumns => 2, + PrintConv => { + 0 => 'n/a', + 1 => 'Neutral', + 2 => 'Yellow', + 3 => 'Orange', + 4 => 'Red', + 5 => 'Green', + }, + }, + 0x526 => { #6 + Name => 'PictureModeTone', + Writable => 'int16s', + PrintConvColumns => 2, + PrintConv => { + 0 => 'n/a', + 1 => 'Neutral', + 2 => 'Sepia', + 3 => 'Blue', + 4 => 'Purple', + 5 => 'Green', + }, + }, + 0x527 => { #12 + Name => 'NoiseFilter', + Writable => 'int16s', + Count => 3, + PrintConv => { + '0 0 0' => 'n/a', #PH (?) + '-2 -2 1' => 'Off', + '-1 -2 1' => 'Low', + '0 -2 1' => 'Standard', + '1 -2 1' => 'High', + }, + }, + 0x529 => { #PH + Name => 'ArtFilter', + Writable => 'int16u', + Count => 4, + PrintConvColumns => 2, + PrintConv => [ \%filters ], + }, + 0x52c => { #PH + Name => 'MagicFilter', + Writable => 'int16u', + Count => 4, # (2nd number is 0, 1280 or 1792, 3rd/4th are 0) + # (1792 observed for E-5 Gentle Sepia and XZ-1 Dramatic Tone) + PrintConvColumns => 2, + PrintConv => [ \%filters ], + }, + 0x52d => { #11 + Name => 'PictureModeEffect', + Writable => 'int16s', + Count => 3, + PrintConv => { + '0 0 0' => 'n/a', #PH (?) + '-1 -1 1' => 'Low', + '0 -1 1' => 'Standard', + '1 -1 1' => 'High', + }, + }, + 0x52e => { #11/PH + Name => 'ToneLevel', + PrintConv => [ + \%toneLevelType, + undef, # (highlights value) + undef, # (highlights min) + undef, # (highlights max) + \%toneLevelType, + undef, # (shadows value) + undef, # (shadows min) + undef, # (shadows max) + \%toneLevelType, + undef, # (midtones value) + undef, # (midtones min) + undef, # (midtones max) + \%toneLevelType, + undef, + undef, + undef, + \%toneLevelType, + undef, + undef, + undef, + \%toneLevelType, + undef, + undef, + undef, + \%toneLevelType, + undef, + undef, + undef, + ] + }, + 0x52f => { #PH + Name => 'ArtFilterEffect', + Writable => 'int16u', + Count => 20, + PrintHex => 1, + PrintConvColumns => 2, + PrintConv => [ + \%filters, + undef, + undef, + '"Partial Color $val"', #23 + { # there are 5 available art filter effects for the E-PL3... + 0x0000 => 'No Effect', + 0x8010 => 'Star Light', + 0x8020 => 'Pin Hole', + 0x8030 => 'Frame', + 0x8040 => 'Soft Focus', + 0x8050 => 'White Edge', + 0x8060 => 'B&W', # (NC - E-PL2 with "Grainy Film" filter) + 0x8080 => 'Blur Top and Bottom', #23 + 0x8081 => 'Blur Left and Right', #23 + # (E-PL2 also has "Pict. Tone" effect) + }, + undef, + { #23 + 0 => 'No Color Filter', + 1 => 'Yellow Color Filter', + 2 => 'Orange Color Filter', + 3 => 'Red Color Filter', + 4 => 'Green Color Filter', + }, + ], + }, + 0x532 => { #23 + Name => 'ColorCreatorEffect', + Writable => 'int16s', + Count => 6, + PrintConv => [ + '"Color $val"', + undef, # (Color min) + undef, # (Color max) + '"Strength $val"', + undef, # (Strength min) + undef, # (Strength max) + ], + }, + 0x537 => { #23 + Name => 'MonochromeProfileSettings', + Writable => 'int16s', + Count => 6, + PrintConv => [ + { + 0 => 'No Filter', + 1 => 'Yellow Filter', + 2 => 'Orange Filter', + 3 => 'Red Filter', + 4 => 'Magenta Filter', + 5 => 'Blue Filter', + 6 => 'Cyan Filter', + 7 => 'Green Filter', + 8 => 'Yellow-green Filter', + }, + undef, # (Filter number min) + undef, # (Filter number max) + '"Strength $val"', + undef, # (Strength min) + undef, # (Strength max) + ], + }, + 0x538 => { #23 + Name => 'FilmGrainEffect', + Writable => 'int16s', + PrintConv => { + 0 => 'Off', + 1 => 'Low', + 2 => 'Medium', + 3 => 'High', + }, + }, + 0x539 => { #23 + Name => 'ColorProfileSettings', + Writable => 'int16s', + Count => 14, + PrintConv => [ + '"Min $val"', + '"Max $val"', + '"Yellow $val"', + '"Orange $val"', + '"Orange-red $val"', + '"Red $val"', + '"Magenta $val"', + '"Violet $val"', + '"Blue $val"', + '"Blue-cyan $val"', + '"Cyan $val"', + '"Green-cyan $val"', + '"Green $val"', + '"Yellow-green $val"', + ], + }, + 0x53a => { #23 + Name => 'MonochromeVignetting', + Writable => 'int16s', + Notes => '-5 to +5: positive is white vignetting, negative is black vignetting', + }, + 0x53b => { #23 + Name => 'MonochromeColor', + Writable => 'int16s', + PrintConv => { + 0 => '(none)', + 1 => 'Normal', + 2 => 'Sepia', + 3 => 'Blue', + 4 => 'Purple', + 5 => 'Green', + }, + }, + 0x600 => { #PH/4/22 + Name => 'DriveMode', + Writable => 'int16u', + Count => -1, + Notes => '2, 3 or 5 numbers: 1. Mode, 2. Shot number, 3. Mode bits, 5. Shutter mode', + PrintConv => q{ + my ($a,$b,$c,$d,$e) = split ' ',$val; + if ($e) { + $e = '; ' . ({ 2 => 'Anti-shock 0', 4 => 'Electronic shutter' }->{$e} || "Unknown ($e)"); + } else { + $e = ''; + } + return "Single Shot$e" unless $a; + if ($a == 5 and defined $c) { + $a = DecodeBits($c, { #6 + 0 => 'AE', + 1 => 'WB', + 2 => 'FL', + 3 => 'MF', + 4 => 'ISO', #forum8906 + 5 => 'AE Auto', #forum8906 + 6 => 'Focus', #PH + }) . ' Bracketing'; + $a =~ s/, /+/g; + } else { + my %a = ( + 1 => 'Continuous Shooting', + 2 => 'Exposure Bracketing', + 3 => 'White Balance Bracketing', + 4 => 'Exposure+WB Bracketing', #6 + ); + $a = $a{$a} || "Unknown ($a)"; + } + return "$a, Shot $b$e"; + }, + }, + 0x601 => { #6 + Name => 'PanoramaMode', + Writable => 'int16u', + Notes => '2 numbers: 1. Mode, 2. Shot number', + PrintConv => q{ + my ($a,$b) = split ' ',$val; + return 'Off' unless $a; + my %a = ( + 1 => 'Left to Right', + 2 => 'Right to Left', + 3 => 'Bottom to Top', + 4 => 'Top to Bottom', + ); + return ($a{$a} || "Unknown ($a)") . ', Shot ' . $b; + }, + }, + 0x603 => { #PH/4 + Name => 'ImageQuality2', + Writable => 'int16u', + PrintConv => { + 1 => 'SQ', + 2 => 'HQ', + 3 => 'SHQ', + 4 => 'RAW', + 5 => 'SQ (5)', # (E-500) + }, + }, + 0x604 => { #PH + Name => 'ImageStabilization', + Writable => 'int32u', + DataMember => 'ImageStabilization', + RawConv => '$$self{ImageStabilization} = $val', + PrintConv => { + 0 => 'Off', + 1 => 'On, Mode 1', + 2 => 'On, Mode 2', + 3 => 'On, Mode 3', + 4 => 'On, Mode 4', # (NC, E-P5) + }, + }, + 0x804 => { #PH (E-M1 with firmware update) + Name => 'StackedImage', + Writable => 'int32u', + Count => 2, + PrintConv => { + '0 0' => 'No', + '3 2' => 'ND2 (1EV)', #IB + '3 4' => 'ND4 (2EV)', #IB + '3 8' => 'ND8 (3EV)', #IB + '3 16' => 'ND16 (4EV)', #IB + '3 32' => 'ND32 (5EV)', #IB + '5 4' => 'HDR1', #forum8906 + '6 4' => 'HDR2', #forum8906 + '8 8' => 'Tripod high resolution', #IB + '9 2' => 'Focus-stacked (2 images)', #IB + '9 3' => 'Focus-stacked (3 images)', #IB + '9 4' => 'Focus-stacked (4 images)', #IB + '9 5' => 'Focus-stacked (5 images)', #IB + '9 6' => 'Focus-stacked (6 images)', #IB + '9 7' => 'Focus-stacked (7 images)', #IB + '9 8' => 'Focus-stacked (8 images)', + '9 9' => 'Focus-stacked (9 images)', #IB + '9 10' => 'Focus-stacked (10 images)', #IB + '9 11' => 'Focus-stacked (11 images)', #IB + '9 12' => 'Focus-stacked (12 images)', #IB + '9 13' => 'Focus-stacked (13 images)', #IB + '9 14' => 'Focus-stacked (14 images)', #IB + '9 15' => 'Focus-stacked (15 images)', #IB + '11 16' => 'Hand-held high resolution', #IB + }, + }, + 0x900 => { #11 + Name => 'ManometerPressure', + Writable => 'int16u', + ValueConv => '$val / 10', + ValueConvInv => '$val * 10', + PrintConv => '"$val kPa"', + PrintConvInv => '$val=~s/ ?kPa//i; $val', + }, + 0x901 => { #PH (u770SW) + # 2 numbers: 1st looks like meters above sea level, 2nd is usually 3x the 1st (feet?) + Name => 'ManometerReading', + Writable => 'int32s', + Count => 2, + ValueConv => 'my @a=split(" ",$val); $_ /= 10 foreach @a; "@a"', + ValueConvInv => 'my @a=split(" ",$val); $_ *= 10 foreach @a; "@a"', + PrintConv => '$val=~s/(\S+) (\S+)/$1 m, $2 ft/; $val', + PrintConvInv => '$val=~s/ ?(m|ft)//gi; $val', + }, + 0x902 => { #11 + Name => 'ExtendedWBDetect', + Writable => 'int16u', + PrintConv => \%offOn, + }, + 0x903 => { #11 + Name => 'RollAngle', + Notes => 'converted to degrees of clockwise camera rotation', + Writable => 'int16s', + Count => 2, # (second value is 0 if level gauge is off) + # negate to express as clockwise rotation + ValueConv => '$val=~s/ 1$// ? -$val/10 : "n/a"', + ValueConvInv => 'IsFloat($val) ? sprintf("%.0f 1",-$val*10) : "0 0"', + }, + 0x904 => { #11 + Name => 'PitchAngle', + Notes => 'converted to degrees of upward camera tilt', + Writable => 'int16s', + Count => 2, # (second value is 0 if level gauge is off) + ValueConv => '$val =~ s/ 1$// ? $val / 10 : "n/a"', + ValueConvInv => 'IsFloat($val) ? sprintf("%.0f 1",$val*10) : "0 0"', + }, + 0x908 => { #PH (NC, E-M1) + Name => 'DateTimeUTC', + Writable => 'string', + Groups => { 2 => 'Time' }, + Shift => 'Time', + PrintConv => '$self->ConvertDateTime($val)', + PrintConvInv => '$self->InverseDateTime($val,undef,1)', + }, +); + +# Olympus RAW processing IFD (ref 6) +%Image::ExifTool::Olympus::RawDevelopment = ( + WRITE_PROC => \&Image::ExifTool::Exif::WriteExif, + CHECK_PROC => \&Image::ExifTool::Exif::CheckExif, + WRITABLE => 1, + GROUPS => { 0 => 'MakerNotes', 2 => 'Camera' }, + 0x000 => { #PH + Name => 'RawDevVersion', + Writable => 'undef', + RawConv => '$val=~s/\0+$//; $val', # (may be null terminated) + Count => 4, + }, + 0x100 => { Name => 'RawDevExposureBiasValue', Writable => 'rational64s' }, + 0x101 => { Name => 'RawDevWhiteBalanceValue', Writable => 'int16u' }, + 0x102 => { Name => 'RawDevWBFineAdjustment', Writable => 'int16s' }, + 0x103 => { Name => 'RawDevGrayPoint', Writable => 'int16u', Count => 3 }, + 0x104 => { Name => 'RawDevSaturationEmphasis', Writable => 'int16s', Count => 3 }, + 0x105 => { Name => 'RawDevMemoryColorEmphasis', Writable => 'int16u' }, + 0x106 => { Name => 'RawDevContrastValue', Writable => 'int16s', Count => 3 }, + 0x107 => { Name => 'RawDevSharpnessValue', Writable => 'int16s', Count => 3 }, + 0x108 => { + Name => 'RawDevColorSpace', + Writable => 'int16u', + PrintConv => { #11 + 0 => 'sRGB', + 1 => 'Adobe RGB', + 2 => 'Pro Photo RGB', + }, + }, + 0x109 => { + Name => 'RawDevEngine', + Writable => 'int16u', + PrintConv => { #11 + 0 => 'High Speed', + 1 => 'High Function', + 2 => 'Advanced High Speed', + 3 => 'Advanced High Function', + }, + }, + 0x10a => { + Name => 'RawDevNoiseReduction', + Writable => 'int16u', + PrintConv => { #11 + 0 => '(none)', + BITMASK => { + 0 => 'Noise Reduction', + 1 => 'Noise Filter', + 2 => 'Noise Filter (ISO Boost)', + }, + }, + }, + 0x10b => { + Name => 'RawDevEditStatus', + Writable => 'int16u', + PrintConv => { #11 + 0 => 'Original', + 1 => 'Edited (Landscape)', + 6 => 'Edited (Portrait)', + 8 => 'Edited (Portrait)', + }, + }, + 0x10c => { + Name => 'RawDevSettings', + Writable => 'int16u', + PrintConv => { #11 + 0 => '(none)', + BITMASK => { + 0 => 'WB Color Temp', + 1 => 'WB Gray Point', + 2 => 'Saturation', + 3 => 'Contrast', + 4 => 'Sharpness', + 5 => 'Color Space', + 6 => 'High Function', + 7 => 'Noise Reduction', + }, + }, + }, +); + +# Olympus RAW processing B IFD (ref 11) +%Image::ExifTool::Olympus::RawDevelopment2 = ( + WRITE_PROC => \&Image::ExifTool::Exif::WriteExif, + CHECK_PROC => \&Image::ExifTool::Exif::CheckExif, + WRITABLE => 1, + GROUPS => { 0 => 'MakerNotes', 2 => 'Camera' }, + 0x000 => { + Name => 'RawDevVersion', + Writable => 'undef', + RawConv => '$val=~s/\0+$//; $val', # (may be null terminated) + Count => 4, + }, + 0x100 => { Name => 'RawDevExposureBiasValue', Writable => 'rational64s' }, + 0x101 => { + Name => 'RawDevWhiteBalance', + Writable => 'int16u', + PrintConv => { + 1 => 'Color Temperature', + 2 => 'Gray Point', + }, + }, + 0x102 => { Name => 'RawDevWhiteBalanceValue', Writable => 'int16u' }, + 0x103 => { Name => 'RawDevWBFineAdjustment', Writable => 'int16s' }, + 0x104 => { Name => 'RawDevGrayPoint', Writable => 'int16u', Count => 3 }, + 0x105 => { Name => 'RawDevContrastValue', Writable => 'int16s', Count => 3 }, + 0x106 => { Name => 'RawDevSharpnessValue', Writable => 'int16s', Count => 3 }, + 0x107 => { Name => 'RawDevSaturationEmphasis', Writable => 'int16s', Count => 3 }, + 0x108 => { Name => 'RawDevMemoryColorEmphasis', Writable => 'int16u' }, + 0x109 => { + Name => 'RawDevColorSpace', + Writable => 'int16u', + PrintConv => { + 0 => 'sRGB', + 1 => 'Adobe RGB', + 2 => 'Pro Photo RGB', + }, + }, + 0x10a => { + Name => 'RawDevNoiseReduction', + Writable => 'int16u', + PrintConv => { + 0 => '(none)', + BITMASK => { + 0 => 'Noise Reduction', + 1 => 'Noise Filter', + 2 => 'Noise Filter (ISO Boost)', + }, + }, + }, + 0x10b => { + Name => 'RawDevEngine', + Writable => 'int16u', + PrintConv => { + 0 => 'High Speed', + 1 => 'High Function', + }, + }, + 0x10c => { + Name => 'RawDevPictureMode', + Writable => 'int16u', + PrintConv => { + 1 => 'Vivid', + 2 => 'Natural', + 3 => 'Muted', + 256 => 'Monotone', + 512 => 'Sepia', + }, + }, + 0x10d => { Name => 'RawDevPMSaturation', Writable => 'int16s', Count => 3 }, + 0x10e => { Name => 'RawDevPMContrast', Writable => 'int16s', Count => 3 }, + 0x10f => { Name => 'RawDevPMSharpness', Writable => 'int16s', Count => 3 }, + 0x110 => { + Name => 'RawDevPM_BWFilter', + Writable => 'int16u', + PrintConv => { + 1 => 'Neutral', + 2 => 'Yellow', + 3 => 'Orange', + 4 => 'Red', + 5 => 'Green', + }, + }, + 0x111 => { + Name => 'RawDevPMPictureTone', + Writable => 'int16u', + PrintConv => { + 1 => 'Neutral', + 2 => 'Sepia', + 3 => 'Blue', + 4 => 'Purple', + 5 => 'Green', + }, + }, + 0x112 => { Name => 'RawDevGradation', Writable => 'int16s', Count => 3 }, + 0x113 => { Name => 'RawDevSaturation3', Writable => 'int16s', Count => 3 }, #(NC Count) + 0x119 => { Name => 'RawDevAutoGradation', Writable => 'int16u', PrintConv => \%offOn }, + 0x120 => { Name => 'RawDevPMNoiseFilter', Writable => 'int16u' }, #(NC format) + 0x121 => { #PH (E-P5) + Name => 'RawDevArtFilter', + Writable => 'int16u', + Count => 4, + PrintConvColumns => 2, + PrintConv => [ \%filters ], + }, +); + +# Olympus Image processing IFD +%Image::ExifTool::Olympus::ImageProcessing = ( + WRITE_PROC => \&Image::ExifTool::Exif::WriteExif, + CHECK_PROC => \&Image::ExifTool::Exif::CheckExif, + WRITABLE => 1, + GROUPS => { 0 => 'MakerNotes', 2 => 'Camera' }, + 0x000 => { #PH + Name => 'ImageProcessingVersion', + Writable => 'undef', + RawConv => '$val=~s/\0+$//; $val', # (may be null terminated) + Count => 4, + }, + 0x100 => { Name => 'WB_RBLevels', Writable => 'int16u', Count => 2 }, #6 + # 0x101 - in-camera AutoWB unless it is all 0's or all 256's (ref IB) + 0x102 => { Name => 'WB_RBLevels3000K', Writable => 'int16u', Count => 2 }, #11 + 0x103 => { Name => 'WB_RBLevels3300K', Writable => 'int16u', Count => 2 }, #11 + 0x104 => { Name => 'WB_RBLevels3600K', Writable => 'int16u', Count => 2 }, #11 + 0x105 => { Name => 'WB_RBLevels3900K', Writable => 'int16u', Count => 2 }, #11 + 0x106 => { Name => 'WB_RBLevels4000K', Writable => 'int16u', Count => 2 }, #11 + 0x107 => { Name => 'WB_RBLevels4300K', Writable => 'int16u', Count => 2 }, #11 + 0x108 => { Name => 'WB_RBLevels4500K', Writable => 'int16u', Count => 2 }, #11 + 0x109 => { Name => 'WB_RBLevels4800K', Writable => 'int16u', Count => 2 }, #11 + 0x10a => { Name => 'WB_RBLevels5300K', Writable => 'int16u', Count => 2 }, #11 + 0x10b => { Name => 'WB_RBLevels6000K', Writable => 'int16u', Count => 2 }, #11 + 0x10c => { Name => 'WB_RBLevels6600K', Writable => 'int16u', Count => 2 }, #11 + 0x10d => { Name => 'WB_RBLevels7500K', Writable => 'int16u', Count => 2 }, #11 + 0x10e => { Name => 'WB_RBLevelsCWB1', Writable => 'int16u', Count => 2 }, #11 + 0x10f => { Name => 'WB_RBLevelsCWB2', Writable => 'int16u', Count => 2 }, #11 + 0x110 => { Name => 'WB_RBLevelsCWB3', Writable => 'int16u', Count => 2 }, #11 + 0x111 => { Name => 'WB_RBLevelsCWB4', Writable => 'int16u', Count => 2 }, #11 + 0x113 => { Name => 'WB_GLevel3000K', Writable => 'int16u' }, #11 + 0x114 => { Name => 'WB_GLevel3300K', Writable => 'int16u' }, #11 + 0x115 => { Name => 'WB_GLevel3600K', Writable => 'int16u' }, #11 + 0x116 => { Name => 'WB_GLevel3900K', Writable => 'int16u' }, #11 + 0x117 => { Name => 'WB_GLevel4000K', Writable => 'int16u' }, #11 + 0x118 => { Name => 'WB_GLevel4300K', Writable => 'int16u' }, #11 + 0x119 => { Name => 'WB_GLevel4500K', Writable => 'int16u' }, #11 + 0x11a => { Name => 'WB_GLevel4800K', Writable => 'int16u' }, #11 + 0x11b => { Name => 'WB_GLevel5300K', Writable => 'int16u' }, #11 + 0x11c => { Name => 'WB_GLevel6000K', Writable => 'int16u' }, #11 + 0x11d => { Name => 'WB_GLevel6600K', Writable => 'int16u' }, #11 + 0x11e => { Name => 'WB_GLevel7500K', Writable => 'int16u' }, #11 + 0x11f => { Name => 'WB_GLevel', Writable => 'int16u' }, #11 + # 0x121 = WB preset for flash (about 6000K) (ref IB) + # 0x125 = WB preset for underwater (ref IB) + 0x200 => { #6 + Name => 'ColorMatrix', + Writable => 'int16u', + Format => 'int16s', + Count => 9, + }, + # color matrices (ref 11): + # 0x0201-0x020d are sRGB color matrices + # 0x020e-0x021a are Adobe RGB color matrices + # 0x021b-0x0227 are ProPhoto RGB color matrices + # 0x0228 and 0x0229 are ColorMatrix for E-330 + # 0x0250-0x0252 are sRGB color matrices + # 0x0253-0x0255 are Adobe RGB color matrices + # 0x0256-0x0258 are ProPhoto RGB color matrices + 0x300 => { Name => 'Enhancer', Writable => 'int16u' }, #11 + 0x301 => { Name => 'EnhancerValues', Writable => 'int16u', Count => 7 }, #11 + 0x310 => { Name => 'CoringFilter', Writable => 'int16u' }, #11 + 0x311 => { Name => 'CoringValues', Writable => 'int16u', Count => 7 }, #11 + 0x600 => { Name => 'BlackLevel2', Writable => 'int16u', Count => 4 }, #11 + 0x610 => { Name => 'GainBase', Writable => 'int16u' }, #11 + 0x611 => { Name => 'ValidBits', Writable => 'int16u', Count => 2 }, #4/6 + 0x612 => { Name => 'CropLeft', Writable => 'int16u', Count => 2 }, #11 + 0x613 => { Name => 'CropTop', Writable => 'int16u', Count => 2 }, #11 + 0x614 => { Name => 'CropWidth', Writable => 'int32u' }, #PH/11 + 0x615 => { Name => 'CropHeight', Writable => 'int32u' }, #PH/11 + 0x635 => { #PH (data starts with "CMIO\x01\0") + Name => 'UnknownBlock1', + Writable => 'undef', + Notes => 'large unknown data block in ORF images but not JPG images', + # 'Drop' because too large for APP1 in JPEG images + Flags => [ 'Unknown', 'Binary', 'Drop' ], + }, + 0x636 => { #PH (data starts with "CMIO\x01\0") + Name => 'UnknownBlock2', + Writable => 'undef', + Notes => 'large unknown data block in ORF images but not JPG images', + # 'Drop' because too large for APP1 in JPEG images + Flags => [ 'Unknown', 'Binary', 'Drop' ], + }, + # 0x800 LensDistortionParams, float[9] (ref 11) + # 0x801 LensShadingParams, int16u[16] (ref 11) + 0x0805 => { #IB + Name => 'SensorCalibration', + Notes => '2 numbers: 1. Recommended maximum, 2. Calibration midpoint', + Writable => 'int16s', + Count => 2, + }, + # 0x1010-0x1012 are the processing options used in camera or in + # Olympus software, which 0x050a-0x050c are in-camera only (ref 6) + 0x1010 => { #PH/4 + Name => 'NoiseReduction2', + Writable => 'int16u', + PrintConv => { + 0 => '(none)', + BITMASK => { + 0 => 'Noise Reduction', + 1 => 'Noise Filter', + 2 => 'Noise Filter (ISO Boost)', + }, + }, + }, + 0x1011 => { #6 + Name => 'DistortionCorrection2', + Writable => 'int16u', + PrintConv => \%offOn, + }, + 0x1012 => { #PH/4 + Name => 'ShadingCompensation2', + Writable => 'int16u', + PrintConv => \%offOn, + }, + 0x101c => { #11 + Name => 'MultipleExposureMode', + Writable => 'int16u', + Count => 2, + PrintConv => [{ + 0 => 'Off', + 2 => 'On (2 frames)', + 3 => 'On (3 frames)', + }], + }, + 0x1103 => { #PH + Name => 'UnknownBlock3', + Writable => 'undef', + Notes => 'large unknown data block in ORF images but not JPG images', + # 'Drop' because too large for APP1 in JPEG images + Flags => [ 'Unknown', 'Binary', 'Drop' ], + }, + 0x1104 => { #PH (overlaps data for 0x1103 in E-M5 ORF images) + Name => 'UnknownBlock4', + Writable => 'undef', + Notes => 'large unknown data block in ORF images but not JPG images', + # 'Drop' because too large for APP1 in JPEG images + Flags => [ 'Unknown', 'Binary', 'Drop' ], + }, + 0x1112 => { #11 + Name => 'AspectRatio', + Writable => 'int8u', + Count => 2, + PrintConv => { + # '0 0' - have seen this with a 16:9 XZ-1 image - PH + '1 1' => '4:3', + '1 4' => '1:1', #PH (E-P5 Storyboard effect, does this indicate 4:3 converted to 6:6?) + '2 1' => '3:2 (RAW)', #forum6285 + '2 2' => '3:2', + '3 1' => '16:9 (RAW)', #forum6285 + '3 3' => '16:9', + '4 1' => '1:1 (RAW)', #forum6285 + '4 4' => '6:6', + '5 5' => '5:4', + '6 6' => '7:6', + '7 7' => '6:5', + '8 8' => '7:5', + '9 1' => '3:4 (RAW)', #forum6285 + '9 9' => '3:4', + }, + }, + 0x1113 => { Name => 'AspectFrame', Writable => 'int16u', Count => 4 }, #11 + 0x1200 => { #11/PH + Name => 'FacesDetected', + Writable => 'int32u', + Count => -1, + Notes => '2 or 3 values', + }, + 0x1201 => { #11/PH + Name => 'FaceDetectArea', + Writable => 'int16s', + Count => -1, # (varies with model) + Binary => 1, # (too long) + Notes => q{ + for models with 2 values in FacesDetected this gives X/Y coordinates in the + FaceDetectFrame for all 4 corners of the face rectangle. For models with 3 + values in FacesDetected this gives X/Y coordinates, size and rotation angle + of the face detect square + }, + }, + 0x1202 => { Name => 'MaxFaces', Writable => 'int32u', Count => 3 }, #PH + 0x1203 => { #PH + Name => 'FaceDetectFrameSize', + Writable => 'int16u', + Count => 6, + Notes => 'width/height of the full face detect frame', + }, + 0x1207 => { #PH + Name => 'FaceDetectFrameCrop', + Writable => 'int16s', + Count => 12, + Notes => 'X/Y offset and width/height of the cropped face detect frame', + }, + 0x1306 => { #PH (NC, E-M1) + Name => 'CameraTemperature', + Writable => 'int16u', + Format => 'int16s', #(NC) + ValueConv => '$val ? $val : undef', # zero for some models (how to differentiate from 0 C?) + Notes => 'this seems to be in degrees C only for some models', + }, + 0x1900 => { #23 + Name => 'KeystoneCompensation', + Writable => 'int8u', + Count => 2, + PrintConv => { + '0 0' => 'Off', + '0 1' => 'On', + }, + }, + 0x1901 => { #23 + Name => 'KeystoneDirection', + Writable => 'int8u', + Count => 2, + PrintConv => { + 0 => 'Vertical', + 1 => 'Horizontal', + }, + }, + # 0x1905 - focal length (PH, E-M1) + 0x1906 => { #23 + Name => 'KeystoneValue', + Writable => 'int16s', + Count => 3, + # (use in conjunction with KeystoneDirection, -ve is Top or Right, +ve is Bottom or Left) + Notes => '3 numbers: 1. Keystone Value, 2. Min, 3. Max', + }, +); + +# Olympus Focus Info IFD +%Image::ExifTool::Olympus::FocusInfo = ( + WRITE_PROC => \&Image::ExifTool::Exif::WriteExif, + CHECK_PROC => \&Image::ExifTool::Exif::CheckExif, + WRITABLE => 1, + GROUPS => { 0 => 'MakerNotes', 2 => 'Camera' }, + 0x000 => { #PH + Name => 'FocusInfoVersion', + Writable => 'undef', + RawConv => '$val=~s/\0+$//; $val', # (may be null terminated) + Count => 4, + }, + 0x209 => { #PH/4 + Name => 'AutoFocus', + Writable => 'int16u', + PrintConv => \%offOn, + Unknown => 1, #6 + }, + 0x210 => { Name => 'SceneDetect', Writable => 'int16u' }, #11 + 0x211 => { #11 + Name => 'SceneArea', + Writable => 'int32u', + Count => 8, + Unknown => 1, # (numbers don't make much sense?) + }, + 0x212 => { #11 + Name => 'SceneDetectData', + Writable => 'int32u', + Count => 720, + Binary => 1, + Unknown => 1, # (but what does it mean?) + }, + # 0x214 - int16u: normally 0, but 1 for E-M1 focus-bracketing, and have seen 1 and 256 at other times + 0x300 => { Name => 'ZoomStepCount', Writable => 'int16u' }, #6 + 0x301 => { Name => 'FocusStepCount', Writable => 'int16u' }, #11 + 0x303 => { Name => 'FocusStepInfinity', Writable => 'int16u' }, #11 + 0x304 => { Name => 'FocusStepNear', Writable => 'int16u' }, #11 + 0x305 => { #4 + Name => 'FocusDistance', + Writable => 'rational64u', + # this rational value looks like it is in mm when the denominator is + # 1 (E-1), and cm when denominator is 10 (E-300), so if we ignore the + # denominator we are consistently in mm - PH + Format => 'int32u', + Count => 2, + ValueConv => q{ + my ($a,$b) = split ' ',$val; + return 0 if $a == 0xffffffff; + return $a / 1000; + }, + ValueConvInv => q{ + return '4294967295 1' unless $val; + $val = int($val * 1000 + 0.5); + return "$val 1"; + }, + PrintConv => '$val ? "$val m" : "inf"', + PrintConvInv => '$val eq "inf" ? 0 : $val=~s/\s*m$//, $val', + }, + 0x308 => [ # NEED A BETTER WAY TO DETERMINE WHICH MODELS USE WHICH ENCODING! + { + Name => 'AFPoint', + Condition => '$$self{Model} =~ /E-(3|5|30)\b/', + Writable => 'int16u', + PrintHex => 1, + # decoded by ref 6 + Notes => q{ + for the E-3, E-5 and E-30 the value is separated into 2 parts: low 5 bits + give AF point, upper bits give AF target selection mode + }, + ValueConv => '($val & 0x1f) . " " . ($val & 0xffe0)', + ValueConvInv => 'my @v=split(" ",$val); @v == 2 ? $v[0] + $v[1] : $val', + PrintConvColumns => 2, + PrintConv => [ + { + 0x00 => '(none)', + 0x01 => 'Top-left (horizontal)', + 0x02 => 'Top-center (horizontal)', + 0x03 => 'Top-right (horizontal)', + 0x04 => 'Left (horizontal)', + 0x05 => 'Mid-left (horizontal)', + 0x06 => 'Center (horizontal)', + 0x07 => 'Mid-right (horizontal)', + 0x08 => 'Right (horizontal)', + 0x09 => 'Bottom-left (horizontal)', + 0x0a => 'Bottom-center (horizontal)', + 0x0b => 'Bottom-right (horizontal)', + 0x0c => 'Top-left (vertical)', + 0x0d => 'Top-center (vertical)', + 0x0e => 'Top-right (vertical)', + 0x0f => 'Left (vertical)', + 0x10 => 'Mid-left (vertical)', + 0x11 => 'Center (vertical)', + 0x12 => 'Mid-right (vertical)', + 0x13 => 'Right (vertical)', + 0x14 => 'Bottom-left (vertical)', + 0x15 => 'Bottom-center (vertical)', + 0x16 => 'Bottom-right (vertical)', + 0x1f => 'n/a', #PH (NC, E-3) + }, + { + 0x00 => 'Single Target', + 0x40 => 'All Target', + 0x80 => 'Dynamic Single Target', + 0xe0 => 'n/a', #PH (NC, E-3) + } + ], + },{ #PH (models with 7-point AF) + Name => 'AFPoint', + Condition => '$$self{Model} =~ /E-(520|600|620)\b/', + Notes => 'models with 7-point AF', + Writable => 'int16u', + PrintHex => 1, + ValueConv => '($val & 0x1f) . " " . ($val & 0xffe0)', + ValueConvInv => 'my @v=split(" ",$val); @v == 2 ? $v[0] + $v[1] : $val', + PrintConv => [ + { + 0x00 => '(none)', + 0x01 => 'Center', + # need to fill this in... + }, + { + 0x00 => 'Single Target', + 0x40 => 'All Target', # (guess) + }, + ] + },{ #11 + Name => 'AFPoint', + Writable => 'int16u', + Notes => 'other models', + RawConv => '($val or $$self{Model} ne "E-P1") ? $val : undef', + PrintConv => { + # (E-P1 always writes 0, maybe other models do too - PH) + 0 => 'Left (or n/a)', + 1 => 'Center (horizontal)', #6 (E-510) + 2 => 'Right', + 3 => 'Center (vertical)', #6 (E-510) + 255 => 'None', + }, + } + ], + # 0x31a Continuous AF parameters? + 0x328 => { #PH + Name => 'AFInfo', + SubDirectory => { TagTable => 'Image::ExifTool::Olympus::AFInfo' }, + }, + # 0x1200-0x1209 Flash information: + 0x1201 => { #6 + Name => 'ExternalFlash', + Writable => 'int16u', + Count => 2, + PrintConv => { + '0 0' => 'Off', + '1 0' => 'On', + }, + }, + 0x1203 => { #11 + Name => 'ExternalFlashGuideNumber', + Writable => 'rational64s', + Unknown => 1, # (needs verification) + }, + 0x1204 => { #11(reversed)/7 + Name => 'ExternalFlashBounce', + Writable => 'int16u', + PrintConv => { + 0 => 'Bounce or Off', + 1 => 'Direct', + }, + }, + 0x1205 => { Name => 'ExternalFlashZoom', Writable => 'rational64u' }, #11 (ref converts to mm using table) + 0x1208 => { #6 + Name => 'InternalFlash', + Writable => 'int16u', + Count => -1, + PrintConv => { + '0' => 'Off', + '1' => 'On', + '0 0' => 'Off', + '1 0' => 'On', + }, + }, + 0x1209 => { #6 + Name => 'ManualFlash', + Writable => 'int16u', + Count => 2, + Notes => '2 numbers: 1. 0=Off, 1=On, 2. Flash strength', + PrintConv => q{ + my ($a,$b) = split ' ',$val; + return 'Off' unless $a; + $b = ($b == 1) ? 'Full' : "1/$b"; + return "On ($b strength)"; + }, + }, + 0x120a => { #PH + Name => 'MacroLED', + Writable => 'int16u', + PrintConv => \%offOn, + }, + 0x1500 => [{ #6 + Name => 'SensorTemperature', + # (Stylus 1 stores values like "34 0 0") + Condition => '$$self{Model} =~ /E-(1|M5)\b/ || $count != 1', + Writable => 'int16s', + PrintConv => '$val=~s/ 0 0$//; "$val C"', + PrintConvInv => '$val=~s/ ?C$//; $val', + },{ + Name => 'SensorTemperature', + Writable => 'int16s', + RawConv => '($val and $val ne "-32768") ? $val : undef', # ignore 0 and -32768 + # ValueConv => '-2*(($val/135)**2)+55', #11 + ValueConv => '84 - 3 * $val / 26', #http://u88.n24.queensu.ca/exiftool/forum/index.php/topic,5423.0.html + ValueConvInv => 'int((84 - $val) * 26 / 3 + 0.5)', + PrintConv => 'sprintf("%.1f C",$val)', + PrintConvInv => '$val=~s/ ?C$//; $val', + # data from test shots by Eric Sibert: + # E-510 E-620 + # Raw Ambient Raw Ambient + # --- ------- --- ------- + # 534 22.7 518 22.7 + # 550 20.6 531 19.3 + # 552 20.8 533 17.9 + # 558 19.3 582 17.2 + # 564 19.1 621 12.3 + # 567 17.8 634 9.7 + # 576 18.6 650 8.0 + # 582 17.2 660 7.7 + # 599 13.8 703 3.3 + # 631 10.7 880 -20.6 + # 642 12.4 880 -20.6 + # 652 9.6 892 -24.4 + # 692 5.2 892 -22.7 + # 714 3.3 + # 895 -19.8 + # 895 -19.2 + # 900 -21.7 + }], + 0x1600 => { # ref http://fourthirdsphoto.com/vbb/showpost.php?p=107607&postcount=15 + Name => 'ImageStabilization', + # (the other value is more reliable, so ignore this totally if the other exists) + Condition => 'not defined $$self{ImageStabilization}', + Writable => 'undef', + # if the first 4 bytes are non-zero, then bit 0x01 of byte 44 + # gives the stabilization mode + PrintConv => q{ + $val =~ /^\0{4}/ ? 'Off' : 'On, ' . + (unpack('x44C',$val) & 0x01 ? 'Mode 1' : 'Mode 2') + }, + }, + # 0x102a same as Subdir4-0x300 +); + +# AF information (ref PH) +%Image::ExifTool::Olympus::AFInfo = ( + PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData, + GROUPS => { 0 => 'MakerNotes', 2 => 'Camera' }, + FIRST_ENTRY => 0, + # 0x2a - int8u: ImagerAFMode? 0=Manual, 1=Auto + # 0x30 - int16u: AFAreaXPosition? + # 0x32 - int16u: AFAreaWidth? (202) + # 0x34 - int16u: AFAreaYPosition? + # 0x36 - int16u: AFAreaHeight? (50) + # (AF area positions above give the top-left coordinates of the AF area in the + # AF frame. Increasing Y is downwards, and the AF frame size is about 1280x256) +); + +# Olympus raw information tags (ref 6) +%Image::ExifTool::Olympus::RawInfo = ( + WRITE_PROC => \&Image::ExifTool::Exif::WriteExif, + CHECK_PROC => \&Image::ExifTool::Exif::CheckExif, + NOTES => 'These tags are found only in ORF images of some models (eg. C8080WZ).', + GROUPS => { 0 => 'MakerNotes', 2 => 'Camera' }, + 0x000 => { + Name => 'RawInfoVersion', + Writable => 'undef', + RawConv => '$val=~s/\0+$//; $val', # (may be null terminated) + Count => 4, + }, + 0x100 => { Name => 'WB_RBLevelsUsed', Writable => 'int16u', Count => 2 }, + 0x110 => { Name => 'WB_RBLevelsAuto', Writable => 'int16u', Count => 2 }, + 0x120 => { Name => 'WB_RBLevelsShade', Writable => 'int16u', Count => 2 }, + 0x121 => { Name => 'WB_RBLevelsCloudy', Writable => 'int16u', Count => 2 }, + 0x122 => { Name => 'WB_RBLevelsFineWeather', Writable => 'int16u', Count => 2 }, + 0x123 => { Name => 'WB_RBLevelsTungsten', Writable => 'int16u', Count => 2 }, + 0x124 => { Name => 'WB_RBLevelsEveningSunlight',Writable => 'int16u', Count => 2 }, + 0x130 => { Name => 'WB_RBLevelsDaylightFluor', Writable => 'int16u', Count => 2 }, + 0x131 => { Name => 'WB_RBLevelsDayWhiteFluor', Writable => 'int16u', Count => 2 }, + 0x132 => { Name => 'WB_RBLevelsCoolWhiteFluor', Writable => 'int16u', Count => 2 }, + 0x133 => { Name => 'WB_RBLevelsWhiteFluorescent',Writable => 'int16u', Count => 2 }, + 0x200 => { + Name => 'ColorMatrix2', + Format => 'int16s', + Writable => 'int16u', + Count => 9, + }, + # 0x240 => 'ColorMatrixDefault', ? + # 0x250 => 'ColorMatrixSaturation', ? + # 0x251 => 'ColorMatrixHue', ? + # 0x252 => 'ColorMatrixContrast', ? + # 0x300 => sharpness-related + # 0x301 => list of sharpness-related values + 0x310 => { Name => 'CoringFilter', Writable => 'int16u' }, + 0x311 => { Name => 'CoringValues', Writable => 'int16u', Count => 11 }, + 0x600 => { Name => 'BlackLevel2', Writable => 'int16u', Count => 4 }, + 0x601 => { + Name => 'YCbCrCoefficients', + Notes => 'stored as int16u[6], but extracted as rational32u[3]', + Format => 'rational32u', + }, + 0x611 => { Name => 'ValidPixelDepth', Writable => 'int16u', Count => 2 }, + 0x612 => { Name => 'CropLeft', Writable => 'int16u' }, #11 + 0x613 => { Name => 'CropTop', Writable => 'int16u' }, #11 + 0x614 => { Name => 'CropWidth', Writable => 'int32u' }, + 0x615 => { Name => 'CropHeight', Writable => 'int32u' }, + 0x1000 => { + Name => 'LightSource', + Writable => 'int16u', + PrintConv => { + 0 => 'Unknown', + 16 => 'Shade', + 17 => 'Cloudy', + 18 => 'Fine Weather', + 20 => 'Tungsten (Incandescent)', + 22 => 'Evening Sunlight', + 33 => 'Daylight Fluorescent', + 34 => 'Day White Fluorescent', + 35 => 'Cool White Fluorescent', + 36 => 'White Fluorescent', + 256 => 'One Touch White Balance', + 512 => 'Custom 1-4', + }, + }, + # the following 5 tags all have 3 values: val, min, max + 0x1001 => { Name => 'WhiteBalanceComp', Writable => 'int16s', Count => 3 }, + 0x1010 => { Name => 'SaturationSetting', Writable => 'int16s', Count => 3 }, + 0x1011 => { Name => 'HueSetting', Writable => 'int16s', Count => 3 }, + 0x1012 => { Name => 'ContrastSetting', Writable => 'int16s', Count => 3 }, + 0x1013 => { Name => 'SharpnessSetting', Writable => 'int16s', Count => 3 }, + # settings written by Camedia Master 4.x + 0x2000 => { Name => 'CMExposureCompensation', Writable => 'rational64s' }, + 0x2001 => { Name => 'CMWhiteBalance', Writable => 'int16u' }, + 0x2002 => { Name => 'CMWhiteBalanceComp', Writable => 'int16s' }, + 0x2010 => { Name => 'CMWhiteBalanceGrayPoint', Writable => 'int16u', Count => 3 }, + 0x2020 => { Name => 'CMSaturation', Writable => 'int16s', Count => 3 }, + 0x2021 => { Name => 'CMHue', Writable => 'int16s', Count => 3 }, + 0x2022 => { Name => 'CMContrast', Writable => 'int16s', Count => 3 }, + 0x2023 => { Name => 'CMSharpness', Writable => 'int16s', Count => 3 }, +); + +# Olympus unknown information tags +%Image::ExifTool::Olympus::UnknownInfo = ( + WRITE_PROC => \&Image::ExifTool::Exif::WriteExif, + CHECK_PROC => \&Image::ExifTool::Exif::CheckExif, + GROUPS => { 0 => 'MakerNotes', 2 => 'Camera' }, +); + +# Tags found only in some FE models +%Image::ExifTool::Olympus::FETags = ( + WRITE_PROC => \&Image::ExifTool::Exif::WriteExif, + CHECK_PROC => \&Image::ExifTool::Exif::CheckExif, + GROUPS => { 0 => 'MakerNotes', 2 => 'Camera' }, + NOTES => q{ + Some FE models write a large number of tags here, but most of this + information remains unknown. + }, + 0x0100 => { + Name => 'BodyFirmwareVersion', + Writable => 'string', + }, +); + +# tags in Olympus QuickTime videos (ref PH) +# (similar information in Kodak,Minolta,Nikon,Olympus,Pentax and Sanyo videos) +%Image::ExifTool::Olympus::MOV1 = ( + PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData, + GROUPS => { 0 => 'MakerNotes', 2 => 'Camera' }, + FIRST_ENTRY => 0, + NOTES => q{ + This information is found in MOV videos from Olympus models such as the + D540Z, D595Z, FE100, FE110, FE115, FE170 and FE200. + }, + 0x00 => { + Name => 'Make', + Format => 'string[24]', + }, + 0x18 => { + Name => 'Model', + Description => 'Camera Model Name', + Format => 'string[8]', + SeparateTable => 'CameraType', + PrintConv => \%olympusCameraTypes, + }, + # (01 00 at offset 0x20) + 0x26 => { + Name => 'ExposureUnknown', + Unknown => 1, + Format => 'int32u', + # this conversion doesn't work for all models (eg. gives "1/100000") + ValueConv => '$val ? 10 / $val : 0', + PrintConv => 'Image::ExifTool::Exif::PrintExposureTime($val)', + }, + 0x2a => { + Name => 'FNumber', + Format => 'rational64u', + PrintConv => 'sprintf("%.1f",$val)', + }, + 0x32 => { #(NC) + Name => 'ExposureCompensation', + Format => 'rational64s', + PrintConv => 'Image::ExifTool::Exif::PrintFraction($val)', + }, + # 0x44 => WhiteBalance ? + 0x48 => { + Name => 'FocalLength', + Format => 'rational64u', + PrintConv => 'sprintf("%.1f mm",$val)', + }, + # 0xb1 => 'ISO', #(I don't think this works - PH) +); + +# tags in Olympus QuickTime videos (ref PH) +# (similar information in Kodak,Minolta,Nikon,Olympus,Pentax and Sanyo videos) +%Image::ExifTool::Olympus::MOV2 = ( + PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData, + GROUPS => { 0 => 'MakerNotes', 2 => 'Camera' }, + FIRST_ENTRY => 0, + NOTES => q{ + This information is found in MOV videos from Olympus models such as the + FE120, FE140 and FE190. + }, + 0x00 => { + Name => 'Make', + Format => 'string[24]', + }, + 0x18 => { + Name => 'Model', + Description => 'Camera Model Name', + Format => 'string[24]', + Notes => 'the actual model name, no decoding necessary', + }, + # (01 00 at offset 0x30) + 0x36 => { + Name => 'ExposureTime', + Format => 'int32u', + ValueConv => '$val ? 10 / $val : 0', + PrintConv => 'Image::ExifTool::Exif::PrintExposureTime($val)', + }, + 0x3a => { + Name => 'FNumber', + Format => 'rational64u', + PrintConv => 'sprintf("%.1f",$val)', + }, + 0x42 => { #(NC) + Name => 'ExposureCompensation', + Format => 'rational64s', + PrintConv => 'Image::ExifTool::Exif::PrintFraction($val)', + }, + 0x58 => { + Name => 'FocalLength', + Format => 'rational64u', + PrintConv => 'sprintf("%.1f mm",$val)', + }, + 0xc1 => { + Name => 'ISO', + Format => 'int16u', + }, +); + +# tags in Olympus MP4 videos (ref PH) +%Image::ExifTool::Olympus::MP4 = ( + PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData, + GROUPS => { 0 => 'MakerNotes', 2 => 'Camera' }, + FIRST_ENTRY => 0, + NOTES => q{ + This information is found in MP4 videos from Olympus models such as the + u7040 and u9010. + }, + 0x00 => { + Name => 'Make', + Format => 'string[24]', + }, + 0x18 => { + Name => 'Model', + Description => 'Camera Model Name', + Format => 'string[24]', + Notes => 'oddly different than CameraType values in JPEG images by the same camera', + PrintConv => { + SG472 => 'u7040,S7040', + SG473 => 'u9010,S9010', + SG475 => 'SP800UZ', + SG551 => 'SZ-30MR', + SG553 => 'SP-610UZ', + SG554 => 'SZ-10', + SG555 => 'SZ-20', + SG573 => 'SZ-14', + SG575 => 'SP-620UZ', + }, + }, + 0x28 => { + Name => 'FNumber', + Format => 'rational64u', + PrintConv => 'sprintf("%.1f",$val)', + }, + 0x30 => { #(NC) + Name => 'ExposureCompensation', + Format => 'rational64s', + PrintConv => 'Image::ExifTool::Exif::PrintFraction($val)', + }, + # 0x38 - int32u: 3 + # 0x3c - int32u: 1 + # 0x40 - int16u: 5 + # 0x42 - int16u: 0,4,9 + # 0x64 - int32u: 0,6000,12000 + # 0x48 - int32u: 100 (ISO?) + 0x68 => { + Name => 'MovableInfo', + Condition => '$$valPt =~ /^DIGI/', + SubDirectory => { TagTable => 'Image::ExifTool::Olympus::MovableInfo' }, + }, + 0x72 => { + Name => 'MovableInfo', + Condition => '$$valPt =~ /^DIGI/', + SubDirectory => { TagTable => 'Image::ExifTool::Olympus::MovableInfo' }, + }, +); + +# yet a different QuickTime TAGS format (PH, E-M5) +%Image::ExifTool::Olympus::MOV3 = ( + GROUPS => { 0 => 'MakerNotes', 2 => 'Camera' }, + NOTES => 'QuickTime information found in the TAGS atom of MOV videos from the E-M5.', + OLYM => { + Name => 'OlympusAtom', + SubDirectory => { TagTable => 'Image::ExifTool::Olympus::OLYM2' }, + }, +); + +# yet a different QuickTime OLYM atom format (PH, E-M5) +%Image::ExifTool::Olympus::OLYM2 = ( + GROUPS => { 0 => 'MakerNotes', 2 => 'Camera' }, + prms => { + Name => 'MakerNotes', + SubDirectory => { TagTable => 'Image::ExifTool::Olympus::prms' }, + }, + thmb =>{ + Name => 'ThumbInfo', + SubDirectory => { TagTable => 'Image::ExifTool::Olympus::thmb2' }, + }, + scrn =>{ + Name => 'PreviewInfo', + SubDirectory => { TagTable => 'Image::ExifTool::Olympus::scrn2' }, + }, +); + +# the "prms" atom in E-M5 MOV videos (PH, E-M5) +%Image::ExifTool::Olympus::prms = ( + PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData, + GROUPS => { 0 => 'MakerNotes', 2 => 'Camera' }, + FIRST_ENTRY => 0, + NOTES => q{ + Information extracted from the "prms" atom in MOV videos from Olympus models + such as the OM E-M5. + }, + 0x12 => { + Name => 'Make', + Format => 'string[24]', + }, + 0x2c => { + Name => 'Model', + Description => 'Camera Model Name', + Format => 'string[24]', + SeparateTable => 'CameraType', + PrintConv => \%olympusCameraTypes, + }, + 0x83 => { + Name => 'DateTime1', + Format => 'string[24]', + Groups => { 2 => 'Time' }, + }, + 0x9d => { + Name => 'DateTime2', + Format => 'string[24]', + Groups => { 2 => 'Time' }, + }, +); + +# yet a different "thmb" atom format (PH, E-M5) +%Image::ExifTool::Olympus::thmb2 = ( + PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData, + GROUPS => { 0 => 'MakerNotes', 2 => 'Camera' }, + 0 => { + Name => 'ThumbnailWidth', + Format => 'int16u', + }, + 2 => { + Name => 'ThumbnailHeight', + Format => 'int16u', + }, + 4 => { + Name => 'ThumbnailLength', + Format => 'int32u', + }, + 8 => { + Name => 'ThumbnailImage', + Groups => { 2 => 'Preview' }, + Format => 'undef[$val{4}]', + Notes => '160x120 JPEG thumbnail image', + RawConv => '$self->ValidateImage(\$val,$tag)', + }, +); + +# yet a different "scrn" atom format (PH, E-M5) +%Image::ExifTool::Olympus::scrn2 = ( + PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData, + GROUPS => { 0 => 'MakerNotes', 2 => 'Camera' }, + # 0 => int16u: 1 - number of preview images? + 2 => { + Name => 'OlympusPreview', + SubDirectory => { TagTable => 'Image::ExifTool::Olympus::scrn' }, + }, +); + +# movable information found in MP4 videos +%Image::ExifTool::Olympus::MovableInfo = ( + PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData, + GROUPS => { 0 => 'MakerNotes', 2 => 'Camera' }, + FIRST_ENTRY => 0, + 0x04 => { #(NC) + Name => 'ISO', + Format => 'int32u', + }, + 0x2c => { + Name => 'EncoderVersion', + Format => 'string[16]', + }, + 0x3c => { + Name => 'DecoderVersion', + Format => 'string[16]', + }, + 0x83 => { + Name => 'Thumbnail', + SubDirectory => { + TagTable => 'Image::ExifTool::Olympus::Thumbnail', + Base => '$start', # (use a separate table because of this) + }, + }, +); + +# thumbnail image information found in MP4 videos (similar in Olympus,Samsung,Sanyo) (ref PH) +%Image::ExifTool::Olympus::Thumbnail = ( + PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData, + GROUPS => { 0 => 'MakerNotes', 2 => 'Camera' }, + FIRST_ENTRY => 0, + FORMAT => 'int32u', + 1 => 'ThumbnailWidth', + 2 => 'ThumbnailHeight', + 3 => 'ThumbnailLength', + 4 => { Name => 'ThumbnailOffset', IsOffset => 1 }, +); + +# thumbnail information found in 'thmb' atom of MP4 videos from the TG-810 (ref PH) +%Image::ExifTool::Olympus::thmb = ( + NOTES => 'Information extracted from the "thmb" atom of Olympus MP4 videos.', + PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData, + GROUPS => { 0 => 'MakerNotes', 2 => 'Camera' }, + 0 => { + Name => 'ThumbnailLength', + Format => 'int32u', + }, + 4 => { + Name => 'ThumbnailImage', + Groups => { 2 => 'Preview' }, + Format => 'undef[$val{0}]', + Notes => '160x120 JPEG thumbnail image', + RawConv => '$self->ValidateImage(\$val,$tag)', + }, +); + +# thumbnail information found in 'scrn' atom of MP4 videos from the TG-810 (ref PH) +%Image::ExifTool::Olympus::scrn = ( + NOTES => 'Information extracted from the "scrn" atom of Olympus MP4 videos.', + PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData, + GROUPS => { 0 => 'MakerNotes', 2 => 'Camera' }, + 0 => { + Name => 'PreviewImageLength', + Format => 'int32u', + }, + 4 => { + Name => 'PreviewImage', + Groups => { 2 => 'Preview' }, + Format => 'undef[$val{0}]', + Notes => '640x480 JPEG preview image', + RawConv => '$self->ValidateImage(\$val,$tag)', + }, +); + +# information in OLYM atom of MP4 videos from the TG-810 (ref PH) +%Image::ExifTool::Olympus::OLYM = ( + NOTES => 'Tags found in the OLYM atom of MP4 videos from the TG-810.', + PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData, + GROUPS => { 0 => 'MakerNotes', 2 => 'Camera' }, + 0x0e => { + Name => 'Make', + Format => 'string[26]', + }, + 0x28 => { + Name => 'Model', + Description => 'Camera Model Name', + Format => 'string[24]', + SeparateTable => 'CameraType', + PrintConv => \%olympusCameraTypes, + }, + 0x5a => { + Name => 'FNumber', + Format => 'rational64u', + PrintConv => 'sprintf("%.1f",$val)', + }, + 0x7f => { + Name => 'DateTimeOriginal', #(NC) + Format => 'string[24]', + Groups => { 2 => 'Time' }, + PrintConv => '$self->ConvertDateTime($val)', + }, + 0x99 => { + Name => 'DateTime2', + Format => 'string[24]', + Groups => { 2 => 'Time' }, + }, + 0x109 => { + Name => 'ThumbnailWidth', + Format => 'int16u', + }, + 0x10b => { + Name => 'ThumbnailHeight', + Format => 'int16u', + }, +); + +# tags in Olympus AVI videos (ref PH) +# (very similar to Pentax::Junk2 tags) +%Image::ExifTool::Olympus::AVI = ( + PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData, + GROUPS => { 0 => 'MakerNotes', 2 => 'Camera' }, + FIRST_ENTRY => 0, + NOTES => 'This information is found in Olympus AVI videos.', + 0x12 => { + Name => 'Make', + Format => 'string[24]', + }, + 0x2c => { + Name => 'Model', + Description => 'Camera Model Name', + Format => 'string[24]', + SeparateTable => 'CameraType', + PrintConv => \%olympusCameraTypes, + }, + 0x5e => { + Name => 'FNumber', + Format => 'rational64u', + PrintConv => 'sprintf("%.1f",$val)', + }, + 0x83 => { + Name => 'DateTime1', + Format => 'string[24]', + Groups => { 2 => 'Time' }, + }, + 0x9d => { + Name => 'DateTime2', + Format => 'string[24]', + Groups => { 2 => 'Time' }, + }, + 0x129 => { + Name => 'ThumbInfo', + SubDirectory => { TagTable => 'Image::ExifTool::Olympus::thmb2' }, + }, +); + +# tags in WAV files from Olympus PCM linear recorders (ref 18) +%Image::ExifTool::Olympus::WAV = ( + PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData, + GROUPS => { 0 => 'MakerNotes', 2 => 'Audio' }, + FIRST_ENTRY => 0, + NOTES => q{ + This information is found in WAV files from Olympus PCM linear recorders + like the LS-5, LS-10, LS-11. + }, + 0x0c => { + Name => 'Model', + Description => 'Camera Model Name', + Format => 'string[16]', + }, + 0x1c => { + Name => 'FileNumber', + Format => 'int32u', + PrintConv => 'sprintf("%.4d", $val)', + }, + 0x26 => { + Name => 'DateTimeOriginal', + Description => 'Date/Time Original', + Groups => { 2 => 'Time' }, + Format => 'undef[12]', + Notes => 'time at start of recording', + ValueConv => q{ + return undef unless $val =~ /^(\d{2})(\d{2})(\d{2})(\d{2})(\d{2})(\d{2})$/; + my $y = $1 < 70 ? "20$1" : "19$1"; + return "$y:$2:$3 $4:$5:$6"; + }, + PrintConv => '$self->ConvertDateTime($val)', + }, + 0x32 => { + Name => 'DateTimeEnd', + Groups => { 2 => 'Time' }, + Format => 'undef[12]', + Notes => 'time at end of recording', + ValueConv => q{ + return undef unless $val =~ /^(\d{2})(\d{2})(\d{2})(\d{2})(\d{2})(\d{2})$/; + my $y = $1 < 70 ? "20$1" : "19$1"; + return "$y:$2:$3 $4:$5:$6"; + }, + PrintConv => '$self->ConvertDateTime($val)', + }, + 0x3e => { + Name => 'RecordingTime', + Format => 'undef[6]', + ValueConv => '$val =~ s/^(\d{2})(\d{2})/$1:$2:/; $val', + }, + 0x200 => { + Name => 'Duration', + Format => 'int32u', + ValueConv => '$val / 1000', + PrintConv => 'ConvertDuration($val)', + }, + 0x20a => { Name => 'Index01', %indexInfo }, + 0x214 => { Name => 'Index02', %indexInfo }, + 0x21e => { Name => 'Index03', %indexInfo }, + 0x228 => { Name => 'Index04', %indexInfo }, + 0x232 => { Name => 'Index05', %indexInfo }, + 0x23c => { Name => 'Index06', %indexInfo }, + 0x246 => { Name => 'Index07', %indexInfo }, + 0x250 => { Name => 'Index08', %indexInfo }, + 0x25a => { Name => 'Index09', %indexInfo }, + 0x264 => { Name => 'Index10', %indexInfo }, + 0x26e => { Name => 'Index11', %indexInfo }, + 0x278 => { Name => 'Index12', %indexInfo }, + 0x282 => { Name => 'Index13', %indexInfo }, + 0x28c => { Name => 'Index14', %indexInfo }, + 0x296 => { Name => 'Index15', %indexInfo }, + 0x2a0 => { Name => 'Index16', %indexInfo }, +); + +# DSS information written by Olympus voice recorders (ref PH) +%Image::ExifTool::Olympus::DSS = ( + PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData, + GROUPS => { 0 => 'MakerNotes', 2 => 'Audio' }, + FIRST_ENTRY => 0, + NOTES => q{ + Information extracted from DSS/DS2 files and the ID3 XOLY frame of MP3 files + written by some Olympus voice recorders. + }, + # 0 - file format: + # "\x02dss"(DSS file and XOLY frame in MP3 file) + # "\x03ds2"(DS2 file) + # "\x03mp3"(ID3 XOLY frame in MP3 file) + 12 => { Name => 'Model', Format => 'string[16]' }, # (name truncated by some models) + 38 => { + Name => 'StartTime', + Format => 'string[12]', + Groups => { 2 => 'Time' }, + ValueConv => '$val =~ s/(\d{2})(\d{2})(\d{2})(\d{2})(\d{2})(\d{2})/20$1:$2:$3 $4:$5:$6/; $val', + PrintConv => '$self->ConvertDateTime($val)', + }, + 50 => { + Name => 'EndTime', + Format => 'string[12]', + Groups => { 2 => 'Time' }, + ValueConv => '$val =~ s/(\d{2})(\d{2})(\d{2})(\d{2})(\d{2})(\d{2})/20$1:$2:$3 $4:$5:$6/; $val', + PrintConv => '$self->ConvertDateTime($val)', + }, + 62 => { + Name => 'Duration', + Format => 'string[6]', + ValueConv => '$val =~ /(\d{2})(\d{2})(\d{2})/ ? ($1 * 60 + $2) * 60 + $3 : undef', + PrintConv => 'ConvertDuration($val)', + }, + 798 => { # (ref http://search.cpan.org/~rgibson/Audio-DSS-0.02/) + Name => 'Comment', + Format => 'string[100]', + }, +); + +# Olympus composite tags +%Image::ExifTool::Olympus::Composite = ( + GROUPS => { 2 => 'Camera' }, + ExtenderStatus => { + Notes => q{ + Olympus cameras have the quirk that they may retain the extender settings + after the extender is removed until the camera is powered off. This tag is + an attempt to represent the actual status of the extender. + }, + Require => { + 0 => 'Olympus:Extender', + 1 => 'Olympus:LensType', + 2 => 'MaxApertureValue', + }, + ValueConv => 'Image::ExifTool::Olympus::ExtenderStatus($val[0],$prt[1],$val[2])', + PrintConv => { + 0 => 'Not attached', + 1 => 'Attached', + 2 => 'Removed', + }, + }, + ZoomedPreviewImage => { + Groups => { 2 => 'Preview' }, + Require => { + 0 => 'ZoomedPreviewStart', + 1 => 'ZoomedPreviewLength', + }, + RawConv => q{ + @grps = $self->GetGroup($$val{0}); # set groups from input tag + Image::ExifTool::Exif::ExtractImage($self,$val[0],$val[1],"ZoomedPreviewImage"); + }, + }, +); + +# add our composite tags +Image::ExifTool::AddCompositeTags('Image::ExifTool::Olympus'); + + +#------------------------------------------------------------------------------ +# Determine if the extender (EX-25/EC-14) was really attached (ref 9) +# Inputs: 0) Extender, 1) LensType string, 2) MaxApertureAtMaxFocal +# Returns: 0=not attached, 1=attached, 2=could have been removed +# Notes: Olympus has a bug in the in-camera firmware which results in the +# extender information being cached and written into the EXIF data even after +# the extender has been removed. You must power cycle the camera to prevent it +# from writing the cached extender information into the EXIF data. +sub ExtenderStatus($$$) +{ + my ($extender, $lensType, $maxAperture) = @_; + my @info = split ' ', $extender; + # validate that extender identifier is reasonable + return 0 unless @info >= 2 and hex($info[1]); + # if it's not an EC-14 (id '0 04') then assume it was really attached + # (other extenders don't seem to affect the reported max aperture) + return 1 if "$info[0] $info[1]" ne '0 04'; + # get the maximum aperture for this lens (in $1) + $lensType =~ / F(\d+(\.\d+)?)/ or return 1; + # If the maximum aperture at the maximum focal length is greater than the + # known max/max aperture of the lens, then the extender must be attached + return ($maxAperture - $1 > 0.2) ? 1 : 2; +} + +#------------------------------------------------------------------------------ +# Print AF points +# Inputs: 0) AF point data (string of integers) +# Notes: I'm just guessing that the 2nd and 4th bytes are the Y coordinates, +# and that more AF points will show up in the future (derived from E-1 images, +# and the E-1 uses just one of 3 possible AF points, all centered in Y) - PH +sub PrintAFAreas($) +{ + my $val = shift; + my @points = split ' ', $val; + my %afPointNames = ( + 0x36794285 => 'Left', + 0x79798585 => 'Center', + 0xBD79C985 => 'Right', + ); + $val = ''; + my $pt; + foreach $pt (@points) { + next unless $pt; + $val and $val .= ', '; + $afPointNames{$pt} and $val .= $afPointNames{$pt} . ' '; + my @coords = unpack('C4',pack('N',$pt)); + $val .= "($coords[0],$coords[1])-($coords[2],$coords[3])"; + } + $val or $val = 'none'; + return $val; +} + +#------------------------------------------------------------------------------ +# Extract information from a DSS/DS2 voice recorder audio file or ID3 XOLY frame +# Inputs: 0) ExifTool object reference, 1) dirInfo reference +# Returns: 1 on success +sub ProcessDSS($$;$) +{ + my ($et, $dirInfo) = @_; + + # allow this to be called with either RAF or DataPt + my $raf = $$dirInfo{RAF}; + if ($raf) { + my $buff; + $raf->Read($buff, 898) > 68 or return 0; + $buff =~ /^(\x02dss|\x03ds2)/ or return 0; + $dirInfo = { DataPt => \$buff }; + $et->SetFileType(uc substr $buff, 1, 3); + } + my $tagTablePtr = GetTagTable('Image::ExifTool::Olympus::DSS'); + return $et->ProcessBinaryData($dirInfo, $tagTablePtr); +} + +#------------------------------------------------------------------------------ +# Process ORF file +# Inputs: 0) ExifTool object reference, 1) directory information reference +# Returns: 1 if this looked like a valid ORF file, 0 otherwise +sub ProcessORF($$) +{ + my ($et, $dirInfo) = @_; + return $et->ProcessTIFF($dirInfo); +} + +1; # end + +__END__ + +=head1 NAME + +Image::ExifTool::Olympus - Olympus/Epson maker notes tags + +=head1 SYNOPSIS + +This module is loaded automatically by Image::ExifTool when required. + +=head1 DESCRIPTION + +This module contains definitions required by Image::ExifTool to interpret +Olympus or Epson maker notes in EXIF information. + +=head1 AUTHOR + +Copyright 2003-2019, Phil Harvey (phil at owl.phy.queensu.ca) + +This library is free software; you can redistribute it and/or modify it +under the same terms as Perl itself. + +=head1 REFERENCES + +=over 4 + +=item L<http://park2.wakwak.com/~tsuruzoh/Computer/Digicams/exif-e.html> + +=item L<http://www.cybercom.net/~dcoffin/dcraw/> + +=item L<http://www.ozhiker.com/electronics/pjmt/jpeg_info/olympus_mn.html> + +=item L<http://olypedia.de/Olympus_Makernotes> + +=back + +=head1 ACKNOWLEDGEMENTS + +Thanks to Markku Hanninen, Remi Guyomarch, Frank Ledwon, Michael Meissner, +Mark Dapoz, Ioannis Panagiotopoulos and Tomasz Kawecki for their help +figuring out some Olympus tags, and Lilo Huang, Chris Shaw and Viktor +Lushnikov for adding to the LensType list. + +=head1 SEE ALSO + +L<Image::ExifTool::TagNames/Olympus Tags>, +L<Image::ExifTool(3pm)|Image::ExifTool> + +=cut diff --git a/lib/Image/ExifTool/OpenEXR.pm b/lib/Image/ExifTool/OpenEXR.pm new file mode 100644 index 0000000..3f85a4c --- /dev/null +++ b/lib/Image/ExifTool/OpenEXR.pm @@ -0,0 +1,323 @@ +#------------------------------------------------------------------------------ +# File: OpenEXR.pm +# +# Description: Read OpenEXR meta information +# +# Revisions: 2011/12/10 - P. Harvey Created +# +# References: 1) http://www.openexr.com/ +#------------------------------------------------------------------------------ + +package Image::ExifTool::OpenEXR; + +use strict; +use vars qw($VERSION); +use Image::ExifTool qw(:DataAccess :Utils); +use Image::ExifTool::GPS; + +$VERSION = '1.02'; + +# supported EXR value format types (other types are extracted as undef binary data) +my %formatType = ( + box2f => 'float[4]', + box2i => 'int32s[4]', + chlist => 1, + chromaticities => 'float[8]', + compression => 'int8u', + double => 'double', + envmap => 'int8u', + float => 'float', + 'int' => 'int32s', + keycode => 'int32s[7]', + lineOrder => 'int8u', + m33f => 'float[9]', + m44f => 'float[16]', + rational => 'rational64s', + string => 'string', # incorrect in specification! (no leading int) + stringvector => 1, + tiledesc => 1, + timecode => 'int32u[2]', + v2f => 'float[2]', + v2i => 'int32s[2]', + v3f => 'float[3]', + v3i => 'int32s[3]', +); + +# OpenEXR tags +%Image::ExifTool::OpenEXR::Main = ( + GROUPS => { 2 => 'Image' }, + NOTES => q{ + Information extracted from EXR images. See L<http://www.openexr.com/> for + the official specification. + }, + _ver => { Name => 'EXRVersion' }, + _lay => { + Name => 'Layout', + PrintHex => 1, + PrintConv => { 0 => 'Scan Lines', 0x200 => 'Tiles' }, + }, + adoptedNeutral => { }, + altitude => { + Name => 'GPSAltitude', + Groups => { 2 => 'Location' }, + PrintConv => q{ + $val = int($val * 10) / 10; + return ($val =~ s/^-// ? "$val m Below" : "$val m Above") . " Sea Level"; + }, + }, + aperture => { PrintConv => 'sprintf("%.1f",$val)' }, + channels => { }, + chromaticities => { }, + capDate => { + Name => 'DateTimeOriginal', + Groups => { 2 => 'Time' }, + PrintConv => '$self->ConvertDateTime($val)', + }, + comments => { }, + compression => { + PrintConvColumns => 2, + PrintConv => { + 0 => 'None', + 1 => 'RLE', + 2 => 'ZIPS', + 3 => 'ZIP', + 4 => 'PIZ', + 5 => 'PXR24', + 6 => 'B44', + 7 => 'B44A', + }, + }, + dataWindow => { }, + displayWindow => { }, + envmap => { + Name => 'EnvironmentMap', + PrintConv => { + 0 => 'Latitude/Longitude', + 1 => 'Cube', + }, + }, + expTime => { + Name => 'ExposureTime', + PrintConv => 'Image::ExifTool::Exif::PrintExposureTime($val)', + }, + focus => { + Name => 'FocusDistance', + PrintConv => '"$val m"', + }, + framesPerSecond => { }, + keyCode => { }, + isoSpeed => { Name => 'ISO' }, + latitude => { + Name => 'GPSLatitude', + Groups => { 2 => 'Location' }, + PrintConv => 'Image::ExifTool::GPS::ToDMS($self, $val, 1, "N")', + }, + lineOrder => { + PrintConv => { + 0 => 'Increasing Y', + 1 => 'Decreasing Y', + 2 => 'Random Y', + }, + }, + longitude => { + Name => 'GPSLongitude', + Groups => { 2 => 'Location' }, + PrintConv => 'Image::ExifTool::GPS::ToDMS($self, $val, 1, "E")', + }, + lookModTransform => { }, + multiView => { }, + owner => { Groups => { 2 => 'Author' } }, + pixelAspectRatio => { }, + preview => { }, + renderingTransform => { }, + screenWindowCenter => { }, + screenWindowWidth => { }, + tiles => { }, + timeCode => { }, + utcOffset => { + Name => 'TimeZone', + Groups => { 2 => 'Time' }, + PrintConv => 'TimeZoneString($val / 60)', + }, + whiteLuminance => { }, + worldToCamera => { }, + worldToNDC => { }, + wrapmodes => { Name => 'WrapModes' }, + xDensity => { Name => 'XResolution' }, + # also observed: + # ilut +); + +#------------------------------------------------------------------------------ +# Extract information from an OpenEXR file +# Inputs: 0) ExifTool object reference, 1) DirInfo reference +# Returns: 1 on success, 0 if this wasn't a valid OpenEXR file +sub ProcessEXR($$) +{ + my ($et, $dirInfo) = @_; + my $raf = $$dirInfo{RAF}; + my $verbose = $et->Options('Verbose'); + my $binary = $et->Options('Binary') || $verbose; + my ($buff, $buf2, $dim); + + # verify this is a valid RIFF file + return 0 unless $raf->Read($buff, 8) == 8; + return 0 unless $buff =~ /^\x76\x2f\x31\x01/s; + $et->SetFileType(); + SetByteOrder('II'); + my $tagTablePtr = GetTagTable('Image::ExifTool::OpenEXR::Main'); + + # extract information from header + my $ver = unpack('x4V', $buff); + $et->HandleTag($tagTablePtr, '_ver', $ver & 0xff); + $et->HandleTag($tagTablePtr, '_lay', $ver & 0x200); + + # extract attributes + for (;;) { + $raf->Read($buff, 68) or last; + last if $buff =~ /^\0/; + unless ($buff =~ /^([^\0]{1,31})\0([^\0]{1,31})\0(.{4})/sg) { + $et->Warn('EXR format error'); + last; + } + my ($tag, $type, $size) = ($1, $2, unpack('V', $3)); + unless ($raf->Seek(pos($buff) - length($buff), 1)) { + $et->Warn('Seek error'); + last; + } + my $tagInfo = $et->GetTagInfo($tagTablePtr, $tag); + unless ($tagInfo) { + my $name = ucfirst $tag; + $name =~ tr/-_a-zA-Z0-9//dc; + if (length $name <= 1) { + if (length $name) { + $name = "Tag$name"; + } else { + $name = 'Invalid'; + } + } + $tagInfo = { Name => $name, WasAdded => 1 }; + AddTagToTable($tagTablePtr, $tag, $tagInfo); + $et->VPrint(0, $$et{INDENT}, "[adding $tag]\n"); + } + my ($val, $success); + my $format = $formatType{$type}; + if ($format or $binary) { + $raf->Read($buff, $size) == $size and $success = 1; + if (not $format) { + $val = \$buff; # treat as undef binary data + } elsif ($format ne '1') { + # handle formats which map nicely into ExifTool format codes + if ($format =~ /^(\w+)\[?(\d*)/) { + my ($fmt, $cnt) = ($1, $2); + $cnt = $fmt eq 'string' ? $size : 1 unless $cnt; + $val = ReadValue(\$buff, 0, $fmt, $cnt, $size); + } + # handle other format types + } elsif ($type eq 'tiledesc') { + if ($size >= 9) { + my $x = Get32u(\$buff, 0); + my $y = Get32u(\$buff, 4); + my $mode = Get8u(\$buff, 8); + my $lvl = { 0 => 'One Level', 1 => 'MIMAP Levels', 2 => 'RIPMAP Levels' }->{$mode & 0x0f}; + $lvl or $lvl = 'Unknown Levels (' . ($mode & 0xf) . ')'; + my $rnd = { 0 => 'Round Down', 1 => 'Round Up' }->{$mode >> 4}; + $rnd or $rnd = 'Unknown Rounding (' . ($mode >> 4) . ')'; + $val = "${x}x$y; $lvl; $rnd"; + } + } elsif ($type eq 'chlist') { + $val = [ ]; + while ($buff =~ /\G([^\0]{1,31})\0(.{16})/sg) { + my ($str, $dat) = ($1, $2); + my ($pix,$lin,$x,$y) = unpack('VCx3VV', $dat); + $pix = { 0 => 'int8u', 1 => 'half', 2 => 'float' }->{$pix} || "unknown($pix)"; + push @$val, "$str $pix" . ($lin ? ' linear' : '') . " $x $y"; + } + } elsif ($type eq 'stringvector') { + $val = [ ]; + my $pos = 0; + while ($pos + 4 <= length($buff)) { + my $len = Get32u(\$buff, $pos); + last if $pos + 4 + $len > length($buff); + push @$val, substr($buff, $pos + 4, $len); + $pos += 4 + $len; + } + } else { + $val = \$buff; # (shouldn't happen) + } + } else { + # avoid loading binary data + $val = \ "Binary data $size bytes"; + $success = $raf->Seek($size, 1); + } + unless ($success) { + $et->Warn('Truncated or corrupted EXR file'); + last; + } + $val = '<bad>' unless defined $val; + + # take image dimensions from dataWindow (with displayWindow as backup) + if (($tag eq 'dataWindow' or (not $dim and $tag eq 'displayWindow')) and + $val =~ /^(-?\d+) (-?\d+) (-?\d+) (-?\d+)$/) + { + $dim = [$3 - $1 + 1, $4 - $2 + 1]; + } + if ($verbose) { + my $dataPt = ref $val ? $val : \$val, + $et->VerboseInfo($tag, $tagInfo, + Table => $tagTablePtr, + Value => $val, + Size => $size, + Format => $type, + DataPt => \$buff, + Addr => $raf->Tell() - $size, + ); + } + $et->FoundTag($tagInfo, $val); + } + if ($dim) { + $et->FoundTag('ImageWidth', $$dim[0]); + $et->FoundTag('ImageHeight', $$dim[1]); + } + return 1; +} + +1; # end + +__END__ + +=head1 NAME + +Image::ExifTool::OpenEXR - Read OpenEXR meta information + +=head1 SYNOPSIS + +This module is used by Image::ExifTool + +=head1 DESCRIPTION + +This module contains definitions required by Image::ExifTool to extract meta +information from OpenEXR images. + +=head1 AUTHOR + +Copyright 2003-2019, Phil Harvey (phil at owl.phy.queensu.ca) + +This library is free software; you can redistribute it and/or modify it +under the same terms as Perl itself. + +=head1 REFERENCES + +=over 4 + +=item L<http://www.openexr.com/documentation.html> + +=back + +=head1 SEE ALSO + +L<Image::ExifTool::TagNames/OpenEXR Tags>, +L<Image::ExifTool(3pm)|Image::ExifTool> + +=cut + diff --git a/lib/Image/ExifTool/Opus.pm b/lib/Image/ExifTool/Opus.pm new file mode 100644 index 0000000..7b9ea4f --- /dev/null +++ b/lib/Image/ExifTool/Opus.pm @@ -0,0 +1,98 @@ +#------------------------------------------------------------------------------ +# File: Opus.pm +# +# Description: Read Ogg Opus audio meta information +# +# Revisions: 2016/07/14 - P. Harvey Created +# +# References: 1) https://www.opus-codec.org/docs/ +# 2) https://wiki.xiph.org/OggOpus +# 3) https://tools.ietf.org/pdf/rfc7845.pdf +#------------------------------------------------------------------------------ + +package Image::ExifTool::Opus; + +use strict; +use vars qw($VERSION); + +$VERSION = '1.00'; + +# Opus metadata types +%Image::ExifTool::Opus::Main = ( + NOTES => q{ + Information extracted from Ogg Opus files. See + L<https://www.opus-codec.org/docs/> for the specification. + }, + 'OpusHead' => { + Name => 'Header', + SubDirectory => { TagTable => 'Image::ExifTool::Opus::Header' }, + }, + 'OpusTags' => { + Name => 'Comments', + SubDirectory => { TagTable => 'Image::ExifTool::Vorbis::Comments' }, + }, +); + +%Image::ExifTool::Opus::Header = ( + PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData, + GROUPS => { 2 => 'Audio' }, + 0 => 'OpusVersion', + 1 => 'AudioChannels', + # 2 => 'PreSkip' (int16u) + 4 => { + Name => 'SampleRate', + Format => 'int32u', + }, + 8 => { + Name => 'OutputGain', + Format => 'int16u', + ValueConv => '10 ** ($val/5120)', + }, +); + +1; # end + +__END__ + +=head1 NAME + +Image::ExifTool::Opus - Read Ogg Opus audio meta information + +=head1 SYNOPSIS + +This module is used by Image::ExifTool + +=head1 DESCRIPTION + +This module contains definitions required by Image::ExifTool to extract meta +information from Ogg Opus audio files. + +=head1 AUTHOR + +Copyright 2003-2019, Phil Harvey (phil at owl.phy.queensu.ca) + +This library is free software; you can redistribute it and/or modify it +under the same terms as Perl itself. + +=head1 REFERENCES + +=over 4 + +=item L<https://www.opus-codec.org/docs/> + +=item L<https://wiki.xiph.org/OggOpus> + +=item L<https://tools.ietf.org/pdf/rfc7845.pdf> + +=back + +=head1 SEE ALSO + +L<Image::ExifTool::TagNames/Opus Tags>, +L<Image::ExifTool::TagNames/Ogg Tags>, +L<Image::ExifTool::TagNames/Vorbis Tags>, +L<Image::ExifTool::TagNames/FLAC Tags>, +L<Image::ExifTool(3pm)|Image::ExifTool> + +=cut + diff --git a/lib/Image/ExifTool/PCX.pm b/lib/Image/ExifTool/PCX.pm new file mode 100644 index 0000000..96b2575 --- /dev/null +++ b/lib/Image/ExifTool/PCX.pm @@ -0,0 +1,138 @@ +#------------------------------------------------------------------------------ +# File: PCX.pm +# +# Description: Read metadata from PC Paintbrush files +# +# Revisions: 2018/12/12 - P. Harvey Created +# +# References: 1) http://qzx.com/pc-gpe/pcx.txt +# 2) https://www.fileformat.info/format/pcx/corion.htm +#------------------------------------------------------------------------------ + +package Image::ExifTool::PCX; + +use strict; +use vars qw($VERSION); +use Image::ExifTool qw(:DataAccess :Utils); + +$VERSION = '1.00'; + +# PCX info +%Image::ExifTool::PCX::Main = ( + PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData, + GROUPS => { 0 => 'File', 1 => 'File', 2 => 'Image' }, + NOTES => 'Tags extracted from PC Paintbrush images.', + DATAMEMBER => [ 0x04, 0x05 ], + 0x00 => { + Name => 'Manufacturer', + PrintConv => { 10 => 'ZSoft' }, + }, + 0x01 => { + Name => 'Software', + PrintConv => { + 0 => 'PC Paintbrush 2.5', + 2 => 'PC Paintbrush 2.8 (with palette)', + 3 => 'PC Paintbrush 2.8 (without palette)', + 4 => 'PC Paintbrush for Windows', + 5 => 'PC Paintbrush 3.0+', + }, + }, + 0x02 => { Name => 'Encoding', PrintConv => { 1 => 'RLE' } }, + 0x03 => 'BitsPerPixel', + 0x04 => { + Name => 'LeftMargin', + Format => 'int16u', + RawConv => '$$self{LeftMargin} = $val', + }, + 0x06 => { + Name => 'TopMargin', + Format => 'int16u', + RawConv => '$$self{TopMargin} = $val', + }, + 0x08 => { + Name => 'ImageWidth', + Format => 'int16u', + Notes => 'adjusted for LeftMargin', + ValueConv => '$val - $$self{LeftMargin} + 1', + }, + 0x0a => { + Name => 'ImageHeight', + Format => 'int16u', + Notes => 'adjusted for TopMargin', + ValueConv => '$val - $$self{TopMargin} + 1', + }, + 0x0c => 'XResolution', + 0x0e => 'YResolution', + 0x41 => 'ColorPlanes', + 0x42 => { Name => 'BytesPerLine', Format => 'int16u' }, + 0x44 => { + Name => 'ColorMode', + PrintConv => { + 0 => 'n/a', + 1 => 'Color Palette', + 2 => 'Grayscale', + }, + }, + 0x46 => { Name => 'ScreenWidth', Format => 'int16u', RawConv => '$val or undef' }, + 0x48 => { Name => 'ScreenHeight', Format => 'int16u', RawConv => '$val or undef' }, +); + +#------------------------------------------------------------------------------ +# Extract information from a PCX image +# Inputs: 0) ExifTool object reference, 1) dirInfo reference +# Returns: 1 on success, 0 if this wasn't a valid PCX file +sub ProcessPCX($$) +{ + my ($et, $dirInfo) = @_; + my $raf = $$dirInfo{RAF}; + my $buff; + return 0 unless $raf->Read($buff, 0x50) == 0x50 and + $buff =~ /^\x0a[\0-\x05]\x01[\x01\x02\x04\x08].{64}[\0-\x02]/s; + SetByteOrder('II'); + $et->SetFileType(); + my %dirInfo = ( DirName => 'PCX', DataPt => \$buff ); + my $tagTablePtr = GetTagTable('Image::ExifTool::PCX::Main'); + return $et->ProcessBinaryData(\%dirInfo, $tagTablePtr); +} + +1; # end + +__END__ + +=head1 NAME + +Image::ExifTool::PCX - Read metadata from PC Paintbrush files + +=head1 SYNOPSIS + +This module is used by Image::ExifTool + +=head1 DESCRIPTION + +This module contains routines required by Image::ExifTool to extract +information from PC Paintbrush (PCX) files. + +=head1 AUTHOR + +Copyright 2003-2019, Phil Harvey (phil at owl.phy.queensu.ca) + +This library is free software; you can redistribute it and/or modify it +under the same terms as Perl itself. + +=head1 REFERENCES + +=over 4 + +=item L<http://qzx.com/pc-gpe/pcx.txt> + +=item L<https://www.fileformat.info/format/pcx/corion.htm> + +=back + +=head1 SEE ALSO + +L<Image::ExifTool::TagNames/PCX Tags>, +L<Image::ExifTool(3pm)|Image::ExifTool> + +=cut + diff --git a/lib/Image/ExifTool/PDF.pm b/lib/Image/ExifTool/PDF.pm new file mode 100644 index 0000000..962c3dc --- /dev/null +++ b/lib/Image/ExifTool/PDF.pm @@ -0,0 +1,2380 @@ +#------------------------------------------------------------------------------ +# File: PDF.pm +# +# Description: Read PDF meta information +# +# Revisions: 07/11/2005 - P. Harvey Created +# 07/25/2005 - P. Harvey Add support for encrypted documents +# +# References: 1) http://www.adobe.com/devnet/pdf/pdf_reference.html +# 2) http://search.cpan.org/dist/Crypt-RC4/ +# 3) http://www.adobe.com/devnet/acrobat/pdfs/PDF32000_2008.pdf +# 4) http://www.adobe.com/content/dam/Adobe/en/devnet/pdf/pdfs/adobe_supplement_iso32000.pdf +# 5) http://tools.ietf.org/search/rfc3454 +# 6) http://www.armware.dk/RFC/rfc/rfc4013.html +#------------------------------------------------------------------------------ + +package Image::ExifTool::PDF; + +use strict; +use vars qw($VERSION $AUTOLOAD $lastFetched); +use Image::ExifTool qw(:DataAccess :Utils); +require Exporter; + +$VERSION = '1.47'; + +sub FetchObject($$$$); +sub ExtractObject($$;$$); +sub ReadToNested($;$); +sub ProcessDict($$$$;$$); +sub ProcessAcroForm($$$$;$$); +sub ExpandArray($); +sub ReadPDFValue($); +sub CheckPDF($$$); + +# $lastFetched - last fetched object reference (used for decryption) +# (undefined if fetched object was already decrypted, eg. object from stream) + +my $cryptInfo; # encryption object reference (plus additional information) +my $cryptString; # flag that strings are encrypted +my $cryptStream; # flag that streams are encrypted +my $lastOffset; # last fetched object offset +my %streamObjs; # hash of stream objects +my %fetched; # dicts fetched in verbose mode (to avoid cyclical recursion) +my $pdfVer; # version of PDF file being processed + +# filters supported in DecodeStream() +my %supportedFilter = ( + '/FlateDecode' => 1, + '/Crypt' => 1, + '/Identity' => 1, # (not filtered) + '/DCTDecode' => 1, # (JPEG image - not filtered) + '/JPXDecode' => 1, # (Jpeg2000 image - not filtered) + '/LZWDecode' => 1, # (usually a bitmapped image) + '/ASCIIHexDecode' => 1, + '/ASCII85Decode' => 1, + # other standard filters that we currently don't support + #'/JBIG2Decode' => 0, # (JBIG2 image format not supported) + #'/CCITTFaxDecode' => 0, + #'/RunLengthDecode' => 0, +); + +# tags in main PDF directories +%Image::ExifTool::PDF::Main = ( + GROUPS => { 2 => 'Document' }, + VARS => { CAPTURE => ['Main','Prev'] }, + Info => { + SubDirectory => { TagTable => 'Image::ExifTool::PDF::Info' }, + # Adobe Acrobat 10.1.5 will create a duplicate Info dictionary with + # a different object number when metadata is edited. This flag + # is part of a patch to ignore this duplicate information (unless + # the IgnoreMinorErrors option is used) + IgnoreDuplicates => 1, + }, + Root => { + SubDirectory => { TagTable => 'Image::ExifTool::PDF::Root' }, + }, + Encrypt => { + NoProcess => 1, # don't process normally (processed in advance) + SubDirectory => { TagTable => 'Image::ExifTool::PDF::Encrypt' }, + }, + _linearized => { + Name => 'Linearized', + Notes => 'flag set if document is linearized for fast web display; not a real Tag ID', + PrintConv => { 'true' => 'Yes', 'false' => 'No' }, + }, +); + +# tags in PDF Info dictionary +%Image::ExifTool::PDF::Info = ( + GROUPS => { 2 => 'Document' }, + VARS => { CAPTURE => ['Info'] }, + EXTRACT_UNKNOWN => 1, # extract all unknown tags in this directory + WRITE_PROC => \&Image::ExifTool::DummyWriteProc, + CHECK_PROC => \&CheckPDF, + WRITABLE => 'string', + # set PRIORITY to 0 so most recent Info dictionary takes precedence + # (Acrobat Pro bug? doesn't use same object/generation number for + # new Info dictionary when doing incrmental update) + PRIORITY => 0, + NOTES => q{ + As well as the tags listed below, the PDF specification allows for + user-defined tags to exist in the Info dictionary. These tags, which should + have corresponding XMP-pdfx entries in the XMP of the PDF XML Metadata + object, are also extracted by ExifTool. + + B<Writable> specifies the value format, and may be C<string>, C<date>, + C<integer>, C<real>, C<boolean> or C<name> for PDF tags. + }, + Title => { }, + Author => { Groups => { 2 => 'Author' } }, + Subject => { }, + Keywords => { List => 'string' }, # this is a string list + Creator => { }, + Producer => { }, + CreationDate => { + Name => 'CreateDate', + Writable => 'date', + Groups => { 2 => 'Time' }, + Shift => 'Time', + PrintConv => '$self->ConvertDateTime($val)', + PrintConvInv => '$self->InverseDateTime($val)', + }, + ModDate => { + Name => 'ModifyDate', + Writable => 'date', + Groups => { 2 => 'Time' }, + Shift => 'Time', + PrintConv => '$self->ConvertDateTime($val)', + PrintConvInv => '$self->InverseDateTime($val)', + }, + Trapped => { + Protected => 1, + # remove leading '/' from '/True' or '/False' + ValueConv => '$val=~s{^/}{}; $val', + ValueConvInv => '"/$val"', + }, + 'AAPL:Keywords' => { #PH + Name => 'AppleKeywords', + List => 'array', # this is an array of values + Notes => q{ + keywords written by Apple utilities, although they seem to use PDF:Keywords + when reading + }, + }, +); + +# tags in the PDF Root document catalog +%Image::ExifTool::PDF::Root = ( + GROUPS => { 2 => 'Document' }, + # note: can't capture previous versions of Root since they are not parsed + VARS => { CAPTURE => ['Root'] }, + NOTES => 'This is the PDF document catalog.', + MarkInfo => { + SubDirectory => { TagTable => 'Image::ExifTool::PDF::MarkInfo' }, + }, + Metadata => { + SubDirectory => { TagTable => 'Image::ExifTool::PDF::Metadata' }, + }, + Pages => { + SubDirectory => { TagTable => 'Image::ExifTool::PDF::Pages' }, + }, + Perms => { + SubDirectory => { TagTable => 'Image::ExifTool::PDF::Perms' }, + }, + AcroForm => { + SubDirectory => { TagTable => 'Image::ExifTool::PDF::AcroForm' }, + }, + Lang => 'Language', + PageLayout => { }, + PageMode => { }, + Version => 'PDFVersion', +); + +# tags extracted from the PDF Encrypt dictionary +%Image::ExifTool::PDF::Encrypt = ( + GROUPS => { 2 => 'Document' }, + NOTES => 'Tags extracted from the document Encrypt dictionary.', + Filter => { + Name => 'Encryption', + Notes => q{ + extracted value is actually a combination of the Filter, SubFilter, V, R and + Length information from the Encrypt dictionary + }, + }, + P => { + Name => 'UserAccess', + ValueConv => '$val & 0x0f3c', # ignore reserved bits + PrintConvColumns => 2, + PrintConv => { BITMASK => { + 2 => 'Print', + 3 => 'Modify', + 4 => 'Copy', + 5 => 'Annotate', + 8 => 'Fill forms', + 9 => 'Extract', + 10 => 'Assemble', + 11 => 'Print high-res', + }}, + }, +); + +# tags in PDF Pages dictionary +%Image::ExifTool::PDF::Pages = ( + GROUPS => { 2 => 'Document' }, + Count => 'PageCount', + Kids => { + SubDirectory => { TagTable => 'Image::ExifTool::PDF::Kids' }, + }, +); + +# tags in PDF Perms dictionary +%Image::ExifTool::PDF::Perms = ( + NOTES => 'Additional document permissions imposed by digital signatures.', + DocMDP => { + SubDirectory => { TagTable => 'Image::ExifTool::PDF::Signature' }, + }, + FieldMDP => { + SubDirectory => { TagTable => 'Image::ExifTool::PDF::Signature' }, + }, + UR3 => { + SubDirectory => { TagTable => 'Image::ExifTool::PDF::Signature' }, + }, +); + +# tags in PDF Perms dictionary +%Image::ExifTool::PDF::AcroForm = ( + PROCESS_PROC => \&ProcessAcroForm, + _has_xfa => { + Name => 'HasXFA', + Notes => q{ + this tag is defined if a document contains form fields, and is true if it + uses XML Forms Architecture; not a real Tag ID + }, + PrintConv => { 'true' => 'Yes', 'false' => 'No' }, + }, +); + +# tags in PDF Kids dictionary +%Image::ExifTool::PDF::Kids = ( + Metadata => { + SubDirectory => { TagTable => 'Image::ExifTool::PDF::Metadata' }, + }, + PieceInfo => { + SubDirectory => { TagTable => 'Image::ExifTool::PDF::PieceInfo' }, + }, + Resources => { + SubDirectory => { TagTable => 'Image::ExifTool::PDF::Resources' }, + }, + Kids => { + Condition => '$self->Options("ExtractEmbedded")', + SubDirectory => { TagTable => 'Image::ExifTool::PDF::Kids' }, + }, +); + +# tags in PDF Resources dictionary +%Image::ExifTool::PDF::Resources = ( + ColorSpace => { + SubDirectory => { TagTable => 'Image::ExifTool::PDF::ColorSpace' }, + }, + XObject => { + Condition => '$self->Options("ExtractEmbedded")', + SubDirectory => { TagTable => 'Image::ExifTool::PDF::XObject' }, + }, + Properties => { + Condition => '$self->Options("ExtractEmbedded")', + SubDirectory => { TagTable => 'Image::ExifTool::PDF::Properties' }, + }, +); + +# tags in PDF ColorSpace dictionary +%Image::ExifTool::PDF::ColorSpace = ( + DefaultRGB => { + SubDirectory => { TagTable => 'Image::ExifTool::PDF::DefaultRGB' }, + }, + Cs1 => { + SubDirectory => { TagTable => 'Image::ExifTool::PDF::Cs1' }, + }, +); + +# tags in PDF DefaultRGB dictionary +%Image::ExifTool::PDF::DefaultRGB = ( + ICCBased => { + SubDirectory => { TagTable => 'Image::ExifTool::PDF::ICCBased' }, + }, +); + +# tags in PDF Cs1 dictionary +%Image::ExifTool::PDF::Cs1 = ( + _stream => { + SubDirectory => { TagTable => 'Image::ExifTool::ICC_Profile::Main' }, + }, +); + +# tags in PDF ICCBased dictionary +%Image::ExifTool::PDF::ICCBased = ( + _stream => { + SubDirectory => { TagTable => 'Image::ExifTool::ICC_Profile::Main' }, + }, +); + +# tags in PDF XObject dictionary (parsed only if ExtractEmbedded is enabled) +%Image::ExifTool::PDF::XObject = ( + EXTRACT_UNKNOWN => 0, # extract known but numbered tags (Im1, Im2, etc) + Im => { + Notes => q{ + the ExtractEmbedded option enables information to be extracted from these + embedded images + }, + SubDirectory => { TagTable => 'Image::ExifTool::PDF::Im' }, + }, +); + +# tags in PDF Im# dictionary +%Image::ExifTool::PDF::Im = ( + NOTES => q{ + Information extracted from embedded images with the ExtractEmbedded option. + The EmbeddedImage and its metadata are extracted only for JPEG and Jpeg2000 + image formats. + }, + Width => 'EmbeddedImageWidth', + Height => 'EmbeddedImageHeight', + Filter => { Name => 'EmbeddedImageFilter', List => 1 }, + ColorSpace => { + Name => 'EmbeddedImageColorSpace', + List => 1, + RawConv => 'ref $val ? undef : $val', # (ignore color space data) + }, + Image_stream => { + Name => 'EmbeddedImage', + Groups => { 2 => 'Preview' }, + Binary => 1, + }, +); + +# tags in PDF Properties dictionary +%Image::ExifTool::PDF::Properties = ( + EXTRACT_UNKNOWN => 0, # extract known but numbered tags (MC0, MC1, etc) + MC => { + Notes => q{ + the ExtractEmbedded option enables information to be extracted from these + embedded metadata dictionaries + }, + SubDirectory => { TagTable => 'Image::ExifTool::PDF::MC' }, + } +); + +# tags in PDF MC# dictionary +%Image::ExifTool::PDF::MC = ( + Metadata => { + SubDirectory => { TagTable => 'Image::ExifTool::PDF::Metadata' }, + } +); + +# tags in PDF PieceInfo dictionary +%Image::ExifTool::PDF::PieceInfo = ( + AdobePhotoshop => { + SubDirectory => { TagTable => 'Image::ExifTool::PDF::AdobePhotoshop' }, + }, + Illustrator => { + # assume this is an illustrator file if it contains this directory + # and doesn't have a ".PDF" extension + Condition => q{ + $self->OverrideFileType("AI") unless $$self{FILE_EXT} and $$self{FILE_EXT} eq 'PDF'; + return 1; + }, + SubDirectory => { TagTable => 'Image::ExifTool::PDF::Illustrator' }, + }, +); + +# tags in PDF AdobePhotoshop dictionary +%Image::ExifTool::PDF::AdobePhotoshop = ( + Private => { + SubDirectory => { TagTable => 'Image::ExifTool::PDF::Private' }, + }, +); + +# tags in PDF Illustrator dictionary +%Image::ExifTool::PDF::Illustrator = ( + Private => { + SubDirectory => { TagTable => 'Image::ExifTool::PDF::AIPrivate' }, + }, +); + +# tags in PDF Private dictionary +%Image::ExifTool::PDF::Private = ( + ImageResources => { + SubDirectory => { TagTable => 'Image::ExifTool::PDF::ImageResources' }, + }, +); + +# tags in PDF AI Private dictionary +%Image::ExifTool::PDF::AIPrivate = ( + GROUPS => { 2 => 'Document' }, + EXTRACT_UNKNOWN => 0, # extract known but numbered tags + AIMetaData => { + SubDirectory => { TagTable => 'Image::ExifTool::PDF::AIMetaData' }, + }, + AIPrivateData => { + Notes => q{ + the ExtractEmbedded option enables information to be extracted from embedded + PostScript documents in the AIPrivateData# and AIPDFPrivateData# streams + }, + JoinStreams => 1, # join streams from numbered tags and process as one + SubDirectory => { TagTable => 'Image::ExifTool::PostScript::Main' }, + }, + AIPDFPrivateData => { + JoinStreams => 1, # join streams from numbered tags and process as one + SubDirectory => { TagTable => 'Image::ExifTool::PostScript::Main' }, + }, + RoundTripVersion => { }, + ContainerVersion => { }, + CreatorVersion => { }, +); + +# tags in PDF AIMetaData dictionary +%Image::ExifTool::PDF::AIMetaData = ( + _stream => { + SubDirectory => { TagTable => 'Image::ExifTool::PostScript::Main' }, + }, +); + +# tags in PDF ImageResources dictionary +%Image::ExifTool::PDF::ImageResources = ( + _stream => { + SubDirectory => { TagTable => 'Image::ExifTool::Photoshop::Main' }, + }, +); + +# tags in PDF MarkInfo dictionary +%Image::ExifTool::PDF::MarkInfo = ( + GROUPS => { 2 => 'Document' }, + Marked => { + Name => 'TaggedPDF', + Notes => "not a Tagged PDF if this tag is missing", + PrintConv => { 'true' => 'Yes', 'false' => 'No' }, + }, +); + +# tags in PDF Metadata dictionary +%Image::ExifTool::PDF::Metadata = ( + GROUPS => { 2 => 'Document' }, + XML_stream => { # this is the stream for a Subtype /XML dictionary (not a real tag) + Name => 'XMP', + SubDirectory => { TagTable => 'Image::ExifTool::XMP::Main' }, + }, +); + +# tags in PDF signature directories (DocMDP, FieldMDP or UR3) +%Image::ExifTool::PDF::Signature = ( + GROUPS => { 2 => 'Document' }, + ContactInfo => 'SignerContactInfo', + Location => 'SigningLocation', + M => { + Name => 'SigningDate', + Format => 'date', + Groups => { 2 => 'Time' }, + PrintConv => '$self->ConvertDateTime($val)', + }, + Name => 'SigningAuthority', + Reason => 'SigningReason', + Reference => { + SubDirectory => { TagTable => 'Image::ExifTool::PDF::Reference' }, + }, + Prop_AuthTime => { + Name => 'AuthenticationTime', + PrintConv => 'ConvertTimeSpan($val) . " ago"', + }, + Prop_AuthType => 'AuthenticationType', +); + +# tags in PDF Reference dictionary +%Image::ExifTool::PDF::Reference = ( + TransformParams => { + SubDirectory => { TagTable => 'Image::ExifTool::PDF::TransformParams' }, + }, +); + +# tags in PDF TransformParams dictionary +%Image::ExifTool::PDF::TransformParams = ( + GROUPS => { 2 => 'Document' }, + Annots => { + Name => 'AnnotationUsageRights', + Notes => q{ + possible values are Create, Delete, Modify, Copy, Import and Export; + additional values for UR3 signatures are Online and SummaryView + }, + List => 1, + }, + Document => { + Name => 'DocumentUsageRights', + Notes => 'only possible value is FullSave', + List => 1, + }, + Form => { + Name => 'FormUsageRights', + Notes => q{ + possible values are FillIn, Import, Export, SubmitStandalone and + SpawnTemplate; additional values for UR3 signatures are BarcodePlaintext and + Online + }, + List => 1, + }, + FormEX => { + Name => 'FormExtraUsageRights', + Notes => 'UR signatures only; only possible value is BarcodePlaintext', + List => 1, + }, + Signature => { + Name => 'SignatureUsageRights', + Notes => 'only possible value is Modify', + List => 1, + }, + EF => { + Name => 'EmbeddedFileUsageRights', + Notes => 'possible values are Create, Delete, Modify and Import', + List => 1, + }, + Msg => 'UsageRightsMessage', + P => { + Name => 'ModificationPermissions', + Notes => q{ + 1-3 for DocMDP signatures, default 2; true/false for UR3 signatures, default + false + }, + PrintConv => { + 1 => 'No changes permitted', + 2 => 'Fill forms, Create page templates, Sign', + 3 => 'Fill forms, Create page templates, Sign, Create/Delete/Edit annotations', + 'true' => 'Restrict all applications to reader permissions', + 'false' => 'Do not restrict applications to reader permissions', + }, + }, + Action => { + Name => 'FieldPermissions', + Notes => 'FieldMDP signatures only', + PrintConv => { + 'All' => 'Disallow changes to all form fields', + 'Include' => 'Disallow changes to specified form fields', + 'Exclude' => 'Allow changes to specified form fields', + }, + }, + Fields => { + Notes => 'FieldMDP signatures only', + Name => 'FormFields', + List => 1, + }, +); + +# unknown tags for use in verbose option +%Image::ExifTool::PDF::Unknown = ( + GROUPS => { 2 => 'Unknown' }, +); + +#------------------------------------------------------------------------------ +# AutoLoad our writer routines when necessary +# +sub AUTOLOAD +{ + return Image::ExifTool::DoAutoLoad($AUTOLOAD, @_); +} + +#------------------------------------------------------------------------------ +# Convert from PDF to EXIF-style date/time +# Inputs: 0) PDF date/time string (D:YYYYmmddHHMMSS+HH'MM') +# Returns: EXIF date string (YYYY:mm:dd HH:MM:SS+HH:MM) +sub ConvertPDFDate($) +{ + my $date = shift; + # remove optional 'D:' prefix + $date =~ s/^D://; + # fill in default values if necessary + # YYYYmmddHHMMSS + my $default = '00000101000000'; + if (length $date < length $default) { + $date .= substr($default, length $date); + } + $date =~ /^(\d{4})(\d{2})(\d{2})(\d{2})(\d{2})(\d{2})(.*)/ or return $date; + $date = "$1:$2:$3 $4:$5:$6"; + if ($7) { + my $tz = $7; + if ($tz =~ /^\s*Z/i) { + # ignore any "HH'mm'" after the Z (OS X 10.6 does this) + $date .= 'Z'; + # tolerate some improper formatting in timezone specification + } elsif ($tz =~ /^\s*([-+])\s*(\d+)[': ]+(\d*)/) { + $date .= $1 . $2 . ':' . ($3 || '00'); + } + } + return $date; +} + +#------------------------------------------------------------------------------ +# Locate any object in the XRef tables (including compressed objects) +# Inputs: 0) XRef reference, 1) object reference string (or free object number) +# Returns: offset to object in file or compressed object reference string, +# 0 if object is free, or undefined on error +sub LocateAnyObject($$) +{ + my ($xref, $ref) = @_; + return undef unless $xref; + return $$xref{$ref} if exists $$xref{$ref}; + # get the object number + return undef unless $ref =~ /^(\d+)/; + my $objNum = $1; + # return 0 if the object number has been reused (old object is free) + return 0 if defined $$xref{$objNum}; +# +# scan our XRef stream dictionaries for this object +# + return undef unless $$xref{dicts}; + my $dict; + foreach $dict (@{$$xref{dicts}}) { + # quick check to see if the object is in the range for this xref stream + next if $objNum >= $$dict{Size}; + my $index = $$dict{Index}; + next if $objNum < $$index[0]; + # scan the tables for the specified object + my $size = $$dict{_entry_size}; + my $num = scalar(@$index) / 2; + my $tot = 0; + my $i; + for ($i=0; $i<$num; ++$i) { + my $start = $$index[$i*2]; + my $count = $$index[$i*2+1]; + # table is in ascending order, so quit if we have passed the object + last if $objNum < $start; + if ($objNum < $start + $count) { + my $offset = $size * ($objNum - $start + $tot); + last if $offset + $size > length $$dict{_stream}; + my @c = unpack("x$offset C$size", $$dict{_stream}); + # extract values from this table entry + # (can be 1, 2, 3, 4, etc.. bytes per value) + my (@t, $j, $k); + my $w = $$dict{W}; + for ($j=0; $j<3; ++$j) { + # use default value if W entry is 0 (as per spec) + # - 0th element defaults to 1, others default to 0 + $$w[$j] or $t[$j] = ($j ? 0 : 1), next; + $t[$j] = shift(@c); + for ($k=1; $k < $$w[$j]; ++$k) { + $t[$j] = 256 * $t[$j] + shift(@c); + } + } + # by default, use "o g R" as the xref key + # (o = object number, g = generation number) + my $ref2 = "$objNum $t[2] R"; + if ($t[0] == 1) { + # normal object reference: + # $t[1]=offset of object from start, $t[2]=generation number + $$xref{$ref2} = $t[1]; + } elsif ($t[0] == 2) { + # compressed object reference: + # $t[1]=stream object number, $t[2]=index of object in stream + $ref2 = "$objNum 0 R"; + $$xref{$ref2} = "I$t[2] $t[1] 0 R"; + } elsif ($t[0] == 0) { + # free object: + # $t[1]=next free object in linked list, $t[2]=generation number + $$xref{$ref2} = 0; + } else { + # treat as a null object + $$xref{$ref2} = undef; + } + $$xref{$objNum} = $t[1]; # remember offsets by object number too + return $$xref{$ref} if $ref eq $ref2; + return 0; # object is free or was reused + } + $tot += $count; + } + } + return undef; +} + +#------------------------------------------------------------------------------ +# Locate a regular object in the XRef tables (does not include compressed objects) +# Inputs: 0) XRef reference, 1) object reference string (or free object number) +# Returns: offset to object in file, 0 if object is free, +# or undef on error or if object was compressed +sub LocateObject($$) +{ + my ($xref, $ref) = @_; + my $offset = LocateAnyObject($xref, $ref); + return undef if $offset and $offset =~ /^I/; + return $offset; +} + +#------------------------------------------------------------------------------ +# Fetch indirect object from file (from inside a stream if required) +# Inputs: 0) ExifTool object reference, 1) object reference string, +# 2) xref lookup, 3) object name (for warning messages) +# Returns: object data or undefined on error +# Notes: sets $lastFetched to the object reference, or undef if the object +# was extracted from an encrypted stream +sub FetchObject($$$$) +{ + my ($et, $ref, $xref, $tag) = @_; + $lastFetched = $ref; # save this for decoding if necessary + my $offset = LocateAnyObject($xref, $ref); + $lastOffset = $offset; + unless ($offset) { + $et->Warn("Bad $tag reference") unless defined $offset; + return undef; + } + my ($data, $obj); + if ($offset =~ s/^I(\d+) //) { + my $index = $1; # object index in stream + my ($objNum) = split ' ', $ref; # save original object number + $ref = $offset; # now a reference to the containing stream object + $obj = $streamObjs{$ref}; + unless ($obj) { + # don't try to load the same object stream twice + return undef if defined $obj; + $streamObjs{$ref} = ''; + # load the parent object stream + $obj = FetchObject($et, $ref, $xref, $tag); + # make sure it contains everything we need + return undef unless defined $obj and ref($obj) eq 'HASH'; + return undef unless $$obj{First} and $$obj{N}; + return undef unless DecodeStream($et, $obj); + # add a special '_table' entry to this dictionary which contains + # the list of object number/offset pairs from the stream header + my $num = $$obj{N} * 2; + my @table = split ' ', $$obj{_stream}, $num; + return undef unless @table == $num; + # remove everything before first object in stream + $$obj{_stream} = substr($$obj{_stream}, $$obj{First}); + $table[$num-1] =~ s/^(\d+).*/$1/s; # trim excess from last number + $$obj{_table} = \@table; + # save the object stream so we don't have to re-load it later + $streamObjs{$ref} = $obj; + } + # verify that we have the specified object + my $i = 2 * $index; + my $table = $$obj{_table}; + unless ($index < $$obj{N} and $$table[$i] == $objNum) { + $et->Warn("Bad index for stream object $tag"); + return undef; + } + # extract the object at the specified index in the stream + # (offsets in table are in sequential order, so we can subract from + # the next offset to get the object length) + $offset = $$table[$i + 1]; + my $len = ($$table[$i + 3] || length($$obj{_stream})) - $offset; + $data = substr($$obj{_stream}, $offset, $len); + # avoid re-decrypting data in already decrypted streams + undef $lastFetched if $cryptStream; + return ExtractObject($et, \$data); + } + my $raf = $$et{RAF}; + $raf->Seek($offset+$$et{PDFBase}, 0) or $et->Warn("Bad $tag offset"), return undef; + # verify that we are reading the expected object + $raf->ReadLine($data) or $et->Warn("Error reading $tag data"), return undef; + ($obj = $ref) =~ s/R/obj/; + unless ($data =~ s/^$obj//) { + $et->Warn("$tag object ($obj) not found at $offset"); + return undef; + } + # read the first line of data for the object (skipping comments if necessary) + for (;;) { + last if $data =~ /\S/ and $data !~ /^\s*%/; + $raf->ReadLine($data) or $et->Warn("Error reading $tag data"), return undef; + } + return ExtractObject($et, \$data, $raf, $xref); +} + +#------------------------------------------------------------------------------ +# Convert PDF value to something readable +# Inputs: 0) PDF object data +# Returns: converted object +sub ReadPDFValue($) +{ + my $str = shift; + # decode all strings in an array + if (ref $str eq 'ARRAY') { + # create new list to not alter the original data when rewriting + my ($val, @vals); + foreach $val (@$str) { + push @vals, ReadPDFValue($val); + } + return \@vals; + } + length $str or return $str; + my $delim = substr($str, 0, 1); + if ($delim eq '(') { # literal string + $str = $1 if $str =~ /^.*?\((.*)\)/s; # remove brackets + # decode escape sequences in literal strings + while ($str =~ /\\(.)/sg) { + my $n = pos($str) - 2; + my $c = $1; + my $r; + if ($c =~ /[0-7]/) { + # get up to 2 more octal digits + $c .= $1 if $str =~ /\G([0-7]{1,2})/g; + # convert octal escape code + $r = chr(oct($c) & 0xff); + } elsif ($c eq "\x0d") { + # the string is continued if the line ends with '\' + # (also remove "\x0d\x0a") + $c .= $1 if $str =~ /\G(\x0a)/g; + $r = ''; + } elsif ($c eq "\x0a") { + $r = ''; + } else { + # convert escaped characters + ($r = $c) =~ tr/nrtbf/\n\r\t\b\f/; + } + substr($str, $n, length($c)+1) = $r; + # continue search after this character + pos($str) = $n + length($r); + } + Crypt(\$str, $lastFetched) if $cryptString; + } elsif ($delim eq '<') { # hex string + # decode hex data + $str =~ tr/0-9A-Fa-f//dc; + $str .= '0' if length($str) & 0x01; # (by the spec) + $str = pack('H*', $str); + Crypt(\$str, $lastFetched) if $cryptString; + } elsif ($delim eq '/') { # name + $str = substr($str, 1); + # convert escape codes (PDF 1.2 or later) + $str =~ s/#([0-9a-f]{2})/chr(hex($1))/sgei if $pdfVer >= 1.2; + } + return $str; +} + +#------------------------------------------------------------------------------ +# Extract PDF object from combination of buffered data and file +# Inputs: 0) ExifTool object reference, 1) data reference, +# 2) optional raf reference, 3) optional xref table +# Returns: converted PDF object or undef on error +# a) dictionary object --> hash reference +# b) array object --> array reference +# c) indirect reference --> scalar reference +# d) string, name, integer, boolean, null --> scalar value +# - updates $$dataPt on return to contain unused data +# - creates two bogus entries ('_stream' and '_tags') in dictionaries to represent +# the stream data and a list of the tags (not including '_stream' and '_tags') +# in their original order +sub ExtractObject($$;$$) +{ + my ($et, $dataPt, $raf, $xref) = @_; + my (@tags, $data, $objData); + my $dict = { }; + my $delim; + + for (;;) { + if ($$dataPt =~ /^\s*(<{1,2}|\[|\()/s) { + $delim = $1; + $$dataPt =~ s/^\s+//; # remove leading white space + $objData = ReadToNested($dataPt, $raf); + return undef unless defined $objData; + last; + } elsif ($$dataPt =~ s{^\s*(\S[^[(/<>\s]*)\s*}{}s) { +# +# extract boolean, numerical, string, name, null object or indirect reference +# + $objData = $1; + # look for an indirect reference + if ($objData =~ /^\d+$/ and $$dataPt =~ s/^(\d+)\s+R//s) { + $objData .= "$1 R"; + $objData = \$objData; # return scalar reference + } + return $objData; # return simple scalar or scalar reference + } + $raf and $raf->ReadLine($data) or return undef; + $$dataPt .= $data; + } +# +# return literal string or hex string without parsing +# + if ($delim eq '(' or $delim eq '<') { + return $objData; +# +# extract array +# + } elsif ($delim eq '[') { + $objData =~ /^.*?\[(.*)\]/s or return undef; + my $data = $1; # brackets removed + my @list; + for (;;) { + last unless $data =~ m{\s*(\S[^[(/<>\s]*)}sg; + my $val = $1; + if ($val =~ /^(<{1,2}|\[|\()/) { + my $pos = pos($data) - length($val); + # nested dict, array, literal string or hex string + my $buff = substr($data, $pos); + $val = ReadToNested(\$buff); + last unless defined $val; + pos($data) = $pos + length($val); + $val = ExtractObject($et, \$val); + } elsif ($val =~ /^\d/) { + my $pos = pos($data); + if ($data =~ /\G\s+(\d+)\s+R/g) { + $val = \ "$val $1 R"; # make a reference + } else { + pos($data) = $pos; + } + } + push @list, $val; + } + return \@list; + } +# +# extract dictionary +# + # Note: entries are not necessarily separated by whitespace (doh!) + # eg) "/Tag/Name", "/Tag(string)", "/Tag[array]", etc are legal! + # Also, they may be separated by a comment (eg. "/Tag%comment\nValue"), + # but comments have already been removed + while ($objData =~ m{(\s*)/([^/[\]()<>{}\s]+)\s*(\S[^[(/<>\s]*)}sg) { + my $tag = $2; + my $val = $3; + if ($val =~ /^(<{1,2}|\[|\()/) { + # nested dict, array, literal string or hex string + $objData = substr($objData, pos($objData)-length($val)); + $val = ReadToNested(\$objData, $raf); + last unless defined $val; + $val = ExtractObject($et, \$val); + pos($objData) = 0; + } elsif ($val =~ /^\d/) { + my $pos = pos($objData); + if ($objData =~ /\G\s+(\d+)\s+R/sg) { + $val = \ "$val $1 R"; # make a reference + } else { + pos($objData) = $pos; + } + } + if ($$dict{$tag}) { + # duplicate dictionary entries are not allowed + $et->Warn("Duplicate '${tag}' entry in dictionary (ignored)"); + } else { + # save the entry + push @tags, $tag; + $$dict{$tag} = $val; + } + } + return undef unless @tags; + $$dict{_tags} = \@tags; + return $dict unless $raf; # direct objects can not have streams +# +# extract the stream object +# + # dictionary must specify stream Length + my $length = $$dict{Length} or return $dict; + if (ref $length) { + $length = $$length; + my $oldpos = $raf->Tell(); + # get the location of the object specifying the length + # (compressed objects are not allowed) + my $offset = LocateObject($xref, $length) or return $dict; + $offset or $et->Warn('Bad Length object'), return $dict; + $raf->Seek($offset+$$et{PDFBase}, 0) or $et->Warn('Bad Length offset'), return $dict; + # verify that we are reading the expected object + $raf->ReadLine($data) or $et->Warn('Error reading Length data'), return $dict; + $length =~ s/R/obj/; + unless ($data =~ /^$length\s+(\d+)?/) { + $et->Warn("Length object ($length) not found at $offset"); + return $dict; + } + if (defined $1) { + $length = $1; + } else { + $raf->ReadLine($data) or $et->Warn('Error reading stream Length'), return $dict; + $data =~ /^\s*(\d+)/ or $et->Warn('Stream length not found'), return $dict; + $length = $1; + } + $raf->Seek($oldpos, 0); # restore position to start of stream + } + # extract the trailing stream data + for (;;) { + # find the stream token + if ($$dataPt =~ /(\S+)/) { + last unless $1 eq 'stream'; + # read an extra line because it may contain our \x0a + $$dataPt .= $data if $raf->ReadLine($data); + # remove our stream header + $$dataPt =~ s/^\s*stream(\x0a|\x0d\x0a)//s; + my $more = $length - length($$dataPt); + if ($more > 0) { + unless ($raf->Read($data, $more) == $more) { + $et->Warn('Error reading stream data'); + $$dataPt = ''; + return $dict; + } + $$dict{_stream} = $$dataPt . $data; + $$dataPt = ''; + } elsif ($more < 0) { + $$dict{_stream} = substr($$dataPt, 0, $length); + $$dataPt = substr($$dataPt, $length); + } else { + $$dict{_stream} = $$dataPt; + $$dataPt = ''; + } + last; + } + $raf->ReadLine($data) or last; + $$dataPt .= $data; + } + return $dict; +} + +#------------------------------------------------------------------------------ +# Read to nested delimiter +# Inputs: 0) data reference, 1) optional raf reference +# Returns: data up to and including matching delimiter (or undef on error) +# - updates data reference with trailing data +# - unescapes characters in literal strings +my %closingDelim = ( # lookup for matching delimiter + '(' => ')', + '[' => ']', + '<' => '>', + '<<' => '>>', +); +sub ReadToNested($;$) +{ + my ($dataPt, $raf) = @_; + my @delim = (''); # closing delimiter list, most deeply nested first + pos($$dataPt) = 0; # begin at start of data + for (;;) { + unless ($$dataPt =~ /(\\*)(\(|\)|<{1,2}|>{1,2}|\[|\]|%)/g) { + # must read some more data + my $buff; + last unless $raf and $raf->ReadLine($buff); + $$dataPt .= $buff; + pos($$dataPt) = length($$dataPt) - length($buff); + next; + } + # are we in a literal string? + if ($delim[0] eq ')') { + # ignore escaped delimiters (preceded by odd number of \'s) + next if length($1) & 0x01; + # ignore all delimiters but unescaped braces + next unless $2 eq '(' or $2 eq ')'; + } elsif ($2 eq '%') { + # ignore the comment + my $pos = pos($$dataPt) - 1; + # remove everything from '%' up to but not including newline + $$dataPt =~ /.*/g; + my $end = pos($$dataPt); + $$dataPt = substr($$dataPt, 0, $pos) . substr($$dataPt, $end); + pos($$dataPt) = $pos; + next; + } + if ($closingDelim{$2}) { + # push the corresponding closing delimiter + unshift @delim, $closingDelim{$2}; + next; + } + unless ($2 eq $delim[0]) { + # handle the case where we find a ">>>" and interpret it + # as ">> >" instead of "> >>" + next unless $2 eq '>>' and $delim[0] eq '>'; + pos($$dataPt) = pos($$dataPt) - 1; + } + shift @delim; # remove from nesting list + next if $delim[0]; # keep going if we have more nested delimiters + my $pos = pos($$dataPt); + my $buff = substr($$dataPt, 0, $pos); + $$dataPt = substr($$dataPt, $pos); + return $buff; # success! + } + return undef; # didn't find matching delimiter +} + +#------------------------------------------------------------------------------ +# Decode LZW-encoded data (ref 1) +# Inputs: 0) data reference +# Returns: true on success and data is decoded, or false and data is untouched +sub DecodeLZW($) +{ + my $dataPt = shift; + return 0 if length $$dataPt < 4; + my @lzw = (map(chr, 0..255), undef, undef); # LZW code table + my $mask = 0x01ff; # mask for least-significant 9 bits + my @dat = unpack 'n*', $$dataPt . "\0"; + my $word = ($dat[0] << 16) | $dat[1]; + my ($bit, $pos, $bits, $out) = (0, 2, 9, ''); + my $lastVal; + for (;;) { + # bits are packed MSB first in PDF LZW (the PDF spec doesn't mention this) + my $shift = 32 - ($bit + $bits); + if ($shift < 0) { + return 0 if $pos >= @dat; # missing EOD marker + $word = (($word & 0xffff) << 16) | $dat[$pos++]; # read next word + $bit -= 16; + $shift += 16; + }; + my $code = ($word >> $shift) & $mask; + $bit += $bits; + my $val = $lzw[$code]; + if (defined $val) { + # store new code as previous sequence plus 1st char of new sequence + push @lzw, $lastVal . substr($val, 0, 1) if defined $lastVal; + } elsif ($code == @lzw) { # new code + return 0 unless defined $lastVal; + # we are using the code that we are about to generate, so the last + # character in the new sequence must be the same as the first + # character in the previous sequence (makes sense if you think about it) + $val = $lastVal . substr($lastVal, 0, 1); + push @lzw, $val; + } elsif ($code == 256) { # clear table + splice @lzw, 258; + $bits = 9; + $mask = 0x1ff; + undef $lastVal; + next; + } elsif ($code == 257) { # EOD marker + last; # all done! + } else { + return 0; + } + $out .= $val; # add this byte sequence to the output + # we added a new entry to the LZW table, so we must increase + # the bit width if necessary, up to a maximum of 12 + @lzw >= $mask and $bits < 12 and ++$bits, $mask |= $mask << 1; + $lastVal = $val; + } + $$dataPt = $out; # return decompressed data + return 1; +} + +#------------------------------------------------------------------------------ +# Decode filtered stream +# Inputs: 0) ExifTool object reference, 1) dictionary reference +# Returns: true if stream has been decoded OK +sub DecodeStream($$) +{ + local $_; + my ($et, $dict) = @_; + + return 0 unless $$dict{_stream}; # no stream to decode + + # get list of filters + my (@filters, @decodeParms, $filter); + if (ref $$dict{Filter} eq 'ARRAY') { + @filters = @{$$dict{Filter}}; + } elsif (defined $$dict{Filter}) { + @filters = ($$dict{Filter}); + } + # be sure we can process all the filters before we take the time to do the decryption + foreach $filter (@filters) { + next if $supportedFilter{$filter}; + $et->WarnOnce("Unsupported Filter $filter"); + return 0; + } + # apply decryption first if required (and if the default encryption + # has not been overridden by a Crypt filter. Note: the Crypt filter + # must be first in the Filter array: ref 3, page 38) + unless (defined $$dict{_decrypted} or ($filters[0] and $filters[0] eq '/Crypt')) { + CryptStream($dict, $lastFetched); + } + return 1 unless $$dict{Filter}; # Filter entry is mandatory + return 0 if defined $$dict{_filtered}; # avoid double-filtering + $$dict{_filtered} = 1; # set flag to prevent double-filtering + + # get array of DecodeParms dictionaries + if (ref $$dict{DecodeParms} eq 'ARRAY') { + @decodeParms = @{$$dict{DecodeParms}}; + } else { + @decodeParms = ($$dict{DecodeParms}); + } + + foreach $filter (@filters) { + my $decodeParms = shift @decodeParms; + + if ($filter eq '/FlateDecode') { + # make sure we support the predictor (if used) before decoding + my $pre; + if (ref $decodeParms eq 'HASH') { + $pre = $$decodeParms{Predictor}; + if ($pre and $pre ne '1' and $pre ne '12') { + $et->WarnOnce("FlateDecode Predictor $pre currently not supported"); + return 0; + } + } + if (eval { require Compress::Zlib }) { + my $inflate = Compress::Zlib::inflateInit(); + my ($buff, $stat); + $inflate and ($buff, $stat) = $inflate->inflate($$dict{_stream}); + if ($inflate and $stat == Compress::Zlib::Z_STREAM_END()) { + $$dict{_stream} = $buff; + } else { + $et->Warn('Error inflating stream'); + return 0; + } + } else { + $et->WarnOnce('Install Compress::Zlib to process filtered streams'); + return 0; + } + next unless $pre and $pre eq '12'; # 12 = 'up' prediction + + # apply anti-predictor + my $cols = $$decodeParms{Columns}; + unless ($cols) { + # currently only support 'up' prediction + $et->WarnOnce('No Columns for decoding stream'); + return 0; + } + my @bytes = unpack('C*', $$dict{_stream}); + my @pre = (0) x $cols; # initialize predictor array + my $buff = ''; + while (@bytes > $cols) { + unless (($_ = shift @bytes) == 2) { + $et->WarnOnce("Unsupported PNG filter $_"); # (yes, PNG) + return 0; + } + foreach (@pre) { + $_ = ($_ + shift(@bytes)) & 0xff; + } + $buff .= pack('C*', @pre); + } + $$dict{_stream} = $buff; + + } elsif ($filter eq '/Crypt') { + + # (we shouldn't have to check the _decrypted flag since we + # already checked the _filtered flag, but what the heck...) + next if defined $$dict{_decrypted}; + # assume Identity filter (the default) if DecodeParms are missing + next unless ref $decodeParms eq 'HASH'; + my $name = $$decodeParms{Name}; + next unless defined $name or $name eq 'Identity'; + if ($name ne 'StdCF') { + $et->WarnOnce("Unsupported Crypt Filter $name"); + return 0; + } + unless ($cryptInfo) { + $et->WarnOnce('Missing Encrypt StdCF entry'); + return 0; + } + # decrypt the stream manually because we want to: + # 1) ignore $cryptStream (StmF) setting + # 2) ignore EncryptMetadata setting (I can't find mention of how to + # reconcile this in the spec., but this would make sense) + # 3) avoid adding the crypt key extension (ref 3, page 58, Algorithm 1b) + # 4) set _decrypted flag so we will recrypt according to StmF when + # writing (since we don't yet write Filter'd streams) + Crypt(\$$dict{_stream}, 'none'); + $$dict{_decrypted} = ($cryptStream ? 1 : 0); + + } elsif ($filter eq '/LZWDecode') { + + # make sure we don't have any unsupported decoding parameters + if (ref $decodeParms eq 'HASH') { + if ($$decodeParms{Predictor}) { + $et->WarnOnce("LZWDecode Predictor $$decodeParms{Predictor} currently not supported"); + return 0; + } elsif ($$decodeParms{EarlyChange}) { + $et->WarnOnce("LZWDecode EarlyChange currently not supported"); + return 0; + } + } + unless (DecodeLZW(\$$dict{_stream})) { + $et->WarnOnce('LZW decompress error'); + return 0; + } + + } elsif ($filter eq '/ASCIIHexDecode') { + + $$dict{_stream} =~ s/>.*//; # truncate at '>' (end of data mark) + $$dict{_stream} =~ tr/0-9a-zA-Z//d; # remove illegal characters + $$dict{_stream} = pack 'H*', $$dict{_stream}; + + } elsif ($filter eq '/ASCII85Decode') { + + my ($err, @out, $i); + my ($n, $val) = (0, 0); + foreach (split //, $$dict{_stream}) { + if ($_ ge '!' and $_ le 'u') {; + $val = 85 * $val + ord($_) - 33; + next unless ++$n == 5; + } elsif ($_ eq '~') { + $n == 1 and $err = 1; # error to have a single char in the last group of 5 + for ($i=$n; $i<5; ++$i) { $val *= 85; } + } elsif ($_ eq 'z') { + $n and $err = 2, last; # error if 'z' isn't the first char + $n = 5; + } else { + next if /^\s$/; # ignore white space + $err = 3, last; # any other character is an error + } + $val = unpack('V', pack('N', $val)); # reverse byte order + while (--$n > 0) { + push @out, $val & 0xff; + $val >>= 8; + } + last if $_ eq '~'; + # (both $n and $val are zero again now) + } + $err and $et->WarnOnce("ASCII85Decode error $err"); + $$dict{_stream} = pack('C*', @out); + } + } + return 1; +} + +#------------------------------------------------------------------------------ +# Initialize state for RC4 en/decryption (ref 2) +# Inputs: 0) RC4 key string +# Returns: RC4 key hash reference +sub RC4Init($) +{ + my @key = unpack('C*', shift); + my @state = (0 .. 255); + my ($i, $j) = (0, 0); + while ($i < 256) { + my $st = $state[$i]; + $j = ($j + $st + $key[$i % scalar(@key)]) & 0xff; + $state[$i++] = $state[$j]; + $state[$j] = $st; + } + return { State => \@state, XY => [ 0, 0 ] }; +} + +#------------------------------------------------------------------------------ +# Apply RC4 en/decryption (ref 2) +# Inputs: 0) data reference, 1) RC4 key hash reference or RC4 key string +# - can call this method directly with a key string, or with with the key +# reference returned by RC4Init +# - RC4 is a symmetric algorithm, so encryption is the same as decryption +sub RC4Crypt($$) +{ + my ($dataPt, $key) = @_; + $key = RC4Init($key) unless ref $key eq 'HASH'; + my $state = $$key{State}; + my ($x, $y) = @{$$key{XY}}; + + my @data = unpack('C*', $$dataPt); + foreach (@data) { + $x = ($x + 1) & 0xff; + my $stx = $$state[$x]; + $y = ($stx + $y) & 0xff; + my $sty = $$state[$x] = $$state[$y]; + $$state[$y] = $stx; + $_ ^= $$state[($stx + $sty) & 0xff]; + } + $$key{XY} = [ $x, $y ]; + $$dataPt = pack('C*', @data); +} + +#------------------------------------------------------------------------------ +# Update AES cipher with a bit of data +# Inputs: 0) data +# Returns: encrypted data +my $cipherMore; +sub CipherUpdate($) +{ + my $dat = shift; + my $pos = 0; + $dat = $cipherMore . $dat if length $dat; + while ($pos + 16 <= length($dat)) { + substr($dat,$pos,16) = Image::ExifTool::AES::Cipher(substr($dat,$pos,16)); + $pos += 16; + } + if ($pos < length $dat) { + $cipherMore = substr($dat,$pos); + $dat = substr($dat,0,$pos); + } else { + $cipherMore = ''; + } + return $dat; +} + +#------------------------------------------------------------------------------ +# Get encrypted hash +# Inputs: 0) Password, 1) salt, 2) vector, 3) encryption revision +# Returns: hash +sub GetHash($$$$) +{ + my ($password, $salt, $vector, $rev) = @_; + + # return Rev 5 hash + return Digest::SHA::sha256($password, $salt, $vector) if $rev == 5; + + # compute Rev 6 hardened hash + # (ref http://code.google.com/p/origami-pdf/source/browse/lib/origami/encryption.rb) + my $blockSize = 32; + my $input = Digest::SHA::sha256($password, $salt, $vector) . ("\0" x 32); + my $key = substr($input, 0, 16); + my $iv = substr($input, 16, 16); + my $h; + my $x = ''; + my $i = 0; + while ($i < 64 or $i < ord(substr($x,-1,1))+32) { + + my $block = substr($input, 0, $blockSize); + $x = ''; + Image::ExifTool::AES::Crypt(\$x, $key, $iv, 1); + $cipherMore = ''; + + my ($j, $digest); + for ($j=0; $j<64; ++$j) { + $x = ''; + $x .= CipherUpdate($password) if length $password; + $x .= CipherUpdate($block); + $x .= CipherUpdate($vector) if length $vector; + if ($j == 0) { + my @a = unpack('C16', $x); + my $sum = 0; + $sum += $_ foreach @a; + # set SHA block size (32, 48 or 64 bytes = SHA-256, 384 or 512) + $blockSize = 32 + ($sum % 3) * 16; + $digest = Digest::SHA->new($blockSize * 8); + } + $digest->add($x); + } + + $h = $digest->digest(); + $key = substr($h, 0, 16); + substr($input,0,16) = $h; + $iv = substr($h, 16, 16); + ++$i; + } + return substr($h, 0, 32); +} + +#------------------------------------------------------------------------------ +# Initialize decryption +# Inputs: 0) ExifTool object reference, 1) Encrypt dictionary reference, +# 2) ID from file trailer dictionary +# Returns: error string or undef on success (and sets $cryptInfo) +sub DecryptInit($$$) +{ + local $_; + my ($et, $encrypt, $id) = @_; + + undef $cryptInfo; + unless ($encrypt and ref $encrypt eq 'HASH') { + return 'Error loading Encrypt object'; + } + my $filt = $$encrypt{Filter}; + unless ($filt and $filt =~ s/^\///) { + return 'Encrypt dictionary has no Filter!'; + } + # extract some interesting tags + my $ver = $$encrypt{V} || 0; + my $rev = $$encrypt{R} || 0; + my $enc = "$filt V$ver"; + $enc .= ".$rev" if $filt eq 'Standard'; + $enc .= " ($1)" if $$encrypt{SubFilter} and $$encrypt{SubFilter} =~ /^\/(.*)/; + $enc .= ' (' . ($$encrypt{Length} || 40) . '-bit)' if $filt eq 'Standard'; + my $tagTablePtr = GetTagTable('Image::ExifTool::PDF::Encrypt'); + $et->HandleTag($tagTablePtr, 'Filter', $enc); + if ($filt ne 'Standard') { + return "Encryption filter $filt currently not supported"; + } elsif (not defined $$encrypt{R}) { + return 'Standard security handler missing revision'; + } + unless ($$encrypt{O} and $$encrypt{P} and $$encrypt{U}) { + return 'Incomplete Encrypt specification'; + } + if ("$ver.$rev" >= 5.6) { + # apologize for poor performance (AES is a pure Perl implementation) + $et->Warn('Decryption is very slow for encryption V5.6 or higher', 3); + } + $et->HandleTag($tagTablePtr, 'P', $$encrypt{P}); + + my %parm; # optional parameters extracted from Encrypt dictionary + + if ($ver == 1 or $ver == 2) { + $cryptString = $cryptStream = 1; + } elsif ($ver == 4 or $ver == 5) { + # initialize our $cryptString and $cryptStream flags + foreach ('StrF', 'StmF') { + my $flagPt = $_ eq 'StrF' ? \$cryptString : \$cryptStream; + $$flagPt = $$encrypt{$_}; + undef $$flagPt if $$flagPt and $$flagPt eq '/Identity'; + return "Unsupported $_ encryption $$flagPt" if $$flagPt and $$flagPt ne '/StdCF'; + } + if ($cryptString or $cryptStream) { + return 'Missing or invalid Encrypt StdCF entry' unless ref $$encrypt{CF} eq 'HASH' and + ref $$encrypt{CF}{StdCF} eq 'HASH' and $$encrypt{CF}{StdCF}{CFM}; + my $cryptMeth = $$encrypt{CF}{StdCF}{CFM}; + unless ($cryptMeth =~ /^\/(V2|AESV2|AESV3)$/) { + return "Unsupported encryption method $cryptMeth"; + } + # set "_aesv2" or "_aesv3" flag in %$encrypt hash if AES encryption was used + $$encrypt{'_' . lc($1)} = 1 if $cryptMeth =~ /^\/(AESV2|AESV3)$/; + } + if ($ver == 5) { + # validate OE and UE entries + foreach ('OE', 'UE') { + return "Missing Encrypt $_ entry" unless $$encrypt{$_}; + $parm{$_} = ReadPDFValue($$encrypt{$_}); + return "Invalid Encrypt $_ entry" unless length $parm{$_} == 32; + } + require Image::ExifTool::AES; # will need this later + } + } else { + return "Encryption version $ver currently not supported"; + } + $id or return "Can't decrypt (no document ID)"; + + # make sure we have the necessary libraries available + if ($ver < 5) { + unless (eval { require Digest::MD5 }) { + return "Install Digest::MD5 to process encrypted PDF"; + } + } else { + unless (eval { require Digest::SHA }) { + return "Install Digest::SHA to process AES-256 encrypted PDF"; + } + } + + # calculate file-level en/decryption key + my $pad = "\x28\xBF\x4E\x5E\x4E\x75\x8A\x41\x64\x00\x4E\x56\xFF\xFA\x01\x08". + "\x2E\x2E\x00\xB6\xD0\x68\x3E\x80\x2F\x0C\xA9\xFE\x64\x53\x69\x7A"; + my $o = ReadPDFValue($$encrypt{O}); + my $u = ReadPDFValue($$encrypt{U}); + + # set flag indicating whether metadata is encrypted + # (in version 4 and higher, metadata streams may not be encrypted) + if ($ver < 4 or not $$encrypt{EncryptMetadata} or $$encrypt{EncryptMetadata} !~ /false/i) { + $$encrypt{_meta} = 1; + } + # try no password first, then try provided password if available + my ($try, $key); + for ($try=0; ; ++$try) { + my $password; + if ($try == 0) { + $password = ''; + } elsif ($try == 1) { + $password = $et->Options('Password'); + return 'Document is password protected (use Password option)' unless defined $password; + # make sure there is no UTF-8 flag on the password + if ($] >= 5.006 and (eval { require Encode; Encode::is_utf8($password) } or $@)) { + # repack by hand if Encode isn't available + $password = $@ ? pack('C*',unpack($] < 5.010000 ? 'U0C*' : 'C0C*',$password)) : Encode::encode('utf8',$password); + } + } else { + return 'Incorrect password'; + } + if ($ver < 5) { + if (length $password) { + # password must be encoding in PDFDocEncoding (ref iso32000) + $password = $et->Encode($password, 'PDFDoc'); + # truncate or pad the password to exactly 32 bytes + if (length($password) > 32) { + $password = substr($password, 0, 32); + } elsif (length($password) < 32) { + $password .= substr($pad, 0, 32-length($password)); + } + } else { + $password = $pad; + } + $key = $password . $o . pack('V', $$encrypt{P}) . $id; + my $rep = 1; + if ($rev == 3 or $rev == 4) { + # must add this if metadata not encrypted + $key .= "\xff\xff\xff\xff" unless $$encrypt{_meta}; + $rep += 50; # repeat MD5 50 more times if revision is 3 or greater + } + my ($len, $i, $dat); + if ($ver == 1) { + $len = 5; + } else { + $len = $$encrypt{Length} || 40; + $len >= 40 or return 'Bad Encrypt Length'; + $len = int($len / 8); + } + for ($i=0; $i<$rep; ++$i) { + $key = substr(Digest::MD5::md5($key), 0, $len); + } + # decrypt U to see if a user password is required + if ($rev >= 3) { + $dat = Digest::MD5::md5($pad . $id); + RC4Crypt(\$dat, $key); + for ($i=1; $i<=19; ++$i) { + my @key = unpack('C*', $key); + foreach (@key) { $_ ^= $i; } + RC4Crypt(\$dat, pack('C*', @key)); + } + $dat .= substr($u, 16); + } else { + $dat = $pad; + RC4Crypt(\$dat, $key); + } + last if $dat eq $u; # all done if this was the correct key + } else { + return 'Invalid O or U Encrypt entries' if length($o) < 48 or length($u) < 48; + if (length $password) { + # Note: this should be good for passwords containing reasonable characters, + # but to be bullet-proof we need to apply the SASLprep (IETF RFC 4013) profile + # of stringprep (IETF RFC 3454) to the password before encoding in UTF-8 + $password = $et->Encode($password, 'UTF8'); + $password = substr($password, 0, 127) if length($password) > 127; + } + # test for the owner password + my $sha = GetHash($password, substr($o,32,8), substr($u,0,48), $rev); + if ($sha eq substr($o, 0, 32)) { + $key = GetHash($password, substr($o,40,8), substr($u,0,48), $rev); + my $dat = ("\0" x 16) . $parm{OE}; + # decrypt with no padding + my $err = Image::ExifTool::AES::Crypt(\$dat, $key, 0, 1); + return $err if $err; + $key = $dat; # use this as the file decryption key + last; + } + # test for the user password + $sha = GetHash($password, substr($u,32,8), '', $rev); + if ($sha eq substr($u, 0, 32)) { + $key = GetHash($password, substr($u,40,8), '', $rev); + my $dat = ("\0" x 16) . $parm{UE}; + my $err = Image::ExifTool::AES::Crypt(\$dat, $key, 0, 1); + return $err if $err; + $key = $dat; # use this as the file decryption key + last; + } + } + } + $$encrypt{_key} = $key; # save the file-level encryption key + $cryptInfo = $encrypt; # save reference to the file-level Encrypt object + return undef; # success! +} + +#------------------------------------------------------------------------------ +# Decrypt/Encrypt data +# Inputs: 0) data ref +# 1) PDF object reference to use as crypt key extension (may be 'none' to +# avoid extending the encryption key, as for streams with Crypt Filter) +# 2) encrypt flag (false for decryption) +sub Crypt($$;$) +{ + return unless $cryptInfo; + my ($dataPt, $keyExt, $encrypt) = @_; + # do not decrypt if the key extension object is undefined + # (this doubles as a flag to disable decryption/encryption) + return unless defined $keyExt; + my $key = $$cryptInfo{_key}; + # apply the necessary crypt key extension + unless ($$cryptInfo{_aesv3}) { + unless ($keyExt eq 'none') { + # extend crypt key using object and generation number + unless ($keyExt =~ /^(I\d+ )?(\d+) (\d+)/) { + $$cryptInfo{_error} = 'Invalid object reference for encryption'; + return; + } + $key .= substr(pack('V', $2), 0, 3) . substr(pack('V', $3), 0, 2); + } + # add AES-128 salt if necessary (this little gem is conveniently + # omitted from the Adobe PDF 1.6 documentation, causing me to + # waste 12 hours trying to figure out why this wasn't working -- + # it appears in ISO32000 though, so I should have been using that) + $key .= 'sAlT' if $$cryptInfo{_aesv2}; + my $len = length($key); + $key = Digest::MD5::md5($key); # get 16-byte MD5 digest + $key = substr($key, 0, $len) if $len < 16; # trim if necessary + } + # perform the decryption/encryption + if ($$cryptInfo{_aesv2} or $$cryptInfo{_aesv3}) { + require Image::ExifTool::AES; + my $err = Image::ExifTool::AES::Crypt($dataPt, $key, $encrypt); + $err and $$cryptInfo{_error} = $err; + } else { + RC4Crypt($dataPt, $key); + } +} + +#------------------------------------------------------------------------------ +# Decrypt/Encrypt stream data +# Inputs: 0) dictionary ref, 1) PDF object reference to use as crypt key extension +sub CryptStream($$) +{ + return unless $cryptStream; + my ($dict, $keyExt) = @_; + my $type = $$dict{Type} || ''; + # XRef streams are not encrypted (ref 3, page 50), + # and Metadata may or may not be encrypted + if ($cryptInfo and $type ne '/XRef' and + ($$cryptInfo{_meta} or $type ne '/Metadata')) + { + Crypt(\$$dict{_stream}, $keyExt, $$dict{_decrypted}); + # toggle _decrypted flag + $$dict{_decrypted} = ($$dict{_decrypted} ? undef : 1); + } else { + $$dict{_decrypted} = 0; # stream should never be encrypted + } +} + +#------------------------------------------------------------------------------ +# Generate a new PDF tag (based on its ID) and add it to a tag table +# Inputs: 0) tag table ref, 1) tag ID +# Returns: tag info ref +sub NewPDFTag($$) +{ + my ($tagTablePtr, $tag) = @_; + my $name = $tag; + # translate URL-like escape sequences + $name =~ s/#([0-9a-f]{2})/chr(hex($1))/ige; + $name =~ s/[^-\w]+/_/g; # translate invalid characters to an underline + $name =~ s/(^|_)([a-z])/\U$2/g; # start words with upper case + my $tagInfo = { Name => $name }; + AddTagToTable($tagTablePtr, $tag, $tagInfo); + return $tagInfo; +} + +#------------------------------------------------------------------------------ +# Process AcroForm dictionary to set HasXMLFormsArchitecture flag +# Inputs: Same as ProcessDict +sub ProcessAcroForm($$$$;$$) +{ + my ($et, $tagTablePtr, $dict, $xref, $nesting, $type) = @_; + $et->HandleTag($tagTablePtr, '_has_xfa', $$dict{XFA} ? 'true' : 'false'); + return ProcessDict($et, $tagTablePtr, $dict, $xref, $nesting, $type); +} + +#------------------------------------------------------------------------------ +# Expand array into a string +# Inputs: 0) array ref +# Return: string +sub ExpandArray($) +{ + my $val = shift; + my @list = @$val; + foreach (@list) { + ref $_ eq 'SCALAR' and $_ = "ref($$_)", next; + ref $_ eq 'ARRAY' and $_ = ExpandArray($_), next; + defined $_ or $_ = '<undef>', next; + } + return '[' . join(',',@list) . ']'; +} + +#------------------------------------------------------------------------------ +# Process PDF dictionary extract tag values +# Inputs: 0) ExifTool object reference, 1) tag table reference +# 2) dictionary reference, 3) cross-reference table reference, +# 4) nesting depth, 5) dictionary capture type +sub ProcessDict($$$$;$$) +{ + my ($et, $tagTablePtr, $dict, $xref, $nesting, $type) = @_; + my $verbose = $et->Options('Verbose'); + my $unknown = $$tagTablePtr{EXTRACT_UNKNOWN}; + my $embedded = (defined $unknown and not $unknown and $et->Options('ExtractEmbedded')); + my @tags = @{$$dict{_tags}}; + my ($next, %join); + my $index = 0; + + $nesting = ($nesting || 0) + 1; + if ($nesting > 50) { + $et->WarnOnce('Nesting too deep (directory ignored)'); + return; + } + # save entire dictionary for rewriting if specified + if ($$et{PDF_CAPTURE} and $$tagTablePtr{VARS} and + $tagTablePtr->{VARS}->{CAPTURE}) + { + my $name; + foreach $name (@{$tagTablePtr->{VARS}->{CAPTURE}}) { + next if $$et{PDF_CAPTURE}{$name}; + # make sure we load the right type if indicated + next if $type and $type ne $name; + $$et{PDF_CAPTURE}{$name} = $dict; + last; + } + } +# +# extract information from all tags in the dictionary +# + for (;;) { + my ($tag, $isSubDoc); + if (@tags) { + $tag = shift @tags; + } elsif (defined $next and not $next) { + $tag = 'Next'; + $next = 1; + } else { + last; + } + my $val = $$dict{$tag}; + my $tagInfo = $et->GetTagInfo($tagTablePtr, $tag); + if ($tagInfo) { + undef $tagInfo if $$tagInfo{NoProcess}; + } elsif ($embedded and $tag =~ /^(.*?)(\d+)$/ and + $$tagTablePtr{$1} and (ref $val ne 'SCALAR' or not $fetched{$$val})) + { + my ($name, $num) = ($1, $2); + $tagInfo = $et->GetTagInfo($tagTablePtr, $name); + if (ref $tagInfo eq 'HASH' and $$tagInfo{JoinStreams}) { + $fetched{$$val} = 1; + my $obj = FetchObject($et, $$val, $xref, $tag); + $join{$name} = [] unless $join{$name}; + next unless ref $obj eq 'HASH' and $$obj{_stream}; + # save all the stream data to join later + DecodeStream($et, $obj); + $join{$name}->[$num] = $$obj{_stream}; + undef $tagInfo; # don't process + } else { + $isSubDoc = 1; # treat as a sub-document + } + } + if ($verbose) { + my ($val2, $extra); + if (ref $val eq 'SCALAR') { + $extra = ", indirect object ($$val)"; + if ($fetched{$$val}) { + $val2 = "ref($$val)"; + } elsif ($tag eq 'Next' and not $next) { + # handle 'Next' links after all others + $next = 0; + next; + } else { + $fetched{$$val} = 1; + $val = FetchObject($et, $$val, $xref, $tag); + unless (defined $val) { + my $str; + if (defined $lastOffset) { + $val2 = '<free>'; + $str = 'Object was freed'; + } else { + $val2 = '<err>'; + $str = 'Error reading object'; + } + $et->VPrint(0, "$$et{INDENT}${str}:\n"); + } + } + } elsif (ref $val eq 'HASH') { + $extra = ', direct dictionary'; + } elsif (ref $val eq 'ARRAY') { + $extra = ', direct array of ' . scalar(@$val) . ' objects'; + } else { + $extra = ', direct object'; + } + my $isSubdir; + if (ref $val eq 'HASH') { + $isSubdir = 1; + } elsif (ref $val eq 'ARRAY') { + # recurse into objects in arrays only if they are lists of + # dictionaries or indirect objects which could be dictionaries + $isSubdir = 1 if @$val; + foreach (@$val) { + next if ref $_ eq 'HASH' or ref $_ eq 'SCALAR'; + undef $isSubdir; + last; + } + } + if ($isSubdir) { + # create bogus subdirectory to recurse into this dict + $tagInfo or $tagInfo = { + Name => $tag, + SubDirectory => { TagTable => 'Image::ExifTool::PDF::Unknown' }, + }; + } else { + $val2 = ExpandArray($val) if ref $val eq 'ARRAY'; + # generate tag info if we will use it later + if (not $tagInfo and defined $val and $unknown) { + $tagInfo = NewPDFTag($tagTablePtr, $tag); + } + } + $et->VerboseInfo($tag, $tagInfo, + Value => $val2 || $val, + Extra => $extra, + Index => $index++, + ); + next unless defined $val; + } + unless ($tagInfo) { + # add any tag found in Info dictionary to table + next unless $unknown; + $tagInfo = NewPDFTag($tagTablePtr, $tag); + } + # increment document number if necessary + my ($oldDocNum, $oldNumTags); + if ($isSubDoc) { + $oldDocNum = $$et{DOC_NUM}; + $oldNumTags = $$et{NUM_FOUND}; + $$et{DOC_NUM} = ++$$et{DOC_COUNT}; + } + if ($$tagInfo{SubDirectory}) { + # process the subdirectory + my @subDicts; + if (ref $val eq 'ARRAY') { + @subDicts = @{$val}; + } else { + @subDicts = ( $val ); + } + # loop through all values of this tag + for (;;) { + my $subDict = shift @subDicts or last; + # save last fetched object in case we fetch another one here + my $prevFetched = $lastFetched; + if (ref $subDict eq 'SCALAR') { + # only fetch once (other copies are obsolete) + next if $fetched{$$subDict}; + if ($$tagInfo{IgnoreDuplicates}) { + my $flag = "ProcessedPDF_$tag"; + if ($$et{$flag}) { + next if $et->WarnOnce("Ignored duplicate $tag dictionary", 2); + } else { + $$et{$flag} = 1; + } + } + # load dictionary via an indirect reference + $fetched{$$subDict} = 1; + my $obj = FetchObject($et, $$subDict, $xref, $tag); + unless (defined $obj) { + unless (defined $lastOffset) { + $et->Warn("Error reading $tag object ($$subDict)"); + } + next; + } + $subDict = $obj; + } + if (ref $subDict eq 'ARRAY') { + # convert array of key/value pairs to a hash + next if @$subDict < 2; + my %hash = ( _tags => [] ); + while (@$subDict >= 2) { + my $key = shift @$subDict; + $key =~ s/^\///; + push @{$hash{_tags}}, $key; + $hash{$key} = shift @$subDict; + } + $subDict = \%hash; + } else { + next unless ref $subDict eq 'HASH'; + } + # set flag to re-crypt all strings when rewriting if the dictionary + # came from an encrypted stream + $$subDict{_needCrypt}{'*'} = 1 unless $lastFetched; + my $subTablePtr = GetTagTable($tagInfo->{SubDirectory}->{TagTable}); + if (not $verbose) { + my $proc = $$subTablePtr{PROCESS_PROC} || \&ProcessDict; + &$proc($et, $subTablePtr, $subDict, $xref, $nesting); + } elsif ($next) { + # handle 'Next' links at this level to avoid deep recursion + undef $next; + $index = 0; + $tagTablePtr = $subTablePtr; + $dict = $subDict; + @tags = @{$$subDict{_tags}}; + $et->VerboseDir($tag, scalar(@tags)); + } else { + my $oldIndent = $$et{INDENT}; + my $oldDir = $$et{DIR_NAME}; + $$et{INDENT} .= '| '; + $$et{DIR_NAME} = $tag; + $et->VerboseDir($tag, scalar(@{$$subDict{_tags}})); + ProcessDict($et, $subTablePtr, $subDict, $xref, $nesting); + $$et{INDENT} = $oldIndent; + $$et{DIR_NAME} = $oldDir; + } + $lastFetched = $prevFetched; + } + } else { + # fetch object if necessary + # (OS X 10.6 writes indirect objects in the Info dictionary!) + if (ref $val eq 'SCALAR') { + my $prevFetched = $lastFetched; + # (note: fetching the same object multiple times is OK here) + $val = FetchObject($et, $$val, $xref, $tag); + if (defined $val) { + $val = ReadPDFValue($val); + # set flag to re-encrypt if necessary if rewritten + $$dict{_needCrypt}{$tag} = ($lastFetched ? 0 : 1) if $cryptString; + $lastFetched = $prevFetched; # restore last fetched object reference + } + } else { + $val = ReadPDFValue($val); + } + # convert from UTF-16 (big endian) to UTF-8 or Latin if necessary + # unless this is binary data (hex-encoded strings would not have been converted) + if (ref $val) { + if (ref $val eq 'ARRAY') { + my $v; + foreach $v (@$val) { + $et->FoundTag($tagInfo, $v); + } + } + } elsif (defined $val) { + my $format = $$tagInfo{Format} || $$tagInfo{Writable} || 'string'; + $val = ConvertPDFDate($val) if $format eq 'date'; + if (not $$tagInfo{Binary} and $val =~ /[\x18-\x1f\x80-\xff]/) { + # text string is already in Unicode if it starts with "\xfe\xff", + # otherwise we must first convert from PDFDocEncoding + $val = $et->Decode($val, ($val=~s/^\xfe\xff// ? 'UCS2' : 'PDFDoc'), 'MM'); + } + if ($$tagInfo{List} and not $$et{OPTIONS}{NoPDFList}) { + # separate tokens in comma or whitespace delimited lists + my @values = ($val =~ /,/) ? split /,+\s*/, $val : split ' ', $val; + foreach $val (@values) { + $et->FoundTag($tagInfo, $val); + } + } else { + # a simple tag value + $et->FoundTag($tagInfo, $val); + } + } + } + if ($isSubDoc) { + # restore original document number + $$et{DOC_NUM} = $oldDocNum; + --$$et{DOC_COUNT} if $oldNumTags == $$et{NUM_FOUND}; + } + } +# +# extract information from joined streams if necessary +# + + if (%join) { + my ($tag, $i); + foreach $tag (sort keys %join) { + my $list = $join{$tag}; + last unless defined $$list[1] and $$list[1] =~ /^%.*?([\x0d\x0a]*)/; + my $buff = "%!PS-Adobe-3.0$1"; # add PS header with same line break + for ($i=1; defined $$list[$i]; ++$i) { + $buff .= $$list[$i]; + undef $$list[$i]; # free memory + } + # increment document number for tags extracted from embedded EPS + my $oldDocNum = $$et{DOC_NUM}; + my $oldNumTags = $$et{NUM_FOUND}; + $$et{DOC_NUM} = ++$$et{DOC_COUNT}; + # extract PostScript information + $et->HandleTag($tagTablePtr, $tag, $buff); + $$et{DOC_NUM} = $oldDocNum; + # revert document counter if we didn't add any new tags + --$$et{DOC_COUNT} if $oldNumTags == $$et{NUM_FOUND}; + delete $$et{DOC_NUM}; + } + } +# +# extract information from stream object if it exists (eg. Metadata stream) +# + for (;;) { # (cheap goto) + last unless $$dict{_stream}; + my $tag = '_stream'; + # add Subtype (if it exists) to stream name and remove leading '/' + ($tag = $$dict{Subtype} . $tag) =~ s/^\/// if $$dict{Subtype}; + last unless $$tagTablePtr{$tag}; + my $tagInfo = $et->GetTagInfo($tagTablePtr, $tag) or last; + unless ($$tagInfo{SubDirectory}) { + # don't build filter lists across different images + delete $$et{LIST_TAGS}{$$tagTablePtr{Filter}}; + # we arrive here only when extracting embedded images + # - only extract known image types and ignore others + my $filter = $$dict{Filter} || ''; + $filter = @$filter[-1] if ref $filter eq 'ARRAY'; # (get last Filter type) + my $result; + if ($filter eq '/DCTDecode' or $filter eq '/JPXDecode') { + DecodeStream($et, $dict) or last; + # save the image itself + $et->FoundTag($tagInfo, \$$dict{_stream}); + # extract information from embedded image + $result = $et->ExtractInfo(\$$dict{_stream}, { ReEntry => 1 }); + } + unless ($result) { + $et->FoundTag('FileType', defined $result ? '(unknown)' : '(unsupported)'); + } + last; + } + # decode stream if necessary + DecodeStream($et, $dict) or last; + if ($verbose > 2) { + $et->VPrint(2,"$$et{INDENT}$$et{DIR_NAME} stream data\n"); + $et->VerboseDump(\$$dict{_stream}); + } + # extract information from stream + my %dirInfo = ( + DataPt => \$$dict{_stream}, + DataLen => length $$dict{_stream}, + DirStart => 0, + DirLen => length $$dict{_stream}, + Parent => 'PDF', + ); + my $subTablePtr = GetTagTable($tagInfo->{SubDirectory}->{TagTable}); + unless ($et->ProcessDirectory(\%dirInfo, $subTablePtr)) { + $et->Warn("Error processing $$tagInfo{Name} information"); + } + last; + } +} + +#------------------------------------------------------------------------------ +# Extract information from PDF file +# Inputs: 0) ExifTool object reference, 1) dirInfo reference +# Returns: 0 if not a PDF file, 1 on success, otherwise a negative error number +sub ReadPDF($$) +{ + my ($et, $dirInfo) = @_; + my $raf = $$dirInfo{RAF}; + my $verbose = $et->Options('Verbose'); + my ($buff, $encrypt, $id); +# +# validate PDF file +# + # (linearization dictionary must be in the first 1024 bytes of the file) + $raf->Read($buff, 1024) >= 8 or return 0; + $buff =~ /^(\s*)%PDF-(\d+\.\d+)/ or return 0; + $$et{PDFBase} = length $1 and $et->Warn('PDF header is not at start of file',1); + $pdfVer = $2; + $et->SetFileType(); # set the FileType tag + $et->Warn("May not be able to read a PDF version $pdfVer file") if $pdfVer >= 2.0; + # store PDFVersion tag + my $tagTablePtr = GetTagTable('Image::ExifTool::PDF::Root'); + $et->HandleTag($tagTablePtr, 'Version', $pdfVer); + $tagTablePtr = GetTagTable('Image::ExifTool::PDF::Main'); +# +# check for a linearized PDF (only if reading) +# + my $capture = $$et{PDF_CAPTURE}; + unless ($capture) { + my $lin = 'false'; + if ($buff =~ /<</g) { + $buff = substr($buff, pos($buff) - 2); + my $dict = ExtractObject($et, \$buff); + if (ref $dict eq 'HASH' and $$dict{Linearized} and $$dict{L}) { + if (not $$et{VALUE}{FileSize}) { + undef $lin; # can't determine if it is linearized + } elsif ($$dict{L} == $$et{VALUE}{FileSize} - $$et{PDFBase}) { + $lin = 'true'; + } + } + } + $et->HandleTag($tagTablePtr, '_linearized', $lin) if $lin; + } +# +# read the xref tables referenced from startxref at the end of the file +# + my @xrefOffsets; + $raf->Seek(0, 2) or return -2; + # the %%EOF must occur within the last 1024 bytes of the file (PDF spec, appendix H) + my $len = $raf->Tell(); + $len = 1024 if $len > 1024; + $raf->Seek(-$len, 2) or return -2; + $raf->Read($buff, $len) == $len or return -3; + # find the LAST xref table in the file (may be multiple %%EOF marks, + # and comments between "startxref" and "%%EOF") + $buff =~ /^.*startxref(\s+)(\d+)(\s+)(%[^\x0d\x0a]*\s+)*%%EOF/s or return -4; + my $ws = $1 . $3; + my $xr = $2; + push @xrefOffsets, $xr, 'Main'; + # set input record separator + local $/ = $ws =~ /(\x0d\x0a|\x0d|\x0a)/ ? $1 : "\x0a"; + my (%xref, @mainDicts, %loaded, $mainFree); + # initialize variables to capture when rewriting + if ($capture) { + $capture->{startxref} = $xr; + $capture->{xref} = \%xref; + $capture->{newline} = $/; + $capture->{mainFree} = $mainFree = { }; + } +XRef: + while (@xrefOffsets) { + my $offset = shift @xrefOffsets; + my $type = shift @xrefOffsets; + next if $loaded{$offset}; # avoid infinite recursion + unless ($raf->Seek($offset+$$et{PDFBase}, 0)) { + %loaded or return -5; + $et->Warn('Bad offset for secondary xref table'); + next; + } + # Note: care must be taken because ReadLine may read more than we want if + # the newline sequence for this table is different than the rest of the file + for (;;) { + unless ($raf->ReadLine($buff)) { + %loaded or return -6; + $et->Warn('Bad offset for secondary xref table'); + next XRef; + } + last if $buff =~/\S/; # skip blank lines + } + my $loadXRefStream; + if ($buff =~ s/^\s*xref\s+//s) { + # load xref table + for (;;) { + # read another line if necessary (skipping blank lines) + $raf->ReadLine($buff) or return -6 until $buff =~ /\S/; + last if $buff =~ s/^\s*trailer([\s<[(])/$1/s; + $buff =~ s/^\s*(\d+)\s+(\d+)\s+//s or return -4; + my ($start, $num) = ($1, $2); + $raf->Seek(-length($buff), 1) or return -4; + my $i; + for ($i=0; $i<$num; ++$i) { + $raf->Read($buff, 20) == 20 or return -6; + $buff =~ /^\s*(\d{10}) (\d{5}) (f|n)/s or return -4; + my $num = $start + $i; + # locate object to generate entry from stream if necessary + # (must do this before we test $xref{$num}) + LocateAnyObject(\%xref, $num) if $xref{dicts}; + # save offset for newest copy of all objects + # (or next object number for free objects) + unless (defined $xref{$num}) { + my ($offset, $gen) = (int($1), int($2)); + $xref{$num} = $offset; + if ($3 eq 'f') { + # save free objects in last xref table for rewriting + $$mainFree{$num} = [ $offset, $gen, 'f' ] if $mainFree; + next; + } + # also save offset keyed by object reference string + $xref{"$num $gen R"} = $offset; + } + } + # (I have a sample from Adobe which has an empty xref table) + # %xref or return -4; # xref table may not be empty + $buff = ''; + } + undef $mainFree; # only do this for the last xref table + } elsif ($buff =~ s/^\s*(\d+)\s+(\d+)\s+obj//s) { + # this is a PDF-1.5 cross-reference stream dictionary + $loadXRefStream = 1; + } else { + %loaded or return -4; + $et->Warn('Invalid secondary xref table'); + next; + } + my $mainDict = ExtractObject($et, \$buff, $raf, \%xref); + unless (ref $mainDict eq 'HASH') { + %loaded or return -8; + $et->Warn('Error loading secondary dictionary'); + next; + } + if ($loadXRefStream) { + # decode and save our XRef stream from PDF-1.5 file + # (but parse it later as required to save time) + # Note: this technique can potentially result in an old object + # being used if the file was incrementally updated and an older + # object from an xref table was replaced by a newer object in an + # xref stream. But doing so isn't a good idea (if allowed at all) + # because a PDF 1.4 consumer would also make this same mistake. + if ($$mainDict{Type} eq '/XRef' and $$mainDict{W} and + @{$$mainDict{W}} > 2 and $$mainDict{Size} and + DecodeStream($et, $mainDict)) + { + # create Index entry if it doesn't exist + $$mainDict{Index} or $$mainDict{Index} = [ 0, $$mainDict{Size} ]; + # create '_entry_size' entry for internal use + my $w = $$mainDict{W}; + my $size = 0; + foreach (@$w) { $size += $_; } + $$mainDict{_entry_size} = $size; + # save this stream dictionary to use later if required + $xref{dicts} = [] unless $xref{dicts}; + push @{$xref{dicts}}, $mainDict; + } else { + %loaded or return -9; + $et->Warn('Invalid xref stream in secondary dictionary'); + } + } + $loaded{$offset} = 1; + # load XRef stream in hybrid file if it exists + push @xrefOffsets, $$mainDict{XRefStm}, 'XRefStm' if $$mainDict{XRefStm}; + $encrypt = $$mainDict{Encrypt} if $$mainDict{Encrypt}; + if ($$mainDict{ID} and ref $$mainDict{ID} eq 'ARRAY') { + $id = ReadPDFValue($mainDict->{ID}->[0]); + } + push @mainDicts, $mainDict, $type; + # load previous xref table if it exists + push @xrefOffsets, $$mainDict{Prev}, 'Prev' if $$mainDict{Prev}; + } +# +# extract encryption information if necessary +# + if ($encrypt) { + if (ref $encrypt eq 'SCALAR') { + $encrypt = FetchObject($et, $$encrypt, \%xref, 'Encrypt'); + } + # generate Encryption tag information + my $err = DecryptInit($et, $encrypt, $id); + if ($err) { + $et->Warn($err); + $$capture{Error} = $err if $capture; + return -1; + } + } +# +# extract the information beginning with each of the main dictionaries +# + my $i = 0; + my $num = (scalar @mainDicts) / 2; + while (@mainDicts) { + my $dict = shift @mainDicts; + my $type = shift @mainDicts; + if ($verbose) { + ++$i; + my $n = scalar(@{$$dict{_tags}}); + $et->VPrint(0, "PDF dictionary ($i of $num) with $n entries:\n"); + } + ProcessDict($et, $tagTablePtr, $dict, \%xref, 0, $type); + } + # handle any decryption errors + if ($encrypt) { + my $err = $$encrypt{_error}; + if ($err) { + $et->Warn($err); + $$capture{Error} = $err if $capture; + return -1; + } + } + return 1; +} + +#------------------------------------------------------------------------------ +# ReadPDF() warning strings for each error return value +my %pdfWarning = ( + # -1 is reserved as error return value with no associated warning + -2 => 'Error seeking in file', + -3 => 'Error reading file', + -4 => 'Invalid xref table', + -5 => 'Invalid xref offset', + -6 => 'Error reading xref table', + -7 => 'Error reading trailer', + -8 => 'Error reading main dictionary', + -9 => 'Invalid xref stream in main dictionary', +); + +#------------------------------------------------------------------------------ +# Extract information from PDF file +# Inputs: 0) ExifTool object reference, 1) dirInfo reference +# Returns: 1 if this was a valid PDF file +sub ProcessPDF($$) +{ + my ($et, $dirInfo) = @_; + + undef $cryptInfo; # (must not delete after returning so writer can use it) + undef $cryptStream; + undef $cryptString; + my $result = ReadPDF($et, $dirInfo); + if ($result < 0) { + $et->Warn($pdfWarning{$result}) if $pdfWarning{$result}; + $result = 1; + } + # clean up and return + undef %streamObjs; + undef %fetched; + return $result; +} + +1; # end + + +__END__ + +=head1 NAME + +Image::ExifTool::PDF - Read PDF meta information + +=head1 SYNOPSIS + +This module is loaded automatically by Image::ExifTool when required. + +=head1 DESCRIPTION + +This code reads meta information from PDF (Adobe Portable Document Format) +files. It supports object streams introduced in PDF-1.5 but only with a +limited set of Filter and Predictor algorithms, however all standard +encryption methods through PDF-1.7 extension level 3 are supported, +including AESV2 (AES-128) and AESV3 (AES-256). + +=head1 AUTHOR + +Copyright 2003-2019, Phil Harvey (phil at owl.phy.queensu.ca) + +This library is free software; you can redistribute it and/or modify it +under the same terms as Perl itself. + +=head1 REFERENCES + +=over 4 + +=item L<http://partners.adobe.com/public/developer/pdf/index_reference.html> + +=item L<Crypt::RC4|Crypt::RC4> + +=item L<http://www.adobe.com/devnet/acrobat/pdfs/PDF32000_2008.pdf> + +=item L<http://www.adobe.com/content/dam/Adobe/en/devnet/pdf/pdfs/adobe_supplement_iso32000.pdf> + +=item L<http://tools.ietf.org/search/rfc3454> + +=item L<http://www.armware.dk/RFC/rfc/rfc4013.html> + +=back + +=head1 SEE ALSO + +L<Image::ExifTool::TagNames/PDF Tags>, +L<Image::ExifTool(3pm)|Image::ExifTool> + +=cut diff --git a/lib/Image/ExifTool/PGF.pm b/lib/Image/ExifTool/PGF.pm new file mode 100644 index 0000000..2af84c1 --- /dev/null +++ b/lib/Image/ExifTool/PGF.pm @@ -0,0 +1,143 @@ +#------------------------------------------------------------------------------ +# File: PGF.pm +# +# Description: Read Progressive Graphics File meta information +# +# Revisions: 2011/01/25 - P. Harvey Created +# +# References: 1) http://www.libpgf.org/ +# 2) http://www.exiv2.org/ +#------------------------------------------------------------------------------ + +package Image::ExifTool::PGF; + +use strict; +use vars qw($VERSION); +use Image::ExifTool qw(:DataAccess :Utils); + +$VERSION = '1.02'; + +# PGF header information +%Image::ExifTool::PGF::Main = ( + GROUPS => { 0 => 'File', 1 => 'File', 2 => 'Image' }, + PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData, + PRIORITY => 2, # (to take precedence over PNG tags from embedded image) + NOTES => q{ + The following table lists information extracted from the header of + Progressive Graphics File (PGF) images. As well, information is extracted + from the embedded PNG metadata image if it exists. See + L<http://www.libpgf.org/> for the PGF specification. + }, + 3 => { + Name => 'PGFVersion', + PrintConv => 'sprintf("0x%.2x", $val)', + # this is actually a bitmask (ref digikam PGFtypes.h): + # 0x02 - data structure PGFHeader of major version 2 + # 0x04 - 32-bit values + # 0x08 - supports regions of interest + # 0x10 - new coding scheme since major version 5 + # 0x20 - new HeaderSize: 32 bits instead of 16 bits + }, + 8 => { Name => 'ImageWidth', Format => 'int32u' }, + 12 => { Name => 'ImageHeight', Format => 'int32u' }, + 16 => 'PyramidLevels', + 17 => 'Quality', + 18 => 'BitsPerPixel', + 19 => 'ColorComponents', + 20 => { + Name => 'ColorMode', + RawConv => '$$self{PGFColorMode} = $val', + PrintConvColumns => 2, + PrintConv => { + 0 => 'Bitmap', + 1 => 'Grayscale', + 2 => 'Indexed', + 3 => 'RGB', + 4 => 'CMYK', + 7 => 'Multichannel', + 8 => 'Duotone', + 9 => 'Lab', + }, + }, + 21 => { Name => 'BackgroundColor', Format => 'int8u[3]' }, +); + +#------------------------------------------------------------------------------ +# Extract information from a PGF image +# Inputs: 0) ExifTool object reference, 1) dirInfo reference +# Returns: 1 on success, 0 if this wasn't a valid PGF file +sub ProcessPGF($$) +{ + my ($et, $dirInfo) = @_; + my $raf = $$dirInfo{RAF}; + my $buff; + + # read header and check magic number + return 0 unless $raf->Read($buff, 24) == 24 and $buff =~ /^PGF(.)/s; + my $ver = ord $1; + $et->SetFileType(); + SetByteOrder('II'); + + # currently support only version 0x36 + unless ($ver == 0x36) { + $et->Error(sprintf('Unsupported PGF version 0x%.2x', $ver)); + return 1; + } + # extract information from the PGF header + my $tagTablePtr = GetTagTable('Image::ExifTool::PGF::Main'); + $et->ProcessDirectory({ DataPt => \$buff, DataPos => 0 }, $tagTablePtr); + + my $len = Get32u(\$buff, 4) - 16; # length of post-header data + + # skip colour table if necessary + $len -= $raf->Seek(1024, 1) ? 1024 : $len if $$et{PGFColorMode} == 2; + + # extract information from the embedded metadata image (PNG format) + if ($len > 0 and $len < 0x1000000 and $raf->Read($buff, $len) == $len) { + $et->ExtractInfo(\$buff, { ReEntry => 1 }); + } + return 1; +} + + +1; # end + +__END__ + +=head1 NAME + +Image::ExifTool::PGF - Read Progressive Graphics File meta information + +=head1 SYNOPSIS + +This module is used by Image::ExifTool + +=head1 DESCRIPTION + +This module contains definitions required by Image::ExifTool to extract meta +information from Progressive Graphics File (PGF) images. + +=head1 AUTHOR + +Copyright 2003-2019, Phil Harvey (phil at owl.phy.queensu.ca) + +This library is free software; you can redistribute it and/or modify it +under the same terms as Perl itself. + +=head1 REFERENCES + +=over 4 + +=item L<http://www.libpgf.org/> + +=item L<http://www.exiv2.org/> + +=back + +=head1 SEE ALSO + +L<Image::ExifTool::TagNames/PGF Tags>, +L<Image::ExifTool(3pm)|Image::ExifTool> + +=cut + diff --git a/lib/Image/ExifTool/PICT.pm b/lib/Image/ExifTool/PICT.pm new file mode 100644 index 0000000..7441d70 --- /dev/null +++ b/lib/Image/ExifTool/PICT.pm @@ -0,0 +1,1260 @@ +#------------------------------------------------------------------------------ +# File: PICT.pm +# +# Description: Read PICT meta information +# +# Revisions: 10/10/2005 - P. Harvey Created +# +# Notes: Extraction of PICT opcodes is still experimental +# +# - size difference in PixPat color table?? (imagemagick reads only 1 long per entry) +# - other differences in the way imagemagick reads 16-bit images +# +# References: 1) http://developer.apple.com/documentation/mac/QuickDraw/QuickDraw-2.html +# 2) http://developer.apple.com/documentation/QuickTime/INMAC/QT/iqImageCompMgr.a.htm +#------------------------------------------------------------------------------ + +package Image::ExifTool::PICT; + +use strict; +use vars qw($VERSION); +use Image::ExifTool qw(:DataAccess :Utils); + +$VERSION = '1.05'; + +sub ReadPictValue($$$;$); + +my ($vers, $extended); # PICT version number, and extended flag +my ($verbose, $out, $indent); # used in verbose mode + +# ranges of reserved opcodes. +# opcodes at the start of each range must be defined in the tag table +my @reserved = ( + 0x0017 => 0x0019, 0x0024 => 0x0027, 0x0035 => 0x0037, 0x003d => 0x003f, + 0x0045 => 0x0047, 0x004d => 0x004f, 0x0055 => 0x0057, 0x005d => 0x005f, + 0x0065 => 0x0067, 0x006d => 0x006f, 0x0075 => 0x0077, 0x007d => 0x007f, + 0x0085 => 0x0087, 0x008d => 0x008f, 0x0092 => 0x0097, 0x00a2 => 0x00af, + 0x00b0 => 0x00cf, 0x00d0 => 0x00fe, 0x0100 => 0x01ff, 0x0300 => 0x0bfe, + 0x0c01 => 0x7eff, 0x7f00 => 0x7fff, 0x8000 => 0x80ff, 0x8100 => 0x81ff, + 0x8201 => 0xffff, +); + +# Apple data structures in PICT images +my %structs = ( + Arc => [ + rect => 'Rect', + startAng => 'int16s', + arcAng => 'int16s', + ], + BitMap => [ + # (no baseAddr) + rowBytes => 'int16u', + bounds => 'Rect', + ], + # BitsRect data for PICT version 1 + BitsRect1 => [ + bitMap => 'BitMap', + srcRect => 'Rect', + dstRect => 'Rect', + mode => 'int16u', + dataSize => 'int16u', + bitData => 'binary[$val{dataSize}]', + ], + # BitsRect data for PICT version 2 + BitsRect2 => [ + pixMap => 'PixMap', + colorTable => 'ColorTable', + srcRect => 'Rect', + dstRect => 'Rect', + mode => 'int16u', + pixData => \ 'GetPixData($val{pixMap}, $raf)', + ], + # BitsRgn data for PICT version 1 + BitsRgn1 => [ + bitMap => 'BitMap', + srcRect => 'Rect', + dstRect => 'Rect', + mode => 'int16u', + maskRgn => 'Rgn', + dataSize => 'int16u', + bitData => 'binary[$val{dataSize}]', + ], + # BitsRgn data for PICT version 2 + BitsRgn2 => [ + pixMap => 'PixMap', + colorTable => 'ColorTable', + srcRect => 'Rect', + dstRect => 'Rect', + mode => 'int16u', + maskRgn => 'Rgn', + pixData => \ 'GetPixData($val{pixMap}, $raf)', + ], + ColorSpec => [ + value => 'int16u', + rgb => 'RGBColor', + ], + ColorTable => [ + ctSeed => 'int32u', + ctFlags => 'int16u', + ctSize => 'int16u', + ctTable => 'ColorSpec[$val{ctSize}+1]', + ], + # http://developer.apple.com/documentation/QuickTime/INMAC/QT/iqImageCompMgr.a.htm + CompressedQuickTime => [ + size => 'int32u', # size NOT including size word + version => 'int16u', + matrix => 'int32u[9]', + matteSize => 'int32u', + matteRect => 'Rect', + mode => 'int16u', + srcRect => 'Rect', + accuracy => 'int32u', + maskSize => 'int32u', + matteDescr => 'Int32uData[$val{matteSize} ? 1 : 0]', + matteData => 'int8u[$val{matteSize}]', + maskRgn => 'int8u[$val{maskSize}]', + imageDescr => 'ImageDescription', + # size should be $val{imageDescr}->{dataSize}, but this is unreliable + imageData => q{binary[$val{size} - 68 - $val{maskSize} - $val{imageDescr}->{size} - + ($val{matteSize} ? $val{mattSize} + $val{matteDescr}->{size} : 0)] + }, + ], + DirectBitsRect => [ + baseAddr => 'int32u', + pixMap => 'PixMap', + srcRect => 'Rect', + dstRect => 'Rect', + mode => 'int16u', + pixData => \ 'GetPixData($val{pixMap}, $raf)', + ], + DirectBitsRgn => [ + baseAddr => 'int32u', + pixMap => 'PixMap', + srcRect => 'Rect', + dstRect => 'Rect', + mode => 'int16u', + maskRgn => 'Rgn', + pixData => \ 'GetPixData($val{pixMap}, $raf)', + ], + # http://developer.apple.com/technotes/qd/qd_01.html + FontName => [ + size => 'int16u', # size NOT including size word + oldFontID => 'int16u', + nameLen => 'int8u', + fontName => 'string[$val{nameLen}]', + padding => 'binary[$val{size} - $val{nameLen} - 3]', + ], + # http://developer.apple.com/documentation/QuickTime/APIREF/imagedescription.htm + ImageDescription => [ + size => 'int32u', # size INCLUDING size word + cType => 'string[4]', + res1 => 'int32u', + res2 => 'int16u', + dataRefIndex => 'int16u', + version => 'int16u', + revision => 'int16u', + vendor => 'string[4]', + temporalQuality => 'int32u', + quality => 'int32u', + width => 'int16u', + height => 'int16u', + hRes => 'fixed32u', + vRes => 'fixed32u', + dataSize => 'int32u', + frameCount => 'int16u', + nameLen => 'int8u', + compressor => 'string[31]', + depth => 'int16u', + clutID => 'int16u', + clutData => 'binary[$val{size}-86]', + ], + Int8uText => [ + val => 'int8u', + count => 'int8u', + text => 'string[$val{count}]', + ], + Int8u2Text => [ + val => 'int8u[2]', + count => 'int8u', + text => 'string[$val{count}]', + ], + Int16Data => [ + size => 'int16u', # size NOT including size word + data => 'int8u[$val{size}]', + ], + Int32uData => [ + size => 'int32u', # size NOT including size word + data => 'int8u[$val{size}]', + ], + LongComment => [ + kind => 'int16u', + size => 'int16u', # size of data only + data => 'binary[$val{size}]', + ], + PixMap => [ + # Note: does not contain baseAddr + # (except for DirectBits opcodes in which it is loaded separately) + rowBytes => 'int16u', + bounds => 'Rect', + pmVersion => 'int16u', + packType => 'int16u', + packSize => 'int32u', + hRes => 'fixed32s', + vRes => 'fixed32s', + pixelType => 'int16u', + pixelSize => 'int16u', + cmpCount => 'int16u', + cmpSize => 'int16u', + planeBytes => 'int32u', + pmTable => 'int32u', + pmReserved => 'int32u', + ], + PixPat => [ + patType => 'int16u', # 1 = non-dithered, 2 = dithered + pat1Data => 'int8u[8]', + # dithered PixPat has RGB entry + RGB => 'RGBColor[$val{patType} == 2 ? 1 : 0]', + # non-dithered PixPat has other stuff instead + nonDithered=> 'PixPatNonDithered[$val{patType} == 2 ? 0 : 1]', + ], + PixPatNonDithered => [ + pixMap => 'PixMap', + colorTable => 'ColorTable', + pixData => \ 'GetPixData($val{pixMap}, $raf)', + ], + Point => [ + v => 'int16s', + h => 'int16s', + ], + PointText => [ + txLoc => 'Point', + count => 'int8u', + text => 'string[$val{count}]', + ], + Polygon => [ + polySize => 'int16u', + polyBBox => 'Rect', + polyPoints => 'int16u[($val{polySize}-10)/2]', + ], + Rect => [ + topLeft => 'Point', + botRight => 'Point', + ], + RGBColor => [ + red => 'int16u', + green => 'int16u', + blue => 'int16u', + ], + Rgn => [ + rgnSize => 'int16u', + rgnBBox => 'Rect', + data => 'int8u[$val{rgnSize}-10]', + ], + ShortLine => [ + pnLoc => 'Point', + dh => 'int8s', + dv => 'int8s', + ], + # http://developer.apple.com/documentation/QuickTime/INMAC/QT/iqImageCompMgr.a.htm + UncompressedQuickTime => [ + size => 'int32u', # size NOT including size word + version => 'int16u', + matrix => 'int32u[9]', + matteSize => 'int32u', + matteRect => 'Rect', + matteDescr => 'Int32uData[$val{matteSize} ? 1 : 0]', + matteData => 'binary[$val{matteSize}]', + subOpcodeData => q{ + binary[ $val{size} - 50 - + ($val{matteSize} ? $val{mattSize} + $val{matteDescr}->{size} : 0)] + }, + ], +); + +# PICT image opcodes +%Image::ExifTool::PICT::Main = ( + VARS => { NO_LOOKUP => 1 }, # omit tags from lookup + NOTES => q{ +The PICT format contains no true meta information, except for the possible +exception of the LongComment opcode. By default, only ImageWidth, +ImageHeight and X/YResolution are extracted from a PICT image. Tags in the +following table represent image opcodes. Extraction of these tags is +experimental, and is only enabled with the Verbose or Unknown options. + }, + 0x0000 => { + Name => 'Nop', + Description => 'No Operation', + Format => 'null', + }, + 0x0001 => { + Name => 'ClipRgn', + Description => 'Clipping Region', + Format => 'Rgn', + }, + 0x0002 => { + Name => 'BkPat', + Description => 'Background Pattern', + Format => 'int8u[8]', + }, + 0x0003 => { + Name => 'TxFont', + Description => 'Font Number', + Format => 'int16u', + }, + 0x0004 => { + Name => 'TxFace', + Description => 'Text Font Style', + Format => 'int8u', + }, + 0x0005 => { + Name => 'TxMode', + Description => 'Text Source Mode', + Format => 'int16u', + }, + 0x0006 => { + Name => 'SpExtra', + Description => 'Extra Space', + Format => 'fixed32s', + }, + 0x0007 => { + Name => 'PnSize', + Description => 'Pen Size', + Format => 'Point', + }, + 0x0008 => { + Name => 'PnMode', + Description => 'Pen Mode', + Format => 'int16u', + }, + 0x0009 => { + Name => 'PnPat', + Description => 'Pen Pattern', + Format => 'int8u[8]', + }, + 0x000a => { + Name => 'FillPat', + Description => 'Fill Pattern', + Format => 'int8u[8]', + }, + 0x000b => { + Name => 'OvSize', + Description => 'Oval Size', + Format => 'Point', + }, + 0x000c => { + Name => 'Origin', + Format => 'Point', + }, + 0x000d => { + Name => 'TxSize', + Description => 'Text Size', + Format => 'int16u', + }, + 0x000e => { + Name => 'FgColor', + Description => 'Foreground Color', + Format => 'int32u', + }, + 0x000f => { + Name => 'BkColor', + Description => 'Background Color', + Format => 'int32u', + }, + 0x0010 => { + Name => 'TxRatio', + Description => 'Text Ratio', + Format => 'Rect', + }, + 0x0011 => { + Name => 'VersionOp', + Description => 'Version', + Format => 'int8u', + }, + 0x0012 => { + Name => 'BkPixPat', + Description => 'Background Pixel Pattern', + Format => 'PixPat', + }, + 0x0013 => { + Name => 'PnPixPat', + Description => 'Pen Pixel Pattern', + Format => 'PixPat', + }, + 0x0014 => { + Name => 'FillPixPat', + Description => 'Fill Pixel Pattern', + Format => 'PixPat', + }, + 0x0015 => { + Name => 'PnLocHFrac', + Description => 'Fractional Pen Position', + Format => 'int16u', + }, + 0x0016 => { + Name => 'ChExtra', + Description => 'Added Width for NonSpace Characters', + Format => 'int16u', + }, + 0x0017 => { + Name => 'Reserved', + Format => 'Unknown', + }, + 0x001a => { + Name => 'RGBFgCol', + Description => 'Foreground Color', + Format => 'RGBColor', + }, + 0x001b => { + Name => 'RGBBkCol', + Description => 'Background Color', + Format => 'RGBColor', + }, + 0x001c => { + Name => 'HiliteMode', + Description => 'Highlight Mode Flag', + Format => 'null', + }, + 0x001d => { + Name => 'HiliteColor', + Description => 'Highlight Color', + Format => 'RGBColor', + }, + 0x001e => { + Name => 'DefHilite', + Description => 'Use Default Highlight Color', + Format => 'null', + }, + 0x001f => { + Name => 'OpColor', + Format => 'RGBColor', + }, + 0x0020 => { + Name => 'Line', + Format => 'Rect', + }, + 0x0021 => { + Name => 'LineFrom', + Format => 'Point', + }, + 0x0022 => { + Name => 'ShortLine', + Format => 'ShortLine', + }, + 0x0023 => { + Name => 'ShortLineFrom', + Format => 'int8u[2]', + }, + 0x0024 => { + Name => 'Reserved', + Format => 'Int16Data', + }, + 0x0028 => { + Name => 'LongText', + Format => 'PointText', + }, + 0x0029 => { + Name => 'DHText', + Format => 'Int8uText', + }, + 0x002a => { + Name => 'DVText', + Format => 'Int8uText', + }, + 0x002b => { + Name => 'DHDVText', + Format => 'Int8u2Text', + }, + 0x002c => { + Name => 'FontName', + Format => 'FontName', + }, + 0x002d => { + Name => 'LineJustify', + Format => 'int8u[10]', + }, + 0x002e => { + Name => 'GlyphState', + Format => 'int8u[8]', + }, + 0x002f => { + Name => 'Reserved', + Format => 'Int16Data', + }, + 0x0030 => { + Name => 'FrameRect', + Format => 'Rect', + }, + 0x0031 => { + Name => 'PaintRect', + Format => 'Rect', + }, + 0x0032 => { + Name => 'EraseRect', + Format => 'Rect', + }, + 0x0033 => { + Name => 'InvertRect', + Format => 'Rect', + }, + 0x0034 => { + Name => 'FillRect', + Format => 'Rect', + }, + 0x0035 => { + Name => 'Reserved', + Format => 'Rect', + }, + 0x0038 => { + Name => 'FrameSameRect', + Format => 'null', + }, + 0x0039 => { + Name => 'PaintSameRect', + Format => 'null', + }, + 0x003a => { + Name => 'EraseSameRect', + Format => 'null', + }, + 0x003b => { + Name => 'InvertSameRect', + Format => 'null', + }, + 0x003c => { + Name => 'FillSameRect', + Format => 'null', + }, + 0x003d => { + Name => 'Reserved', + Format => 'null', + }, + 0x0040 => { + Name => 'FrameRRect', + Format => 'Rect', + }, + 0x0041 => { + Name => 'PaintRRect', + Format => 'Rect', + }, + 0x0042 => { + Name => 'EraseRRect', + Format => 'Rect', + }, + 0x0043 => { + Name => 'InvertRRect', + Format => 'Rect', + }, + 0x0044 => { + Name => 'FillRRect', + Format => 'Rect', + }, + 0x0045 => { + Name => 'Reserved', + Format => 'Rect', + }, + 0x0048 => { + Name => 'FrameSameRRect', + Format => 'null', + }, + 0x0049 => { + Name => 'PaintSameRRect', + Format => 'null', + }, + 0x004a => { + Name => 'EraseSameRRect', + Format => 'null', + }, + 0x004b => { + Name => 'InvertSameRRect', + Format => 'null', + }, + 0x004c => { + Name => 'FillSameRRect', + Format => 'null', + }, + 0x004d => { + Name => 'Reserved', + Format => 'null', + }, + 0x0050 => { + Name => 'FrameOval', + Format => 'Rect', + }, + 0x0051 => { + Name => 'PaintOval', + Format => 'Rect', + }, + 0x0052 => { + Name => 'EraseOval', + Format => 'Rect', + }, + 0x0053 => { + Name => 'InvertOval', + Format => 'Rect', + }, + 0x0054 => { + Name => 'FillOval', + Format => 'Rect', + }, + 0x0055 => { + Name => 'Reserved', + Format => 'Rect', + }, + 0x0058 => { + Name => 'FrameSameOval', + Format => 'null', + }, + 0x0059 => { + Name => 'PaintSameOval', + Format => 'null', + }, + 0x005a => { + Name => 'EraseSameOval', + Format => 'null', + }, + 0x005b => { + Name => 'InvertSameOval', + Format => 'null', + }, + 0x005c => { + Name => 'FillSameOval', + Format => 'null', + }, + 0x005d => { + Name => 'Reserved', + Format => 'null', + }, + 0x0060 => { + Name => 'FrameArc', + Format => 'Arc', + }, + 0x0061 => { + Name => 'PaintArc', + Format => 'Arc', + }, + 0x0062 => { + Name => 'EraseArc', + Format => 'Arc', + }, + 0x0063 => { + Name => 'InvertArc', + Format => 'Arc', + }, + 0x0064 => { + Name => 'FillArc', + Format => 'Arc', + }, + 0x0065 => { + Name => 'Reserved', + Format => 'Arc', + }, + 0x0068 => { + Name => 'FrameSameArc', + Format => 'Point', + }, + 0x0069 => { + Name => 'PaintSameArc', + Format => 'Point', + }, + 0x006a => { + Name => 'EraseSameArc', + Format => 'Point', + }, + 0x006b => { + Name => 'InvertSameArc', + Format => 'Point', + }, + 0x006c => { + Name => 'FillSameArc', + Format => 'Point', + }, + 0x006d => { + Name => 'Reserved', + Format => 'int32u', + }, + 0x0070 => { + Name => 'FramePoly', + Format => 'Polygon', + }, + 0x0071 => { + Name => 'PaintPoly', + Format => 'Polygon', + }, + 0x0072 => { + Name => 'ErasePoly', + Format => 'Polygon', + }, + 0x0073 => { + Name => 'InvertPoly', + Format => 'Polygon', + }, + 0x0074 => { + Name => 'FillPoly', + Format => 'Polygon', + }, + 0x0075 => { + Name => 'Reserved', + Format => 'Polygon', + }, + 0x0078 => { + Name => 'FrameSamePoly', + Format => 'null', + }, + 0x0079 => { + Name => 'PaintSamePoly', + Format => 'null', + }, + 0x007a => { + Name => 'EraseSamePoly', + Format => 'null', + }, + 0x007b => { + Name => 'InvertSamePoly', + Format => 'null', + }, + 0x007c => { + Name => 'FillSamePoly', + Format => 'null', + }, + 0x007d => { + Name => 'Reserved', + Format => 'null', + }, + 0x0080 => { + Name => 'FrameRgn', + Format => 'Rgn', + }, + 0x0081 => { + Name => 'PaintRgn', + Format => 'Rgn', + }, + 0x0082 => { + Name => 'EraseRgn', + Format => 'Rgn', + }, + 0x0083 => { + Name => 'InvertRgn', + Format => 'Rgn', + }, + 0x0084 => { + Name => 'FillRgn', + Format => 'Rgn', + }, + 0x0085 => { + Name => 'Reserved', + Format => 'Rgn', + }, + 0x0088 => { + Name => 'FrameSameRgn', + Format => 'null', + }, + 0x0089 => { + Name => 'PaintSameRgn', + Format => 'null', + }, + 0x008a => { + Name => 'EraseSameRgn', + Format => 'null', + }, + 0x008b => { + Name => 'InvertSameRgn', + Format => 'null', + }, + 0x008c => { + Name => 'FillSameRgn', + Format => 'null', + }, + 0x008d => { + Name => 'Reserved', + Format => 'null', + }, + 0x0090 => { + Name => 'BitsRect', + Description => 'CopyBits with Clipped Rectangle', + Format => 'BitsRect#', # (version-dependent format) + }, + 0x0091 => { + Name => 'BitsRgn', + Description => 'CopyBits with Clipped Region', + Format => 'BitsRgn#', # (version-dependent format) + }, + 0x0092 => { + Name => 'Reserved', + Format => 'Int16Data', + }, + 0x0098 => { + Name => 'PackBitsRect', + Description => 'Packed CopyBits with Clipped Rectangle', + Format => 'BitsRect#', # (version-dependent format) + }, + 0x0099 => { + Name => 'PackBitsRgn', + Description => 'Packed CopyBits with Clipped Region', + Format => 'BitsRgn#', # (version-dependent format) + }, + 0x009a => { + Name => 'DirectBitsRect', + Format => 'DirectBitsRect', + }, + 0x009b => { + Name => 'DirectBitsRgn', + Format => 'DirectBitsRgn', + }, + 0x009c => { + Name => 'Reserved', + Format => 'Int16Data', + }, + 0x009d => { + Name => 'Reserved', + Format => 'Int16Data', + }, + 0x009e => { + Name => 'Reserved', + Format => 'Int16Data', + }, + 0x009f => { + Name => 'Reserved', + Format => 'Int16Data', + }, + 0x00a0 => { + Name => 'ShortComment', + Format => 'int16u', + }, + 0x00a1 => [ + # this list for documentation only [currently not extracted] + { + # (not actually a full Photohop IRB record it appears, but it does start + # with '8BIM', and does contain resolution information at offset 0x0a) + Name => 'LongComment', # kind = 498 + Format => 'LongComment', + SubDirectory => { TagTable => 'Image::ExifTool::Photoshop::Main' }, + }, + { + Name => 'LongComment', # kind = 224 + Format => 'LongComment', + SubDirectory => { + TagTable => 'Image::ExifTool::ICC_Profile::Main', + Start => '$valuePtr + 4', + }, + }, + ], + 0x00a2 => { + Name => 'Reserved', + Format => 'Int16Data', + }, + 0x00b0 => { + Name => 'Reserved', + Format => 'null', + }, + 0x00d0 => { + Name => 'Reserved', + Format => 'Int32uData', + }, + 0x00ff => { + Name => 'OpEndPic', + Description => 'End of picture', + Format => 'null', # 2 for version 2!? + }, + 0x0100 => { + Name => 'Reserved', + Format => 'int16u', + }, + 0x0200 => { + Name => 'Reserved', + Format => 'int32u', + }, + 0x02ff => { + Name => 'Version', + Description => 'Version number of picture', + Format => 'int16u', + }, + 0x0300 => { + Name => 'Reserved', + Format => 'int16u', + }, + 0x0bff => { + Name => 'Reserved', + Format => 'int8u[22]', + }, + 0x0c00 => { + Name => 'HeaderOp', + Format => 'int16u[12]', + }, + 0x0c01 => { + Name => 'Reserved', + Format => 'int8u[24]', + }, + 0x7f00 => { + Name => 'Reserved', + Format => 'int8u[254]', + }, + 0x8000 => { + Name => 'Reserved', + Format => 'null', + }, + 0x8100 => { + Name => 'Reserved', + Format => 'Int32uData', + }, + 0x8200 => { + Name => 'CompressedQuickTime', + Format => 'CompressedQuickTime', + }, + 0x8201 => { + Name => 'UncompressedQuickTime', + Format => 'Int32uData', + }, + 0xffff => { + Name => 'Reserved', + Format => 'Int32uData', + }, +); + +# picture comment 'kind' codes +# http://developer.apple.com/technotes/qd/qd_10.html +my %commentKind = ( + 150 => 'TextBegin', + 151 => 'TextEnd', + 152 => 'StringBegin', + 153 => 'StringEnd', + 154 => 'TextCenter', + 155 => 'LineLayoutOff', + 156 => 'LineLayoutOn', + 157 => 'ClientLineLayout', + 160 => 'PolyBegin', + 161 => 'PolyEnd', + 163 => 'PolyIgnore', + 164 => 'PolySmooth', + 165 => 'PolyClose', + 180 => 'DashedLine', + 181 => 'DashedStop', + 182 => 'SetLineWidth', + 190 => 'PostScriptBegin', + 191 => 'PostScriptEnd', + 192 => 'PostScriptHandle', + 193 => 'PostScriptFile', + 194 => 'TextIsPostScript', + 195 => 'ResourcePS', + 196 => 'PSBeginNoSave', + 197 => 'SetGrayLevel', + 200 => 'RotateBegin', + 201 => 'RotateEnd', + 202 => 'RotateCenter', + 210 => 'FormsPrinting', + 211 => 'EndFormsPrinting', + 224 => '<ICC Profile>', + 498 => '<Photoshop Data>', + 1000 => 'BitMapThinningOff', + 1001 => 'BitMapThinningOn', +); + +#------------------------------------------------------------------------------ +# Get PixData data +# Inputs: 0) reference to PixMap, 1) RAF reference +# Returns: reference to PixData or undef on error +sub GetPixData($$) +{ + my ($pixMap, $raf) = @_; + my $packType = $pixMap->{packType}; + my $rowBytes = $pixMap->{rowBytes} & 0x3fff; # remove flags bits + my $height = $pixMap->{bounds}->{botRight}->{v} - + $pixMap->{bounds}->{topLeft}->{v}; + my ($data, $size, $buff, $i); + + if ($packType == 1 or $rowBytes < 8) { # unpacked data + $size = $rowBytes * $height; + return undef unless $raf->Read($data, $size) == $size; + } elsif ($packType == 2) { # pad byte dropped + $size = int($rowBytes * $height * 3 / 4 + 0.5); + return undef unless $raf->Read($data, $size) == $size; + } else { + $data = ''; + for ($i=0; $i<$height; ++$i) { + if ($rowBytes > 250) { + $raf->Read($buff,2) == 2 or return undef; + $size = unpack('n',$buff); + } else { + $raf->Read($buff,1) == 1 or return undef; + $size = unpack('C',$buff); + } + $data .= $buff; + $raf->Read($buff,$size) == $size or return undef; + $data .= $buff; + } + } + return \$data; +} + +#------------------------------------------------------------------------------ +# Read value from PICT file +# Inputs: 0) RAF reference, 1) tag, 2) format, 3) optional count +# Returns: value, reference to structure hash, or undef on error +sub ReadPictValue($$$;$) +{ + my ($raf, $tag, $format, $count) = @_; + return undef unless $format; + unless (defined $count) { + if ($format =~ /(.+)\[(.+)\]/s) { + $format = $1; + $count = $2; + } else { + $count = 1; # count undefined: assume 1 + } + } + my $cntStr = ($count == 1) ? '' : "[$count]"; + # no size if count is 0 + my $size = $count ? Image::ExifTool::FormatSize($format) : 0; + if (defined $size or $format eq 'null') { + my $val; + if ($size) { + my $buff; + $size *= $count; + $raf->Read($buff, $size) == $size or return undef; + $val = ReadValue(\$buff, 0, $format, $count, $size); + } else { + $val = ''; + } + if ($verbose) { + print $out "${indent}$tag ($format$cntStr)"; + if ($size) { + if (not defined $val) { + print $out " = <undef>\n"; + } elsif ($format eq 'binary') { + print $out " = <binary data>\n"; + if ($verbose > 2) { + my %parms = ( Out => $out ); + $parms{MaxLen} = 96 if $verbose < 4; + HexDump(\$val, undef, %parms); + } + } else { + print $out " = $val\n"; + } + } else { + print $out "\n"; + } + } + return \$val if $format eq 'binary' and defined $val; + return $val; + } + $verbose and print $out "${indent}$tag ($format$cntStr):\n"; + my $struct = $structs{$format} or return undef; + my ($c, @vals); + for ($c=0; $c<$count; ++$c) { + my (%val, $i); + for ($i=0; ; $i+=2) { + my $tag = $$struct[$i] or last; + my $fmt = $$struct[$i+1]; + my ($cnt, $val); + $indent .= ' '; + if (ref $fmt) { + $val = eval $$fmt; + $@ and warn $@; + if ($verbose and defined $val) { + printf $out "${indent}$tag (binary[%d]) = <binary data>\n",length($$val); + if ($verbose > 2) { + my %parms = ( Out => $out ); + $parms{MaxLen} = 96 if $verbose < 4; + HexDump($val, undef, %parms); + } + } + } elsif ($fmt =~ /(.+)\[(.+)\]/s) { + $fmt = $1; + $cnt = eval $2; + $@ and warn $@; + $val = ReadPictValue($raf, $tag, $fmt, $cnt); + } else { + $val = ReadPictValue($raf, $tag, $fmt); + } + $indent = substr($indent, 2); + return undef unless defined $val; + $val{$tag} = $val; + } + return \%val if $count == 1; + push @vals, \%val; + } + return \@vals; +} + +#------------------------------------------------------------------------------ +# Extract meta information from a PICT image +# Inputs: 0) ExifTool object reference, 1) dirInfo reference +# Returns: 1 on success, 0 if this wasn't a valid PICT image +sub ProcessPICT($$) +{ + my ($et, $dirInfo) = @_; + my $raf = $$dirInfo{RAF}; + $verbose = $et->Options('Verbose'); + $out = $et->Options('TextOut'); + $indent = ''; + my ($buff, $tried, @hdr, $op, $hRes, $vRes); + + # recognize both PICT files and PICT resources (PICT files have a + # 512-byte header that we ignore, but PICT resources do not) + for (;;) { + $raf->Read($buff, 12) == 12 or return 0; + @hdr = unpack('x2n5', $buff); + $op = pop @hdr; + # check for PICT version 1 format + if ($op eq 0x1101) { + $vers = 1; + undef $extended; + last; + } + # check for PICT version 2 format + if ($op eq 0x0011) { + $raf->Read($buff, 28) == 28 or return 0; + if ($buff =~ /^\x02\xff\x0c\x00\xff\xff/) { + $vers = 2; + undef $extended; + last; + } + if ($buff =~ /^\x02\xff\x0c\x00\xff\xfe/) { + $vers = 2; + $extended = 1; + ($hRes, $vRes) = unpack('x8N2', $buff); + last; + } + } + return 0 if $tried; + $tried = 1; + $raf->Seek(512, 0) or return 0; + } + # make the bounding rect signed + foreach (@hdr) { + $_ >= 0x8000 and $_ -= 0x10000; + } + my $w = $hdr[3] - $hdr[1]; + my $h = $hdr[2] - $hdr[0]; + return 0 unless $w > 0 and $h > 0; + + SetByteOrder('MM'); + + if ($extended) { + # extended version 2 pictures contain resolution information + # and image bounds are in 72-dpi equivalent units + $hRes = GetFixed32s(\$buff, 8); + $vRes = GetFixed32s(\$buff, 12); + return 0 unless $hRes and $vRes; + $w = int($w * $hRes / 72 + 0.5); + $h = int($h * $vRes / 72 + 0.5); + } + $et->SetFileType(); + $et->FoundTag('ImageWidth', $w); + $et->FoundTag('ImageHeight', $h); + $et->FoundTag('XResolution', $hRes) if $hRes; + $et->FoundTag('YResolution', $vRes) if $vRes; + + # don't extract image opcodes unless verbose + return 1 unless $verbose or $et->Options('Unknown'); + + $verbose and printf $out "PICT version $vers%s\n", $extended ? ' extended' : ''; + + my $tagTablePtr = GetTagTable('Image::ExifTool::PICT::Main'); + + my $success; + for (;;) { + if ($vers == 1) { + $raf->Read($buff, 1) == 1 or last; + $op = ord($buff); + } else { + # must start version 2 opcode on an even byte + $raf->Read($buff, 1) if $raf->Tell() & 0x01; + $raf->Read($buff, 2) == 2 or last; + $op = unpack('n', $buff); + } + my $tagInfo = $et->GetTagInfo($tagTablePtr, $op); + unless ($tagInfo) { + my $i; + # search for reserved tag info + for ($i=0; $i<scalar(@reserved); $i+=2) { + next unless $op >= $reserved[$i]; + last if $op > $reserved[$i+1]; + $tagInfo = $et->GetTagInfo($tagTablePtr, $reserved[$i]); + last; + } + last unless $tagInfo; + } + if ($op eq 0xff) { + $verbose and print $out "End of picture\n"; + $success = 1; + last; + } + my $format = $$tagInfo{Format}; + unless ($format) { + $et->Warn("Missing format for $$tagInfo{Name}"); + last; + } + # replace version number for version-dependent formats + $format =~ s/#$/$vers/; + my $wid = $vers * 2; + $verbose and printf $out "Tag 0x%.${wid}x, ", $op; + my $val = ReadPictValue($raf, $$tagInfo{Name}, $format); + unless (defined $val) { + $et->Warn("Error reading $$tagInfo{Name} information"); + last; + } + if (ref $val eq 'HASH') { + # extract JPEG image from CompressedQuickTime imageData + if ($$tagInfo{Name} eq 'CompressedQuickTime' and + ref $val->{imageDescr} eq 'HASH' and + $val->{imageDescr}->{compressor} and + $val->{imageDescr}->{compressor} eq 'Photo - JPEG' and + ref $val->{imageData} eq 'SCALAR' and + $et->ValidateImage($val->{imageData}, 'PreviewImage')) + { + $et->FoundTag('PreviewImage', $val->{imageData}); + } + } else { + # $et->FoundTag($tagInfo, $val); + } + } + $success or $et->Warn('End of picture not found'); + return 1; +} + +1; # end + +__END__ + +=head1 NAME + +Image::ExifTool::PICT - Read PICT meta information + +=head1 SYNOPSIS + +This module is used by Image::ExifTool + +=head1 DESCRIPTION + +This module contains routines required by Image::ExifTool to read PICT +(Apple Picture) images. + +=head1 NOTES + +Extraction of PICT opcodes is experimental, and is only enabled with the +Verbose or the Unknown option. + +=head1 AUTHOR + +Copyright 2003-2019, Phil Harvey (phil at owl.phy.queensu.ca) + +This library is free software; you can redistribute it and/or modify it +under the same terms as Perl itself. + +=head1 REFERENCES + +=over 4 + +=item L<http://developer.apple.com/documentation/mac/QuickDraw/QuickDraw-2.html> + +=item L<http://developer.apple.com/documentation/QuickTime/INMAC/QT/iqImageCompMgr.a.htm> + +=back + +=head1 SEE ALSO + +L<Image::ExifTool::TagNames/PICT Tags>, +L<Image::ExifTool(3pm)|Image::ExifTool> + +=cut + diff --git a/lib/Image/ExifTool/PLIST.pm b/lib/Image/ExifTool/PLIST.pm new file mode 100644 index 0000000..52c4f62 --- /dev/null +++ b/lib/Image/ExifTool/PLIST.pm @@ -0,0 +1,462 @@ +#------------------------------------------------------------------------------ +# File: PLIST.pm +# +# Description: Read Apple PLIST information +# +# Revisions: 2013-02-01 - P. Harvey Created +# +# References: 1) http://www.apple.com/DTDs/PropertyList-1.0.dtd +# 2) http://opensource.apple.com/source/CF/CF-550/CFBinaryPList.c +# +# Notes: - Sony MODD files also use XML PLIST format, but with a few quirks +# +# - Decodes both the binary and XML-based PLIST formats +#------------------------------------------------------------------------------ + +package Image::ExifTool::PLIST; + +use strict; +use vars qw($VERSION); +use Image::ExifTool qw(:DataAccess :Utils); +use Image::ExifTool::XMP; +use Image::ExifTool::GPS; + +$VERSION = '1.09'; + +sub ExtractObject($$;$); +sub Get24u($$); + +# access routines to read various-sized integer/real values (add 0x100 to size for reals) +my %readProc = ( + 1 => \&Get8u, + 2 => \&Get16u, + 3 => \&Get24u, + 4 => \&Get32u, + 8 => \&Get64u, + 0x104 => \&GetFloat, + 0x108 => \&GetDouble, +); + +# recognize different types of PLIST files based on certain tags +my %plistType = ( + adjustmentBaseVersion => 'AAE', +); + +# PLIST tags (generated on-the-fly for most tags) +%Image::ExifTool::PLIST::Main = ( + PROCESS_PROC => \&ProcessPLIST, + GROUPS => { 0 => 'PLIST', 1 => 'XML', 2 => 'Document' }, + VARS => { LONG_TAGS => 4 }, + NOTES => q{ + Apple Property List tags. ExifTool reads both XML and binary-format PLIST + files, and will extract any existing tags even if they aren't listed below. + These tags belong to the family 0 "PLIST" group, but family 1 group may be + either "XML" or "PLIST" depending on whether the format is XML or binary. + }, +# +# tags found in PLIST information of QuickTime iTunesInfo iTunMOVI atom (ref PH) +# + 'cast//name' => { Name => 'Cast', List => 1 }, + 'directors//name' => { Name => 'Directors', List => 1 }, + 'producers//name' => { Name => 'Producers', List => 1 }, + 'screenwriters//name' => { Name => 'Screenwriters', List => 1 }, + 'codirectors//name' => { Name => 'Codirectors', List => 1 }, # (NC) + 'studio//name' => { Name => 'Studio', List => 1 }, # (NC) +# +# tags found in MODD files (ref PH) +# + 'MetaDataList//DateTimeOriginal' => { + Name => 'DateTimeOriginal', + Description => 'Date/Time Original', + Groups => { 2 => 'Time' }, + # Sony uses a "real" here -- number of days since Dec 31, 1899 + ValueConv => 'IsFloat($val) ? ConvertUnixTime(($val - 25569) * 24 * 3600) : $val', + PrintConv => '$self->ConvertDateTime($val)', + }, + 'MetaDataList//Duration' => { + Name => 'Duration', + Groups => { 2 => 'Video' }, + PrintConv => 'ConvertDuration($val)', + }, + 'MetaDataList//Geolocation/Latitude' => { + Name => 'GPSLatitude', + Groups => { 2 => 'Location' }, + PrintConv => 'Image::ExifTool::GPS::ToDMS($self, $val, 1, "N")', + }, + 'MetaDataList//Geolocation/Longitude' => { + Name => 'GPSLongitude', + Groups => { 2 => 'Location' }, + PrintConv => 'Image::ExifTool::GPS::ToDMS($self, $val, 1, "E")', + }, + 'MetaDataList//Geolocation/MapDatum' => { + Name => 'GPSMapDatum', + Groups => { 2 => 'Location' }, + }, + XMLFileType => { + # recognize MODD files by their content + RawConv => q{ + if ($val eq 'ModdXML' and $$self{FILE_TYPE} eq 'XMP') { + $self->OverrideFileType('MODD'); + } + return $val; + }, + }, +); + +#------------------------------------------------------------------------------ +# We found a PLIST XML property name/value +# Inputs: 0) ExifTool object ref, 1) tag table ref +# 2) reference to array of XML property names (last is current property) +# 3) property value, 4) attribute hash ref (not used here) +# Returns: 1 if valid tag was found +sub FoundTag($$$$;$) +{ + my ($et, $tagTablePtr, $props, $val, $attrs) = @_; + return 0 unless @$props; + my $verbose = $et->Options('Verbose'); + my $keys = $$et{PListKeys} || ( $$et{PListKeys} = [] ); + + my $prop = $$props[-1]; + if ($verbose > 1) { + $et->VPrint(0, $$et{INDENT}, '[', join('/',@$props), ' = ', + $et->Printable($val), "]\n"); + } + # un-escape XML character entities + $val = Image::ExifTool::XMP::UnescapeXML($val); + + # handle the various PLIST properties + if ($prop eq 'data') { + if ($val =~ /^[0-9a-f]+$/ and not length($val) & 0x01) { + # MODD files use ASCII-hex encoded "data"... + my $buff = pack('H*', $val); + $val = \$buff; + } else { + # ...but the PLIST DTD specifies Base64 encoding + $val = Image::ExifTool::XMP::DecodeBase64($val); + } + } elsif ($prop eq 'date') { + $val = Image::ExifTool::XMP::ConvertXMPDate($val); + } elsif ($prop eq 'true' or $prop eq 'false') { + $val = ucfirst $prop; + } else { + # convert from UTF8 to ExifTool Charset + $val = $et->Decode($val, 'UTF8'); + if ($prop eq 'key') { + if (@$props <= 3) { # top-level key should be plist/dict/key + @$keys = ( $val ); + } else { + # save key names to be used in tag name + push @$keys, '' while @$keys < @$props - 3; + pop @$keys while @$keys > @$props - 2; + $$keys[@$props - 3] = $val; + } + return 0; + } + } + + return 0 unless @$keys; # can't store value if no associated key + + my $tag = join '/', @$keys; # generate tag ID from 'key' values + my $tagInfo = $$tagTablePtr{$tag}; + unless ($tagInfo) { + $et->VPrint(0, $$et{INDENT}, "[adding $tag]\n") if $verbose; + # generate tag name from ID + my $name = $tag; + $name =~ s{^MetaDataList//}{}; # shorten long MODD metadata tag names + $name =~ s{//name$}{}; # remove unnecessary MODD "name" property + $name =~ s/([^A-Za-z])([a-z])/$1\u$2/g; # capitalize words + $name =~ tr/-_a-zA-Z0-9//dc; # remove illegal characters + $tagInfo = { Name => ucfirst($name), List => 1 }; + if ($prop eq 'date') { + $$tagInfo{Groups}{2} = 'Time'; + $$tagInfo{PrintConv} = '$self->ConvertDateTime($val)'; + } + AddTagToTable($tagTablePtr, $tag, $tagInfo); + } + # allow list-behaviour only for consecutive tags with the same ID + if ($$et{LastPListTag} and $$et{LastPListTag} ne $tagInfo) { + delete $$et{LIST_TAGS}{$$et{LastPListTag}}; + } + $$et{LastPListTag} = $tagInfo; + # override file type if applicable + $et->OverrideFileType($plistType{$tag}) if $plistType{$tag} and $$et{FILE_TYPE} eq 'XMP'; + # save the tag + $et->HandleTag($tagTablePtr, $tag, $val); + + return 1; +} + +#------------------------------------------------------------------------------ +# Get big-endian 24-bit integer +# Inputs: 0) data ref, 1) offset +# Returns: integer value +sub Get24u($$) +{ + my ($dataPt, $off) = @_; + return unpack 'N', "\0" . substr($$dataPt, $off, 3); +} + +#------------------------------------------------------------------------------ +# Extract object from binary PLIST file at the current file position (ref 2) +# Inputs: 0) ExifTool ref, 1) PLIST info ref, 2) parent tag ID (undef for top) +# Returns: the object, or undef on error +sub ExtractObject($$;$) +{ + my ($et, $plistInfo, $parent) = @_; + my $raf = $$plistInfo{RAF}; + my ($buff, $val); + + $raf->Read($buff, 1) == 1 or return undef; + my $type = ord($buff) >> 4; + my $size = ord($buff) & 0x0f; + if ($type == 0) { # null/bool/fill + $val = { 0x00=>'<null>', 0x08=>'True', 0x09=>'False', 0x0f=>'<fill>' }->{$size}; + } elsif ($type == 1 or $type == 2 or $type == 3) { # int, float or date + $size = 1 << $size; + my $proc = ($type == 1 ? $readProc{$size} : $readProc{$size + 0x100}) or return undef; + $val = &$proc(\$buff, 0) if $raf->Read($buff, $size) == $size; + if ($type == 3 and defined $val) { # date + # dates are referenced to Jan 1, 2001 (11323 days from Unix time zero) + $val = Image::ExifTool::ConvertUnixTime($val + 11323 * 24 * 3600, 1); + $$plistInfo{DateFormat} = 1; + } + } elsif ($type == 8) { # UID + ++$size; + $raf->Read($buff, $size) == $size or return undef; + my $proc = $readProc{$size}; + if ($proc) { + $val = &$proc(\$buff, 0); + } elsif ($size == 16) { + require Image::ExifTool::ASF; + $val = Image::ExifTool::ASF::GetGUID($buff); + } else { + $val = "0x" . unpack 'H*', $buff; + } + } else { + # $size is the size of the remaining types + if ($size == 0x0f) { + # size is stored in extra integer object + $size = ExtractObject($et, $plistInfo); + return undef unless defined $size and $size =~ /^\d+$/; + } + if ($type == 4) { # data + if ($size < 1000000 or $et->Options('Binary')) { + $raf->Read($buff, $size) == $size or return undef; + } else { + $buff = "Binary data $size bytes"; + } + $val = \$buff; # (return reference for binary data) + } elsif ($type == 5) { # ASCII string + $raf->Read($val, $size) == $size or return undef; + } elsif ($type == 6) { # UCS-2BE string + $size *= 2; + $raf->Read($buff, $size) == $size or return undef; + $val = $et->Decode($buff, 'UCS2'); + } elsif ($type == 10 or $type == 12 or $type == 13) { # array, set or dict + # the remaining types store a list of references + my $refSize = $$plistInfo{RefSize}; + my $refProc = $$plistInfo{RefProc}; + my $num = $type == 13 ? $size * 2 : $size; + my $len = $num * $refSize; + $raf->Read($buff, $len) == $len or return undef; + my $table = $$plistInfo{Table}; + my ($i, $ref, @refs, @array); + for ($i=0; $i<$num; ++$i) { + my $ref = &$refProc(\$buff, $i * $refSize); + return 0 if $ref >= @$table; + push @refs, $ref; + } + if ($type == 13) { # dict + # prevent infinite recursion + if (defined $parent and length $parent > 1000) { + $et->WarnOnce('Possible deep recursion while parsing PLIST'); + return undef; + } + my $tagTablePtr = $$plistInfo{TagTablePtr}; + my $verbose = $et->Options('Verbose'); + for ($i=0; $i<$size; ++$i) { + # get the entry key + $raf->Seek($$table[$refs[$i]], 0) or return undef; + my $key = ExtractObject($et, $plistInfo); + next unless defined $key and length $key; # silently ignore bad dict entries + # get the entry value + $raf->Seek($$table[$refs[$i+$size]], 0) or return undef; + # generate an ID for this tag + my $tag = defined $parent ? "$parent/$key" : $key; + undef $$plistInfo{DateFormat}; + my $val = ExtractObject($et, $plistInfo, $tag); + next if not defined $val or ref($val) eq 'HASH'; + my $tagInfo = $et->GetTagInfo($tagTablePtr, $tag); + unless ($tagInfo) { + $et->VPrint(0, $$et{INDENT}, "[adding $tag]\n") if $verbose; + my $name = $tag; + $name =~ s/([^A-Za-z])([a-z])/$1\u$2/g; # capitalize words + $name =~ tr/-_a-zA-Z0-9//dc; # remove illegal characters + $tagInfo = { Name => ucfirst($name), List => 1 }; + if ($$plistInfo{DateFormat}) { + $$tagInfo{Groups}{2} = 'Time'; + $$tagInfo{PrintConv} = '$self->ConvertDateTime($val)'; + } + AddTagToTable($tagTablePtr, $tag, $tagInfo); + } + # allow list-behaviour only for consecutive tags with the same ID + if ($$et{LastPListTag} and $$et{LastPListTag} ne $tagInfo) { + delete $$et{LIST_TAGS}{$$et{LastPListTag}}; + } + $$et{LastPListTag} = $tagInfo; + $et->HandleTag($tagTablePtr, $tag, $val); + } + $val = { }; # flag the value as a dictionary (ie. tags already saved) + } else { + # extract the referenced objects + foreach $ref (@refs) { + $raf->Seek($$table[$ref], 0) or return undef; # seek to this object + $val = ExtractObject($et, $plistInfo, $parent); + next unless defined $val and ref $val ne 'HASH'; + push @array, $val; + } + $val = \@array; + } + } + } + return $val; +} + +#------------------------------------------------------------------------------ +# Process binary PLIST data (ref 2) +# Inputs: 0) ExifTool object ref, 1) DirInfo ref, 2) tag table ref +# Returns: 1 on success (and returns plist value as $$dirInfo{Value}) +sub ProcessBinaryPLIST($$$) +{ + my ($et, $dirInfo, $tagTablePtr) = @_; + my ($i, $buff, @table); + my $dataPt = $$dirInfo{DataPt}; + + $et->VerboseDir('Binary PLIST'); + SetByteOrder('MM'); + + if ($dataPt) { + my $start = $$dirInfo{DirStart}; + if ($start or ($$dirInfo{DirLen} and $$dirInfo{DirLen} != length $$dataPt)) { + my $buf2 = substr($$dataPt, $start || 0, $$dirInfo{DirLen}); + $$dirInfo{RAF} = new File::RandomAccess(\$buf2); + } else { + $$dirInfo{RAF} = new File::RandomAccess($dataPt); + } + my $strt = $$dirInfo{DirStart} || 0; + } + # read and parse the trailer + my $raf = $$dirInfo{RAF} or return 0; + $raf->Seek(-32,2) and $raf->Read($buff,32)==32 or return 0; + my $intSize = Get8u(\$buff, 6); + my $refSize = Get8u(\$buff, 7); + my $numObj = Get64u(\$buff, 8); + my $topObj = Get64u(\$buff, 16); + my $tableOff = Get64u(\$buff, 24); + + return 0 if $topObj >= $numObj; + my $intProc = $readProc{$intSize} or return 0; + my $refProc = $readProc{$refSize} or return 0; + + # read and parse the offset table + my $tableSize = $intSize * $numObj; + $raf->Seek($tableOff, 0) and $raf->Read($buff, $tableSize) == $tableSize or return 0; + for ($i=0; $i<$numObj; ++$i) { + push @table, &$intProc(\$buff, $i * $intSize); + } + my %plistInfo = ( + RAF => $raf, + RefSize => $refSize, + RefProc => $refProc, + Table => \@table, + TagTablePtr => $tagTablePtr, + ); + # position file pointer at the top object, and extract it + $raf->Seek($table[$topObj], 0) or return 0; + $$dirInfo{Value} = ExtractObject($et, \%plistInfo); + return defined $$dirInfo{Value} ? 1 : 0; +} + +#------------------------------------------------------------------------------ +# Extract information from a PLIST file +# Inputs: 0) ExifTool object ref, 1) dirInfo ref, 2) tag table ref +# Returns: 1 on success, 0 if this wasn't valid PLIST +sub ProcessPLIST($$;$) +{ + my ($et, $dirInfo, $tagTablePtr) = @_; + + # process XML PLIST data using the XMP module + $$dirInfo{XMPParseOpts}{FoundProc} = \&FoundTag; + my $result = Image::ExifTool::XMP::ProcessXMP($et, $dirInfo, $tagTablePtr); + delete $$dirInfo{XMPParseOpts}; + + unless ($result) { + my $buff; + my $raf = $$dirInfo{RAF} or return 0; + $raf->Seek(0,0) and $raf->Read($buff, 64) or return 0; + if ($buff =~ /^bplist0/) { + # binary PLIST file + my $tagTablePtr = GetTagTable('Image::ExifTool::PLIST::Main'); + $et->SetFileType('PLIST', 'application/x-plist'); + $$et{SET_GROUP1} = 'PLIST'; + unless (ProcessBinaryPLIST($et, $dirInfo, $tagTablePtr)) { + $et->Error('Error reading binary PLIST file'); + } + delete $$et{SET_GROUP1}; + $result = 1; + } elsif ($$et{FILE_EXT} and $$et{FILE_EXT} eq 'PLIST' and + $buff =~ /^\xfe\xff\x00/) + { + # (have seen very old PLIST files encoded as UCS-2BE with leading BOM) + $et->Error('Old PLIST format currently not supported'); + $result = 1; + } + } + return $result; +} + +1; # end + +__END__ + +=head1 NAME + +Image::ExifTool::PLIST - Read Apple PLIST information + +=head1 SYNOPSIS + +This module is used by Image::ExifTool + +=head1 DESCRIPTION + +This module contains the routines used by Image::ExifTool to extract +information from Apple Property List files. + +=head1 NOTES + +This module decodes both the binary and XML-based PLIST format. + +=head1 AUTHOR + +Copyright 2003-2019, Phil Harvey (phil at owl.phy.queensu.ca) + +This library is free software; you can redistribute it and/or modify it +under the same terms as Perl itself. + +=head1 REFERENCES + +=over 4 + +=item L<http://www.apple.com/DTDs/PropertyList-1.0.dtd> + +=item L<http://opensource.apple.com/source/CF/CF-550/CFBinaryPList.c> + +=back + +=head1 SEE ALSO + +L<Image::ExifTool::TagNames/PLIST Tags>, +L<Image::ExifTool(3pm)|Image::ExifTool> + +=cut + diff --git a/lib/Image/ExifTool/PLUS.pm b/lib/Image/ExifTool/PLUS.pm new file mode 100644 index 0000000..df3f44d --- /dev/null +++ b/lib/Image/ExifTool/PLUS.pm @@ -0,0 +1,2607 @@ +#------------------------------------------------------------------------------ +# File: PLUS.pm +# +# Description: PLUS (Picture Licensing Universal System) tags +# +# Revisions: 2016/05/18 - P. Harvey Created +# +# References: 1) http://www.useplus.com/useplus/standards.asp +#------------------------------------------------------------------------------ + +package Image::ExifTool::PLUS; + +use strict; +use vars qw($VERSION); +use Image::ExifTool::XMP; + +$VERSION = '1.00'; + +sub ValidateMediaSummary($); + +#------------------------------------------------------------------------------ +# PLUS (Picture Licensing Universal System) + +# PLUS vocabulary conversions +my %plusVocab = ( + ValueConv => '$val =~ s{http://ns.useplus.org/ldf/vocab/}{}; $val', + ValueConvInv => '"http://ns.useplus.org/ldf/vocab/$val"', +); + +# PLUS License Data Format 1.2.1 structures +# (this seems crazy to me -- why did they define different ID/Name structures +# for each field rather than just re-using the same structure?) +my %plusLicensee = ( + STRUCT_NAME => 'Licensee', + NAMESPACE => 'plus', + # all "rdf:type" properties removed in version 1.2.1 + # (idiots. Why did they put them there in the first place? -- it required + # a special patch for ExifTool to support these, and now they are gone!) + # TYPE => 'plus:LicenseeDetail', (removed in 1.2.1) + LicenseeID => { }, + LicenseeName=> { }, +); +my %plusEndUser = ( + STRUCT_NAME => 'EndUser', + NAMESPACE => 'plus', + # TYPE => 'plus:EndUserDetail', (removed in 1.2.1) + EndUserID => { }, + EndUserName => { }, +); +my %plusLicensor = ( + STRUCT_NAME => 'Licensor', + NAMESPACE => 'plus', + # TYPE => 'plus:LicensorDetail', (removed in 1.2.1) + LicensorID => { }, + LicensorName => { }, + LicensorStreetAddress => { }, + LicensorExtendedAddress => { }, + LicensorCity => { }, + LicensorRegion => { }, + LicensorPostalCode => { }, + LicensorCountry => { }, + LicensorTelephoneType1 => { + %plusVocab, + PrintConv => { + 'work' => 'Work', + 'cell' => 'Cell', + 'fax' => 'FAX', + 'home' => 'Home', + 'pager' => 'Pager', + }, + }, + LicensorTelephone1 => { }, + LicensorTelephoneType2 => { + %plusVocab, + PrintConv => { + 'work' => 'Work', + 'cell' => 'Cell', + 'fax' => 'FAX', + 'home' => 'Home', + 'pager' => 'Pager', + }, + }, + LicensorTelephone2 => { }, + LicensorEmail => { }, + LicensorURL => { }, +); +my %plusCopyrightOwner = ( + STRUCT_NAME => 'CopyrightOwner', + NAMESPACE => 'plus', + # TYPE => 'plus:CopyrightOwnerDetail', (removed in 1.2.1) + CopyrightOwnerID => { }, + CopyrightOwnerName => { }, +); +my %plusImageCreator = ( + STRUCT_NAME => 'ImageCreator', + NAMESPACE => 'plus', + # TYPE => 'plus:ImageCreatorDetail', (removed in 1.2.1) + ImageCreatorID => { }, + ImageCreatorName => { }, +); +my %plusImageSupplier = ( + STRUCT_NAME => 'ImageSupplier', + NAMESPACE => 'plus', + # TYPE => 'plus:ImageSupplierDetail', (removed in 1.2.1) + ImageSupplierID => { }, + ImageSupplierName => { }, +); + +# Media Matrix 1.1.1 decoding +my %mediaMatrix = ( + Notes => q{ + The lookup below is used to add human-readable descriptions to Media Matrix + ID's in PLUS Media Summary Codes. + }, + OTHER => sub { + my ($val, $inv, $conv) = @_; + $val = uc $val; # convert to upper case + if ($inv) { + # prepare MediaSummaryCode for writing + $val =~ s/\(.*?\)//sg; # remove descriptions + $val =~ s/^\s*?PLUS\s+(V[0-9]+)\s+(U[0-9]+)\s*;/|PLUS|$1|$2|/s; # reformat header + $val =~ tr/;/|/; # use "|" as separator instead of ";" + $val =~ tr/0-9A-Z|//dc; # remove extraneous characters + $val .= '|' unless $val =~ /\|$/; # add terminating "|" + ValidateMediaSummary($val) or return undef; + } elsif ($val =~ /^\|PLUS\|(.*?)\|(.*?)\|(.*)/s) { + # add human-readable descriptions + my ($ver,$num,$code) = ($1,$2,$3); + $ver .= " (LDF Version $1.$2)" if $ver =~ /V0*(\d+)(\d{2})$/; + $num .= " ($1 Media Usages:)" if $num =~ /U0*(\d+)/; + $code =~ tr/0-9A-Z|//dc; # remove extraneous characters + $val = "PLUS $ver $num"; + while ($code =~ /(\d[A-Z]{3})/g) { + my $mmid = $1; + if (defined $$conv{$mmid}) { + $val .= " $mmid ($$conv{$mmid})"; + } elsif ($mmid =~ /^1I([A-Z])([A-Z])/) { # decode Usage Item count + my $n = (ord($1)-65) * 26 + ord($2)-65 + 1; + # (add a separator before each new Media Usage Code) + $val .= "; $mmid ($n Usage Items:)"; + } elsif ($mmid =~ /^1UN([A-Z])/) { # decode Usage Number + $val .= " (Usage Number $1)"; + } else { + $val .= " $mmid"; + } + } + } + return $val; + }, + # 1 - Usage + '1IAA' => '1 Usage Item:', + '1IAB' => '2 Usage Items:', + '1IAC' => '3 Usage Items:', + '1IAD' => '4 Usage Items:', + '1IAE' => '5 Usage Items:', + # ... + '1UNA' => 'Usage Number A', + '1UNB' => 'Usage Number B', + '1UNC' => 'Usage Number C', + '1UND' => 'Usage Number D', + '1UNE' => 'Usage Number E', + # ... + # 2 - Media + '2BOB' => 'Advertising|Periodicals|Magazine, Consumer|Printed', + '2ACE' => 'Advertising|Periodicals|Magazine, Consumer|Internet Website', + '2GEN' => 'Advertising|Periodicals|Magazine, Consumer|Internet Downloadable File', + '2ADS' => 'Advertising|Periodicals|Magazine, Consumer|Internet Email', + '2GIB' => 'Advertising|Periodicals|Magazine, Consumer|All Internet Distribution Formats', + '2GHI' => 'Advertising|Periodicals|Magazine, Consumer|Recordable Media', + '2GEY' => 'Advertising|Periodicals|Magazine, Consumer|All Electronic Distribution Formats', + '2HAT' => 'Advertising|Periodicals|Magazine, Trade|Printed', + '2HAG' => 'Advertising|Periodicals|Magazine, Trade|Internet Website', + '2HAE' => 'Advertising|Periodicals|Magazine, Trade|Internet Downloadable File', + '2AFT' => 'Advertising|Periodicals|Magazine, Trade|Internet Email', + '2HAJ' => 'Advertising|Periodicals|Magazine, Trade|All Internet Distribution Formats', + '2AGE' => 'Advertising|Periodicals|Magazine, Trade|Recordable Media', + '2HAH' => 'Advertising|Periodicals|Magazine, Trade|All Electronic Distribution Formats', + '2JAR' => 'Advertising|Periodicals|Magazine, Corporate|Printed', + '2GIN' => 'Advertising|Periodicals|Magazine, Corporate|Internet Website', + '2GIE' => 'Advertising|Periodicals|Magazine, Corporate|Internet Downloadable File', + '2AGO' => 'Advertising|Periodicals|Magazine, Corporate|Internet Email', + '2GNU' => 'Advertising|Periodicals|Magazine, Corporate|All Internet Distribution Formats', + '2GIP' => 'Advertising|Periodicals|Magazine, Corporate|Recordable Media', + '2GIT' => 'Advertising|Periodicals|Magazine, Corporate|All Electronic Distribution Formats', + '2DEB' => 'Advertising|Periodicals|Magazine, Education|Printed', + '2GUM' => 'Advertising|Periodicals|Magazine, Education|Internet Website', + '2GUL' => 'Advertising|Periodicals|Magazine, Education|Internet Downloadable File', + '2AHA' => 'Advertising|Periodicals|Magazine, Education|Internet Email', + '2GYP' => 'Advertising|Periodicals|Magazine, Education|All Internet Distribution Formats', + '2GUV' => 'Advertising|Periodicals|Magazine, Education|Recordable Media', + '2GUY' => 'Advertising|Periodicals|Magazine, Education|All Electronic Distribution Formats', + '2CUS' => 'Advertising|Periodicals|Magazine, Custom Published|Printed', + '2GOR' => 'Advertising|Periodicals|Magazine, Custom Published|Internet Website', + '2GOS' => 'Advertising|Periodicals|Magazine, Custom Published|Internet Downloadable File', + '2AIL' => 'Advertising|Periodicals|Magazine, Custom Published|Internet Email', + '2GOX' => 'Advertising|Periodicals|Magazine, Custom Published|All Internet Distribution Formats', + '2ALP' => 'Advertising|Periodicals|Magazine, Custom Published|Recordable Media', + '2AMI' => 'Advertising|Periodicals|Magazine, Custom Published|All Electronic Distribution Formats', + '2BEN' => 'Advertising|Periodicals|Magazine, Advertorial|Printed', + '2BAP' => 'Advertising|Periodicals|Magazine, Advertorial|Internet Website', + '2BAM' => 'Advertising|Periodicals|Magazine, Advertorial|Internet Downloadable File', + '2BOP' => 'Advertising|Periodicals|Magazine, Advertorial|Internet Email', + '2GOB' => 'Advertising|Periodicals|Magazine, Advertorial|All Internet Distribution Formats', + '2DUH' => 'Advertising|Periodicals|Magazine, Advertorial|All Electronic Distribution Formats', + '2DUP' => 'Advertising|Periodicals|Magazine Reprints, All Types|Printed', + '2HAS' => 'Advertising|Periodicals|Magazine Reprints, All Types|Internet Website', + '2HAP' => 'Advertising|Periodicals|Magazine Reprints, All Types|Internet Downloadable File', + '2AMP' => 'Advertising|Periodicals|Magazine Reprints, All Types|Internet Email', + '2HEH' => 'Advertising|Periodicals|Magazine Reprints, All Types|All Internet Distribution Formats', + '2HAW' => 'Advertising|Periodicals|Magazine Reprints, All Types|Recordable Media', + '2HAY' => 'Advertising|Periodicals|Magazine Reprints, All Types|All Electronic Distribution Formats', + '2MOO' => 'Advertising|Periodicals|Magazine, All Types|Printed', + '2ANA' => 'Advertising|Periodicals|Magazine, All Types|Internet Website', + '2GOO' => 'Advertising|Periodicals|Magazine, All Types|Recordable Media', + '2ANY' => 'Advertising|Periodicals|Magazine, All Types|Internet Downloadable File', + '2APE' => 'Advertising|Periodicals|Magazine, All Types|Internet Email', + '2APT' => 'Advertising|Periodicals|Magazine, All Types|All Internet Distribution Formats', + '2ARK' => 'Advertising|Periodicals|Magazine, All Types|All Electronic Distribution Formats', + '2KEG' => 'Advertising|Periodicals|Newspaper, Weekly Supplement|Printed', + '2HOB' => 'Advertising|Periodicals|Newspaper, Weekly Supplement|Internet Website', + '2HOD' => 'Advertising|Periodicals|Newspaper, Weekly Supplement|Internet Downloadable File', + '2ARM' => 'Advertising|Periodicals|Newspaper, Weekly Supplement|Internet Email', + '2HMM' => 'Advertising|Periodicals|Newspaper, Weekly Supplement|All Internet Distribution Formats', + '2HOE' => 'Advertising|Periodicals|Newspaper, Weekly Supplement|Recordable Media', + '2HIS' => 'Advertising|Periodicals|Newspaper, Weekly Supplement|All Electronic Distribution Formats', + '2KEN' => 'Advertising|Periodicals|Newspaper, Tabloid|Printed', + '2HOY' => 'Advertising|Periodicals|Newspaper, Tabloid|Internet Website', + '2HUH' => 'Advertising|Periodicals|Newspaper, Tabloid|All Internet Distribution Formats', + '2ASH' => 'Advertising|Periodicals|Newspaper, Tabloid|Internet Downloadable File', + '2BAY' => 'Advertising|Periodicals|Newspaper, Tabloid|Internet Email', + '2HUE' => 'Advertising|Periodicals|Newspaper, Tabloid|Recordable Media', + '2HOW' => 'Advertising|Periodicals|Newspaper, Tabloid|All Electronic Distribution Formats', + '2NEW' => 'Advertising|Periodicals|Newspaper, All Types|Printed', + '2HID' => 'Advertising|Periodicals|Newspaper, All Types|Internet Website', + '2HIE' => 'Advertising|Periodicals|Newspaper, All Types|Internet Downloadable File', + '2BED' => 'Advertising|Periodicals|Newspaper, All Types|Internet Email', + '2HIC' => 'Advertising|Periodicals|Newspaper, All Types|All Internet Distribution Formats', + '2HIM' => 'Advertising|Periodicals|Newspaper, All Types|Recordable Media', + '2HEY' => 'Advertising|Periodicals|Newspaper, All Types|All Electronic Distribution Formats', + '2JAY' => 'Advertising|Periodicals|Newsletter, All Types|Printed', + '2HES' => 'Advertising|Periodicals|Newsletter, All Types|Internet Website', + '2HEP' => 'Advertising|Periodicals|Newsletter, All Types|Internet Downloadable File', + '2HEW' => 'Advertising|Periodicals|Newsletter, All Types|All Internet Distribution Formats', + '2BID' => 'Advertising|Periodicals|Newsletter, All Types|Internet Email', + '2HET' => 'Advertising|Periodicals|Newsletter, All Types|Recordable Media', + '2HEN' => 'Advertising|Periodicals|Newsletter, All Types|All Electronic Distribution Formats', + '2BAH' => 'Advertising|Periodicals|Quarterly Report|Printed', + '2HUT' => 'Advertising|Periodicals|Quarterly Report|Internet Website', + '2HUP' => 'Advertising|Periodicals|Quarterly Report|Internet Downloadable File', + '2BAL' => 'Advertising|Periodicals|Quarterly Report|Internet Email', + '2JEE' => 'Advertising|Periodicals|Quarterly Report|All Internet Distribution Formats', + '2HYP' => 'Advertising|Periodicals|Quarterly Report|Recordable Media', + '2JAG' => 'Advertising|Periodicals|Quarterly Report|All Electronic Distribution Formats', + '2ANN' => 'Advertising|Periodicals|Annual Report|Printed', + '2FON' => 'Advertising|Periodicals|Annual Report|Internet Website', + '2FOH' => 'Advertising|Periodicals|Annual Report|Internet Downloadable File', + '2FOP' => 'Advertising|Periodicals|Annual Report|Internet Email', + '2FOY' => 'Advertising|Periodicals|Annual Report|All Internet Distribution Formats', + '2BAS' => 'Advertising|Periodicals|Annual Report|Recordable Media', + '2FOU' => 'Advertising|Periodicals|Annual Report|All Electronic Distribution Formats', + '2KIP' => 'Advertising|Periodicals|Program Advertising|Printed', + '2DEE' => 'Advertising|Periodicals|Wrapper|Printed', + '2FUD' => 'Advertising|Periodicals|Cover Wrap|Printed', + '2FUB' => 'Advertising|Periodicals|Belly Band|Printed', + '2BAT' => 'Advertising|Periodicals|Free Standing Insert, All Insert Types|Printed', + '2HIP' => 'Advertising|Periodicals|Free Standing Insert, Advertorial Insert|Printed', + '2BAG' => 'Advertising|Periodicals|All Periodical Types|Printed', + '2FIZ' => 'Advertising|Periodicals|All Periodical Types|Internet Website', + '2BOD' => 'Advertising|Periodicals|All Periodical Types|Internet Downloadable File', + '2BOW' => 'Advertising|Periodicals|All Periodical Types|Internet Email', + '2FOB' => 'Advertising|Periodicals|All Periodical Types|All Internet Distribution Formats', + '2FIR' => 'Advertising|Periodicals|All Periodical Types|Recordable Media', + '2FLU' => 'Advertising|Periodicals|All Periodical Types|All Electronic Distribution Formats', + '2EDH' => 'Advertising|Marketing Materials|Artist\'s Reference, All Types|Printed', + '2ECU' => 'Advertising|Marketing Materials|Artist\'s Reference, All Types|All Internet Distribution Formats', + '2DOT' => 'Advertising|Marketing Materials|Artist\'s Reference, All Types|All Electronic Distribution Formats', + '2MMA' => 'Advertising|Marketing Materials|Bill Insert|Printed', + '2MMB' => 'Advertising|Marketing Materials|Blow In Card|Printed', + '2MMC' => 'Advertising|Marketing Materials|Bound-in Insert|Printed', + '2MMD' => 'Advertising|Marketing Materials|Broadside|Printed', + '2EGG' => 'Advertising|Marketing Materials|Brochure|Printed', + '2EFF' => 'Advertising|Marketing Materials|Brochure|Internet Downloadable File', + '2EFS' => 'Advertising|Marketing Materials|Brochure|Internet Email', + '2EFT' => 'Advertising|Marketing Materials|Brochure|Recordable Media', + '2MME' => 'Advertising|Marketing Materials|Buckslip|Printed', + '2MMF' => 'Advertising|Marketing Materials|Business Card|Printed', + '2MMG' => 'Advertising|Marketing Materials|Business Envelope|Printed', + '2BIZ' => 'Advertising|Marketing Materials|Card, Business Greeting Card|Printed', + '2MMI' => 'Advertising|Marketing Materials|Business Invitation|Printed', + '2MMJ' => 'Advertising|Marketing Materials|Business Reply Card|Printed', + '2MMK' => 'Advertising|Marketing Materials|Business Reply Envelope|Printed', + '2MML' => 'Advertising|Marketing Materials|Business Stationery|Printed', + '2FIG' => 'Advertising|Marketing Materials|Catalog|Printed', + '2ELL' => 'Advertising|Marketing Materials|Catalog|Internet Downloadable File', + '2ELS' => 'Advertising|Marketing Materials|Catalog|Internet Email', + '2ELF' => 'Advertising|Marketing Materials|Catalog|Recordable Media', + '2EDU' => 'Advertising|Marketing Materials|CD ROM|Recordable Media', + '2MMM' => 'Advertising|Marketing Materials|Compliment Slip|Printed', + '2MMN' => 'Advertising|Marketing Materials|Coupon|Printed', + '2EGO' => 'Advertising|Marketing Materials|Coupon|Internet Downloadable File', + '2ENG' => 'Advertising|Marketing Materials|Coupon|Internet Email', + '2ENS' => 'Advertising|Marketing Materials|Coupon|Recordable Media', + '2MMP' => 'Advertising|Marketing Materials|Coupon Packs|Printed', + '2DVA' => 'Advertising|Marketing Materials|DVD|Recordable Media', + '2MMQ' => 'Advertising|Marketing Materials|Flyaway Card|Printed', + '2FLY' => 'Advertising|Marketing Materials|Flyer|Printed', + '2MMR' => 'Advertising|Marketing Materials|Leaflet|Printed', + '2MMS' => 'Advertising|Marketing Materials|Magalog|Printed', + '2END' => 'Advertising|Marketing Materials|Magalog|Internet Downloadable File', + '2EON' => 'Advertising|Marketing Materials|Magalog|Internet Email', + '2FAX' => 'Advertising|Marketing Materials|Magalog|Recordable Media', + '2MMT' => 'Advertising|Marketing Materials|One Sheet|Printed', + '2MMU' => 'Advertising|Marketing Materials|Onsert|Printed', + '2MMV' => 'Advertising|Marketing Materials|Polybag|Printed', + '2BUN' => 'Advertising|Marketing Materials|Promo Card|Printed', + '2MMW' => 'Advertising|Marketing Materials|Promotional Calendar, One Page|Printed', + '2FAS' => 'Advertising|Marketing Materials|Promotional Calendar, One Page|Internet Downloadable File', + '2FAY' => 'Advertising|Marketing Materials|Promotional Calendar, One Page|Internet Email', + '2GUT' => 'Advertising|Marketing Materials|Promotional Calendar, One Page|Recordable Media', + '2EWE' => 'Advertising|Marketing Materials|Promotional Calendar, One Page|All Electronic Distribution Formats', + '2YAM' => 'Advertising|Marketing Materials|Promotional Calendar, Multi-Page|Printed', + '2ESS' => 'Advertising|Marketing Materials|Promotional Calendar, Multi-Page|Internet Downloadable File', + '2ETA' => 'Advertising|Marketing Materials|Promotional Calendar, Multi-Page|Internet Email', + '2HAD' => 'Advertising|Marketing Materials|Promotional Calendar, Multi-Page|Recordable Media', + '2FET' => 'Advertising|Marketing Materials|Promotional E-card|Internet Email', + '2FEU' => 'Advertising|Marketing Materials|Promotional E-card|All Internet Distribution Formats', + '2FEH' => 'Advertising|Marketing Materials|Promotional E-card|Recordable Media', + '2FEN' => 'Advertising|Marketing Materials|Promotional E-card|Internet Downloadable File', + '2MMX' => 'Advertising|Marketing Materials|Promotional Envelope|Printed', + '2NUT' => 'Advertising|Marketing Materials|Promotional Postcard|Printed', + '2KAF' => 'Advertising|Marketing Materials|Public Relations, Press Kit|Printed', + '2JUT' => 'Advertising|Marketing Materials|Public Relations, Press Kit|Internet Website', + '2JUN' => 'Advertising|Marketing Materials|Public Relations, Press Kit|Internet Downloadable File', + '2JUS' => 'Advertising|Marketing Materials|Public Relations, Press Kit|Internet Email', + '2JOW' => 'Advertising|Marketing Materials|Public Relations, Press Kit|All Internet Distribution Formats', + '2JOB' => 'Advertising|Marketing Materials|Public Relations, Press Kit|Recordable Media', + '2JOE' => 'Advertising|Marketing Materials|Public Relations, Press Kit|All Electronic Distribution Formats', + '2KAB' => 'Advertising|Marketing Materials|Public Relations, Press Kit|Television Broadcast', + '2KEX' => 'Advertising|Marketing Materials|Public Relations, Press Release|Printed', + '2KEA' => 'Advertising|Marketing Materials|Public Relations, Press Release|Internet Website', + '2KAT' => 'Advertising|Marketing Materials|Public Relations, Press Release|Internet Downloadable File', + '2KAY' => 'Advertising|Marketing Materials|Public Relations, Press Release|Internet Email', + '2KAS' => 'Advertising|Marketing Materials|Public Relations, Press Release|Recordable Media', + '2KID' => 'Advertising|Marketing Materials|Public Relations, Press Release|All Electronic Distribution Formats', + '2KEF' => 'Advertising|Marketing Materials|Public Relations, Press Release|Television Broadcast', + '2JIB' => 'Advertising|Marketing Materials|Public Relations, All Types|Printed', + '2MMY' => 'Advertising|Marketing Materials|Sales Kit|Printed', + '2MMZ' => 'Advertising|Marketing Materials|Self Mailer|Printed', + '2JAM' => 'Advertising|Marketing Materials|All Marketing Material Types|Printed', + '2HAM' => 'Advertising|Marketing Materials|All Marketing Material Types|Internet Downloadable File', + '2DYE' => 'Advertising|Marketing Materials|All Marketing Material Types|Internet Email', + '2DUO' => 'Advertising|Marketing Materials|All Marketing Material Types|Recordable Media', + '2BEG' => 'Advertising|Book|Retail Book, Directory|Printed', + '2EAC' => 'Advertising|Book|Retail Book, Directory|E-Book in Internet Website', + '2EAD' => 'Advertising|Book|Retail Book, Directory|E-Book in Internet Downloadable File', + '2EAE' => 'Advertising|Book|Retail Book, Directory|All E-Book Internet Distribution Formats', + '2EAF' => 'Advertising|Book|Retail Book, Directory|E-Book on Recordable Media', + '2EAG' => 'Advertising|Book|Retail Book, Directory|All E-Book Distribution Formats', + '2ELM' => 'Advertising|Book|Textbook, All Types|Printed', + '2EAH' => 'Advertising|Book|Textbook, All Types|E-Book in Internet Website', + '2EAJ' => 'Advertising|Book|Textbook, All Types|E-Book in Internet Downloadable File', + '2EAK' => 'Advertising|Book|Textbook, All Types|All E-Book Internet Distribution Formats', + '2EAL' => 'Advertising|Book|Textbook, All Types|E-Book on Recordable Media', + '2EAM' => 'Advertising|Book|Textbook, All Types|All E-Book Distribution Formats', + '2HOG' => 'Advertising|Book|All Book Types|Printed', + '2EAN' => 'Advertising|Book|All Book Types|All E-Book Internet Distribution Formats', + '2EAP' => 'Advertising|Book|All Book Types|All E-Book Distribution Formats', + '2HEM' => 'Advertising|Display|Billboard, Bulletin|Printed', + '2BUR' => 'Advertising|Display|Billboard, Bulletin|Electronic Display', + '2DAG' => 'Advertising|Display|Billboard, Spectacular|Printed', + '2DAD' => 'Advertising|Display|Billboard, Spectacular|Electronic Display', + '2DAK' => 'Advertising|Display|Billboard, Wallscape|Printed', + '2DAH' => 'Advertising|Display|Billboard, Wallscape|Electronic Display', + '2DAB' => 'Advertising|Display|Billboard, Rotating Billboard|Printed', + '2BLD' => 'Advertising|Display|Billboard, Building Wrap|Printed', + '2BYS' => 'Advertising|Display|Billboard, Mobile Billboard|Printed', + '2BYE' => 'Advertising|Display|Billboard, Mobile Billboard|Electronic Display', + '2BIL' => 'Advertising|Display|Billboard, All Types|Printed', + '2BUD' => 'Advertising|Display|Billboard, All Types|Electronic Display', + '2BRR' => 'Advertising|Display|Banner, Backdrop|Printed', + '2BUB' => 'Advertising|Display|Banner, Background|Printed', + '2BRA' => 'Advertising|Display|Banner, Airborne Display|Printed', + '2BRO' => 'Advertising|Display|Banner, All Types|Printed', + '2BAN' => 'Advertising|Display|Banner, All Types|Electronic Display', + '2CAR' => 'Advertising|Display|Shopping Cart|Printed', + '2CRT' => 'Advertising|Display|Shopping Cart|Electronic Display', + '2FAD' => 'Advertising|Display|Poster, Movie Poster|Printed', + '2HON' => 'Advertising|Display|Poster, Movie Poster|Electronic Display', + '2DIB' => 'Advertising|Display|Poster, Door Side Poster|Printed', + '2DEY' => 'Advertising|Display|Poster, Door Side Poster|Electronic Display', + '2DEV' => 'Advertising|Display|Poster, Corporate Poster|Printed', + '2DEN' => 'Advertising|Display|Poster, Corporate Poster|Electronic Display', + '2ELE' => 'Advertising|Display|Poster, Elevator Advertising|Printed', + '2DID' => 'Advertising|Display|Poster, Elevator Advertising|Electronic Display', + '2DRY' => 'Advertising|Display|Poster, Restroom Poster|Printed', + '2WET' => 'Advertising|Display|Poster, Restroom Poster|Electronic Display', + '2DEL' => 'Advertising|Display|Poster, Backlit Print|Printed', + '2DEX' => 'Advertising|Display|Poster, Display Chrome|Printed', + '2FAT' => 'Advertising|Display|Poster, All Types|Printed', + '2DAW' => 'Advertising|Display|Poster, All Types|Electronic Display', + '2MOB' => 'Advertising|Display|Store Display, In-Store Poster|Printed', + '2DIT' => 'Advertising|Display|Store Display, In-Store Poster|Electronic Display', + '2FOG' => 'Advertising|Display|Store Display, All Display Types|Printed', + '2DIN' => 'Advertising|Display|Store Display, All Display Types|Electronic Display', + '2HOT' => 'Advertising|Display|Terminal Advertising, Airport Display|Printed', + '2JOU' => 'Advertising|Display|Terminal Advertising, Airport Display|Electronic Display', + '2DOM' => 'Advertising|Display|Terminal Advertising, Bus Stop Advertising|Printed', + '2DOL' => 'Advertising|Display|Terminal Advertising, Bus Stop Advertising|Electronic Display', + '2DOR' => 'Advertising|Display|Terminal Advertising, Ferry Terminal Advertising|Printed', + '2DON' => 'Advertising|Display|Terminal Advertising, Ferry Terminal Advertising|Electronic Display', + '2TAN' => 'Advertising|Display|Terminal Advertising, Shelter Advertising|Printed', + '2DOS' => 'Advertising|Display|Terminal Advertising, Shelter Advertising|Electronic Display', + '2DUB' => 'Advertising|Display|Terminal Advertising, Station Poster|Printed', + '2DOW' => 'Advertising|Display|Terminal Advertising, Station Poster|Electronic Display', + '2DUG' => 'Advertising|Display|Terminal Advertising, Subway Terminal Advertising|Printed', + '2DUE' => 'Advertising|Display|Terminal Advertising, Subway Terminal Advertising|Electronic Display', + '2DUN' => 'Advertising|Display|Terminal Advertising, Train Terminal Advertising|Printed', + '2DUI' => 'Advertising|Display|Terminal Advertising, Train Terminal Advertising|Electronic Display', + '2JOY' => 'Advertising|Display|Terminal Advertising, All Types|Printed', + '2DOE' => 'Advertising|Display|Terminal Advertising, All Types|Electronic Display', + '2TAX' => 'Advertising|Display|Transit Advertising, Taxi Advertising|Printed', + '2BUS' => 'Advertising|Display|Transit Advertising, Bus Panel|Printed', + '2TRC' => 'Advertising|Display|Transit Advertising, Bus Panel|Electronic Display', + '2TRE' => 'Advertising|Display|Transit Advertising, Bus Poster|Printed', + '2BPE' => 'Advertising|Display|Transit Advertising, Bus Poster|Electronic Display', + '2TRG' => 'Advertising|Display|Transit Advertising, Bus Rear Display|Printed', + '2TRF' => 'Advertising|Display|Transit Advertising, Bus Rear Display|Electronic Display', + '2TRN' => 'Advertising|Display|Transit Advertising, Bus Wrap|Printed', + '2TRM' => 'Advertising|Display|Transit Advertising, Bus Wrap|Electronic Display', + '2TRJ' => 'Advertising|Display|Transit Advertising, Subway Advertising|Printed', + '2TRI' => 'Advertising|Display|Transit Advertising, Subway Advertising|Electronic Display', + '2TRL' => 'Advertising|Display|Transit Advertising, Train Advertising|Printed', + '2TRK' => 'Advertising|Display|Transit Advertising, Train Advertising|Electronic Display', + '2TRQ' => 'Advertising|Display|Transit Advertising, Commercial Vehicles|Printed', + '2TRR' => 'Advertising|Display|Transit Advertising, Commercial Vehicles|Electronic Display', + '2FER' => 'Advertising|Display|Transit Advertising, Ferry Advertising|Printed', + '2TRH' => 'Advertising|Display|Transit Advertising, Ferry Advertising|Electronic Display', + '2TRA' => 'Advertising|Display|Transit Advertising, All Types|Printed', + '2TRB' => 'Advertising|Display|Transit Advertising, All Types|Electronic Display', + '2DAM' => 'Advertising|Display|Event, Stadium Advertising|Printed', + '2DAL' => 'Advertising|Display|Event, Stadium Advertising|Electronic Display', + '2DIS' => 'Advertising|Display|Event, Trade Show Display|Printed', + '2DAP' => 'Advertising|Display|Event, Trade Show Display|Electronic Display', + '2BIG' => 'Advertising|Display|All Display Types|Printed', + '2BOG' => 'Advertising|Display|All Display Types|Electronic Display', + '2BOY' => 'Advertising|Art|Art Display, Display Print|Printed', + '2ART' => 'Advertising|Art|Art Display, All Art Types|Printed', + '2BEL' => 'Advertising|Art|Art Display, All Art Types|Internet Website', + '2BEY' => 'Advertising|Art|Art Display, All Art Types|All Internet Distribution Formats', + '2BOS' => 'Advertising|Art|Art Display, All Art Types|Electronic Display', + '2BIS' => 'Advertising|Art|Art Display, All Art Types|All Electronic Distribution Formats', + '2ADH' => 'Advertising|Point of Purchase|Adhesive Tag|Printed', + '2BOT' => 'Advertising|Point of Purchase|Bottlenecker|Printed', + '2CAS' => 'Advertising|Point of Purchase|Case Card|Printed', + '2COU' => 'Advertising|Point of Purchase|Counter Card|Printed', + '2BUY' => 'Advertising|Point of Purchase|Floor Graphic|Printed', + '2TAG' => 'Advertising|Point of Purchase|Hang Tag|Printed', + '2GYM' => 'Advertising|Point of Purchase|Kiosk, Interactive Kiosk|Printed', + '2GUN' => 'Advertising|Point of Purchase|Kiosk, Interactive Kiosk|Electronic Display', + '2JUG' => 'Advertising|Point of Purchase|Kiosk, Telephone Kiosk|Printed', + '2FIN' => 'Advertising|Point of Purchase|Kiosk, All Types|Printed', + '2KIO' => 'Advertising|Point of Purchase|Kiosk, All Types|Electronic Display', + '2MEN' => 'Advertising|Point of Purchase|Menu|Printed', + '2TAL' => 'Advertising|Point of Purchase|Shelf Talker|Printed', + '2TIN' => 'Advertising|Point of Purchase|Slip Case|Printed', + '2WAX' => 'Advertising|Point of Purchase|Table Tent|Printed', + '2BIN' => 'Advertising|Point of Purchase|All Point of Purchase Types|Printed', + '2BIB' => 'Advertising|Point of Purchase|All Point of Purchase Types|Electronic Display', + '2BAR' => 'Advertising|Point of Purchase|All Point of Purchase Types|All Electronic Distribution Formats', + '2MAR' => 'Advertising|Website|Web Page, Design Element|Internet Website', + '2MAX' => 'Advertising|Website|Web Page, Design Element|All Internet Distribution Formats', + '2MAS' => 'Advertising|Website|Web Page, Design Element|Recordable Media', + '2MAW' => 'Advertising|Website|Web Page, Design Element|All Electronic Distribution Formats', + '2MED' => 'Advertising|Website|Web Page, Web Banner Ad|Internet Website', + '2MEW' => 'Advertising|Website|Web Page, Web Banner Ad|All Internet Distribution Formats', + '2MEG' => 'Advertising|Website|Web Page, Web Banner Ad|Recordable Media', + '2MEM' => 'Advertising|Website|Web Page, Web Banner Ad|All Electronic Distribution Formats', + '2JWL' => 'Advertising|Website|Web Page, Web Interstitial Ad|Internet Website', + '2MIG' => 'Advertising|Website|Web Page, Web Interstitial Ad|All Internet Distribution Formats', + '2MIB' => 'Advertising|Website|Web Page, Web Interstitial Ad|Recordable Media', + '2MID' => 'Advertising|Website|Web Page, Web Interstitial Ad|All Electronic Distribution Formats', + '2WEB' => 'Advertising|Website|Web Page, All Types|Internet Website', + '2KUE' => 'Advertising|Website|Web Page, All Types|All Internet Distribution Formats', + '2MAC' => 'Advertising|Website|Web Page, All Types|Recordable Media', + '2MAE' => 'Advertising|Website|Web Page, All Types|All Electronic Distribution Formats', + '2MIL' => 'Advertising|Website|Webcast, All Types|Internet Website', + '2EMA' => 'Advertising|Email|All Email Types|Internet Email', + '2ZUS' => 'Advertising|Mobile|All Mobile Types|Mobile', + '2FUR' => 'Advertising|Live Presentation|Sales Presentation|Projected Display', + '2EYE' => 'Advertising|Live Presentation|Panel Presentation|Projected Display', + '2TOE' => 'Advertising|Live Presentation|Trade Show Presentation|Projected Display', + '2JAW' => 'Advertising|Live Presentation|Stage Performance|Projected Display', + '2EAR' => 'Advertising|Live Presentation|All Live Presentation Types|All Electronic Distribution Formats', + '2FID' => 'Advertising|Merchandise|Apparel, T-Shirts|Printed or Woven', + '2FEZ' => 'Advertising|Merchandise|Apparel, General Apparel|Printed or Woven', + '2FIE' => 'Advertising|Merchandise|Folder|Printed', + '2AAY' => 'Advertising|All Media Types|Promotional Reproduction of Licensed Usage in Context|All Distribution Formats', + '2AAA' => 'Advertising|All Media Types|All Formats|All Distribution Formats', + '2GEM' => 'Editorial|Periodicals|Magazine, Consumer|Printed', + '2GDW' => 'Editorial|Periodicals|Magazine, Consumer|Internet Website', + '2GDY' => 'Editorial|Periodicals|Magazine, Consumer|Internet Downloadable File', + '2KIN' => 'Editorial|Periodicals|Magazine, Consumer|Internet Email', + '2GEA' => 'Editorial|Periodicals|Magazine, Consumer|All Internet Distribution Formats', + '2GDV' => 'Editorial|Periodicals|Magazine, Consumer|Recordable Media', + '2GDZ' => 'Editorial|Periodicals|Magazine, Consumer|All Electronic Distribution Formats', + '2MOM' => 'Editorial|Periodicals|Magazine, Trade|Printed', + '2MOW' => 'Editorial|Periodicals|Magazine, Trade|Internet Website', + '2MUT' => 'Editorial|Periodicals|Magazine, Trade|Internet Downloadable File', + '2NAB' => 'Editorial|Periodicals|Magazine, Trade|Internet Email', + '2NAG' => 'Editorial|Periodicals|Magazine, Trade|All Internet Distribution Formats', + '2GFD' => 'Editorial|Periodicals|Magazine, Trade|Recordable Media', + '2NOB' => 'Editorial|Periodicals|Magazine, Trade|All Electronic Distribution Formats', + '2MAY' => 'Editorial|Periodicals|Magazine, Education|Printed', + '2GEP' => 'Editorial|Periodicals|Magazine, Education|Internet Website', + '2GEQ' => 'Editorial|Periodicals|Magazine, Education|Internet Downloadable File', + '2NOW' => 'Editorial|Periodicals|Magazine, Education|Internet Email', + '2GES' => 'Editorial|Periodicals|Magazine, Education|All Internet Distribution Formats', + '2GEK' => 'Editorial|Periodicals|Magazine, Education|Recordable Media', + '2GER' => 'Editorial|Periodicals|Magazine, Education|All Electronic Distribution Formats', + '2MOP' => 'Editorial|Periodicals|Magazine, Custom Published|Printed', + '2GEF' => 'Editorial|Periodicals|Magazine, Custom Published|Internet Website', + '2GEG' => 'Editorial|Periodicals|Magazine, Custom Published|Internet Downloadable File', + '2NUN' => 'Editorial|Periodicals|Magazine, Custom Published|Internet Email', + '2GEI' => 'Editorial|Periodicals|Magazine, Custom Published|All Internet Distribution Formats', + '2GEC' => 'Editorial|Periodicals|Magazine, Custom Published|Recordable Media', + '2GEH' => 'Editorial|Periodicals|Magazine, Custom Published|All Electronic Distribution Formats', + '2MEL' => 'Editorial|Periodicals|Magazine, Partworks|Printed', + '2GEV' => 'Editorial|Periodicals|Magazine, Partworks|Internet Website', + '2GEW' => 'Editorial|Periodicals|Magazine, Partworks|Internet Downloadable File', + '2TAB' => 'Editorial|Periodicals|Magazine, Partworks|Internet Email', + '2GFB' => 'Editorial|Periodicals|Magazine, Partworks|All Internet Distribution Formats', + '2GEZ' => 'Editorial|Periodicals|Magazine, Partworks|Recordable Media', + '2GFA' => 'Editorial|Periodicals|Magazine, Partworks|All Electronic Distribution Formats', + '2WIG' => 'Editorial|Periodicals|Scholarly Journal|Printed', + '2GGF' => 'Editorial|Periodicals|Scholarly Journal|Internet Website', + '2GGG' => 'Editorial|Periodicals|Scholarly Journal|Internet Downloadable File', + '2TAD' => 'Editorial|Periodicals|Scholarly Journal|Internet Email', + '2GGI' => 'Editorial|Periodicals|Scholarly Journal|All Internet Distribution Formats', + '2GGD' => 'Editorial|Periodicals|Scholarly Journal|Recordable Media', + '2GGH' => 'Editorial|Periodicals|Scholarly Journal|All Electronic Distribution Formats', + '2MAG' => 'Editorial|Periodicals|Magazine, All Types|Printed', + '2GDP' => 'Editorial|Periodicals|Magazine, All Types|Internet Website', + '2GDM' => 'Editorial|Periodicals|Magazine, All Types|Internet Downloadable File', + '2GDQ' => 'Editorial|Periodicals|Magazine, All Types|Internet Email', + '2GDT' => 'Editorial|Periodicals|Magazine, All Types|All Internet Distribution Formats', + '2GDR' => 'Editorial|Periodicals|Magazine, All Types|Recordable Media', + '2GDS' => 'Editorial|Periodicals|Magazine, All Types|All Electronic Distribution Formats', + '2JET' => 'Editorial|Periodicals|Newspaper, All Types|Printed', + '2GFN' => 'Editorial|Periodicals|Newspaper, All Types|Internet Website', + '2GFP' => 'Editorial|Periodicals|Newspaper, All Types|Internet Downloadable File', + '2TAJ' => 'Editorial|Periodicals|Newspaper, All Types|Internet Email', + '2GFR' => 'Editorial|Periodicals|Newspaper, All Types|All Internet Distribution Formats', + '2GFM' => 'Editorial|Periodicals|Newspaper, All Types|Recordable Media', + '2GFQ' => 'Editorial|Periodicals|Newspaper, All Types|All Electronic Distribution Formats', + '2TUB' => 'Editorial|Periodicals|Newspaper, Weekly Supplement|Printed', + '2GFW' => 'Editorial|Periodicals|Newspaper, Weekly Supplement|Internet Website', + '2GFY' => 'Editorial|Periodicals|Newspaper, Weekly Supplement|Internet Downloadable File', + '2TAO' => 'Editorial|Periodicals|Newspaper, Weekly Supplement|Internet Email', + '2GFV' => 'Editorial|Periodicals|Newspaper, Weekly Supplement|All Internet Distribution Formats', + '2GFS' => 'Editorial|Periodicals|Newspaper, Weekly Supplement|Recordable Media', + '2GFU' => 'Editorial|Periodicals|Newspaper, Weekly Supplement|All Electronic Distribution Formats', + '2FAN' => 'Editorial|Periodicals|Newspaper, Tabloid|Printed', + '2TEX' => 'Editorial|Periodicals|Newspaper, Tabloid|Internet Website', + '2GGA' => 'Editorial|Periodicals|Newspaper, Tabloid|Internet Downloadable File', + '2TIP' => 'Editorial|Periodicals|Newspaper, Tabloid|Internet Email', + '2TON' => 'Editorial|Periodicals|Newspaper, Tabloid|All Internet Distribution Formats', + '2TIE' => 'Editorial|Periodicals|Newspaper, Tabloid|Recordable Media', + '2TOT' => 'Editorial|Periodicals|Newspaper, Tabloid|All Electronic Distribution Formats', + '2TOM' => 'Editorial|Periodicals|Newsletter|Printed', + '2GFH' => 'Editorial|Periodicals|Newsletter|Internet Website', + '2GFI' => 'Editorial|Periodicals|Newsletter|Internet Downloadable File', + '2NEL' => 'Editorial|Periodicals|Newsletter|Internet Email', + '2GFK' => 'Editorial|Periodicals|Newsletter|All Internet Distribution Formats', + '2GFG' => 'Editorial|Periodicals|Newsletter|Recordable Media', + '2GFJ' => 'Editorial|Periodicals|Newsletter|All Electronic Distribution Formats', + '2BUG' => 'Editorial|Book|Retail Book, Children\'s Book|Printed', + '2EPC' => 'Editorial|Book|Retail Book, Children\'s Book|E-Book in Internet Website', + '2EBE' => 'Editorial|Book|Retail Book, Children\'s Book|E-Book in Internet Downloadable File', + '2EGB' => 'Editorial|Book|Retail Book, Children\'s Book|E-Book in Internet Email', + '2EKB' => 'Editorial|Book|Retail Book, Children\'s Book|All E-Book Internet Distribution Formats', + '2ERB' => 'Editorial|Book|Retail Book, Children\'s Book|E-Book on Recordable Media', + '2EGC' => 'Editorial|Book|Retail Book, Children\'s Book|All E-Book Distribution Formats', + '2TAE' => 'Editorial|Book|Retail Book, Coffee Table Book|Printed', + '2TAV' => 'Editorial|Book|Retail Book, Concept Book|Printed', + '2EPD' => 'Editorial|Book|Retail Book, Concept Book|E-Book in Internet Website', + '2EBF' => 'Editorial|Book|Retail Book, Concept Book|E-Book in Internet Downloadable File', + '2EGD' => 'Editorial|Book|Retail Book, Concept Book|E-Book in Internet Email', + '2EKC' => 'Editorial|Book|Retail Book, Concept Book|All E-Book Internet Distribution Formats', + '2ERC' => 'Editorial|Book|Retail Book, Concept Book|E-Book on Recordable Media', + '2EGE' => 'Editorial|Book|Retail Book, Concept Book|All E-Book Distribution Formats', + '2DIR' => 'Editorial|Book|Retail Book, Directory|Printed', + '2EPE' => 'Editorial|Book|Retail Book, Directory|E-Book in Internet Website', + '2EBG' => 'Editorial|Book|Retail Book, Directory|E-Book in Internet Downloadable File', + '2ERD' => 'Editorial|Book|Retail Book, Directory|E-Book on Recordable Media', + '2YEA' => 'Editorial|Book|Retail Book, Directory|All Electronic Distribution Formats', + '2EAB' => 'Editorial|Book|Retail Book, Directory|All E-Book Distribution Formats', + '2HAN' => 'Editorial|Book|Retail Book, Handbook|Printed', + '2EPF' => 'Editorial|Book|Retail Book, Handbook|E-Book in Internet Website', + '2EBH' => 'Editorial|Book|Retail Book, Handbook|E-Book in Internet Downloadable File', + '2EGH' => 'Editorial|Book|Retail Book, Handbook|E-Book in Internet Email', + '2EKD' => 'Editorial|Book|Retail Book, Handbook|All E-Book Internet Distribution Formats', + '2ERF' => 'Editorial|Book|Retail Book, Handbook|E-Book on Recordable Media', + '2EGJ' => 'Editorial|Book|Retail Book, Handbook|All E-Book Distribution Formats', + '2HIL' => 'Editorial|Book|Retail Book, Hi-lo Book|Printed', + '2EPG' => 'Editorial|Book|Retail Book, Hi-lo Book|E-Book in Internet Website', + '2EBI' => 'Editorial|Book|Retail Book, Hi-lo Book|E-Book in Internet Downloadable File', + '2EGK' => 'Editorial|Book|Retail Book, Hi-lo Book|E-Book in Internet Email', + '2EKE' => 'Editorial|Book|Retail Book, Hi-lo Book|All E-Book Internet Distribution Formats', + '2ERG' => 'Editorial|Book|Retail Book, Hi-lo Book|E-Book on Recordable Media', + '2EGL' => 'Editorial|Book|Retail Book, Hi-lo Book|All E-Book Distribution Formats', + '2WAB' => 'Editorial|Book|Retail Book, Illustrated Book|Printed', + '2EPH' => 'Editorial|Book|Retail Book, Illustrated Book|E-Book in Internet Website', + '2EBJ' => 'Editorial|Book|Retail Book, Illustrated Book|E-Book in Internet Downloadable File', + '2EGM' => 'Editorial|Book|Retail Book, Illustrated Book|E-Book in Internet Email', + '2EKF' => 'Editorial|Book|Retail Book, Illustrated Book|All E-Book Internet Distribution Formats', + '2ERH' => 'Editorial|Book|Retail Book, Illustrated Book|E-Book on Recordable Media', + '2EGN' => 'Editorial|Book|Retail Book, Illustrated Book|All E-Book Distribution Formats', + '2WHA' => 'Editorial|Book|Retail Book, Illustrated Guide|Printed', + '2EPJ' => 'Editorial|Book|Retail Book, Illustrated Guide|E-Book in Internet Website', + '2EBL' => 'Editorial|Book|Retail Book, Illustrated Guide|E-Book in Internet Downloadable File', + '2EGP' => 'Editorial|Book|Retail Book, Illustrated Guide|E-Book in Internet Email', + '2EKG' => 'Editorial|Book|Retail Book, Illustrated Guide|All E-Book Internet Distribution Formats', + '2ERI' => 'Editorial|Book|Retail Book, Illustrated Guide|E-Book on Recordable Media', + '2EGQ' => 'Editorial|Book|Retail Book, Illustrated Guide|All E-Book Distribution Formats', + '2EGR' => 'Editorial|Book|Retail Book, Illustrated Guide|All E-Book Distribution Formats', + '2MAN' => 'Editorial|Book|Retail Book, Manual|Printed', + '2EPK' => 'Editorial|Book|Retail Book, Manual|E-Book in Internet Website', + '2EBM' => 'Editorial|Book|Retail Book, Manual|E-Book in Internet Downloadable File', + '2EGS' => 'Editorial|Book|Retail Book, Manual|E-Book in Internet Email', + '2EKH' => 'Editorial|Book|Retail Book, Manual|All E-Book Internet Distribution Formats', + '2ERJ' => 'Editorial|Book|Retail Book, Manual|E-Book on Recordable Media', + '2EGT' => 'Editorial|Book|Retail Book, Manual|All E-Book Distribution Formats', + '2YAP' => 'Editorial|Book|Retail Book, Novelty Book|Printed', + '2EPL' => 'Editorial|Book|Retail Book, Novelty Book|E-Book in Internet Website', + '2EBN' => 'Editorial|Book|Retail Book, Novelty Book|E-Book in Internet Downloadable File', + '2EGV' => 'Editorial|Book|Retail Book, Novelty Book|E-Book in Internet Email', + '2EKJ' => 'Editorial|Book|Retail Book, Novelty Book|All E-Book Internet Distribution Formats', + '2ERK' => 'Editorial|Book|Retail Book, Novelty Book|E-Book on Recordable Media', + '2EGW' => 'Editorial|Book|Retail Book, Novelty Book|All E-Book Distribution Formats', + '2YEN' => 'Editorial|Book|Retail Book, Postcard Book|Printed', + '2EPM' => 'Editorial|Book|Retail Book, Postcard Book|E-Book in Internet Website', + '2EBP' => 'Editorial|Book|Retail Book, Postcard Book|E-Book in Internet Downloadable File', + '2EGY' => 'Editorial|Book|Retail Book, Postcard Book|E-Book in Internet Email', + '2EKK' => 'Editorial|Book|Retail Book, Postcard Book|All E-Book Internet Distribution Formats', + '2ERL' => 'Editorial|Book|Retail Book, Postcard Book|E-Book on Recordable Media', + '2EGZ' => 'Editorial|Book|Retail Book, Postcard Book|All E-Book Distribution Formats', + '2YOK' => 'Editorial|Book|Retail Book, Young Adult Book|Printed', + '2EPN' => 'Editorial|Book|Retail Book, Young Adult Book|E-Book in Internet Website', + '2EBQ' => 'Editorial|Book|Retail Book, Young Adult Book|E-Book in Internet Downloadable File', + '2EJB' => 'Editorial|Book|Retail Book, Young Adult Book|E-Book in Internet Email', + '2EKL' => 'Editorial|Book|Retail Book, Young Adult Book|All E-Book Internet Distribution Formats', + '2ERM' => 'Editorial|Book|Retail Book, Young Adult Book|E-Book on Recordable Media', + '2EJC' => 'Editorial|Book|Retail Book, Young Adult Book|All E-Book Distribution Formats', + '2BOO' => 'Editorial|Book|Retail Book, All Types|Printed', + '2EPB' => 'Editorial|Book|Retail Book, All Types|E-Book in Internet Website', + '2EBC' => 'Editorial|Book|Retail Book, All Types|E-Book in Internet Downloadable File', + '2EJD' => 'Editorial|Book|Retail Book, All Types|E-Book in Internet Email', + '2EKM' => 'Editorial|Book|Retail Book, All Types|All E-Book Internet Distribution Formats', + '2ERN' => 'Editorial|Book|Retail Book, All Types|E-Book on Recordable Media', + '2EJE' => 'Editorial|Book|Retail Book, All Types|All E-Book Distribution Formats', + '2EEL' => 'Editorial|Book|Textbook, Compendium|Printed', + '2EPQ' => 'Editorial|Book|Textbook, Compendium|E-Book in Internet Website', + '2EBS' => 'Editorial|Book|Textbook, Compendium|E-Book in Internet Downloadable File', + '2EJF' => 'Editorial|Book|Textbook, Compendium|E-Book in Internet Email', + '2EKN' => 'Editorial|Book|Textbook, Compendium|All E-Book Internet Distribution Formats', + '2ERP' => 'Editorial|Book|Textbook, Compendium|E-Book on Recordable Media', + '2EJJ' => 'Editorial|Book|Textbook, Compendium|All E-Book Distribution Formats', + '2EMU' => 'Editorial|Book|Textbook, Course Pack|Printed', + '2GBN' => 'Editorial|Book|Textbook, Course Pack|Internet Website', + '2GBM' => 'Editorial|Book|Textbook, Course Pack|Internet Downloadable File', + '2ZOO' => 'Editorial|Book|Textbook, Course Pack|Internet Email', + '2GBQ' => 'Editorial|Book|Textbook, Course Pack|All Internet Distribution Formats', + '2ZOA' => 'Editorial|Book|Textbook, Course Pack|Recordable Media', + '2GBP' => 'Editorial|Book|Textbook, Course Pack|All Distribution Formats', + '2BEE' => 'Editorial|Book|Textbook, Middle Reader|Printed', + '2EPR' => 'Editorial|Book|Textbook, Middle Reader|E-Book in Internet Website', + '2EBT' => 'Editorial|Book|Textbook, Middle Reader|E-Book in Internet Downloadable File', + '2EJK' => 'Editorial|Book|Textbook, Middle Reader|E-Book in Internet Email', + '2EKP' => 'Editorial|Book|Textbook, Middle Reader|All E-Book Internet Distribution Formats', + '2ERQ' => 'Editorial|Book|Textbook, Middle Reader|E-Book on Recordable Media', + '2EJL' => 'Editorial|Book|Textbook, Middle Reader|All E-Book Distribution Formats', + '2BOA' => 'Editorial|Book|Textbook, Student Edition|Printed', + '2EPS' => 'Editorial|Book|Textbook, Student Edition|E-Book in Internet Website', + '2EBV' => 'Editorial|Book|Textbook, Student Edition|E-Book in Internet Downloadable File', + '2EJM' => 'Editorial|Book|Textbook, Student Edition|E-Book in Internet Email', + '2EKQ' => 'Editorial|Book|Textbook, Student Edition|All E-Book Internet Distribution Formats', + '2ERS' => 'Editorial|Book|Textbook, Student Edition|E-Book on Recordable Media', + '2EJN' => 'Editorial|Book|Textbook, Student Edition|All E-Book Distribution Formats', + '2FOX' => 'Editorial|Book|Textbook, All Types|Printed', + '2EPP' => 'Editorial|Book|Textbook, All Types|E-Book in Internet Website', + '2EBR' => 'Editorial|Book|Textbook, All Types|E-Book in Internet Downloadable File', + '2EGA' => 'Editorial|Book|Textbook, All Types|E-Book in Internet Email', + '2EKR' => 'Editorial|Book|Textbook, All Types|All E-Book Internet Distribution Formats', + '2ERT' => 'Editorial|Book|Textbook, All Types|E-Book on Recordable Media', + '2EJP' => 'Editorial|Book|Textbook, All Types|All E-Book Distribution Formats', + '2GBZ' => 'Editorial|Book|Textbook Ancillary Materials, Educational Film Set|Projected Display', + '2YET' => 'Editorial|Book|Textbook Ancillary Materials, Packaging For Recordable Media|Printed', + '2YUM' => 'Editorial|Book|Textbook Ancillary Materials, Lab Manual|Printed', + '2EPZ' => 'Editorial|Book|Textbook Ancillary Materials, Lab Manual|E-Book in Internet Website', + '2EBA' => 'Editorial|Book|Textbook Ancillary Materials, Lab Manual|E-Book in Internet Downloadable File', + '2EJQ' => 'Editorial|Book|Textbook Ancillary Materials, Lab Manual|E-Book in Internet Email', + '2EKS' => 'Editorial|Book|Textbook Ancillary Materials, Lab Manual|All E-Book Internet Distribution Formats', + '2ERU' => 'Editorial|Book|Textbook Ancillary Materials, Lab Manual|E-Book on Recordable Media', + '2EJR' => 'Editorial|Book|Textbook Ancillary Materials, Lab Manual|All E-Book Distribution Formats', + '2YAK' => 'Editorial|Book|Textbook Ancillary Materials, Teachers\' Edition|Printed', + '2EPT' => 'Editorial|Book|Textbook Ancillary Materials, Teachers\' Edition|E-Book in Internet Website', + '2EBW' => 'Editorial|Book|Textbook Ancillary Materials, Teachers\' Edition|E-Book in Internet Downloadable File', + '2EJS' => 'Editorial|Book|Textbook Ancillary Materials, Teachers\' Edition|E-Book in Internet Email', + '2EKT' => 'Editorial|Book|Textbook Ancillary Materials, Teachers\' Edition|All E-Book Internet Distribution Formats', + '2ERV' => 'Editorial|Book|Textbook Ancillary Materials, Teachers\' Edition|E-Book on Recordable Media', + '2EJT' => 'Editorial|Book|Textbook Ancillary Materials, Teachers\' Edition|All E-Book Distribution Formats', + '2ZOT' => 'Editorial|Book|Textbook Ancillary Materials, Teacher\'s Manual|Printed', + '2EPW' => 'Editorial|Book|Textbook Ancillary Materials, Teacher\'s Manual|E-Book in Internet Website', + '2EBD' => 'Editorial|Book|Textbook Ancillary Materials, Teacher\'s Manual|E-Book in Internet Downloadable File', + '2EJV' => 'Editorial|Book|Textbook Ancillary Materials, Teacher\'s Manual|E-Book in Internet Email', + '2EKU' => 'Editorial|Book|Textbook Ancillary Materials, Teacher\'s Manual|All E-Book Internet Distribution Formats', + '2ERW' => 'Editorial|Book|Textbook Ancillary Materials, Teacher\'s Manual|E-Book on Recordable Media', + '2EJW' => 'Editorial|Book|Textbook Ancillary Materials, Teacher\'s Manual|All E-Book Distribution Formats', + '2GEE' => 'Editorial|Book|Textbook Ancillary Materials, Workbook|Printed', + '2EPY' => 'Editorial|Book|Textbook Ancillary Materials, Workbook|E-Book in Internet Website', + '2EBB' => 'Editorial|Book|Textbook Ancillary Materials, Workbook|E-Book in Internet Downloadable File', + '2EJY' => 'Editorial|Book|Textbook Ancillary Materials, Workbook|E-Book in Internet Email', + '2EKV' => 'Editorial|Book|Textbook Ancillary Materials, Workbook|All E-Book Internet Distribution Formats', + '2ERY' => 'Editorial|Book|Textbook Ancillary Materials, Workbook|E-Book on Recordable Media', + '2EJZ' => 'Editorial|Book|Textbook Ancillary Materials, Workbook|All E-Book Distribution Formats', + '2ELK' => 'Editorial|Book|Textbook Ancillary Materials, All Ancillary Types|Printed', + '2GBY' => 'Editorial|Book|Textbook Ancillary Materials, All Ancillary Types|All Internet Distribution Formats', + '2GBW' => 'Editorial|Book|Textbook Ancillary Materials, All Ancillary Types|All Distribution Formats', + '2NAY' => 'Editorial|Book|Reference Book, Encyclopedia|Printed', + '2EAQ' => 'Editorial|Book|Reference Book, Encyclopedia|E-Book in Internet Website', + '2EMB' => 'Editorial|Book|Reference Book, Encyclopedia|E-Book in Internet Downloadable File', + '2EMC' => 'Editorial|Book|Reference Book, Encyclopedia|All E-Book Internet Distribution Formats', + '2EMD' => 'Editorial|Book|Reference Book, Encyclopedia|E-Book on Recordable Media', + '2NAH' => 'Editorial|Book|Reference Book, Encyclopedia|All Electronic Distribution Formats', + '2NIP' => 'Editorial|Book|Reference Book, Telephone Book|Printed', + '2EMF' => 'Editorial|Book|Reference Book, Telephone Book|E-Book in Internet Website', + '2EMG' => 'Editorial|Book|Reference Book, Telephone Book|E-Book in Internet Downloadable File', + '2EMH' => 'Editorial|Book|Reference Book, Telephone Book|All E-Book Internet Distribution Formats', + '2EMI' => 'Editorial|Book|Reference Book, Telephone Book|E-Book on Recordable Media', + '2EMJ' => 'Editorial|Book|Reference Book, Telephone Book|All E-Book Distribution Formats', + '2DOG' => 'Editorial|Book|Reference Book, All Types|Printed', + '2EMK' => 'Editorial|Book|Reference Book, All Types|E-Book in Internet Website', + '2EML' => 'Editorial|Book|Reference Book, All Types|E-Book in Internet Downloadable File', + '2EMM' => 'Editorial|Book|Reference Book, All Types|All E-Book Internet Distribution Formats', + '2EMN' => 'Editorial|Book|Reference Book, All Types|E-Book on Recordable Media', + '2EMP' => 'Editorial|Book|Reference Book, All Types|All E-Book Distribution Formats', + '2DEW' => 'Editorial|Book|Trade Book, All Types|Printed', + '2EPV' => 'Editorial|Book|Trade Book, All Types|E-Book in Internet Website', + '2EMQ' => 'Editorial|Book|Trade Book, All Types|E-Book in Internet Downloadable File', + '2EMR' => 'Editorial|Book|Trade Book, All Types|E-Book in Internet Email', + '2EMS' => 'Editorial|Book|Trade Book, All Types|All E-Book Internet Distribution Formats', + '2ERA' => 'Editorial|Book|Trade Book, All Types|E-Book on Recordable Media', + '2EMT' => 'Editorial|Book|Trade Book, All Types|All E-Book Distribution Formats', + '2MOG' => 'Editorial|Book|All Book Types|Printed', + '2EPA' => 'Editorial|Book|All Book Types|E-Book in Internet Website', + '2EBK' => 'Editorial|Book|All Book Types|E-Book in Internet Downloadable File', + '2EJU' => 'Editorial|Book|All Book Types|E-Book in Internet Email', + '2EKA' => 'Editorial|Book|All Book Types|All E-Book Internet Distribution Formats', + '2ERZ' => 'Editorial|Book|All Book Types|E-Book on Recordable Media', + '2EJA' => 'Editorial|Book|All Book Types|All E-Book Distribution Formats', + '2MOR' => 'Editorial|Book|Artist\'s Reference, All Types|Printed', + '2EKW' => 'Editorial|Book|Artist\'s Reference, All Types|All E-Book Internet Distribution Formats', + '2EMV' => 'Editorial|Book|Artist\'s Reference, All Types|All E-Book Distribution Formats', + '2GAL' => 'Editorial|Display|Gallery Exhibition|Printed', + '2GDJ' => 'Editorial|Display|Gallery Exhibition|Electronic Display', + '2MUS' => 'Editorial|Display|Museum Display|Printed', + '2GDK' => 'Editorial|Display|Museum Display|Electronic Display', + '2EAU' => 'Editorial|Display|Poster, Educational Poster|Printed', + '2GHG' => 'Editorial|Website|Web Page, Body Content|Internet Website', + '2GHK' => 'Editorial|Website|Web Page, Body Content|All Internet Distribution Formats', + '2GHH' => 'Editorial|Website|Web Page, Body Content|Recordable Media', + '2GHJ' => 'Editorial|Website|Web Page, Body Content|All Electronic Distribution Formats', + '2GHB' => 'Editorial|Website|Web Page, All Types|Internet Website', + '2GHF' => 'Editorial|Website|Web Page, All Types|All Internet Distribution Formats', + '2GHC' => 'Editorial|Website|Web Page, All Types|Recordable Media', + '2GHD' => 'Editorial|Website|Web Page, All Types|All Electronic Distribution Formats', + '2GHA' => 'Editorial|Website|Webcast, All Types|Internet Website', + '2ZAG' => 'Editorial|Mobile|All Mobile Types|Mobile', + '2GGM' => 'Editorial|Merchandise|CD ROM|Recordable Media', + '2DVE' => 'Editorial|Merchandise|DVD|Recordable Media', + '2AAE' => 'Editorial|All Media Types|All Formats|All Distribution Formats', + '2ZIG' => 'Products|Mobile|Wallpaper|Mobile', + '2ZIP' => 'Products|Mobile|Game, All Types|Mobile', + '2ZAP' => 'Products|Mobile|Entertainment Programming|Mobile', + '2ZEN' => 'Products|Mobile|Computer Software|Mobile', + '2ZAM' => 'Products|Mobile|All Mobile Types|Mobile', + '2ADD' => 'Products|Merchandise|Address Book|Printed', + '2ANT' => 'Products|Merchandise|Anthology|Printed', + '2APP' => 'Products|Merchandise|Apparel, General Apparel|Printed or Woven', + '2TST' => 'Products|Merchandise|Apparel, T-Shirts|Printed or Woven', + '2BIO' => 'Products|Merchandise|Birthday Book|Printed', + '2BLA' => 'Products|Merchandise|Blank Note Book|Printed', + '2ATM' => 'Products|Merchandise|Card, ATM Card|Printed', + '2BNK' => 'Products|Merchandise|Card, Bank Card|Printed', + '2CRE' => 'Products|Merchandise|Card, Credit Card|Printed', + '2BIT' => 'Products|Merchandise|Card, Debit Card|Printed', + '2GFT' => 'Products|Merchandise|Card, Gift Card|Printed', + '2GRE' => 'Products|Merchandise|Card, Greeting Card|Printed', + '2HER' => 'Products|Merchandise|Card, Hero Card|Printed', + '2CRD' => 'Products|Merchandise|Card, Other Card|Printed', + '2ATT' => 'Products|Merchandise|Card, Phone Card|Printed', + '2CDR' => 'Products|Merchandise|CD ROM|Recordable Media', + '2CHK' => 'Products|Merchandise|Check|Printed', + '2BAK' => 'Products|Merchandise|Computer Software|Internet Downloadable File', + '2BAU' => 'Products|Merchandise|Computer Software|Internet Email', + '2BAV' => 'Products|Merchandise|Computer Software|All Internet Distribution Formats', + '2BAJ' => 'Products|Merchandise|Computer Software|Recordable Media', + '2WAR' => 'Products|Merchandise|Computer Software|All Electronic Distribution Formats', + '2GIG' => 'Products|Merchandise|Datebook|Printed', + '2DIA' => 'Products|Merchandise|Diary|Printed', + '2BAZ' => 'Products|Merchandise|Diary|Internet Downloadable File', + '2BBA' => 'Products|Merchandise|Diary|Internet Email', + '2BAW' => 'Products|Merchandise|Diary|Recordable Media', + '2HUB' => 'Products|Merchandise|Double Postcard|Printed', + '2DVD' => 'Products|Merchandise|DVD|Recordable Media', + '2EAT' => 'Products|Merchandise|Edible Media|Printed', + '2FOL' => 'Products|Merchandise|Folder|Printed', + '2GAB' => 'Products|Merchandise|Game, Computer Game|Internet Downloadable File', + '2GAH' => 'Products|Merchandise|Game, Computer Game|Internet Email', + '2GAE' => 'Products|Merchandise|Game, Computer Game|All Internet Distribution Formats', + '2GAG' => 'Products|Merchandise|Game, Computer Game|Recordable Media', + '2GAN' => 'Products|Merchandise|Game, Computer Game|All Electronic Distribution Formats', + '2GAP' => 'Products|Merchandise|Game, All Types|Printed', + '2GAT' => 'Products|Merchandise|Game, All Types|Internet Downloadable File', + '2GAS' => 'Products|Merchandise|Game, All Types|Internet Email', + '2GAD' => 'Products|Merchandise|Game, All Types|All Internet Distribution Formats', + '2GAR' => 'Products|Merchandise|Game, All Types|Recordable Media', + '2GAM' => 'Products|Merchandise|Game, All Types|All Electronic Distribution Formats', + '2BOX' => 'Products|Merchandise|Gift Box|Printed', + '2GIF' => 'Products|Merchandise|Gift Certificate|Printed', + '2WRP' => 'Products|Merchandise|Gift Wrap|Printed', + '2JIG' => 'Products|Merchandise|Jigsaw Puzzle|Printed', + '2JIN' => 'Products|Merchandise|Jigsaw Puzzle|Internet Downloadable File', + '2JIL' => 'Products|Merchandise|Jigsaw Puzzle|Recordable Media', + '2JRN' => 'Products|Merchandise|Journal|Printed', + '2MAP' => 'Products|Merchandise|Map|Printed', + '2MAD' => 'Products|Merchandise|Map|Internet Downloadable File', + '2MET' => 'Products|Merchandise|Map|Internet Email', + '2MIM' => 'Products|Merchandise|Map|All Internet Distribution Formats', + '2MIR' => 'Products|Merchandise|Map|Recordable Media', + '2MAB' => 'Products|Merchandise|Map|All Electronic Distribution Formats', + '2MOU' => 'Products|Merchandise|Mouse Pad|Printed', + '2MUG' => 'Products|Merchandise|Mugs|Printed', + '2NOV' => 'Products|Merchandise|Novelty Products|Printed', + '2MCH' => 'Products|Merchandise|Other Merchandise|Printed', + '2ALB' => 'Products|Merchandise|Photo Album|Printed', + '2MAT' => 'Products|Merchandise|Placemat|Printed', + '2MRP' => 'Products|Merchandise|Plates|Printed', + '2TOP' => 'Products|Merchandise|Poster, Retail Poster|Printed', + '2FUN' => 'Products|Merchandise|Playing Cards|Printed', + '2CLO' => 'Products|Merchandise|Retail Calendar, One Page|Printed', + '2CAL' => 'Products|Merchandise|Retail Calendar, Multi-Page|Printed', + '2BCJ' => 'Products|Merchandise|Retail Calendar, Multi-Page|Internet Downloadable File', + '2BCI' => 'Products|Merchandise|Retail Calendar, Multi-Page|Internet Email', + '2BCH' => 'Products|Merchandise|Retail Calendar, Multi-Page|All Internet Distribution Formats', + '2BCF' => 'Products|Merchandise|Retail Calendar, Multi-Page|Recordable Media', + '2BCG' => 'Products|Merchandise|Retail Calendar, Multi-Page|All Electronic Distribution Formats', + '2FAR' => 'Products|Merchandise|Retail Postcard|Printed', + '2FIB' => 'Products|Merchandise|Screen Saver|Internet Downloadable File', + '2GEL' => 'Products|Merchandise|Screen Saver|Internet Email', + '2TOD' => 'Products|Merchandise|Screen Saver|All Internet Distribution Formats', + '2WRY' => 'Products|Merchandise|Screen Saver|Recordable Media', + '2HEX' => 'Products|Merchandise|Screen Saver|All Electronic Distribution Formats', + '2KEP' => 'Products|Merchandise|Souvenir|Printed', + '2WEE' => 'Products|Merchandise|Stamp|Printed', + '2WIT' => 'Products|Merchandise|Stationery|Printed', + '2TIC' => 'Products|Merchandise|Sticker|Printed', + '2FEM' => 'Products|Merchandise|Textiles|Printed or Woven', + '2TKT' => 'Products|Merchandise|Ticket|Printed', + '2TOY' => 'Products|Merchandise|Toy|Printed', + '2TRD' => 'Products|Merchandise|Trading Cards|Printed', + '2TUA' => 'Products|Merchandise|Virtual Reality|Recordable Media', + '2WAL' => 'Products|Merchandise|Wallpaper|Printed', + '2MER' => 'Products|Merchandise|All Merchandise Types|Printed', + '2BAB' => 'Products|Art|Artist\'s Reference, Tattoo|Printed', + '2DVL' => 'Products|Product Packaging|Packaging For Recordable Media, Liner Notes|Printed', + '2DVP' => 'Products|Product Packaging|Packaging For Recordable Media, All Packaging Types|Printed', + '2FRA' => 'Products|Product Packaging|Picture Frame Insert|Printed', + '2EVE' => 'Products|Product Packaging|Retail Packaging, All Packaging Types|Printed', + '2WHO' => 'Products|Product Packaging|Wholesale Packaging, All Packaging Types|Printed', + '2DAY' => 'Products|Product Packaging|All Product Packaging Types|Printed', + '2AAP' => 'Products|All Media Types|All Formats|All Distribution Formats', + '2TUX' => 'Internal Company Use|Periodicals|Magazine, Custom Published|Printed', + '2BIC' => 'Internal Company Use|Periodicals|Magazine, Custom Published|Intranet and Extranet Website', + '2BIF' => 'Internal Company Use|Periodicals|Magazine, Custom Published|Intranet and Extranet Downloadable File', + '2FOE' => 'Internal Company Use|Periodicals|Magazine, Custom Published|Internet Email', + '2BII' => 'Internal Company Use|Periodicals|Magazine, Custom Published|All Intranet and Extranet Distribution Formats', + '2BIA' => 'Internal Company Use|Periodicals|Magazine, Custom Published|Recordable Media', + '2BIH' => 'Internal Company Use|Periodicals|Magazine, Custom Published|All Electronic Distribution Formats', + '2FRO' => 'Internal Company Use|Comp Use|All Comp Types|Printed', + '2FPO' => 'Internal Company Use|Comp Use|All Comp Types|All Electronic Distribution Formats', + '2GED' => 'Internal Company Use|Internal Review|All Review Types|Printed', + '2GID' => 'Internal Company Use|Internal Review|All Review Types|All Electronic Distribution Formats', + '2GOA' => 'Internal Company Use|Promotional Materials|Corporate Brochure|Printed', + '2BHH' => 'Internal Company Use|Promotional Materials|Corporate Brochure|Intranet and Extranet Downloadable File', + '2BHI' => 'Internal Company Use|Promotional Materials|Corporate Brochure|Intranet and Extranet Email', + '2BHG' => 'Internal Company Use|Promotional Materials|Corporate Brochure|Recordable Media', + '2BHN' => 'Internal Company Use|Promotional Materials|Corporate Calendar|Printed', + '2BHL' => 'Internal Company Use|Promotional Materials|Corporate Calendar|Intranet and Extranet Downloadable File', + '2BHM' => 'Internal Company Use|Promotional Materials|Corporate Calendar|Intranet and Extranet Email', + '2BHK' => 'Internal Company Use|Promotional Materials|Corporate Calendar|Recordable Media', + '2BHY' => 'Internal Company Use|Promotional Materials|Corporate Folder|Printed', + '2BHQ' => 'Internal Company Use|Promotional Materials|Card, Corporate Card|Printed', + '2BHT' => 'Internal Company Use|Promotional Materials|Card, Corporate Card|Intranet and Extranet Downloadable File', + '2BHU' => 'Internal Company Use|Promotional Materials|Card, Corporate Card|Intranet and Extranet Email', + '2BHS' => 'Internal Company Use|Promotional Materials|Card, Corporate Card|Recordable Media', + '2BHZ' => 'Internal Company Use|Promotional Materials|CD ROM|Recordable Media', + '2DVI' => 'Internal Company Use|Promotional Materials|DVD|Recordable Media', + '2BHV' => 'Internal Company Use|Promotional Materials|Sales Kit|All Electronic Distribution Formats', + '2BHW' => 'Internal Company Use|Promotional Materials|Training Materials|Printed', + '2BJN' => 'Internal Company Use|Website|Web Page, Content Body|Intranet and Extranet Website', + '2FAB' => 'Internal Company Use|Website|Web Page, Content Body|Recordable Media', + '2FAC' => 'Internal Company Use|Website|Web Page, Content Body|All Electronic Distribution Formats', + '2FAH' => 'Internal Company Use|Website|Web Page, Design Element|Intranet and Extranet Website', + '2FAI' => 'Internal Company Use|Website|Web Page, Design Element|Recordable Media', + '2FAJ' => 'Internal Company Use|Website|Web Page, Design Element|All Electronic Distribution Formats', + '2NET' => 'Internal Company Use|Website|Web Page, All Types|Intranet and Extranet Website', + '2BJL' => 'Internal Company Use|Website|Web Page, All Types|Recordable Media', + '2BJK' => 'Internal Company Use|Website|Web Page, All Types|All Electronic Distribution Formats', + '2BJH' => 'Internal Company Use|Website|Webcast, All Types|Intranet and Extranet Website', + '2WAN' => 'Internal Company Use|Website|All Website Types|Intranet and Extranet Website', + '2BHD' => 'Internal Company Use|Email|All Email Types|Intranet and Extranet Email', + '2ZUM' => 'Internal Company Use|Mobile|All Mobile Types|Mobile', + '2BHF' => 'Internal Company Use|Live Presentation|Internal Presentation|Projected Display', + '2BHB' => 'Internal Company Use|Art|Art Display, Display Print|Printed', + '2GOY' => 'Internal Company Use|Art|Art Display, All Art Types|Printed', + '2HAO' => 'Internal Company Use|Art|Art Display, All Art Types|Electronic Display', + '2AAI' => 'Internal Company Use|All Media Types|All Formats|All Distribution Formats', + '2TVC' => 'Motion Picture & TV|Television Programming|Commercial|Television Broadcast', + '2TEB' => 'Motion Picture & TV|Television Programming|Commercial|Internet Downloadable File', + '2TEC' => 'Motion Picture & TV|Television Programming|Commercial|All Internet Distribution Formats', + '2TEG' => 'Motion Picture & TV|Television Programming|Commercial|Recordable Media', + '2TVD' => 'Motion Picture & TV|Television Programming|Commercial|All Electronic Distribution Formats', + '2TVE' => 'Motion Picture & TV|Television Programming|Infomercial|Television Broadcast', + '2TEH' => 'Motion Picture & TV|Television Programming|Infomercial|Internet Downloadable File', + '2TEJ' => 'Motion Picture & TV|Television Programming|Infomercial|All Internet Distribution Formats', + '2TEK' => 'Motion Picture & TV|Television Programming|Infomercial|Recordable Media', + '2TVF' => 'Motion Picture & TV|Television Programming|Infomercial|All Electronic Distribution Formats', + '2TVG' => 'Motion Picture & TV|Television Programming|On-Air Promotion|Television Broadcast', + '2TEL' => 'Motion Picture & TV|Television Programming|On-Air Promotion|Internet Downloadable File', + '2TEM' => 'Motion Picture & TV|Television Programming|On-Air Promotion|All Internet Distribution Formats', + '2TEP' => 'Motion Picture & TV|Television Programming|On-Air Promotion|Recordable Media', + '2TVH' => 'Motion Picture & TV|Television Programming|On-Air Promotion|All Electronic Distribution Formats', + '2TVI' => 'Motion Picture & TV|Television Programming|Documentary Program|Television Broadcast', + '2TER' => 'Motion Picture & TV|Television Programming|Documentary Program|Internet Downloadable File', + '2TES' => 'Motion Picture & TV|Television Programming|Documentary Program|All Internet Distribution Formats', + '2TET' => 'Motion Picture & TV|Television Programming|Documentary Program|Recordable Media', + '2TVJ' => 'Motion Picture & TV|Television Programming|Documentary Program|All Electronic Distribution Formats', + '2TVA' => 'Motion Picture & TV|Television Programming|All Television Advertising Types|Television Broadcast', + '2TEA' => 'Motion Picture & TV|Television Programming|All Television Advertising Types|Internet Downloadable File', + '2TEQ' => 'Motion Picture & TV|Television Programming|All Television Advertising Types|All Internet Distribution Formats', + '2TED' => 'Motion Picture & TV|Television Programming|All Television Advertising Types|Recordable Media', + '2TVB' => 'Motion Picture & TV|Television Programming|All Television Advertising Types|All Electronic Distribution Formats', + '2TVK' => 'Motion Picture & TV|Television Programming|Educational Program|Television Broadcast', + '2TEU' => 'Motion Picture & TV|Television Programming|Educational Program|Internet Downloadable File', + '2TEV' => 'Motion Picture & TV|Television Programming|Educational Program|All Internet Distribution Formats', + '2TEW' => 'Motion Picture & TV|Television Programming|Educational Program|Recordable Media', + '2TVL' => 'Motion Picture & TV|Television Programming|Educational Program|All Electronic Distribution Formats', + '2TVM' => 'Motion Picture & TV|Television Programming|Entertainment Program|Television Broadcast', + '2TEY' => 'Motion Picture & TV|Television Programming|Entertainment Program|Internet Downloadable File', + '2TEZ' => 'Motion Picture & TV|Television Programming|Entertainment Program|All Internet Distribution Formats', + '2TLA' => 'Motion Picture & TV|Television Programming|Entertainment Program|Recordable Media', + '2TVN' => 'Motion Picture & TV|Television Programming|Entertainment Program|All Electronic Distribution Formats', + '2TVY' => 'Motion Picture & TV|Television Programming|Made For TV Movie|Television Broadcast', + '2TLC' => 'Motion Picture & TV|Television Programming|Made For TV Movie|Internet Downloadable File', + '2TLB' => 'Motion Picture & TV|Television Programming|Made For TV Movie|All Internet Distribution Formats', + '2TLD' => 'Motion Picture & TV|Television Programming|Made For TV Movie|Recordable Media', + '2TVP' => 'Motion Picture & TV|Television Programming|Made For TV Movie|All Electronic Distribution Formats', + '2TEF' => 'Motion Picture & TV|Television Programming|News Program, Flash|Television Broadcast', + '2TVS' => 'Motion Picture & TV|Television Programming|News Program|Television Broadcast', + '2TLE' => 'Motion Picture & TV|Television Programming|News Program|Internet Downloadable File', + '2TLF' => 'Motion Picture & TV|Television Programming|News Program|All Internet Distribution Formats', + '2TLG' => 'Motion Picture & TV|Television Programming|News Program|Recordable Media', + '2TVT' => 'Motion Picture & TV|Television Programming|News Program|All Electronic Distribution Formats', + '2TLH' => 'Motion Picture & TV|Television Programming|Non Broadcast Pilot|Recordable Media', + '2TLJ' => 'Motion Picture & TV|Television Programming|Non Broadcast Pilot|Projected Display', + '2TVU' => 'Motion Picture & TV|Television Programming|Non-Profit Program|Television Broadcast', + '2TLK' => 'Motion Picture & TV|Television Programming|Non-Profit Program|Internet Downloadable File', + '2TLL' => 'Motion Picture & TV|Television Programming|Non-Profit Program|All Internet Distribution Formats', + '2TLM' => 'Motion Picture & TV|Television Programming|Non-Profit Program|Recordable Media', + '2TVV' => 'Motion Picture & TV|Television Programming|Non-Profit Program|All Electronic Distribution Formats', + '2TLR' => 'Motion Picture & TV|Television Programming|Prop|Television Broadcast', + '2TLN' => 'Motion Picture & TV|Television Programming|Prop|Internet Downloadable File', + '2TLP' => 'Motion Picture & TV|Television Programming|Prop|All Internet Distribution Formats', + '2TLQ' => 'Motion Picture & TV|Television Programming|Prop|Recordable Media', + '2TVW' => 'Motion Picture & TV|Television Programming|Prop|All Electronic Distribution Formats', + '2TLV' => 'Motion Picture & TV|Television Programming|Set Decor|Television Broadcast', + '2TLS' => 'Motion Picture & TV|Television Programming|Set Decor|Internet Downloadable File', + '2TLT' => 'Motion Picture & TV|Television Programming|Set Decor|All Internet Distribution Formats', + '2TLU' => 'Motion Picture & TV|Television Programming|Set Decor|Recordable Media', + '2TVQ' => 'Motion Picture & TV|Television Programming|Set Decor|All Electronic Distribution Formats', + '2KOA' => 'Motion Picture & TV|Television Programming|Artist\'s Reference, All Types|Projected Display', + '2KOB' => 'Motion Picture & TV|Television Programming|Artist\'s Reference, All Types|Internet Downloadable File', + '2KOI' => 'Motion Picture & TV|Television Programming|Artist\'s Reference, All Types|All Internet Distribution Formats', + '2KOP' => 'Motion Picture & TV|Television Programming|Artist\'s Reference, All Types|Recordable Media', + '2KOR' => 'Motion Picture & TV|Television Programming|Artist\'s Reference, All Types|All Electronic Distribution Formats', + '2KOS' => 'Motion Picture & TV|Television Programming|Artist\'s Reference, All Types|Television Broadcast', + '2TEE' => 'Motion Picture & TV|Television Programming|All Editorial Television Types|Television Broadcast', + '2TLW' => 'Motion Picture & TV|Television Programming|All Editorial Television Types|Internet Downloadable File', + '2TLY' => 'Motion Picture & TV|Television Programming|All Editorial Television Types|All Internet Distribution Formats', + '2TLZ' => 'Motion Picture & TV|Television Programming|All Editorial Television Types|Recordable Media', + '2TVZ' => 'Motion Picture & TV|Television Programming|All Editorial Television Types|All Electronic Distribution Formats', + '2JOT' => 'Motion Picture & TV|Motion Picture|In Theater Commercial|Projected Display', + '2ATE' => 'Motion Picture & TV|Motion Picture|Movie Trailer|Projected Display', + '2MPP' => 'Motion Picture & TV|Motion Picture|Movie Trailer|Internet Downloadable File', + '2BET' => 'Motion Picture & TV|Motion Picture|Movie Trailer|All Internet Distribution Formats', + '2DIG' => 'Motion Picture & TV|Motion Picture|Movie Trailer|Recordable Media', + '2AID' => 'Motion Picture & TV|Motion Picture|Movie Trailer|All Electronic Distribution Formats', + '2MPF' => 'Motion Picture & TV|Motion Picture|Movie Trailer|Television Broadcast', + '2JOG' => 'Motion Picture & TV|Motion Picture|Documentary Film|Projected Display', + '2MPM' => 'Motion Picture & TV|Motion Picture|Documentary Film|Internet Downloadable File', + '2TUG' => 'Motion Picture & TV|Motion Picture|Documentary Film|All Internet Distribution Formats', + '2TRY' => 'Motion Picture & TV|Motion Picture|Documentary Film|Recordable Media', + '2DOC' => 'Motion Picture & TV|Motion Picture|Documentary Film|All Electronic Distribution Formats', + '2MPD' => 'Motion Picture & TV|Motion Picture|Documentary Film|Television Broadcast', + '2FEA' => 'Motion Picture & TV|Motion Picture|Feature Film|Projected Display', + '2MPN' => 'Motion Picture & TV|Motion Picture|Feature Film|Internet Downloadable File', + '2WAG' => 'Motion Picture & TV|Motion Picture|Feature Film|All Internet Distribution Formats', + '2WIN' => 'Motion Picture & TV|Motion Picture|Feature Film|Recordable Media', + '2FIL' => 'Motion Picture & TV|Motion Picture|Feature Film|All Electronic Distribution Formats', + '2MPE' => 'Motion Picture & TV|Motion Picture|Feature Film|Television Broadcast', + '2WIZ' => 'Motion Picture & TV|Motion Picture|Short Film|Projected Display', + '2MPS' => 'Motion Picture & TV|Motion Picture|Short Film|Internet Downloadable File', + '2ASK' => 'Motion Picture & TV|Motion Picture|Short Film|All Internet Distribution Formats', + '2AIM' => 'Motion Picture & TV|Motion Picture|Short Film|Recordable Media', + '2FIT' => 'Motion Picture & TV|Motion Picture|Short Film|All Electronic Distribution Formats', + '2MPI' => 'Motion Picture & TV|Motion Picture|Short Film|Television Broadcast', + '2MPG' => 'Motion Picture & TV|Motion Picture|Prop|Television Broadcast', + '2HOP' => 'Motion Picture & TV|Motion Picture|Prop|Projected Display', + '2MPQ' => 'Motion Picture & TV|Motion Picture|Prop|Internet Downloadable File', + '2HIT' => 'Motion Picture & TV|Motion Picture|Prop|All Internet Distribution Formats', + '2FRY' => 'Motion Picture & TV|Motion Picture|Prop|Recordable Media', + '2EFX' => 'Motion Picture & TV|Motion Picture|Prop|All Electronic Distribution Formats', + '2MPH' => 'Motion Picture & TV|Motion Picture|Set Decor|Television Broadcast', + '2MPR' => 'Motion Picture & TV|Motion Picture|Set Decor|Internet Downloadable File', + '2JAB' => 'Motion Picture & TV|Motion Picture|Set Decor|All Internet Distribution Formats', + '2HUG' => 'Motion Picture & TV|Motion Picture|Set Decor|Recordable Media', + '2HUM' => 'Motion Picture & TV|Motion Picture|Set Decor|All Electronic Distribution Formats', + '2ARC' => 'Motion Picture & TV|Motion Picture|Set Decor|Projected Display', + '2TAP' => 'Motion Picture & TV|Motion Picture|Artist\'s Reference, All Types|Projected Display', + '2MPL' => 'Motion Picture & TV|Motion Picture|Artist\'s Reference, All Types|Internet Downloadable File', + '2NOD' => 'Motion Picture & TV|Motion Picture|Artist\'s Reference, All Types|All Internet Distribution Formats', + '2MIX' => 'Motion Picture & TV|Motion Picture|Artist\'s Reference, All Types|Recordable Media', + '2NAP' => 'Motion Picture & TV|Motion Picture|Artist\'s Reference, All Types|All Electronic Distribution Formats', + '2MPC' => 'Motion Picture & TV|Motion Picture|Artist\'s Reference, All Types|Television Broadcast', + '2FIX' => 'Motion Picture & TV|Motion Picture|All Motion Picture Types|Projected Display', + '2MPJ' => 'Motion Picture & TV|Motion Picture|All Motion Picture Types|Internet Downloadable File', + '2DIP' => 'Motion Picture & TV|Motion Picture|All Motion Picture Types|All Internet Distribution Formats', + '2MOV' => 'Motion Picture & TV|Motion Picture|All Motion Picture Types|Recordable Media', + '2MPA' => 'Motion Picture & TV|Motion Picture|All Motion Picture Types|Television Broadcast', + '2ACT' => 'Motion Picture & TV|Motion Picture|All Motion Picture Types|All Electronic Distribution Formats', + '2MPB' => 'Motion Picture & TV|Music Video|All Music Video Types|Television Broadcast', + '2MPK' => 'Motion Picture & TV|Music Video|All Music Video Types|Internet Downloadable File', + '2BER' => 'Motion Picture & TV|Music Video|All Music Video Types|Recordable Media', + '2BES' => 'Motion Picture & TV|Music Video|All Music Video Types|All Internet Distribution Formats', + '2TVR' => 'Motion Picture & TV|Music Video|All Music Video Types|All Electronic Distribution Formats', + '2AAM' => 'Motion Picture & TV|All Media Types|All Formats|All Distribution Formats', + '2WED' => 'Personal Use|Personal Review|All Review Types|Printed', + '2DIM' => 'Personal Use|Personal Review|All Review Types|All Electronic Distribution Formats', + '2BFR' => 'Personal Use|Website|Web Page, All Types|Internet Website', + '2BFU' => 'Personal Use|Website|Web Page, All Types|All Internet Distribution Formats', + '2BFS' => 'Personal Use|Website|Web Page, All Types|Recordable Media', + '2BFT' => 'Personal Use|Website|Web Page, All Types|All Electronic Distribution Formats', + '2ZIT' => 'Personal Use|Mobile|Wallpaper|Mobile', + '2ZOB' => 'Personal Use|Mobile|All Mobile Types|Mobile', + '2BFN' => 'Personal Use|Art|Art Display, Display Print|Printed', + '2KIT' => 'Personal Use|Art|Art Display, All Art Types|Printed', + '2BFJ' => 'Personal Use|Art|Art Display, All Art Types|Internet Website', + '2BFI' => 'Personal Use|Art|Art Display, All Art Types|All Internet Distribution Formats', + '2BFK' => 'Personal Use|Art|Art Display, All Art Types|Electronic Display', + '2BFH' => 'Personal Use|Art|Art Display, All Art Types|All Electronic Distribution Formats', + '2TAT' => 'Personal Use|Art|Artist\'s Reference, Tattoo|Printed', + '2BFP' => 'Personal Use|Art|Study Print, Educational|Printed', + '2AAU' => 'Personal Use|All Media Types|All Formats|All Distribution Formats', + '2AAB' => 'All Categories|Book|All Book Types|All Distribution Formats', + '2AAD' => 'All Categories|Display|All Display Types|All Distribution Formats', + '2AAT' => 'All Categories|Marketing Materials|All Marketing Material Types|All Distribution Formats', + '2AAH' => 'All Categories|Merchandise|All Merchandise Types|All Distribution Formats', + '2AAL' => 'All Categories|Mobile|All Mobile Types|All Distribution Formats', + '2AAX' => 'All Categories|Motion Picture|All Motion Picture Types|All Distribution Formats', + '2AAV' => 'All Categories|Music Video|All Music Video Types|All Distribution Formats', + '2AAC' => 'All Categories|Periodicals|All Periodical Types|All Distribution Formats', + '2AAR' => 'All Categories|Point of Purchase|All Point Of Purchase Types|All Distribution Formats', + '2AAG' => 'All Categories|Product Packaging|All Product Packaging Types|All Distribution Formats', + '2AAN' => 'All Categories|Television Programming|All Television Programming Types|All Distribution Formats', + '2BAA' => 'All Categories|Website|All Web Page Types|All Distribution Formats', + '2ALL' => 'All Categories|All Media Types|All Formats|All Distribution Formats', + '2UNL' => 'Unlicensed|Not Applicable|Not Applicable|Not Applicable', + # 3P - Placement + '3PAA' => 'Any Placements on All Pages', + '3PXX' => 'Not Applicable or None', + '3PUL' => 'Any Placements', + '3PNQ' => 'Single Placement in Content Body', + '3PPU' => 'Single Placement on Title Page', + '3PQT' => 'Single Placement on Table Of Contents', + '3PQA' => 'Single Placement as Frontispiece', + '3PQI' => 'Single Placement on Preface', + '3PPW' => 'Single Placement as Forward', + '3PSA' => 'Single Placement as Front Matter', + '3PNI' => 'Single Placement as Chapter Opener', + '3PQN' => 'Single Placement as Vignette', + '3PRT' => 'Single Placement on Pop Up', + '3PNZ' => 'Single Placement in Bibliography', + '3PQZ' => 'Single Placement on Index', + '3PQG' => 'Single Placement on Any Interior Page', + '3PSR' => 'Single Placement on Inside Cover', + '3PQE' => 'Single Placement on Spine', + '3PSL' => 'Single Placement on Flap', + '3PSP' => 'Single Placement on Back Cover', + '3PNN' => 'Single Placement on Front Cover', + '3PTL' => 'Single Placement on Front Cover And Back Cover', + '3PPA' => 'Single Placement on Dust Jacket', + '3PTD' => 'Single Placements on Interior, Covers and Jacket', + '3PRY' => 'Multiple Placements in Content Body', + '3PRL' => 'Multiple Placements on Any Interior Pages', + '3PSU' => 'Multiple Placements on Inside Cover', + '3PQS' => 'Multiple Placements on Back Cover', + '3PRZ' => 'Multiple Placements on Front Cover', + '3PTM' => 'Multiple Placements on Front Cover And Back Cover', + '3PTC' => 'Multiple Placements on Dust Jacket', + '3PTE' => 'Multiple Placements on Interior, Covers and Jacket', + '3PST' => 'Single Placement on Any Interior Page', + '3PPK' => 'Single Placement on Inside Cover', + '3PNR' => 'Single Placement on Back Cover', + '3PRB' => 'Single Placement on Front Cover', + '3PUD' => 'Single Placement on Back Cover Or Interior Page', + '3PTB' => 'Single Placement on Front Cover And Interior Page', + '3PUF' => 'Single Placement on Front Cover Or Back Cover', + '3PNF' => 'Single Placement on Front Cover And Back Cover', + '3PTP' => 'Single Placement on Any Cover And Interior Page', + '3PQW' => 'Multiple Placements on Any Interior Pages', + '3PNY' => 'Multiple Placements on Inside Cover', + '3PNC' => 'Multiple Placements on Back Cover', + '3PPV' => 'Multiple Placements on Front Cover', + '3PRG' => 'Multiple Placements on Front Cover And Back Cover', + '3PTN' => 'Multiple Placements on Any Covers And Interior Pages', + '3PQX' => 'Single Placement on Any Interior Page', + '3PTF' => 'Single Placement on Section Opener Page', + '3PNT' => 'Single Placement on Front Page', + '3PTH' => 'Single Placement on Section Opener and Front Page', + '3PSY' => 'Multiple Placements on Any Interior Pages', + '3PTG' => 'Multiple Placements on Section Opener Page', + '3PTI' => 'Multiple Placements on Section Opener and Front Page', + '3PPM' => 'Multiple Placements on Any Pages', + '3PQJ' => 'Single Placement on Wrap Around Cover', + '3PQB' => 'Multiple Placements on Wrap Around Cover', + '3PRS' => 'Single Placement in Content Body', + '3PRI' => 'Single Placement as Colophon', + '3PRC' => 'Single Placement on Table Of Contents', + '3PQQ' => 'Single Placement as Unit Opener', + '3PND' => 'Single Placement as Chapter Opener', + '3PQF' => 'Single Placements in Bibliography', + '3PRN' => 'Single Placement on Any Interior Page', + '3PQH' => 'Single Placement on Back Cover', + '3PSJ' => 'Single Placement on Front Cover', + '3PTJ' => 'Single Placement on Any Covers And Interior Pages', + '3PRD' => 'Multiple Placements in Content Body', + '3PSM' => 'Multiple Placements on Any Interior Pages', + '3PSN' => 'Multiple Placements on Back Cover', + '3PPF' => 'Multiple Placements on Front Cover', + '3PTK' => 'Multiple Placements on Any Covers And Interior Pages', + '3PNE' => 'Single Placement on Front Side', + '3PQC' => 'Single Placement on Back Side', + '3PPL' => 'Single Placement on Both Sides', + '3PNV' => 'Multiple Placements on Front Side', + '3PSB' => 'Multiple Placements on Back Side', + '3PQK' => 'Multiple Placements on Both Sides', + '3PTA' => 'Single Placement on One Side', + '3PNB' => 'Multiple Placements on One Side', + '3PRQ' => 'Single Placement on Screen', + '3PSD' => 'Multiple Placements on Screen', + '3PPH' => 'Single Placement on Inside', + '3PSQ' => 'Single Placement on Back Side', + '3PRU' => 'Single Placement on Front Side', + '3PNP' => 'Single Placement on Both Sides', + '3PRK' => 'Multiple Placements on Inside', + '3PQM' => 'Multiple Placements on Back Side', + '3PNK' => 'Multiple Placements on Front Side', + '3PRV' => 'Multiple Placements on Both Sides', + '3PRH' => 'Single Placement on Any Interior Page', + '3PSH' => 'Single Placement on Back Cover', + '3PQY' => 'Single Placement on Front Cover', + '3PRM' => 'Single Placement on Front Cover And Back Cover', + '3PTQ' => 'Single Placement on Any Covers And Interior Pages', + '3PRF' => 'Multiple Placements on Any Interior Pages', + '3PSF' => 'Multiple Placements on Back Cover', + '3PRJ' => 'Multiple Placements on Front Cover', + '3PPP' => 'Multiple Placements on Front Cover And Interior Pages', + '3PSS' => 'Multiple Placements on Front Cover And Back Cover', + '3PTR' => 'Multiple Placements on Any Covers And Interior Pages', + '3PSW' => 'Single Placement on Item', + '3PNL' => 'Multiple Placements on Item', + '3PPX' => 'Single Placement on Packaging Exterior|Front', + '3PUJ' => 'Single Placement on Packaging Exterior|Back or Side', + '3PPD' => 'Single Placement in Packaging Interior', + '3PSI' => 'Multiple Placements on Packaging Exterior|Front', + '3PUH' => 'Multiple Placements on Packaging Exterior|Back or Side', + '3PPC' => 'Multiple Placements in Packaging Interior', + '3PTS' => 'Single Placement Anywhere On Packaging', + '3PTT' => 'Multiple Placements Anywhere On Packaging', + '3PNW' => 'Single Placement in Body Of Program', + '3PQU' => 'Single Placement in Closing Sequence', + '3PRR' => 'Single Placement in Title Sequence', + '3PTV' => 'Single Placement in Any Part', + '3PPZ' => 'Multiple Placements in Body Of Program', + '3PPN' => 'Multiple Placements in Closing Sequence', + '3PSV' => 'Multiple Placements in Title Sequence', + '3PTU' => 'Multiple Placements in Any Part', + '3PRP' => 'Single Placement in Body Of Advertisement', + '3PPJ' => 'Multiple Placements in Body Of Advertisement', + '3PPR' => 'Single Placement in Any Part', + '3PRW' => 'Multiple Placements in Any Part', + '3PQD' => 'Single Placement on Secondary Page', + '3PQP' => 'Single Placement on Pop Up', + '3PPS' => 'Single Placement on Landing Page', + '3PPG' => 'Single Placement on Splash Page', + '3PPY' => 'Single Placement on Home Page', + '3PTY' => 'Single Placement on Home Page And Secondary Pages', + '3PTW' => 'Single Placement on Any Pages', + '3PSZ' => 'Multiple Placements on Secondary Pages', + '3PNJ' => 'Multiple Placements on Pop Ups', + '3PPI' => 'Multiple Placements on Landing Pages', + '3PNS' => 'Multiple Placements on Splash Pages', + '3PNU' => 'Multiple Placements on Home Page', + '3PPQ' => 'Multiple Placements on Home Page And Secondary Pages', + '3PTZ' => 'Multiple Placements on Any Pages', + '3PPE' => 'Single Placement as Flash', + '3PNM' => 'Single Placement in Body Of Program', + '3PPB' => 'Single Placement in Closing Sequence', + '3PSC' => 'Single Placement in Title Sequence', + '3PUC' => 'Single Placement in Any Part', + '3PNX' => 'Multiple Placements as Flash', + '3PNH' => 'Multiple Placements in Body Of Program', + '3PQL' => 'Multiple Placements in Closing Sequence', + '3PSK' => 'Multiple Placements in Title Sequence', + '3PUB' => 'Multiple Placements in Any Part', + # 4S - Size + '4SAA' => 'Any Size Image|Any Size Media', + '4SXX' => 'Not Applicable or None', + '4SUL' => 'Any Sizes', + '4SJA' => 'Up To 1/16 Page|Any Size Page', + '4SBN' => 'Up To 1/8 Page Image|Any Size Page', + '4SJB' => 'Up To 1/4 Page Image|Any Size Page', + '4SEU' => 'Up To 1/3 Page Image|Any Size Page', + '4SEJ' => 'Up To 1/2 Page Image|Any Size Page', + '4SMG' => 'Up To 3/4 Page Image|Any Size Page', + '4SAG' => 'Up To Full Page Image|Any Size Page', + '4SFI' => 'Up To 2 Page Image|Any Size Pages', + '4SJZ' => 'Up To 3 Page Image|Any Size Pages', + '4SFG' => 'Up To 4 Page Image|Any Size Pages', + '4SBP' => 'Any Size Image|Any Size Page', + '4SGF' => 'Up To 1/4 Page Image|Up To 1/4 Page Ad', + '4SCH' => 'Up To 1/4 Page Image|Up To 1/2 Page Ad', + '4SIY' => 'Up To 1/4 Page Image|Up To Full Page Ad', + '4SCV' => 'Up To 1/2 Page Image|Up To 1/2 Page Ad', + '4SLY' => 'Up To 1/2 Page Image|Up To Full Page Ad', + '4SBU' => 'Up To 1/2 Page Image|Up To 2 Page Ad', + '4SCP' => 'Up To Full Page Image|Up To Full Page Ad', + '4SGL' => 'Up To Full Page Image|Up To 2 Page Ad', + '4SGM' => 'Up To Full Page Image|Any Size Ad', + '4SMB' => 'Up To 2 Page Image|Up To 2 Page Ad', + '4SFR' => 'Up To 2 Page Image|Any Size Ad', + '4SKP' => 'Any Size Image|Any Size Ad', + '4SBK' => 'Up To 1/16 Page Image|Any Size Page', + '4SJS' => 'Up To 1/8 Page Image|Any Size Page', + '4SLV' => 'Up To 1/4 Page Image|Any Size Page', + '4SGW' => 'Up To 1/2 Page Image|Any Size Page', + '4SKD' => 'Up To Full Page Image|Any Size Page', + '4SFJ' => 'Up To 2 Page Image|Any Size Pages', + '4SLA' => 'Any Size Image|Any Size Pages', + '4SKE' => 'Up To 1/8 Page Image|Any Size Page', + '4SAK' => 'Up To 1/4 Page Image|Any Size Page', + '4SLD' => 'Up To 1/2 Page Image|Any Size Page', + '4SJV' => 'Up To Full Page Image|Any Size Page', + '4SJU' => 'Up To 2 Page Image|Any Size Pages', + '4SIW' => 'Any Size Image|Any Size Pages', + '4SAL' => 'Up To 1/4 Area Image|Up To Full Area Media', + '4SJM' => 'Up To 1/2 Area Image|Up To Full Area Media', + '4SKZ' => 'Up To Full Area Image|Up To Full Area Media', + '4SCN' => 'Up To 1/8 Page Image|Up To Full Page Media', + '4SLW' => 'Up To 1/4 Page Image|Up To Full Page Media', + '4SIZ' => 'Up To 1/2 Page Image|Up To Full Page Media', + '4SAC' => 'Up To Full Page Image|Up To Full Page Media', + '4SFX' => 'Up To 8 x 10 Inch Image|Any Size Media', + '4SFP' => 'Up To 11 x 14 Inch Image|Any Size Media', + '4SMV' => 'Any Size Image|Any Size Media', + '4SJD' => 'Up To 21 x 30 cm Image|Any Size Media', + '4SFQ' => 'Up To 30 x 42 cm Image|Any Size Media', + '4SJK' => 'Any Size Image|Up To Full Card', + '4SEQ' => 'Up To 5 x 5 Inch Image|Up To 40 x 40 Inch Media', + '4SIV' => 'Up To 10 x 10 Inch Image|Up To 40 x 40 Inch Media', + '4SCE' => 'Up To 20 x 20 Inch Image|Up To 40 x 40 Inch Media', + '4SDP' => 'Up To 30x 30 Inch Image|Up To 40 x 40 Inch Media', + '4SCT' => 'Up To 40 x 40 Inch Image|Up To 40 x 40 Inch Media', + '4SBJ' => 'Up To 20 x 20 cm Image|Up To 100 x 100 cm Media', + '4SKI' => 'Up To 30 x 30 cm Image|Up To 100 x 100 cm Media', + '4SJW' => 'Up To 40 x 40 cm Image|Up To 100 x 100 cm Media', + '4SCB' => 'Up To 50 x 50 cm Image|Up To 100 x 100 cm Media', + '4SAT' => 'Up To 75 x 75 cm Image|Up To 100 x 100 cm Media', + '4SCI' => 'Up To 100 x 100 cm Image|Up To 100 x 100 cm Media', + '4SGP' => 'Any Size Image|Any Size Media', + '4SIX' => 'Up To 1/4 Area Image|Up To 11 x 36 Foot Display', + '4SHA' => 'Up To 1/4 Area Image|Up To 10 x 40 Foot Display', + '4SGU' => 'Up To 1/4 Area Image|Up To 14 x 48 Foot Display', + '4SAJ' => 'Up To 1/2 Area Image|Up To 11 x 36 Foot Display', + '4SDX' => 'Up To 1/2 Area Image|Up To 10 x 40 Foot Display', + '4SCR' => 'Up To 1/2 Area Image|Up To 14 x 48 Foot Display', + '4SFM' => 'Up To Full Area Image|Up To 11 x 36 Foot Display', + '4SKV' => 'Up To Full Area Image|Up To 10 x 40 Foot Display', + '4SGE' => 'Up To Full Area Image|Up To 14 x 48 Foot Display', + '4SMW' => 'Up To Full Area Image|Any Size Display', + '4SJI' => 'Up To 1/4 Area Image|Up To 4 x 8 Foot Media', + '4SBI' => 'Up To 1/4 Area Image|Up To 10 x 8 Foot Media', + '4SIM' => 'Up To 1/4 Area Image|Up To 12 x 24 Foot Media', + '4SFF' => 'Up To 1/4 Area Image|Any Size Media', + '4SAX' => 'Up To 1/2 Area Image|Up To 4 x 8 Foot Media', + '4SLI' => 'Up To 1/2 Area Image|Up To 10 x 8 Foot Media', + '4SLS' => 'Up To 1/2 Area Image|Up To 12 x 24 Foot Media', + '4SMK' => 'Up To 1/2 Area Image|Any Size Media', + '4SLG' => 'Up To Full Area Image|Up To 4 x 8 Foot Media', + '4SAN' => 'Up To Full Area Image|Up To 10 x 8 Foot Media', + '4SDI' => 'Up To Full Area Image|Up To 12 x 24 Foot Media', + '4SML' => 'Up To Full Area Image|Any Size Media', + '4SKF' => 'Up To 1/4 Area Image|Up To 672 Square Foot Display', + '4SKR' => 'Up To 1/4 Area Image|Up To 1,200 Square Foot Display', + '4SLK' => 'Up To 1/4 Area Image|Up To 2,400 Square Foot Display', + '4SJQ' => 'Up To 1/4 Area Image|Up To 4,800 Square Foot Display', + '4SEY' => 'Up To 1/4 Area Image|Up To 10,000 Square Foot Display', + '4SFE' => 'Up To 1/4 Area Image|Any Size Display', + '4SKS' => 'Up To 1/2 Area Image|Up To 672 Square Foot Display', + '4SGS' => 'Up To 1/2 Area Image|Up To 1,200 Square Foot Display', + '4SMA' => 'Up To 1/2 Area Image|Up To 2,400 Square Foot Display', + '4SAF' => 'Up To 1/2 Area Image|Up To 4,800 Square Foot Display', + '4SAW' => 'Up To 1/2 Area Image|Up To 10,000 Square Foot Display', + '4SAQ' => 'Up To 1/2 Area Image|Any Size Display', + '4SLN' => 'Up To Full Area Image|Up To 672 Square Foot Display', + '4SDS' => 'Up To Full Area Image|Up To 1,200 Square Foot Display', + '4SIT' => 'Up To Full Area Image|Up To 2,400 Square Foot Display', + '4SGX' => 'Up To Full Area Image|Up To 4,800 Square Foot Display', + '4SBD' => 'Up To Full Area Image|Up To 10,000 Square Foot Display', + '4SBF' => 'Up To Full Area Image|Any Size Display', + '4SDD' => 'Up To 1/4 Area Image|Up To 4 Sheet Display', + '4SBC' => 'Up To 1/4 Area Image|Up To 8 Sheet Display', + '4SLJ' => 'Up To 1/4 Area Image|Up To 12 Sheet Display', + '4SAD' => 'Up To 1/4 Area Image|Up To 16 Sheet Display', + '4SEA' => 'Up To 1/4 Area Image|Up To 30 Sheet Display', + '4SCD' => 'Up To 1/4 Area Image|Up To 48 Sheet Display', + '4SKX' => 'Up To 1/4 Area Image|Up To 96 Sheet Display', + '4SMN' => 'Up To 1/4 Area Image|Any Size Display', + '4SDU' => 'Up To 1/2 Area Image|Up To 4 Sheet Display', + '4SBL' => 'Up To 1/2 Area Image|Up To 8 Sheet Display', + '4SER' => 'Up To 1/2 Area Image|Up To 12 Sheet Display', + '4SEN' => 'Up To 1/2 Area Image|Up To 16 Sheet Display', + '4SLP' => 'Up To 1/2 Area Image|Up To 30 Sheet Display', + '4SGQ' => 'Up To 1/2 Area Image|Up To 48 Sheet Display', + '4SDF' => 'Up To 1/2 Area Image|Up To 96 Sheet Display', + '4SMP' => 'Up To 1/2 Area Image|Any Size Display', + '4SFL' => 'Up To Full Area Image|Up To 4 Sheet Display', + '4SFS' => 'Up To Full Area Image|Up To 8 Sheet Display', + '4SIF' => 'Up To Full Area Image|Up To 12 Sheet Display', + '4SIS' => 'Up To Full Area Image|Up To 16 Sheet Display', + '4SFD' => 'Up To Full Area Image|Up To 30 Sheet Display', + '4SFU' => 'Up To Full Area Image|Up To 48 Sheet Display', + '4SDK' => 'Up To Full Area Image|Up To 96 Sheet Display', + '4SMQ' => 'Up To Full Area Image|Any Size Display', + '4SKA' => 'Up To 1/4 Area Image|Up To 20 x 30 Inch Media', + '4SIK' => 'Up To 1/4 Area Image|Up To 24 x 36 Inch Media', + '4SFK' => 'Up To 1/4 Area Image|Up To 30 x 40 Inch Media', + '4SDV' => 'Up To 1/4 Area Image|Up To 40 x 60 Inch Media', + '4SMX' => 'Up To 1/4 Area Image|Any Size Media', + '4SEF' => 'Up To 1/4 Area Image|Up To A1 Media', + '4SCJ' => 'Up To 1/4 Area Image|Up To B1 Media', + '4SJG' => 'Up To 1/4 Area Image|Up To A0 Media', + '4SIP' => 'Up To 1/4 Area Image|Up To B0 Media', + '4SKU' => 'Up To 1/2 Area Image|Up To 20 x 30 Inch Media', + '4SAS' => 'Up To 1/2 Area Image|Up To 24 x 36 Inch Media', + '4SGB' => 'Up To 1/2 Area Image|Up To 30 x 40 Inch Media', + '4SBQ' => 'Up To 1/2 Area Image|Up To 40 x 60 Inch Media', + '4SMY' => 'Up To 1/2 Area Image|Any Size Media', + '4SKJ' => 'Up To 1/2 Area Image|Up To A1 Media', + '4SAM' => 'Up To 1/2 Area Image|Up To B1 Media', + '4SDZ' => 'Up To 1/2 Area Image|Up To A0 Media', + '4SGT' => 'Up To 1/2 Area Image|Up To B0 Media', + '4SKN' => 'Up To Full Area Image|Up To 20 x 30 Inch Media', + '4SIQ' => 'Up To Full Area Image|Up To 24 x 36 Inch Media', + '4SLT' => 'Up To Full Area Image|Up To 30 x 40 Inch Media', + '4SDN' => 'Up To Full Area Image|Up To 40 x 60 Inch Media', + '4SMZ' => 'Up To Full Area Image|Any Size Media', + '4SBH' => 'Up To Full Area Image|Up To A1 Media', + '4SLU' => 'Up To Full Area Image|Up To B1 Media', + '4SEL' => 'Up To Full Area Image|Up To A0 Media', + '4SBM' => 'Up To Full Area Image|Up To B0 Media', + '4SIH' => 'Up To 1/4 Area Image|Up To 24 x 30 Inch Display', + '4SKW' => 'Up To 1/4 Area Image|Up To 30 x 40 Inch Display', + '4SDM' => 'Up To 1/4 Area Image|Up To 27 x 85 Inch Display', + '4SJP' => 'Up To 1/4 Area Image|Up To 60 x 40 Inch Display', + '4SIB' => 'Up To 1/4 Area Image|Up To 69 x 48 Inch Display', + '4SDH' => 'Up To 1/4 Area Image|Up To 27 x 141 Inch Display', + '4SJL' => 'Up To 1/4 Area Image|Up To 30 x 240 Inch Display', + '4SLQ' => 'Up To 1/4 Area Image|Up To B1 Display', + '4SLL' => 'Up To 1/4 Area Image|Up To A0 Display', + '4SEI' => 'Up To 1/4 Area Image|Up To B0 Display', + '4SBA' => 'Up To 1/2 Area Image|Up To 24 x 30 Inch Display', + '4SCL' => 'Up To 1/2 Area Image|Up To 30 x 40 Inch Display', + '4SIC' => 'Up To 1/2 Area Image|Up To 27 x 85 Inch Display', + '4SBY' => 'Up To 1/2 Area Image|Up To 60 x 40 Inch Display', + '4SFZ' => 'Up To 1/2 Area Image|Up To 27 x 141 Inch Display', + '4SAU' => 'Up To 1/2 Area Image|Up To 26 x 241 Inch Display', + '4SBR' => 'Up To 1/2 Area Image|Up To 30 x 240 Inch Display', + '4SCC' => 'Up To 1/2 Area Image|Up To B1 Display', + '4SAB' => 'Up To 1/2 Area Image|Up To A0 Display', + '4SLX' => 'Up To 1/2 Area Image|Up To B0 Display', + '4SGI' => 'Up To Full Area Image|Up To 24 x 30 Inch Display', + '4SBT' => 'Up To Full Area Image|Up To 30 x 40 Inch Display', + '4SGK' => 'Up To Full Area Image|Up To 27 x 85 Inch Display', + '4SIL' => 'Up To Full Area Image|Up To 60 x 40 Inch Display', + '4SAH' => 'Up To Full Area Image|Up To 69 x 48 Inch Display', + '4SGA' => 'Up To Full Area Image|Up To 27 x 141 Inch Display', + '4SDR' => 'Up To Full Area Image|Up To 26 x 241 Inch Display', + '4SID' => 'Up To Full Area Image|Up To 30 x 240 Inch Display', + '4SCX' => 'Up To Full Area Image|Any Size Display', + '4SGR' => 'Up To Full Area Image|Up To B1 Display', + '4SEC' => 'Up To Full Area Image|Up To A0 Display', + '4SET' => 'Up To Full Area Image|Up To B0 Display', + '4SKT' => 'Up To 1/4 Area Image|Up To 43 x 62 Inch Display', + '4SEW' => 'Up To 1/4 Area Image|Up To 48 x 71 Inch Display', + '4SEH' => 'Up To 1/4 Area Image|Up To 43 x 126 Inch Display', + '4SBS' => 'Up To 1/4 Area Image|Up To 83 x 135 Inch Display', + '4SMR' => 'Up To 1/4 Area Image|Any Size Display', + '4SJX' => 'Up To 1/4 Area Image|Up To B0 Display', + '4SAY' => 'Up To 1/2 Area Image|Up To 43 x 62 Inch Display', + '4SKY' => 'Up To 1/2 Area Image|Up To 48 x 71 Inch Display', + '4SBV' => 'Up To 1/2 Area Image|Up To 43 x 126 Inch Display', + '4SEP' => 'Up To 1/2 Area Image|Up To 83 x 135 Inch Display', + '4SNG' => 'Up To 1/2 Area Image|Any Size Display', + '4SAZ' => 'Up To 1/2 Area Image|Up To B0 Display', + '4SDW' => 'Up To Full Area Image|Up To 43 x 62 Inch Display', + '4SFW' => 'Up To Full Area Image|Up To 48 x 71 Inch Display', + '4SGN' => 'Up To Full Area Image|Up To 43 x 126 Inch Display', + '4SBX' => 'Up To Full Area Image|Up To 83 x 135 Inch Display', + '4SNO' => 'Up To Full Area Image|Any Size Display', + '4SKK' => 'Up To Full Area Image|Up To B0 Display', + '4SAP' => 'Up To 1/4 Screen Image|Up To 32 Inch Screen', + '4SEK' => 'Up To 1/4 Screen Image|Up To 63 Inch Screen', + '4SLZ' => 'Up To 1/4 Screen Image|Up To 10 Diagonal Foot Screen', + '4SIE' => 'Up To 1/4 Screen Image|Up To 30 Diagonal Foot Screen', + '4SEM' => 'Up To 1/4 Screen Image|Up To 100 Diagonal Foot Screen', + '4SGJ' => 'Up To 1/2 Screen Image|Up To 32 Inch Screen', + '4SBE' => 'Up To 1/2 Screen Image|Up To 63 Inch Screen', + '4SIJ' => 'Up To 1/2 Screen Image|Up To 10 Diagonal Foot Screen', + '4SGY' => 'Up To 1/2 Screen Image|Up To 30 Diagonal Foot Screen', + '4SDQ' => 'Up To 1/2 Screen Image|Up To 100 Diagonal Foot Screen', + '4SBZ' => 'Up To Full Screen Image|Up To 32 Inch Screen', + '4SJF' => 'Up To Full Screen Image|Up To 63 Inch Screen', + '4SLE' => 'Up To Full Screen Image|Up To 10 Diagonal Foot Screen', + '4SJY' => 'Up To Full Screen Image|Up To 30 Diagonal Foot Screen', + '4SKC' => 'Up To Full Screen Image|Up To 100 Diagonal Foot Screen', + '4SDL' => 'Up To Full Screen Image|Any Size Screen', + '4SFA' => 'Up To 1/4 Area Image|Any Size Item', + '4SCG' => 'Up To 1/2 Area Image|Any Size Item', + '4SLR' => 'Up To Full Area Image|Any Size Item', + '4SGZ' => 'Up To 3 x 4.5 Inch Image|Any Size Media', + '4SFH' => 'Up To 5 x 7 Inch Image|Any Size Media', + '4SCU' => 'Up To 6 x 9 Inch Image|Any Size Media', + '4SLF' => 'Up To 8 x 10 Inch Image|Any Size Media', + '4SAV' => 'Up To 8 x 12 Inch Image|Any Size Media', + '4SKB' => 'Up To 11 x 14 Inch Image|Any Size Media', + '4SAE' => 'Up To 14 x 20 Inch Image|Any Size Media', + '4SEZ' => 'Up To 16 x 20 Inch Image|Any Size Media', + '4SDB' => 'Up To 20 x 24 Inch Image|Any Size Media', + '4SDG' => 'Up To 24 x 30 Inch Image|Any Size Media', + '4SDE' => 'Up To 30 x 40 Inch Image|Any Size Media', + '4SJE' => 'Up To 38 x 50 Inch Image|Any Size Media', + '4SCM' => 'Up To 40 x 60 Inch Image|Any Size Media', + '4SIN' => 'Any Size Image|Any Size Media', + '4SDA' => 'Up To 11 x 15 cm Image|Any Size Media', + '4SME' => 'Up To 13 x 18 cm Image|Any Size Media', + '4SFC' => 'Up To 15 x 21 cm Image|Any Size Media', + '4SIG' => 'Up To 18 x 25 cm Image|Any Size Media', + '4SEV' => 'Up To 21 x 30 cm Image|Any Size Media', + '4SJJ' => 'Up To 25 x 36 cm Image|Any Size Media', + '4SMD' => 'Up To 25 x 36 cm Image|Any Size Media', + '4SLH' => 'Up To 30 x 42 cm Image|Any Size Media', + '4SEE' => 'Up To 42 x 60 cm Image|Any Size Media', + '4SDC' => 'Up To 50 x 71 cm Image|Any Size Media', + '4SDY' => 'Up To 60 x 85 cm Image|Any Size Media', + '4SCQ' => 'Up To 70 x 100 cm Image|Any Size Media', + '4SMF' => 'Up To 85 x 119 cm Image|Any Size Media', + '4SJC' => 'Up To 100 x 142 cm Image|Any Size Media', + '4SFN' => 'Up To 1/4 Area Image|Up To 25 x 13 Inch Media', + '4SLC' => 'Up To 1/4 Area Image|Up To 50 x 24 Inch Media', + '4SIR' => 'Up To 1/4 Area Image|Up To 26 x 53 Inch Media', + '4SDT' => 'Up To 1/4 Area Image|Up To 46 x 60 Inch Media', + '4SFB' => 'Up To 1/4 Area Image|Up To 138 x 53 Inch Media', + '4SGV' => 'Up To 1/2 Area Image|Up To 25 x 13 Inch Media', + '4SJR' => 'Up To 1/2 Area Image|Up To 50 x 24 Inch Media', + '4SKL' => 'Up To 1/2 Area Image|Up To 26 x 53 Inch Media', + '4SEX' => 'Up To 1/2 Area Image|Up To 46 x 60 Inch Media', + '4SBW' => 'Up To 1/2 Area Image|Up To 138 x 53 Inch Media', + '4SJN' => 'Up To Full Area Image|Up To 25 x 13 Inch Media', + '4SKH' => 'Up To Full Area Image|Up To 50 x 24 Inch Media', + '4SKM' => 'Up To Full Area Image|Up To 26 x 53 Inch Media', + '4SGG' => 'Up To Full Area Image|Up To 46 x 60 Inch Media', + '4SDJ' => 'Up To Full Area Image|Up To 138 x 53 Inch Media', + '4SCZ' => 'Up To 1/4 Screen Image|Up To 15 Inch Screen', + '4SCS' => 'Up To 1/4 Screen Image|Up To 21 Inch Screen', + '4SMS' => 'Up To 1/4 Screen Image|Any Size Screen', + '4SED' => 'Up To 1/2 Screen Image|Up To 15 Inch Screen', + '4SFV' => 'Up To 1/2 Screen Image|Up To 21 Inch Screen', + '4SMT' => 'Up To 1/2 Screen Image|Any Size Screen', + '4SCY' => 'Up To Full Screen Image|Up To 15 Inch Screen', + '4SEB' => 'Up To Full Screen Image|Up To 21 Inch Screen', + '4SMU' => 'Up To Full Screen Image|Any Size Screen', + '4SGH' => 'Up To 1/4 Screen Image|Any Size Screen', + '4SGC' => 'Up To 1/2 Screen Image|Any Size Screen', + '4SES' => 'Up To Full Screen Image|Any Size Screen', + '4SKQ' => 'Up To 1/4 Area Image|Up To 180 x 150 Pixels Ad', + '4SCA' => 'Up To 1/4 Area Image|Up To 468 x 60 Pixels Ad', + '4SCK' => 'Up To 1/4 Area Image|Up To 728 x 90 Pixels Ad', + '4SCF' => 'Up To 1/4 Area Image|Up To 300 x 600 Pixels Ad', + '4SIU' => 'Up To 1/4 Area Image|Up To Full Screen Ad', + '4SAI' => 'Up To 1/2 Area Image|Up To 180 x 150 Pixels Ad', + '4SII' => 'Up To 1/2 Area Image|Up To 468 x 60 Pixels Ad', + '4SCW' => 'Up To 1/2 Area Image|Up To 728 x 90 Pixels Ad', + '4SLM' => 'Up To 1/2 Area Image|Up To 300 x 600 Pixels Ad', + '4SFT' => 'Up To 1/2 Area Image|Up To Full Screen Ad', + '4SJT' => 'Up To Full Area Image|Up To 180 x 150 Pixels Ad', + '4SGD' => 'Up To Full Area Image|Up To 468 x 60 Pixels Ad', + '4SAR' => 'Up To Full Area Image|Up To 728 x 90 Pixels Ad', + '4SEG' => 'Up To Full Area Image|Up To 300 x 600 Pixels Ad', + '4SBG' => 'Any Size Image|Up To Full Screen Ad', + '4SMH' => 'Up To 150 x 150 Pixels Image|Any Size Screen', + '4SMJ' => 'Up To 300 x 600 Pixels Image|Any Size Screen', + '4SKG' => 'Any Size Image|Any Size Screen', + # 5V - Version + '5VAA' => 'All Versions', + '5VXX' => 'Not Applicable or None', + '5VUL' => 'Any Versions', + '5VVM' => 'Single Print Version', + '5VVB' => 'Multiple Print Versions', + '5VUP' => 'Single Version', + '5VUY' => 'Multiple Versions', + '5VVC' => 'Single Paperback Edition', + '5VUK' => 'Single Hardcover Edition', + '5VVH' => 'Single Edition in All Binding Formats', + '5VVK' => 'Multiple Paperback Editions', + '5VUU' => 'Multiple Hardcover Editions', + '5VVL' => 'Multiple Editions in All Binding Formats', + '5VUZ' => 'Single Issue', + '5VVJ' => 'Multiple Issues', + '5VUG' => 'Single Edition', + '5VVG' => 'Multiple Editions', + # 6Q - Quantity + '6QAA' => 'Any Quantity', + '6QXX' => 'Not Applicable or None', + '6QUL' => 'Any Quantity', + '6QAU' => 'One|Print Run', + '6QDA' => 'Up To 10|Print Run', + '6QEY' => 'Up To 100|Print Run', + '6QBA' => 'Up To 1,000|Print Run', + '6QCW' => 'Up To 5,000|Print Run', + '6QEC' => 'Up To 10,000|Print Run', + '6QFD' => 'Up To 25,000|Print Run', + '6QBH' => 'Up To 40,000|Print Run', + '6QFR' => 'Up To 50,000|Print Run', + '6QDQ' => 'Up To 100,000|Print Run', + '6QBG' => 'Up To 250,000|Print Run', + '6QEN' => 'Up To 500,000|Print Run', + '6QDL' => 'Any Quantity Of|Print Run', + '6QBU' => 'One|Copy', + '6QDR' => 'Up To 10|Total Circulation', + '6QFU' => 'Up To 25|Total Circulation', + '6QFV' => 'Up To 50|Total Circulation', + '6QEJ' => 'Up To 100|Total Circulation', + '6QFW' => 'Up To 250|Total Circulation', + '6QFY' => 'Up To 500|Total Circulation', + '6QCD' => 'Up To 1,000|Total Circulation', + '6QFZ' => 'Up To 2,500|Total Circulation', + '6QAT' => 'Up To 5,000|Total Circulation', + '6QBB' => 'Up To 10,000|Total Circulation', + '6QFS' => 'Up To 25,000|Total Circulation', + '6QAN' => 'Up To 50,000|Total Circulation', + '6QCS' => 'Up To 100,000|Total Circulation', + '6QDT' => 'Up To 250,000|Total Circulation', + '6QCI' => 'Up To 500,000|Total Circulation', + '6QCN' => 'Up To 1 Million|Total Circulation', + '6QCK' => 'Up To 2 Million|Total Circulation', + '6QCL' => 'Up To 3 Million|Total Circulation', + '6QAV' => 'Up To 5 Million|Total Circulation', + '6QDK' => 'Up To 10 Million|Total Circulation', + '6QGB' => 'Up To 25 Million|Total Circulation', + '6QGC' => 'Up To 50 Million|Total Circulation', + '6QEV' => 'Any Quantity Of|Circulation', + '6QFI' => 'One|Reprint', + '6QDG' => 'Up To 10|Reprints', + '6QCB' => 'Up To 100|Reprints', + '6QAY' => 'Up To 1,000|Reprints', + '6QBF' => 'Up To 10,000|Reprints', + '6QCU' => 'Any Quantity Of|Reprints', + '6QEH' => 'One|Print Run', + '6QDH' => 'Up To 10|Print Run', + '6QAZ' => 'Up To 100|Print Run', + '6QFB' => 'Up To 1,000|Print Run', + '6QAQ' => 'Up To 5,000|Print Run', + '6QEG' => 'Up To 10,000|Print Run', + '6QBV' => 'Up To 25,000|Print Run', + '6QCG' => 'Up To 50,000|Print Run', + '6QAH' => 'Up To 100,000|Print Run', + '6QDE' => 'Up To 250,000|Print Run', + '6QDJ' => 'Up To 500,000|Print Run', + '6QCZ' => 'Up To 1 Million|Print Run', + '6QCT' => 'Up To 2 Million|Print Run', + '6QAR' => 'Up To 3 Million|Print Run', + '6QDC' => 'Up To 5 Million|Print Run', + '6QDU' => 'Up To 10 Million|Print Run', + '6QEU' => 'Any Quantity Of|Print Run', + '6QFT' => 'One|Copy', + '6QDI' => 'One|Display', + '6QDY' => 'Up To 5|Displays', + '6QFJ' => 'Up To 10|Displays', + '6QEL' => 'Up To 25|Displays', + '6QBD' => 'Up To 50|Displays', + '6QAE' => 'Up To 100|Displays', + '6QCE' => 'Up To 250|Displays', + '6QAP' => 'Up To 500|Displays', + '6QBY' => 'Up To 1,000|Displays', + '6QBC' => 'Up To 2,500|Displays', + '6QET' => 'Up To 5,000|Displays', + '6QFF' => 'Up To 10,000|Displays', + '6QDS' => 'Up To 25,000|Displays', + '6QES' => 'Up To 50,000|Displays', + '6QDZ' => 'Up To 100,000|Displays', + '6QBW' => 'Up To 250,000|Displays', + '6QAX' => 'Up To 500,000|Displays', + '6QDB' => 'Up To 1 Million|Displays', + '6QEK' => 'Up To 2 Million|Displays', + '6QFA' => 'Up To 3 Million|Displays', + '6QCJ' => 'Up To 5 Million|Displays', + '6QFQ' => 'Any Quantity Of|Displays', + '6QCX' => 'One|Display', + '6QBP' => 'Up To 5|Displays', + '6QAL' => 'Up To 10|Displays', + '6QDX' => 'Up To 25|Displays', + '6QEM' => 'Up To 50|Displays', + '6QEA' => 'Up To 100|Displays', + '6QFG' => 'Up To 250|Displays', + '6QAG' => 'Up To 500|Displays', + '6QEI' => 'Any Quantity Of|Displays', + '6QEP' => 'One|Copy', + '6QEX' => 'Two|Copies', + '6QCF' => 'Three|Copies', + '6QBK' => 'Four|Copies', + '6QBL' => 'Five|Copies', + '6QCP' => 'Up To 10|Copies', + '6QDV' => 'Up To 50|Copies', + '6QCM' => 'Up To 100|Copies', + '6QAI' => 'Up To 500|Copies', + '6QAS' => 'Up To 1,000|Copies', + '6QDW' => 'Up To 5,000|Copies', + '6QCQ' => 'Up To 10,000|Copies', + '6QAM' => 'Any Quantity Of|Copies', + '6QBE' => 'One|Copy', + '6QFC' => 'Up To 5|Copies', + '6QEB' => 'Up To 10|Copies', + '6QGD' => 'Up To 25|Copies', + '6QGE' => 'Up To 50|Copies', + '6QCR' => 'Up To 100|Copies', + '6QCA' => 'Up To 250|Copies', + '6QBS' => 'Up To 500|Copies', + '6QDF' => 'Up To 1,000|Copies', + '6QEW' => 'Up To 2,500|Copies', + '6QFE' => 'Up To 5,000|Copies', + '6QEE' => 'Up To 10,000|Copies', + '6QBT' => 'Up To 25,000|Copies', + '6QDP' => 'Up To 50,000|Copies', + '6QDN' => 'Up To 100,000|Copies', + '6QFN' => 'Any Quantity Of|Copies', + '6QFH' => 'Up To 10,000|Viewers', + '6QCV' => 'Up To 100,000|Viewers', + '6QBN' => 'Up To 1 Million|Viewers', + '6QFP' => 'Up To 10 Million|Viewers', + '6QBI' => 'Up To 100 Million|Viewers', + '6QBQ' => 'Any Quantity Of|Viewers', + '6QAB' => 'Up To 10,000|Impressions', + '6QBR' => 'Up To 100,000|Impressions', + '6QCY' => 'Up To 1 Million|Impressions', + '6QBM' => 'Up To 10 Million|Impressions', + '6QFM' => 'Any Quantity Of|Impressions', + '6QDD' => 'Up To 100|Viewers', + '6QEQ' => 'Up To 1,000|Viewers', + '6QEZ' => 'Up To 10,000|Viewers', + '6QBZ' => 'Up To 100,000|Viewers', + '6QCC' => 'Any Quantity Of|Viewers', + '6QCH' => 'One|Copy', + '6QAW' => 'Up To 5|Copies', + '6QAK' => 'Up To 10|Copies', + '6QFL' => 'Up To 100|Copies', + '6QAC' => 'Up To 1,000|Copies', + '6QAD' => 'Up To 10,000|Copies', + '6QEF' => 'Up To 25,000|Copies', + '6QAF' => 'Up To 50,000|Copies', + '6QED' => 'Up To 100,000|Copies', + '6QFK' => 'Up To 250,000|Copies', + '6QDM' => 'Up To 500,000|Copies', + '6QBX' => 'Up To 1 Million|Copies', + '6QER' => 'Any Quantity Of|Copies', + # 7D - Duration + '7DAA' => 'In Perpetuity', + '7DXX' => 'Not Applicable or None', + '7DUL' => 'Any Durations', + '7DUT' => 'Up To 10 Years', + '7DUS' => 'Up To 6 Months', + '7DUV' => 'Up To 6 Months', + '7DUW' => 'Up To 1 Year', + '7DUY' => 'Up To 3 Years', + '7DUZ' => 'Up To 5 Years', + '7DUQ' => 'Up To 10 Years', + '7DXC' => 'Up To 1 Day', + '7DXL' => 'Up To 1 Week', + '7DXH' => 'Life Of Publication', + '7DYF' => 'Up To 1 Day', + '7DWL' => 'Up To 1 Week', + '7DYJ' => 'Up To 2 Weeks', + '7DXF' => 'Up To 1 Month', + '7DZF' => 'Up To 2 Months', + '7DWC' => 'Up To 3 Months', + '7DWW' => 'Up To 6 Months', + '7DZA' => 'Up To 1 Year', + '7DZP' => 'Up To 2 Years', + '7DZJ' => 'Up To 3 Years', + '7DZK' => 'Up To 5 Years', + '7DZL' => 'Up To 10 Years', + '7DWS' => 'Life Of Publication', + '7DXZ' => 'Up To 3 Months', + '7DXW' => 'Up To 6 Months', + '7DXD' => 'Up To 1 Year', + '7DYS' => 'Life Of Publication', + '7DYM' => 'Up To 1 Year', + '7DWE' => 'Up To 2 Years', + '7DYL' => 'Up To 3 Years', + '7DWV' => 'Up To 5 Years', + '7DWB' => 'Up To 7 Years', + '7DYY' => 'Up To 10 Years', + '7DWG' => 'Up To 15 Years', + '7DXA' => 'Full Term Of Copyright', + '7DXT' => 'Up To 1 Day', + '7DXB' => 'Up To 1 Week', + '7DYI' => 'Up To 1 Month', + '7DWI' => 'Up To 1 Year', + '7DZM' => 'Up To 2 Years', + '7DZN' => 'Up To 3 Years', + '7DYV' => 'Life Of Event', + '7DXQ' => 'Up To 1 Year', + '7DZH' => 'Up To 2 Years', + '7DXP' => 'Up To 3 Years', + '7DYD' => 'Up To 5 Years', + '7DWU' => 'Up To 7 Years', + '7DXG' => 'Up To 10 Years', + '7DXV' => 'Up To 15 Years', + '7DWR' => 'In Perpetuity', + '7DXM' => 'Up To 1 Year', + '7DWK' => 'Up To 2 Years', + '7DXS' => 'In Perpetuity', + '7DYG' => 'Up To 1 Day', + '7DZD' => 'Up To 1 Week', + '7DWP' => 'Up To 13 Weeks', + '7DYT' => 'Up To 26 Weeks', + '7DWT' => 'Up To 52 Weeks', + '7DYA' => 'Up To 5 Years', + '7DXR' => 'Up To 10 Years', + '7DXI' => 'In Perpetuity', + '7DYW' => 'Up To 1 Day', + '7DYP' => 'Up To 1 Week', + '7DWJ' => 'Up To 1 Month', + '7DYE' => 'Up To 3 Months', + '7DYX' => 'Up To 6 Months', + '7DXE' => 'Up To 1 Year', + '7DWZ' => 'Up To 2 Years', + '7DZB' => 'Up To 3 Years', + '7DYN' => 'Up To 5 Years', + '7DYC' => 'Up To 10 Years', + '7DXY' => 'Up To 15 Years', + '7DWM' => 'In Perpetuity', + '7DYZ' => 'Up To 1 Day', + '7DXK' => 'Up To 1 Month', + '7DWY' => 'Up To 3 Months', + '7DYB' => 'Up To 6 Months', + '7DZG' => 'Up To 1 Year', + '7DYK' => 'Up To 2 Years', + '7DYQ' => 'In Perpetuity', + # 8R - Region + '8RAA' => 'Worldwide', + '8RXX' => 'Not Applicable or None', + '8RUL' => 'Any Regions', + '8RWA' => 'Broad International Region|Worldwide Excluding Northern America', + '8RWB' => 'Broad International Region|Worldwide Excluding USA', + '8RWC' => 'Broad International Region|Worldwide Excluding USA and Europe', + '8RWD' => 'Broad International Region|Worldwide Excluding Europe', + '8RWE' => 'Broad International Region|Worldwide Excluding USA and UK', + '8RWF' => 'Broad International Region|Worldwide Excluding UK', + '8RWG' => 'Broad International Region|All English Speaking Countries', + '8RWH' => 'Broad International Region|All English Speaking Countries Excluding USA', + '8RAH' => 'Broad International Region|All Spanish Speaking Countries', + '8RWI' => 'Broad International Region|All Spanish Speaking Countries Excluding USA', + '8RFY' => 'Broad International Region|All Americas', + '8REK' => 'Broad International Region|Europe, Middle East and Africa', + '8RWJ' => 'Broad International Region|USA, Canada and Mexico', + '8RQV' => 'Northern America|One Minor City, Up To 250,000 Population', + '8RQT' => 'Northern America|One Major City, Over 250,000 Population', + '8RQU' => 'Northern America|One Metropolitan Area, Adjoining Cities', + '8RRJ' => 'Northern America|One State Or Province', + '8RYK' => 'Northern America|Up To 3 States Or Provinces', + '8RCD' => 'Northern America|Up To 5 States Or Provinces', + '8RGJ' => 'Northern America|All Northern American Countries', + '8RCE' => 'Northern America|USA and Canada', + '8RHQ' => 'Northern America|USA', + '8RCA' => 'Northern America|Canada', + '8RHJ' => 'Northern America|USA-Central', + '8RHP' => 'Northern America|USA-Midwest', + '8RHR' => 'Northern America|USA-Northeast', + '8RHS' => 'Northern America|USA-Pacific Northwest', + '8RHW' => 'Northern America|USA-Southeast', + '8RHX' => 'Northern America|USA-Southwest', + '8RIA' => 'Northern America|USA-West', + '8RHY' => 'Northern America|USA-Minor Outlying Islands', + '8RUK' => 'Northern America|USA-All Territories, Protectorates, Dependencies, Outposts', + '8RBK' => 'Northern America|Canada-British Columbia', + '8RUM' => 'Northern America|Canada-Prairies', + '8RUN' => 'Northern America|Canada-Atlantic Provinces', + '8RCJ' => 'Northern America|Canada-Ontario', + '8RUP' => 'Northern America|Canada-Quebec', + '8RUQ' => 'Northern America|Canada-Northern Territories', + '8RBM' => 'Northern America|Bermuda', + '8RGL' => 'Northern America|Greenland', + '8RPM' => 'Northern America|Saint Pierre and Miquelon', + '8RQL' => 'Europe|One Minor City, Up To 250,000 Population', + '8RQJ' => 'Europe|One Major City, Over 250,000 Population', + '8RQK' => 'Europe|One Metropolitan Area, Adjoining Cities', + '8RRF' => 'Europe|One State Or Province', + '8RYF' => 'Europe|Up To 3 States Or Provinces', + '8RYG' => 'Europe|Up To 5 States Or Provinces', + '8RDU' => 'Europe|All Europe', + '8REL' => 'Europe|All European Union Countries', + '8REI' => 'Europe|All United Kingdom', + '8REJ' => 'Europe|All Western Europe', + '8RED' => 'Europe|All Northern Europe', + '8REB' => 'Europe|All European Mediterranean Countries', + '8REA' => 'Europe|All Eastern Europe', + '8RDW' => 'Europe|All Baltic States', + '8RDX' => 'Europe|All Benelux', + '8RDY' => 'Europe|All Caucasian States', + '8REF' => 'Europe|All Scandinavia', + '8RAX' => 'Europe|Aland Islands', + '8RAL' => 'Europe|Albania', + '8RAD' => 'Europe|Andorra', + '8RAM' => 'Europe|Armenia', + '8RAT' => 'Europe|Austria', + '8RAZ' => 'Europe|Azerbaijan', + '8RBY' => 'Europe|Belarus', + '8RBE' => 'Europe|Belgium', + '8RBA' => 'Europe|Bosnia and Herzegovina', + '8RBG' => 'Europe|Bulgaria', + '8RDR' => 'Europe|Croatia', + '8RCY' => 'Europe|Cyprus', + '8RCZ' => 'Europe|Czech Republic', + '8RDK' => 'Europe|Denmark', + '8REM' => 'Europe|England', + '8REE' => 'Europe|Estonia', + '8RDS' => 'Europe|Faeroe Islands', + '8RFI' => 'Europe|Finland', + '8RFR' => 'Europe|France', + '8RGE' => 'Europe|Georgia', + '8RDE' => 'Europe|Germany', + '8RGI' => 'Europe|Gibraltar', + '8RGR' => 'Europe|Greece', + '8RGG' => 'Europe|Guernsey', + '8RHU' => 'Europe|Hungary', + '8RIS' => 'Europe|Iceland', + '8RIE' => 'Europe|Ireland', + '8RIM' => 'Europe|Isle Of Man', + '8RIT' => 'Europe|Italy', + '8RJE' => 'Europe|Jersey', + '8RLV' => 'Europe|Latvia', + '8RLI' => 'Europe|Liechtenstein', + '8RLT' => 'Europe|Lithuania', + '8RLU' => 'Europe|Luxembourg', + '8RMK' => 'Europe|Macedonia', + '8RMT' => 'Europe|Malta', + '8RMD' => 'Europe|Moldova', + '8RMC' => 'Europe|Monaco', + '8RNL' => 'Europe|Netherlands', + '8RUH' => 'Europe|Northern Ireland', + '8RNO' => 'Europe|Norway', + '8RPL' => 'Europe|Poland', + '8RPT' => 'Europe|Portugal', + '8RRO' => 'Europe|Romania', + '8RRU' => 'Europe|Russian Federation', + '8RSM' => 'Europe|San Marino', + '8REN' => 'Europe|Scotland', + '8RCS' => 'Europe|Serbia and Montenegro', + '8RSK' => 'Europe|Slovakia', + '8RSI' => 'Europe|Slovenia', + '8RES' => 'Europe|Spain', + '8RSE' => 'Europe|Sweden', + '8RCH' => 'Europe|Switzerland', + '8RUA' => 'Europe|Ukraine', + '8RUI' => 'Europe|Wales', + '8RDT' => 'Europe|Vatican City State', + '8RQF' => 'Asia|One Minor City, Up To 250,000 Population', + '8RQD' => 'Asia|One Major City, Over 250,000 Population', + '8RQE' => 'Asia|One Metropolitan Area, Adjoining Cities', + '8RRC' => 'Asia|One State Or Province', + '8RAV' => 'Asia|Up To 3 States Or Provinces', + '8RYD' => 'Asia|Up To 5 States Or Provinces', + '8RDB' => 'Asia|All Asia', + '8RDC' => 'Asia|All Central Asia', + '8RCP' => 'Asia|All Eastern Asia', + '8RDG' => 'Asia|All Southern Asia', + '8RDH' => 'Asia|All Southeastern Asia', + '8RBD' => 'Asia|Bangladesh', + '8RBT' => 'Asia|Bhutan', + '8RBN' => 'Asia|Brunei Darussalam', + '8RKH' => 'Asia|Cambodia', + '8RCN' => 'Asia|All China', + '8RUB' => 'Asia|China-East', + '8RAY' => 'Asia|China-Northeast', + '8RUC' => 'Asia|China-North', + '8RUD' => 'Asia|China-South Central', + '8RUF' => 'Asia|China-Southwest', + '8RHK' => 'Asia|Hong Kong', + '8RIN' => 'Asia|India', + '8RID' => 'Asia|Indonesia', + '8RJP' => 'Asia|Japan', + '8RKZ' => 'Asia|Kazakhstan', + '8RKP' => 'Asia|North Korea', + '8RKR' => 'Asia|South Korea', + '8RKG' => 'Asia|Kyrgyzstan', + '8RLA' => 'Asia|Laos', + '8RMO' => 'Asia|Macao', + '8RMY' => 'Asia|Malaysia', + '8RMV' => 'Asia|Maldives', + '8RMN' => 'Asia|Mongolia', + '8RMM' => 'Asia|Myanmar', + '8RNP' => 'Asia|Nepal', + '8RPK' => 'Asia|Pakistan', + '8RPH' => 'Asia|Philippines', + '8RSG' => 'Asia|Singapore', + '8RTW' => 'Asia|Taiwan', + '8RTJ' => 'Asia|Tajikistan', + '8RTH' => 'Asia|Thailand', + '8RDA' => 'Asia|Tibet', + '8RTL' => 'Asia|Timor-Leste', + '8RTM' => 'Asia|Turkmenistan', + '8RUZ' => 'Asia|Uzbekistan', + '8RVN' => 'Asia|Viet Nam', + '8RQO' => 'Latin America and Caribbean|One Minor City, Up To 250,000 Population', + '8RQM' => 'Latin America and Caribbean|One Major City, Over 250,000 Population', + '8RQN' => 'Latin America and Caribbean|One Metropolitan Area, Adjoining Cities', + '8RRG' => 'Latin America and Caribbean|One State Or Province', + '8RYH' => 'Latin America and Caribbean|Up To 3 States Or Provinces', + '8RYI' => 'Latin America and Caribbean|Up To 5 States Or Provinces', + '8RAC' => 'Latin America and Caribbean|All Latin America and Caribbean', + '8RUJ' => 'Latin America and Caribbean|All Latin America', + '8RFZ' => 'Latin America and Caribbean|All Caribbean', + '8RFS' => 'Latin America and Caribbean|All South America', + '8RGC' => 'Latin America and Caribbean|All Central America', + '8RFT' => 'Latin America and Caribbean|All Andean Countries', + '8RFU' => 'Latin America and Caribbean|All Southern Cone', + '8RFV' => 'Latin America and Caribbean|All Amazonia', + '8RAI' => 'Latin America and Caribbean|Anguilla', + '8RAG' => 'Latin America and Caribbean|Antigua and Barbuda', + '8RAR' => 'Latin America and Caribbean|Argentina', + '8RAW' => 'Latin America and Caribbean|Aruba', + '8RBS' => 'Latin America and Caribbean|Bahamas', + '8RBB' => 'Latin America and Caribbean|Barbados', + '8RBZ' => 'Latin America and Caribbean|Belize', + '8RGZ' => 'Latin America and Caribbean|Bequia', + '8RBO' => 'Latin America and Caribbean|Bolivia', + '8RHA' => 'Latin America and Caribbean|Bonaire', + '8RBR' => 'Latin America and Caribbean|Brazil', + '8RHB' => 'Latin America and Caribbean|British Virgin Islands', + '8RKY' => 'Latin America and Caribbean|Cayman Islands', + '8RCL' => 'Latin America and Caribbean|Chile', + '8RCO' => 'Latin America and Caribbean|Colombia', + '8RCR' => 'Latin America and Caribbean|Costa Rica', + '8RCU' => 'Latin America and Caribbean|Cuba', + '8RHC' => 'Latin America and Caribbean|Curacao', + '8RDM' => 'Latin America and Caribbean|Dominica', + '8RDO' => 'Latin America and Caribbean|Dominican Republic', + '8REC' => 'Latin America and Caribbean|Ecuador', + '8RSV' => 'Latin America and Caribbean|El Salvador', + '8RFK' => 'Latin America and Caribbean|Falkland Islands, Malvinas', + '8RGF' => 'Latin America and Caribbean|French Guiana', + '8RGD' => 'Latin America and Caribbean|Grenada', + '8RGP' => 'Latin America and Caribbean|Guadeloupe', + '8RGT' => 'Latin America and Caribbean|Guatemala', + '8RGY' => 'Latin America and Caribbean|Guyana', + '8RHT' => 'Latin America and Caribbean|Haiti', + '8RHN' => 'Latin America and Caribbean|Honduras', + '8RJM' => 'Latin America and Caribbean|Jamaica', + '8RMQ' => 'Latin America and Caribbean|Martinique', + '8RMX' => 'Latin America and Caribbean|Mexico', + '8RMS' => 'Latin America and Caribbean|Montserrat', + '8RAN' => 'Latin America and Caribbean|Netherlands Antilles', + '8RNI' => 'Latin America and Caribbean|Nicaragua', + '8RPA' => 'Latin America and Caribbean|Panama', + '8RPY' => 'Latin America and Caribbean|Paraguay', + '8RFQ' => 'Latin America and Caribbean|Patagonia', + '8RPE' => 'Latin America and Caribbean|Peru', + '8RPR' => 'Latin America and Caribbean|Puerto Rico', + '8RHD' => 'Latin America and Caribbean|Saba', + '8RHE' => 'Latin America and Caribbean|Saint Barthelemy', + '8RHF' => 'Latin America and Caribbean|Saint Eustatius', + '8RKN' => 'Latin America and Caribbean|Saint Kitts and Nevis', + '8RLC' => 'Latin America and Caribbean|Saint Lucia', + '8RHG' => 'Latin America and Caribbean|Saint Martin', + '8RVC' => 'Latin America and Caribbean|Saint Vincent and The Grenadines', + '8RSR' => 'Latin America and Caribbean|Suriname', + '8RTT' => 'Latin America and Caribbean|Trinidad and Tobago', + '8RTC' => 'Latin America and Caribbean|Turks and Caicos Islands', + '8RHH' => 'Latin America and Caribbean|U.S. Virgin Islands', + '8RUY' => 'Latin America and Caribbean|Uruguay', + '8RVE' => 'Latin America and Caribbean|Venezuela', + '8RQZ' => 'Oceania|One Minor City, Up To 250,000 Population', + '8RQW' => 'Oceania|One Major City, Over 250,000 Population', + '8RQY' => 'Oceania|One Metropolitan Area, Adjoining Cities', + '8RRK' => 'Oceania|One State Or Province', + '8RYL' => 'Oceania|Up To 3 States Or Provinces', + '8RYM' => 'Oceania|Up To 5 States Or Provinces', + '8RCT' => 'Oceania|All Oceania', + '8RUR' => 'Oceania|All Australia and New Zealand', + '8RUS' => 'Oceania|All Oceania excluding Australia and New Zealand', + '8RAU' => 'Oceania|Australia', + '8RAS' => 'Oceania|American Samoa', + '8RCX' => 'Oceania|Christmas Island', + '8RCC' => 'Oceania|Cocos, Keeling Islands', + '8RKM' => 'Oceania|Comoros', + '8RCK' => 'Oceania|Cook Islands', + '8RFJ' => 'Oceania|Fiji', + '8RPF' => 'Oceania|French Polynesia', + '8RGU' => 'Oceania|Guam', + '8RKI' => 'Oceania|Kiribati', + '8RMG' => 'Oceania|Madagascar', + '8RMH' => 'Oceania|Marshall Islands', + '8RMU' => 'Oceania|Mauritius', + '8RFM' => 'Oceania|Micronesia', + '8RFF' => 'Oceania|Midway Islands', + '8RNR' => 'Oceania|Nauru', + '8RNC' => 'Oceania|New Caledonia', + '8RNZ' => 'Oceania|New Zealand', + '8RNU' => 'Oceania|Niue', + '8RNF' => 'Oceania|Norfolk Island', + '8RMP' => 'Oceania|Northern Mariana Islands', + '8RPW' => 'Oceania|Palau', + '8RPG' => 'Oceania|Papua New Guinea', + '8RPN' => 'Oceania|Pitcairn Islands', + '8RFH' => 'Oceania|Rapa Nui, Easter Island', + '8RWS' => 'Oceania|Samoa', + '8RSC' => 'Oceania|Seychelles', + '8RSB' => 'Oceania|Solomon Islands', + '8RLK' => 'Oceania|Sri Lanka', + '8RFL' => 'Oceania|Tahiti', + '8RTK' => 'Oceania|Tokelau', + '8RTO' => 'Oceania|Tonga', + '8RTV' => 'Oceania|Tuvalu', + '8RVU' => 'Oceania|Vanuatu', + '8RFP' => 'Oceania|Wallis and Futuna', + '8RQS' => 'Middle East|One Minor City, Up To 250,000 Population', + '8RQP' => 'Middle East|One Major City, Over 250,000 Population', + '8RQR' => 'Middle East|One Metropolitan Area, Adjoining Cities', + '8RRH' => 'Middle East|One State Or Province', + '8RYJ' => 'Middle East|Up To 3 States Or Provinces', + '8RBX' => 'Middle East|Up To 5 States Or Provinces', + '8REX' => 'Middle East|All Middle East', + '8REY' => 'Middle East|All Middle Eastern Gulf States', + '8RIB' => 'Middle East|All Middle Eastern Mediterranean Countries', + '8RAF' => 'Middle East|Afghanistan', + '8RBH' => 'Middle East|Bahrain', + '8RIR' => 'Middle East|Iran', + '8RIQ' => 'Middle East|Iraq', + '8RIL' => 'Middle East|Israel', + '8RJO' => 'Middle East|Jordan', + '8RKW' => 'Middle East|Kuwait', + '8RLB' => 'Middle East|Lebanon', + '8ROM' => 'Middle East|Oman', + '8REV' => 'Middle East|Palestinian Authority', + '8RQA' => 'Middle East|Qatar', + '8RSA' => 'Middle East|Saudi Arabia', + '8RSY' => 'Middle East|Syria', + '8RTR' => 'Middle East|Turkey', + '8RAE' => 'Middle East|United Arab Emirates', + '8RYE' => 'Middle East|Yemen', + '8RQC' => 'Africa|One Minor City, Up To 250,000 Population', + '8RQX' => 'Africa|One Major City, Over 250,000 Population', + '8RQB' => 'Africa|One Metropolitan Area, Adjoining Cities', + '8RRB' => 'Africa|One State Or Province', + '8RYB' => 'Africa|Up To 3 States Or Provinces', + '8RYC' => 'Africa|Up To 5 States Or Provinces', + '8RAJ' => 'Africa|All Africa', + '8RAK' => 'Africa|All African Mediterranean Countries', + '8RAP' => 'Africa|All Central Africa', + '8RAQ' => 'Africa|All Eastern Africa', + '8RBC' => 'Africa|All Southern Africa', + '8RBL' => 'Africa|All Western Africa', + '8RDZ' => 'Africa|Algeria', + '8RAO' => 'Africa|Angola', + '8RBP' => 'Africa|Ascension Island', + '8RBJ' => 'Africa|Benin', + '8RBW' => 'Africa|Botswana', + '8RBF' => 'Africa|Burkina Faso', + '8RBI' => 'Africa|Burundi', + '8RCM' => 'Africa|Cameroon', + '8RCV' => 'Africa|Cape Verde', + '8RCF' => 'Africa|Central African Republic', + '8RTD' => 'Africa|Chad', + '8RCG' => 'Africa|Congo', + '8RCI' => 'Africa|Cote D\'Ivoire', + '8RDJ' => 'Africa|Djibouti', + '8REG' => 'Africa|Egypt', + '8RGQ' => 'Africa|Equatorial Guinea', + '8RER' => 'Africa|Eritrea', + '8RET' => 'Africa|Ethiopia', + '8RGA' => 'Africa|Gabon', + '8RGM' => 'Africa|Gambia', + '8RGH' => 'Africa|Ghana', + '8RGN' => 'Africa|Guinea', + '8RGW' => 'Africa|Guinea-Bissau', + '8RKE' => 'Africa|Kenya', + '8RLS' => 'Africa|Lesotho', + '8RLR' => 'Africa|Liberia', + '8RLY' => 'Africa|Libyan Arab Jamahiriya', + '8RMW' => 'Africa|Malawi', + '8RML' => 'Africa|Mali', + '8RMR' => 'Africa|Mauritania', + '8RYT' => 'Africa|Mayotte', + '8RMA' => 'Africa|Morocco', + '8RMZ' => 'Africa|Mozambique', + '8RNA' => 'Africa|Namibia', + '8RNE' => 'Africa|Niger', + '8RNG' => 'Africa|Nigeria', + '8RRE' => 'Africa|Reunion', + '8RRW' => 'Africa|Rwanda', + '8RSH' => 'Africa|Saint Helena', + '8RST' => 'Africa|Sao Tome and Principe', + '8RSN' => 'Africa|Senegal', + '8RSL' => 'Africa|Sierra Leone', + '8RSO' => 'Africa|Somalia', + '8RZA' => 'Africa|South Africa', + '8RSD' => 'Africa|Sudan', + '8RSZ' => 'Africa|Swaziland', + '8RTZ' => 'Africa|Tanzania, United Republic Of', + '8RTG' => 'Africa|Togo', + '8RTN' => 'Africa|Tunisia', + '8RUG' => 'Africa|Uganda', + '8REH' => 'Africa|Western Sahara', + '8RZM' => 'Africa|Zambia', + '8RZW' => 'Africa|Zimbabwe', + '8RBQ' => 'Other Regions|Antarctica', + '8RCB' => 'Other Regions|All Arctic and Arctic Ocean Islands', + '8RFB' => 'Other Regions|All Northern Atlantic Ocean Islands', + '8RFW' => 'Other Regions|All Southern Atlantic Ocean Islands', + '8RFX' => 'Other Regions|All Southern Indian Ocean Islands', + '8REU' => 'Other Regions|All French Southern Territories', + '8RDQ' => 'Other Regions|All British Indian Ocean Territories', + # 8L - Language + '8LAA' => 'All Languages', + '8LXX' => 'Not Applicable or None', + '8LUL' => 'Any Languages', + '8LOL' => 'Any One Language', + '8LEN' => 'English', + '8LAF' => 'Afrikaans', + '8LAR' => 'Arabic', + '8LBO' => 'Bosnian', + '8LBU' => 'Bulgarian', + '8LCA' => 'Chinese-Cantonese', + '8LCH' => 'Chinese-Mandarin', + '8LCP' => 'Chinese-Other', + '8LCR' => 'Croatian', + '8LCZ' => 'Czech', + '8LDA' => 'Danish', + '8LDU' => 'Dutch', + '8LES' => 'Estonian', + '8LFI' => 'Finnish', + '8LFR' => 'French', + '8LGE' => 'German', + '8LGR' => 'Greek', + '8LHE' => 'Hebrew', + '8LHI' => 'Hindi', + '8LHU' => 'Hungarian', + '8LIC' => 'Icelandic', + '8LIN' => 'Indonesian', + '8LIG' => 'Irish Gaelic', + '8LIT' => 'Italian', + '8LJA' => 'Japanese', + '8LKO' => 'Korean', + '8LLA' => 'Latvian', + '8LMG' => 'Mongolian', + '8LNO' => 'Norwegian', + '8LPO' => 'Polish', + '8LPR' => 'Portuguese', + '8LRO' => 'Romanian', + '8LRU' => 'Russian', + '8LSG' => 'Scottish Gaelic', + '8LSE' => 'Serbian', + '8LSI' => 'Sindhi', + '8LSV' => 'Slovakian', + '8LSL' => 'Slovenian', + '8LSP' => 'Spanish', + '8LSH' => 'Swahili', + '8LSZ' => 'Swazi', + '8LSW' => 'Swedish', + '8LTA' => 'Tagalog', + '8LTH' => 'Thai', + '8LTU' => 'Turkish', + '8LUR' => 'Ukrainian', + '8LYI' => 'Yiddish', + '8LOT' => 'Other Language', + # 8I - Industry + '8IAA' => 'All Industries', + '8IXX' => 'Not Applicable or None', + '8IUL' => 'Any Industries', + '8IAD' => 'Advertising and Marketing', + '8IAG' => 'Agriculture, Farming and Horticulture', + '8IAT' => 'Airline Transportation', + '8IAL' => 'Alcohol', + '8IAR' => 'Architecture and Engineering', + '8IAE' => 'Arts and Entertainment', + '8IAU' => 'Automotive', + '8IAV' => 'Aviation', + '8IBA' => 'Baby and Childcare', + '8IBE' => 'Beauty and Personal Care', + '8IBI' => 'Biotechnology', + '8IBR' => 'Broadcast Media', + '8ICO' => 'Business Consulting and Services', + '8ICH' => 'Chemicals', + '8ICE' => 'Communications Equipment and Services', + '8IHS' => 'Computer Hardware, Software and Peripherals', + '8ICC' => 'Construction and Contracting', + '8IAP' => 'Consumer Appliances and Electronics', + '8ICG' => 'Counseling', + '8IEC' => 'Ecology, Environmental and Conservation', + '8IED' => 'Education', + '8IEM' => 'Employment Training and Recruitment', + '8IEN' => 'Energy, Utilities and Fuel', + '8IEV' => 'Events and Conventions', + '8IFA' => 'Fashion', + '8IFI' => 'Financial Services and Banking', + '8IFB' => 'Food and Beverage Processing', + '8IFL' => 'Food and Beverage Retail', + '8IFS' => 'Food Services', + '8IFO' => 'Forestry and Wood Products', + '8IFR' => 'Freight and Warehousing', + '8IFU' => 'Furniture', + '8IGA' => 'Games, Toys and Hobbies', + '8IGI' => 'Gaming Industry', + '8IGL' => 'Gardening and Landscaping', + '8IGO' => 'Government and Politics', + '8IGR' => 'Graphic Design', + '8IGC' => 'Greeting Card', + '8IHI' => 'Heavy Industry', + '8IHO' => 'Home Improvement', + '8IHH' => 'Hotels and Hospitality', + '8IHA' => 'Household Appliances', + '8IHC' => 'Household Cleaning Products', + '8IIM' => 'Industry and Manufacturing', + '8IIT' => 'Information Technologies', + '8IIN' => 'Insurance', + '8IIS' => 'Internet Services', + '8ILS' => 'Legal Services', + '8IME' => 'Medical and Healthcare', + '8IMS' => 'Microelectronics and Semiconductors', + '8IMW' => 'Military and Weapons', + '8IMM' => 'Mining and Metals', + '8IMU' => 'Music', + '8INP' => 'Not For Profit, Social, Charitable', + '8IOP' => 'Office Products', + '8IOG' => 'Oil and Gas', + '8IOI' => 'Other Industry', + '8IPO' => 'Personal Use Only', + '8IPP' => 'Pet Products and Services', + '8IPS' => 'Pharmaceuticals and Supplements', + '8IPT' => 'Printing and Reprographics', + '8IPR' => 'Public Relations', + '8IPM' => 'Publishing Media', + '8IRE' => 'Real Estate', + '8IRR' => 'Religion and Religious Services', + '8ISM' => 'Retail Sales and Marketing', + '8IRM' => 'Retail Merchandise', + '8ISS' => 'Safety and Security', + '8ISC' => 'Sciences', + '8ISH' => 'Shipping', + '8ISO' => 'Software', + '8ISF' => 'Sports, Fitness and Recreation', + '8ITE' => 'Telecommunications', + '8ITX' => 'Textiles and Apparel', + '8ITB' => 'Tobacco', + '8ITR' => 'Travel and Tourism', + # 9E - Exclusivity + '9EXX' => 'Not Applicable or None', + '9ENE' => 'Non-Exclusive', + '9EXC' => 'All Exclusive', + '9EIN' => 'Exclusivity For Industry', + '9EME' => 'Exclusivity For Media', + '9ELA' => 'Exclusivity For Language', + '9ERE' => 'Exclusivity For Region' +); + +# PLUS License Data Format 1.2.0 (plus) (ref 1) +%Image::ExifTool::PLUS::XMP = ( + %Image::ExifTool::XMP::xmpTableDefaults, + GROUPS => { 0 => 'XMP', 1 => 'XMP-plus', 2 => 'Author' }, + NAMESPACE => 'plus', + NOTES => q{ + PLUS (Picture Licensing Universal System) License Data Format 1.2.1 XMP + tags. Note that all controlled-vocabulary tags in this table (ie. tags with + a fixed set of values) have raw values which begin with + "http://ns.useplus.org/ldf/vocab/", but to reduce clutter this prefix has + been removed from the values shown below. See L<http://ns.useplus.org/> for + the complete specification. + }, + Version => { Name => 'PLUSVersion' }, + Licensee => { + FlatName => '', + Struct => \%plusLicensee, + List => 'Seq', + }, + EndUser => { + FlatName => '', + Struct => \%plusEndUser, + List => 'Seq', + }, + Licensor => { + FlatName => '', + Struct => \%plusLicensor, + List => 'Seq', + }, + LicensorNotes => { Writable => 'lang-alt' }, + MediaSummaryCode => { + SeparateTable => 'MediaMatrix', + PrintConv => \%mediaMatrix, + }, + LicenseStartDate => { %Image::ExifTool::XMP::dateTimeInfo, Groups => { 2 => 'Time'} }, + LicenseEndDate => { %Image::ExifTool::XMP::dateTimeInfo, Groups => { 2 => 'Time'} }, + MediaConstraints => { Writable => 'lang-alt' }, + RegionConstraints => { Writable => 'lang-alt' }, + ProductOrServiceConstraints => { Writable => 'lang-alt' }, + ImageFileConstraints => { + List => 'Bag', + %plusVocab, + PrintConv => { + 'IF-MFN' => 'Maintain File Name', + 'IF-MID' => 'Maintain ID in File Name', + 'IF-MMD' => 'Maintain Metadata', + 'IF-MFT' => 'Maintain File Type', + }, + }, + ImageAlterationConstraints => { + List => 'Bag', + %plusVocab, + PrintConv => { + 'AL-CRP' => 'No Cropping', + 'AL-FLP' => 'No Flipping', + 'AL-RET' => 'No Retouching', + 'AL-CLR' => 'No Colorization', + 'AL-DCL' => 'No De-Colorization', + 'AL-MRG' => 'No Merging', + }, + }, + ImageDuplicationConstraints => { + %plusVocab, + PrintConv => { + 'DP-NDC' => 'No Duplication Constraints', + 'DP-LIC' => 'Duplication Only as Necessary Under License', + 'DP-NOD' => 'No Duplication', + }, + }, + ModelReleaseStatus => { + %plusVocab, + PrintConv => { + 'MR-NON' => 'None', + 'MR-NAP' => 'Not Applicable', + 'MR-UMR' => 'Unlimited Model Releases', + 'MR-LMR' => 'Limited or Incomplete Model Releases', + }, + }, + ModelReleaseID => { List => 'Bag' }, + MinorModelAgeDisclosure => { + %plusVocab, + PrintConv => { + 'AG-UNK' => 'Age Unknown', + 'AG-A25' => 'Age 25 or Over', + 'AG-A24' => 'Age 24', + 'AG-A23' => 'Age 23', + 'AG-A22' => 'Age 22', + 'AG-A21' => 'Age 21', + 'AG-A20' => 'Age 20', + 'AG-A19' => 'Age 19', + 'AG-A18' => 'Age 18', + 'AG-A17' => 'Age 17', + 'AG-A16' => 'Age 16', + 'AG-A15' => 'Age 15', + 'AG-U14' => 'Age 14 or Under', + }, + }, + PropertyReleaseStatus => { + %plusVocab, + PrintConv => { + 'PR-NON' => 'None', + 'PR-NAP' => 'Not Applicable', + 'PR-UPR' => 'Unlimited Property Releases', + 'PR-LPR' => 'Limited or Incomplete Property Releases', + }, + }, + PropertyReleaseID => { List => 'Bag' }, + OtherConstraints => { Writable => 'lang-alt' }, + CreditLineRequired => { + %plusVocab, + PrintConv => { + 'CR-NRQ' => 'Not Required', + 'CR-COI' => 'Credit on Image', + 'CR-CAI' => 'Credit Adjacent To Image', + 'CR-CCA' => 'Credit in Credits Area', + }, + }, + AdultContentWarning => { + %plusVocab, + PrintConv => { + 'CW-NRQ' => 'Not Required', + 'CW-AWR' => 'Adult Content Warning Required', + 'CW-UNK' => 'Unknown', + }, + }, + OtherLicenseRequirements => { Writable => 'lang-alt' }, + TermsAndConditionsText => { Writable => 'lang-alt' }, + TermsAndConditionsURL => { }, + OtherConditions => { Writable => 'lang-alt' }, + ImageType => { + %plusVocab, + PrintConv => { + 'TY-PHO' => 'Photographic Image', + 'TY-ILL' => 'Illustrated Image', + 'TY-MCI' => 'Multimedia or Composited Image', + 'TY-VID' => 'Video', + 'TY-OTR' => 'Other', + }, + }, + LicensorImageID => { }, + FileNameAsDelivered => { }, + ImageFileFormatAsDelivered => { + %plusVocab, + PrintConv => { + 'FF-JPG' => 'JPEG Interchange Formats (JPG, JIF, JFIF)', + 'FF-TIF' => 'Tagged Image File Format (TIFF)', + 'FF-GIF' => 'Graphics Interchange Format (GIF)', + 'FF-RAW' => 'Proprietary RAW Image Format', + 'FF-DNG' => 'Digital Negative (DNG)', + 'FF-EPS' => 'Encapsulated PostScript (EPS)', + 'FF-BMP' => 'Windows Bitmap (BMP)', + 'FF-PSD' => 'Photoshop Document (PSD)', + 'FF-PIC' => 'Macintosh Picture (PICT)', + 'FF-PNG' => 'Portable Network Graphics (PNG)', + 'FF-WMP' => 'Windows Media Photo (HD Photo)', + 'FF-OTR' => 'Other', + }, + }, + ImageFileSizeAsDelivered => { + %plusVocab, + PrintConv => { + 'SZ-U01' => 'Up to 1 MB', + 'SZ-U10' => 'Up to 10 MB', + 'SZ-U30' => 'Up to 30 MB', + 'SZ-U50' => 'Up to 50 MB', + 'SZ-G50' => 'Greater than 50 MB', + }, + }, + CopyrightStatus => { + %plusVocab, + PrintConv => { + 'CS-PRO' => 'Protected', + 'CS-PUB' => 'Public Domain', + 'CS-UNK' => 'Unknown', + }, + }, + CopyrightRegistrationNumber => { }, + FirstPublicationDate => { %Image::ExifTool::XMP::dateTimeInfo, Groups => { 2 => 'Time'} }, + CopyrightOwner => { + FlatName => '', + Struct => \%plusCopyrightOwner, + List => 'Seq', + }, + CopyrightOwnerImageID => { }, + ImageCreator => { + FlatName => '', + Struct => \%plusImageCreator, + List => 'Seq', + }, + ImageCreatorImageID => { }, + ImageSupplier => { + FlatName => '', + Struct => \%plusImageSupplier, + List => 'Seq', + }, + ImageSupplierImageID => { }, + LicenseeImageID => { }, + LicenseeImageNotes => { Writable => 'lang-alt' }, + OtherImageInfo => { Writable => 'lang-alt' }, + LicenseID => { }, + LicensorTransactionID => { List => 'Bag' }, + LicenseeTransactionID => { List => 'Bag' }, + LicenseeProjectReference=> { List => 'Bag' }, + LicenseTransactionDate => { %Image::ExifTool::XMP::dateTimeInfo, Groups => { 2 => 'Time'} }, + Reuse => { + %plusVocab, + PrintConv => { + 'RE-REU' => 'Repeat Use', + 'RE-NAP' => 'Not Applicable', + }, + }, + OtherLicenseDocuments => { List => 'Bag' }, + OtherLicenseInfo => { Writable => 'lang-alt' }, + # Note: these are Bag's of lang-alt lists -- a nested list tag! + Custom1 => { List => 'Bag', Writable => 'lang-alt' }, + Custom2 => { List => 'Bag', Writable => 'lang-alt' }, + Custom3 => { List => 'Bag', Writable => 'lang-alt' }, + Custom4 => { List => 'Bag', Writable => 'lang-alt' }, + Custom5 => { List => 'Bag', Writable => 'lang-alt' }, + Custom6 => { List => 'Bag', Writable => 'lang-alt' }, + Custom7 => { List => 'Bag', Writable => 'lang-alt' }, + Custom8 => { List => 'Bag', Writable => 'lang-alt' }, + Custom9 => { List => 'Bag', Writable => 'lang-alt' }, + Custom10 => { List => 'Bag', Writable => 'lang-alt' }, +); + +#------------------------------------------------------------------------------ +# Validate Media Summary Code +# Inputs: 0) Media Usage Code +# Returns: true if OK, false on severe error +# - issues warning for detected format problems +# - repairs some repairable problems +sub ValidateMediaSummary($) +{ + my $val = shift; + + my @a = split /\|/, $val; + @a >= 4 and $a[0] eq '' or warn("Not a valid Media Summary Code\n"), return 0; + $a[1] eq 'PLUS' or warn("Unrecognized Media Usage standard\n"), return 0; + $a[2] =~ /^V(\d+)/ or warn("Unrecognized Media Usage version\n"); + $a[3] =~ /^U(\d+)/ or warn("Invalid Media Usage count\n"), return 0; + my $numUsages = $1; + my ($i, $j); + unless ($numUsages == @a - 4) { + warn("Fixed incorrect number of Media Usages\n"); + $numUsages = @a - 4; + $a[3] = sprintf('U%.3d', $numUsages); + } + for ($i=1; $i<=$numUsages; ++$i) { + my $usage = $a[$i + 3]; + $usage =~ /^1I([A-Z])([A-Z])/ or warn("Missing Media Usage $i item count\n"), return 0; + length($usage) % 4 and warn("Incorrect Media Usage $i length\n"), return 0; + my $numItems = (ord($1)-65) * 26 + ord($2)-65 + 1; + unless (length($usage) == 4 * ($numItems + 1)) { + $numItems = length($usage) / 4 - 1; + warn("Fixed incorrect Media Usage $i item count\n"); + $a[$i+3] = '1I' . chr(65 + int($numItems / 26)) . chr($numItems % 26) . substr($usage, 4); + } + for ($j=1; $j<=$numItems; ++$j) { + my $item = substr($usage, $j*4, 4); + $item =~ /^\d[A-Z]{3}$/ or warn(qq(Invalid item "$item" for Media Usage $i\n)), return 0; + } + } + $_[0] = join('|', @a) . '|' if $Image::ExifTool::evalWarning; + return 1; +} + +1; # end + +__END__ + +=head1 NAME + +Image::ExifTool::PLUS - PLUS (Picture Licensing Universal System) tags + +=head1 DESCRIPTION + +Definitions for PLUS (Picture Licensing Universal System) tags. + +=head1 AUTHOR + +Copyright 2003-2019, Phil Harvey (phil at owl.phy.queensu.ca) + +This library is free software; you can redistribute it and/or modify it +under the same terms as Perl itself. + +=head1 REFERENCES + +=over 4 + +=item L<http://www.useplus.com/useplus/standards.asp> + +=back + +=head1 SEE ALSO + +L<Image::ExifTool::TagNames/PLUS Tags>, +L<Image::ExifTool(3pm)|Image::ExifTool> + +=cut diff --git a/lib/Image/ExifTool/PNG.pm b/lib/Image/ExifTool/PNG.pm new file mode 100644 index 0000000..5d53a11 --- /dev/null +++ b/lib/Image/ExifTool/PNG.pm @@ -0,0 +1,1471 @@ +#------------------------------------------------------------------------------ +# File: PNG.pm +# +# Description: Read and write PNG meta information +# +# Revisions: 06/10/2005 - P. Harvey Created +# 06/23/2005 - P. Harvey Added MNG and JNG support +# 09/16/2005 - P. Harvey Added write support +# +# References: 1) http://www.libpng.org/pub/png/spec/1.2/ +# 2) http://www.faqs.org/docs/png/ +# 3) http://www.libpng.org/pub/mng/ +# 4) http://www.libpng.org/pub/png/spec/register/ +# 5) ftp://ftp.simplesystems.org/pub/png/documents/pngext-1.4.0-pdg.html +# 6) ftp://ftp.simplesystems.org/pub/png/documents/pngext-1.5.0.html +# +# Notes: Writing meta information in PNG images is a pain in the butt +# for a number of reasons: One biggie is that you have to +# decompress then decode the ASCII/hex profile information before +# you can edit it, then you have to ASCII/hex-encode, recompress +# and calculate a CRC before you can write it out again. gaaaak. +#------------------------------------------------------------------------------ + +package Image::ExifTool::PNG; + +use strict; +use vars qw($VERSION $AUTOLOAD %stdCase); +use Image::ExifTool qw(:DataAccess :Utils); + +$VERSION = '1.46'; + +sub ProcessPNG_tEXt($$$); +sub ProcessPNG_iTXt($$$); +sub ProcessPNG_eXIf($$$); +sub ProcessPNG_Compressed($$$); +sub CalculateCRC($;$$$); +sub HexEncode($); +sub AddChunks($$;@); +sub Add_iCCP($$); +sub DoneDir($$$;$); +sub GetLangInfo($$); +sub BuildTextChunk($$$$$); +sub ConvertPNGDate($$); +sub InversePNGDate($$); + +# translate lower-case to actual case used for eXIf/zXIf chunks +%stdCase = ( 'zxif' => 'zxIf', exif => 'eXIf' ); + +my $noCompressLib; + +# look up for file type, header chunk and end chunk, based on file signature +my %pngLookup = ( + "\x89PNG\r\n\x1a\n" => ['PNG', 'IHDR', 'IEND' ], + "\x8aMNG\r\n\x1a\n" => ['MNG', 'MHDR', 'MEND' ], + "\x8bJNG\r\n\x1a\n" => ['JNG', 'JHDR', 'IEND' ], +); + +# map for directories in PNG images +my %pngMap = ( + IFD1 => 'IFD0', + EXIF => 'IFD0', # to write EXIF as a block + ExifIFD => 'IFD0', + GPS => 'IFD0', + SubIFD => 'IFD0', + GlobParamIFD => 'IFD0', + PrintIM => 'IFD0', + InteropIFD => 'ExifIFD', + MakerNotes => 'ExifIFD', + IFD0 => 'PNG', + XMP => 'PNG', + ICC_Profile => 'PNG', + Photoshop => 'PNG', + 'PNG-pHYs' => 'PNG', + IPTC => 'Photoshop', + MakerNotes => 'ExifIFD', +); + +# color type of current image +$Image::ExifTool::PNG::colorType = -1; + +# PNG chunks +%Image::ExifTool::PNG::Main = ( + WRITE_PROC => \&Image::ExifTool::DummyWriteProc, + GROUPS => { 2 => 'Image' }, + PREFERRED => 1, # always add these tags when writing + NOTES => q{ + Tags extracted from PNG images. See + L<http://www.libpng.org/pub/png/spec/1.2/> for the official PNG 1.2 + specification. + + According to the specification, a PNG file should end at the IEND chunk, + however ExifTool will preserve any data found after this when writing unless + it is specifically deleted with C<-Trailer:All=>. When reading, a minor + warning is issued if this trailer exists, and ExifTool will attempt to parse + this data as additional PNG chunks. + }, + bKGD => { + Name => 'BackgroundColor', + ValueConv => 'join(" ",unpack(length($val) < 2 ? "C" : "n*", $val))', + }, + cHRM => { + Name => 'PrimaryChromaticities', + SubDirectory => { TagTable => 'Image::ExifTool::PNG::PrimaryChromaticities' }, + }, + dSIG => { + Name => 'DigitalSignature', + Binary => 1, + }, + fRAc => { + Name => 'FractalParameters', + Binary => 1, + }, + gAMA => { + Name => 'Gamma', + Notes => q{ + ExifTool reports the gamma for decoding the image, which is consistent with + the EXIF convention, but is the inverse of the stored encoding gamma + }, + ValueConv => 'my $a=unpack("N",$val);$a ? int(1e9/$a+0.5)/1e4 : $val', + }, + gIFg => { + Name => 'GIFGraphicControlExtension', + Binary => 1, + }, + gIFt => { + Name => 'GIFPlainTextExtension', + Binary => 1, + }, + gIFx => { + Name => 'GIFApplicationExtension', + Binary => 1, + }, + hIST => { + Name => 'PaletteHistogram', + Binary => 1, + }, + iCCP => { + Name => 'ICC_Profile', + Notes => 'this is where ExifTool will write a new ICC_Profile', + SubDirectory => { + TagTable => 'Image::ExifTool::ICC_Profile::Main', + ProcessProc => \&ProcessPNG_Compressed, + }, + }, + 'iCCP-name' => { + Name => 'ProfileName', + Notes => 'not a real tag ID, this tag represents the iCCP profile name', + }, +# IDAT +# IEND + IHDR => { + Name => 'ImageHeader', + SubDirectory => { TagTable => 'Image::ExifTool::PNG::ImageHeader' }, + }, + iTXt => { + Name => 'InternationalText', + SubDirectory => { + TagTable => 'Image::ExifTool::PNG::TextualData', + ProcessProc => \&ProcessPNG_iTXt, + }, + }, + oFFs => { + Name => 'ImageOffset', + ValueConv => q{ + my @a = unpack("NNC",$val); + $a[2] = ($a[2] ? "microns" : "pixels"); + return "$a[0], $a[1] ($a[2])"; + }, + }, + pCAL => { + Name => 'PixelCalibration', + Binary => 1, + }, + pHYs => { + Name => 'PhysicalPixel', + SubDirectory => { + TagTable => 'Image::ExifTool::PNG::PhysicalPixel', + DirName => 'PNG-pHYs', # (needed for writing) + }, + }, + PLTE => { + Name => 'Palette', + ValueConv => 'length($val) <= 3 ? join(" ",unpack("C*",$val)) : \$val', + }, + sBIT => { + Name => 'SignificantBits', + ValueConv => 'join(" ",unpack("C*",$val))', + }, + sCAL => { # png 1.4.0 + Name => 'SubjectScale', + SubDirectory => { TagTable => 'Image::ExifTool::PNG::SubjectScale' }, + }, + sPLT => { + Name => 'SuggestedPalette', + Binary => 1, + PrintConv => 'split("\0",$$val,1)', # extract palette name + }, + sRGB => { + Name => 'SRGBRendering', + ValueConv => 'unpack("C",$val)', + PrintConv => { + 0 => 'Perceptual', + 1 => 'Relative Colorimetric', + 2 => 'Saturation', + 3 => 'Absolute Colorimetric', + }, + }, + sTER => { # png 1.4.0 + Name => 'StereoImage', + SubDirectory => { TagTable => 'Image::ExifTool::PNG::StereoImage' }, + }, + tEXt => { + Name => 'TextualData', + SubDirectory => { TagTable => 'Image::ExifTool::PNG::TextualData' }, + }, + tIME => { + Name => 'ModifyDate', + Groups => { 2 => 'Time' }, + Writable => 1, + Shift => 'Time', + ValueConv => 'sprintf("%.4d:%.2d:%.2d %.2d:%.2d:%.2d", unpack("nC5", $val))', + ValueConvInv => q{ + my @a = ($val=~/^(\d+):(\d+):(\d+)\s+(\d+):(\d+):(\d+)/); + @a == 6 or warn('Invalid date'), return undef; + return pack('nC5', @a); + }, + PrintConv => '$self->ConvertDateTime($val)', + PrintConvInv => '$self->InverseDateTime($val)', + }, + tRNS => { + Name => 'Transparency', + ValueConv => q{ + return \$val if length($val) > 6; + join(" ",unpack($Image::ExifTool::PNG::colorType == 3 ? "C*" : "n*", $val)); + }, + }, + tXMP => { + Name => 'XMP', + Notes => 'obsolete location specified by a September 2001 XMP draft', + NonStandard => 'XMP', + SubDirectory => { TagTable => 'Image::ExifTool::XMP::Main' }, + }, + vpAg => { # private imagemagick chunk + Name => 'VirtualPage', + SubDirectory => { TagTable => 'Image::ExifTool::PNG::VirtualPage' }, + }, + zTXt => { + Name => 'CompressedText', + SubDirectory => { + TagTable => 'Image::ExifTool::PNG::TextualData', + ProcessProc => \&ProcessPNG_Compressed, + }, + }, + # animated PNG (ref https://wiki.mozilla.org/APNG_Specification) + acTL => { + Name => 'AnimationControl', + SubDirectory => { + TagTable => 'Image::ExifTool::PNG::AnimationControl', + }, + }, + # eXIf (ref 6) + $stdCase{exif} => { + Name => $stdCase{exif}, + Notes => 'this is where ExifTool will create new EXIF', + SubDirectory => { + TagTable => 'Image::ExifTool::Exif::Main', + DirName => 'EXIF', # (to write as a block) + ProcessProc => \&ProcessPNG_eXIf, + }, + }, + # zXIf + $stdCase{zxif} => { + Name => $stdCase{zxif}, + Notes => 'a once-proposed chunk for compressed EXIF', + NonStandard => 'EXIF', + SubDirectory => { + TagTable => 'Image::ExifTool::Exif::Main', + DirName => 'EXIF', # (to write as a block) + ProcessProc => \&ProcessPNG_eXIf, + }, + }, + # fcTL - animation frame control for each frame + # fdAT - animation data for each frame +); + +# PNG IHDR chunk +%Image::ExifTool::PNG::ImageHeader = ( + PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData, + GROUPS => { 2 => 'Image' }, + 0 => { + Name => 'ImageWidth', + Format => 'int32u', + }, + 4 => { + Name => 'ImageHeight', + Format => 'int32u', + }, + 8 => 'BitDepth', + 9 => { + Name => 'ColorType', + RawConv => '$Image::ExifTool::PNG::colorType = $val', + PrintConv => { + 0 => 'Grayscale', + 2 => 'RGB', + 3 => 'Palette', + 4 => 'Grayscale with Alpha', + 6 => 'RGB with Alpha', + }, + }, + 10 => { + Name => 'Compression', + PrintConv => { 0 => 'Deflate/Inflate' }, + }, + 11 => { + Name => 'Filter', + PrintConv => { 0 => 'Adaptive' }, + }, + 12 => { + Name => 'Interlace', + PrintConv => { 0 => 'Noninterlaced', 1 => 'Adam7 Interlace' }, + }, +); + +# PNG cHRM chunk +%Image::ExifTool::PNG::PrimaryChromaticities = ( + PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData, + GROUPS => { 2 => 'Image' }, + FORMAT => 'int32u', + 0 => { Name => 'WhitePointX', ValueConv => '$val / 100000' }, + 1 => { Name => 'WhitePointY', ValueConv => '$val / 100000' }, + 2 => { Name => 'RedX', ValueConv => '$val / 100000' }, + 3 => { Name => 'RedY', ValueConv => '$val / 100000' }, + 4 => { Name => 'GreenX', ValueConv => '$val / 100000' }, + 5 => { Name => 'GreenY', ValueConv => '$val / 100000' }, + 6 => { Name => 'BlueX', ValueConv => '$val / 100000' }, + 7 => { Name => 'BlueY', ValueConv => '$val / 100000' }, +); + +# PNG pHYs chunk +%Image::ExifTool::PNG::PhysicalPixel = ( + PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData, + WRITE_PROC => \&Image::ExifTool::WriteBinaryData, + WRITABLE => 1, + GROUPS => { 1 => 'PNG-pHYs', 2 => 'Image' }, + WRITE_GROUP => 'PNG-pHYs', + NOTES => q{ + These tags are found in the PNG pHYs chunk and belong to the PNG-pHYs family + 1 group. They are all created together with default values if necessary + when any of these tags is written, and may only be deleted as a group. + }, + 0 => { + Name => 'PixelsPerUnitX', + Format => 'int32u', + }, + 4 => { + Name => 'PixelsPerUnitY', + Format => 'int32u', + }, + 8 => { + Name => 'PixelUnits', + PrintConv => { 0 => 'Unknown', 1 => 'meters' }, + }, +); + +# PNG sCAL chunk +%Image::ExifTool::PNG::SubjectScale = ( + PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData, + GROUPS => { 2 => 'Image' }, + 0 => { + Name => 'SubjectUnits', + PrintConv => { 1 => 'meters', 2 => 'radians' }, + }, + 1 => { + Name => 'SubjectPixelWidth', + Format => 'var_string', + }, + 2 => { + Name => 'SubjectPixelHeight', + Format => 'var_string', + }, +); + +# PNG vpAg chunk +%Image::ExifTool::PNG::VirtualPage = ( + PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData, + GROUPS => { 2 => 'Image' }, + FORMAT => 'int32u', + 0 => 'VirtualImageWidth', + 1 => 'VirtualImageHeight', + 2 => { + Name => 'VirtualPageUnits', + Format => 'int8u', + # what is the conversion for this? + }, +); + +# PNG sTER chunk +%Image::ExifTool::PNG::StereoImage = ( + PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData, + GROUPS => { 2 => 'Image' }, + 0 => { + Name => 'StereoMode', + PrintConv => { + 0 => 'Cross-fuse Layout', + 1 => 'Diverging-fuse Layout', + }, + }, +); + +my %unreg = ( Notes => 'unregistered' ); + +# Tags for PNG tEXt zTXt and iTXt chunks +# (NOTE: ValueConv is set dynamically, so don't set it here!) +%Image::ExifTool::PNG::TextualData = ( + PROCESS_PROC => \&ProcessPNG_tEXt, + WRITE_PROC => \&Image::ExifTool::DummyWriteProc, + WRITABLE => 'string', + PREFERRED => 1, # always add these tags when writing + GROUPS => { 2 => 'Image' }, + LANG_INFO => \&GetLangInfo, + NOTES => q{ + The PNG TextualData format allows arbitrary tag names to be used. The tags + listed below are the only ones that can be written (unless new user-defined + tags are added via the configuration file), however ExifTool will extract + any other TextualData tags that are found. All TextualData tags (including + tags not listed below) are removed when deleting all PNG tags. + + These tags may be stored as tEXt, zTXt or iTXt chunks in the PNG image. By + default ExifTool writes new string-value tags as as uncompressed tEXt, or + compressed zTXt if the Compress (-z) option is used and Compress::Zlib is + available. Alternate language tags and values containing special characters + (unless the Latin character set is used) are written as iTXt, and compressed + if the Compress option is used and Compress::Zlib is available. Raw profile + information is always created as compressed zTXt if Compress::Zlib is + available, or tEXt otherwise. Standard XMP is written as uncompressed iTXt. + + Alternate languages are accessed by suffixing the tag name with a '-', + followed by an RFC 3066 language code (eg. "PNG:Comment-fr", or + "Title-en-US"). See L<http://www.ietf.org/rfc/rfc3066.txt> for the RFC 3066 + specification. + + Some of the tags below are not registered as part of the PNG specification, + but are included here because they are generated by other software such as + ImageMagick. + }, + Title => { }, + Author => { Groups => { 2 => 'Author' } }, + Description => { }, + Copyright => { Groups => { 2 => 'Author' } }, + 'Creation Time' => { + Name => 'CreationTime', + Groups => { 2 => 'Time' }, + Shift => 'Time', + Notes => 'stored in RFC-1123 format and converted to/from EXIF format by ExifTool', + RawConv => \&ConvertPNGDate, + ValueConvInv => \&InversePNGDate, + PrintConv => '$self->ConvertDateTime($val)', + PrintConvInv => '$self->InverseDateTime($val,undef,1)', + }, + Software => { }, + Disclaimer => { }, + # change name to differentiate from ExifTool Warning + Warning => { Name => 'PNGWarning', }, + Source => { }, + Comment => { }, + Collection => { }, # (PNG extensions, 2004) +# +# The following tags are not part of the original PNG specification, +# but are written by ImageMagick and other software +# + Artist => { %unreg, Groups => { 2 => 'Author' } }, + Document => { %unreg }, + Label => { %unreg }, + Make => { %unreg, Groups => { 2 => 'Camera' } }, + Model => { %unreg, Groups => { 2 => 'Camera' } }, + 'create-date'=> { + Name => 'CreateDate', + Groups => { 2 => 'Time' }, + Shift => 'Time', + %unreg, + ValueConv => 'require Image::ExifTool::XMP; Image::ExifTool::XMP::ConvertXMPDate($val)', + ValueConvInv => 'require Image::ExifTool::XMP; Image::ExifTool::XMP::FormatXMPDate($val)', + PrintConv => '$self->ConvertDateTime($val)', + PrintConvInv => '$self->InverseDateTime($val,undef,1)', + }, + 'modify-date'=> { + Name => 'ModDate', # (to distinguish from tIME chunk "ModifyDate") + Groups => { 2 => 'Time' }, + Shift => 'Time', + %unreg, + ValueConv => 'require Image::ExifTool::XMP; Image::ExifTool::XMP::ConvertXMPDate($val)', + ValueConvInv => 'require Image::ExifTool::XMP; Image::ExifTool::XMP::FormatXMPDate($val)', + PrintConv => '$self->ConvertDateTime($val)', + PrintConvInv => '$self->InverseDateTime($val,undef,1)', + }, + TimeStamp => { %unreg, Groups => { 2 => 'Time' }, Shift => 'Time' }, + URL => { %unreg }, + 'XML:com.adobe.xmp' => { + Name => 'XMP', + Notes => q{ + unregistered, but this is the location according to the June 2002 or later + XMP specification, and is where ExifTool will add a new XMP chunk if the + image didn't already contain XMP + }, + SubDirectory => { + TagTable => 'Image::ExifTool::XMP::Main', + }, + }, + 'Raw profile type APP1' => [ + { + # EXIF table must come first because we key on this in ProcessProfile() + # (No condition because this is just for BuildTagLookup) + Name => 'APP1_Profile', + %unreg, + NonStandard => 'EXIF', + SubDirectory => { + TagTable => 'Image::ExifTool::Exif::Main', + ProcessProc => \&ProcessProfile, + }, + }, + { + Name => 'APP1_Profile', + NonStandard => 'XMP', + SubDirectory => { + TagTable => 'Image::ExifTool::XMP::Main', + ProcessProc => \&ProcessProfile, + }, + }, + ], + 'Raw profile type exif' => { + Name => 'EXIF_Profile', + %unreg, + NonStandard => 'EXIF', + SubDirectory => { + TagTable => 'Image::ExifTool::Exif::Main', + ProcessProc => \&ProcessProfile, + }, + }, + 'Raw profile type icc' => { + Name => 'ICC_Profile', + %unreg, + SubDirectory => { + TagTable => 'Image::ExifTool::ICC_Profile::Main', + ProcessProc => \&ProcessProfile, + }, + }, + 'Raw profile type icm' => { + Name => 'ICC_Profile', + %unreg, + SubDirectory => { + TagTable => 'Image::ExifTool::ICC_Profile::Main', + ProcessProc => \&ProcessProfile, + }, + }, + 'Raw profile type iptc' => { + Name => 'IPTC_Profile', + Notes => q{ + unregistered. May be either IPTC IIM or Photoshop IRB format. This is + where ExifTool will add new IPTC, inside a Photoshop IRB container + }, + SubDirectory => { + TagTable => 'Image::ExifTool::Photoshop::Main', + ProcessProc => \&ProcessProfile, + }, + }, + 'Raw profile type xmp' => { + Name => 'XMP_Profile', + %unreg, + NonStandard => 'XMP', + SubDirectory => { + TagTable => 'Image::ExifTool::XMP::Main', + ProcessProc => \&ProcessProfile, + }, + }, + 'Raw profile type 8bim' => { + Name => 'Photoshop_Profile', + %unreg, + SubDirectory => { + TagTable => 'Image::ExifTool::Photoshop::Main', + ProcessProc => \&ProcessProfile, + }, + }, +); + +# Animation control +%Image::ExifTool::PNG::AnimationControl = ( + PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData, + GROUPS => { 2 => 'Image' }, + FORMAT => 'int32u', + NOTES => q{ + Tags found in the Animation Conrol chunk. See + L<https://wiki.mozilla.org/APNG_Specification> for details. + }, + 0 => { + Name => 'AnimationFrames', + RawConv => '$self->OverrideFileType("APNG", undef, "PNG"); $val', + }, + 1 => { + Name => 'AnimationPlays', + PrintConv => '$val || "inf"', + }, +); + +#------------------------------------------------------------------------------ +# AutoLoad our writer routines when necessary +# +sub AUTOLOAD +{ + return Image::ExifTool::DoAutoLoad($AUTOLOAD, @_); +} + +#------------------------------------------------------------------------------ +# Get standard case for language code (this routine copied from XMP.pm) +# Inputs: 0) Language code +# Returns: Language code in standard case +sub StandardLangCase($) +{ + my $lang = shift; + # make 2nd subtag uppercase only if it is 2 letters + return lc($1) . uc($2) . lc($3) if $lang =~ /^([a-z]{2,3}|[xi])(-[a-z]{2})\b(.*)/i; + return lc($lang); +} + +#------------------------------------------------------------------------------ +# Convert date from PNG to EXIF format +# Inputs: 0) Date/time in PNG format, 1) ExifTool ref +# Returns: EXIF formatted date/time string +my %monthNum = ( + Jan=>1, Feb=>2, Mar=>3, Apr=>4, May=>5, Jun=>6, + Jul=>7, Aug=>8, Sep=>9, Oct=>10,Nov=>11,Dec=>12 +); +my %tzConv = ( + UT => '+00:00', GMT => '+00:00', UTC => '+00:00', # (UTC not in spec -- PH addition) + EST => '-05:00', EDT => '-04:00', + CST => '-06:00', CDT => '-05:00', + MST => '-07:00', MDT => '-06:00', + PST => '-08:00', PDT => '-07:00', + A => '-01:00', N => '+01:00', + B => '-02:00', O => '+02:00', + C => '-03:00', P => '+03:00', + D => '-04:00', Q => '+04:00', + E => '-05:00', R => '+05:00', + F => '-06:00', S => '+06:00', + G => '-07:00', T => '+07:00', + H => '-08:00', U => '+08:00', + I => '-09:00', V => '+09:00', + K => '-10:00', W => '+10:00', + L => '-11:00', X => '+11:00', + M => '-12:00', Y => '+12:00', + Z => '+00:00', +); +sub ConvertPNGDate($$) +{ + my ($val, $et) = @_; + # standard format is like "Mon, 1 Jan 2018 12:10:22 EST" (RFC-1123 section 5.2.14) + while ($val =~ /(\d+)\s*(Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec)\s*(\d+)\s+(\d+):(\d{2})(:\d{2})?\s*(\S*)/i) { + my ($day,$mon,$yr,$hr,$min,$sec,$tz) = ($1,$2,$3,$4,$5,$6,$7); + $yr += $yr > 70 ? 1900 : 2000 if $yr < 100; # boost year to 4 digits if necessary + $mon = $monthNum{ucfirst lc $mon} or return $val; + if (not $tz) { + $tz = ''; + } elsif ($tzConv{uc $tz}) { + $tz = $tzConv{uc $tz}; + } elsif ($tz =~ /^([-+]\d+):?(\d{2})/) { + $tz = $1 . ':' . $2; + } else { + last; # (non-standard date) + } + return sprintf("%.4d:%.2d:%.2d %.2d:%.2d%s%s",$yr,$mon,$day,$hr,$min,$sec||':00',$tz); + } + if (($et->Options('StrictDate') and not $$et{TAGS_FROM_FILE}) or $et->Options('Validate')) { + $et->Warn('Non standard PNG date/time format', 1); + } + return $val; +} + +#------------------------------------------------------------------------------ +# Convert EXIF date/time to PNG format +# Inputs: 0) Date/time in EXIF format, 1) ExifTool ref +# Returns: PNG formatted date/time string +sub InversePNGDate($$) +{ + my ($val, $et) = @_; + if ($et->Options('StrictDate')) { + my $err; + if ($val =~ /^(\d{4}):(\d{2}):(\d{2}) (\d{2})(:\d{2})(:\d{2})?(?:\.\d*)?\s*(\S*)/) { + my ($yr,$mon,$day,$hr,$min,$sec,$tz) = ($1,$2,$3,$4,$5,$6,$7); + $sec or $sec = ''; + my %monName = map { $monthNum{$_} => $_ } keys %monthNum; + $mon = $monName{$mon + 0} or $err = 1; + if (length $tz) { + $tz =~ /^(Z|[-+]\d{2}:?\d{2})/ or $err = 1; + $tz =~ tr/://d; + $tz = ' ' . $tz; + } + $val = "$day $mon $yr $hr$min$sec$tz" unless $err; + } + if ($err) { + warn "Invalid date/time (use YYYY:mm:dd HH:MM:SS[.ss][+/-HH:MM|Z])\n"; + undef $val; + } + } + return $val; +} + +#------------------------------------------------------------------------------ +# Get localized version of tagInfo hash +# Inputs: 0) tagInfo hash ref, 1) language code (eg. "x-default") +# Returns: new tagInfo hash ref, or undef if invalid +sub GetLangInfo($$) +{ + my ($tagInfo, $lang) = @_; + $lang =~ tr/_/-/; # RFC 3066 specifies '-' as a separator + # no alternate languages for XMP or raw profile directories + return undef if $$tagInfo{SubDirectory}; + # language code must normalized for use in tag ID + return Image::ExifTool::GetLangInfo($tagInfo, StandardLangCase($lang)); +} + +#------------------------------------------------------------------------------ +# Found a PNG tag -- extract info from subdirectory or decompress data if necessary +# Inputs: 0) ExifTool object reference, 1) Pointer to tag table, +# 2) Tag ID, 3) Tag value, 4) [optional] compressed data flag: +# 0=not compressed, 1=unknown compression, 2-N=compression with type N-2 +# 5) optional output buffer ref, 6) character encoding (tEXt/zTXt/iTXt only) +# 6) optional language code +# Returns: 1 on success +sub FoundPNG($$$$;$$$$) +{ + my ($et, $tagTablePtr, $tag, $val, $compressed, $outBuff, $enc, $lang) = @_; + return 0 unless defined $val; + my $verbose = $et->Options('Verbose'); + my $id = $tag; # generate tag ID which includes language code + if ($lang) { + # case of language code must be normalized since they are case insensitive + $lang = StandardLangCase($lang); + $id .= '-' . $lang; + } + my $tagInfo = $et->GetTagInfo($tagTablePtr, $id) || + # (some software forgets to capitalize first letter) + $et->GetTagInfo($tagTablePtr, ucfirst($id)); + # create alternate language tag if necessary + if (not $tagInfo and $lang) { + $tagInfo = $et->GetTagInfo($tagTablePtr, $tag) || + $et->GetTagInfo($tagTablePtr, ucfirst($tag)); + $tagInfo = GetLangInfo($tagInfo, $lang) if $tagInfo; + } +# +# uncompress data if necessary +# + my ($wasCompressed, $deflateErr); + if ($compressed and $compressed > 1) { + if ($compressed == 2) { # Inflate/Deflate compression + if (eval { require Compress::Zlib }) { + my ($v2, $stat); + my $inflate = Compress::Zlib::inflateInit(); + $inflate and ($v2, $stat) = $inflate->inflate($val); + if ($inflate and $stat == Compress::Zlib::Z_STREAM_END()) { + $val = $v2; + $compressed = 0; + $wasCompressed = 1; + } else { + $deflateErr = "Error inflating $tag"; + } + } elsif (not $noCompressLib) { + $deflateErr = "Install Compress::Zlib to read compressed information"; + } else { + $deflateErr = ''; # flag deflate error but no warning + } + } else { + $compressed -= 2; + $deflateErr = "Unknown compression method $compressed for $tag"; + } + if ($compressed and $verbose and $tagInfo and $$tagInfo{SubDirectory}) { + $et->VerboseDir("Unable to decompress $$tagInfo{Name}", 0, length($val)); + } + # issue warning if relevant + if ($deflateErr and not $outBuff) { + $et->Warn($deflateErr); + $noCompressLib = 1 if $deflateErr =~ /^Install/; + } + } + # translate character encoding if necessary (tEXt/zTXt/iTXt string values only) + if ($enc and not $compressed and not ($tagInfo and $$tagInfo{SubDirectory})) { + $val = $et->Decode($val, $enc); + } +# +# extract information from subdirectory if available +# + if ($tagInfo) { + my $tagName = $$tagInfo{Name}; + my $processed; + if ($$tagInfo{SubDirectory}) { + if ($$et{OPTIONS}{Validate} and $$tagInfo{NonStandard}) { + $et->Warn("Non-standard $$tagInfo{NonStandard} in PNG $tag chunk", 1); + } + my $subdir = $$tagInfo{SubDirectory}; + my $dirName = $$subdir{DirName} || $tagName; + if (not $compressed) { + my $len = length $val; + if ($verbose and $$et{INDENT} ne ' ') { + if ($wasCompressed and $verbose > 2) { + my $name = $tagName; + $wasCompressed and $name = "Decompressed $name"; + $et->VerboseDir($name, 0, $len); + $et->VerboseDump(\$val); + } + # don't indent next directory (since it is really the same data) + $$et{INDENT} =~ s/..$//; + } + my $processProc = $$subdir{ProcessProc}; + # nothing more to do if writing and subdirectory is not writable + my $subTable = GetTagTable($$subdir{TagTable}); + return 1 if $outBuff and not $$subTable{WRITE_PROC}; + my $dirName = $$subdir{DirName} || $tagName; + my %subdirInfo = ( + DataPt => \$val, + DirStart => 0, + DataLen => $len, + DirLen => $len, + DirName => $dirName, + TagInfo => $tagInfo, + ReadOnly => 1, # (used only by WriteXMP) + OutBuff => $outBuff, + ); + # no need to re-decompress if already done + undef $processProc if $wasCompressed and $processProc and $processProc eq \&ProcessPNG_Compressed; + # rewrite this directory if necessary (but always process TextualData normally) + if ($outBuff and not $processProc and $subTable ne \%Image::ExifTool::PNG::TextualData) { + return 1 unless $$et{EDIT_DIRS}{$dirName}; + $$outBuff = $et->WriteDirectory(\%subdirInfo, $subTable); + if ($tagName eq 'XMP' and $$outBuff) { + if ($$et{FoundIDAT} and $$et{DEL_GROUP}{XMP}) { + $et->VPrint(0,' Deleting XMP'); + $$outBuff = ''; + } else { + # make sure the XMP is marked as read-only + Image::ExifTool::XMP::ValidateXMP($outBuff,'r'); + } + } + DoneDir($et, $dirName, $outBuff, $$tagInfo{NonStandard}); + } else { + # issue warning for standard XMP after IDAT (PNGEarlyXMP option) + if ($tagName eq 'XMP' and not $$tagInfo{NonStandard} and + $$et{FoundIDAT} and $$et{FoundIDAT} == 2) + { + $et->Warn('XMP found after PNG IDAT'); + $$et{FoundIDAT} = 1; + } + $processed = $et->ProcessDirectory(\%subdirInfo, $subTable, $processProc); + } + $compressed = 1; # pretend this is compressed since it is binary data + } elsif ($outBuff) { + if ($$et{DEL_GROUP}{$dirName} or ($dirName eq 'EXIF' and $$et{DEL_GROUP}{IFD0})) { + $$outBuff = ''; + ++$$et{CHANGED}; + $et->VPrint(0, " Deleting $tag chunk"); + } else { + if ($$et{EDIT_DIRS}{$dirName} or ($dirName eq 'EXIF' and $$et{EDIT_DIRS}{IFD0})) { + $et->Warn("Can't write $dirName. Requires Compress::Zlib"); + } + # pretend we did this directory so we don't try to recreate it + DoneDir($et, $dirName, $outBuff, $$tagInfo{NonStandard}); + } + } + } + if ($outBuff) { + my $writable = $$tagInfo{Writable}; + my $isOverwriting; + if ($writable or ($$tagTablePtr{WRITABLE} and + not defined $writable and not $$tagInfo{SubDirectory})) + { + # write new value for this tag if necessary + my $newVal; + if ($$et{DEL_GROUP}{PNG} or $$et{PNGDoneTag}{$tag} or + $$et{PNGDoneTag}{ucfirst $tag}) + { + # remove this tag now, but keep in ADD_PNG list to add back later + $isOverwriting = 1; + } else { + # remove this from the list of PNG tags to add + delete $$et{ADD_PNG}{$id}; + # (also handle case of tEXt tags written with lowercase first letter) + delete $$et{ADD_PNG}{ucfirst($id)}; + my $nvHash = $et->GetNewValueHash($tagInfo); + $isOverwriting = $et->IsOverwriting($nvHash); + if (defined $deflateErr) { + $newVal = $et->GetNewValue($nvHash); + # can only write tag now if always overwriting + if ($isOverwriting > 0) { + $val = '<deflate error>'; + } elsif ($isOverwriting) { + $isOverwriting = 0; # can't overwrite + $et->Warn($deflateErr) if $deflateErr; + } + } else { + if ($isOverwriting < 0) { + $isOverwriting = $et->IsOverwriting($nvHash, $val); + } + # (must get new value after IsOverwriting() in case it was shifted) + $newVal = $et->GetNewValue($nvHash); + } + } + if ($isOverwriting) { + $$outBuff = (defined $newVal) ? $newVal : ''; + ++$$et{CHANGED}; + $et->VerboseValue("- PNG:$tagName", $val); + $et->VerboseValue("+ PNG:$tagName", $newVal) if defined $newVal; + } + } + if (defined $$outBuff and length $$outBuff) { + if ($enc) { # must be tEXt/zTXt/iTXt if $enc is set + $$outBuff = BuildTextChunk($et, $tag, $tagInfo, $$outBuff, $lang); + } elsif ($wasCompressed) { + # re-compress the output data + my $len = length $$outBuff; + my $deflate = Compress::Zlib::deflateInit(); + if ($deflate) { + $$outBuff = $deflate->deflate($$outBuff); + $$outBuff .= $deflate->flush() if defined $$outBuff; + } else { + undef $$outBuff; + } + if (not $$outBuff) { + $et->Warn("PNG:$tagName not written (compress error)"); + } elsif (lc $tag eq 'zxif') { + $$outBuff = "\0" . pack('N',$len) . $$outBuff; # add zXIf header + } + } + } + return 1; + } + return 1 if $processed; + } elsif ($outBuff) { + if ($$et{DEL_GROUP}{PNG} and $tagTablePtr eq \%Image::ExifTool::PNG::TextualData) { + # delete all TextualData tags if deleting the PNG group + $$outBuff = ''; + ++$$et{CHANGED}; + $et->VerboseValue("- PNG:$tag", $val); + } + return 1; + } else { + my $name; + ($name = $tag) =~ s/\s+(.)/\u$1/g; # remove white space from tag name + $tagInfo = { Name => $name }; + $$tagInfo{LangCode} = $lang if $lang; + # make unknown profiles binary data type + $$tagInfo{Binary} = 1 if $tag =~ /^Raw profile type /; + $verbose and $et->VPrint(0, " | [adding $tag]\n"); + AddTagToTable($tagTablePtr, $tag, $tagInfo); + } +# +# store this tag information +# + if ($verbose) { + # temporarily remove subdirectory so it isn't printed in verbose information + # since we aren't decoding it anyway; + my $subdir = $$tagInfo{SubDirectory}; + delete $$tagInfo{SubDirectory}; + $et->VerboseInfo($tag, $tagInfo, + Table => $tagTablePtr, + DataPt => \$val, + ); + $$tagInfo{SubDirectory} = $subdir if $subdir; + } + # set the RawConv dynamically depending on whether this is binary or not + my $delRawConv; + if ($compressed and not defined $$tagInfo{ValueConv}) { + $$tagInfo{RawConv} = '\$val'; + $delRawConv = 1; + } + $et->FoundTag($tagInfo, $val); + delete $$tagInfo{RawConv} if $delRawConv; + return 1; +} + +#------------------------------------------------------------------------------ +# Process encoded PNG profile information +# Inputs: 0) ExifTool object reference, 1) DirInfo reference, 2) Pointer to tag table +# Returns: 1 on success +sub ProcessProfile($$$) +{ + my ($et, $dirInfo, $tagTablePtr) = @_; + my $dataPt = $$dirInfo{DataPt}; + my $tagInfo = $$dirInfo{TagInfo}; + my $outBuff = $$dirInfo{OutBuff}; + my $tagName = $$tagInfo{Name}; + + # ImageMagick 5.3.6 writes profiles with the following headers: + # "\nICC Profile\n", "\nIPTC profile\n", "\n\xaa\x01{generic prof\n" + # and "\ngeneric profile\n" + return 0 unless $$dataPt =~ /^\n(.*?)\n\s*(\d+)\n(.*)/s; + my ($profileType, $len) = ($1, $2); + # data is encoded in hex, so change back to binary + my $buff = pack('H*', join('',split(' ',$3))); + my $actualLen = length $buff; + if ($len ne $actualLen) { + $et->Warn("$tagName is wrong size (should be $len bytes but is $actualLen)"); + $len = $actualLen; + } + my $verbose = $et->Options('Verbose'); + if ($verbose) { + if ($verbose > 2) { + $et->VerboseDir("Decoded $tagName", 0, $len); + $et->VerboseDump(\$buff); + } + # don't indent next directory (since it is really the same data) + $$et{INDENT} =~ s/..$//; + } + my %dirInfo = ( + Parent => 'PNG', + DataPt => \$buff, + DataLen => $len, + DirStart => 0, + DirLen => $len, + Base => 0, + OutFile => $outBuff, + ); + $$et{PROCESSED} = { }; # reset processed directory offsets + my $processed = 0; + my $oldChanged = $$et{CHANGED}; + my $exifTable = GetTagTable('Image::ExifTool::Exif::Main'); + my $editDirs = $$et{EDIT_DIRS}; + + if ($tagTablePtr ne $exifTable) { + # this is unfortunate, but the "IPTC" profile may be stored as either + # IPTC IIM or a Photoshop IRB resource, so we must test for this + if ($tagName eq 'IPTC_Profile' and $buff =~ /^\x1c/) { + $tagTablePtr = GetTagTable('Image::ExifTool::IPTC::Main'); + } + # process non-EXIF and non-APP1 profile as-is + if ($outBuff) { + # no need to rewrite this if not editing tags in this directory + my $dir = $tagName; + $dir =~ s/_Profile// unless $dir =~ /^ICC/; + return 1 unless $$editDirs{$dir}; + $$outBuff = $et->WriteDirectory(\%dirInfo, $tagTablePtr); + DoneDir($et, $dir, $outBuff, $$tagInfo{NonStandard}); + } else { + $processed = $et->ProcessDirectory(\%dirInfo, $tagTablePtr); + } + } elsif ($buff =~ /^$Image::ExifTool::exifAPP1hdr/) { + # APP1 EXIF information + return 1 if $outBuff and not $$editDirs{IFD0}; + my $hdrLen = length($Image::ExifTool::exifAPP1hdr); + $dirInfo{DirStart} += $hdrLen; + $dirInfo{DirLen} -= $hdrLen; + if ($outBuff) { + # delete non-standard EXIF if recreating from scratch + if ($$et{DEL_GROUP}{EXIF} or $$et{DEL_GROUP}{IFD0}) { + $$outBuff = ''; + $et->VPrint(0, ' Deleting non-standard APP1 EXIF information'); + return 1; + } + $$outBuff = $et->WriteDirectory(\%dirInfo, $tagTablePtr, + \&Image::ExifTool::WriteTIFF); + $$outBuff = $Image::ExifTool::exifAPP1hdr . $$outBuff if $$outBuff; + DoneDir($et, 'IFD0', $outBuff); + } else { + $processed = $et->ProcessTIFF(\%dirInfo); + } + } elsif ($buff =~ /^$Image::ExifTool::xmpAPP1hdr/) { + # APP1 XMP information + my $hdrLen = length($Image::ExifTool::xmpAPP1hdr); + my $tagTablePtr = GetTagTable('Image::ExifTool::XMP::Main'); + $dirInfo{DirStart} += $hdrLen; + $dirInfo{DirLen} -= $hdrLen; + if ($outBuff) { + return 1 unless $$editDirs{XMP}; + $$outBuff = $et->WriteDirectory(\%dirInfo, $tagTablePtr); + $$outBuff and $$outBuff = $Image::ExifTool::xmpAPP1hdr . $$outBuff; + DoneDir($et, 'XMP', $outBuff, 1); + } else { + $processed = $et->ProcessDirectory(\%dirInfo, $tagTablePtr); + } + } elsif ($buff =~ /^(MM\0\x2a|II\x2a\0)/) { + # TIFF information + return 1 if $outBuff and not $$editDirs{IFD0}; + if ($outBuff) { + # delete non-standard EXIF if recreating from scratch + if ($$et{DEL_GROUP}{EXIF} or $$et{DEL_GROUP}{IFD0}) { + $$outBuff = ''; + $et->VPrint(0, ' Deleting non-standard EXIF/TIFF information'); + return 1; + } + $$outBuff = $et->WriteDirectory(\%dirInfo, $tagTablePtr, + \&Image::ExifTool::WriteTIFF); + DoneDir($et, 'IFD0', $outBuff); + } else { + $processed = $et->ProcessTIFF(\%dirInfo); + } + } else { + my $profName = $profileType; + $profName =~ tr/\x00-\x1f\x7f-\xff/./; + $et->Warn("Unknown raw profile '${profName}'"); + } + if ($outBuff and defined $$outBuff and length $$outBuff) { + if ($$et{CHANGED} != $oldChanged) { + my $hdr = sprintf("\n%s\n%8d\n", $profileType, length($$outBuff)); + # hex encode the data + $$outBuff = $hdr . HexEncode($outBuff); + } else { + undef $$outBuff; + } + } + return $processed; +} + +#------------------------------------------------------------------------------ +# Process PNG compressed zTXt or iCCP chunk +# Inputs: 0) ExifTool object reference, 1) DirInfo reference, 2) Pointer to tag table +# Returns: 1 on success +# Notes: writes new chunk data to ${$$dirInfo{OutBuff}} if writing tag +sub ProcessPNG_Compressed($$$) +{ + my ($et, $dirInfo, $tagTablePtr) = @_; + my ($tag, $val) = split /\0/, ${$$dirInfo{DataPt}}, 2; + return 0 unless defined $val; + # set compressed to 2 + compression method to decompress the data + my $compressed = 2 + unpack('C', $val); + my $hdr = $tag . "\0" . substr($val, 0, 1); + $val = substr($val, 1); # remove compression method byte + my $success; + my $outBuff = $$dirInfo{OutBuff}; + my $tagInfo = $$dirInfo{TagInfo}; + # use the PNG chunk tag instead of the embedded tag name for iCCP chunks + if ($tagInfo and $$tagInfo{Name} eq 'ICC_Profile') { + $et->VerboseDir('iCCP'); + $tagTablePtr = \%Image::ExifTool::PNG::Main; + if (length($tag) and not $outBuff) { + FoundPNG($et, $tagTablePtr, 'iCCP-name', $tag); + } + $success = FoundPNG($et, $tagTablePtr, 'iCCP', $val, $compressed, $outBuff); + $$outBuff = $hdr . $$outBuff if $outBuff and $$outBuff; + } else { + $success = FoundPNG($et, $tagTablePtr, $tag, $val, $compressed, $outBuff, 'Latin'); + } + return $success; +} + +#------------------------------------------------------------------------------ +# Process PNG tEXt chunk +# Inputs: 0) ExifTool object reference, 1) DirInfo reference, 2) Pointer to tag table +# Returns: 1 on success +# Notes: writes new chunk data to ${$$dirInfo{OutBuff}} if writing tag +sub ProcessPNG_tEXt($$$) +{ + my ($et, $dirInfo, $tagTablePtr) = @_; + my ($tag, $val) = split /\0/, ${$$dirInfo{DataPt}}, 2; + my $outBuff = $$dirInfo{OutBuff}; + return FoundPNG($et, $tagTablePtr, $tag, $val, undef, $outBuff, 'Latin'); +} + +#------------------------------------------------------------------------------ +# Process PNG iTXt chunk +# Inputs: 0) ExifTool object reference, 1) DirInfo reference, 2) Pointer to tag table +# Returns: 1 on success +# Notes: writes new chunk data to ${$$dirInfo{OutBuff}} if writing tag +sub ProcessPNG_iTXt($$$) +{ + my ($et, $dirInfo, $tagTablePtr) = @_; + my ($tag, $dat) = split /\0/, ${$$dirInfo{DataPt}}, 2; + return 0 unless defined $dat and length($dat) >= 4; + my ($compressed, $meth) = unpack('CC', $dat); + my ($lang, $trans, $val) = split /\0/, substr($dat, 2), 3; + # set compressed flag so we will decompress it in FoundPNG() + $compressed and $compressed = 2 + $meth; + my $outBuff = $$dirInfo{OutBuff}; + return FoundPNG($et, $tagTablePtr, $tag, $val, $compressed, $outBuff, 'UTF8', $lang); +} + +#------------------------------------------------------------------------------ +# Process PNG eXIf/zXIf chunk +# Inputs: 0) ExifTool object reference, 1) DirInfo reference, 2) Pointer to tag table +# Returns: 1 on success +# Notes: writes new chunk data to ${$$dirInfo{OutBuff}} if writing tag +sub ProcessPNG_eXIf($$$) +{ + my ($et, $dirInfo, $tagTablePtr) = @_; + my $outBuff = $$dirInfo{OutBuff}; + my $dataPt = $$dirInfo{DataPt}; + my $tagInfo = $$dirInfo{TagInfo}; + my $tag = $$tagInfo{TagID}; + my $del = $outBuff && ($$et{DEL_GROUP}{EXIF} or $$et{DEL_GROUP}{IFD0}); + my $type; + + if ($$dataPt =~ /^Exif\0\0/) { + $et->Warn('Improper "Exif00" header in EXIF chunk'); + $$dataPt = substr($$dataPt, 6); + $$dirInfo{DataLen} = length $$dataPt; + $$dirInfo{DirLen} -= 6 if $$dirInfo{DirLen}; + } + if ($$dataPt =~ /^(\0|II|MM)/) { + $type = $1; + } elsif ($del) { + $et->VPrint(0, " Deleting invalid $tag chunk"); + $$outBuff = ''; + ++$$et{CHANGED}; + return 1; + } else { + $et->Warn("Invalid $tag chunk"); + return 0; + } + if ($type eq "\0") { # is this compressed EXIF? + my $buf = substr($$dataPt, 5); + # go around again to uncompress the data + $tagTablePtr = GetTagTable('Image::ExifTool::PNG::Main'); + return FoundPNG($et, $tagTablePtr, $$tagInfo{TagID}, \$buf, 2, $outBuff); + } elsif (not $outBuff) { + return $et->ProcessTIFF($dirInfo); + # (zxIf was not adopted) + #} elsif ($del and ($et->Options('Compress') xor lc($tag) eq 'zxif')) { + } elsif ($del and lc($tag) eq 'zxif') { + $et->VPrint(0, " Deleting $tag chunk"); + $$outBuff = ''; + ++$$et{CHANGED}; + } elsif ($$et{EDIT_DIRS}{IFD0}) { + $$outBuff = $et->WriteDirectory($dirInfo, $tagTablePtr, + \&Image::ExifTool::WriteTIFF); + DoneDir($et, 'IFD0', $outBuff, $$tagInfo{NonStandard}); + } + return 1; +} + +#------------------------------------------------------------------------------ +# Extract meta information from a PNG image +# Inputs: 0) ExifTool object reference, 1) dirInfo reference +# Returns: 1 on success, 0 if this wasn't a valid PNG image, or -1 on write error +sub ProcessPNG($$) +{ + my ($et, $dirInfo) = @_; + my $outfile = $$dirInfo{OutFile}; + my $raf = $$dirInfo{RAF}; + my $datChunk = ''; + my $datCount = 0; + my $datBytes = 0; + my ($sig, $err); + + # check to be sure this is a valid PNG/MNG/JNG image + return 0 unless $raf->Read($sig,8) == 8 and $pngLookup{$sig}; + + $$raf{NoBuffer} = 1 if $et->Options('FastScan'); # disable buffering in FastScan mode + + my $earlyXMP = $et->Options('PNGEarlyXMP'); + if ($outfile) { + delete $$et{TextChunkType}; + Write($outfile, $sig) or $err = 1 if $outfile; + # can only add tags in Main and TextualData tables + $$et{ADD_PNG} = $et->GetNewTagInfoHash( + \%Image::ExifTool::PNG::Main, + \%Image::ExifTool::PNG::TextualData); + # NOTE: PNGDoneTag and PNGDoneDir are used to keep track of metadata added + # before the PNG IEND chunk is encountered. Currently this is implemented + # only for XMP (written before IDAT with the PNGEarlyXMP option), but + # may be implemented in the future for other types - PH + $$et{PNGDoneTag} = { }; + $$et{PNGDoneDir} = { }; + # initialize with same directories, with PNG tags taking priority + $et->InitWriteDirs(\%pngMap,'PNG'); + # write XMP before IDAT if we would delete it later anyway + $earlyXMP = 1 if $$et{DEL_GROUP}{XMP}; + } + my ($fileType, $hdrChunk, $endChunk) = @{$pngLookup{$sig}}; + $et->SetFileType($fileType); # set the FileType tag + SetByteOrder('MM'); # PNG files are big-endian + my $tagTablePtr = GetTagTable('Image::ExifTool::PNG::Main'); + my $mngTablePtr; + if ($fileType ne 'PNG') { + $mngTablePtr = GetTagTable('Image::ExifTool::MNG::Main'); + } + my $verbose = $et->Options('Verbose'); + my $out = $et->Options('TextOut'); + my ($hbuf, $dbuf, $cbuf, $wasHdr, $wasEnd); + + # process the PNG/MNG/JNG chunks + undef $noCompressLib; + for (;;) { + my $n = $raf->Read($hbuf,8); + if ($wasEnd) { + last unless $n; # stop now if normal end of PNG + $et->WarnOnce("Trailer data after $fileType $endChunk chunk", 1); + last if $n < 8; + $$et{SET_GROUP1} = 'Trailer'; + } elsif ($n != 8) { + $et->Warn("Truncated $fileType image") unless $wasEnd; + last; + } + my ($len, $chunk) = unpack('Na4',$hbuf); + if ($len > 0x7fffffff) { + $et->Warn("Invalid $fileType chunk size") unless $wasEnd; + last; + } + if ($verbose) { + # don't dump image data chunks in verbose mode (only give count instead) + if ($datCount and $chunk ne $datChunk) { + my $s = $datCount > 1 ? 's' : ''; + print $out "$fileType $datChunk ($datCount chunk$s, total $datBytes bytes)\n"; + $datCount = $datBytes = 0; + $datChunk = ''; + } + if ($chunk =~ /^(IDAT|JDAT|JDAA)$/) { + $datChunk = $chunk; + $datCount++; + $datBytes += $len; + } + } + if ($outfile) { + if ($chunk eq $endChunk) { + # add any new chunks immediately before the IEND/MEND chunk + AddChunks($et, $outfile) or $err = 1; + } elsif ($chunk eq 'PLTE' or $chunk eq 'IDAT') { + if ($chunk eq 'IDAT') { + # add XMP before IDAT if specified + AddChunks($et, $outfile, 'XMP') or $err = 1 if $earlyXMP; + # pHYs comes before IDAT + AddChunks($et, $outfile, 'PNG-pHYs') or $err = 1; + } + # iCCP chunk must come before PLTE and IDAT + # (ignore errors -- will add later as text profile if this fails) + Add_iCCP($et, $outfile); + } + } + if ($chunk eq $endChunk) { + # read CRC + unless ($raf->Read($cbuf,4) == 4) { + $et->Warn("Truncated $fileType $endChunk chunk") unless $wasEnd; + last; + } + $verbose and print $out "$fileType $chunk (end of image)\n"; + $wasEnd = 1; + if ($outfile) { + # write the IEND/MEND chunk with CRC + Write($outfile, $hbuf, $cbuf) or $err = 1; + if ($$et{DEL_GROUP}{Trailer}) { + if ($raf->Read($hbuf, 1)) { + $verbose and printf $out " Deleting PNG trailer\n"; + ++$$et{CHANGED}; + } + } else { + # copy over any existing trailer data + my $tot = 0; + for (;;) { + $n = $raf->Read($hbuf, 65536) or last; + $tot += $n; + Write($outfile, $hbuf) or $err = 1; + } + $tot and $verbose and printf $out " Copying PNG trailer ($tot bytes)\n"; + } + last; + } + next; + } + # set FoundIDAT flag: 1=after IDAT, 2=after IDAT and warn about late XMP + $$et{FoundIDAT} = $earlyXMP ? 2 : 1 if $chunk eq 'IDAT'; + # read chunk data and CRC + unless ($raf->Read($dbuf,$len)==$len and $raf->Read($cbuf, 4)==4) { + $et->Warn("Corrupted $fileType image") unless $wasEnd; + last; + } + unless ($wasHdr) { + if ($chunk eq $hdrChunk) { + $wasHdr = 1; + } elsif ($hdrChunk eq 'IHDR' and $chunk eq 'CgBI') { + $et->Warn('Non-standard PNG image (Apple iPhone format)'); + } else { + $et->Warn("$fileType image did not start with $hdrChunk"); + last; + } + } + if ($verbose) { + # check CRC when in verbose mode (since we don't care about speed) + my $crc = CalculateCRC(\$hbuf, undef, 4); + $crc = CalculateCRC(\$dbuf, $crc); + $crc == unpack('N',$cbuf) or $et->Warn("Bad CRC for $chunk chunk") unless $wasEnd; + if ($datChunk) { + Write($outfile, $hbuf, $dbuf, $cbuf) or $err = 1 if $outfile; + next; + } + print $out "$fileType $chunk ($len bytes):\n"; + $et->VerboseDump(\$dbuf, Addr => $raf->Tell() - $len - 4) if $verbose > 2; + } + # translate case of chunk name if necessary + if (not $$tagTablePtr{$chunk}) { + my $stdChunk = $stdCase{lc $chunk}; + if ($stdChunk) { + if ($outfile and ($$et{EDIT_DIRS}{IFD0} or $stdChunk !~ /^[ez]xif$/i)) { + $et->Warn("Changed $chunk chunk to $stdChunk", 1); + ++$$et{CHANGED}; + } else { + $et->Warn("$chunk chunk should be $stdChunk", 1); + } + $chunk = $stdCase{lc $chunk}; + } + } + # only extract information from chunks in our tables + my ($theBuff, $outBuff); + $outBuff = \$theBuff if $outfile; + if ($$tagTablePtr{$chunk}) { + FoundPNG($et, $tagTablePtr, $chunk, $dbuf, undef, $outBuff); + } elsif ($mngTablePtr and $$mngTablePtr{$chunk}) { + FoundPNG($et, $mngTablePtr, $chunk, $dbuf, undef, $outBuff); + } + if ($outfile) { + if (defined $theBuff) { + next unless length $theBuff; # empty if we deleted the information + # change chunk type if necessary + if ($$et{TextChunkType}) { + $chunk = $$et{TextChunkType}; + delete $$et{TextChunkType}; + } + $hbuf = pack('Na4', length($theBuff), $chunk); + $dbuf = $theBuff; + my $crc = CalculateCRC(\$hbuf, undef, 4); + $crc = CalculateCRC(\$dbuf, $crc); + $cbuf = pack('N', $crc); + } + Write($outfile, $hbuf, $dbuf, $cbuf) or $err = 1; + } + } + delete $$et{SET_GROUP1}; + return -1 if $outfile and ($err or not $wasEnd); + return 1; # this was a valid PNG/MNG/JNG image +} + +1; # end + +__END__ + +=head1 NAME + +Image::ExifTool::PNG - Read and write PNG meta information + +=head1 SYNOPSIS + +This module is used by Image::ExifTool + +=head1 DESCRIPTION + +This module contains routines required by Image::ExifTool to read and +write PNG (Portable Network Graphics), MNG (Multi-image Network Graphics) +and JNG (JPEG Network Graphics) images. + +=head1 AUTHOR + +Copyright 2003-2019, Phil Harvey (phil at owl.phy.queensu.ca) + +This library is free software; you can redistribute it and/or modify it +under the same terms as Perl itself. + +=head1 REFERENCES + +=over 4 + +=item L<http://www.libpng.org/pub/png/spec/1.2/> + +=item L<http://www.faqs.org/docs/png/> + +=item L<http://www.libpng.org/pub/mng/> + +=item L<http://www.libpng.org/pub/png/spec/register/> + +=back + +=head1 SEE ALSO + +L<Image::ExifTool::TagNames/PNG Tags>, +L<Image::ExifTool::TagNames/MNG Tags>, +L<Image::ExifTool(3pm)|Image::ExifTool> + +=cut + diff --git a/lib/Image/ExifTool/PPM.pm b/lib/Image/ExifTool/PPM.pm new file mode 100644 index 0000000..c78ece0 --- /dev/null +++ b/lib/Image/ExifTool/PPM.pm @@ -0,0 +1,169 @@ +#------------------------------------------------------------------------------ +# File: PPM.pm +# +# Description: Read and write PPM meta information +# +# Revisions: 09/03/2005 - P. Harvey Created +# +# References: 1) http://netpbm.sourceforge.net/doc/ppm.html +# 2) http://netpbm.sourceforge.net/doc/pgm.html +# 3) http://netpbm.sourceforge.net/doc/pbm.html +#------------------------------------------------------------------------------ + +package Image::ExifTool::PPM; + +use strict; +use vars qw($VERSION); +use Image::ExifTool qw(:DataAccess :Utils); + +$VERSION = '1.09'; + +#------------------------------------------------------------------------------ +# Read or write information in a PPM/PGM/PBM image +# Inputs: 0) ExifTool object reference, 1) Directory information reference +# Returns: 1 on success, 0 if this wasn't a valid PPM file, -1 on write error +sub ProcessPPM($$) +{ + my ($et, $dirInfo) = @_; + my $raf = $$dirInfo{RAF}; + my $outfile = $$dirInfo{OutFile}; + my $verbose = $et->Options('Verbose'); + my $out = $et->Options('TextOut'); + my ($buff, $num, $type, %info); +# +# read as much of the image as necessary to extract the header and comments +# + for (;;) { + if (defined $buff) { + # need to read some more data + my $tmp; + return 0 unless $raf->Read($tmp, 1024); + $buff .= $tmp; + } else { + return 0 unless $raf->Read($buff, 1024); + } + # verify this is a valid PPM file + return 0 unless $buff =~ /^P([1-6])\s+/g; + $num = $1; + # note: may contain comments starting with '#' + if ($buff =~ /\G#/gc) { + # must read more if we are in the middle of a comment + next unless $buff =~ /\G ?(.*\n(#.*\n)*)\s*/g; + $info{Comment} = $1; + next if $buff =~ /\G#/gc; + } else { + delete $info{Comment}; + } + next unless $buff =~ /\G(\S+)\s+(\S+)\s/g; + $info{ImageWidth} = $1; + $info{ImageHeight} = $2; + $type = [qw{PPM PBM PGM}]->[$num % 3]; + last if $type eq 'PBM'; # (no MaxVal for PBM images) + if ($buff =~ /\G\s*#/gc) { + next unless $buff =~ /\G ?(.*\n(#.*\n)*)\s*/g; + $info{Comment} = '' unless exists $info{Comment}; + $info{Comment} .= $1; + next if $buff =~ /\G#/gc; + } + next unless $buff =~ /\G(\S+)\s/g; + $info{MaxVal} = $1; + last; + } + # validate numerical values + foreach (keys %info) { + next if $_ eq 'Comment'; + return 0 unless $info{$_} =~ /^\d+$/; + } + if (defined $info{Comment}) { + $info{Comment} =~ s/^# ?//mg; # remove "# " at the start of each line + $info{Comment} =~ s/\n$//; # remove trailing newline + } + $et->SetFileType($type); + my $len = pos($buff); +# +# rewrite the file if requested +# + if ($outfile) { + my $nvHash; + my $newComment = $et->GetNewValue('Comment', \$nvHash); + my $oldComment = $info{Comment}; + if ($et->IsOverwriting($nvHash, $oldComment)) { + ++$$et{CHANGED}; + $et->VerboseValue('- Comment', $oldComment) if defined $oldComment; + $et->VerboseValue('+ Comment', $newComment) if defined $newComment; + } else { + $newComment = $oldComment; # use existing comment + } + my $hdr = "P$num\n"; + if (defined $newComment) { + $newComment =~ s/\n/\n# /g; + $hdr .= "# $newComment\n"; + } + $hdr .= "$info{ImageWidth} $info{ImageHeight}\n"; + $hdr .= "$info{MaxVal}\n" if $type ne 'PBM'; + # write header and start of image + Write($outfile, $hdr, substr($buff, $len)) or return -1; + # copy over the rest of the image + while ($raf->Read($buff, 0x10000)) { + Write($outfile, $buff) or return -1; + } + return 1; + } +# +# save extracted information +# + if ($verbose > 2) { + print $out "$type header ($len bytes):\n"; + $et->VerboseDump(\$buff, Len => $len); + } + my $tag; + foreach $tag (qw{Comment ImageWidth ImageHeight MaxVal}) { + $et->FoundTag($tag, $info{$tag}) if defined $info{$tag}; + } + return 1; +} + +1; # end + +__END__ + +=head1 NAME + +Image::ExifTool::PPM - Read and write PPM meta information + +=head1 SYNOPSIS + +This module is used by Image::ExifTool + +=head1 DESCRIPTION + +This module contains definitions required by Image::ExifTool to read and +write PPM (Portable Pixel Map), PGM (Portable Gray Map) and PBM (Portable +BitMap) images. + +=head1 AUTHOR + +Copyright 2003-2019, Phil Harvey (phil at owl.phy.queensu.ca) + +This library is free software; you can redistribute it and/or modify it +under the same terms as Perl itself. + +=head1 REFERENCES + +=over 4 + +=item L<http://netpbm.sourceforge.net/doc/ppm.html> + +=item L<http://netpbm.sourceforge.net/doc/pgm.html> + +=item L<http://netpbm.sourceforge.net/doc/pbm.html> + +=back + +=head1 SEE ALSO + +L<Image::ExifTool::TagNames/PPM Tags>, +L<Image::ExifTool(3pm)|Image::ExifTool> + +=cut + diff --git a/lib/Image/ExifTool/PSP.pm b/lib/Image/ExifTool/PSP.pm new file mode 100644 index 0000000..a763313 --- /dev/null +++ b/lib/Image/ExifTool/PSP.pm @@ -0,0 +1,306 @@ +#------------------------------------------------------------------------------ +# File: PSP.pm +# +# Description: Read Paint Shop Pro meta information +# +# Revisions: 2010/01/23 - P. Harvey Created +# +# References: 1) http://www.jasc.com/support/kb/articles/pspspec.asp +#------------------------------------------------------------------------------ + +package Image::ExifTool::PSP; + +use strict; +use vars qw($VERSION); +use Image::ExifTool qw(:DataAccess :Utils); +use Image::ExifTool::Exif; + +$VERSION = '1.05'; + +sub ProcessExtData($$$); + +# PSP info +%Image::ExifTool::PSP::Main = ( + GROUPS => { 2 => 'Image' }, + VARS => { ALPHA_FIRST => 1 }, + NOTES => q{ + Tags extracted from Paint Shop Pro images (PSP, PSPIMAGE, PSPFRAME, + PSPSHAPE, PSPTUBE and TUB extensions). + }, + # FileVersions: + # 3.0 => PSP 5 + # 4.0 => PSP 6 + # 5.0 => PSP 7 + # 6.0 => PSP 8 + # 7.0 => PSP 9 + # ? => PSP X + # ? => PSP X1 (is this the same as X?) + # ? => PSP X2 + # 10.0 => PSP X3 (= PSP 13) + FileVersion => { PrintConv => '$val=~tr/ /./; $val' }, + 0 => [ + { + Condition => '$$self{PSPFileVersion} > 3', + Name => 'ImageInfo', + SubDirectory => { + TagTable => 'Image::ExifTool::PSP::Image', + Start => 4, + }, + }, + { + Name => 'ImageInfo', + SubDirectory => { + TagTable => 'Image::ExifTool::PSP::Image', + }, + }, + ], + 1 => { + Name => 'CreatorInfo', + SubDirectory => { TagTable => 'Image::ExifTool::PSP::Creator' }, + }, + 10 => { + Name => 'ExtendedInfo', + SubDirectory => { TagTable => 'Image::ExifTool::PSP::Ext' }, + }, + # this is inside the composite image bank block (16), which I don't want to parse... + #18 => { + # Name => 'PreviewImage', + # Groups => { 2 => 'Preview' }, + # RawConv => '$self->ValidateImage(\$val,$tag)', + #}, +); + +# the PSP image block +%Image::ExifTool::PSP::Image = ( + PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData, + GROUPS => { 2 => 'Image' }, + 0 => { Name => 'ImageWidth', Format => 'int32u' }, + 4 => { Name => 'ImageHeight', Format => 'int32u' }, + 8 => { Name => 'ImageResolution', Format => 'double' }, + 16 => { + Name => 'ResolutionUnit', + Format => 'int8u', + PrintConv => { + 0 => 'None', + 1 => 'inches', + 2 => 'cm', + }, + }, + 17 => { + Name => 'Compression', + Format => 'int16u', + PrintConv => { + 0 => 'None', + 1 => 'RLE', + 2 => 'LZ77', + 3 => 'JPEG', + }, + }, + 19 => { Name => 'BitsPerSample',Format => 'int16u' }, + 21 => { Name => 'Planes', Format => 'int16u' }, + 23 => { Name => 'NumColors', Format => 'int32u' }, +); + +# the PSP creator data block +%Image::ExifTool::PSP::Creator = ( + PROCESS_PROC => \&ProcessExtData, + GROUPS => { 2 => 'Image' }, + PRIORITY => 0, # prefer EXIF if it exists + 0 => 'Title', + 1 => { + Name => 'CreateDate', + Format => 'int32u', + Groups => { 2 => 'Time' }, + ValueConv => 'Image::ExifTool::ConvertUnixTime($val,1)', + PrintConv => '$self->ConvertDateTime($val)', + }, + 2 => { + Name => 'ModifyDate', + Format => 'int32u', + Groups => { 2 => 'Time' }, + ValueConv => 'Image::ExifTool::ConvertUnixTime($val,1)', + PrintConv => '$self->ConvertDateTime($val)', + }, + 3 => { + Name => 'Artist', + Groups => { 2 => 'Author' }, + }, + 4 => { + Name => 'Copyright', + Groups => { 2 => 'Author' }, + }, + 5 => 'Description', + 6 => { + Name => 'CreatorAppID', + Format => 'int32u', + PrintConv => { + 0 => 'Unknown', + 1 => 'Paint Shop Pro', + }, + }, + 7 => { + Name => 'CreatorAppVersion', + Format => 'int8u', + Count => 4, + ValueConv => 'join(" ",reverse split " ", $val)', # low byte first + PrintConv => '$val=~tr/ /./; $val', + }, +); + +# the PSP extended data block +%Image::ExifTool::PSP::Ext = ( + PROCESS_PROC => \&ProcessExtData, + GROUPS => { 2 => 'Image' }, + 3 => { + Name => 'EXIFInfo', #(don't change this name, it is used in the code) + SubDirectory => { TagTable => 'Image::ExifTool::Exif::Main' }, + }, +); + +#------------------------------------------------------------------------------ +# Extract information from the extended data block +# Inputs: 0) ExifTool object ref, 1) dirInfo ref, 2) tag table ref +# Returns: 1 on success +sub ProcessExtData($$$) +{ + my ($et, $dirInfo, $tagTablePtr) = @_; + my $dataPt = $$dirInfo{DataPt}; + my $dirLen = $$dirInfo{DirLen}; + my $pos = 0; + # loop through sub-blocks + while ($pos + 10 < $dirLen) { + unless (substr($$dataPt, $pos, 4) eq "~FL\0") { + $et->Warn('Lost synchronization while reading sub blocks'); + last; + } + my $tag = Get16u($dataPt, $pos + 4); + my $len = Get32u($dataPt, $pos + 6); + $pos += 10 + $len; + if ($pos > $dirLen) { + $et->Warn("Truncated sub block ID=$tag len=$len"); + last; + } + next unless $$tagTablePtr{$tag}; + my $tagInfo = $et->GetTagInfo($tagTablePtr, $tag) or next; + my $start = $pos - $len; + unless ($$tagInfo{Name} eq 'EXIFInfo') { + $et->HandleTag($tagTablePtr, $tag, undef, + TagInfo => $tagInfo, + DataPt => $dataPt, + DataPos => $$dirInfo{DataPos}, + DataLen => length $$dataPt, + Start => $start, + Size => $len, + ); + next; + } + # validate EXIF block header and set byte order + next unless $len > 14 and substr($$dataPt, $pos - $len, 6) eq "Exif\0\0"; + next unless SetByteOrder(substr($$dataPt, $start + 6, 2)); + # This is REALLY annoying... They use a standard TIFF offset to point to + # the first IFD, but after that the offsets are relative to the start of + # the IFD instead of the TIFF base, which means that I must handle it as a + # special case. Dumb, dumb... + $start += 14; + my %dirInfo = ( + DirName => 'EXIF', + Parent => 'PSP', + DataPt => $dataPt, + DataPos => -$start, # data position relative to Base + DataLen => length $$dataPt, + DirStart => $start, + Base => $start + $$dirInfo{DataPos}, # absolute base offset + Multi => 0, + ); + my $exifTable = GetTagTable($$tagInfo{SubDirectory}{TagTable}); + Image::ExifTool::Exif::ProcessExif($et, \%dirInfo, $exifTable); + SetByteOrder('II'); + } + return 1; +} + +#------------------------------------------------------------------------------ +# Extract information from a PSP file +# Inputs: 0) ExifTool object reference, 1) dirInfo reference +# Returns: 1 on success, 0 if this wasn't a valid PSP file +sub ProcessPSP($$) +{ + my ($et, $dirInfo) = @_; + my $raf = $$dirInfo{RAF}; + my ($buff, $tag, $len, $err); + return 0 unless $raf->Read($buff, 32) == 32 and + $buff eq "Paint Shop Pro Image File\x0a\x1a\0\0\0\0\0" and + $raf->Read($buff, 4) == 4; + $et->SetFileType(); + SetByteOrder('II'); + my $tagTablePtr = GetTagTable('Image::ExifTool::PSP::Main'); + my @a = unpack('v*', $buff); + # figure out block header length for this format PSP file + my $hlen = $a[0] > 3 ? 10 : 14; + $$et{PSPFileVersion} = $a[0]; # save for use in Condition + $et->HandleTag($tagTablePtr, FileVersion => "@a"); + # loop through blocks in file + my $pos = 36; + for (;;) { + last unless $raf->Read($buff, $hlen) == $hlen; + unless ($buff =~ /^~BK\0/) { + $et->Warn('Lost synchronization while reading main PSP blocks'); + last; + } + $tag = Get16u(\$buff, 4); + $len = Get32u(\$buff, $hlen - 4); + $pos += $hlen + $len; + unless ($$tagTablePtr{$tag}) { + $raf->Seek($len, 1) or $err=1, last; + next; + } + $raf->Read($buff, $len) == $len or $err=1, last; + $et->HandleTag($tagTablePtr, $tag, $buff, + DataPt => \$buff, + DataPos => $pos - $len, + Size => $len, + ); + } + $err and $et->Warn("Truncated main block ID=$tag len=$len"); + return 1; +} + +1; # end + +__END__ + +=head1 NAME + +Image::ExifTool::PSP - Read Paint Shop Pro meta information + +=head1 SYNOPSIS + +This module is used by Image::ExifTool + +=head1 DESCRIPTION + +This module contains routines required by Image::ExifTool to extract +information from Paint Shop Pro images. + +=head1 AUTHOR + +Copyright 2003-2019, Phil Harvey (phil at owl.phy.queensu.ca) + +This library is free software; you can redistribute it and/or modify it +under the same terms as Perl itself. + +=head1 REFERENCES + +=over 4 + +=item L<http://www.jasc.com/support/kb/articles/pspspec.asp> + +=back + +=head1 SEE ALSO + +L<Image::ExifTool::TagNames/PSP Tags>, +L<Image::ExifTool(3pm)|Image::ExifTool> + +=cut + diff --git a/lib/Image/ExifTool/Palm.pm b/lib/Image/ExifTool/Palm.pm new file mode 100644 index 0000000..90f8fe2 --- /dev/null +++ b/lib/Image/ExifTool/Palm.pm @@ -0,0 +1,403 @@ +#------------------------------------------------------------------------------ +# File: Palm.pm +# +# Description: Read Palm Database files +# +# Revisions: 2014/05/28 - P. Harvey Created +# +# References: 1) http://wiki.mobileread.com/wiki/PDB +# 2) http://wiki.mobileread.com/wiki/MOBI +#------------------------------------------------------------------------------ + +package Image::ExifTool::Palm; + +use strict; +use vars qw($VERSION); +use Image::ExifTool qw(:DataAccess :Utils); + +$VERSION = '1.00'; + +sub ProcessEXTH($$$); + +# type/creator ID's for Palm database files +my %palmTypes = ( + '.pdfADBE' => 'Adobe Reader', + 'TEXtREAd' => 'PalmDOC', + 'BVokBDIC' => 'BDicty', + 'DB99DBOS' => 'DB (Database program)', + 'PNRdPPrs' => 'eReader', + 'DataPPrs' => 'eReader', + 'vIMGView' => 'FireViewer (ImageViewer)', + 'PmDBPmDB' => 'HanDBase', + 'InfoINDB' => 'InfoView', + 'ToGoToGo' => 'iSilo', + 'SDocSilX' => 'iSilo 3', + 'JbDbJBas' => 'JFile', + 'JfDbJFil' => 'JFile Pro', + 'DATALSdb' => 'LIST', + 'Mdb1Mdb1' => 'MobileDB', + 'BOOKMOBI' => 'Mobipocket', + 'DataPlkr' => 'Plucker', + 'DataSprd' => 'QuickSheet', + 'SM01SMem' => 'SuperMemo', + 'TEXtTlDc' => 'TealDoc', + 'InfoTlIf' => 'TealInfo', + 'DataTlMl' => 'TealMeal', + 'DataTlPt' => 'TealPaint', + 'dataTDBP' => 'ThinkDB', + 'TdatTide' => 'Tides', + 'ToRaTRPW' => 'TomeRaider', + 'zTXTGPlm' => 'Weasel', + 'BDOCWrdS' => 'WordSmith', +); + +my %dateTimeInfo = ( + # like QuickTime, the time zero should be Jan 1, 1904, but not all software writes this, + # so assume a time zero of Jan 1, 1970 if the date is before this + RawConv => q{ + my $offset = (66 * 365 + 17) * 24 * 3600; + return $val - $offset if $val >= $offset; + return $val; + }, + ValueConv => 'ConvertUnixTime($val, 1)', # (UTC written by "EPUB Converter", ref PH) + PrintConv => '$self->ConvertDateTime($val)', +); + +# Palm Database header information +%Image::ExifTool::Palm::Main = ( + GROUPS => { 0 => 'Palm', 1 => 'Palm', 2 => 'Document' }, + PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData, + FORMAT => 'int32u', + NOTES => q{ + Information extracted from Palm database files (PDB and PRC extensions), + Mobipocket electronic books (MOBI), and Amazon Kindle KF7 and KF8 books (AZW + and AZW3). + }, + 0 => { Name => 'DatabaseName', Format => 'string[32]' }, + # 8 - int16u: file attributes (not very useful) + # 8.5 - int16u: version + 9 => { + Name => 'CreateDate', + Groups => { 2 => 'Time' }, + %dateTimeInfo, + }, + 10 => { + Name => 'ModifyDate', + Groups => { 2 => 'Time' }, + %dateTimeInfo, + }, + 11 => { + Name => 'LastBackupDate', + Groups => { 2 => 'Time' }, + %dateTimeInfo, + }, + 12 => 'ModificationNumber', + 15 => { + Name => 'PalmFileType', + Format => 'undef[8]', + PrintConv => \%palmTypes, + }, +); + + +# MOBI header tags +%Image::ExifTool::Palm::MOBI = ( + GROUPS => { 0 => 'Palm', 1 => 'MOBI', 2 => 'Document' }, + NOTES => q{ + Information extracted from the MOBI header of Mobipocket and Amazon Kindle + KF7 and KF8 files. + }, + PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData, + FORMAT => 'int32u', + 0 => { + Name => 'Compression', + Format => 'int16u', + PrintConv => { + 1 => 'None', + 2 => 'PalmDOC', + 17480 => 'HUFF/CDIC', + }, + }, + 1 => { + Name => 'UncompressedTextLength', + PrintConv => \&Image::ExifTool::ConvertFileSize, + }, + 3 => { + Name => 'Encryption', + PrintConv => { + 0 => 'None', + 1 => 'Old Mobipocket', + 2 => 'Mobipocket', + }, + }, + 6 => { + Name => 'MobiType', + PrintConv => { + 2 => 'Mobipocket Book', + 3 => 'PalmDoc Book', + 4 => 'Audio', + 232 => 'mobipocket? generated by kindlegen1.2', + 248 => 'KF8: generated by kindlegen2', + 257 => 'News', + 258 => 'News_Feed', + 259 => 'News_Magazine', + 513 => 'PICS', + 514 => 'WORD', + 515 => 'XLS', + 516 => 'PPT', + 517 => 'TEXT', + 518 => 'HTML', + }, + }, + 7 => { + Name => 'CodePage', + RawConv => '$$self{CodePage} = $val', + PrintConv => { + # just define commonly used code pages + # (a much more complete list may be found in FlashPix.pm) + 1252 => 'Windows Latin 1 (Western European)', + 65001 => 'Unicode (UTF-8)', + }, + }, + 9 => 'MobiVersion', + 21 => 'BookName', # this is actually an offset, but replace it with the string later + 26 => 'MinimumVersion', +); + +# MOBI extended header tags +%Image::ExifTool::Palm::EXTH = ( + GROUPS => { 0 => 'Palm', 1 => 'MOBI', 2 => 'Document' }, + FORMAT => 'string', + NOTES => 'Information extracted from the MOBI extended header.', + PROCESS_PROC => \&ProcessEXTH, + 1 => 'DRMServerID', + 2 => 'DRMCommerceID', + 3 => 'DRM_E-BookBaseID', + 100 => { Name => 'Author', Groups => { 2 => 'Author' } }, + 101 => 'Publisher', + 102 => 'Imprint', + 103 => 'Description', + 104 => 'ISBN', + 105 => { Name => 'Subject', List => 1 }, + 106 => { + Name => 'PublishDate', + Groups => { 2 => 'Time' }, + ValueConv => q{ + require Image::ExifTool::XMP; + Image::ExifTool::XMP::ConvertXMPDate($val, 1); + }, + PrintConv => '$self->ConvertDateTime($val)', + }, + 107 => 'Review', + 108 => 'Contributor', + 109 => { Name => 'Rights', Groups => { 2 => 'Author' } }, + 110 => 'SubjectCode', + 111 => 'BookType', + 112 => 'Source', + 113 => 'ASIN', + 114 => 'BookVersion', + 115 => { Name => 'SampleFlag', Format => 'int32u' }, + 116 => { Name => 'StartReading', Format => 'int32u' }, + 117 => 'Adult', + 118 => 'RetailPrice', + 119 => 'RetailPriceCurrency', + # 121 => 'KF8BoundaryOffset', + 125 => { Name => 'ResourceCount', Format => 'int32u' }, + 129 => 'KF8CoverURI', + 200 => 'DictionaryShortName', + # 201 => { Name => 'CoverOffset', Format => 'int32u' }, + # 202 => { Name => 'ThumbOffset', Format => 'int32u' }, + # 203 => 'HasFakeCover', + 204 => { + Name => 'CreatorSoftware', + Format => 'int32u', + PrintConv => { + 1 => 'Mobigen', + 2 => 'Mobipocket', + 200 => 'Kindlegen (Windows)', + 201 => 'Kindlegen (Linux)', + 202 => 'Kindlegen (Mac)', + }, + }, + 205 => { Name => 'CreatorMajorVersion', Format => 'int32u' }, + 206 => { Name => 'CreatorMinorVersion', Format => 'int32u' }, + 207 => { Name => 'CreatorBuildNumber', Format => 'int32u' }, + 208 => 'Watermark', + 209 => 'Tamper-proofKeys', + # 300 => 'FontSignature', + 401 => { Name => 'ClippingLimit', Format => 'int8u' }, + 402 => 'PublisherLimit', + 404 => { + Name => 'TextToSpeech', + Format => 'int8u', + PrintConv => { 0 => 'Enabled', 1 => 'Disabled' }, + }, + 405 => { Name => 'RentalFlag', Format => 'int8u' }, #? + 406 => 'RentalExpirationDate', + 501 => { Name => 'CDEType', Format => 'int32u' }, + 502 => 'LastUpdateTime', + 503 => 'UpdatedTitle', + 504 => 'ASIN2', + 524 => 'Language', + 525 => 'Alignment', + 535 => 'CreatorBuildNumber2', +); + +#------------------------------------------------------------------------------ +# Process the MOBI extended header +# Inputs: 0) ExifTool ref, 1) dirInfo ref, 2) tag table ref +# Returns: 1 (EXTH should have already been validated) +sub ProcessEXTH($$$) +{ + my ($et, $dirInfo, $tagTablePtr) = @_; + my $dataPt = $$dirInfo{DataPt}; + my $dataPos = $$dirInfo{DataPos}; + my $enc = $$dirInfo{Encoding} || 'UTF8'; + my $dirLen = length $$dataPt; + my ($index, $pos); + + $et->VerboseDir('EXTH', $$dirInfo{NumEntries}, $dirLen); + + # process the EXTH entries + for ($index=0, $pos=0; ; ++$index) { + last if $pos + 8 > $dirLen; + my $tag = Get32u($dataPt, $pos); + my $len = Get32u($dataPt, $pos + 4); + last if $len < 8 or $pos + $len > $dirLen; + my $key = $et->HandleTag($tagTablePtr, $tag, undef, + DataPt => $dataPt, + DataPos => $dataPos, + Start => $pos + 8, + Size => $len - 8, + Index => $index, + ); + # recode text if necessary + $$et{VALUE}{$key} = $et->Decode($$et{VALUE}{$key}, $enc) if $key; + $pos += $len; + } + return 1; +} + +#------------------------------------------------------------------------------ +# Extract information from a Palm DB file +# Inputs: 0) ExifTool ref, 1) dirInfo reference +# Returns: 1 if this was a recognized PDB file, 0 otherwise +sub ProcessPDB($$) +{ + my ($et, $dirInfo) = @_; + my $raf = $$dirInfo{RAF}; + my ($buff, $buf2, $size, $enc); + my $verbose = $et->Options('Verbose'); + + # verify this is a valid Palm DB file + return 0 unless $raf->Read($buff, 86) == 86; + my $type = $palmTypes{substr($buff, 60, 8)}; + return 0 unless $type; +# +# Read and process the Palm DB file header +# + $et->SetFileType($type eq 'Mobipocket' ? 'MOBI' : 'PDB'); + SetByteOrder('MM'); + + my $tagTablePtr = GetTagTable('Image::ExifTool::Palm::Main'); + $et->ProcessDirectory({ DataPt => \$buff }, $tagTablePtr); + + return 1 unless $type eq 'Mobipocket' and Get16u(\$buff, 76); +# +# Read and process MOBI header (should be the first record) +# + my $offset = Get32u(\$buff, 78); # get offset to first record + unless ($raf->Seek($offset, 0) and $raf->Read($buff, 274) == 274) { + $et->Warn('Truncated MOBI header'); + return 1; + } + unless (substr($buff, 16, 4) eq 'MOBI') { + $et->Warn('Invalid MOBI header'); + return 1; + } + $tagTablePtr = GetTagTable('Image::ExifTool::Palm::MOBI'); + $et->ProcessDirectory({ DataPt => \$buff }, $tagTablePtr); + + # get text encoding + $enc = $Image::ExifTool::charsetName{"cp$$et{CodePage}"} if $$et{CodePage}; + $enc = 'UTF8' unless $enc; + + # extract the BookName string + my $off = Get32u(\$buff, 84); + my $len = Get32u(\$buff, 88); + + $raf->Seek($offset+$off, 0) and $raf->Read($buf2, $len) == $len or $buf2 = '<err>'; + $$et{VALUE}{BookName} = $et->Decode($buf2, $enc); +# +# Process the MOBI extended header if it exists +# + # first, check the flag bit to see if the EXTH record should exist + my $flag = Get32u(\$buff, 128); + return 1 unless $flag & 0x40; # check extended header flag + + $len = Get32u(\$buff, 20) + 16; # MOBI header length (including PalmDOC header) + + unless ($raf->Seek($offset+$len, 0) and $raf->Read($buf2, 12) == 12 and + substr($buf2,0,4) eq 'EXTH' and ($size = Get32u(\$buf2, 4)) > 12) + { + $et->Warn('Invalid MOBI extended header'); + return 1; + } + + # read and process the MOBI extended header + $size -= 12; + $raf->Read($buff, $size) == $size or $et->Warn('Truncated MOBI extended header'), return 1; + my %dirInfo = ( + DataPt => \$buff, + DataPos => $offset + $len + 12, + NumEntries => Get32u(\$buf2, 8), + Encoding => $enc, + ); + $tagTablePtr = GetTagTable('Image::ExifTool::Palm::EXTH'); + $et->ProcessDirectory(\%dirInfo, $tagTablePtr); + + return 1; +} + +1; # end + +__END__ + +=head1 NAME + +Image::ExifTool::Palm - Read Palm Database files + +=head1 SYNOPSIS + +This module is used by Image::ExifTool + +=head1 DESCRIPTION + +This module contains code to extract metadata from Palm database files (PDB +and PRC extensions), Mobipocket electronic books (MOBI), and Amazon Kindle +KF7 and KF8 books (AZW and AZW3). + +=head1 AUTHOR + +Copyright 2003-2019, Phil Harvey (phil at owl.phy.queensu.ca) + +This library is free software; you can redistribute it and/or modify it +under the same terms as Perl itself. + +=head1 REFERENCES + +=over 4 + +=item L<http://wiki.mobileread.com/wiki/PDB> + +=item L<http://wiki.mobileread.com/wiki/MOBI> + +=back + +=head1 SEE ALSO + +L<Image::ExifTool::TagNames/Palm Tags>, +L<Image::ExifTool(3pm)|Image::ExifTool> + +=cut + diff --git a/lib/Image/ExifTool/Panasonic.pm b/lib/Image/ExifTool/Panasonic.pm new file mode 100644 index 0000000..0429348 --- /dev/null +++ b/lib/Image/ExifTool/Panasonic.pm @@ -0,0 +1,2654 @@ +#------------------------------------------------------------------------------ +# File: Panasonic.pm +# +# Description: Panasonic/Leica maker notes tags +# +# Revisions: 11/10/2004 - P. Harvey Created +# +# References: 1) http://www.compton.nu/panasonic.html (based on FZ10) +# 2) Derived from DMC-FZ3 samples from dpreview.com +# 3) http://johnst.org/sw/exiftags/ +# 4) Tels (http://bloodgate.com/) private communication (tests with FZ5) +# 7) http://homepage3.nifty.com/kamisaka/makernote/makernote_pana.htm (2007/10/02) +# 8) Marcel Coenen private communication (DMC-FZ50) +# 9) http://forums.dpreview.com/forums/read.asp?forum=1033&message=22756430 +# 10) http://bretteville.com/pdfs/M8Metadata_v2.pdf +# 11) http://www.digital-leica.com/lens_codes/index.html +# (now https://www.l-camera-forum.com/leica-news/leica-lens-codes/) +# 12) Joerg - http://www.cpanforum.com/threads/11602 (LX3 firmware 2.0) +# 13) Michael Byczkowski private communication (Leica M9) +# 14) Carl Bretteville private communication (M9) +# 15) Zdenek Mihula private communication (TZ8) +# 16) Olaf Ulrich private communication +# 17) http://u88.n24.queensu.ca/exiftool/forum/index.php/topic,4922.0.html +# 18) Thomas Modes private communication (G6) +# 19) http://u88.n24.queensu.ca/exiftool/forum/index.php/topic,5533.0.html +# 20) Bernd-Michael Kemper private communication (DMC-GX80/85) +# 21) Klaus Homeister forum post +# JD) Jens Duttke private communication (TZ3,FZ30,FZ50) +#------------------------------------------------------------------------------ + +package Image::ExifTool::Panasonic; + +use strict; +use vars qw($VERSION %leicaLensTypes); +use Image::ExifTool qw(:DataAccess :Utils); +use Image::ExifTool::Exif; + +$VERSION = '2.04'; + +sub ProcessLeicaLEIC($$$); +sub WhiteBalanceConv($;$$); + +# Leica lens types (ref 10) +%leicaLensTypes = ( + OTHER => sub { + my ($val, $inv, $conv) = @_; + return undef if $inv or not $val =~ s/ .*//; + return $$conv{$val}; + }, + Notes => q{ + the LensType value is obtained by splitting the stored value into 2 + integers: The stored value divided by 4, and its lower 2 bits. The second + number is used only if necessary to identify certain manually coded lenses + on the M9, or the focal length of some multi-focal lenses. + }, + # All M9 codes (two numbers: first the LensID then the lower 2 bits) + # are ref PH with samples from ref 13. From ref 10, the lower 2 bits of + # the LensType value give the frame selector position for most lenses, + # although for the 28-35-50mm (at least) it gives the focal length selection. + # The M9 also gives the focal length selection but for other lenses the + # lower 3 bits don't change with frame selector position except for the lens + # shows as uncoded for certain lenses and some incorrect positions of the + # frame selector. The bits are zero for uncoded lenses when manually coding + # from the menu on the M9. - PH + # Frame selector bits (from ref 10, M8): + # 1 => '28/90mm frame lines engaged', + # 2 => '24/35mm frame lines engaged', + # 3 => '50/75mm frame lines engaged', + '0 0' => 'Uncoded lens', +# +# NOTE: MUST ADD ENTRY TO %frameSelectorBits below when a new lens is added!!!! +# + # model number(s): + 1 => 'Elmarit-M 21mm f/2.8', # 11134 + 3 => 'Elmarit-M 28mm f/2.8 (III)', # 11804 + 4 => 'Tele-Elmarit-M 90mm f/2.8 (II)', # 11800 + 5 => 'Summilux-M 50mm f/1.4 (II)', # 11868/11856/11114 + 6 => 'Summicron-M 35mm f/2 (IV)', # 11310/11311 + '6 0' => 'Summilux-M 35mm f/1.4', # 11869/11870/11860 + 7 => 'Summicron-M 90mm f/2 (II)', # 11136/11137 + 9 => 'Elmarit-M 135mm f/2.8 (I/II)', # 11829 + '9 0' => 'Apo-Telyt-M 135mm f/3.4', # 11889 + 11 => 'Summaron-M 28mm f/5.6', # ? (ref IB) + 12 => 'Thambar-M 90mm f/2.2', # ? (ref IB) + 16 => 'Tri-Elmar-M 16-18-21mm f/4 ASPH.',# 11626 + '16 1' => 'Tri-Elmar-M 16-18-21mm f/4 ASPH. (at 16mm)', + '16 2' => 'Tri-Elmar-M 16-18-21mm f/4 ASPH. (at 18mm)', + '16 3' => 'Tri-Elmar-M 16-18-21mm f/4 ASPH. (at 21mm)', + 23 => 'Summicron-M 50mm f/2 (III)', # 11817, version (I) in camera menu + 24 => 'Elmarit-M 21mm f/2.8 ASPH.', # 11135/11897 + 25 => 'Elmarit-M 24mm f/2.8 ASPH.', # 11878/11898 + 26 => 'Summicron-M 28mm f/2 ASPH.', # 11604 + 27 => 'Elmarit-M 28mm f/2.8 (IV)', # 11809 + 28 => 'Elmarit-M 28mm f/2.8 ASPH.', # 11606 + 29 => 'Summilux-M 35mm f/1.4 ASPH.', # 11874/11883 + '29 0' => 'Summilux-M 35mm f/1.4 ASPHERICAL', # 11873 (different from "ASPH." model!) + 30 => 'Summicron-M 35mm f/2 ASPH.', # 11879/11882 + 31 => 'Noctilux-M 50mm f/1', # 11821/11822 + '31 0' => 'Noctilux-M 50mm f/1.2', # 11820 + 32 => 'Summilux-M 50mm f/1.4 ASPH.', # 11891/11892 + 33 => 'Summicron-M 50mm f/2 (IV, V)', # 11819/11825/11826/11816, version (II,III) in camera menu + 34 => 'Elmar-M 50mm f/2.8', # 11831/11823/11825 + 35 => 'Summilux-M 75mm f/1.4', # 11814/11815/11810 + 36 => 'Apo-Summicron-M 75mm f/2 ASPH.', # 11637 + 37 => 'Apo-Summicron-M 90mm f/2 ASPH.', # 11884/11885 + 38 => 'Elmarit-M 90mm f/2.8', # 11807/11808, version (II) in camera menu + 39 => 'Macro-Elmar-M 90mm f/4', # 11633/11634 + '39 0' => 'Tele-Elmar-M 135mm f/4 (II)',# 11861 + 40 => 'Macro-Adapter M', # 14409 + '41 3' => 'Apo-Summicron-M 50mm f/2 Asph', #16 + 42 => 'Tri-Elmar-M 28-35-50mm f/4 ASPH.',# 11625 + '42 1' => 'Tri-Elmar-M 28-35-50mm f/4 ASPH. (at 28mm)', + '42 2' => 'Tri-Elmar-M 28-35-50mm f/4 ASPH. (at 35mm)', + '42 3' => 'Tri-Elmar-M 28-35-50mm f/4 ASPH. (at 50mm)', + 43 => 'Summarit-M 35mm f/2.5', # ? (ref PH) + 44 => 'Summarit-M 50mm f/2.5', # ? (ref PH) + 45 => 'Summarit-M 75mm f/2.5', # ? (ref PH) + 46 => 'Summarit-M 90mm f/2.5', # ? + 47 => 'Summilux-M 21mm f/1.4 ASPH.', # ? (ref 11) + 48 => 'Summilux-M 24mm f/1.4 ASPH.', # ? (ref 11) + 49 => 'Noctilux-M 50mm f/0.95 ASPH.', # ? (ref 11) + 50 => 'Elmar-M 24mm f/3.8 ASPH.', # ? (ref 11) + 51 => 'Super-Elmar-M 21mm f/3.4 Asph', # ? (ref 16, frameSelectorBits=1) + '51 2' => 'Super-Elmar-M 14mm f/3.8 Asph', # ? (ref 16) + 52 => 'Super-Elmar-M 18mm f/3.8 ASPH.', # ? (ref PH/11) + '53 2' => 'Apo-Telyt-M 135mm f/3.4', #16 + '53 3' => 'Apo-Summicron-M 50mm f/2 (VI)', #LR + 58 => 'Noctilux-M 75mm f/1.25 ASPH.', # ? (ref IB) +); + +# M9 frame selector bits for each lens +# 1 = towards lens = 28/90mm or 21mm or Adapter (or Elmarit-M 135mm f/2.8) +# 2 = away from lens = 24/35mm (or 35/135mm on the M9) +# 3 = middle position = 50/75mm or 18mm +my %frameSelectorBits = ( + 1 => 1, + 3 => 1, + 4 => 1, + 5 => 3, + 6 => 2, + 7 => 1, + 9 => 1, # (because lens has special magnifier for the rangefinder) + 16 => 1, # or 2 or 3 + 23 => 3, + 24 => 1, + 25 => 2, + 26 => 1, + 27 => 1, + 28 => 1, + 29 => 2, + 30 => 2, + 31 => 3, + 32 => 3, + 33 => 3, + 34 => 3, + 35 => 3, + 36 => 3, + 37 => 1, + 38 => 1, + 39 => 1, + 40 => 1, + 42 => 1, # or 2 or 3 + 43 => 2, # (NC) + 44 => 3, # (NC) + 45 => 3, + 46 => 1, # (NC) + 47 => 1, # (NC) + 48 => 2, # (NC) + 49 => 3, # (NC) + 50 => 2, # (NC) + 51 => 1, # or 2 (ref 16) + 52 => 3, + 53 => 2, #16 +); + +# conversions for ShootingMode and SceneMode +my %shootingMode = ( + 1 => 'Normal', + 2 => 'Portrait', + 3 => 'Scenery', + 4 => 'Sports', + 5 => 'Night Portrait', + 6 => 'Program', + 7 => 'Aperture Priority', + 8 => 'Shutter Priority', + 9 => 'Macro', + 10 => 'Spot', #7 + 11 => 'Manual', + 12 => 'Movie Preview', #PH (LZ6) + 13 => 'Panning', + 14 => 'Simple', #PH (LZ6) + 15 => 'Color Effects', #7 + 16 => 'Self Portrait', #PH (TZ5) + 17 => 'Economy', #7 + 18 => 'Fireworks', + 19 => 'Party', + 20 => 'Snow', + 21 => 'Night Scenery', + 22 => 'Food', #7 + 23 => 'Baby', #JD + 24 => 'Soft Skin', #PH (LZ6) + 25 => 'Candlelight', #PH (LZ6) + 26 => 'Starry Night', #PH (LZ6) + 27 => 'High Sensitivity', #7 (LZ6) + 28 => 'Panorama Assist', #7 + 29 => 'Underwater', #7 + 30 => 'Beach', #PH (LZ6) + 31 => 'Aerial Photo', #PH (LZ6) + 32 => 'Sunset', #PH (LZ6) + 33 => 'Pet', #JD + 34 => 'Intelligent ISO', #PH (LZ6) + 35 => 'Clipboard', #7 + 36 => 'High Speed Continuous Shooting', #7 + 37 => 'Intelligent Auto', #7 + 39 => 'Multi-aspect', #PH (TZ5) + 41 => 'Transform', #PH (FS7) + 42 => 'Flash Burst', #PH (FZ28) + 43 => 'Pin Hole', #PH (FZ28) + 44 => 'Film Grain', #PH (FZ28) + 45 => 'My Color', #PH (GF1) + 46 => 'Photo Frame', #PH (FS7) + 48 => 'Movie', #PH (GM1) + # 49 - seen for FS4 (snow?) + 51 => 'HDR', #12 + 52 => 'Peripheral Defocus', #Horst Wandres + 55 => 'Handheld Night Shot', #PH (FZ47) + 57 => '3D', #PH (3D1) + 59 => 'Creative Control', #PH (FZ47) + 60 => 'Intelligent Auto Plus', #20 + 62 => 'Panorama', #17 + 63 => 'Glass Through', #17 + 64 => 'HDR', #17 + 66 => 'Digital Filter', #PH (GF5 "Impressive Art", "Cross Process", "Color Select", "Star") + 67 => 'Clear Portrait', #18 + 68 => 'Silky Skin', #18 + 69 => 'Backlit Softness', #18 + 70 => 'Clear in Backlight', #18 + 71 => 'Relaxing Tone', #18 + 72 => "Sweet Child's Face", #18 + 73 => 'Distinct Scenery', #18 + 74 => 'Bright Blue Sky', #18 + 75 => 'Romantic Sunset Glow', #18 + 76 => 'Vivid Sunset Glow', #18 + 77 => 'Glistening Water', #18 + 78 => 'Clear Nightscape', #18 + 79 => 'Cool Night Sky', #18 + 80 => 'Warm Glowing Nightscape', #18 + 81 => 'Artistic Nightscape', #18 + 82 => 'Glittering Illuminations', #18 + 83 => 'Clear Night Portrait', #18 + 84 => 'Soft Image of a Flower', #18 + 85 => 'Appetizing Food', #18 + 86 => 'Cute Desert', #18 + 87 => 'Freeze Animal Motion', #18 + 88 => 'Clear Sports Shot', #18 + 89 => 'Monochrome', #18 + 90 => 'Creative Control', #18 +); + +%Image::ExifTool::Panasonic::Main = ( + WRITE_PROC => \&Image::ExifTool::Exif::WriteExif, + CHECK_PROC => \&Image::ExifTool::Exif::CheckExif, + GROUPS => { 0 => 'MakerNotes', 2 => 'Camera' }, + WRITABLE => 1, + 0x01 => { + Name => 'ImageQuality', + Writable => 'int16u', + Notes => 'quality of the main image, which may be in a different file', + PrintConv => { + 1 => 'TIFF', #PH (FZ20) + 2 => 'High', + 3 => 'Normal', + # 5 - seen this for 1920x1080, 30fps SZ7 video - PH + 6 => 'Very High', #3 (Leica) + 7 => 'RAW', #3 (Leica) + 9 => 'Motion Picture', #PH (LZ6) + 11 => 'Full HD Movie', #PH (V-LUX) + 12 => '4k Movie', #PH (V-LUX) + }, + }, + 0x02 => { + Name => 'FirmwareVersion', + Writable => 'undef', + Notes => q{ + for some camera models such as the FZ30 this may be an internal production + reference number and not the actual firmware version + }, # (ref http://www.stevesforums.com/forums/view_topic.php?id=87764&forum_id=23&) + # (can be either binary or ascii -- add decimal points if binary) + ValueConv => '$val=~/[\0-\x2f]/ ? join(" ",unpack("C*",$val)) : $val', + ValueConvInv => q{ + $val =~ /(\d+ ){3}\d+/ and $val = pack('C*',split(' ', $val)); + length($val) == 4 or warn "Version must be 4 numbers\n"; + return $val; + }, + PrintConv => '$val=~tr/ /./; $val', + PrintConvInv => '$val=~tr/./ /; $val', + }, + 0x03 => { + Name => 'WhiteBalance', + Writable => 'int16u', + PrintConv => { + 1 => 'Auto', + 2 => 'Daylight', + 3 => 'Cloudy', + 4 => 'Incandescent', #PH + 5 => 'Manual', + 8 => 'Flash', + 10 => 'Black & White', #3 (Leica) + 11 => 'Manual 2', #PH (FZ8) + 12 => 'Shade', #PH (FS7) + 13 => 'Kelvin', #PeterK (NC) + 14 => 'Manual 3', #forum9296 + 15 => 'Manual 4', #forum9296 + # also seen 18,26 (forum9296) + 19 => 'Auto (cool)', #PH (Leica C-Lux) + }, + }, + 0x07 => { + Name => 'FocusMode', + Writable => 'int16u', + PrintConv => { + 1 => 'Auto', + 2 => 'Manual', + 4 => 'Auto, Focus button', #4 + 5 => 'Auto, Continuous', #4 + 6 => 'AF-S', #18 (also seen for GF1 - PH) + 7 => 'AF-C', #18 + 8 => 'AF-F', #18 (auto-focus flexible) + }, + }, + 0x0f => [ + { + Name => 'AFAreaMode', + Condition => '$$self{Model} =~ /DMC-FZ10\b/', #JD + Writable => 'int8u', + Count => 2, + Notes => 'DMC-FZ10', + PrintConv => { + '0 1' => 'Spot Mode On', + '0 16' => 'Spot Mode Off', + }, + },{ + Name => 'AFAreaMode', + Writable => 'int8u', + Count => 2, + Notes => 'other models', + PrintConv => { #PH + '0 1' => '9-area', # (FS7) + '0 16' => '3-area (high speed)', # (FZ8) + '0 23' => '23-area', #PH (FZ47,NC) + '0 49' => '49-area', #20 + '1 0' => 'Spot Focusing', # (FZ8) + '1 1' => '5-area', # (FZ8) + '16' => 'Normal?', # (only mode for DMC-LC20) + '16 0' => '1-area', # (FZ8) + '16 16' => '1-area (high speed)', # (FZ8) + # '32 0' is Face Detect for FS7, and Face Detect or Focus Tracking + # for the DMC-FZ200 (ref 17), and Auto is DMC-L1 guess, + '32 0' => 'Tracking', + '32 1' => '3-area (left)?', # (DMC-L1 guess) + '32 2' => '3-area (center)?', # (DMC-L1 guess) + '32 3' => '3-area (right)?', # (DMC-L1 guess) + '64 0' => 'Face Detect', + '128 0' => 'Spot Focusing 2', #18 + }, + }, + ], + 0x1a => { + Name => 'ImageStabilization', + Writable => 'int16u', + PrintConv => { + 2 => 'On, Mode 1', + 3 => 'Off', + 4 => 'On, Mode 2', + 5 => 'Panning', #18 + # GF1 also has a "Mode 3" - PH + 6 => 'On, Mode 3', #PH (GX7, sensor shift?) + 9 => 'Dual IS', #20 + 11 => 'Dual2 IS', #forum9298 + }, + }, + 0x1c => { + Name => 'MacroMode', + Writable => 'int16u', + PrintConv => { + 1 => 'On', + 2 => 'Off', + 0x101 => 'Tele-Macro', #7 + 0x201 => 'Macro Zoom', #PH (FS7) + }, + }, + 0x1f => { + Name => 'ShootingMode', + Writable => 'int16u', + PrintConvColumns => 2, + PrintConv => \%shootingMode, + }, + 0x20 => { + Name => 'Audio', + Writable => 'int16u', + PrintConv => { + 1 => 'Yes', + 2 => 'No', + 3 => 'Stereo', #PH (NC) + }, + }, + 0x21 => { #2 + Name => 'DataDump', + Writable => 0, + Binary => 1, + }, + # 0x22 - normally 0, but 2 for 'Simple' ShootingMode in LZ6 sample - PH + 0x23 => { + Name => 'WhiteBalanceBias', + Format => 'int16s', + Writable => 'int16s', + ValueConv => '$val / 3', + ValueConvInv => '$val * 3', + PrintConv => 'Image::ExifTool::Exif::PrintFraction($val)', + PrintConvInv => 'Image::ExifTool::Exif::ConvertFraction($val)', + }, + 0x24 => { + Name => 'FlashBias', + Format => 'int16s', + Writable => 'int16s', + ValueConv => '$val / 3', #17 (older models may not have factor of 3? - PH) + ValueConvInv => '$val * 3', + PrintConv => 'Image::ExifTool::Exif::PrintFraction($val)', + PrintConvInv => 'Image::ExifTool::Exif::ConvertFraction($val)', + }, + 0x25 => { #PH + Name => 'InternalSerialNumber', + Writable => 'undef', + Count => 16, + Notes => q{ + this number is unique, and contains the date of manufacture, but is not the + same as the number printed on the camera body + }, + PrintConv => q{ + return $val unless $val=~/^([A-Z]\d{2})(\d{2})(\d{2})(\d{2})(\d{4})/; + my $yr = $2 + ($2 < 70 ? 2000 : 1900); + return "($1) $yr:$3:$4 no. $5"; + }, + PrintConvInv => '$_=$val; tr/A-Z0-9//dc; s/(.{3})(19|20)/$1/; $_', + }, + 0x26 => { #PH + Name => 'PanasonicExifVersion', + Writable => 'undef', + }, + # 0x27 - values: 0 (LZ6,FX10K) + 0x28 => { + Name => 'ColorEffect', + Writable => 'int16u', + # FX30 manual: (ColorMode) natural, vivid, cool, warm, b/w, sepia + PrintConv => { + 1 => 'Off', + 2 => 'Warm', + 3 => 'Cool', + 4 => 'Black & White', + 5 => 'Sepia', + 6 => 'Happy', #PH (FX70) (yes, really. you wouldn't want sad colors now would you?) + 8 => 'Vivid', #PH (SZ3) + }, + }, + 0x29 => { #JD + Name => 'TimeSincePowerOn', + Writable => 'int32u', + Notes => q{ + time in 1/100 s from when the camera was powered on to when the image is + written to memory card + }, + ValueConv => '$val / 100', + ValueConvInv => '$val * 100', + PrintConv => sub { # convert to format "[DD days ]HH:MM:SS.ss" + my $val = shift; + my $str = ''; + if ($val >= 24 * 3600) { + my $d = int($val / (24 * 3600)); + $str .= "$d days "; + $val -= $d * 24 * 3600; + } + my $h = int($val / 3600); + $val -= $h * 3600; + my $m = int($val / 60); + $val -= $m * 60; + my $ss = sprintf('%05.2f', $val); + if ($ss >= 60) { + $ss = '00.00'; + ++$m >= 60 and $m -= 60, ++$h; + } + return sprintf("%s%.2d:%.2d:%s",$str,$h,$m,$ss); + }, + PrintConvInv => sub { + my $val = shift; + my @vals = ($val =~ /\d+(?:\.\d*)?/g); + my $sec = 0; + $sec += 24 * 3600 * shift(@vals) if @vals > 3; + $sec += 3600 * shift(@vals) if @vals > 2; + $sec += 60 * shift(@vals) if @vals > 1; + $sec += shift(@vals) if @vals; + return $sec; + }, + }, + 0x2a => { #4 + Name => 'BurstMode', + Writable => 'int16u', + Notes => 'decoding may be different for some models', + PrintConv => { + 0 => 'Off', + 1 => 'On', #PH (TZ5) [was "Low/High Quality" from ref 4] + 2 => 'Auto Exposure Bracketing (AEB)', #17 + 4 => 'Unlimited', #PH (TZ5) + 8 => 'White Balance Bracketing', #18 + 17 => 'On (with flash)', #forum5597 + }, + }, + 0x2b => { #4 + Name => 'SequenceNumber', + Writable => 'int32u', + }, + 0x2c => [ + { + Name => 'ContrastMode', + Condition => '$$self{Model} !~ /^DMC-(FX10|G1|L1|L10|LC80|GF\d+|G2|TZ10|ZS7)$/', + Flags => 'PrintHex', + Writable => 'int16u', + Notes => q{ + this decoding seems to work for some models such as the LC1, LX2, FZ7, FZ8, + FZ18 and FZ50, but may not be correct for other models such as the FX10, G1, L1, + L10 and LC80 + }, + PrintConv => { + 0x00 => 'Normal', + 0x01 => 'Low', + 0x02 => 'High', + # 0x03 - observed with LZ6 and TZ5 in Fireworks mode + # and GX7 in Fantasy/Retro/OldDays/HighKey - PH + # 0x04 - observed in MP4 movie with GM1 (EXIF and 0x39 Contrast "Normal") - PH + # 0x05 - observed with FX01, FX40 and FP8 (EXIF contrast "Normal") - PH + 0x06 => 'Medium Low', #PH (FZ18) + 0x07 => 'Medium High', #PH (FZ18) + # 0x08 - GX7 in DynamicMonochrome mode + 0x0d => 'High Dynamic', #PH (FZ47 in ?) + # 0x13 - seen for LX100 (PH) + # 0x18 - seen for FZ2500 (PH) + # DMC-LC1 values: + 0x100 => 'Low', + 0x110 => 'Normal', + 0x120 => 'High', + } + },{ + Name => 'ContrastMode', + Condition => '$$self{Model} =~ /^DMC-(GF\d+|G2)$/', + Notes => 'these values are used by the G2, GF1, GF2, GF3, GF5 and GF6', + Writable => 'int16u', + PrintConv => { # (decoded for GF1 unless otherwise noted) + 0 => '-2', + 1 => '-1', + 2 => 'Normal', + 3 => '+1', + 4 => '+2', + # Note: Other Contrast tags will be "Normal" in any of these modes: + 5 => 'Normal 2', # 5 - seen for Portrait (FX80) and Normal (GF6) + 7 => 'Nature (Color Film)', # (GF1,G2; GF3 "Miniature") + 9 => 'Expressive', #(GF3) + 12 => 'Smooth (Color Film) or Pure (My Color)', #(GF1,G2 "Smooth Color") + 17 => 'Dynamic (B&W Film)', #(GF1,G2) + 22 => 'Smooth (B&W Film)', #(GF1,G2) + 25 => 'High Dynamic', #(GF5) + 26 => 'Retro', #(GF5) + 27 => 'Dynamic (Color Film)', #(GF1,G2) (GF3 "High Key") + 28 => 'Low Key', #(GF5) + 29 => 'Toy Effect', #(GF5) + 32 => 'Vibrant (Color Film) or Expressive (My Color)', # (GF1; G2 "Vibrant"; GF2,GF5 "Expressive") + 33 => 'Elegant (My Color)', + 37 => 'Nostalgic (Color Film)', # (GF1,G2; GF5 "Sepia") + 41 => 'Dynamic Art (My Color)', # (GF5 "High Key") + 42 => 'Retro (My Color)', + 45 => 'Cinema', #(GF2) + 47 => 'Dynamic Mono', #(GF5) + 50 => 'Impressive Art', #(GF5) + 51 => 'Cross Process', #(GF5) + 100 => 'High Dynamic 2', #Exiv2 (G6) + 101 => 'Retro 2', #Exiv2 (G6) + 102 => 'High Key 2', #Exiv2 (G6) + 103 => 'Low Key 2', #Exiv2 (G6) + 104 => 'Toy Effect 2', #Exiv2 (G6) + 107 => 'Expressive 2', #(GF6) + 112 => 'Sepia', #Exiv2 (G6) + 117 => 'Miniature', #Exiv2 (G6) + 122 => 'Dynamic Monochrome', #(GF6) + 127 => 'Old Days', #Exiv2 (G6) + 132 => 'Dynamic Monochrome 2', #Exiv2 (G6) + 135 => 'Impressive Art 2', #Exiv2 (G6) + 136 => 'Cross Process 2', #Exiv2 (G6) + 137 => 'Toy Pop', #Exiv2 (G6) + 138 => 'Fantasy', #Exiv2 (G6) + 256 => 'Normal 3', #Exiv2 (G6) + 272 => 'Standard', #Exiv2 (G6) + 288 => 'High', #Exiv2 (G6) + # more new modes for GF6: + # ? => 'Old Days', + # ? => 'Toy Pop', + # ? => 'Bleach Bypass', + # ? => 'Fantasy', + # ? => 'Star Filter', + # ? => 'One Point Color', + # ? => 'Sunshine', + }, + },{ + Name => 'ContrastMode', + Condition => '$$self{Model} =~ /^DMC-(TZ10|ZS7)$/', + Notes => 'these values are used by the TZ10 and ZS7', + Writable => 'int16u', + PrintConv => { + 0 => 'Normal', + 1 => '-2', + 2 => '+2', + 5 => '-1', + 6 => '+1', + }, + },{ + Name => 'ContrastMode', + Writable => 'int16u', + }, + ], + 0x2d => { + Name => 'NoiseReduction', + Writable => 'int16u', + Notes => 'the encoding for this value is not consistent between models', + PrintConv => { + 0 => 'Standard', + 1 => 'Low (-1)', + 2 => 'High (+1)', + 3 => 'Lowest (-2)', #JD + 4 => 'Highest (+2)', #JD + # 6 - seen for DC-S1/S1R (IB) + # 65531 - seen for LX100/FZ2500 "NR1" test shots at imaging-resource (PH) + # 0 - seen for FZ2500 "NR6D" test shots (PH) + }, + }, + 0x2e => { #4 + Name => 'SelfTimer', + Writable => 'int16u', + PrintConv => { + 1 => 'Off', + 2 => '10 s', + 3 => '2 s', + 4 => '10 s / 3 pictures', #17 + # 258 - seen for FZ2500,TZ90,LeicaCLux (PH) + }, + }, + # 0x2f - values: 1 (LZ6,FX10K) + 0x30 => { #7 + Name => 'Rotation', + Writable => 'int16u', + PrintConv => { + 1 => 'Horizontal (normal)', + 3 => 'Rotate 180', #PH + 6 => 'Rotate 90 CW', #PH (ref 7 gives 270 CW) + 8 => 'Rotate 270 CW', #PH (ref 7 gives 90 CW) + }, + }, + 0x31 => { #PH (FS7) + Name => 'AFAssistLamp', + Writable => 'int16u', + PrintConv => { + 1 => 'Fired', + 2 => 'Enabled but Not Used', + 3 => 'Disabled but Required', + 4 => 'Disabled and Not Required', + # have seen a value of 5 - PH + # values possibly related to FOC-L? - JD + }, + }, + 0x32 => { #7 + Name => 'ColorMode', + Writable => 'int16u', + PrintConv => { + 0 => 'Normal', + 1 => 'Natural', + 2 => 'Vivid', + # have seen 3 for GF2 - PH + }, + }, + 0x33 => { #JD + Name => 'BabyAge', + Writable => 'string', + Notes => 'or pet age', #PH + PrintConv => '$val eq "9999:99:99 00:00:00" ? "(not set)" : $val', + PrintConvInv => '$val =~ /^\d/ ? $val : "9999:99:99 00:00:00"', + }, + 0x34 => { #7/PH + Name => 'OpticalZoomMode', + Writable => 'int16u', + PrintConv => { + 1 => 'Standard', + 2 => 'Extended', + }, + }, + 0x35 => { #9 + Name => 'ConversionLens', + Writable => 'int16u', + PrintConv => { #PH (unconfirmed) + 1 => 'Off', + 2 => 'Wide', + 3 => 'Telephoto', + 4 => 'Macro', + }, + }, + 0x36 => { #8 + Name => 'TravelDay', + Writable => 'int16u', + PrintConv => '$val == 65535 ? "n/a" : $val', + PrintConvInv => '$val =~ /(\d+)/ ? $1 : $val', + }, + # 0x37 - values: 0,1,2 (LZ6, 0 for movie preview); 257 (FX10K); 0,256 (TZ5, 0 for movie preview) + # 0x38 - values: 0,1,2 (LZ6, same as 0x37); 1,2 (FX10K); 0,256 (TZ5, 0 for movie preview) + 0x39 => { #7 (L1/L10) + Name => 'Contrast', + Format => 'int16s', + Writable => 'int16u', + %Image::ExifTool::Exif::printParameter, + }, + 0x3a => { + Name => 'WorldTimeLocation', + Writable => 'int16u', + PrintConv => { + 1 => 'Home', + 2 => 'Destination', + }, + }, + 0x3b => { #PH (TZ5/FS7) + # (tags 0x3b, 0x3e, 0x8008 and 0x8009 have the same values in all my samples - PH) + Name => 'TextStamp', + Writable => 'int16u', + PrintConv => { 1 => 'Off', 2 => 'On' }, + }, + 0x3c => { #PH + Name => 'ProgramISO', # (maybe should rename this ISOSetting?) + Writable => 'int16u', # (new models store a long here) + PrintConv => { + OTHER => sub { shift }, + 65534 => 'Intelligent ISO', #PH (FS7) + 65535 => 'n/a', + -1 => 'n/a', + }, + }, + 0x3d => { #PH + Name => 'AdvancedSceneType', + Writable => 'int16u', + Notes => 'used together with SceneMode to derive Composite AdvancedSceneMode', + }, + 0x3e => { #PH (TZ5/FS7) + # (tags 0x3b, 0x3e, 0x8008 and 0x8009 have the same values in all my samples - PH) + Name => 'TextStamp', + Writable => 'int16u', + PrintConv => { 1 => 'Off', 2 => 'On' }, + }, + 0x3f => { #PH (TZ7) + Name => 'FacesDetected', + Writable => 'int16u', + }, + 0x40 => { #7 (L1/L10) + Name => 'Saturation', + Format => 'int16s', + Writable => 'int16u', + %Image::ExifTool::Exif::printParameter, + }, + 0x41 => { #7 (L1/L10) + Name => 'Sharpness', + Format => 'int16s', + Writable => 'int16u', + %Image::ExifTool::Exif::printParameter, + }, + 0x42 => { #7 (DMC-L1) + Name => 'FilmMode', + Writable => 'int16u', + PrintConv => { + 0 => 'n/a', #PH (eg. FZ100 "Photo Frame" ShootingMode) + 1 => 'Standard (color)', + 2 => 'Dynamic (color)', + 3 => 'Nature (color)', + 4 => 'Smooth (color)', + 5 => 'Standard (B&W)', + 6 => 'Dynamic (B&W)', + 7 => 'Smooth (B&W)', + # 8 => 'My Film 1'? (from owner manual) + # 9 => 'My Film 2'? + 10 => 'Nostalgic', #(GH1) + 11 => 'Vibrant', #(GH1) + # 12 => 'Multi Film'? (in the GH1 specs) + }, + }, + 0x43 => { #forum9369 + Name => 'JPEGQuality', + Writable => 'int16u', + PrintConv => { + 0 => 'n/a (Movie)', + 2 => 'High', + 3 => 'Standard', + 6 => 'Very High', + 255 => 'n/a (RAW only)', + }, + }, + 0x44 => { + Name => 'ColorTempKelvin', + Format => 'int16u', + }, + 0x45 => { #19 + Name => 'BracketSettings', + Writable => 'int16u', + PrintConv => { + 0 => 'No Bracket', + 1 => '3 Images, Sequence 0/-/+', + 2 => '3 Images, Sequence -/0/+', + 3 => '5 Images, Sequence 0/-/+', + 4 => '5 Images, Sequence -/0/+', + 5 => '7 Images, Sequence 0/-/+', + 6 => '7 Images, Sequence -/0/+', + }, + }, + 0x46 => { #PH/JD + Name => 'WBShiftAB', + Format => 'int16s', + Writable => 'int16u', + Notes => 'positive is a shift toward blue', + }, + 0x47 => { #PH/JD + Name => 'WBShiftGM', + Format => 'int16s', + Writable => 'int16u', + Notes => 'positive is a shift toward green', + }, + 0x48 => { #17 + Name => 'FlashCurtain', + Writable => 'int16u', + PrintConv => { + 0 => 'n/a', + 1 => '1st', + 2 => '2nd', + }, + }, + 0x49 => { #19 + Name => 'LongExposureNoiseReduction', + Writable => 'int16u', + PrintConv => { + 1 => 'Off', + 2 => 'On' + } + }, + # 0x4a - int16u: 0 + 0x4b => { #PH + Name => 'PanasonicImageWidth', + Writable => 'int32u', + }, + 0x4c => { #PH + Name => 'PanasonicImageHeight', + Writable => 'int32u', + }, + 0x4d => { #PH (FS7) + Name => 'AFPointPosition', + Writable => 'rational64u', + Count => 2, + Notes => 'X Y coordinates of primary AF area center, in the range 0.0 to 1.0', + PrintConv => q{ + return 'none' if $val eq '16777216 16777216'; + my @a = split ' ', $val; + sprintf("%.2g %.2g",@a); + }, + PrintConvInv => '$val eq "none" ? "16777216 16777216" : $val', + }, + 0x4e => { #PH + Name => 'FaceDetInfo', + PrintConv => 'length $val', + SubDirectory => { + TagTable => 'Image::ExifTool::Panasonic::FaceDetInfo', + }, + }, + # 0x4f,0x50 - int16u: 0 + 0x51 => { + Name => 'LensType', + Writable => 'string', + ValueConv => '$val=~s/ +$//; $val', # trim trailing spaces + ValueConvInv => '$val', + }, + 0x52 => { #7 (DMC-L1) + Name => 'LensSerialNumber', + Writable => 'string', + ValueConv => '$val=~s/ +$//; $val', # trim trailing spaces + ValueConvInv => '$val', + }, + 0x53 => { #7 (DMC-L1) + Name => 'AccessoryType', + Writable => 'string', + ValueConv => '$val=~s/ +$//; $val', # trim trailing spaces + ValueConvInv => '$val', + }, + 0x54 => { #19 + Name => 'AccessorySerialNumber', + Writable => 'string', + ValueConv => '$val=~s/ +$//; $val', # trim trailing spaces + ValueConvInv => '$val', + }, + # 0x55 - int16u: 1 (see forum9372) + # 0x57 - int16u: 0 + 0x59 => { #PH (FS7) + Name => 'Transform', + Writable => 'undef', + Notes => 'decoded as two 16-bit signed integers', + Format => 'int16s', + Count => 2, + PrintConv => { + '-3 2' => 'Slim High', + '-1 1' => 'Slim Low', + '0 0' => 'Off', + '1 1' => 'Stretch Low', + '3 2' => 'Stretch High', + }, + }, + # 0x5a - int16u: 0,2 + # 0x5b - int16u: 0 + # 0x5c - int16u: 0,2 + 0x5d => { #PH (GF1, FZ35) + Name => 'IntelligentExposure', + Notes => 'not valid for some models', # (doesn't change in ZS7 and GH1 images) + Writable => 'int16u', + PrintConv => { + 0 => 'Off', + 1 => 'Low', + 2 => 'Standard', + 3 => 'High', + }, + }, + # 0x5e,0x5f - undef[4] + 0x60 => { #18 + Name => 'LensFirmwareVersion', + Writable => 'undef', + Format => 'int8u', + Count => 4, + PrintConv => '$val=~tr/ /./; $val', + PrintConvInv => '$val=~tr/./ /; $val', + }, + 0x61 => { #PH + Name => 'FaceRecInfo', + SubDirectory => { + TagTable => 'Image::ExifTool::Panasonic::FaceRecInfo', + }, + }, + 0x62 => { #PH (FS7) + Name => 'FlashWarning', + Writable => 'int16u', + PrintConv => { 0 => 'No', 1 => 'Yes (flash required but disabled)' }, + }, + 0x63 => { #PH + # not sure exactly what this means, but in my samples this is + # FacesRecognized bytes of 0x01, padded with 0x00 to a length of 4 - PH + Name => 'RecognizedFaceFlags', + Format => 'int8u', + Count => 4, + Writable => 'undef', + Unknown => 1, + }, + 0x65 => { #15 + Name => 'Title', + Format => 'string', + Writable => 'undef', # (Count 64) + }, + 0x66 => { #15 + Name => 'BabyName', + Notes => 'or pet name', + Format => 'string', + Writable => 'undef', # (Count 64) + }, + 0x67 => { #15 + Name => 'Location', + Groups => { 2 => 'Location' }, + Format => 'string', + Writable => 'undef', # (Count 64) + }, + # 0x68 - int8u: 1 + 0x69 => { #PH (ZS7) + Name => 'Country', # (Country/Region) + Groups => { 2 => 'Location' }, + Format => 'string', + Writable => 'undef', # (Count 72) + }, + # 0x6a - int8u: 1 + 0x6b => { #PH (ZS7) + Name => 'State', # (State/Province/Count -- what is Count?) + Groups => { 2 => 'Location' }, + Format => 'string', + Writable => 'undef', # (Count 72) + }, + # 0x6c - int8u: 1 + 0x6d => { #PH (ZS7) (also see forum5997) + Name => 'City', # (City/Town) + Groups => { 2 => 'Location' }, + Format => 'string', + Writable => 'undef', # (Count 72) + Notes => 'City/Town as stored by some models, or County/Township for others', + }, + # 0x6e - int8u: 1 + 0x6f => { #PH (ZS7) + Name => 'Landmark', # (Landmark) + Groups => { 2 => 'Location' }, + Format => 'string', + Writable => 'undef', # (Count 128) + }, + 0x70 => { #PH (ZS7) + Name => 'IntelligentResolution', + Writable => 'int8u', + PrintConv => { + 0 => 'Off', + # Note: I think these values make sense for the GH2, but meanings + # may be different for other models + 1 => 'Low', + 2 => 'Standard', + 3 => 'High', + 4 => 'Extended', + }, + }, + # 0x71 - undef[128] (maybe text stamp text?) + 0x77 => { #18 + Name => 'BurstSpeed', + Writable => 'int16u', + Notes => 'images per second', + }, + # 0x72,0x73,0x74,0x75,0x77,0x78: 0 + # 0x76: 0, (3 for G6 with HDR on, ref 18) + 0x76 => { #18/21 + Name => 'HDRShot', + Writable => 'int16u', + PrintConv => { 0 => 'Off', 3 => 'On' }, + }, + 0x79 => { #PH (GH2) + Name => 'IntelligentD-Range', + Writable => 'int16u', + PrintConv => { + 0 => 'Off', + 1 => 'Low', + 2 => 'Standard', + 3 => 'High', + }, + }, + # 0x7a,0x7b: 0 + 0x7c => { #18 + Name => 'ClearRetouch', + Writable => 'int16u', + PrintConv => { 0 => 'Off', 1 => 'On' }, + }, + 0x80 => { #forum5997 (seen garbage here for SZ5 - PH) + Name => 'City2', # (City/Town/Village) + Groups => { 2 => 'Location' }, + Format => 'string', + Writable => 'undef', # (Count 72) + Notes => 'City/Town/Village as stored by some models', + }, + # 0x81 - undef[72]: "---" + # 0x82 - undef[72]: "---" + # 0x83 - undef[72]: "---" + # 0x84 - undef[72]: "---" + # 0x85 - undef[128]: "---" + 0x86 => { #http://dev.exiv2.org/issues/825 + Name => 'ManometerPressure', + Writable => 'int16u', + RawConv => '$val==65535 ? undef : $val', + ValueConv => '$val / 10', + ValueConvInv => '$val * 10', + PrintConv => 'sprintf("%.1f kPa",$val)', + PrintConvInv => '$val=~s/ ?kPa//i; $val', + }, + 0x89 => { + Name => 'PhotoStyle', + Writable => 'int16u', + PrintConv => { + 0 => 'Auto', + 1 => 'Standard or Custom', + 2 => 'Vivid', + 3 => 'Natural', + 4 => 'Monochrome', + 5 => 'Scenery', + 6 => 'Portrait', + }, + }, + 0x8a => { #18 + Name => 'ShadingCompensation', + Writable => 'int16u', + PrintConv => { + 0 => 'Off', + 1 => 'On' + } + }, + 0x8b => { #21 + Name => 'WBShiftIntelligentAuto', + Writable => 'int16u', + Format => 'int16s', + Notes => 'value is -9 for blue to +9 for amber. Valid for Intelligent-Auto modes', + }, + 0x8c => { + Name => 'AccelerometerZ', + Writable => 'int16u', + Format => 'int16s', + Notes => 'positive is acceleration upwards', + }, + 0x8d => { + Name => 'AccelerometerX', + Writable => 'int16u', + Format => 'int16s', + Notes => 'positive is acceleration to the left', + }, + 0x8e => { + Name => 'AccelerometerY', + Writable => 'int16u', + Format => 'int16s', + Notes => 'positive is acceleration backwards', + }, + 0x8f => { #18 + Name => 'CameraOrientation', + Writable => 'int8u', + PrintConv => { + 0 => 'Normal', + 1 => 'Rotate CW', + 2 => 'Rotate 180', + 3 => 'Rotate CCW', + 4 => 'Tilt Upwards', + 5 => 'Tilt Downwards' + } + }, + 0x90 => { + Name => 'RollAngle', + Writable => 'int16u', + Format => 'int16s', + Notes => 'converted to degrees of clockwise camera rotation', + ValueConv => '$val / 10', + ValueConvInv => '$val * 10', + }, + 0x91 => { + Name => 'PitchAngle', + Writable => 'int16u', + Format => 'int16s', + Notes => 'converted to degrees of upward camera tilt', + ValueConv => '-$val / 10', + ValueConvInv => '-$val * 10', + }, + 0x92 => { #21 (forum9453) + Name => 'WBShiftCreativeControl', + Writable => 'int8u', + Format => 'int8s', + Notes => 'WB shift or style strength. Valid for Creative-Control modes', + }, + 0x93 => { #18 + Name => 'SweepPanoramaDirection', + Writable => 'int8u', + PrintConv => { + 0 => 'Off', + 1 => 'Left to Right', + 2 => 'Right to Left', + 3 => 'Top to Bottom', + 4 => 'Bottom to Top' + } + }, + 0x94 => { #18 + Name => 'SweepPanoramaFieldOfView', + Writable => 'int16u' + }, + 0x96 => { #18 + Name => 'TimerRecording', + Writable => 'int8u', + PrintConv => { + 0 => 'Off', + 1 => 'Time Lapse', + 2 => 'Stop-motion Animation', + }, + }, + 0x9d => { #18 + Name => 'InternalNDFilter', + Writable => 'rational64u' + }, + 0x9e => { #18 + Name => 'HDR', + Writable => 'int16u', + PrintConv => { + 0 => 'Off', + 100 => '1 EV', + 200 => '2 EV', + 300 => '3 EV', + 32868 => '1 EV (Auto)', + 32968 => '2 EV (Auto)', + 33068 => '3 EV (Auto)', + }, + }, + 0x9f => { #18 + Name => 'ShutterType', + Writable => 'int16u', + PrintConv => { + 0 => 'Mechanical', + 1 => 'Electronic', + 2 => 'Hybrid', #PH (GM1, 1st curtain electronic, 2nd curtain mechanical) + }, + }, + # 0xa0 - undef[32]: AWB gains and black levels (ref forum9303) + 0xa3 => { #18 + Name => 'ClearRetouchValue', + Writable => 'rational64u', + # undef if ClearRetouch is off, 0 if it is on + }, + 0xa7 => { #forum9374 (conversion table for 14- to 16-bit mapping) + Name => 'OutputLUT', + Binary => 1, + Notes => q{ + 2-column by 432-row binary lookup table of unsigned short values for + converting to 16-bit output (1st column) from 14 bits (2nd column) with + camera contrast + }, + }, + 0xab => { #18 + Name => 'TouchAE', + Writable => 'int16u', + PrintConv => { 0 => 'Off', 1 => 'On' }, + }, + 0xad => { #forum9360 + Name => 'HighlightShadow', + Writable => 'int16u', + Count => 2, + }, + 0xaf => { #PH (is this in UTC maybe? -- sometimes different time zone other times) + Name => 'TimeStamp', + Writable => 'string', + Groups => { 2 => 'Time' }, + Shift => 'Time', + PrintConv => '$self->ConvertDateTime($val)', + PrintConvInv => '$self->InverseDateTime($val)', + }, + 0xb4 => { #forum9429 + Name => 'MultiExposure', + Writable => 'int16u', + PrintConv => { 0 => 'n/a', 1 => 'Off', 2 => 'On' }, + }, + 0xb9 => { #forum9425 + Name => 'RedEyeRemoval', + Writable => 'int16u', + PrintConv => { 0 => 'Off', 1 => 'On' }, + }, + 0xbb => { #forum9282 + Name => 'VideoBurstMode', + Writable => 'int32u', + PrintHex => 1, + PrintConv => { + 0x01 => 'Off', + 0x04 => 'Post Focus', + 0x18 => '4K Burst', + 0x28 => '4K Burst (Start/Stop)', + 0x48 => '4K Pre-burst', + 0x108 => 'Loop Recording', + }, + }, + 0xbc => { #forum9282 + Name => 'DiffractionCorrection', + Writable => 'int16u', + PrintConv => { 0 => 'Off', 1 => 'Auto' }, + }, + 0x0e00 => { + Name => 'PrintIM', + Description => 'Print Image Matching', + Writable => 0, + SubDirectory => { TagTable => 'Image::ExifTool::PrintIM::Main' }, + }, + 0x2003 => { #21 + Name => 'TimeInfo', + SubDirectory => { TagTable => 'Image::ExifTool::Panasonic::TimeInfo' }, + }, + 0x8000 => { #PH + Name => 'MakerNoteVersion', + Format => 'undef', + }, + 0x8001 => { #7/PH/JD + Name => 'SceneMode', + Writable => 'int16u', + PrintConvColumns => 2, + PrintConv => { + 0 => 'Off', + %shootingMode, + }, + }, + 0x8002 => { #21 + Name => 'HighlightWarning', + Writable => 'int16u', + PrintConv => { 0 => 'Disabled', 1 => 'No', 2 => 'Yes' }, + }, + 0x8003 => { #21 + Name => 'DarkFocusEnvironment', + Writable => 'int16u', + PrintConv => { 1 => 'No', 2 => 'Yes' }, + }, + 0x8004 => { #PH/JD + Name => 'WBRedLevel', + Writable => 'int16u', + }, + 0x8005 => { #PH/JD + Name => 'WBGreenLevel', + Writable => 'int16u', + }, + 0x8006 => { #PH/JD + Name => 'WBBlueLevel', + Writable => 'int16u', + }, + #0x8007 => { #PH - questionable [disabled because it conflicts with EXIF in too many samples] + # Name => 'FlashFired', + # Writable => 'int16u', + # PrintConv => { 0 => 'Yes', 1 => 'No' }, + #}, + 0x8008 => { #PH (TZ5/FS7) + # (tags 0x3b, 0x3e, 0x8008 and 0x8009 have the same values in all my samples - PH) + Name => 'TextStamp', + Writable => 'int16u', + PrintConv => { 1 => 'Off', 2 => 'On' }, + }, + 0x8009 => { #PH (TZ5/FS7) + # (tags 0x3b, 0x3e, 0x8008 and 0x8009 have the same values in all my samples - PH) + Name => 'TextStamp', + Writable => 'int16u', + PrintConv => { 1 => 'Off', 2 => 'On' }, + }, + 0x8010 => { #PH + Name => 'BabyAge', + Writable => 'string', + Notes => 'or pet age', + PrintConv => '$val eq "9999:99:99 00:00:00" ? "(not set)" : $val', + PrintConvInv => '$val =~ /^\d/ ? $val : "9999:99:99 00:00:00"', + }, + 0x8012 => { #PH (FS7) + Name => 'Transform', + Writable => 'undef', + Notes => 'decoded as two 16-bit signed integers', + Format => 'int16s', + Count => 2, + PrintConv => { + '-3 2' => 'Slim High', + '-1 1' => 'Slim Low', + '0 0' => 'Off', + '1 1' => 'Stretch Low', + '3 2' => 'Stretch High', + }, + }, +); + +# Leica type2 maker notes (ref 10) +%Image::ExifTool::Panasonic::Leica2 = ( + WRITE_PROC => \&Image::ExifTool::Exif::WriteExif, + CHECK_PROC => \&Image::ExifTool::Exif::CheckExif, + GROUPS => { 0 => 'MakerNotes', 1 => 'Leica', 2 => 'Camera' }, + WRITABLE => 1, + NOTES => 'These tags are used by the Leica M8.', + 0x300 => { + Name => 'Quality', + Writable => 'int16u', + PrintConv => { + 1 => 'Fine', + 2 => 'Basic', + }, + }, + 0x302 => { + Name => 'UserProfile', + Writable => 'int32u', + PrintConv => { + 1 => 'User Profile 1', + 2 => 'User Profile 2', + 3 => 'User Profile 3', + 4 => 'User Profile 0 (Dynamic)', + }, + }, + 0x303 => { + Name => 'SerialNumber', + Writable => 'int32u', + PrintConv => 'sprintf("%.7d", $val)', + PrintConvInv => '$val', + }, + 0x304 => { + Name => 'WhiteBalance', + Writable => 'int16u', + Notes => 'values above 0x8000 are converted to Kelvin color temperatures', + PrintConv => { + 0 => 'Auto or Manual', + 1 => 'Daylight', + 2 => 'Fluorescent', + 3 => 'Tungsten', + 4 => 'Flash', + 10 => 'Cloudy', + 11 => 'Shade', + OTHER => \&WhiteBalanceConv, + }, + }, + 0x310 => { + Name => 'LensType', + Writable => 'int32u', + SeparateTable => 1, + ValueConv => '($val >> 2) . " " . ($val & 0x3)', + ValueConvInv => \&LensTypeConvInv, + PrintConv => \%leicaLensTypes, + }, + 0x311 => { + Name => 'ExternalSensorBrightnessValue', + Format => 'rational64s', # (incorrectly unsigned in JPEG images) + Writable => 'rational64s', + Notes => '"blue dot" measurement', + PrintConv => 'sprintf("%.2f", $val)', + PrintConvInv => '$val', + }, + 0x312 => { + Name => 'MeasuredLV', + Format => 'rational64s', # (incorrectly unsigned in JPEG images) + Writable => 'rational64s', + Notes => 'imaging sensor or TTL exposure meter measurement', + PrintConv => 'sprintf("%.2f", $val)', + PrintConvInv => '$val', + }, + 0x313 => { + Name => 'ApproximateFNumber', + Writable => 'rational64u', + PrintConv => 'sprintf("%.1f", $val)', + PrintConvInv => '$val', + }, + 0x320 => { + Name => 'CameraTemperature', + Writable => 'int32s', + PrintConv => '"$val C"', + PrintConvInv => '$val=~s/ ?C//; $val', + }, + 0x321 => { Name => 'ColorTemperature', Writable => 'int32u' }, + 0x322 => { Name => 'WBRedLevel', Writable => 'rational64u' }, + 0x323 => { Name => 'WBGreenLevel', Writable => 'rational64u' }, + 0x324 => { Name => 'WBBlueLevel', Writable => 'rational64u' }, + 0x325 => { + Name => 'UV-IRFilterCorrection', + Description => 'UV/IR Filter Correction', + Writable => 'int32u', + PrintConv => { + 0 => 'Not Active', + 1 => 'Active', + }, + }, + 0x330 => { Name => 'CCDVersion', Writable => 'int32u' }, + 0x331 => { Name => 'CCDBoardVersion', Writable => 'int32u' }, + 0x332 => { Name => 'ControllerBoardVersion', Writable => 'int32u' }, + 0x333 => { Name => 'M16CVersion', Writable => 'int32u' }, + 0x340 => { Name => 'ImageIDNumber', Writable => 'int32u' }, +); + +# Leica type3 maker notes (ref PH) +%Image::ExifTool::Panasonic::Leica3 = ( + WRITE_PROC => \&Image::ExifTool::Exif::WriteExif, + CHECK_PROC => \&Image::ExifTool::Exif::CheckExif, + GROUPS => { 0 => 'MakerNotes', 1 => 'Leica', 2 => 'Camera' }, + WRITABLE => 1, + NOTES => 'These tags are used by the Leica R8 and R9 digital backs.', + 0x0b => { #IB + Name => 'SerialInfo', + SubDirectory => { TagTable => 'Image::ExifTool::Panasonic::SerialInfo' }, + }, + 0x0d => { + Name => 'WB_RGBLevels', + Writable => 'int16u', + Count => 3, + }, +); + +# Leica serial number info (ref IB) +%Image::ExifTool::Panasonic::SerialInfo = ( + PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData, + GROUPS => { 0 => 'MakerNotes', 1 => 'Leica', 2 => 'Camera' }, + TAG_PREFIX => 'Leica_SerialInfo', + FIRST_ENTRY => 0, + 4 => { + Name => 'SerialNumber', + Format => 'string[8]', + } +); + +# Leica type4 maker notes (ref PH) (M9) +%Image::ExifTool::Panasonic::Leica4 = ( + WRITE_PROC => \&Image::ExifTool::Exif::WriteExif, + CHECK_PROC => \&Image::ExifTool::Exif::CheckExif, + GROUPS => { 0 => 'MakerNotes', 1 => 'Leica', 2 => 'Camera' }, + WRITABLE => 1, + NOTES => 'This information is written by the M9.', + 0x3000 => { + Name => 'Subdir3000', + SubDirectory => { + TagTable => 'Image::ExifTool::Panasonic::Subdir', + ByteOrder => 'Unknown', + }, + }, + 0x3100 => { + Name => 'Subdir3100', + SubDirectory => { + TagTable => 'Image::ExifTool::Panasonic::Subdir', + ByteOrder => 'Unknown', + }, + }, + 0x3400 => { + Name => 'Subdir3400', + SubDirectory => { + TagTable => 'Image::ExifTool::Panasonic::Subdir', + ByteOrder => 'Unknown', + }, + }, + 0x3900 => { + Name => 'Subdir3900', + SubDirectory => { + TagTable => 'Image::ExifTool::Panasonic::Subdir', + ByteOrder => 'Unknown', + }, + }, +); + +# Leica M9 SubDirectory tags (ref PH) +%Image::ExifTool::Panasonic::Subdir = ( + WRITE_PROC => \&Image::ExifTool::Exif::WriteExif, + CHECK_PROC => \&Image::ExifTool::Exif::CheckExif, + GROUPS => { 0 => 'MakerNotes', 1 => 'Leica', 2 => 'Camera' }, + TAG_PREFIX => 'Leica_Subdir', + WRITABLE => 1, + # 0x3001 - normally 0 but value of 2 when manual coding is used + # with a coded lens (but only tested with Elmar-M 50mm f/2.8) - PH + 0x300a => { + Name => 'Contrast', + Writable => 'int32u', + PrintConv => { + 0 => 'Low', + 1 => 'Medium Low', + 2 => 'Normal', + 3 => 'Medium High', + 4 => 'High', + }, + }, + 0x300b => { + Name => 'Sharpening', + Writable => 'int32u', + PrintConv => { + 0 => 'Off', + 1 => 'Low', + 2 => 'Normal', + 3 => 'Medium High', + 4 => 'High', + }, + }, + 0x300d => { + Name => 'Saturation', + Writable => 'int32u', + PrintConv => { + 0 => 'Low', + 1 => 'Medium Low', + 2 => 'Normal', + 3 => 'Medium High', + 4 => 'High', + 5 => 'Black & White', + 6 => 'Vintage B&W', + }, + }, + # 0x3032 - some sort of RGB coefficients? (zeros unless Kelvin WB, but same for all Color Temps) + 0x3033 => { + Name => 'WhiteBalance', + Writable => 'int32u', + PrintConv => { #13 + 0 => 'Auto', + 1 => 'Tungsten', + 2 => 'Fluorescent', + 3 => 'Daylight Fluorescent', + 4 => 'Daylight', + 5 => 'Flash', + 6 => 'Cloudy', + 7 => 'Shade', + 8 => 'Manual', + 9 => 'Kelvin', + }, + }, + 0x3034 => { + Name => 'JPEGQuality', + Writable => 'int32u', + PrintConv => { + 94 => 'Basic', + 97 => 'Fine', + }, + }, + # 0x3035 (int32u): -1 unless Manual WB (2 in my Manual sample) + 0x3036 => { + Name => 'WB_RGBLevels', + Writable => 'rational64u', + Count => 3, + }, + 0x3038 => { + Name => 'UserProfile', # (CameraProfile according to ref 14) + Writable => 'string', + }, + 0x303a => { + Name => 'JPEGSize', + Writable => 'int32u', + PrintConv => { + 0 => '5216x3472', + 1 => '3840x2592', + 2 => '2592x1728', + 3 => '1728x1152', + 4 => '1280x864', + }, + }, + 0x3103 => { #13 (valid for FW 1.116 and later) + Name => 'SerialNumber', + Writable => 'string', + }, + # 0x3104 body-dependent string ("00012905000000") (not serial number) + # 0x3105 body-dependent string ("00012905000000") + # 0x3107 - body-dependent string ("4H205800116800") (not serial number) + 0x3109 => { + Name => 'FirmwareVersion', + Writable => 'string', + }, + 0x312a => { #14 (NC) + Name => 'BaseISO', + Writable => 'int32u', + }, + 0x312b => { + Name => 'SensorWidth', + Writable => 'int32u', + }, + 0x312c => { + Name => 'SensorHeight', + Writable => 'int32u', + }, + 0x312d => { #14 (NC) + Name => 'SensorBitDepth', + Writable => 'int32u', + }, + 0x3402 => { #PH/13 + Name => 'CameraTemperature', + Writable => 'int32s', + PrintConv => '"$val C"', + PrintConvInv => '$val=~s/ ?C//; $val', + }, + 0x3405 => { + Name => 'LensType', + Writable => 'int32u', + SeparateTable => 1, + ValueConv => '($val >> 2) . " " . ($val & 0x3)', + ValueConvInv => \&LensTypeConvInv, + PrintConv => \%leicaLensTypes, + }, + 0x3406 => { #PH/13 + Name => 'ApproximateFNumber', + Writable => 'rational64u', + PrintConv => 'sprintf("%.1f", $val)', + PrintConvInv => '$val', + }, + 0x3407 => { #14 + Name => 'MeasuredLV', + Writable => 'int32s', + Notes => 'imaging sensor or TTL exposure meter measurement', + ValueConv => '$val / 1e5', #PH (NC) + ValueConvInv => '$val * 1e5', #PH (NC) + PrintConv => 'sprintf("%.2f", $val)', + PrintConvInv => '$val', + }, + 0x3408 => { #14 + Name => 'ExternalSensorBrightnessValue', + Writable => 'int32s', + Notes => '"blue dot" measurement', + ValueConv => '$val / 1e5', #PH (NC) + ValueConvInv => '$val * 1e5', #PH (NC) + PrintConv => 'sprintf("%.2f", $val)', + PrintConvInv => '$val', + }, + 0x3901 => { + Name => 'Data1', + SubDirectory => { TagTable => 'Image::ExifTool::Panasonic::Data1' }, + }, + 0x3902 => { + Name => 'Data2', + SubDirectory => { TagTable => 'Image::ExifTool::Panasonic::Data2' }, + }, + # 0x3903 - larger binary data block +); + +# time stamp information (ref 21) +%Image::ExifTool::Panasonic::TimeInfo = ( + PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData, + WRITE_PROC => \&Image::ExifTool::WriteBinaryData, + CHECK_PROC => \&Image::ExifTool::CheckBinaryData, + GROUPS => { 0 => 'MakerNotes', 1 => 'Panasonic', 2 => 'Image' }, + FIRST_ENTRY => 0, + WRITABLE => 1, + 0 => { + Name => 'PanasonicDateTime', + Groups => { 2 => 'Time' }, + Shift => 'Time', + Format => 'undef[8]', + RawConv => '$val =~ /^\0/ ? undef : $val', + ValueConv => 'sprintf("%s:%s:%s %s:%s:%s.%s", unpack "H4H2H2H2H2H2H2", $val)', + ValueConvInv => q{ + $val =~ s/[-+].*//; # remove time zone + $val =~ tr/0-9//dc; # remove non-digits + $val = pack("H*",$val); + $val .= "\0" while length $val < 8; + return $val; + }, + PrintConv => '$self->ConvertDateTime($val)', + PrintConvInv => '$self->InverseDateTime($val)', + }, + # 8 - 8 bytes usually 8 x 0xff (spot for another date/time?) + 16 => { + Name => 'TimeLapseShotNumber', + Format => 'int32u', + }, +); + +%Image::ExifTool::Panasonic::Data1 = ( + PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData, + WRITE_PROC => \&Image::ExifTool::WriteBinaryData, + CHECK_PROC => \&Image::ExifTool::CheckBinaryData, + GROUPS => { 0 => 'MakerNotes', 1 => 'Leica', 2 => 'Camera' }, + WRITABLE => 1, + TAG_PREFIX => 'Leica_Data1', + FIRST_ENTRY => 0, + 0x0016 => { + Name => 'LensType', + Format => 'int32u', + Priority => 0, + SeparateTable => 1, + ValueConv => '(($val >> 2) & 0xffff) . " " . ($val & 0x3)', + ValueConvInv => \&LensTypeConvInv, + PrintConv => \%leicaLensTypes, + }, +); + +%Image::ExifTool::Panasonic::Data2 = ( + PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData, + GROUPS => { 0 => 'MakerNotes', 1 => 'Leica', 2 => 'Camera' }, + TAG_PREFIX => 'Leica_Data2', + FIRST_ENTRY => 0, +); + +# Leica type5 maker notes (ref PH) (X1) +%Image::ExifTool::Panasonic::Leica5 = ( + WRITE_PROC => \&Image::ExifTool::Exif::WriteExif, + CHECK_PROC => \&Image::ExifTool::Exif::CheckExif, + GROUPS => { 0 => 'MakerNotes', 1 => 'Leica', 2 => 'Camera' }, + WRITABLE => 1, + PRIORITY => 0, + NOTES => 'This information is written by the X1, X2, X VARIO and T.', + 0x0303 => { + Name => 'LensType', + Condition => '$format eq "string"', + Notes => 'Leica T only', + Writable => 'string', + }, + # 0x0304 - int8u[1]: may be M-lens ID for Leica SL, mounted through "M-adapter L" (ref IB) + # --> int8u[4] for some models (maybe not lens ID for these?) - PH + # (see http://us.leica-camera.com/Photography/Leica-APS-C/Lenses-for-Leica-TL/L-Adapters/M-Adapter-L) + # 58 = 'Leica Noctilux-M 75mm F1.25 ASPH (Typ 601) on Leica SL + 0x0305 => { #IB + Name => 'SerialNumber', + Writable => 'int32u', + }, + # 0x0406 - saturation or sharpness + 0x0407 => { Name => 'OriginalFileName', Writable => 'string' }, + 0x0408 => { Name => 'OriginalDirectory',Writable => 'string' }, + 0x040a => { #IB + Name => 'FocusInfo', + SubDirectory => { TagTable => 'Image::ExifTool::Panasonic::FocusInfo' }, + }, + # 0x040b - related to white balance + 0x040d => { + Name => 'ExposureMode', + Format => 'int8u', + Count => 4, + PrintConv => { + '0 0 0 0' => 'Program AE', + # '0 1 0 0' - seen for X (Typ 113) - PH + '1 0 0 0' => 'Aperture-priority AE', + '1 1 0 0' => 'Aperture-priority AE (1)', # (see for Leica T) + '2 0 0 0' => 'Shutter speed priority AE', #(guess) + '3 0 0 0' => 'Manual', + }, + }, + 0x0410 => { + Name => 'ShotInfo', + SubDirectory => { TagTable => 'Image::ExifTool::Panasonic::ShotInfo' }, + }, + # 0x0410 - int8u[16]: first byte is FileNumber + # 0x0411 - int8u[4]: first number is FilmMode (1=Standard,2=Vivid,3=Natural,4=BW Natural,5=BW High Contrast) + 0x0412 => { Name => 'FilmMode', Writable => 'string' }, + 0x0413 => { Name => 'WB_RGBLevels', Writable => 'rational64u', Count => 3 }, + 0x0500 => { + Name => 'InternalSerialNumber', + Writable => 'undef', + PrintConv => q{ + return $val unless $val=~/^(.{3})(\d{2})(\d{2})(\d{2})(\d{4})/; + my $yr = $2 + ($2 < 70 ? 2000 : 1900); + return "($1) $yr:$3:$4 no. $5"; + }, + PrintConvInv => '$_=$val; tr/A-Z0-9//dc; s/(.{3})(19|20)/$1/; $_', + }, +); + +# Leica type5 ShotInfo (ref PH) (X2) +%Image::ExifTool::Panasonic::ShotInfo = ( + PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData, + WRITE_PROC => \&Image::ExifTool::WriteBinaryData, + CHECK_PROC => \&Image::ExifTool::CheckBinaryData, + GROUPS => { 0 => 'MakerNotes', 1 => 'Leica', 2 => 'Camera' }, + TAG_PREFIX => 'Leica_ShotInfo', + FIRST_ENTRY => 0, + WRITABLE => 1, + 0 => { + Name => 'FileIndex', + Format => 'int16u', + }, +); + +# Leica type5 FocusInfo (ref IB) +%Image::ExifTool::Panasonic::FocusInfo = ( + PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData, + WRITE_PROC => \&Image::ExifTool::WriteBinaryData, + CHECK_PROC => \&Image::ExifTool::CheckBinaryData, + GROUPS => { 0 => 'MakerNotes', 1 => 'Leica', 2 => 'Camera' }, + TAG_PREFIX => 'Leica_FocusInfo', + FIRST_ENTRY => 0, + WRITABLE => 1, + FORMAT => 'int16u', + 0 => { + Name => 'FocusDistance', + ValueConv => '$val / 1000', + ValueConvInv => '$val * 1000', + PrintConv => '$val < 65535 ? "$val m" : "inf"', + PrintConvInv => '$val =~ s/ ?m$//; IsFloat($val) ? $val : 65535', + }, + 1 => { + Name => 'FocalLength', + Priority => 0, + RawConv => '$val ? $val : undef', + ValueConv => '$val / 1000', + ValueConvInv => '$val * 1000', + PrintConv => 'sprintf("%.1f mm",$val)', + PrintConvInv => '$val=~s/\s*mm$//;$val', + }, +); + +# Leica type6 maker notes (ref PH) (S2) +%Image::ExifTool::Panasonic::Leica6 = ( + WRITE_PROC => \&Image::ExifTool::Exif::WriteExif, + CHECK_PROC => \&Image::ExifTool::Exif::CheckExif, + GROUPS => { 0 => 'MakerNotes', 1 => 'Leica', 2 => 'Camera' }, + NOTES => q{ + This information is written by the S2 and M (Typ 240), as a trailer in JPEG + images. + }, + 0x300 => { + Name => 'PreviewImage', + Groups => { 2 => 'Preview' }, + Writable => 'undef', + Notes => 'S2 and M (Typ 240)', + DataTag => 'PreviewImage', + RawConv => q{ + return \$val if $val =~ /^Binary/; + return \$val if $val =~ /^\xff\xd8\xff/; + $$self{PreviewError} = 1 unless $val eq 'none'; + return undef; + }, + ValueConvInv => '$val || "none"', + WriteCheck => 'return $val=~/^(none|\xff\xd8\xff)/s ? undef : "Not a valid image"', + ChangeBase => '$dirStart + $dataPos - 8', + }, + 0x301 => { + Name => 'UnknownBlock', + Notes => 'unknown 320kB block, not copied to JPEG images', + Flags => [ 'Unknown', 'Binary', 'Drop' ], + }, + # 0x302 - same value as 4 unknown bytes at the end of JPEG or after the DNG TIFF header (ImageID, ref IB) + 0x303 => { + Name => 'LensType', + Writable => 'string', + ValueConv => '$val=~s/ +$//; $val', # trim trailing spaces + ValueConvInv => '$val', + }, + 0x304 => { #IB + Name => 'FocusDistance', + Notes => 'focus distance in mm for most models, but cm for others', + Writable => 'int32u', + }, + 0x311 => { + Name => 'ExternalSensorBrightnessValue', + Condition => '$$self{Model} =~ /Typ 006/', + Notes => 'Leica S only', + Format => 'rational64s', # (may be incorrectly unsigned in JPEG images) + Writable => 'rational64s', + PrintConv => 'sprintf("%.2f", $val)', + PrintConvInv => '$val', + }, + 0x312 => { + Name => 'MeasuredLV', + Condition => '$$self{Model} =~ /Typ 006/', + Notes => 'Leica S only', + Format => 'rational64s', # (may be incorrectly unsigned in JPEG images) + Writable => 'rational64s', + PrintConv => 'sprintf("%.2f", $val)', + PrintConvInv => '$val', + }, + 0x320 => { + Name => 'FirmwareVersion', + Condition => '$$self{Model} =~ /Typ 006/', + Notes => 'Leica S only', + Writable => 'int8u', + Count => 4, + PrintConv => '$val=~tr/ /./; $val', + PrintConvInv => '$val=~tr/./ /; $val', + }, + 0x321 => { #IB + Name => 'LensSerialNumber', + Condition => '$$self{Model} =~ /Typ 006/', + Notes => 'Leica S only', + Writable => 'int32u', + PrintConv => 'sprintf("%.10d",$val)', + PrintConvInv => '$val', + }, + # 0x321 - SerialNumber for Leica S? (ref IB) + # 0x340 - same as 0x302 (ImageID, ref IB) +); + +# Leica type9 maker notes (ref IB) (S) +%Image::ExifTool::Panasonic::Leica9 = ( + WRITE_PROC => \&Image::ExifTool::Exif::WriteExif, + CHECK_PROC => \&Image::ExifTool::Exif::CheckExif, + GROUPS => { 0 => 'MakerNotes', 1 => 'Leica', 2 => 'Camera' }, + NOTES => 'This information is written by the Leica S (Typ 007).', + 0x304 => { + Name => 'FocusDistance', + Notes => 'focus distance in mm for most models, but cm for others', + Writable => 'int32u', + }, + 0x311 => { + Name => 'ExternalSensorBrightnessValue', + Format => 'rational64s', # (may be incorrectly unsigned in JPEG images) + Writable => 'rational64s', + PrintConv => 'sprintf("%.2f", $val)', + PrintConvInv => '$val', + }, + 0x312 => { + Name => 'MeasuredLV', + Format => 'rational64s', # (may be incorrectly unsigned in JPEG images) + Writable => 'rational64s', + PrintConv => 'sprintf("%.2f", $val)', + PrintConvInv => '$val', + }, + # 0x340 - ImageUniqueID +); + +# Type 2 tags (ref PH) +%Image::ExifTool::Panasonic::Type2 = ( + PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData, + GROUPS => { 0 => 'MakerNotes', 2 => 'Image' }, + FIRST_ENTRY => 0, + FORMAT => 'int16u', + NOTES => q{ + This type of maker notes is used by models such as the NV-DS65, PV-D2002, + PV-DC3000, PV-DV203, PV-DV401, PV-DV702, PV-L2001, PV-SD4090, PV-SD5000 and + iPalm. + }, + 0 => { + Name => 'MakerNoteType', + Format => 'string[4]', + }, + # seems to vary inversely with amount of light, so I'll call it 'Gain' - PH + # (minimum is 16, maximum is 136. Value is 0 for pictures captured from video) + 3 => 'Gain', +); + +# Face detection position information (ref PH) +%Image::ExifTool::Panasonic::FaceDetInfo = ( + PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData, + WRITE_PROC => \&Image::ExifTool::WriteBinaryData, + CHECK_PROC => \&Image::ExifTool::CheckBinaryData, + GROUPS => { 0 => 'MakerNotes', 2 => 'Image' }, + WRITABLE => 1, + FORMAT => 'int16u', + FIRST_ENTRY => 0, + DATAMEMBER => [ 0 ], + NOTES => 'Face detection position information.', + 0 => { + Name => 'NumFacePositions', + Format => 'int16u', + DataMember => 'NumFacePositions', + RawConv => '$$self{NumFacePositions} = $val', + Notes => q{ + number of detected face positions stored in this record. May be less than + FacesDetected + }, + }, + 1 => { + Name => 'Face1Position', + Format => 'int16u[4]', + RawConv => '$$self{NumFacePositions} < 1 ? undef : $val', + Notes => q{ + 4 numbers: X/Y coordinates of the face center and width/height of face. + Coordinates are relative to an image twice the size of the thumbnail, or 320 + pixels wide + }, + }, + 5 => { + Name => 'Face2Position', + Format => 'int16u[4]', + RawConv => '$$self{NumFacePositions} < 2 ? undef : $val', + }, + 9 => { + Name => 'Face3Position', + Format => 'int16u[4]', + RawConv => '$$self{NumFacePositions} < 3 ? undef : $val', + }, + 13 => { + Name => 'Face4Position', + Format => 'int16u[4]', + RawConv => '$$self{NumFacePositions} < 4 ? undef : $val', + }, + 17 => { + Name => 'Face5Position', + Format => 'int16u[4]', + RawConv => '$$self{NumFacePositions} < 5 ? undef : $val', + }, +); + +# Face recognition information from DMC-TZ7 (ref PH) +%Image::ExifTool::Panasonic::FaceRecInfo = ( + PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData, + WRITE_PROC => \&Image::ExifTool::WriteBinaryData, + CHECK_PROC => \&Image::ExifTool::CheckBinaryData, + GROUPS => { 0 => 'MakerNotes', 2 => 'Image' }, + WRITABLE => 1, + FIRST_ENTRY => 0, + DATAMEMBER => [ 0 ], + NOTES => q{ + Tags written by cameras with facial recognition. These cameras not only + detect faces in an image, but also recognize specific people based a + user-supplied set of known faces. + }, + 0 => { + Name => 'FacesRecognized', + Format => 'int16u', + DataMember => 'FacesRecognized', + RawConv => '$$self{FacesRecognized} = $val', + }, + 4 => { + Name => 'RecognizedFace1Name', + Format => 'string[20]', + RawConv => '$$self{FacesRecognized} < 1 ? undef : $val', + }, + 24 => { + Name => 'RecognizedFace1Position', + Format => 'int16u[4]', + RawConv => '$$self{FacesRecognized} < 1 ? undef : $val', + Notes => 'coordinates in same format as face detection tags above', + }, + 32 => { + Name => 'RecognizedFace1Age', + Format => 'string[20]', + RawConv => '$$self{FacesRecognized} < 1 ? undef : $val', + }, + 52 => { + Name => 'RecognizedFace2Name', + Format => 'string[20]', + RawConv => '$$self{FacesRecognized} < 2 ? undef : $val', + }, + 72 => { + Name => 'RecognizedFace2Position', + Format => 'int16u[4]', + RawConv => '$$self{FacesRecognized} < 2 ? undef : $val', + }, + 80 => { + Name => 'RecognizedFace2Age', + Format => 'string[20]', + RawConv => '$$self{FacesRecognized} < 2 ? undef : $val', + }, + 100 => { + Name => 'RecognizedFace3Name', + Format => 'string[20]', + RawConv => '$$self{FacesRecognized} < 3 ? undef : $val', + }, + 120 => { + Name => 'RecognizedFace3Position', + Format => 'int16u[4]', + RawConv => '$$self{FacesRecognized} < 3 ? undef : $val', + }, + 128 => { + Name => 'RecognizedFace3Age', + Format => 'string[20]', + RawConv => '$$self{FacesRecognized} < 3 ? undef : $val', + }, +); + +# PANA atom found in user data of MP4 videos (ref PH) +%Image::ExifTool::Panasonic::PANA = ( + PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData, + GROUPS => { 0 => 'MakerNotes', 2 => 'Image' }, + NOTES => q{ + Tags extracted from the PANA and LEIC user data found in MP4 videos from + various Panasonic and Leica models. + }, + 0x00 => { + Name => 'Make', + Condition => '$$valPt =~ /^(LEICA|Panasonic)/', # (only seen "LEICA") + Groups => { 2 => 'Camera' }, + Format => 'string[22]', + RawConv => '$$self{LeicaLEIC} = 1;$$self{Make} = $val', + }, + 0x04 => { + Name => 'Model', + Condition => '$$valPt =~ /^[^\0]{6}/ and not $$self{LeicaLEIC}', + Description => 'Camera Model Name', + Groups => { 2 => 'Camera' }, + Format => 'string[16]', + RawConv => '$$self{Model} = $val', + }, + 0x0c => { # (FZ1000) + Name => 'Model', + Condition => '$$valPt =~ /^[^\0]{6}/ and not $$self{LeicaLEIC} and not $$self{Model}', + Description => 'Camera Model Name', + Groups => { 2 => 'Camera' }, + Format => 'string[16]', + RawConv => '$$self{Model} = $val', + }, + 0x10 => { # (DC-FT7) + Name => 'JPEG-likeData', + # looks like a JPEG preview, but not a well-formed JPEG file + Condition => '$$valPt =~ /^\xff\xd8\xff\xe1..Exif\0\0/s', + Format => 'undef[$size-0x10]', + SubDirectory => { + TagTable => 'Image::ExifTool::Exif::Main', + ProcessProc => \&Image::ExifTool::ProcessTIFF, + Start => 12, + }, + }, + 0x16 => { + Name => 'Model', + Condition => '$$self{LeicaLEIC}', + Description => 'Camera Model Name', + Groups => { 2 => 'Camera' }, + Format => 'string[30]', + RawConv => '$$self{Model} = $val', + }, + 0x40 => { + Name => 'ThumbnailTest', + Format => 'undef[0x600]', + Hidden => 1, + RawConv => q{ + if (substr($val,0x1c,3) eq "\xff\xd8\xff") { # offset 0x5c + $$self{ThumbType} = 1; + } elsif (substr($val,0x506,3) eq "\xff\xd8\xff") { # offset 0x546 + $$self{ThumbType} = 2; + } elsif (substr($val,0x51e,3) eq "\xff\xd8\xff") { # offset 0x55e (Leica T) + $$self{ThumbType} = 3; + } else { + $$self{ThumbType} = 0; + } + return undef; + }, + }, + 0x34 => { + Name => 'Version1', + Condition => '$$self{LeicaLEIC}', + Format => 'string[14]', + }, + 0x3e => { + Name => 'Version2', + Condition => '$$self{LeicaLEIC}', + Format => 'string[14]', + }, + 0x50 => { + Name => 'MakerNoteLeica5', + Condition => '$$self{LeicaLEIC}', + SubDirectory => { + TagTable => 'Image::ExifTool::Panasonic::Leica5', + ProcessProc => \&ProcessLeicaLEIC, + }, + }, + 0x58 => { + Name => 'ThumbnailWidth', + Condition => '$$self{ThumbType} == 1', + Notes => 'Panasonic models', + Format => 'int16u', + }, + 0x5a => { + Name => 'ThumbnailHeight', + Condition => '$$self{ThumbType} == 1', + Format => 'int16u', + }, + 0x5c => { + Name => 'ThumbnailImage', + Condition => '$$self{ThumbType} == 1', + Groups => { 2 => 'Preview' }, + Format => 'undef[16384]', + ValueConv => '$val=~s/\0*$//; \$val', # remove trailing zeros + }, + # 0x5c - there is some messed-up EXIF-IFD-looking data starting here in + # Leica X VARIO MP4 videos, but it doesn't quite make sense + 0x536 => { # (Leica X VARIO) + Name => 'ThumbnailWidth', + Condition => '$$self{ThumbType} == 2', + Notes => 'Leica X Vario', + Format => 'int32uRev', # (little-endian) + }, + 0x53a => { # (Leica X VARIO) + Name => 'ThumbnailHeight', + Condition => '$$self{ThumbType} == 2', + Format => 'int32uRev', # (little-endian) + }, + 0x53e => { # (Leica X VARIO) + Name => 'ThumbnailLength', + Condition => '$$self{ThumbType} == 2', + Format => 'int32uRev', # (little-endian) + }, + 0x546 => { # (Leica X VARIO) + Name => 'ThumbnailImage', + Condition => '$$self{ThumbType} == 2', + Groups => { 2 => 'Preview' }, + Format => 'undef[$val{0x53e}]', + Binary => 1, + }, + 0x54e => { # (Leica T) + Name => 'ThumbnailWidth', + Condition => '$$self{ThumbType} == 3', + Notes => 'Leica X Vario', + Format => 'int32uRev', # (little-endian) + }, + 0x552 => { # (Leica T) + Name => 'ThumbnailHeight', + Condition => '$$self{ThumbType} == 3', + Format => 'int32uRev', # (little-endian) + }, + 0x556 => { # (Leica T) + Name => 'ThumbnailLength', + Condition => '$$self{ThumbType} == 3', + Format => 'int32uRev', # (little-endian) + }, + 0x55e => { # (Leica T) + Name => 'ThumbnailImage', + Condition => '$$self{ThumbType} == 3', + Groups => { 2 => 'Preview' }, + Format => 'undef[$val{0x556}]', + Binary => 1, + }, + 0x4068 => { + Name => 'ExifData', + Condition => '$$valPt =~ /^\xff\xd8\xff\xe1..Exif\0\0/s', + SubDirectory => { + TagTable => 'Image::ExifTool::Exif::Main', + ProcessProc => \&Image::ExifTool::ProcessTIFF, + Start => 12, + }, + }, + 0x4080 => { # (FZ1000) + Name => 'ExifData', + Condition => '$$valPt =~ /^\xff\xd8\xff\xe1..Exif\0\0/s', + SubDirectory => { + TagTable => 'Image::ExifTool::Exif::Main', + ProcessProc => \&Image::ExifTool::ProcessTIFF, + Start => 12, + }, + }, +); + +# Panasonic Composite tags +%Image::ExifTool::Panasonic::Composite = ( + GROUPS => { 2 => 'Camera' }, + AdvancedSceneMode => { + SeparateTable => 'Panasonic AdvancedSceneMode', # print values in a separate table + Require => { + 0 => 'Model', + 1 => 'SceneMode', + 2 => 'AdvancedSceneType', + }, + ValueConv => '"$val[0] $val[1] $val[2]"', + PrintConv => { #PH + OTHER => sub { + my ($val,$flag,$conv) = @_; + $val =~ s/.* (\d+ \d+)/$1/; # drop model name + return $$conv{$val} if $$conv{$val}; + my @v = split ' ', $val; + my $prt = $shootingMode{$v[0]}; + # AdvancedSceneType=1 for non-automatic modes P,A,S,SCN (ref 19) + # AdvancedSceneType=5 for automatic mode iA (ref 19) + if ($prt) { + return $prt if $v[1] == 1; + return "$prt (intelligent auto)" if $v[1] == 5; + return "$prt ($v[1])"; + } + return "Unknown ($val)"; + }, + Notes => 'A Composite tag derived from Model, SceneMode and AdvancedSceneType.', + '0 1' => 'Off', + # '0 7' - seen this for V-LUX movies (PH) + # '0 8' - seen for D-LUX(Typ104) movies (PH) + '2 2' => 'Outdoor Portrait', #(FZ28) + '2 3' => 'Indoor Portrait', #(FZ28) + '2 4' => 'Creative Portrait', #(FZ28) + '3 2' => 'Nature', #(FZ28) + '3 3' => 'Architecture', #(FZ28) + '3 4' => 'Creative Scenery', #(FZ28) + #'3 5' - ? (FT1) + '4 2' => 'Outdoor Sports', #(FZ28) + '4 3' => 'Indoor Sports', #(FZ28) + '4 4' => 'Creative Sports', #(FZ28) + '9 2' => 'Flower', #(FZ28) + '9 3' => 'Objects', #(FZ28) + '9 4' => 'Creative Macro', #(FZ28) + #'9 5' - ? (GF3) + '21 2' => 'Illuminations', #(FZ28) + '21 4' => 'Creative Night Scenery', #(FZ28) + #'21 5' - ? (LX3) + #'37 5' - ? (various) + '45 2' => 'Cinema', #(GF2) + '45 7' => 'Expressive', #(GF1,GF2) + '45 8' => 'Retro', #(GF1,GF2) + '45 9' => 'Pure', #(GF1,GF2) + '45 10' => 'Elegant', #(GF1,GF2) + '45 12' => 'Monochrome', #(GF1,GF2) + '45 13' => 'Dynamic Art', #(GF1,GF2) + '45 14' => 'Silhouette', #(GF1,GF2) + '51 2' => 'HDR Art', #12 + '51 3' => 'HDR B&W', #12 + '59 1' => 'Expressive', #(GF5) + '59 2' => 'Retro', #(GF5) + '59 3' => 'High Key', #(GF5) + '59 4' => 'Sepia', #(GF3,GF5) + '59 5' => 'High Dynamic', #(GF3,GF5) + '59 6' => 'Miniature', #(GF3) + '59 9' => 'Low Key', #(GF5) + '59 10' => 'Toy Effect', #(GF5) + '59 11' => 'Dynamic Monochrome', #(GF5) + '59 12' => 'Soft', #(GF5) + '66 1' => 'Impressive Art', #19 + '66 2' => 'Cross Process', #(GF5) + '66 3' => 'Color Select', #(GF5) (called "One Point Color" by some other models - PH) + '66 4' => 'Star', #(GF5) + '90 3' => 'Old Days', #18 + '90 4' => 'Sunshine', #18 + '90 5' => 'Bleach Bypass', #18 + '90 6' => 'Toy Pop', #18 + '90 7' => 'Fantasy', #18 + '90 8' => 'Monochrome', #PH (GX7) + '90 9' => 'Rough Monochrome', #PH (GX7) + '90 10' => 'Silky Monochrome', #PH (GX7) + '92 1' => 'Handheld Night Shot', #Horst Wandres (FZ1000) + # TZ40 Creative Control modes (ref 19) + 'DMC-TZ40 90 1' => 'Expressive', + 'DMC-TZ40 90 2' => 'Retro', + 'DMC-TZ40 90 3' => 'High Key', + 'DMC-TZ40 90 4' => 'Sepia', + 'DMC-TZ40 90 5' => 'High Dynamic', + 'DMC-TZ40 90 6' => 'Miniature', + 'DMC-TZ40 90 9' => 'Low Key', + 'DMC-TZ40 90 10' => 'Toy Effect', + 'DMC-TZ40 90 11' => 'Dynamic Monochrome', + 'DMC-TZ40 90 12' => 'Soft', + }, + }, +); + +# add our composite tags +Image::ExifTool::AddCompositeTags('Image::ExifTool::Panasonic'); + +#------------------------------------------------------------------------------ +# Inverse conversion for Leica M9 lens codes +# Inputs: 0) value +# Returns: Converted value, or undef on error +sub LensTypeConvInv($) +{ + my $val = shift; + if ($val =~ /^(\d+) (\d+)$/) { + return ($1 << 2) + ($2 & 0x03); + } elsif ($val =~ /^\d+$/) { + my $bits = $frameSelectorBits{$val}; + return undef unless defined $bits; + return ($val << 2) | $bits; + } else { + return undef; + } +} + +#------------------------------------------------------------------------------ +# Convert Leica Kelvin white balance +# Inputs: 0) value, 1) flag to perform inverse conversion +# Returns: Converted value, or undef on error +sub WhiteBalanceConv($;$$) +{ + my ($val, $inv) = @_; + if ($inv) { + return $1 + 0x8000 if $val =~ /(\d+)/; + } else { + return ($val - 0x8000) . ' Kelvin' if $val > 0x8000; + } + return undef; +} + +#------------------------------------------------------------------------------ +# Process Leica makernotes in LEIC atom of MP4 videos (Leica T and X Vario) +# Inputs: 0) ExifTool ref, 1) dirInfo ref, 2) tag table ref +# Returns: 1 on success +sub ProcessLeicaLEIC($$$) +{ + my ($et, $dirInfo, $tagTablePtr) = @_; + my $dataPt = $$dirInfo{DataPt}; + my $dirStart = $$dirInfo{DirStart} || 0; + my $dirLen = $$dirInfo{DirLen} || (length($$dataPt) - $dirStart); + return 0 if $dirLen < 6; + SetByteOrder('II'); + my $numEntries = Get16u($dataPt, $dirStart); + return 0 if $numEntries < 1 or $numEntries > 255; + my $size = Get32u($dataPt, $dirStart + 2); + return 0 if $size < $numEntries * 12 or $size + 6 > $dirLen; + # the Leica programmers want to make things difficult, so they store + # the entry count before the directory size, making it impossible to + # process as a standard TIFF IFD without a bit of reorganization... + Set16u($numEntries, $dataPt, $dirStart + 4); + my %dirInfo = %$dirInfo; + $dirInfo{DirStart} = $dirStart + 4; + $dirInfo{DirLen} = $size - 4; + $dirInfo{DataPos} -= $dirStart; + $dirInfo{Base} += $dirStart; + return Image::ExifTool::Exif::ProcessExif($et, \%dirInfo, $tagTablePtr); + return 1; +} + +#------------------------------------------------------------------------------ +# Process MakerNote trailer written by Leica S2 +# Inputs: 0) ExifTool object ref, 1) new absolute position of Leica trailer when writing +# Returns: On success: 1 when reading, directory data when writing; othewise undef +# Notes: +# - may be called twice for a file if the first call doesn't succeed +# - must leave RAF position unchanged +# - uses information from LeicaTrailer member: +# TagInfo = tag info ref for MakerNote SubDirectory +# Offset/Size = value offset/size from MakerNote IFD +# TrailStart/TrailLen = actual JPEG trailer position/size (2nd call only) +# - deletes LeicaTrailer member and sets LeicaTrailerPos when successful +sub ProcessLeicaTrailer($;$) +{ + my ($et, $newPos) = @_; + my $trail = $$et{LeicaTrailer}; + my $raf = $$et{RAF}; + my $trailPos = $$trail{TrailPos}; + my $pos = $trailPos || $$trail{Offset}; + my $len = $$trail{TrailLen} || $$trail{Size}; + my ($buff, $result, %tagPtr); + + delete $$et{LeicaTrailer} if $trailPos; # done after this + unless ($len > 0) { + $et->Warn('Missing Leica MakerNote trailer', 1) if $trailPos; + delete $$et{LeicaTrailer}; + return undef; + } + my $oldPos = $raf->Tell(); + my $ok = ($raf->Seek($pos, 0) and $raf->Read($buff, $len) == $len); + $raf->Seek($oldPos, 0); + unless ($ok) { + $et->Warn('Error reading Leica MakerNote trailer', 1) if $trailPos; + return undef; + } + # look for Leica MakerNote header (should be at start of + # trailer, but allow up to 256 bytes of garbage just in case) + if ($buff !~ /^(.{0,256})LEICA\0..../sg) { + my $what = $trailPos ? 'trailer' : 'offset'; + $et->Warn("Invalid Leica MakerNote $what", 1); + return undef; + } + my $junk = $1; + my $start = pos($buff) - 10; + if ($start and not $trailPos) { + $et->Warn('Invalid Leica MakerNote offset', 1); + return undef; + } +# +# all checks passed -- go ahead and process the trailer now +# + my $hdrLen = 8; + my $dirStart = $start + $hdrLen; + my $tagInfo = $$trail{TagInfo}; + if ($$et{HTML_DUMP}) { + my $name = $$tagInfo{Name}; + $et->HDump($pos+$start, $len-$start, "$name value", 'Leica MakerNote trailer', 4); + $et->HDump($pos+$start, $hdrLen, "MakerNotes header", $name); + } elsif ($et->Options('Verbose')) { + my $where = sprintf('at offset 0x%x', $pos); + $et->VPrint(0, "Leica MakerNote trailer ($len bytes $where):\n"); + } + # delete LeicaTrailer member so we don't try to process it again + delete $$et{LeicaTrailer}; + $$et{LeicaTrailerPos} = $pos + $start; # return actual start position of Leica trailer + + my $oldOrder = GetByteOrder(); + my $num = Get16u(\$buff, $dirStart); # get entry count + ToggleByteOrder() if ($num>>8) > ($num&0xff); # set byte order + + # use specialized algorithm to automatically fix offsets + my $valStart = $dirStart + 2 + 12 * $num + 4; + my $fix = 0; + if ($valStart < $len) { + my $valBlock = Image::ExifTool::MakerNotes::GetValueBlocks(\$buff, $dirStart, \%tagPtr); + # find the minimum offset (excluding the PreviewImage tag 0x300 and 0x301) + my $minPtr; + foreach (keys %tagPtr) { + my $ptr = $tagPtr{$_}; + next if $_ == 0x300 or $_ == 0x301 or not $ptr or $ptr == 0xffffffff; + $minPtr = $ptr if not defined $minPtr or $minPtr > $ptr; + } + if ($minPtr) { + my $diff = $minPtr - ($valStart + $pos); + pos($buff) = $valStart; + my $expect; + if ($$et{Model} eq 'S2') { + # scan value data for the first non-zero byte + if ($buff =~ /[^\0]/g) { + my $n = pos($buff) - 1 - $valStart; # number of zero bytes + # S2 writes 282 bytes of zeros, exiftool writes none + $expect = $n >= 282 ? 282 : 0; + } + } else { # M (Type 240) + # scan for the lens type (M writes 114 bytes of garbage first) + if ($buff =~ /\G.{114}([\x20-\x7f]*\0*)/sg and length($1) >= 50) { + $expect = 114; + } + } + my $fixBase = $et->Options('FixBase'); + if (not defined $expect) { + $et->Warn('Unrecognized Leica trailer structure'); + } elsif ($diff != $expect or defined $fixBase) { + $fix = $expect - $diff; + if (defined $fixBase) { + $fix = $fixBase if $fixBase ne ''; + $et->Warn("Adjusted MakerNotes base by $fix",1); + } else { + $et->Warn("Possibly incorrect maker notes offsets (fixed by $fix)",1); + } + } + } + } + # generate dirInfo for Leica MakerNote directory + my %dirInfo = ( + Name => $$tagInfo{Name}, + Base => $fix, + DataPt => \$buff, + DataPos => $pos - $fix, + DataLen => $len, + DirStart => $dirStart, + DirLen => $len - $dirStart, + DirName => 'MakerNotes', + Parent => 'ExifIFD', + TagInfo => $tagInfo, + ); + my $tagTablePtr = GetTagTable($$tagInfo{SubDirectory}{TagTable}); + if ($newPos) { # are we writing? + if ($$et{Model} ne 'S2') { + $et->Warn('Leica MakerNote trailer too messed up to edit. Copying as a block', 1); + return $buff; + } + # set position of new MakerNote IFD (+ 8 for Leica MakerNote header) + $dirInfo{NewDataPos} = $newPos + $start + 8; + $result = $et->WriteDirectory(\%dirInfo, $tagTablePtr); + # write preview image last if necessary and fix up the preview offsets + my $previewInfo = $$et{PREVIEW_INFO}; + delete $$et{PREVIEW_INFO}; + if ($result) { + if ($previewInfo) { + my $fixup = $previewInfo->{Fixup}; + # set preview offset (relative to start of makernotes, + 8 for makernote header) + $fixup->SetMarkerPointers(\$result, 'PreviewImage', length($result) + 8); + $result .= $$previewInfo{Data}; + } + return $junk . substr($buff, $start, $hdrLen) . $result; + } + } else { + # extract information + $result = $et->ProcessDirectory(\%dirInfo, $tagTablePtr); + # also extract as a block if necessary + if ($et->Options('MakerNotes') or + $$et{REQ_TAG_LOOKUP}{lc($$tagInfo{Name})}) + { + # makernote header must be included in RebuildMakerNotes call + $dirInfo{DirStart} -= 8; + $dirInfo{DirLen} += 8; + $$et{MAKER_NOTE_BYTE_ORDER} = GetByteOrder(); + # rebuild maker notes (creates $$et{MAKER_NOTE_FIXUP}) + my $val = Image::ExifTool::Exif::RebuildMakerNotes($et, \%dirInfo, $tagTablePtr); + unless (defined $val) { + $et->Warn('Error rebuilding maker notes (may be corrupt)') if $len > 4; + $val = $buff, + } + my $key = $et->FoundTag($tagInfo, $val); + $et->SetGroup($key, 'ExifIFD'); + } + } + SetByteOrder($oldOrder); + return $result; +} + +1; # end + +__END__ + +=head1 NAME + +Image::ExifTool::Panasonic - Panasonic/Leica maker notes tags + +=head1 SYNOPSIS + +This module is loaded automatically by Image::ExifTool when required. + +=head1 DESCRIPTION + +This module contains definitions required by Image::ExifTool to interpret +Panasonic and Leica maker notes in EXIF information. + +=head1 AUTHOR + +Copyright 2003-2019, Phil Harvey (phil at owl.phy.queensu.ca) + +This library is free software; you can redistribute it and/or modify it +under the same terms as Perl itself. + +=head1 REFERENCES + +=over 4 + +=item L<http://www.compton.nu/panasonic.html> + +=item L<http://johnst.org/sw/exiftags/> + +=item L<http://homepage3.nifty.com/kamisaka/makernote/makernote_pana.htm> + +=item L<http://bretteville.com/pdfs/M8Metadata_v2.pdf> + +=item L<http://www.digital-leica.com/lens_codes/index.html> + +=item (...plus lots of testing with store demos and my wife's DMC-FS7!) + +=back + +=head1 ACKNOWLEDGEMENTS + +Thanks to Tels, Marcel Coenen, Jens Duttke, Joerg, Michael Byczkowski, Carl +Bretteville, Zdenek Mihula and Olaf Ulrich for their contributions. + +=head1 SEE ALSO + +L<Image::ExifTool::TagNames/Panasonic Tags>, +L<Image::ExifTool(3pm)|Image::ExifTool> + +=cut diff --git a/lib/Image/ExifTool/PanasonicRaw.pm b/lib/Image/ExifTool/PanasonicRaw.pm new file mode 100644 index 0000000..141638f --- /dev/null +++ b/lib/Image/ExifTool/PanasonicRaw.pm @@ -0,0 +1,845 @@ +#------------------------------------------------------------------------------ +# File: PanasonicRaw.pm +# +# Description: Read/write Panasonic/Leica RAW/RW2/RWL meta information +# +# Revisions: 2009/03/24 - P. Harvey Created +# 2009/05/12 - PH Added RWL file type (same format as RW2) +# +# References: 1) http://u88.n24.queensu.ca/exiftool/forum/index.php/topic,1542.0.html +# 2) http://www.cybercom.net/~dcoffin/dcraw/ +# 3) http://syscall.eu/#pana +# 4) Klaus Homeister private communication +# IB) Iliah Borg private communication (LibRaw) +# JD) Jens Duttke private communication (TZ3,FZ30,FZ50) +#------------------------------------------------------------------------------ + +package Image::ExifTool::PanasonicRaw; + +use strict; +use vars qw($VERSION); +use Image::ExifTool qw(:DataAccess :Utils); +use Image::ExifTool::Exif; + +$VERSION = '1.23'; + +sub ProcessJpgFromRaw($$$); +sub WriteJpgFromRaw($$$); +sub WriteDistortionInfo($$$); +sub ProcessDistortionInfo($$$); + +my %jpgFromRawMap = ( + IFD1 => 'IFD0', + EXIF => 'IFD0', # to write EXIF as a block + ExifIFD => 'IFD0', + GPS => 'IFD0', + SubIFD => 'IFD0', + GlobParamIFD => 'IFD0', + PrintIM => 'IFD0', + InteropIFD => 'ExifIFD', + MakerNotes => 'ExifIFD', + IFD0 => 'APP1', + MakerNotes => 'ExifIFD', + Comment => 'COM', +); + +my %wbTypeInfo = ( + PrintConv => \%Image::ExifTool::Exif::lightSource, + SeparateTable => 'EXIF LightSource', +); + +my %panasonicWhiteBalance = ( #forum9396 + 0 => 'Auto', + 1 => 'Daylight', + 2 => 'Cloudy', + 3 => 'Tungsten', + 4 => 'n/a', + 5 => 'Flash', + 6 => 'n/a', + 7 => 'n/a', + 8 => 'Custom#1', + 9 => 'Custom#2', + 10 => 'Custom#3', + 11 => 'Custom#4', + 12 => 'Shade', + 13 => 'Kelvin', + 16 => 'AWBc', # GH5 and G9 (Makernotes WB==19) +); + +# Tags found in Panasonic RAW/RW2/RWL images (ref PH) +%Image::ExifTool::PanasonicRaw::Main = ( + GROUPS => { 0 => 'EXIF', 1 => 'IFD0', 2 => 'Image'}, + WRITE_PROC => \&Image::ExifTool::Exif::WriteExif, + CHECK_PROC => \&Image::ExifTool::Exif::CheckExif, + WRITE_GROUP => 'IFD0', # default write group + NOTES => 'These tags are found in IFD0 of Panasonic/Leica RAW, RW2 and RWL images.', + 0x01 => { + Name => 'PanasonicRawVersion', + Writable => 'undef', + }, + 0x02 => 'SensorWidth', #1/PH + 0x03 => 'SensorHeight', #1/PH + 0x04 => 'SensorTopBorder', #JD + 0x05 => 'SensorLeftBorder', #JD + 0x06 => 'SensorBottomBorder', #PH + 0x07 => 'SensorRightBorder', #PH + # observed values for unknown tags - PH + # 0x08: 1 + # 0x09: 1,3,4 + # 0x0a: 12 + # (IB gave 0x08-0x0a as BlackLevel tags, but Klaus' decoding makes more sense) + 0x08 => { Name => 'SamplesPerPixel', Writable => 'int16u', Protected => 1 }, #4 + 0x09 => { #4 + Name => 'CFAPattern', + Writable => 'int16u', + Protected => 1, + PrintConv => { + 0 => 'n/a', + 1 => '[Red,Green][Green,Blue]', # (CM-1, FZ70) + 2 => '[Green,Red][Blue,Green]', # (LX-7) + 3 => '[Green,Blue][Red,Green]', # (ZS100, FZ2500, FZ1000, ...) + 4 => '[Blue,Green][Green,Red]', # (LC-100, G-7, V-LUX1, ...) + }, + }, + 0x0a => { Name => 'BitsPerSample', Writable => 'int16u', Protected => 1 }, #4 + 0x0b => { #4 + Name => 'Compression', + Writable => 'int16u', + Protected => 1, + PrintConv => { + 34316 => 'Panasonic RAW 1', # (most models - RAW/RW2/RWL) + 34826 => 'Panasonic RAW 2', # (DIGILUX 2 - RAW) + 34828 => 'Panasonic RAW 3', # (D-LUX2,D-LUX3,FZ30,LX1 - RAW) + 34830 => 'Panasonic RAW 4', #IB (Leica DIGILUX 3, Panasonic DMC-L1) + }, + }, + # 0x0c: 2 (only Leica Digilux 2) + # 0x0d: 0,1 + # 0x0e,0x0f,0x10: 4095 + 0x0e => { Name => 'LinearityLimitRed', Writable => 'int16u' }, #IB + 0x0f => { Name => 'LinearityLimitGreen', Writable => 'int16u' }, #IB + 0x10 => { Name => 'LinearityLimitBlue', Writable => 'int16u' }, #IB + 0x11 => { #JD + Name => 'RedBalance', + Writable => 'int16u', + ValueConv => '$val / 256', + ValueConvInv => 'int($val * 256 + 0.5)', + Notes => 'found in Digilux 2 RAW images', + }, + 0x12 => { #JD + Name => 'BlueBalance', + Writable => 'int16u', + ValueConv => '$val / 256', + ValueConvInv => 'int($val * 256 + 0.5)', + }, + 0x13 => { #IB + Name => 'WBInfo', + SubDirectory => { TagTable => 'Image::ExifTool::PanasonicRaw::WBInfo' }, + }, + 0x17 => { #1 + Name => 'ISO', + Writable => 'int16u', + }, + # 0x18,0x19,0x1a: 0 + 0x18 => { #IB + Name => 'HighISOMultiplierRed', + Writable => 'int16u', + ValueConv => '$val / 256', + ValueConvInv => 'int($val * 256 + 0.5)', + }, + 0x19 => { #IB + Name => 'HighISOMultiplierGreen', + Writable => 'int16u', + ValueConv => '$val / 256', + ValueConvInv => 'int($val * 256 + 0.5)', + }, + 0x1a => { #IB + Name => 'HighISOMultiplierBlue', + Writable => 'int16u', + ValueConv => '$val / 256', + ValueConvInv => 'int($val * 256 + 0.5)', + }, + # 0x1b: [binary data] (something to do with the camera ISO cababilities: int16u count N, + # followed by table of N entries: int16u ISO, int16u[3] RGB gains - ref IB) + 0x1c => { Name => 'BlackLevelRed', Writable => 'int16u' }, #IB + 0x1d => { Name => 'BlackLevelGreen', Writable => 'int16u' }, #IB + 0x1e => { Name => 'BlackLevelBlue', Writable => 'int16u' }, #IB + 0x24 => { #2 + Name => 'WBRedLevel', + Writable => 'int16u', + }, + 0x25 => { #2 + Name => 'WBGreenLevel', + Writable => 'int16u', + }, + 0x26 => { #2 + Name => 'WBBlueLevel', + Writable => 'int16u', + }, + 0x27 => { #IB + Name => 'WBInfo2', + SubDirectory => { TagTable => 'Image::ExifTool::PanasonicRaw::WBInfo2' }, + }, + # 0x27,0x29,0x2a,0x2b,0x2c: [binary data] + 0x2d => { #IB + Name => 'RawFormat', + Writable => 'int16u', + Protected => 1, + # 2 - RAW DMC-FZ8/FZ18 + # 3 - RAW DMC-L10 + # 4 - RW2 for most other models, including G9 normal resolution and YUNEEC CGO4 + # (must add 15 to black levels for RawFormat == 4) + # 5 - RW2 DC-GH5s and G9 HiRes + # missing - DMC-LX1/FZ30/FZ50/L1/LX1/LX2 + }, + 0x2e => { #JD + Name => 'JpgFromRaw', # (writable directory!) + Groups => { 2 => 'Preview' }, + Writable => 'undef', + # protect this tag because it contains all the metadata + Flags => [ 'Binary', 'Protected', 'NestedHtmlDump', 'BlockExtract' ], + Notes => 'processed as an embedded document because it contains full EXIF', + WriteCheck => '$val eq "none" ? undef : $self->CheckImage(\$val)', + DataTag => 'JpgFromRaw', + RawConv => '$self->ValidateImage(\$val,$tag)', + SubDirectory => { + # extract information from embedded image since it is metadata-rich, + # unless HtmlDump option set (note that the offsets will be relative, + # not absolute like they should be in verbose mode) + TagTable => 'Image::ExifTool::JPEG::Main', + WriteProc => \&WriteJpgFromRaw, + ProcessProc => \&ProcessJpgFromRaw, + }, + }, + 0x2f => { Name => 'CropTop', Writable => 'int16u' }, + 0x30 => { Name => 'CropLeft', Writable => 'int16u' }, + 0x31 => { Name => 'CropBottom', Writable => 'int16u' }, + 0x32 => { Name => 'CropRight', Writable => 'int16u' }, + 0x10f => { + Name => 'Make', + Groups => { 2 => 'Camera' }, + Writable => 'string', + DataMember => 'Make', + # save this value as an ExifTool member variable + RawConv => '$self->{Make} = $val', + }, + 0x110 => { + Name => 'Model', + Description => 'Camera Model Name', + Groups => { 2 => 'Camera' }, + Writable => 'string', + DataMember => 'Model', + # save this value as an ExifTool member variable + RawConv => '$self->{Model} = $val', + }, + 0x111 => { + Name => 'StripOffsets', + # (this value is 0xffffffff for some models, and RawDataOffset must be used) + Flags => [ 'IsOffset', 'PanasonicHack' ], + OffsetPair => 0x117, # point to associated byte counts + ValueConv => 'length($val) > 32 ? \$val : $val', + }, + 0x112 => { + Name => 'Orientation', + Writable => 'int16u', + PrintConv => \%Image::ExifTool::Exif::orientation, + Priority => 0, # so IFD1 doesn't take precedence + }, + 0x116 => { + Name => 'RowsPerStrip', + Priority => 0, + }, + 0x117 => { + Name => 'StripByteCounts', + # (note that this value may represent something like uncompressed byte count + # for RAW/RW2/RWL images from some models, and is zero for some other models) + OffsetPair => 0x111, # point to associated offset + ValueConv => 'length($val) > 32 ? \$val : $val', + }, + 0x118 => { + Name => 'RawDataOffset', #PH (RW2/RWL) + IsOffset => '$$et{TIFF_TYPE} =~ /^(RW2|RWL)$/', # (invalid in DNG-converted files) + PanasonicHack => 1, + OffsetPair => 0x117, # (use StripByteCounts as the offset pair) + NotRealPair => 1, # (to avoid Validate warning) + }, + 0x119 => { + Name => 'DistortionInfo', + SubDirectory => { TagTable => 'Image::ExifTool::PanasonicRaw::DistortionInfo' }, + }, + # 0x11b - chromatic aberration correction (ref 3) (also see forum9366) + 0x11c => { #forum9373 + Name => 'Gamma', + Writable => 'int16u', + # unfortunately it seems that the scaling factor varies with model... + ValueConv => '$val / ($val >= 1024 ? 1024 : ($val >= 256 ? 256 : 100))', + ValueConvInv => 'int($val * 256 + 0.5)', + }, + 0x120 => { + Name => 'CameraIFD', + SubDirectory => { + TagTable => 'Image::ExifTool::PanasonicRaw::CameraIFD', + Base => '$start', + ProcessProc => \&Image::ExifTool::ProcessTIFF, + }, + }, + 0x121 => { #forum9295 + Name => 'Multishot', + Writable => 'int32u', + PrintConv => { + 0 => 'Off', + 65536 => 'Pixel Shift', + }, + }, + # 0x122 - int32u: RAWDataOffset for the GH5s/GX9, or pointer to end of raw data for G9 (forum9295) + 0x2bc => { # PH Extension!! + Name => 'ApplicationNotes', # (writable directory!) + Writable => 'int8u', + Format => 'undef', + Flags => [ 'Binary', 'Protected' ], + SubDirectory => { + DirName => 'XMP', + TagTable => 'Image::ExifTool::XMP::Main', + }, + }, + 0x001b => { #forum9250 + Name => 'NoiseReductionParams', + Writable => 'undef', + Format => 'int16u', + Count => -1, + Flags => 'Protected', + Notes => q{ + the camera's default noise reduction setup. The first number is the number + of entries, then for each entry there are 4 numbers: an ISO speed, and + noise-reduction strengths the R, G and B channels + }, + }, + 0x83bb => { # PH Extension!! + Name => 'IPTC-NAA', # (writable directory!) + Format => 'undef', # convert binary values as undef + Writable => 'int32u', # but write int32u format code in IFD + WriteGroup => 'IFD0', + Flags => [ 'Binary', 'Protected' ], + SubDirectory => { + DirName => 'IPTC', + TagTable => 'Image::ExifTool::IPTC::Main', + }, + }, + 0x8769 => { + Name => 'ExifOffset', + Groups => { 1 => 'ExifIFD' }, + Flags => 'SubIFD', + SubDirectory => { + TagTable => 'Image::ExifTool::Exif::Main', + DirName => 'ExifIFD', + Start => '$val', + }, + }, + 0x8825 => { + Name => 'GPSInfo', + Groups => { 1 => 'GPS' }, + Flags => 'SubIFD', + SubDirectory => { + DirName => 'GPS', + TagTable => 'Image::ExifTool::GPS::Main', + Start => '$val', + }, + }, + # 0xffff => 'DCSHueShiftValues', #exifprobe (NC) +); + +# white balance information (ref IB) +# (PanasonicRawVersion<200: Digilux 2) +%Image::ExifTool::PanasonicRaw::WBInfo = ( + PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData, + WRITE_PROC => \&Image::ExifTool::WriteBinaryData, + CHECK_PROC => \&Image::ExifTool::CheckBinaryData, + WRITABLE => 1, + FORMAT => 'int16u', + FIRST_ENTRY => 0, + 0 => 'NumWBEntries', + 1 => { Name => 'WBType1', %wbTypeInfo }, + 2 => { Name => 'WB_RBLevels1', Format => 'int16u[2]' }, + 4 => { Name => 'WBType2', %wbTypeInfo }, + 5 => { Name => 'WB_RBLevels2', Format => 'int16u[2]' }, + 7 => { Name => 'WBType3', %wbTypeInfo }, + 8 => { Name => 'WB_RBLevels3', Format => 'int16u[2]' }, + 10 => { Name => 'WBType4', %wbTypeInfo }, + 11 => { Name => 'WB_RBLevels4', Format => 'int16u[2]' }, + 13 => { Name => 'WBType5', %wbTypeInfo }, + 14 => { Name => 'WB_RBLevels5', Format => 'int16u[2]' }, + 16 => { Name => 'WBType6', %wbTypeInfo }, + 17 => { Name => 'WB_RBLevels6', Format => 'int16u[2]' }, + 19 => { Name => 'WBType7', %wbTypeInfo }, + 20 => { Name => 'WB_RBLevels7', Format => 'int16u[2]' }, +); + +# white balance information (ref IB) +# (PanasonicRawVersion>=200: D-Lux2, D-Lux3, DMC-FZ18/FZ30/LX1/L10) +%Image::ExifTool::PanasonicRaw::WBInfo2 = ( + PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData, + WRITE_PROC => \&Image::ExifTool::WriteBinaryData, + CHECK_PROC => \&Image::ExifTool::CheckBinaryData, + WRITABLE => 1, + FORMAT => 'int16u', + FIRST_ENTRY => 0, + 0 => 'NumWBEntries', + 1 => { Name => 'WBType1', %wbTypeInfo }, + 2 => { Name => 'WB_RGBLevels1', Format => 'int16u[3]' }, + 5 => { Name => 'WBType2', %wbTypeInfo }, + 6 => { Name => 'WB_RGBLevels2', Format => 'int16u[3]' }, + 9 => { Name => 'WBType3', %wbTypeInfo }, + 10 => { Name => 'WB_RGBLevels3', Format => 'int16u[3]' }, + 13 => { Name => 'WBType4', %wbTypeInfo }, + 14 => { Name => 'WB_RGBLevels4', Format => 'int16u[3]' }, + 17 => { Name => 'WBType5', %wbTypeInfo }, + 18 => { Name => 'WB_RGBLevels5', Format => 'int16u[3]' }, + 21 => { Name => 'WBType6', %wbTypeInfo }, + 22 => { Name => 'WB_RGBLevels6', Format => 'int16u[3]' }, + 25 => { Name => 'WBType7', %wbTypeInfo }, + 26 => { Name => 'WB_RGBLevels7', Format => 'int16u[3]' }, +); + +# lens distortion information (ref 3) +# (distortion correction equation: Ru = scale*(Rd + a*Rd^3 + b*Rd^5 + c*Rd^7), ref 3) +%Image::ExifTool::PanasonicRaw::DistortionInfo = ( + PROCESS_PROC => \&ProcessDistortionInfo, + WRITE_PROC => \&WriteDistortionInfo, + CHECK_PROC => \&Image::ExifTool::CheckBinaryData, + # (don't make this family 0 MakerNotes because we don't want it to be a deletable group) + GROUPS => { 0 => 'PanasonicRaw', 1 => 'PanasonicRaw', 2 => 'Image'}, + WRITABLE => 1, + FORMAT => 'int16s', + FIRST_ENTRY => 0, + NOTES => 'Lens distortion correction information.', + # 0,1 - checksums + 2 => { + Name => 'DistortionParam02', + ValueConv => '$val / 32768', + ValueConvInv => '$val * 32768', + }, + # 3 - usually 0, but seen 0x026b when value 5 is non-zero + 4 => { + Name => 'DistortionParam04', + ValueConv => '$val / 32768', + ValueConvInv => '$val * 32768', + }, + 5 => { + Name => 'DistortionScale', + ValueConv => '1 / (1 + $val/32768)', + ValueConvInv => '(1/$val - 1) * 32768', + }, + # 6 - seen 0x0000-0x027f + 7.1 => { + Name => 'DistortionCorrection', + Mask => 0x0f, + # (have seen the upper 4 bits set for GF5 and GX1, giving a value of -4095 - PH) + PrintConv => { 0 => 'Off', 1 => 'On' }, + }, + 8 => { + Name => 'DistortionParam08', + ValueConv => '$val / 32768', + ValueConvInv => '$val * 32768', + }, + 9 => { + Name => 'DistortionParam09', + ValueConv => '$val / 32768', + ValueConvInv => '$val * 32768', + }, + # 10 - seen 0xfc,0x0101,0x01f4,0x021d,0x0256 + 11 => { + Name => 'DistortionParam11', + ValueConv => '$val / 32768', + ValueConvInv => '$val * 32768', + }, + 12 => { + Name => 'DistortionN', + Unknown => 1, + }, + # 13 - seen 0x0000,0x01f9-0x02b2 + # 14,15 - checksums +); + +# Panasonic RW2 camera IFD written by GH5 (ref PH) +# (doesn't seem to be valid for the GF7 or GM5 -- encrypted?) +%Image::ExifTool::PanasonicRaw::CameraIFD = ( + GROUPS => { 0 => 'PanasonicRaw', 1 => 'CameraIFD', 2 => 'Camera'}, + # (don't know what format codes 0x101 and 0x102 are for, so just + # map them into 4 = int32u for now) + VARS => { MAP_FORMAT => { 0x101 => 4, 0x102 => 4 } }, + 0x1001 => { #forum9388 + Name => 'MultishotOn', + Writable => 'int32u', + PrintConv => { 0 => 'No', 1 => 'Yes' }, + }, + 0x1100 => { #forum9274 + Name => 'FocusStepNear', + Writable => 'int16s', + }, + 0x1101 => { #forum9274 (was forum8484) + Name => 'FocusStepCount', + Writable => 'int16s', + }, + 0x1102 => { #forum9417 + Name => 'FlashFired', + Writable => 'int32u', + PrintConv => { 0 => 'No', 1 => 'Yes' }, + }, + # 0x1104 - set when camera shoots on lowest possible Extended-ISO (forum9290) + 0x1105 => { #forum9392 + Name => 'ZoomPosition', + Notes => 'in the range 0-255 for most cameras', + Writable => 'int32u', + }, + 0x1200 => { #forum9278 + Name => 'LensAttached', + Notes => 'many CameraIFD tags are invalid if there is no lens attached', + Writable => 'int32u', + PrintConv => { 0 => 'No', 1 => 'Yes' }, + }, + # 1201 - LensStyle? ref forum9394 + 0x1203 => { #4 + Name => 'FocalLengthIn35mmFormat', + Writable => 'int16u', + PrintConv => '"$val mm"', + PrintConvInv => '$val=~s/\s*mm$//;$val', + }, + 0x1305 => { #forum9384 + Name => 'HighISOMode', + Writable => 'int16u', + RawConv => '$val || undef', + PrintConv => { 1 => 'On', 2 => 'Off' }, + }, + # 0x140b - scaled overall black level? (ref forum9281) + # 0x1411 - scaled black level per channel difference (ref forum9281) + # 0x2000 - WB tungsten=3, daylight=4 (ref forum9467) + # 0x2009 - scaled black level per channel (ref forum9281) + # 0x3000-0x310b - red/blue balances * 1024 (ref forum9467) + # 0x3000 modifiedTungsten-Red (-2?) + # 0x3001 modifiedTungsten-Blue (-2?) + # 0x3002 modifiedDaylight-Red (-2?) + # 0x3003 modifiedDaylight-Blue (-2?) + # 0x3004 modifiedTungsten-Red (-1?) + # 0x3005 modifiedTungsten-Blue (-1?) + # 0x3006 modifiedDaylight-Red (-1?) + # 0x3007 modifiedDaylight-Blue (-1?) + # 0x3100 DefaultTungsten-Red + # 0x3101 DefaultTungsten-Blue + # 0x3102 DefaultDaylight-Red + # 0x3103 DefaultDaylight-Blue + # 0x3104 modifiedTungsten-Red (+1?) + # 0x3105 modifiedTungsten-Blue (+1?) + # 0x3106 modifiedDaylight-Red (+1?) + # 0x3107 modifiedDaylight-Blue (+1?) + # 0x3108 modifiedTungsten-Red (+2?) + # 0x3109 modifiedTungsten-Blue (+2?) + # 0x310a modifiedDaylight-Red (+2?) + # 0x310b modifiedDaylight-Blue (+2?) + 0x3200 => { #forum9275 + Name => 'WB_CFA0_LevelDaylight', + Writable => 'int16u', + }, + 0x3201 => { #forum9275 + Name => 'WB_CFA1_LevelDaylight', + Writable => 'int16u', + }, + 0x3202 => { #forum9275 + Name => 'WB_CFA2_LevelDaylight', + Writable => 'int16u', + }, + 0x3203 => { #forum9275 + Name => 'WB_CFA3_LevelDaylight', + Writable => 'int16u', + }, + # 0x3204-0x3207 - user multipliers * 1024 ? (ref forum9275) + # 0x320a - scaled maximum value of raw data (scaling = 4x) (ref forum9281) + # 0x3209 - gamma (x256) (ref forum9281) + 0x3300 => { #forum9296/9396 + Name => 'WhiteBalanceSet', + Writable => 'int8u', + PrintConv => \%panasonicWhiteBalance, + SeparateTable => 'WhiteBalance', + }, + 0x3420 => { #forum9276 + Name => 'WB_RedLevelAuto', + Writable => 'int16u', + }, + 0x3421 => { #forum9276 + Name => 'WB_BlueLevelAuto', + Writable => 'int16u', + }, + 0x3501 => { #4 + Name => 'Orientation', + Writable => 'int8u', + PrintConv => \%Image::ExifTool::Exif::orientation, + }, + 0x3600 => { #forum9396 + Name => 'WhiteBalanceDetected', + Writable => 'int8u', + PrintConv => \%panasonicWhiteBalance, + SeparateTable => 'WhiteBalance', + }, +); + +# PanasonicRaw composite tags +%Image::ExifTool::PanasonicRaw::Composite = ( + ImageWidth => { + Require => { + 0 => 'IFD0:SensorLeftBorder', + 1 => 'IFD0:SensorRightBorder', + }, + ValueConv => '$val[1] - $val[0]', + }, + ImageHeight => { + Require => { + 0 => 'IFD0:SensorTopBorder', + 1 => 'IFD0:SensorBottomBorder', + }, + ValueConv => '$val[1] - $val[0]', + }, +); + +# add our composite tags +Image::ExifTool::AddCompositeTags('Image::ExifTool::PanasonicRaw'); + + +#------------------------------------------------------------------------------ +# checksum algorithm for lens distortion correction information (ref 3) +# Inputs: 0) data ref, 1) start position, 2) number of bytes, 3) incement +# Returns: checksum value +sub Checksum($$$$) +{ + my ($dataPt, $start, $num, $inc) = @_; + my $csum = 0; + my $i; + for ($i=0; $i<$num; ++$i) { + $csum = (73 * $csum + Get8u($dataPt, $start + $i * $inc)) % 0xffef; + } + return $csum; +} + +#------------------------------------------------------------------------------ +# Read lens distortion information +# Inputs: 0) ExifTool ref, 1) dirInfo ref, 2) tag table ref +# Returns: 1 on success +sub ProcessDistortionInfo($$$) +{ + my ($et, $dirInfo, $tagTablePtr) = @_; + my $dataPt = $$dirInfo{DataPt}; + my $start = $$dirInfo{DirStart} || 0; + my $size = $$dirInfo{DirLen} || (length($$dataPt) - $start); + if ($size == 32) { + # verify the checksums (ref 3) + my $csum1 = Checksum($dataPt, $start + 4, 12, 1); + my $csum2 = Checksum($dataPt, $start + 16, 12, 1); + my $csum3 = Checksum($dataPt, $start + 2, 14, 2); + my $csum4 = Checksum($dataPt, $start + 3, 14, 2); + my $res = $csum1 ^ Get16u($dataPt, $start + 2) ^ + $csum2 ^ Get16u($dataPt, $start + 28) ^ + $csum3 ^ Get16u($dataPt, $start + 0) ^ + $csum4 ^ Get16u($dataPt, $start + 30); + $et->Warn('Invalid DistortionInfo checksum',1) if $res; + } else { + $et->Warn('Invalid DistortionInfo',1); + } + return $et->ProcessBinaryData($dirInfo, $tagTablePtr); +} + +#------------------------------------------------------------------------------ +# Write lens distortion information +# Inputs: 0) ExifTool ref, 1) dirInfo ref, 2) tag table ref +# Returns: updated distortion information or undef on error +sub WriteDistortionInfo($$$) +{ + my ($et, $dirInfo, $tagTablePtr) = @_; + $et or return 1; # (allow dummy access) + my $dat = $et->WriteBinaryData($dirInfo, $tagTablePtr); + if (defined $dat and length($dat) == 32) { + # fix checksums (ref 3) + Set16u(Checksum(\$dat, 4, 12, 1), \$dat, 2); + Set16u(Checksum(\$dat, 16, 12, 1), \$dat, 28); + Set16u(Checksum(\$dat, 2, 14, 2), \$dat, 0); + Set16u(Checksum(\$dat, 3, 14, 2), \$dat, 30); + } else { + $et->Warn('Error wriing DistortionInfo',1); + } + return $dat; +} + +#------------------------------------------------------------------------------ +# Patch for writing non-standard Panasonic RAW/RW2/RWL raw data +# Inputs: 0) offset info ref, 1) raf ref, 2) IFD number +# Returns: error string, or undef on success +# OffsetInfo is a hash by tag ID of lists with the following elements: +# 0 - tag info ref +# 1 - pointer to int32u offset in IFD or value data +# 2 - value count +# 3 - reference to list of original offset values +# 4 - IFD format number +sub PatchRawDataOffset($$$) +{ + my ($offsetInfo, $raf, $ifd) = @_; + my $stripOffsets = $$offsetInfo{0x111}; + my $stripByteCounts = $$offsetInfo{0x117}; + my $rawDataOffset = $$offsetInfo{0x118}; + my $err; + $err = 1 unless $ifd == 0; + $err = 1 unless $stripOffsets and $stripByteCounts and $$stripOffsets[2] == 1; + if ($rawDataOffset) { + $err = 1 unless $$rawDataOffset[2] == 1; + $err = 1 unless $$stripOffsets[3][0] == 0xffffffff or $$stripByteCounts[3][0] == 0; + } + $err and return 'Unsupported Panasonic/Leica RAW variant'; + if ($rawDataOffset) { + # update StripOffsets along with this tag if it contains a reasonable value + unless ($$stripOffsets[3][0] == 0xffffffff) { + # save pointer to StripOffsets value for updating later + push @$rawDataOffset, $$stripOffsets[1]; + } + # handle via RawDataOffset instead of StripOffsets + $stripOffsets = $$offsetInfo{0x111} = $rawDataOffset; + delete $$offsetInfo{0x118}; + } + # determine the length of the raw data + my $pos = $raf->Tell(); + $raf->Seek(0, 2) or $err = 1; # seek to end of file + my $len = $raf->Tell() - $$stripOffsets[3][0]; + $raf->Seek($pos, 0); + # quick check to be sure the raw data length isn't unreasonable + # (the 22-byte length is for '<Dummy raw image data>' in our tests) + $err = 1 if ($len < 1000 and $len != 22) or $len & 0x80000000; + $err and return 'Error reading Panasonic raw data'; + # update StripByteCounts info with raw data length + # (note that the original value is maintained in the file) + $$stripByteCounts[3][0] = $len; + + return undef; +} + +#------------------------------------------------------------------------------ +# Write meta information to Panasonic JpgFromRaw in RAW/RW2/RWL image +# Inputs: 0) ExifTool object ref, 1) dirInfo ref, 2) tag table ref +# Returns: updated image data, or undef if nothing changed +sub WriteJpgFromRaw($$$) +{ + my ($et, $dirInfo, $tagTablePtr) = @_; + my $dataPt = $$dirInfo{DataPt}; + my $byteOrder = GetByteOrder(); + my $fileType = $$et{TIFF_TYPE}; # RAW, RW2 or RWL + my $dirStart = $$dirInfo{DirStart}; + if ($dirStart) { # DirStart is non-zero in DNG-converted RW2/RWL + my $dirLen = $$dirInfo{DirLen} | length($$dataPt) - $dirStart; + my $buff = substr($$dataPt, $dirStart, $dirLen); + $dataPt = \$buff; + } + my $raf = new File::RandomAccess($dataPt); + my $outbuff; + my %dirInfo = ( + RAF => $raf, + OutFile => \$outbuff, + ); + $$et{BASE} = $$dirInfo{DataPos}; + $$et{FILE_TYPE} = $$et{TIFF_TYPE} = 'JPEG'; + # use a specialized map so we don't write XMP or IPTC (or other junk) into the JPEG + my $editDirs = $$et{EDIT_DIRS}; + my $addDirs = $$et{ADD_DIRS}; + $et->InitWriteDirs(\%jpgFromRawMap); + # don't add XMP segment (IPTC won't get added because it is in Photoshop record) + delete $$et{ADD_DIRS}{XMP}; + my $result = $et->WriteJPEG(\%dirInfo); + # restore variables we changed + $$et{BASE} = 0; + $$et{FILE_TYPE} = 'TIFF'; + $$et{TIFF_TYPE} = $fileType; + $$et{EDIT_DIRS} = $editDirs; + $$et{ADD_DIRS} = $addDirs; + SetByteOrder($byteOrder); + return $result > 0 ? $outbuff : $$dataPt; +} + +#------------------------------------------------------------------------------ +# Extract meta information from an Panasonic JpgFromRaw +# Inputs: 0) ExifTool object reference, 1) dirInfo reference +# Returns: 1 on success, 0 if this wasn't a valid JpgFromRaw image +sub ProcessJpgFromRaw($$$) +{ + my ($et, $dirInfo, $tagTablePtr) = @_; + my $dataPt = $$dirInfo{DataPt}; + my $byteOrder = GetByteOrder(); + my $fileType = $$et{TIFF_TYPE}; # RAW, RW2 or RWL + my $tagInfo = $$dirInfo{TagInfo}; + my $verbose = $et->Options('Verbose'); + my ($indent, $out); + $tagInfo or $et->Warn('No tag info for Panasonic JpgFromRaw'), return 0; + my $dirStart = $$dirInfo{DirStart}; + if ($dirStart) { # DirStart is non-zero in DNG-converted RW2/RWL + my $dirLen = $$dirInfo{DirLen} | length($$dataPt) - $dirStart; + my $buff = substr($$dataPt, $dirStart, $dirLen); + $dataPt = \$buff; + } + $$et{BASE} = $$dirInfo{DataPos} + ($dirStart || 0); + $$et{FILE_TYPE} = $$et{TIFF_TYPE} = 'JPEG'; + $$et{DOC_NUM} = 1; + # extract information from embedded JPEG + my %dirInfo = ( + Parent => 'RAF', + RAF => new File::RandomAccess($dataPt), + ); + if ($verbose) { + my $indent = $$et{INDENT}; + $$et{INDENT} = ' '; + $out = $et->Options('TextOut'); + print $out '--- DOC1:JpgFromRaw ',('-'x56),"\n"; + } + my $rtnVal = $et->ProcessJPEG(\%dirInfo); + # restore necessary variables for continued RW2/RWL processing + $$et{BASE} = 0; + $$et{FILE_TYPE} = 'TIFF'; + $$et{TIFF_TYPE} = $fileType; + delete $$et{DOC_NUM}; + SetByteOrder($byteOrder); + if ($verbose) { + $$et{INDENT} = $indent; + print $out ('-'x76),"\n"; + } + return $rtnVal; +} + +1; # end + +__END__ + +=head1 NAME + +Image::ExifTool::PanasonicRaw - Read/write Panasonic/Leica RAW/RW2/RWL meta information + +=head1 SYNOPSIS + +This module is loaded automatically by Image::ExifTool when required. + +=head1 DESCRIPTION + +This module contains definitions required by Image::ExifTool to read and +write meta information in Panasonic/Leica RAW, RW2 and RWL images. + +=head1 AUTHOR + +Copyright 2003-2019, Phil Harvey (phil at owl.phy.queensu.ca) + +This library is free software; you can redistribute it and/or modify it +under the same terms as Perl itself. + +=head1 REFERENCES + +=over 4 + +=item L<http://www.cybercom.net/~dcoffin/dcraw/> + +=back + +=head1 SEE ALSO + +L<Image::ExifTool::TagNames/PanasonicRaw Tags>, +L<Image::ExifTool(3pm)|Image::ExifTool> + +=cut diff --git a/lib/Image/ExifTool/Pentax.pm b/lib/Image/ExifTool/Pentax.pm new file mode 100644 index 0000000..a7a52dd --- /dev/null +++ b/lib/Image/ExifTool/Pentax.pm @@ -0,0 +1,6268 @@ +#------------------------------------------------------------------------------ +# File: Pentax.pm +# +# Description: Pentax/Asahi EXIF maker notes tags +# +# Revisions: 11/25/2003 - P. Harvey Created +# 02/10/2004 - P. Harvey Completely re-done +# 02/16/2004 - W. Smith Updated (see ref 3) +# 11/10/2004 - P. Harvey Added support for Asahi cameras +# 01/10/2005 - P. Harvey Added LensType with values from ref 4 +# 03/30/2005 - P. Harvey Added new tags from ref 5 +# 10/04/2005 - P. Harvey Added MOV tags +# 10/22/2007 - P. Harvey Got my new K10D! (more new tags to decode) +# 11/03/2010 - P. Harvey Got my new K-5! (a gold mine of new tags to discover!) +# +# References: 1) Image::MakerNotes::Pentax +# 2) http://johnst.org/sw/exiftags/ (Asahi cameras) +# 3) Wayne Smith private communication (Optio 550) +# 4) http://kobe1995.jp/~kaz/astro/istD.html +# 5) John Francis (http://www.panix.com/~johnf/raw/index.html) (ist-D/ist-DS) +# 6) http://www.cybercom.net/~dcoffin/dcraw/ +# 7) Douglas O'Brien private communication (*istD, K10D) +# 8) Denis Bourez private communication +# 9) Kazumichi Kawabata private communication +# 10) David Buret private communication (*istD) +# 11) http://forums.dpreview.com/forums/read.asp?forum=1036&message=17465929 +# 12) Derby Chang private communication +# 13) http://homepage3.nifty.com/kamisaka/makernote/makernote_pentax.htm (2007/02/28) +# 14) Ger Vermeulen private communication (Optio S6) +# 15) Barney Garrett private communication (Samsung GX-1S) +# 16) Axel Kellner private communication (K10D) +# 17) Cvetan Ivanov private communication (K100D) +# 18) http://gvsoft.homedns.org/exif/makernote-pentax-type3.html +# 19) Dave Nicholson private communication (K10D) +# 20) Bogdan and yeryry (http://www.cpanforum.com/posts/8037) +# 21) Peter (*istD, http://www.cpanforum.com/posts/8078) +# 22) Bozi (K10D, http://www.cpanforum.com/posts/8480) +# 23) Akos Szalkai (https://rt.cpan.org/Ticket/Display.html?id=43743) +# 24) Albert Bogner private communication +# 26) http://u88.n24.queensu.ca/exiftool/forum/index.php/topic,3444.0.html +# 27) http://u88.n24.queensu.ca/exiftool/forum/index.php/topic,3833.0.html +# 28) Klaus Homeister http://u88.n24.queensu.ca/exiftool/forum/index.php/topic,4803.0.html +# 29) Louis Granboulan private communication (K-5II) +# 30) http://u88.n24.queensu.ca/exiftool/forum/index.php?topic=5433 +# 31) Andras Salamon private communication (K-70) +# IB) Iliah Borg private communication (LibRaw) +# JD) Jens Duttke private communication +# NJ) Niels Kristian Bech Jensen private communication +# +# Notes: See POD documentation at the bottom of this file +#------------------------------------------------------------------------------ + +package Image::ExifTool::Pentax; + +use strict; +use vars qw($VERSION %pentaxLensTypes); +use Image::ExifTool::Exif; +use Image::ExifTool::GPS; +use Image::ExifTool::HP; + +$VERSION = '3.26'; + +sub CryptShutterCount($$); +sub PrintFilter($$$); +sub DecodeAFPoints($$$$;$); + +# pentax lens type codes (ref 4) +# The first number gives the lens series, and the 2nd gives the model number +# Series numbers: K=1; A=2; F=3; FAJ=4; DFA=4,7; FA=3,4,5,6; FA*=5,6; +# DA=3,4,7; DA*=7,8; FA645=11; DFA645=13; Q=21 +%pentaxLensTypes = ( + Notes => q{ + The first number gives the series of the lens, and the second identifies the + lens model. Note that newer series numbers may not always be properly + identified by cameras running older firmware versions. Decimal values have + been added to differentiate lenses which would otherwise have the same + LensType, and are used by the Composite LensID tag when attempting to + identify the specific lens model. + }, + OTHER => sub { + my ($val, $inv, $conv) = @_; + return undef if $inv; + # *istD may report a series number of 4 for series 7 lenses + $val =~ s/^4 /7 / and $$conv{$val} and return "$$conv{$val} ($_[0])"; + # cameras that don't recognize SDM lenses (eg. older K10 firmware) + # may report series 7 instead of 8 + $val =~ s/^7 /8 / and $$conv{$val} and return "$$conv{$val} ? ($_[0])"; + # there seems to some inconsistency between FA and DFA lenses for the 645D... + ($val =~ s/^11 /13 / or $val =~ s/^13 /11 /) and $$conv{$val} and return "$$conv{$val} ? ($_[0])"; + return undef; + }, + '0 0' => 'M-42 or No Lens', #17 + '1 0' => 'K or M Lens', + '2 0' => 'A Series Lens', #7 (from smc PENTAX-A 400mm F5.6) + '3 0' => 'Sigma', + # (and 'Sigma 18-50mm F2.8 EX Macro') + # (and 'Sigma 30mm F1.4 EX DC', ref PH) + # (and 'Sigma 50-500mm F4-6.3 DG APO') + # (and 'Sigma 70mm F2.8 EX DG Macro') + # (and 'Sigma 105mm F2.8 EX DG Macro', ref 24) + # (and 'Sigma 180mm F4.5 EX DG Macro') + '3 17' => 'smc PENTAX-FA SOFT 85mm F2.8', # (also F version, ref 29) + '3 18' => 'smc PENTAX-F 1.7X AF ADAPTER', + '3 19' => 'smc PENTAX-F 24-50mm F4', + '3 20' => 'smc PENTAX-F 35-80mm F4-5.6', + '3 21' => 'smc PENTAX-F 80-200mm F4.7-5.6', + '3 22' => 'smc PENTAX-F FISH-EYE 17-28mm F3.5-4.5', + '3 23' => 'smc PENTAX-F 100-300mm F4.5-5.6 or Sigma Lens', + '3 23.1' => 'Sigma AF 28-300mm F3.5-5.6 DL IF', #JD + '3 23.2' => 'Sigma AF 28-300mm F3.5-6.3 DG IF Macro', #JD + '3 23.3' => 'Tokina 80-200mm F2.8 ATX-Pro', #Exiv2 + '3 24' => 'smc PENTAX-F 35-135mm F3.5-4.5', + '3 25' => 'smc PENTAX-F 35-105mm F4-5.6 or Sigma or Tokina Lens', + '3 25.1' => 'Sigma 55-200mm F4-5.6 DC', #JD + '3 25.2' => 'Sigma AF 28-300mm F3.5-5.6 DL IF', #11 + '3 25.3' => 'Sigma AF 28-300mm F3.5-6.3 DL IF', #Exiv2 + '3 25.4' => 'Sigma AF 28-300mm F3.5-6.3 DG IF Macro', #JD + '3 25.5' => 'Tokina 80-200mm F2.8 ATX-Pro', #12 + '3 26' => 'smc PENTAX-F* 250-600mm F5.6 ED[IF]', + '3 27' => 'smc PENTAX-F 28-80mm F3.5-4.5 or Tokina Lens', + '3 27.1' => 'Tokina AT-X Pro AF 28-70mm F2.6-2.8', #JD + '3 28' => 'smc PENTAX-F 35-70mm F3.5-4.5 or Tokina Lens', + '3 28.1' => 'Tokina 19-35mm F3.5-4.5 AF', #12 + '3 28.2' => 'Tokina AT-X AF 400mm F5.6', #NJ + '3 29' => 'PENTAX-F 28-80mm F3.5-4.5 or Sigma or Tokina Lens', + '3 29.1' => 'Sigma AF 18-125mm F3.5-5.6 DC', #11 + '3 29.2' => 'Tokina AT-X PRO 28-70mm F2.6-2.8', #22 + '3 30' => 'PENTAX-F 70-200mm F4-5.6', + '3 31' => 'smc PENTAX-F 70-210mm F4-5.6 or Tokina or Takumar Lens', + '3 31.1' => 'Tokina AF 730 75-300mm F4.5-5.6', + '3 31.2' => 'Takumar-F 70-210mm F4-5.6', #JD + '3 32' => 'smc PENTAX-F 50mm F1.4', + '3 33' => 'smc PENTAX-F 50mm F1.7', + '3 34' => 'smc PENTAX-F 135mm F2.8 [IF]', + '3 35' => 'smc PENTAX-F 28mm F2.8', + '3 36' => 'Sigma 20mm F1.8 EX DG Aspherical RF', + '3 38' => 'smc PENTAX-F* 300mm F4.5 ED[IF]', + '3 39' => 'smc PENTAX-F* 600mm F4 ED[IF]', + '3 40' => 'smc PENTAX-F Macro 100mm F2.8', + '3 41' => 'smc PENTAX-F Macro 50mm F2.8 or Sigma Lens', #4 + '3 41.1' => 'Sigma 50mm F2.8 Macro', #16 + '3 42' => 'Sigma 300mm F2.8 EX DG APO IF', #27 + '3 44' => 'Sigma or Tamron Lens (3 44)', + '3 44.1' => 'Sigma AF 10-20mm F4-5.6 EX DC', #JD + '3 44.2' => 'Sigma 12-24mm F4.5-5.6 EX DG', #12 (added "-5.6", ref 29) + '3 44.3' => 'Sigma 17-70mm F2.8-4.5 DC Macro', #(Bart Hickman) + '3 44.4' => 'Sigma 18-50mm F3.5-5.6 DC', #4 + '3 44.5' => 'Sigma 17-35mm F2.8-4 EX DG', #29 + '3 44.6' => 'Tamron 35-90mm F4 AF', #12 + '3 44.7' => 'Sigma AF 18-35mm F3.5-4.5 Aspherical', #29 + '3 46' => 'Sigma or Samsung Lens (3 46)', + '3 46.1' => 'Sigma APO 70-200mm F2.8 EX', + '3 46.2' => 'Sigma EX APO 100-300mm F4 IF', #JD + '3 46.3' => 'Samsung/Schneider D-XENON 50-200mm F4-5.6 ED', #29 + '3 50' => 'smc PENTAX-FA 28-70mm F4 AL', + '3 51' => 'Sigma 28mm F1.8 EX DG Aspherical Macro', + '3 52' => 'smc PENTAX-FA 28-200mm F3.8-5.6 AL[IF] or Tamron Lens', + '3 52.1' => 'Tamron AF LD 28-200mm F3.8-5.6 [IF] Aspherical (171D)', #JD + '3 53' => 'smc PENTAX-FA 28-80mm F3.5-5.6 AL', + '3 247' => 'smc PENTAX-DA FISH-EYE 10-17mm F3.5-4.5 ED[IF]', + '3 248' => 'smc PENTAX-DA 12-24mm F4 ED AL[IF]', + '3 250' => 'smc PENTAX-DA 50-200mm F4-5.6 ED', + '3 251' => 'smc PENTAX-DA 40mm F2.8 Limited', + '3 252' => 'smc PENTAX-DA 18-55mm F3.5-5.6 AL', + '3 253' => 'smc PENTAX-DA 14mm F2.8 ED[IF]', + '3 254' => 'smc PENTAX-DA 16-45mm F4 ED AL', + '3 255' => 'Sigma Lens (3 255)', + '3 255.1' => 'Sigma 18-200mm F3.5-6.3 DC', #8 + '3 255.2' => 'Sigma DL-II 35-80mm F4-5.6', #12 + '3 255.3' => 'Sigma DL Zoom 75-300mm F4-5.6', #12 + '3 255.4' => 'Sigma DF EX Aspherical 28-70mm F2.8', #12 + '3 255.5' => 'Sigma AF Tele 400mm F5.6 Multi-coated', #JD + '3 255.6' => 'Sigma 24-60mm F2.8 EX DG', #PH + '3 255.7' => 'Sigma 70-300mm F4-5.6 Macro', #JD + '3 255.8' => 'Sigma 55-200mm F4-5.6 DC', #JD + '3 255.9' => 'Sigma 18-50mm F2.8 EX DC', #JD (also Macro version - PH) + '4 1' => 'smc PENTAX-FA SOFT 28mm F2.8', + '4 2' => 'smc PENTAX-FA 80-320mm F4.5-5.6', + '4 3' => 'smc PENTAX-FA 43mm F1.9 Limited', + '4 6' => 'smc PENTAX-FA 35-80mm F4-5.6', + '4 9' => 'Irix 11mm F4 Firefly', #27 + '4 10' => 'Irix 15mm F2.4', #27 + '4 12' => 'smc PENTAX-FA 50mm F1.4', #17 + '4 15' => 'smc PENTAX-FA 28-105mm F4-5.6 [IF]', + '4 16' => 'Tamron AF 80-210mm F4-5.6 (178D)', #13 + '4 19' => 'Tamron SP AF 90mm F2.8 (172E)', + '4 20' => 'smc PENTAX-FA 28-80mm F3.5-5.6', + '4 21' => 'Cosina AF 100-300mm F5.6-6.7', #20 + '4 22' => 'Tokina 28-80mm F3.5-5.6', #13 + '4 23' => 'smc PENTAX-FA 20-35mm F4 AL', + '4 24' => 'smc PENTAX-FA 77mm F1.8 Limited', + '4 25' => 'Tamron SP AF 14mm F2.8', #13 + '4 26' => 'smc PENTAX-FA Macro 100mm F3.5 or Cosina Lens', + '4 26.1' => 'Cosina 100mm F3.5 Macro', #JD + '4 27' => 'Tamron AF 28-300mm F3.5-6.3 LD Aspherical[IF] Macro (185D/285D)', + '4 28' => 'smc PENTAX-FA 35mm F2 AL', + '4 29' => 'Tamron AF 28-200mm F3.8-5.6 LD Super II Macro (371D)', #JD + '4 34' => 'smc PENTAX-FA 24-90mm F3.5-4.5 AL[IF]', + '4 35' => 'smc PENTAX-FA 100-300mm F4.7-5.8', + # '4 36' => 'Tamron AF70-300mm F4-5.6 LD Macro', # both 572D and A17 (Di) - ref JD + '4 36' => 'Tamron AF 70-300mm F4-5.6 LD Macro 1:2', #NJ + '4 37' => 'Tamron SP AF 24-135mm F3.5-5.6 AD AL (190D)', #13 + '4 38' => 'smc PENTAX-FA 28-105mm F3.2-4.5 AL[IF]', + '4 39' => 'smc PENTAX-FA 31mm F1.8 AL Limited', + '4 41' => 'Tamron AF 28-200mm Super Zoom F3.8-5.6 Aspherical XR [IF] Macro (A03)', + '4 43' => 'smc PENTAX-FA 28-90mm F3.5-5.6', + '4 44' => 'smc PENTAX-FA J 75-300mm F4.5-5.8 AL', + '4 45' => 'Tamron Lens (4 45)', + '4 45.1' => 'Tamron 28-300mm F3.5-6.3 Ultra zoom XR', + '4 45.2' => 'Tamron AF 28-300mm F3.5-6.3 XR Di LD Aspherical [IF] Macro', #JD + '4 46' => 'smc PENTAX-FA J 28-80mm F3.5-5.6 AL', + '4 47' => 'smc PENTAX-FA J 18-35mm F4-5.6 AL', + #'4 49' => 'Tamron SP AF 28-75mm F2.8 XR Di (A09)', + '4 49' => 'Tamron SP AF 28-75mm F2.8 XR Di LD Aspherical [IF] Macro', #NJ + '4 51' => 'smc PENTAX-D FA 50mm F2.8 Macro', + '4 52' => 'smc PENTAX-D FA 100mm F2.8 Macro', + '4 55' => 'Samsung/Schneider D-XENOGON 35mm F2', #29 + '4 56' => 'Samsung/Schneider D-XENON 100mm F2.8 Macro', #Alan Robinson + '4 75' => 'Tamron SP AF 70-200mm F2.8 Di LD [IF] Macro (A001)', #JD + '4 214' => 'smc PENTAX-DA 35mm F2.4 AL', #PH + '4 229' => 'smc PENTAX-DA 18-55mm F3.5-5.6 AL II', #JD + '4 230' => 'Tamron SP AF 17-50mm F2.8 XR Di II', #20 + '4 231' => 'smc PENTAX-DA 18-250mm F3.5-6.3 ED AL [IF]', #21 + '4 237' => 'Samsung/Schneider D-XENOGON 10-17mm F3.5-4.5', #JD + '4 239' => 'Samsung/Schneider D-XENON 12-24mm F4 ED AL [IF]', #23 + '4 242' => 'smc PENTAX-DA* 16-50mm F2.8 ED AL [IF] SDM (SDM unused)', #Pietu Pohjalainen + '4 243' => 'smc PENTAX-DA 70mm F2.4 Limited', #JD + '4 244' => 'smc PENTAX-DA 21mm F3.2 AL Limited', #9 + '4 245' => 'Samsung/Schneider D-XENON 50-200mm F4-5.6', #15 + '4 246' => 'Samsung/Schneider D-XENON 18-55mm F3.5-5.6', #15 + '4 247' => 'smc PENTAX-DA FISH-EYE 10-17mm F3.5-4.5 ED[IF]', #10 + '4 248' => 'smc PENTAX-DA 12-24mm F4 ED AL [IF]', #10 + '4 249' => 'Tamron XR DiII 18-200mm F3.5-6.3 (A14)', + '4 250' => 'smc PENTAX-DA 50-200mm F4-5.6 ED', #8 + '4 251' => 'smc PENTAX-DA 40mm F2.8 Limited', #9 + '4 252' => 'smc PENTAX-DA 18-55mm F3.5-5.6 AL', #8 + '4 253' => 'smc PENTAX-DA 14mm F2.8 ED[IF]', + '4 254' => 'smc PENTAX-DA 16-45mm F4 ED AL', + '5 1' => 'smc PENTAX-FA* 24mm F2 AL[IF]', + '5 2' => 'smc PENTAX-FA 28mm F2.8 AL', + '5 3' => 'smc PENTAX-FA 50mm F1.7', + '5 4' => 'smc PENTAX-FA 50mm F1.4', + '5 5' => 'smc PENTAX-FA* 600mm F4 ED[IF]', + '5 6' => 'smc PENTAX-FA* 300mm F4.5 ED[IF]', + '5 7' => 'smc PENTAX-FA 135mm F2.8 [IF]', + '5 8' => 'smc PENTAX-FA Macro 50mm F2.8', + '5 9' => 'smc PENTAX-FA Macro 100mm F2.8', + '5 10' => 'smc PENTAX-FA* 85mm F1.4 [IF]', + '5 11' => 'smc PENTAX-FA* 200mm F2.8 ED[IF]', + '5 12' => 'smc PENTAX-FA 28-80mm F3.5-4.7', + '5 13' => 'smc PENTAX-FA 70-200mm F4-5.6', + '5 14' => 'smc PENTAX-FA* 250-600mm F5.6 ED[IF]', + '5 15' => 'smc PENTAX-FA 28-105mm F4-5.6', + '5 16' => 'smc PENTAX-FA 100-300mm F4.5-5.6', + '5 98' => 'smc PENTAX-FA 100-300mm F4.5-5.6', #JD (pre-production? - PH) + '6 1' => 'smc PENTAX-FA* 85mm F1.4 [IF]', + '6 2' => 'smc PENTAX-FA* 200mm F2.8 ED[IF]', + '6 3' => 'smc PENTAX-FA* 300mm F2.8 ED[IF]', + '6 4' => 'smc PENTAX-FA* 28-70mm F2.8 AL', + '6 5' => 'smc PENTAX-FA* 80-200mm F2.8 ED[IF]', + '6 6' => 'smc PENTAX-FA* 28-70mm F2.8 AL', + '6 7' => 'smc PENTAX-FA* 80-200mm F2.8 ED[IF]', + '6 8' => 'smc PENTAX-FA 28-70mm F4AL', + '6 9' => 'smc PENTAX-FA 20mm F2.8', + '6 10' => 'smc PENTAX-FA* 400mm F5.6 ED[IF]', + '6 13' => 'smc PENTAX-FA* 400mm F5.6 ED[IF]', + '6 14' => 'smc PENTAX-FA* Macro 200mm F4 ED[IF]', + '7 0' => 'smc PENTAX-DA 21mm F3.2 AL Limited', #13 + '7 58' => 'smc PENTAX-D FA Macro 100mm F2.8 WR', #PH - this bit of information cost me $600 ;) + '7 75' => 'Tamron SP AF 70-200mm F2.8 Di LD [IF] Macro (A001)', #(Anton Bondar) + '7 201' => 'smc Pentax-DA L 50-200mm F4-5.6 ED WR', #(Bruce Rusk) + '7 202' => 'smc PENTAX-DA L 18-55mm F3.5-5.6 AL WR', #29 + '7 203' => 'HD PENTAX-DA 55-300mm F4-5.8 ED WR', #29 + '7 204' => 'HD PENTAX-DA 15mm F4 ED AL Limited', #forum5318 + '7 205' => 'HD PENTAX-DA 35mm F2.8 Macro Limited', #29 + '7 206' => 'HD PENTAX-DA 70mm F2.4 Limited', #29 + '7 207' => 'HD PENTAX-DA 21mm F3.2 ED AL Limited', #forum5327 + '7 208' => 'HD PENTAX-DA 40mm F2.8 Limited', #PH + '7 212' => 'smc PENTAX-DA 50mm F1.8', #PH + '7 213' => 'smc PENTAX-DA 40mm F2.8 XS', #PH + '7 214' => 'smc PENTAX-DA 35mm F2.4 AL', #PH + '7 216' => 'smc PENTAX-DA L 55-300mm F4-5.8 ED', #PH + '7 217' => 'smc PENTAX-DA 50-200mm F4-5.6 ED WR', #JD + '7 218' => 'smc PENTAX-DA 18-55mm F3.5-5.6 AL WR', #JD + '7 220' => 'Tamron SP AF 10-24mm F3.5-4.5 Di II LD Aspherical [IF]', #24 + '7 221' => 'smc PENTAX-DA L 50-200mm F4-5.6 ED', #Ar't + '7 222' => 'smc PENTAX-DA L 18-55mm F3.5-5.6', #PH (tag 0x003f -- was '7 229' in LensInfo of one test image) + '7 223' => 'Samsung/Schneider D-XENON 18-55mm F3.5-5.6 II', #PH + '7 224' => 'smc PENTAX-DA 15mm F4 ED AL Limited', #JD + '7 225' => 'Samsung/Schneider D-XENON 18-250mm F3.5-6.3', #8/PH + '7 226' => 'smc PENTAX-DA* 55mm F1.4 SDM (SDM unused)', #PH (NC) + '7 227' => 'smc PENTAX-DA* 60-250mm F4 [IF] SDM (SDM unused)', #PH (NC) + '7 228' => 'Samsung 16-45mm F4 ED', #29 + '7 229' => 'smc PENTAX-DA 18-55mm F3.5-5.6 AL II', #JD + '7 230' => 'Tamron AF 17-50mm F2.8 XR Di-II LD (Model A16)', #JD + '7 231' => 'smc PENTAX-DA 18-250mm F3.5-6.3 ED AL [IF]', #JD + '7 233' => 'smc PENTAX-DA 35mm F2.8 Macro Limited', #JD + '7 234' => 'smc PENTAX-DA* 300mm F4 ED [IF] SDM (SDM unused)', #19 (NC) + '7 235' => 'smc PENTAX-DA* 200mm F2.8 ED [IF] SDM (SDM unused)', #PH (NC) + '7 236' => 'smc PENTAX-DA 55-300mm F4-5.8 ED', #JD + '7 238' => 'Tamron AF 18-250mm F3.5-6.3 Di II LD Aspherical [IF] Macro', #JD + '7 241' => 'smc PENTAX-DA* 50-135mm F2.8 ED [IF] SDM (SDM unused)', #PH + '7 242' => 'smc PENTAX-DA* 16-50mm F2.8 ED AL [IF] SDM (SDM unused)', #19 + '7 243' => 'smc PENTAX-DA 70mm F2.4 Limited', #PH + '7 244' => 'smc PENTAX-DA 21mm F3.2 AL Limited', #16 + '8 0' => 'Sigma 50-150mm F2.8 II APO EX DC HSM', #forum2997 + '8 3' => 'Sigma AF 18-125mm F3.5-5.6 DC', #29 + '8 4' => 'Sigma 50mm F1.4 EX DG HSM', #Artur private communication + '8 7' => 'Sigma 24-70mm F2.8 IF EX DG HSM', #Exiv2 + '8 8' => 'Sigma 18-250mm F3.5-6.3 DC OS HSM', #27 + '8 11' => 'Sigma 10-20mm F3.5 EX DC HSM', #27 + '8 12' => 'Sigma 70-300mm F4-5.6 DG OS', #forum3382 + '8 13' => 'Sigma 120-400mm F4.5-5.6 APO DG OS HSM', #26 + '8 14' => 'Sigma 17-70mm F2.8-4.0 DC Macro OS HSM', #(Hubert Meier) + '8 15' => 'Sigma 150-500mm F5-6.3 APO DG OS HSM', #26 + '8 16' => 'Sigma 70-200mm F2.8 EX DG Macro HSM II', #26 + '8 17' => 'Sigma 50-500mm F4.5-6.3 DG OS HSM', #(Heike Herrmann) (also APO, ref 26) + '8 18' => 'Sigma 8-16mm F4.5-5.6 DC HSM', #forum2998 + '8 21' => 'Sigma 17-50mm F2.8 EX DC OS HSM', #26 + '8 22' => 'Sigma 85mm F1.4 EX DG HSM', #26 + '8 23' => 'Sigma 70-200mm F2.8 APO EX DG OS HSM', #27 + '8 25' => 'Sigma 17-50mm F2.8 EX DC HSM', #Exiv2 + '8 27' => 'Sigma 18-200mm F3.5-6.3 II DC HSM', #27 + '8 28' => 'Sigma 18-250mm F3.5-6.3 DC Macro HSM', #27 + '8 29' => 'Sigma 35mm F1.4 DG HSM', #27 + '8 30' => 'Sigma 17-70mm F2.8-4 DC Macro HSM | C', #27 + '8 31' => 'Sigma 18-35mm F1.8 DC HSM', #27 + '8 32' => 'Sigma 30mm F1.4 DC HSM | A', #27 + '8 33' => 'Sigma 18-200mm F3.5-6.3 DC Macro HSM', #DieterPearcey (C014) + '8 34' => 'Sigma 18-300mm F3.5-6.3 DC Macro HSM', #NJ + '8 59' => 'HD PENTAX-D FA 150-450mm F4.5-5.6 ED DC AW', #29 + '8 60' => 'HD PENTAX-D FA* 70-200mm F2.8 ED DC AW', #29 + '8 61' => 'HD PENTAX-D FA 28-105mm F3.5-5.6 ED DC WR', #PH + '8 62' => 'HD PENTAX-D FA 24-70mm F2.8 ED SDM WR', #PH + '8 63' => 'HD PENTAX-D FA 15-30mm F2.8 ED SDM WR', #PH + '8 64' => 'HD PENTAX-D FA* 50mm F1.4 SDM AW', #27 + '8 196' => 'HD PENTAX-DA* 11-18mm F2.8 ED DC AW', #29 + '8 197' => 'HD PENTAX-DA 55-300mm F4.5-6.3 ED PLM WR RE', #29 + '8 198' => 'smc PENTAX-DA L 18-50mm F4-5.6 DC WR RE', #29 + '8 199' => 'HD PENTAX-DA 18-50mm F4-5.6 DC WR RE', #29 + '8 200' => 'HD PENTAX-DA 16-85mm F3.5-5.6 ED DC WR', #29 + '8 209' => 'HD PENTAX-DA 20-40mm F2.8-4 ED Limited DC WR', #29 + '8 210' => 'smc PENTAX-DA 18-270mm F3.5-6.3 ED SDM', #Helmut Schutz + '8 211' => 'HD PENTAX-DA 560mm F5.6 ED AW', #PH + '8 215' => 'smc PENTAX-DA 18-135mm F3.5-5.6 ED AL [IF] DC WR', #PH + '8 226' => 'smc PENTAX-DA* 55mm F1.4 SDM', #JD + '8 227' => 'smc PENTAX-DA* 60-250mm F4 [IF] SDM', #JD + '8 232' => 'smc PENTAX-DA 17-70mm F4 AL [IF] SDM', #JD + '8 234' => 'smc PENTAX-DA* 300mm F4 ED [IF] SDM', #19 + '8 235' => 'smc PENTAX-DA* 200mm F2.8 ED [IF] SDM', #JD + '8 241' => 'smc PENTAX-DA* 50-135mm F2.8 ED [IF] SDM', #JD + '8 242' => 'smc PENTAX-DA* 16-50mm F2.8 ED AL [IF] SDM', #JD + '8 255' => 'Sigma Lens (8 255)', + '8 255.1' => 'Sigma 70-200mm F2.8 EX DG Macro HSM II', #JD + '8 255.2' => 'Sigma 150-500mm F5-6.3 DG APO [OS] HSM', #JD (non-OS version has same type, ref 29) + '8 255.3' => 'Sigma 50-150mm F2.8 II APO EX DC HSM', #forum2997 + '8 255.4' => 'Sigma 4.5mm F2.8 EX DC HSM Circular Fisheye', #PH + '8 255.5' => 'Sigma 50-200mm F4-5.6 DC OS', #26 + '8 255.6' => 'Sigma 24-70mm F2.8 EX DG HSM', #29 +# +# 645 lenses +# + '9 0' => '645 Manual Lens', #PH (NC) + '10 0' => '645 A Series Lens', #PH + '11 1' => 'smc PENTAX-FA 645 75mm F2.8', #PH + '11 2' => 'smc PENTAX-FA 645 45mm F2.8', #PH + '11 3' => 'smc PENTAX-FA* 645 300mm F4 ED [IF]', #PH + '11 4' => 'smc PENTAX-FA 645 45-85mm F4.5', #PH + '11 5' => 'smc PENTAX-FA 645 400mm F5.6 ED [IF]', #PH + '11 7' => 'smc PENTAX-FA 645 Macro 120mm F4', #PH + '11 8' => 'smc PENTAX-FA 645 80-160mm F4.5', #PH + '11 9' => 'smc PENTAX-FA 645 200mm F4 [IF]', #PH + '11 10' => 'smc PENTAX-FA 645 150mm F2.8 [IF]', #PH + '11 11' => 'smc PENTAX-FA 645 35mm F3.5 AL [IF]', #PH + '11 12' => 'smc PENTAX-FA 645 300mm F5.6 ED [IF]', #29 + '11 14' => 'smc PENTAX-FA 645 55-110mm F5.6', #PH + '11 16' => 'smc PENTAX-FA 645 33-55mm F4.5 AL', #PH + '11 17' => 'smc PENTAX-FA 645 150-300mm F5.6 ED [IF]', #PH + '11 21' => 'HD PENTAX-D FA 645 35mm F3.5 AL [IF]', #29 + '13 18' => 'smc PENTAX-D FA 645 55mm F2.8 AL [IF] SDM AW', #PH + '13 19' => 'smc PENTAX-D FA 645 25mm F4 AL [IF] SDM AW', #PH + '13 20' => 'HD PENTAX-D FA 645 90mm F2.8 ED AW SR', #PH + '13 253' => 'HD PENTAX-DA 645 28-45mm F4.5 ED AW SR', #Dominique Schrekling email + '13 254' => 'smc PENTAX-DA 645 25mm F4 AL [IF] SDM AW', #forum8253 +# +# Q-mount lenses (21=auto focus lens, 22=manual focus) +# + '21 0' => 'Pentax Q Manual Lens', #PH + '21 1' => '01 Standard Prime 8.5mm F1.9', #PH + '21 2' => '02 Standard Zoom 5-15mm F2.8-4.5', #PH + '22 3' => '03 Fish-eye 3.2mm F5.6', #PH + '22 4' => '04 Toy Lens Wide 6.3mm F7.1', #PH + '22 5' => '05 Toy Lens Telephoto 18mm F8', #PH + '21 6' => '06 Telephoto Zoom 15-45mm F2.8', #PH + '21 7' => '07 Mount Shield 11.5mm F9', #PH (NC) + '21 8' => '08 Wide Zoom 3.8-5.9mm F3.7-4', #PH (NC) + '21 233' => 'Adapter Q for K-mount Lens', #29 +# +# Ricoh lenses +# + '31 1' => 'GR Lens', #PH (GR III 28mm F2.8) +); + +# Pentax model ID codes - PH +my %pentaxModelID = ( + 0x0000d => 'Optio 330/430', + 0x12926 => 'Optio 230', + 0x12958 => 'Optio 330GS', + 0x12962 => 'Optio 450/550', + 0x1296c => 'Optio S', + 0x12971 => 'Optio S V1.01', + 0x12994 => '*ist D', + 0x129b2 => 'Optio 33L', + 0x129bc => 'Optio 33LF', + 0x129c6 => 'Optio 33WR/43WR/555', + 0x129d5 => 'Optio S4', + 0x12a02 => 'Optio MX', + 0x12a0c => 'Optio S40', + 0x12a16 => 'Optio S4i', + 0x12a34 => 'Optio 30', + 0x12a52 => 'Optio S30', + 0x12a66 => 'Optio 750Z', + 0x12a70 => 'Optio SV', + 0x12a75 => 'Optio SVi', + 0x12a7a => 'Optio X', + 0x12a8e => 'Optio S5i', + 0x12a98 => 'Optio S50', + 0x12aa2 => '*ist DS', + 0x12ab6 => 'Optio MX4', + 0x12ac0 => 'Optio S5n', + 0x12aca => 'Optio WP', + 0x12afc => 'Optio S55', + 0x12b10 => 'Optio S5z', + 0x12b1a => '*ist DL', + 0x12b24 => 'Optio S60', + 0x12b2e => 'Optio S45', + 0x12b38 => 'Optio S6', + 0x12b4c => 'Optio WPi', #13 + 0x12b56 => 'BenQ DC X600', + 0x12b60 => '*ist DS2', + 0x12b62 => 'Samsung GX-1S', + 0x12b6a => 'Optio A10', + 0x12b7e => '*ist DL2', + 0x12b80 => 'Samsung GX-1L', + 0x12b9c => 'K100D', + 0x12b9d => 'K110D', + 0x12ba2 => 'K100D Super', #JD + 0x12bb0 => 'Optio T10/T20', + 0x12be2 => 'Optio W10', + 0x12bf6 => 'Optio M10', + 0x12c1e => 'K10D', + 0x12c20 => 'Samsung GX10', + 0x12c28 => 'Optio S7', + 0x12c2d => 'Optio L20', + 0x12c32 => 'Optio M20', + 0x12c3c => 'Optio W20', + 0x12c46 => 'Optio A20', + 0x12c78 => 'Optio E30', + 0x12c7d => 'Optio E35', + 0x12c82 => 'Optio T30', + 0x12c8c => 'Optio M30', + 0x12c91 => 'Optio L30', + 0x12c96 => 'Optio W30', + 0x12ca0 => 'Optio A30', + 0x12cb4 => 'Optio E40', + 0x12cbe => 'Optio M40', + 0x12cc3 => 'Optio L40', + 0x12cc5 => 'Optio L36', + 0x12cc8 => 'Optio Z10', + 0x12cd2 => 'K20D', + 0x12cd4 => 'Samsung GX20', #8 + 0x12cdc => 'Optio S10', + 0x12ce6 => 'Optio A40', + 0x12cf0 => 'Optio V10', + 0x12cfa => 'K200D', + 0x12d04 => 'Optio S12', + 0x12d0e => 'Optio E50', + 0x12d18 => 'Optio M50', + 0x12d22 => 'Optio L50', + 0x12d2c => 'Optio V20', + 0x12d40 => 'Optio W60', + 0x12d4a => 'Optio M60', + 0x12d68 => 'Optio E60/M90', + 0x12d72 => 'K2000', + 0x12d73 => 'K-m', + 0x12d86 => 'Optio P70', + 0x12d90 => 'Optio L70', + 0x12d9a => 'Optio E70', + 0x12dae => 'X70', + 0x12db8 => 'K-7', + 0x12dcc => 'Optio W80', + 0x12dea => 'Optio P80', + 0x12df4 => 'Optio WS80', + 0x12dfe => 'K-x', + 0x12e08 => '645D', + 0x12e12 => 'Optio E80', + 0x12e30 => 'Optio W90', + 0x12e3a => 'Optio I-10', + 0x12e44 => 'Optio H90', + 0x12e4e => 'Optio E90', + 0x12e58 => 'X90', + 0x12e6c => 'K-r', + 0x12e76 => 'K-5', + 0x12e8a => 'Optio RS1000/RS1500', + 0x12e94 => 'Optio RZ10', + 0x12e9e => 'Optio LS1000', + 0x12ebc => 'Optio WG-1 GPS', + 0x12ed0 => 'Optio S1', + 0x12ee4 => 'Q', + 0x12ef8 => 'K-01', + 0x12f0c => 'Optio RZ18', + 0x12f16 => 'Optio VS20', + 0x12f2a => 'Optio WG-2 GPS', + 0x12f48 => 'Optio LS465', + 0x12f52 => 'K-30', + 0x12f5c => 'X-5', + 0x12f66 => 'Q10', + 0x12f70 => 'K-5 II', + 0x12f71 => 'K-5 II s', #forum4515 + 0x12f7a => 'Q7', + 0x12f84 => 'MX-1', + 0x12f8e => 'WG-3 GPS', + 0x12f98 => 'WG-3', + 0x12fa2 => 'WG-10', + 0x12fb6 => 'K-50', + 0x12fc0 => 'K-3', #29 + 0x12fca => 'K-500', + 0x12fe8 => 'WG-4', # (Ricoh) + 0x12fde => 'WG-4 GPS', # (Ricoh) + 0x13006 => 'WG-20', # (Ricoh) + 0x13010 => '645Z', + 0x1301a => 'K-S1', + 0x13024 => 'K-S2', #29 (Ricoh) + 0x1302e => 'Q-S1', + 0x13056 => 'WG-30', # (Ricoh) + 0x1307e => 'WG-30W', # (Ricoh) + 0x13088 => 'WG-5 GPS', # (Ricoh) + 0x13092 => 'K-1', #IB (Ricoh) + 0x1309c => 'K-3 II', #29 (Ricoh) + 0x131f0 => 'WG-M2', # (Ricoh) + 0x1320e => 'GR III', # (Ricoh) + 0x13222 => 'K-70', #29 (Ricoh) + 0x1322c => 'KP', #29 (Ricoh) + 0x13240 => 'K-1 Mark II', # (Ricoh) +); + +# Pentax city codes - (PH, Optio WP) +my %pentaxCities = ( + 0 => 'Pago Pago', + 1 => 'Honolulu', + 2 => 'Anchorage', + 3 => 'Vancouver', + 4 => 'San Francisco', + 5 => 'Los Angeles', + 6 => 'Calgary', + 7 => 'Denver', + 8 => 'Mexico City', + 9 => 'Chicago', + 10 => 'Miami', + 11 => 'Toronto', + 12 => 'New York', + 13 => 'Santiago', + 14 => 'Caracus', + 15 => 'Halifax', + 16 => 'Buenos Aires', + 17 => 'Sao Paulo', + 18 => 'Rio de Janeiro', + 19 => 'Madrid', + 20 => 'London', + 21 => 'Paris', + 22 => 'Milan', + 23 => 'Rome', + 24 => 'Berlin', + 25 => 'Johannesburg', + 26 => 'Istanbul', + 27 => 'Cairo', + 28 => 'Jerusalem', + 29 => 'Moscow', + 30 => 'Jeddah', + 31 => 'Tehran', + 32 => 'Dubai', + 33 => 'Karachi', + 34 => 'Kabul', + 35 => 'Male', + 36 => 'Delhi', + 37 => 'Colombo', + 38 => 'Kathmandu', + 39 => 'Dacca', + 40 => 'Yangon', + 41 => 'Bangkok', + 42 => 'Kuala Lumpur', + 43 => 'Vientiane', + 44 => 'Singapore', + 45 => 'Phnom Penh', + 46 => 'Ho Chi Minh', + 47 => 'Jakarta', + 48 => 'Hong Kong', + 49 => 'Perth', + 50 => 'Beijing', + 51 => 'Shanghai', + 52 => 'Manila', + 53 => 'Taipei', + 54 => 'Seoul', + 55 => 'Adelaide', + 56 => 'Tokyo', + 57 => 'Guam', + 58 => 'Sydney', + 59 => 'Noumea', + 60 => 'Wellington', + 61 => 'Auckland', + 62 => 'Lima', + 63 => 'Dakar', + 64 => 'Algiers', + 65 => 'Helsinki', + 66 => 'Athens', + 67 => 'Nairobi', + 68 => 'Amsterdam', + 69 => 'Stockholm', + 70 => 'Lisbon', #14 + 71 => 'Copenhagen', #NJ + 72 => 'Warsaw', + 73 => 'Prague', + 74 => 'Budapest', +); + +# digital filter tag information (ref PH, K-5) +# (also see %filterSettings below for decoding of filter parameters) +my %digitalFilter = ( + Format => 'undef[17]', + RawConv => '($val!~/^\\0/ or $$self{OPTIONS}{Unknown}) ? join(" ",unpack("Cc*",$val)) : undef', + SeparateTable => 'DigitalFilter', + ValueConvInv => q{ + return "\0" x 17 if $val eq "0"; + $val = pack("Cc*", $val=~/[-+]?\d+/g); + length($val)==17 or warn("Expecting 17 values\n"), return undef; + return $val; + }, + PrintConv => { + OTHER => \&PrintFilter, # this routine actually converts all values + 0 => 'Off', + 1 => 'Base Parameter Adjust', + 2 => 'Soft Focus', + 3 => 'High Contrast', + 4 => 'Color Filter', + 5 => 'Extract Color', + 6 => 'Monochrome', + 7 => 'Slim', + 9 => 'Fisheye', + 10 => 'Toy Camera', + 11 => 'Retro', + 12 => 'Pastel', + 13 => 'Water Color', + 14 => 'HDR', + 16 => 'Miniature', + 17 => 'Starburst', + 18 => 'Posterization', + 19 => 'Sketch Filter', + 20 => 'Shading', # (Q) + 21 => 'Invert Color', # (Q) + 23 => 'Tone Expansion', #Forum5247 + 27 => 'Unicolor Bold', #31 + 28 => 'Bold Monochrome', #31 + 29 => 'Replace Color', #31 + 254 => 'Custom Filter', + }, +); + +# digital filter setting names and conversions (ref PH, K-5) +# Note: names must be unique for writing +my %filterSettings = ( + 1 => ['Brightness', '%+d'], # BPA (-8-+8) + 2 => ['Saturation', '%+d'], # BPA (-3-+3) + 3 => ['Hue', '%+d'], # BPA (-3-+3) + 4 => ['Contrast', '%+d'], # BPA (-3-+3) + 5 => ['Sharpness', '%+d'], # BPA (-3-+3) + 6 => ['SoftFocus', '%d'], # Soft Focus/Custom (1-3) + 7 => ['ShadowBlur', { 0=>'Off',1=>'On' }], # Soft Focus + 8 => ['HighContrast', '%d'], # High Contrast/Custom (1-5) + 9 => ['Color', { 1=>'Red',2=>'Magenta',3=>'Blue',4=>'Cyan',5=>'Green',6=>'Yellow' }], # Color Filter + 10 => ['Density', { 1=>'Light',2=>'Standard',3=>'Dark' }], # Color Filter + 11 => ['ExtractedColor',{ 0=>'Off',1=>'Red',2=>'Magenta',3=>'Blue',4=>'Cyan',5=>'Green',6=>'Yellow' }], # Extract Color [x2] + 12 => ['ColorRange', '%+d'], # Extract Color [x2] (-2-+2) + 13 => ['FilterEffect', { 0=>'Off',1=>'Red',2=>'Green',3=>'Blue',4=>'Infrared'}], # Monochrome + 14 => ['ToningBA', '%+d'], # Monochrome (-3-+3) + 15 => ['InvertColor', { 0=>'Off',1=>'On' }], # Custom/Invert Color + 16 => ['Slim', '%+d'], # Slim (-8-+8) + 17 => ['EffectDensity', { 1=>'Sparse',2=>'Normal',3=>'Dense' }], # Starburst + 18 => ['Size', { 1=>'Small',2=>'Medium',3=>'Large' }], # Starburst + 19 => ['Angle', { 0=>'0deg',2=>'30deg',3=>'45deg',4=>'60deg'}], # Starburst (1 is unused) + 20 => ['Fisheye', { 1=>'Weak',2=>'Medium',3=>'Strong' }], # Fisheye + 21 => ['DistortionType', '%d'], # Custom (1-3) + 22 => ['DistortionLevel',{0=>'Off',1=>'Weak',2=>'Medium',3=>'Strong' }], #Custom + 23 => ['ShadingType', '%d'], # Custom/Shading (1-6) + 24 => ['ShadingLevel', '%+d'], # Custom/Shading (-3-+3) + 25 => ['Shading', '%d'], # Toy Camera (1-3) + 26 => ['Blur', '%d'], # Toy Camera (1-3) + 27 => ['ToneBreak', { 0=>'Off',1=>'Red',2=>'Green',3=>'Blue',4=>'Yellow'}], # Toy Camera/Custom + 28 => ['Toning', '%+d'], # Retro (-3-+3) + 29 => ['FrameComposite',{ 0=>'None',1=>'Thin',2=>'Medium',3=>'Thick' }], # Retro + 30 => ['PastelStrength',{ 1=>'Weak',2=>'Medium',3=>'Strong' }], # Pastel + 31 => ['Intensity', '%d'], # Water Color (1-3) + 32 => ['Saturation2', { 0=>'Off',1=>'Low',2=>'Medium',3=>'High' }], # Water Color + 33 => ['HDR', { 1=>'Weak',2=>'Medium',3=>'Strong' }], # HDR + # (34 missing) + 35 => ['FocusPlane', '%+d'], # Miniature (-3-+3) + 36 => ['FocusWidth', { 1=>'Narrow',2=>'Middle',3=>'Wide' }], # Miniature + 37 => ['PlaneAngle', { 0=>'Horizontal',1=>'Vertical',2=>'Positive slope',3=>'Negative slope' }], # Miniature + 38 => ['Blur2', '%d'], # Miniature (1-3) + 39 => ['Shape', { 1=>'Cross',2=>'Star',3=>'Snowflake',4=>'Heart',5=>'Note'}], # Starburst + 40 => ['Posterization', '%d'], # Posterization (1-5) + 41 => ['Contrast2', { 1=>'Low',2=>'Medium',3=>'High'}], # Sketch Filter + 42 => ['ScratchEffect', { 0=>'Off',1=>'On' }], # Sketch Filter + 45 => ['ToneExpansion', { 1=>'Low',2=>'Medium',3=>'High' }], # Tone Expansion (ref Forum5247) + 47 => ['UnicolorBold', { 1=>'Red',2=>'Magenta',3=>'Blue',4=>'Cyan',5=>'Green',6=>'Yellow' }], #31 Unicolor Bold + 48 => ['BoldMonochrome', '%d'], #31 Bold Monochrome (1-3) + 49 => ['OriginalColor', { 1=>'Red',2=>'Magenta',3=>'Blue',4=>'Cyan',5=>'Green',6=>'Yellow' }], #31 Replace Color + 50 => ['NewColor', { 1=>'Red',2=>'Magenta',3=>'Blue',4=>'Cyan',5=>'Green',6=>'Yellow' }], #31 Replace Color + 51 => ['ColorScale', '%d'], #31 Replace Color (1-5) + 52 => ['Toning2', '%+d'], #31 Extract Color (-3-+3) +); + +# decoding for Pentax Firmware ID tags - PH +my %pentaxFirmwareID = ( + # the first 2 numbers are the firmware version, I'm not sure what the second 2 mean + # Note: the byte order may be different for some models + # which give, for example, version 0.01 instead of 1.00 + ValueConv => sub { + my $val = shift; + return $val unless length($val) == 4; + # (value is encrypted by toggling all bits) + my @a = map { $_ ^ 0xff } unpack("C*",$val); + return sprintf('%d %.2d %.2d %.2d', @a); + }, + ValueConvInv => sub { + my $val = shift; + my @a = $val=~/\b\d+\b/g; + return $val unless @a == 4; + @a = map { ($_ & 0xff) ^ 0xff } @a; + return pack("C*", @a); + }, + PrintConv => '$val=~tr/ /./; $val', + PrintConvInv => '$val=~s/^(\d+)\.(\d+)\.(\d+)\.(\d+)/$1 $2 $3 $4/ ? $val : undef', +); + +# convert 16 or 77 metering segment values to approximate LV equivalent - PH +my %convertMeteringSegments = ( + PrintConv => sub { join ' ', map( + { $_==255 ? 'n/a' : $_==0 ? '0' : sprintf '%.1f', $_ / 8 - 6 } split(' ',$_[0]) + ) }, + PrintConvInv => sub { join ' ', map( + { /^n/i ? 255 : $_==0 ? '0' : int(($_ + 6) * 8 + 0.5) } split(' ',$_[0]) + ) }, +); + +# lens code conversions +my %lensCode = ( + Unknown => 1, + PrintConv => 'sprintf("0x%.2x", $val)', + PrintConvInv => 'hex($val)', +); + +# conversions for tags 0x0053-0x005a +my %colorTemp = ( + Writable => 'undef', + Count => 4, + ValueConv => sub { + my $val = shift; + return $val unless length $val == 4; + my @a = unpack 'nCC', $val; + $a[0] = 53190 - $a[0]; + $a[1] = ($a[2] & 0x0f); $a[1] -= 16 if $a[1] >= 8; + $a[2] = ($a[2] >> 4); $a[2] -= 16 if $a[2] >= 8; + return "@a"; + }, + ValueConvInv => sub { + my $val = shift; + my @a = split ' ', $val; + return undef unless @a == 3; + return pack 'nCC', 53190 - $a[0], 0, ($a[1] & 0x0f) + (($a[2] & 0x0f) << 4); + }, + PrintConv => sub { + $_ = shift; + s/ ([1-9])/ +$1/g; + s/ 0/ 0/g; + return $_; + }, + PrintConvInv => '$val', +); + +# conversions for KelvinWB tags +my %kelvinWB = ( + Format => 'int16u[4]', + ValueConv => sub { + my @a = split ' ', shift; + (53190 - $a[0]) . ' ' . $a[1] . ' ' . ($a[2] / 8192) . ' ' . ($a[3] / 8192); + }, + ValueConvInv => sub { + my @a = split ' ', shift; + (53190 - $a[0]) . ' ' . $a[1] . ' ' . int($a[2]*8192+0.5) . ' ' . int($a[3]*8192+0.5); + }, +); + +my %noYes = ( 0 => 'No', 1 => 'Yes' ); + +# common attributes for writable BinaryData directories +my %binaryDataAttrs = ( + PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData, + WRITE_PROC => \&Image::ExifTool::WriteBinaryData, + CHECK_PROC => \&Image::ExifTool::CheckBinaryData, + WRITABLE => 1, + FIRST_ENTRY => 0, +); + +# Pentax makernote tags +%Image::ExifTool::Pentax::Main = ( + WRITE_PROC => \&Image::ExifTool::Exif::WriteExif, + CHECK_PROC => \&Image::ExifTool::Exif::CheckExif, + GROUPS => { 0 => 'MakerNotes', 2 => 'Camera' }, + WRITABLE => 1, + 0x0000 => { #5 + Name => 'PentaxVersion', + Writable => 'int8u', + Count => 4, + PrintConv => '$val=~tr/ /./; $val', + PrintConvInv => '$val=~tr/./ /; $val', + # 0.1.0.3 - PENTAX Optio E40 + # 3.0.0.0 - K10D + # 3.1.0.0 - Optio A40/S10/L36/L40/M40/V10 + # 3.1.1.0 - Optio L36/L40/M40/V10 + # 3.1.2.0 - Optio Z10 + # 4.0.2.0 - Optio E50 + # 4.1.0.0 - Optio S12 + # 4.1.1.0 - Optio M50 + # 4.1.2.0 - K20D, K200D + # 4.2.0.0 - Optio L50/V20 + # 4.2.1.0 - Optio E60/M90 + # 4.2.2.0 - Optio W60 + # 4.2.3.0 - Optio M60 + # 4.4.0.1 - K-m, K2000 + # 4.5.0.0 - Optio E70/L70 + # 4.5.0.0 - Optio E70/L70/P70 + # 4.6.0.0 - Optio E80/E90/W80 + # 5.0.0.0 - K-7, Optio P80/WS80 + # 5.1.0.0 - K-x + # 5.2.0.0 - Optio I-10 + # 5.3.0.0 - Optio H90 + # 5.3.2.0 - Optio W90/X90 + # 6.0.0.0 - K-r, 645D + # 6.1.3.0 - Optio LS1000/RS1000/RS1500/RZ10 + # 7.0.0.0 - K-5 + # 7.1.0.0 - Optio WG-1GPS/WG-10/WG-20 + # 7.2.0.0 - Optio S1 + # 8.0.0.0 - Q + # 8.0.1.0 - Optio RZ18 + # 8.0.4.0 - Optio VS20 + # 8.1.0.0 - Optio LS465/WG-2GPS + # 9.0.0.0 - K-01 + # 9.1.2.0 - X-5 + # 10.0.0.0 - K-30, K-50, K-500, K-5 II, K-5 II s + # 10.0.2.0 - Q10 + # 10.2.0.0 - WG-3/WG-4 + # 10.2.1.0 - MX-1 + # 10.4.1.0 - WG-3/4/5 GPS, WG-30/30W + # 10.6.1.0 - Q-S1, Q7 + # 11.0.0.0 - K-3 + # 11.2.1.0 - 645Z + # 11.3.0.0 - K-S1 + # 11.5.0.0 - K-S2 + # 11.6.1.0 - K-3 II + # 11.7.5.0 - WG-M2 + # 12.0.0.0 - K-1 + # 12.1.3.0 - K-70 + # 12.1.5.0 - KP + }, + 0x0001 => { #PH + Name => 'PentaxModelType', + Writable => 'int16u', + # (values of 0-5 seem to group models into 6 categories, ref 13) + }, + 0x0002 => { #PH + Name => 'PreviewImageSize', + Groups => { 2 => 'Image' }, + Writable => 'int16u', + Count => 2, + PrintConv => '$val =~ tr/ /x/; $val', + PrintConvInv => '$val =~ tr/x/ /; $val', + }, + 0x0003 => { #PH + Name => 'PreviewImageLength', + OffsetPair => 0x0004, # point to associated offset + DataTag => 'PreviewImage', + Groups => { 2 => 'Image' }, + Writable => 'int32u', + WriteGroup => 'MakerNotes', + Protected => 2, + }, + 0x0004 => { #PH + Name => 'PreviewImageStart', + IsOffset => 2, # code to use original base + OffsetPair => 0x0003, # point to associated byte count + DataTag => 'PreviewImage', + Groups => { 2 => 'Image' }, + Writable => 'int32u', + WriteGroup => 'MakerNotes', + Protected => 2, + }, + 0x0005 => { #13 + Name => 'PentaxModelID', + Writable => 'int32u', + PrintHex => 1, + SeparateTable => 1, + DataMember => 'PentaxModelID', + RawConv => '$$self{PentaxModelID} = $val', + PrintConv => \%pentaxModelID, + }, + 0x0006 => { #5 + # Note: Year is int16u in MM byte ordering regardless of EXIF byte order + Name => 'Date', + Groups => { 2 => 'Time' }, + Notes => 'changing either Date or Time will affect ShutterCount decryption', + Writable => 'undef', + Count => 4, + Shift => 'Time', + DataMember => 'PentaxDate', + RawConv => '$$self{PentaxDate} = $val', # save to decrypt ShutterCount + ValueConv => 'length($val)==4 ? sprintf("%.4d:%.2d:%.2d",unpack("nC2",$val)) : "Unknown ($val)"', + ValueConvInv => q{ + $val =~ s/(\d) .*/$1/; # remove Time + my @v = split /:/, $val; + return pack("nC2",$v[0],$v[1],$v[2]); + }, + }, + 0x0007 => { #5 + Name => 'Time', + Groups => { 2 => 'Time' }, + Writable => 'undef', + Count => 3, + Shift => 'Time', + DataMember => 'PentaxTime', + RawConv => '$$self{PentaxTime} = $val', # save to decrypt ShutterCount + ValueConv => 'length($val)>=3 ? sprintf("%.2d:%.2d:%.2d",unpack("C3",$val)) : "Unknown ($val)"', + ValueConvInv => q{ + $val =~ s/^[0-9:]+ (\d)/$1/; # remove Date + return pack("C3",split(/:/,$val)); + }, + }, + 0x0008 => { #2 + Name => 'Quality', + Writable => 'int16u', + PrintConvColumns => 2, + PrintConv => { + 0 => 'Good', + 1 => 'Better', + 2 => 'Best', + 3 => 'TIFF', #5 + 4 => 'RAW', #5 + 5 => 'Premium', #PH (K20D) + 7 => 'RAW (pixel shift enabled)', #forum6536 (K-3 II) + 8 => 'Dynamic Pixel Shift', #IB + 65535 => 'n/a', #PH (Q MOV video) + }, + }, + 0x0009 => { #3 + Name => 'PentaxImageSize', + Groups => { 2 => 'Image' }, + Writable => 'int16u', + PrintConvColumns => 2, + PrintConv => { + 0 => '640x480', + 1 => 'Full', #PH - this can mean 2048x1536 or 2240x1680 or ... ? + 2 => '1024x768', + 3 => '1280x960', #PH (Optio WP) + 4 => '1600x1200', + 5 => '2048x1536', + 8 => '2560x1920 or 2304x1728', #PH (Optio WP) or #14 + 9 => '3072x2304', #PH (Optio M30) + 10 => '3264x2448', #13 + 19 => '320x240', #PH (Optio WP) + 20 => '2288x1712', #13 + 21 => '2592x1944', + 22 => '2304x1728 or 2592x1944', #2 or #14 + 23 => '3056x2296', #13 + 25 => '2816x2212 or 2816x2112', #13 or #14 + 27 => '3648x2736', #PH (Optio A20) + 29 => '4000x3000', #PH (X70) + 30 => '4288x3216', #PH (Optio RS1000) + 31 => '4608x3456', #PH (Optio RZ18) + 129 => '1920x1080', #PH (Optio RZ10) + 135 => '4608x2592', #PH (Q10 stretch filter) + 257 => '3216x3216', #PH (Optio RZ10) + '0 0' => '2304x1728', #13 + '4 0' => '1600x1200', #PH (Optio MX4) + '5 0' => '2048x1536', #13 + '8 0' => '2560x1920', #13 + '32 2' => '960x640', #7 + '33 2' => '1152x768', #7 + '34 2' => '1536x1024', #7 + '35 1' => '2400x1600', #7 + '36 0' => '3008x2008 or 3040x2024', #PH + '37 0' => '3008x2000', #13 + # 65535 - seen for an X-5 panorama (PH) + }, + }, + 0x000b => { #3 + Name => 'PictureMode', + Writable => 'int16u', + Count => -1, + Notes => q{ + 1 or 2 values. Decimal values differentiate Optio 555 modes which are + different from other models + }, + ValueConv => '(IsInt($val) and $val < 4 and $$self{Model} =~ /Optio 555\b/) ? $val + 0.1 : $val', + ValueConvInv => 'int $val', + PrintConvColumns => 2, + PrintConv => [{ + 0 => 'Program', #PH + 0.1 => 'Av', #PH (Optio 555) + 1 => 'Shutter Speed Priority', #JD + 1.1 => 'M', #PH (Optio 555) + 2 => 'Program AE', #13 + 2.1 => 'Tv', #PH (Optio 555) + 3 => 'Manual', #13 + 3.1 => 'USER', #PH (Optio 555) + 5 => 'Portrait', + 6 => 'Landscape', + 8 => 'Sport', #PH + 9 => 'Night Scene', + # 10 "full mode"? #13 + 11 => 'Soft', #PH + 12 => 'Surf & Snow', + 13 => 'Candlelight', #13 + 14 => 'Autumn', + 15 => 'Macro', + 17 => 'Fireworks', + 18 => 'Text', + 19 => 'Panorama', #PH + 20 => '3-D', #PH (Optio 555) + 21 => 'Black & White', #PH (Optio 555) + 22 => 'Sepia', #PH (Optio 555) + 23 => 'Red', #PH (Optio 555) + 24 => 'Pink', #PH (Optio 555) + 25 => 'Purple', #PH (Optio 555) + 26 => 'Blue', #PH (Optio 555) + 27 => 'Green', #PH (Optio 555) + 28 => 'Yellow', #PH (Optio 555) + 30 => 'Self Portrait', #PH + 31 => 'Illustrations', #13 + 33 => 'Digital Filter', #13 + 35 => 'Night Scene Portrait', #NJ + 37 => 'Museum', #PH + 38 => 'Food', #PH + 39 => 'Underwater', #NJ + 40 => 'Green Mode', #PH + 49 => 'Light Pet', #PH + 50 => 'Dark Pet', #PH + 51 => 'Medium Pet', #PH + 53 => 'Underwater', #PH + 54 => 'Candlelight', #PH + 55 => 'Natural Skin Tone', #PH + 56 => 'Synchro Sound Record', #PH + 58 => 'Frame Composite', #14 + 59 => 'Report', #NJ + 60 => 'Kids', #13 + 61 => 'Blur Reduction', #13 + 63 => 'Panorama 2', #PH (X-5) + 65 => 'Half-length Portrait', #JD + 66 => 'Portrait 2', #PH (LS645) + 74 => 'Digital Microscope', #PH (WG-4) + 75 => 'Blue Sky', #PH (LS465) + 80 => 'Miniature', #PH (VS20) + 81 => 'HDR', #PH (LS465) + 83 => 'Fisheye', #PH (VS20) + 85 => 'Digital Filter 4', #PH (WG-5) + 221 => 'P', #PH (Optio 555) + 255=> 'PICT', #PH (Optio 555) + }], + }, + 0x000c => { #PH + Name => 'FlashMode', + Writable => 'int16u', + Count => -1, + PrintHex => 1, + PrintConv => [{ + 0x000 => 'Auto, Did not fire', + 0x001 => 'Off, Did not fire', + 0x002 => 'On, Did not fire', #19 + 0x003 => 'Auto, Did not fire, Red-eye reduction', + 0x005 => 'On, Did not fire, Wireless (Master)', #19 + 0x100 => 'Auto, Fired', + 0x102 => 'On, Fired', + 0x103 => 'Auto, Fired, Red-eye reduction', + 0x104 => 'On, Red-eye reduction', + 0x105 => 'On, Wireless (Master)', #19 + 0x106 => 'On, Wireless (Control)', #19 + 0x108 => 'On, Soft', + 0x109 => 'On, Slow-sync', + 0x10a => 'On, Slow-sync, Red-eye reduction', + 0x10b => 'On, Trailing-curtain Sync', + },{ #19 (AF-540FGZ flash) + 0x000 => 'n/a - Off-Auto-Aperture', #19 + 0x03f => 'Internal', + 0x100 => 'External, Auto', + 0x23f => 'External, Flash Problem', #JD + 0x300 => 'External, Manual', + 0x304 => 'External, P-TTL Auto', + 0x305 => 'External, Contrast-control Sync', #JD + 0x306 => 'External, High-speed Sync', + 0x30c => 'External, Wireless', + 0x30d => 'External, Wireless, High-speed Sync', + }], + }, + 0x000d => [ #2 + { + Name => 'FocusMode', + # (can't test for "PENTAX" because MOV videos don't have Make) + Condition => '$$self{Make} !~ /^Asahi/', + Notes => 'Pentax models', + Writable => 'int16u', + PrintConvColumns => 2, + PrintConv => { #PH + 0 => 'Normal', + 1 => 'Macro', + 2 => 'Infinity', + 3 => 'Manual', + 4 => 'Super Macro', #JD + 5 => 'Pan Focus', + # 8 - seen for Ricoh GR III + # 9 - seen for Ricoh GR III + 16 => 'AF-S (Focus-priority)', #17 + 17 => 'AF-C (Focus-priority)', #17 + 18 => 'AF-A (Focus-priority)', #PH (educated guess) + 32 => 'Contrast-detect (Focus-priority)', #PH (K-5) + 33 => 'Tracking Contrast-detect (Focus-priority)', #PH (K-5) + # bit 8 indicates release priority + 272 => 'AF-S (Release-priority)', #PH (K-5,K-3) + 273 => 'AF-C (Release-priority)', #PH (K-5,K-3) + 274 => 'AF-A (Release-priority)', #PH (K-3) + 288 => 'Contrast-detect (Release-priority)', #PH (K-01) + # 32777 (0x8009) - seen for Ricoh GR III + # 32779 (0x800b) - seen for Ricoh GR III + }, + },{ + Name => 'FocusMode', + Writable => 'int16u', + Notes => 'Asahi models', + PrintConv => { #2 + 0 => 'Normal', + 1 => 'Macro (1)', + 2 => 'Macro (2)', + 3 => 'Infinity', + }, + }, + ], + 0x000e => [{ #29 + Name => 'AFPointSelected', + Condition => '$$self{Model} =~ /K-1\b/', + Writable => 'int16u', + Notes => 'K-1', + PrintConvColumns => 2, + PrintConv => [{ + 0xffff => 'Auto', + 0xfffe => 'Fixed Center', + 0xfffd => 'Automatic Tracking AF', #JD + 0xfffc => 'Face Detect AF', #JD + 0xfffb => 'AF Select', #PH (Q select from 25-areas) + # AF pattern: + # 01 02 03 04 05 + # 06 07 08 09 10 11 12 + # 13 14 15 16 17 18 19 20 21 + # 22 23 24 25 26 27 28 + # 29 30 31 32 33 + 0 => 'None', + 1 => 'Top-left', + 2 => 'Top Near-left', + 3 => 'Top', + 4 => 'Top Near-right', + 5 => 'Top-right', + 6 => 'Upper Far-left', + 7 => 'Upper-left', + 8 => 'Upper Near-left', + 9 => 'Upper-middle', + 10 => 'Upper Near-right', + 11 => 'Upper-right', + 12 => 'Upper Far-right', + 13 => 'Far Far Left', + 14 => 'Far Left', + 15 => 'Left', + 16 => 'Near-left', + 17 => 'Center', + 18 => 'Near-right', + 19 => 'Right', + 20 => 'Far Right', + 21 => 'Far Far Right', + 22 => 'Lower Far-left', + 23 => 'Lower-left', + 24 => 'Lower Near-left', + 25 => 'Lower-middle', + 26 => 'Lower Near-right', + 27 => 'Lower-right', + 28 => 'Lower Far-right', + 29 => 'Bottom-left', + 30 => 'Bottom Near-left', + 31 => 'Bottom', + 32 => 'Bottom Near-right', + 33 => 'Bottom-right', + 263 => 'Zone Select Upper-left', # 01,02;06,07,08;14,15,16 + 264 => 'Zone Select Upper Near-left', # 01,02,03;07,08,09;15,16,17 + 265 => 'Zone Select Upper Middle', # 02,03,04;08,09,10;16,17,18 + 266 => 'Zone Select Upper Near-right', # 03,04,05;09,10,11;17,18,19 + 267 => 'Zone Select Upper-right', # 04,05;10,11,12;18,19,20 + 270 => 'Zone Select Far Left', # 06,07;13,14,15;22,23 + 271 => 'Zone Select Left', # 06,07,08;14,15,16;22,23,24 + 272 => 'Zone Select Near-left', # 07,08,09;15,16,17;23,24,25 + 273 => 'Zone Select Center', # 08,09,10;16,17,18;24,25,26 + 274 => 'Zone Select Near-right', # 09,10,11;17,18,19;25,26,27 + 275 => 'Zone Select Right', # 10,11,12;18,19,20;26,27,28 + 276 => 'Zone Select Far Right', # 11,12;19,20,21;27,28 + 279 => 'Zone Select Lower-left', # 14,15,16;22,23,24;29,30 + 280 => 'Zone Select Lower Near-left', # 15,16,17;23,24,25;29,30,31 + 281 => 'Zone Select Lower-middle', # 16,17,18;24,25,26;30,31,32 + 282 => 'Zone Select Lower Near-right', # 17,18,19;25,26,27;31,32,33 + 283 => 'Zone Select Lower-right', # 18,19,20;26,27,28;32,33 + },{ + 0 => 'Single Point', + 1 => 'Expanded Area 9-point (S)', + 3 => 'Expanded Area 25-point (M)', + 5 => 'Expanded Area 33-point (L)', + }], + },{ + Name => 'AFPointSelected', + Condition => '$$self{Model} =~ /K-3\b/', + Writable => 'int16u', + Notes => 'K-3', + PrintConvColumns => 2, + PrintConv => [{ + # 0 - Contrast-detect AF? - PH (K-5) + 0xffff => 'Auto', + 0xfffe => 'Fixed Center', + 0xfffd => 'Automatic Tracking AF', #JD + 0xfffc => 'Face Detect AF', #JD + 0xfffb => 'AF Select', #PH (Q select from 25-areas) + # AF pattern: (ref forum5422) + # 01 02 03 04 05 + # 06 07 08 09 10 + # 11 12 13 14 15 16 17 + # 18 19 20 21 22 + # 23 24 25 26 27 + 0 => 'None', + 1 => 'Top-left', + 2 => 'Top Near-left', + 3 => 'Top', + 4 => 'Top Near-right', + 5 => 'Top-right', + 6 => 'Upper-left', + 7 => 'Upper Near-left', + 8 => 'Upper-middle', + 9 => 'Upper Near-right', + 10 => 'Upper-right', + 11 => 'Far Left', + 12 => 'Left', + 13 => 'Near-left', + 14 => 'Center', + 15 => 'Near-right', + 16 => 'Right', + 17 => 'Far Right', + 18 => 'Lower-left', + 19 => 'Lower Near-left', + 20 => 'Lower-middle', + 21 => 'Lower Near-right', + 22 => 'Lower-right', + 23 => 'Bottom-left', + 24 => 'Bottom Near-left', + 25 => 'Bottom', + 26 => 'Bottom Near-right', + 27 => 'Bottom-right', + #forum5892 + 257 => 'Zone Select Top-left', + 258 => 'Zone Select Top Near-left', + 259 => 'Zone Select Top', + 260 => 'Zone Select Top Near-right', + 261 => 'Zone Select Top-right', + 262 => 'Zone Select Upper-left', + 263 => 'Zone Select Upper Near-left', + 264 => 'Zone Select Upper-middle', + 265 => 'Zone Select Upper Near-right', + 266 => 'Zone Select Upper-right', + 267 => 'Zone Select Far Left', + 268 => 'Zone Select Left', + 269 => 'Zone Select Near-left', + 270 => 'Zone Select Center', + 271 => 'Zone Select Near-right', + 272 => 'Zone Select Right', + 273 => 'Zone Select Far Right', + 274 => 'Zone Select Lower-left', + 275 => 'Zone Select Lower Near-left', + 276 => 'Zone Select Lower-middle', + 277 => 'Zone Select Lower Near-right', + 278 => 'Zone Select Lower-right', + 279 => 'Zone Select Bottom-left', + 280 => 'Zone Select Bottom Near-left', + 281 => 'Zone Select Bottom', + 282 => 'Zone Select Bottom Near-right', + 283 => 'Zone Select Bottom-right', + },{ #forum5892 + 0 => 'Single Point', + 1 => 'Expanded Area 9-point (S)', + 3 => 'Expanded Area 25-point (M)', + 5 => 'Expanded Area 27-point (L)', + }], + },{ #7 + Name => 'AFPointSelected', + Writable => 'int16u', + Notes => 'other models', + PrintConvColumns => 2, + PrintConv => [{ + # 0 - Contrast-detect AF? - PH (K-5) + 0xffff => 'Auto', + 0xfffe => 'Fixed Center', + 0xfffd => 'Automatic Tracking AF', #JD + 0xfffc => 'Face Detect AF', #JD + 0xfffb => 'AF Select', #PH (Q select from 25-areas) + 0 => 'None', #PH (Q in manual focus mode) + 1 => 'Upper-left', + 2 => 'Top', + 3 => 'Upper-right', + 4 => 'Left', + 5 => 'Mid-left', + 6 => 'Center', + 7 => 'Mid-right', + 8 => 'Right', + 9 => 'Lower-left', + 10 => 'Bottom', + 11 => 'Lower-right', + }, + # (second number exists for K-5II(s) is usually 0, but is 1 for AF.C with + # AFPointMode=='Select' and extended tracking focus points are enabled in the settings) + ], + }], + 0x000f => [{ #PH + Name => 'AFPointsInFocus', + Condition => '$$self{Model} =~ /K-3\b/', + Writable => 'int32u', + Notes => 'K-3 only', + PrintHex => 1, + PrintConv => { + 0 => '(none)', + BITMASK => { + 0 => 'Top-left', + 1 => 'Top Near-left', + 2 => 'Top', + 3 => 'Top Near-right', + 4 => 'Top-right', + 5 => 'Upper-left', + 6 => 'Upper Near-left', + 7 => 'Upper-middle', + 8 => 'Upper Near-right', + 9 => 'Upper-right', + 10 => 'Far Left', + 11 => 'Left', + 12 => 'Near-left', + 13 => 'Center', + 14 => 'Near-right', + 15 => 'Right', + 16 => 'Far Right', + 17 => 'Lower-left', + 18 => 'Lower Near-left', + 19 => 'Lower-middle', + 20 => 'Lower Near-right', + 21 => 'Lower-right', + 22 => 'Bottom-left', + 23 => 'Bottom Near-left', + 24 => 'Bottom', + 25 => 'Bottom Near-right', + 26 => 'Bottom-right', + }, + }, + },{ #PH + Name => 'AFPointsInFocus', + Notes => 'other models', + Writable => 'int16u', + PrintHex => 1, + PrintConv => { + 0xffff => 'None', + 0 => 'Fixed Center or Multiple', #PH/14 + 1 => 'Top-left', + 2 => 'Top-center', + 3 => 'Top-right', + 4 => 'Left', + 5 => 'Center', + 6 => 'Right', + 7 => 'Bottom-left', + 8 => 'Bottom-center', + 9 => 'Bottom-right', + }, + }], + 0x0010 => { #PH + Name => 'FocusPosition', + Writable => 'int16u', + Notes => 'related to focus distance but affected by focal length', + }, + 0x0012 => { #PH + Name => 'ExposureTime', + Writable => 'int32u', + Priority => 0, + ValueConv => '$val * 1e-5', + ValueConvInv => '$val * 1e5', + # value may be 0xffffffff in Bulb mode (ref JD) + PrintConv => '$val > 42949 ? "Unknown (Bulb)" : Image::ExifTool::Exif::PrintExposureTime($val)', + PrintConvInv => '$val=~/(unknown|bulb)/i ? $val : Image::ExifTool::Exif::ConvertFraction($val)', + }, + 0x0013 => { #PH + Name => 'FNumber', + Writable => 'int16u', + Priority => 0, + ValueConv => '$val / 10', + ValueConvInv => '$val * 10', + PrintConv => 'sprintf("%.1f",$val)', + PrintConvInv => '$val', + }, + # ISO Tag - Entries confirmed by W. Smith 12 FEB 04 + 0x0014 => { + Name => 'ISO', + Writable => 'int16u', + Notes => 'may be different than EXIF:ISO, which can round to the nearest full stop', + PrintConvColumns => 4, + PrintConv => { + # 1/3 EV step values + 3 => 50, + 4 => 64, + 5 => 80, + 6 => 100, + 7 => 125, #PH + 8 => 160, #PH + 9 => 200, + 10 => 250, + 11 => 320, #PH + 12 => 400, + 13 => 500, + 14 => 640, + 15 => 800, + 16 => 1000, + 17 => 1250, + 18 => 1600, #PH + 19 => 2000, #PH + 20 => 2500, #PH + 21 => 3200, #PH + 22 => 4000, + 23 => 5000, + 24 => 6400, #PH + 25 => 8000, #PH + 26 => 10000, #PH + 27 => 12800, #PH + 28 => 16000, #PH + 29 => 20000, #PH + 30 => 25600, #PH + 31 => 32000, #PH + 32 => 40000, #PH + 33 => 51200, #PH + 34 => 64000, #PH (NC) + 35 => 80000, #PH (NC) + 36 => 102400, #27 + 37 => 128000, #PH (NC) + 38 => 160000, #PH (NC) + 39 => 204800, #27 + 40 => 256000, #PH (NC) + 41 => 320000, #PH (NC) + 42 => 409600, #PH (NC) + 43 => 512000, #PH (NC) + 44 => 640000, #PH (NC) + 45 => 819200, #PH (KP) + # Optio 330/430 (oddball) + 50 => 50, #PH + 100 => 100, #PH + 200 => 200, #PH + 400 => 400, #PH + 800 => 800, #PH + 1600 => 1600, #PH + 3200 => 3200, #PH + # 1/2 EV step values + 258 => 50, #PH (NC) + 259 => 70, #PH (NC) + 260 => 100, #19 + 261 => 140, #19 + 262 => 200, #19 + 263 => 280, #19 + 264 => 400, #19 + 265 => 560, #19 + 266 => 800, #19 + 267 => 1100, #19 + 268 => 1600, #19 + 269 => 2200, #PH + 270 => 3200, #PH + 271 => 4500, #PH + 272 => 6400, #PH + 273 => 9000, #PH + 274 => 12800, #PH + 275 => 18000, #PH + 276 => 25600, #PH + 277 => 36000, #PH + 278 => 51200, #PH + 279 => 72000, #PH (NC) + 280 => 102400, #PH (NC) + 281 => 144000, #PH (NC) + 282 => 204800, #PH (NC) + 283 => 288000, #PH (NC) + 284 => 409600, #PH (NC) + 285 => 576000, #PH (NC) + 286 => 819200, #PH (NC) + 65534 => 'Auto 2', #PH (Q/Q10/Q7 MOV) [how is this different from 65535?] + 65535 => 'Auto', #PH/31 (K-01/K-70 MP4) + }, + }, + 0x0015 => { #PH + Name => 'LightReading', + Format => 'int16s', # (because I may have seen negative numbers) + Writable => 'int16u', + # ranges from 0-12 for my Optio WP - PH + Notes => q{ + calibrated differently for different models. For the Optio WP, add 6 to get + approximate Light Value. May not be valid for some models, eg. Optio S + }, + }, + 0x0016 => [{ #PH + Name => 'ExposureCompensation', + Condition => '$count == 1', + Notes => q{ + some models write two values here. The second value is meaning of the + second value is not yet known + }, + Writable => 'int16u', + ValueConv => '($val - 50) / 10', + ValueConvInv => 'int($val * 10 + 50.5)', + PrintConv => '$val ? sprintf("%+.1f", $val) : 0', + PrintConvInv => 'Image::ExifTool::Exif::ConvertFraction($val)', + },{ + Name => 'ExposureCompensation', + Writable => 'int16u', + # (2 values for K-70, etc -- have only seen "0" for the 2nd value - PH) + Count => 2, + ValueConv => '$val =~ s/ .*//; ($val - 50) / 10', + ValueConvInv => 'int($val * 10 + 50.5) . " 0"', + PrintConv => '$val ? sprintf("%+.1f", $val) : 0', + PrintConvInv => 'Image::ExifTool::Exif::ConvertFraction($val)', + }], + 0x0017 => { #3 + Name => 'MeteringMode', + Writable => 'int16u', + PrintConv => { + 0 => 'Multi-segment', + 1 => 'Center-weighted average', + 2 => 'Spot', + # have seen value of 16 for E70 + }, + }, + 0x0018 => { #PH + Name => 'AutoBracketing', + Writable => 'int16u', + Count => -1, + Notes => q{ + 1 or 2 values: exposure bracket step in EV, then extended bracket if + available. Extended bracket values are printed as 'WB-BA', 'WB-GM', + 'Saturation', 'Sharpness', 'Contrast', 'Hue' or 'HighLowKey' followed by + '+1', '+2' or '+3' for step size + }, + # 1=.3ev, 2=.7, 3=1.0, ... 10=.5ev, 11=1.5, ... + ValueConv => [ '$val<10 ? $val/3 : $val-9.5' ], + ValueConvInv => [ 'abs($val-int($val)-.5)>0.05 ? int($val*3+0.5) : int($val+10)' ], + PrintConv => sub { + my @v = split(' ', shift); + $v[0] = sprintf('%.1f', $v[0]) if $v[0]; + if ($v[1]) { + my %s = (1=>'WB-BA',2=>'WB-GM',3=>'Saturation',4=>'Sharpness', + 5=>'Contrast',6=>'Hue',7=>'HighLowKey'); + my $t = $v[1] >> 8; + $v[1] = sprintf('%s+%d', $s{$t} || "Unknown($t)", $v[1] & 0xff); + } elsif (defined $v[1]) { + $v[1] = 'No Extended Bracket', + } + return join(' EV, ', @v); + }, + PrintConvInv => sub { + my @v = split(/, ?/, shift); + $v[0] =~ s/ ?EV//i; + if ($v[1]) { + my %s = ('WB-BA'=>1,'WB-GM'=>2,'Saturation'=>3,'Sharpness'=>4, + 'Contrast'=>5,'Hue'=>6,'HighLowKey'=>7); + if ($v[1] =~ /^No\b/i) { + $v[1] = 0; + } elsif ($v[1] =~ /Unknown\((\d+)\)\+(\d+)/i) { + $v[1] = ($1 << 8) + $2; + } elsif ($v[1] =~ /([\w-]+)\+(\d+)/ and $s{$1}) { + $v[1] = ($s{$1} << 8) + $2; + } else { + warn "Bad extended bracket\n"; + } + } + return "@v"; + }, + }, + 0x0019 => { #3 + Name => 'WhiteBalance', + Writable => 'int16u', + PrintConvColumns => 2, + PrintConv => { + 0 => 'Auto', + 1 => 'Daylight', + 2 => 'Shade', + 3 => 'Fluorescent', #2 + 4 => 'Tungsten', + 5 => 'Manual', + 6 => 'Daylight Fluorescent', #13 + 7 => 'Day White Fluorescent', #13 + 8 => 'White Fluorescent', #13 + 9 => 'Flash', #13 + 10 => 'Cloudy', #13 + 11 => 'Warm White Fluorescent', #PH (K-3) + 14 => 'Multi Auto', #PH (K-3) + 15 => 'Color Temperature Enhancement', #PH + 17 => 'Kelvin', #PH + 0xfffe => 'Unknown', #13 + 0xffff => 'User-Selected', #13 + }, + }, + 0x001a => { #5 + Name => 'WhiteBalanceMode', + Writable => 'int16u', + PrintConv => { + 1 => 'Auto (Daylight)', + 2 => 'Auto (Shade)', + 3 => 'Auto (Flash)', + 4 => 'Auto (Tungsten)', + 6 => 'Auto (Daylight Fluorescent)', #19 (NC) + 7 => 'Auto (Day White Fluorescent)', #17 (K100D guess) + 8 => 'Auto (White Fluorescent)', #17 (K100D guess) + 10 => 'Auto (Cloudy)', #17 (K100D guess) + # 0xfffd observed in K100D (ref 17) + 0xfffe => 'Unknown', #PH (you get this when shooting night sky shots) + 0xffff => 'User-Selected', + }, + }, + 0x001b => { #6 + Name => 'BlueBalance', + Writable => 'int16u', + ValueConv => '$val / 256', + ValueConvInv => 'int($val * 256 + 0.5)', + }, + 0x001c => { #6 + Name => 'RedBalance', + Writable => 'int16u', + ValueConv => '$val / 256', + ValueConvInv => 'int($val * 256 + 0.5)', + }, + 0x001d => [ + # Would be nice if there was a general way to determine units for FocalLength... + { + # Optio 30, 33WR, 43WR, 450, 550, 555, 750Z, X + Name => 'FocalLength', + Condition => '$self->{Model} =~ /^PENTAX Optio (30|33WR|43WR|450|550|555|750Z|X)\b/', + Writable => 'int32u', + Priority => 0, + ValueConv => '$val / 10', + ValueConvInv => '$val * 10', + PrintConv => 'sprintf("%.1f mm",$val)', + PrintConvInv => '$val=~s/\s*mm//;$val', + }, + { + # K100D, Optio 230, 330GS, 33L, 33LF, A10, M10, MX, MX4, S, S30, + # S4, S4i, S5i, S5n, S5z, S6, S45, S50, S55, S60, SV, Svi, W10, WP, + # *ist D, DL, DL2, DS, DS2 + # (Note: the Optio S6 seems to report the minimum focal length - PH) + Name => 'FocalLength', + Writable => 'int32u', + Priority => 0, + ValueConv => '$val / 100', + ValueConvInv => '$val * 100', + PrintConv => 'sprintf("%.1f mm",$val)', + PrintConvInv => '$val=~s/\s*mm//;$val', + }, + ], + 0x001e => { #3 + Name => 'DigitalZoom', + Writable => 'int16u', + ValueConv => '$val / 100', #14 + ValueConvInv => '$val * 100', #14 + }, + 0x001f => { + Name => 'Saturation', + Writable => 'int16u', + Count => -1, + Notes => '1 or 2 values', + PrintConvColumns => 2, + PrintConv => [{ # the *istD has pairs of values - PH + 0 => '-2 (low)', #PH + 1 => '0 (normal)', #PH + 2 => '+2 (high)', #PH + 3 => '-1 (medium low)', #2 + 4 => '+1 (medium high)', #2 + 5 => '-3 (very low)', #PH + 6 => '+3 (very high)', #PH (NC) + 7 => '-4 (minimum)', #PH (NC) + 8 => '+4 (maximum)', #PH (K-5) + 65535 => 'None', #PH (Monochrome) + }], + }, + 0x0020 => { + Name => 'Contrast', + Writable => 'int16u', + Count => -1, + Notes => '1 or 2 values', + PrintConvColumns => 2, + PrintConv => [{ # the *istD has pairs of values - PH + 0 => '-2 (low)', #PH + 1 => '0 (normal)', #PH + 2 => '+2 (high)', #PH + 3 => '-1 (medium low)', #2 + 4 => '+1 (medium high)', #2 + 5 => '-3 (very low)', #PH + 6 => '+3 (very high)', #PH (NC) + 7 => '-4 (minimum)', #PH (NC) + 8 => '+4 (maximum)', #PH (K-5) + 65535 => 'n/a', # got this for a Backlight Silhouette - PH (Q) + }], + }, + 0x0021 => { + Name => 'Sharpness', + Writable => 'int16u', + Count => -1, + Notes => '1 or 2 values', + PrintConvColumns => 2, + PrintConv => [{ # the *istD has pairs of values - PH + 0 => '-2 (soft)', #PH + 1 => '0 (normal)', #PH + 2 => '+2 (hard)', #PH + 3 => '-1 (medium soft)', #2 + 4 => '+1 (medium hard)', #2 + 5 => '-3 (very soft)', #(NC) + 6 => '+3 (very hard)', #(NC) + 7 => '-4 (minimum)', #PH (NC) + 8 => '+4 (maximum)', #PH (NC) + }], + }, + 0x0022 => { #PH + Name => 'WorldTimeLocation', + Groups => { 2 => 'Time' }, + Writable => 'int16u', + PrintConv => { + 0 => 'Hometown', + 1 => 'Destination', + }, + }, + 0x0023 => { #PH + Name => 'HometownCity', + Groups => { 2 => 'Time' }, + Writable => 'int16u', + SeparateTable => 'City', + PrintConv => \%pentaxCities, + }, + 0x0024 => { #PH + Name => 'DestinationCity', + Groups => { 2 => 'Time' }, + Writable => 'int16u', + SeparateTable => 'City', + PrintConv => \%pentaxCities, + }, + 0x0025 => { #PH + Name => 'HometownDST', + Groups => { 2 => 'Time' }, + Writable => 'int16u', + PrintConv => { 0 => 'No', 1 => 'Yes' }, + }, + 0x0026 => { #PH + Name => 'DestinationDST', + Groups => { 2 => 'Time' }, + Writable => 'int16u', + PrintConv => { 0 => 'No', 1 => 'Yes' }, + }, + 0x0027 => { #PH + Name => 'DSPFirmwareVersion', + Writable => 'undef', + # - for K10D, this comes from 4 bytes at offset 0x1c in the firmware file + %pentaxFirmwareID, + }, + 0x0028 => { #PH + Name => 'CPUFirmwareVersion', + Writable => 'undef', + # - for K10D, this comes from 4 bytes at offset 0x83fbf8 in firmware file + %pentaxFirmwareID, + }, + 0x0029 => { #5 + Name => 'FrameNumber', + # - one report that this has a value of 84 for the first image with a *istDS + # - another report that file number 4 has frameNumber 154 for *istD, and + # that framenumber jumped at about 9700 to around 26000 + # - with *istDS firmware 2.0, this tag was removed and ShutterCount was added + Writable => 'int32u', + }, + # 0x002b - definitely exposure related somehow - PH + 0x002d => [{ #PH + Name => 'EffectiveLV', + Condition => '$format eq "int16u"', + Notes => 'camera-calculated light value, but includes exposure compensation', + Writable => 'int16u', + Format => 'int16s', # (negative values are valid even though Pentax writes int16u) + ValueConv => '$val/1024', + ValueConvInv => '$val * 1024', + PrintConv => 'sprintf("%.1f",$val)', + PrintConvInv => '$val', + },{ + Name => 'EffectiveLV', + Condition => '$format eq "int32u"', + Writable => 'int32u', + Format => 'int32s', + ValueConv => '$val/1024', + ValueConvInv => '$val * 1024', + PrintConv => 'sprintf("%.1f",$val)', + PrintConvInv => '$val', + }], + 0x0032 => { #13 + Name => 'ImageEditing', + Writable => 'undef', + Format => 'int8u', + Count => 4, + PrintConv => { + '0 0' => 'None', #PH + '0 0 0 0' => 'None', + '0 0 0 4' => 'Digital Filter', + '1 0 0 0' => 'Resized', #PH (K-5) + '2 0 0 0' => 'Cropped', #PH + # note: doesn't apply to digital filters applied when picture is taken + '4 0 0 0' => 'Digital Filter 4', #PH (K10D, Ricoh WG-5) + '6 0 0 0' => 'Digital Filter 6', #PH (K-5) + '8 0 0 0' => 'Red-eye Correction', #PH (WG-10) + '16 0 0 0' => 'Frame Synthesis?', + }, + }, + 0x0033 => { #PH (K110D/K100D/K-m) + Name => 'PictureMode', + Writable => 'int8u', + Count => 3, + Relist => [ [0, 1], 2 ], # join values 0 and 1 for PrintConv + PrintConvColumns => 2, + PrintConv => [{ + # Program dial modes (from K110D) + '0 0' => 'Program', # (also on K10D, custom settings: Program Line 1, e-dial in Program 3, 4 or 5) + '0 1' => 'Hi-speed Program', #19 (K10D, custom settings: Program Line 2, e-dial in Program 3, 4 or 5) + '0 2' => 'DOF Program', #19 (K10D, custom settings: Program Line 3, e-dial in Program 3, 4 or 5) + '0 3' => 'MTF Program', #19 (K10D, custom settings: Program Line 4, e-dial in Program 3, 4 or 5) + '0 4' => 'Standard', #13 + '0 5' => 'Portrait', + '0 6' => 'Landscape', + '0 7' => 'Macro', + '0 8' => 'Sport', + '0 9' => 'Night Scene Portrait', + '0 10' => 'No Flash', + # SCN modes (menu-selected) (from K100D) + '0 11' => 'Night Scene', + '0 12' => 'Surf & Snow', + '0 13' => 'Text', + '0 14' => 'Sunset', + '0 15' => 'Kids', + '0 16' => 'Pet', + '0 17' => 'Candlelight', + '0 18' => 'Museum', + '0 19' => 'Food', + '0 20' => 'Stage Lighting', + '0 21' => 'Night Snap', + '0 23' => 'Blue Sky', # (Q) + '0 24' => 'Sunset', # (Q) + '0 26' => 'Night Scene HDR', # (Q) + '0 27' => 'HDR', # (Q) + '0 28' => 'Quick Macro', # (Q) + '0 29' => 'Forest', # (Q) + '0 30' => 'Backlight Silhouette', # (Q) + # AUTO PICT modes (auto-selected) + '1 4' => 'Auto PICT (Standard)', #13 + '1 5' => 'Auto PICT (Portrait)', #7 (K100D) + '1 6' => 'Auto PICT (Landscape)', # K110D + '1 7' => 'Auto PICT (Macro)', #13 + '1 8' => 'Auto PICT (Sport)', #13 + # *istD modes (ref 7) + '2 0' => 'Program (HyP)', #13 (K-5 Normal program line - PH) + '2 1' => 'Hi-speed Program (HyP)', #19 (K10D, custom settings: Program Line 2, e-dial in Program 1, 2) + '2 2' => 'DOF Program (HyP)', #19 (K10D, custom settings: Program Line 3, e-dial in Program 1, 2) + '2 3' => 'MTF Program (HyP)', #19 (K10D, custom settings: Program Line 4, e-dial in Program 1, 2) + '2 22' => 'Shallow DOF (HyP)', #PH (K-5) + '3 0' => 'Green Mode', #16 + '4 0' => 'Shutter Speed Priority', + '5 0' => 'Aperture Priority', + '6 0' => 'Program Tv Shift', + '7 0' => 'Program Av Shift', #19 + '8 0' => 'Manual', + '9 0' => 'Bulb', + '10 0' => 'Aperture Priority, Off-Auto-Aperture', + '11 0' => 'Manual, Off-Auto-Aperture', + '12 0' => 'Bulb, Off-Auto-Aperture', + '19 0' => 'Astrotracer', #29 + # extra K10D modes (ref 16) + '13 0' => 'Shutter & Aperture Priority AE', + '15 0' => 'Sensitivity Priority AE', + '16 0' => 'Flash X-Sync Speed AE', + '18 0' => 'Auto Program (Normal)', #PH (K-5) + '18 1' => 'Auto Program (Hi-speed)', #PH (NC) + '18 2' => 'Auto Program (DOF)', #PH (K-5) + '18 3' => 'Auto Program (MTF)', #PH (NC) + '18 22' => 'Auto Program (Shallow DOF)', #PH (NC) + '20 22' => 'Blur Control', #PH (Q) + '249 0' => 'Movie (TAv)', #31 + '250 0' => 'Movie (TAv, Auto Aperture)', #31 + '251 0' => 'Movie (Manual)', #31 + '252 0' => 'Movie (Manual, Auto Aperture)', #31 + '253 0' => 'Movie (Av)', #31 + '254 0' => 'Movie (Av, Auto Aperture)', #31 + '255 0' => 'Movie (P, Auto Aperture)', #31 + '255 4' => 'Video (4)', #PH (K-x,K-01) + },{ + # EV step size (ref 19) + 0 => '1/2 EV steps', + 1 => '1/3 EV steps', + }], + }, + 0x0034 => { #7/PH + Name => 'DriveMode', + Writable => 'int8u', + Count => 4, + PrintConv => [{ + 0 => 'Single-frame', # (also Interval Shooting for K-01 - PH) + 1 => 'Continuous', # (K-5 Hi) + 2 => 'Continuous (Lo)', #PH (K-5) + 3 => 'Burst', #PH (K20D) + 4 => 'Continuous (Medium)', #PH (K-3) + 255 => 'Video', #PH (K-x) + },{ + 0 => 'No Timer', + 1 => 'Self-timer (12 s)', + 2 => 'Self-timer (2 s)', + 15 => 'Video', #PH (Q MOV) + 16 => 'Mirror Lock-up', # (K-5) + 255 => 'n/a', #PH (K-x) + },{ + 0 => 'Shutter Button', # (also computer remote control - PH) + 1 => 'Remote Control (3 s delay)', #19 + 2 => 'Remote Control', #19 + 4 => 'Remote Continuous Shooting', # (K-5) + },{ + 0x00 => 'Single Exposure', + 0x01 => 'Multiple Exposure', + 0x02 => 'Composite Average', #31 + 0x03 => 'Composite Additive', #31 + 0x04 => 'Composite Bright', #31 + 0x08 => 'Interval Shooting', #31 + 0x0a => 'Interval Composite Average', #31 + 0x0b => 'Interval Composite Additive', #31 + 0x0c => 'Interval Composite Bright', #31 + 0x0f => 'Interval Movie', #PH (K-01) + 0x10 => 'HDR', #PH (645D) + 0x20 => 'HDR Strong 1', #PH (NC) (K-5) + 0x30 => 'HDR Strong 2', #PH (K-5) + 0x40 => 'HDR Strong 3', #PH (K-5) + 0x50 => 'HDR Manual', #31 (K-70 HDR 1 and HDR 2) + 0xe0 => 'HDR Auto', #PH (K-5, K-70) + 0xff => 'Video', #PH (K-x) + }], + }, + 0x0035 => { #PH + Name => 'SensorSize', + Format => 'int16u', + Count => 2, + Notes => 'includes masked pixels', + # values for various models (not sure why this is in 2um increments): + # 11894 7962 (K10D,K-m) 12012 7987 (*istDS,K100D,K110D) 12012 8019 (*istD), + # 12061 7988 (K-5) 12053 8005 (K-r,K-x) 14352 9535 (K20D,K-7) + # 22315 16711 (645) 12080 8008 (K-01) + ValueConv => 'my @a=split(" ",$val); $_/=500 foreach @a; join(" ",@a)', + ValueConvInv => 'my @a=split(" ",$val); $_*=500 foreach @a; join(" ",@a)', + PrintConv => 'sprintf("%.3f x %.3f mm", split(" ",$val))', + PrintConvInv => '$val=~s/\s*mm$//; $val=~s/\s*x\s*/ /; $val', + }, + 0x0037 => { #13 + Name => 'ColorSpace', + Writable => 'int16u', + PrintConv => { + 0 => 'sRGB', + 1 => 'Adobe RGB', + }, + }, + 0x0038 => { #5 (PEF only) + Name => 'ImageAreaOffset', + Writable => 'int16u', + Count => 2, + }, + 0x0039 => { #PH + Name => 'RawImageSize', + Writable => 'int16u', + Count => 2, + PrintConv => '$_=$val;s/ /x/;$_', + }, + 0x003c => { #7/PH + Name => 'AFPointsInFocus', + # not writable because I'm not decoding these 4 bytes fully: + # Nibble pattern: XSSSYUUU + # X = unknown (AF focused flag?, 0 or 1) + # SSS = selected AF point bitmask (0x000 or 0x7ff if unused) + # Y = unknown (observed 0,6,7,b,e, always 0 if SSS is 0x000 or 0x7ff) + # UUU = af points used + Format => 'int32u', + Notes => '*istD only', + ValueConv => '$val & 0x7ff', # ignore other bits for now + PrintConvColumns => 2, + PrintConv => { + 0 => '(none)', + BITMASK => { + 0 => 'Upper-left', + 1 => 'Top', + 2 => 'Upper-right', + 3 => 'Left', + 4 => 'Mid-left', + 5 => 'Center', + 6 => 'Mid-right', + 7 => 'Right', + 8 => 'Lower-left', + 9 => 'Bottom', + 10 => 'Lower-right', + }, + }, + }, + 0x003d => { #IB + Name => 'DataScaling', + Writable => 'int16u', + # divide by the second value of Pentax_0x0201 (WhitePoint), usually + # 8192, to get the floating point normalization factor. + # One of the examples of how this tag can be used is calculation of + # baseline exposure compensation (Adobe-style) for a PEF: + # log2(Pentax_0x007e)-14-0.5+log2(Pentax_0x003d)-13 + # or + # log2(Pentax_0x007e*(Pentax_0x003d/(2^13))/(2^14))-0.5 + # where + # makernotes:Pentax_0x003d/(2^13) is the normalization factor. (ref IB) + # - 8192 for most images, but occasionally 11571 for K100D/K110D, + # and 8289 or 8456 for the K-x (ref PH) + }, + 0x003e => { #PH + Name => 'PreviewImageBorders', + Writable => 'int8u', + Count => 4, + Notes => 'top, bottom, left, right', + }, + 0x003f => { #PH + Name => 'LensRec', + SubDirectory => { TagTable => 'Image::ExifTool::Pentax::LensRec' }, + }, + 0x0040 => { #PH + Name => 'SensitivityAdjust', + Writable => 'int16u', + ValueConv => '($val - 50) / 10', + ValueConvInv => '$val * 10 + 50', + PrintConv => '$val ? sprintf("%+.1f", $val) : 0', + PrintConvInv => '$val', + }, + 0x0041 => { #19 + Name => 'ImageEditCount', + Writable => 'int16u', + }, + 0x0047 => { #PH + Name => 'CameraTemperature', # (chassis temperature, ref forum6677) + Writable => 'int8s', + PrintConv => '"$val C"', + PrintConvInv => '$val=~s/ ?c$//i; $val', + }, + 0x0048 => { #19 + Name => 'AELock', + Writable => 'int16u', + PrintConv => { + 0 => 'Off', + 1 => 'On', + }, + }, + 0x0049 => { #13 + Name => 'NoiseReduction', + Writable => 'int16u', + PrintConv => { 0 => 'Off', 1 => 'On' }, + }, + 0x004d => [{ #PH + Name => 'FlashExposureComp', + Condition => '$count == 1', + Writable => 'int32s', + ValueConv => '$val / 256', + ValueConvInv => 'int($val * 256 + ($val > 0 ? 0.5 : -0.5))', + PrintConv => '$val ? sprintf("%+.1f", $val) : 0', + PrintConvInv => 'Image::ExifTool::Exif::ConvertFraction($val)', + },{ #PH (K-3) + Name => 'FlashExposureComp', + Writable => 'int8s', + Count => 2, # (don't know what the 2nd number is for) + ValueConv => [ '$val / 6' ], + ValueConvInv => [ '$val / 6' ], + PrintConv => [ '$val ? sprintf("%+.1f", $val) : 0' ], + PrintConvInv => [ 'Image::ExifTool::Exif::ConvertFraction($val)' ], + }], + 0x004f => { #PH + Name => 'ImageTone', # (Called CustomImageMode in K20D manual) + Writable => 'int16u', + PrintConvColumns => 2, + PrintConv => { + 0 => 'Natural', + 1 => 'Bright', + 2 => 'Portrait', # (K20D/K200D) + 3 => 'Landscape', # (K20D) + 4 => 'Vibrant', # (K20D) + 5 => 'Monochrome', # (K20D) + 6 => 'Muted', # (645D) + 7 => 'Reversal Film', # (645D) (Ricoh WG-5 "Slide Film") + 8 => 'Bleach Bypass', # (K-5) + 9 => 'Radiant', # (Q) + 10 => 'Cross Processing', #31 (K-70) + 11 => 'Flat', #31 (K-70) + # 256 - seen for GR III + # 262 - seen for GR III + }, + }, + 0x0050 => { #PH + Name => 'ColorTemperature', + Writable => 'int16u', + RawConv => '$val ? $val : undef', + ValueConv => '53190 - $val', + ValueConvInv => '53190 - $val', + }, + # 0x0053-0x005a - not in JPEG images - PH + 0x0053 => { #28 + Name => 'ColorTempDaylight', + %colorTemp, + Notes => '0x0053-0x005a are 3 numbers: Kelvin, shift AB, shift GM', + }, + 0x0054 => { Name => 'ColorTempShade', %colorTemp }, #28 + 0x0055 => { Name => 'ColorTempCloudy', %colorTemp }, #28 + 0x0056 => { Name => 'ColorTempTungsten', %colorTemp }, #28 + 0x0057 => { Name => 'ColorTempFluorescentD', %colorTemp }, #28 + 0x0058 => { Name => 'ColorTempFluorescentN', %colorTemp }, #28 + 0x0059 => { Name => 'ColorTempFluorescentW', %colorTemp }, #28 + 0x005a => { Name => 'ColorTempFlash', %colorTemp }, #28 + 0x005c => [{ #PH + Name => 'ShakeReductionInfo', + Condition => '$count == 4', # (2 bytes for the K-3) + Format => 'undef', # (written as int8u) - do this just to save time converting the value + SubDirectory => { TagTable => 'Image::ExifTool::Pentax::SRInfo' }, + },{ + Name => 'ShakeReductionInfo', + Format => 'undef', # (written as int8u) - do this just to save time converting the value + SubDirectory => { TagTable => 'Image::ExifTool::Pentax::SRInfo2' }, + }], + 0x005d => { #JD/PH + # (used by all Pentax DSLR's except *istD and *istDS until firmware 2.0 - PH) + # Observed values for the first shot of a new K10D are: 81 [PH], 181 [19], + # 246 [7], and 209 [18 (one of the first 20 shots)], so there must be a number + # of test images shot in the factory. (But my new K-5 started at 1 - PH) + # This count includes shutter actuations even if they don't result in a + # recorded image (eg. manual white balance frame or digital preview), but + # does not include actuations due to Live View or video recording - PH + Name => 'ShutterCount', + Writable => 'undef', + Count => 4, + Notes => q{ + Note: May be reset by servicing! Also, does not include shutter actuations + for live view or video recording + }, + # raw value is a big-endian 4-byte integer, encrypted using Date and Time + RawConv => 'length($val) == 4 ? unpack("N",$val) : undef', + RawConvInv => q{ + my $val = Image::ExifTool::Pentax::CryptShutterCount($val,$self); + return pack('N', $val); + }, + ValueConv => \&CryptShutterCount, + ValueConvInv => '$val', + }, + # 0x005e - + 0x0060 => { #PH (K-5) + Name => 'FaceInfo', + Format => 'undef', # (written as int8u) + SubDirectory => { TagTable => 'Image::ExifTool::Pentax::FaceInfo' }, + }, + 0x0062 => { #forum4803 + Name => 'RawDevelopmentProcess', + Condition => '$$self{Make} =~ /^(PENTAX|RICOH)/', # rules out Kodak, which also use this tag + Writable => 'int16u', + PrintConv => { + 1 => '1 (K10D,K200D,K2000,K-m)', + 3 => '3 (K20D)', + 4 => '4 (K-7)', + 5 => '5 (K-x)', + 6 => '6 (645D)', + 7 => '7 (K-r)', + 8 => '8 (K-5,K-5II,K-5IIs)', + 9 => '9 (Q)', + 10 => '10 (K-01,K-30,K-50,K-500)', + 11 => '11 (Q10)', + 12 => '12 (MX-1,Q-S1,Q7)', + 13 => '13 (K-3,K-3II)', + 14 => '14 (645Z)', + 15 => '15 (K-S1,K-S2)', #PH + 16 => '16 (K-1)', #PH + 17 => '17 (K-70)', #29 + 18 => '18 (KP)', #PH + 19 => '19 (GR III)', #PH + }, + }, + 0x0067 => { #PH (K-5) + Name => 'Hue', + Writable => 'int16u', + PrintConvColumns => 2, + PrintConv => { + 0 => -2, + 1 => 'Normal', + 2 => 2, + 3 => -1, + 4 => 1, + 5 => -3, + 6 => 3, + 7 => -4, + 8 => 4, + 65535 => 'None', # (Monochrome) + }, + }, + # 0x0067 - int16u: 1 [and 65535 in Monochrome] (K20D,K200D) - PH + 0x0068 => { #PH + Name => 'AWBInfo', + Format => 'undef', # (written as int8u) + SubDirectory => { TagTable => 'Image::ExifTool::Pentax::AWBInfo' }, + }, + 0x0069 => { #PH (K20D, K-5, K-01 highlights only) + Name => 'DynamicRangeExpansion', + Notes => q{ + called highlight correction by Pentax for the K20D, K-5, K-01 and maybe + other models + }, + Writable => 'undef', + Format => 'int8u', + Count => 4, + PrintConv => [{ + 0 => 'Off', + 1 => 'On', + },{ + 0 => 0, + 1 => 'Enabled', # (K-01) + 2 => 'Auto', # (K-01) + }], + }, + 0x006b => { #PH (K-5) + Name => 'TimeInfo', + Format => 'undef', # (written as int8u) + SubDirectory => { TagTable => 'Image::ExifTool::Pentax::TimeInfo' }, + }, + 0x006c => { #PH (K-5) + Name => 'HighLowKeyAdj', + Description => 'High/Low Key Adj', + Writable => 'int16s', + Count => 2, + PrintConvColumns => 3, + PrintConv => { + '-4 0' => -4, + '-3 0' => -3, + '-2 0' => -2, + '-1 0' => -1, + '0 0' => 0, + '1 0' => 1, + '2 0' => 2, + '3 0' => 3, + '4 0' => 4, + }, + }, + 0x006d => { #PH (K-5) + Name => 'ContrastHighlight', + Writable => 'int16s', + Count => 2, + PrintConvColumns => 3, + PrintConv => { + '-4 0' => -4, + '-3 0' => -3, + '-2 0' => -2, + '-1 0' => -1, + '0 0' => 0, + '1 0' => 1, + '2 0' => 2, + '3 0' => 3, + '4 0' => 4, + }, + }, + 0x006e => { #PH (K-5) + Name => 'ContrastShadow', + Writable => 'int16s', + Count => 2, + PrintConvColumns => 3, + PrintConv => { + '-4 0' => -4, + '-3 0' => -3, + '-2 0' => -2, + '-1 0' => -1, + '0 0' => 0, + '1 0' => 1, + '2 0' => 2, + '3 0' => 3, + '4 0' => 4, + }, + }, + 0x006f => { #PH (K-5) + Name => 'ContrastHighlightShadowAdj', + Description => 'Contrast Highlight/Shadow Adj', + Writable => 'int8u', + PrintConv => { + 0 => 'Off', + 1 => 'On', + }, + }, + 0x0070 => { #PH (K-5) + Name => 'FineSharpness', + Writable => 'int8u', + Count => -1, # 1 for K20/K200, 2 for K-5 + PrintConv => [{ + 0 => 'Off', + 1 => 'On', + },{ + 0 => 'Normal', + 2 => 'Extra fine', + }], + }, + 0x0071 => { #PH (K20D,K-x) + Name => 'HighISONoiseReduction', + Format => 'int8u', + PrintConv => [{ + 0 => 'Off', + 1 => 'Weakest', + 2 => 'Weak', # (called "Low" by K-x) + 3 => 'Strong', # (called "High" by K-x) + 4 => 'Medium', + 255 => 'Auto', # (K-5) + },{ + 0 => 'Inactive', + 1 => 'Active', + 2 => 'Active (Weak)', # (K-5) + 3 => 'Active (Strong)', # (K-5) + 4 => 'Active (Medium)', # (K-5) + },{ # Start ISO level for NR (K-x) + 48 => 'ISO>400', + 56 => 'ISO>800', + 64 => 'ISO>1600', + 72 => 'ISO>3200', + }], + }, + 0x0072 => { #JD (K20D) + Name => 'AFAdjustment', + Writable => 'int16s', + }, + 0x0073 => { #PH (K-5) + Name => 'MonochromeFilterEffect', + Writable => 'int16u', + PrintConvColumns => 2, + PrintConv => { + 65535 => 'None', + 1 => 'Green', + 2 => 'Yellow', + 3 => 'Orange', + 4 => 'Red', + 5 => 'Magenta', + 6 => 'Blue', + 7 => 'Cyan', + 8 => 'Infrared', + }, + }, + 0x0074 => { #PH (K-5) + Name => 'MonochromeToning', + Writable => 'int16u', + PrintConvColumns => 2, + PrintConv => { + 65535 => 'None', + 0 => -4, + 1 => -3, + 2 => -2, + 3 => -1, + 4 => 0, + 5 => 1, + 6 => 2, + 7 => 3, + 8 => 4, + }, + }, + 0x0076 => { #PH (K-5) + Name => 'FaceDetect', + Writable => 'int8u', + Count => 2, + # the Optio S12 writes this but not the FacesDetected tag, so get FacesDetected from here + DataMember => 'FacesDetected', + RawConv => '$val =~ / (\d+)/ and $$self{FacesDetected} = $1; $val', + # (the K-3 reports "On" even in phase-detect focus modes) + PrintConv => [ + '$val ? "On ($val faces max)" : "Off"', + '"$val faces detected"', + ], + PrintConvInv => [ + '$val =~ /(\d+)/ ? $1 : 0', + '$val =~ /(\d+)/ ? $1 : 0', + ], + }, + 0x0077 => { #PH (K-5) + # set by taking a picture with face detect AF, + # but it isn't reset until camera is turned off? - PH + Name => 'FaceDetectFrameSize', + Writable => 'int16u', + Count => 2, + }, + # 0x0078 - int16u[2]: '0 0' (K-5,K-7,K-r,K-x) + 0x0079 => { #PH + Name => 'ShadowCorrection', + Writable => 'int8u', + Count => -1, + PrintConvColumns => 2, + PrintConv => { + # (1 value for K-m/K2000, 2 for 645D) + 0 => 'Off', + 1 => 'On', + 2 => 'Auto 2', # (NC, WG-3) + '0 0' => 'Off', + '1 1' => 'Weak', + '1 2' => 'Normal', + '1 3' => 'Strong', + '2 4' => 'Auto', # (K-01) + }, + }, + 0x007a => { #PH + Name => 'ISOAutoParameters', + Writable => 'int8u', + Count => 2, + PrintConv => { + '1 0' => 'Slow', + '2 0' => 'Standard', + '3 0' => 'Fast', + # '1 108' - seen for GR III + }, + }, + 0x007b => { #PH (K-5) + Name => 'CrossProcess', + Writable => 'int8u', + PrintConvColumns => 2, + PrintConv => { + 0 => 'Off', + 1 => 'Random', + 2 => 'Preset 1', + 3 => 'Preset 2', + 4 => 'Preset 3', + 33 => 'Favorite 1', + 34 => 'Favorite 2', + 35 => 'Favorite 3', + }, + }, + 0x007d => { #PH + Name => 'LensCorr', + Format => 'undef', # (written as int8u) + SubDirectory => { TagTable => 'Image::ExifTool::Pentax::LensCorr' }, + }, + 0x007e => { #IB + Name => 'WhiteLevel', # (with black level already subtracted) + Writable => 'int32u', + # 15859,15860,15864,15865,16315 (K-5 PEF/DNG only) - PH + # 3934, 3935 (Q DNG) - PH + }, + 0x007f => { #PH (K-5) + Name => 'BleachBypassToning', + Writable => 'int16u', + PrintConvColumns => 2, + PrintConv => { + 65535 => 'n/a', #31 + 0 => 'Off', #31 + 1 => 'Green', + 2 => 'Yellow', + 3 => 'Orange', + 4 => 'Red', + 5 => 'Magenta', + 6 => 'Purple', + 7 => 'Blue', + 8 => 'Cyan', + }, + }, + 0x0080 => { #PH (Q) + Name => 'AspectRatio', + PrintConv => { + 0 => '4:3', + 1 => '3:2', + 2 => '16:9', + 3 => '1:1', + }, + }, + # 0x0081 - int8u: 0 (Q) + 0x0082 => { + Name => 'BlurControl', + Writable => 'int8u', + Count => 4, + PrintConv => [ + { + 0 => 'Off', + 1 => 'Low', + 2 => 'Medium', + 3 => 'High', + }, + undef, # 0 with BlurControl is Off, seen 0,1,3 when on (related to subject distance?) + undef, # 0 with BlurControl Off, 45 when on + undef, # always 0 + ], + }, + # 0x0083 - int8u: 0 (Q DNG) + # 0x0084 - int8u: 0 (Q) + 0x0085 => { #PH + Name => 'HDR', + Format => 'int8u', + Count => 4, + PrintConv => [{ # (K-01,K-3) + 0 => 'Off', + 1 => 'HDR Auto', + 2 => 'HDR 1', + 3 => 'HDR 2', + 4 => 'HDR 3', + 5 => 'HDR Advanced', #29 (K-1) + },{ # (K-01) + 0 => 'Auto-align Off', + 1 => 'Auto-align On', + },{ + # not sure about this - PH + # - you can set HDR "Exposure Bracket Value" with the K-3 + # - guessed from imaging-resource K-3 samples K3OUTBHDR_A{1,2,3} + 0 => 'n/a', + 4 => '1 EV', + 8 => '2 EV', + 12 => '3 EV', # (get this from K-01, but can't set EV) + }, + # (4th number is always 0) + ], + }, + # 0x0086 - int8u: 0, 111[Sport,Pet] (Q) - related to Tracking FocusMode? + # 0x0087 - int8u: 0 (Q) + 0x0088 => { #PH + Name => 'NeutralDensityFilter', + Writable => 'int8u', + Count => -1, + PrintConv => { + 0 => 'Off', + 1 => 'On', + '0 2' => 'Off (0 2)', #PH (NC, GR III) + '1 2' => 'On (1 2)', #PH (NC, GR III) + }, + }, + 0x008b => { #PH (LS465) + Name => 'ISO', + Priority => 0, + Writable => 'int32u', + }, + 0x0092 => { #31 + Name => 'IntervalShooting', + Notes => '2 numbers: 1. Shot number 2. Total number of shots', + Writable => 'int16u', + Count => 2, + PrintConv => { + '0 0' => 'Off', + OTHER => sub { + my ($val, $inv) = @_; + if ($inv) { + $val =~ tr/0-9 //dc; + } else { + $val =~ s/(\d+) (\d+)/Shot $1 of $2/; + } + return $val; + }, + }, + }, + 0x0095 => { #31 + Name => 'SkinToneCorrection', + Writable => 'int8s', + Count => 2, + PrintConv => { + '0 0' => 'Off', + '1 1' => 'On (type 1)', + '1 2' => 'On (type 2)', + }, + }, + 0x0096 => { #31 + Name => 'ClarityControl', + Writable => 'int8s', + Count => 2, + PrintConv => { + '0 0' => 'Off', + OTHER => sub { + my ($val, $inv) = @_; + if ($inv) { + $val =~ /(\d+ -?\d+)/ and return $1; + return ("1 $val"); + } elsif ($val =~ /^1 (-?\d+)$/) { + return $1 ? sprintf('%+d', $1) : 0; + } else { + return "Unknown ($val)"; + } + }, + }, + }, + 0x0200 => { #5 + Name => 'BlackPoint', + Writable => 'int16u', + Count => 4, + }, + 0x0201 => { #5 + # (this doesn't change for different fixed white balances in JPEG images: Daylight, + # Tungsten, Kelvin, etc -- always "8192 8192 8192 8192", but it varies for these in + # RAW images, all images in Auto, for different Manual WB settings, and for images + # taken via Pentax Remote Assistant) - PH + Name => 'WhitePoint', + Writable => 'int16u', + Count => 4, + }, + # 0x0202: int16u[4]: all 0's in all my samples + 0x0203 => { #JD (not really sure what these mean) + Name => 'ColorMatrixA', # (camera RGB to sRGB matrix, *ist D, ref IB) + Writable => 'int16s', + Count => 9, + ValueConv => 'join(" ",map({ $_/8192 } split(" ",$val)))', + ValueConvInv => 'join(" ",map({ int($_*8192 + ($_<0?-0.5:0.5)) } split(" ",$val)))', + PrintConv => 'join(" ",map({sprintf("%.5f",$_)} split(" ",$val)))', + PrintConvInv => '"$val"', + }, + 0x0204 => { #JD + Name => 'ColorMatrixB', # (camera RGB to Adobe RGB matrix, *ist D, ref IB) + Writable => 'int16s', + Count => 9, + ValueConv => 'join(" ",map({ $_/8192 } split(" ",$val)))', + ValueConvInv => 'join(" ",map({ int($_*8192 + ($_<0?-0.5:0.5)) } split(" ",$val)))', + PrintConv => 'join(" ",map({sprintf("%.5f",$_)} split(" ",$val)))', + PrintConvInv => '"$val"', + }, + 0x0205 => [{ #19 + Name => 'CameraSettings', + # size: *istD/*istDs/K100D/K110D=16, K-m/K2000=14, K-7/K-x=19, + # K200D/K20D/K-5/645D=20, K-r=21, K10D=22, K-01=25 + Condition => '$count < 25', # (not valid for the K-01) + SubDirectory => { + TagTable => 'Image::ExifTool::Pentax::CameraSettings', + ByteOrder => 'BigEndian', + }, + },{ + Name => 'CameraSettingsUnknown', + SubDirectory => { + TagTable => 'Image::ExifTool::Pentax::CameraSettingsUnknown', + ByteOrder => 'BigEndian', + }, + }], + 0x0206 => [{ #PH + Name => 'AEInfo', + # size: *istD/*istDs/K100D/K110D=14, K10D/K200D/K20D=16, K-m/K2000=20, + # K-7/K-x=24, K-5/K-r/645D=25 + Condition => '$count <= 25 and $count != 21 and $$self{AEInfoSize} = $count', + SubDirectory => { TagTable => 'Image::ExifTool::Pentax::AEInfo' }, + },{ + Name => 'AEInfo2', + # size: K-01=21 + Condition => '$count == 21', + SubDirectory => { TagTable => 'Image::ExifTool::Pentax::AEInfo2' }, + },{ + Name => 'AEInfo3', + # size: K-30=48 + Condition => '$count == 48', + SubDirectory => { TagTable => 'Image::ExifTool::Pentax::AEInfo3' }, + },{ + Name => 'AEInfoUnknown', + # size: Q/Q10=34 + SubDirectory => { TagTable => 'Image::ExifTool::Pentax::AEInfoUnknown' }, + }], + 0x0207 => [ #PH + { + Name => 'LensInfo', + # the *ist series (and Samsung GX-1) always use the old format, and all + # other models but the K100D, K110D and K100D Super always use the newer + # format, and for the K110D/K110D we expect ff or 00 00 at byte 20 if + # it is the old format.) + Condition => q{ + $$self{Model}=~/(\*ist|GX-1[LS])/ or + ($$self{Model}=~/(K100D|K110D)/ and $$valPt=~/^.{20}(\xff|\0\0)/s) + }, + SubDirectory => { TagTable => 'Image::ExifTool::Pentax::LensInfo' }, + },{ + Name => 'LensInfo', + Condition => '$count != 90 and $count != 91 and $count != 80 and $count != 128 and $count != 168', + SubDirectory => { TagTable => 'Image::ExifTool::Pentax::LensInfo2' }, + },{ + Name => 'LensInfo', # 645D + Condition => '$count == 90', + SubDirectory => { TagTable => 'Image::ExifTool::Pentax::LensInfo3' }, + },{ + Name => 'LensInfo', # K-r, K-5, K-5II + Condition => '$count == 91', + SubDirectory => { TagTable => 'Image::ExifTool::Pentax::LensInfo4' }, + },{ + Name => 'LensInfo', # K-01, K-30, K-50, K-500, K-3, K-3II + Condition => '$count == 80 or $count == 128', + SubDirectory => { TagTable => 'Image::ExifTool::Pentax::LensInfo5' }, + } + # ($count == 168 - Ricoh GR III) + ], + 0x0208 => [ #PH + { + Name => 'FlashInfo', + Condition => '$count == 27', + SubDirectory => { TagTable => 'Image::ExifTool::Pentax::FlashInfo' }, + }, + { + Name => 'FlashInfoUnknown', + SubDirectory => { TagTable => 'Image::ExifTool::Pentax::FlashInfoUnknown' }, + }, + ], + 0x0209 => { #PH + Name => 'AEMeteringSegments', + Format => 'int8u', + Count => -1, + Notes => q{ + measurements from each of the 16 AE metering segments for models such as the + K10D, 77 metering segments for models such as the K-5, and 4050 metering + segments for the K-3, converted to LV + }, + %convertMeteringSegments, + # 16 metering segment 77 metering segment + # locations (ref JD, K10D) locations (ref PH, K-5) + # +-------------------------+ + # | 14 | +----------------------------------+ + # | +---+---+---+---+ | | 0 1 2 3 4 5 6 7 8 9 10 | + # | | 5 | 3/1\ 2| 4 | | | 11 12 13 14 15 16 17 18 19 20 21 | + # | +-+-+-+-+ - +-+-+-+-+ | | 22 23 24 25 26 27 28 29 30 31 32 | + # +--+ 9 | 7 ||0|| 6 | 8 +--+ | 33 34 35 36 37 38 39 40 41 42 43 | + # | +-+-+-+-+ - +-+-+-+-+ | | 44 45 46 47 48 49 50 51 52 53 54 | + # | |13 |11\ /10|12 | | | 55 56 57 58 59 60 61 62 63 64 65 | + # | +---+---+---+---+ | | 66 67 68 69 70 71 72 73 74 75 76 | + # | 15 | +----------------------------------+ + # +-------------------------+ + }, + 0x020a => { #PH/JD/19 + Name => 'FlashMeteringSegments', + Format => 'int8u', + Count => -1, + %convertMeteringSegments, + }, + 0x020b => { #PH/JD/19 + Name => 'SlaveFlashMeteringSegments', + Format => 'int8u', + Count => -1, + Notes => 'used in wireless control mode', + %convertMeteringSegments, + }, + 0x020d => { #PH + Name => 'WB_RGGBLevelsDaylight', + Writable => 'int16u', + Count => 4, + }, + 0x020e => { #PH + Name => 'WB_RGGBLevelsShade', + Writable => 'int16u', + Count => 4, + }, + 0x020f => { #PH + Name => 'WB_RGGBLevelsCloudy', + Writable => 'int16u', + Count => 4, + }, + 0x0210 => { #PH + Name => 'WB_RGGBLevelsTungsten', + Writable => 'int16u', + Count => 4, + }, + 0x0211 => { #PH + Name => 'WB_RGGBLevelsFluorescentD', + Writable => 'int16u', + Count => 4, + }, + 0x0212 => { #PH + Name => 'WB_RGGBLevelsFluorescentN', + Writable => 'int16u', + Count => 4, + }, + 0x0213 => { #PH + Name => 'WB_RGGBLevelsFluorescentW', + Writable => 'int16u', + Count => 4, + }, + 0x0214 => { #PH + Name => 'WB_RGGBLevelsFlash', + Writable => 'int16u', + Count => 4, + }, + 0x0215 => { #PH + Name => 'CameraInfo', + Format => 'undef', # (written as int32u) + SubDirectory => { TagTable => 'Image::ExifTool::Pentax::CameraInfo' }, + }, + 0x0216 => { #PH + Name => 'BatteryInfo', + SubDirectory => { + TagTable => 'Image::ExifTool::Pentax::BatteryInfo', + ByteOrder => 'BigEndian', # have seen makernotes changed to little-endian in DNG! + }, + }, + # 0x021a - undef[1068] (K-5) - ToneMode/Saturation mapping matrices (ref 28) + 0x021b => { #19 + Name => 'SaturationInfo', + Flags => [ 'Unknown', 'Binary' ], + Writable => 0, + Notes => 'only in PEF and DNG images', + # K10D values with various Saturation settings (ref 19): + # Very Low: 000000022820f9a0fe4000802660f92002e0fee01e402c40f880fb40ffc02b20f52002e0fe401ee0 + # Low: 000000022ae0f700fe20ff402840f88001e0fcc021602f60f560fb40fe602d20f48001c0fbc02280 + # Med Low: 000000022dc0f420fe20fe002a20f7e000c0fa8024c032c0f220fb20fce02f60f3c000a0f9202640 + # Normal: 000000023120f0e0fe00fc802c40f740ffa0f7e028803660ee80fb20fb4031c0f300ff60f6202a80 + # Med High: 0000000234e0ed40fde0fae02ea0f680fe60f5002ca03a80ea80fb00f9603480f220fe00f2e02f20 + # High: 0000000238c0e960fde0f9203140f5a0fce0f1e031403f00e600fb00f7803760f120fc60ef403460 + # Very High:000000023d20e520fdc0f7203420f4c0fb60ee6036404400e120fae0f5403aa0f020fac0eb403a00 + }, + # 0x021c - undef[18] (K-5) + # 0x021d - undef[18] (K-5) + # 0x021e - undef[8] (K-5, Q) + 0x021f => { #JD + Name => 'AFInfo', + SubDirectory => { + # NOTE: Most of these subdirectories are 'undef' format, and as such the + # byte ordering is not changed when changed via the Pentax software (which + # will write a little-endian TIFF on an Intel system). So we must define + # BigEndian byte ordering for any of these which contain multi-byte values. - PH + ByteOrder => 'BigEndian', + TagTable => 'Image::ExifTool::Pentax::AFInfo', + }, + }, + 0x0220 => { #6 + Name => 'HuffmanTable', + Flags => [ 'Unknown', 'Binary' ], + Writable => 0, + Notes => 'found in K10D, K20D and K2000D PEF images', + }, + 0x0221 => { #28 + Name => 'KelvinWB', + SubDirectory => { TagTable => 'Image::ExifTool::Pentax::KelvinWB' }, + }, + 0x0222 => { #PH + Name => 'ColorInfo', + SubDirectory => { TagTable => 'Image::ExifTool::Pentax::ColorInfo' }, + }, + # 0x0223 - undef[198] (K-5 PEF/DNG only) + 0x0224 => { #19 + Name => 'EVStepInfo', + Drop => 200, # drop if larger than 200 bytes (40 kB in Pentax Q and Q10) + SubDirectory => { TagTable => 'Image::ExifTool::Pentax::EVStepInfo' }, + }, + 0x0226 => { #PH + Name => 'ShotInfo', # (may want to change this later when more is decoded) + SubDirectory => { TagTable => 'Image::ExifTool::Pentax::ShotInfo' }, + }, + 0x0227 => { #PH + Name => 'FacePos', + Condition => '$$self{FacesDetected}', # ignore if no faces to decode + SubDirectory => { TagTable => 'Image::ExifTool::Pentax::FacePos' }, + }, + 0x0228 => { #PH + Name => 'FaceSize', + Condition => '$$self{FacesDetected}', # ignore if no faces to decode + SubDirectory => { TagTable => 'Image::ExifTool::Pentax::FaceSize' }, + }, + 0x0229 => { #PH (verified) (K-m, K-x, K-7) + Name => 'SerialNumber', + Writable => 'string', + Notes => 'left blank by some cameras', + }, + 0x022a => { #PH (K-5) + Name => 'FilterInfo', + SubDirectory => { + TagTable => 'Image::ExifTool::Pentax::FilterInfo', + ByteOrder => 'BigEndian', + }, + }, + 0x022b => { #PH (K-5) + Name => 'LevelInfo', + SubDirectory => { TagTable => 'Image::ExifTool::Pentax::LevelInfo' }, + }, + # 0x022c - undef[46] (K-5) + 0x022d => { #28 + Name => 'WBLevels', + Condition => '$count == 100', # (just to be safe, but no other counts observed) + SubDirectory => { TagTable => 'Image::ExifTool::Pentax::WBLevels' }, + }, + 0x022e => { #PH (K-5 AVI videos) + Name => 'Artist', + Groups => { 2 => 'Author' }, + Writable => 'string', + }, + 0x022f => { #PH (K-5 AVI videos) + Name => 'Copyright', + Groups => { 2 => 'Author' }, + Writable => 'string', + }, + 0x0230 => { #PH (K-x AVI videos) (and K-70/Q-S1 MOV videos, ref 31) + Name => 'FirmwareVersion', + Notes => 'only in videos', + # this tag only exists in AVI/MOV videos, and for the K-x the value of + # this tag is "K-x Ver 1.00", which is the same as the EXIF Software + # tag. I used a different tag name for this because Pentax uses the + # AVI Software tag for a different string, "PENTAX K-x". + Writable => 'string', + }, + 0x0231 => { #PH (K-5) + Name => 'ContrastDetectAFArea', + Writable => 'int16u', + Count => 4, + Notes => q{ + AF area of the most recent contrast-detect focus operation. Coordinates + are left, top, width and height in a 720x480 frame, with Y downwards + }, + }, + 0x0235 => { #PH (K-5) + Name => 'CrossProcessParams', + # (it would be interesting to know exactly what these mean) + Writable => 'undef', + Format => 'int8u', + Count => 10, + }, + # 0x0236 - undef[52] (Q) + # 0x0237 - undef[11] possibly related to smart effect setting? (Q) + # 0x0238 - undef[9] (Q) + 0x0239 => { #PH + Name => 'LensInfoQ', + SubDirectory => { TagTable => 'Image::ExifTool::Pentax::LensInfoQ' }, + }, + # 0x023a - undef[10] (Q) + # 0x023b - undef[9] (K-01) + # 01a700500000000000, 91a700500000000000, 41a700500000000000, 002700500000000000 + # c00500400000000000, 400500500000000000, 4004ff420100000000, 4087ff480000000000 + 0x023f => { #31 (K-70 MOV videos) + Name => 'Model', + Description => 'Camera Model Name', + Writable => 'string', + }, + 0x0243 => { #PH + Name => 'PixelShiftInfo', + SubDirectory => { TagTable => 'Image::ExifTool::Pentax::PixelShiftInfo' }, + }, + 0x0245 => { #29 + Name => 'AFPointInfo', + SubDirectory => { TagTable => 'Image::ExifTool::Pentax::AFPointInfo' }, + }, + 0x03fe => { #PH + Name => 'DataDump', + Writable => 0, + PrintConv => '\$val', + }, + 0x03ff => [ #PH + { + Name => 'TempInfo', + Condition => '$$self{Model} =~ /K-(01|3|30|5|50|500)\b/', + SubDirectory => { TagTable => 'Image::ExifTool::Pentax::TempInfo' }, + },{ + Name => 'UnknownInfo', + SubDirectory => { TagTable => 'Image::ExifTool::Pentax::UnknownInfo' }, + }, + ], + 0x0402 => { #5 + Name => 'ToneCurve', + PrintConv => '\$val', + }, + 0x0403 => { #5 + Name => 'ToneCurves', + PrintConv => '\$val', + }, + # 0x0404 - undef[2086] (K-5) + 0x0405 => { #PH - undef[24200] (K-5 PEF/DNG only), undef[28672] (Q DNG) + Name => 'UnknownBlock', + Writable => 'undef', + Notes => 'large unknown data block in PEF/DNG images but not JPG images', + Flags => [ 'Unknown', 'Binary', 'Drop' ], + }, + # 0x0406 - undef[4116] (K-5) + # 0x0407 - undef[3072] (Q DNG) + # 0x0408 - undef[1024] (Q DNG) + 0x0e00 => { + Name => 'PrintIM', + Description => 'Print Image Matching', + Writable => 0, + SubDirectory => { + TagTable => 'Image::ExifTool::PrintIM::Main', + }, + }, +); + +# shake reduction information (ref PH) +%Image::ExifTool::Pentax::SRInfo = ( + %binaryDataAttrs, + GROUPS => { 0 => 'MakerNotes', 2 => 'Camera' }, + NOTES => 'Shake reduction information.', + 0 => { + Name => 'SRResult', + PrintConv => { #PH/JD + 0 => 'Not stabilized', + BITMASK => { + 0 => 'Stabilized', + # have seen 1 and 4 for 0.5 and 0.3 sec exposures with NR on and Bit 0 also set - ref 19 + # have seen bits 1,2,3,4 in K-5 AVI videos - PH + 6 => 'Not ready', + }, + }, + }, + 1 => { + Name => 'ShakeReduction', + PrintConv => { + 0 => 'Off', + 1 => 'On', + 4 => 'Off (4)', # (K20D, K200D, K-7, K-5) + 5 => 'On but Disabled', # (K20D, K-5) + # (can be 5 "On but Disabled" for K-5 with HDR [auto-align off only], + # Composition Adjust, DriveMode = Self-timer or Remote, and movie with SR off!) + 6 => 'On (Video)', # (K-7) + 7 => 'On (7)', #(NC) (K20D, K200D, K-m, K-5) + 15 => 'On (15)', # (K20D with Tamron 10-20mm @ 10mm) + 39 => 'On (mode 2)', # (K-01) (on during capture and live view) + 135 => 'On (135)', # (K-5IIs) + 167 => 'On (mode 1)', # (K-01) (on during capture only) + }, + }, + 2 => { + Name => 'SRHalfPressTime', + # (was SR_SWSToSWRTime: SWS=photometering switch, SWR=shutter release switch) + # (from http://www.patentstorm.us/patents/6597867-description.html) + # (here, SR could more accurately mean Shutter Release, not Shake Reduction) + # (not valid for K-01 - PH) + Notes => q{ + time from when the shutter button was half pressed to when the shutter was + released, including time for focusing. Not valid for some models + }, + # (constant of 60 determined from times: 2sec=127; 3sec=184,197; 4sec=244,249,243,246 - PH) + ValueConv => '$val / 60', + ValueConvInv => 'my $v=$val*60; $v < 255 ? int($v + 0.5) : 255', + PrintConv => 'sprintf("%.2f s",$val) . ($val > 254.5/60 ? " or longer" : "")', + PrintConvInv => '$val=~tr/0-9.//dc; $val', + }, + 3 => { #JD + Name => 'SRFocalLength', + ValueConv => '$val & 0x01 ? $val * 4 : $val / 2', + ValueConvInv => '$val <= 127 ? int($val) * 2 : int($val / 4) | 0x01', + PrintConv => '"$val mm"', + PrintConvInv => '$val=~s/\s*mm//;$val', + }, +); + +# shake reduction information for the K-3 (ref PH) +%Image::ExifTool::Pentax::SRInfo2 = ( + %binaryDataAttrs, + GROUPS => { 0 => 'MakerNotes', 2 => 'Camera' }, + NOTES => 'Shake reduction information for the K-3.', + 0 => { + Name => 'SRResult', + Unknown => 1, + PrintConv => { BITMASK => { + # Bit 0 - have seen this set in a few Pentax samples - PH + # Bit 6 - usually set when SR is Off, and occasionally when On - PH + # Bit 7 - set when AA simulation is on - PH + }}, + }, + 1 => { + Name => 'ShakeReduction', + PrintConv => { #forum5425 + 0 => 'Off', # (NC for K-3) + 1 => 'On', # (NC for K-3) + 4 => 'Off (AA simulation off)', + 5 => 'On but Disabled', # (NC for K-3) + 6 => 'On (Video)', # (NC for K-3) + 7 => 'On (AA simulation off)', + 8 => 'Off (AA simulation type 1) (8)', #forum8362 (K-70) + 12 => 'Off (AA simulation type 1)', # (AA linear motion) + 15 => 'On (AA simulation type 1)', # (AA linear motion) + 16 => 'Off (AA simulation type 2) (16)', #forum8362 (K-70) + 20 => 'Off (AA simulation type 2)', # (AA circular motion) + 23 => 'On (AA simulation type 2)', # (AA circular motion) + }, + }, +); + +# face detection information (ref PH, K-5) +%Image::ExifTool::Pentax::FaceInfo = ( + %binaryDataAttrs, + GROUPS => { 0 => 'MakerNotes', 2 => 'Camera' }, + DATAMEMBER => [ 0 ], + 0 => { + Name => 'FacesDetected', + RawConv => '$$self{FacesDetected} = $val', + }, + 2 => { + Name => 'FacePosition', + Notes => q{ + X/Y coordinates of the center of the main face in percent of frame size, + with positive Y downwards + }, + Format => 'int8u[2]', + }, +); + +# automatic white balance settings (ref PH, K-5) +%Image::ExifTool::Pentax::AWBInfo = ( + %binaryDataAttrs, + GROUPS => { 0 => 'MakerNotes', 2 => 'Camera' }, + # 0 - always 1? + # (data ends here for the K20D, K200D, K-x and K-7) + 0 => { + Name => 'WhiteBalanceAutoAdjustment', + PrintConv => { + 0 => 'Off', + 1 => 'On', + }, + }, + 1 => { # (exists only for K-5) + Name => 'TungstenAWB', + PrintConv => { + 0 => 'Subtle Correction', + 1 => 'Strong Correction', + }, + }, +); + +# world time settings (ref PH, K-5) +%Image::ExifTool::Pentax::TimeInfo = ( + %binaryDataAttrs, + GROUPS => { 0 => 'MakerNotes', 2 => 'Time' }, + 0.1 => { + Name => 'WorldTimeLocation', + Mask => 0x01, + PrintConv => { + 0 => 'Hometown', + 1 => 'Destination', + }, + }, + 0.2 => { + Name => 'HometownDST', + Mask => 0x02, + PrintConv => \%noYes, + }, + 0.3 => { + Name => 'DestinationDST', + Mask => 0x04, + PrintConv => \%noYes, + }, + 2 => { + Name => 'HometownCity', + SeparateTable => 'City', + PrintConv => \%pentaxCities, + }, + 3 => { + Name => 'DestinationCity', + SeparateTable => 'City', + PrintConv => \%pentaxCities, + }, +); + +# lens distortion correction (ref PH, K-5) +%Image::ExifTool::Pentax::LensCorr = ( + %binaryDataAttrs, + GROUPS => { 0 => 'MakerNotes', 2 => 'Image' }, + 0 => { + Name => 'DistortionCorrection', + PrintConv => { 0 => 'Off', 1 => 'On' }, + }, + 1 => { + Name => 'ChromaticAberrationCorrection', + PrintConv => { 0 => 'Off', 1 => 'On' }, + }, + 2 => { + Name => 'PeripheralIlluminationCorr', + PrintConv => { 0 => 'Off', 1 => 'On' }, + }, + 3 => { + Name => 'DiffractionCorrection', + PrintConv => { 0 => 'Off', 16 => 'On' }, + }, +); + +# camera settings (ref 19) +%Image::ExifTool::Pentax::CameraSettings = ( + %binaryDataAttrs, + GROUPS => { 0 => 'MakerNotes', 2 => 'Camera' }, + PRIORITY => 0, + NOTES => 'Camera settings information written by Pentax DSLR cameras.', + 0 => { + Name => 'PictureMode2', + PrintConv => { + 0 => 'Scene Mode', #PH + 1 => 'Auto PICT', #PH (NC) + 2 => 'Program AE', + 3 => 'Green Mode', + 4 => 'Shutter Speed Priority', + 5 => 'Aperture Priority', + 6 => 'Program Tv Shift', #PH + 7 => 'Program Av Shift', + 8 => 'Manual', #PH + 9 => 'Bulb', #PH + 10 => 'Aperture Priority, Off-Auto-Aperture', #PH (NC) + 11 => 'Manual, Off-Auto-Aperture', #PH + 12 => 'Bulb, Off-Auto-Aperture', #PH (NC) + 13 => 'Shutter & Aperture Priority AE', + 15 => 'Sensitivity Priority AE', + 16 => 'Flash X-Sync Speed AE', #PH + }, + }, + 1.1 => { + Name => 'ProgramLine', + # only set to other than Normal when in Program AE mode + Mask => 0x03, + PrintConv => { + 0 => 'Normal', + 1 => 'Hi Speed', + 2 => 'Depth', + 3 => 'MTF', + }, + }, + 1.2 => { # (K10D, K-5) + Name => 'EVSteps', + Mask => 0x20, + PrintConv => { + 0 => '1/2 EV Steps', + 1 => '1/3 EV Steps', + }, + }, + 1.3 => { # (this bit is set for movies with the K-5 - PH) + Name => 'E-DialInProgram', + # always set even when not in Program AE mode + Mask => 0x40, + PrintConv => { + 0 => 'Tv or Av', + 1 => 'P Shift', + }, + }, + 1.4 => { # (K10D, K-5) + Name => 'ApertureRingUse', + # always set even Aperture Ring is in A mode + Mask => 0x80, + PrintConv => { + 0 => 'Prohibited', + 1 => 'Permitted', + }, + }, + 2 => { + Name => 'FlashOptions', + Notes => 'the camera flash options settings, set even if the flash is off', + Mask => 0xf0, + # Note: These tags correlate with the FlashMode and InternalFlashMode values, + # and match what is displayed by the Pentax software + PrintConv => { + 0 => 'Normal', # (this value can occur in Green Mode) - ref 19 + 1 => 'Red-eye reduction', # (this value can occur in Green Mode) - ref 19 + 2 => 'Auto', # (this value can occur in other than Green Mode) - ref 19 + 3 => 'Auto, Red-eye reduction', #PH (this value can occur in other than Green Mode) - ref 19 + 5 => 'Wireless (Master)', + 6 => 'Wireless (Control)', + 8 => 'Slow-sync', + 9 => 'Slow-sync, Red-eye reduction', + 10 => 'Trailing-curtain Sync' + }, + }, + 2.1 => { + Name => 'MeteringMode2', + Mask => 0x0f, + Notes => 'may not be valid for some models, eg. *ist D', + PrintConv => { + 0 => 'Multi-segment', + BITMASK => { + 0 => 'Center-weighted average', + 1 => 'Spot', + }, + }, + }, + 3 => { + Name => 'AFPointMode', + Mask => 0xf0, + PrintConv => { + 0 => 'Auto', + BITMASK => { + 0 => 'Select', + 1 => 'Fixed Center', + # have seen bit 2 set in pre-production images (firmware 0.20) - PH + }, + }, + }, + 3.1 => { + Name => 'FocusMode2', + Mask => 0x0f, + PrintConv => { + 0 => 'Manual', + 1 => 'AF-S', + 2 => 'AF-C', + 3 => 'AF-A', #PH + }, + }, + 4 => { + Name => 'AFPointSelected2', + Format => 'int16u', + PrintConv => { + 0 => 'Auto', + BITMASK => { + 0 => 'Upper-left', + 1 => 'Top', + 2 => 'Upper-right', + 3 => 'Left', + 4 => 'Mid-left', + 5 => 'Center', + 6 => 'Mid-right', + 7 => 'Right', + 8 => 'Lower-left', + 9 => 'Bottom', + 10 => 'Lower-right', + }, + }, + }, + 6 => { + Name => 'ISOFloor', #PH + # manual ISO or minimum ISO in Auto ISO mode - PH + ValueConv => 'int(100*exp(Image::ExifTool::Pentax::PentaxEv($val-32)*log(2))+0.5)', + ValueConvInv => 'Image::ExifTool::Pentax::PentaxEvInv(log($val/100)/log(2))+32', + }, + 7 => { + Name => 'DriveMode2', + PrintConv => { + 0 => 'Single-frame', + BITMASK => { + 0 => 'Continuous', # (K-5 Hi) + 1 => 'Continuous (Lo)', #PH (K-5) + 2 => 'Self-timer (12 s)', #PH + 3 => 'Self-timer (2 s)', #PH + 4 => 'Remote Control (3 s delay)', + 5 => 'Remote Control', + 6 => 'Exposure Bracket', #PH/19 + 7 => 'Multiple Exposure', + }, + }, + }, + 8 => { + Name => 'ExposureBracketStepSize', + # This is set even when Exposure Bracket is Off (and the K10D + # displays Ò---Ó as the step size when you press the EB button) - DaveN + # because the last value is remembered and if you turn Exposure Bracket + # on the step size goes back to what it was before. + PrintConv => { + 3 => '0.3', + 4 => '0.5', + 5 => '0.7', + 8 => '1.0', #PH + 11 => '1.3', + 12 => '1.5', + 13 => '1.7', #(NC) + 16 => '2.0', #PH + }, + }, + 9 => { #PH/19 + Name => 'BracketShotNumber', + PrintHex => 1, + PrintConv => { + 0 => 'n/a', + 0x02 => '1 of 2', #PH (K-5) + 0x12 => '2 of 2', #PH (K-5) + 0x03 => '1 of 3', + 0x13 => '2 of 3', + 0x23 => '3 of 3', + 0x05 => '1 of 5', + 0x15 => '2 of 5', + 0x25 => '3 of 5', + 0x35 => '4 of 5', + 0x45 => '5 of 5', + }, + }, + 10 => { + Name => 'WhiteBalanceSet', + Mask => 0xf0, + # Not necessarily the white balance used; for example if the custom menu is set to + # "WB when using flash" -> "2 Flash", then this tag reports the camera setting while + # tag 0x0019 reports Flash if the Flash was used. + PrintConv => { + 0 => 'Auto', + 1 => 'Daylight', + 2 => 'Shade', + 3 => 'Cloudy', + 4 => 'Daylight Fluorescent', + 5 => 'Day White Fluorescent', + 6 => 'White Fluorescent', + 7 => 'Tungsten', + 8 => 'Flash', + 9 => 'Manual', + # The three Set Color Temperature settings refer to the 3 preset settings which + # can be saved in the menu (see page 123 of the K10D manual) + 12 => 'Set Color Temperature 1', + 13 => 'Set Color Temperature 2', + 14 => 'Set Color Temperature 3', + }, + }, + 10.1 => { + Name => 'MultipleExposureSet', + Mask => 0x0f, + PrintConv => { + 0 => 'Off', + 1 => 'On', + }, + }, + 13 => { + Name => 'RawAndJpgRecording', + Condition => '$$self{Model} =~ /(K10D|GX10)\b/', + Notes => 'K10D only', + # this is actually a bit field: - PH + # bit 0=JPEG, bit 2=PEF, bit 3=DNG; high nibble: 0x00=best, 0x20=better, 0x40=good + PrintHex => 1, + PrintConv => { + 0x01 => 'JPEG (Best)', #PH + 0x04 => 'RAW (PEF, Best)', + 0x05 => 'RAW+JPEG (PEF, Best)', + 0x08 => 'RAW (DNG, Best)', #PH (NC) + 0x09 => 'RAW+JPEG (DNG, Best)', #PH (NC) + 0x21 => 'JPEG (Better)', #PH + 0x24 => 'RAW (PEF, Better)', + 0x25 => 'RAW+JPEG (PEF, Better)', #PH + 0x28 => 'RAW (DNG, Better)', #PH + 0x29 => 'RAW+JPEG (DNG, Better)', #PH (NC) + 0x41 => 'JPEG (Good)', + 0x44 => 'RAW (PEF, Good)', #PH (NC) + 0x45 => 'RAW+JPEG (PEF, Good)', #PH (NC) + 0x48 => 'RAW (DNG, Good)', #PH (NC) + 0x49 => 'RAW+JPEG (DNG, Good)', + # have seen values of 0,2,34 for other models (not K10D) - PH + }, + }, + 14.1 => { #PH + Name => 'JpgRecordedPixels', + Condition => '$$self{Model} =~ /(K10D|GX10)\b/', + Notes => 'K10D only', + Mask => 0x03, + PrintConv => { + 0 => '10 MP', + 1 => '6 MP', + 2 => '2 MP', + }, + }, + 14.2 => { #PH (K-5) + Name => 'LinkAEToAFPoint', + Condition => '$$self{Model} =~ /K-5\b/', + Notes => 'K-5 only', + Mask => 0x01, + PrintConv => { 0 => 'Off', 1 => 'On' }, + }, + 14.3 => { #PH (K-5) + Name => 'SensitivitySteps', + Condition => '$$self{Model} =~ /K-5\b/', + Notes => 'K-5 only', + Mask => 0x02, + PrintConv => { + 0 => '1 EV Steps', + 1 => 'As EV Steps', + }, + }, + 14.4 => { #PH (K-5) + Name => 'ISOAuto', + Condition => '$$self{Model} =~ /K-5\b/', + Notes => 'K-5 only', + Mask => 0x04, + PrintConv => { 0 => 'Off', 1 => 'On' }, + }, + # 14.5 Mask 0x80 - changes for K-5 + 16 => { + Name => 'FlashOptions2', + Condition => '$$self{Model} =~ /(K10D|GX10)\b/', + Notes => 'K10D only; set even if the flash is off', + Mask => 0xf0, + # Note: the Normal and Auto values (0x00 to 0x30) do not tags always + # correlate with the FlashMode, InternalFlashMode and FlashOptions values + # however, these values seem to better match the K10D's actual functionality + # (always Auto in Green mode always Normal otherwise if one of the other options + # isn't selected) - ref 19 + # (these tags relate closely to InternalFlashMode values - PH) + PrintConv => { + 0 => 'Normal', # (this value never occurs in Green Mode) - ref 19 + 1 => 'Red-eye reduction', # (this value never occurs in Green Mode) - ref 19 + 2 => 'Auto', # (this value only occurs in Green Mode) - ref 19 + 3 => 'Auto, Red-eye reduction', # (this value only occurs in Green Mode) - ref 19 + 5 => 'Wireless (Master)', + 6 => 'Wireless (Control)', + 8 => 'Slow-sync', + 9 => 'Slow-sync, Red-eye reduction', + 10 => 'Trailing-curtain Sync' + }, + }, + 16.1 => { + Name => 'MeteringMode3', + Condition => '$$self{Model} =~ /(K10D|GX10)\b/', + Notes => 'K10D only', + Mask => 0x0f, + PrintConv => { + 0 => 'Multi-segment', + BITMASK => { + 0 => 'Center-weighted average', + 1 => 'Spot', + }, + }, + }, + # 16 Mask 0x0f - changes when changing EV steps? (K-5) + 17.1 => { + Name => 'SRActive', + Condition => '$$self{Model} =~ /(K10D|GX10)\b/', + Notes => q{ + K10D only; SR is active only when ShakeReduction is On, DriveMode is not + Remote or Self-timer, and Internal/ExternalFlashMode is not "On, Wireless" + }, + Mask => 0x80, + PrintConv => \%noYes, + }, + 17.2 => { + Name => 'Rotation', + Condition => '$$self{Model} =~ /(K10D|GX10)\b/', + Notes => 'K10D only', + Mask => 0x60, + PrintConv => { + 0 => 'Horizontal (normal)', + 1 => 'Rotate 180', + 2 => 'Rotate 90 CW', + 3 => 'Rotate 270 CW', + }, + }, + # Bit 0x08 is set on 3 of my 3000 shots to (All 3 were Shutter Priority + # but this may not mean anything with such a small sample) - ref 19 + 17.3 => { + Name => 'ISOSetting', + Condition => '$$self{Model} =~ /(K10D|GX10)\b/', + Notes => 'K10D only', + Mask => 0x04, + PrintConv => { + 0 => 'Manual', + 1 => 'Auto', + }, + }, + 17.4 => { + Name => 'SensitivitySteps', + Condition => '$$self{Model} =~ /(K10D|GX10)\b/', + Notes => 'K10D only', + Mask => 0x02, + PrintConv => { + 0 => '1 EV Steps', + 1 => 'As EV Steps', + }, + }, + # 17 Mask 0x08 - changed when changing Auto ISO range (K-5) + 18 => { + Name => 'TvExposureTimeSetting', + Condition => '$$self{Model} =~ /(K10D|GX10)\b/', + Notes => 'K10D only', + ValueConv => 'exp(-Image::ExifTool::Pentax::PentaxEv($val-68)*log(2))', + ValueConvInv => 'Image::ExifTool::Pentax::PentaxEvInv(-log($val)/log(2))+68', + PrintConv => 'Image::ExifTool::Exif::PrintExposureTime($val)', + PrintConvInv => 'Image::ExifTool::Exif::ConvertFraction($val)', + }, + 19 => { + Name => 'AvApertureSetting', + Condition => '$$self{Model} =~ /(K10D|GX10)\b/', + Notes => 'K10D only', + ValueConv => 'exp(Image::ExifTool::Pentax::PentaxEv($val-68)*log(2)/2)', + ValueConvInv => 'Image::ExifTool::Pentax::PentaxEvInv(log($val)*2/log(2))+68', + PrintConv => 'sprintf("%.1f",$val)', + PrintConvInv => '$val', + }, + 20 => { #PH + Name => 'SvISOSetting', + Condition => '$$self{Model} =~ /(K10D|GX10)\b/', + Notes => 'K10D only', + # ISO setting for sensitivity-priority mode + # (conversion may not give actual displayed values:) + # 32 => 100, 35 => 125, 36 => 140, 37 => 160, + # 40 => 200, 43 => 250, 44 => 280, 45 => 320, + # 48 => 400, 51 => 500, 52 => 560, 53 => 640, + # 56 => 800, 59 => 1000,60 => 1100,61 => 1250, 64 => 1600 + ValueConv => 'int(100*exp(Image::ExifTool::Pentax::PentaxEv($val-32)*log(2))+0.5)', + ValueConvInv => 'Image::ExifTool::Pentax::PentaxEvInv(log($val/100)/log(2))+32', + }, + 21 => { #PH + Name => 'BaseExposureCompensation', + Condition => '$$self{Model} =~ /(K10D|GX10)\b/', + Notes => 'K10D only; exposure compensation without auto bracketing', + ValueConv => 'Image::ExifTool::Pentax::PentaxEv(64-$val)', + ValueConvInv => '64-Image::ExifTool::Pentax::PentaxEvInv($val)', + PrintConv => '$val ? sprintf("%+.1f", $val) : 0', + PrintConvInv => 'Image::ExifTool::Exif::ConvertFraction($val)', + }, +); + +# unknown camera settings (K-01) +%Image::ExifTool::Pentax::CameraSettingsUnknown = ( + %binaryDataAttrs, + GROUPS => { 0 => 'MakerNotes', 2 => 'Camera' }, + NOTES => 'This information has not yet been decoded for models such as the K-01.', +); + +# auto-exposure information (ref PH) +%Image::ExifTool::Pentax::AEInfo = ( + %binaryDataAttrs, + GROUPS => { 0 => 'MakerNotes', 2 => 'Camera' }, + DATAMEMBER => [ 7 ], + NOTES => 'Auto-exposure information for most Pentax models.', + # instead of /8, should these be PentaxEv(), as in CameraSettings? - PH + 0 => { + Name => 'AEExposureTime', + Notes => 'val = 24 * 2**((32-raw)/8)', + ValueConv => '24*exp(-($val-32)*log(2)/8)', + ValueConvInv => '-log($val/24)*8/log(2)+32', + PrintConv => 'Image::ExifTool::Exif::PrintExposureTime($val)', + PrintConvInv => 'Image::ExifTool::Exif::ConvertFraction($val)', + }, + 1 => { + Name => 'AEAperture', + Notes => 'val = 2**((raw-68)/16)', + ValueConv => 'exp(($val-68)*log(2)/16)', + ValueConvInv => 'log($val)*16/log(2)+68', + PrintConv => 'sprintf("%.1f",$val)', + PrintConvInv => '$val', + }, + 2 => { + Name => 'AE_ISO', + Notes => 'val = 100 * 2**((raw-32)/8)', + ValueConv => '100*exp(($val-32)*log(2)/8)', + ValueConvInv => 'log($val/100)*8/log(2)+32', + PrintConv => 'int($val + 0.5)', + PrintConvInv => '$val', + }, + 3 => { + Name => 'AEXv', + Notes => 'val = (raw-64)/8', + ValueConv => '($val-64)/8', + ValueConvInv => '$val * 8 + 64', + }, + 4 => { + Name => 'AEBXv', + Format => 'int8s', + Notes => 'val = raw / 8', + ValueConv => '$val / 8', + ValueConvInv => '$val * 8', + }, + 5 => { + Name => 'AEMinExposureTime', #19 + Notes => 'val = 24 * 2**((32-raw)/8)', + ValueConv => '24*exp(-($val-32)*log(2)/8)', #JD + ValueConvInv => '-log($val/24)*8/log(2)+32', + PrintConv => 'Image::ExifTool::Exif::PrintExposureTime($val)', + PrintConvInv => 'Image::ExifTool::Exif::ConvertFraction($val)', + }, + 6 => { + Name => 'AEProgramMode', + PrintConvColumns => 2, + PrintConv => { + 0 => 'M, P or TAv', + 1 => 'Av, B or X', + 2 => 'Tv', + 3 => 'Sv or Green Mode', + 8 => 'Hi-speed Program', + 11 => 'Hi-speed Program (P-Shift)', #19 + 16 => 'DOF Program', #19 + 19 => 'DOF Program (P-Shift)', #19 + 24 => 'MTF Program', #19 + 27 => 'MTF Program (P-Shift)', #19 + 35 => 'Standard', + 43 => 'Portrait', + 51 => 'Landscape', + 59 => 'Macro', + 67 => 'Sport', + 75 => 'Night Scene Portrait', + 83 => 'No Flash', + 91 => 'Night Scene', + # 96 - seen for Pentax Q10 + 99 => 'Surf & Snow', + 104 => 'Night Snap', # (Q) + 107 => 'Text', + 115 => 'Sunset', + # 116 - seen for Pentax Q (vivid?) + 123 => 'Kids', + 131 => 'Pet', + 139 => 'Candlelight', + 144 => 'SCN', # (Q) + 160 => 'Program', # (Q) + # 142 - seen for Pentax Q in Program mode + 147 => 'Museum', + 184 => 'Shallow DOF Program', # (K-5) + 216 => 'HDR', # (Q) + }, + }, + 7 => { + Name => 'AEFlags', + Writable => 0, + Hook => '$size > 20 and $varSize += 1', + Notes => 'indices after this are incremented by 1 for some models', + # (this tag can't be unknown because the Hook must be evaluated + # to shift the following offsets if necessary. Instead, ignore + # the return value unless Unknown option used) + RawConv => '$$self{OPTIONS}{Unknown} ? $val : undef', + PrintConv => { #19 + # (seems to be the warnings displayed in the viewfinder for several bits) + BITMASK => { + # 0 - seen in extreme low light conditions (e.g. Lens Cap On) + # 1 - seen in 2 cases, Aperture Priority mode, Auto ISO at 100, + # Shutter speed at 1/4000 and aperture opened wider causing under exposure + # 2 - only (but not always) set in Shutter Speed Priority (seems to be when over/under exposed). + # In one case set when auto exposure compensation changed the Tv from 1/250 to 1/80. + # In another case set when external flash was in SB mode so did not fire. + 3 => 'AE lock', + 4 => 'Flash recommended?', # not 100% sure of this one + # 5 - seen lots... + # 6 - seen lots... + 7 => 'Aperture wide open', # mostly true... (Set for all my lenses except for DA* 16-50mm) + }, + }, + }, + # Note: Offsets below shifted by 1 if record size is > 20 bytes + # (implemented by the Hook above) + 8 => { #30 + Name => 'AEApertureSteps', + Notes => q{ + number of steps the aperture has been stopped down from wide open. There + are roughly 8 steps per F-stop for most lenses, or 18 steps for 645D lenses, + but it varies slightly by lens + }, + PrintConv => '$val == 255 ? "n/a" : $val', + PrintConvInv => '$val eq "n/a" ? 255 : $val', + }, + 9 => { #19 + Name => 'AEMaxAperture', + Notes => 'val = 2**((raw-68)/16)', + ValueConv => 'exp(($val-68)*log(2)/16)', + ValueConvInv => 'log($val)*16/log(2)+68', + PrintConv => 'sprintf("%.1f",$val)', + PrintConvInv => '$val', + }, + 10 => { #19 + Name => 'AEMaxAperture2', + Notes => 'val = 2**((raw-68)/16)', + ValueConv => 'exp(($val-68)*log(2)/16)', + ValueConvInv => 'log($val)*16/log(2)+68', + PrintConv => 'sprintf("%.1f",$val)', + PrintConvInv => '$val', + }, + 11 => { #19 + Name => 'AEMinAperture', + Notes => 'val = 2**((raw-68)/16)', + ValueConv => 'exp(($val-68)*log(2)/16)', + ValueConvInv => 'log($val)*16/log(2)+68', + PrintConv => 'sprintf("%.0f",$val)', + PrintConvInv => '$val', + }, + 12 => { #19 + Name => 'AEMeteringMode', + PrintConv => { + 0 => 'Multi-segment', + BITMASK => { + 4 => 'Center-weighted average', + 5 => 'Spot', + }, + }, + }, + 13 => { #30 + Name => 'AEWhiteBalance', + Condition => '$$self{AEInfoSize} == 24', # (not thoroughly tested for other sizes) + Notes => 'K7 and Kx', + Mask => 0xf0, + PrintConv => { + 0 => 'Standard', + 1 => 'Daylight', + 2 => 'Shade', + 3 => 'Cloudy', + 4 => 'Daylight Fluorescent', + 5 => 'Day White Fluorescent', + 6 => 'White Fluorescent', + 7 => 'Tungsten', + 8 => 'Unknown', #31 (or not set due to inadequate lighting) + }, + }, + 13.1 => { #30 + Name => 'AEMeteringMode2', + Condition => '$$self{AEInfoSize} == 24', # (not thoroughly tested for other sizes) + Notes => 'K7 and Kx, override for an incompatible metering mode setting', + Mask => 0x0f, + PrintConv => { + 0 => 'Multi-segment', + BITMASK => { + 0 => 'Center-weighted average', + 1 => 'Spot', + # 2 - seen for K7 AVI movie + }, + }, + }, + 14 => { #19 + Name => 'FlashExposureCompSet', + Description => 'Flash Exposure Comp. Setting', + Format => 'int8s', + Notes => q{ + reports the camera setting, unlike tag 0x004d which reports 0 in Green mode + or if flash was on but did not fire. Both this tag and 0x004d report the + setting even if the flash is off + }, + ValueConv => 'Image::ExifTool::Pentax::PentaxEv($val)', + ValueConvInv => 'Image::ExifTool::Pentax::PentaxEvInv($val)', + PrintConv => '$val ? sprintf("%+.1f", $val) : 0', + PrintConvInv => 'Image::ExifTool::Exif::ConvertFraction($val)', + }, + 21 => { #30 + Name => 'LevelIndicator', + PrintConv => '$val == 90 ? "n/a" : $val', + PrintConvInv => '$val eq "n/a" ? 90 : $val', + }, +); + +# auto-exposure information for the K-01 (ref PH) +%Image::ExifTool::Pentax::AEInfo2 = ( + %binaryDataAttrs, + GROUPS => { 0 => 'MakerNotes', 2 => 'Camera' }, + NOTES => 'Auto-exposure information for the K-01.', + # instead of /8, should these be PentaxEv(), as in CameraSettings? - PH + 2 => { + Name => 'AEExposureTime', + Notes => 'val = 24 * 2**((32-raw)/8)', + ValueConv => '24*exp(-($val-32)*log(2)/8)', + ValueConvInv => '-log($val/24)*8/log(2)+32', + PrintConv => 'Image::ExifTool::Exif::PrintExposureTime($val)', + PrintConvInv => 'Image::ExifTool::Exif::ConvertFraction($val)', + }, + 3 => { + Name => 'AEAperture', + Notes => 'val = 2**((raw-68)/16)', + ValueConv => 'exp(($val-68)*log(2)/16)', + ValueConvInv => 'log($val)*16/log(2)+68', + PrintConv => 'sprintf("%.1f",$val)', + PrintConvInv => '$val', + }, + 4 => { + Name => 'AE_ISO', + Notes => 'val = 100 * 2**((raw-32)/8)', + ValueConv => '100*exp(($val-32)*log(2)/8)', + ValueConvInv => 'log($val/100)*8/log(2)+32', + PrintConv => 'int($val + 0.5)', + PrintConvInv => '$val', + }, + 5 => { + Name => 'AEXv', + # this is the negative of exposure compensation, not including bracketing + Notes => 'val = (raw-64)/8', + ValueConv => '($val-64)/8', + ValueConvInv => '$val * 8 + 64', + }, + 6 => { + Name => 'AEBXv', + # this is the negative of auto exposure bracketing compensation + Format => 'int8s', + Notes => 'val = raw / 8', + ValueConv => '$val / 8', + ValueConvInv => '$val * 8', + }, + 8 => { + Name => 'AEError', + Format => 'int8s', + # this is usually zero except in M exposure mode, but it can be non-zero + # in other modes (eg. if you hit an aperture limit in Tv mode) + ValueConv => '-($val-64)/8', # (negate to make overexposed positive) + ValueConvInv => '-$val * 8 + 64', + }, + 11 => { + Name => 'AEApertureSteps', + Notes => q{ + number of steps the aperture has been stopped down from wide open. There + are roughly 8 steps per F-stop, but it varies slightly by lens + }, + PrintConv => '$val == 255 ? "n/a" : $val', + PrintConvInv => '$val eq "n/a" ? 255 : $val', + }, + 15 => { + Name => 'SceneMode', + PrintConvColumns => 2, + PrintConv => { + 0 => 'Off', + 1 => 'HDR', + 4 => 'Auto PICT', + 5 => 'Portrait', + 6 => 'Landscape', + 7 => 'Macro', + 8 => 'Sport', + 9 => 'Night Scene Portrait', + 10 => 'No Flash', + 11 => 'Night Scene', + 12 => 'Surf & Snow', + 14 => 'Sunset', + 15 => 'Kids', + 16 => 'Pet', + 17 => 'Candlelight', + 18 => 'Museum', + 20 => 'Food', + 21 => 'Stage Lighting', + 22 => 'Night Snap', + 25 => 'Night Scene HDR', + 26 => 'Blue Sky', + 27 => 'Forest', + 29 => 'Backlight Silhouette', + }, + }, + 16 => { + Name => 'AEMaxAperture', + Notes => 'val = 2**((raw-68)/16)', + ValueConv => 'exp(($val-68)*log(2)/16)', + ValueConvInv => 'log($val)*16/log(2)+68', + PrintConv => 'sprintf("%.1f",$val)', + PrintConvInv => '$val', + }, + 17 => { + Name => 'AEMaxAperture2', + Notes => 'val = 2**((raw-68)/16)', + ValueConv => 'exp(($val-68)*log(2)/16)', + ValueConvInv => 'log($val)*16/log(2)+68', + PrintConv => 'sprintf("%.1f",$val)', + PrintConvInv => '$val', + }, + 18 => { + Name => 'AEMinAperture', + Notes => 'val = 2**((raw-68)/16)', + ValueConv => 'exp(($val-68)*log(2)/16)', + ValueConvInv => 'log($val)*16/log(2)+68', + PrintConv => 'sprintf("%.0f",$val)', + PrintConvInv => '$val', + }, + 19 => { + Name => 'AEMinExposureTime', + Notes => 'val = 24 * 2**((32-raw)/8)', + ValueConv => '24*exp(-($val-32)*log(2)/8)', + ValueConvInv => '-log($val/24)*8/log(2)+32', + PrintConv => 'Image::ExifTool::Exif::PrintExposureTime($val)', + PrintConvInv => 'Image::ExifTool::Exif::ConvertFraction($val)', + }, +); + +# auto-exposure information for the K-30 (ref PH) +%Image::ExifTool::Pentax::AEInfo3 = ( + %binaryDataAttrs, + GROUPS => { 0 => 'MakerNotes', 2 => 'Camera' }, + NOTES => 'Auto-exposure information for the K-3, K-30, K-50 and K-500.', + # instead of /8, should these be PentaxEv(), as in CameraSettings? - PH + 16 => { + Name => 'AEExposureTime', + Notes => 'val = 24 * 2**((32-raw)/8)', + ValueConv => '24*exp(-($val-32)*log(2)/8)', + ValueConvInv => '-log($val/24)*8/log(2)+32', + PrintConv => 'Image::ExifTool::Exif::PrintExposureTime($val)', + PrintConvInv => 'Image::ExifTool::Exif::ConvertFraction($val)', + }, + 17 => { + Name => 'AEAperture', + Notes => 'val = 2**((raw-68)/16)', + ValueConv => 'exp(($val-68)*log(2)/16)', + ValueConvInv => 'log($val)*16/log(2)+68', + PrintConv => 'sprintf("%.1f",$val)', + PrintConvInv => '$val', + }, + 18 => { + Name => 'AE_ISO', + Notes => 'val = 100 * 2**((raw-32)/8)', + ValueConv => '100*exp(($val-32)*log(2)/8)', + ValueConvInv => 'log($val/100)*8/log(2)+32', + PrintConv => 'int($val + 0.5)', + PrintConvInv => '$val', + }, + 28 => { + Name => 'AEMaxAperture', + Notes => 'val = 2**((raw-68)/16)', + ValueConv => 'exp(($val-68)*log(2)/16)', + ValueConvInv => 'log($val)*16/log(2)+68', + PrintConv => 'sprintf("%.1f",$val)', + PrintConvInv => '$val', + }, + 29 => { + Name => 'AEMaxAperture2', + Notes => 'val = 2**((raw-68)/16)', + ValueConv => 'exp(($val-68)*log(2)/16)', + ValueConvInv => 'log($val)*16/log(2)+68', + PrintConv => 'sprintf("%.1f",$val)', + PrintConvInv => '$val', + }, + 30 => { + Name => 'AEMinAperture', + Notes => 'val = 2**((raw-68)/16)', + ValueConv => 'exp(($val-68)*log(2)/16)', + ValueConvInv => 'log($val)*16/log(2)+68', + PrintConv => 'sprintf("%.0f",$val)', + PrintConvInv => '$val', + }, + 31 => { + Name => 'AEMinExposureTime', + Notes => 'val = 24 * 2**((32-raw)/8)', + ValueConv => '24*exp(-($val-32)*log(2)/8)', + ValueConvInv => '-log($val/24)*8/log(2)+32', + PrintConv => 'Image::ExifTool::Exif::PrintExposureTime($val)', + PrintConvInv => 'Image::ExifTool::Exif::ConvertFraction($val)', + }, +); + +# unknown auto-exposure information (Q, Q10) +%Image::ExifTool::Pentax::AEInfoUnknown = ( + %binaryDataAttrs, + GROUPS => { 0 => 'MakerNotes', 2 => 'Camera' }, +); + +# lens type +%Image::ExifTool::Pentax::LensRec = ( + %binaryDataAttrs, + GROUPS => { 0 => 'MakerNotes', 2 => 'Camera' }, + NOTES => q{ + This record stores the LensType, plus one or two unknown bytes for some + models. + }, + 0 => { + Name => 'LensType', + Format => 'int8u[2]', + Priority => 0, + ValueConvInv => '$val=~s/\.\d+$//; $val', + PrintConv => \%pentaxLensTypes, + SeparateTable => 1, + }, + 3 => { #PH + Name => 'ExtenderStatus', + Notes => 'not valid if a non-AF lens is used', + PrintConv => { 0 => 'Not attached', 1 => 'Attached' }, + }, + # this is a binaryData table because some cameras add an extra + # byte or two here (typically zeros)... +); + +# lens information (ref PH) +%Image::ExifTool::Pentax::LensInfo = ( + %binaryDataAttrs, + GROUPS => { 0 => 'MakerNotes', 2 => 'Camera' }, + IS_SUBDIR => [ 3 ], + NOTES => 'Pentax lens information structure for models such as the *istD.', + 0 => { + Name => 'LensType', + Format => 'int8u[2]', + Priority => 0, + ValueConvInv => '$val=~s/\.\d+$//; $val', + PrintConv => \%pentaxLensTypes, + SeparateTable => 1, + }, + 3 => { + Name => 'LensData', + Format => 'undef[17]', + SubDirectory => { TagTable => 'Image::ExifTool::Pentax::LensData' }, + }, +); + +# lens information for newer models (ref PH) +%Image::ExifTool::Pentax::LensInfo2 = ( + %binaryDataAttrs, + GROUPS => { 0 => 'MakerNotes', 2 => 'Camera' }, + IS_SUBDIR => [ 4 ], + NOTES => 'Pentax lens information structure for models such as the K10D and K20D.', + 0 => { + Name => 'LensType', + Format => 'int8u[4]', + Priority => 0, + ValueConv => q{ + my @v = split(' ',$val); + $v[0] &= 0x0f; + $v[1] = $v[2] * 256 + $v[3]; # (always high byte first) + return "$v[0] $v[1]"; + }, + # just fill in the missing bits/bytes with zeros... + ValueConvInv => q{ + my @v = split(' ',$val); + return undef unless @v == 2; + $v[2] = ($v[1] >> 8) & 0xff; + $v[3] = $v[1] & 0xff; + $v[1] = 0; + return "@v"; + }, + PrintConv => \%pentaxLensTypes, + SeparateTable => 1, + }, + 4 => { + Name => 'LensData', + Format => 'undef[17]', + SubDirectory => { TagTable => 'Image::ExifTool::Pentax::LensData' }, + }, +); + +# lens information for 645D (ref PH) +%Image::ExifTool::Pentax::LensInfo3 = ( + %binaryDataAttrs, + GROUPS => { 0 => 'MakerNotes', 2 => 'Camera' }, + IS_SUBDIR => [ 13 ], + NOTES => 'Pentax lens information structure for 645D.', + 1 => { + Name => 'LensType', + Format => 'int8u[4]', + Priority => 0, + ValueConv => q{ + my @v = split(' ',$val); + $v[0] &= 0x0f; + $v[1] = $v[2] * 256 + $v[3]; # (always high byte first) + return "$v[0] $v[1]"; + }, + # just fill in the missing bits/bytes with zeros... + ValueConvInv => q{ + my @v = split(' ',$val); + return undef unless @v == 2; + $v[2] = ($v[1] >> 8) & 0xff; + $v[3] = $v[1] & 0xff; + $v[1] = 0; + return "@v"; + }, + PrintConv => \%pentaxLensTypes, + SeparateTable => 1, + }, + 13 => { + Name => 'LensData', + Format => 'undef[17]', + SubDirectory => { TagTable => 'Image::ExifTool::Pentax::LensData' }, + }, +); + +# lens information for K-5, K-r, etc (ref PH) +%Image::ExifTool::Pentax::LensInfo4 = ( + %binaryDataAttrs, + GROUPS => { 0 => 'MakerNotes', 2 => 'Camera' }, + IS_SUBDIR => [ 12 ], + NOTES => 'Pentax lens information structure for models such as the K-5 and K-r.', + 1 => { + Name => 'LensType', + Format => 'int8u[4]', + Priority => 0, + ValueConv => q{ + my @v = split(' ',$val); + $v[0] &= 0x0f; + $v[1] = $v[2] * 256 + $v[3]; # (always high byte first) + return "$v[0] $v[1]"; + }, + # just fill in the missing bits/bytes with zeros... + ValueConvInv => q{ + my @v = split(' ',$val); + return undef unless @v == 2; + $v[2] = ($v[1] >> 8) & 0xff; + $v[3] = $v[1] & 0xff; + $v[1] = 0; + return "@v"; + }, + PrintConv => \%pentaxLensTypes, + SeparateTable => 1, + }, + 12 => { + Name => 'LensData', + Format => 'undef[18]', + Condition => '$$self{NewLensData} = 1', # not really a condition, just used to set flag + SubDirectory => { TagTable => 'Image::ExifTool::Pentax::LensData' }, + }, +); + +# lens information for K-01, K-30, K-50, K-500, K-3, K-3II, K-S1 (ref PH) +%Image::ExifTool::Pentax::LensInfo5 = ( + %binaryDataAttrs, + GROUPS => { 0 => 'MakerNotes', 2 => 'Camera' }, + IS_SUBDIR => [ 15 ], + NOTES => 'Pentax lens information structure for the K-01 and newer models.', + 1 => { + Name => 'LensType', + Format => 'int8u[5]', + Priority => 0, + ValueConv => q{ + my @v = split(' ',$val); + $v[0] &= 0x0f; + $v[1] = $v[3] * 256 + $v[4]; # (always high byte first) + return "$v[0] $v[1]"; + }, + # just fill in the missing bits/bytes with zeros... + ValueConvInv => q{ + my @v = split(' ',$val); + return undef unless @v == 2; + $v[3] = ($v[1] >> 8) & 0xff; + $v[4] = $v[1] & 0xff; + $v[1] = $v[2] = 0; + return "@v"; + }, + PrintConv => \%pentaxLensTypes, + SeparateTable => 1, + }, + 15 => { + Name => 'LensData', + Format => 'undef[17]', + SubDirectory => { TagTable => 'Image::ExifTool::Pentax::LensData' }, + }, +); + +# lens data information, including lens codes (ref PH) +%Image::ExifTool::Pentax::LensData = ( + %binaryDataAttrs, + GROUPS => { 0 => 'MakerNotes', 2 => 'Camera' }, + DATAMEMBER => [ 12.1 ], + NOTES => q{ + Pentax lens data information. Some of these tags require interesting binary + gymnastics to decode them into useful values. + }, + # this byte comes from the lens electrical contacts + # (see http://kmp.bdimitrov.de/technology/K-mount/Ka.html) + 0.1 => { #JD + Name => 'AutoAperture', + Condition => 'not $$self{NewLensData}', + Notes => 'not valid for the K-r, K-5 or K-5II', #29 + Mask => 0x01, + PrintConv => { 0 => 'On', 1 => 'Off' }, + }, + 0.2 => { #JD + Name => 'MinAperture', + Condition => 'not $$self{NewLensData}', + Notes => 'not valid for the K-r, K-5 or K-5II', #29 + Mask => 0x06, + PrintConv => { + 0 => 22, + 1 => 32, + 2 => 45, + 3 => 16, + }, + }, + 0.3 => { #JD + Name => 'LensFStops', + Condition => 'not $$self{NewLensData}', + Notes => 'not valid for the K-r, K-5 or K-5II', #29 + Mask => 0x70, + ValueConv => '5 + ($val ^ 0x07) / 2', + ValueConvInv => '(($val - 5) * 2) ^ 0x07', + }, + # 1-16 look like Lens Codes LC0-LC15, ref patent 5617173 and 5999753 [+notes by PH] + 1 => { # LC0 = lens kind + version data + Name => 'LensKind', + %lensCode, + }, + 2 => { # LC1 = lens data (changes with AF setting) + Name => 'LC1', + %lensCode, + }, + # LC2 = distance data + 3 => { #29 + Name => 'MinFocusDistance', + Notes => 'minimum focus distance for the lens', + Mask => 0xf8, + PrintConv => { + 0 => '0.13-0.19 m', # (plus K or M lenses) + 1 => '0.20-0.24 m', + 2 => '0.25-0.28 m', + 3 => '0.28-0.30 m', + 4 => '0.35-0.38 m', + 5 => '0.40-0.45 m', + 6 => '0.49-0.50 m', # (plus many Sigma lenses) + 7 => '0.6 m', #PH (NC) + 8 => '0.7 m', # (plus Sigma 55-200) + 9 => '0.8-0.9 m', #PH (NC) Tokina 28-70/2.6-2.8 + 10 => '1.0 m', # (plus Sigma 70 macro) + 11 => '1.1-1.2 m', + 12 => '1.4-1.5 m', + 13 => '1.5 m', # Sigma 70-300/4-5.6 macro + 14 => '2.0 m', + 15 => '2.0-2.1 m', #PH (NC) + 16 => '2.1 m', # Sigma 135-400 APO & DG: 2.0-2.2m + 17 => '2.2-2.9 m', #PH (NC) + 18 => '3.0 m', # Sigma 50-500 : 1.0-3.0m depending on the focal length + ## 50mm, 100mm => 1.0m + ## 200mm => 1.1m + ## 300mm => 1.5m + ## 400mm => 2.2m + ## 500mm => 3.0m + 19 => '4-5 m', #PH (NC) + 20 => '5.6 m', # Pentax DA 560 + # To check: Sigma 120-400 OS: MFD 1.5m + # To check: Sigma 150-500 OS: MFD 2.2m + # To check: Sigma 50-500 has MFD 50-180cm + # 0xd0 - seen for the Sigma 4.5mm F2.8 EX DC HSM Circular Fisheye (ref PH) + }, + }, + 3.1 => { #29 + Name => 'FocusRangeIndex', + Mask => 0x07, + PrintConv => { + 7 => '0 (very close)', + 6 => '1 (close)', + 4 => '2', + 5 => '3', + 1 => '4', + 0 => '5', + 2 => '6 (far)', + 3 => '7 (very far)', + }, + }, + 4 => { # LC3 = K-value data (AF pulses to displace image by unit length) + Name => 'LC3', + %lensCode, + }, + 5 => { # LC4 = abberation correction, near distance data + Name => 'LC4', + %lensCode, + }, + 6 => { # LC5 = light color abberation correction data + Name => 'LC5', + %lensCode, + }, + 7 => { # LC6 = open abberation data + Name => 'LC6', + %lensCode, + }, + 8 => { # LC7 = AF minimum actuation condition + Name => 'LC7', + %lensCode, + }, + 9 => [{ # LC8 = focal length data + Name => 'LensFocalLength', + Notes => 'focal length of lens alone, without adapter', #PH + Priority => 0, + Condition => '$$self{Model} !~ /645Z/', #PH (doesn't work for 645Z) + ValueConv => '10*($val>>2) * 4**(($val&0x03)-2)', #JD + ValueConvInv => q{ + my $range = int(log($val/10)/(2*log(2))); + warn("Value out of range") and return undef if $range < 0 or $range > 3; + return $range + (int($val/(10*4**($range-2))+0.5) << 2); + }, + PrintConv => 'sprintf("%.1f mm", $val)', + PrintConvInv => '$val=~s/\s*mm//; $val', + },{ + Name => 'LC8', + %lensCode, + }], + # the following aperture values change with focal length + 10 => { # LC9 = nominal AVmin/AVmax data (open/closed aperture values) + Name => 'NominalMaxAperture', + Mask => 0xf0, + ValueConv => '2**($val/4)', #JD + ValueConvInv => '4*log($val)/log(2)', + PrintConv => 'sprintf("%.1f", $val)', + PrintConvInv => '$val', + }, + 10.1 => { # LC9 = nominal AVmin/AVmax data (open/closed aperture values) + Name => 'NominalMinAperture', + Mask => 0x0f, + ValueConv => '2**(($val+10)/4)', #JD + ValueConvInv => '4*log($val)/log(2) - 10', + PrintConv => 'sprintf("%.0f", $val)', + PrintConvInv => '$val', + }, + 11 => { # LC10 = mv'/nv' data (full-aperture metering error compensation/marginal lumination compensation) + Name => 'LC10', + %lensCode, + }, + 12 => { # LC11 = AVC 1/EXP data + Name => 'LC11', + %lensCode, + }, + 12.1 => { + Name => 'NewLensDataHook', + Hidden => 1, + Hook => '$varSize += 1 if $$self{NewLensData}', + RawConv => 'undef', + }, + 13 => { # LC12 = mv1 AVminsif data + Name => 'LC12', + Notes => "ID's 13-16 are offset by 1 for the K-r, K-5 and K-5II", #29 + %lensCode, + }, + # 14 - related to live view for K-5 (normally 3, but 1 or 5 in LV mode) + 14.1 => { # LC13 = AVmin (open aperture value) [MaxAperture=(2**((AVmin-1)/32))] + Name => 'MaxAperture', + Condition => '$$self{Model} ne "K-5"', + Notes => 'effective wide open aperture for current focal length', + Mask => 0x7f, # (not sure what the high bit indicates) + # (a value of 1 seems to indicate 'n/a') + RawConv => '$val > 1 ? $val : undef', + ValueConv => '2**(($val-1)/32)', + ValueConvInv => '32*log($val)/log(2) + 1', + PrintConv => 'sprintf("%.1f", $val)', + PrintConvInv => '$val', + }, + 15 => { # LC14 = UNT_12 UNT_6 data + Name => 'LC14', + %lensCode, + }, + 16 => { # LC15 = incorporated flash suited END data + Name => 'LC15', + %lensCode, + }, +); + +# flash information (ref PH) +%Image::ExifTool::Pentax::FlashInfo = ( + %binaryDataAttrs, + GROUPS => { 0 => 'MakerNotes', 2 => 'Camera' }, + NOTES => 'Flash information tags for the K10D, K20D and K200D.', + 0 => { + Name => 'FlashStatus', + PrintHex => 1, + PrintConv => { #19 + 0x00 => 'Off', + 0x01 => 'Off (1)', #PH (K-5) + 0x02 => 'External, Did not fire', # 0010 + 0x06 => 'External, Fired', # 0110 + 0x08 => 'Internal, Did not fire (0x08)', + 0x09 => 'Internal, Did not fire', # 1001 + 0x0d => 'Internal, Fired', # 1101 + }, + }, + 1 => { + Name => 'InternalFlashMode', + PrintHex => 1, + PrintConv => { + 0x00 => 'n/a - Off-Auto-Aperture', #19 + 0x86 => 'Fired, Wireless (Control)', #19 + 0x95 => 'Fired, Wireless (Master)', #19 + 0xc0 => 'Fired', # K10D + 0xc1 => 'Fired, Red-eye reduction', # *istDS2, K10D + 0xc2 => 'Fired, Auto', # K100D, K110D + 0xc3 => 'Fired, Auto, Red-eye reduction', #PH + 0xc6 => 'Fired, Wireless (Control), Fired normally not as control', #19 (Remote 3s) + 0xc8 => 'Fired, Slow-sync', # K10D + 0xc9 => 'Fired, Slow-sync, Red-eye reduction', # K10D + 0xca => 'Fired, Trailing-curtain Sync', # K10D + 0xf0 => 'Did not fire, Normal', #19 + 0xf1 => 'Did not fire, Red-eye reduction', #19 + 0xf2 => 'Did not fire, Auto', #19 + 0xf3 => 'Did not fire, Auto, Red-eye reduction', #19 + 0xf4 => 'Did not fire, (Unknown 0xf4)', #19 + 0xf5 => 'Did not fire, Wireless (Master)', #19 + 0xf6 => 'Did not fire, Wireless (Control)', #19 + 0xf8 => 'Did not fire, Slow-sync', #19 + 0xf9 => 'Did not fire, Slow-sync, Red-eye reduction', #19 + 0xfa => 'Did not fire, Trailing-curtain Sync', #19 + }, + }, + 2 => { + Name => 'ExternalFlashMode', + PrintHex => 1, + PrintConv => { #19 + 0x00 => 'n/a - Off-Auto-Aperture', + 0x3f => 'Off', + 0x40 => 'On, Auto', + 0xbf => 'On, Flash Problem', #JD + 0xc0 => 'On, Manual', + 0xc4 => 'On, P-TTL Auto', + 0xc5 => 'On, Contrast-control Sync', #JD + 0xc6 => 'On, High-speed Sync', + 0xcc => 'On, Wireless', + 0xcd => 'On, Wireless, High-speed Sync', + 0xf0 => 'Not Connected', #PH (K-5) + }, + }, + 3 => { + Name => 'InternalFlashStrength', + Notes => 'saved from the most recent flash picture, on a scale of about 0 to 100', + }, + 4 => 'TTL_DA_AUp', + 5 => 'TTL_DA_ADown', + 6 => 'TTL_DA_BUp', + 7 => 'TTL_DA_BDown', + 24.1 => { #19/17 + Name => 'ExternalFlashGuideNumber', + Mask => 0x1f, + Notes => 'val = 2**(raw/16 + 4), with a few exceptions', + ValueConv => q{ + return 0 unless $val; + $val = -3 if $val == 29; # -3 is stored as 0x1d + return 2**($val/16 + 4); + }, + ValueConvInv => q{ + return 0 unless $val; + my $raw = int((log($val)/log(2)-4)*16+0.5); + $raw = 29 if $raw < 0; # guide number of 14 gives -3 which is stored as 0x1d + $raw = 31 if $raw > 31; # maximum value is 0x1f + return $raw; + }, + PrintConv => '$val ? int($val + 0.5) : "n/a"', + PrintConvInv => '$val=~/^n/ ? 0 : $val', + # observed values for various flash focal lengths/guide numbers: + # AF-540FGZ (ref 19) AF-360FGZ (ref 17) + # 6 => 20mm/21 29 => 20mm/14 (wide angle panel used) + # 16 => 24mm/32 6 => 24mm/21 + # 18 => 28mm/35 7 => 28mm/22 + # 21 => 35mm/39 10 => 35mm/25 + # 24 => 50mm/45 14 => 50mm/30 + # 26 => 70mm/50 17 => 70mm/33 + # 28 => 85mm/54 19 => 85mm/36 + # (I have also seen a value of 31 when both flashes are used together + # in a wired configuration, but I don't know exactly what this means - PH) + }, + # 24 - have seen bit 0x80 set when 2 external wired flashes are used - PH + # 24 - have seen bit 0x40 set when wireless high speed sync is used - ref 19 + 25 => { #19 + Name => 'ExternalFlashExposureComp', + PrintConv => { + 0 => 'n/a', # Off or Auto Modes + 144 => 'n/a (Manual Mode)', # Manual Flash Output + 164 => '-3.0', + 167 => '-2.5', + 168 => '-2.0', + 171 => '-1.5', + 172 => '-1.0', + 175 => '-0.5', + 176 => '0.0', + 179 => '0.5', + 180 => '1.0', + }, + }, + 26 => { #17 + Name => 'ExternalFlashBounce', + Notes => 'saved from the most recent external flash picture', #19 + PrintConv => { + 0 => 'n/a', + 16 => 'Direct', + 48 => 'Bounce', + }, + }, + # ? => 'ExternalFlashAOutput', + # ? => 'ExternalFlashBOutput', +); + +%Image::ExifTool::Pentax::FlashInfoUnknown = ( + %binaryDataAttrs, + GROUPS => { 0 => 'MakerNotes', 2 => 'Camera' }, + # 4 - changes with FEC for K-5 - PH +); + +# camera manufacture information (ref PH) +%Image::ExifTool::Pentax::CameraInfo = ( + %binaryDataAttrs, + GROUPS => { 0 => 'MakerNotes', 2 => 'Camera' }, + FORMAT => 'int32u', + 0 => { + Name => 'PentaxModelID', + Priority => 0, # (Optio SVi uses incorrect Optio SV ID here) + SeparateTable => 1, + PrintHex => 1, + PrintConv => \%pentaxModelID, + }, + 1 => { + Name => 'ManufactureDate', + Groups => { 2 => 'Time' }, + Notes => q{ + this value, and the values of the tags below, may change if the camera is + serviced + }, + ValueConv => q{ + $val =~ /^(\d{4})(\d{2})(\d{2})$/ and return "$1:$2:$3"; + # Optio A10 and A20 leave "200" off the year + $val =~ /^(\d)(\d{2})(\d{2})$/ and return "200$1:$2:$3"; + return "Unknown ($val)"; + }, + ValueConvInv => '$val=~tr/0-9//dc; $val', + }, + 2 => { + #(see http://www.pentaxforums.com/forums/pentax-dslr-discussion/25711-k10d-update-model-revision-8-1-yes-no-8.html) + Name => 'ProductionCode', #(previously ModelRevision) + Format => 'int32u[2]', + Note => 'values of 8.x indicate that the camera has been serviced', + ValueConv => '$val=~tr/ /./; $val', + ValueConvInv => '$val=~tr/./ /; $val', + PrintConv => '$val=~/^8\./ ? "$val (camera has been serviced)" : $val', + PrintConvInv => '$val=~s/\s+.*//s; $val', + }, + 4 => 'InternalSerialNumber', +); + +# battery information (ref PH) +%Image::ExifTool::Pentax::BatteryInfo = ( + %binaryDataAttrs, + GROUPS => { 0 => 'MakerNotes', 2 => 'Camera' }, +# size of data: +# 4 (K-m,K2000=4xAA), 6 (*istD,K10D,K100D,K110D=2xCR-V3/4xAA), +# 7 (K20D=D-LI50, K200D=4xAA), 8 (645D=D-LI90), 10 (K-r pre-production?), +# 14 (K-7=D-LI90, K-r=D-LI109/4xAA, K-x=4xAA), 26 (K-5=D-LI90) +# battery grips available for: +# BG1 (*istD), BG2 (K10D/K20D), BG3 (K200D), BG4 (K-7,K-5) +# no grip available: K-x + 0.1 => { #19 + Name => 'PowerSource', + Mask => 0x0f, + # have seen the upper bit set (value of 0x82) for the + # *istDS and K100D, but I'm not sure what this means - PH + # I've also seen: 0x42 (K2000), 0xf2 (K-7,K-r,K-5), 0x12,0x22 (K-x) - PH + PrintConv => { + 1 => 'Camera Battery', #PH (NC, GR III) + 2 => 'Body Battery', + 3 => 'Grip Battery', + 4 => 'External Power Supply', #PH + }, + }, + 1.1 => [ + { + Name => 'BodyBatteryState', + Condition => '$$self{Model} =~ /(\*ist|K100D|K200D|K10D|GX10|K20D|GX20|GX-1[LS]?)\b/', + Notes => '*istD, K100D, K200D, K10D and K20D', + Mask => 0xf0, + PrintConv => { #19 + 1 => 'Empty or Missing', + 2 => 'Almost Empty', + 3 => 'Running Low', + 4 => 'Full', + }, + },{ + Name => 'BodyBatteryState', + Condition => '$$self{Model} !~ /(K110D|K2000|K-m)\b/', + Notes => 'other models except the K110D, K2000 and K-m', + Mask => 0xf0, + PrintConv => { + 1 => 'Empty or Missing', + 2 => 'Almost Empty', + 3 => 'Running Low', + 4 => 'Close to Full', + 5 => 'Full', + }, + },{ + Name => 'BodyBatteryState', + Notes => 'decoding unknown for other models', + Mask => 0xf0, + }, + ], + 1.2 => [ + { + Name => 'GripBatteryState', + Condition => '$$self{Model} =~ /(K10D|GX10|K20D|GX20)\b/', + Notes => 'K10D and K20D', + Mask => 0x0f, + PrintConv => { #19 + 1 => 'Empty or Missing', + 2 => 'Almost Empty', + 3 => 'Running Low', + 4 => 'Full', + }, + },{ + Name => 'GripBatteryState', + Notes => 'decoding unknown for other models', + Unknown => 1, # (doesn't appear to be valid for the K-5) + Mask => 0x0f, + }, + ], + # internal and grip battery voltage Analogue to Digital measurements, + # open circuit and under load + 2 => [ + { + Name => 'BodyBatteryADNoLoad', + Description => 'Body Battery A/D No Load', + Condition => '$$self{Model} =~ /(K10D|GX10|K20D|GX20)\b/', + Notes => 'roughly calibrated for K10D with a new Pentax battery', + # rough linear calibration drops quickly below 30% - PH + # DVM readings: 8.18V=186, 8.42-8.40V=192 (full), 6.86V=155 (empty) + PrintConv => 'sprintf("%d (%.1fV, %d%%)",$val,$val*8.18/186,($val-155)*100/35)', + PrintConvInv => '$val=~s/ .*//; $val', + }, + { + Name => 'BodyBatteryADNoLoad', + Description => 'Body Battery A/D No Load', + Condition => '$$self{Model} =~ /(\*ist|K100D|K200D|GX-1[LS]?)\b/', + }, + { + Name => 'BodyBatteryVoltage1', # (static?) + Condition => '$$self{Model} !~ /(K100D|K110D|K2000|K-m|Q\d*)\b/', + Format => 'int16u', + ValueConv => '$val / 100', + ValueConvInv => '$val * 100', + PrintConv => 'sprintf("%.2f V", $val)', + PrintConvInv => '$val =~ s/\s*V$//', + # For my K-5: Min (0%) Max (100%) At Meas + # BodyBatteryVoltage1 6.24 V 7.75 V 7.66 V + # BodyBatteryVoltage2 5.98 V 7.43 V 7.34 V + # BodyBatteryVoltage3 6.41 V 7.93 V 7.84 V + # BodyBatteryVoltage4 6.10 V 7.55 V 7.45 V + # "Meas" open-circuit voltages with DVM: AB=0V, AC=+8.33V, BC=+8.22V + # (terminal "C" is closest to edge of battery) + }, + ], + 3 => [ + { + Name => 'BodyBatteryADLoad', + Description => 'Body Battery A/D Load', + Condition => '$$self{Model} =~ /(K10D|GX10|K20D|GX20)\b/', + Notes => 'roughly calibrated for K10D with a new Pentax battery', + # [have seen 187] - PH + PrintConv => 'sprintf("%d (%.1fV, %d%%)",$val,$val*8.18/186,($val-152)*100/34)', + PrintConvInv => '$val=~s/ .*//; $val', + }, + { + Name => 'BodyBatteryADLoad', + Description => 'Body Battery A/D Load', + Condition => '$$self{Model} =~ /(\*ist|K100D|K200D)\b/', + }, + ], + 4 => [ + { + Name => 'GripBatteryADNoLoad', + Description => 'Grip Battery A/D No Load', + Condition => '$$self{Model} =~ /(\*ist|K10D|GX10|K20D|GX20|GX-1[LS]?)\b/', + }, + { + Name => 'BodyBatteryVoltage2', # (less than BodyBatteryVoltage1 -- under load?) + Condition => '$$self{Model} !~ /(K100D|K110D|K2000|K-m|Q\d*)\b/', + Format => 'int16u', + ValueConv => '$val / 100', + ValueConvInv => '$val * 100', + PrintConv => 'sprintf("%.2f V", $val)', + PrintConvInv => '$val =~ s/\s*V$//', + }, + ], + 5 => { + Name => 'GripBatteryADLoad', + Condition => '$$self{Model} =~ /(\*ist|K10D|GX10|K20D|GX20)\b/', + Description => 'Grip Battery A/D Load', + }, + 6 => { + Name => 'BodyBatteryVoltage3', # (greater than BodyBatteryVoltage1) + Condition => '$$self{Model} =~ /(K-5|K-r|645D)\b/', + Format => 'int16u', + Notes => 'K-5, K-r and 645D only', + ValueConv => '$val / 100', + ValueConvInv => '$val * 100', + PrintConv => 'sprintf("%.2f V", $val)', + PrintConvInv => '$val =~ s/\s*V$//', + }, + 8 => { + Name => 'BodyBatteryVoltage4', # (between BodyBatteryVoltage1 and BodyBatteryVoltage2) + Condition => '$$self{Model} =~ /(K-5|K-r)\b/', + Format => 'int16u', + Notes => 'K-5 and K-r only', + ValueConv => '$val / 100', + ValueConvInv => '$val * 100', + PrintConv => 'sprintf("%.2f V", $val)', + PrintConvInv => '$val =~ s/\s*V$//', + }, +); + +# auto focus information +%Image::ExifTool::Pentax::AFInfo = ( + %binaryDataAttrs, + GROUPS => { 0 => 'MakerNotes', 2 => 'Camera' }, + # AF Info tag names in K10D debugging output - PH: + # SelectArea, InFocusArea, Predictor, Defocus, IntegTime2msStep, + # CalFlag, ContrastFlag, PrecalFlag, SelectSensor + 0x00 => { #PH + Name => 'AFPointsUnknown1', + Unknown => 1, + Format => 'int16u', + ValueConv => '$self->Options("Unknown") ? $val : $val & 0x7ff', + ValueConvInv => '$val', + PrintConvColumns => 2, + PrintConv => { + 0 => '(none)', + 0x07ff => 'All', + 0x0777 => 'Central 9 points', + BITMASK => { + 0 => 'Upper-left', + 1 => 'Top', + 2 => 'Upper-right', + 3 => 'Left', + 4 => 'Mid-left', + 5 => 'Center', + 6 => 'Mid-right', + 7 => 'Right', + 8 => 'Lower-left', + 9 => 'Bottom', + 10 => 'Lower-right', + # (bits 12-15 are flags of some sort) + }, + }, + }, + 0x02 => { #PH + Name => 'AFPointsUnknown2', + Unknown => 1, + Format => 'int16u', + ValueConv => '$self->Options("Unknown") ? $val : $val & 0x7ff', + ValueConvInv => '$val', + PrintConvColumns => 2, + PrintConv => { + 0 => 'Auto', + BITMASK => { + 0 => 'Upper-left', + 1 => 'Top', + 2 => 'Upper-right', + 3 => 'Left', + 4 => 'Mid-left', + 5 => 'Center', + 6 => 'Mid-right', + 7 => 'Right', + 8 => 'Lower-left', + 9 => 'Bottom', + 10 => 'Lower-right', + # (bits 12-15 are flags of some sort) + # bit 15 is set for center focus point only if it is vertical + }, + }, + }, + 0x04 => { #PH (educated guess - predicted amount to drive lens) + Name => 'AFPredictor', + Format => 'int16s', + }, + 0x06 => 'AFDefocus', #PH (educated guess - calculated distance from focused) + 0x07 => { #PH + # effective exposure time for AF sensors in 2 ms increments + Name => 'AFIntegrationTime', + Notes => 'times less than 2 ms give a value of 0', + ValueConv => '$val * 2', + ValueConvInv => 'int($val / 2)', # (don't round up) + PrintConv => '"$val ms"', + PrintConvInv => '$val=~tr/0-9//dc; $val', + }, + # 0x0a - values: 00,05,0d,15,86,8e,a6,ae + 0x0b => { #JD + Name => 'AFPointsInFocus', + Condition => '$$self{Model} !~ /K-[13]\b/', + Notes => q{ + models other than the K-1 and K-3. May report two points in focus even + though a single AFPoint has been selected, in which case the selected + AFPoint is the first reported + }, + PrintConvColumns => 2, + PrintConv => { + 0 => 'None', + 1 => 'Lower-left, Bottom', + 2 => 'Bottom', + 3 => 'Lower-right, Bottom', + 4 => 'Mid-left, Center', + 5 => 'Center (horizontal)', #PH + 6 => 'Mid-right, Center', + 7 => 'Upper-left, Top', + 8 => 'Top', + 9 => 'Upper-right, Top', + 10 => 'Right', + 11 => 'Lower-left, Mid-left', + 12 => 'Upper-left, Mid-left', + 13 => 'Bottom, Center', + 14 => 'Top, Center', + 15 => 'Lower-right, Mid-right', + 16 => 'Upper-right, Mid-right', + 17 => 'Left', + 18 => 'Mid-left', + 19 => 'Center (vertical)', #PH + 20 => 'Mid-right', + }, + }, + 0x1fd => { + Name => 'AFHold', + Notes => 'decoded only for the K-3 II', + Condition => '$$self{Model} eq "PENTAX K-3 II"', + PrintConv => { 0 => 'Off', 1 => 'Short', 2 => 'Medium', 3 => 'Long' }, + }, +); + +# Kelvin white balance information (ref 28, topic 4834) +%Image::ExifTool::Pentax::KelvinWB = ( + %binaryDataAttrs, + FORMAT => 'int16u', + GROUPS => { 0 => 'MakerNotes', 2 => 'Camera' }, + NOTES => 'White balance Blue/Red gains as a function of color temperature.', + 1 => { Name => 'KelvinWB_Daylight', %kelvinWB }, + 5 => { Name => 'KelvinWB_01', %kelvinWB }, + 9 => { Name => 'KelvinWB_02', %kelvinWB }, + 13 => { Name => 'KelvinWB_03', %kelvinWB }, + 17 => { Name => 'KelvinWB_04', %kelvinWB }, + 21 => { Name => 'KelvinWB_05', %kelvinWB }, + 25 => { Name => 'KelvinWB_06', %kelvinWB }, + 29 => { Name => 'KelvinWB_07', %kelvinWB }, + 33 => { Name => 'KelvinWB_08', %kelvinWB }, + 37 => { Name => 'KelvinWB_09', %kelvinWB }, + 41 => { Name => 'KelvinWB_10', %kelvinWB }, + 45 => { Name => 'KelvinWB_11', %kelvinWB }, + 49 => { Name => 'KelvinWB_12', %kelvinWB }, + 53 => { Name => 'KelvinWB_13', %kelvinWB }, + 57 => { Name => 'KelvinWB_14', %kelvinWB }, + 61 => { Name => 'KelvinWB_15', %kelvinWB }, + 65 => { Name => 'KelvinWB_16', %kelvinWB }, +); + +# color information - PH +%Image::ExifTool::Pentax::ColorInfo = ( + %binaryDataAttrs, + GROUPS => { 0 => 'MakerNotes', 2 => 'Image' }, + FORMAT => 'int8s', + 16 => { + Name => 'WBShiftAB', + Notes => 'positive is a shift toward blue', + }, + 17 => { + Name => 'WBShiftGM', + Notes => 'positive is a shift toward green', + }, +); + +# EV step size information - ref 19 +%Image::ExifTool::Pentax::EVStepInfo = ( + %binaryDataAttrs, + GROUPS => { 0 => 'MakerNotes', 2 => 'Camera' }, + 0 => { + Name => 'EVSteps', + PrintConv => { + 0 => '1/2 EV Steps', + 1 => '1/3 EV Steps', + }, + }, + 1 => { + Name => 'SensitivitySteps', + PrintConv => { + 0 => '1 EV Steps', + 1 => 'As EV Steps', + }, + }, +); + +# shot information? - ref PH (K-5) +%Image::ExifTool::Pentax::ShotInfo = ( + %binaryDataAttrs, + GROUPS => { 0 => 'MakerNotes', 2 => 'Camera' }, + # 0: 0xf2/0xf3 (HDR), 0xf0 (otherwise) + 1 => { # (presumably this is from an orientation sensor) + Name => 'CameraOrientation', + Condition => '$$self{Model} =~ /K-(5|7|r|x)\b/', + Notes => 'K-5, K-7, K-r and K-x', + PrintHex => 1, + PrintConv => { + 0x10 => 'Horizontal (normal)', + 0x20 => 'Rotate 180', + 0x30 => 'Rotate 90 CW', + 0x40 => 'Rotate 270 CW', + 0x50 => 'Upwards', # (to the sky) + 0x60 => 'Downwards', # (to the ground) + }, + }, + # 2: 0xd3 (live view), 0xdb (HDR), 0x7b (otherwise) + # 3: 0xff + # 4: 0x64, 0x6a, 0x6f, 0xa4, 0xaa, 0xab, 0xbf + # 5: 0xfe + # 6: 0x0e + # 7: 0x02 (live view), 0x06 (otherwise) + # 8-10: 0x00 +); + +# face detect positions - ref PH (Optio RZ10) +%Image::ExifTool::Pentax::FacePos = ( + %binaryDataAttrs, + GROUPS => { 0 => 'MakerNotes', 2 => 'Image' }, + FORMAT => 'int16u', + 0 => { + Name => 'Face1Position', + Format => 'int16u[2]', + RawConv => '$$self{FacesDetected} < 1 ? undef : $val', + Notes => 'X/Y coordinates of face center in full-sized image', + }, + 2 => { + Name => 'Face2Position', + Format => 'int16u[2]', + RawConv => '$$self{FacesDetected} < 2 ? undef : $val', + }, + 4 => { + Name => 'Face3Position', + Format => 'int16u[2]', + RawConv => '$$self{FacesDetected} < 3 ? undef : $val', + }, + 6 => { + Name => 'Face4Position', + Format => 'int16u[2]', + RawConv => '$$self{FacesDetected} < 4 ? undef : $val', + }, + 8 => { + Name => 'Face5Position', + Format => 'int16u[2]', + RawConv => '$$self{FacesDetected} < 5 ? undef : $val', + }, + 10 => { + Name => 'Face6Position', + Format => 'int16u[2]', + RawConv => '$$self{FacesDetected} < 6 ? undef : $val', + }, + 12 => { + Name => 'Face7Position', + Format => 'int16u[2]', + RawConv => '$$self{FacesDetected} < 7 ? undef : $val', + }, + 14 => { + Name => 'Face8Position', + Format => 'int16u[2]', + RawConv => '$$self{FacesDetected} < 8 ? undef : $val', + }, + 16 => { + Name => 'Face9Position', + Format => 'int16u[2]', + RawConv => '$$self{FacesDetected} < 9 ? undef : $val', + }, + 18 => { + Name => 'Face10Position', + Format => 'int16u[2]', + RawConv => '$$self{FacesDetected} < 10 ? undef : $val', + }, + 20 => { + Name => 'Face11Position', + Format => 'int16u[2]', + RawConv => '$$self{FacesDetected} < 11 ? undef : $val', + }, + 22 => { + Name => 'Face12Position', + Format => 'int16u[2]', + RawConv => '$$self{FacesDetected} < 12 ? undef : $val', + }, + 24 => { + Name => 'Face13Position', + Format => 'int16u[2]', + RawConv => '$$self{FacesDetected} < 13 ? undef : $val', + }, + 26 => { + Name => 'Face14Position', + Format => 'int16u[2]', + RawConv => '$$self{FacesDetected} < 14 ? undef : $val', + }, + 28 => { + Name => 'Face15Position', + Format => 'int16u[2]', + RawConv => '$$self{FacesDetected} < 15 ? undef : $val', + }, + 30 => { + Name => 'Face16Position', + Format => 'int16u[2]', + RawConv => '$$self{FacesDetected} < 16 ? undef : $val', + }, + 32 => { + Name => 'Face17Position', + Format => 'int16u[2]', + RawConv => '$$self{FacesDetected} < 17 ? undef : $val', + }, + 34 => { + Name => 'Face18Position', + Format => 'int16u[2]', + RawConv => '$$self{FacesDetected} < 18 ? undef : $val', + }, + 36 => { + Name => 'Face19Position', + Format => 'int16u[2]', + RawConv => '$$self{FacesDetected} < 19 ? undef : $val', + }, + 38 => { + Name => 'Face20Position', + Format => 'int16u[2]', + RawConv => '$$self{FacesDetected} < 20 ? undef : $val', + }, + 40 => { + Name => 'Face21Position', + Format => 'int16u[2]', + RawConv => '$$self{FacesDetected} < 21 ? undef : $val', + }, + 42 => { + Name => 'Face22Position', + Format => 'int16u[2]', + RawConv => '$$self{FacesDetected} < 22 ? undef : $val', + }, + 44 => { + Name => 'Face23Position', + Format => 'int16u[2]', + RawConv => '$$self{FacesDetected} < 23 ? undef : $val', + }, + 46 => { + Name => 'Face24Position', + Format => 'int16u[2]', + RawConv => '$$self{FacesDetected} < 24 ? undef : $val', + }, + 48 => { + Name => 'Face25Position', + Format => 'int16u[2]', + RawConv => '$$self{FacesDetected} < 25 ? undef : $val', + }, + 50 => { + Name => 'Face26Position', + Format => 'int16u[2]', + RawConv => '$$self{FacesDetected} < 26 ? undef : $val', + }, + 52 => { + Name => 'Face27Position', + Format => 'int16u[2]', + RawConv => '$$self{FacesDetected} < 27 ? undef : $val', + }, + 54 => { + Name => 'Face28Position', + Format => 'int16u[2]', + RawConv => '$$self{FacesDetected} < 28 ? undef : $val', + }, + 56 => { + Name => 'Face29Position', + Format => 'int16u[2]', + RawConv => '$$self{FacesDetected} < 29 ? undef : $val', + }, + 58 => { + Name => 'Face30Position', + Format => 'int16u[2]', + RawConv => '$$self{FacesDetected} < 30 ? undef : $val', + }, + 60 => { + Name => 'Face31Position', + Format => 'int16u[2]', + RawConv => '$$self{FacesDetected} < 31 ? undef : $val', + }, + 62 => { + Name => 'Face32Position', + Format => 'int16u[2]', + RawConv => '$$self{FacesDetected} < 32 ? undef : $val', + }, +); + +# face detect sizes - ref PH (Optio RZ10) +%Image::ExifTool::Pentax::FaceSize = ( + %binaryDataAttrs, + GROUPS => { 0 => 'MakerNotes', 2 => 'Image' }, + FORMAT => 'int16u', + 0 => { + Name => 'Face1Size', + Format => 'int16u[2]', + RawConv => '$$self{FacesDetected} < 1 ? undef : $val', + }, + 2 => { + Name => 'Face2Size', + Format => 'int16u[2]', + RawConv => '$$self{FacesDetected} < 2 ? undef : $val', + }, + 4 => { + Name => 'Face3Size', + Format => 'int16u[2]', + RawConv => '$$self{FacesDetected} < 3 ? undef : $val', + }, + 6 => { + Name => 'Face4Size', + Format => 'int16u[2]', + RawConv => '$$self{FacesDetected} < 4 ? undef : $val', + }, + 8 => { + Name => 'Face5Size', + Format => 'int16u[2]', + RawConv => '$$self{FacesDetected} < 5 ? undef : $val', + }, + 10 => { + Name => 'Face6Size', + Format => 'int16u[2]', + RawConv => '$$self{FacesDetected} < 6 ? undef : $val', + }, + 12 => { + Name => 'Face7Size', + Format => 'int16u[2]', + RawConv => '$$self{FacesDetected} < 7 ? undef : $val', + }, + 14 => { + Name => 'Face8Size', + Format => 'int16u[2]', + RawConv => '$$self{FacesDetected} < 8 ? undef : $val', + }, + 16 => { + Name => 'Face9Size', + Format => 'int16u[2]', + RawConv => '$$self{FacesDetected} < 9 ? undef : $val', + }, + 18 => { + Name => 'Face10Size', + Format => 'int16u[2]', + RawConv => '$$self{FacesDetected} < 10 ? undef : $val', + }, + 20 => { + Name => 'Face11Size', + Format => 'int16u[2]', + RawConv => '$$self{FacesDetected} < 11 ? undef : $val', + }, + 22 => { + Name => 'Face12Size', + Format => 'int16u[2]', + RawConv => '$$self{FacesDetected} < 12 ? undef : $val', + }, + 24 => { + Name => 'Face13Size', + Format => 'int16u[2]', + RawConv => '$$self{FacesDetected} < 13 ? undef : $val', + }, + 26 => { + Name => 'Face14Size', + Format => 'int16u[2]', + RawConv => '$$self{FacesDetected} < 14 ? undef : $val', + }, + 28 => { + Name => 'Face15Size', + Format => 'int16u[2]', + RawConv => '$$self{FacesDetected} < 15 ? undef : $val', + }, + 30 => { + Name => 'Face16Size', + Format => 'int16u[2]', + RawConv => '$$self{FacesDetected} < 16 ? undef : $val', + }, + 32 => { + Name => 'Face17Size', + Format => 'int16u[2]', + RawConv => '$$self{FacesDetected} < 17 ? undef : $val', + }, + 34 => { + Name => 'Face18Size', + Format => 'int16u[2]', + RawConv => '$$self{FacesDetected} < 18 ? undef : $val', + }, + 36 => { + Name => 'Face19Size', + Format => 'int16u[2]', + RawConv => '$$self{FacesDetected} < 19 ? undef : $val', + }, + 38 => { + Name => 'Face20Size', + Format => 'int16u[2]', + RawConv => '$$self{FacesDetected} < 20 ? undef : $val', + }, + 40 => { + Name => 'Face21Size', + Format => 'int16u[2]', + RawConv => '$$self{FacesDetected} < 21 ? undef : $val', + }, + 42 => { + Name => 'Face22Size', + Format => 'int16u[2]', + RawConv => '$$self{FacesDetected} < 22 ? undef : $val', + }, + 44 => { + Name => 'Face23Size', + Format => 'int16u[2]', + RawConv => '$$self{FacesDetected} < 23 ? undef : $val', + }, + 46 => { + Name => 'Face24Size', + Format => 'int16u[2]', + RawConv => '$$self{FacesDetected} < 24 ? undef : $val', + }, + 48 => { + Name => 'Face25Size', + Format => 'int16u[2]', + RawConv => '$$self{FacesDetected} < 25 ? undef : $val', + }, + 50 => { + Name => 'Face26Size', + Format => 'int16u[2]', + RawConv => '$$self{FacesDetected} < 26 ? undef : $val', + }, + 52 => { + Name => 'Face27Size', + Format => 'int16u[2]', + RawConv => '$$self{FacesDetected} < 27 ? undef : $val', + }, + 54 => { + Name => 'Face28Size', + Format => 'int16u[2]', + RawConv => '$$self{FacesDetected} < 28 ? undef : $val', + }, + 56 => { + Name => 'Face29Size', + Format => 'int16u[2]', + RawConv => '$$self{FacesDetected} < 29 ? undef : $val', + }, + 58 => { + Name => 'Face30Size', + Format => 'int16u[2]', + RawConv => '$$self{FacesDetected} < 30 ? undef : $val', + }, + 60 => { + Name => 'Face31Size', + Format => 'int16u[2]', + RawConv => '$$self{FacesDetected} < 31 ? undef : $val', + }, + 62 => { + Name => 'Face32Size', + Format => 'int16u[2]', + RawConv => '$$self{FacesDetected} < 32 ? undef : $val', + }, +); + +# digital filter information - ref PH (K-5) +%Image::ExifTool::Pentax::FilterInfo = ( + %binaryDataAttrs, + GROUPS => { 0 => 'MakerNotes', 2 => 'Image' }, + FORMAT => 'int8u', + NOTES => q{ + The parameters associated with each type of digital filter are unique, and + these settings are also extracted with the DigitalFilter tag. Information + is not extracted for filters that are "Off" unless the Unknown option is + used. + }, + 0 => { + Name => 'SourceDirectoryIndex', + Format => 'int16u', + }, + 2 => { + Name => 'SourceFileIndex', + Format => 'int16u', + }, + 0x005 => { Name => 'DigitalFilter01', %digitalFilter }, + 0x016 => { Name => 'DigitalFilter02', %digitalFilter }, + 0x027 => { Name => 'DigitalFilter03', %digitalFilter }, + 0x038 => { Name => 'DigitalFilter04', %digitalFilter }, + 0x049 => { Name => 'DigitalFilter05', %digitalFilter }, + 0x05a => { Name => 'DigitalFilter06', %digitalFilter }, + 0x06b => { Name => 'DigitalFilter07', %digitalFilter }, + 0x07c => { Name => 'DigitalFilter08', %digitalFilter }, + 0x08d => { Name => 'DigitalFilter09', %digitalFilter }, + 0x09e => { Name => 'DigitalFilter10', %digitalFilter }, + 0x0af => { Name => 'DigitalFilter11', %digitalFilter }, + 0x0c0 => { Name => 'DigitalFilter12', %digitalFilter }, + 0x0d1 => { Name => 'DigitalFilter13', %digitalFilter }, + 0x0e2 => { Name => 'DigitalFilter14', %digitalFilter }, + 0x0f3 => { Name => 'DigitalFilter15', %digitalFilter }, + 0x104 => { Name => 'DigitalFilter16', %digitalFilter }, + 0x115 => { Name => 'DigitalFilter17', %digitalFilter }, + 0x126 => { Name => 'DigitalFilter18', %digitalFilter }, + 0x137 => { Name => 'DigitalFilter19', %digitalFilter }, + 0x148 => { Name => 'DigitalFilter20', %digitalFilter }, +); + +# electronic level information - ref PH (K-5) +%Image::ExifTool::Pentax::LevelInfo = ( + %binaryDataAttrs, + GROUPS => { 0 => 'MakerNotes', 2 => 'Camera' }, + FORMAT => 'int8s', + NOTES => q{ + Tags decoded from the electronic level information for the K-5. May not be + valid for other models. + }, + 0 => { + Name => 'LevelOrientation', + Mask => 0x0f, + PrintHex => 0, + PrintConv => { + 0 => 'n/a', #PH (NC, GR III) + 1 => 'Horizontal (normal)', + 2 => 'Rotate 180', + 3 => 'Rotate 90 CW', + 4 => 'Rotate 270 CW', + 9 => 'Horizontal; Off Level', + 10 => 'Rotate 180; Off Level', + 11 => 'Rotate 90 CW; Off Level', + 12 => 'Rotate 270 CW; Off Level', + 13 => 'Upwards', + 14 => 'Downwards', + }, + }, + 0.1 => { + Name => 'CompositionAdjust', + Mask => 0xf0, + PrintConv => { + 0 => 'Off', + 2 => 'Composition Adjust', + 10 => 'Composition Adjust + Horizon Correction', + 12 => 'Horizon Correction', + }, + }, + 1 => { + Name => 'RollAngle', + Notes => 'converted to degrees of clockwise camera rotation', + ValueConv => '-$val / 2', + ValueConvInv => '-$val * 2', + }, + 2 => { + Name => 'PitchAngle', + Notes => 'converted to degrees of upward camera tilt', + ValueConv => '-$val / 2', + ValueConvInv => '-$val * 2', + }, + # 3,4 - related somehow to horizon correction and composition adjust + # 5,6,7 - (the notes below refer to how the image moves in the LCD monitor) + 5 => { + Name => 'CompositionAdjustX', + Notes => 'steps to the right, 1/16 mm per step', + ValueConv => '-$val', + ValueConvInv => '-$val', + }, + 6 => { + Name => 'CompositionAdjustY', + Notes => 'steps up, 1/16 mm per step', + ValueConv => '-$val', + ValueConvInv => '-$val', + }, + 7 => { + Name => 'CompositionAdjustRotation', + Notes => 'steps clockwise, 1/8 degree per step', + ValueConv => '-$val / 2', + ValueConvInv => '-$val * 2', + }, +); + +# white balance RGGB levels (ref 28) +%Image::ExifTool::Pentax::WBLevels = ( + %binaryDataAttrs, + GROUPS => { 0 => 'MakerNotes', 2 => 'Camera' }, + # 0 - 11 (number of entries in this table) + # 1 - 0 + 2 => { + Name => 'WB_RGGBLevelsDaylight', + Format => 'int16u[4]', + }, + # 10 - 1 + 11 => { + Name => 'WB_RGGBLevelsShade', + Format => 'int16u[4]', + }, + # 19 - 2 + 20 => { + Name => 'WB_RGGBLevelsCloudy', + Format => 'int16u[4]', + }, + # 28 - 3 + 29 => { + Name => 'WB_RGGBLevelsTungsten', + Format => 'int16u[4]', + }, + # 37 - 4 + 38 => { + Name => 'WB_RGGBLevelsFluorescentD', + Format => 'int16u[4]', + }, + # 46 - 5 + 47 => { + Name => 'WB_RGGBLevelsFluorescentN', + Format => 'int16u[4]', + }, + # 55 - 6 + 56 => { + Name => 'WB_RGGBLevelsFluorescentW', + Format => 'int16u[4]', + }, + # 64 - 7 + 65 => { + Name => 'WB_RGGBLevelsFlash', + Format => 'int16u[4]', + }, + # 73 - 8 + 74 => { + Name => 'WB_RGGBLevelsFluorescentL', + Format => 'int16u[4]', + }, + # 82 - 0xfe + 83 => { + Name => 'WB_RGGBLevelsUnknown', + Format => 'int16u[4]', + Unknown => 1, + }, + # 91 - 0xff + 92 => { + Name => 'WB_RGGBLevelsUserSelected', + Format => 'int16u[4]', + }, +); + +# lens information for Penax Q (ref PH) +# (306 bytes long, I wonder if this contains vignetting information too?) +%Image::ExifTool::Pentax::LensInfoQ = ( + %binaryDataAttrs, + GROUPS => { 0 => 'MakerNotes', 2 => 'Camera' }, + NOTES => 'More lens information stored by the Pentax Q.', + 0x0c => { + Name => 'LensModel', + Format => 'string[30]', + }, + 0x2a => { + Name => 'LensInfo', + Format => 'string[20]', + ValueConv => '$val=~s/mm/mm /; $val', + ValueConvInv => '$val=~tr/ //d; $val', + } +); + +# Pixel shift information for the K-3II (ref PH) +%Image::ExifTool::Pentax::PixelShiftInfo = ( + %binaryDataAttrs, + GROUPS => { 0 => 'MakerNotes', 2 => 'Camera' }, + NOTES => 'Pixel shift information stored by the K-3 II.', + 0x00 => { + Name => 'PixelShiftResolution', + PrintConv => { 0 => 'Off', 1 => 'On' }, + }, +); + +# AF point information for the K-1 (ref 29) +%Image::ExifTool::Pentax::AFPointInfo = ( + %binaryDataAttrs, + GROUPS => { 0 => 'MakerNotes', 2 => 'Camera' }, + NOTES => 'AF point information written by the K-1.', + # 0 - int16u: 1 (version?) + 2 => { + Name => 'NumAFPoints', + Format => 'int16u', + }, + 4 => { + Name => 'AFPointsInFocus', + Condition => '$$self{Model} =~ /K-1\b/', + Format => 'int8u[9]', + PrintConv => 'Image::ExifTool::Pentax::DecodeAFPoints($val,33,2,0x02)', + }, + 4.1 => { + Name => 'AFPointsSelected', + Condition => '$$self{Model} =~ /K-1\b/', + Format => 'int8u[9]', + PrintConv => 'Image::ExifTool::Pentax::DecodeAFPoints($val,33,2,0x03)', + }, + 4.2 => { + Name => 'AFPointsSpecial', + Condition => '$$self{Model} =~ /K-1\b/', + Format => 'int8u[9]', + PrintConv => 'Image::ExifTool::Pentax::DecodeAFPoints($val,33,2,0x03,0x03)', + }, +); + +# temperature information for some models - PH +%Image::ExifTool::Pentax::TempInfo = ( + %binaryDataAttrs, + GROUPS => { 0 => 'MakerNotes', 2 => 'Camera' }, + NOTES => q{ + A number of additional temperature readings are extracted from this 256-byte + binary-data block in images from models such as the K-01, K-3, K-5, K-50 and + K-500. It is currently not known where the corresponding temperature + sensors are located in the camera. + }, + # (it would be nice to know where these temperature sensors are located, + # but since according to the manual the Slow Shutter Speed NR Auto mode + # is based on "internal temperature", my guess is that there must be + # at least one on the sensor itself. These temperatures seem to rise + # more quickly than CameraTemperature when shooting video.) + 0x0c => { + Name => 'SensorTemperature', #forum6677 (was CameraTemperature2) + Format => 'int16s', + ValueConv => '$val / 10', + ValueConvInv => '$val * 10', + PrintConv => 'sprintf("%.1f C", $val)', + PrintConvInv => '$val=~s/ ?c$//i; $val', + }, + 0x0e => { + Name => 'SensorTemperature2', #forum6677 (was CameraTemperature3) + Format => 'int16s', + ValueConv => '$val / 10', + ValueConvInv => '$val * 10', + PrintConv => 'sprintf("%.1f C", $val)', + PrintConvInv => '$val=~s/ ?c$//i; $val', + }, + 0x14 => { + Name => 'CameraTemperature4', + Condition => '$$self{Model} =~ /K-5\b/', + Format => 'int16s', + PrintConv => '"$val C"', + PrintConvInv => '$val=~s/ ?c$//i; $val', + }, + 0x16 => { # usually the same as CameraTemperature4, but not always + Name => 'CameraTemperature5', + Condition => '$$self{Model} =~ /K-5\b/', + Format => 'int16s', + PrintConv => '"$val C"', + PrintConvInv => '$val=~s/ ?c$//i; $val', + }, + # 0x18,0x1a,0x1c,0x1e = int16u[4] BlackPoint - PH +); + +# currently unknown info +%Image::ExifTool::Pentax::UnknownInfo = ( + %binaryDataAttrs, + GROUPS => { 0 => 'MakerNotes', 2 => 'Camera' }, + # K10D: first 8 bytes seem to be short integers which change with ISO (value + # is usually close to ISO/100) possibly smoothing or gain parameters? - PH + # byte 0-1 - Higher for high color temperatures (red boost or red noise suppression?) + # byte 6-7 - Higher for low color temperatures (blue boost or blue noise suppression?) + # also changing are bytes 10,11,14,15 +); + +# Pentax type 2 (Casio-like) maker notes (ref 1) +%Image::ExifTool::Pentax::Type2 = ( + WRITE_PROC => \&Image::ExifTool::Exif::WriteExif, + CHECK_PROC => \&Image::ExifTool::Exif::CheckExif, + GROUPS => { 0 => 'MakerNotes', 2 => 'Camera' }, + WRITABLE => 'int16u', + NOTES => q{ + These tags are used by the Pentax Optio 330 and 430, and are similar to the + tags used by Casio. + }, + 0x0001 => { + Name => 'RecordingMode', + PrintConv => { + 0 => 'Auto', + 1 => 'Night Scene', + 2 => 'Manual', + }, + }, + 0x0002 => { + Name => 'Quality', + PrintConv => { + 0 => 'Good', + 1 => 'Better', + 2 => 'Best', + }, + }, + 0x0003 => { + Name => 'FocusMode', + PrintConv => { + 2 => 'Custom', + 3 => 'Auto', + }, + }, + 0x0004 => { + Name => 'FlashMode', + PrintConv => { + 1 => 'Auto', + 2 => 'On', + 4 => 'Off', + 6 => 'Red-eye reduction', + }, + }, + # Casio 0x0005 is FlashIntensity + # Casio 0x0006 is ObjectDistance + 0x0007 => { + Name => 'WhiteBalance', + PrintConv => { + 0 => 'Auto', + 1 => 'Daylight', + 2 => 'Shade', + 3 => 'Tungsten', + 4 => 'Fluorescent', + 5 => 'Manual', + }, + }, + 0x000a => { + Name => 'DigitalZoom', + Writable => 'int32u', + }, + 0x000b => { + Name => 'Sharpness', + PrintConv => { + 0 => 'Normal', + 1 => 'Soft', + 2 => 'Hard', + }, + }, + 0x000c => { + Name => 'Contrast', + PrintConv => { + 0 => 'Normal', + 1 => 'Low', + 2 => 'High', + }, + }, + 0x000d => { + Name => 'Saturation', + PrintConv => { + 0 => 'Normal', + 1 => 'Low', + 2 => 'High', + }, + }, + 0x0014 => { + Name => 'ISO', + Priority => 0, + PrintConv => { + 10 => 100, + 16 => 200, + 50 => 50, #PH + 100 => 100, #PH + 200 => 200, #PH + 400 => 400, #PH + 800 => 800, #PH + 1600 => 1600, #PH + 3200 => 3200, #PH + 65534 => 'Auto 2', #PH (Q-S1 MOV) [how is this different from 65535?] + 65535 => 'Auto', #PH (K-S1 MOV) + }, + }, + 0x0017 => { + Name => 'ColorFilter', + PrintConv => { + 1 => 'Full', + 2 => 'Black & White', + 3 => 'Sepia', + }, + }, + # Casio 0x0018 is AFPoint + # Casio 0x0019 is FlashIntensity + 0x0e00 => { + Name => 'PrintIM', + Description => 'Print Image Matching', + Writable => 0, + SubDirectory => { + TagTable => 'Image::ExifTool::PrintIM::Main', + }, + }, + 0x1000 => { + Name => 'HometownCityCode', + Writable => 'undef', + Count => 4, + }, + 0x1001 => { #PH + Name => 'DestinationCityCode', + Writable => 'undef', + Count => 4, + }, +); + +# ASCII-based maker notes of Optio E20 and E25 - PH +%Image::ExifTool::Pentax::Type4 = ( + PROCESS_PROC => \&Image::ExifTool::HP::ProcessHP, + GROUPS => { 0 => 'MakerNotes', 2 => 'Camera' }, + NOTES => q{ + The following few tags are extracted from the wealth of information + available in maker notes of the Optio E20 and E25. These maker notes are + stored as ASCII text in a format very similar to some HP models. + }, + 'F/W Version' => 'FirmwareVersion', +); + +# tags in Pentax QuickTime videos (PH - tests with Optio WP) +# (similar information in Kodak,Minolta,Nikon,Olympus,Pentax and Sanyo videos) +%Image::ExifTool::Pentax::MOV = ( + PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData, + GROUPS => { 0 => 'MakerNotes', 2 => 'Camera' }, + FIRST_ENTRY => 0, + NOTES => 'This information is found in MOV videos from cameras such as the Optio WP.', + 0x00 => { + Name => 'Make', + Format => 'string[24]', + }, + # (01 00 at offset 0x20) + 0x26 => { + Name => 'ExposureTime', + Format => 'int32u', + ValueConv => '$val ? 10 / $val : 0', + PrintConv => 'Image::ExifTool::Exif::PrintExposureTime($val)', + }, + 0x2a => { + Name => 'FNumber', + Format => 'rational64u', + PrintConv => 'sprintf("%.1f",$val)', + }, + 0x32 => { + Name => 'ExposureCompensation', + Format => 'rational64s', + PrintConv => '$val ? sprintf("%+.1f", $val) : 0', + }, + 0x44 => { + Name => 'WhiteBalance', + Format => 'int16u', + PrintConv => { + 0 => 'Auto', + 1 => 'Daylight', + 2 => 'Shade', + 3 => 'Fluorescent', #2 + 4 => 'Tungsten', + 5 => 'Manual', + }, + }, + 0x48 => { + Name => 'FocalLength', + Format => 'rational64u', + PrintConv => 'sprintf("%.1f mm",$val)', + }, + 0xaf => { + Name => 'ISO', + Format => 'int16u', + }, +); + +# Pentax metadata in AVI videos (PH) +%Image::ExifTool::Pentax::AVI = ( + NOTES => 'Pentax-specific RIFF tags found in AVI videos.', + GROUPS => { 0 => 'MakerNotes', 2 => 'Video' }, + hymn => { + Name => 'MakerNotes', + SubDirectory => { + TagTable => 'Image::ExifTool::Pentax::Main', + Start => 10, + Base => '$start', + ByteOrder => 'Unknown', # K-70 is little-endian, K-x is big-endian + }, + }, + mknt => { # (Q-S1) + Name => 'MakerNotes', + SubDirectory => { + TagTable => 'Image::ExifTool::Pentax::Main', + Start => 10, + Base => '$start', + ByteOrder => 'Unknown', + }, + }, +); + +# Pentax metadata in S1 AVI maker notes (PH) +%Image::ExifTool::Pentax::S1 = ( + NOTES => 'Tags extracted from the maker notes of AVI videos from the Optio S1.', + GROUPS => { 0 => 'MakerNotes', 2 => 'Camera' }, + 0x0000 => { #5 + Name => 'MakerNoteVersion', + Writable => 'undef', + Count => 4, + }, +); + +# Pentax metadata in AVI videos from the RS1000 (PH) +%Image::ExifTool::Pentax::Junk = ( + NOTES => 'Tags found in the JUNK chunk of AVI videos from the RS1000.', + PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData, + GROUPS => { 0 => 'MakerNotes', 2 => 'Camera' }, + 0x0c => { + Name => 'Model', + Description => 'Camera Model Name', + Format => 'string[32]', + }, +); + +# PreviewImage information found in PXTH atom of K-01 MOV videos +%Image::ExifTool::Pentax::PXTH = ( + NOTES => 'Tags found in the PXTH atom of MOV videos from the K-01.', + PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData, + GROUPS => { 0 => 'MakerNotes', 2 => 'Camera' }, + 0x00 => { + Name => 'PreviewImageLength', + Format => 'int32u', + }, + 0x04 => { + Name => 'PreviewImage', + Groups => { 2 => 'Preview' }, + Format => 'undef[$val{0}]', + Notes => '640-pixel-wide JPEG preview', # (360 pixels high, may depend on aspect ratio) + RawConv => '$self->ValidateImage(\$val,$tag)', + }, +); + +# information in PENT atom of MOV videos from the Optio WG-2 GPS +%Image::ExifTool::Pentax::PENT = ( + NOTES => 'Tags found in the PENT atom of MOV videos from the Optio WG-2 GPS.', + PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData, + GROUPS => { 0 => 'MakerNotes', 2 => 'Camera' }, + 0 => { + Name => 'Make', + Format => 'string[24]', + }, + 0x1a => { + Name => 'Model', + Description => 'Camera Model Name', + Format => 'string[24]', + }, + 0x38 => { #(NC) + Name => 'ExposureTime', + Format => 'int32u', + ValueConv => '$val ? 10 / $val : 0', + PrintConv => 'Image::ExifTool::Exif::PrintExposureTime($val)', + }, + 0x3c => { + Name => 'FNumber', + Format => 'rational64u', + PrintConv => 'sprintf("%.1f",$val)', + }, + 0x44 => { #(NC) + Name => 'ExposureCompensation', + Format => 'rational64s', + PrintConv => '$val ? sprintf("%+.1f", $val) : 0', + }, + 0x54 => { #(NC) + Name => 'FocalLength', + Format => 'int32u', + PrintConv => '"$val mm"', + }, + 0x71 => { + Name => 'DateTime1', + Format => 'string[24]', + Groups => { 2 => 'Time' }, + }, + 0x8b => { + Name => 'DateTime2', + Format => 'string[24]', + Groups => { 2 => 'Time' }, + }, + 0xa7 => { #(NC) + Name => 'ISO', + Format => 'int32u', + }, + 0xc7 => { + Name => 'GPSVersionID', + Format => 'undef[8]', + Groups => { 1 => 'GPS', 2 => 'Location' }, + DataMember => 'GPSVersionID', + RawConv => '$$self{GPSVersionID} = ($val=~s/GPS_// ? join(" ",unpack("C*",$val)) : undef)', + PrintConv => '$val =~ tr/ /./; $val', + }, + 0xcf => { + Name => 'GPSLatitudeRef', + Condition => '$$self{GPSVersionID}', + Format => 'string[2]', + Groups => { 1 => 'GPS', 2 => 'Location' }, + PrintConv => { + N => 'North', + S => 'South', + }, + }, + 0xd1 => { + Name => 'GPSLatitude', + Condition => '$$self{GPSVersionID}', + Format => 'rational64u[3]', + Groups => { 1 => 'GPS', 2 => 'Location' }, + ValueConv => 'Image::ExifTool::GPS::ToDegrees($val)', + PrintConv => 'Image::ExifTool::GPS::ToDMS($self, $val, 1)', + }, + 0xe9 => { + Name => 'GPSLongitudeRef', + Condition => '$$self{GPSVersionID}', + Format => 'string[2]', + Groups => { 1 => 'GPS', 2 => 'Location' }, + PrintConv => { + E => 'East', + W => 'West', + }, + }, + 0xeb => { + Name => 'GPSLongitude', + Condition => '$$self{GPSVersionID}', + Format => 'rational64u[3]', + Groups => { 1 => 'GPS', 2 => 'Location' }, + ValueConv => 'Image::ExifTool::GPS::ToDegrees($val)', + PrintConv => 'Image::ExifTool::GPS::ToDMS($self, $val, 1)', + }, + 0x103 => { + Name => 'GPSAltitudeRef', + Condition => '$$self{GPSVersionID}', + Format => 'int8u', + Groups => { 1 => 'GPS', 2 => 'Location' }, + PrintConv => { + 0 => 'Above Sea Level', + 1 => 'Below Sea Level', + }, + }, + 0x104 => { + Name => 'GPSAltitude', + Condition => '$$self{GPSVersionID}', + Format => 'rational64u', + Groups => { 1 => 'GPS', 2 => 'Location' }, + PrintConv => '$val =~ /^(inf|undef)$/ ? $val : "$val m"', + }, + 0x11c => { + Name => 'GPSTimeStamp', + Condition => '$$self{GPSVersionID}', + Groups => { 1 => 'GPS', 2 => 'Time' }, + Format => 'rational64u[3]', + ValueConv => 'Image::ExifTool::GPS::ConvertTimeStamp($val)', + PrintConv => 'Image::ExifTool::GPS::PrintTimeStamp($val)', + }, + 0x134 => { + Name => 'GPSSatellites', + Condition => '$$self{GPSVersionID}', + Format => 'string[3]', + Groups => { 1 => 'GPS', 2 => 'Location' }, + }, + 0x137 => { + Name => 'GPSStatus', + Condition => '$$self{GPSVersionID}', + Format => 'string[2]', + Groups => { 1 => 'GPS', 2 => 'Location' }, + PrintConv => { + A => 'Measurement Active', + V => 'Measurement Void', + }, + }, + 0x139 => { + Name => 'GPSMeasureMode', + Condition => '$$self{GPSVersionID}', + Format => 'string[2]', + Groups => { 1 => 'GPS', 2 => 'Location' }, + PrintConv => { + 2 => '2-Dimensional Measurement', + 3 => '3-Dimensional Measurement', + }, + }, + 0x13b => { + Name => 'GPSMapDatum', + Condition => '$$self{GPSVersionID}', + Format => 'string[7]', + Groups => { 1 => 'GPS', 2 => 'Location' }, + }, + 0x142 => { + Name => 'GPSDateStamp', + Condition => '$$self{GPSVersionID}', + Groups => { 1 => 'GPS', 2 => 'Time' }, + Format => 'string[11]', + ValueConv => 'Image::ExifTool::Exif::ExifDate($val)', + }, + 0x173 => { #(NC) + Name => 'AudioCodecID', + Format => 'string[4]', + }, + 0x7d3 => { + Name => 'PreviewImage', + Groups => { 2 => 'Preview' }, + Format => 'undef[$size-0x7d3]', + Notes => '640x480 JPEG preview image', # (black borders pad to 480 pixels high) + RawConv => '$self->ValidateImage(\$val,$tag)', + }, +); + +# tags in Pentax Optio RZ18 AVI videos (ref PH) +# (very similar to Olympus::AVI tags) +%Image::ExifTool::Pentax::Junk2 = ( + PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData, + GROUPS => { 0 => 'MakerNotes', 2 => 'Camera' }, + FIRST_ENTRY => 0, + NOTES => 'This information is found in AVI videos from the Optio RZ18.', + 0x12 => { + Name => 'Make', + Format => 'string[24]', + }, + 0x2c => { + Name => 'Model', + Description => 'Camera Model Name', + Format => 'string[24]', + }, + 0x5e => { + Name => 'FNumber', + Format => 'rational64u', + PrintConv => 'sprintf("%.1f",$val)', + }, + 0x83 => { + Name => 'DateTime1', + Format => 'string[24]', + Groups => { 2 => 'Time' }, + }, + 0x9d => { + Name => 'DateTime2', + Format => 'string[24]', + Groups => { 2 => 'Time' }, + }, + 0x12b => { + Name => 'ThumbnailWidth', + Format => 'int16u', + }, + 0x12d => { + Name => 'ThumbnailHeight', + Format => 'int16u', + }, + 0x12f => { + Name => 'ThumbnailLength', + Format => 'int32u', + }, + 0x133 => { + Name => 'ThumbnailImage', + Groups => { 2 => 'Preview' }, + Format => 'undef[$val{0x12f}]', + Notes => '160x120 JPEG thumbnail image', + RawConv => '$self->ValidateImage(\$val,$tag)', + }, +); + +#------------------------------------------------------------------------------ +# Convert filter settings (ref PH, K-5) +# Inputs: 0) value to convert, 1) flag for inverse conversion, 2) lookup table +# Returns: converted value +sub PrintFilter($$$) +{ + my ($val, $inv, $conv) = @_; + my (@vals, @cval, $t, $v); + + if (not $inv) { + # forward conversion (reading): + @vals = split ' ',$val; + $t = shift @vals; + push @cval, $$conv{$t} || "Unknown ($t)"; + while (@vals) { + $t = shift @vals; + $v = shift @vals; + next unless $t; + last unless defined $v; + my $c = $filterSettings{$t}; + if ($c) { + my $c1 = $$c[1]; + if (ref $c1) { + $v = $$c1{$v} || "Unknown($v)"; + } elsif ($v) { + $v = sprintf $c1, $v; + } + push @cval, "$$c[0]=$v"; + } else { + push @cval, "Unknown($t)=$v"; + } + } + return @cval ? \@cval : undef; + } else { + # reverse conversion (writing): + @vals = split /,\s*/, $val; + # convert filter name + delete $$conv{OTHER}; # avoid recursion + $v = Image::ExifTool::ReverseLookup(shift(@vals), $conv); + $$conv{OTHER} = \&PrintFilter; + return undef unless defined $v; + push @cval, $v; + # generate a lookup table for the filter setting name + my %settingNames; + $settingNames{$_} = $filterSettings{$_}[0] foreach keys %filterSettings; + # convert filter settings + foreach $v (@vals) { + $v =~ /^(.*)=(.*)$/ or return undef; + ($t, $v) = ($1, $2); + # look up settings name + $t = Image::ExifTool::ReverseLookup($t, \%settingNames); + return undef unless defined $t; + if (ref $filterSettings{$t}[1]) { + # look up settings value + $v = Image::ExifTool::ReverseLookup($v, $filterSettings{$t}[1]); + return undef unless defined $v; + } else { + return undef unless Image::ExifTool::IsInt($v); + } + push @cval, $t, $v; + } + push @cval, (0) x (17 - @cval) if @cval < 17; # pad with zeros if necessary + return join(' ', @cval); + } +} + +#------------------------------------------------------------------------------ +# Decode AF bit mask (ref 29) +# Inputs: 0) raw binary value, 1) number of AF points, 2) number of bits per AF point, +# 3) bit mask, 4) bit value (undef for any bit set) +sub DecodeAFPoints($$$$;$) +{ + my ($val, $num, $bits, $mask, $bitVal) = @_; + my @bytes = split ' ', $val; + my $i = 1; # (starts at AF point number 1) + my $shift = 8 - $bits; + my $byte = shift @bytes; + my @bitList; + for (;;) { + if ($bitVal) { + push @bitList, $i if (($byte >> $shift) & $mask) == $bitVal; + } else { + push @bitList, $i if ($byte >> $shift) & $mask; + } + last if ++$i > $num; + $shift -= $bits; + if ($shift < 0) { + last unless @bytes; + $byte = shift @bytes; + $shift += 8; + } + } + return join(',', @bitList); +} + +#------------------------------------------------------------------------------ +# Convert Pentax hex-based EV (modulo 8) to real number +# Inputs: 0) value to convert +# eg) 0x00 -> 0 +# 0x03 -> 0.33333 +# 0x04 -> 0.5 +# 0x05 -> 0.66666 +# 0x08 -> 1 ... etc +sub PentaxEv($) +{ + my $val = shift; + if ($val & 0x01) { + my $sign = $val < 0 ? -1 : 1; + my $frac = ($val * $sign) & 0x07; + if ($frac == 0x03) { + $val += $sign * ( 8 / 3 - $frac); + } elsif ($frac == 0x05) { + $val += $sign * (16 / 3 - $frac); + } + } + return $val / 8; +} + +#------------------------------------------------------------------------------ +# Convert number to Pentax hex-based EV (modulo 8) +# Inputs: 0) number +# Returns: Pentax EV code +sub PentaxEvInv($) +{ + my $num = shift; + my $val = $num * 8; + # extra fudging makes sure 0.3 and 0.33333 both round up to 3, etc + my $sign = $num < 0 ? -1 : 1; + my $inum = $num * $sign - int($num * $sign); + if ($inum > 0.29 and $inum < 0.4) { + $val += $sign / 3; + } elsif ($inum > 0.6 and $inum < .71) { + $val -= $sign / 3; + } + return int($val + 0.5 * $sign); +} + +#------------------------------------------------------------------------------ +# Encrypt or decrypt Pentax ShutterCount (symmetrical encryption) - PH +# Inputs: 0) shutter count value, 1) ExifTool object ref +# Returns: Encrypted or decrypted ShutterCount +sub CryptShutterCount($$) +{ + my ($val, $et) = @_; + # Pentax Date and Time values are used in the encryption + return undef unless $$et{PentaxDate} and $$et{PentaxTime} and + length($$et{PentaxDate})==4 and length($$et{PentaxTime})>=3; + # get Date and Time as integers (after padding Time with a null byte) + my $date = unpack('N', $$et{PentaxDate}); + my $time = unpack('N', $$et{PentaxTime} . "\0"); + return $val ^ $date ^ (0xffffffff - $time); +} + + +1; # end + +__END__ + +=head1 NAME + +Image::ExifTool::Pentax - Pentax/Asahi maker notes tags + +=head1 SYNOPSIS + +This module is loaded automatically by Image::ExifTool when required. + +=head1 DESCRIPTION + +This module contains definitions required by Image::ExifTool to interpret +Pentax and Asahi maker notes in EXIF information. + +=head1 NOTES + +I couldn't find a good source for Pentax maker notes information, but I've +managed to discover a fair bit of information by analyzing sample images +downloaded from the internet, and through tests with my own Optio S, Optio +WP, K10D, K-01 and K-5, and with help provided by other ExifTool users (see +L</ACKNOWLEDGEMENTS>). + +The Pentax maker notes are stored in standard EXIF format, but the offsets +used for some of their cameras are wacky. The Optio 330 gives the offset +relative to the offset of the tag in the directory, the Optio WP uses a base +offset in the middle of nowhere, and the Optio 550 uses different (and +totally illogical) bases for different menu entries. Very weird. (It +wouldn't surprise me if Pentax can't read their own maker notes!) Luckily, +there are only a few entries in the maker notes which are large enough to +require offsets, so this doesn't affect much useful information. ExifTool +attempts to make sense of this fiasco by making an assumption about where +the information should be stored to deduce the correct offsets. + +=head1 REFERENCES + +=over 4 + +=item L<Image::MakerNotes::Pentax|Image::MakerNotes::Pentax> + +=item L<http://johnst.org/sw/exiftags/> (Asahi models) + +=item L<http://kobe1995.jp/~kaz/astro/istD.html> + +=item L<http://www.cybercom.net/~dcoffin/dcraw/> + +=item (...plus lots of testing with my Optio WP, K10D and K-5!) + +=back + +=head1 ACKNOWLEDGEMENTS + +Thanks to Wayne Smith, John Francis, Douglas O'Brien, Cvetan Ivanov, Jens +Duttke, Dave Nicholson, Iliah Borg, Klaus Homeister, Louis Granboulan and +Andras Salamon for help figuring out some Pentax tags, Ger Vermeulen and +Niels Kristian Bech Jensen for contributing print conversion values for some +tags, and everyone who helped contribute to the LensType values. + +=head1 AUTHOR + +Copyright 2003-2019, Phil Harvey (phil at owl.phy.queensu.ca) + +This library is free software; you can redistribute it and/or modify it +under the same terms as Perl itself. + +=head1 SEE ALSO + +L<Image::ExifTool::TagNames/Pentax Tags>, +L<Image::ExifTool(3pm)|Image::ExifTool>, +L<Image::Info(3pm)|Image::Info> + +=cut diff --git a/lib/Image/ExifTool/PhaseOne.pm b/lib/Image/ExifTool/PhaseOne.pm new file mode 100644 index 0000000..268fb94 --- /dev/null +++ b/lib/Image/ExifTool/PhaseOne.pm @@ -0,0 +1,731 @@ +#------------------------------------------------------------------------------ +# File: PhaseOne.pm +# +# Description: Phase One maker notes tags +# +# Revisions: 2013-02-17 - P. Harvey Created +# +# References: 1) http://www.cybercom.net/~dcoffin/dcraw/ +#------------------------------------------------------------------------------ + +package Image::ExifTool::PhaseOne; + +use strict; +use vars qw($VERSION); +use Image::ExifTool qw(:DataAccess :Utils); +use Image::ExifTool::Exif; + +$VERSION = '1.05'; + +sub WritePhaseOne($$$); +sub ProcessPhaseOne($$$); + +# default formats based on PhaseOne format size +my @formatName = ( undef, 'string', 'int16s', undef, 'int32s' ); + +# Phase One maker notes (ref PH) +%Image::ExifTool::PhaseOne::Main = ( + PROCESS_PROC => \&ProcessPhaseOne, + WRITE_PROC => \&WritePhaseOne, + CHECK_PROC => \&Image::ExifTool::Exif::CheckExif, + WRITABLE => '1', + FORMAT => 'int32s', + GROUPS => { 0 => 'MakerNotes', 2 => 'Camera' }, + VARS => { ENTRY_SIZE => 16 }, # (entries contain a format field) + NOTES => 'These tags are extracted from the maker notes of Phase One images.', + 0x0100 => { #1 + Name => 'CameraOrientation', + ValueConv => '$val & 0x03', # ignore other bits for now + PrintConv => { + 0 => 'Horizontal (normal)', + 1 => 'Rotate 90 CW', + 2 => 'Rotate 270 CW', + 3 => 'Rotate 180', + }, + }, + # 0x0101 - int32u: 96,160,192,256,544 (same as 0x0213) + 0x0102 => { Name => 'SerialNumber', Format => 'string' }, + # 0x0103 - int32u: 19,20,59769034 + # 0x0104 - int32u: 50,200 + 0x0105 => 'ISO', + 0x0106 => { + Name => 'ColorMatrix1', + Format => 'float', + Count => 9, + PrintConv => q{ + my @a = map { sprintf('%.3f', $_) } split ' ', $val; + return "@a"; + }, + PrintConvInv => '$val', + }, + 0x0107 => { Name => 'WB_RGBLevels', Format => 'float', Count => 3 }, + 0x0108 => 'SensorWidth', + 0x0109 => 'SensorHeight', + 0x010a => 'SensorLeftMargin', #1 + 0x010b => 'SensorTopMargin', #1 + 0x010c => 'ImageWidth', + 0x010d => 'ImageHeight', + 0x010e => { #1 + Name => 'RawFormat', + # 1 = raw bit mask 0x5555 (>1 mask 0x1354) + # >2 = compressed + # 5 = non-linear + PrintConv => { #PH + 1 => 'RAW 1', #? (encrypted) + 2 => 'RAW 2', #? (encrypted) + 3 => 'IIQ L', + # 4? + 5 => 'IIQ S', + 6 => 'IIQ Sv2', + }, + }, + 0x010f => { + Name => 'RawData', + Format => 'undef', # (actually 2-byte integers, but don't convert) + Binary => 1, + PutFirst => 1, + Writable => 0, + Drop => 1, # don't copy to other file types + }, + 0x0110 => { #1 + Name => 'SensorCalibration', + SubDirectory => { TagTable => 'Image::ExifTool::PhaseOne::SensorCalibration' }, + }, + 0x0112 => { + Name => 'DateTimeOriginal', + Description => 'Date/Time Original', + Format => 'int32u', + Writable => 0, # (don't write because this is an encryption key for RawFormat 1 and 2) + Priority => 0, + Shift => 'Time', + Groups => { 2 => 'Time' }, + Notes => 'may be used as a key to encrypt the raw data', #1 + ValueConv => 'ConvertUnixTime($val)', + ValueConvInv => 'GetUnixTime($val)', + PrintConv => '$self->ConvertDateTime($val)', + PrintConvInv => '$self->InverseDateTime($val)', + }, + 0x0113 => 'ImageNumber', # (NC) + 0x0203 => { Name => 'Software', Format => 'string' }, + 0x0204 => { Name => 'System', Format => 'string' }, + # 0x020b - int32u: 0,1 + # 0x020c - int32u: 1,2 + # 0x020e - int32u: 1,3 + 0x0210 => { # (NC) (used in linearization formula - ref 1) + Name => 'SensorTemperature', + Format => 'float', + PrintConv => 'sprintf("%.2f C",$val)', + PrintConvInv => '$val=~s/ ?C//; $val', + }, + 0x0211 => { # (NC) + Name => 'SensorTemperature2', + Format => 'float', + PrintConv => 'sprintf("%.2f C",$val)', + PrintConvInv => '$val=~s/ ?C//; $val', + }, + 0x0212 => { + Name => 'UnknownDate', + Format => 'int32u', + Groups => { 2 => 'Time' }, + # (this time is within about 10 minutes before or after 0x0112) + Unknown => 1, + Shift => 'Time', + ValueConv => 'ConvertUnixTime($val)', + ValueConvInv => 'GetUnixTime($val)', + PrintConv => '$self->ConvertDateTime($val)', + PrintConvInv => '$self->InverseDateTime($val)', + }, + # 0x0213 - int32u: 96,160,192,256,544 (same as 0x0101) + # 0x0215 - int32u: 4,5 + # 0x021a - used by dcraw + 0x021c => { Name => 'StripOffsets', Binary => 1, Writable => 0 }, + 0x021d => 'BlackLevel', #1 + # 0x021e - int32u: 1 + # 0x0220 - int32u: 32 + # 0x0221 - float: 0-271 + 0x0222 => 'SplitColumn', #1 + 0x0223 => { Name => 'BlackLevelData', Format => 'int16u', Count => -1, Binary => 1 }, #1 + # 0x0224 - int32u: 1688,2748,3372 + 0x0225 => { + Name => 'PhaseOne_0x0225', + Format => 'int16s', + Count => -1, + Flags => ['Unknown','Hidden'], + PrintConv => 'length($val) > 60 ? substr($val,0,55) . "[...]" : $val', + }, + 0x0226 => { + Name => 'ColorMatrix2', + Format => 'float', + Count => 9, + PrintConv => q{ + my @a = map { sprintf('%.3f', $_) } split ' ', $val; + return "@a"; + }, + PrintConvInv => '$val', + }, + # 0x0227 - int32u: 0,1 + # 0x0228 - int32u: 1,2 + # 0x0229 - int32s: -2,0 + 0x0267 => { #PH + Name => 'AFAdjustment', + Format => 'float', + }, + 0x022b => { #PH + Name => 'PhaseOne_0x022b', + Format => 'float', + Flags => ['Unknown','Hidden'], + }, + # 0x0242 - int32u: 55 + # 0x0244 - int32u: 102 + # 0x0245 - float: 1.2 + 0x0258 => { #PH + Name => 'PhaseOne_0x0258', + Format => 'int16s', + Flags => ['Unknown','Hidden'], + PrintConv => 'length($val) > 60 ? substr($val,0,55) . "[...]" : $val', + }, + 0x025a => { #PH + Name => 'PhaseOne_0x025a', + Format => 'int16s', + Flags => ['Unknown','Hidden'], + PrintConv => 'length($val) > 60 ? substr($val,0,55) . "[...]" : $val', + }, + # 0x0300 - int32u: 100,101,102 + 0x0301 => { Name => 'FirmwareVersions', Format => 'string' }, + # 0x0304 - int32u: 8,3073,3076 + 0x0400 => { + Name => 'ShutterSpeedValue', + Format => 'float', + ValueConv => 'abs($val)<100 ? 2**(-$val) : 0', + ValueConvInv => '$val>0 ? -log($val)/log(2) : -100', + PrintConv => 'Image::ExifTool::Exif::PrintExposureTime($val)', + PrintConvInv => 'Image::ExifTool::Exif::ConvertFraction($val)', + }, + 0x0401 => { + Name => 'ApertureValue', + Format => 'float', + ValueConv => '2 ** ($val / 2)', + ValueConvInv => '$val>0 ? 2*log($val)/log(2) : 0', + PrintConv => 'sprintf("%.1f",$val)', + PrintConvInv => '$val', + }, + 0x0402 => { + Name => 'ExposureCompensation', + Format => 'float', + PrintConv => 'sprintf("%.3f",$val)', + PrintConvInv => '$val', + }, + 0x0403 => { + Name => 'FocalLength', + Format => 'float', + PrintConv => 'sprintf("%.1f mm",$val)', + PrintConvInv => '$val=~s/\s*mm$//;$val', + }, + # 0x0404 - int32u: 0,3 + # 0x0405 - int32u? (big numbers) + # 0x0406 - int32u: 1 + # 0x0407 - float: -0.333 (exposure compensation again?) + # 0x0408-0x0409 - int32u: 1 + 0x0410 => { Name => 'CameraModel', Format => 'string' }, + # 0x0411 - int32u: 33556736 + 0x0412 => { Name => 'LensModel', Format => 'string' }, + 0x0414 => { + Name => 'MaxApertureValue', + Format => 'float', + ValueConv => '2 ** ($val / 2)', + ValueConvInv => '$val>0 ? 2*log($val)/log(2) : 0', + PrintConv => 'sprintf("%.1f",$val)', + PrintConvInv => '$val', + }, + 0x0415 => { + Name => 'MinApertureValue', + Format => 'float', + ValueConv => '2 ** ($val / 2)', + ValueConvInv => '$val>0 ? 2*log($val)/log(2) : 0', + PrintConv => 'sprintf("%.1f",$val)', + PrintConvInv => '$val', + }, + # 0x0416 - float: (min focal length? ref LR, Credo50) (but looks more like an int32u date for the 645DF - PH) + # 0x0417 - float: 80 (max focal length? ref LR) + 0x0455 => { #PH + Name => 'Viewfinder', + Format => 'string', + }, +); + +# Phase One metadata (ref 1) +%Image::ExifTool::PhaseOne::SensorCalibration = ( + PROCESS_PROC => \&ProcessPhaseOne, + WRITE_PROC => \&WritePhaseOne, + CHECK_PROC => \&Image::ExifTool::Exif::CheckExif, + GROUPS => { 0 => 'MakerNotes', 2 => 'Camera' }, + TAG_PREFIX => 'SensorCalibration', + VARS => { ENTRY_SIZE => 12 }, # (entries do not contain a format field) + 0x0400 => { + Name => 'SensorDefects', + # list of defects. each defect is 4 x int16u values: + # 0=column, 1=row, 2=type (129=bad pixel, 131=bad column), 3=? + # (but it isn't really worth the time decoding this -- it can be a few hundred kB) + Format => 'undef', + Binary => 1, + }, + 0x0401 => { + Name => 'AllColorFlatField1', + Format => 'undef', + Flags => ['Unknown','Binary'], + }, + 0x0404 => { #PH + Name => 'SensorCalibration_0x0404', + Format => 'string', + Flags => ['Unknown','Hidden'], + }, + 0x0405 => { #PH + Name => 'SensorCalibration_0x0405', + Format => 'string', + Flags => ['Unknown','Hidden'], + }, + 0x0406 => { #PH + Name => 'SensorCalibration_0x0406', + Format => 'string', + Flags => ['Unknown','Hidden'], + }, + 0x0407 => { #PH + Name => 'SerialNumber', + Format => 'string', + Writable => 1, + }, + 0x0408 => { #PH + Name => 'SensorCalibration_0x0408', + Format => 'float', + Flags => ['Unknown','Hidden'], + }, + 0x040b => { + Name => 'RedBlueFlatField', + Format => 'undef', + Flags => ['Unknown','Binary'], + }, + 0x040f => { #PH + Name => 'SensorCalibration_0x040f', + Format => 'undef', + Flags => ['Unknown','Hidden'], + }, + 0x0410 => { + Name => 'AllColorFlatField2', + Format => 'undef', + Flags => ['Unknown','Binary'], + }, + # 0x0412 - used by dcraw + 0x0413 => { #PH + Name => 'SensorCalibration_0x0413', + Format => 'double', + Flags => ['Unknown','Hidden'], + }, + 0x0414 => { #PH + Name => 'SensorCalibration_0x0414', + Format => 'undef', + Flags => ['Unknown','Hidden'], + ValueConv => q{ + my $order = GetByteOrder(); + if (length $val >= 8 and SetByteOrder(substr($val,0,2))) { + $val = ReadValue(\$val, 2, 'int16u', 1, length($val)-2) . ' ' . + ReadValue(\$val, 4, 'float', undef, length($val)-4); + SetByteOrder($order); + } + return $val; + }, + }, + 0x0416 => { + Name => 'AllColorFlatField3', + Format => 'undef', + Flags => ['Unknown','Binary'], + }, + 0x0418 => { #PH + Name => 'SensorCalibration_0x0418', + Format => 'undef', + Flags => ['Unknown','Hidden'], + }, + 0x0419 => { + Name => 'LinearizationCoefficients1', + Format => 'float', + PrintConv => 'my @a=split " ",$val;join " ", map { sprintf("%.5g",$_) } @a', + }, + 0x041a => { + Name => 'LinearizationCoefficients2', + Format => 'float', + PrintConv => 'my @a=split " ",$val;join " ", map { sprintf("%.5g",$_) } @a', + }, + 0x041c => { #PH + Name => 'SensorCalibration_0x041c', + Format => 'float', + Flags => ['Unknown','Hidden'], + }, + 0x041e => { #PH + Name => 'SensorCalibration_0x041e', + Format => 'undef', + Flags => ['Unknown','Hidden'], + ValueConv => q{ + my $order = GetByteOrder(); + if (length $val >= 8 and SetByteOrder(substr($val,0,2))) { + $val = ReadValue(\$val, 2, 'int16u', 1, length($val)-2) . ' ' . + ReadValue(\$val, 4, 'float', undef, length($val)-4); + SetByteOrder($order); + } + return $val; + }, + }, +); + +#------------------------------------------------------------------------------ +# Do HTML dump of an IFD entry +# Inputs: 0) ExifTool ref, 1) tag table ref, 3) tag ID, 4) tag value, +# 5) IFD entry offset, 6) IFD entry size, 7) parameter hash +sub HtmlDump($$$$$$%) +{ + my ($et, $tagTablePtr, $tagID, $value, $entry, $entryLen, %parms) = @_; + my ($dirName, $index, $formatStr, $dataPos, $base, $size, $valuePtr) = + @parms{qw(DirName Index Format DataPos Base Size Start)}; + my $tagInfo = $et->GetTagInfo($tagTablePtr, $tagID); + my ($tagName, $colName, $subdir); + my $count = $parms{Count} || $size; + $base = 0 unless defined $base; + if ($tagInfo) { + $tagName = $$tagInfo{Name}; + $subdir = $$tagInfo{SubDirectory}; + if ($$tagInfo{Format}) { + $formatStr = $$tagInfo{Format}; + $count = $size / Image::ExifTool::FormatSize($formatStr); + } + } else { + $tagName = sprintf("Tag 0x%.4x", $tagID); + } + my $dname = sprintf("${dirName}-%.2d", $index); + # build our tool tip + my $fstr = "$formatStr\[$count]"; + my $tip = sprintf("Tag ID: 0x%.4x\n", $tagID) . + "Format: $fstr\nSize: $size bytes\n"; + if ($size > 4) { + $tip .= sprintf("Value offset: 0x%.4x\n", $valuePtr - $base); + $tip .= sprintf("Actual offset: 0x%.4x\n", $valuePtr + $dataPos); + $tip .= sprintf("Offset base: 0x%.4x\n", $dataPos + $base); + $colName = "<span class=F>$tagName</span>"; + } else { + $colName = $tagName; + } + unless (ref $value) { + my $tval = length($value) > 32 ? substr($value,0,28) . '[...]' : $value; + $tval =~ tr/\x00-\x1f\x7f-\xff/./; + $tip .= "Value: $tval"; + } + $et->HDump($entry+$dataPos, $entryLen, "$dname $colName", $tip, 1); + if ($size > 4) { + my $dumpPos = $valuePtr + $dataPos; + # add value data block + $et->HDump($dumpPos,$size,"$tagName value",'SAME', $subdir ? 0x04 : 0); + } +} + +#------------------------------------------------------------------------------ +# Write PhaseOne maker notes (both types of PhaseOne IFD) +# Inputs: 0) ExifTool object ref, 1) source dirInfo ref, 2) tag table ref +# Returns: data block or undef on error +sub WritePhaseOne($$$) +{ + my ($et, $dirInfo, $tagTablePtr) = @_; + $et or return 1; # allow dummy access to autoload this package + + # nothing to do if we aren't changing any PhaseOne tags + my $newTags = $et->GetNewTagInfoHash($tagTablePtr); + return undef unless %$newTags or $$et{DropTags}; + + my $dataPt = $$dirInfo{DataPt}; + my $dataPos = $$dirInfo{DataPos} || 0; + my $dirStart = $$dirInfo{DirStart} || 0; + my $dirLen = $$dirInfo{DirLen} || $$dirInfo{DataLen} - $dirStart; + my $dirName = $$dirInfo{DirName}; + my $verbose = $et->Options('Verbose'); + + return undef if $dirLen < 12; + unless ($$tagTablePtr{VARS} and $$tagTablePtr{VARS}{ENTRY_SIZE}) { + $et->WarnOnce("No ENTRY_SIZE for $$tagTablePtr{TABLE_NAME}"); + return undef; + } + my $entrySize = $$tagTablePtr{VARS}{ENTRY_SIZE}; + my $ifdType = $$tagTablePtr{TAG_PREFIX} || 'PhaseOne'; + my $hdr = substr($$dataPt, $dirStart, 12); + if ($entrySize == 16) { + return undef unless $hdr =~ /^(IIII.waR|MMMMRaw.)/s; + } elsif ($hdr !~ /^(IIII\x01\0\0\0|MMMM\0\0\0\x01)/s) { + $et->Warn("Unrecognized $ifdType directory version"); + return undef; + } + SetByteOrder(substr($hdr, 0, 2)); + # get offset to start of PhaseOne directory + my $ifdStart = Get32u(\$hdr, 8); + return undef if $ifdStart + 8 > $dirLen; + # initialize output directory buffer with (fixed) number of entries plus 4-byte padding + my $dirBuff = substr($$dataPt, $dirStart + $ifdStart, 8); + # get number of entries in PhaseOne directory + my $numEntries = Get32u(\$dirBuff, 0); + my $ifdEnd = $ifdStart + 8 + $entrySize * $numEntries; + return undef if $numEntries < 2 or $numEntries > 300 or $ifdEnd > $dirLen; + my $hdrBuff = $hdr; + my $valBuff = ''; # buffer for value data + my $fixup = new Image::ExifTool::Fixup; + my $index; + for ($index=0; $index<$numEntries; ++$index) { + my $entry = $dirStart + $ifdStart + 8 + $entrySize * $index; + my $tagID = Get32u($dataPt, $entry); + my $size = Get32u($dataPt, $entry+$entrySize-8); + my ($formatSize, $formatStr); + if ($entrySize == 16) { + $formatSize = Get32u($dataPt, $entry+4); + $formatStr = $formatName[$formatSize]; + unless ($formatStr) { + $et->Warn("Possibly invalid $ifdType IFD entry $index",1); + delete $$newTags{$tagID}; # make sure we don't try to change this one + } + } else { + # (no format code for SensorCalibration IFD entries) + $formatSize = 1; + $formatStr = 'undef'; + } + my $valuePtr = $entry + $entrySize - 4; + if ($size > 4) { + if ($size > 0x7fffffff) { + $et->Error("Invalid size for $ifdType IFD entry $index",1); + return undef; + } + $valuePtr = Get32u($dataPt, $valuePtr); + if ($valuePtr + $size > $dirLen) { + $et->Error(sprintf("Invalid offset 0x%.4x for $ifdType IFD entry $index",$valuePtr),1); + return undef; + } + $valuePtr += $dirStart; + } + my $value = substr($$dataPt, $valuePtr, $size); + my $tagInfo = $$newTags{$tagID} || $$tagTablePtr{$tagID}; + $tagInfo = $et->GetTagInfo($tagTablePtr, $tagID) if $tagInfo and ref($tagInfo) ne 'HASH'; + if ($$newTags{$tagID}) { + $formatStr = $$tagInfo{Format} if $$tagInfo{Format}; + my $count = int($size / Image::ExifTool::FormatSize($formatStr)); + my $val = ReadValue(\$value, 0, $formatStr, $count, $size); + my $nvHash = $et->GetNewValueHash($tagInfo); + if ($et->IsOverwriting($nvHash, $val)) { + my $newVal = $et->GetNewValue($nvHash); + # allow count to change for string and undef types only + undef $count if $formatStr eq 'string' or $formatStr eq 'undef'; + my $newValue = WriteValue($newVal, $formatStr, $count); + if (defined $newValue) { + $value = $newValue; + $size = length $newValue; + $et->VerboseValue("- $dirName:$$tagInfo{Name}", $val); + $et->VerboseValue("+ $dirName:$$tagInfo{Name}", $newVal); + ++$$et{CHANGED}; + } + } + } elsif ($tagInfo and $$tagInfo{SubDirectory}) { + my $subTable = GetTagTable($$tagInfo{SubDirectory}{TagTable}); + my %subdirInfo = ( + DirName => $$tagInfo{Name}, + DataPt => \$value, + DataLen => length $value, + ); + my $newValue = $et->WriteDirectory(\%subdirInfo, $subTable); + if (defined $newValue and length($newValue)) { + $value = $newValue; + $size = length $newValue; + } + } elsif ($$et{DropTags} and (($tagInfo and $$tagInfo{Drop}) or $size > 8192)) { + # decrease the number of entries in the directory + Set32u(Get32u(\$dirBuff, 0) - 1, \$dirBuff, 0); + next; # drop this tag + } + # add the tagID, possibly format size, and size to this directory entry + $dirBuff .= substr($$dataPt, $entry, $entrySize - 8) . Set32u($size); + + # pad value to an even 4-byte boundary just in case + $value .= ("\0" x (4 - ($size & 0x03))) if $size & 0x03 or not $size; + if ($size <= 4) { + # store value in place of the IFD value pointer (already padded to 4 bytes) + $dirBuff .= $value; + } elsif ($tagInfo and $$tagInfo{PutFirst}) { + # store value immediately after header + $dirBuff .= Set32u(length $hdrBuff); + $hdrBuff .= $value; + } else { + # store value at end of value buffer + $fixup->AddFixup(length $dirBuff); + $dirBuff .= Set32u(length $valBuff); + $valBuff .= $value; + } + } + # apply necessary fixup to offsets in PhaseOne directory + $$fixup{Shift} = length $hdrBuff; + $fixup->ApplyFixup(\$dirBuff); + # set pointer to PhaseOneIFD in header + Set32u(length($hdrBuff) + length($valBuff), \$hdrBuff, 8); + return $hdrBuff . $valBuff . $dirBuff; +} + +#------------------------------------------------------------------------------ +# Read Phase One maker notes +# Inputs: 0) ExifTool object ref, 1) dirInfo ref, 2) tag table ref +# Returns: 1 on success +# Notes: This routine processes both the main PhaseOne IFD type (with 16 bytes +# per entry), and the SensorCalibration IFD type (12 bytes per entry) +sub ProcessPhaseOne($$$) +{ + my ($et, $dirInfo, $tagTablePtr) = @_; + my $dataPt = $$dirInfo{DataPt}; + my $dataPos = ($$dirInfo{DataPos} || 0) + ($$dirInfo{Base} || 0); + my $dirStart = $$dirInfo{DirStart} || 0; + my $dirLen = $$dirInfo{DirLen} || $$dirInfo{DataLen} - $dirStart; + my $binary = $et->Options('Binary'); + my $verbose = $et->Options('Verbose'); + my $htmlDump = $$et{HTML_DUMP}; + + return 0 if $dirLen < 12; + unless ($$tagTablePtr{VARS} and $$tagTablePtr{VARS}{ENTRY_SIZE}) { + $et->WarnOnce("No ENTRY_SIZE for $$tagTablePtr{TABLE_NAME}"); + return undef; + } + my $entrySize = $$tagTablePtr{VARS}{ENTRY_SIZE}; + my $ifdType = $$tagTablePtr{TAG_PREFIX} || 'PhaseOne'; + + my $hdr = substr($$dataPt, $dirStart, 12); + if ($entrySize == 16) { + return 0 unless $hdr =~ /^(IIII.waR|MMMMRaw.)/s; + } elsif ($hdr !~ /^(IIII\x01\0\0\0|MMMM\0\0\0\x01)/s) { + $et->Warn("Unrecognized $ifdType directory version"); + return 0; + } + SetByteOrder(substr($hdr, 0, 2)); + # get offset to start of PhaseOne directory + my $ifdStart = Get32u(\$hdr, 8); + return 0 if $ifdStart + 8 > $dirLen; + # get number of entries in PhaseOne directory + my $numEntries = Get32u($dataPt, $dirStart + $ifdStart); + my $ifdEnd = $ifdStart + 8 + $entrySize * $numEntries; + return 0 if $numEntries < 2 or $numEntries > 300 or $ifdEnd > $dirLen; + $et->VerboseDir($ifdType, $numEntries); + if ($htmlDump) { + $et->HDump($dirStart + $dataPos, 8, "$ifdType header"); + $et->HDump($dirStart + $dataPos + 8, 4, "$ifdType IFD offset"); + $et->HDump($dirStart + $dataPos + $ifdStart, 4, "$ifdType entries", + "Entry count: $numEntries"); + $et->HDump($dirStart + $dataPos + $ifdStart + 4, 4, '[unused]'); + } + my $index; + for ($index=0; $index<$numEntries; ++$index) { + my $entry = $dirStart + $ifdStart + 8 + $entrySize * $index; + my $tagID = Get32u($dataPt, $entry); + my $size = Get32u($dataPt, $entry+$entrySize-8); + my $valuePtr = $entry + $entrySize - 4; + my ($formatSize, $formatStr, $value); + if ($entrySize == 16) { + # (format code only for the 16-byte IFD entry) + $formatSize = Get32u($dataPt, $entry+4); + $formatStr = $formatName[$formatSize]; + unless ($formatStr) { + $et->WarnOnce("Unrecognized $ifdType format size $formatSize",1); + $formatSize = 1; + $formatStr = 'undef'; + } + } elsif ($size %4) { + $formatSize = 1; + $formatStr = 'undef'; + } else { + $formatSize = 4; + $formatStr = 'int32s'; + } + if ($size > 4) { + if ($size > 0x7fffffff) { + $et->Warn("Invalid size for $ifdType IFD entry $index"); + return 0; + } + $valuePtr = Get32u($dataPt, $valuePtr); + if ($valuePtr + $size > $dirLen) { + $et->Warn(sprintf("Invalid offset 0x%.4x for $ifdType IFD entry $index",$valuePtr)); + return 0; + } + $valuePtr += $dirStart; + } + my $tagInfo = $et->GetTagInfo($tagTablePtr, $tagID); + if ($tagInfo) { + $formatStr = $$tagInfo{Format} if $$tagInfo{Format}; + } else { + next unless $verbose or $htmlDump; + } + my $count = int($size / Image::ExifTool::FormatSize($formatStr)); + if ($count > 100000 and not $binary) { + $value = \ "Binary data $size bytes"; + } else { + $value = ReadValue($dataPt,$valuePtr,$formatStr,$count,$size); + # try to distinguish between the various format types + if ($formatStr eq 'int32s') { + my ($val) = split ' ', $value; + if (defined $val) { + # get floating point exponent (has bias of 127) + my $exp = ($val & 0x7f800000) >> 23; + if ($exp > 120 and $exp < 140) { + $formatStr = 'float'; + $value = ReadValue($dataPt,$valuePtr,$formatStr,$count,$size); + } + } + } + } + my %parms = ( + DirName => $ifdType, + Index => $index, + DataPt => $dataPt, + DataPos => $dataPos, + Size => $size, + Start => $valuePtr, + Format => $formatStr, + Count => $count + ); + $htmlDump and HtmlDump($et, $tagTablePtr, $tagID, $value, $entry, $entrySize, + %parms, Base => $dirStart); + $et->HandleTag($tagTablePtr, $tagID, $value, %parms); + } + return 1; +} + +1; # end + +__END__ + +=head1 NAME + +Image::ExifTool::PhaseOne - Phase One maker notes tags + +=head1 SYNOPSIS + +This module is loaded automatically by Image::ExifTool when required. + +=head1 DESCRIPTION + +This module contains definitions required by Image::ExifTool to decode Phase +One maker notes. + +=head1 AUTHOR + +Copyright 2003-2019, Phil Harvey (phil at owl.phy.queensu.ca) + +This library is free software; you can redistribute it and/or modify it +under the same terms as Perl itself. + +=head1 REFERENCES + +=over 4 + +=item L<http://www.cybercom.net/~dcoffin/dcraw/> + +=back + +=head1 SEE ALSO + +L<Image::ExifTool::TagNames/PhaseOne Tags>, +L<Image::ExifTool(3pm)|Image::ExifTool> + +=cut diff --git a/lib/Image/ExifTool/PhotoCD.pm b/lib/Image/ExifTool/PhotoCD.pm new file mode 100644 index 0000000..f469982 --- /dev/null +++ b/lib/Image/ExifTool/PhotoCD.pm @@ -0,0 +1,506 @@ +#------------------------------------------------------------------------------ +# File: PhotoCD.pm +# +# Description: Read Kodak Photo CD Image Pac (PCD) metadata +# +# Revisions: 2012/05/07 - P. Harvey Created +# +# References: 1) http://pcdtojpeg.sourceforge.net/ +#------------------------------------------------------------------------------ + +package Image::ExifTool::PhotoCD; + +use strict; +use vars qw($VERSION); +use Image::ExifTool qw(:DataAccess :Utils); + +$VERSION = '1.03'; + +sub ProcessExtData($$$); + +# PhotoCD info +%Image::ExifTool::PhotoCD::Main = ( + PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData, + GROUPS => { 2 => 'Image' }, + NOTES => 'Tags extracted from Kodak Photo CD Image Pac (PCD) files.', + 7 => { + Name => 'SpecificationVersion', + Format => 'int8u[2]', + RawConv => '$val eq "255 255" ? "n/a" : $val', + ValueConv => '$val =~ tr/ /./; $val', + }, + 9 => { + Name => 'AuthoringSoftwareRelease', + Format => 'int8u[2]', + RawConv => '$val eq "255 255" ? "n/a" : $val', + ValueConv => '$val =~ tr/ /./; $val', + }, + 11 => { + Name => 'ImageMagnificationDescriptor', + Format => 'int8u[2]', + ValueConv => '$val =~ tr/ /./; $val', + }, + 13 => { + Name => 'CreateDate', + Format => 'int32u', + Groups => { 2 => 'Time' }, + RawConv => '$val == 0xffffffff ? undef : $val', + ValueConv => 'ConvertUnixTime($val,1)', + PrintConv => '$self->ConvertDateTime($val)', + }, + 17 => { + Name => 'ModifyDate', + Format => 'int32u', + Groups => { 2 => 'Time' }, + RawConv => '$val == 0xffffffff ? undef : $val', + ValueConv => 'ConvertUnixTime($val,1)', + PrintConv => '$self->ConvertDateTime($val)', + }, + 21 => { + Name => 'ImageMedium', + PrintConv => { + 0 => 'Color negative', + 1 => 'Color reversal', + 2 => 'Color hard copy', + 3 => 'Thermal hard copy', + 4 => 'Black and white negative', + 5 => 'Black and white reversal', + 6 => 'Black and white hard copy', + 7 => 'Internegative', + 8 => 'Synthetic image', + }, + }, + 22 => { + Name => 'ProductType', + Format => 'string[20]', + ValueConv => '$val =~ s/[ \0]+$//; $val', + }, + 42 => { + Name => 'ScannerVendorID', + Format => 'string[20]', + ValueConv => '$val =~ s/[ \0]+$//; $val', + }, + 62 => { + Name => 'ScannerProductID', + Format => 'string[16]', + ValueConv => '$val =~ s/[ \0]+$//; $val', + }, + 78 => { + Name => 'ScannerFirmwareVersion', + Format => 'string[4]', + ValueConv => '$val =~ s/[ \0]+$//; $val', + }, + 82 => { + Name => 'ScannerFirmwareDate', + Format => 'string[8]', + ValueConv => '$val =~ s/[ \0]+$//; $val', + }, + 90 => { + Name => 'ScannerSerialNumber', + Format => 'string[20]', + ValueConv => '$val =~ s/[ \0]+$//; $val', + }, + 110 => { + Name => 'ScannerPixelSize', + Format => 'undef[2]', + ValueConv => 'join(".",unpack("H2H2",$val))', + PrintConv => '"$val micrometers"', + }, + 112 => { + Name => 'ImageWorkstationMake', + Format => 'string[20]', + ValueConv => '$val =~ s/[ \0]+$//; $val', + }, + 132 => { + Name => 'CharacterSet', + PrintConv => { + 1 => '38 characters ISO 646', + 2 => '65 characters ISO 646', + 3 => '95 characters ISO 646', + 4 => '191 characters ISO 8850-1', + 5 => 'ISO 2022', + 6 => 'Includes characters not ISO 2375 registered', + }, + }, + 133 => { + Name => 'CharacterEscapeSequence', + Format => 'undef[32]', + Binary => 1, + Unknown => 1, + }, + 165 => { + Name => 'PhotoFinisherName', + Format => 'string[60]', + ValueConv => '$val =~ s/[ \0]+$//; $val', + }, + 225 => { + Name => 'HasSBA', + Format => 'undef[3]', + Hidden => 1, + RawConv => '$val eq "SBA" and $$self{HasSBA} = 1; undef', + }, + 228 => { + Name => 'SceneBalanceAlgorithmRevision', + Condition => '$$self{HasSBA}', + Format => 'int8u[2]', + ValueConv => '$val =~ tr/ /./; $val', + }, + 230 => { + Name => 'SceneBalanceAlgorithmCommand', + Condition => '$$self{HasSBA}', + PrintConv => { + 0 => 'Neutral SBA On, Color SBA On', + 1 => 'Neutral SBA Off, Color SBA Off', + 2 => 'Neutral SBA On, Color SBA Off', + 3 => 'Neutral SBA Off, Color SBA On', + }, + }, + 325 => { + Name => 'SceneBalanceAlgorithmFilmID', + Condition => '$$self{HasSBA}', + Format => 'int16u', + PrintConv => { + 1 => '3M ScotchColor AT 100', + 2 => '3M ScotchColor AT 200', + 3 => '3M ScotchColor HR2 400', + 7 => '3M Scotch HR 200 Gen 2', + 9 => '3M Scotch HR 400 Gen 2', + 16 => 'Agfa Agfacolor XRS 400 Gen 1', + 17 => 'Agfa Agfacolor XRG/XRS 400', + 18 => 'Agfa Agfacolor XRG/XRS 200', + 19 => 'Agfa Agfacolor XRS 1000 Gen 2', + 20 => 'Agfa Agfacolor XRS 400 Gen 2', + 21 => 'Agfa Agfacolor XRS/XRC 100', + 26 => 'Fuji Reala 100 (JAPAN)', + 27 => 'Fuji Reala 100 Gen 1', + 28 => 'Fuji Reala 100 Gen 2', + 29 => 'Fuji SHR 400 Gen 2', + 30 => 'Fuji Super HG 100', + 31 => 'Fuji Super HG 1600 Gen 1', + 32 => 'Fuji Super HG 200', + 33 => 'Fuji Super HG 400', + 34 => 'Fuji Super HG 100 Gen 2', + 35 => 'Fuji Super HR 100 Gen 1', + 36 => 'Fuji Super HR 100 Gen 2', + 37 => 'Fuji Super HR 1600 Gen 2', + 38 => 'Fuji Super HR 200 Gen 1', + 39 => 'Fuji Super HR 200 Gen 2', + 40 => 'Fuji Super HR 400 Gen 1', + 43 => 'Fuji NSP 160S (Pro)', + 45 => 'Kodak Kodacolor VR 100 Gen 2', + 47 => 'Kodak Gold 400 Gen 3', + 55 => 'Kodak Ektar 100 Gen 1', + 56 => 'Kodak Ektar 1000 Gen 1', + 57 => 'Kodak Ektar 125 Gen 1', + 58 => 'Kodak Royal Gold 25 RZ', + 60 => 'Kodak Gold 1600 Gen 1', + 61 => 'Kodak Gold 200 Gen 2', + 62 => 'Kodak Gold 400 Gen 2', + 65 => 'Kodak Kodacolor VR 100 Gen 1', + 66 => 'Kodak Kodacolor VR 1000 Gen 2', + 67 => 'Kodak Kodacolor VR 1000 Gen 1', + 68 => 'Kodak Kodacolor VR 200 Gen 1', + 69 => 'Kodak Kodacolor VR 400 Gen 1', + 70 => 'Kodak Kodacolor VR 200 Gen 2', + 71 => 'Kodak Kodacolor VRG 100 Gen 1', + 72 => 'Kodak Gold 100 Gen 2', + 73 => 'Kodak Kodacolor VRG 200 Gen 1', + 74 => 'Kodak Gold 400 Gen 1', + 87 => 'Kodak Ektacolor Gold 160', + 88 => 'Kodak Ektapress 1600 Gen 1 PPC', + 89 => 'Kodak Ektapress Gold 100 Gen 1 PPA', + 90 => 'Kodak Ektapress Gold 400 PPB-3', + 92 => 'Kodak Ektar 25 Professional PHR', + 97 => 'Kodak T-Max 100 Professional', + 98 => 'Kodak T-Max 3200 Professional', + 99 => 'Kodak T-Max 400 Professional', + 101 => 'Kodak Vericolor 400 Prof VPH', + 102 => 'Kodak Vericolor III Pro', + 121 => 'Konika Konica Color SR-G 3200', + 122 => 'Konika Konica Color Super SR100', + 123 => 'Konika Konica Color Super SR 400', + 138 => 'Kodak Gold Unknown', + 139 => 'Kodak Unknown Neg A- Normal SBA', + 143 => 'Kodak Ektar 100 Gen 2', + 147 => 'Kodak Kodacolor CII', + 148 => 'Kodak Kodacolor II', + 149 => 'Kodak Gold Plus 200 Gen 3', + 150 => 'Kodak Internegative +10% Contrast', + 151 => 'Agfa Agfacolor Ultra 50', + 152 => 'Fuji NHG 400', + 153 => 'Agfa Agfacolor XRG 100', + 154 => 'Kodak Gold Plus 100 Gen 3', + 155 => 'Konika Konica Color Super SR200 Gen 1', + 156 => 'Konika Konica Color SR-G 160', + 157 => 'Agfa Agfacolor Optima 125', + 158 => 'Agfa Agfacolor Portrait 160', + 162 => 'Kodak Kodacolor VRG 400 Gen 1', + 163 => 'Kodak Gold 200 Gen 1', + 164 => 'Kodak Kodacolor VRG 100 Gen 2', + 174 => 'Kodak Internegative +20% Contrast', + 175 => 'Kodak Internegative +30% Contrast', + 176 => 'Kodak Internegative +40% Contrast', + 184 => 'Kodak TMax-100 D-76 CI = .40', + 185 => 'Kodak TMax-100 D-76 CI = .50', + 186 => 'Kodak TMax-100 D-76 CI = .55', + 187 => 'Kodak TMax-100 D-76 CI = .70', + 188 => 'Kodak TMax-100 D-76 CI = .80', + 189 => 'Kodak TMax-100 TMax CI = .40', + 190 => 'Kodak TMax-100 TMax CI = .50', + 191 => 'Kodak TMax-100 TMax CI = .55', + 192 => 'Kodak TMax-100 TMax CI = .70', + 193 => 'Kodak TMax-100 TMax CI = .80', + 195 => 'Kodak TMax-400 D-76 CI = .40', + 196 => 'Kodak TMax-400 D-76 CI = .50', + 197 => 'Kodak TMax-400 D-76 CI = .55', + 198 => 'Kodak TMax-400 D-76 CI = .70', + 214 => 'Kodak TMax-400 D-76 CI = .80', + 215 => 'Kodak TMax-400 TMax CI = .40', + 216 => 'Kodak TMax-400 TMax CI = .50', + 217 => 'Kodak TMax-400 TMax CI = .55', + 218 => 'Kodak TMax-400 TMax CI = .70', + 219 => 'Kodak TMax-400 TMax CI = .80', + 224 => '3M ScotchColor ATG 400/EXL 400', + 266 => 'Agfa Agfacolor Optima 200', + 267 => 'Konika Impressa 50', + 268 => 'Polaroid Polaroid CP 200', + 269 => 'Konika Konica Color Super SR200 Gen 2', + 270 => 'ILFORD XP2 400', + 271 => 'Polaroid Polaroid Color HD2 100', + 272 => 'Polaroid Polaroid Color HD2 400', + 273 => 'Polaroid Polaroid Color HD2 200', + 282 => '3M ScotchColor ATG-1 200', + 284 => 'Konika XG 400', + 307 => 'Kodak Universal Reversal B/W', + 308 => 'Kodak RPC Copy Film Gen 1', + 312 => 'Kodak Universal E6', + 324 => 'Kodak Gold Ultra 400 Gen 4', + 328 => 'Fuji Super G 100', + 329 => 'Fuji Super G 200', + 330 => 'Fuji Super G 400 Gen 2', + 333 => 'Kodak Universal K14', + 334 => 'Fuji Super G 400 Gen 1', + 366 => 'Kodak Vericolor HC 6329 VHC', + 367 => 'Kodak Vericolor HC 4329 VHC', + 368 => 'Kodak Vericolor L 6013 VPL', + 369 => 'Kodak Vericolor L 4013 VPL', + 418 => 'Kodak Ektacolor Gold II 400 Prof', + 430 => 'Kodak Royal Gold 1000', + 431 => 'Kodak Kodacolor VR 200 / 5093', + 432 => 'Kodak Gold Plus 100 Gen 4', + 443 => 'Kodak Royal Gold 100', + 444 => 'Kodak Royal Gold 400', + 445 => 'Kodak Universal E6 auto-balance', + 446 => 'Kodak Universal E6 illum. corr.', + 447 => 'Kodak Universal K14 auto-balance', + 448 => 'Kodak Universal K14 illum. corr.', + 449 => 'Kodak Ektar 100 Gen 3 SY', + 456 => 'Kodak Ektar 25', + 457 => 'Kodak Ektar 100 Gen 3 CX', + 458 => 'Kodak Ektapress Plus 100 Prof PJA-1', + 459 => 'Kodak Ektapress Gold II 100 Prof', + 460 => 'Kodak Pro 100 PRN', + 461 => 'Kodak Vericolor HC 100 Prof VHC-2', + 462 => 'Kodak Prof Color Neg 100', + 463 => 'Kodak Ektar 1000 Gen 2', + 464 => 'Kodak Ektapress Plus 1600 Pro PJC-1', + 465 => 'Kodak Ektapress Gold II 1600 Prof', + 466 => 'Kodak Super Gold 1600 GF Gen 2', + 467 => 'Kodak Kodacolor 100 Print Gen 4', + 468 => 'Kodak Super Gold 100 Gen 4', + 469 => 'Kodak Gold 100 Gen 4', + 470 => 'Kodak Gold III 100 Gen 4', + 471 => 'Kodak Funtime 100 FA', + 472 => 'Kodak Funtime 200 FB', + 473 => 'Kodak Kodacolor VR 200 Gen 4', + 474 => 'Kodak Gold Super 200 Gen 4', + 475 => 'Kodak Kodacolor 200 Print Gen 4', + 476 => 'Kodak Super Gold 200 Gen 4', + 477 => 'Kodak Gold 200 Gen 4', + 478 => 'Kodak Gold III 200 Gen 4', + 479 => 'Kodak Gold Ultra 400 Gen 5', + 480 => 'Kodak Super Gold 400 Gen 5', + 481 => 'Kodak Gold 400 Gen 5', + 482 => 'Kodak Gold III 400 Gen 5', + 483 => 'Kodak Kodacolor 400 Print Gen 5', + 484 => 'Kodak Ektapress Plus 400 Prof PJB-2', + 485 => 'Kodak Ektapress Gold II 400 Prof G5', + 486 => 'Kodak Pro 400 PPF-2', + 487 => 'Kodak Ektacolor Gold II 400 EGP-4', + 488 => 'Kodak Ektacolor Gold 400 Prof EGP-4', + 489 => 'Kodak Ektapress Gold II Multspd PJM', + 490 => 'Kodak Pro 400 MC PMC', + 491 => 'Kodak Vericolor 400 Prof VPH-2', + 492 => 'Kodak Vericolor 400 Plus Prof VPH-2', + 493 => 'Kodak Unknown Neg Product Code 83', + 505 => 'Kodak Ektacolor Pro Gold 160 GPX', + 508 => 'Kodak Royal Gold 200', + 517 => 'Kodak 4050000000', + 519 => 'Kodak Gold Plus 100 Gen 5', + 520 => 'Kodak Gold 800 Gen 1', + 521 => 'Kodak Gold Super 200 Gen 5', + 522 => 'Kodak Ektapress Plus 200 Prof', + 523 => 'Kodak 4050 E6 auto-balance', + 524 => 'Kodak 4050 E6 ilum. corr.', + 525 => 'Kodak 4050 K14', + 526 => 'Kodak 4050 K14 auto-balance', + 527 => 'Kodak 4050 K14 ilum. corr.', + 528 => 'Kodak 4050 Reversal B&W', + 532 => 'Kodak Advantix 200', + 533 => 'Kodak Advantix 400', + 534 => 'Kodak Advantix 100', + 535 => 'Kodak Ektapress Multspd Prof PJM-2', + 536 => 'Kodak Kodacolor VR 200 Gen 5', + 537 => 'Kodak Funtime 200 FB Gen 2', + 538 => 'Kodak Commercial 200', + 539 => 'Kodak Royal Gold 25 Copystand', + 540 => 'Kodak Kodacolor DA 100 Gen 5', + 545 => 'Kodak Kodacolor VR 400 Gen 2', + 546 => 'Kodak Gold 100 Gen 6', + 547 => 'Kodak Gold 200 Gen 6', + 548 => 'Kodak Gold 400 Gen 6', + 549 => 'Kodak Royal Gold 100 Gen 2', + 550 => 'Kodak Royal Gold 200 Gen 2', + 551 => 'Kodak Royal Gold 400 Gen 2', + 552 => 'Kodak Gold Max 800 Gen 2', + 554 => 'Kodak 4050 E6 high contrast', + 555 => 'Kodak 4050 E6 low saturation high contrast', + 556 => 'Kodak 4050 E6 low saturation', + 557 => 'Kodak Universal E-6 Low Saturation', + 558 => 'Kodak T-Max T400 CN', + 563 => 'Kodak Ektapress PJ100', + 564 => 'Kodak Ektapress PJ400', + 565 => 'Kodak Ektapress PJ800', + 567 => 'Kodak Portra 160NC', + 568 => 'Kodak Portra 160VC', + 569 => 'Kodak Portra 400NC', + 570 => 'Kodak Portra 400VC', + 575 => 'Kodak Advantix 100-2', + 576 => 'Kodak Advantix 200-2', + 577 => 'Kodak Advantix Black & White + 400', + 578 => 'Kodak Ektapress PJ800-2', + }, + }, + 331 => { + Name => 'CopyrightStatus', + Condition => '$$self{HasSBA}', + RawConv => '$$self{CopyrightStatus} = $val', + PrintConv => { + 1 => 'Restrictions apply', + 0xff => 'Not specified', + }, + }, + 332 => { + Name => 'CopyrightFileName', + Condition => '$$self{CopyrightStatus} and $$self{CopyrightStatus} == 1', + Format => 'string[12]', + ValueConv => '$val =~ s/[ \0]+$//; $val', + }, + 1538 => { + Name => 'Orientation', + Mask => 0x03, + RawConv => '$$self{Orient} = $val', + PrintConv => { + 0 => 'Horizontal (normal)', + 1 => 'Rotate 270 CW', + 2 => 'Rotate 180', + 3 => 'Rotate 90 CW', + }, + }, + 1538.1 => { + Name => 'ImageWidth', + Mask => 0x0c, + # 0=Base (768x512), 1=4Base (1536x1024), 2=16Base (3072x2048) + ValueConv => '($$self{Orient} & 0x01 ? 512 : 768) * ($val * 2 || 1)', + }, + 1538.2 => { + Name => 'ImageHeight', + Mask => 0x0c, + ValueConv => '($$self{Orient} & 0x01 ? 768 : 512) * ($val * 2 || 1)', + }, + 1538.3 => { + Name => 'CompressionClass', + Mask => 0x60, + PrintConv => { + 0 => 'Class 1 - 35mm film; Pictoral hard copy', + 1 => 'Class 2 - Large format film', + 2 => 'Class 3 - Text and graphics, high resolution', + 3 => 'Class 4 - Text and graphics, high dynamic range', + }, + }, + #1544 => 'InterleaveRatio', + #1545 => 'ADPCMResolution', + #1546 => { + # Name => 'ADPCMMagnificationPanning', + # Format => 'int8u[2]', + #}, + #1548 => 'ADPCMMagnificationFactor', + #1549 => { + # Name => 'ADPCMDisplayOffset', + # Format => 'int8u[2]', + #}, + #1551 => 'ADPCMTransitionDescriptor', +); + +#------------------------------------------------------------------------------ +# Extract information from a PhotoCD image +# Inputs: 0) ExifTool object reference, 1) dirInfo reference +# Returns: 1 on success, 0 if this wasn't a valid PhotoCD file +sub ProcessPCD($$) +{ + my ($et, $dirInfo) = @_; + my $raf = $$dirInfo{RAF}; + my $buff; + return 0 unless $raf->Seek(2048, 0) and + $raf->Read($buff, 2048) == 2048 and + $buff =~ /^PCD_IPI/; + SetByteOrder('MM'); + $et->SetFileType(); + my %dirInfo = ( + DirName => 'PhotoCD', + DataPt => \$buff, + DataPos => 4096, + ); + my $tagTablePtr = GetTagTable('Image::ExifTool::PhotoCD::Main'); + return $et->ProcessBinaryData(\%dirInfo, $tagTablePtr); +} + +1; # end + +__END__ + +=head1 NAME + +Image::ExifTool::PhotoCD - Read Kodak Photo CD Image Pac (PCD) metadata + +=head1 SYNOPSIS + +This module is used by Image::ExifTool + +=head1 DESCRIPTION + +This module contains routines required by Image::ExifTool to extract +information from Kodak Photo CD Image Pac (PCD) files. + +=head1 AUTHOR + +Copyright 2003-2019, Phil Harvey (phil at owl.phy.queensu.ca) + +This library is free software; you can redistribute it and/or modify it +under the same terms as Perl itself. + +=head1 REFERENCES + +=over 4 + +=item L<http://pcdtojpeg.sourceforge.net/> + +=back + +=head1 SEE ALSO + +L<Image::ExifTool::TagNames/PhotoCD Tags>, +L<Image::ExifTool(3pm)|Image::ExifTool> + +=cut + diff --git a/lib/Image/ExifTool/PhotoMechanic.pm b/lib/Image/ExifTool/PhotoMechanic.pm new file mode 100644 index 0000000..85c7dba --- /dev/null +++ b/lib/Image/ExifTool/PhotoMechanic.pm @@ -0,0 +1,256 @@ +#------------------------------------------------------------------------------ +# File: PhotoMechanic.pm +# +# Description: Read/write Camera Bits Photo Mechanic information +# +# Revisions: 10/28/2006 - P. Harvey Created +#------------------------------------------------------------------------------ + +package Image::ExifTool::PhotoMechanic; + +use strict; +use vars qw($VERSION); +use Image::ExifTool qw(:DataAccess :Utils); +use Image::ExifTool::Exif; +use Image::ExifTool::IPTC; +use Image::ExifTool::XMP; + +$VERSION = '1.05'; + +sub ProcessPhotoMechanic($$); + +# color class names +my %colorClasses = ( + 0 => '0 (None)', + 1 => '1 (Winner)', + 2 => '2 (Winner alt)', + 3 => '3 (Superior)', + 4 => '4 (Superior alt)', + 5 => '5 (Typical)', + 6 => '6 (Typical alt)', + 7 => '7 (Extras)', + 8 => '8 (Trash)', +); + +# main tag table IPTC-format records in PhotoMechanic trailer +%Image::ExifTool::PhotoMechanic::Main = ( + GROUPS => { 2 => 'Image' }, + PROCESS_PROC => \&Image::ExifTool::IPTC::ProcessIPTC, + WRITE_PROC => \&Image::ExifTool::IPTC::WriteIPTC, + NOTES => q{ + The Photo Mechanic trailer contains data in an IPTC-format structure, with + soft edit information stored under record number 2. + }, + 2 => { + Name => 'SoftEdit', + SubDirectory => { + TagTable => 'Image::ExifTool::PhotoMechanic::SoftEdit', + }, + }, +); + +# raw/preview crop coordinate conversions +my %rawCropConv = ( + ValueConv => '$val / 655.36', + ValueConvInv => 'int($val * 655.36 + 0.5)', + PrintConv => 'sprintf("%.3f%%",$val)', + PrintConvInv => '$val=~tr/ %//d; $val', +); + +# Record 2 -- PhotoMechanic soft edit information +%Image::ExifTool::PhotoMechanic::SoftEdit = ( + GROUPS => { 2 => 'Image' }, + WRITE_PROC => \&Image::ExifTool::IPTC::WriteIPTC, + CHECK_PROC => \&Image::ExifTool::IPTC::CheckIPTC, + WRITABLE => 1, + FORMAT => 'int32s', + 209 => { Name => 'RawCropLeft', %rawCropConv }, + 210 => { Name => 'RawCropTop', %rawCropConv }, + 211 => { Name => 'RawCropRight', %rawCropConv }, + 212 => { Name => 'RawCropBottom', %rawCropConv }, + 213 => 'ConstrainedCropWidth', + 214 => 'ConstrainedCropHeight', + 215 => 'FrameNum', + 216 => { + Name => 'Rotation', + PrintConv => { + 0 => '0', + 1 => '90', + 2 => '180', + 3 => '270', + }, + }, + 217 => 'CropLeft', + 218 => 'CropTop', + 219 => 'CropRight', + 220 => 'CropBottom', + 221 => { + Name => 'Tagged', + PrintConv => { 0 => 'No', 1 => 'Yes' }, + }, + 222 => { + Name => 'ColorClass', + PrintConv => \%colorClasses, + }, + 223 => 'Rating', + 236 => { Name => 'PreviewCropLeft', %rawCropConv }, + 237 => { Name => 'PreviewCropTop', %rawCropConv }, + 238 => { Name => 'PreviewCropRight', %rawCropConv }, + 239 => { Name => 'PreviewCropBottom', %rawCropConv }, +); + +# PhotoMechanic XMP properties +%Image::ExifTool::PhotoMechanic::XMP = ( + GROUPS => { 0 => 'XMP', 1 => 'XMP-photomech', 2 => 'Image' }, + NAMESPACE => { photomechanic => 'http://ns.camerabits.com/photomechanic/1.0/' }, + WRITE_PROC => \&Image::ExifTool::XMP::WriteXMP, + WRITABLE => 'string', + NOTES => q{ + Below is a list of the observed PhotoMechanic XMP tags. The actual + namespace prefix is "photomechanic" but ExifTool shortens this in + the family 1 group name. + }, + ColorClass => { + Writable => 'integer', + PrintConv => \%colorClasses, + }, + CountryCode => { Avoid => 1, Groups => { 2 => 'Location' } }, + EditStatus => { }, + PMVersion => { }, + Prefs => { + Notes => 'format is "Tagged:0, ColorClass:1, Rating:2, FrameNum:3"', + PrintConv => q{ + $val =~ s[\s*(\d+):\s*(\d+):\s*(\d+):\s*(\S*)] + [Tagged:$1, ColorClass:$2, Rating:$3, FrameNum:$4]; + return $val; + }, + PrintConvInv => q{ + $val =~ s[Tagged:\s*(\d+).*ColorClass:\s*(\d+).*Rating:\s*(\d+).*FrameNum:\s*(\S*)] + [$1:$2:$3:$4]is; + return $val; + }, + }, + Tagged => { Writable => 'boolean', PrintConv => { False => 'No', True => 'Yes' } }, + TimeCreated => { + Avoid => 1, + Groups => { 2 => 'Time' }, + Shift => 'Time', + ValueConv => 'Image::ExifTool::Exif::ExifTime($val)', + ValueConvInv => 'Image::ExifTool::IPTC::IptcTime($val)', + }, +); + +#------------------------------------------------------------------------------ +# Read/write PhotoMechanic information in a file +# Inputs: 0) ExifTool object reference, 1) dirInfo reference +# Returns: 1 on success, 0 if this file didn't contain PhotoMechanic information +# - updates DataPos to point to start of PhotoMechanic information +# - updates DirLen to trailer length +sub ProcessPhotoMechanic($$) +{ + my ($et, $dirInfo) = @_; + my $raf = $$dirInfo{RAF}; + my $offset = $$dirInfo{Offset} || 0; + my $outfile = $$dirInfo{OutFile}; + my $verbose = $et->Options('Verbose'); + my $out = $et->Options('TextOut'); + my $rtnVal = 0; + my ($buff, $footer); + + for (;;) { + # read and validate trailer footer (last 12 bytes) + last unless $raf->Seek(-12-$offset, 2) and $raf->Read($footer, 12) == 12; + last unless $footer =~ /cbipcbbl$/; + my $size = unpack('N', $footer); + + if ($size & 0x80000000 or not $raf->Seek(-$size-12, 1)) { + $et->Warn('Bad PhotoMechanic trailer'); + last; + } + unless ($raf->Read($buff, $size) == $size) { + $et->Warn('Error reading PhotoMechanic trailer'); + last; + } + $rtnVal = 1; # we read the trailer successfully + + # set variables returned in dirInfo hash + $$dirInfo{DataPos} = $raf->Tell() - $size; + $$dirInfo{DirLen} = $size + 12; + + my %dirInfo = ( + DataPt => \$buff, + DataPos => $$dirInfo{DataPos}, + DirStart => 0, + DirLen => $size, + Parent => 'PhotoMechanic', + ); + my $tagTablePtr = GetTagTable('Image::ExifTool::PhotoMechanic::Main'); + if (not $outfile) { + # extract trailer information + $et->DumpTrailer($dirInfo) if $verbose or $$et{HTML_DUMP}; + $et->ProcessDirectory(\%dirInfo, $tagTablePtr); + } elsif ($$et{DEL_GROUP}{PhotoMechanic}) { + # delete the trailer + $verbose and print $out " Deleting PhotoMechanic trailer\n"; + ++$$et{CHANGED}; + } else { + # rewrite the trailer + my $newPt; + my $newBuff = $et->WriteDirectory(\%dirInfo, $tagTablePtr); + if (defined $newBuff) { + $newPt = \$newBuff; # write out the modified trailer + my $pad = 0x800 - length($newBuff); + if ($pad > 0 and not $et->Options('Compact')) { + # pad out to 2kB like PhotoMechanic does + $newBuff .= "\0" x $pad; + } + # generate new footer + $footer = pack('N', length($$newPt)) . 'cbipcbbl'; + } else { + $newPt = \$buff; # just copy existing trailer + } + # write out the trailer + Write($outfile, $$newPt, $footer) or $rtnVal = -1; + } + last; + } + return $rtnVal; +} + +1; # end + +__END__ + +=head1 NAME + +Image::ExifTool::PhotoMechanic - Read/write Photo Mechanic information + +=head1 SYNOPSIS + +This module is used by Image::ExifTool + +=head1 DESCRIPTION + +This module contains definitions required by Image::ExifTool to read and +write information written by the Camera Bits Photo Mechanic software. + +=head1 AUTHOR + +Copyright 2003-2019, Phil Harvey (phil at owl.phy.queensu.ca) + +This library is free software; you can redistribute it and/or modify it +under the same terms as Perl itself. + +=head1 ACKNOWLEDGEMENTS + +Many thanks to the great support provided by Camera Bits, and in particular +for the valuable exchanges with Kirk Baker. Based on this experience, I can +say that the technical support offered by Camera Bits is second to none. + +=head1 SEE ALSO + +L<Image::ExifTool::TagNames/PhotoMechanic Tags>, +L<Image::ExifTool(3pm)|Image::ExifTool> + +=cut + diff --git a/lib/Image/ExifTool/Photoshop.pm b/lib/Image/ExifTool/Photoshop.pm new file mode 100644 index 0000000..3156db2 --- /dev/null +++ b/lib/Image/ExifTool/Photoshop.pm @@ -0,0 +1,1157 @@ +#------------------------------------------------------------------------------ +# File: Photoshop.pm +# +# Description: Read/write Photoshop IRB meta information +# +# Revisions: 02/06/2004 - P. Harvey Created +# 02/25/2004 - P. Harvey Added hack for problem with old photoshops +# 10/04/2004 - P. Harvey Added a bunch of tags (ref Image::MetaData::JPEG) +# but left most of them commented out until I have enough +# information to write PrintConv routines for them to +# display something useful +# 07/08/2005 - P. Harvey Added support for reading PSD files +# 01/07/2006 - P. Harvey Added PSD write support +# 11/04/2006 - P. Harvey Added handling of resource name +# +# References: 1) http://www.fine-view.com/jp/lab/doc/ps6ffspecsv2.pdf +# 2) http://www.ozhiker.com/electronics/pjmt/jpeg_info/irb_jpeg_qual.html +# 3) Matt Mueller private communication (tests with PS CS2) +# 4) http://www.fileformat.info/format/psd/egff.htm +# 5) http://www.telegraphics.com.au/svn/psdparse/trunk/resources.c +# 6) http://libpsd.graphest.com/files/Photoshop%20File%20Formats.pdf +# 7) http://www.adobe.com/devnet-apps/photoshop/fileformatashtml/ +#------------------------------------------------------------------------------ + +package Image::ExifTool::Photoshop; + +use strict; +use vars qw($VERSION $AUTOLOAD $iptcDigestInfo); +use Image::ExifTool qw(:DataAccess :Utils); + +$VERSION = '1.63'; + +sub ProcessPhotoshop($$$); +sub WritePhotoshop($$$); +sub ProcessLayers($$$); + +# map of where information is stored in PSD image +my %psdMap = ( + IPTC => 'Photoshop', + XMP => 'Photoshop', + EXIFInfo => 'Photoshop', + IFD0 => 'EXIFInfo', + IFD1 => 'IFD0', + ICC_Profile => 'Photoshop', + ExifIFD => 'IFD0', + GPS => 'IFD0', + SubIFD => 'IFD0', + GlobParamIFD => 'IFD0', + PrintIM => 'IFD0', + InteropIFD => 'ExifIFD', + MakerNotes => 'ExifIFD', +); + +# tag information for PhotoshopThumbnail and PhotoshopBGRThumbnail +my %thumbnailInfo = ( + Writable => 'undef', + Protected => 1, + RawConv => 'my $img=substr($val,0x1c); $self->ValidateImage(\$img,$tag)', + ValueConvInv => q{ + my $et = new Image::ExifTool; + my @tags = qw{ImageWidth ImageHeight FileType}; + my $info = $et->ImageInfo(\$val, @tags); + my ($w, $h, $type) = @$info{@tags}; + $w and $h and $type eq 'JPEG' or warn("Not a valid JPEG image\n"), return undef; + my $wbytes = int(($w * 24 + 31) / 32) * 4; + return pack('N6n2', 1, $w, $h, $wbytes, $wbytes * $h, length($val), 24, 1) . $val; + }, +); + +# tag info to decode Photoshop Unicode string +my %unicodeString = ( + ValueConv => sub { + my ($val, $et) = @_; + return '<err>' if length($val) < 4; + my $len = unpack('N', $val) * 2; + return '<err>' if length($val) < 4 + $len; + return $et->Decode(substr($val, 4, $len), 'UCS2', 'MM'); + }, + ValueConvInv => sub { + my ($val, $et) = @_; + return pack('N', length $val) . $et->Encode($val, 'UCS2', 'MM'); + }, +); + +# Photoshop APP13 tag table +# (set Unknown flag for information we don't want to display normally) +%Image::ExifTool::Photoshop::Main = ( + GROUPS => { 2 => 'Image' }, + PROCESS_PROC => \&ProcessPhotoshop, + WRITE_PROC => \&WritePhotoshop, + 0x03e8 => { Unknown => 1, Name => 'Photoshop2Info' }, + 0x03e9 => { Unknown => 1, Name => 'MacintoshPrintInfo' }, + 0x03ea => { Unknown => 1, Name => 'XMLData', Binary => 1 }, #PH + 0x03eb => { Unknown => 1, Name => 'Photoshop2ColorTable' }, + 0x03ed => { + Name => 'ResolutionInfo', + SubDirectory => { + TagTable => 'Image::ExifTool::Photoshop::Resolution', + }, + }, + 0x03ee => { + Name => 'AlphaChannelsNames', + ValueConv => 'Image::ExifTool::Photoshop::ConvertPascalString($self,$val)', + }, + 0x03ef => { Unknown => 1, Name => 'DisplayInfo' }, + 0x03f0 => { Unknown => 1, Name => 'PStringCaption' }, + 0x03f1 => { Unknown => 1, Name => 'BorderInformation' }, + 0x03f2 => { Unknown => 1, Name => 'BackgroundColor' }, + 0x03f3 => { Unknown => 1, Name => 'PrintFlags', Format => 'int8u' }, + 0x03f4 => { Unknown => 1, Name => 'BW_HalftoningInfo' }, + 0x03f5 => { Unknown => 1, Name => 'ColorHalftoningInfo' }, + 0x03f6 => { Unknown => 1, Name => 'DuotoneHalftoningInfo' }, + 0x03f7 => { Unknown => 1, Name => 'BW_TransferFunc' }, + 0x03f8 => { Unknown => 1, Name => 'ColorTransferFuncs' }, + 0x03f9 => { Unknown => 1, Name => 'DuotoneTransferFuncs' }, + 0x03fa => { Unknown => 1, Name => 'DuotoneImageInfo' }, + 0x03fb => { Unknown => 1, Name => 'EffectiveBW', Format => 'int8u' }, + 0x03fc => { Unknown => 1, Name => 'ObsoletePhotoshopTag1' }, + 0x03fd => { Unknown => 1, Name => 'EPSOptions' }, + 0x03fe => { Unknown => 1, Name => 'QuickMaskInfo' }, + 0x03ff => { Unknown => 1, Name => 'ObsoletePhotoshopTag2' }, + 0x0400 => { Unknown => 1, Name => 'TargetLayerID', Format => 'int16u' }, # (LayerStateInfo) + 0x0401 => { Unknown => 1, Name => 'WorkingPath' }, + 0x0402 => { Unknown => 1, Name => 'LayersGroupInfo', Format => 'int16u' }, + 0x0403 => { Unknown => 1, Name => 'ObsoletePhotoshopTag3' }, + 0x0404 => { + Name => 'IPTCData', + SubDirectory => { + DirName => 'IPTC', + TagTable => 'Image::ExifTool::IPTC::Main', + }, + }, + 0x0405 => { Unknown => 1, Name => 'RawImageMode' }, + 0x0406 => { #2 + Name => 'JPEG_Quality', + SubDirectory => { + TagTable => 'Image::ExifTool::Photoshop::JPEG_Quality', + }, + }, + 0x0408 => { Unknown => 1, Name => 'GridGuidesInfo' }, + 0x0409 => { + Name => 'PhotoshopBGRThumbnail', + Notes => 'this is a JPEG image, but in BGR format instead of RGB', + %thumbnailInfo, + Groups => { 2 => 'Preview' }, + }, + 0x040a => { + Name => 'CopyrightFlag', + Writable => 'int8u', + Groups => { 2 => 'Author' }, + ValueConv => 'join(" ",unpack("C*", $val))', + ValueConvInv => 'pack("C*",split(" ",$val))', + PrintConv => { #3 + 0 => 'False', + 1 => 'True', + }, + }, + 0x040b => { + Name => 'URL', + Writable => 'string', + Groups => { 2 => 'Author' }, + }, + 0x040c => { + Name => 'PhotoshopThumbnail', + %thumbnailInfo, + Groups => { 2 => 'Preview' }, + }, + 0x040d => { + Name => 'GlobalAngle', + Writable => 'int32u', + ValueConv => 'unpack("N",$val)', + ValueConvInv => 'pack("N",$val)', + }, + 0x040e => { Unknown => 1, Name => 'ColorSamplersResource' }, + 0x040f => { + Name => 'ICC_Profile', + SubDirectory => { + TagTable => 'Image::ExifTool::ICC_Profile::Main', + }, + }, + 0x0410 => { Unknown => 1, Name => 'Watermark', Format => 'int8u' }, + 0x0411 => { Unknown => 1, Name => 'ICC_Untagged', Format => 'int8u' }, + 0x0412 => { Unknown => 1, Name => 'EffectsVisible', Format => 'int8u' }, + 0x0413 => { Unknown => 1, Name => 'SpotHalftone' }, + 0x0414 => { Unknown => 1, Name => 'IDsBaseValue', Description => 'IDs Base Value', Format => 'int32u' }, + 0x0415 => { Unknown => 1, Name => 'UnicodeAlphaNames' }, + 0x0416 => { Unknown => 1, Name => 'IndexedColorTableCount', Format => 'int16u' }, + 0x0417 => { Unknown => 1, Name => 'TransparentIndex', Format => 'int16u' }, + 0x0419 => { + Name => 'GlobalAltitude', + Writable => 'int32u', + ValueConv => 'unpack("N",$val)', + ValueConvInv => 'pack("N",$val)', + }, + 0x041a => { + Name => 'SliceInfo', + SubDirectory => { TagTable => 'Image::ExifTool::Photoshop::SliceInfo' }, + }, + 0x041b => { Name => 'WorkflowURL', %unicodeString }, + 0x041c => { Unknown => 1, Name => 'JumpToXPEP' }, + 0x041d => { Unknown => 1, Name => 'AlphaIdentifiers' }, + 0x041e => { + Name => 'URL_List', + List => 1, + Writable => 1, + ValueConv => sub { + my ($val, $et) = @_; + return '<err>' if length($val) < 4; + my $num = unpack('N', $val); + my ($i, @vals); + my $pos = 4; + for ($i=0; $i<$num; ++$i) { + $pos += 8; # (skip word and ID) + last if length($val) < $pos + 4; + my $len = unpack("x${pos}N", $val) * 2; + last if length($val) < $pos + 4 + $len; + push @vals, $et->Decode(substr($val,$pos+4,$len), 'UCS2', 'MM'); + $pos += 4 + $len; + } + return \@vals; + }, + # (this is tricky to make writable) + }, + 0x0421 => { + Name => 'VersionInfo', + SubDirectory => { + TagTable => 'Image::ExifTool::Photoshop::VersionInfo', + }, + }, + 0x0422 => { + Name => 'EXIFInfo', #PH (Found in EPS and PSD files) + SubDirectory => { + TagTable=> 'Image::ExifTool::Exif::Main', + ProcessProc => \&Image::ExifTool::ProcessTIFF, + WriteProc => \&Image::ExifTool::WriteTIFF, + }, + }, + 0x0423 => { Unknown => 1, Name => 'ExifInfo2', Binary => 1 }, #5 + 0x0424 => { + Name => 'XMP', + SubDirectory => { + TagTable => 'Image::ExifTool::XMP::Main', + }, + }, + 0x0425 => { + Name => 'IPTCDigest', + Writable => 'string', + Protected => 1, + Notes => q{ + this tag indicates provides a way for XMP-aware applications to indicate + that the XMP is synchronized with the IPTC. When writing, special values of + "new" and "old" represent the digests of the IPTC from the edited and + original files respectively, and are undefined if the IPTC does not exist in + the respective file. Set this to "new" as an indication that the XMP is + synchronized with the IPTC + }, + # also note the 'new' feature requires that the IPTC comes before this tag is written + ValueConv => 'unpack("H*", $val)', + ValueConvInv => q{ + if (lc($val) eq 'new' or lc($val) eq 'old') { + { + local $SIG{'__WARN__'} = sub { }; + return lc($val) if eval { require Digest::MD5 }; + } + warn "Digest::MD5 must be installed\n"; + return undef; + } + return pack('H*', $val) if $val =~ /^[0-9a-f]{32}$/i; + warn "Value must be 'new', 'old' or 32 hexadecimal digits\n"; + return undef; + } + }, + 0x0426 => { + Name => 'PrintScaleInfo', + SubDirectory => { TagTable => 'Image::ExifTool::Photoshop::PrintScaleInfo' }, + }, + 0x0428 => { + Name => 'PixelInfo', + SubDirectory => { TagTable => 'Image::ExifTool::Photoshop::PixelInfo' }, + }, + 0x0429 => { Unknown => 1, Name => 'LayerComps' }, #5 + 0x042a => { Unknown => 1, Name => 'AlternateDuotoneColors' }, #5 + 0x042b => { Unknown => 1, Name => 'AlternateSpotColors' }, #5 + 0x042d => { #7 + Name => 'LayerSelectionIDs', + Description => 'Layer Selection IDs', + Unknown => 1, + ValueConv => q{ + my ($n, @a) = unpack("nN*",$val); + $#a = $n - 1 if $n > @a; + return join(' ', @a); + }, + }, + 0x042e => { Unknown => 1, Name => 'HDRToningInfo' }, #7 + 0x042f => { Unknown => 1, Name => 'PrintInfo' }, #7 + 0x0430 => { Unknown => 1, Name => 'LayerGroupsEnabledID', Format => 'int8u' }, #7 + 0x0431 => { Unknown => 1, Name => 'ColorSamplersResource2' }, #7 + 0x0432 => { Unknown => 1, Name => 'MeasurementScale' }, #7 + 0x0433 => { Unknown => 1, Name => 'TimelineInfo' }, #7 + 0x0434 => { Unknown => 1, Name => 'SheetDisclosure' }, #7 + 0x0435 => { Unknown => 1, Name => 'DisplayInfo' }, #7 + 0x0436 => { Unknown => 1, Name => 'OnionSkins' }, #7 + 0x0438 => { Unknown => 1, Name => 'CountInfo' }, #7 + 0x043a => { Unknown => 1, Name => 'PrintInfo2' }, #7 + 0x043b => { Unknown => 1, Name => 'PrintStyle' }, #7 + 0x043c => { Unknown => 1, Name => 'MacintoshNSPrintInfo' }, #7 + 0x043d => { Unknown => 1, Name => 'WindowsDEVMODE' }, #7 + 0x043e => { Unknown => 1, Name => 'AutoSaveFilePath' }, #7 + 0x043f => { Unknown => 1, Name => 'AutoSaveFormat' }, #7 + 0x0440 => { Unknown => 1, Name => 'PathSelectionState' }, #7 + # 0x07d0-0x0bb6 Path information + 0x0bb7 => { + Name => 'ClippingPathName', + # convert from a Pascal string (ignoring 6 bytes of unknown data after string) + ValueConv => q{ + my $len = ord($val); + $val = substr($val, 0, $len+1) if $len < length($val); + return Image::ExifTool::Photoshop::ConvertPascalString($self,$val); + }, + }, + 0x0bb8 => { Unknown => 1, Name => 'OriginPathInfo' }, #7 + # 0x0fa0-0x1387 - plug-in resources (ref 7) + 0x1b58 => { Unknown => 1, Name => 'ImageReadyVariables' }, #7 + 0x1b59 => { Unknown => 1, Name => 'ImageReadyDataSets' }, #7 + 0x1f40 => { Unknown => 1, Name => 'LightroomWorkflow' }, #7 + 0x2710 => { Unknown => 1, Name => 'PrintFlagsInfo' }, +); + +# Photoshop JPEG quality record (ref 2) +%Image::ExifTool::Photoshop::JPEG_Quality = ( + PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData, + WRITE_PROC => \&Image::ExifTool::WriteBinaryData, + CHECK_PROC => \&Image::ExifTool::CheckBinaryData, + FORMAT => 'int16s', + GROUPS => { 2 => 'Image' }, + 0 => { + Name => 'PhotoshopQuality', + Writable => 1, + PrintConv => '$val + 4', + PrintConvInv => '$val - 4', + }, + 1 => { + Name => 'PhotoshopFormat', + PrintConv => { + 0x0000 => 'Standard', + 0x0001 => 'Optimized', + 0x0101 => 'Progressive', + }, + }, + 2 => { + Name => 'ProgressiveScans', + PrintConv => { + 1 => '3 Scans', + 2 => '4 Scans', + 3 => '5 Scans', + }, + }, +); + +# Photoshop Slices +%Image::ExifTool::Photoshop::SliceInfo = ( + PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData, + 20 => { Name => 'SlicesGroupName', Format => 'var_ustr32' }, + 24 => { Name => 'NumSlices', Format => 'int32u' }, +); + +# Photoshop resolution information #PH +%Image::ExifTool::Photoshop::Resolution = ( + PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData, + WRITE_PROC => \&Image::ExifTool::WriteBinaryData, + CHECK_PROC => \&Image::ExifTool::CheckBinaryData, + FORMAT => 'int16u', + FIRST_ENTRY => 0, + WRITABLE => 1, + GROUPS => { 2 => 'Image' }, + 0 => { + Name => 'XResolution', + Format => 'int32u', + Priority => 0, + ValueConv => '$val / 0x10000', + ValueConvInv => 'int($val * 0x10000 + 0.5)', + PrintConv => 'int($val * 100 + 0.5) / 100', + PrintConvInv => '$val', + }, + 2 => { + Name => 'DisplayedUnitsX', + PrintConv => { + 1 => 'inches', + 2 => 'cm', + }, + }, + 4 => { + Name => 'YResolution', + Format => 'int32u', + Priority => 0, + ValueConv => '$val / 0x10000', + ValueConvInv => 'int($val * 0x10000 + 0.5)', + PrintConv => 'int($val * 100 + 0.5) / 100', + PrintConvInv => '$val', + }, + 6 => { + Name => 'DisplayedUnitsY', + PrintConv => { + 1 => 'inches', + 2 => 'cm', + }, + }, +); + +# Photoshop version information +%Image::ExifTool::Photoshop::VersionInfo = ( + PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData, + WRITE_PROC => \&Image::ExifTool::WriteBinaryData, + CHECK_PROC => \&Image::ExifTool::CheckBinaryData, + FIRST_ENTRY => 0, + GROUPS => { 2 => 'Image' }, + # (always 1) 0 => { Name => 'PhotoshopVersion', Format => 'int32u' }, + 4 => { Name => 'HasRealMergedData', Format => 'int8u', PrintConv => { 0 => 'No', 1 => 'Yes' } }, + 5 => { Name => 'WriterName', Format => 'var_ustr32' }, + 9 => { Name => 'ReaderName', Format => 'var_ustr32' }, + # (always 1) 13 => { Name => 'FileVersion', Format => 'int32u' }, +); + +# Print Scale +%Image::ExifTool::Photoshop::PrintScaleInfo = ( + PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData, + WRITE_PROC => \&Image::ExifTool::WriteBinaryData, + CHECK_PROC => \&Image::ExifTool::CheckBinaryData, + FIRST_ENTRY => 0, + GROUPS => { 2 => 'Image' }, + 0 => { + Name => 'PrintStyle', + Format => 'int16u', + PrintConv => { + 0 => 'Centered', + 1 => 'Size to Fit', + 2 => 'User Defined', + }, + }, + 2 => { Name => 'PrintPosition', Format => 'float[2]' }, + 10 => { Name => 'PrintScale', Format => 'float' }, +); + +# Pixel Aspect Ratio +%Image::ExifTool::Photoshop::PixelInfo = ( + PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData, + WRITE_PROC => \&Image::ExifTool::WriteBinaryData, + CHECK_PROC => \&Image::ExifTool::CheckBinaryData, + FIRST_ENTRY => 0, + GROUPS => { 2 => 'Image' }, + # 0 - version + 4 => { Name => 'PixelAspectRatio', Format => 'double' }, +); + +# Photoshop PSD file header +%Image::ExifTool::Photoshop::Header = ( + PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData, + FORMAT => 'int16u', + GROUPS => { 2 => 'Image' }, + NOTES => 'This information is found in the PSD file header.', + 6 => 'NumChannels', + 7 => { Name => 'ImageHeight', Format => 'int32u' }, + 9 => { Name => 'ImageWidth', Format => 'int32u' }, + 11 => 'BitDepth', + 12 => { + Name => 'ColorMode', + PrintConvColumns => 2, + PrintConv => { + 0 => 'Bitmap', + 1 => 'Grayscale', + 2 => 'Indexed', + 3 => 'RGB', + 4 => 'CMYK', + 7 => 'Multichannel', + 8 => 'Duotone', + 9 => 'Lab', + }, + }, +); + +# Layer information +%Image::ExifTool::Photoshop::Layers = ( + PROCESS_PROC => \&ProcessLayers, + GROUPS => { 2 => 'Image' }, + NOTES => 'Tags extracted from Photoshop layer information.', + # tags extracted from layer information + # (tag ID's are for convenience only) + _xcnt => { Name => 'LayerCount', Format => 'int16u' }, + _xrct => { + Name => 'LayerRectangles', + Format => 'int32u', + Count => 4, + List => 1, + Notes => 'top left bottom right', + }, + _xnam => { Name => 'LayerNames', + Format => 'string', + List => 1, + ValueConv => q{ + my $charset = $self->Options('CharsetPhotoshop') || 'Latin'; + return $self->Decode($val, $charset); + }, + }, + _xbnd => { + Name => 'LayerBlendModes', + Format => 'undef', + List => 1, + RawConv => 'GetByteOrder() eq "II" ? pack "N*", unpack "V*", $val : $val', + PrintConv => { + pass => 'Pass Through', + norm => 'Normal', + diss => 'Dissolve', + dark => 'Darken', + 'mul '=> 'Multiply', + idiv => 'Color Burn', + lbrn => 'Linear Burn', + dkCl => 'Darker Color', + lite => 'Lighten', + scrn => 'Screen', + 'div '=> 'Color Dodge', + lddg => 'Linear Dodge', + lgCl => 'Lighter Color', + over => 'Overlay', + sLit => 'Soft Light', + hLit => 'Hard Light', + vLit => 'Vivid Light', + lLit => 'Linear Light', + pLit => 'Pin Light', + hMix => 'Hard Mix', + diff => 'Difference', + smud => 'Exclusion', + fsub => 'Subtract', + fdiv => 'Divide', + 'hue '=> 'Hue', + 'sat '=> 'Saturation', + colr => 'Color', + 'lum '=> 'Luminosity', + }, + }, + _xopc => { + Name => 'LayerOpacities', + Format => 'int8u', + List => 1, + ValueConv => '100 * $val / 255', + PrintConv => 'sprintf("%d%%",$val)', + }, + # tags extracted from additional layer information (tag ID's are real) + # - must be able to accomodate a blank entry to preserve the list ordering + luni => { + Name => 'LayerUnicodeNames', + List => 1, + RawConv => q{ + return '' if length($val) < 4; + my $len = Get32u(\$val, 0); + return $self->Decode(substr($val, 4, $len * 2), 'UCS2'); + }, + }, + lyid => { + Name => 'LayerIDs', + Description => 'Layer IDs', + Format => 'int32u', + List => 1, + Unknown => 1, + }, + shmd => { # layer metadata (undocumented structure) + # (for now, only extract layerTime. May also contain "layerXMP" -- + # it would be nice to decode this but I need a sample) + Name => 'LayerModifyDates', + Groups => { 2 => 'Time' }, + List => 1, + RawConv => q{ + return '' unless $val =~ /layerTime(doub|buod)(.{8})/s; + my $tmp = $2; + return GetDouble(\$tmp, 0); + }, + ValueConv => 'length $val ? ConvertUnixTime($val,1) : ""', + PrintConv => 'length $val ? $self->ConvertDateTime($val) : ""', + }, +); + +# tags extracted from ImageSourceData found in TIFF images (ref PH) +%Image::ExifTool::Photoshop::DocumentData = ( + PROCESS_PROC => \&ProcessDocumentData, + GROUPS => { 2 => 'Image' }, + Layr => { + Name => 'Layers', + SubDirectory => { TagTable => 'Image::ExifTool::Photoshop::Layers' }, + }, + Lr16 => { # (NC) + Name => 'Layers', + SubDirectory => { TagTable => 'Image::ExifTool::Photoshop::Layers' }, + }, +); + +# image data +%Image::ExifTool::Photoshop::ImageData = ( + PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData, + GROUPS => { 2 => 'Image' }, + 0 => { + Name => 'Compression', + Format => 'int16u', + PrintConv => { + 0 => 'Uncompressed', + 1 => 'RLE', + 2 => 'ZIP without prediction', + 3 => 'ZIP with prediction', + }, + }, +); + +# tags for unknown resource types +%Image::ExifTool::Photoshop::Unknown = ( + GROUPS => { 2 => 'Unknown' }, +); + +# define reference to IPTCDigest tagInfo hash for convenience +$iptcDigestInfo = $Image::ExifTool::Photoshop::Main{0x0425}; + + +#------------------------------------------------------------------------------ +# AutoLoad our writer routines when necessary +# +sub AUTOLOAD +{ + return Image::ExifTool::DoAutoLoad($AUTOLOAD, @_); +} + +#------------------------------------------------------------------------------ +# Convert pascal string(s) to something we can use +# Inputs: 1) Pascal string data +# Returns: Strings, concatenated with ', ' +sub ConvertPascalString($$) +{ + my ($et, $inStr) = @_; + my $outStr = ''; + my $len = length($inStr); + my $i=0; + while ($i < $len) { + my $n = ord(substr($inStr, $i, 1)); + last if $i + $n >= $len; + $i and $outStr .= ', '; + $outStr .= substr($inStr, $i+1, $n); + $i += $n + 1; + } + my $charset = $et->Options('CharsetPhotoshop') || 'Latin'; + return $et->Decode($outStr, $charset); +} + +#------------------------------------------------------------------------------ +# Process Photoshop layers and mask information section of PSD/PSB file +# Inputs: 0) ExifTool ref, 1) DirInfo ref, 2) tag table ref +# Returns: 1 on success (and seeks to the end of this section) +sub ProcessLayersAndMask($$$) +{ + local $_; + my ($et, $dirInfo, $tagTablePtr) = @_; + my $raf = $$dirInfo{RAF}; + my $fileType = $$et{VALUE}{FileType}; + my $data; + + return 0 unless $fileType eq 'PSD' or $fileType eq 'PSB'; # (no layer section in CS1 files) + + # (some words are 4 bytes in PSD files and 8 bytes in PSB) + my ($psb, $psiz) = $fileType eq 'PSB' ? (1, 8) : (undef, 4); + + # read the layer information header + my $n = $psiz * 2 + 2; + $raf->Read($data, $n) == $n or return 0; + my $tot = $psb ? Get64u(\$data, 0) : Get32u(\$data, 0); # length of layer and mask info + return 1 if $tot == 0; + my $end = $raf->Tell() - $psiz - 2 + $tot; + $data = substr $data, $psiz; + my $len = $psb ? Get64u(\$data, 0) : Get32u(\$data, 0); # length of layer info section + my $num = Get16s(\$data, $psiz); + # check for Lr16 block if layers length is 0 (ref https://forums.adobe.com/thread/1540914) + if ($len == 0 and $num == 0) { + $raf->Read($data,10) == 10 or return 0; + if ($data =~/^..8BIMLr16/s) { + $raf->Read($data, $psiz+2) == $psiz+2 or return 0; + $len = $psb ? Get64u(\$data, 0) : Get32u(\$data, 0); + } else { + $raf->Seek(-10, 1) or return 0; + } + } + $len += 2; # include layer count with layer info section + $raf->Seek(-2, 1) or return 0; + my %dinfo = ( + RAF => $raf, + DirLen => $len, + ); + $$et{IsPSB} = $psb; # set PSB flag + ProcessLayers($et, \%dinfo, $tagTablePtr); + + # seek to the end of this section and return success flag + return $raf->Seek($end, 0) ? 1 : 0; +} + +#------------------------------------------------------------------------------ +# Process Photoshop layers (beginning with layer count) +# Inputs: 0) ExifTool ref, 1) DirInfo ref, 2) tag table ref +# Returns: 1 on success +# Notes: Uses ExifTool IsPSB member to determine whether file is PSB format +sub ProcessLayers($$$) +{ + local $_; + my ($et, $dirInfo, $tagTablePtr) = @_; + my ($i, $n, %count, $buff, $buf2); + my $raf = $$dirInfo{RAF}; + my $dirLen = $$dirInfo{DirLen}; + my $verbose = $$et{OPTIONS}{Verbose}; + my %dinfo = ( DataPt => \$buff, Base => $raf->Tell() ); + my $pos = 0; + return 0 if $dirLen < 2; + $raf->Read($buff, 2) == 2 or return 0; + my $num = Get16s(\$buff, 0); + $num = -$num if $num < 0; # (first channel is transparency data if negative) + $et->VerboseDir('Layers', $num, $dirLen); + $et->HandleTag($tagTablePtr, '_xcnt', $num, Start => $pos, Size => 2, %dinfo); # LayerCount + my $oldIndent = $$et{INDENT}; + $$et{INDENT} .= '| '; + + $pos += 2; + my $psb = $$et{IsPSB}; # is PSB format? + my $psiz = $psb ? 8 : 4; + for ($i=0; $i<$num; ++$i) { + $et->VPrint(0, $oldIndent.'+ [Layer '.($i+1)." of $num]\n"); + last if $pos + 18 > $dirLen; + $raf->Read($buff, 18) == 18 or last; + $dinfo{DataPos} = $pos; + # save the layer rectangle + $et->HandleTag($tagTablePtr, '_xrct', undef, Start => 0, Size => 16, %dinfo); + my $numChannels = Get16u(\$buff, 16); + $n = (2 + $psiz) * $numChannels; # size of channel information + $raf->Seek($n, 1) or last; + $pos += 18 + $n; + last if $pos + 20 > $dirLen; + $raf->Read($buff, 20) == 20 or last; + $dinfo{DataPos} = $pos; + my $sig = substr($buff, 0, 4); + $sig =~ /^(8BIM|MIB8)$/ or last; # verify signature + $et->HandleTag($tagTablePtr, '_xbnd', undef, Start => 4, Size => 4, %dinfo); + $et->HandleTag($tagTablePtr, '_xopc', undef, Start => 8, Size => 1, %dinfo); + my $nxt = $pos + 16 + Get32u(\$buff, 12); + $n = Get32u(\$buff, 16); # get size of layer mask data + $pos += 20 + $n; # skip layer mask data + last if $pos + 4 > $dirLen; + $raf->Seek($n, 1) and $raf->Read($buff, 4) == 4 or last; + $n = Get32u(\$buff, 0); # get size of layer blending ranges + $pos += 4 + $n; # skip layer blending ranges data + last if $pos + 1 > $dirLen; + $raf->Seek($n, 1) and $raf->Read($buff, 1) == 1 or last; + $n = Get8u(\$buff, 0); # get length of layer name + last if $pos + 1 + $n > $dirLen; + $raf->Read($buff, $n) == $n or last; + $dinfo{DataPos} = $pos + 1; + $et->HandleTag($tagTablePtr, '_xnam', undef, Start => 0, Size => $n, %dinfo); + my $frag = ($n + 1) & 0x3; + $raf->Seek(4 - $frag, 1) or last if $frag; + $n = ($n + 4) & 0xfffffffc; # +1 for length byte then pad to multiple of 4 bytes + $pos += $n; + # process additional layer info + while ($pos + 12 <= $nxt) { + $raf->Read($buff, 12) == 12 or last; + my $dat = substr($buff, 0, 8); + $dat = pack 'N*', unpack 'V*', $dat if GetByteOrder() eq 'II'; + my $sig = substr($dat, 0, 4); + last unless $sig eq '8BIM' or $sig eq '8B64'; # verify signature + my $tag = substr($dat, 4, 4); + # (some structures have an 8-byte size word [augh!] + # --> it would be great if '8B64' indicated a 64-bit version, and this may well + # be the case, but it is not mentioned in the Photoshop file format specification) + if ($psb and $tag =~ /^(LMsk|Lr16|Lr32|Layr|Mt16|Mt32|Mtrn|Alph|FMsk|lnk2|FEid|FXid|PxSD)$/) { + last if $pos + 16 > $nxt; + $raf->Read($buf2, 4) == 4 or last; + $buff .= $buf2; + $n = Get64u(\$buff, 8); + $pos += 4; + } else { + $n = Get32u(\$buff, 8); + } + $pos += 12; + last if $pos + $n > $nxt; + $frag = $n & 0x3; + if ($$tagTablePtr{$tag} or $verbose) { + # pad with empty entries if necessary to keep the same index for each item in the layer + $count{$tag} = 0 unless defined $count{$tag}; + $raf->Read($buff, $n) == $n or last; + $dinfo{DataPos} = $pos; + while ($count{$tag} < $i) { + $et->HandleTag($tagTablePtr, $tag, ''); + ++$count{$tag}; + } + $et->HandleTag($tagTablePtr, $tag, undef, Start => 0, Size => $n, %dinfo); + ++$count{$tag}; + if ($frag) { + $raf->Seek(4 - $frag, 1) or last; + $n += 4 - $frag; # pad to multiple of 4 bytes (PH NC) + } + } else { + $n += 4 - $frag if $frag; + $raf->Seek($n, 1) or last; + } + $pos += $n; # step to start of next structure + } + $pos = $nxt; + } + $$et{INDENT} = $oldIndent; + return 1; +} + +#------------------------------------------------------------------------------ +# Process Photoshop ImageSourceData +# Inputs: 0) ExifTool ref, 1) dirInfo ref, 2) tag table ref +# Returns: 1 on success +sub ProcessDocumentData($$$) +{ + my ($et, $dirInfo, $tagTablePtr) = @_; + my $verbose = $$et{OPTIONS}{Verbose}; + my $raf = $$dirInfo{RAF}; + my $dirLen = $$dirInfo{DirLen}; + my $pos = 36; # length of header + my $buff; + + $et->VerboseDir('Photoshop Document Data', undef, $dirLen); + unless ($raf) { + my $dataPt = $$dirInfo{DataPt}; + my $start = $$dirInfo{DirStart} || 0; + $raf = new File::RandomAccess($dataPt); + $raf->Seek($start, 0) if $start; + $dirLen = length $$dataPt - $start unless defined $dirLen; + $et->VerboseDump($dataPt, Start => $start, Len => $dirLen, Base => $$dirInfo{Base}); + } + unless ($raf->Read($buff, $pos) == $pos and + $buff =~ /^Adobe Photoshop Document Data (Block|V0002)\0/) + { + $et->Warn('Invalid Photoshop Document Data'); + return 0; + } + my $psb = ($1 eq 'V0002'); + my %dinfo = ( DataPt => \$buff ); + my ($n, $setOrder); + $$et{IsPSB} = $psb; # set PSB flag (needed when handling Layers directory) + while ($pos + 12 <= $dirLen) { + $raf->Read($buff, 8) == 8 or last; + # set byte order according to byte order of first signature + SetByteOrder($buff =~ /^(8BIM|8B64)/ ? 'MM' : 'II') if $pos == 36; + $buff = pack 'N*', unpack 'V*', $buff if GetByteOrder() eq 'II'; + my $sig = substr($buff, 0, 4); + last unless $sig eq '8BIM' or $sig eq '8B64'; # verify signature + my $tag = substr($buff, 4, 4); + if ($psb and $tag =~ /^(LMsk|Lr16|Lr32|Layr|Mt16|Mt32|Mtrn|Alph|FMsk|lnk2|FEid|FXid|PxSD)$/) { + last if $pos + 16 > $dirLen; + $raf->Read($buff, 8) == 8 or last; + $n = Get64u(\$buff, 0); + $pos += 4; + } else { + $raf->Read($buff, 4) == 4 or last; + $n = Get32u(\$buff, 0); + } + $pos += 12; + last if $pos + $n > $dirLen; + my $pad = (4 - ($n & 3)) & 3; # number of padding bytes + my $tagInfo = $$tagTablePtr{$tag}; + if ($tagInfo or $verbose) { + if ($tagInfo and $$tagInfo{SubDirectory}) { + my $fpos = $raf->Tell() + $n + $pad; + my $subTable = GetTagTable($$tagInfo{SubDirectory}{TagTable}); + $et->ProcessDirectory({ RAF => $raf, DirLen => $n }, $subTable); + $raf->Seek($fpos, 0) or last; + } else { + $dinfo{DataPos} = $raf->Tell(); + $dinfo{Start} = 0; + $dinfo{Size} = $n; + $raf->Read($buff, $n) == $n or last; + $et->HandleTag($tagTablePtr, $tag, undef, %dinfo); + $raf->Seek($pad, 1) or last; + } + } else { + $raf->Seek($n + $pad, 1) or last; + } + $pos += $n + $pad; # step to start of next structure + } + return 1; +} + +#------------------------------------------------------------------------------ +# Process Photoshop APP13 record +# Inputs: 0) ExifTool object reference, 1) Reference to directory information +# 2) Tag table reference +# Returns: 1 on success +sub ProcessPhotoshop($$$) +{ + my ($et, $dirInfo, $tagTablePtr) = @_; + my $dataPt = $$dirInfo{DataPt}; + my $pos = $$dirInfo{DirStart}; + my $dirEnd = $pos + $$dirInfo{DirLen}; + my $verbose = $et->Options('Verbose'); + my $success = 0; + + # ignore non-standard XMP while in strict MWG compatibility mode + if (($Image::ExifTool::MWG::strict or $et->Options('Validate')) and + $$et{FILE_TYPE} =~ /^(JPEG|TIFF|PSD)$/) + { + my $path = $et->MetadataPath(); + unless ($path =~ /^(JPEG-APP13-Photoshop|TIFF-IFD0-Photoshop|PSD)$/) { + if ($Image::ExifTool::MWG::strict) { + $et->Warn("Ignored non-standard Photoshop at $path"); + return 1; + } else { + $et->Warn("Non-standard Photoshop at $path", 1); + } + } + } + if ($$et{FILE_TYPE} eq 'JPEG' and $$dirInfo{Parent} ne 'APP13') { + $$et{LOW_PRIORITY_DIR}{'*'} = 1; # lower priority of all these tags + } + SetByteOrder('MM'); # Photoshop is always big-endian + $verbose and $et->VerboseDir('Photoshop', 0, $$dirInfo{DirLen}); + + # scan through resource blocks: + # Format: 0) Type, 4 bytes - '8BIM' (or the rare 'PHUT', 'DCSR', 'AgHg' or 'MeSa') + # 1) TagID,2 bytes + # 2) Name, pascal string padded to even no. bytes + # 3) Size, 4 bytes - N + # 4) Data, N bytes + while ($pos + 8 < $dirEnd) { + my $type = substr($$dataPt, $pos, 4); + my ($ttPtr, $extra, $val, $name); + if ($type eq '8BIM') { + $ttPtr = $tagTablePtr; + } elsif ($type =~ /^(PHUT|DCSR|AgHg|MeSa)$/) { # (PHUT~ImageReady, MeSa~PhotoDeluxe) + $ttPtr = GetTagTable('Image::ExifTool::Photoshop::Unknown'); + } else { + $type =~ s/([^\w])/sprintf("\\x%.2x",ord($1))/ge; + $et->Warn(qq{Bad Photoshop IRB resource "$type"}); + last; + } + my $tag = Get16u($dataPt, $pos + 4); + $pos += 6; # point to start of name + my $nameLen = Get8u($dataPt, $pos); + my $namePos = ++$pos; + # skip resource block name (pascal string, padded to an even # of bytes) + $pos += $nameLen; + ++$pos unless $nameLen & 0x01; + if ($pos + 4 > $dirEnd) { + $et->Warn("Bad Photoshop resource block"); + last; + } + my $size = Get32u($dataPt, $pos); + $pos += 4; + if ($size + $pos > $dirEnd) { + $et->Warn("Bad Photoshop resource data size $size"); + last; + } + $success = 1; + if ($nameLen) { + $name = substr($$dataPt, $namePos, $nameLen); + $extra = qq{, Name="$name"}; + } else { + $name = ''; + } + my $tagInfo = $et->GetTagInfo($ttPtr, $tag); + # append resource name to value if requested (braced by "/#...#/") + if ($tagInfo and defined $$tagInfo{SetResourceName} and + $$tagInfo{SetResourceName} eq '1' and $name !~ m{/#}) + { + $val = substr($$dataPt, $pos, $size) . '/#' . $name . '#/'; + } + $et->HandleTag($ttPtr, $tag, $val, + TagInfo => $tagInfo, + Extra => $extra, + DataPt => $dataPt, + DataPos => $$dirInfo{DataPos}, + Size => $size, + Start => $pos, + Parent => $$dirInfo{DirName}, + ); + $size += 1 if $size & 0x01; # size is padded to an even # bytes + $pos += $size; + } + delete $$et{LOW_PRIORITY_DIR}{'*'}; + return $success; +} + +#------------------------------------------------------------------------------ +# extract information from Photoshop PSD file +# Inputs: 0) ExifTool object reference, 1) dirInfo reference +# Returns: 1 if this was a valid PSD file, -1 on write error +sub ProcessPSD($$) +{ + my ($et, $dirInfo) = @_; + my $raf = $$dirInfo{RAF}; + my $outfile = $$dirInfo{OutFile}; + my ($data, $err, $tagTablePtr); + + $raf->Read($data, 30) == 30 or return 0; + $data =~ /^8BPS\0([\x01\x02])/ or return 0; + SetByteOrder('MM'); + $et->SetFileType($1 eq "\x01" ? 'PSD' : 'PSB'); # set the FileType tag + my %dirInfo = ( + DataPt => \$data, + DirStart => 0, + DirName => 'Photoshop', + ); + my $len = Get32u(\$data, 26); + if ($outfile) { + Write($outfile, $data) or $err = 1; + $raf->Read($data, $len) == $len or return -1; + Write($outfile, $data) or $err = 1; # write color mode data + # initialize map of where things are written + $et->InitWriteDirs(\%psdMap); + } else { + # process the header + $tagTablePtr = GetTagTable('Image::ExifTool::Photoshop::Header'); + $dirInfo{DirLen} = 30; + $et->ProcessDirectory(\%dirInfo, $tagTablePtr); + $raf->Seek($len, 1) or $err = 1; # skip over color mode data + } + # read image resource section + $raf->Read($data, 4) == 4 or $err = 1; + $len = Get32u(\$data, 0); + $raf->Read($data, $len) == $len or $err = 1; + $tagTablePtr = GetTagTable('Image::ExifTool::Photoshop::Main'); + $dirInfo{DirLen} = $len; + my $rtnVal = 1; + if ($outfile) { + # rewrite IRB resources + $data = WritePhotoshop($et, \%dirInfo, $tagTablePtr); + if ($data) { + $len = Set32u(length $data); + Write($outfile, $len, $data) or $err = 1; + # look for trailer and edit if necessary + my $trailInfo = Image::ExifTool::IdentifyTrailer($raf); + if ($trailInfo) { + my $tbuf = ''; + $$trailInfo{OutFile} = \$tbuf; # rewrite trailer(s) + # rewrite all trailers to buffer + if ($et->ProcessTrailers($trailInfo)) { + my $copyBytes = $$trailInfo{DataPos} - $raf->Tell(); + if ($copyBytes >= 0) { + # copy remaining PSD file up to start of trailer + while ($copyBytes) { + my $n = ($copyBytes > 65536) ? 65536 : $copyBytes; + $raf->Read($data, $n) == $n or $err = 1; + Write($outfile, $data) or $err = 1; + $copyBytes -= $n; + } + # write the trailer (or not) + $et->WriteTrailerBuffer($trailInfo, $outfile) or $err = 1; + } else { + $et->Warn('Overlapping trailer'); + undef $trailInfo; + } + } else { + undef $trailInfo; + } + } + unless ($trailInfo) { + # copy over the rest of the file + while ($raf->Read($data, 65536)) { + Write($outfile, $data) or $err = 1; + } + } + } else { + $err = 1; + } + $rtnVal = -1 if $err; + } elsif ($err) { + $et->Warn('File format error'); + } else { + # read IRB resources + ProcessPhotoshop($et, \%dirInfo, $tagTablePtr); + # read layer and mask information section + $dirInfo{RAF} = $raf; + $tagTablePtr = GetTagTable('Image::ExifTool::Photoshop::Layers'); + my $oldIndent = $$et{INDENT}; + $$et{INDENT} .= '| '; + if (ProcessLayersAndMask($et, \%dirInfo, $tagTablePtr) and + # read compression mode from image data section + $raf->Read($data,2) == 2) + { + my %dirInfo = ( + DataPt => \$data, + DataPos => $raf->Tell() - 2, + ); + $tagTablePtr = GetTagTable('Image::ExifTool::Photoshop::ImageData'); + $et->ProcessDirectory(\%dirInfo, $tagTablePtr); + } + $$et{INDENT} = $oldIndent; + # process trailers if they exist + my $trailInfo = Image::ExifTool::IdentifyTrailer($raf); + $et->ProcessTrailers($trailInfo) if $trailInfo; + } + return $rtnVal; +} + +1; # end + + +__END__ + +=head1 NAME + +Image::ExifTool::Photoshop - Read/write Photoshop IRB meta information + +=head1 SYNOPSIS + +This module is loaded automatically by Image::ExifTool when required. + +=head1 DESCRIPTION + +Photoshop writes its own format of meta information called a Photoshop IRB +resource which is located in the APP13 record of JPEG files. This module +contains the definitions to read this information. + +=head1 NOTES + +Photoshop IRB blocks may have an associated resource name. These names are +usually just an empty string, but if not empty they are displayed in the +verbose level 2 (or greater) output. A special C<SetResourceName> flag may +be set to '1' in the tag information hash to cause the resource name to be +appended to the value when extracted. If this is done, the returned value +has the form "VALUE/#NAME#/". When writing, the writer routine looks for +this syntax (if C<SetResourceName> is defined), and and uses the embedded +name to set the name of the new resource. This allows the resource names to +be preserved when copying Photoshop information via user-defined tags. + +=head1 AUTHOR + +Copyright 2003-2019, Phil Harvey (phil at owl.phy.queensu.ca) + +This library is free software; you can redistribute it and/or modify it +under the same terms as Perl itself. + +=head1 REFERENCES + +=over 4 + +=item L<http://www.fine-view.com/jp/lab/doc/ps6ffspecsv2.pdf> + +=item L<http://www.ozhiker.com/electronics/pjmt/jpeg_info/irb_jpeg_qual.html> + +=item L<http://www.fileformat.info/format/psd/egff.htm> + +=item L<http://libpsd.graphest.com/files/Photoshop%20File%20Formats.pdf> + +=item L<http://www.adobe.com/devnet-apps/photoshop/fileformatashtml/> + +=back + +=head1 SEE ALSO + +L<Image::ExifTool::TagNames/Photoshop Tags>, +L<Image::ExifTool(3pm)|Image::ExifTool>, +L<Image::MetaData::JPEG(3pm)|Image::MetaData::JPEG> + +=cut diff --git a/lib/Image/ExifTool/PostScript.pm b/lib/Image/ExifTool/PostScript.pm new file mode 100644 index 0000000..ffe96da --- /dev/null +++ b/lib/Image/ExifTool/PostScript.pm @@ -0,0 +1,724 @@ +#------------------------------------------------------------------------------ +# File: PostScript.pm +# +# Description: Read PostScript meta information +# +# Revisions: 07/08/2005 - P. Harvey Created +# +# References: 1) http://partners.adobe.com/public/developer/en/ps/5002.EPSF_Spec.pdf +# 2) http://partners.adobe.com/public/developer/en/ps/5001.DSC_Spec.pdf +# 3) http://partners.adobe.com/public/developer/en/illustrator/sdk/AI7FileFormat.pdf +#------------------------------------------------------------------------------ + +package Image::ExifTool::PostScript; + +use strict; +use vars qw($VERSION $AUTOLOAD); +use Image::ExifTool qw(:DataAccess :Utils); + +$VERSION = '1.43'; + +sub WritePS($$); +sub ProcessPS($$;$); + +# PostScript tag table +%Image::ExifTool::PostScript::Main = ( + PROCESS_PROC => \&ProcessPS, + WRITE_PROC => \&WritePS, + PREFERRED => 1, # always add these tags when writing + GROUPS => { 2 => 'Image' }, + # Note: Make all of these tags priority 0 since the first one found at + # the start of the file should take priority (in case multiples exist) + Author => { Priority => 0, Groups => { 2 => 'Author' }, Writable => 'string' }, + BoundingBox => { Priority => 0 }, + Copyright => { Priority => 0, Writable => 'string' }, #2 + CreationDate => { + Name => 'CreateDate', + Priority => 0, + Groups => { 2 => 'Time' }, + Writable => 'string', + PrintConv => '$self->ConvertDateTime($val)', + PrintConvInv => '$self->InverseDateTime($val)', + }, + Creator => { Priority => 0, Writable => 'string' }, + ImageData => { Priority => 0 }, + For => { Priority => 0, Writable => 'string', Notes => 'for whom the document was prepared'}, + Keywords => { Priority => 0, Writable => 'string' }, + ModDate => { + Name => 'ModifyDate', + Priority => 0, + Groups => { 2 => 'Time' }, + Writable => 'string', + PrintConv => '$self->ConvertDateTime($val)', + PrintConvInv => '$self->InverseDateTime($val)', + }, + Pages => { Priority => 0 }, + Routing => { Priority => 0, Writable => 'string' }, #2 + Subject => { Priority => 0, Writable => 'string' }, + Title => { Priority => 0, Writable => 'string' }, + Version => { Priority => 0, Writable => 'string' }, #2 + # these subdirectories for documentation only + BeginPhotoshop => { + Name => 'PhotoshopData', + SubDirectory => { + TagTable => 'Image::ExifTool::Photoshop::Main', + }, + }, + BeginICCProfile => { + Name => 'ICC_Profile', + SubDirectory => { + TagTable => 'Image::ExifTool::ICC_Profile::Main', + }, + }, + begin_xml_packet => { + Name => 'XMP', + SubDirectory => { + TagTable => 'Image::ExifTool::XMP::Main', + }, + }, + TIFFPreview => { + Groups => { 2 => 'Preview' }, + Binary => 1, + Notes => q{ + not a real tag ID, but used to represent the TIFF preview extracted from DOS + EPS images + }, + }, + BeginDocument => { + Name => 'EmbeddedFile', + SubDirectory => { + TagTable => 'Image::ExifTool::PostScript::Main', + }, + Notes => 'extracted with ExtractEmbedded option', + }, + EmbeddedFileName => { + Notes => q{ + not a real tag ID, but the file name from a BeginDocument statement. + Extracted with document metadata when ExtractEmbedded option is used + }, + }, + # AI metadata (most with a single leading '%') + AI9_ColorModel => { + Name => 'AIColorModel', + PrintConv => { + 1 => 'RGB', + 2 => 'CMYK', + }, + }, + AI3_ColorUsage => { Name => 'AIColorUsage' }, + AI5_RulerUnits => { + Name => 'AIRulerUnits', + PrintConv => { + 0 => 'Inches', + 1 => 'Millimeters', + 2 => 'Points', + 3 => 'Picas', + 4 => 'Centimeters', + 6 => 'Pixels', + }, + }, + AI5_TargetResolution => { Name => 'AITargetResolution' }, + AI5_NumLayers => { Name => 'AINumLayers' }, + AI5_FileFormat => { Name => 'AIFileFormat' }, + AI8_CreatorVersion => { Name => 'AICreatorVersion' }, # (double leading '%') + AI12_BuildNumber => { Name => 'AIBuildNumber' }, +); + +# composite tags +%Image::ExifTool::PostScript::Composite = ( + GROUPS => { 2 => 'Image' }, + # BoundingBox is in points, not pixels, + # but use it anyway if ImageData is not available + ImageWidth => { + Desire => { + 0 => 'Main:PostScript:ImageData', + 1 => 'PostScript:BoundingBox', + }, + ValueConv => 'Image::ExifTool::PostScript::ImageSize(\@val, 0)', + }, + ImageHeight => { + Desire => { + 0 => 'Main:PostScript:ImageData', + 1 => 'PostScript:BoundingBox', + }, + ValueConv => 'Image::ExifTool::PostScript::ImageSize(\@val, 1)', + }, +); + +# add our composite tags +Image::ExifTool::AddCompositeTags('Image::ExifTool::PostScript'); + +#------------------------------------------------------------------------------ +# AutoLoad our writer routines when necessary +# +sub AUTOLOAD +{ + return Image::ExifTool::DoAutoLoad($AUTOLOAD, @_); +} + +#------------------------------------------------------------------------------ +# Is this a PC system +# Returns: true for PC systems +my %isPC = (MSWin32 => 1, os2 => 1, dos => 1, NetWare => 1, symbian => 1, cygwin => 1); +sub IsPC() +{ + return $isPC{$^O}; +} + +#------------------------------------------------------------------------------ +# Get image width or height +# Inputs: 0) value list ref (ImageData, BoundingBox), 1) true to get height +sub ImageSize($$) +{ + my ($vals, $getHeight) = @_; + my ($w, $h); + if ($$vals[0] and $$vals[0] =~ /^(\d+) (\d+)/) { + ($w, $h) = ($1, $2); + } elsif ($$vals[1] and $$vals[1] =~ /^(\d+) (\d+) (\d+) (\d+)/) { + ($w, $h) = ($3 - $1, $4 - $2); + } + return $getHeight ? $h : $w; +} + +#------------------------------------------------------------------------------ +# Set PostScript format error warning +# Inputs: 0) ExifTool object reference, 1) error string +# Returns: 1 +sub PSErr($$) +{ + my ($et, $str) = @_; + # set file type if not done already + my $ext = $$et{FILE_EXT}; + $et->SetFileType(($ext and $ext eq 'AI') ? 'AI' : 'PS'); + $et->Warn("PostScript format error ($str)"); + return 1; +} + +#------------------------------------------------------------------------------ +# Return input record separator to use for the specified file +# Inputs: 0) RAF reference +# Returns: Input record separator or undef on error +sub GetInputRecordSeparator($) +{ + my $raf = shift; + my $pos = $raf->Tell(); # save current position + my ($data, $sep); + $raf->Read($data,256) or return undef; + my ($a, $d) = (999,999); + $a = pos($data), pos($data) = 0 if $data =~ /\x0a/g; + $d = pos($data) if $data =~ /\x0d/g; + my $diff = $a - $d; + if ($diff eq 1) { + $sep = "\x0d\x0a"; + } elsif ($diff eq -1) { + $sep = "\x0a\x0d"; + } elsif ($diff > 0) { + $sep = "\x0d"; + } elsif ($diff < 0) { + $sep = "\x0a"; + } # else error + $raf->Seek($pos, 0); # restore original position + return $sep; +} + +#------------------------------------------------------------------------------ +# Decode comment from PostScript file +# Inputs: 0) comment string, 1) RAF ref, 2) reference to lines array +# 3) optional data reference for extra lines read from file +# Returns: Decoded comment string (may be an array reference) +# - handles multi-line comments and escape sequences +sub DecodeComment($$$;$) +{ + my ($val, $raf, $lines, $dataPt) = @_; + $val =~ s/\x0d*\x0a*$//; # remove trailing CR, LF or CR/LF + # check for continuation comments + for (;;) { + unless (@$lines) { + my $buff; + $raf->ReadLine($buff) or last; + my $altnl = $/ eq "\x0d" ? "\x0a" : "\x0d"; + if ($buff =~ /$altnl/) { + chomp $buff if $/ eq "\x0d\x0a"; # remove DOS newline before splitting + # split into separate lines + @$lines = split /$altnl/, $buff, -1; + # handle case of DOS newline data inside file using Unix newlines + @$lines = ( $$lines[0] . $$lines[1] ) if @$lines == 2 and $$lines[1] eq $/; + # add back trailing DOS newline if necessary + @$lines ? @$lines[-1] .= $/ : push @$lines, $/ if $/ eq "\x0d\x0a"; + } else { + push @$lines, $buff; + } + } + last unless $$lines[0] =~ /^%%\+/; # is the next line a continuation? + $$dataPt .= $$lines[0] if $dataPt; # add to data if necessary + $$lines[0] =~ s/\x0d*\x0a*$//; # remove trailing CR, LF or CR/LF + $val .= substr(shift(@$lines), 3); # add to value (without leading "%%+") + } + my @vals; + # handle bracketed string values + if ($val =~ s/^\((.*)\)$/$1/) { # remove brackets if necessary + # split into an array of strings if necessary + my $nesting = 1; + while ($val =~ /(\(|\))/g) { + my $bra = $1; + my $pos = pos($val) - 2; + my $backslashes = 0; + while ($pos and substr($val, $pos, 1) eq '\\') { + --$pos; + ++$backslashes; + } + next if $backslashes & 0x01; # escaped if odd number + if ($bra eq '(') { + ++$nesting; + } else { + --$nesting; + unless ($nesting) { + push @vals, substr($val, 0, pos($val)-1); + $val = substr($val, pos($val)); + ++$nesting if $val =~ s/\s*\(//; + } + } + } + push @vals, $val; + foreach $val (@vals) { + # decode escape sequences in bracketed strings + # (similar to code in PDF.pm, but without line continuation) + while ($val =~ /\\(.)/sg) { + my $n = pos($val) - 2; + my $c = $1; + my $r; + if ($c =~ /[0-7]/) { + # get up to 2 more octal digits + $c .= $1 if $val =~ /\G([0-7]{1,2})/g; + # convert octal escape code + $r = chr(oct($c) & 0xff); + } else { + # convert escaped characters + ($r = $c) =~ tr/nrtbf/\n\r\t\b\f/; + } + substr($val, $n, length($c)+1) = $r; + # continue search after this character + pos($val) = $n + length($r); + } + } + $val = @vals > 1 ? \@vals : $vals[0]; + } + return $val; +} + +#------------------------------------------------------------------------------ +# Unescape PostScript string +# Inputs: 0) string +# Returns: unescaped string +sub UnescapePostScript($) +{ + my $str = shift; + # decode escape sequences in literal strings + while ($str =~ /\\(.)/sg) { + my $n = pos($str) - 2; + my $c = $1; + my $r; + if ($c =~ /[0-7]/) { + # get up to 2 more octal digits + $c .= $1 if $str =~ /\G([0-7]{1,2})/g; + # convert octal escape code + $r = chr(oct($c) & 0xff); + } elsif ($c eq "\x0d") { + # the string is continued if the line ends with '\' + # (also remove "\x0d\x0a") + $c .= $1 if $str =~ /\G(\x0a)/g; + $r = ''; + } elsif ($c eq "\x0a") { + $r = ''; + } else { + # convert escaped characters + ($r = $c) =~ tr/nrtbf/\n\r\t\b\f/; + } + substr($str, $n, length($c)+1) = $r; + # continue search after this character + pos($str) = $n + length($r); + } + return $str; +} + +#------------------------------------------------------------------------------ +# Extract information from EPS, PS or AI file +# Inputs: 0) ExifTool object reference, 1) dirInfo reference, 2) optional tag table ref +# Returns: 1 if this was a valid PostScript file +sub ProcessPS($$;$) +{ + my ($et, $dirInfo, $tagTablePtr) = @_; + my $raf = $$dirInfo{RAF}; + my $embedded = $et->Options('ExtractEmbedded'); + my ($data, $dos, $endDoc, $fontTable, $comment); + + # allow read from data + unless ($raf) { + $raf = new File::RandomAccess($$dirInfo{DataPt}); + $et->VerboseDir('PostScript'); + } +# +# determine if this is a postscript file +# + $raf->Read($data, 4) == 4 or return 0; + # accept either ASCII or DOS binary postscript file format + return 0 unless $data =~ /^(%!PS|%!Ad|%!Fo|\xc5\xd0\xd3\xc6)/; + if ($data =~ /^%!Ad/) { + # I've seen PS files start with "%!Adobe-PS"... + return 0 unless $raf->Read($data, 6) == 6 and $data eq "obe-PS"; + } elsif ($data =~ /^\xc5\xd0\xd3\xc6/) { + # process DOS binary file header + # - save DOS header then seek ahead and check PS header + $raf->Read($dos, 26) == 26 or return 0; + SetByteOrder('II'); + unless ($raf->Seek(Get32u(\$dos, 0), 0) and + $raf->Read($data, 4) == 4 and $data eq '%!PS') + { + return PSErr($et, 'invalid header'); + } + } else { + # check for PostScript font file (PFA or PFB) + my $d2; + $data .= $d2 if $raf->Read($d2,12); + if ($data =~ /^%!(PS-(AdobeFont-|Bitstream )|FontType1-)/) { + $et->SetFileType('PFA'); # PostScript ASCII font file + $fontTable = GetTagTable('Image::ExifTool::Font::PSInfo'); + # PostScript font files may contain an unformatted comments which may + # contain useful information, so accumulate these for the Comment tag + $comment = 1; + } + $raf->Seek(-length($data), 1); + } +# +# set the newline type based on the first newline found in the file +# + local $/ = GetInputRecordSeparator($raf); + $/ or return PSErr($et, 'invalid PS data'); + + # set file type (PostScript or EPS) + $raf->ReadLine($data) or $data = ''; + my $type; + if ($data =~ /EPSF/) { + $type = 'EPS'; + } else { + # read next line to see if this is an Illustrator file + my $line2; + my $pos = $raf->Tell(); + if ($raf->ReadLine($line2) and $line2 =~ /^%%Creator: Adobe Illustrator/) { + $type = 'AI'; + } else { + $type = 'PS'; + } + $raf->Seek($pos, 0); + } + $et->SetFileType($type); + return 1 if $$et{OPTIONS}{FastScan} and $$et{OPTIONS}{FastScan} == 3; +# +# extract TIFF information from DOS header +# + $tagTablePtr or $tagTablePtr = GetTagTable('Image::ExifTool::PostScript::Main'); + if ($dos) { + my $base = Get32u(\$dos, 16); + if ($base) { + my $pos = $raf->Tell(); + # extract the TIFF preview + my $len = Get32u(\$dos, 20); + my $val = $et->ExtractBinary($base, $len, 'TIFFPreview'); + if (defined $val and $val =~ /^(MM\0\x2a|II\x2a\0|Binary)/) { + $et->HandleTag($tagTablePtr, 'TIFFPreview', $val); + } else { + $et->Warn('Bad TIFF preview image'); + } + # extract information from TIFF in DOS header + # (set Parent to '' to avoid setting FileType tag again) + my %dirInfo = ( + Parent => '', + RAF => $raf, + Base => $base, + ); + $et->ProcessTIFF(\%dirInfo) or $et->Warn('Bad embedded TIFF'); + # position file pointer to extract PS information + $raf->Seek($pos, 0); + } + } +# +# parse the postscript +# + my ($buff, $mode, $beginToken, $endToken, $docNum, $subDocNum, $changedNL); + my (@lines, $altnl); + if ($/ eq "\x0d") { + $altnl = "\x0a"; + } else { + $/ = "\x0a"; # end on any LF (even if DOS CR+LF) + $altnl = "\x0d"; + } + for (;;) { + if (@lines) { + $data = shift @lines; + } else { + $raf->ReadLine($data) or last; + # check for alternate newlines as efficiently as possible + if ($data =~ /$altnl/) { + if (length($data) > 500000 and IsPC()) { + # Windows can't split very long lines due to poor memory handling, + # so re-read the file with the other newline character instead + # (slower but uses less memory) + unless ($changedNL) { + $changedNL = 1; + my $t = $/; + $/ = $altnl; + $altnl = $t; + $raf->Seek(-length($data), 1); + next; + } + } else { + # split into separate lines + @lines = split /$altnl/, $data, -1; + $data = shift @lines; + if (@lines == 1 and $lines[0] eq $/) { + # handle case of DOS newline data inside file using Unix newlines + $data .= $lines[0]; + undef @lines; + } + } + } + } + undef $changedNL; + if ($mode) { + if (not $endToken) { + $buff .= $data; + next unless $data =~ m{<\?xpacket end=.(w|r).\?>($/|$)}; + } elsif ($data !~ /^$endToken/i) { + if ($mode eq 'XMP') { + $buff .= $data; + } elsif ($mode eq 'Document') { + # ignore embedded documents, but keep track of nesting level + $docNum .= '-1' if $data =~ /^$beginToken/; + } else { + # data is ASCII-hex encoded + $data =~ tr/0-9A-Fa-f//dc; # remove all but hex characters + $buff .= pack('H*', $data); # translate from hex + } + next; + } elsif ($mode eq 'Document') { + $docNum =~ s/-?\d+$//; # decrement document nesting level + # done with Document mode if we are back at the top level + undef $mode unless $docNum; + next; + } + } elsif ($endDoc and $data =~ /^$endDoc/i) { + $docNum =~ s/-?(\d+)$//; # decrement nesting level + $subDocNum = $1; # remember our last sub-document number + $$et{DOC_NUM} = $docNum; + undef $endDoc unless $docNum; # done with document if top level + next; + } elsif ($data =~ /^(%{1,2})(Begin)(_xml_packet|Photoshop|ICCProfile|Document|Binary)/i) { + # the beginning of a data block + my %modeLookup = ( + _xml_packet => 'XMP', + photoshop => 'Photoshop', + iccprofile => 'ICC_Profile', + document => 'Document', + binary => undef, # (we will try to skip this) + ); + $mode = $modeLookup{lc $3}; + unless ($mode) { + if (not @lines and $data =~ /^%{1,2}BeginBinary:\s*(\d+)/i) { + $raf->Seek($1, 1) or last; # skip binary data + } + next; + } + $buff = ''; + $beginToken = $1 . $2 . $3; + $endToken = $1 . ($2 eq 'begin' ? 'end' : 'End') . $3; + if ($mode eq 'Document') { + # this is either the 1st sub-document or Nth document + if ($docNum) { + # increase nesting level + $docNum .= '-' . (++$subDocNum); + } else { + # this is the Nth document + $docNum = $$et{DOC_COUNT} + 1; + } + $subDocNum = 0; # new level, so reset subDocNum + next unless $embedded; # skip over this document + # set document number for family 4-7 group names + $$et{DOC_NUM} = $docNum; + $$et{LIST_TAGS} = { }; # don't build lists across different documents + $$et{PROCESSED} = { }; # re-initialize processed directory lookup too + $endDoc = $endToken; # parse to EndDocument token + # reset mode to allow parsing into sub-directories + undef $endToken; + undef $mode; + # save document name if available + if ($data =~ /^$beginToken:\s+([^\n\r]+)/i) { + my $docName = $1; + # remove brackets if necessary + $docName = $1 if $docName =~ /^\((.*)\)$/; + $et->HandleTag($tagTablePtr, 'EmbeddedFileName', $docName); + } + } + next; + } elsif ($data =~ /^<\?xpacket begin=.{7,13}W5M0MpCehiHzreSzNTczkc9d/) { + # pick up any stray XMP data + $mode = 'XMP'; + $buff = $data; + undef $endToken; # no end token (just look for xpacket end) + # XMP could be contained in a single line (if newlines are different) + next unless $data =~ m{<\?xpacket end=.(w|r).\?>($/|$)}; + } elsif ($data =~ /^%%?(\w+): ?(.*)/s and $$tagTablePtr{$1}) { + my ($tag, $val) = ($1, $2); + # only allow 'ImageData' and AI tags to have single leading '%' + next unless $data =~ /^%(%|AI\d+_)/ or $tag eq 'ImageData'; + # decode comment string (reading continuation lines if necessary) + $val = DecodeComment($val, $raf, \@lines); + $et->HandleTag($tagTablePtr, $tag, $val); + next; + } elsif ($embedded and $data =~ /^%AI12_CompressedData/) { + # the rest of the file is compressed + unless (eval { require Compress::Zlib }) { + $et->Warn('Install Compress::Zlib to extract compressed embedded data'); + last; + } + # seek back to find the start of the compressed data in the file + my $tlen = length($data) + @lines; + $tlen += length $_ foreach @lines; + my $backTo = $raf->Tell() - $tlen - 64; + $backTo = 0 if $backTo < 0; + last unless $raf->Seek($backTo, 0) and $raf->Read($data, 2048); + last unless $data =~ s/.*?%AI12_CompressedData//; + my $inflate = Compress::Zlib::inflateInit(); + $inflate or $et->Warn('Error initializing inflate'), last; + # generate a PS-like file in memory from the compressed data + my $verbose = $et->Options('Verbose'); + if ($verbose > 1) { + $et->VerboseDir('AI12_CompressedData (first 4kB)'); + $et->VerboseDump(\$data); + } + # remove header if it exists (Windows AI files only) + $data =~ s/^.{0,256}EndData[\x0d\x0a]+//s; + my $val; + for (;;) { + my ($v2, $stat) = $inflate->inflate($data); + $stat == Compress::Zlib::Z_STREAM_END() and $val .= $v2, last; + $stat != Compress::Zlib::Z_OK() and undef($val), last; + if (defined $val) { + $val .= $v2; + } elsif ($v2 =~ /^%!PS/) { + $val = $v2; + } else { + # add postscript header (for file recognition) if it doesn't exist + $val = "%!PS-Adobe-3.0$/" . $v2; + } + $raf->Read($data, 65536) or last; + } + defined $val or $et->Warn('Error inflating AI compressed data'), last; + if ($verbose > 1) { + $et->VerboseDir('Uncompressed AI12 Data'); + $et->VerboseDump(\$val); + } + # extract information from embedded images in the uncompressed data + $val = # add PS header in case it needs one + ProcessPS($et, { DataPt => \$val }); + last; + } elsif ($fontTable) { + if (defined $comment) { + # extract initial comments from PostScript Font files + if ($data =~ /^%\s+(.*?)[\x0d\x0a]/) { + $comment .= "\n" if $comment; + $comment .= $1; + next; + } elsif ($data !~ /^%/) { + # stop extracting comments at the first non-comment line + $et->FoundTag('Comment', $comment) if length $comment; + undef $comment; + } + } + if ($data =~ m{^\s*/(\w+)\s*(.*)} and $$fontTable{$1}) { + my ($tag, $val) = ($1, $2); + if ($val =~ /^\((.*)\)/) { + $val = UnescapePostScript($1); + } elsif ($val =~ m{/?(\S+)}) { + $val = $1; + } + $et->HandleTag($fontTable, $tag, $val); + } elsif ($data =~ /^currentdict end/) { + # only extract tags from initial FontInfo dict + undef $fontTable; + } + next; + } else { + next; + } + # extract information from buffered data + my %dirInfo = ( + DataPt => \$buff, + DataLen => length $buff, + DirStart => 0, + DirLen => length $buff, + Parent => 'PostScript', + ); + my $subTablePtr = GetTagTable("Image::ExifTool::${mode}::Main"); + unless ($et->ProcessDirectory(\%dirInfo, $subTablePtr)) { + $et->Warn("Error processing $mode information in PostScript file"); + } + undef $buff; + undef $mode; + } + $mode = 'Document' if $endDoc and not $mode; + $mode and PSErr($et, "unterminated $mode data"); + return 1; +} + +#------------------------------------------------------------------------------ +# Extract information from EPS file +# Inputs: 0) ExifTool object reference, 1) dirInfo reference +# Returns: 1 if this was a valid PostScript file +sub ProcessEPS($$) +{ + return ProcessPS($_[0],$_[1]); +} + +1; # end + + +__END__ + +=head1 NAME + +Image::ExifTool::PostScript - Read PostScript meta information + +=head1 SYNOPSIS + +This module is loaded automatically by Image::ExifTool when required. + +=head1 DESCRIPTION + +This code reads meta information from EPS (Encapsulated PostScript), PS +(PostScript) and AI (Adobe Illustrator) files. + +=head1 AUTHOR + +Copyright 2003-2019, Phil Harvey (phil at owl.phy.queensu.ca) + +This library is free software; you can redistribute it and/or modify it +under the same terms as Perl itself. + +=head1 REFERENCES + +=over 4 + +=item L<http://partners.adobe.com/public/developer/en/ps/5002.EPSF_Spec.pdf> + +=item L<http://partners.adobe.com/public/developer/en/ps/5001.DSC_Spec.pdf> + +=item L<http://partners.adobe.com/public/developer/en/illustrator/sdk/AI7FileFormat.pdf> + +=back + +=head1 SEE ALSO + +L<Image::ExifTool::TagNames/PostScript Tags>, +L<Image::ExifTool(3pm)|Image::ExifTool> + +=cut diff --git a/lib/Image/ExifTool/PrintIM.pm b/lib/Image/ExifTool/PrintIM.pm new file mode 100644 index 0000000..12b8e5b --- /dev/null +++ b/lib/Image/ExifTool/PrintIM.pm @@ -0,0 +1,125 @@ +#------------------------------------------------------------------------------ +# File: PrintIM.pm +# +# Description: Read PrintIM meta information +# +# Revisions: 04/07/2004 - P. Harvey Created +#------------------------------------------------------------------------------ + +package Image::ExifTool::PrintIM; + +use strict; +use vars qw($VERSION); +use Image::ExifTool qw(:DataAccess); + +$VERSION = '1.07'; + +sub ProcessPrintIM($$$); + +# PrintIM table (proprietary specification by Epson) +%Image::ExifTool::PrintIM::Main = ( + PROCESS_PROC => \&ProcessPrintIM, + GROUPS => { 0 => 'PrintIM', 1 => 'PrintIM', 2 => 'Printing' }, + PRINT_CONV => 'sprintf("0x%.8x", $val)', + TAG_PREFIX => 'PrintIM', + PrintIMVersion => { # values: 0100, 0250, 0260, 0300 + Description => 'PrintIM Version', + PrintConv => undef, + }, + # the following names are from http://www.kanzaki.com/ns/exif + # but the decoding is unknown: + # 9 => { Name => 'PIMContrast', Unknown => 1 }, #1 + # 10 => { Name => 'PIMBrightness', Unknown => 1 }, #1 + # 11 => { Name => 'PIMColorbalance', Unknown => 1 }, #1 + # 12 => { Name => 'PIMSaturation', Unknown => 1 }, #1 + # 13 => { Name => 'PIMSharpness', Unknown => 1 }, #1 +); + + +#------------------------------------------------------------------------------ +# Process PrintIM IFD +# Inputs: 0) ExifTool object ref, 1) dirInfo ref, 2) tag table ref +# Returns: 1 on success +sub ProcessPrintIM($$$) +{ + my ($et, $dirInfo, $tagTablePtr) = @_; + my $dataPt = $$dirInfo{DataPt}; + my $offset = $$dirInfo{DirStart}; + my $size = $$dirInfo{DirLen}; + my $verbose = $et->Options('Verbose'); + + unless ($size) { + $et->Warn('Empty PrintIM data', 1); + return 0; + } + unless ($size > 15) { + $et->Warn('Bad PrintIM data'); + return 0; + } + unless (substr($$dataPt, $offset, 7) eq 'PrintIM') { + $et->Warn('Invalid PrintIM header'); + return 0; + } + # check size of PrintIM block + my $num = Get16u($dataPt, $offset + 14); + if ($size < 16 + $num * 6) { + # size is too big, maybe byte ordering is wrong + ToggleByteOrder(); + $num = Get16u($dataPt, $offset + 14); + if ($size < 16 + $num * 6) { + $et->Warn('Bad PrintIM size'); + return 0; + } + } + $verbose and $et->VerboseDir('PrintIM', $num); + $et->HandleTag($tagTablePtr, 'PrintIMVersion', substr($$dataPt, $offset + 8, 4), + DataPt => $dataPt, + Start => $offset + 8, + Size => 4, + ); + my $n; + for ($n=0; $n<$num; ++$n) { + my $pos = $offset + 16 + $n * 6; + my $tag = Get16u($dataPt, $pos); + my $val = Get32u($dataPt, $pos + 2); + $et->HandleTag($tagTablePtr, $tag, $val, + Index => $n, + DataPt => $dataPt, + Start => $pos + 2, + Size => 4, + ); + } + return 1; +} + + +1; # end + +__END__ + +=head1 NAME + +Image::ExifTool::PrintIM - Read PrintIM meta information + +=head1 SYNOPSIS + +This module is loaded automatically by Image::ExifTool when required. + +=head1 DESCRIPTION + +This module contains definitions required by Image::ExifTool to interpret +Print Image Matching meta information. + +=head1 AUTHOR + +Copyright 2003-2019, Phil Harvey (phil at owl.phy.queensu.ca) + +This library is free software; you can redistribute it and/or modify it +under the same terms as Perl itself. + +=head1 SEE ALSO + +L<Image::ExifTool::TagNames/PrintIM Tags>, +L<Image::ExifTool(3pm)|Image::ExifTool> + +=cut diff --git a/lib/Image/ExifTool/Qualcomm.pm b/lib/Image/ExifTool/Qualcomm.pm new file mode 100644 index 0000000..ed6ed6b --- /dev/null +++ b/lib/Image/ExifTool/Qualcomm.pm @@ -0,0 +1,1344 @@ +#------------------------------------------------------------------------------ +# File: Qualcomm.pm +# +# Description: Read Qualcomm APP7 meta information +# +# Revisions: 2012/02/14 - P. Harvey Created +#------------------------------------------------------------------------------ + +package Image::ExifTool::Qualcomm; + +use strict; +use vars qw($VERSION); +use Image::ExifTool qw(:DataAccess :Utils); + +$VERSION = '1.01'; + +sub ProcessQualcomm($$$); +sub MakeNameAndDesc($$); + +# Qualcomm format codes (ref PH (NC)) +my @qualcommFormat = ( + 'int8u', 'int8s', 'int16u', 'int16s', + 'int32u', 'int32s', 'float', 'double', +); + +# information found in JPEG APP7 Qualcomm Camera Attributes segment +%Image::ExifTool::Qualcomm::Main = ( + PROCESS_PROC => \&ProcessQualcomm, + GROUPS => { 0 => 'MakerNotes', 2 => 'Camera' }, + VARS => { NO_ID => 1, NO_LOOKUP => 1 }, # too long, too many, and too obscure + NOTES => q{ + The tags below have been observed in the JPEG APP7 "Qualcomm Camera + Attributes" segment written by some cameras such as the HP iPAQ Voice + Messenger. ExifTool will extract any information found from this segment, + even if it is not listed in this table. + }, + 'aec_current_sensor_luma' => { }, + 'af_position' => { }, + 'aec_current_exp_index' => { }, + 'awb_sample_decision' => { }, + 'asf5_enable' => { }, + 'asf5_filter_mode' => { }, + 'asf5_exposure_index_1' => { }, + 'asf5_exposure_index_2' => { }, + 'asf5_max_exposure_index' => { }, + 'asf5_luma_filter[0]' => { }, + 'asf5_luma_filter[1]' => { }, + 'asf5_luma_filter[2]' => { }, + 'asf5_luma_filter[3]' => { }, + 'asf5_luma_filter[4]' => { }, + 'asf5_luma_filter[5]' => { }, + 'asf5_luma_filter[6]' => { }, + 'asf5_luma_filter[7]' => { }, + 'asf5_luma_filter[8]' => { }, + 'asf5_filter1_a11' => { }, + 'asf5_filter1_a12' => { }, + 'asf5_filter1_a13' => { }, + 'asf5_filter1_a14' => { }, + 'asf5_filter1_a15' => { }, + 'asf5_filter1_a21' => { }, + 'asf5_filter1_a22' => { }, + 'asf5_filter1_a23' => { }, + 'asf5_filter1_a24' => { }, + 'asf5_filter1_a25' => { }, + 'asf5_filter1_a31' => { }, + 'asf5_filter1_a32' => { }, + 'asf5_filter1_a33' => { }, + 'asf5_filter1_a34' => { }, + 'asf5_filter1_a35' => { }, + 'asf5_filter1_a41' => { }, + 'asf5_filter1_a42' => { }, + 'asf5_filter1_a43' => { }, + 'asf5_filter1_a44' => { }, + 'asf5_filter1_a45' => { }, + 'asf5_filter1_a51' => { }, + 'asf5_filter1_a52' => { }, + 'asf5_filter1_a53' => { }, + 'asf5_filter1_a54' => { }, + 'asf5_filter1_a55' => { }, + 'asf5_filter2_a11' => { }, + 'asf5_filter2_a12' => { }, + 'asf5_filter2_a13' => { }, + 'asf5_filter2_a14' => { }, + 'asf5_filter2_a15' => { }, + 'asf5_filter2_a21' => { }, + 'asf5_filter2_a22' => { }, + 'asf5_filter2_a23' => { }, + 'asf5_filter2_a24' => { }, + 'asf5_filter2_a25' => { }, + 'asf5_filter2_a31' => { }, + 'asf5_filter2_a32' => { }, + 'asf5_filter2_a33' => { }, + 'asf5_filter2_a34' => { }, + 'asf5_filter2_a35' => { }, + 'asf5_filter2_a41' => { }, + 'asf5_filter2_a42' => { }, + 'asf5_filter2_a43' => { }, + 'asf5_filter2_a44' => { }, + 'asf5_filter2_a45' => { }, + 'asf5_filter2_a51' => { }, + 'asf5_filter2_a52' => { }, + 'asf5_filter2_a53' => { }, + 'asf5_filter2_a54' => { }, + 'asf5_filter2_a55' => { }, + 'asf5_nrmize_factor1' => { }, + 'asf5_nrmize_factor2' => { }, + 'asf5_low_lo_thres' => { }, + 'asf5_low_up_thres' => { }, + 'asf5_low_shrp_deg_f1' => { }, + 'asf5_low_shrp_deg_f2' => { }, + 'asf5_low_smth_prcnt' => { }, + 'asf5_nrm_lo_thres' => { }, + 'asf5_nrm_up_thres' => { }, + 'asf5_nrm_shrp_deg_f1' => { }, + 'asf5_nrm_shrp_deg_f2' => { }, + 'asf5_nrm_smth_prcnt' => { }, + 'asf5_brt_lo_thres' => { }, + 'asf5_brt_up_thres' => { }, + 'asf5_brt_shrp_deg_f1' => { }, + 'asf5_brt_shrp_deg_f2' => { }, + 'asf5_brt_smth_percent' => { }, + 'asf3_enable' => { }, + 'asf3_edge_filter_a11' => { }, + 'asf3_edge_filter_a12' => { }, + 'asf3_edge_filter_a13' => { }, + 'asf3_edge_filter_a21' => { }, + 'asf3_edge_filter_a22' => { }, + 'asf3_edge_filter_a23' => { }, + 'asf3_edge_filter_a31' => { }, + 'asf3_edge_filter_a32' => { }, + 'asf3_edge_filter_a33' => { }, + 'asf3_noise_filter_a11' => { }, + 'asf3_noise_filter_a12' => { }, + 'asf3_noise_filter_a13' => { }, + 'asf3_noise_filter_a21' => { }, + 'asf3_noise_filter_a22' => { }, + 'asf3_noise_filter_a23' => { }, + 'asf3_noise_filter_a31' => { }, + 'asf3_noise_filter_a32' => { }, + 'asf3_noise_filter_a33' => { }, + 'asf3_lower_threshold' => { }, + 'asf3_upper_threshold' => { }, + 'asf3_edge_detect' => { }, + 'aec_enable' => { }, + 'aec_mode' => { }, + 'aec_aggressiveness' => { }, + 'aec_luma_target' => { }, + 'aec_luma_tolerance' => { }, + 'aec_indoor_idx' => { }, + 'aec_odoor_idx' => { }, + 'aec_exposure_index_adj_step' => { }, + 'aec_outdoor_gamma_index' => { }, + 'aec_vfe_luma' => { }, + 'aec_high_luma_region_threshold' => { }, + 'aec_snapshot_sensor_gain' => { }, + 'aec_snapshot_digital_gain' => { }, + 'aec_snapshot_line_count' => { }, + 'aec_snapshot_exposure_time_ms' => { }, + 'aec_outdoor_bright_enable' => { }, + 'aec_outdoor_bright_reduction' => { }, + 'aec_outdoor_bright_threshold_LO' => { }, + 'aec_outdoor_bright_threshold_HI' => { }, + 'aec_outdoor_bright_discarded' => { }, + 'aec_high_luma_region_count' => { }, + 'antibanding_enable' => { }, + 'anti_bading_pixel_clk' => { }, + 'anti_bading_pixel_clk_per_line' => { }, + 'afr_enable' => { }, + 'afr_faster_0_trigger' => { }, + 'afr_slower_0_trigger' => { }, + 'afr_faster_0_exp_mod' => { }, + 'afr_slower_0_exp_mod' => { }, + 'afr_faster_1_trigger' => { }, + 'afr_slower_1_trigger' => { }, + 'afr_faster_1_exp_mod' => { }, + 'afr_slower_1_exp_mod' => { }, + 'afr_faster_2_trigger' => { }, + 'afr_slower_2_trigger' => { }, + 'afr_faster_2_exp_mod' => { }, + 'afr_slower_2_exp_mod' => { }, + 'afr_faster_3_trigger' => { }, + 'afr_slower_3_trigger' => { }, + 'afr_faster_3_exp_mod' => { }, + 'afr_slower_3_exp_mod' => { }, + 'afr_faster_4_trigger' => { }, + 'afr_slower_4_trigger' => { }, + 'afr_faster_4_exp_mod' => { }, + 'afr_slower_4_exp_mod' => { }, + 'afr_possible_frame_cnt' => { }, + 'af_enable' => { }, + 'af_steps_near_far' => { }, + 'af_steps_near_infinity' => { }, + 'af_gross_step' => { }, + 'af_fine_step' => { }, + 'af_fine_srch_points' => { }, + 'af_process' => { }, + 'af_mode' => { }, + 'af_near_end' => { }, + 'af_boundary' => { }, + 'af_far_end' => { }, + 'af_collect_end_stat' => { }, + 'af_test_mode' => { }, + 'af_undershoot_protect' => { }, + 'af_reset_lens_after_snap' => { }, + 'clip_to_af_rato' => { }, + 'af_pos_def_macro' => { }, + 'af_pos_def_norm' => { }, + 'af_vfe_vert_offset' => { }, + 'af_vfe_horz_offset' => { }, + 'af_vfe_vert_height' => { }, + 'af_vfe_horz_width' => { }, + 'af_vfe_metric_max' => { }, + 'af_trace_positions[0]' => { }, + 'af_trace_positions[1]' => { }, + 'af_trace_positions[2]' => { }, + 'af_trace_positions[3]' => { }, + 'af_trace_positions[4]' => { }, + 'af_trace_positions[5]' => { }, + 'af_trace_positions[6]' => { }, + 'af_trace_positions[7]' => { }, + 'af_trace_positions[8]' => { }, + 'af_trace_positions[9]' => { }, + 'af_trace_positions[10]' => { }, + 'af_trace_positions[11]' => { }, + 'af_trace_positions[12]' => { }, + 'af_trace_positions[13]' => { }, + 'af_trace_positions[14]' => { }, + 'af_trace_positions[15]' => { }, + 'af_trace_positions[16]' => { }, + 'af_trace_positions[17]' => { }, + 'af_trace_positions[18]' => { }, + 'af_trace_positions[19]' => { }, + 'af_trace_positions[20]' => { }, + 'af_trace_positions[21]' => { }, + 'af_trace_positions[22]' => { }, + 'af_trace_positions[23]' => { }, + 'af_trace_positions[24]' => { }, + 'af_trace_positions[25]' => { }, + 'af_trace_positions[26]' => { }, + 'af_trace_positions[27]' => { }, + 'af_trace_positions[28]' => { }, + 'af_trace_positions[29]' => { }, + 'af_trace_positions[30]' => { }, + 'af_trace_positions[31]' => { }, + 'af_trace_positions[32]' => { }, + 'af_trace_positions[33]' => { }, + 'af_trace_positions[34]' => { }, + 'af_trace_positions[35]' => { }, + 'af_trace_positions[36]' => { }, + 'af_trace_positions[37]' => { }, + 'af_trace_positions[38]' => { }, + 'af_trace_positions[39]' => { }, + 'af_trace_positions[40]' => { }, + 'af_trace_positions[41]' => { }, + 'af_trace_positions[42]' => { }, + 'af_trace_positions[43]' => { }, + 'af_trace_positions[44]' => { }, + 'af_trace_positions[45]' => { }, + 'af_trace_positions[46]' => { }, + 'af_trace_positions[47]' => { }, + 'af_trace_positions[48]' => { }, + 'af_trace_positions[49]' => { }, + 'af_trace_stats[0]' => { }, + 'af_trace_stats[1]' => { }, + 'af_trace_stats[2]' => { }, + 'af_trace_stats[3]' => { }, + 'af_trace_stats[4]' => { }, + 'af_trace_stats[5]' => { }, + 'af_trace_stats[6]' => { }, + 'af_trace_stats[7]' => { }, + 'af_trace_stats[8]' => { }, + 'af_trace_stats[9]' => { }, + 'af_trace_stats[10]' => { }, + 'af_trace_stats[11]' => { }, + 'af_trace_stats[12]' => { }, + 'af_trace_stats[13]' => { }, + 'af_trace_stats[14]' => { }, + 'af_trace_stats[15]' => { }, + 'af_trace_stats[16]' => { }, + 'af_trace_stats[17]' => { }, + 'af_trace_stats[18]' => { }, + 'af_trace_stats[19]' => { }, + 'af_trace_stats[20]' => { }, + 'af_trace_stats[21]' => { }, + 'af_trace_stats[22]' => { }, + 'af_trace_stats[23]' => { }, + 'af_trace_stats[24]' => { }, + 'af_trace_stats[25]' => { }, + 'af_trace_stats[26]' => { }, + 'af_trace_stats[27]' => { }, + 'af_trace_stats[28]' => { }, + 'af_trace_stats[29]' => { }, + 'af_trace_stats[30]' => { }, + 'af_trace_stats[31]' => { }, + 'af_trace_stats[32]' => { }, + 'af_trace_stats[33]' => { }, + 'af_trace_stats[34]' => { }, + 'af_trace_stats[35]' => { }, + 'af_trace_stats[36]' => { }, + 'af_trace_stats[37]' => { }, + 'af_trace_stats[38]' => { }, + 'af_trace_stats[39]' => { }, + 'af_trace_stats[40]' => { }, + 'af_trace_stats[41]' => { }, + 'af_trace_stats[42]' => { }, + 'af_trace_stats[43]' => { }, + 'af_trace_stats[44]' => { }, + 'af_trace_stats[45]' => { }, + 'af_trace_stats[46]' => { }, + 'af_trace_stats[47]' => { }, + 'af_trace_stats[48]' => { }, + 'af_trace_stats[49]' => { }, + 'af_focus_time' => { }, + 'awb_enable' => { }, + 'awb_algorithm' => { }, + 'awb_aggressiveness' => { }, + 'awb_red_gain_ref1' => { }, + 'awb_blue_gain_ref1' => { }, + 'awb_red_gain_adj_ref1' => { }, + 'awb_blue_gain_adj_ref1' => { }, + 'awb_red_gain_ref2' => { }, + 'awb_blue_gain_ref2' => { }, + 'awb_red_gain_adj_ref2' => { }, + 'awb_blue_gain_adj_ref2' => { }, + 'awb_red_gain_ref3' => { }, + 'awb_blue_gain_ref3' => { }, + 'awb_red_gain_adj_ref3' => { }, + 'awb_blue_gain_adj_ref3' => { }, + 'awb_red_gain_ref4' => { }, + 'awb_blue_gain_ref4' => { }, + 'awb_red_gain_adj_ref4' => { }, + 'awb_blue_gain_adj_ref4' => { }, + 'awb_red_gain_ref5' => { }, + 'awb_blue_gain_ref5' => { }, + 'awb_red_gain_adj_ref5' => { }, + 'awb_blue_gain_adj_ref5' => { }, + 'awb_red_gain_ref6' => { }, + 'awb_blue_gain_ref6' => { }, + 'awb_red_gain_adj_ref6' => { }, + 'awb_blue_gain_adj_ref6' => { }, + 'awb_red_gain_ref7' => { }, + 'awb_blue_gain_ref7' => { }, + 'awb_red_gain_adj_ref7' => { }, + 'awb_blue_gain_adj_ref7' => { }, + 'awb_red_gain_ref8' => { }, + 'awb_blue_gain_ref8' => { }, + 'awb_red_gain_adj_ref8' => { }, + 'awb_blue_gain_adj_ref8' => { }, + 'awb_lo_vfe_max_y' => { }, + 'awb_lo_vfe_min_y' => { }, + 'awb_lo_vfe_m1' => { }, + 'awb_lo_vfe_m2' => { }, + 'awb_lo_vfe_m3' => { }, + 'awb_lo_vfe_m4' => { }, + 'awb_lo_vfe_c1' => { }, + 'awb_lo_vfe_c2' => { }, + 'awb_lo_vfe_c3' => { }, + 'awb_lo_vfe_c4' => { }, + 'awb_norm_vfe_max_y' => { }, + 'awb_norm_vfe_min_y' => { }, + 'awb_norm_vfe_m1' => { }, + 'awb_norm_vfe_m2' => { }, + 'awb_norm_vfe_m3' => { }, + 'awb_norm_vfe_m4' => { }, + 'awb_norm_vfe_c1' => { }, + 'awb_norm_vfe_c2' => { }, + 'awb_norm_vfe_c3' => { }, + 'awb_norm_vfe_c4' => { }, + 'awb_oudor_vfe_max_y' => { }, + 'awb_oudor_vfe_min_y' => { }, + 'awb_oudor_vfe_m1' => { }, + 'awb_oudor_vfe_m2' => { }, + 'awb_oudor_vfe_m3' => { }, + 'awb_oudor_vfe_m4' => { }, + 'awb_oudor_vfe_c1' => { }, + 'awb_oudor_vfe_c2' => { }, + 'awb_oudor_vfe_c3' => { }, + 'awb_oudor_vfe_c4' => { }, + 'awb_cc_bias' => { }, + 'awb_min_r_gain' => { }, + 'awb_min_g_gain' => { }, + 'awb_min_b_gain' => { }, + 'awb_max_r_gain' => { }, + 'awb_max_g_gain' => { }, + 'awb_max_b_gain' => { }, + 'awb_outdoor_sample_influence' => { }, + 'awb_indoor_sample_influence' => { }, + 'awb_low_lig_col_cor_ena' => { }, + 'awb_agw_grid_dist_2_thresh' => { }, + 'awb_ave_rg_ratio' => { }, + 'awb_ave_bg_ratio' => { }, + 'awb_compact_cluster_R2' => { }, + 'outlier_distance' => { }, + 'awb_green_offset_rg' => { }, + 'awb_green_offset_bg' => { }, + 'awb_prev_wb_rgain' => { }, + 'awb_prev_wb_ggain' => { }, + 'awb_prev_wb_bgain' => { }, + 'awb_snapshot_r_gain' => { }, + 'awb_snapshot_b_gain' => { }, + 'rolloff_enable' => { }, + 'r2_tl84_cx' => { }, + 'r2_tl84_cy' => { }, + 'r2_tl84_width' => { }, + 'r2_tl84_height' => { }, + 'r2_tl84_intervals' => { }, + 'r2_tl84_tbl[0]' => { }, + 'r2_tl84_tbl[1]' => { }, + 'r2_tl84_tbl[2]' => { }, + 'r2_tl84_tbl[3]' => { }, + 'r2_tl84_tbl[4]' => { }, + 'r2_tl84_tbl[5]' => { }, + 'r2_tl84_tbl[6]' => { }, + 'r2_tl84_tbl[7]' => { }, + 'r2_tl84_tbl[8]' => { }, + 'r2_tl84_tbl[9]' => { }, + 'r2_tl84_tbl[10]' => { }, + 'r2_tl84_tbl[11]' => { }, + 'r2_tl84_tbl[12]' => { }, + 'r2_tl84_tbl[13]' => { }, + 'r2_tl84_tbl[14]' => { }, + 'r2_tl84_tbl[15]' => { }, + 'r2_tl84_tbl[16]' => { }, + 'r2_tl84_tbl[17]' => { }, + 'r2_tl84_tbl[18]' => { }, + 'r2_tl84_tbl[19]' => { }, + 'r2_tl84_tbl[20]' => { }, + 'r2_tl84_tbl[21]' => { }, + 'r2_tl84_tbl[22]' => { }, + 'r2_tl84_tbl[23]' => { }, + 'r2_tl84_tbl[24]' => { }, + 'r2_tl84_tbl[25]' => { }, + 'r2_tl84_tbl[26]' => { }, + 'r2_tl84_tbl[27]' => { }, + 'r2_tl84_tbl[28]' => { }, + 'r2_tl84_tbl[29]' => { }, + 'r2_tl84_tbl[30]' => { }, + 'r2_tl84_tbl[31]' => { }, + 'r2_tl84_red_ctbl[0]' => { }, + 'r2_tl84_red_ctbl[1]' => { }, + 'r2_tl84_red_ctbl[2]' => { }, + 'r2_tl84_red_ctbl[3]' => { }, + 'r2_tl84_red_ctbl[4]' => { }, + 'r2_tl84_red_ctbl[5]' => { }, + 'r2_tl84_red_ctbl[6]' => { }, + 'r2_tl84_red_ctbl[7]' => { }, + 'r2_tl84_red_ctbl[8]' => { }, + 'r2_tl84_red_ctbl[9]' => { }, + 'r2_tl84_red_ctbl[10]' => { }, + 'r2_tl84_red_ctbl[11]' => { }, + 'r2_tl84_red_ctbl[12]' => { }, + 'r2_tl84_red_ctbl[13]' => { }, + 'r2_tl84_red_ctbl[14]' => { }, + 'r2_tl84_red_ctbl[15]' => { }, + 'r2_tl84_red_ctbl[16]' => { }, + 'r2_tl84_red_ctbl[17]' => { }, + 'r2_tl84_red_ctbl[18]' => { }, + 'r2_tl84_red_ctbl[19]' => { }, + 'r2_tl84_red_ctbl[20]' => { }, + 'r2_tl84_red_ctbl[21]' => { }, + 'r2_tl84_red_ctbl[22]' => { }, + 'r2_tl84_red_ctbl[23]' => { }, + 'r2_tl84_red_ctbl[24]' => { }, + 'r2_tl84_red_ctbl[25]' => { }, + 'r2_tl84_red_ctbl[26]' => { }, + 'r2_tl84_red_ctbl[27]' => { }, + 'r2_tl84_red_ctbl[28]' => { }, + 'r2_tl84_red_ctbl[29]' => { }, + 'r2_tl84_red_ctbl[30]' => { }, + 'r2_tl84_red_ctbl[31]' => { }, + 'r2_tl84_green_ctbl[0]' => { }, + 'r2_tl84_green_ctbl[1]' => { }, + 'r2_tl84_green_ctbl[2]' => { }, + 'r2_tl84_green_ctbl[3]' => { }, + 'r2_tl84_green_ctbl[4]' => { }, + 'r2_tl84_green_ctbl[5]' => { }, + 'r2_tl84_green_ctbl[6]' => { }, + 'r2_tl84_green_ctbl[7]' => { }, + 'r2_tl84_green_ctbl[8]' => { }, + 'r2_tl84_green_ctbl[9]' => { }, + 'r2_tl84_green_ctbl[10]' => { }, + 'r2_tl84_green_ctbl[11]' => { }, + 'r2_tl84_green_ctbl[12]' => { }, + 'r2_tl84_green_ctbl[13]' => { }, + 'r2_tl84_green_ctbl[14]' => { }, + 'r2_tl84_green_ctbl[15]' => { }, + 'r2_tl84_green_ctbl[16]' => { }, + 'r2_tl84_green_ctbl[17]' => { }, + 'r2_tl84_green_ctbl[18]' => { }, + 'r2_tl84_green_ctbl[19]' => { }, + 'r2_tl84_green_ctbl[20]' => { }, + 'r2_tl84_green_ctbl[21]' => { }, + 'r2_tl84_green_ctbl[22]' => { }, + 'r2_tl84_green_ctbl[23]' => { }, + 'r2_tl84_green_ctbl[24]' => { }, + 'r2_tl84_green_ctbl[25]' => { }, + 'r2_tl84_green_ctbl[26]' => { }, + 'r2_tl84_green_ctbl[27]' => { }, + 'r2_tl84_green_ctbl[28]' => { }, + 'r2_tl84_green_ctbl[29]' => { }, + 'r2_tl84_green_ctbl[30]' => { }, + 'r2_tl84_green_ctbl[31]' => { }, + 'r2_tl84_blue_ctbl[0]' => { }, + 'r2_tl84_blue_ctbl[1]' => { }, + 'r2_tl84_blue_ctbl[2]' => { }, + 'r2_tl84_blue_ctbl[3]' => { }, + 'r2_tl84_blue_ctbl[4]' => { }, + 'r2_tl84_blue_ctbl[5]' => { }, + 'r2_tl84_blue_ctbl[6]' => { }, + 'r2_tl84_blue_ctbl[7]' => { }, + 'r2_tl84_blue_ctbl[8]' => { }, + 'r2_tl84_blue_ctbl[9]' => { }, + 'r2_tl84_blue_ctbl[10]' => { }, + 'r2_tl84_blue_ctbl[11]' => { }, + 'r2_tl84_blue_ctbl[12]' => { }, + 'r2_tl84_blue_ctbl[13]' => { }, + 'r2_tl84_blue_ctbl[14]' => { }, + 'r2_tl84_blue_ctbl[15]' => { }, + 'r2_tl84_blue_ctbl[16]' => { }, + 'r2_tl84_blue_ctbl[17]' => { }, + 'r2_tl84_blue_ctbl[18]' => { }, + 'r2_tl84_blue_ctbl[19]' => { }, + 'r2_tl84_blue_ctbl[20]' => { }, + 'r2_tl84_blue_ctbl[21]' => { }, + 'r2_tl84_blue_ctbl[22]' => { }, + 'r2_tl84_blue_ctbl[23]' => { }, + 'r2_tl84_blue_ctbl[24]' => { }, + 'r2_tl84_blue_ctbl[25]' => { }, + 'r2_tl84_blue_ctbl[26]' => { }, + 'r2_tl84_blue_ctbl[27]' => { }, + 'r2_tl84_blue_ctbl[28]' => { }, + 'r2_tl84_blue_ctbl[29]' => { }, + 'r2_tl84_blue_ctbl[30]' => { }, + 'r2_tl84_blue_ctbl[31]' => { }, + 'r2_tl84_red_stbl[0]' => { }, + 'r2_tl84_red_stbl[1]' => { }, + 'r2_tl84_red_stbl[2]' => { }, + 'r2_tl84_red_stbl[3]' => { }, + 'r2_tl84_red_stbl[4]' => { }, + 'r2_tl84_red_stbl[5]' => { }, + 'r2_tl84_red_stbl[6]' => { }, + 'r2_tl84_red_stbl[7]' => { }, + 'r2_tl84_red_stbl[8]' => { }, + 'r2_tl84_red_stbl[9]' => { }, + 'r2_tl84_red_stbl[10]' => { }, + 'r2_tl84_red_stbl[11]' => { }, + 'r2_tl84_red_stbl[12]' => { }, + 'r2_tl84_red_stbl[13]' => { }, + 'r2_tl84_red_stbl[14]' => { }, + 'r2_tl84_red_stbl[15]' => { }, + 'r2_tl84_red_stbl[16]' => { }, + 'r2_tl84_red_stbl[17]' => { }, + 'r2_tl84_red_stbl[18]' => { }, + 'r2_tl84_red_stbl[19]' => { }, + 'r2_tl84_red_stbl[20]' => { }, + 'r2_tl84_red_stbl[21]' => { }, + 'r2_tl84_red_stbl[22]' => { }, + 'r2_tl84_red_stbl[23]' => { }, + 'r2_tl84_red_stbl[24]' => { }, + 'r2_tl84_red_stbl[25]' => { }, + 'r2_tl84_red_stbl[26]' => { }, + 'r2_tl84_red_stbl[27]' => { }, + 'r2_tl84_red_stbl[28]' => { }, + 'r2_tl84_red_stbl[29]' => { }, + 'r2_tl84_red_stbl[30]' => { }, + 'r2_tl84_red_stbl[31]' => { }, + 'r2_tl84_blue_stbl[0]' => { }, + 'r2_tl84_blue_stbl[1]' => { }, + 'r2_tl84_blue_stbl[2]' => { }, + 'r2_tl84_blue_stbl[3]' => { }, + 'r2_tl84_blue_stbl[4]' => { }, + 'r2_tl84_blue_stbl[5]' => { }, + 'r2_tl84_blue_stbl[6]' => { }, + 'r2_tl84_blue_stbl[7]' => { }, + 'r2_tl84_blue_stbl[8]' => { }, + 'r2_tl84_blue_stbl[9]' => { }, + 'r2_tl84_blue_stbl[10]' => { }, + 'r2_tl84_blue_stbl[11]' => { }, + 'r2_tl84_blue_stbl[12]' => { }, + 'r2_tl84_blue_stbl[13]' => { }, + 'r2_tl84_blue_stbl[14]' => { }, + 'r2_tl84_blue_stbl[15]' => { }, + 'r2_tl84_blue_stbl[16]' => { }, + 'r2_tl84_blue_stbl[17]' => { }, + 'r2_tl84_blue_stbl[18]' => { }, + 'r2_tl84_blue_stbl[19]' => { }, + 'r2_tl84_blue_stbl[20]' => { }, + 'r2_tl84_blue_stbl[21]' => { }, + 'r2_tl84_blue_stbl[22]' => { }, + 'r2_tl84_blue_stbl[23]' => { }, + 'r2_tl84_blue_stbl[24]' => { }, + 'r2_tl84_blue_stbl[25]' => { }, + 'r2_tl84_blue_stbl[26]' => { }, + 'r2_tl84_blue_stbl[27]' => { }, + 'r2_tl84_blue_stbl[28]' => { }, + 'r2_tl84_blue_stbl[29]' => { }, + 'r2_tl84_blue_stbl[30]' => { }, + 'r2_tl84_blue_stbl[31]' => { }, + 'r2_tl84_green_stbl[0]' => { }, + 'r2_tl84_green_stbl[1]' => { }, + 'r2_tl84_green_stbl[2]' => { }, + 'r2_tl84_green_stbl[3]' => { }, + 'r2_tl84_green_stbl[4]' => { }, + 'r2_tl84_green_stbl[5]' => { }, + 'r2_tl84_green_stbl[6]' => { }, + 'r2_tl84_green_stbl[7]' => { }, + 'r2_tl84_green_stbl[8]' => { }, + 'r2_tl84_green_stbl[9]' => { }, + 'r2_tl84_green_stbl[10]' => { }, + 'r2_tl84_green_stbl[11]' => { }, + 'r2_tl84_green_stbl[12]' => { }, + 'r2_tl84_green_stbl[13]' => { }, + 'r2_tl84_green_stbl[14]' => { }, + 'r2_tl84_green_stbl[15]' => { }, + 'r2_tl84_green_stbl[16]' => { }, + 'r2_tl84_green_stbl[17]' => { }, + 'r2_tl84_green_stbl[18]' => { }, + 'r2_tl84_green_stbl[19]' => { }, + 'r2_tl84_green_stbl[20]' => { }, + 'r2_tl84_green_stbl[21]' => { }, + 'r2_tl84_green_stbl[22]' => { }, + 'r2_tl84_green_stbl[23]' => { }, + 'r2_tl84_green_stbl[24]' => { }, + 'r2_tl84_green_stbl[25]' => { }, + 'r2_tl84_green_stbl[26]' => { }, + 'r2_tl84_green_stbl[27]' => { }, + 'r2_tl84_green_stbl[28]' => { }, + 'r2_tl84_green_stbl[29]' => { }, + 'r2_tl84_green_stbl[30]' => { }, + 'r2_tl84_green_stbl[31]' => { }, + 'r2_d65_cx' => { }, + 'r2_d65_cy' => { }, + 'r2_d65_width' => { }, + 'r2_d65_height' => { }, + 'r2_d65_intervals' => { }, + 'r2_d65_tbl[0]' => { }, + 'r2_d65_tbl[1]' => { }, + 'r2_d65_tbl[2]' => { }, + 'r2_d65_tbl[3]' => { }, + 'r2_d65_tbl[4]' => { }, + 'r2_d65_tbl[5]' => { }, + 'r2_d65_tbl[6]' => { }, + 'r2_d65_tbl[7]' => { }, + 'r2_d65_tbl[8]' => { }, + 'r2_d65_tbl[9]' => { }, + 'r2_d65_tbl[10]' => { }, + 'r2_d65_tbl[11]' => { }, + 'r2_d65_tbl[12]' => { }, + 'r2_d65_tbl[13]' => { }, + 'r2_d65_tbl[14]' => { }, + 'r2_d65_tbl[15]' => { }, + 'r2_d65_tbl[16]' => { }, + 'r2_d65_tbl[17]' => { }, + 'r2_d65_tbl[18]' => { }, + 'r2_d65_tbl[19]' => { }, + 'r2_d65_tbl[20]' => { }, + 'r2_d65_tbl[21]' => { }, + 'r2_d65_tbl[22]' => { }, + 'r2_d65_tbl[23]' => { }, + 'r2_d65_tbl[24]' => { }, + 'r2_d65_tbl[25]' => { }, + 'r2_d65_tbl[26]' => { }, + 'r2_d65_tbl[27]' => { }, + 'r2_d65_tbl[28]' => { }, + 'r2_d65_tbl[29]' => { }, + 'r2_d65_tbl[30]' => { }, + 'r2_d65_tbl[31]' => { }, + 'r2_d65_red_ctbl[0]' => { }, + 'r2_d65_red_ctbl[1]' => { }, + 'r2_d65_red_ctbl[2]' => { }, + 'r2_d65_red_ctbl[3]' => { }, + 'r2_d65_red_ctbl[4]' => { }, + 'r2_d65_red_ctbl[5]' => { }, + 'r2_d65_red_ctbl[6]' => { }, + 'r2_d65_red_ctbl[7]' => { }, + 'r2_d65_red_ctbl[8]' => { }, + 'r2_d65_red_ctbl[9]' => { }, + 'r2_d65_red_ctbl[10]' => { }, + 'r2_d65_red_ctbl[11]' => { }, + 'r2_d65_red_ctbl[12]' => { }, + 'r2_d65_red_ctbl[13]' => { }, + 'r2_d65_red_ctbl[14]' => { }, + 'r2_d65_red_ctbl[15]' => { }, + 'r2_d65_red_ctbl[16]' => { }, + 'r2_d65_red_ctbl[17]' => { }, + 'r2_d65_red_ctbl[18]' => { }, + 'r2_d65_red_ctbl[19]' => { }, + 'r2_d65_red_ctbl[20]' => { }, + 'r2_d65_red_ctbl[21]' => { }, + 'r2_d65_red_ctbl[22]' => { }, + 'r2_d65_red_ctbl[23]' => { }, + 'r2_d65_red_ctbl[24]' => { }, + 'r2_d65_red_ctbl[25]' => { }, + 'r2_d65_red_ctbl[26]' => { }, + 'r2_d65_red_ctbl[27]' => { }, + 'r2_d65_red_ctbl[28]' => { }, + 'r2_d65_red_ctbl[29]' => { }, + 'r2_d65_red_ctbl[30]' => { }, + 'r2_d65_red_ctbl[31]' => { }, + 'r2_d65_green_ctbl[0]' => { }, + 'r2_d65_green_ctbl[1]' => { }, + 'r2_d65_green_ctbl[2]' => { }, + 'r2_d65_green_ctbl[3]' => { }, + 'r2_d65_green_ctbl[4]' => { }, + 'r2_d65_green_ctbl[5]' => { }, + 'r2_d65_green_ctbl[6]' => { }, + 'r2_d65_green_ctbl[7]' => { }, + 'r2_d65_green_ctbl[8]' => { }, + 'r2_d65_green_ctbl[9]' => { }, + 'r2_d65_green_ctbl[10]' => { }, + 'r2_d65_green_ctbl[11]' => { }, + 'r2_d65_green_ctbl[12]' => { }, + 'r2_d65_green_ctbl[13]' => { }, + 'r2_d65_green_ctbl[14]' => { }, + 'r2_d65_green_ctbl[15]' => { }, + 'r2_d65_green_ctbl[16]' => { }, + 'r2_d65_green_ctbl[17]' => { }, + 'r2_d65_green_ctbl[18]' => { }, + 'r2_d65_green_ctbl[19]' => { }, + 'r2_d65_green_ctbl[20]' => { }, + 'r2_d65_green_ctbl[21]' => { }, + 'r2_d65_green_ctbl[22]' => { }, + 'r2_d65_green_ctbl[23]' => { }, + 'r2_d65_green_ctbl[24]' => { }, + 'r2_d65_green_ctbl[25]' => { }, + 'r2_d65_green_ctbl[26]' => { }, + 'r2_d65_green_ctbl[27]' => { }, + 'r2_d65_green_ctbl[28]' => { }, + 'r2_d65_green_ctbl[29]' => { }, + 'r2_d65_green_ctbl[30]' => { }, + 'r2_d65_green_ctbl[31]' => { }, + 'r2_d65_blue_ctbl[0]' => { }, + 'r2_d65_blue_ctbl[1]' => { }, + 'r2_d65_blue_ctbl[2]' => { }, + 'r2_d65_blue_ctbl[3]' => { }, + 'r2_d65_blue_ctbl[4]' => { }, + 'r2_d65_blue_ctbl[5]' => { }, + 'r2_d65_blue_ctbl[6]' => { }, + 'r2_d65_blue_ctbl[7]' => { }, + 'r2_d65_blue_ctbl[8]' => { }, + 'r2_d65_blue_ctbl[9]' => { }, + 'r2_d65_blue_ctbl[10]' => { }, + 'r2_d65_blue_ctbl[11]' => { }, + 'r2_d65_blue_ctbl[12]' => { }, + 'r2_d65_blue_ctbl[13]' => { }, + 'r2_d65_blue_ctbl[14]' => { }, + 'r2_d65_blue_ctbl[15]' => { }, + 'r2_d65_blue_ctbl[16]' => { }, + 'r2_d65_blue_ctbl[17]' => { }, + 'r2_d65_blue_ctbl[18]' => { }, + 'r2_d65_blue_ctbl[19]' => { }, + 'r2_d65_blue_ctbl[20]' => { }, + 'r2_d65_blue_ctbl[21]' => { }, + 'r2_d65_blue_ctbl[22]' => { }, + 'r2_d65_blue_ctbl[23]' => { }, + 'r2_d65_blue_ctbl[24]' => { }, + 'r2_d65_blue_ctbl[25]' => { }, + 'r2_d65_blue_ctbl[26]' => { }, + 'r2_d65_blue_ctbl[27]' => { }, + 'r2_d65_blue_ctbl[28]' => { }, + 'r2_d65_blue_ctbl[29]' => { }, + 'r2_d65_blue_ctbl[30]' => { }, + 'r2_d65_blue_ctbl[31]' => { }, + 'r2_d65_red_stbl[0]' => { }, + 'r2_d65_red_stbl[1]' => { }, + 'r2_d65_red_stbl[2]' => { }, + 'r2_d65_red_stbl[3]' => { }, + 'r2_d65_red_stbl[4]' => { }, + 'r2_d65_red_stbl[5]' => { }, + 'r2_d65_red_stbl[6]' => { }, + 'r2_d65_red_stbl[7]' => { }, + 'r2_d65_red_stbl[8]' => { }, + 'r2_d65_red_stbl[9]' => { }, + 'r2_d65_red_stbl[10]' => { }, + 'r2_d65_red_stbl[11]' => { }, + 'r2_d65_red_stbl[12]' => { }, + 'r2_d65_red_stbl[13]' => { }, + 'r2_d65_red_stbl[14]' => { }, + 'r2_d65_red_stbl[15]' => { }, + 'r2_d65_red_stbl[16]' => { }, + 'r2_d65_red_stbl[17]' => { }, + 'r2_d65_red_stbl[18]' => { }, + 'r2_d65_red_stbl[19]' => { }, + 'r2_d65_red_stbl[20]' => { }, + 'r2_d65_red_stbl[21]' => { }, + 'r2_d65_red_stbl[22]' => { }, + 'r2_d65_red_stbl[23]' => { }, + 'r2_d65_red_stbl[24]' => { }, + 'r2_d65_red_stbl[25]' => { }, + 'r2_d65_red_stbl[26]' => { }, + 'r2_d65_red_stbl[27]' => { }, + 'r2_d65_red_stbl[28]' => { }, + 'r2_d65_red_stbl[29]' => { }, + 'r2_d65_red_stbl[30]' => { }, + 'r2_d65_red_stbl[31]' => { }, + 'r2_d65_blue_stbl[0]' => { }, + 'r2_d65_blue_stbl[1]' => { }, + 'r2_d65_blue_stbl[2]' => { }, + 'r2_d65_blue_stbl[3]' => { }, + 'r2_d65_blue_stbl[4]' => { }, + 'r2_d65_blue_stbl[5]' => { }, + 'r2_d65_blue_stbl[6]' => { }, + 'r2_d65_blue_stbl[7]' => { }, + 'r2_d65_blue_stbl[8]' => { }, + 'r2_d65_blue_stbl[9]' => { }, + 'r2_d65_blue_stbl[10]' => { }, + 'r2_d65_blue_stbl[11]' => { }, + 'r2_d65_blue_stbl[12]' => { }, + 'r2_d65_blue_stbl[13]' => { }, + 'r2_d65_blue_stbl[14]' => { }, + 'r2_d65_blue_stbl[15]' => { }, + 'r2_d65_blue_stbl[16]' => { }, + 'r2_d65_blue_stbl[17]' => { }, + 'r2_d65_blue_stbl[18]' => { }, + 'r2_d65_blue_stbl[19]' => { }, + 'r2_d65_blue_stbl[20]' => { }, + 'r2_d65_blue_stbl[21]' => { }, + 'r2_d65_blue_stbl[22]' => { }, + 'r2_d65_blue_stbl[23]' => { }, + 'r2_d65_blue_stbl[24]' => { }, + 'r2_d65_blue_stbl[25]' => { }, + 'r2_d65_blue_stbl[26]' => { }, + 'r2_d65_blue_stbl[27]' => { }, + 'r2_d65_blue_stbl[28]' => { }, + 'r2_d65_blue_stbl[29]' => { }, + 'r2_d65_blue_stbl[30]' => { }, + 'r2_d65_blue_stbl[31]' => { }, + 'r2_d65_green_stbl[0]' => { }, + 'r2_d65_green_stbl[1]' => { }, + 'r2_d65_green_stbl[2]' => { }, + 'r2_d65_green_stbl[3]' => { }, + 'r2_d65_green_stbl[4]' => { }, + 'r2_d65_green_stbl[5]' => { }, + 'r2_d65_green_stbl[6]' => { }, + 'r2_d65_green_stbl[7]' => { }, + 'r2_d65_green_stbl[8]' => { }, + 'r2_d65_green_stbl[9]' => { }, + 'r2_d65_green_stbl[10]' => { }, + 'r2_d65_green_stbl[11]' => { }, + 'r2_d65_green_stbl[12]' => { }, + 'r2_d65_green_stbl[13]' => { }, + 'r2_d65_green_stbl[14]' => { }, + 'r2_d65_green_stbl[15]' => { }, + 'r2_d65_green_stbl[16]' => { }, + 'r2_d65_green_stbl[17]' => { }, + 'r2_d65_green_stbl[18]' => { }, + 'r2_d65_green_stbl[19]' => { }, + 'r2_d65_green_stbl[20]' => { }, + 'r2_d65_green_stbl[21]' => { }, + 'r2_d65_green_stbl[22]' => { }, + 'r2_d65_green_stbl[23]' => { }, + 'r2_d65_green_stbl[24]' => { }, + 'r2_d65_green_stbl[25]' => { }, + 'r2_d65_green_stbl[26]' => { }, + 'r2_d65_green_stbl[27]' => { }, + 'r2_d65_green_stbl[28]' => { }, + 'r2_d65_green_stbl[29]' => { }, + 'r2_d65_green_stbl[30]' => { }, + 'r2_d65_green_stbl[31]' => { }, + 'r2_a_cx' => { }, + 'r2_a_cy' => { }, + 'r2_a_width' => { }, + 'r2_a_height' => { }, + 'r2_a_intervals' => { }, + 'r2_a_tbl[0]' => { }, + 'r2_a_tbl[1]' => { }, + 'r2_a_tbl[2]' => { }, + 'r2_a_tbl[3]' => { }, + 'r2_a_tbl[4]' => { }, + 'r2_a_tbl[5]' => { }, + 'r2_a_tbl[6]' => { }, + 'r2_a_tbl[7]' => { }, + 'r2_a_tbl[8]' => { }, + 'r2_a_tbl[9]' => { }, + 'r2_a_tbl[10]' => { }, + 'r2_a_tbl[11]' => { }, + 'r2_a_tbl[12]' => { }, + 'r2_a_tbl[13]' => { }, + 'r2_a_tbl[14]' => { }, + 'r2_a_tbl[15]' => { }, + 'r2_a_tbl[16]' => { }, + 'r2_a_tbl[17]' => { }, + 'r2_a_tbl[18]' => { }, + 'r2_a_tbl[19]' => { }, + 'r2_a_tbl[20]' => { }, + 'r2_a_tbl[21]' => { }, + 'r2_a_tbl[22]' => { }, + 'r2_a_tbl[23]' => { }, + 'r2_a_tbl[24]' => { }, + 'r2_a_tbl[25]' => { }, + 'r2_a_tbl[26]' => { }, + 'r2_a_tbl[27]' => { }, + 'r2_a_tbl[28]' => { }, + 'r2_a_tbl[29]' => { }, + 'r2_a_tbl[30]' => { }, + 'r2_a_tbl[31]' => { }, + 'r2_a_red_ctbl[0]' => { }, + 'r2_a_red_ctbl[1]' => { }, + 'r2_a_red_ctbl[2]' => { }, + 'r2_a_red_ctbl[3]' => { }, + 'r2_a_red_ctbl[4]' => { }, + 'r2_a_red_ctbl[5]' => { }, + 'r2_a_red_ctbl[6]' => { }, + 'r2_a_red_ctbl[7]' => { }, + 'r2_a_red_ctbl[8]' => { }, + 'r2_a_red_ctbl[9]' => { }, + 'r2_a_red_ctbl[10]' => { }, + 'r2_a_red_ctbl[11]' => { }, + 'r2_a_red_ctbl[12]' => { }, + 'r2_a_red_ctbl[13]' => { }, + 'r2_a_red_ctbl[14]' => { }, + 'r2_a_red_ctbl[15]' => { }, + 'r2_a_red_ctbl[16]' => { }, + 'r2_a_red_ctbl[17]' => { }, + 'r2_a_red_ctbl[18]' => { }, + 'r2_a_red_ctbl[19]' => { }, + 'r2_a_red_ctbl[20]' => { }, + 'r2_a_red_ctbl[21]' => { }, + 'r2_a_red_ctbl[22]' => { }, + 'r2_a_red_ctbl[23]' => { }, + 'r2_a_red_ctbl[24]' => { }, + 'r2_a_red_ctbl[25]' => { }, + 'r2_a_red_ctbl[26]' => { }, + 'r2_a_red_ctbl[27]' => { }, + 'r2_a_red_ctbl[28]' => { }, + 'r2_a_red_ctbl[29]' => { }, + 'r2_a_red_ctbl[30]' => { }, + 'r2_a_red_ctbl[31]' => { }, + 'r2_a_green_ctbl[0]' => { }, + 'r2_a_green_ctbl[1]' => { }, + 'r2_a_green_ctbl[2]' => { }, + 'r2_a_green_ctbl[3]' => { }, + 'r2_a_green_ctbl[4]' => { }, + 'r2_a_green_ctbl[5]' => { }, + 'r2_a_green_ctbl[6]' => { }, + 'r2_a_green_ctbl[7]' => { }, + 'r2_a_green_ctbl[8]' => { }, + 'r2_a_green_ctbl[9]' => { }, + 'r2_a_green_ctbl[10]' => { }, + 'r2_a_green_ctbl[11]' => { }, + 'r2_a_green_ctbl[12]' => { }, + 'r2_a_green_ctbl[13]' => { }, + 'r2_a_green_ctbl[14]' => { }, + 'r2_a_green_ctbl[15]' => { }, + 'r2_a_green_ctbl[16]' => { }, + 'r2_a_green_ctbl[17]' => { }, + 'r2_a_green_ctbl[18]' => { }, + 'r2_a_green_ctbl[19]' => { }, + 'r2_a_green_ctbl[20]' => { }, + 'r2_a_green_ctbl[21]' => { }, + 'r2_a_green_ctbl[22]' => { }, + 'r2_a_green_ctbl[23]' => { }, + 'r2_a_green_ctbl[24]' => { }, + 'r2_a_green_ctbl[25]' => { }, + 'r2_a_green_ctbl[26]' => { }, + 'r2_a_green_ctbl[27]' => { }, + 'r2_a_green_ctbl[28]' => { }, + 'r2_a_green_ctbl[29]' => { }, + 'r2_a_green_ctbl[30]' => { }, + 'r2_a_green_ctbl[31]' => { }, + 'r2_a_blue_ctbl[0]' => { }, + 'r2_a_blue_ctbl[1]' => { }, + 'r2_a_blue_ctbl[2]' => { }, + 'r2_a_blue_ctbl[3]' => { }, + 'r2_a_blue_ctbl[4]' => { }, + 'r2_a_blue_ctbl[5]' => { }, + 'r2_a_blue_ctbl[6]' => { }, + 'r2_a_blue_ctbl[7]' => { }, + 'r2_a_blue_ctbl[8]' => { }, + 'r2_a_blue_ctbl[9]' => { }, + 'r2_a_blue_ctbl[10]' => { }, + 'r2_a_blue_ctbl[11]' => { }, + 'r2_a_blue_ctbl[12]' => { }, + 'r2_a_blue_ctbl[13]' => { }, + 'r2_a_blue_ctbl[14]' => { }, + 'r2_a_blue_ctbl[15]' => { }, + 'r2_a_blue_ctbl[16]' => { }, + 'r2_a_blue_ctbl[17]' => { }, + 'r2_a_blue_ctbl[18]' => { }, + 'r2_a_blue_ctbl[19]' => { }, + 'r2_a_blue_ctbl[20]' => { }, + 'r2_a_blue_ctbl[21]' => { }, + 'r2_a_blue_ctbl[22]' => { }, + 'r2_a_blue_ctbl[23]' => { }, + 'r2_a_blue_ctbl[24]' => { }, + 'r2_a_blue_ctbl[25]' => { }, + 'r2_a_blue_ctbl[26]' => { }, + 'r2_a_blue_ctbl[27]' => { }, + 'r2_a_blue_ctbl[28]' => { }, + 'r2_a_blue_ctbl[29]' => { }, + 'r2_a_blue_ctbl[30]' => { }, + 'r2_a_blue_ctbl[31]' => { }, + 'r2_a_red_stbl[0]' => { }, + 'r2_a_red_stbl[1]' => { }, + 'r2_a_red_stbl[2]' => { }, + 'r2_a_red_stbl[3]' => { }, + 'r2_a_red_stbl[4]' => { }, + 'r2_a_red_stbl[5]' => { }, + 'r2_a_red_stbl[6]' => { }, + 'r2_a_red_stbl[7]' => { }, + 'r2_a_red_stbl[8]' => { }, + 'r2_a_red_stbl[9]' => { }, + 'r2_a_red_stbl[10]' => { }, + 'r2_a_red_stbl[11]' => { }, + 'r2_a_red_stbl[12]' => { }, + 'r2_a_red_stbl[13]' => { }, + 'r2_a_red_stbl[14]' => { }, + 'r2_a_red_stbl[15]' => { }, + 'r2_a_red_stbl[16]' => { }, + 'r2_a_red_stbl[17]' => { }, + 'r2_a_red_stbl[18]' => { }, + 'r2_a_red_stbl[19]' => { }, + 'r2_a_red_stbl[20]' => { }, + 'r2_a_red_stbl[21]' => { }, + 'r2_a_red_stbl[22]' => { }, + 'r2_a_red_stbl[23]' => { }, + 'r2_a_red_stbl[24]' => { }, + 'r2_a_red_stbl[25]' => { }, + 'r2_a_red_stbl[26]' => { }, + 'r2_a_red_stbl[27]' => { }, + 'r2_a_red_stbl[28]' => { }, + 'r2_a_red_stbl[29]' => { }, + 'r2_a_red_stbl[30]' => { }, + 'r2_a_red_stbl[31]' => { }, + 'r2_a_blue_stbl[0]' => { }, + 'r2_a_blue_stbl[1]' => { }, + 'r2_a_blue_stbl[2]' => { }, + 'r2_a_blue_stbl[3]' => { }, + 'r2_a_blue_stbl[4]' => { }, + 'r2_a_blue_stbl[5]' => { }, + 'r2_a_blue_stbl[6]' => { }, + 'r2_a_blue_stbl[7]' => { }, + 'r2_a_blue_stbl[8]' => { }, + 'r2_a_blue_stbl[9]' => { }, + 'r2_a_blue_stbl[10]' => { }, + 'r2_a_blue_stbl[11]' => { }, + 'r2_a_blue_stbl[12]' => { }, + 'r2_a_blue_stbl[13]' => { }, + 'r2_a_blue_stbl[14]' => { }, + 'r2_a_blue_stbl[15]' => { }, + 'r2_a_blue_stbl[16]' => { }, + 'r2_a_blue_stbl[17]' => { }, + 'r2_a_blue_stbl[18]' => { }, + 'r2_a_blue_stbl[19]' => { }, + 'r2_a_blue_stbl[20]' => { }, + 'r2_a_blue_stbl[21]' => { }, + 'r2_a_blue_stbl[22]' => { }, + 'r2_a_blue_stbl[23]' => { }, + 'r2_a_blue_stbl[24]' => { }, + 'r2_a_blue_stbl[25]' => { }, + 'r2_a_blue_stbl[26]' => { }, + 'r2_a_blue_stbl[27]' => { }, + 'r2_a_blue_stbl[28]' => { }, + 'r2_a_blue_stbl[29]' => { }, + 'r2_a_blue_stbl[30]' => { }, + 'r2_a_blue_stbl[31]' => { }, + 'r2_a_green_stbl[0]' => { }, + 'r2_a_green_stbl[1]' => { }, + 'r2_a_green_stbl[2]' => { }, + 'r2_a_green_stbl[3]' => { }, + 'r2_a_green_stbl[4]' => { }, + 'r2_a_green_stbl[5]' => { }, + 'r2_a_green_stbl[6]' => { }, + 'r2_a_green_stbl[7]' => { }, + 'r2_a_green_stbl[8]' => { }, + 'r2_a_green_stbl[9]' => { }, + 'r2_a_green_stbl[10]' => { }, + 'r2_a_green_stbl[11]' => { }, + 'r2_a_green_stbl[12]' => { }, + 'r2_a_green_stbl[13]' => { }, + 'r2_a_green_stbl[14]' => { }, + 'r2_a_green_stbl[15]' => { }, + 'r2_a_green_stbl[16]' => { }, + 'r2_a_green_stbl[17]' => { }, + 'r2_a_green_stbl[18]' => { }, + 'r2_a_green_stbl[19]' => { }, + 'r2_a_green_stbl[20]' => { }, + 'r2_a_green_stbl[21]' => { }, + 'r2_a_green_stbl[22]' => { }, + 'r2_a_green_stbl[23]' => { }, + 'r2_a_green_stbl[24]' => { }, + 'r2_a_green_stbl[25]' => { }, + 'r2_a_green_stbl[26]' => { }, + 'r2_a_green_stbl[27]' => { }, + 'r2_a_green_stbl[28]' => { }, + 'r2_a_green_stbl[29]' => { }, + 'r2_a_green_stbl[30]' => { }, + 'r2_a_green_stbl[31]' => { }, + 'def_cor_c0' => { }, + 'def_cor_c1' => { }, + 'def_cor_c2' => { }, + 'def_cor_c3' => { }, + 'def_cor_c4' => { }, + 'def_cor_c5' => { }, + 'def_cor_c6' => { }, + 'def_cor_c7' => { }, + 'def_cor_c8' => { }, + 'def_cor_k0' => { }, + 'def_cor_k1' => { }, + 'def_cor_k2' => { }, + 'yhi_ylo_cor_c0' => { }, + 'yhi_ylo_cor_c1' => { }, + 'yhi_ylo_cor_c2' => { }, + 'yhi_ylo_cor_c3' => { }, + 'yhi_ylo_cor_c4' => { }, + 'yhi_ylo_cor_c5' => { }, + 'yhi_ylo_cor_c6' => { }, + 'yhi_ylo_cor_c7' => { }, + 'yhi_ylo_cor_c8' => { }, + 'yhi_ylo_cor_k0' => { }, + 'yhi_ylo_cor_k1' => { }, + 'yhi_ylo_cor_k2' => { }, + 'def_conv_chrm_a_m' => { }, + 'def_conv_chrm_a_p' => { }, + 'def_conv_chrm_b_m' => { }, + 'def_conv_chrm_b_p' => { }, + 'def_conv_chrm_c_m' => { }, + 'def_conv_chrm_c_p' => { }, + 'def_conv_chrm_d_m' => { }, + 'def_conv_chrm_d_p' => { }, + 'def_conv_chrm_k_cb' => { }, + 'def_conv_chrm_k_cr' => { }, + 'def_conv_luma_v0' => { }, + 'def_conv_luma_v1' => { }, + 'def_conv_luma_v2' => { }, + 'def_conv_luma_k' => { }, + 'tl84_conv_chrm_a_m' => { }, + 'tl84_conv_chrm_a_p' => { }, + 'tl84_conv_chrm_b_m' => { }, + 'tl84_conv_chrm_b_p' => { }, + 'tl84_conv_chrm_c_m' => { }, + 'tl84_conv_chrm_c_p' => { }, + 'tl84_conv_chrm_d_m' => { }, + 'tl84_conv_chrm_d_p' => { }, + 'tl84_conv_chrm_k_cb' => { }, + 'tl84_conv_chrm_k_cr' => { }, + 'tl84_conv_luma_v0' => { }, + 'tl84_conv_luma_v1' => { }, + 'tl84_conv_luma_v2' => { }, + 'tl84_conv_luma_k' => { }, + 'incand_conv_chrm_a_m' => { }, + 'incand_conv_chrm_a_p' => { }, + 'incand_conv_chrm_b_m' => { }, + 'incand_conv_chrm_b_p' => { }, + 'incand_conv_chrm_c_m' => { }, + 'incand_conv_chrm_c_p' => { }, + 'incand_conv_chrm_d_m' => { }, + 'incand_conv_chrm_d_p' => { }, + 'incand_conv_chrm_k_cb' => { }, + 'incand_conv_chrm_k_cr' => { }, + 'incand_conv_luma_v0' => { }, + 'incand_conv_luma_v1' => { }, + 'incand_conv_luma_v2' => { }, + 'incand_conv_luma_k' => { }, + 'daylt_conv_chrm_a_m' => { }, + 'daylt_conv_chrm_a_p' => { }, + 'daylt_conv_chrm_b_m' => { }, + 'daylt_conv_chrm_b_p' => { }, + 'daylt_conv_chrm_c_m' => { }, + 'daylt_conv_chrm_c_p' => { }, + 'daylt_conv_chrm_d_m' => { }, + 'daylt_conv_chrm_d_p' => { }, + 'daylt_conv_chrm_k_cb' => { }, + 'daylt_conv_chrm_k_cr' => { }, + 'daylt_conv_luma_v0' => { }, + 'daylt_conv_luma_v1' => { }, + 'daylt_conv_luma_v2' => { }, + 'daylt_conv_luma_k' => { }, + 'yhi_ylo_conv_chrm_a_m' => { }, + 'yhi_ylo_conv_chrm_a_p' => { }, + 'yhi_ylo_conv_chrm_b_m' => { }, + 'yhi_ylo_conv_chrm_b_p' => { }, + 'yhi_ylo_conv_chrm_c_m' => { }, + 'yhi_ylo_conv_chrm_c_p' => { }, + 'yhi_ylo_conv_chrm_d_m' => { }, + 'yhi_ylo_conv_chrm_d_p' => { }, + 'yhi_ylo_conv_chrm_k_cb' => { }, + 'yhi_ylo_conv_chrm_k_cr' => { }, + 'yhi_ylo_conv_luma_v0' => { }, + 'yhi_ylo_conv_luma_v1' => { }, + 'yhi_ylo_conv_luma_v2' => { }, + 'yhi_ylo_conv_luma_k' => { }, + 'gamma_enable' => { }, + 'def_luma_gamma_mode' => { }, + 'def_rgb_gamma_mode' => { }, + 'blck_lvl_even_cols' => { }, + 'blck_lvl_odd_cols' => { }, + 'defect_pix_min_thresh' => { }, + 'defect_pix_max_thresh' => { }, + 'defect_pix_cor_enable' => { }, + 'prview_resol' => { }, + 'snapshot_resol' => { }, + 'curr_resol' => { }, + 'sensor_fmt' => { }, + 'discard_frst_frm' => { }, + 'frm_skip_pttrn' => { }, + 'sensor_type' => { }, + 'max_video_fps' => { }, + 'video_fps' => { }, + 'max_prview_fps' => { }, + 'prview_fps' => { }, + 'nghtsht_fps' => { }, + 'sensr_ful_wdth' => { }, + 'sensr_ful_hght' => { }, + 'sensr_qtr_wdth' => { }, + 'sensr_qtr_hght' => { }, + 'nightshot_mode' => { }, + 'pclk_invert' => { }, + 'cam_mclk_hz' => { }, + 'chrom_supress' => { }, + 'chro_sup_luma_thres_1' => { }, + 'chro_sup_luma_thres_2' => { }, + 'chro_sup_luma_thres_3' => { }, + 'chro_sup_luma_thres_4' => { }, + 'chro_sup_chro_thres_1' => { }, + 'chro_sup_chro_thres_2' => { }, + 'la_detect' => { }, + 'la_enable' => { }, + 'HJR_enable' => { }, + 'HJR_max_num_frames' => { }, + 'HJR_one_to_two_offset' => { }, + 'HJR_n_reduction_flat' => { }, + 'HJR_n_reduction_texture' => { }, + 'HJR_texture_threshold' => { }, +); + +# generate tag names and descriptions +{ + local $_; + my $table = \%Image::ExifTool::Qualcomm::Main; + MakeNameAndDesc($_, $$table{$_}) foreach TagTableKeys($table); +} + +#------------------------------------------------------------------------------ +# Generate tag Name and Description from a Qualcomm tag ID +# Inputs: 0) tag ID, 1) tagInfo ref +# Returns: true on success +sub MakeNameAndDesc($$) +{ + local $_ = shift; + my $tagInfo = shift; + # capitalize various leading acronyms or just first letter... + s/^(asf|awb|aec|afr|af_|la_|r2_tl|tl)/\U$1/ or $_ = ucfirst; + s/_([a-z])/_\u$1/g; # capitalize first letter of each word + s/\[(\d+)\]$/sprintf("_%.2d",$1)/e; # use 2-digit subscripts (and remove brackets) + tr/-_a-zA-Z0-9//dc; # delete invalid characters + my $desc = $_; + # convert underlines to spaces in description + if ($desc =~ tr/_/ /) { + # remove unnecessary underlines from tag name... + s/_([A-Z][a-z])/$1/g; + s/([a-z0-9])_([A-Z])/$1$2/g; + s/([A-Za-z])_(\d)/$1$2/g; + } + return 0 unless length; + $$tagInfo{Name} = $_; + $$tagInfo{Description} = $desc; + return 1; +} + +#------------------------------------------------------------------------------ +# Process Qualcomm APP7 metadata (ref PH) +# Inputs: 0) ExifTool object ref, 1) dirInfo ref, 2) tag table ref +# Returns: 1 on success +sub ProcessQualcomm($$$) +{ + my ($et, $dirInfo, $tagTablePtr) = @_; + my $dataPt = $$dirInfo{DataPt}; + my $dataPos = $$dirInfo{DataPos}; + my $pos = $$dirInfo{DirStart}; + my $dirEnd = $pos + $$dirInfo{DirLen}; + + $et->VerboseDir('Qualcomm', undef, $$dirInfo{DirLen}); + SetByteOrder('II'); + + while ($pos + 3 < $dirEnd) { + my $valLen = Get16u($dataPt, $pos); + my $tagLen = Get8u($dataPt, $pos + 2); + last if $pos + 8 + $tagLen + $valLen > $dirEnd; + my $tag = substr($$dataPt, $pos + 3, $tagLen); + $pos += 3 + $tagLen; # point to format byte + my $fmt = Get8u($dataPt, $pos); + # (not sure what these counts are for -- both are always 1 in my samples) + #my $cnt1 = Get16u($dataPt, $pos + 1); + #my $cnt2 = Get16u($dataPt, $pos + 3); + $pos += 5; # point to start of value data + my ($val, $format); + if ($fmt <= 7) { + $format = $qualcommFormat[$fmt]; + $val = ReadValue($dataPt, $pos, $format, undef, $valLen); + } else { + $format = "format $fmt"; + my $value = substr($$dataPt, $pos, $valLen); + $val = \$value; + } + unless (defined $$tagTablePtr{$tag} or $Image::ExifTool::specialTags{$tag}) { + my %tagInfo; + if (MakeNameAndDesc($tag, \%tagInfo)) { + $et->VPrint(0, $$et{INDENT}, "[adding Qualcomm:$tagInfo{Name}]\n"); + AddTagToTable($tagTablePtr, $tag, \%tagInfo); + } + } + $et->HandleTag($tagTablePtr, $tag, $val, + DataPt => $dataPt, + DataPos => $dataPos, + Start => $pos, + Size => $valLen, + Format => $format, + ); + $pos += $valLen; # point to start of next entry + } + return 1; +} + +1; # end + +__END__ + +=head1 NAME + +Image::ExifTool::Qualcomm - Read Qualcomm APP7 meta information + +=head1 SYNOPSIS + +This module is loaded automatically by Image::ExifTool when required. + +=head1 DESCRIPTION + +This module contains definitions required by Image::ExifTool to read +information from the APP7 Qualcomm segment in JPEG images. + +=head1 AUTHOR + +Copyright 2003-2019, Phil Harvey (phil at owl.phy.queensu.ca) + +This library is free software; you can redistribute it and/or modify it +under the same terms as Perl itself. + +=head1 SEE ALSO + +L<Image::ExifTool::TagNames/Qualcomm Tags>, +L<Image::ExifTool(3pm)|Image::ExifTool> + +=cut diff --git a/lib/Image/ExifTool/QuickTime.pm b/lib/Image/ExifTool/QuickTime.pm new file mode 100644 index 0000000..c8a1096 --- /dev/null +++ b/lib/Image/ExifTool/QuickTime.pm @@ -0,0 +1,8094 @@ +#------------------------------------------------------------------------------ +# File: QuickTime.pm +# +# Description: Read QuickTime and MP4 meta information +# +# Revisions: 10/04/2005 - P. Harvey Created +# 12/19/2005 - P. Harvey Added MP4 support +# 09/22/2006 - P. Harvey Added M4A support +# 07/27/2010 - P. Harvey Updated to 2010-05-03 QuickTime spec +# +# References: +# +# 1) http://developer.apple.com/mac/library/documentation/QuickTime/QTFF/QTFFChap1/qtff1.html +# 2) http://search.cpan.org/dist/MP4-Info-1.04/ +# 3) http://www.geocities.com/xhelmboyx/quicktime/formats/mp4-layout.txt +# 4) http://wiki.multimedia.cx/index.php?title=Apple_QuickTime +# 5) ISO 14496-12 (http://read.pudn.com/downloads64/ebook/226547/ISO_base_media_file_format.pdf) +# 6) ISO 14496-16 (http://www.iec-normen.de/previewpdf/info_isoiec14496-16%7Bed2.0%7Den.pdf) +# 7) http://atomicparsley.sourceforge.net/mpeg-4files.html +# 8) http://wiki.multimedia.cx/index.php?title=QuickTime_container +# 9) http://www.adobe.com/devnet/xmp/pdfs/XMPSpecificationPart3.pdf (Oct 2008) +# 10) http://code.google.com/p/mp4v2/wiki/iTunesMetadata +# 11) http://www.canieti.com.mx/assets/files/1011/IEC_100_1384_DC.pdf +# 12) QuickTime file format specification 2010-05-03 +# 13) http://www.adobe.com/devnet/flv/pdf/video_file_format_spec_v10.pdf +# 14) http://standards.iso.org/ittf/PubliclyAvailableStandards/c051533_ISO_IEC_14496-12_2008.zip +# 15) http://getid3.sourceforge.net/source/module.audio-video.quicktime.phps +# 16) http://qtra.apple.com/atoms.html +# 17) http://www.etsi.org/deliver/etsi_ts/126200_126299/126244/10.01.00_60/ts_126244v100100p.pdf +# 18) https://github.com/appsec-labs/iNalyzer/blob/master/scinfo.m +# 19) http://nah6.com/~itsme/cvs-xdadevtools/iphone/tools/decodesinf.pl +# 20) https://developer.apple.com/legacy/library/documentation/quicktime/reference/QT7-1_Update_Reference/QT7-1_Update_Reference.pdf +# 21) Francois Bonzon private communication +# 22) https://developer.apple.com/library/mac/documentation/QuickTime/QTFF/Metadata/Metadata.html +#------------------------------------------------------------------------------ + +package Image::ExifTool::QuickTime; + +use strict; +use vars qw($VERSION $AUTOLOAD); +use Image::ExifTool qw(:DataAccess :Utils); +use Image::ExifTool::Exif; +use Image::ExifTool::GPS; + +$VERSION = '2.21'; + +sub ProcessMOV($$;$); +sub ProcessKeys($$$); +sub ProcessMetaKeys($$$); +sub ProcessMetaData($$$); +sub ProcessEncodingParams($$$); +sub ProcessSampleDesc($$$); +sub ProcessHybrid($$$); +sub ProcessRights($$$); +sub Process_mebx($$$); # (in QuickTimeStream.pl) +sub ProcessTTAD($$$); # (in QuickTimeStream.pl) +sub ParseItemLocation($$); +sub ParseItemInfoEntry($$); +sub ParseItemPropAssoc($$); +sub FixWrongFormat($); +sub GetMatrixStructure($$); +sub ConvertISO6709($); +sub ConvertChapterList($); +sub PrintChapter($); +sub PrintGPSCoordinates($); +sub UnpackLang($); +sub WriteQuickTime($$$); +sub WriteMOV($$); + +# MIME types for all entries in the ftypLookup with file extensions +# (defaults to 'video/mp4' if not found in this lookup) +my %mimeLookup = ( + '3G2' => 'video/3gpp2', + '3GP' => 'video/3gpp', + AAX => 'audio/vnd.audible.aax', + DVB => 'video/vnd.dvb.file', + F4A => 'audio/mp4', + F4B => 'audio/mp4', + JP2 => 'image/jp2', + JPM => 'image/jpm', + JPX => 'image/jpx', + M4A => 'audio/mp4', + M4B => 'audio/mp4', + M4P => 'audio/mp4', + M4V => 'video/x-m4v', + MOV => 'video/quicktime', + MQV => 'video/quicktime', + HEIC => 'image/heic', + HEVC => 'image/heic-sequence', + HEIF => 'image/heif', + CRX => 'video/x-canon-crx', # (will get overridden) +); + +# look up file type from ftyp atom type, with MIME type in comment if known +# (ref http://www.ftyps.com/) +my %ftypLookup = ( + '3g2a' => '3GPP2 Media (.3G2) compliant with 3GPP2 C.S0050-0 V1.0', # video/3gpp2 + '3g2b' => '3GPP2 Media (.3G2) compliant with 3GPP2 C.S0050-A V1.0.0', # video/3gpp2 + '3g2c' => '3GPP2 Media (.3G2) compliant with 3GPP2 C.S0050-B v1.0', # video/3gpp2 + '3ge6' => '3GPP (.3GP) Release 6 MBMS Extended Presentations', # video/3gpp + '3ge7' => '3GPP (.3GP) Release 7 MBMS Extended Presentations', # video/3gpp + '3gg6' => '3GPP Release 6 General Profile', # video/3gpp + '3gp1' => '3GPP Media (.3GP) Release 1 (probably non-existent)', # video/3gpp + '3gp2' => '3GPP Media (.3GP) Release 2 (probably non-existent)', # video/3gpp + '3gp3' => '3GPP Media (.3GP) Release 3 (probably non-existent)', # video/3gpp + '3gp4' => '3GPP Media (.3GP) Release 4', # video/3gpp + '3gp5' => '3GPP Media (.3GP) Release 5', # video/3gpp + '3gp6' => '3GPP Media (.3GP) Release 6 Basic Profile', # video/3gpp + '3gp6' => '3GPP Media (.3GP) Release 6 Progressive Download', # video/3gpp + '3gp6' => '3GPP Media (.3GP) Release 6 Streaming Servers', # video/3gpp + '3gs7' => '3GPP Media (.3GP) Release 7 Streaming Servers', # video/3gpp + 'aax ' => 'Audible Enhanced Audiobook (.AAX)', #PH + 'avc1' => 'MP4 Base w/ AVC ext [ISO 14496-12:2005]', # video/mp4 + 'CAEP' => 'Canon Digital Camera', + 'caqv' => 'Casio Digital Camera', + 'CDes' => 'Convergent Design', + 'da0a' => 'DMB MAF w/ MPEG Layer II aud, MOT slides, DLS, JPG/PNG/MNG images', + 'da0b' => 'DMB MAF, extending DA0A, with 3GPP timed text, DID, TVA, REL, IPMP', + 'da1a' => 'DMB MAF audio with ER-BSAC audio, JPG/PNG/MNG images', + 'da1b' => 'DMB MAF, extending da1a, with 3GPP timed text, DID, TVA, REL, IPMP', + 'da2a' => 'DMB MAF aud w/ HE-AAC v2 aud, MOT slides, DLS, JPG/PNG/MNG images', + 'da2b' => 'DMB MAF, extending da2a, with 3GPP timed text, DID, TVA, REL, IPMP', + 'da3a' => 'DMB MAF aud with HE-AAC aud, JPG/PNG/MNG images', + 'da3b' => 'DMB MAF, extending da3a w/ BIFS, 3GPP timed text, DID, TVA, REL, IPMP', + 'dmb1' => 'DMB MAF supporting all the components defined in the specification', + 'dmpf' => 'Digital Media Project', # various + 'drc1' => 'Dirac (wavelet compression), encapsulated in ISO base media (MP4)', + 'dv1a' => 'DMB MAF vid w/ AVC vid, ER-BSAC aud, BIFS, JPG/PNG/MNG images, TS', + 'dv1b' => 'DMB MAF, extending dv1a, with 3GPP timed text, DID, TVA, REL, IPMP', + 'dv2a' => 'DMB MAF vid w/ AVC vid, HE-AAC v2 aud, BIFS, JPG/PNG/MNG images, TS', + 'dv2b' => 'DMB MAF, extending dv2a, with 3GPP timed text, DID, TVA, REL, IPMP', + 'dv3a' => 'DMB MAF vid w/ AVC vid, HE-AAC aud, BIFS, JPG/PNG/MNG images, TS', + 'dv3b' => 'DMB MAF, extending dv3a, with 3GPP timed text, DID, TVA, REL, IPMP', + 'dvr1' => 'DVB (.DVB) over RTP', # video/vnd.dvb.file + 'dvt1' => 'DVB (.DVB) over MPEG-2 Transport Stream', # video/vnd.dvb.file + 'F4A ' => 'Audio for Adobe Flash Player 9+ (.F4A)', # audio/mp4 + 'F4B ' => 'Audio Book for Adobe Flash Player 9+ (.F4B)', # audio/mp4 + 'F4P ' => 'Protected Video for Adobe Flash Player 9+ (.F4P)', # video/mp4 + 'F4V ' => 'Video for Adobe Flash Player 9+ (.F4V)', # video/mp4 + 'isc2' => 'ISMACryp 2.0 Encrypted File', # ?/enc-isoff-generic + 'iso2' => 'MP4 Base Media v2 [ISO 14496-12:2005]', # video/mp4 + 'isom' => 'MP4 Base Media v1 [IS0 14496-12:2003]', # video/mp4 + 'JP2 ' => 'JPEG 2000 Image (.JP2) [ISO 15444-1 ?]', # image/jp2 + 'JP20' => 'Unknown, from GPAC samples (prob non-existent)', + 'jpm ' => 'JPEG 2000 Compound Image (.JPM) [ISO 15444-6]', # image/jpm + 'jpx ' => 'JPEG 2000 with extensions (.JPX) [ISO 15444-2]', # image/jpx + 'KDDI' => '3GPP2 EZmovie for KDDI 3G cellphones', # video/3gpp2 + #LCAG => (found in CompatibleBrands of Leica MOV videos) + 'M4A ' => 'Apple iTunes AAC-LC (.M4A) Audio', # audio/x-m4a + 'M4B ' => 'Apple iTunes AAC-LC (.M4B) Audio Book', # audio/mp4 + 'M4P ' => 'Apple iTunes AAC-LC (.M4P) AES Protected Audio', # audio/mp4 + 'M4V ' => 'Apple iTunes Video (.M4V) Video', # video/x-m4v + 'M4VH' => 'Apple TV (.M4V)', # video/x-m4v + 'M4VP' => 'Apple iPhone (.M4V)', # video/x-m4v + 'mj2s' => 'Motion JPEG 2000 [ISO 15444-3] Simple Profile', # video/mj2 + 'mjp2' => 'Motion JPEG 2000 [ISO 15444-3] General Profile', # video/mj2 + 'mmp4' => 'MPEG-4/3GPP Mobile Profile (.MP4/3GP) (for NTT)', # video/mp4 + 'mp21' => 'MPEG-21 [ISO/IEC 21000-9]', # various + 'mp41' => 'MP4 v1 [ISO 14496-1:ch13]', # video/mp4 + 'mp42' => 'MP4 v2 [ISO 14496-14]', # video/mp4 + 'mp71' => 'MP4 w/ MPEG-7 Metadata [per ISO 14496-12]', # various + 'MPPI' => 'Photo Player, MAF [ISO/IEC 23000-3]', # various + 'mqt ' => 'Sony / Mobile QuickTime (.MQV) US Patent 7,477,830 (Sony Corp)', # video/quicktime + 'MSNV' => 'MPEG-4 (.MP4) for SonyPSP', # audio/mp4 + 'NDAS' => 'MP4 v2 [ISO 14496-14] Nero Digital AAC Audio', # audio/mp4 + 'NDSC' => 'MPEG-4 (.MP4) Nero Cinema Profile', # video/mp4 + 'NDSH' => 'MPEG-4 (.MP4) Nero HDTV Profile', # video/mp4 + 'NDSM' => 'MPEG-4 (.MP4) Nero Mobile Profile', # video/mp4 + 'NDSP' => 'MPEG-4 (.MP4) Nero Portable Profile', # video/mp4 + 'NDSS' => 'MPEG-4 (.MP4) Nero Standard Profile', # video/mp4 + 'NDXC' => 'H.264/MPEG-4 AVC (.MP4) Nero Cinema Profile', # video/mp4 + 'NDXH' => 'H.264/MPEG-4 AVC (.MP4) Nero HDTV Profile', # video/mp4 + 'NDXM' => 'H.264/MPEG-4 AVC (.MP4) Nero Mobile Profile', # video/mp4 + 'NDXP' => 'H.264/MPEG-4 AVC (.MP4) Nero Portable Profile', # video/mp4 + 'NDXS' => 'H.264/MPEG-4 AVC (.MP4) Nero Standard Profile', # video/mp4 + 'odcf' => 'OMA DCF DRM Format 2.0 (OMA-TS-DRM-DCF-V2_0-20060303-A)', # various + 'opf2' => 'OMA PDCF DRM Format 2.1 (OMA-TS-DRM-DCF-V2_1-20070724-C)', + 'opx2' => 'OMA PDCF DRM + XBS extensions (OMA-TS-DRM_XBS-V1_0-20070529-C)', + 'pana' => 'Panasonic Digital Camera', + 'qt ' => 'Apple QuickTime (.MOV/QT)', # video/quicktime + 'ROSS' => 'Ross Video', + 'sdv ' => 'SD Memory Card Video', # various? + 'ssc1' => 'Samsung stereoscopic, single stream', + 'ssc2' => 'Samsung stereoscopic, dual stream', + 'XAVC' => 'Sony XAVC', #PH + 'heic' => 'High Efficiency Image Format HEVC still image (.HEIC)', # image/heic + 'hevc' => 'High Efficiency Image Format HEVC sequence (.HEICS)', # image/heic-sequence + 'mif1' => 'High Efficiency Image Format still image (.HEIF)', # image/heif + 'msf1' => 'High Efficiency Image Format sequence (.HEIFS)', # image/heif-sequence + 'crx ' => 'Canon Raw (.CRX)', #PH (CR3 or CRM; use Canon CompressorVersion to decide) +); + +# information for time/date-based tags (time zero is Jan 1, 1904) +my %timeInfo = ( + Notes => 'converted from UTC to local time if the QuickTimeUTC option is set', + # It is not uncommon for brain-dead software to use the wrong time zero, + # so assume a time zero of Jan 1, 1970 if the date is before this + RawConv => q{ + my $offset = (66 * 365 + 17) * 24 * 3600; + return $val - $offset if $val >= $offset or $$self{OPTIONS}{QuickTimeUTC}; + $self->WarnOnce('Patched incorrect time zero for QuickTime date/time tag',1) if $val; + return $val; + }, + Shift => 'Time', + Writable => 1, + Permanent => 1, + DelValue => 0, + # Note: This value will be in UTC if generated by a system that is aware of the time zone + ValueConv => 'ConvertUnixTime($val, $self->Options("QuickTimeUTC"))', + ValueConvInv => 'GetUnixTime($val, $self->Options("QuickTimeUTC")) + (66 * 365 + 17) * 24 * 3600', + PrintConv => '$self->ConvertDateTime($val)', + PrintConvInv => '$self->InverseDateTime($val)', + # (can't put Groups here because they aren't constant!) +); +# information for duration tags +my %durationInfo = ( + ValueConv => '$$self{TimeScale} ? $val / $$self{TimeScale} : $val', + PrintConv => '$$self{TimeScale} ? ConvertDuration($val) : $val', +); +# handle unknown tags +my %unknownInfo = ( + Unknown => 1, + ValueConv => '$val =~ /^([\x20-\x7e]*)\0*$/ ? $1 : \$val', +); +# parsing for most of the 3gp udta language text boxes +my %langText = ( + RawConv => sub { + my ($val, $self) = @_; + return '<err>' unless length $val >= 6; + my $lang = UnpackLang(Get16u(\$val, 4)); + $lang = $lang ? "($lang) " : ''; + $val = substr($val, 6); # isolate string + $val = $self->Decode($val, 'UCS2') if $val =~ /^\xfe\xff/; + return $lang . $val; + }, +); + +# 4-character Vendor ID codes (ref PH) +my %vendorID = ( + appl => 'Apple', + fe20 => 'Olympus (fe20)', # (FE200) + FFMP => 'FFmpeg', + 'GIC '=> 'General Imaging Co.', + kdak => 'Kodak', + KMPI => 'Konica-Minolta', + leic => 'Leica', + mino => 'Minolta', + niko => 'Nikon', + NIKO => 'Nikon', + olym => 'Olympus', + pana => 'Panasonic', + pent => 'Pentax', + pr01 => 'Olympus (pr01)', # (FE100,FE110,FE115) + sany => 'Sanyo', + 'SMI '=> 'Sorenson Media Inc.', + ZORA => 'Zoran Corporation', + 'AR.D'=> 'Parrot AR.Drone', + ' KD '=> 'Kodak', # (FZ201) +); + +# QuickTime data atom encodings for string types (ref 12) +my %stringEncoding = ( + 1 => 'UTF8', + 2 => 'UTF16', + 3 => 'ShiftJIS', + 4 => 'UTF8', + 5 => 'UTF16', +); + +my %graphicsMode = ( + # (ref http://homepage.mac.com/vanhoek/MovieGuts%20docs/64.html) + 0x00 => 'srcCopy', + 0x01 => 'srcOr', + 0x02 => 'srcXor', + 0x03 => 'srcBic', + 0x04 => 'notSrcCopy', + 0x05 => 'notSrcOr', + 0x06 => 'notSrcXor', + 0x07 => 'notSrcBic', + 0x08 => 'patCopy', + 0x09 => 'patOr', + 0x0a => 'patXor', + 0x0b => 'patBic', + 0x0c => 'notPatCopy', + 0x0d => 'notPatOr', + 0x0e => 'notPatXor', + 0x0f => 'notPatBic', + 0x20 => 'blend', + 0x21 => 'addPin', + 0x22 => 'addOver', + 0x23 => 'subPin', + 0x24 => 'transparent', + 0x25 => 'addMax', + 0x26 => 'subOver', + 0x27 => 'addMin', + 0x31 => 'grayishTextOr', + 0x32 => 'hilite', + 0x40 => 'ditherCopy', + # the following ref ISO/IEC 15444-3 + 0x100 => 'Alpha', + 0x101 => 'White Alpha', + 0x102 => 'Pre-multiplied Black Alpha', + 0x110 => 'Component Alpha', +); + +my %channelLabel = ( + 0xFFFFFFFF => 'Unknown', + 0 => 'Unused', + 100 => 'UseCoordinates', + 1 => 'Left', + 2 => 'Right', + 3 => 'Center', + 4 => 'LFEScreen', + 5 => 'LeftSurround', + 6 => 'RightSurround', + 7 => 'LeftCenter', + 8 => 'RightCenter', + 9 => 'CenterSurround', + 10 => 'LeftSurroundDirect', + 11 => 'RightSurroundDirect', + 12 => 'TopCenterSurround', + 13 => 'VerticalHeightLeft', + 14 => 'VerticalHeightCenter', + 15 => 'VerticalHeightRight', + 16 => 'TopBackLeft', + 17 => 'TopBackCenter', + 18 => 'TopBackRight', + 33 => 'RearSurroundLeft', + 34 => 'RearSurroundRight', + 35 => 'LeftWide', + 36 => 'RightWide', + 37 => 'LFE2', + 38 => 'LeftTotal', + 39 => 'RightTotal', + 40 => 'HearingImpaired', + 41 => 'Narration', + 42 => 'Mono', + 43 => 'DialogCentricMix', + 44 => 'CenterSurroundDirect', + 45 => 'Haptic', + 200 => 'Ambisonic_W', + 201 => 'Ambisonic_X', + 202 => 'Ambisonic_Y', + 203 => 'Ambisonic_Z', + 204 => 'MS_Mid', + 205 => 'MS_Side', + 206 => 'XY_X', + 207 => 'XY_Y', + 301 => 'HeadphonesLeft', + 302 => 'HeadphonesRight', + 304 => 'ClickTrack', + 305 => 'ForeignLanguage', + 400 => 'Discrete', + 0x10000 => 'Discrete_0', + 0x10001 => 'Discrete_1', + 0x10002 => 'Discrete_2', + 0x10003 => 'Discrete_3', + 0x10004 => 'Discrete_4', + 0x10005 => 'Discrete_5', + 0x10006 => 'Discrete_6', + 0x10007 => 'Discrete_7', + 0x10008 => 'Discrete_8', + 0x10009 => 'Discrete_9', + 0x1000a => 'Discrete_10', + 0x1000b => 'Discrete_11', + 0x1000c => 'Discrete_12', + 0x1000d => 'Discrete_13', + 0x1000e => 'Discrete_14', + 0x1000f => 'Discrete_15', + 0x1ffff => 'Discrete_65535', +); + +# properties which don't get inherited from the parent +my %dontInherit = ( + ispe => 1, # size of parent may be different +); + +# the usual atoms required to decode timed metadata with the ExtractEmbedded option +my %eeStd = ( stco => 1, co64 => 1, stsz => 1, stz2 => 1, stsc => 1, stts => 1 ); + +# boxes for the various handler types that we want to save when ExtractEmbedded is enabled +my %eeBox = ( + # (note: vide is only processed if specific atoms exist in the VideoSampleDesc) + vide => { %eeStd, + JPEG => 1, + # avcC => 1, # (uncomment to parse H264 stream) + }, + text => { %eeStd }, + meta => { %eeStd }, + sbtl => { %eeStd }, + data => { %eeStd }, + camm => { %eeStd }, # (Insta360) + '' => { 'gps ' => 1 }, # (no handler -- top level box) +); + +# QuickTime atoms +%Image::ExifTool::QuickTime::Main = ( + PROCESS_PROC => \&ProcessMOV, + WRITE_PROC => \&WriteQuickTime, # (only needs to be defined for directories to process when writing) + GROUPS => { 2 => 'Video' }, + NOTES => q{ + The QuickTime format is used for many different types of audio, video and + image files (most notably, MOV/MP4 videos and HEIC/CR3 images). Exiftool + extracts standard meta information a variety of audio, video and image + parameters, as well as proprietary information written by many camera + models. Tags with a question mark after their name are not extracted unless + the Unknown option is set. + + ExifTool currently has a very limited ability to write metadata in + QuickTime-format videos. It can edit/create/delete any XMP tags, but may + only be used to edit certain date/time tags and the video orientation in + native QuickTime metadata. + + According to the specification, many QuickTime date/time tags should be + stored as UTC. Unfortunately, digital cameras often store local time values + instead (presumably because they don't know the time zone). For this + reason, by default ExifTool does not assume a time zone for these values. + However, if the QuickTimeUTC API option is set, then ExifTool will assume + these values are properly stored as UTC, and will convert them to local time + when extracting. + + See + L<http://developer.apple.com/mac/library/documentation/QuickTime/QTFF/QTFFChap1/qtff1.html> + for the official specification. + }, + meta => { # 'meta' is found here in my Sony ILCE-7S MP4 sample - PH + Name => 'Meta', + SubDirectory => { + TagTable => 'Image::ExifTool::QuickTime::Meta', + Start => 4, # skip 4-byte version number header + }, + }, + free => [ + { + Name => 'KodakFree', + # (found in Kodak M5370 MP4 videos) + Condition => '$$valPt =~ /^\0\0\0.Seri/s', + SubDirectory => { TagTable => 'Image::ExifTool::Kodak::Free' }, + },{ + Unknown => 1, + Binary => 1, + }, + # (also Samsung WB750 uncompressed thumbnail data starting with "SDIC\0") + ], + # fre1 - 4 bytes: "june" (Kodak PixPro SP360) + frea => { + Name => 'Kodak_frea', + SubDirectory => { TagTable => 'Image::ExifTool::Kodak::frea' }, + }, + skip => [ + { + Name => 'CanonSkip', + Condition => '$$valPt =~ /^\0.{3}(CNDB|CNCV|CNMN|CNFV|CNTH|CNDM)/s', + SubDirectory => { TagTable => 'Image::ExifTool::Canon::Skip' }, + }, + { Name => 'Skip', Unknown => 1, Binary => 1 }, + ], + wide => { Unknown => 1, Binary => 1 }, + ftyp => { #MP4 + Name => 'FileType', + SubDirectory => { TagTable => 'Image::ExifTool::QuickTime::FileType' }, + }, + pnot => { + Name => 'Preview', + SubDirectory => { TagTable => 'Image::ExifTool::QuickTime::Preview' }, + }, + PICT => { + Name => 'PreviewPICT', + Groups => { 2 => 'Preview' }, + Binary => 1, + }, + pict => { #8 + Name => 'PreviewPICT', + Groups => { 2 => 'Preview' }, + Binary => 1, + }, + # (note that moov is present for an HEIF sequence) + moov => { + Name => 'Movie', + SubDirectory => { TagTable => 'Image::ExifTool::QuickTime::Movie' }, + }, + moof => { + Name => 'MovieFragment', + SubDirectory => { TagTable => 'Image::ExifTool::QuickTime::MovieFragment' }, + }, + # mfra - movie fragment random access: contains tfra (track fragment random access), and + # mfro (movie fragment random access offset) (ref 5) + mdat => { Name => 'MovieData', Unknown => 1, Binary => 1 }, + 'mdat-size' => { + Name => 'MovieDataSize', + Notes => q{ + not a real tag ID, this tag represents the size of the 'mdat' data in bytes + and is used in the AvgBitrate calculation + }, + }, + 'mdat-offset' => 'MovieDataOffset', + junk => { Unknown => 1, Binary => 1 }, #8 + uuid => [ + { #9 (MP4 files) + Name => 'XMP', + # *** this is where ExifTool writes XMP in MP4 videos (as per XMP spec) *** + Condition => '$$valPt=~/^\xbe\x7a\xcf\xcb\x97\xa9\x42\xe8\x9c\x71\x99\x94\x91\xe3\xaf\xac/', + SubDirectory => { + TagTable => 'Image::ExifTool::XMP::Main', + Start => 16, + }, + }, + { #11 (MP4 files) + Name => 'UUID-PROF', + Condition => '$$valPt=~/^PROF!\xd2\x4f\xce\xbb\x88\x69\x5c\xfa\xc9\xc7\x40/', + SubDirectory => { + TagTable => 'Image::ExifTool::QuickTime::Profile', + Start => 24, # uid(16) + version(1) + flags(3) + count(4) + }, + }, + { #PH (Flip MP4 files) + Name => 'UUID-Flip', + Condition => '$$valPt=~/^\x4a\xb0\x3b\x0f\x61\x8d\x40\x75\x82\xb2\xd9\xfa\xce\xd3\x5f\xf5/', + SubDirectory => { + TagTable => 'Image::ExifTool::QuickTime::Flip', + Start => 16, + }, + }, + # "\x98\x7f\xa3\xdf\x2a\x85\x43\xc0\x8f\x8f\xd9\x7c\x47\x1e\x8e\xea" - unknown data in Flip videos + { #PH (Canon CR3) + Name => 'UUID-Preview', + Condition => '$$valPt=~/^\xea\xf4\x2b\x5e\x1c\x98\x4b\x88\xb9\xfb\xb7\xdc\x40\x6e\x4d\x16/', + Name => 'PreviewImage', + Groups => { 2 => 'Preview' }, + RawConv => '$val = substr($val, 0x30); $self->ValidateImage(\$val, $tag)', + }, + { #8 + Name => 'UUID-Unknown', + %unknownInfo, + }, + ], + _htc => { + Name => 'HTCInfo', + SubDirectory => { TagTable => 'Image::ExifTool::QuickTime::HTCInfo' }, + }, + udta => { + Name => 'UserData', + SubDirectory => { TagTable => 'Image::ExifTool::FLIR::UserData' }, + }, + thum => { #PH + Name => 'ThumbnailImage', + Groups => { 2 => 'Preview' }, + Binary => 1, + }, + ardt => { #PH + Name => 'ARDroneFile', + ValueConv => 'length($val) > 4 ? substr($val,4) : $val', # remove length + }, + prrt => { #PH + Name => 'ARDroneTelemetry', + Notes => q{ + telemetry information for each video frame: status1, status2, time, pitch, + roll, yaw, speed, altitude + }, + ValueConv => q{ + my $size = length $val; + return \$val if $size < 12 or not $$self{OPTIONS}{Binary}; + my $len = Get16u(\$val, 2); + my $str = ''; + SetByteOrder('II'); + my $pos = 12; + while ($pos + $len <= $size) { + my $s1 = Get16u(\$val, $pos); + # s2: 7=take-off?, 3=moving, 4=hovering, 9=landing?, 2=landed + my $s2 = Get16u(\$val, $pos + 2); + $str .= "$s1 $s2"; + my $num = int(($len-4)/4); + my ($i, $v); + for ($i=0; $i<$num; ++$i) { + my $pt = $pos + 4 + $i * 4; + if ($i > 0 && $i < 4) { + $v = GetFloat(\$val, $pt); # pitch/roll/yaw + } else { + $v = Get32u(\$val, $pt); + # convert time to sec, and speed(NC)/altitude to metres + $v /= 1000 if $i <= 5; + } + $str .= " $v"; + } + $str .= "\n"; + $pos += $len; + } + SetByteOrder('MM'); + return \$str; + }, + }, + udat => { #PH (GPS NMEA-format log written by Datakam Player software) + Name => 'GPSLog', + Binary => 1, # (actually ASCII, but very lengthy) + }, + # meta - proprietary XML information written by some Flip cameras - PH + # beam - 16 bytes found in an iPhone video +); + +# MPEG-4 'ftyp' atom +# (ref http://developer.apple.com/mac/library/documentation/QuickTime/QTFF/QTFFChap1/qtff1.html) +%Image::ExifTool::QuickTime::FileType = ( + PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData, + GROUPS => { 2 => 'Video' }, + FORMAT => 'int32u', + 0 => { + Name => 'MajorBrand', + Format => 'undef[4]', + PrintConv => \%ftypLookup, + }, + 1 => { + Name => 'MinorVersion', + Format => 'undef[4]', + ValueConv => 'sprintf("%x.%x.%x", unpack("nCC", $val))', + }, + 2 => { + Name => 'CompatibleBrands', + Format => 'undef[$size-8]', + # ignore any entry with a null, and return others as a list + ValueConv => 'my @a=($val=~/.{4}/sg); @a=grep(!/\0/,@a); \@a', + }, +); + +# proprietary HTC atom (HTC One MP4 video) +%Image::ExifTool::QuickTime::HTCInfo = ( + PROCESS_PROC => \&ProcessMOV, + GROUPS => { 2 => 'Video' }, + NOTES => 'Tags written by some HTC camera phones.', + slmt => { + Name => 'Unknown_slmt', + Unknown => 1, + Format => 'int32u', # (observed values: 4) + }, +); + +# atoms used in QTIF files +%Image::ExifTool::QuickTime::ImageFile = ( + PROCESS_PROC => \&ProcessMOV, + GROUPS => { 2 => 'Image' }, + NOTES => 'Tags used in QTIF QuickTime Image Files.', + idsc => { + Name => 'ImageDescription', + SubDirectory => { TagTable => 'Image::ExifTool::QuickTime::ImageDesc' }, + }, + idat => { + Name => 'ImageData', + Binary => 1, + }, + iicc => { + Name => 'ICC_Profile', + SubDirectory => { TagTable => 'Image::ExifTool::ICC_Profile::Main' }, + }, +); + +# image description data block +%Image::ExifTool::QuickTime::ImageDesc = ( + PROCESS_PROC => \&ProcessHybrid, + VARS => { ID_LABEL => 'ID/Index' }, + GROUPS => { 2 => 'Image' }, + FORMAT => 'int16u', + 2 => { + Name => 'CompressorID', + Format => 'string[4]', +# not very useful since this isn't a complete list and name is given below +# # ref http://developer.apple.com/mac/library/documentation/QuickTime/QTFF/QTFFChap3/qtff3.html +# PrintConv => { +# cvid => 'Cinepak', +# jpeg => 'JPEG', +# 'smc '=> 'Graphics', +# 'rle '=> 'Animation', +# rpza => 'Apple Video', +# kpcd => 'Kodak Photo CD', +# 'png '=> 'Portable Network Graphics', +# mjpa => 'Motion-JPEG (format A)', +# mjpb => 'Motion-JPEG (format B)', +# SVQ1 => 'Sorenson video, version 1', +# SVQ3 => 'Sorenson video, version 3', +# mp4v => 'MPEG-4 video', +# 'dvc '=> 'NTSC DV-25 video', +# dvcp => 'PAL DV-25 video', +# 'gif '=> 'Compuserve Graphics Interchange Format', +# h263 => 'H.263 video', +# tiff => 'Tagged Image File Format', +# 'raw '=> 'Uncompressed RGB', +# '2vuY'=> "Uncompressed Y'CbCr, 3x8-bit 4:2:2 (2vuY)", +# 'yuv2'=> "Uncompressed Y'CbCr, 3x8-bit 4:2:2 (yuv2)", +# v308 => "Uncompressed Y'CbCr, 8-bit 4:4:4", +# v408 => "Uncompressed Y'CbCr, 8-bit 4:4:4:4", +# v216 => "Uncompressed Y'CbCr, 10, 12, 14, or 16-bit 4:2:2", +# v410 => "Uncompressed Y'CbCr, 10-bit 4:4:4", +# v210 => "Uncompressed Y'CbCr, 10-bit 4:2:2", +# }, + # (HEVC-encoded videos have a CompressorID of 'hvc1') + }, + 10 => { + Name => 'VendorID', + Format => 'string[4]', + RawConv => 'length $val ? $val : undef', + PrintConv => \%vendorID, + SeparateTable => 'VendorID', + }, + # 14 - ("Quality" in QuickTime docs) ?? + 16 => 'SourceImageWidth', + 17 => 'SourceImageHeight', + 18 => { Name => 'XResolution', Format => 'fixed32u' }, + 20 => { Name => 'YResolution', Format => 'fixed32u' }, + # 24 => 'FrameCount', # always 1 (what good is this?) + 25 => { + Name => 'CompressorName', + Format => 'string[32]', + # (sometimes this is a Pascal string, and sometimes it is a C string) + RawConv => q{ + $val=substr($val,1,ord($1)) if $val=~/^([\0-\x1f])/ and ord($1)<length($val); + length $val ? $val : undef; + }, + }, + 41 => 'BitDepth', +# +# Observed offsets for child atoms of various CompressorID types: +# +# CompressorID Offset Child atoms +# ----------- ------ ---------------- +# avc1 86 avcC, btrt, colr, pasp, fiel, clap, svcC +# mp4v 86 esds, pasp +# s263 86 d263 +# + btrt => { + Name => 'BitrateInfo', + SubDirectory => { TagTable => 'Image::ExifTool::QuickTime::Bitrate' }, + }, + # Reference for fiel, colr, pasp, clap: + # https://developer.apple.com/library/mac/technotes/tn2162/_index.html#//apple_ref/doc/uid/DTS40013070-CH1-TNTAG9 + fiel => { + Name => 'VideoFieldOrder', + ValueConv => 'join(" ", unpack("C*",$val))', + PrintConv => [{ + 1 => 'Progressive', + 2 => '2:1 Interlaced', + }], + }, + colr => { + Name => 'ColorRepresentation', + ValueConv => 'join(" ", substr($val,0,4), unpack("x4n*",$val))', + }, + pasp => { + Name => 'PixelAspectRatio', + ValueConv => 'join(":", unpack("N*",$val))', + }, + clap => { + Name => 'CleanAperture', + SubDirectory => { TagTable => 'Image::ExifTool::QuickTime::CleanAperture' }, + }, + avcC => { + # (see http://thompsonng.blogspot.ca/2010/11/mp4-file-format-part-2.html) + Name => 'AVCConfiguration', + Unknown => 1, + Binary => 1, + }, + JPEG => { # (found in CR3 images; used as a flag to identify JpgFromRaw 'vide' stream) + Name => 'JPEGInfo', + # (4 bytes all zero) + Unknown => 1, + Binary => 1, + }, + # hvcC - HEVC configuration + # svcC - 7 bytes: 00 00 00 00 ff e0 00 + # esds - elementary stream descriptor + # d263 + gama => { Name => 'Gamma', Format => 'fixed32u' }, + # mjqt - default quantization table for MJPEG + # mjht - default Huffman table for MJPEG + # csgm ? (seen in hevc video) + # CMP1 - 52 bytes (Canon CR3) + # JPEG - 4 bytes all 0 (Canon CR3) + # free - (Canon CR3) + CDI1 => { # Canon CR3 + Name => 'CDI1', + SubDirectory => { + TagTable => 'Image::ExifTool::Canon::CDI1', + Start => 4, + }, + }, +# +# spherical video v2 stuff (untested) +# + st3d => { + Name => 'Stereoscopic3D', + Format => 'int8u', + ValueConv => '$val =~ s/.* //; $val', # (remove leading version/flags bytes?) + PrintConv => { + 0 => 'Monoscopic', + 1 => 'Stereoscopic Top-Bottom', + 2 => 'Stereoscopic Left-Right', + 3 => 'Stereoscopic Stereo-Custom', # (provisional in spec as of 2017-10-10) + }, + }, + sv3d => { + Name => 'SphericalVideo', + SubDirectory => { TagTable => 'Image::ExifTool::QuickTime::sv3d' }, + }, +); + +# 'sv3d' atom information (ref https://github.com/google/spatial-media/blob/master/docs/spherical-video-v2-rfc.md) +%Image::ExifTool::QuickTime::sv3d = ( + PROCESS_PROC => \&ProcessMOV, + GROUPS => { 2 => 'Video' }, + NOTES => q{ + Tags defined by the Spherical Video V2 specification. See + L<https://github.com/google/spatial-media/blob/master/docs/spherical-video-v2-rfc.md> + for the specification. + }, + svhd => { + Name => 'MetadataSource', + Format => 'undef', + ValueConv => '$val=~tr/\0//d; $val', # (remove version/flags? and terminator?) + }, + proj => { + Name => 'Projection', + SubDirectory => { TagTable => 'Image::ExifTool::QuickTime::proj' }, + }, +); + +# 'proj' atom information (ref https://github.com/google/spatial-media/blob/master/docs/spherical-video-v2-rfc.md) +%Image::ExifTool::QuickTime::proj = ( + PROCESS_PROC => \&ProcessMOV, + GROUPS => { 2 => 'Video' }, + prhd => { + Name => 'ProjectionHeader', + SubDirectory => { TagTable => 'Image::ExifTool::QuickTime::prhd' }, + }, + cbmp => { + Name => 'CubemapProj', + SubDirectory => { TagTable => 'Image::ExifTool::QuickTime::cbmp' }, + }, + equi => { + Name => 'EquirectangularProj', + SubDirectory => { TagTable => 'Image::ExifTool::QuickTime::equi' }, + }, + # mshp - MeshProjection (P.I.T.A. to decode, for not much reward, see ref) +); + +# 'prhd' atom information (ref https://github.com/google/spatial-media/blob/master/docs/spherical-video-v2-rfc.md) +%Image::ExifTool::QuickTime::prhd = ( + PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData, + GROUPS => { 2 => 'Video' }, + FORMAT => 'fixed32s', + # 0 - version (high 8 bits) / flags (low 24 bits) + 1 => 'PoseYawDegrees', + 2 => 'PosePitchDegrees', + 3 => 'PoseRollDegrees', +); + +# 'cbmp' atom information (ref https://github.com/google/spatial-media/blob/master/docs/spherical-video-v2-rfc.md) +%Image::ExifTool::QuickTime::cbmp = ( + PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData, + GROUPS => { 2 => 'Video' }, + FORMAT => 'int32u', + # 0 - version (high 8 bits) / flags (low 24 bits) + 1 => 'Layout', + 2 => 'Padding', +); + +# 'equi' atom information (ref https://github.com/google/spatial-media/blob/master/docs/spherical-video-v2-rfc.md) +%Image::ExifTool::QuickTime::equi = ( + PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData, + GROUPS => { 2 => 'Video' }, + FORMAT => 'int32u', # (actually 0.32 fixed point) + # 0 - version (high 8 bits) / flags (low 24 bits) + 1 => { Name => 'ProjectionBoundsTop', ValueConv => '$val / 4294967296' }, + 2 => { Name => 'ProjectionBoundsBottom',ValueConv => '$val / 4294967296' }, + 3 => { Name => 'ProjectionBoundsLeft', ValueConv => '$val / 4294967296' }, + 4 => { Name => 'ProjectionBoundsRight', ValueConv => '$val / 4294967296' }, +); + +# 'btrt' atom information (ref http://lists.freedesktop.org/archives/gstreamer-commits/2011-October/054459.html) +%Image::ExifTool::QuickTime::Bitrate = ( + PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData, + GROUPS => { 2 => 'Video' }, + FORMAT => 'int32u', + PRIORITY => 0, # often filled with zeros + 0 => 'BufferSize', + 1 => 'MaxBitrate', + 2 => 'AverageBitrate', +); + +# 'clap' atom information (ref https://developer.apple.com/library/mac/technotes/tn2162/_index.html#//apple_ref/doc/uid/DTS40013070-CH1-TNTAG9) +%Image::ExifTool::QuickTime::CleanAperture = ( + PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData, + GROUPS => { 2 => 'Video' }, + FORMAT => 'rational64u', + 0 => 'CleanApertureWidth', + 1 => 'CleanApertureHeight', + 2 => 'CleanApertureOffsetX', + 3 => 'CleanApertureOffsetY', +); + +# preview data block +%Image::ExifTool::QuickTime::Preview = ( + PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData, + WRITE_PROC => \&Image::ExifTool::WriteBinaryData, + CHECK_PROC => \&Image::ExifTool::CheckBinaryData, + GROUPS => { 2 => 'Image' }, + FORMAT => 'int16u', + 0 => { + Name => 'PreviewDate', + Format => 'int32u', + Groups => { 2 => 'Time' }, + %timeInfo, + }, + 2 => 'PreviewVersion', + 3 => { + Name => 'PreviewAtomType', + Format => 'string[4]', + }, + 5 => 'PreviewAtomIndex', +); + +# movie atoms +%Image::ExifTool::QuickTime::Movie = ( + PROCESS_PROC => \&ProcessMOV, + WRITE_PROC => \&WriteQuickTime, + GROUPS => { 2 => 'Video' }, + mvhd => { + Name => 'MovieHeader', + SubDirectory => { TagTable => 'Image::ExifTool::QuickTime::MovieHeader' }, + }, + trak => { + Name => 'Track', + SubDirectory => { TagTable => 'Image::ExifTool::QuickTime::Track' }, + }, + udta => { + Name => 'UserData', + SubDirectory => { TagTable => 'Image::ExifTool::QuickTime::UserData' }, + }, + meta => { # 'meta' is found here in my EX-F1 MOV sample - PH + Name => 'Meta', + SubDirectory => { TagTable => 'Image::ExifTool::QuickTime::Meta' }, + }, + iods => { + Name => 'InitialObjectDescriptor', + Flags => ['Binary','Unknown'], + }, + uuid => [ + { #11 (MP4 files) (also found in QuickTime::Track) + Name => 'UUID-USMT', + Condition => '$$valPt=~/^USMT!\xd2\x4f\xce\xbb\x88\x69\x5c\xfa\xc9\xc7\x40/', + SubDirectory => { + TagTable => 'Image::ExifTool::QuickTime::UserMedia', + Start => 16, + }, + }, + { #PH (Canon SX280) + Name => 'UUID-Canon', + Condition => '$$valPt=~/^\x85\xc0\xb6\x87\x82\x0f\x11\xe0\x81\x11\xf4\xce\x46\x2b\x6a\x48/', + SubDirectory => { + TagTable => 'Image::ExifTool::Canon::uuid', + Start => 16, + }, + }, + { + Name => 'UUID-Unknown', + %unknownInfo, + }, + ], + cmov => { + Name => 'CompressedMovie', + SubDirectory => { TagTable => 'Image::ExifTool::QuickTime::CMovie' }, + }, + htka => { # (written by HTC One M8 in slow-motion 1280x720 video - PH) + Name => 'HTCTrack', + SubDirectory => { TagTable => 'Image::ExifTool::QuickTime::Track' }, + }, + 'gps ' => { # GPS data written by Novatek cameras (parsed in QuickTimeStream.pl) + Name => 'GPSDataList', + Unknown => 1, + Binary => 1, + }, + # prfl - Profile (ref 12) + # clip - clipping --> contains crgn (clip region) (ref 12) + # mvex - movie extends --> contains mehd (movie extends header), trex (track extends) (ref 14) + # ICAT - 4 bytes: "6350" (Nikon CoolPix S6900), "6500" (Panasonic FT7) +); + +# (ref CFFMediaFormat-2_1.pdf) +%Image::ExifTool::QuickTime::MovieFragment = ( + PROCESS_PROC => \&ProcessMOV, + WRITE_PROC => \&WriteQuickTime, + GROUPS => { 2 => 'Video' }, + # mfhd - movie fragment header + traf => { + Name => 'TrackFragment', + SubDirectory => { TagTable => 'Image::ExifTool::QuickTime::TrackFragment' }, + }, +); + +# (ref CFFMediaFormat-2_1.pdf) +%Image::ExifTool::QuickTime::TrackFragment = ( + PROCESS_PROC => \&ProcessMOV, + WRITE_PROC => \&WriteQuickTime, + GROUPS => { 2 => 'Video' }, + # tfhd - track fragment header + # edts - edits --> contains elst (edit list) (ref PH) + # tfdt - track fragment base media decode time + # trik - trick play box + # trun - track fragment run box + # avcn - AVC NAL unit storage box + # secn - sample encryption box + # saio - sample auxiliary information offsets box + # sbgp - sample to group box + # sgpd - sample group description box + # sdtp - independent and disposable samples (ref 5) + # subs - sub-sample information (ref 5) +); + +# movie header data block +%Image::ExifTool::QuickTime::MovieHeader = ( + PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData, + WRITE_PROC => \&Image::ExifTool::WriteBinaryData, + CHECK_PROC => \&Image::ExifTool::CheckBinaryData, + GROUPS => { 2 => 'Video' }, + FORMAT => 'int32u', + DATAMEMBER => [ 0, 1, 2, 3, 4 ], + 0 => { + Name => 'MovieHeaderVersion', + Format => 'int8u', + RawConv => '$$self{MovieHeaderVersion} = $val', + }, + 1 => { + Name => 'CreateDate', + Groups => { 2 => 'Time' }, + %timeInfo, + # this is int64u if MovieHeaderVersion == 1 (ref 13) + Hook => '$$self{MovieHeaderVersion} and $format = "int64u", $varSize += 4', + }, + 2 => { + Name => 'ModifyDate', + Groups => { 2 => 'Time' }, + %timeInfo, + # this is int64u if MovieHeaderVersion == 1 (ref 13) + Hook => '$$self{MovieHeaderVersion} and $format = "int64u", $varSize += 4', + }, + 3 => { + Name => 'TimeScale', + RawConv => '$$self{TimeScale} = $val', + }, + 4 => { + Name => 'Duration', + %durationInfo, + # this is int64u if MovieHeaderVersion == 1 (ref 13) + Hook => '$$self{MovieHeaderVersion} and $format = "int64u", $varSize += 4', + }, + 5 => { + Name => 'PreferredRate', + ValueConv => '$val / 0x10000', + }, + 6 => { + Name => 'PreferredVolume', + Format => 'int16u', + ValueConv => '$val / 256', + PrintConv => 'sprintf("%.2f%%", $val * 100)', + }, + 9 => { + Name => 'MatrixStructure', + Format => 'fixed32s[9]', + # (the right column is fixed 2.30 instead of 16.16) + ValueConv => q{ + my @a = split ' ',$val; + $_ /= 0x4000 foreach @a[2,5,8]; + return "@a"; + }, + }, + 18 => { Name => 'PreviewTime', %durationInfo }, + 19 => { Name => 'PreviewDuration', %durationInfo }, + 20 => { Name => 'PosterTime', %durationInfo }, + 21 => { Name => 'SelectionTime', %durationInfo }, + 22 => { Name => 'SelectionDuration',%durationInfo }, + 23 => { Name => 'CurrentTime', %durationInfo }, + 24 => 'NextTrackID', +); + +# track atoms +%Image::ExifTool::QuickTime::Track = ( + PROCESS_PROC => \&ProcessMOV, + WRITE_PROC => \&WriteQuickTime, + GROUPS => { 1 => 'Track#', 2 => 'Video' }, + tkhd => { + Name => 'TrackHeader', + SubDirectory => { TagTable => 'Image::ExifTool::QuickTime::TrackHeader' }, + }, + udta => { + Name => 'UserData', + SubDirectory => { TagTable => 'Image::ExifTool::QuickTime::UserData' }, + }, + mdia => { #MP4 + Name => 'Media', + SubDirectory => { TagTable => 'Image::ExifTool::QuickTime::Media' }, + }, + meta => { #PH (MOV) + Name => 'Meta', + SubDirectory => { TagTable => 'Image::ExifTool::QuickTime::Meta' }, + }, + tref => { + Name => 'TrackRef', + SubDirectory => { TagTable => 'Image::ExifTool::QuickTime::TrackRef' }, + }, + tapt => { + Name => 'TrackAperture', + SubDirectory => { TagTable => 'Image::ExifTool::QuickTime::TrackAperture' }, + }, + uuid => [ + { #11 (MP4 files) (also found in QuickTime::Movie) + Name => 'UUID-USMT', + Condition => '$$valPt=~/^USMT!\xd2\x4f\xce\xbb\x88\x69\x5c\xfa\xc9\xc7\x40/', + SubDirectory => { + TagTable => 'Image::ExifTool::QuickTime::UserMedia', + Start => 16, + }, + }, + { #https://github.com/google/spatial-media/blob/master/docs/spherical-video-rfc.md + Name => 'SphericalVideoXML', + Condition => '$$valPt=~/^\xff\xcc\x82\x63\xf8\x55\x4a\x93\x88\x14\x58\x7a\x02\x52\x1f\xdd/', + Flags => [ 'Binary', 'BlockExtract' ], + Writable => 0, + SubDirectory => { + TagTable => 'Image::ExifTool::XMP::Main', + Start => 16, + }, + }, + { + Name => 'UUID-Unknown', + %unknownInfo, + }, + ], + # edts - edits --> contains elst (edit list) + # clip - clipping --> contains crgn (clip region) + # matt - track matt --> contains kmat (compressed matt) + # load - track loading settings + # imap - track input map --> contains ' in' --> contains ' ty', obid + # prfl - Profile (ref 12) +); + +# track header data block +%Image::ExifTool::QuickTime::TrackHeader = ( + PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData, + WRITE_PROC => \&Image::ExifTool::WriteBinaryData, + CHECK_PROC => \&Image::ExifTool::CheckBinaryData, + GROUPS => { 1 => 'Track#', 2 => 'Video' }, + FORMAT => 'int32u', + DATAMEMBER => [ 0, 1, 2, 5, 7 ], + 0 => { + Name => 'TrackHeaderVersion', + Format => 'int8u', + Priority => 0, + RawConv => '$$self{TrackHeaderVersion} = $val', + }, + 1 => { + Name => 'TrackCreateDate', + Priority => 0, + Groups => { 2 => 'Time' }, + %timeInfo, + # this is int64u if TrackHeaderVersion == 1 (ref 13) + Hook => '$$self{TrackHeaderVersion} and $format = "int64u", $varSize += 4', + }, + 2 => { + Name => 'TrackModifyDate', + Priority => 0, + Groups => { 2 => 'Time' }, + %timeInfo, + # this is int64u if TrackHeaderVersion == 1 (ref 13) + Hook => '$$self{TrackHeaderVersion} and $format = "int64u", $varSize += 4', + }, + 3 => { + Name => 'TrackID', + Priority => 0, + }, + 5 => { + Name => 'TrackDuration', + Priority => 0, + %durationInfo, + # this is int64u if TrackHeaderVersion == 1 (ref 13) + Hook => '$$self{TrackHeaderVersion} and $format = "int64u", $varSize += 4', + }, + 7 => { # (used only for writing MatrixStructure) + Name => 'ImageSizeLookahead', + Hidden => 1, + Format => 'int32u[14]', + RawConv => '$$self{ImageSizeLookahead} = $val; undef', + }, + 8 => { + Name => 'TrackLayer', + Format => 'int16u', + Priority => 0, + }, + 9 => { + Name => 'TrackVolume', + Format => 'int16u', + Priority => 0, + ValueConv => '$val / 256', + PrintConv => 'sprintf("%.2f%%", $val * 100)', + }, + 10 => { + Name => 'MatrixStructure', + Format => 'fixed32s[9]', + Notes => 'writable for the video track via the Composite Rotation tag', + Writable => 1, + Permanent => 1, + # only set rotation if image size is non-zero + RawConvInv => \&GetMatrixStructure, + # (the right column is fixed 2.30 instead of 16.16) + ValueConv => q{ + my @a = split ' ',$val; + $_ /= 0x4000 foreach @a[2,5,8]; + return "@a"; + }, + ValueConvInv => q{ + my @a = split ' ',$val; + $_ *= 0x4000 foreach @a[2,5,8]; + return "@a"; + }, + }, + 19 => { + Name => 'ImageWidth', + Priority => 0, + RawConv => \&FixWrongFormat, + }, + 20 => { + Name => 'ImageHeight', + Priority => 0, + RawConv => \&FixWrongFormat, + }, +); + +# user data atoms +%Image::ExifTool::QuickTime::UserData = ( + PROCESS_PROC => \&ProcessMOV, + WRITE_PROC => \&WriteQuickTime, + GROUPS => { 2 => 'Video' }, + NOTES => q{ + Tag ID's beginning with the copyright symbol (hex 0xa9) are multi-language + text. Alternate language tags are accessed by adding a dash followed by the + language/country code to the tag name. ExifTool will extract any + multi-language user data tags found, even if they don't exist in this table. + }, + "\xa9cpy" => { Name => 'Copyright', Groups => { 2 => 'Author' } }, + "\xa9day" => { + Name => 'ContentCreateDate', + Groups => { 2 => 'Time' }, + # handle values in the form "2010-02-12T13:27:14-0800" (written by Apple iPhone) + ValueConv => q{ + require Image::ExifTool::XMP; + $val = Image::ExifTool::XMP::ConvertXMPDate($val); + $val =~ s/([-+]\d{2})(\d{2})$/$1:$2/; # add colon to timezone if necessary + return $val; + }, + PrintConv => '$self->ConvertDateTime($val)', + }, + "\xa9ART" => 'Artist', #PH (iTunes 8.0.2) + "\xa9alb" => 'Album', #PH (iTunes 8.0.2) + "\xa9arg" => 'Arranger', #12 + "\xa9ark" => 'ArrangerKeywords', #12 + "\xa9cmt" => 'Comment', #PH (iTunes 8.0.2) + "\xa9cok" => 'ComposerKeywords', #12 + "\xa9com" => 'Composer', #12 + "\xa9dir" => 'Director', #12 + "\xa9ed1" => 'Edit1', + "\xa9ed2" => 'Edit2', + "\xa9ed3" => 'Edit3', + "\xa9ed4" => 'Edit4', + "\xa9ed5" => 'Edit5', + "\xa9ed6" => 'Edit6', + "\xa9ed7" => 'Edit7', + "\xa9ed8" => 'Edit8', + "\xa9ed9" => 'Edit9', + "\xa9fmt" => 'Format', + "\xa9gen" => 'Genre', #PH (iTunes 8.0.2) + "\xa9grp" => 'Grouping', #PH (NC) + "\xa9inf" => 'Information', + "\xa9isr" => 'ISRCCode', #12 + "\xa9lab" => 'RecordLabelName', #12 + "\xa9lal" => 'RecordLabelURL', #12 + "\xa9lyr" => 'Lyrics', #PH (NC) + "\xa9mak" => 'Make', #12 + "\xa9mal" => 'MakerURL', #12 + "\xa9mod" => 'Model', #PH + "\xa9nam" => 'Title', #12 + "\xa9pdk" => 'ProducerKeywords', #12 + "\xa9phg" => 'RecordingCopyright', #12 + "\xa9prd" => 'Producer', + "\xa9prf" => 'Performers', + "\xa9prk" => 'PerformerKeywords', #12 + "\xa9prl" => 'PerformerURL', + "\xa9dir" => 'Director', #12 + "\xa9req" => 'Requirements', + "\xa9snk" => 'SubtitleKeywords', #12 + "\xa9snm" => 'Subtitle', #12 + "\xa9src" => 'SourceCredits', #12 + "\xa9swf" => 'SongWriter', #12 + "\xa9swk" => 'SongWriterKeywords', #12 + "\xa9swr" => 'SoftwareVersion', #12 + "\xa9too" => 'Encoder', #PH (NC) + "\xa9trk" => 'Track', #PH (NC) + "\xa9wrt" => 'Composer', + "\xa9xyz" => { #PH (iPhone 3GS) + Name => 'GPSCoordinates', + Groups => { 2 => 'Location' }, + ValueConv => \&ConvertISO6709, + PrintConv => \&PrintGPSCoordinates, + }, + # \xa9 tags written by DJI Phantom 3: (ref PH) + "\xa9xsp" => 'SpeedX', #PH (guess) + "\xa9ysp" => 'SpeedY', #PH (guess) + "\xa9zsp" => 'SpeedZ', #PH (guess) + "\xa9fpt" => 'Pitch', #PH + "\xa9fyw" => 'Yaw', #PH + "\xa9frl" => 'Roll', #PH + "\xa9gpt" => 'CameraPitch', #PH + "\xa9gyw" => 'CameraYaw', #PH + "\xa9grl" => 'CameraRoll', #PH + "\xa9enc" => 'EncoderID', #PH (forum9271) + # and the following entries don't have the proper 4-byte header for \xa9 tags: + "\xa9dji" => { Name => 'UserData_dji', Format => 'undef', Binary => 1, Unknown => 1, Hidden => 1 }, + "\xa9res" => { Name => 'UserData_res', Format => 'undef', Binary => 1, Unknown => 1, Hidden => 1 }, + "\xa9uid" => { Name => 'UserData_uid', Format => 'undef', Binary => 1, Unknown => 1, Hidden => 1 }, + "\xa9mdl" => { Name => 'Model', Format => 'string', Notes => 'non-standard-format DJI tag' }, + # end DJI tags + name => 'Name', + WLOC => { + Name => 'WindowLocation', + Format => 'int16u', + }, + LOOP => { + Name => 'LoopStyle', + Format => 'int32u', + PrintConv => { + 1 => 'Normal', + 2 => 'Palindromic', + }, + }, + SelO => { + Name => 'PlaySelection', + Format => 'int8u', + }, + AllF => { + Name => 'PlayAllFrames', + Format => 'int8u', + }, + meta => { + Name => 'Meta', + SubDirectory => { + TagTable => 'Image::ExifTool::QuickTime::Meta', + Start => 4, # must skip 4-byte version number header + }, + }, + 'ptv '=> { + Name => 'PrintToVideo', + SubDirectory => { TagTable => 'Image::ExifTool::QuickTime::Video' }, + }, + hnti => { + Name => 'HintInfo', + SubDirectory => { TagTable => 'Image::ExifTool::QuickTime::HintInfo' }, + }, + hinf => { + Name => 'HintTrackInfo', + SubDirectory => { TagTable => 'Image::ExifTool::QuickTime::HintTrackInfo' }, + }, + hinv => 'HintVersion', #PH (guess) + XMP_ => { #PH (Adobe CS3 Bridge) + Name => 'XMP', + # *** this is where ExifTool writes XMP in MOV videos (as per XMP spec) *** + SubDirectory => { TagTable => 'Image::ExifTool::XMP::Main' }, + }, + # the following are 3gp tags, references: + # http://atomicparsley.sourceforge.net + # http://www.3gpp.org/ftp/tsg_sa/WG4_CODEC/TSGS4_25/Docs/ + cprt => { Name => 'Copyright', %langText, Groups => { 2 => 'Author' } }, + auth => { Name => 'Author', %langText, Groups => { 2 => 'Author' } }, + titl => { Name => 'Title', %langText }, + dscp => { Name => 'Description',%langText }, + perf => { Name => 'Performer', %langText }, + gnre => { Name => 'Genre', %langText }, + albm => { Name => 'Album', %langText }, + coll => { Name => 'CollectionName', %langText }, #17 + rtng => { + Name => 'Rating', + # (4-byte flags, 4-char entity, 4-char criteria, 2-byte lang, string) + RawConv => q{ + return '<err>' unless length $val >= 14; + my $str = 'Entity=' . substr($val,4,4) . ' Criteria=' . substr($val,8,4); + $str =~ tr/\0-\x1f\x7f-\xff//d; # remove unprintable characters + my $lang = Image::ExifTool::QuickTime::UnpackLang(Get16u(\$val, 12)); + $lang = $lang ? "($lang) " : ''; + $val = substr($val, 14); + $val = $self->Decode($val, 'UCS2') if $val =~ /^\xfe\xff/; + return $lang . $str . ' ' . $val; + }, + }, + clsf => { + Name => 'Classification', + # (4-byte flags, 4-char entity, 2-byte index, 2-byte lang, string) + RawConv => q{ + return '<err>' unless length $val >= 12; + my $str = 'Entity=' . substr($val,4,4) . ' Index=' . Get16u(\$val,8); + $str =~ tr/\0-\x1f\x7f-\xff//d; # remove unprintable characters + my $lang = Image::ExifTool::QuickTime::UnpackLang(Get16u(\$val, 10)); + $lang = $lang ? "($lang) " : ''; + $val = substr($val, 12); + $val = $self->Decode($val, 'UCS2') if $val =~ /^\xfe\xff/; + return $lang . $str . ' ' . $val; + }, + }, + kywd => { + Name => 'Keywords', + # (4 byte flags, 2-byte lang, 1-byte count, count x pascal strings) + RawConv => q{ + return '<err>' unless length $val >= 7; + my $lang = Image::ExifTool::QuickTime::UnpackLang(Get16u(\$val, 4)); + $lang = $lang ? "($lang) " : ''; + my $num = Get8u(\$val, 6); + my ($i, @vals); + my $pos = 7; + for ($i=0; $i<$num; ++$i) { + last if $pos >= length $val; + my $len = Get8u(\$val, $pos++); + last if $pos + $len > length $val; + my $v = substr($val, $pos, $len); + $v = $self->Decode($v, 'UCS2') if $v =~ /^\xfe\xff/; + push @vals, $v; + $pos += $len; + } + my $sep = $self->Options('ListSep'); + return $lang . join($sep, @vals); + }, + }, + loci => { + Name => 'LocationInformation', + Groups => { 2 => 'Location' }, + # (4-byte flags, 2-byte lang, location string, 1-byte role, 4-byte fixed longitude, + # 4-byte fixed latitude, 4-byte fixed altitude, body string, notes string) + RawConv => q{ + return '<err>' unless length $val >= 6; + my $lang = Image::ExifTool::QuickTime::UnpackLang(Get16u(\$val, 4)); + $lang = $lang ? "($lang) " : ''; + $val = substr($val, 6); + my $str; + if ($val =~ /^\xfe\xff/) { + $val =~ s/^(\xfe\xff(.{2})*?)\0\0//s or return '<err>'; + $str = $self->Decode($1, 'UCS2'); + } else { + $val =~ s/^(.*?)\0//s or return '<err>'; + $str = $1; + } + $str = '(none)' unless length $str; + return '<err>' if length $val < 13; + my $role = Get8u(\$val, 0); + my $lon = GetFixed32s(\$val, 1); + my $lat = GetFixed32s(\$val, 5); + my $alt = GetFixed32s(\$val, 9); + my $roleStr = {0=>'shooting',1=>'real',2=>'fictional',3=>'reserved'}->{$role}; + $str .= ' Role=' . ($roleStr || "unknown($role)"); + $str .= sprintf(' Lat=%.5f Lon=%.5f Alt=%.2f', $lat, $lon, $alt); + $val = substr($val, 13); + if ($val =~ s/^(\xfe\xff(.{2})*?)\0\0//s) { + $str .= ' Body=' . $self->Decode($1, 'UCS2'); + } elsif ($val =~ s/^(.*?)\0//s) { + $str .= " Body=$1"; + } + if ($val =~ s/^(\xfe\xff(.{2})*?)\0\0//s) { + $str .= ' Notes=' . $self->Decode($1, 'UCS2'); + } elsif ($val =~ s/^(.*?)\0//s) { + $str .= " Notes=$1"; + } + return $lang . $str; + }, + }, + yrrc => { + Name => 'Year', + Groups => { 2 => 'Time' }, + RawConv => 'length($val) >= 6 ? Get16u(\$val,4) : "<err>"', + }, + urat => { #17 + Name => 'UserRating', + RawConv => q{ + return '<err>' unless length $val >= 8; + return Get8u(\$val, 7); + }, + }, + # tsel - TrackSelection (ref 17) + # Apple tags (ref 16) + angl => { Name => 'CameraAngle', Format => 'string' }, # (NC) + clfn => { Name => 'ClipFileName', Format => 'string' }, # (NC) + clid => { Name => 'ClipID', Format => 'string' }, # (NC) + cmid => { Name => 'CameraID', Format => 'string' }, # (NC) + cmnm => { # (NC) + Name => 'Model', + Description => 'Camera Model Name', + Format => 'string', # (necessary to remove the trailing NULL) + }, + date => { # (NC) + Name => 'DateTimeOriginal', + Groups => { 2 => 'Time' }, + ValueConv => q{ + require Image::ExifTool::XMP; + $val = Image::ExifTool::XMP::ConvertXMPDate($val); + $val =~ s/([-+]\d{2})(\d{2})$/$1:$2/; # add colon to timezone if necessary + return $val; + }, + PrintConv => '$self->ConvertDateTime($val)', + }, + manu => { # (SX280) + Name => 'Make', + # (with Canon there are 6 unknown bytes before the model: "\0\0\0\0\x15\xc7") + RawConv => '$val=~s/^\0{4}..//s; $val=~s/\0.*//; $val', + }, + modl => { # (Samsung GT-S8530, Canon SX280) + Name => 'Model', + Description => 'Camera Model Name', + # (with Canon there are 6 unknown bytes before the model: "\0\0\0\0\x15\xc7") + RawConv => '$val=~s/^\0{4}..//s; $val=~s/\0.*//; $val', + }, + reel => { Name => 'ReelName', Format => 'string' }, # (NC) + scen => { Name => 'Scene', Format => 'string' }, # (NC) + shot => { Name => 'ShotName', Format => 'string' }, # (NC) + slno => { Name => 'SerialNumber', Format => 'string' }, # (NC) + apmd => { Name => 'ApertureMode', Format => 'undef' }, #20 + kgtt => { #http://lists.ffmpeg.org/pipermail/ffmpeg-devel-irc/2012-June/000707.html + # 'TrackType' will expand to 'Track#Type' when found inside a track + Name => 'TrackType', + # set flag to process this as international text + # even though the tag ID doesn't start with 0xa9 + IText => 1, + }, + chpl => { # (Nero chapter list) + Name => 'ChapterList', + ValueConv => \&ConvertChapterList, + PrintConv => \&PrintChapter, + }, + # ndrm - 7 bytes (0 0 0 1 0 0 0) Nero Digital Rights Management? (PH) + # other non-Apple tags (ref 16) + # hpix - HipixRichPicture (ref 16, HIPIX) + # strk - sub-track information (ref 16, ISO) +# +# Manufacturer-specific metadata +# + TAGS => [ #PH + # these tags were initially discovered in a Pentax movie, + # but similar information is found in videos from other manufacturers + { + Name => 'FujiFilmTags', + Condition => '$$valPt =~ /^FUJIFILM DIGITAL CAMERA\0/', + SubDirectory => { + TagTable => 'Image::ExifTool::FujiFilm::MOV', + ByteOrder => 'LittleEndian', + }, + }, + { + Name => 'KodakTags', + Condition => '$$valPt =~ /^EASTMAN KODAK COMPANY/', + SubDirectory => { + TagTable => 'Image::ExifTool::Kodak::MOV', + ByteOrder => 'LittleEndian', + }, + }, + { + Name => 'KonicaMinoltaTags', + Condition => '$$valPt =~ /^KONICA MINOLTA DIGITAL CAMERA/', + SubDirectory => { + TagTable => 'Image::ExifTool::Minolta::MOV1', + ByteOrder => 'LittleEndian', + }, + }, + { + Name => 'MinoltaTags', + Condition => '$$valPt =~ /^MINOLTA DIGITAL CAMERA/', + SubDirectory => { + TagTable => 'Image::ExifTool::Minolta::MOV2', + ByteOrder => 'LittleEndian', + }, + }, + { + Name => 'NikonTags', + Condition => '$$valPt =~ /^NIKON DIGITAL CAMERA\0/', + SubDirectory => { + TagTable => 'Image::ExifTool::Nikon::MOV', + ByteOrder => 'LittleEndian', + }, + }, + { + Name => 'OlympusTags1', + Condition => '$$valPt =~ /^OLYMPUS DIGITAL CAMERA\0.{9}\x01\0/s', + SubDirectory => { + TagTable => 'Image::ExifTool::Olympus::MOV1', + ByteOrder => 'LittleEndian', + }, + }, + { + Name => 'OlympusTags2', + Condition => '$$valPt =~ /^OLYMPUS DIGITAL CAMERA(?!\0.{21}\x0a\0{3})/s', + SubDirectory => { + TagTable => 'Image::ExifTool::Olympus::MOV2', + ByteOrder => 'LittleEndian', + }, + }, + { + Name => 'OlympusTags3', + Condition => '$$valPt =~ /^OLYMPUS DIGITAL CAMERA\0/', + SubDirectory => { + TagTable => 'Image::ExifTool::Olympus::MP4', + ByteOrder => 'LittleEndian', + }, + }, + { + Name => 'OlympusTags4', + Condition => '$$valPt =~ /^.{16}OLYM\0/s', + SubDirectory => { + TagTable => 'Image::ExifTool::Olympus::MOV3', + Start => 12, + }, + }, + { + Name => 'PentaxTags', + Condition => '$$valPt =~ /^PENTAX DIGITAL CAMERA\0/', + SubDirectory => { + TagTable => 'Image::ExifTool::Pentax::MOV', + ByteOrder => 'LittleEndian', + }, + }, + { + Name => 'SamsungTags', + Condition => '$$valPt =~ /^SAMSUNG DIGITAL CAMERA\0/', + SubDirectory => { + TagTable => 'Image::ExifTool::Samsung::MP4', + ByteOrder => 'LittleEndian', + }, + }, + { + Name => 'SanyoMOV', + Condition => q{ + $$valPt =~ /^SANYO DIGITAL CAMERA\0/ and + $self->{VALUE}->{FileType} eq "MOV" + }, + SubDirectory => { + TagTable => 'Image::ExifTool::Sanyo::MOV', + ByteOrder => 'LittleEndian', + }, + }, + { + Name => 'SanyoMP4', + Condition => q{ + $$valPt =~ /^SANYO DIGITAL CAMERA\0/ and + $self->{VALUE}->{FileType} eq "MP4" + }, + SubDirectory => { + TagTable => 'Image::ExifTool::Sanyo::MP4', + ByteOrder => 'LittleEndian', + }, + }, + { + Name => 'UnknownTags', + Unknown => 1, + Binary => 1 + }, + ], + # ---- Canon ---- + CNCV => { Name => 'CompressorVersion', Format => 'string' }, #PH (5D Mark II) + CNMN => { + Name => 'Model', #PH (EOS 550D) + Description => 'Camera Model Name', + Format => 'string', # (necessary to remove the trailing NULL) + }, + CNFV => { Name => 'FirmwareVersion', Format => 'string' }, #PH (EOS 550D) + CNTH => { #PH (PowerShot S95) + Name => 'CanonCNTH', + SubDirectory => { TagTable => 'Image::ExifTool::Canon::CNTH' }, + }, + CNOP => { #PH (7DmkII) + Name => 'CanonCNOP', + SubDirectory => { TagTable => 'Image::ExifTool::Canon::CNOP' }, + }, + # CNDB - 2112 bytes (550D) + # CNDM - 4 bytes - 0xff,0xd8,0xff,0xd9 (S95) + # CNDG - 10232 bytes, mostly zeros (N100) + # ---- Casio ---- + QVMI => { #PH + Name => 'CasioQVMI', + # Casio stores standard EXIF-format information in MOV videos (eg. EX-S880) + SubDirectory => { + TagTable => 'Image::ExifTool::Exif::Main', + ProcessProc => \&Image::ExifTool::Exif::ProcessExif, # (because ProcessMOV is default) + DirName => 'IFD0', + Multi => 0, # (no NextIFD pointer) + Start => 10, + ByteOrder => 'BigEndian', + }, + }, + # ---- FujiFilm ---- + FFMV => { #PH (FinePix HS20EXR) + Name => 'FujiFilmFFMV', + SubDirectory => { TagTable => 'Image::ExifTool::FujiFilm::FFMV' }, + }, + MVTG => { #PH (FinePix HS20EXR) + Name => 'FujiFilmMVTG', + SubDirectory => { + TagTable => 'Image::ExifTool::Exif::Main', + ProcessProc => \&Image::ExifTool::Exif::ProcessExif, # (because ProcessMOV is default) + DirName => 'IFD0', + Start => 16, + Base => '$start', + ByteOrder => 'LittleEndian', + }, + }, + # ---- GoPro ---- (ref PH) + GoPr => 'GoProType', # (Hero3+) + FIRM => 'FirmwareVersion', # (Hero4) + LENS => 'LensSerialNumber', # (Hero4) + CAME => { # (Hero4) + Name => 'SerialNumberHash', + Description => 'Camera Serial Number Hash', + ValueConv => 'unpack("H*",$val)', + }, + # SETT? 12 bytes (Hero4) + # MUID? 32 bytes (Hero4, starts with serial number hash) + # HMMT? 404 bytes (Hero4, all zero) + # BCID? 26 bytes (Hero5, all zero) + # GUMI? 16 bytes (Hero5) + "FOV\0" => 'FieldOfView', #forum8938 (Hero2) seen: "Wide" + GPMF => { + Name => 'GoProGPMF', + SubDirectory => { TagTable => 'Image::ExifTool::GoPro::GPMF' }, + }, + # free (all zero) + "\xa9TSC" => 'StartTimeScale', # (Hero6) + "\xa9TSZ" => 'StartTimeSampleSize', # (Hero6) + # --- HTC ---- + htcb => { + Name => 'HTCBinary', + SubDirectory => { TagTable => 'Image::ExifTool::QuickTime::HTCBinary' }, + }, + # ---- Kodak ---- + DcMD => { + Name => 'KodakDcMD', + SubDirectory => { TagTable => 'Image::ExifTool::Kodak::DcMD' }, + }, + SNum => { Name => 'SerialNumber', Groups => { 2 => 'Camera' } }, + ptch => { Name => 'Pitch', Format => 'rational64s' }, # Units?? + _yaw => { Name => 'Yaw', Format => 'rational64s' }, # Units?? + roll => { Name => 'Roll', Format => 'rational64s' }, # Units?? + _cx_ => { Name => 'CX', Format => 'rational64s', Unknown => 1 }, + _cy_ => { Name => 'CY', Format => 'rational64s', Unknown => 1 }, + rads => { Name => 'Rads', Format => 'rational64s', Unknown => 1 }, + lvlm => { Name => 'LevelMeter', Format => 'rational64s', Unknown => 1 }, # (guess) + Lvlm => { Name => 'LevelMeter', Format => 'rational64s', Unknown => 1 }, # (guess) + pose => { Name => 'pose', SubDirectory => { TagTable => 'Image::ExifTool::Kodak::pose' } }, + # AMBA => Ambarella AVC atom (unknown data written by Kodak Playsport video cam) + # tmlp - 1 byte: 0 (PixPro SP360/4KVR360) + # pivi - 72 bytes (PixPro SP360) + # pive - 12 bytes (PixPro SP360) + # loop - 4 bytes: 0 0 0 0 (PixPro 4KVR360) + # m cm - 2 bytes: 0 0 (PixPro 4KVR360) + # m ev - 2 bytes: 0 0 (PixPro SP360/4KVR360) (exposure comp?) + # m vr - 2 bytes: 0 1 (PixPro 4KVR360) (virtual reality?) + # m wb - 4 bytes: 0 0 0 0 (PixPro SP360/4KVR360) (white balance?) + # mclr - 4 bytes: 0 0 0 0 (PixPro SP360/4KVR360) + # mmtr - 4 bytes: 0,6 0 0 0 (PixPro SP360/4KVR360) + # mflr - 4 bytes: 0 0 0 0 (PixPro SP360) + # lvlm - 24 bytes (PixPro SP360) + # Lvlm - 24 bytes (PixPro 4KVR360) + # ufdm - 4 bytes: 0 0 0 1 (PixPro SP360) + # mtdt - 1 byte: 0 (PixPro SP360/4KVR360) + # gdta - 75240 bytes (PixPro SP360) + # EIS1 - 4 bytes: 03 07 00 00 (PixPro 4KVR360) + # EIS2 - 4 bytes: 04 97 00 00 (PixPro 4KVR360) + # ---- LG ---- + adzc => { Name => 'Unknown_adzc', Unknown => 1, Hidden => 1, %langText }, # "false\0/","true\0/" + adze => { Name => 'Unknown_adze', Unknown => 1, Hidden => 1, %langText }, # "false\0/" + adzm => { Name => 'Unknown_adzm', Unknown => 1, Hidden => 1, %langText }, # "\x0e\x04/","\x10\x06" + # ---- Microsoft ---- + Xtra => { #PH (microsoft) + Name => 'MicrosoftXtra', + SubDirectory => { TagTable => 'Image::ExifTool::Microsoft::Xtra' }, + }, + # ---- Minolta ---- + MMA0 => { #PH (DiMage 7Hi) + Name => 'MinoltaMMA0', + SubDirectory => { TagTable => 'Image::ExifTool::Minolta::MMA' }, + }, + MMA1 => { #PH (Dimage A2) + Name => 'MinoltaMMA1', + SubDirectory => { TagTable => 'Image::ExifTool::Minolta::MMA' }, + }, + # ---- Nikon ---- + NCDT => { #PH + Name => 'NikonNCDT', + SubDirectory => { TagTable => 'Image::ExifTool::Nikon::NCDT' }, + }, + # ---- Olympus ---- + scrn => { #PH (TG-810) + Name => 'OlympusPreview', + Condition => '$$valPt =~ /^.{4}\xff\xd8\xff\xdb/s', + SubDirectory => { TagTable => 'Image::ExifTool::Olympus::scrn' }, + }, + # ---- Panasonic/Leica ---- + PANA => { #PH + Name => 'PanasonicPANA', + SubDirectory => { TagTable => 'Image::ExifTool::Panasonic::PANA' }, + }, + LEIC => { #PH + Name => 'LeicaLEIC', + SubDirectory => { TagTable => 'Image::ExifTool::Panasonic::PANA' }, + }, + # ---- Pentax ---- + thmb => [ # (apparently defined by 3gpp, ref 16) + { #PH (Pentax Q) + Name => 'MakerNotePentax5a', + Condition => '$$valPt =~ /^PENTAX \0II/', + SubDirectory => { + TagTable => 'Image::ExifTool::Pentax::Main', + ProcessProc => \&Image::ExifTool::Exif::ProcessExif, # (because ProcessMOV is default) + Start => 10, + Base => '$start - 10', + ByteOrder => 'LittleEndian', + }, + },{ #PH (TG-810) + Name => 'OlympusThumbnail', + Condition => '$$valPt =~ /^.{4}\xff\xd8\xff\xdb/s', + SubDirectory => { TagTable => 'Image::ExifTool::Olympus::thmb' }, + },{ #17 (format is in bytes 3-7) + Name => 'ThumbnailImage', + Condition => '$$valPt =~ /^.{8}\xff\xd8\xff\xdb/s', + Groups => { 2 => 'Preview' }, + RawConv => 'substr($val, 8)', + Binary => 1, + },{ #17 (format is in bytes 3-7) + Name => 'ThumbnailPNG', + Condition => '$$valPt =~ /^.{8}\x89PNG\r\n\x1a\n/s', + Groups => { 2 => 'Preview' }, + RawConv => 'substr($val, 8)', + Binary => 1, + },{ + Name => 'UnknownThumbnail', + Groups => { 2 => 'Preview' }, + Binary => 1, + }, + ], + PENT => { #PH + Name => 'PentaxPENT', + SubDirectory => { + TagTable => 'Image::ExifTool::Pentax::PENT', + ByteOrder => 'LittleEndian', + }, + }, + PXTH => { #PH (Pentax K-01) + Name => 'PentaxPreview', + SubDirectory => { TagTable => 'Image::ExifTool::Pentax::PXTH' }, + }, + PXMN => [{ #PH (Pentax K-01) + Name => 'MakerNotePentax5b', + Condition => '$$valPt =~ /^PENTAX \0MM/', + SubDirectory => { + TagTable => 'Image::ExifTool::Pentax::Main', + ProcessProc => \&Image::ExifTool::Exif::ProcessExif, # (because ProcessMOV is default) + Start => 10, + Base => '$start - 10', + ByteOrder => 'BigEndian', + }, + },{ #PH (Pentax 645Z) + Name => 'MakerNotePentax5c', + Condition => '$$valPt =~ /^PENTAX \0II/', + SubDirectory => { + TagTable => 'Image::ExifTool::Pentax::Main', + ProcessProc => \&Image::ExifTool::Exif::ProcessExif, # (because ProcessMOV is default) + Start => 10, + Base => '$start - 10', + ByteOrder => 'LittleEndian', + }, + },{ + Name => 'MakerNotePentaxUnknown', + Binary => 1, + }], + # ---- Ricoh ---- + RTHU => { #PH (GR) + Name => 'PreviewImage', + Groups => { 2 => 'Preview' }, + RawConv => '$self->ValidateImage(\$val, $tag)', + }, + RMKN => { #PH (GR) + Name => 'RicohRMKN', + SubDirectory => { + TagTable => 'Image::ExifTool::Exif::Main', + ProcessProc => \&Image::ExifTool::ProcessTIFF, # (because ProcessMOV is default) + }, + }, + # ---- Samsung ---- + vndr => 'Vendor', #PH (Samsung PL70) + SDLN => 'PlayMode', #PH (NC, Samsung ST80 "SEQ_PLAY") + INFO => { + Name => 'SamsungINFO', + SubDirectory => { TagTable => 'Image::ExifTool::Samsung::INFO' }, + }, + '@sec' => { #PH (Samsung WB30F) + Name => 'SamsungSec', + SubDirectory => { TagTable => 'Image::ExifTool::Samsung::sec' }, + }, + 'smta' => { #PH (Samsung SM-C101) + Name => 'SamsungSmta', + SubDirectory => { + TagTable => 'Image::ExifTool::Samsung::smta', + Start => 4, + }, + }, + cver => 'CodeVersion', #PH (guess, Samsung MV900F) + # ducp - 4 bytes all zero (Samsung ST96,WB750), 52 bytes all zero (Samsung WB30F) + # edli - 52 bytes all zero (Samsung WB30F) + # @etc - 4 bytes all zero (Samsung WB30F) + # saut - 4 bytes all zero (Samsung SM-N900T) + # smrd - string "TRUEBLUE" (Samsung SM-C101) + # ---- TomTom Bandit Action Cam ---- + TTMD => { + Name => 'TomTomMetaData', + SubDirectory => { TagTable => 'Image::ExifTool::QuickTime::TomTom' }, + }, + # ---- Unknown ---- + # CDET - 128 bytes (unknown origin) +# +# other 3rd-party tags +# (ref http://code.google.com/p/mp4parser/source/browse/trunk/isoparser/src/main/resources/isoparser-default.properties?r=814) +# + ccid => 'ContentID', + icnu => 'IconURI', + infu => 'InfoURL', + cdis => 'ContentDistributorID', + albr => { Name => 'AlbumArtist', Groups => { 2 => 'Author' } }, + cvru => 'CoverURI', + lrcu => 'LyricsURI', + + tags => { # found in Audible .m4b audio books (ref PH) + Name => 'Audible_tags', + SubDirectory => { TagTable => 'Image::ExifTool::Audible::tags' }, + }, +); + +# Unknown information stored in HTC One (M8) videos - PH +%Image::ExifTool::QuickTime::HTCBinary = ( + PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData, + GROUPS => { 0 => 'MakerNotes', 1 => 'HTC', 2 => 'Video' }, + TAG_PREFIX => 'HTCBinary', + FORMAT => 'int32u', + FIRST_ENTRY => 0, + # 0 - values: 1 + # 1 - values: 0 + # 2 - values: 0 + # 3 - values: FileSize minus 12 (why?) + # 4 - values: 12 +); + +# TomTom Bandit Action Cam metadata (ref PH) +%Image::ExifTool::QuickTime::TomTom = ( + PROCESS_PROC => \&ProcessMOV, + GROUPS => { 2 => 'Video' }, + NOTES => 'Tags found in TomTom Bandit Action Cam MP4 videos.', + TTAD => { + Name => 'TomTomAD', + SubDirectory => { + TagTable => 'Image::ExifTool::QuickTime::Stream', + ProcessProc => \&Image::ExifTool::QuickTime::ProcessTTAD, + }, + }, + TTHL => { Name => 'TomTomHL', Binary => 1, Unknown => 1 }, # (mostly zeros) + # (TTID values are different for each video) + TTID => { Name => 'TomTomID', ValueConv => 'unpack("x4H*",$val)' }, + TTVI => { Name => 'TomTomVI', Format => 'int32u', Unknown => 1 }, # seen: "0 1 61 508 508" + # TTVD seen: "normal 720p 60fps 60fps 16/9 wide 1x" + TTVD => { Name => 'TomTomVD', ValueConv => 'my @a = ($val =~ /[\x20-\x7f]+/g); "@a"' }, +); + +# User-specific media data atoms (ref 11) +%Image::ExifTool::QuickTime::UserMedia = ( + PROCESS_PROC => \&ProcessMOV, + GROUPS => { 2 => 'Video' }, + MTDT => { + Name => 'MetaData', + SubDirectory => { TagTable => 'Image::ExifTool::QuickTime::MetaData' }, + }, +); + +# User-specific media data atoms (ref 11) +%Image::ExifTool::QuickTime::MetaData = ( + PROCESS_PROC => \&Image::ExifTool::QuickTime::ProcessMetaData, + GROUPS => { 2 => 'Video' }, + TAG_PREFIX => 'MetaData', + 0x01 => 'Title', + 0x03 => { + Name => 'ProductionDate', + Groups => { 2 => 'Time' }, + # translate from format "YYYY/mm/dd HH:MM:SS" + ValueConv => '$val=~tr{/}{:}; $val', + PrintConv => '$self->ConvertDateTime($val)', + }, + 0x04 => 'Software', + 0x05 => 'Product', + 0x0a => { + Name => 'TrackProperty', + RawConv => 'my @a=unpack("Nnn",$val); "@a"', + PrintConv => [ + { 0 => 'No presentation', BITMASK => { 0 => 'Main track' } }, + { 0 => 'No attributes', BITMASK => { 15 => 'Read only' } }, + '"Priority $val"', + ], + }, + 0x0b => { + Name => 'TimeZone', + Groups => { 2 => 'Time' }, + RawConv => 'Get16s(\$val,0)', + PrintConv => 'TimeZoneString($val)', + }, + 0x0c => { + Name => 'ModifyDate', + Groups => { 2 => 'Time' }, + # translate from format "YYYY/mm/dd HH:MM:SS" + ValueConv => '$val=~tr{/}{:}; $val', + PrintConv => '$self->ConvertDateTime($val)', + }, +); + +# compressed movie atoms (ref http://wiki.multimedia.cx/index.php?title=QuickTime_container#cmov) +%Image::ExifTool::QuickTime::CMovie = ( + PROCESS_PROC => \&ProcessMOV, + GROUPS => { 2 => 'Video' }, + dcom => 'Compression', + # cmvd - compressed movie data +); + +# Profile atoms (ref 11) +%Image::ExifTool::QuickTime::Profile = ( + PROCESS_PROC => \&ProcessMOV, + GROUPS => { 2 => 'Video' }, + FPRF => { + Name => 'FileGlobalProfile', + SubDirectory => { TagTable => 'Image::ExifTool::QuickTime::FileProf' }, + }, + APRF => { + Name => 'AudioProfile', + SubDirectory => { TagTable => 'Image::ExifTool::QuickTime::AudioProf' }, + }, + VPRF => { + Name => 'VideoProfile', + SubDirectory => { TagTable => 'Image::ExifTool::QuickTime::VideoProf' }, + }, + OLYM => { #PH + Name => 'OlympusOLYM', + SubDirectory => { + TagTable => 'Image::ExifTool::Olympus::OLYM', + ByteOrder => 'BigEndian', + }, + }, +); + +# FPRF atom information (ref 11) +%Image::ExifTool::QuickTime::FileProf = ( + PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData, + GROUPS => { 2 => 'Video' }, + FORMAT => 'int32u', + 0 => { Name => 'FileProfileVersion', Unknown => 1 }, # unknown = uninteresting + 1 => { + Name => 'FileFunctionFlags', + PrintConv => { BITMASK => { + 28 => 'Fragmented', + 29 => 'Additional tracks', + 30 => 'Edited', # (main AV track is edited) + }}, + }, + # 2 - reserved +); + +# APRF atom information (ref 11) +%Image::ExifTool::QuickTime::AudioProf = ( + PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData, + GROUPS => { 2 => 'Audio' }, + FORMAT => 'int32u', + 0 => { Name => 'AudioProfileVersion', Unknown => 1 }, + 1 => 'AudioTrackID', + 2 => { + Name => 'AudioCodec', + Format => 'undef[4]', + }, + 3 => { + Name => 'AudioCodecInfo', + Unknown => 1, + PrintConv => 'sprintf("0x%.4x", $val)', + }, + 4 => { + Name => 'AudioAttributes', + PrintConv => { BITMASK => { + 0 => 'Encrypted', + 1 => 'Variable bitrate', + 2 => 'Dual mono', + }}, + }, + 5 => { + Name => 'AudioAvgBitrate', + ValueConv => '$val * 1000', + PrintConv => 'ConvertBitrate($val)', + }, + 6 => { + Name => 'AudioMaxBitrate', + ValueConv => '$val * 1000', + PrintConv => 'ConvertBitrate($val)', + }, + 7 => 'AudioSampleRate', + 8 => 'AudioChannels', +); + +# VPRF atom information (ref 11) +%Image::ExifTool::QuickTime::VideoProf = ( + PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData, + GROUPS => { 2 => 'Video' }, + FORMAT => 'int32u', + 0 => { Name => 'VideoProfileVersion', Unknown => 1 }, + 1 => 'VideoTrackID', + 2 => { + Name => 'VideoCodec', + Format => 'undef[4]', + }, + 3 => { + Name => 'VideoCodecInfo', + Unknown => 1, + PrintConv => 'sprintf("0x%.4x", $val)', + }, + 4 => { + Name => 'VideoAttributes', + PrintConv => { BITMASK => { + 0 => 'Encrypted', + 1 => 'Variable bitrate', + 2 => 'Variable frame rate', + 3 => 'Interlaced', + }}, + }, + 5 => { + Name => 'VideoAvgBitrate', + ValueConv => '$val * 1000', + PrintConv => 'ConvertBitrate($val)', + }, + 6 => { + Name => 'VideoMaxBitrate', + ValueConv => '$val * 1000', + PrintConv => 'ConvertBitrate($val)', + }, + 7 => { + Name => 'VideoAvgFrameRate', + Format => 'fixed32u', + PrintConv => 'int($val * 1000 + 0.5) / 1000', + }, + 8 => { + Name => 'VideoMaxFrameRate', + Format => 'fixed32u', + PrintConv => 'int($val * 1000 + 0.5) / 1000', + }, + 9 => { + Name => 'VideoSize', + Format => 'int16u[2]', + PrintConv => '$val=~tr/ /x/; $val', + }, + 10 => { + Name => 'PixelAspectRatio', + Format => 'int16u[2]', + PrintConv => '$val=~tr/ /:/; $val', + }, +); + +# meta atoms +%Image::ExifTool::QuickTime::Meta = ( + PROCESS_PROC => \&ProcessMOV, + GROUPS => { 2 => 'Video' }, + ilst => { + Name => 'ItemList', + SubDirectory => { + TagTable => 'Image::ExifTool::QuickTime::ItemList', + HasData => 1, # process atoms as containers with 'data' elements + }, + }, + # MP4 tags (ref 5) + hdlr => { + Name => 'Handler', + SubDirectory => { TagTable => 'Image::ExifTool::QuickTime::Handler' }, + }, + dinf => { + Name => 'DataInformation', + Flags => ['Binary','Unknown'], + }, + ipmc => { + Name => 'IPMPControl', + Flags => ['Binary','Unknown'], + }, + iloc => { + Name => 'ItemLocation', + RawConv => \&ParseItemLocation, + Notes => 'parsed, but not extracted as a tag', + }, + ipro => { + Name => 'ItemProtection', + Flags => ['Binary','Unknown'], + }, + iinf => [{ + Name => 'ItemInformation', + Condition => '$$valPt =~ /^\0/', # (version 0?) + SubDirectory => { + TagTable => 'Image::ExifTool::QuickTime::ItemInfo', + Start => 6, # (4-byte version/flags + 2-byte count) + }, + },{ + Name => 'ItemInformation', + SubDirectory => { + TagTable => 'Image::ExifTool::QuickTime::ItemInfo', + Start => 8, # (4-byte version/flags + 4-byte count) + }, + }], + 'xml ' => { + Name => 'XML', + Flags => [ 'Binary', 'Protected', 'BlockExtract' ], + SubDirectory => { + TagTable => 'Image::ExifTool::XMP::XML', + IgnoreProp => { NonRealTimeMeta => 1 }, # ignore container for Sony 'nrtm' + }, + }, + 'keys' => { + Name => 'Keys', + SubDirectory => { TagTable => 'Image::ExifTool::QuickTime::Keys' }, + }, + bxml => { + Name => 'BinaryXML', + Flags => ['Binary','Unknown'], + }, + pitm => [{ + Name => 'PrimaryItemReference', + Condition => '$$valPt =~ /^\0/', # (version 0?) + RawConv => '$$self{PrimaryItem} = unpack("x4n",$val)', + },{ + Name => 'PrimaryItemReference', + RawConv => '$$self{PrimaryItem} = unpack("x4N",$val)', + }], + free => { #PH + Name => 'Free', + Flags => ['Binary','Unknown'], + }, + iprp => { + Name => 'ItemProperties', + SubDirectory => { TagTable => 'Image::ExifTool::QuickTime::ItemProp' }, + }, + iref => { + Name => 'ItemReference', + # the version is needed to parse some of the item references + Condition => '$$self{ItemRefVersion} = ord($$valPt); 1', + SubDirectory => { + TagTable => 'Image::ExifTool::QuickTime::ItemRef', + Start => 4, + }, + }, + # idat +); + +%Image::ExifTool::QuickTime::ItemProp = ( + PROCESS_PROC => \&ProcessMOV, + GROUPS => { 2 => 'Image' }, + ipco => { + Name => 'ItemPropertyContainer', + SubDirectory => { TagTable => 'Image::ExifTool::QuickTime::ItemPropCont' }, + }, + ipma => { + Name => 'ItemPropertyAssociation', + RawConv => \&ParseItemPropAssoc, + Notes => 'parsed, but not extracted as a tag', + }, +); + +%Image::ExifTool::QuickTime::ItemPropCont = ( + PROCESS_PROC => \&ProcessMOV, + GROUPS => { 2 => 'Image' }, + VARS => { START_INDEX => 1 }, # show verbose indices starting at 1 + colr => [{ + Name => 'ICC_Profile', + Condition => '$$valPt =~ /^(prof|rICC)/', + SubDirectory => { + TagTable => 'Image::ExifTool::ICC_Profile::Main', + Start => 4, + }, + },{ + Name => 'Unknown_colr', + Flags => ['Binary','Unknown','Hidden'], + }], + irot => { + Name => 'Rotation', + Format => 'int8u', + ValueConv => '$val * 90', + }, + ispe => { + Name => 'ImageSpatialExtent', + Condition => '$$valPt =~ /^\0{4}/', # (version/flags == 0/0) + RawConv => q{ + my @dim = unpack("x4N*", $val); + return undef if @dim < 2; + unless ($$self{DOC_NUM}) { + $self->FoundTag(ImageWidth => $dim[0]); + $self->FoundTag(ImageHeight => $dim[1]); + } + return join ' ', @dim; + }, + PrintConv => '$val =~ tr/ /x/; $val', + }, + pixi => { + Name => 'ImagePixelDepth', + Condition => '$$valPt =~ /^\0{4}./s', # (version/flags == 0/0 and count) + RawConv => 'join " ", unpack("x5C*", $val)', + }, + auxC => { + Name => 'AuxiliaryImageType', + Format => 'undef', + RawConv => '$val = substr($val, 4); $val =~ s/\0.*//s; $val', + }, + pasp => { + Name => 'PixelAspectRatio', + Format => 'int32u', + }, + rloc => { + Name => 'RelativeLocation', + Format => 'int32u', + RawConv => '$val =~ s/^\S+\s+//; $val', # remove version/flags + }, + clap => { + Name => 'CleanAperture', + Format => 'rational64u', + Notes => '4 numbers: width, height, left and top', + }, + hvcC => { + Name => 'HEVCConfiguration', + Flags => ['Binary','Unknown'], + }, +); + +%Image::ExifTool::QuickTime::ItemRef = ( + PROCESS_PROC => \&ProcessMOV, + GROUPS => { 2 => 'Image' }, + # (Note: ExifTool's ItemRefVersion may be used to test the iref version number) + # dimg - DerivedImage + # thmb - Thumbnail + # auxl - AuxiliaryImage + cdsc => { + Name => 'ContentDescribes', + Notes => 'parsed, but not extracted as a tag', + RawConv => sub { + my ($val, $et) = @_; + my ($id, $count, @to); + if ($$et{ItemRefVersion}) { + return undef if length $val < 10; + ($id, $count, @to) = unpack('NnN*', $val); + } else { + return undef if length $val < 6; + ($id, $count, @to) = unpack('nnn*', $val); + } + # add all referenced item ID's to a "RefersTo" lookup + $$et{ItemInfo}{$id}{RefersTo}{$_} = 1 foreach @to; + $et->VPrint(1, "$$et{INDENT} Item $id describes: @to\n"); + return undef; + }, + }, +); + +%Image::ExifTool::QuickTime::ItemInfo = ( + PROCESS_PROC => \&ProcessMOV, + GROUPS => { 2 => 'Image' }, + # avc1 - AVC image + # hvc1 - HEVC image + # lhv1 - L-HEVC image + # infe - ItemInformationEntry + # infe types: avc1,hvc1,lhv1,Exif,xml1,iovl(overlay image),grid,mime,hvt1(tile image) + infe => { + Name => 'ItemInfoEntry', + RawConv => \&ParseItemInfoEntry, + Notes => 'parsed, but not extracted as a tag', + }, +); + +# track reference atoms +%Image::ExifTool::QuickTime::TrackRef = ( + PROCESS_PROC => \&ProcessMOV, + GROUPS => { 1 => 'Track#', 2 => 'Video' }, + chap => { Name => 'ChapterListTrackID', Format => 'int32u' }, + tmcd => { Name => 'TimeCode', Format => 'int32u' }, + mpod => { #PH (FLIR MP4) + Name => 'ElementaryStreamTrack', + Format => 'int32u', + ValueConv => '$val =~ s/^1 //; $val', # (why 2 numbers? -- ignore the first if "1") + }, + # also: sync, scpt, ssrc, iTunesInfo + cdsc => { + Name => 'ContentDescribes', + Format => 'int32u', + PrintConv => '"Track $val"', + }, + # cdep (Structural Dependency QT tag?) +); + +# track aperture mode dimensions atoms +# (ref https://developer.apple.com/library/mac/#documentation/QuickTime/QTFF/QTFFChap2/qtff2.html) +%Image::ExifTool::QuickTime::TrackAperture = ( + PROCESS_PROC => \&ProcessMOV, + GROUPS => { 1 => 'Track#', 2 => 'Video' }, + clef => { + Name => 'CleanApertureDimensions', + Format => 'fixed32u', + Count => 3, + ValueConv => '$val =~ s/^.*? //; $val', # remove flags word + PrintConv => '$val =~ tr/ /x/; $val', + }, + prof => { + Name => 'ProductionApertureDimensions', + Format => 'fixed32u', + Count => 3, + ValueConv => '$val =~ s/^.*? //; $val', + PrintConv => '$val =~ tr/ /x/; $val', + }, + enof => { + Name => 'EncodedPixelsDimensions', + Format => 'fixed32u', + Count => 3, + ValueConv => '$val =~ s/^.*? //; $val', + PrintConv => '$val =~ tr/ /x/; $val', + }, +); + +# item list atoms +# -> these atoms are unique, and contain one or more 'data' atoms +%Image::ExifTool::QuickTime::ItemList = ( + PROCESS_PROC => \&ProcessMOV, + GROUPS => { 2 => 'Audio' }, + NOTES => q{ + As well as these tags, the "mdta" handler uses numerical tag ID's which are + added dynamically to this table after processing the Meta Keys information. + }, + # in this table, binary 1 and 2-byte "data"-type tags are interpreted as + # int8u and int16u. Multi-byte binary "data" tags are extracted as binary data + "\xa9ART" => 'Artist', + "\xa9alb" => 'Album', + "\xa9cmt" => 'Comment', + "\xa9com" => 'Composer', + "\xa9day" => { + Name => 'ContentCreateDate', + Groups => { 2 => 'Time' }, + # handle values in the form "2010-02-12T13:27:14-0800" + ValueConv => q{ + require Image::ExifTool::XMP; + $val = Image::ExifTool::XMP::ConvertXMPDate($val); + $val =~ s/([-+]\d{2})(\d{2})$/$1:$2/; # add colon to timezone if necessary + return $val; + }, + PrintConv => '$self->ConvertDateTime($val)', + }, + "\xa9des" => 'Description', #4 + "\xa9enc" => 'EncodedBy', #10 + "\xa9gen" => 'Genre', + "\xa9grp" => 'Grouping', + "\xa9lyr" => 'Lyrics', + "\xa9nam" => 'Title', + # "\xa9st3" ? #10 + "\xa9too" => 'Encoder', + "\xa9trk" => 'Track', + "\xa9wrt" => 'Composer', + '----' => { + Name => 'iTunesInfo', + SubDirectory => { TagTable => 'Image::ExifTool::QuickTime::iTunesInfo' }, + }, + aART => { Name => 'AlbumArtist', Groups => { 2 => 'Author' } }, + covr => { Name => 'CoverArt', Groups => { 2 => 'Preview' } }, + cpil => { #10 + Name => 'Compilation', + PrintConv => { 0 => 'No', 1 => 'Yes' }, + }, + disk => { + Name => 'DiskNumber', + Format => 'undef', # (necessary to prevent decoding as string!) + ValueConv => 'length($val) >= 6 ? join(" of ",unpack("x2nn",$val)) : \$val', + }, + pgap => { #10 + Name => 'PlayGap', + PrintConv => { + 0 => 'Insert Gap', + 1 => 'No Gap', + }, + }, + tmpo => { + Name => 'BeatsPerMinute', + Format => 'int16u', # marked as boolean but really int16u in my sample + }, + trkn => { + Name => 'TrackNumber', + Format => 'undef', # (necessary to prevent decoding as string!) + ValueConv => 'length($val) >= 6 ? join(" of ",unpack("x2nn",$val)) : \$val', + }, +# +# Note: it is possible that the tags below are not being decoded properly +# because I don't have samples to verify many of these - PH +# + akID => { #10 + Name => 'AppleStoreAccountType', + PrintConv => { + 0 => 'iTunes', + 1 => 'AOL', + }, + }, + albm => 'Album', #(ffmpeg source) + apID => 'AppleStoreAccount', + atID => { #10 (or TV series) + Name => 'AlbumTitleID', + Format => 'int32u', + }, + auth => { Name => 'Author', Groups => { 2 => 'Author' } }, + catg => 'Category', #7 + cnID => { #10 + Name => 'AppleStoreCatalogID', + Format => 'int32u', + }, + cprt => { Name => 'Copyright', Groups => { 2 => 'Author' } }, + dscp => 'Description', + desc => 'Description', #7 + gnre => { #10 + Name => 'Genre', + PrintConv => q{ + return $val unless $val =~ /^\d+$/; + require Image::ExifTool::ID3; + Image::ExifTool::ID3::PrintGenre($val - 1); # note the "- 1" + }, + }, + egid => 'EpisodeGlobalUniqueID', #7 + geID => { #10 + Name => 'GenreID', + Format => 'int32u', + SeparateTable => 1, + PrintConv => { #21 (based on https://affiliate.itunes.apple.com/resources/documentation/genre-mapping/) + 2 => 'Music|Blues', + 3 => 'Music|Comedy', + 4 => "Music|Children's Music", + 5 => 'Music|Classical', + 6 => 'Music|Country', + 7 => 'Music|Electronic', + 8 => 'Music|Holiday', + 9 => 'Music|Classical|Opera', + 10 => 'Music|Singer/Songwriter', + 11 => 'Music|Jazz', + 12 => 'Music|Latino', + 13 => 'Music|New Age', + 14 => 'Music|Pop', + 15 => 'Music|R&B/Soul', + 16 => 'Music|Soundtrack', + 17 => 'Music|Dance', + 18 => 'Music|Hip-Hop/Rap', + 19 => 'Music|World', + 20 => 'Music|Alternative', + 21 => 'Music|Rock', + 22 => 'Music|Christian & Gospel', + 23 => 'Music|Vocal', + 24 => 'Music|Reggae', + 25 => 'Music|Easy Listening', + 26 => 'Podcasts', + 27 => 'Music|J-Pop', + 28 => 'Music|Enka', + 29 => 'Music|Anime', + 30 => 'Music|Kayokyoku', + 31 => 'Music Videos', + 32 => 'TV Shows', + 33 => 'Movies', + 34 => 'Music', + 35 => 'iPod Games', + 36 => 'App Store', + 37 => 'Tones', + 38 => 'Books', + 39 => 'Mac App Store', + 40 => 'Textbooks', + 50 => 'Music|Fitness & Workout', + 51 => 'Music|Pop|K-Pop', + 52 => 'Music|Karaoke', + 53 => 'Music|Instrumental', + 74 => 'Audiobooks|News', + 75 => 'Audiobooks|Programs & Performances', + 1001 => 'Music|Alternative|College Rock', + 1002 => 'Music|Alternative|Goth Rock', + 1003 => 'Music|Alternative|Grunge', + 1004 => 'Music|Alternative|Indie Rock', + 1005 => 'Music|Alternative|New Wave', + 1006 => 'Music|Alternative|Punk', + 1007 => 'Music|Blues|Chicago Blues', + 1009 => 'Music|Blues|Classic Blues', + 1010 => 'Music|Blues|Contemporary Blues', + 1011 => 'Music|Blues|Country Blues', + 1012 => 'Music|Blues|Delta Blues', + 1013 => 'Music|Blues|Electric Blues', + 1014 => "Music|Children's Music|Lullabies", + 1015 => "Music|Children's Music|Sing-Along", + 1016 => "Music|Children's Music|Stories", + 1017 => 'Music|Classical|Avant-Garde', + 1018 => 'Music|Classical|Baroque Era', + 1019 => 'Music|Classical|Chamber Music', + 1020 => 'Music|Classical|Chant', + 1021 => 'Music|Classical|Choral', + 1022 => 'Music|Classical|Classical Crossover', + 1023 => 'Music|Classical|Early Music', + 1024 => 'Music|Classical|Impressionist', + 1025 => 'Music|Classical|Medieval Era', + 1026 => 'Music|Classical|Minimalism', + 1027 => 'Music|Classical|Modern Era', + 1028 => 'Music|Classical|Opera', + 1029 => 'Music|Classical|Orchestral', + 1030 => 'Music|Classical|Renaissance', + 1031 => 'Music|Classical|Romantic Era', + 1032 => 'Music|Classical|Wedding Music', + 1033 => 'Music|Country|Alternative Country', + 1034 => 'Music|Country|Americana', + 1035 => 'Music|Country|Bluegrass', + 1036 => 'Music|Country|Contemporary Bluegrass', + 1037 => 'Music|Country|Contemporary Country', + 1038 => 'Music|Country|Country Gospel', + 1039 => 'Music|Country|Honky Tonk', + 1040 => 'Music|Country|Outlaw Country', + 1041 => 'Music|Country|Traditional Bluegrass', + 1042 => 'Music|Country|Traditional Country', + 1043 => 'Music|Country|Urban Cowboy', + 1044 => 'Music|Dance|Breakbeat', + 1045 => 'Music|Dance|Exercise', + 1046 => 'Music|Dance|Garage', + 1047 => 'Music|Dance|Hardcore', + 1048 => 'Music|Dance|House', + 1049 => "Music|Dance|Jungle/Drum'n'bass", + 1050 => 'Music|Dance|Techno', + 1051 => 'Music|Dance|Trance', + 1052 => 'Music|Jazz|Big Band', + 1053 => 'Music|Jazz|Bop', + 1054 => 'Music|Easy Listening|Lounge', + 1055 => 'Music|Easy Listening|Swing', + 1056 => 'Music|Electronic|Ambient', + 1057 => 'Music|Electronic|Downtempo', + 1058 => 'Music|Electronic|Electronica', + 1060 => 'Music|Electronic|IDM/Experimental', + 1061 => 'Music|Electronic|Industrial', + 1062 => 'Music|Singer/Songwriter|Alternative Folk', + 1063 => 'Music|Singer/Songwriter|Contemporary Folk', + 1064 => 'Music|Singer/Songwriter|Contemporary Singer/Songwriter', + 1065 => 'Music|Singer/Songwriter|Folk-Rock', + 1066 => 'Music|Singer/Songwriter|New Acoustic', + 1067 => 'Music|Singer/Songwriter|Traditional Folk', + 1068 => 'Music|Hip-Hop/Rap|Alternative Rap', + 1069 => 'Music|Hip-Hop/Rap|Dirty South', + 1070 => 'Music|Hip-Hop/Rap|East Coast Rap', + 1071 => 'Music|Hip-Hop/Rap|Gangsta Rap', + 1072 => 'Music|Hip-Hop/Rap|Hardcore Rap', + 1073 => 'Music|Hip-Hop/Rap|Hip-Hop', + 1074 => 'Music|Hip-Hop/Rap|Latin Rap', + 1075 => 'Music|Hip-Hop/Rap|Old School Rap', + 1076 => 'Music|Hip-Hop/Rap|Rap', + 1077 => 'Music|Hip-Hop/Rap|Underground Rap', + 1078 => 'Music|Hip-Hop/Rap|West Coast Rap', + 1079 => 'Music|Holiday|Chanukah', + 1080 => 'Music|Holiday|Christmas', + 1081 => "Music|Holiday|Christmas: Children's", + 1082 => 'Music|Holiday|Christmas: Classic', + 1083 => 'Music|Holiday|Christmas: Classical', + 1084 => 'Music|Holiday|Christmas: Jazz', + 1085 => 'Music|Holiday|Christmas: Modern', + 1086 => 'Music|Holiday|Christmas: Pop', + 1087 => 'Music|Holiday|Christmas: R&B', + 1088 => 'Music|Holiday|Christmas: Religious', + 1089 => 'Music|Holiday|Christmas: Rock', + 1090 => 'Music|Holiday|Easter', + 1091 => 'Music|Holiday|Halloween', + 1092 => 'Music|Holiday|Holiday: Other', + 1093 => 'Music|Holiday|Thanksgiving', + 1094 => 'Music|Christian & Gospel|CCM', + 1095 => 'Music|Christian & Gospel|Christian Metal', + 1096 => 'Music|Christian & Gospel|Christian Pop', + 1097 => 'Music|Christian & Gospel|Christian Rap', + 1098 => 'Music|Christian & Gospel|Christian Rock', + 1099 => 'Music|Christian & Gospel|Classic Christian', + 1100 => 'Music|Christian & Gospel|Contemporary Gospel', + 1101 => 'Music|Christian & Gospel|Gospel', + 1103 => 'Music|Christian & Gospel|Praise & Worship', + 1104 => 'Music|Christian & Gospel|Southern Gospel', + 1105 => 'Music|Christian & Gospel|Traditional Gospel', + 1106 => 'Music|Jazz|Avant-Garde Jazz', + 1107 => 'Music|Jazz|Contemporary Jazz', + 1108 => 'Music|Jazz|Crossover Jazz', + 1109 => 'Music|Jazz|Dixieland', + 1110 => 'Music|Jazz|Fusion', + 1111 => 'Music|Jazz|Latin Jazz', + 1112 => 'Music|Jazz|Mainstream Jazz', + 1113 => 'Music|Jazz|Ragtime', + 1114 => 'Music|Jazz|Smooth Jazz', + 1115 => 'Music|Latino|Latin Jazz', + 1116 => 'Music|Latino|Contemporary Latin', + 1117 => 'Music|Latino|Pop Latino', + 1118 => 'Music|Latino|Raices', # (Ra&iacute;ces) + 1119 => 'Music|Latino|Latin Urban', + 1120 => 'Music|Latino|Baladas y Boleros', + 1121 => 'Music|Latino|Rock y Alternativo', + 1122 => 'Music|Brazilian', + 1123 => 'Music|Latino|Musica Mexicana', # (M&uacute;sica Mexicana) + 1124 => 'Music|Latino|Salsa y Tropical', + 1125 => 'Music|New Age|Environmental', + 1126 => 'Music|New Age|Healing', + 1127 => 'Music|New Age|Meditation', + 1128 => 'Music|New Age|Nature', + 1129 => 'Music|New Age|Relaxation', + 1130 => 'Music|New Age|Travel', + 1131 => 'Music|Pop|Adult Contemporary', + 1132 => 'Music|Pop|Britpop', + 1133 => 'Music|Pop|Pop/Rock', + 1134 => 'Music|Pop|Soft Rock', + 1135 => 'Music|Pop|Teen Pop', + 1136 => 'Music|R&B/Soul|Contemporary R&B', + 1137 => 'Music|R&B/Soul|Disco', + 1138 => 'Music|R&B/Soul|Doo Wop', + 1139 => 'Music|R&B/Soul|Funk', + 1140 => 'Music|R&B/Soul|Motown', + 1141 => 'Music|R&B/Soul|Neo-Soul', + 1142 => 'Music|R&B/Soul|Quiet Storm', + 1143 => 'Music|R&B/Soul|Soul', + 1144 => 'Music|Rock|Adult Alternative', + 1145 => 'Music|Rock|American Trad Rock', + 1146 => 'Music|Rock|Arena Rock', + 1147 => 'Music|Rock|Blues-Rock', + 1148 => 'Music|Rock|British Invasion', + 1149 => 'Music|Rock|Death Metal/Black Metal', + 1150 => 'Music|Rock|Glam Rock', + 1151 => 'Music|Rock|Hair Metal', + 1152 => 'Music|Rock|Hard Rock', + 1153 => 'Music|Rock|Metal', + 1154 => 'Music|Rock|Jam Bands', + 1155 => 'Music|Rock|Prog-Rock/Art Rock', + 1156 => 'Music|Rock|Psychedelic', + 1157 => 'Music|Rock|Rock & Roll', + 1158 => 'Music|Rock|Rockabilly', + 1159 => 'Music|Rock|Roots Rock', + 1160 => 'Music|Rock|Singer/Songwriter', + 1161 => 'Music|Rock|Southern Rock', + 1162 => 'Music|Rock|Surf', + 1163 => 'Music|Rock|Tex-Mex', + 1165 => 'Music|Soundtrack|Foreign Cinema', + 1166 => 'Music|Soundtrack|Musicals', + 1167 => 'Music|Comedy|Novelty', + 1168 => 'Music|Soundtrack|Original Score', + 1169 => 'Music|Soundtrack|Soundtrack', + 1171 => 'Music|Comedy|Standup Comedy', + 1172 => 'Music|Soundtrack|TV Soundtrack', + 1173 => 'Music|Vocal|Standards', + 1174 => 'Music|Vocal|Traditional Pop', + 1175 => 'Music|Jazz|Vocal Jazz', + 1176 => 'Music|Vocal|Vocal Pop', + 1177 => 'Music|World|Afro-Beat', + 1178 => 'Music|World|Afro-Pop', + 1179 => 'Music|World|Cajun', + 1180 => 'Music|World|Celtic', + 1181 => 'Music|World|Celtic Folk', + 1182 => 'Music|World|Contemporary Celtic', + 1183 => 'Music|Reggae|Modern Dancehall', + 1184 => 'Music|World|Drinking Songs', + 1185 => 'Music|Indian|Indian Pop', + 1186 => 'Music|World|Japanese Pop', + 1187 => 'Music|World|Klezmer', + 1188 => 'Music|World|Polka', + 1189 => 'Music|World|Traditional Celtic', + 1190 => 'Music|World|Worldbeat', + 1191 => 'Music|World|Zydeco', + 1192 => 'Music|Reggae|Roots Reggae', + 1193 => 'Music|Reggae|Dub', + 1194 => 'Music|Reggae|Ska', + 1195 => 'Music|World|Caribbean', + 1196 => 'Music|World|South America', + 1197 => 'Music|Arabic', + 1198 => 'Music|World|North America', + 1199 => 'Music|World|Hawaii', + 1200 => 'Music|World|Australia', + 1201 => 'Music|World|Japan', + 1202 => 'Music|World|France', + 1203 => 'Music|World|Africa', + 1204 => 'Music|World|Asia', + 1205 => 'Music|World|Europe', + 1206 => 'Music|World|South Africa', + 1207 => 'Music|Jazz|Hard Bop', + 1208 => 'Music|Jazz|Trad Jazz', + 1209 => 'Music|Jazz|Cool Jazz', + 1210 => 'Music|Blues|Acoustic Blues', + 1211 => 'Music|Classical|High Classical', + 1220 => 'Music|Brazilian|Axe', # (Ax&eacute;) + 1221 => 'Music|Brazilian|Bossa Nova', + 1222 => 'Music|Brazilian|Choro', + 1223 => 'Music|Brazilian|Forro', # (Forr&oacute;) + 1224 => 'Music|Brazilian|Frevo', + 1225 => 'Music|Brazilian|MPB', + 1226 => 'Music|Brazilian|Pagode', + 1227 => 'Music|Brazilian|Samba', + 1228 => 'Music|Brazilian|Sertanejo', + 1229 => 'Music|Brazilian|Baile Funk', + 1230 => 'Music|Alternative|Chinese Alt', + 1231 => 'Music|Alternative|Korean Indie', + 1232 => 'Music|Chinese', + 1233 => 'Music|Chinese|Chinese Classical', + 1234 => 'Music|Chinese|Chinese Flute', + 1235 => 'Music|Chinese|Chinese Opera', + 1236 => 'Music|Chinese|Chinese Orchestral', + 1237 => 'Music|Chinese|Chinese Regional Folk', + 1238 => 'Music|Chinese|Chinese Strings', + 1239 => 'Music|Chinese|Taiwanese Folk', + 1240 => 'Music|Chinese|Tibetan Native Music', + 1241 => 'Music|Hip-Hop/Rap|Chinese Hip-Hop', + 1242 => 'Music|Hip-Hop/Rap|Korean Hip-Hop', + 1243 => 'Music|Korean', + 1244 => 'Music|Korean|Korean Classical', + 1245 => 'Music|Korean|Korean Trad Song', + 1246 => 'Music|Korean|Korean Trad Instrumental', + 1247 => 'Music|Korean|Korean Trad Theater', + 1248 => 'Music|Rock|Chinese Rock', + 1249 => 'Music|Rock|Korean Rock', + 1250 => 'Music|Pop|C-Pop', + 1251 => 'Music|Pop|Cantopop/HK-Pop', + 1252 => 'Music|Pop|Korean Folk-Pop', + 1253 => 'Music|Pop|Mandopop', + 1254 => 'Music|Pop|Tai-Pop', + 1255 => 'Music|Pop|Malaysian Pop', + 1256 => 'Music|Pop|Pinoy Pop', + 1257 => 'Music|Pop|Original Pilipino Music', + 1258 => 'Music|Pop|Manilla Sound', + 1259 => 'Music|Pop|Indo Pop', + 1260 => 'Music|Pop|Thai Pop', + 1261 => 'Music|Vocal|Trot', + 1262 => 'Music|Indian', + 1263 => 'Music|Indian|Bollywood', + 1264 => 'Music|Indian|Tamil', + 1265 => 'Music|Indian|Telugu', + 1266 => 'Music|Indian|Regional Indian', + 1267 => 'Music|Indian|Devotional & Spiritual', + 1268 => 'Music|Indian|Sufi', + 1269 => 'Music|Indian|Indian Classical', + 1270 => 'Music|World|Russian Chanson', + 1271 => 'Music|World|Dini', + 1272 => 'Music|World|Halk', + 1273 => 'Music|World|Sanat', + 1274 => 'Music|World|Dangdut', + 1275 => 'Music|World|Indonesian Religious', + 1276 => 'Music|World|Calypso', + 1277 => 'Music|World|Soca', + 1278 => 'Music|Indian|Ghazals', + 1279 => 'Music|Indian|Indian Folk', + 1280 => 'Music|World|Arabesque', + 1281 => 'Music|World|Afrikaans', + 1282 => 'Music|World|Farsi', + 1283 => 'Music|World|Israeli', + 1284 => 'Music|Arabic|Khaleeji', + 1285 => 'Music|Arabic|North African', + 1286 => 'Music|Arabic|Arabic Pop', + 1287 => 'Music|Arabic|Islamic', + 1288 => 'Music|Soundtrack|Sound Effects', + 1289 => 'Music|Folk', + 1290 => 'Music|Orchestral', + 1291 => 'Music|Marching', + 1293 => 'Music|Pop|Oldies', + 1294 => 'Music|Country|Thai Country', + 1295 => 'Music|World|Flamenco', + 1296 => 'Music|World|Tango', + 1297 => 'Music|World|Fado', + 1298 => 'Music|World|Iberia', + 1299 => 'Music|World|Russian', + 1300 => 'Music|World|Turkish', + 1301 => 'Podcasts|Arts', + 1302 => 'Podcasts|Society & Culture|Personal Journals', + 1303 => 'Podcasts|Comedy', + 1304 => 'Podcasts|Education', + 1305 => 'Podcasts|Kids & Family', + 1306 => 'Podcasts|Arts|Food', + 1307 => 'Podcasts|Health', + 1309 => 'Podcasts|TV & Film', + 1310 => 'Podcasts|Music', + 1311 => 'Podcasts|News & Politics', + 1314 => 'Podcasts|Religion & Spirituality', + 1315 => 'Podcasts|Science & Medicine', + 1316 => 'Podcasts|Sports & Recreation', + 1318 => 'Podcasts|Technology', + 1320 => 'Podcasts|Society & Culture|Places & Travel', + 1321 => 'Podcasts|Business', + 1323 => 'Podcasts|Games & Hobbies', + 1324 => 'Podcasts|Society & Culture', + 1325 => 'Podcasts|Government & Organizations', + 1337 => 'Music Videos|Classical|Piano', + 1401 => 'Podcasts|Arts|Literature', + 1402 => 'Podcasts|Arts|Design', + 1404 => 'Podcasts|Games & Hobbies|Video Games', + 1405 => 'Podcasts|Arts|Performing Arts', + 1406 => 'Podcasts|Arts|Visual Arts', + 1410 => 'Podcasts|Business|Careers', + 1412 => 'Podcasts|Business|Investing', + 1413 => 'Podcasts|Business|Management & Marketing', + 1415 => 'Podcasts|Education|K-12', + 1416 => 'Podcasts|Education|Higher Education', + 1417 => 'Podcasts|Health|Fitness & Nutrition', + 1420 => 'Podcasts|Health|Self-Help', + 1421 => 'Podcasts|Health|Sexuality', + 1438 => 'Podcasts|Religion & Spirituality|Buddhism', + 1439 => 'Podcasts|Religion & Spirituality|Christianity', + 1440 => 'Podcasts|Religion & Spirituality|Islam', + 1441 => 'Podcasts|Religion & Spirituality|Judaism', + 1443 => 'Podcasts|Society & Culture|Philosophy', + 1444 => 'Podcasts|Religion & Spirituality|Spirituality', + 1446 => 'Podcasts|Technology|Gadgets', + 1448 => 'Podcasts|Technology|Tech News', + 1450 => 'Podcasts|Technology|Podcasting', + 1454 => 'Podcasts|Games & Hobbies|Automotive', + 1455 => 'Podcasts|Games & Hobbies|Aviation', + 1456 => 'Podcasts|Sports & Recreation|Outdoor', + 1459 => 'Podcasts|Arts|Fashion & Beauty', + 1460 => 'Podcasts|Games & Hobbies|Hobbies', + 1461 => 'Podcasts|Games & Hobbies|Other Games', + 1462 => 'Podcasts|Society & Culture|History', + 1463 => 'Podcasts|Religion & Spirituality|Hinduism', + 1464 => 'Podcasts|Religion & Spirituality|Other', + 1465 => 'Podcasts|Sports & Recreation|Professional', + 1466 => 'Podcasts|Sports & Recreation|College & High School', + 1467 => 'Podcasts|Sports & Recreation|Amateur', + 1468 => 'Podcasts|Education|Educational Technology', + 1469 => 'Podcasts|Education|Language Courses', + 1470 => 'Podcasts|Education|Training', + 1471 => 'Podcasts|Business|Business News', + 1472 => 'Podcasts|Business|Shopping', + 1473 => 'Podcasts|Government & Organizations|National', + 1474 => 'Podcasts|Government & Organizations|Regional', + 1475 => 'Podcasts|Government & Organizations|Local', + 1476 => 'Podcasts|Government & Organizations|Non-Profit', + 1477 => 'Podcasts|Science & Medicine|Natural Sciences', + 1478 => 'Podcasts|Science & Medicine|Medicine', + 1479 => 'Podcasts|Science & Medicine|Social Sciences', + 1480 => 'Podcasts|Technology|Software How-To', + 1481 => 'Podcasts|Health|Alternative Health', + 1602 => 'Music Videos|Blues', + 1603 => 'Music Videos|Comedy', + 1604 => "Music Videos|Children's Music", + 1605 => 'Music Videos|Classical', + 1606 => 'Music Videos|Country', + 1607 => 'Music Videos|Electronic', + 1608 => 'Music Videos|Holiday', + 1609 => 'Music Videos|Classical|Opera', + 1610 => 'Music Videos|Singer/Songwriter', + 1611 => 'Music Videos|Jazz', + 1612 => 'Music Videos|Latin', + 1613 => 'Music Videos|New Age', + 1614 => 'Music Videos|Pop', + 1615 => 'Music Videos|R&B/Soul', + 1616 => 'Music Videos|Soundtrack', + 1617 => 'Music Videos|Dance', + 1618 => 'Music Videos|Hip-Hop/Rap', + 1619 => 'Music Videos|World', + 1620 => 'Music Videos|Alternative', + 1621 => 'Music Videos|Rock', + 1622 => 'Music Videos|Christian & Gospel', + 1623 => 'Music Videos|Vocal', + 1624 => 'Music Videos|Reggae', + 1625 => 'Music Videos|Easy Listening', + 1626 => 'Music Videos|Podcasts', + 1627 => 'Music Videos|J-Pop', + 1628 => 'Music Videos|Enka', + 1629 => 'Music Videos|Anime', + 1630 => 'Music Videos|Kayokyoku', + 1631 => 'Music Videos|Disney', + 1632 => 'Music Videos|French Pop', + 1633 => 'Music Videos|German Pop', + 1634 => 'Music Videos|German Folk', + 1635 => 'Music Videos|Alternative|Chinese Alt', + 1636 => 'Music Videos|Alternative|Korean Indie', + 1637 => 'Music Videos|Chinese', + 1638 => 'Music Videos|Chinese|Chinese Classical', + 1639 => 'Music Videos|Chinese|Chinese Flute', + 1640 => 'Music Videos|Chinese|Chinese Opera', + 1641 => 'Music Videos|Chinese|Chinese Orchestral', + 1642 => 'Music Videos|Chinese|Chinese Regional Folk', + 1643 => 'Music Videos|Chinese|Chinese Strings', + 1644 => 'Music Videos|Chinese|Taiwanese Folk', + 1645 => 'Music Videos|Chinese|Tibetan Native Music', + 1646 => 'Music Videos|Hip-Hop/Rap|Chinese Hip-Hop', + 1647 => 'Music Videos|Hip-Hop/Rap|Korean Hip-Hop', + 1648 => 'Music Videos|Korean', + 1649 => 'Music Videos|Korean|Korean Classical', + 1650 => 'Music Videos|Korean|Korean Trad Song', + 1651 => 'Music Videos|Korean|Korean Trad Instrumental', + 1652 => 'Music Videos|Korean|Korean Trad Theater', + 1653 => 'Music Videos|Rock|Chinese Rock', + 1654 => 'Music Videos|Rock|Korean Rock', + 1655 => 'Music Videos|Pop|C-Pop', + 1656 => 'Music Videos|Pop|Cantopop/HK-Pop', + 1657 => 'Music Videos|Pop|Korean Folk-Pop', + 1658 => 'Music Videos|Pop|Mandopop', + 1659 => 'Music Videos|Pop|Tai-Pop', + 1660 => 'Music Videos|Pop|Malaysian Pop', + 1661 => 'Music Videos|Pop|Pinoy Pop', + 1662 => 'Music Videos|Pop|Original Pilipino Music', + 1663 => 'Music Videos|Pop|Manilla Sound', + 1664 => 'Music Videos|Pop|Indo Pop', + 1665 => 'Music Videos|Pop|Thai Pop', + 1666 => 'Music Videos|Vocal|Trot', + 1671 => 'Music Videos|Brazilian', + 1672 => 'Music Videos|Brazilian|Axe', # (Ax&eacute;) + 1673 => 'Music Videos|Brazilian|Baile Funk', + 1674 => 'Music Videos|Brazilian|Bossa Nova', + 1675 => 'Music Videos|Brazilian|Choro', + 1676 => 'Music Videos|Brazilian|Forro', + 1677 => 'Music Videos|Brazilian|Frevo', + 1678 => 'Music Videos|Brazilian|MPB', + 1679 => 'Music Videos|Brazilian|Pagode', + 1680 => 'Music Videos|Brazilian|Samba', + 1681 => 'Music Videos|Brazilian|Sertanejo', + 1682 => 'Music Videos|Classical|High Classical', + 1683 => 'Music Videos|Fitness & Workout', + 1684 => 'Music Videos|Instrumental', + 1685 => 'Music Videos|Jazz|Big Band', + 1686 => 'Music Videos|Pop|K-Pop', + 1687 => 'Music Videos|Karaoke', + 1688 => 'Music Videos|Rock|Heavy Metal', + 1689 => 'Music Videos|Spoken Word', + 1690 => 'Music Videos|Indian', + 1691 => 'Music Videos|Indian|Bollywood', + 1692 => 'Music Videos|Indian|Tamil', + 1693 => 'Music Videos|Indian|Telugu', + 1694 => 'Music Videos|Indian|Regional Indian', + 1695 => 'Music Videos|Indian|Devotional & Spiritual', + 1696 => 'Music Videos|Indian|Sufi', + 1697 => 'Music Videos|Indian|Indian Classical', + 1698 => 'Music Videos|World|Russian Chanson', + 1699 => 'Music Videos|World|Dini', + 1700 => 'Music Videos|World|Halk', + 1701 => 'Music Videos|World|Sanat', + 1702 => 'Music Videos|World|Dangdut', + 1703 => 'Music Videos|World|Indonesian Religious', + 1704 => 'Music Videos|Indian|Indian Pop', + 1705 => 'Music Videos|World|Calypso', + 1706 => 'Music Videos|World|Soca', + 1707 => 'Music Videos|Indian|Ghazals', + 1708 => 'Music Videos|Indian|Indian Folk', + 1709 => 'Music Videos|World|Arabesque', + 1710 => 'Music Videos|World|Afrikaans', + 1711 => 'Music Videos|World|Farsi', + 1712 => 'Music Videos|World|Israeli', + 1713 => 'Music Videos|Arabic', + 1714 => 'Music Videos|Arabic|Khaleeji', + 1715 => 'Music Videos|Arabic|North African', + 1716 => 'Music Videos|Arabic|Arabic Pop', + 1717 => 'Music Videos|Arabic|Islamic', + 1718 => 'Music Videos|Soundtrack|Sound Effects', + 1719 => 'Music Videos|Folk', + 1720 => 'Music Videos|Orchestral', + 1721 => 'Music Videos|Marching', + 1723 => 'Music Videos|Pop|Oldies', + 1724 => 'Music Videos|Country|Thai Country', + 1725 => 'Music Videos|World|Flamenco', + 1726 => 'Music Videos|World|Tango', + 1727 => 'Music Videos|World|Fado', + 1728 => 'Music Videos|World|Iberia', + 1729 => 'Music Videos|World|Russian', + 1730 => 'Music Videos|World|Turkish', + 1731 => 'Music Videos|Alternative|College Rock', + 1732 => 'Music Videos|Alternative|Goth Rock', + 1733 => 'Music Videos|Alternative|Grunge', + 1734 => 'Music Videos|Alternative|Indie Rock', + 1735 => 'Music Videos|Alternative|New Wave', + 1736 => 'Music Videos|Alternative|Punk', + 1737 => 'Music Videos|Blues|Acoustic Blues', + 1738 => 'Music Videos|Blues|Chicago Blues', + 1739 => 'Music Videos|Blues|Classic Blues', + 1740 => 'Music Videos|Blues|Contemporary Blues', + 1741 => 'Music Videos|Blues|Country Blues', + 1742 => 'Music Videos|Blues|Delta Blues', + 1743 => 'Music Videos|Blues|Electric Blues', + 1744 => "Music Videos|Children's Music|Lullabies", + 1745 => "Music Videos|Children's Music|Sing-Along", + 1746 => "Music Videos|Children's Music|Stories", + 1747 => 'Music Videos|Christian & Gospel|CCM', + 1748 => 'Music Videos|Christian & Gospel|Christian Metal', + 1749 => 'Music Videos|Christian & Gospel|Christian Pop', + 1750 => 'Music Videos|Christian & Gospel|Christian Rap', + 1751 => 'Music Videos|Christian & Gospel|Christian Rock', + 1752 => 'Music Videos|Christian & Gospel|Classic Christian', + 1753 => 'Music Videos|Christian & Gospel|Contemporary Gospel', + 1754 => 'Music Videos|Christian & Gospel|Gospel', + 1755 => 'Music Videos|Christian & Gospel|Praise & Worship', + 1756 => 'Music Videos|Christian & Gospel|Southern Gospel', + 1757 => 'Music Videos|Christian & Gospel|Traditional Gospel', + 1758 => 'Music Videos|Classical|Avant-Garde', + 1759 => 'Music Videos|Classical|Baroque Era', + 1760 => 'Music Videos|Classical|Chamber Music', + 1761 => 'Music Videos|Classical|Chant', + 1762 => 'Music Videos|Classical|Choral', + 1763 => 'Music Videos|Classical|Classical Crossover', + 1764 => 'Music Videos|Classical|Early Music', + 1765 => 'Music Videos|Classical|Impressionist', + 1766 => 'Music Videos|Classical|Medieval Era', + 1767 => 'Music Videos|Classical|Minimalism', + 1768 => 'Music Videos|Classical|Modern Era', + 1769 => 'Music Videos|Classical|Orchestral', + 1770 => 'Music Videos|Classical|Renaissance', + 1771 => 'Music Videos|Classical|Romantic Era', + 1772 => 'Music Videos|Classical|Wedding Music', + 1773 => 'Music Videos|Comedy|Novelty', + 1774 => 'Music Videos|Comedy|Standup Comedy', + 1775 => 'Music Videos|Country|Alternative Country', + 1776 => 'Music Videos|Country|Americana', + 1777 => 'Music Videos|Country|Bluegrass', + 1778 => 'Music Videos|Country|Contemporary Bluegrass', + 1779 => 'Music Videos|Country|Contemporary Country', + 1780 => 'Music Videos|Country|Country Gospel', + 1781 => 'Music Videos|Country|Honky Tonk', + 1782 => 'Music Videos|Country|Outlaw Country', + 1783 => 'Music Videos|Country|Traditional Bluegrass', + 1784 => 'Music Videos|Country|Traditional Country', + 1785 => 'Music Videos|Country|Urban Cowboy', + 1786 => 'Music Videos|Dance|Breakbeat', + 1787 => 'Music Videos|Dance|Exercise', + 1788 => 'Music Videos|Dance|Garage', + 1789 => 'Music Videos|Dance|Hardcore', + 1790 => 'Music Videos|Dance|House', + 1791 => "Music Videos|Dance|Jungle/Drum'n'bass", + 1792 => 'Music Videos|Dance|Techno', + 1793 => 'Music Videos|Dance|Trance', + 1794 => 'Music Videos|Easy Listening|Lounge', + 1795 => 'Music Videos|Easy Listening|Swing', + 1796 => 'Music Videos|Electronic|Ambient', + 1797 => 'Music Videos|Electronic|Downtempo', + 1798 => 'Music Videos|Electronic|Electronica', + 1799 => 'Music Videos|Electronic|IDM/Experimental', + 1800 => 'Music Videos|Electronic|Industrial', + 1801 => 'Music Videos|Hip-Hop/Rap|Alternative Rap', + 1802 => 'Music Videos|Hip-Hop/Rap|Dirty South', + 1803 => 'Music Videos|Hip-Hop/Rap|East Coast Rap', + 1804 => 'Music Videos|Hip-Hop/Rap|Gangsta Rap', + 1805 => 'Music Videos|Hip-Hop/Rap|Hardcore Rap', + 1806 => 'Music Videos|Hip-Hop/Rap|Hip-Hop', + 1807 => 'Music Videos|Hip-Hop/Rap|Latin Rap', + 1808 => 'Music Videos|Hip-Hop/Rap|Old School Rap', + 1809 => 'Music Videos|Hip-Hop/Rap|Rap', + 1810 => 'Music Videos|Hip-Hop/Rap|Underground Rap', + 1811 => 'Music Videos|Hip-Hop/Rap|West Coast Rap', + 1812 => 'Music Videos|Holiday|Chanukah', + 1813 => 'Music Videos|Holiday|Christmas', + 1814 => "Music Videos|Holiday|Christmas: Children's", + 1815 => 'Music Videos|Holiday|Christmas: Classic', + 1816 => 'Music Videos|Holiday|Christmas: Classical', + 1817 => 'Music Videos|Holiday|Christmas: Jazz', + 1818 => 'Music Videos|Holiday|Christmas: Modern', + 1819 => 'Music Videos|Holiday|Christmas: Pop', + 1820 => 'Music Videos|Holiday|Christmas: R&B', + 1821 => 'Music Videos|Holiday|Christmas: Religious', + 1822 => 'Music Videos|Holiday|Christmas: Rock', + 1823 => 'Music Videos|Holiday|Easter', + 1824 => 'Music Videos|Holiday|Halloween', + 1825 => 'Music Videos|Holiday|Thanksgiving', + 1826 => 'Music Videos|Jazz|Avant-Garde Jazz', + 1828 => 'Music Videos|Jazz|Bop', + 1829 => 'Music Videos|Jazz|Contemporary Jazz', + 1830 => 'Music Videos|Jazz|Cool Jazz', + 1831 => 'Music Videos|Jazz|Crossover Jazz', + 1832 => 'Music Videos|Jazz|Dixieland', + 1833 => 'Music Videos|Jazz|Fusion', + 1834 => 'Music Videos|Jazz|Hard Bop', + 1835 => 'Music Videos|Jazz|Latin Jazz', + 1836 => 'Music Videos|Jazz|Mainstream Jazz', + 1837 => 'Music Videos|Jazz|Ragtime', + 1838 => 'Music Videos|Jazz|Smooth Jazz', + 1839 => 'Music Videos|Jazz|Trad Jazz', + 1840 => 'Music Videos|Latin|Alternative & Rock in Spanish', + 1841 => 'Music Videos|Latin|Baladas y Boleros', + 1842 => 'Music Videos|Latin|Contemporary Latin', + 1843 => 'Music Videos|Latin|Latin Jazz', + 1844 => 'Music Videos|Latin|Latin Urban', + 1845 => 'Music Videos|Latin|Pop in Spanish', + 1846 => 'Music Videos|Latin|Raices', + 1847 => 'Music Videos|Latin|Musica Mexicana', # (M&uacute;sica Mexicana) + 1848 => 'Music Videos|Latin|Salsa y Tropical', + 1849 => 'Music Videos|New Age|Healing', + 1850 => 'Music Videos|New Age|Meditation', + 1851 => 'Music Videos|New Age|Nature', + 1852 => 'Music Videos|New Age|Relaxation', + 1853 => 'Music Videos|New Age|Travel', + 1854 => 'Music Videos|Pop|Adult Contemporary', + 1855 => 'Music Videos|Pop|Britpop', + 1856 => 'Music Videos|Pop|Pop/Rock', + 1857 => 'Music Videos|Pop|Soft Rock', + 1858 => 'Music Videos|Pop|Teen Pop', + 1859 => 'Music Videos|R&B/Soul|Contemporary R&B', + 1860 => 'Music Videos|R&B/Soul|Disco', + 1861 => 'Music Videos|R&B/Soul|Doo Wop', + 1862 => 'Music Videos|R&B/Soul|Funk', + 1863 => 'Music Videos|R&B/Soul|Motown', + 1864 => 'Music Videos|R&B/Soul|Neo-Soul', + 1865 => 'Music Videos|R&B/Soul|Soul', + 1866 => 'Music Videos|Reggae|Modern Dancehall', + 1867 => 'Music Videos|Reggae|Dub', + 1868 => 'Music Videos|Reggae|Roots Reggae', + 1869 => 'Music Videos|Reggae|Ska', + 1870 => 'Music Videos|Rock|Adult Alternative', + 1871 => 'Music Videos|Rock|American Trad Rock', + 1872 => 'Music Videos|Rock|Arena Rock', + 1873 => 'Music Videos|Rock|Blues-Rock', + 1874 => 'Music Videos|Rock|British Invasion', + 1875 => 'Music Videos|Rock|Death Metal/Black Metal', + 1876 => 'Music Videos|Rock|Glam Rock', + 1877 => 'Music Videos|Rock|Hair Metal', + 1878 => 'Music Videos|Rock|Hard Rock', + 1879 => 'Music Videos|Rock|Jam Bands', + 1880 => 'Music Videos|Rock|Prog-Rock/Art Rock', + 1881 => 'Music Videos|Rock|Psychedelic', + 1882 => 'Music Videos|Rock|Rock & Roll', + 1883 => 'Music Videos|Rock|Rockabilly', + 1884 => 'Music Videos|Rock|Roots Rock', + 1885 => 'Music Videos|Rock|Singer/Songwriter', + 1886 => 'Music Videos|Rock|Southern Rock', + 1887 => 'Music Videos|Rock|Surf', + 1888 => 'Music Videos|Rock|Tex-Mex', + 1889 => 'Music Videos|Singer/Songwriter|Alternative Folk', + 1890 => 'Music Videos|Singer/Songwriter|Contemporary Folk', + 1891 => 'Music Videos|Singer/Songwriter|Contemporary Singer/Songwriter', + 1892 => 'Music Videos|Singer/Songwriter|Folk-Rock', + 1893 => 'Music Videos|Singer/Songwriter|New Acoustic', + 1894 => 'Music Videos|Singer/Songwriter|Traditional Folk', + 1895 => 'Music Videos|Soundtrack|Foreign Cinema', + 1896 => 'Music Videos|Soundtrack|Musicals', + 1897 => 'Music Videos|Soundtrack|Original Score', + 1898 => 'Music Videos|Soundtrack|Soundtrack', + 1899 => 'Music Videos|Soundtrack|TV Soundtrack', + 1900 => 'Music Videos|Vocal|Standards', + 1901 => 'Music Videos|Vocal|Traditional Pop', + 1902 => 'Music Videos|Jazz|Vocal Jazz', + 1903 => 'Music Videos|Vocal|Vocal Pop', + 1904 => 'Music Videos|World|Africa', + 1905 => 'Music Videos|World|Afro-Beat', + 1906 => 'Music Videos|World|Afro-Pop', + 1907 => 'Music Videos|World|Asia', + 1908 => 'Music Videos|World|Australia', + 1909 => 'Music Videos|World|Cajun', + 1910 => 'Music Videos|World|Caribbean', + 1911 => 'Music Videos|World|Celtic', + 1912 => 'Music Videos|World|Celtic Folk', + 1913 => 'Music Videos|World|Contemporary Celtic', + 1914 => 'Music Videos|World|Europe', + 1915 => 'Music Videos|World|France', + 1916 => 'Music Videos|World|Hawaii', + 1917 => 'Music Videos|World|Japan', + 1918 => 'Music Videos|World|Klezmer', + 1919 => 'Music Videos|World|North America', + 1920 => 'Music Videos|World|Polka', + 1921 => 'Music Videos|World|South Africa', + 1922 => 'Music Videos|World|South America', + 1923 => 'Music Videos|World|Traditional Celtic', + 1924 => 'Music Videos|World|Worldbeat', + 1925 => 'Music Videos|World|Zydeco', + 1926 => 'Music Videos|Christian & Gospel', + 1928 => 'Music Videos|Classical|Art Song', + 1929 => 'Music Videos|Classical|Brass & Woodwinds', + 1930 => 'Music Videos|Classical|Solo Instrumental', + 1931 => 'Music Videos|Classical|Contemporary Era', + 1932 => 'Music Videos|Classical|Oratorio', + 1933 => 'Music Videos|Classical|Cantata', + 1934 => 'Music Videos|Classical|Electronic', + 1935 => 'Music Videos|Classical|Sacred', + 1936 => 'Music Videos|Classical|Guitar', + 1938 => 'Music Videos|Classical|Violin', + 1939 => 'Music Videos|Classical|Cello', + 1940 => 'Music Videos|Classical|Percussion', + 1941 => 'Music Videos|Electronic|Dubstep', + 1942 => 'Music Videos|Electronic|Bass', + 1943 => 'Music Videos|Hip-Hop/Rap|UK Hip-Hop', + 1944 => 'Music Videos|Reggae|Lovers Rock', + 1945 => 'Music Videos|Alternative|EMO', + 1946 => 'Music Videos|Alternative|Pop Punk', + 1947 => 'Music Videos|Alternative|Indie Pop', + 1948 => 'Music Videos|New Age|Yoga', + 1949 => 'Music Videos|Pop|Tribute', + 1950 => 'Music Videos|Pop|Shows', + 4000 => 'TV Shows|Comedy', + 4001 => 'TV Shows|Drama', + 4002 => 'TV Shows|Animation', + 4003 => 'TV Shows|Action & Adventure', + 4004 => 'TV Shows|Classic', + 4005 => 'TV Shows|Kids', + 4006 => 'TV Shows|Nonfiction', + 4007 => 'TV Shows|Reality TV', + 4008 => 'TV Shows|Sci-Fi & Fantasy', + 4009 => 'TV Shows|Sports', + 4010 => 'TV Shows|Teens', + 4011 => 'TV Shows|Latino TV', + 4401 => 'Movies|Action & Adventure', + 4402 => 'Movies|Anime', + 4403 => 'Movies|Classics', + 4404 => 'Movies|Comedy', + 4405 => 'Movies|Documentary', + 4406 => 'Movies|Drama', + 4407 => 'Movies|Foreign', + 4408 => 'Movies|Horror', + 4409 => 'Movies|Independent', + 4410 => 'Movies|Kids & Family', + 4411 => 'Movies|Musicals', + 4412 => 'Movies|Romance', + 4413 => 'Movies|Sci-Fi & Fantasy', + 4414 => 'Movies|Short Films', + 4415 => 'Movies|Special Interest', + 4416 => 'Movies|Thriller', + 4417 => 'Movies|Sports', + 4418 => 'Movies|Western', + 4419 => 'Movies|Urban', + 4420 => 'Movies|Holiday', + 4421 => 'Movies|Made for TV', + 4422 => 'Movies|Concert Films', + 4423 => 'Movies|Music Documentaries', + 4424 => 'Movies|Music Feature Films', + 4425 => 'Movies|Japanese Cinema', + 4426 => 'Movies|Jidaigeki', + 4427 => 'Movies|Tokusatsu', + 4428 => 'Movies|Korean Cinema', + 4429 => 'Movies|Russian', + 4430 => 'Movies|Turkish', + 4431 => 'Movies|Bollywood', + 4432 => 'Movies|Regional Indian', + 4433 => 'Movies|Middle Eastern', + 4434 => 'Movies|African', + 6000 => 'App Store|Business', + 6001 => 'App Store|Weather', + 6002 => 'App Store|Utilities', + 6003 => 'App Store|Travel', + 6004 => 'App Store|Sports', + 6005 => 'App Store|Social Networking', + 6006 => 'App Store|Reference', + 6007 => 'App Store|Productivity', + 6008 => 'App Store|Photo & Video', + 6009 => 'App Store|News', + 6010 => 'App Store|Navigation', + 6011 => 'App Store|Music', + 6012 => 'App Store|Lifestyle', + 6013 => 'App Store|Health & Fitness', + 6014 => 'App Store|Games', + 6015 => 'App Store|Finance', + 6016 => 'App Store|Entertainment', + 6017 => 'App Store|Education', + 6018 => 'App Store|Books', + 6020 => 'App Store|Medical', + 6021 => 'App Store|Magazines & Newspapers', + 6022 => 'App Store|Catalogs', + 6023 => 'App Store|Food & Drink', + 6024 => 'App Store|Shopping', + 6025 => 'App Store|Stickers', + 7001 => 'App Store|Games|Action', + 7002 => 'App Store|Games|Adventure', + 7003 => 'App Store|Games|Arcade', + 7004 => 'App Store|Games|Board', + 7005 => 'App Store|Games|Card', + 7006 => 'App Store|Games|Casino', + 7007 => 'App Store|Games|Dice', + 7008 => 'App Store|Games|Educational', + 7009 => 'App Store|Games|Family', + 7011 => 'App Store|Games|Music', + 7012 => 'App Store|Games|Puzzle', + 7013 => 'App Store|Games|Racing', + 7014 => 'App Store|Games|Role Playing', + 7015 => 'App Store|Games|Simulation', + 7016 => 'App Store|Games|Sports', + 7017 => 'App Store|Games|Strategy', + 7018 => 'App Store|Games|Trivia', + 7019 => 'App Store|Games|Word', + 8001 => 'Tones|Ringtones|Alternative', + 8002 => 'Tones|Ringtones|Blues', + 8003 => "Tones|Ringtones|Children's Music", + 8004 => 'Tones|Ringtones|Classical', + 8005 => 'Tones|Ringtones|Comedy', + 8006 => 'Tones|Ringtones|Country', + 8007 => 'Tones|Ringtones|Dance', + 8008 => 'Tones|Ringtones|Electronic', + 8009 => 'Tones|Ringtones|Enka', + 8010 => 'Tones|Ringtones|French Pop', + 8011 => 'Tones|Ringtones|German Folk', + 8012 => 'Tones|Ringtones|German Pop', + 8013 => 'Tones|Ringtones|Hip-Hop/Rap', + 8014 => 'Tones|Ringtones|Holiday', + 8015 => 'Tones|Ringtones|Inspirational', + 8016 => 'Tones|Ringtones|J-Pop', + 8017 => 'Tones|Ringtones|Jazz', + 8018 => 'Tones|Ringtones|Kayokyoku', + 8019 => 'Tones|Ringtones|Latin', + 8020 => 'Tones|Ringtones|New Age', + 8021 => 'Tones|Ringtones|Classical|Opera', + 8022 => 'Tones|Ringtones|Pop', + 8023 => 'Tones|Ringtones|R&B/Soul', + 8024 => 'Tones|Ringtones|Reggae', + 8025 => 'Tones|Ringtones|Rock', + 8026 => 'Tones|Ringtones|Singer/Songwriter', + 8027 => 'Tones|Ringtones|Soundtrack', + 8028 => 'Tones|Ringtones|Spoken Word', + 8029 => 'Tones|Ringtones|Vocal', + 8030 => 'Tones|Ringtones|World', + 8050 => 'Tones|Alert Tones|Sound Effects', + 8051 => 'Tones|Alert Tones|Dialogue', + 8052 => 'Tones|Alert Tones|Music', + 8053 => 'Tones|Ringtones', + 8054 => 'Tones|Alert Tones', + 8055 => 'Tones|Ringtones|Alternative|Chinese Alt', + 8056 => 'Tones|Ringtones|Alternative|College Rock', + 8057 => 'Tones|Ringtones|Alternative|Goth Rock', + 8058 => 'Tones|Ringtones|Alternative|Grunge', + 8059 => 'Tones|Ringtones|Alternative|Indie Rock', + 8060 => 'Tones|Ringtones|Alternative|Korean Indie', + 8061 => 'Tones|Ringtones|Alternative|New Wave', + 8062 => 'Tones|Ringtones|Alternative|Punk', + 8063 => 'Tones|Ringtones|Anime', + 8064 => 'Tones|Ringtones|Arabic', + 8065 => 'Tones|Ringtones|Arabic|Arabic Pop', + 8066 => 'Tones|Ringtones|Arabic|Islamic', + 8067 => 'Tones|Ringtones|Arabic|Khaleeji', + 8068 => 'Tones|Ringtones|Arabic|North African', + 8069 => 'Tones|Ringtones|Blues|Acoustic Blues', + 8070 => 'Tones|Ringtones|Blues|Chicago Blues', + 8071 => 'Tones|Ringtones|Blues|Classic Blues', + 8072 => 'Tones|Ringtones|Blues|Contemporary Blues', + 8073 => 'Tones|Ringtones|Blues|Country Blues', + 8074 => 'Tones|Ringtones|Blues|Delta Blues', + 8075 => 'Tones|Ringtones|Blues|Electric Blues', + 8076 => 'Tones|Ringtones|Brazilian', + 8077 => 'Tones|Ringtones|Brazilian|Axe', # (Ax&eacute;) + 8078 => 'Tones|Ringtones|Brazilian|Baile Funk', + 8079 => 'Tones|Ringtones|Brazilian|Bossa Nova', + 8080 => 'Tones|Ringtones|Brazilian|Choro', + 8081 => 'Tones|Ringtones|Brazilian|Forro', # (Forr&oacute;) + 8082 => 'Tones|Ringtones|Brazilian|Frevo', + 8083 => 'Tones|Ringtones|Brazilian|MPB', + 8084 => 'Tones|Ringtones|Brazilian|Pagode', + 8085 => 'Tones|Ringtones|Brazilian|Samba', + 8086 => 'Tones|Ringtones|Brazilian|Sertanejo', + 8087 => "Tones|Ringtones|Children's Music|Lullabies", + 8088 => "Tones|Ringtones|Children's Music|Sing-Along", + 8089 => "Tones|Ringtones|Children's Music|Stories", + 8090 => 'Tones|Ringtones|Chinese', + 8091 => 'Tones|Ringtones|Chinese|Chinese Classical', + 8092 => 'Tones|Ringtones|Chinese|Chinese Flute', + 8093 => 'Tones|Ringtones|Chinese|Chinese Opera', + 8094 => 'Tones|Ringtones|Chinese|Chinese Orchestral', + 8095 => 'Tones|Ringtones|Chinese|Chinese Regional Folk', + 8096 => 'Tones|Ringtones|Chinese|Chinese Strings', + 8097 => 'Tones|Ringtones|Chinese|Taiwanese Folk', + 8098 => 'Tones|Ringtones|Chinese|Tibetan Native Music', + 8099 => 'Tones|Ringtones|Christian & Gospel', + 8100 => 'Tones|Ringtones|Christian & Gospel|CCM', + 8101 => 'Tones|Ringtones|Christian & Gospel|Christian Metal', + 8102 => 'Tones|Ringtones|Christian & Gospel|Christian Pop', + 8103 => 'Tones|Ringtones|Christian & Gospel|Christian Rap', + 8104 => 'Tones|Ringtones|Christian & Gospel|Christian Rock', + 8105 => 'Tones|Ringtones|Christian & Gospel|Classic Christian', + 8106 => 'Tones|Ringtones|Christian & Gospel|Contemporary Gospel', + 8107 => 'Tones|Ringtones|Christian & Gospel|Gospel', + 8108 => 'Tones|Ringtones|Christian & Gospel|Praise & Worship', + 8109 => 'Tones|Ringtones|Christian & Gospel|Southern Gospel', + 8110 => 'Tones|Ringtones|Christian & Gospel|Traditional Gospel', + 8111 => 'Tones|Ringtones|Classical|Avant-Garde', + 8112 => 'Tones|Ringtones|Classical|Baroque Era', + 8113 => 'Tones|Ringtones|Classical|Chamber Music', + 8114 => 'Tones|Ringtones|Classical|Chant', + 8115 => 'Tones|Ringtones|Classical|Choral', + 8116 => 'Tones|Ringtones|Classical|Classical Crossover', + 8117 => 'Tones|Ringtones|Classical|Early Music', + 8118 => 'Tones|Ringtones|Classical|High Classical', + 8119 => 'Tones|Ringtones|Classical|Impressionist', + 8120 => 'Tones|Ringtones|Classical|Medieval Era', + 8121 => 'Tones|Ringtones|Classical|Minimalism', + 8122 => 'Tones|Ringtones|Classical|Modern Era', + 8123 => 'Tones|Ringtones|Classical|Orchestral', + 8124 => 'Tones|Ringtones|Classical|Renaissance', + 8125 => 'Tones|Ringtones|Classical|Romantic Era', + 8126 => 'Tones|Ringtones|Classical|Wedding Music', + 8127 => 'Tones|Ringtones|Comedy|Novelty', + 8128 => 'Tones|Ringtones|Comedy|Standup Comedy', + 8129 => 'Tones|Ringtones|Country|Alternative Country', + 8130 => 'Tones|Ringtones|Country|Americana', + 8131 => 'Tones|Ringtones|Country|Bluegrass', + 8132 => 'Tones|Ringtones|Country|Contemporary Bluegrass', + 8133 => 'Tones|Ringtones|Country|Contemporary Country', + 8134 => 'Tones|Ringtones|Country|Country Gospel', + 8135 => 'Tones|Ringtones|Country|Honky Tonk', + 8136 => 'Tones|Ringtones|Country|Outlaw Country', + 8137 => 'Tones|Ringtones|Country|Thai Country', + 8138 => 'Tones|Ringtones|Country|Traditional Bluegrass', + 8139 => 'Tones|Ringtones|Country|Traditional Country', + 8140 => 'Tones|Ringtones|Country|Urban Cowboy', + 8141 => 'Tones|Ringtones|Dance|Breakbeat', + 8142 => 'Tones|Ringtones|Dance|Exercise', + 8143 => 'Tones|Ringtones|Dance|Garage', + 8144 => 'Tones|Ringtones|Dance|Hardcore', + 8145 => 'Tones|Ringtones|Dance|House', + 8146 => "Tones|Ringtones|Dance|Jungle/Drum'n'bass", + 8147 => 'Tones|Ringtones|Dance|Techno', + 8148 => 'Tones|Ringtones|Dance|Trance', + 8149 => 'Tones|Ringtones|Disney', + 8150 => 'Tones|Ringtones|Easy Listening', + 8151 => 'Tones|Ringtones|Easy Listening|Lounge', + 8152 => 'Tones|Ringtones|Easy Listening|Swing', + 8153 => 'Tones|Ringtones|Electronic|Ambient', + 8154 => 'Tones|Ringtones|Electronic|Downtempo', + 8155 => 'Tones|Ringtones|Electronic|Electronica', + 8156 => 'Tones|Ringtones|Electronic|IDM/Experimental', + 8157 => 'Tones|Ringtones|Electronic|Industrial', + 8158 => 'Tones|Ringtones|Fitness & Workout', + 8159 => 'Tones|Ringtones|Folk', + 8160 => 'Tones|Ringtones|Hip-Hop/Rap|Alternative Rap', + 8161 => 'Tones|Ringtones|Hip-Hop/Rap|Chinese Hip-Hop', + 8162 => 'Tones|Ringtones|Hip-Hop/Rap|Dirty South', + 8163 => 'Tones|Ringtones|Hip-Hop/Rap|East Coast Rap', + 8164 => 'Tones|Ringtones|Hip-Hop/Rap|Gangsta Rap', + 8165 => 'Tones|Ringtones|Hip-Hop/Rap|Hardcore Rap', + 8166 => 'Tones|Ringtones|Hip-Hop/Rap|Hip-Hop', + 8167 => 'Tones|Ringtones|Hip-Hop/Rap|Korean Hip-Hop', + 8168 => 'Tones|Ringtones|Hip-Hop/Rap|Latin Rap', + 8169 => 'Tones|Ringtones|Hip-Hop/Rap|Old School Rap', + 8170 => 'Tones|Ringtones|Hip-Hop/Rap|Rap', + 8171 => 'Tones|Ringtones|Hip-Hop/Rap|Underground Rap', + 8172 => 'Tones|Ringtones|Hip-Hop/Rap|West Coast Rap', + 8173 => 'Tones|Ringtones|Holiday|Chanukah', + 8174 => 'Tones|Ringtones|Holiday|Christmas', + 8175 => "Tones|Ringtones|Holiday|Christmas: Children's", + 8176 => 'Tones|Ringtones|Holiday|Christmas: Classic', + 8177 => 'Tones|Ringtones|Holiday|Christmas: Classical', + 8178 => 'Tones|Ringtones|Holiday|Christmas: Jazz', + 8179 => 'Tones|Ringtones|Holiday|Christmas: Modern', + 8180 => 'Tones|Ringtones|Holiday|Christmas: Pop', + 8181 => 'Tones|Ringtones|Holiday|Christmas: R&B', + 8182 => 'Tones|Ringtones|Holiday|Christmas: Religious', + 8183 => 'Tones|Ringtones|Holiday|Christmas: Rock', + 8184 => 'Tones|Ringtones|Holiday|Easter', + 8185 => 'Tones|Ringtones|Holiday|Halloween', + 8186 => 'Tones|Ringtones|Holiday|Thanksgiving', + 8187 => 'Tones|Ringtones|Indian', + 8188 => 'Tones|Ringtones|Indian|Bollywood', + 8189 => 'Tones|Ringtones|Indian|Devotional & Spiritual', + 8190 => 'Tones|Ringtones|Indian|Ghazals', + 8191 => 'Tones|Ringtones|Indian|Indian Classical', + 8192 => 'Tones|Ringtones|Indian|Indian Folk', + 8193 => 'Tones|Ringtones|Indian|Indian Pop', + 8194 => 'Tones|Ringtones|Indian|Regional Indian', + 8195 => 'Tones|Ringtones|Indian|Sufi', + 8196 => 'Tones|Ringtones|Indian|Tamil', + 8197 => 'Tones|Ringtones|Indian|Telugu', + 8198 => 'Tones|Ringtones|Instrumental', + 8199 => 'Tones|Ringtones|Jazz|Avant-Garde Jazz', + 8201 => 'Tones|Ringtones|Jazz|Big Band', + 8202 => 'Tones|Ringtones|Jazz|Bop', + 8203 => 'Tones|Ringtones|Jazz|Contemporary Jazz', + 8204 => 'Tones|Ringtones|Jazz|Cool Jazz', + 8205 => 'Tones|Ringtones|Jazz|Crossover Jazz', + 8206 => 'Tones|Ringtones|Jazz|Dixieland', + 8207 => 'Tones|Ringtones|Jazz|Fusion', + 8208 => 'Tones|Ringtones|Jazz|Hard Bop', + 8209 => 'Tones|Ringtones|Jazz|Latin Jazz', + 8210 => 'Tones|Ringtones|Jazz|Mainstream Jazz', + 8211 => 'Tones|Ringtones|Jazz|Ragtime', + 8212 => 'Tones|Ringtones|Jazz|Smooth Jazz', + 8213 => 'Tones|Ringtones|Jazz|Trad Jazz', + 8214 => 'Tones|Ringtones|Pop|K-Pop', + 8215 => 'Tones|Ringtones|Karaoke', + 8216 => 'Tones|Ringtones|Korean', + 8217 => 'Tones|Ringtones|Korean|Korean Classical', + 8218 => 'Tones|Ringtones|Korean|Korean Trad Instrumental', + 8219 => 'Tones|Ringtones|Korean|Korean Trad Song', + 8220 => 'Tones|Ringtones|Korean|Korean Trad Theater', + 8221 => 'Tones|Ringtones|Latin|Alternative & Rock in Spanish', + 8222 => 'Tones|Ringtones|Latin|Baladas y Boleros', + 8223 => 'Tones|Ringtones|Latin|Contemporary Latin', + 8224 => 'Tones|Ringtones|Latin|Latin Jazz', + 8225 => 'Tones|Ringtones|Latin|Latin Urban', + 8226 => 'Tones|Ringtones|Latin|Pop in Spanish', + 8227 => 'Tones|Ringtones|Latin|Raices', + 8228 => 'Tones|Ringtones|Latin|Musica Mexicana', # (M&uacute;sica Mexicana) + 8229 => 'Tones|Ringtones|Latin|Salsa y Tropical', + 8230 => 'Tones|Ringtones|Marching Bands', + 8231 => 'Tones|Ringtones|New Age|Healing', + 8232 => 'Tones|Ringtones|New Age|Meditation', + 8233 => 'Tones|Ringtones|New Age|Nature', + 8234 => 'Tones|Ringtones|New Age|Relaxation', + 8235 => 'Tones|Ringtones|New Age|Travel', + 8236 => 'Tones|Ringtones|Orchestral', + 8237 => 'Tones|Ringtones|Pop|Adult Contemporary', + 8238 => 'Tones|Ringtones|Pop|Britpop', + 8239 => 'Tones|Ringtones|Pop|C-Pop', + 8240 => 'Tones|Ringtones|Pop|Cantopop/HK-Pop', + 8241 => 'Tones|Ringtones|Pop|Indo Pop', + 8242 => 'Tones|Ringtones|Pop|Korean Folk-Pop', + 8243 => 'Tones|Ringtones|Pop|Malaysian Pop', + 8244 => 'Tones|Ringtones|Pop|Mandopop', + 8245 => 'Tones|Ringtones|Pop|Manilla Sound', + 8246 => 'Tones|Ringtones|Pop|Oldies', + 8247 => 'Tones|Ringtones|Pop|Original Pilipino Music', + 8248 => 'Tones|Ringtones|Pop|Pinoy Pop', + 8249 => 'Tones|Ringtones|Pop|Pop/Rock', + 8250 => 'Tones|Ringtones|Pop|Soft Rock', + 8251 => 'Tones|Ringtones|Pop|Tai-Pop', + 8252 => 'Tones|Ringtones|Pop|Teen Pop', + 8253 => 'Tones|Ringtones|Pop|Thai Pop', + 8254 => 'Tones|Ringtones|R&B/Soul|Contemporary R&B', + 8255 => 'Tones|Ringtones|R&B/Soul|Disco', + 8256 => 'Tones|Ringtones|R&B/Soul|Doo Wop', + 8257 => 'Tones|Ringtones|R&B/Soul|Funk', + 8258 => 'Tones|Ringtones|R&B/Soul|Motown', + 8259 => 'Tones|Ringtones|R&B/Soul|Neo-Soul', + 8260 => 'Tones|Ringtones|R&B/Soul|Soul', + 8261 => 'Tones|Ringtones|Reggae|Modern Dancehall', + 8262 => 'Tones|Ringtones|Reggae|Dub', + 8263 => 'Tones|Ringtones|Reggae|Roots Reggae', + 8264 => 'Tones|Ringtones|Reggae|Ska', + 8265 => 'Tones|Ringtones|Rock|Adult Alternative', + 8266 => 'Tones|Ringtones|Rock|American Trad Rock', + 8267 => 'Tones|Ringtones|Rock|Arena Rock', + 8268 => 'Tones|Ringtones|Rock|Blues-Rock', + 8269 => 'Tones|Ringtones|Rock|British Invasion', + 8270 => 'Tones|Ringtones|Rock|Chinese Rock', + 8271 => 'Tones|Ringtones|Rock|Death Metal/Black Metal', + 8272 => 'Tones|Ringtones|Rock|Glam Rock', + 8273 => 'Tones|Ringtones|Rock|Hair Metal', + 8274 => 'Tones|Ringtones|Rock|Hard Rock', + 8275 => 'Tones|Ringtones|Rock|Metal', + 8276 => 'Tones|Ringtones|Rock|Jam Bands', + 8277 => 'Tones|Ringtones|Rock|Korean Rock', + 8278 => 'Tones|Ringtones|Rock|Prog-Rock/Art Rock', + 8279 => 'Tones|Ringtones|Rock|Psychedelic', + 8280 => 'Tones|Ringtones|Rock|Rock & Roll', + 8281 => 'Tones|Ringtones|Rock|Rockabilly', + 8282 => 'Tones|Ringtones|Rock|Roots Rock', + 8283 => 'Tones|Ringtones|Rock|Singer/Songwriter', + 8284 => 'Tones|Ringtones|Rock|Southern Rock', + 8285 => 'Tones|Ringtones|Rock|Surf', + 8286 => 'Tones|Ringtones|Rock|Tex-Mex', + 8287 => 'Tones|Ringtones|Singer/Songwriter|Alternative Folk', + 8288 => 'Tones|Ringtones|Singer/Songwriter|Contemporary Folk', + 8289 => 'Tones|Ringtones|Singer/Songwriter|Contemporary Singer/Songwriter', + 8290 => 'Tones|Ringtones|Singer/Songwriter|Folk-Rock', + 8291 => 'Tones|Ringtones|Singer/Songwriter|New Acoustic', + 8292 => 'Tones|Ringtones|Singer/Songwriter|Traditional Folk', + 8293 => 'Tones|Ringtones|Soundtrack|Foreign Cinema', + 8294 => 'Tones|Ringtones|Soundtrack|Musicals', + 8295 => 'Tones|Ringtones|Soundtrack|Original Score', + 8296 => 'Tones|Ringtones|Soundtrack|Sound Effects', + 8297 => 'Tones|Ringtones|Soundtrack|Soundtrack', + 8298 => 'Tones|Ringtones|Soundtrack|TV Soundtrack', + 8299 => 'Tones|Ringtones|Vocal|Standards', + 8300 => 'Tones|Ringtones|Vocal|Traditional Pop', + 8301 => 'Tones|Ringtones|Vocal|Trot', + 8302 => 'Tones|Ringtones|Jazz|Vocal Jazz', + 8303 => 'Tones|Ringtones|Vocal|Vocal Pop', + 8304 => 'Tones|Ringtones|World|Africa', + 8305 => 'Tones|Ringtones|World|Afrikaans', + 8306 => 'Tones|Ringtones|World|Afro-Beat', + 8307 => 'Tones|Ringtones|World|Afro-Pop', + 8308 => 'Tones|Ringtones|World|Arabesque', + 8309 => 'Tones|Ringtones|World|Asia', + 8310 => 'Tones|Ringtones|World|Australia', + 8311 => 'Tones|Ringtones|World|Cajun', + 8312 => 'Tones|Ringtones|World|Calypso', + 8313 => 'Tones|Ringtones|World|Caribbean', + 8314 => 'Tones|Ringtones|World|Celtic', + 8315 => 'Tones|Ringtones|World|Celtic Folk', + 8316 => 'Tones|Ringtones|World|Contemporary Celtic', + 8317 => 'Tones|Ringtones|World|Dangdut', + 8318 => 'Tones|Ringtones|World|Dini', + 8319 => 'Tones|Ringtones|World|Europe', + 8320 => 'Tones|Ringtones|World|Fado', + 8321 => 'Tones|Ringtones|World|Farsi', + 8322 => 'Tones|Ringtones|World|Flamenco', + 8323 => 'Tones|Ringtones|World|France', + 8324 => 'Tones|Ringtones|World|Halk', + 8325 => 'Tones|Ringtones|World|Hawaii', + 8326 => 'Tones|Ringtones|World|Iberia', + 8327 => 'Tones|Ringtones|World|Indonesian Religious', + 8328 => 'Tones|Ringtones|World|Israeli', + 8329 => 'Tones|Ringtones|World|Japan', + 8330 => 'Tones|Ringtones|World|Klezmer', + 8331 => 'Tones|Ringtones|World|North America', + 8332 => 'Tones|Ringtones|World|Polka', + 8333 => 'Tones|Ringtones|World|Russian', + 8334 => 'Tones|Ringtones|World|Russian Chanson', + 8335 => 'Tones|Ringtones|World|Sanat', + 8336 => 'Tones|Ringtones|World|Soca', + 8337 => 'Tones|Ringtones|World|South Africa', + 8338 => 'Tones|Ringtones|World|South America', + 8339 => 'Tones|Ringtones|World|Tango', + 8340 => 'Tones|Ringtones|World|Traditional Celtic', + 8341 => 'Tones|Ringtones|World|Turkish', + 8342 => 'Tones|Ringtones|World|Worldbeat', + 8343 => 'Tones|Ringtones|World|Zydeco', + 8345 => 'Tones|Ringtones|Classical|Art Song', + 8346 => 'Tones|Ringtones|Classical|Brass & Woodwinds', + 8347 => 'Tones|Ringtones|Classical|Solo Instrumental', + 8348 => 'Tones|Ringtones|Classical|Contemporary Era', + 8349 => 'Tones|Ringtones|Classical|Oratorio', + 8350 => 'Tones|Ringtones|Classical|Cantata', + 8351 => 'Tones|Ringtones|Classical|Electronic', + 8352 => 'Tones|Ringtones|Classical|Sacred', + 8353 => 'Tones|Ringtones|Classical|Guitar', + 8354 => 'Tones|Ringtones|Classical|Piano', + 8355 => 'Tones|Ringtones|Classical|Violin', + 8356 => 'Tones|Ringtones|Classical|Cello', + 8357 => 'Tones|Ringtones|Classical|Percussion', + 8358 => 'Tones|Ringtones|Electronic|Dubstep', + 8359 => 'Tones|Ringtones|Electronic|Bass', + 8360 => 'Tones|Ringtones|Hip-Hop/Rap|UK Hip Hop', + 8361 => 'Tones|Ringtones|Reggae|Lovers Rock', + 8362 => 'Tones|Ringtones|Alternative|EMO', + 8363 => 'Tones|Ringtones|Alternative|Pop Punk', + 8364 => 'Tones|Ringtones|Alternative|Indie Pop', + 8365 => 'Tones|Ringtones|New Age|Yoga', + 8366 => 'Tones|Ringtones|Pop|Tribute', + 8367 => 'Tones|Ringtones|Pop|Shows', + 9002 => 'Books|Nonfiction', + 9003 => 'Books|Romance', + 9004 => 'Books|Travel & Adventure', + 9007 => 'Books|Arts & Entertainment', + 9008 => 'Books|Biographies & Memoirs', + 9009 => 'Books|Business & Personal Finance', + 9010 => 'Books|Children & Teens', + 9012 => 'Books|Humor', + 9015 => 'Books|History', + 9018 => 'Books|Religion & Spirituality', + 9019 => 'Books|Science & Nature', + 9020 => 'Books|Sci-Fi & Fantasy', + 9024 => 'Books|Lifestyle & Home', + 9025 => 'Books|Health, Mind & Body', + 9026 => 'Books|Comics & Graphic Novels', + 9027 => 'Books|Computers & Internet', + 9028 => 'Books|Cookbooks, Food & Wine', + 9029 => 'Books|Professional & Technical', + 9030 => 'Books|Parenting', + 9031 => 'Books|Fiction & Literature', + 9032 => 'Books|Mysteries & Thrillers', + 9033 => 'Books|Reference', + 9034 => 'Books|Politics & Current Events', + 9035 => 'Books|Sports & Outdoors', + 10001 => 'Books|Lifestyle & Home|Antiques & Collectibles', + 10002 => 'Books|Arts & Entertainment|Art & Architecture', + 10003 => 'Books|Religion & Spirituality|Bibles', + 10004 => 'Books|Health, Mind & Body|Spirituality', + 10005 => 'Books|Business & Personal Finance|Industries & Professions', + 10006 => 'Books|Business & Personal Finance|Marketing & Sales', + 10007 => 'Books|Business & Personal Finance|Small Business & Entrepreneurship', + 10008 => 'Books|Business & Personal Finance|Personal Finance', + 10009 => 'Books|Business & Personal Finance|Reference', + 10010 => 'Books|Business & Personal Finance|Careers', + 10011 => 'Books|Business & Personal Finance|Economics', + 10012 => 'Books|Business & Personal Finance|Investing', + 10013 => 'Books|Business & Personal Finance|Finance', + 10014 => 'Books|Business & Personal Finance|Management & Leadership', + 10015 => 'Books|Comics & Graphic Novels|Graphic Novels', + 10016 => 'Books|Comics & Graphic Novels|Manga', + 10017 => 'Books|Computers & Internet|Computers', + 10018 => 'Books|Computers & Internet|Databases', + 10019 => 'Books|Computers & Internet|Digital Media', + 10020 => 'Books|Computers & Internet|Internet', + 10021 => 'Books|Computers & Internet|Network', + 10022 => 'Books|Computers & Internet|Operating Systems', + 10023 => 'Books|Computers & Internet|Programming', + 10024 => 'Books|Computers & Internet|Software', + 10025 => 'Books|Computers & Internet|System Administration', + 10026 => 'Books|Cookbooks, Food & Wine|Beverages', + 10027 => 'Books|Cookbooks, Food & Wine|Courses & Dishes', + 10028 => 'Books|Cookbooks, Food & Wine|Special Diet', + 10029 => 'Books|Cookbooks, Food & Wine|Special Occasions', + 10030 => 'Books|Cookbooks, Food & Wine|Methods', + 10031 => 'Books|Cookbooks, Food & Wine|Reference', + 10032 => 'Books|Cookbooks, Food & Wine|Regional & Ethnic', + 10033 => 'Books|Cookbooks, Food & Wine|Specific Ingredients', + 10034 => 'Books|Lifestyle & Home|Crafts & Hobbies', + 10035 => 'Books|Professional & Technical|Design', + 10036 => 'Books|Arts & Entertainment|Theater', + 10037 => 'Books|Professional & Technical|Education', + 10038 => 'Books|Nonfiction|Family & Relationships', + 10039 => 'Books|Fiction & Literature|Action & Adventure', + 10040 => 'Books|Fiction & Literature|African American', + 10041 => 'Books|Fiction & Literature|Religious', + 10042 => 'Books|Fiction & Literature|Classics', + 10043 => 'Books|Fiction & Literature|Erotica', + 10044 => 'Books|Sci-Fi & Fantasy|Fantasy', + 10045 => 'Books|Fiction & Literature|Gay', + 10046 => 'Books|Fiction & Literature|Ghost', + 10047 => 'Books|Fiction & Literature|Historical', + 10048 => 'Books|Fiction & Literature|Horror', + 10049 => 'Books|Fiction & Literature|Literary', + 10050 => 'Books|Mysteries & Thrillers|Hard-Boiled', + 10051 => 'Books|Mysteries & Thrillers|Historical', + 10052 => 'Books|Mysteries & Thrillers|Police Procedural', + 10053 => 'Books|Mysteries & Thrillers|Short Stories', + 10054 => 'Books|Mysteries & Thrillers|British Detectives', + 10055 => 'Books|Mysteries & Thrillers|Women Sleuths', + 10056 => 'Books|Romance|Erotic Romance', + 10057 => 'Books|Romance|Contemporary', + 10058 => 'Books|Romance|Paranormal', + 10059 => 'Books|Romance|Historical', + 10060 => 'Books|Romance|Short Stories', + 10061 => 'Books|Romance|Suspense', + 10062 => 'Books|Romance|Western', + 10063 => 'Books|Sci-Fi & Fantasy|Science Fiction', + 10064 => 'Books|Sci-Fi & Fantasy|Science Fiction & Literature', + 10065 => 'Books|Fiction & Literature|Short Stories', + 10066 => 'Books|Reference|Foreign Languages', + 10067 => 'Books|Arts & Entertainment|Games', + 10068 => 'Books|Lifestyle & Home|Gardening', + 10069 => 'Books|Health, Mind & Body|Health & Fitness', + 10070 => 'Books|History|Africa', + 10071 => 'Books|History|Americas', + 10072 => 'Books|History|Ancient', + 10073 => 'Books|History|Asia', + 10074 => 'Books|History|Australia & Oceania', + 10075 => 'Books|History|Europe', + 10076 => 'Books|History|Latin America', + 10077 => 'Books|History|Middle East', + 10078 => 'Books|History|Military', + 10079 => 'Books|History|United States', + 10080 => 'Books|History|World', + 10081 => "Books|Children & Teens|Children's Fiction", + 10082 => "Books|Children & Teens|Children's Nonfiction", + 10083 => 'Books|Professional & Technical|Law', + 10084 => 'Books|Fiction & Literature|Literary Criticism', + 10085 => 'Books|Science & Nature|Mathematics', + 10086 => 'Books|Professional & Technical|Medical', + 10087 => 'Books|Arts & Entertainment|Music', + 10088 => 'Books|Science & Nature|Nature', + 10089 => 'Books|Arts & Entertainment|Performing Arts', + 10090 => 'Books|Lifestyle & Home|Pets', + 10091 => 'Books|Nonfiction|Philosophy', + 10092 => 'Books|Arts & Entertainment|Photography', + 10093 => 'Books|Fiction & Literature|Poetry', + 10094 => 'Books|Health, Mind & Body|Psychology', + 10095 => 'Books|Reference|Almanacs & Yearbooks', + 10096 => 'Books|Reference|Atlases & Maps', + 10097 => 'Books|Reference|Catalogs & Directories', + 10098 => 'Books|Reference|Consumer Guides', + 10099 => 'Books|Reference|Dictionaries & Thesauruses', + 10100 => 'Books|Reference|Encyclopedias', + 10101 => 'Books|Reference|Etiquette', + 10102 => 'Books|Reference|Quotations', + 10103 => 'Books|Reference|Words & Language', + 10104 => 'Books|Reference|Writing', + 10105 => 'Books|Religion & Spirituality|Bible Studies', + 10106 => 'Books|Religion & Spirituality|Buddhism', + 10107 => 'Books|Religion & Spirituality|Christianity', + 10108 => 'Books|Religion & Spirituality|Hinduism', + 10109 => 'Books|Religion & Spirituality|Islam', + 10110 => 'Books|Religion & Spirituality|Judaism', + 10111 => 'Books|Science & Nature|Astronomy', + 10112 => 'Books|Science & Nature|Chemistry', + 10113 => 'Books|Science & Nature|Earth Sciences', + 10114 => 'Books|Science & Nature|Essays', + 10115 => 'Books|Science & Nature|History', + 10116 => 'Books|Science & Nature|Life Sciences', + 10117 => 'Books|Science & Nature|Physics', + 10118 => 'Books|Science & Nature|Reference', + 10119 => 'Books|Health, Mind & Body|Self-Improvement', + 10120 => 'Books|Nonfiction|Social Science', + 10121 => 'Books|Sports & Outdoors|Baseball', + 10122 => 'Books|Sports & Outdoors|Basketball', + 10123 => 'Books|Sports & Outdoors|Coaching', + 10124 => 'Books|Sports & Outdoors|Extreme Sports', + 10125 => 'Books|Sports & Outdoors|Football', + 10126 => 'Books|Sports & Outdoors|Golf', + 10127 => 'Books|Sports & Outdoors|Hockey', + 10128 => 'Books|Sports & Outdoors|Mountaineering', + 10129 => 'Books|Sports & Outdoors|Outdoors', + 10130 => 'Books|Sports & Outdoors|Racket Sports', + 10131 => 'Books|Sports & Outdoors|Reference', + 10132 => 'Books|Sports & Outdoors|Soccer', + 10133 => 'Books|Sports & Outdoors|Training', + 10134 => 'Books|Sports & Outdoors|Water Sports', + 10135 => 'Books|Sports & Outdoors|Winter Sports', + 10136 => 'Books|Reference|Study Aids', + 10137 => 'Books|Professional & Technical|Engineering', + 10138 => 'Books|Nonfiction|Transportation', + 10139 => 'Books|Travel & Adventure|Africa', + 10140 => 'Books|Travel & Adventure|Asia', + 10141 => 'Books|Travel & Adventure|Specialty Travel', + 10142 => 'Books|Travel & Adventure|Canada', + 10143 => 'Books|Travel & Adventure|Caribbean', + 10144 => 'Books|Travel & Adventure|Latin America', + 10145 => 'Books|Travel & Adventure|Essays & Memoirs', + 10146 => 'Books|Travel & Adventure|Europe', + 10147 => 'Books|Travel & Adventure|Middle East', + 10148 => 'Books|Travel & Adventure|United States', + 10149 => 'Books|Nonfiction|True Crime', + 11001 => 'Books|Sci-Fi & Fantasy|Fantasy|Contemporary', + 11002 => 'Books|Sci-Fi & Fantasy|Fantasy|Epic', + 11003 => 'Books|Sci-Fi & Fantasy|Fantasy|Historical', + 11004 => 'Books|Sci-Fi & Fantasy|Fantasy|Paranormal', + 11005 => 'Books|Sci-Fi & Fantasy|Fantasy|Short Stories', + 11006 => 'Books|Sci-Fi & Fantasy|Science Fiction & Literature|Adventure', + 11007 => 'Books|Sci-Fi & Fantasy|Science Fiction & Literature|High Tech', + 11008 => 'Books|Sci-Fi & Fantasy|Science Fiction & Literature|Short Stories', + 11009 => 'Books|Professional & Technical|Education|Language Arts & Disciplines', + 11010 => 'Books|Communications & Media', + 11011 => 'Books|Communications & Media|Broadcasting', + 11012 => 'Books|Communications & Media|Digital Media', + 11013 => 'Books|Communications & Media|Journalism', + 11014 => 'Books|Communications & Media|Photojournalism', + 11015 => 'Books|Communications & Media|Print', + 11016 => 'Books|Communications & Media|Speech', + 11017 => 'Books|Communications & Media|Writing', + 11018 => 'Books|Arts & Entertainment|Art & Architecture|Urban Planning', + 11019 => 'Books|Arts & Entertainment|Dance', + 11020 => 'Books|Arts & Entertainment|Fashion', + 11021 => 'Books|Arts & Entertainment|Film', + 11022 => 'Books|Arts & Entertainment|Interior Design', + 11023 => 'Books|Arts & Entertainment|Media Arts', + 11024 => 'Books|Arts & Entertainment|Radio', + 11025 => 'Books|Arts & Entertainment|TV', + 11026 => 'Books|Arts & Entertainment|Visual Arts', + 11027 => 'Books|Biographies & Memoirs|Arts & Entertainment', + 11028 => 'Books|Biographies & Memoirs|Business', + 11029 => 'Books|Biographies & Memoirs|Culinary', + 11030 => 'Books|Biographies & Memoirs|Gay & Lesbian', + 11031 => 'Books|Biographies & Memoirs|Historical', + 11032 => 'Books|Biographies & Memoirs|Literary', + 11033 => 'Books|Biographies & Memoirs|Media & Journalism', + 11034 => 'Books|Biographies & Memoirs|Military', + 11035 => 'Books|Biographies & Memoirs|Politics', + 11036 => 'Books|Biographies & Memoirs|Religious', + 11037 => 'Books|Biographies & Memoirs|Science & Technology', + 11038 => 'Books|Biographies & Memoirs|Sports', + 11039 => 'Books|Biographies & Memoirs|Women', + 11040 => 'Books|Romance|New Adult', + 11042 => 'Books|Romance|Romantic Comedy', + 11043 => 'Books|Romance|Gay & Lesbian', + 11044 => 'Books|Fiction & Literature|Essays', + 11045 => 'Books|Fiction & Literature|Anthologies', + 11046 => 'Books|Fiction & Literature|Comparative Literature', + 11047 => 'Books|Fiction & Literature|Drama', + 11049 => 'Books|Fiction & Literature|Fairy Tales, Myths & Fables', + 11050 => 'Books|Fiction & Literature|Family', + 11051 => 'Books|Comics & Graphic Novels|Manga|School Drama', + 11052 => 'Books|Comics & Graphic Novels|Manga|Human Drama', + 11053 => 'Books|Comics & Graphic Novels|Manga|Family Drama', + 11054 => 'Books|Sports & Outdoors|Boxing', + 11055 => 'Books|Sports & Outdoors|Cricket', + 11056 => 'Books|Sports & Outdoors|Cycling', + 11057 => 'Books|Sports & Outdoors|Equestrian', + 11058 => 'Books|Sports & Outdoors|Martial Arts & Self Defense', + 11059 => 'Books|Sports & Outdoors|Motor Sports', + 11060 => 'Books|Sports & Outdoors|Rugby', + 11061 => 'Books|Sports & Outdoors|Running', + 11062 => 'Books|Health, Mind & Body|Diet & Nutrition', + 11063 => 'Books|Science & Nature|Agriculture', + 11064 => 'Books|Science & Nature|Atmosphere', + 11065 => 'Books|Science & Nature|Biology', + 11066 => 'Books|Science & Nature|Ecology', + 11067 => 'Books|Science & Nature|Environment', + 11068 => 'Books|Science & Nature|Geography', + 11069 => 'Books|Science & Nature|Geology', + 11070 => 'Books|Nonfiction|Social Science|Anthropology', + 11071 => 'Books|Nonfiction|Social Science|Archaeology', + 11072 => 'Books|Nonfiction|Social Science|Civics', + 11073 => 'Books|Nonfiction|Social Science|Government', + 11074 => 'Books|Nonfiction|Social Science|Social Studies', + 11075 => 'Books|Nonfiction|Social Science|Social Welfare', + 11076 => 'Books|Nonfiction|Social Science|Society', + 11077 => 'Books|Nonfiction|Philosophy|Aesthetics', + 11078 => 'Books|Nonfiction|Philosophy|Epistemology', + 11079 => 'Books|Nonfiction|Philosophy|Ethics', + 11080 => 'Books|Nonfiction|Philosophy|Language', + 11081 => 'Books|Nonfiction|Philosophy|Logic', + 11082 => 'Books|Nonfiction|Philosophy|Metaphysics', + 11083 => 'Books|Nonfiction|Philosophy|Political', + 11084 => 'Books|Nonfiction|Philosophy|Religion', + 11085 => 'Books|Reference|Manuals', + 11086 => 'Books|Kids', + 11087 => 'Books|Kids|Animals', + 11088 => 'Books|Kids|Basic Concepts', + 11089 => 'Books|Kids|Basic Concepts|Alphabet', + 11090 => 'Books|Kids|Basic Concepts|Body', + 11091 => 'Books|Kids|Basic Concepts|Colors', + 11092 => 'Books|Kids|Basic Concepts|Counting & Numbers', + 11093 => 'Books|Kids|Basic Concepts|Date & Time', + 11094 => 'Books|Kids|Basic Concepts|General', + 11095 => 'Books|Kids|Basic Concepts|Money', + 11096 => 'Books|Kids|Basic Concepts|Opposites', + 11097 => 'Books|Kids|Basic Concepts|Seasons', + 11098 => 'Books|Kids|Basic Concepts|Senses & Sensation', + 11099 => 'Books|Kids|Basic Concepts|Size & Shape', + 11100 => 'Books|Kids|Basic Concepts|Sounds', + 11101 => 'Books|Kids|Basic Concepts|Words', + 11102 => 'Books|Kids|Biography', + 11103 => 'Books|Kids|Careers & Occupations', + 11104 => 'Books|Kids|Computers & Technology', + 11105 => 'Books|Kids|Cooking & Food', + 11106 => 'Books|Kids|Arts & Entertainment', + 11107 => 'Books|Kids|Arts & Entertainment|Art', + 11108 => 'Books|Kids|Arts & Entertainment|Crafts', + 11109 => 'Books|Kids|Arts & Entertainment|Music', + 11110 => 'Books|Kids|Arts & Entertainment|Performing Arts', + 11111 => 'Books|Kids|Family', + 11112 => 'Books|Kids|Fiction', + 11113 => 'Books|Kids|Fiction|Action & Adventure', + 11114 => 'Books|Kids|Fiction|Animals', + 11115 => 'Books|Kids|Fiction|Classics', + 11116 => 'Books|Kids|Fiction|Comics & Graphic Novels', + 11117 => 'Books|Kids|Fiction|Culture, Places & People', + 11118 => 'Books|Kids|Fiction|Family & Relationships', + 11119 => 'Books|Kids|Fiction|Fantasy', + 11120 => 'Books|Kids|Fiction|Fairy Tales, Myths & Fables', + 11121 => 'Books|Kids|Fiction|Favorite Characters', + 11122 => 'Books|Kids|Fiction|Historical', + 11123 => 'Books|Kids|Fiction|Holidays & Celebrations', + 11124 => 'Books|Kids|Fiction|Monsters & Ghosts', + 11125 => 'Books|Kids|Fiction|Mysteries', + 11126 => 'Books|Kids|Fiction|Nature', + 11127 => 'Books|Kids|Fiction|Religion', + 11128 => 'Books|Kids|Fiction|Sci-Fi', + 11129 => 'Books|Kids|Fiction|Social Issues', + 11130 => 'Books|Kids|Fiction|Sports & Recreation', + 11131 => 'Books|Kids|Fiction|Transportation', + 11132 => 'Books|Kids|Games & Activities', + 11133 => 'Books|Kids|General Nonfiction', + 11134 => 'Books|Kids|Health', + 11135 => 'Books|Kids|History', + 11136 => 'Books|Kids|Holidays & Celebrations', + 11137 => 'Books|Kids|Holidays & Celebrations|Birthdays', + 11138 => 'Books|Kids|Holidays & Celebrations|Christmas & Advent', + 11139 => 'Books|Kids|Holidays & Celebrations|Easter & Lent', + 11140 => 'Books|Kids|Holidays & Celebrations|General', + 11141 => 'Books|Kids|Holidays & Celebrations|Halloween', + 11142 => 'Books|Kids|Holidays & Celebrations|Hanukkah', + 11143 => 'Books|Kids|Holidays & Celebrations|Other', + 11144 => 'Books|Kids|Holidays & Celebrations|Passover', + 11145 => 'Books|Kids|Holidays & Celebrations|Patriotic Holidays', + 11146 => 'Books|Kids|Holidays & Celebrations|Ramadan', + 11147 => 'Books|Kids|Holidays & Celebrations|Thanksgiving', + 11148 => "Books|Kids|Holidays & Celebrations|Valentine's Day", + 11149 => 'Books|Kids|Humor', + 11150 => 'Books|Kids|Humor|Jokes & Riddles', + 11151 => 'Books|Kids|Poetry', + 11152 => 'Books|Kids|Learning to Read', + 11153 => 'Books|Kids|Learning to Read|Chapter Books', + 11154 => 'Books|Kids|Learning to Read|Early Readers', + 11155 => 'Books|Kids|Learning to Read|Intermediate Readers', + 11156 => 'Books|Kids|Nursery Rhymes', + 11157 => 'Books|Kids|Government', + 11158 => 'Books|Kids|Reference', + 11159 => 'Books|Kids|Religion', + 11160 => 'Books|Kids|Science & Nature', + 11161 => 'Books|Kids|Social Issues', + 11162 => 'Books|Kids|Social Studies', + 11163 => 'Books|Kids|Sports & Recreation', + 11164 => 'Books|Kids|Transportation', + 11165 => 'Books|Young Adult', + 11166 => 'Books|Young Adult|Animals', + 11167 => 'Books|Young Adult|Biography', + 11168 => 'Books|Young Adult|Careers & Occupations', + 11169 => 'Books|Young Adult|Computers & Technology', + 11170 => 'Books|Young Adult|Cooking & Food', + 11171 => 'Books|Young Adult|Arts & Entertainment', + 11172 => 'Books|Young Adult|Arts & Entertainment|Art', + 11173 => 'Books|Young Adult|Arts & Entertainment|Crafts', + 11174 => 'Books|Young Adult|Arts & Entertainment|Music', + 11175 => 'Books|Young Adult|Arts & Entertainment|Performing Arts', + 11176 => 'Books|Young Adult|Family', + 11177 => 'Books|Young Adult|Fiction', + 11178 => 'Books|Young Adult|Fiction|Action & Adventure', + 11179 => 'Books|Young Adult|Fiction|Animals', + 11180 => 'Books|Young Adult|Fiction|Classics', + 11181 => 'Books|Young Adult|Fiction|Comics & Graphic Novels', + 11182 => 'Books|Young Adult|Fiction|Culture, Places & People', + 11183 => 'Books|Young Adult|Fiction|Dystopian', + 11184 => 'Books|Young Adult|Fiction|Family & Relationships', + 11185 => 'Books|Young Adult|Fiction|Fantasy', + 11186 => 'Books|Young Adult|Fiction|Fairy Tales, Myths & Fables', + 11187 => 'Books|Young Adult|Fiction|Favorite Characters', + 11188 => 'Books|Young Adult|Fiction|Historical', + 11189 => 'Books|Young Adult|Fiction|Holidays & Celebrations', + 11190 => 'Books|Young Adult|Fiction|Horror, Monsters & Ghosts', + 11191 => 'Books|Young Adult|Fiction|Crime & Mystery', + 11192 => 'Books|Young Adult|Fiction|Nature', + 11193 => 'Books|Young Adult|Fiction|Religion', + 11194 => 'Books|Young Adult|Fiction|Romance', + 11195 => 'Books|Young Adult|Fiction|Sci-Fi', + 11196 => 'Books|Young Adult|Fiction|Coming of Age', + 11197 => 'Books|Young Adult|Fiction|Sports & Recreation', + 11198 => 'Books|Young Adult|Fiction|Transportation', + 11199 => 'Books|Young Adult|Games & Activities', + 11200 => 'Books|Young Adult|General Nonfiction', + 11201 => 'Books|Young Adult|Health', + 11202 => 'Books|Young Adult|History', + 11203 => 'Books|Young Adult|Holidays & Celebrations', + 11204 => 'Books|Young Adult|Holidays & Celebrations|Birthdays', + 11205 => 'Books|Young Adult|Holidays & Celebrations|Christmas & Advent', + 11206 => 'Books|Young Adult|Holidays & Celebrations|Easter & Lent', + 11207 => 'Books|Young Adult|Holidays & Celebrations|General', + 11208 => 'Books|Young Adult|Holidays & Celebrations|Halloween', + 11209 => 'Books|Young Adult|Holidays & Celebrations|Hanukkah', + 11210 => 'Books|Young Adult|Holidays & Celebrations|Other', + 11211 => 'Books|Young Adult|Holidays & Celebrations|Passover', + 11212 => 'Books|Young Adult|Holidays & Celebrations|Patriotic Holidays', + 11213 => 'Books|Young Adult|Holidays & Celebrations|Ramadan', + 11214 => 'Books|Young Adult|Holidays & Celebrations|Thanksgiving', + 11215 => "Books|Young Adult|Holidays & Celebrations|Valentine's Day", + 11216 => 'Books|Young Adult|Humor', + 11217 => 'Books|Young Adult|Humor|Jokes & Riddles', + 11218 => 'Books|Young Adult|Poetry', + 11219 => 'Books|Young Adult|Politics & Government', + 11220 => 'Books|Young Adult|Reference', + 11221 => 'Books|Young Adult|Religion', + 11222 => 'Books|Young Adult|Science & Nature', + 11223 => 'Books|Young Adult|Coming of Age', + 11224 => 'Books|Young Adult|Social Studies', + 11225 => 'Books|Young Adult|Sports & Recreation', + 11226 => 'Books|Young Adult|Transportation', + 11227 => 'Books|Communications & Media', + 11228 => 'Books|Military & Warfare', + 11229 => 'Books|Romance|Inspirational', + 11231 => 'Books|Romance|Holiday', + 11232 => 'Books|Romance|Wholesome', + 11233 => 'Books|Romance|Military', + 11234 => 'Books|Arts & Entertainment|Art History', + 11236 => 'Books|Arts & Entertainment|Design', + 11243 => 'Books|Business & Personal Finance|Accounting', + 11244 => 'Books|Business & Personal Finance|Hospitality', + 11245 => 'Books|Business & Personal Finance|Real Estate', + 11246 => 'Books|Humor|Jokes & Riddles', + 11247 => 'Books|Religion & Spirituality|Comparative Religion', + 11255 => 'Books|Cookbooks, Food & Wine|Culinary Arts', + 11259 => 'Books|Mysteries & Thrillers|Cozy', + 11260 => 'Books|Politics & Current Events|Current Events', + 11261 => 'Books|Politics & Current Events|Foreign Policy & International Relations', + 11262 => 'Books|Politics & Current Events|Local Government', + 11263 => 'Books|Politics & Current Events|National Government', + 11264 => 'Books|Politics & Current Events|Political Science', + 11265 => 'Books|Politics & Current Events|Public Administration', + 11266 => 'Books|Politics & Current Events|World Affairs', + 11273 => 'Books|Nonfiction|Family & Relationships|Family & Childcare', + 11274 => 'Books|Nonfiction|Family & Relationships|Love & Romance', + 11275 => 'Books|Sci-Fi & Fantasy|Fantasy|Urban', + 11276 => 'Books|Reference|Foreign Languages|Arabic', + 11277 => 'Books|Reference|Foreign Languages|Bilingual Editions', + 11278 => 'Books|Reference|Foreign Languages|African Languages', + 11279 => 'Books|Reference|Foreign Languages|Ancient Languages', + 11280 => 'Books|Reference|Foreign Languages|Chinese', + 11281 => 'Books|Reference|Foreign Languages|English', + 11282 => 'Books|Reference|Foreign Languages|French', + 11283 => 'Books|Reference|Foreign Languages|German', + 11284 => 'Books|Reference|Foreign Languages|Hebrew', + 11285 => 'Books|Reference|Foreign Languages|Hindi', + 11286 => 'Books|Reference|Foreign Languages|Italian', + 11287 => 'Books|Reference|Foreign Languages|Japanese', + 11288 => 'Books|Reference|Foreign Languages|Korean', + 11289 => 'Books|Reference|Foreign Languages|Linguistics', + 11290 => 'Books|Reference|Foreign Languages|Other Languages', + 11291 => 'Books|Reference|Foreign Languages|Portuguese', + 11292 => 'Books|Reference|Foreign Languages|Russian', + 11293 => 'Books|Reference|Foreign Languages|Spanish', + 11294 => 'Books|Reference|Foreign Languages|Speech Pathology', + 11295 => 'Books|Science & Nature|Mathematics|Advanced Mathematics', + 11296 => 'Books|Science & Nature|Mathematics|Algebra', + 11297 => 'Books|Science & Nature|Mathematics|Arithmetic', + 11298 => 'Books|Science & Nature|Mathematics|Calculus', + 11299 => 'Books|Science & Nature|Mathematics|Geometry', + 11300 => 'Books|Science & Nature|Mathematics|Statistics', + 11301 => 'Books|Professional & Technical|Medical|Veterinary', + 11302 => 'Books|Professional & Technical|Medical|Neuroscience', + 11303 => 'Books|Professional & Technical|Medical|Immunology', + 11304 => 'Books|Professional & Technical|Medical|Nursing', + 11305 => 'Books|Professional & Technical|Medical|Pharmacology & Toxicology', + 11306 => 'Books|Professional & Technical|Medical|Anatomy & Physiology', + 11307 => 'Books|Professional & Technical|Medical|Dentistry', + 11308 => 'Books|Professional & Technical|Medical|Emergency Medicine', + 11309 => 'Books|Professional & Technical|Medical|Genetics', + 11310 => 'Books|Professional & Technical|Medical|Psychiatry', + 11311 => 'Books|Professional & Technical|Medical|Radiology', + 11312 => 'Books|Professional & Technical|Medical|Alternative Medicine', + 11317 => 'Books|Nonfiction|Philosophy|Political Philosophy', + 11319 => 'Books|Nonfiction|Philosophy|Philosophy of Language', + 11320 => 'Books|Nonfiction|Philosophy|Philosophy of Religion', + 11327 => 'Books|Nonfiction|Social Science|Sociology', + 11329 => 'Books|Professional & Technical|Engineering|Aeronautics', + 11330 => 'Books|Professional & Technical|Engineering|Chemical & Petroleum Engineering', + 11331 => 'Books|Professional & Technical|Engineering|Civil Engineering', + 11332 => 'Books|Professional & Technical|Engineering|Computer Science', + 11333 => 'Books|Professional & Technical|Engineering|Electrical Engineering', + 11334 => 'Books|Professional & Technical|Engineering|Environmental Engineering', + 11335 => 'Books|Professional & Technical|Engineering|Mechanical Engineering', + 11336 => 'Books|Professional & Technical|Engineering|Power Resources', + 11337 => 'Books|Comics & Graphic Novels|Manga|Boys', + 11338 => 'Books|Comics & Graphic Novels|Manga|Men', + 11339 => 'Books|Comics & Graphic Novels|Manga|Girls', + 11340 => 'Books|Comics & Graphic Novels|Manga|Women', + 11341 => 'Books|Comics & Graphic Novels|Manga|Other', + 12001 => 'Mac App Store|Business', + 12002 => 'Mac App Store|Developer Tools', + 12003 => 'Mac App Store|Education', + 12004 => 'Mac App Store|Entertainment', + 12005 => 'Mac App Store|Finance', + 12006 => 'Mac App Store|Games', + 12007 => 'Mac App Store|Health & Fitness', + 12008 => 'Mac App Store|Lifestyle', + 12010 => 'Mac App Store|Medical', + 12011 => 'Mac App Store|Music', + 12012 => 'Mac App Store|News', + 12013 => 'Mac App Store|Photography', + 12014 => 'Mac App Store|Productivity', + 12015 => 'Mac App Store|Reference', + 12016 => 'Mac App Store|Social Networking', + 12017 => 'Mac App Store|Sports', + 12018 => 'Mac App Store|Travel', + 12019 => 'Mac App Store|Utilities', + 12020 => 'Mac App Store|Video', + 12021 => 'Mac App Store|Weather', + 12022 => 'Mac App Store|Graphics & Design', + 12201 => 'Mac App Store|Games|Action', + 12202 => 'Mac App Store|Games|Adventure', + 12203 => 'Mac App Store|Games|Arcade', + 12204 => 'Mac App Store|Games|Board', + 12205 => 'Mac App Store|Games|Card', + 12206 => 'Mac App Store|Games|Casino', + 12207 => 'Mac App Store|Games|Dice', + 12208 => 'Mac App Store|Games|Educational', + 12209 => 'Mac App Store|Games|Family', + 12210 => 'Mac App Store|Games|Kids', + 12211 => 'Mac App Store|Games|Music', + 12212 => 'Mac App Store|Games|Puzzle', + 12213 => 'Mac App Store|Games|Racing', + 12214 => 'Mac App Store|Games|Role Playing', + 12215 => 'Mac App Store|Games|Simulation', + 12216 => 'Mac App Store|Games|Sports', + 12217 => 'Mac App Store|Games|Strategy', + 12218 => 'Mac App Store|Games|Trivia', + 12219 => 'Mac App Store|Games|Word', + 13001 => 'App Store|Magazines & Newspapers|News & Politics', + 13002 => 'App Store|Magazines & Newspapers|Fashion & Style', + 13003 => 'App Store|Magazines & Newspapers|Home & Garden', + 13004 => 'App Store|Magazines & Newspapers|Outdoors & Nature', + 13005 => 'App Store|Magazines & Newspapers|Sports & Leisure', + 13006 => 'App Store|Magazines & Newspapers|Automotive', + 13007 => 'App Store|Magazines & Newspapers|Arts & Photography', + 13008 => 'App Store|Magazines & Newspapers|Brides & Weddings', + 13009 => 'App Store|Magazines & Newspapers|Business & Investing', + 13010 => "App Store|Magazines & Newspapers|Children's Magazines", + 13011 => 'App Store|Magazines & Newspapers|Computers & Internet', + 13012 => 'App Store|Magazines & Newspapers|Cooking, Food & Drink', + 13013 => 'App Store|Magazines & Newspapers|Crafts & Hobbies', + 13014 => 'App Store|Magazines & Newspapers|Electronics & Audio', + 13015 => 'App Store|Magazines & Newspapers|Entertainment', + 13017 => 'App Store|Magazines & Newspapers|Health, Mind & Body', + 13018 => 'App Store|Magazines & Newspapers|History', + 13019 => 'App Store|Magazines & Newspapers|Literary Magazines & Journals', + 13020 => "App Store|Magazines & Newspapers|Men's Interest", + 13021 => 'App Store|Magazines & Newspapers|Movies & Music', + 13023 => 'App Store|Magazines & Newspapers|Parenting & Family', + 13024 => 'App Store|Magazines & Newspapers|Pets', + 13025 => 'App Store|Magazines & Newspapers|Professional & Trade', + 13026 => 'App Store|Magazines & Newspapers|Regional News', + 13027 => 'App Store|Magazines & Newspapers|Science', + 13028 => 'App Store|Magazines & Newspapers|Teens', + 13029 => 'App Store|Magazines & Newspapers|Travel & Regional', + 13030 => "App Store|Magazines & Newspapers|Women's Interest", + 15000 => 'Textbooks|Arts & Entertainment', + 15001 => 'Textbooks|Arts & Entertainment|Art & Architecture', + 15002 => 'Textbooks|Arts & Entertainment|Art & Architecture|Urban Planning', + 15003 => 'Textbooks|Arts & Entertainment|Art History', + 15004 => 'Textbooks|Arts & Entertainment|Dance', + 15005 => 'Textbooks|Arts & Entertainment|Design', + 15006 => 'Textbooks|Arts & Entertainment|Fashion', + 15007 => 'Textbooks|Arts & Entertainment|Film', + 15008 => 'Textbooks|Arts & Entertainment|Games', + 15009 => 'Textbooks|Arts & Entertainment|Interior Design', + 15010 => 'Textbooks|Arts & Entertainment|Media Arts', + 15011 => 'Textbooks|Arts & Entertainment|Music', + 15012 => 'Textbooks|Arts & Entertainment|Performing Arts', + 15013 => 'Textbooks|Arts & Entertainment|Photography', + 15014 => 'Textbooks|Arts & Entertainment|Theater', + 15015 => 'Textbooks|Arts & Entertainment|TV', + 15016 => 'Textbooks|Arts & Entertainment|Visual Arts', + 15017 => 'Textbooks|Biographies & Memoirs', + 15018 => 'Textbooks|Business & Personal Finance', + 15019 => 'Textbooks|Business & Personal Finance|Accounting', + 15020 => 'Textbooks|Business & Personal Finance|Careers', + 15021 => 'Textbooks|Business & Personal Finance|Economics', + 15022 => 'Textbooks|Business & Personal Finance|Finance', + 15023 => 'Textbooks|Business & Personal Finance|Hospitality', + 15024 => 'Textbooks|Business & Personal Finance|Industries & Professions', + 15025 => 'Textbooks|Business & Personal Finance|Investing', + 15026 => 'Textbooks|Business & Personal Finance|Management & Leadership', + 15027 => 'Textbooks|Business & Personal Finance|Marketing & Sales', + 15028 => 'Textbooks|Business & Personal Finance|Personal Finance', + 15029 => 'Textbooks|Business & Personal Finance|Real Estate', + 15030 => 'Textbooks|Business & Personal Finance|Reference', + 15031 => 'Textbooks|Business & Personal Finance|Small Business & Entrepreneurship', + 15032 => 'Textbooks|Children & Teens', + 15033 => 'Textbooks|Children & Teens|Fiction', + 15034 => 'Textbooks|Children & Teens|Nonfiction', + 15035 => 'Textbooks|Comics & Graphic Novels', + 15036 => 'Textbooks|Comics & Graphic Novels|Graphic Novels', + 15037 => 'Textbooks|Comics & Graphic Novels|Manga', + 15038 => 'Textbooks|Communications & Media', + 15039 => 'Textbooks|Communications & Media|Broadcasting', + 15040 => 'Textbooks|Communications & Media|Digital Media', + 15041 => 'Textbooks|Communications & Media|Journalism', + 15042 => 'Textbooks|Communications & Media|Photojournalism', + 15043 => 'Textbooks|Communications & Media|Print', + 15044 => 'Textbooks|Communications & Media|Speech', + 15045 => 'Textbooks|Communications & Media|Writing', + 15046 => 'Textbooks|Computers & Internet', + 15047 => 'Textbooks|Computers & Internet|Computers', + 15048 => 'Textbooks|Computers & Internet|Databases', + 15049 => 'Textbooks|Computers & Internet|Digital Media', + 15050 => 'Textbooks|Computers & Internet|Internet', + 15051 => 'Textbooks|Computers & Internet|Network', + 15052 => 'Textbooks|Computers & Internet|Operating Systems', + 15053 => 'Textbooks|Computers & Internet|Programming', + 15054 => 'Textbooks|Computers & Internet|Software', + 15055 => 'Textbooks|Computers & Internet|System Administration', + 15056 => 'Textbooks|Cookbooks, Food & Wine', + 15057 => 'Textbooks|Cookbooks, Food & Wine|Beverages', + 15058 => 'Textbooks|Cookbooks, Food & Wine|Courses & Dishes', + 15059 => 'Textbooks|Cookbooks, Food & Wine|Culinary Arts', + 15060 => 'Textbooks|Cookbooks, Food & Wine|Methods', + 15061 => 'Textbooks|Cookbooks, Food & Wine|Reference', + 15062 => 'Textbooks|Cookbooks, Food & Wine|Regional & Ethnic', + 15063 => 'Textbooks|Cookbooks, Food & Wine|Special Diet', + 15064 => 'Textbooks|Cookbooks, Food & Wine|Special Occasions', + 15065 => 'Textbooks|Cookbooks, Food & Wine|Specific Ingredients', + 15066 => 'Textbooks|Engineering', + 15067 => 'Textbooks|Engineering|Aeronautics', + 15068 => 'Textbooks|Engineering|Chemical & Petroleum Engineering', + 15069 => 'Textbooks|Engineering|Civil Engineering', + 15070 => 'Textbooks|Engineering|Computer Science', + 15071 => 'Textbooks|Engineering|Electrical Engineering', + 15072 => 'Textbooks|Engineering|Environmental Engineering', + 15073 => 'Textbooks|Engineering|Mechanical Engineering', + 15074 => 'Textbooks|Engineering|Power Resources', + 15075 => 'Textbooks|Fiction & Literature', + 15076 => 'Textbooks|Fiction & Literature|Latino', + 15077 => 'Textbooks|Fiction & Literature|Action & Adventure', + 15078 => 'Textbooks|Fiction & Literature|African American', + 15079 => 'Textbooks|Fiction & Literature|Anthologies', + 15080 => 'Textbooks|Fiction & Literature|Classics', + 15081 => 'Textbooks|Fiction & Literature|Comparative Literature', + 15082 => 'Textbooks|Fiction & Literature|Erotica', + 15083 => 'Textbooks|Fiction & Literature|Gay', + 15084 => 'Textbooks|Fiction & Literature|Ghost', + 15085 => 'Textbooks|Fiction & Literature|Historical', + 15086 => 'Textbooks|Fiction & Literature|Horror', + 15087 => 'Textbooks|Fiction & Literature|Literary', + 15088 => 'Textbooks|Fiction & Literature|Literary Criticism', + 15089 => 'Textbooks|Fiction & Literature|Poetry', + 15090 => 'Textbooks|Fiction & Literature|Religious', + 15091 => 'Textbooks|Fiction & Literature|Short Stories', + 15092 => 'Textbooks|Health, Mind & Body', + 15093 => 'Textbooks|Health, Mind & Body|Fitness', + 15094 => 'Textbooks|Health, Mind & Body|Self-Improvement', + 15095 => 'Textbooks|History', + 15096 => 'Textbooks|History|Africa', + 15097 => 'Textbooks|History|Americas', + 15098 => 'Textbooks|History|Americas|Canada', + 15099 => 'Textbooks|History|Americas|Latin America', + 15100 => 'Textbooks|History|Americas|United States', + 15101 => 'Textbooks|History|Ancient', + 15102 => 'Textbooks|History|Asia', + 15103 => 'Textbooks|History|Australia & Oceania', + 15104 => 'Textbooks|History|Europe', + 15105 => 'Textbooks|History|Middle East', + 15106 => 'Textbooks|History|Military', + 15107 => 'Textbooks|History|World', + 15108 => 'Textbooks|Humor', + 15109 => 'Textbooks|Language Studies', + 15110 => 'Textbooks|Language Studies|African Languages', + 15111 => 'Textbooks|Language Studies|Ancient Languages', + 15112 => 'Textbooks|Language Studies|Arabic', + 15113 => 'Textbooks|Language Studies|Bilingual Editions', + 15114 => 'Textbooks|Language Studies|Chinese', + 15115 => 'Textbooks|Language Studies|English', + 15116 => 'Textbooks|Language Studies|French', + 15117 => 'Textbooks|Language Studies|German', + 15118 => 'Textbooks|Language Studies|Hebrew', + 15119 => 'Textbooks|Language Studies|Hindi', + 15120 => 'Textbooks|Language Studies|Indigenous Languages', + 15121 => 'Textbooks|Language Studies|Italian', + 15122 => 'Textbooks|Language Studies|Japanese', + 15123 => 'Textbooks|Language Studies|Korean', + 15124 => 'Textbooks|Language Studies|Linguistics', + 15125 => 'Textbooks|Language Studies|Other Language', + 15126 => 'Textbooks|Language Studies|Portuguese', + 15127 => 'Textbooks|Language Studies|Russian', + 15128 => 'Textbooks|Language Studies|Spanish', + 15129 => 'Textbooks|Language Studies|Speech Pathology', + 15130 => 'Textbooks|Lifestyle & Home', + 15131 => 'Textbooks|Lifestyle & Home|Antiques & Collectibles', + 15132 => 'Textbooks|Lifestyle & Home|Crafts & Hobbies', + 15133 => 'Textbooks|Lifestyle & Home|Gardening', + 15134 => 'Textbooks|Lifestyle & Home|Pets', + 15135 => 'Textbooks|Mathematics', + 15136 => 'Textbooks|Mathematics|Advanced Mathematics', + 15137 => 'Textbooks|Mathematics|Algebra', + 15138 => 'Textbooks|Mathematics|Arithmetic', + 15139 => 'Textbooks|Mathematics|Calculus', + 15140 => 'Textbooks|Mathematics|Geometry', + 15141 => 'Textbooks|Mathematics|Statistics', + 15142 => 'Textbooks|Medicine', + 15143 => 'Textbooks|Medicine|Anatomy & Physiology', + 15144 => 'Textbooks|Medicine|Dentistry', + 15145 => 'Textbooks|Medicine|Emergency Medicine', + 15146 => 'Textbooks|Medicine|Genetics', + 15147 => 'Textbooks|Medicine|Immunology', + 15148 => 'Textbooks|Medicine|Neuroscience', + 15149 => 'Textbooks|Medicine|Nursing', + 15150 => 'Textbooks|Medicine|Pharmacology & Toxicology', + 15151 => 'Textbooks|Medicine|Psychiatry', + 15152 => 'Textbooks|Medicine|Psychology', + 15153 => 'Textbooks|Medicine|Radiology', + 15154 => 'Textbooks|Medicine|Veterinary', + 15155 => 'Textbooks|Mysteries & Thrillers', + 15156 => 'Textbooks|Mysteries & Thrillers|British Detectives', + 15157 => 'Textbooks|Mysteries & Thrillers|Hard-Boiled', + 15158 => 'Textbooks|Mysteries & Thrillers|Historical', + 15159 => 'Textbooks|Mysteries & Thrillers|Police Procedural', + 15160 => 'Textbooks|Mysteries & Thrillers|Short Stories', + 15161 => 'Textbooks|Mysteries & Thrillers|Women Sleuths', + 15162 => 'Textbooks|Nonfiction', + 15163 => 'Textbooks|Nonfiction|Family & Relationships', + 15164 => 'Textbooks|Nonfiction|Transportation', + 15165 => 'Textbooks|Nonfiction|True Crime', + 15166 => 'Textbooks|Parenting', + 15167 => 'Textbooks|Philosophy', + 15168 => 'Textbooks|Philosophy|Aesthetics', + 15169 => 'Textbooks|Philosophy|Epistemology', + 15170 => 'Textbooks|Philosophy|Ethics', + 15171 => 'Textbooks|Philosophy|Philosophy of Language', + 15172 => 'Textbooks|Philosophy|Logic', + 15173 => 'Textbooks|Philosophy|Metaphysics', + 15174 => 'Textbooks|Philosophy|Political Philosophy', + 15175 => 'Textbooks|Philosophy|Philosophy of Religion', + 15176 => 'Textbooks|Politics & Current Events', + 15177 => 'Textbooks|Politics & Current Events|Current Events', + 15178 => 'Textbooks|Politics & Current Events|Foreign Policy & International Relations', + 15179 => 'Textbooks|Politics & Current Events|Local Governments', + 15180 => 'Textbooks|Politics & Current Events|National Governments', + 15181 => 'Textbooks|Politics & Current Events|Political Science', + 15182 => 'Textbooks|Politics & Current Events|Public Administration', + 15183 => 'Textbooks|Politics & Current Events|World Affairs', + 15184 => 'Textbooks|Professional & Technical', + 15185 => 'Textbooks|Professional & Technical|Design', + 15186 => 'Textbooks|Professional & Technical|Language Arts & Disciplines', + 15187 => 'Textbooks|Professional & Technical|Engineering', + 15188 => 'Textbooks|Professional & Technical|Law', + 15189 => 'Textbooks|Professional & Technical|Medical', + 15190 => 'Textbooks|Reference', + 15191 => 'Textbooks|Reference|Almanacs & Yearbooks', + 15192 => 'Textbooks|Reference|Atlases & Maps', + 15193 => 'Textbooks|Reference|Catalogs & Directories', + 15194 => 'Textbooks|Reference|Consumer Guides', + 15195 => 'Textbooks|Reference|Dictionaries & Thesauruses', + 15196 => 'Textbooks|Reference|Encyclopedias', + 15197 => 'Textbooks|Reference|Etiquette', + 15198 => 'Textbooks|Reference|Quotations', + 15199 => 'Textbooks|Reference|Study Aids', + 15200 => 'Textbooks|Reference|Words & Language', + 15201 => 'Textbooks|Reference|Writing', + 15202 => 'Textbooks|Religion & Spirituality', + 15203 => 'Textbooks|Religion & Spirituality|Bible Studies', + 15204 => 'Textbooks|Religion & Spirituality|Bibles', + 15205 => 'Textbooks|Religion & Spirituality|Buddhism', + 15206 => 'Textbooks|Religion & Spirituality|Christianity', + 15207 => 'Textbooks|Religion & Spirituality|Comparative Religion', + 15208 => 'Textbooks|Religion & Spirituality|Hinduism', + 15209 => 'Textbooks|Religion & Spirituality|Islam', + 15210 => 'Textbooks|Religion & Spirituality|Judaism', + 15211 => 'Textbooks|Religion & Spirituality|Spirituality', + 15212 => 'Textbooks|Romance', + 15213 => 'Textbooks|Romance|Contemporary', + 15214 => 'Textbooks|Romance|Erotic Romance', + 15215 => 'Textbooks|Romance|Paranormal', + 15216 => 'Textbooks|Romance|Historical', + 15217 => 'Textbooks|Romance|Short Stories', + 15218 => 'Textbooks|Romance|Suspense', + 15219 => 'Textbooks|Romance|Western', + 15220 => 'Textbooks|Sci-Fi & Fantasy', + 15221 => 'Textbooks|Sci-Fi & Fantasy|Fantasy', + 15222 => 'Textbooks|Sci-Fi & Fantasy|Fantasy|Contemporary', + 15223 => 'Textbooks|Sci-Fi & Fantasy|Fantasy|Epic', + 15224 => 'Textbooks|Sci-Fi & Fantasy|Fantasy|Historical', + 15225 => 'Textbooks|Sci-Fi & Fantasy|Fantasy|Paranormal', + 15226 => 'Textbooks|Sci-Fi & Fantasy|Fantasy|Short Stories', + 15227 => 'Textbooks|Sci-Fi & Fantasy|Science Fiction', + 15228 => 'Textbooks|Sci-Fi & Fantasy|Science Fiction & Literature', + 15229 => 'Textbooks|Sci-Fi & Fantasy|Science Fiction & Literature|Adventure', + 15230 => 'Textbooks|Sci-Fi & Fantasy|Science Fiction & Literature|High Tech', + 15231 => 'Textbooks|Sci-Fi & Fantasy|Science Fiction & Literature|Short Stories', + 15232 => 'Textbooks|Science & Nature', + 15233 => 'Textbooks|Science & Nature|Agriculture', + 15234 => 'Textbooks|Science & Nature|Astronomy', + 15235 => 'Textbooks|Science & Nature|Atmosphere', + 15236 => 'Textbooks|Science & Nature|Biology', + 15237 => 'Textbooks|Science & Nature|Chemistry', + 15238 => 'Textbooks|Science & Nature|Earth Sciences', + 15239 => 'Textbooks|Science & Nature|Ecology', + 15240 => 'Textbooks|Science & Nature|Environment', + 15241 => 'Textbooks|Science & Nature|Essays', + 15242 => 'Textbooks|Science & Nature|Geography', + 15243 => 'Textbooks|Science & Nature|Geology', + 15244 => 'Textbooks|Science & Nature|History', + 15245 => 'Textbooks|Science & Nature|Life Sciences', + 15246 => 'Textbooks|Science & Nature|Nature', + 15247 => 'Textbooks|Science & Nature|Physics', + 15248 => 'Textbooks|Science & Nature|Reference', + 15249 => 'Textbooks|Social Science', + 15250 => 'Textbooks|Social Science|Anthropology', + 15251 => 'Textbooks|Social Science|Archaeology', + 15252 => 'Textbooks|Social Science|Civics', + 15253 => 'Textbooks|Social Science|Government', + 15254 => 'Textbooks|Social Science|Social Studies', + 15255 => 'Textbooks|Social Science|Social Welfare', + 15256 => 'Textbooks|Social Science|Society', + 15257 => 'Textbooks|Social Science|Society|African Studies', + 15258 => 'Textbooks|Social Science|Society|American Studies', + 15259 => 'Textbooks|Social Science|Society|Asia Pacific Studies', + 15260 => 'Textbooks|Social Science|Society|Cross-Cultural Studies', + 15261 => 'Textbooks|Social Science|Society|European Studies', + 15262 => 'Textbooks|Social Science|Society|Immigration & Emigration', + 15263 => 'Textbooks|Social Science|Society|Indigenous Studies', + 15264 => 'Textbooks|Social Science|Society|Latin & Caribbean Studies', + 15265 => 'Textbooks|Social Science|Society|Middle Eastern Studies', + 15266 => 'Textbooks|Social Science|Society|Race & Ethnicity Studies', + 15267 => 'Textbooks|Social Science|Society|Sexuality Studies', + 15268 => "Textbooks|Social Science|Society|Women's Studies", + 15269 => 'Textbooks|Social Science|Sociology', + 15270 => 'Textbooks|Sports & Outdoors', + 15271 => 'Textbooks|Sports & Outdoors|Baseball', + 15272 => 'Textbooks|Sports & Outdoors|Basketball', + 15273 => 'Textbooks|Sports & Outdoors|Coaching', + 15274 => 'Textbooks|Sports & Outdoors|Equestrian', + 15275 => 'Textbooks|Sports & Outdoors|Extreme Sports', + 15276 => 'Textbooks|Sports & Outdoors|Football', + 15277 => 'Textbooks|Sports & Outdoors|Golf', + 15278 => 'Textbooks|Sports & Outdoors|Hockey', + 15279 => 'Textbooks|Sports & Outdoors|Motor Sports', + 15280 => 'Textbooks|Sports & Outdoors|Mountaineering', + 15281 => 'Textbooks|Sports & Outdoors|Outdoors', + 15282 => 'Textbooks|Sports & Outdoors|Racket Sports', + 15283 => 'Textbooks|Sports & Outdoors|Reference', + 15284 => 'Textbooks|Sports & Outdoors|Soccer', + 15285 => 'Textbooks|Sports & Outdoors|Training', + 15286 => 'Textbooks|Sports & Outdoors|Water Sports', + 15287 => 'Textbooks|Sports & Outdoors|Winter Sports', + 15288 => 'Textbooks|Teaching & Learning', + 15289 => 'Textbooks|Teaching & Learning|Adult Education', + 15290 => 'Textbooks|Teaching & Learning|Curriculum & Teaching', + 15291 => 'Textbooks|Teaching & Learning|Educational Leadership', + 15292 => 'Textbooks|Teaching & Learning|Educational Technology', + 15293 => 'Textbooks|Teaching & Learning|Family & Childcare', + 15294 => 'Textbooks|Teaching & Learning|Information & Library Science', + 15295 => 'Textbooks|Teaching & Learning|Learning Resources', + 15296 => 'Textbooks|Teaching & Learning|Psychology & Research', + 15297 => 'Textbooks|Teaching & Learning|Special Education', + 15298 => 'Textbooks|Travel & Adventure', + 15299 => 'Textbooks|Travel & Adventure|Africa', + 15300 => 'Textbooks|Travel & Adventure|Americas', + 15301 => 'Textbooks|Travel & Adventure|Americas|Canada', + 15302 => 'Textbooks|Travel & Adventure|Americas|Latin America', + 15303 => 'Textbooks|Travel & Adventure|Americas|United States', + 15304 => 'Textbooks|Travel & Adventure|Asia', + 15305 => 'Textbooks|Travel & Adventure|Caribbean', + 15306 => 'Textbooks|Travel & Adventure|Essays & Memoirs', + 15307 => 'Textbooks|Travel & Adventure|Europe', + 15308 => 'Textbooks|Travel & Adventure|Middle East', + 15309 => 'Textbooks|Travel & Adventure|Oceania', + 15310 => 'Textbooks|Travel & Adventure|Specialty Travel', + 15311 => 'Textbooks|Comics & Graphic Novels|Comics', + 15312 => 'Textbooks|Reference|Manuals', + 16001 => 'App Store|Stickers|Emoji & Expressions', + 16003 => 'App Store|Stickers|Animals & Nature', + 16005 => 'App Store|Stickers|Art', + 16006 => 'App Store|Stickers|Celebrations', + 16007 => 'App Store|Stickers|Celebrities', + 16008 => 'App Store|Stickers|Comics & Cartoons', + 16009 => 'App Store|Stickers|Eating & Drinking', + 16010 => 'App Store|Stickers|Gaming', + 16014 => 'App Store|Stickers|Movies & TV', + 16015 => 'App Store|Stickers|Music', + 16017 => 'App Store|Stickers|People', + 16019 => 'App Store|Stickers|Places & Objects', + 16021 => 'App Store|Stickers|Sports & Activities', + 16025 => 'App Store|Stickers|Kids & Family', + 16026 => 'App Store|Stickers|Fashion', + 100000 => 'Music|Christian & Gospel', + 100001 => 'Music|Classical|Art Song', + 100002 => 'Music|Classical|Brass & Woodwinds', + 100003 => 'Music|Classical|Solo Instrumental', + 100004 => 'Music|Classical|Contemporary Era', + 100005 => 'Music|Classical|Oratorio', + 100006 => 'Music|Classical|Cantata', + 100007 => 'Music|Classical|Electronic', + 100008 => 'Music|Classical|Sacred', + 100009 => 'Music|Classical|Guitar', + 100010 => 'Music|Classical|Piano', + 100011 => 'Music|Classical|Violin', + 100012 => 'Music|Classical|Cello', + 100013 => 'Music|Classical|Percussion', + 100014 => 'Music|Electronic|Dubstep', + 100015 => 'Music|Electronic|Bass', + 100016 => 'Music|Hip-Hop/Rap|UK Hip-Hop', + 100017 => 'Music|Reggae|Lovers Rock', + 100018 => 'Music|Alternative|EMO', + 100019 => 'Music|Alternative|Pop Punk', + 100020 => 'Music|Alternative|Indie Pop', + 100021 => 'Music|New Age|Yoga', + 100022 => 'Music|Pop|Tribute', + 100023 => 'Music|Pop|Shows', + 40000000 => 'iTunes U', + 40000001 => 'iTunes U|Business', + 40000002 => 'iTunes U|Business|Economics', + 40000003 => 'iTunes U|Business|Finance', + 40000004 => 'iTunes U|Business|Hospitality', + 40000005 => 'iTunes U|Business|Management', + 40000006 => 'iTunes U|Business|Marketing', + 40000007 => 'iTunes U|Business|Personal Finance', + 40000008 => 'iTunes U|Business|Real Estate', + 40000009 => 'iTunes U|Engineering', + 40000010 => 'iTunes U|Engineering|Chemical & Petroleum Engineering', + 40000011 => 'iTunes U|Engineering|Civil Engineering', + 40000012 => 'iTunes U|Engineering|Computer Science', + 40000013 => 'iTunes U|Engineering|Electrical Engineering', + 40000014 => 'iTunes U|Engineering|Environmental Engineering', + 40000015 => 'iTunes U|Engineering|Mechanical Engineering', + 40000016 => 'iTunes U|Art & Architecture', + 40000017 => 'iTunes U|Art & Architecture|Architecture', + 40000019 => 'iTunes U|Art & Architecture|Art History', + 40000020 => 'iTunes U|Art & Architecture|Dance', + 40000021 => 'iTunes U|Art & Architecture|Film', + 40000022 => 'iTunes U|Art & Architecture|Design', + 40000023 => 'iTunes U|Art & Architecture|Interior Design', + 40000024 => 'iTunes U|Art & Architecture|Music', + 40000025 => 'iTunes U|Art & Architecture|Theater', + 40000026 => 'iTunes U|Health & Medicine', + 40000027 => 'iTunes U|Health & Medicine|Anatomy & Physiology', + 40000028 => 'iTunes U|Health & Medicine|Behavioral Science', + 40000029 => 'iTunes U|Health & Medicine|Dentistry', + 40000030 => 'iTunes U|Health & Medicine|Diet & Nutrition', + 40000031 => 'iTunes U|Health & Medicine|Emergency Medicine', + 40000032 => 'iTunes U|Health & Medicine|Genetics', + 40000033 => 'iTunes U|Health & Medicine|Gerontology', + 40000034 => 'iTunes U|Health & Medicine|Health & Exercise Science', + 40000035 => 'iTunes U|Health & Medicine|Immunology', + 40000036 => 'iTunes U|Health & Medicine|Neuroscience', + 40000037 => 'iTunes U|Health & Medicine|Pharmacology & Toxicology', + 40000038 => 'iTunes U|Health & Medicine|Psychiatry', + 40000039 => 'iTunes U|Health & Medicine|Global Health', + 40000040 => 'iTunes U|Health & Medicine|Radiology', + 40000041 => 'iTunes U|History', + 40000042 => 'iTunes U|History|Ancient History', + 40000043 => 'iTunes U|History|Medieval History', + 40000044 => 'iTunes U|History|Military History', + 40000045 => 'iTunes U|History|Modern History', + 40000046 => 'iTunes U|History|African History', + 40000047 => 'iTunes U|History|Asia-Pacific History', + 40000048 => 'iTunes U|History|European History', + 40000049 => 'iTunes U|History|Middle Eastern History', + 40000050 => 'iTunes U|History|North American History', + 40000051 => 'iTunes U|History|South American History', + 40000053 => 'iTunes U|Communications & Media', + 40000054 => 'iTunes U|Philosophy', + 40000055 => 'iTunes U|Religion & Spirituality', + 40000056 => 'iTunes U|Language', + 40000057 => 'iTunes U|Language|African Languages', + 40000058 => 'iTunes U|Language|Ancient Languages', + 40000061 => 'iTunes U|Language|English', + 40000063 => 'iTunes U|Language|French', + 40000064 => 'iTunes U|Language|German', + 40000065 => 'iTunes U|Language|Italian', + 40000066 => 'iTunes U|Language|Linguistics', + 40000068 => 'iTunes U|Language|Spanish', + 40000069 => 'iTunes U|Language|Speech Pathology', + 40000070 => 'iTunes U|Literature', + 40000071 => 'iTunes U|Literature|Anthologies', + 40000072 => 'iTunes U|Literature|Biography', + 40000073 => 'iTunes U|Literature|Classics', + 40000074 => 'iTunes U|Literature|Literary Criticism', + 40000075 => 'iTunes U|Literature|Fiction', + 40000076 => 'iTunes U|Literature|Poetry', + 40000077 => 'iTunes U|Mathematics', + 40000078 => 'iTunes U|Mathematics|Advanced Mathematics', + 40000079 => 'iTunes U|Mathematics|Algebra', + 40000080 => 'iTunes U|Mathematics|Arithmetic', + 40000081 => 'iTunes U|Mathematics|Calculus', + 40000082 => 'iTunes U|Mathematics|Geometry', + 40000083 => 'iTunes U|Mathematics|Statistics', + 40000084 => 'iTunes U|Science', + 40000085 => 'iTunes U|Science|Agricultural', + 40000086 => 'iTunes U|Science|Astronomy', + 40000087 => 'iTunes U|Science|Atmosphere', + 40000088 => 'iTunes U|Science|Biology', + 40000089 => 'iTunes U|Science|Chemistry', + 40000090 => 'iTunes U|Science|Ecology', + 40000091 => 'iTunes U|Science|Geography', + 40000092 => 'iTunes U|Science|Geology', + 40000093 => 'iTunes U|Science|Physics', + 40000094 => 'iTunes U|Psychology & Social Science', + 40000095 => 'iTunes U|Law & Politics|Law', + 40000096 => 'iTunes U|Law & Politics|Political Science', + 40000097 => 'iTunes U|Law & Politics|Public Administration', + 40000098 => 'iTunes U|Psychology & Social Science|Psychology', + 40000099 => 'iTunes U|Psychology & Social Science|Social Welfare', + 40000100 => 'iTunes U|Psychology & Social Science|Sociology', + 40000101 => 'iTunes U|Society', + 40000103 => 'iTunes U|Society|Asia Pacific Studies', + 40000104 => 'iTunes U|Society|European Studies', + 40000105 => 'iTunes U|Society|Indigenous Studies', + 40000106 => 'iTunes U|Society|Latin & Caribbean Studies', + 40000107 => 'iTunes U|Society|Middle Eastern Studies', + 40000108 => "iTunes U|Society|Women's Studies", + 40000109 => 'iTunes U|Teaching & Learning', + 40000110 => 'iTunes U|Teaching & Learning|Curriculum & Teaching', + 40000111 => 'iTunes U|Teaching & Learning|Educational Leadership', + 40000112 => 'iTunes U|Teaching & Learning|Family & Childcare', + 40000113 => 'iTunes U|Teaching & Learning|Learning Resources', + 40000114 => 'iTunes U|Teaching & Learning|Psychology & Research', + 40000115 => 'iTunes U|Teaching & Learning|Special Education', + 40000116 => 'iTunes U|Art & Architecture|Culinary Arts', + 40000117 => 'iTunes U|Art & Architecture|Fashion', + 40000118 => 'iTunes U|Art & Architecture|Media Arts', + 40000119 => 'iTunes U|Art & Architecture|Photography', + 40000120 => 'iTunes U|Art & Architecture|Visual Art', + 40000121 => 'iTunes U|Business|Entrepreneurship', + 40000122 => 'iTunes U|Communications & Media|Broadcasting', + 40000123 => 'iTunes U|Communications & Media|Digital Media', + 40000124 => 'iTunes U|Communications & Media|Journalism', + 40000125 => 'iTunes U|Communications & Media|Photojournalism', + 40000126 => 'iTunes U|Communications & Media|Print', + 40000127 => 'iTunes U|Communications & Media|Speech', + 40000128 => 'iTunes U|Communications & Media|Writing', + 40000129 => 'iTunes U|Health & Medicine|Nursing', + 40000130 => 'iTunes U|Language|Arabic', + 40000131 => 'iTunes U|Language|Chinese', + 40000132 => 'iTunes U|Language|Hebrew', + 40000133 => 'iTunes U|Language|Hindi', + 40000134 => 'iTunes U|Language|Indigenous Languages', + 40000135 => 'iTunes U|Language|Japanese', + 40000136 => 'iTunes U|Language|Korean', + 40000137 => 'iTunes U|Language|Other Languages', + 40000138 => 'iTunes U|Language|Portuguese', + 40000139 => 'iTunes U|Language|Russian', + 40000140 => 'iTunes U|Law & Politics', + 40000141 => 'iTunes U|Law & Politics|Foreign Policy & International Relations', + 40000142 => 'iTunes U|Law & Politics|Local Governments', + 40000143 => 'iTunes U|Law & Politics|National Governments', + 40000144 => 'iTunes U|Law & Politics|World Affairs', + 40000145 => 'iTunes U|Literature|Comparative Literature', + 40000146 => 'iTunes U|Philosophy|Aesthetics', + 40000147 => 'iTunes U|Philosophy|Epistemology', + 40000148 => 'iTunes U|Philosophy|Ethics', + 40000149 => 'iTunes U|Philosophy|Metaphysics', + 40000150 => 'iTunes U|Philosophy|Political Philosophy', + 40000151 => 'iTunes U|Philosophy|Logic', + 40000152 => 'iTunes U|Philosophy|Philosophy of Language', + 40000153 => 'iTunes U|Philosophy|Philosophy of Religion', + 40000154 => 'iTunes U|Psychology & Social Science|Archaeology', + 40000155 => 'iTunes U|Psychology & Social Science|Anthropology', + 40000156 => 'iTunes U|Religion & Spirituality|Buddhism', + 40000157 => 'iTunes U|Religion & Spirituality|Christianity', + 40000158 => 'iTunes U|Religion & Spirituality|Comparative Religion', + 40000159 => 'iTunes U|Religion & Spirituality|Hinduism', + 40000160 => 'iTunes U|Religion & Spirituality|Islam', + 40000161 => 'iTunes U|Religion & Spirituality|Judaism', + 40000162 => 'iTunes U|Religion & Spirituality|Other Religions', + 40000163 => 'iTunes U|Religion & Spirituality|Spirituality', + 40000164 => 'iTunes U|Science|Environment', + 40000165 => 'iTunes U|Society|African Studies', + 40000166 => 'iTunes U|Society|American Studies', + 40000167 => 'iTunes U|Society|Cross-cultural Studies', + 40000168 => 'iTunes U|Society|Immigration & Emigration', + 40000169 => 'iTunes U|Society|Race & Ethnicity Studies', + 40000170 => 'iTunes U|Society|Sexuality Studies', + 40000171 => 'iTunes U|Teaching & Learning|Educational Technology', + 40000172 => 'iTunes U|Teaching & Learning|Information/Library Science', + 40000173 => 'iTunes U|Language|Dutch', + 40000174 => 'iTunes U|Language|Luxembourgish', + 40000175 => 'iTunes U|Language|Swedish', + 40000176 => 'iTunes U|Language|Norwegian', + 40000177 => 'iTunes U|Language|Finnish', + 40000178 => 'iTunes U|Language|Danish', + 40000179 => 'iTunes U|Language|Polish', + 40000180 => 'iTunes U|Language|Turkish', + 40000181 => 'iTunes U|Language|Flemish', + 50000024 => 'Audiobooks', + 50000040 => 'Audiobooks|Fiction', + 50000041 => 'Audiobooks|Arts & Entertainment', + 50000042 => 'Audiobooks|Biography & Memoir', + 50000043 => 'Audiobooks|Business', + 50000044 => 'Audiobooks|Kids & Young Adults', + 50000045 => 'Audiobooks|Classics', + 50000046 => 'Audiobooks|Comedy', + 50000047 => 'Audiobooks|Drama & Poetry', + 50000048 => 'Audiobooks|Speakers & Storytellers', + 50000049 => 'Audiobooks|History', + 50000050 => 'Audiobooks|Languages', + 50000051 => 'Audiobooks|Mystery', + 50000052 => 'Audiobooks|Nonfiction', + 50000053 => 'Audiobooks|Religion & Spirituality', + 50000054 => 'Audiobooks|Science', + 50000055 => 'Audiobooks|Sci Fi & Fantasy', + 50000056 => 'Audiobooks|Self Development', + 50000057 => 'Audiobooks|Sports', + 50000058 => 'Audiobooks|Technology', + 50000059 => 'Audiobooks|Travel & Adventure', + 50000061 => 'Music|Spoken Word', + 50000063 => 'Music|Disney', + 50000064 => 'Music|French Pop', + 50000066 => 'Music|German Pop', + 50000068 => 'Music|German Folk', + 50000069 => 'Audiobooks|Romance', + 50000070 => 'Audiobooks|Audiobooks Latino', + 50000071 => 'Books|Comics & Graphic Novels|Manga|Action', + 50000072 => 'Books|Comics & Graphic Novels|Manga|Comedy', + 50000073 => 'Books|Comics & Graphic Novels|Manga|Erotica', + 50000074 => 'Books|Comics & Graphic Novels|Manga|Fantasy', + 50000075 => 'Books|Comics & Graphic Novels|Manga|Four Cell Manga', + 50000076 => 'Books|Comics & Graphic Novels|Manga|Gay & Lesbian', + 50000077 => 'Books|Comics & Graphic Novels|Manga|Hard-Boiled', + 50000078 => 'Books|Comics & Graphic Novels|Manga|Heroes', + 50000079 => 'Books|Comics & Graphic Novels|Manga|Historical Fiction', + 50000080 => 'Books|Comics & Graphic Novels|Manga|Mecha', + 50000081 => 'Books|Comics & Graphic Novels|Manga|Mystery', + 50000082 => 'Books|Comics & Graphic Novels|Manga|Nonfiction', + 50000083 => 'Books|Comics & Graphic Novels|Manga|Religious', + 50000084 => 'Books|Comics & Graphic Novels|Manga|Romance', + 50000085 => 'Books|Comics & Graphic Novels|Manga|Romantic Comedy', + 50000086 => 'Books|Comics & Graphic Novels|Manga|Science Fiction', + 50000087 => 'Books|Comics & Graphic Novels|Manga|Sports', + 50000088 => 'Books|Fiction & Literature|Light Novels', + 50000089 => 'Books|Comics & Graphic Novels|Manga|Horror', + 50000090 => 'Books|Comics & Graphic Novels|Comics', + 50000091 => 'Books|Romance|Multicultural', + }, + }, + grup => 'Grouping', #10 + hdvd => { #10 + Name => 'HDVideo', + PrintConv => { 0 => 'No', 1 => 'Yes' }, + }, + keyw => 'Keyword', #7 + ldes => 'LongDescription', #10 + pcst => { #7 + Name => 'Podcast', + PrintConv => { 0 => 'No', 1 => 'Yes' }, + }, + perf => 'Performer', + plID => { #10 (or TV season) + Name => 'PlayListID', + Format => 'int8u', # actually int64u, but split it up + }, + purd => 'PurchaseDate', #7 + purl => 'PodcastURL', #7 + rtng => { #10 + Name => 'Rating', + PrintConv => { + 0 => 'none', + 1 => 'Explicit', + 2 => 'Clean', + 4 => 'Explicit (old)', + }, + }, + sfID => { #10 + Name => 'AppleStoreCountry', + Format => 'int32u', + SeparateTable => 1, + PrintConv => { #21 + 143441 => 'United States', # US + 143442 => 'France', # FR + 143443 => 'Germany', # DE + 143444 => 'United Kingdom', # GB + 143445 => 'Austria', # AT + 143446 => 'Belgium', # BE + 143447 => 'Finland', # FI + 143448 => 'Greece', # GR + 143449 => 'Ireland', # IE + 143450 => 'Italy', # IT + 143451 => 'Luxembourg', # LU + 143452 => 'Netherlands', # NL + 143453 => 'Portugal', # PT + 143454 => 'Spain', # ES + 143455 => 'Canada', # CA + 143456 => 'Sweden', # SE + 143457 => 'Norway', # NO + 143458 => 'Denmark', # DK + 143459 => 'Switzerland', # CH + 143460 => 'Australia', # AU + 143461 => 'New Zealand', # NZ + 143462 => 'Japan', # JP + 143463 => 'Hong Kong', # HK + 143464 => 'Singapore', # SG + 143465 => 'China', # CN + 143466 => 'Republic of Korea', # KR + 143467 => 'India', # IN + 143468 => 'Mexico', # MX + 143469 => 'Russia', # RU + 143470 => 'Taiwan', # TW + 143471 => 'Vietnam', # VN + 143472 => 'South Africa', # ZA + 143473 => 'Malaysia', # MY + 143474 => 'Philippines', # PH + 143475 => 'Thailand', # TH + 143476 => 'Indonesia', # ID + 143477 => 'Pakistan', # PK + 143478 => 'Poland', # PL + 143479 => 'Saudi Arabia', # SA + 143480 => 'Turkey', # TR + 143481 => 'United Arab Emirates', # AE + 143482 => 'Hungary', # HU + 143483 => 'Chile', # CL + 143484 => 'Nepal', # NP + 143485 => 'Panama', # PA + 143486 => 'Sri Lanka', # LK + 143487 => 'Romania', # RO + 143489 => 'Czech Republic', # CZ + 143491 => 'Israel', # IL + 143492 => 'Ukraine', # UA + 143493 => 'Kuwait', # KW + 143494 => 'Croatia', # HR + 143495 => 'Costa Rica', # CR + 143496 => 'Slovakia', # SK + 143497 => 'Lebanon', # LB + 143498 => 'Qatar', # QA + 143499 => 'Slovenia', # SI + 143501 => 'Colombia', # CO + 143502 => 'Venezuela', # VE + 143503 => 'Brazil', # BR + 143504 => 'Guatemala', # GT + 143505 => 'Argentina', # AR + 143506 => 'El Salvador', # SV + 143507 => 'Peru', # PE + 143508 => 'Dominican Republic', # DO + 143509 => 'Ecuador', # EC + 143510 => 'Honduras', # HN + 143511 => 'Jamaica', # JM + 143512 => 'Nicaragua', # NI + 143513 => 'Paraguay', # PY + 143514 => 'Uruguay', # UY + 143515 => 'Macau', # MO + 143516 => 'Egypt', # EG + 143517 => 'Kazakhstan', # KZ + 143518 => 'Estonia', # EE + 143519 => 'Latvia', # LV + 143520 => 'Lithuania', # LT + 143521 => 'Malta', # MT + 143523 => 'Moldova', # MD + 143524 => 'Armenia', # AM + 143525 => 'Botswana', # BW + 143526 => 'Bulgaria', # BG + 143528 => 'Jordan', # JO + 143529 => 'Kenya', # KE + 143530 => 'Macedonia', # MK + 143531 => 'Madagascar', # MG + 143532 => 'Mali', # ML + 143533 => 'Mauritius', # MU + 143534 => 'Niger', # NE + 143535 => 'Senegal', # SN + 143536 => 'Tunisia', # TN + 143537 => 'Uganda', # UG + 143538 => 'Anguilla', # AI + 143539 => 'Bahamas', # BS + 143540 => 'Antigua and Barbuda', # AG + 143541 => 'Barbados', # BB + 143542 => 'Bermuda', # BM + 143543 => 'British Virgin Islands', # VG + 143544 => 'Cayman Islands', # KY + 143545 => 'Dominica', # DM + 143546 => 'Grenada', # GD + 143547 => 'Montserrat', # MS + 143548 => 'St. Kitts and Nevis', # KN + 143549 => 'St. Lucia', # LC + 143550 => 'St. Vincent and The Grenadines', # VC + 143551 => 'Trinidad and Tobago', # TT + 143552 => 'Turks and Caicos', # TC + 143553 => 'Guyana', # GY + 143554 => 'Suriname', # SR + 143555 => 'Belize', # BZ + 143556 => 'Bolivia', # BO + 143557 => 'Cyprus', # CY + 143558 => 'Iceland', # IS + 143559 => 'Bahrain', # BH + 143560 => 'Brunei Darussalam', # BN + 143561 => 'Nigeria', # NG + 143562 => 'Oman', # OM + 143563 => 'Algeria', # DZ + 143564 => 'Angola', # AO + 143565 => 'Belarus', # BY + 143566 => 'Uzbekistan', # UZ + 143568 => 'Azerbaijan', # AZ + 143571 => 'Yemen', # YE + 143572 => 'Tanzania', # TZ + 143573 => 'Ghana', # GH + 143575 => 'Albania', # AL + 143576 => 'Benin', # BJ + 143577 => 'Bhutan', # BT + 143578 => 'Burkina Faso', # BF + 143579 => 'Cambodia', # KH + 143580 => 'Cape Verde', # CV + 143581 => 'Chad', # TD + 143582 => 'Republic of the Congo', # CG + 143583 => 'Fiji', # FJ + 143584 => 'Gambia', # GM + 143585 => 'Guinea-Bissau', # GW + 143586 => 'Kyrgyzstan', # KG + 143587 => "Lao People's Democratic Republic", # LA + 143588 => 'Liberia', # LR + 143589 => 'Malawi', # MW + 143590 => 'Mauritania', # MR + 143591 => 'Federated States of Micronesia', # FM + 143592 => 'Mongolia', # MN + 143593 => 'Mozambique', # MZ + 143594 => 'Namibia', # NA + 143595 => 'Palau', # PW + 143597 => 'Papua New Guinea', # PG + 143598 => 'Sao Tome and Principe', # ST (S&atilde;o Tom&eacute; and Pr&iacute;ncipe) + 143599 => 'Seychelles', # SC + 143600 => 'Sierra Leone', # SL + 143601 => 'Solomon Islands', # SB + 143602 => 'Swaziland', # SZ + 143603 => 'Tajikistan', # TJ + 143604 => 'Turkmenistan', # TM + 143605 => 'Zimbabwe', # ZW + }, + }, + soaa => 'SortAlbumArtist', #10 + soal => 'SortAlbum', #10 + soar => 'SortArtist', #10 + soco => 'SortComposer', #10 + sonm => 'SortName', #10 + sosn => 'SortShow', #10 + stik => { #10 + Name => 'MediaType', + PrintConvColumns => 2, + PrintConv => { #(http://weblog.xanga.com/gryphondwb/615474010/iphone-ringtones---what-did-itunes-741-really-do.html) + 0 => 'Movie (old)', #forum9059 (was Movie) + 1 => 'Normal (Music)', + 2 => 'Audiobook', + 5 => 'Whacked Bookmark', + 6 => 'Music Video', + 9 => 'Movie', #forum9059 (was Short Film) + 10 => 'TV Show', + 11 => 'Booklet', + 14 => 'Ringtone', + 21 => 'Podcast', #15 + 23 => 'iTunes U', #forum9059 + }, + }, + rate => 'RatingPercent', #PH + titl => 'Title', + tven => 'TVEpisodeID', #7 + tves => { #7/10 + Name => 'TVEpisode', + Format => 'int32u', + }, + tvnn => 'TVNetworkName', #7 + tvsh => 'TVShow', #10 + tvsn => { #7/10 + Name => 'TVSeason', + Format => 'int32u', + }, + yrrc => 'Year', #(ffmpeg source) + itnu => { #PH (iTunes 10.5) + Name => 'iTunesU', + Description => 'iTunes U', + PrintConv => { 0 => 'No', 1 => 'Yes' }, + }, + #https://github.com/communitymedia/mediautilities/blob/master/src/net/sourceforge/jaad/mp4/boxes/BoxTypes.java + gshh => { Name => 'GoogleHostHeader', Format => 'string' }, + gspm => { Name => 'GooglePingMessage', Format => 'string' }, + gspu => { Name => 'GooglePingURL', Format => 'string' }, + gssd => { Name => 'GoogleSourceData', Format => 'string' }, + gsst => { Name => 'GoogleStartTime', Format => 'string' }, + gstd => { Name => 'GoogleTrackDuration',Format => 'string', ValueConv => '$val / 1000', PrintConv => 'ConvertDuration($val)' }, + + # atoms observed in AAX audiobooks (ref PH) + "\xa9cpy" => { Name => 'Copyright', Groups => { 2 => 'Author' } }, + "\xa9pub" => 'Publisher', + "\xa9nrt" => 'Narrator', + '@pti' => 'ParentTitle', # (guess -- same as "\xa9nam") + '@PST' => 'ParentShortTitle', # (guess -- same as "\xa9nam") + '@ppi' => 'ParentProductID', # (guess -- same as 'prID') + '@sti' => 'ShortTitle', # (guess -- same as "\xa9nam") + prID => 'ProductID', + rldt => { Name => 'ReleaseDate', Groups => { 2 => 'Time' }}, + CDEK => { Name => 'Unknown_CDEK', Unknown => 1 }, # eg: "B004ZMTFEG" - used in URL's ("asin=") + CDET => { Name => 'Unknown_CDET', Unknown => 1 }, # eg: "ADBL" + VERS => 'ProductVersion', + GUID => 'GUID', + AACR => { Name => 'Unknown_AACR', Unknown => 1 }, # eg: "CR!1T1H1QH6WX7T714G2BMFX3E9MC4S" + # ausr - 30 bytes (User Alias?) +); + +# tag decoded from timed face records +%Image::ExifTool::QuickTime::FaceInfo = ( + PROCESS_PROC => \&ProcessMOV, + GROUPS => { 2 => 'Video' }, + crec => { + Name => 'FaceRec', + SubDirectory => { + TagTable => 'Image::ExifTool::QuickTime::FaceRec', + }, + }, +); + +# tag decoded from timed face records +%Image::ExifTool::QuickTime::FaceRec = ( + PROCESS_PROC => \&ProcessMOV, + GROUPS => { 2 => 'Video' }, + cits => { + Name => 'FaceItem', + SubDirectory => { + TagTable => 'Image::ExifTool::QuickTime::Keys', + ProcessProc => \&Process_mebx, + }, + }, +); + +# item list keys (ref PH) +%Image::ExifTool::QuickTime::Keys = ( + PROCESS_PROC => \&Image::ExifTool::QuickTime::ProcessKeys, + VARS => { LONG_TAGS => 3 }, + NOTES => q{ + This directory contains a list of key names which are used to decode + ItemList tags written by the "mdta" handler. The prefix of + "com.apple.quicktime." has been removed from all TagID's below. + }, + version => 'Version', + album => 'Album', + artist => { }, + artwork => { }, + author => { Name => 'Author', Groups => { 2 => 'Author' } }, + comment => { }, + copyright => { Name => 'Copyright', Groups => { 2 => 'Author' } }, + creationdate=> { + Name => 'CreationDate', + Groups => { 2 => 'Time' }, + ValueConv => q{ + require Image::ExifTool::XMP; + $val = Image::ExifTool::XMP::ConvertXMPDate($val,1); + $val =~ s/([-+]\d{2})(\d{2})$/$1:$2/; # add colon to timezone if necessary + return $val; + }, + PrintConv => '$self->ConvertDateTime($val)', + }, + description => { }, + director => { }, + title => { }, #22 + genre => { }, + information => { }, + keywords => { }, + producer => { }, #22 + make => { Name => 'Make', Groups => { 2 => 'Camera' } }, + model => { Name => 'Model', Groups => { 2 => 'Camera' } }, + publisher => { }, + software => { }, + year => { Groups => { 2 => 'Time' } }, + 'camera.identifier' => 'CameraIdentifier', # (iPhone 4) + 'camera.framereadouttimeinmicroseconds' => { # (iPhone 4) + Name => 'FrameReadoutTime', + ValueConv => '$val * 1e-6', + PrintConv => '$val * 1e6 . " microseconds"', + }, + 'location.ISO6709' => { + Name => 'GPSCoordinates', + Groups => { 2 => 'Location' }, + ValueConv => \&ConvertISO6709, + PrintConv => \&PrintGPSCoordinates, + }, + 'location.name' => { Name => 'LocationName', Groups => { 2 => 'Location' } }, + 'location.body' => { Name => 'LocationBody', Groups => { 2 => 'Location' } }, + 'location.note' => { Name => 'LocationNote', Groups => { 2 => 'Location' } }, + 'location.role' => { + Name => 'LocationRole', + Groups => { 2 => 'Location' }, + PrintConv => { + 0 => 'Shooting Location', + 1 => 'Real Location', + 2 => 'Fictional Location', + }, + }, + 'location.date' => { + Name => 'LocationDate', + Groups => { 2 => 'Time' }, + ValueConv => q{ + require Image::ExifTool::XMP; + $val = Image::ExifTool::XMP::ConvertXMPDate($val); + $val =~ s/([-+]\d{2})(\d{2})$/$1:$2/; # add colon to timezone if necessary + return $val; + }, + PrintConv => '$self->ConvertDateTime($val)', + }, + 'direction.facing' => { Name => 'CameraDirection', Groups => { 2 => 'Location' } }, + 'direction.motion' => { Name => 'CameraMotion', Groups => { 2 => 'Location' } }, + 'location.body' => { Name => 'LocationBody', Groups => { 2 => 'Location' } }, + 'player.version' => 'PlayerVersion', + 'player.movie.visual.brightness'=> 'Brightness', + 'player.movie.visual.color' => 'Color', + 'player.movie.visual.tint' => 'Tint', + 'player.movie.visual.contrast' => 'Contrast', + 'player.movie.audio.gain' => 'AudioGain', + 'player.movie.audio.treble' => 'Trebel', + 'player.movie.audio.bass' => 'Bass', + 'player.movie.audio.balance' => 'Balance', + 'player.movie.audio.pitchshift' => 'PitchShift', + 'player.movie.audio.mute' => { + Name => 'Mute', + Format => 'int8u', + PrintConv => { 0 => 'Off', 1 => 'On' }, + }, + 'rating.user' => 'UserRating', # (Canon ELPH 510 HS) + 'collection.user' => 'UserCollection', #22 + 'Encoded_With' => 'EncodedWith', +# +# seen in timed metadata (mebx), and added dynamically via SaveMetaKeys() (ref PH): +# + # (mdta)com.apple.quicktime.video-orientation (dtyp=66, int16s) + 'video-orientation' => 'VideoOrientation', + # (mdta)com.apple.quicktime.detected-face (dtyp='com.apple.quicktime.detected-face') + 'detected-face' => { + Name => 'FaceInfo', + SubDirectory => { TagTable => 'Image::ExifTool::QuickTime::FaceInfo' }, + }, + # ---- detected-face fields ---- + # --> back here after a round trip through FaceInfo -> FaceRec -> FaceItem + # (fiel)com.apple.quicktime.detected-face.bounds (dtyp=80, float[8]) + 'detected-face.bounds' => { + Name => 'DetectedFaceBounds', + # round to a reasonable number of decimal places + PrintConv => 'my @a=split " ",$val;$_=int($_*1e6+.5)/1e6 foreach @a;join " ",@a', + }, + # (fiel)com.apple.quicktime.detected-face.face-id (dtyp=77, int32u) + 'detected-face.face-id' => 'DetectedFaceID', + # (fiel)com.apple.quicktime.detected-face.roll-angle (dtyp=23, float) + 'detected-face.roll-angle' => 'DetectedFaceRollAngle', + # (fiel)com.apple.quicktime.detected-face.yaw-angle (dtyp=23, float) + 'detected-face.yaw-angle' => 'DetectedFaceYawAngle', +); + +# iTunes info ('----') atoms +%Image::ExifTool::QuickTime::iTunesInfo = ( + PROCESS_PROC => \&ProcessMOV, + GROUPS => { 2 => 'Audio' }, + NOTES => q{ + ExifTool will extract any iTunesInfo tags that exist, even if they are not + defined in this table. + }, + # 'mean'/'name'/'data' atoms form a triplet, but unfortunately + # I haven't been able to find any documentation on this. + # 'mean' is normally 'com.apple.iTunes' + mean => { + Name => 'Mean', + # the 'Triplet' flag tells ProcessMOV() to generate + # a single tag from the mean/name/data triplet + Triplet => 1, + Hidden => 1, + }, + name => { + Name => 'Name', + Triplet => 1, + Hidden => 1, + }, + data => { + Name => 'Data', + Triplet => 1, + Hidden => 1, + }, + # the tag ID's below are composed from "mean/name", + # but "mean/" is omitted if it is "com.apple.iTunes/": + 'iTunMOVI' => { + Name => 'iTunMOVI', + SubDirectory => { TagTable => 'Image::ExifTool::PLIST::Main' }, + }, + 'tool' => { + Name => 'iTunTool', + Description => 'iTunTool', + Format => 'int32u', + PrintConv => 'sprintf("0x%.8x",$val)', + }, + 'iTunEXTC' => { + Name => 'ContentRating', + Notes => 'standard | rating | score | reasons', + # eg. 'us-tv|TV-14|500|V', 'mpaa|PG-13|300|For violence and sexuality' + # (see http://shadowofged.blogspot.ca/2008/06/itunes-content-ratings.html) + }, + 'iTunNORM' => { + Name => 'VolumeNormalization', + PrintConv => '$val=~s/ 0+(\w)/ $1/g; $val=~s/^\s+//; $val', + }, + 'iTunSMPB' => { + Name => 'iTunSMPB', + Description => 'iTunSMPB', + # hex format, similar to iTunNORM, but 12 words instead of 10, + # and 4th word is 16 hex digits (all others are 8) + # (gives AAC encoder delay, ref http://code.google.com/p/l-smash/issues/detail?id=1) + PrintConv => '$val=~s/ 0+(\w)/ $1/g; $val=~s/^\s+//; $val', + }, + # (CDDB = Compact Disc DataBase) + # iTunes_CDDB_1 = <CDDB1 disk ID>+<# tracks>+<logical block address for each track>... + 'iTunes_CDDB_1' => 'CDDB1Info', + 'iTunes_CDDB_TrackNumber' => 'CDDBTrackNumber', + 'Encoding Params' => { + Name => 'EncodingParams', + SubDirectory => { TagTable => 'Image::ExifTool::QuickTime::EncodingParams' }, + }, + # also heard about 'iTunPGAP', but I haven't seen a sample + DISCNUMBER => 'DiscNumber', #PH + TRACKNUMBER => 'TrackNumber', #PH + popularimeter => 'Popularimeter', #PH +); + +# iTunes audio encoding parameters +# ref https://developer.apple.com/library/mac/#documentation/MusicAudio/Reference/AudioCodecServicesRef/Reference/reference.html +%Image::ExifTool::QuickTime::EncodingParams = ( + PROCESS_PROC => \&ProcessEncodingParams, + GROUPS => { 2 => 'Audio' }, + # (I have commented out the ones that don't have integer values because they + # probably don't appear, and definitely wouldn't work with current decoding - PH) + + # global codec properties + #'lnam' => 'AudioCodecName', + #'lmak' => 'AudioCodecManufacturer', + #'lfor' => 'AudioCodecFormat', + 'vpk?' => 'AudioHasVariablePacketByteSizes', + #'ifm#' => 'AudioSupportedInputFormats', + #'ofm#' => 'AudioSupportedOutputFormats', + #'aisr' => 'AudioAvailableInputSampleRates', + #'aosr' => 'AudioAvailableOutputSampleRates', + 'abrt' => 'AudioAvailableBitRateRange', + 'mnip' => 'AudioMinimumNumberInputPackets', + 'mnop' => 'AudioMinimumNumberOutputPackets', + 'cmnc' => 'AudioAvailableNumberChannels', + 'lmrc' => 'AudioDoesSampleRateConversion', + #'aicl' => 'AudioAvailableInputChannelLayoutTags', + #'aocl' => 'AudioAvailableOutputChannelLayoutTags', + #'if4o' => 'AudioInputFormatsForOutputFormat', + #'of4i' => 'AudioOutputFormatsForInputFormat', + #'acfi' => 'AudioFormatInfo', + + # instance codec properties + 'tbuf' => 'AudioInputBufferSize', + 'pakf' => 'AudioPacketFrameSize', + 'pakb' => 'AudioMaximumPacketByteSize', + #'ifmt' => 'AudioCurrentInputFormat', + #'ofmt' => 'AudioCurrentOutputFormat', + #'kuki' => 'AudioMagicCookie', + 'ubuf' => 'AudioUsedInputBufferSize', + 'init' => 'AudioIsInitialized', + 'brat' => 'AudioCurrentTargetBitRate', + #'cisr' => 'AudioCurrentInputSampleRate', + #'cosr' => 'AudioCurrentOutputSampleRate', + 'srcq' => 'AudioQualitySetting', + #'brta' => 'AudioApplicableBitRateRange', + #'isra' => 'AudioApplicableInputSampleRates', + #'osra' => 'AudioApplicableOutputSampleRates', + 'pad0' => 'AudioZeroFramesPadded', + 'prmm' => 'AudioCodecPrimeMethod', + #'prim' => 'AudioCodecPrimeInfo', + #'icl ' => 'AudioInputChannelLayout', + #'ocl ' => 'AudioOutputChannelLayout', + #'acs ' => 'AudioCodecSettings', + #'acfl' => 'AudioCodecFormatList', + 'acbf' => 'AudioBitRateControlMode', + 'vbrq' => 'AudioVBRQuality', + 'mdel' => 'AudioMinimumDelayMode', + + # deprecated + 'pakd' => 'AudioRequiresPacketDescription', + #'brt#' => 'AudioAvailableBitRates', + 'acef' => 'AudioExtendFrequencies', + 'ursr' => 'AudioUseRecommendedSampleRate', + 'oppr' => 'AudioOutputPrecedence', + #'loud' => 'AudioCurrentLoudnessStatistics', + + # others + 'vers' => 'AudioEncodingParamsVersion', #PH + 'cdcv' => { #PH + Name => 'AudioComponentVersion', + ValueConv => 'join ".", unpack("ncc", pack("N",$val))', + }, +); + +# print to video data block +%Image::ExifTool::QuickTime::Video = ( + PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData, + GROUPS => { 2 => 'Video' }, + 0 => { + Name => 'DisplaySize', + PrintConv => { + 0 => 'Normal', + 1 => 'Double Size', + 2 => 'Half Size', + 3 => 'Full Screen', + 4 => 'Current Size', + }, + }, + 6 => { + Name => 'SlideShow', + PrintConv => { + 0 => 'No', + 1 => 'Yes', + }, + }, +); + +# 'hnti' atoms +%Image::ExifTool::QuickTime::HintInfo = ( + PROCESS_PROC => \&ProcessMOV, + GROUPS => { 2 => 'Video' }, + 'rtp ' => { + Name => 'RealtimeStreamingProtocol', + PrintConv => '$val=~s/^sdp /(SDP) /; $val', + }, + 'sdp ' => 'StreamingDataProtocol', +); + +# 'hinf' atoms +%Image::ExifTool::QuickTime::HintTrackInfo = ( + PROCESS_PROC => \&ProcessMOV, + GROUPS => { 2 => 'Video' }, + trpY => { Name => 'TotalBytes', Format => 'int64u' }, #(documented) + trpy => { Name => 'TotalBytes', Format => 'int64u' }, #(observed) + totl => { Name => 'TotalBytes', Format => 'int32u' }, + nump => { Name => 'NumPackets', Format => 'int64u' }, + npck => { Name => 'NumPackets', Format => 'int32u' }, + tpyl => { Name => 'TotalBytesNoRTPHeaders', Format => 'int64u' }, + tpaY => { Name => 'TotalBytesNoRTPHeaders', Format => 'int32u' }, #(documented) + tpay => { Name => 'TotalBytesNoRTPHeaders', Format => 'int32u' }, #(observed) + maxr => { + Name => 'MaxDataRate', + Format => 'int32u', + Count => 2, + PrintConv => 'my @a=split(" ",$val);sprintf("%d bytes in %.3f s",$a[1],$a[0]/1000)', + }, + dmed => { Name => 'MediaTrackBytes', Format => 'int64u' }, + dimm => { Name => 'ImmediateDataBytes', Format => 'int64u' }, + drep => { Name => 'RepeatedDataBytes', Format => 'int64u' }, + tmin => { + Name => 'MinTransmissionTime', + Format => 'int32u', + PrintConv => 'sprintf("%.3f s",$val/1000)', + }, + tmax => { + Name => 'MaxTransmissionTime', + Format => 'int32u', + PrintConv => 'sprintf("%.3f s",$val/1000)', + }, + pmax => { Name => 'LargestPacketSize', Format => 'int32u' }, + dmax => { + Name => 'LargestPacketDuration', + Format => 'int32u', + PrintConv => 'sprintf("%.3f s",$val/1000)', + }, + payt => { + Name => 'PayloadType', + Format => 'undef', # (necessary to prevent decoding as string!) + ValueConv => 'unpack("N",$val) . " " . substr($val, 5)', + PrintConv => '$val=~s/ /, /;$val', + }, +); + +# MP4 media box (ref 5) +%Image::ExifTool::QuickTime::Media = ( + PROCESS_PROC => \&ProcessMOV, + WRITE_PROC => \&WriteQuickTime, + GROUPS => { 1 => 'Track#', 2 => 'Video' }, + NOTES => 'MP4 media box.', + mdhd => { + Name => 'MediaHeader', + SubDirectory => { TagTable => 'Image::ExifTool::QuickTime::MediaHeader' }, + }, + hdlr => { + Name => 'Handler', + SubDirectory => { TagTable => 'Image::ExifTool::QuickTime::Handler' }, + }, + minf => { + Name => 'MediaInfo', + SubDirectory => { TagTable => 'Image::ExifTool::QuickTime::MediaInfo' }, + }, +); + +# MP4 media header box (ref 5) +%Image::ExifTool::QuickTime::MediaHeader = ( + PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData, + WRITE_PROC => \&Image::ExifTool::WriteBinaryData, + CHECK_PROC => \&Image::ExifTool::CheckBinaryData, + GROUPS => { 1 => 'Track#', 2 => 'Video' }, + FORMAT => 'int32u', + DATAMEMBER => [ 0, 1, 2, 3, 4 ], + 0 => { + Name => 'MediaHeaderVersion', + RawConv => '$$self{MediaHeaderVersion} = $val', + }, + 1 => { + Name => 'MediaCreateDate', + Groups => { 2 => 'Time' }, + %timeInfo, + # this is int64u if MediaHeaderVersion == 1 (ref 5/13) + Hook => '$$self{MediaHeaderVersion} and $format = "int64u", $varSize += 4', + }, + 2 => { + Name => 'MediaModifyDate', + Groups => { 2 => 'Time' }, + %timeInfo, + # this is int64u if MediaHeaderVersion == 1 (ref 5/13) + Hook => '$$self{MediaHeaderVersion} and $format = "int64u", $varSize += 4', + }, + 3 => { + Name => 'MediaTimeScale', + RawConv => '$$self{MediaTS} = $val', + }, + 4 => { + Name => 'MediaDuration', + RawConv => '$$self{MediaTS} ? $val / $$self{MediaTS} : $val', + PrintConv => '$$self{MediaTS} ? ConvertDuration($val) : $val', + # this is int64u if MediaHeaderVersion == 1 (ref 5/13) + Hook => '$$self{MediaHeaderVersion} and $format = "int64u", $varSize += 4', + }, + 5 => { + Name => 'MediaLanguageCode', + Format => 'int16u', + RawConv => '$val ? $val : undef', + # allow both Macintosh (for MOV files) and ISO (for MP4 files) language codes + ValueConv => '$val < 0x400 ? $val : pack "C*", map { (($val>>$_)&0x1f)+0x60 } 10, 5, 0', + PrintConv => q{ + return $val unless $val =~ /^\d+$/; + require Image::ExifTool::Font; + return $Image::ExifTool::Font::ttLang{Macintosh}{$val} || "Unknown ($val)"; + }, + }, +); + +# MP4 media information box (ref 5) +%Image::ExifTool::QuickTime::MediaInfo = ( + PROCESS_PROC => \&ProcessMOV, + WRITE_PROC => \&WriteQuickTime, + GROUPS => { 1 => 'Track#', 2 => 'Video' }, + NOTES => 'MP4 media info box.', + vmhd => { + Name => 'VideoHeader', + SubDirectory => { TagTable => 'Image::ExifTool::QuickTime::VideoHeader' }, + }, + smhd => { + Name => 'AudioHeader', + SubDirectory => { TagTable => 'Image::ExifTool::QuickTime::AudioHeader' }, + }, + hmhd => { + Name => 'HintHeader', + SubDirectory => { TagTable => 'Image::ExifTool::QuickTime::HintHeader' }, + }, + nmhd => { + Name => 'NullMediaHeader', + Flags => ['Binary','Unknown'], + }, + dinf => { + Name => 'DataInfo', + SubDirectory => { TagTable => 'Image::ExifTool::QuickTime::DataInfo' }, + }, + gmhd => { + Name => 'GenMediaHeader', + SubDirectory => { TagTable => 'Image::ExifTool::QuickTime::GenMediaHeader' }, + }, + hdlr => { #PH + Name => 'Handler', + SubDirectory => { TagTable => 'Image::ExifTool::QuickTime::Handler' }, + }, + stbl => { + Name => 'SampleTable', + SubDirectory => { TagTable => 'Image::ExifTool::QuickTime::SampleTable' }, + }, +); + +# MP4 video media header (ref 5) +%Image::ExifTool::QuickTime::VideoHeader = ( + PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData, + GROUPS => { 2 => 'Video' }, + NOTES => 'MP4 video media header.', + FORMAT => 'int16u', + 2 => { + Name => 'GraphicsMode', + PrintHex => 1, + SeparateTable => 'GraphicsMode', + PrintConv => \%graphicsMode, + }, + 3 => { Name => 'OpColor', Format => 'int16u[3]' }, +); + +# MP4 audio media header (ref 5) +%Image::ExifTool::QuickTime::AudioHeader = ( + PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData, + GROUPS => { 2 => 'Audio' }, + NOTES => 'MP4 audio media header.', + FORMAT => 'int16u', + 2 => { Name => 'Balance', Format => 'fixed16s' }, +); + +# MP4 hint media header (ref 5) +%Image::ExifTool::QuickTime::HintHeader = ( + PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData, + NOTES => 'MP4 hint media header.', + FORMAT => 'int16u', + 2 => 'MaxPDUSize', + 3 => 'AvgPDUSize', + 4 => { Name => 'MaxBitrate', Format => 'int32u', PrintConv => 'ConvertBitrate($val)' }, + 6 => { Name => 'AvgBitrate', Format => 'int32u', PrintConv => 'ConvertBitrate($val)' }, +); + +# MP4 sample table box (ref 5) +%Image::ExifTool::QuickTime::SampleTable = ( + PROCESS_PROC => \&ProcessMOV, + WRITE_PROC => \&WriteQuickTime, + GROUPS => { 2 => 'Video' }, + NOTES => 'MP4 sample table box.', + stsd => [ + { + Name => 'AudioSampleDesc', + Condition => '$$self{HandlerType} and $$self{HandlerType} eq "soun"', + SubDirectory => { + TagTable => 'Image::ExifTool::QuickTime::AudioSampleDesc', + ProcessProc => \&ProcessSampleDesc, + }, + },{ + Name => 'VideoSampleDesc', + Condition => '$$self{HandlerType} and $$self{HandlerType} eq "vide"', + SubDirectory => { + TagTable => 'Image::ExifTool::QuickTime::ImageDesc', + ProcessProc => \&ProcessSampleDesc, + }, + },{ + Name => 'HintSampleDesc', + Condition => '$$self{HandlerType} and $$self{HandlerType} eq "hint"', + SubDirectory => { + TagTable => 'Image::ExifTool::QuickTime::HintSampleDesc', + ProcessProc => \&ProcessSampleDesc, + }, + },{ + Name => 'MetaSampleDesc', + Condition => '$$self{HandlerType} and $$self{HandlerType} eq "meta"', + SubDirectory => { + TagTable => 'Image::ExifTool::QuickTime::MetaSampleDesc', + ProcessProc => \&ProcessSampleDesc, + }, + },{ + Name => 'OtherSampleDesc', + SubDirectory => { + TagTable => 'Image::ExifTool::QuickTime::OtherSampleDesc', + ProcessProc => \&ProcessSampleDesc, + }, + }, + # (Note: "alis" HandlerType handled by the parent audio or video handler) + ], + stts => [ # decoding time-to-sample table + { + Name => 'VideoFrameRate', + Notes => 'average rate calculated from time-to-sample table for video media', + Condition => '$$self{HandlerType} and $$self{HandlerType} eq "vide"', + Format => 'undef', # (necessary to prevent decoding as string!) + # (must be RawConv so appropriate MediaTS is used in calculation) + RawConv => 'Image::ExifTool::QuickTime::CalcSampleRate($self, \$val)', + PrintConv => 'int($val * 1000 + 0.5) / 1000', + }, + { + Name => 'TimeToSampleTable', + Flags => ['Binary','Unknown'], + }, + ], + ctts => { + Name => 'CompositionTimeToSample', + Flags => ['Binary','Unknown'], + }, + stsc => { + Name => 'SampleToChunk', + Flags => ['Binary','Unknown'], + }, + stsz => { + Name => 'SampleSizes', + Flags => ['Binary','Unknown'], + }, + stz2 => { + Name => 'CompactSampleSizes', + Flags => ['Binary','Unknown'], + }, + stco => { + Name => 'ChunkOffset', + Flags => ['Binary','Unknown'], + }, + co64 => { + Name => 'ChunkOffset64', + Flags => ['Binary','Unknown'], + }, + stss => { + Name => 'SyncSampleTable', + Flags => ['Binary','Unknown'], + }, + stsh => { + Name => 'ShadowSyncSampleTable', + Flags => ['Binary','Unknown'], + }, + padb => { + Name => 'SamplePaddingBits', + Flags => ['Binary','Unknown'], + }, + stdp => { + Name => 'SampleDegradationPriority', + Flags => ['Binary','Unknown'], + }, + sdtp => { + Name => 'IdependentAndDisposableSamples', + Flags => ['Binary','Unknown'], + }, + sbgp => { + Name => 'SampleToGroup', + Flags => ['Binary','Unknown'], + }, + sgpd => { + Name => 'SampleGroupDescription', + Flags => ['Binary','Unknown'], + }, + subs => { + Name => 'Sub-sampleInformation', + Flags => ['Binary','Unknown'], + }, + cslg => { + Name => 'CompositionToDecodeTimelineMapping', + Flags => ['Binary','Unknown'], + }, + stps => { + Name => 'PartialSyncSamples', + ValueConv => 'join " ",unpack("x8N*",$val)', + }, + # mark - 8 bytes all zero (GoPro) +); + +# MP4 audio sample description box (ref 5/AtomicParsley 0.9.4 parsley.cpp) +%Image::ExifTool::QuickTime::AudioSampleDesc = ( + PROCESS_PROC => \&ProcessHybrid, + VARS => { ID_LABEL => 'ID/Index' }, + GROUPS => { 2 => 'Audio' }, + NOTES => q{ + MP4 audio sample description. This hybrid atom contains both data and child + atoms. + }, + 4 => { + Name => 'AudioFormat', + Format => 'undef[4]', + RawConv => q{ + $$self{AudioFormat} = $val; + return undef unless $val =~ /^[\w ]{4}$/i; + # check for protected audio format + $self->OverrideFileType('M4P') if $val eq 'drms' and $$self{VALUE}{FileType} eq 'M4A'; + return $val; + }, + }, + 20 => { #PH + Name => 'AudioVendorID', + Condition => '$$self{AudioFormat} ne "mp4s"', + Format => 'undef[4]', + RawConv => '$val eq "\0\0\0\0" ? undef : $val', + PrintConv => \%vendorID, + SeparateTable => 'VendorID', + }, + 24 => { Name => 'AudioChannels', Format => 'int16u' }, + 26 => { Name => 'AudioBitsPerSample', Format => 'int16u' }, + 32 => { Name => 'AudioSampleRate', Format => 'fixed32u' }, +# +# Observed offsets for child atoms of various AudioFormat types: +# +# AudioFormat Offset Child atoms +# ----------- ------ ---------------- +# mp4a 52 * wave, chan, esds +# in24 52 wave, chan +# "ms\0\x11" 52 wave +# sowt 52 chan +# mp4a 36 * esds, pinf +# drms 36 esds, sinf +# samr 36 damr +# alac 36 alac +# ac-3 36 dac3 +# +# (* child atoms found at different offsets in mp4a) +# + pinf => { + Name => 'PurchaseInfo', + SubDirectory => { TagTable => 'Image::ExifTool::QuickTime::ProtectionInfo' }, + }, + sinf => { # "protection scheme information" + Name => 'ProtectionInfo', #3 + SubDirectory => { TagTable => 'Image::ExifTool::QuickTime::ProtectionInfo' }, + }, + # f - 16/36 bytes + # esds - 31/40/42/43 bytes - ES descriptor (ref 3) + damr => { #3 + Name => 'DecodeConfig', + SubDirectory => { TagTable => 'Image::ExifTool::QuickTime::DecodeConfig' }, + }, + wave => { + Name => 'Wave', + SubDirectory => { TagTable => 'Image::ExifTool::QuickTime::Wave' }, + }, + chan => { + Name => 'AudioChannelLayout', + SubDirectory => { TagTable => 'Image::ExifTool::QuickTime::ChannelLayout' }, + } + # alac - 28 bytes + # adrm - AAX DRM atom? 148 bytes + # aabd - AAX unknown 17kB (contains 'aavd' strings) +); + +# AMR decode config box (ref 3) +%Image::ExifTool::QuickTime::DecodeConfig = ( + PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData, + GROUPS => { 2 => 'Audio' }, + 0 => { + Name => 'EncoderVendor', + Format => 'undef[4]', + }, + 4 => 'EncoderVersion', + # 5 - int16u - packet modes + # 7 - int8u - number of packet mode changes + # 8 - int8u - bytes per packet +); + +%Image::ExifTool::QuickTime::ProtectionInfo = ( + PROCESS_PROC => \&ProcessMOV, + GROUPS => { 2 => 'Audio' }, + NOTES => 'Child atoms found in "sinf" and/or "pinf" atoms.', + frma => 'OriginalFormat', + # imif - IPMP information + schm => { + Name => 'SchemeType', + SubDirectory => { TagTable => 'Image::ExifTool::QuickTime::SchemeType' }, + }, + schi => { + Name => 'SchemeInfo', + SubDirectory => { TagTable => 'Image::ExifTool::QuickTime::SchemeInfo' }, + }, + # skcr + # enda +); + +%Image::ExifTool::QuickTime::Wave = ( + PROCESS_PROC => \&ProcessMOV, + frma => 'PurchaseFileFormat', + # "ms\0\x11" - 20 bytes +); + +# audio channel layout (ref CoreAudioTypes.h) +%Image::ExifTool::QuickTime::ChannelLayout = ( + PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData, + GROUPS => { 2 => 'Audio' }, + DATAMEMBER => [ 0, 8 ], + NOTES => 'Audio channel layout.', + # 0 - version and flags + 4 => { + Name => 'LayoutFlags', + Format => 'int16u', + RawConv => '$$self{LayoutFlags} = $val', + PrintConvColumns => 2, + PrintConv => { + 0 => 'UseDescriptions', + 1 => 'UseBitmap', + 100 => 'Mono', + 101 => 'Stereo', + 102 => 'StereoHeadphones', + 100 => 'Mono', + 101 => 'Stereo', + 102 => 'StereoHeadphones', + 103 => 'MatrixStereo', + 104 => 'MidSide', + 105 => 'XY', + 106 => 'Binaural', + 107 => 'Ambisonic_B_Format', + 108 => 'Quadraphonic', + 109 => 'Pentagonal', + 110 => 'Hexagonal', + 111 => 'Octagonal', + 112 => 'Cube', + 113 => 'MPEG_3_0_A', + 114 => 'MPEG_3_0_B', + 115 => 'MPEG_4_0_A', + 116 => 'MPEG_4_0_B', + 117 => 'MPEG_5_0_A', + 118 => 'MPEG_5_0_B', + 119 => 'MPEG_5_0_C', + 120 => 'MPEG_5_0_D', + 121 => 'MPEG_5_1_A', + 122 => 'MPEG_5_1_B', + 123 => 'MPEG_5_1_C', + 124 => 'MPEG_5_1_D', + 125 => 'MPEG_6_1_A', + 126 => 'MPEG_7_1_A', + 127 => 'MPEG_7_1_B', + 128 => 'MPEG_7_1_C', + 129 => 'Emagic_Default_7_1', + 130 => 'SMPTE_DTV', + 131 => 'ITU_2_1', + 132 => 'ITU_2_2', + 133 => 'DVD_4', + 134 => 'DVD_5', + 135 => 'DVD_6', + 136 => 'DVD_10', + 137 => 'DVD_11', + 138 => 'DVD_18', + 139 => 'AudioUnit_6_0', + 140 => 'AudioUnit_7_0', + 141 => 'AAC_6_0', + 142 => 'AAC_6_1', + 143 => 'AAC_7_0', + 144 => 'AAC_Octagonal', + 145 => 'TMH_10_2_std', + 146 => 'TMH_10_2_full', + 147 => 'DiscreteInOrder', + 148 => 'AudioUnit_7_0_Front', + 149 => 'AC3_1_0_1', + 150 => 'AC3_3_0', + 151 => 'AC3_3_1', + 152 => 'AC3_3_0_1', + 153 => 'AC3_2_1_1', + 154 => 'AC3_3_1_1', + 155 => 'EAC_6_0_A', + 156 => 'EAC_7_0_A', + 157 => 'EAC3_6_1_A', + 158 => 'EAC3_6_1_B', + 159 => 'EAC3_6_1_C', + 160 => 'EAC3_7_1_A', + 161 => 'EAC3_7_1_B', + 162 => 'EAC3_7_1_C', + 163 => 'EAC3_7_1_D', + 164 => 'EAC3_7_1_E', + 165 => 'EAC3_7_1_F', + 166 => 'EAC3_7_1_G', + 167 => 'EAC3_7_1_H', + 168 => 'DTS_3_1', + 169 => 'DTS_4_1', + 170 => 'DTS_6_0_A', + 171 => 'DTS_6_0_B', + 172 => 'DTS_6_0_C', + 173 => 'DTS_6_1_A', + 174 => 'DTS_6_1_B', + 175 => 'DTS_6_1_C', + 176 => 'DTS_7_0', + 177 => 'DTS_7_1', + 178 => 'DTS_8_0_A', + 179 => 'DTS_8_0_B', + 180 => 'DTS_8_1_A', + 181 => 'DTS_8_1_B', + 182 => 'DTS_6_1_D', + 183 => 'AAC_7_1_B', + 0xffff => 'Unknown', + }, + }, + 6 => { + Name => 'AudioChannels', + Condition => '$$self{LayoutFlags} != 0 and $$self{LayoutFlags} != 1', + Format => 'int16u', + }, + 8 => { + Name => 'AudioChannelTypes', + Condition => '$$self{LayoutFlags} == 1', + Format => 'int32u', + PrintConv => { BITMASK => { + 0 => 'Left', + 1 => 'Right', + 2 => 'Center', + 3 => 'LFEScreen', + 4 => 'LeftSurround', + 5 => 'RightSurround', + 6 => 'LeftCenter', + 7 => 'RightCenter', + 8 => 'CenterSurround', + 9 => 'LeftSurroundDirect', + 10 => 'RightSurroundDirect', + 11 => 'TopCenterSurround', + 12 => 'VerticalHeightLeft', + 13 => 'VerticalHeightCenter', + 14 => 'VerticalHeightRight', + 15 => 'TopBackLeft', + 16 => 'TopBackCenter', + 17 => 'TopBackRight', + }}, + }, + 12 => { + Name => 'NumChannelDescriptions', + Condition => '$$self{LayoutFlags} == 1', + Format => 'int32u', + RawConv => '$$self{NumChannelDescriptions} = $val', + }, + 16 => { + Name => 'Channel1Label', + Condition => '$$self{LayoutFlags} == 1 and $$self{NumChannelDescriptions} > 0', + Format => 'int32u', + SeparateTable => 'ChannelLabel', + PrintConv => \%channelLabel, + }, + 20 => { + Name => 'Channel1Flags', + Condition => '$$self{LayoutFlags} == 1 and $$self{NumChannelDescriptions} > 0', + Format => 'int32u', + PrintConv => { BITMASK => { 0 => 'Rectangular', 1 => 'Spherical', 2 => 'Meters' }}, + }, + 24 => { + Name => 'Channel1Coordinates', + Condition => '$$self{LayoutFlags} == 1 and $$self{NumChannelDescriptions} > 0', + Notes => q{ + 3 numbers: for rectangular coordinates left/right, back/front, down/up; for + spherical coordinates left/right degrees, down/up degrees, distance + }, + Format => 'float[3]', + }, + 36 => { + Name => 'Channel2Label', + Condition => '$$self{LayoutFlags} == 1 and $$self{NumChannelDescriptions} > 1', + Format => 'int32u', + SeparateTable => 'ChannelLabel', + PrintConv => \%channelLabel, + }, + 40 => { + Name => 'Channel2Flags', + Condition => '$$self{LayoutFlags} == 1 and $$self{NumChannelDescriptions} > 1', + Format => 'int32u', + PrintConv => { BITMASK => { 0 => 'Rectangular', 1 => 'Spherical', 2 => 'Meters' }}, + }, + 44 => { + Name => 'Channel2Coordinates', + Condition => '$$self{LayoutFlags} == 1 and $$self{NumChannelDescriptions} > 1', + Format => 'float[3]', + }, + 56 => { + Name => 'Channel3Label', + Condition => '$$self{LayoutFlags} == 1 and $$self{NumChannelDescriptions} > 2', + Format => 'int32u', + SeparateTable => 'ChannelLabel', + PrintConv => \%channelLabel, + }, + 60 => { + Name => 'Channel3Flags', + Condition => '$$self{LayoutFlags} == 1 and $$self{NumChannelDescriptions} > 2', + Format => 'int32u', + PrintConv => { BITMASK => { 0 => 'Rectangular', 1 => 'Spherical', 2 => 'Meters' }}, + }, + 64 => { + Name => 'Channel3Coordinates', + Condition => '$$self{LayoutFlags} == 1 and $$self{NumChannelDescriptions} > 2', + Format => 'float[3]', + }, + 76 => { + Name => 'Channel4Label', + Condition => '$$self{LayoutFlags} == 1 and $$self{NumChannelDescriptions} > 3', + Format => 'int32u', + SeparateTable => 'ChannelLabel', + PrintConv => \%channelLabel, + }, + 80 => { + Name => 'Channel4Flags', + Condition => '$$self{LayoutFlags} == 1 and $$self{NumChannelDescriptions} > 3', + Format => 'int32u', + PrintConv => { BITMASK => { 0 => 'Rectangular', 1 => 'Spherical', 2 => 'Meters' }}, + }, + 84 => { + Name => 'Channel4Coordinates', + Condition => '$$self{LayoutFlags} == 1 and $$self{NumChannelDescriptions} > 3', + Format => 'float[3]', + }, + 96 => { + Name => 'Channel5Label', + Condition => '$$self{LayoutFlags} == 1 and $$self{NumChannelDescriptions} > 4', + Format => 'int32u', + SeparateTable => 'ChannelLabel', + PrintConv => \%channelLabel, + }, + 100 => { + Name => 'Channel5Flags', + Condition => '$$self{LayoutFlags} == 1 and $$self{NumChannelDescriptions} > 4', + Format => 'int32u', + PrintConv => { BITMASK => { 0 => 'Rectangular', 1 => 'Spherical', 2 => 'Meters' }}, + }, + 104 => { + Name => 'Channel5Coordinates', + Condition => '$$self{LayoutFlags} == 1 and $$self{NumChannelDescriptions} > 4', + Format => 'float[3]', + }, + 116 => { + Name => 'Channel6Label', + Condition => '$$self{LayoutFlags} == 1 and $$self{NumChannelDescriptions} > 5', + Format => 'int32u', + SeparateTable => 'ChannelLabel', + PrintConv => \%channelLabel, + }, + 120 => { + Name => 'Channel6Flags', + Condition => '$$self{LayoutFlags} == 1 and $$self{NumChannelDescriptions} > 5', + Format => 'int32u', + PrintConv => { BITMASK => { 0 => 'Rectangular', 1 => 'Spherical', 2 => 'Meters' }}, + }, + 124 => { + Name => 'Channel6Coordinates', + Condition => '$$self{LayoutFlags} == 1 and $$self{NumChannelDescriptions} > 5', + Format => 'float[3]', + }, + 136 => { + Name => 'Channel7Label', + Condition => '$$self{LayoutFlags} == 1 and $$self{NumChannelDescriptions} > 6', + Format => 'int32u', + SeparateTable => 'ChannelLabel', + PrintConv => \%channelLabel, + }, + 140 => { + Name => 'Channel7Flags', + Condition => '$$self{LayoutFlags} == 1 and $$self{NumChannelDescriptions} > 6', + Format => 'int32u', + PrintConv => { BITMASK => { 0 => 'Rectangular', 1 => 'Spherical', 2 => 'Meters' }}, + }, + 144 => { + Name => 'Channel7Coordinates', + Condition => '$$self{LayoutFlags} == 1 and $$self{NumChannelDescriptions} > 6', + Format => 'float[3]', + }, + 156 => { + Name => 'Channel8Label', + Condition => '$$self{LayoutFlags} == 1 and $$self{NumChannelDescriptions} > 7', + Format => 'int32u', + SeparateTable => 'ChannelLabel', + PrintConv => \%channelLabel, + }, + 160 => { + Name => 'Channel8Flags', + Condition => '$$self{LayoutFlags} == 1 and $$self{NumChannelDescriptions} > 7', + Format => 'int32u', + PrintConv => { BITMASK => { 0 => 'Rectangular', 1 => 'Spherical', 2 => 'Meters' }}, + }, + 164 => { + Name => 'Channel8Coordinates', + Condition => '$$self{LayoutFlags} == 1 and $$self{NumChannelDescriptions} > 7', + Format => 'float[3]', + }, + # (arbitrarily decode only first 8 channels) +); + +# scheme type atom +# ref http://xhelmboyx.tripod.com/formats/mp4-layout.txt +%Image::ExifTool::QuickTime::SchemeType = ( + PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData, + GROUPS => { 2 => 'Audio' }, + # 0 - 4 bytes version + 4 => { Name => 'SchemeType', Format => 'undef[4]' }, + 8 => { Name => 'SchemeVersion', Format => 'int16u' }, + 10 => { Name => 'SchemeURL', Format => 'string[$size-10]' }, +); + +%Image::ExifTool::QuickTime::SchemeInfo = ( + PROCESS_PROC => \&ProcessMOV, + GROUPS => { 2 => 'Audio' }, + user => { + Name => 'UserID', + Groups => { 2 => 'Author' }, + ValueConv => '"0x" . unpack("H*",$val)', + }, + cert => { # ref http://www.onvif.org/specs/stream/ONVIF-ExportFileFormat-Spec-v100.pdf + Name => 'Certificate', + ValueConv => '"0x" . unpack("H*",$val)', + }, + 'key ' => { + Name => 'KeyID', + ValueConv => '"0x" . unpack("H*",$val)', + }, + iviv => { + Name => 'InitializationVector', + ValueConv => 'unpack("H*",$val)', + }, + righ => { + Name => 'Rights', + Groups => { 2 => 'Author' }, + SubDirectory => { TagTable => 'Image::ExifTool::QuickTime::Rights' }, + }, + name => { Name => 'UserName', Groups => { 2 => 'Author' } }, + # chtb + # priv - private data + # sign + # adkm - Adobe DRM key management system (ref http://download.macromedia.com/f4v/video_file_format_spec_v10_1.pdf) + # iKMS + # iSFM + # iSLT +); + +%Image::ExifTool::QuickTime::Rights = ( + PROCESS_PROC => \&ProcessRights, + GROUPS => { 2 => 'Audio' }, + veID => 'ItemVendorID', #PH ("VendorID" ref 19) + plat => 'Platform', #18? + aver => 'VersionRestrictions', #19 ("appversion?" ref 18) + tran => 'TransactionID', #18 + song => 'ItemID', #19 ("appid" ref 18) + tool => { + Name => 'ItemTool', #PH (guess) ("itunes build?" ref 18) + Format => 'string', + }, + medi => 'MediaFlags', #PH (?) + mode => 'ModeFlags', #PH (?) 0x04 is HD flag (https://compilr.com/heksesang/requiem-mac/UnDrm.java) +); + +# MP4 hint sample description box (ref 5) +# (ref https://developer.apple.com/library/mac/documentation/QuickTime/QTFF/QTFFChap3/qtff3.html#//apple_ref/doc/uid/TP40000939-CH205-SW1) +%Image::ExifTool::QuickTime::HintSampleDesc = ( + PROCESS_PROC => \&ProcessHybrid, + VARS => { ID_LABEL => 'ID/Index' }, + NOTES => 'MP4 hint sample description.', + 4 => { Name => 'HintFormat', Format => 'undef[4]' }, + # 14 - int16u DataReferenceIndex + 16 => { Name => 'HintTrackVersion', Format => 'int16u' }, + # 18 - int16u LastCompatibleHintTrackVersion + 20 => { Name => 'MaxPacketSize', Format => 'int32u' }, +# +# Observed offsets for child atoms of various HintFormat types: +# +# HintFormat Offset Child atoms +# ----------- ------ ---------------- +# "rtp " 24 tims +# + tims => { Name => 'RTPTimeScale', Format => 'int32u' }, + tsro => { Name => 'TimestampRandomOffset', Format => 'int32u' }, + snro => { Name => 'SequenceNumberRandomOffset', Format => 'int32u' }, +); + +# MP4 metadata sample description box +%Image::ExifTool::QuickTime::MetaSampleDesc = ( + PROCESS_PROC => \&ProcessHybrid, + NOTES => 'MP4 metadata sample description.', + 4 => { + Name => 'MetaFormat', + Format => 'undef[4]', + RawConv => '$$self{MetaFormat} = $val', + }, +# +# Observed offsets for child atoms of various MetaFormat types: +# +# MetaFormat Offset Child atoms +# ----------- ------ ---------------- +# mebx 24 keys,btrt,lidp,lidl +# fdsc - - +# gpmd - - +# rtmd - - +# CTMD - - +# + 'keys' => { #PH (iPhone7+ hevc) + Name => 'Keys', + SubDirectory => { + TagTable => 'Image::ExifTool::QuickTime::Keys', + ProcessProc => \&ProcessMetaKeys, + }, + }, + btrt => { + Name => 'BitrateInfo', + SubDirectory => { TagTable => 'Image::ExifTool::QuickTime::Bitrate' }, + }, +); + +# MP4 generic sample description box +%Image::ExifTool::QuickTime::OtherSampleDesc = ( + PROCESS_PROC => \&ProcessHybrid, + 4 => { + Name => 'OtherFormat', + Format => 'undef[4]', + RawConv => '$$self{MetaFormat} = $val', # (yes, use MetaFormat for this too) + }, +# +# Observed offsets for child atoms of various OtherFormat types: +# +# OtherFormat Offset Child atoms +# ----------- ------ ---------------- +# avc1 86 avcC +# mp4a 36 esds +# mp4s 16 esds +# tmcd 34 name +# data - - +# + ftab => { Name => 'FontTable', Format => 'undef', ValueConv => 'substr($val, 5)' }, +); + +# MP4 data information box (ref 5) +%Image::ExifTool::QuickTime::DataInfo = ( + PROCESS_PROC => \&ProcessMOV, + NOTES => 'MP4 data information box.', + dref => { + Name => 'DataRef', + SubDirectory => { + TagTable => 'Image::ExifTool::QuickTime::DataRef', + Start => 8, + }, + }, +); + +# Generic media header +%Image::ExifTool::QuickTime::GenMediaHeader = ( + PROCESS_PROC => \&ProcessMOV, + gmin => { + Name => 'GenMediaInfo', + SubDirectory => { TagTable => 'Image::ExifTool::QuickTime::GenMediaInfo' }, + }, + text => { + Name => 'Text', + Flags => ['Binary','Unknown'], + }, + tmcd => { + Name => 'TimeCode', + SubDirectory => { TagTable => 'Image::ExifTool::QuickTime::TimeCode' }, + }, +); + +# TimeCode header +%Image::ExifTool::QuickTime::TimeCode = ( + PROCESS_PROC => \&ProcessMOV, + tcmi => { + Name => 'TCMediaInfo', + SubDirectory => { TagTable => 'Image::ExifTool::QuickTime::TCMediaInfo' }, + }, +); + +# TimeCode media info (ref 12) +%Image::ExifTool::QuickTime::TCMediaInfo = ( + PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData, + GROUPS => { 2 => 'Video' }, + 4 => { + Name => 'TextFont', + Format => 'int16u', + PrintConv => { 0 => 'System' }, + }, + 6 => { + Name => 'TextFace', + Format => 'int16u', + PrintConv => { + 0 => 'Plain', + BITMASK => { + 0 => 'Bold', + 1 => 'Italic', + 2 => 'Underline', + 3 => 'Outline', + 4 => 'Shadow', + 5 => 'Condense', + 6 => 'Extend', + }, + }, + }, + 8 => { + Name => 'TextSize', + Format => 'int16u', + }, + # 10 - reserved + 12 => { + Name => 'TextColor', + Format => 'int16u[3]', + }, + 18 => { + Name => 'BackgroundColor', + Format => 'int16u[3]', + }, + 24 => { + Name => 'FontName', + Format => 'pstring', + ValueConv => '$self->Decode($val, $self->Options("CharsetQuickTime"))', + }, +); + +# Generic media info (ref http://sourceforge.jp/cvs/view/ntvrec/ntvrec/libqtime/gmin.h?view=co) +%Image::ExifTool::QuickTime::GenMediaInfo = ( + PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData, + GROUPS => { 2 => 'Video' }, + 0 => 'GenMediaVersion', + 1 => { Name => 'GenFlags', Format => 'int8u[3]' }, + 4 => { Name => 'GenGraphicsMode', + Format => 'int16u', + PrintHex => 1, + SeparateTable => 'GraphicsMode', + PrintConv => \%graphicsMode, + }, + 6 => { Name => 'GenOpColor', Format => 'int16u[3]' }, + 12 => { Name => 'GenBalance', Format => 'fixed16s' }, +); + +# MP4 data reference box (ref 5) +%Image::ExifTool::QuickTime::DataRef = ( + PROCESS_PROC => \&ProcessMOV, + NOTES => 'MP4 data reference box.', + 'url ' => { + Name => 'URL', + Format => 'undef', # (necessary to prevent decoding as string!) + RawConv => q{ + # ignore if self-contained (flags bit 0 set) + return undef if unpack("N",$val) & 0x01; + $_ = substr($val,4); s/\0.*//s; $_; + }, + }, + "url\0" => { # (written by GoPro) + Name => 'URL', + Format => 'undef', # (necessary to prevent decoding as string!) + RawConv => q{ + # ignore if self-contained (flags bit 0 set) + return undef if unpack("N",$val) & 0x01; + $_ = substr($val,4); s/\0.*//s; $_; + }, + }, + 'urn ' => { + Name => 'URN', + Format => 'undef', # (necessary to prevent decoding as string!) + RawConv => q{ + return undef if unpack("N",$val) & 0x01; + $_ = substr($val,4); s/\0+/; /; s/\0.*//s; $_; + }, + }, +); + +# MP4 handler box (ref 5) +%Image::ExifTool::QuickTime::Handler = ( + PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData, + GROUPS => { 2 => 'Video' }, + 4 => { #PH + Name => 'HandlerClass', + Format => 'undef[4]', + RawConv => '$val eq "\0\0\0\0" ? undef : $val', + PrintConv => { + mhlr => 'Media Handler', + dhlr => 'Data Handler', + }, + }, + 8 => { + Name => 'HandlerType', + Format => 'undef[4]', + RawConv => '$$self{HandlerType} = $val unless $val eq "alis" or $val eq "url "; $val', + PrintConvColumns => 2, + PrintConv => { + alis => 'Alias Data', #PH + crsm => 'Clock Reference', #3 + hint => 'Hint Track', + ipsm => 'IPMP', #3 + m7sm => 'MPEG-7 Stream', #3 + meta => 'NRT Metadata', #PH + mdir => 'Metadata', #3 + mdta => 'Metadata Tags', #PH + mjsm => 'MPEG-J', #3 + ocsm => 'Object Content', #3 + odsm => 'Object Descriptor', #3 + priv => 'Private', #PH + sdsm => 'Scene Description', #3 + soun => 'Audio Track', + text => 'Text', #PH (but what type? subtitle?) + tmcd => 'Time Code', #PH + 'url '=> 'URL', #3 + vide => 'Video Track', + subp => 'Subpicture', #http://www.google.nl/patents/US7778526 + nrtm => 'Non-Real Time Metadata', #PH (Sony ILCE-7S) [how is this different from "meta"?] + pict => 'Picture', # (HEIC images) + camm => 'Camera Metadata', # (Insta360 MP4) + psmd => 'Panasonic Static Metadata', #PH (Leica C-Lux CAM-DC25) + }, + }, + 12 => { #PH + Name => 'HandlerVendorID', + Format => 'undef[4]', + RawConv => '$val eq "\0\0\0\0" ? undef : $val', + PrintConv => \%vendorID, + SeparateTable => 'VendorID', + }, + 24 => { + Name => 'HandlerDescription', + Format => 'string', + # (sometimes this is a Pascal string, and sometimes it is a C string) + RawConv => q{ + $val=substr($val,1,ord($1)) if $val=~/^([\0-\x1f])/ and ord($1)<length($val); + length $val ? $val : undef; + }, + }, +); + +# Flip uuid data (ref PH) +%Image::ExifTool::QuickTime::Flip = ( + PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData, + FORMAT => 'int32u', + FIRST_ENTRY => 0, + NOTES => 'Found in MP4 files from Flip Video cameras.', + GROUPS => { 1 => 'MakerNotes', 2 => 'Image' }, + 1 => 'PreviewImageWidth', + 2 => 'PreviewImageHeight', + 13 => 'PreviewImageLength', + 14 => { # (confirmed for FlipVideoMinoHD) + Name => 'SerialNumber', + Groups => { 2 => 'Camera' }, + Format => 'string[16]', + }, + 28 => { + Name => 'PreviewImage', + Groups => { 2 => 'Preview' }, + Format => 'undef[$val{13}]', + RawConv => '$self->ValidateImage(\$val, $tag)', + }, +); + +# QuickTime composite tags +%Image::ExifTool::QuickTime::Composite = ( + GROUPS => { 2 => 'Video' }, + Rotation => { + Notes => q{ + writing this tag updates QuickTime MatrixStructure for all tracks with a + non-zero image size + }, + Require => { + 0 => 'QuickTime:MatrixStructure', + 1 => 'QuickTime:HandlerType', + }, + Writable => 1, + WriteAlso => { + MatrixStructure => 'Image::ExifTool::QuickTime::GetRotationMatrix($val)', + }, + ValueConv => 'Image::ExifTool::QuickTime::CalcRotation($self)', + ValueConvInv => '$val', + }, + AvgBitrate => { + Priority => 0, # let QuickTime::AvgBitrate take priority + Require => { + 0 => 'QuickTime::MovieDataSize', + 1 => 'QuickTime::Duration', + }, + RawConv => q{ + return undef unless $val[1]; + $val[1] /= $$self{TimeScale} if $$self{TimeScale}; + my $key = 'MovieDataSize'; + my $size = $val[0]; + for (;;) { + $key = $self->NextTagKey($key) or last; + $size += $self->GetValue($key, 'ValueConv'); + } + return int($size * 8 / $val[1] + 0.5); + }, + PrintConv => 'ConvertBitrate($val)', + }, + GPSLatitude => { + Require => 'QuickTime:GPSCoordinates', + Groups => { 2 => 'Location' }, + ValueConv => 'my @c = split " ", $val; $c[0]', + PrintConv => 'Image::ExifTool::GPS::ToDMS($self, $val, 1, "N")', + }, + GPSLongitude => { + Require => 'QuickTime:GPSCoordinates', + Groups => { 2 => 'Location' }, + ValueConv => 'my @c = split " ", $val; $c[1]', + PrintConv => 'Image::ExifTool::GPS::ToDMS($self, $val, 1, "E")', + }, + # split altitude into GPSAltitude/GPSAltitudeRef like EXIF and XMP + GPSAltitude => { + Require => 'QuickTime:GPSCoordinates', + Groups => { 2 => 'Location' }, + Priority => 0, # (because it may not exist) + ValueConv => 'my @c = split " ", $val; defined $c[2] ? abs($c[2]) : undef', + PrintConv => '"$val m"', + }, + GPSAltitudeRef => { + Require => 'QuickTime:GPSCoordinates', + Groups => { 2 => 'Location' }, + Priority => 0, # (because altitude information may not exist) + ValueConv => 'my @c = split " ", $val; defined $c[2] ? ($c[2] < 0 ? 1 : 0) : undef', + PrintConv => { + 0 => 'Above Sea Level', + 1 => 'Below Sea Level', + }, + }, + GPSLatitude2 => { + Name => 'GPSLatitude', + Require => 'QuickTime:LocationInformation', + Groups => { 2 => 'Location' }, + ValueConv => '$val =~ /Lat=([-+.\d]+)/; $1', + PrintConv => 'Image::ExifTool::GPS::ToDMS($self, $val, 1, "N")', + }, + GPSLongitude2 => { + Name => 'GPSLongitude', + Require => 'QuickTime:LocationInformation', + Groups => { 2 => 'Location' }, + ValueConv => '$val =~ /Lon=([-+.\d]+)/; $1', + PrintConv => 'Image::ExifTool::GPS::ToDMS($self, $val, 1, "E")', + }, + GPSAltitude2 => { + Name => 'GPSAltitude', + Require => 'QuickTime:LocationInformation', + Groups => { 2 => 'Location' }, + ValueConv => '$val =~ /Alt=([-+.\d]+)/; abs($1)', + PrintConv => '"$val m"', + }, + GPSAltitudeRef2 => { + Name => 'GPSAltitudeRef', + Require => 'QuickTime:LocationInformation', + Groups => { 2 => 'Location' }, + ValueConv => '$val =~ /Alt=([-+.\d]+)/; $1 < 0 ? 1 : 0', + PrintConv => { + 0 => 'Above Sea Level', + 1 => 'Below Sea Level', + }, + }, + CDDBDiscPlayTime => { + Require => 'CDDB1Info', + Groups => { 2 => 'Audio' }, + ValueConv => '$val =~ /^..([a-z0-9]{4})/i ? hex($1) : undef', + PrintConv => 'ConvertDuration($val)', + }, + CDDBDiscTracks => { + Require => 'CDDB1Info', + Groups => { 2 => 'Audio' }, + ValueConv => '$val =~ /^.{6}([a-z0-9]{2})/i ? hex($1) : undef', + }, +); + +# add our composite tags +Image::ExifTool::AddCompositeTags('Image::ExifTool::QuickTime'); + + +#------------------------------------------------------------------------------ +# AutoLoad our routines when necessary +# +sub AUTOLOAD +{ + if ($AUTOLOAD eq 'Image::ExifTool::QuickTime::Process_mebx' or + $AUTOLOAD eq 'Image::ExifTool::QuickTime::ProcessTTAD') + { + require 'Image/ExifTool/QuickTimeStream.pl'; + no strict 'refs'; + return &$AUTOLOAD(@_); + } else { + return Image::ExifTool::DoAutoLoad($AUTOLOAD, @_); + } +} + +#------------------------------------------------------------------------------ +# Get rotation matrix +# Inputs: 0) angle in degrees +# Returns: 9-element rotation matrix as a string (with 0 x/y offsets) +sub GetRotationMatrix($) +{ + my $ang = 3.1415926536 * shift() / 180; + my $cos = cos $ang; + my $sin = sin $ang; + my $msn = -$sin; + return "$cos $sin 0 $msn $cos 0 0 0 1"; +} + +#------------------------------------------------------------------------------ +# Get rotation angle from a matrix +# Inputs: 0) rotation matrix as a string +# Return: positive rotation angle in degrees rounded to 3 decimal points, +# or undef on error +sub GetRotationAngle($) +{ + my $rotMatrix = shift; + my @a = split ' ', $rotMatrix; + return undef if $a[0]==0 and $a[1]==0; + # calculate the rotation angle (assume uniform rotation) + my $angle = atan2($a[1], $a[0]) * 180 / 3.14159; + $angle += 360 if $angle < 0; + return int($angle * 1000 + 0.5) / 1000; +} + +#------------------------------------------------------------------------------ +# Calculate rotation of video track +# Inputs: 0) ExifTool object ref +# Returns: rotation angle or undef +sub CalcRotation($) +{ + my $et = shift; + my $value = $$et{VALUE}; + my ($i, $track); + # get the video track family 1 group (eg. "Track1"); + for ($i=0; ; ++$i) { + my $idx = $i ? " ($i)" : ''; + my $tag = "HandlerType$idx"; + last unless $$value{$tag}; + next unless $$value{$tag} eq 'vide'; + $track = $et->GetGroup($tag, 1); + last; + } + return undef unless $track; + # get the video track matrix + for ($i=0; ; ++$i) { + my $idx = $i ? " ($i)" : ''; + my $tag = "MatrixStructure$idx"; + last unless $$value{$tag}; + next unless $et->GetGroup($tag, 1) eq $track; + return GetRotationAngle($$value{$tag}); + } + return undef; +} + +#------------------------------------------------------------------------------ +# Get MatrixStructure for a given rotation angle +# Inputs: 0) rotation angle (deg), 1) ExifTool ref +# Returns: matrix structure as a string, or undef if it can't be rotated +# - requires ImageSizeLookahead to determine the video image size, and doesn't +# rotate matrix unless image size is valid +sub GetMatrixStructure($$) +{ + my ($val, $et) = @_; + my @a = split ' ', $val; + # pass straight through if it already has an offset + return $val unless $a[6] == 0 and $a[7] == 0; + my @s = split ' ', $$et{ImageSizeLookahead}; + my ($w, $h) = @s[12,13]; + return undef unless $w and $h; # don't rotate 0-sized track + $_ = Image::ExifTool::QuickTime::FixWrongFormat($_) foreach $w,$h; + # apply necessary offsets for the standard rotations + my $angle = GetRotationAngle($val); + return undef unless defined $angle; + if ($angle == 90) { + @a[6,7] = ($h, 0); + } elsif ($angle == 180) { + @a[6,7] = ($w, $h); + } elsif ($angle == 270) { + @a[6,7] = (0, $w); + } + return "@a"; +} + +#------------------------------------------------------------------------------ +# Determine the average sample rate from a time-to-sample table +# Inputs: 0) ExifTool object ref, 1) time-to-sample table data ref +# Returns: average sample rate (in Hz) +sub CalcSampleRate($$) +{ + my ($et, $valPt) = @_; + my @dat = unpack('N*', $$valPt); + my ($num, $dur) = (0, 0); + my $i; + for ($i=2; $i<@dat-1; $i+=2) { + $num += $dat[$i]; # total number of samples + $dur += $dat[$i] * $dat[$i+1]; # total sample duration + } + return undef unless $num and $dur and $$et{MediaTS}; + return $num * $$et{MediaTS} / $dur; +} + +#------------------------------------------------------------------------------ +# Fix incorrect format for ImageWidth/Height as written by Pentax +sub FixWrongFormat($) +{ + my $val = shift; + return undef unless $val; + return $val & 0xfff00000 ? unpack('n',pack('N',$val)) : $val; +} + +#------------------------------------------------------------------------------ +# Convert ISO 6709 string to standard lag/lon format +# Inputs: 0) ISO 6709 string (lat, lon, and optional alt) +# Returns: position in decimal degress with altitude if available +# Notes: Wikipedia indicates altitude may be in feet -- how is this specified? +sub ConvertISO6709($) +{ + my $val = shift; + if ($val =~ /^([-+]\d{1,2}(?:\.\d*)?)([-+]\d{1,3}(?:\.\d*)?)([-+]\d+(?:\.\d*)?)?/) { + # +DD.DDD+DDD.DDD+AA.AAA + $val = ($1 + 0) . ' ' . ($2 + 0); + $val .= ' ' . ($3 + 0) if $3; + } elsif ($val =~ /^([-+])(\d{2})(\d{2}(?:\.\d*)?)([-+])(\d{3})(\d{2}(?:\.\d*)?)([-+]\d+(?:\.\d*)?)?/) { + # +DDMM.MMM+DDDMM.MMM+AA.AAA + my $lat = $2 + $3 / 60; + $lat = -$lat if $1 eq '-'; + my $lon = $5 + $6 / 60; + $lon = -$lon if $4 eq '-'; + $val = "$lat $lon"; + $val .= ' ' . ($7 + 0) if $7; + } elsif ($val =~ /^([-+])(\d{2})(\d{2})(\d{2}(?:\.\d*)?)([-+])(\d{3})(\d{2})(\d{2}(?:\.\d*)?)([-+]\d+(?:\.\d*)?)?/) { + # +DDMMSS.SSS+DDDMMSS.SSS+AA.AAA + my $lat = $2 + $3 / 60 + $4 / 3600; + $lat = -$lat if $1 eq '-'; + my $lon = $6 + $7 / 60 + $8 / 3600; + $lon = -$lon if $5 eq '-'; + $val = "$lat $lon"; + $val .= ' ' . ($9 + 0) if $9; + } + return $val; +} + +#------------------------------------------------------------------------------ +# Convert Nero chapter list (ref ffmpeg libavformat/movenc.c) +# Inputs: 0) binary chpl data +# Returns: chapter list +sub ConvertChapterList($) +{ + my $val = shift; + my $size = length $val; + return '<invalid>' if $size < 9; + my $num = Get8u(\$val, 8); + my ($i, @chapters); + my $pos = 9; + for ($i=0; $i<$num; ++$i) { + last if $pos + 9 > $size; + my $dur = Get64u(\$val, $pos) / 10000000; + my $len = Get8u(\$val, $pos + 8); + last if $pos + 9 + $len > $size; + my $title = substr($val, $pos + 9, $len); + $pos += 9 + $len; + push @chapters, "$dur $title"; + } + return \@chapters; # return as a list +} + +#------------------------------------------------------------------------------ +# Print conversion for a Nero chapter list item +# Inputs: 0) ValueConv chapter string +# Returns: formatted chapter string +sub PrintChapter($) +{ + my $val = shift; + $val =~ /^(\S+) (.*)/ or return $val; + my ($dur, $title) = ($1, $2); + my $h = int($dur / 3600); + $dur -= $h * 3600; + my $m = int($dur / 60); + my $s = $dur - $m * 60; + my $ss = sprintf('%06.3f', $s); + if ($ss >= 60) { + $ss = '00.000'; + ++$m >= 60 and $m -= 60, ++$h; + } + return sprintf("[%d:%.2d:%s] %s",$h,$m,$ss,$title); +} + +#------------------------------------------------------------------------------ +# Format GPSCoordinates for printing +# Inputs: 0) string with numerical lat, lon and optional alt, separated by spaces +# 1) ExifTool object reference +# Returns: PrintConv value +sub PrintGPSCoordinates($) +{ + my ($val, $et) = @_; + my @v = split ' ', $val; + my $prt = Image::ExifTool::GPS::ToDMS($et, $v[0], 1, "N") . ', ' . + Image::ExifTool::GPS::ToDMS($et, $v[1], 1, "E"); + if (defined $v[2]) { + $prt .= ', ' . ($v[2] < 0 ? -$v[2] . ' m Below' : $v[2] . ' m Above') . ' Sea Level'; + } + return $prt; +} + +#------------------------------------------------------------------------------ +# Unpack packed ISO 639/T language code +# Inputs: 0) packed language code (or undef) +# Returns: language code, or undef for default language, or 'err' for format error +sub UnpackLang($) +{ + my $lang = shift; + if ($lang) { + # language code is packed in 5-bit characters + $lang = pack "C*", map { (($lang>>$_)&0x1f)+0x60 } 10, 5, 0; + # validate language code + if ($lang =~ /^[a-z]+$/) { + # treat 'eng' or 'und' as the default language + undef $lang if $lang eq 'und' or $lang eq 'eng'; + } else { + $lang = 'err'; # invalid language code + } + } + return $lang; +} + +#------------------------------------------------------------------------------ +# Get langInfo hash and save details about alt-lang tags +# Inputs: 0) ExifTool ref, 1) tagInfo hash ref, 2) locale code +# Returns: new tagInfo hash ref, or undef if invalid +sub GetLangInfoQT($$$) +{ + my ($et, $tagInfo, $langCode) = @_; + my $langInfo = Image::ExifTool::GetLangInfo($tagInfo, $langCode); + if ($langInfo) { + $$et{QTLang} or $$et{QTLang} = [ ]; + push @{$$et{QTLang}}, $$langInfo{Name}; + } + return $langInfo; +} + +#------------------------------------------------------------------------------ +# Get variable-length integer from data (used by ParseItemLocation) +# Inputs: 0) data ref, 1) start position, 2) integer size in bytes (0, 4 or 8), +# 3) default value +# Returns: integer value, and updates current position +sub GetVarInt($$$;$) +{ + my ($dataPt, $pos, $n, $default) = @_; + my $len = length $$dataPt; + $_[1] = $pos + $n; # update current position + return undef if $pos + $n > $len; + if ($n == 0) { + return $default || 0; + } elsif ($n == 4) { + return Get32u($dataPt, $pos); + } elsif ($n == 8) { + return Get64u($dataPt, $pos); + } + return undef; +} + +#------------------------------------------------------------------------------ +# Get null-terminated string from binary data (used by ParseItemInfoEntry) +# Inputs: 0) data ref, 1) start position +# Returns: string, and updates current position +sub GetString($$) +{ + my ($dataPt, $pos) = @_; + my $len = length $$dataPt; + my $str = ''; + while ($pos < $len) { + my $ch = substr($$dataPt, $pos, 1); + ++$pos; + last if ord($ch) == 0; + $str .= $ch; + } + $_[1] = $pos; # update current position + return $str; +} + +#------------------------------------------------------------------------------ +# Get a printable version of the tag ID +# Inputs: 0) tag ID, 1) Flag: 1=print as 4- or 8-digit hex value if necessary +# Returns: Printable tag ID +sub PrintableTagID($;$) +{ + my $tag = $_[0]; + my $n = ($tag =~ s/([\x00-\x1f\x7f-\xff])/'x'.unpack('H*',$1)/eg); + if ($n > 2 and $_[1]) { + $tag = '0x' . unpack('H8', $_[0]); + $tag =~ s/^0x0000/0x/; + } + return $tag; +} + +#============================================================================== +# The following ParseXxx routines parse various boxes to extract this +# information about embedded items in a $$et{ItemInfo} hash, keyed by item ID: +# +# iloc: +# ConstructionMethod - offset type: 0=file, 1=idat, 2=item +# DataReferenceIndex - 0 for "this file", otherwise index in dref box +# BaseOffset - base for file offsets +# Extents - list of index,offset,length details for data in file +# infe: +# ProtectionIndex - index if item is protected (0 for unprotected) +# Name - item name +# ContentType - mime type of item +# ContentEncoding - item encoding +# URI - URI of a 'uri '-type item +# ipma: +# Association - list of associated properties in the ipco container +# Essential - list of "essential" flags for the associated properties +# cdsc: +# RefersTo - hash lookup of flags based on referred item ID +# other: +# DocNum - exiftool document number for this item +# +#------------------------------------------------------------------------------ +# Parse item location (iloc) box (ref ISO 14496-12:2015 pg.79) +# Inputs: 0) iloc data, 1) ExifTool ref +# Returns: undef, and fills in ExifTool ItemInfo hash +sub ParseItemLocation($$) +{ + my ($val, $et) = @_; + my ($i, $j, $num, $pos, $id); + my ($extent_index, $extent_offset, $extent_length); + + my $items = $$et{ItemInfo} || ($$et{ItemInfo} = { }); + my $len = length $val; + return undef if $len < 8; + my $ver = Get8u(\$val, 0); + my $siz = Get16u(\$val, 4); + my $noff = ($siz >> 12); + my $nlen = ($siz >> 8) & 0x0f; + my $nbas = ($siz >> 4) & 0x0f; + my $nind = $siz & 0x0f; + if ($ver < 2) { + $num = Get16u(\$val, 6); + $pos = 8; + } else { + return undef if $len < 10; + $num = Get32u(\$val, 6); + $pos = 10; + } + for ($i=0; $i<$num; ++$i) { + if ($ver < 2) { + return undef if $pos + 2 > $len; + $id = Get16u(\$val, $pos); + $pos += 2; + } else { + return undef if $pos + 4 > $len; + $id = Get32u(\$val, $pos); + $pos += 4; + } + if ($ver == 1 or $ver == 2) { + return undef if $pos + 2 > $len; + $$items{$id}{ConstructionMethod} = Get16u(\$val, $pos) & 0x0f; + $pos += 2; + } + return undef if $pos + 2 > $len; + $$items{$id}{DataReferenceIndex} = Get16u(\$val, $pos); + $pos += 2; + $$items{$id}{BaseOffset} = GetVarInt(\$val, $pos, $nbas); + return undef if $pos + 2 > $len; + my $ext_num = Get16u(\$val, $pos); + $pos += 2; + my @extents; + for ($j=0; $j<$ext_num; ++$j) { + if ($ver == 1 or $ver == 2) { + $extent_index = GetVarInt(\$val, $pos, $nind, 1); + } + $extent_offset = GetVarInt(\$val, $pos, $noff); + $extent_length = GetVarInt(\$val, $pos, $nlen); + return undef unless defined $extent_length; + push @extents, [ $extent_index, $extent_offset, $extent_length ]; + } + # save item location information keyed on 1-based item ID: + $$items{$id}{Extents} = \@extents; + } + return undef; +} + +#------------------------------------------------------------------------------ +# Parse item information entry (infe) box (ref ISO 14496-12:2015 pg.82) +# Inputs: 0) infe data, 1) ExifTool ref +# Returns: undef, and fills in ExifTool ItemInfo hash +sub ParseItemInfoEntry($$) +{ + my ($val, $et) = @_; + my $id; + + my $verbose = $et->Options('Verbose'); + my $items = $$et{ItemInfo} || ($$et{ItemInfo} = { }); + my $len = length $val; + return undef if $len < 4; + my $ver = Get8u(\$val, 0); + my $pos = 4; + return undef if $pos + 4 > $len; + if ($ver == 0 or $ver == 1) { + $id = Get16u(\$val, $pos); + $$items{$id}{ProtectionIndex} = Get16u(\$val, $pos + 2); + $pos += 4; + $$items{$id}{Name} = GetString(\$val, $pos); + $$items{$id}{ContentType} = GetString(\$val, $pos); + $$items{$id}{ContentEncoding} = GetString(\$val, $pos); + } else { + if ($ver == 2) { + $id = Get16u(\$val, $pos); + $pos += 2; + } elsif ($ver == 3) { + $id = Get32u(\$val, $pos); + $pos += 4; + } + return undef if $pos + 6 > $len; + $$items{$id}{ProtectionIndex} = Get16u(\$val, $pos); + my $type = substr($val, $pos + 2, 4); + $$items{$id}{Type} = $type; + $pos += 6; + $$items{$id}{Name} = GetString(\$val, $pos); + if ($type eq 'mime') { + $$items{$id}{ContentType} = GetString(\$val, $pos); + $$items{$id}{ContentEncoding} = GetString(\$val, $pos); + } elsif ($type eq 'uri ') { + $$items{$id}{URI} = GetString(\$val, $pos); + } + } + $et->VPrint(1, "$$et{INDENT} Item $id: Type=", $$items{$id}{Type} || '', + ' Name=', $$items{$id}{Name} || '', + ' ContentType=', $$items{$id}{ContentType} || '', + "\n") if $verbose > 1; + return undef; +} + +#------------------------------------------------------------------------------ +# Parse item property association (ipma) box (ref https://github.com/gpac/gpac/blob/master/src/isomedia/iff.c) +# Inputs: 0) infe data, 1) ExifTool ref +# Returns: undef, and fills in ExifTool ItemInfo hash +# Note: this information is currently not used by ExifTool (must figure out how to do this) +sub ParseItemPropAssoc($$) +{ + my ($val, $et) = @_; + my ($i, $j, $id); + + my $verbose = $et->Options('Verbose'); + my $items = $$et{ItemInfo} || ($$et{ItemInfo} = { }); + my $len = length $val; + return undef if $len < 8; + my $ver = Get8u(\$val, 0); + my $flg = Get32u(\$val, 0); + my $num = Get32u(\$val, 4); + my $pos = 8; + for ($i=0; $i<$num; ++$i) { + if ($ver == 0) { + return undef if $pos + 3 > $len; + $id = Get16u(\$val, $pos); + $pos += 2; + } else { + return undef if $pos + 5 > $len; + $id = Get32u(\$val, $pos); + $pos += 4; + } + my $n = Get8u(\$val, $pos++); + my (@association, @essential); + if ($flg & 0x01) { + return undef if $pos + $n * 2 > $len; + for ($j=0; $j<$n; ++$j) { + my $tmp = Get16u(\$val, $pos + $j * 2); + push @association, $tmp & 0x7fff; + push @essential, ($tmp & 0x8000) ? 1 : 0; + } + $pos += $n * 2; + } else { + return undef if $pos + $n > $len; + for ($j=0; $j<$n; ++$j) { + my $tmp = Get8u(\$val, $pos + $j); + push @association, $tmp & 0x7f; + push @essential, ($tmp & 0x80) ? 1 : 0; + } + $pos += $n; + } + $$items{$id}{Association} = \@association; + $$items{$id}{Essential} = \@essential; + $et->VPrint(1, "$$et{INDENT} Item $id properties: @association\n") if $verbose > 1; + } + return undef; +} + +#------------------------------------------------------------------------------ +# Process item information now +# Inputs: 0) ExifTool ref, 1) RAF ref +sub HandleItemInfo($$) +{ + my ($et, $raf) = @_; + my $items = $$et{ItemInfo}; + my $buff; + + # extract information from EXIF/XMP metadata items + if ($items and $raf) { + my $curPos = $raf->Tell(); + my $primary = $$et{PrimaryItem}; + my $id; + foreach $id (sort { $a <=> $b } keys %$items) { + my $item = $$items{$id}; + my $type = $$item{ContentType} || $$item{Type} || next; + unless ($type eq 'Exif') { + next unless $type eq 'application/rdf+xml'; + $type = 'XMP'; + } + if ($$item{ContentEncoding}) { + $et->WarnOnce("Can't currently decode encoded $type metadata"); + next; + } + if ($$item{ProtectionIndex}) { + $et->WarnOnce("Can't currently decode protected $type metadata"); + next; + } + if ($$item{ConstructionMethod}) { + $et->WarnOnce("Can't currently extract $type with construction method $$item{ConstructionMethod}"); + next; + } + next if $$item{DataReferenceIndex}; # (can only extract information from "this file") + my ($extent, $proc); + my $base = $$item{BaseOffset} || 0; + undef $buff; + my $val = ''; + foreach $extent (@{$$item{Extents}}) { + $val .= $buff if defined $buff; + $raf->Seek($$extent[1] + $base, 0) or last; + $raf->Read($buff, $$extent[2]) or last; + } + next unless defined $buff; + $buff = $val . $buff if length $val; + my $start = $type eq 'Exif' ? 10 : 0; # skip count and "Exif\0\0" header + my $pos = $$item{Extents}[0][1] + $base; + my %dirInfo = ( + DataPt => \$buff, + DataLen => length $buff, + DirStart => $start, + DirLen => length($buff) - $start, + DataPos => $pos, + Base => $pos, # (needed for IsOffset tags in binary data) + ); + # handle processing of metadata for sub-documents + if (defined $primary and $$item{RefersTo} and not $$item{RefersTo}{$primary}) { + # set document number if this doesn't refer to the primary document + $$et{DOC_NUM} = ++$$et{DOC_COUNT}; + # associate this document number with the lowest item index + my ($lowest) = sort { $a <=> $b } keys %{$$item{RefersTo}}; + $$items{$lowest}{DocNum} = $$et{DOC_NUM}; + } + my $subTable = GetTagTable('Image::ExifTool::' . $type . '::Main'); + $proc = \&Image::ExifTool::ProcessTIFF if $type eq 'Exif'; + $et->ProcessDirectory(\%dirInfo, $subTable, $proc); + delete $$et{DOC_NUM}; + } + $raf->Seek($curPos, 0); # seek back to original position + } + # process the item properties now that we should know their associations and document numbers + if ($$et{ItemPropertyContainer}) { + my ($dirInfo, $subTable, $proc) = @{$$et{ItemPropertyContainer}}; + $$et{IsItemProperty} = 1; # set item property flag + $et->ProcessDirectory($dirInfo, $subTable, $proc); + delete $$et{ItemPropertyContainer}; + delete $$et{IsItemProperty}; + delete $$et{DOC_NUM}; + } + delete $$et{ItemInfo}; +} + +#------------------------------------------------------------------------------ +# Process MPEG-4 MTDT atom (ref 11) +# Inputs: 0) ExifTool object ref, 1) dirInfo ref, 2) tag table ref +# Returns: 1 on success +sub ProcessMetaData($$$) +{ + my ($et, $dirInfo, $tagTablePtr) = @_; + my $dataPt = $$dirInfo{DataPt}; + my $dirLen = length $$dataPt; + my $verbose = $et->Options('Verbose'); + return 0 unless $dirLen >= 2; + my $count = Get16u($dataPt, 0); + $verbose and $et->VerboseDir('MetaData', $count); + my $i; + my $pos = 2; + for ($i=0; $i<$count; ++$i) { + last if $pos + 10 > $dirLen; + my $size = Get16u($dataPt, $pos); + last if $size < 10 or $size + $pos > $dirLen; + my $tag = Get32u($dataPt, $pos + 2); + my $lang = Get16u($dataPt, $pos + 6); + my $enc = Get16u($dataPt, $pos + 8); + my $val = substr($$dataPt, $pos + 10, $size); + my $tagInfo = $et->GetTagInfo($tagTablePtr, $tag); + if ($tagInfo) { + # convert language code to ASCII (ignore read-only bit) + $lang = UnpackLang($lang); + # handle alternate languages + if ($lang) { + my $langInfo = GetLangInfoQT($et, $tagInfo, $lang); + $tagInfo = $langInfo if $langInfo; + } + $verbose and $et->VerboseInfo($tag, $tagInfo, + Value => $val, + DataPt => $dataPt, + Start => $pos + 10, + Size => $size - 10, + ); + # convert from UTF-16 BE if necessary + $val = $et->Decode($val, 'UCS2') if $enc == 1; + if ($enc == 0 and $$tagInfo{Unknown}) { + # binary data + $et->FoundTag($tagInfo, \$val); + } else { + $et->FoundTag($tagInfo, $val); + } + } + $pos += $size; + } + return 1; +} + +#------------------------------------------------------------------------------ +# Process sample description table +# Inputs: 0) ExifTool object ref, 1) dirInfo ref, 2) tag table ref +# Returns: 1 on success +# (ref https://developer.apple.com/library/content/documentation/QuickTime/QTFF/QTFFChap2/qtff2.html#//apple_ref/doc/uid/TP40000939-CH204-25691) +sub ProcessSampleDesc($$$) +{ + my ($et, $dirInfo, $tagTablePtr) = @_; + my $dataPt = $$dirInfo{DataPt}; + my $pos = $$dirInfo{DirStart} || 0; + my $dirLen = $$dirInfo{DirLen} || (length($$dataPt) - $pos); + return 0 if $pos + 8 > $dirLen; + + my $num = Get32u($dataPt, 4); # get number of sample descriptions in table + $pos += 8; + my $i; + for ($i=0; $i<$num; ++$i) { # loop through sample descriptions + last if $pos + 8 > $dirLen; + my $size = Get32u($dataPt, $pos); + last if $pos + $size > $dirLen; + $$dirInfo{DirStart} = $pos; + $$dirInfo{DirLen} = $size; + ProcessHybrid($et, $dirInfo, $tagTablePtr); + $pos += $size; + } + return 1; +} + +#------------------------------------------------------------------------------ +# Process hybrid binary data + QuickTime container (ref PH) +# Inputs: 0) ExifTool object ref, 1) dirInfo ref, 2) tag table ref +# Returns: 1 on success +sub ProcessHybrid($$$) +{ + my ($et, $dirInfo, $tagTablePtr) = @_; + # brute-force search for child atoms after first 8 bytes of binary data + my $dataPt = $$dirInfo{DataPt}; + my $dirStart = $$dirInfo{DirStart} || 0; + my $dirLen = $$dirInfo{DirLen} || length($$dataPt) - $dirStart; + my $end = $dirStart + $dirLen; + my $pos = $dirStart + 8; # skip length/version + my $try = $pos; + my $childPos; + + while ($pos <= $end - 8) { + my $tag = substr($$dataPt, $try+4, 4); + # look only for well-behaved tag ID's + $tag =~ /[^\w ]/ and $try = ++$pos, next; + my $size = Get32u($dataPt, $try); + if ($size + $try == $end) { + # the atom ends exactly at the end of the parent -- this must be it + $childPos = $pos; + $$dirInfo{DirLen} = $pos; # the binary data ends at the first child atom + last; + } + if ($size < 8 or $size + $try > $end - 8) { + $try = ++$pos; # fail. try next position + } else { + $try += $size; # could be another atom following this + } + } + # process binary data + $$dirInfo{MixedTags} = 1; # ignore non-integer tag ID's + $et->ProcessBinaryData($dirInfo, $tagTablePtr); + # process child atoms if found + if ($childPos) { + $$dirInfo{DirStart} = $childPos; + $$dirInfo{DirLen} = $end - $childPos; + ProcessMOV($et, $dirInfo, $tagTablePtr); + } + return 1; +} + +#------------------------------------------------------------------------------ +# Process iTunes 'righ' atom (ref PH) +# Inputs: 0) ExifTool object ref, 1) dirInfo ref, 2) tag table ref +# Returns: 1 on success +sub ProcessRights($$$) +{ + my ($et, $dirInfo, $tagTablePtr) = @_; + my $dataPt = $$dirInfo{DataPt}; + my $dataPos = $$dirInfo{Base}; + my $dirLen = length $$dataPt; + my $unknown = $$et{OPTIONS}{Unknown} || $$et{OPTIONS}{Verbose}; + my $pos; + $et->VerboseDir('righ', $dirLen / 8); + for ($pos = 0; $pos + 8 <= $dirLen; $pos += 8) { + my $tag = substr($$dataPt, $pos, 4); + last if $tag eq "\0\0\0\0"; + my $val = substr($$dataPt, $pos + 4, 4); + my $tagInfo = $et->GetTagInfo($tagTablePtr, $tag); + unless ($tagInfo) { + next unless $unknown; + my $name = PrintableTagID($tag); + $tagInfo = { + Name => "Unknown_$name", + Description => "Unknown $name", + Unknown => 1, + }, + AddTagToTable($tagTablePtr, $tag, $tagInfo); + } + $val = '0x' . unpack('H*', $val) unless $$tagInfo{Format}; + $et->HandleTag($tagTablePtr, $tag, $val, + DataPt => $dataPt, + DataPos => $dataPos, + Start => $pos + 4, + Size => 4, + ); + } + return 1; +} + +#------------------------------------------------------------------------------ +# Process iTunes Encoding Params (ref PH) +# Inputs: 0) ExifTool object ref, 1) dirInfo ref, 2) tag table ref +# Returns: 1 on success +sub ProcessEncodingParams($$$) +{ + my ($et, $dirInfo, $tagTablePtr) = @_; + my $dataPt = $$dirInfo{DataPt}; + my $dirLen = length $$dataPt; + my $pos; + $et->VerboseDir('Encoding Params', $dirLen / 8); + for ($pos = 0; $pos + 8 <= $dirLen; $pos += 8) { + my ($tag, $val) = unpack("x${pos}a4N", $$dataPt); + $et->HandleTag($tagTablePtr, $tag, $val); + } + return 1; +} + +#------------------------------------------------------------------------------ +# Process Meta keys and add tags to the ItemList table ('mdta' handler) (ref PH) +# Inputs: 0) ExifTool object ref, 1) dirInfo ref, 2) tag table ref +# Returns: 1 on success +sub ProcessKeys($$$) +{ + local $_; + my ($et, $dirInfo, $tagTablePtr) = @_; + my $dataPt = $$dirInfo{DataPt}; + my $dirLen = length $$dataPt; + my $out; + if ($et->Options('Verbose')) { + $et->VerboseDir('Keys'); + $out = $et->Options('TextOut'); + } + my $pos = 8; + my $index = 1; + ++$$et{KeyCount}; # increment key count for this directory + my $infoTable = GetTagTable('Image::ExifTool::QuickTime::ItemList'); + my $userTable = GetTagTable('Image::ExifTool::QuickTime::UserData'); + while ($pos < $dirLen - 4) { + my $len = unpack("x${pos}N", $$dataPt); + last if $len < 8 or $pos + $len > $dirLen; + delete $$tagTablePtr{$index}; + my $ns = substr($$dataPt, $pos + 4, 4); + my $tag = substr($$dataPt, $pos + 8, $len - 8); + $tag =~ s/\0.*//s; # truncate at null + if ($ns eq 'mdta') { + $tag =~ s/^com\.apple\.quicktime\.//; # remove common apple quicktime domain + } + $tag = "Tag_$ns" unless $tag; + # (I have some samples where the tag is a reversed ItemList or UserData tag ID) + my $tagInfo = $et->GetTagInfo($tagTablePtr, $tag); + unless ($tagInfo) { + $tagInfo = $et->GetTagInfo($infoTable, $tag); + unless ($tagInfo) { + $tagInfo = $et->GetTagInfo($userTable, $tag); + if (not $tagInfo and $tag =~ /^\w{3}\xa9$/) { + $tag = pack('N', unpack('V', $tag)); + $tagInfo = $et->GetTagInfo($infoTable, $tag); + $tagInfo or $tagInfo = $et->GetTagInfo($userTable, $tag); + } + } + } + my ($newInfo, $msg); + if ($tagInfo) { + $newInfo = { + Name => $$tagInfo{Name}, + Format => $$tagInfo{Format}, + ValueConv => $$tagInfo{ValueConv}, + PrintConv => $$tagInfo{PrintConv}, + }; + my $groups = $$tagInfo{Groups}; + $$newInfo{Groups} = { %$groups } if $groups; + } elsif ($tag =~ /^[-\w.]+$/) { + # create info for tags with reasonable id's + my $name = $tag; + $name =~ s/\.(.)/\U$1/g; + $newInfo = { Name => ucfirst($name) }; + $msg = ' (Unknown)'; + } + # substitute this tag in the ItemList table with the given index + my $id = $$et{KeyCount} . '.' . $index; + if (ref $$infoTable{$id} eq 'HASH') { + # delete other languages too if they exist + my $oldInfo = $$infoTable{$id}; + if ($$oldInfo{OtherLang}) { + delete $$infoTable{$_} foreach @{$$oldInfo{OtherLang}}; + } + delete $$infoTable{$id}; + } + if ($newInfo) { + $msg or $msg = ''; + AddTagToTable($infoTable, $id, $newInfo); + $out and print $out "$$et{INDENT}Added ItemList Tag $id = $tag$msg\n"; + } + $pos += $len; + ++$index; + } + return 1; +} + +#------------------------------------------------------------------------------ +# Process keys in MetaSampleDesc directory +# Inputs: 0) ExifTool object ref, 1) dirInfo ref, 2) tag table ref +# Returns: 1 on success +sub ProcessMetaKeys($$$) +{ + my ($et, $dirInfo, $tagTablePtr) = @_; + # save this information to decode timed metadata samples when ExtractEmbedded is used + SaveMetaKeys($et, $dirInfo, $tagTablePtr) if $$et{OPTIONS}{ExtractEmbedded}; + return 1; +} + +#------------------------------------------------------------------------------ +# Process a QuickTime atom +# Inputs: 0) ExifTool object ref, 1) dirInfo ref, 2) optional tag table ref +# Returns: 1 on success +sub ProcessMOV($$;$) +{ + local $_; + my ($et, $dirInfo, $tagTablePtr) = @_; + my $raf = $$dirInfo{RAF}; + my $dataPt = $$dirInfo{DataPt}; + my $verbose = $et->Options('Verbose'); + my $dataPos = $$dirInfo{Base} || 0; + my $charsetQuickTime = $et->Options('CharsetQuickTime'); + my ($buff, $tag, $size, $track, $isUserData, %triplet, $doDefaultLang, $index); + my ($dirEnd, $ee, $unkOpt, %saveOptions); + + my $topLevel = not $$et{InQuickTime}; + $$et{InQuickTime} = 1; + $$et{HandlerType} = $$et{MetaFormat} = '' unless defined $$et{HandlerType}; + + unless (defined $$et{KeyCount}) { + $$et{KeyCount} = 0; # initialize ItemList key directory count + $doDefaultLang = 1; # flag to generate default language tags + } + # more convenient to package data as a RandomAccess file + unless ($raf) { + $raf = new File::RandomAccess($dataPt); + $dirEnd = $dataPos + $$dirInfo{DirLen} + ($$dirInfo{DirStart} || 0) if $$dirInfo{DirLen}; + } + # skip leading bytes if necessary + if ($$dirInfo{DirStart}) { + $raf->Seek($$dirInfo{DirStart}, 1) or return 0; + $dataPos += $$dirInfo{DirStart}; + } + # read size/tag name atom header + $raf->Read($buff,8) == 8 or return 0; + $dataPos += 8; + if ($tagTablePtr) { + $isUserData = ($tagTablePtr eq \%Image::ExifTool::QuickTime::UserData); + } else { + $tagTablePtr = GetTagTable('Image::ExifTool::QuickTime::Main'); + } + ($size, $tag) = unpack('Na4', $buff); + if ($dataPt) { + $verbose and $et->VerboseDir($$dirInfo{DirName}); + } else { + # check on file type if called with a RAF + $$tagTablePtr{$tag} or return 0; + if ($tag eq 'ftyp' and $size >= 12) { + # read ftyp atom to see what type of file this is + my $fileType; + if ($raf->Read($buff, $size-8) == $size-8) { + $raf->Seek(-($size-8), 1); + my $type = substr($buff, 0, 4); + # see if we know the extension for this file type + if ($ftypLookup{$type} and $ftypLookup{$type} =~ /\(\.(\w+)/) { + $fileType = $1; + # check compatible brands + } elsif ($buff =~ /^.{8}(.{4})+(mp41|mp42|avc1)/s) { + $fileType = 'MP4'; + } elsif ($buff =~ /^.{8}(.{4})+(f4v )/s) { + $fileType = 'F4V'; + } elsif ($buff =~ /^.{8}(.{4})+(qt )/s) { + $fileType = 'MOV'; + } + } + $fileType or $fileType = 'MP4'; # default to MP4 + $et->SetFileType($fileType, $mimeLookup{$fileType} || 'video/mp4'); + # temporarily set ExtractEmbedded option for CRX files + $saveOptions{ExtractEmbedded} = $et->Options(ExtractEmbedded => 1) if $fileType eq 'CRX'; + } else { + $et->SetFileType(); # MOV + } + SetByteOrder('MM'); + $$et{PRIORITY_DIR} = 'XMP'; # have XMP take priority + } + $$raf{NoBuffer} = 1 if $et->Options('FastScan'); # disable buffering in FastScan mode + + if ($$et{OPTIONS}{ExtractEmbedded}) { + $ee = 1; + $unkOpt = $$et{OPTIONS}{Unknown}; + require 'Image/ExifTool/QuickTimeStream.pl'; + } + $index = $$tagTablePtr{VARS}{START_INDEX} if $$tagTablePtr{VARS}; + for (;;) { + my ($eeTag, $ignore); + if ($size < 8) { + if ($size == 0) { + if ($dataPt) { + # a zero size isn't legal for contained atoms, but Canon uses it to + # terminate the CNTH atom (eg. CanonEOS100D.mov), so tolerate it here + my $pos = $raf->Tell() - 4; + $raf->Seek(0,2); + my $str = $$dirInfo{DirName} . ' with ' . ($raf->Tell() - $pos) . ' bytes'; + $et->VPrint(0,"$$et{INDENT}\[Terminator found in $str remaining]"); + } else { + $tag = PrintableTagID($tag); + $et->VPrint(0,"$$et{INDENT}Tag '${tag}' extends to end of file"); + } + last; + } + $size == 1 or $et->Warn('Invalid atom size'), last; + # read extended atom size + $raf->Read($buff, 8) == 8 or last; + $dataPos += 8; + my ($hi, $lo) = unpack('NN', $buff); + if ($hi or $lo > 0x7fffffff) { + if ($hi > 0x7fffffff) { + $et->Warn('Invalid atom size'); + last; + } elsif (not $et->Options('LargeFileSupport')) { + $et->Warn('End of processing at large atom (LargeFileSupport not enabled)'); + last; + } + } + $size = $hi * 4294967296 + $lo - 16; + $size < 0 and $et->Warn('Invalid extended size'), last; + } else { + $size -= 8; + } + if ($isUserData and $$et{SET_GROUP1}) { + my $tagInfo = $et->GetTagInfo($tagTablePtr, $tag); + # add track name to UserData tags inside tracks + $tag = $$et{SET_GROUP1} . $tag; + if (not $$tagTablePtr{$tag} and $tagInfo) { + my %newInfo = %$tagInfo; + foreach ('Name', 'Description') { + next unless $$tagInfo{$_}; + $newInfo{$_} = $$et{SET_GROUP1} . $$tagInfo{$_}; + $newInfo{$_} =~ s/^(Track\d+)Track/$1/; # remove duplicate "Track" in name + } + AddTagToTable($tagTablePtr, $tag, \%newInfo); + } + } + # set flag to store additional information for ExtractEmbedded option + my $handlerType = $$et{HandlerType}; + if ($eeBox{$handlerType} and $eeBox{$handlerType}{$tag}) { + if ($ee) { + $eeTag = 1; + $$et{OPTIONS}{Unknown} = 1; # temporarily enable "Unknown" option + } elsif ($handlerType ne 'vide' and not $$et{OPTIONS}{Validate}) { + $et->WarnOnce('The ExtractEmbedded option may find more tags in the movie data',3); + } + } + my $tagInfo = $et->GetTagInfo($tagTablePtr, $tag); + + $$et{OPTIONS}{Unknown} = $unkOpt if $eeTag; # restore Unknown option + + # allow numerical tag ID's + unless ($tagInfo) { + my $id = $$et{KeyCount} . '.' . unpack('N', $tag); + if ($$tagTablePtr{$id}) { + $tagInfo = $et->GetTagInfo($tagTablePtr, $id); + $tag = $id; + } + } + # generate tagInfo if Unknown option set + if (not defined $tagInfo and ($$et{OPTIONS}{Unknown} or + $verbose or $tag =~ /^\xa9/)) + { + my $name = PrintableTagID($tag,1); + if ($name =~ /^xa9(.*)/) { + $tagInfo = { + Name => "UserData_$1", + Description => "User Data $1", + }; + } else { + $tagInfo = { + Name => "Unknown_$name", + Description => "Unknown $name", + %unknownInfo, + }; + } + AddTagToTable($tagTablePtr, $tag, $tagInfo); + } + # save required tag sizes + if ($$tagTablePtr{"$tag-size"}) { + $et->HandleTag($tagTablePtr, "$tag-size", $size); + $et->HandleTag($tagTablePtr, "$tag-offset", $raf->Tell()) if $$tagTablePtr{"$tag-offset"}; + } + # load values only if associated with a tag (or verbose) and not too big + if ($size > 0x2000000) { # start to get worried above 32 MB + $ignore = 1; + if ($tagInfo and not $$tagInfo{Unknown} and not $eeTag) { + my $t = PrintableTagID($tag); + if ($size > 0x8000000) { + $et->Warn("Skipping '${t}' atom > 128 MB", 1); + } else { + $et->Warn("Skipping '${t}' atom > 32 MB", 2) or $ignore = 0; + } + } + } + if (defined $tagInfo and not $ignore) { + # set document number for this item property if necessary + if ($$et{IsItemProperty}) { + my $items = $$et{ItemInfo}; + my ($id, $prop, $mainItem, $docNum, $lowest); + my $primary = $$et{PrimaryItem} || 0; +ItemID: foreach $id (keys %$items) { + next unless $$items{$id}{Association}; + my $item = $$items{$id}; + foreach $prop (@{$$item{Association}}) { + next unless $prop == $index; + if ($id == $primary or (not $dontInherit{$tag} and + (not $$item{RefersTo} or $$item{RefersTo}{$primary}))) + { + # this is associated with the primary item or an item describing + # the primary item, so consider this part of the main document + undef $docNum; + undef $lowest; + last ItemID; + } elsif ($$item{DocNum}) { + # this property is already associated with an item that has + # an ExifTool document number, so use the lowest assocated DocNum + $docNum = $$item{DocNum} if not defined $docNum or $docNum > $$item{DocNum}; + } elsif (not defined $lowest or $lowest > $id) { + # keep track of the lowest associated item ID + $lowest = $id; + } + } + } + if (not defined $docNum and defined $lowest) { + # this is the first time we've seen metadata from this item, + # so use a new document number + $docNum = ++$$et{DOC_COUNT}; + $$items{$lowest}{DocNum} = $docNum; + } + $$et{DOC_NUM} = $docNum; + } + my $val; + my $missing = $size - $raf->Read($val, $size); + if ($missing) { + $et->Warn("Truncated '${tag}' data (missing $missing bytes)"); + last; + } + # use value to get tag info if necessary + $tagInfo or $tagInfo = $et->GetTagInfo($tagTablePtr, $tag, \$val); + my $hasData = ($$dirInfo{HasData} and $val =~ /\0...data\0/s); + if ($verbose and not $hasData) { + my $tval; + if ($tagInfo and $$tagInfo{Format}) { + $tval = ReadValue(\$val, 0, $$tagInfo{Format}, $$tagInfo{Count}, length($val)); + } + $et->VerboseInfo($tag, $tagInfo, + Value => $tval, + DataPt => \$val, + DataPos => $dataPos, + Size => $size, + Format => $tagInfo ? $$tagInfo{Format} : undef, + Index => $index, + ); + } + # extract metadata from stream if ExtractEmbedded option is enabled + if ($eeTag) { + ParseTag($et, $tag, \$val); + # forget this tag if we generated it only for ExtractEmbedded + undef $tagInfo if $tagInfo and $$tagInfo{Unknown} and not $unkOpt; + } + + # handle iTunesInfo mean/name/data triplets + if ($tagInfo and $$tagInfo{Triplet}) { + if ($tag eq 'data' and $triplet{mean} and $triplet{name}) { + $tag = $triplet{name}; + # add 'mean' to name unless it is 'com.apple.iTunes' + $tag = $triplet{mean} . '/' . $tag unless $triplet{mean} eq 'com.apple.iTunes'; + $tagInfo = $et->GetTagInfo($tagTablePtr, $tag, \$val); + unless ($tagInfo) { + my $name = $triplet{name}; + my $desc = $name; + $name =~ tr/-_a-zA-Z0-9//dc; + $desc =~ tr/_/ /; + $tagInfo = { + Name => $name, + Description => $desc, + }; + AddTagToTable($tagTablePtr, $tag, $tagInfo); + } + # ignore 8-byte header + $val = substr($val, 8) if length($val) >= 8; + unless ($$tagInfo{Format} or $$tagInfo{SubDirectory}) { + # extract as binary if it contains any non-ASCII or control characters + if ($val =~ /[^\x20-\x7e]/) { + my $buff = $val; + $val = \$buff; + } + } + undef %triplet; + } else { + undef %triplet if $tag eq 'mean'; + $triplet{$tag} = substr($val,4) if length($val) > 4; + undef $tagInfo; # don't store this tag + } + } + if ($tagInfo) { + my $subdir = $$tagInfo{SubDirectory}; + if ($subdir) { + my $start = $$subdir{Start} || 0; + my ($base, $dPos) = ($dataPos, 0); + if ($$subdir{Base}) { + $dPos -= eval $$subdir{Base}; + $base -= $dPos; + } + my %dirInfo = ( + DataPt => \$val, + DataLen => $size, + DirStart => $start, + DirLen => $size - $start, + DirName => $$subdir{DirName} || $$tagInfo{Name}, + HasData => $$subdir{HasData}, + Multi => $$subdir{Multi}, + IgnoreProp => $$subdir{IgnoreProp}, # (XML hack) + DataPos => $dPos, + Base => $base, # (needed for IsOffset tags in binary data) + ); + $dirInfo{BlockInfo} = $tagInfo if $$tagInfo{BlockExtract}; + if ($$subdir{ByteOrder} and $$subdir{ByteOrder} =~ /^Little/) { + SetByteOrder('II'); + } + my $oldGroup1 = $$et{SET_GROUP1}; + if ($$tagInfo{Name} eq 'Track') { + $track or $track = 0; + $$et{SET_GROUP1} = 'Track' . (++$track); + } + my $subTable = GetTagTable($$subdir{TagTable}); + my $proc = $$subdir{ProcessProc}; + # make ProcessMOV() the default processing procedure for subdirectories + $proc = \&ProcessMOV unless $proc or $$subTable{PROCESS_PROC}; + if ($size > $start) { + # delay processing of ipco box until after all other boxes + if ($tag eq 'ipco' and not $$et{IsItemProperty}) { + $$et{ItemPropertyContainer} = [ \%dirInfo, $subTable, $proc ]; + $et->VPrint(0,"$$et{INDENT}\[Process ipco box later]"); + } else { + $et->ProcessDirectory(\%dirInfo, $subTable, $proc); + } + } + if ($tag eq 'stbl') { + # process sample data when exiting SampleTable box if extracting embedded + ProcessSamples($et) if $ee; + } elsif ($tag eq 'minf') { + $$et{HandlerType} = ''; # reset handler type at end of media info box + } + $$et{SET_GROUP1} = $oldGroup1; + SetByteOrder('MM'); + if ($tag eq 'meta') { + # handle metadata now if we just processed the 'meta' box + HandleItemInfo($et, $raf) if $tag eq 'meta'; + } + } elsif ($hasData) { + # handle atoms containing 'data' tags + # (currently ignore contained atoms: 'itif', 'name', etc.) + my $pos = 0; + for (;;) { + last if $pos + 16 > $size; + my ($len, $type, $flags, $ctry, $lang) = unpack("x${pos}Na4Nnn", $val); + last if $pos + $len > $size; + my $value; + my $format = $$tagInfo{Format}; + if ($type eq 'data' and $len >= 16) { + $pos += 16; + $len -= 16; + $value = substr($val, $pos, $len); + # format flags (ref 12): + # 0x0=binary, 0x1=UTF-8, 0x2=UTF-16, 0x3=ShiftJIS, + # 0x4=UTF-8 0x5=UTF-16, 0xd=JPEG, 0xe=PNG, + # 0x15=signed int, 0x16=unsigned int, 0x17=float, + # 0x18=double, 0x1b=BMP, 0x1c='meta' atom + if ($stringEncoding{$flags}) { + # handle all string formats + $value = $et->Decode($value, $stringEncoding{$flags}); + # (shouldn't be null terminated, but some software writes it anyway) + $value =~ s/\0$// unless $$tagInfo{Binary}; + } else { + if (not $format) { + if ($flags == 0x15 or $flags == 0x16) { + $format = { 1=>'int8', 2=>'int16', 4=>'int32' }->{$len}; + $format .= $flags == 0x15 ? 's' : 'u' if $format; + } elsif ($flags == 0x17) { + $format = 'float'; + } elsif ($flags == 0x18) { + $format = 'double'; + } elsif ($flags == 0x00) { + # read 1 and 2-byte binary as integers + if ($len == 1) { + $format = 'int8u', + } elsif ($len == 2) { + $format = 'int16u', + } + } + } + if ($format) { + $value = ReadValue(\$value, 0, $format, $$tagInfo{Count}, $len); + } elsif (not $$tagInfo{ValueConv}) { + # make binary data a scalar reference unless a ValueConv exists + my $buf = $value; + $value = \$buf; + } + } + } + my $langInfo; + if ($ctry or $lang) { + # ignore country ('ctry') and language lists ('lang') for now + undef $ctry if $ctry and $ctry <= 255; + undef $lang if $lang and $lang <= 255; + $lang = UnpackLang($lang); + # add country code if specified + if ($ctry) { + $ctry = unpack('a2',pack('n',$ctry)); # unpack as ISO 3166-1 + # treat 'ZZ' like a default country (see ref 12) + undef $ctry if $ctry eq 'ZZ'; + if ($ctry and $ctry =~ /^[A-Z]{2}$/) { + $lang or $lang = 'und'; + $lang .= "-$ctry"; + } + } + if ($lang) { + # get tagInfo for other language + $langInfo = GetLangInfoQT($et, $tagInfo, $lang); + # save other language tag ID's so we can delete later if necessary + if ($langInfo) { + $$tagInfo{OtherLang} or $$tagInfo{OtherLang} = [ ]; + push @{$$tagInfo{OtherLang}}, $$langInfo{TagID}; + } + } + } + $langInfo or $langInfo = $tagInfo; + $et->VerboseInfo($tag, $langInfo, + Value => ref $value ? $$value : $value, + DataPt => \$val, + DataPos => $dataPos, + Start => $pos, + Size => $len, + Format => $format, + Index => $index, + Extra => sprintf(", Type='${type}', Flags=0x%x",$flags) + ) if $verbose; + $et->FoundTag($langInfo, $value) if defined $value; + $pos += $len; + } + } elsif ($tag =~ /^\xa9/ or $$tagInfo{IText}) { + # parse international text to extract all languages + my $pos = 0; + if ($$tagInfo{Format}) { + $et->FoundTag($tagInfo, ReadValue(\$val, 0, $$tagInfo{Format}, undef, length($val))); + $pos = $size; + } + for (;;) { + last if $pos + 4 > $size; + my ($len, $lang) = unpack("x${pos}nn", $val); + $pos += 4; + # according to the QuickTime spec (ref 12), $len should include + # 4 bytes for length and type words, but nobody (including + # Apple, Pentax and Kodak) seems to add these in, so try + # to allow for either + if ($pos + $len > $size) { + $len -= 4; + last if $pos + $len > $size or $len < 0; + } + # ignore any empty entries (or null padding) after the first + next if not $len and $pos; + my $str = substr($val, $pos, $len); + my $langInfo; + if ($lang < 0x400) { + # this is a Macintosh language code + # a language code of 0 is Macintosh english, so treat as default + if ($lang) { + # use Font.pm to look up language string + require Image::ExifTool::Font; + $lang = $Image::ExifTool::Font::ttLang{Macintosh}{$lang}; + } + # the spec says only "Macintosh text encoding", but + # allow this to be configured by the user + $str = $et->Decode($str, $charsetQuickTime); + } else { + # convert language code to ASCII (ignore read-only bit) + $lang = UnpackLang($lang); + # may be either UTF-8 or UTF-16BE + my $enc = $str=~s/^\xfe\xff// ? 'UTF16' : 'UTF8'; + $str = $et->Decode($str, $enc); + } + $langInfo = GetLangInfoQT($et, $tagInfo, $lang) if $lang; + $et->FoundTag($langInfo || $tagInfo, $str); + $pos += $len; + } + } else { + my $format = $$tagInfo{Format}; + if ($format) { + $val = ReadValue(\$val, 0, $format, $$tagInfo{Count}, length($val)); + } + my $oldBase; + if ($$tagInfo{SetBase}) { + $oldBase = $$et{BASE}; + $$et{BASE} = $dataPos; + } + my $key = $et->FoundTag($tagInfo, $val); + $$et{BASE} = $oldBase if defined $oldBase; + # decode if necessary (NOTE: must be done after RawConv) + if (defined $key and (not $format or $format =~ /^string/) and + not $$tagInfo{Unknown} and not $$tagInfo{ValueConv} and + not $$tagInfo{Binary} and defined $$et{VALUE}{$key} and not ref $val) + { + my $vp = \$$et{VALUE}{$key}; + if (not ref $$vp and length($$vp) <= 65536 and $$vp =~ /[\x80-\xff]/) { + # the encoding of this is not specified, so use CharsetQuickTime + # unless the string is valid UTF-8 + require Image::ExifTool::XMP; + my $enc = Image::ExifTool::XMP::IsUTF8($vp) > 0 ? 'UTF8' : $charsetQuickTime; + $$vp = $et->Decode($$vp, $enc); + } + } + } + } + } else { + $et->VerboseInfo($tag, $tagInfo, + Size => $size, + Extra => sprintf(' at offset 0x%.4x', $raf->Tell()), + ) if $verbose; + $raf->Seek($size, 1) or $et->Warn("Truncated '${tag}' data"), last; + } + $dataPos += $size + 8; # point to start of next atom data + last if $dirEnd and $dataPos >= $dirEnd; # (note: ignores last value if 0 bytes) + $raf->Read($buff, 8) == 8 or last; + ($size, $tag) = unpack('Na4', $buff); + ++$index if defined $index; + } + # fill in missing defaults for alternate language tags + # (the first language is taken as the default) + if ($doDefaultLang and $$et{QTLang}) { +QTLang: foreach $tag (@{$$et{QTLang}}) { + next unless defined $$et{VALUE}{$tag}; + my $langInfo = $$et{TAG_INFO}{$tag} or next; + my $tagInfo = $$langInfo{SrcTagInfo} or next; + my $infoHash = $$et{TAG_INFO}; + my $name = $$tagInfo{Name}; + # loop through all instances of this tag name and generate the default-language + # version only if we don't already have a QuickTime tag with this name + my ($i, $key); + for ($i=0, $key=$name; $$infoHash{$key}; ++$i, $key="$name ($i)") { + next QTLang if $et->GetGroup($key, 0) eq 'QuickTime'; + } + $et->FoundTag($tagInfo, $$et{VALUE}{$tag}); + } + delete $$et{QTLang}; + } + if ($topLevel) { + HandleItemInfo($et, $raf); # process our item information + ScanMovieData($et) if $ee; # brute force scan for metadata embedded in movie data + } + # restore any changed options + $et->Options($_ => $saveOptions{$_}) foreach keys %saveOptions; + return 1; +} + +#------------------------------------------------------------------------------ +# Process a QuickTime Image File +# Inputs: 0) ExifTool object reference, 1) directory information reference +# Returns: 1 on success +sub ProcessQTIF($$) +{ + my ($et, $dirInfo) = @_; + my $table = GetTagTable('Image::ExifTool::QuickTime::ImageFile'); + return ProcessMOV($et, $dirInfo, $table); +} + +1; # end + +__END__ + +=head1 NAME + +Image::ExifTool::QuickTime - Read QuickTime and MP4 meta information + +=head1 SYNOPSIS + +This module is used by Image::ExifTool + +=head1 DESCRIPTION + +This module contains routines required by Image::ExifTool to extract +information from QuickTime and MP4 video, M4A audio, and HEIC image files. + +=head1 AUTHOR + +Copyright 2003-2019, Phil Harvey (phil at owl.phy.queensu.ca) + +This library is free software; you can redistribute it and/or modify it +under the same terms as Perl itself. + +=head1 REFERENCES + +=over 4 + +=item L<http://developer.apple.com/mac/library/documentation/QuickTime/QTFF/QTFFChap1/qtff1.html> + +=item L<http://search.cpan.org/dist/MP4-Info-1.04/> + +=item L<http://www.geocities.com/xhelmboyx/quicktime/formats/mp4-layout.txt> + +=item L<http://wiki.multimedia.cx/index.php?title=Apple_QuickTime> + +=item L<http://atomicparsley.sourceforge.net/mpeg-4files.html> + +=item L<http://wiki.multimedia.cx/index.php?title=QuickTime_container> + +=item L<http://code.google.com/p/mp4v2/wiki/iTunesMetadata> + +=item L<http://www.canieti.com.mx/assets/files/1011/IEC_100_1384_DC.pdf> + +=item L<http://www.adobe.com/devnet/flv/pdf/video_file_format_spec_v10.pdf> + +=back + +=head1 SEE ALSO + +L<Image::ExifTool::TagNames/QuickTime Tags>, +L<Image::ExifTool(3pm)|Image::ExifTool> + +=cut + diff --git a/lib/Image/ExifTool/QuickTimeStream.pl b/lib/Image/ExifTool/QuickTimeStream.pl new file mode 100644 index 0000000..3b0baff --- /dev/null +++ b/lib/Image/ExifTool/QuickTimeStream.pl @@ -0,0 +1,1697 @@ +#------------------------------------------------------------------------------ +# File: QuickTimeStream.pl +# +# Description: Extract embedded information from QuickTime movie data +# +# Revisions: 2018-01-03 - P. Harvey Created +# +# References: 1) https://developer.apple.com/library/content/documentation/QuickTime/QTFF/QTFFChap3/qtff3.html#//apple_ref/doc/uid/TP40000939-CH205-SW130 +# 2) http://sergei.nz/files/nvtk_mp42gpx.py +# 3) https://forum.flitsservice.nl/dashcam-info/dod-ls460w-gps-data-uit-mov-bestand-lezen-t87926.html +# 4) https://developers.google.com/streetview/publish/camm-spec +# 5) https://sergei.nz/extracting-gps-data-from-viofo-a119-and-other-novatek-powered-cameras/ +#------------------------------------------------------------------------------ +package Image::ExifTool::QuickTime; + +use strict; + +sub Process_tx3g($$$); +sub ProcessFreeGPS($$$); +sub ProcessFreeGPS2($$$); + +# QuickTime data types that have ExifTool equivalents +# (ref https://developer.apple.com/library/content/documentation/QuickTime/QTFF/Metadata/Metadata.html#//apple_ref/doc/uid/TP40000939-CH1-SW35) +my %qtFmt = ( + 0 => 'undef', + 1 => 'string', # (UTF-8) + # 2 - UTF-16 + # 3 - shift-JIS + # 4 - UTF-8 sort + # 5 - UTF-16 sort + # 13 - JPEG image + # 14 - PNG image + # 21 - signed integer (1,2,3 or 4 bytes) + # 22 - unsigned integer (1,2,3 or 4 bytes) + 23 => 'float', + 24 => 'double', + # 27 - BMP image + # 28 - QuickTime atom + 65 => 'int8s', + 66 => 'int16s', + 67 => 'int32s', + 70 => 'float', # float[2] x,y + 71 => 'float', # float[2] width,height + 72 => 'float', # float[4] x,y,width,height + 74 => 'int64s', + 75 => 'int8u', + 76 => 'int16u', + 77 => 'int32u', + 78 => 'int64u', + 79 => 'float', # float[9] transform matrix + 80 => 'float', # float[8] face coordinates +); + +# maximums for validating H,M,S,d,m,Y from "freeGPS " metadata +my @dateMax = ( 24, 59, 59, 2200, 12, 31 ); + +# typical (minimum?) size of freeGPS block +my $gpsBlockSize = 0x8000; + +# conversion factors +my $knotsToKph = 1.852; # knots --> km/h +my $mpsToKph = 3.6; # m/s --> km/h + +# handler types to process based on MetaFormat/OtherFormat +my %processByMetaFormat = ( + meta => 1, # ('CTMD' in CR3 images, 'priv' unknown in DJI video) + data => 1, # ('RVMI') + sbtl => 1, # (subtitle; 'tx3g' in Yuneec drone videos) +); + +# data lengths for each INSV record type +my %insvDataLen = ( + 0x300 => 56, + 0x400 => 16, + 0x700 => 53, +); + +# tags extracted from various QuickTime data streams +%Image::ExifTool::QuickTime::Stream = ( + GROUPS => { 2 => 'Location' }, + NOTES => q{ + Timed metadata extracted from QuickTime movie data and some AVI videos when + the ExtractEmbedded option is used. + }, + VARS => { NO_ID => 1 }, + GPSLatitude => { PrintConv => 'Image::ExifTool::GPS::ToDMS($self, $val, 1, "N")' }, + GPSLongitude => { PrintConv => 'Image::ExifTool::GPS::ToDMS($self, $val, 1, "E")' }, + GPSAltitude => { PrintConv => '(sprintf("%.4f", $val) + 0) . " m"' }, # round to 4 decimals + GPSSpeed => { PrintConv => 'sprintf("%.4f", $val) + 0' }, # round to 4 decimals + GPSSpeedRef => { PrintConv => { K => 'km/h', M => 'mph', N => 'knots' } }, + GPSTrack => { PrintConv => 'sprintf("%.4f", $val) + 0' }, # round to 4 decimals + GPSTrackRef => { PrintConv => { M => 'Magnetic North', T => 'True North' } }, + GPSDateTime => { PrintConv => '$self->ConvertDateTime($val)', Groups => { 2 => 'Time' } }, + GPSTimeStamp => { PrintConv => 'Image::ExifTool::GPS::PrintTimeStamp($val)', Groups => { 2 => 'Time' } }, + GPSSatellites=> { }, + GPSDOP => { Description => 'GPS Dilution Of Precision' }, + CameraDateTime=>{ PrintConv => '$self->ConvertDateTime($val)', Groups => { 2 => 'Time' } }, + Accelerometer=> { Notes => 'right/up/backward acceleration in units of g' }, + AngularVelocity => { }, + RawGSensor => { + # (same as GSensor, but offset by some unknown value) + ValueConv => 'my @a=split " ",$val; $_/=1000 foreach @a; "@a"', + }, + Text => { Groups => { 2 => 'Other' } }, + TimeCode => { Groups => { 2 => 'Video' } }, + FrameNumber => { Groups => { 2 => 'Video' } }, + SampleTime => { Groups => { 2 => 'Video' }, PrintConv => 'ConvertDuration($val)', Notes => 'sample decoding time' }, + SampleDuration=>{ Groups => { 2 => 'Video' }, PrintConv => 'ConvertDuration($val)' }, + UserLabel => { Groups => { 2 => 'Other' } }, +# +# timed metadata decoded based on MetaFormat (format of 'meta' or 'data' sample description) +# [or HandlerType, or specific 'vide' type if specified] +# + mebx => { + Name => 'mebx', + SubDirectory => { + TagTable => 'Image::ExifTool::QuickTime::Keys', + ProcessProc => \&Process_mebx, + }, + }, + gpmd => { + Name => 'gpmd', + SubDirectory => { TagTable => 'Image::ExifTool::GoPro::GPMF' }, + }, + fdsc => { + Name => 'fdsc', + Condition => '$$valPt =~ /^GPRO/', + # (other types of "fdsc" samples aren't yet parsed: /^GP\x00/ and /^GP\x04/) + SubDirectory => { TagTable => 'Image::ExifTool::GoPro::fdsc' }, + }, + rtmd => { + Name => 'rtmd', + SubDirectory => { TagTable => 'Image::ExifTool::Sony::rtmd' }, + }, + CTMD => { # (Canon Timed MetaData) + Name => 'CTMD', + SubDirectory => { TagTable => 'Image::ExifTool::Canon::CTMD' }, + }, + tx3g => { + Name => 'tx3g', + SubDirectory => { TagTable => 'Image::ExifTool::QuickTime::tx3g' }, + }, + RVMI => [{ # data "OtherFormat" written by unknown software + Name => 'RVMI_gReV', + Condition => '$$valPt =~ /^gReV/', # GPS data + SubDirectory => { + TagTable => 'Image::ExifTool::QuickTime::RVMI_gReV', + ByteOrder => 'Little-endian', + }, + },{ + Name => 'RVMI_sReV', + Condition => '$$valPt =~ /^sReV/', # sensor data + SubDirectory => { + TagTable => 'Image::ExifTool::QuickTime::RVMI_sReV', + ByteOrder => 'Little-endian', + }, + # (there is also "tReV" data that hasn't been decoded yet) + }], + camm => [{ + Name => 'camm0', + # (according to the spec. the first 2 bytes are reserved and should be zero, + # but I have a sample where these bytes are non-zero, so allow anything here) + Condition => '$$valPt =~ /^..\0\0/s', + SubDirectory => { + TagTable => 'Image::ExifTool::QuickTime::camm0', + ByteOrder => 'Little-Endian', + }, + },{ + Name => 'camm1', + Condition => '$$valPt =~ /^..\x01\0/s', + SubDirectory => { + TagTable => 'Image::ExifTool::QuickTime::camm1', + ByteOrder => 'Little-Endian', + }, + },{ # (written by Insta360) - [HandlerType, not MetaFormat] + Name => 'camm2', + Condition => '$$valPt =~ /^..\x02\0/s', + SubDirectory => { + TagTable => 'Image::ExifTool::QuickTime::camm2', + ByteOrder => 'Little-Endian', + }, + },{ + Name => 'camm3', + Condition => '$$valPt =~ /^..\x03\0/s', + SubDirectory => { + TagTable => 'Image::ExifTool::QuickTime::camm3', + ByteOrder => 'Little-Endian', + }, + },{ + Name => 'camm4', + Condition => '$$valPt =~ /^..\x04\0/s', + SubDirectory => { + TagTable => 'Image::ExifTool::QuickTime::camm4', + ByteOrder => 'Little-Endian', + }, + },{ + Name => 'camm5', + Condition => '$$valPt =~ /^..\x05\0/s', + SubDirectory => { + TagTable => 'Image::ExifTool::QuickTime::camm5', + ByteOrder => 'Little-Endian', + }, + },{ + Name => 'camm6', + Condition => '$$valPt =~ /^..\x06\0/s', + SubDirectory => { + TagTable => 'Image::ExifTool::QuickTime::camm6', + ByteOrder => 'Little-Endian', + }, + },{ + Name => 'camm7', + Condition => '$$valPt =~ /^..\x07\0/s', + SubDirectory => { + TagTable => 'Image::ExifTool::QuickTime::camm7', + ByteOrder => 'Little-Endian', + }, + }], + JPEG => { # (in CR3 images) - [vide HandlerType with JPEG in SampleDescription, not MetaFormat] + Name => 'JpgFromRaw', + Groups => { 2 => 'Preview' }, + RawConv => '$self->ValidateImage(\$val,$tag)', + }, + text => { # (TomTom Bandit MP4) - [sbtl HandlerType with 'text' in SampleDescription] + Name => 'PreviewInfo', + Condition => 'length $$valPt > 12 and Get32u($valPt,4) == length($$valPt) and $$valPt =~ /^.{8}\xff\xd8\xff/s', + SubDirectory => { TagTable => 'Image::ExifTool::QuickTime::PreviewInfo' }, + }, + INSV => { SubDirectory => { TagTable => 'Image::ExifTool::QuickTime::INSV_MakerNotes' } }, + Unknown00 => { Unknown => 1 }, + Unknown01 => { Unknown => 1 }, + Unknown02 => { Unknown => 1 }, + Unknown03 => { Unknown => 1 }, +); + +# tags found in 'camm' type 0 timed metadata (ref 4) +%Image::ExifTool::QuickTime::camm0 = ( + PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData, + GROUPS => { 2 => 'Location' }, + FIRST_ENTRY => 0, + NOTES => q{ + The camm0 through camm7 tables define tags extracted from the Google Street + View Camera Motion Metadata of MP4 videos. See + L<https://developers.google.com/streetview/publish/camm-spec> for the + specification. + }, + 4 => { + Name => 'AngleAxis', + Notes => 'angle axis orientation in radians in local coordinate system', + Format => 'float[3]', + }, +); + +# tags found in 'camm' type 1 timed metadata (ref 4) +%Image::ExifTool::QuickTime::camm1 = ( + PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData, + GROUPS => { 2 => 'Camera' }, + FIRST_ENTRY => 0, + 4 => { + Name => 'PixelExposureTime', + Format => 'int32s', + ValueConv => '$val * 1e-9', + PrintConv => 'sprintf("%.4g ms", $val * 1000)', + }, + 8 => { + Name => 'RollingShutterSkewTime', + Format => 'int32s', + ValueConv => '$val * 1e-9', + PrintConv => 'sprintf("%.4g ms", $val * 1000)', + }, +); + +# tags found in 'camm' type 2 timed metadata (ref PH, Insta360Pro) +%Image::ExifTool::QuickTime::camm2 = ( + PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData, + GROUPS => { 2 => 'Location' }, + FIRST_ENTRY => 0, + 4 => { + Name => 'AngularVelocity', + Notes => 'gyro angular velocity about X, Y and Z axes in rad/s', + Format => 'float[3]', + }, +); + +# tags found in 'camm' type 3 timed metadata (ref PH, Insta360Pro) +%Image::ExifTool::QuickTime::camm3 = ( + PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData, + GROUPS => { 2 => 'Location' }, + FIRST_ENTRY => 0, + 4 => { + Name => 'Acceleration', + Notes => 'acceleration in the X, Y and Z directions in m/s^2', + Format => 'float[3]', + }, +); + +# tags found in 'camm' type 4 timed metadata (ref 4) +%Image::ExifTool::QuickTime::camm4 = ( + PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData, + GROUPS => { 2 => 'Location' }, + FIRST_ENTRY => 0, + 4 => { + Name => 'Position', + Notes => 'X, Y, Z position in local coordinate system', + Format => 'float[3]', + }, +); + +# tags found in 'camm' type 5 timed metadata (ref 4) +%Image::ExifTool::QuickTime::camm5 = ( + PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData, + GROUPS => { 2 => 'Location' }, + FIRST_ENTRY => 0, + 4 => { + Name => 'GPSLatitude', + Format => 'double', + ValueConv => 'Image::ExifTool::GPS::ToDegrees($val, 1)', + PrintConv => 'Image::ExifTool::GPS::ToDMS($self, $val, 1, "N")', + }, + 12 => { + Name => 'GPSLongitude', + Format => 'double', + ValueConv => 'Image::ExifTool::GPS::ToDegrees($val, 1)', + PrintConv => 'Image::ExifTool::GPS::ToDMS($self, $val, 1, "E")', + }, + 20 => { + Name => 'GPSAltitude', + Format => 'double', + PrintConv => '$_ = sprintf("%.6f", $val); s/\.?0+$//; "$_ m"', + }, +); + +# tags found in 'camm' type 6 timed metadata (ref PH/4, Insta360) +%Image::ExifTool::QuickTime::camm6 = ( + PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData, + GROUPS => { 2 => 'Location' }, + FIRST_ENTRY => 0, + 0x04 => { + Name => 'GPSDateTime', + Groups => { 2 => 'Time' }, + Format => 'double', + ValueConv => q{ + my $str = ConvertUnixTime($val); + my $frac = $val - int($val); + if ($frac != 0) { + $frac = sprintf('%.6f', $frac); + $frac =~ s/^0//; + $frac =~ s/0+$//; + $str .= $frac; + } + return $str . 'Z'; + }, + PrintConv => '$self->ConvertDateTime($val)', + }, + 0x0c => { + Name => 'GPSMeasureMode', + Format => 'int32u', + PrintConv => { + 0 => 'No Measurement', + 2 => '2-Dimensional Measurement', + 3 => '3-Dimensional Measurement', + }, + }, + 0x10 => { + Name => 'GPSLatitude', + Format => 'double', + ValueConv => 'Image::ExifTool::GPS::ToDegrees($val, 1)', + PrintConv => 'Image::ExifTool::GPS::ToDMS($self, $val, 1, "N")', + }, + 0x18 => { + Name => 'GPSLongitude', + Format => 'double', + ValueConv => 'Image::ExifTool::GPS::ToDegrees($val, 1)', + PrintConv => 'Image::ExifTool::GPS::ToDMS($self, $val, 1, "E")', + }, + 0x20 => { + Name => 'GPSAltitude', + Format => 'float', + PrintConv => '$_ = sprintf("%.3f", $val); s/\.?0+$//; "$_ m"', + }, + 0x24 => { Name => 'GPSHorizontalAccuracy', Format => 'float', Notes => 'metres' }, + 0x28 => { Name => 'GPSVerticalAccuracy', Format => 'float' }, + 0x2c => { Name => 'GPSVelocityEast', Format => 'float', Notes => 'm/s' }, + 0x30 => { Name => 'GPSVelocityNorth', Format => 'float' }, + 0x34 => { Name => 'GPSVelocityUp', Format => 'float' }, + 0x38 => { Name => 'GPSSpeedAccuracy', Format => 'float' }, +); + +# tags found in 'camm' type 7 timed metadata (ref 4) +%Image::ExifTool::QuickTime::camm7 = ( + PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData, + GROUPS => { 2 => 'Location' }, + FIRST_ENTRY => 0, + 4 => { + Name => 'MagneticField', + Format => 'float[3]', + Notes => 'microtesla', + }, +); + +# preview image stored by TomTom Bandit ActionCam +%Image::ExifTool::QuickTime::PreviewInfo = ( + PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData, + FIRST_ENTRY => 0, + NOTES => 'Preview stored by TomTom Bandit ActionCam.', + 8 => { + Name => 'PreviewImage', + Groups => { 2 => 'Preview' }, + Binary => 1, + Format => 'undef[$size-8]', + }, +); + +# tags found in 'RVMI' 'gReV' timed metadata (ref PH) +%Image::ExifTool::QuickTime::RVMI_gReV = ( + PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData, + GROUPS => { 2 => 'Location' }, + FIRST_ENTRY => 0, + NOTES => 'GPS information extracted from the RVMI box of MOV videos.', + 4 => { + Name => 'GPSLatitude', + Format => 'int32s', + ValueConv => 'Image::ExifTool::GPS::ToDegrees($val/1e6, 1)', + PrintConv => 'Image::ExifTool::GPS::ToDMS($self, $val, 1, "N")', + }, + 8 => { + Name => 'GPSLongitude', + Format => 'int32s', + ValueConv => 'Image::ExifTool::GPS::ToDegrees($val/1e6, 1)', + PrintConv => 'Image::ExifTool::GPS::ToDMS($self, $val, 1, "E")', + }, + # 12 - int32s: space for altitude? (always zero in my sample) + 16 => { + Name => 'GPSSpeed', # km/h + Format => 'int16s', + ValueConv => '$val / 10', + }, + 18 => { + Name => 'GPSTrack', + Format => 'int16u', + ValueConv => '$val * 2', + }, +); + +# tags found in 'RVMI' 'sReV' timed metadata (ref PH) +%Image::ExifTool::QuickTime::RVMI_sReV = ( + PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData, + GROUPS => { 2 => 'Location' }, + FIRST_ENTRY => 0, + NOTES => q{ + G-sensor information extracted from the RVMI box of MOV videos. + }, + 4 => { + Name => 'GSensor', + Format => 'int16s[3]', # X Y Z + ValueConv => 'my @a=split " ",$val; $_/=1000 foreach @a; "@a"', + }, +); + +# tags found in 'tx3g' sbtl timed metadata (ref PH) +%Image::ExifTool::QuickTime::tx3g = ( + PROCESS_PROC => \&Process_tx3g, + GROUPS => { 2 => 'Location' }, + FIRST_ENTRY => 0, + NOTES => 'Tags extracted from the tx3g sbtl timed metadata of Yuneec drones.', + Lat => { + Name => 'GPSLatitude', + PrintConv => 'Image::ExifTool::GPS::ToDMS($self, $val, 1, "N")', + }, + Lon => { + Name => 'GPSLongitude', + PrintConv => 'Image::ExifTool::GPS::ToDMS($self, $val, 1, "E")', + }, + Alt => { + Name => 'GPSAltitude', + ValueConv => '$val =~ s/\s*m$//; $val', # remove " m" + PrintConv => '"$val m"', # add it back again + }, + Yaw => 'Yaw', + Pitch => 'Pitch', + Roll => 'Roll', + GimYaw => 'GimbalYaw', + GimPitch => 'GimbalPitch', + GimRoll => 'GimbalRoll', +); + +%Image::ExifTool::QuickTime::INSV_MakerNotes = ( + GROUPS => { 1 => 'MakerNotes', 2 => 'Camera' }, + 0x0a => 'SerialNumber', + 0x12 => 'Model', + 0x1a => 'Firmware', + 0x2a => { + Name => 'Parameters', + ValueConv => '$val =~ tr/_/ /; $val', + }, +); + +#------------------------------------------------------------------------------ +# Save information from keys in OtherSampleDesc directory for processing timed metadata +# Inputs: 0) ExifTool object ref, 1) dirInfo ref, 2) tag table ref +# Returns: 1 on success +# (ref "Timed Metadata Media" here: +# https://developer.apple.com/library/content/documentation/QuickTime/QTFF/QTFFChap3/qtff3.html) +sub SaveMetaKeys($$$) +{ + local $_; + my ($et, $dirInfo, $tagTbl) = @_; + my $dataPt = $$dirInfo{DataPt}; + my $dirLen = length $$dataPt; + return 0 unless $dirLen > 8; + my $pos = 0; + my $verbose = $$et{OPTIONS}{Verbose}; + my $oldIndent = $$et{INDENT}; + my $ee = $$et{ee}; + $ee or $ee = $$et{ee} = { }; + + $verbose and $et->VerboseDir($$dirInfo{DirName}, undef, $dirLen); + + # loop through metadata key table + while ($pos + 8 < $dirLen) { + my $size = Get32u($dataPt, $pos); + my $id = substr($$dataPt, $pos+4, 4); + my $end = $pos + $size; + $end = $dirLen if $end > $dirLen; + $pos += 8; + my ($tagID, $format, $pid); + if ($verbose) { + $pid = PrintableTagID($id,1); + $et->VPrint(0, "$oldIndent+ [Metdata Key entry, Local ID=$pid, $size bytes]\n"); + $$et{INDENT} .= '| '; + } + + while ($pos + 4 < $end) { + my $len = unpack("x${pos}N", $$dataPt); + last if $len < 8 or $pos + $len > $end; + my $tag = substr($$dataPt, $pos + 4, 4); + $pos += 8; $len -= 8; + my $val = substr($$dataPt, $pos, $len); + $pos += $len; + my $str; + if ($tag eq 'keyd') { + ($tagID = $val) =~ s/^(mdta|fiel)com\.apple\.quicktime\.//; + $tagID = "Tag_$val" unless $tagID; + ($str = $val) =~ s/(.{4})/$1 / if $verbose; + } elsif ($tag eq 'dtyp') { + next if length $val < 4; + if (length $val >= 4) { + my $ns = unpack('N', $val); + if ($ns == 0) { + length $val >= 8 or $et->Warn('Short dtyp data'), next; + $str = unpack('x4N',$val); + $format = $qtFmt{$str} || 'undef'; + } elsif ($ns == 1) { + $str = substr($val, 4); + $format = 'undef'; + } else { + $format = 'undef'; + } + $str .= " ($format)" if $verbose and defined $str; + } + } + if ($verbose > 1) { + if (defined $str) { + $str =~ tr/\x00-\x1f\x7f-\xff/./; + $str = " = $str"; + } else { + $str = ''; + } + $et->VPrint(1, $$et{INDENT}."- Tag '".PrintableTagID($tag)."' ($len bytes)$str\n"); + $et->VerboseDump(\$val); + } + } + if (defined $tagID and defined $format) { + if ($verbose) { + my $t2 = PrintableTagID($tagID); + $et->VPrint(0, "$$et{INDENT}Added Local ID $pid = $t2 ($format)\n"); + } + $$ee{'keys'}{$id} = { TagID => $tagID, Format => $format }; + } + $$et{INDENT} = $oldIndent; + } + return 1; +} + +#------------------------------------------------------------------------------ +# We found some tags for this sample, so set document number and save timing information +# Inputs: 0) ExifTool ref, 1) tag table ref, 2) sample time, 3) sample duration +sub FoundSomething($$;$$) +{ + my ($et, $tagTbl, $time, $dur) = @_; + $$et{DOC_NUM} = ++$$et{DOC_COUNT}; + $et->HandleTag($tagTbl, SampleTime => $time) if defined $time; + $et->HandleTag($tagTbl, SampleDuration => $dur) if defined $dur; +} + +#------------------------------------------------------------------------------ +# Parse textual metadata +# Inputs: 0) ExifTool ref, 1) tag table ref, 2) data ref +sub ParseText($$$) +{ + my ($et, $tagTbl, $buffPt) = @_; + while ($$buffPt =~ /\$(\w+)([^\$]*)/g) { + my ($tag, $dat) = ($1, $2); + if ($tag =~ /^[A-Z]{2}RMC$/ and $dat =~ /^,(\d{2})(\d{2})(\d+(\.\d*)?),A?,(\d*?)(\d{1,2}\.\d+),([NS]),(\d*?)(\d{1,2}\.\d+),([EW]),(\d*\.?\d*),(\d*\.?\d*),(\d{2})(\d{2})(\d+)/) { + $et->HandleTag($tagTbl, GPSLatitude => (($5 || 0) + $6/60) * ($7 eq 'N' ? 1 : -1)); + $et->HandleTag($tagTbl, GPSLongitude => (($8 || 0) + $9/60) * ($10 eq 'E' ? 1 : -1)); + if (length $11) { + $et->HandleTag($tagTbl, GPSSpeed => $11 * $knotsToKph); + $et->HandleTag($tagTbl, GPSSpeedRef => 'K'); + } + if (length $12) { + $et->HandleTag($tagTbl, GPSTrack => $11); + $et->HandleTag($tagTbl, GPSTrackRef => 'T'); + } + my $year = $15 + ($15 >= 70 ? 1900 : 2000); + my $str = sprintf('%.4d:%.2d:%.2d %.2d:%.2d:%.2dZ', $year, $14, $13, $1, $2, $3); + $et->HandleTag($tagTbl, GPSDateTime => $str); + } elsif ($tag eq 'BEGINGSENSOR' and $dat =~ /^:([-+]\d+\.\d+):([-+]\d+\.\d+):([-+]\d+\.\d+)/) { + $et->HandleTag($tagTbl, Accelerometer => "$1 $2 $3"); + } elsif ($tag eq 'TIME' and $dat =~ /^:(\d+)/) { + $et->HandleTag($tagTbl, TimeCode => $1 / ($$et{MediaTS} || 1)); + } elsif ($tag eq 'BEGIN') { + $et->HandleTag($tagTbl, Text => $dat) if length $dat; + } elsif ($tag ne 'END') { + $et->HandleTag($tagTbl, Text => "\$$tag$dat"); + } + } +} + +#------------------------------------------------------------------------------ +# Exract embedded metadata from media samples +# Inputs: 0) ExifTool ref +# Notes: Also accesses ExifTool RAF*, SET_GROUP1, HandlerType, MetaFormat, +# ee*, and avcC elements (* = must exist) +sub ProcessSamples($) +{ + my $et = shift; + my ($raf, $ee) = @$et{qw(RAF ee)}; + my ($i, $buff, $pos, $hdrLen, $hdrFmt, @time, @dur, $oldIndent); + + return unless $ee; + delete $$et{ee}; # use only once + + # only process specific types of video streams + my $type = $$et{HandlerType} || ''; + if ($type eq 'vide') { + if ($$ee{avcC}) { $type = 'avcC' } + elsif ($$ee{JPEG}) { $type = 'JPEG' } + else { return } + } + + my ($start, $size) = @$ee{qw(start size)}; +# +# determine sample start offsets from chunk offsets (stco) and sample-to-chunk table (stsc), +# and sample time/duration from time-to-sample (stts) +# + unless ($start and $size) { + return unless $size; + my ($stco, $stsc, $stts) = @$ee{qw(stco stsc stts)}; + return unless $stco and $stsc and @$stsc; + $start = [ ]; + my ($nextChunk, $iChunk) = (0, 1); + my ($chunkStart, $startChunk, $samplesPerChunk, $descIdx, $timeCount, $timeDelta, $time); + if ($stts and @$stts > 1) { + $time = 0; + $timeCount = shift @$stts; + $timeDelta = shift @$stts; + } + my $ts = $$et{MediaTS} || 1; + foreach $chunkStart (@$stco) { + if ($iChunk >= $nextChunk and @$stsc) { + ($startChunk, $samplesPerChunk, $descIdx) = @{shift @$stsc}; + $nextChunk = $$stsc[0][0] if @$stsc; + } + @$size < @$start + $samplesPerChunk and $et->WarnOnce('Sample size error'), return; + my $sampleStart = $chunkStart; + for ($i=0; ; ) { + push @$start, $sampleStart; + if (defined $time) { + until ($timeCount) { + if (@$stts < 2) { + undef $time; + last; + } + $timeCount = shift @$stts; + $timeDelta = shift @$stts; + } + push @time, $time / $ts; + push @dur, $timeDelta / $ts; + $time += $timeDelta; + --$timeCount; + } + # (eventually should use the description indices: $descIdx) + last if ++$i >= $samplesPerChunk; + $sampleStart += $$size[$#$start]; + } + ++$iChunk; + } + @$start == @$size or $et->WarnOnce('Incorrect sample start/size count'), return; + } +# +# extract and parse the sample data +# + my $tagTbl = GetTagTable('Image::ExifTool::QuickTime::Stream'); + my $verbose = $et->Options('Verbose'); + my $metaFormat = $$et{MetaFormat} || ''; + my $tell = $raf->Tell(); + + if ($verbose) { + $et->VPrint(0, "---- Extract Embedded ----\n"); + $oldIndent = $$et{INDENT}; + $$et{INDENT} = ''; + } + # get required information from avcC box if parsing video data + if ($type eq 'avcC') { + $hdrLen = (Get8u(\$$ee{avcC}, 4) & 0x03) + 1; + $hdrFmt = ($hdrLen == 4 ? 'N' : $hdrLen == 2 ? 'n' : 'C'); + require Image::ExifTool::H264; + } + # loop through all samples + for ($i=0; $i<@$start and $i<@$size; ++$i) { + + # read the sample data + my $size = $$size[$i]; + next unless $raf->Seek($$start[$i], 0) and $raf->Read($buff, $size) == $size; + + if ($type eq 'avcC') { + next if length($buff) <= $hdrLen; + # scan through all NAL units and send them to ParseH264Video() + for ($pos=0; ; ) { + my $len = unpack("x$pos$hdrFmt", $buff); + last if $pos + $hdrLen + $len > length($buff); + my $tmp = "\0\0\0\x01" . substr($buff, $pos+$hdrLen, $len); + Image::ExifTool::H264::ParseH264Video($et, \$tmp); + $pos += $hdrLen + $len; + last if $pos + $hdrLen >= length($buff); + } + next; + } + if ($verbose > 1) { + my $hdr = $$et{SET_GROUP1} ? "$$et{SET_GROUP1} Type='${type}' Format='${metaFormat}'" : "Type='${type}'"; + $et->VPrint(1, "${hdr}, Sample ".($i+1).' of '.scalar(@$start)." ($size bytes)\n"); + $et->VerboseDump(\$buff, Addr => $$start[$i]); + } + if ($type eq 'text') { + + FoundSomething($et, $tagTbl, $time[$i], $dur[$i]); + unless ($buff =~ /^\$BEGIN/) { + # remove ending "encd" box if it exists + $buff =~ s/\0\0\0\x0cencd\0\0\x01\0$// and $size -= 12; + # cameras such as the CanonPowerShotN100 store ASCII time codes with a + # leading 2-byte integer giving the length of the string + # (and chapter names start with a 2-byte integer too) + if ($size >= 2 and unpack('n',$buff) == $size - 2) { + next if $size == 2; + $buff = substr($buff,2); + } + my $val; + # check for encrypted GPS text as written by E-PRANCE B47FS camera + if ($buff =~ /^\0/ and $buff =~ /\x0a$/ and length($buff) > 5) { + # decode simple ASCII difference cipher, + # based on known value of 4th-last char = '*' + my $dif = ord('*') - ord(substr($buff, -4, 1)); + my $tmp = pack 'C*',map { $_=($_+$dif)&0xff } unpack 'C*',substr $buff,1,-1; + if ($verbose > 2) { + $et->VPrint(0, "[decrypted text]\n"); + $et->VerboseDump(\$tmp); + } + if ($tmp =~ /^(.*?)(\$[A-Z]{2}RMC.*)/s) { + ($val, $buff) = ($1, $2); + $val =~ tr/\t/ /; + $et->HandleTag($tagTbl, RawGSensor => $val) if length $val; + } + } elsif ($buff =~ /^PNDM/ and length $buff >= 20) { + # Garmin Dashcam format (actually binary, not text) + $et->HandleTag($tagTbl, GPSLatitude => Get32s(\$buff, 12) * 180/0x80000000); + $et->HandleTag($tagTbl, GPSLongitude => Get32s(\$buff, 16) * 180/0x80000000); + $et->HandleTag($tagTbl, GPSSpeed => Get16u(\$buff, 8)); + $et->HandleTag($tagTbl, GPSSpeedRef => 'M'); + next; + } + unless (defined $val) { + $et->HandleTag($tagTbl, Text => $buff); # just store any other text + next; + } + } + ParseText($et, $tagTbl, \$buff); + + } elsif ($processByMetaFormat{$type}) { + + if ($$tagTbl{$metaFormat}) { + my $tagInfo = $et->GetTagInfo($tagTbl, $metaFormat, \$buff); + if ($tagInfo) { + FoundSomething($et, $tagTbl, $time[$i], $dur[$i]); + $$et{ee} = $ee; # need ee information for 'keys' + $et->HandleTag($tagTbl, $metaFormat, undef, + DataPt => \$buff, + Base => $$start[$i], + TagInfo => $tagInfo, + ); + delete $$et{ee}; + } elsif ($metaFormat eq 'camm' and $buff =~ /^X/) { + # seen 'camm' metadata in this format (X/Y/Z acceleration and G force? + GPRMC + ?) + # "X0000.0000Y0000.0000Z0000.0000G0000.0000$GPRMC,000125,V,,,,,000.0,,280908,002.1,N*71~, 794021 \x0a" + FoundSomething($et, $tagTbl, $time[$i], $dur[$i]); + $et->HandleTag($tagTbl, Accelerometer => "$1 $2 $3 $4") if $buff =~ /X(.*?)Y(.*?)Z(.*?)G(.*?)\$/; + ParseText($et, $tagTbl, \$buff); + } + } elsif ($verbose) { + $et->VPrint(0, "Unknown meta format ($metaFormat)"); + } + + } elsif ($type eq 'gps ') { # (ie. GPSDataList tag) + + if ($buff =~ /^....freeGPS /s) { + # decode "freeGPS " data (Novatek) + ProcessFreeGPS($et, { + DataPt => \$buff, + SampleTime => $time[$i], + SampleDuration => $dur[$i], + }, $tagTbl) ; + } + + } elsif ($$tagTbl{$type}) { + + my $tagInfo = $et->GetTagInfo($tagTbl, $type, \$buff); + if ($tagInfo) { + FoundSomething($et, $tagTbl, $time[$i], $dur[$i]); + $et->HandleTag($tagTbl, $type, undef, + DataPt => \$buff, + Base => $$start[$i], + TagInfo => $tagInfo, + ); + } + } + } + if ($verbose) { + $$et{INDENT} = $oldIndent; + $et->VPrint(0, "--------------------------\n"); + } + # clean up + $raf->Seek($tell, 0); # restore original file position + $$et{DOC_NUM} = 0; + $$et{HandlerType} = $$et{HanderDesc} = ''; +} + +#------------------------------------------------------------------------------ +# Process "freeGPS " data blocks referenced by a 'gps ' (GPSDataList) atom +# Inputs: 0) ExifTool ref, 1) dirInfo ref {DataPt,SampleTime,SampleDuration}, 2) tagTable ref +# Returns: 1 on success (or 0 on unrecognized or "measurement-void" GPS data) +# Notes: +# - also see ProcessFreeGPS2() below for processing of other types of freeGPS blocks +sub ProcessFreeGPS($$$) +{ + my ($et, $dirInfo, $tagTbl) = @_; + my $dataPt = $$dirInfo{DataPt}; + my $dirLen = length $$dataPt; + my ($yr, $mon, $day, $hr, $min, $sec, $stat, $lbl); + my ($lat, $latRef, $lon, $lonRef, $spd, $trk, $alt, @acc, @xtra); + + return 0 if $dirLen < 92; + + if (substr($$dataPt,12,1) eq "\x05") { + + # decode encrypted ASCII-based GPS (DashCam Azdome GS63H, ref 5) + # header looks like this in my sample: + # 0000: 00 00 80 00 66 72 65 65 47 50 53 20 05 01 00 00 [....freeGPS ....] + # 0010: 01 03 aa aa f2 e1 f0 ee 54 54 98 9a 9b 92 9a 93 [........TT......] + # 0020: 98 9e 98 98 9e 93 98 92 a6 9f 9f 9c 9d ed fa 8a [................] + my $n = $dirLen - 18; + $n = 0x101 if $n > 0x101; + my $buf2 = pack 'C*', map { $_ ^ 0xaa } unpack 'C*', substr($$dataPt,18,$n); + if ($et->Options('Verbose') > 1) { + $et->VPrint(1, '[decrypted freeGPS data]'); + $et->VerboseDump(\$buf2); + } + # (extract longitude as 9 digits, not 8, ref PH) + return 0 unless $buf2 =~ /^.{8}(\d{4})(\d{2})(\d{2})(\d{2})(\d{2})(\d{2}).(.{15})([NS])(\d{8})([EW])(\d{9})(\d{8})/s; + ($yr,$mon,$day,$hr,$min,$sec,$lbl,$latRef,$lat,$lonRef,$lon,$spd) = ($1,$2,$3,$4,$5,$6,$7,$8,$9/1e4,$10,$11/1e4,$12); + $spd += 0; # remove leading 0's + $lbl =~ s/\0.*//s; $lbl =~ s/\s+$//; # truncate at null and remove trailing spaces + push @xtra, UserLabel => $lbl if length $lbl; + # extract accelerometer data (ref PH) + @acc = ($1/100,$2/100,$3/100) if $buf2 =~ /^.{173}([-+]\d{3})([-+]\d{3})([-+]\d{3})/s; + + } elsif ($$dataPt =~ /^.{52}(\d{4})(\d{2})(\d{2})(\d{2})(\d{2})(\d{2})/s) { + + # decode NMEA-format GPS data (NextBase 512GW dashcam, ref PH) + # header looks like this in my sample: + # 0000: 00 00 80 00 66 72 65 65 47 50 53 20 40 01 00 00 [....freeGPS @...] + # 0010: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 [................] + # 0020: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 [................] + push @xtra, CameraDateTime => "$1:$2:$3 $4:$5:$6"; + if ($$dataPt =~ /\$[A-Z]{2}RMC,(\d{2})(\d{2})(\d+(\.\d*)?),A?,(\d+\.\d+),([NS]),(\d+\.\d+),([EW]),(\d*\.?\d*),(\d*\.?\d*),(\d{2})(\d{2})(\d+)/s) { + ($lat,$latRef,$lon,$lonRef) = ($5,$6,$7,$8); + $yr = $13 + ($13 >= 70 ? 1900 : 2000); + ($mon,$day,$hr,$min,$sec) = ($12,$11,$1,$2,$3); + $spd = $9 * $knotsToKph if length $9; + $trk = $10 if length $10; + } + if ($$dataPt =~ /\$[A-Z]{2}GGA,(\d{2})(\d{2})(\d+(\.\d*)?),(\d+\.\d+),([NS]),(\d+\.\d+),([EW]),[1-6]?,(\d+)?,(\.\d+|\d+\.?\d*)?,(-?\d+\.?\d*)?,M?/s) { + ($hr,$min,$sec,$lat,$latRef,$lon,$lonRef) = ($1,$2,$3,$5,$6,$7,$8) unless defined $yr; + $alt = $11; + unshift @xtra, GPSSatellites => $9; + unshift @xtra, GPSDOP => $10; + } + if (defined $lat) { + # extract accelerometer readings if GPS was valid + @acc = unpack('x68V3', $$dataPt); + # change to signed integer and divide by 256 + map { $_ = $_ - 4294967296 if $_ >= 0x80000000; $_ /= 256 } @acc; + } + + } else { + + # decode binary GPS format (Viofo A119S, ref 2) + # header looks like this in my sample: + # 0000: 00 00 80 00 66 72 65 65 47 50 53 20 4c 00 00 00 [....freeGPS L...] + # 0010: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 [................] + # 0020: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 [................] + # (records are same structure as Type 3 Novatek GPS in ProcessFreeGPS2() below) + ($hr,$min,$sec,$yr,$mon,$day,$stat,$latRef,$lonRef,$lat,$lon,$spd,$trk) = + unpack('x48V6a1a1a1x1V4', $$dataPt); + # ignore invalid fixes + return 0 unless $stat eq 'A' and ($latRef eq 'N' or $latRef eq 'S') and + ($lonRef eq 'E' or $lonRef eq 'W'); + ($lat,$lon,$spd,$trk) = unpack 'f*', pack 'L*', $lat, $lon, $spd, $trk; + $yr += 2000 if $yr < 2000; + $spd *= $knotsToKph; # convert speed to km/h + # ($trk is not confirmed; may be GPSImageDirection, ref PH) + } +# +# save tag values extracted by above code +# + FoundSomething($et, $tagTbl, $$dirInfo{SampleTime}, $$dirInfo{SampleDuration}); + # lat/long are in DDDMM.MMMM format + my $deg = int($lat / 100); + $lat = $deg + ($lat - $deg * 100) / 60; + $deg = int($lon / 100); + $lon = $deg + ($lon - $deg * 100) / 60; + $sec = '0' . $sec unless $sec =~ /^\d{2}/; # pad integer part of seconds to 2 digits + if (defined $yr) { + my $time = sprintf('%.4d:%.2d:%.2d %.2d:%.2d:%sZ',$yr,$mon,$day,$hr,$min,$sec); + $et->HandleTag($tagTbl, GPSDateTime => $time); + } elsif (defined $hr) { + my $time = sprintf('%.2d:%.2d:%sZ',$hr,$min,$sec); + $et->HandleTag($tagTbl, GPSTimeStamp => $time); + } + $et->HandleTag($tagTbl, GPSLatitude => $lat * ($latRef eq 'S' ? -1 : 1)); + $et->HandleTag($tagTbl, GPSLongitude => $lon * ($lonRef eq 'W' ? -1 : 1)); + $et->HandleTag($tagTbl, GPSAltitude => $alt) if defined $alt; + if (defined $spd) { + $et->HandleTag($tagTbl, GPSSpeed => $spd); + $et->HandleTag($tagTbl, GPSSpeedRef => 'K'); + } + if (defined $trk) { + $et->HandleTag($tagTbl, GPSTrack => $trk); + $et->HandleTag($tagTbl, GPSTrackRef => 'T'); + } + while (@xtra) { + my $tag = shift @xtra; + $et->HandleTag($tagTbl, $tag => shift @xtra); + } + $et->HandleTag($tagTbl, Accelerometer => \@acc) if @acc; + return 1; +} + +#------------------------------------------------------------------------------ +# Process "freeGPS " data blocks _not_ referenced by a 'gps ' atom +# Inputs: 0) ExifTool ref, 1) dirInfo ref {DataPt,DataPos,DirLen}, 2) tagTable ref +# Returns: 1 on success +# Notes: +# - also see ProcessFreeGPS() above +sub ProcessFreeGPS2($$$) +{ + my ($et, $dirInfo, $tagTbl) = @_; + my $dataPt = $$dirInfo{DataPt}; + my $dirLen = $$dirInfo{DirLen}; + my ($yr, $mon, $day, $hr, $min, $sec, $pos); + my ($lat, $latRef, $lon, $lonRef, $spd, $trk, $alt, $ddd, $unk); + + return 0 if $dirLen < 82; # minimum size of block with a single GPS record + + if (substr($$dataPt,0x45,3) eq 'ATC') { + + # header looks like this: (sample 1) + # 0000: 00 00 80 00 66 72 65 65 47 50 53 20 38 06 00 00 [....freeGPS 8...] + # 0010: 49 51 53 32 30 31 33 30 33 30 36 42 00 00 00 00 [IQS20130306B....] + # 0020: 4d 61 79 20 31 35 20 32 30 31 35 2c 20 31 39 3a [May 15 2015, 19:] + # (sample 2) + # 0000: 00 00 80 00 66 72 65 65 47 50 53 20 4c 06 00 00 [....freeGPS L...] + # 0010: 32 30 31 33 30 33 31 38 2e 30 31 00 00 00 00 00 [20130318.01.....] + # 0020: 4d 61 72 20 31 38 20 32 30 31 33 2c 20 31 34 3a [Mar 18 2013, 14:] + + my ($recPos, $lastRecPos, $foundNew); + my $verbose = $et->Options('Verbose'); + my $dataPos = $$dirInfo{DataPos}; + my $then = $$et{FreeGPS2}{Then}; + $then or $then = $$et{FreeGPS2}{Then} = [ (0) x 6 ]; + # Loop through records in the ATC-type GPS block until we find the most recent. + # If we have already found one, then we only need to check the first record + # (in case the buffer wrapped around), and the record after the position of + # the last record we found, because the others will be old. Odd, but this + # is the way it is done... I have only seen one new 52-byte record in the + # entire 32 kB block, but the entire device ring buffer (containing 30 + # entries in my samples) is stored every time. The code below allows for + # the possibility of missing blocks and multiple new records in a single + # block, but I have never seen this. Note that there may be some earlier + # GPS records at the end of the first block that we will miss decoding, but + # these should (I believe) be before the start of the video +ATCRec: for ($recPos = 0x30; $recPos + 52 < $dirLen; $recPos += 52) { + + my $a = substr($$dataPt, $recPos, 52); # isolate a single record + # decrypt record + my @a = unpack('C*', $a); + my ($key1, $key2) = @a[0x14, 0x1c]; + $a[$_] ^= $key1 foreach 0x00..0x14, 0x18..0x1b; + $a[$_] ^= $key2 foreach 0x1c, 0x20..0x32; + my $b = pack 'C*', @a; + # unpack and validate date/time + my @now = unpack 'x13C3x28vC2', $b; # (H-1,M,S,Y,m,d) + $now[0] = ($now[0] + 1) & 0xff; # increment hour + my $i; + for ($i=0; $i<@dateMax; ++$i) { + next if $now[$i] <= $dateMax[$i]; + $et->WarnOnce('Invalid GPS date/time'); + next ATCRec; # ignore this record + } + # look for next ATC record in temporal sequence + foreach $i (3..5, 0..2) { + if ($now[$i] < $$then[$i]) { + last ATCRec if $foundNew; + last; + } + next if $now[$i] == $$then[$i]; + # we found a more recent record -- extract it and remember its location + if ($verbose) { + $et->VPrint(2, " + [encrypted GPS record]\n"); + $et->VerboseDump(\$a, DataPos => $dataPos + $recPos); + $et->VPrint(2, " + [decrypted GPS record]\n"); + $et->VerboseDump(\$b); + #my @v = unpack 'H8VVC4V!CA3V!CA3VvvV!vCCCCH4', $b; + #$et->VPrint(2, " + [unpacked: @v]\n"); + # values unpacked above (ref PH): + # 0) 0x00 4 bytes - byte 0=1, 1=counts to 255, 2=record index, 3=0 (ref 3) + # 1) 0x04 4 bytes - int32u: bits 0-4=day, 5-8=mon, 9-19=year (ref 3) + # 2) 0x08 4 bytes - int32u: bits 0-5=sec, 6-11=min, 12-16=hour (ref 3) + # 3) 0x0c 1 byte - seen values of 0,1,2 - GPS status maybe? + # 4) 0x0d 1 byte - hour minus 1 + # 5) 0x0e 1 byte - minute + # 6) 0x0f 1 byte - second + # 7) 0x10 4 bytes - int32s latitude * 1e7 + # 8) 0x14 1 byte - always 0 (used for decryption) + # 9) 0x15 3 bytes - always "ATC" + # 10) 0x18 4 bytes - int32s longitude * 1e7 + # 11) 0x1c 1 byte - always 0 (used for decryption) + # 12) 0x1d 3 bytes - always "001" + # 13) 0x20 4 bytes - int32s speed * 100 (m/s) + # 14) 0x24 2 bytes - int16u heading * 100 (-180 to 180 deg) + # 15) 0x26 2 bytes - always zero + # 16) 0x28 4 bytes - int32s altitude * 1000 (ref 3) + # 17) 0x2c 2 bytes - int16u year + # 18) 0x2e 1 byte - month + # 19) 0x2f 1 byte - day + # 20) 0x30 1 byte - unknown + # 21) 0x31 1 byte - always zero + # 22) 0x32 2 bytes - checksum ? + } + @$then = @now; + $$et{DOC_NUM} = ++$$et{DOC_COUNT}; + $trk = Get16s(\$b, 0x24) / 100; + $trk += 360 if $trk < 0; + my $time = sprintf('%.4d:%.2d:%.2d %.2d:%.2d:%.2dZ', @now[3..5, 0..2]); + $et->HandleTag($tagTbl, GPSDateTime => $time); + $et->HandleTag($tagTbl, GPSLatitude => Get32s(\$b, 0x10) / 1e7); + $et->HandleTag($tagTbl, GPSLongitude => Get32s(\$b, 0x18) / 1e7); + $et->HandleTag($tagTbl, GPSSpeed => Get32s(\$b, 0x20) / 100 * $mpsToKph); + $et->HandleTag($tagTbl, GPSSpeedRef => 'K'); + $et->HandleTag($tagTbl, GPSTrack => $trk); + $et->HandleTag($tagTbl, GPSTrackRef => 'T'); + $et->HandleTag($tagTbl, GPSAltitude => Get32s(\$b, 0x28) / 1000); + $lastRecPos = $recPos; + $foundNew = 1; + # don't skip to location of previous recent record in ring buffer + # since we found a more recent record here + delete $$et{FreeGPS2}{RecentRecPos}; + last; + } + # skip older records + my $recentRecPos = $$et{FreeGPS2}{RecentRecPos}; + $recPos = $recentRecPos if $recentRecPos and $recPos < $recentRecPos; + } + # save position of most recent record (needed when parsing the next freeGPS block) + $$et{FreeGPS2}{RecentRecPos} = $lastRecPos; + return 1; + + } elsif ($$dataPt =~ /^.{60}A\0.{10}([NS])\0.{14}([EW])\0/s) { + + # header looks like this in my sample: + # 0000: 00 00 80 00 66 72 65 65 47 50 53 20 08 01 00 00 [....freeGPS ....] + # 0010: 32 30 31 33 30 38 31 35 2e 30 31 00 00 00 00 00 [20130815.01.....] + # 0020: 4a 75 6e 20 31 30 20 32 30 31 37 2c 20 31 34 3a [Jun 10 2017, 14:] + + # Type 2 (ref PH): + # 0x30 - int32u hour + # 0x34 - int32u minute + # 0x38 - int32u second + # 0x3c - int32u GPS status ('A' or 'V') + # 0x40 - double latitude (DDMM.MMMMMM) + # 0x48 - int32u latitude ref ('N' or 'S') + # 0x50 - double longitude (DDMM.MMMMMM) + # 0x58 - int32u longitude ref ('E' or 'W') + # 0x60 - double speed (knots) + # 0x68 - double heading (deg) + # 0x70 - int32u year - 2000 + # 0x74 - int32u month + # 0x78 - int32u day + ($latRef, $lonRef) = ($1, $2); + ($hr,$min,$sec,$yr,$mon,$day) = unpack('x48V3x52V3', $$dataPt); + $lat = GetDouble($dataPt, 0x40); + $lon = GetDouble($dataPt, 0x50); + $spd = GetDouble($dataPt, 0x60) * $knotsToKph; + $trk = GetDouble($dataPt, 0x68); + + } elsif ($$dataPt =~ /^.{72}A([NS])([EW])/s) { + + # Type 3 (Novatek GPS, ref 2): (in case it wasn't decoded via 'gps ' atom) + # 0x30 - int32u hour + # 0x34 - int32u minute + # 0x38 - int32u second + # 0x3c - int32u year - 2000 + # 0x40 - int32u month + # 0x44 - int32u day + # 0x48 - int8u GPS status ('A' or 'V') + # 0x49 - int8u latitude ref ('N' or 'S') + # 0x4a - int8u longitude ref ('E' or 'W') + # 0x4b - 0 + # 0x4c - float latitude (DDMM.MMMMMM) + # 0x50 - float longitude (DDMM.MMMMMM) + # 0x54 - float speed (knots) + # 0x58 - float heading (deg) + # Type 3b, same as above for 0x30-0x4a (ref PH) + # 0x4c - int32s latitude (decimal degrees * 1e7) + # 0x50 - int32s longitude (decimal degrees * 1e7) + # 0x54 - int32s speed (m/s * 100) + # 0x58 - float altitude (m * 1000, NC) + ($latRef, $lonRef) = ($1, $2); + ($hr,$min,$sec,$yr,$mon,$day) = unpack('x48V6', $$dataPt); + if (substr($$dataPt, 16, 3) eq 'IQS') { + # Type 3b (ref PH) + # header looks like this in my sample: + # 0000: 00 00 80 00 66 72 65 65 47 50 53 20 4c 00 00 00 [....freeGPS L...] + # 0010: 49 51 53 5f 41 37 5f 32 30 31 35 30 34 31 37 00 [IQS_A7_20150417.] + # 0020: 4d 61 72 20 32 39 20 32 30 31 37 2c 20 31 36 3a [Mar 29 2017, 16:] + $ddd = 1; + $lat = abs Get32s($dataPt, 0x4c) / 1e7; + $lon = abs Get32s($dataPt, 0x50) / 1e7; + $spd = Get32s($dataPt, 0x54) / 100 * $mpsToKph; + $alt = GetFloat($dataPt, 0x58) / 1000; # (NC) + } else { + # Type 3 (ref 2) + # (no sample with this format) + $lat = GetFloat($dataPt, 0x4c); + $lon = GetFloat($dataPt, 0x50); + $spd = GetFloat($dataPt, 0x54) * $knotsToKph; + $trk = GetFloat($dataPt, 0x58); + } + + } else { + + # (look for binary GPS as stored by NextBase 512G, ref PH) + # header looks like this in my sample: + # 0000: 00 00 80 00 66 72 65 65 47 50 53 20 78 01 00 00 [....freeGPS x...] + # 0010: 78 2e 78 78 00 00 00 00 00 00 00 00 00 00 00 00 [x.xx............] + # 0020: 30 30 30 30 30 00 00 00 00 00 00 00 00 00 00 00 [00000...........] + + # followed by a number of 32-byte records in this format (big endian!): + # 0x30 - int16u unknown (seen: 0x24 0x53 = "$S") + # 0x32 - int16u speed (m/s * 100) + # 0x34 - int16s heading (deg * 100) (or GPSImgDirection?) + # 0x36 - int16u year + # 0x38 - int8u month + # 0x39 - int8u day + # 0x3a - int8u hour + # 0x3b - int8u min + # 0x3c - int16u sec * 10 + # 0x3e - int8u unknown (seen: 2) + # 0x3f - int32s latitude (decimal degrees * 1e7) + # 0x43 - int32s longitude (decimal degrees * 1e7) + # 0x47 - int8u unknown (seen: 16) + # 0x48-0x4f - all zero + for ($pos=0x32; ; ) { + ($spd,$trk,$yr,$mon,$day,$hr,$min,$sec,$unk,$lat,$lon) = unpack "x${pos}nnnCCCCnCNN", $$dataPt; + # validate record using date/time + last if $yr < 2000 or $yr > 2200 or + $mon < 1 or $mon > 12 or + $day < 1 or $day > 31 or + $hr > 59 or $min > 59 or $sec > 600; + # change lat/lon to signed integer and divide by 1e7 + map { $_ = $_ - 4294967296 if $_ >= 0x80000000; $_ /= 1e7 } $lat, $lon; + $trk -= 0x10000 if $trk >= 0x8000; # make it signed + $trk /= 100; + $trk += 360 if $trk < 0; + my $time = sprintf("%.4d:%.2d:%.2d %.2d:%.2d:%04.1fZ", $yr, $mon, $day, $hr, $min, $sec/10); + $$et{DOC_NUM} = ++$$et{DOC_COUNT}; + $et->HandleTag($tagTbl, GPSDateTime => $time); + $et->HandleTag($tagTbl, GPSLatitude => $lat); + $et->HandleTag($tagTbl, GPSLongitude => $lon); + $et->HandleTag($tagTbl, GPSSpeed => $spd / 100 * $mpsToKph); + $et->HandleTag($tagTbl, GPSSpeedRef => 'K'); + $et->HandleTag($tagTbl, GPSTrack => $trk); + $et->HandleTag($tagTbl, GPSTrackRef => 'T'); + last if $pos += 0x20 > length($$dataPt) - 0x1e; + } + return $$et{DOC_NUM} ? 1 : 0; # return 0 if nothing extracted + } +# +# save tag values extracted by above code +# + return 0 if $mon < 1 or $mon > 12; # quick sanity check + $$et{DOC_NUM} = ++$$et{DOC_COUNT}; + $yr += 2000 if $yr < 2000; + my $time = sprintf('%.4d:%.2d:%.2d %.2d:%.2d:%.2dZ', $yr, $mon, $day, $hr, $min, $sec); + # convert from DDMM.MMMMMM to DD.DDDDDD format if necessary + unless ($ddd) { + my $deg = int($lat / 100); + $lat = $deg + ($lat - $deg * 100) / 60; + $deg = int($lon / 100); + $lon = $deg + ($lon - $deg * 100) / 60; + } + $et->HandleTag($tagTbl, GPSDateTime => $time); + $et->HandleTag($tagTbl, GPSLatitude => $lat * ($latRef eq 'S' ? -1 : 1)); + $et->HandleTag($tagTbl, GPSLongitude => $lon * ($lonRef eq 'W' ? -1 : 1)); + $et->HandleTag($tagTbl, GPSSpeed => $spd); # (now in km/h) + $et->HandleTag($tagTbl, GPSSpeedRef => 'K'); + if (defined $trk) { + $et->HandleTag($tagTbl, GPSTrack => $trk); + $et->HandleTag($tagTbl, GPSTrackRef => 'T'); + } + if (defined $alt) { + $et->HandleTag($tagTbl, GPSAltitude => $alt); + } + return 1; +} + +#------------------------------------------------------------------------------ +# Extract embedded information referenced from a track +# Inputs: 0) ExifTool ref, 1) tag name, 2) data ref +sub ParseTag($$$) +{ + local $_; + my ($et, $tag, $dataPt) = @_; + my $dataLen = length $$dataPt; + + if ($tag eq 'stsz' or $tag eq 'stz2' and $dataLen > 12) { + # read the sample sizes + my ($sz, $num) = unpack('x4N2', $$dataPt); + my $size = $$et{ee}{size} = [ ]; + if ($tag eq 'stsz') { + if ($sz == 0) { + @$size = ReadValue($dataPt, 12, 'int32u', $num, $dataLen-12); + } else { + @$size = ($sz) x $num; + } + } else { + $sz &= 0xff; + if ($sz == 4) { + my @tmp = ReadValue($dataPt, 12, 'int8u', int(($num+1)/2), $dataLen-12); + foreach (@tmp) { + push @$size, $_ >> 4; + push @$size, $_ & 0xff; + } + } elsif ($sz == 8 || $sz == 16) { + @$size = ReadValue($dataPt, 12, "int${sz}u", $num, $dataLen-12); + } + } + } elsif ($tag eq 'stco' or $tag eq 'co64' and $dataLen > 8) { + # read the chunk offsets + my $num = unpack('x4N', $$dataPt); + my $stco = $$et{ee}{stco} = [ ]; + @$stco = ReadValue($dataPt, 8, $tag eq 'stco' ? 'int32u' : 'int64u', $num, $dataLen-8); + } elsif ($tag eq 'stsc' and $dataLen > 8) { + # read the sample-to-chunk box + my $num = unpack('x4N', $$dataPt); + if ($dataLen >= 8 + $num * 12) { + my ($i, @stsc); + for ($i=0; $i<$num; ++$i) { + # list of (first-chunk, samples-per-chunk, sample-description-index) + push @stsc, [ unpack('x'.(8+$i*12).'N3', $$dataPt) ]; + } + $$et{ee}{stsc} = \@stsc; + } + } elsif ($tag eq 'stts' and $dataLen > 8) { + # read the time-to-sample box + my $num = unpack('x4N', $$dataPt); + if ($dataLen >= 8 + $num * 8) { + $$et{ee}{stts} = [ unpack('x8N'.($num*2), $$dataPt) ]; + } + } elsif ($tag eq 'avcC') { + # read the AVC compressor configuration + $$et{ee}{avcC} = $$dataPt if $dataLen >= 7; # (minimum length is 7) + } elsif ($tag eq 'JPEG') { + $$et{ee}{JPEG} = $$dataPt; + } elsif ($tag eq 'gps ' and $dataLen > 8) { + # decode Novatek 'gps ' box (ref 2) + my $num = Get32u($dataPt, 4); + $num = int(($dataLen - 8) / 8) if $num * 8 + 8 > $dataLen; + my $start = $$et{ee}{start} = [ ]; + my $size = $$et{ee}{size} = [ ]; + my $i; + for ($i=0; $i<$num; ++$i) { + push @$start, Get32u($dataPt, 8 + $i * 8); + push @$size, Get32u($dataPt, 12 + $i * 8); + } + $$et{HandlerType} = $tag; # fake handler type + ProcessSamples($et); # we have all we need to process sample data now + } +} + +#------------------------------------------------------------------------------ +# Process Yuneec 'tx3g' sbtl metadata (ref PH) +# Inputs: 0) ExifTool object ref, 1) dirInfo ref, 2) tag table ref +# Returns: 1 on success +sub Process_tx3g($$$) +{ + my ($et, $dirInfo, $tagTablePtr) = @_; + my $dataPt = $$dirInfo{DataPt}; + return 0 if length $$dataPt < 2; + pos($$dataPt) = 2; # skip 2-byte length word + $et->HandleTag($tagTablePtr, $1, $2) while $$dataPt =~ /(\w+):([^:]*[^:\s])(\s|$)/sg; + return 1; +} + +#------------------------------------------------------------------------------ +# Process QuickTime 'mebx' timed metadata +# Inputs: 0) ExifTool ref, 1) dirInfo ref, 2) tag table ref +# Returns: 1 on success +# - uses tag ID keys stored in the ExifTool ee data member by a previous call to SaveMetaKeys +sub Process_mebx($$$) +{ + my ($et, $dirInfo, $tagTbl) = @_; + my $ee = $$et{ee} or return 0; + return 0 unless $$ee{'keys'}; + my $dataPt = $$dirInfo{DataPt}; + + # parse using information from 'keys' table (eg. Apple iPhone7+ hevc 'Core Media Data Handler') + $et->VerboseDir('mebx', undef, length $$dataPt); + my $pos = 0; + while ($pos + 8 < length $$dataPt) { + my $len = Get32u($dataPt, $pos); + last if $len < 8 or $pos + $len > length $$dataPt; + my $id = substr($$dataPt, $pos+4, 4); + my $info = $$ee{'keys'}{$id}; + if ($info) { + my $tag = $$info{TagID}; + unless ($$tagTbl{$tag}) { + next unless $tag =~ /^[-\w.]+$/; + # create info for tags with reasonable id's + my $name = $tag; + $name =~ s/[-.](.)/\U$1/g; + AddTagToTable($tagTbl, $tag, { Name => ucfirst($name) }); + } + my $val = ReadValue($dataPt, $pos+8, $$info{Format}, undef, $len-8); + $et->HandleTag($tagTbl, $tag, $val, + DataPt => $dataPt, + Base => $$dirInfo{Base}, + Start => $pos + 8, + Size => $len - 8, + ); + } else { + $et->WarnOnce('No key information for mebx ID ' . PrintableTagID($id,1)); + } + $pos += $len; + } + return 1; +} + +#------------------------------------------------------------------------------ +# Process TomTom Bandit Action Cam TTAD atom (ref PH) +# Inputs: 0) ExifTool object ref, 1) dirInfo ref, 2) tag table ref +# Returns: 1 on success +my %ttLen = ( # expected lengths of TomTom records + 0 => 12, # (records may be longer sometimes -- don't know why) + 1 => 4, + 2 => 12, + 3 => 12, + # (haven't seen a record 4 yet) + 5 => 92, +); +sub ProcessTTAD($$$) +{ + my ($et, $dirInfo, $tagTbl) = @_; + my $dataPt = $$dirInfo{DataPt}; + my $dirLen = $$dirInfo{DirLen}; + my $pos = 76; + + return 0 if $dirLen < $pos; + + $et->VerboseDir('TTAD', undef, $dirLen); + SetByteOrder('II'); + + my $found = 0; + my $lastTime = 0; + my $lastGoodPos = $pos; + my $ee = $et->Options('ExtractEmbedded'); + my $unknown = $et->Options('Unknown'); + + for (;;) { + # look for next sync byte + pos($$dataPt) = $pos; + last unless $$dataPt =~ /\xff/g; + $pos = pos($$dataPt); + last if $pos + 5 >= $dirLen; + if ($pos - $lastGoodPos > 0x100) { + $et->Warn('Unrecognized or bad TTAD data', 1); + last; + } + my ($tm, $type) = unpack 'VC', substr($$dataPt, $pos, 5); + next unless $ttLen{$type} and $tm >= $lastTime and $tm <= $lastTime + 1000; + $lastTime = $tm; + $pos += 5; + last if $pos + $ttLen{$type} > $dirLen; + $lastGoodPos = $pos; + unless ($ee) { + $found & (1 << $type) and $pos += $ttLen{$type}, next; + $found |= (1 << $type); + } + if ($type == 0 or $type == 3) { + # (these are both just educated guesses - PH) + FoundSomething($et, $tagTbl, Get32u($dataPt,$pos-5) / 1000); + my @a = map { Get32s($dataPt,$pos+4*$_) / 1000 } 0..2; + $et->HandleTag($tagTbl, ($type ? 'Accelerometer' : 'AngularVelocity') => "@a"); + } elsif ($type == 5) { + # example records unpacked with 'dVddddVddddv*' + # datetime ? spd ele lat lon ? trk ? ? ? ? ? ? ? ? ? + # 2019:03:05 07:52:58.999Z 3 0.02 242 48.0254203 7.8497567 0 45.69 13.34 17.218 17.218 0 0 0 32760 5 0 + # 2019:03:05 07:52:59.999Z 3 0.14 242 48.0254203 7.8497567 0 45.7 12.96 15.662 15.662 0 0 0 32760 5 0 + # 2019:03:05 07:53:00.999Z 3 0.67 243.78 48.0254584 7.8497907 0 50.93 9.16 10.84 10.84 0 0 0 32760 5 0 + # (I think "5" may be the number of satellites. seen: 5,6,7 - PH) + FoundSomething($et, $tagTbl, Get32u($dataPt,$pos-5) / 1000); + my $tm = GetDouble($dataPt, $pos); + $et->HandleTag($tagTbl, GPSDateTime => Image::ExifTool::ConvertUnixTime($tm,undef,3).'Z'); + $et->HandleTag($tagTbl, GPSAltitude => GetDouble($dataPt, $pos+0x14)); + $et->HandleTag($tagTbl, GPSLatitude => GetDouble($dataPt, $pos+0x1c)); + $et->HandleTag($tagTbl, GPSLongitude => GetDouble($dataPt, $pos+0x24)); + $et->HandleTag($tagTbl, GPSSpeed => GetDouble($dataPt, $pos+0x0c) * $mpsToKph); + $et->HandleTag($tagTbl, GPSSpeedRef => 'K'); + $et->HandleTag($tagTbl, GPSTrack => GetDouble($dataPt, $pos+0x30)); + $et->HandleTag($tagTbl, GPSTrackRef => 'T'); + if ($unknown) { + my @a = map { GetDouble($dataPt, $pos+0x38+8*$_) } 0..2; + $et->HandleTag($tagTbl, Unknown03 => "@a"); + } + } elsif ($type < 3) { + # as yet unknown: + # 1 - int32s[1]? (values around 98k) + # 2 - int32s[3] (values like "806 8124 4323" -- probably something * 1000 again) + if ($unknown) { + FoundSomething($et, $tagTbl, Get32u($dataPt,$pos-5) / 1000); + my $n = $type == 1 ? 0 : 2; + my @a = map { Get32s($dataPt,$pos+4*$_) } 0..$n; + $et->HandleTag($tagTbl, "Unknown0$type" => "@a"); + } + } else { + $et->WarnOnce("Unknown TTAD record type $type",1); + } + if (not $ee and ($found & 0x29) == 0x29) { # without -ee, stop after we find types 0,3,5 + $et->WarnOnce('The ExtractEmbedded option may find more tags in the movie data',3); + last; + } + $pos += $ttLen{$type}; + } + SetByteOrder('MM'); + delete $$et{DOC_NUM}; + return 1; +} + +#------------------------------------------------------------------------------ +# Extract information from Insta360 trailer +# Inputs: 0) ExifTool ref +sub ProcessINSVTrailer($) +{ + local $_; + my $et = shift; + my $raf = $$et{RAF}; + my $buff; + + return unless $raf->Seek(-78, 2) and $raf->Read($buff, 78) == 78 and + substr($buff,-32) eq "8db42d694ccc418790edff439fe026bf"; # check magic number + + my $tagTbl = GetTagTable('Image::ExifTool::QuickTime::Stream'); + my $fileEnd = $raf->Tell(); + my $trailerLen = unpack('x38V', $buff); + my $trailerStart = $fileEnd - $trailerLen; + my $unknown = $et->Options('Unknown'); + my $verbose = $et->Options('Verbose'); + my $pos = $fileEnd - 78; + my ($i, $p); + SetByteOrder('II'); + # loop through all records in the trailer, from last to first + for (;;) { + my ($id, $len) = unpack('vV', $buff); + ($pos -= $len) < $trailerStart and last; + $raf->Seek($pos, 0) or last; + $raf->Read($buff, $len) == $len or last; + if ($verbose) { + $et->VPrint(0, sprintf("INSV Record 0x%x (offset 0x%x, %d bytes):\n", $id, $pos, $len)); + $et->VerboseDump(\$buff); + } + my $dlen = $insvDataLen{$id}; + if ($dlen) { + $len % $dlen and $et->Warn(sprintf('Unexpected INSV record 0x%x length',$id)), last; + if ($id == 0x300) { + for ($p=0; $p<$len; $p+=$dlen) { + $$et{DOC_NUM} = ++$$et{DOC_COUNT}; + my @a = map { GetDouble(\$buff, $p + 8 * $_) } 1..6; + $et->HandleTag($tagTbl, TimeCode => sprintf('%.3f', Get64u(\$buff, $p) / 1000)); + $et->HandleTag($tagTbl, Accelerometer => "@a[0..2]"); # (NC) + $et->HandleTag($tagTbl, AngularVelocity => "@a[3..5]"); # (NC) + } + } elsif ($id == 0x400 and $unknown) { + for ($p=0; $p<$len; $p+=$dlen) { + $$et{DOC_NUM} = ++$$et{DOC_COUNT}; + $et->HandleTag($tagTbl, TimeCode => sprintf('%.3f', Get64u(\$buff, $p) / 1000)); + $et->HandleTag($tagTbl, Unknown01 => GetDouble(\$buff, $p + 8)); + } + } elsif ($id == 0x700) { + for ($p=0; $p<$len; $p+=$dlen) { + my $tmp = substr($buff, $p, $dlen); + my @a = unpack('VVvaa8aa8aa8a8a8', $tmp); + next unless $a[3] eq 'A'; # (ignore void fixes) + last unless ($a[5] eq 'N' or $a[5] eq 'S') and # (quick validation) + ($a[7] eq 'E' or $a[7] eq 'W'); + $$et{DOC_NUM} = ++$$et{DOC_COUNT}; + $a[$_] = GetDouble(\$a[$_], 0) foreach 4,6,8,9,10; + $a[4] *= -abs($a[4]) if $a[5] eq 'S'; # (abs just in case it was already signed) + $a[6] *= -abs($a[6]) if $a[7] eq 'W'; + $et->HandleTag($tagTbl, GPSDateTime => Image::ExifTool::ConvertUnixTime($a[0]) . 'Z'); + $et->HandleTag($tagTbl, GPSLatitude => $a[4]); + $et->HandleTag($tagTbl, GPSLongitude => $a[6]); + $et->HandleTag($tagTbl, GPSSpeed => $a[8] * $mpsToKph); + $et->HandleTag($tagTbl, GPSSpeedRef => 'K'); + $et->HandleTag($tagTbl, GPSTrack => $a[9]); + $et->HandleTag($tagTbl, GPSTrackRef => 'T'); + $et->HandleTag($tagTbl, GPSAltitude => $a[10]); + $et->HandleTag($tagTbl, Unknown02 => "@a[1,2]"); + } + } + } elsif ($id == 0x101) { + my $tagTablePtr = GetTagTable('Image::ExifTool::QuickTime::INSV_MakerNotes'); + for ($i=0, $p=0; $i<4; ++$i) { + last if $p + 2 > $len; + my ($t, $n) = unpack("x${p}CC", $buff); + last if $p + 2 + $n > $len; + my $val = substr($buff, $p+2, $n); + $et->HandleTag($tagTablePtr, $t, $val); + $p += 2 + $n; + } + } + ($pos -= 6) < $trailerStart and last; # step back to previous record + $raf->Seek($pos, 0) or last; + $raf->Read($buff, 6) == 6 or last; + } + SetByteOrder('MM'); +} + +#------------------------------------------------------------------------------ +# Scan movie data for "freeGPS" metadata if not found already (ref PH) +# Inputs: 0) ExifTool ref +sub ScanMovieData($) +{ + my $et = shift; + my $raf = $$et{RAF} or return; + my ($tagTbl, $oldByteOrder, $verbose, $buff, $dataLen); + my ($pos, $buf2) = (0, ''); + + # don't rescan for freeGPS if we already found embedded metadata + my $dataPos = $$et{VALUE}{MovieDataOffset}; + if ($dataPos and not $$et{DOC_COUNT}) { + $dataLen = $$et{VALUE}{MovieDataSize}; + if ($dataLen) { + if ($raf->Seek($dataPos, 0)) { + $$et{FreeGPS2} = { }; # initialize variable space for FreeGPS2() + } else { + undef $dataLen; + } + } + } + + # loop through 'mdat' movie data looking for GPS information + while ($dataLen) { + last if $pos + $gpsBlockSize > $dataLen; + last unless $raf->Read($buff, $gpsBlockSize); + $buff = $buf2 . $buff if length $buf2; + last if length $buff < $gpsBlockSize; + # look for "freeGPS " block + # (found on an absolute 0x8000-byte boundary in all of my samples, + # but allow for any alignment when searching) + if ($buff !~ /\0..\0freeGPS /sg) { # (seen ".." = "\0\x80","\x01\0") + $buf2 = substr($buff,-12); + $pos += length($buff)-12; + # in all of my samples the first freeGPS block is within 2 MB of the start + # of the mdat, so limit the scan to the first 20 MB to be fast and safe + next if $tagTbl or $pos < 20e6; + last; + } elsif (not $tagTbl) { + # initialize variables for extracting metadata from this block + $tagTbl = GetTagTable('Image::ExifTool::QuickTime::Stream'); + $verbose = $$et{OPTIONS}{Verbose}; + $oldByteOrder = GetByteOrder(); + SetByteOrder('II'); + $et->VPrint(0, "---- Extract Embedded ----\n"); + $$et{INDENT} .= '| '; + } + if (pos($buff) > 12) { + $pos += pos($buff) - 12; + $buff = substr($buff, pos($buff) - 12); + } + # make sure we have the full freeGPS record + my $len = unpack('N', $buff); + if ($len < 12) { + $len = 12; + } else { + my $more = $len - length($buff); + if ($more > 0) { + last unless $raf->Read($buf2, $more) == $more; + $buff .= $buf2; + } + if ($verbose) { + $et->VerboseDir('GPS', undef, $len); + $et->VerboseDump(\$buff, DataPos => $pos + $dataPos); + } + my $dirInfo = { DataPt => \$buff, DataPos => $pos + $dataPos, DirLen => $len }; + ProcessFreeGPS2($et, $dirInfo, $tagTbl); + } + $pos += $len; + $buf2 = substr($buff, $len); + } + if ($tagTbl) { + $$et{DOC_NUM} = 0; + $et->VPrint(0, "--------------------------\n"); + SetByteOrder($oldByteOrder); + $$et{INDENT} = substr $$et{INDENT}, 0, -2; + } + # process INSV trailer if it exists + ProcessINSVTrailer($et); +} + +1; # end + +__END__ + +=head1 NAME + +Image::ExifTool::QuickTime - Extract embedded information from movie data + +=head1 SYNOPSIS + +These routines are autoloaded by Image::ExifTool::QuickTime. + +=head1 DESCRIPTION + +This file contains routines used by Image::ExifTool to extract embedded +information like GPS tracks from MOV, MP4 and INSV movie data. + +=head1 AUTHOR + +Copyright 2003-2019, Phil Harvey (phil at owl.phy.queensu.ca) + +This library is free software; you can redistribute it and/or modify it +under the same terms as Perl itself. + +=head1 REFERENCES + +=over 4 + +=item Lhttps://developer.apple.com/library/content/documentation/QuickTime/QTFF/QTFFChap3/qtff3.html#//apple_ref/doc/uid/TP40000939-CH205-SW130> + +=item L<http://sergei.nz/files/nvtk_mp42gpx.py> + +=item L<https://forum.flitsservice.nl/dashcam-info/dod-ls460w-gps-data-uit-mov-bestand-lezen-t87926.html> + +=item L<https://developers.google.com/streetview/publish/camm-spec> + +=item L<https://sergei.nz/extracting-gps-data-from-viofo-a119-and-other-novatek-powered-cameras/> + +=back + +=head1 SEE ALSO + +L<Image::ExifTool::QuickTime(3pm)|Image::ExifTool::QuickTime>, +L<Image::ExifTool::TagNames/QuickTime Stream Tags>, +L<Image::ExifTool::TagNames/GoPro GPMF Tags>, +L<Image::ExifTool::TagNames/Sony rtmd Tags>, +L<Image::ExifTool(3pm)|Image::ExifTool> + +=cut + diff --git a/lib/Image/ExifTool/README b/lib/Image/ExifTool/README new file mode 100644 index 0000000..36b3b5e --- /dev/null +++ b/lib/Image/ExifTool/README @@ -0,0 +1,1064 @@ +-------------------------------------------------------------------------------- +File: Image/ExifTool/README + +Description: ExifTool support modules documentation + +The ExifTool support modules are loaded by ExifTool to allow processing of +various meta information formats. + +The tables in these files are used as lookups based on the tag ID values. The +hash keys are the tag IDs (in decimal or hexadecimal if the ID is numerical as +with EXIF tables, or the tag name if the ID is ASCII as with XMP tables). In +the case of a BinaryData table, the IDs are numerical and specify offsets into +the binary data block (floating point IDs allow multiple tags for the same +offset, with the integer part being used for the offset). The corresponding +hash value provides information about the tag (explained later). + +Twenty-six special keys (TABLE_NAME, SHORT_NAME, PROCESS_PROC, WRITE_PROC, +CHECK_PROC, GROUPS, FORMAT, FIRST_ENTRY, TAG_PREFIX, PRINT_CONV, WRITABLE, +TABLE_DESC, NOTES, IS_OFFSET, IS_SUBDIR, EXTRACT_UNKNOWN, NAMESPACE, PREFERRED, +SRC_TABLE, PRIORITY, AVOID, WRITE_GROUP, LANG_INFO, VARS, DATAMEMBER and +SET_GROUP1) are used to provide additional information about a table. The +special keys have names that are all capitalized to avoid possible conflicts +with tag keys. Below is an explanation of the meaning of each special key: + + TABLE_NAME : Name of this table (set automatically by GetTagTable()). + + SHORT_NAME : Table name with leading "Image::ExifTool::" removed. + + PROCESS_PROC : Reference to a function used to process the directory for this + table. If PROCESS_PROC is not given, \&Image::ExifTool::Exif::ProcessExif is + assumed (except for QuickTime atoms for which + \&Image::ExifTool::QuickTime::ProcessMOV is the default). If PROCESS_PROC is + set to 0, the tags are not added to the lookup. The process proc returns 1 on + success or 0 on failure, and takes 3 arguments: 0) reference to the ExifTool + object, 1) reference to a directory information hash (with the following + entries:), 2) reference to the tag table hash. + + Name - Tag name for this SubDirectory entry (for verbose messages) + Base - Base offset for pointers from start of file + DataPt - Reference to data block containing directory (may be undef) + DataPos - Position of data block within file (relative to Base) + DataLen - Length of data block in bytes + DirStart - Offset to start of directory from start of data block + DirLen - Length of directory data within block + DirName - Name of this directory + OutFile - Output file or scalar reference + Parent - Name of parent directory + RAF - Reference to File::RandomAccess object if available + NewDataPos - File position of new data (write proc only) + Fixup - Reference to hash of offset fixups (used in EXIF writing only) + FixBase - Flag set to attempt to fix base offsets + FixOffsets - Evaluated for each value pointer to patch maker note offsets + LastIFD - Used by WriteExif() to return offset of last IFD written + ImageData - Used by WriteExif() to avoid buffering large image data blocks + + WRITE_PROC : Reference to a function to write all new tags for this directory. + The write proc returns the new directory data or undefined on error. It takes + the same arguments as the process proc above except that the second argument + (reference to directory information hash) is optional, and if specified gives + information about the source directory for tags to be copied to the output. + + CHECK_PROC : Reference to a function which validates Raw values for writing. + The function takes three arguments: 0) ExifTool object reference, 1) tagInfo + reference, 2) value reference, and returns undefined (and possibly modifies + the input value) if successful, or an error message if there was a format + problem. May set ExifTool CHECK_WARN datamember for success with a warning. + + GROUPS : A hash lookup for the default group names for all entries in this + table. If not specified, the default Group 0 and 1 names will be set + automatically according to the name of the module, and the default Group 2 + name will be set to 'Other'. + + FORMAT : Specifies the default tag Format, and corresponding pointer increment + for entries in a BinaryData table. Defaults to 'int8u' for BinaryData tables + if not specified. The possible values of FORMAT are: + + int8s - Signed 8-bit integer (EXIF 'SBYTE') + int8u - Unsigned 8-bit integer (EXIF 'BYTE') + int16s - Signed 16-bit integer (EXIF 'SSHORT') + int16u - Unsigned 16-bit integer (EXIF 'SHORT') + int16uRev - Unsigned 16-bit integer, reversed byte order + int32s - Signed 32-bit integer (EXIF 'SLONG') + int32u - Unsigned 32-bit integer (EXIF 'LONG') + int64s - Signed 64-bit integer (BigTIFF 'SLONG8') + int64u - Unsigned 64-bit integer (BigTIFF 'LONG8') + rational32s - Rational consisting of 2 int16s values + rational32u - Rational consisting of 2 int16u values + rational64s - Rational consisting of 2 int32s values (EXIF 'SRATIONAL') + rational64u - Rational consisting of 2 int32u values (EXIF 'RATIONAL') + fixed16s - Signed 16-bit fixed point value + fixed16u - Unsigned 16-bit fixed point value + fixed32s - Signed 32-bit fixed point value + fixed32u - Unsigned 32-bit fixed point value + float - 32-bit IEEE floating point value (EXIF 'FLOAT') + double - 64-bit IEEE floating point value (EXIF 'DOUBLE') + extended - 80-bit extended floating float + ifd - Unsigned 32-bit integer sub-IFD pointer (EXIF 'IFD') + ifd64 - Unsigned 64-bit integer sub-IFD pointer (BigTIFF 'IFD8') + string - Series of 8-bit characters (EXIF 'ASCII') + undef - Undefined-format binary data (EXIF 'UNDEFINED') + binary - Binary data (same as 'undef') + + Additionally, the following variable-length Format types may be used in + individual tag information hashes of a BinaryData table. The 'var_' formats + cause subsequent tag indices to be incremented according to the size of the + data, not including the terminator. See "Format" below for more details. + + pstring - Pascal string (1-byte length followed by ASCII string) + var_string - variable-length null-terminated ASCII string + var_ustring - variable-length null-terminated UCS-2 string + var_pstring - variable-length Pascal string + var_pstr32 - variable-length Pascal string /w 32-bit len + var_ustr32 - variable-length UCS-2 string /w 32-bit len + var_int16u - variable-length undef data with int6u count + var_ue7 - variable-length 7-bit-at-a-time integer (BPG) + + And the following format codes are used for string values in XMP metadata. + (See the XMP specification for more details.) + + boolean - "True" or "False" + date - date/time string + integer - integer as a string + lang-alt - list of alternate-language strings + rational - "N/D" where N=numerator, D=Denominator + real - floating point value as a string + string - unformatted string + struct - structure + + FIRST_ENTRY : Specifies the index for the first tag entry in a binary table. + This value is only used if the Unknown option is set to 2 or higher, and + allows the binary data to be scanned for unknown tag entries. + + TAG_PREFIX : Prefix for names of unknown tags. + + PRINT_CONV : Default print conversion for tags where PrintConv isn't + specified. PrintConv may be set to undef for individual tags to disable print + conversion when PRINT_CONV is defined for a table. + + WRITABLE : Indicates that all tags in this table are writable. This is the + same as setting the Writable flag for each individual tag in the table, except + for SubDirectory tags which are not made Writable. + + TABLE_DESC : Short description for this table. Plain text only. Used only + for XML tag database output. + + NOTES : Notes to introduce the table in the TagNames documentation. Pod + formatting codes B<>, C<> and L<> may be used in this text. + + IS_OFFSET : Writable BinaryData tables only. Reference to list of sorted + TagID's representing offsets. + + IS_SUBDIR : Writable BinaryData tables only. A reference to a list of sorted + tag ID's representing subdirectories. + + EXTRACT_UNKNOWN : Used in PDF tables to specify a directory where all unknown + tags should be extracted. Set to 0 to extract only unknown numbered tags for + which the unnumbered tag is known. + + NAMESPACE : Namespace prefix for tags in the XMP table. If this isn't a + standard namespace defined in %Image::ExifTool::XMP::nsURI, then the URI must + be defined as well (however, this is not recommended for pre-defined + namespaces because then non-standard namespace prefixes won't be recognized). + To define the URI, the NAMESPACE value is a reference to a hash where the key + is the namespace prefix and and the value is the URI (alternatively, a + reference to a 2-element array containing the prefix and URI is also allowed + for backward compatibility). The NAMESPACE value may be undef for XMP tables + where tags have variable namespaces (in this case each tag must have a + Namespace entry). + + PREFERRED : Set to true if the tags in this table should always be added when + writing information. Overrides the order specified by SetNewGroups(). When + this feature is used, it may also be desireable to specify a preferred group + when calling InitWriteDirs() to write these tags; this avoids creating other + directories for tags which are already being creating in the preferred group. + + SRC_TABLE : Used internally to store the source table name of a user-defined + tag table so the appropriate module can be loaded as required. + + PRIORITY : Default Priority for all tags in this table. + + AVOID : Flag set to Avoid writing all tags in this table. + + WRITE_GROUP : Default WriteGroup for all tags in the table. + + LANG_INFO : Code reference to a routine which returns a reference to a + language-specific tag information hash. The routine takes two arguments: a + reference to the non-specific tagInfo hash, and the language code. Used only + in tables with writable tags which support tag name language extensions (eg. + MIE and XMP). + + VARS : Hash used to store additional parameters. Individual modules may use + this to store any parameters they want. The following additional parameters + have been defined, and may be used by any module: + + ID_LABEL Label to use instead of "Tag ID" for column heading in tag + name documentation. When this is set, numerical TagID's are + not converted to hexadecimal notation. Unless otherwise set, + an ID_LABEL of "Index" is assumed for tables which use + ProcessBinaryData. + + NO_ID Avoid printing "Tag ID" column in tag name documentation. + + HEX_ID Print tag ID in hexadecimal (with 4 hex digits or more). + + NO_LOOKUP Do not add tags to TagLookup.pm lookup tables. + + CAPTURE Used by PDF module to name dictionaries to capture when + writing. + + MINOR_ERRORS [EXIF tables only] Flag to make errors in this IFD minor, or + to downgrade already minor errors to warnings while writing. + (Errors in MakerNote IFD's are already classified as minor.) + Note that for certain types errors, the response is to delete + the entire IFD from the image. + + ALPHA_FIRST Sort alphabetical tags before numerical in documentation. + + LONG_TAGS Suppress "Long tags" warning when generating documentation. + Value is the number of long tag names to expect. + + SORT_PROC Reference to sort procedure for sorting tag ID's in the + documentation. Takes two arguments and returns -1, 0 or 1 + if the first argument is less than, equal to, or greater than + the second argument. + + ENTRY_SIZE Used by ProcessPhaseOne to specify size of IFD entry + + MAP_FORMAT Lookup to map unknown format numbers (eg. Panasonic CameraIFD) + + START_INDEX [QuickTime tables only] Initial index for indices shown in + Verbose output. Indices are not show otherwise. + + DATAMEMBER : BinaryData tables only. A reference to a list of sorted tag ID's + which must be extracted as data members when writing. Must also list "var_" + format tags and tags with Hook so offsets are properly calculated if the table + is writable. + + SET_GROUP1 : [EXIF tables only] Flag to set group1 name to the directory name + for all tags in the table. + +The remaining entries in a tag table are the tag IDs with their associated +information. The information may exist in one of three forms: 1) A simple +scalar which is the name of the tag, 2) A reference to a hash of information +describing this tag, or 3) a reference to a list of hashes which contain +Condition expressions allowing the appropriate hash to be selected to suit the +conditions. The following is a description of possible hash entries. All +entries are optional, except for the tag Name which is required if the tag ID is +numerical. + + Name : The tag name. Tag names need not be unique. If they aren't + unique, then duplicate tags will hide the values of previous + tags when extracting information unless the Duplicates option + is set or the new tag has lower Priority. With Duplicates + set, to allow multiple tags with the same name to exist in the + tag information hash, the key of the previous tag is changed + to the form "TagName (N)", where N starts at 1 and increments + for subsequent duplicate tags. A tag name should start with + an uppercase letter, and contain only the characters in the + set [A-Za-z0-9_-]. If not given, the Name is taken from the + tag ID with the first character changed to upper case. + + Description : A more readable description of tag name. If a tag doesn't + specify a Description, then the tag Name is used instead, with + spaces inserted between the words. + + Notes : Notes for this tag in the HTML TagNames documentation. + + Groups : Hash lookup for group names for this tag. If not specified, + defaults to the GROUPS specified in the table definition. + + Format : Only valid for BinaryData, EXIF and IPTC tables. For a Binary + or EXIF table, this gives the format that is used to convert + the binary data, and is one of the FORMAT types specified + above. If not specified, the Format of an EXIF entry is taken + from the EXIF information, and the Format of a BinaryData + entry is taken from the FORMAT specified for the table (or + int8u if FORMAT is not specified). Must be specified for + Writable tags where the value must be converted for a + Condition. For BinaryData tables, the format may have a size + in trailing brackets which is a Perl expression to be + evaluated. The expression may access any of the previous + table entries through a %val hash (read-only tags), the data + size via $size, or the ExifTool object via $self. For + example, 'string[$val{3}]' defines a string with length given + by the table entry with tag index '3'. An initial "var_" may + be added to the Format name of any BinaryData tag with a size + in brackets. In this case, subsequent offsets are adjusted by + the value length minus the size of the default table FORMAT + (eg. "var_int16u[10]" causes subsequent offsets to be + incremented by sizeof(int16u) * 10 - sizeof(int8u) if the + default table FORMAT is "int8u"). Note that all "var_" Format + tags (as well as tags with values used within "var_" Format + expressions) must have corresponding DATAMEMBER entries. + + Count : Used when writing EXIF information to specify the number + values to write, or the number of characters in a fixed-length + string. A value of -1 indicates that the count is variable + and should be determined by the number of values provided. + Defaults to 1 if not specified for non-string formats. Note + that this count corresponds to the specified Format, so if a + different-sized Writable format is defined, the actual count + written to the file will be different. + + FixCount : Flag set to determine correct count from offsets in IFD. This + is necessary for some Kodak tags which write an incorrect + Count value. + + Flags : Flags to specify characteristics for this tag. May be a + simple scalar flag name, a reference to a list of flag names, + or a reference to a hash of flag/value pairs. If not a hash + reference, the flag value is set to 1. Flags are expanded for + faster access at run time into members of the tagInfo hash, + and may be written directly as members if desired. The + available flag names are: + + 'AutoSplit' - [List tags only] Similar to ListSplit option, + but applied automatically to individual tags. Value specifies + pattern for split, or 1 for default pattern ',?\\s+'. + + 'Avoid' - avoid creating this tag if possible. This is only + effective if another tag exists with the same name. Setting + this flag also sets the default Priority to 0 for this tag. + + 'Binary' - set to 1 for binary data. This has the same effect + as setting ValueConv to '\$val', but it it a bit cleaner and + avoids dummy ValueConvInv entries for writable tags. Has no + effect if ValueConv is defined for the tag. Some values may + be treated as binary data even if this flag is not set. + + 'BlockExtract' - set for writable directories in EXIF + information which are extracted by default. Otherwise + writable directories are only extracted as a block if + specified explicitly. Also used for Jpeg2000 and QuickTime + XMP-like tags to extract as a block with a name other than + 'XMP'. + + 'ConvertBinary' - true to apply ValueConv and/or PrintConv to + Binary values (ie. SCALAR references). (By default, these + conversions are not done for Binary values.) + + 'DataMember' - name of exiftool data member associated with + this tag if it should be stored as a special data member when + writing information. Necessary only if the value of the tag + affects other written information. Currently only used for + tags in EXIF tables where it triggers the execution of the + RawConv to convert and store the value as an ExifTool data + member when writing. + + 'DataTag' - associated tag name containing data for offset or + byte count tags. + + 'Drop' - [IFD-format and PhaseOne makernote tags only] set to + 1 for tags that should be excluded when rebuilding maker notes + when copying all tags. Set to a number larger than 1 to drop + only if data is larger than this size. Works for SubDirectory + tags too. + + 'EntryBased' - set to 1 if the offset for this value is based + on the IFD entry position. This allows individual values to + be entry-based even though some others aren't (as with the + Casio PrintIM information). + + 'Flat' - [flattened XMP structure tags only] must be set for + all pre-defined flattened tags (including user-defined + flattened tags). This flag is reset to 0 internally after all + associated flattened tags in the structure have been + generated. + + 'Flattened' - [reserved] used internally to mark Struct tags + which have been processed to generate flattened equivalents. + + 'GotGroups' - [reserved] flag used internally to indicate that + the Groups hash has been initialized for this tag. + + 'Hidden' - set to hide tag from the TagName documentation. + Also suppresses verbose output of a BinaryData tag. + + 'IsComposite' - flag set for Composite tags + + 'IsOffset' - flag set if the tag represents an offset to some + data, and causes value will be adjusted to an absolute file + offset. If set to 2, the offset base of the parent directory + is used even if the base changes for the current directory + (only some maker notes are this messed up). Set to 3 if + absolute file offsets are used. May be set to an expression + to be evaluated. Expression may access $val and $et, + and is evaluated only when reading. + + 'List' - flag indicating that duplicate entries of this tag + are allowed, and will be accumulated in a list. Note that for + XMP information, 3 different types of lists are supported and + the List value specifies the type: 'Bag', 'Seq' or 'Alt'. As + well, a value of '1' is used internally in XMP to allow list + behaviour for a flattened tag which is itself not a list + element (eg. a member of list of structures). Note that in + ExifTool an XMP lang-alt tag (Writable="lang-alt") is NOT a + list-type tag (unless it is a list of lang-alt lists, which is + uncommon). + + 'MakerNotes' - set if this tag is maker note data. + + 'MakerPreview' - set in the PreviewImageStart tag information + if the preview must be stored inside the maker notes. + + 'Mandatory' - set for mandatory tags. Used only by TagInfoXML + and for documentation purposes. Mandatory tags may be added + automatically by ExifTool. + + 'NestedHtmlDump' - flag set if value for this tag is also + dumped when processing the SubDirectory. This flag is implied + if the MakerNotes flag is set. Set to 2 if the dump should + only be underlined if nested inside other maker notes. + + 'NotIFD' - set for 'MakerNotes' SubDirectory tags only if the + SubDirectory is not EXIF IFD format. (Note: All SubDirectory + tags in the MakerNotes table are 'MakerNotes' type by + default.) + + 'OffsetPair' - set if the tag represents half of an offset/ + byte count pair. Data for these tags must be handled + separately. Value is the tagID for the paired tag. + + 'Permanent' - flag indicates that a tag is permanent, and + can't be added or deleted from the file, although a new value + may be written if the tag already exists. By default, all + MakerNotes tags are permanent unless otherwise specified. + + 'PrintHex' - specifies that unknown PrintConv values should + be printed in hex (eg. 'Unknown (0x1)'). Also causes + numerical tag values to be printed in hex in the HTML tag name + documentation, padded to the number of digits given by the + PrintHex value. + + 'PrintSort' - causes PrintConv values to be sorted by value + rather than key in the HTML tag name documentation. + + 'PrintString' - flag set to force PrintConv values to be + printed as strings in the documentation. + + 'Priority' - gives the priority of this tag while reading. If + set to zero, this tag will not override the value of previous + tags with the same name. If the priority is greater than + zero, this tag won't be overridden by subsequent tags unless + their priority is equal to or greater than this priority. A + special feature is that Priority 0 tags are automatically + incremented to Priority 1 if they exist in the IFD of the full + resolution image (as determined by SubfileType). If not + defined, the priority defaults to 1 for all tags except except + tags in IFD1 of JPEG images which default to priority 0. + + 'Protected' - bit mask to protect tags from writing: + Bit 0x01 indicates an 'unsafe' tag, which is not set via + SetNewValuesFromFile() unless specified explicitly. + Bit 0x02 indicates a 'protected' tag, which should not be set + directly by the user. + + 'PutFirst' - [EXIF only] flag to place this value before IFD0 + when writing (ie. immediately after TIFF header). Only used + for values in main IFD's (IFD0, IFD1, etc) and IFD's where + SubIFD flag is set to 2 (currently only ExifIFD). + + 'RawJoin' - [List tags only] Joins raw List-type tag values + into a single string with a space separator, allowing + ValueConv and PrintConv to act on the concatenated string so + the tag does not exhibit list-type behaviour. When writing, + the inverse is performed and the value is split at whitespace. + + 'Resource' - [XMP only] flag to write value as an rdf:resource + in an empty element instead of as a normal string. + + 'SeparateTable' - set to list PrintConv values in a separate + table in the HTML documentation. Value is 1 for a table name + of 'Module TagName', or 'TAG' for 'Module TAG', or 'MODULE + TAG' to fully specify the table name. The table may have a + 'Notes' entry for a description of the table. + + 'SetResourceName' - [Photoshop tags only] set to 1 to append + resource name to the extracted value (eg. 'VALUE/#NAME#/'). + Also allows resource name to be appended when writing new + values. May be set to any value other than 1 for a default + resource name to use when writing if an appended name is not + provided. + + 'StructType' - [reserved] used internally by XMP writer for + flattened structure tags as a flag to indicate that one or + more enclosing structures has a TYPE field. + + 'SubDoc' - [Composite tags only] set to cause this Composite + tag to also be generated for each sub-document. To achieve + this, 'Main:' and 'Doc#:' prefixes are added to all Require'd + and Desire'd tag names which don't already start with 'Main:' + or 'Doc#:', and the Composite tag is built once for each of + the main document and all sub-documents. May be a reference + to a list of indices for Desire'd tags, one of which must + exist to generate this tag for sub-documents. + + 'SubIFD' - used in writing to determine that the tag specifies + an offset to a sub-IFD. When this flag is set, the Group1 + name gives the name of the IFD. Must be set if and only if + the tag has a SubDirectory Start that references '$val' (this + is validated by BuildTagLookup). Set to 2 for standard EXIF + SubIFD's where the PutFirst flag is valid. + + 'Unknown' - this is an unknown tag (only extracted when the + Unknown option is set). + + 'WriteNothing' - flag indicating that nothing is actually + written when this tag is set. It is a fake writable tag that + isn't actually written (eg. Geotag). Used to avoid processing + a file unnecessarily if nothing will actually be written. + + 'WritePseudo' - flag indicating that this is a writable pseudo + tag. If set, this tag may be written without actually writing + to the file (eg. FileName, FileModifyDate). + + 'WrongBase' - ['IsOffset' tags only] An expression using $self + that is evaluated to generate a base shift for 'IsOffset' tags + which use a different base than the rest of the tags. + + RawConv : Used to convert the Raw value at extraction time (while the + image file is still open, unlike ValueConv and PrintConv below + which are done later only if the value is requested). May be + a scalar expression using $val (the Raw tag value), $self (the + current ExifTool object), $tag (the tag key), $tagInfo + (reference to the tag information hash), $priority (to + dynamically set the priority of a tag), and @grps (to + dynamically set the family and/or groups), or a code reference + with $val and $self as arguments (in which case $$self{grps} + may be used to set the groups). For Composite tags, $val is a + reference to a hash of source ("derived from") tag names, and + @val may be used to access the Raw values of these tags. The + returned value may be a scalar which is used as the new Raw + value, a scalar reference to a binary data value, a hash + reference for Composite tags, an ARRAY reference for a list of + values, or undefined to indicate that the tag should be + ignored. If RawConv is specified for a Composite tag, then + ValueConv and PrintConv evals will no longer have access to + the source @val and @prt values unless the input $val is + returned. RawConv may generate Warning or Error tags, while + ValueConv and PrintConv should not (see ValueConv note below). + Note: RawConv should only be used if necessary (in general, + only if the conversion may return undef to ignore the tag, or + if a Warning may be issued) because ValueConv is more + efficient since it is only executed if the tag value is + requested, while RawConv is executed for all extracted tags. + + ValueConv : Used to convert the Raw value to a useable form. May be a hash + reference to act as a lookup table, a scalar which is + evaluated as a Perl expression, a code reference to a + subroutine, or an ARRAY reference (in which case the value is + split at whitespace into a list of items and each item is + converted by the associated entry in the ValueConv list. A + special value of 'REPEAT' may be used to repeat the previous + conversion for all remaning elements). If a hash reference is + used and the Raw value doesn't appear as one of the keys, then + the converted value is set to "Unknown (X)", where X is the + Raw value (unless either of the special keys exist: 'BITMASK', + a reference to a hash used to decode individual value bits; or + 'OTHER', a reference to a subroutine used to convert unknown + values. The OTHER subroutine takes 3 arguments: the value, a + flag which is set for the inverse conversion, and a reference + to the PrintConv hash, and returns the converted value or + undef on error -- it may call warn() to return an error + message. The lookup hash may also contain a 'Notes' entry + which is used for documentation if the SeparateTable flag is + set). In an expression, $self is a reference to the current + ExifTool object, $val is the Raw value, and $tag is the tag + key. The subroutine takes 2 arguments: the Raw value and a + reference to the current ExifTool object. The advanced + formatting expression (if any) may be accessed via the + ExifTool "FMT_EXPR" member variable. The expression or + subroutine is evaluated if and when the tag value is requested + (ie. only after all extraction is complete), so if necessary + at this time the values of all other tags are available via + calls to $self->GetValue("Tag","Raw"). (Note: In theory, + types other than "Raw" may be accessed, but they are slower + and may lead to cyclical dependencies so they should be + avoided). When evaluated, the expression or subroutine + returns a scalar for the converted value, a SCALAR reference + to a binary data value (see the 'Binary' flag), or an ARRAY + reference for a list of values. The return value should + always be defined -- use RawConv instead to return undef if it + is necessary to test the value for validity, otherwise an + undef tag may hide a previously defined value when the + Duplicates option is not enabled. If this isn't possible (as + with Composite tags where the converted values of the source + tags are needed), set the Priority to 0 to avoid taking + priority over a valid tag. If ValueConv is not specified, the + Raw value is not converted. Composite tags which Require or + Desire other tags may access the ValueConv, PrintConv and Raw + values of these tags through the elements of the @val, @prt + and @raw lists respectively (only if there was no RawConv or + it returned a hash reference). For these tags, $val may be + used in an expression to represent $val[0], and the first + argument passed for a code reference is a reference to @val. + Note: Warnings issued by these conversions are intercepted by + ExifTool and saved as Warning tags, but since ValueConv and + PrintConv conversions are done on demand, the warnings may be + generated after the list of extracted tags is returned, so may + easily be missed. + + PrintConv : This entry is similar to ValueConv above, except that it is + used to further convert the tag value to a human readable + form. It can be either a hash lookup, a scalar Perl + expression, a code reference or a list reference. In this + expression, $self, $val and $tag may be used as with + ValueConv, but if ValueConv was defined then $val is the + ValueConv value instead of the Raw value. The returned value + should always be defined. Note that the print conversion is + only done if the PrintConv option is enabled (which it is by + default), and if the result of the ValueConv is not a scalar + reference. If it is a list reference, then the converted + values are joined by '; ' in the output string. + + RawConvInv : The inverse of RawConv. This should only be used in very rare + situations when the raw value can not be predetermined. + Unlike the other inverse conversions which are applied in + SetNewValue(), this conversion is applied in WriteInfo() as + the file is being written. This is important because it means + that FILE_TYPE and any DataMember tags ocurring before this + tag in the file are available. Beware that if the return + value is not defined, the tag will be deleted unless there is + specific logic to avoid this (currently, only EXIF and Binary + data directories handle this case). + + ValueConvInv : The inverse of ValueConv. Only necessary for Writable tags + when ValueConv is specified (except WriteAlso tags). Note + that DataMember tags may NOT be used in the inverse + conversions because these conversions are done before the + input file is parsed. Instead, a Condition or RawConvInv must + be used. May return undef on conversion error and call warn() + to issue a warning. If warn() is not called, a generic + warning is generated when undef is returned. An empty warning + ("\n") may be issued to suppress warning messages when undef + is returned. If a scalar, the expression may use the + variables $val, $self and $wantGroup. If a code ref, the + routine is passed 2 arguments: $val and $self. Note that this + conversion is not applied for deleted tags (ie. $val is + undef). + + PrintConvInv : The inverse of PrintConv. Necessary for Writable tags + when PrintConv is specified (unless WriteAlso is used), but + may be used without PrintConv. See ValueConvInv above for + more details. + + PrintConvColumns : Number of columns for PrintConv lookup in HTML docs. If not + set, the number of columns is determined automatically + according to the maximum width of the entries. + + DelValue : Raw value to be used when deleting a permanent tag. (Note all + MakerNotes tags are permanent.) If not specified, an attempt + is made to convert an empty string for the raw value. + + Validate : Scalar expression used to validate the raw value of a tag when + the Validate option is set. The expression may access $val + (the Raw tag value), $tag (the tag key) and $self (the current + ExifTool object), and should return a warning if any problem + is found, or false if OK. The evaluation is performed in the + Image::ExifTool::Validate package namespace, so functions of + this package need not be prefixed by the package name. + + Relist : [Only if ValueConv or PrintConv is a list ref] Reference to a + list of original value indices used to reorganize values. Each + entry in the list may be a scalar index, or a reference to a + list of indices to join values. (Currently values may be + joined, but the order of writable values must not be changed + until this ability is added to the writer.) + + Mask : [BinaryData tags only] Bitmask for this value. (Multiple tags + may have the same index by using floating point indices. An + unknown tag will only be generated for a certain TagID if + there is no integral TagID for that tag.) The Mask and + BitShift are applied before evaluating RawConv. + + BitShift : [Mask tags only] Bit shift for Mask-ed values. If not + specified, set to the number of trailing bits in the Mask. + When reading, the value is shifted by this number of bits + after the Mask is applied. + + Condition : If given, specifies scalar which is evaluated as a Perl + expression at extraction time to decide whether the tag is + valid. If used in a list of alternate tag definitions, the + first list entry with a true condition is taken. If no + condition exists, then a 'true' condition is assumed. The + expression may use $self to access the ExifTool object. The + first 128 bytes of the raw data value are accessible through + the reference $valPt for EXIF, Jpeg2000, QuickTime and + BinaryData tags only (note that for BinaryData tags, the raw + data of $$valPt is always 'undef' type, and may not be used + when writing except for SubDirectory tags). EXIF tags (and + maybe some other types) may also reference the format string + and value count through $format and $count. Note that if the + value is writable and $valPt is used, the tag must have a + Format (unless 'undef' or 'string'), and a Count (unless 1 or + length of the 'undef' or 'string'), so the raw data may be + generated for evaluating the Condition. When writing, $valPt, + $format and $count refer to the new value, except for + MakerNotes tags where $format and $count refer to the old tag + if it existed. + + Require : [Composite tags only] A hash reference specifying the tags + required to calculate the Composite tag value. The hash + values are the names of the required tags, and the keys + specify the indices where the tag values are stored in the + @val list used in the ValueConv and/or PrintConv expression. + The Composite value is only calculated if the values for all + Require'd tags are defined. Require, Desire and Inhibit tag + names may be prefixed by an optional group family 0 or 1 name + followed by a colon. Case IS significant. The keys used by + the Require, Desire and Inhibit hashes must not overlap (since + they are used as indices into the common @val, @prt and @raw + lists), and together the keys must be sequential starting from + 0. A special feature allows a scalar tag name to be used + instead of the hash reference when only the 0th tag is + defined. For example, the following two definitions are + equivalent: + + Require => { 0 => 'XMP:Title' }, + Require => 'XMP:Title', + + Desire : [Composite tags only] This is the same as Require except that + the Composite value is calculated even if the specified tags + don't exist. Beware that the elements of @val, @prt and @raw + may be undefined for Desire'd tags. If no tags are Require'd, + at least one of the Desire'd tags must exist for the Composite + tag to be generated. If there are no Require'd or Desire'd + tags, then the Composite tag is always generated. + + Inhibit : [Composite tags only] Similar to the Require and Desire + hashes, except that the Composite tag is NOT built if any of + the Inhibit tags exist. + + Shift : [Writable tags only] Specifies type of shift to apply if this + value may be shifted. Set to 'Time' for shifting date/time + tags, or '0' to prevent tag from being shifted or + conditionally deleted. + + Writable : Indicates this tag can be written (or not written if Writable + is set to zero), and for EXIF-type tables gives format for + writing. Writable may be set to 1 for MakerNotes information + because the existing format is always used, however providing + a format is desireable because it is used in validating the + value. For EXIF tables, the Writable flag may be different + than the Format flag, in which case Format is used for + converting the binary value and Writable specifies the format + code written to the EXIF IFD. For SubDirectories in EXIF + information, this flag is only defined if the SubDirectory is + writable as a block, or if the SubDirectory can not be edited + (in which case Writable is set to 0). If non-zero, the + SubDirectory is also extracted as a block, so the Binary and + Protected flags should usually set as well. There is + currently no way to specify a write format for a SubDirectory + that is not writable as a block (the default is 'int32u' for + IFD-type SubDirectories, and 'undef' for all others). + + WriteAlso : Used for writable tag to specify other tags to write when this + tag is written. The value is a hash reference. The hash keys + are the names of the tags to write, and the values are + evaluated to obtain the ValueConv values of each tag (or undef + to delete the tag). In the eval, $val is the new Raw value of + the parent tag (which may be undef if the tag is being + deleted, and should not be modified because it will affect + subsequent WriteAlso tags), and the %opts hash may be accessed + to modify SetNewValue options for each tag. By default, Type + is set to "ValueConv" and the Protected option has bit 0x02 + set to allow writing of Protected tags that aren't directly + writable. The AddValue, DelValue, Shift and Replace options + from the parent tag are also defined, but no other options are + set by default. Previous new values of WriteAlso tags have + already been removed prior to the eval if the Replace option + was used for the parent tag. If an empty warning is issued + ("\n"), the target tag is not written and no error is + reported. + + WriteCheck : If given, specifies a scalar which is evaluated as a Perl + expression for a one-time validatation the Raw value being + written. The expression has access to 3 variables: $val is + the value to be written, $self is the ExifTool object, and + $tagInfo is the tag information hash reference. It returns an + error string, or undef if the value is good. If the error + string is empty, the tag is not written and no warnings are + issued, but WriteAlso is still evaluated if it exists. + + WriteOnly : Flag set if tag is write-only. Used for documentation only. + + DelCheck : Similar to WriteCheck, but called when the tag is deleted. The + expression may access $self, $tagInfo and $wantGroup. Returns + error string, or undef on success, and may set $val to + something other than undef. May return empty string ('') to + suppress warning messages but not delete tag (eg. when + deleting only associated tags). + + WriteCondition: [Writable EXIF tags only] Specifies a condition to be + evaluated before the tag can be written to a specific file. + The condition may use $self to reference the ExifTool object, + and returns true if it is OK for writing. Unlike WriteCheck + which is done only once when the new value is set, this + condition is evaluated just before the tag is written to the + file. + + WriteGroup : [Writable EXIF and Composite tags only] Specifies the IFD + where the information gets written by default. Must be + defined for writable EXIF tags if WRITE_GROUP is not specified + in table. A WriteGroup of 'All' is special: For writable + Composite tags this causes any group specified for the + Composite tag to be propagated to the WriteAlso tags when + writing. For other tags this allows writing to all EXIF IFD's + simultaneously (in which case the tag should have a Condition + or WriteCondition to restrict the IFD's to which the tag is + actually written). + + IsOverwriting : [Writable EXIF tags only] Specifies reference to subroutine + which determines if tag should be overwritten. Arguments are: + 0) ExifTool object ref, 1) new value hash ref, 2) old value, + 3) new value reference. + + Override : [User-defined Composite tags only] Flag to specify that the + new tag definition should override the definition of existing + Composite tags with the same name. Default is 1 unless + otherwise specified. + + AllowGroup : [Writable tags only] Regular expression string (case + insensitive) to match group names which are allowed when + writing this tag. Only needed if tag can be written to + groups other than the normal groups for this tag (very rare). + + OffsetPair : Used in EXIF table to specify the tagID for the corresponding + offset or length tag. + + DataTag : Used in EXIF table to specify the tag name of the data + associated with offset/length tags. + + FixFormat : [Writable EXIF SubIFD SubDirectory's only] Used to specify a + format for writing an IFD pointer other than 'int32u'. + + ChangeBase : [EXIF tags in JPEG images only] Eval used to return new base + for the offset for this tag only. Eval may use $dirStart and + $dataPos. Note this is geared to the quirky Leica preview + image offset, and is only used if the preview is outside the + APP1 EXIF segment. + + BitsPerWord : [BITMASK tags only] Number of bits per decoded word. Defaults + to 32 if not specified. + + BitsTotal : [Writable BITMASK tags only] Total number of bits in bit mask. + Defaults to BitsPerWord if not specified. + + FixedSize : [EXIF only] Hack to ignore value size and use this instead. + Only valid if Format is also defined. + + Struct : [XMP tags only] Reference to structure hash for structured XMP + tags. See "STRUCTURES" section below for more details. (For + backward compatibility, this may be a name to an entry in + %Image::ExifTool::UserDefined::xmpStruct, but this use is + deprecated.) Flattened tags are automatically generated for + each field in the structure. Note that Struct tags can NOT + have ValueConv/PrintConv entries, because values that are HASH + references are are also used by Composite tags, which use the + the Conv entries to generate the Composite value. + + NoSubStruct : [XMP tags only] Flag set in flattened tag to break cyclical + recursion in nested structures. + + Namespace : [XMP tags only] Gives standard XMP namespace prefix to use for + this tag. If not defined, the tag table NAMESPACE is used. + + FlatName : [Struct tags and structure fields only] Name used for + automatically-generated flattened tag names, defaults to Name + if not specified. In general, this is used to remove the + redundant names found in some specifications. May be empty + ('') for a Struct tag but not for a structure field. + + Units : [MIE tags only] Reference to a list of valid units strings. + The default units are the first item in the list. + + Hook : [BinaryData tags only] Expression to be evaluated when + extracting tag to allow dynamic Format, etc for BinaryData + tags. May access $self, and $size (the full size of the + binary data block), and assign a new value to $format to + dynamically set the tag format, and/or increment $varSize to + add a byte offset to subsequent tags. $varSize may be set to + a large number to effectively abort processing of the + directory after this tag. Must have corresponding DATAMEMBER + entry in writable tables. Must not have Unknown set. + + LargeTag : [BinaryData tags only] Flag to indicate that the data for this + tag is large, and that it shouldn't be stored in the %val + hash, even if the tag exists as a DATAMEMBER. + + SetBase : [QuickTime and BinaryData tags only] Sets ExifTool BASE offset + for use when ExtractInfo is called with the ReEntry flag from + inside the RawConv of a tag. + + TagID : [reserved] Used internally to save the table key for this tag. + Note: For XMP tables this corresponds to the XMP property + name, but the table key may have a full XMP namespace prefix + added. + + NewTagID : [reserved] Used internally to save new ID of tag in Composite + table if it is different that the original TagID (happens if + there was a conflict with an existing entry in the table) + + Index : [reserved] Used internally to save the index of tagInfo items + which are in a conditional list. + + Table : [reserved] Reference to parent tag table. + + PropertyPath : [reserved] Used internally by XMP writer to save property path + name. Also used in structure field information hashes, but + for these the full property path is not stored. + + SrcTagInfo : [reserved] Used internally to store reference to default + language tagInfo hash for alternate-language tags. + + OtherLang : [reserved] Used internally by QuickTime module to store a list + of tag ID's for alternate-language tags based on this one. + + RootTagInfo : [reserved] Used internally to store a reference to the tag + information hash of the top-level structure for flattened + structure tags. + + Module : [reserved] Used internally to store module name for writable + Composite tags. + + LangCode : [reserved] Used internally to indicate language code for + alternate language tags (eg. 'fr'). Only used with formats + which support alternate languages (eg. XMP, MIE, etc). + + SubDirectory { If it exists, this specifies the start of a new subdirectory. + It contains a collection of variables which specify the type + and location of the subdirectory. Note that ValueConv and + PrintConv do not apply to SubDirectory tags, but RawConv is + evaluated before the SubDirectory is processed. The following + is a list of SubDirectory variables: + + TagTable : Specifies the name of the tag table lookup for the new + subdirectory. If not specified, the parent tag table is used. + + Start : The offset to the start of the subdirectory relative to the + current Base. This is a Perl expression which may use + $valuePtr to represent the location of the tag value in the + file, or $val for the value itself. If not specified, a Start + of '$valuePtr' is assumed. + + OffsetPt : [EXIF directories only] If specified, this is a Perl + expression that gives the position of a 32-bit word in the + current directory that is added to the Start position to get + the position of the new subdirectory. The expression + should use the position of the current tag ($valuePtr). + + Base : This expression specifies the base offset for all pointers in + the subdirectory. This need not be specified if the offset is + the same as the current directory, which is normally the case. + May use $start to represent the subdirectory start location + relative to the current base, and $base for the value of the + current base. If this is defined, the automatic validation of + base offsets is disabled for maker notes directories. The IFD + is flagged as using relative offsets when writing if '$start' + is used in this expression. + + EntryBased : [EXIF directories only] Flag indicating that the offsets are + based on the individual directory entry position, so offsets + are incremented by 12 times the corresponding entry index. + + MaxSubdirs : Maximum number of subdirectories specified by the current tag + (if the tag specifies multiple values). If not specified, the + tag value ($val) is used as-is. If MaxSubdirs is specified, + then one subdirectory is parsed for each value found up to the + maximum number specified. Ignored when writing. + + ByteOrder : Specifies byte ordering if different than than the rest of the + file. Must be either BigEndian, LittleEndian or Unknown. If + Unknown is specified, the byte order will be determined from + the directory count (however, this can not be done if OffsetPt + is specified). + + Validate : If given, specifies Perl expression which is used to validate + the subdirectory data (regardless of Validate option setting). + The following variables may be used in the expression: $val + (value of the tag), $dirData (reference to directory data), + $subdirStart (offset to subdirectory start) and $size (size of + subdirectory). Returns true if subirectory is valid. + + ProcessProc: If given, specifies processing procedure used to decode this + subdirectory data. This overrides the default procedure + specified by PROCESS_PROC in the tag table. + + WriteProc : If given, specifies processing procedure used to write this + subdirectory data. This overrides the default procedure + specified by WRITE_PROC in the tag table. + + DirName : Name of this subdirectory. If not specified, the name is + taken from the tag name. DirName is important because it is + used when writing to compare against names in the directory + map to determine which directories need to be edited. + + FixBase : Flag set if base offsets should be fixed. Used to add a + constant to maker notes offsets to fix damage done by some + image editing utilities. (maker notes only) Set to 2 for + unknown maker notes to be a bit more flexible in adjusting + the base offset. + + AutoFix : Flag set to patch GE makernote offset quirks and apply FixBase + without warnings when writing. + + FixOffsets : Expression to evaluate for each value pointer to patch + problems with some EXIF maker note offsets. May access the + following variables: $valuePtr, $valEnd, $size, $tagID and + $wFlag. May return undef when writing to ignore the entry. + + RelativeBase:[EXIF directories only] Flag to adjust all offsets relative + to the start of the IFD when writing. + + Multi : [EXIF directories only] Flag to allow multiple linked IFD's. + 1 is assumed if DirName is IFD0 or SubIFD unless otherwise + defined. + + Magic : [TiffIFD directories only] Magic number used in TIFF-like + header. + } + +STRUCTURES + +Structure hashes are very similar to tag tables in that their keys are structure +field ID's and their values are structure field information hashes. The special +keys in structure hashes are: + + NAMESPACE : Same as in tag tables, but may be set to undef for a + variable-namespace structure which holds any top-level tag. This + is mandatory for built-in tags, but optional for user-defined + tags (where it defaults to the NAMESPACE of the tag table). + + STRUCT_NAME : Name of structure (used in warning messages and documentation). + May contain leading module name separated by a space to avoid + name conflicts with same-named structures in other modules. + Default module is "XMP" unless otherwise specified. + + TYPE : rdf:type resource for structure. + + NOTES : Notes for documentation. + + GROUPS : Same as in tag table, but only the family 2 group name is used, + as the default for the flattened tags. + +The contained structure field information hashes are similar to tag information +hashes, except that only the following elements are used: + + Raw/Value/PrintConv (and their inverses), TagID (optional), Groups, List, + Writable, Struct, Namespace, LangCode, PropertyPath, Notes. + +But note that for PropertyPath, only the element of the path corresponding to +the specific field is stored (including any necessary list properties). The +full property path is obtained by walking the structure tree. + +Flattened tags corresponding to each field in a structure are automatically +generated (using an on-demand approach to reduce startup overhead). Pre-defined +flattened tags are allowed, and are used when it is necessary to change the Name +or Description of a flattened tag. The flattened tag information hash entries +are copied from the corresponding structure field definitions, even for +pre-defined flattened tags. The exception is that the List property is +generated automatically unless explicity set to 0 in a pre-defined flattened +tag. + +-------------------------------------------------------------------------------- diff --git a/lib/Image/ExifTool/RIFF.pm b/lib/Image/ExifTool/RIFF.pm new file mode 100644 index 0000000..a5aa8b9 --- /dev/null +++ b/lib/Image/ExifTool/RIFF.pm @@ -0,0 +1,1745 @@ +#------------------------------------------------------------------------------ +# File: RIFF.pm +# +# Description: Read RIFF/AVI/WAV meta information +# +# Revisions: 09/14/2005 - P. Harvey Created +# 06/28/2017 - PH Added MBWF/RF64 support +# +# References: 1) http://www.exif.org/Exif2-2.PDF +# 2) http://www.vlsi.fi/datasheets/vs1011.pdf +# 3) http://www.music-center.com.br/spec_rif.htm +# 4) http://www.codeproject.com/audio/wavefiles.asp +# 5) http://msdn.microsoft.com/archive/en-us/directx9_c/directx/htm/avirifffilereference.asp +# 6) http://research.microsoft.com/invisible/tests/riff.h.htm +# 7) http://www.onicos.com/staff/iz/formats/wav.html +# 8) http://graphics.cs.uni-sb.de/NMM/dist-0.9.1/Docs/Doxygen/html/mmreg_8h-source.html +# 9) http://developers.videolan.org/vlc/vlc/doc/doxygen/html/codecs_8h-source.html +# 10) http://wiki.multimedia.cx/index.php?title=TwoCC +# 11) Andreas Winter (SCLive) private communication +# 12) http://abcavi.kibi.ru/infotags.htm +# 13) http://tech.ebu.ch/docs/tech/tech3285.pdf +# 14) https://developers.google.com/speed/webp/docs/riff_container +# 15) https://tech.ebu.ch/docs/tech/tech3306-2009.pdf +#------------------------------------------------------------------------------ + +package Image::ExifTool::RIFF; + +use strict; +use vars qw($VERSION); +use Image::ExifTool qw(:DataAccess :Utils); + +$VERSION = '1.51'; + +sub ConvertTimecode($); +sub ProcessSGLT($$$); +sub ProcessSLLT($$$); + +# recognized RIFF variants +my %riffType = ( + 'WAVE' => 'WAV', 'AVI ' => 'AVI', 'WEBP' => 'WEBP', + 'LA02' => 'LA', 'LA03' => 'LA', 'LA04' => 'LA', + 'OFR ' => 'OFR', 'LPAC' => 'PAC', 'wvpk' => 'WV', +); + +# MIME types of recognized RIFF-format files +my %riffMimeType = ( + WAV => 'audio/x-wav', + AVI => 'video/x-msvideo', + WEBP => 'image/webp', + LA => 'audio/x-nspaudio', + OFR => 'audio/x-ofr', + PAC => 'audio/x-lpac', + WV => 'audio/x-wavpack', +); + +# character sets for recognized Windows code pages +my %code2charset = ( + 0 => 'Latin', + 65001 => 'UTF8', + 1252 => 'Latin', + 1250 => 'Latin2', + 1251 => 'Cyrillic', + 1253 => 'Greek', + 1254 => 'Turkish', + 1255 => 'Hebrew', + 1256 => 'Arabic', + 1257 => 'Baltic', + 1258 => 'Vietnam', + 874 => 'Thai', + 10000 => 'MacRoman', + 10029 => 'MacLatin2', + 10007 => 'MacCyrillic', + 10006 => 'MacGreek', + 10081 => 'MacTurkish', + 10010 => 'MacRomanian', + 10079 => 'MacIceland', + 10082 => 'MacCroatian', +); + +%Image::ExifTool::RIFF::audioEncoding = ( #2 + Notes => 'These "TwoCC" audio encoding codes are used in RIFF and ASF files.', + 0x01 => 'Microsoft PCM', + 0x02 => 'Microsoft ADPCM', + 0x03 => 'Microsoft IEEE float', + 0x04 => 'Compaq VSELP', #4 + 0x05 => 'IBM CVSD', #4 + 0x06 => 'Microsoft a-Law', + 0x07 => 'Microsoft u-Law', + 0x08 => 'Microsoft DTS', #4 + 0x09 => 'DRM', #4 + 0x0a => 'WMA 9 Speech', #9 + 0x0b => 'Microsoft Windows Media RT Voice', #10 + 0x10 => 'OKI-ADPCM', + 0x11 => 'Intel IMA/DVI-ADPCM', + 0x12 => 'Videologic Mediaspace ADPCM', #4 + 0x13 => 'Sierra ADPCM', #4 + 0x14 => 'Antex G.723 ADPCM', #4 + 0x15 => 'DSP Solutions DIGISTD', + 0x16 => 'DSP Solutions DIGIFIX', + 0x17 => 'Dialoic OKI ADPCM', #6 + 0x18 => 'Media Vision ADPCM', #6 + 0x19 => 'HP CU', #7 + 0x1a => 'HP Dynamic Voice', #10 + 0x20 => 'Yamaha ADPCM', #6 + 0x21 => 'SONARC Speech Compression', #6 + 0x22 => 'DSP Group True Speech', #6 + 0x23 => 'Echo Speech Corp.', #6 + 0x24 => 'Virtual Music Audiofile AF36', #6 + 0x25 => 'Audio Processing Tech.', #6 + 0x26 => 'Virtual Music Audiofile AF10', #6 + 0x27 => 'Aculab Prosody 1612', #7 + 0x28 => 'Merging Tech. LRC', #7 + 0x30 => 'Dolby AC2', + 0x31 => 'Microsoft GSM610', + 0x32 => 'MSN Audio', #6 + 0x33 => 'Antex ADPCME', #6 + 0x34 => 'Control Resources VQLPC', #6 + 0x35 => 'DSP Solutions DIGIREAL', #6 + 0x36 => 'DSP Solutions DIGIADPCM', #6 + 0x37 => 'Control Resources CR10', #6 + 0x38 => 'Natural MicroSystems VBX ADPCM', #6 + 0x39 => 'Crystal Semiconductor IMA ADPCM', #6 + 0x3a => 'Echo Speech ECHOSC3', #6 + 0x3b => 'Rockwell ADPCM', + 0x3c => 'Rockwell DIGITALK', + 0x3d => 'Xebec Multimedia', #6 + 0x40 => 'Antex G.721 ADPCM', + 0x41 => 'Antex G.728 CELP', + 0x42 => 'Microsoft MSG723', #7 + 0x43 => 'IBM AVC ADPCM', #10 + 0x45 => 'ITU-T G.726', #9 + 0x50 => 'Microsoft MPEG', + 0x51 => 'RT23 or PAC', #7 + 0x52 => 'InSoft RT24', #4 + 0x53 => 'InSoft PAC', #4 + 0x55 => 'MP3', + 0x59 => 'Cirrus', #7 + 0x60 => 'Cirrus Logic', #6 + 0x61 => 'ESS Tech. PCM', #6 + 0x62 => 'Voxware Inc.', #6 + 0x63 => 'Canopus ATRAC', #6 + 0x64 => 'APICOM G.726 ADPCM', + 0x65 => 'APICOM G.722 ADPCM', + 0x66 => 'Microsoft DSAT', #6 + 0x67 => 'Micorsoft DSAT DISPLAY', #6 + 0x69 => 'Voxware Byte Aligned', #7 + 0x70 => 'Voxware AC8', #7 + 0x71 => 'Voxware AC10', #7 + 0x72 => 'Voxware AC16', #7 + 0x73 => 'Voxware AC20', #7 + 0x74 => 'Voxware MetaVoice', #7 + 0x75 => 'Voxware MetaSound', #7 + 0x76 => 'Voxware RT29HW', #7 + 0x77 => 'Voxware VR12', #7 + 0x78 => 'Voxware VR18', #7 + 0x79 => 'Voxware TQ40', #7 + 0x7a => 'Voxware SC3', #10 + 0x7b => 'Voxware SC3', #10 + 0x80 => 'Soundsoft', #6 + 0x81 => 'Voxware TQ60', #7 + 0x82 => 'Microsoft MSRT24', #7 + 0x83 => 'AT&T G.729A', #7 + 0x84 => 'Motion Pixels MVI MV12', #7 + 0x85 => 'DataFusion G.726', #7 + 0x86 => 'DataFusion GSM610', #7 + 0x88 => 'Iterated Systems Audio', #7 + 0x89 => 'Onlive', #7 + 0x8a => 'Multitude, Inc. FT SX20', #10 + 0x8b => 'Infocom ITS A/S G.721 ADPCM', #10 + 0x8c => 'Convedia G729', #10 + 0x8d => 'Not specified congruency, Inc.', #10 + 0x91 => 'Siemens SBC24', #7 + 0x92 => 'Sonic Foundry Dolby AC3 APDIF', #7 + 0x93 => 'MediaSonic G.723', #8 + 0x94 => 'Aculab Prosody 8kbps', #8 + 0x97 => 'ZyXEL ADPCM', #7, + 0x98 => 'Philips LPCBB', #7 + 0x99 => 'Studer Professional Audio Packed', #7 + 0xa0 => 'Malden PhonyTalk', #8 + 0xa1 => 'Racal Recorder GSM', #10 + 0xa2 => 'Racal Recorder G720.a', #10 + 0xa3 => 'Racal G723.1', #10 + 0xa4 => 'Racal Tetra ACELP', #10 + 0xb0 => 'NEC AAC NEC Corporation', #10 + 0xff => 'AAC', #10 + 0x100 => 'Rhetorex ADPCM', #6 + 0x101 => 'IBM u-Law', #3 + 0x102 => 'IBM a-Law', #3 + 0x103 => 'IBM ADPCM', #3 + 0x111 => 'Vivo G.723', #7 + 0x112 => 'Vivo Siren', #7 + 0x120 => 'Philips Speech Processing CELP', #10 + 0x121 => 'Philips Speech Processing GRUNDIG', #10 + 0x123 => 'Digital G.723', #7 + 0x125 => 'Sanyo LD ADPCM', #8 + 0x130 => 'Sipro Lab ACEPLNET', #8 + 0x131 => 'Sipro Lab ACELP4800', #8 + 0x132 => 'Sipro Lab ACELP8V3', #8 + 0x133 => 'Sipro Lab G.729', #8 + 0x134 => 'Sipro Lab G.729A', #8 + 0x135 => 'Sipro Lab Kelvin', #8 + 0x136 => 'VoiceAge AMR', #10 + 0x140 => 'Dictaphone G.726 ADPCM', #8 + 0x150 => 'Qualcomm PureVoice', #8 + 0x151 => 'Qualcomm HalfRate', #8 + 0x155 => 'Ring Zero Systems TUBGSM', #8 + 0x160 => 'Microsoft Audio1', #8 + 0x161 => 'Windows Media Audio V2 V7 V8 V9 / DivX audio (WMA) / Alex AC3 Audio', #10 + 0x162 => 'Windows Media Audio Professional V9', #10 + 0x163 => 'Windows Media Audio Lossless V9', #10 + 0x164 => 'WMA Pro over S/PDIF', #10 + 0x170 => 'UNISYS NAP ADPCM', #10 + 0x171 => 'UNISYS NAP ULAW', #10 + 0x172 => 'UNISYS NAP ALAW', #10 + 0x173 => 'UNISYS NAP 16K', #10 + 0x174 => 'MM SYCOM ACM SYC008 SyCom Technologies', #10 + 0x175 => 'MM SYCOM ACM SYC701 G726L SyCom Technologies', #10 + 0x176 => 'MM SYCOM ACM SYC701 CELP54 SyCom Technologies', #10 + 0x177 => 'MM SYCOM ACM SYC701 CELP68 SyCom Technologies', #10 + 0x178 => 'Knowledge Adventure ADPCM', #10 + 0x180 => 'Fraunhofer IIS MPEG2AAC', #10 + 0x190 => 'Digital Theater Systems DTS DS', #10 + 0x200 => 'Creative Labs ADPCM', #6 + 0x202 => 'Creative Labs FASTSPEECH8', #6 + 0x203 => 'Creative Labs FASTSPEECH10', #6 + 0x210 => 'UHER ADPCM', #8 + 0x215 => 'Ulead DV ACM', #10 + 0x216 => 'Ulead DV ACM', #10 + 0x220 => 'Quarterdeck Corp.', #6 + 0x230 => 'I-Link VC', #8 + 0x240 => 'Aureal Semiconductor Raw Sport', #8 + 0x241 => 'ESST AC3', #10 + 0x250 => 'Interactive Products HSX', #8 + 0x251 => 'Interactive Products RPELP', #8 + 0x260 => 'Consistent CS2', #8 + 0x270 => 'Sony SCX', #8 + 0x271 => 'Sony SCY', #10 + 0x272 => 'Sony ATRAC3', #10 + 0x273 => 'Sony SPC', #10 + 0x280 => 'TELUM Telum Inc.', #10 + 0x281 => 'TELUMIA Telum Inc.', #10 + 0x285 => 'Norcom Voice Systems ADPCM', #10 + 0x300 => 'Fujitsu FM TOWNS SND', #6 + 0x301 => 'Fujitsu (not specified)', #10 + 0x302 => 'Fujitsu (not specified)', #10 + 0x303 => 'Fujitsu (not specified)', #10 + 0x304 => 'Fujitsu (not specified)', #10 + 0x305 => 'Fujitsu (not specified)', #10 + 0x306 => 'Fujitsu (not specified)', #10 + 0x307 => 'Fujitsu (not specified)', #10 + 0x308 => 'Fujitsu (not specified)', #10 + 0x350 => 'Micronas Semiconductors, Inc. Development', #10 + 0x351 => 'Micronas Semiconductors, Inc. CELP833', #10 + 0x400 => 'Brooktree Digital', #6 + 0x401 => 'Intel Music Coder (IMC)', #10 + 0x402 => 'Ligos Indeo Audio', #10 + 0x450 => 'QDesign Music', #8 + 0x500 => 'On2 VP7 On2 Technologies', #10 + 0x501 => 'On2 VP6 On2 Technologies', #10 + 0x680 => 'AT&T VME VMPCM', #7 + 0x681 => 'AT&T TCP', #8 + 0x700 => 'YMPEG Alpha (dummy for MPEG-2 compressor)', #10 + 0x8ae => 'ClearJump LiteWave (lossless)', #10 + 0x1000 => 'Olivetti GSM', #6 + 0x1001 => 'Olivetti ADPCM', #6 + 0x1002 => 'Olivetti CELP', #6 + 0x1003 => 'Olivetti SBC', #6 + 0x1004 => 'Olivetti OPR', #6 + 0x1100 => 'Lernout & Hauspie', #6 + 0x1101 => 'Lernout & Hauspie CELP codec', #10 + 0x1102 => 'Lernout & Hauspie SBC codec', #10 + 0x1103 => 'Lernout & Hauspie SBC codec', #10 + 0x1104 => 'Lernout & Hauspie SBC codec', #10 + 0x1400 => 'Norris Comm. Inc.', #6 + 0x1401 => 'ISIAudio', #7 + 0x1500 => 'AT&T Soundspace Music Compression', #7 + 0x181c => 'VoxWare RT24 speech codec', #10 + 0x181e => 'Lucent elemedia AX24000P Music codec', #10 + 0x1971 => 'Sonic Foundry LOSSLESS', #10 + 0x1979 => 'Innings Telecom Inc. ADPCM', #10 + 0x1c07 => 'Lucent SX8300P speech codec', #10 + 0x1c0c => 'Lucent SX5363S G.723 compliant codec', #10 + 0x1f03 => 'CUseeMe DigiTalk (ex-Rocwell)', #10 + 0x1fc4 => 'NCT Soft ALF2CD ACM', #10 + 0x2000 => 'FAST Multimedia DVM', #7 + 0x2001 => 'Dolby DTS (Digital Theater System)', #10 + 0x2002 => 'RealAudio 1 / 2 14.4', #10 + 0x2003 => 'RealAudio 1 / 2 28.8', #10 + 0x2004 => 'RealAudio G2 / 8 Cook (low bitrate)', #10 + 0x2005 => 'RealAudio 3 / 4 / 5 Music (DNET)', #10 + 0x2006 => 'RealAudio 10 AAC (RAAC)', #10 + 0x2007 => 'RealAudio 10 AAC+ (RACP)', #10 + 0x2500 => 'Reserved range to 0x2600 Microsoft', #10 + 0x3313 => 'makeAVIS (ffvfw fake AVI sound from AviSynth scripts)', #10 + 0x4143 => 'Divio MPEG-4 AAC audio', #10 + 0x4201 => 'Nokia adaptive multirate', #10 + 0x4243 => 'Divio G726 Divio, Inc.', #10 + 0x434c => 'LEAD Speech', #10 + 0x564c => 'LEAD Vorbis', #10 + 0x5756 => 'WavPack Audio', #10 + 0x674f => 'Ogg Vorbis (mode 1)', #10 + 0x6750 => 'Ogg Vorbis (mode 2)', #10 + 0x6751 => 'Ogg Vorbis (mode 3)', #10 + 0x676f => 'Ogg Vorbis (mode 1+)', #10 + 0x6770 => 'Ogg Vorbis (mode 2+)', #10 + 0x6771 => 'Ogg Vorbis (mode 3+)', #10 + 0x7000 => '3COM NBX 3Com Corporation', #10 + 0x706d => 'FAAD AAC', #10 + 0x7a21 => 'GSM-AMR (CBR, no SID)', #10 + 0x7a22 => 'GSM-AMR (VBR, including SID)', #10 + 0xa100 => 'Comverse Infosys Ltd. G723 1', #10 + 0xa101 => 'Comverse Infosys Ltd. AVQSBC', #10 + 0xa102 => 'Comverse Infosys Ltd. OLDSBC', #10 + 0xa103 => 'Symbol Technologies G729A', #10 + 0xa104 => 'VoiceAge AMR WB VoiceAge Corporation', #10 + 0xa105 => 'Ingenient Technologies Inc. G726', #10 + 0xa106 => 'ISO/MPEG-4 advanced audio Coding', #10 + 0xa107 => 'Encore Software Ltd G726', #10 + 0xa109 => 'Speex ACM Codec xiph.org', #10 + 0xdfac => 'DebugMode SonicFoundry Vegas FrameServer ACM Codec', #10 + 0xe708 => 'Unknown -', #10 + 0xf1ac => 'Free Lossless Audio Codec FLAC', #10 + 0xfffe => 'Extensible', #7 + 0xffff => 'Development', #4 +); + +# RIFF info +%Image::ExifTool::RIFF::Main = ( + PROCESS_PROC => \&Image::ExifTool::RIFF::ProcessChunks, + NOTES => q{ + The RIFF container format is used various types of fines including AVI, WAV, + WEBP, LA, OFR, PAC and WV. According to the EXIF specification, Meta + information is embedded in two types of RIFF C<LIST> chunks: C<INFO> and + C<exif>, and information about the audio content is stored in the C<fmt > + chunk. As well as this information, some video information and proprietary + manufacturer-specific information is also extracted. + + Large AVI videos may be a concatenation of two or more RIFF chunks. For + these files, information is extracted from subsequent RIFF chunks as + sub-documents, but the Duration is calculated for the full video. + }, + # (not 100% sure that the concatination technique mentioned above is valid - PH) + 'fmt ' => { + Name => 'AudioFormat', + SubDirectory => { TagTable => 'Image::ExifTool::RIFF::AudioFormat' }, + }, + 'bext' => { + Name => 'BroadcastExtension', + SubDirectory => { TagTable => 'Image::ExifTool::RIFF::BroadcastExt' }, + }, + ds64 => { #15 + Name => 'DataSize64', + SubDirectory => { TagTable => 'Image::ExifTool::RIFF::DS64' }, + }, + list => 'ListType', #15 + labl => { #15 + Name => 'Label', + SubDirectory => { TagTable => 'Image::ExifTool::RIFF::Label' }, + }, + LIST_INFO => { + Name => 'Info', + SubDirectory => { TagTable => 'Image::ExifTool::RIFF::Info' }, + }, + LIST_exif => { + Name => 'Exif', + SubDirectory => { TagTable => 'Image::ExifTool::RIFF::Exif' }, + }, + LIST_hdrl => { # AVI header LIST chunk + Name => 'Hdrl', + SubDirectory => { TagTable => 'Image::ExifTool::RIFF::Hdrl' }, + }, + LIST_Tdat => { #PH (Adobe CS3 Bridge) + Name => 'Tdat', + SubDirectory => { TagTable => 'Image::ExifTool::RIFF::Tdat' }, + }, + LIST_ncdt => { #PH (Nikon metadata) + Name => 'NikonData', + SubDirectory => { + TagTable => 'Image::ExifTool::Nikon::AVI', + # define ProcessProc here so we don't need to load RIFF.pm from Nikon.pm + ProcessProc => \&Image::ExifTool::RIFF::ProcessChunks, + }, + }, + LIST_hydt => { #PH (Pentax metadata) + Name => 'PentaxData', + SubDirectory => { + TagTable => 'Image::ExifTool::Pentax::AVI', + ProcessProc => \&Image::ExifTool::RIFF::ProcessChunks, + }, + }, + LIST_pntx => { #Andras Salamon (Q-S1 AVI) + Name => 'PentaxData2', + SubDirectory => { + TagTable => 'Image::ExifTool::Pentax::AVI', + ProcessProc => \&Image::ExifTool::RIFF::ProcessChunks, + }, + }, + # seen LIST_JUNK + JUNK => [ + { + Name => 'OlympusJunk', + Condition => '$$valPt =~ /^OLYMDigital Camera/', + SubDirectory => { TagTable => 'Image::ExifTool::Olympus::AVI' }, + }, + { + Name => 'CasioJunk', + Condition => '$$valPt =~ /^QVMI/', + # Casio stores standard EXIF-format information in AVI videos (EX-S600) + SubDirectory => { + TagTable => 'Image::ExifTool::Exif::Main', + DirName => 'IFD0', + Multi => 0, # (IFD1 is not written) + Start => 10, + ByteOrder => 'BigEndian', + }, + }, + { + Name => 'RicohJunk', + # the Ricoh Caplio GX stores sub-chunks in here + Condition => '$$valPt =~ /^ucmt/', + SubDirectory => { + TagTable => 'Image::ExifTool::Ricoh::AVI', + ProcessProc => \&Image::ExifTool::RIFF::ProcessChunks, + }, + }, + { + Name => 'PentaxJunk', # (Optio RS1000) + Condition => '$$valPt =~ /^IIII\x01\0/', + SubDirectory => { TagTable => 'Image::ExifTool::Pentax::Junk' }, + }, + { + Name => 'PentaxJunk2', # (Optio RZ18) + Condition => '$$valPt =~ /^PENTDigital Camera/', + SubDirectory => { TagTable => 'Image::ExifTool::Pentax::Junk2' }, + }, + { + Name => 'TextJunk', + # try to interpret unknown junk as an ASCII string + RawConv => '$val =~ /^([^\0-\x1f\x7f-\xff]+)\0*$/ ? $1 : undef', + } + ], + _PMX => { #PH (Adobe CS3 Bridge) + Name => 'XMP', + Notes => 'AVI and WAV files', + SubDirectory => { TagTable => 'Image::ExifTool::XMP::Main' }, + }, + JUNQ => { #PH (Adobe CS3 Bridge) + # old XMP is preserved when metadata is replaced in Bridge + Name => 'OldXMP', + Binary => 1, + }, + olym => { + Name => 'Olym', + SubDirectory => { TagTable => 'Image::ExifTool::Olympus::WAV' }, + }, + fact => { + Name => 'NumberOfSamples', + RawConv => 'Get32u(\$val, 0)', + }, + 'cue ' => { + Name => 'CuePoints', + Binary => 1, + }, + afsp => { }, + IDIT => { + Name => 'DateTimeOriginal', + Description => 'Date/Time Original', + Groups => { 2 => 'Time' }, + ValueConv => 'Image::ExifTool::RIFF::ConvertRIFFDate($val)', + PrintConv => '$self->ConvertDateTime($val)', + }, + CSET => { + Name => 'CharacterSet', + SubDirectory => { TagTable => 'Image::ExifTool::RIFF::CSET' }, + }, +# +# WebP-specific tags +# + EXIF => { # (WebP) + Name => 'EXIF', + Notes => 'WebP files', + SubDirectory => { + TagTable => 'Image::ExifTool::Exif::Main', + ProcessProc => \&Image::ExifTool::ProcessTIFF, + }, + }, + 'XMP ' => { #14 (WebP) + Name => 'XMP', + Notes => 'WebP files', + SubDirectory => { TagTable => 'Image::ExifTool::XMP::Main' }, + }, + ICCP => { #14 (WebP) + Name => 'ICC_Profile', + Notes => 'WebP files', + SubDirectory => { TagTable => 'Image::ExifTool::ICC_Profile::Main' }, + }, + 'VP8 ' => { # (WebP lossy) + Name => 'VP8Bitstream', + Condition => '$$valPt =~ /^...\x9d\x01\x2a/s', + SubDirectory => { TagTable => 'Image::ExifTool::RIFF::VP8' }, + }, + VP8L => { #14 (WebP lossless) + Name => 'VP8L', + Condition => '$$valPt =~ /^\x2f/', + SubDirectory => { TagTable => 'Image::ExifTool::RIFF::VP8L' }, + }, + VP8X => { #14 (WebP extended) + Name => 'VP8X', + SubDirectory => { TagTable => 'Image::ExifTool::RIFF::VP8X' }, + }, + ANIM => { #14 (WebP animation) + Name => 'ANIM', + SubDirectory => { TagTable => 'Image::ExifTool::RIFF::ANIM' }, + }, + ANMF => { #14 (WebP animation frame) + Name => 'ANMF', + SubDirectory => { TagTable => 'Image::ExifTool::RIFF::ANMF' }, + }, + ALPH => { #14 (WebP alpha) + Name => 'ALPH', + SubDirectory => { TagTable => 'Image::ExifTool::RIFF::ALPH' }, + }, + SGLT => { #PH (BikeBro) + Name => 'BikeBroAccel', + SubDirectory => { + TagTable => 'Image::ExifTool::QuickTime::Stream', + ProcessProc => \&ProcessSGLT, + }, + }, + SLLT => { #PH (BikeBro) + Name => 'BikeBroGPS', + SubDirectory => { + TagTable => 'Image::ExifTool::QuickTime::Stream', + ProcessProc => \&ProcessSLLT, + }, + }, +); + +# the maker notes used by some digital cameras +%Image::ExifTool::RIFF::Junk = ( + PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData, + GROUPS => { 2 => 'Audio' }, +); + +# Format and Audio Stream Format chunk data +%Image::ExifTool::RIFF::AudioFormat = ( + PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData, + GROUPS => { 2 => 'Audio' }, + FORMAT => 'int16u', + 0 => { + Name => 'Encoding', + PrintHex => 1, + PrintConv => \%Image::ExifTool::RIFF::audioEncoding, + SeparateTable => 'AudioEncoding', + }, + 1 => 'NumChannels', + 2 => { + Name => 'SampleRate', + Format => 'int32u', + }, + 4 => { + Name => 'AvgBytesPerSec', + Format => 'int32u', + }, + # uninteresting + # 6 => 'BlockAlignment', + 7 => 'BitsPerSample', +); + +# Broadcast Audio Extension 'bext' information (ref 13) +%Image::ExifTool::RIFF::BroadcastExt = ( + PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData, + GROUPS => { 2 => 'Audio' }, + NOTES => q{ + Information found in the Broadcast Audio Extension chunk (see + L<http://tech.ebu.ch/docs/tech/tech3285.pdf>). + }, + 0 => { + Name => 'Description', + Format => 'string[256]', + }, + 256 => { + Name => 'Originator', + Format => 'string[32]', + }, + 288 => { + Name => 'OriginatorReference', + Format => 'string[32]', + }, + 320 => { + Name => 'DateTimeOriginal', + Description => 'Date/Time Original', + Groups => { 2 => 'Time' }, + Format => 'string[18]', + ValueConv => '$_=$val; tr/-/:/; s/^(\d{4}:\d{2}:\d{2})/$1 /; $_', + PrintConv => '$self->ConvertDateTime($val)', + }, + 338 => { + Name => 'TimeReference', + Notes => 'first sample count since midnight', + Format => 'int32u[2]', + ValueConv => 'my @v=split(" ",$val); $v[0] + $v[1] * 4294967296', + }, + 346 => { + Name => 'BWFVersion', + Format => 'int16u', + }, + # 348 - int8u[64] - SMPTE 330M UMID (Unique Material Identifier) + # 412 - int8u[190] - reserved + 602 => { + Name => 'CodingHistory', + Format => 'string[$size-602]', + }, +); + +# 64-bit chunk sizes (ref 15) +%Image::ExifTool::RIFF::DS64 = ( + PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData, + GROUPS => { 2 => 'Audio' }, + FORMAT => 'int64u', + NOTES => q{ + 64-bit data sizes for MBWF/RF64 files. See + L<https://tech.ebu.ch/docs/tech/tech3306-2009.pdf> for the specification. + }, + 0 => { + Name => 'RIFFSize64', + PrintConv => \&Image::ExifTool::ConvertFileSize, + }, + 1 => { + Name => 'DataSize64', + DataMember => 'DataSize64', + RawConv => '$$self{DataSize64} = $val', + PrintConv => \&Image::ExifTool::ConvertFileSize, + }, + 2 => 'NumberOfSamples64', + # (after this comes a table of size overrides for chunk + # types other than 'data', but since these are currently + # very unlikely, support for these is not yet implemented) +); + +# cue point labels (ref 15) +%Image::ExifTool::RIFF::Label = ( + PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData, + GROUPS => { 2 => 'Audio' }, + FORMAT => 'int32u', + 0 => 'LabelID', + 1 => { + Name => 'LabelText', + Format => 'string[$size-4]', + }, +); + +# Sub chunks of INFO LIST chunk +%Image::ExifTool::RIFF::Info = ( + PROCESS_PROC => \&Image::ExifTool::RIFF::ProcessChunks, + GROUPS => { 2 => 'Audio' }, + FORMAT => 'string', + NOTES => q{ + RIFF INFO tags found in AVI video and WAV audio files. Tags which are part + of the EXIF 2.3 specification have an underlined Tag Name in the HTML + version of this documentation. Other tags are found in AVI files generated + by some software. + }, + IARL => 'ArchivalLocation', + IART => { Name => 'Artist', Groups => { 2 => 'Author' } }, + ICMS => 'Commissioned', + ICMT => 'Comment', + ICOP => { Name => 'Copyright', Groups => { 2 => 'Author' } }, + ICRD => { + Name => 'DateCreated', + Groups => { 2 => 'Time' }, + ValueConv => '$_=$val; s/-/:/g; $_', + }, + ICRP => 'Cropped', + IDIM => 'Dimensions', + IDPI => 'DotsPerInch', + IENG => 'Engineer', + IGNR => 'Genre', + IKEY => 'Keywords', + ILGT => 'Lightness', + IMED => 'Medium', + INAM => 'Title', + IPLT => 'NumColors', + IPRD => 'Product', + ISBJ => 'Subject', + ISFT => { + Name => 'Software', + # remove trailing nulls/spaces and split at first null + # (Casio writes "CASIO" in unicode after the first null) + ValueConv => '$_=$val; s/(\s*\0)+$//; s/(\s*\0)/, /; s/\0+//g; $_', + }, + ISHP => 'Sharpness', + ISRC => 'Source', + ISRF => 'SourceForm', + ITCH => 'Technician', +# +# 3rd party tags +# + # internet movie database (ref 12) + ISGN => 'SecondaryGenre', + IWRI => 'WrittenBy', + IPRO => 'ProducedBy', + ICNM => 'Cinematographer', + IPDS => 'ProductionDesigner', + IEDT => 'EditedBy', + ICDS => 'CostumeDesigner', + IMUS => 'MusicBy', + ISTD => 'ProductionStudio', + IDST => 'DistributedBy', + ICNT => 'Country', + ILNG => 'Language', + IRTD => 'Rating', + ISTR => 'Starring', + # MovieID (ref12) + TITL => 'Title', + DIRC => 'Directory', + YEAR => 'Year', + GENR => 'Genre', + COMM => 'Comments', + LANG => 'Language', + AGES => 'Rated', + STAR => 'Starring', + CODE => 'EncodedBy', + PRT1 => 'Part', + PRT2 => 'NumberOfParts', + # Morgan Multimedia INFO tags (ref 12) + IAS1 => 'FirstLanguage', + IAS2 => 'SecondLanguage', + IAS3 => 'ThirdLanguage', + IAS4 => 'FourthLanguage', + IAS5 => 'FifthLanguage', + IAS6 => 'SixthLanguage', + IAS7 => 'SeventhLanguage', + IAS8 => 'EighthLanguage', + IAS9 => 'NinthLanguage', + ICAS => 'DefaultAudioStream', + IBSU => 'BaseURL', + ILGU => 'LogoURL', + ILIU => 'LogoIconURL', + IWMU => 'WatermarkURL', + IMIU => 'MoreInfoURL', + IMBI => 'MoreInfoBannerImage', + IMBU => 'MoreInfoBannerURL', + IMIT => 'MoreInfoText', + # GSpot INFO tags (ref 12) + IENC => 'EncodedBy', + IRIP => 'RippedBy', + # Sound Forge Pro tags + DISP => 'SoundSchemeTitle', + TLEN => { Name => 'Length', ValueConv => '$val/1000', PrintConv => '"$val s"' }, + TRCK => 'TrackNumber', + TURL => 'URL', + TVER => 'Version', + LOCA => 'Location', + TORG => 'Organization', + # Sony Vegas AVI tags, also used by SCLive and Adobe Premier (ref 11) + TAPE => { + Name => 'TapeName', + Groups => { 2 => 'Video' }, + }, + TCOD => { + Name => 'StartTimecode', + # this is the tape time code for the start of the video + Groups => { 2 => 'Video' }, + ValueConv => '$val * 1e-7', + PrintConv => \&ConvertTimecode, + }, + TCDO => { + Name => 'EndTimecode', + Groups => { 2 => 'Video' }, + ValueConv => '$val * 1e-7', + PrintConv => \&ConvertTimecode, + }, + VMAJ => { + Name => 'VegasVersionMajor', + Groups => { 2 => 'Video' }, + }, + VMIN => { + Name => 'VegasVersionMinor', + Groups => { 2 => 'Video' }, + }, + CMNT => { + Name => 'Comment', + Groups => { 2 => 'Video' }, + }, + RATE => { + Name => 'Rate', #? (video? units?) + Groups => { 2 => 'Video' }, + }, + STAT => { + Name => 'Statistics', + Groups => { 2 => 'Video' }, + # ("7318 0 3.430307 1", "0 0 3500.000000 1", "7 0 3.433228 1") + PrintConv => [ + '"$val frames captured"', + '"$val dropped"', + '"Data rate $val"', + { 0 => 'Bad', 1 => 'OK' }, # capture OK? + ], + }, + DTIM => { + Name => 'DateTimeOriginal', + Description => 'Date/Time Original', + Groups => { 2 => 'Time' }, + ValueConv => q{ + my @v = split ' ', $val; + return undef unless @v == 2; + # the Kodak EASYSHARE Sport stores this incorrectly as a string: + return $val if $val =~ /^\d{4}:\d{2}:\d{2} \d{2}:\d{2}:\d{2}$/; + # get time in seconds + $val = 1e-7 * ($v[0] * 4294967296 + $v[1]); + # shift from Jan 1, 1601 to Jan 1, 1970 + $val -= 134774 * 24 * 3600 if $val != 0; + return Image::ExifTool::ConvertUnixTime($val); + }, + PrintConv => '$self->ConvertDateTime($val)', + }, + # not observed, but apparently part of the standard: + IDIT => { + Name => 'DateTimeOriginal', + Description => 'Date/Time Original', + Groups => { 2 => 'Time' }, + ValueConv => 'Image::ExifTool::RIFF::ConvertRIFFDate($val)', + PrintConv => '$self->ConvertDateTime($val)', + }, + ISMP => 'TimeCode', +); + +# Sub chunks of EXIF LIST chunk +%Image::ExifTool::RIFF::Exif = ( + PROCESS_PROC => \&Image::ExifTool::RIFF::ProcessChunks, + GROUPS => { 2 => 'Audio' }, + NOTES => 'These tags are part of the EXIF 2.3 specification for WAV audio files.', + ever => 'ExifVersion', + erel => 'RelatedImageFile', + etim => { Name => 'TimeCreated', Groups => { 2 => 'Time' } }, + ecor => { Name => 'Make', Groups => { 2 => 'Camera' } }, + emdl => { Name => 'Model', Groups => { 2 => 'Camera' }, Description => 'Camera Model Name' }, + emnt => { Name => 'MakerNotes', Binary => 1 }, + eucm => { + Name => 'UserComment', + PrintConv => 'Image::ExifTool::Exif::ConvertExifText($self,$val,"RIFF:UserComment")', + }, +); + +# Sub chunks of hdrl LIST chunk +%Image::ExifTool::RIFF::Hdrl = ( + PROCESS_PROC => \&Image::ExifTool::RIFF::ProcessChunks, + GROUPS => { 2 => 'Image' }, + avih => { + Name => 'AVIHeader', + SubDirectory => { TagTable => 'Image::ExifTool::RIFF::AVIHeader' }, + }, + IDIT => { + Name => 'DateTimeOriginal', + Description => 'Date/Time Original', + Groups => { 2 => 'Time' }, + ValueConv => 'Image::ExifTool::RIFF::ConvertRIFFDate($val)', + PrintConv => '$self->ConvertDateTime($val)', + }, + ISMP => 'TimeCode', + LIST_strl => { + Name => 'Stream', + SubDirectory => { TagTable => 'Image::ExifTool::RIFF::Stream' }, + }, + LIST_odml => { + Name => 'OpenDML', + SubDirectory => { TagTable => 'Image::ExifTool::RIFF::OpenDML' }, + }, +); + +# Sub chunks of Tdat LIST chunk (ref PH) +%Image::ExifTool::RIFF::Tdat = ( + PROCESS_PROC => \&Image::ExifTool::RIFF::ProcessChunks, + GROUPS => { 2 => 'Video' }, + # (have seen tc_O, tc_A, rn_O and rn_A) +); + +# RIFF character set chunk +%Image::ExifTool::RIFF::CSET = ( + PROCESS_PROC => \&Image::ExifTool::RIFF::ProcessBinaryData, + GROUPS => { 2 => 'Other' }, + FORMAT => 'int16u', + 0 => { + Name => 'CodePage', + RawConv => '$$self{CodePage} = $val', + }, + 1 => 'CountryCode', + 2 => 'LanguageCode', + 3 => 'Dialect', +); + +%Image::ExifTool::RIFF::AVIHeader = ( + PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData, + GROUPS => { 2 => 'Video' }, + FORMAT => 'int32u', + FIRST_ENTRY => 0, + 0 => { + Name => 'FrameRate', + # (must use RawConv because raw value used in Composite tag) + RawConv => '$val ? 1e6 / $val : undef', + PrintConv => 'int($val * 1000 + 0.5) / 1000', + }, + 1 => { + Name => 'MaxDataRate', + PrintConv => 'sprintf("%.4g kB/s",$val / 1024)', + }, + # 2 => 'PaddingGranularity', + # 3 => 'Flags', + 4 => 'FrameCount', + # 5 => 'InitialFrames', + 6 => 'StreamCount', + # 7 => 'SuggestedBufferSize', + 8 => 'ImageWidth', + 9 => 'ImageHeight', +); + +%Image::ExifTool::RIFF::Stream = ( + PROCESS_PROC => \&Image::ExifTool::RIFF::ProcessChunks, + GROUPS => { 2 => 'Image' }, + strh => { + Name => 'StreamHeader', + SubDirectory => { TagTable => 'Image::ExifTool::RIFF::StreamHeader' }, + }, + strn => 'StreamName', + strd => { #PH + Name => 'StreamData', + SubDirectory => { TagTable => 'Image::ExifTool::RIFF::StreamData' }, + }, + strf => [ + { + Name => 'AudioFormat', + Condition => '$$self{RIFFStreamType} eq "auds"', + SubDirectory => { TagTable => 'Image::ExifTool::RIFF::AudioFormat' }, + }, + { + Name => 'VideoFormat', + Condition => '$$self{RIFFStreamType} eq "vids"', + SubDirectory => { TagTable => 'Image::ExifTool::BMP::Main' }, + }, + ], +); + +# Open DML tags (ref http://www.morgan-multimedia.com/download/odmlff2.pdf) +%Image::ExifTool::RIFF::OpenDML = ( + PROCESS_PROC => \&Image::ExifTool::RIFF::ProcessChunks, + GROUPS => { 2 => 'Video' }, + dmlh => { + Name => 'ExtendedAVIHeader', + SubDirectory => { TagTable => 'Image::ExifTool::RIFF::ExtAVIHdr' }, + }, +); + +# Extended AVI Header tags (ref http://www.morgan-multimedia.com/download/odmlff2.pdf) +%Image::ExifTool::RIFF::ExtAVIHdr = ( + PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData, + GROUPS => { 2 => 'Video' }, + FORMAT => 'int32u', + 0 => 'TotalFrameCount', +); + +%Image::ExifTool::RIFF::StreamHeader = ( + PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData, + GROUPS => { 2 => 'Video' }, + FORMAT => 'int32u', + FIRST_ENTRY => 0, + PRIORITY => 0, # so we get values from the first stream + 0 => { + Name => 'StreamType', + Format => 'string[4]', + RawConv => '$$self{RIFFStreamType} = $val', + PrintConv => { + auds => 'Audio', + mids => 'MIDI', + txts => 'Text', + vids => 'Video', + iavs => 'Interleaved Audio+Video', + }, + }, + 1 => [ + { + Name => 'AudioCodec', + Condition => '$$self{RIFFStreamType} eq "auds"', + Format => 'string[4]', + }, + { + Name => 'VideoCodec', + Condition => '$$self{RIFFStreamType} eq "vids"', + Format => 'string[4]', + }, + { + Name => 'Codec', + Format => 'string[4]', + }, + ], + # 2 => 'StreamFlags', + # 3 => 'StreamPriority', + # 3.5 => 'Language', + # 4 => 'InitialFrames', + 5 => [ + { + Name => 'AudioSampleRate', + Condition => '$$self{RIFFStreamType} eq "auds"', + Format => 'rational64u', + ValueConv => '$val ? 1/$val : 0', + PrintConv => 'int($val * 100 + 0.5) / 100', + }, + { + Name => 'VideoFrameRate', + Condition => '$$self{RIFFStreamType} eq "vids"', + Format => 'rational64u', + # (must use RawConv because raw value used in Composite tag) + RawConv => '$val ? 1/$val : undef', + PrintConv => 'int($val * 1000 + 0.5) / 1000', + }, + { + Name => 'StreamSampleRate', + Format => 'rational64u', + ValueConv => '$val ? 1/$val : 0', + PrintConv => 'int($val * 1000 + 0.5) / 1000', + }, + ], + # 7 => 'Start', + 8 => [ + { + Name => 'AudioSampleCount', + Condition => '$$self{RIFFStreamType} eq "auds"', + }, + { + Name => 'VideoFrameCount', + Condition => '$$self{RIFFStreamType} eq "vids"', + }, + { + Name => 'StreamSampleCount', + }, + ], + # 9 => 'SuggestedBufferSize', + 10 => { + Name => 'Quality', + PrintConv => '$val eq 0xffffffff ? "Default" : $val', + }, + 11 => { + Name => 'SampleSize', + PrintConv => '$val ? "$val byte" . ($val==1 ? "" : "s") : "Variable"', + }, + # 12 => { Name => 'Frame', Format => 'int16u[4]' }, +); + +%Image::ExifTool::RIFF::StreamData = ( #PH + PROCESS_PROC => \&Image::ExifTool::RIFF::ProcessStreamData, + GROUPS => { 2 => 'Video' }, + NOTES => q{ + This chunk is used to store proprietary information in AVI videos from some + cameras. The first 4 characters of the data are used as the Tag ID below. + }, + AVIF => { + Name => 'AVIF', + SubDirectory => { + TagTable => 'Image::ExifTool::Exif::Main', + DirName => 'IFD0', + Start => 8, + ByteOrder => 'LittleEndian', + }, + }, + CASI => { # (used by Casio GV-10) + Name => 'CasioData', + SubDirectory => { TagTable => 'Image::ExifTool::Casio::AVI' }, + }, + Zora => 'VendorName', # (Samsung PL90 AVI files) + unknown => { + Name => 'UnknownData', + # try to interpret unknown stream data as a string + RawConv => '$_=$val; /^[^\0-\x1f\x7f-\xff]+$/ ? $_ : undef', + }, +); + +# VP8 bitstream (ref http://www.rfc-editor.org/rfc/pdfrfc/rfc6386.txt.pdf) +%Image::ExifTool::RIFF::VP8 = ( + PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData, + GROUPS => { 2 => 'Image' }, + NOTES => q{ + This chunk is found in simple-format (lossy) WebP files. See + L<https://developers.google.com/speed/webp/docs/riff_container> for the WebP + container specification. + }, + 0 => { + Name => 'VP8Version', + Mask => 0x0e, + PrintConv => { + 0 => '0 (bicubic reconstruction, normal loop)', + 1 => '1 (bilinear reconstruction, simple loop)', + 2 => '2 (bilinear reconstruction, no loop)', + 3 => '3 (no reconstruction, no loop)', + }, + }, + 6 => { + Name => 'ImageWidth', + Format => 'int16u', + Mask => 0x3fff, + }, + 6.1 => { + Name => 'HorizontalScale', + Format => 'int16u', + Mask => 0xc000, + }, + 8 => { + Name => 'ImageHeight', + Format => 'int16u', + Mask => 0x3fff, + }, + 8.1 => { + Name => 'VerticalScale', + Format => 'int16u', + Mask => 0xc000, + }, +); + +# WebP lossless info (ref 14) +%Image::ExifTool::RIFF::VP8L = ( + PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData, + NOTES => 'This chunk is found in lossless WebP files.', + GROUPS => { 2 => 'Image' }, + 1 => { + Name => 'ImageWidth', + Format => 'int16u', + ValueConv => '($val & 0x3fff) + 1', + }, + 2 => { + Name => 'ImageHeight', + Format => 'int32u', + ValueConv => '(($val >> 6) & 0x3fff) + 1', + }, +); + +# WebP extended info (ref 14) +%Image::ExifTool::RIFF::VP8X = ( + PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData, + GROUPS => { 2 => 'Image' }, + NOTES => 'This chunk is found in extended WebP files.', + # 0 - bitmask: 2=ICC, 3=alpha, 4=EXIF, 5=XMP, 6=animation + 4 => { + Name => 'ImageWidth', + Format => 'int32u', + ValueConv => '($val & 0xffffff) + 1', + }, + 6 => { + Name => 'ImageHeight', + Format => 'int32u', + ValueConv => '($val >> 8) + 1', + }, +); + +# WebP animation info (ref 14) +%Image::ExifTool::RIFF::ANIM = ( + PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData, + GROUPS => { 2 => 'Image' }, + NOTES => 'WebP animation chunk.', + 0 => { + Name => 'BackgroundColor', + Format => 'int8u[4]', + }, + 4 => { + Name => 'AnimationLoopCount', + PrintConv => '$val || "inf"', + }, +); + +# WebP animation frame info (ref 14) +%Image::ExifTool::RIFF::ANMF = ( + PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData, + GROUPS => { 2 => 'Image' }, + NOTES => 'WebP animation frame chunk.', + 12 => { + Name => 'Duration', + Format => 'int32u', + Notes => 'extracted as the sum of durations of all animation frames', + RawConv => q{ + if (defined $$self{VALUE}{Duration}) { + $$self{VALUE}{Duration} += $val & 0x0fff; + return undef; + } + return $val & 0x0fff; + }, + ValueConv => '$val / 1000', + PrintConv => 'ConvertDuration($val)', + }, +); + +# WebP alpha info (ref 14) +%Image::ExifTool::RIFF::ALPH = ( + PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData, + GROUPS => { 2 => 'Image' }, + NOTES => 'WebP alpha chunk.', + 0 => { + Name => 'AlphaPreprocessing', + Mask => 0x03, + PrintConv => { + 0 => 'none', + 1 => 'Level Reduction', + }, + }, + 0.1 => { + Name => 'AlphaFiltering', + Mask => 0x03, + PrintConv => { + 0 => 'none', + 1 => 'Horizontal', + 2 => 'Vertical', + 3 => 'Gradient', + }, + }, + 0.2 => { + Name => 'AlphaCompression', + Mask => 0x03, + PrintConv => { + 0 => 'none', + 1 => 'Lossless', + }, + }, +); + +# RIFF composite tags +%Image::ExifTool::RIFF::Composite = ( + Duration => { + Require => { + 0 => 'RIFF:FrameRate', + 1 => 'RIFF:FrameCount', + }, + Desire => { + 2 => 'VideoFrameRate', + 3 => 'VideoFrameCount', + }, + RawConv => 'Image::ExifTool::RIFF::CalcDuration($self, @val)', + PrintConv => 'ConvertDuration($val)', + }, + Duration2 => { + Name => 'Duration', + Require => { + 0 => 'RIFF:AvgBytesPerSec', + 1 => 'FileSize', + }, + Desire => { + # check FrameCount because this calculation only applies + # to audio-only files (eg. WAV) + 2 => 'FrameCount', + 3 => 'VideoFrameCount', + }, + # (can't calculate duration like this for compressed audio types) + RawConv => q{ + return undef if $$self{VALUE}{FileType} =~ /^(LA|OFR|PAC|WV)$/; + return ($val[0] and not ($val[2] or $val[3])) ? $val[1] / $val[0] : undef; + }, + PrintConv => 'ConvertDuration($val)', + }, +); + +# add our composite tags +Image::ExifTool::AddCompositeTags('Image::ExifTool::RIFF'); + + +#------------------------------------------------------------------------------ +# Convert RIFF date to EXIF format +my %monthNum = ( + Jan=>1, Feb=>2, Mar=>3, Apr=>4, May=>5, Jun=>6, + Jul=>7, Aug=>8, Sep=>9, Oct=>10,Nov=>11,Dec=>12 +); +sub ConvertRIFFDate($) +{ + my $val = shift; + my @part = split ' ', $val; + my $mon; + if (@part >= 5 and $mon = $monthNum{ucfirst(lc($part[1]))}) { + # the standard AVI date format (eg. "Mon Mar 10 15:04:43 2003") + $val = sprintf("%.4d:%.2d:%.2d %s", $part[4], + $mon, $part[2], $part[3]); + } elsif ($val =~ m{(\d{4})/\s*(\d+)/\s*(\d+)/?\s+(\d+):\s*(\d+)\s*(P?)}) { + # but the Casio QV-3EX writes dates like "2001/ 1/27 1:42PM", + # and the Casio EX-Z30 writes "2005/11/28/ 09:19"... doh! + $val = sprintf("%.4d:%.2d:%.2d %.2d:%.2d:00",$1,$2,$3,$4+($6?12:0),$5); + } elsif ($val =~ m{(\d{4})[-/](\d+)[-/](\d+)\s+(\d+:\d+:\d+)}) { + # the Konica KD500Z writes "2002-12-16 15:35:01\0\0" + $val = "$1:$2:$3 $4"; + } + return $val; +} + +#------------------------------------------------------------------------------ +# Print time +# Inputs: 0) time in seconds +# Returns: time string +sub ConvertTimecode($) +{ + my $val = shift; + my $hr = int($val / 3600); + $val -= $hr * 3600; + my $min = int($val / 60); + $val -= $min * 60; + my $ss = sprintf('%05.2f', $val); + if ($ss >= 60) { # handle round-off problems + $ss = '00.00'; + ++$min >= 60 and $min -= 60, ++$hr; + } + return sprintf('%d:%.2d:%s', $hr, $min, $ss); +} + +#------------------------------------------------------------------------------ +# Calculate duration of RIFF +# Inputs: 0) ExifTool ref, 1/2) RIFF:FrameRate/Count, 2/3) VideoFrameRate/Count +# Returns: Duration in seconds or undef +# Notes: Sums duration of all sub-documents (concatenated AVI files) +sub CalcDuration($@) +{ + my ($et, @val) = @_; + my $totalDuration = 0; + my $subDoc = 0; + my @keyList; + for (;;) { + # this is annoying. Apparently (although I couldn't verify this), FrameCount + # in the RIFF header includes multiple video tracks if they exist (eg. with the + # FujiFilm REAL 3D AVI's), but the video stream information isn't reliable for + # some cameras (eg. Olympus FE models), so use the video stream information + # only if the RIFF header duration is 2 to 3 times longer + my $dur1 = $val[1] / $val[0] if $val[0]; + if ($val[2] and $val[3]) { + my $dur2 = $val[3] / $val[2]; + my $rat = $dur1 / $dur2; + $dur1 = $dur2 if $rat > 1.9 and $rat < 3.1; + } + $totalDuration += $dur1 if defined $dur1; + last unless $subDoc++ < $$et{DOC_COUNT}; + # get tag values for next sub-document + my @tags = qw(FrameRate FrameCount VideoFrameRate VideoFrameCount); + my $rawValue = $$et{VALUE}; + my ($i, $j, $key, $keys); + for ($i=0; $i<@tags; ++$i) { + if ($subDoc == 1) { + # generate list of available keys for each tag + $keys = $keyList[$i] = [ ]; + for ($j=0; ; ++$j) { + $key = $tags[$i]; + $key .= " ($j)" if $j; + last unless defined $$rawValue{$key}; + push @$keys, $key; + } + } else { + $keys = $keyList[$i]; + } + # find key for tag in this sub-document + my $grp = "Doc$subDoc"; + $grp .= ":RIFF" if $i < 2; # (tags 0 and 1 also in RIFF group) + $key = $et->GroupMatches($grp, $keys); + $val[$i] = $key ? $$rawValue{$key} : undef; + } + last unless defined $val[0] and defined $val[1]; # (Require'd tags) + } + return $totalDuration; +} + +#------------------------------------------------------------------------------ +# Process stream data +# Inputs: 0) ExifTool object ref, 1) dirInfo reference, 2) tag table ref +# Returns: 1 on success +sub ProcessStreamData($$$) +{ + my ($et, $dirInfo, $tagTbl) = @_; + my $dataPt = $$dirInfo{DataPt}; + my $start = $$dirInfo{DirStart}; + my $size = $$dirInfo{DirLen}; + return 0 if $size < 4; + if ($et->Options('Verbose')) { + $et->VerboseDir($$dirInfo{DirName}, 0, $size); + } + my $tag = substr($$dataPt, $start, 4); + my $tagInfo = $et->GetTagInfo($tagTbl, $tag); + unless ($tagInfo) { + $tagInfo = $et->GetTagInfo($tagTbl, 'unknown'); + return 1 unless $tagInfo; + } + my $subdir = $$tagInfo{SubDirectory}; + if ($$tagInfo{SubDirectory}) { + my $offset = $$subdir{Start} || 0; + my $baseShift = $$dirInfo{DataPos} + $$dirInfo{DirStart} + $offset; + my %subdirInfo = ( + DataPt => $dataPt, + DataPos => $$dirInfo{DataPos} - $baseShift, + Base => ($$dirInfo{Base} || 0) + $baseShift, + DataLen => $$dirInfo{DataLen}, + DirStart=> $$dirInfo{DirStart} + $offset, + DirLen => $$dirInfo{DirLen} - $offset, + DirName => $$subdir{DirName}, + Parent => $$dirInfo{DirName}, + ); + unless ($offset) { + # allow processing of 2nd directory at the same address + my $addr = $subdirInfo{DirStart} + $subdirInfo{DataPos} + $subdirInfo{Base}; + delete $$et{PROCESSED}{$addr} + } + # (we could set FIRST_EXIF_POS to $subdirInfo{Base} here to make + # htmlDump offsets relative to EXIF base if we wanted...) + my $subTable = GetTagTable($$subdir{TagTable}); + $et->ProcessDirectory(\%subdirInfo, $subTable); + } else { + $et->HandleTag($tagTbl, $tag, undef, + DataPt => $dataPt, + DataPos => $$dirInfo{DataPos}, + Start => $start, + Size => $size, + TagInfo => $tagInfo, + ); + } + return 1; +} + +#------------------------------------------------------------------------------ +# Make tag information hash for unknown tag +# Inputs: 0) Tag table ref, 1) tag ID +sub MakeTagInfo($$) +{ + my ($tagTbl, $tag) = @_; + my $name = $tag; + my $n = ($name =~ s/([\x00-\x1f\x7f-\xff])/'x'.unpack('H*',$1)/eg); + # print in hex if tag is numerical + $name = sprintf('0x%.4x',unpack('N',$tag)) if $n > 2; + AddTagToTable($tagTbl, $tag, { + Name => "Unknown_$name", + Description => "Unknown $name", + Unknown => 1, + Binary => 1, + }); +} + +#------------------------------------------------------------------------------ +# Process RIFF chunks +# Inputs: 0) ExifTool object reference, 1) directory information reference +# 2) tag table reference +# Returns: 1 on success +sub ProcessChunks($$$) +{ + my ($et, $dirInfo, $tagTbl) = @_; + my $dataPt = $$dirInfo{DataPt}; + my $start = $$dirInfo{DirStart}; + my $size = $$dirInfo{DirLen}; + my $end = $start + $size; + my $base = $$dirInfo{Base}; + my $verbose = $et->Options('Verbose'); + my $unknown = $et->Options('Unknown'); + my $charset = $et->Options('CharsetRIFF'); + + unless ($charset) { + if ($$et{CodePage}) { + $charset = $$et{CodePage}; + } elsif (defined $charset and $charset eq '0') { + $charset = 'Latin'; + } + } + + $et->VerboseDir($$dirInfo{DirName}, 0, $size) if $verbose; + + while ($start + 8 < $end) { + my $tag = substr($$dataPt, $start, 4); + my $len = Get32u($dataPt, $start + 4); + $start += 8; + if ($start + $len > $end) { + $et->Warn("Bad $tag chunk"); + return 0; + } + if ($tag eq 'LIST' and $len >= 4) { + $tag .= '_' . substr($$dataPt, $start, 4); + $len -= 4; + $start += 4; + } + my $tagInfo = $et->GetTagInfo($tagTbl, $tag); + my $baseShift = 0; + my $val; + if ($tagInfo) { + if ($$tagInfo{SubDirectory}) { + # adjust base if necessary (needed for Ricoh maker notes) + my $newBase = $tagInfo->{SubDirectory}{Base}; + if (defined $newBase) { + # different than your average Base eval... + # here we use an absolute $start address + $start += $base; + #### eval Base ($start) + $newBase = eval $newBase; + $baseShift = $newBase - $base; + $start -= $base; + } + } elsif (not $$tagInfo{Binary}) { + my $format = $$tagInfo{Format} || $$tagTbl{FORMAT}; + if ($format and $format eq 'string') { + $val = substr($$dataPt, $start, $len); + $val =~ s/\0+$//; # remove trailing nulls from strings + # decode if necessary + $val = $et->Decode($val, $charset) if $charset; + } + } + } elsif ($verbose or $unknown) { + MakeTagInfo($tagTbl, $tag); + } + $et->HandleTag($tagTbl, $tag, $val, + DataPt => $dataPt, + DataPos => $$dirInfo{DataPos} - $baseShift, + Start => $start, + Size => $len, + Base => $base + $baseShift, + Addr => $base + $baseShift + $start, + ); + ++$len if $len & 0x01; # must account for padding if odd number of bytes + $start += $len; + } + return 1; +} + +#------------------------------------------------------------------------------ +# Process BikeBro SGLT chunk (accelerometer data) (ref PH) +# Inputs: 0) ExifTool ref, 1) dirInfo ref, 2) tag table ref +# Returns: 1 on success +sub ProcessSGLT($$$) +{ + my ($et, $dirInfo, $tagTbl) = @_; + my $dataPt = $$dirInfo{DataPt}; + my $dataLen = length $$dataPt; + my $ee = $et->Options('ExtractEmbedded'); + my $pos; + # example accelerometer record: + # 0 1 2 3 4 5 6 7 + # 00 00 00 24 02 00 00 01 17 04 00 00 00 00 00 00 00 00 9b 02 + # frame------ ?? Xs X---------- Ys Y---------- Zs Z---------- + $$et{SET_GROUP0} = $$et{SET_GROUP1} = 'RIFF'; + for ($pos=0; $pos<=$dataLen-20; $pos+=20) { + $$et{DOC_NUM} = ++$$et{DOC_COUNT}; + my $buff = substr($$dataPt, $pos); + my @a = unpack('NCCNCNCN', $buff); + my @acc = ($a[3]*($a[2]?-1:1)/1e5, $a[5]*($a[4]?-1:1)/1e5, $a[7]*($a[6]?-1:1)/1e5); + $et->HandleTag($tagTbl, FrameNumber => $a[0]); + $et->HandleTag($tagTbl, Accelerometer => "@acc"); + unless ($ee) { + $et->Warn('Use ExtractEmbedded option to extract all accelerometer data', 3); + last; + } + } + delete $$et{SET_GROUP0}; + delete $$et{SET_GROUP1}; + $$et{DOC_NUM} = 0; + return 0; +} + +#------------------------------------------------------------------------------ +# Process BikeBro SLLT chunk (GPS information) (ref PH) +# Inputs: 0) ExifTool ref, 1) dirInfo ref, 2) tag table ref +# Returns: 1 on success +sub ProcessSLLT($$$) +{ + my ($et, $dirInfo, $tagTbl) = @_; + my $dataPt = $$dirInfo{DataPt}; + my $dataLen = length $$dataPt; + my $ee = $et->Options('ExtractEmbedded'); + my $pos; + # example GPS record: + # 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 + # 00 00 00 17 01 00 00 03 fa 21 ec 00 35 01 6e c0 06 00 08 00 62 10 0b 1b 07 e2 03 0e 57 4e + # frame------ ?? lonDD lonDDDDDDDD latDD latDDDDDDDD alt-- spd-- hr mn sc yr--- mn dy EW NS + $$et{SET_GROUP0} = $$et{SET_GROUP1} = 'RIFF'; + for ($pos=0; $pos<=$dataLen-30; $pos+=30) { + $$et{DOC_NUM} = ++$$et{DOC_COUNT}; + my $buff = substr($$dataPt, $pos); + my @a = unpack('NCnNnNnnCCCnCCaa', $buff); + # - is $a[1] perhaps GPSStatus? (only seen 1, or perhaps record type 1=GPS, 2=acc?) + my $time = sprintf('%.4d:%.2d:%.2d %.2d:%.2d:%.2dZ', @a[11..13, 8..10]); + $et->HandleTag($tagTbl, FrameNumber => $a[0]); + $et->HandleTag($tagTbl, GPSDateTime => $time); + $et->HandleTag($tagTbl, GPSLatitude => ($a[4] + $a[5]/1e8) * ($a[15] eq 'S' ? -1 : 1)); + $et->HandleTag($tagTbl, GPSLongitude => ($a[2] + $a[3]/1e8) * ($a[14] eq 'W' ? -1 : 1)); + $et->HandleTag($tagTbl, GPSAltitude => $a[6]); + $et->HandleTag($tagTbl, GPSSpeed => $a[7]); + $et->HandleTag($tagTbl, GPSSpeedRef => 'K'); + unless ($ee) { + $et->Warn('Use ExtractEmbedded option to extract timed GPS', 3); + last; + } + } + delete $$et{SET_GROUP0}; + delete $$et{SET_GROUP1}; + $$et{DOC_NUM} = 0; + return 1; +} + +#------------------------------------------------------------------------------ +# Extract information from a RIFF file +# Inputs: 0) ExifTool object reference, 1) DirInfo reference +# Returns: 1 on success, 0 if this wasn't a valid RIFF file +sub ProcessRIFF($$) +{ + my ($et, $dirInfo) = @_; + my $raf = $$dirInfo{RAF}; + my ($buff, $buf2, $type, $mime, $err, $rf64); + my $verbose = $et->Options('Verbose'); + my $unknown = $et->Options('Unknown'); + + # verify this is a valid RIFF file + return 0 unless $raf->Read($buff, 12) == 12; + if ($buff =~ /^(RIFF|RF64)....(.{4})/s) { + $type = $riffType{$2}; + $rf64 = 1 if $1 eq 'RF64'; + } else { + # minimal support for a few obscure lossless audio formats... + return 0 unless $buff =~ /^(LA0[234]|OFR |LPAC|wvpk)/ and $raf->Read($buf2, 1024); + $type = $riffType{$1}; + $buff .= $buf2; + return 0 unless $buff =~ /WAVE(.{4})?fmt /sg and $raf->Seek(pos($buff) - 4, 0); + } + $$raf{NoBuffer} = 1 if $et->Options('FastScan'); # disable buffering in FastScan mode + $mime = $riffMimeType{$type} if $type; + $et->SetFileType($type, $mime); + $$et{VALUE}{FileType} .= ' (RF64)' if $rf64; + $$et{RIFFStreamType} = ''; # initialize stream type + SetByteOrder('II'); + my $tagTbl = GetTagTable('Image::ExifTool::RIFF::Main'); + my $pos = 12; +# +# Read chunks in RIFF image +# + for (;;) { + my $num = $raf->Read($buff, 8); + if ($num < 8) { + $err = 1 if $num; + last; + } + $pos += 8; + my ($tag, $len) = unpack('a4V', $buff); + # special case: construct new tag name from specific LIST type + if ($tag eq 'LIST') { + $raf->Read($buff, 4) == 4 or $err=1, last; + $pos += 4; + $tag .= "_$buff"; + $len -= 4; # already read 4 bytes (the LIST type) + } elsif ($tag eq 'data' and $len == 0xffffffff and $$et{DataSize64}) { + $len = $$et{DataSize64}; + } + $et->VPrint(0, "RIFF '${tag}' chunk ($len bytes of data):\n"); + if ($len <= 0) { + if ($len < 0) { + $et->Warn('Invalid chunk length'); + } elsif ($tag eq "\0\0\0\0") { + # avoid reading through corupted files filled with nulls because it takes forever + $et->Warn('Encountered empty null chunk. Processing aborted'); + } else { + next; + } + last; + } + # stop when we hit the audio data or AVI index or AVI movie data + # --> no more because Adobe Bridge stores XMP after this!! + # (so now we only do this on the FastScan option) + if (($tag eq 'data' or $tag eq 'idx1' or $tag eq 'LIST_movi') and + $et->Options('FastScan')) + { + $et->VPrint(0, "(end of parsing)\n"); + last; + } + # RIFF chunks are padded to an even number of bytes + my $len2 = $len + ($len & 0x01); + if ($$tagTbl{$tag} or (($verbose or $unknown) and $tag !~ /^(data|idx1|LIST_movi|RIFF)$/)) { + $raf->Read($buff, $len2) == $len2 or $err=1, last; + MakeTagInfo($tagTbl, $tag) if not $$tagTbl{$tag} and ($verbose or $unknown); + $et->HandleTag($tagTbl, $tag, $buff, + DataPt => \$buff, + DataPos => 0, # (relative to Base) + Start => 0, + Size => $len2, + Base => $pos, + ); + } elsif ($tag eq 'RIFF') { + # don't read into RIFF chunk (eg. concatenated video file) + $raf->Read($buff, 4) == 4 or $err=1, last; + # extract information from remaining file as an embedded file + $$et{DOC_NUM} = ++$$et{DOC_COUNT} + } else { + if ($len > 0x7fffffff and not $et->Options('LargeFileSupport')) { + $et->Warn("Stopped parsing at large $tag chunk (LargeFileSupport not set)"); + last; + } + $raf->Seek($len2, 1) or $err=1, last; + } + $pos += $len2; + } + delete $$et{DOC_NUM}; + $err and $et->Warn('Error reading RIFF file (corrupted?)'); + return 1; +} + +1; # end + +__END__ + +=head1 NAME + +Image::ExifTool::RIFF - Read RIFF/AVI/WAV meta information + +=head1 SYNOPSIS + +This module is used by Image::ExifTool + +=head1 DESCRIPTION + +This module contains routines required by Image::ExifTool to extract +information from RIFF-based (Resource Interchange File Format) files, +including AVI videos, WAV audio files and WEBP images. + +=head1 AUTHOR + +Copyright 2003-2019, Phil Harvey (phil at owl.phy.queensu.ca) + +This library is free software; you can redistribute it and/or modify it +under the same terms as Perl itself. + +=head1 REFERENCES + +=over 4 + +=item L<http://www.exif.org/Exif2-2.PDF> + +=item L<http://www.vlsi.fi/datasheets/vs1011.pdf> + +=item L<http://www.music-center.com.br/spec_rif.htm> + +=item L<http://www.codeproject.com/audio/wavefiles.asp> + +=item L<http://msdn.microsoft.com/archive/en-us/directx9_c/directx/htm/avirifffilereference.asp> + +=item L<http://wiki.multimedia.cx/index.php?title=TwoCC> + +=item L<https://developers.google.com/speed/webp/docs/riff_container> + +=item L<https://tech.ebu.ch/docs/tech/tech3306-2009.pdf> + +=back + +=head1 SEE ALSO + +L<Image::ExifTool::TagNames/RIFF Tags>, +L<Image::ExifTool(3pm)|Image::ExifTool> + +=cut + diff --git a/lib/Image/ExifTool/RSRC.pm b/lib/Image/ExifTool/RSRC.pm new file mode 100644 index 0000000..fd470ba --- /dev/null +++ b/lib/Image/ExifTool/RSRC.pm @@ -0,0 +1,241 @@ +#------------------------------------------------------------------------------ +# File: RSRC.pm +# +# Description: Read Mac OS Resource information +# +# Revisions: 2010/03/17 - P. Harvey Created +# +# References: 1) http://developer.apple.com/legacy/mac/library/documentation/mac/MoreToolbox/MoreToolbox-99.html +#------------------------------------------------------------------------------ + +package Image::ExifTool::RSRC; + +use strict; +use vars qw($VERSION); +use Image::ExifTool qw(:DataAccess :Utils); + +$VERSION = '1.08'; + +# Information decoded from Mac OS resources +%Image::ExifTool::RSRC::Main = ( + GROUPS => { 2 => 'Document' }, + NOTES => q{ + Tags extracted from Mac OS resource files and DFONT files. These tags may + also be extracted from the resource fork of any file in OS X, either by + adding "/..namedfork/rsrc" to the filename to process the resource fork + alone, or by using the ExtractEmbedded (-ee) option to process the resource + fork as a sub-document of the main file. When writing, ExifTool preserves + the Mac OS resource fork by default, but it may deleted with C<-rsrc:all=> + on the command line. + }, + '8BIM' => { + Name => 'PhotoshopInfo', + SubDirectory => { TagTable => 'Image::ExifTool::Photoshop::Main' }, + }, + 'sfnt' => { + Name => 'Font', + SubDirectory => { TagTable => 'Image::ExifTool::Font::Name' }, + }, + # my samples of postscript-type DFONT files have a POST resource + # with ID 0x1f5 and the same format as a PostScript file + 'POST_0x01f5' => { + Name => 'PostscriptFont', + SubDirectory => { TagTable => 'Image::ExifTool::PostScript::Main' }, + }, + 'usro_0x0000' => 'OpenWithApplication', + 'vers_0x0001' => 'ApplicationVersion', + 'STR _0xbff3' => 'ApplicationMissingMsg', + 'STR _0xbff4' => 'CreatorApplication', + # the following written by Photoshop + # (ref http://www.adobe.ca/devnet/photoshop/psir/ps_image_resources.pdf) + 'STR#_0x0080' => 'Keywords', + 'TEXT_0x0080' => 'Description', + # don't extract PICT's because the clip region isn't set properly + # in the PICT resource for some reason. Also, a dummy 512-byte + # header would have to be added to create a valid PICT file. + # 'PICT' => { Name => 'PreviewPICT', Binary => 1 }, +); + +#------------------------------------------------------------------------------ +# Read information from a Mac resource file (ref 1) +# Inputs: 0) ExifTool ref, 1) dirInfo ref +# Returns: 1 on success, 0 if this wasn't a valid resource file +sub ProcessRSRC($$) +{ + my ($et, $dirInfo) = @_; + my $raf = $$dirInfo{RAF}; + my ($hdr, $map, $buff, $i, $j); + + # attempt to validate the format as thoroughly as practical + return 0 unless $raf->Read($hdr, 30) == 30; + my ($datOff, $mapOff, $datLen, $mapLen) = unpack('N*', $hdr); + return 0 unless $raf->Seek(0, 2); + my $fLen = $raf->Tell(); + return 0 if $datOff < 0x10 or $datOff + $datLen > $fLen; + return 0 if $mapOff < 0x10 or $mapOff + $mapLen > $fLen or $mapLen < 30; + return 0 if $datOff < $mapOff and $datOff + $datLen > $mapOff; + return 0 if $mapOff < $datOff and $mapOff + $mapLen > $datOff; + + # read the resource map + $raf->Seek($mapOff, 0) and $raf->Read($map, $mapLen) == $mapLen or return 0; + SetByteOrder('MM'); + my $typeOff = Get16u(\$map, 24); + my $nameOff = Get16u(\$map, 26); + my $numTypes = Get16u(\$map, 28); + + # validate offsets in the resource map + return 0 if $typeOff < 28 or $nameOff < 30; + + $et->SetFileType('RSRC') unless $$et{IN_RESOURCE}; + my $verbose = $et->Options('Verbose'); + my $tagTablePtr = GetTagTable('Image::ExifTool::RSRC::Main'); + $et->VerboseDir('RSRC', $numTypes+1); + + # parse resource type list + for ($i=0; $i<=$numTypes; ++$i) { + my $off = $typeOff + 2 + 8 * $i; # offset of entry in type list + last if $off + 8 > $mapLen; + my $resType = substr($map,$off,4); # resource type + my $resNum = Get16u(\$map,$off+4); # number of resources - 1 + my $refOff = Get16u(\$map,$off+6) + $typeOff; # offset to first resource reference + # loop through all resources + for ($j=0; $j<=$resNum; ++$j) { + my $roff = $refOff + 12 * $j; + last if $roff + 12 > $mapLen; + # read only the 24-bit resource data offset + my $id = Get16u(\$map,$roff); + my $resOff = (Get32u(\$map,$roff+4) & 0x00ffffff) + $datOff; + my $resNameOff = Get16u(\$map,$roff+2) + $nameOff + $mapOff; + my ($tag, $val, $valLen); + my $tagInfo = $$tagTablePtr{$resType}; + if ($tagInfo) { + $tag = $resType; + } else { + $tag = sprintf('%s_0x%.4x', $resType, $id); + $tagInfo = $$tagTablePtr{$tag}; + } + # read the resource data if necessary + if ($tagInfo or $verbose) { + unless ($raf->Seek($resOff, 0) and $raf->Read($buff, 4) == 4 and + ($valLen = unpack('N', $buff)) < 100000000 and # arbitrary size limit (100MB) + $raf->Read($val, $valLen) == $valLen) + { + $et->Warn("Error reading $resType resource"); + next; + } + } + if ($verbose) { + my ($resName, $nameLen); + $resName = '' unless $raf->Seek($resNameOff, 0) and $raf->Read($buff, 1) and + ($nameLen = ord $buff) != 0 and $raf->Read($resName, $nameLen) == $nameLen; + $et->VPrint(0,sprintf("%s resource ID 0x%.4x (offset 0x%.4x, $valLen bytes, name='%s'):\n", + $resType, $id, $resOff, $resName)); + $et->VerboseDump(\$val); + } + next unless $tagInfo; + if ($resType eq 'vers') { + # parse the 'vers' resource to get the long version string + next unless $valLen > 8; + # long version string is after short version + my $p = 7 + Get8u(\$val, 6); + next if $p >= $valLen; + my $vlen = Get8u(\$val, $p++); + next if $p + $vlen > $valLen; + my $tagTablePtr = GetTagTable('Image::ExifTool::RSRC::Main'); + $val = $et->Decode(substr($val, $p, $vlen), 'MacRoman'); + } elsif ($resType eq 'sfnt') { + # parse the OTF font block + $raf->Seek($resOff + 4, 0) or next; + $$dirInfo{Base} = $resOff + 4; + require Image::ExifTool::Font; + unless (Image::ExifTool::Font::ProcessOTF($et, $dirInfo)) { + $et->Warn('Unrecognized sfnt resource format'); + } + # assume this is a DFONT file unless processing the rsrc fork + $et->OverrideFileType('DFONT') unless $$et{DOC_NUM}; + next; + } elsif ($resType eq '8BIM') { + my $ttPtr = GetTagTable('Image::ExifTool::Photoshop::Main'); + $et->HandleTag($ttPtr, $id, $val, + DataPt => \$val, + DataPos => $resOff + 4, + Size => $valLen, + Start => 0, + Parent => 'RSRC', + ); + next; + } elsif ($resType eq 'STR ' and $valLen > 1) { + # extract Pascal string + my $len = ord $val; + next unless $valLen >= $len + 1; + $val = substr($val, 1, $len); + } elsif ($resType eq 'usro' and $valLen > 4) { + my $len = unpack('N', $val); + next unless $valLen >= $len + 4; + ($val = substr($val, 4, $len)) =~ s/\0.*//g; # truncate at null + } elsif ($resType eq 'STR#' and $valLen > 2) { + # extract list of strings (ref http://simtech.sourceforge.net/tech/strings.html) + my $num = unpack('n', $val); + next if $num & 0xf000; # (ignore special-format STR# resources) + my ($i, @vals); + my $pos = 2; + for ($i=0; $i<$num; ++$i) { + last if $pos >= $valLen; + my $len = ord substr($val, $pos++, 1); + last if $pos + $len > $valLen; + push @vals, substr($val, $pos, $len); + $pos += $len; + } + $val = \@vals; + } elsif ($resType eq 'POST') { + # assume this is a DFONT file unless processing the rsrc fork + $et->OverrideFileType('DFONT') unless $$et{DOC_NUM}; + $val = substr $val, 2; + } elsif ($resType ne 'TEXT') { + next; + } + $et->HandleTag($tagTablePtr, $tag, $val); + } + } + return 1; +} + +1; # end + +__END__ + +=head1 NAME + +Image::ExifTool::RSRC - Read Mac OS Resource information + +=head1 SYNOPSIS + +This module is used by Image::ExifTool + +=head1 DESCRIPTION + +This module contains routines required by Image::ExifTool to read Mac OS +resource files. + +=head1 AUTHOR + +Copyright 2003-2019, Phil Harvey (phil at owl.phy.queensu.ca) + +This library is free software; you can redistribute it and/or modify it +under the same terms as Perl itself. + +=head1 REFERENCES + +=over 4 + +=item L<http://developer.apple.com/legacy/mac/library/documentation/mac/MoreToolbox/MoreToolbox-99.html> + +=back + +=head1 SEE ALSO + +L<Image::ExifTool::TagNames/RSRC Tags>, +L<Image::ExifTool(3pm)|Image::ExifTool> + +=cut + diff --git a/lib/Image/ExifTool/RTF.pm b/lib/Image/ExifTool/RTF.pm new file mode 100644 index 0000000..62ad18f --- /dev/null +++ b/lib/Image/ExifTool/RTF.pm @@ -0,0 +1,385 @@ +#------------------------------------------------------------------------------ +# File: RTF.pm +# +# Description: Read Rich Text Format meta information +# +# Revisions: 2010/06/17 - P. Harvey Created +# +# References: 1) http://download.microsoft.com/download/2/f/5/2f599e18-07ee-4ec5-a1e7-f4e6a9423592/Word2007RTFSpec9.doc +# 2) http://search.cpan.org/dist/RTF-Writer/lib/RTF/Cookbook.pod +#------------------------------------------------------------------------------ + +package Image::ExifTool::RTF; + +use strict; +use vars qw($VERSION); +use Image::ExifTool qw(:DataAccess :Utils); + +$VERSION = '1.03'; + +sub ProcessUserProps($$$); + +# supported RTF character entities +my %rtfEntity = ( + par => 0x0a, + tab => 0x09, + endash => 0x2013, + emdash => 0x2014, + lquote => 0x2018, + rquote => 0x2019, + ldblquote => 0x201c, + rdblquote => 0x201d, + bullet => 0x2022, +); + +# RTF tags (ref 1) +%Image::ExifTool::RTF::Main = ( + GROUPS => { 2 => 'Document' }, + NOTES => q{ + This table lists standard tags of the RTF information group, but ExifTool + will also extract any non-standard tags found in this group. As well, + ExifTool will extract any custom properties that are found. See + L<http://www.microsoft.com/en-ca/download/details.aspx?id=10725> for the + specification. + }, + title => { }, + subject => { }, + author => { Groups => { 2 => 'Author' } }, + manager => { }, + company => { }, + copyright=> { Groups => { 2 => 'Author' } }, # (written by Apple TextEdit) + operator => { Name => 'LastModifiedBy' }, + category => { }, + keywords => { }, + comment => { }, + doccomm => { Name => 'Comments' }, + hlinkbase=> { Name => 'HyperlinkBase' }, + creatim => { + Name => 'CreateDate', + Format => 'date', + Groups => { 2 => 'Time' }, + PrintConv => '$self->ConvertDateTime($val)', + }, + revtim => { + Name => 'ModifyDate', + Format => 'date', + Groups => { 2 => 'Time' }, + PrintConv => '$self->ConvertDateTime($val)', + }, + printim => { + Name => 'LastPrinted', + Format => 'date', + Groups => { 2 => 'Time' }, + PrintConv => '$self->ConvertDateTime($val)', + }, + buptim => { + Name => 'BackupTime', + Format => 'date', + Groups => { 2 => 'Time' }, + PrintConv => '$self->ConvertDateTime($val)', + }, + edmins => { + Name => 'TotalEditTime', # in minutes + PrintConv => 'ConvertTimeSpan($val, 60)', + }, + nofpages => { Name => 'Pages' }, + nofwords => { Name => 'Words' }, + nofchars => { Name => 'Characters' }, + nofcharsws=>{ + Name => 'CharactersWithSpaces', + Notes => q{ + according to the 2007 Microsoft RTF specification this is clearly the number + of characters NOT including spaces, but Microsoft Word writes this as the + number WITH spaces, so ExifTool names this tag according to the de facto + standard + }, + }, + id => { Name => 'InternalIDNumber' }, + version => { Name => 'RevisionNumber' }, + vern => { Name => 'InternalVersionNumber' }, +); + +# lookup for user-defined properties +# (none are pre-defined and this table doesn't appear in the docs) +%Image::ExifTool::RTF::UserProps = ( + GROUPS => { 2 => 'Document' }, +); + +#------------------------------------------------------------------------------ +# Read to nested closing curly bracket "}" +# Inputs: 0) data ref, 1) optional RAF ref to read more data if available +# Returns: text inside brackets, or undef on error +# Notes: On entry the current position in the data must be set to immediately +# after the command that opens the bracket. On return the current +# position is immediately following the closing brace if the return +# value is defined. +sub ReadToNested($;$) +{ + my ($dataPt, $raf) = @_; + my $pos = pos $$dataPt; + my $level = 1; + for (;;) { + # look for the next bracket + unless ($$dataPt =~ /(\\*)([{}])/g) { + # must read some more data + my $p = length $$dataPt; + my $buff; + last unless $raf and $raf->Read($buff, 65536); + $$dataPt .= $buff; + # rewind position to include any leading backslashes + --$p while $p and substr($$dataPt, $p - 1, 1) eq '\\'; + pos($$dataPt) = $p; # set position to continue search + next; + } + # bracket is escaped if preceded by an odd number of backslashes + next if $1 and length($1) & 0x01; + $2 eq '{' and ++$level, next; + next unless --$level <= 0; + return substr($$dataPt, $pos, pos($$dataPt) - $pos - 1); + } + return undef; +} + +#------------------------------------------------------------------------------ +# Unescape RTF escape sequences +# Inputs: 0) ExifTool ref, 1) RTF text, 2) RTF character set (for hex characters) +# Returns: Unescaped text (in current ExifTool Charset) +sub UnescapeRTF($$$) +{ + my ($et, $val, $charset) = @_; + + # return now unless we have a control sequence + unless ($val =~ /\\/) { + $val =~ tr/\n\r//d; # ignore CR's and LF's + return $val; + } + # CR/LF is signficant if it terminates a control sequence (so change these to a space) + # (was $val =~ s/(^|[^\\])((?:\\\\)*)(\\[a-zA-Z]+(?:-?\d+)?)[\n\r]/$1$2$3 /g;) + $val =~ s/\\(?:([a-zA-Z]+(?:-?\d+)?)[\n\r]|(.))/'\\'.($1 ? "$1 " : $2)/sge; + # protect the newline control sequence by converting to a \par command + # (was $val =~ s/(^|[^\\])((?:\\\\)*)(\\[\n\r])/$1$2\\par /g;) + $val =~ s/(\\[\n\r])|(\\.)/$2 || '\\par '/sge; + # all other CR/LF's are ignored (so delete them) + $val =~ tr/\n\r//d; + + my $rtnVal = ''; + my $len = length $val; + my $skip = 1; # default Unicode skip count + my $p0 = 0; + + for (;;) { + # find next backslash + my $p1 = ($val =~ /\\/g) ? pos($val) : $len + 1; + # add text up to start of this control sequence (or up to end) + my $n = $p1 - $p0 - 1; + $rtnVal .= substr($val, $p0, $n) if $n > 0; + # all done if at the end or if control sequence is empty + last if $p1 >= $len; + # look for an ASCII-letter control word or Unicode control + if ($val =~ /\G([a-zA-Z]+)(-?\d+)? ?/g) { + # interpret command if recognized + if ($1 eq 'uc') { # \ucN + $skip = $2; + } elsif ($1 eq 'u') { # \uN + require Image::ExifTool::Charset; + $rtnVal .= Image::ExifTool::Charset::Recompose($et, [$2]); + if ($skip) { + # must skip the specified number of characters + # (not simple because RTF control words count as a single character) + last unless $val =~ /\G([^\\]|\\([a-zA-Z]+)(-?\d+)? ?|\\'.{2}|\\.){$skip}/g; + } + } elsif ($rtfEntity{$1}) { + require Image::ExifTool::Charset; + $rtnVal .= Image::ExifTool::Charset::Recompose($et, [$rtfEntity{$1}]); + } # (else ignore the command) + } else { + my $ch = substr($val, $p1, 1); + if ($ch eq "'") { + # hex character code + last if $p1 + 3 > $len; + my $hex = substr($val, $p1 + 1, 2); + if ($hex =~ /^[0-9a-fA-F]{2}$/) { + require Image::ExifTool::Charset; + $rtnVal .= $et->Decode(chr(hex($hex)), $charset); + } + pos($val) = $p1 + 3; # skip to after the hex code + } else { + # assume a standard control symbol (\, {, }, etc) + # (note, this may not be valid for some uncommon + # control symbols like \~ for non-breaking space) + $rtnVal .= $ch; + pos($val) = $p1 + 1; # skip to after this character + } + } + $p0 = pos($val); + } + return $rtnVal; +} + +#------------------------------------------------------------------------------ +# Read information in a RTF document +# Inputs: 0) ExifTool ref, 1) dirInfo ref +# Returns: 1 on success, 0 if this wasn't a valid RTF file +sub ProcessRTF($$) +{ + my ($et, $dirInfo) = @_; + my $raf = $$dirInfo{RAF}; + my ($buff, $buf2, $cs); + + return 0 unless $raf->Read($buff, 64) and $raf->Seek(0,0); + return 0 unless $buff =~ /^[\n\r]*\{[\n\r]*\\rtf[^a-zA-Z]/; + $et->SetFileType(); +# +# determine the RTF character set +# + if ($buff=~ /\\ansicpg(\d*)/) { + $cs = "cp$1"; + } elsif ($buff=~ /\\(ansi|mac|pc|pca)[^a-zA-Z]/) { + my %trans = ( + ansi => 'Latin', + mac => 'MacRoman', + pc => 'cp437', + pca => 'cp850', + ); + $cs = $trans{$1}; + } else { + $et->Warn('Unspecified RTF encoding. Will assume Latin'); + $cs = 'Latin'; + } + my $charset = $Image::ExifTool::charsetName{lc $cs}; + unless ($charset) { + $et->Warn("Unsupported RTF encoding $cs. Will assume Latin."); + $charset = 'Latin'; + } + my $tagTablePtr = GetTagTable('Image::ExifTool::RTF::Main'); + undef $buff; +# +# scan for \info group +# + for (;;) { + $raf->Read($buf2, 65536) or last; + if (defined $buff) { + # read more but leave some overlap for the match + $buff = substr($buff, -16) . $buf2; + } else { + $buff = $buf2; + } + next unless $buff =~ /[^\\]\{[\n\r]*\\info([^a-zA-Z])/g; + # anything but a space is included in the contents + pos($buff) = pos($buff) - 1 if $1 ne ' '; + my $info = ReadToNested(\$buff, $raf); + unless (defined $info) { + $et->Warn('Unterminated information group'); + last; + } + # process info commands (eg. "\author", "\*\copyright"); + while ($info =~ /\{[\n\r]*(\\\*[\n\r]*)?\\([a-zA-Z]+)([^a-zA-Z])/g) { + pos($info) = pos($info) - 1 if $3 ne ' '; + my $tag = $2; + my $val = ReadToNested(\$info); + last unless defined $val; + my $tagInfo = $$tagTablePtr{$tag}; + if ($tagInfo and $$tagInfo{Format} and $$tagInfo{Format} eq 'date') { + # parse RTF date commands + my %idx = (yr=>0,mo=>1,dy=>2,hr=>3,min=>4,sec=>5); + my @t = (0) x 6; + while ($val =~ /\\([a-z]+)(\d+)/g) { + next unless defined $idx{$1}; + $t[$idx{$1}] = $2; + } + $val = sprintf("%.4d:%.2d:%.2d %.2d:%.2d:%.2d", @t); + } else { + # unescape RTF string value + $val = UnescapeRTF($et, $val, $charset); + } + # create tagInfo for unknown tags + if (not $tagInfo) { + AddTagToTable($tagTablePtr, $tag, { Name => ucfirst($tag) }); + } + $et->HandleTag($tagTablePtr, $tag, $val); + } + } + return 1 unless defined $buff; +# +# scan for \userprops (but don't read more from file to find the start of this command) +# + pos($buff) = 0; + while ($buff =~ /[^\\]\{[\n\r]*\\\*[\n\r]*\\userprops([^a-zA-Z])/g) { + # Note: The RTF spec places brackets around each propinfo structure, + # but Microsoft Word doesn't write it this way, so tolerate either. + pos($buff) = pos($buff) - 1 if $1 ne ' '; + my $props = ReadToNested(\$buff, $raf); + $tagTablePtr = Image::ExifTool::GetTagTable('Image::ExifTool::RTF::UserProps'); + unless (defined $props) { + $et->Warn('Unterminated user properties'); + last; + } + # process user properties + my $tag; + while ($props =~ /\{[\n\r]*(\\\*[\n\r]*)?\\([a-zA-Z]+)([^a-zA-Z])/g) { + pos($props) = pos($props) - 1 if $3 ne ' '; + my $t = $2; + my $val = ReadToNested(\$props); + last unless defined $val; + $val = UnescapeRTF($et, $val, $charset); + if ($t eq 'propname') { + $tag = $val; + next; + } elsif ($t ne 'staticval' or not defined $tag) { + next; # ignore \linkval and \proptype for now + } + $tag =~ s/\s(.)/\U$1/g; # capitalize all words in tag name + $tag =~ tr/-_a-zA-Z0-9//dc; # remove illegal characters + next unless $tag; + # create tagInfo for unknown tags + unless ($$tagTablePtr{$tag}) { + AddTagToTable($tagTablePtr, $tag, { Name => $tag }); + } + $et->HandleTag($tagTablePtr, $tag, $val); + } + last; # (didn't really want to loop) + } + return 1; +} + +1; # end + +__END__ + +=head1 NAME + +Image::ExifTool::RTF - Read Rich Text Format meta information + +=head1 SYNOPSIS + +This module is used by Image::ExifTool + +=head1 DESCRIPTION + +This module contains definitions required by Image::ExifTool to read meta +information from RTF (Rich Text Format) documents. + +=head1 AUTHOR + +Copyright 2003-2019, Phil Harvey (phil at owl.phy.queensu.ca) + +This library is free software; you can redistribute it and/or modify it +under the same terms as Perl itself. + +=head1 REFERENCES + +=over 4 + +=item L<http://download.microsoft.com/download/2/f/5/2f599e18-07ee-4ec5-a1e7-f4e6a9423592/Word2007RTFSpec9.doc> + +=item L<http://search.cpan.org/dist/RTF-Writer/lib/RTF/Cookbook.pod> + +=back + +=head1 SEE ALSO + +L<Image::ExifTool::TagNames/RTF Tags>, +L<Image::ExifTool(3pm)|Image::ExifTool> + +=cut + diff --git a/lib/Image/ExifTool/Radiance.pm b/lib/Image/ExifTool/Radiance.pm new file mode 100644 index 0000000..f1a933d --- /dev/null +++ b/lib/Image/ExifTool/Radiance.pm @@ -0,0 +1,144 @@ +#------------------------------------------------------------------------------ +# File: Radiance.pm +# +# Description: Read Radiance RGBE HDR meta information +# +# Revisions: 2011/12/10 - P. Harvey Created +# +# References: 1) http://www.graphics.cornell.edu/online/formats/rgbe/ +# 2) http://radsite.lbl.gov/radiance/refer/filefmts.pdf +#------------------------------------------------------------------------------ + +package Image::ExifTool::Radiance; + +use strict; +use vars qw($VERSION); +use Image::ExifTool qw(:DataAccess :Utils); + +$VERSION = '1.01'; + +# Radiance tags +%Image::ExifTool::Radiance::Main = ( + GROUPS => { 2 => 'Image' }, + NOTES => q{ + Information extracted from Radiance RGBE HDR images. Tag ID's are all + uppercase as stored in the file, but converted to lowercase by when + extracting to avoid conflicts with internal ExifTool variables. See + L<http://radsite.lbl.gov/radiance/refer/filefmts.pdf> and + L<http://www.graphics.cornell.edu/online/formats/rgbe/> for the + specification. + }, + _orient => { + Name => 'Orientation', + PrintConv => { + '-Y +X' => 'Horizontal (normal)', + '-Y -X' => 'Mirror horizontal', + '+Y -X' => 'Rotate 180', + '+Y +X' => 'Mirror vertical', + '+X -Y' => 'Mirror horizontal and rotate 270 CW', + '+X +Y' => 'Rotate 90 CW', + '-X +Y' => 'Mirror horizontal and rotate 90 CW', + '-X -Y' => 'Rotate 270 CW', + }, + }, + _command => 'Command', + software => 'Software', + view => 'View', + 'format' => 'Format', # <-- this is the one that caused the conflict when uppercase + exposure => { + Name => 'Exposure', + Notes => 'divide pixel values by this to get watts/steradian/meter^2', + }, + gamma => 'Gamma', + colorcorr => 'ColorCorrection', + pixaspect => 'PixelAspectRatio', + primaries => 'ColorPrimaries', +); + +#------------------------------------------------------------------------------ +# Extract information from a Radiance HDR file +# Inputs: 0) ExifTool object reference, 1) DirInfo reference +# Returns: 1 on success, 0 if this wasn't a valid RGBE image +sub ProcessHDR($$) +{ + my ($et, $dirInfo) = @_; + my $raf = $$dirInfo{RAF}; + my $buff; + local $/ = "\x0a"; # set newline character for reading + + # verify this is a valid RIFF file + return 0 unless $raf->ReadLine($buff) and $buff =~ /^#\?(RADIANCE|RGBE)\x0a/s; + $et->SetFileType(); + my $tagTablePtr = GetTagTable('Image::ExifTool::Radiance::Main'); + + while ($raf->ReadLine($buff)) { + chomp $buff; + last unless length($buff) > 0 and length($buff) < 4096; + unless ($buff =~ /^(.*)?\s*=\s*(.*)/) { + $et->HandleTag($tagTablePtr, '_command', $buff); + next; + } + # use lower-case tag names to avoid conflicts with reserved tag table entries + my ($tag, $val) = (lc $1, $2); + my $tagInfo = $et->GetTagInfo($tagTablePtr, $tag); + unless ($tagInfo) { + my $name = $tag; + $name =~ tr/-_a-zA-Z0-9//dc; + next unless length($name) > 1; + $name = ucfirst $name; + $tagInfo = { Name => $name }; + AddTagToTable($tagTablePtr, $tag, $tagInfo); + } + $et->FoundTag($tagInfo, $val); + } + # get image dimensions + if ($raf->ReadLine($buff) and $buff =~ /([-+][XY])\s*(\d+)\s*([-+][XY])\s*(\d+)/) { + $et->HandleTag($tagTablePtr, '_orient', "$1 $3"); + $et->FoundTag('ImageHeight', $2); + $et->FoundTag('ImageWidth', $4); + } + return 1; +} + +1; # end + +__END__ + +=head1 NAME + +Image::ExifTool::Radiance - Read Radiance RGBE HDR meta information + +=head1 SYNOPSIS + +This module is used by Image::ExifTool + +=head1 DESCRIPTION + +This module contains definitions required by Image::ExifTool to extract meta +information from Radiance RGBE images. RGBE (Red Green Blue Exponent) +images are a type of high dynamic-range image. + +=head1 AUTHOR + +Copyright 2003-2019, Phil Harvey (phil at owl.phy.queensu.ca) + +This library is free software; you can redistribute it and/or modify it +under the same terms as Perl itself. + +=head1 REFERENCES + +=over 4 + +=item L<http://radsite.lbl.gov/radiance/refer/filefmts.pdf> + +=item L<http://www.graphics.cornell.edu/online/formats/rgbe/> + +=back + +=head1 SEE ALSO + +L<Image::ExifTool::TagNames/Radiance Tags>, +L<Image::ExifTool(3pm)|Image::ExifTool> + +=cut + diff --git a/lib/Image/ExifTool/Rawzor.pm b/lib/Image/ExifTool/Rawzor.pm new file mode 100644 index 0000000..5dc79e7 --- /dev/null +++ b/lib/Image/ExifTool/Rawzor.pm @@ -0,0 +1,190 @@ +#------------------------------------------------------------------------------ +# File: Rawzor.pm +# +# Description: Read meta information from Rawzor compressed images +# +# Revisions: 09/09/2008 - P. Harvey Created +# +# References: 1) http://www.rawzor.com/ +#------------------------------------------------------------------------------ + +package Image::ExifTool::Rawzor; + +use strict; +use vars qw($VERSION); +use Image::ExifTool qw(:DataAccess :Utils); + +$VERSION = '1.05'; + +# currently support this version Rawzor images +my $implementedRawzorVersion = 199; # (up to version 1.99) + +# Rawzor-specific tags +%Image::ExifTool::Rawzor::Main = ( + GROUPS => { 2 => 'Other' }, + VARS => { NO_ID => 1 }, + NOTES => q{ + Rawzor files store compressed images of other formats. As well as the + information listed below, exiftool uncompresses and extracts the meta + information from the original image. + }, + OriginalFileType => { }, + OriginalFileSize => { + PrintConv => $Image::ExifTool::Extra{FileSize}->{PrintConv}, + }, + RawzorRequiredVersion => { + ValueConv => '$val / 100', + PrintConv => 'sprintf("%.2f", $val)', + }, + RawzorCreatorVersion => { + ValueConv => '$val / 100', + PrintConv => 'sprintf("%.2f", $val)', + }, + # compression factor is originalSize/compressedSize (and compression + # ratio is the inverse - ref "Data Compression" by David Salomon) + CompressionFactor => { PrintConv => 'sprintf("%.2f", $val)' }, +); + +#------------------------------------------------------------------------------ +# Extract information from a Rawzor file +# Inputs: 0) ExifTool object reference, 1) dirInfo reference +# Returns: 1 on success, 0 if this wasn't a valid Rawzor file +sub ProcessRWZ($$) +{ + my ($et, $dirInfo) = @_; + my $raf = $$dirInfo{RAF}; + my ($buff, $buf2); + + # read the Rawzor file header: + # 0 string - "rawzor" signature + # 6 int16u - Required SDK version + # 8 int16u - Creator SDK version + # 10 int64u - RWZ file size + # 18 int64u - original raw file size + # 26 undef[12] - reserved + # 38 int64u - metadata offset + $raf->Read($buff, 46) == 46 and $buff =~ /^rawzor/ or return 0; + + SetByteOrder('II'); + my $reqVers = Get16u(\$buff, 6); + my $creatorVers = Get16u(\$buff, 8); + my $rwzSize = Get64u(\$buff, 10); + my $origSize = Get64u(\$buff, 18); + my $tagTablePtr = GetTagTable('Image::ExifTool::Rawzor::Main'); + $et->HandleTag($tagTablePtr, RawzorRequiredVersion => $reqVers); + $et->HandleTag($tagTablePtr, RawzorCreatorVersion => $creatorVers); + $et->HandleTag($tagTablePtr, OriginalFileSize => $origSize); + $et->HandleTag($tagTablePtr, CompressionFactor => $origSize/$rwzSize) if $rwzSize; + # check version numbers + if ($reqVers > $implementedRawzorVersion) { + $et->Warn("Version $reqVers Rawzor images not yet supported"); + return 1; + } + my $metaOffset = Get64u(\$buff, 38); + if ($metaOffset > 0x7fffffff) { + $et->Warn('Bad metadata offset'); + return 1; + } + # check for the ability to uncompress the information + unless (eval { require IO::Uncompress::Bunzip2 }) { + $et->Warn('Install IO::Compress::Bzip2 to decode Rawzor bzip2 compression'); + return 1; + } + # read the metadata header: + # 0 int64u - metadata section 0 end (offset in original file) + # 8 int64u - metadata section 1 start + # 16 int64u - metadata section 1 end + # 24 int64u - metadata section 2 start + # 32 undef[4] - reserved + # 36 int32u - original metadata size + # 40 int32u - compressed metadata size + unless ($raf->Seek($metaOffset, 0) and $raf->Read($buff, 44) == 44) { + $et->Warn('Error reading metadata header'); + return 1; + } + my $metaSize = Get32u(\$buff, 36); + if ($metaSize) { + $$et{DontValidateImageData} = 1; + # validate the metadata header and read the compressed metadata + my $end0 = Get64u(\$buff, 0); + my $pos1 = Get64u(\$buff, 8); + my $end1 = Get64u(\$buff, 16); + my $pos2 = Get64u(\$buff, 24); + my $len = Get32u(\$buff, 40); + unless ($raf->Read($buff, $len) == $len and + $end0 + ($end1 - $pos1) + ($origSize - $pos2) == $metaSize and + $end0 <= $pos1 and $pos1 <= $end1 and $end1 <= $pos2) + { + $et->Warn('Error reading image metadata'); + return 1; + } + # uncompress the metadata + unless (IO::Uncompress::Bunzip2::bunzip2(\$buff, \$buf2) and + length($buf2) eq $metaSize) + { + $et->Warn('Error uncompressing image metadata'); + return 1; + } + # re-assemble the original file (sans image data) + undef $buff; # (can't hurt to free memory as soon as possible) + $buff = substr($buf2, 0, $end0) . ("\0" x ($pos1 - $end0)) . + substr($buf2, $end0, $end1 - $pos1) . ("\0" x ($pos2 - $end1)) . + substr($buf2, $end0 + $end1 - $pos1, $origSize - $pos2); + undef $buf2; + + # extract original information by calling ExtractInfo recursively + $et->ExtractInfo(\$buff, { ReEntry => 1 }); + undef $buff; + } + # set OriginalFileType from FileType of original file + # then change FileType and MIMEType to indicate a Rawzor image + my $origFileType = $$et{VALUE}{FileType}; + if ($origFileType) { + $et->HandleTag($tagTablePtr, OriginalFileType => $origFileType); + $et->OverrideFileType('RWZ'); + } else { + $et->HandleTag($tagTablePtr, OriginalFileType => 'Unknown'); + $et->SetFileType(); + } + return 1; +} + +1; # end + +__END__ + +=head1 NAME + +Image::ExifTool::Rawzor - Read meta information from Rawzor compressed images + +=head1 SYNOPSIS + +This module is used by Image::ExifTool + +=head1 DESCRIPTION + +This module contains definitions required by Image::ExifTool to extract meta +information from Rawzor compressed images. + +=head1 AUTHOR + +Copyright 2003-2019, Phil Harvey (phil at owl.phy.queensu.ca) + +This library is free software; you can redistribute it and/or modify it +under the same terms as Perl itself. + +=head1 REFERENCES + +=over 4 + +=item L<http://www.rawzor.com/> + +=back + +=head1 SEE ALSO + +L<Image::ExifTool::TagNames/Rawzor Tags>, +L<Image::ExifTool(3pm)|Image::ExifTool> + +=cut + diff --git a/lib/Image/ExifTool/Real.pm b/lib/Image/ExifTool/Real.pm new file mode 100644 index 0000000..ea63bd2 --- /dev/null +++ b/lib/Image/ExifTool/Real.pm @@ -0,0 +1,739 @@ +#------------------------------------------------------------------------------ +# File: Real.pm +# +# Description: Read Real audio/video meta information +# +# Revisions: 05/16/2006 - P. Harvey Created +# +# References: 1) http://www.getid3.org/ +# 2) https://common.helixcommunity.org/nonav/2003/HCS_SDK_r5/htmfiles/rmff.htm +#------------------------------------------------------------------------------ + +package Image::ExifTool::Real; + +use strict; +use vars qw($VERSION); +use Image::ExifTool qw(:DataAccess :Utils); +use Image::ExifTool::Canon; + +$VERSION = '1.06'; + +sub ProcessRealMeta($$$); +sub ProcessRealProperties($$$); + +# Real property types (ref PH) +my %propertyType = ( + 0 => 'int32u', + 2 => 'string', +); + +# Real Metadata property types +my %metadataFormat = ( + 1 => 'string', # text + 2 => 'string', # text list + 3 => 'flag', # 1 or 4 byte integer + 4 => 'int32u', # 4-byte integer + 5 => 'undef', # binary data + 6 => 'string', # URL + 7 => 'string', # date + 8 => 'string', # file name + 9 => undef, # grouping + 10 => undef, # reference +); + +# Real Metadata property flag bit descriptions +my %metadataFlag = ( + 0 => 'Read Only', + 1 => 'Private', + 2 => 'Type Descriptor', +); + + +# tags used in RealMedia (RM, RV and RMVB) files +%Image::ExifTool::Real::Media = ( + GROUPS => { 2 => 'Video' }, + NOTES => q{ + These B<Tag ID>'s are Chunk ID's used in RealMedia and RealVideo (RM, RV and + RMVB) files. + }, + CONT => { SubDirectory => { TagTable => 'Image::ExifTool::Real::ContentDescr' } }, + MDPR => { SubDirectory => { TagTable => 'Image::ExifTool::Real::MediaProps' } }, + PROP => { SubDirectory => { TagTable => 'Image::ExifTool::Real::Properties' } }, + RJMD => { SubDirectory => { TagTable => 'Image::ExifTool::Real::Metadata' } }, +); + +# pseudo-tags used in RealAudio (RA) files +%Image::ExifTool::Real::Audio = ( + GROUPS => { 2 => 'Audio' }, + NOTES => q{ + Tags in the following table reference information extracted from various + versions of RealAudio (RA) files. + }, + '.ra3' => { Name => 'RA3', SubDirectory => { TagTable => 'Image::ExifTool::Real::AudioV3' } }, + '.ra4' => { Name => 'RA4', SubDirectory => { TagTable => 'Image::ExifTool::Real::AudioV4' } }, + '.ra5' => { Name => 'RA5', SubDirectory => { TagTable => 'Image::ExifTool::Real::AudioV5' } }, +); + +# pseudo-tags used in RealMedia Metafiles and RealMedia Plug-in Metafiles (RAM and RPM) +%Image::ExifTool::Real::Metafile = ( + GROUPS => { 2 => 'Video' }, + NOTES => q{ + Tags representing information extracted from Real Audio Metafile and + RealMedia Plug-in Metafile (RAM and RPM) files. + }, + txt => 'Text', + url => 'URL', +); + +%Image::ExifTool::Real::Properties = ( + GROUPS => { 1 => 'Real-PROP', 2 => 'Video' }, + PROCESS_PROC => \&Image::ExifTool::Canon::ProcessSerialData, + VARS => { ID_LABEL => 'Sequence' }, + FORMAT => 'int32u', + 0 => { Name => 'MaxBitrate', PrintConv => 'ConvertBitrate($val)' }, + 1 => { Name => 'AvgBitrate', PrintConv => 'ConvertBitrate($val)' }, + 2 => 'MaxPacketSize', + 3 => 'AvgPacketSize', + 4 => 'NumPackets', + 5 => { Name => 'Duration', ValueConv => '$val / 1000', PrintConv => 'ConvertDuration($val)' }, + 6 => { Name => 'Preroll', ValueConv => '$val / 1000', PrintConv => 'ConvertDuration($val)' }, + 7 => { Name => 'IndexOffset', Unknown => 1 }, + 8 => { Name => 'DataOffset', Unknown => 1 }, + 9 => { Name => 'NumStreams', Format => 'int16u' }, + 10 => { + Name => 'Flags', + Format => 'int16u', + PrintConv => { BITMASK => { + 0 => 'Allow Recording', + 1 => 'Perfect Play', + 2 => 'Live', + 3 => 'Allow Download', #PH (from rmeditor dump) + } }, + }, +); + +%Image::ExifTool::Real::MediaProps = ( + GROUPS => { 1 => 'Real-MDPR', 2 => 'Video' }, + PROCESS_PROC => \&Image::ExifTool::Canon::ProcessSerialData, + VARS => { ID_LABEL => 'Sequence' }, + FORMAT => 'int32u', + PRIORITY => 0, # first stream takes priority + 0 => { Name => 'StreamNumber', Format => 'int16u' }, + 1 => { Name => 'StreamMaxBitrate', PrintConv => 'ConvertBitrate($val)' }, + 2 => { Name => 'StreamAvgBitrate', PrintConv => 'ConvertBitrate($val)' }, + 3 => { Name => 'StreamMaxPacketSize' }, + 4 => { Name => 'StreamAvgPacketSize' }, + 5 => { Name => 'StreamStartTime' }, + 6 => { Name => 'StreamPreroll', ValueConv => '$val / 1000', PrintConv => 'ConvertDuration($val)' }, + 7 => { Name => 'StreamDuration',ValueConv => '$val / 1000', PrintConv => 'ConvertDuration($val)' }, + 8 => { Name => 'StreamNameLen', Format => 'int8u', Unknown => 1 }, + 9 => { Name => 'StreamName', Format => 'string[$val{8}]' }, + 10 => { Name => 'StreamMimeLen', Format => 'int8u', Unknown => 1 }, + 11 => { + Name => 'StreamMimeType', + Format => 'string[$val{10}]', + RawConv => '$self->{RealStreamMime} = $val', + }, + 12 => { Name => 'FileInfoLen', Unknown => 1 }, + 13 => { + Name => 'FileInfoLen2', + # if this condition fails, subsequent tags will not be processed + Condition => '$self->{RealStreamMime} eq "logical-fileinfo"', + Unknown => 1, + }, + 14 => { + Name => 'FileInfoVersion', + Format => 'int16u', + }, + 15 => { + Name => 'PhysicalStreams', + Format => 'int16u', + Unknown => 1, + }, + 16 => { + Name => 'PhysicalStreamNumbers', + Format => 'int16u[$val{15}]', + Unknown => 1, + }, + 17 => { + Name => 'DataOffsets', + Format => 'int32u[$val{15}]', + Unknown => 1, + }, + 18 => { + Name => 'NumRules', + Format => 'int16u', + Unknown => 1, + }, + 19 => { + Name => 'PhysicalStreamNumberMap', + Format => 'int16u[$val{18}]', + Unknown => 1, + }, + 20 => { + Name => 'NumProperties', + Format => 'int16u', + Unknown => 1, + }, + 21 => { + Name => 'FileInfoProperties', + Format => 'undef[$val{13}-$val{15}*6-$val{18}*2-12]', + SubDirectory => { TagTable => 'Image::ExifTool::Real::FileInfo' }, + }, +); + +# Observed FileInfo properties (ref PH) +%Image::ExifTool::Real::FileInfo = ( + GROUPS => { 1 => 'Real-MDPR', 2 => 'Video' }, + PROCESS_PROC => \&ProcessRealProperties, + NOTES => q{ + The following tags have been observed in the FileInfo properties, but any + other existing information will also be extracted. + }, + Indexable => { PrintConv => { 0 => 'False', 1 => 'True' } }, + Keywords => { }, + Description => { }, + 'File ID' => { Name => 'FileID' }, + 'Content Rating' => { + Name => 'ContentRating', + PrintConv => { + 0 => 'No Rating', + 1 => 'All Ages', + 2 => 'Older Children', + 3 => 'Younger Teens', + 4 => 'Older Teens', + 5 => 'Adult Supervision Recommended', + 6 => 'Adults Only', + }, + }, + Audiences => { }, + audioMode => { Name => 'AudioMode' }, + 'Creation Date' => { + Name => 'CreateDate', + Groups => { 2 => 'Time' }, + ValueConv => q{ + $val =~ m{(\d+)/(\d+)/(\d+)\s+(\d+):(\d+):(\d+)} ? + sprintf("%.4d:%.2d:%.2d %.2d:%.2d:%.2d",$3,$2,$1,$4,$5,$6) : $val + }, + PrintConv => '$self->ConvertDateTime($val)', + }, + 'Generated By' => { Name => 'Software' }, + 'Modification Date' => { + Name => 'ModifyDate', + Groups => { 2 => 'Time' }, + ValueConv => q{ + $val =~ m{(\d+)/(\d+)/(\d+)\s+(\d+):(\d+):(\d+)} ? + sprintf("%.4d:%.2d:%.2d %.2d:%.2d:%.2d",$3,$2,$1,$4,$5,$6) : $val + }, + PrintConv => '$self->ConvertDateTime($val)', + }, + 'Target Audiences' => { Name => 'TargetAudiences' }, + 'Audio Format' => { Name => 'AudioFormat' }, + 'Video Quality' => { Name => 'VideoQuality' }, + videoMode => { Name => 'VideoMode' }, +); + +%Image::ExifTool::Real::ContentDescr = ( + GROUPS => { 1 => 'Real-CONT', 2 => 'Video' }, + PROCESS_PROC => \&Image::ExifTool::Canon::ProcessSerialData, + VARS => { ID_LABEL => 'Sequence' }, + FORMAT => 'int16u', + 0 => { Name => 'TitleLen', Unknown => 1 }, + 1 => { Name => 'Title', Format => 'string[$val{0}]' }, + 2 => { Name => 'AuthorLen', Unknown => 1 }, + 3 => { Name => 'Author', Format => 'string[$val{2}]', Groups => { 2 => 'Author' } }, + 4 => { Name => 'CopyrightLen', Unknown => 1 }, + 5 => { Name => 'Copyright', Format => 'string[$val{4}]', Groups => { 2 => 'Author' } }, + 6 => { Name => 'CommentLen', Unknown => 1 }, + 7 => { Name => 'Comment', Format => 'string[$val{6}]' }, +); + +# Real RJMD meta information (ref PH) +%Image::ExifTool::Real::Metadata = ( + GROUPS => { 1 => 'Real-RJMD', 2 => 'Video' }, + PROCESS_PROC => \&ProcessRealMeta, + NOTES => q{ + The tags below represent information which has been observed in the Real + Metadata format, but ExifTool will extract any information it finds in this + format. (As far as I can tell from the referenced documentation, string + values should be plain text, but this is not the case for the only sample + file I have been able to obtain containing this information. These tags + could also be split into separate sub-directories, but this will wait until + I have better documentation or a more complete set of samples.) + }, + 'Album/Name' => 'AlbumName', + 'Track/Category' => 'TrackCategory', + 'Track/Comments' => 'TrackComments', + 'Track/Lyrics' => 'TrackLyrics', +); + +%Image::ExifTool::Real::AudioV3 = ( + GROUPS => { 1 => 'Real-RA3', 2 => 'Audio' }, + PROCESS_PROC => \&Image::ExifTool::Canon::ProcessSerialData, + VARS => { ID_LABEL => 'Sequence' }, + FORMAT => 'int8u', + 0 => { Name => 'Channels', Format => 'int16u' }, + 1 => { Name => 'Unknown', Format => 'int16u[3]', Unknown => 1 }, + 2 => { Name => 'BytesPerMinute', Format => 'int16u' }, + 3 => { Name => 'AudioBytes', Format => 'int32u' }, + 4 => { Name => 'TitleLen', Unknown => 1 }, + 5 => { Name => 'Title', Format => 'string[$val{4}]' }, + 6 => { Name => 'ArtistLen', Unknown => 1 }, + 7 => { Name => 'Artist', Format => 'string[$val{6}]', Groups => { 2 => 'Author' } }, + 8 => { Name => 'CopyrightLen', Unknown => 1 }, + 9 => { Name => 'Copyright', Format => 'string[$val{8}]', Groups => { 2 => 'Author' } }, + 10 => { Name => 'CommentLen', Unknown => 1 }, + 11 => { Name => 'Comment', Format => 'string[$val{10}]' }, +); + +%Image::ExifTool::Real::AudioV4 = ( + GROUPS => { 1 => 'Real-RA4', 2 => 'Audio' }, + PROCESS_PROC => \&Image::ExifTool::Canon::ProcessSerialData, + VARS => { ID_LABEL => 'Sequence' }, + FORMAT => 'int16u', + 0 => { Name => 'FourCC1', Format => 'undef[4]', Unknown => 1 }, + 1 => { Name => 'AudioFileSize', Format => 'int32u', Unknown => 1 }, + 2 => { Name => 'Version2', Unknown => 1 }, + 3 => { Name => 'HeaderSize', Format => 'int32u', Unknown => 1 }, + 4 => { Name => 'CodecFlavorID', Unknown => 1 }, + 5 => { Name => 'CodedFrameSize', Format => 'int32u', Unknown => 1 }, + 6 => { Name => 'AudioBytes', Format => 'int32u' }, + 7 => { Name => 'BytesPerMinute', Format => 'int32u' }, + 8 => { Name => 'Unknown', Format => 'int32u', Unknown => 1 }, + 9 => { Name => 'SubPacketH', Unknown => 1 }, + 10 => 'AudioFrameSize', + 11 => { Name => 'SubPacketSize', Unknown => 1 }, + 12 => { Name => 'Unknown', Unknown => 1 }, + 13 => 'SampleRate', + 14 => { Name => 'Unknown', Unknown => 1 }, + 15 => 'BitsPerSample', + 16 => 'Channels', + 17 => { Name => 'FourCC2Len', Format => 'int8u', Unknown => 1 }, + 18 => { Name => 'FourCC2', Format => 'undef[4]', Unknown => 1 }, + 19 => { Name => 'FourCC3Len', Format => 'int8u', Unknown => 1 }, + 20 => { Name => 'FourCC3', Format => 'undef[4]', Unknown => 1 }, + 21 => { Name => 'Unknown', Format => 'int8u', Unknown => 1 }, + 22 => { Name => 'Unknown', Unknown => 1 }, + 23 => { Name => 'TitleLen', Format => 'int8u', Unknown => 1 }, + 24 => { Name => 'Title', Format => 'string[$val{23}]' }, + 25 => { Name => 'ArtistLen', Format => 'int8u', Unknown => 1 }, + 26 => { Name => 'Artist', Format => 'string[$val{25}]', Groups => { 2 => 'Author' } }, + 27 => { Name => 'CopyrightLen', Format => 'int8u', Unknown => 1 }, + 28 => { Name => 'Copyright', Format => 'string[$val{27}]', Groups => { 2 => 'Author' } }, + 29 => { Name => 'CommentLen', Format => 'int8u', Unknown => 1 }, + 30 => { Name => 'Comment', Format => 'string[$val{29}]' }, +); + +%Image::ExifTool::Real::AudioV5 = ( + GROUPS => { 1 => 'Real-RA5', 2 => 'Audio' }, + PROCESS_PROC => \&Image::ExifTool::Canon::ProcessSerialData, + VARS => { ID_LABEL => 'Sequence' }, + FORMAT => 'int16u', + 0 => { Name => 'FourCC1', Format => 'undef[4]', Unknown => 1 }, + 1 => { Name => 'AudioFileSize', Format => 'int32u', Unknown => 1 }, + 2 => { Name => 'Version2', Unknown => 1 }, + 3 => { Name => 'HeaderSize', Format => 'int32u', Unknown => 1 }, + 4 => { Name => 'CodecFlavorID', Unknown => 1 }, + 5 => { Name => 'CodedFrameSize', Format => 'int32u', Unknown => 1 }, + 6 => { Name => 'AudioBytes', Format => 'int32u' }, + 7 => { Name => 'BytesPerMinute', Format => 'int32u' }, + 8 => { Name => 'Unknown', Format => 'int32u', Unknown => 1 }, + 9 => { Name => 'SubPacketH', Unknown => 1 }, + 10 => { Name => 'FrameSize', Unknown => 1 }, + 11 => { Name => 'SubPacketSize', Unknown => 1 }, + 12 => 'SampleRate', + 13 => { Name => 'SampleRate2', Unknown => 1 }, + 14 => { Name => 'BitsPerSample', Format => 'int32u' }, + 15 => 'Channels', + 16 => { Name => 'Genr', Format => 'int32u', Unknown => 1 }, + 17 => { Name => 'FourCC3', Format => 'undef[4]', Unknown => 1 }, +); + +#------------------------------------------------------------------------------ +# Process Real NameValueProperties +# Inputs: 0) ExifTool object reference, 1) dirInfo ref, 2) tag table ref +# Returns: 1 on success +sub ProcessRealProperties($$$) +{ + my ($et, $dirInfo, $tagTablePtr) = @_; + my $dataPt = $$dirInfo{DataPt}; + my $dirLen = $$dirInfo{DirLen}; + my $pos = $$dirInfo{DirStart}; + my $verbose = $et->Options('Verbose'); + + $verbose and $et->VerboseDir('RealProperties', undef, $dirLen); + + while ($pos + 6 <= $dirLen) { + + # get property size and version + my ($size, $vers) = unpack("x${pos}Nn", $$dataPt); + last if $size < 6; + unless ($vers == 0) { + $pos += $size; + next; + } + $pos += 6; + + my $tagLen = unpack("x${pos}C", $$dataPt); + ++$pos; + + last if $pos + $tagLen > $dirLen; + my $tag = substr($$dataPt, $pos, $tagLen); + $pos += $tagLen; + + last if $pos + 6 > $dirLen; + my ($type, $valLen) = unpack("x${pos}Nn", $$dataPt); + $pos += 6; + + last if $pos + $valLen > $dirLen; + my $format = $propertyType{$type} || 'undef'; + my $count = int($valLen / Image::ExifTool::FormatSize($format)); + my $val = ReadValue($dataPt, $pos, $format, $count, $dirLen-$pos); + + my $tagInfo = $et->GetTagInfo($tagTablePtr, $tag); + unless ($tagInfo) { + my $tagName; + ($tagName = $tag) =~ s/\s+//g; + next unless $tagName =~ /^\w+$/; # ignore crazy names + $tagInfo = { Name => ucfirst($tagName) }; + AddTagToTable($tagTablePtr, $tag, $tagInfo); + } + if ($verbose) { + $et->VerboseInfo($tag, $tagInfo, + Table => $tagTablePtr, + Value => $val, + DataPt => $dataPt, + Size => $valLen, + Start => $pos, + Addr => $pos + $$dirInfo{DataPos}, + Format => $format, + Count => $count, + ); + } + $et->FoundTag($tagInfo, $val); + $pos += $valLen; + } + return 1; +} + +#------------------------------------------------------------------------------ +# Process Real metadata properties +# Inputs: 0) ExifTool object reference, 1) dirInfo ref, 2) tag table ref +# Returns: 1 on success +sub ProcessRealMeta($$$) +{ + my ($et, $dirInfo, $tagTablePtr) = @_; + my $dataPt = $$dirInfo{DataPt}; + my $dataPos = $$dirInfo{DataPos}; + my $pos = $$dirInfo{DirStart}; + my $dirEnd = $pos + $$dirInfo{DirLen}; + my $verbose = $et->Options('Verbose'); + my $prefix = $$dirInfo{Prefix} || ''; + $prefix and $prefix .= '/'; + + $verbose and $et->VerboseDir('RealMetadata', undef, $$dirInfo{DirLen}); + + for (;;) { + last if $pos + 28 > $dirEnd; + # extract fixed-position metadata structure members + my ($size, $type, $flags, $valuePos, $subPropPos, $numSubProps, $nameLen) + = unpack("x${pos}N7", $$dataPt); + # make pointers relative to data start + $valuePos += $pos; + $subPropPos += $pos; + # validate what we have read so far + last if $pos + $size > $dirEnd; + last if $pos + 28 + $nameLen > $dirEnd; + last if $valuePos < $pos + 28 + $nameLen; + last if $valuePos + 4 > $dirEnd; + my $tag = substr($$dataPt, $pos + 28, $nameLen); + $tag =~ s/\0.*//s; # truncate at null + $tag = $prefix . $tag; + my $valueLen = unpack("x${valuePos}N", $$dataPt); + $valuePos += 4; # point at value itself + last if $valuePos + $valueLen > $dirEnd; + + my $format = $metadataFormat{$type}; + my $tagInfo = $et->GetTagInfo($tagTablePtr, $tag); + unless ($tagInfo) { + my $tagName = $tag; + $tagName =~ tr/A-Za-z0-9//dc; + $tagInfo = { Name => ucfirst($tagName) }; + AddTagToTable($tagTablePtr, $tag, $tagInfo); + } + if ($verbose) { + $format = 'undef' unless defined $format; + $flags = Image::ExifTool::DecodeBits($flags, \%metadataFlag); + } + if ($valueLen and $format) { + # (a flag can be 1 or 4 bytes) + if ($format eq 'flag') { + $format = ($valueLen == 4) ? 'int32u' : 'int8u'; + } elsif ($type == 7 and $tagInfo) { + # add PrintConv and ValueConv for "date" type + $$tagInfo{ValueConv} or $$tagInfo{ValueConv} = q{ + $val =~ /^(\d{4})(\d{2})(\d{2})(\d{2})(\d{2})(\d{2})/ ? + sprintf("%.4d:%.2d:%.2d %.2d:%.2d:%.2d",$1,$2,$3,$4,$5,$6) : + $val; + }; + $$tagInfo{PrintConv} or $$tagInfo{PrintConv} = '$self->ConvertDateTime($val)'; + } + my $count = int($valueLen / Image::ExifTool::FormatSize($format)); + my $val = ReadValue($dataPt, $valuePos, $format, $count, $dirEnd-$valuePos); + $et->HandleTag($tagTablePtr, $tag, $val, + DataPt => $dataPt, + DataPos => $dataPos, + Start => $valuePos, + Size => $valueLen, + Format => "type=$type, flags=$flags", + ); + } + # extract sub-properties + if ($numSubProps) { + my $dirStart = $valuePos + $valueLen + $numSubProps * 8; + my %dirInfo = ( + DataPt => $dataPt, + DataPos => $dataPos, + DirStart => $dirStart, + DirLen => $pos + $size - $dirStart, + Prefix => $tag, + ); + $et->ProcessDirectory(\%dirInfo, $tagTablePtr); + } + $pos += $size; # step to next Metadata structure + } + unless ($pos == $dirEnd) { + $et->Warn('Format error in Real Metadata'); + return 0; + } + return 1; +} + +#------------------------------------------------------------------------------ +# Read information frame a Real file +# Inputs: 0) ExifTool object reference, 1) Directory information reference +# Returns: 1 on success, 0 if this wasn't a valid Real file +sub ProcessReal($$) +{ + my ($et, $dirInfo) = @_; + my $raf = $$dirInfo{RAF}; + my ($buff, $tag, $vers, $extra, @mimeTypes, %dirCount); + + $raf->Read($buff, 8) == 8 or return 0; + $buff =~ m{^(\.RMF|\.ra\xfd|pnm://|rtsp://|http://)} or return 0; + + my $fast3 = $$et{OPTIONS}{FastScan} && $$et{OPTIONS}{FastScan} == 3; + my ($type, $tagTablePtr); + if ($1 eq '.RMF') { + $tagTablePtr = GetTagTable('Image::ExifTool::Real::Media'); + $type = 'RM'; + } elsif ($1 eq ".ra\xfd") { + $tagTablePtr = GetTagTable('Image::ExifTool::Real::Audio'); + $type = 'RA'; + } else { + $tagTablePtr = GetTagTable('Image::ExifTool::Real::Metafile'); + my $ext = $$et{FILE_EXT}; + $type = ($ext and $ext eq 'RPM') ? 'RPM' : 'RAM'; + require Image::ExifTool::PostScript; + local $/ = Image::ExifTool::PostScript::GetInputRecordSeparator($raf) || "\n"; + $raf->Seek(0,0); + while ($raf->ReadLine($buff)) { + last if length $buff > 256; + next unless $buff ; + chomp $buff; + if ($type) { + # must be a Real file type if protocol is http + return 0 if $buff =~ /^http/ and $buff !~ /\.(ra|rm|rv|rmvb|smil)$/i; + $et->SetFileType($type); + return 1 if $fast3; + undef $type; + } + # save URL or Text from RAM file + my $tag = $buff =~ m{^[a-z]{3,4}://} ? 'url' : 'txt'; + $et->HandleTag($tagTablePtr, $tag, $buff); + } + return 1; + } + + $et->SetFileType($type); + return 1 if $fast3; + SetByteOrder('MM'); + my $verbose = $et->Options('Verbose'); +# +# Process RealAudio file +# + if ($type eq 'RA') { + ($vers, $extra) = unpack('x4nn', $buff); + $tag = ".ra$vers"; + my $fpos = $raf->Tell(); + unless ($raf->Read($buff, 512)) { + $et->Warn('Error reading audio header'); + return 1; + } + my $tagInfo = $et->GetTagInfo($tagTablePtr, $tag); + if ($verbose > 2) { + $et->VerboseInfo($tag, $tagInfo, DataPt => \$buff, DataPos => $fpos); + } + if ($tagInfo) { + my $subTablePtr = GetTagTable($tagInfo->{SubDirectory}->{TagTable}); + my %dirInfo = ( + DataPt => \$buff, + DataPos => $fpos, + DirLen => length $buff, + DirStart => 0, + ); + $et->ProcessDirectory(\%dirInfo, $subTablePtr); + } else { + $et->Warn('Unsupported RealAudio version'); + } + return 1; + } +# +# Process RealMedia file +# + # skip the rest of the RM header + my $size = unpack('x4N', $buff); + unless ($raf->Seek($size - 8, 1)) { + $et->Warn('Error seeking in file'); + return 0; + } + + # Process RealMedia chunks + for (;;) { + $raf->Read($buff, 10) == 10 or last; + ($tag, $size, $vers) = unpack('a4Nn', $buff); + last if $tag eq "\0\0\0\0"; + if ($verbose) { + $et->VPrint(0, "$tag chunk ($size bytes):\n"); + } else { + last if $tag eq 'DATA'; # stop normal parsing at DATA tag + } + if ($size & 0x80000000) { + $et->Warn('Bad chunk header'); + last; + } + my $tagInfo = $et->GetTagInfo($tagTablePtr, $tag); + if ($tagInfo and $$tagInfo{SubDirectory}) { + my $fpos = $raf->Tell(); + unless ($raf->Read($buff, $size-10) == $size-10) { + $et->Warn("Error reading $tag chunk"); + last; + } + if ($verbose > 2) { + $et->VerboseInfo($tag, $tagInfo, DataPt => \$buff, DataPos => $fpos); + } + my $subTablePtr = GetTagTable($tagInfo->{SubDirectory}->{TagTable}); + my %dirInfo = ( + DataPt => \$buff, + DataPos => $fpos, + DirLen => length $buff, + DirStart => 0, + ); + if ($dirCount{$tag}) { + $$et{SET_GROUP1} = '+' . ++$dirCount{$tag}; + } else { + $dirCount{$tag} = 1; + } + $et->ProcessDirectory(\%dirInfo, $subTablePtr); + delete $$et{SET_GROUP1}; + # keep track of stream MIME types + my $mime = $$et{RealStreamMime}; + if ($mime) { + delete $$et{RealStreamMime}; + $mime =~ s/\0.*//s; + push @mimeTypes, $mime unless $mime =~ /^logical-/; + } + } else { + unless ($raf->Seek($size-10, 1)) { + $et->Warn('Error seeking in file'); + last; + } + } + } + # override MIMEType with stream MIME type if we only have one stream + if (@mimeTypes == 1 and length $mimeTypes[0]) { + $$et{VALUE}{MIMEType} = $mimeTypes[0]; + $et->VPrint(0, " MIMEType = $mimeTypes[0]\n"); + } +# +# Process footer containing Real metadata and ID3 information +# + if ($raf->Seek(-140, 2) and $raf->Read($buff, 12) == 12 and $buff =~ /^RMJE/) { + my $metaSize = unpack('x8N', $buff); + if ($raf->Seek(-$metaSize-12, 1) and + $raf->Read($buff, $metaSize) == $metaSize and + $buff =~ /^RJMD/) + { + my %dirInfo = ( + DataPt => \$buff, + DataPos => $raf->Tell() - $metaSize, + DirStart => 8, + DirLen => length($buff) - 8, + ); + my $tagTablePtr = GetTagTable('Image::ExifTool::Real::Metadata'); + $et->ProcessDirectory(\%dirInfo, $tagTablePtr); + } else { + $et->Warn('Bad metadata footer'); + } + if ($raf->Seek(-128, 2) and $raf->Read($buff, 128) == 128 and $buff =~ /^TAG/) { + $et->VPrint(0, "ID3v1:\n"); + my %dirInfo = ( + DataPt => \$buff, + DirStart => 0, + DirLen => length($buff), + ); + my $tagTablePtr = GetTagTable('Image::ExifTool::ID3::v1'); + $et->ProcessDirectory(\%dirInfo, $tagTablePtr); + } + } + return 1; +} + +1; # end + +__END__ + +=head1 NAME + +Image::ExifTool::Real - Read Real audio/video meta information + +=head1 SYNOPSIS + +This module is used by Image::ExifTool + +=head1 DESCRIPTION + +This module contains the routines required by Image::ExifTool to read meta +information in RealAudio (RA), RealMedia (RM, RV and RMVB) and RealMedia +Metafile (RAM and RPM) files. + +=head1 NOTES + +There must be a bug in the software that wrote the Metadata used in the test +file t/images/Real.rm because the TrackLyricsDataSize word is written +little-endian, but the Real format is big-endian. + +=head1 AUTHOR + +Copyright 2003-2019, Phil Harvey (phil at owl.phy.queensu.ca) + +This library is free software; you can redistribute it and/or modify it +under the same terms as Perl itself. + +=head1 REFERENCES + +=over 4 + +=item L<http://www.getid3.org/> + +=item L<https://common.helixcommunity.org/nonav/2003/HCS_SDK_r5/htmfiles/rmff.htm> + +=back + +=head1 SEE ALSO + +L<Image::ExifTool::TagNames/Real Tags>, +L<Image::ExifTool(3pm)|Image::ExifTool> + +=cut + diff --git a/lib/Image/ExifTool/Reconyx.pm b/lib/Image/ExifTool/Reconyx.pm new file mode 100644 index 0000000..7f069ba --- /dev/null +++ b/lib/Image/ExifTool/Reconyx.pm @@ -0,0 +1,444 @@ +#------------------------------------------------------------------------------ +# File: Reconyx.pm +# +# Description: Reconyx maker notes tags +# +# Revisions: 2011-01-11 - P. Harvey Created +# +# References: 1) RCNX_MN10.pdf (courtesy of Reconyx Inc.) +# 2) ultrafire_makernote.pdf (courtesy of Reconyx Inc.) +# 3) Reconyx private communication +#------------------------------------------------------------------------------ + +package Image::ExifTool::Reconyx; + +use strict; +use vars qw($VERSION); + +$VERSION = '1.06'; + +# info for Type2 version tags +my %versionInfo = ( + Format => 'undef[7]', + ValueConv => 'sprintf("V%.2x.%.2x %.4x:%.2x:%.2x Rev.%s", unpack("CCvCCa", $val))', + ValueConvInv => q{ + my @v = $val =~ /^V([0-9a-f]+)\.([0-9a-f]+) (\d{4}):(\d{2}):(\d{2})\s*Rev\.(\w)/i or return undef; + pack('CCvCCa', map(hex, @v[0..4]), $v[5]); + }, +); + +# maker notes for Reconyx Hyperfire cameras (ref PH) +%Image::ExifTool::Reconyx::Main = ( + GROUPS => { 0 => 'MakerNotes', 2 => 'Camera' }, + PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData, + WRITE_PROC => \&Image::ExifTool::WriteBinaryData, + CHECK_PROC => \&Image::ExifTool::CheckBinaryData, + TAG_PREFIX => 'Reconyx', + FORMAT => 'int16u', + WRITABLE => 1, + FIRST_ENTRY => 0, + NOTES => q{ + The following tags are extracted from the maker notes of Reconyx Hyperfire + cameras such as the HC500, HC600 and PC900. + }, + 0x00 => { #1 + Name => 'MakerNoteVersion', + PrintConv => 'sprintf("0x%.4x", $val)', + Writable => 0, # (we use this for identification, 0xf101 --> rev 1.0) + PrintConvInv => 'hex $val', + }, + 0x01 => { #1 + Name => 'FirmwareVersion', + Format => 'int16u[3]', + PrintConv => '$val=~tr/ /./; $val', + Writable => 0, # (we use this for identification, 0x0003 --> ver 2 or 3) + }, + 0x04 => { #1 + Name => 'FirmwareDate', + Format => 'int16u[2]', + ValueConv => q{ + my @v = split(' ',$val); + sprintf('%.4x:%.2x:%.2x', $v[0], $v[1]>>8, $v[1]&0xff); + }, + ValueConvInv => q{ + my @v = split(':', $val); + hex($v[0]) . ' ' . hex($v[1] . $v[2]); + }, + }, + 0x06 => { + Name => 'TriggerMode', + Format => 'string[2]', + PrintConv => { + C => 'CodeLoc Not Entered', #1 + E => 'External Sensor', #1 + M => 'Motion Detection', + T => 'Time Lapse', + }, + }, + 0x07 => { + Name => 'Sequence', + Format => 'int16u[2]', + PrintConv => '$val =~ s/ / of /; $val', + PrintConvInv => 'join(" ", $val=~/\d+/g)', + }, + 0x09 => { #1 + Name => 'EventNumber', + Format => 'int16u[2]', + ValueConv => 'my @v=split(" ",$val); ($v[0]<<16) + $v[1]', + ValueConvInv => '($val>>16) . " " . ($val&0xffff)', + }, + 0x0b => { + Name => 'DateTimeOriginal', + Description => 'Date/Time Original', + Format => 'int16u[6]', + Groups => { 2 => 'Time' }, + Priority => 0, # (not as reliable as EXIF) + Shift => 'Time', + ValueConv => q{ + my @a = split ' ', $val; + # have seen these values written big-endian when everything else is little-endian + if ($a[0] & 0xff00 and not $a[0] & 0xff) { + $_ = ($_ >> 8) | (($_ & 0xff) << 8) foreach @a; + } + sprintf('%.4d:%.2d:%.2d %.2d:%.2d:%.2d', @a[5,3,4,2,1,0]); + }, + ValueConvInv => q{ + my @a = ($val =~ /\d+/g); + return undef unless @a >= 6; + join ' ', @a[5,4,3,1,2,0]; + }, + PrintConv => '$self->ConvertDateTime($val)', + PrintConvInv => '$self->InverseDateTime($val)', + }, + 0x12 => { + Name => 'MoonPhase', + Groups => { 2 => 'Time' }, + PrintConv => { + 0 => 'New', + 1 => 'New Crescent', + 2 => 'First Quarter', + 3 => 'Waxing Gibbous', + 4 => 'Full', + 5 => 'Waning Gibbous', + 6 => 'Last Quarter', + 7 => 'Old Crescent', + }, + }, + 0x13 => { + Name => 'AmbientTemperatureFahrenheit', + Format => 'int16s', + PrintConv => '"$val F"', + PrintConvInv => '$val=~/(-?\d+)/ ? $1 : $val', + }, + 0x14 => { + Name => 'AmbientTemperature', + Format => 'int16s', + PrintConv => '"$val C"', + PrintConvInv => '$val=~/(-?\d+)/ ? $1 : $val', + }, + 0x15 => { + Name => 'SerialNumber', + Format => 'undef[30]', + RawConv => '$_ = $self->Decode($val, "UCS2"); s/\0.*//; $_', + RawConvInv => q{ + $_ = $self->Encode($val, "UCS2"); + $_ = substr($_, 0, 30) if length($_) > 30; + return $_; + }, + }, + 0x24 => 'Contrast', #1 + 0x25 => 'Brightness', #1 + 0x26 => 'Sharpness', #1 + 0x27 => 'Saturation', #1 + 0x28 => { + Name => 'InfraredIlluminator', + PrintConv => { 0 => 'Off', 1 => 'On' }, + }, + 0x29 => 'MotionSensitivity', #1 + 0x2a => { #1 + Name => 'BatteryVoltage', + ValueConv => '$val / 1000', + ValueConvInv => '$val * 1000', + PrintConv => '"$val V"', + PrintConvInv => '$val=~s/ ?V$//; $val', + }, + 0x2b => { + Name => 'UserLabel', + Format => 'string[22]', #1 (but manual says 16-char limit) + }, +); + +# maker notes for Reconyx UltraFire cameras (ref PH) +%Image::ExifTool::Reconyx::Type2 = ( + GROUPS => { 0 => 'MakerNotes', 2 => 'Camera' }, + PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData, + WRITE_PROC => \&Image::ExifTool::WriteBinaryData, + CHECK_PROC => \&Image::ExifTool::CheckBinaryData, + TAG_PREFIX => 'Reconyx', + WRITABLE => 1, + FIRST_ENTRY => 0, + NOTES => 'Tags extracted from models such as the UltraFire.', + # 0x0a - int32u makernote ID 0x00020000 #2 + # 0x0e - int16u makernote size #2 + # 0x12 - int32u public structure ID 0x07f100001 #2 + # 0x16 - int16u public structure size #2 (0x5d = start of public ID to end of UserLabel) + 0x18 => { Name => 'FirmwareVersion', %versionInfo }, + 0x1f => { Name => 'Micro1Version', %versionInfo }, #2 + 0x26 => { Name => 'BootLoaderVersion', %versionInfo }, #2 + 0x2d => { Name => 'Micro2Version', %versionInfo }, #2 + 0x34 => { + Name => 'TriggerMode', + Format => 'undef[1]', + PrintConv => { + M => 'Motion Detection', + T => 'Time Lapse', + P => 'Point and Shoot', #2 + }, + }, + 0x35 => { + Name => 'Sequence', + Format => 'int8u[2]', + PrintConv => '$val =~ s/ / of /; $val', + PrintConvInv => 'join(" ", $val=~/\d+/g)', + }, + 0x37 => { #2 + Name => 'EventNumber', + Format => 'int32u', + }, + 0x3b => { + Name => 'DateTimeOriginal', + Description => 'Date/Time Original', + Format => 'int8u[7]', + Groups => { 2 => 'Time' }, + Priority => 0, # (not as reliable as EXIF) + Shift => 'Time', + ValueConv => q{ + my @a = split ' ', $val; + $a[5] += pop(@a) * 256; + sprintf('%.4d:%.2d:%.2d %.2d:%.2d:%.2d', reverse @a); + }, + ValueConvInv => q{ + my @a = ($val =~ /\d+/g); + return undef unless @a >= 6; + unshift @a, ($a[0] >> 8); + $a[1] -= $a[0] * 256; + join ' ', @a[6,5,4,3,2,1,0]; + }, + PrintConv => '$self->ConvertDateTime($val)', + PrintConvInv => '$self->InverseDateTime($val)', + }, + 0x42 => { #2 + Name => 'DayOfWeek', + Groups => { 2 => 'Time' }, + PrintConv => { + 0 => 'Sunday', + 1 => 'Monday', + 2 => 'Tuesday', + 3 => 'Wednesday', + 4 => 'Thursday', + 5 => 'Friday', + 6 => 'Saturday', + }, + }, + 0x43 => { + Name => 'MoonPhase', + Groups => { 2 => 'Time' }, + PrintConv => { + 0 => 'New', + 1 => 'New Crescent', + 2 => 'First Quarter', + 3 => 'Waxing Gibbous', + 4 => 'Full', + 5 => 'Waning Gibbous', + 6 => 'Last Quarter', + 7 => 'Old Crescent', + }, + }, + 0x44 => { + Name => 'AmbientTemperatureFahrenheit', + Format => 'int16s', + PrintConv => '"$val F"', + PrintConvInv => '$val=~/(-?\d+)/ ? $1 : $val', + }, + 0x46 => { + Name => 'AmbientTemperature', + Format => 'int16s', + PrintConv => '"$val C"', + PrintConvInv => '$val=~/(-?\d+)/ ? $1 : $val', + }, + 0x48 => { + Name => 'Illumination', + PrintConv => { 0 => 'Off', 1 => 'On' }, + }, + 0x49 => { + Name => 'BatteryVoltage', + Format => 'int16u', + ValueConv => '$val / 1000', + ValueConvInv => '$val * 1000', + PrintConv => '"$val V"', + PrintConvInv => '$val=~s/ ?V$//; $val', + }, + 0x4b => { + Name => 'SerialNumber', + Format => 'string[15]', + }, + 0x5a => { + Name => 'UserLabel', + Format => 'string[21]', + }, +); + +# maker notes for Reconyx HP2X cameras (ref 3) +%Image::ExifTool::Reconyx::Type3 = ( + GROUPS => { 0 => 'MakerNotes', 2 => 'Camera' }, + PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData, + WRITE_PROC => \&Image::ExifTool::WriteBinaryData, + CHECK_PROC => \&Image::ExifTool::CheckBinaryData, + TAG_PREFIX => 'Reconyx', + WRITABLE => 1, + FIRST_ENTRY => 0, + NOTES => 'Tags extracted from models such as the HP2X.', + # 0x0a => { Name => 'StructureVersion', Format => 'int16u' }, + # 0x0c => { Name => 'ParentFileSize', Format => 'int32u' }, + 0x10 => { Name => 'FileNumber', Format => 'int16u' }, + 0x12 => { Name => 'DirectoryNumber', Format => 'int16u' }, + # 0x14 => { Name => 'DirCreateDate', Format => 'int16u' }, + # 0x16 => { Name => 'DirCreateTime', Format => 'int16u' }, + # 0x18 - int16[8] SDCardLabel + # 0x28 => { Name => 'MakerNoteVersion', Format => 'int16u' }, + 0x2a => { + Name => 'FirmwareVersion', + Format => 'int16u[3]', + ValueConv => 'my @a = split " ",$val; sprintf("%d.%d%c",@a)', + ValueConvInv => '$val=~/(\d+)\.(\d+)([a-zA-Z])/ ? "$1 $2 ".ord($3) : undef', + }, + 0x30 => { + Name => 'FirmwareDate', + Format => 'int16u[2]', + ValueConv => 'my ($y,$d) = split " ", $val; sprintf("%.4x:%.2x:%.2x",$y,$d>>8,$d&0xff)', + ValueConvInv => 'my @a=split ":", $val; hex($a[0])." ".hex($a[1].$a[2])', + }, + 0x34 => { + Name => 'TriggerMode', #PH (NC) (called EventType in the Reconyx code) + Format => 'string[2]', + PrintConv => { + M => 'Motion Detection', # (seen this one only) + T => 'Time Lapse', # (NC) + P => 'Point and Shoot', # (NC) + }, + }, + 0x36 => { + Name => 'Sequence', + Format => 'int16u[2]', + PrintConv => '$val =~ s/ / of /; $val', + PrintConvInv => 'join(" ", $val=~/\d+/g)', + }, + 0x3a => { + Name => 'EventNumber', + Format => 'int16u[2]', + ValueConv => 'my @a=split " ",$val;($a[0]<<16)+$a[1]', + ValueConvInv => '($val >> 16) . " " . ($val & 0xffff)', + }, + 0x3e => { + Name => 'DateTimeOriginal', + Description => 'Date/Time Original', + Format => 'int16u[6]', + Groups => { 2 => 'Time' }, + Priority => 0, # (not as reliable as EXIF) + Shift => 'Time', + ValueConv => q{ + my @a = split ' ', $val; + sprintf('%.4d:%.2d:%.2d %.2d:%.2d:%.2d', reverse @a); + }, + ValueConvInv => q{ + my @a = ($val =~ /\d+/g); + return undef unless @a >= 6; + join ' ', @a[6,5,4,3,2,1,0]; + }, + PrintConv => '$self->ConvertDateTime($val)', + PrintConvInv => '$self->InverseDateTime($val)', + }, + 0x4a => { #2 + Name => 'DayOfWeek', + Groups => { 2 => 'Time' }, + Format => 'int16u', + PrintConv => { + 0 => 'Sunday', + 1 => 'Monday', + 2 => 'Tuesday', + 3 => 'Wednesday', + 4 => 'Thursday', + 5 => 'Friday', + 6 => 'Saturday', + }, + }, + 0x4c => { + Name => 'MoonPhase', + Groups => { 2 => 'Time' }, + Format => 'int16u', + PrintConv => { + 0 => 'New', + 1 => 'New Crescent', + 2 => 'First Quarter', + 3 => 'Waxing Gibbous', + 4 => 'Full', + 5 => 'Waning Gibbous', + 6 => 'Last Quarter', + 7 => 'Old Crescent', + }, + }, + 0x4e => { + Name => 'AmbientTemperatureFahrenheit', + Format => 'int16s', + PrintConv => '"$val F"', + PrintConvInv => '$val=~/(-?\d+)/ ? $1 : $val', + }, + 0x50 => { + Name => 'AmbientTemperature', + Format => 'int16s', + PrintConv => '"$val C"', + PrintConvInv => '$val=~/(-?\d+)/ ? $1 : $val', + }, + 0x52 => { Name => 'Contrast', Format => 'int16u' }, + 0x54 => { Name => 'Brightness', Format => 'int16u' }, + 0x56 => { Name => 'Sharpness', Format => 'int16u' }, + 0x58 => { Name => 'Saturation', Format => 'int16u' }, + 0x5a => { Name => 'Flash', Format => 'int16u', PrintConv => { 0 => 'Off', 1 => 'On' } }, + 0x5c => { Name => 'AmbientInfrared', Format => 'int16u' }, + 0x5e => { Name => 'AmbientLight', Format => 'int16u' }, + 0x60 => { Name => 'MotionSensitivity', Format => 'int16u' }, + 0x62 => { Name => 'BatteryVoltage', Format => 'int16u' }, + 0x64 => { Name => 'BatteryVoltageAvg', Format => 'int16u' }, + 0x66 => { Name => 'BatteryType', Format => 'int16u' }, + 0x68 => { Name => 'UserLabel', Format => 'string[22]' }, + 0x7e => { Name => 'SerialNumber', Format => 'unicode[15]' }, +); + +__END__ + +=head1 NAME + +Image::ExifTool::Reconyx - Reconyx maker notes tags + +=head1 SYNOPSIS + +This module is loaded automatically by Image::ExifTool when required. + +=head1 DESCRIPTION + +This module contains definitions required by Image::ExifTool to interpret +maker notes in images from Reconyx cameras. + +=head1 AUTHOR + +Copyright 2003-2019, Phil Harvey (phil at owl.phy.queensu.ca) + +This library is free software; you can redistribute it and/or modify it +under the same terms as Perl itself. + +=head1 SEE ALSO + +L<Image::ExifTool::TagNames/Reconyx Tags>, +L<Image::ExifTool(3pm)|Image::ExifTool> + +=cut diff --git a/lib/Image/ExifTool/Red.pm b/lib/Image/ExifTool/Red.pm new file mode 100644 index 0000000..92d020a --- /dev/null +++ b/lib/Image/ExifTool/Red.pm @@ -0,0 +1,325 @@ +#------------------------------------------------------------------------------ +# File: Red.pm +# +# Description: Read Redcode R3D video files +# +# Revisions: 2018-01-25 - P. Harvey Created +# +# References: 1) http://www.wikiwand.com/en/REDCODE +#------------------------------------------------------------------------------ + +package Image::ExifTool::Red; + +use strict; +use vars qw($VERSION); +use Image::ExifTool qw(:DataAccess :Utils); + +$VERSION = '1.01'; + +sub ProcessR3D($$); + +# RED format codes (ref PH) +my %redFormat = ( + 0 => 'int8u', + 1 => 'string', + 2 => 'float', + 3 => 'int8u', # (how is this different than 0?) + 4 => 'int16u', + 5 => 'int8s', # (not sure about this) + 6 => 'int32s', + 7 => 'undef', # (mixed-format structure?) + 8 => 'int32u', # (NC) + 9 => 'undef', # ? (seen 256 bytes, all zero) +); + +# error strings +my $errTrunc = 'Truncated R3D file'; + +# RED directory tags (ref PH) +%Image::ExifTool::Red::Main = ( + GROUPS => { 2 => 'Camera' }, + NOTES => 'Tags extracted from Redcode R3D video files.', + VARS => { ALPHA_FIRST => 1 }, + + RED1 => { Name => 'Red1Header', SubDirectory => { TagTable => 'Image::ExifTool::Red::RED1' } }, + RED2 => { Name => 'Red2Header', SubDirectory => { TagTable => 'Image::ExifTool::Red::RED2' } }, + + # (upper 4 bits of tag ID are the format code) + # ---- format 1 ---- + 0x1000 => 'StartEdgeCode', #1 + 0x1001 => { Name => 'StartTimecode', Groups => { 2 => 'Time' } }, #1 + 0x1002 => { #1 + Name => 'OtherDate1', + Groups => { 2 => 'Time' }, + # format is "YYYY_MM_DD[_TZ?]" + ValueConv => '$val =~ s/(\d{4})_(\d{2})_/$1:$2:/; $val =~ tr/_/ /; $val', + }, + 0x1003 => { #1 + Name => 'OtherDate2', + Groups => { 2 => 'Time' }, + ValueConv => '$val =~ s/(\d{4})_(\d{2})_/$1:$2:/; $val =~ tr/_/ /; $val', + }, + 0x1004 => { #1 + Name => 'OtherDate3', + Groups => { 2 => 'Time' }, + ValueConv => '$val =~ s/(\d{4})_(\d{2})_/$1:$2:/; $val =~ tr/_/ /; $val', + }, + 0x1005 => { #1 + Name => 'DateTimeOriginal', + Description => 'Date/Time Original', + Groups => { 2 => 'Time' }, + ValueConv => '$val =~ s/(\d{4})(\d{2})(\d{2})(\d{2})(\d{2})/$1:$2:$3 $4:$5:/; $val', + PrintConv => '$self->ConvertDateTime($val)', + }, + 0x1006 => 'SerialNumber', #1 + 0x1019 => 'CameraType', #1 + 0x101a => { Name => 'ReelNumber', Groups => { 2 => 'Video' } }, #1 + 0x101b => { Name => 'Take', Groups => { 2 => 'Video' } }, + 0x1023 => { #1 + Name => 'DateCreated', + Groups => { 2 => 'Time' }, + ValueConv => '$val =~ s/(\d{4})(\d{2})/$1:$2:/; $val', + }, + 0x1024 => { #1 + Name => 'TimeCreated', + Groups => { 2 => 'Time' }, + ValueConv => '$val =~ s/(\d{2})(\d{2})/$1:$2:/; $val', + }, + 0x1025 => 'FirmwareVersion', #1 + 0x1029 => { Name => 'ReelTimecode', Groups => { 2 => 'Time' } }, #1 + 0x102a => 'StorageType', #1 + 0x1030 => { #1 + Name => 'StorageFormatDate', + Groups => { 2 => 'Time' }, + ValueConv => '$val =~ s/(\d{4})(\d{2})/$1:$2:/; $val', + }, + 0x1031 => { #1 + Name => 'StorageFormatTime', + Groups => { 2 => 'Time' }, + ValueConv => '$val =~ s/(\d{2})(\d{2})/$1:$2:/; $val', + }, + 0x1032 => 'StorageSerialNumber', #1 + 0x1033 => 'StorageModel', #1 + 0x1036 => 'AspectRatio', #1 + # 0x1041 - seen 'NA' + 0x1042 => 'Revision', # ? (seen "TODO, rev EPIC-1.0" and "MYSTERIUM X, rev EPIC-1.0") + # 0x1051 - seen 'C', 'L' + 0x1056 => 'OriginalFileName', + 0x106e => 'LensMake', + 0x106f => 'LensNumber', # (last 2 hex digits are LensType) + 0x1070 => 'LensModel', + 0x1071 => { + Name => 'Model', + Description => 'Camera Model Name', + }, + 0x107c => { Name => 'CameraOperator', Groups => { 2 => 'Author' } }, + 0x1086 => { + Name => 'VideoFormat', + Groups => { 2 => 'Video' }, + }, + 0x1096 => 'Filter', # optical low-pass filter + 0x10a0 => 'Brain', + 0x10a1 => 'Sensor', + # ---- format 2 ---- + 0x200d => 'ColorTemperature', + # 0x200e - (sometimes this is frame rate) + # 0x2015 - seen '1 1 1' (RGBGain or RGBGamma?) + 0x204b => 'RGBCurves', # (blackx/y,toex/y,midx/y,kneex/y,whitex/y) + 0x2066 => { + Name => 'OriginalFrameRate', + Groups => { 2 => 'Video' }, + PrintConv => 'int($val * 1000 + 0.5) / 1000', + }, + # ---- format 4 ---- + 0x4037 => { Name => 'CropArea' }, # (NC) + 0x403b => 'ISO', + # 0x404e - related to CropArea (or "0 0 0 0") + 0x406a => { Name => 'FNumber', ValueConv => '$val / 10' }, + 0x406b => 'FocalLength', + # 0x4084 - related to ISO? + # 0x4087 - related to ISO? + # ---- format 6 ---- + 0x606c => { Name => 'FocusDistance', ValueConv => '$val/1000', PrintConv => '"$val m"' }, +); + +# RED1 file header (ref PH) +%Image::ExifTool::Red::RED1 = ( + GROUPS => { 2 => 'Video' }, + PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData, + NOTES => 'Redcode version 1 header.', + # 0x00 - int32u: length of header + # 0x04 - string: "RED1" + # 0x0a - string: "R1" + 0x07 => { Name => 'RedcodeVersion', Format => 'string[1]' }, #1 + # 0x0e - looks funny; my sample has a value of 43392 here + # 0x0e => { Name => 'AudioSampleRate', Format => 'int16u' }, #1 + 0x36 => { Name => 'ImageWidth', Format => 'int16u' }, #1 + 0x3a => { Name => 'ImageHeight', Format => 'int16u' }, #PH (ref 1 gave 0x3c) + 0x3e => { #PH (ref 1 gave 0x42 for denom) + Name => 'FrameRate', + Format => 'rational32u', + PrintConv => 'int($val * 1000 + 0.5) / 1000', + }, + 0x43 => { Name => 'OriginalFileName', Format => 'string[32]' }, #1 +); + +# RED2 file header (ref PH) +%Image::ExifTool::Red::RED2 = ( + GROUPS => { 2 => 'Video' }, + PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData, + NOTES => 'Redcode version 2 header.', + # 0x00 - int32u: length of header + # 0x04 - string: "RED2" + 0x07 => { Name => 'RedcodeVersion', Format => 'string[1]' }, + # 0x08 - seen 0x05 + # 0x09 - seen 0x0d,0x0f,0x10 + # 0x0a - string: "R2" + # 0x0c - seen 0x04,0x05,0x07,0x08,0x0b,0x0c + # 0x0d - seen 0x01,0x08 (and 0x09 in block 1) + # 0x0e - int16u: seen 3072 + # 0x10 - looks like some sort of 32-byte hash or something (same in other blocks) + # 0x30-0x3f - mostly 0x00's with a couple of 0x01's + # 0x40 - int8u: count of 0x18-byte "rdi" records + # 0x41-0x43 - seen "\0\0\x01" + # ---- rdi record: (0x18 bytes long) ---- + # 0x44 - string: "rdi#" (where number is index of "rdi" record, starting at \x01) + 0x4c => { Name => 'ImageWidth', Format => 'int32u' }, + 0x50 => { Name => 'ImageHeight', Format => 'int32u' }, + # 0x54 - seen 0x11,0x13,0x15 (and 0x03 in "rdi\x02" record) + # 0x55 - seen 0x02 + 0x56 => { + Name => 'FrameRate', + Format => 'int16u[3]', + ValueConv => 'my @a = split " ",$val; ($a[1] * 0x10000 + $a[2]) / $a[0]', + PrintConv => 'int($val * 1000 + 0.5) / 1000', + }, + # (immediately following last "rdi" record is a + # Red directory beginning with int16u size) +); + +#------------------------------------------------------------------------------ +# Process metadata from a Redcode R3D video (ref PH) +# Inputs: 0) ExifTool object reference, 1) dirInfo reference +# Returns: 1 on success, 0 if this wasn't a valid R3D file +sub ProcessR3D($$) +{ + my ($et, $dirInfo) = @_; + my $raf = $$dirInfo{RAF}; + my ($buff, $buf2, $pos, $dirLen, $dirEnd); + my $verbose = $et->Options('Verbose'); + + # R3D file structure: + # - each block starts with int32u block size followed by 4-byte block type + # - first block type is either "RED1" (version 1) or "RED2" (version 2) + # - blocks begin on even 0x1000 byte boundaries for version 2 files + + # validate the file header + return 0 unless $raf->Read($buff, 8) == 8 and $buff =~ /^\0\0..RED(1|2)/s; + my $ver = $1; + my $size = unpack('N', $buff); + return 0 if $size < 8; + + $et->SetFileType(); + SetByteOrder('MM'); + my $tagTablePtr = GetTagTable('Image::ExifTool::Red::Main'); + my $dataPos = 0; + + # read the first block of the file + $raf->Read($buf2, $size - 8) == $size - 8 or return $et->Warn($errTrunc); + $buff .= $buf2; + + # extract tags from the header + $et->HandleTag($tagTablePtr, "RED$ver", undef, DataPt => \$buff); + + # read the second block from a version 1 file because + # the first block doesn't contain a Red directory + if ($ver eq '1') { + # (read more than we need) + $raf->Read($buff, 0x10000) or return $et->Warn($errTrunc); + $dataPos += $size; + $pos = 0x22; # directory starts at offset 0x22 + } else { + # calculate position of Red directory start + length($buff) < 0x41 and return $et->Warn($errTrunc); + my $n = Get8u(\$buff, 0x40); # number of "rdi" records + $pos = 0x44 + $n * 0x18; + } + if ($pos + 8 > length $buff) { + $dirLen = 0; # find directory the hard way + } else { + $dirLen = Get16u(\$buff, $pos); # get length of Red directory + $pos += 2; # skip length word + } + # do sanity check on the directory size (in case our assumptions were wrong) + if ($dirLen < 300 or $dirLen >= 2048 or $pos + $dirLen > length $buff) { + # tag 0x1000 with length 0x000f should be near the directory start + $buff =~ /\0\x0f\x10\0/g or return $et->Warn("Can't find Red directory"); + $pos = pos($buff) - 4; + $dirEnd = length $buff; + undef $dirLen; + $et->Warn('This R3D file is different. Please submit a sample for testing'); + } else { + $dirEnd = $pos + $dirLen; + } + $$et{INDENT} .= '| ', $et->VerboseDir('Red', undef, $dirLen) if $verbose; + + # process the first Red directory + while ($pos + 4 <= $dirEnd) { + my $len = Get16u(\$buff, $pos); + last if $len < 4 or $pos + $len > $dirEnd; + my $tag = Get16u(\$buff, $pos + 2); + my $fmt = $redFormat{$tag >> 12}; # format is top 4 bits of tag ID (ref PH) + $fmt or $dirLen && $et->Warn('Unknown format code'), last; + $et->HandleTag($tagTablePtr, $tag, undef, + DataPt => \$buff, + DataPos => $dataPos, + Start => $pos + 4, + Size => $len - 4, + Format => $fmt, + ); + $pos += $len; + } + $$et{INDENT} = substr($$et{INDENT}, 0, -2) if $verbose; + + return 1; +} + +1; # end + +__END__ + +=head1 NAME + +Image::ExifTool::Red - Read Redcode R3D video files + +=head1 SYNOPSIS + +This module is used by Image::ExifTool + +=head1 DESCRIPTION + +This module contains routines required by Image::ExifTool to read metadata +from Redcode R3D version 1 and 2 video files. + +=head1 AUTHOR + +Copyright 2003-2019, Phil Harvey (phil at owl.phy.queensu.ca) + +This library is free software; you can redistribute it and/or modify it +under the same terms as Perl itself. + +=head1 REFERENCES + +=over 4 + +=item L<http://www.wikiwand.com/en/REDCODE> + +=back + +=head1 SEE ALSO + +L<Image::ExifTool::TagNames/Red Tags>, +L<Image::ExifTool(3pm)|Image::ExifTool> + +=cut + diff --git a/lib/Image/ExifTool/Ricoh.pm b/lib/Image/ExifTool/Ricoh.pm new file mode 100644 index 0000000..864f0da --- /dev/null +++ b/lib/Image/ExifTool/Ricoh.pm @@ -0,0 +1,1146 @@ +#------------------------------------------------------------------------------ +# File: Ricoh.pm +# +# Description: Ricoh EXIF maker notes tags +# +# Revisions: 03/28/2005 - P. Harvey Created +# +# References: 1) http://www.ozhiker.com/electronics/pjmt/jpeg_info/ricoh_mn.html +# 2) http://homepage3.nifty.com/kamisaka/makernote/makernote_ricoh.htm +# 3) Tim Gray private communication (GR) +# 4) https://github.com/atotto/ricoh-theta-tools/ +# IB) Iliah Borg private communication (LibRaw) +#------------------------------------------------------------------------------ + +package Image::ExifTool::Ricoh; + +use strict; +use vars qw($VERSION); +use Image::ExifTool qw(:DataAccess :Utils); +use Image::ExifTool::Exif; + +$VERSION = '1.33'; + +sub ProcessRicohText($$$); +sub ProcessRicohRMETA($$$); + +# lens types for Ricoh GXR +my %ricohLensIDs = ( + Notes => q{ + Lens units available for the GXR, used by the Ricoh Composite LensID tag. Note + that unlike lenses for all other makes of cameras, the focal lengths in these + model names have already been scaled to include the 35mm crop factor. + }, + # (the exact lens model names used by Ricoh, except for a change in case) + 'RL1' => 'GR Lens A12 50mm F2.5 Macro', + 'RL2' => 'Ricoh Lens S10 24-70mm F2.5-4.4 VC', + 'RL3' => 'Ricoh Lens P10 28-300mm F3.5-5.6 VC', + 'RL5' => 'GR Lens A12 28mm F2.5', + 'RL8' => 'Mount A12', + 'RL6' => 'Ricoh Lens A16 24-85mm F3.5-5.5', +); + +%Image::ExifTool::Ricoh::Main = ( + GROUPS => { 0 => 'MakerNotes', 2 => 'Camera' }, + WRITE_PROC => \&Image::ExifTool::Exif::WriteExif, + CHECK_PROC => \&Image::ExifTool::Exif::CheckExif, + WRITABLE => 1, + 0x0001 => { Name => 'MakerNoteType', Writable => 'string' }, + 0x0002 => { #PH + Name => 'FirmwareVersion', + Writable => 'string', + # eg. "Rev0113" is firmware version 1.13 + PrintConv => '$val=~/^Rev(\d+)$/ ? sprintf("%.2f",$1/100) : $val', + PrintConvInv => '$val=~/^(\d+)\.(\d+)$/ ? sprintf("Rev%.2d%.2d",$1,$2) : $val', + }, + 0x0005 => [ #PH + { + Condition => '$$valPt =~ /^[-\w ]+$/', + Name => 'SerialNumber', # (verified for GXR) + Writable => 'undef', + Count => 16, + Notes => q{ + the serial number stamped on the camera begins with 2 model-specific letters + followed by the last 8 digits of this value. For the GXR, this is the + serial number of the lens unit + }, + PrintConv => '$val=~s/^(.*)(.{8})$/($1)$2/; $val', + PrintConvInv => '$val=~tr/()//d; $val', + },{ + Name => 'InternalSerialNumber', + Writable => 'undef', + Count => 16, + ValueConv => 'unpack("H*", $val)', + ValueConvInv => 'pack("H*", $val)', + }, + ], + 0x0e00 => { + Name => 'PrintIM', + Writable => 0, + Description => 'Print Image Matching', + SubDirectory => { TagTable => 'Image::ExifTool::PrintIM::Main' }, + }, + 0x1000 => { #3 + Name => 'RecordingFormat', + Writable => 'int16u', + PrintConv => { + 2 => 'JPEG', + 3 => 'DNG', + }, + }, + 0x1001 => [{ + Name => 'ImageInfo', + Condition => '$format ne "int16u"', + SubDirectory => { TagTable => 'Image::ExifTool::Ricoh::ImageInfo' }, + },{ #3 + Name => 'ExposureProgram', + Writable => 'int16u', + Notes => 'GR', + PrintConv => { + 1 => 'Auto', + 2 => 'Program AE', + 3 => 'Aperture-priority AE', + 4 => 'Shutter speed priority AE', + 5 => 'Shutter/aperture priority AE', # TAv + 6 => 'Manual', + 7 => 'Movie', #PH + }, + }], + 0x1002 => { #3 + Name => 'DriveMode', + Condition => '$format eq "int16u"', + Notes => 'valid only for some models', + Writable => 'int16u', + PrintConv => { + 0 => 'Single-frame', + 1 => 'Continuous', + 8 => 'AF-priority Continuous', + }, + }, + 0x1003 => [{ + Name => 'Sharpness', + Condition => '$format ne "int16u"', + Writable => 'int32u', + PrintConv => { + 0 => 'Sharp', + 1 => 'Normal', + 2 => 'Soft', + }, + },{ #3 + Name => 'WhiteBalance', + Writable => 'int16u', + Notes => 'GR', + PrintConv => { + 0 => 'Auto', + 1 => 'Multi-P Auto', + 2 => 'Daylight', + 3 => 'Cloudy', + 4 => 'Incandescent 1', + 5 => 'Incandescent 2', + 6 => 'Daylight Fluorescent', + 7 => 'Neutral White Fluorescent', + 8 => 'Cool White Fluorescent', + 9 => 'Warm White Fluorescent', + 10 => 'Manual', + 11 => 'Kelvin', + 12 => 'Shade', #IB + }, + }], + 0x1004 => { #3 + Name => 'WhiteBalanceFineTune', + Condition => '$format eq "int16u"', + Format => 'int16s', + Writable => 'int16u', + Notes => q{ + 2 numbers: amount of adjustment towards Amber and Green. Not valid for all + models + }, + }, + # 0x1005 int16u - 5 + 0x1006 => { #3 + Name => 'FocusMode', + Writable => 'int16u', + PrintConv => { + 1 => 'Manual', + 2 => 'Multi AF', + 3 => 'Spot AF', + 4 => 'Snap', + 5 => 'Infinity', + 7 => 'Face Detect', #PH + 8 => 'Subject Tracking', + 9 => 'Pinpoint AF', + 10 => 'Movie', #PH + }, + }, + 0x1007 => { #3 + Name => 'AutoBracketing', + Writable => 'int16u', + PrintConv => { + 0 => 'Off', + 9 => 'AE', + 11 => 'WB', + 16 => 'DR', # (dynamic range) + 17 => 'Contrast', + 18 => 'WB2', # (selects two different WB presets besides normal) + 19 => 'Effect', + }, + }, + 0x1009 => { #3 + Name => 'MacroMode', + Writable => 'int16u', + PrintConv => { 0 => 'Off', 1 => 'On' }, + }, + 0x100a => { #3 + Name => 'FlashMode', + Writable => 'int16u', + PrintConv => { + 0 => 'Off', + 1 => 'Auto, Fired', + 2 => 'On', + 3 => 'Auto, Fired, Red-eye reduction', + 4 => 'Slow Sync', + 5 => 'Manual', + 6 => 'On, Red-eye reduction', + 7 => 'Synchro, Red-eye reduction', + 8 => 'Auto, Did not fire', + }, + }, + 0x100b => { #3 + Name => 'FlashExposureComp', + Writable => 'rational64s', + PrintConv => '$val ? sprintf("%+.1f",$val) : 0', + PrintConvInv => '$val', + }, + 0x100c => { #3 + Name => 'ManualFlashOutput', + Writable => 'rational64s', + PrintConv => { + 0 => 'Full', + -24 => '1/1.4', + -48 => '1/2', + -72 => '1/2.8', + -96 => '1/4', + -120 => '1/5.6', + -144 => '1/8', + -168 => '1/11', + -192 => '1/16', + -216 => '1/22', + -240 => '1/32', + -288 => '1/64', + }, + }, + 0x100d => { #3 + Name => 'FullPressSnap', + Writable => 'int16u', + PrintConv => { 0 => 'Off', 1 => 'On' }, + }, + 0x100e => { #3 + Name => 'DynamicRangeExpansion', + Writable => 'int16u', + PrintConv => { + 0 => 'Off', + 3 => 'Weak', + 4 => 'Medium', + 5 => 'Strong', + }, + }, + 0x100f => { #3 + Name => 'NoiseReduction', + Writable => 'int16u', + PrintConv => { + 0 => 'Off', + 1 => 'Weak', + 2 => 'Medium', + 3 => 'Strong', + }, + }, + 0x1010 => { #3 + Name => 'ImageEffects', + Writable => 'int16u', + PrintConv => { + 0 => 'Standard', + 1 => 'Vivid', + 3 => 'Black & White', + 5 => 'B&W Toning Effect', + 6 => 'Setting 1', + 7 => 'Setting 2', + 9 => 'High-contrast B&W', + 10 => 'Cross Process', + 11 => 'Positive Film', + 12 => 'Bleach Bypass', + 13 => 'Retro', + 15 => 'Miniature', + 17 => 'High Key', + }, + }, + 0x1011 => { #3 + Name => 'Vignetting', + Writable => 'int16u', + PrintConv => { + 0 => 'Off', + 1 => 'Low', + 2 => 'Medium', + 3 => 'High', + }, + }, + 0x1012 => { #PH + Name => 'Contrast', + Writable => 'int32u', + Format => 'int32s', #3 (high-contrast B&W also has -1 and -2 settings) + PrintConv => { + OTHER => sub { shift }, + 2147483647 => 'MAX', #3 (high-contrast B&W effect MAX setting) + }, + }, + 0x1013 => { Name => 'Saturation', Writable => 'int32u' }, #PH + 0x1014 => { Name => 'Sharpness', Writable => 'int32u' }, #3 + 0x1015 => { #3 + Name => 'ToningEffect', + Writable => 'int16u', + PrintConv => { + 0 => 'Off', + 1 => 'Sepia', + 2 => 'Red', + 3 => 'Green', + 4 => 'Blue', + 5 => 'Purple', + 6 => 'B&W', + 7 => 'Color', + }, + }, + 0x1016 => { #3 + Name => 'HueAdjust', + Writable => 'int16u', + PrintConv => { + 0 => 'Off', + 1 => 'Basic', + 2 => 'Magenta', + 3 => 'Yellow', + 4 => 'Normal', + 5 => 'Warm', + 6 => 'Cool', + }, + }, + 0x1017 => { #3 + Name => 'WideAdapter', + Writable => 'int16u', + PrintConv => { + 0 => 'Not Attached', + 2 => 'Attached', # (21mm) + }, + }, + 0x1018 => { #3 + Name => 'CropMode35mm', + Writable => 'int16u', + PrintConv => { 0 => 'Off', 1 => 'On' }, + }, + 0x1019 => { #3 + Name => 'NDFilter', + Writable => 'int16u', + PrintConv => { 0 => 'Off', 1 => 'On' }, + }, + 0x101a => { Name => 'WBBracketShotNumber', Writable => 'int16u' }, #3 + # 0x1100 - related to DR correction (ref 3) + 0x1307 => { Name => 'ColorTempKelvin', Writable => 'int32u' }, #3 + 0x1308 => { Name => 'ColorTemperature', Writable => 'int32u' }, #3 + 0x1500 => { #3 + Name => 'FocalLength', + Writable => 'rational64u', + PrintConv => 'sprintf("%.1f mm",$val)', + PrintConvInv => '$val=~s/\s*mm$//;$val', + }, + 0x1200 => { #3 + Name => 'AFStatus', + Writable => 'int16u', + PrintConv => { + 0 => 'Out of Focus', + 1 => 'In Focus', + }, + }, + # 0x1201-0x1204 - related to focus points (ref 3) + 0x1201 => { #PH (NC) + Name => 'AFAreaXPosition1', + Writable => 'int32u', + Notes => 'manual AF area position in a 1280x864 image', + }, + 0x1202 => { Name => 'AFAreaYPosition1', Writable => 'int32u' }, #PH (NC) + 0x1203 => { #PH (NC) + Name => 'AFAreaXPosition', + Writable => 'int32u', + Notes => 'manual AF area position in the full image', + # (coordinates change to correspond with smaller image + # when recording reduced-size JPEG) + }, + 0x1204 => { Name => 'AFAreaYPosition', Writable => 'int32u' }, #PH (NC) + 0x1205 => { #3 + Name => 'AFAreaMode', + Writable => 'int16u', + PrintConv => { + 0 => 'Auto', + 2 => 'Manual', + }, + }, + 0x1601 => { Name => 'SensorWidth', Writable => 'int32u' }, #3 + 0x1602 => { Name => 'SensorHeight', Writable => 'int32u' }, #3 + 0x1603 => { Name => 'CroppedImageWidth', Writable => 'int32u' }, #3 + 0x1604 => { Name => 'CroppedImageHeight', Writable => 'int32u' }, #3 + # 0x1700 - Composite? (0=normal image, 1=interval composite, 2=multi-exposure composite) (ref 3) + # 0x1703 - 0=normal, 1=final composite (ref 3) + # 0x1704 - 0=normal, 2=final composite (ref 3) + 0x2001 => [ + { + Name => 'RicohSubdir', + Condition => q{ + $self->{Model} !~ /^Caplio RR1\b/ and + ($format ne 'int32u' or $count != 1) + }, + SubDirectory => { + Validate => '$val =~ /^\[Ricoh Camera Info\]/', + TagTable => 'Image::ExifTool::Ricoh::Subdir', + Start => '$valuePtr + 20', + ByteOrder => 'BigEndian', + }, + }, + { + Name => 'RicohSubdirIFD', + # the CX6 and GR Digital 4 write an int32u pointer in AVI videos -- doh! + Condition => '$self->{Model} !~ /^Caplio RR1\b/', + Flags => 'SubIFD', + SubDirectory => { + TagTable => 'Image::ExifTool::Ricoh::Subdir', + Start => '$val + 20', # (skip over "[Ricoh Camera Info]\0" header) + ByteOrder => 'BigEndian', + }, + }, + { + Name => 'RicohRR1Subdir', + SubDirectory => { + Validate => '$val =~ /^\[Ricoh Camera Info\]/', + TagTable => 'Image::ExifTool::Ricoh::Subdir', + Start => '$valuePtr + 20', + ByteOrder => 'BigEndian', + # the Caplio RR1 uses a different base address -- doh! + Base => '$start-20', + }, + }, + ], + 0x4001 => { + Name => 'ThetaSubdir', + Groups => { 1 => 'MakerNotes' }, # SubIFD needs group 1 set + Flags => 'SubIFD', + SubDirectory => { + TagTable => 'Image::ExifTool::Ricoh::ThetaSubdir', + Start => '$val', + }, + }, +); + +# Ricoh type 2 maker notes (ref PH) +# (similar to Kodak::Type11 and GE::Main) +%Image::ExifTool::Ricoh::Type2 = ( + GROUPS => { 0 => 'MakerNotes', 2 => 'Camera' }, + NOTES => q{ + Tags written by models such as the Ricoh HZ15 and the Pentax XG-1. These + are not writable due to numerous formatting errors as written by these + cameras. + }, + # 0x104 - int32u: 1 + # 0x200 - int32u[3]: 0 0 0 + # 0x202 - int16u: 0 (GE Macro?) + # 0x203 - int16u: 0,3 (Kodak PictureEffect?) + # 0x204 - rational64u: 0/10 + # 0x205 - rational64u: 150/1 + # 0x206 - float[6]: (not really float because size should be 2 bytes) + 0x207 => { + Name => 'RicohModel', + Writable => 'string', + }, + 0x300 => { + # brutal. There are lots of errors in the XG-1 maker notes. For the XG-1, + # 0x300 has a value of "XG-1Pentax". The "XG-1" part is likely an improperly + # stored 0x207 RicohModel, resulting in an erroneous 4-byte offset for this tag + Name => 'RicohMake', + Writable => 'undef', + ValueConv => '$val =~ s/ *$//; $val', + }, + # 0x306 - int16u: 1 + # 0x500 - int16u: 0,1 + # 0x501 - int16u: 0 + # 0x502 - int16u: 0 + # 0x9c9c - int8u[6]: ? + # 0xadad - int8u[20480]: ? +); + +# Ricoh image info (ref 2) +%Image::ExifTool::Ricoh::ImageInfo = ( + GROUPS => { 0 => 'MakerNotes', 2 => 'Image' }, + PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData, + WRITE_PROC => \&Image::ExifTool::WriteBinaryData, + CHECK_PROC => \&Image::ExifTool::CheckBinaryData, + WRITABLE => 1, + PRIORITY => 0, + FORMAT => 'int8u', + FIRST_ENTRY => 0, + IS_OFFSET => [ 28 ], # tag 28 is 'IsOffset' + 0 => { + Name => 'RicohImageWidth', + Format => 'int16u', + }, + 2 => { + Name => 'RicohImageHeight', + Format => 'int16u', + }, + 6 => { + Name => 'RicohDate', + Groups => { 2 => 'Time' }, + Format => 'int8u[7]', + # (what an insane way to encode the date) + ValueConv => q{ + sprintf("%.2x%.2x:%.2x:%.2x %.2x:%.2x:%.2x", + split(' ', $val)); + }, + ValueConvInv => q{ + my @vals = ($val =~ /(\d{1,2})/g); + push @vals, 0 if @vals < 7; + join(' ', map(hex, @vals)); + }, + }, + 28 => { + Name => 'PreviewImageStart', + Format => 'int16u', # ha! (only the lower 16 bits, even if > 0xffff) + Flags => 'IsOffset', + OffsetPair => 30, # associated byte count tagID + DataTag => 'PreviewImage', + Protected => 2, + WriteGroup => 'MakerNotes', + # prevent preview from being written to MakerNotes of DNG images + RawConvInv => q{ + return $val if $$self{FILE_TYPE} eq "JPEG"; + warn "\n"; # suppress warning + return undef; + }, + }, + 30 => { + Name => 'PreviewImageLength', + Format => 'int16u', + OffsetPair => 28, # point to associated offset + DataTag => 'PreviewImage', + Protected => 2, + WriteGroup => 'MakerNotes', + RawConvInv => q{ + return $val if $$self{FILE_TYPE} eq "JPEG"; + warn "\n"; # suppress warning + return undef; + }, + }, + 32 => { + Name => 'FlashMode', + PrintConv => { + 0 => 'Off', + 1 => 'Auto', #PH + 2 => 'On', + }, + }, + 33 => { + Name => 'Macro', + PrintConv => { 0 => 'Off', 1 => 'On' }, + }, + 34 => { + Name => 'Sharpness', + PrintConv => { + 0 => 'Sharp', + 1 => 'Normal', + 2 => 'Soft', + }, + }, + 38 => { + Name => 'WhiteBalance', + PrintConv => { + 0 => 'Auto', + 1 => 'Daylight', + 2 => 'Cloudy', + 3 => 'Tungsten', + 4 => 'Fluorescent', + 5 => 'Manual', #PH (GXR) + 7 => 'Detail', + 9 => 'Multi-pattern Auto', #PH (GXR) + }, + }, + 39 => { + Name => 'ISOSetting', + PrintConv => { + 0 => 'Auto', + 1 => 64, + 2 => 100, + 4 => 200, + 6 => 400, + 7 => 800, + 8 => 1600, + 9 => 'Auto', #PH (? CX3) + 10 => 3200, #PH (A16) + 11 => '100 (Low)', #PH (A16) + }, + }, + 40 => { + Name => 'Saturation', + PrintConv => { + 0 => 'High', + 1 => 'Normal', + 2 => 'Low', + 3 => 'B&W', + 6 => 'Toning Effect', #PH (GXR Sepia,Red,Green,Blue,Purple) + 9 => 'Vivid', #PH (GXR) + 10 => 'Natural', #PH (GXR) + }, + }, +); + +# Ricoh subdirectory tags (ref PH) +# NOTE: this subdir is currently not writable because the offsets would require +# special code to handle the funny start location and base offset +%Image::ExifTool::Ricoh::Subdir = ( + GROUPS => { 0 => 'MakerNotes', 2 => 'Camera' }, + WRITE_PROC => \&Image::ExifTool::Exif::WriteExif, + CHECK_PROC => \&Image::ExifTool::Exif::CheckExif, + # the significance of the following 2 dates is not known. They are usually + # within a month of each other, but I have seen differences of nearly a year. + # Sometimes the first is more recent, and sometimes the second. + # 0x0003 - int32u[1] + 0x0004 => { # (NC) + Name => 'ManufactureDate1', + Groups => { 2 => 'Time' }, + Writable => 'string', + Count => 20, + }, + 0x0005 => { # (NC) + Name => 'ManufactureDate2', + Groups => { 2 => 'Time' }, + Writable => 'string', + Count => 20, + }, + # 0x0006 - undef[16] ? + # 0x0007 - int32u[1] ? + # 0x000c - int32u[2] 1st number is a counter (file number? shutter count?) - PH + # 0x0014 - int8u[338] could contain some data related to face detection? - PH + # 0x0015 - int8u[2]: related to noise reduction? + 0x001a => { #PH + Name => 'FaceInfo', + SubDirectory => { TagTable => 'Image::ExifTool::Ricoh::FaceInfo' }, + }, + 0x0029 => { + Name => 'FirmwareInfo', + SubDirectory => { TagTable => 'Image::ExifTool::Ricoh::FirmwareInfo' }, + }, + 0x002a => { + Name => 'NoiseReduction', + # this is the applied value if NR is set to "Auto" + Writable => 'int32u', + PrintConv => { + 0 => 'Off', + 1 => 'Weak', + 2 => 'Strong', + 3 => 'Max', + }, + }, + 0x002c => { # (GXR) + Name => 'SerialInfo', + SubDirectory => { TagTable => 'Image::ExifTool::Ricoh::SerialInfo' }, + } + # 0x000E ProductionNumber? (ref 2) [no. zero for most models - PH] +); + +# Ricoh Theta subdirectory tags - Contains orientation information (ref 4) +%Image::ExifTool::Ricoh::ThetaSubdir = ( + GROUPS => { 0 => 'MakerNotes', 2 => 'Camera' }, + WRITE_PROC => \&Image::ExifTool::Exif::WriteExif, + CHECK_PROC => \&Image::ExifTool::Exif::CheckExif, + # 0x0001 - int16u[1] ? + # 0x0002 - int16u[1] ? + 0x0003 => { + Name => 'Accelerometer', + Writable => 'rational64s', + Count => 2, + }, + 0x0004 => { + Name => 'Compass', + Writable => 'rational64u', + }, + # 0x0005 - int16u[1] ? + # 0x0006 - int16u[1] ? + # 0x0007 - int16u[1] ? + # 0x0008 - int16u[1] ? + # 0x0009 - int16u[1] ? + 0x000a => { + Name => 'TimeZone', + Writable => 'string', + }, + # 0x0101 - int16u[4] ISO (why 4 values?) + # 0x0102 - rational64s[2] FNumber (why 2 values?) + # 0x0103 - rational64u[2] ExposureTime (why 2 values?) + # 0x0104 - string[9] SerialNumber? + # 0x0105 - string[9] SerialNumber? +); + +# face detection information (ref PH, CX4) +%Image::ExifTool::Ricoh::FaceInfo = ( + GROUPS => { 0 => 'MakerNotes', 2 => 'Camera' }, + PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData, + WRITE_PROC => \&Image::ExifTool::WriteBinaryData, + CHECK_PROC => \&Image::ExifTool::CheckBinaryData, + WRITABLE => 1, + FIRST_ENTRY => 0, + DATAMEMBER => [ 181 ], + 0xb5 => { # (should be int16u at 0xb4?) + Name => 'FacesDetected', + DataMember => 'FacesDetected', + RawConv => '$$self{FacesDetected} = $val', + }, + 0xb6 => { + Name => 'FaceDetectFrameSize', + Format => 'int16u[2]', + }, + 0xbc => { + Name => 'Face1Position', + Condition => '$$self{FacesDetected} >= 1', + Format => 'int16u[4]', + Notes => q{ + left, top, width and height of detected face in coordinates of + FaceDetectFrameSize with increasing Y downwards + }, + }, + 0xc8 => { + Name => 'Face2Position', + Condition => '$$self{FacesDetected} >= 2', + Format => 'int16u[4]', + }, + 0xd4 => { + Name => 'Face3Position', + Condition => '$$self{FacesDetected} >= 3', + Format => 'int16u[4]', + }, + 0xe0 => { + Name => 'Face4Position', + Condition => '$$self{FacesDetected} >= 4', + Format => 'int16u[4]', + }, + 0xec => { + Name => 'Face5Position', + Condition => '$$self{FacesDetected} >= 5', + Format => 'int16u[4]', + }, + 0xf8 => { + Name => 'Face6Position', + Condition => '$$self{FacesDetected} >= 6', + Format => 'int16u[4]', + }, + 0x104 => { + Name => 'Face7Position', + Condition => '$$self{FacesDetected} >= 7', + Format => 'int16u[4]', + }, + 0x110 => { + Name => 'Face8Position', + Condition => '$$self{FacesDetected} >= 8', + Format => 'int16u[4]', + }, +); + +# firmware version information (ref PH) +%Image::ExifTool::Ricoh::FirmwareInfo = ( + GROUPS => { 0 => 'MakerNotes', 2 => 'Camera' }, + PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData, + WRITE_PROC => \&Image::ExifTool::WriteBinaryData, + CHECK_PROC => \&Image::ExifTool::CheckBinaryData, + WRITABLE => 1, + 0x00 => { + Name => 'FirmwareRevision', + Format => 'string[12]', + }, + 0x0c => { + Name => 'FirmwareRevision2', + Format => 'string[12]', + }, +); + +# serial/version number information written by GXR (ref PH) +%Image::ExifTool::Ricoh::SerialInfo = ( + GROUPS => { 0 => 'MakerNotes', 2 => 'Camera' }, + PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData, + WRITE_PROC => \&Image::ExifTool::WriteBinaryData, + CHECK_PROC => \&Image::ExifTool::CheckBinaryData, + WRITABLE => 1, + NOTES => 'This information is found in images from the GXR.', + 0 => { + Name => 'BodyFirmware', #(NC) + Format => 'string[16]', + # observed: "RS1 :V00560000" --> FirmwareVersion "Rev0056" + # "RS1 :V01020200" --> FirmwareVersion "Rev0102" + }, + 16 => { + Name => 'BodySerialNumber', + Format => 'string[16]', + # observed: "SID:00100056" --> "WD00100056" on plate + }, + 32 => { + Name => 'LensFirmware', #(NC) + Format => 'string[16]', + # observed: "RL1 :V00560000", "RL1 :V01020200" - A12 50mm F2.5 Macro + # "RL2 :V00560000", "RL2 :V01020300" - S10 24-70mm F2.5-4.4 VC + # --> used in a Composite tag to determine LensType + }, + 48 => { + Name => 'LensSerialNumber', + Format => 'string[16]', + # observed: (S10) "LID:00010024" --> "WF00010024" on plate + # (A12) "LID:00010054" --> "WE00010029" on plate?? + }, +); + +# Ricoh text-type maker notes (PH) +%Image::ExifTool::Ricoh::Text = ( + GROUPS => { 0 => 'MakerNotes', 2 => 'Camera' }, + PROCESS_PROC => \&ProcessRicohText, + NOTES => q{ + Some Ricoh DC and RDC models use a text-based format for their maker notes + instead of the IFD format used by the Caplio models. Below is a list of known + tags in this information. + }, + Rev => { + Name => 'FirmwareVersion', + PrintConv => '$val=~/^\d+$/ ? sprintf("%.2f",$val/100) : $val', + PrintConvInv => '$val=~/^(\d+)\.(\d+)$/ ? sprintf("%.2d%.2d",$1,$2) : $val', + }, + Rv => { + Name => 'FirmwareVersion', + PrintConv => '$val=~/^\d+$/ ? sprintf("%.2f",$val/100) : $val', + PrintConvInv => '$val=~/^(\d+)\.(\d+)$/ ? sprintf("%.2d%.2d",$1,$2) : $val', + }, + Rg => 'RedGain', + Gg => 'GreenGain', + Bg => 'BlueGain', +); + +%Image::ExifTool::Ricoh::RMETA = ( + GROUPS => { 0 => 'APP5', 1 => 'RMETA', 2 => 'Image' }, + PROCESS_PROC => \&Image::ExifTool::Ricoh::ProcessRicohRMETA, + NOTES => q{ + The Ricoh Caplio Pro G3 has the ability to add custom fields to the APP5 + "RMETA" segment of JPEG images. While only a few observed tags have been + defined below, ExifTool will extract any information found here. + }, + 'Sign type' => { Name => 'SignType', PrintConv => { + 1 => 'Directional', + 2 => 'Warning', + 3 => 'Information', + } }, + Location => { PrintConv => { + 1 => 'Verge', + 2 => 'Gantry', + 3 => 'Central reservation', + 4 => 'Roundabout', + } }, + Lit => { PrintConv => { + 1 => 'Yes', + 2 => 'No', + } }, + Condition => { PrintConv => { + 1 => 'Good', + 2 => 'Fair', + 3 => 'Poor', + 4 => 'Damaged', + } }, + Azimuth => { PrintConv => { + 1 => 'N', + 2 => 'NNE', + 3 => 'NE', + 4 => 'ENE', + 5 => 'E', + 6 => 'ESE', + 7 => 'SE', + 8 => 'SSE', + 9 => 'S', + 10 => 'SSW', + 11 => 'SW', + 12 => 'WSW', + 13 => 'W', + 14 => 'WNW', + 15 => 'NW', + 16 => 'NNW', + } }, + _audio => { + Name => 'SoundFile', + Notes => 'audio data recorded in JPEG images by the G700SE', + }, +); + +# information stored in Ricoh AVI images (ref PH) +%Image::ExifTool::Ricoh::AVI = ( + GROUPS => { 0 => 'MakerNotes', 2 => 'Video' }, + ucmt => { + Name => 'Comment', + # Ricoh writes a "Unicode" header even when text is ASCII (spaces anyway) + ValueConv => '$_=$val; s/^(Unicode\0|ASCII\0\0\0)//; tr/\0//d; s/\s+$//; $_', + }, + mnrt => { + Name => 'MakerNoteRicoh', + SubDirectory => { + TagTable => 'Image::ExifTool::Ricoh::Main', + Start => '$valuePtr + 8', + ByteOrder => 'BigEndian', + Base => '8', + }, + }, + rdc2 => { + Name => 'RicohRDC2', + Unknown => 1, + ValueConv => 'unpack("H*",$val)', + # have seen values like 0a000444 and 00000000 - PH + }, + thum => { + Name => 'ThumbnailImage', + Groups => { 2 => 'Preview' }, + Binary => 1, + }, +); + +# Ricoh composite tags +%Image::ExifTool::Ricoh::Composite = ( + GROUPS => { 2 => 'Camera' }, + LensID => { + SeparateTable => 'Ricoh LensID', + Require => 'Ricoh:LensFirmware', + RawConv => '$val[0] ? $val[0] : undef', + ValueConv => '$val=~s/\s*:.*//; $val', + PrintConv => \%ricohLensIDs, + }, + RicohPitch => { + Require => 'Ricoh:Accelerometer', + ValueConv => 'my @v = split(" ",$val); $v[1]', + }, + RicohRoll => { + Require => 'Ricoh:Accelerometer', + ValueConv => 'my @v = split(" ",$val); $v[0] <= 180 ? $v[0] : $v[0] - 360', + }, +); + +# add our composite tags +Image::ExifTool::AddCompositeTags('Image::ExifTool::Ricoh'); + + +#------------------------------------------------------------------------------ +# Process Ricoh text-based maker notes +# Inputs: 0) ExifTool object reference +# 1) Reference to directory information hash +# 2) Pointer to tag table for this directory +# Returns: 1 on success, otherwise returns 0 and sets a Warning +sub ProcessRicohText($$$) +{ + my ($et, $dirInfo, $tagTablePtr) = @_; + my $dataPt = $$dirInfo{DataPt}; + my $dataLen = $$dirInfo{DataLen}; + my $dirStart = $$dirInfo{DirStart} || 0; + my $dirLen = $$dirInfo{DirLen} || $dataLen - $dirStart; + my $verbose = $et->Options('Verbose'); + + my $data = substr($$dataPt, $dirStart, $dirLen); + return 1 if $data =~ /^\0/; # blank Ricoh maker notes + # validate text maker notes + unless ($data =~ /^(Rev|Rv)/) { + $et->Warn('Bad Ricoh maker notes'); + return 0; + } + while ($data =~ m/([A-Z][a-z]{1,2})([0-9A-F]+);/sg) { + my $tag = $1; + my $val = $2; + my $tagInfo = $et->GetTagInfo($tagTablePtr, $tag); + if ($verbose) { + $et->VerboseInfo($tag, $tagInfo, + Table => $tagTablePtr, + Value => $val, + ); + } + unless ($tagInfo) { + next unless $$et{OPTIONS}{Unknown}; + $tagInfo = { + Name => "Ricoh_Text_$tag", + Unknown => 1, + PrintConv => 'length($val) > 60 ? substr($val,0,55) . "[...]" : $val', + }; + # add tag information to table + AddTagToTable($tagTablePtr, $tag, $tagInfo); + } + $et->FoundTag($tagInfo, $val); + } + return 1; +} + +#------------------------------------------------------------------------------ +# Process Ricoh APP5 RMETA information +# Inputs: 0) ExifTool ref, 1) dirInfo ref, 2) tag table ref +# Returns: 1 on success, otherwise returns 0 and sets a Warning +sub ProcessRicohRMETA($$$) +{ + my ($et, $dirInfo, $tagTablePtr) = @_; + my $dataPt = $$dirInfo{DataPt}; + my $dirStart = $$dirInfo{DirStart}; + my $dataLen = length($$dataPt); + my $dirLen = $dataLen - $dirStart; + my $verbose = $et->Options('Verbose'); + + $et->VerboseDir('Ricoh RMETA') if $verbose; + $dirLen < 20 and $et->Warn('Truncated Ricoh RMETA data', 1), return 0; + my $byteOrder = substr($$dataPt, $dirStart, 2); + $byteOrder = GetByteOrder() if $byteOrder eq "\0\0"; # (same order as container) + SetByteOrder($byteOrder) or $et->Warn('Bad Ricoh RMETA data', 1), return 0; + # get the RMETA segment number + my $rmetaNum = Get16u($dataPt, $dirStart+4); + if ($rmetaNum != 0) { + # not sure how to recognize audio, so do it by checking for "RIFF" header + # and assume all subsequent RMETA segments are part of the audio data + # (but it looks like the int16u at $dirStart+6 is the next block number + # if the data is continued, or 0 for the last block) + $dirLen < 14 and $et->Warn('Short Ricoh RMETA block', 1), return 0; + my $audioLen = Get16u($dataPt, $dirStart+12); + $audioLen + 14 > $dirLen and $et->Warn('Truncated Ricoh RMETA audio data', 1), return 0; + my $buff = substr($$dataPt, $dirStart + 14, $audioLen); + if ($audioLen >= 4 and substr($buff, 0, 4) eq 'RIFF') { + $et->HandleTag($tagTablePtr, '_audio', \$buff); + } elsif ($$et{VALUE}{SoundFile}) { + ${$$et{VALUE}{SoundFile}} .= $buff; + } else { + $et->Warn('Unknown Ricoh RMETA type', 1); + return 0; + } + return 1; + } + # decode standard RMETA tag directory + my (@tags, @vals, @nums, $valPos, $numPos); + my $pos = $dirStart + Get16u($dataPt, $dirStart+8); + my $numEntries = Get16u($dataPt, $pos); + $numEntries > 100 and $et->Warn('Bad RMETA entry count'), return 0; + $pos += 10; # start of first RMETA section + # loop through RMETA sections + while ($pos <= $dataLen - 4) { + my $type = Get16u($dataPt, $pos); + my $size = Get16u($dataPt, $pos + 2); + last unless $size; + $pos += 4; + $size -= 2; + if ($size < 0 or $pos + $size > $dataLen) { + $et->Warn('Corrupted Ricoh RMETA data', 1); + last; + } + my $dat = substr($$dataPt, $pos, $size); + if ($verbose) { + $et->VPrint(2, "$$et{INDENT}RMETA section type=$type size=$size\n"); + $et->VerboseDump(\$dat, Addr => $$dirInfo{DataPos} + $pos); + } + if ($type == 1) { # section 1: tag names + # save the tag names + @tags = split /\0/, $dat, $numEntries+1; + } elsif ($type == 2 || $type == 18) { # section 2/18: string values (G800 uses type 18) + # save the tag values (assume "ASCII\0" encoding since others never seen) + @vals = split /\0/, $dat, $numEntries+1; + $valPos = $pos; # save position of first string value + } elsif ($type == 3) { # section 3: numerical values + if ($size < $numEntries * 2) { + $et->Warn('Truncated RMETA section 3'); + } else { + # save the numerical tag values + # (0=empty, 0xffff=text input, otherwise menu item number) + @nums = unpack(($byteOrder eq 'MM' ? 'n' : 'v').$numEntries, $dat); + $numPos = $pos; # save position of numerical values + } + } elsif ($type != 16) { + $et->Warn("Unrecognized RMETA section (type $type, len $size)"); + } + $pos += $size; + } + return 1 unless @tags or @vals; + $valPos or $valPos = 0; # (just in case there was no value section) + # find next tag in null-delimited list + # unpack numerical values from block of int16u values + my ($i, $name); + for ($i=0; $i<$numEntries; ++$i) { + my $tag = $tags[$i]; + my $val = $vals[$i]; + $val = '' unless defined $val; + unless (defined $tag and length $tag) { + length $val or ++$valPos, next; # (skip empty entries) + $tag = ''; + } + ($name = $tag) =~ s/\b([a-z])/\U$1/gs; # capitalize all words + $name =~ s/ (\w)/\U$1/g; # remove special characters + $name = 'RMETA_Unknown' unless length($name); + my $num = $nums[$i]; + my $tagInfo = $et->GetTagInfo($tagTablePtr, $tag); + if ($tagInfo) { + # make sure print conversion is defined + $$tagInfo{PrintConv} = { } unless ref $$tagInfo{PrintConv} eq 'HASH'; + } else { + # create tagInfo hash + $tagInfo = { Name => $name, PrintConv => { } }; + AddTagToTable($tagTablePtr, $tag, $tagInfo); + } + # use string value directly if no numerical value + $num = $val unless defined $num; + # add conversion for this value (replacing any existing entry) + $tagInfo->{PrintConv}->{$num} = length $val ? $val : $num; + if ($verbose) { + my %datParms; + if (length $val) { + %datParms = ( Start => $valPos, Size => length($val), Format => 'string' ); + } elsif ($numPos) { + %datParms = ( Start => $numPos + $i * 2, Size => 2, Format => 'int16u' ); + } + %datParms and $datParms{DataPt} = $dataPt, $datParms{DataPos} = $$dirInfo{DataPos}; + $et->VerboseInfo($tag, $tagInfo, Table=>$tagTablePtr, Value=>$num, %datParms); + } + $et->FoundTag($tagInfo, $num); + $valPos += length($val) + 1; + } + return 1; +} + +1; # end + +__END__ + +=head1 NAME + +Image::ExifTool::Ricoh - Ricoh EXIF maker notes tags + +=head1 SYNOPSIS + +This module is loaded automatically by Image::ExifTool when required. + +=head1 DESCRIPTION + +This module contains definitions required by Image::ExifTool to +interpret Ricoh maker notes EXIF meta information. + +=head1 AUTHOR + +Copyright 2003-2019, Phil Harvey (phil at owl.phy.queensu.ca) + +This library is free software; you can redistribute it and/or modify it +under the same terms as Perl itself. + +=head1 REFERENCES + +=over 4 + +=item L<http://www.ozhiker.com/electronics/pjmt/jpeg_info/ricoh_mn.html> + +=back + +=head1 ACKNOWLEDGEMENTS + +Thanks to Tim Gray for his help decoding a number of tags for the Ricoh GR. + +=head1 SEE ALSO + +L<Image::ExifTool::TagNames/Ricoh Tags>, +L<Image::ExifTool(3pm)|Image::ExifTool> + +=cut diff --git a/lib/Image/ExifTool/Samsung.pm b/lib/Image/ExifTool/Samsung.pm new file mode 100644 index 0000000..9e6a49f --- /dev/null +++ b/lib/Image/ExifTool/Samsung.pm @@ -0,0 +1,1342 @@ +#------------------------------------------------------------------------------ +# File: Samsung.pm +# +# Description: Samsung EXIF maker notes tags +# +# Revisions: 2010/03/01 - P. Harvey Created +# +# References: 1) Tae-Sun Park private communication +# 2) http://www.cybercom.net/~dcoffin/dcraw/ +# 3) Pascal de Bruijn private communication (NX100) +# 4) Jaroslav Stepanek via rt.cpan.org +# 5) Nick Livchits private communication +# 6) Sreerag Raghavan private communication (SM-C200) +# IB) Iliah Borg private communcation (LibRaw) +# NJ) Niels Kristian Bech Jensen private communication +#------------------------------------------------------------------------------ + +package Image::ExifTool::Samsung; + +use strict; +use vars qw($VERSION %samsungLensTypes); +use Image::ExifTool qw(:DataAccess :Utils); +use Image::ExifTool::Exif; + +$VERSION = '1.44'; + +sub WriteSTMN($$$); +sub ProcessINFO($$$); +sub ProcessSamsungIFD($$$); + +# Samsung LensType lookup +%samsungLensTypes = ( + # (added "Samsung NX" in all of these lens names - ref 4) + 0 => 'Built-in or Manual Lens', #PH (EX1, WB2000) + 1 => 'Samsung NX 30mm F2 Pancake', + 2 => 'Samsung NX 18-55mm F3.5-5.6 OIS', # (also version II, ref 1) + 3 => 'Samsung NX 50-200mm F4-5.6 ED OIS', + # what about the non-OIS version of the 18-55, + # which was supposed to be available before the 20-50? - PH + 4 => 'Samsung NX 20-50mm F3.5-5.6 ED', #PH/4 + 5 => 'Samsung NX 20mm F2.8 Pancake', #PH + 6 => 'Samsung NX 18-200mm F3.5-6.3 ED OIS', #4 + 7 => 'Samsung NX 60mm F2.8 Macro ED OIS SSA', #1 + 8 => 'Samsung NX 16mm F2.4 Pancake', #1/4 + 9 => 'Samsung NX 85mm F1.4 ED SSA', #4 + 10 => 'Samsung NX 45mm F1.8', #3 + 11 => 'Samsung NX 45mm F1.8 2D/3D', #3 + 12 => 'Samsung NX 12-24mm F4-5.6 ED', #4 + 13 => 'Samsung NX 16-50mm F2-2.8 S ED OIS', #forum3833 + 14 => 'Samsung NX 10mm F3.5 Fisheye', #NJ + 15 => 'Samsung NX 16-50mm F3.5-5.6 Power Zoom ED OIS', #5 + 20 => 'Samsung NX 50-150mm F2.8 S ED OIS', #PH + 21 => 'Samsung NX 300mm F2.8 ED OIS', #IB +); + +# range of values for Formats used in encrypted information +my %formatMinMax = ( + int16u => [ 0, 65535 ], + int32u => [ 0, 4294967295 ], + int16s => [ -32768, 32767 ], + int32s => [ -2147483648, 2147483647 ], +); + +# Samsung "STMN" maker notes (ref PH) +%Image::ExifTool::Samsung::Main = ( + PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData, + WRITE_PROC => \&WriteSTMN, + CHECK_PROC => \&Image::ExifTool::CheckBinaryData, + WRITABLE => 1, + FORMAT => 'int32u', + FIRST_ENTRY => 0, + IS_OFFSET => [ 2 ], # tag 2 is 'IsOffset' + IS_SUBDIR => [ 11 ], + GROUPS => { 0 => 'MakerNotes', 2 => 'Image' }, + NOTES => q{ + Tags found in the binary "STMN" format maker notes written by a number of + Samsung models. + }, + 0 => { + Name => 'MakerNoteVersion', + Format => 'undef[8]', + }, + 2 => { + Name => 'PreviewImageStart', + OffsetPair => 3, # associated byte count tagID + DataTag => 'PreviewImage', + IsOffset => 3, + Protected => 2, + WriteGroup => 'MakerNotes', + }, + 3 => { + Name => 'PreviewImageLength', + OffsetPair => 2, # point to associated offset + DataTag => 'PreviewImage', + Protected => 2, + WriteGroup => 'MakerNotes', + }, + 11 => { + Name => 'SamsungIFD', + # Note: this is not always an IFD. In many models the string + # "Park Byeongchan" is found at this location + Condition => '$$valPt =~ /^[^\0]\0\0\0/', + Format => 'undef[$size - 44]', + SubDirectory => { TagTable => 'Image::ExifTool::Samsung::IFD' }, + }, +); + +%Image::ExifTool::Samsung::IFD = ( + PROCESS_PROC => \&ProcessSamsungIFD, + NOTES => q{ + This is a standard-format IFD found in the maker notes of some Samsung + models, except that the entry count is a 4-byte integer and the offsets are + relative to the end of the IFD. Currently, no tags in this IFD are known, + so the Unknown (-u) or Verbose (-v) option must be used to see this + information. + }, + GROUPS => { 0 => 'MakerNotes', 2 => 'Image' }, + # 0x0001 - undef[4000|4100]: starts with "MN_PRV" (or all zeros) + # 0x0002 - undef[7000] : starts with "Kim Miae" + # 0x0003 - undef[5000] : starts with "Lee BK" + # 0x0004 - undef[500|2000] : starts with "IPCD" (or all zeros) + # 0x0006 - undef[100|200] : starts with "MN_ADS" (or all zeros) +); + +# Samsung maker notes (ref PH) +%Image::ExifTool::Samsung::Type2 = ( + WRITE_PROC => \&Image::ExifTool::Exif::WriteExif, + CHECK_PROC => \&Image::ExifTool::Exif::CheckExif, + WRITABLE => 1, + GROUPS => { 0 => 'MakerNotes', 2 => 'Image' }, + NOTES => 'Tags found in the EXIF-format maker notes of newer Samsung models.', + 0x0001 => { + Name => 'MakerNoteVersion', + Writable => 'undef', + Count => 4, + }, + 0x0002 => { + Name => 'DeviceType', + Groups => { 2 => 'Camera' }, + Writable => 'int32u', + PrintHex => 1, + PrintConv => { + 0x1000 => 'Compact Digital Camera', + 0x2000 => 'High-end NX Camera', + 0x3000 => 'HXM Video Camera', + 0x12000 => 'Cell Phone', + 0x300000 => 'SMX Video Camera', + }, + }, + 0x0003 => { + Name => 'SamsungModelID', + Groups => { 2 => 'Camera' }, + Writable => 'int32u', + PrintHex => 1, + PrintConv => { + 0x100101c => 'NX10', + 0x1001226 => 'HMX-S10BP', + 0x1001226 => 'HMX-S15BP', + 0x1001233 => 'HMX-Q10', + 0x1001234 => 'HMX-H300', + 0x1001234 => 'HMX-H304', + 0x100130c => 'NX100', + 0x1001327 => 'NX11', + 0x170104b => 'ES65, ES67 / VLUU ES65, ES67 / SL50', + 0x170104e => 'ES70, ES71 / VLUU ES70, ES71 / SL600', + 0x1701052 => 'ES73 / VLUU ES73 / SL605', + 0x1701055 => 'ES25, ES27 / VLUU ES25, ES27 / SL45', + 0x1701300 => 'ES28 / VLUU ES28', + 0x1701303 => 'ES74,ES75,ES78 / VLUU ES75,ES78', + 0x2001046 => 'PL150 / VLUU PL150 / TL210 / PL151', + 0x2001048 => 'PL100 / TL205 / VLUU PL100 / PL101', + 0x2001311 => 'PL120,PL121 / VLUU PL120,PL121', + 0x2001315 => 'PL170,PL171 / VLUUPL170,PL171', + 0x200131e => 'PL210, PL211 / VLUU PL210, PL211', + 0x2701317 => 'PL20,PL21 / VLUU PL20,PL21', + 0x2a0001b => 'WP10 / VLUU WP10 / AQ100', + 0x3000000 => 'Various Models (0x3000000)', + #0x3000000 => 'DV150F / DV151F / DV155F', + #0x3000000 => 'NX mini', + #0x3000000 => 'NX3000', + #0x3000000 => 'NX3300', + #0x3000000 => 'ST150F / ST151F / ST152F', + #0x3000000 => 'WB200F / WB201F / WB202F', + #0x3000000 => 'WB250F / WB251F / WB252F', + #0x3000000 => 'WB30F / WB31F / WB32F', + #0x3000000 => 'WB350F / WB351F / WB352F', + #0x3000000 => 'WB800F', + 0x3a00018 => 'Various Models (0x3a00018)', + #0x3a00018 => 'ES30 / VLUU ES30', + #0x3a00018 => 'ES80 / ES81', + #0x3a00018 => 'ES9 / ES8', + #0x3a00018 => 'PL200 / VLUU PL200', + #0x3a00018 => 'PL80 / VLUU PL80 / SL630 / PL81', + #0x3a00018 => 'PL90 / VLUU PL90', + #0x3a00018 => 'WB1100F / WB1101F / WB1102F', + #0x3a00018 => 'WB2200F', + 0x400101f => 'ST1000 / ST1100 / VLUU ST1000 / CL65', + 0x4001022 => 'ST550 / VLUU ST550 / TL225', + 0x4001025 => 'Various Models (0x4001025)', + #0x4001025 => 'DV300 / DV300F / DV305F', + #0x4001025 => 'ST500 / VLUU ST500 / TL220', + #0x4001025 => 'ST200 / ST200F / ST201 / ST201F / ST205F', + 0x400103e => 'VLUU ST5500, ST5500, CL80', + 0x4001041 => 'VLUU ST5000, ST5000, TL240', + 0x4001043 => 'ST70 / VLUU ST70 / ST71', + 0x400130a => 'Various Models (0x400130a)', + #0x400130a => 'VLUU ST100, ST100', + #0x400130a => 'VLUU ST600, ST600', + #0x400130a => 'VLUU ST80, ST80', + 0x400130e => 'ST90,ST91 / VLUU ST90,ST91', + 0x4001313 => 'VLUU ST95, ST95', + 0x4a00015 => 'VLUU ST60', + 0x4a0135b => 'ST30, ST65 / VLUU ST65 / ST67', + 0x5000000 => 'Various Models (0x5000000)', + #0x5000000 => 'EX2F', + #0x5000000 => 'NX1000', + #0x5000000 => 'NX20', + #0x5000000 => 'NX200', + #0x5000000 => 'NX210', + #0x5000000 => 'ST96', + #0x5000000 => 'WB750', + #0x5000000 => 'ST700', + 0x5001038 => 'Various Models (0x5001038)', + #0x5001038 => 'EK-GN120', + #0x5001038 => 'HMX-E10', + #0x5001038 => 'NX1', + #0x5001038 => 'NX2000', + #0x5001038 => 'NX30', + #0x5001038 => 'NX300', + #0x5001038 => 'NX500', + #0x5001038 => 'SM-C200', + #0x5001038 => 'WB2000', + 0x500103a => 'WB650 / VLUU WB650 / WB660', + 0x500103c => 'WB600 / VLUU WB600 / WB610', + 0x500133e => 'WB150 / WB150F / WB152 / WB152F / WB151', + 0x5a0000f => 'WB5000 / HZ25W', + 0x6001036 => 'EX1', + 0x700131c => 'VLUU SH100, SH100', + 0x27127002 => 'SMX-C20N', + }, + }, + # 0x0004 - undef[x] (SamsungContentsID?) + # 0x000a - int32u (ContinuousShotMode?) + # 0x000b - int16u (BestPhotoMode?) + # 0x000c - int32u ? values: 0,1 + # 0x000e - int32u[2] (SoundMultiPicture?) + # 0x0010 - rational64u ? values: undef,inf + 0x0011 => { #6 + Name => 'OrientationInfo', + SubDirectory => { TagTable => 'Image::ExifTool::Samsung::OrientationInfo' }, + }, + 0x0020 => [{ #forum7685 + Name => 'SmartAlbumColor', + Condition => '$$valPt =~ /^\0{4}/', + Writable => 'int16u', + Count => 2, + PrintConv => { + '0 0' => 'n/a', + }, + },{ + Name => 'SmartAlbumColor', + Writable => 'int16u', + Count => 2, + PrintConv => [{ + 0 => 'Red', + 1 => 'Yellow', + 2 => 'Green', + 3 => 'Blue', + 4 => 'Magenta', + 5 => 'Black', + 6 => 'White', + 7 => 'Various', + }], + }], + 0x0021 => { #1 + Name => 'PictureWizard', + Writable => 'int16u', + SubDirectory => { TagTable => 'Image::ExifTool::Samsung::PictureWizard' }, + }, + # 0x0022 - int32u (CaptureMode?) (Gamma? eg. 65538 = 1.2, ref forum7720) + # 0x0023 - string: "0123456789" (PH) (placeholder for SerialNumber?) + # 0x0025 - int32u (ImageCount?) + # 0x002a - undef[4] (SNSDirectShare?) + # 0x002f - string (GPSInfo01?) + 0x0030 => { #1 (NX100 with GPS) + Name => 'LocalLocationName', + Groups => { 2 => 'Location' }, + Writable => 'string', + Format => 'undef', + # this contains 2 place names (in Korean if in Korea), separated by a null+space + # - terminate at double-null and replace nulls with newlines + ValueConv => '$val=~s/\0\0.*//; $val=~s/\0 */\n/g; $val', + ValueConvInv => '$val=~s/(\x0d\x0a|\x0d|\x0a)/\0 /g; $val . "\0\0"' + }, + 0x0031 => { #1 (NX100 with GPS) + Name => 'LocationName', + Groups => { 2 => 'Location' }, + Writable => 'string', + }, + # 0x0032 - string (GPSInfo03) + # 0x0033 - string (GPSInfo04) + # 0x0034 - string (GPSInfo05) + 0x0035 => [{ + Name => 'PreviewIFD', + Condition => '$$self{TIFF_TYPE} eq "SRW" and $$self{Model} ne "EK-GN120"', # (not an IFD in JPEG images) + Groups => { 1 => 'PreviewIFD' }, + Flags => 'SubIFD', + SubDirectory => { + TagTable => 'Image::ExifTool::Nikon::PreviewIFD', + ByteOrder => 'Unknown', + Start => '$val', + }, + },{ + Name => 'PreviewIFD', + Condition => '$$self{TIFF_TYPE} eq "SRW"', # (not an IFD in JPEG images) + Groups => { 1 => 'PreviewIFD' }, + Flags => 'SubIFD', + SubDirectory => { + TagTable => 'Image::ExifTool::Nikon::PreviewIFD', + ByteOrder => 'Unknown', + Start => '$val - 36', + }, + }], + # 0x003a - int16u[2] (SmartLensInfo?) + # 0x003b - int16u[2] (PhotoStyleSelectInfo?) + # 0x003c - int16u (SmartRange?) + # 0x003d - int16u[5] (SmartCropInfo?) + # 0x003e - int32u (DualCapture?) + # 0x003f - int16u[2] (SGIFInfo?) + 0x0040 => { #forum7432 + Name => 'RawDataByteOrder', + PrintConv => { + 0 => 'Little-endian (Intel, II)', + 1 => 'Big-endian (Motorola, MM)', #(NC) + }, + }, + 0x0041 => { #forum7684 + Name => 'WhiteBalanceSetup', + Writable => 'int32u', + PrintConv => { + 0 => 'Auto', + 1 => 'Manual', + }, + }, + 0x0043 => { #1 (NC) + Name => 'CameraTemperature', + Groups => { 2 => 'Camera' }, + Writable => 'rational64s', + # (DPreview samples all 0.2 C --> pre-production model) + PrintConv => '$val =~ /\d/ ? "$val C" : $val', + PrintConvInv => '$val=~s/ ?C//; $val', + }, + # 0x0045 => { Name => 'RawCompressionMode', Writable => 'int32u' }, # (related to ExposureMode, not raw compresison? ref forum7432) + # 0x004a - int32u[7] (ImageVerification?) + # 0x004b - int32u[2] (RewindInfo?) + # 0x0050 - int32u (ColorSpace? - inconsistent) values: 1 (related to compression mode, ref forum7432) + 0x0050 => { #forum7432 + Name => 'RawDataCFAPattern', + PrintConv => { + 0 => 'Unchanged', + 1 => 'Swap', + 65535 => 'Roll', + }, + }, + # 0x0054 - int16u[2] (WeatherInfo?) + # 0x0060 - undef (AEInfo?) + # 0x0080 - undef (AFInfo?) + # 0x00a0 - undef[8192] (AWBInfo1): white balance information (ref 1): + # At byte 5788, the WBAdjust: "Adjust\0\X\0\Y\0\Z\xee\xea\xce\xab", where + # Y = BA adjust (0=Blue7, 7=0, 14=Amber7), Z = MG (0=Magenta7, 7=0, 14=Green7) + # 0x00a1 - undef (AWBInfo2?) + # 0x00c0 - undef (IPCInfo?) + # 0x00c7 - undef (SmartFunctionInfo?) + # 0x00e0 - int16u (SceneResult?) + # 0x00e1 - int16u[8] (SADebugInfo01?) + # 0x00e1 - int16u[x] (SADebugInfo02?) + 0x0100 => { + Name => 'FaceDetect', + Writable => 'int16u', + PrintConv => { 0 => 'Off', 1 => 'On' }, #(NC) + }, + # 0x0101 - int16u[6] (FaceDetectInfo?) + # 0x0102 - int16u[x] (FaceDetectInfo?) + 0x0120 => { + Name => 'FaceRecognition', + Writable => 'int32u', + PrintConv => { 0 => 'Off', 1 => 'On' }, #(NC) + }, + 0x0123 => { Name => 'FaceName', Writable => 'string' }, + # 0x140 - undef (LensInfo?) +# +# the following tags found only in SRW images +# + # 0xa000 - rational64u: 1 or 1.1 (ref PH) (MakerNoteVersion?) + 0xa001 => { #1 + Name => 'FirmwareName', + Groups => { 2 => 'Camera' }, + Writable => 'string', + }, + 0xa002 => { #PH/IB + Name => 'SerialNumber', + Condition => '$$valPt =~ /^\w{5}/', # should be at least 5 characters long + Groups => { 2 => 'Camera' }, + Writable => 'string', + }, + 0xa003 => { #1 (SRW images only) + Name => 'LensType', + Groups => { 2 => 'Camera' }, + Writable => 'int16u', + Count => -1, + PrintConv => [ \%samsungLensTypes ], + }, + 0xa004 => { #1 + Name => 'LensFirmware', + Groups => { 2 => 'Camera' }, + Writable => 'string', + }, + 0xa005 => { + Name => 'InternalLensSerialNumber', # Not the printed serial number (ref 1) + Groups => { 2 => 'Camera' }, + Writable => 'string', + }, + 0xa010 => { #1 + Name => 'SensorAreas', + Groups => { 2 => 'Camera' }, + Notes => 'full and valid sensor areas', + Writable => 'int32u', + Count => 8, + }, + 0xa011 => { #1 + Name => 'ColorSpace', + Writable => 'int16u', + PrintConv => { + 0 => 'sRGB', + 1 => 'Adobe RGB', + }, + }, + 0xa012 => { #1 + Name => 'SmartRange', + Writable => 'int16u', + PrintConv => { 0 => 'Off', 1 => 'On' }, + }, + 0xa013 => { #1 + Name => 'ExposureCompensation', + Writable => 'rational64s', + }, + 0xa014 => { #1 + Name => 'ISO', + Writable => 'int32u', + }, + 0xa018 => { #1 + Name => 'ExposureTime', + Writable => 'rational64u', + PrintConv => 'Image::ExifTool::Exif::PrintExposureTime($val)', + PrintConvInv => '$val', + }, + 0xa019 => { #1 + Name => 'FNumber', + Priority => 0, + Writable => 'rational64u', + PrintConv => 'sprintf("%.1f",$val)', + PrintConvInv => '$val', + }, + 0xa01a => { #1 + Name => 'FocalLengthIn35mmFormat', + Groups => { 2 => 'Camera' }, + Priority => 0, + Format => 'int32u', + ValueConv => '$val / 10', + ValueConvInv => '$val * 10', + PrintConv => '"$val mm"', + PrintConvInv => '$val=~s/\s*mm$//;$val', + }, + # 0xa01b - int32u (ImageCount?) + # 0xa01b - int16u (LDCLens?) + 0xa020 => { #1 + Name => 'EncryptionKey', + Writable => 'int32u', + Count => 11, + Protected => 1, + DataMember => 'EncryptionKey', + RawConv => '$$self{EncryptionKey} = [ split(" ",$val) ]; $val', + Notes => 'key used to decrypt the tags below', + # value is "305 72 737 456 282 307 519 724 13 505 193" + }, + 0xa021 => { #1 + Name => 'WB_RGGBLevelsUncorrected', + Writable => 'int32u', + Count => 4, + Notes => 'these tags not corrected for WB_RGGBLevelsBlack', + RawConv => 'Image::ExifTool::Samsung::Crypt($self,$val,$tagInfo,"-0")', + RawConvInv => 'Image::ExifTool::Samsung::Crypt($self,$val,$tagInfo,0)', + }, + 0xa022 => { #1 + Name => 'WB_RGGBLevelsAuto', + Writable => 'int32u', + Count => 4, + RawConv => 'Image::ExifTool::Samsung::Crypt($self,$val,$tagInfo,-4)', + RawConvInv => 'Image::ExifTool::Samsung::Crypt($self,$val,$tagInfo,4)', + }, + 0xa023 => { #1 + Name => 'WB_RGGBLevelsIlluminator1', + Writable => 'int32u', + Count => 4, + RawConv => 'Image::ExifTool::Samsung::Crypt($self,$val,$tagInfo,-8)', + RawConvInv => 'Image::ExifTool::Samsung::Crypt($self,$val,$tagInfo,8)', + }, + 0xa024 => { #1 + Name => 'WB_RGGBLevelsIlluminator2', + Writable => 'int32u', + Count => 4, + RawConv => 'Image::ExifTool::Samsung::Crypt($self,$val,$tagInfo,-1)', + RawConvInv => 'Image::ExifTool::Samsung::Crypt($self,$val,$tagInfo,1)', + }, + 0xa025 => { # (PostAEGain?) + Name => 'DigitalGain', #IB + Writable => 'int32u', + RawConv => 'Image::ExifTool::Samsung::Crypt($self,$val,$tagInfo,6)', + RawConvInv => 'Image::ExifTool::Samsung::Crypt($self,$val,$tagInfo,-6)', + }, + 0xa025 => { #IB + Name => 'HighlightLinearityLimit', + Writable => 'int32u', + }, + 0xa028 => { #2/PH + Name => 'WB_RGGBLevelsBlack', + Writable => 'int32s', + Count => 4, + RawConv => 'Image::ExifTool::Samsung::Crypt($self,$val,$tagInfo,"-0")', + RawConvInv => 'Image::ExifTool::Samsung::Crypt($self,$val,$tagInfo,0)', + }, + 0xa030 => { #1 + Name => 'ColorMatrix', + Writable => 'int32s', + Count => 9, + RawConv => 'Image::ExifTool::Samsung::Crypt($self,$val,$tagInfo,0)', + RawConvInv => 'Image::ExifTool::Samsung::Crypt($self,$val,$tagInfo,"-0")', + }, + 0xa031 => { #1 + Name => 'ColorMatrixSRGB', + Writable => 'int32s', + Count => 9, + RawConv => 'Image::ExifTool::Samsung::Crypt($self,$val,$tagInfo,0)', + RawConvInv => 'Image::ExifTool::Samsung::Crypt($self,$val,$tagInfo,"-0")', + }, + 0xa032 => { #1 + Name => 'ColorMatrixAdobeRGB', + Writable => 'int32s', + Count => 9, + RawConv => 'Image::ExifTool::Samsung::Crypt($self,$val,$tagInfo,0)', + RawConvInv => 'Image::ExifTool::Samsung::Crypt($self,$val,$tagInfo,"-0")', + }, + 0xa033 => { #1 + Name => 'CbCrMatrixDefault', + Writable => 'int32s', + Count => 4, + RawConv => 'Image::ExifTool::Samsung::Crypt($self,$val,$tagInfo,0)', + RawConvInv => 'Image::ExifTool::Samsung::Crypt($self,$val,$tagInfo,"-0")', + }, + 0xa034 => { #1 + Name => 'CbCrMatrix', + Writable => 'int32s', + Count => 4, + RawConv => 'Image::ExifTool::Samsung::Crypt($self,$val,$tagInfo,4)', + RawConvInv => 'Image::ExifTool::Samsung::Crypt($self,$val,$tagInfo,-4)', + }, + 0xa035 => { #1 + Name => 'CbCrGainDefault', + Writable => 'int32u', + Count => 2, + RawConv => 'Image::ExifTool::Samsung::Crypt($self,$val,$tagInfo,"-0")', + RawConvInv => 'Image::ExifTool::Samsung::Crypt($self,$val,$tagInfo,0)', + }, + 0xa036 => { #1 + Name => 'CbCrGain', + Writable => 'int32u', + Count => 2, + RawConv => 'Image::ExifTool::Samsung::Crypt($self,$val,$tagInfo,-2)', + RawConvInv => 'Image::ExifTool::Samsung::Crypt($self,$val,$tagInfo,2)', + }, + 0xa040 => { #1 + Name => 'ToneCurveSRGBDefault', + Writable => 'int32u', + Count => 23, + Notes => q{ + first value gives the number of tone curve entries. This is followed by an + array of X coordinates then an array of Y coordinates + }, + RawConv => 'Image::ExifTool::Samsung::Crypt($self,$val,$tagInfo,0,"-0")', + RawConvInv => 'Image::ExifTool::Samsung::Crypt($self,$val,$tagInfo,"-0",0)', + }, + 0xa041 => { #1 + Name => 'ToneCurveAdobeRGBDefault', + Writable => 'int32u', + Count => 23, + RawConv => 'Image::ExifTool::Samsung::Crypt($self,$val,$tagInfo,0,"-0")', + RawConvInv => 'Image::ExifTool::Samsung::Crypt($self,$val,$tagInfo,"-0",0)', + }, + 0xa042 => { #1 + Name => 'ToneCurveSRGB', + Writable => 'int32u', + Count => 23, + RawConv => 'Image::ExifTool::Samsung::Crypt($self,$val,$tagInfo,0,"-0")', + RawConvInv => 'Image::ExifTool::Samsung::Crypt($self,$val,$tagInfo,"-0",0)', + }, + 0xa043 => { #1 + Name => 'ToneCurveAdobeRGB', + Writable => 'int32u', + Count => 23, + RawConv => 'Image::ExifTool::Samsung::Crypt($self,$val,$tagInfo,0,"-0")', + RawConvInv => 'Image::ExifTool::Samsung::Crypt($self,$val,$tagInfo,"-0",0)', + }, + 0xa048 => { #1 + Name => 'RawData', + Unknown => 1, + Writable => 'int32s', + Count => 12, + RawConv => 'Image::ExifTool::Samsung::Crypt($self,$val,$tagInfo,0)', + RawConvInv => 'Image::ExifTool::Samsung::Crypt($self,$val,$tagInfo,"-0")', + }, + 0xa050 => { #1 + Name => 'Distortion', + Unknown => 1, + Writable => 'int32s', + Count => 8, + RawConv => 'Image::ExifTool::Samsung::Crypt($self,$val,$tagInfo,0)', + RawConvInv => 'Image::ExifTool::Samsung::Crypt($self,$val,$tagInfo,"-0")', + }, + 0xa051 => { #1 + Name => 'ChromaticAberration', + Unknown => 1, + Writable => 'int16u', + Count => 22, + RawConv => 'Image::ExifTool::Samsung::Crypt($self,$val,$tagInfo,"-0",-7,-3)', + RawConvInv => 'Image::ExifTool::Samsung::Crypt($self,$val,$tagInfo,0,7,3)', + }, + 0xa052 => { #1 + Name => 'Vignetting', + Unknown => 1, + Writable => 'int16u', + Count => 15, + RawConv => 'Image::ExifTool::Samsung::Crypt($self,$val,$tagInfo,0,"-0")', + RawConvInv => 'Image::ExifTool::Samsung::Crypt($self,$val,$tagInfo,"-0",0)', + }, + 0xa053 => { #1 + Name => 'VignettingCorrection', + Unknown => 1, + Writable => 'int16u', + Count => 15, + RawConv => 'Image::ExifTool::Samsung::Crypt($self,$val,$tagInfo,0,"-0")', + RawConvInv => 'Image::ExifTool::Samsung::Crypt($self,$val,$tagInfo,"-0",0)', + }, + 0xa054 => { #1 + Name => 'VignettingSetting', + Unknown => 1, + Writable => 'int16u', + Count => 15, + RawConv => 'Image::ExifTool::Samsung::Crypt($self,$val,$tagInfo,0,"-0")', + RawConvInv => 'Image::ExifTool::Samsung::Crypt($self,$val,$tagInfo,"-0",0)', + }, + 0xa055 => { #1 + Name => 'Samsung_Type2_0xa055', # (DistortionCamera1st?) + Unknown => 1, + Hidden => 1, + Writable => 'int32s', + Count => 8, + RawConv => 'Image::ExifTool::Samsung::Crypt($self,$val,$tagInfo,8)', + RawConvInv => 'Image::ExifTool::Samsung::Crypt($self,$val,$tagInfo,-8)', + }, + 0xa056 => { #1 + Name => 'Samsung_Type2_0xa056', # (DistortionCamera2nd?) + Unknown => 1, + Hidden => 1, + Writable => 'int32s', + Count => 8, + RawConv => 'Image::ExifTool::Samsung::Crypt($self,$val,$tagInfo,5)', + RawConvInv => 'Image::ExifTool::Samsung::Crypt($self,$val,$tagInfo,-5)', + }, + 0xa057 => { #1 + Name => 'Samsung_Type2_0xa057', # (DistortionCameraSetting?) + Unknown => 1, + Hidden => 1, + Writable => 'int32s', + Count => 8, + RawConv => 'Image::ExifTool::Samsung::Crypt($self,$val,$tagInfo,2)', + RawConvInv => 'Image::ExifTool::Samsung::Crypt($self,$val,$tagInfo,-2)', + }, + # 0xa060 - rational64u (CISTemperature?) + # 0xa061 - int16u (Compression?) +); + +# orientation information (ref 6) +%Image::ExifTool::Samsung::OrientationInfo = ( + PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData, + WRITE_PROC => \&Image::ExifTool::WriteBinaryData, + CHECK_PROC => \&Image::ExifTool::CheckBinaryData, + WRITABLE => 1, + FORMAT => 'rational64s', + FIRST_ENTRY => 0, + GROUPS => { 0 => 'MakerNotes', 2 => 'Camera' }, + NOTES => 'Camera orientation information written by the Gear 360 (SM-C200).', + 0 => { + Name => 'YawAngle', #(NC) + Unknown => 1, + Notes => 'always zero', + }, + 1 => { + Name => 'PitchAngle', + Notes => 'upward tilt of rear camera in degrees', + }, + 2 => { + Name => 'RollAngle', + Notes => 'clockwise rotation of rear camera in degrees', + }, +); + +# Picture Wizard information (ref 1) +%Image::ExifTool::Samsung::PictureWizard = ( + PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData, + WRITE_PROC => \&Image::ExifTool::WriteBinaryData, + CHECK_PROC => \&Image::ExifTool::CheckBinaryData, + WRITABLE => 1, + FORMAT => 'int16u', + FIRST_ENTRY => 0, + GROUPS => { 0 => 'MakerNotes', 2 => 'Image' }, + 0 => { + Name => 'PictureWizardMode', + PrintConvColumns => 3, + PrintConv => { #3 + 0 => 'Standard', + 1 => 'Vivid', + 2 => 'Portrait', + 3 => 'Landscape', + 4 => 'Forest', + 5 => 'Retro', + 6 => 'Cool', + 7 => 'Calm', + 8 => 'Classic', + 9 => 'Custom1', + 10 => 'Custom2', + 11 => 'Custom3', + 255 => 'n/a', #PH + }, + }, + 1 => 'PictureWizardColor', + 2 => { + Name => 'PictureWizardSaturation', + ValueConv => '$val - 4', + ValueConvInv => '$val + 4', + }, + 3 => { + Name => 'PictureWizardSharpness', + ValueConv => '$val - 4', + ValueConvInv => '$val + 4', + }, + 4 => { + Name => 'PictureWizardContrast', + ValueConv => '$val - 4', + ValueConvInv => '$val + 4', + }, +); + +# INFO tags in Samsung MP4 videos (ref PH) +%Image::ExifTool::Samsung::INFO = ( + PROCESS_PROC => \&ProcessINFO, + GROUPS => { 0 => 'MakerNotes', 2 => 'Video' }, + NOTES => q{ + This information is found in MP4 videos from Samsung models such as the + SMX-C20N. + }, + EFCT => 'Effect', # (guess) + QLTY => 'Quality', + # MDEL - value: 0 + # ASPT - value: 1, 2 +); + +# Samsung MP4 TAGS information (PH - from WP10 sample) +# --> very similar to Sanyo MP4 information +%Image::ExifTool::Samsung::MP4 = ( + PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData, + GROUPS => { 0 => 'MakerNotes', 2 => 'Camera' }, + NOTES => q{ + This information is found in Samsung MP4 videos from models such as the + WP10. + }, + 0x00 => { + Name => 'Make', + Format => 'string[24]', + PrintConv => 'ucfirst(lc($val))', + }, + 0x18 => { + Name => 'Model', + Description => 'Camera Model Name', + Format => 'string[16]', + }, + 0x2e => { #(NC) + Name => 'ExposureTime', + Format => 'int32u', + ValueConv => '$val ? 10 / $val : 0', + PrintConv => 'Image::ExifTool::Exif::PrintExposureTime($val)', + }, + 0x32 => { + Name => 'FNumber', + Format => 'rational64u', + PrintConv => 'sprintf("%.1f",$val)', + }, + 0x3a => { #(NC) + Name => 'ExposureCompensation', + Format => 'rational64s', + PrintConv => '$val ? sprintf("%+.1f", $val) : 0', + }, + 0x6a => { + Name => 'ISO', + Format => 'int32u', + }, + 0x7d => { + Name => 'Software', + Format => 'string[32]', + # (these tags are not at a constant offset for Olympus/Sanyo videos, + # so just to be safe use this to validate subsequent tags) + RawConv => q{ + $val =~ /^SAMSUNG/ or return undef; + $$self{SamsungMP4} = 1; + return $val; + }, + }, + 0xf4 => { + Name => 'Thumbnail', + Condition => '$$self{SamsungMP4}', + SubDirectory => { + TagTable => 'Image::ExifTool::Samsung::Thumbnail', + Base => '$start', + }, + }, +); + +# thumbnail image information found in MP4 videos (similar in Olympus,Samsung,Sanyo) +%Image::ExifTool::Samsung::Thumbnail = ( + PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData, + GROUPS => { 0 => 'MakerNotes', 2 => 'Camera' }, + FIRST_ENTRY => 0, + FORMAT => 'int32u', + 1 => 'ThumbnailWidth', + 2 => 'ThumbnailHeight', + 3 => 'ThumbnailLength', + 4 => { Name => 'ThumbnailOffset', IsOffset => 1 }, +); + +# Samsung MP4 @sec information (PH - from WB30F sample) +%Image::ExifTool::Samsung::sec = ( + PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData, + GROUPS => { 0 => 'MakerNotes', 2 => 'Camera' }, + NOTES => q{ + This information is found in the @sec atom of Samsung MP4 videos from models + such as the WB30F. + }, + 0x00 => { + Name => 'Make', + Format => 'string[32]', + PrintConv => 'ucfirst(lc($val))', + }, + 0x20 => { + Name => 'Model', + Description => 'Camera Model Name', + Format => 'string[32]', + }, + 0x200 => { Name => 'ThumbnailWidth', Format => 'int32u' }, + 0x204 => { Name => 'ThumbnailHeight', Format => 'int32u' }, + 0x208 => { Name => 'ThumbnailLength', Format => 'int32u' }, # (2 bytes too long in my sample) + 0x20c => { + Name => 'ThumbnailImage', + Groups => { 2 => 'Preview' }, + Format => 'undef[$val{0x208}]', + Notes => 'the THM image, embedded metadata is extracted as the first sub-document', + SetBase => 1, + RawConv => q{ + my $pt = $self->ValidateImage(\$val, $tag); + if ($pt) { + $$self{BASE} += 0x20c; + $$self{DOC_NUM} = ++$$self{DOC_COUNT}; + $self->ExtractInfo($pt, { ReEntry => 1 }); + $$self{DOC_NUM} = 0; + } + return $pt; + }, + }, +); + +# Samsung MP4 smta information (PH - from SM-C101 sample) +%Image::ExifTool::Samsung::smta = ( + GROUPS => { 0 => 'MakerNotes', 2 => 'Video' }, + NOTES => q{ + This information is found in the smta atom of Samsung MP4 videos from models + such as the Galaxy S4. + }, + svss => { + Name => 'SamsungSvss', + SubDirectory => { TagTable => 'Image::ExifTool::Samsung::svss' }, + }, + # swtr - 4 bytes, all zero + # scid - 8 bytes, all zero + # saut - 4 bytes, all zero +); + +# Samsung MP4 svss information (PH - from SM-C101 sample) +%Image::ExifTool::Samsung::svss = ( + GROUPS => { 0 => 'MakerNotes', 2 => 'Video' }, + NOTES => q{ + This information is found in the svss atom of Samsung MP4 videos from models + such as the Galaxy S4. + }, + # junk - 10240 bytes, all zero +); + +# thumbnail image information found in some MP4 videos +%Image::ExifTool::Samsung::Thumbnail2 = ( + PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData, + GROUPS => { 0 => 'MakerNotes', 2 => 'Camera' }, + FIRST_ENTRY => 0, + FORMAT => 'int32u', + 1 => 'ThumbnailWidth', + 2 => 'ThumbnailHeight', + 3 => 'ThumbnailLength', + 4 => { Name => 'ThumbnailOffset', IsOffset => 1 }, +); + +# information extracted from "ssuniqueid\0" APP5 (ref PH) +%Image::ExifTool::Samsung::APP5 = ( + GROUPS => { 0 => 'MakerNotes', 2 => 'Camera' }, + ssuniqueid => { + Name => 'UniqueID', + # 32 bytes - some sort of serial number? + ValueConv => 'unpack("H*",$val)', + }, +); + +# information extracted from Samsung trailer (ie. Samsung SM-T805 "Sound & Shot" JPEG) (ref PH) +%Image::ExifTool::Samsung::Trailer = ( + GROUPS => { 0 => 'MakerNotes', 2 => 'Other' }, + VARS => { NO_ID => 1 }, + NOTES => q{ + Tags extracted from the trailer of JPEG images written when using certain + features (such as "Sound & Shot" or "Shot & More") from Samsung models such + as the Galaxy S4 and Tab S. + }, + '0x0001-name' => 'EmbeddedImageName', # ("DualShot_1","DualShot_2") + '0x0001' => { Name => 'EmbeddedImage', Groups => { 2 => 'Preview' }, Binary => 1 }, + '0x0100-name' => 'EmbeddedAudioFileName', # ("SoundShot_000") + '0x0100' => { Name => 'EmbeddedAudioFile', Groups => { 2 => 'Audio' }, Binary => 1 }, + '0x0201-name' => 'SurroundShotVideoName', # ("Interactive_Panorama_000") + '0x0201' => { Name => 'SurroundShotVideo', Groups => { 2 => 'Video' }, Binary => 1 }, + # 0x0800-name - seen 'SoundShot_Meta_Info' + # 0x0800 - unknown (29 bytes) (contains already-extracted EmbeddedAudioFileName) + # 0x0830-name - seen '1165724808.pre' + # 0x0830 - unknown (164004 bytes) + # 0x08d0-name - seen 'Interactive_Panorama_Info' + # 0x08d0 - unknown (7984 bytes) + # 0x08e0-name - seen 'Panorama_Shot_Info' + # 0x08e0 - string, seen 'PanoramaShot' + # 0x08e1-name - seen 'Motion_Panorama_Info' + # 0x09e0-name - seen 'Burst_Shot_Info' + # 0x09e0 - string, seen '489489125' + # 0x0a01-name - seen 'Image_UTC_Data' + '0x0a01' => { #forum7161 + Name => 'TimeStamp', + Groups => { 2 => 'Time' }, + ValueConv => 'ConvertUnixTime($val / 1e3, 1)', + PrintConv => '$self->ConvertDateTime($val)', + }, + '0x0a20-name' => 'DualCameraImageName', # ("FlipPhoto_002") + '0x0a20' => { Name => 'DualCameraImage', Groups => { 2 => 'Preview' }, Binary => 1 }, + '0x0a30-name' => 'EmbeddedVideoType', # ("MotionPhoto_Data") + '0x0a30' => { Name => 'EmbeddedVideoFile', Groups => { 2 => 'Video' }, Binary => 1 }, #forum7161 + # 0x0aa1-name - seen 'MCC_Data' + # 0x0aa1 - seen '234','222' + '0x0ab1-name' => 'DepthMapName', # seen 'DualShot_DepthMap_1' (SM-N950U) + '0x0ab1' => { Name => 'DepthMapData', Binary => 1 }, + # 0x0ab3-name - seen 'DualShot_Extra_Info' (SM-N950U) + '0x0ab3' => { # (SM-N950U) + Name => 'DualShotInfo', + SubDirectory => { TagTable => 'Image::ExifTool::Samsung::DualShotInfo' }, + }, + # 0x0ac0-name - seen 'ZoomInOut_Info' (SM-N950U) + # 0x0ac0 - 2048 bytes of interesting stuff including firmware version? (SM-N950U) + # 0xa050-name - seen 'Jpeg360_2D_Info' (Samsung Gear 360) + # 0xa050 - seen 'Jpeg3602D' (Samsung Gear 360) +); + +# DualShot Extra Info (ref PH) +%Image::ExifTool::Samsung::DualShotInfo = ( + PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData, + GROUPS => { 0 => 'MakerNotes', 2 => 'Image' }, + FIRST_ENTRY => 0, + FORMAT => 'int32u', + 9 => 'DepthMapWidth', + 10 => 'DepthMapHeight', +); + +# Samsung composite tags +%Image::ExifTool::Samsung::Composite = ( + GROUPS => { 2 => 'Image' }, + WB_RGGBLevels => { + Require => { + 0 => 'WB_RGGBLevelsUncorrected', + 1 => 'WB_RGGBLevelsBlack', + }, + ValueConv => q{ + my @a = split ' ', $val[0]; + my @b = split ' ', $val[1]; + $a[$_] -= $b[$_] foreach 0..$#a; + return "@a"; + }, + }, + DepthMapTiff => { + Require => { + 0 => 'DepthMapData', + 1 => 'DepthMapWidth', + 2 => 'DepthMapHeight', + }, + ValueConv => q{ + return undef unless length ${$val[0]} == $val[1] * $val[2]; + my $tiff = MakeTiffHeader($val[1],$val[2],1,8) . ${$val[0]}; + return \$tiff; + }, + } +); + +# add our composite tags +Image::ExifTool::AddCompositeTags('Image::ExifTool::Samsung'); + +#------------------------------------------------------------------------------ +# Encrypt/Decrypt NX10 information +# Inputs: 0) ExifTool ref, 1) value as a string of integers, +# 2) tagInfo hash ref, 3-N) encryption salt values +# Returns: encrypted/decrypted value +# Notes: +# 1) The encryption salt starts with '-' to reverse the encryption algorithm +# 2) Additional salt values are provided when tag stores multiple arrays +# (in which case the first value of the tag gives the array length) +sub Crypt($$$@) +{ + my ($et, $val, $tagInfo, @salt) = @_; + my $key = $$et{EncryptionKey} or return undef; + my $format = $$tagInfo{Writable} || $$tagInfo{Format} or return undef; + return undef unless $formatMinMax{$format}; + my ($min, $max) = @{$formatMinMax{$format}}; + my @a = split ' ', $val; + my $newSalt = (@salt > 1) ? 1 : 0; # skip length entry if this is an array + my ($i, $sign, $salt, $start); + for ($i=$newSalt; $i<@a; ++$i) { + if ($i == $newSalt) { + $start = $i; + $salt = shift @salt; + $sign = ($salt =~ s/^-//) ? -1 : 1; + $newSalt += $a[0] if @salt; + } + $a[$i] += $sign * $$key[($salt+$i-$start) % scalar(@$key)]; + # handle integer wrap-around + if ($sign > 0) { + $a[$i] -= $max - $min + 1 if $a[$i] > $max; + } else { + $a[$i] += $max - $min + 1 if $a[$i] < $min; + } + } + return "@a"; +} + +#------------------------------------------------------------------------------ +# Process Samsung MP4 INFO data +# Inputs: 0) ExifTool ref, 1) dirInfo ref, 2) tag table ref +# Returns: 1 on success +sub ProcessINFO($$$) +{ + my ($et, $dirInfo, $tagTablePtr) = @_; + my $dataPt = $$dirInfo{DataPt}; + my $pos = $$dirInfo{DirStart}; + my $len = $$dirInfo{DirLen}; + my $end = $pos + $len; + $et->VerboseDir('INFO', undef, $len); + while ($pos + 8 <= $end) { + my $tag = substr($$dataPt, $pos, 4); + my $val = Get32u($dataPt, $pos + 4); + unless ($$tagTablePtr{$tag}) { + my $name = "Samsung_INFO_$tag"; + $name =~ tr/-_0-9a-zA-Z//dc; + AddTagToTable($tagTablePtr, $tag, { Name => $name }) if $name; + } + $et->HandleTag($tagTablePtr, $tag, $val); + $pos += 8; + } + return 1; +} + +#------------------------------------------------------------------------------ +# Inputs: 0) ExifTool object ref, 1) source dirInfo ref, 2) tag table ref +# Returns: true on success +sub ProcessSamsungIFD($$$) +{ + my ($et, $dirInfo, $tagTablePtr) = @_; + my $len = $$dirInfo{DataLen}; + my $pos = $$dirInfo{DirStart}; + return 0 unless $pos + 4 < $len; + my $dataPt = $$dirInfo{DataPt}; + my $buff = substr($$dataPt, $pos, 4); + # this is not an IFD for many models + # (the string "Park Byeongchan" is often found here) + return 0 unless $buff =~ s/^([^\0])\0\0\0/$1\0$1\0/s; + my $numEntries = ord $1; + if ($$et{HTML_DUMP}) { + my $pt = $$dirInfo{DirStart} + $$dirInfo{DataPos} + $$dirInfo{Base}; + $et->HDump($pt-44, 44, "MakerNotes header", 'Samsung'); + $et->HDump($pt, 4, "MakerNotes entries", "Format: int32u\nEntry count: $numEntries"); + $$dirInfo{NoDumpEntryCount} = 1; + } + substr($$dataPt, $pos, 4) = $buff; # insert bogus 2-byte entry count + # offset base is at end of IFD + my $shift = $$dirInfo{DirStart} + 4 + $numEntries * 12 + 4; + $$dirInfo{Base} += $shift; + $$dirInfo{DataPos} -= $shift; + $$dirInfo{DirStart} += 2; # start at bogus entry count + $$dirInfo{ZeroOffsetOK} = 1; # disable check for zero offset + delete $$et{NO_UNKNOWN}; # (set for BinaryData, but not for EXIF IFD's) + my $rtn = Image::ExifTool::Exif::ProcessExif($et, $dirInfo, $tagTablePtr); + substr($$dataPt, $pos + 2, 1) = "\0"; # remove bogus count + return $rtn; +} + +#------------------------------------------------------------------------------ +# Read/write Samsung trailer (ie. "Sound & Shot" written by Galaxy Tab S (SM-T805)) +# Inputs: 0) ExifTool object reference, 1) dirInfo reference +# Returns: 1 on success, 0 not valid Samsung trailer, or -1 error writing +# - updates DataPos to point to start of Samsung trailer +# - updates DirLen to existing trailer length +sub ProcessSamsung($$$) +{ + my ($et, $dirInfo) = @_; + my $raf = $$dirInfo{RAF}; + my $offset = $$dirInfo{Offset} || 0; + my $outfile = $$dirInfo{OutFile}; + my $verbose = $et->Options('Verbose'); + my $unknown = $et->Options('Unknown'); + my ($buff, $buf2, $index, $offsetPos, $audioNOff, $audioSize); + + return 0 unless $raf->Seek(-6-$offset, 2) and $raf->Read($buff, 6) == 6 and + ($buff eq 'QDIOBS' or $buff eq "\0\0SEFT"); + my $endPos = $raf->Tell(); + $raf->Seek(-2, 1) or return 0 if $buff eq 'QDIOBS'; # rewind to before 'BS' + my $blockEnd = $raf->Tell(); + SetByteOrder('II'); + + # read blocks backward until we find the SEFH/SEFT block + # (the only other block I have seen is QDIO/QDIO) +SamBlock: + for (;;) { + last unless $raf->Seek($blockEnd-8, 0) and $raf->Read($buff, 8) == 8; + my $type = substr($buff, 4); + last unless $type =~ /^\w+$/; + my $len = Get32u(\$buff, 0); + last unless $len < 0x10000 and $len >= 4 and $len + 8 < $blockEnd; + last unless $raf->Seek(-8-$len, 1) and $raf->Read($buff, $len) == $len; + $blockEnd -= $len + 8; + unless ($type eq 'SEFT') { # look for directory block (ends with "SEFT") + next unless $outfile and $type eq 'QDIO'; + # QDIO block format: + # 0 - 'QDIO' + # 4 - int32u: 101 (version) + # 8 - int32u: 1 + # 12 - int32u: absolute offset of audio file start (augh!!) + # 16 - int32u: absolute offset of audio file end (augh!!) + # 20 - int32u: 20 (QDIO block length minus 8) + # 24 - 'QDIO' + if ($len == 20) { + # save position of audio file offset in QDIO block + $offsetPos = $endPos - $raf->Tell() + $len - 12; + } else { + $et->Error('Unsupported Samsung trailer QDIO block', 1); + } + next; + } + last unless $buff =~ /^SEFH/ and $len >= 12; # validate SEFH header + my $dirPos = $raf->Tell() - $len; + # my $ver = Get32u(\$buff, 0x04); # version (=101) + my $count = Get32u(\$buff, 0x08); + last if 12 + 12 * $count > $len; + my $tagTablePtr = GetTagTable('Image::ExifTool::Samsung::Trailer'); + + # scan ahead quickly to look for the block where the data comes first + # (have only seen this to be the first in the directory, but just in case) + my $firstBlock = 0; + for ($index=0; $index<$count; ++$index) { + my $entry = 12 + 12 * $index; + my $noff = Get32u(\$buff, $entry + 4); # negative offset + $firstBlock = $noff if $firstBlock < $noff; + } + # save trailer position and length + my $dataPos = $$dirInfo{DataPos} = $dirPos - $firstBlock; + my $dirLen = $$dirInfo{DirLen} = $endPos - $dataPos; + if (($verbose or $$et{HTML_DUMP}) and not $outfile) { + $et->DumpTrailer($dirInfo); + return 1 if $$et{HTML_DUMP}; + } + # read through the SEFH/SEFT directory entries + for ($index=0; $index<$count; ++$index) { + my $entry = 12 + 12 * $index; + # first 2 bytes always 0 (may be part of block type) + my $type = Get16u(\$buff, $entry + 2); # block type + my $noff = Get32u(\$buff, $entry + 4); # negative offset + my $size = Get32u(\$buff, $entry + 8); # block size + last SamBlock if $noff > $dirPos or $size > $noff or $size < 8; + $firstBlock = $noff if $firstBlock < $noff; + if ($outfile) { + next unless $type == 0x0100 and not $audioNOff; + # save offset and length of first audio file for QDIO block + last unless $raf->Seek($dirPos-$noff, 0) and $raf->Read($buf2, 8) == 8; + $len = Get32u(\$buf2, 4); + $audioNOff = $noff - 8 - $len; # negative offset to start of audio data + $audioSize = $size - 8 - $len; + next; + } + # add unknown tags if necessary + my $tag = sprintf("0x%.4x", $type); + unless ($$tagTablePtr{$tag}) { + next unless $unknown or $verbose; + my %tagInfo = ( + Name => "SamsungTrailer_$tag", + Description => "Samsung Trailer $tag", + Unknown => 1, + Binary => 1, + ); + AddTagToTable($tagTablePtr, $tag, \%tagInfo); + } + unless ($$tagTablePtr{"$tag-name"}) { + my %tagInfo2 = ( + Name => "SamsungTrailer_${tag}Name", + Description => "Samsung Trailer $tag Name", + Unknown => 1, + ); + AddTagToTable($tagTablePtr, "$tag-name", \%tagInfo2); + } + last unless $raf->Seek($dirPos-$noff, 0) and $raf->Read($buf2, $size) == $size; + # (could validate the first 4 bytes of the block because they + # are the same as the first 4 bytes of the directory entry) + $len = Get32u(\$buf2, 4); + last if $len + 8 > $size; + # extract tag name and value + $et->HandleTag($tagTablePtr, "$tag-name", undef, + DataPt => \$buf2, + DataPos => $dirPos - $noff, + Start => 8, + Size => $len, + ); + $et->HandleTag($tagTablePtr, $tag, undef, + DataPt => \$buf2, + DataPos => $dirPos - $noff, + Start => 8 + $len, + Size => $size - (8 + $len), + ); + } + if ($outfile) { + last unless $raf->Seek($dataPos, 0) and $raf->Read($buff, $dirLen) == $dirLen; + # adjust the absolute offset in the QDIO block if necessary + if ($offsetPos and $audioNOff) { + # initialize the audio file start/end position in the QDIO block + my $newPos = Tell($outfile) + $dirPos - $audioNOff - $dataPos; + Set32u($newPos, \$buff, length($buff) - $offsetPos); + Set32u($newPos + $audioSize, \$buff, length($buff) - $offsetPos + 4); + # add a fixup so the calling routine can apply further shifts if necessary + require Image::ExifTool::Fixup; + my $fixup = $$dirInfo{Fixup}; + $fixup or $fixup = $$dirInfo{Fixup} = new Image::ExifTool::Fixup; + $fixup->AddFixup(length($buff) - $offsetPos); + $fixup->AddFixup(length($buff) - $offsetPos + 4); + } + $et->VPrint(0, "Writing Samsung trailer ($dirLen bytes)\n") if $verbose; + Write($$dirInfo{OutFile}, $buff) or return -1; + return 1; + } + return 1; + } + $et->Warn('Error processing Samsung trailer',1); + return 0; +} + +#------------------------------------------------------------------------------ +# Write Samsung STMN maker notes +# Inputs: 0) ExifTool object ref, 1) source dirInfo ref, 2) tag table ref +# Returns: Binary data block or undefined on error +sub WriteSTMN($$$) +{ + my ($et, $dirInfo, $tagTablePtr) = @_; + # create a Fixup for the PreviewImage + $$dirInfo{Fixup} = new Image::ExifTool::Fixup; + my $val = Image::ExifTool::WriteBinaryData($et, $dirInfo, $tagTablePtr); + # force PreviewImage into the trailer even if it fits in EXIF segment + $$et{PREVIEW_INFO}{IsTrailer} = 1 if $$et{PREVIEW_INFO}; + return $val; +} + +1; # end + +__END__ + +=head1 NAME + +Image::ExifTool::Samsung - Samsung EXIF maker notes tags + +=head1 SYNOPSIS + +This module is loaded automatically by Image::ExifTool when required. + +=head1 DESCRIPTION + +This module contains definitions required by Image::ExifTool to interpret +Samsung maker notes in EXIF information. + +=head1 AUTHOR + +Copyright 2003-2019, Phil Harvey (phil at owl.phy.queensu.ca) + +This library is free software; you can redistribute it and/or modify it +under the same terms as Perl itself. + +=head1 REFERENCES + +=over 4 + +=item L<http://www.cybercom.net/~dcoffin/dcraw/> + +=back + +=head1 ACKNOWLEDGEMENTS + +Thanks to Tae-Sun Park for decoding a number of tags, Pascal de Bruijn for +the PictureWizard values, and everyone else who helped by discovering new +Samsung information. + +=head1 SEE ALSO + +L<Image::ExifTool::TagNames/Samsung Tags>, +L<Image::ExifTool(3pm)|Image::ExifTool> + +=cut diff --git a/lib/Image/ExifTool/Sanyo.pm b/lib/Image/ExifTool/Sanyo.pm new file mode 100644 index 0000000..d7e493d --- /dev/null +++ b/lib/Image/ExifTool/Sanyo.pm @@ -0,0 +1,440 @@ +#------------------------------------------------------------------------------ +# File: Sanyo.pm +# +# Description: Sanyo EXIF maker notes tags +# +# Revisions: 04/06/2004 - P. Harvey Created +# +# Reference: http://www.exif.org/makernotes/SanyoMakerNote.html +#------------------------------------------------------------------------------ + +package Image::ExifTool::Sanyo; + +use strict; +use vars qw($VERSION); +use Image::ExifTool::Exif; + +$VERSION = '1.16'; + +my %offOn = ( + 0 => 'Off', + 1 => 'On', +); + +%Image::ExifTool::Sanyo::Main = ( + WRITE_PROC => \&Image::ExifTool::Exif::WriteExif, + CHECK_PROC => \&Image::ExifTool::Exif::CheckExif, + WRITABLE => 1, + GROUPS => { 0 => 'MakerNotes', 2 => 'Camera' }, + 0x00ff => { + # this is an absolute offset in the JPG file... odd - PH + Name => 'MakerNoteOffset', + Writable => 'int32u', + }, + 0x0100 => { + Name => 'SanyoThumbnail', + Groups => { 2 => 'Preview' }, + Writable => 'undef', + WriteCheck => '$self->CheckImage(\$val)', + RawConv => '$self->ValidateImage(\$val,$tag)', + }, + 0x0200 => { + Name => 'SpecialMode', + Writable => 'int32u', + Count => 3, + }, + 0x0201 => { + Name => 'SanyoQuality', + Flags => 'PrintHex', + Writable => 'int16u', + PrintConv => { + 0x0000 => 'Normal/Very Low', + 0x0001 => 'Normal/Low', + 0x0002 => 'Normal/Medium Low', + 0x0003 => 'Normal/Medium', + 0x0004 => 'Normal/Medium High', + 0x0005 => 'Normal/High', + 0x0006 => 'Normal/Very High', + 0x0007 => 'Normal/Super High', + # have seen 0x11 with HD2000 in '8M-H JPEG' mode - PH + 0x0100 => 'Fine/Very Low', + 0x0101 => 'Fine/Low', + 0x0102 => 'Fine/Medium Low', + 0x0103 => 'Fine/Medium', + 0x0104 => 'Fine/Medium High', + 0x0105 => 'Fine/High', + 0x0106 => 'Fine/Very High', + 0x0107 => 'Fine/Super High', + 0x0200 => 'Super Fine/Very Low', + 0x0201 => 'Super Fine/Low', + 0x0202 => 'Super Fine/Medium Low', + 0x0203 => 'Super Fine/Medium', + 0x0204 => 'Super Fine/Medium High', + 0x0205 => 'Super Fine/High', + 0x0206 => 'Super Fine/Very High', + 0x0207 => 'Super Fine/Super High', + }, + }, + 0x0202 => { + Name => 'Macro', + Writable => 'int16u', + PrintConv => { + 0 => 'Normal', + 1 => 'Macro', + 2 => 'View', + 3 => 'Manual', + }, + }, + 0x0204 => { + Name => 'DigitalZoom', + Writable => 'rational64u', + }, + 0x0207 => 'SoftwareVersion', + 0x0208 => 'PictInfo', + 0x0209 => 'CameraID', + 0x020e => { + Name => 'SequentialShot', + Writable => 'int16u', + PrintConv => { + 0 => 'None', + 1 => 'Standard', + 2 => 'Best', + 3 => 'Adjust Exposure', + }, + }, + 0x020f => { + Name => 'WideRange', + Writable => 'int16u', + PrintConv => \%offOn, + }, + 0x0210 => { + Name => 'ColorAdjustmentMode', + Writable => 'int16u', + PrintConv => \%offOn, + }, + 0x0213 => { + Name => 'QuickShot', + Writable => 'int16u', + PrintConv => \%offOn, + }, + 0x0214 => { + Name => 'SelfTimer', + Writable => 'int16u', + PrintConv => \%offOn, + }, + # 0x0215 - Flash? + 0x0216 => { + Name => 'VoiceMemo', + Writable => 'int16u', + PrintConv => \%offOn, + }, + 0x0217 => { + Name => 'RecordShutterRelease', + Writable => 'int16u', + PrintConv => { + 0 => 'Record while down', + 1 => 'Press start, press stop', + }, + }, + 0x0218 => { + Name => 'FlickerReduce', + Writable => 'int16u', + PrintConv => \%offOn, + }, + 0x0219 => { + Name => 'OpticalZoomOn', + Writable => 'int16u', + PrintConv => \%offOn, + }, + 0x021b => { + Name => 'DigitalZoomOn', + Writable => 'int16u', + PrintConv => \%offOn, + }, + 0x021d => { + Name => 'LightSourceSpecial', + Writable => 'int16u', + PrintConv => \%offOn, + }, + 0x021e => { + Name => 'Resaved', + Writable => 'int16u', + PrintConv => { + 0 => 'No', + 1 => 'Yes', + }, + }, + 0x021f => { + Name => 'SceneSelect', + Writable => 'int16u', + PrintConv => { + 0 => 'Off', + 1 => 'Sport', + 2 => 'TV', + 3 => 'Night', + 4 => 'User 1', + 5 => 'User 2', + 6 => 'Lamp', #PH + }, + }, + 0x0223 => [ + { + Name => 'ManualFocusDistance', + Condition => '$format eq "rational64u"', + Writable => 'rational64u', + }, { #PH + Name => 'FaceInfo', + SubDirectory => { TagTable => 'Image::ExifTool::Sanyo::FaceInfo' }, + }, + ], + 0x0224 => { + Name => 'SequenceShotInterval', + Writable => 'int16u', + PrintConv => { + 0 => '5 frames/s', + 1 => '10 frames/s', + 2 => '15 frames/s', + 3 => '20 frames/s', + }, + }, + 0x0225 => { + Name => 'FlashMode', + Writable => 'int16u', + PrintConv => { + 0 => 'Auto', + 1 => 'Force', + 2 => 'Disabled', + 3 => 'Red eye', + }, + }, + 0x0e00 => { + Name => 'PrintIM', + Description => 'Print Image Matching', + Writable => 0, + SubDirectory => { + TagTable => 'Image::ExifTool::PrintIM::Main', + }, + }, + 0x0f00 => { + Name => 'DataDump', + Writable => 0, + Binary => 1, + }, +); + +# face detection information (ref PH) +%Image::ExifTool::Sanyo::FaceInfo = ( + PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData, + WRITE_PROC => \&Image::ExifTool::WriteBinaryData, + CHECK_PROC => \&Image::ExifTool::CheckBinaryData, + GROUPS => { 0 => 'MakerNotes', 2 => 'Image' }, + WRITABLE => 1, + FORMAT => 'int32u', + FIRST_ENTRY => 0, + 0 => 'FacesDetected', + 4 => { + Name => 'FacePosition', + Format => 'int32u[4]', + Notes => q{ + left, top, right and bottom coordinates of detected face in an unrotated + 640-pixel-wide image, with increasing Y downwards + }, + }, +); + +# tags in Sanyo MOV videos (PH - observations from an E6 sample) +# (similar information in Kodak,Minolta,Nikon,Olympus,Pentax and Sanyo videos) +%Image::ExifTool::Sanyo::MOV = ( + PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData, + GROUPS => { 0 => 'MakerNotes', 2 => 'Camera' }, + NOTES => 'This information is found in Sanyo MOV videos.', + 0x00 => { + Name => 'Make', + Format => 'string[24]', + }, + 0x18 => { + Name => 'Model', + Description => 'Camera Model Name', + Format => 'string[8]', + }, + # (01 00 at offset 0x20) + 0x26 => { + Name => 'ExposureTime', + Format => 'int32u', + ValueConv => '$val ? 10 / $val : 0', + PrintConv => 'Image::ExifTool::Exif::PrintExposureTime($val)', + }, + 0x2a => { + Name => 'FNumber', + Format => 'int32u', + ValueConv => '$val / 10', + PrintConv => 'sprintf("%.1f",$val)', + }, + 0x32 => { + Name => 'ExposureCompensation', + Format => 'int32s', + ValueConv => '$val / 10', + PrintConv => 'Image::ExifTool::Exif::PrintFraction($val)', + }, + 0x44 => { + Name => 'WhiteBalance', + Format => 'int16u', + PrintConv => { + 0 => 'Auto', + 1 => 'Daylight', + 2 => 'Shade', + 3 => 'Fluorescent', #2 + 4 => 'Tungsten', + 5 => 'Manual', + }, + }, + 0x48 => { + Name => 'FocalLength', + Format => 'int32u', + ValueConv => '$val / 10', + PrintConv => 'sprintf("%.1f mm",$val)', + }, +); + +# tags in Sanyo MP4 videos (PH - from C4, C5 and HD1A samples) +# --> very similar to Samsung MP4 information +# (there is still a lot more information here that could be decoded!) +%Image::ExifTool::Sanyo::MP4 = ( + PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData, + GROUPS => { 0 => 'MakerNotes', 2 => 'Camera' }, + NOTES => 'This information is found in Sanyo MP4 videos.', + 0x00 => { + Name => 'Make', + Format => 'string[5]', + PrintConv => 'ucfirst(lc($val))', + }, + 0x18 => { + Name => 'Model', + Description => 'Camera Model Name', + Format => 'string[8]', + }, + # (01 00 at offset 0x28) + # (0x2e has values 0x31, 0x33 and 0x3c in my samples, but + # some of the shutter speeds should be around 1/500 or so) + 0x32 => { + Name => 'FNumber', + Format => 'rational64u', + PrintConv => 'sprintf("%.1f",$val)', + }, + 0x3a => { # (NC) + Name => 'ExposureCompensation', + Format => 'rational64s', + PrintConv => '$val ? sprintf("%+.1f", $val) : 0', + }, + 0x6a => { + Name => 'ISO', + Format => 'int32u', + }, + 0xd1 => { + Name => 'Software', + Notes => 'these tags are shifted up by 1 byte for some models like the HD1A', + Format => 'undef[32]', + RawConv => q{ + $val =~ /^SANYO/ or return undef; + $val =~ tr/\0//d; + $$self{SanyoSledder0xd1} = 1; + return $val; + }, + }, + 0xd2 => { + Name => 'Software', + Format => 'undef[32]', + RawConv => q{ + $val =~ /^SANYO/ or return undef; + $val =~ tr/\0//d; + $$self{SanyoSledder0xd2} = 1; + return $val; + }, + }, + 0xf1 => { + Name => 'Thumbnail', + Condition => '$$self{SanyoSledder0xd1}', + SubDirectory => { + TagTable => 'Image::ExifTool::Sanyo::Thumbnail', + Base => '$start', + }, + }, + 0xf2 => { + Name => 'Thumbnail', + Condition => '$$self{SanyoSledder0xd2}', + SubDirectory => { + TagTable => 'Image::ExifTool::Sanyo::Thumbnail', + Base => '$start', + }, + }, +); + +# thumbnail image information found in MP4 videos (similar in Olympus,Samsung,Sanyo) +%Image::ExifTool::Sanyo::Thumbnail = ( + PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData, + GROUPS => { 0 => 'MakerNotes', 2 => 'Camera' }, + FIRST_ENTRY => 0, + FORMAT => 'int32u', + 1 => 'ThumbnailWidth', + 2 => 'ThumbnailHeight', + 3 => 'ThumbnailLength', + 4 => { Name => 'ThumbnailOffset', IsOffset => 1 }, +); + + +#------------------------------------------------------------------------------ +# Patch incorrect offsets in J1, J2, J4, S1, S3 and S4 maker notes +# Inputs: 0) valuePtr, 1) end of previous value, 2) value size, 3) tag ID, 4) write flag +sub FixOffsets($$$$;$) +{ + my ($valuePtr, $valEnd, $size, $tagID, $wFlag) = @_; + # ignore existing offsets and calculate reasonable values instead + if ($tagID == 0x100) { + # just ignore the SanyoThumbnail when writing (pointer is garbage) + $_[0] = undef if $wFlag; + } else { + $_[0] = $valEnd; # set value pointer to next logical location + ++$size if $size & 0x01; + $_[1] += $size; # update end-of-value pointer + } +} + + +1; # end + +__END__ + +=head1 NAME + +Image::ExifTool::Sanyo - Sanyo EXIF maker notes tags + +=head1 SYNOPSIS + +This module is loaded automatically by Image::ExifTool when required. + +=head1 DESCRIPTION + +This module contains definitions required by Image::ExifTool to interpret +Sanyo maker notes in EXIF information. + +=head1 AUTHOR + +Copyright 2003-2019, Phil Harvey (phil at owl.phy.queensu.ca) + +This library is free software; you can redistribute it and/or modify it +under the same terms as Perl itself. + +=head1 REFERENCES + +=over 4 + +=item L<http://www.exif.org/makernotes/SanyoMakerNote.html> + +=back + +=head1 SEE ALSO + +L<Image::ExifTool::TagNames/Sanyo Tags>, +L<Image::ExifTool(3pm)|Image::ExifTool> + +=cut diff --git a/lib/Image/ExifTool/Scalado.pm b/lib/Image/ExifTool/Scalado.pm new file mode 100644 index 0000000..b9fd587 --- /dev/null +++ b/lib/Image/ExifTool/Scalado.pm @@ -0,0 +1,141 @@ +#------------------------------------------------------------------------------ +# File: Scalado.pm +# +# Description: Read APP4 SCALADO metadata +# +# Revisions: 2013-09-13 - P. Harvey Created +#------------------------------------------------------------------------------ + +package Image::ExifTool::Scalado; + +use strict; +use vars qw($VERSION); +use Image::ExifTool qw(:DataAccess :Utils); +use Image::ExifTool::PLIST; + +$VERSION = '1.01'; + +sub ProcessScalado($$$); + +# JPEG APP4 SCALADO tags +%Image::ExifTool::Scalado::Main = ( + GROUPS => { 0 => 'APP4', 1 => 'Scalado', 2 => 'Image' }, + PROCESS_PROC => \&ProcessScalado, + TAG_PREFIX => 'Scalado', + FORMAT => 'int32s', + NOTES => q{ + Tags extracted from the JPEG APP4 "SCALADO" segment found in images from + HTC, LG and Samsung phones. (Presumably written by Scalado mobile software, + L<http://www.scalado.com/>.) + }, + SPMO => { + Name => 'DataLength', + Unknown => 1, + }, + WDTH => { + Name => 'PreviewImageWidth', + ValueConv => '$val ? abs($val) : undef', + }, + HGHT => { + Name => 'PreviewImageHeight', + ValueConv => '$val ? abs($val) : undef', + }, + QUAL => { + Name => 'PreviewQuality', + ValueConv => '$val ? abs($val) : undef', + }, + # tags not yet decoded with observed values: + # CHKH: 0, various negative values + # CHKL: various negative values + # CLEN: -1024 + # CSPC: -2232593 + # DATA: (+ve data length) + # HDEC: 0 + # MAIN: 0, 60 + # META: 24 + # SCI0: (+ve data length) often 36 + # SCI1: (+ve data length) 36 + # SCX0: (+ve data length) + # SCX1: (+ve data length) often 84 + # WDEC: 0 + # VERS: -131328 +); + +#------------------------------------------------------------------------------ +# Extract information from the JPEG APP4 SCALADO segment +# Inputs: 0) ExifTool object ref, 1) dirInfo ref, 2) tag table ref +# Returns: 1 on success +sub ProcessScalado($$$) +{ + my ($et, $dirInfo, $tagTablePtr) = @_; + my $dataPt = $$dirInfo{DataPt}; + my $pos = 0; + my $end = length $$dataPt; + my $unknown = $et->Options('Unknown'); + + $et->VerboseDir('APP4 SCALADO', undef, $end); + SetByteOrder('MM'); + + for (;;) { + last if $pos + 12 > $end; + my $tag = substr($$dataPt, $pos, 4); + my $ver = Get32u($dataPt, $pos + 4); # (looks like a version for some tags) + if (not $$tagTablePtr{$tag} and $unknown) { + my $name = $tag; + $name =~ tr/-A-Za-z0-9_//dc; + last unless length $name; # stop if tag is garbage + AddTagToTable($tagTablePtr, $tag, { + Name => "Scalado_$name", + Description => "Scalado $name", + Unknown => 1, + }); + } + $et->HandleTag($tagTablePtr, $tag, undef, + DataPt => $dataPt, + Start => $pos + 8, + Size => 4, + Extra => ", ver $ver", + ); + if ($tag eq 'SPMO') { + my $val = Get32u($dataPt, $pos + 8) ; + if ($ver < 5) { # (I don't have samples for version 3 or 4, so I'm not sure about these) + $end -= $val; # SPMO gives trailer data length + } else { + $end = $val + 12; # SPMO gives length of Scalado directory (excepting this entry) + } + } + $pos += 12; + } + return 1; +} + +1; # end + +__END__ + +=head1 NAME + +Image::ExifTool::Scalado - Read APP4 SCALADO metadata + +=head1 SYNOPSIS + +This module is loaded automatically by Image::ExifTool when required. + +=head1 DESCRIPTION + +This module contains definitions required by Image::ExifTool to read +metadata from the JPEG APP4 SCALADO segment. + +=head1 AUTHOR + +Copyright 2003-2019, Phil Harvey (phil at owl.phy.queensu.ca) + +This library is free software; you can redistribute it and/or modify it +under the same terms as Perl itself. + +=head1 SEE ALSO + +L<Image::ExifTool::TagNames/Scalado Tags>, +L<Image::ExifTool(3pm)|Image::ExifTool> + +=cut diff --git a/lib/Image/ExifTool/Shift.pl b/lib/Image/ExifTool/Shift.pl new file mode 100644 index 0000000..07f5d91 --- /dev/null +++ b/lib/Image/ExifTool/Shift.pl @@ -0,0 +1,625 @@ +#------------------------------------------------------------------------------ +# File: Shift.pl +# +# Description: ExifTool time shifting routines +# +# Revisions: 10/28/2005 - P. Harvey Created +#------------------------------------------------------------------------------ + +package Image::ExifTool; + +use strict; + +sub ShiftTime($$;$$); + +#------------------------------------------------------------------------------ +# apply shift to value in new value hash +# Inputs: 0) ExifTool ref, 1) shift type, 2) shift string, 3) raw date/time value, +# 4) new value hash ref +# Returns: error string or undef on success and updates value in new value hash +sub ApplyShift($$$$;$) +{ + my ($self, $func, $shift, $val, $nvHash) = @_; + + # get shift direction from first character in shift string + my $pre = ($shift =~ s/^(\+|-)//) ? $1 : '+'; + my $dir = ($pre eq '+') ? 1 : -1; + my $tagInfo = $$nvHash{TagInfo}; + my $tag = $$tagInfo{Name}; + my $shiftOffset; + if ($$nvHash{ShiftOffset}) { + $shiftOffset = $$nvHash{ShiftOffset}; + } else { + $shiftOffset = $$nvHash{ShiftOffset} = { }; + } + + # initialize handler for eval warnings + local $SIG{'__WARN__'} = \&SetWarning; + SetWarning(undef); + + # shift is applied to ValueConv value, so we must ValueConv-Shift-ValueConvInv + my ($type, $err); + foreach $type ('ValueConv','Shift','ValueConvInv') { + if ($type eq 'Shift') { + #### eval ShiftXxx function + $err = eval "Shift$func(\$val, \$shift, \$dir, \$shiftOffset)"; + } elsif ($$tagInfo{$type}) { + my $conv = $$tagInfo{$type}; + if (ref $conv eq 'CODE') { + $val = &$conv($val, $self); + } else { + return "Can't handle $type for $tag in ApplyShift()" if ref $$tagInfo{$type}; + #### eval ValueConv/ValueConvInv ($val, $self) + $val = eval $$tagInfo{$type}; + } + } else { + next; + } + # handle errors + $err and return $err; + $@ and SetWarning($@); + GetWarning() and return CleanWarning(); + } + # update value in new value hash + $nvHash->{Value} = [ $val ]; + return undef; # success +} + +#------------------------------------------------------------------------------ +# Check date/time shift +# Inputs: 0) shift type, 1) shift string (without sign) +# Returns: updated shift string, or undef on error (and may update shift) +sub CheckShift($$) +{ + my ($type, $shift) = @_; + my $err; + if ($type eq 'Time') { + return "No shift direction" unless $shift =~ s/^(\+|-)//; + # do a test shift to validate the shift string + my $testTime = '2005:11:02 09:00:13.25-04:00'; + $err = ShiftTime($testTime, $shift, $1 eq '+' ? 1 : -1); + } else { + $err = "Unknown shift type ($type)"; + } + return $err; +} + +#------------------------------------------------------------------------------ +# return the number of days in a month +# Inputs: 0) month number (Jan=1, may be outside range), 1) year +# Returns: number of days in month +sub DaysInMonth($$) +{ + my ($mon, $year) = @_; + my @days = (31,28,31,30,31,30,31,31,30,31,30,31); + # adjust to the range [0,11] + while ($mon < 1) { $mon += 12; --$year; } + while ($mon > 12) { $mon -= 12; ++$year; } + # return standard number of days unless february on a leap year + return $days[$mon-1] unless $mon == 2 and not $year % 4; + # leap years don't occur on even centuries except every 400 years + return 29 if $year % 100 or not $year % 400; + return 28; +} + +#------------------------------------------------------------------------------ +# split times into corresponding components: YYYY mm dd HH MM SS tzh tzm +# Inputs: 0) date/time or shift string 1) reference to list for returned components +# 2) optional reference to list of time components (if shift string) +# Returns: true on success +# Returned components are 0-Y, 1-M, 2-D, 3-hr, 4-min, 5-sec, 6-tzhr, 7-tzmin +sub SplitTime($$;$) +{ + my ($val, $vals, $time) = @_; + # insert zeros if missing in shift string + if ($time) { + $val =~ s/(^|[-+:\s]):/${1}0:/g; + $val =~ s/:([:\s]|$)/:0$1/g; + } + # change dashes to colons in date (for XMP dates) + if ($val =~ s/^(\d{4})-(\d{2})-(\d{2})/$1:$2:$3/) { + $val =~ tr/T/ /; # change 'T' separator to ' ' + } + # add space before timezone to split it into a separate word + $val =~ s/(\+|-)/ $1/; + my @words = split ' ', $val; + my $err = 1; + my @v; + for (;;) { + my $word = shift @words; + last unless defined $word; + # split word into separate numbers (allow decimal points but no signs) + my @vals = $word =~ /(?=\d|\.\d)\d*(?:\.\d*)?/g or last; + if ($word =~ /^(\+|-)/) { + # this is the timezone + (defined $v[6] or @vals > 2) and $err = 1, last; + my $sign = ($1 ne '-') ? 1 : -1; + # apply sign to both minutes and seconds + $v[6] = $sign * shift(@vals); + $v[7] = $sign * (shift(@vals) || 0); + } elsif ((@words and $words[0] =~ /^\d+/) or # there is a time word to follow + (not $time and $vals[0] =~ /^\d{3}/) or # first value is year (3 or more digits) + ($time and not defined $$time[3] and not defined $v[0])) # we don't have a time + { + # this is a date (must come first) + (@v or @vals > 3) and $err = 1, last; + not $time and @vals != 3 and $err = 1, last; + $v[2] = pop(@vals); # take day first if only one specified + $v[1] = pop(@vals) || 0; + $v[0] = pop(@vals) || 0; + } else { + # this is a time (can't come after timezone) + (defined $v[3] or defined $v[6] or @vals > 3) and $err = 1, last; + not $time and @vals != 3 and @vals != 2 and $err = 1, last; + $v[3] = shift(@vals); # take hour first if only one specified + $v[4] = shift(@vals) || 0; + $v[5] = shift(@vals) || 0; + } + $err = 0; + } + return 0 if $err or not @v; + if ($time) { + # zero any required shift entries which aren't yet defined + $v[0] = $v[1] = $v[2] = 0 if defined $$time[0] and not defined $v[0]; + $v[3] = $v[4] = $v[5] = 0 if defined $$time[3] and not defined $v[3]; + $v[6] = $v[7] = 0 if defined $$time[6] and not defined $v[6]; + } + @$vals = @v; # return split time components + return 1; +} + +#------------------------------------------------------------------------------ +# shift date/time by components +# Inputs: 0) split date/time list ref, 1) split shift list ref, +# 2) shift direction, 3) reference to output list of shifted components +# 4) number of decimal points in seconds +# 5) reference to return time difference due to rounding +# Returns: error string or undef on success +sub ShiftComponents($$$$$;$) +{ + my ($time, $shift, $dir, $toTime, $dec, $rndPt) = @_; + # min/max for Y, M, D, h, m, s + my @min = ( 0, 1, 1, 0, 0, 0); + my @max = (10000,12,28,24,60,60); + my $i; +# +# apply the shift +# + my $c = 0; + for ($i=0; $i<@$time; ++$i) { + my $v = ($$time[$i] || 0) + $dir * ($$shift[$i] || 0) + $c; + # handle fractional values by propagating remainders downwards + if ($v != int($v) and $i < 5) { + my $iv = int($v); + $c = ($v - $iv) * $max[$i+1]; + $v = $iv; + } else { + $c = 0; + } + $$toTime[$i] = $v; + } + # round off seconds to the required number of decimal points + my $sec = $$toTime[5]; + if (defined $sec and $sec != int($sec)) { + my $mult = 10 ** $dec; + my $rndSec = int($sec * $mult + 0.5 * ($sec <=> 0)) / $mult; + $rndPt and $$rndPt = $sec - $rndSec; + $$toTime[5] = $rndSec; + } +# +# handle overflows, starting with least significant number first (seconds) +# + $c = 0; + for ($i=5; $i>=0; $i--) { + defined $$time[$i] or $c = 0, next; + # apply shift and adjust for previous overflow + my $v = $$toTime[$i] + $c; + $c = 0; # set carry to zero + # adjust for over/underflow + my ($min, $max) = ($min[$i], $max[$i]); + if ($v < $min) { + if ($i == 2) { # 2 = day of month + do { + # add number of days in previous month + --$c; + my $mon = $$toTime[$i-1] + $c; + $v += DaysInMonth($mon, $$toTime[$i-2]); + } while ($v < 1); + } else { + my $fc = ($v - $min) / $max; + # carry ($c) must be largest integer equal to or less than $fc + $c = int($fc); + --$c if $c > $fc; + $v -= $c * $max; + } + } elsif ($v >= $max + $min) { + if ($i == 2) { + for (;;) { + # test against number of days in current month + my $mon = $$toTime[$i-1] + $c; + my $days = DaysInMonth($mon, $$toTime[$i-2]); + last if $v <= $days; + $v -= $days; + ++$c; + last if $v <= 28; + } + } else { + my $fc = ($v - $max - $min) / $max; + # carry ($c) must be smallest integer greater than $fc + $c = int($fc); + ++$c if $c <= $fc; + $v -= $c * $max; + } + } + $$toTime[$i] = $v; # save the new value + } + # handle overflows in timezone + if (defined $$toTime[6]) { + my $m = $$toTime[6] * 60 + $$toTime[7]; + $m += 0.5 * ($m <=> 0); # avoid round-off errors + $$toTime[6] = int($m / 60); + $$toTime[7] = int($m - $$toTime[6] * 60); + } + return undef; # success +} + +#------------------------------------------------------------------------------ +# Shift an integer or floating-point number +# Inputs: 0) date/time string, 1) shift string, 2) shift direction (+1 or -1) +# 3) (unused) +# Returns: undef and updates input value +sub ShiftNumber($$$;$) +{ + my ($val, $shift, $dir) = @_; + $_[0] = $val + $shift * $dir; # return shifted value + return undef; # success! +} + +#------------------------------------------------------------------------------ +# Shift date/time string +# Inputs: 0) date/time string, 1) shift string, 2) shift direction (+1 or -1), +# or 0 or undef to take shift direction from sign of shift, +# 3) reference to ShiftOffset hash (with Date, DateTime, Time, Timezone keys) +# Returns: error string or undef on success and date/time string is updated +sub ShiftTime($$;$$) +{ + local $_; + my ($val, $shift, $dir, $shiftOffset) = @_; + my (@time, @shift, @toTime, $mode, $needShiftOffset, $dec); + $dir or $dir = ($shift =~ s/^(\+|-)// and $1 eq '-') ? -1 : 1; +# +# figure out what we are dealing with (time, date or date/time) +# + SplitTime($val, \@time) or return "Invalid time string ($val)"; + if (defined $time[0]) { + $mode = defined $time[3] ? 'DateTime' : 'Date'; + } elsif (defined $time[3]) { + $mode = 'Time'; + } + # get number of digits after the seconds decimal point + if (defined $time[5] and $time[5] =~ /\.(\d+)/) { + $dec = length($1); + } else { + $dec = 0; + } + if ($shiftOffset) { + $needShiftOffset = 1 unless defined $$shiftOffset{$mode}; + $needShiftOffset = 1 if defined $time[6] and not defined $$shiftOffset{Timezone}; + } else { + $needShiftOffset = 1; + } + if ($needShiftOffset) { +# +# apply date/time shift the hard way +# + SplitTime($shift, \@shift, \@time) or return "Invalid shift string ($shift)"; + + # change 'Z' timezone to '+00:00' only if necessary + if (@shift > 6 and @time <= 6) { + $time[6] = $time[7] = 0 if $val =~ s/Z$/\+00:00/; + } + my $rndDiff; + my $err = ShiftComponents(\@time, \@shift, $dir, \@toTime, $dec, \$rndDiff); + $err and return $err; +# +# calculate and save the shift offsets for next time +# + if ($shiftOffset) { + if (defined $time[0] or defined $time[3]) { + my @tm1 = (0, 0, 0, 1, 0, 2000); + my @tm2 = (0, 0, 0, 1, 0, 2000); + if (defined $time[0]) { + @tm1[3..5] = reverse @time[0..2]; + @tm2[3..5] = reverse @toTime[0..2]; + --$tm1[4]; # month should start from 0 + --$tm2[4]; + } + my $diff = 0; + if (defined $time[3]) { + @tm1[0..2] = reverse @time[3..5]; + @tm2[0..2] = reverse @toTime[3..5]; + # handle fractional seconds separately + $diff = $tm2[0] - int($tm2[0]) - ($tm1[0] - int($tm1[0])); + $diff += $rndDiff if defined $rndDiff; # un-do rounding + $tm1[0] = int($tm1[0]); + $tm2[0] = int($tm2[0]); + } + eval q{ + require Time::Local; + $diff += Time::Local::timegm(@tm2) - Time::Local::timegm(@tm1); + }; + # not a problem if we failed here since we'll just try again next time, + # so don't return error message + unless (@$) { + my $mode; + if (defined $time[0]) { + $mode = defined $time[3] ? 'DateTime' : 'Date'; + } else { + $mode = 'Time'; + } + $$shiftOffset{$mode} = $diff; + } + } + if (defined $time[6]) { + $$shiftOffset{Timezone} = ($toTime[6] - $time[6]) * 60 + + $toTime[7] - $time[7]; + } + } + + } else { +# +# apply shift from previously calculated offsets +# + if ($$shiftOffset{Timezone} and @time <= 6) { + # change 'Z' timezone to '+00:00' only if necessary + $time[6] = $time[7] = 0 if $val =~ s/Z$/\+00:00/; + } + # apply the previous date/time shift if necessary + if ($mode) { + my @tm = (0, 0, 0, 1, 0, 2000); + if (defined $time[0]) { + @tm[3..5] = reverse @time[0..2]; + --$tm[4]; # month should start from 0 + } + @tm[0..2] = reverse @time[3..5] if defined $time[3]; + # save fractional seconds + my $frac = $tm[0] - int($tm[0]); + $tm[0] = int($tm[0]); + my $tm; + eval q{ + require Time::Local; + $tm = Time::Local::timegm(@tm) + $frac; + }; + $@ and return CleanWarning($@); + $tm += $$shiftOffset{$mode}; # apply the shift + $tm < 0 and return 'Shift results in negative time'; + # save fractional seconds in shifted time + $frac = $tm - int($tm); + if ($frac) { + $tm = int($tm); + # must account for any rounding that could occur + $frac + 0.5 * 10 ** (-$dec) >= 1 and ++$tm, $frac = 0; + } + @tm = gmtime($tm); + @toTime = reverse @tm[0..5]; + $toTime[0] += 1900; + ++$toTime[1]; + $toTime[5] += $frac; # add the fractional seconds back in + } + # apply the previous timezone shift if necessary + if (defined $time[6]) { + my $m = $time[6] * 60 + $time[7]; + $m += $$shiftOffset{Timezone}; + $m += 0.5 * ($m <=> 0); # avoid round-off errors + $toTime[6] = int($m / 60); + $toTime[7] = int($m - $toTime[6] * 60); + } + } +# +# insert shifted time components back into original string +# + my $i; + for ($i=0; $i<@toTime; ++$i) { + next unless defined $time[$i] and defined $toTime[$i]; + my ($v, $d, $s); + if ($i != 6) { # not timezone hours + last unless $val =~ /((?=\d|\.\d)\d*(\.\d*)?)/g; + next if $toTime[$i] == $time[$i]; + $v = $1; # value + $d = $2; # decimal part of value + $s = ''; # no sign + } else { + last if $time[$i] == $toTime[$i] and $time[$i+1] == $toTime[$i+1]; + last unless $val =~ /((?:\+|-)(?=\d|\.\d)\d*(\.\d*)?)/g; + $v = $1; + $d = $2; + if ($toTime[6] >= 0 and $toTime[7] >= 0) { + $s = '+'; + } else { + $s = '-'; + $toTime[6] = -$toTime[6]; + $toTime[7] = -$toTime[7]; + } + } + my $nv = $toTime[$i]; + my $pos = pos $val; + my $len = length $v; + my $sig = $len - length $s; + my $dec = $d ? length($d) - 1 : 0; + my $newNum = sprintf($dec ? "$s%0$sig.${dec}f" : "$s%0${sig}d", $nv); + substr($val, $pos - $len, $len) = $newNum; + pos($val) = $pos + length($newNum) - $len; + } + $_[0] = $val; # return shifted value + return undef; # success! +} + + +1; # end + +__END__ + +=head1 NAME + +Image::ExifTool::Shift.pl - ExifTool time shifting routines + +=head1 DESCRIPTION + +This module contains routines used by ExifTool to shift date and time +values. + +=head1 METHODS + +=head2 ShiftTime + +Shift date/time value + + use Image::ExifTool; + $err = Image::ExifTool::ShiftTime($dateTime, $shift); + +=over 4 + +=item Inputs: + +0) Date/time string in EXIF format (eg. C<2016:01:30 11:45:00>). + +1) Shift string (see below) with optional leading sign for shift direction. + +2) [optional] Direction of shift (-1 or +1), or 0 or undef to use the sign +from the shift string. + +3) [optional] Reference to time-shift hash -- filled in by first call to +B<ShiftTime>, and used in subsequent calls to shift date/time values by the +same relative amount (see L</TRICKY> section below). + +=item Return value: + +Error string, or undef on success and the input date/time string is shifted +by the specified amount. + +=back + +=head1 SHIFT STRING + +Time shifts are applied to standard EXIF-formatted date/time values (eg. +C<2005:03:14 18:55:00>). Date-only and time-only values may also be +shifted, and an optional timezone (eg. C<-05:00>) is also supported. Here +are some general rules and examples to explain how shift strings are +interpreted: + +Date-only values are shifted using the following formats: + + 'Y:M:D' - shift date by 'Y' years, 'M' months and 'D' days + 'M:D' - shift months and days only + 'D' - shift specified number of days + +Time-only values are shifted using the following formats: + + 'h:m:s' - shift time by 'h' hours, 'm' minutes and 's' seconds + 'h:m' - shift hours and minutes only + 'h' - shift specified number of hours + +Timezone shifts are specified in the following formats: + + '+h:m' - shift timezone by 'h' hours and 'm' minutes + '-h:m' - negative shift of timezone hours and minutes + '+h' - shift timezone hours only + '-h' - negative shift of timezone hours only + +A valid shift value consists of one or two arguments, separated by a space. +If only one is provided, it is assumed to be a time shift when applied to a +time-only or a date/time value, or a date shift when applied to a date-only +value. For example: + + '1' - shift by 1 hour if applied to a time or date/time + value, or by one day if applied to a date value + '2:0' - shift 2 hours (time, date/time), or 2 months (date) + '5:0:0' - shift 5 hours (time, date/time), or 5 years (date) + '0:0:1' - shift 1 s (time, date/time), or 1 day (date) + +If two arguments are given, the date shift is first, followed by the time +shift: + + '3:0:0 0' - shift date by 3 years + '0 15:30' - shift time by 15 hours and 30 minutes + '1:0:0 0:0:0+5:0' - shift date by 1 year and timezone by 5 hours + +A date shift is simply ignored if applied to a time value or visa versa. + +Numbers specified in shift fields may contain a decimal point: + + '1.5' - 1 hour 30 minutes (time, date/time), or 1 day (date) + '2.5 0' - 2 days 12 hours (date/time), 12 hours (time) or + 2 days (date) + +And to save typing, a zero is assumed for any missing numbers: + + '1::' - shift by 1 hour (time, date/time) or 1 year (date) + '26:: 0' - shift date by 26 years + '+:30' - shift timezone by 30 minutes + +Below are some specific examples applied to real date and/or time values +('Dir' is the applied shift direction: '+' is positive, '-' is negative): + + Original Value Shift Dir Shifted Value + --------------------- ------- --- --------------------- + '20:30:00' '5' + '01:30:00' + '2005:01:27' '5' + '2005:02:01' + '2005:01:27 20:30:00' '5' + '2005:01:28 01:30:00' + '11:54:00' '2.5 0' - '23:54:00' + '2005:11:02' '2.5 0' - '2005:10:31' + '2005:11:02 11:54:00' '2.5 0' - '2005:10:30 23:54:00' + '2004:02:28 08:00:00' '1 1.3' + '2004:02:29 09:18:00' + '07:00:00' '-5' + '07:00:00' + '07:00:00+01:00' '-5' + '07:00:00-04:00' + '07:00:00Z' '+2:30' - '07:00:00-02:30' + '1970:01:01' '35::' + '2005:01:01' + '2005:01:01' '400' + '2006:02:05' + '10:00:00.00' '::1.33' - '09:59:58.67' + +=head1 NOTES + +The format of the original date/time value is not changed when the time +shift is applied. This means that the length of the date/time string will +not change, and only the numbers in the string will be modified. The only +exception to this rule is that a 'Z' timezone is changed to '+00:00' +notation if a timezone shift is applied. A timezone will not be added to +the date/time string. + +=head1 TRICKY + +This module is perhaps more complicated than it needs to be because it is +designed to be very flexible in the way time shifts are specified and +applied... + +The ability to shift dates by Y years, M months, etc, conflicts with the +design goal of maintaining a constant shift for all time values when +applying a batch shift. This is because shifting by 1 month can be +equivalent to anything from 28 to 31 days, and 1 year can be 365 or 366 +days, depending on the starting date. + +The inconsistency is handled by shifting the first tag found with the actual +specified shift, then calculating the equivalent time difference in seconds +for this shift and applying this difference to subsequent tags in a batch +conversion. So if it works as designed, the behaviour should be both +intuitive and mathematically correct, and the user shouldn't have to worry +about details such as this (in keeping with Perl's "do the right thing" +philosophy). + +=head1 BUGS + +Due to the use of the standard time library functions, dates are typically +limited to the range 1970 to 2038 on 32-bit systems. + +=head1 AUTHOR + +Copyright 2003-2019, Phil Harvey (phil at owl.phy.queensu.ca) + +This library is free software; you can redistribute it and/or modify it +under the same terms as Perl itself. + +=head1 SEE ALSO + +L<Image::ExifTool(3pm)|Image::ExifTool> + +=cut diff --git a/lib/Image/ExifTool/Shortcuts.pm b/lib/Image/ExifTool/Shortcuts.pm new file mode 100644 index 0000000..1e7a54f --- /dev/null +++ b/lib/Image/ExifTool/Shortcuts.pm @@ -0,0 +1,344 @@ +#------------------------------------------------------------------------------ +# File: Shortcuts.pm +# +# Description: ExifTool shortcut tags +# +# Revisions: 02/07/2004 - PH Moved out of Exif.pm +# 09/15/2004 - PH Added D70Boring from Greg Troxel +# 01/11/2005 - PH Added Canon20D from Christian Koller +# 03/03/2005 - PH Added user defined shortcuts +# 03/26/2005 - PH Added Nikon from Tom Christiansen +# 02/28/2007 - PH Removed model-dependent shortcuts +# --> this is what UserDefined::Shortcuts is for +# 02/25/2009 - PH Added Unsafe +# 07/03/2010 - PH Added CommonIFD0 +#------------------------------------------------------------------------------ + +package Image::ExifTool::Shortcuts; + +use strict; +use vars qw($VERSION); + +$VERSION = '1.63'; + +# this is a special table used to define command-line shortcuts +# (documentation Notes may be added for these via %shortcutNotes in BuildTagLookup.pm) +%Image::ExifTool::Shortcuts::Main = ( + # this shortcut allows the three common date/time tags to be shifted at once + AllDates => [ + 'DateTimeOriginal', + 'CreateDate', + 'ModifyDate', + ], + # This is a shortcut to some common information which is useful in most images + Common => [ + 'FileName', + 'FileSize', + 'Model', + 'DateTimeOriginal', + 'ImageSize', + 'Quality', + 'FocalLength', + 'ShutterSpeed', + 'Aperture', + 'ISO', + 'WhiteBalance', + 'Flash', + ], + # This shortcut provides the same information as the Canon utilities + Canon => [ + 'FileName', + 'Model', + 'DateTimeOriginal', + 'ShootingMode', + 'ShutterSpeed', + 'Aperture', + 'MeteringMode', + 'ExposureCompensation', + 'ISO', + 'Lens', + 'FocalLength', + 'ImageSize', + 'Quality', + 'Flash', + 'FlashType', + 'ConditionalFEC', + 'RedEyeReduction', + 'ShutterCurtainHack', + 'WhiteBalance', + 'FocusMode', + 'Contrast', + 'Sharpness', + 'Saturation', + 'ColorTone', + 'ColorSpace', + 'LongExposureNoiseReduction', + 'FileSize', + 'FileNumber', + 'DriveMode', + 'OwnerName', + 'SerialNumber', + ], + Nikon => [ + 'Model', + 'SubSecDateTimeOriginal', + 'ShutterCount', + 'LensSpec', + 'FocalLength', + 'ImageSize', + 'ShutterSpeed', + 'Aperture', + 'ISO', + 'NoiseReduction', + 'ExposureProgram', + 'ExposureCompensation', + 'WhiteBalance', + 'WhiteBalanceFineTune', + 'ShootingMode', + 'Quality', + 'MeteringMode', + 'FocusMode', + 'ImageOptimization', + 'ToneComp', + 'ColorHue', + 'ColorSpace', + 'HueAdjustment', + 'Saturation', + 'Sharpness', + 'Flash', + 'FlashMode', + 'FlashExposureComp', + ], + # This shortcut may be useful when copying tags between files to either + # copy the maker notes as a block or prevent it from being copied + MakerNotes => [ + 'MakerNotes', # (for RIFF MakerNotes) + 'MakerNoteApple', + 'MakerNoteCanon', + 'MakerNoteCasio', + 'MakerNoteCasio2', + 'MakerNoteDJI', + 'MakerNoteFLIR', + 'MakerNoteFujiFilm', + 'MakerNoteGE', + 'MakerNoteGE2', + 'MakerNoteHasselblad', + 'MakerNoteHP', + 'MakerNoteHP2', + 'MakerNoteHP4', + 'MakerNoteHP6', + 'MakerNoteISL', + 'MakerNoteJVC', + 'MakerNoteJVCText', + 'MakerNoteKodak1a', + 'MakerNoteKodak1b', + 'MakerNoteKodak2', + 'MakerNoteKodak3', + 'MakerNoteKodak4', + 'MakerNoteKodak5', + 'MakerNoteKodak6a', + 'MakerNoteKodak6b', + 'MakerNoteKodak7', + 'MakerNoteKodak8a', + 'MakerNoteKodak8b', + 'MakerNoteKodak8c', + 'MakerNoteKodak9', + 'MakerNoteKodak10', + 'MakerNoteKodak11', + 'MakerNoteKodak12', + 'MakerNoteKodakUnknown', + 'MakerNoteKyocera', + 'MakerNoteMinolta', + 'MakerNoteMinolta2', + 'MakerNoteMinolta3', + 'MakerNoteMotorola', + 'MakerNoteNikon', + 'MakerNoteNikon2', + 'MakerNoteNikon3', + 'MakerNoteNintendo', + 'MakerNoteOlympus', + 'MakerNoteOlympus2', + 'MakerNoteLeica', + 'MakerNoteLeica2', + 'MakerNoteLeica3', + 'MakerNoteLeica4', + 'MakerNoteLeica5', + 'MakerNoteLeica6', + 'MakerNoteLeica7', + 'MakerNoteLeica8', + 'MakerNoteLeica9', + 'MakerNoteLeica10', + 'MakerNotePanasonic', + 'MakerNotePanasonic2', + 'MakerNotePanasonic3', + 'MakerNotePentax', + 'MakerNotePentax2', + 'MakerNotePentax3', + 'MakerNotePentax4', + 'MakerNotePentax5', + 'MakerNotePentax6', + 'MakerNotePhaseOne', + 'MakerNoteReconyx', + 'MakerNoteReconyx2', + 'MakerNoteReconyx3', + 'MakerNoteRicoh', + 'MakerNoteRicoh2', + 'MakerNoteRicohPentax', + 'MakerNoteRicohText', + 'MakerNoteSamsung1a', + 'MakerNoteSamsung1b', + 'MakerNoteSamsung2', + 'MakerNoteSanyo', + 'MakerNoteSanyoC4', + 'MakerNoteSanyoPatch', + 'MakerNoteSigma', + 'MakerNoteSony', + 'MakerNoteSony2', + 'MakerNoteSony3', + 'MakerNoteSony4', + 'MakerNoteSony5', + 'MakerNoteSonyEricsson', + 'MakerNoteSonySRF', + 'MakerNoteUnknownText', + 'MakerNoteUnknownBinary', + 'MakerNoteUnknown', + ], + # "unsafe" tags we normally don't copy in JPEG images, defined + # as a shortcut to use when rebuilding JPEG EXIF from scratch + Unsafe => [ + 'IFD0:YCbCrPositioning', + 'IFD0:YCbCrCoefficients', + 'IFD0:TransferFunction', + 'ExifIFD:ComponentsConfiguration', + 'ExifIFD:CompressedBitsPerPixel', + 'InteropIFD:InteropIndex', + 'InteropIFD:InteropVersion', + 'InteropIFD:RelatedImageWidth', + 'InteropIFD:RelatedImageHeight', + ], + # standard tags used to define the color space of an image + # (useful to preserve color space when deleting all meta information) + ColorSpaceTags => [ + 'ExifIFD:ColorSpace', + 'ExifIFD:Gamma', + 'InteropIFD:InteropIndex', + 'ICC_Profile', + ], + # common metadata tags found in IFD0 of TIFF images + CommonIFD0 => [ + # standard EXIF + 'IFD0:ImageDescription', + 'IFD0:Make', + 'IFD0:Model', + 'IFD0:Software', + 'IFD0:ModifyDate', + 'IFD0:Artist', + 'IFD0:Copyright', + # other TIFF tags + 'IFD0:Rating', + 'IFD0:RatingPercent', + 'IFD0:DNGLensInfo', + 'IFD0:PanasonicTitle', + 'IFD0:PanasonicTitle2', + 'IFD0:XPTitle', + 'IFD0:XPComment', + 'IFD0:XPAuthor', + 'IFD0:XPKeywords', + 'IFD0:XPSubject', + ], + # large binary data tags which won't be loaded if excluded when extracting + LargeTags => [ + 'CanonVRD', + 'DLOData', + 'EXIF', + 'ICC_Profile', + 'IDCPreviewImage', + 'ImageData', + 'IPTC', + 'JpgFromRaw', + 'OriginalRawImage', + 'OtherImage', + 'PreviewImage', + 'ThumbnailImage', + 'TIFFPreview', + 'XML', + 'XMP', + 'ZoomedPreviewImage', + ], +); + +#------------------------------------------------------------------------------ +# load user-defined shortcuts if available +# Inputs: reference to user-defined shortcut hash +sub LoadShortcuts($) +{ + my $shortcuts = shift; + my $shortcut; + foreach $shortcut (keys %$shortcuts) { + my $val = $$shortcuts{$shortcut}; + # also allow simple aliases + $val = [ $val ] unless ref $val eq 'ARRAY'; + # save the user-defined shortcut or alias + $Image::ExifTool::Shortcuts::Main{$shortcut} = $val; + } +} +# (for backward compatibility, renamed in ExifTool 7.75) +if (%Image::ExifTool::Shortcuts::UserDefined) { + LoadShortcuts(\%Image::ExifTool::Shortcuts::UserDefined); +} +if (%Image::ExifTool::UserDefined::Shortcuts) { + LoadShortcuts(\%Image::ExifTool::UserDefined::Shortcuts); +} + + +1; # end + +__END__ + +=head1 NAME + +Image::ExifTool::Shortcuts - ExifTool shortcut tags + +=head1 SYNOPSIS + +This module is required by Image::ExifTool. + +=head1 DESCRIPTION + +This module contains definitions for tag name shortcuts used by +Image::ExifTool. You can customize this file to add your own shortcuts. + +Individual users may also add their own shortcuts to the .ExifTool_config +file in their home directory (or the directory specified by the +EXIFTOOL_HOME environment variable). The shortcuts are defined in a hash +called %Image::ExifTool::UserDefined::Shortcuts. The keys of the hash are +the shortcut names, and the elements are either tag names or references to +lists of tag names. + +An example shortcut definition in .ExifTool_config: + + %Image::ExifTool::UserDefined::Shortcuts = ( + MyShortcut => ['createdate','exif:exposuretime','aperture'], + MyAlias => 'FocalLengthIn35mmFormat', + ); + +In this example, MyShortcut is a shortcut for the CreateDate, +EXIF:ExposureTime and Aperture tags, and MyAlias is a shortcut for +FocalLengthIn35mmFormat. + +The target tag names may contain an optional group name prefix. A group +name applied to the shortcut will be ignored for any target tag with a group +name prefix. + +=head1 AUTHOR + +Copyright 2003-2019, Phil Harvey (phil at owl.phy.queensu.ca) + +This library is free software; you can redistribute it and/or modify it +under the same terms as Perl itself. + +=head1 SEE ALSO + +L<Image::ExifTool(3pm)|Image::ExifTool> + +=cut diff --git a/lib/Image/ExifTool/Sigma.pm b/lib/Image/ExifTool/Sigma.pm new file mode 100644 index 0000000..3f55912 --- /dev/null +++ b/lib/Image/ExifTool/Sigma.pm @@ -0,0 +1,772 @@ +#------------------------------------------------------------------------------ +# File: Sigma.pm +# +# Description: Sigma/Foveon EXIF maker notes tags +# +# Revisions: 04/06/2004 - P. Harvey Created +# 02/20/2007 - PH added SD14 tags +# 24/06/2010 - PH decode some SD15 tags +# +# References: 1) http://www.x3f.info/technotes/FileDocs/MakerNoteDoc.html +# IB) Iliah Borg private communication (LibRaw) +# NJ) Niels Kristian Bech Jensen +# JR) Jos Roost +#------------------------------------------------------------------------------ + +package Image::ExifTool::Sigma; + +use strict; +use vars qw($VERSION %sigmaLensTypes); +use Image::ExifTool::Exif; + +$VERSION = '1.24'; + +# sigma LensType lookup (ref IB) +%sigmaLensTypes = ( + Notes => q{ + Sigma LensType values are hexadecimal numbers stored as a string (without + the leading "0x"). Decimal values have been added to differentiate lenses + which would otherwise have the same LensType, and are used by the Composite + LensID tag when attempting to identify the specific lens model. + }, + # 0x0 => 'Sigma 50mm F2.8 EX Macro', (0x0 used for other lenses too) + # 0x8 - 18-125mm LENSARANGE@18mm=22-4 + 0x10, 'Sigma 50mm F2.8 EX DG MACRO', + # (0x10 = 16) + 16.1 => 'Sigma 70mm F2.8 EX DG Macro', + 16.2 => 'Sigma 105mm F2.8 EX DG Macro', + 0x16 => 'Sigma 18-50mm F3.5-5.6 DC', #PH + 0x103 => 'Sigma 180mm F3.5 EX IF HSM APO Macro', + 0x104 => 'Sigma 150mm F2.8 EX DG HSM APO Macro', + 0x105 => 'Sigma 180mm F3.5 EX DG HSM APO Macro', + 0x106 => 'Sigma 150mm F2.8 EX DG OS HSM APO Macro', + 0x107 => 'Sigma 180mm F2.8 EX DG OS HSM APO Macro', + # (0x129 = 297) + 0x129 => 'Sigma Lens (0x129)', #PH + 297.1 => 'Sigma 14mm F2.8 EX Aspherical', #PH + 297.2 => 'Sigma 30mm F1.4', + # (0x131 = 305) + 0x131 => 'Sigma Lens (0x131)', + 305.1 => 'Sigma 17-70mm F2.8-4.5 DC Macro', #PH + 305.2 => 'Sigma 70-200mm F2.8 APO EX HSM', + 305.3 => 'Sigma 120-300mm F2.8 APO EX IF HSM', + 0x134 => 'Sigma 100-300mm F4 EX DG HSM APO', + 0x135 => 'Sigma 120-300mm F2.8 EX DG HSM APO', + 0x136 => 'Sigma 120-300mm F2.8 EX DG OS HSM APO', + 0x137 => 'Sigma 120-300mm F2.8 DG OS HSM | S', + 0x143 => 'Sigma 600mm F8 Mirror', + # (0x145 = 325) + 0x145 => 'Sigma Lens (0x145)', #PH + 325.1 => 'Sigma 15-30mm F3.5-4.5 EX DG Aspherical', #PH + 325.2 => 'Sigma 18-50mm F2.8 EX DG', #PH (NC) + 325.3 => 'Sigma 20-40mm F2.8 EX DG', #PH + 0x150 => 'Sigma 30mm F1.4 DC HSM', + # (0x152 = 338) + 0x152 => 'Sigma Lens (0x152)', + 338.1 => 'Sigma APO 800mm F5.6 EX DG HSM', + 338.2 => 'Sigma 12-24mm F4.5-5.6 EX DG ASP HSM', + 338.3 => 'Sigma 10-20mm F4-5.6 EX DC HSM', + 0x165 => 'Sigma 70-200mm F2.8 EX', # ...but what specific model?: + # 70-200mm F2.8 EX APO - Original version, minimum focus distance 1.8m (1999) + # 70-200mm F2.8 EX DG - Adds 'digitally optimized' lens coatings to reduce flare (2005) + # 70-200mm F2.8 EX DG Macro (HSM) - Minimum focus distance reduced to 1m (2006) + # 70-200mm F2.8 EX DG Macro HSM II - Improved optical performance (2007) + 0x169 => 'Sigma 18-50mm F2.8 EX DC', #PH (NC) + 0x183 => 'Sigma 500mm F4.5 EX HSM APO', + 0x184 => 'Sigma 500mm F4.5 EX DG HSM APO', + 0x185 => 'Sigma 500mm F4 DG OS HSM | S', #JR (NC; based on product number) (016) + 0x194 => 'Sigma 300mm F2.8 EX HSM APO', + 0x195 => 'Sigma 300mm F2.8 EX DG HSM APO', + 0x200 => 'Sigma 12-24mm F4.5-5.6 EX DG ASP HSM', + 0x201 => 'Sigma 10-20mm F4-5.6 EX DC HSM', + 0x202 => 'Sigma 10-20mm F3.5 EX DC HSM', + 0x203 => 'Sigma 8-16mm F4.5-5.6 DC HSM', + 0x204 => 'Sigma 12-24mm F4.5-5.6 DG HSM II', + 0x205 => 'Sigma 12-24mm F4 DG HSM | A', #JR (NC; based on product number) (016) + 0x210 => 'Sigma 18-35mm F1.8 DC HSM | A', + 0x240 => 'Sigma 135mm F1.8 DG HSM | A', #JR (NC; based on product number) (017) + 0x256 => 'Sigma 105mm F2.8 EX Macro', + 0x257 => 'Sigma 105mm F2.8 EX DG Macro', + 0x258 => 'Sigma 105mm F2.8 EX DG OS HSM Macro', + 0x270 => 'Sigma 70mm F2.8 EX DG Macro', #NJ (SD1) + 0x300 => 'Sigma 30mm F1.4 EX DC HSM', + 0x301 => 'Sigma 30mm F1.4 DC HSM | A', + 0x302 => 'Sigma 30mm F1.4 DC DN | C', #JR (DN lenses are only for Sony E or MFT mount) + 0x310 => 'Sigma 50mm F1.4 EX DG HSM', + 0x311 => 'Sigma 50mm F1.4 DG HSM | A', + 0x320 => 'Sigma 85mm F1.4 EX DG HSM', + 0x321 => 'Sigma 85mm F1.4 DG HSM | A', #JR (NC; based on product number) (016) + 0x330 => 'Sigma 30mm F2.8 EX DN', + 0x340 => 'Sigma 35mm F1.4 DG HSM', + 0x345 => 'Sigma 50mm F2.8 EX Macro', + 0x346 => 'Sigma 50mm F2.8 EX DG Macro', + 0x350 => 'Sigma 60mm F2.8 DN | A', + 0x400 => 'Sigma 19mm F2.8 EX DN', + 0x401 => 'Sigma 24mm F1.4 DG HSM | A', + 0x411 => 'Sigma 20mm F1.8 EX DG ASP RF', + 0x412 => 'Sigma 20mm F1.4 DG HSM | A', + 0x432 => 'Sigma 24mm F1.8 EX DG ASP Macro', + 0x440 => 'Sigma 28mm F1.8 EX DG ASP Macro', + 0x450 => 'Sigma 14mm F1.8 DH HSM | A', #JR (NC; based on product number) (017) + 0x461 => 'Sigma 14mm F2.8 EX ASP HSM', + 0x475 => 'Sigma 15mm F2.8 EX Diagonal FishEye', + 0x476 => 'Sigma 15mm F2.8 EX DG Diagonal Fisheye', + 0x477 => 'Sigma 10mm F2.8 EX DC HSM Fisheye', + 0x483 => 'Sigma 8mm F4 EX Circular Fisheye', + 0x484 => 'Sigma 8mm F4 EX DG Circular Fisheye', + 0x485 => 'Sigma 8mm F3.5 EX DG Circular Fisheye', + 0x486 => 'Sigma 4.5mm F2.8 EX DC HSM Circular Fisheye', + 0x506 => 'Sigma 70-300mm F4-5.6 APO Macro Super II', + 0x507 => 'Sigma 70-300mm F4-5.6 DL Macro Super II', + 0x508 => 'Sigma 70-300mm F4-5.6 DG APO Macro', + 0x509 => 'Sigma 70-300mm F4-5.6 DG Macro', + 0x510 => 'Sigma 17-35 F2.8-4 EX DG ASP', + 0x512 => 'Sigma 15-30mm F3.5-4.5 EX DG ASP DF', + 0x513 => 'Sigma 20-40mm F2.8 EX DG', + 0x519 => 'Sigma 17-35 F2.8-4 EX ASP HSM', + 0x520 => 'Sigma 100-300mm F4.5-6.7 DL', + 0x521 => 'Sigma 18-50mm F3.5-5.6 DC Macro', + 0x527 => 'Sigma 100-300mm F4 EX IF HSM', + 0x529 => 'Sigma 120-300mm F2.8 EX HSM IF APO', + 0x547 => 'Sigma 24-60mm F2.8 EX DG', + 0x548 => 'Sigma 24-70mm F2.8 EX DG Macro', + 0x549 => 'Sigma 28-70mm F2.8 EX DG', + 0x566 => 'Sigma 70-200mm F2.8 EX IF APO', + 0x567 => 'Sigma 70-200mm F2.8 EX IF HSM APO', + 0x568 => 'Sigma 70-200mm F2.8 EX DG IF HSM APO', + 0x569 => 'Sigma 70-200 F2.8 EX DG HSM APO Macro', + 0x571 => 'Sigma 24-70mm F2.8 IF EX DG HSM', + 0x572 => 'Sigma 70-300mm F4-5.6 DG OS', + 0x576 => 'Sigma 24-70mm F2.8 DG OS HSM | A', #JR (NC; based on product number) (017) + 0x579 => 'Sigma 70-200mm F2.8 EX DG HSM APO Macro', # (also II version) + 0x580 => 'Sigma 18-50mm F2.8 EX DC', + 0x581 => 'Sigma 18-50mm F2.8 EX DC Macro', #PH (SD1) + 0x582 => 'Sigma 18-50mm F2.8 EX DC HSM Macro', + 0x583 => 'Sigma 17-50mm F2.8 EX DC OS HSM', #PH (also SD1 Kit, is this HSM? - PH) + 0x588 => 'Sigma 24-35mm F2 DG HSM | A', + 0x589 => 'Sigma APO 70-200mm F2.8 EX DG OS HSM', + 0x594 => 'Sigma 300-800mm F5.6 EX HSM IF APO', + 0x595 => 'Sigma 300-800mm F5.6 EX DG APO HSM', + 0x597 => 'Sigma 200-500mm F2.8 APO EX DG', + 0x5A8 => 'Sigma 70-300mm F4-5.6 APO DG Macro (Motorized)', + 0x5A9 => 'Sigma 70-300mm F4-5.6 DG Macro (Motorized)', + 0x633 => 'Sigma 28-70mm F2.8-4 HS', + 0x634 => 'Sigma 28-70mm F2.8-4 DG', + 0x635 => 'Sigma 24-105mm F4 DG OS HSM | A', + 0x644 => 'Sigma 28-80mm F3.5-5.6 ASP HF Macro', + 0x659 => 'Sigma 28-80mm F3.5-5.6 Mini Zoom Macro II ASP', + 0x661 => 'Sigma 28-105mm F2.8-4 IF ASP', + 0x663 => 'Sigma 28-105mm F3.8-5.6 IF UC-III ASP', + 0x664 => 'Sigma 28-105mm F2.8-4 IF DG ASP', + 0x667 => 'Sigma 24-135mm F2.8-4.5 IF ASP', + 0x668 => 'Sigma 17-70mm F2.8-4 DC Macro OS HSM', + 0x669 => 'Sigma 17-70mm F2.8-4.5 DC HSM Macro', + 0x684 => 'Sigma 55-200mm F4-5.6 DC', + 0x686 => 'Sigma 50-200mm F4-5.6 DC OS HSM', + 0x689 => 'Sigma 17-70mm F2.8-4.5 DC Macro', + 0x690 => 'Sigma 50-150mm F2.8 EX DC HSM APO', + 0x691 => 'Sigma 50-150mm F2.8 EX DC APO HSM II', + 0x692 => 'Sigma APO 50-150mm F2.8 EX DC OS HSM', + 0x693 => 'Sigma 50-100mm F1.8 DC HSM | A', #JR (NC; based on product number) (016) + 0x709 => 'Sigma 28-135mm F3.8-5.6 IF ASP Macro', + 0x723 => 'Sigma 135-400mm F4.5-5.6 ASP APO', + 0x725 => 'Sigma 80-400mm F4.5-5.6 EX OS', + 0x726 => 'Sigma 80-400mm F4.5-5.6 EX DG OS APO', + 0x727 => 'Sigma 135-400mm F4.5-5.6 DG ASP APO', + 0x728 => 'Sigma 120-400mm F4.5-5.6 DG APO OS HSM', + 0x729 => 'Sigma 100-400mm F5-6.3 DG OS HSM | C', #JR (017) + 0x733 => 'Sigma 170-500mm F5-6.3 ASP APO', + 0x734 => 'Sigma 170-500mm F5-6.3 DG ASP APO', + 0x735 => 'Sigma 50-500mm F4-6.3 EX RF HSM APO', + 0x736 => 'Sigma 50-500mm F4-6.3 EX DG HSM APO', + 0x737 => 'Sigma 150-500mm F5-6.3 APO DG OS HSM', + 0x738 => 'Sigma 50-500mm F4.5-6.3 APO DG OS HSM', + 0x740 => 'Sigma 150-600mm F5-6.3 DG OS HSM | S', + 0x745 => 'Sigma 150-600mm F5-6.3 DG OS HSM | C', + 0x777 => 'Sigma 18-200mm F3.5-6.3 DC', + 0x77D => 'Sigma 18-200mm F3.5-6.3 DC (Motorized)', + 0x787 => 'Sigma 28-200mm F3.5-5.6 Compact ASP HZ Macro', + 0x789 => 'Sigma 18-125mm F3.5-5.6 DC', + 0x793 => 'Sigma 28-300mm F3.5-6.3 Macro', + 0x794 => 'Sigma 28-200mm F3.5-5.6 DG Compact ASP HZ Macro', + 0x795 => 'Sigma 28-300mm F3.5-6.3 DG Macro', + 0x823 => 'Sigma 1.4X TC EX APO', + 0x824 => 'Sigma 1.4X Teleconverter EX APO DG', + 0x853 => 'Sigma 18-125mm F3.8-5.6 DC OS HSM', + 0x861 => 'Sigma 18-50mm F2.8-4.5 DC OS HSM', #NJ (SD1) + 0x870 => 'Sigma 2.0X Teleconverter TC-2001', #JR + 0x875 => 'Sigma 2.0X TC EX APO', + 0x876 => 'Sigma 2.0X Teleconverter EX APO DG', + 0x879 => 'Sigma 1.4X Teleconverter TC-1401', #JR + 0x880 => 'Sigma 18-250mm F3.5-6.3 DC OS HSM', + 0x882 => 'Sigma 18-200mm F3.5-6.3 II DC OS HSM', + 0x883 => 'Sigma 18-250mm F3.5-6.3 DC Macro OS HSM', + 0x884 => 'Sigma 17-70mm F2.8-4 DC OS HSM Macro | C', + 0x885 => 'Sigma 18-200mm F3.5-6.3 DC OS HSM Macro | C', + 0x886 => 'Sigma 18-300mm F3.5-6.3 DC OS HSM Macro | C', + 0x888 => 'Sigma 18-200mm F3.5-6.3 DC OS', + 0x890 => 'Sigma Mount Converter MC-11', #JR + 0x929 => 'Sigma 19mm F2.8 DN | A', + 0x929 => 'Sigma 30mm F2.8 DN | A', + 0x929 => 'Sigma 60mm F2.8 DN | A', + 0x1003 => 'Sigma 19mm F2.8', #PH (DP1 Merrill kit) + 0x1004 => 'Sigma 30mm F2.8', #PH (DP2 Merrill kit) + 0x1005 => 'Sigma 50mm F2.8 Macro', #PH (DP3 Merrill kit) + 0x1006 => 'Sigma 19mm F2.8', #NJ (DP1 Quattro kit) + 0x1007 => 'Sigma 30mm F2.8', #PH (DP2 Quattro kit) + 0x1008 => 'Sigma 50mm F2.8 Macro', #NJ (DP3 Quattro kit) + 0x1009 => 'Sigma 14mm F4', #NJ (DP0 Quattro kit) + 0x8900 => 'Sigma 70-300mm F4-5.6 DG OS', #PH (SD15) + 0xA100 => 'Sigma 24-70mm F2.8 DG Macro', #PH (SD15) + # 'FFFF' - seen this for a 28-70mm F2.8 lens - PH +); + +%Image::ExifTool::Sigma::Main = ( + WRITE_PROC => \&Image::ExifTool::Exif::WriteExif, + CHECK_PROC => \&Image::ExifTool::Exif::CheckExif, + WRITABLE => 'string', + GROUPS => { 0 => 'MakerNotes', 2 => 'Camera' }, + NOTES => q{ + These tags are written by Sigma/Foveon cameras. In the early days Sigma was + a class leader by releasing their maker note specification to the public, + but since then they have deviated from this standard and newer camera models + are less than consistent about their metadata formats. + }, + 0x0002 => 'SerialNumber', + 0x0003 => 'DriveMode', + 0x0004 => 'ResolutionMode', + 0x0005 => 'AFMode', + 0x0006 => 'FocusSetting', + 0x0007 => 'WhiteBalance', + 0x0008 => { + Name => 'ExposureMode', + PrintConv => { #PH + A => 'Aperture-priority AE', + M => 'Manual', + P => 'Program AE', + S => 'Shutter speed priority AE', + }, + }, + 0x0009 => { + Name => 'MeteringMode', + PrintConv => { #PH + A => 'Average', + C => 'Center-weighted average', + 8 => 'Multi-segment', + }, + }, + 0x000a => 'LensFocalRange', + 0x000b => 'ColorSpace', + # SIGMA PhotoPro writes these tags as strings, but some cameras (at least) write them as rational + 0x000c => [ + { + Name => 'ExposureCompensation', + Condition => '$format eq "string"', + ValueConv => '$val =~ s/Expo:\s*//, $val', + ValueConvInv => 'IsFloat($val) ? sprintf("Expo:%+.1f",$val) : undef', + }, + { #PH + Name => 'ExposureAdjust', + Writable => 'rational64s', + Unknown => 1, + }, + ], + 0x000d => [ + { + Name => 'Contrast', + Condition => '$format eq "string"', + ValueConv => '$val =~ s/Cont:\s*//, $val', + ValueConvInv => 'IsFloat($val) ? sprintf("Cont:%+.1f",$val) : undef', + }, + { #PH + Name => 'Contrast', + Writable => 'rational64s', + Priority => 0, + }, + ], + 0x000e => [ + { + Name => 'Shadow', + Condition => '$format eq "string"', + ValueConv => '$val =~ s/Shad:\s*//, $val', + ValueConvInv => 'IsFloat($val) ? sprintf("Shad:%+.1f",$val) : undef', + }, + { #PH (may be incorrect for the SD1) + Name => 'Shadow', + Writable => 'rational64s', + Priority => 0, + }, + ], + 0x000f => [ + { + Name => 'Highlight', + Condition => '$format eq "string"', + ValueConv => '$val =~ s/High:\s*//, $val', + ValueConvInv => 'IsFloat($val) ? sprintf("High:%+.1f",$val) : undef', + }, + { #PH (may be incorrect for the SD1) + Name => 'Highlight', + Writable => 'rational64s', + Priority => 0, + }, + ], + 0x0010 => [ + { + Name => 'Saturation', + Condition => '$format eq "string"', + ValueConv => '$val =~ s/Satu:\s*//, $val', + ValueConvInv => 'IsFloat($val) ? sprintf("Satu:%+.1f",$val) : undef', + }, + { #PH (may be incorrect for the SD1) + Name => 'Saturation', + Writable => 'rational64s', + Priority => 0, + }, + ], + 0x0011 => [ + { + Name => 'Sharpness', + Condition => '$format eq "string"', + ValueConv => '$val =~ s/Shar:\s*//, $val', + ValueConvInv => 'IsFloat($val) ? sprintf("Shar:%+.1f",$val) : undef', + }, + { #PH (may be incorrect for the SD1) + Name => 'Sharpness', + Writable => 'rational64s', + Priority => 0, + }, + ], + 0x0012 => [ + { + Name => 'X3FillLight', + Condition => '$format eq "string"', + ValueConv => '$val =~ s/Fill:\s*//, $val', + ValueConvInv => 'IsFloat($val) ? sprintf("Fill:%+.1f",$val) : undef', + }, + { #PH + Name => 'X3FillLight', + Writable => 'rational64s', + }, + ], + 0x0014 => [ + { + Name => 'ColorAdjustment', + Condition => '$format eq "string"', + ValueConv => '$val =~ s/CC:\s*//, $val', + ValueConvInv => 'IsInt($val) ? "CC:$val" : undef', + }, + { #PH + Name => 'ColorAdjustment', + Writable => 'rational64s', + Count => 3, + }, + ], + 0x0015 => 'AdjustmentMode', + 0x0016 => { + Name => 'Quality', + ValueConv => '$val =~ s/Qual:\s*//, $val', + ValueConvInv => 'IsInt($val) ? "Qual:$val" : undef', + }, + 0x0017 => 'Firmware', + 0x0018 => { + Name => 'Software', + Priority => 0, + }, + 0x0019 => 'AutoBracket', + 0x001a => [ #PH + { + Name => 'PreviewImageStart', + Condition => '$format eq "int32u"', + Notes => q{ + Sigma Photo Pro writes ChrominanceNoiseReduction here, but various + models use this for PreviewImageStart + }, + IsOffset => 1, + OffsetPair => 0x001b, + DataTag => 'PreviewImage', + Writable => 'int32u', + WriteGroup => 'MakerNotes', + Protected => 2, + },{ # (written by Sigma Photo Pro) + Name => 'ChrominanceNoiseReduction', + Condition => '$format eq "string"', + ValueConv => '$val =~ s/Chro:\s*//, $val', + ValueConvInv => 'IsFloat($val) ? sprintf("Chro:%+.1f",$val) : undef', + }, + # the SD1 writes something else here (rational64s, value 0/10) + # (but we can't test by model because Sigma Photo Pro writes this too) + ], + 0x001b => [ #PH + { + Name => 'PreviewImageLength', + Condition => '$format eq "int32u"', + Notes => q{ + Sigma Photo Pro writes LuminanceNoiseReduction here, but various models use + this for PreviewImageLength + }, + OffsetPair => 0x001a, + DataTag => 'PreviewImage', + Writable => 'int32u', + WriteGroup => 'MakerNotes', + Protected => 2, + },{ # (written by Sigma Photo Pro) + Name => 'LuminanceNoiseReduction', + Condition => '$format eq "string"', + ValueConv => '$val =~ s/Luma:\s*//, $val', + ValueConvInv => 'IsFloat($val) ? sprintf("Luma:%+.1f",$val) : undef', + }, + # the SD1 writes something else here (rational64s, value 0/10) + ], + 0x001c => [ #PH + { + Name => 'PreviewImageSize', + Condition => '$$self{Model} !~ /^SIGMA (SD1( Merrill)?|DP\d (Merrill|Quattro))$/i', + Notes => q{ + PreviewImageStart for the SD1 and Merrill/Quattro models, and + PreviewImageSize for others + }, + Writable => 'int16u', + Count => 2, + },{ + Name => 'PreviewImageStart', + Condition => '$format eq "int32u"', + IsOffset => 1, + OffsetPair => 0x001d, + DataTag => 'PreviewImage', + Writable => 'int32u', + WriteGroup => 'MakerNotes', + Protected => 2, + }, + ], + 0x001d => [ #PH + { + Name => 'MakerNoteVersion', + Condition => '$$self{Model} !~ /^SIGMA (SD1( Merrill)?|DP\d (Merrill|Quattro))$/i', + Notes => q{ + PreviewImageLength for the SD1 and Merrill/Quattro models, and + MakerNoteVersion for others + }, + Writable => 'undef', + },{ + Name => 'PreviewImageLength', + Condition => '$format eq "int32u"', + OffsetPair => 0x001c, + DataTag => 'PreviewImage', + Writable => 'int32u', + WriteGroup => 'MakerNotes', + Protected => 2, + }, + ], + # 0x001e - int16u: 0, 4, 13 - flash mode for other models? + 0x001e => { #PH + Name => 'PreviewImageSize', + Condition => '$$self{Model} =~ /^(SIGMA (DP\d (Merrill|Quattro))|sd Quattro)$/i', + Notes => 'only valid for some models', + Writable => 'int16u', + Count => 2, + }, + 0x001f => [ #PH + { + Name => 'AFPoint', # (NC -- invalid for SD9,SD14?) + Condition => '$$self{Model} !~ /^SIGMA (SD1( Merrill)?|DP\d (Merrill|Quattro))$/i', + Notes => q{ + MakerNoteVersion for the SD1 and Merrill/Quattro models, and AFPoint for + others + }, + # values: "", "Center", "Center,Center", "Right,Right" + },{ + Name => 'MakerNoteVersion', + Writable => 'undef', + }, + ], + # 0x0020 - string: " " for most models, or int16u: 4 for the DP3 Merrill + # 0x0021 - string: " " for most models, or int8u[2]: '3 3' for the DP3 Merrill + 0x0022 => { #PH (NC) + Name => 'FileFormat', + Condition => '$$self{Model} !~ /^SIGMA (SD1( Merrill)?|DP\d (Merrill|Quattro))$/i', + Notes => 'models other than the SD1 and Merrill/Quattro models', + # values: "JPG", "JPG-S", "JPG-P", "X3F", "X3F-S" + }, + # 0x0023 - string: "", 10, 83, 131, 145, 150, 152, 169 + 0x0024 => { # (invalid for SD9,SD14?) + Name => 'Calibration', + Condition => '$$self{Model} !~ /^SIGMA (SD1( Merrill)?|DP\d (Merrill|Quattro))$/i', + Notes => 'models other than the SD1 and Merrill/Quattro models', + }, + # 0x0025 - string: "", "0.70", "0.90" + # 0x0026-2b - int32u: 0 + 0x0026 => { #PH (NC) + Name => 'FileFormat', + Condition => '$$self{Model} =~ /^SIGMA (SD1( Merrill)?|DP\d (Merrill|Quattro))$/i', + Notes => 'SD1 and Merrill/Quattro models only', + }, + 0x0027 => { #PH + Name => 'LensType', + Condition => '$$self{Model} =~ /^SIGMA (SD1( Merrill)?|DP\d (Merrill|Quattro))$/i', + Notes => 'SD1 and Merrill/Quattro models only', + ValueConv => '$val =~ /^[0-9a-f]+$/i ? hex($val) : $val', + # (truncate decimal part and convert hex) + ValueConvInv => '$val=~s/\.\d+$//;$val=~/^0x/ and $val=hex($val);IsInt($val) ? sprintf("%x",$val) : $val', + SeparateTable => 'LensType', + PrintHex => 1, + PrintConv => \%sigmaLensTypes, + }, + 0x002a => { #PH + Name => 'LensFocalRange', + Condition => '$$self{Model} =~ /^SIGMA (SD1( Merrill)?|DP\d (Merrill|Quattro))$/i', + Notes => 'SD1 and Merrill/Quattro models only', + Writable => 'rational64u', + Count => 2, + PrintConv => '$val=~s/ / to /; $val', + PrintConvInv => '$val=~s/to //; $val', + }, + 0x002b => { #PH + Name => 'LensMaxApertureRange', + # for most models this gives the max aperture at the long/short focal lengths, + # but for some models this gives the min/max aperture + Condition => '$$self{Model} =~ /^SIGMA (SD1( Merrill)?|DP\d (Merrill|Quattro))$/i', + Notes => 'SD1 and Merrill/Quattro models only', + Writable => 'rational64u', + Count => 2, + PrintConv => '$val=~s/ / to /; $val', + PrintConvInv => '$val=~s/to /; $val', + }, + 0x002c => { #PH + Name => 'ColorMode', + Condition => '$format eq "int32u"', + Notes => 'not valid for some models', + Writable => 'int32u', + # this tag written by Sigma Photo Pro even for cameras that write 'n/a' here + PrintConv => { + 0 => 'n/a', + 1 => 'Sepia', + 2 => 'B&W', + 3 => 'Standard', + 4 => 'Vivid', + 5 => 'Neutral', + 6 => 'Portrait', + 7 => 'Landscape', + 8 => 'FOV Classic Blue', + }, + }, + # 0x002d - int32u: 0 + # 0x002e - rational64s: (the negative of FlashExposureComp, but why?) + # 0x002f - int32u: 0, 1 + 0x0030 => [ #PH + { + Name => 'LensApertureRange', + Condition => '$$self{Model} !~ /^SIGMA (SD1( Merrill)?|DP\d (Merrill|Quattro))$/i', + Notes => q{ + Calibration for the SD1 and Merrill/Quattro models, and LensApertureRange + for others. Note that LensApertureRange changes with focal length, and some + models report the maximum aperture here + }, + },{ + Name => 'Calibration', + }, + ], + 0x0031 => { #PH + Name => 'FNumber', + Condition => '$$self{Model} !~ /^SIGMA (SD1( Merrill)?|DP\d (Merrill|Quattro))$/i', + Notes => 'models other than the SD1 and Merrill/Quattro models', + Writable => 'rational64u', + PrintConv => 'sprintf("%.1f",$val)', + PrintConvInv => '$val', + Priority => 0, + }, + 0x0032 => { #PH + Name => 'ExposureTime', + Condition => '$$self{Model} !~ /^SIGMA (SD1( Merrill)?|DP\d (Merrill|Quattro))$/i', + Notes => 'models other than the SD1 and Merrill/Quattro models', + Writable => 'rational64u', + PrintConv => 'Image::ExifTool::Exif::PrintExposureTime($val)', + PrintConvInv => '$val', + Priority => 0, + }, + 0x0033 => { #PH + Name => 'ExposureTime2', + Condition => '$$self{Model} !~ / (SD1|SD9|SD15|Merrill|Quattro)$/', + Notes => 'models other than the SD1, SD9, SD15 and Merrill/Quattro models', + Writable => 'string', + ValueConv => '$val * 1e-6', + ValueConvInv => 'int($val * 1e6 + 0.5)', + PrintConv => 'Image::ExifTool::Exif::PrintExposureTime($val)', + PrintConvInv => 'Image::ExifTool::Exif::ConvertFraction($val)', + }, + 0x0034 => { #PH + Name => 'BurstShot', + Condition => '$$self{Model} !~ /^SIGMA (SD1( Merrill)?|DP\d (Merrill|Quattro))$/i', + Notes => 'models other than the SD1 and Merrill/Quattro models', + Writable => 'int32u', + }, + # 0x0034 - int32u: 0,1,2,3 or 4 + 0x0035 => { #PH + Name => 'ExposureCompensation', + Condition => '$$self{Model} !~ /^SIGMA (SD1( Merrill)?|DP\d (Merrill|Quattro))$/i', + Notes => 'models other than the SD1 and Merrill/Quattro models', + Writable => 'rational64s', + # add a '+' sign to positive values + PrintConv => '$val and $val =~ s/^(\d)/\+$1/; $val', + PrintConvInv => '$val', + }, + # 0x0036 - string: " " + # 0x0037-38 - string: "" + 0x0039 => { #PH (invalid for SD9, SD14?) + Name => 'SensorTemperature', + Condition => '$$self{Model} !~ /^SIGMA (SD1( Merrill)?|DP\d (Merrill|Quattro))$/i', + Notes => 'models other than the SD1 and Merrill/Quattro models', + # (string format) + PrintConv => 'IsInt($val) ? "$val C" : $val', + PrintConvInv => '$val=~s/ ?C$//; $val', + }, + 0x003a => { #PH + Name => 'FlashExposureComp', + Condition => '$$self{Model} !~ /^SIGMA (SD1( Merrill)?|DP\d (Merrill|Quattro))$/i', + Notes => 'models other than the SD1 and Merrill/Quattro models', + Writable => 'rational64s', + }, + 0x003b => { #PH (how is this different from other Firmware?) + Name => 'Firmware', + Condition => '$$self{Model} !~ /^SIGMA (SD1( Merrill)?|DP\d (Merrill|Quattro))$/i', + Notes => 'models other than the SD1 and Merrill/Quattro models', + Priority => 0, + }, + 0x003c => { #PH + Name => 'WhiteBalance', + Condition => '$$self{Model} !~ /^SIGMA (SD1( Merrill)?|DP\d (Merrill|Quattro))$/i', + Notes => 'models other than the SD1 and Merrill/Quattro models', + Priority => 0, + }, + 0x003d => { #PH (new for SD15 and SD1) + Name => 'PictureMode', + Notes => 'same as ColorMode, but "Standard" when ColorMode is Sepia or B&W', + }, + 0x0048 => { #PH + Name => 'LensApertureRange', + Condition => '$$self{Model} =~ /^SIGMA (SD1( Merrill)?|DP\d (Merrill|Quattro))$/i', + Notes => 'SD1 and Merrill/Quattro models only', + }, + 0x0049 => { #PH + Name => 'FNumber', + Condition => '$$self{Model} =~ /^SIGMA (SD1( Merrill)?|DP\d (Merrill|Quattro))$/i', + Notes => 'SD1 and Merrill/Quattro models only', + Writable => 'rational64u', + PrintConv => 'sprintf("%.1f",$val)', + PrintConvInv => '$val', + Priority => 0, + }, + 0x004a => { #PH + Name => 'ExposureTime', + Condition => '$$self{Model} =~ /^SIGMA (SD1( Merrill)?|DP\d (Merrill|Quattro))$/i', + Notes => 'SD1 and Merrill/Quattro models only', + Writable => 'rational64u', + PrintConv => 'Image::ExifTool::Exif::PrintExposureTime($val)', + PrintConvInv => '$val', + Priority => 0, + }, + 0x004b => [{ #PH + Name => 'ExposureTime2', + Condition => '$$self{Model} =~ /^SIGMA (SD1( Merrill)?|DP\d Merrill)$/', + Notes => 'SD1 and Merrill/Quattro models only', + Writable => 'string', + PrintConv => 'Image::ExifTool::Exif::PrintExposureTime($val)', + PrintConvInv => 'Image::ExifTool::Exif::ConvertFraction($val)', + },{ + Name => 'ExposureTime2', + Condition => '$$self{Model} =~ /^SIGMA dp\d Quattro$/i', + Notes => 'SD1 and Merrill/Quattro models only', + Writable => 'string', + ValueConv => '$val / 1000000', + ValueConvInv => '$val * 1000000', + PrintConv => 'Image::ExifTool::Exif::PrintExposureTime($val)', + PrintConvInv => 'Image::ExifTool::Exif::ConvertFraction($val)', + }], + 0x004d => { #PH + Name => 'ExposureCompensation', + Condition => '$$self{Model} =~ /^SIGMA (SD1( Merrill)?|DP\d (Merrill|Quattro))$/i', + Notes => 'SD1 and Merrill/Quattro models only', + Writable => 'rational64s', + # add a '+' sign to positive values + PrintConv => '$val and $val =~ s/^(\d)/\+$1/; $val', + PrintConvInv => '$val', + }, + # 0x0054 - string: "F20","F23" + 0x0055 => { #PH + Name => 'SensorTemperature', + Condition => '$$self{Model} =~ /^SIGMA (SD1( Merrill)?|DP\d (Merrill|Quattro))$/i', + Notes => 'SD1 and Merrill/Quattro models only', + # (string format) + PrintConv => 'IsInt($val) ? "$val C" : $val', + PrintConvInv => '$val=~s/ ?C$//; $val', + }, + 0x0056 => { #PH (NC) + Name => 'FlashExposureComp', + Condition => '$$self{Model} =~ /^SIGMA (SD1( Merrill)?|DP\d (Merrill|Quattro))$/i', + Notes => 'SD1 and Merrill/Quattro models only', + Writable => 'rational64s', + }, + 0x0057 => { #PH (how is this different from other Firmware?) + Name => 'Firmware', + Condition => '$$self{Model} =~ /^SIGMA (SD1( Merrill)?|DP\d (Merrill|Quattro))$/i', + Notes => 'SD1 and Merrill/Quattro models only', + Priority => 0, + }, + 0x0058 => { #PH + Name => 'WhiteBalance', + Condition => '$$self{Model} =~ /^SIGMA (SD1( Merrill)?|DP\d (Merrill|Quattro))$/i', + Notes => 'SD1 and Merrill/Quattro models only', + Priority => 0, + }, + 0x0059 => { #PH + Name => 'DigitalFilter', + Condition => '$$self{Model} =~ /^SIGMA (SD1( Merrill)?|DP\d (Merrill|Quattro))$/i', + Notes => 'SD1 and Merrill/Quattro models only', + # seen: Standard, Landscape,Monochrome,Neutral,Portrait,Sepia,Vivid + }, + # 0x005a/b/c - rational64s: 0/10 for the SD1 + 0x0084 => { #PH + Name => 'Model', + Description => 'Camera Model Name', + Writable => 'string', + }, + # 0x0085 +); + +1; # end + +__END__ + +=head1 NAME + +Image::ExifTool::Sigma - Sigma/Foveon EXIF maker notes tags + +=head1 SYNOPSIS + +This module is loaded automatically by Image::ExifTool when required. + +=head1 DESCRIPTION + +This module contains definitions required by Image::ExifTool to interpret +Sigma and Foveon maker notes in EXIF information. + +=head1 AUTHOR + +Copyright 2003-2019, Phil Harvey (phil at owl.phy.queensu.ca) + +This library is free software; you can redistribute it and/or modify it +under the same terms as Perl itself. + +=head1 REFERENCES + +=over 4 + +=item L<http://www.x3f.info/technotes/FileDocs/MakerNoteDoc.html> + +=back + +=head1 SEE ALSO + +L<Image::ExifTool::TagNames/Sigma Tags>, +L<Image::ExifTool(3pm)|Image::ExifTool> + +=cut diff --git a/lib/Image/ExifTool/SigmaRaw.pm b/lib/Image/ExifTool/SigmaRaw.pm new file mode 100644 index 0000000..de3182d --- /dev/null +++ b/lib/Image/ExifTool/SigmaRaw.pm @@ -0,0 +1,665 @@ +#------------------------------------------------------------------------------ +# File: SigmaRaw.pm +# +# Description: Read Sigma/Foveon RAW (X3F) meta information +# +# Revisions: 2005/10/16 - P. Harvey Created +# 2009/11/30 - P. Harvey Support X3F v2.3 written by Sigma DP2 +# +# References: 1) http://www.x3f.info/technotes/FileDocs/X3F_Format.pdf +#------------------------------------------------------------------------------ + +package Image::ExifTool::SigmaRaw; + +use strict; +use vars qw($VERSION); +use Image::ExifTool qw(:DataAccess :Utils); +use Image::ExifTool::Sigma; + +$VERSION = '1.26'; + +sub ProcessX3FHeader($$$); +sub ProcessX3FDirectory($$$); +sub ProcessX3FProperties($$$); + +# main X3F sections (plus header stuff) +%Image::ExifTool::SigmaRaw::Main = ( + PROCESS_PROC => \&ProcessX3FDirectory, + NOTES => q{ + These tags are used in Sigma and Foveon RAW (.X3F) images. Metadata is also + extracted from the JpgFromRaw image if it exists (all models but the SD9 and + SD10). Currently, metadata may only be written to the embedded JpgFromRaw. + }, + Header => { + SubDirectory => { TagTable => 'Image::ExifTool::SigmaRaw::Header' }, + }, + Header4 => { + SubDirectory => { TagTable => 'Image::ExifTool::SigmaRaw::Header4' }, + }, + HeaderExt => { + SubDirectory => { TagTable => 'Image::ExifTool::SigmaRaw::HeaderExt' }, + }, + PROP => { + Name => 'Properties', + SubDirectory => { TagTable => 'Image::ExifTool::SigmaRaw::Properties' }, + }, + IMAG => { + Name => 'PreviewImage', + Groups => { 2 => 'Preview' }, + Binary => 1, + }, + IMA2 => [ + { + Name => 'PreviewImage', + Condition => 'not $$self{IsJpgFromRaw}', + Groups => { 2 => 'Preview' }, + Binary => 1, + }, + { + Name => 'JpgFromRaw', + Groups => { 2 => 'Preview' }, + Binary => 1, + }, + ] +); + +# common X3F header structure +%Image::ExifTool::SigmaRaw::Header = ( + PROCESS_PROC => \&ProcessX3FHeader, + FORMAT => 'int32u', + NOTES => 'Information extracted from the header of an X3F file.', + 1 => { + Name => 'FileVersion', + ValueConv => '($val >> 16) . "." . ($val & 0xffff)', + }, + 2 => { + Name => 'ImageUniqueID', + # the serial number (with an extra leading "0") makes up + # the first 8 digits of this UID, + Format => 'undef[16]', + ValueConv => 'unpack("H*", $val)', + }, + 6 => { + Name => 'MarkBits', + PrintConv => { BITMASK => { } }, + }, + 7 => 'ImageWidth', + 8 => 'ImageHeight', + 9 => 'Rotation', + 10 => { + Name => 'WhiteBalance', + Format => 'string[32]', + }, + 18 => { #PH (DP2, FileVersion 2.3) + Name => 'SceneCaptureType', + Format => 'string[32]', + }, +); + +# X3F version 4 header structure (ref PH) +%Image::ExifTool::SigmaRaw::Header4 = ( + PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData, + FORMAT => 'int32u', + NOTES => 'Header information for version 4.0 or greater X3F.', + 1 => { + Name => 'FileVersion', + ValueConv => '($val >> 16) . "." . ($val & 0xffff)', + }, + # 8 - undef[4]: 4 random ASCII characters + 10 => 'ImageWidth', + 11 => 'ImageHeight', + 12 => 'Rotation', + # don't know what the rest of the header contains, but none of + # these values change in any of my samples... +); + +# extended header tags +%Image::ExifTool::SigmaRaw::HeaderExt = ( + GROUPS => { 2 => 'Camera' }, + FORMAT => 'float', + NOTES => 'Extended header data found in version 2.1 and 2.2 files', + 0 => 'Unused', + 1 => { Name => 'ExposureAdjust',PrintConv => 'sprintf("%.1f",$val)' }, + 2 => { Name => 'Contrast', PrintConv => 'sprintf("%.1f",$val)' }, + 3 => { Name => 'Shadow', PrintConv => 'sprintf("%.1f",$val)' }, + 4 => { Name => 'Highlight', PrintConv => 'sprintf("%.1f",$val)' }, + 5 => { Name => 'Saturation', PrintConv => 'sprintf("%.1f",$val)' }, + 6 => { Name => 'Sharpness', PrintConv => 'sprintf("%.1f",$val)' }, + 7 => { Name => 'RedAdjust', PrintConv => 'sprintf("%.1f",$val)' }, + 8 => { Name => 'GreenAdjust', PrintConv => 'sprintf("%.1f",$val)' }, + 9 => { Name => 'BlueAdjust', PrintConv => 'sprintf("%.1f",$val)' }, + 10 => { Name => 'X3FillLight', PrintConv => 'sprintf("%.1f",$val)' }, +); + +# PROP tags +%Image::ExifTool::SigmaRaw::Properties = ( + PROCESS_PROC => \&ProcessX3FProperties, + GROUPS => { 2 => 'Camera' }, + PRIORITY => 0, # (because these aren't writable like the EXIF ones) + AEMODE => { + Name => 'MeteringMode', + PrintConv => { + 8 => '8-segment', + C => 'Center-weighted average', + A => 'Average', + }, + }, + AFAREA => 'AFArea', # observed: CENTER_V + AFINFOCUS => 'AFInFocus', # observed: H + AFMODE => 'FocusMode', + AP_DESC => 'ApertureDisplayed', + APERTURE => { + Name => 'FNumber', + Groups => { 2 => 'Image' }, + PrintConv => 'sprintf("%.1f",$val)', + }, + BRACKET => 'BracketShot', + BURST => 'BurstShot', + CAMMANUF => 'Make', + CAMMODEL => 'Model', + CAMNAME => 'CameraName', + CAMSERIAL => 'SerialNumber', + CM_DESC => 'SceneCaptureType', #PH (DP2) + COLORSPACE => 'ColorSpace', # observed: sRGB + DRIVE => { + Name => 'DriveMode', + PrintConv => { + SINGLE => 'Single Shot', + MULTI => 'Multi Shot', + '2S' => '2 s Timer', + '10S' => '10 s Timer', + UP => 'Mirror Up', + AB => 'Auto Bracket', + OFF => 'Off', + }, + }, + EVAL_STATE => 'EvalState', # observed: POST-EXPOSURE + EXPCOMP => { + Name => 'ExposureCompensation', + Groups => { 2 => 'Image' }, + PrintConv => 'Image::ExifTool::Exif::PrintFraction($val)', + }, + EXPNET => { + Name => 'NetExposureCompensation', + Groups => { 2 => 'Image' }, + PrintConv => 'Image::ExifTool::Exif::PrintFraction($val)', + }, + EXPTIME => { + Name => 'IntegrationTime', + Groups => { 2 => 'Image' }, + ValueConv => '$val * 1e-6', # convert from usec + PrintConv => 'Image::ExifTool::Exif::PrintExposureTime($val)', + }, + FIRMVERS => 'FirmwareVersion', + FLASH => { + Name => 'FlashMode', + PrintConv => 'ucfirst(lc($val))', + }, + FLASHEXPCOMP=> 'FlashExpComp', + FLASHPOWER => 'FlashPower', + FLASHTTLMODE=> 'FlashTTLMode', # observed: ON + FLASHTYPE => 'FlashType', # observed: NONE + FLENGTH => { + Name => 'FocalLength', + PrintConv => 'sprintf("%.1f mm",$val)', + }, + FLEQ35MM => { + Name => 'FocalLengthIn35mmFormat', + PrintConv => 'sprintf("%.1f mm",$val)', + }, + FOCUS => { + Name => 'Focus', + PrintConv => { + AF => 'Auto-focus Locked', + 'NO LOCK' => "Auto-focus Didn't Lock", + M => 'Manual', + }, + }, + IMAGERBOARDID => 'ImagerBoardID', + IMAGERTEMP => { + Name => 'SensorTemperature', + PrintConv => '"$val C"', + }, + IMAGEBOARDID=> 'ImageBoardID', #PH (DP2) + ISO => 'ISO', + LENSARANGE => 'LensApertureRange', + LENSFRANGE => 'LensFocalRange', + LENSMODEL => { + Name => 'LensType', + ValueConv => '$val =~ /^[0-9a-f]+$/i ? hex($val) : $val', + ValueConvInv => '$val=~s/\.\d+$//; IsInt($val) ? sprintf("%x",$val) : $val', # (truncate decimal part) + SeparateTable => 'Sigma LensType', + PrintHex => 1, + PrintConv => \%Image::ExifTool::Sigma::sigmaLensTypes, + }, + PMODE => { + Name => 'ExposureProgram', + PrintConv => { + P => 'Program', + A => 'Aperture Priority', + S => 'Shutter Priority', + M => 'Manual', + }, + }, + RESOLUTION => { + Name => 'Quality', + PrintConv => { + LOW => 'Low', + MED => 'Medium', + HI => 'High', + }, + }, + SENSORID => 'SensorID', + SH_DESC => 'ShutterSpeedDisplayed', + SHUTTER => { + Name => 'ExposureTime', + Groups => { 2 => 'Image' }, + PrintConv => 'Image::ExifTool::Exif::PrintExposureTime($val)', + }, + TIME => { + Name => 'DateTimeOriginal', + Groups => { 2 => 'Time' }, + Description => 'Date/Time Original', + ValueConv => 'ConvertUnixTime($val)', + PrintConv => '$self->ConvertDateTime($val)', + }, + WB_DESC => 'WhiteBalance', + VERSION_BF => 'VersionBF', +); + +#------------------------------------------------------------------------------ +# Extract null-terminated unicode string from list of characters +# Inputs: 0) ExifTool ref, 1) list ref, 2) position in list +# Returns: Converted string +sub ExtractUnicodeString($$$) +{ + my ($et, $chars, $pos) = @_; + my $i; + for ($i=$pos; $i<@$chars; ++$i) { + last unless $$chars[$i]; + } + my $buff = pack('v*', @$chars[$pos..$i-1]); + return $et->Decode($buff, 'UCS2', 'II'); +} + +#------------------------------------------------------------------------------ +# Process an X3F header +# Inputs: 0) ExifTool ref, 1) DirInfo ref, 2) tag table ref +# Returns: 1 on success +sub ProcessX3FHeader($$$) +{ + my ($et, $dirInfo, $tagTablePtr) = @_; + my $dataPt = $$dirInfo{DataPt}; + my $hdrLen = $$dirInfo{DirLen}; + + # process the static header structure first + $et->ProcessBinaryData($dirInfo, $tagTablePtr); + + # process extended data if available + if (length($$dataPt) - $hdrLen >= 160) { + my $verbose = $et->Options('Verbose'); + if ($verbose) { + $et->VerboseDir('X3F HeaderExt', 32); + $et->VerboseDump($dataPt, Start => $hdrLen); + } + $tagTablePtr = GetTagTable('Image::ExifTool::SigmaRaw::HeaderExt'); + my @tags = unpack("x${hdrLen}C32", $$dataPt); + my $i; + my $unused = 0; + for ($i=0; $i<32; ++$i) { + $tags[$i] or ++$unused, next; + $et->HandleTag($tagTablePtr, $tags[$i], undef, + Index => $i, + DataPt => $dataPt, + Start => $hdrLen + 32 + $i * 4, + Size => 4, + ); + } + $et->VPrint(0, "$$et{INDENT}($unused entries unused)\n"); + } + return 1; +} + +#------------------------------------------------------------------------------ +# Process an X3F properties +# Inputs: 0) ExifTool ref, 1) DirInfo ref, 2) tag table ref +# Returns: 1 on success +sub ProcessX3FProperties($$$) +{ + my ($et, $dirInfo, $tagTablePtr) = @_; + my $dataPt = $$dirInfo{DataPt}; + my $size = length($$dataPt); + my $verbose = $et->Options('Verbose'); + my $unknown = $et->Options('Unknown'); + + unless ($size >= 24 and $$dataPt =~ /^SECp/) { + $et->Warn('Bad properties header'); + return 0; + } + my ($entries, $fmt, $len) = unpack('x8V2x4V', $$dataPt); + unless ($size >= 24 + 8 * $entries + $len) { + $et->Warn('Truncated Property directory'); + return 0; + } + $verbose and $et->VerboseDir('Properties', $entries); + $fmt == 0 or $et->Warn("Unsupported character format $fmt"), return 0; + my $charPos = 24 + 8 * $entries; + my @chars = unpack('v*',substr($$dataPt, $charPos, $len * 2)); + my $index; + for ($index=0; $index<$entries; ++$index) { + my ($namePos, $valPos) = unpack('V2',substr($$dataPt, $index*8 + 24, 8)); + if ($namePos >= @chars or $valPos >= @chars) { + $et->Warn('Bad Property pointer'); + return 0; + } + my $tag = ExtractUnicodeString($et, \@chars, $namePos); + my $val = ExtractUnicodeString($et, \@chars, $valPos); + if (not $$tagTablePtr{$tag} and $unknown and $tag =~ /^\w+$/) { + my $tagInfo = { + Name => "SigmaRaw_$tag", + Description => Image::ExifTool::MakeDescription('SigmaRaw', $tag), + Unknown => 1, + Writable => 0, # can't write unknown tags + }; + # add tag information to table + AddTagToTable($tagTablePtr, $tag, $tagInfo); + } + + $et->HandleTag($tagTablePtr, $tag, $val, + Index => $index, + DataPt => $dataPt, + Start => $charPos + 2 * $valPos, + Size => 2 * (length($val) + 1), + ); + } + return 1; +} + +#------------------------------------------------------------------------------ +# Write an X3F file +# Inputs: 0) ExifTool ref, 1) DirInfo ref (DirStart = directory offset) +# Returns: error string, undef on success, or -1 on write error +# Notes: Writes metadata to embedded JpgFromRaw image +sub WriteX3F($$) +{ + my ($et, $dirInfo) = @_; + my $raf = $$dirInfo{RAF}; + my $outfile = $$dirInfo{OutFile}; + my ($outDir, $buff, $ver, $entries, $dir, $outPos, $index, $didContain); + + $raf->Seek($$dirInfo{DirStart}, 0) or return 'Error seeking to directory start'; + + # read the X3F directory header (will be copied directly to output) + $raf->Read($outDir, 12) == 12 or return 'Truncated X3F image'; + $outDir =~ /^SECd/ or return 'Bad section header'; + ($ver, $entries) = unpack('x4V2', $outDir); + + # do sanity check on number of entries in directory + return 'Invalid X3F directory count' unless $entries > 2 and $entries < 20; + # read the directory entries + unless ($raf->Read($dir, $entries * 12) == $entries * 12) { + return 'Truncated X3F directory'; + } + # do a quick scan to determine the offset of the first data subsection + for ($index=0; $index<$entries; ++$index) { + my $pos = $index * 12; + my ($offset, $len, $tag) = unpack("x${pos}V2a4", $dir); + # remember position of first data subsection + $outPos = $offset if not defined $outPos or $outPos > $offset; + } + # copy the file header up to the start of the first data subsection + unless ($raf->Seek(0,0) and $raf->Read($buff, $outPos) == $outPos) { + return 'Error reading X3F header'; + } + Write($outfile, $buff) or return -1; + + # loop through directory, rewriting each section + for ($index=0; $index<$entries; ++$index) { + + my $pos = $index * 12; + my ($offset, $len, $tag) = unpack("x${pos}V2a4", $dir); + $raf->Seek($offset, 0) or return 'Bad data offset'; + + if ($tag eq 'IMA2' and $len > 28) { + # check subsection header (28 bytes) to see if this is a JPEG preview image + $raf->Read($buff, 28) == 28 or return 'Error reading PreviewImage header'; + Write($outfile, $buff) or return -1; + $len -= 28; + + # only rewrite full-sized JpgFromRaw (version 2.0, type 2, format 18) + if ($buff =~ /^SECi\0\0\x02\0\x02\0\0\0\x12\0\0\0/ and + $$et{ImageWidth} == unpack('x16V', $buff)) + { + $raf->Read($buff, $len) == $len or return 'Error reading JpgFromRaw'; + # use same write directories as JPEG + $et->InitWriteDirs('JPEG'); + # rewrite the embedded JPEG in memory + my $newData; + my %jpegInfo = ( + Parent => 'X3F', + RAF => new File::RandomAccess(\$buff), + OutFile => \$newData, + ); + $$et{FILE_TYPE} = 'JPEG'; + my $success = $et->WriteJPEG(\%jpegInfo); + $$et{FILE_TYPE} = 'X3F'; + SetByteOrder('II'); + return 'Error writing X3F JpgFromRaw' unless $success and $newData; + return -1 if $success < 0; + # write new data if anything changed, otherwise copy old image + my $outPt = $$et{CHANGED} ? \$newData : \$buff; + Write($outfile, $$outPt) or return -1; + # set $len to the total subsection data length + $len = length($$outPt) + 28; + $didContain = 1; + } else { + # copy original image data + Image::ExifTool::CopyBlock($raf, $outfile, $len) or return 'Corrupted X3F image'; + $len += 28; + } + } else { + # copy data for this subsection + Image::ExifTool::CopyBlock($raf, $outfile, $len) or return 'Corrupted X3F directory'; + } + # add directory entry and update output file position + $outDir .= pack('V2a4', $outPos, $len, $tag); + $outPos += $len; + # pad data to an even 4-byte boundary + if ($len & 0x03) { + my $pad = 4 - ($len & 0x03); + Write($outfile, "\0" x $pad) or return -1; + $outPos += $pad; + } + } + # warn if we couldn't add metadata to this image (should only be SD9 or SD10) + $didContain or $et->Warn("Can't yet write SD9 or SD10 X3F images"); + # write out the directory and the directory pointer, and we are done + Write($outfile, $outDir, pack('V', $outPos)) or return -1; + return undef; +} + +#------------------------------------------------------------------------------ +# Process an X3F directory +# Inputs: 0) ExifTool ref, 1) DirInfo ref, 2) tag table ref +# Returns: error string or undef on success +sub ProcessX3FDirectory($$$) +{ + my ($et, $dirInfo, $tagTablePtr) = @_; + my $raf = $$dirInfo{RAF}; + my $verbose = $et->Options('Verbose'); + + $raf->Seek($$dirInfo{DirStart}, 0) or return 'Error seeking to directory start'; + + # parse the X3F directory structure + my ($buff, $ver, $entries, $index, $dir); + $raf->Read($buff, 12) == 12 or return 'Truncated X3F image'; + $buff =~ /^SECd/ or return 'Bad section header'; + ($ver, $entries) = unpack('x4V2', $buff); + $verbose and $et->VerboseDir('X3F Subsection', $entries); + $raf->Read($dir, $entries * 12) == $entries * 12 or return 'Truncated X3F directory'; + for ($index=0; $index<$entries; ++$index) { + my $pos = $index * 12; + my ($offset, $len, $tag) = unpack("x${pos}V2a4", $dir); + my $tagInfo = $et->GetTagInfo($tagTablePtr, $tag); + if ($verbose) { + $et->VPrint(0, "$$et{INDENT}$index) $tag Subsection ($len bytes):\n"); + if ($verbose > 2) { + $raf->Seek($offset, 0) or return 'Error seeking'; + $raf->Read($buff, $len) == $len or return 'Truncated image'; + $et->VerboseDump(\$buff); + } + } + next unless $tagInfo; + $raf->Seek($offset, 0) or return "Error seeking for $$tagInfo{Name}"; + if ($$tagInfo{Name} eq 'PreviewImage') { + # check image header to see if this is a JPEG preview image + $raf->Read($buff, 28) == 28 or return 'Error reading PreviewImage header'; + # ignore all image data but JPEG compressed (version 2.0, type 2, format 18) + next unless $buff =~ /^SECi\0\0\x02\0\x02\0\0\0\x12\0\0\0/; + # check preview image size and extract full-sized preview as JpgFromRaw + if ($$et{ImageWidth} == unpack('x16V', $buff)) { + $$et{IsJpgFromRaw} = 1; + $tagInfo = $et->GetTagInfo($tagTablePtr, $tag); + delete $$et{IsJpgFromRaw}; + } + $offset += 28; + $len -= 28; + } + $raf->Read($buff, $len) == $len or return "Error reading $$tagInfo{Name} data"; + my $subdir = $$tagInfo{SubDirectory}; + if ($subdir) { + my %dirInfo = ( DataPt => \$buff ); + my $subTable = GetTagTable($$subdir{TagTable}); + $et->ProcessDirectory(\%dirInfo, $subTable); + } else { + # extract metadata from JpgFromRaw + if ($$tagInfo{Name} eq 'JpgFromRaw') { + my %dirInfo = ( + Parent => 'X3F', + RAF => new File::RandomAccess(\$buff), + ); + $$et{BASE} += $offset; + $et->ProcessJPEG(\%dirInfo); + $$et{BASE} -= $offset; + SetByteOrder('II'); + } + $et->FoundTag($tagInfo, $buff); + } + } + return undef; +} + +#------------------------------------------------------------------------------ +# Read/write information from a Sigma raw (X3F) image +# Inputs: 0) ExifTool ref, 1) DirInfo ref +# Returns: 1 on success, 0 if this wasn't a valid X3F image, or -1 on write error +sub ProcessX3F($$) +{ + my ($et, $dirInfo) = @_; + my $outfile = $$dirInfo{OutFile}; + my $raf = $$dirInfo{RAF}; + my $warn = $outfile ? \&Image::ExifTool::Error : \&Image::ExifTool::Warn; + my ($buff, $err, $hdrLen); + + return 0 unless $raf->Read($buff, 40) == 40; + return 0 unless $buff =~ /^FOVb/; + + SetByteOrder('II'); + $et->SetFileType(); + + # check version number + my $ver = unpack('x4V',$buff); + $ver = ($ver >> 16) . '.' . ($ver & 0xffff); + if ($ver > 5) { + &$warn($et, "Untested X3F version ($ver). Please submit sample for testing", 1); + } + # read version 2.1/2.2/2.3 extended header + if ($ver > 2) { + my ($extra, $buf2); + if ($ver >= 4) { + $hdrLen = 0x300; + $extra = 0; + } else { + $hdrLen = $ver > 2.2 ? 104 : 72; # SceneCaptureType string added in 2.3 + $extra = 160; # (extended header is 160 bytes) + } + my $more = $hdrLen - length($buff) + $extra; + unless ($raf->Read($buf2, $more) == $more) { + &$warn($et, 'Error reading X3F header'); + return 1; + } + $buff .= $buf2; + } + my ($widPos, $hdrType) = $ver < 4 ? (28, 'Header') : (40, 'Header4'); + # extract ImageWidth for later + $$et{ImageWidth} = Get32u(\$buff, $widPos); + # process header information + my $tagTablePtr = GetTagTable('Image::ExifTool::SigmaRaw::Main'); + unless ($outfile) { + $et->HandleTag($tagTablePtr, $hdrType, $buff, + DataPt => \$buff, + Size => $hdrLen, + ); + } + # read the directory pointer + $raf->Seek(-4, 2) or &$warn($et, 'Seek error'), return 1; + unless ($raf->Read($buff, 4) == 4) { + &$warn($et, 'Error reading X3F dir pointer'); + return 1; + } + my $offset = unpack('V', $buff); + my %dirInfo = ( + RAF => $raf, + DirStart => $offset, + ); + if ($outfile) { + $dirInfo{OutFile} = $outfile; + $err = WriteX3F($et, \%dirInfo); + return -1 if $err and $err eq '-1'; + } else { + # process the X3F subsections + $err = $et->ProcessDirectory(\%dirInfo, $tagTablePtr); + } + $err and &$warn($et, $err); + return 1; +} + +1; # end + +__END__ + +=head1 NAME + +Image::ExifTool::SigmaRaw - Read Sigma/Foveon RAW (X3F) meta information + +=head1 SYNOPSIS + +This module is loaded automatically by Image::ExifTool when required. + +=head1 DESCRIPTION + +This module contains definitions required by Image::ExifTool to read +Sigma and Foveon X3F images. + +=head1 AUTHOR + +Copyright 2003-2019, Phil Harvey (phil at owl.phy.queensu.ca) + +This library is free software; you can redistribute it and/or modify it +under the same terms as Perl itself. + +=head1 REFERENCES + +=over 4 + +=item L<http://www.x3f.info/technotes/FileDocs/X3F_Format.pdf> + +=back + +=head1 SEE ALSO + +L<Image::ExifTool::TagNames/SigmaRaw Tags>, +L<Image::ExifTool::Sigma(3pm)|Image::ExifTool::Sigma>, +L<Image::ExifTool(3pm)|Image::ExifTool> + +=cut diff --git a/lib/Image/ExifTool/Sony.pm b/lib/Image/ExifTool/Sony.pm new file mode 100644 index 0000000..17a2b5f --- /dev/null +++ b/lib/Image/ExifTool/Sony.pm @@ -0,0 +1,10555 @@ +#------------------------------------------------------------------------------ +# File: Sony.pm +# +# Description: Sony EXIF Maker Notes tags +# +# Revisions: 04/06/2004 - P. Harvey Created +# +# References: 1) http://www.cybercom.net/~dcoffin/dcraw/ +# 2) http://homepage3.nifty.com/kamisaka/makernote/makernote_sony.htm (2006/08/06) +# 3) Thomas Bodenmann private communication +# 4) Philippe Devaux private communication (A700) +# 5) Marcus Holland-Moritz private communication (A700) +# 6) Andrey Tverdokhleb private communication +# 7) Rudiger Lange private communication (A700) +# 8) Igal Milchtaich private communication +# 9) Michael Reitinger private communication (DSC-TX7,RX100) +# 10) http://www.klingebiel.com/tempest/hd/pmp.html +# 11) Mike Battilana private communication +# 13) http://www.mi-fo.de/forum/index.php?showtopic=33239 +# http://www.dyxum.com/dforum/the-alpha-shutter-count-tool_topic97489_page4.html +# 14) Albert Shan private communication (A7M3) +# IB) Iliah Borg private communication (LibRaw) +# JD) Jens Duttke private communication +# JR) Jos Roost private communication +#------------------------------------------------------------------------------ + +package Image::ExifTool::Sony; + +use strict; +use vars qw($VERSION %sonyLensTypes); +use Image::ExifTool qw(:DataAccess :Utils); +use Image::ExifTool::Exif; +use Image::ExifTool::Minolta; + +$VERSION = '3.01'; + +sub ProcessSRF($$$); +sub ProcessSR2($$$); +sub ProcessSonyPIC($$$); +sub ProcessMoreInfo($$$); +sub Process_rtmd($$$); +sub Decipher($;$); +sub ProcessEnciphered($$$); +sub WriteEnciphered($$$); +sub WriteSR2($$$); +sub ConvLensSpec($); +sub ConvInvLensSpec($); +sub PrintLensSpec($); +sub PrintInvLensSpec($;$$); + +# (%sonyLensTypes is filled in based on Minolta LensType's) + +# Sony E-mount lenses +# (NOTE: these should be kept in sync with the 65535 entries in %minoltaLensTypes) +my %sonyLensTypes2 = ( + Notes => 'Lens type numbers for Sony E-mount lenses used by NEX models.', + 0 => 'Unknown E-mount lens or other lens', + 1 => 'Sony LA-EA1 or Sigma MC-11 Adapter', # MC-11 with not-supported lenses + 2 => 'Sony LA-EA2 Adapter', + 3 => 'Sony LA-EA3 Adapter', #(NC) ILCE-7 image with A-mount lens, but also has 0x940e 2nd byte=2 + 6 => 'Sony LA-EA4 Adapter', #(NC) ILCE-7R image with A-mount lens and having phase-detect info blocks in 0x940e AFInfo + # 27 => Venus Optics Laowa 12mm f2.8 Zero-D or 105mm f2 (T3.2) Smooth Trans Focus (ref IB) + 44 => 'Metabones Canon EF Smart Adapter', #JR + 78 => 'Metabones Canon EF Smart Adapter Mark III or Other Adapter', #PH/JR (also Mark IV, Fotodiox and Viltrox) + 234 => 'Metabones Canon EF Smart Adapter Mark IV', #JR (LensMount reported as A-mount) + 239 => 'Metabones Canon EF Speed Booster', #JR + # Sony VX product code: (http://www.mi-fo.de/forum/index.php?s=7df1c8d3b1cd675f2abf4f4442e19cf2&showtopic=35035&view=findpost&p=303746) + 32784 => 'Sony E 16mm F2.8', # VX9100 + 32785 => 'Sony E 18-55mm F3.5-5.6 OSS', # VX9101 + 32786 => 'Sony E 55-210mm F4.5-6.3 OSS', # VX9102 + 32787 => 'Sony E 18-200mm F3.5-6.3 OSS', # VX9103 + 32788 => 'Sony E 30mm F3.5 Macro', # VX9104 + 32789 => 'Sony E 24mm F1.8 ZA or Samyang AF 50mm F1.4 FE', # VX9105 + 32789.1 => 'Samyang AF 50mm F1.4 FE', + 32790 => 'Sony E 50mm F1.8 OSS or Samyang AF 14mm F2.8 FE', # VX9106 + 32790.1 => 'Samyang AF 14mm F2.8 FE', + 32791 => 'Sony E 16-70mm F4 ZA OSS', # VX9107 + 32792 => 'Sony E 10-18mm F4 OSS', # VX9108 + 32793 => 'Sony E PZ 16-50mm F3.5-5.6 OSS', # VX9109 + 32794 => 'Sony FE 35mm F2.8 ZA or Samyang AF 24mm F2.8 FE', # VX9110 + 32794.1 => 'Samyang AF 24mm F2.8 FE', #JR + 32795 => 'Sony FE 24-70mm F4 ZA OSS', # VX9111 + 32796 => 'Sony FE 85mm F1.8', #JR + 32797 => 'Sony E 18-200mm F3.5-6.3 OSS LE', # VX9113 + 32798 => 'Sony E 20mm F2.8', # VX9114 + 32799 => 'Sony E 35mm F1.8 OSS', # VX9115 + 32800 => 'Sony E PZ 18-105mm F4 G OSS', #JR # VX9116 + 32801 => 'Sony FE 12-24mm F4 G', #JR + 32802 => 'Sony FE 90mm F2.8 Macro G OSS', # VX? + 32803 => 'Sony E 18-50mm F4-5.6', + 32804 => 'Sony FE 24mm F1.4 GM', #IB + 32805 => 'Sony FE 24-105mm F4 G OSS', #IB # VX9121 + + 32807 => 'Sony E PZ 18-200mm F3.5-6.3 OSS', # VX9123 + 32808 => 'Sony FE 55mm F1.8 ZA', # VX9124 + + 32810 => 'Sony FE 70-200mm F4 G OSS', #JR # VX9126 + 32811 => 'Sony FE 16-35mm F4 ZA OSS', #JR # VX9127 + 32812 => 'Sony FE 50mm F2.8 Macro', #JR + 32813 => 'Sony FE 28-70mm F3.5-5.6 OSS', # VX9129 + 32814 => 'Sony FE 35mm F1.4 ZA', # VX? + 32815 => 'Sony FE 24-240mm F3.5-6.3 OSS', # VX? + 32816 => 'Sony FE 28mm F2', #JR # VX? + 32817 => 'Sony FE PZ 28-135mm F4 G OSS',#JR # VX? + + 32819 => 'Sony FE 100mm F2.8 STF GM OSS', #JR (appears to use 33076 when switched to macro mode) + 32820 => 'Sony E PZ 18-110mm F4 G OSS', #JR + 32821 => 'Sony FE 24-70mm F2.8 GM', #JR/IB + 32822 => 'Sony FE 50mm F1.4 ZA', #JR + 32823 => 'Sony FE 85mm F1.4 GM', #JR/IB + 32824 => 'Sony FE 50mm F1.8', #JR (Sony code 'SEL50F18F' with trailing "F" as compared to 'SEL50F18' for 32790) + + 32826 => 'Sony FE 21mm F2.8 (SEL28F20 + SEL075UWC)', #JR # (+ Ultra-wide converter) + 32827 => 'Sony FE 16mm F3.5 Fisheye (SEL28F20 + SEL057FEC)', #JR # (+ Fisheye converter) + 32828 => 'Sony FE 70-300mm F4.5-5.6 G OSS', #JR + 32829 => 'Sony FE 100-400mm F4.5-5.6 GM OSS', #JR + 32830 => 'Sony FE 70-200mm F2.8 GM OSS', #JR + 32831 => 'Sony FE 16-35mm F2.8 GM', #JR + 32848 => 'Sony FE 400mm F2.8 GM OSS', #IB + 32849 => 'Sony E 18-135mm F3.5-5.6 OSS', #JR + 32850 => 'Sony FE 135mm F1.8 GM', #IB + + # (comment this out so LensID will report the LensModel, which is more useful) + # 33002 => 'Metabones Canon EF Smart Adapter with Ver.5x', #PH/JR (corresponds to 234, but LensMount reported as E-mount) + + 33072 => 'Sony FE 70-200mm F2.8 GM OSS + 1.4X Teleconverter', #JR + 33073 => 'Sony FE 70-200mm F2.8 GM OSS + 2X Teleconverter', #JR + 33076 => 'Sony FE 100mm F2.8 STF GM OSS (macro mode)', #JR (with macro switching ring set to "0.57m - 1.0m") + 33077 => 'Sony FE 100-400mm F4.5-5.6 GM OSS + 1.4X Teleconverter', #JR + 33078 => 'Sony FE 100-400mm F4.5-5.6 GM OSS + 2X Teleconverter', #JR + 33079 => 'Sony FE 400mm F2.8 GM OSS + 1.4X Teleconverter', #IB + 33080 => 'Sony FE 400mm F2.8 GM OSS + 2X Teleconverter', #JR + + 49201 => 'Zeiss Touit 12mm F2.8', #JR (lens firmware Ver.02) + 49202 => 'Zeiss Touit 32mm F1.8', #JR (lens firmware Ver.02) + 49203 => 'Zeiss Touit 50mm F2.8 Macro', #JR (lens firmware Ver.02) + 49216 => 'Zeiss Batis 25mm F2', #JR + 49217 => 'Zeiss Batis 85mm F1.8', #JR + 49218 => 'Zeiss Batis 18mm F2.8', #IB + 49219 => 'Zeiss Batis 135mm F2.8', #IB + 49220 => 'Zeiss Batis 40mm F2 CF', #IB + 49232 => 'Zeiss Loxia 50mm F2', #JR (lens firmware Ver.02) + 49233 => 'Zeiss Loxia 35mm F2', #JR (lens firmware Ver.02) + 49234 => 'Zeiss Loxia 21mm F2.8', #PH + 49235 => 'Zeiss Loxia 85mm F2.4', #JR + 49236 => 'Zeiss Loxia 25mm F2.4', #JR + + 49457 => 'Tamron 28-75mm F2.8 Di III RXD', #JR (Model A036) + + 50480 => 'Sigma 30mm F1.4 DC DN | C', #IB/JR (016) + 50481 => 'Sigma 50mm F1.4 DG HSM | A', #JR (014 + MC-11 or 018) + 50482 => 'Sigma 18-300mm F3.5-6.3 DC MACRO OS HSM | C + MC-11', #JR (014) + 50483 => 'Sigma 18-35mm F1.8 DC HSM | A + MC-11', #JR (013) + 50484 => 'Sigma 24-35mm F2 DG HSM | A + MC-11', #JR (015) + 50486 => 'Sigma 150-600mm F5-6.3 DG OS HSM | C + MC-11', #JR (015) + 50487 => 'Sigma 20mm F1.4 DG HSM | A + MC-11', #JR (015) + 50488 => 'Sigma 35mm F1.4 DG HSM | A', #JR (012 + MC-11 or 018) + 50489 => 'Sigma 150-600mm F5-6.3 DG OS HSM | S + MC-11', #JR (014) + 50490 => 'Sigma 120-300mm F2.8 DG OS HSM | S + MC-11', #JR (013) + 50492 => 'Sigma 24-105mm F4 DG OS HSM | A + MC-11', #JR (013) + 50493 => 'Sigma 17-70mm F2.8-4 DC MACRO OS HSM | C + MC-11', #JR (013) + 50495 => 'Sigma 50-100mm F1.8 DC HSM | A + MC-11', #JR (016) + 50499 => 'Sigma 85mm F1.4 DG HSM | A', #JR (018) + 50501 => 'Sigma 100-400mm F5-6.3 DG OS HSM | C + MC-11', #JR (017) + 50503 => 'Sigma 16mm F1.4 DC DN | C', #JR (017) + 50507 => 'Sigma 105mm F1.4 DG HSM | A', #IB (018) + 50508 => 'Sigma 56mm F1.4 DC DN | C', #JR (018) + 50512 => 'Sigma 70-200mm F2.8 DG OS HSM | S', #IB (018) + 50513 => 'Sigma 70mm F2.8 DG MACRO | A', #JR (018) + + 50992 => 'Voigtlander SUPER WIDE-HELIAR 15mm F4.5 III', #JR + 50993 => 'Voigtlander HELIAR-HYPER WIDE 10mm F5.6', #IB + 50994 => 'Voigtlander ULTRA WIDE-HELIAR 12mm F5.6 III', #IB + 50995 => 'Voigtlander MACRO APO-LANTHAR 65mm F2 Aspherical', #JR + 50996 => 'Voigtlander NOKTON 40mm F1.2 Aspherical', #JR + 50997 => 'Voigtlander NOKTON classic 35mm F1.4', #JR + 50998 => 'Voigtlander MACRO APO-LANTHAR 110mm F2.5', #JR + 50999 => 'Voigtlander COLOR-SKOPAR 21mm F3.5 Aspherical', #IB + 51000 => 'Voigtlander NOKTON 50mm F1.2 Aspherical', #JR + + # lenses listed in the Sigma MC-11 list, but not yet seen: + # 504xx => 'Sigma 18-200mm F3.5-6.3 DC MACRO OS HSM | C + MC-11', # (014) + # 504xx => 'Sigma 24mm F1.4 DG HSM | A + MC-11', # (015) + # 504xx => 'Sigma 30mm F1.4 DC HSM | A + MC-11', # (013) + + 51505 => 'Samyang AF 14mm F2.8 FE or Samyang AF 35mm F2.8 FE', #forum3833 + 51505.1 => 'Samyang AF 35mm F2.8 FE', #PH + 51507 => 'Samyang AF 35mm F1.4', #IB +); + +# ExposureProgram values (ref PH, mainly decoded from A200) +my %sonyExposureProgram = ( + 0 => 'Auto', # (same as 'Program AE'?) + 1 => 'Manual', + 2 => 'Program AE', + 3 => 'Aperture-priority AE', + 4 => 'Shutter speed priority AE', + 8 => 'Program Shift A', #7 + 9 => 'Program Shift S', #7 + 16 => 'Portrait', # (A330) + 17 => 'Sports', # (A330) + 18 => 'Sunset', # (A330) + 19 => 'Night Portrait', # (A330) + 20 => 'Landscape', # (A330) + 21 => 'Macro', # (A330) + 35 => 'Auto No Flash', # (A330) +); + +# ExposureProgram values in CameraSettings3 (ref JR) +my %sonyExposureProgram2 = ( # A580 Mode Dial setting: + 1 => 'Program AE', # P + 2 => 'Aperture-priority AE', # A + 3 => 'Shutter speed priority AE', # S + 4 => 'Manual', # M + 5 => 'Cont. Priority AE', # (A35) + 16 => 'Auto', # AUTO + 17 => 'Auto (no flash)', # "flash strike-out" symbol + 18 => 'Auto+', #PH (A33) + 49 => 'Portrait', # SCN + 50 => 'Landscape', # SCN + 51 => 'Macro', # SCN + 52 => 'Sports', # SCN + 53 => 'Sunset', # SCN + 54 => 'Night view', # SCN + 55 => 'Night view/portrait', # SCN + 56 => 'Handheld Night Shot', # SCN (also called "Hand-held Twilight") + 57 => '3D Sweep Panorama', # "Panorama" symbol + 64 => 'Auto 2', #PH (A33 AUTO) + 65 => 'Auto 2 (no flash)', #JR (NC, A35) + 80 => 'Sweep Panorama', # "Panorama" symbol + 96 => 'Anti Motion Blur', #PH (NEX-5) + # 128-138 are A35 picture effects (combined SCN/Picture effect mode dial position) + 128 => 'Toy Camera', + 129 => 'Pop Color', + 130 => 'Posterization', + 131 => 'Posterization B/W', + 132 => 'Retro Photo', + 133 => 'High-key', + 134 => 'Partial Color Red', + 135 => 'Partial Color Green', + 136 => 'Partial Color Blue', + 137 => 'Partial Color Yellow', + 138 => 'High Contrast Monochrome', +); + +# ExposureProgram values in Tags 2010 and 94xx (ref JR) +my %sonyExposureProgram3 = ( + 0 => 'Program AE', + 1 => 'Aperture-priority AE', + 2 => 'Shutter speed priority AE', + 3 => 'Manual', + 4 => 'Auto', + 5 => 'iAuto', + 6 => 'Superior Auto', + 7 => 'iAuto+', + 8 => 'Portrait', + 9 => 'Landscape', + 10 => 'Twilight', + 11 => 'Twilight Portrait', + 12 => 'Sunset', + 14 => 'Action (High speed)', #PH (RX100) + 16 => 'Sports', + 17 => 'Handheld Night Shot', + 18 => 'Anti Motion Blur', + 19 => 'High Sensitivity', + 21 => 'Beach', + 22 => 'Snow', + 23 => 'Fireworks', + 26 => 'Underwater', + 27 => 'Gourmet', + 28 => 'Pet', + 29 => 'Macro', + 30 => 'Backlight Correction HDR', + # 32 => 'Night ... ???', # seen for HDR-CX360E + 33 => 'Sweep Panorama', + 36 => 'Background Defocus', + 37 => 'Soft Skin', + 42 => '3D Image', + 43 => 'Cont. Priority AE', + 45 => 'Document', + 46 => 'Party', +); + +# WhiteBalanceSetting values (ref JR) +my %whiteBalanceSetting = ( + 0x10 => 'Auto (-3)', #(NC) + 0x11 => 'Auto (-2)', #(NC) + 0x12 => 'Auto (-1)', #(NC) + 0x13 => 'Auto (0)', + 0x14 => 'Auto (+1)', #(NC) + 0x15 => 'Auto (+2)', #(NC) + 0x16 => 'Auto (+3)', #(NC) + 0x20 => 'Daylight (-3)', + 0x21 => 'Daylight (-2)', #(NC) + 0x22 => 'Daylight (-1)', #(NC) + 0x23 => 'Daylight (0)', + 0x24 => 'Daylight (+1)', + 0x25 => 'Daylight (+2)', + 0x26 => 'Daylight (+3)', + 0x30 => 'Shade (-3)', #(NC) + 0x31 => 'Shade (-2)', #(NC) + 0x32 => 'Shade (-1)', #(NC) + 0x33 => 'Shade (0)', + 0x34 => 'Shade (+1)', #(NC) + 0x35 => 'Shade (+2)', #(NC) + 0x36 => 'Shade (+3)', + 0x40 => 'Cloudy (-3)', #(NC) + 0x41 => 'Cloudy (-2)', #(NC) + 0x42 => 'Cloudy (-1)', #(NC) + 0x43 => 'Cloudy (0)', + 0x44 => 'Cloudy (+1)', #(NC) + 0x45 => 'Cloudy (+2)', #(NC) + 0x46 => 'Cloudy (+3)', #(NC) + 0x50 => 'Tungsten (-3)', #(NC) + 0x51 => 'Tungsten (-2)', #(NC) + 0x52 => 'Tungsten (-1)', #(NC) + 0x53 => 'Tungsten (0)', + 0x54 => 'Tungsten (+1)', #(NC) + 0x55 => 'Tungsten (+2)', #(NC) + 0x56 => 'Tungsten (+3)', #(NC) + 0x60 => 'Fluorescent (-3)', #(NC) + 0x61 => 'Fluorescent (-2)', #(NC) + 0x62 => 'Fluorescent (-1)', #(NC) + 0x63 => 'Fluorescent (0)', + 0x64 => 'Fluorescent (+1)', #(NC) + 0x65 => 'Fluorescent (+2)', #(NC) + 0x66 => 'Fluorescent (+3)', #(NC) + 0x70 => 'Flash (-3)', #(NC) + 0x71 => 'Flash (-2)', #(NC) + 0x72 => 'Flash (-1)', #(NC) + 0x73 => 'Flash (0)', + 0x74 => 'Flash (+1)', #(NC) + 0x75 => 'Flash (+2)', #(NC) + 0x76 => 'Flash (+3)', #(NC) + 0xa3 => 'Custom', + 0xf3 => 'Color Temperature/Color Filter', +); + +# AF points for cameras with 15-point AF (ref JR) +my %afPoint15 = ( + 0 => 'Upper-left', + 1 => 'Left', + 2 => 'Lower-left', + 3 => 'Far Left', + 4 => 'Top (horizontal)', + 5 => 'Near Right', + 6 => 'Center (horizontal)', + 7 => 'Near Left', + 8 => 'Bottom (horizontal)', + 9 => 'Top (vertical)', + 10 => 'Center (vertical)', + 11 => 'Bottom (vertical)', + 12 => 'Far Right', + 13 => 'Upper-right', + 14 => 'Right', + 15 => 'Lower-right', + 16 => 'Upper-middle', + 17 => 'Lower-middle', +); + +# AF points for cameras with 19-point AF (ref PH) +# (verified for A77 firmware 1.07) +my %afPoint19 = ( + 0 => 'Upper Far Left', + 1 => 'Upper-left (horizontal)', + 2 => 'Far Left (horizontal)', + 3 => 'Left (horizontal)', + 4 => 'Lower Far Left', + 5 => 'Lower-left (horizontal)', + 6 => 'Upper-left (vertical)', + 7 => 'Left (vertical)', + 8 => 'Lower-left (vertical)', + 9 => 'Far Left (vertical)', + 10 => 'Top (horizontal)', + 11 => 'Near Right', + 12 => 'Center (horizontal)', + 13 => 'Near Left', + 14 => 'Bottom (horizontal)', + 15 => 'Top (vertical)', + 16 => 'Upper-middle', + 17 => 'Center (vertical)', + 18 => 'Lower-middle', + 19 => 'Bottom (vertical)', + 20 => 'Upper Far Right', + 21 => 'Upper-right (horizontal)', + 22 => 'Far Right (horizontal)', + 23 => 'Right (horizontal)', + 24 => 'Lower Far Right', + 25 => 'Lower-right (horizontal)', + 26 => 'Far Right (vertical)', + 27 => 'Upper-right (vertical)', + 28 => 'Right (vertical)', + 29 => 'Lower-right (vertical)', +); + +# 79 AF point layout and indices for ILCA-68/77M2, numbered 0-78 for direct look-up from BITMASK in 0x2020, +# E6 = Center (ref JR) +my %afPoints79 = ( + 0=>'A5', 1=>'A6', 2=>'A7', + 3=>'B2', 4=>'B3', 5=>'B4', 6=>'B5', 7=>'B6', 8=>'B7', 9=>'B8', 10=>'B9', 11=>'B10', + 12=>'C1', 13=>'C2', 14=>'C3', 15=>'C4', 16=>'C5', 17=>'C6', 18=>'C7', 19=>'C8', 20=>'C9', 21=>'C10', 22=>'C11', + 23=>'D1', 24=>'D2', 25=>'D3', 26=>'D4', 27=>'D5', 28=>'D6', 29=>'D7', 30=>'D8', 31=>'D9', 32=>'D10', 33=>'D11', + 34=>'E1', 35=>'E2', 36=>'E3', 37=>'E4', 38=>'E5', 39=>'E6', 40=>'E7', 41=>'E8', 42=>'E9', 43=>'E10', 44=>'E11', + 45=>'F1', 46=>'F2', 47=>'F3', 48=>'F4', 49=>'F5', 50=>'F6', 51=>'F7', 52=>'F8', 53=>'F9', 54=>'F10', 55=>'F11', + 56=>'G1', 57=>'G2', 58=>'G3', 59=>'G4', 60=>'G5', 61=>'G6', 62=>'G7', 63=>'G8', 64=>'G9', 65=>'G10', 66=>'G11', + 67=>'H2', 68=>'H3', 69=>'H4', 70=>'H5', 71=>'H6', 72=>'H7', 73=>'H8', 74=>'H9', 75=>'H10', + 76=>'I5', 77=>'I6', 78=>'I7', +); + +# AFPoint and AFStatus tags in AFInfo(Tag940e) use numbers 0 to 94 for the 79 positions + 15 cross + 1 F2.8 +my %afPoints79_940e = ( + 59=>'A5', 50=>'A6', 41=>'A7', + 14=>'B2', 7=>'B3', 0=>'B4', 60=>'B5', 51=>'B6', 42=>'B7', 87=>'B8', 80=>'B9', 73=>'B10', + 21=>'C1', 15=>'C2', 8=>'C3', 1=>'C4', 61=>'C5', 52=>'C6', 43=>'C7', 88=>'C8', 81=>'C9', 74=>'C10', 68=>'C11', + 22=>'D1', 16=>'D2', 9=>'D3', 2=>'D4', 62=>'D5', 53=>'D6', 44=>'D7', 89=>'D8', 82=>'D9', 75=>'D10', 69=>'D11', + 23=>'E1', 17=>'E2', 10=>'E3', 3=>'E4', 63=>'E5', 54=>'E6 Center', 45=>'E7', 90=>'E8', 83=>'E9', 76=>'E10', 70=>'E11', + 24=>'F1', 18=>'F2', 11=>'F3', 4=>'F4', 64=>'F5', 55=>'F6', 46=>'F7', 91=>'F8', 84=>'F9', 77=>'F10', 71=>'F11', + 25=>'G1', 19=>'G2', 12=>'G3', 5=>'G4', 65=>'G5', 56=>'G6', 47=>'G7', 92=>'G8', 85=>'G9', 78=>'G10', 72=>'G11', + 20=>'H2', 13=>'H3', 6=>'H4', 66=>'H5', 57=>'H6', 48=>'H7', 93=>'H8', 86=>'H9', 79=>'H10', + 67=>'I5', 58=>'I6', 49=>'I7', + + 28=>'A5 Vertical', 27=>'A6 Vertical', 26=>'A7 Vertical', + 31=>'C5 Vertical', 30=>'C6 Vertical', 29=>'C7 Vertical', + 34=>'E5 Vertical', 33=>'E6 Center Vertical', 32=>'E7 Vertical', + 37=>'G5 Vertical', 36=>'G6 Vertical', 35=>'G7 Vertical', + 40=>'I5 Vertical', 39=>'I6 Vertical', 38=>'I7 Vertical', + + 94=>'E6 Center F2.8', +); + +# ILCA-99M2 has dedicated 79 point Phase Detection AF sensor with similar layout as ILCA-68 and ILCA-77M2. +# ILCA-99M2 has also 399 Focal Plane Phase-Detection AF Points in 19 rows of 21 points, same as ILCE-7RM2. +# Of these 399 points, 323 points are selectable: 19 rows of 17 points (2 left-most and right-most columns not selectable). +# The 79 Focal Plane points that overlap with the 79 points of the dedicated sensor provide for Hybrid Phase AF Points. +# Tag 0x201e gives value 162 for the Center AF point, and 162 is exactly the center of 323 points... +# The below table lists the selectable AF points that correspond to the 79 points of the dedicated sensor. (ref JR) +my %afPoints99M2 = ( + 93=>'A5 (93)', 94=>'A6 (94)', 95=>'A7 (95)', + 106=>'B2 (106)', 107=>'B3 (107)', 108=>'B4 (108)', 110=>'B5 (110)', 111=>'B6 (111)', 112=>'B7 (112)', 114=>'B8 (114)', 115=>'B9 (115)', 116=>'B10 (116)', + 122=>'C1 (122)', 123=>'C2 (123)', 124=>'C3 (124)', 125=>'C4 (125)', 127=>'C5 (127)', 128=>'C6 (128)', 129=>'C7 (129)', 131=>'C8 (131)', 132=>'C9 (132)', 133=>'C10 (133)', 134=>'C11 (134)', + 139=>'D1 (139)', 140=>'D2 (140)', 141=>'D3 (141)', 142=>'D4 (142)', 144=>'D5 (144)', 145=>'D6 (145)', 146=>'D7 (146)', 148=>'D8 (148)', 149=>'D9 (149)', 150=>'D10 (150)', 151=>'D11 (151)', + 156=>'E1 (156)', 157=>'E2 (157)', 158=>'E3 (158)', 159=>'E4 (159)', 161=>'E5 (161)', 162=>'E6 (162)', 163=>'E7 (163)', 165=>'E8 (165)', 166=>'E9 (166)', 167=>'E10 (167)', 168=>'E11 (168)', + 173=>'F1 (173)', 174=>'F2 (174)', 175=>'F3 (175)', 176=>'F4 (176)', 178=>'F5 (178)', 179=>'F6 (179)', 180=>'F7 (180)', 182=>'F8 (182)', 183=>'F9 (183)', 184=>'F10 (184)', 185=>'F11 (185)', + 190=>'G1 (190)', 191=>'G2 (191)', 192=>'G3 (192)', 193=>'G4 (193)', 195=>'G5 (195)', 196=>'G6 (196)', 197=>'G7 (197)', 199=>'G8 (199)', 200=>'G9 (200)', 201=>'G10 (201)', 202=>'G11 (202)', + 208=>'H2 (208)', 209=>'H3 (209)', 210=>'H4 (210)', 212=>'H5 (212)', 213=>'H6 (213)', 214=>'H7 (214)', 216=>'H8 (216)', 217=>'H9 (217)', 218=>'H10 (218)', + 229=>'I5 (229)', 230=>'I6 (230)', 231=>'I7 (231)', +); + +my %binaryDataAttrs = ( + PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData, + WRITE_PROC => \&Image::ExifTool::WriteBinaryData, + CHECK_PROC => \&Image::ExifTool::CheckBinaryData, + WRITABLE => 1, + FIRST_ENTRY => 0, +); + +# tagInfo attributes for unknown cipher block tags +my %unknownCipherData = ( + Unknown => 1, # require Unknown option + Hidden => 1, # doesn't appear in Tag Name documentation + RawConv => sub { Decipher(\$_[0]); return $_[0] }, + ValueConv => 'PrintHex($val)', # print as hex + PrintConv => 'length($val) > 65 ? substr($val,0,60) . "[...]" : $val', # limit length +); + +my %meterInfo1 = ( + Format => 'int32u[27]', + PrintConv => 'sprintf("%19d %4d %6d" . " %3d %4d %6d" x 8, split(" ",$val))', + PrintConvInv => '$val', +); +my %meterInfo2 = ( + Format => 'int32u[33]', + PrintConv => 'sprintf("%3d %4d %6d" . " %3d %4d %6d" x 10, split(" ",$val))', + PrintConvInv => '$val', +); +my %meterInfo1b = ( + Format => 'undef[90]', + ValueConv => \&ConvMeter1, + PrintConv => 'sprintf("%19d %4d %6d" . " %3d %4d %6d" x 8, split(" ",$val))', +); +my %meterInfo2b = ( + Format => 'undef[110]', + ValueConv => \&ConvMeter2, + PrintConv => 'sprintf("%3d %4d %6d" . " %3d %4d %6d" x 10, split(" ",$val))', +); + +my %hidUnk = ( Hidden => 1, Unknown => 1 ); + +# Sony maker notes tags (some elements in common with %Image::ExifTool::Minolta::Main) +%Image::ExifTool::Sony::Main = ( + WRITE_PROC => \&Image::ExifTool::Exif::WriteExif, + CHECK_PROC => \&Image::ExifTool::Exif::CheckExif, + GROUPS => { 0 => 'MakerNotes', 2 => 'Camera' }, + NOTES => q{ + The following information has been decoded from the MakerNotes of Sony + cameras. Some of these tags have been inherited from the Minolta + MakerNotes. + }, + 0x0010 => [ #PH + # appears to contain mostly AF related information; + # for SLT-A77V and newer, similar info is found in 0x940e AFInfo" (ref JR) + { + Name => 'CameraInfo', + # count: A700=368, A850/A900=5478 + Condition => '$count == 368 or $count == 5478', + SubDirectory => { + TagTable => 'Image::ExifTool::Sony::CameraInfo', + ByteOrder => 'BigEndian', + }, + },{ + Name => 'CameraInfo2', + # count: A200/A300/A350=5506, A230/A290/A330/A380/A390=6118 + Condition => '$count == 5506 or $count == 6118', + SubDirectory => { + TagTable => 'Image::ExifTool::Sony::CameraInfo2', + ByteOrder => 'LittleEndian', + }, + },{ + Name => 'CameraInfo3', + # count: A33/A35/A55V/A450/A500/A550/A560/A580/NEX3/5/5C/C3/VG10E=15360 + Condition => '$count == 15360', + SubDirectory => { + TagTable => 'Image::ExifTool::Sony::CameraInfo3', + ByteOrder => 'LittleEndian', + }, + },{ + Name => 'CameraInfoUnknown', + SubDirectory => { TagTable => 'Image::ExifTool::Sony::CameraInfoUnknown' }, + }, + ], + # 0x0018 - starts with "GYRO" for sweep panorama images (ref JR) + # - contains ImageStabilization information for Minolta + 0x0020 => [ + # similar to WBInfoA100 in Minolta.pm. + # appears to contain various types of information, as in MoreInfo. (ref JR) + { + Name => 'FocusInfo', #PH + # count: A200/A230/A290/A300/A330/A350/A380/A390==19154, A700/A850/A900=19148 + Condition => '$count == 19154 or $count == 19148', + SubDirectory => { + TagTable => 'Image::ExifTool::Sony::FocusInfo', + ByteOrder => 'LittleEndian', + }, + },{ + Name => 'MoreInfo', #JR + # count: A450/A500/A550/A560/A580/A33/A35/A55/NEX-3/5/C3/VG10E==20480 + SubDirectory => { + TagTable => 'Image::ExifTool::Sony::MoreInfo', + ByteOrder => 'LittleEndian', + }, + }, + ], + 0x0102 => { #5/JD + Name => 'Quality', + Writable => 'int32u', + PrintConv => { + 0 => 'RAW', + 1 => 'Super Fine', + 2 => 'Fine', + 3 => 'Standard', + 4 => 'Economy', + 5 => 'Extra Fine', + 6 => 'RAW + JPEG', + 7 => 'Compressed RAW', + 8 => 'Compressed RAW + JPEG', + 0xffffffff => 'n/a', #PH (SLT-A57 panorama) + }, + }, + 0x0104 => { #5/JD + Name => 'FlashExposureComp', + Description => 'Flash Exposure Compensation', + Writable => 'rational64s', + }, + 0x0105 => { #5/JD (models since mid-2014, ILCA-77M2, ILCE-7M2/7RM2/7SM2, do not report this tag anymore, ref JR) + Name => 'Teleconverter', + Writable => 'int32u', + PrintHex => 1, + PrintConv => \%Image::ExifTool::Minolta::minoltaTeleconverters, + }, + 0x0112 => { #JD + Name => 'WhiteBalanceFineTune', + Format => 'int32s', + Writable => 'int32u', + }, + 0x0114 => [ #PH + { + Name => 'CameraSettings', + # count: A200/A300/A350/A700=280, A850/A900=364 + Condition => '$count == 280 or $count == 364', + SubDirectory => { + TagTable => 'Image::ExifTool::Sony::CameraSettings', + ByteOrder => 'BigEndian', + }, + },{ + Name => 'CameraSettings2', + # count: A230/A290/A330/A380/A390=332 + Condition => '$count == 332', + SubDirectory => { + TagTable => 'Image::ExifTool::Sony::CameraSettings2', + ByteOrder => 'BigEndian', + }, + },{ + Name => 'CameraSettings3', + # count: A560/A580/A33/A35/A55/NEX3/5/5C/C3/VG10E=1536, A450/A500/A550=2048 + Condition => '$count == 1536 || $count == 2048', + SubDirectory => { + TagTable => 'Image::ExifTool::Sony::CameraSettings3', + ByteOrder => 'LittleEndian', + }, + },{ + Name => 'CameraSettingsUnknown', + SubDirectory => { + TagTable => 'Image::ExifTool::Sony::CameraSettingsUnknown', + ByteOrder => 'BigEndian', + }, + }, + ], + 0x0115 => { #JD + Name => 'WhiteBalance', + Writable => 'int32u', + Priority => 2, # (more reliable for the RX100) + PrintHex => 1, + PrintConv => { + 0x00 => 'Auto', + 0x01 => 'Color Temperature/Color Filter', + 0x10 => 'Daylight', + 0x20 => 'Cloudy', + 0x30 => 'Shade', + 0x40 => 'Tungsten', + 0x50 => 'Flash', + 0x60 => 'Fluorescent', + 0x70 => 'Custom', + 0x80 => 'Underwater', + }, + }, + # Tag 0x0116: extra hardware info (ref JR) + # (tag not present for A100, A200, A300, A350, A700, nor for A37, A57, A65, A77) + 0x0116 => [ #JR + { + Name => 'ExtraInfo', + Condition => '$$self{Model} =~ /^DSLR-A(850|900)\b/', + SubDirectory => { + TagTable => 'Image::ExifTool::Sony::ExtraInfo', + ByteOrder => 'BigEndian', + }, + },{ + Name => 'ExtraInfo2', + Condition => '$$self{Model} =~ /^DSLR-A(230|290|330|380|390)\b/', + SubDirectory => { TagTable => 'Image::ExifTool::Sony::ExtraInfo2' }, + },{ + Name => 'ExtraInfo3', + # for DSLR-A450/500/550/560/580, SLT-A33/35/55 and NEX-3/5/5C. + SubDirectory => { TagTable => 'Image::ExifTool::Sony::ExtraInfo3' }, + } + ], + 0x0e00 => { + Name => 'PrintIM', + Description => 'Print Image Matching', + SubDirectory => { TagTable => 'Image::ExifTool::PrintIM::Main' }, + }, + # the next 3 tags have a different meaning for some models (with format int32u) + 0x1000 => { #9 (F88, multi burst mode only) + Name => 'MultiBurstMode', + Condition => '$format eq "undef"', + Notes => 'MultiBurst tags valid only for models with this feature, like the F88', + Writable => 'undef', + Format => 'int8u', + PrintConv => { 0 => 'Off', 1 => 'On' }, + }, + 0x1001 => { #9 (F88, multi burst mode only) + Name => 'MultiBurstImageWidth', + Condition => '$format eq "int16u"', + Writable => 'int16u', + }, + 0x1002 => { #9 (F88, multi burst mode only) + Name => 'MultiBurstImageHeight', + Condition => '$format eq "int16u"', + Writable => 'int16u', + }, + 0x1003 => { #9 (64 bytes, contains Panorama info for various DSC, NEX, SLT and DSLR models) + Name => 'Panorama', + # panorama: first 4 bytes '1 1 0 0' (little-endian) or '0 0 1 1' (big-endian) + # non-panorama: all bytes are '0' (ref JR) + Condition => '$$self{Panorama} = ($$valPt =~ /^(\0\0)?\x01\x01/)', # (little- or big-endian int32u = 257) + SubDirectory => { TagTable => 'Image::ExifTool::Sony::Panorama' }, + }, + # 0x2000 - undef[1] + 0x2001 => { #PH (JPEG images from all DSLR's except the A100) + Name => 'PreviewImage', + Groups => { 2 => 'Preview' }, + Writable => 'undef', + DataTag => 'PreviewImage', + Notes => 'HD-size preview in JPEG images from almost all DSLR/SLT/ILCA/NEX/ILCE.', + # Note: the preview data starts with a 32-byte proprietary Sony header + # first 8 bytes after 32-byte header: + # \x00\xd8\xff\xe1\x00\x27\xff\xff for JPEG files from A33/35/55V/450/500/550/560/580, NEX-3/5/5C/C3/VG10 + # \x00\xd8\xff\xdb\x00\x84\x00\x01 for JPEG files from all other models + # ( \xff\xd8\xff\xdb\x00\x84\x00\x01 corresponding bytes for all ARW files ) + # + # DSLR-A700/A850/A900 and DSLR-A200/A300/A350: + # - no MPImage2 + # DSLR-A230/A290/A330/A380/A390: + # - PreviewImage start-offset is at 110 bytes inside MPImage2 + # DSLR-A450/A500/A550/A560/A580, SLT-A33/A35/A55V, NEX-3/5/5C/C3/VG10/VG10E: + # - PreviewImage start-offset is at 106 bytes inside MPImage2 + # - different first bytes after 32-byte header + # SLT-A37/A57/A58/A65V/A77V/A99V, ILCA-77M2, NEX-3N/5N/5R/5T/6/7/F3, ILCE-3000/3500/5000/6000/7/7R/7S: + # - PreviewImage start-offset is at 130 bytes inside MPImage2 + # NEX-VG20E/VG30E/VG900, ILCE-QX1: 0x2001 not present + # ILCE-5100/ILCE-7M2/7RM2/7SM2 : 0x2001 present but Size 0 and Offset 0 + # + WriteCheck => 'return $val=~/^(none|.{32}\xff\xd8\xff)/s ? undef : "Not a valid image"', + RawConv => q{ + return \$val if $val =~ /^Binary/; + $val = substr($val,0x20) if length($val) > 0x20; +# return \$val if $val =~ s/^.(\xd8\xff\xdb)/\xff$1/s; + return \$val if $val =~ s/^.(\xd8\xff[\xdb\xe1])/\xff$1/s; + $$self{PreviewError} = 1 unless $val eq 'none' or $val eq ''; + return undef; + }, + # must construct 0x20-byte header which contains length, width and height + ValueConvInv => q{ + return 'none' unless $val; + my $e = new Image::ExifTool; + my $info = $e->ImageInfo(\$val,'ImageWidth','ImageHeight'); + return undef unless $$info{ImageWidth} and $$info{ImageHeight}; + my $size = Set32u($$info{ImageWidth}) . Set32u($$info{ImageHeight}); + return Set32u(length $val) . $size . ("\0" x 8) . $size . ("\0" x 4) . $val; + }, + }, + 0x2002 => { #JR (written by Sony IDC) + Name => 'Rating', + Writable => 'int32u', # (0-5 stars) (4294967295 for an HX9V iSweep Panorama, ref JR) + }, + # 0x2003 - string[256]: all 0 for DSLR, SLT, NEX; data for DSC-HX9V + 0x2004 => { #PH (NEX-5) + Name => 'Contrast', + Writable => 'int32s', + PrintConv => '$val > 0 ? "+$val" : $val', + PrintConvInv => '$val', + }, + 0x2005 => { #PH (NEX-5) + Name => 'Saturation', + Writable => 'int32s', + PrintConv => '$val > 0 ? "+$val" : $val', + PrintConvInv => '$val', + }, + 0x2006 => { #PH + Name => 'Sharpness', + Writable => 'int32s', + PrintConv => '$val > 0 ? "+$val" : $val', + PrintConvInv => '$val', + }, + 0x2007 => { #PH + Name => 'Brightness', + Writable => 'int32s', + PrintConv => '$val > 0 ? "+$val" : $val', + PrintConvInv => '$val', + }, + 0x2008 => { #PH + Name => 'LongExposureNoiseReduction', + Writable => 'int32u', + PrintHex => 1, + PrintConv => { + 0 => 'Off', + 1 => 'On (unused)', + 0x10001 => 'On (dark subtracted)', # (NEX-C3) + 0xffff0000 => 'Off (65535)', + 0xffff0001 => 'On (65535)', + 0xffffffff => 'n/a', + }, + }, + 0x2009 => { #PH + Name => 'HighISONoiseReduction', + Writable => 'int16u', + PrintConv => { + 0 => 'Off', + 1 => 'Low', + 2 => 'Normal', + 3 => 'High', + 256 => 'Auto', + # it seems that all DSC models except DSC-RX models give n/a here (ref JR) + 65535 => 'n/a', + }, + }, + 0x200a => { #PH (A550) + Name => 'HDR', + Writable => 'int32u', + Format => 'int16u', + Count => 2, + Notes => 'stored as a 32-bit integer, but read as two 16-bit integers', + PrintHex => 1, + PrintConv => [{ + 0x0 => 'Off', + 0x01 => 'Auto', + 0x10 => '1.0 EV', + 0x11 => '1.5 EV', + 0x12 => '2.0 EV', + 0x13 => '2.5 EV', + 0x14 => '3.0 EV', + 0x15 => '3.5 EV', + 0x16 => '4.0 EV', + 0x17 => '4.5 EV', + 0x18 => '5.0 EV', + 0x19 => '5.5 EV', + 0x1a => '6.0 EV', + },{ #JR (A580) + 0 => 'Uncorrected image', # A580 stores 2 images: uncorrected and HDR + 1 => 'HDR image (good)', + 2 => 'HDR image (fail 1)', # alignment problem? + 3 => 'HDR image (fail 2)', # contrast problem? + }], + }, + 0x200b => { #PH + Name => 'MultiFrameNoiseReduction', + Writable => 'int32u', + Notes => 'may not be valid for RS100', # (RS100 sample was 0 when this feature was turned on) + PrintConv => { + 0 => 'Off', + 1 => 'On', + 255 => 'n/a', + }, + }, + # 0x200c - int32u[3]: '0 0 0'; seen '2 1 0' for HX9V 3D-Image (in both JPG and MPO image) + # 0x200d - rational64u: 10/10, seen 2.5 for DSC-TX300V, 8 for DSC-HX100V/RX10 + 0x200e => { #PH (HX20V) + Name => 'PictureEffect', + Writable => 'int16u', + PrintConv => { + 0 => 'Off', + 1 => 'Toy Camera', #JR (A35) + 2 => 'Pop Color', # (also A35/NEX-C3, ref JR) + 3 => 'Posterization', #JR (A35) + 4 => 'Posterization B/W', #JR (A35) + 5 => 'Retro Photo', #JR (A35, NEX-5) + 6 => 'Soft High Key', # (also A65V, A35/NEX-C3 call this "High-key", ref JR) + 7 => 'Partial Color (red)', #JR (A35) + 8 => 'Partial Color (green)', #JR (A35, NEX-5) + 9 => 'Partial Color (blue)', #JR (A35) + 10 => 'Partial Color (yellow)', #JR (A35, NEX-5) + 13 => 'High Contrast Monochrome', #JR (A35) + 16 => 'Toy Camera (normal)', # (also A65, ref JR) + 17 => 'Toy Camera (cool)', # (RX100) + 18 => 'Toy Camera (warm)', # (RX100) + 19 => 'Toy Camera (green)', # (RX100) + 20 => 'Toy Camera (magenta)', # (RX100) + 32 => 'Soft Focus (low)', #JR (RX100) + 33 => 'Soft Focus', #JR (A65V) + 34 => 'Soft Focus (high)', # (RX100) + 48 => 'Miniature (auto)', #JR (A65V/NEX-7, horizontal) + 49 => 'Miniature (top)', # (RX100) + 50 => 'Miniature (middle horizontal)', # (WX100/HX20V, horizontal) + 51 => 'Miniature (bottom)', # (WX100, rotate 90 CW) + 52 => 'Miniature (left)', # (RX100) + 53 => 'Miniature (middle vertical)', # (RX100) + 54 => 'Miniature (right)', # (RX100) + 64 => 'HDR Painting (low)', # (RX100) + 65 => 'HDR Painting', # (also A65V, ref JR) + 66 => 'HDR Painting (high)', # (RX100) + 80 => 'Rich-tone Monochrome', # (also A65V, ref JR) + 97 => 'Water Color', # (HX200V) + 98 => 'Water Color 2', + 112 => 'Illustration (low)', # (RX100) + 113 => 'Illustration', # (RX100) + 114 => 'Illustration (high)', # (RX100) + }, + }, + 0x200f => { #PH (RX100) + Name => 'SoftSkinEffect', + Writable => 'int32u', + PrintConv => { + 0 => 'Off', + 1 => 'Low', + 2 => 'Mid', + 3 => 'High', + # 0x10001 - seen (ref JR) + # 0x10002 - seen for landscape and portrait flash (ref JR) + # 0x10003 - seen (ref JR) + 0xffffffff => 'n/a', # (A35) + }, + }, + 0x2010 => [ #JR + # different camera models have similar content but at different offsets, appears to correlate with: + # 0x1206 - 0x1207 deciphered (0x1205 changes with firmware version): + # ad c3 - NEX-5N + # 0x0192 - 0x0193 deciphered (0x0191 changes with firmware version): + # 91 c3 - NEX-VG20E + # 93 c3 - NEX-7, SLT-A65V/A77V + # 94 c3 - Hasselblad Lunar + # 0x0012 - 0x0013 deciphered (0x0011 changes with firmware version): + # 94 c3 - SLT-A37/A57, NEX-F3 + # 95 d3 - DSC-WX50, WX70 + # 98 c3 - DSC-HX200V, HX20V, HX30V, TX200V, TX300V + # 98 d3 - DSC-HX10V, TX66, WX100, WX150 + # 9a c3 - DSC-RX1, RX1R + # 9b c3 - SLT-A99V, Hasselblad HV + # 9c c3 - NEX-VG30E + # 9d c3 - DSC-RX100, Hasselblad Stellar + # 9e c3 - NEX-VG900, SLT-A58 + # a1 d3 - DSC-TX30 + # a2 d3 - DSC-WX60, WX80, WX200, WX300 + # a3 c3 - NEX-6, DSC-HX300, HX50V + # a4 c3 - NEX-3N/5R/5T, ILCE-3000/3500 + # unknown offsets or values for DSC-TX20/TX55/WX30 + # unknown offsets or values for DSC-HX60V/HX350/HX400V/QX10/QX30/QX100/RX10/RX100M2/RX100M3/WX220/WX350, + # ILCA-68/77M2, ILCE-5000/5100/6000/7/7M2/7R/7S/QX1, Stellar2, Lusso + # unknown offsets or values for DSC-HX80/HX90V/RX0/RX1RM2/RX10M2/RX10M3/RX100M4/RX100M5/WX500, ILCE-6300/6500/7RM2/7SM2, ILCA-99M2 + # unknown offsets or values for ILCE-6400/7M3/7RM3/9, DSC-RX10M4/RX100M6/RX100M5A/HX99 + { + Name => 'Tag2010a', # ad + Condition => '$$self{Model} =~ /^NEX-5N$/', + SubDirectory => { TagTable => 'Image::ExifTool::Sony::Tag2010a' }, + },{ + Name => 'Tag2010b', # 91, 93 + Condition => '$$self{Model} =~ /^(SLT-A(65|77)V?|NEX-(7|VG20E)|Lunar)$/', + SubDirectory => { TagTable => 'Image::ExifTool::Sony::Tag2010b' }, + },{ + Name => 'Tag2010c', # 94 + Condition => '$$self{Model} =~ /^(SLT-A(37|57)|NEX-F3)$/', + SubDirectory => { TagTable => 'Image::ExifTool::Sony::Tag2010c' }, + },{ + Name => 'Tag2010d', # 95, 98 + Condition => q{ + $$self{Model} =~ /^(DSC-(HX10V|HX20V|HX30V|HX200V|TX66|TX200V|TX300V|WX50|WX70|WX100|WX150))$/ and + not $$self{Panorama} + }, + SubDirectory => { TagTable => 'Image::ExifTool::Sony::Tag2010d' }, + },{ + Name => 'Tag2010e', # 9a, 9b, 9c, 9d, 9e, a1, a2, a3, a4 + Condition => q{ + $$self{Model} =~ /^(SLT-A99V?|HV|SLT-A58|ILCE-(3000|3500)|NEX-(3N|5R|5T|6|VG900|VG30E)|DSC-(RX100|RX1|RX1R)|Stellar)$/ or + ($$self{Model} =~ /^(DSC-(HX300|HX50|HX50V|TX30|WX60|WX80|WX200|WX300))$/ and not $$self{Panorama}) + }, + SubDirectory => { TagTable => 'Image::ExifTool::Sony::Tag2010e' }, + },{ + Name => 'Tag2010f', # ? + Condition => '$$self{Model} =~ /^(DSC-(RX100M2|QX10|QX100))$/', + SubDirectory => { TagTable => 'Image::ExifTool::Sony::Tag2010f' }, + },{ + Name => 'Tag2010g', # ? + Condition => '$$self{Model} =~ /^(DSC-(QX30|RX10|RX100M3|HX60V|HX350|HX400V|WX220|WX350)|ILCE-(7(R|S|M2)?|[56]000|5100|QX1)|ILCA-(68|77M2))\b/', + SubDirectory => { TagTable => 'Image::ExifTool::Sony::Tag2010g' }, + },{ + Name => 'Tag2010h', # ? + Condition => '$$self{Model} =~ /^(DSC-(RX0|RX1RM2|RX10M2|RX10M3|RX100M4|RX100M5|HX80|HX90V?|WX500)|ILCE-(6300|6500|7RM2|7SM2)|ILCA-99M2)\b/', + SubDirectory => { TagTable => 'Image::ExifTool::Sony::Tag2010h' }, + },{ + Name => 'Tag2010i', # ? + Condition => '$$self{Model} =~ /^(ILCE-(6400|7M3|7RM3|9)|DSC-(RX10M4|RX100M6|RX100M5A|HX99))\b/', + SubDirectory => { TagTable => 'Image::ExifTool::Sony::Tag2010i' }, + },{ + Name => 'Tag_0x2010', + %unknownCipherData, + }], + 0x2011 => { #PH (A77, NEX-5N) + Name => 'VignettingCorrection', + Writable => 'int32u', + PrintConv => { + 0 => 'Off', + 2 => 'Auto', + 0xffffffff => 'n/a', # (RX100) + }, + }, + 0x2012 => { #PH (A77, NEX-5N) + Name => 'LateralChromaticAberration', + Writable => 'int32u', + PrintConv => { + 0 => 'Off', + 2 => 'Auto', + 0xffffffff => 'n/a', # (RX100) + }, + }, + 0x2013 => { #PH (A77, NEX-5N) ("Setting"; application of such correction is indicated in Tag9405 - ref JR) + Name => 'DistortionCorrectionSetting', + Writable => 'int32u', + PrintConv => { + 0 => 'Off', + 2 => 'Auto', + 0xffffffff => 'n/a', # (RX100) + }, + }, + 0x2014 => { #JR/9 + Name => 'WBShiftAB_GM', + Writable => 'int32s', + Count => 2, + Notes => q{ + 2 numbers: 1. positive is a shift toward amber, 2. positive is a shift + toward magenta + }, + }, + # 0x2015 - int16u: 65535, also for 'normal' HDR images; 0 for HDR-paint and Rich-tone Monochrome effect images + 0x2016 => { #PH (RX100) + Name => 'AutoPortraitFramed', + Writable => 'int16u', + Notes => '"Yes" if this image was created by the Auto Portrait Framing feature', + PrintConv => { 0 => 'No', 1 => 'Yes' }, + }, + # 0x2017 - int32u: flash mode. 0=off, 1=fired, 2=red-eye (PH, NEX-6) (also in A99, RX1, NEX-5R) + 0x2017 => { #JR + Name => 'FlashAction', + Writable => 'int32u', + PrintConv => { + 0 => 'Did not fire', + 1 => 'Flash Fired', + 2 => 'External Flash Fired', + 3 => 'Wireless Controlled Flash Fired', # (NC) seen for ILCE-9 and ILCE-7M3 images + }, + }, + # 0x2018 - something with external flash: seen 1 only when 0x2017 = 2 + # 0x2019 - 0 or 1 (seen 1 for ILCA-77M2, ILCE-7M2/7RM2) + # 0x201a - 0 or 1 + 0x201a => { #JR + Name => 'ElectronicFrontCurtainShutter', + Writable => 'int32u', + PrintConv => { + 0 => 'Off', + 1 => 'On', + }, + }, + 0x201b => { #PH + # FocusMode for SLT/HV/ILCA and NEX/ILCE; doesn't seem to apply to DSC models (always 0) + # from 2018: at least DSC-RX10M4 and RX100M6 also use this tag + Name => 'FocusMode', + Condition => '($$self{Model} !~ /^DSC-/) or ($$self{Model} =~ /^DSC-(RX10M4|RX100M6|RX100M5A|HX99)/)', + Writable => 'int8u', + Priority => 0, + PrintConv => { + 0 => 'Manual', + 2 => 'AF-S', + 3 => 'AF-C', + 4 => 'AF-A', + 6 => 'DMF', # "Direct Manual Focus" + 7 => 'AF-D', # "Depth Map Assist Continuous AF" + }, + }, + 0x201c => [ #JR + # AFAreaModeSetting for SLT/HV/ILCA and NEX/ILCE; doesn't seem to apply to DSC models (always 0) + # from 2018: at least DSC-RX10M4 and RX100M6 also use this tag + # all DSLR/SLT/HV Wide Zone Spot Local + # all NEX and ILCE-3000 Multi Center FlexibleSpot + # all ILCE and ILCA Wide Zone Center FlexibleSpot ExpandedFlexibleSpot + # (actual AFAreaMode used may be different as camera can override this under certain conditions) + { + Name => 'AFAreaModeSetting', + Condition => '$$self{Model} =~ /^(SLT-|HV)/', + Notes => 'SLT models', + Writable => 'int8u', + PrintConv => { + 0 => 'Wide', + 4 => 'Local', + 8 => 'Zone', #PH + 9 => 'Spot', + }, + },{ + Name => 'AFAreaModeSetting', + Condition => '$$self{Model} =~ /^(NEX-|ILCE-|DSC-(RX10M4|RX100M6|RX100M5A|HX99))/', + Notes => 'NEX, ILCE and some DSC models', + RawConv => '$$self{AFAreaILCE} = $val', + DataMember => 'AFAreaILCE', + Writable => 'int8u', + PrintConv => { + 0 => 'Wide', # all NEX and ILCE-3000/3500 use the name 'Multi' + 1 => 'Center', + 3 => 'Flexible Spot', + 4 => 'Flexible Spot (LA-EA4)', # seen for ILCE-7RM2 with LA-EA4 + 9 => 'Center (LA-EA4)', # seen for ILCE-7RM2 with LA-EA4 + 11 => 'Zone', + 12 => 'Expanded Flexible Spot', + }, + },{ + Name => 'AFAreaModeSetting', + Condition => '$$self{Model} =~ /^ILCA-/', + Notes => 'ILCA models', + RawConv => '$$self{AFAreaILCA} = $val', + DataMember => 'AFAreaILCA', + Writable => 'int8u', + PrintConv => { + 0 => 'Wide', + 4 => 'Flexible Spot', + 8 => 'Zone', + 9 => 'Center', + 12 => 'Expanded Flexible Spot', + }, + }, + ], + 0x201d => { #JR + # Flexible Spot position for NEX/ILCE, non-zero only when AFAreaMode='Flexible Spot' + # from 2018: at least DSC-RX10M4 and RX100M6 also use this tag + # observed values in range (0 0) to (640 480), with center (320 240) often seen + # for NEX-5R/6, positions appear to be in an 11x9 grid + Name => 'FlexibleSpotPosition', + Condition => '$$self{Model} =~ /^(NEX-|ILCE-|DSC-(RX10M4|RX100M6|RX100M5A|HX99))/', + Writable => 'int16u', + Count => 2, + Notes => q{ + X and Y coordinates of the AF point, valid only when AFAreaMode is Flexible + Spot + }, + }, + 0x201e => [{ #PH (A99) + # Selected AF Point for SLT/HV/ILCA or ILCE with LA-EA2/EA4 + # Selected AF Zone for NEX/ILCE/ILCA when AFAreaMode = 'Zone', + # but also with Expanded Flexible Spot for ILCE-7RM2/7SM2/9 ... + # doesn't seem to apply to DSC models (always 0) + Name => 'AFPointSelected', + Condition => q{ + ($$self{Model} =~ /^(SLT-|HV)/) or ($$self{Model} =~ /^ILCE-/ and + defined $$self{AFAreaILCE} and $$self{AFAreaILCE} == 4) + }, + Notes => 'SLT models or ILCE with LA-EA2/EA4', + Writable => 'int8u', + PrintConvColumns => 2, + PrintConv => { + 0 => 'Auto', #(NC) + 1 => 'Center', + 2 => 'Top', + 3 => 'Upper-right', + 4 => 'Right', + 5 => 'Lower-right', + 6 => 'Bottom', + 7 => 'Lower-left', + 8 => 'Left', + 9 => 'Upper-left', + 10 => 'Far Right', + 11 => 'Far Left', + 12 => 'Upper-middle', + 13 => 'Near Right', + 14 => 'Lower-middle', + 15 => 'Near Left', + 16 => 'Upper Far Right', + 17 => 'Lower Far Right', + 18 => 'Lower Far Left', + 19 => 'Upper Far Left', + }, + },{ + Name => 'AFPointSelected', + Condition => '$$self{Model} =~ /^ILCA-(68|77M2)/ and defined $$self{AFAreaILCA} and $$self{AFAreaILCA} != 8', + Notes => 'ILCA-68 and ILCA-77M2', + Writable => 'int8u', + ValueConv => '$val - 1', # to get the same numbers as from the BITMASK in 0x2020 + ValueConvInv => '$val + 1', + PrintConvColumns => 5, + PrintConv => { + -1 => 'Auto', + %afPoints79, + 39 => 'E6 (Center)', # (add " (Center)" to central point) + }, + },{ + Name => 'AFPointSelected', + Condition => '($$self{Model} =~ /^ILCA-99M2/ and defined $$self{AFAreaILCA} and $$self{AFAreaILCA} != 8)', + Notes => 'ILCA-99M2 when AFAreaModeSetting is not Zone', + # (appears to indicate the number of the selectable Focal Plane AF Point) + Writable => 'int8u', + PrintConvColumns => 4, + PrintConv => { + 0 => 'Auto', # seen for AFAreaModeSetting = Center, Wide + %afPoints99M2, # for selected AFPoints corresponding to the 79 dedicated AF points + 162 => 'E6 (162, Center)', # add " (Center)" to central point + OTHER => sub { shift }, # pass other values straight through + }, + },{ + Name => 'AFPointSelected', + Condition => '($$self{Model} =~ /^ILCA-/ and defined $$self{AFAreaILCA} and $$self{AFAreaILCA} == 8)', + Notes => 'ILCA models when AFAreaModeSetting is set to Zone', + # ILCA-68 and 77M2 have 9 Zones: numbers/locations verified for ILCA-77M2 + # ILCA-99M2 has 15 Zones in Hybrid-AF and 9 Zones in dedicated Phase AF Area, so may not be valid for ILCA-99M2... + Writable => 'int8u', + PrintConv => { + 0 => 'n/a', + 1 => 'Top Left Zone', + 2 => 'Top Zone', + 3 => 'Top Right Zone', + 4 => 'Left Zone', + 5 => 'Center Zone', + 6 => 'Right Zone', + 7 => 'Bottom Left Zone', + 8 => 'Bottom Zone', + 9 => 'Bottom Right Zone', + #14 => ' ??? ', # seen for ILCA-99M2 + }, + },{ + Name => 'AFPointSelected', + # non-zero only when AFAreaMode is 'Zone', and 'Expanded-Flexible-Spot' for ILCE-6300/7RM2/7SM2 + # each Zone has 3x3 AF Areas --> 9 positions within 5x5 total Contrast AF Areas + Condition => '$$self{Model} =~ /^(NEX-|ILCE-)/', + Notes => 'NEX and ILCE models', + Writable => 'int8u', + PrintConv => { + 0 => 'n/a', + 1 => 'Center Zone', + 2 => 'Top Zone', + 3 => 'Right Zone', + 4 => 'Left Zone', + 5 => 'Bottom Zone', + 6 => 'Bottom Right Zone', + 7 => 'Bottom Left Zone', + 8 => 'Top Left Zone', + 9 => 'Top Right Zone', + }, + }], + # 0x201f - 0 0 0 0 for SLT and DSC; 4 values for NEX/ILCE with 4th value always 0: + # possibly bits relating to the 25 AF-Contrast-areas ??? + # 0x2020 - 10 values; for SLT/ILCA and NEX/ILCE with A-mount lens: relates to (phase-detect) AFPoints + # but not used by ILCA-99M2 anymore ... ? + 0x2020 => [{ + Name => 'AFPointsUsed', + Condition => '$$self{Model} !~ /^(ILCA-|DSC-)/', # (doesn't seem to apply to DSC-models) + Notes => 'SLT models, or NEX/ILCE with A-mount lenses', + BitsPerWord => 8, + BitsTotal => 80, + PrintConvColumns => 2, + PrintConv => { + 0 => '(none)', + BITMASK => { + 0 => 'Center', + 1 => 'Top', + 2 => 'Upper-right', + 3 => 'Right', + 4 => 'Lower-right', + 5 => 'Bottom', + 6 => 'Lower-left', + 7 => 'Left', + 8 => 'Upper-left', + 9 => 'Far Right', + 10 => 'Far Left', + 11 => 'Upper-middle', + 12 => 'Near Right', + 13 => 'Lower-middle', + 14 => 'Near Left', + 15 => 'Upper Far Right', + 16 => 'Lower Far Right', + 17 => 'Lower Far Left', + 18 => 'Upper Far Left', + }, + }, + },{ + Name => 'AFPointsUsed', + Condition => '$$self{Model} =~ /^ILCA-(68|77M2)/', + Notes => 'ILCA models', + BitsPerWord => 8, + BitsTotal => 80, + PrintConvColumns => 4, + PrintConv => { + 0 => '(none)', + BITMASK => { %afPoints79 }, + }, + }], + # 0x2021 - 0 for DSC; 0, 1 or 2 for SLT/ILCA and NEX/ILCE: 1=Face, 2=object-tracking ? + # from 2018: at least DSC-RX10M4 and RX100M6 also use this tag + 0x2021 => { #JR + Name => 'AFTracking', + Condition => '($$self{Model} !~ /^DSC-/) or ($$self{Model} =~ /^DSC-(RX10M4|RX100M6|RX100M5A|HX99)/)', + Writable => 'int8u', + PrintConv => { + 0 => 'Off', + 1 => 'Face tracking', + 2 => 'Lock On AF', + }, + }, + # 0x2022 - 13 bytes (104 bits) for SLT-A58/A99V, NEX-3N/5R/5T/6/VG30E/VG900, ILCE-3000/3500/5000/7/7R + # 26 bytes (208 bits) for ILCA-77M2, ILCE-5100/6000/7M2/7S/QX1 (7M2 has 117, 5100/6000 have 179 PhaseAFPoints) + # 52 bytes (416 bits) for ILCE-7RM2 (which has 399 PhaseAFPoints) and ILCE-7SM2 + # Only seen non-zero values for ILCE-5100/6000/7M2/7RM2 in AF-C mode: maybe FocalPlaneAFPointsUsed ??? + # (Similar number of bytes for contemporary DSC models, but mostly all non-zero values.) + # ILCE-6300 does not write this tag anymore, but writes 0x202a ... + 0x2022 => [{ + Name => 'FocalPlaneAFPointsUsed', + Condition => '$$self{Model} =~ /^(ILCE-(5100|6000|7M2))/', + Notes => 'On-sensor/focal-plane phase AF points for ILCE with hybrid AF', + BitsPerWord => 8, + BitsTotal => 208, # 26 words + PrintConv => { + 0 => '(none)', + BITMASK => { }, + }, + },{ + Name => 'FocalPlaneAFPointsUsed', + Condition => '$$self{Model} =~ /^ILCE-7RM2/', + # ILCE-7RM2 has 399 points in 19 rows of 21 points, numbered [0] to [398], [199] is Center + BitsPerWord => 8, + BitsTotal => 416, # 52 words + PrintConv => { + 0 => '(none)', + BITMASK => { }, + }, + }], + 0x2023 => { #JR + Name => 'MultiFrameNREffect', + Writable => 'int32u', + PrintConv => { + 0 => 'Normal', + 1 => 'High', # seen this only for ILCA-77M2 MFNR-12 images + }, + }, + # 0x2024 - 96 byte data block, very similar to 0x3000 ShotInfo, seen in Xperia Z5 + # 0x2025 - n1 n2 0 0 DSC-RX100M3/RX100M4/RX10M2/HX90V/WX500, ILCA-77M2, ILCE-5100/7M2/7RM2/7S/QX1 + # seen n1=0,2,4,5,7 and n2=0,1,3, very often: 7 3 0 0 + + # 0x2026 - 2 values: more precise WB Shift: AB in steps of 0.50, GM in steps of 0.25 (ILCE-7RM2 onwards) + 0x2026 => { #JR + Name => 'WBShiftAB_GM_Precise', + Writable => 'int32s', + Count => 2, + Notes => q{ + 2 numbers: 1. positive is a shift toward amber, 2. positive is a shift + toward magenta + }, + PrintConv => 'my @v=split(" ",$val); $_/=1000 foreach @v; sprintf("%.2f %.2f",$v[0],$v[1])', + }, + # 0x2027 - W H W/2 H/2 or W H val1 val2 (0 0 0 0 for Panorama images) + # Probably location of focus for Playback Zoom. + # Origin appears to be top-left, i.e. 1st coord to the right, 2nd coord. pointing down. + 0x2027 => { #JR + Name => 'FocusLocation', #(NC) + Writable => 'int16u', + Count => 4, + NOTES => q{ + Location in the image where the camera focused, used for Playback Zoom. + If the focus location information cannot be obtained, the centre of the + image will be used. + }, + }, + # 0x2028 - 0 0 for DSC-RX100M4/RX10M2, ILCE-7RM2/7SM2; seen non-zero values only for DSC-RX1RM2 + 0x2028 => { #JR + Name => 'VariableLowPassFilter', + Writable => 'int16u', + Count => 2, + PrintConv => { + '0 0' => 'n/a', + '1 0' => 'Off', + '1 1' => 'Standard', + '1 2' => 'High', + }, + }, + 0x2029 => { # uncompressed 14-bit RAW file type setting introduced 2015 + Name => 'RAWFileType', + Writable => 'int16u', + PrintConv => { + 0 => 'Compressed RAW', + 1 => 'Uncompressed RAW', + }, + }, + # 0x202a - first seen for ILCE-6300: 66 bytes + # possibly a 'replacement' for Tag2022 FocalPlaneAFPointsUsed, + # but now indicating locations in a 640x428 grid (3:2 part of LCD ?) + # first byte value 1 for ILCE-6300/6500/9, ILCA-99M2 + # values 110,137, ... for DSC-RX10M3, therefore limit to first byte = 1 for now + 0x202a => { + Name => 'Tag202a', + Condition => '$$valPt =~ /^\x01/', + SubDirectory => { TagTable => 'Image::ExifTool::Sony::Tag202a' }, + }, + 0x202b => { #JR (ILCA-99M2, ILCE-6500/7M3/7RM3/9, DSC-RX10M4/RX100M5 and newer) + Name => 'PrioritySetInAWB', + Writable => 'int8u', + PrintConv => { + 0 => 'Standard', + 1 => 'Ambience', + 2 => 'White', + }, + }, + 0x202c => { #JR + Name => 'MeteringMode2', + Writable => 'int16u', + PrintHex => 1, + PrintConv => { + 0x100 => 'Multi-segment', + 0x200 => 'Center-weighted average', + 0x301 => 'Spot (Standard)', + 0x302 => 'Spot (Large)', + 0x400 => 'Average', + 0x500 => 'Highlight', + }, + }, + 0x202d => { #JR first seen for ILCA-99M2, ILCE-6500, DSC-RX100M5 + Name => 'ExposureStandardAdjustment', # (NC) + Writable => 'rational64s', + PrintConv => '$val ? sprintf("%+.1f",$val) : 0', + PrintConvInv => '$val', + }, + 0x202e => { #JR (ILCE-7M3/7RM3 and newer) + Name => 'Quality', + Writable => 'int16u', + Count => 2, + PrintConv => { + '0 0' => 'n/a', + '0 1' => 'Standard JPEG', + '0 2' => 'Fine JPEG', + '0 3' => 'Extra Fine JPEG', + '1 0' => 'RAW', + '1 1' => 'RAW + Standard JPEG', + '1 2' => 'RAW + Fine JPEG', + '1 3' => 'RAW + Extra Fine JPEG', + }, + }, + 0x202f => { #JR (ILCE-7RM3) + Name => 'PixelShiftInfo', + Writable => 'undef', + # 6 bytes, all 0 for non-PixelShift images + # first 4 bytes: GroupID, read as int32u + # the ID displayed by Sony ImageDataConverter appears to be based on the lower 22 bits: + # 5 bits, 5 bits, 6 bits, 6 bits + # last 2 bytes: ShotNumber: (1 4) to (4 4) are the 4 source images, + # (0 4) is combined "PixelShifted" image + RawConv => q{ + my ($a,$b,$c) = (Get32u(\$val,0), Get8u(\$val,4), Get8u(\$val,5)); + sprintf("%.2d%.2d%.2d%.2d %d %d 0x%x",($a>>17)&0x1f,($a>>12)&0x1f,($a>>6)&0x3f,$a&0x3f,$b,$c,$a>>22); + }, + RawConvInv => q{ + my ($a,$b,$c,$d) = split ' ', $val; + my @a = $a =~ /../g; + return undef unless @a == 4; + return Set32u((hex($d)<<22) | ($a[0]<<17) | ($a[1]<<12) | ($a[2]<<6) | $a[3]) . chr($b) . chr($c); + }, + PrintConv => { + '00000000 0 0 0x0' => 'n/a', + OTHER => sub { + my ($val, $inv) = @_; + if ($inv) { + $val =~ s{Composed}{Shot 0/4}i; + $val =~ s{^(?:Group)?\s*(\d+)[, ]+(?:Shot\s*)?(\d+)[/ ](\d+)\s*\(?(\w+)\)?}{$1 $2 $3 $4}i or return undef; + } else { + $val =~ s{(\d+) (\d+) (\d+) (\w+)}{Group $1, Shot $2/$3 ($4)} or return undef; + $val =~ s{Shot\s*0+/0*4\b}{Composed}i; + } + return $val; + }, + }, + }, + 0x2031 => { #JR (only for ILCE-9 v2.00; ILCE-9 v2.10 and higher have "option" to write into EXIF tag 0xa431 ) + Name => 'SerialNumber', + Writable => 'string', + ValueConv => '$val=~s/(\d{2})(\d{2})(\d{2})(\d{2})/$4$3$2$1/; $val=~s/^0//; $val', + ValueConvInv => '$val="0$val" if length($val)==7; $val=~s/(\d{2})(\d{2})(\d{2})(\d{2})/$4$3$2$1/; $val', + PrintConv => 'sprintf("%.8d",$val)', + PrintConvInv => '$val', + }, + 0x3000 => { + Name => 'ShotInfo', + SubDirectory => { TagTable => 'Image::ExifTool::Sony::ShotInfo' }, + }, + # 0x3000: data block that includes DateTimeOriginal string + # 0x5001 - 0 + # 0x5002 - 128 +# +# at least some data for tags 0x2010, 0x9050 and 0x94xx is encrypted - PH +# (This is certainly true for at least parts of 0x2010, 0x9050, 0x9400, 0x9402 and 0x9403, +# but hasn't been verified for other tags -- just to be thorough, decipher all of them) +# Note: "(e)" in a comment indicates an enciphered value, all other values are deciphered +# + # 0x900b - 1st byte 0xae: face detection info for A450/500/550/560/580, A33/35/55, NEX-3/5/5C/C3/VG10 + # - other 1st byte values for some DSC-models + # - seen many 1,8,27,64... values: assume encrypted like other 9xxx tags + 0x900b => { + Name => 'Tag900b', + Condition => '$$valPt =~ /^\xae/', + SubDirectory => { TagTable => 'Image::ExifTool::Sony::Tag900b' }, + }, + 0x9050 => [ + # 944 bytes for A37, A57, A99, NEX-F3, NEX-5R, NEX-6, DSC-RX1, DSC-RX100 + # 3072 bytes for A65, A77, NEX-5N, NEX-7, NEX-VG20 (ref JR) + # not valid for DSC/Stellar models + # from mid-2015: ILCE-7RM2/7SM2/6300 and newer models use different offsets + { + Name => 'Tag9050a', + Condition => '$$self{Model} !~ /^(DSC-|Stellar|ILCE-(6300|6400|6500|7M3|7RM2|7RM3|7SM2|9)|ILCA-99M2)/', + SubDirectory => { + TagTable => 'Image::ExifTool::Sony::Tag9050a', + ByteOrder => 'LittleEndian', + }, + },{ + Name => 'Tag9050b', + Condition => '$$self{Model} =~ /^(ILCE-(6300|6400|6500|7M3|7RM2|7RM3|7SM2|9)|ILCA-99M2)/', + SubDirectory => { + TagTable => 'Image::ExifTool::Sony::Tag9050b', + ByteOrder => 'LittleEndian', + }, + },{ + Name => 'Sony_0x9050', + %unknownCipherData, + }], + 0x9400 => [ + # first byte: + # 0x07 (e) for DSC-HX7V/HX9V/HX100V/TX10/TX100/TX100V/WX7/WX9/WX10, HDR-CX../PJ.. + # 0x09 (e) for DSC-TX20/TX55/WX30 + # 0x0a (e) for SLT-A37/A57/A65V/A77V/A99V, NEX-F3/5N/5R/5T/6/7/VG20E, DSC-RX100/RX1/RX1R/HX10V/HX20V/HX30V/HX200V/TX200V/TX300V/TX66/WX50/WX100/WX150, Lunar/Stellar/HV + # 0x0c (e) for ILCE-3000/3500, NEX-3N, SLT-A58, DSC-HX50V/HX300/RX100M2/TX30/WX60/WX80/WX200/WX300, DSC-QX10/QX100 + # 0xd0 (e) H90, W650, W690: tag9400 decoding appears not valid/different + # 0x23 (e) for DSC-RX10/HX60V/HX350/HX400V/WX220/WX350, ILCE-7/7R/5000/6000, ILCA-68/77M2 + # 0x24 (e) for ILCA-99M2,ILCE-5100/6300/6500/7M2/7RM2/7S/7SM2/QX1, DSC-HX80/HX90V/QX30/RX0/RX100M3/RX100M4/RX100M5/RX10M2/RX10M3/RX1RM2/WX500 + # 0x26 (e) for ILCE-6400/7M3/7RM3/9, DSC-RX10M4/RX100M5A/RX100M6/HX99 + # first byte decoded: 40, 204, 202, 27, 58, 62, 48, 215 respectively + { + Name => 'Tag9400a', + Condition => q{ + $$valPt =~ /^[\x07\x09\x0a]/ or + ($$valPt =~ /^[\x5e\xe7\x04]/ and $$self{DoubleCipher} = 1) + }, + SubDirectory => { TagTable => 'Image::ExifTool::Sony::Tag9400a' }, + },{ + Name => 'Tag9400b', + Condition => '$$valPt =~ /^\x0c/', + SubDirectory => { TagTable => 'Image::ExifTool::Sony::Tag9400b' }, + },{ + Name => 'Tag9400c', + Condition => '$$valPt =~ /^[\x23\x24\x26]/', + SubDirectory => { TagTable => 'Image::ExifTool::Sony::Tag9400c' }, + },{ + Name => 'Sony_0x9400', + %unknownCipherData, + }], + 0x9401 => { + Name => 'Tag9401', + SubDirectory => { TagTable => 'Image::ExifTool::Sony::Tag9401' }, + # notes for data in this block (ref PH/JR): + # 0x02-0x03 appear to have some relation to start-offset of data... + # 0x00 - 0x03 Metering + # Mode + # f4 00 00 03 - - DSC-H90/W650/W690 + # cf 0b 9f 0f 0x09bc (a) DSC-WX9 + # 1c 00 ac 0f 0x09c9 (b) HDR-CX130E/CX160E/CX360E/CX560E/CX700E/PJ10E/PJ30E + # b7 0f f7 0f 0x09dd (c) DSC-HX7V/TX10/WX7/WX10 + # b7 0f fa 0f 0x09e0 (d) DSC-HX9V/HX100V/TX100/TX100V + # 27 00 fd 0f 0x09e7 (e) DSC-TX20/TX55/WX30 + # 69 1f ff 0f 0x09e9 (f) NEX-5N + # 21 2b cf 0f 0x09e9 (f) NEX-7/VG20E, SLT-A65V/A77V, Lunar + # 2d 00 d5 0d 0x09a2 (g) DSC-HX10V/HX20V/HX30V/HX200V/TX66/TX200V/TX300V/WX50/WX70/WX100/WX150 + # 2f 00 d6 0d 0x09a3 (h) NEX-F3, SLT-A37/A57 + # 30 00 d8 0d 0x09a5 (i) HDR-AS15 + # 32 00 e2 0d 0x09ac (j) DSC-RX100, Stellar + # 33 00 e2 0d 0x09ac (j) NEX-5R/5T/6, NEX-VG900/VG30E + # 33 50 e2 0d 0x09ac (j) SLT-A99V, HV + # 33 40 0d 0e 0x09d7 (k) DSC-RX1 v0.01 + # 33 41 0d 0e 0x09d7 (k) DSC-RX1, DSC-RX1R + # 38 00 32 0e 0x09fc (l) SLT-A58, ILCE-3000/3500, NEX-3N, DSC-HX300/HX50V/WX200/WX300/WX60/WX80/TX30 + # 3a 10 3a 0e 0x0a01 (m) DSC-QX10/QX100 + # 3a 20 47 0e 0x0a01 (m) DSC-RX100M2 + # 43 00 66 0e 0x0a1b (n) ILCE-7/7R v0.xx/v1.00/v1.01, ILCE-5000, DSC-RX10 + # 43 10 66 0e 0x0a1b (n) ILCE-7/7R v1.02/v1.10 + # 43 30 6c 0e 0x0a1b (n) ILCE-7/7R v1.20-v3.20 + # 44 00 9c 0e 0x0a39 (o) ILCE-6000 v1.00/v1.10, DSC-HX60V/HX350/HX400V/WX220/WX350 (also DSC-QX30 samples from sony.net) + # 44 10 a2 0e 0x0a39 (o) ILCE-6000 v1.20/v1.21 + # 44 20 a2 0e 0x0a39 (o) ILCE-6000 v2.00-v3.20 + # 49 00 b0 0e 0x0a3b (p) ILCA-68 v1.00, ILCA-77M2 V1.00/v1.01/v2.00 (also DSC-RX100M3 samples from sony.net) + # 4a 00 b3 0e 0x0a3d (q) ILCE-7S v1.00, ILCE-5100 v1.00/v1.10, ILCE-QX1, DSC-QX30/RX100M3 + # 4a 20 b9 0e 0x0a3d (q) ILCE-7S v1.20-v3.20 + # 4e 10 d0 0e 0x0a5a (r) ILCE-7M2 v1.00/v1.10 + # 4e 30 d6 0e 0x0a5a (r) ILCE-7M2 v1.20-v4.00 + # 5a 00 14 0f 0x0a85 (s) DSC-HX80/HX90V/WX500 + # 5d 00 56 0f 0x0ac7 (t) DSC-RX10M2/RX100M4, ILCE-7RM2/7SM2 v1.00-v2.20 (also DSC-RX1RM2 samples from Sony) + # 5d 1d 58 0f 0x0ac7 (t) ILCE-7RM2 v3.00-v4.00 + # 5d 1e 57 0f 0x0ac7 (t) DSC-RX1RM2 v1.00 + # 5d 10 56 0f 0x0ac7 (t) ILCE-6300 v1.00 (samples from Sony) + # 5d 20 58 0f 0x0ac7 (t) ILCE-6300 v1.00/v1.10 + # 5e 00 56 0f 0x0ac7 (t) DSC-RX10M3 v1.00 + # 64 00 a8 0f 0x0b15 (u) DSC-RX100M5 v1.00 + # 67 00 f9 0f 0x0b66 (v) ILCA-99M2 v1.00, ILCE-6500 v1.00-v1.05, DSC-RX0 v1.00 + # 7c 00 fe 0f 0x0adb (w) ILCE-9 v0.01-v2.00 + # 7d 00 fe 0f 0x0adb (w) ILCE-9 v2.10-v4.00 + # 7f 00 fa 0f 0x0add (x) DSC-RX10M4 v1.00 + # 80 00 fa 0f 0x0add (x) ILCE-7M3 v1.00/v2.00, ILCE-7RM3 v0.01/v1.00/v1.01/v2.00 + # 82 00 fc 0f 0x0ad9 (y) DSC-RX100M5A v1.00, DSC-RX100M6 v1.00 + # 90 00 fe 0f 0x098f? (z) DSC-HX99 v1.00 + # 92 10 ff 0f (za) ILCE-6400 v1.00 + # + # 0x0004 - (RX100: 0 or 1. subsequent data valid only if 1 - PH) + # 0x0007 => { + # Name => 'DynamicRangeOptimizer_9401', + # PrintConv => { + # 0 => 'Disabled', # seen for Panorama images + # 1 => 'Auto', + # 3 => 'Lv1', #(NC) + # 4 => 'Lv2', #(NC) + # 5 => 'Lv3', + # 6 => 'Lv4', + # 7 => 'Lv5', + # # 8 - seen for VG20E and some other models - PH + # 255 => 'Off', + # }, + # }, + }, + 0x9402 => [{ + Name => 'Tag9402', + # first 2 bytes deciphered: + # 0x00 0x00 SLT-A37/A57/A65/A77 + # 0x0e 0x00 DSC-H90/HX7V/HX9V/HX100V/TX10/TX100/TX100V/TX20/TX55/W650/W690/W730/WX10/WX30/WX7/WX9, but also seen: + # 0x0e 0x01 for a few DSC-W650/W690 samples ... + # 0x0f 0x01 NEX-5N/7/VG20, Lunar + # 0x10 0x01 DSC-HX10V/HX200V/HX20V/HX300/HX30V/HX50V/TX200V/TX30/TX300V/TX66/RX100/RX1/RX1R/WX100/WX150/WX200/WX300/WX50/WX60/WX70/WX80, Stellar, + # ILCE-3000/3500, NEX-F3/3N/5R/5T/6/VG30/VG900 + # 0x11 0x01 DSC-RX100M2/QX10/QX100 + # 0x13 0x01 ILCE-5000/7/7R, DSC-RX10, but also seen: + # 0x12 0x01 for ILCE-7/7R and DSC-RX10 samples from Sony.net ... + # 0x15 0x01 for a few ILCE-7/7R ... + # 0x14 0x01 ILCE-6000, DSC-HX60V/HX350/HX400V/WX220/WX350 + # 0x17 0x01 ILCE-7S/7M2/5100/QX1, DSC-QX30/RX100M3 + # 0x19 0x01 DSC-HX80/HX90V/RX1RM2/RX10M2/RX100M4/WX500, ILCE-6300/7RM2/7SM2 + # 0x1a 0x01 DSC-RX0/RX10M3/RX100M5, ILCE-6500 + # 0x1c 0x01 ILCE-9 + # 0x1d 0x01 DSC-RX10M4 + # 0x1e 0x01 ILCE-7M3/7RM3, DSC-RX100M5A/RX100M6 + # 0x1f 0x01 DSC-HX99 + # 0x20 0x01 ILCE-6400 + # var var SLT-A58/A99V, HV, ILCA-68/77M2/99M2 + # only valid when first byte 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x17, 0x19, 0x1a, 0x1c (enciphered 0x8a, 0x70, 0xb6, 0x69, 0x88, 0x20, 0x30, 0xd7, 0xbb, 0x92, 0x28) +# Condition => '$$self{DoubleCipher} ? $$valPt =~ /^[\x7e\x46\x1d\x18\x3a\x95\x24\x26\xd6]\x01/ : $$valPt =~ /^[\x8a\x70\xb6\x69\x88\x20\x30\xd7\xbb\x92\x28]\x01/', +# alternative simpler Condition: +# not valid for SLT/HV/ILCA models, and not valid for first byte 0x0e or 0xff (enciphered 0x05 or 0xff) + Condition => '$$self{Model} !~ /^(SLT-|HV|ILCA-)/ and $$valPt !~ /^[\x05\xff]/', + SubDirectory => { TagTable => 'Image::ExifTool::Sony::Tag9402' }, + },{ + Name => 'Sony_0x9402', + %unknownCipherData, + }], + 0x9403 => { + Name => 'Tag9403', + SubDirectory => { TagTable => 'Image::ExifTool::Sony::Tag9403' }, + }, + # 0x9404 first 5 bytes (deciphered): + # 4 0 163 1 2 SLT-A65V/A77V, NEX-5N/7, Lunar, DSC-HX7V/HX9V/HX100V/TX10/TX20/TX55/TX100/TX100V/WX9/WX10/WX30... + # 5 0 172 1 2 DSC-HX10V/HX200V/HX20V/HX30V/TX66/TX200V/TX300V/WX50/WX70/WX100/WX150... + # 9 0 38 2 2 SLT-A37/A57/A99V, NEX-5R/5T/6/F3/VG30E/VG900, DSC-RX1/RX1R/RX100, Stellar + # 12 0 8 2 2 SLT-A58, NEX-3N, ILCE-3000/3500, DSC-HX300/HX50V/WX60/WX80/WX300/TX30... + # 13 0 9 2 2 DSC-QX10/QX100/RX100M2 + # 15 0 35 2 2 ILCA-68/77M2, ILCE-5000/5100/6000/7/7R/7S/7M2/QX1, DSC-HX60V/HX350/HX400V/QX30/RX10/RX100M3/WX220/WX350 + # 16 0 85 2 2 DSC-HX80/HX90V/WX500 + # 17 0 232 1 2 DSC-RX0/RX1RM2/RX10M2/RX10M3/RX10M4/RX100M4/RX100M5/RX100M5A/RX100M6/HX99, ILCE-6300/6400/6500/7M3/7RM2/7RM3/7SM2/9, ILCA-99M2 + # other values for Panorama images and several other models + 0x9404 => [{ + Name => 'Tag9404a', + # first byte must be 4 or 5 and 4th byte must be 1 (deciphered) + Condition => '$$valPt =~ /^[\x40\x7d]..\x01/', + SubDirectory => { TagTable => 'Image::ExifTool::Sony::Tag9404a' }, + },{ + Name => 'Tag9404b', + # first byte must be 9 or 12 or 13 or 15 or 16 and 4th byte must be 2 (deciphered) + Condition => '$$valPt =~ /^[\xe7\xea\xcd\x8a\x70]..\x08/', + SubDirectory => { TagTable => 'Image::ExifTool::Sony::Tag9404b' }, + },{ + Name => 'Tag9404c', + # first byte must be 17 and 4th byte must be 1 (deciphered) + Condition => '$$valPt =~ /^\xb6..\x01/', + SubDirectory => { TagTable => 'Image::ExifTool::Sony::Tag9404c' }, + },{ + Name => 'Sony_0x9404', + %unknownCipherData, + }], + # 0x9405 first 2 bytes: + # 0 0 (0x00 = 0 0 enc.) DSC-H90 + # 2 0 (0x08 = 8 0 enc.) DSC and HDR of HX9V generation + # 3 0 (0x1b = 27 0 enc.) SLT, NEX, ILCE-3000/3500, DSC-RX100/RX1 + other DSC of same generation, also QX10 and QX100 + # 4 0 (0x40 = 64 0 enc.) DSC-RX1R + # 5 0 (0x7d = 125 0 enc.) DSC-RX100M2 + # 136 var (0x3a = 58 var enc.) ILCE-7/7R/5000/6000, DSC-HX60V/HX350/HX400V/RX10/WX220/WX350 + # 137 var (0xb3 = 179 var enc.) ILCA-68/77M2, DSC-RX100M3 - appears to go with 136 + # 138 var (0x7e = 126 var enc.) ILCE-7S/5100/QX1, DSC-QX30 - appears to go with 136 + # 139 var (0x9a = 154 var enc.) ILCE-7M2 + # 142 var (0x25 = 37 var enc.) DSC-HX80/HX90V/RX1RM2/RX10M2/RX10M3/RX100M4/WX500, ILCE-6300/7RM2/7SM2 + # 144 var (0xe1 = 225 var enc.) DSC-RX100M5 + # 145 var (0x76 = 118 var enc.) ILCA-99M2, ILCE-6500, DSC-RX0 + # 163 var (0x8b = 139 var enc.) ILCE-6400/7M3/7RM3/9, DSC-RX10M4/RX100M5A/RX100M6/HX99 + 0x9405 => [{ + Name => 'Tag9405a', + # first byte must be 0x1b or 0x40 or 0x7d + Condition => '$$valPt =~ /^[\x1b\x40\x7d]/', + SubDirectory => { TagTable => 'Image::ExifTool::Sony::Tag9405a' }, + },{ + Name => 'Tag9405b', + # first byte must be 0x3a, 0xb3, 0x7e, 0x9a, 0x25, 0xe1, 0x76 or 0x8b + Condition => '$$valPt =~ /^[\x3a\xb3\x7e\x9a\x25\xe1\x76\x8b]/', + SubDirectory => { TagTable => 'Image::ExifTool::Sony::Tag9405b' }, + },{ + Name => 'Sony_0x9405', + %unknownCipherData, + }], + 0x9406 => [{ + Name => 'Tag9406', + # - first byte must be 0x01 or 0x02 (enciphered 0x01 or 0x08), or 0x03 (enc. 0x1b) for ILCE-6300/7RM2/7SM2, and + # third byte must be 0x02 or 0x03 (enciphered 0x08 or 0x1b) - ref JR + # (applies to most SLT and NEX models, but no DSC models) + Condition => '$$valPt =~ /^[\x01\x08\x1b].[\x08\x1b]/s', + SubDirectory => { TagTable => 'Image::ExifTool::Sony::Tag9406' }, + },{ + Name => 'Sony_0x9406', + %unknownCipherData, + }], + 0x9407 => { + Name => 'Sony_0x9407', + %unknownCipherData, + }, + 0x9408 => { + Name => 'Sony_0x9408', + %unknownCipherData, + }, + 0x9409 => { + Name => 'Sony_0x9409', + %unknownCipherData, + }, + 0x940a => [{ + Name => 'Tag940a', + Condition => '$$self{Model} =~ /^(SLT-|HV)/', # but appears not valid for ILCA models ... + SubDirectory => { TagTable => 'Image::ExifTool::Sony::Tag940a' }, + },{ + Name => 'Sony_0x940a', + %unknownCipherData, + }], + 0x940b => { + Name => 'Sony_0x940b', + %unknownCipherData, + }, + 0x940c => [{ + Name => 'Tag940c', + Condition => '$$self{Model} =~ /^(NEX-|ILCE-|Lunar)\b/', + SubDirectory => { TagTable => 'Image::ExifTool::Sony::Tag940c' }, + },{ + Name => 'Sony_0x940c', + %unknownCipherData, + }], + 0x940d => { + Name => 'Sony_0x940d', + %unknownCipherData, + }, +# 0x940e: 2nd byte = 0: no AFInfo, default for NEX/ILCE +# 2nd byte = 1: AFInfo for SLT/ILCA models (but also seen 1 for DSC-HX20W/HX300/WX70 ...) +# 2nd byte = 2: AFInfo for NEX/ILCE with LA-EA2/EA4 Phase-detect AF Adapter + 0x940e => [{ + Name => 'AFInfo', + Condition => '$$self{Model} =~ /^(SLT-|HV|ILCA-)/', + SubDirectory => { TagTable => 'Image::ExifTool::Sony::AFInfo' }, + },{ + Name => 'Tag940e', + Condition => '$$self{Model} =~ /^(NEX-|ILCE-|Lunar)/', + SubDirectory => { TagTable => 'Image::ExifTool::Sony::Tag940e' }, + },{ + Name => 'Sony_0x940e', + %unknownCipherData, + }], + 0x940f => { + Name => 'Sony_0x940f', + %unknownCipherData, + }, + 0x9411 => { + Name => 'Sony_0x9411', + %unknownCipherData, + # 0x02 - int32u?: 1,3,5,7,9 (A77) + }, + 0xb000 => { #8 + Name => 'FileFormat', + Writable => 'int8u', + Count => 4, + # dynamically set the file type to SR2 because we could have assumed ARW up till now + RawConv => q{ + $self->OverrideFileType($$self{TIFF_TYPE} = 'SR2') if $val eq '1 0 0 0'; + return $val; + }, + PrintConvColumns => 2, + PrintConv => { + '0 0 0 2' => 'JPEG', + '1 0 0 0' => 'SR2', + '2 0 0 0' => 'ARW 1.0', + '3 0 0 0' => 'ARW 2.0', + '3 1 0 0' => 'ARW 2.1', + '3 2 0 0' => 'ARW 2.2', #PH (NEX-5) + '3 3 0 0' => 'ARW 2.3', #PH (SLT-A65,SLT-A77) + '3 3 1 0' => 'ARW 2.3.1', #PH/JR (DSC-RX1R/RX100M2/Stellar2) + '3 3 2 0' => 'ARW 2.3.2', #JR (DSC-RX1RM2,ILCE-7SM2 - support for uncompressed 14-bit RAW) + '3 3 3 0' => 'ARW 2.3.3', #JR (ILCE-9) + '3 3 5 0' => 'ARW 2.3.5', #JR (DSC-HX99) + # what about cRAW images? + }, + }, + 0xb001 => { # ref http://forums.dpreview.com/forums/read.asp?forum=1037&message=33609644 + # (ARW and SR2 images only until the SLT-A65V started writing them to JPEG too) + Name => 'SonyModelID', + Writable => 'int16u', + PrintConvColumns => 2, + PrintConv => { + #0 => 'DSC-HX80', #PH (and several other DSC models) + 2 => 'DSC-R1', + 256 => 'DSLR-A100', + 257 => 'DSLR-A900', + 258 => 'DSLR-A700', + 259 => 'DSLR-A200', + 260 => 'DSLR-A350', + 261 => 'DSLR-A300', + 262 => 'DSLR-A900 (APS-C mode)', #http://u88.n24.queensu.ca/exiftool/forum/index.php/topic,3994.0.html + 263 => 'DSLR-A380/A390', #PH (A390) + 264 => 'DSLR-A330', + 265 => 'DSLR-A230', + 266 => 'DSLR-A290', #PH + 269 => 'DSLR-A850', + 270 => 'DSLR-A850 (APS-C mode)', #http://u88.n24.queensu.ca/exiftool/forum/index.php/topic,3994.0.html + 273 => 'DSLR-A550', + 274 => 'DSLR-A500', #PH + 275 => 'DSLR-A450', #http://dev.exiv2.org/issues/show/0000611 + 278 => 'NEX-5', #PH + 279 => 'NEX-3', #PH + 280 => 'SLT-A33', #PH + 281 => 'SLT-A55 / SLT-A55V', #PH (A55 NC) + 282 => 'DSLR-A560', #PH + 283 => 'DSLR-A580', #http://u88.n24.queensu.ca/exiftool/forum/index.php/topic,2881.0.html + 284 => 'NEX-C3', #PH + 285 => 'SLT-A35', #JR + 286 => 'SLT-A65 / SLT-A65V', #PH + 287 => 'SLT-A77 / SLT-A77V', #PH + 288 => 'NEX-5N', #PH + 289 => 'NEX-7', #PH (also Hasselblad Lunar, ref JR) + 290 => 'NEX-VG20E', #JR + 291 => 'SLT-A37', #JR + 292 => 'SLT-A57', #JR + 293 => 'NEX-F3', #PH + 294 => 'SLT-A99 / SLT-A99V', #JR (also Hasselblad HV) + 295 => 'NEX-6', #JR + 296 => 'NEX-5R', #JR + 297 => 'DSC-RX100', #PH (also Hasselblad Stellar, ref JR) + 298 => 'DSC-RX1', #JR + 299 => 'NEX-VG900', #JR + 300 => 'NEX-VG30E', #JR + 302 => 'ILCE-3000 / ILCE-3500', #JR + 303 => 'SLT-A58', #JR + 305 => 'NEX-3N', #PH + 306 => 'ILCE-7', #JR + 307 => 'NEX-5T', #JR + 308 => 'DSC-RX100M2', #JR + 309 => 'DSC-RX10', #JR + 310 => 'DSC-RX1R', #JR + 311 => 'ILCE-7R', #JR + 312 => 'ILCE-6000', #JR + 313 => 'ILCE-5000', #JR + 317 => 'DSC-RX100M3', #JR + 318 => 'ILCE-7S', #JR + 319 => 'ILCA-77M2', #IB + 339 => 'ILCE-5100', #JR + 340 => 'ILCE-7M2', #JR + 341 => 'DSC-RX100M4', #PH + 342 => 'DSC-RX10M2', #JR + 344 => 'DSC-RX1RM2', #JR + 346 => 'ILCE-QX1', #IB + 347 => 'ILCE-7RM2', #JR + 350 => 'ILCE-7SM2', #JR + 353 => 'ILCA-68', #IB + 354 => 'ILCA-99M2', #JR + 355 => 'DSC-RX10M3', #PH + 356 => 'DSC-RX100M5', #IB/JR + 357 => 'ILCE-6300', #IB + 358 => 'ILCE-9', #JR + 360 => 'ILCE-6500', #JR + 362 => 'ILCE-7RM3', #IB + 363 => 'ILCE-7M3', #JR/IB + 364 => 'DSC-RX0', #PH + 365 => 'DSC-RX10M4', #JR + 366 => 'DSC-RX100M6', #IB + 367 => 'DSC-HX99', #IB + 369 => 'DSC-RX100M5A', #JR + 371 => 'ILCE-6400', #IB + }, + }, + 0xb020 => { #2 + Name => 'CreativeStyle', + Writable => 'string', + # (all of these values have been observed, ref JR and PH) + # - this PrintConv is included to make these strings consistent with + # other CreativeStyle tags, and to facilitate the language translations + # - these values are always English, regardless of the camera language settings + PrintConv => { + OTHER => sub { shift }, # pass other values straight through + None => 'None', + AdobeRGB => 'Adobe RGB', + Real => 'Real', + Standard => 'Standard', + Vivid => 'Vivid', + Portrait => 'Portrait', + Landscape => 'Landscape', + Sunset => 'Sunset', + Nightview => 'Night View/Portrait', + BW => 'B&W', + Neutral => 'Neutral', + Clear => 'Clear', + Deep => 'Deep', + Light => 'Light', + Autumnleaves=> 'Autumn Leaves', + Sepia => 'Sepia', + }, + }, + 0xb021 => { #2 + Name => 'ColorTemperature', + Writable => 'int32u', + PrintConv => '$val ? ($val==0xffffffff ? "n/a" : $val) : "Auto"', + PrintConvInv => '$val=~/Auto/i ? 0 : ($val eq "n/a" ? 0xffffffff : $val)', + }, + 0xb022 => { #7 + Name => 'ColorCompensationFilter', + Format => 'int32s', + Writable => 'int32u', # (written incorrectly as unsigned by Sony) + Notes => 'negative is green, positive is magenta', + }, + 0xb023 => { #PH (A100) - (set by mode dial) + Name => 'SceneMode', + Writable => 'int32u', + PrintConvColumns => 2, + PrintConv => \%Image::ExifTool::Minolta::minoltaSceneMode, + }, + 0xb024 => { #PH (A100) + Name => 'ZoneMatching', + Writable => 'int32u', + PrintConv => { + 0 => 'ISO Setting Used', + 1 => 'High Key', + 2 => 'Low Key', + }, + }, + 0xb025 => { #PH (A100) + Name => 'DynamicRangeOptimizer', + Writable => 'int32u', + PrintConvColumns => 2, + PrintConv => { + 0 => 'Off', + 1 => 'Standard', + 2 => 'Advanced Auto', + 3 => 'Auto', # (A550) + 8 => 'Advanced Lv1', #JD + 9 => 'Advanced Lv2', #JD + 10 => 'Advanced Lv3', #JD + 11 => 'Advanced Lv4', #JD + 12 => 'Advanced Lv5', #JD + 16 => 'Lv1', # (NEX-5) + 17 => 'Lv2', + 18 => 'Lv3', + 19 => 'Lv4', + 20 => 'Lv5', + }, + }, + 0xb026 => { #PH (A100) + Name => 'ImageStabilization', + Writable => 'int32u', + PrintConv => { + 0 => 'Off', + 1 => 'On', + 0xffffffff => 'n/a', # (HX9V sweep panorama, ref JR) + }, + }, + 0xb027 => { #2 + Name => 'LensType', + Writable => 'int32u', + SeparateTable => 1, + # set to 65535 for E-mount lenses (values 0x80xx) + ValueConvInv => '($val & 0xff00) == 0x8000 ? 65535 : int($val)', + PrintConv => \%sonyLensTypes, + }, + 0xb028 => { #2 + # (used by the DSLR-A100) + Name => 'MinoltaMakerNote', + # must check for zero since apparently a value of zero indicates the IFD doesn't exist + # (dumb Sony -- they shouldn't write this tag if the IFD is missing!) + Condition => '$$valPt ne "\0\0\0\0"', + Flags => 'SubIFD', + SubDirectory => { + TagTable => 'Image::ExifTool::Minolta::Main', + Start => '$val', + }, + }, + 0xb029 => { #2 (set by creative style menu) + Name => 'ColorMode', + Writable => 'int32u', + PrintConvColumns => 2, + PrintConv => \%Image::ExifTool::Minolta::sonyColorMode, + }, + 0xb02a => { + Name => 'LensSpec', + Format => 'undef', + Writable => 'int8u', + Count => 8, + Notes => q{ + like LensInfo, but also specifies lens features: DT, E, ZA, G, SSM, SAM, + OSS, STF, Reflex, Macro and Fisheye + }, + ValueConv => \&ConvLensSpec, + ValueConvInv => \&ConvInvLensSpec, + PrintConv => \&PrintLensSpec, + PrintConvInv => \&PrintInvLensSpec, + }, + 0xb02b => { #PH (A550 JPEG and A200, A230, A300, A350, A380, A700 and A900 ARW) + Name => 'FullImageSize', + Writable => 'int32u', + Count => 2, + # values stored height first, so swap to get "width height" + ValueConv => 'join(" ", reverse split(" ", $val))', + ValueConvInv => 'join(" ", reverse split(" ", $val))', + PrintConv => '$val =~ tr/ /x/; $val', + PrintConvInv => '$val =~ tr/x/ /; $val', + }, + 0xb02c => { #PH (A550 JPEG and A200, A230, A300, A350, A380, A700 and A900 ARW) + Name => 'PreviewImageSize', + Writable => 'int32u', + Count => 2, + ValueConv => 'join(" ", reverse split(" ", $val))', + ValueConvInv => 'join(" ", reverse split(" ", $val))', + PrintConv => '$val =~ tr/ /x/; $val', + PrintConvInv => '$val =~ tr/x/ /; $val', + }, + 0xb040 => { #2 + Name => 'Macro', + Writable => 'int16u', + RawConv => '$val == 65535 ? undef : $val', + PrintConv => { + 0 => 'Off', + 1 => 'On', + 2 => 'Close Focus', #9 + 65535 => 'n/a', #PH (A100) + }, + }, + 0xb041 => { #2 + Name => 'ExposureMode', + Writable => 'int16u', + RawConv => '$val == 65535 ? undef : $val', + PrintConvColumns => 2, + PrintConv => { + 0 => 'Program AE', # (RX100 'Program','Sunset' - PH) + 1 => 'Portrait', #PH (HX1) + 2 => 'Beach', #9 + 3 => 'Sports', #9 + 4 => 'Snow', #9 + 5 => 'Landscape', + 6 => 'Auto', # (RX100 'Intelligent Auto' - PH) + 7 => 'Aperture-priority AE', + 8 => 'Shutter speed priority AE', + 9 => 'Night Scene / Twilight',#2/9 + 10 => 'Hi-Speed Shutter', #9 + 11 => 'Twilight Portrait', #9 (RX100 'Night Portrait' - PH) + 12 => 'Soft Snap/Portrait', #9 (TX7 'Soft Snap'; RX100/A37 'Portrait' but manuals say "reproduces soft skin tone" - PH) + 13 => 'Fireworks', #9 + 14 => 'Smile Shutter', #9 (T200) + 15 => 'Manual', + 18 => 'High Sensitivity', #9 + 19 => 'Macro', #JR + 20 => 'Advanced Sports Shooting', #9 + 29 => 'Underwater', #9 + # 30 seen for DSC-W110 and W390, maybe something with Face or Portrait ?? + 33 => 'Food', #9 + 34 => 'Sweep Panorama', #PH (HX1) + 35 => 'Handheld Night Shot', #PH (HX1/TX1, also called "Hand-held Twilight") + 36 => 'Anti Motion Blur', #PH (TX1) + 37 => 'Pet', #9 + 38 => 'Backlight Correction HDR', #9 + 39 => 'Superior Auto', #9 + 40 => 'Background Defocus', #PH (HX20V) + 41 => 'Soft Skin', #JR (HX9V) (HX200V Portrait - PH) + 42 => '3D Image', #JR (HX9V) + # 50 seen for DSC-W530 + 65535 => 'n/a', #PH (A100) + }, + }, + 0xb042 => { #9 + Name => 'FocusMode', + # Only FocusMode for older DSC models; + # Newest DSC models give only 0, many models of 'HX9V generation' give only 4 - + # these models give FocusMode in tag 0xb04e, and are excluded here. + Condition => q{ + ($$self{TagB042} = Get16u($valPt, 0)) and + (not $$self{MetaVersion} or $$self{MetaVersion} ne 'DC7303320222000') + }, + Notes => 'not valid for all models', + Writable => 'int16u', + RawConv => '$val == 65535 ? undef : $val', + PrintConv => { + # 0 - seen this for panorama shot + 1 => 'AF-S', # (called Single-AF by Sony) + 2 => 'AF-C', # (called Monitor-AF by Sony) + 4 => 'Permanent-AF', # (TX7,HX9V?) + 65535 => 'n/a', #PH (A100), also for DSC-W690 panorama shots + }, + }, + 0xb043 => [{ #9 + Name => 'AFAreaMode', + # AFAreaMode only for older models; + # exclude newest DSC models, which give AFAreaMode in Tag9402 0x0017 (eg. RX100 - PH) + Writable => 'int16u', + Condition => 'not $$self{MetaVersion} or $$self{MetaVersion} ne "DC7303320222000"', #JR + RawConv => '$val == 65535 ? undef : $val', + Notes => 'older models', + PrintConv => { + # 0 - (takes this value after camera reset, but can't be set back once changed) + 0 => 'Default', + 1 => 'Multi', + 2 => 'Center', + 3 => 'Spot', + 4 => 'Flexible Spot', # (T200) + 6 => 'Touch', + 14 => 'Tracking', #JR (HX9V) ("Manual" for the T200?, ref 9) + 15 => 'Face Tracking', # (not set when in face detect mode and no faces detected) + 65535 => 'n/a', #PH (A100) + }, + },{ #JR + Name => 'AFAreaMode', + # AFAreaMode for DSC-HX9V generation, having values that appear to be different from older models. + Writable => 'int16u', + Condition => '$$self{TagB042} and $$self{TagB042} != 0', + Notes => 'DSC-HX9V generation cameras', + PrintConv => { + 0 => 'Multi', + 1 => 'Center', + 2 => 'Spot', #(NC) seen for DSC-WX9 + 3 => 'Flexible Spot', + 10 => 'Selective (for Miniature effect)', # seen for Miniature effect of DSC-WX30 + 14 => 'Tracking', + 15 => 'Face Tracking', + 255 => 'Manual', + }, + }], + 0xb044 => { #9 + Name => 'AFIlluminator', + Writable => 'int16u', + RawConv => '$val == 65535 ? undef : $val', + PrintConv => { + 0 => 'Off', + 1 => 'Auto', + 65535 => 'n/a', #PH (A100) + }, + }, + # 0xb045 - int16u: 0 + # 0xb046 - int16u: 0 + 0xb047 => { #2 + Name => 'JPEGQuality', + Writable => 'int16u', + RawConv => '$val == 65535 ? undef : $val', + PrintConv => { + 0 => 'Standard', + 1 => 'Fine', + 2 => 'Extra Fine', #JR + 65535 => 'n/a', #PH (A100) + }, + }, + 0xb048 => { #9 + Name => 'FlashLevel', #JR other name, but values -9 to 9 match FlashExposureCompensation + Writable => 'int16s', + RawConv => '($val == -1 and $$self{Model} =~ /DSLR-A100\b/) ? undef : $val', + PrintConv => { + -32768 => 'Low', + -9 => '-9/3', #JR + -6 => '-6/3', #JR + -5 => '-5/3', #JR + -4 => '-4/3', #JR + -3 => '-3/3', + -2 => '-2/3', + -1 => '-1/3', # (for the A100, -1 is effectively 'n/a' - PH) + 0 => 'Normal', + 1 => '+1/3', + 2 => '+2/3', + 3 => '+3/3', + 4 => '+4/3', #JR (NC) + 5 => '+5/3', #JR (NC) + 6 => '+6/3', #JR + 128 => 'n/a', #JR (HX9V) + 32767 => 'High', + }, + }, + 0xb049 => { #9 + Name => 'ReleaseMode', + Writable => 'int16u', + RawConv => '$val == 65535 ? undef : $val', + PrintConv => { + 0 => 'Normal', # (ie. shutter button) + 2 => 'Continuous', + 5 => 'Exposure Bracketing', + 6 => 'White Balance Bracketing', # (HX5) + 8 => 'DRO Bracketing', #JR (ILCE-7RM2) + 65535 => 'n/a', #PH (A100) + }, + }, + 0xb04a => { #9 + Name => 'SequenceNumber', + Notes => 'shot number in continuous burst', + Writable => 'int16u', + RawConv => '$val == 65535 ? undef : $val', + PrintConv => { + 0 => 'Single', + 65535 => 'n/a', #PH (A100) + OTHER => sub { shift }, # pass all other numbers straight through + }, + }, + 0xb04b => { #2/PH + Name => 'Anti-Blur', + Writable => 'int16u', + RawConv => '$val == 65535 ? undef : $val', + PrintConv => { + 0 => 'Off', + 1 => 'On (Continuous)', #PH (NC) + 2 => 'On (Shooting)', #PH (NC) + 65535 => 'n/a', + }, + }, + # 0xb04c - rational64u: 10/10 (seen 5 for HX9V Manual-exposure images, ref JR) + # 0xb04d - int16u: 0 + # (the Kamisaka decoding of 0xb04e seems wrong - ref JR) + # 0xb04e => { #2 + # Name => 'LongExposureNoiseReduction', + # Notes => 'LongExposureNoiseReduction for other models', + # Writable => 'int16u', + # RawConv => '$val == 65535 ? undef : $val', + # PrintConv => { + # 0 => 'Off', + # 1 => 'On', + # 2 => 'On 2', #PH (TX10, TX100, WX9, WX10, etc) + # # 4 - seen this (CX360E, CX700E) + # 65535 => 'n/a', #PH (A100) + # }, + # }, + 0xb04e => { #PH (RX100) - but not in RX100M3 anymore (ref JR) + Name => 'FocusMode', + Condition => '$$self{MetaVersion} and $$self{MetaVersion} eq "DC7303320222000"', #JR + Notes => 'valid for DSC-HX9V generation and newer', + Writable => 'int16u', + PrintConv => { + 0 => 'Manual', + # 1 - seen for DSC-WX7 burst, HDR-CX130E/CX560E + 2 => 'AF-S', + 3 => 'AF-C', + # 4 - seen for HDR-CX360E/CX700E + 5 => 'Semi-manual', #JR (HX9V) + 6 => 'DMF', # "Direct Manual Focus" + }, + }, + 0xb04f => { #PH (TX1) + Name => 'DynamicRangeOptimizer', + Writable => 'int16u', + Priority => 0, # (unreliable for the A77) + PrintConv => { + 0 => 'Off', + 1 => 'Standard', + 2 => 'Plus', + # 8 for HDR models - what does this mean? + }, + }, + 0xb050 => { #PH (RX100) + Name => 'HighISONoiseReduction2', + Condition => '$$self{Model} =~ /^(DSC-|Stellar)/', + Notes => 'DSC models only', + Writable => 'int16u', + PrintConv => { + 0 => 'Normal', + 1 => 'High', + 2 => 'Low', + 3 => 'Off', #JR + # it seems that all SLT and NEX models give n/a here (ref JR) + 65535 => 'n/a', + }, + }, + # 0xb051 - int16u: 0 + 0xb052 => { #PH (TX1) + Name => 'IntelligentAuto', + Writable => 'int16u', + PrintConv => { + 0 => 'Off', + 1 => 'On', + 2 => 'Advanced', #9 + }, + }, + # 0xb053 - int16u: normally 0, but got 1 for a superior auto backlight picture (RX100) + 0xb054 => { #PH/9/JR (TX1,TX7,RX100,HX9V) + Name => 'WhiteBalance', + Writable => 'int16u', + Notes => q{ + decoding of the Fluorescent settings matches the EXIF standard, which is + different than the names used by Sony for some models + }, + PrintConv => { + 0 => 'Auto', + 4 => 'Custom', # (manual) + 5 => 'Daylight', + 6 => 'Cloudy', + # PrintConv names matching Exif Fluorescent LightSource names (ref JR) + # (Sony uses conflicting names for some models) + 7 => 'Cool White Fluorescent', # (RX100) (TX7/HX9V "Fluorescent 1 (White)", ref 9/JR) + 8 => 'Day White Fluorescent', # (RX100) (TX7/HX9V "Fluorescent 2 (Natural White)", ref 9/JR) + 9 => 'Daylight Fluorescent', # (RX100) (TX7/HX9V "Fluorescent 3 (Day White)", ref 9/JR) + 10 => 'Incandescent2', #JR (HX9V) + 11 => 'Warm White Fluorescent', + 14 => 'Incandescent', + 15 => 'Flash', + 17 => 'Underwater 1 (Blue Water)', #9 + 18 => 'Underwater 2 (Green Water)', #9 + 19 => 'Underwater Auto', #JR + }, + }, +); + +# "SEMC MS" maker notes +%Image::ExifTool::Sony::Ericsson = ( + WRITE_PROC => \&Image::ExifTool::Exif::WriteExif, + CHECK_PROC => \&Image::ExifTool::Exif::CheckExif, + GROUPS => { 0 => 'MakerNotes', 2 => 'Image' }, + NOTES => 'Maker notes found in images from some Sony Ericsson phones.', + 0x2000 => { + Name => 'MakerNoteVersion', + Writable => 'undef', + Count => 4, + }, + 0x201 => { + Name => 'PreviewImageStart', + IsOffset => 1, + MakerPreview => 1, # force preview inside maker notes + OffsetPair => 0x202, + DataTag => 'PreviewImage', + Writable => 'int32u', + WriteGroup => 'MakerNotes', + Protected => 2, + Notes => 'a small 320x200 preview image', + }, + 0x202 => { + Name => 'PreviewImageLength', + OffsetPair => 0x201, + DataTag => 'PreviewImage', + Writable => 'int32u', + WriteGroup => 'MakerNotes', + Protected => 2, + }, +); + +# camera information for the A700/A850/A900 (ref JR) +%Image::ExifTool::Sony::CameraInfo = ( + %binaryDataAttrs, + GROUPS => { 0 => 'MakerNotes', 2 => 'Camera' }, + NOTES => 'Camera information for the A700, A850 and A900.', + 0x00 => { + Name => 'LensSpec', + # the A700/A850/A900 use a different int16 byte ordering! - PH + Format => 'undef[8]', + ValueConv => sub { + my $val = shift;; + return ConvLensSpec(pack('v*', unpack('n*', $val))); + }, + ValueConvInv => sub { + my $val = shift; + return pack('v*', unpack('n*', ConvInvLensSpec($val))); + }, + PrintConv => \&PrintLensSpec, + PrintConvInv => \&PrintInvLensSpec, + }, + 0x0014 => { + Name => 'FocusModeSetting', + Notes => 'FocusModeSetting for the A700, A850 and A900', + PrintConv => { + 0 => 'Manual', + 1 => 'AF-S', + 2 => 'AF-C', + 3 => 'AF-A', + 4 => 'DMF', + }, + }, + 0x0015 => { # the AF Point selected in AFAreaMode=Local or Spot; always '0' for AFAreaMode=Wide + Name => 'AFPointSelected', + PrintConvColumns => 2, + PrintConv => { + 0 => 'Auto', + 1 => 'Center', + 2 => 'Top', + 3 => 'Upper-right', + 4 => 'Right', + 5 => 'Lower-right', + 6 => 'Bottom', + 7 => 'Lower-left', + 8 => 'Left', + 9 => 'Upper-left', + 10 => 'Far Right', # only given by A700 + 11 => 'Far Left', # only given by A700 + }, + }, + # 0x0019 - AF sensor used for focusing for A700/A850/A900: + # + # A700 AF sensor layout: A850/A900 AF sensor layout: + # + # - *-* - = AF sensor + # | | | | * = assist sensor + # - *-* o = F2.8 sensor + # | | |o| | | | * |o| * | A700 center: double-cross + F2.8 + # - *-* A850 center: double-cross + F2.8 + 4 assist + # | | | | + # - *-* + # + # Following values seen for A700/A850 in AFAreaMode=Local or Spot: (other values only seen in "Wide") + # + # 16 + # 0 19 + # 13 + # 3 1 22 20 18 + # 8 + # 2 21 + # 5 + # + # Note 1: A850/A900 AFPoint Selected 'Left'/'Right' (in 0x0015) corresponds in position (see diagram) + # to A700 Local AFPoint 'Far Left'/'Far Right', and gives 'Far Left'/'Far Right' in 0x0019. + # Note 2: A700 in "Wide" also gives all 23 values in 0x0019, although it doesn't have assist-points ... + 0x0019 => { # the AF sensor used for focusing + Name => 'AFPoint', + PrintConv => { + 0 => 'Upper-left', + 1 => 'Left', + 2 => 'Lower-left', + 3 => 'Far Left', + 4 => 'Bottom Assist-left', #(NC) + 5 => 'Bottom', + 6 => 'Bottom Assist-right', #(NC) + # values 7-14: 8 center points: 4 from double-cross + 4 assist; 7-10 appear horizontal, 11-14 vertical + 7 => 'Center (7)', #(NC) + 8 => 'Center (horizontal)', + 9 => 'Center (9)', #(NC) + 10 => 'Center (10)', #(NC) + 11 => 'Center (11)', #(NC) + 12 => 'Center (12)', #(NC) + 13 => 'Center (vertical)', + 14 => 'Center (14)', #(NC) + 15 => 'Top Assist-left', #(NC) + 16 => 'Top', + 17 => 'Top Assist-right', #(NC) + 18 => 'Far Right', + 19 => 'Upper-right', + 20 => 'Right', + 21 => 'Lower-right', + 22 => 'Center F2.8', + }, + }, + # AF Status for A700/A850/A900, which have different sensor layout + # and different int16 byte ordering + 0x001e => { Name => 'AFStatusActiveSensor', %Image::ExifTool::Minolta::afStatusInfo }, + 0x0020 => { Name => 'AFStatusUpper-left', %Image::ExifTool::Minolta::afStatusInfo }, + 0x0022 => { Name => 'AFStatusLeft', %Image::ExifTool::Minolta::afStatusInfo }, + 0x0024 => { Name => 'AFStatusLower-left', %Image::ExifTool::Minolta::afStatusInfo }, + 0x0026 => { Name => 'AFStatusFarLeft', %Image::ExifTool::Minolta::afStatusInfo }, + 0x0028 => { Name => 'AFStatusBottomAssist-left', %Image::ExifTool::Minolta::afStatusInfo }, + 0x002a => { Name => 'AFStatusBottom', %Image::ExifTool::Minolta::afStatusInfo }, + 0x002c => { Name => 'AFStatusBottomAssist-right', %Image::ExifTool::Minolta::afStatusInfo }, + 0x002e => { Name => 'AFStatusCenter-7', %Image::ExifTool::Minolta::afStatusInfo }, + 0x0030 => { Name => 'AFStatusCenter-horizontal', %Image::ExifTool::Minolta::afStatusInfo }, + 0x0032 => { Name => 'AFStatusCenter-9', %Image::ExifTool::Minolta::afStatusInfo }, + 0x0034 => { Name => 'AFStatusCenter-10', %Image::ExifTool::Minolta::afStatusInfo }, + 0x0036 => { Name => 'AFStatusCenter-11', %Image::ExifTool::Minolta::afStatusInfo }, + 0x0038 => { Name => 'AFStatusCenter-12', %Image::ExifTool::Minolta::afStatusInfo }, + 0x003a => { Name => 'AFStatusCenter-vertical', %Image::ExifTool::Minolta::afStatusInfo }, + 0x003c => { Name => 'AFStatusCenter-14', %Image::ExifTool::Minolta::afStatusInfo }, + 0x003e => { Name => 'AFStatusTopAssist-left', %Image::ExifTool::Minolta::afStatusInfo }, + 0x0040 => { Name => 'AFStatusTop', %Image::ExifTool::Minolta::afStatusInfo }, + 0x0042 => { Name => 'AFStatusTopAssist-right', %Image::ExifTool::Minolta::afStatusInfo }, + 0x0044 => { Name => 'AFStatusFarRight', %Image::ExifTool::Minolta::afStatusInfo }, + 0x0046 => { Name => 'AFStatusUpper-right', %Image::ExifTool::Minolta::afStatusInfo }, + 0x0048 => { Name => 'AFStatusRight', %Image::ExifTool::Minolta::afStatusInfo }, + 0x004a => { Name => 'AFStatusLower-right', %Image::ExifTool::Minolta::afStatusInfo }, + 0x004c => { Name => 'AFStatusCenterF2-8', %Image::ExifTool::Minolta::afStatusInfo }, + 0x0130 => { + Name => 'AFMicroAdjValue', + Condition => '$$self{Model} =~ /^DSLR-A(850|900)\b/', + ValueConv => '$val - 20', + ValueConvInv => '$val + 20', + }, + 0x0131 => { + Name => 'AFMicroAdjMode', + Condition => '$$self{Model} =~ /^DSLR-A(850|900)\b/', + Mask => 0x80, + PrintConv => { + 0 => 'Off', + 1 => 'On', + }, + }, + 305.1 => { # (0x131) + Name => 'AFMicroAdjRegisteredLenses', + Notes => 'number of registered lenses with a non-zero AFMicroAdjValue', + Condition => '$$self{Model} =~ /^DSLR-A(850|900)\b/', + Mask => 0x7f, + }, + # 0x0166 - 40 x 128 int8u values: AF Info Blocks for A850 and A900, not for A700 +); + +# camera information for other DSLR models (ref JR) +%Image::ExifTool::Sony::CameraInfo2 = ( + %binaryDataAttrs, + GROUPS => { 0 => 'MakerNotes', 2 => 'Camera' }, + NOTES => q{ + Camera information for the DSLR-A200, A230, A290, A300, A330, A350, A380 and + A390. + }, + 0x00 => { + Name => 'LensSpec', + Format => 'undef[8]', + ValueConv => \&ConvLensSpec, + ValueConvInv => \&ConvInvLensSpec, + PrintConv => \&PrintLensSpec, + PrintConvInv => \&PrintInvLensSpec, + }, + # 0x0010 - maybe to do with AFStatus: 0 na./Manual, 4 Failed, 16 Tracking, 64 Focused + 0x0014 => { + Name => 'AFPointSelected', + PrintConvColumns => 2, + PrintConv => { #JR (NC) same list as A100, A700/A900, as all have 9 point AF + 0 => 'Auto', + 1 => 'Center', + 2 => 'Top', + 3 => 'Upper-right', + 4 => 'Right', + 5 => 'Lower-right', + 6 => 'Bottom', + 7 => 'Lower-left', + 8 => 'Left', + 9 => 'Upper-left', + }, + }, + 0x0015 => { + Name => 'FocusModeSetting', + Notes => 'FocusModeSetting for other models', + PrintConv => { + 0 => 'Manual', + 1 => 'AF-S', + 2 => 'AF-C', + 3 => 'AF-A', + 4 => 'DMF', + }, + }, + # 0x0018 - AF sensor used for focusing for A200/A230/A290/A300/A330/A350/A380/A390; AF sensor layout: + # + # - - = AF sensor + # | | + = cross sensor + # + # - + - + # + # | | + # - + # + 0x0018 => { # used A100 list which appears to match + Name => 'AFPoint', + PrintConv => { + 0 => 'Top-right', + 1 => 'Bottom-right', + 2 => 'Bottom', + 3 => 'Middle Horizontal', + 4 => 'Center Vertical', + 5 => 'Top', + 6 => 'Top-left', + 7 => 'Bottom-left', + }, + }, + # AF Status for A200/A230/A290/A300/A330/A350/A380/A390: analogous to A100 in Minolta.pm + 0x001b => { Name => 'AFStatusActiveSensor', %Image::ExifTool::Minolta::afStatusInfo }, + 0x001d => { Name => 'AFStatusTop-right', %Image::ExifTool::Minolta::afStatusInfo }, + 0x001f => { Name => 'AFStatusBottom-right', %Image::ExifTool::Minolta::afStatusInfo }, + 0x0021 => { Name => 'AFStatusBottom', %Image::ExifTool::Minolta::afStatusInfo }, + # MiddleHorizontal is any of the 3 central horizontal sensors + 0x0023 => { Name => 'AFStatusMiddleHorizontal', %Image::ExifTool::Minolta::afStatusInfo }, + 0x0025 => { Name => 'AFStatusCenterVertical', %Image::ExifTool::Minolta::afStatusInfo }, + 0x0027 => { Name => 'AFStatusTop', %Image::ExifTool::Minolta::afStatusInfo }, + 0x0029 => { Name => 'AFStatusTop-left', %Image::ExifTool::Minolta::afStatusInfo }, + 0x002b => { Name => 'AFStatusBottom-left', %Image::ExifTool::Minolta::afStatusInfo }, + # the 3 MiddleHorizontal sensors + 0x002d => { Name => 'AFStatusLeft', %Image::ExifTool::Minolta::afStatusInfo }, + 0x002f => { Name => 'AFStatusCenterHorizontal', %Image::ExifTool::Minolta::afStatusInfo }, + 0x0031 => { Name => 'AFStatusRight', %Image::ExifTool::Minolta::afStatusInfo }, + # 0x0166 - 59 x 96 int8u values: AF Info Blocks for A230/A290/A330/A380/A390 + # 0x0182 - 58 x 88 int8u values: AF Info Blocks for A200/A300/A350 +); + +# Camera information for the A55 (ref PH) +# (also valid for A33, A35, A560, A580 - ref JR) +%Image::ExifTool::Sony::CameraInfo3 = ( + %binaryDataAttrs, + GROUPS => { 0 => 'MakerNotes', 2 => 'Camera' }, + IS_SUBDIR => [ 0x23 ], + NOTES => q{ + Camera information stored by the A33, A35, A55, A450, A500, A550, A560, + A580, NEX-3/5/5C/C3 and VG10E. Some tags are valid only for some of these + models. + }, + 0x00 => { #JR + Name => 'LensSpec', + Condition => '$$self{Model} !~ /^NEX-5C/', + Format => 'undef[8]', + ValueConv => \&ConvLensSpec, + ValueConvInv => \&ConvInvLensSpec, + PrintConv => \&PrintLensSpec, + PrintConvInv => \&PrintInvLensSpec, + }, + 0x0e => { #JR + Name => 'FocalLength', + Condition => '$$self{Model} !~ /^DSLR-(A450|A500|A550)$/', + Format => 'int16u', + Priority => 0, + ValueConv => '$val / 10', + ValueConvInv => '$val * 10', + PrintConv => 'sprintf("%.1f mm",$val)', + PrintConvInv => '$val =~ s/ mm//; $val', + }, + 0x10 => { #JR + Name => 'FocalLengthTeleZoom', + Condition => '$$self{Model} !~ /^DSLR-(A450|A500|A550)$/', + Format => 'int16u', + ValueConv => '$val * 2 / 3', + ValueConvInv => 'int($val * 3 / 2 + 0.5)', + PrintConv => 'sprintf("%.1f mm",$val)', + PrintConvInv => '$val =~ s/ mm//; $val', + }, +# +# Note: +# The below AF decoding covers cameras with 2 different AF systems, with overlapping offsets ! +# 1) DSLR-A450/A500/A550 with 9 point AF system: decoding/offsets identical to A200 - A390 in CameraInfo +# 2) SLT-A33/A35/A55 and DSLR-A560/A580 with 15 point AF system: similar/more info but at different offsets +# + 0x14 => { #JR + Name => 'AFPointSelected', + Condition => '$$self{Model} =~ /^(DSLR-A(450|500|550))\b/', + # (these cameras have a 9-point AF system, ref JR) + PrintConvColumns => 2, + PrintConv => { + 0 => 'Auto', # (seen in Wide mode and for Manual Focus) + 1 => 'Center', # seen for AFArea=Spot + 2 => 'Top', + 3 => 'Upper-right', + 4 => 'Right', + 5 => 'Lower-right', + 6 => 'Bottom', + 7 => 'Lower-left', + 8 => 'Left', + 9 => 'Upper-left', + }, + }, + 0x15 => { #JR + Name => 'FocusMode', + Condition => '$$self{Model} =~ /^(DSLR-A(450|500|550))\b/', + PrintConv => { + 0 => 'Manual', + 1 => 'AF-S', + 2 => 'AF-C', + 3 => 'AF-A', + }, + }, + 0x18 => { #JR + Name => 'AFPoint', + Condition => '$$self{Model} =~ /^DSLR-A(450|500|550)\b/', + PrintConv => { + 0 => 'Top-right', + 1 => 'Bottom-right', + 2 => 'Bottom', + 3 => 'Middle Horizontal', + 4 => 'Center Vertical', + 5 => 'Top', + 6 => 'Top-left', + 7 => 'Bottom-left', + }, + }, + 0x19 => { #JR + Name => 'FocusStatus', + Condition => '$$self{Model} =~ /^(SLT-|DSLR-A(560|580))\b/', + Notes => 'not valid with Contrast AF or for NEX models', + # seen the following values: + # 0 with MF (A35, A55V-HDR, A560, A580), non-AF lens (A35), and A580 Contrast-AF + # 4 with MF (A33, A55V), and A580 Contrast-AF + # 16 with AF-C (or AF-A) and focus OK + # 24 with AF-C (or AF-A) and unsharp or fast moving subject e.g. bird in flight + # 64 with AF-S (or AF-A) and focus OK + PrintConv => { + 0 => 'Manual - Not confirmed (0)', + 4 => 'Manual - Not confirmed (4)', + 16 => 'AF-C - Confirmed', + 24 => 'AF-C - Not Confirmed', + 64 => 'AF-S - Confirmed', + }, + }, + 0x1b => { #JR + Name => 'AFStatusActiveSensor', + Condition => '$$self{Model} =~ /^DSLR-A(450|500|550)\b/', + %Image::ExifTool::Minolta::afStatusInfo, + }, + 0x1c => { + Name => 'AFPointSelected', # (v8.88: renamed from LocalAFAreaPointSelected) + Condition => '$$self{Model} =~ /^(SLT-|DSLR-A(560|580))\b/', + Notes => 'not valid for Contrast AF', #JR + # (all of these cameras have an 15-point three-cross AF system, ref JR) + PrintConvColumns => 2, + PrintConv => { + 0 => 'Auto', # (seen in Wide mode) + 1 => 'Center', + 2 => 'Top', + 3 => 'Upper-right', + 4 => 'Right', + 5 => 'Lower-right', + 6 => 'Bottom', + 7 => 'Lower-left', + 8 => 'Left', + 9 => 'Upper-left', + 10 => 'Far Right', + 11 => 'Far Left', + 12 => 'Upper-middle', + 13 => 'Near Right', + 14 => 'Lower-middle', + 15 => 'Near Left', + }, + }, + 0x1d => [ + { + Name => 'FocusMode', + Condition => '$$self{Model} =~ /^(SLT-|DSLR-A(560|580))\b/', + PrintConv => { + 0 => 'Manual', + 1 => 'AF-S', + 2 => 'AF-C', + 3 => 'AF-A', + }, + },{ #JR + Name => 'AFStatusTop-right', + Condition => '$$self{Model} =~ /^DSLR-A(450|500|550)\b/', + %Image::ExifTool::Minolta::afStatusInfo, + }, + ], + 0x1f => { #JR + Name => 'AFStatusBottom-right', + Condition => '$$self{Model} =~ /^DSLR-A(450|500|550)\b/', + %Image::ExifTool::Minolta::afStatusInfo, + }, + 0x20 => { #JR + Name => 'AFPoint', # (v8.88: renamed from LocalAFAreaPointUsed) + Condition => '$$self{Model} =~ /^(SLT-|DSLR-A(560|580))\b/', + Notes => 'the AF sensor used for focusing. Not valid for Contrast AF', + PrintConvColumns => 2, + PrintConv => { + %afPoint15, + 255 => '(none)', #PH (A55, guess; also A35 with non-AF lens, ref JR) + }, + }, + 0x21 => [ #JR + { + Name => 'AFStatusActiveSensor', + Condition => '$$self{Model} =~ /^(SLT-|DSLR-A(560|580))\b/', + %Image::ExifTool::Minolta::afStatusInfo, + },{ + Name => 'AFStatusBottom', + Condition => '$$self{Model} =~ /^DSLR-A(450|500|550)\b/', + %Image::ExifTool::Minolta::afStatusInfo, + }, + ], + 0x23 => [ #JR + { + Name => 'AFStatus15', + Condition => '$$self{Model} =~ /^(SLT-|DSLR-A(560|580))\b/', + Format => 'int16s[18]', + SubDirectory => { TagTable => 'Image::ExifTool::Sony::AFStatus15' }, + },{ + Name => 'AFStatusMiddleHorizontal', # MiddleHorizontal is any of the 3 central horizontal sensors + Condition => '$$self{Model} =~ /^DSLR-A(450|500|550)\b/', + %Image::ExifTool::Minolta::afStatusInfo, + }, + ], + 0x25 => { Name => 'AFStatusCenterVertical', Condition => '$$self{Model} =~ /^DSLR-A(450|500|550)\b/', %Image::ExifTool::Minolta::afStatusInfo }, + 0x27 => { Name => 'AFStatusTop', Condition => '$$self{Model} =~ /^DSLR-A(450|500|550)\b/', %Image::ExifTool::Minolta::afStatusInfo }, + 0x29 => { Name => 'AFStatusTop-left', Condition => '$$self{Model} =~ /^DSLR-A(450|500|550)\b/', %Image::ExifTool::Minolta::afStatusInfo }, + 0x2b => { Name => 'AFStatusBottom-left', Condition => '$$self{Model} =~ /^DSLR-A(450|500|550)\b/', %Image::ExifTool::Minolta::afStatusInfo }, + # the 3 MiddleHorizontal sensors: + 0x2d => { Name => 'AFStatusLeft', Condition => '$$self{Model} =~ /^DSLR-A(450|500|550)\b/', %Image::ExifTool::Minolta::afStatusInfo }, + 0x2f => { Name => 'AFStatusCenterHorizontal', Condition => '$$self{Model} =~ /^DSLR-A(450|500|550)\b/', %Image::ExifTool::Minolta::afStatusInfo }, + 0x31 => { Name => 'AFStatusRight', Condition => '$$self{Model} =~ /^DSLR-A(450|500|550)\b/', %Image::ExifTool::Minolta::afStatusInfo }, + # 0x0166 - starting here there are 96 AF Info blocks of 155 bytes each for the SLT-A33/A35/A55 and DSLR-A560/A580, + # starting here there are 86 AF Info blocks of 174 bytes each for the DSLR-A450/A500/A550, + # but NOT for NEX, and not for the A580 in Contrast-AF mode (ref JR) + # The 43rd byte of each block for A580 appears to be the AFPoint as in offset 0x20, + # possibly also 73rd and 74th byte +); + +# Camera information for other models (ref PH) +%Image::ExifTool::Sony::CameraInfoUnknown = ( + %binaryDataAttrs, + GROUPS => { 0 => 'MakerNotes', 2 => 'Camera' }, +); + +# white balance and other camera information (ref PH) +%Image::ExifTool::Sony::FocusInfo = ( + %binaryDataAttrs, + GROUPS => { 0 => 'MakerNotes', 2 => 'Camera' }, + PRIORITY => 0, + NOTES => q{ + More camera settings and focus information decoded for models such as the + A200, A230, A290, A300, A330, A350, A380, A390, A700, A850 and A900. + }, + 0x0e => [{ #7/JR + Name => 'DriveMode2', + Condition => '$$self{Model} =~ /^DSLR-A(230|290|330|380|390)$/', + Notes => 'A230, A290, A330, A380 and A390', + ValueConvInv => '$val', + PrintHex => 1, + PrintConv => { # (values confirmed for specified models - PH) + 0x01 => 'Single Frame', # (A230,A330,A380) + 0x02 => 'Continuous High', #PH (A230,A330) + 0x04 => 'Self-timer 10 sec', # (A230) + 0x05 => 'Self-timer 2 sec, Mirror Lock-up', # (A230,A290,A330,A380,390) + 0x07 => 'Continuous Bracketing', # (A230,A330) + 0x0a => 'Remote Commander', # (A230) + 0x0b => 'Continuous Self-timer', # (A230,A330) + }, + },{ + Name => 'DriveMode2', + Notes => 'A200, A300, A350, A700, A850 and A900', + ValueConvInv => '$val', + PrintHex => 1, + PrintConv => { + 0x01 => 'Single Frame', + 0x02 => 'Continuous High', # A700/A900; not on A850 + 0x12 => 'Continuous Low', #JR + 0x04 => 'Self-timer 10 sec', + 0x05 => 'Self-timer 2 sec, Mirror Lock-up', + 0x06 => 'Single-frame Bracketing', + 0x07 => 'Continuous Bracketing', + 0x18 => 'White Balance Bracketing Low', #JR + 0x28 => 'White Balance Bracketing High', #JR + 0x19 => 'D-Range Optimizer Bracketing Low', #JR + 0x29 => 'D-Range Optimizer Bracketing High', #JR + 0x0a => 'Remote Commander', #JR + 0x0b => 'Mirror Lock-up', #JR (A850/A900; not on A700) + }, + }], + 0x10 => { #JR (1 and 2 inverted!) + Name => 'Rotation', + PrintConv => { + 0 => 'Horizontal (normal)', + 1 => 'Rotate 270 CW', + 2 => 'Rotate 90 CW', + }, + }, + 0x14 => { + Name => 'ImageStabilizationSetting', + PrintConv => { 0 => 'Off', 1 => 'On' }, + }, + 0x15 => { #7 + Name => 'DynamicRangeOptimizerMode', + PrintConv => { + 0 => 'Off', + 1 => 'Standard', + 2 => 'Advanced Auto', + 3 => 'Advanced Level', + }, + }, + 0x2b => { #JR seen 2,1,3 for both WB and DRO bracketing + Name => 'BracketShotNumber', + Notes => 'WB and DRO bracketing', + }, + 0x2c => { #JR + Name => 'WhiteBalanceBracketing', + PrintConv => { + 0 => 'Off', + 1 => 'Low', + 2 => 'High', + }, + }, + 0x2d => { #JR seen 2,1,3 for both WB and DRO bracketing + Name => 'BracketShotNumber2', + }, + 0x2e => { #JR + Name => 'DynamicRangeOptimizerBracket', + PrintConv => { + 0 => 'Off', + 1 => 'Low', + 2 => 'High', + }, + }, + 0x2f => { #JR seen 0,1,2 and 0,1,2,3,4 for 3 and 5 image bracketing sequences + Name => 'ExposureBracketShotNumber', + }, + 0x3f => { #JR + Name => 'ExposureProgram', + SeparateTable => 'ExposureProgram', + PrintConv => \%sonyExposureProgram, + }, + 0x41 => { #JR style actually used (combination of mode dial + creative style menu) + Name => 'CreativeStyle', + PrintConvColumns => 2, + PrintConv => { + 1 => 'Standard', + 2 => 'Vivid', + 3 => 'Portrait', + 4 => 'Landscape', + 5 => 'Sunset', + 6 => 'Night View/Portrait', + 8 => 'B&W', + 9 => 'Adobe RGB', # A700 + 11 => 'Neutral', + 12 => 'Clear', #7 + 13 => 'Deep', #7 + 14 => 'Light', #7 + 15 => 'Autumn Leaves', #7 + 16 => 'Sepia', #7 + }, + }, + 0x6d => { + Name => 'ISOSetting', + ValueConv => '$val ? exp(($val/8-6)*log(2))*100 : $val', + ValueConvInv => '$val ? 8*(log($val/100)/log(2)+6) : $val', + PrintConv => '$val ? sprintf("%.0f",$val) : "Auto"', + PrintConvInv => '$val =~ /auto/i ? 0 : $val', + }, + 0x6f => { + Name => 'ISO', + ValueConv => '$val ? exp(($val/8-6)*log(2))*100 : $val', + ValueConvInv => '$val ? 8*(log($val/100)/log(2)+6) : $val', + PrintConv => '$val ? sprintf("%.0f",$val) : "Auto"', + PrintConvInv => '$val =~ /auto/i ? 0 : $val', + }, + 0x77 => { #JR + Name => 'DynamicRangeOptimizerMode', + PrintConv => { + 0 => 'Off', + 1 => 'Standard', + 2 => 'Advanced Auto', + 3 => 'Advanced Level', + }, + }, + 0x79 => 'DynamicRangeOptimizerLevel', +# 0x06f1 - int16u LensType, Condition => '$$self{Model} =~ /^DSLR-A(700|850|900)$/', +# 0x4a81 - int16u LensType, Condition => '$$self{Model} !~ /^DSLR-A(700|850|900)$/', +# 0x4a84 - int16uRev LensType, Condition => '$$self{Model} =~ /^DSLR-A(700|850|900)$/', + 0x0846 => { #13 + Name => 'ShutterCount', # (=ImageCount for these models) + Condition => '$$self{Model} =~ /^DSLR-A(230|290|330|380|390|850|900)$/', + Format => 'int32u', + Notes => 'only valid for some DSLR models', + RawConv => '$val & 0x00ffffff', #PH + }, + 0x09bb => { #PH (validated only for DSLR-A850) + Name => 'FocusPosition', + Condition => '$$self{Model} =~ /^DSLR-A(200|230|290|300|330|350|380|390|700|850|900)$/', + Notes => 'only valid for some DSLR models', + # 128 = infinity -- see Composite:FocusDistance below + }, + 0x1110 => { # (9600 bytes: 4 sets of 40x30 int16u values in the range 0-8191) + Name => 'TiffMeteringImage', + Format => 'undef[9600]', + Notes => q{ + 13-bit RBGG (?) 40x30 pixels, presumably metering info, extracted as a + 16-bit TIFF image; + }, + ValueConv => sub { + my ($val, $et) = @_; + return undef unless length $val >= 9600; + return \ "Binary data 7404 bytes" unless $et->Options('Binary'); + my @dat = unpack('n*', $val); + # TIFF header for a 16-bit RGB 10dpi 40x30 image + $val = Image::ExifTool::MakeTiffHeader(40,30,3,16,10); + # re-order data to RGB pixels + my ($i, @val); + for ($i=0; $i<40*30; ++$i) { + # data is 13-bit (max 8191), shift left to fill 16 bits + # (typically, this gives a very dark image since the data should + # really be anti-logged to convert from EV to perceived brightness) +# push @val, $dat[$i]<<3, $dat[$i+2400]<<3, $dat[$i+1200]<<3; + push @val, int(5041.1*log($dat[$i]+1)/log(2)), int(5041.1*log($dat[$i+2400]+1)/log(2)), int(5041.1*log($dat[$i+1200]+1)/log(2)); + } + $val .= pack('v*', @val); # add TIFF strip data + return \$val; + }, + }, +); + +# more camera setting information (ref JR) +# - many of these tags are the same as in CameraSettings3 +%Image::ExifTool::Sony::MoreInfo = ( + PROCESS_PROC => \&ProcessMoreInfo, + WRITE_PROC => \&ProcessMoreInfo, + GROUPS => { 0 => 'MakerNotes', 2 => 'Camera' }, + NOTES => q{ + More camera settings information decoded for the A450, A500, A550, A560, + A580, A33, A35, A55, NEX-3/5/C3 and VG10E. + }, + 0x0001 => { # (256 bytes) + Name => 'MoreSettings', + SubDirectory => { TagTable => 'Image::ExifTool::Sony::MoreSettings' }, + }, + # (byte sizes for a single A580 image -- not checked for other images) + 0x0002 => [ # (256 bytes) + { + Name => 'FaceInfo', + Condition => '$$self{Model} !~ /^DSLR-(A450|A500|A550)$/', + SubDirectory => { TagTable => 'Image::ExifTool::Sony::FaceInfo' }, + },{ + Name => 'FaceInfoA', + Condition => '$$self{Model} =~ /^DSLR-(A450|A500|A550)$/', + SubDirectory => { TagTable => 'Image::ExifTool::Sony::FaceInfoA' }, + }, + ], + # 0x0101: 512 bytes + # 0x0102: 1804 bytes + # 0x0103: 176 bytes + # 0x0104: 1088 bytes + # 0x0105: 160 bytes (all zero unless flash is used, ref JR) + # 0x0106: 256 bytes (faces detected if first byte is non-zero? ref JR) + 0x0107 => { # (7200 bytes: 3 sets of 40x30 int16u values in the range 0-1023) + Name => 'TiffMeteringImage', + Notes => q{ + 10-bit RGB data from the 1200 AE metering segments, extracted as a 16-bit + TIFF image + }, + ValueConv => sub { + my ($val, $et) = @_; + return undef unless length $val >= 7200; + return \ "Binary data 7404 bytes" unless $et->Options('Binary'); + my @dat = unpack('v*', $val); + # TIFF header for a 16-bit RGB 10dpi 40x30 image + $val = Image::ExifTool::MakeTiffHeader(40,30,3,16,10); + # re-order data to RGB pixels + my ($i, @val); + for ($i=0; $i<40*30; ++$i) { + # data is 10-bit (max 1023), shift left to fill 16 bits + # (typically, this gives a very dark image since the data should + # really be anti-logged to convert from EV to perceived brightness) + push @val, $dat[$i]<<6, $dat[$i+1200]<<6, $dat[$i+2400]<<6; + } + $val .= pack('v*', @val); # add TIFF strip data + return \$val; + }, + }, + # 0x0108: 140 bytes + # 0x0109: 256 bytes + # 0x010a: 256 bytes + # 0x0306: 276 bytes + # 0x0307: 256 bytes + # 0x0308: 96 bytes + # 0x0309: 112 bytes + # 0xffff: 788 bytes + 0x0201 => { # (368 bytes) + Name => 'MoreInfo0201', + SubDirectory => { TagTable => 'Image::ExifTool::Sony::MoreInfo0201' }, + }, + # 0x0202: 144 bytes + # 0x0401: 4608 bytes + 0x0401 => { + Name => 'MoreInfo0401', + SubDirectory => { TagTable => 'Image::ExifTool::Sony::MoreInfo0401' }, + }, +); + +%Image::ExifTool::Sony::MoreInfo0201 = ( + %binaryDataAttrs, + GROUPS => { 0 => 'MakerNotes', 2 => 'Camera' }, + PRIORITY => 0, +# 0x005d - also from 0 - 255, in sync with but lower than 0x005e, depending on FocalLength +# 0x005e => { +# # FocusPosition for A560/A580/A33/A35/A55V +# # seen values from 80 - 255 (= infinity) -- see Composite:FocusDistance2 below +# Name => 'FocusPosition2_0201', +# Condition => '$$self{Model} !~ /^(NEX-|DSLR-(A450|A500|A550)$)/', +# }, +# 0x0093 - also from 0 - 255, in sync with but lower than 0x0094, depending on FocalLength +# 0x0094 => { +# # FocusPosition for A450/A500/A550 +# # seen values from 80 - 255 (= infinity) -- see Composite:FocusDistance2 below +# Name => 'FocusPosition2_0201', +# Condition => '$$self{Model} =~ /^(DSLR-(A450|A500|A550)$)/', +# }, + 0x011b => { #13 + Name => 'ImageCount', + Condition => '$$self{Model} !~ /^DSLR-A(450|500|550)$/', #JR + Format => 'int32u', + Notes => 'not valid for the A450, A500 or A550', + RawConv => '$val & 0x00ffffff', + }, + 0x0125 => { #13 + Name => 'ShutterCount', + Condition => '$$self{Model} !~ /^DSLR-A(450|500|550)$/', #JR + Format => 'int32u', + Notes => 'not valid for the A450, A500 or A550', + RawConv => '$val & 0x00ffffff', + }, + 0x014a => { #13 + Name => 'ShutterCount', # (=ImageCount for these models) + Condition => '$$self{Model} =~ /^DSLR-A(450|500|550)$/', #JR + Format => 'int32u', + Notes => 'A450, A500 and A550 only', + RawConv => '$val & 0x00ffffff', + }, +); + +%Image::ExifTool::Sony::MoreInfo0401 = ( + %binaryDataAttrs, + GROUPS => { 0 => 'MakerNotes', 2 => 'Camera' }, + PRIORITY => 0, + 0x044e => { #JR + Name => 'ShotNumberSincePowerUp', + Condition => '$$self{Model} !~ /^NEX-(3|5)$/', + Format => 'int32u', + Notes => 'Not valid for the NEX-3 or NEX-5', + RawConv => '$val & 0x00ffffff', + }, +# 0x101e - int16u LensType Condition => '$$self{Model} =~ /^SLT-A(33|55V)/', +# 0x1022 - int16u LensType Condition => '$$self{Model} =~ /^DSLR-A(560|580)/', +# 0x102a - int16u LensType Condition => '$$self{Model} =~ /^(SLT-A35|NEX-C3)/', + +# 0x10a8 - int16u LensType Condition => '$$self{Model} =~ /^SLT-A(33|55V)/', +# 0x10ac - int16u LensType Condition => '$$self{Model} =~ /^DSLR-A(560|580)/', +# 0x10b4 - int16u LensType Condition => '$$self{Model} =~ /^(SLT-A35|NEX-C3)/', +# +# 0x10f7 - int16u LensType Condition => '$$self{Model} =~ /^SLT-A(33|55V)/', +# 0x10fb - int16u LensType Condition => '$$self{Model} =~ /^DSLR-A(560|580)/', +# 0x1103 - int16u LensType Condition => '$$self{Model} =~ /^(SLT-A35|NEX-C3)/', +# +# 0x1181 - int16u LensType Condition => '$$self{Model} =~ /^SLT-A(33|55V)/', +# 0x1185 - int16u LensType Condition => '$$self{Model} =~ /^DSLR-A(560|580)/', +# 0x118d - int16u LensType Condition => '$$self{Model} =~ /^(SLT-A35|NEX-C3)/', +); + +# more camera setting information (ref JR) +# - many of these tags are the same as in CameraSettings3 +%Image::ExifTool::Sony::MoreSettings = ( + %binaryDataAttrs, + GROUPS => { 0 => 'MakerNotes', 2 => 'Camera' }, + PRIORITY => 0, + 0x01 => { # interesting: somewhere between CameraSettings3 0x04 and 0x34 + Name => 'DriveMode2', + PrintHex => 1, + PrintConv => { + 0x10 => 'Single Frame', + 0x21 => 'Continuous High', # also automatically selected for Scene mode Sports-action (0x05=52) + 0x22 => 'Continuous Low', + 0x30 => 'Speed Priority Continuous', + 0x51 => 'Self-timer 10 sec', + 0x52 => 'Self-timer 2 sec, Mirror Lock-up', + 0x71 => 'Continuous Bracketing 0.3 EV', + 0x75 => 'Continuous Bracketing 0.7 EV', + 0x91 => 'White Balance Bracketing Low', + 0x92 => 'White Balance Bracketing High', + 0xc0 => 'Remote Commander', + }, + }, + 0x02 => { + Name => 'ExposureProgram', + SeparateTable => 'ExposureProgram2', + PrintConv => \%sonyExposureProgram2, + }, + 0x03 => { + Name => 'MeteringMode', + PrintConv => { + 1 => 'Multi-segment', + 2 => 'Center-weighted average', + 3 => 'Spot', + }, + }, + 0x04 => { + Name => 'DynamicRangeOptimizerSetting', + PrintConv => { + 1 => 'Off', + 16 => 'On (Auto)', + 17 => 'On (Manual)', + }, + }, + 0x05 => 'DynamicRangeOptimizerLevel', + 0x06 => { + Name => 'ColorSpace', + PrintConv => { + 1 => 'sRGB', + 2 => 'Adobe RGB', + }, + }, + 0x07 => { + Name => 'CreativeStyleSetting', + PrintConvColumns => 2, + PrintConv => { + 16 => 'Standard', + 32 => 'Vivid', + 64 => 'Portrait', + 80 => 'Landscape', + 96 => 'B&W', + 160 => 'Sunset', + }, + }, + 0x08 => { #JR + Name => 'ContrastSetting', + Format => 'int8s', + PrintConv => '$val > 0 ? "+$val" : $val', + PrintConvInv => '$val', + }, + 0x09 => { + Name => 'SaturationSetting', + Format => 'int8s', + PrintConv => '$val > 0 ? "+$val" : $val', + PrintConvInv => '$val', + }, + 0x0a => { + Name => 'SharpnessSetting', + Format => 'int8s', + PrintConv => '$val > 0 ? "+$val" : $val', + PrintConvInv => '$val', + }, + 0x0d => { + Name => 'WhiteBalanceSetting', + # many guessed, based on "logical system" as observed for Daylight and Shade and steps of 16 between the modes + PrintHex => 1, + PrintConvColumns => 2, + PrintConv => \%whiteBalanceSetting, + SeparateTable => 1, + }, + 0x0e => { + Name => 'ColorTemperatureSetting', + # matches "0xb021 ColorTemperature" when WB set to "Custom" or "Color Temperature/Color Filter" + ValueConv => '$val * 100', + ValueConvInv => '$val / 100', + PrintConv => '"$val K"', + PrintConvInv => '$val =~ s/ ?K$//i; $val', + }, + 0x0f => { + Name => 'ColorCompensationFilterSet', + # seen 0, 1-9 and 245-255, corresponding to 0, M1-M9 and G9-G1 on camera display + # matches "0xb022 ColorCompensationFilter" when WB set to "Custom" or "Color Temperature/Color Filter" + Format => 'int8s', + Notes => 'negative is green, positive is magenta', + PrintConv => '$val > 0 ? "+$val" : $val', + PrintConvInv => '$val', + }, + 0x10 => { + Name => 'FlashMode', + PrintConvColumns => 2, + PrintConv => { + 1 => 'Flash Off', + 16 => 'Autoflash', + 17 => 'Fill-flash', + 18 => 'Slow Sync', + 19 => 'Rear Sync', + 20 => 'Wireless', + }, + }, + 0x11 => { + Name => 'LongExposureNoiseReduction', + PrintConv => { + 1 => 'Off', + 16 => 'On', # (unused or dark subject) + }, + }, + 0x12 => { + Name => 'HighISONoiseReduction', + PrintConv => { + 16 => 'Low', + 17 => 'High', + 19 => 'Auto', + }, + }, + 0x13 => { # why is this not valid for A450/A500/A550 ? + Name => 'FocusMode', + Condition => '$$self{Model} !~ /^DSLR-(A450|A500|A550)$/', + PrintConv => { + 17 => 'AF-S', + 18 => 'AF-C', + 19 => 'AF-A', + 32 => 'Manual', + 48 => 'DMF', #(NC) (seen for NEX-5) + }, + }, + 0x15 => { + Name => 'MultiFrameNoiseReduction', + Condition => '$$self{Model} !~ /^DSLR-(A450|A500|A550)$/', + PrintConv => { + 0 => 'n/a', # seen for A450/A500/A550 + 1 => 'Off', + 16 => 'On', + 255 => 'None', # seen for NEX-3/5/C3 + }, + }, + 0x16 => { + Name => 'HDRSetting', + PrintConv => { + 1 => 'Off', + 16 => 'On (Auto)', + 17 => 'On (Manual)', + }, + }, + 0x17 => { + Name => 'HDRLevel', + PrintConvColumns => 3, + PrintConv => { + 33 => '1 EV', + 34 => '1.5 EV', #JR (NC) + 35 => '2 EV', + 36 => '2.5 EV', #JR (NC) + 37 => '3 EV', + 38 => '3.5 EV', #PH (NC) + 39 => '4 EV', + 40 => '5 EV', + 41 => '6 EV', + }, + }, + 0x18 => { + Name => 'ViewingMode', + PrintConv => { + 16 => 'ViewFinder', + 33 => 'Focus Check Live View', + 34 => 'Quick AF Live View', + }, + }, + 0x19 => { + Name => 'FaceDetection', + PrintConv => { + 1 => 'Off', + 16 => 'On', + }, + }, + 0x1a => { + Name => 'CustomWB_RBLevels', + # matches "0x7313 WB_RGGBLevels" when WB set to "Custom", except factor of 4 + Format => 'int16uRev[2]', + }, + # From here different and overlapping offsets for 3 groups of cameras: + # 1) DSLR-A450/A500/A550 + # 2) NEX-3/5/5C + # 3) DSLR-A560/A580, NEX-C3/VG10/VG10E, SLT-A33/A35/A55V + 0x1e => [{ + Name => 'BrightnessValue', + Condition => '$$self{Model} =~ /^DSLR-(A450|A500|A550)/', + Notes => 'A450, A500 and A550', + ValueConv => '($val-106)/8', + ValueConvInv => '$val * 8 + 106', + },{ + Name => 'ExposureCompensationSet', + Notes => 'other models', + ValueConv => '($val - 128) / 24', #PH + ValueConvInv => 'int($val * 24 + 128.5)', + PrintConv => '$val ? sprintf("%+.1f",$val) : 0', + PrintConvInv => 'Image::ExifTool::Exif::ConvertFraction($val)', + }], + 0x1f => [{ + Name => 'ISO', + Condition => '$$self{Model} =~ /^DSLR-(A450|A500|A550)/', + Notes => 'A450, A500 and A550', + ValueConv => '$val ? exp(($val/8-6)*log(2))*100 : $val', + ValueConvInv => '$val ? 8*(log($val/100)/log(2)+6) : $val', + PrintConv => '$val ? sprintf("%.0f",$val) : "Auto"', + PrintConvInv => '$val =~ /auto/i ? 0 : $val', + },{ + Name => 'FlashExposureCompSet', + Notes => 'other models', + Description => 'Flash Exposure Comp. Setting', + ValueConv => '($val - 128) / 24', #PH + ValueConvInv => 'int($val * 24 + 128.5)', + PrintConv => '$val ? sprintf("%+.1f",$val) : 0', + PrintConvInv => 'Image::ExifTool::Exif::ConvertFraction($val)', + }], + 0x20 => [{ + Name => 'FNumber', + Condition => '$$self{Model} =~ /^DSLR-(A450|A500|A550)/', + Notes => 'A450, A500 and A550', + ValueConv => '2 ** (($val/8 - 1) / 2)', + ValueConvInv => 'int((log($val) * 2 / log(2) + 1) * 8 + 0.5)', + PrintConv => 'Image::ExifTool::Exif::PrintFNumber($val)', + PrintConvInv => '$val', + },{ + Name => 'LiveViewAFMethod', + Condition => '$$self{Model} !~ /^NEX-(3|5|5C)/', + Notes => 'other models except the NEX-3/5/5C', + PrintConv => { + 0 => 'n/a', + 1 => 'Phase-detect AF', + 2 => 'Contrast AF', + # Contrast AF is only available with SSM/SAM lenses and in Focus Check LV, + # NOT in Quick AF LV, and is automatically set when mounting SSM/SAM lens + # - changes into Phase-AF when switching to Quick AF LV. + }, + }], + 0x21 => [{ + Name => 'ExposureTime', + Condition => '$$self{Model} =~ /^DSLR-(A450|A500|A550)/', + Notes => 'A450, A500 and A550', + ValueConv => '$val ? 2 ** (6 - $val/8) : 0', + ValueConvInv => '$val ? int((6 - log($val) / log(2)) * 8 + 0.5) : 0', + PrintConv => '$val ? Image::ExifTool::Exif::PrintExposureTime($val) : "Bulb"', + PrintConvInv => 'lc($val) eq "bulb" ? 0 : Image::ExifTool::Exif::ConvertFraction($val)', + },{ + Name => 'ISO', + Condition => '$$self{Model} =~ /^NEX-(3|5|5C)/', + Notes => 'NEX-3/5/5C', + ValueConv => '$val ? exp(($val/8-6)*log(2))*100 : $val', + ValueConvInv => '$val ? 8*(log($val/100)/log(2)+6) : $val', + PrintConv => '$val ? sprintf("%.0f",$val) : "Auto"', + PrintConvInv => '$val =~ /auto/i ? 0 : $val', + }], + 0x22 => { + Name => 'FNumber', + Condition => '$$self{Model} =~ /^NEX-(3|5|5C)/', + Notes => 'NEX-3/5/5C only', + ValueConv => '2 ** (($val/8 - 1) / 2)', + ValueConvInv => 'int((log($val) * 2 / log(2) + 1) * 8 + 0.5)', + PrintConv => 'Image::ExifTool::Exif::PrintFNumber($val)', + PrintConvInv => '$val', + }, + 0x23 => [{ + Name => 'FocalLength2', + Condition => '$$self{Model} =~ /^DSLR-(A450|A500|A550)/', + Notes => 'A450, A500 and A550', + ValueConv => '10 * 2 ** (($val-28)/16)', + ValueConvInv => '$val>0 ? log($val/10)/log(2) * 16 + 28 : 0', + PrintConv => 'sprintf("%.1f mm",$val)', + PrintConvInv => '$val=~s/\s*mm$//; $val', + },{ + Name => 'ExposureTime', + Condition => '$$self{Model} =~ /^NEX-(3|5|5C)/', + Notes => 'NEX-3/5/5C', + ValueConv => '$val ? 2 ** (6 - $val/8) : 0', + ValueConvInv => '$val ? int((6 - log($val) / log(2)) * 8 + 0.5) : 0', + PrintConv => '$val ? Image::ExifTool::Exif::PrintExposureTime($val) : "Bulb"', + PrintConvInv => 'lc($val) eq "bulb" ? 0 : Image::ExifTool::Exif::ConvertFraction($val)', + }], + 0x24 => { + Name => 'ExposureCompensation2', + Condition => '$$self{Model} =~ /^DSLR-(A450|A500|A550)/', + Notes => 'A450, A500 and A550', + Format => 'int16s', + ValueConv => '$val / 8', + ValueConvInv => '$val * 8', + PrintConv => '$val ? sprintf("%+.1f",$val) : 0', + PrintConvInv => '$val', + }, + 0x25 => [{ + Name => 'FocalLength2', + Condition => '$$self{Model} =~ /^NEX-(3|5|5C)/', + Notes => 'NEX-3/5/5C', + ValueConv => '10 * 2 ** (($val-28)/16)', + ValueConvInv => '$val>0 ? log($val/10)/log(2) * 16 + 28 : 0', + PrintConv => 'sprintf("%.1f mm",$val)', + PrintConvInv => '$val=~s/\s*mm$//; $val', + },{ + Name => 'ISO', + Condition => '$$self{Model} !~ /^DSLR-(A450|A500|A550)/', + Notes => 'other models except the A450, A500 and A550', + ValueConv => '$val ? exp(($val/8-6)*log(2))*100 : $val', + ValueConvInv => '$val ? 8*(log($val/100)/log(2)+6) : $val', + PrintConv => '$val ? sprintf("%.0f",$val) : "Auto"', + PrintConvInv => '$val =~ /auto/i ? 0 : $val', + }], + 0x26 => [{ + Name => 'FlashExposureCompSet2', + Description => 'Flash Exposure Comp. Setting 2', + Condition => '$$self{Model} =~ /^DSLR-(A450|A500|A550)/', + Notes => 'A450, A500 and A550', + Format => 'int16s', + ValueConv => '$val / 8', + ValueConvInv => '$val * 8', + PrintConv => '$val ? sprintf("%+.1f",$val) : 0', + PrintConvInv => '$val', + },{ + Name => 'ExposureCompensation2', + Condition => '$$self{Model} =~ /^NEX-(3|5|5C)/', + Notes => 'NEX-3/5/5C', + Format => 'int16s', + ValueConv => '$val / 8', + ValueConvInv => '$val * 8', + PrintConv => '$val ? sprintf("%+.1f",$val) : 0', + PrintConvInv => '$val', + },{ + Name => 'FNumber', + Notes => 'other models', + ValueConv => '2 ** (($val/8 - 1) / 2)', + ValueConvInv => 'int((log($val) * 2 / log(2) + 1) * 8 + 0.5)', + PrintConv => 'Image::ExifTool::Exif::PrintFNumber($val)', + PrintConvInv => '$val', + }], + 0x27 => { + Name => 'ExposureTime', + Condition => '$$self{Model} !~ /^NEX-(3|5|5C)|DSLR-(A450|A500|A550)/', + Notes => 'models other than the A450, A500, A550 and NEX-3/5/5C', + ValueConv => '$val ? 2 ** (6 - $val/8) : 0', + ValueConvInv => '$val ? int((6 - log($val) / log(2)) * 8 + 0.5) : 0', + PrintConv => '$val ? Image::ExifTool::Exif::PrintExposureTime($val) : "Bulb"', + PrintConvInv => 'lc($val) eq "bulb" ? 0 : Image::ExifTool::Exif::ConvertFraction($val)', + }, + 0x28 => { + Name => 'Orientation2', + Condition => '$$self{Model} =~ /^DSLR-(A450|A500|A550)/', + Notes => 'A450, A500 and A550', + PrintConv => { + 1 => 'Horizontal (normal)', + 2 => 'Rotate 180', + 6 => 'Rotate 90 CW', + 8 => 'Rotate 270 CW', + }, + }, + 0x29 => [{ + # FocusPosition for A450/A500/A550 + # seen values from 80 - 255 (= infinity) -- see Composite:FocusDistance2 below + Name => 'FocusPosition2', + Condition => '$$self{Model} =~ /^DSLR-(A450|A500|A550)/', + Notes => 'A450, A500 and A550', + },{ + # value increase of 16 corresponds to doubling of FocalLength + Name => 'FocalLength2', + Condition => '$$self{Model} !~ /^NEX-(3|5|5C)/', + Notes => 'other models except the NEX-3/5/5C', + ValueConv => '10 * 2 ** (($val-28)/16)', + ValueConvInv => '$val>0 ? log($val/10)/log(2) * 16 + 28 : 0', + PrintConv => 'sprintf("%.1f mm",$val)', + PrintConvInv => '$val=~s/\s*mm$//; $val', + }], + 0x2a => [{ + Name => 'FlashAction', + Condition => '$$self{Model} =~ /^DSLR-(A450|A500|A550)/', + Notes => 'A450, A500 and A550', + PrintConv => { + 0 => 'Did not fire', + 1 => 'Fired', + }, + },{ + Name => 'ExposureCompensation2', + Condition => '$$self{Model} !~ /^NEX-(3|5|5C)/', + Notes => 'other models except the NEX-3/5/5C', + Format => 'int16s', + ValueConv => '$val / 8', + ValueConvInv => '$val * 8', + PrintConv => '$val ? sprintf("%+.1f",$val) : 0', + PrintConvInv => '$val', + }], + 0x2b => { + # FocusPosition for NEX-3/5/5C + # seen values from 80 - 255 (= infinity) -- see Composite:FocusDistance2 below + Name => 'FocusPosition2', + Condition => '$$self{Model} =~ /^NEX-(3|5|5C)/', + Notes => 'NEX-3/5/5C only', + }, + 0x2c => [{ + Name => 'FocusMode2', + Condition => '$$self{Model} =~ /^DSLR-(A450|A500|A550)/', + Notes => 'A450, A500 and A550', + PrintConv => { + 0 => 'AF', + 1 => 'MF', + }, + },{ + Name => 'FlashAction', + Condition => '$$self{Model} =~ /^NEX-(3|5|5C)/', + Notes => 'NEX-3/5/5C FlashAction2', + PrintConv => { + 0 => 'Did not fire', + 1 => 'Fired', + }, + },{ + Name => 'FlashExposureCompSet2', + Description => 'Flash Exposure Comp. Setting 2', + Notes => 'other models FlashExposureCompSet2', + Format => 'int16s', + ValueConv => '$val / 8', + ValueConvInv => '$val * 8', + PrintConv => '$val ? sprintf("%+.1f",$val) : 0', + PrintConvInv => '$val', + }], + 0x2e => [{ + Name => 'FocusMode2', + Condition => '$$self{Model} =~ /^NEX-(3|5|5C)/', + Notes => 'NEX-3/5/5C', + PrintConv => { + 0 => 'AF', + 1 => 'MF', + }, + },{ + Name => 'Orientation2', # seen some A55 images where this does not match the other Orientation tags + Condition => '$$self{Model} !~ /^DSLR-(A450|A500|A550)/', + Notes => 'other models except the A450, A500 and A550', + PrintConv => { + 1 => 'Horizontal (normal)', + 2 => 'Rotate 180', + 6 => 'Rotate 90 CW', + 8 => 'Rotate 270 CW', + }, + }], + 0x2f => { + # FocusPosition for A560/A580/A33/A35/A55V and NEX-C3/VG10/VG10E + # seen values from 80 - 255 (= infinity) -- see Composite:FocusDistance2 below + Name => 'FocusPosition2', + Condition => '$$self{Model} !~ /^NEX-(3|5|5C)|DSLR-(A450|A500|A550)/', + Notes => 'models other than the A450, A500, A550 and NEX-3/5/5C', + }, + 0x30 => { + Name => 'FlashAction', + Condition => '$$self{Model} !~ /^NEX-(3|5|5C)|DSLR-(A450|A500|A550)/', + Notes => 'models other than the A450, A500, A550 and NEX-3/5/5C', + PrintConv => { + 0 => 'Did not fire', + 1 => 'Fired', + }, + }, + 0x32 => { + Name => 'FocusMode2', + Condition => '$$self{Model} !~ /^NEX-(3|5|5C)|DSLR-(A450|A500|A550)/', + Notes => 'models other than the A450, A500, A550 and NEX-3/5/5C', + PrintConv => { + 0 => 'AF', + 1 => 'MF', + }, + }, + 0x0077 => { + Name => 'FlashAction2', + Condition => '$$self{Model} =~ /^DSLR-(A450|A500|A550)/', + PrintConv => { + 0 => 'Did not fire', + 2 => 'External Flash fired (2)', + 3 => 'Built-in Flash fired', + 4 => 'External Flash fired (4)', # what is difference with 2 ? + }, + }, + 0x0078 => { + Name => 'FlashActionExternal', + Condition => '$$self{Model} =~ /^NEX-(3|5|5C)/', + PrintConv => { + 136 => 'Did not fire', + 121 => 'Fired', # what is difference with 122 ? + 122 => 'Fired', + }, + }, + 0x007c => { + Name => 'FlashActionExternal', + Condition => '$$self{Model} !~ /^NEX-(3|5|5C)|DSLR-(A450|A500|A550)/', + PrintConv => { + 136 => 'Did not fire', + 167 => 'Fired', + 182 => 'Fired, HSS', + }, + }, + 0x0082 => { + Name => 'FlashStatus', + Condition => '$$self{Model} =~ /^NEX-(3|5|5C)/', + PrintConv => { + 0 => 'None', + 2 => 'External', + }, + }, + 0x0086 => { + Name => 'FlashStatus', + Condition => '$$self{Model} !~ /^NEX-(3|5|5C)|DSLR-(A450|A500|A550)/', + PrintConv => { + 0 => 'None', + 1 => 'Built-in', + 2 => 'External', + }, + }, +); + +# Face detection information (ref JR) +my %faceInfo = ( + Format => 'int16u[4]', + # re-order to top,left,height,width and scale to full-sized image like other Sony models + ValueConv => 'my @v=split(" ",$val); $_*=15 foreach @v; "$v[1] $v[0] $v[3] $v[2]"', + ValueConvInv => 'my @v=split(" ",$val); $_=int($_/15+0.5) foreach @v; "$v[1] $v[0] $v[3] $v[2]"', +); +%Image::ExifTool::Sony::FaceInfo = ( + %binaryDataAttrs, + GROUPS => { 0 => 'MakerNotes', 2 => 'Camera' }, + FORMAT => 'int16u', + DATAMEMBER => [ 0x00 ], + 0x00 => { + Name => 'FacesDetected', + DataMember => 'FacesDetected', + Format => 'int16s', + RawConv => '$$self{FacesDetected} = ($val == -1 ? 0 : $val); $val', + PrintConv => { + OTHER => sub { shift }, # pass other values straight through + -1 => 'n/a', + }, + }, + 0x01 => { + Name => 'Face1Position', + Condition => '$$self{FacesDetected} >= 1', + %faceInfo, + Notes => q{ + re-ordered and scaled to return the top, left, height and width of detected + face, with coordinates relative to the full-sized unrotated image and + increasing Y downwards + }, + }, + 0x06 => { + Name => 'Face2Position', + Condition => '$$self{FacesDetected} >= 2', + %faceInfo, + }, + 0x0b => { + Name => 'Face3Position', + Condition => '$$self{FacesDetected} >= 3', + %faceInfo, + }, + 0x10 => { + Name => 'Face4Position', + Condition => '$$self{FacesDetected} >= 4', + %faceInfo, + }, + 0x15 => { + Name => 'Face5Position', + Condition => '$$self{FacesDetected} >= 5', + %faceInfo, + }, + 0x1a => { + Name => 'Face6Position', + Condition => '$$self{FacesDetected} >= 6', + %faceInfo, + }, + 0x1f => { + Name => 'Face7Position', + Condition => '$$self{FacesDetected} >= 7', + %faceInfo, + }, + 0x24 => { + Name => 'Face8Position', + Condition => '$$self{FacesDetected} >= 8', + %faceInfo, + }, +); + +%Image::ExifTool::Sony::FaceInfoA = ( # different offsets for A450/A500/A550 + %binaryDataAttrs, + GROUPS => { 0 => 'MakerNotes', 2 => 'Camera' }, + FORMAT => 'int16u', + DATAMEMBER => [ 0x02, 0x03, 0x08 ], +# +# The FacesDetected number at 0x03 below is often 1 lower than the one at Tag900b 0x02. +# The number of Face Positions starting at 0x5b (max. 4) corresponds to the number at 0x03. +# The number of Face Positions starting at 0x0b usually corresponds to the FacesDetected number of Tag900b... +# Therefore created the extra condition at 0x0b (11.1) to output an available FacePosition, even when 0x03=0... +# + 0x02 => { + Name => 'FaceTest2', + DataMember => 'FaceTest2', + Hidden => 1, + RawConv => '$$self{FaceTest2} = $val; $$self{OPTIONS}{Unknown}<2 ? undef : $val', + }, + 0x03 => { + Name => 'FacesDetected', + DataMember => 'FacesDetected', + RawConv => '$$self{FacesDetected} = ($val > 8 ? 0 : $val); $val', + ValueConv => '$val > 8 ? 0 : $val', + }, + 0x08 => { + Name => 'FaceTest8', + DataMember => 'FaceTest8', + Hidden => 1, + RawConv => '$$self{FaceTest8} = $val; $$self{OPTIONS}{Unknown}<2 ? undef : $val', + }, +# 0x0b - start of 8 Face Positions of 10 int16u values each + 0x0b => { + Name => 'PotentialFace1Position', + Condition => q{ + $$self{FacesDetected} >= 1 or + ($$self{FaceTest8} > 0 and ($$self{FaceTest2} == 1 or $$self{FaceTest2} == 257)) + }, + %faceInfo, + }, + 0x15 => { + Name => 'PotentialFace2Position', + Condition => '$$self{FacesDetected} >= 2 or ($$self{FacesDetected} == 1 and $$self{FaceTest8} > 0)', + %faceInfo, + }, + 0x1f => { + Name => 'PotentialFace3Position', + Condition => '$$self{FacesDetected} >= 3 or ($$self{FacesDetected} == 2 and $$self{FaceTest8} > 0)', + %faceInfo, + }, + 0x29 => { + Name => 'PotentialFace4Position', + Condition => '$$self{FacesDetected} >= 4 or ($$self{FacesDetected} == 3 and $$self{FaceTest8} > 0)', + %faceInfo, + }, + 0x33 => { + Name => 'PotentialFace5Position', + Condition => '$$self{FacesDetected} >= 5 or ($$self{FacesDetected} == 4 and $$self{FaceTest8} > 0)', + %faceInfo, + }, + 0x3d => { + Name => 'PotentialFace6Position', + Condition => '$$self{FacesDetected} >= 6 or ($$self{FacesDetected} == 5 and $$self{FaceTest8} > 0)', + %faceInfo, + }, + 0x47 => { + Name => 'PotentialFace7Position', + Condition => '$$self{FacesDetected} >= 7 or ($$self{FacesDetected} == 6 and $$self{FaceTest8} > 0)', + %faceInfo, + }, + 0x51 => { + Name => 'PotentialFace8Position', + Condition => '$$self{FacesDetected} >= 8 or ($$self{FacesDetected} == 7 and $$self{FaceTest8} > 0)', + %faceInfo, + }, +# 0x5b - start of max. 4 further Face Positions here + 0x5b => { + Name => 'Face1Position', + Condition => '$$self{FacesDetected} >= 1', + %faceInfo, + }, + 0x65 => { + Name => 'Face2Position', + Condition => '$$self{FacesDetected} >= 2', + %faceInfo, + }, + 0x6f => { + Name => 'Face3Position', + Condition => '$$self{FacesDetected} >= 3', + %faceInfo, + }, + 0x79 => { + Name => 'Face4Position', + Condition => '$$self{FacesDetected} >= 4', + %faceInfo, + }, +); + +# Camera settings (ref PH) (decoded mainly from A200) +%Image::ExifTool::Sony::CameraSettings = ( + %binaryDataAttrs, + GROUPS => { 0 => 'MakerNotes', 2 => 'Camera' }, + FORMAT => 'int16u', + PRIORITY => 0, + NOTES => 'Camera settings for the A200, A300, A350, A700, A850 and A900.', + 0x00 => { #JR + Name => 'ExposureTime', + ValueConv => '$val ? 2 ** (6 - $val/8) : 0', + ValueConvInv => '$val ? int((6 - log($val) / log(2)) * 8 + 0.5) : 0', + PrintConv => '$val ? Image::ExifTool::Exif::PrintExposureTime($val) : "Bulb"', + PrintConvInv => 'lc($val) eq "bulb" ? 0 : Image::ExifTool::Exif::ConvertFraction($val)', + }, + 0x01 => { #JR + Name => 'FNumber', + ValueConv => '2 ** (($val/8 - 1) / 2)', + ValueConvInv => 'int((log($val) * 2 / log(2) + 1) * 8 + 0.5)', + PrintConv => 'Image::ExifTool::Exif::PrintFNumber($val)', + PrintConvInv => '$val', + }, + 0x02 => { #JR (requires external flash) + Name => 'HighSpeedSync', + PrintConv => { + 0 => 'Off', + 1 => 'On', + }, + }, + 0x03 => { #JR + Name => 'ExposureCompensationSet', + ValueConv => '($val - 128) / 24', + ValueConvInv => 'int($val * 24 + 128.5)', + PrintConv => '$val ? sprintf("%+.1f",$val) : 0', + PrintConvInv => 'Image::ExifTool::Exif::ConvertFraction($val)', + }, + 0x04 => { #7/JR + Name => 'DriveMode', + Mask => 0xff, # (not sure what upper byte is for) + PrintHex => 1, + PrintConv => { + 0x01 => 'Single Frame', + 0x02 => 'Continuous High', # A700/A900; not on A850 + 0x12 => 'Continuous Low', #JR + 0x04 => 'Self-timer 10 sec', + 0x05 => 'Self-timer 2 sec, Mirror Lock-up', + 0x06 => 'Single-frame Bracketing', + 0x07 => 'Continuous Bracketing', # (A200 val=0x1107) + 0x18 => 'White Balance Bracketing Low', #JR + 0x28 => 'White Balance Bracketing High', #JR + 0x19 => 'D-Range Optimizer Bracketing Low', #JR + 0x29 => 'D-Range Optimizer Bracketing High', #JR + 0x0a => 'Remote Commander', #JR + 0x0b => 'Mirror Lock-up', #JR (A850/A900; not on A700) + }, + }, + 0x05 => { #JR + Name => 'WhiteBalanceSetting', + PrintConv => { + 2 => 'Auto', + 4 => 'Daylight', + 5 => 'Fluorescent', + 6 => 'Tungsten', + 7 => 'Flash', + 16 => 'Cloudy', + 17 => 'Shade', + 18 => 'Color Temperature/Color Filter', + 32 => 'Custom 1', + 33 => 'Custom 2', + 34 => 'Custom 3', + }, + }, + 0x06 => { #7 (A700) (ref JR: at least also valid for A200, ValueConv as for ColorCompensationFilterSet) + Name => 'WhiteBalanceFineTune', + ValueConv => '$val > 128 ? $val - 256 : $val', + ValueConvInv => '$val < 0 ? $val + 256 : $val', + }, + 0x07 => { #JR as set in WB "Color Temperature/Color Filter" and in White Balance Bracketing + Name => 'ColorTemperatureSet', + ValueConv => '$val * 100', + ValueConvInv => '$val / 100', + PrintConv => '"$val K"', + PrintConvInv => '$val =~ s/ ?K$//i; $val', + }, + 0x08 => { #JR as set in WB "Color Temperature/Color Filter" + Name => 'ColorCompensationFilterSet', + Notes => 'negative is green, positive is magenta', + ValueConv => '$val > 128 ? $val - 256 : $val', + ValueConvInv => '$val < 0 ? $val + 256 : $val', + PrintConv => '$val > 0 ? "+$val" : $val', + PrintConvInv => '$val', + }, + 0x0c => { #JR as set in WB "Custom" and in White Balance Bracketing + Name => 'ColorTemperatureCustom', + ValueConv => '$val * 100', + ValueConvInv => '$val / 100', + PrintConv => '"$val K"', + PrintConvInv => '$val =~ s/ ?K$//i; $val', + }, + 0x0d => { #JR as set in WB "Custom" + Name => 'ColorCompensationFilterCustom', + Notes => 'negative is green, positive is magenta', + ValueConv => '$val > 128 ? $val - 256 : $val', + ValueConvInv => '$val < 0 ? $val + 256 : $val', + PrintConv => '$val > 0 ? "+$val" : $val', + PrintConvInv => '$val', + }, + 0x0f => { #JR + Name => 'WhiteBalance', + PrintConv => { + 2 => 'Auto', + 4 => 'Daylight', + 5 => 'Fluorescent', + 6 => 'Tungsten', + 7 => 'Flash', + 12 => 'Color Temperature', + 13 => 'Color Filter', + 14 => 'Custom', + 16 => 'Cloudy', + 17 => 'Shade', + }, + }, + 0x10 => { #7 (A700) + Name => 'FocusModeSetting', + PrintConv => { + 0 => 'Manual', + 1 => 'AF-S', + 2 => 'AF-C', + 3 => 'AF-A', + 4 => 'DMF', #JR + }, + }, + 0x11 => { #JD (A700) + Name => 'AFAreaMode', + PrintConv => { + 0 => 'Wide', + 1 => 'Local', + 2 => 'Spot', + }, + }, + 0x12 => { #7 (A700) + Name => 'AFPointSetting', + Format => 'int16u', + # The AF point as selected by the user in AFAreaMode=Local or Spot; + # Reported value remains at the last-set position in AFAreaModes=Wide. + # A200, A300, A350: 9-point centre-cross (ref JR) + # A700: 11-point centre-dual-cross (ref JR) + # A850, A900: 9-point centre-dual-cross with 10 assist-points (ref JR) + PrintConvColumns => 2, + PrintConv => { + 1 => 'Center', + 2 => 'Top', + 3 => 'Upper-right', + 4 => 'Right', + 5 => 'Lower-right', + 6 => 'Bottom', + 7 => 'Lower-left', + 8 => 'Left', + 9 => 'Upper-left', + 10 => 'Far Right', # (presumably A700 only) + 11 => 'Far Left', # (presumably A700 only) + }, + }, + 0x13 => { #JR + Name => 'FlashMode', + PrintConv => { + 0 => 'Autoflash', + 2 => 'Rear Sync', + 3 => 'Wireless', + 4 => 'Fill-flash', + 5 => 'Flash Off', + 6 => 'Slow Sync', + }, + }, + 0x14 => { #JR + Name => 'FlashExposureCompSet', + Description => 'Flash Exposure Comp. Setting', + # (as pre-selected by the user, not zero if flash didn't fire) + ValueConv => '($val - 128) / 24', #PH + ValueConvInv => 'int($val * 24 + 128.5)', + PrintConv => '$val ? sprintf("%+.1f",$val) : 0', + PrintConvInv => 'Image::ExifTool::Exif::ConvertFraction($val)', + }, + 0x15 => { #7 + Name => 'MeteringMode', + PrintConv => { + 1 => 'Multi-segment', + 2 => 'Center-weighted average', + 4 => 'Spot', + }, + }, + 0x16 => { + Name => 'ISOSetting', + # 0 indicates 'Auto' (I think) + ValueConv => '$val ? exp(($val/8-6)*log(2))*100 : $val', + ValueConvInv => '$val ? 8*(log($val/100)/log(2)+6) : $val', + PrintConv => '$val ? sprintf("%.0f",$val) : "Auto"', + PrintConvInv => '$val =~ /auto/i ? 0 : $val', + }, + 0x18 => { #7 + Name => 'DynamicRangeOptimizerMode', + PrintConv => { + 0 => 'Off', + 1 => 'Standard', + 2 => 'Advanced Auto', + 3 => 'Advanced Level', + }, + }, + 0x19 => { #7 + Name => 'DynamicRangeOptimizerLevel', + }, + 0x1a => { # style actually used (combination of mode dial + creative style menu) + Name => 'CreativeStyle', + PrintConvColumns => 2, + PrintConv => { + 1 => 'Standard', + 2 => 'Vivid', + 3 => 'Portrait', + 4 => 'Landscape', + 5 => 'Sunset', + 6 => 'Night View/Portrait', + 8 => 'B&W', + 9 => 'Adobe RGB', # A700 + 11 => 'Neutral', + 12 => 'Clear', #7 + 13 => 'Deep', #7 + 14 => 'Light', #7 + 15 => 'Autumn Leaves', #7 + 16 => 'Sepia', #7 + }, + }, + 0x1b => { #JR + Name => 'ColorSpace', + PrintConv => { + 0 => 'sRGB', + 1 => 'Adobe RGB', # (A850, selected via Colorspace menu item) + 5 => 'Adobe RGB (A700)', # (A700, selected via CreativeStyle menu) + }, + }, + 0x1c => { + Name => 'Sharpness', + ValueConv => '$val - 10', + ValueConvInv => '$val + 10', + PrintConv => '$val > 0 ? "+$val" : $val', + PrintConvInv => '$val', + }, + 0x1d => { + Name => 'Contrast', + ValueConv => '$val - 10', + ValueConvInv => '$val + 10', + PrintConv => '$val > 0 ? "+$val" : $val', + PrintConvInv => '$val', + }, + 0x1e => { + Name => 'Saturation', + ValueConv => '$val - 10', + ValueConvInv => '$val + 10', + PrintConv => '$val > 0 ? "+$val" : $val', + PrintConvInv => '$val', + }, + 0x1f => { #7 + Name => 'ZoneMatchingValue', + ValueConv => '$val - 10', + ValueConvInv => '$val + 10', + PrintConv => '$val > 0 ? "+$val" : $val', + PrintConvInv => '$val', + }, + 0x22 => { #7 + Name => 'Brightness', + ValueConv => '$val - 10', + ValueConvInv => '$val + 10', + PrintConv => '$val > 0 ? "+$val" : $val', + PrintConvInv => '$val', + }, + 0x23 => { + Name => 'FlashControl', + PrintConv => { + 0 => 'ADI', + 1 => 'Pre-flash TTL', + 2 => 'Manual', + }, + }, + 0x28 => { #7 + Name => 'PrioritySetupShutterRelease', + PrintConv => { + 0 => 'AF', + 1 => 'Release', + }, + }, + 0x29 => { #7 + Name => 'AFIlluminator', + PrintConv => { + 0 => 'Auto', + 1 => 'Off', + }, + }, + 0x2a => { #7 + Name => 'AFWithShutter', + PrintConv => { 0 => 'On', 1 => 'Off' }, + }, + 0x2b => { #7 + Name => 'LongExposureNoiseReduction', + PrintConv => { 0 => 'Off', 1 => 'On' }, + }, + 0x2c => { #7 + Name => 'HighISONoiseReduction', + PrintConv => { + 0 => 'Normal', + 1 => 'Low', + 2 => 'High', + 3 => 'Off', + }, + }, + 0x2d => { #7 + Name => 'ImageStyle', + PrintConvColumns => 2, + PrintConv => { + 1 => 'Standard', + 2 => 'Vivid', + 3 => 'Portrait', #PH + 4 => 'Landscape', #PH + 5 => 'Sunset', #PH + 7 => 'Night View/Portrait', #PH (A200/A350 when CreativeStyle was 6!) + 8 => 'B&W', #PH (guess) + 9 => 'Adobe RGB', + 11 => 'Neutral', + 129 => 'StyleBox1', + 130 => 'StyleBox2', + 131 => 'StyleBox3', + 132 => 'StyleBox4', #JR (A850) + 133 => 'StyleBox5', #JR (A850) + 134 => 'StyleBox6', #JR (A850) + }, + }, + 0x2e => { #JR (may not apply to A200/A300/A350 -- they don't have the AF/MF button) + Name => 'FocusModeSwitch', + PrintConv => { + 0 => 'AF', + 1 => 'Manual', + }, + }, + 0x2f => { #JR + Name => 'ShutterSpeedSetting', + Notes => 'used in M, S and Program Shift S modes', + ValueConv => '$val ? 2 ** (6 - $val/8) : 0', + ValueConvInv => '$val ? int((6 - log($val) / log(2)) * 8 + 0.5) : 0', + PrintConv => '$val ? Image::ExifTool::Exif::PrintExposureTime($val) : "Bulb"', + PrintConvInv => 'lc($val) eq "bulb" ? 0 : Image::ExifTool::Exif::ConvertFraction($val)', + }, + 0x30 => { #JR + Name => 'ApertureSetting', + Notes => 'used in M, A and Program Shift A modes', + ValueConv => '2 ** (($val/8 - 1) / 2)', + ValueConvInv => 'int((log($val) * 2 / log(2) + 1) * 8 + 0.5)', + PrintConv => 'Image::ExifTool::Exif::PrintFNumber($val)', + PrintConvInv => '$val', + }, + 0x3c => { + Name => 'ExposureProgram', + SeparateTable => 'ExposureProgram', + PrintConv => \%sonyExposureProgram, + }, + 0x3d => { + Name => 'ImageStabilizationSetting', + PrintConv => { 0 => 'Off', 1 => 'On' }, + }, + 0x3e => { #JR + Name => 'FlashAction', + PrintConv => { + 0 => 'Did not fire', + 1 => 'Fired', + 2 => 'External Flash, Did not fire', + 3 => 'External Flash, Fired', + }, + }, + 0x3f => { # (verified for A330/A380) + Name => 'Rotation', + PrintConv => { + 0 => 'Horizontal (normal)', + 1 => 'Rotate 90 CW', #(NC) + 2 => 'Rotate 270 CW', + }, + }, + 0x40 => { #JR + Name => 'AELock', + PrintConv => { + 1 => 'Off', + 2 => 'On', + }, + }, + 0x4c => { #JR + Name => 'FlashAction2', + PrintConv => { + 1 => 'Fired, Autoflash', + 2 => 'Fired, Fill-flash', + 3 => 'Fired, Rear Sync', + 4 => 'Fired, Wireless', + 5 => 'Did not fire', + 6 => 'Fired, Slow Sync', + 17 => 'Fired, Autoflash, Red-eye reduction', + 18 => 'Fired, Fill-flash, Red-eye reduction', + 34 => 'Fired, Fill-flash, HSS', + }, + }, + 0x4d => { #JR + Name => 'FocusMode', # (focus mode actually used) + PrintConv => { + 0 => 'Manual', + 1 => 'AF-S', + 2 => 'AF-C', + 3 => 'AF-A', + 4 => 'DMF', #JR + }, + }, + 0x50 => { #JR + Name => 'BatteryState', + PrintConv => { + 2 => 'Empty', # 0% + 3 => 'Very Low', # 1 - 20% + 4 => 'Low', # 21 - 50% + 5 => 'Sufficient', # 51 - 80% + 6 => 'Full', # > 80% + }, + }, + 0x51 => { #JR + Name => 'BatteryLevel', + PrintConv => '"$val%"', + PrintConvInv => '$val=~s/\s*\%//; $val', + }, + 0x53 => { #JR + Name => 'FocusStatus', + PrintConv => { + 0 => 'Not confirmed', + 4 => 'Not confirmed, Tracking', + BITMASK => { + 0 => 'Confirmed', + 1 => 'Failed', + 2 => 'Tracking', + }, + }, + }, + 0x54 => { + Name => 'SonyImageSize', + PrintConv => { + 1 => 'Large', + 2 => 'Medium', + 3 => 'Small', + }, + }, + 0x55 => { #7 + Name => 'AspectRatio', + PrintConv => { + 1 => '3:2', + 2 => '16:9', + }, + }, + 0x56 => { #PH/7 + Name => 'Quality', + PrintConv => { + 0 => 'RAW', + 2 => 'CRAW', + 34 => 'RAW + JPEG', + 35 => 'CRAW + JPEG', + 16 => 'Extra Fine', + 32 => 'Fine', + 48 => 'Standard', + }, + }, + 0x58 => { #7 + Name => 'ExposureLevelIncrements', + PrintConv => { + 33 => '1/3 EV', + 50 => '1/2 EV', + }, + }, + 0x6a => { #JR + Name => 'RedEyeReduction', + PrintConv => { + 0 => 'Off', + 1 => 'On', + }, + }, + 0x9a => { #JR + Name => 'FolderNumber', + Mask => 0x03ff, # (not sure what the upper 6 bits are for) + PrintConv => 'sprintf("%.3d",$val)', + PrintConvInv => '$val', + }, + 0x9b => { #JR + Name => 'ImageNumber', + Mask => 0x3fff, # (not sure what the upper 2 bits are for) + PrintConv => 'sprintf("%.4d",$val)', + PrintConvInv => '$val', + }, +); + +# Camera settings (ref PH) (A230, A290, A330, A380 and A390) +%Image::ExifTool::Sony::CameraSettings2 = ( + %binaryDataAttrs, + GROUPS => { 0 => 'MakerNotes', 2 => 'Camera' }, + FORMAT => 'int16u', + PRIORITY => 0, + NOTES => 'Camera settings for the A230, A290, A330, A380 and A390.', +### 0x00-0x03: same TagID as CameraSettings + 0x00 => { #JR + Name => 'ExposureTime', + ValueConv => '$val ? 2 ** (6 - $val/8) : 0', + ValueConvInv => '$val ? int((6 - log($val) / log(2)) * 8 + 0.5) : 0', + PrintConv => '$val ? Image::ExifTool::Exif::PrintExposureTime($val) : "Bulb"', + PrintConvInv => 'lc($val) eq "bulb" ? 0 : Image::ExifTool::Exif::ConvertFraction($val)', + }, + 0x01 => { #JR + Name => 'FNumber', + ValueConv => '2 ** (($val/8 - 1) / 2)', + ValueConvInv => 'int((log($val) * 2 / log(2) + 1) * 8 + 0.5)', + PrintConv => 'Image::ExifTool::Exif::PrintFNumber($val)', + PrintConvInv => '$val', + }, + 0x02 => { #JR (requires external flash) + Name => 'HighSpeedSync', + PrintConv => { + 0 => 'Off', + 1 => 'On', + }, + }, + 0x03 => { #JR + Name => 'ExposureCompensationSet', + ValueConv => '($val - 128) / 24', + ValueConvInv => 'int($val * 24 + 128.5)', + PrintConv => '$val ? sprintf("%+.1f",$val) : 0', + PrintConvInv => 'Image::ExifTool::Exif::ConvertFraction($val)', + }, +### 0x04-0x11: subtract 1 from CameraSettings TagID + 0x04 => { #JR + Name => 'WhiteBalanceSetting', + PrintConv => { + 2 => 'Auto', + 4 => 'Daylight', + 5 => 'Fluorescent', + 6 => 'Tungsten', + 7 => 'Flash', + 16 => 'Cloudy', + 17 => 'Shade', + 18 => 'Color Temperature/Color Filter', + 32 => 'Custom 1', + 33 => 'Custom 2', + 34 => 'Custom 3', + }, + }, + 0x05 => { #JR + Name => 'WhiteBalanceFineTune', + ValueConv => '$val > 128 ? $val - 256 : $val', + ValueConvInv => '$val < 0 ? $val + 256 : $val', + }, + 0x06 => { #JR as set in WB "Color Temperature/Color Filter" and in White Balance Bracketing + Name => 'ColorTemperatureSet', + ValueConv => '$val * 100', + ValueConvInv => '$val / 100', + PrintConv => '"$val K"', + PrintConvInv => '$val =~ s/ ?K$//i; $val', + }, + 0x07 => { #JR as set in WB "Color Temperature/Color Filter" + Name => 'ColorCompensationFilterSet', + Notes => 'negative is green, positive is magenta', + ValueConv => '$val > 128 ? $val - 256 : $val', + ValueConvInv => '$val < 0 ? $val + 256 : $val', + PrintConv => '$val > 0 ? "+$val" : $val', + PrintConvInv => '$val', + }, + 0x08 => { #JR + Name => 'CustomWB_RGBLevels', + Format => 'int16u[3]', + }, + 0x0b => { #JR as set in WB "Custom" and in White Balance Bracketing + Name => 'ColorTemperatureCustom', + ValueConv => '$val * 100', + ValueConvInv => '$val / 100', + PrintConv => '"$val K"', + PrintConvInv => '$val =~ s/ ?K$//i; $val', + }, + 0x0c => { #JR as set in WB "Custom" + Name => 'ColorCompensationFilterCustom', + Notes => 'negative is green, positive is magenta', + ValueConv => '$val > 128 ? $val - 256 : $val', + ValueConvInv => '$val < 0 ? $val + 256 : $val', + PrintConv => '$val > 0 ? "+$val" : $val', + PrintConvInv => '$val', + }, + 0x0e => { #JR + Name => 'WhiteBalance', + PrintConv => { + 2 => 'Auto', + 4 => 'Daylight', + 5 => 'Fluorescent', + 6 => 'Tungsten', + 7 => 'Flash', + 12 => 'Color Temperature', + 13 => 'Color Filter', + 14 => 'Custom', + 16 => 'Cloudy', + 17 => 'Shade', + }, + }, + 0x0f => { #JR/PH (educated guess) + Name => 'FocusModeSetting', + PrintConv => { + 0 => 'Manual', + 1 => 'AF-S', + 2 => 'AF-C', + 3 => 'AF-A', + # seen 5 for A380 (FocusMode was Manual and FocusStatus was Confirmed) + }, + }, + 0x10 => { #JR/PH (educated guess) + Name => 'AFAreaMode', + PrintConv => { + 0 => 'Wide', + 1 => 'Local', + 2 => 'Spot', + }, + }, + 0x11 => { #JR/PH (educated guess) + Name => 'AFPointSetting', + Format => 'int16u', + # The AF point as selected by the user in AFAreaMode=Local or Spot; + # Reported value remains at the last-set position in AFAreaModes=Wide. + # (all of these cameras have a 9-point centre-cross AF system, ref JR) + PrintConvColumns => 2, + PrintConv => { + 1 => 'Center', + 2 => 'Top', + 3 => 'Upper-right', + 4 => 'Right', + 5 => 'Lower-right', + 6 => 'Bottom', + 7 => 'Lower-left', + 8 => 'Left', + 9 => 'Upper-left', + }, + }, +### 0x12-0x18: subtract 2 from CameraSettings TagID + 0x12 => { #JR + Name => 'FlashExposureCompSet', + Description => 'Flash Exposure Comp. Setting', + # (as pre-selected by the user, not zero if flash didn't fire) + ValueConv => '($val - 128) / 24', #PH + ValueConvInv => 'int($val * 24 + 128.5)', + PrintConv => '$val ? sprintf("%+.1f",$val) : 0', + PrintConvInv => 'Image::ExifTool::Exif::ConvertFraction($val)', + }, + 0x13 => { + Name => 'MeteringMode', + PrintConv => { + 1 => 'Multi-segment', + 2 => 'Center-weighted average', + 4 => 'Spot', + }, + }, + 0x14 => { # A330/A380 + Name => 'ISOSetting', + # 0 indicates 'Auto' (?) + ValueConv => '$val ? exp(($val/8-6)*log(2))*100 : $val', + ValueConvInv => '$val ? 8*(log($val/100)/log(2)+6) : $val', + PrintConv => '$val ? sprintf("%.0f",$val) : "Auto"', + PrintConvInv => '$val =~ /auto/i ? 0 : $val', + }, + 0x16 => { + Name => 'DynamicRangeOptimizerMode', + PrintConv => { + 0 => 'Off', + 1 => 'Standard', + 2 => 'Advanced Auto', + 3 => 'Advanced Level', + }, + }, + 0x17 => 'DynamicRangeOptimizerLevel', + 0x18 => { # A380 + Name => 'CreativeStyle', + PrintConvColumns => 2, + PrintConv => { + 1 => 'Standard', + 2 => 'Vivid', + 3 => 'Portrait', + 4 => 'Landscape', + 5 => 'Sunset', + 6 => 'Night View/Portrait', + 8 => 'B&W', + # (these models don't have Neutral - PH) + }, + }, +### 0x19-0x1b: subtract 3 from CameraSettings TagID + 0x19 => { + Name => 'Sharpness', + ValueConv => '$val - 10', + ValueConvInv => '$val + 10', + PrintConv => '$val > 0 ? "+$val" : $val', + PrintConvInv => '$val', + }, + 0x1a => { + Name => 'Contrast', + ValueConv => '$val - 10', + ValueConvInv => '$val + 10', + PrintConv => '$val > 0 ? "+$val" : $val', + PrintConvInv => '$val', + }, + 0x1b => { + Name => 'Saturation', + ValueConv => '$val - 10', + ValueConvInv => '$val + 10', + PrintConv => '$val > 0 ? "+$val" : $val', + PrintConvInv => '$val', + }, +### 0x1c-0x24: subtract 4 from CameraSettings TagID (not sure about 0x1c) + 0x1f => { #PH (educated guess) + Name => 'FlashControl', + PrintConv => { + 0 => 'ADI', + 1 => 'Pre-flash TTL', + 2 => 'Manual', + }, + }, +### 0x25-0x27: subtract 6 from CameraSettings TagID + 0x25 => { #PH + Name => 'LongExposureNoiseReduction', + PrintConv => { 0 => 'Off', 1 => 'On' }, + }, + 0x26 => { #PH + Name => 'HighISONoiseReduction', + # (Note: the order is different from that in CameraSettings) + PrintConv => { + 0 => 'Off', + 1 => 'Low', + 2 => 'Normal', + 3 => 'High', + }, + }, + 0x27 => { #PH + Name => 'ImageStyle', + PrintConvColumns => 2, + PrintConv => { + 1 => 'Standard', + 2 => 'Vivid', + 3 => 'Portrait', #PH + 4 => 'Landscape', #PH + 5 => 'Sunset', #PH + 7 => 'Night View/Portrait', #PH (A200 when CreativeStyle was 6!) + 8 => 'B&W', #PH (A380) + # (these models don't have Neutral - PH) + }, + }, +### 0x28-0x3b: subtract 7 from CameraSettings TagID + 0x28 => { #PH + Name => 'ShutterSpeedSetting', + Notes => 'used in M, S and Program Shift S modes', + ValueConv => '$val ? 2 ** (6 - $val/8) : 0', + ValueConvInv => '$val ? int((6 - log($val) / log(2)) * 8 + 0.5) : 0', + PrintConv => '$val ? Image::ExifTool::Exif::PrintExposureTime($val) : "Bulb"', + PrintConvInv => 'lc($val) eq "bulb" ? 0 : Image::ExifTool::Exif::ConvertFraction($val)', + }, + 0x29 => { #PH + Name => 'ApertureSetting', + Notes => 'used in M, A and Program Shift A modes', + ValueConv => '2 ** (($val/8 - 1) / 2)', + ValueConvInv => 'int((log($val) * 2 / log(2) + 1) * 8 + 0.5)', + PrintConv => 'Image::ExifTool::Exif::PrintFNumber($val)', + PrintConvInv => '$val', + }, +### 0x3c-0x59: same TagID as CameraSettings + 0x3c => { + Name => 'ExposureProgram', + SeparateTable => 'ExposureProgram', + PrintConv => \%sonyExposureProgram, + }, + 0x3d => { # (copied from CameraSettings, ref JR) + Name => 'ImageStabilizationSetting', + PrintConv => { 0 => 'Off', 1 => 'On' }, + }, + 0x3e => { #JR + Name => 'FlashAction', + PrintConv => { + 0 => 'Did not fire', + 1 => 'Fired', + 2 => 'External Flash, Did not fire', + 3 => 'External Flash, Fired', + }, + }, + 0x3f => { # (verified for A330/A380) + Name => 'Rotation', + PrintConv => { + 0 => 'Horizontal (normal)', + 1 => 'Rotate 90 CW', #(NC) + 2 => 'Rotate 270 CW', + }, + }, + 0x40 => { #JR + Name => 'AELock', + PrintConv => { + 1 => 'Off', + 2 => 'On', + }, + }, + 0x4c => { #JR + Name => 'FlashAction2', + PrintConv => { + 1 => 'Fired, Autoflash', + 2 => 'Fired, Fill-flash', + 3 => 'Fired, Rear Sync', + 4 => 'Fired, Wireless', + 5 => 'Did not fire', + 6 => 'Fired, Slow Sync', + 17 => 'Fired, Autoflash, Red-eye reduction', + 18 => 'Fired, Fill-flash, Red-eye reduction', + 34 => 'Fired, Fill-flash, HSS', + }, + }, + 0x4d => { #JR + Name => 'FocusMode', # (focus mode actually used) + PrintConv => { + 0 => 'Manual', + 1 => 'AF-S', + 2 => 'AF-C', + 3 => 'AF-A', + }, + }, + 0x53 => { #JR (copied from CameraSettings, but all bits may not be applicable for these models) + Name => 'FocusStatus', + PrintConv => { + 0 => 'Not confirmed', + 4 => 'Not confirmed, Tracking', + BITMASK => { + 0 => 'Confirmed', + 1 => 'Failed', + 2 => 'Tracking', + }, + }, + }, + 0x54 => { + Name => 'SonyImageSize', + PrintConv => { + 1 => 'Large', + 2 => 'Medium', + 3 => 'Small', + }, + }, + 0x55 => { # (copied from CameraSettings, ref JR) + Name => 'AspectRatio', + PrintConv => { + 1 => '3:2', + 2 => '16:9', + }, + }, + 0x56 => { # (copied from CameraSettings, ref JR) + Name => 'Quality', + PrintConv => { + 0 => 'RAW', + 2 => 'CRAW', + 34 => 'RAW + JPEG', + 35 => 'CRAW + JPEG', + 16 => 'Extra Fine', + 32 => 'Fine', + 48 => 'Standard', + }, + }, + 0x58 => { # (copied from CameraSettings, ref JR) + Name => 'ExposureLevelIncrements', + PrintConv => { + 33 => '1/3 EV', + 50 => '1/2 EV', + }, + }, +### 0x5a onwards: subtract 1 from CameraSettings TagID + # (0x69 not confirmed) + #0x69 => { #JR + # Name => 'RedEyeReduction', + # PrintConv => { + # 0 => 'Off', + # 1 => 'On', + # }, + #}, + 0x7e => { #JR + Name => 'DriveMode', + Mask => 0xff, # (not sure what upper byte is for) + PrintConv => { # (values confirmed for specified models - PH) + 1 => 'Single Frame', # (A230,A330,A380) + 2 => 'Continuous High', #PH (A230,A330) + 4 => 'Self-timer 10 sec', # (A230) + 5 => 'Self-timer 2 sec, Mirror Lock-up', # (A230,A290,A330,A380,390) + 7 => 'Continuous Bracketing', # (A230 val=0x1107, A330 val=0x1307 [0.7 EV]) + 10 => 'Remote Commander', # (A230) + 11 => 'Continuous Self-timer', # (A230 val=0x800b [5 shots], A330 val=0x400b [3 shots]) + }, + }, + 0x7f => { #JR + Name => 'FlashMode', + PrintConv => { + 0 => 'Autoflash', + 2 => 'Rear Sync', + 3 => 'Wireless', + 4 => 'Fill-flash', + 5 => 'Flash Off', + 6 => 'Slow Sync', + }, + }, + 0x83 => { #PH + Name => 'ColorSpace', + PrintConv => { + 5 => 'Adobe RGB', + 6 => 'sRGB', + }, + }, +); + +# more Camera settings (ref PH) +# This was decoded for the A55, but it seems to apply to the following models: +# A33, A35, A55, A450, A500, A550, A560, A580, NEX-3, NEX-5, NEX-C3 and NEX-VG10E +%Image::ExifTool::Sony::CameraSettings3 = ( + %binaryDataAttrs, + GROUPS => { 0 => 'MakerNotes', 2 => 'Camera' }, + FORMAT => 'int8u', + PRIORITY => 0, + DATAMEMBER => [ 0x99 ], + NOTES => q{ + Camera settings for models such as the A33, A35, A55, A450, A500, A550, + A560, A580, NEX-3, NEX-5, NEX-C3 and NEX-VG10E. + }, + 0x00 => { #JR + Name => 'ShutterSpeedSetting', + Notes => 'used only in M and S exposure modes', + ValueConv => '$val ? 2 ** (6 - $val/8) : 0', + ValueConvInv => '$val ? int((6 - log($val) / log(2)) * 8 + 0.5) : 0', + PrintConv => '$val ? Image::ExifTool::Exif::PrintExposureTime($val) : "Bulb"', + PrintConvInv => 'lc($val) eq "bulb" ? 0 : Image::ExifTool::Exif::ConvertFraction($val)', + }, + 0x01 => { #JR + Name => 'ApertureSetting', + Notes => 'used only in M and A exposure modes', + ValueConv => '2 ** (($val/8 - 1) / 2)', + ValueConvInv => 'int((log($val) * 2 / log(2) + 1) * 8 + 0.5)', + PrintConv => 'Image::ExifTool::Exif::PrintFNumber($val)', + PrintConvInv => '$val', + }, + 0x02 => { + Name => 'ISOSetting', + ValueConv => '($val and $val < 254) ? exp(($val/8-6)*log(2))*100 : $val', + ValueConvInv => '($val and $val != 254) ? 8*(log($val/100)/log(2)+6) : $val', + PrintConv => { + OTHER => sub { + my ($val, $inv) = @_; + return int($val + 0.5) unless $inv; + return Image::ExifTool::IsFloat($val) ? $val : undef; + }, + 0 => 'Auto', + 254 => 'n/a', # get this for multi-shot noise reduction + }, + }, + 0x03 => { #JR + Name => 'ExposureCompensationSet', + ValueConv => '($val - 128) / 24', #PH + ValueConvInv => 'int($val * 24 + 128.5)', + PrintConv => '$val ? sprintf("%+.1f",$val) : 0', + PrintConvInv => 'Image::ExifTool::Exif::ConvertFraction($val)', + }, + 0x04 => { #JR + Name => 'DriveModeSetting', + # Same drivemode info is repeated in 0x0034, but with at least the following exceptions: + # - 0x0034 not for A550 ? - seen "0" + # - hand-held night (0x05=56): 0x0004=0x10 and 0x0034=0xd3 + # - 3D sweep panorama (0x05=57): 0x0004=0x10 and 0x0034=0xd6 + # - sweep panorama (0x05=80): 0x0004=0x10 and 0x0034=0xd5 + # preliminary conclusion: 0x0004 is Drivemode as pre-set, but may be overruled by Scene/Panorama mode selections + # 0x0034 is Divemode as actually used + PrintHex => 1, + PrintConv => { + 0x10 => 'Single Frame', + 0x21 => 'Continuous High', # also automatically selected for Scene mode Sports-action (0x05=52) + 0x22 => 'Continuous Low', + 0x30 => 'Speed Priority Continuous', + 0x51 => 'Self-timer 10 sec', + 0x52 => 'Self-timer 2 sec, Mirror Lock-up', + 0x71 => 'Continuous Bracketing 0.3 EV', + 0x75 => 'Continuous Bracketing 0.7 EV', + 0x91 => 'White Balance Bracketing Low', + 0x92 => 'White Balance Bracketing High', + 0xc0 => 'Remote Commander', + }, + }, + 0x05 => { #JR + Name => 'ExposureProgram', + # Camera exposure program/mode as selected with the Mode dial. + # For SCN a further selection is done via the menu + # Matches OK with 0xb023 + SeparateTable => 'ExposureProgram2', + PrintConv => \%sonyExposureProgram2, + }, + 0x06 => { #JR + Name => 'FocusModeSetting', + PrintConv => { + 17 => 'AF-S', + 18 => 'AF-C', + 19 => 'AF-A', + 32 => 'Manual', + 48 => 'DMF', #(NC) (seen for NEX-5) + }, + }, + 0x07 => { #JR + Name => 'MeteringMode', + PrintConv => { + 1 => 'Multi-segment', + 2 => 'Center-weighted average', + 3 => 'Spot', + }, + }, + 0x09 => { #JR + Name => 'SonyImageSize', + PrintConv => { # values confirmed as noted for the A580 and A33 + 21 => 'Large (3:2)', # A580: 16M (4912x3264), A33: 14M (4592x3056) + 22 => 'Medium (3:2)', # A580: 8.4M (3568x2368), A33: 7.4M (3344x2224) + 23 => 'Small (3:2)', # A580: 4.0M (2448x1624), A33: 3.5M (2288x1520) + 25 => 'Large (16:9)', # A580: 14M (4912x2760) + 26 => 'Medium (16:9)', # A580: 7.1M (3568x2000) + 27 => 'Small (16:9)', # A580: 3.4M (2448x1376) + }, + }, + 0x0a => { #JR + Name => 'AspectRatio', + # normally 4 for A580 3:2 ratio images + # seen 8 when selecting 16:9 via menu, and when selecting Panorama mode + PrintConv => { + 4 => '3:2', + 8 => '16:9', + }, + }, + 0x0b => { #JR + Name => 'Quality', + PrintConv => { + 2 => 'RAW', + 4 => 'RAW + JPEG', + 6 => 'Fine', + 7 => 'Standard', + }, + }, + 0x0c => { + Name => 'DynamicRangeOptimizerSetting', + PrintConv => { + 1 => 'Off', + 16 => 'On (Auto)', + 17 => 'On (Manual)', + }, + }, + 0x0d => 'DynamicRangeOptimizerLevel', + 0x0e => { #JR + Name => 'ColorSpace', + PrintConv => { + 1 => 'sRGB', + 2 => 'Adobe RGB', + }, + }, + 0x0f => { #JR + Name => 'CreativeStyleSetting', + PrintConvColumns => 2, + PrintConv => { + 16 => 'Standard', + 32 => 'Vivid', + 64 => 'Portrait', + 80 => 'Landscape', + 96 => 'B&W', + 160 => 'Sunset', + }, + }, + 0x10 => { #JR (seen values 253, 254, 255, 0, 1, 2, 3) + Name => 'ContrastSetting', + Format => 'int8s', + PrintConv => '$val > 0 ? "+$val" : $val', + PrintConvInv => '$val', + }, + 0x11 => { #JR + Name => 'SaturationSetting', + Format => 'int8s', + PrintConv => '$val > 0 ? "+$val" : $val', + PrintConvInv => '$val', + }, + 0x12 => { #JR + Name => 'SharpnessSetting', + Format => 'int8s', + PrintConv => '$val > 0 ? "+$val" : $val', + PrintConvInv => '$val', + }, + 0x16 => { #JR + Name => 'WhiteBalanceSetting', + # many guessed, based on "logical system" as observed for Daylight and Shade and steps of 16 between the modes + PrintHex => 1, + PrintConvColumns => 2, + PrintConv => \%whiteBalanceSetting, + SeparateTable => 1, + }, + 0x17 => { #JR + Name => 'ColorTemperatureSetting', + # matches "0xb021 ColorTemperature" when WB set to "Custom" or "Color Temperature/Color Filter" + ValueConv => '$val * 100', + ValueConvInv => '$val / 100', + PrintConv => '"$val K"', + PrintConvInv => '$val =~ s/ ?K$//i; $val', + }, + 0x18 => { #JR + Name => 'ColorCompensationFilterSet', + # seen 0, 1-9 and 245-255, corresponding to 0, M1-M9 and G9-G1 on camera display + # matches "0xb022 ColorCompensationFilter" when WB set to "Custom" or "Color Temperature/Color Filter" + Format => 'int8s', + Notes => 'negative is green, positive is magenta', + PrintConv => '$val > 0 ? "+$val" : $val', + PrintConvInv => '$val', + }, + 0x19 => { #JR + Name => 'CustomWB_RGBLevels', + Format => 'int16uRev[3]', + # 0x19 - 0x1e are related to Custom WB measurements performed by the camera. + # The values change only each time when measuring and setting a new Custom WB. + # (0x19,0x1a) and (0x1d,0x1e) are same as MoreSettings (0x1a,0x1b) and (0x1c,0x1d) + }, + # 0x1f - always 2 (ref JR) + 0x20 => { #JR + Name => 'FlashMode', + PrintConvColumns => 2, + PrintConv => { + 1 => 'Flash Off', + 16 => 'Autoflash', + 17 => 'Fill-flash', + 18 => 'Slow Sync', + 19 => 'Rear Sync', + 20 => 'Wireless', + }, + }, + 0x21 => { #JR + Name => 'FlashControl', + PrintConv => { + 1 => 'ADI Flash', + 2 => 'Pre-flash TTL', + }, + }, + 0x23 => { #JR + Name => 'FlashExposureCompSet', + Description => 'Flash Exposure Comp. Setting', + # (as pre-selected by the user, not zero if flash didn't fire) + ValueConv => '($val - 128) / 24', #PH + ValueConvInv => 'int($val * 24 + 128.5)', + PrintConv => '$val ? sprintf("%+.1f",$val) : 0', + PrintConvInv => 'Image::ExifTool::Exif::ConvertFraction($val)', + }, + 0x24 => { + Name => 'AFAreaMode', + PrintConv => { + 1 => 'Wide', + 2 => 'Spot', + 3 => 'Local', + 4 => 'Flexible', #JR + # (Flexible Spot is a grid of 17x11 points for the NEX-5) + }, + }, + 0x25 => { #JR + Name => 'LongExposureNoiseReduction', + PrintConv => { + 1 => 'Off', + 16 => 'On', # (unused or dark subject) + }, + }, + 0x26 => { #JR + Name => 'HighISONoiseReduction', + PrintConv => { + 16 => 'Low', + 17 => 'High', + 19 => 'Auto', + }, + }, + 0x27 => { #JR + Name => 'SmileShutterMode', + PrintConv => { + 17 => 'Slight Smile', + 18 => 'Normal Smile', + 19 => 'Big Smile', + }, + }, + 0x28 => { #JR + Name => 'RedEyeReduction', + PrintConv => { + 1 => 'Off', + 16 => 'On', + }, + }, + 0x2d => { + Name => 'HDRSetting', + PrintConv => { + 1 => 'Off', + 16 => 'On (Auto)', + 17 => 'On (Manual)', + }, + }, + 0x2e => { + Name => 'HDRLevel', + PrintConvColumns => 3, + PrintConv => { + 33 => '1 EV', + 34 => '1.5 EV', #JR (NC) + 35 => '2 EV', + 36 => '2.5 EV', #JR (NC) + 37 => '3 EV', + 38 => '3.5 EV', #PH (NC) + 39 => '4 EV', + 40 => '5 EV', + 41 => '6 EV', + }, + }, + 0x2f => { #JR (not sure what is difference with 0x85) + Name => 'ViewingMode', + PrintConv => { + 16 => 'ViewFinder', + 33 => 'Focus Check Live View', + 34 => 'Quick AF Live View', + }, + }, + 0x30 => { #JR + Name => 'FaceDetection', + PrintConv => { + 1 => 'Off', + 16 => 'On', + }, + }, + 0x31 => { #JR + Name => 'SmileShutter', + PrintConv => { + 1 => 'Off', + 16 => 'On', + }, + }, + 0x32 => { #JR + Name => 'SweepPanoramaSize', + Condition => '$$self{Model} !~ /^DSLR-(A450|A500|A550)$/', + PrintConv => { + 1 => 'Standard', + 2 => 'Wide', + }, + }, + 0x33 => { #JR + Name => 'SweepPanoramaDirection', + Condition => '$$self{Model} !~ /^DSLR-(A450|A500|A550)$/', + PrintConv => { + 1 => 'Right', + 2 => 'Left', + 3 => 'Up', + 4 => 'Down', + }, + }, + 0x34 => { #JR + Name => 'DriveMode', # (drive mode actually used) + Condition => '$$self{Model} !~ /^DSLR-(A450|A500|A550)$/', + PrintHex => 1, + PrintConv => { + 0x10 => 'Single Frame', + 0x21 => 'Continuous High', # also automatically selected for Scene mode Sports-action (0x05=52) + 0x22 => 'Continuous Low', + 0x30 => 'Speed Priority Continuous', + 0x51 => 'Self-timer 10 sec', + 0x52 => 'Self-timer 2 sec, Mirror Lock-up', + 0x71 => 'Continuous Bracketing 0.3 EV', + 0x75 => 'Continuous Bracketing 0.7 EV', + 0x91 => 'White Balance Bracketing Low', + 0x92 => 'White Balance Bracketing High', + 0xc0 => 'Remote Commander', + 0xd1 => 'Continuous - HDR', + 0xd2 => 'Continuous - Multi Frame NR', + 0xd3 => 'Continuous - Handheld Night Shot', # (also called "Hand-held Twilight") + 0xd4 => 'Continuous - Anti Motion Blur', #PH (NEX-5) + 0xd5 => 'Continuous - Sweep Panorama', + 0xd6 => 'Continuous - 3D Sweep Panorama', + }, + }, + 0x35 => { + Name => 'MultiFrameNoiseReduction', + Condition => '$$self{Model} !~ /^DSLR-(A450|A500|A550)$/', + PrintConv => { + 0 => 'n/a', # seen for A450/A500/A550 + 1 => 'Off', + 16 => 'On', + 255 => 'None', # seen for NEX-3/5/C3 + }, + }, + 0x36 => { #JR (not 100% sure about this one) + Name => 'LiveViewAFSetting', + Condition => '$$self{Model} !~ /^(NEX-|DSLR-(A450|A500|A550)$)/', + PrintConv => { + 0 => 'n/a', + 1 => 'Phase-detect AF', + 2 => 'Contrast AF', + # Contrast AF is only available with SSM/SAM lenses and in Focus Check LV, + # NOT in Quick AF LV, and is automatically set when mounting SSM/SAM lens + # - changes into Phase-AF when switching to Quick AF LV. + }, + }, + 0x38 => { #JR + Name => 'PanoramaSize3D', + Description => '3D Panorama Size', + Condition => '$$self{Model} !~ /^DSLR-(A450|A500|A550)$/', + PrintConv => { + 0 => 'n/a', + 1 => 'Standard', + 2 => 'Wide', + 3 => '16:9', + }, + }, + 0x83 => { #JR + Name => 'AFButtonPressed', + # only indicates pressing and holding the "AF" button (centre-controller), + # not pressing the shutter release button halfway down + Condition => '$$self{Model} !~ /^(NEX-|DSLR-(A450|A500|A550)$)/', + PrintConv => { + 1 => 'No', + 16 => 'Yes', + }, + }, + 0x84 => { #JR (not 100% sure about this one) + Name => 'LiveViewMetering', + Condition => '$$self{Model} !~ /^(NEX-|DSLR-(A450|A500|A550)$)/', + PrintConv => { + 0 => 'n/a', + 16 => '40 Segment', # DSLR with LiveView/OVF switch in OVF position + 32 => '1200-zone Evaluative', # SLT, or DSLR with LiveView/OVF switch in LiveView position + }, + }, + 0x85 => { #JR (not sure what is difference with 0x2f) + Name => 'ViewingMode2', + Condition => '$$self{Model} !~ /^(NEX-|DSLR-(A450|A500|A550)$)/', + PrintConv => { + 0 => 'n/a', + 16 => 'Viewfinder', + 33 => 'Focus Check Live View', + 34 => 'Quick AF Live View', + }, + }, + 0x86 => { #JR + Name => 'AELock', + Condition => '$$self{Model} !~ /^(NEX-|DSLR-(A450|A500|A550)$)/', + PrintConv => { + 1 => 'On', + 2 => 'Off', + }, + }, + 0x87 => { #JR + Name => 'FlashStatusBuilt-in', + Condition => '$$self{Model} !~ /^DSLR-(A450|A500|A550)/', + PrintConv => { + 1 => 'Off', + 2 => 'On', + }, + }, + 0x88 => { #JR + Name => 'FlashStatusExternal', + Condition => '$$self{Model} !~ /^DSLR-(A450|A500|A550)/', + PrintConv => { + 1 => 'None', + 2 => 'Off', + 3 => 'On', + }, + }, +# 0x8a => { #JR +# Name => 'LensAF', +# Condition => '$$self{Model} !~ /^DSLR-(A450|A500|A550)$/', +# PrintConv => { +# 1 => 'No', +# 16 => 'AF Lens', +# }, +# }, + 0x8b => { #JR + Name => 'LiveViewFocusMode', + Condition => '$$self{Model} !~ /^(NEX-|DSLR-(A450|A500|A550)$)/', + PrintConv => { + 0 => 'n/a', + 1 => 'AF', + 16 => 'Manual', + }, + }, +# 0x8e => { #JR +# Name => 'LensSAM', +# Condition => '$$self{Model} !~ /^DSLR-(A450|A500|A550)$/', +# PrintConv => { +# 1 => 'No', +# 16 => 'SAM Lens', +# }, +# }, + 0x99 => { #JR + Name => 'LensMount', + Condition => '$$self{Model} !~ /^DSLR-(A450|A500|A550)$/', + DataMember => 'LensMount', + RawConv => '$$self{LensMount} = $val', + PrintConv => { + 1 => 'Unknown', + 16 => 'A-mount', + 17 => 'E-mount', + }, + }, +# 0x9b => { #JR +# Name => 'LensOSS', +# Condition => '$$self{Model} !~ /^DSLR-(A450|A500|A550)$/', +# PrintConv => { +# 1 => 'No', +# 16 => 'OSS Lens', +# 17 => 'OSS Lens (NEX-VG)', # active ? +# }, +# }, + # 0x9c - 1; 2 for multi-shot modes + 0x10c => { #JR + Name => 'SequenceNumber', + Condition => '$$self{Model} !~ /^DSLR-(A450|A500|A550)$/', # seen 18 for A550, so better exclude ? + # normally 0; seen 1,2,3 for bracketing, 6 for Handheld Night Shot, 3 for HDR, 6 for MFNR + PrintConv => { + 0 => 'Single', + 255 => 'n/a', + OTHER => sub { shift }, # pass all other numbers straight through + }, + }, + # when reading 0x0114 - 0x0117 as int32u: + # - upper 8 bits (0x0117): always value 4, meaning unknown + # - next 10 bits: FolderNumber (max. 999 according to manual) + # - last 14 bits: ImageNumber (max 9999) + 0x0114 => { #JR + Name => 'FolderNumber', + Condition => '$$self{Model} !~ /^DSLR-(A450|A500|A550)$/', + Format => 'int32u', + Mask => 0x00ffc000, + PrintConv => 'sprintf("%.3d",$val)', + PrintConvInv => '$val', + }, + 276.1 => { #JR (0x0114.1) + Name => 'ImageNumber', + Condition => '$$self{Model} !~ /^DSLR-(A450|A500|A550)$/', + Format => 'int32u', + Mask => 0x00003fff, + PrintConv => 'sprintf("%.4d",$val)', + PrintConvInv => '$val', + }, + 0x200 => { #JR + Name => 'ShotNumberSincePowerUp2', + Notes => q{ + same as ShotNumberSincePowerUp for single-shot images, but includes all + shots of the current image in multi-shot modes like HDR, panorama, and + multi-frame noise reduction + }, + # (includes all shutter actuations of the current shot) + Condition => '$$self{Model} !~ /^DSLR-(A450|A500|A550)$/', + Format => 'int32u', + }, + 0x283 => { #JR + Name => 'AFButtonPressed', + # only indicates pressing and holding the "AF" button (centre-controller), + # not pressing the shutter release button halfway down + Condition => '$$self{Model} =~ /^DSLR-(A450|A500|A550)$/', + PrintConv => { + 1 => 'No', + 16 => 'Yes', + }, + }, + 0x284 => { #JR (not 100% sure about this one) + Name => 'LiveViewMetering', + Condition => '$$self{Model} =~ /^DSLR-(A450|A500|A550)$/', + PrintConv => { + 0 => 'n/a', + 16 => '40 Segment', # DSLR with LiveView/OVF switch in OVF position + 32 => '1200-zone Evaluative', # DSLR with LiveView/OVF switch in LiveView position + }, + }, + 0x285 => { #JR (not sure what is difference with 0x2f) + Name => 'ViewingMode2', + Condition => '$$self{Model} =~ /^DSLR-(A450|A500|A550)$/', + PrintConv => { + 0 => 'n/a', + 16 => 'Viewfinder', + 33 => 'Focus Check Live View', + 34 => 'Quick AF Live View', + }, + }, + 0x286 => { #JR + Name => 'AELock', + Condition => '$$self{Model} =~ /^DSLR-(A450|A500|A550)$/', + PrintConv => { + 1 => 'On', + 2 => 'Off', + }, + }, + 0x287 => { #JR + Name => 'FlashStatusBuilt-in', + Condition => '$$self{Model} =~ /^DSLR-(A450|A500|A550)$/', + Notes => 'A450, A500 and A550', + PrintConv => { + 1 => 'Off', + 2 => 'On', + }, + }, + 0x288 => { #JR + Name => 'FlashStatusExternal', + Condition => '$$self{Model} =~ /^DSLR-(A450|A500|A550)$/', + Notes => 'A450, A500 and A550', + PrintConv => { + 1 => 'None', + 2 => 'Off', + 3 => 'On', + }, + }, + 0x28b => { #JR + Name => 'LiveViewFocusMode', + Condition => '$$self{Model} =~ /^DSLR-(A450|A500|A550)$/', + PrintConv => { + 0 => 'n/a', + 1 => 'AF', + 16 => 'Manual', + }, + }, + 0x30c => { #JR + Name => 'SequenceNumber', + Condition => '$$self{Model} =~ /^DSLR-(A450|A500|A550)$/', + Notes => 'A450, A500 and A550', + # normally 0; seen 2 for HDR + PrintConv => { + 0 => 'Single', + 255 => 'n/a', + OTHER => sub { shift }, # pass all other numbers straight through + }, + }, + 0x314 => { #JR + Name => 'ImageNumber', + Condition => '$$self{Model} =~ /^DSLR-(A450|A500|A550)$/', + Format => 'int16u', + Notes => 'A450, A500 and A550', + Mask => 0x3fff, #PH (not sure what the upper 2 bits are for) + PrintConv => 'sprintf("%.4d",$val)', + PrintConvInv => '$val', + }, + 0x316 => { #JR + Name => 'FolderNumber', + Condition => '$$self{Model} =~ /^DSLR-(A450|A500|A550)$/', + Notes => 'A450, A500 and A550', + Format => 'int16u', + Mask => 0x03ff, #(NC) + PrintConv => 'sprintf("%.3d",$val)', + PrintConvInv => '$val', + }, + 0x03f0 => { + Name => 'LensE-mountVersion', + Format => 'int16u', + Condition => '($$self{Model} =~ /^NEX-/)', + PrintConv => 'sprintf("%x.%.2x",$val>>8,$val&0xff)', + PrintConvInv => 'my @a=split(/\./,$val);(hex($a[0])<<8)|hex($a[1])', + }, + # 0x03f3 - this is probably LensFirmwareVersion and not CameraE-MountVersion (ref JR, Sept.2015) + # 0x03f3 and 0x03f4 change together and behave similarly to Tag940c 0x0014 and 0x0015 - see comments there. + 0x03f3 => { + Name => 'LensFirmwareVersion', + Format => 'int16u', + Condition => '($$self{Model} =~ /^NEX-/)', + PrintConv => 'sprintf("Ver.%.2x.%.3d",$val>>8,$val&0xff)', + }, + 0x3f7 => { #JR + Name => 'LensType2', + Condition => '($$self{Model} =~ /^NEX-/) and ($$self{LensMount} != 1)', + Format => 'int16u', + SeparateTable => 'LensType2', + PrintConv => \%sonyLensTypes2, + }, + 0x400 => { #JR + Name => 'ImageNumber', + Condition => '$$self{Model} =~ /^DSLR-(A450|A500|A550)$/', + Format => 'int16u', + Notes => 'A450, A500 and A550', + Mask => 0x3fff, #PH (not sure what the upper 2 bits are for) + PrintConv => 'sprintf("%.4d",$val)', + PrintConvInv => '$val', + }, + 0x402 => { #JR + Name => 'FolderNumber', + Condition => '$$self{Model} =~ /^DSLR-(A450|A500|A550)$/', + Format => 'int16u', + Mask => 0x03ff, #(NC) + Notes => 'A450, A500 and A550', + PrintConv => 'sprintf("%.3d",$val)', + PrintConvInv => '$val', + }, +); + +# Camera settings for other models +%Image::ExifTool::Sony::CameraSettingsUnknown = ( + %binaryDataAttrs, + GROUPS => { 0 => 'MakerNotes', 2 => 'Camera' }, + FORMAT => 'int16u', +); + +# extra hardware information (ref JR) +%Image::ExifTool::Sony::ExtraInfo = ( + %binaryDataAttrs, + GROUPS => { 0 => 'MakerNotes', 2 => 'Camera' }, + NOTES => 'Extra hardware information for the A850 and A900.', + # 0x0000: seen values 5 or 6 + 0x0001 => { + Name => 'BatteryTemperature', + # seen values of appr. 55 - 115: looks like temperature Fahrenheit + # changing battery in cold weather: new battery starts with value 53 + ValueConv => '($val - 32) / 1.8', # convert to Celsius + ValueConvInv => '$val * 1.8 + 32', + PrintConv => 'sprintf("%.1f C",$val)', + PrintConvInv => '$val=~ s/\s*C//; $val', + # (may be invalid for non-OEM batteries) + }, + 0x0002 => { + Name => 'BatteryUnknown', + # appears to be an int16u value together with 0x0005 (values similar to ExtraInfo3 0x0000) + # seen values of appr. 800 at 23 deg C to 630 at 40 deg C for A850 with NP-FM500H battery (7.2 V nominal) + # i.e. inversely proportional to BatteryTemperature: can not be BatteryVoltage, must be something else ? + Unknown => 1, + Format => 'undef[4]', + ValueConv => sub { + my $val = shift;; + my @a = unpack("CvC",pack('v*', unpack('n*', $val))); + return $a[1]; + }, + }, + # 0x0003: seen 0 or 16 + # 0x0004: always 255 + # 0x0006: int16u value together with 0x0009: same behaviour and almost same values as 0x0002 + # 0x0007: always 3 + 0x0008 => { + Name => 'BatteryVoltage', + # 0x0008: int16u value together with 0x000b: + # values follow BatteryLevel: from appr.900 when battery full, to appr. 775 when empty. + # with factor 118 they range from appr. 7.6 to 6.6 - looks like battery voltage (nominal 7.2 V) + Unknown => 1, + Format => 'undef[4]', + ValueConv => sub { + my $val = shift;; + my @a = unpack("CvC",pack('v*', unpack('n*', $val))); + return $a[1]/118; + }, + PrintConv => 'sprintf("%.2f V",$val)', + }, + 0x000a => { + # seen mostly 213 and 246, corresponding with other ImageStabilization On/Off tags. + Name => 'ImageStabilization2', + Unknown => 1, # (because the decoding is funny and possibly incomplete - PH) + PrintConv => { + 191 => 'On (191)', # seen a few times with moving subject, continuous drive, bracketing + 207 => 'On (207)', # seen once with RemoteCommander + 210 => 'On (210)', # seen a few times with continous drive + 213 => 'On', + 246 => 'Off', + }, + }, + # 0x000c: seen always decreasing values, from max. 107 to min. 0, + # then jump back to high value: correlates with battery change/recharging + # Seen once 255 immediately after inserting new battery, next frame OK at 106. + # Validation: matches exactly with batterylevel display on camera (all 100+ values displayed as 100%) + 0x000c => { + Name => 'BatteryLevel', + PrintConv => '"$val%"', + PrintConvInv => '$val=~s/\s*\%//; $val', + }, + # 0x000d: always 2 + # 0x000e: always 204 + # 0x000f: always 0 + # 0x0010-0x0019: always 204 + 0x001a => { + Name => 'ExtraInfoVersion', + Format => 'int8u[4]', + PrintConv => '$val=~tr/ /./; $val', + PrintConvInv => '$val=~tr/./ /; $val', + # always 0 1 0 1 for 0x0131 Software = DSLR-A850 v1.00 + # always 0 2 0 4 for 0x0131 Software = DSLR-A850 v2.00 + # seen 0 2 0 0 for 0x0131 Software = DSLR-A900 v1.00 + # seen 0 4 0 0 for 0x0131 Software = DSLR-A900 v1.00 + # seen 0 5 0 4 for 0x0131 Software = DSLR-A900 v2.00 + # A850: correlates exactly with Firmware versions. + # A900: have there been different FW 1.0 versions ? + }, +); + +# extra hardware information (ref JR) +%Image::ExifTool::Sony::ExtraInfo2 = ( + %binaryDataAttrs, + GROUPS => { 0 => 'MakerNotes', 2 => 'Camera' }, + NOTES => 'Extra hardware information for the A230/290/330/380/390.', + 0x0004 => { + Name => 'BatteryLevel', + PrintConv => '"$val%"', + PrintConvInv => '$val=~s/\s*\%//; $val', + }, + 0x0012 => { + Name => 'ImageStabilization', + PrintConv => { + 0 => 'Off', + 64 => 'On', + }, + }, +); + +# extra hardware information (ref JR) +%Image::ExifTool::Sony::ExtraInfo3 = ( + %binaryDataAttrs, + GROUPS => { 0 => 'MakerNotes', 2 => 'Camera' }, + NOTES => q{ + Extra hardware information for the A33, A35, A55, A450, A500, A550, A560, + A580 and NEX-3/5/C3/VG10. + }, + 0x0000 => { + Name => 'BatteryUnknown', + # seen values of appr. 870 at 10 deg C to 650 at 39 deg C for A580 with NP-FM500H battery (7.2 V nominal) + # i.e. inversely proportional to BatteryTemperature: can not be BatteryVoltage, must be something else ? + Unknown => 1, + Format => 'int16u', + }, + 0x0002 => { + Name => 'BatteryTemperature', + ValueConv => '($val - 32) / 1.8', # convert to Celsius + ValueConvInv => '$val * 1.8 + 32', + PrintConv => 'sprintf("%.1f C",$val)', + PrintConvInv => '$val=~ s/\s*C//; $val', + }, + 0x0004 => { + Name => 'BatteryLevel', + PrintConv => '"$val%"', + PrintConvInv => '$val=~s/\s*\%//; $val', + }, + # 0x0005: always 255 + # from here on the differences between DSLR, SLT and NEX + # 0x0006 and 0x0008: + # values follow BatteryLevel: start high (970, 940) when battery full, + # and decrease with decreasing battery level to (850, 815) + # with factor 128 they range from (7.6, 7.3) to (6.6, 6.4) - looks like battery voltage (nominal 7.2 V) + 0x0006 => { + Name => 'BatteryVoltage1', + Format => 'int16u', + Condition => '$$self{Model} !~ /^(NEX-(3|5|5C|C3|VG10|VG10E))\b/', + ValueConv => '$val / 128', + ValueConvInv => '$val * 128', + PrintConv => 'sprintf("%.2f V",$val)', + PrintConvInv => '$val=~s/\s*V//; $val', + }, + 0x0008 => { + Name => 'BatteryVoltage2', + Format => 'int16u', + Condition => '$$self{Model} !~ /^(NEX-(3|5|5C|C3|VG10|VG10E))\b/', + ValueConv => '$val / 128', + ValueConvInv => '$val * 128', + PrintConv => 'sprintf("%.2f V",$val)', + PrintConvInv => '$val=~s/\s*V//; $val', + }, + # 0x000a - 0x000f: 3 int16u values: probably some mode or status info: + # seen various 3-number-sequences for SLT and DSLR, but meaning unknown + # 0x000a => { + # Name => 'ExtraInfo_000a', + # Format => 'int16u[3]', + # Condition => '$$self{Model} !~ /^(NEX-(3|5|5C|C3|VG10|VG10E))\b/', + # }, + # 0x0010 seen: + # 176 for SLT + # 204 for NEX + # 240 for DSLR + 0x0011 => { + Name => 'ImageStabilization', + Condition => '$$self{Model} !~ /^(NEX-(3|5|5C|C3|VG10|VG10E))\b/', + # usually matches 0xb026 ImageStabilization, except some images with SelfTimer and on tripod + PrintConv => { + 0 => 'Off', + 64 => 'On', + }, + }, + 0x0014 => [ + { + Name => 'BatteryState', + Condition => '$$self{Model} =~ /^SLT-/', + # possibly relates to "simple" batterylevel indication with battery-icon, but not completely sure + Notes => 'BatteryState for SLT models', + PrintConv => { + 1 => 'Empty', + 2 => 'Low', + 3 => 'Half full', + 4 => 'Almost full', + 5 => 'Full', + }, + },{ + Name => 'ExposureProgram', + Condition => '$$self{Model} =~ /^DSLR-(A450|A500|A550)\b/', + Notes => 'ExposureProgram for the A450, A500 and A550', + Priority => 0, # (some unknown values) + PrintConv => { + 241 => 'Landscape', + 243 => 'Aperture-priority AE', + 245 => 'Portrait', + 246 => 'Auto', + 247 => 'Program AE', + 249 => 'Macro', + 252 => 'Sunset', + 253 => 'Sports', #PH (A550) + 255 => 'Manual', + # missing: Shutter speed priority AE, No Flash, Night View + }, + },{ + Name => 'ModeDialPosition', + Condition => '$$self{Model} =~ /^DSLR-/', + Notes => 'ModeDialPosition for other DSLR models', + # (decoded from A560/A580) + PrintConv => { + 248 => 'No Flash', + 249 => 'Aperture-priority AE', + 250 => 'SCN', # <-- the reason we don't call it ExposureProgram for these models + 251 => 'Shutter speed priority AE', + 252 => 'Auto', + 253 => 'Program AE', + 254 => 'Panorama', + 255 => 'Manual', + }, + }, + ], + # 0x0015: DSLR: appears to be a bitmask relating to "switch" positions: + # bit 0 ( 1) only seen OFF for A580 + # bit 1 ( 2) ON = Flash down, OFF = Flash raised + # bit 2 ( 4) only seen ON for A580 + # bit 3 ( 8) only seen ON for A580 + # bit 4 ( 16) ON = AF, OFF = MF + # bit 5 ( 32) ON = OVF, OFF = LiveView + # bit 6 ( 64) seen ON and OFF, meaning unknown + # bit 7 (128) seen ON and OFF, meaning unknown + # 0x0016: DSLR: seen 244,245,252,254, decoded for A580 with 32GB SD and 16GB MS cards + # 0x0016: NEX: seen 61,62, 125,126, 190: bits '64' and '128' appear to relate to CameraOrientation + # 0x0016: SLT: seen 64 - 78, meaning unknown + 0x0016 => [{ + Name => 'MemoryCardConfiguration', + Condition => '$$self{Model} =~ /^DSLR-/', + PrintConv => { + 244 => 'MemoryStick in use, SD card present', + 245 => 'MemoryStick in use, SD slot empty', + 252 => 'SD card in use, MemoryStick present', + 254 => 'SD card in use, MemoryStick slot empty', + }, + },{ + Name => 'CameraOrientation', + Condition => '$$self{Model} =~ /^(NEX-(3|5|5C|C3|VG10|VG10E))\b/', + Mask => 0xc0, # (don't know what other bits mean) + PrintConv => { + 0 => 'Horizontal (normal)', + 1 => 'Rotate 90 CW', + 2 => 'Rotate 270 CW', + 3 => 'Rotate 180', #(NC) + }, + + }], + # 0x0017: seen 0 for SLT, 255 for DSLR, variable for NEX + 0x0018 => { + Name => 'CameraOrientation', + Condition => '$$self{Model} !~ /^(NEX-(3|5|5C|C3|VG10|VG10E))\b/', + Mask => 0x30, # (don't know what other bits mean) + PrintConv => { + 0 => 'Horizontal (normal)', + 1 => 'Rotate 90 CW', + 2 => 'Rotate 270 CW', + 3 => 'Rotate 180', + }, + }, + # 0x0019: + # A450/500/550: 0 - 12 and 233 - 255 + # A560/580: 1 or 64, seen a few 0 and 8 + # A33/35/55: seen 0, 1, 64 + # NEX: 204 + # 0x001a, 0x001c appear to be 2 int16u values, meaning unknown +); + +# shot information (ref PH) +%Image::ExifTool::Sony::ShotInfo = ( + %binaryDataAttrs, + GROUPS => { 0 => 'MakerNotes', 2 => 'Image' }, + DATAMEMBER => [ 0x02, 0x30, 0x32, 0x34 ], + IS_SUBDIR => [ 0x48, 0x5e ], + # 0x00 - byte order 'II' + 0x02 => { + Name => 'FaceInfoOffset', + Format => 'int16u', + DataMember => 'FaceInfoOffset', + Writable => 0, + RawConv => '$$self{FaceInfoOffset} = $val', + }, + 0x06 => { + Name => 'SonyDateTime', + Format => 'string[20]', + Groups => { 2 => 'Time' }, + Shift => 'Time', + PrintConv => '$self->ConvertDateTime($val)', + PrintConvInv => '$self->InverseDateTime($val,0)', + }, + 0x1a => { Name => 'SonyImageHeight', Format => 'int16u' }, #JR + 0x1c => { Name => 'SonyImageWidth', Format => 'int16u' }, #JR + 0x30 => { #Jeffrey Friedl + Name => 'FacesDetected', + DataMember => 'FacesDetected', + Format => 'int16u', + RawConv => '$$self{FacesDetected} = $val', + }, + 0x32 => { + Name => 'FaceInfoLength', # length of a single FaceInfo entry + DataMember => 'FaceInfoLength', + Format => 'int16u', + Writable => 0, + RawConv => '$$self{FaceInfoLength} = $val', + }, + 0x34 => { + # oldest/other DSC/other - + # older DSC models "DC5303320222000" or "DC6303320222000" + # DSC-W650/W690/W730 "THm101000000000" or "THm211000000000" + # DSC-HX9V generation and newer "DC7303320222000" + Name => 'MetaVersion', # (tentative) + Format => 'string[16]', + DataMember => 'MetaVersion', + RawConv => '$$self{MetaVersion} = $val', + }, + 0x48 => { # (most models: DC5303320222000 and DC6303320222000) + Name => 'FaceInfo1', + Condition => q{ + $$self{FacesDetected} and + $$self{FaceInfoOffset} == 0x48 and + $$self{FaceInfoLength} == 0x20 + }, + SubDirectory => { TagTable => 'Image::ExifTool::Sony::FaceInfo1' }, + }, + 0x5e => { # (HX7V: DC7303320222000) + Name => 'FaceInfo2', + Condition => q{ + $$self{FacesDetected} and + $$self{FaceInfoOffset} == 0x5e and + $$self{FaceInfoLength} == 0x25 + }, + SubDirectory => { TagTable => 'Image::ExifTool::Sony::FaceInfo2' }, + }, +); + +# tags used in Tag2010 and Tag9400 tables +my %sequenceImageNumber = ( #PH + Name => 'SequenceImageNumber', + Notes => 'number of images captured in burst sequence', + # (not shutter count because it increments for auto portrait framing) + Format => 'int32u', + ValueConv => '$val + 1', + ValueConvInv => '$val - 1', +); +my %sequenceFileNumber = ( #PH + Name => 'SequenceFileNumber', + Notes => 'file number in burst sequence', + Format => 'int32u', + ValueConv => '$val + 1', #JR + ValueConvInv => '$val - 1', +); +my %releaseMode2 = ( #JR + Name => 'ReleaseMode2', + SeparateTable => 'ReleaseMode2', + PrintConv => { + 0 => 'Normal', + 1 => 'Continuous', # (RX100 "Continuous - Self-timer") + 2 => 'Continuous - Exposure Bracketing', # (RX100) +# 3 - also DRO Bracketing (ILCE-7RM2), not "Continuous" because only single exposure from which camera makes 3 versions + 3 => 'DRO or White Balance Bracketing', # (HX9V) (RX100) (ILCE-7RM2) + 5 => 'Continuous - Burst', # (HX9V) + 6 => 'Single Frame - Capture During Movie', #PH (RX100) + 7 => 'Continuous - Sweep Panorama', + 8 => 'Continuous - Anti-Motion Blur, Hand-held Twilight', # (HX9V) + 9 => 'Continuous - HDR', + 10 => 'Continuous - Background defocus', # (HX9V) + 13 => 'Continuous - 3D Sweep Panorama', #PH/JR + 15 => 'Continuous - High Resolution Sweep Panorama', #JR (HX50V) + 16 => 'Continuous - 3D Image', # (HX9V) + 17 => 'Continuous - Burst 2', # (WX7 - PH) (#JR 9400-SequenceLength=10 shots) + # 18 - seen for several ILCE-7S v2.00 iAuto+ single-shot images ... + 19 => 'Continuous - Speed/Advance Priority', #PH/JR (RX100) + 20 => 'Continuous - Multi Frame NR', + 23 => 'Single-frame - Exposure Bracketing', # (seen for ILCE-7 series) + 26 => 'Continuous Low', #PH (A77) + 27 => 'Continuous - High Sensitivity', # seen for DSC-WX60 and WX300 + 28 => 'Smile Shutter', #PH (RX100) + 29 => 'Continuous - Tele-zoom Advance Priority', + # 30 - seen quite often for single-shot images ... SLT-A58, ILCE-5100/6000 + # 33 - Continuous - seen for DSC-RX100M5, RX10M4, maybe 24 fps mode ??? + 146 => 'Single Frame - Movie Capture', #PH (seen in Tag2010 ReleaseMode2 values) + }, +); + +# tag definitions for Tag2010 tables (ref JR) +my %sonyDateTime2010 = ( + Name => 'SonyDateTime', + Format => 'undef[7]', + Shift => 'Time', + ValueConv => q{ + my @v = unpack('vC*', $val); + return sprintf("%.4d:%.2d:%.2d %.2d:%.2d:%.2d", @v) + }, + ValueConvInv => q{ + my @v = ($val =~ /\d+/g); + return undef unless @v == 6; + return pack('vC*', @v); + }, + PrintConv => '$self->ConvertDateTime($val)', + PrintConvInv => '$self->InverseDateTime($val,0)', +); +my %releaseMode2010 = ( + Name => 'ReleaseMode3', + PrintConv => { + 0 => 'Normal', + 1 => 'Continuous', + 2 => 'Bracketing', # (all types: Continuous and Single-Frame Exposure, White Balance and DRO bracketing - PH/JR) + # 3 => 'Remote Commander', (NC) (seen this when other ReleaseMode and ReleaseMode2 are 'Normal' - PH, A77) + 4 => 'Continuous - Burst', # seen for DSC-WX500 with burst of 10 shots + 5 => 'Continuous - Speed/Advance Priority', + 6 => 'Normal - Self-timer', # seen for ILCE-6300/6500/9, ILCA-99M2 + }, +); +my %selfTimer2010 = ( + Name => 'SelfTimer', + PrintConv => { + 0 => 'Off', + 1 => 'Self-timer 10 s', + 2 => 'Self-timer 2 s', + }, +); +my %selfTimerB2010 = ( # also value 1 for new 5 s mode of DSC-HX90V/RX10M2/RX100M4/WX500, ILCE-7RM2/7SM2 + Name => 'SelfTimer', + PrintConv => { + 0 => 'Off', + 1 => 'Self-timer 5 or 10 s', + 2 => 'Self-timer 2 s', + }, +); +my %gain2010 = ( + Name => 'StopsAboveBaseISO', + # BaseISO is 100 for SLT, ILCE-3000, NEX-5N/5R/5T/6/7/VG20/VG30/VG900, DSC-RX1/RX1R + # BaseISO is 200 for NEX-F3/3N + # BaseISO is 160 for DSC-RX100M2 + # BaseISO is 125 for DSC-RX100 + # Also several other DSC models have BaseISO different from 100. + Format => 'int16u', + ValueConv => '16 - $val/256', + ValueConvInv => '(16 - $val) * 256', + PrintConv => '$val ? sprintf("%.1f",$val) : $val', + PrintConvInv => '$val', +); +my %brightnessValue2010 = ( + Name => 'BrightnessValue', + Format => 'int16u', + ValueConv => '$val/256 - 56.6', + ValueConvInv => '($val + 56.6) * 256', +); +my %dynamicRangeOptimizer2010 = ( + Name => 'DynamicRangeOptimizer', + PrintConv => { + 0 => 'Off', + 1 => 'Auto', + 3 => 'Lv1', + 4 => 'Lv2', + 5 => 'Lv3', + 6 => 'Lv4', + 7 => 'Lv5', + 8 => 'n/a', + }, +); +my %hdr2010 = ( + Name => 'HDRSetting', # (Off when HDR tag is On for RX100 superior auto backlight - PH) + PrintConv => { + 0 => 'Off', + 1 => 'HDR Auto', + 3 => 'HDR 1 EV', + 5 => 'HDR 2 EV', + 7 => 'HDR 3 EV', + 9 => 'HDR 4 EV', + 11 => 'HDR 5 EV', + 13 => 'HDR 6 EV', + }, +); +my %exposureComp2010 = ( # only as set manually, remains 0 in exposure-bracketing modes + Name => 'ExposureCompensation', + Format=>'int16s', + ValueConv => '-$val/256', + ValueConvInv => '-$val*256', + PrintConv => '$val ? sprintf("%+.1f",$val) : 0', + PrintConvInv => '$val', +); +my %pictureEffect2010 = ( + Name => 'PictureEffect2', + SeparateTable => 'PictureEffect2', + PrintConv => { + 0 => 'Off', + 1 => 'Toy Camera', + 2 => 'Pop Color', + 3 => 'Posterization', + 4 => 'Retro Photo', + 5 => 'Soft High Key', + 6 => 'Partial Color', + 7 => 'High Contrast Monochrome', + 8 => 'Soft Focus', + 9 => 'HDR Painting', + 10 => 'Rich-tone Monochrome', + 11 => 'Miniature', + 12 => 'Water Color', + 13 => 'Illustration', + }, +); +my %quality2010 = ( + Name => 'Quality2', + PrintConv => { + 0 => 'JPEG', + 1 => 'RAW', + 2 => 'RAW + JPEG', + }, +); +my %meteringMode2010 = ( + Name => 'MeteringMode', + PrintConv => { + 0 => 'Multi-segment', + 2 => 'Center-weighted average', + 3 => 'Spot', + 4 => 'Average', + 5 => 'Highlight', + }, +); +my %flashMode2010 = ( + Name => 'FlashMode', + PrintConv => { + 0 => 'Autoflash', + 1 => 'Fill-flash', + 2 => 'Flash Off', + 3 => 'Slow Sync', + 4 => 'Rear Sync', + 6 => 'Wireless', + # 129 => 'unknown', # seen for ILCE-7M3 images + }, +); +my %exposureProgram2010 = ( + Name => 'ExposureProgram', + SeparateTable => 'ExposureProgram3', + PrintConv => \%sonyExposureProgram3, +); +my %pictureProfile2010 = ( + Name => 'PictureProfile', + # values 0-9: Seen for all cameras writing this tag: matches CreativeStyle and/or SceneMode settings. + # 10 and higher: Seen for ILCE-7S/7M2 and newer, having a PictureProfile setting, also some DSC/HDR models. + # Although intended for video, when set these profiles are also applied to (JPG) still images. + PrintConv => { + 0 => 'Gamma Still - Standard/Neutral (PP2)', # CreativeStyle = Standard or Neutral + 1 => 'Gamma Still - Portrait', + #2 - seen for DSC-HX90 + 3 => 'Gamma Still - Night View/Portrait', + 4 => 'Gamma Still - B&W/Sepia', + 5 => 'Gamma Still - Clear', + 6 => 'Gamma Still - Deep', + 7 => 'Gamma Still - Light', + 8 => 'Gamma Still - Vivid', # SceneMode or CreativeStyle = Vivid, Autumn, Sunset or Landscape + 9 => 'Gamma Still - Real', + 10 => 'Gamma Movie (PP1)', + 22 => 'Gamma ITU709 (PP3 or PP4)', # (also PP4 for A7M3, ref 14) + 24 => 'Gamma Cine1 (PP5)', + 25 => 'Gamma Cine2 (PP6)', + 26 => 'Gamma Cine3', + 27 => 'Gamma Cine4', + 28 => 'Gamma S-Log2 (PP7)', + 29 => 'Gamma ITU709 (800%)', + 31 => 'Gamma S-Log3 (PP8 or PP9)', #14 + 33 => 'Gamma HLG2 (PP10)', #14 + }, +); +my %isoSetting2010 = ( + 0 => 'Auto', + 5 => 25, + 8 => 50, + 9 => 64, + 10 => 80, + 11 => 100, + 12 => 125, + 13 => 160, + 14 => 200, + 15 => 250, + 16 => 320, + 17 => 400, + 18 => 500, + 19 => 640, + 20 => 800, + 21 => 1000, + 22 => 1250, + 23 => 1600, + 24 => 2000, + 25 => 2500, + 26 => 3200, + 27 => 4000, + 28 => 5000, + 29 => 6400, + 30 => 8000, + 31 => 10000, + 32 => 12800, + 33 => 16000, + 34 => 20000, + 35 => 25600, + 38 => 51200, + 39 => 64000, + 41 => 102400, + 42 => 128000, + 43 => 160000, + 44 => 204800, + 47 => 409600, +); + +%Image::ExifTool::Sony::Tag2010a = ( #JR + PROCESS_PROC => \&ProcessEnciphered, + WRITE_PROC => \&WriteEnciphered, + CHECK_PROC => \&Image::ExifTool::CheckBinaryData, + FORMAT => 'int8u', + NOTES => 'Valid for NEX-5N.', + WRITABLE => 1, + FIRST_ENTRY => 0, + PRIORITY => 0, + GROUPS => { 0 => 'MakerNotes', 2 => 'Image' }, + 0x04b0 => { + Name => 'MeterInfo', + Format => 'int32u[486]', + Unknown => 1, + SubDirectory => { TagTable => 'Image::ExifTool::Sony::MeterInfo' }, + }, + 0x1128 => { %releaseMode2010 }, + 0x112c => { %releaseMode2 }, + 0x1134 => { %selfTimer2010 }, + 0x1138 => { %flashMode2010 }, + 0x113e => { %gain2010 }, + 0x1140 => { %brightnessValue2010 }, + 0x1144 => { %dynamicRangeOptimizer2010 }, + 0x1148 => { %hdr2010 }, + 0x114c => { %exposureComp2010 }, + 0x115e => { %pictureProfile2010 }, + 0x115f => { %pictureProfile2010 }, + 0x1163 => { %pictureEffect2010 }, + 0x1170 => { %quality2010 }, + 0x1174 => { %meteringMode2010 }, + 0x1175 => { %exposureProgram2010 }, + 0x117c => { Name => 'WB_RGBLevels', Format => 'int16u[3]' }, + #0x1a08 => { Name => 'SonyImageWidth', Format => 'int16u' }, + #0x1a0c => { Name => 'SonyImageHeight', Format => 'int16u' }, +); + +%Image::ExifTool::Sony::Tag2010b = ( #JR + PROCESS_PROC => \&ProcessEnciphered, + WRITE_PROC => \&WriteEnciphered, + CHECK_PROC => \&Image::ExifTool::CheckBinaryData, + FORMAT => 'int8u', + NOTES => 'Valid for SLT-A65/A77, NEX-7/VG20E.', + WRITABLE => 1, + FIRST_ENTRY => 0, + PRIORITY => 0, + GROUPS => { 0 => 'MakerNotes', 2 => 'Image' }, + 0x0000 => { %sequenceImageNumber }, #PH + 0x0004 => { %sequenceFileNumber }, #PH + 0x0008 => { %releaseMode2, Format => 'int32u' }, + #0x0044 => { Name => 'SonyImageWidth3', Format => 'int16u' }, + #0x0048 => { Name => 'SonyImageHeight3', Format => 'int16u' }, + #0x0054 => { Name => 'SonyImageWidth2', Format => 'int16u' }, + #0x0058 => { Name => 'SonyImageHeight2', Format => 'int16u' }, + #0x0064 => { Name => 'SonyImageWidth', Format => 'int16u' }, + #0x0068 => { Name => 'SonyImageHeight', Format => 'int16u' }, + #0x00a8 => { Name => 'SonyImageWidth2', Format => 'int16u' }, + #0x00ac => { Name => 'SonyImageHeight2', Format => 'int16u' }, + #0x00b8 => { Name => 'SonyImageWidth2', Format => 'int16u' }, + #0x00bc => { Name => 'SonyImageHeight2', Format => 'int16u' }, + #0x00c8 => { Name => 'SonyImageWidth', Format => 'int16u' }, + #0x00cc => { Name => 'SonyImageHeight', Format => 'int16u' }, + 0x01b6 => { %sonyDateTime2010, Groups => { 2 => 'Time' } }, + #0x0204 => { Name => 'SonyImageWidth', Format => 'int16u' }, + #0x0206 => { Name => 'SonyImageHeight', Format => 'int16u' }, + 0x0324 => { %dynamicRangeOptimizer2010 }, + 0x04b4 => { + Name => 'MeterInfo', + Format => 'int32u[486]', + Unknown => 1, + SubDirectory => { TagTable => 'Image::ExifTool::Sony::MeterInfo' }, + }, + 0x1128 => { %releaseMode2010 }, + 0x112c => { %releaseMode2 }, + 0x1134 => { %selfTimer2010 }, + 0x1138 => { %flashMode2010 }, + 0x113e => { %gain2010 }, + 0x1140 => { %brightnessValue2010 }, + 0x1144 => { %dynamicRangeOptimizer2010 }, + 0x1148 => { %hdr2010 }, + 0x114c => { %exposureComp2010 }, + 0x1162 => { %pictureProfile2010 }, + 0x1163 => { %pictureProfile2010 }, + 0x1167 => { %pictureEffect2010 }, + 0x1174 => { %quality2010 }, + 0x1178 => { %meteringMode2010 }, + 0x1179 => { %exposureProgram2010 }, + 0x1180 => { Name => 'WB_RGBLevels', Format => 'int16u[3]' }, + 0x1218 => { + Name => 'SonyISO', + Format => 'int16u', + ValueConv => '100 * 2**(16 - $val/256)', + ValueConvInv => '256 * (16 - log($val/100)/log(2))', + PrintConv => 'sprintf("%.0f",$val)', + PrintConvInv => '$val', + }, + #0x1a08 => { Name => 'SonyImageWidth', Format => 'int16u' }, + #0x1a0c => { Name => 'SonyImageHeight', Format => 'int16u' }, + 0x1a23 => { # only for NEX-7 with Firmware v1.02 and higher, but slightly different from Tag9405 ... + Name => 'DistortionCorrParams', + Format => 'int16s[16]', + }, +); + +%Image::ExifTool::Sony::Tag2010c = ( #JR + PROCESS_PROC => \&ProcessEnciphered, + WRITE_PROC => \&WriteEnciphered, + CHECK_PROC => \&Image::ExifTool::CheckBinaryData, + FORMAT => 'int8u', + NOTES => 'Valid for SLT-A37/A57 and NEX-F3.', + WRITABLE => 1, + FIRST_ENTRY => 0, + PRIORITY => 0, + GROUPS => { 0 => 'MakerNotes', 2 => 'Image' }, + 0x0000 => { %sequenceImageNumber }, #PH + 0x0004 => { %sequenceFileNumber }, #PH + 0x0008 => { %releaseMode2, Format => 'int32u' }, + #0x0048 => { Name => 'SonyImageWidth3', Format => 'int16u' }, + #0x004c => { Name => 'SonyImageHeight3', Format => 'int16u' }, + #0x0058 => { Name => 'SonyImageWidth2', Format => 'int16u' }, + #0x005c => { Name => 'SonyImageHeight2', Format => 'int16u' }, + #0x0068 => { Name => 'SonyImageWidth', Format => 'int16u' }, + #0x006c => { Name => 'SonyImageHeight', Format => 'int16u' }, + #0x00c0 => { Name => 'SonyImageWidth2', Format => 'int16u' }, + #0x00c4 => { Name => 'SonyImageHeight2', Format => 'int16u' }, + #0x00d0 => { Name => 'SonyImageWidth2', Format => 'int16u' }, + #0x00d4 => { Name => 'SonyImageHeight2', Format => 'int16u' }, + #0x00e0 => { Name => 'SonyImageWidth', Format => 'int16u' }, + #0x00e4 => { Name => 'SonyImageHeight', Format => 'int16u' }, + #0x0134 => { Name => 'SonyImageHeight', Format => 'int16u' }, + #0x0144 => { Name => 'SonyImageHeight', Format => 'int16u' }, + #0x0154 => { Name => 'SonyImageHeight', Format => 'int16u' }, + 0x0200 => { Name => 'DigitalZoomRatio', ValueConv => '$val/16', ValueConvInv => '$val*16', Priority => 0 }, + 0x0210 => { %sonyDateTime2010, Groups => { 2 => 'Time' } }, + 0x0300 => { %dynamicRangeOptimizer2010 }, + 0x0490 => { + Name => 'MeterInfo', + Format => 'int32u[486]', + Unknown => 1, + SubDirectory => { TagTable => 'Image::ExifTool::Sony::MeterInfo' }, + }, + 0x1104 => { %releaseMode2010 }, + 0x1108 => { %releaseMode2 }, + 0x1110 => { %selfTimer2010 }, + 0x1114 => { %flashMode2010 }, + 0x111a => { %gain2010 }, + 0x111c => { %brightnessValue2010 }, + 0x1120 => { %dynamicRangeOptimizer2010 }, + 0x1124 => { %hdr2010 }, + 0x1128 => { %exposureComp2010 }, + 0x113e => { %pictureProfile2010 }, + 0x113f => { %pictureProfile2010 }, + 0x1143 => { %pictureEffect2010 }, + 0x1150 => { %quality2010 }, + 0x1154 => { %meteringMode2010 }, + 0x1155 => { %exposureProgram2010 }, + 0x115c => { Name => 'WB_RGBLevels', Format => 'int16u[3]' }, + 0x11f4 => { + Name => 'SonyISO', + Format => 'int16u', + ValueConv => '100 * 2**(16 - $val/256)', + ValueConvInv => '256 * (16 - log($val/100)/log(2))', + PrintConv => 'sprintf("%.0f",$val)', + PrintConvInv => '$val', + }, + #0x1a08 => { Name => 'SonyImageWidth', Format => 'int16u' }, + #0x1a0c => { Name => 'SonyImageHeight', Format => 'int16u' }, +); + +%Image::ExifTool::Sony::Tag2010d = ( #JR + PROCESS_PROC => \&ProcessEnciphered, + WRITE_PROC => \&WriteEnciphered, + CHECK_PROC => \&Image::ExifTool::CheckBinaryData, + FORMAT => 'int8u', + NOTES => q{ + Valid for DSC-HX10V/HX20V/HX200V/TX66/TX200V/TX300V/WX50/WX100/WX150, but + not valid for panorama images. + }, + WRITABLE => 1, + FIRST_ENTRY => 0, + PRIORITY => 0, + GROUPS => { 0 => 'MakerNotes', 2 => 'Image' }, + 0x0000 => { %sequenceImageNumber }, #PH + 0x0004 => { %sequenceFileNumber }, #PH + 0x0008 => { %releaseMode2, Format => 'int32u' }, + #0x0048 => { Name => 'SonyImageWidth3', Format => 'int16u' }, + #0x004c => { Name => 'SonyImageHeight3', Format => 'int16u' }, + #0x0058 => { Name => 'SonyImageWidth2', Format => 'int16u' }, + #0x005c => { Name => 'SonyImageHeight2', Format => 'int16u' }, + #0x0068 => { Name => 'SonyImageWidth', Format => 'int16u' }, + #0x006c => { Name => 'SonyImageHeight', Format => 'int16u' }, + #0x00c0 => { Name => 'SonyImageWidth2', Format => 'int16u' }, + #0x00c4 => { Name => 'SonyImageHeight2', Format => 'int16u' }, + #0x00d0 => { Name => 'SonyImageWidth2', Format => 'int16u' }, + #0x00d4 => { Name => 'SonyImageHeight2', Format => 'int16u' }, + #0x00e0 => { Name => 'SonyImageWidth', Format => 'int16u' }, + #0x00e4 => { Name => 'SonyImageHeight', Format => 'int16u' }, + 0x01fe => { %sonyDateTime2010, Groups => { 2 => 'Time' } }, + 0x037c => { %dynamicRangeOptimizer2010 }, + 0x050c => { + Name => 'MeterInfo', + Format => 'int32u[486]', + Unknown => 1, + SubDirectory => { TagTable => 'Image::ExifTool::Sony::MeterInfo' }, + }, + 0x1180 => { %releaseMode2010 }, + 0x1184 => { %releaseMode2 }, + 0x118c => { %selfTimer2010 }, + 0x1190 => { %flashMode2010 }, + 0x1196 => { %gain2010 }, + 0x1198 => { %brightnessValue2010 }, + 0x119c => { %dynamicRangeOptimizer2010 }, + 0x11a0 => { %hdr2010 }, + 0x11ba => { %pictureProfile2010 }, + 0x11bb => { %pictureProfile2010 }, + 0x11bf => { %pictureEffect2010 }, + 0x11d0 => { %meteringMode2010 }, + # 0x11d1 - not valid for HX20V panorama images - PH + 0x11d1 => { %exposureProgram2010 }, + 0x11d8 => { Name => 'WB_RGBLevels', Format => 'int16u[3]' }, + 0x1270 => { + Name => 'SonyISO', + Format => 'int16u', + ValueConv => '100 * 2**(16 - $val/256)', + ValueConvInv => '256 * (16 - log($val/100)/log(2))', + PrintConv => 'sprintf("%.0f",$val)', + PrintConvInv => '$val', + }, +); + +%Image::ExifTool::Sony::Tag2010e = ( #JR + PROCESS_PROC => \&ProcessEnciphered, + WRITE_PROC => \&WriteEnciphered, + CHECK_PROC => \&Image::ExifTool::CheckBinaryData, + FORMAT => 'int8u', + NOTES => q{ + Valid for SLT-A58/A99, ILCE-3000/3500, NEX-3N/5R/5T/6/VG30E/VG900, DSC-RX100, + DSC-RX1/RX1R. Also valid for DSC-HX300/HX50V/TX30/WX60/WX200/WX300, but not + for panorama images. + }, + WRITABLE => 1, + FIRST_ENTRY => 0, + PRIORITY => 0, + GROUPS => { 0 => 'MakerNotes', 2 => 'Image' }, + 0x0000 => { %sequenceImageNumber }, #PH + 0x0004 => { %sequenceFileNumber }, #PH + 0x0008 => { %releaseMode2, Format => 'int32u' }, + #0x0048 => { Name => 'SonyImageWidth3', Format => 'int16u' }, + #0x004c => { Name => 'SonyImageHeight3', Format => 'int16u' }, + #0x0058 => { Name => 'SonyImageWidth2', Format => 'int16u' }, + #0x005c => { Name => 'SonyImageHeight2', Format => 'int16u' }, + #0x0068 => { Name => 'SonyImageWidth', Format => 'int16u' }, + #0x006c => { Name => 'SonyImageHeight', Format => 'int16u' }, + #0x00c0 => { Name => 'SonyImageWidth2', Format => 'int16u' }, + #0x00c4 => { Name => 'SonyImageHeight2', Format => 'int16u' }, + #0x00d0 => { Name => 'SonyImageWidth2', Format => 'int16u' }, + #0x00d4 => { Name => 'SonyImageHeight2', Format => 'int16u' }, + #0x00e0 => { Name => 'SonyImageWidth', Format => 'int16u' }, + #0x00e4 => { Name => 'SonyImageHeight', Format => 'int16u' }, + #0x01fa => { Name => 'SonyImageHeight', Format => 'int16u' }, + #0x0200 => { Name => 'SonyImageWidth', Format => 'int16u' }, + 0x021c => { Name => 'DigitalZoomRatio', ValueConv => '$val/16', ValueConvInv => '$val*16', Priority => 0 }, + 0x022c => { %sonyDateTime2010, Groups => { 2 => 'Time' } }, + 0x0328 => { %dynamicRangeOptimizer2010 }, + 0x04b8 => { + Name => 'MeterInfo', + Format => 'int32u[486]', + Unknown => 1, + SubDirectory => { TagTable => 'Image::ExifTool::Sony::MeterInfo' }, + }, + 0x115c => { %releaseMode2010 }, + 0x1160 => { %releaseMode2 }, + 0x1168 => { %selfTimer2010 }, + 0x116c => { %flashMode2010 }, + 0x1172 => { %gain2010 }, + 0x1174 => { %brightnessValue2010 }, + 0x1178 => { %dynamicRangeOptimizer2010 }, + 0x117c => { %hdr2010 }, + 0x1180 => { %exposureComp2010 }, + 0x1196 => { %pictureProfile2010 }, + 0x1197 => { %pictureProfile2010 }, + 0x119b => { %pictureEffect2010 }, + 0x11a8 => { %quality2010 }, + 0x11ac => { %meteringMode2010 }, + 0x11ad => { %exposureProgram2010 }, + 0x11b4 => { Name => 'WB_RGBLevels', Format => 'int16u[3]' }, + 0x1254 => { + Condition => '$$self{Model} =~ /^(SLT-(A99|A99V)|NEX-(5R|5T|6|VG900|VG30E)|DSC-RX100|Stellar|HV)\b/', + Name => 'SonyISO', + Format => 'int16u', + ValueConv => '100 * 2**(16 - $val/256)', + ValueConvInv => '256 * (16 - log($val/100)/log(2))', + PrintConv => 'sprintf("%.0f",$val)', + PrintConvInv => '$val', + }, + 0x1258 => { + Condition => '$$self{Model} =~ /^(DSC-(RX1|RX1R))\b/', + Name => 'SonyISO', + Format => 'int16u', + ValueConv => '100 * 2**(16 - $val/256)', + ValueConvInv => '256 * (16 - log($val/100)/log(2))', + PrintConv => 'sprintf("%.0f",$val)', + PrintConvInv => '$val', + }, + 0x1278 => { + Condition => '$$self{Model} =~ /^(SLT-A58|ILCE-(3000|3500)|NEX-3N|DSC-(HX300|HX50V|WX60|WX80|WX200|WX300|TX30))\b/', + Name => 'FocalLength', + Format => 'int16u', + ValueConv => '$val / 10', + ValueConvInv => '$val * 10', + PrintConv => 'sprintf("%.1f mm",$val)', + PrintConvInv => '$val =~ s/ ?mm//; $val', + }, + 0x127a => { + Condition => '$$self{Model} =~ /^(SLT-A58|ILCE-(3000|3500)|NEX-3N|DSC-(HX300|HX50V|WX60|WX80|WX200|WX300|TX30))\b/', + Name => 'MinFocalLength', + Format => 'int16u', + ValueConv => '$val / 10', + ValueConvInv => '$val * 10', + PrintConv => 'sprintf("%.1f mm",$val)', + PrintConvInv => '$val =~ s/ ?mm//; $val', + }, + 0x127c => { # may give 0 for fixed focal length lenses + Condition => '$$self{Model} =~ /^(SLT-A58|ILCE-(3000|3500)|NEX-3N|DSC-(HX300|HX50V|WX60|WX80|WX200|WX300|TX30))\b/', + Name => 'MaxFocalLength', + Format => 'int16u', + RawConv => '$val || undef', + ValueConv => '$val / 10', + ValueConvInv => '$val * 10', + PrintConv => 'sprintf("%.1f mm",$val)', + PrintConvInv => '$val =~ s/ ?mm//; $val', + }, + 0x1280 => { + Condition => '$$self{Model} =~ /^(SLT-A58|ILCE-(3000|3500)|NEX-3N|DSC-(HX300|HX50V|WX60|WX80|WX200|WX300|TX30))\b/', + Name => 'SonyISO', + Format => 'int16u', + ValueConv => '100 * 2**(16 - $val/256)', + ValueConvInv => '256 * (16 - log($val/100)/log(2))', + PrintConv => 'sprintf("%.0f",$val)', + PrintConvInv => '$val', + }, + 0x1870 => { + Name => 'DistortionCorrParams', + Condition => '$$self{Model} !~ /^(DSC-|Stellar)/', + Format => 'int16s[16]', + }, + # 0x1890 - same as 0x1892, but has value 3 for 50mm F1.4 ZA, DT 18-135mm and for 70-400mm G II: meaning ?? + 0x1891 => { + Name => 'LensFormat', + Condition => '$$self{Model} !~ /^(DSC-|Stellar)/', + PrintConv => { + 0 => 'Unknown', + 1 => 'APS-C', + 2 => 'Full-frame', + }, + }, + 0x1892 => { + Name => 'LensMount', + DataMember => 'LensMount', + RawConv => '$$self{LensMount} = $val; $$self{Model} =~ /^(DSC-|Stellar)/ ? undef : $val', + PrintConv => { + 0 => 'Unknown', + 1 => 'A-mount', + 2 => 'E-mount', + }, + }, + 0x1893 => { #JR + Name => 'LensType2', + Condition => '$$self{LensMount} == 2', + Format => 'int16u', + SeparateTable => 'LensType2', + PrintConv => \%sonyLensTypes2, + }, + 0x1896 => { + Name => 'LensType', + Condition => '$$self{LensMount} == 1', + Priority => 0, #PH (just to be safe) + Format => 'int16u', #PH + SeparateTable => 1, + ValueConvInv => '($val & 0xff00) == 0x8000 ? 0 : int($val)', + PrintConv => \%sonyLensTypes, + }, + 0x1898 => { + Name => 'DistortionCorrParamsPresent', + Condition => '$$self{Model} !~ /^(DSC-|Stellar)/', + PrintConv => { 0 => 'No', 1 => 'Yes'}, + }, + 0x1899 => { + Name => 'DistortionCorrParamsNumber', + Condition => '$$self{Model} !~ /^DSC-/', + PrintConv => { 11 => '11 (APS-C)', 16 => '16 (Full-frame)'}, + }, + #0x1914 => { Name => 'SonyImageWidth', Format => 'int16u' }, + #0x1918 => { Name => 'SonyImageHeight', Format => 'int16u' }, + #0x192e => { Name => 'SonyImageWidth', Format => 'int16u' }, + #0x1930 => { Name => 'SonyImageHeight', Format => 'int16u' }, +); + +%Image::ExifTool::Sony::Tag2010f = ( #JR + PROCESS_PROC => \&ProcessEnciphered, + WRITE_PROC => \&WriteEnciphered, + CHECK_PROC => \&Image::ExifTool::CheckBinaryData, + FORMAT => 'int8u', + NOTES => 'Valid for DSC-RX100M2, DSC-QX10/QX100.', + WRITABLE => 1, + FIRST_ENTRY => 0, + PRIORITY => 0, + GROUPS => { 0 => 'MakerNotes', 2 => 'Image' }, + 0x0004 => { %releaseMode2, Format => 'int32u' }, # NOT at offset 0x08 ! + #0x002e => { Name => 'SonyImageWidth3', Format => 'int16u' }, + #0x0042 => { Name => 'SonyImageWidth3', Format => 'int16u' }, + 0x0050 => { %dynamicRangeOptimizer2010 }, + 0x01e0 => { + Name => 'MeterInfo', + Format => 'int32u[486]', + Unknown => 1, + SubDirectory => { TagTable => 'Image::ExifTool::Sony::MeterInfo' }, + }, + 0x1014 => { %releaseMode2010 }, + 0x1018 => { %releaseMode2 }, + 0x1020 => { %selfTimer2010 }, + 0x1024 => { %flashMode2010 }, + 0x102a => { %gain2010 }, + 0x102c => { %brightnessValue2010 }, + 0x1030 => { %dynamicRangeOptimizer2010 }, + 0x1034 => { %hdr2010 }, + 0x1038 => { %exposureComp2010 }, + 0x104e => { %pictureProfile2010 }, + 0x104f => { %pictureProfile2010 }, + 0x1053 => { %pictureEffect2010 }, + 0x1060 => { %quality2010 }, + 0x1064 => { %meteringMode2010 }, + 0x1065 => { %exposureProgram2010 }, + 0x106c => { Name => 'WB_RGBLevels', Format => 'int16u[3]' }, + #0x1096 => { Name => 'SonyImageWidth3', Format => 'int16u' }, + #0x10aa => { Name => 'SonyImageWidth3', Format => 'int16u' }, + 0x1134 => { + Name => 'FocalLength', + Format => 'int16u', + ValueConv => '$val / 10', + ValueConvInv => '$val * 10', + PrintConv => 'sprintf("%.1f mm",$val)', + PrintConvInv => '$val =~ s/ ?mm//; $val', + }, + 0x1136 => { + Name => 'MinFocalLength', + Format => 'int16u', + ValueConv => '$val / 10', + ValueConvInv => '$val * 10', + PrintConv => 'sprintf("%.1f mm",$val)', + PrintConvInv => '$val =~ s/ ?mm//; $val', + }, + 0x1138 => { + Name => 'MaxFocalLength', + Format => 'int16u', + ValueConv => '$val / 10', + ValueConvInv => '$val * 10', + PrintConv => 'sprintf("%.1f mm",$val)', + PrintConvInv => '$val =~ s/ ?mm//; $val', + }, + 0x113c => { + Name => 'SonyISO', + Format => 'int16u', + ValueConv => '100 * 2**(16 - $val/256)', + ValueConvInv => '256 * (16 - log($val/100)/log(2))', + PrintConv => 'sprintf("%.0f",$val)', + PrintConvInv => '$val', + }, + #0x1914 => { Name => 'SonyImageWidth', Format => 'int16u' }, + #0x1918 => { Name => 'SonyImageHeight', Format => 'int16u' }, + #0x192e => { Name => 'SonyImageWidth', Format => 'int16u' }, + #0x1930 => { Name => 'SonyImageHeight', Format => 'int16u' }, +); + +%Image::ExifTool::Sony::Tag2010g = ( #JR + PROCESS_PROC => \&ProcessEnciphered, + WRITE_PROC => \&WriteEnciphered, + CHECK_PROC => \&Image::ExifTool::CheckBinaryData, + FORMAT => 'int8u', + NOTES => q{ + Valid for DSC-HX60V/HX350/HX400V/QX30/RX10/RX100M3/WX220/WX350, + ILCE-7/7R/7S/7M2/5000/5100/6000/QX1, ILCA-68/77M2. + }, + WRITABLE => 1, + FIRST_ENTRY => 0, + PRIORITY => 0, + GROUPS => { 0 => 'MakerNotes', 2 => 'Image' }, + 0x0004 => { %releaseMode2, Format => 'int32u' }, # NOT at offset 0x08 ! + 0x0050 => { %dynamicRangeOptimizer2010 }, + 0x020c => { %releaseMode2010 }, + 0x0210 => { %releaseMode2 }, + 0x0218 => { %selfTimer2010 }, + 0x021c => { %flashMode2010 }, + 0x0222 => { %gain2010 }, + 0x0224 => { %brightnessValue2010 }, + 0x0228 => { %dynamicRangeOptimizer2010 }, + 0x022c => { %hdr2010 }, + 0x0230 => { %exposureComp2010 }, + 0x0246 => { %pictureProfile2010 }, + 0x0247 => { %pictureProfile2010 }, + 0x024b => { %pictureEffect2010 }, + 0x0258 => { %quality2010 }, + 0x025c => { %meteringMode2010 }, + 0x025d => { %exposureProgram2010 }, + 0x0264 => { Name => 'WB_RGBLevels', Format => 'int16u[3]' }, + 0x032c => { + Name => 'FocalLength', + Format => 'int16u', + ValueConv => '$val / 10', + ValueConvInv => '$val * 10', + PrintConv => 'sprintf("%.1f mm",$val)', + PrintConvInv => '$val =~ s/ ?mm//; $val', + }, + 0x032e => { + Name => 'MinFocalLength', + Format => 'int16u', + ValueConv => '$val / 10', + ValueConvInv => '$val * 10', + PrintConv => 'sprintf("%.1f mm",$val)', + PrintConvInv => '$val =~ s/ ?mm//; $val', + }, + 0x0330 => { # may give 0 for fixed focal length lenses + Name => 'MaxFocalLength', + Format => 'int16u', + RawConv => '$val || undef', + ValueConv => '$val / 10', + ValueConvInv => '$val * 10', + PrintConv => 'sprintf("%.1f mm",$val)', + PrintConvInv => '$val =~ s/ ?mm//; $val', + }, + 0x0344 => { + Name => 'SonyISO', + Format => 'int16u', + ValueConv => '100 * 2**(16 - $val/256)', + ValueConvInv => '256 * (16 - log($val/100)/log(2))', + PrintConv => 'sprintf("%.0f",$val)', + PrintConvInv => '$val', + }, + 0x0388 => { + Name => 'MeterInfo', + Format => 'int32u[486]', + Unknown => 1, + SubDirectory => { TagTable => 'Image::ExifTool::Sony::MeterInfo' }, + }, + 0x189c => { + Name => 'DistortionCorrParams', + Condition => '$$self{Model} !~ /^DSC-/', + Format => 'int16s[16]', + }, + # 0x18bc - same as 0x18be, but has value 3 for 50mm F1.4 ZA, DT 18-135mm and for 70-400mm G II: meaning ?? + 0x18bd => { + Name => 'LensFormat', + Condition => '$$self{Model} !~ /^DSC-/', + PrintConv => { + 0 => 'Unknown', + 1 => 'APS-C', + 2 => 'Full-frame', + }, + }, + 0x18be => { + Name => 'LensMount', + DataMember => 'LensMount', + RawConv => '$$self{LensMount} = $val; $$self{Model} =~ /^DSC-/ ? undef : $val', + PrintConv => { + 0 => 'Unknown', + 1 => 'A-mount', + 2 => 'E-mount', + }, + }, + 0x18bf => { #JR + Name => 'LensType2', + Condition => '$$self{LensMount} == 2', + Format => 'int16u', + SeparateTable => 'LensType2', + PrintConv => \%sonyLensTypes2, + }, + 0x18c2 => { + Name => 'LensType', + Condition => '$$self{LensMount} == 1', + Priority => 0, #PH (just to be safe) + Format => 'int16u', #PH + SeparateTable => 1, + ValueConvInv => '($val & 0xff00) == 0x8000 ? 0 : int($val)', + PrintConv => \%sonyLensTypes, + }, + 0x18c4 => { + Name => 'DistortionCorrParamsPresent', + Condition => '$$self{Model} !~ /^DSC-/', + PrintConv => { 0 => 'No', 1 => 'Yes'}, + }, + 0x18c5 => { + Name => 'DistortionCorrParamsNumber', + Condition => '$$self{Model} !~ /^DSC-/', + PrintConv => { 11 => '11 (APS-C)', 16 => '16 (Full-frame)'}, + }, + # 0x1940 => { Name => 'SonyImageWidth', Format => 'int16u' }, + # 0x1944 => { Name => 'SonyImageHeight', Format => 'int16u' }, + # 0x195a => { Name => 'SonyImageWidth', Format => 'int16u' }, + # 0x195c => { Name => 'SonyImageHeight', Format => 'int16u' }, +); + +%Image::ExifTool::Sony::Tag2010h = ( #JR + PROCESS_PROC => \&ProcessEnciphered, + WRITE_PROC => \&WriteEnciphered, + CHECK_PROC => \&Image::ExifTool::CheckBinaryData, + FORMAT => 'int8u', + NOTES => q{ + Valid for DSC-HX80/HX90V/RX0/RX1RM2/RX10M2/RX10M3/RX100M4/RX100M5/WX500, + ILCE-6300/6500/7RM2/7SM2, ILCA-99M2. + }, + WRITABLE => 1, + FIRST_ENTRY => 0, + PRIORITY => 0, + GROUPS => { 0 => 'MakerNotes', 2 => 'Image' }, + 0x0004 => { %releaseMode2, Format => 'int32u' }, + 0x0050 => { %dynamicRangeOptimizer2010 }, + 0x020c => { %releaseMode2010 }, + 0x0210 => { %releaseMode2 }, + 0x0218 => { %selfTimerB2010 }, + 0x021c => { %flashMode2010 }, + 0x0222 => { %gain2010 }, + 0x0224 => { %brightnessValue2010 }, + 0x0228 => { %dynamicRangeOptimizer2010 }, + 0x022c => { %hdr2010 }, + 0x0230 => { %exposureComp2010 }, + 0x0246 => { %pictureProfile2010 }, + 0x0247 => { %pictureProfile2010 }, + 0x024b => { %pictureEffect2010 }, + 0x0258 => { %quality2010 }, + 0x025c => { %meteringMode2010 }, + 0x025d => { %exposureProgram2010 }, + 0x0264 => { Name => 'WB_RGBLevels', Format => 'int16u[3]' }, + 0x032c => { + Name => 'FocalLength', + Format => 'int16u', + ValueConv => '$val / 10', + ValueConvInv => '$val * 10', + PrintConv => 'sprintf("%.1f mm",$val)', + PrintConvInv => '$val =~ s/ ?mm//; $val', + }, + 0x032e => { + Name => 'MinFocalLength', + Format => 'int16u', + ValueConv => '$val / 10', + ValueConvInv => '$val * 10', + PrintConv => 'sprintf("%.1f mm",$val)', + PrintConvInv => '$val =~ s/ ?mm//; $val', + }, + 0x0330 => { # may give 0 for fixed focal length lenses + Name => 'MaxFocalLength', + Format => 'int16u', + RawConv => '$val || undef', + ValueConv => '$val / 10', + ValueConvInv => '$val * 10', + PrintConv => 'sprintf("%.1f mm",$val)', + PrintConvInv => '$val =~ s/ ?mm//; $val', + }, + 0x0346 => { + Name => 'SonyISO', + Format => 'int16u', + ValueConv => '100 * 2**(16 - $val/256)', + ValueConvInv => '256 * (16 - log($val/100)/log(2))', + PrintConv => 'sprintf("%.0f",$val)', + PrintConvInv => '$val', + }, + 0x0388 => { + Name => 'MeterInfo', + Format => 'int32u[486]', + Condition => '$$self{Model} !~ /^(ILCA-99M2|ILCE-6500|DSC-(RX0|RX100M5))/', + Unknown => 1, + SubDirectory => { TagTable => 'Image::ExifTool::Sony::MeterInfo' }, + }, + 0x0398 => { + Name => 'MeterInfo', + Format => 'int32u[486]', + Condition => '$$self{Model} =~ /^(ILCA-99M2|ILCE-6500|DSC-(RX0|RX100M5))/', + Unknown => 1, + SubDirectory => { TagTable => 'Image::ExifTool::Sony::MeterInfo' }, + }, + 0x18cc => { + Name => 'DistortionCorrParams', + Condition => '$$self{Model} !~ /^DSC-/', + Format => 'int16s[16]', + }, + # 0x18ec - same as 0x18ee, but has value 3 for LensType>=65, except SAL300F28G2 + 0x18ed => { + Name => 'LensFormat', + Condition => '$$self{Model} !~ /^DSC-/', + PrintConv => { + 0 => 'Unknown', + 1 => 'APS-C', + 2 => 'Full-frame', + }, + }, + 0x18ee => { + Name => 'LensMount', + DataMember => 'LensMount', + RawConv => '$$self{LensMount} = $val; $$self{Model} =~ /^DSC-/ ? undef : $val', + PrintConv => { + 0 => 'Unknown', + 1 => 'A-mount', + 2 => 'E-mount', + }, + }, + 0x18ef => { #JR + Name => 'LensType2', + Condition => '$$self{LensMount} == 2', + Format => 'int16u', + SeparateTable => 'LensType2', + PrintConv => \%sonyLensTypes2, + }, + 0x18f2 => { + Name => 'LensType', + Condition => '$$self{LensMount} == 1', + Priority => 0, #PH (just to be safe) + Format => 'int16u', #PH + SeparateTable => 1, + ValueConvInv => '($val & 0xff00) == 0x8000 ? 0 : int($val)', + PrintConv => \%sonyLensTypes, + }, + 0x18f4 => { + Name => 'DistortionCorrParamsPresent', + Condition => '$$self{Model} !~ /^DSC-/', + PrintConv => { 0 => 'No', 1 => 'Yes'}, + }, + 0x18f5 => { + Name => 'DistortionCorrParamsNumber', + Condition => '$$self{Model} !~ /^DSC-/', + PrintConv => { 11 => '11 (APS-C)', 16 => '16 (Full-frame)'}, + }, + # 0x1970 => { Name => 'SonyImageWidth', Format => 'int16u' }, + # 0x1974 => { Name => 'SonyImageHeight', Format => 'int16u' }, + # 0x198a => { Name => 'SonyImageWidth', Format => 'int16u' }, + # 0x198c => { Name => 'SonyImageHeight', Format => 'int16u' }, +); + +%Image::ExifTool::Sony::Tag2010i = ( #JR + PROCESS_PROC => \&ProcessEnciphered, + WRITE_PROC => \&WriteEnciphered, + CHECK_PROC => \&Image::ExifTool::CheckBinaryData, + FORMAT => 'int8u', + NOTES => q{ + Valid for ILCE-6400/7M3/7RM3/9, DSC-RX10M4/RX100M6/RX100M5A/HX99. + }, + WRITABLE => 1, + FIRST_ENTRY => 0, + PRIORITY => 0, + GROUPS => { 0 => 'MakerNotes', 2 => 'Image' }, + 0x0004 => { %releaseMode2, Format => 'int32u' }, + 0x004e => { %dynamicRangeOptimizer2010 }, + 0x0204 => { %releaseMode2010 }, + 0x0208 => { %releaseMode2 }, + 0x0210 => { %selfTimerB2010 }, + 0x0211 => { %flashMode2010 }, + 0x0217 => { %gain2010 }, + 0x0219 => { %brightnessValue2010 }, + 0x021b => { %dynamicRangeOptimizer2010 }, + 0x021f => { %hdr2010 }, + 0x0223 => { %exposureComp2010 }, + 0x0237 => { %pictureProfile2010 }, + 0x0238 => { %pictureProfile2010 }, + 0x023c => { %pictureEffect2010 }, + 0x0247 => { %quality2010 }, + 0x024b => { %meteringMode2010 }, + 0x024c => { %exposureProgram2010 }, + 0x0252 => { Name => 'WB_RGBLevels', Format => 'int16u[3]' }, + 0x030a => { + Name => 'FocalLength', + Format => 'int16u', + ValueConv => '$val / 10', + ValueConvInv => '$val * 10', + PrintConv => 'sprintf("%.1f mm",$val)', + PrintConvInv => '$val =~ s/ ?mm//; $val', + }, + 0x030c => { + Name => 'MinFocalLength', + Format => 'int16u', + ValueConv => '$val / 10', + ValueConvInv => '$val * 10', + PrintConv => 'sprintf("%.1f mm",$val)', + PrintConvInv => '$val =~ s/ ?mm//; $val', + }, + 0x030e => { # may give 0 for fixed focal length lenses + Name => 'MaxFocalLength', + Format => 'int16u', + RawConv => '$val || undef', + ValueConv => '$val / 10', + ValueConvInv => '$val * 10', + PrintConv => 'sprintf("%.1f mm",$val)', + PrintConvInv => '$val =~ s/ ?mm//; $val', + }, + 0x0320 => { + Name => 'SonyISO', + Format => 'int16u', + ValueConv => '100 * 2**(16 - $val/256)', + ValueConvInv => '256 * (16 - log($val/100)/log(2))', + PrintConv => 'sprintf("%.0f",$val)', + PrintConvInv => '$val', + }, + 0x036d => { # different format from all previous cameras: now each triple is int16u-int32u-int32u + Name => 'MeterInfo', + Format => 'undef[1620]', + Unknown => 1, + SubDirectory => { TagTable => 'Image::ExifTool::Sony::MeterInfo9' }, + }, + 0x17d0 => { + Name => 'DistortionCorrParams', + Condition => '$$self{Model} !~ /^DSC-/', + Format => 'int16s[16]', + }, + # 0x17f0 - same as 0x17f2, but has value 3 for LensType>=65, except SAL300F28G2 + 0x17f1 => { + Name => 'LensFormat', + Condition => '$$self{Model} !~ /^DSC-/', + PrintConv => { + 0 => 'Unknown', + 1 => 'APS-C', + 2 => 'Full-frame', + }, + }, + 0x17f2 => { + Name => 'LensMount', + DataMember => 'LensMount', + RawConv => '$$self{LensMount} = $val; $$self{Model} =~ /^DSC-/ ? undef : $val', + PrintConv => { + 0 => 'Unknown', + 1 => 'A-mount', + 2 => 'E-mount', + }, + }, + 0x17f3 => { #JR + Name => 'LensType2', + Condition => '$$self{LensMount} == 2', + Format => 'int16u', + SeparateTable => 'LensType2', + PrintConv => \%sonyLensTypes2, + }, + 0x17f6 => { + Name => 'LensType', + Condition => '$$self{LensMount} == 1', + Priority => 0, #PH (just to be safe) + Format => 'int16u', #PH + SeparateTable => 1, + ValueConvInv => '($val & 0xff00) == 0x8000 ? 0 : int($val)', + PrintConv => \%sonyLensTypes, + }, + 0x17f8 => { + Name => 'DistortionCorrParamsPresent', + Condition => '$$self{Model} !~ /^DSC-/', + PrintConv => { 0 => 'No', 1 => 'Yes'}, + }, + 0x17f9 => { + Name => 'DistortionCorrParamsNumber', + Condition => '$$self{Model} !~ /^DSC-/', + PrintConv => { 11 => '11 (APS-C)', 16 => '16 (Full-frame)'}, + }, +); + +%Image::ExifTool::Sony::Tag202a = ( + %binaryDataAttrs, + GROUPS => { 0 => 'MakerNotes', 2 => 'Camera' }, + FORMAT => 'int8u', + DATAMEMBER => [ 0x01 ], +# +# first seen for ILCE-6300 +# Possibly the Locations of the FocalPlaneAFPointsUsed are indicated here. +# 66 bytes, structure appears to be as follows: +# 0x00 - 1 for ILCE-6300/6500, ILCA-99M2 +# 0x01 - int8u: 0 to 15 - nr of locations to follow +# 0x02 and 0x03 - (128 2) or 640 - (max.) width (X) of (LCD screen) area of following locations +# 0x04 and 0x05 - (172 1) or 428 - (max.) height (Y) of (LCD screen) area of following locations +# origin of X-Y coordinates appears to be top-left, i.e. X to the right, Y pointing down. +# 0x06 0x07 0x08 0x09 - 2x int16u : X and Y coordinates of Location 1 +# etc. +# + 0x01 => { + Name => 'FocalPlaneAFPointsUsed', + DataMember => 'Locations', + Format => 'int8u', + RawConv => '$$self{Locations} = $val', + }, + 0x02 => { + Name => 'FocalPlaneAFPointArea', + Condition => '$$self{Locations} >= 1', # only output this if at least 1 Location follows ? + Format => 'int16u[2]', + }, + 0x06 => { Name => 'FocalPlaneAFPointLocation1', Condition => '$$self{Locations} >= 1', Format => 'int16u[2]' }, + 0x0a => { Name => 'FocalPlaneAFPointLocation2', Condition => '$$self{Locations} >= 2', Format => 'int16u[2]' }, + 0x0e => { Name => 'FocalPlaneAFPointLocation3', Condition => '$$self{Locations} >= 3', Format => 'int16u[2]' }, + 0x12 => { Name => 'FocalPlaneAFPointLocation4', Condition => '$$self{Locations} >= 4', Format => 'int16u[2]' }, + 0x16 => { Name => 'FocalPlaneAFPointLocation5', Condition => '$$self{Locations} >= 5', Format => 'int16u[2]' }, + 0x1a => { Name => 'FocalPlaneAFPointLocation6', Condition => '$$self{Locations} >= 6', Format => 'int16u[2]' }, + 0x1e => { Name => 'FocalPlaneAFPointLocation7', Condition => '$$self{Locations} >= 7', Format => 'int16u[2]' }, + 0x22 => { Name => 'FocalPlaneAFPointLocation8', Condition => '$$self{Locations} >= 8', Format => 'int16u[2]' }, + 0x26 => { Name => 'FocalPlaneAFPointLocation9', Condition => '$$self{Locations} >= 9', Format => 'int16u[2]' }, + 0x2a => { Name => 'FocalPlaneAFPointLocation10', Condition => '$$self{Locations} >= 10', Format => 'int16u[2]' }, + 0x2e => { Name => 'FocalPlaneAFPointLocation11', Condition => '$$self{Locations} >= 11', Format => 'int16u[2]' }, + 0x32 => { Name => 'FocalPlaneAFPointLocation12', Condition => '$$self{Locations} >= 12', Format => 'int16u[2]' }, + 0x36 => { Name => 'FocalPlaneAFPointLocation13', Condition => '$$self{Locations} >= 13', Format => 'int16u[2]' }, + 0x3a => { Name => 'FocalPlaneAFPointLocation14', Condition => '$$self{Locations} >= 14', Format => 'int16u[2]' }, + 0x3e => { Name => 'FocalPlaneAFPointLocation15', Condition => '$$self{Locations} >= 15', Format => 'int16u[2]' }, +); + +# possible metering information (ref JR) +%Image::ExifTool::Sony::MeterInfo = ( + %binaryDataAttrs, + GROUPS => { 0 => 'MakerNotes', 2 => 'Image' }, + NOTES => q{ + Information possibly related to metering. Extracted only if the Unknown + option is used. + }, +# +# 162 'triplets' of 3 int32u numbers: (k,n1,n2) +# These appear to relate to two sets of brightness distribution over the image area: +# Set 1: 7 rows of 9 +# Set 2: 9 rows of 11 +# +# Exact meaning presently unknown, however: +# n1 ranges from 0 (black) - appr. 1300 (bright white) +# n2 ranges from 0 (black) - appr. 142000 (bright white), i.e. roughly factor 100 higher +# Many panorama images: all 0 +# Flash images: n2 = n1 +# k maybe some kind of 'gain' or multiplication factor ? +# k distribution over the image as function of Aspect-Ratio is as follows: +# +# 3:2 image 16:9 image 4:3 image +# set 1: +# +# 12 12 12 12 12 12 12 12 12 12 12 12 15 18 15 12 12 12 9 12 12 12 12 12 12 12 9 +# 12 12 12 12 12 12 12 12 12 12 12 12 15 18 15 12 12 12 9 12 12 12 12 12 12 12 9 +# 16 16 16 16 16 16 16 16 16 12 12 12 15 18 15 12 12 12 12 16 16 16 16 16 16 16 12 +# 16 16 16 16 16 16 16 16 16 12 12 12 15 18 15 12 12 12 12 16 16 16 16 16 16 16 12 +# 16 16 16 16 16 16 16 16 16 12 12 12 15 18 15 12 12 12 12 16 16 16 16 16 16 16 12 +# 12 12 12 12 12 12 12 12 12 12 12 12 15 18 15 12 12 12 9 12 12 12 12 12 12 12 9 +# 12 12 12 12 12 12 12 12 12 12 12 12 15 18 15 12 12 12 9 12 12 12 12 12 12 12 9 +# +# set 2: +# +# 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 15 18 15 12 12 12 12 9 9 12 12 12 12 12 12 12 9 9 +# 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 15 18 15 12 12 12 12 9 9 12 12 12 12 12 12 12 9 9 +# 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 15 18 15 12 12 12 12 9 9 12 12 12 12 12 12 12 9 9 +# 16 16 16 16 16 16 16 16 16 16 16 12 12 12 12 15 18 15 12 12 12 12 12 12 16 16 16 16 16 16 16 12 12 +# 16 16 16 16 16 16 16 16 16 16 16 12 12 12 12 15 18 15 12 12 12 12 12 12 16 16 16 16 16 16 16 12 12 +# 16 16 16 16 16 16 16 16 16 16 16 12 12 12 12 15 18 15 12 12 12 12 12 12 16 16 16 16 16 16 16 12 12 +# 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 15 18 15 12 12 12 12 9 9 12 12 12 12 12 12 12 9 9 +# 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 15 18 15 12 12 12 12 9 9 12 12 12 12 12 12 12 9 9 +# 12 12 12 12 12 12 12 12 12 12 12 8 8 8 8 10 12 10 8 8 8 8 9 9 12 12 12 12 12 12 12 9 9 +# +# Usually, in the center, the numbers of set 1 row 2-6 match with set 2 row 3-7, except for first and last 2 columns. +# + 0x0000 => { Name => 'MeterInfo1Row1', %meterInfo1 }, + 0x006c => { Name => 'MeterInfo1Row2', %meterInfo1 }, + 0x00d8 => { Name => 'MeterInfo1Row3', %meterInfo1 }, + 0x0144 => { Name => 'MeterInfo1Row4', %meterInfo1 }, + 0x01b0 => { Name => 'MeterInfo1Row5', %meterInfo1 }, + 0x021c => { Name => 'MeterInfo1Row6', %meterInfo1 }, + 0x0288 => { Name => 'MeterInfo1Row7', %meterInfo1 }, + + 0x02f4 => { Name => 'MeterInfo2Row1', %meterInfo2 }, + 0x0378 => { Name => 'MeterInfo2Row2', %meterInfo2 }, + 0x03fc => { Name => 'MeterInfo2Row3', %meterInfo2 }, + 0x0480 => { Name => 'MeterInfo2Row4', %meterInfo2 }, + 0x0504 => { Name => 'MeterInfo2Row5', %meterInfo2 }, + 0x0588 => { Name => 'MeterInfo2Row6', %meterInfo2 }, + 0x060c => { Name => 'MeterInfo2Row7', %meterInfo2 }, + 0x0690 => { Name => 'MeterInfo2Row8', %meterInfo2 }, + 0x0714 => { Name => 'MeterInfo2Row9', %meterInfo2 }, +); + +# possible metering information (ref JR) +%Image::ExifTool::Sony::MeterInfo9 = ( + %binaryDataAttrs, + GROUPS => { 0 => 'MakerNotes', 2 => 'Image' }, + NOTES => q{ + Information possibly related to metering. Extracted only if the Unknown + option is used. + }, +# new format for ILCE-9: +# 162 'triplets' of (int16u int32u int32u) numbers: (k,n1,n2) +# Set 1: 7 rows of 9 +# Set 2: 9 rows of 11 + 0x0000 => { Name => 'MeterInfo1Row1', %meterInfo1b }, + 0x005a => { Name => 'MeterInfo1Row2', %meterInfo1b }, + 0x00b4 => { Name => 'MeterInfo1Row3', %meterInfo1b }, + 0x010e => { Name => 'MeterInfo1Row4', %meterInfo1b }, + 0x0168 => { Name => 'MeterInfo1Row5', %meterInfo1b }, + 0x01c2 => { Name => 'MeterInfo1Row6', %meterInfo1b }, + 0x021c => { Name => 'MeterInfo1Row7', %meterInfo1b }, + + 0x0276 => { Name => 'MeterInfo2Row1', %meterInfo2b }, + 0x02e4 => { Name => 'MeterInfo2Row2', %meterInfo2b }, + 0x0352 => { Name => 'MeterInfo2Row3', %meterInfo2b }, + 0x03c0 => { Name => 'MeterInfo2Row4', %meterInfo2b }, + 0x042e => { Name => 'MeterInfo2Row5', %meterInfo2b }, + 0x049c => { Name => 'MeterInfo2Row6', %meterInfo2b }, + 0x050a => { Name => 'MeterInfo2Row7', %meterInfo2b }, + 0x0578 => { Name => 'MeterInfo2Row8', %meterInfo2b }, + 0x05e6 => { Name => 'MeterInfo2Row9', %meterInfo2b }, +); + +%Image::ExifTool::Sony::Tag900b = ( #JR + PROCESS_PROC => \&ProcessEnciphered, + WRITE_PROC => \&WriteEnciphered, + CHECK_PROC => \&Image::ExifTool::CheckBinaryData, + GROUPS => { 0 => 'MakerNotes', 2 => 'Camera' }, + # 0x0000 - always 174 (e) + 0x0002 => { + Name => 'FacesDetected', + PrintConv => { + 0 => '0', + 98 => '1', + 57 => '2', + 93 => '3', + 77 => '4', + 33 => '5', + 168 => '6', + 241 => '7', + 115 => '8', + }, + }, + # 0x00bc - always 98 (221 (e)) + 0x00bd => { + Condition => '$$self{Model} !~ /^DSLR-(A450|A500|A550)$/', # always 98 for A450/A500/A550: exclude + Name => 'FaceDetection', + PrintConv => { + 0 => 'Off', + 98 => 'On', + }, + }, +); + +%Image::ExifTool::Sony::Tag9050a = ( #JR + PROCESS_PROC => \&ProcessEnciphered, + WRITE_PROC => \&WriteEnciphered, + CHECK_PROC => \&Image::ExifTool::CheckBinaryData, + FORMAT => 'int8u', + NOTES => q{ + Valid for SLT, ILCA, NEX and ILCE models, except ILCE-6300/6500/7RM2/7SM2, + ILCA-99M2. + }, + WRITABLE => 1, + FIRST_ENTRY => 0, + DATAMEMBER => [ 0x0105 ], + GROUPS => { 0 => 'MakerNotes', 2 => 'Image' }, + NOTES => q{ + Data for tags 0x9050, 0x94xx and 0x2010 is encrypted by a simple + substitution cipher, but the deciphered values are listed below. + }, + 0x0000 => { + Condition => '$$self{Model} !~ /^(NEX-|Lunar|ILCE-)/', + Name => 'SonyMaxAperture', # (at current focal length) + # seen values from 17 - 48 + ValueConv => '2 ** (($val/8 - 1.06) / 2)', + ValueConvInv => 'int((log($val) * 2 / log(2) + 1) * 8 + 0.5)', + PrintConv => 'sprintf("%.1f",$val)', + PrintConvInv => '$val', + }, + 0x0001 => { + Condition => '$$self{Model} !~ /^(NEX-|Lunar|ILCE-)/', + Name => 'SonyMinAperture', # (at current focal length) + # seen values from 80 - 95 + ValueConv => '2 ** (($val/8 - 1.06) / 2)', + ValueConvInv => 'int((log($val) * 2 / log(2) + 1) * 8 + 0.5)', + PrintConv => 'sprintf("%.0f",$val)', + PrintConvInv => '$val', + }, +# 0x0002 and 0x0004 (int16u) for SLT: +# appears to be difference between used FNumber and MaxAperture, 256 being +1 APEX or stop +# however, not always valid e.g. bracketing, Shutter-prio e.a. +# difference between 0x0002 and 0x0004 mostly 0.0, 0.1 or 0.2 stops. + # 0x0020 - int16u[3]: all 0's when Silent Shooting / Electronic Shutter (ILCE-7S only) + 0x0031 => { #JR + Name => 'FlashStatus', + RawConv => '$$self{FlashFired} = $val', + PrintConv => { + 0 => 'No Flash present', + 2 => 'Flash Inhibited', # seen for ILCE-7/7R continuous, panorama, HDR mode + 64 => 'Built-in Flash present', + 65 => 'Built-in Flash Fired', + 66 => 'Built-in Flash Inhibited', # seen for panorama, HDR, burst mode + 128 => 'External Flash present', # seen for NEX-5N/5T + 129 => 'External Flash Fired', # seen for SLT-A99V, ILCE-7R, NEX-5N/5R + }, + }, + 0x0032 => { #13 + Name => 'ShutterCount', + # this seems to be valid for the A7R,A37,A57,A65,A77,A99,A99V and possibly the + # NEX-5N/7. For the A99V it is definitely more than 16 bits, but it wraps at + # 65536 for the A7R. + Format => 'int32u', + Notes => q{ + total number of image exposures made by the camera, modulo 65536 for some + models + }, + RawConv => '$val & 0x00ffffff', + }, + 0x003a => { # appr. same value as Exif ExposureTime, but longer in HDR-modes + Name => 'SonyExposureTime', + Format => 'int16u', + ValueConv => '$val ? 2 ** (16 - $val/256) : 0', + ValueConvInv => '$val ? int((16 - log($val) / log(2)) * 256 + 0.5) : 0', + PrintConv => '$val ? Image::ExifTool::Exif::PrintExposureTime($val) : "Bulb"', + PrintConvInv => 'lc($val) eq "bulb" ? 0 : Image::ExifTool::Exif::ConvertFraction($val)', + }, + 0x003c => { + Name => 'SonyFNumber', + Format => 'int16u', + ValueConv => '2 ** (($val/256 - 16) / 2)', + ValueConvInv => '(log($val)*2/log(2)+16)*256', + PrintConv => 'sprintf("%.1f",$val)', + PrintConvInv => '$val', + }, + 0x003f => { + Name => 'ReleaseMode2', + %releaseMode2, + }, +# 0x004c - 0x005b: A-Mount: 16 values, only non-zero data for lenses giving "A-mount (3)" in 0x0104 below. +# e.g for SAL70400G2: 9 5 5 64 69 74 79 84 89 94 98 104 255 105 89 80 +# where 9 means 9 focal lengths: 64 ... 104, +# corresponding to 70-400mm via FocalLength = 4.375*2**($val/16) +# 0x004c, 0x0051: E-Mount: ShutterCount and dateTime + 0x004c => { # only ILCE-7/7R/7S/7M2/5000/5100/6000/QX1 - but appears not valid when flash is used ... + Name => 'ShutterCount2', + Condition => '($$self{Model} =~ /^(ILCE-(7(R|S|M2)?|[56]000|5100|QX1))\b/) and (($$self{FlashFired} & 0x01) != 1)', + Format => 'int32u', + RawConv => '$val & 0x00ffffff', + }, + 0x0051 => { # only ILCE-7/7R/7S/7M2/5000/5100/6000/QX1, but hours usually different from SonyDateTime - UTC? + # appears not valid (all '0') when flash is used, panorama, hdr modes ... + Name => 'SonyDateTime2', + Condition => '$$self{Model} =~ /^(ILCE-(7(R|S|M2)?|[56]000|5100|QX1))\b/', + Groups => { 2 => 'Time' }, + Shift => 'Time', + Format => 'undef[6]', + ValueConv => q{ + my @v = unpack('C*', $val); + return undef unless $v[0] > 0; + return sprintf("20%.2d:%.2d:%.2d %.2d:%.2d:%.2d", @v) + }, + ValueConvInv => q{ + my @v = ($val =~ /\d+/g); + return undef unless @v == 6 and ($v[0]-=2000) >= 0; + return pack('C*', @v); + }, + PrintConv => '$self->ConvertDateTime($val)', + PrintConvInv => '$self->InverseDateTime($val,0)', + }, + 0x0067 => { + Name => 'ReleaseMode2', + Condition => '$$self{Model} !~ /^(SLT-A(65|77)V?|Lunar|NEX-(5N|7|VG20E))/', + %releaseMode2, + }, + 0x007c => { #JR valid for ILCE and most NEX + Name => 'InternalSerialNumber', #(NC) + Condition => '$$self{Model} !~ /^(Lunar|NEX-(5N|7|VG20E)|SLT-|HV|ILCA-)/', + Format => 'int8u[4]', + PrintConv => 'unpack "H*", pack "C*", split " ", $val', + }, + 0x00f0 => { #JR valid for SLT/ILCA models + Name => 'InternalSerialNumber', #(NC) + Condition => '$$self{Model} =~ /^(SLT-|HV|ILCA-)/', + Format => 'int8u[5]', + PrintConv => 'unpack "H*", pack "C*", split " ", $val', + PrintConvInv => 'join " ", unpack "C*", pack "H*", $val', + }, + # 0x0104 - same as 0x0105, but has value 3 for 50mm F1.4 ZA, DT 18-135mm and for 70-400mm G II: meaning ?? + 0x0105 => { + Name => 'LensMount', + DataMember => 'LensMount', + RawConv => '$$self{LensMount} = $val', + PrintConv => { + 0 => 'Unknown', + 1 => 'A-mount', + 2 => 'E-mount', + }, + }, + 0x0106 => { + Name => 'LensFormat', + PrintConv => { + 0 => 'Unknown', + 1 => 'APS-C', + 2 => 'Full-frame', + }, + }, + 0x0107 => { + Name => 'LensType2', + Condition => '$$self{LensMount} == 2', + Format => 'int16u', + SeparateTable => 'LensType2', + PrintConv => \%sonyLensTypes2, + }, + 0x0109 => { + Name => 'LensType', + Condition => '$$self{LensMount} == 1', + Priority => 0, #PH (just to be safe) + Format => 'int16u', #PH + Notes => 'SLT models, and NEX with A-mount lenses', + SeparateTable => 1, + # has a value of 0 for E-mount lenses (values 0x80xx) + ValueConvInv => '($val & 0xff00) == 0x8000 ? 0 : int($val)', + PrintConv => \%sonyLensTypes, + }, + 0x010b => { + Name => 'DistortionCorrParamsPresent', + PrintConv => { 0 => 'No', 1 => 'Yes'}, + }, + # 0x0115 and 0x0116, or 0x0116 and 0x0117: + # give the same info as the first and last bytes of LensSpec, + # but also for older Sony and Minolta lenses where all LensSpec bytes are 0. + 0x0115 => { + Name => 'LensSpecFeatures', + Condition => '$$self{Model} =~ /^(SLT-A(37|57|65|77)V?|Lunar|NEX-(F3|5N|7|VG20E))/', + Format => 'undef[2]', + ValueConv => 'join " ", unpack "H2H2", $val', + ValueConvInv => sub { + my @a = split(" ", shift); + return @a == 2 ? pack 'CC', hex($a[0]), hex($a[1]) : undef; + }, + PrintConv => \&PrintLensSpec, + PrintConvInv => 'Image::ExifTool::Sony::PrintInvLensSpec($val, $self, 1)', + }, + 0x0116 => { + Name => 'LensSpecFeatures', + Condition => '$$self{Model} !~ /^(SLT-A(37|57|65|77)V?|Lunar|NEX-(F3|5N|7|VG20E))/', + Format => 'undef[2]', + ValueConv => 'join " ", unpack "H2H2", $val', + ValueConvInv => sub { + my @a = split(" ", shift); + return @a == 2 ? pack 'CC', hex($a[0]), hex($a[1]) : undef; + }, + PrintConv => \&PrintLensSpec, + PrintConvInv => 'Image::ExifTool::Sony::PrintInvLensSpec($val, $self, 1)', + }, + +# 0x0122 => {Name=>'LensType',Format=>'int16u',Condition =>'$$self{Model}=~/^(SLT-A(37|57|65|77)V?|Lunar|NEX-(F3|5N|7|VG20E))/'}, +# 0x0123 => {Name=>'LensType',Format=>'int16u',Condition =>'$$self{Model}=~/^(SLT-A(58|99V?)|HV|ILCA-(68|77M2)|NEX-(3N|5R|5T|6|VG30E|VG900)|ILCE-(3000|3500|5000|5100|6000|7|7R|7S|7M2|QX1))/'}, +# 0x012d => {Name=>'LensType',Format=>'int16u',Condition =>'$$self{Model}=~/^(SLT-A(37|57|65|77)V?|Lunar|NEX-(F3|5N|7|VG20E))/'}, +# 0x012e => {Name=>'LensType',Format=>'int16u',Condition =>'$$self{Model}=~/^(SLT-A(58|99V?)|HV|ILCA-(68|77M2)|NEX-(3N|5R|5T|6|VG30E|VG900)|ILCE-(3000|3500|5000|5100|6000|7|7R|7S|7M2|QX1))/'}, + +# ShutterCount3 = ShutterCount for SLT-A58, ILCE, ILCA, NEX-3N +# ShutterCount-1 for SLT-A37,A57,A65,A77,A99, NEX-F3,5N,5R,5T,6,7, sometimes 0 +# ShutterCount-2 for NEX-VG, and often 0; "ShutterCount-2" also seen on a few A99V images +# The offset for ShutterCount3 changes with firmware version for the ILCE-7/7R/7S/7M2, so don't decode it for now: +# ILCE-7M2/7S: 0x01a0 (firmware 1.0x, 1.1x), 0x01b6 (firmware 1.20, 1.21, 2.00) +# ILCE-7/7R: 0x01aa (firmware 1.0x, 1.1x), 0x01c0 (firmware 1.20, 1.21, 2.00) +# Similarly for ILCE-6000 v2.00: 0x01aa --> 0x01c0: removed from 0x01aa + 0x01a0 => { + Name => 'ShutterCount3', + Format => 'int32u', + RawConv => '$val == 0 ? undef : $val', + Condition => '$$self{Model} =~ /^(ILCE-(5100|QX1)|ILCA-(68|77M2))/', + }, + 0x01aa => { + Name => 'ShutterCount3', + Format => 'int32u', + RawConv => '$val == 0 ? undef : $val', + Condition => '$$self{Model} =~ /^(SLT-A(58|99V?)|HV|NEX-(3N|5R|5T|6|VG900|VG30E)|ILCE-([35]000|3500))\b/', + }, + 0x01bd => { + Name => 'ShutterCount3', + Format => 'int32u', + RawConv => '$val == 0 ? undef : $val', + Condition => '$$self{Model} =~ /^(SLT-A(37|57|65|77)V?|Lunar|NEX-(F3|5N|7|VG20E))/', + }, + +# 0x0222 => {Name=>'LensType2',Format=>'int16u',Condition =>'$$self{Model}=~/^(ILCE-(5100|7S|7M2|QX1))/'}, +# 0x0224 => {Name=>'LensType', Format=>'int16u',Condition =>'$$self{Model}=~/^(ILCE-(5100|7S|7M2|QX1)|ILCA-(68|77M2))/'}, +# 0x0229 => {Name=>'LensType2',Format=>'int16u',Condition =>'$$self{Model}=~/^(NEX-(5R|5T|6|VG30E|VG900))/'}, +# 0x022b => {Name=>'LensType', Format=>'int16u',Condition =>'$$self{Model}=~/^(NEX-(5R|5T|6|VG30E|VG900))/'}, +# 0x022c => {Name=>'LensType2',Format=>'int16u',Condition =>'$$self{Model}=~/^(ILCE-(3000|3500|5000|6000|7|7R)|NEX-3N)\b/'}, +# 0x022e => {Name=>'LensType', Format=>'int16u',Condition =>'$$self{Model}=~/^(ILCE-(3000|3500|5000|6000|7|7R)|NEX-3N|SLT-A(58|99V?)|HV)\b/'}, + +# 0x0231 => {Name=>'LensSpecFeatures',Format=>'undef[2]',Condition=>'$$self{Model}=~/^(ILCE-(7S|7M2|5100|QX1)|ILCA-(68|77M2))/'}, +# 0x0238 => {Name=>'LensSpecFeatures',Format=>'undef[2]',Condition=>'$$self{Model}=~/^(NEX-(5R|5T|6|VG30E|VG900))/'}, +# 0x023b => {Name=>'LensSpecFeatures',Format=>'undef[2]',Condition=>'$$self{Model}=~/^(SLT-A(58|99V?)|HV|ILCE-(3000|3500|5000|6000|7|7R)|NEX-3N)\b/'}, + +# 0x023c => {Name=>'LensType2',Format=>'int16u',Condition =>'$$self{Model}=~/^(Lunar|NEX-(F3|5N|7|VG20E))/'}, +# 0x023e => {Name=>'LensType', Format=>'int16u',Condition =>'$$self{Model}=~/^(SLT-A(37|57|65|77)V?|Lunar|NEX-(F3|5N|7|VG20E)|ILCE-(5100|7S|7M2|QX1)|ILCA-(68|77M2))/'}, +# 0x0245 => {Name=>'LensType', Format=>'int16u',Condition =>'$$self{Model}=~/^(NEX-(5R|5T|6|VG30E|VG900))/'}, +# 0x0248 => {Name=>'LensType', Format=>'int16u',Condition =>'$$self{Model}=~/^(SLT-A(58|99V?)|HV|ILCE-(3000|3500|5000|6000|7|7R)|NEX-3N)\b/'}, +# 0x0249 => {Name=>'LensType', Format=>'int16u',Condition =>'$$self{Model}=~/^(ILCE-(5100|7S|7M2|QX1)|ILCA-(68|77M2))/'}, + +# 0x024a => {Name=>'LensSpecFeatures',Format=>'undef[2]',Condition=>'$$self{Model}=~/^(SLT-A(37|57|65|77)V?|Lunar|NEX-(F3|5N|7|VG20E))/'}, + +# 0x0250 => {Name=>'LensType', Format=>'int16u',Condition =>'$$self{Model}=~/^(NEX-(5R|5T|6|VG30E|VG900))/'}, +# 0x0253 => {Name=>'LensType', Format=>'int16u',Condition =>'$$self{Model}=~/^(SLT-A(58|99V?)|HV|ILCE-(3000|3500|5000|6000|7|7R|7S|7M2)|NEX-3N)\b/'}, +# 0x0257 => {Name=>'LensType', Format=>'int16u',Condition =>'$$self{Model}=~/^(SLT-A(37|57|65|77)V?|Lunar|NEX-(F3|5N|7|VG20E))/'}, +# 0x0262 => {Name=>'LensType', Format=>'int16u',Condition =>'$$self{Model}=~/^(SLT-A(37|57|65|77)V?|Lunar|NEX-(F3|5N|7|VG20E))/'}, + +# 0x031b => {%gain2010,Condition=>'$$self{Model}=~/^(DSC-RX100M3|ILCA-(68|77M2)|ILCE-(5100|7S|7M2|QX1))/'}, +# 0x032c => {%gain2010,Condition=>'$$self{Model}=~/^(NEX-(5R|5T|6|VG30E|VG900))/'}, +# 0x032f => {%gain2010,Condition=>'$$self{Model}=~/^(DSC-RX10|SLT-A(58|99V?)|HV|ILCE-(3000|3500|5000|6000|7|7R)|NEX-3N)\b/'}, +# 0x0350 => {%gain2010,Condition=>'$$self{Model}=~/^(SLT-A(37|57)|NEX-F3)/'}, +# 0x037b => {%gain2010,Condition=>'$$self{Model}=~/^(SLT-A(65|77)V?|Lunar|NEX-(7|VG20E))/'}, +); + +%Image::ExifTool::Sony::Tag9050b = ( #JR + PROCESS_PROC => \&ProcessEnciphered, + WRITE_PROC => \&WriteEnciphered, + CHECK_PROC => \&Image::ExifTool::CheckBinaryData, + FORMAT => 'int8u', + NOTES => q{ + Valid from July 2015 for ILCE-6300/6400/6500/7M3/7RM2/7RM3/7SM2/9, + ILCA-99M2. + }, + WRITABLE => 1, + FIRST_ENTRY => 0, + DATAMEMBER => [ 0x0105 ], + GROUPS => { 0 => 'MakerNotes', 2 => 'Image' }, + 0x0000 => { + Condition => '$$self{Model} =~ /^(ILCA-)/', + Name => 'SonyMaxAperture', # (at current focal length) + # seen values from 17 - 48 + ValueConv => '2 ** (($val/8 - 1.06) / 2)', + ValueConvInv => 'int((log($val) * 2 / log(2) + 1) * 8 + 0.5)', + PrintConv => 'sprintf("%.1f",$val)', + PrintConvInv => '$val', + }, + 0x0001 => { + Condition => '$$self{Model} =~ /^(ILCA-)/', + Name => 'SonyMinAperture', # (at current focal length) + # seen values from 80 - 95 + ValueConv => '2 ** (($val/8 - 1.06) / 2)', + ValueConvInv => 'int((log($val) * 2 / log(2) + 1) * 8 + 0.5)', + PrintConv => 'sprintf("%.0f",$val)', + PrintConvInv => '$val', + }, + # 0x0026 - int16u[3]: all 0's when Silent Shooting / Electronic Shutter + 0x002c => { + Name => 'Shutter', + Condition => '$$self{Model} !~ /^(ILCE-6400)/', + PrintConv => { + 0 => 'Silent / Electronic', + 56 => 'Mechanical', + }, + }, + 0x0039 => { + Name => 'FlashStatus', + RawConv => '$$self{FlashFired} = $val', + PrintConv => { + 0 => 'No Flash present', + 2 => 'Flash Inhibited', # seen for ILCE-7/7R continuous, panorama, HDR mode + 64 => 'Built-in Flash present', + 65 => 'Built-in Flash Fired', + 66 => 'Built-in Flash Inhibited', # seen for panorama, HDR, burst mode + 128 => 'External Flash present', # seen for NEX-5N/5T + 129 => 'External Flash Fired', # seen for SLT-A99V, ILCE-7R, NEX-5N/5R + }, + }, + 0x003a => { + Name => 'ShutterCount', + # or "ShutterCount"? : number of shutter actuations, does not increase during Silent Shooting, + # at least for ILCE-7RM2 + Format => 'int32u', + Notes => 'total number of image exposures made by the camera', + RawConv => '$val & 0x00ffffff', + }, + 0x0046 => { # appr. same value as Exif ExposureTime, but longer in HDR-modes + Name => 'SonyExposureTime', + Format => 'int16u', + ValueConv => '$val ? 2 ** (16 - $val/256) : 0', + ValueConvInv => '$val ? int((16 - log($val) / log(2)) * 256 + 0.5) : 0', + PrintConv => '$val ? Image::ExifTool::Exif::PrintExposureTime($val) : "Bulb"', + PrintConvInv => 'lc($val) eq "bulb" ? 0 : Image::ExifTool::Exif::ConvertFraction($val)', + }, + 0x0048 => { + Name => 'SonyFNumber', + Format => 'int16u', + ValueConv => '2 ** (($val/256 - 16) / 2)', + ValueConvInv => '(log($val)*2/log(2)+16)*256', + PrintConv => 'sprintf("%.1f",$val)', + PrintConvInv => '$val', + }, + 0x004b => { + Name => 'ReleaseMode2', + %releaseMode2, + }, + 0x0050 => { + Name => 'ShutterCount2', + Condition => '(($$self{FlashFired} & 0x01) != 1) and ($$self{Model} =~ /^(ILCE-6400)/)', + Format => 'int32u', + RawConv => '$val & 0x00ffffff', + }, + 0x0052 => { + Name => 'ShutterCount2', + Condition => '(($$self{FlashFired} & 0x01) != 1) and ($$self{Model} =~ /^(ILCE-(7M3|7RM3))/)', + Format => 'int32u', + RawConv => '$val & 0x00ffffff', + }, +# 0x0058 - 0x0067: A-Mount: 16 values, only non-zero data for lenses giving "A-mount (3)" in 0x0104 below. +# e.g for SAL70400G2: 9 5 5 64 69 74 79 84 89 94 98 104 255 105 89 80 +# where 9 means 9 focal lengths: 64 ... 104, +# corresponding to 70-400mm via FocalLength = 4.375*2**($val/16) +# 0x0058, 0x0061: E-Mount: ShutterCount and dateTime + 0x0058 => { # appears not valid when flash is used ... not for ILCA-99M2 + Name => 'ShutterCount2', + Condition => '(($$self{FlashFired} & 0x01) != 1) and ($$self{Model} !~ /^(ILCA-99M2|ILCE-(6400|7M3|7RM3))/)', + Format => 'int32u', + RawConv => '$val & 0x00ffffff', + }, + 0x0061 => { # only minutes-seconds, not for ILCA-99M2, ILCE-9 + Name => 'SonyTimeMinSec', + Condition => '$$self{Model} !~ /^(ILCA-99M2|ILCE-(6400|7M3|7RM3|9))/', + Format => 'undef[2]', + ValueConv => q{ + my @v = unpack('C*', $val); + return sprintf("%.2d:%.2d", @v) + }, + }, + 0x006b => { + Name => 'ReleaseMode2', + Condition => '$$self{Model} =~ /^(ILCE-6400)/', + %releaseMode2, + }, + 0x006d => { + Name => 'ReleaseMode2', + Condition => '$$self{Model} =~ /^(ILCE-(7M3|7RM3))/', + %releaseMode2, + }, + 0x0073 => { + Name => 'ReleaseMode2', + Condition => '$$self{Model} !~ /^(ILCE-(6400|7M3|7RM3))/', + %releaseMode2, + }, + 0x0088 => { + Name => 'InternalSerialNumber', #(NC) + Format => 'int8u[6]', + PrintConv => 'unpack "H*", pack "C*", split " ", $val', + }, + +##### same offsets for lens info tags + + # 0x0104 - same as 0x0105, but has value 3 for 50mm F1.4 ZA, DT 18-135mm and for 70-400mm G II: meaning ?? + 0x0105 => { + Name => 'LensMount', + DataMember => 'LensMount', + RawConv => '$$self{LensMount} = $val', + PrintConv => { + 0 => 'Unknown', + 1 => 'A-mount', + 2 => 'E-mount', + }, + }, + 0x0106 => { + Name => 'LensFormat', + PrintConv => { + 0 => 'Unknown', + 1 => 'APS-C', + 2 => 'Full-frame', + }, + }, + 0x0107 => { + Name => 'LensType2', + Condition => '$$self{LensMount} == 2', + Format => 'int16u', + SeparateTable => 'LensType2', + PrintConv => \%sonyLensTypes2, + }, + 0x0109 => { + Name => 'LensType', + Condition => '$$self{LensMount} == 1', + Priority => 0, #PH (just to be safe) + Format => 'int16u', #PH + Notes => 'SLT models, and NEX with A-mount lenses', + SeparateTable => 1, + # has a value of 0 for E-mount lenses (values 0x80xx) + ValueConvInv => '($val & 0xff00) == 0x8000 ? 0 : int($val)', + PrintConv => \%sonyLensTypes, + }, + 0x010b => { + Name => 'DistortionCorrParamsPresent', + PrintConv => { 0 => 'No', 1 => 'Yes'}, + }, + # 0x0116 and 0x0117: + # give the same info as the first and last bytes of LensSpec, + # but also for older Sony and Minolta lenses where all LensSpec bytes are 0. + 0x0116 => { + Name => 'LensSpecFeatures', + Format => 'undef[2]', + ValueConv => 'join " ", unpack "H2H2", $val', + ValueConvInv => sub { + my @a = split(" ", shift); + return @a == 2 ? pack 'CC', hex($a[0]), hex($a[1]) : undef; + }, + PrintConv => \&PrintLensSpec, + PrintConvInv => 'Image::ExifTool::Sony::PrintInvLensSpec($val, $self, 1)', + }, +# +# tags becoming model- and/or firmware-dependent from here. +# + 0x019f => { + Name => 'ShutterCount3', + Condition => '$$self{Model} =~ /^(ILCE-(6400|7M3|7RM3|9))/', + Format => 'int32u', + RawConv => '$val == 0 ? undef : $val', + }, + 0x01cb => { + Name => 'ShutterCount3', + Condition => '$$self{Model} =~ /^(ILCE-(7RM2|7SM2))/', + Format => 'int32u', + RawConv => '$val == 0 ? undef : $val', + }, + 0x01cd => { + Name => 'ShutterCount3', + Condition => '$$self{Model} =~ /^(ILCE-(6300|6500)|ILCA-99M2)/', + Format => 'int32u', + RawConv => '$val == 0 ? undef : $val', + }, +# the following tags are commented out because they can cause problems for the +# Composite LensID of non-electronic lenses (even if Priority is set to 0) +# 0x020d => { +# Name=>'LensType2', +# Condition => '$$self{Model} =~ /^(ILCE-(7RM2|7SM2))/', +# Format=>'int16u', +# }, +# 0x020f => [{ +# Name=>'LensType', +# Condition => '$$self{Model} =~ /^(ILCE-(7RM2|7SM2))/', +# Format=>'int16u', +# },{ +# Name=>'LensType2', +# Condition => '$$self{Model} =~ /^(ILCE-(6300|6500)|ILCA-99M2)/', +# Format=>'int16u', +# }], +# 0x0211 => { +# Name=>'LensType', +# Condition => '$$self{Model} =~ /^(ILCE-(6300|6500)|ILCA-99M2)/', +# Format=>'int16u', +# }, + 0x021c => { + Name => 'LensSpecFeatures', + Condition => '$$self{Model} =~ /^(ILCE-(7RM2|7SM2))/', + Priority => 0, + Format => 'undef[2]', + ValueConv => 'join " ", unpack "H2H2", $val', + ValueConvInv => sub { + my @a = split(" ", shift); + return @a == 2 ? pack 'CC', hex($a[0]), hex($a[1]) : undef; + }, + PrintConv => \&PrintLensSpec, + PrintConvInv => 'Image::ExifTool::Sony::PrintInvLensSpec($val, $self, 1)', + }, + 0x021e => { + Name => 'LensSpecFeatures', + Condition => '$$self{Model} =~ /^(ILCE-(6300|6500)|ILCA-99M2)/', + Priority => 0, + Format => 'undef[2]', + ValueConv => 'join " ", unpack "H2H2", $val', + ValueConvInv => sub { + my @a = split(" ", shift); + return @a == 2 ? pack 'CC', hex($a[0]), hex($a[1]) : undef; + }, + PrintConv => \&PrintLensSpec, + PrintConvInv => 'Image::ExifTool::Sony::PrintInvLensSpec($val, $self, 1)', + }, +); + +%Image::ExifTool::Sony::Tag9400a = ( #JR + PROCESS_PROC => \&ProcessEnciphered, + WRITE_PROC => \&WriteEnciphered, + CHECK_PROC => \&Image::ExifTool::CheckBinaryData, + FORMAT => 'int8u', + NOTES => 'Valid for many DSC, NEX and SLT models', + WRITABLE => 1, + FIRST_ENTRY => 0, + GROUPS => { 0 => 'MakerNotes', 2 => 'Image' }, + 0x0008 => { %sequenceImageNumber }, #PH + 0x000c => { %sequenceFileNumber }, #PH + 0x0010 => { %releaseMode2 }, + 0x0012 => { + Name => 'DigitalZoom', + Condition => '$$self{Model} !~ /^(SLT-(A65|A77)V?|NEX-(5N|7|VG20E)|Lunar|DSC-(HX10V|HX20V|HX200V|TX20|TX55|TX300V|WX30|WX70))\b/', + PrintConv => { + 0 => 'No', + 1 => 'Yes', + }, + }, +# 0x0013 - Flash fired 0=no, 1=yes +# 0x0014 - related to flash / RedEyeReduction ? +# 0x0015 - CameraType: 1=HDR, 2=DSC, 3=SLT/NEX + 0x001a => { #PH + Name => 'ShotNumberSincePowerUp', + Format => 'int32u', + }, +# 0x001e - increments by 4 or 6 or 8 each shutter release press since power up +# 0x001f - 0=most pictures, 1='Self-timer/Self-portrait', 2='Self-portrait (2 people)', +# 3='Continuous Self-timer', 26='Sweep Panorama' (PH, RX100) +# 0x0021 - maybe related to Image Stabilization or Smile Shutter ? + 0x0022 => { + Name => 'SequenceLength', + PrintConv => { + 0 => 'Continuous', # (RX100 too) + 1 => '1 shot', + 2 => '2 shots', # (Background defocus, 3D Image) + 3 => '3 shots', # (HDR, WB Bracketing) (RX100, also continuous bracket) + 4 => '4 shots', # seen for DSC-WX300 in Superior-Auto Anti-Motion-Blur + 5 => '5 shots', # (PH, RX100) + 6 => '6 shots', # (Multi Frame NR, Anti Motion blur, Hand-held Twilight) + 10 => '10 shots', # (HX9V Burst) + 100 => 'Continuous - iSweep Panorama', # (HX9V) + 200 => 'Continuous - Sweep Panorama', + }, + }, +# 0x0027 - 1=single exposure, 2=multi-exposure (eg. pano,some superior auto) (PH, RX100) + 0x0028 => { + Name => 'CameraOrientation', # (also RX100 - PH) + PrintConv => { + 1 => 'Horizontal (normal)', + 3 => 'Rotate 180', + 6 => 'Rotate 90 CW', + 8 => 'Rotate 270 CW', + }, + }, + 0x0029 => { + Name => 'Quality2', # (also RX100 - PH) + PrintConv => { + 0 => 'JPEG', + 1 => 'RAW', + 2 => 'RAW + JPEG', + 3 => 'JPEG + MPO', # 3D images + }, + }, +# 0x002b - FacesDetected_OK 0=no, 1=yes appears valid for SLT, but not for NEX and DSC-HX9V +# 0x0030 - long exposure noise reduction used 0=no, 1=yes (PH, RX100) +# 0x0031 - smile shutter used 0=no, 1=yes (PH, RX100) +# 0x0033 - 0 for DSC-HX9V, 8 for SLT, NEX +# 0x0034 and 0x0038 - different offset for HX9V and SLT/NEX, but similar numbers, non-zero when flash fired + 0x0044 => { + Condition => '$$self{Model} =~ /^(SLT-|HV|NEX-|Lunar|DSC-RX|Stellar)/', # not valid for most other DSC and HDR models + Name => 'SonyImageHeight', + Format => 'int16u', + PrintConv => '$val > 0 ? 8*$val : "n.a."', + }, + 0x0052 => { + Name => 'ModelReleaseYear', + Condition => '$$self{Model} =~ /^(SLT-|HV|NEX-|Lunar|DSC-RX|Stellar)/', # not valid for most other DSC and HDR models + Format => 'int8u', + PrintConv => 'sprintf("20%.2d", $val)', + }, +); + +%Image::ExifTool::Sony::Tag9400b = ( #JR + PROCESS_PROC => \&ProcessEnciphered, + WRITE_PROC => \&WriteEnciphered, + CHECK_PROC => \&Image::ExifTool::CheckBinaryData, + FORMAT => 'int8u', + NOTES => q{ + Valid for NEX-3N, ILCE-3000/3500, SLT-A58, DSC-WX60, DSC-WX300, DSC-RX100M2, + DSC-HX50V, DSC-QX10/QX100. + }, + WRITABLE => 1, + FIRST_ENTRY => 0, + GROUPS => { 0 => 'MakerNotes', 2 => 'Image' }, + 0x0008 => { %sequenceImageNumber }, #PH + 0x000c => { %sequenceFileNumber }, #PH + 0x0010 => { %releaseMode2 }, + 0x0012 => { + Name => 'DigitalZoom', + PrintConv => { + 0 => 'No', + 1 => 'Yes', + }, + }, +# 0x0013 - Flash fired 0=no, 1=yes +# 0x0014 - related to flash / RedEyeReduction ? +# 0x0015 - CameraType: 1=HDR, 2=DSC, 3=SLT/NEX + 0x0016 => { #PH + Name => 'ShotNumberSincePowerUp', + Format => 'int32u', + }, + 0x001e => { + Name => 'SequenceLength', + PrintConv => { + 0 => 'Continuous', + 1 => '1 shot', + 2 => '2 shots', + 3 => '3 shots', + 4 => '4 shots', + 5 => '5 shots', + 6 => '6 shots', + 10 => '10 shots', + 100 => 'Continuous - iSweep Panorama', + 200 => 'Continuous - Sweep Panorama', + }, + }, + 0x0024 => { + Name => 'CameraOrientation', + PrintConv => { + 1 => 'Horizontal (normal)', + 3 => 'Rotate 180', + 6 => 'Rotate 90 CW', + 8 => 'Rotate 270 CW', + }, + }, + 0x0025 => { + Name => 'Quality2', + PrintConv => { + 0 => 'JPEG', + 1 => 'RAW', + 2 => 'RAW + JPEG', + 3 => 'JPEG + MPO', # 3D images + }, + }, +# 0x0027 - FacesDetected_OK 0=no, 1=yes +# 0x002c - long exposure noise reduction used 0=no, 1=yes (PH, RX100) + 0x003f => { + Name => 'SonyImageHeight', + Format => 'int16u', + PrintConv => '$val > 0 ? 8*$val : "n.a."', + }, + 0x0046 => { # but Panorama images give incorrect result + Name => 'ModelReleaseYear', + Format => 'int8u', + PrintConv => 'sprintf("20%.2d", $val)', + }, +); + +%Image::ExifTool::Sony::Tag9400c = ( #JR + PROCESS_PROC => \&ProcessEnciphered, + WRITE_PROC => \&WriteEnciphered, + CHECK_PROC => \&Image::ExifTool::CheckBinaryData, + FORMAT => 'int8u', + WRITABLE => 1, + NOTES => q{ + Valid for DSC-HX60V/HX80/HX90V/HX99/HX350/HX400V/QX30/RX0/RX1RM2/RX10/ + RX10M2/RX10M3/RX10M4/RX100M3/RX100M4/RX100M5/RX100M5A/RX100M6/WX220/WX350/ + WX500, ILCE-7/7R/7S/7M2/7M3/7RM2/7RM3/7SM2/9/5000/5100/6000/6300/6400/6500/ + QX1, ILCA-68/77M2/99M2. + }, + FIRST_ENTRY => 0, + GROUPS => { 0 => 'MakerNotes', 2 => 'Image' }, + 0x0009 => { %releaseMode2 }, + 0x000a => [{ + Condition => '$$self{Model} =~ /^(ILCE-(6400|7M3|7RM3|9)|DSC-(RX10M4|RX100M6|RX100M5A|HX99))\b/', + Name => 'ShotNumberSincePowerUp', + Format => 'int8u', + },{ + Name => 'ShotNumberSincePowerUp', + Format => 'int32u', + }], + 0x0012 => { %sequenceImageNumber }, + 0x0016 => { + Name => 'SequenceLength', + PrintConv => { + 0 => 'Continuous', + 1 => '1 shot', + 2 => '2 shots', + 3 => '3 shots', + 4 => '4 shots', + 5 => '5 shots', + 6 => '6 shots', + 9 => '9 shots', # ILCE-7RM2 9-shot bracketing + 10 => '10 shots', + 12 => '12 shots', # ILCA-77M2 12-shot MFNR-mode + 100 => 'Continuous - iSweep Panorama', + 200 => 'Continuous - Sweep Panorama', + }, + }, + 0x001a => { %sequenceFileNumber }, + 0x001e => { + Name => 'SequenceLength', + PrintConv => { + 0 => 'Continuous', + 1 => '1 file', + 2 => '2 files', + 3 => '3 files', + 5 => '5 files', + 9 => '9 files', # ILCE-7RM2 9-shot bracketing + 10 => '10 files', # seen for DSC-WX500 with burst of 10 shots + }, + }, + 0x0029 => { + Name => 'CameraOrientation', + PrintConv => { + 1 => 'Horizontal (normal)', + 3 => 'Rotate 180', + 6 => 'Rotate 90 CW', + 8 => 'Rotate 270 CW', + }, + }, + 0x002a => { + Name => 'Quality2', + PrintConv => { + 0 => 'JPEG', + 1 => 'RAW', + 2 => 'RAW + JPEG', + 3 => 'JPEG + MPO', # 3D images + }, + }, + 0x0047 => { + Name => 'SonyImageHeight', + Format => 'int16u', + PrintConv => '$val > 0 ? 8*$val : "n.a."', + }, + 0x0053 => { + Name => 'ModelReleaseYear', + Format => 'int8u', + PrintConv => 'sprintf("20%.2d", $val)', + }, +); + +%Image::ExifTool::Sony::Tag9401 = ( # JR + PROCESS_PROC => \&ProcessEnciphered, + WRITE_PROC => \&WriteEnciphered, + CHECK_PROC => \&Image::ExifTool::CheckBinaryData, + FORMAT => 'int8u', + WRITABLE => 1, + FIRST_ENTRY => 0, + GROUPS => { 0 => 'MakerNotes', 2 => 'Image' }, + DATAMEMBER => [ 0 ], + IS_SUBDIR => [ 0x059d, 0x0634, 0x0636, 0x064c, 0x0653, 0x0678, 0x06b8, 0x06de, 0x06e7 ], + 0x0000 => { Name => 'Ver9401', Hidden => 1, RawConv => '$$self{Ver9401} = $val; $$self{OPTIONS}{Unknown}<2 ? undef : $val' }, + + 0x059d => { Name => 'ISOInfo', Condition => '$$self{Ver9401} =~ /^(144|146)/', Format => 'int8u[5]', SubDirectory => { TagTable => 'Image::ExifTool::Sony::ISOInfo' } }, + 0x0634 => { Name => 'ISOInfo', Condition => '$$self{Ver9401} == 68', Format => 'int8u[5]', SubDirectory => { TagTable => 'Image::ExifTool::Sony::ISOInfo' } }, + 0x0636 => { Name => 'ISOInfo', Condition => '$$self{Ver9401} =~ /^(73|74)/', Format => 'int8u[5]', SubDirectory => { TagTable => 'Image::ExifTool::Sony::ISOInfo' } }, + 0x064c => { Name => 'ISOInfo', Condition => '$$self{Ver9401} == 78', Format => 'int8u[5]', SubDirectory => { TagTable => 'Image::ExifTool::Sony::ISOInfo' } }, + 0x0653 => { Name => 'ISOInfo', Condition => '$$self{Ver9401} == 90', Format => 'int8u[5]', SubDirectory => { TagTable => 'Image::ExifTool::Sony::ISOInfo' } }, + 0x0678 => { Name => 'ISOInfo', Condition => '$$self{Ver9401} =~ /^(93|94)/', Format => 'int8u[5]', SubDirectory => { TagTable => 'Image::ExifTool::Sony::ISOInfo' } }, + 0x06b8 => { Name => 'ISOInfo', Condition => '$$self{Ver9401} =~ /^(100|103)/', Format => 'int8u[5]', SubDirectory => { TagTable => 'Image::ExifTool::Sony::ISOInfo' } }, + 0x06de => { Name => 'ISOInfo', Condition => '$$self{Ver9401} =~ /^(124|125)/', Format => 'int8u[5]', SubDirectory => { TagTable => 'Image::ExifTool::Sony::ISOInfo' } }, + 0x06e7 => { Name => 'ISOInfo', Condition => '$$self{Ver9401} =~ /^(127|128|130)/', Format => 'int8u[5]', SubDirectory => { TagTable => 'Image::ExifTool::Sony::ISOInfo' } }, +); + +%Image::ExifTool::Sony::ISOInfo = ( # JR + FORMAT => 'int8u', + %binaryDataAttrs, + GROUPS => { 0 => 'MakerNotes', 2 => 'Camera' }, + 0x0000 => { Name => 'ISOSetting', ValueConv => \%isoSetting2010 }, + 0x0002 => { Name => 'ISOAutoMin', ValueConv => \%isoSetting2010 }, + 0x0004 => { Name => 'ISOAutoMax', ValueConv => \%isoSetting2010 }, +); + +# PH (RX100) +%Image::ExifTool::Sony::Tag9402 = ( + PROCESS_PROC => \&ProcessEnciphered, + WRITE_PROC => \&WriteEnciphered, + CHECK_PROC => \&Image::ExifTool::CheckBinaryData, + FORMAT => 'int8u', + WRITABLE => 1, + FIRST_ENTRY => 0, + GROUPS => { 0 => 'MakerNotes', 2 => 'Image' }, + DATAMEMBER => [ 0x02 ], + PRIORITY => 0, + 0x02 => { + Name => 'TempTest1', + DataMember => 'TempTest1', + Hidden => 1, + RawConv => '$$self{TempTest1}=$val; $$self{OPTIONS}{Unknown}<2 ? undef : $val', + }, + 0x04 => { + Name => 'AmbientTemperature', + # this (and many other values) are only valid if 0x02 is 255 (why?) + Condition => '$$self{TempTest1} == 255', + Format => 'int8s', # (verified for negative temperature) + PrintConv => '"$val C"', + PrintConvInv => '$val=~s/ ?C//; $val', + }, + 0x16 => { #JR + Name => 'FocusMode', + Mask => 0x7f, # (often +128, not sure what upper bit is for) + PrintConv => { + 0 => 'Manual', + 2 => 'AF-S', + 3 => 'AF-C', + 4 => 'AF-A', # seen in ILCE-6000 images + 6 => 'DMF', + # 7 => 'AF-D', # not for DSC, NEX, ILCE ... + }, + }, + 0x17 => { + Name => 'AFAreaMode', + PrintConv => { + 0 => 'Multi', # newer DSC/ILC use name 'Wide' + 1 => 'Center', + 2 => 'Spot', #(NC) seen for DSC-WX300 + 3 => 'Flexible Spot', + 10 => 'Selective (for Miniature effect)', # seen for DSC-HX30V,TX30,WX60,WX100 + 11 => 'Zone', #JR (ILCE-7 series) + 12 => 'Expanded Flexible Spot', #JR (HX90V, ILCE-7 series) + 14 => 'Tracking', + 15 => 'Face Tracking', + 255 => 'Manual', + }, + }, + # 0x24, 0x26: factor 10 for NEX and ILCE, factor 100 for DSC + # 0x24, 0x26, 0x28, 0x2a: inconsistent for A-mount lenses on NEX/ILCE: some correct, some 0, some incorrect ... + # 0x28 - not valid for DSC-[HTW]X models, or DSC-RX100 +# 0x24 => { # same values as Exif FocalLength (but have seen FocalLength for previous shot, ref IB, RX100M5) +# Name => 'FocalLength', +# Format => 'int16u', +# RawConv => '$val || undef', +# ValueConv => '$val / ($$self{Model}=~/DSC/ ? 100 : 10)', +# ValueConvInv => '$val * ($$self{Model}=~/DSC/ ? 100 : 10)', +# PrintConv => 'sprintf("%.1f mm",$val)', +# PrintConvInv => '$val =~ s/ ?mm//; $val', +# }, +# 0x26 => { # usually identical to 0x24 or 0 +# Name => 'FocalLength', +# Format => 'int16u', +# ValueConv => '$val / ($$self{Model}=~/DSC/ ? 100 : 10)', +# ValueConvInv => '$val * ($$self{Model}=~/DSC/ ? 100 : 10)', +# PrintConv => 'sprintf("%.1f mm",$val)', +# PrintConvInv => '$val =~ s/ ?mm//; $val', +# }, +# 0x28 => { # values slightly different from Exif FocalLength +# Name => 'FocalLength2', +# Format => 'int16u', +# RawConv => '$val || undef', +# ValueConv => '$val / 10', +# ValueConvInv => '$val * 10', +# PrintConv => 'sprintf("%.1f mm",$val)', +# PrintConvInv => '$val =~ s/ ?mm//; $val', +# }, +# 0x2a => { # usually identical to 0x28 or 0 +# Name => 'FocalLength2', +# Format => 'int16u', +# ValueConv => '$val / 10', +# ValueConvInv => '$val * 10', +# PrintConv => 'sprintf("%.1f mm",$val)', +# PrintConvInv => '$val =~ s/ ?mm//; $val', +# }, +# 0x002c => { +# # seen values from 80 - 255 (= infinity) -- see Composite:FocusDistance2 below +# Name => 'FocusPosition2', +# Condition => '$$self{Model} !~ /^(DSC-|Stellar)/', +# }, + 0x002d => { # usually same as 0x002c, but some differences + # seen values from 80 - 255 (= infinity) -- see Composite:FocusDistance2 below + Name => 'FocusPosition2', + Condition => '$$self{Model} !~ /^(DSC-|Stellar)/', + }, + # 0x8a - int32u: some sort of accumulated time or something since power up + # (doesn't increment during continuous shooting and at some other times) +); + +# PH (RX100) +%Image::ExifTool::Sony::Tag9403 = ( + PROCESS_PROC => \&ProcessEnciphered, + WRITE_PROC => \&WriteEnciphered, + CHECK_PROC => \&Image::ExifTool::CheckBinaryData, + FORMAT => 'int8u', + WRITABLE => 1, + FIRST_ENTRY => 0, + GROUPS => { 0 => 'MakerNotes', 2 => 'Image' }, + DATAMEMBER => [ 0x04 ], + 0x04 => { + # seen values 0,2,3,18,32,49,50,83,148 + # CameraTemperature is valid for all values except 0,148 + Name => 'TempTest2', + DataMember => 'TempTest2', + Hidden => 1, + RawConv => '$$self{TempTest2}=$val; $$self{OPTIONS}{Unknown}<2 ? undef : $val', + }, + 0x05 => { + Name => 'CameraTemperature', # (maybe SensorTemperature? - heats up when taking movies) + Condition => '$$self{TempTest2} and $$self{TempTest2} < 100', + Format => 'int8s', # have seen as low as -1 for AmbientTemperature of -18 + PrintConv => '"$val C"', + PrintConvInv => '$val=~s/ ?C//; $val', + }, + # 0x0f - same as 0x05 + # 0x18 - maybe another temperature? +); + +# Tag9404 (ref JR) +%Image::ExifTool::Sony::Tag9404a = ( + PROCESS_PROC => \&ProcessEnciphered, + WRITE_PROC => \&WriteEnciphered, + CHECK_PROC => \&Image::ExifTool::CheckBinaryData, + FORMAT => 'int8u', + WRITABLE => 1, + FIRST_ENTRY => 0, + GROUPS => { 0 => 'MakerNotes', 2 => 'Image' }, + 0x000b => { %exposureProgram2010 }, + 0x000d => { Name => 'IntelligentAuto', PrintConv => { 0 => 'Off', 1 => 'On'} }, + 0x0019 => { + Name => 'LensZoomPosition', + Format => 'int16u', + Condition => '$$self{Model} !~ /^SLT-/', + PrintConv => 'sprintf("%.0f%%",$val/10.24)', + PrintConvInv => '$val=~s/ ?%$//; $val * 10.24', + }, +); + +# Tag9404 (ref JR) +%Image::ExifTool::Sony::Tag9404b= ( + PROCESS_PROC => \&ProcessEnciphered, + WRITE_PROC => \&WriteEnciphered, + CHECK_PROC => \&Image::ExifTool::CheckBinaryData, + FORMAT => 'int8u', + WRITABLE => 1, + FIRST_ENTRY => 0, + GROUPS => { 0 => 'MakerNotes', 2 => 'Image' }, + 0x000c => { %exposureProgram2010 }, + 0x000e => { Name => 'IntelligentAuto', PrintConv => { 0 => 'Off', 1 => 'On'} }, + 0x001e => { + Name => 'LensZoomPosition', + Format => 'int16u', + Condition => '$$self{Model} !~ /^(SLT-|HV|ILCA-)/', + PrintConv => 'sprintf("%.0f%%",$val/10.24)', + PrintConvInv => '$val=~s/ ?%$//; $val * 10.24', + }, + 0x0020 => { + # seen values from 80 - 255 (= infinity) -- see Composite:FocusDistance2 below + Name => 'FocusPosition2', + Condition => '$$self{Model} =~ /^(SLT-|HV|ILCA-)/', + }, +); + +# Tag9404 (ref JR) +%Image::ExifTool::Sony::Tag9404c= ( + PROCESS_PROC => \&ProcessEnciphered, + WRITE_PROC => \&WriteEnciphered, + CHECK_PROC => \&Image::ExifTool::CheckBinaryData, + FORMAT => 'int8u', + WRITABLE => 1, + FIRST_ENTRY => 0, + GROUPS => { 0 => 'MakerNotes', 2 => 'Image' }, + 0x000b => { %exposureProgram2010 }, + 0x000d => { Name => 'IntelligentAuto', PrintConv => { 0 => 'Off', 1 => 'On'} }, +); + +# Tag9405 (ref JR) +%Image::ExifTool::Sony::Tag9405a = ( + PROCESS_PROC => \&ProcessEnciphered, + WRITE_PROC => \&WriteEnciphered, + CHECK_PROC => \&Image::ExifTool::CheckBinaryData, + FORMAT => 'int8u', + WRITABLE => 1, + FIRST_ENTRY => 0, + PRIORITY => 0, + DATAMEMBER => [ 0x0604 ], + GROUPS => { 0 => 'MakerNotes', 2 => 'Image' }, + NOTES => 'Valid for SLT, NEX, ILCE-3000/3500 and several DSC models.', + 0x0600 => { + Name => 'DistortionCorrParamsPresent', + Condition => '$$self{Model} !~ /^(DSC-|Stellar)/', + PrintConv => { 0 => 'No', 1 => 'Yes'}, + }, + 0x0601 => { + Name => 'DistortionCorrection', + PrintConv => { + 0 => 'None', + 1 => 'Applied', + }, + }, + # 0x0602 - same as 0x0604, but has value 3 for 50mm F1.4 ZA, DT 18-135mm and for 70-400mm G II: meaning ?? + 0x0603 => { + Name => 'LensFormat', + Condition => '$$self{Model} !~ /^(DSC-|Stellar)/', + PrintConv => { + 0 => 'Unknown', + 1 => 'APS-C', + 2 => 'Full-frame', + }, + }, + 0x0604 => { + Name => 'LensMount', + DataMember => 'LensMount', + RawConv => '$$self{LensMount} = $val; $$self{Model} =~ /^(DSC-|Stellar)/ ? undef : $val', + PrintConv => { + 0 => 'Unknown', + 1 => 'A-mount', + 2 => 'E-mount', + # 6 - seen for A58 panorama image + }, + }, + 0x0605 => { + Name => 'LensType2', + Condition => '$$self{LensMount} == 2', + Format => 'int16u', + Notes => 'E-mount lenses', + SeparateTable => 'LensType2', + PrintConv => \%sonyLensTypes2, + }, + 0x0608 => { + Name => 'LensType', + Condition => '$$self{LensMount} == 1', + Format => 'int16u', + Notes => 'A-mount lenses on SLT and NEX', + SeparateTable => 1, + PrintConv => \%sonyLensTypes, + }, + 0x064a => { + Name => 'VignettingCorrParams', + Condition => '$$self{Model} !~ /^(DSC-|Stellar)/', + Format => 'int16s[16]', + }, + 0x066a => { + Name => 'ChromaticAberrationCorrParams', + Condition => '$$self{Model} !~ /^(DSC-|Stellar)/', + Format => 'int16s[32]', + }, + 0x06ca => { + Name => 'DistortionCorrParams', + Condition => '$$self{Model} !~ /^(DSC-|Stellar)/', + Format => 'int16s[16]', + }, +); + +# Tag9405b (ref JR) +%Image::ExifTool::Sony::Tag9405b = ( + PROCESS_PROC => \&ProcessEnciphered, + WRITE_PROC => \&WriteEnciphered, + CHECK_PROC => \&Image::ExifTool::CheckBinaryData, + FORMAT => 'int8u', + WRITABLE => 1, + FIRST_ENTRY => 0, + PRIORITY => 0, + DATAMEMBER => [ 0x005e ], + GROUPS => { 0 => 'MakerNotes', 2 => 'Image' }, + NOTES => q{ + Valid for DSC-HX60V/HX80/HX90V/HX99/HX350/HX400V/QX30/RX0/RX10/RX10M2/ + RX10M3/RX10M4/RX100M3/RX100M4/RX100M5/RX100M5A/RX100M6/WX220/WX350, ILCE-7/ + 7M2/7M3/7R/7RM2/7S/7SM2/9/5000/5100/6000/6300/6500/QX1, ILCA-68/77M2/99M2. + }, + 0x0004 => { + Name => 'SonyISO', + Format => 'int16u', + ValueConv => '100 * 2**(16 - $val/256)', + ValueConvInv => '256 * (16 - log($val/100)/log(2))', + PrintConv => 'sprintf("%.0f",$val)', + PrintConvInv => '$val', + }, + 0x0006 => { + Name => 'BaseISO', + Format => 'int16u', + ValueConv => '100 * 2**(16 - $val/256)', + ValueConvInv => '256 * (16 - log($val/100)/log(2))', + PrintConv => 'sprintf("%.0f",$val)', + PrintConvInv => '$val', + }, + 0x000a => { %gain2010 }, + 0x000e => { # appr. same value as Exif ExposureTime, but shorter in HDR-modes + Name => 'SonyExposureTime2', + Format => 'int16u', + ValueConv => '$val ? 2 ** (16 - $val/256) : 0', + ValueConvInv => '$val ? int((16 - log($val) / log(2)) * 256 + 0.5) : 0', + PrintConv => '$val ? Image::ExifTool::Exif::PrintExposureTime($val) : "Bulb"', + PrintConvInv => 'lc($val) eq "bulb" ? 0 : Image::ExifTool::Exif::ConvertFraction($val)', + }, + 0x0010 => { + Name => 'ExposureTime', + Format => 'rational32u', + PrintConv => '$val ? Image::ExifTool::Exif::PrintExposureTime($val) : "Bulb"', # (Bulb NC) + PrintConvInv => 'lc($val) eq "bulb" ? 0 : $val', + }, + 0x0014 => { # but often odd results for DSC models: exclude + # also often deviating results for Sony FE 90mm F2.8 Macro G OSS ... + Name => 'SonyFNumber', + Format => 'int16u', + Condition => '$$self{Model} !~ /^DSC-/', + ValueConv => '2 ** (($val/256 - 16) / 2)', + ValueConvInv => '(log($val)*2/log(2)+16)*256', + PrintConv => 'sprintf("%.1f",$val)', + PrintConvInv => '$val', + }, + 0x0016 => { + Name => 'SonyMaxApertureValue', # (at current focal length) + Format => 'int16u', + ValueConv => '2 ** (($val/256 - 16) / 2)', + ValueConvInv => '(log($val)*2/log(2)+16)*256', + PrintConv => 'sprintf("%.1f",$val)', + PrintConvInv => '$val', + }, + 0x0024 => { %sequenceImageNumber }, + 0x0034 => { %releaseMode2 }, + # 0x003e and 0x0040: maximum image size; ShotInfo gives actual image size + 0x003e => { Name => 'SonyImageWidthMax', Format => 'int16u' }, + 0x0040 => { Name => 'SonyImageHeightMax', Format => 'int16u' }, + 0x0042 => { + Name => 'HighISONoiseReduction', + PrintConv => { + 0 => 'Off', + 1 => 'Low', + 2 => 'Normal', + 3 => 'High', + }, + }, + 0x0044 => { + Name => 'LongExposureNoiseReduction', + PrintConv => { + 0 => 'Off', + 1 => 'On', # (unused or dark subject) + }, + }, + 0x0046 => { %pictureEffect2010 }, + 0x0048 => { %exposureProgram2010 }, + 0x004a => { + Name => 'CreativeStyle', + PrintConv => { + 0 => 'Standard', + 1 => 'Vivid', + 2 => 'Neutral', + 3 => 'Portrait', + 4 => 'Landscape', + 5 => 'B&W', + 6 => 'Clear', + 7 => 'Deep', + 8 => 'Light', + 9 => 'Sunset', + 10 => 'Night View/Portrait', + 11 => 'Autumn Leaves', + 13 => 'Sepia', + }, + }, + 0x0052 => { + Name => 'Sharpness', + Format => 'int8s', + PrintConv => '$val > 0 ? "+$val" : $val', + PrintConvInv => '$val', + }, + 0x005a => { + Name => 'DistortionCorrParamsPresent', + Condition => '$$self{Model} !~ /^DSC-/', + PrintConv => { 0 => 'No', 1 => 'Yes'}, + }, + 0x005b => { + Name => 'DistortionCorrection', + PrintConv => { + 0 => 'None', + 1 => 'Applied', + }, + }, + # 0x005c - same as 0x005e, but has value 3 for 50mm F1.4 ZA, DT 18-135mm and for 70-400mm G II: meaning ?? + 0x005d => { + Name => 'LensFormat', + Condition => '$$self{Model} !~ /^DSC-/', + PrintConv => { + 0 => 'Unknown', + 1 => 'APS-C', + 2 => 'Full-frame', + }, + }, + 0x005e => { + Name => 'LensMount', + DataMember => 'LensMount', + RawConv => '$$self{LensMount} = $val; $$self{Model} =~ /^DSC-/ ? undef : $val', + PrintConv => { + 0 => 'Unknown', + 1 => 'A-mount', + 2 => 'E-mount', + }, + }, + 0x0060 => { + Name => 'LensType2', + Condition => '$$self{LensMount} == 2', + Format => 'int16u', + Notes => 'E-mount lenses', + SeparateTable => 'LensType2', + PrintConv => \%sonyLensTypes2, + }, + 0x0062 => { + Name => 'LensType', + Condition => '$$self{LensMount} == 1', + Format => 'int16u', + Notes => 'A-mount lenses on SLT and NEX', + SeparateTable => 1, + PrintConv => \%sonyLensTypes, + }, + 0x0064 => { + Name => 'DistortionCorrParams', + Condition => '$$self{Model} !~ /^DSC-/', + Format => 'int16s[16]', + }, + 0x0342 => { + Name => 'LensZoomPosition', + Condition => '$$self{Model} !~ /^(ILCA-|ILCE-(7RM2|7M3|7RM3|7SM2|6300|6400|6500|9)|DSC-(HX80|HX90V|HX99|RX0|RX10M2|RX10M3|RX10M4|RX100M4|RX100M5|RX100M5A|RX100M6|WX500))/', + Format => 'int16u', + PrintConv => 'sprintf("%.0f%%",$val/10.24)', + PrintConvInv => '$val=~s/ ?%$//; $val * 10.24', + }, + 0x034a => { + Name => 'VignettingCorrParams', + Condition => '$$self{Model} =~ /^(ILCA-(68|77M2)|ILCE-(5000|5100|6000|7|7R|7S|QX1)|Lusso)\b/', + Format => 'int16s[16]', + }, + 0x0350 => { + Name => 'VignettingCorrParams', + Condition => '$$self{Model} =~ /^(ILCE-7M2)/', + Format => 'int16s[16]', + }, + 0x035c => { + Name => 'VignettingCorrParams', + Condition => '$$self{Model} =~ /^(ILCA-99M2|ILCE-(6400|6500|7M3|7RM3|9))/', + Format => 'int16s[16]', + }, + 0x035a => { + Name => 'LensZoomPosition', + Condition => '$$self{Model} =~ /^(ILCE-(7RM2|7SM2)|DSC-(HX80|HX90V|RX10M2|RX10M3|RX100M4|WX500))/', + Format => 'int16u', + PrintConv => 'sprintf("%.0f%%",$val/10.24)', + PrintConvInv => '$val=~s/ ?%$//; $val * 10.24', + }, + 0x0368 => { + Name => 'VignettingCorrParams', + Condition => '$$self{Model} =~ /^(ILCE-(6300|7RM2|7SM2))/', + Format => 'int16s[16]', + }, + 0x037c => { + Name => 'ChromaticAberrationCorrParams', + Condition => '$$self{Model} =~ /^(ILCA-(68|77M2)|ILCE-(5000|5100|6000|7|7R|7S|QX1)|Lusso)\b/', + Format => 'int16s[32]', + }, + 0x0384 => { + Name => 'ChromaticAberrationCorrParams', + Condition => '$$self{Model} =~ /^(ILCE-7M2)/', + Format => 'int16s[32]', + }, + 0x039c => { + Name => 'ChromaticAberrationCorrParams', + Condition => '$$self{Model} =~ /^(ILCE-(6300|7RM2|7SM2))/', + Format => 'int16s[32]', + }, + 0x03b0 => { + Name => 'ChromaticAberrationCorrParams', + Condition => '$$self{Model} =~ /^(ILCA-99M2|ILCE-6500)/', + Format => 'int16s[32]', + }, + 0x03b8 => { + Name => 'ChromaticAberrationCorrParams', + Condition => '$$self{Model} =~ /^(ILCE-(6400|7M3|7RM3|9))/', + Format => 'int16s[32]', + }, +); + +# Tag9406 (ref JR) +%Image::ExifTool::Sony::Tag9406 = ( + PROCESS_PROC => \&ProcessEnciphered, + WRITE_PROC => \&WriteEnciphered, + CHECK_PROC => \&Image::ExifTool::CheckBinaryData, + FORMAT => 'int8u', + WRITABLE => 1, + FIRST_ENTRY => 0, + GROUPS => { 0 => 'MakerNotes', 2 => 'Image' }, +# 0x0000: 1 for SLT-A37/A57/A65/A77, NEX-5N/7/F3/VG20 +# 2 for SLT-A58/99V, NEX-3N/5R/5T/6/VG30/VG900, ILCA-68/77M2, ILCE-3000/3500/7/7M2/7R/7S/5000/6000 +# 3 for ILCA-99M2, ILCE-6300/6500/7M3/7RM2/7RM3/7SM2/9 +# 0x0001+0x0002: Int16u, seen 580 - 770: similar to "BatteryUnknown" ?? +# 0x0005: int8u, seen 73 - 117: maybe Fahrenheit? Higher than "AmbientTemperature", but same trend. + 0x0005 => { + Name => 'BatteryTemperature', + ValueConv => '($val - 32) / 1.8', # convert to Celsius + ValueConvInv => '$val * 1.8 + 32', + PrintConv => 'sprintf("%.1f C",$val)', + PrintConvInv => '$val=~s/\s*C//; $val', + }, + # 0x0006: usually 0, seen non-zero values only for SLT-A99V, ILCA-77M2/99M2 and ILCE-7/7R/7RM2/9: BatteryLevel Grip ? + 0x0006 => { + Name => 'BatteryLevelGrip1', + Condition => '$$valPt !~ /^\x00/', # only valid when not 0 + PrintConv => '"$val%"', + PrintConvInv => '$val=~s/\s*\%//; $val', + }, + # 0x0007: seen values from 8 - 105, decreasing in sequences of images: BatteryLevel + 0x0007 => { + Name => 'BatteryLevel', + PrintConv => '"$val%"', + PrintConvInv => '$val=~s/\s*\%//; $val', + }, + # 0x0008: usually 255 or 0 (ILCE-7/7R), seen other values only for A99V and ILCE-7/7R when 0x0006 not 0. + # A99V with grip can have 3 batteries: => Grip 2; + # but ILCE-7/7R with grip can have max 2, and as all ILCE-7/7R samples give >100 values, exclude... + 0x0008 => { + Name => 'BatteryLevelGrip2', + Condition => '$$valPt !~ /^[\x00\xff]/ and $$self{Model} !~ /^(ILCE-(7|7R)|Lusso)$/', # only when not 0 or 255 and not for ILCE-7/7R + PrintConv => '"$val%"', + PrintConvInv => '$val=~s/\s*\%//; $val', + }, +# 0x0009-0x001a: looks like 9 Int16u values +# 0x0022: 0 or 1 for A99, NEX-5R, 6 +# 0x0025: 0 or 1 for other SLT and NEX (0x0022, 0x0023, 0x0024 = 255) +); + +# Tag940a (ref PH, decoded mainly from A77) +%Image::ExifTool::Sony::Tag940a = ( + PROCESS_PROC => \&ProcessEnciphered, + WRITE_PROC => \&WriteEnciphered, + CHECK_PROC => \&Image::ExifTool::CheckBinaryData, + FORMAT => 'int8u', + WRITABLE => 1, + FIRST_ENTRY => 0, + GROUPS => { 0 => 'MakerNotes', 2 => 'Camera' }, + NOTES => 'These tags are currently extracted for SLT models only.', + # 0x00 - 10(A65,A77,NEX-5N,7,VG20E), 11(A37,A57,A99,NEX-5R,6,F3,RX1,RX100), + # 9(HX9V), 4,68,86,110(panoramas) - ref JR + 0x04 => { + Name => 'AFPointsSelected', + Format => 'int32u', + PrintConvColumns => 2, + PrintConv => { + # verified for A77 firmware 1.03 and 1.07 and A99 firmware 1.00, + # but there were inconsistencies with my A77 firmware 1.04 samples - PH + 0 => '(none)', # ILCA-68/77M2/99M2 always give this + 0x00007801 => 'Center Zone', + 0x0001821c => 'Right Zone', + 0x000605c0 => 'Left Zone', + 0x0003ffff => '(all LA-EA4)', # for LA-EA4: 18 bits + 0x7fffffff => '(all)', # also for LA-EA2 + 0xffffffff => 'n/a', # DSC and ILCE/NEX models always give this, except when using LA-EA2 or LA-EA4 + # (on Wide AFAreaMode, outer focus points are dropped + # at progressively higher digital zoom ratios, ref JR) + BITMASK => { + 0 => 'Center', # (1.04 gave this for Upper-middle and Near Left) + 1 => 'Top', # (1.04 didn't give this value) + 2 => 'Upper-right', # (1.04 OK) + 3 => 'Right', # (1.04 didn't give this value) + 4 => 'Lower-right', # (1.04 gave this for Bottom) + 5 => 'Bottom', # (1.04 gave this for Lower-middle) + 6 => 'Lower-left', # (1.04 gave this for Left and Lower Far Left) + 7 => 'Left', # (1.04 gave this for Far Left) + 8 => 'Upper-left', # (1.04 OK) + 9 => 'Far Right', # (1.04 gave this for Upper Far Right and Right) + 10 => 'Far Left', # (1.04 didn't give this value) + 11 => 'Upper-middle', # (1.04 gave this for Top) + 12 => 'Near Right', # (1.04 gave this for Center) + 13 => 'Lower-middle', # (1.04 gave this for Lower-left and Near Right) + 14 => 'Near Left', # (1.04 didn't give this value) + 15 => 'Upper Far Right',# (1.04 didn't give this value) + 16 => 'Lower Far Right',# (1.04 OK, but gave this for Far Right and Lower-right too) + 17 => 'Lower Far Left', # (1.04 didn't give this value) + 18 => 'Upper Far Left', # (1.04 OK) + # higher bits may be used in panorama images - ref JR + }, + }, + }, + # 0x0a - int16u: 0,1,2,3 + # 0xa6 - 8 bytes face detection info ?; starts with 1, otherwise all 0 +); + +# Tag940c (ref JR) +%Image::ExifTool::Sony::Tag940c = ( + PROCESS_PROC => \&ProcessEnciphered, + WRITE_PROC => \&WriteEnciphered, + CHECK_PROC => \&Image::ExifTool::CheckBinaryData, + FORMAT => 'int8u', + WRITABLE => 1, + FIRST_ENTRY => 0, + GROUPS => { 0 => 'MakerNotes', 2 => 'Image' }, + DATAMEMBER => [ 0x0008 ], + NOTES => 'NEX and ILCE models only.', + + # 0x0001 - 0 for all NEX and ILCE-3000/3500, 20 for all other ILCE (17 for ILCE samples from Sony.net) + # 0x0008 - LensMount, but different values from Tag9405-0x0105 and Tag9050-0x0604. + # don't know what difference is between values '1' and '5' ... + 0x0008 => { + Name => 'LensMount2', # ? maybe some other meaning ? (A-mount adapter-only images give 0) + RawConv => '$$self{LensMount} = $val', + PrintConv => { + 0 => 'Unknown', # LA-EA3 with non-SSM/SAM lens will often give this, not 1 or 5 + 1 => 'A-mount (1)', + 4 => 'E-mount', + 5 => 'A-mount (5)', + }, + }, + # 0x0009 - LensType3: + # This tag appears to also indicate adapter info, similar to CameraSettings3-0x03f7 for the original NEX-3/5. + # (Tag9405-0x0605 and Tag9050-0x0107 LensType2 always give '0' for adapters/A-mount lenses.) + # - seen a few instances of 0x0009 indicating an E-mount lens, but 0xb027 LensType indicating an A-mount lens: + # possibly due to adapter info not being read/reset correctly ? + # August 2015: renamed from LensType2 into Lenstype3 because too often info here relates to previously-mounted-lens + 0x0009 => { + Name => 'LensType3', + RawConv => '(($$self{LensMount} != 0) or ($val > 0 and $val < 32784)) ? $val : undef', + Format => 'int16u', + SeparateTable => 'LensType2', + PrintConv => \%sonyLensTypes2, + }, + 0x000b => { + Name => 'CameraE-mountVersion', + Format => 'int16u', + PrintConv => 'sprintf("%x.%.2x",$val>>8,$val&0xff)', + PrintConvInv => 'my @a=split(/\./,$val);(hex($a[0])<<8)|hex($a[1])', + # E-mount versions seen for various cameras / camera-firmware versions: + # - : info not present in CameraSettings3 for NEX-3/5/5C/C3/VG10E + # 1.14: NEX-5N/5R/6/7/F3/VG20E/VG30E/VG900 v1.00, NEX-5N v1.01, NEX-3N v0.90 + # 1.20: NEX-3N v1.00, NEX-6 v1.01, NEX-7 v1.02, ILCE-3000 v1.00, ILCE-3500 v1.01 + # 1.30: NEX-5T v1.00, NEX-6 v1.02/v1.03, NEX-7 v1.03 + # 1.31: ILCE-7/7R v0.95/v1.00/v1.01, ILCE-5000 + # 1.40: ILCE-7/7R v1.02/v1.10, ILCE-7S v1.00, ILCE-6000 v1.00/v1.10, ILCE-5100/QX1 + # 1.50: ILCE-7/7R/7S v1.20-v3.20, ILCE-7M2, ILCE-7RM2 v1.00-v3.00, ILCE-7SM2 v1.00-v2.20, + # ILCE-6000 v1.20-v3.20 + # 1.60: ILCE-6300/6500, ILCE-7RM2 v3.05-v4.00 + # 1.70: ILCE-7M3/7RM3/9 + # 1.80: ILCE-6400 + }, + 0x000d => { + Name => 'LensE-mountVersion', + Condition => '$$self{LensMount} != 0', + Format => 'int16u', + PrintConv => 'sprintf("%x.%.2x",$val>>8,$val&0xff)', + PrintConvInv => 'my @a=split(/\./,$val);(hex($a[0])<<8)|hex($a[1])', + # E-mount versions seen for various lens models: + # 0.00: Unknown lenses/adapters + # 1.00: SEL18200LE, Sigma DN, Tamron Di III, Zeiss Touit + # 1.07: (Ver.01) original E-lenses (SEL16F28, SEL18200, SEL1855, SEL24F18Z, SEL30M35, SEL50F18, SEL55210) and LA-EA1 + # 1.08: LA-EA1 (Ver.02), Metabones Smart + # 1.14: LA-EA2 + # 1.20: (Ver.02) firmware-updated E-lenses (SEL1855, SEL24F18Z, SEL30M35, SEL50F18, SEL55210), + # newer E-lenses (SEL1018, SEL1670Z, SEL20F28, SEL35F18, SELP1650, SELP18105G, SELP18200) or LA-EA3 Ver.01 + # 1.30: LA-EA4 + # 1.31: original FE-lenses (SEL2470Z, SEL2870, SEL35F28Z, SEL55F18Z), SEL1850 + # 1.35: SEL70200G, SEL55210 (Black?, seen with ILCE-3500) + # 1.40: SEL1635Z, SEL24240, SEL35F14Z, SELP28135G, Zeiss Loxia 35mm/50mm Ver.01, Zeiss Touit Ver.02 + # 1.41: SELP18105G Ver.02 + # 1.50: SEL28F20, SEL90M28G, Zeiss Batis 18mm/25mm/85mm/135mm, Zeiss Loxia 21mm, Zeiss Loxia 35mm/50mm Ver.02, + # Tokina Firin 20mm + # 1.60: SEL1224G, SEL1635GM, SELP18110G, SEL18135, SEL2470GM, SEL24105G, SEL50F14Z, SEL50F18F, SEL50M28, SEL70200GM, + # SEL70300G, SEL85F14GM, SEL85F18, SEL100F28GM, SEL100400GM, Sigma 30mm F1.4 DC DN, Sigma MC-11, + # Samyang AF 14mm/50mm, Voigtlander 15mm, Sigma 16mm F1.4 DC DN + # 1.70: LA-EA3 Ver.02, Samyang AF 35mm, Tamron 28-75mm, Voigtlander 10mm/12mm/40mm/65mm, Zeiss Loxia 25mm/85mm + # 1.80: Voigtlander 21mm + }, + # 0x0014 and 0x0015: change together: LensFirmwareVersion + # 0x0015 as 2-digit hex matches known firmware versions of Sony lenses and Metabones adapters, + # 0x0014 as 3-digit decimal: not confirmed sub-versions + # Some versions as seen with this decoding: + # 00.nnn for several pre-production Sony E-mount lenses + # 01.000 - 01.009 for various Sony E-mount lenses + # 02.nnn, 03.nnn for various Sony E-mount lenses for which a Ver.02 or Ver.03 update is available + # 16.001 for Metabones Speed Booster + # 19/22/24/30/32/41.001 etc. for Metabones Canon EF Smart adapters + 0x0014 => { + Name => 'LensFirmwareVersion', + Condition => '$$self{LensMount} != 0', + Format => 'int16u', + PrintConv => 'sprintf("Ver.%.2x.%.3d",$val>>8,$val&0xff)', + }, + # 0x0016 - 0x003f: non-0 data present when: 0x0001>0 AND 0x0008=4(E-mount) AND 0x000f<255 +); + + +# AFInfo (SLT models only) (ref PH, decoded mainly from A77) +%Image::ExifTool::Sony::AFInfo = ( + PROCESS_PROC => \&ProcessEnciphered, + WRITE_PROC => \&WriteEnciphered, + CHECK_PROC => \&Image::ExifTool::CheckBinaryData, + FORMAT => 'int8u', + WRITABLE => 1, + FIRST_ENTRY => 0, + PRIORITY => 0, + GROUPS => { 0 => 'MakerNotes', 2 => 'Camera' }, + DATAMEMBER => [ 0x02 ], + IS_SUBDIR => [ 0x11 ], + NOTES => 'These tags are currently extracted for SLT models only.', + # first 4 bytes (deciphered) (ref JR): + # 0 1 1 0 for A37, A57, A58 + # 2 1 1 0 for A65V + # 2 1 2 0 for A77V + # 0 1 2 0 for A99V + # 1 1 3 0 for ILCA-68/77M2/99M2 + # 0 0 0 0 for NEX and ILCE-3000/3500, also seen for SLT/ILCA with non-AF lens + # 1 0 0 0 for ILCE-5000/5100/6000/7/7M2/7R/7S/QX1 + # 6 0 0 0 for ILCE-6300/6500/7M3/7RM2/7RM3/7SM2/9 + # 0 2 0 0 for NEX/ILCE with LA-EA2/EA4 Phase-AF adapter + # 2 0 0 0 seen for a few NEX-5N images + # 2 2 0 0 seen for a few NEX-5N/7 images with LA-EA2 adapter + 0x02 => { + Name => 'AFType', + RawConv => '$$self{AFType} = $val', + PrintConv => { + # 0 => '?? n.a.', # seen on some A99V images with non-AF (Samyang) lens + 1 => '15-point', + 2 => '19-point', + 3 => '79-point', # ILCA-68/77M2/99M2 + }, + }, + +### decoding for SLT; ILCA-68/77M2/99M2 (AFType == 3) uses different offsets: see below + + 0x04 => { + Name => 'AFStatusActiveSensor', + Condition => '$$self{Model} !~ /^ILCA-/', + %Image::ExifTool::Minolta::afStatusInfo, + }, + 0x07 => [ # the active AF sensor + { + Name => 'AFPoint', + Condition => '$$self{AFType} == 1', + Notes => 'models with 15-point AF', + PrintConvColumns => 2, + PrintConv => \%afPoint15, + },{ + Name => 'AFPoint', + Condition => '$$self{AFType} == 2', + Notes => 'models with 19-point AF', + PrintConvColumns => 2, + PrintConv => \%afPoint19, + }, + ], + 0x08 => [ # the AF sensor in focus at focus time (shutter release half press) + { + Name => 'AFPointInFocus', + Condition => '$$self{AFType} == 1', + Notes => 'models with 15-point AF', + PrintConvColumns => 2, + PrintConv => { + %afPoint15, + 255 => '(none)', + }, + },{ + Name => 'AFPointInFocus', + Condition => '$$self{AFType} == 2', + Notes => 'models with 19-point AF', + PrintConvColumns => 2, + PrintConv => { + %afPoint19, + 255 => '(none)', + }, + }, + ], + 0x09 => [ # the AF sensor in focus at shutter release (shutter release full press) + { + Name => 'AFPointAtShutterRelease', + Condition => '$$self{AFType} == 1', + Notes => 'models with 15-point AF', + PrintConvColumns => 2, + PrintConv => { + %afPoint15, + 30 => '(out of focus)', + }, + },{ + Name => 'AFPointAtShutterRelease', + Condition => '$$self{AFType} == 2', + Notes => 'models with 19-point AF', + PrintConvColumns => 2, + PrintConv => { + %afPoint19, + 30 => '(out of focus)', + }, + }, + ], + 0x0a => { + Name => 'AFAreaMode', + Condition => '$$self{Model} !~ /^ILCA-/', + PrintConv => { + 0 => 'Wide', + 1 => 'Spot', + 2 => 'Local', + 3 => 'Zone', + }, + }, + 0x0b => { + Name => 'FocusMode', + Condition => '$$self{Model} !~ /^ILCA-/', + PrintConvColumns => 2, + # validated for A77 firmware 1.03, 1.04 and 1.07 and A99 + # - not confirmed for A37,A57 and A65 which also write this tag + PrintConv => { + 0 => 'Manual', + 2 => 'AF-S', + 3 => 'AF-C', + 4 => 'AF-A', + 6 => 'DMF', + 7 => 'AF-D', # (unique to A99) + }, + }, + 0x11 => [ #JR + { + Name => 'AFStatus15', + Condition => '$$self{AFType} == 1', + Format => 'int16s[18]', + SubDirectory => { TagTable => 'Image::ExifTool::Sony::AFStatus15' }, + },{ + Name => 'AFStatus19', + Condition => '$$self{AFType} == 2', + Format => 'int16s[30]', + SubDirectory => { TagTable => 'Image::ExifTool::Sony::AFStatus19' }, + }, + ], + # 0x004d - 18 or 30 int16 values + # 0x0089 - 18 or 30 int16 values + # 0x00b1 - 18 or 30 int16 values + # 0x0121 - 18 or 30 int16s values, similar to 0x11 AFStatus + # 0x016e - SLT: 4 bytes indicating 'AFPointsUsed', identical to first 4 bytes of 0x2020 for A58/A99V + 0x016e => { + Name => 'AFPointsUsed', + Condition => '$$self{Model} !~ /^ILCA-/', + Notes => 'SLT models only', + Format => 'int32u', + PrintConvColumns => 2, + PrintConv => { + 0 => '(none)', + BITMASK => { + 0 => 'Center', + 1 => 'Top', + 2 => 'Upper-right', + 3 => 'Right', + 4 => 'Lower-right', + 5 => 'Bottom', + 6 => 'Lower-left', + 7 => 'Left', + 8 => 'Upper-left', + 9 => 'Far Right', + 10 => 'Far Left', + 11 => 'Upper-middle', + 12 => 'Near Right', + 13 => 'Lower-middle', + 14 => 'Near Left', + 15 => 'Upper Far Right', + 16 => 'Lower Far Right', + 17 => 'Lower Far Left', + 18 => 'Upper Far Left', + }, + }, + }, + # 0x017b: int16s: also has to do with AFMicroAdj: value equals -AFMA * 4 * MaxApertureValue (ref JR) + 0x017d => { #PH (verified for the SLT-A77/A99; other SLT models don't have this setting - ref JR) + # (different from AFMicroAdjValue because it is 0 when the adjustment is off) + Name => 'AFMicroAdj', + Condition => '$$self{Model} !~ /^ILCA-/', + Format => 'int8s', + }, + 0x017e => { #JR + Name => 'ExposureProgram', + Condition => '$$self{Model} !~ /^ILCA-/', + Priority => 0, + SeparateTable => 'ExposureProgram3', + PrintConv => \%sonyExposureProgram3, + }, + # 0x01b8 - 65 AF Info blocks of 180 bytes each for SLT (ref JR) + # In each block, the 9th, 10th and 11th byte appear to relate to AFPoint as at offsets 0x07, 0x08, 0x09 above.. + # Possibly, these blocks relate to sequential focusing attempts and/or object tracking, + # the first byte being an Index or Counter. + # The last block before the block with index 0, appears to relate to the AF data at ShutterRelease. + + # 0xf38,0x1208,0x14d8,0x158c,0x1640,(and more) - 0 if AFMicroAdj is On, 1 if Off + # 0x1ab6 - 0x80 if AFMicroAdj is On, 0 if Off + # tags also related to AFPoint (PH, A77): + # 0x11ec, 0x122a, 0x1408, 0x1446, 0x14bc, 0x1f86, + # 0x14fa, 0x1570, 0x1572, 0x15ae, 0x1f48 + +### decoding for ILCA-68/77M2/99M2, AFType == 3 + + 0x0005 => { #JR + Name => 'FocusMode', + Condition => '$$self{Model} =~ /^ILCA-/', + Notes => 'ILCA models only', + Writable => 'int8u', + Priority => 0, + PrintConv => { + 0 => 'Manual', + 2 => 'AF-S', + 3 => 'AF-C', + 4 => 'AF-A', + 6 => 'DMF', + # 7 => 'AF-D', # not yet seen + }, + }, + # 0x0010 - for ILCA-68/77M2/99M2: 10 bytes identical to 0x2020, and probably indicating 'AFPointsUsed' (ref JR) + 0x0010 => { + Name => 'AFPointsUsed', + Condition => '$$self{Model} =~ /^ILCA-/', + Format => 'int8u[10]', + BitsPerWord => 8, + BitsTotal => 80, + PrintConv => { + 0 => '(none)', + BITMASK => { %afPoints79 }, + }, + }, + # 0x0037, 0x0038, 0x0039 similar to 0x07, 0x08, 0x09, but using numbers from 0-94 for ILCA-68/77M2/99M2 + 0x0037 => { # the active AF sensor + Name => 'AFPoint', + Condition => '$$self{AFType} == 3', + PrintConv => { + %afPoints79_940e, + 255 => '(none)', + }, + }, + 0x0038 => { # the AF sensor in focus at focus time (shutter release half press) + Name => 'AFPointInFocus', + Condition => '$$self{AFType} == 3', + PrintConv => { + %afPoints79_940e, + 255 => '(none)', + }, + }, + 0x0039 => { # the AF sensor in focus at shutter release (shutter release full press) + Name => 'AFPointAtShutterRelease', + Condition => '$$self{AFType} == 3', + PrintConv => { + %afPoints79_940e, + 95 => '(none)', + }, + }, + 0x003a => { #JR + Name => 'AFAreaMode', + Condition => '$$self{Model} =~ /^ILCA-/', + PrintConv => { + 0 => 'Wide', + 1 => 'Center', + 2 => 'Flexible Spot', + 3 => 'Zone', + 4 => 'Expanded Flexible Spot', #(NC) + }, + }, + 0x003b => { + Name => 'AFStatusActiveSensor', + Condition => '$$self{Model} =~ /^ILCA-/', + %Image::ExifTool::Minolta::afStatusInfo, + }, + 0x0043 => { + Name => 'ExposureProgram', + Condition => '$$self{Model} =~ /^ILCA-/', + Priority => 0, + SeparateTable => 'ExposureProgram3', + PrintConv => \%sonyExposureProgram3, + }, + # 0x004e: int16s: also has to do with AFMicroAdj: value equals -AFMA * 4 * MaxApertureValue (ref JR) + 0x0050 => { #PH (ILCA-A77M2, to be confirmed for other ILCA models) + Name => 'AFMicroAdj', + Condition => '$$self{Model} =~ /^ILCA-/', + Format => 'int8s', + }, + # 0x007d - AFStatus79 - 95 int16s values for the ILCA-68/77M2/99M2: 79 AF points + 15 cross + 1 F2.8 + 0x007d => { + Name => 'AFStatus79', + Condition => '$$self{AFType} == 3', + Format => 'int16s[95]', + SubDirectory => { TagTable => 'Image::ExifTool::Sony::AFStatus79' }, + }, + # 0x013b - 95 int8u values + # 0x01ab - 95 int8u values + # 0x021b - 95 int16s values, similar to 0x007d AFStatus79, but not sure if this is valid for ILCA-99M2 + # 0x04c0 - 45 AF Info blocks of 244 bytes each for ILCA-68/77M2 + # 0x12a0 - 30 AF Info blocks of 244 bytes each for ILCA-99M2 +); + +%Image::ExifTool::Sony::Tag940e = ( #JR + PROCESS_PROC => \&ProcessEnciphered, + WRITE_PROC => \&WriteEnciphered, + CHECK_PROC => \&Image::ExifTool::CheckBinaryData, + FORMAT => 'int8u', + FIRST_ENTRY => 0, + GROUPS => { 0 => 'MakerNotes', 2 => 'Image' }, + NOTES => 'E-mount models.', + + # (see comment in AFInfo for deciphered values of first 4 bytes for various models) + + # 0x0004 - if 0x0001 == 2: LA-EA2/EA4 15-point SLT Phase-detect AF adapter used: + # start of 164-byte AF Info Blocks, possibly the 11th byte might be the AFPoint. + # ILCE-7M2/7RM2/7SM2: 40 Blocks of 164 bytes + # other NEX/ILCE: 74 blocks of 164 bytes + + # 0x1a06 onwards - first seen for ILCE-7RM2: appears to be some kind of metering image + 0x1a06 => { Name => 'TiffMeteringImageWidth', Condition => '$$self{Model} =~ /^(ILCE-(6300|6500|7M3|7RM2|7RM3|7SM2|9))\b/' }, + 0x1a07 => { Name => 'TiffMeteringImageHeight', Condition => '$$self{Model} =~ /^(ILCE-(6300|6500|7M3|7RM2|7RM3|7SM2|9))\b/' }, + 0x1a08 => { # (2640 bytes: 1 set of 44x30 int16u values) + Name => 'TiffMeteringImage', + Condition => '$$self{Model} =~ /^(ILCE-(6300|6500|7M3|7RM2|7RM3|7SM2|9))\b/', + Format => 'undef[2640]', + Notes => q{ + 13(?)-bit intensity data from 1320 (1200) metering segments, extracted as a + 16-bit TIFF image + }, + ValueConv => sub { + my ($val, $et) = @_; + return undef unless length $val >= 2640; + return \ "Binary data 2640 bytes" unless $et->Options('Binary'); + my @dat = unpack('v*', $val); + # TIFF header for a 16-bit RGB 10dpi 44x30 image + $val = Image::ExifTool::MakeTiffHeader(44,30,3,16,10); + # re-order data to RGB pixels - use same value for R, G and B + my ($i, @val); + for ($i=0; $i<44*30; ++$i) { + # data is 13-bit (max 8191), shift left to fill 16 bits + push @val, int(5041.1*log($dat[$i]+1)/log(2)), int(5041.1*log($dat[$i]+1)/log(2)), int(5041.1*log($dat[$i]+1)/log(2)); + } + $val .= pack('v*', @val); # add TIFF strip data + return \$val; + }, + }, +); + +# AF Point Status (ref JR) +%Image::ExifTool::Sony::AFStatus15 = ( + %binaryDataAttrs, + GROUPS => { 0 => 'MakerNotes', 2 => 'Camera' }, + NOTES => 'AF Status information for models with 15-point AF.', + 0x00 => { Name => 'AFStatusUpper-left', %Image::ExifTool::Minolta::afStatusInfo }, + 0x02 => { Name => 'AFStatusLeft', %Image::ExifTool::Minolta::afStatusInfo }, + 0x04 => { Name => 'AFStatusLower-left', %Image::ExifTool::Minolta::afStatusInfo }, + 0x06 => { Name => 'AFStatusFarLeft', %Image::ExifTool::Minolta::afStatusInfo }, + 0x08 => { Name => 'AFStatusTopHorizontal', %Image::ExifTool::Minolta::afStatusInfo }, + 0x0a => { Name => 'AFStatusNearRight', %Image::ExifTool::Minolta::afStatusInfo }, + 0x0c => { Name => 'AFStatusCenterHorizontal', %Image::ExifTool::Minolta::afStatusInfo }, + 0x0e => { Name => 'AFStatusNearLeft', %Image::ExifTool::Minolta::afStatusInfo }, + 0x10 => { Name => 'AFStatusBottomHorizontal', %Image::ExifTool::Minolta::afStatusInfo }, + 0x12 => { Name => 'AFStatusTopVertical', %Image::ExifTool::Minolta::afStatusInfo }, + 0x14 => { Name => 'AFStatusCenterVertical', %Image::ExifTool::Minolta::afStatusInfo }, + 0x16 => { Name => 'AFStatusBottomVertical', %Image::ExifTool::Minolta::afStatusInfo }, + 0x18 => { Name => 'AFStatusFarRight', %Image::ExifTool::Minolta::afStatusInfo }, + 0x1a => { Name => 'AFStatusUpper-right', %Image::ExifTool::Minolta::afStatusInfo }, + 0x1c => { Name => 'AFStatusRight', %Image::ExifTool::Minolta::afStatusInfo }, + 0x1e => { Name => 'AFStatusLower-right', %Image::ExifTool::Minolta::afStatusInfo }, + 0x20 => { Name => 'AFStatusUpper-middle', %Image::ExifTool::Minolta::afStatusInfo }, + 0x22 => { Name => 'AFStatusLower-middle', %Image::ExifTool::Minolta::afStatusInfo }, +); + +# AF Point Status (ref JR) +%Image::ExifTool::Sony::AFStatus19 = ( + %binaryDataAttrs, + GROUPS => { 0 => 'MakerNotes', 2 => 'Camera' }, + NOTES => 'AF Status information for models with 19-point AF.', + 0x00 => { Name => 'AFStatusUpperFarLeft', %Image::ExifTool::Minolta::afStatusInfo }, + 0x02 => { Name => 'AFStatusUpper-leftHorizontal', %Image::ExifTool::Minolta::afStatusInfo }, + 0x04 => { Name => 'AFStatusFarLeftHorizontal', %Image::ExifTool::Minolta::afStatusInfo }, + 0x06 => { Name => 'AFStatusLeftHorizontal', %Image::ExifTool::Minolta::afStatusInfo }, + 0x08 => { Name => 'AFStatusLowerFarLeft', %Image::ExifTool::Minolta::afStatusInfo }, + 0x0a => { Name => 'AFStatusLower-leftHorizontal', %Image::ExifTool::Minolta::afStatusInfo }, + 0x0c => { Name => 'AFStatusUpper-leftVertical', %Image::ExifTool::Minolta::afStatusInfo }, + 0x0e => { Name => 'AFStatusLeftVertical', %Image::ExifTool::Minolta::afStatusInfo }, + 0x10 => { Name => 'AFStatusLower-leftVertical', %Image::ExifTool::Minolta::afStatusInfo }, + 0x12 => { Name => 'AFStatusFarLeftVertical', %Image::ExifTool::Minolta::afStatusInfo }, + 0x14 => { Name => 'AFStatusTopHorizontal', %Image::ExifTool::Minolta::afStatusInfo }, + 0x16 => { Name => 'AFStatusNearRight', %Image::ExifTool::Minolta::afStatusInfo }, + 0x18 => { Name => 'AFStatusCenterHorizontal', %Image::ExifTool::Minolta::afStatusInfo }, + 0x1a => { Name => 'AFStatusNearLeft', %Image::ExifTool::Minolta::afStatusInfo }, + 0x1c => { Name => 'AFStatusBottomHorizontal', %Image::ExifTool::Minolta::afStatusInfo }, + 0x1e => { Name => 'AFStatusTopVertical', %Image::ExifTool::Minolta::afStatusInfo }, + 0x20 => { Name => 'AFStatusUpper-middle', %Image::ExifTool::Minolta::afStatusInfo }, + 0x22 => { Name => 'AFStatusCenterVertical', %Image::ExifTool::Minolta::afStatusInfo }, + 0x24 => { Name => 'AFStatusLower-middle', %Image::ExifTool::Minolta::afStatusInfo }, + 0x26 => { Name => 'AFStatusBottomVertical', %Image::ExifTool::Minolta::afStatusInfo }, + 0x28 => { Name => 'AFStatusUpperFarRight', %Image::ExifTool::Minolta::afStatusInfo }, + 0x2a => { Name => 'AFStatusUpper-rightHorizontal',%Image::ExifTool::Minolta::afStatusInfo }, + 0x2c => { Name => 'AFStatusFarRightHorizontal', %Image::ExifTool::Minolta::afStatusInfo }, + 0x2e => { Name => 'AFStatusRightHorizontal', %Image::ExifTool::Minolta::afStatusInfo }, + 0x30 => { Name => 'AFStatusLowerFarRight', %Image::ExifTool::Minolta::afStatusInfo }, + 0x32 => { Name => 'AFStatusLower-rightHorizontal',%Image::ExifTool::Minolta::afStatusInfo }, + 0x34 => { Name => 'AFStatusFarRightVertical', %Image::ExifTool::Minolta::afStatusInfo }, + 0x36 => { Name => 'AFStatusUpper-rightVertical', %Image::ExifTool::Minolta::afStatusInfo }, + 0x38 => { Name => 'AFStatusRightVertical', %Image::ExifTool::Minolta::afStatusInfo }, + 0x3a => { Name => 'AFStatusLower-rightVertical', %Image::ExifTool::Minolta::afStatusInfo }, +); + +# AF Point Status (ref JR) +%Image::ExifTool::Sony::AFStatus79 = ( + %binaryDataAttrs, + GROUPS => { 0 => 'MakerNotes', 2 => 'Camera' }, + NOTES => 'AF Status information for models with 79-point AF.', +# +# ILCA-68/77M2 AF sensor layout: +# A5* A6* A7* +# B2 B3 B4 B5 B6 B7 B8 B9 B10 +# C1 C2 C3 C4 C5* C6* C7* C8 C9 C10 C11 +# D1 D2 D3 D4 D5 D6 D7 D8 D9 D10 D11 +# E1 E2 E3 E4 E5* E6* E7* E8 E9 E10 E11 +# F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 +# G1 G2 G3 G4 G5* G6* G7* G8 G9 G10 G11 +# H2 H3 H4 H5 H6 H7 H8 H9 H10 +# I5* I6* I7* +# left section, from top to bottom, from right to left + 0x00 => { Name => 'AFStatus_00_B4', %Image::ExifTool::Minolta::afStatusInfo }, + 0x02 => { Name => 'AFStatus_01_C4', %Image::ExifTool::Minolta::afStatusInfo }, + 0x04 => { Name => 'AFStatus_02_D4', %Image::ExifTool::Minolta::afStatusInfo }, + 0x06 => { Name => 'AFStatus_03_E4', %Image::ExifTool::Minolta::afStatusInfo }, + 0x08 => { Name => 'AFStatus_04_F4', %Image::ExifTool::Minolta::afStatusInfo }, + 0x0a => { Name => 'AFStatus_05_G4', %Image::ExifTool::Minolta::afStatusInfo }, + 0x0c => { Name => 'AFStatus_06_H4', %Image::ExifTool::Minolta::afStatusInfo }, + 0x0e => { Name => 'AFStatus_07_B3', %Image::ExifTool::Minolta::afStatusInfo }, + 0x10 => { Name => 'AFStatus_08_C3', %Image::ExifTool::Minolta::afStatusInfo }, + 0x12 => { Name => 'AFStatus_09_D3', %Image::ExifTool::Minolta::afStatusInfo }, + 0x14 => { Name => 'AFStatus_10_E3', %Image::ExifTool::Minolta::afStatusInfo }, + 0x16 => { Name => 'AFStatus_11_F3', %Image::ExifTool::Minolta::afStatusInfo }, + 0x18 => { Name => 'AFStatus_12_G3', %Image::ExifTool::Minolta::afStatusInfo }, + 0x1a => { Name => 'AFStatus_13_H3', %Image::ExifTool::Minolta::afStatusInfo }, + 0x1c => { Name => 'AFStatus_14_B2', %Image::ExifTool::Minolta::afStatusInfo }, + 0x1e => { Name => 'AFStatus_15_C2', %Image::ExifTool::Minolta::afStatusInfo }, + 0x20 => { Name => 'AFStatus_16_D2', %Image::ExifTool::Minolta::afStatusInfo }, + 0x22 => { Name => 'AFStatus_17_E2', %Image::ExifTool::Minolta::afStatusInfo }, + 0x24 => { Name => 'AFStatus_18_F2', %Image::ExifTool::Minolta::afStatusInfo }, + 0x26 => { Name => 'AFStatus_19_G2', %Image::ExifTool::Minolta::afStatusInfo }, + 0x28 => { Name => 'AFStatus_20_H2', %Image::ExifTool::Minolta::afStatusInfo }, + 0x2a => { Name => 'AFStatus_21_C1', %Image::ExifTool::Minolta::afStatusInfo }, + 0x2c => { Name => 'AFStatus_22_D1', %Image::ExifTool::Minolta::afStatusInfo }, + 0x2e => { Name => 'AFStatus_23_E1', %Image::ExifTool::Minolta::afStatusInfo }, + 0x30 => { Name => 'AFStatus_24_F1', %Image::ExifTool::Minolta::afStatusInfo }, + 0x32 => { Name => 'AFStatus_25_G1', %Image::ExifTool::Minolta::afStatusInfo }, +# center section, cross-sensors *, from right to left, from top to bottom +# These are presumably Vertical, as all others are default Horizontal (ref Sony ILCA-77M2 brochure). + 0x34 => { Name => 'AFStatus_26_A7_Vertical', %Image::ExifTool::Minolta::afStatusInfo }, + 0x36 => { Name => 'AFStatus_27_A6_Vertical', %Image::ExifTool::Minolta::afStatusInfo }, + 0x38 => { Name => 'AFStatus_28_A5_Vertical', %Image::ExifTool::Minolta::afStatusInfo }, + 0x3a => { Name => 'AFStatus_29_C7_Vertical', %Image::ExifTool::Minolta::afStatusInfo }, + 0x3c => { Name => 'AFStatus_30_C6_Vertical', %Image::ExifTool::Minolta::afStatusInfo }, + 0x3e => { Name => 'AFStatus_31_C5_Vertical', %Image::ExifTool::Minolta::afStatusInfo }, + 0x40 => { Name => 'AFStatus_32_E7_Vertical', %Image::ExifTool::Minolta::afStatusInfo }, + 0x42 => { Name => 'AFStatus_33_E6_Center_Vertical', %Image::ExifTool::Minolta::afStatusInfo }, + 0x44 => { Name => 'AFStatus_34_E5_Vertical', %Image::ExifTool::Minolta::afStatusInfo }, + 0x46 => { Name => 'AFStatus_35_G7_Vertical', %Image::ExifTool::Minolta::afStatusInfo }, + 0x48 => { Name => 'AFStatus_36_G6_Vertical', %Image::ExifTool::Minolta::afStatusInfo }, + 0x4a => { Name => 'AFStatus_37_G5_Vertical', %Image::ExifTool::Minolta::afStatusInfo }, + 0x4c => { Name => 'AFStatus_38_I7_Vertical', %Image::ExifTool::Minolta::afStatusInfo }, + 0x4e => { Name => 'AFStatus_39_I6_Vertical', %Image::ExifTool::Minolta::afStatusInfo }, + 0x50 => { Name => 'AFStatus_40_I5_Vertical', %Image::ExifTool::Minolta::afStatusInfo }, +# center section, all sensors, from top to bottom, from right to left + 0x52 => { Name => 'AFStatus_41_A7', %Image::ExifTool::Minolta::afStatusInfo }, + 0x54 => { Name => 'AFStatus_42_B7', %Image::ExifTool::Minolta::afStatusInfo }, + 0x56 => { Name => 'AFStatus_43_C7', %Image::ExifTool::Minolta::afStatusInfo }, + 0x58 => { Name => 'AFStatus_44_D7', %Image::ExifTool::Minolta::afStatusInfo }, + 0x5a => { Name => 'AFStatus_45_E7', %Image::ExifTool::Minolta::afStatusInfo }, + 0x5c => { Name => 'AFStatus_46_F7', %Image::ExifTool::Minolta::afStatusInfo }, + 0x5e => { Name => 'AFStatus_47_G7', %Image::ExifTool::Minolta::afStatusInfo }, + 0x60 => { Name => 'AFStatus_48_H7', %Image::ExifTool::Minolta::afStatusInfo }, + 0x62 => { Name => 'AFStatus_49_I7', %Image::ExifTool::Minolta::afStatusInfo }, + 0x64 => { Name => 'AFStatus_50_A6', %Image::ExifTool::Minolta::afStatusInfo }, + 0x66 => { Name => 'AFStatus_51_B6', %Image::ExifTool::Minolta::afStatusInfo }, + 0x68 => { Name => 'AFStatus_52_C6', %Image::ExifTool::Minolta::afStatusInfo }, + 0x6a => { Name => 'AFStatus_53_D6', %Image::ExifTool::Minolta::afStatusInfo }, + 0x6c => { Name => 'AFStatus_54_E6_Center', %Image::ExifTool::Minolta::afStatusInfo }, + 0x6e => { Name => 'AFStatus_55_F6', %Image::ExifTool::Minolta::afStatusInfo }, + 0x70 => { Name => 'AFStatus_56_G6', %Image::ExifTool::Minolta::afStatusInfo }, + 0x72 => { Name => 'AFStatus_57_H6', %Image::ExifTool::Minolta::afStatusInfo }, + 0x74 => { Name => 'AFStatus_58_I6', %Image::ExifTool::Minolta::afStatusInfo }, + 0x76 => { Name => 'AFStatus_59_A5', %Image::ExifTool::Minolta::afStatusInfo }, + 0x78 => { Name => 'AFStatus_60_B5', %Image::ExifTool::Minolta::afStatusInfo }, + 0x7a => { Name => 'AFStatus_61_C5', %Image::ExifTool::Minolta::afStatusInfo }, + 0x7c => { Name => 'AFStatus_62_D5', %Image::ExifTool::Minolta::afStatusInfo }, + 0x7e => { Name => 'AFStatus_63_E5', %Image::ExifTool::Minolta::afStatusInfo }, + 0x80 => { Name => 'AFStatus_64_F5', %Image::ExifTool::Minolta::afStatusInfo }, + 0x82 => { Name => 'AFStatus_65_G5', %Image::ExifTool::Minolta::afStatusInfo }, + 0x84 => { Name => 'AFStatus_66_H5', %Image::ExifTool::Minolta::afStatusInfo }, + 0x86 => { Name => 'AFStatus_67_I5', %Image::ExifTool::Minolta::afStatusInfo }, +# right section, from top to bottom, from right to left + 0x88 => { Name => 'AFStatus_68_C11', %Image::ExifTool::Minolta::afStatusInfo }, + 0x8a => { Name => 'AFStatus_69_D11', %Image::ExifTool::Minolta::afStatusInfo }, + 0x8c => { Name => 'AFStatus_70_E11', %Image::ExifTool::Minolta::afStatusInfo }, + 0x8e => { Name => 'AFStatus_71_F11', %Image::ExifTool::Minolta::afStatusInfo }, + 0x90 => { Name => 'AFStatus_72_G11', %Image::ExifTool::Minolta::afStatusInfo }, + 0x92 => { Name => 'AFStatus_73_B10', %Image::ExifTool::Minolta::afStatusInfo }, + 0x94 => { Name => 'AFStatus_74_C10', %Image::ExifTool::Minolta::afStatusInfo }, + 0x96 => { Name => 'AFStatus_75_D10', %Image::ExifTool::Minolta::afStatusInfo }, + 0x98 => { Name => 'AFStatus_76_E10', %Image::ExifTool::Minolta::afStatusInfo }, + 0x9a => { Name => 'AFStatus_77_F10', %Image::ExifTool::Minolta::afStatusInfo }, + 0x9c => { Name => 'AFStatus_78_G10', %Image::ExifTool::Minolta::afStatusInfo }, + 0x9e => { Name => 'AFStatus_79_H10', %Image::ExifTool::Minolta::afStatusInfo }, + 0xa0 => { Name => 'AFStatus_80_B9', %Image::ExifTool::Minolta::afStatusInfo }, + 0xa2 => { Name => 'AFStatus_81_C9', %Image::ExifTool::Minolta::afStatusInfo }, + 0xa4 => { Name => 'AFStatus_82_D9', %Image::ExifTool::Minolta::afStatusInfo }, + 0xa6 => { Name => 'AFStatus_83_E9', %Image::ExifTool::Minolta::afStatusInfo }, + 0xa8 => { Name => 'AFStatus_84_F9', %Image::ExifTool::Minolta::afStatusInfo }, + 0xaa => { Name => 'AFStatus_85_G9', %Image::ExifTool::Minolta::afStatusInfo }, + 0xac => { Name => 'AFStatus_86_H9', %Image::ExifTool::Minolta::afStatusInfo }, + 0xae => { Name => 'AFStatus_87_B8', %Image::ExifTool::Minolta::afStatusInfo }, + 0xb0 => { Name => 'AFStatus_88_C8', %Image::ExifTool::Minolta::afStatusInfo }, + 0xb2 => { Name => 'AFStatus_89_D8', %Image::ExifTool::Minolta::afStatusInfo }, + 0xb4 => { Name => 'AFStatus_90_E8', %Image::ExifTool::Minolta::afStatusInfo }, + 0xb6 => { Name => 'AFStatus_91_F8', %Image::ExifTool::Minolta::afStatusInfo }, + 0xb8 => { Name => 'AFStatus_92_G8', %Image::ExifTool::Minolta::afStatusInfo }, + 0xba => { Name => 'AFStatus_93_H8', %Image::ExifTool::Minolta::afStatusInfo }, +# central F2.8 sensor + 0xbc => { Name => 'AFStatus_94_E6_Center_F2-8', %Image::ExifTool::Minolta::afStatusInfo }, +); + +%Image::ExifTool::Sony::FaceInfo1 = ( + %binaryDataAttrs, + GROUPS => { 0 => 'MakerNotes', 2 => 'Image' }, + 0x00 => { + Name => 'Face1Position', + Format => 'int16u[4]', + Notes => q{ + top, left, height and width of detected face. Coordinates are relative to + the full-sized unrotated image, with increasing Y downwards + }, + RawConv => '$$self{FacesDetected} < 1 ? undef : $val', + }, + 0x20 => { + Name => 'Face2Position', + Format => 'int16u[4]', + RawConv => '$$self{FacesDetected} < 2 ? undef : $val', + }, + 0x40 => { + Name => 'Face3Position', + Format => 'int16u[4]', + RawConv => '$$self{FacesDetected} < 3 ? undef : $val', + }, + 0x60 => { + Name => 'Face4Position', + Format => 'int16u[4]', + RawConv => '$$self{FacesDetected} < 4 ? undef : $val', + }, + 0x80 => { + Name => 'Face5Position', + Format => 'int16u[4]', + RawConv => '$$self{FacesDetected} < 5 ? undef : $val', + }, + 0xa0 => { + Name => 'Face6Position', + Format => 'int16u[4]', + RawConv => '$$self{FacesDetected} < 6 ? undef : $val', + }, + 0xc0 => { + Name => 'Face7Position', + Format => 'int16u[4]', + RawConv => '$$self{FacesDetected} < 7 ? undef : $val', + }, + 0xe0 => { + Name => 'Face8Position', + Format => 'int16u[4]', + RawConv => '$$self{FacesDetected} < 8 ? undef : $val', + }, +); + +%Image::ExifTool::Sony::FaceInfo2 = ( + %binaryDataAttrs, + GROUPS => { 0 => 'MakerNotes', 2 => 'Image' }, + 0x00 => { + Name => 'Face1Position', + Format => 'int16u[4]', + Notes => q{ + top, left, height and width of detected face. Coordinates are relative to + the full-sized unrotated image, with increasing Y downwards + }, + RawConv => '$$self{FacesDetected} < 1 ? undef : $val', + }, + 0x25 => { + Name => 'Face2Position', + Format => 'int16u[4]', + RawConv => '$$self{FacesDetected} < 2 ? undef : $val', + }, + 0x4a => { + Name => 'Face3Position', + Format => 'int16u[4]', + RawConv => '$$self{FacesDetected} < 3 ? undef : $val', + }, + 0x6f => { + Name => 'Face4Position', + Format => 'int16u[4]', + RawConv => '$$self{FacesDetected} < 4 ? undef : $val', + }, + 0x94 => { + Name => 'Face5Position', + Format => 'int16u[4]', + RawConv => '$$self{FacesDetected} < 5 ? undef : $val', + }, + 0xb9 => { + Name => 'Face6Position', + Format => 'int16u[4]', + RawConv => '$$self{FacesDetected} < 6 ? undef : $val', + }, + 0xde => { + Name => 'Face7Position', + Format => 'int16u[4]', + RawConv => '$$self{FacesDetected} < 7 ? undef : $val', + }, + 0x103 => { + Name => 'Face8Position', + Format => 'int16u[4]', + RawConv => '$$self{FacesDetected} < 8 ? undef : $val', + }, +); + +# panorama info for cameras such as the HX1, HX5, TX7 (ref 9/PH) +%Image::ExifTool::Sony::Panorama = ( + %binaryDataAttrs, + GROUPS => { 0 => 'MakerNotes', 2 => 'Image' }, + FORMAT => 'int32u', + NOTES => q{ + Tags found in panorama images from various Sony DSC, NEX, SLT and DSLR + cameras. The width/height values of these tags are not affected by camera + rotation -- the width is always the longer dimension. + }, + # 0: 257 for panorama images, 0 for all other images (ref JR) + 1 => 'PanoramaFullWidth', # (including black/gray borders) + 2 => 'PanoramaFullHeight', + 3 => { + Name => 'PanoramaDirection', + PrintConv => { + 0 => 'Left or Up', + 1 => 'Right or Down', + }, + }, + # crop area to remove black/gray borders from full image + 4 => 'PanoramaCropLeft', + 5 => 'PanoramaCropTop', #PH guess (NC) + 6 => 'PanoramaCropRight', + 7 => 'PanoramaCropBottom', + # 8: 1728 (HX1), 1824 (HX5/TX7) (value8/value9 = 16/9) + 8 => 'PanoramaFrameWidth', #PH guess (NC) + # 9: 972 (HX1), 1026 (HX5/TX7) + 9 => 'PanoramaFrameHeight', #PH guess (NC) + # 10: 3200-3800 (HX1), 4000-4900 (HX5/TX7) + 10 => 'PanoramaSourceWidth', #PH guess (NC) + # 11: 800-1800 (larger for taller panoramas) + 11 => 'PanoramaSourceHeight', #PH guess (NC) + # 12-15: 0 +); + +# tag table for SRF0 IFD (ref 1) +%Image::ExifTool::Sony::SRF = ( + PROCESS_PROC => \&ProcessSRF, + GROUPS => { 0 => 'MakerNotes', 1 => 'SRF#', 2 => 'Camera' }, + NOTES => q{ + The maker notes in SRF (Sony Raw Format) images contain 7 IFD's with family + 1 group names SRF0 through SRF6. SRF0 and SRF1 use the tags in this table, + while SRF2 through SRF5 use the tags in the next table, and SRF6 uses + standard EXIF tags. All information other than SRF0 is encrypted, but + thanks to Dave Coffin the decryption algorithm is known. SRF images are + written by the Sony DSC-F828 and DSC-V3. + }, + # tags 0-1 are used in SRF1 + 0 => { + Name => 'SRF2Key', + Notes => 'key to decrypt maker notes from the start of SRF2', + RawConv => '$$self{SRF2Key} = $val', + }, + 1 => { + Name => 'DataKey', + Notes => 'key to decrypt the rest of the file from the end of the maker notes', + RawConv => '$$self{SRFDataKey} = $val', + }, + # SRF0 contains a single unknown tag with TagID 0x0003 +); + +# tag table for Sony RAW Format (ref 1) +%Image::ExifTool::Sony::SRF2 = ( + PROCESS_PROC => \&ProcessSRF, + GROUPS => { 0 => 'MakerNotes', 1 => 'SRF#', 2 => 'Camera' }, + NOTES => "These tags are found in the SRF2 through SRF5 IFD's.", + # the following tags are used in SRF2-5 + 2 => 'SRF6Offset', #PH + # SRFDataOffset references 2220 bytes of unknown data for the DSC-F828 - PH + 3 => { Name => 'SRFDataOffset', Unknown => 1 }, #PH + 4 => { Name => 'RawDataOffset' }, #PH + 5 => { Name => 'RawDataLength' }, #PH + 0x0043 => 'MaxApertureAtMaxFocal', #IB + 0x0044 => 'MaxApertureAtMinFocal', #IB + 0x0045 => { #IB + Name => 'MinFocalLength', + PrintConv => '"$val mm"', + }, + 0x0046 => { #IB + Name => 'MaxFocalLength', + PrintConv => '"$val mm"', + }, + 0x00c0 => 'WBRedDaylight', #IB + 0x00c1 => 'WBGreenDaylight', #IB + 0x00c2 => 'WBBlueDaylight', #IB + 0x00c3 => 'WBRedCloudy', #IB + 0x00c4 => 'WBGreenCloudy', #IB + 0x00c5 => 'WBBlueCloudy', #IB + 0x00c6 => 'WBRedFluorescent', #IB + 0x00c7 => 'WBGreenFluorescent', #IB + 0x00c8 => 'WBBlueFluorescent', #IB + 0x00c9 => 'WBRedTungsten', #IB + 0x00ca => 'WBGreenTungsten', #IB + 0x00cb => 'WBBlueTungsten', #IB + 0x00cc => 'WBRedFlash', #IB + 0x00cd => 'WBGreenFlash', #IB + 0x00ce => 'WBBlueFlash', #IB + 0x00d0 => 'WBRedAsShot', #IB + 0x00d1 => 'WBGreenAsShot', #IB + 0x00d2 => 'WBBlueAsShot', #IB +); + +# tag table for Sony RAW 2 Format Private IFD (ref 1) +%Image::ExifTool::Sony::SR2Private = ( + PROCESS_PROC => \&ProcessSR2, + WRITE_PROC => \&WriteSR2, + GROUPS => { 0 => 'MakerNotes', 1 => 'SR2', 2 => 'Camera' }, + NOTES => q{ + The SR2 format uses the DNGPrivateData tag to reference a private IFD + containing these tags. SR2 images are written by the Sony DSC-R1, but + this information is also written to ARW images by other models. + }, + 0x7200 => { + Name => 'SR2SubIFDOffset', + # (adjusting offset messes up calculations for AdobeSR2 in DNG images) + # Flags => 'IsOffset', + # (can't set OffsetPair or else DataMember won't be set when writing) + # OffsetPair => 0x7201, + DataMember => 'SR2SubIFDOffset', + RawConv => '$$self{SR2SubIFDOffset} = $val', + }, + 0x7201 => { + Name => 'SR2SubIFDLength', + # (can't set OffsetPair or else DataMember won't be set when writing) + # OffsetPair => 0x7200, + DataMember => 'SR2SubIFDLength', + RawConv => '$$self{SR2SubIFDLength} = $val', + }, + 0x7221 => { + Name => 'SR2SubIFDKey', + Format => 'int32u', + Notes => 'key to decrypt SR2SubIFD', + DataMember => 'SR2SubIFDKey', + RawConv => '$$self{SR2SubIFDKey} = $val', + PrintConv => 'sprintf("0x%.8x", $val)', + }, + 0x7240 => { #PH + Name => 'IDC_IFD', + Groups => { 1 => 'SonyIDC' }, + Condition => '$$valPt !~ /^\0\0\0\0/', # (just in case this could be zero) + Flags => 'SubIFD', + SubDirectory => { + DirName => 'SonyIDC', + TagTable => 'Image::ExifTool::SonyIDC::Main', + Start => '$val', + }, + }, + 0x7241 => { #PH + Name => 'IDC2_IFD', + Groups => { 1 => 'SonyIDC' }, + Condition => '$$valPt !~ /^\0\0\0\0/', # may be zero if dir doesn't exist + Flags => 'SubIFD', + SubDirectory => { + DirName => 'SonyIDC2', + TagTable => 'Image::ExifTool::SonyIDC::Main', + Start => '$val', + Base => '$start', + MaxSubdirs => 20, # (A900 has 10 null entries, but IDC writes only 1) + RelativeBase => 1, # needed to write SubIFD with relative offsets + }, + }, + 0x7250 => { #1 + Name => 'MRWInfo', + Condition => '$$valPt !~ /^\0\0\0\0/', # (just in case this could be zero) + SubDirectory => { + TagTable => 'Image::ExifTool::MinoltaRaw::Main', + }, + }, +); + +%Image::ExifTool::Sony::SR2SubIFD = ( + WRITE_PROC => \&Image::ExifTool::Exif::WriteExif, + CHECK_PROC => \&Image::ExifTool::Exif::CheckExif, + GROUPS => { 0 => 'MakerNotes', 1 => 'SR2SubIFD', 2 => 'Camera' }, + SET_GROUP1 => 1, # set group1 name to directory name for all tags in table + NOTES => 'Tags in the encrypted SR2SubIFD', + 0x7300 => 'BlackLevel', #IB (R1) + 0x7302 => 'WB_GRBGLevelsAuto', #IB (R1) + 0x7303 => 'WB_GRBGLevels', #1 (R1 "as shot", ref IB) + 0x7310 => 'BlackLevel', #IB (divide by 4) + 0x7312 => 'WB_RGGBLevelsAuto', #IB + 0x7313 => 'WB_RGGBLevels', #6 + 0x7480 => 'WB_RGBLevelsDaylight', #IB (R1) + 0x7481 => 'WB_RGBLevelsCloudy', #IB (R1) + 0x7482 => 'WB_RGBLevelsTungsten', #IB (R1) + 0x7483 => 'WB_RGBLevelsFlash', #IB (R1) + 0x7484 => 'WB_RGBLevels4500K', #IB (R1) + 0x7486 => 'WB_RGBLevelsFluorescent', #IB (R1) + 0x74a0 => 'MaxApertureAtMaxFocal', #PH + 0x74a1 => 'MaxApertureAtMinFocal', #PH + 0x74a2 => { #IB (R1) + Name => 'MaxFocalLength', + PrintConv => '"$val mm"', + }, + 0x74a3 => { #IB (R1) + Name => 'MinFocalLength', + PrintConv => '"$val mm"', + }, + 0x74c0 => { #PH + Name => 'SR2DataIFD', + Groups => { 1 => 'SR2DataIFD' }, # (needed to set SubIFD DirName) + Flags => 'SubIFD', + SubDirectory => { + TagTable => 'Image::ExifTool::Sony::SR2DataIFD', + Start => '$val', + MaxSubdirs => 20, # an A700 ARW has 14 of these! - PH + }, + }, + 0x7800 => 'ColorMatrix', #IB (divide by 1024) + 0x7820 => 'WB_RGBLevelsDaylight', #6 (or 5300K, ref IB) + 0x7821 => 'WB_RGBLevelsCloudy', #6 (or 6100K, ref IB) + 0x7822 => 'WB_RGBLevelsTungsten', #6 + 0x7823 => 'WB_RGBLevelsFlash', #IB + 0x7824 => 'WB_RGBLevels4500K', #IB + 0x7825 => 'WB_RGBLevelsShade', #6 (or 7500K, ref IB) + 0x7826 => 'WB_RGBLevelsFluorescent', #6 (~4000K) + 0x7827 => 'WB_RGBLevelsFluorescentP1', #IB (~5000K) + 0x7828 => 'WB_RGBLevelsFluorescentP2', #IB (~6500K) (was Flash, ref 6) + 0x7829 => 'WB_RGBLevelsFluorescentM1', #IB (~3500K) + 0x782a => 'WB_RGBLevels8500K', #IB + 0x782b => 'WB_RGBLevels6000K', #IB + 0x782c => 'WB_RGBLevels3200K', #IB + 0x782d => 'WB_RGBLevels2500K', #IB + 0x787f => 'WhiteLevel', #IB (divide by 4) + 0x797d => 'VignettingCorrParams', #forum7640 + 0x7980 => 'ChromaticAberrationCorrParams', #forum6509 (Sony A7 ARW) + 0x7982 => 'DistortionCorrParams', #forum6509 (Sony A7 ARW) +); + +%Image::ExifTool::Sony::SR2DataIFD = ( + WRITE_PROC => \&Image::ExifTool::Exif::WriteExif, + CHECK_PROC => \&Image::ExifTool::Exif::CheckExif, + GROUPS => { 0 => 'MakerNotes', 1 => 'SR2DataIFD', 2 => 'Camera' }, + SET_GROUP1 => 1, # set group1 name to directory name for all tags in table + # 0x7313 => 'WB_RGGBLevels', (duplicated in all SR2DataIFD's) + 0x7770 => { #PH + Name => 'ColorMode', + Priority => 0, + }, +); + +# extract information from "SONY PIC\0" maker notes (ref PH) +%Image::ExifTool::Sony::PIC = ( + PROCESS_PROC => \&ProcessSonyPIC, + GROUPS => { 0 => 'MakerNotes', 2 => 'Camera' }, + NOTES => q{ + The TextInfo data is extracted as a block to preserve the formatting, and + some of the more interesting information is extracted as separate tags. + }, + TextInfo1 => { Binary => 1 }, + TextInfo2 => { Binary => 1 }, + # tags extracted from TextInfo blocks (ID's must end with ':') + 'Temp:' => { + Name => 'CameraTemperature', + RawConv => '$val =~ /^-?\d+/ ? $val : undef', + PrintConv => '"$val C"', + }, + 'Temp:Clbt:' => { Name => 'BoardTemperature', PrintConv => '"$val C"' }, #(NC) + 'Capt:' => { Name => 'SensorTemperature', PrintConv => '"$val C"' }, #(NC) + 'VR Enable C:' => { + Name => 'VibrationReduction', + PrintConv => { 0 => 'Off', 1 => 'On' }, #(NC) + }, + 'FWVer:' => 'FirmwareVersion', + 'BC:' => { + Name => 'Barcode', + Condition => 'not $$self{VALUE}{Barcode}', + ValueConv => '$val=~s/IP1.*//; $val', + }, + 'barcode:' => 'Barcode', + 'BarCode:' => { + Name => 'Barcode', + ValueConv => 'length($val) > 12 ? substr($val,0,12) : $val', + }, + # 'EvA:' - exposure compensation * 10 (ref JR) + # IFD: for documentation only -- this IFD is handled manually + IFD => { + Name => 'PIC_IFD', + SubDirectory => { TagTable => 'Image::ExifTool::Sony::Main' }, + }, +); + +# tags found in DSC-F1 PMP header (ref 10) +%Image::ExifTool::Sony::PMP = ( + PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData, + GROUPS => { 0 => 'MakerNotes', 2 => 'Image' }, + FIRST_ENTRY => 0, + NOTES => q{ + These tags are written in the proprietary-format header of PMP images from + the DSC-F1. + }, + 8 => { #PH + Name => 'JpgFromRawStart', + Format => 'int32u', + Notes => q{ + OK, not really a RAW file, but this mechanism is used to allow extraction of + the JPEG image from a PMP file + }, + }, + 12 => { Name => 'JpgFromRawLength', Format => 'int32u' }, + 22 => { Name => 'SonyImageWidth', Format => 'int16u' }, + 24 => { Name => 'SonyImageHeight', Format => 'int16u' }, + 27 => { + Name => 'Orientation', + PrintConv => { + 0 => 'Horizontal (normal)', + 1 => 'Rotate 270 CW',#11 + 2 => 'Rotate 180', + 3 => 'Rotate 90 CW',#11 + }, + }, + 29 => { + Name => 'ImageQuality', + PrintConv => { + 8 => 'Snap Shot', + 23 => 'Standard', + 51 => 'Fine', + }, + }, + # 40 => ImageWidth again (int16u) + # 42 => ImageHeight again (int16u) + 52 => { Name => 'Comment', Format => 'string[19]' }, + 76 => { + Name => 'DateTimeOriginal', + Description => 'Date/Time Original', + Format => 'int8u[6]', + Groups => { 2 => 'Time' }, + ValueConv => q{ + my @a = split ' ', $val; + $a[0] += $a[0] < 70 ? 2000 : 1900; + sprintf('%.4d:%.2d:%.2d %.2d:%.2d:%.2d', @a); + }, + PrintConv => '$self->ConvertDateTime($val)', + }, + 84 => { + Name => 'ModifyDate', + Format => 'int8u[6]', + Groups => { 2 => 'Time' }, + ValueConv => q{ + my @a = split ' ', $val; + $a[0] += $a[0] < 70 ? 2000 : 1900; + sprintf('%.4d:%.2d:%.2d %.2d:%.2d:%.2d', @a); + }, + PrintConv => '$self->ConvertDateTime($val)', + }, + 102 => { + Name => 'ExposureTime', + Format => 'int16s', + RawConv => '$val <= 0 ? undef : $val', + ValueConv => '2 ** (-$val / 100)', + PrintConv => 'Image::ExifTool::Exif::PrintExposureTime($val)', + }, + 106 => { # (NC -- not written by DSC-F1) + Name => 'FNumber', + Format => 'int16s', + RawConv => '$val <= 0 ? undef : $val', + ValueConv => '$val / 100', # (likely wrong) + }, + 108 => { # (NC -- not written by DSC-F1) + Name => 'ExposureCompensation', + Format => 'int16s', + RawConv => '($val == -1 or $val == -32768) ? undef : $val', + ValueConv => '$val / 100', # (probably wrong too) + }, + 112 => { # (NC -- not written by DSC-F1) + Name => 'FocalLength', + Format => 'int16s', + Groups => { 2 => 'Camera' }, + RawConv => '$val <= 0 ? undef : $val', + ValueConv => '$val / 100', + PrintConv => 'sprintf("%.1f mm",$val)', + }, + 118 => { + Name => 'Flash', + Groups => { 2 => 'Camera' }, + PrintConv => { 0 => 'No Flash', 1 => 'Fired' }, + }, +); + +# tags found in 'rtmd' timed metadata in ILCE-7S/DSC-RX100M6 MP4 videos (ref PH) +%Image::ExifTool::Sony::rtmd = ( + PROCESS_PROC => \&Process_rtmd, + GROUPS => { 2 => 'Video' }, + NOTES => q{ + These tags are extracted from the 'rtmd' timed metadata of MP4 videos from + some models when the ExtractEmbedded option is used. + }, + # 0x060e - 16 bytes starting with 0x060e2b340253 (fake tag ID - comes before 0x8300 container) + 0x060e => { Name => 'Sony_rtmd_0x060e', Format => 'int8u', %hidUnk }, + # 0x32xx - 16 bytes starting with 0x060e2b340401 + 0x3210 => { Name => 'Sony_rtmd_0x3210', Format => 'int8u', %hidUnk }, + 0x3219 => { Name => 'Sony_rtmd_0x3219', Format => 'int8u', %hidUnk }, + 0x321a => { Name => 'Sony_rtmd_0x321a', Format => 'int8u', %hidUnk }, + 0x8000 => { Name => 'Sony_rtmd_0x8000', Format => 'int16u', %hidUnk }, + 0x8001 => { Name => 'Sony_rtmd_0x8001', Format => 'int16u', %hidUnk }, + # 0x8100 - 16 bytes starting with 0x060e2b340401 + 0x8100 => { Name => 'Sony_rtmd_0x8100', Format => 'int8u', %hidUnk }, + 0x8101 => { Name => 'Sony_rtmd_0x8101', Format => 'int8u', %hidUnk }, # seen: 0,1 + 0x8109 => { Name => 'Sony_rtmd_0x8109', Format => 'int32u', %hidUnk }, # seen: "1 50" + 0x810a => { Name => 'Sony_rtmd_0x810a', Format => 'int16u', %hidUnk }, # seen: 0 + 0x810b => { Name => 'Sony_rtmd_0x810b', Format => 'int16u', %hidUnk }, # seen: 100 + 0x810c => { Name => 'Sony_rtmd_0x810c', Format => 'int16u', %hidUnk }, # seen: 100 + 0x810d => { Name => 'Sony_rtmd_0x810d', Format => 'int8u', %hidUnk }, # seen: 1 + # 0x8300 - container for other tags in this format + 0xe000 => { Name => 'Sony_rtmd_0xe000', Format => 'int8u', %hidUnk }, # (16 bytes) + 0xe300 => { Name => 'Sony_rtmd_0xe300', Format => 'int8u', %hidUnk }, # seen: 0,1 + 0xe301 => { Name => 'Sony_rtmd_0xe301', Format => 'int32u', %hidUnk }, # seen: 100 + 0xe302 => { Name => 'Sony_rtmd_0xe302', Format => 'int8u', %hidUnk }, # seen: 1 + 0xe303 => { Name => 'Sony_rtmd_0xe303', Format => 'int8u', %hidUnk }, # seen: 255 + 0xe304 => { + Name => 'DateTime', + Groups => { 2 => 'Time' }, + Format => 'undef', + ValueConv => 'my @a=unpack("x1H4H2H2H2H2H2",$val); "$a[0]:$a[1]:$a[2] $a[3]:$a[4]:$a[5]"', + PrintConv => '$self->ConvertDateTime($val)', + }, +); + +# Composite Sony tags +%Image::ExifTool::Sony::Composite = ( + GROUPS => { 2 => 'Camera' }, + FocusDistance => { + Require => { + 0 => 'Sony:FocusPosition', + 1 => 'FocalLength', + }, + Notes => 'distance in metres = FocusPosition * FocalLength / 1000', + ValueConv => '$val >= 128 ? "inf" : $val * $val[1] / 1000', + PrintConv => '$val eq "inf" ? $val : "$val m"', + }, + FocusDistance2 => { + # For DSLR-A550 and newer, NEX/ILCE/SLT/ILCA (only A65V/A77V are missing ...): + # seen FocusPosition2 with values from 80 - 255 (and 21 for Touit 12mm...) + # Formula from minolta.pm (WBInfoA100 - 0x49bb) gives mostly correct/acceptable distance indications. + # (http://u88.n24.queensu.ca/exiftool/forum/index.php/topic,3688.0.html) + # if this value is the 35mm equivalent magnification, then the formula could + # be (1.5 * 2**($val/16-5)+1) * FocalLength, but this tends to underestimate + # distance by about 18% (ref 20) (255=inf) + # modified 16-10-2014 based on A99V measurements: use FocalLengthIn35mmFormat and leave out the "1.5*" factor. + Require => { + 0 => 'Sony:FocusPosition2', + 1 => 'FocalLengthIn35mmFormat', + }, + ValueConv => q{ + return undef unless $val; + return 'inf' if $val >= 255; + return (2**($val/16-5) + 1) * $val[1] / 1000; + }, + PrintConv => '$val eq "inf" ? $val : sprintf("%.2f m",$val)', + }, +); + +# add our composite tags +Image::ExifTool::AddCompositeTags('Image::ExifTool::Sony'); + +sub SortLensTypes +{ + return $a <=> $b unless $a =~ /\./ and $b =~ /\./; + my @a = split /\./, $a; + my @b = split /\./, $b; + # must compare the decimal part separately to sort in proper order + return $a[0] <=> $b[0] || $a[1] <=> $b[1]; +} + +# fill in Sony LensType lookup based on Minolta values +{ + my $minoltaTypes = \%Image::ExifTool::Minolta::minoltaLensTypes; + %sonyLensTypes = %$minoltaTypes; + my $other = $$minoltaTypes{OTHER}; + delete $$minoltaTypes{Notes}; # (temporarily) + delete $$minoltaTypes{OTHER}; # (temporarily) + my $id; + # 5-digit lens ID's are missing the last digit (usually "1") in the metadata for + # some Sony models, so generate corresponding 4-digit entries for these cameras + foreach $id (sort SortLensTypes keys %$minoltaTypes) { + next if $id < 10000; + my $sid = int($id/10); + my $i; + my $lens = $$minoltaTypes{$id}; + if ($sonyLensTypes{$sid}) { + # put lens name with "or" first in list + if ($lens =~ / or /) { + my $tmp = $sonyLensTypes{$sid}; + $sonyLensTypes{$sid} = $lens; + $lens = $tmp; + } + for (;;) { + $i = ($i || 0) + 1; + $sid = int($id/10) . ".$i"; + last unless $sonyLensTypes{$sid}; + } + } + $sonyLensTypes{$sid} = $lens; + } + $$minoltaTypes{Notes} = $sonyLensTypes{Notes}; # (restore original Notes) + $$minoltaTypes{OTHER} = $other; +} + +#------------------------------------------------------------------------------ +# Process "SONY PIC\0" maker notes (DSC-H200/J10/W370/W510, MHS-TS20, ref PH) +# Inputs: 0) ExifTool object ref, 1) dirInfo ref, 2) tag table ref +# Returns: 1 +sub ProcessSonyPIC($$$) +{ + my ($et, $dirInfo, $tagTablePtr) = @_; + my $dataPt = $$dirInfo{DataPt}; + my $start = $$dirInfo{DirStart} || 0; + my $len = $$dirInfo{DirLen} || (length($$dataPt) - $start); + my $data = substr($$dataPt, $start, $len); + + # H200 panorama images have an IFD at offset 12 (non-panoramas have 0's here) + # - assume other images could too, but do a bit of validation to check + # - MHS-TS20 images have some other data here + if ($len >= 26) { + my $count = Get16u($dataPt, $start + 12); + if ($count > 256) { + ToggleByteOrder(); + $count = Get16u($dataPt, $start + 12); + } + if ($count and $count < 256) { + my $format = Get16u($dataPt, $start + 16); + if ($format >= 1 and $format <= 10) { + $$dirInfo{DirStart} = $start + 12; + $$dirInfo{DirLen} = $len - 12; + my $sonyTable = GetTagTable('Image::ExifTool::Sony::Main'); + Image::ExifTool::Exif::ProcessExif($et, $dirInfo, $sonyTable); + } + } + } + # Do a brute force search for text data: + # For the DSC-J10/W370/W510 the first text block is at offset 0x1ec and + # starts with "BarCode:". For the H200 it is at 0x1f0 and starts with "BC:". + # For the TS20 it is at 0x5b and starts with "V400 AELOG\nbarcode:". + # The second text block starts with "AFLOG" (Auto-Focus log) and is at + # 0x600 for all models, except for the TS20 it is at 0x45b. + my $i = 0; + while ($data =~ /(\w[\x09\x0a\x0d\x20-\x7e]+)/sg) { + next unless length $1 > 32; + my ($tag, $val) = ('TextInfo' . (++$i), $1); + $$tagTablePtr{$tag} or AddTagToTable($tagTablePtr, $tag, { Name => $tag, Binary => 1 }); + $et->HandleTag($tagTablePtr, $tag, $val); + # extract interesting tags separately (might want to speed this up) + foreach $tag (sort { lc $a cmp lc $b } keys %$tagTablePtr) { + next unless $tag =~ /:$/ and $val =~ /\b$tag\s*([^\s;,:]+)/; + $et->HandleTag($tagTablePtr, $tag, $1); + } + } + return 1; +} + +#------------------------------------------------------------------------------ +# MeterInfo value conversions +# Inputs: 0) value +# Returns: converted value +sub ConvMeter1($) +{ + my $val = shift; + return \$val unless length($val) == 90; + my @a = unpack("SLLSLLSLLSLLSLLSLLSLLSLLSLL",$val); + return join ' ', @a; +} +sub ConvMeter2($) +{ + my $val = shift; + return \$val unless length($val) == 110; + my @a = unpack("SLLSLLSLLSLLSLLSLLSLLSLLSLLSLLSLL",$val); + return join ' ', @a; +} + +#------------------------------------------------------------------------------ +# LensSpec value conversions +# Inputs: 0) value +# Returns: converted value +# Notes: unpacks in format compatible with LensInfo, with extra flags bytes at start and end +sub ConvLensSpec($) +{ + my $val = shift; + return \$val unless length($val) == 8; + my @a = unpack("H2H4H4H2H2H2",$val); + $a[1] += 0; $a[2] += 0; # remove leading zeros from focal lengths + s/([a-f])/hex($1)/e foreach @a[3,4]; # convert hex digits (ie. "b0" = f11) + $a[3] /= 10; $a[4] /= 10; # divide f-numbers by 10 + return join ' ', @a; +} +sub ConvInvLensSpec($) +{ + my $val = shift; + my @a=split(" ", $val); + return $val unless @a == 6; + $a[3] *= 10; $a[4] *= 10; # f-numbers are multiplied by 10 + s/^(\d{2})0$/sprintf('%x0',$1)/e foreach @a[3,4]; + $_ = hex foreach @a; # convert from hex + return pack 'CnnCCC', @a; +} + +#------------------------------------------------------------------------------ +# Print Sony LensSpec value +# Inputs: 0) LensSpec numerical value +# Returns: converted LensSpec string (eg. "DT 18-55mm F3.5-5.6 SAM") +# Refs: http://equational.org/importphotos/alphalensinfo.html +# http://www.dyxum.com/dforum/the-lens-information-different-from-lensid_topic37682.html +my @lensFeatures = ( + # lens features in the order they are added to the LensSpec string + # (high byte of Mask/Bits represents byte 0 of LensSpec, low byte is byte 7) + # Mask { Bits Name Bits Name } Prefix flag + # ------ ------ ----- ------ ----- ----------- + [ 0x4000, { 0x4000 => 'PZ' }, 1 ], + [ 0x0300, { 0x0100 => 'DT', 0x0200 => 'FE', 0x0300 => 'E' }, 1 ], # (will come before preceding prefix), FE added (ref JR) + [ 0x00e0, { 0x0020 => 'STF', 0x0040 => 'Reflex', 0x0060 => 'Macro', 0x0080 => 'Fisheye' } ], + [ 0x000c, { 0x0004 => 'ZA', 0x0008 => 'G' } ], + [ 0x0003, { 0x0001 => 'SSM', 0x0002 => 'SAM' } ], + [ 0x8000, { 0x8000 => 'OSS' } ], + [ 0x2000, { 0x2000 => 'LE' } ], #JR + [ 0x0800, { 0x0800 => 'II' } ], #JR +); +sub PrintLensSpec($) +{ + my $val = shift; + my ($rtnVal, $feature, $f1, $sf, $lf, $sa, $la, $f2); + # 0=flags1, 1=short focal, 2=long focal, 3=max aperture at short focal, + # 4=max aperture at long focal, 5=flags2 + my @a = split ' ', $val; + if (@a == 2) { # LensSpecFeatures patch + ($f1, $f2) = @a; + $rtnVal = ''; + } elsif (@a >= 6) { + ($f1, $sf, $lf, $sa, $la, $f2) = @a; + # crude validation of focal length and aperture values + if ($sf != 0 and $sa != 0 and ($lf == 0 or $lf >= $sf) and ($la == 0 or $la >= $sa)) { + # use focal and aperture range if this is a zoom lens + $sf .= '-' . $lf if $lf != $sf and $lf != 0; + $sa .= '-' . $la if $sa != $la and $la != 0; + $rtnVal = "${sf}mm F$sa"; # heart of LensSpec is a LensInfo string + } + } + if (defined $rtnVal) { + # loop through available lens features + my $flags = hex($f1 . $f2); + foreach $feature (@lensFeatures) { + my $bits = $$feature[0] & $flags; + next unless $bits or $$feature[1]{$bits}; + # add feature name as a prefix or suffix to the LensSpec + my $str = $$feature[1]{$bits} || sprintf('Unknown(%.4x)',$bits); + $rtnVal = $rtnVal ? ($$feature[2] ? "$str $rtnVal" : "$rtnVal $str") : $str; + } + } else { + $rtnVal = "Unknown ($val)"; + } + return $rtnVal; +} +# inverse conversion +sub PrintInvLensSpec($;$$) +{ + my ($val, $self, $features) = @_; + return $1 if $val =~ /Unknown \((.*)\)/i; + my ($sf, $lf, $sa, $la) = Image::ExifTool::Exif::GetLensInfo($val); + my $str; + if ($features) { + $str = ''; + } elsif ($sf) { + # fixed focal length and aperture have zero for 2nd number + $lf = 0 if $lf == $sf; + $la = 0 if $la == $sa; + $str = " $sf $lf $sa $la"; + } else { + return undef; + } + my $flags = 0; + my ($feature, $bits); + foreach $feature (@lensFeatures) { + foreach $bits (keys %{$$feature[1]}) { + # set corresponding flag bits for each feature name found + my $name = $$feature[1]{$bits}; + $val =~ /\b$name\b/i and $flags |= $bits; + } + } + return sprintf "%.2x$str %.2x", $flags>>8, $flags&0xff; +} + +#------------------------------------------------------------------------------ +# Read/Write MoreInfo information (tag 0x0020, count 20480) +# Inputs: 0) ExifTool object ref, 1) dirInfo ref, 2) tag table ref +# Returns: 1 on success when reading, or new directory when writing (IsWriting set) +sub ProcessMoreInfo($$$) +{ + my ($et, $dirInfo, $tagTablePtr) = @_; + $et or return 1; # allow dummy access to write routine + my $dataPt = $$dirInfo{DataPt}; + my $start = $$dirInfo{DirStart} || 0; + my $dirLen = $$dirInfo{DirLen} || length($$dataPt); + my $isWriting = $$dirInfo{IsWriting}; + my $rtnVal = $isWriting ? undef : 0; + return $rtnVal if $dirLen < 4; + + my $num = Get16u($dataPt, $start); # number of entries + my $len = Get16u($dataPt, $start + 2); # total data length + + if ($dirLen < 4 + $num * 4) { + $et->Warn('Truncated MoreInfo data', 1); + return $rtnVal; + } + if ($num > 50) { + $et->Warn('Possibly corrupted MoreInfo data', 1); + return $rtnVal; + } + + $et->VerboseDir('MoreInfo', $num, $len) unless $isWriting; + + if ($len > $dirLen) { + $et->Warn('MoreInfo data length too large', 1); + $len = $dirLen; + } + # loop through the MoreInfo index section to get the block offsets and tag ID's + # (in case they are out of order, even though this may never happen) + my ($i, @offset, @tagID, %blockSize); + for ($i=0; $i<$num; ++$i) { + my $entry = $start + 4 + $i * 4; + push @tagID, Get16u($dataPt, $entry); + push @offset, Get16u($dataPt, $entry + 2); + if ($offset[-1] > $len and $offset[-1] <= $dirLen) { + $et->Warn('MoreInfo data length too small', 1); + $len = $dirLen; + } + } + # generate a lookup table of block sizes + my @sorted = sort { $a <=> $b } @offset; + push @sorted, 0xffff; # (simplifies logic in loop below) + for ($i=0; $i<$num; ++$i) { + my $offset = $sorted[$i]; + my $size = $sorted[$i+1] - $offset; + # note that block size will be negative for blocks with starting + # offsets greater than $dirLen, but we will ignore these below + $size = $len - $offset if $size > $len - $offset; + # (if blockSize is already defined for this offset, then there + # are 2 blocks with the same starting offset and the existing + # size must be zero. Since we can't know which block is + # actually non-zero size, the reasonable thing to do is + # assume that both have a size of zero) + $blockSize{$offset} = $size unless defined $blockSize{$offset}; + } + # initialize successful return value + $rtnVal = $isWriting ? substr($$dataPt, $start, $dirLen) : 1; + # now process each block + my $unknown = $$et{OPTIONS}{Unknown}; + for ($i=0; $i<$num; ++$i) { + next if $offset[$i] > $dirLen; # ignore bad offsets + my $tag = $tagID[$i]; + if ($isWriting) { + # write new tags + my $tagInfo = $$tagTablePtr{$tag}; + next unless ref $tagInfo eq 'HASH' and $$tagInfo{SubDirectory}; + my $offset = $offset[$i]; + my $size = $blockSize{$offset}; + next unless $size; # ignore zero-length blocks + my %dirInfo = ( + DirName => $$tagInfo{Name}, + Parent => $$dirInfo{DirName}, + DataPt => \$rtnVal, + DirStart => $offset, + DirLen => $size, + ); + my $subTable = GetTagTable($$tagInfo{SubDirectory}{TagTable}); + my $val = $et->WriteDirectory(\%dirInfo, $subTable); + # update this block in the returned MoreInfo data + substr($rtnVal, $offset, $size) = $val if defined $val; + next; + } + # generate binary tables for unknown tags if -U option used + if (not defined $$tagTablePtr{$tag} and $unknown > 1) { + my $name = sprintf('MoreInfo%.4x', $tag); + my $table = "Image::ExifTool::Sony::$name"; + no strict 'refs'; + %$table = ( + PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData, + FIRST_ENTRY => 0, + GROUPS => { 0 => 'MakerNotes', 2 => 'Image' }, + ); + use strict 'refs'; + my %tagInfo = ( + Name => $name, + SubDirectory => { TagTable => $table }, + ); + AddTagToTable($tagTablePtr, $tag, \%tagInfo); + } + $et->HandleTag($tagTablePtr, $tag, undef, + Index => $i, + DataPt => $dataPt, + DataPos => $$dirInfo{DataPos}, + Start => $start + $offset[$i], + Size => $blockSize{$offset[$i]}, + ); + } + return $rtnVal; +} + +#------------------------------------------------------------------------------ +# Read Sony DSC-F1 PMP file +# Inputs: 0) ExifTool object ref, 1) dirInfo ref +# Returns: 1 on success when reading, 0 if this isn't a valid PMP file +sub ProcessPMP($$) +{ + my ($et, $dirInfo) = @_; + my $raf = $$dirInfo{RAF}; + my $buff; + $raf->Read($buff, 128) == 128 or return 0; + # validate header length (124 bytes) + $buff =~ /^.{8}\0{3}\x7c.{112}\xff\xd8\xff\xdb$/s or return 0; + $et->SetFileType(); + SetByteOrder('MM'); + $et->FoundTag(Make => 'Sony'); + $et->FoundTag(Model => 'DSC-F1'); + # extract information from 124-byte header + my $tagTablePtr = GetTagTable('Image::ExifTool::Sony::PMP'); + my %dirInfo = ( DataPt => \$buff, DirName => 'PMP' ); + $et->ProcessDirectory(\%dirInfo, $tagTablePtr); + # process JPEG image + $raf->Seek(124, 0); + $$dirInfo{Base} = 124; + $et->ProcessJPEG($dirInfo); + return 1; +} + +#------------------------------------------------------------------------------ +# Set the ARW file type and decide between SubIFD and A100DataOffset +# Inputs: 0) ExifTool object ref, 1) reference to tag 0x14a raw data +# Returns: true if tag 0x14a is a SubIFD, false otherwise +sub SetARW($$) +{ + my ($et, $valPt) = @_; + + # assume ARW for now -- SR2's get identified when FileFormat is parsed + $et->OverrideFileType($$et{TIFF_TYPE} = 'ARW'); + + # this should always be a SubIFD for models other than the A100 + return 1 unless $$et{Model} eq 'DSLR-A100' and length $$valPt == 4; + + # for the A100, IFD0 tag 0x14a is either a pointer to the raw data if this is + # an original image, or a SubIFD offset if the image was edited by Sony IDC, + # so assume it points to the raw data if it isn't a valid IFD (this assumption + # will be checked later when we try to parse the SR2Private directory) + my %subdir = ( + DirStart => Get32u($valPt, 0), + Base => 0, + RAF => $$et{RAF}, + AllowOutOfOrderTags => 1, # doh! + ); + return Image::ExifTool::Exif::ValidateIFD(\%subdir); +} + +#------------------------------------------------------------------------------ +# Finish writing ARW image, patching necessary Sony quirks, etc +# Inputs: 0) ExifTool ref, 1) dirInfo ref, 2) EXIF data ref, 3) image data reference +# Returns: undef on success, error string otherwise +# Notes: (it turns that all of this is for the A100 only) +sub FinishARW($$$$) +{ + my ($et, $dirInfo, $dataPt, $imageData) = @_; + + # pre-scan IFD0 to get IFD entry offsets for each tag + my $dataLen = length $$dataPt; + return 'Truncated IFD0' if $dataLen < 2; + my $n = Get16u($dataPt, 0); + return 'Truncated IFD0' if $dataLen < 2 + 12 * $n; + my ($i, %entry, $dataBlock, $pad, $dataOffset); + for ($i=0; $i<$n; ++$i) { + my $entry = 2 + $i * 12; + $entry{Get16u($dataPt, $entry)} = $entry; + } + # fix up SR2Private offset and A100DataOffset (A100 only) + if ($entry{0xc634} and $$et{MRWDirData}) { + return 'Unexpected MRW block' unless $$et{Model} eq 'DSLR-A100'; + return 'Missing A100DataOffset' unless $entry{0x14a} and $$et{A100DataOffset}; + # account for total length of image data + my $totalLen = 8 + $dataLen; + if (ref $imageData) { + foreach $dataBlock (@$imageData) { + my ($pos, $size, $pad) = @$dataBlock; + $totalLen += $size + $pad; + } + } + # align MRW block on an even 4-byte boundary + my $remain = $totalLen & 0x03; + $pad = 4 - $remain and $totalLen += $pad if $remain; + # set offset for the MRW directory data + Set32u($totalLen, $dataPt, $entry{0xc634} + 8); + # also pad MRWDirData data to an even 4 bytes (just to be safe) + $remain = length($$et{MRWDirData}) & 0x03; + $$et{MRWDirData} .= "\0" x (4 - $remain) if $remain; + $totalLen += length $$et{MRWDirData}; + # fix up A100DataOffset + $dataOffset = $$et{A100DataOffset}; + Set32u($totalLen, $dataPt, $entry{0x14a} + 8); + } + # patch double-referenced and incorrectly-sized A100 PreviewImage + if ($entry{0x201} and $$et{A100PreviewStart} and + $entry{0x202} and $$et{A100PreviewLength}) + { + Set32u($$et{A100PreviewStart}, $dataPt, $entry{0x201} + 8); + Set32u($$et{A100PreviewLength}, $dataPt, $entry{0x202} + 8); + } + # write TIFF IFD structure + my $outfile = $$dirInfo{OutFile}; + my $header = GetByteOrder() . Set16u(0x2a) . Set32u(8); + Write($outfile, $header, $$dataPt) or return 'Error writing'; + # copy over image data + if (ref $imageData) { + $et->CopyImageData($imageData, $outfile) or return 'Error copying image data'; + } + # write MRW data if necessary + if ($$et{MRWDirData}) { + Write($outfile, "\0" x $pad) if $pad; # write padding if necessary + Write($outfile, $$et{MRWDirData}); + delete $$et{MRWDirData}; + # set TIFF_END to copy over the MRW image data + $$et{TIFF_END} = $dataOffset if $dataOffset; + } + return undef; +} + +#------------------------------------------------------------------------------ +# Decrypt/Encrypt Sony data (ref 1) (reversible encryption) +# Inputs: 0) data reference, 1) start offset, 2) data length, 3) decryption key +# Returns: nothing (original data buffer is updated with decrypted data) +# Notes: data length should be a multiple of 4 +sub Decrypt($$$$) +{ + my ($dataPt, $start, $len, $key) = @_; + my ($i, $j, @pad); + my $words = int ($len / 4); + + for ($i=0; $i<4; ++$i) { + my $lo = ($key & 0xffff) * 0x0edd + 1; + my $hi = ($key >> 16) * 0x0edd + ($key & 0xffff) * 0x02e9 + ($lo >> 16); + $pad[$i] = $key = (($hi & 0xffff) << 16) + ($lo & 0xffff); + } + $pad[3] = ($pad[3] << 1 | ($pad[0]^$pad[2]) >> 31) & 0xffffffff; + for ($i=4; $i<0x7f; ++$i) { + $pad[$i] = (($pad[$i-4]^$pad[$i-2]) << 1 | + ($pad[$i-3]^$pad[$i-1]) >> 31) & 0xffffffff; + } + my @data = unpack("x$start N$words", $$dataPt); + for ($i=0x7f,$j=0; $j<$words; ++$i,++$j) { + $data[$j] ^= $pad[$i & 0x7f] = $pad[($i+1) & 0x7f] ^ $pad[($i+65) & 0x7f]; + } + substr($$dataPt, $start, $words*4) = pack('N*', @data); +} + +#------------------------------------------------------------------------------ +# Decipher/encipher Sony tag 0x94xx data (ref PH) +# Inputs: 0) data reference, 1) true to encipher the data +sub Decipher($;$) +{ + my ($dataPt, $encipher) = @_; + # This is a simple substitution cipher, so use a hardcoded translation table for speed. + # The formula is: $c = ($b*$b*$b) % 249, where $c is the enciphered data byte + # (note that bytes with values 249-255 are not translated, and 0-1, 82-84, + # 165-167 and 248 have the same enciphered value) + if ($encipher) { # encipher + $$dataPt =~ tr/\x02-\xf7/\x08\x1b\x40\x7d\xd8\x5e\x0e\xe7\x04V\xea\xcd\x05\x8ap\xb6i\x88\x200\xbe\xd7\x81\xbb\x92\x0c\x28\xecl\xa0\x95Q\xd3\x2f\x5dj\x5c9\x07\xc5\x87L\x1a\xf0\xe2\xef\x24y\x02\xb7\xac\xe0\x60\x2bG\xba\x91\xcbu\x8e\x233\xc4\xe3\x96\xdc\xc2N\x7fb\xf6OeE\xeet\xcf\x138KRST\x5bn\x93\xd02\xb1aAW\xa9D\x27X\xdd\xc3\x10\xbc\xdbs\x83\x181\xd4\x15\xe5_\x7bF\xbf\xf3\xe8\xa4\x2d\x82\xb0\xbd\xaf\x8cZ\x1f\xda\x9fmJ\x3cIw\xccU\x11\x06\x3a\xb3\x7e\x9a\x14\xe4\x25\xc8\xe1v\x86\x1e\x3d\xe96\x1c\xa1\xd2\xb5P\xa2\xb8\x98H\xc7\x29f\x8b\x9e\xa5\xa6\xa7\xae\xc1\xe6\x2a\x85\x0b\xb4\x94\xaa\x03\x97z\xab7\x1dc\x165\xc6\xd6k\x84\x2eh\x3f\xb2\xce\x99\x19MB\xf7\x80\xd5\x0a\x17\x09\xdf\xadr4\xf2\xc0\x9d\x8f\x9c\xca\x26\xa8dY\x8d\x0d\xd1\xedg\x3ex\x22\x3b\xc9\xd9q\x90C\x89o\xf4\x2c\x0f\xa3\xf5\x12\xeb\x9b\x21\x7c\xb9\xde\xf1/; + } else { # decipher + $$dataPt =~ tr/\x08\x1b\x40\x7d\xd8\x5e\x0e\xe7\x04V\xea\xcd\x05\x8ap\xb6i\x88\x200\xbe\xd7\x81\xbb\x92\x0c\x28\xecl\xa0\x95Q\xd3\x2f\x5dj\x5c9\x07\xc5\x87L\x1a\xf0\xe2\xef\x24y\x02\xb7\xac\xe0\x60\x2bG\xba\x91\xcbu\x8e\x233\xc4\xe3\x96\xdc\xc2N\x7fb\xf6OeE\xeet\xcf\x138KRST\x5bn\x93\xd02\xb1aAW\xa9D\x27X\xdd\xc3\x10\xbc\xdbs\x83\x181\xd4\x15\xe5_\x7bF\xbf\xf3\xe8\xa4\x2d\x82\xb0\xbd\xaf\x8cZ\x1f\xda\x9fmJ\x3cIw\xccU\x11\x06\x3a\xb3\x7e\x9a\x14\xe4\x25\xc8\xe1v\x86\x1e\x3d\xe96\x1c\xa1\xd2\xb5P\xa2\xb8\x98H\xc7\x29f\x8b\x9e\xa5\xa6\xa7\xae\xc1\xe6\x2a\x85\x0b\xb4\x94\xaa\x03\x97z\xab7\x1dc\x165\xc6\xd6k\x84\x2eh\x3f\xb2\xce\x99\x19MB\xf7\x80\xd5\x0a\x17\x09\xdf\xadr4\xf2\xc0\x9d\x8f\x9c\xca\x26\xa8dY\x8d\x0d\xd1\xedg\x3ex\x22\x3b\xc9\xd9q\x90C\x89o\xf4\x2c\x0f\xa3\xf5\x12\xeb\x9b\x21\x7c\xb9\xde\xf1/\x02-\xf7/; + } +} + +#------------------------------------------------------------------------------ +# Process Sony 0x94xx cipherdata directory +# Inputs: 0) ExifTool object ref, 1) directory information ref, 2) tag table ref +# Returns: 1 on success +# Notes: +# 1) dirInfo may contain VarFormatData (reference to empty list) to return +# details about any variable-length-format tags in the table (used when writing) +# 2) A bug in ExifTool 9.04-9.10 could have double-enciphered these blocks +sub ProcessEnciphered($$$) +{ + my ($et, $dirInfo, $tagTablePtr) = @_; + my $dataPt = $$dirInfo{DataPt}; + my $dirStart = $$dirInfo{DirStart} || 0; + my $dirLen = $$dirInfo{DirLen} || (length($$dataPt) - $dirStart); + my $data = substr($$dataPt, $dirStart, $dirLen); + my %dirInfo = ( + %$dirInfo, + DataPt => \$data, + DataPos => $$dirInfo{DataPos} + $dirStart, + DirStart => 0, + ); + Decipher(\$data); + if ($$et{DoubleCipher}) { + Decipher(\$data); + $et->WarnOnce('Some Sony metadata is double-enciphered. Write any tag to fix',1); + } + if ($et->Options('Verbose') > 2) { + my $tagInfo = $$dirInfo{TagInfo} || { Name => 'data' }; + my $str = $$et{DoubleCipher} ? 'ouble-d' : ''; + $et->VerboseDir("D${str}eciphered $$tagInfo{Name}"); + $et->VerboseDump(\$data, + Prefix => $$et{INDENT} . ' ', + DataPos => $$dirInfo{DirStart} + $$dirInfo{DataPos} + ($$dirInfo{Base} || 0), + ); + } + return $et->ProcessBinaryData(\%dirInfo, $tagTablePtr); +} + +#------------------------------------------------------------------------------ +# Write Sony 0x94xx cipherdata directory +# Inputs: 0) ExifTool object ref, 1) source dirInfo ref, 2) tag table ref +# Returns: cipherdata block or undefined on error +sub WriteEnciphered($$$) +{ + my ($et, $dirInfo, $tagTablePtr) = @_; + $et or return 1; + my $dataPt = $$dirInfo{DataPt}; + my $dirStart = $$dirInfo{DirStart} || 0; + my $dirLen = $$dirInfo{DirLen} || (length($$dataPt) - $dirStart); + my $data = substr($$dataPt, $dirStart, $dirLen); + my $changed = $$et{CHANGED}; + Decipher(\$data); + # fix double-enciphered data (due to bug in ExifTool 9.04-9.10) + if ($$et{DoubleCipher}) { + Decipher(\$data); + ++$$et{CHANGED}; + $et->WarnOnce('Fixed double-enciphered Sony metadata',1); + } + my %dirInfo = ( + %$dirInfo, + DataPt => \$data, + DataPos => $$dirInfo{DataPos} + $dirStart, + DirStart => 0, + ); + $data = $et->WriteBinaryData(\%dirInfo, $tagTablePtr); + if ($changed == $$et{CHANGED}) { + # nothing changed, so recover original data + $data = substr($$dataPt, $dirStart, $dirLen); + } elsif (defined $data) { + Decipher(\$data,1); # re-encipher + } + return $data; +} + +#------------------------------------------------------------------------------ +# Process "rtmd" timed metadata embedded in Sony MP4 videos (ref PH) +# Inputs: 0) ExifTool object ref, 1) dirInfo ref, 2) tag table ref +# Returns: 1 on success +sub Process_rtmd($$$) +{ + my ($et, $dirInfo, $tagTablePtr) = @_; + my $dataPt = $$dirInfo{DataPt}; + my $dataPos = ($$dirInfo{DataPos} || 0) + ($$dirInfo{Base} || 0); + my $end = length $$dataPt; + return 0 if $end < 2; + $et->VerboseDir('Sony rtmd', undef, $end); + # Note: The 0x1c-byte header contains some as-yet unextracted information: + # offset 0x0e: int8u some minutes + # 0x0f: int8u some seconds + # 0x11: int8u frame number? (0-24 or 0-25) + my $pos = Get16u($dataPt, 0); # get header length (= 0x1c) + while ($pos + 4 < $end) { + my $tag = Get16u($dataPt, $pos); + last if $tag == 0; + my $len = Get16u($dataPt, $pos+2); + if ($tag == 0x060e) { + $len = 0x10; # (unknown 16 bytes starting with 0x060e2b340253) + } else { + $pos += 4; # skip tag id/size + next if $tag == 0x8300; # descend into contents of 0x8300 (container) + } + last if $pos + $len > $end; + $et->HandleTag($tagTablePtr, $tag, undef, + DataPt => $dataPt, + DataPos => $dataPos, + Start => $pos, + Size => $len, + ); + $pos += $len; # step to next tag + } + return 1; +}; + +#------------------------------------------------------------------------------ +# Process SRF maker notes +# Inputs: 0) ExifTool object ref, 1) dirInfo ref, 2) tag table ref +# Returns: 1 on success +sub ProcessSRF($$$) +{ + my ($et, $dirInfo, $tagTablePtr) = @_; + my $dataPt = $$dirInfo{DataPt}; + my $start = $$dirInfo{DirStart}; + my $verbose = $et->Options('Verbose'); + + # process IFD chain + my ($ifd, $success); + for ($ifd=0; ; ) { + # switch tag table for SRF2-5 and SRF6 + if ($ifd == 2) { + $tagTablePtr = GetTagTable('Image::ExifTool::Sony::SRF2'); + } elsif ($ifd == 6) { + # SRF6 uses standard EXIF tags + $tagTablePtr = GetTagTable('Image::ExifTool::Exif::Main'); + } + my $srf = $$dirInfo{DirName} = "SRF$ifd"; + $$et{SET_GROUP1} = $srf; + $success = Image::ExifTool::Exif::ProcessExif($et, $dirInfo, $tagTablePtr); + delete $$et{SET_GROUP1}; + last unless $success; +# +# get pointer to next IFD +# + my $count = Get16u($dataPt, $$dirInfo{DirStart}); + my $dirEnd = $$dirInfo{DirStart} + 2 + $count * 12; + last if $dirEnd + 4 > length($$dataPt); + my $nextIFD = Get32u($dataPt, $dirEnd); + last unless $nextIFD; + $nextIFD -= $$dirInfo{DataPos}; # adjust for position of makernotes data + $$dirInfo{DirStart} = $nextIFD; +# +# decrypt next IFD data if necessary +# + ++$ifd; + my ($key, $len); + if ($ifd == 1) { + # get the key to decrypt IFD1 + my $cp = $start + 0x8ddc; # why? + last if $cp + 1 > length($$dataPt); + my $ip = $cp + 4 * unpack("x$cp C", $$dataPt); + last if $ip + 4 > length($$dataPt); + $key = unpack("x$ip N", $$dataPt); + $len = $cp + $nextIFD; # decrypt up to $cp + } elsif ($ifd == 2) { + # get the key to decrypt IFD2 + $key = $$et{SRF2Key}; + $len = length($$dataPt) - $nextIFD; # decrypt rest of maker notes + } else { + next; # no decryption needed + } + # decrypt data + Decrypt($dataPt, $nextIFD, $len, $key) if defined $key; + next unless $verbose > 2; + # display decrypted data in verbose mode + $et->VerboseDir("Decrypted SRF$ifd", 0, $nextIFD + $len); + $et->VerboseDump($dataPt, + Prefix => "$$et{INDENT} ", + Start => $nextIFD, + DataPos => $$dirInfo{DataPos}, + ); + } +} + +#------------------------------------------------------------------------------ +# Write SR2 data +# Inputs: 0) ExifTool object ref, 1) dirInfo ref, 2) tag table ref +# Returns: 1 on success when reading, or SR2 directory or undef when writing +sub WriteSR2($$$) +{ + my ($et, $dirInfo, $tagTablePtr) = @_; + $et or return 1; # allow dummy access + my $buff = ''; + $$dirInfo{OutFile} = \$buff; + return ProcessSR2($et, $dirInfo, $tagTablePtr); +} + +#------------------------------------------------------------------------------ +# Read/Write SR2 IFD and its encrypted subdirectories +# Inputs: 0) ExifTool object ref, 1) dirInfo ref, 2) tag table ref +# Returns: 1 on success when reading, or SR2 directory or undef when writing +sub ProcessSR2($$$) +{ + my ($et, $dirInfo, $tagTablePtr) = @_; + my $raf = $$dirInfo{RAF}; + my $dataPt = $$dirInfo{DataPt}; + my $dataPos = $$dirInfo{DataPos}; + my $dataLen = $$dirInfo{DataLen} || length $$dataPt; + my $base = $$dirInfo{Base} || 0; + my $outfile = $$dirInfo{OutFile}; + + # clear SR2 member variables to be safe + delete $$et{SR2SubIFDOffset}; + delete $$et{SR2SubIFDLength}; + delete $$et{SR2SubIFDKey}; + + # make sure we have the first 4 bytes available to test directory type + my $buff; + if ($dataLen < 4 and $raf) { + my $pos = $dataPos + ($$dirInfo{DirStart}||0) + $base; + if ($raf->Seek($pos, 0) and $raf->Read($buff, 4) == 4) { + $dataPt = \$buff; + undef $$dirInfo{DataPt}; # must load data from file + $raf->Seek($pos, 0); + } + } + # this may either be a normal IFD, or a MRW data block + # (only original ARW images from the A100 use the MRW block) + my $dataOffset; + if ($dataPt and $$dataPt =~ /^\0MR[IM]/) { + my ($err, $srfPos, $srfLen, $dataOffset); + $dataOffset = $$et{A100DataOffset}; + if ($dataOffset) { + # save information about the RAW data trailer so it will be preserved + $$et{KnownTrailer} = { Name => 'A100 RAW Data', Start => $dataOffset }; + } else { + $err = 'A100DataOffset tag is missing from A100 ARW image'; + } + $raf or $err = 'Unrecognized SR2 structure'; + unless ($err) { + $srfPos = $raf->Tell(); + $srfLen = $dataOffset - $srfPos; + unless ($srfLen > 0 and $raf->Read($buff, $srfLen) == $srfLen) { + $err = 'Error reading MRW directory'; + } + } + if ($err) { + $outfile and $et->Error($err), return undef; + $et->Warn($err); + return 0; + } + my %dirInfo = ( DataPt => \$buff ); + require Image::ExifTool::MinoltaRaw; + if ($outfile) { + # save MRW data to be written last + $$et{MRWDirData} = Image::ExifTool::MinoltaRaw::WriteMRW($et, \%dirInfo); + return $$et{MRWDirData} ? "\0\0\0\0\0\0" : undef; + } else { + if (not $outfile and $$et{HTML_DUMP}) { + $et->HDump($srfPos, $srfLen, '[A100 SRF Data]'); + } + return Image::ExifTool::MinoltaRaw::ProcessMRW($et, \%dirInfo); + } + } elsif ($$et{A100DataOffset}) { + my $err = 'Unexpected A100DataOffset tag'; + $outfile and $et->Error($err), return undef; + $et->Warn($err); + return 0; + } + my $verbose = $et->Options('Verbose'); + my $result; + if ($outfile) { + $result = Image::ExifTool::Exif::WriteExif($et, $dirInfo, $tagTablePtr); + return undef unless $result; + $$outfile .= $result; + + } else { + $result = Image::ExifTool::Exif::ProcessExif($et, $dirInfo, $tagTablePtr); + } + return $result unless $result and $$et{SR2SubIFDOffset}; + # only take first offset value if more than one! + my @offsets = split ' ', $$et{SR2SubIFDOffset}; + my $offset = shift @offsets; + my $length = $$et{SR2SubIFDLength}; + my $key = $$et{SR2SubIFDKey}; + my @subifdPos; + if ($offset and $length and defined $key) { + my $buff; + # read encrypted SR2SubIFD from file + if (($raf and $raf->Seek($offset+$base, 0) and + $raf->Read($buff, $length) == $length) or + # or read from data (when processing Adobe DNGPrivateData) + ($offset - $dataPos >= 0 and $offset - $dataPos + $length < $dataLen and + ($buff = substr($$dataPt, $offset - $dataPos, $length)))) + { + Decrypt(\$buff, 0, $length, $key); + # display decrypted data in verbose mode + if ($verbose > 2 and not $outfile) { + $et->VerboseDir("Decrypted SR2SubIFD", 0, $length); + $et->VerboseDump(\$buff, Addr => $offset + $base); + } + my $num = ''; + my $dPos = $offset; + for (;;) { + my %dirInfo = ( + Base => $base, + DataPt => \$buff, + DataLen => length $buff, + DirStart => $offset - $dPos, + DirName => "SR2SubIFD$num", + DataPos => $dPos, + ); + my $subTable = GetTagTable('Image::ExifTool::Sony::SR2SubIFD'); + if ($outfile) { + my $fixup = new Image::ExifTool::Fixup; + $dirInfo{Fixup} = $fixup; + $result = $et->WriteDirectory(\%dirInfo, $subTable); + return undef unless $result; + # save position of this SubIFD + push @subifdPos, length($$outfile); + # add this directory to the returned data + $$fixup{Start} += length($$outfile); + $$outfile .= $result; + $$dirInfo{Fixup}->AddFixup($fixup); + } else { + $result = $et->ProcessDirectory(\%dirInfo, $subTable); + } + last unless @offsets; + $offset = shift @offsets; + $num = ($num || 1) + 1; + } + + } else { + $et->Warn('Error reading SR2 data'); + } + } + if ($outfile and @subifdPos) { + # the SR2SubIFD must be padded to a multiple of 4 bytes for the encryption + my $sr2Len = length($$outfile) - $subifdPos[0]; + if ($sr2Len & 0x03) { + my $pad = 4 - ($sr2Len & 0x03); + $sr2Len += $pad; + $$outfile .= ' ' x $pad; + } + # save the new SR2SubIFD Length and Key to be used later for encryption + $$et{SR2SubIFDLength} = $sr2Len; + my $newKey = $$et{VALUE}{SR2SubIFDKey}; + $$et{SR2SubIFDKey} = $newKey if defined $newKey; + # update SubIFD pointers manually and add to fixup, and set SR2SubIFDLength + my $n = Get16u($outfile, 0); + my ($i, %found); + for ($i=0; $i<$n; ++$i) { + my $entry = 2 + 12 * $i; + my $tagID = Get16u($outfile, $entry); + # only interested in SR2SubIFDOffset (0x7200) and SR2SubIFDLength (0x7201) + next unless $tagID == 0x7200 or $tagID == 0x7201; + $found{$tagID} = 1; + my $fmt = Get16u($outfile, $entry + 2); + if ($fmt != 0x04) { # must be int32u + $et->Error("Unexpected format ($fmt) for SR2SubIFD tag"); + return undef; + } + if ($tagID == 0x7201) { # SR2SubIFDLength + Set32u($sr2Len, $outfile, $entry + 8); + next; + } + my $tag = 'SR2SubIFDOffset'; + my $valuePtr = @subifdPos < 2 ? $entry+8 : Get32u($outfile, $entry+8); + my $pos; + foreach $pos (@subifdPos) { + Set32u($pos, $outfile, $valuePtr); + $$dirInfo{Fixup}->AddFixup($valuePtr, $tag); + undef $tag; + $valuePtr += 4; + } + } + unless ($found{0x7200} and $found{0x7201}) { + $et->Error('Missing SR2SubIFD tag'); + return undef; + } + } + return $outfile ? $$outfile : $result; +} + +1; # end + +__END__ + +=head1 NAME + +Image::ExifTool::Sony - Sony EXIF maker notes tags + +=head1 SYNOPSIS + +This module is loaded automatically by Image::ExifTool when required. + +=head1 DESCRIPTION + +This module contains definitions required by Image::ExifTool to interpret +Sony maker notes EXIF meta information. + +=head1 NOTES + +Also see Minolta.pm since Sony DSLR models use structures originating from +Minolta. + +=head1 AUTHOR + +Copyright 2003-2019, Phil Harvey (phil at owl.phy.queensu.ca) + +This library is free software; you can redistribute it and/or modify it +under the same terms as Perl itself. + +=head1 REFERENCES + +=over 4 + +=item L<http://www.cybercom.net/~dcoffin/dcraw/> + +=item L<http://homepage3.nifty.com/kamisaka/makernote/makernote_sony.htm> + +=item L<http://www.klingebiel.com/tempest/hd/pmp.html> + +=item (...plus lots of testing with my RX100!) + +=back + +=head1 ACKNOWLEDGEMENTS + +Thanks to Thomas Bodenmann, Philippe Devaux, Jens Duttke, Marcus +Holland-Moritz, Andrey Tverdokhleb, Rudiger Lange, Igal Milchtaich, Michael +Reitinger and Jos Roost for help decoding some tags. + +=head1 SEE ALSO + +L<Image::ExifTool::TagNames/Sony Tags>, +L<Image::ExifTool::TagNames/Minolta Tags>, +L<Image::ExifTool(3pm)|Image::ExifTool> + +=cut diff --git a/lib/Image/ExifTool/SonyIDC.pm b/lib/Image/ExifTool/SonyIDC.pm new file mode 100644 index 0000000..b9e4c7c --- /dev/null +++ b/lib/Image/ExifTool/SonyIDC.pm @@ -0,0 +1,393 @@ +#------------------------------------------------------------------------------ +# File: SonyIDC.pm +# +# Description: Read/write Sony IDC information +# +# Revisions: 2010/01/05 - P. Harvey Created +#------------------------------------------------------------------------------ + +package Image::ExifTool::SonyIDC; + +use strict; +use vars qw($VERSION); +use Image::ExifTool qw(:DataAccess :Utils); +use Image::ExifTool::Exif; + +$VERSION = '1.08'; + +# Sony IDC tags (ref PH) +%Image::ExifTool::SonyIDC::Main = ( + WRITE_PROC => \&Image::ExifTool::Exif::WriteExif, + CHECK_PROC => \&Image::ExifTool::Exif::CheckExif, + GROUPS => { 0 => 'MakerNotes', 2 => 'Image' }, + NOTES => 'Tags written by the Sony Image Data Converter utility in ARW images.', + SET_GROUP1 => 1, + 0x201 => { + Name => 'IDCPreviewStart', + IsOffset => 1, + OffsetPair => 0x202, + DataTag => 'IDCPreview', + Writable => 'int32u', + Protected => 2, + }, + 0x202 => { + Name => 'IDCPreviewLength', + OffsetPair => 0x201, + DataTag => 'IDCPreview', + Writable => 'int32u', + Protected => 2, + }, + 0x8000 => { + Name => 'IDCCreativeStyle', + Writable => 'int32u', + PrintConvColumns => 2, + PrintConv => { + 1 => 'Camera Setting', + 2 => 'Standard', + 3 => 'Real', + 4 => 'Vivid', + 5 => 'Adobe RGB', + 6 => 'A100 Standard', # shows up as '-' in IDC menu + 7 => 'Neutral', + 8 => 'Portrait', + 9 => 'Landscape', + 10 => 'Clear', + 11 => 'Deep', + 12 => 'Light', + 13 => 'Sunset', + 14 => 'Night View', + 15 => 'Autumn Leaves', + 16 => 'B&W', + 17 => 'Sepia', + }, + }, + 0x8001 => { + Name => 'CreativeStyleWasChanged', + Writable => 'int32u', + Notes => 'set if the creative style was ever changed', + # (even if it was changed back again later) + PrintConv => { 0 => 'No', 1 => 'Yes' }, + }, + 0x8002 => { + Name => 'PresetWhiteBalance', + Writable => 'int32u', + PrintConv => { + 1 => 'Camera Setting', + 2 => 'Color Temperature', + 3 => 'Specify Gray Point', + 4 => 'Daylight', + 5 => 'Cloudy', + 6 => 'Shade', + 7 => 'Cool White Fluorescent', + 8 => 'Day Light Fluorescent', + 9 => 'Day White Fluorescent', + 10 => 'Warm White Fluorescent', + 11 => 'Tungsten', + 12 => 'Flash', + 13 => 'Auto', + }, + }, + 0x8013 => { Name => 'ColorTemperatureAdj', Writable => 'int16u' }, + 0x8014 => { Name => 'PresetWhiteBalanceAdj',Writable => 'int32s' }, + 0x8015 => { Name => 'ColorCorrection', Writable => 'int32s' }, + 0x8016 => { Name => 'SaturationAdj', Writable => 'int32s' }, + 0x8017 => { Name => 'ContrastAdj', Writable => 'int32s' }, + 0x8018 => { + Name => 'BrightnessAdj', + Writable => 'int32s', + PrintConv => 'sprintf("%.2f", $val/300)', #JR + PrintConvInv => '$val * 300', + }, + 0x8019 => { Name => 'HueAdj', Writable => 'int32s' }, + 0x801a => { Name => 'SharpnessAdj', Writable => 'int32s' }, + 0x801b => { Name => 'SharpnessOvershoot', Writable => 'int32s' }, + 0x801c => { Name => 'SharpnessUndershoot', Writable => 'int32s' }, + 0x801d => { Name => 'SharpnessThreshold', Writable => 'int32s' }, + 0x801e => { + Name => 'NoiseReductionMode', + Writable => 'int16u', + PrintConv => { + 0 => 'Off', + 1 => 'On', + }, + }, + 0x8021 => { + Name => 'GrayPoint', + Writable => 'int16u', + Count => 4, + }, + 0x8022 => { + Name => 'D-RangeOptimizerMode', + Writable => 'int16u', + PrintConv => { + 0 => 'Off', + 1 => 'Auto', + 2 => 'Manual', + }, + }, + 0x8023 => { Name => 'D-RangeOptimizerValue', Writable => 'int32s' }, + 0x8024 => { Name => 'D-RangeOptimizerHighlight',Writable => 'int32s' }, + 0x8026 => { + Name => 'HighlightColorDistortReduct', + Writable => 'int16u', + PrintConv => { + 0 => 'Standard', + 1 => 'Advanced', + }, + }, + 0x8027 => { + Name => 'NoiseReductionValue', + Writable => 'int32s', + ValueConv => '($val + 100) / 2', + ValueConvInv => '$val * 2 - 100', + }, + 0x8028 => { + Name => 'EdgeNoiseReduction', + Writable => 'int32s', + ValueConv => '($val + 100) / 2', + ValueConvInv => '$val * 2 - 100', + }, + 0x8029 => { + Name => 'ColorNoiseReduction', + Writable => 'int32s', + ValueConv => '($val + 100) / 2', + ValueConvInv => '$val * 2 - 100', + }, + 0x802d => { Name => 'D-RangeOptimizerShadow', Writable => 'int32s' }, + 0x8030 => { Name => 'PeripheralIllumCentralRadius', Writable => 'int32s' }, + 0x8031 => { Name => 'PeripheralIllumCentralValue', Writable => 'int32s' }, + 0x8032 => { Name => 'PeripheralIllumPeriphValue', Writable => 'int32s' }, + 0x8040 => { #JR + Name => 'DistortionCompensation', + Writable => 'int32s', + PrintConv => { + -1 => 'n/a', # (fixed by lens) + 1 => 'On', + 2 => 'Off', + }, + }, + 0x9000 => { + Name => 'ToneCurveBrightnessX', + Writable => 'int16u', + Count => -1, + }, + 0x9001 => { + Name => 'ToneCurveRedX', + Writable => 'int16u', + Count => -1, + }, + 0x9002 => { + Name => 'ToneCurveGreenX', + Writable => 'int16u', + Count => -1, + }, + 0x9003 => { + Name => 'ToneCurveBlueX', + Writable => 'int16u', + Count => -1, + }, + 0x9004 => { + Name => 'ToneCurveBrightnessY', + Writable => 'int16u', + Count => -1, + }, + 0x9005 => { + Name => 'ToneCurveRedY', + Writable => 'int16u', + Count => -1, + }, + 0x9006 => { + Name => 'ToneCurveGreenY', + Writable => 'int16u', + Count => -1, + }, + 0x9007 => { + Name => 'ToneCurveBlueY', + Writable => 'int16u', + Count => -1, + }, + 0x900d => { #JR + Name => 'ChromaticAberrationCorrection', # "Magnification Chromatic Aberration" + Writable => 'int32s', + PrintConv => { 1 => 'On', 2 => 'Off' }, + }, + 0x900e => { #JR + Name => 'InclinationCorrection', + Writable => 'int32u', + PrintConv => { 0 => 'Off', 1 => 'On' }, + }, + 0x900f => { #JR + Name => 'InclinationAngle', + Writable => 'int32s', + PrintConv => 'sprintf("%.1f deg", $val/1000)', + PrintConvInv => 'ToFloat($val) * 1000', + }, + 0x9010 => { #JR + Name => 'Cropping', + Writable => 'int32u', + PrintConv => { 0 => 'Off', 1 => 'On' }, + }, + 0x9011 => { #JR + Name => 'CropArea', + Writable => 'int32u', + Count => 4, + }, + 0x9012 => { #JR + Name => 'PreviewImageSize', + Writable => 'int32u', + Count => 2, + }, + 0x9013 => { #JR (ARQ images) + Name => 'PxShiftPeriphEdgeNR', + Writable => 'int32s', + PrintConv => { 0 => 'Off', 1 => 'On' }, + }, + 0x9014 => { #JR (ARQ images) + Name => 'PxShiftPeriphEdgeNRValue', + Writable => 'int32s', + PrintConv => 'sprintf("%.1f", $val/10)', + PrintConvInv => '$val * 10', + }, + 0x9017 => { Name => 'WhitesAdj', Writable => 'int32s' }, #JR + 0x9018 => { Name => 'BlacksAdj', Writable => 'int32s' }, #JR + 0x9019 => { Name => 'HighlightsAdj', Writable => 'int32s' }, #JR + 0x901a => { Name => 'ShadowsAdj', Writable => 'int32s' }, #JR + 0xd000 => { Name => 'CurrentVersion', Writable => 'int32u' }, + 0xd001 => { + Name => 'VersionIFD', + Groups => { 1 => 'Version0' }, + Flags => 'SubIFD', + Notes => 'there is one VersionIFD for each entry in the "Version Stack"', + SubDirectory => { + DirName => 'Version0', + TagTable => 'Image::ExifTool::SonyIDC::Main', + Start => '$val', + Base => '$start', + MaxSubdirs => 20, # (IDC v3.0 writes max. 10) + RelativeBase => 1, # needed to write SubIFD with relative offsets + }, + }, + 0xd100 => { + Name => 'VersionCreateDate', + Writable => 'string', + Groups => { 2 => 'Time' }, + Notes => 'date/time when this entry was created in the "Version Stack"', + Shift => 'Time', + PrintConv => '$self->ConvertDateTime($val)', + PrintConvInv => '$self->InverseDateTime($val,0)', + }, + 0xd101 => { + Name => 'VersionModifyDate', + Writable => 'string', + Groups => { 2 => 'Time' }, + Shift => 'Time', + PrintConv => '$self->ConvertDateTime($val)', + PrintConvInv => '$self->InverseDateTime($val,0)', + }, +); + +# extract IDC preview images as composite tags +%Image::ExifTool::SonyIDC::Composite = ( + GROUPS => { 2 => 'Image' }, + IDCPreviewImage => { + Groups => { 2 => 'Preview' }, + Require => { + 0 => 'IDCPreviewStart', + 1 => 'IDCPreviewLength', + }, + # extract all preview images (not just one) + RawConv => q{ + @grps = $self->GetGroup($$val{0}); + require Image::ExifTool::SonyIDC; + Image::ExifTool::SonyIDC::ExtractPreviews($self); + }, + }, +); + +# add our composite tags +Image::ExifTool::AddCompositeTags('Image::ExifTool::SonyIDC'); + +# set "Permanent" flag for all tags +{ + my $key; + foreach $key (TagTableKeys(\%Image::ExifTool::SonyIDC::Main)) { + $Image::ExifTool::SonyIDC::Main{$key}{Permanent} = 1; + } +} + +#------------------------------------------------------------------------------ +# Extract all IDC preview images +# Inputs: 0) ExifTool object ref +# Returns: data for "IDCPreviewImage" tag (which I have never seen), +# or undef if there was no preview in the SonyIDC IFD +sub ExtractPreviews($) +{ + my $et = shift; + my $i = 1; + my $xtra = ' (1)'; + my $preview; + # loop through all available IDC preview images in the order they were found + for (;;) { + my $key = "IDCPreviewStart$xtra"; + unless (defined $$et{VALUE}{$key}) { + last unless $xtra; + $xtra = ''; # do the last tag extracted last + next; + } + # run through IDC preview images in the same order they were extracted + my $off = $et->GetValue($key, 'ValueConv') or last; + my $len = $et->GetValue("IDCPreviewLength$xtra", 'ValueConv') or last; + # get stack version from number in group 1 name + my $grp1 = $et->GetGroup($key, 1); + if ($grp1 =~ /(\d+)$/) { + my $tag = "IDCPreviewImage$1"; + unless ($Image::ExifTool::Extra{$tag}) { + AddTagToTable(\%Image::ExifTool::Extra, $tag, { + Name => $tag, + Groups => { 0 => 'Composite', 1 => 'Composite', 2 => 'Preview'}, + }); + } + my $val = Image::ExifTool::Exif::ExtractImage($et, $off, $len, $tag); + $et->FoundTag($tag, $val, $et->GetGroup($key)); + } else { + $preview = Image::ExifTool::Exif::ExtractImage($et, $off, $len, 'IDCPreviewImage'); + } + # step to next set of tags unless we are done + last unless $xtra; + ++$i; + $xtra = " ($i)"; + } + return $preview; +} + +1; # end + +__END__ + +=head1 NAME + +Image::ExifTool::SonyIDC - Read/write Sony IDC information + +=head1 SYNOPSIS + +This module is used by Image::ExifTool + +=head1 DESCRIPTION + +This module contains definitions required by Image::ExifTool to read and +write Sony Image Data Converter version 3.0 metadata in ARW images. + +=head1 AUTHOR + +Copyright 2003-2019, Phil Harvey (phil at owl.phy.queensu.ca) + +This library is free software; you can redistribute it and/or modify it +under the same terms as Perl itself. + +=head1 SEE ALSO + +L<Image::ExifTool::TagNames/SonyIDC Tags>, +L<Image::ExifTool(3pm)|Image::ExifTool> + +=cut + diff --git a/lib/Image/ExifTool/Stim.pm b/lib/Image/ExifTool/Stim.pm new file mode 100644 index 0000000..90bc829 --- /dev/null +++ b/lib/Image/ExifTool/Stim.pm @@ -0,0 +1,196 @@ +#------------------------------------------------------------------------------ +# File: Stim.pm +# +# Description: Definitions for Stereo Still Image tags +# +# Revisions: 06/12/2009 - P. Harvey Created +# +# References: 1) http://www.cipa.jp/std/documents/e/DC-006_E.pdf +#------------------------------------------------------------------------------ + +package Image::ExifTool::Stim; + +use strict; +use vars qw($VERSION); + +$VERSION = '1.01'; + +# Tags found in APP3 Stim segment in JPEG images +%Image::ExifTool::Stim::Main = ( + GROUPS => { 0 => 'Stim', 1 => 'Stim', 2 => 'Image'}, + NOTES => q{ + These tags are part of the CIPA Stereo Still Image specification, and are + found in the APP3 "Stim" segment of JPEG images. See + L<http://www.cipa.jp/std/documents/e/DC-006_E.pdf> for the + official specification. + }, + 0 => 'StimVersion', + 1 => { + Name => 'ApplicationData', + Binary => 1, + }, + 2 => { + Name => 'ImageArrangement', + PrintConv => { + 0 => 'Parallel View Alignment', + 1 => 'Cross View Alignment', + }, + }, + 3 => { + Name => 'ImageRotation', + PrintConv => { + 1 => 'None', + }, + }, + 4 => 'ScalingFactor', + 5 => 'CropXSize', + 6 => 'CropYSize', + 7 => { + Name => 'CropX', + SubDirectory => { + TagTable => 'Image::ExifTool::Stim::CropX', + }, + }, + 8 => { + Name => 'CropY', + SubDirectory => { + TagTable => 'Image::ExifTool::Stim::CropY', + }, + }, + 9 => { + Name => 'ViewType', + PrintConv => { + 0 => 'No Pop-up Effect', + 1 => 'Pop-up Effect', + }, + }, + 10 => { + Name => 'RepresentativeImage', + PrintConv => { + 0 => 'Left Viewpoint', + 1 => 'Right Viewpoint', + }, + }, + 11 => { + Name => 'ConvergenceBaseImage', + PrintConv => { + 0 => 'Left Viewpoint', + 1 => 'Right Viewpoint', + 255 => 'Equivalent for Both Viewpoints', + }, + }, + 12 => { + Name => 'AssumedDisplaySize', + PrintConv => '"$val mm"', + }, + 13 => { + Name => 'AssumedDistanceView', + PrintConv => '"$val mm"', + }, + 14 => 'RepresentativeDisparityNear', + 15 => 'RepresentativeDisparityFar', + 16 => { + Name => 'InitialDisplayEffect', + PrintConv => { + 0 => 'Off', + 1 => 'On', + }, + }, + 17 => { + Name => 'ConvergenceDistance', + PrintConv => '$val ? "$val mm" : "inf"', + }, + 18 => { + Name => 'CameraArrangementInterval', + PrintConv => '"$val mm"', + }, + 19 => 'ShootingCount', +); + +# crop offset X tags +%Image::ExifTool::Stim::CropX = ( + PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData, + GROUPS => { 0 => 'Stim', 1 => 'Stim', 2 => 'Image'}, + 0 => { + Name => 'CropXCommonOffset', + Format => 'int16u', + PrintConv => { + 0 => 'Common Offset Setting', + 1 => 'Individual Offset Setting', + }, + }, + 2 => 'CropXViewpointNumber', + 3 => { + Name => 'CropXOffset', + Format => 'int32s', + }, + 7 => 'CropXViewpointNumber2', + 8 => { + Name => 'CropXOffset2', + Format => 'int32s', + }, +); + +# crop offset Y tags +%Image::ExifTool::Stim::CropY = ( + PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData, + GROUPS => { 0 => 'Stim', 1 => 'Stim', 2 => 'Image'}, + 0 => { + Name => 'CropYCommonOffset', + Format => 'int16u', + PrintConv => { + 0 => 'Common Offset Setting', + 1 => 'Individual Offset Setting', + }, + }, + 2 => 'CropYViewpointNumber', + 3 => { + Name => 'CropYOffset', + Format => 'int32s', + }, + 7 => 'CropYViewpointNumber2', + 8 => { + Name => 'CropYOffset2', + Format => 'int32s', + }, +); + +1; # end + +__END__ + +=head1 NAME + +Image::ExifTool::Stim - Definitions for Stereo Still Image tags + +=head1 SYNOPSIS + +This module is used by Image::ExifTool + +=head1 DESCRIPTION + +This module contains tag definitions for Stereo Still Image format (Stim) +information. + +=head1 AUTHOR + +Copyright 2003-2019, Phil Harvey (phil at owl.phy.queensu.ca) + +This library is free software; you can redistribute it and/or modify it +under the same terms as Perl itself. + +=head1 REFERENCES + +=over 4 + +=item L<http://www.cipa.jp/std/documents/e/DC-006_E.pdf> + +=back + +=head1 SEE ALSO + +L<Image::ExifTool::TagNames/Stim Tags>, +L<Image::ExifTool(3pm)|Image::ExifTool> + +=cut + diff --git a/lib/Image/ExifTool/TagInfoXML.pm b/lib/Image/ExifTool/TagInfoXML.pm new file mode 100644 index 0000000..ed6456f --- /dev/null +++ b/lib/Image/ExifTool/TagInfoXML.pm @@ -0,0 +1,830 @@ +#------------------------------------------------------------------------------ +# File: TagInfoXML.pm +# +# Description: Read/write tag information XML database +# +# Revisions: 2009/01/28 - P. Harvey Created +#------------------------------------------------------------------------------ + +package Image::ExifTool::TagInfoXML; + +use strict; +require Exporter; + +use vars qw($VERSION @ISA $makeMissing); +use Image::ExifTool qw(:Utils :Vars); +use Image::ExifTool::XMP; + +$VERSION = '1.30'; +@ISA = qw(Exporter); + +# set this to a language code to generate Lang module with 'MISSING' entries +$makeMissing = ''; + +sub LoadLangModules($;$); +sub WriteLangModule($$;$); +sub NumbersFirst; + +# names for acknowledgements in the POD documentation +my %credits = ( + cs => 'Jens Duttke and Petr MichE<aacute>lek', + de => 'Jens Duttke and Herbert Kauer', + es => 'Jens Duttke, Santiago del BrE<iacute>o GonzE<aacute>lez and Emilio Sancha', + fi => 'Jens Duttke and Jarkko ME<auml>kineva', + fr => 'Jens Duttke, Bernard Guillotin, Jean Glasser, Jean Piquemal, Harry Nizard and Alphonse Philippe', + it => 'Jens Duttke, Ferdinando Agovino, Emilio Dati and Michele Locati', + ja => 'Jens Duttke and Kazunari Nishina', + ko => 'Jens Duttke and Jeong Beom Kim', + nl => 'Jens Duttke, Peter Moonen, Herman Beld and Peter van der Laan', + pl => 'Jens Duttke, Przemyslaw Sulek and Kacper Perschke', + ru => 'Jens Duttke, Sergey Shemetov, Dmitry Yerokhin and Anton Sukhinov', + sv => 'Jens Duttke and BjE<ouml>rn SE<ouml>derstrE<ouml>m', + 'tr' => 'Jens Duttke, Hasan Yildirim and Cihan Ulusoy', + zh_cn => 'Jens Duttke and Haibing Zhong', + zh_tw => 'Jens Duttke and MikeF', +); + +# translate country codes to language codes +my %translateLang = ( + ch_s => 'zh_cn', + ch_cn => 'zh_cn', + ch_tw => 'zh_tw', + cz => 'cs', + jp => 'ja', + kr => 'ko', + se => 'sv', +); + +my $numbersFirst = 1; # set to -1 to sort numbers last, or 2 to put negative numbers last +my $caseInsensitive; # used internally by sort routine + +#------------------------------------------------------------------------------ +# Utility to print tag information database as an XML list +# Inputs: 0) output file name (undef to send to console), +# 1) group name (may be undef), 2) options hash ('Flags','NoDesc','Lang') +# Returns: true on success +sub Write(;$$%) +{ + local ($_, *PTIFILE); + my ($file, $group, %opts) = @_; + my @groups = split ':', $group if $group; + my $et = new Image::ExifTool; + my ($fp, $tableName, %langInfo, @langs, $defaultLang); + + Image::ExifTool::LoadAllTables(); # first load all our tables + unless ($opts{NoDesc}) { + $defaultLang = $Image::ExifTool::defaultLang; + LoadLangModules(\%langInfo, $opts{Lang}); # load necessary Lang modules + if ($opts{Lang}) { + @langs = grep /^$opts{Lang}$/i, keys %langInfo; + } else { + @langs = sort keys %langInfo; + } + } + if (defined $file) { + open PTIFILE, ">$file" or return 0; + $fp = \*PTIFILE; + } else { + $fp = \*STDOUT; + } + print $fp "<?xml version='1.0' encoding='UTF-8'?>\n"; + print $fp "<!-- Generated by Image::ExifTool $Image::ExifTool::VERSION -->\n"; + print $fp "<taginfo>\n\n"; + + # loop through all tables and save tag names to %allTags hash + foreach $tableName (sort keys %allTables) { + my $table = GetTagTable($tableName); + my $grps = $$table{GROUPS}; + my ($tagID, $didTag); + # sort in same order as tag name documentation + $caseInsensitive = ($tableName =~ /::XMP::/); + # get list of languages defining elements in this table + my $isBinary = ($$table{PROCESS_PROC} and + $$table{PROCESS_PROC} eq \&Image::ExifTool::ProcessBinaryData); + # generate flattened tag names for structure fields if this is an XMP table + if ($$table{GROUPS} and $$table{GROUPS}{0} eq 'XMP') { + Image::ExifTool::XMP::AddFlattenedTags($table); + } + $numbersFirst = 2; + $numbersFirst = -1 if $$table{VARS} and $$table{VARS}{ALPHA_FIRST}; + my @keys = sort NumbersFirst TagTableKeys($table); + $numbersFirst = 1; + # loop through all tag ID's in this table + foreach $tagID (@keys) { + my @infoArray = GetTagInfoList($table, $tagID); + my $xmlID = Image::ExifTool::XMP::FullEscapeXML($tagID); + # get a list of languages defining elements for this ID + my ($index, $fam); +PTILoop: for ($index=0; $index<@infoArray; ++$index) { + my $tagInfo = $infoArray[$index]; + # don't list subdirectories unless they are writable + next unless $$tagInfo{Writable} or not $$tagInfo{SubDirectory}; + if (@groups) { + my @tg = $et->GetGroup($tagInfo); + foreach $group (@groups) { + next PTILoop unless grep /^$group$/i, @tg; + } + } + unless ($didTag) { + my $tname = $$table{SHORT_NAME}; + print $fp "<table name='${tname}' g0='$$grps{0}' g1='$$grps{1}' g2='$$grps{2}'>\n"; + unless ($opts{NoDesc}) { + # print table description + my $desc = $$table{TABLE_DESC}; + unless ($desc) { + ($desc = $tname) =~ s/::Main$//; + $desc =~ s/::/ /g; + } + # print alternate language descriptions + print $fp " <desc lang='en'>$desc</desc>\n"; + foreach (@langs) { + $desc = $langInfo{$_}{$tableName} or next; + $desc = Image::ExifTool::XMP::EscapeXML($desc); + print $fp " <desc lang='${_}'>$desc</desc>\n"; + } + } + $didTag = 1; + } + my $name = $$tagInfo{Name}; + my $ind = @infoArray > 1 ? " index='${index}'" : ''; + my $format = $$tagInfo{Writable} || $$table{WRITABLE}; + my $writable = $format ? 'true' : 'false'; + # check our conversions to make sure we can really write this tag + if ($writable eq 'true') { + foreach ('PrintConv','ValueConv') { + next unless $$tagInfo{$_}; + next if $$tagInfo{$_ . 'Inv'}; + next if ref($$tagInfo{$_}) =~ /^(HASH|ARRAY)$/; + next if $$tagInfo{WriteAlso}; + $writable = 'false'; + last; + } + } + $format = $$tagInfo{Format} || $$table{FORMAT} if not defined $format or $format eq '1'; + $format = 'struct' if $$tagInfo{Struct}; + if (defined $format) { + $format =~ s/\[.*\$.*\]//; # remove expressions from format + } elsif ($isBinary) { + $format = 'int8u'; + } else { + $format = '?'; + } + my $count = ''; + if ($format =~ s/\[.*?(\d*)\]$//) { + $count = " count='${1}'" if length $1; + } elsif ($$tagInfo{Count} and $$tagInfo{Count} > 1) { + $count = " count='$$tagInfo{Count}'"; + } + my @groups = $et->GetGroup($tagInfo); + my $writeGroup = $$tagInfo{WriteGroup} || $$table{WRITE_GROUP}; + if ($writeGroup and $writeGroup ne 'Comment') { + $groups[1] = $writeGroup; # use common write group for group 1 + } + # add group names if different from table defaults + my $grp = ''; + for ($fam=0; $fam<3; ++$fam) { + $grp .= " g$fam='$groups[$fam]'" if $groups[$fam] ne $$grps{$fam}; + } + # add flags if necessary + if ($opts{Flags}) { + my @flags; + foreach (qw(Avoid Binary List Mandatory Unknown)) { + push @flags, $_ if $$tagInfo{$_}; + } + push @flags, $$tagInfo{List} if $$tagInfo{List} and $$tagInfo{List} =~ /^(Alt|Bag|Seq)$/; + push @flags, 'Flattened' if defined $$tagInfo{Flat}; + push @flags, 'Unsafe' if $$tagInfo{Protected} and $$tagInfo{Protected} & 0x01; + push @flags, 'Protected' if $$tagInfo{Protected} and $$tagInfo{Protected} & 0x02; + push @flags, 'Permanent' if $$tagInfo{Permanent} or + ($groups[0] eq 'MakerNotes' and not defined $$tagInfo{Permanent}); + $grp = " flags='" . join(',', sort @flags) . "'$grp" if @flags; + } + print $fp " <tag id='${xmlID}' name='${name}'$ind type='${format}'$count writable='${writable}'$grp"; + if ($opts{NoDesc}) { + # short output format + print $fp "/>\n"; # empty tag element + next; # no descriptions or values + } else { + print $fp ">"; + } + my $desc = $$tagInfo{Description}; + $desc = Image::ExifTool::MakeDescription($name) unless defined $desc; + # add alternate language descriptions and get references + # to alternate language PrintConv hashes + my $altDescr = ''; + my %langConv; + foreach (@langs) { + my $ld = $langInfo{$_}{$name} or next; + if (ref $ld) { + $langConv{$_} = $$ld{PrintConv}; + $ld = $$ld{Description} or next; + } + # ignore descriptions that are the same as the default language + next if $ld eq $desc; + $ld = Image::ExifTool::XMP::EscapeXML($ld); + $altDescr .= "\n <desc lang='${_}'>$ld</desc>"; + } + # print tag descriptions + $desc = Image::ExifTool::XMP::EscapeXML($desc); + unless ($opts{Lang} and $altDescr) { + print $fp "\n <desc lang='${defaultLang}'>$desc</desc>"; + } + print $fp "$altDescr\n"; + for (my $i=0; ; ++$i) { + my $conv = $$tagInfo{PrintConv}; + my $idx = ''; + if (ref $conv eq 'ARRAY') { + last unless $i < @$conv; + $conv = $$conv[$i]; + $idx = " index='${i}'"; + } else { + last if $i; + } + next unless ref $conv eq 'HASH'; + # make a list of available alternate languages + my @langConv = sort keys %langConv; + print $fp " <values$idx>\n"; + my $key; + $caseInsensitive = 0; + # add bitmask values to main lookup + if ($$conv{BITMASK}) { + foreach $key (keys %{$$conv{BITMASK}}) { + my $mask = 0x01 << $key; + next if not $mask or $$conv{$mask}; + $$conv{$mask} = $$conv{BITMASK}{$key}; + } + } + foreach $key (sort NumbersFirst keys %$conv) { + next if $key eq 'BITMASK' or $key eq 'OTHER' or $key eq 'Notes'; + my $val = $$conv{$key}; + my $xmlVal = Image::ExifTool::XMP::EscapeXML($val); + my $xmlKey = Image::ExifTool::XMP::FullEscapeXML($key); + print $fp " <key id='${xmlKey}'>\n"; + # add alternate language values + my $altConv = ''; + foreach (@langConv) { + my $lv = $langConv{$_}; + # handle indexed PrintConv entries + $lv = $$lv[$i] or next if ref $lv eq 'ARRAY'; + $lv = $$lv{$val}; + # ignore values that are missing or same as default + next unless defined $lv and $lv ne $val; + $lv = Image::ExifTool::XMP::EscapeXML($lv); + $altConv .= " <val lang='${_}'>$lv</val>\n"; + } + unless ($opts{Lang} and $altConv) { + print $fp " <val lang='${defaultLang}'>$xmlVal</val>\n" + } + print $fp "$altConv </key>\n"; + } + print $fp " </values>\n"; + } + print $fp " </tag>\n"; + } + } + print $fp "</table>\n\n" if $didTag; + } + my $success = 1; + print $fp "</taginfo>\n" or $success = 0; + close $fp or $success = 0 if defined $file; + return $success; +} + +#------------------------------------------------------------------------------ +# Escape backslash and quote in string +# Inputs: string +# Returns: escaped string +sub EscapePerl +{ + my $str = shift; + $str =~ s/\\/\\\\/g; + $str =~ s/'/\\'/g; + return $str; +} + +#------------------------------------------------------------------------------ +# Generate Lang modules from input tag info XML database +# Inputs: 0) XML filename, 1) update flags: +# 0x01 = preserve version numbers +# 0x02 = update all modules, even if they didn't change +# 0x04 = update from scratch, ignoring existing definitions +# 0x08 = override existing different descriptions and values +# Returns: Count of updated Lang modules, or -1 on error +# Notes: Must be run from the directory containing 'lib' +sub BuildLangModules($;$) +{ + local ($_, *XFILE); + my ($file, $updateFlag) = @_; + my ($table, $tableName, $id, $index, $valIndex, $name, $key, $lang, $defDesc); + my (%langInfo, %different, %changed, $overrideDifferent); + + Image::ExifTool::LoadAllTables(); # first load all our tables + # generate our flattened tags + foreach $tableName (sort keys %allTables) { + my $table = GetTagTable($tableName); + next unless $$table{GROUPS} and $$table{GROUPS}{0} eq 'XMP'; + Image::ExifTool::XMP::AddFlattenedTags($table); + } + LoadLangModules(\%langInfo); # load all existing Lang modules + $updateFlag = 0 unless $updateFlag; + %langInfo = () if $updateFlag & 0x04; + $overrideDifferent = 1 if $updateFlag & 0x08; + + if (defined $file) { + open XFILE, $file or return -1; + while (<XFILE>) { + next unless /^\s*<(\/?)(\w+)/; + my $tok = $2; + if ($1) { + # close appropriate entities + if ($tok eq 'tag') { + undef $id; + undef $index; + undef $name; + undef $defDesc; + } elsif ($tok eq 'values') { + undef $key; + undef $valIndex; + } elsif ($tok eq 'table') { + undef $table; + undef $id; + } + next; + } + if ($tok eq 'table') { + /^\s*<table name='([^']+)'[ >]/ or warn('Bad table'), next; + $tableName = "Image::ExifTool::$1"; + # ignore userdefined tables + next if $tableName =~ /^Image::ExifTool::UserDefined/; + $table = Image::ExifTool::GetTagTable($tableName); + $table or warn("Unknown tag table $tableName\n"); + next; + } + next unless defined $table; + if ($tok eq 'tag') { + /^\s*<tag id='([^']*)' name='([^']+)'( index='(\d+)')?[ >]/ or warn('Bad tag'), next; + $id = Image::ExifTool::XMP::FullUnescapeXML($1); + $name = $2; + $index = $4; + $id = hex($id) if $id =~ /^0x[\da-fA-F]+$/; # convert hex ID's + next; + } + if ($tok eq 'values') { + /^\s*<values index='([^']*)'>/ or next; + $valIndex = $1; + } elsif ($tok eq 'key') { + defined $id or warn('No ID'), next; + /^\s*<key id='([^']*)'>/ or warn('Bad key'), next; + $key = Image::ExifTool::XMP::FullUnescapeXML($1); + $key = hex($key) if $key =~ /^0x[\da-fA-F]+$/; # convert hex keys + } elsif ($tok eq 'val' or $tok eq 'desc') { + /^\s*<$tok( lang='([-\w]+?)')?>(.*)<\/$tok>/ or warn("Bad $tok"), next; + $tok eq 'desc' and defined $key and warn('Out of order "desc"'), next; + my $lang = $2 or next; # looking only for alternate languages + $lang =~ tr/-A-Z/_a-z/; + # use standard ISO 639-1 language codes + $lang = $translateLang{$lang} if $translateLang{$lang}; + my $tval = Image::ExifTool::XMP::UnescapeXML($3); + my $val = ucfirst $tval; + $val = $tval if $tval =~ /^(cRAW|iTun)/; # special-case non-capitalized values + my $cap = ($tval ne $val); + if ($makeMissing and $lang eq 'en') { + $lang = $makeMissing; + $val = 'MISSING'; + undef $cap; + } + my $isDefault = ($lang eq $Image::ExifTool::defaultLang); + unless ($langInfo{$lang} or $isDefault) { + print "Creating new language $lang\n"; + $langInfo{$lang} = { }; + } + defined $name or $name = '<unknown>'; + unless (defined $id) { + next if $isDefault; + # this is a table description + next if $langInfo{$lang}{$tableName} and + $langInfo{$lang}{$tableName} eq $val; + $langInfo{$lang}{$tableName} = $val; + $changed{$lang} = 1; + warn("Capitalized '${lang}' val for $name: $val\n") if $cap; + next; + } + my @infoArray = GetTagInfoList($table, $id); + + # this will fail for UserDefined tags and tags without ID's + @infoArray or warn("Error loading tag for $tableName ID='${id}'\n"), next; + my ($tagInfo, $langInfo); + if (defined $index) { + $tagInfo = $infoArray[$index]; + $tagInfo or warn('Invalid index'), next; + } else { + @infoArray > 1 and warn('Missing index'), next; + $tagInfo = $infoArray[0]; + } + my $tagName = $$tagInfo{Name}; + if ($isDefault) { + unless ($$tagInfo{Description}) { + $$tagInfo{Description} = Image::ExifTool::MakeDescription($tagName); + } + $defDesc = $$tagInfo{Description}; + $langInfo = $tagInfo; + } else { + $langInfo = $langInfo{$lang}{$tagName}; + if (not defined $langInfo) { + $langInfo = $langInfo{$lang}{$tagName} = { }; + } elsif (not ref $langInfo) { + $langInfo = $langInfo{$lang}{$tagName} = { Description => $langInfo }; + } + } + # save new value in langInfo record + if ($tok eq 'desc') { + my $oldVal = $$langInfo{Description}; + next if defined $oldVal and $oldVal eq $val; + if ($makeMissing) { + next if defined $oldVal and $val eq 'MISSING'; + } elsif (defined $oldVal) { + my $t = "$lang $tagName"; + unless (defined $different{$t} and $different{$t} eq $val) { + my $a = defined $different{$t} ? 'ANOTHER ' : ''; + warn "${a}Different '${lang}' desc for $tagName: $val (was $$langInfo{Description})\n"; + next if defined $different{$t}; # don't change back again + $different{$t} = $val; + } + next unless $overrideDifferent; + } + next if $isDefault; + if (defined $defDesc and $defDesc eq $val) { + delete $$langInfo{Description}; # delete if same as default language + } else { + $$langInfo{Description} = $val; + } + } else { + defined $key or warn("No key for $$tagInfo{Name}"), next; + my $printConv = $$tagInfo{PrintConv}; + if (ref $printConv eq 'ARRAY') { + defined $valIndex or warn('No value index'), next; + $printConv = $$printConv[$valIndex]; + } + ref $printConv eq 'HASH' or warn('No PrintConv'), next; + my $convVal = $$printConv{$key}; + unless (defined $convVal) { + if ($$printConv{BITMASK} and $key =~ /^\d+$/) { + my $i; + for ($i=0; $i<64; ++$i) { + my $mask = (0x01 << $i) or last; + next unless $key == $mask; + $convVal = $$printConv{BITMASK}{$i}; + } + } + warn("Missing PrintConv entry for $tableName $$tagInfo{Name} $key\n") and next unless defined $convVal; + } + if ($cap and $convVal =~ /^[a-z]/) { + $val = lcfirst $val; # change back to lower case + undef $cap; + } + my $lc = $$langInfo{PrintConv}; + $lc or $lc = $$langInfo{PrintConv} = { }; + $lc = $printConv if ref $lc eq 'ARRAY'; #(default lang only) + my $oldVal = $$lc{$convVal}; + next if defined $oldVal and $oldVal eq $val; + if ($makeMissing) { + next if defined $oldVal and $val eq 'MISSING'; + } elsif (defined $oldVal and (not $isDefault or not $val=~/^\d+$/)) { + my $t = "$lang $tagName $convVal"; + unless (defined $different{$t} and $different{$t} eq $val) { + my $a = defined $different{$t} ? 'ANOTHER ' : ''; + warn "${a}Different '${lang}' val for $tagName '${convVal}': $val (was $oldVal)\n"; + next if defined $different{$t}; # don't change back again + $different{$t} = $val; + } + next unless $overrideDifferent; + } + next if $isDefault; + warn("Capitalized '${lang}' val for $tagName: $tval\n") if $cap; + $$lc{$convVal} = $val; + } + $changed{$lang} = 1; + } + } + close XFILE; + } + # rewrite all changed Lang modules + my $rtnVal = 0; + foreach $lang ($updateFlag & 0x02 ? @Image::ExifTool::langs : sort keys %changed) { + next if $lang eq $Image::ExifTool::defaultLang; + ++$rtnVal; + # write this module (only increment version number if not forced) + WriteLangModule($lang, $langInfo{$lang}, not $updateFlag & 0x01) or $rtnVal = -1, last; + } + return $rtnVal; +} + +#------------------------------------------------------------------------------ +# Write Lang module +# Inputs: 0) language string, 1) langInfo lookup reference, 2) flag to increment version +# Returns: true on success +sub WriteLangModule($$;$) +{ + local ($_, *XOUT); + my ($lang, $langTags, $newVersion) = @_; + my $err; + -e "lib/Image/ExifTool" or die "Must run from directory containing 'lib'\n"; + my $out = "lib/Image/ExifTool/Lang/$lang.pm"; + my $tmp = "$out.tmp"; + open XOUT, ">$tmp" or die "Error creating $tmp\n"; + my $ver = "Image::ExifTool::Lang::${lang}::VERSION"; + no strict 'refs'; + if ($$ver) { + $ver = $$ver; + $ver = int($ver * 100 + 1.5) / 100 if $newVersion; + } else { + $ver = 1.0; + } + $ver = sprintf('%.2f', $ver); + use strict 'refs'; + my $langName = $Image::ExifTool::langName{$lang} || $lang; + $langName =~ s/\s*\(.*//; + print XOUT <<HEADER; +#------------------------------------------------------------------------------ +# File: $lang.pm +# +# Description: ExifTool $langName language translations +# +# Notes: This file generated automatically by Image::ExifTool::TagInfoXML +#------------------------------------------------------------------------------ + +package Image::ExifTool::Lang::$lang; + +use strict; +use vars qw(\$VERSION); + +\$VERSION = '${ver}'; + +HEADER + print XOUT "\%Image::ExifTool::Lang::${lang}::Translate = (\n"; + # loop through all tag and table names + my $tag; + foreach $tag (sort keys %$langTags) { + my $desc = $$langTags{$tag}; + my $conv; + if (ref $desc) { + $conv = $$desc{PrintConv}; + $desc = $$desc{Description}; + # remove description if not necessary + # (not strictly correct -- should test against tag description, not name) + undef $desc if $desc and $desc eq $tag; + # remove unnecessary value translations + if ($conv) { + my @keys = keys %$conv; + foreach (@keys) { + delete $$conv{$_} if $_ eq $$conv{$_}; + } + undef $conv unless %$conv; + } + } + if (defined $desc) { + $desc = EscapePerl($desc); + } else { + next unless $conv; + } + print XOUT " '${tag}' => "; + unless ($conv) { + print XOUT "'${desc}',\n"; + next; + } + print XOUT "{\n"; + print XOUT " Description => '${desc}',\n" if defined $desc; + if ($conv) { + print XOUT " PrintConv => {\n"; + foreach (sort keys %$conv) { + my $str = EscapePerl($_); + my $val = EscapePerl($$conv{$_}); + print XOUT " '${str}' => '${val}',\n"; + } + print XOUT " },\n"; + } + print XOUT " },\n"; + } + # generate acknowledgements for this language + my $ack; + if ($credits{$lang}) { + $ack = "Thanks to $credits{$lang} for providing this translation."; + $ack =~ s/(.{1,76})( +|$)/$1\n/sg; # wrap text to 76 columns + $ack = "~head1 ACKNOWLEDGEMENTS\n\n$ack\n"; + } else { + $ack = ''; + } + my $footer = <<FOOTER; +); + +1; # end + + +__END__ + +~head1 NAME + +Image::ExifTool::Lang::$lang.pm - ExifTool $langName language translations + +~head1 DESCRIPTION + +This file is used by Image::ExifTool to generate localized tag descriptions +and values. + +~head1 AUTHOR + +Copyright 2003-2019, Phil Harvey (phil at owl.phy.queensu.ca) + +This library is free software; you can redistribute it and/or modify it +under the same terms as Perl itself. + +$ack~head1 SEE ALSO + +L<Image::ExifTool(3pm)|Image::ExifTool>, +L<Image::ExifTool::TagInfoXML(3pm)|Image::ExifTool::TagInfoXML> + +~cut +FOOTER + $footer =~ s/^~/=/mg; # un-do pod obfuscation + print XOUT $footer or $err = 1; + close XOUT or $err = 1; + if ($err or not rename($tmp, $out)) { + warn "Error writing $out\n"; + unlink $tmp; + $err = 1; + } + return $err ? 0 : 1; +} + +#------------------------------------------------------------------------------ +# load all lang modules into hash +# Inputs: 0) Hash reference, 1) specific language to load (undef for all) +sub LoadLangModules($;$) +{ + my ($langHash, $lang) = @_; + require Image::ExifTool; + my @langs = $lang ? ($lang) : @Image::ExifTool::langs; + foreach $lang (@langs) { + next if $lang eq $Image::ExifTool::defaultLang; + eval "require Image::ExifTool::Lang::$lang" or warn("Can't load Lang::$lang\n"), next; + my $xlat = "Image::ExifTool::Lang::${lang}::Translate"; + no strict 'refs'; + %$xlat or warn("Missing Info for $lang\n"), next; + $$langHash{$lang} = \%$xlat; + use strict 'refs'; + } +} + +#------------------------------------------------------------------------------ +# sort numbers first numerically, then strings alphabetically (case insensitive) +sub NumbersFirst +{ + my $rtnVal; + my ($bNum, $bDec); + ($bNum, $bDec) = ($1, $3) if $b =~ /^(-?[0-9]+)(\.(\d*))?$/; + if ($a =~ /^(-?[0-9]+)(\.(\d*))?$/) { + if (defined $bNum) { + $bNum += 1e9 if $numbersFirst == 2 and $bNum < 0; + my $aInt = $1; + $aInt += 1e9 if $numbersFirst == 2 and $aInt < 0; + # compare integer part as a number + $rtnVal = $aInt <=> $bNum; + unless ($rtnVal) { + my $aDec = $3 || 0; + $bDec or $bDec = 0; + # compare decimal part as an integer too + # (so that "1.10" comes after "1.9") + $rtnVal = $aDec <=> $bDec; + } + } else { + $rtnVal = -$numbersFirst; + } + } elsif (defined $bNum) { + $rtnVal = $numbersFirst; + } else { + my ($a2, $b2) = ($a, $b); + # expand numbers to 3 digits (with restrictions to avoid messing up ascii-hex tags) + $a2 =~ s/(\d+)/sprintf("%.3d",$1)/eg if $a2 =~ /^(APP|DMC-\w+ )?[.0-9 ]*$/ and length($a2)<16; + $b2 =~ s/(\d+)/sprintf("%.3d",$1)/eg if $b2 =~ /^(APP|DMC-\w+ )?[.0-9 ]*$/ and length($b2)<16; + $caseInsensitive and $rtnVal = (lc($a2) cmp lc($b2)); + $rtnVal or $rtnVal = ($a2 cmp $b2); + } + return $rtnVal; +} + +1; # end + + +__END__ + +=head1 NAME + +Image::ExifTool::TagInfoXML - Read/write tag information XML database + +=head1 DESCRIPTION + +This module is used to generate an XML database from all ExifTool tag +information. The XML database may then be edited and used to re-generate +the language modules (Image::ExifTool::Lang::*). + +=head1 METHODS + +=head2 Write + +Print complete tag information database in XML format. + + # save list of all tags + $success = Image::ExifTool::TagInfoXML::Write('dst.xml'); + + # list all IPTC tags to console, including Flags + Image::ExifTool::TagInfoXML::Write(undef, 'IPTC', Flags => 1); + + # write all EXIF Camera tags to file + Image::ExifTool::TagInfoXML::Write($outfile, 'exif:camera'); + +=over 4 + +=item Inputs: + +0) [optional] Output file name, or undef for console output. Output file +will be overwritten if it already exists. + +1) [optional] String of group names separated by colons to specify the group +to print. A specific IFD may not be given as a group, since EXIF tags may +be written to any IFD. Saves all groups if not specified. + +2) [optional] Hash of options values: + + Flags - Set to output 'flags' attribute + NoDesc - Set to suppress output of descriptions + Lang - Select a single language for output + +=item Return Value: + +True on success. + +=item Sample XML Output: + +=back + + <?xml version='1.0' encoding='UTF-8'?> + <taginfo> + + <table name='XMP::dc' g0='XMP' g1='XMP-dc' g2='Other'> + <desc lang='en'>XMP Dublin Core</desc> + <tag id='title' name='Title' type='lang-alt' writable='true' g2='Image'> + <desc lang='en'>Title</desc> + <desc lang='de'>Titel</desc> + <desc lang='fr'>Titre</desc> + </tag> + ... + </table> + + </taginfo> + +Flags (if selected and available) are formatted as a comma-separated list of +the following possible values: Avoid, Binary, List, Mandatory, Permanent, +Protected, Unknown and Unsafe. See the +L<tag name documentation|Image::ExifTool::TagNames> and +lib/Image/ExifTool/README for a description of these flags. For XMP List +tags, the list type (Alt, Bag or Seq) is also output as a flag if +applicable. + +=head2 BuildLangModules + +Build all Image::ExifTool::Lang modules from an XML database file. + + Image::ExifTool::TagInfoXML::BuildLangModules('src.xml'); + +=over 4 + +=item Inputs: + +0) XML file name + +1) Update flags: + + 0x01 = preserve version numbers + 0x02 = update all modules, even if they didn't change + 0x04 = update from scratch, ignoring existing definitions + 0x08 = override existing different descriptions and values + +=item Return Value: + +Number of modules updated, or negative on error. + +=back + +=head1 AUTHOR + +Copyright 2003-2019, Phil Harvey (phil at owl.phy.queensu.ca) + +This library is free software; you can redistribute it and/or modify it +under the same terms as Perl itself. + +=head1 SEE ALSO + +L<Image::ExifTool(3pm)|Image::ExifTool>, +L<Image::ExifTool::TagNames(3pm)|Image::ExifTool::TagNames> + +=cut diff --git a/lib/Image/ExifTool/TagLookup.pm b/lib/Image/ExifTool/TagLookup.pm new file mode 100644 index 0000000..5abdb6f --- /dev/null +++ b/lib/Image/ExifTool/TagLookup.pm @@ -0,0 +1,10946 @@ +#------------------------------------------------------------------------------ +# File: TagLookup.pm +# +# Description: Fast lookup for ExifTool tags +# +# Notes: This lookup is used to look up tag names for writing +# +# Revisions: 2004-12-31 - P. Harvey Created +# 2013-01-06 - PH Allow wildcards in FindTagInfo() +#------------------------------------------------------------------------------ + +package Image::ExifTool::TagLookup; + +use strict; +require Exporter; + +use vars qw($VERSION @ISA @EXPORT_OK); +use Image::ExifTool qw(:Utils); + +$VERSION = '1.17'; +@ISA = qw(Exporter); +@EXPORT_OK = qw(FindTagInfo TagExists); + +sub AddTags($$); +sub AddFields($$$$$$;$$); + +# +# Note: the lists below were generated by Image::ExifTool::BuildTagLookup +# + +#++++ Begin automatically generated code ++++ + +# list of tables containing writable tags +my @tableList = ( + 'Image::ExifTool::APP12::Ducky', + 'Image::ExifTool::Apple::Main', + 'Image::ExifTool::Canon::AFConfig', + 'Image::ExifTool::Canon::AFMicroAdj', + 'Image::ExifTool::Canon::Ambience', + 'Image::ExifTool::Canon::AspectInfo', + 'Image::ExifTool::Canon::CameraInfo1000D', + 'Image::ExifTool::Canon::CameraInfo1D', + 'Image::ExifTool::Canon::CameraInfo1DX', + 'Image::ExifTool::Canon::CameraInfo1DmkII', + 'Image::ExifTool::Canon::CameraInfo1DmkIII', + 'Image::ExifTool::Canon::CameraInfo1DmkIIN', + 'Image::ExifTool::Canon::CameraInfo1DmkIV', + 'Image::ExifTool::Canon::CameraInfo40D', + 'Image::ExifTool::Canon::CameraInfo450D', + 'Image::ExifTool::Canon::CameraInfo500D', + 'Image::ExifTool::Canon::CameraInfo50D', + 'Image::ExifTool::Canon::CameraInfo550D', + 'Image::ExifTool::Canon::CameraInfo5D', + 'Image::ExifTool::Canon::CameraInfo5DmkII', + 'Image::ExifTool::Canon::CameraInfo5DmkIII', + 'Image::ExifTool::Canon::CameraInfo600D', + 'Image::ExifTool::Canon::CameraInfo60D', + 'Image::ExifTool::Canon::CameraInfo650D', + 'Image::ExifTool::Canon::CameraInfo6D', + 'Image::ExifTool::Canon::CameraInfo70D', + 'Image::ExifTool::Canon::CameraInfo750D', + 'Image::ExifTool::Canon::CameraInfo7D', + 'Image::ExifTool::Canon::CameraInfo80D', + 'Image::ExifTool::Canon::CameraInfoPowerShot', + 'Image::ExifTool::Canon::CameraInfoPowerShot2', + 'Image::ExifTool::Canon::CameraInfoUnknown', + 'Image::ExifTool::Canon::CameraInfoUnknown32', + 'Image::ExifTool::Canon::CameraSettings', + 'Image::ExifTool::Canon::ColorBalance', + 'Image::ExifTool::Canon::ColorCalib', + 'Image::ExifTool::Canon::ColorCalib2', + 'Image::ExifTool::Canon::ColorCoefs', + 'Image::ExifTool::Canon::ColorCoefs2', + 'Image::ExifTool::Canon::ColorData1', + 'Image::ExifTool::Canon::ColorData2', + 'Image::ExifTool::Canon::ColorData3', + 'Image::ExifTool::Canon::ColorData4', + 'Image::ExifTool::Canon::ColorData5', + 'Image::ExifTool::Canon::ColorData6', + 'Image::ExifTool::Canon::ColorData7', + 'Image::ExifTool::Canon::ColorData8', + 'Image::ExifTool::Canon::ColorData9', + 'Image::ExifTool::Canon::ColorInfo', + 'Image::ExifTool::Canon::ContrastInfo', + 'Image::ExifTool::Canon::CropInfo', + 'Image::ExifTool::Canon::FaceDetect1', + 'Image::ExifTool::Canon::FaceDetect2', + 'Image::ExifTool::Canon::FaceDetect3', + 'Image::ExifTool::Canon::FileInfo', + 'Image::ExifTool::Canon::Flags', + 'Image::ExifTool::Canon::FocalLength', + 'Image::ExifTool::Canon::HDRInfo', + 'Image::ExifTool::Canon::LensInfo', + 'Image::ExifTool::Canon::LightingOpt', + 'Image::ExifTool::Canon::Main', + 'Image::ExifTool::Canon::MeasuredColor', + 'Image::ExifTool::Canon::ModifiedInfo', + 'Image::ExifTool::Canon::MovieInfo', + 'Image::ExifTool::Canon::MultiExp', + 'Image::ExifTool::Canon::MyColors', + 'Image::ExifTool::Canon::PSInfo', + 'Image::ExifTool::Canon::PSInfo2', + 'Image::ExifTool::Canon::Panorama', + 'Image::ExifTool::Canon::PreviewImageInfo', + 'Image::ExifTool::Canon::Processing', + 'Image::ExifTool::Canon::SerialInfo', + 'Image::ExifTool::Canon::ShotInfo', + 'Image::ExifTool::Canon::TimeInfo', + 'Image::ExifTool::Canon::VignettingCorr', + 'Image::ExifTool::Canon::VignettingCorr2', + 'Image::ExifTool::CanonCustom::Functions10D', + 'Image::ExifTool::CanonCustom::Functions1D', + 'Image::ExifTool::CanonCustom::Functions2', + 'Image::ExifTool::CanonCustom::Functions20D', + 'Image::ExifTool::CanonCustom::Functions30D', + 'Image::ExifTool::CanonCustom::Functions350D', + 'Image::ExifTool::CanonCustom::Functions400D', + 'Image::ExifTool::CanonCustom::Functions5D', + 'Image::ExifTool::CanonCustom::FunctionsD30', + 'Image::ExifTool::CanonCustom::PersonalFuncValues', + 'Image::ExifTool::CanonCustom::PersonalFuncs', + 'Image::ExifTool::CanonRaw::ExposureInfo', + 'Image::ExifTool::CanonRaw::FlashInfo', + 'Image::ExifTool::CanonRaw::ImageFormat', + 'Image::ExifTool::CanonRaw::ImageInfo', + 'Image::ExifTool::CanonRaw::Main', + 'Image::ExifTool::CanonRaw::MakeModel', + 'Image::ExifTool::CanonRaw::RawJpgInfo', + 'Image::ExifTool::CanonRaw::TimeStamp', + 'Image::ExifTool::CanonVRD::CropInfo', + 'Image::ExifTool::CanonVRD::DLOInfo', + 'Image::ExifTool::CanonVRD::DR4', + 'Image::ExifTool::CanonVRD::DR4Header', + 'Image::ExifTool::CanonVRD::GammaInfo', + 'Image::ExifTool::CanonVRD::Main', + 'Image::ExifTool::CanonVRD::ToneCurve', + 'Image::ExifTool::CanonVRD::Ver1', + 'Image::ExifTool::CanonVRD::Ver2', + 'Image::ExifTool::Casio::FaceInfo1', + 'Image::ExifTool::Casio::FaceInfo2', + 'Image::ExifTool::Casio::Main', + 'Image::ExifTool::Casio::Type2', + 'Image::ExifTool::Composite', + 'Image::ExifTool::DJI::Main', + 'Image::ExifTool::DJI::XMP', + 'Image::ExifTool::DNG::AdobeData', + 'Image::ExifTool::DarwinCore::Main', + 'Image::ExifTool::Exif::Main', + 'Image::ExifTool::Extra', + 'Image::ExifTool::FLIR::Main', + 'Image::ExifTool::FotoStation::Main', + 'Image::ExifTool::FotoStation::SoftEdit', + 'Image::ExifTool::FujiFilm::AFCSettings', + 'Image::ExifTool::FujiFilm::DriveSettings', + 'Image::ExifTool::FujiFilm::FocusSettings', + 'Image::ExifTool::FujiFilm::Main', + 'Image::ExifTool::FujiFilm::PrioritySettings', + 'Image::ExifTool::GE::Main', + 'Image::ExifTool::GPS::Main', + 'Image::ExifTool::IPTC::ApplicationRecord', + 'Image::ExifTool::IPTC::EnvelopeRecord', + 'Image::ExifTool::IPTC::NewsPhoto', + 'Image::ExifTool::JFIF::Main', + 'Image::ExifTool::Jpeg2000::Main', + 'Image::ExifTool::Kodak::CameraInfo', + 'Image::ExifTool::Kodak::IFD', + 'Image::ExifTool::Kodak::KDC_IFD', + 'Image::ExifTool::Kodak::Main', + 'Image::ExifTool::Kodak::Meta', + 'Image::ExifTool::Kodak::SubIFD0', + 'Image::ExifTool::Kodak::SubIFD1', + 'Image::ExifTool::Kodak::SubIFD2', + 'Image::ExifTool::Kodak::SubIFD3', + 'Image::ExifTool::Kodak::SubIFD5', + 'Image::ExifTool::Kodak::Type10', + 'Image::ExifTool::Kodak::Type2', + 'Image::ExifTool::Kodak::Type3', + 'Image::ExifTool::Kodak::Type4', + 'Image::ExifTool::Kodak::Type7', + 'Image::ExifTool::Kodak::Type9', + 'Image::ExifTool::MIE::Audio', + 'Image::ExifTool::MIE::Camera', + 'Image::ExifTool::MIE::Doc', + 'Image::ExifTool::MIE::Extender', + 'Image::ExifTool::MIE::Flash', + 'Image::ExifTool::MIE::GPS', + 'Image::ExifTool::MIE::Geo', + 'Image::ExifTool::MIE::Image', + 'Image::ExifTool::MIE::Lens', + 'Image::ExifTool::MIE::Main', + 'Image::ExifTool::MIE::Orient', + 'Image::ExifTool::MIE::Preview', + 'Image::ExifTool::MIE::Thumbnail', + 'Image::ExifTool::MIE::UTM', + 'Image::ExifTool::MIE::Video', + 'Image::ExifTool::MWG::Collections', + 'Image::ExifTool::MWG::Keywords', + 'Image::ExifTool::MWG::Regions', + 'Image::ExifTool::MacOS::MDItem', + 'Image::ExifTool::MacOS::XAttr', + 'Image::ExifTool::Microsoft::MP', + 'Image::ExifTool::Microsoft::MP1', + 'Image::ExifTool::Microsoft::Stitch', + 'Image::ExifTool::Microsoft::XMP', + 'Image::ExifTool::Minolta::CameraInfoA100', + 'Image::ExifTool::Minolta::CameraSettings', + 'Image::ExifTool::Minolta::CameraSettings5D', + 'Image::ExifTool::Minolta::CameraSettings7D', + 'Image::ExifTool::Minolta::CameraSettingsA100', + 'Image::ExifTool::Minolta::ISInfoA100', + 'Image::ExifTool::Minolta::Main', + 'Image::ExifTool::Minolta::WBInfoA100', + 'Image::ExifTool::MinoltaRaw::PRD', + 'Image::ExifTool::MinoltaRaw::RIF', + 'Image::ExifTool::MinoltaRaw::WBG', + 'Image::ExifTool::Motorola::Main', + 'Image::ExifTool::Nikon::AFInfo', + 'Image::ExifTool::Nikon::AFInfo2', + 'Image::ExifTool::Nikon::AFTune', + 'Image::ExifTool::Nikon::BarometerInfo', + 'Image::ExifTool::Nikon::CaptureOutput', + 'Image::ExifTool::Nikon::ColorBalance1', + 'Image::ExifTool::Nikon::ColorBalance2', + 'Image::ExifTool::Nikon::ColorBalance3', + 'Image::ExifTool::Nikon::ColorBalance4', + 'Image::ExifTool::Nikon::ColorBalanceA', + 'Image::ExifTool::Nikon::ColorBalanceB', + 'Image::ExifTool::Nikon::ColorBalanceC', + 'Image::ExifTool::Nikon::ColorBalanceUnknown', + 'Image::ExifTool::Nikon::DistortInfo', + 'Image::ExifTool::Nikon::FaceDetect', + 'Image::ExifTool::Nikon::FileInfo', + 'Image::ExifTool::Nikon::FlashInfo0100', + 'Image::ExifTool::Nikon::FlashInfo0102', + 'Image::ExifTool::Nikon::FlashInfo0103', + 'Image::ExifTool::Nikon::FlashInfo0106', + 'Image::ExifTool::Nikon::FlashInfo0107', + 'Image::ExifTool::Nikon::GEM', + 'Image::ExifTool::Nikon::HDRInfo', + 'Image::ExifTool::Nikon::ISOInfo', + 'Image::ExifTool::Nikon::LensData00', + 'Image::ExifTool::Nikon::LensData01', + 'Image::ExifTool::Nikon::LensData0204', + 'Image::ExifTool::Nikon::LensData0400', + 'Image::ExifTool::Nikon::LensData0402', + 'Image::ExifTool::Nikon::LensData0403', + 'Image::ExifTool::Nikon::LensData0800', + 'Image::ExifTool::Nikon::LocationInfo', + 'Image::ExifTool::Nikon::Main', + 'Image::ExifTool::Nikon::MultiExposure', + 'Image::ExifTool::Nikon::PictureControl', + 'Image::ExifTool::Nikon::PictureControl2', + 'Image::ExifTool::Nikon::PictureControl3', + 'Image::ExifTool::Nikon::PreviewIFD', + 'Image::ExifTool::Nikon::ROC', + 'Image::ExifTool::Nikon::RetouchInfo', + 'Image::ExifTool::Nikon::Scan', + 'Image::ExifTool::Nikon::ShotInfo', + 'Image::ExifTool::Nikon::ShotInfoD300S', + 'Image::ExifTool::Nikon::ShotInfoD300a', + 'Image::ExifTool::Nikon::ShotInfoD300b', + 'Image::ExifTool::Nikon::ShotInfoD3S', + 'Image::ExifTool::Nikon::ShotInfoD3X', + 'Image::ExifTool::Nikon::ShotInfoD3a', + 'Image::ExifTool::Nikon::ShotInfoD3b', + 'Image::ExifTool::Nikon::ShotInfoD40', + 'Image::ExifTool::Nikon::ShotInfoD4S', + 'Image::ExifTool::Nikon::ShotInfoD500', + 'Image::ExifTool::Nikon::ShotInfoD5000', + 'Image::ExifTool::Nikon::ShotInfoD5100', + 'Image::ExifTool::Nikon::ShotInfoD5200', + 'Image::ExifTool::Nikon::ShotInfoD700', + 'Image::ExifTool::Nikon::ShotInfoD7000', + 'Image::ExifTool::Nikon::ShotInfoD80', + 'Image::ExifTool::Nikon::ShotInfoD800', + 'Image::ExifTool::Nikon::ShotInfoD810', + 'Image::ExifTool::Nikon::ShotInfoD850', + 'Image::ExifTool::Nikon::ShotInfoD90', + 'Image::ExifTool::Nikon::Type2', + 'Image::ExifTool::Nikon::VRInfo', + 'Image::ExifTool::Nikon::WorldTime', + 'Image::ExifTool::NikonCapture::Brightness', + 'Image::ExifTool::NikonCapture::ColorBoost', + 'Image::ExifTool::NikonCapture::CropData', + 'Image::ExifTool::NikonCapture::DLightingHQ', + 'Image::ExifTool::NikonCapture::DLightingHS', + 'Image::ExifTool::NikonCapture::Exposure', + 'Image::ExifTool::NikonCapture::HighlightData', + 'Image::ExifTool::NikonCapture::Main', + 'Image::ExifTool::NikonCapture::NoiseReduction', + 'Image::ExifTool::NikonCapture::PhotoEffects', + 'Image::ExifTool::NikonCapture::PictureCtrl', + 'Image::ExifTool::NikonCapture::RedEyeData', + 'Image::ExifTool::NikonCapture::UnsharpData', + 'Image::ExifTool::NikonCapture::WBAdjData', + 'Image::ExifTool::NikonCustom::SettingsD3', + 'Image::ExifTool::NikonCustom::SettingsD4', + 'Image::ExifTool::NikonCustom::SettingsD40', + 'Image::ExifTool::NikonCustom::SettingsD5', + 'Image::ExifTool::NikonCustom::SettingsD500', + 'Image::ExifTool::NikonCustom::SettingsD5000', + 'Image::ExifTool::NikonCustom::SettingsD5100', + 'Image::ExifTool::NikonCustom::SettingsD5200', + 'Image::ExifTool::NikonCustom::SettingsD610', + 'Image::ExifTool::NikonCustom::SettingsD700', + 'Image::ExifTool::NikonCustom::SettingsD7000', + 'Image::ExifTool::NikonCustom::SettingsD80', + 'Image::ExifTool::NikonCustom::SettingsD800', + 'Image::ExifTool::NikonCustom::SettingsD810', + 'Image::ExifTool::NikonCustom::SettingsD850', + 'Image::ExifTool::NikonCustom::SettingsD90', + 'Image::ExifTool::Nintendo::CameraInfo', + 'Image::ExifTool::Olympus::CameraSettings', + 'Image::ExifTool::Olympus::Equipment', + 'Image::ExifTool::Olympus::FETags', + 'Image::ExifTool::Olympus::FocusInfo', + 'Image::ExifTool::Olympus::ImageProcessing', + 'Image::ExifTool::Olympus::Main', + 'Image::ExifTool::Olympus::RawDevelopment', + 'Image::ExifTool::Olympus::RawDevelopment2', + 'Image::ExifTool::Olympus::RawInfo', + 'Image::ExifTool::PDF::Info', + 'Image::ExifTool::PLUS::XMP', + 'Image::ExifTool::PNG::Main', + 'Image::ExifTool::PNG::PhysicalPixel', + 'Image::ExifTool::PNG::TextualData', + 'Image::ExifTool::Panasonic::Data1', + 'Image::ExifTool::Panasonic::FaceDetInfo', + 'Image::ExifTool::Panasonic::FaceRecInfo', + 'Image::ExifTool::Panasonic::FocusInfo', + 'Image::ExifTool::Panasonic::Leica2', + 'Image::ExifTool::Panasonic::Leica3', + 'Image::ExifTool::Panasonic::Leica5', + 'Image::ExifTool::Panasonic::Leica6', + 'Image::ExifTool::Panasonic::Leica9', + 'Image::ExifTool::Panasonic::Main', + 'Image::ExifTool::Panasonic::ShotInfo', + 'Image::ExifTool::Panasonic::Subdir', + 'Image::ExifTool::Panasonic::TimeInfo', + 'Image::ExifTool::PanasonicRaw::DistortionInfo', + 'Image::ExifTool::PanasonicRaw::Main', + 'Image::ExifTool::PanasonicRaw::WBInfo', + 'Image::ExifTool::PanasonicRaw::WBInfo2', + 'Image::ExifTool::Pentax::AEInfo', + 'Image::ExifTool::Pentax::AEInfo2', + 'Image::ExifTool::Pentax::AEInfo3', + 'Image::ExifTool::Pentax::AFInfo', + 'Image::ExifTool::Pentax::AFPointInfo', + 'Image::ExifTool::Pentax::AWBInfo', + 'Image::ExifTool::Pentax::BatteryInfo', + 'Image::ExifTool::Pentax::CameraInfo', + 'Image::ExifTool::Pentax::CameraSettings', + 'Image::ExifTool::Pentax::ColorInfo', + 'Image::ExifTool::Pentax::EVStepInfo', + 'Image::ExifTool::Pentax::FaceInfo', + 'Image::ExifTool::Pentax::FacePos', + 'Image::ExifTool::Pentax::FaceSize', + 'Image::ExifTool::Pentax::FilterInfo', + 'Image::ExifTool::Pentax::FlashInfo', + 'Image::ExifTool::Pentax::KelvinWB', + 'Image::ExifTool::Pentax::LensCorr', + 'Image::ExifTool::Pentax::LensData', + 'Image::ExifTool::Pentax::LensInfo', + 'Image::ExifTool::Pentax::LensInfo2', + 'Image::ExifTool::Pentax::LensInfo3', + 'Image::ExifTool::Pentax::LensInfo4', + 'Image::ExifTool::Pentax::LensInfo5', + 'Image::ExifTool::Pentax::LensInfoQ', + 'Image::ExifTool::Pentax::LensRec', + 'Image::ExifTool::Pentax::LevelInfo', + 'Image::ExifTool::Pentax::Main', + 'Image::ExifTool::Pentax::PixelShiftInfo', + 'Image::ExifTool::Pentax::SRInfo', + 'Image::ExifTool::Pentax::SRInfo2', + 'Image::ExifTool::Pentax::ShotInfo', + 'Image::ExifTool::Pentax::TempInfo', + 'Image::ExifTool::Pentax::TimeInfo', + 'Image::ExifTool::Pentax::Type2', + 'Image::ExifTool::Pentax::WBLevels', + 'Image::ExifTool::PhaseOne::Main', + 'Image::ExifTool::PhaseOne::SensorCalibration', + 'Image::ExifTool::PhotoMechanic::SoftEdit', + 'Image::ExifTool::PhotoMechanic::XMP', + 'Image::ExifTool::Photoshop::JPEG_Quality', + 'Image::ExifTool::Photoshop::Main', + 'Image::ExifTool::Photoshop::Resolution', + 'Image::ExifTool::PostScript::Main', + 'Image::ExifTool::QuickTime::MediaHeader', + 'Image::ExifTool::QuickTime::MovieHeader', + 'Image::ExifTool::QuickTime::Preview', + 'Image::ExifTool::QuickTime::TrackHeader', + 'Image::ExifTool::Reconyx::Main', + 'Image::ExifTool::Reconyx::Type2', + 'Image::ExifTool::Reconyx::Type3', + 'Image::ExifTool::Ricoh::FaceInfo', + 'Image::ExifTool::Ricoh::FirmwareInfo', + 'Image::ExifTool::Ricoh::ImageInfo', + 'Image::ExifTool::Ricoh::Main', + 'Image::ExifTool::Ricoh::SerialInfo', + 'Image::ExifTool::Ricoh::Subdir', + 'Image::ExifTool::Ricoh::ThetaSubdir', + 'Image::ExifTool::Samsung::Main', + 'Image::ExifTool::Samsung::OrientationInfo', + 'Image::ExifTool::Samsung::PictureWizard', + 'Image::ExifTool::Samsung::Type2', + 'Image::ExifTool::Sanyo::FaceInfo', + 'Image::ExifTool::Sanyo::Main', + 'Image::ExifTool::Sigma::Main', + 'Image::ExifTool::Sony::AFInfo', + 'Image::ExifTool::Sony::AFStatus15', + 'Image::ExifTool::Sony::AFStatus19', + 'Image::ExifTool::Sony::AFStatus79', + 'Image::ExifTool::Sony::CameraInfo', + 'Image::ExifTool::Sony::CameraInfo2', + 'Image::ExifTool::Sony::CameraInfo3', + 'Image::ExifTool::Sony::CameraSettings', + 'Image::ExifTool::Sony::CameraSettings2', + 'Image::ExifTool::Sony::CameraSettings3', + 'Image::ExifTool::Sony::Ericsson', + 'Image::ExifTool::Sony::ExtraInfo', + 'Image::ExifTool::Sony::ExtraInfo2', + 'Image::ExifTool::Sony::ExtraInfo3', + 'Image::ExifTool::Sony::FaceInfo', + 'Image::ExifTool::Sony::FaceInfo1', + 'Image::ExifTool::Sony::FaceInfo2', + 'Image::ExifTool::Sony::FaceInfoA', + 'Image::ExifTool::Sony::FocusInfo', + 'Image::ExifTool::Sony::ISOInfo', + 'Image::ExifTool::Sony::Main', + 'Image::ExifTool::Sony::MeterInfo', + 'Image::ExifTool::Sony::MeterInfo9', + 'Image::ExifTool::Sony::MoreInfo0201', + 'Image::ExifTool::Sony::MoreInfo0401', + 'Image::ExifTool::Sony::MoreSettings', + 'Image::ExifTool::Sony::Panorama', + 'Image::ExifTool::Sony::ShotInfo', + 'Image::ExifTool::Sony::Tag2010a', + 'Image::ExifTool::Sony::Tag2010b', + 'Image::ExifTool::Sony::Tag2010c', + 'Image::ExifTool::Sony::Tag2010d', + 'Image::ExifTool::Sony::Tag2010e', + 'Image::ExifTool::Sony::Tag2010f', + 'Image::ExifTool::Sony::Tag2010g', + 'Image::ExifTool::Sony::Tag2010h', + 'Image::ExifTool::Sony::Tag2010i', + 'Image::ExifTool::Sony::Tag202a', + 'Image::ExifTool::Sony::Tag9050a', + 'Image::ExifTool::Sony::Tag9050b', + 'Image::ExifTool::Sony::Tag9400a', + 'Image::ExifTool::Sony::Tag9400b', + 'Image::ExifTool::Sony::Tag9400c', + 'Image::ExifTool::Sony::Tag9402', + 'Image::ExifTool::Sony::Tag9403', + 'Image::ExifTool::Sony::Tag9404a', + 'Image::ExifTool::Sony::Tag9404b', + 'Image::ExifTool::Sony::Tag9404c', + 'Image::ExifTool::Sony::Tag9405a', + 'Image::ExifTool::Sony::Tag9405b', + 'Image::ExifTool::Sony::Tag9406', + 'Image::ExifTool::Sony::Tag940a', + 'Image::ExifTool::Sony::Tag940c', + 'Image::ExifTool::SonyIDC::Main', + 'Image::ExifTool::XMP::Album', + 'Image::ExifTool::XMP::DICOM', + 'Image::ExifTool::XMP::ExpressionMedia', + 'Image::ExifTool::XMP::GAudio', + 'Image::ExifTool::XMP::GDepth', + 'Image::ExifTool::XMP::GFocus', + 'Image::ExifTool::XMP::GImage', + 'Image::ExifTool::XMP::GPano', + 'Image::ExifTool::XMP::GSpherical', + 'Image::ExifTool::XMP::GettyImages', + 'Image::ExifTool::XMP::LImage', + 'Image::ExifTool::XMP::Lightroom', + 'Image::ExifTool::XMP::MediaPro', + 'Image::ExifTool::XMP::aas', + 'Image::ExifTool::XMP::acdsee', + 'Image::ExifTool::XMP::apple_fi', + 'Image::ExifTool::XMP::aux', + 'Image::ExifTool::XMP::cc', + 'Image::ExifTool::XMP::cell', + 'Image::ExifTool::XMP::creatorAtom', + 'Image::ExifTool::XMP::crs', + 'Image::ExifTool::XMP::dc', + 'Image::ExifTool::XMP::dex', + 'Image::ExifTool::XMP::digiKam', + 'Image::ExifTool::XMP::exif', + 'Image::ExifTool::XMP::exifEX', + 'Image::ExifTool::XMP::extensis', + 'Image::ExifTool::XMP::fpv', + 'Image::ExifTool::XMP::ics', + 'Image::ExifTool::XMP::iptcCore', + 'Image::ExifTool::XMP::iptcExt', + 'Image::ExifTool::XMP::pdf', + 'Image::ExifTool::XMP::photoshop', + 'Image::ExifTool::XMP::pmi', + 'Image::ExifTool::XMP::prism', + 'Image::ExifTool::XMP::prl', + 'Image::ExifTool::XMP::prm', + 'Image::ExifTool::XMP::pur', + 'Image::ExifTool::XMP::rdf', + 'Image::ExifTool::XMP::swf', + 'Image::ExifTool::XMP::tiff', + 'Image::ExifTool::XMP::x', + 'Image::ExifTool::XMP::xmp', + 'Image::ExifTool::XMP::xmpBJ', + 'Image::ExifTool::XMP::xmpDM', + 'Image::ExifTool::XMP::xmpMM', + 'Image::ExifTool::XMP::xmpNote', + 'Image::ExifTool::XMP::xmpPLUS', + 'Image::ExifTool::XMP::xmpRights', + 'Image::ExifTool::XMP::xmpTPg', +); + +# lookup for all writable tags +my %tagLookup = ( + 'aberrationcorrectiondistance' => { 103 => 0x69 }, + 'about' => { 466 => 'about' }, + 'aboutcvterm' => { 458 => 'AboutCvTerm' }, + 'aboutcvtermcvid' => { 458 => [\'AboutCvTerm','AboutCvTermCvId'] }, + 'aboutcvtermid' => { 458 => [\'AboutCvTerm','AboutCvTermCvTermId'] }, + 'aboutcvtermname' => { 458 => [\'AboutCvTerm','AboutCvTermCvTermName'] }, + 'aboutcvtermrefinedabout' => { 458 => [\'AboutCvTerm','AboutCvTermCvTermRefinedAbout'] }, + 'absolutealtitude' => { 110 => 'AbsoluteAltitude' }, + 'abspeakaudiofilepath' => { 472 => 'absPeakAudioFilePath' }, + 'academicfield' => { 462 => 'academicField' }, + 'acceleration' => { 113 => 0x9404, 453 => 'Acceleration' }, + 'accelerationtracking' => { 78 => 0x518 }, + 'accelerationvector' => { 1 => 0x8 }, + 'accelerometer' => { 366 => 0x3 }, + 'accelerometerx' => { 301 => 0x8d }, + 'accelerometery' => { 301 => 0x8e }, + 'accelerometerz' => { 301 => 0x8c }, + 'accessoryserialnumber' => { 301 => 0x54 }, + 'accessorytype' => { 301 => 0x53 }, + 'actionadvised' => { 125 => 0x2a }, + 'activearea' => { 113 => 0xc68d }, + 'actived-lighting' => { 214 => 0x22, 252 => 0x24 }, + 'actived-lightingmode' => { 252 => 0x25 }, + 'adaptervoltage' => { 131 => 0x407 }, + 'addaspectratioinfo' => { 78 => 0x80e }, + 'addiptcinformation' => { 78 => 0x815 }, + 'additionalmodelinformation' => { 458 => 'AddlModelInfo' }, + 'addoriginaldecisiondata' => { 78 => 0x80f, 79 => 0x11, 80 => 0x13, 83 => 0x14 }, + 'address' => { 152 => 'Address' }, + 'adjustmentmode' => { 373 => 0x15 }, + 'adlbracketingstep' => { 233 => 0x883 }, + 'adlbracketingtype' => { 233 => 0x884 }, + 'adobe' => { 114 => 'Adobe' }, + 'adultcontentwarning' => { 288 => 'AdultContentWarning', 465 => 'adultContentWarning' }, + 'advancedfilter' => { 121 => 0x1201 }, + 'advancedraw' => { 254 => 0x76a43203 }, + 'advancedscenetype' => { 301 => 0x3d }, + 'advisory' => { 470 => 'Advisory' }, + 'ae_iso' => { 309 => 0x2, 310 => 0x4, 311 => 0x12 }, + 'aeaperture' => { 309 => 0x1, 310 => 0x3, 311 => 0x11 }, + 'aeaperturesteps' => { 309 => 0x8, 310 => 0xb }, + 'aebautocancel' => { 78 => 0x104 }, + 'aebbracketvalue' => { 72 => 0x11 }, + 'aebracketingsteps' => { 232 => 0x174c, 233 => 0x87b, 241 => 0x1756 }, + 'aebsequence' => { 78 => 0x105 }, + 'aebsequenceautocancel' => { 76 => 0x9, 77 => 0x9, 79 => 0x8, 80 => 0x9, 83 => 0x9, 84 => 0x7 }, + 'aebshotcount' => { 78 => 0x106 }, + 'aebxv' => { 309 => 0x4, 310 => 0x6 }, + 'aeerror' => { 310 => 0x8 }, + 'aeexposuretime' => { 309 => 0x0, 310 => 0x2, 311 => 0x10 }, + 'aelbutton' => { 174 => 0x45 }, + 'aelexposureindicator' => { 174 => 0x51 }, + 'aelock' => { 174 => 0x5b, 263 => '4.2', 272 => '4.2', 278 => 0x201, 336 => 0x48, 381 => 0x40, 382 => 0x40, 383 => [0x86,0x286] }, + 'aelockbutton' => { 261 => '16.1', 263 => '4.1', 266 => '15.1', 267 => '16.1', 268 => '16.1', 270 => '30.1', 271 => '16.1', 272 => '4.1', 274 => '17.1', 276 => '17.1' }, + 'aelockbuttonplusdials' => { 261 => '16.2', 270 => '32.1', 274 => '44.1' }, + 'aelockformb-d80' => { 276 => '3.1' }, + 'aelockmetermodeafterfocus' => { 78 => 0x114 }, + 'aemaxaperture' => { 309 => 0x9, 310 => 0x10, 311 => 0x1c }, + 'aemaxaperture2' => { 309 => 0xa, 310 => 0x11, 311 => 0x1d }, + 'aemeteringmode' => { 309 => 0xc }, + 'aemeteringmode2' => { 309 => '13.1' }, + 'aemeteringsegments' => { 177 => 0x628, 336 => 0x209 }, + 'aemicroadjustment' => { 78 => 0x110 }, + 'aeminaperture' => { 309 => 0xb, 310 => 0x12, 311 => 0x1e }, + 'aeminexposuretime' => { 309 => 0x5, 310 => 0x13, 311 => 0x1f }, + 'aeprogrammode' => { 309 => 0x6 }, + 'aeprojectlink' => { 447 => 'aeProjectLink' }, + 'aeprojectlinkcompositionid' => { 447 => [\'aeProjectLink','aeProjectLinkCompositionID'] }, + 'aeprojectlinkfullpath' => { 447 => [\'aeProjectLink','aeProjectLinkFullPath'] }, + 'aeprojectlinkrenderoutputmoduleindex' => { 447 => [\'aeProjectLink','aeProjectLinkRenderOutputModuleIndex'] }, + 'aeprojectlinkrenderqueueitemid' => { 447 => [\'aeProjectLink','aeProjectLinkRenderQueueItemID'] }, + 'aeprojectlinkrendertimestamp' => { 447 => [\'aeProjectLink','aeProjectLinkRenderTimeStamp'] }, + 'aesetting' => { 33 => 0x21 }, + 'aewhitebalance' => { 309 => 0xd }, + 'aexv' => { 309 => 0x3, 310 => 0x5 }, + 'af-cpriority' => { 122 => '0.2' }, + 'af-cpriorityselection' => { 261 => '1.1', 262 => '1.1', 264 => '1.1', 265 => '1.1', 267 => '0.1', 268 => '0.1', 269 => '0.1', 270 => '1.1', 271 => '0.1', 274 => '1.1', 275 => '1.1' }, + 'af-csetting' => { 118 => 0x0 }, + 'af-cspeedtrackingsensitivity' => { 118 => '0.2' }, + 'af-ctrackingsensitivity' => { 118 => '0.1' }, + 'af-czoneareaswitching' => { 118 => '0.3' }, + 'af-onbutton' => { 264 => '70.1', 265 => '70.1', 275 => '70.1' }, + 'af-onformb-d10' => { 261 => '3.3', 270 => '3.2' }, + 'af-onformb-d11' => { 271 => '2.2' }, + 'af-onformb-d12' => { 274 => '50.1' }, + 'af-spriority' => { 122 => '0.1' }, + 'af-spriorityselection' => { 261 => '1.2', 262 => '1.2', 264 => '1.4', 265 => '1.4', 269 => '0.2', 270 => '1.2', 271 => '0.2', 274 => '1.2', 275 => '1.2' }, + 'afacceldeceltracking' => { 2 => 0x3 }, + 'afactivation' => { 261 => '2.1', 262 => '2.1', 264 => '78.3', 265 => '78.3', 270 => '2.1', 274 => '2.1', 275 => '78.3' }, + 'afadjustment' => { 336 => 0x72, 345 => 0x267 }, + 'afandmeteringbuttons' => { 78 => 0x701 }, + 'afaperture' => { 207 => 0x5, 208 => 0x5, 212 => 0x5 }, + 'afareaheight' => { 183 => [0x1a,0x34,0x50] }, + 'afareaillumination' => { 174 => 0x4b, 272 => '15.3' }, + 'afareamode' => { 120 => '0.2', 170 => 0x33, 174 => 0xe, 182 => 0x0, 183 => 0x5, 301 => 0xf, 363 => 0x1205, 374 => [0xa,0x3a], 381 => 0x11, 382 => 0x10, 383 => 0x24, 394 => 0xb043, 417 => 0x17 }, + 'afareamodesetting' => { 263 => '11.1', 266 => '0.1', 272 => '16.1', 276 => '2.1', 394 => 0x201c }, + 'afareapointsize' => { 120 => '0.3' }, + 'afareas' => { 278 => 0x304 }, + 'afareaselectionmethod' => { 2 => 0xd }, + 'afareaselectmethod' => { 78 => 0x51b }, + 'afareawidth' => { 183 => [0x18,0x32,0x4e] }, + 'afareaxposition' => { 183 => [0x14,0x2e,0x4a], 363 => 0x1203 }, + 'afareaxposition1' => { 363 => 0x1201 }, + 'afareayposition' => { 183 => [0x16,0x30,0x4c], 363 => 0x1204 }, + 'afareayposition1' => { 363 => 0x1202 }, + 'afareazonesize' => { 120 => '0.4' }, + 'afassist' => { 76 => 0x5, 84 => 0x5, 174 => 0x48, 261 => '2.5', 263 => '0.2', 266 => '0.2', 267 => '1.1', 268 => '1.1', 269 => '1.3', 270 => '2.4', 271 => '1.3', 272 => '0.2', 274 => '2.4', 276 => '2.3' }, + 'afassistbeam' => { 2 => 0x8, 78 => 0x50e, 79 => 0x4, 80 => 0x5, 81 => 0x4, 82 => 0x4, 83 => 0x5 }, + 'afassistlamp' => { 301 => 0x31 }, + 'afbuttonpressed' => { 383 => [0x83,0x283] }, + 'afconfigtool' => { 2 => 0x1 }, + 'afdefocus' => { 312 => 0x6 }, + 'afduringliveview' => { 78 => 0x511 }, + 'affinea' => { 441 => 'AffineA' }, + 'affineb' => { 441 => 'AffineB' }, + 'affinec' => { 441 => 'AffineC' }, + 'affined' => { 441 => 'AffineD' }, + 'affinetune' => { 184 => 0x0, 278 => 0x306 }, + 'affinetuneadj' => { 184 => 0x2, 225 => 0x2d1, 226 => 0x2dc, 278 => 0x307 }, + 'affinetuneindex' => { 184 => 0x1 }, + 'affinex' => { 441 => 'AffineX' }, + 'affiney' => { 441 => 'AffineY' }, + 'afhold' => { 312 => 0x1fd }, + 'afilluminator' => { 381 => 0x29, 394 => 0xb044 }, + 'afimageheight' => { 183 => [0x12,0x2c,0x48] }, + 'afimagewidth' => { 183 => [0x10,0x2a,0x46] }, + 'afintegrationtime' => { 312 => 0x7 }, + 'afmicroadj' => { 374 => [0x17d,0x50] }, + 'afmicroadjmode' => { 3 => 0x1, 378 => 0x131 }, + 'afmicroadjregisteredlenses' => { 378 => '305.1' }, + 'afmicroadjustment' => { 78 => 0x507 }, + 'afmicroadjvalue' => { 3 => 0x2, 378 => 0x130 }, + 'afmode' => { 107 => 0x3009, 121 => 0x1022, 170 => 0x16, 373 => 0x5 }, + 'afmoderestrictions' => { 262 => '50.3', 264 => '48.3', 265 => '48.3', 274 => '48.3', 275 => '48.3' }, + 'afonaelockbuttonswitch' => { 78 => 0x702 }, + 'afonbutton' => { 261 => '3.1', 262 => '47.1' }, + 'afpoint' => { 33 => 0x13, 106 => 0x18, 170 => 0x15, 182 => 0x1, 281 => 0x308, 373 => 0x1f, 374 => [0x37,0x7], 378 => 0x19, 379 => 0x18, 380 => [0x18,0x20] }, + 'afpointactivationarea' => { 77 => 0x11, 83 => 0x11 }, + 'afpointareaexpansion' => { 78 => 0x508 }, + 'afpointatshutterrelease' => { 374 => [0x39,0x9] }, + 'afpointautoselection' => { 78 => 0x50b }, + 'afpointbrightness' => { 78 => 0x50d, 261 => '2.4', 262 => '46.5', 264 => '2.2', 265 => '2.2', 274 => '2.3', 275 => '2.2' }, + 'afpointdisplayduringfocus' => { 2 => 0x10, 78 => 0x50c }, + 'afpointillumination' => { 77 => 0xa, 261 => '2.3', 262 => '46.2', 264 => '47.2', 265 => '47.2', 269 => '1.2', 270 => '2.3', 271 => '1.2', 274 => '47.2', 275 => '47.2', 276 => '2.4' }, + 'afpointinfocus' => { 374 => [0x38,0x8] }, + 'afpointmode' => { 317 => 0x3 }, + 'afpointposition' => { 107 => 0x2021, 301 => 0x4d }, + 'afpointregistration' => { 76 => 0x7 }, + 'afpoints' => { 173 => 0x10 }, + 'afpointselected' => { 174 => 0xd, 278 => 0x305, 336 => 0xe, 378 => 0x15, 379 => 0x14, 380 => [0x14,0x1c], 394 => 0x201e }, + 'afpointselected2' => { 317 => 0x4 }, + 'afpointselection' => { 77 => 0xb, 261 => '1.3', 262 => '1.3', 270 => '1.3', 274 => '1.3', 275 => '1.3' }, + 'afpointselectionmethod' => { 78 => 0x50f, 79 => 0xc, 80 => 0xd, 83 => 0xd }, + 'afpointsetting' => { 381 => 0x12, 382 => 0x11 }, + 'afpointsinfocus' => { 72 => 0xe, 182 => 0x2, 312 => 0xb, 313 => 0x4, 336 => [0xf,0x3c] }, + 'afpointsinfocus5d' => { 18 => 0x38 }, + 'afpointspotmetering' => { 77 => 0xd }, + 'afpointsselected' => { 313 => '4.1', 425 => 0x4 }, + 'afpointsspecial' => { 313 => '4.2' }, + 'afpointsunknown1' => { 312 => 0x0 }, + 'afpointsunknown2' => { 312 => 0x2 }, + 'afpointsused' => { 183 => 0x8, 374 => [0x10,0x16e] }, + 'afpointswitching' => { 2 => 0x4 }, + 'afpredictor' => { 312 => 0x4 }, + 'afresponse' => { 214 => 0xad }, + 'afresult' => { 283 => 0x1038 }, + 'afsearch' => { 278 => 0x303 }, + 'afsensoractive' => { 170 => 0x1 }, + 'afstatus' => { 363 => 0x1200 }, + 'afstatus_00_b4' => { 377 => 0x0 }, + 'afstatus_01_c4' => { 377 => 0x2 }, + 'afstatus_02_d4' => { 377 => 0x4 }, + 'afstatus_03_e4' => { 377 => 0x6 }, + 'afstatus_04_f4' => { 377 => 0x8 }, + 'afstatus_05_g4' => { 377 => 0xa }, + 'afstatus_06_h4' => { 377 => 0xc }, + 'afstatus_07_b3' => { 377 => 0xe }, + 'afstatus_08_c3' => { 377 => 0x10 }, + 'afstatus_09_d3' => { 377 => 0x12 }, + 'afstatus_10_e3' => { 377 => 0x14 }, + 'afstatus_11_f3' => { 377 => 0x16 }, + 'afstatus_12_g3' => { 377 => 0x18 }, + 'afstatus_13_h3' => { 377 => 0x1a }, + 'afstatus_14_b2' => { 377 => 0x1c }, + 'afstatus_15_c2' => { 377 => 0x1e }, + 'afstatus_16_d2' => { 377 => 0x20 }, + 'afstatus_17_e2' => { 377 => 0x22 }, + 'afstatus_18_f2' => { 377 => 0x24 }, + 'afstatus_19_g2' => { 377 => 0x26 }, + 'afstatus_20_h2' => { 377 => 0x28 }, + 'afstatus_21_c1' => { 377 => 0x2a }, + 'afstatus_22_d1' => { 377 => 0x2c }, + 'afstatus_23_e1' => { 377 => 0x2e }, + 'afstatus_24_f1' => { 377 => 0x30 }, + 'afstatus_25_g1' => { 377 => 0x32 }, + 'afstatus_26_a7_vertical' => { 377 => 0x34 }, + 'afstatus_27_a6_vertical' => { 377 => 0x36 }, + 'afstatus_28_a5_vertical' => { 377 => 0x38 }, + 'afstatus_29_c7_vertical' => { 377 => 0x3a }, + 'afstatus_30_c6_vertical' => { 377 => 0x3c }, + 'afstatus_31_c5_vertical' => { 377 => 0x3e }, + 'afstatus_32_e7_vertical' => { 377 => 0x40 }, + 'afstatus_33_e6_center_vertical' => { 377 => 0x42 }, + 'afstatus_34_e5_vertical' => { 377 => 0x44 }, + 'afstatus_35_g7_vertical' => { 377 => 0x46 }, + 'afstatus_36_g6_vertical' => { 377 => 0x48 }, + 'afstatus_37_g5_vertical' => { 377 => 0x4a }, + 'afstatus_38_i7_vertical' => { 377 => 0x4c }, + 'afstatus_39_i6_vertical' => { 377 => 0x4e }, + 'afstatus_40_i5_vertical' => { 377 => 0x50 }, + 'afstatus_41_a7' => { 377 => 0x52 }, + 'afstatus_42_b7' => { 377 => 0x54 }, + 'afstatus_43_c7' => { 377 => 0x56 }, + 'afstatus_44_d7' => { 377 => 0x58 }, + 'afstatus_45_e7' => { 377 => 0x5a }, + 'afstatus_46_f7' => { 377 => 0x5c }, + 'afstatus_47_g7' => { 377 => 0x5e }, + 'afstatus_48_h7' => { 377 => 0x60 }, + 'afstatus_49_i7' => { 377 => 0x62 }, + 'afstatus_50_a6' => { 377 => 0x64 }, + 'afstatus_51_b6' => { 377 => 0x66 }, + 'afstatus_52_c6' => { 377 => 0x68 }, + 'afstatus_53_d6' => { 377 => 0x6a }, + 'afstatus_54_e6_center' => { 377 => 0x6c }, + 'afstatus_55_f6' => { 377 => 0x6e }, + 'afstatus_56_g6' => { 377 => 0x70 }, + 'afstatus_57_h6' => { 377 => 0x72 }, + 'afstatus_58_i6' => { 377 => 0x74 }, + 'afstatus_59_a5' => { 377 => 0x76 }, + 'afstatus_60_b5' => { 377 => 0x78 }, + 'afstatus_61_c5' => { 377 => 0x7a }, + 'afstatus_62_d5' => { 377 => 0x7c }, + 'afstatus_63_e5' => { 377 => 0x7e }, + 'afstatus_64_f5' => { 377 => 0x80 }, + 'afstatus_65_g5' => { 377 => 0x82 }, + 'afstatus_66_h5' => { 377 => 0x84 }, + 'afstatus_67_i5' => { 377 => 0x86 }, + 'afstatus_68_c11' => { 377 => 0x88 }, + 'afstatus_69_d11' => { 377 => 0x8a }, + 'afstatus_70_e11' => { 377 => 0x8c }, + 'afstatus_71_f11' => { 377 => 0x8e }, + 'afstatus_72_g11' => { 377 => 0x90 }, + 'afstatus_73_b10' => { 377 => 0x92 }, + 'afstatus_74_c10' => { 377 => 0x94 }, + 'afstatus_75_d10' => { 377 => 0x96 }, + 'afstatus_76_e10' => { 377 => 0x98 }, + 'afstatus_77_f10' => { 377 => 0x9a }, + 'afstatus_78_g10' => { 377 => 0x9c }, + 'afstatus_79_h10' => { 377 => 0x9e }, + 'afstatus_80_b9' => { 377 => 0xa0 }, + 'afstatus_81_c9' => { 377 => 0xa2 }, + 'afstatus_82_d9' => { 377 => 0xa4 }, + 'afstatus_83_e9' => { 377 => 0xa6 }, + 'afstatus_84_f9' => { 377 => 0xa8 }, + 'afstatus_85_g9' => { 377 => 0xaa }, + 'afstatus_86_h9' => { 377 => 0xac }, + 'afstatus_87_b8' => { 377 => 0xae }, + 'afstatus_88_c8' => { 377 => 0xb0 }, + 'afstatus_89_d8' => { 377 => 0xb2 }, + 'afstatus_90_e8' => { 377 => 0xb4 }, + 'afstatus_91_f8' => { 377 => 0xb6 }, + 'afstatus_92_g8' => { 377 => 0xb8 }, + 'afstatus_93_h8' => { 377 => 0xba }, + 'afstatus_94_e6_center_f2-8' => { 377 => 0xbc }, + 'afstatusactivesensor' => { 170 => 0x2, 374 => [0x4,0x3b], 378 => 0x1e, 379 => 0x1b, 380 => [0x1b,0x21] }, + 'afstatusbottom' => { 170 => 0x8, 378 => 0x2a, 379 => 0x21, 380 => 0x21 }, + 'afstatusbottom-left' => { 170 => 0x12, 379 => 0x2b, 380 => 0x2b }, + 'afstatusbottom-right' => { 170 => 0x6, 379 => 0x1f, 380 => 0x1f }, + 'afstatusbottomassist-left' => { 378 => 0x28 }, + 'afstatusbottomassist-right' => { 378 => 0x2c }, + 'afstatusbottomhorizontal' => { 375 => 0x10, 376 => 0x1c }, + 'afstatusbottomvertical' => { 375 => 0x16, 376 => 0x26 }, + 'afstatuscenter-10' => { 378 => 0x34 }, + 'afstatuscenter-11' => { 378 => 0x36 }, + 'afstatuscenter-12' => { 378 => 0x38 }, + 'afstatuscenter-14' => { 378 => 0x3c }, + 'afstatuscenter-7' => { 378 => 0x2e }, + 'afstatuscenter-9' => { 378 => 0x32 }, + 'afstatuscenter-horizontal' => { 378 => 0x30 }, + 'afstatuscenter-vertical' => { 378 => 0x3a }, + 'afstatuscenterf2-8' => { 378 => 0x4c }, + 'afstatuscenterhorizontal' => { 170 => 0x2f, 375 => 0xc, 376 => 0x18, 379 => 0x2f, 380 => 0x2f }, + 'afstatuscentervertical' => { 170 => 0xc, 375 => 0x14, 376 => 0x22, 379 => 0x25, 380 => 0x25 }, + 'afstatusfarleft' => { 375 => 0x6, 378 => 0x26 }, + 'afstatusfarlefthorizontal' => { 376 => 0x4 }, + 'afstatusfarleftvertical' => { 376 => 0x12 }, + 'afstatusfarright' => { 375 => 0x18, 378 => 0x44 }, + 'afstatusfarrighthorizontal' => { 376 => 0x2c }, + 'afstatusfarrightvertical' => { 376 => 0x34 }, + 'afstatusleft' => { 170 => 0x2d, 375 => 0x2, 378 => 0x22, 379 => 0x2d, 380 => 0x2d }, + 'afstatuslefthorizontal' => { 376 => 0x6 }, + 'afstatusleftvertical' => { 376 => 0xe }, + 'afstatuslower-left' => { 375 => 0x4, 378 => 0x24 }, + 'afstatuslower-lefthorizontal' => { 376 => 0xa }, + 'afstatuslower-leftvertical' => { 376 => 0x10 }, + 'afstatuslower-middle' => { 375 => 0x22, 376 => 0x24 }, + 'afstatuslower-right' => { 375 => 0x1e, 378 => 0x4a }, + 'afstatuslower-righthorizontal' => { 376 => 0x32 }, + 'afstatuslower-rightvertical' => { 376 => 0x3a }, + 'afstatuslowerfarleft' => { 376 => 0x8 }, + 'afstatuslowerfarright' => { 376 => 0x30 }, + 'afstatusmiddlehorizontal' => { 170 => 0xa, 379 => 0x23, 380 => 0x23 }, + 'afstatusnearleft' => { 375 => 0xe, 376 => 0x1a }, + 'afstatusnearright' => { 375 => 0xa, 376 => 0x16 }, + 'afstatusright' => { 170 => 0x31, 375 => 0x1c, 378 => 0x48, 379 => 0x31, 380 => 0x31 }, + 'afstatusrighthorizontal' => { 376 => 0x2e }, + 'afstatusrightvertical' => { 376 => 0x38 }, + 'afstatustop' => { 170 => 0xe, 378 => 0x40, 379 => 0x27, 380 => 0x27 }, + 'afstatustop-left' => { 170 => 0x10, 379 => 0x29, 380 => 0x29 }, + 'afstatustop-right' => { 170 => 0x4, 379 => 0x1d, 380 => 0x1d }, + 'afstatustopassist-left' => { 378 => 0x3e }, + 'afstatustopassist-right' => { 378 => 0x42 }, + 'afstatustophorizontal' => { 375 => 0x8, 376 => 0x14 }, + 'afstatustopvertical' => { 375 => 0x12, 376 => 0x1e }, + 'afstatusupper-left' => { 375 => 0x0, 378 => 0x20 }, + 'afstatusupper-lefthorizontal' => { 376 => 0x2 }, + 'afstatusupper-leftvertical' => { 376 => 0xc }, + 'afstatusupper-middle' => { 375 => 0x20, 376 => 0x20 }, + 'afstatusupper-right' => { 375 => 0x1a, 378 => 0x46 }, + 'afstatusupper-righthorizontal' => { 376 => 0x2a }, + 'afstatusupper-rightvertical' => { 376 => 0x36 }, + 'afstatusupperfarleft' => { 376 => 0x0 }, + 'afstatusupperfarright' => { 376 => 0x28 }, + 'afstatusviewfinder' => { 2 => 0x12 }, + 'aftracking' => { 394 => 0x2021 }, + 'aftrackingsensitivity' => { 2 => 0x2 }, + 'aftype' => { 374 => 0x2 }, + 'afwithshutter' => { 381 => 0x2a }, + 'aggregateissuenumber' => { 462 => 'aggregateIssueNumber' }, + 'aggregationtype' => { 462 => 'aggregationType' }, + 'agreement' => { 465 => 'agreement' }, + 'ah2greeninterpolationthreshold' => { 131 => 0xe4e }, + 'aiservocontinuousshooting' => { 77 => 0x15 }, + 'aiservofirstimage' => { 2 => 0x5 }, + 'aiservofirstimagepriority' => { 78 => 0x519 }, + 'aiservoimagepriority' => { 78 => 0x503 }, + 'aiservosecondimage' => { 2 => 0x6 }, + 'aiservosecondimagepriority' => { 78 => 0x51a }, + 'aiservotrackingmethod' => { 78 => 0x504 }, + 'aiservotrackingsensitivity' => { 77 => 0x14, 78 => 0x502 }, + 'album' => { 472 => 'album' }, + 'alreadyapplied' => { 448 => 'AlreadyApplied' }, + 'alternatetitle' => { 462 => 'alternateTitle' }, + 'alternatetitlea-lang' => { 462 => [\'alternateTitle','alternateTitleA-lang'] }, + 'alternatetitlea-platform' => { 462 => [\'alternateTitle','alternateTitleA-platform'] }, + 'alternatetitletext' => { 462 => [\'alternateTitle','alternateTitleText'] }, + 'altitude' => { 185 => 0x6 }, + 'alttapename' => { 472 => 'altTapeName' }, + 'alttimecode' => { 472 => 'altTimecode' }, + 'alttimecodetimeformat' => { 472 => [\'altTimecode','altTimecodeTimeFormat'] }, + 'alttimecodetimevalue' => { 472 => [\'altTimecode','altTimecodeTimeValue'] }, + 'alttimecodevalue' => { 472 => [\'altTimecode','altTimecodeValue'] }, + 'ambienceselection' => { 4 => 0x1 }, + 'ambientinfrared' => { 359 => 0x5c }, + 'ambientlight' => { 359 => 0x5e }, + 'ambienttemperature' => { 113 => 0x9400, 357 => 0x14, 358 => 0x46, 359 => 0x50, 417 => 0x4, 453 => 'Temperature' }, + 'ambienttemperaturefahrenheit' => { 357 => 0x13, 358 => 0x44, 359 => 0x4e }, + 'analogbalance' => { 113 => 0xc627 }, + 'analogcaptureiso' => { 131 => 0x89e }, + 'analogisotable' => { 131 => 0x89d }, + 'angleadj' => { 97 => 0x10003, 103 => 0x8b }, + 'angleinforoll' => { 443 => 'AngleInfoRoll' }, + 'angleinfoyaw' => { 443 => 'AngleInfoYaw' }, + 'anti-blur' => { 394 => 0xb04b }, + 'antialiasstrength' => { 113 => 0xc632 }, + 'aperturelock' => { 262 => '38.2', 264 => '38.2', 265 => '38.2', 274 => '38.2', 275 => '38.2' }, + 'aperturerange' => { 78 => 0x10d }, + 'apertureringuse' => { 317 => '1.4' }, + 'aperturesetting' => { 174 => 0x7, 381 => 0x30, 382 => 0x29, 383 => 0x1 }, + 'aperturevalue' => { 87 => 0x2, 113 => 0x9202, 283 => 0x1002, 345 => 0x401, 452 => 'ApertureValue' }, + 'applekeywords' => { 287 => 'AAPL:Keywords' }, + 'applicationkeystring' => { 131 => 0x400 }, + 'applicationnotes' => { 113 => 0x2bc, 306 => 0x2bc }, + 'applicationrecordversion' => { 125 => 0x0 }, + 'applyshootingmeteringmode' => { 78 => 0x10e }, + 'approved' => { 454 => 'Approved' }, + 'approvedby' => { 454 => 'ApprovedBy' }, + 'approximatefnumber' => { 296 => 0x313, 303 => 0x3406 }, + 'approximatefocusdistance' => { 444 => 'ApproximateFocusDistance' }, + 'appversion' => { 456 => 'AppVersion' }, + 'aquahsl' => { 97 => 0x20914 }, + 'armidentifier' => { 126 => 0x78 }, + 'armversion' => { 126 => 0x7a }, + 'artfilter' => { 278 => 0x529 }, + 'artfiltereffect' => { 278 => 0x52f }, + 'artist' => { 113 => 0x13b, 291 => 'Artist', 336 => 0x22e, 468 => 'Artist', 472 => 'artist' }, + 'artmode' => { 107 => 0x301b }, + 'artmodeparameters' => { 107 => 0x310b }, + 'artworkcircadatecreated' => { 458 => [\'ArtworkOrObject','ArtworkOrObjectAOCircaDateCreated'] }, + 'artworkcontentdescription' => { 458 => [\'ArtworkOrObject','ArtworkOrObjectAOContentDescription'] }, + 'artworkcontributiondescription' => { 458 => [\'ArtworkOrObject','ArtworkOrObjectAOContributionDescription'] }, + 'artworkcopyrightnotice' => { 458 => [\'ArtworkOrObject','ArtworkOrObjectAOCopyrightNotice'] }, + 'artworkcopyrightownerid' => { 458 => [\'ArtworkOrObject','ArtworkOrObjectAOCurrentCopyrightOwnerId'] }, + 'artworkcopyrightownername' => { 458 => [\'ArtworkOrObject','ArtworkOrObjectAOCurrentCopyrightOwnerName'] }, + 'artworkcreator' => { 458 => [\'ArtworkOrObject','ArtworkOrObjectAOCreator'] }, + 'artworkcreatorid' => { 458 => [\'ArtworkOrObject','ArtworkOrObjectAOCreatorId'] }, + 'artworkdatecreated' => { 458 => [\'ArtworkOrObject','ArtworkOrObjectAODateCreated'] }, + 'artworklicensorid' => { 458 => [\'ArtworkOrObject','ArtworkOrObjectAOCurrentLicensorId'] }, + 'artworklicensorname' => { 458 => [\'ArtworkOrObject','ArtworkOrObjectAOCurrentLicensorName'] }, + 'artworkorobject' => { 458 => 'ArtworkOrObject' }, + 'artworkphysicaldescription' => { 458 => [\'ArtworkOrObject','ArtworkOrObjectAOPhysicalDescription'] }, + 'artworksource' => { 458 => [\'ArtworkOrObject','ArtworkOrObjectAOSource'] }, + 'artworksourceinventoryno' => { 458 => [\'ArtworkOrObject','ArtworkOrObjectAOSourceInvNo'] }, + 'artworksourceinvurl' => { 458 => [\'ArtworkOrObject','ArtworkOrObjectAOSourceInvURL'] }, + 'artworkstyleperiod' => { 458 => [\'ArtworkOrObject','ArtworkOrObjectAOStylePeriod'] }, + 'artworktitle' => { 458 => [\'ArtworkOrObject','ArtworkOrObjectAOTitle'] }, + 'aspectframe' => { 282 => 0x1113 }, + 'aspectratio' => { 5 => 0x0, 282 => 0x1112, 336 => 0x80, 381 => 0x55, 382 => 0x55, 383 => 0xa }, + 'assetid' => { 437 => 'AssetID' }, + 'asshoticcprofile' => { 113 => 0xc68f }, + 'asshotneutral' => { 113 => 0xc628 }, + 'asshotpreprofilematrix' => { 113 => 0xc690 }, + 'asshotprofilename' => { 113 => 0xc6f6 }, + 'asshotwhitexy' => { 113 => 0xc629 }, + 'assignbktbutton' => { 261 => '4.2', 262 => '16.1', 264 => '16.1', 265 => '16.1', 274 => '16.1', 275 => '16.1' }, + 'assignfuncbutton' => { 78 => 0x70b }, + 'assignmb-d17af-onbutton' => { 265 => '79.1' }, + 'assignmb-d17funcbutton' => { 265 => '67.1' }, + 'assignmb-d17funcbuttonplusdials' => { 265 => '68.1' }, + 'assignmb-d18af-onbutton' => { 275 => '79.1' }, + 'assignmb-d18funcbutton' => { 275 => '67.1' }, + 'assignmb-d18funcbuttonplusdials' => { 275 => '68.1' }, + 'assignmoviefunc1buttonplusdials' => { 264 => '75.1', 265 => '75.1', 275 => '75.1' }, + 'assignmoviefunc2button' => { 264 => '82.1', 265 => '82.1', 275 => '82.1' }, + 'assignmoviepreviewbuttonplusdials' => { 264 => '75.2', 265 => '75.2', 275 => '75.2' }, + 'assignmovierecordbutton' => { 262 => '43.2', 274 => '45.1' }, + 'assignmovierecordbuttonplusdials' => { 264 => '45.1', 265 => '45.1', 275 => '45.1' }, + 'assignmoviesubselector' => { 264 => '74.1', 265 => '74.1', 275 => '74.1' }, + 'assignmoviesubselectorplusdials' => { 264 => '76.1', 265 => '76.1', 275 => '76.1' }, + 'assignremotefnbutton' => { 262 => '54.1', 274 => '51.1' }, + 'assistbuttonfunction' => { 76 => 0xd }, + 'atcaptureusercrop' => { 131 => 0x943 }, + 'attributionname' => { 445 => 'attributionName' }, + 'attributionurl' => { 445 => 'attributionURL' }, + 'audio' => { 301 => 0x20 }, + 'audiobitrate' => { 63 => 0x6c, 458 => 'audioBitRate' }, + 'audiobitratemode' => { 458 => 'audioBitRateMode' }, + 'audiobitspersample' => { 458 => 'audioBitsPerSample' }, + 'audiochannelcount' => { 458 => 'audioChannelCount' }, + 'audiochannels' => { 63 => 0x70 }, + 'audiochanneltype' => { 472 => 'audioChannelType' }, + 'audiocompression' => { 146 => 'Compression' }, + 'audiocompressor' => { 472 => 'audioCompressor' }, + 'audiodata' => { 431 => 'Data' }, + 'audioduration' => { 125 => 0x99 }, + 'audiomimetype' => { 431 => 'Mime' }, + 'audiomoddate' => { 472 => 'audioModDate' }, + 'audiooutcue' => { 125 => 0x9a }, + 'audiosamplerate' => { 63 => 0x6e, 472 => 'audioSampleRate' }, + 'audiosampletype' => { 472 => 'audioSampleType' }, + 'audiosamplingrate' => { 125 => 0x97 }, + 'audiosamplingresolution' => { 125 => 0x98 }, + 'audiotype' => { 125 => 0x96 }, + 'author' => { 148 => 'Author', 287 => 'Author', 291 => 'Author', 352 => 'Author', 442 => 'author', 459 => 'Author', 470 => 'Author' }, + 'authorsposition' => { 460 => 'AuthorsPosition' }, + 'autoafpointcolortracking' => { 78 => 0x51c }, + 'autoafpointseleositraf' => { 2 => 0xa }, + 'autoaperture' => { 327 => '0.1' }, + 'autobracket' => { 373 => 0x19 }, + 'autobracketing' => { 121 => 0x1100, 336 => 0x18, 363 => 0x1007 }, + 'autobracketingmode' => { 273 => '12.3' }, + 'autobracketingset' => { 273 => '12.1' }, + 'autobracketmodem' => { 261 => '21.2', 262 => '13.3', 264 => '13.2', 265 => '13.2', 270 => '26.2', 274 => '13.3', 275 => '13.2' }, + 'autobracketorder' => { 174 => 0x43, 261 => '21.3', 262 => '13.2', 264 => '13.1', 265 => '13.1', 270 => '26.3', 271 => '12.2', 272 => '2.2', 273 => '12.2', 274 => '13.2', 275 => '13.1', 276 => '13.2' }, + 'autobracketset' => { 261 => '21.1', 262 => '13.1', 266 => '11.1', 267 => '12.1', 268 => '12.1', 270 => '26.1', 271 => '12.1', 272 => '2.1', 274 => '13.1', 276 => '13.1' }, + 'autobrightness' => { 448 => 'AutoBrightness' }, + 'autocontrast' => { 448 => 'AutoContrast' }, + 'autodistortioncontrol' => { 195 => 0x4 }, + 'autodynamicrange' => { 121 => 0x140b }, + 'autoexposure' => { 448 => 'AutoExposure' }, + 'autoexposurebracketing' => { 72 => 0x10 }, + 'autoflashisosensitivity' => { 264 => '38.5', 265 => '38.5', 275 => '38.5' }, + 'autofocus' => { 281 => 0x209 }, + 'autofp' => { 272 => '7.3', 276 => '31.4' }, + 'autoiso' => { 72 => 0x1, 107 => 0x3008, 263 => '1.1', 272 => '1.1' }, + 'autoisomax' => { 263 => '1.2', 272 => '1.2' }, + 'autoisominshutterspeed' => { 263 => '1.3', 272 => '1.3' }, + 'autolateralca' => { 448 => 'AutoLateralCA' }, + 'autolightingoptimizer' => { 15 => 0xbe, 16 => 0xbf, 19 => 0xbf, 59 => 0x2, 78 => 0x204, 97 => 0x20500, 103 => 0x6f }, + 'autolightingoptimizeron' => { 97 => '0x20500.0', 103 => 0x6e }, + 'autoportraitframed' => { 394 => 0x2016 }, + 'autoredeye' => { 254 => 0xfe28a44f }, + 'autorotate' => { 72 => 0x1b }, + 'autoshadows' => { 448 => 'AutoShadows' }, + 'autotone' => { 448 => 'AutoTone' }, + 'autowhiteversion' => { 448 => 'AutoWhiteVersion' }, + 'auxiliarylens' => { 214 => 0x82 }, + 'avaperturesetting' => { 317 => 0x13 }, + 'averageblacklevel' => { 42 => 0xe7, 44 => 0xfb, 45 => 0x114, 46 => 0x146 }, + 'averagelv' => { 177 => 0x38 }, + 'avsettingwithoutlens' => { 78 => 0x707 }, + 'azimuth' => { 156 => 'Azimuth' }, + 'babyage' => { 301 => [0x8010,0x33] }, + 'babyname' => { 301 => 0x66 }, + 'backgroundalpha' => { 467 => 'bgalpha' }, + 'baseexposurecompensation' => { 317 => 0x15 }, + 'baseiso' => { 72 => 0x2, 91 => 0x101c, 131 => 0x903, 303 => 0x312a, 423 => 0x6 }, + 'baseisodaylight' => { 131 => 0x910 }, + 'baseisoflash' => { 131 => 0x913 }, + 'baseisofluorescent' => { 131 => 0x912 }, + 'baseisotungsten' => { 131 => 0x911 }, + 'baselineexposure' => { 113 => 0xc62a }, + 'baselineexposureoffset' => { 113 => 0xc7a5 }, + 'baselinenoise' => { 113 => 0xc62b }, + 'baselinesharpness' => { 113 => 0xc62c }, + 'baseurl' => { 470 => 'BaseURL' }, + 'batterylevel' => { 381 => 0x51, 385 => 0xc, 386 => 0x4, 387 => 0x4, 424 => 0x7 }, + 'batterylevelgrip1' => { 424 => 0x6 }, + 'batterylevelgrip2' => { 424 => 0x8 }, + 'batteryorder' => { 261 => '12.5', 270 => '13.2', 271 => '2.1', 274 => '3.1' }, + 'batterystate' => { 174 => 0x60, 381 => 0x50, 387 => 0x14 }, + 'batterytemperature' => { 385 => 0x1, 387 => 0x2, 424 => 0x5 }, + 'batterytype' => { 60 => 0x38, 359 => 0x66 }, + 'batteryunknown' => { 385 => 0x2, 387 => 0x0 }, + 'batteryvoltage' => { 131 => 0x408, 357 => 0x2a, 358 => 0x49, 359 => 0x62, 385 => 0x8 }, + 'batteryvoltage1' => { 387 => 0x6 }, + 'batteryvoltage2' => { 387 => 0x8 }, + 'batteryvoltageavg' => { 359 => 0x64 }, + 'bayergreensplit' => { 113 => 0xc62d }, + 'bayerpattern' => { 130 => 0xf902, 178 => 0x17 }, + 'beatspliceparams' => { 472 => 'beatSpliceParams' }, + 'beatspliceparamsriseindecibel' => { 472 => [\'beatSpliceParams','beatSpliceParamsRiseInDecibel'] }, + 'beatspliceparamsriseintimeduration' => { 472 => [\'beatSpliceParams','beatSpliceParamsRiseInTimeDuration'] }, + 'beatspliceparamsriseintimedurationscale' => { 472 => [\'beatSpliceParams','beatSpliceParamsRiseInTimeDurationScale'] }, + 'beatspliceparamsriseintimedurationvalue' => { 472 => [\'beatSpliceParams','beatSpliceParamsRiseInTimeDurationValue'] }, + 'beatspliceparamsusefilebeatsmarker' => { 472 => [\'beatSpliceParams','beatSpliceParamsUseFileBeatsMarker'] }, + 'beep' => { 261 => '13.1', 262 => '5.4', 263 => '0.1', 266 => '2.1', 267 => '3.1', 268 => '3.1', 270 => '10.1', 272 => '0.1', 274 => '5.5', 276 => '4.1' }, + 'beeppitch' => { 271 => '3.1' }, + 'beepvolume' => { 271 => '4.5' }, + 'bestqualityscale' => { 113 => 0xc65c }, + 'bestshotmode' => { 107 => 0x3007 }, + 'bitdepth' => { 153 => 'BitDepth', 178 => 0x11, 222 => 0x41 }, + 'bitspercomponent' => { 127 => 0x87 }, + 'bitspersample' => { 113 => 0x102, 306 => 0xa, 468 => 'BitsPerSample' }, + 'blackacquirerows' => { 131 => 0x18ba }, + 'blacklevel' => { 113 => 0xc61a, 193 => 0x20, 214 => 0x3d, 283 => [0x401,0x1012], 345 => 0x21d }, + 'blacklevel2' => { 282 => 0x600, 286 => 0x600 }, + 'blacklevelblue' => { 306 => 0x1e }, + 'blacklevelbottom' => { 131 => 0x3f0 }, + 'blackleveldata' => { 345 => 0x223 }, + 'blackleveldeltah' => { 113 => 0xc61b }, + 'blackleveldeltav' => { 113 => 0xc61c }, + 'blacklevelgreen' => { 306 => 0x1d }, + 'blacklevelred' => { 306 => 0x1c }, + 'blacklevelrepeatdim' => { 113 => 0xc619 }, + 'blacklevelrough' => { 131 => 0x40e }, + 'blacklevelroughafter' => { 131 => 0x416 }, + 'blackleveltop' => { 131 => 0x3ef }, + 'blackpoint' => { 336 => 0x200 }, + 'blacks2012' => { 448 => 'Blacks2012' }, + 'blacksadj' => { 427 => 0x9018 }, + 'bleachbypasstoning' => { 336 => 0x7f }, + 'blockshotafresponse' => { 264 => '1.5', 265 => '1.5', 275 => '1.5' }, + 'blogtitle' => { 462 => 'blogTitle' }, + 'blogurl' => { 462 => 'blogURL' }, + 'bluebalance' => { 283 => 0x1018, 306 => 0x12, 336 => 0x1b }, + 'bluecurvelimits' => { 102 => 0x1fe }, + 'bluecurvepoints' => { 101 => 0x79, 102 => 0x1d4 }, + 'bluehsl' => { 97 => 0x20915 }, + 'bluehue' => { 448 => 'BlueHue' }, + 'bluesaturation' => { 448 => 'BlueSaturation' }, + 'bluratinfinity' => { 433 => 'BlurAtInfinity' }, + 'blurcontrol' => { 336 => 0x82 }, + 'blurwarning' => { 121 => 0x1300 }, + 'bodybatteryadload' => { 315 => 0x3 }, + 'bodybatteryadnoload' => { 315 => 0x2 }, + 'bodybatterystate' => { 315 => '1.1' }, + 'bodybatteryvoltage1' => { 315 => 0x2 }, + 'bodybatteryvoltage2' => { 315 => 0x4 }, + 'bodybatteryvoltage3' => { 315 => 0x6 }, + 'bodybatteryvoltage4' => { 315 => 0x8 }, + 'bodyfirmware' => { 364 => 0x0 }, + 'bodyfirmwareversion' => { 279 => 0x104, 280 => 0x100, 283 => 0x104 }, + 'bodyserialnumber' => { 364 => 0x10 }, + 'bookedition' => { 462 => 'bookEdition' }, + 'bootloaderversion' => { 358 => 0x26 }, + 'bracketmode' => { 54 => 0x3 }, + 'bracketsequence' => { 107 => 0x301d }, + 'bracketsettings' => { 301 => 0x45 }, + 'bracketshotnumber' => { 54 => 0x5, 317 => 0x9, 392 => 0x2b }, + 'bracketshotnumber2' => { 392 => 0x2d }, + 'bracketstep' => { 171 => 0xe }, + 'bracketvalue' => { 54 => 0x4 }, + 'brightness' => { 113 => 0xfe53, 147 => 'Brightness', 167 => 'Brightness', 171 => 0x2c, 216 => 0x34, 217 => 0x39, 218 => 0x41, 357 => 0x25, 359 => 0x54, 381 => 0x22, 394 => 0x2007, 448 => 'Brightness' }, + 'brightnessadj' => { 102 => 0x114, 247 => 0x0, 257 => 0x2d, 427 => 0x8018 }, + 'brightnessvalue' => { 113 => 0x9203, 177 => [0x691,0x49c3], 283 => 0x1003, 399 => 0x1e, 402 => 0x1140, 403 => 0x1140, 404 => 0x111c, 405 => 0x1198, 406 => 0x1174, 407 => 0x102c, 408 => 0x224, 409 => 0x224, 410 => 0x219, 452 => 'BrightnessValue' }, + 'bulbduration' => { 72 => 0x18 }, + 'burstcount' => { 131 => 0x40d }, + 'burstmode' => { 133 => 0xa, 301 => 0x2a }, + 'burstmode2' => { 133 => 0x18 }, + 'burstshot' => { 373 => 0x34 }, + 'burstspeed' => { 301 => 0x77 }, + 'burstuuid' => { 1 => 0xb }, + 'buttonfunctioncontroloff' => { 78 => 0x70a }, + 'bwadjustment' => { 121 => 0x1049 }, + 'bwfilter' => { 171 => 0x2a, 179 => 0x39 }, + 'bwmode' => { 283 => 0x203 }, + 'by-line' => { 125 => 0x50 }, + 'by-linetitle' => { 125 => 0x55 }, + 'bytecount' => { 462 => 'byteCount' }, + 'c14configuration' => { 131 => 0x1964 }, + 'cacheversion' => { 113 => 0xc7aa }, + 'calibratedfocallength' => { 110 => 'CalibratedFocalLength' }, + 'calibratedopticalcenterx' => { 110 => 'CalibratedOpticalCenterX' }, + 'calibratedopticalcentery' => { 110 => 'CalibratedOpticalCenterY' }, + 'calibration' => { 373 => [0x24,0x30] }, + 'calibrationhistory' => { 131 => 0x9c9 }, + 'calibrationilluminant1' => { 113 => 0xc65a }, + 'calibrationilluminant2' => { 113 => 0xc65b }, + 'calibrationversion' => { 131 => 0x9c6 }, + 'callforimage' => { 437 => 'CallForImage' }, + 'cameraangle' => { 472 => 'cameraAngle' }, + 'cameracalibration1' => { 113 => 0xc623 }, + 'cameracalibration2' => { 113 => 0xc624 }, + 'cameracalibrationsig' => { 113 => 0xc6f3 }, + 'cameracolorcalibration01' => { 35 => 0x0, 36 => 0x0 }, + 'cameracolorcalibration02' => { 35 => 0x4, 36 => 0x5 }, + 'cameracolorcalibration03' => { 35 => 0x8, 36 => 0xa }, + 'cameracolorcalibration04' => { 35 => 0xc, 36 => 0xf }, + 'cameracolorcalibration05' => { 35 => 0x10, 36 => 0x14 }, + 'cameracolorcalibration06' => { 35 => 0x14, 36 => 0x19 }, + 'cameracolorcalibration07' => { 35 => 0x18, 36 => 0x1e }, + 'cameracolorcalibration08' => { 35 => 0x1c, 36 => 0x23 }, + 'cameracolorcalibration09' => { 35 => 0x20, 36 => 0x28 }, + 'cameracolorcalibration10' => { 35 => 0x24, 36 => 0x2d }, + 'cameracolorcalibration11' => { 35 => 0x28, 36 => 0x32 }, + 'cameracolorcalibration12' => { 35 => 0x2c, 36 => 0x37 }, + 'cameracolorcalibration13' => { 35 => 0x30, 36 => 0x3c }, + 'cameracolorcalibration14' => { 35 => 0x34, 36 => 0x41 }, + 'cameracolorcalibration15' => { 35 => 0x38, 36 => 0x46 }, + 'camerae-mountversion' => { 426 => 0xb }, + 'cameraelevationangle' => { 113 => 0x9405, 453 => 'CameraElevationAngle' }, + 'camerafilename' => { 437 => 'CameraFilename' }, + 'cameraid' => { 283 => 0x209, 372 => 0x209 }, + 'cameraiso' => { 33 => 0x10 }, + 'cameralabel' => { 113 => 0xc7a1, 472 => 'cameraLabel' }, + 'cameramakemodel' => { 437 => 'CameraMakeModel' }, + 'cameramodel' => { 345 => 0x410, 472 => 'cameraModel' }, + 'cameramodelid' => { 167 => 'CameraModelID' }, + 'cameramove' => { 472 => 'cameraMove' }, + 'cameraorientation' => { 6 => 0x30, 8 => 0x7d, 10 => 0x30, 12 => 0x35, 13 => 0x30, 14 => 0x30, 15 => 0x31, 16 => 0x31, 17 => 0x35, 18 => 0x27, 19 => 0x31, 20 => 0x7d, 21 => 0x38, 22 => 0x36, 23 => 0x7d, 24 => 0x83, 25 => 0x84, 27 => 0x35, 28 => 0x96, 301 => 0x8f, 340 => 0x1, 345 => 0x100, 387 => [0x16,0x18], 414 => 0x28, 415 => 0x24, 416 => 0x29 }, + 'cameraowner' => { 134 => 0xc353 }, + 'cameraparameters' => { 283 => 0x2050 }, + 'camerapicturestyle' => { 27 => 0xaf }, + 'camerapitch' => { 109 => 0x9 }, + 'cameraprofile' => { 448 => 'CameraProfile' }, + 'cameraprofiledigest' => { 448 => 'CameraProfileDigest' }, + 'camerarawcolortone' => { 103 => 0xe1 }, + 'camerarawcontrast' => { 103 => 0xe3 }, + 'camerarawhighlightpoint' => { 103 => 0xe6 }, + 'camerarawlinear' => { 103 => 0xe4 }, + 'camerarawoutputhighlightpoint' => { 103 => 0xe8 }, + 'camerarawoutputshadowpoint' => { 103 => 0xe9 }, + 'camerarawsaturation' => { 103 => 0xe2 }, + 'camerarawshadowpoint' => { 103 => 0xe7 }, + 'camerarawsharpness' => { 103 => 0xe5 }, + 'cameraroll' => { 109 => 0xb }, + 'cameraserialnumber' => { 113 => 0xc62f, 169 => 'CameraSerialNumber', 437 => 'CameraSerialNumber' }, + 'camerasettingsversion' => { 278 => 0x0 }, + 'cameratemperature' => { 6 => 0x18, 8 => 0x1b, 10 => 0x18, 12 => 0x19, 13 => 0x18, 14 => 0x18, 15 => 0x19, 16 => 0x19, 17 => 0x19, 18 => 0x17, 19 => 0x19, 20 => 0x1b, 21 => 0x19, 22 => 0x19, 23 => 0x1b, 24 => 0x1b, 25 => 0x1b, 26 => 0x1b, 27 => 0x19, 28 => 0x1b, 29 => [0x87,0x91], 30 => [0x99,0x9f,0xa4,0xa8,0x105], 32 => ['-3',0x64,0x47,0x53,0x5b,0x5c], 72 => 0xc, 131 => 0x406, 282 => 0x1306, 296 => 0x320, 303 => 0x3402, 336 => 0x47, 370 => 0x43, 418 => 0x5 }, + 'cameratemperature4' => { 341 => 0x14 }, + 'cameratemperature5' => { 341 => 0x16 }, + 'cameratemperaturerangemax' => { 115 => 0x5 }, + 'cameratemperaturerangemin' => { 115 => 0x6 }, + 'cameratype' => { 72 => 0x1a, 283 => 0x207 }, + 'cameratype2' => { 279 => 0x100 }, + 'camerayaw' => { 109 => 0xa }, + 'camreverse' => { 110 => 'CamReverse' }, + 'canondr4' => { 114 => 'CanonDR4' }, + 'canonexposuremode' => { 33 => 0x14 }, + 'canonfiledescription' => { 91 => 0x805 }, + 'canonfilelength' => { 60 => 0xe }, + 'canonfirmwareversion' => { 60 => 0x7, 91 => 0x80b }, + 'canonflashinfo' => { 91 => 0x1028 }, + 'canonflashmode' => { 33 => 0x4 }, + 'canonimagesize' => { 9 => 0x39, 33 => 0xa }, + 'canonimagetype' => { 60 => 0x6, 91 => 0x815 }, + 'canonmodelid' => { 60 => 0x10, 91 => 0x1834 }, + 'canonvrd' => { 114 => 'CanonVRD' }, + 'caption' => { 442 => 'caption' }, + 'caption-abstract' => { 125 => 0x78 }, + 'captionsauthornames' => { 451 => 'CaptionsAuthorNames' }, + 'captionsdatetimestamps' => { 451 => 'CaptionsDateTimeStamps' }, + 'captionwriter' => { 460 => 'CaptionWriter' }, + 'captureframerate' => { 107 => 0x4001 }, + 'captureheightnormal' => { 131 => 0x1839 }, + 'capturelook' => { 131 => 0xc48 }, + 'capturesoftware' => { 435 => 'CaptureSoftware' }, + 'capturewidthnormal' => { 131 => 0x1838 }, + 'capturewidthtest' => { 131 => 0x1842 }, + 'cardshutterlock' => { 174 => 0x49 }, + 'casioimagesize' => { 107 => 0x9 }, + 'catalogsets' => { 125 => 0xff, 430 => 'CatalogSets', 440 => 'CatalogSets' }, + 'categories' => { 60 => 0x23, 442 => 'categories' }, + 'category' => { 125 => 0xf, 277 => 0x30, 460 => 'Category' }, + 'cbcrgain' => { 370 => 0xa036 }, + 'cbcrgaindefault' => { 370 => 0xa035 }, + 'cbcrmatrix' => { 370 => 0xa034 }, + 'cbcrmatrixdefault' => { 370 => 0xa033 }, + 'ccdboardversion' => { 296 => 0x331 }, + 'ccdscanmode' => { 283 => 0x1039 }, + 'ccdsensitivity' => { 244 => 0x6 }, + 'ccdversion' => { 296 => 0x330 }, + 'cellglobalid' => { 446 => 'cgi' }, + 'celllength' => { 113 => 0x109 }, + 'cellr' => { 446 => 'r' }, + 'celltowerid' => { 446 => 'cellid' }, + 'cellwidth' => { 113 => 0x108 }, + 'centerafarea' => { 272 => '15.1' }, + 'centerfocuspoint' => { 276 => '2.2' }, + 'centerpixel' => { 131 => 0x40c }, + 'centerweightedareasize' => { 261 => '7.1', 262 => '8.1', 264 => '8.1', 265 => '8.1', 269 => '7.1', 270 => '5.1', 271 => '7.1', 272 => '6.3', 274 => '8.1', 275 => '8.1', 276 => '8.1' }, + 'certificate' => { 476 => 'Certificate' }, + 'cfainterpolationalgorithm' => { 131 => 0xe60 }, + 'cfainterpolationmetric' => { 131 => 0xe61 }, + 'cfaoffsetcols' => { 131 => 0xc71 }, + 'cfaoffsetrows' => { 131 => 0xc6f }, + 'cfapattern' => { 113 => 0xa302, 306 => 0x9, 452 => 'CFAPattern' }, + 'cfapattern2' => { 113 => 0x828e }, + 'cfapatterncolumns' => { 452 => [\'CFAPattern','CFAPatternColumns'] }, + 'cfapatternrows' => { 452 => [\'CFAPattern','CFAPatternRows'] }, + 'cfapatternvalues' => { 452 => [\'CFAPattern','CFAPatternValues'] }, + 'cfarepeatpatterndim' => { 113 => 0x828d }, + 'cfazipperfixthreshold' => { 131 => 0xe62 }, + 'channel' => { 462 => 'channel' }, + 'channela-lang' => { 462 => [\'channel','channelA-lang'] }, + 'channelchannel' => { 462 => [\'channel','channelChannel'] }, + 'channels' => { 146 => 'Channels' }, + 'channelsubchannel1' => { 462 => [\'channel','channelSubchannel1'] }, + 'channelsubchannel2' => { 462 => [\'channel','channelSubchannel2'] }, + 'channelsubchannel3' => { 462 => [\'channel','channelSubchannel3'] }, + 'channelsubchannel4' => { 462 => [\'channel','channelSubchannel4'] }, + 'checkmark' => { 97 => 0x10101, 102 => 0x26a }, + 'checkmark2' => { 103 => 0x8e }, + 'childfontfiles' => { 477 => [\'Fonts','FontsChildFontFiles'] }, + 'chmodeshootingspeed' => { 261 => '10.3', 262 => '11.2' }, + 'chromablurradius' => { 113 => 0xc631 }, + 'chromanoisecolorspace' => { 131 => 0xe6d }, + 'chromanoiseedgemapthresh' => { 131 => 0xe6c }, + 'chromanoisehighfthresh' => { 131 => 0xe6a }, + 'chromanoiselowfthresh' => { 131 => 0xe6b }, + 'chromaticaberration' => { 97 => 0x20703, 103 => 0x66, 370 => 0xa051 }, + 'chromaticaberrationb' => { 448 => 'ChromaticAberrationB' }, + 'chromaticaberrationblue' => { 97 => 0x20708, 103 => 0x6b }, + 'chromaticaberrationcorr' => { 74 => [0x4,0x5] }, + 'chromaticaberrationcorrection' => { 113 => 0x7034, 326 => 0x1, 427 => 0x900d }, + 'chromaticaberrationcorrparams' => { 113 => 0x7035, 422 => 0x66a, 423 => [0x37c,0x384,0x39c,0x3b0,0x3b8] }, + 'chromaticaberrationon' => { 97 => '0x20703.0', 103 => 0x62 }, + 'chromaticaberrationr' => { 448 => 'ChromaticAberrationR' }, + 'chromaticaberrationred' => { 97 => 0x20707, 103 => 0x6a }, + 'chromaticaberrationsetting' => { 75 => 0x6 }, + 'chrominancenoisereduction' => { 97 => 0x20601, 103 => 0x5e, 373 => 0x1a }, + 'chrominancenr_tiff_jpeg' => { 103 => 0x60 }, + 'circadatecreated' => { 458 => 'CircaDateCreated' }, + 'circgradbasedcorractive' => { 448 => [\'CircularGradientBasedCorrections','CircularGradientBasedCorrectionsCorrectionActive'] }, + 'circgradbasedcorramount' => { 448 => [\'CircularGradientBasedCorrections','CircularGradientBasedCorrectionsCorrectionAmount'] }, + 'circgradbasedcorrbrightness' => { 448 => [\'CircularGradientBasedCorrections','CircularGradientBasedCorrectionsLocalBrightness'] }, + 'circgradbasedcorrclarity' => { 448 => [\'CircularGradientBasedCorrections','CircularGradientBasedCorrectionsLocalClarity'] }, + 'circgradbasedcorrclarity2012' => { 448 => [\'CircularGradientBasedCorrections','CircularGradientBasedCorrectionsLocalClarity2012'] }, + 'circgradbasedcorrcontrast' => { 448 => [\'CircularGradientBasedCorrections','CircularGradientBasedCorrectionsLocalContrast'] }, + 'circgradbasedcorrcontrast2012' => { 448 => [\'CircularGradientBasedCorrections','CircularGradientBasedCorrectionsLocalContrast2012'] }, + 'circgradbasedcorrdefringe' => { 448 => [\'CircularGradientBasedCorrections','CircularGradientBasedCorrectionsLocalDefringe'] }, + 'circgradbasedcorrexposure' => { 448 => [\'CircularGradientBasedCorrections','CircularGradientBasedCorrectionsLocalExposure'] }, + 'circgradbasedcorrexposure2012' => { 448 => [\'CircularGradientBasedCorrections','CircularGradientBasedCorrectionsLocalExposure2012'] }, + 'circgradbasedcorrhighlights2012' => { 448 => [\'CircularGradientBasedCorrections','CircularGradientBasedCorrectionsLocalHighlights2012'] }, + 'circgradbasedcorrhue' => { 448 => [\'CircularGradientBasedCorrections','CircularGradientBasedCorrectionsLocalToningHue'] }, + 'circgradbasedcorrluminancenoise' => { 448 => [\'CircularGradientBasedCorrections','CircularGradientBasedCorrectionsLocalLuminanceNoise'] }, + 'circgradbasedcorrmaskalpha' => { 448 => [\'CircularGradientBasedCorrections','CircularGradientBasedCorrectionsCorrectionMasksAlpha'] }, + 'circgradbasedcorrmaskangle' => { 448 => [\'CircularGradientBasedCorrections','CircularGradientBasedCorrectionsCorrectionMasksAngle'] }, + 'circgradbasedcorrmaskbottom' => { 448 => [\'CircularGradientBasedCorrections','CircularGradientBasedCorrectionsCorrectionMasksBottom'] }, + 'circgradbasedcorrmaskcentervalue' => { 448 => [\'CircularGradientBasedCorrections','CircularGradientBasedCorrectionsCorrectionMasksCenterValue'] }, + 'circgradbasedcorrmaskcenterweight' => { 448 => [\'CircularGradientBasedCorrections','CircularGradientBasedCorrectionsCorrectionMasksCenterWeight'] }, + 'circgradbasedcorrmaskdabs' => { 448 => [\'CircularGradientBasedCorrections','CircularGradientBasedCorrectionsCorrectionMasksDabs'] }, + 'circgradbasedcorrmaskfeather' => { 448 => [\'CircularGradientBasedCorrections','CircularGradientBasedCorrectionsCorrectionMasksFeather'] }, + 'circgradbasedcorrmaskflipped' => { 448 => [\'CircularGradientBasedCorrections','CircularGradientBasedCorrectionsCorrectionMasksFlipped'] }, + 'circgradbasedcorrmaskflow' => { 448 => [\'CircularGradientBasedCorrections','CircularGradientBasedCorrectionsCorrectionMasksFlow'] }, + 'circgradbasedcorrmaskfullx' => { 448 => [\'CircularGradientBasedCorrections','CircularGradientBasedCorrectionsCorrectionMasksFullX'] }, + 'circgradbasedcorrmaskfully' => { 448 => [\'CircularGradientBasedCorrections','CircularGradientBasedCorrectionsCorrectionMasksFullY'] }, + 'circgradbasedcorrmaskleft' => { 448 => [\'CircularGradientBasedCorrections','CircularGradientBasedCorrectionsCorrectionMasksLeft'] }, + 'circgradbasedcorrmaskmidpoint' => { 448 => [\'CircularGradientBasedCorrections','CircularGradientBasedCorrectionsCorrectionMasksMidpoint'] }, + 'circgradbasedcorrmaskperimetervalue' => { 448 => [\'CircularGradientBasedCorrections','CircularGradientBasedCorrectionsCorrectionMasksPerimeterValue'] }, + 'circgradbasedcorrmaskradius' => { 448 => [\'CircularGradientBasedCorrections','CircularGradientBasedCorrectionsCorrectionMasksRadius'] }, + 'circgradbasedcorrmaskright' => { 448 => [\'CircularGradientBasedCorrections','CircularGradientBasedCorrectionsCorrectionMasksRight'] }, + 'circgradbasedcorrmaskroundness' => { 448 => [\'CircularGradientBasedCorrections','CircularGradientBasedCorrectionsCorrectionMasksRoundness'] }, + 'circgradbasedcorrmasks' => { 448 => [\'CircularGradientBasedCorrections','CircularGradientBasedCorrectionsCorrectionMasks'] }, + 'circgradbasedcorrmasksizex' => { 448 => [\'CircularGradientBasedCorrections','CircularGradientBasedCorrectionsCorrectionMasksSizeX'] }, + 'circgradbasedcorrmasksizey' => { 448 => [\'CircularGradientBasedCorrections','CircularGradientBasedCorrectionsCorrectionMasksSizeY'] }, + 'circgradbasedcorrmasktop' => { 448 => [\'CircularGradientBasedCorrections','CircularGradientBasedCorrectionsCorrectionMasksTop'] }, + 'circgradbasedcorrmaskvalue' => { 448 => [\'CircularGradientBasedCorrections','CircularGradientBasedCorrectionsCorrectionMasksMaskValue'] }, + 'circgradbasedcorrmaskversion' => { 448 => [\'CircularGradientBasedCorrections','CircularGradientBasedCorrectionsCorrectionMasksVersion'] }, + 'circgradbasedcorrmaskwhat' => { 448 => [\'CircularGradientBasedCorrections','CircularGradientBasedCorrectionsCorrectionMasksWhat'] }, + 'circgradbasedcorrmaskx' => { 448 => [\'CircularGradientBasedCorrections','CircularGradientBasedCorrectionsCorrectionMasksX'] }, + 'circgradbasedcorrmasky' => { 448 => [\'CircularGradientBasedCorrections','CircularGradientBasedCorrectionsCorrectionMasksY'] }, + 'circgradbasedcorrmaskzerox' => { 448 => [\'CircularGradientBasedCorrections','CircularGradientBasedCorrectionsCorrectionMasksZeroX'] }, + 'circgradbasedcorrmaskzeroy' => { 448 => [\'CircularGradientBasedCorrections','CircularGradientBasedCorrectionsCorrectionMasksZeroY'] }, + 'circgradbasedcorrmoire' => { 448 => [\'CircularGradientBasedCorrections','CircularGradientBasedCorrectionsLocalMoire'] }, + 'circgradbasedcorrsaturation' => { 448 => [\'CircularGradientBasedCorrections','CircularGradientBasedCorrectionsLocalSaturation','CircularGradientBasedCorrectionsLocalToningSaturation'] }, + 'circgradbasedcorrshadows2012' => { 448 => [\'CircularGradientBasedCorrections','CircularGradientBasedCorrectionsLocalShadows2012'] }, + 'circgradbasedcorrsharpness' => { 448 => [\'CircularGradientBasedCorrections','CircularGradientBasedCorrectionsLocalSharpness'] }, + 'circgradbasedcorrtemperature' => { 448 => [\'CircularGradientBasedCorrections','CircularGradientBasedCorrectionsLocalTemperature'] }, + 'circgradbasedcorrtint' => { 448 => [\'CircularGradientBasedCorrections','CircularGradientBasedCorrectionsLocalTint'] }, + 'circgradbasedcorrwhat' => { 448 => [\'CircularGradientBasedCorrections','CircularGradientBasedCorrectionsWhat'] }, + 'circulargradientbasedcorrections' => { 448 => 'CircularGradientBasedCorrections' }, + 'city' => { 125 => 0x5a, 152 => 'City', 301 => 0x6d, 460 => 'City' }, + 'city2' => { 301 => 0x80 }, + 'clarity' => { 217 => 0x35, 218 => 0x3d, 448 => 'Clarity' }, + 'clarity2012' => { 448 => 'Clarity2012' }, + 'claritycontrol' => { 336 => 0x96 }, + 'classifystate' => { 125 => 0xe1 }, + 'clearretouch' => { 301 => 0x7c }, + 'clearretouchvalue' => { 301 => 0xa3 }, + 'client' => { 472 => 'client' }, + 'clientname' => { 454 => 'ClientName' }, + 'clmodeshootingspeed' => { 261 => '10.2', 262 => '11.3', 264 => '11.2', 265 => '11.2', 270 => '11.2', 271 => '10.2', 274 => '11.2', 275 => '11.2', 276 => '11.1' }, + 'cmcontrast' => { 286 => 0x2022 }, + 'cmexposurecompensation' => { 286 => 0x2000 }, + 'cmhue' => { 286 => 0x2021 }, + 'cmsaturation' => { 286 => 0x2020 }, + 'cmsharpness' => { 286 => 0x2023 }, + 'cmwhitebalance' => { 286 => 0x2001 }, + 'cmwhitebalancecomp' => { 286 => 0x2002 }, + 'cmwhitebalancegraypoint' => { 286 => 0x2010 }, + 'codec' => { 160 => 'Codec' }, + 'codedcharacterset' => { 126 => 0x5a }, + 'collection' => { 291 => 'Collection' }, + 'collectionname' => { 161 => [\'Collections','CollectionsCollectionName'] }, + 'collections' => { 161 => 'Collections', 442 => 'collections' }, + 'collectionuri' => { 161 => [\'Collections','CollectionsCollectionURI'] }, + 'color' => { 461 => 'color' }, + 'coloraberrationcontrol' => { 254 => 0xc89224b }, + 'coloradjustment' => { 373 => 0x14 }, + 'coloradjustmentmode' => { 372 => 0x210 }, + 'coloranta' => { 477 => [\'Colorants','ColorantsA'] }, + 'colorantb' => { 477 => [\'Colorants','ColorantsB'] }, + 'colorantblack' => { 477 => [\'Colorants','ColorantsBlack'] }, + 'colorantblue' => { 477 => [\'Colorants','ColorantsBlue'] }, + 'colorantcyan' => { 477 => [\'Colorants','ColorantsCyan'] }, + 'colorantgray' => { 477 => [\'Colorants','ColorantsGray'] }, + 'colorantgreen' => { 477 => [\'Colorants','ColorantsGreen'] }, + 'colorantl' => { 477 => [\'Colorants','ColorantsL'] }, + 'colorantmagenta' => { 477 => [\'Colorants','ColorantsMagenta'] }, + 'colorantmode' => { 477 => [\'Colorants','ColorantsMode'] }, + 'colorantred' => { 477 => [\'Colorants','ColorantsRed'] }, + 'colorants' => { 477 => 'Colorants' }, + 'colorantswatchname' => { 477 => [\'Colorants','ColorantsSwatchName'] }, + 'coloranttint' => { 477 => [\'Colorants','ColorantsTint'] }, + 'coloranttype' => { 477 => [\'Colorants','ColorantsType'] }, + 'colorantyellow' => { 477 => [\'Colorants','ColorantsYellow'] }, + 'colorbalance' => { 147 => 'ColorBalance' }, + 'colorbalanceadj' => { 254 => 0x76a43202 }, + 'colorbalanceblue' => { 171 => 0x1e }, + 'colorbalancegreen' => { 171 => 0x1d }, + 'colorbalancered' => { 171 => 0x1c }, + 'colorbalanceversion' => { 192 => 0x4, 193 => 0x4, 194 => 0x0 }, + 'colorblur' => { 103 => 0x65 }, + 'colorbluron' => { 97 => 0x20704 }, + 'colorbooster' => { 254 => 0x5f0e7d23 }, + 'colorboostlevel' => { 248 => 0x1 }, + 'colorboosttype' => { 248 => 0x0 }, + 'colorchromeeffect' => { 121 => 0x1048 }, + 'colorclass' => { 347 => 0xde, 348 => 'ColorClass' }, + 'colorcompensationfilter' => { 174 => [0x3a,0x5f], 176 => 0x111, 394 => 0xb022 }, + 'colorcompensationfiltercustom' => { 381 => 0xd, 382 => 0xc }, + 'colorcompensationfilterset' => { 381 => 0x8, 382 => 0x7, 383 => 0x18, 399 => 0xf }, + 'colorcontrol' => { 283 => 0x102b }, + 'colorcorrection' => { 427 => 0x8015 }, + 'colorcreatoreffect' => { 278 => 0x532 }, + 'colordataversion' => { 41 => 0x0, 42 => 0x0, 43 => 0x0, 44 => 0x0, 45 => 0x0, 46 => 0x0, 47 => 0x0 }, + 'coloreffect' => { 301 => 0x28 }, + 'colorfilter' => { 106 => 0x17, 107 => 0x3017, 171 => 0x29, 179 => [0x38,0x4d,0x4f], 343 => 0x17 }, + 'colorgain' => { 222 => 0x51 }, + 'colorhue' => { 97 => 0x20900, 214 => 0x8d }, + 'colorimetricreference' => { 113 => 0xc6bf }, + 'colorlabel' => { 451 => 'ColorLabel' }, + 'colormatrix' => { 282 => 0x200, 283 => 0x1011, 370 => 0xa030 }, + 'colormatrix1' => { 113 => 0xc621, 345 => 0x106 }, + 'colormatrix2' => { 113 => 0xc622, 286 => 0x200, 345 => 0x226 }, + 'colormatrixa' => { 336 => 0x203 }, + 'colormatrixadobergb' => { 370 => 0xa032 }, + 'colormatrixb' => { 336 => 0x204 }, + 'colormatrixnumber' => { 283 => 0x1019 }, + 'colormatrixsrgb' => { 370 => 0xa031 }, + 'colormode' => { 107 => 0x3015, 121 => 0x1210, 133 => 0x66, 171 => 0x28, 174 => 0x16, 176 => 0x101, 177 => 0x36, 179 => 0x7, 214 => 0x3, 244 => 0x4, 301 => 0x32, 373 => 0x2c, 394 => 0xb029, 460 => 'ColorMode' }, + 'colormoirereduction' => { 97 => 0x20670, 255 => 0x15 }, + 'colormoirereductionmode' => { 255 => 0x5 }, + 'colormoirereductionon' => { 97 => '0x20670.0' }, + 'colornoisereduction' => { 427 => 0x8029, 448 => 'ColorNoiseReduction' }, + 'colornoisereductiondetail' => { 448 => 'ColorNoiseReductionDetail' }, + 'colornoisereductionintensity' => { 255 => 0x18 }, + 'colornoisereductionsharpness' => { 255 => 0x1c }, + 'colornoisereductionsmoothness' => { 448 => 'ColorNoiseReductionSmoothness' }, + 'colorplanes' => { 117 => 0x2 }, + 'colorprofile' => { 171 => 0x33 }, + 'colorprofilesettings' => { 278 => 0x539 }, + 'colorrepresentation' => { 127 => 0x3c }, + 'colorsaturationadj' => { 97 => 0x20305 }, + 'colorsequence' => { 127 => 0x41 }, + 'colorspace' => { 48 => 0x3, 60 => 0xb4, 91 => 0x10b4, 113 => 0xa001, 153 => 'ColorSpace', 172 => 0x2f, 173 => 0x25, 174 => 0x17, 214 => 0x1e, 278 => 0x507, 336 => 0x37, 370 => 0xa011, 373 => 0xb, 381 => 0x1b, 382 => 0x83, 383 => 0xe, 399 => 0x6, 452 => 'ColorSpace' }, + 'colortempasshot' => { 37 => 0x4, 38 => 0x7, 39 => 0x1d, 40 => 0x26, 41 => 0x43, 44 => 0x43, 45 => 0x43, 46 => 0x43, 47 => 0x4b }, + 'colortempauto' => { 37 => 0x9, 38 => 0xf, 39 => 0x22, 40 => 0x1c, 41 => 0x48, 44 => 0x48, 45 => 0x48, 46 => 0x48, 47 => 0x50 }, + 'colortempcloudy' => { 37 => 0x22, 38 => 0x37, 39 => 0x31, 40 => 0x35, 41 => 0x5c, 44 => 0x75, 45 => 0x8e, 46 => 0x93, 47 => 0x96, 336 => 0x55 }, + 'colortempcustom' => { 41 => 0x84 }, + 'colortempcustom1' => { 39 => 0x45 }, + 'colortempcustom2' => { 39 => 0x4a }, + 'colortempdaylight' => { 37 => 0x18, 38 => 0x27, 39 => 0x27, 40 => 0x2b, 41 => 0x52, 44 => 0x6b, 45 => 0x84, 46 => 0x89, 47 => 0x8c, 336 => 0x53 }, + 'colortemperature' => { 6 => 0x73, 7 => [0x48,0x4e], 8 => 0xc0, 9 => 0x37, 10 => 0x62, 11 => 0x37, 12 => 0x7c, 13 => 0x73, 14 => 0x73, 15 => 0x77, 16 => 0x73, 17 => 0x7c, 18 => 0x58, 19 => 0x73, 20 => 0xc0, 21 => 0x7f, 22 => 0x7d, 23 => 0xc0, 24 => 0xc6, 25 => 0xc7, 26 => 0x135, 27 => 0x7b, 28 => 0x13a, 60 => 0xae, 70 => 0x9, 91 => 0x10ae, 121 => 0x1005, 131 => 0x846, 147 => 'ColorTemperature', 172 => [0x6e,0x49], 173 => 0x3f, 174 => [0x39,0x5e], 176 => 0x10b, 179 => [0x3c,0x4c,0x4e], 296 => 0x321, 336 => 0x50, 363 => 0x1308, 394 => 0xb021, 448 => 'Temperature' }, + 'colortemperatureadj' => { 427 => 0x8013 }, + 'colortemperatureauto' => { 214 => 0x4f }, + 'colortemperaturebg' => { 283 => 0x1013 }, + 'colortemperaturecustom' => { 381 => 0xc, 382 => 0xb }, + 'colortemperaturerg' => { 283 => 0x1014 }, + 'colortemperatureset' => { 381 => 0x7, 382 => 0x6 }, + 'colortemperaturesetting' => { 174 => 0x25, 383 => 0x17, 399 => 0xe }, + 'colortempflash' => { 37 => 0x36, 38 => 0x57, 39 => 0x40, 40 => 0x49, 41 => 0x70, 44 => 0x89, 45 => 0xa2, 46 => 0xa7, 47 => 0xaa, 336 => 0x5a }, + 'colortempflashdata' => { 41 => 0x24a }, + 'colortempfluorescent' => { 37 => 0x2c, 38 => 0x47, 39 => 0x3b, 40 => 0x3f, 41 => 0x66, 44 => 0x7f, 45 => 0x98, 46 => 0x9d, 47 => 0xa0 }, + 'colortempfluorescentd' => { 336 => 0x57 }, + 'colortempfluorescentn' => { 336 => 0x58 }, + 'colortempfluorescentw' => { 336 => 0x59 }, + 'colortempkelvin' => { 37 => 0x31, 38 => 0x4f, 40 => 0x44, 41 => 0x6b, 44 => 0x84, 45 => 0x9d, 46 => 0xa2, 47 => 0xa5, 301 => 0x44, 363 => 0x1307 }, + 'colortempmeasured' => { 37 => 0xe, 38 => 0x17, 41 => 0x4d, 44 => 0x4d, 45 => 0x4d, 46 => 0x4d, 47 => 0x55 }, + 'colortemppc1' => { 40 => 0x94, 41 => 0x75 }, + 'colortemppc2' => { 40 => 0x99, 41 => 0x7a }, + 'colortemppc3' => { 40 => 0x9e, 41 => 0x7f }, + 'colortempshade' => { 37 => 0x1d, 38 => 0x2f, 39 => 0x2c, 40 => 0x30, 41 => 0x57, 44 => 0x70, 45 => 0x89, 46 => 0x8e, 47 => 0x91, 336 => 0x54 }, + 'colortemptungsten' => { 37 => 0x27, 38 => 0x3f, 39 => 0x36, 40 => 0x3a, 41 => 0x61, 44 => 0x7a, 45 => 0x93, 46 => 0x98, 47 => 0x9b, 336 => 0x56 }, + 'colortempunknown' => { 37 => 0x13, 38 => 0x1f, 40 => 0x21, 44 => 0x52, 45 => 0x52, 46 => 0x52, 47 => 0x5a }, + 'colortempunknown10' => { 37 => 0x63, 38 => 0x9f, 40 => 0x76, 44 => 0xa2, 45 => 0x7f, 46 => 0x7f, 47 => 0x87 }, + 'colortempunknown11' => { 37 => 0x68, 38 => 0xa7, 40 => 0x7b, 44 => 0xa7, 45 => 0xa7, 46 => 0x84, 47 => 0xaf }, + 'colortempunknown12' => { 37 => 0x6d, 38 => 0xaf, 40 => 0x80, 44 => 0xac, 45 => 0xac, 46 => 0xac, 47 => 0xb4 }, + 'colortempunknown13' => { 37 => 0x72, 38 => 0xb7, 40 => 0x85, 44 => 0xb1, 45 => 0xb1, 46 => 0xb1, 47 => 0xb9 }, + 'colortempunknown14' => { 40 => 0x8a, 44 => 0xb6, 45 => 0xb6, 46 => 0xb6, 47 => 0xbe }, + 'colortempunknown15' => { 40 => 0x8f, 44 => 0xbb, 45 => 0xbb, 46 => 0xbb, 47 => 0xc3 }, + 'colortempunknown16' => { 40 => 0xa3, 45 => 0xc0, 46 => 0xc0, 47 => 0xc8 }, + 'colortempunknown17' => { 45 => 0xc5, 46 => 0xc5, 47 => 0xcd }, + 'colortempunknown18' => { 45 => 0xca, 46 => 0xca, 47 => 0xd2 }, + 'colortempunknown19' => { 45 => 0xcf, 46 => 0xcf, 47 => 0xd7 }, + 'colortempunknown2' => { 37 => 0x3b, 38 => 0x5f, 40 => 0x4e, 44 => 0x57, 45 => 0x57, 46 => 0x57, 47 => 0x5f }, + 'colortempunknown20' => { 45 => 0xd4, 46 => 0xd4, 47 => 0xdc }, + 'colortempunknown21' => { 46 => 0xd9, 47 => 0xe1 }, + 'colortempunknown22' => { 46 => 0xde, 47 => 0xe6 }, + 'colortempunknown23' => { 46 => 0xe3, 47 => 0xeb }, + 'colortempunknown24' => { 46 => 0xe8, 47 => 0xf0 }, + 'colortempunknown25' => { 46 => 0xed, 47 => 0xf5 }, + 'colortempunknown26' => { 46 => 0xf2, 47 => 0xfa }, + 'colortempunknown27' => { 46 => 0xf7, 47 => 0xff }, + 'colortempunknown28' => { 46 => 0xfc, 47 => 0x104 }, + 'colortempunknown29' => { 46 => 0x101, 47 => 0x109 }, + 'colortempunknown3' => { 37 => 0x40, 38 => 0x67, 40 => 0x53, 44 => 0x5c, 45 => 0x5c, 46 => 0x5c, 47 => 0x64 }, + 'colortempunknown30' => { 46 => 0x106 }, + 'colortempunknown4' => { 37 => 0x45, 38 => 0x6f, 40 => 0x58, 44 => 0x61, 45 => 0x61, 46 => 0x61, 47 => 0x69 }, + 'colortempunknown5' => { 37 => 0x4a, 38 => 0x77, 40 => 0x5d, 44 => 0x66, 45 => 0x66, 46 => 0x66, 47 => 0x6e }, + 'colortempunknown6' => { 37 => 0x4f, 38 => 0x7f, 40 => 0x62, 44 => 0x8e, 45 => 0x6b, 46 => 0x6b, 47 => 0x73 }, + 'colortempunknown7' => { 37 => 0x54, 38 => 0x87, 40 => 0x67, 44 => 0x93, 45 => 0x70, 46 => 0x70, 47 => 0x78 }, + 'colortempunknown8' => { 37 => 0x59, 38 => 0x8f, 40 => 0x6c, 44 => 0x98, 45 => 0x75, 46 => 0x75, 47 => 0x7d }, + 'colortempunknown9' => { 37 => 0x5e, 38 => 0x97, 40 => 0x71, 44 => 0x9d, 45 => 0x7a, 46 => 0x7a, 47 => 0x82 }, + 'colortone' => { 9 => 0x6f, 11 => 0x77, 33 => 0x2a, 48 => 0x2 }, + 'colortoneadj' => { 97 => 0x20304, 102 => 0x11e }, + 'colortoneauto' => { 67 => 0x9c }, + 'colortonefaithful' => { 18 => 0x107, 66 => 0x6c, 67 => 0x6c }, + 'colortonelandscape' => { 18 => 0x105, 66 => 0x3c, 67 => 0x3c }, + 'colortonemonochrome' => { 66 => 0x84, 67 => 0x84 }, + 'colortoneneutral' => { 18 => 0x106, 66 => 0x54, 67 => 0x54 }, + 'colortoneportrait' => { 18 => 0x104, 66 => 0x24, 67 => 0x24 }, + 'colortonestandard' => { 18 => 0x103, 66 => 0xc, 67 => 0xc }, + 'colortoneuserdef1' => { 18 => 0x109, 66 => 0x9c, 67 => 0xb4 }, + 'colortoneuserdef2' => { 18 => 0x10a, 66 => 0xb4, 67 => 0xcc }, + 'colortoneuserdef3' => { 18 => 0x10b, 66 => 0xcc, 67 => 0xe4 }, + 'comlenblksize' => { 131 => 0xfde8 }, + 'commanddials' => { 272 => '5.1' }, + 'commanddialsaperturesetting' => { 261 => '17.3', 262 => '18.3', 264 => '18.3', 265 => '18.3', 270 => '33.3', 271 => '17.3', 274 => '18.3', 275 => '18.3' }, + 'commanddialschangemainsub' => { 261 => '17.2', 262 => '18.1', 264 => '18.1', 265 => '18.1', 270 => '33.2', 271 => '17.2', 274 => '18.1', 275 => '18.1' }, + 'commanddialsmenuandplayback' => { 261 => '17.4', 262 => '18.2', 264 => '18.2', 265 => '18.2', 270 => '33.4', 271 => '17.4', 274 => '18.2', 275 => '18.2' }, + 'commanddialsreverserotation' => { 261 => '17.1', 262 => '6.4', 264 => '6.2', 265 => '6.2', 266 => '16.2', 267 => '17.2', 270 => '33.1', 271 => '17.1', 274 => '6.2', 275 => '6.2', 276 => '18.1' }, + 'commanderchannel' => { 272 => '10.2', 273 => '25.2' }, + 'commandergroupa_ttl-aacomp' => { 272 => '13.1', 273 => '31.1' }, + 'commandergroupa_ttlcomp' => { 276 => '32.1' }, + 'commandergroupamanualoutput' => { 272 => '13.2', 273 => '28.2' }, + 'commandergroupamode' => { 272 => '11.2', 273 => '28.1' }, + 'commandergroupb_ttl-aacomp' => { 272 => '14.1', 273 => '32.1' }, + 'commandergroupb_ttlcomp' => { 276 => '33.1' }, + 'commandergroupbmanualoutput' => { 272 => '14.2', 273 => '29.2' }, + 'commandergroupbmode' => { 272 => '11.3', 273 => '29.1' }, + 'commanderinternalflash' => { 272 => '11.1', 273 => '27.1' }, + 'commanderinternalmanualoutput' => { 272 => '12.2', 273 => '27.2' }, + 'commanderinternalttlchannel' => { 270 => '18.2' }, + 'commanderinternalttlcomp' => { 272 => '12.1', 273 => '30.2', 276 => '31.2' }, + 'commanderinternalttlcompbuiltin' => { 270 => '20.1', 271 => '26.1' }, + 'commanderinternalttlcompgroupa' => { 270 => '21.1', 271 => '27.1' }, + 'commanderinternalttlcompgroupb' => { 270 => '22.1', 271 => '28.1' }, + 'comment' => { 0 => 0x2, 114 => 'Comment', 148 => 'Comment', 291 => 'Comment' }, + 'compass' => { 366 => 0x4 }, + 'complianceprofile' => { 462 => 'complianceProfile' }, + 'componentsconfiguration' => { 113 => 0x9101, 153 => 'Components', 452 => 'ComponentsConfiguration' }, + 'componentversion' => { 91 => 0x80c }, + 'composer' => { 472 => 'composer' }, + 'composition' => { 437 => 'Composition' }, + 'compositionadjust' => { 335 => '0.1' }, + 'compositionadjustrotation' => { 335 => 0x7 }, + 'compositionadjustx' => { 335 => 0x5 }, + 'compositionadjusty' => { 335 => 0x6 }, + 'compressedbitsperpixel' => { 113 => 0x9102, 452 => 'CompressedBitsPerPixel' }, + 'compressedimagesize' => { 176 => 0x40, 283 => 0x40 }, + 'compression' => { 113 => 0x103, 306 => 0xb, 468 => 'Compression' }, + 'compressionfactor' => { 278 => 0x50d }, + 'compressionratio' => { 153 => 'Compression', 283 => 0x1034 }, + 'condadobvfactor' => { 131 => 0xf3e }, + 'condadodaybvthresh' => { 131 => 0xf3c }, + 'condadodayoffsets' => { 131 => 0xf42 }, + 'condadofluoffsets' => { 131 => 0xf44 }, + 'condadofluthresh' => { 131 => 0xf41 }, + 'condadoillfactor' => { 131 => 0xf3f }, + 'condadoneurange' => { 131 => 0xf3d }, + 'condadotunoffsets' => { 131 => 0xf43 }, + 'condadotunthresh' => { 131 => 0xf40 }, + 'confidence' => { 432 => 'Confidence' }, + 'confidencelevel' => { 443 => 'ConfidenceLevel' }, + 'confidencemime' => { 432 => 'ConfidenceMime' }, + 'constrainedcropheight' => { 102 => 0x266, 347 => 0xd6 }, + 'constrainedcropwidth' => { 102 => 0x262, 347 => 0xd5 }, + 'contact' => { 125 => 0x76 }, + 'contactinfo' => { 461 => 'contactInfo' }, + 'containerformat' => { 458 => 'ContainerFormat' }, + 'containerformatidentifier' => { 458 => [\'ContainerFormat','ContainerFormatIdentifier'] }, + 'containerformatname' => { 458 => [\'ContainerFormat','ContainerFormatName'] }, + 'contentidentifier' => { 1 => 0x11 }, + 'contentlocationcode' => { 125 => 0x1a }, + 'contentlocationname' => { 125 => 0x1b }, + 'contenttype' => { 462 => 'contentType' }, + 'continuousbracketing' => { 174 => 0x20 }, + 'continuousdrive' => { 33 => 0x5 }, + 'continuousmodeliveview' => { 275 => '77.2' }, + 'continuousshootingspeed' => { 78 => 0x610 }, + 'continuousshotlimit' => { 78 => 0x611 }, + 'contrast' => { 9 => 0x73, 11 => 0x75, 33 => 0xd, 106 => 0xc, 107 => [0x3012,0x20], 113 => [0xa408,0xfe54], 121 => [0x1004,0x1006], 147 => 'Contrast', 167 => 'Contrast', 171 => 0x20, 172 => 0x31, 173 => 0x27, 174 => 0x19, 179 => 0x2, 216 => 0x33, 217 => 0x37, 218 => 0x3f, 283 => 0x1029, 301 => 0x39, 303 => 0x300a, 336 => 0x20, 343 => 0xc, 357 => 0x24, 359 => 0x52, 363 => 0x1012, 373 => 0xd, 381 => 0x1d, 382 => 0x1a, 394 => 0x2004, 448 => 'Contrast', 452 => 'Contrast' }, + 'contrast2012' => { 448 => 'Contrast2012' }, + 'contrastadj' => { 97 => 0x20303, 102 => 0x115, 257 => 0x2c, 427 => 0x8017 }, + 'contrastauto' => { 67 => 0x90 }, + 'contrastcurve' => { 214 => 0x8c }, + 'contrastdetectaf' => { 183 => 0x4 }, + 'contrastdetectafarea' => { 336 => 0x231 }, + 'contrastdetectafinfocus' => { 183 => [0x1c,0x52] }, + 'contrastfaithful' => { 18 => 0xec, 66 => 0x60, 67 => 0x60 }, + 'contrasthighlight' => { 336 => 0x6d }, + 'contrasthighlightshadowadj' => { 336 => 0x6f }, + 'contrastlandscape' => { 18 => 0xea, 66 => 0x30, 67 => 0x30 }, + 'contrastmode' => { 301 => 0x2c }, + 'contrastmonochrome' => { 18 => 0xed, 66 => 0x78, 67 => 0x78 }, + 'contrastneutral' => { 18 => 0xeb, 66 => 0x48, 67 => 0x48 }, + 'contrastportrait' => { 18 => 0xe9, 66 => 0x18, 67 => 0x18 }, + 'contrastsetting' => { 278 => 0x505, 286 => 0x1012, 383 => 0x10, 399 => 0x8 }, + 'contrastshadow' => { 336 => 0x6e }, + 'contraststandard' => { 18 => 0xe8, 66 => 0x0, 67 => 0x0 }, + 'contrastuserdef1' => { 18 => 0xee, 66 => 0x90, 67 => 0xa8 }, + 'contrastuserdef2' => { 18 => 0xef, 66 => 0xa8, 67 => 0xc0 }, + 'contrastuserdef3' => { 18 => 0xf0, 66 => 0xc0, 67 => 0xd8 }, + 'contributedmedia' => { 472 => 'contributedMedia' }, + 'contributedmediaduration' => { 472 => [\'contributedMedia','contributedMediaDuration'] }, + 'contributedmediadurationscale' => { 472 => [\'contributedMedia','contributedMediaDurationScale'] }, + 'contributedmediadurationvalue' => { 472 => [\'contributedMedia','contributedMediaDurationValue'] }, + 'contributedmediamanaged' => { 472 => [\'contributedMedia','contributedMediaManaged'] }, + 'contributedmediapath' => { 472 => [\'contributedMedia','contributedMediaPath'] }, + 'contributedmediastarttime' => { 472 => [\'contributedMedia','contributedMediaStartTime'] }, + 'contributedmediastarttimescale' => { 472 => [\'contributedMedia','contributedMediaStartTimeScale'] }, + 'contributedmediastarttimevalue' => { 472 => [\'contributedMedia','contributedMediaStartTimeValue'] }, + 'contributedmediatrack' => { 472 => [\'contributedMedia','contributedMediaTrack'] }, + 'contributedmediawebstatement' => { 472 => [\'contributedMedia','contributedMediaWebStatement'] }, + 'contributor' => { 449 => 'contributor', 458 => 'Contributor' }, + 'contributoridentifier' => { 458 => [\'Contributor','ContributorIdentifier'] }, + 'contributorname' => { 458 => [\'Contributor','ContributorName'] }, + 'contributorrole' => { 458 => [\'Contributor','ContributorRole'] }, + 'contributors' => { 148 => 'Contributors' }, + 'controldialset' => { 174 => 0x46 }, + 'controlledvocabularyterm' => { 458 => 'CVterm' }, + 'controllerboardversion' => { 296 => 0x332 }, + 'controlmode' => { 72 => 0x12 }, + 'controlringrotation' => { 78 => 0x712 }, + 'conversionlens' => { 279 => 0x403, 301 => 0x35 }, + 'converter' => { 113 => 0xfe4d, 244 => 0xb, 448 => 'Converter' }, + 'converttograyscale' => { 448 => 'ConvertToGrayscale' }, + 'cookingequipment' => { 464 => 'cookingEquipment' }, + 'cookingmethod' => { 464 => 'cookingMethod' }, + 'copyright' => { 0 => 0x3, 113 => 0x8298, 148 => 'Copyright', 291 => 'Copyright', 336 => 0x22f, 352 => 'Copyright', 459 => 'Copyright', 465 => 'copyright', 468 => 'Copyright', 472 => 'copyright' }, + 'copyrightflag' => { 350 => 0x40a }, + 'copyrightnotice' => { 125 => 0x74 }, + 'copyrightowner' => { 288 => 'CopyrightOwner' }, + 'copyrightownerid' => { 288 => [\'CopyrightOwner','CopyrightOwnerCopyrightOwnerID'] }, + 'copyrightownerimageid' => { 288 => 'CopyrightOwnerImageID' }, + 'copyrightownername' => { 288 => [\'CopyrightOwner','CopyrightOwnerCopyrightOwnerName'] }, + 'copyrightregistrationnumber' => { 288 => 'CopyrightRegistrationNumber' }, + 'copyrightstatus' => { 288 => 'CopyrightStatus' }, + 'copyrightyear' => { 458 => 'CopyrightYear', 462 => 'copyrightYear' }, + 'coringfilter' => { 282 => 0x310, 283 => 0x102d, 286 => 0x310 }, + 'coringvalues' => { 282 => 0x311, 286 => 0x311 }, + 'corporateentity' => { 462 => 'corporateEntity' }, + 'country' => { 152 => 'Country', 301 => 0x69, 460 => 'Country' }, + 'country-primarylocationcode' => { 125 => 0x64 }, + 'country-primarylocationname' => { 125 => 0x65 }, + 'countrycode' => { 213 => 0x5, 348 => 'CountryCode', 457 => 'CountryCode' }, + 'course' => { 464 => 'course' }, + 'coverage' => { 449 => 'coverage' }, + 'coverdate' => { 462 => 'coverDate' }, + 'coverdisplaydate' => { 462 => 'coverDisplayDate' }, + 'cpufirmwareversion' => { 336 => 0x28 }, + 'crc32' => { 450 => 'crc32' }, + 'createdate' => { 113 => 0x9004, 148 => 'CreateDate', 287 => 'CreationDate', 291 => 'create-date', 352 => 'CreationDate', 354 => 0x1, 470 => 'CreateDate' }, + 'creationdate' => { 459 => 'CreationDate', 462 => 'creationDate' }, + 'creationtime' => { 291 => 'Creation Time' }, + 'creativestyle' => { 381 => 0x1a, 382 => 0x18, 392 => 0x41, 394 => 0xb020, 423 => 0x4a }, + 'creativestylesetting' => { 383 => 0xf, 399 => 0x7 }, + 'creativestylewaschanged' => { 427 => 0x8001 }, + 'creator' => { 287 => 'Creator', 352 => 'Creator', 449 => 'creator', 458 => 'Creator', 459 => 'Creator' }, + 'creatoraddress' => { 457 => [\'CreatorContactInfo','CreatorContactInfoCiAdrExtadr'] }, + 'creatorappid' => { 169 => 'CreatorAppId' }, + 'creatorcity' => { 457 => [\'CreatorContactInfo','CreatorContactInfoCiAdrCity'] }, + 'creatorcontactinfo' => { 457 => 'CreatorContactInfo' }, + 'creatorcountry' => { 457 => [\'CreatorContactInfo','CreatorContactInfoCiAdrCtry'] }, + 'creatoridentifier' => { 458 => [\'Creator','CreatorIdentifier'] }, + 'creatorname' => { 458 => [\'Creator','CreatorName'] }, + 'creatoropenwithuioptions' => { 169 => 'CreatorOpenWithUIOptions' }, + 'creatorpostalcode' => { 457 => [\'CreatorContactInfo','CreatorContactInfoCiAdrPcode'] }, + 'creatorregion' => { 457 => [\'CreatorContactInfo','CreatorContactInfoCiAdrRegion'] }, + 'creatorrole' => { 458 => [\'Creator','CreatorRole'] }, + 'creatortool' => { 470 => 'CreatorTool' }, + 'creatorworkemail' => { 457 => [\'CreatorContactInfo','CreatorContactInfoCiEmailWork'] }, + 'creatorworktelephone' => { 457 => [\'CreatorContactInfo','CreatorContactInfoCiTelWork'] }, + 'creatorworkurl' => { 457 => [\'CreatorContactInfo','CreatorContactInfoCiUrlWork'] }, + 'credit' => { 125 => 0x6e, 460 => 'Credit' }, + 'creditline' => { 465 => 'creditLine' }, + 'creditlinereq' => { 475 => 'CreditLineReq' }, + 'creditlinerequired' => { 288 => 'CreditLineRequired' }, + 'cropactive' => { 95 => 0x0, 102 => 0x244 }, + 'cropangle' => { 448 => 'CropAngle' }, + 'croparea' => { 427 => 0x9011 }, + 'cropaspectratio' => { 97 => 0x30101, 102 => 0x260 }, + 'cropaspectratiocustom' => { 97 => 0x30102 }, + 'cropbottom' => { 117 => 0x9, 249 => 0x36, 306 => 0x31, 347 => 0xdc, 448 => 'CropBottom' }, + 'cropbottommargin' => { 50 => 0x3 }, + 'cropcircleactive' => { 103 => 0xd6 }, + 'cropcircleradius' => { 103 => 0xd9 }, + 'cropcirclex' => { 103 => 0xd7 }, + 'cropcircley' => { 103 => 0xd8 }, + 'cropconstraintowarp' => { 448 => 'CropConstrainToWarp' }, + 'croph' => { 441 => 'CropH' }, + 'cropheight' => { 95 => 0x6, 102 => 0x24c, 282 => 0x615, 286 => 0x615, 448 => 'CropHeight' }, + 'crophispeed' => { 214 => 0x1b }, + 'cropleft' => { 102 => 0x246, 117 => 0x6, 249 => 0x1e, 282 => 0x612, 286 => 0x612, 306 => 0x30, 347 => 0xd9, 448 => 'CropLeft' }, + 'cropleftmargin' => { 50 => 0x0 }, + 'cropmode' => { 121 => 0x104d }, + 'cropmode35mm' => { 363 => 0x1018 }, + 'croporiginalheight' => { 95 => 0xb }, + 'croporiginalwidth' => { 95 => 0xa }, + 'cropoutputheight' => { 249 => 0xce }, + 'cropoutputheightinches' => { 249 => 0x96 }, + 'cropoutputpixels' => { 249 => 0xd6 }, + 'cropoutputresolution' => { 249 => 0xb6 }, + 'cropoutputscale' => { 249 => 0xbe }, + 'cropoutputwidth' => { 249 => 0xc6 }, + 'cropoutputwidthinches' => { 249 => 0x8e }, + 'croppedareaimageheightpixels' => { 435 => 'CroppedAreaImageHeightPixels', 436 => 'CroppedAreaImageHeightPixels' }, + 'croppedareaimagewidthpixels' => { 435 => 'CroppedAreaImageWidthPixels', 436 => 'CroppedAreaImageWidthPixels' }, + 'croppedarealeftpixels' => { 435 => 'CroppedAreaLeftPixels', 436 => 'CroppedAreaLeftPixels' }, + 'croppedareatoppixels' => { 435 => 'CroppedAreaTopPixels', 436 => 'CroppedAreaTopPixels' }, + 'croppedimageheight' => { 5 => 0x2, 363 => 0x1604 }, + 'croppedimageleft' => { 5 => 0x3 }, + 'croppedimagetop' => { 5 => 0x4 }, + 'croppedimagewidth' => { 5 => 0x1, 363 => 0x1603 }, + 'cropping' => { 427 => 0x9010 }, + 'cropright' => { 117 => 0x8, 249 => 0x2e, 306 => 0x32, 347 => 0xdb, 448 => 'CropRight' }, + 'croprightmargin' => { 50 => 0x1 }, + 'croprotatedoriginalheight' => { 95 => 0x2 }, + 'croprotatedoriginalwidth' => { 95 => 0x1 }, + 'croprotation' => { 95 => 0x8, 117 => 0xb }, + 'cropscaledresolution' => { 249 => 0x9e }, + 'cropsourceresolution' => { 249 => 0xae }, + 'croptop' => { 102 => 0x248, 117 => 0x7, 249 => 0x26, 282 => 0x613, 286 => 0x613, 306 => 0x2f, 347 => 0xda, 448 => 'CropTop' }, + 'croptopmargin' => { 50 => 0x2 }, + 'cropunit' => { 448 => 'CropUnit' }, + 'cropunits' => { 448 => 'CropUnits' }, + 'cropw' => { 441 => 'CropW' }, + 'cropwidth' => { 95 => 0x5, 102 => 0x24a, 282 => 0x614, 286 => 0x614, 448 => 'CropWidth' }, + 'cropx' => { 95 => 0x3, 441 => 'CropX' }, + 'cropy' => { 95 => 0x4, 441 => 'CropY' }, + 'crossprocess' => { 336 => 0x7b }, + 'crossprocessparams' => { 336 => 0x235 }, + 'cuisine' => { 464 => 'cuisine' }, + 'currenticcprofile' => { 113 => 0xc691 }, + 'currentpreprofilematrix' => { 113 => 0xc692 }, + 'currentversion' => { 427 => 0xd000 }, + 'curve0x' => { 441 => 'Curve0x' }, + 'curve0y' => { 441 => 'Curve0y' }, + 'curve1x' => { 441 => 'Curve1x' }, + 'curve1y' => { 441 => 'Curve1y' }, + 'curve2x' => { 441 => 'Curve2x' }, + 'curve2y' => { 441 => 'Curve2y' }, + 'curve3x' => { 441 => 'Curve3x' }, + 'curve3y' => { 441 => 'Curve3y' }, + 'curve4x' => { 441 => 'Curve4x' }, + 'curve4y' => { 441 => 'Curve4y' }, + 'curves' => { 254 => 0x76a43201 }, + 'custom1' => { 288 => 'Custom1' }, + 'custom10' => { 288 => 'Custom10' }, + 'custom2' => { 288 => 'Custom2' }, + 'custom3' => { 288 => 'Custom3' }, + 'custom4' => { 288 => 'Custom4' }, + 'custom5' => { 288 => 'Custom5' }, + 'custom6' => { 288 => 'Custom6' }, + 'custom7' => { 288 => 'Custom7' }, + 'custom8' => { 288 => 'Custom8' }, + 'custom9' => { 288 => 'Custom9' }, + 'customcolortone' => { 103 => 0x4c }, + 'customcontrast' => { 103 => 0x4e }, + 'customcontrols' => { 78 => 0x70c }, + 'customdefaultunsharpfineness' => { 103 => 0xbe }, + 'customdefaultunsharpstrength' => { 103 => 0xbc }, + 'customdefaultunsharpthreshold' => { 103 => 0xc0 }, + 'customilluminant' => { 131 => 0x405 }, + 'customizedials' => { 78 => 0x715 }, + 'customlinear' => { 103 => 0x4f }, + 'customoutputhighlightpoint' => { 103 => 0x53 }, + 'customoutputshadowpoint' => { 103 => 0x54 }, + 'custompicturestyle' => { 97 => 0x10021 }, + 'custompicturestyledata' => { 97 => 0xf0500 }, + 'custompicturestylefilename' => { 60 => 0x4010 }, + 'customrawhighlight' => { 103 => 0x7c }, + 'customrawhighlightpoint' => { 103 => 0x51 }, + 'customrawshadow' => { 103 => 0x85 }, + 'customrawshadowpoint' => { 103 => 0x52 }, + 'customrendered' => { 113 => 0xa401, 452 => 'CustomRendered' }, + 'customsaturation' => { 103 => 0x4d, 278 => 0x503 }, + 'customsettingsalldefault' => { 261 => '0.2', 270 => '0.2' }, + 'customsettingsbank' => { 261 => '0.1', 262 => '0.1', 264 => '0.1', 265 => '0.1', 270 => '0.1', 274 => '0.2', 275 => '0.2' }, + 'customsharpness' => { 103 => 0x50 }, + 'customunsharpmaskfineness' => { 103 => 0xb8 }, + 'customunsharpmaskstrength' => { 103 => 0xb6 }, + 'customunsharpmaskthreshold' => { 103 => 0xba }, + 'customwb_rblevels' => { 399 => 0x1a }, + 'customwb_rgblevels' => { 382 => 0x8, 383 => 0x19 }, + 'customwbbluelevel' => { 174 => 0x36 }, + 'customwberror' => { 174 => 0x37 }, + 'customwbgreenlevel' => { 174 => 0x35 }, + 'customwbredlevel' => { 174 => 0x34 }, + 'customwbsetting' => { 174 => 0x26 }, + 'd-lightinghq' => { 254 => 0x2175eb78 }, + 'd-lightinghqcolorboost' => { 250 => 0x2 }, + 'd-lightinghqhighlight' => { 250 => 0x1 }, + 'd-lightinghqselected' => { 254 => 0x6a6e36b6 }, + 'd-lightinghqshadow' => { 250 => 0x0 }, + 'd-lightinghs' => { 254 => 0xce5554aa }, + 'd-lightinghsadjustment' => { 251 => 0x0 }, + 'd-lightinghscolorboost' => { 251 => 0x1 }, + 'd-rangeoptimizerhighlight' => { 427 => 0x8024 }, + 'd-rangeoptimizermode' => { 427 => 0x8022 }, + 'd-rangeoptimizershadow' => { 427 => 0x802d }, + 'd-rangeoptimizervalue' => { 427 => 0x8023 }, + 'd810meteringmode' => { 241 => 0x175e }, + 'darkblacksegrows' => { 131 => 0x18d8 }, + 'darkfocusenvironment' => { 301 => 0x8003 }, + 'darkframecountfactor' => { 131 => 0xc85 }, + 'darkframelongexposure' => { 131 => 0xc84 }, + 'darkframeshortexposure' => { 131 => 0xc83 }, + 'darkpedestal' => { 131 => 0xc7f }, + 'data' => { 432 => 'Data' }, + 'datacompressionmethod' => { 127 => 0x6e }, + 'dataimprint' => { 171 => 0x34 }, + 'dataonscreen' => { 458 => 'DataOnScreen' }, + 'dataonscreenregion' => { 458 => [\'DataOnScreen','DataOnScreenRegion'] }, + 'dataonscreenregiond' => { 458 => [\'DataOnScreen','DataOnScreenRegionD'] }, + 'dataonscreenregionh' => { 458 => [\'DataOnScreen','DataOnScreenRegionH'] }, + 'dataonscreenregiontext' => { 458 => [\'DataOnScreen','DataOnScreenRegionText'] }, + 'dataonscreenregionunit' => { 458 => [\'DataOnScreen','DataOnScreenRegionUnit'] }, + 'dataonscreenregionw' => { 458 => [\'DataOnScreen','DataOnScreenRegionW'] }, + 'dataonscreenregionx' => { 458 => [\'DataOnScreen','DataOnScreenRegionX'] }, + 'dataonscreenregiony' => { 458 => [\'DataOnScreen','DataOnScreenRegionY'] }, + 'datascaling' => { 336 => 0x3d }, + 'date' => { 336 => 0x6, 449 => 'date' }, + 'dateacquired' => { 169 => 'DateAcquired' }, + 'datecreated' => { 125 => 0x37, 460 => 'DateCreated' }, + 'datedisplayformat' => { 246 => 0x3 }, + 'dateidentified' => { 112 => [\'Identification','IdentificationDateIdentified'] }, + 'dateimprint' => { 266 => '4.2' }, + 'daterecieved' => { 462 => 'dateRecieved' }, + 'datesent' => { 126 => 0x46 }, + 'datestampmode' => { 60 => 0x1c }, + 'datetime' => { 442 => 'datetime', 468 => 'DateTime' }, + 'datetimedigitized' => { 452 => 'DateTimeDigitized' }, + 'datetimeoriginal' => { 94 => 0x0, 113 => 0x9003, 145 => 0x14, 148 => 'OriginalDate', 357 => 0xb, 358 => 0x3b, 359 => 0x3e, 452 => 'DateTimeOriginal' }, + 'datetimestamp' => { 133 => 0x64 }, + 'datetimeutc' => { 278 => 0x908 }, + 'daylightsavings' => { 73 => 0x3, 246 => 0x2 }, + 'dayofweek' => { 358 => 0x42, 359 => 0x4a }, + 'dccontinent' => { 112 => [\'dctermsLocation','dctermsLocationContinent'] }, + 'dccoordinateprecision' => { 112 => [\'dctermsLocation','dctermsLocationCoordinatePrecision'] }, + 'dccoordinateuncertaintyinmeters' => { 112 => [\'dctermsLocation','dctermsLocationCoordinateUncertaintyInMeters'] }, + 'dccountry' => { 112 => [\'dctermsLocation','dctermsLocationCountry'] }, + 'dccountrycode' => { 112 => [\'dctermsLocation','dctermsLocationCountryCode'] }, + 'dccounty' => { 112 => [\'dctermsLocation','dctermsLocationCounty'] }, + 'dcdecimallatitude' => { 112 => [\'dctermsLocation','dctermsLocationDecimalLatitude'] }, + 'dcdecimallongitude' => { 112 => [\'dctermsLocation','dctermsLocationDecimalLongitude'] }, + 'dcevent' => { 112 => 'Event' }, + 'dcfootprintspatialfit' => { 112 => [\'dctermsLocation','dctermsLocationFootprintSpatialFit'] }, + 'dcfootprintsrs' => { 112 => [\'dctermsLocation','dctermsLocationFootprintSRS'] }, + 'dcfootprintwkt' => { 112 => [\'dctermsLocation','dctermsLocationFootprintWKT'] }, + 'dcgeodeticdatum' => { 112 => [\'dctermsLocation','dctermsLocationGeodeticDatum'] }, + 'dcgeoreferencedby' => { 112 => [\'dctermsLocation','dctermsLocationGeoreferencedBy'] }, + 'dcgeoreferenceddate' => { 112 => [\'dctermsLocation','dctermsLocationGeoreferencedDate'] }, + 'dcgeoreferenceprotocol' => { 112 => [\'dctermsLocation','dctermsLocationGeoreferenceProtocol'] }, + 'dcgeoreferenceremarks' => { 112 => [\'dctermsLocation','dctermsLocationGeoreferenceRemarks'] }, + 'dcgeoreferencesources' => { 112 => [\'dctermsLocation','dctermsLocationGeoreferenceSources'] }, + 'dcgeoreferenceverificationstatus' => { 112 => [\'dctermsLocation','dctermsLocationGeoreferenceVerificationStatus'] }, + 'dchighergeography' => { 112 => [\'dctermsLocation','dctermsLocationHigherGeography'] }, + 'dchighergeographyid' => { 112 => [\'dctermsLocation','dctermsLocationHigherGeographyID'] }, + 'dcisland' => { 112 => [\'dctermsLocation','dctermsLocationIsland'] }, + 'dcislandgroup' => { 112 => [\'dctermsLocation','dctermsLocationIslandGroup'] }, + 'dclocality' => { 112 => [\'dctermsLocation','dctermsLocationLocality'] }, + 'dclocationaccordingto' => { 112 => [\'dctermsLocation','dctermsLocationLocationAccordingTo'] }, + 'dclocationid' => { 112 => [\'dctermsLocation','dctermsLocationLocationID'] }, + 'dclocationremarks' => { 112 => [\'dctermsLocation','dctermsLocationLocationRemarks'] }, + 'dcmaximumdepthinmeters' => { 112 => [\'dctermsLocation','dctermsLocationMaximumDepthInMeters'] }, + 'dcmaximumdistanceabovesurfaceinmeters' => { 112 => [\'dctermsLocation','dctermsLocationMaximumDistanceAboveSurfaceInMeters'] }, + 'dcmaximumelevationinmeters' => { 112 => [\'dctermsLocation','dctermsLocationMaximumElevationInMeters'] }, + 'dcminimumdepthinmeters' => { 112 => [\'dctermsLocation','dctermsLocationMinimumDepthInMeters'] }, + 'dcminimumdistanceabovesurfaceinmeters' => { 112 => [\'dctermsLocation','dctermsLocationMinimumDistanceAboveSurfaceInMeters'] }, + 'dcminimumelevationinmeters' => { 112 => [\'dctermsLocation','dctermsLocationMinimumElevationInMeters'] }, + 'dcmunicipality' => { 112 => [\'dctermsLocation','dctermsLocationMunicipality'] }, + 'dcpointradiusspatialfit' => { 112 => [\'dctermsLocation','dctermsLocationPointRadiusSpatialFit'] }, + 'dcstateprovince' => { 112 => [\'dctermsLocation','dctermsLocationStateProvince'] }, + 'dctermslocation' => { 112 => 'dctermsLocation' }, + 'dcverbatimcoordinates' => { 112 => [\'dctermsLocation','dctermsLocationVerbatimCoordinates'] }, + 'dcverbatimcoordinatesystem' => { 112 => [\'dctermsLocation','dctermsLocationVerbatimCoordinateSystem'] }, + 'dcverbatimdepth' => { 112 => [\'dctermsLocation','dctermsLocationVerbatimDepth'] }, + 'dcverbatimelevation' => { 112 => [\'dctermsLocation','dctermsLocationVerbatimElevation'] }, + 'dcverbatimlatitude' => { 112 => [\'dctermsLocation','dctermsLocationVerbatimLatitude'] }, + 'dcverbatimlocality' => { 112 => [\'dctermsLocation','dctermsLocationVerbatimLocality'] }, + 'dcverbatimlongitude' => { 112 => [\'dctermsLocation','dctermsLocationVerbatimLongitude'] }, + 'dcverbatimsrs' => { 112 => [\'dctermsLocation','dctermsLocationVerbatimSRS'] }, + 'dcwaterbody' => { 112 => [\'dctermsLocation','dctermsLocationWaterBody'] }, + 'declination' => { 156 => 'Declination' }, + 'decposition' => { 171 => 0x32 }, + 'defaultautogray' => { 448 => 'DefaultAutoGray' }, + 'defaultautotone' => { 448 => 'DefaultAutoTone' }, + 'defaultblackrender' => { 113 => 0xc7a6 }, + 'defaultcroporigin' => { 113 => 0xc61f }, + 'defaultcropsize' => { 113 => 0xc620 }, + 'defaulteraseoption' => { 78 => 0x813 }, + 'defaultscale' => { 113 => 0xc61e }, + 'defaultsspecifictoiso' => { 448 => 'DefaultsSpecificToISO' }, + 'defaultsspecifictoserial' => { 448 => 'DefaultsSpecificToSerial' }, + 'defaultusercrop' => { 113 => 0xc7b5 }, + 'defectisocode' => { 131 => 0x90f }, + 'defringe' => { 448 => 'Defringe' }, + 'defringegreenamount' => { 448 => 'DefringeGreenAmount' }, + 'defringegreenhuehi' => { 448 => 'DefringeGreenHueHi' }, + 'defringegreenhuelo' => { 448 => 'DefringeGreenHueLo' }, + 'defringepurpleamount' => { 448 => 'DefringePurpleAmount' }, + 'defringepurplehuehi' => { 448 => 'DefringePurpleHueHi' }, + 'defringepurplehuelo' => { 448 => 'DefringePurpleHueLo' }, + 'dehaze' => { 448 => 'Dehaze' }, + 'deletedimagecount' => { 214 => 0xa6, 223 => 0x6e }, + 'deprecatedon' => { 445 => 'deprecatedOn' }, + 'derivedfrom' => { 473 => 'DerivedFrom' }, + 'derivedfromalternatepaths' => { 473 => [\'DerivedFrom','DerivedFromAlternatePaths'] }, + 'derivedfromdocumentid' => { 473 => [\'DerivedFrom','DerivedFromDocumentID'] }, + 'derivedfromfilepath' => { 473 => [\'DerivedFrom','DerivedFromFilePath'] }, + 'derivedfromfrompart' => { 473 => [\'DerivedFrom','DerivedFromFromPart'] }, + 'derivedfrominstanceid' => { 473 => [\'DerivedFrom','DerivedFromInstanceID'] }, + 'derivedfromlastmodifydate' => { 473 => [\'DerivedFrom','DerivedFromLastModifyDate'] }, + 'derivedfromlasturl' => { 473 => [\'DerivedFrom','DerivedFromLastURL'] }, + 'derivedfromlinkcategory' => { 473 => [\'DerivedFrom','DerivedFromLinkCategory'] }, + 'derivedfromlinkform' => { 473 => [\'DerivedFrom','DerivedFromLinkForm'] }, + 'derivedfrommanager' => { 473 => [\'DerivedFrom','DerivedFromManager'] }, + 'derivedfrommanagervariant' => { 473 => [\'DerivedFrom','DerivedFromManagerVariant'] }, + 'derivedfrommanageto' => { 473 => [\'DerivedFrom','DerivedFromManageTo'] }, + 'derivedfrommanageui' => { 473 => [\'DerivedFrom','DerivedFromManageUI'] }, + 'derivedfrommaskmarkers' => { 473 => [\'DerivedFrom','DerivedFromMaskMarkers'] }, + 'derivedfromoriginaldocumentid' => { 473 => [\'DerivedFrom','DerivedFromOriginalDocumentID'] }, + 'derivedfrompartmapping' => { 473 => [\'DerivedFrom','DerivedFromPartMapping'] }, + 'derivedfromplacedresolutionunit' => { 473 => [\'DerivedFrom','DerivedFromPlacedResolutionUnit'] }, + 'derivedfromplacedxresolution' => { 473 => [\'DerivedFrom','DerivedFromPlacedXResolution'] }, + 'derivedfromplacedyresolution' => { 473 => [\'DerivedFrom','DerivedFromPlacedYResolution'] }, + 'derivedfromrenditionclass' => { 473 => [\'DerivedFrom','DerivedFromRenditionClass'] }, + 'derivedfromrenditionparams' => { 473 => [\'DerivedFrom','DerivedFromRenditionParams'] }, + 'derivedfromtopart' => { 473 => [\'DerivedFrom','DerivedFromToPart'] }, + 'derivedfromversionid' => { 473 => [\'DerivedFrom','DerivedFromVersionID'] }, + 'description' => { 291 => 'Description', 449 => 'description', 470 => 'Description' }, + 'destination' => { 126 => 0x5 }, + 'destinationcity' => { 336 => 0x24, 342 => 0x3 }, + 'destinationcitycode' => { 343 => 0x1001 }, + 'destinationdst' => { 336 => 0x26, 342 => '0.3' }, + 'developmentdynamicrange' => { 121 => 0x1403 }, + 'deviantmatrixcustom' => { 131 => 0x7de }, + 'deviantmatrixdaylight' => { 131 => 0x7da }, + 'deviantmatrixflash' => { 131 => 0x7dd }, + 'deviantmatrixfluorescent' => { 131 => 0x7dc }, + 'deviantmatrixtungsten' => { 131 => 0x7db }, + 'deviantwhitecustom' => { 131 => 0x842 }, + 'deviantwhitedaylight' => { 131 => 0x83e }, + 'deviantwhiteflash' => { 131 => 0x841 }, + 'deviantwhitefluorescent' => { 131 => 0x840 }, + 'deviantwhitetungsten' => { 131 => 0x83f }, + 'device' => { 462 => 'device' }, + 'devicesettingdescription' => { 452 => 'DeviceSettingDescription' }, + 'devicesettingdescriptioncolumns' => { 452 => [\'DeviceSettingDescription','DeviceSettingDescriptionColumns'] }, + 'devicesettingdescriptionrows' => { 452 => [\'DeviceSettingDescription','DeviceSettingDescriptionRows'] }, + 'devicesettingdescriptionsettings' => { 452 => [\'DeviceSettingDescription','DeviceSettingDescriptionSettings'] }, + 'devicetype' => { 370 => 0x2 }, + 'dewarpdata' => { 110 => 'DewarpData' }, + 'dewarpflag' => { 110 => 'DewarpFlag' }, + 'dialdirectiontvav' => { 78 => 0x706 }, + 'dietaryneeds' => { 464 => 'dietaryNeeds' }, + 'diffractioncorrection' => { 301 => 0xbc, 326 => 0x3 }, + 'diffractioncorrectionon' => { 97 => 0x2070b }, + 'digitalcreationdate' => { 125 => 0x3e }, + 'digitalcreationtime' => { 125 => 0x3f }, + 'digitaldeehighlightadj' => { 222 => 0x202 }, + 'digitaldeeshadowadj' => { 222 => 0x200 }, + 'digitaldeethreshold' => { 222 => 0x201 }, + 'digitalfilter' => { 373 => 0x59 }, + 'digitalfilter01' => { 323 => 0x5 }, + 'digitalfilter02' => { 323 => 0x16 }, + 'digitalfilter03' => { 323 => 0x27 }, + 'digitalfilter04' => { 323 => 0x38 }, + 'digitalfilter05' => { 323 => 0x49 }, + 'digitalfilter06' => { 323 => 0x5a }, + 'digitalfilter07' => { 323 => 0x6b }, + 'digitalfilter08' => { 323 => 0x7c }, + 'digitalfilter09' => { 323 => 0x8d }, + 'digitalfilter10' => { 323 => 0x9e }, + 'digitalfilter11' => { 323 => 0xaf }, + 'digitalfilter12' => { 323 => 0xc0 }, + 'digitalfilter13' => { 323 => 0xd1 }, + 'digitalfilter14' => { 323 => 0xe2 }, + 'digitalfilter15' => { 323 => 0xf3 }, + 'digitalfilter16' => { 323 => 0x104 }, + 'digitalfilter17' => { 323 => 0x115 }, + 'digitalfilter18' => { 323 => 0x126 }, + 'digitalfilter19' => { 323 => 0x137 }, + 'digitalfilter20' => { 323 => 0x148 }, + 'digitalgain' => { 70 => 0xb }, + 'digitalgem' => { 203 => 0x0 }, + 'digitalice' => { 222 => 0x100 }, + 'digitalimageguid' => { 458 => 'DigImageGUID' }, + 'digitalroc' => { 220 => 0x0 }, + 'digitalsourcefiletype' => { 458 => 'DigitalSourcefileType' }, + 'digitalsourcetype' => { 458 => 'DigitalSourceType' }, + 'digitalzoom' => { 33 => 0xc, 106 => 0xa, 121 => 0x1044, 133 => 0x68, 147 => 'DigitalZoom', 171 => 0xc, 214 => 0x86, 244 => 0xa, 283 => 0x204, 336 => 0x1e, 343 => 0xa, 372 => 0x204, 414 => 0x12, 415 => 0x12 }, + 'digitalzoomon' => { 372 => 0x21b }, + 'digitalzoomratio' => { 113 => 0xa404, 404 => 0x200, 406 => 0x21c, 452 => 'DigitalZoomRatio' }, + 'director' => { 472 => 'director' }, + 'directorphotography' => { 472 => 'directorPhotography' }, + 'directory' => { 114 => 'Directory' }, + 'directoryindex' => { 6 => 0x137, 8 => 0x2dc, 10 => 0x17e, 12 => 0x238, 13 => 0x13f, 14 => 0x133, 15 => 0x1df, 16 => 0x1a7, 17 => 0x1f0, 18 => 0xcc, 19 => 0x1c7, 20 => 0x298, 21 => 0x1e7, 22 => 0x1e5, 23 => [0x27c,0x280], 24 => 0x2b6, 25 => 0x2bf, 27 => 0x1f7, 28 => 0x4ba }, + 'directoryindex2' => { 20 => 0x29c }, + 'directorynumber' => { 197 => 0x3, 359 => 0x12 }, + 'disclaimer' => { 291 => 'Disclaimer' }, + 'discnumber' => { 472 => 'discNumber' }, + 'dishtype' => { 464 => 'dishType' }, + 'displayallafpoints' => { 78 => 0x514 }, + 'displayaperture' => { 33 => 0x23 }, + 'displayedunitsx' => { 351 => 0x2 }, + 'displayedunitsy' => { 351 => 0x6 }, + 'displayname' => { 461 => 'displayName' }, + 'distance1' => { 133 => 0x28 }, + 'distance2' => { 133 => 0x2c }, + 'distance3' => { 133 => 0x30 }, + 'distance4' => { 133 => 0x34 }, + 'distortion' => { 370 => 0xa050 }, + 'distortioncompensation' => { 427 => 0x8040 }, + 'distortioncontrol' => { 223 => 0x10 }, + 'distortioncorrection' => { 97 => 0x20705, 103 => 0x67, 113 => 0x7036, 278 => 0x50b, 305 => '7.1', 326 => 0x0, 422 => 0x601, 423 => 0x5b }, + 'distortioncorrection2' => { 282 => 0x1011 }, + 'distortioncorrectionalreadyapplied' => { 444 => 'DistortionCorrectionAlreadyApplied' }, + 'distortioncorrectionon' => { 97 => '0x20705.0', 103 => 0x63 }, + 'distortioncorrectionsetting' => { 394 => 0x2013 }, + 'distortioncorrparams' => { 113 => 0x7037, 403 => 0x1a23, 406 => 0x1870, 408 => 0x189c, 409 => 0x18cc, 410 => 0x17d0, 422 => 0x6ca, 423 => 0x64 }, + 'distortioncorrparamsnumber' => { 406 => 0x1899, 408 => 0x18c5, 409 => 0x18f5, 410 => 0x17f9 }, + 'distortioncorrparamspresent' => { 406 => 0x1898, 408 => 0x18c4, 409 => 0x18f4, 410 => 0x17f8, 412 => 0x10b, 413 => 0x10b, 422 => 0x600, 423 => 0x5a }, + 'distortioneffect' => { 97 => 0x20709 }, + 'distortionn' => { 305 => 0xc }, + 'distortionparam02' => { 305 => 0x2 }, + 'distortionparam04' => { 305 => 0x4 }, + 'distortionparam08' => { 305 => 0x8 }, + 'distortionparam09' => { 305 => 0x9 }, + 'distortionparam11' => { 305 => 0xb }, + 'distortionscale' => { 305 => 0x5 }, + 'distributor' => { 462 => 'distributor' }, + 'distributorproductid' => { 461 => 'distributorProductID' }, + 'dloon' => { 97 => '0x20706.0', 103 => 0xdc }, + 'dlosetting' => { 97 => 0x20706, 103 => 0xdd }, + 'dlosettingapplied' => { 96 => 0x4 }, + 'dloshootingdistance' => { 103 => 0xde }, + 'dloversion' => { 96 => 0x5 }, + 'dmcomment' => { 472 => 'comment' }, + 'dmdithermatrix' => { 131 => 0xc7a }, + 'dmdithermatrixheight' => { 131 => 0xc7c }, + 'dmdithermatrixwidth' => { 131 => 0xc7b }, + 'dngadobedata' => { 113 => 0xc634 }, + 'dngbackwardversion' => { 113 => 0xc613 }, + 'dngignoresidecars' => { 448 => 'DNGIgnoreSidecars' }, + 'dnglensinfo' => { 113 => 0xc630 }, + 'dngprivatedata' => { 113 => 0xc634 }, + 'dngversion' => { 113 => 0xc612 }, + 'document' => { 291 => 'Document' }, + 'documentancestors' => { 460 => 'DocumentAncestors' }, + 'documenthistory' => { 125 => 0xe7 }, + 'documentid' => { 473 => 'DocumentID' }, + 'documentname' => { 113 => 0x10d }, + 'documentnotes' => { 125 => 0xe6 }, + 'doi' => { 462 => 'doi' }, + 'dopesheet' => { 458 => 'Dopesheet' }, + 'dopesheetlink' => { 458 => 'DopesheetLink' }, + 'dopesheetlinklink' => { 458 => [\'DopesheetLink','DopesheetLinkLink'] }, + 'dopesheetlinklinkqualifier' => { 458 => [\'DopesheetLink','DopesheetLinkLinkQualifier'] }, + 'doublingmicrovolts' => { 131 => 0xc82 }, + 'dpp' => { 442 => 'dpp' }, + 'dr4cameramodel' => { 98 => 0x3 }, + 'drangepriority' => { 121 => 0x1443 }, + 'drangepriorityauto' => { 121 => 0x1444 }, + 'drangepriorityfixed' => { 121 => 0x1445 }, + 'drivemode' => { 107 => 0x3103, 119 => '0.1', 171 => 0x6, 174 => 0x1e, 177 => 0xe, 278 => 0x600, 336 => 0x34, 363 => 0x1002, 373 => 0x3, 381 => 0x4, 382 => 0x7e, 383 => 0x34 }, + 'drivemode2' => { 174 => 0xa, 317 => 0x7, 392 => 0xe, 399 => 0x1 }, + 'drivemodesetting' => { 383 => 0x4 }, + 'drivespeed' => { 119 => '0.2' }, + 'dspfirmwareversion' => { 336 => 0x27 }, + 'duration' => { 63 => 0x6a, 146 => 'Duration', 160 => 'Duration', 464 => 'duration', 472 => 'duration' }, + 'durationscale' => { 472 => [\'duration','durationScale'] }, + 'durationvalue' => { 472 => [\'duration','durationValue'] }, + 'dustremovaldata' => { 60 => 0x97 }, + 'dynamicafarea' => { 261 => '1.4', 270 => '1.4' }, + 'dynamicareaafdisplay' => { 262 => '46.1', 264 => '47.1', 265 => '47.1', 274 => '47.1', 275 => '47.1' }, + 'dynamicrange' => { 121 => 0x1400 }, + 'dynamicrangeexpansion' => { 336 => 0x69, 363 => 0x100e }, + 'dynamicrangemax' => { 102 => 0x7c }, + 'dynamicrangemin' => { 102 => 0x7a }, + 'dynamicrangeoptimizer' => { 174 => 0x15, 394 => [0xb025,0xb04f], 402 => 0x1144, 403 => [0x1144,0x324], 404 => [0x1120,0x300], 405 => [0x119c,0x37c], 406 => [0x1178,0x328], 407 => [0x1030,0x50], 408 => [0x228,0x50], 409 => [0x228,0x50], 410 => [0x21b,0x4e] }, + 'dynamicrangeoptimizerbracket' => { 392 => 0x2e }, + 'dynamicrangeoptimizerlevel' => { 381 => 0x19, 382 => 0x17, 383 => 0xd, 392 => 0x79, 399 => 0x5 }, + 'dynamicrangeoptimizermode' => { 177 => 0x15, 381 => 0x18, 382 => 0x16, 392 => [0x77,0x15] }, + 'dynamicrangeoptimizersetting' => { 174 => 0x27, 383 => 0xc, 399 => 0x4 }, + 'dynamicrangesetting' => { 121 => 0x1402 }, + 'e-dialinprogram' => { 317 => '1.3' }, + 'earliestageorloweststage' => { 112 => [\'GeologicalContext','GeologicalContextEarliestAgeOrLowestStage'] }, + 'earliesteonorlowesteonothem' => { 112 => [\'GeologicalContext','GeologicalContextEarliestEonOrLowestEonothem'] }, + 'earliestepochorlowestseries' => { 112 => [\'GeologicalContext','GeologicalContextEarliestEpochOrLowestSeries'] }, + 'earliesteraorlowesterathem' => { 112 => [\'GeologicalContext','GeologicalContextEarliestEraOrLowestErathem'] }, + 'earliestperiodorlowestsystem' => { 112 => [\'GeologicalContext','GeologicalContextEarliestPeriodOrLowestSystem'] }, + 'easyexposurecomp' => { 276 => '6.1' }, + 'easyexposurecompensation' => { 261 => '6.4', 262 => '6.5', 264 => '6.3', 265 => '6.3', 269 => '5.1', 270 => '4.4', 271 => '5.2', 274 => '6.3', 275 => '6.3' }, + 'easymode' => { 33 => 0xb }, + 'edgemapslope' => { 131 => 0x930 }, + 'edgemapx1' => { 131 => 0x931 }, + 'edgemapx2' => { 131 => 0x932 }, + 'edgemapx3' => { 131 => 0x934 }, + 'edgemapx4' => { 131 => 0x935 }, + 'edgenoisereduction' => { 255 => 0x4, 427 => 0x8028 }, + 'edition' => { 462 => 'edition' }, + 'editorialupdate' => { 125 => 0x8 }, + 'editstatus' => { 125 => 0x7, 348 => 'EditStatus', 442 => 'EditStatus' }, + 'editversionname' => { 254 => 0x3d136244 }, + 'effectivelv' => { 336 => 0x2d }, + 'effectivemaxaperture' => { 207 => 0x12, 208 => 0x13, 212 => 0x14 }, + 'eissn' => { 462 => 'eIssn' }, + 'electricalblackcolumns' => { 131 => 0x1810 }, + 'electronicfront-curtainshutter' => { 264 => '5.2', 265 => '5.2', 274 => '5.3', 275 => '5.2' }, + 'electronicfrontcurtainshutter' => { 394 => 0x201a }, + 'elevation' => { 156 => 'Elevation' }, + 'email' => { 148 => 'EMail' }, + 'embargodate' => { 465 => 'embargoDate' }, + 'embdencrightsexpr' => { 458 => 'EmbdEncRightsExpr' }, + 'embeddedencodedrightsexpr' => { 458 => [\'EmbdEncRightsExpr','EmbdEncRightsExprEncRightsExpr'] }, + 'embeddedencodedrightsexprlangid' => { 458 => [\'EmbdEncRightsExpr','EmbdEncRightsExprRightsExprLangId'] }, + 'embeddedencodedrightsexprtype' => { 458 => [\'EmbdEncRightsExpr','EmbdEncRightsExprRightsExprEncType'] }, + 'embeddedxmpdigest' => { 460 => 'EmbeddedXMPDigest' }, + 'emissivity' => { 115 => 0x3 }, + 'enablechromanoisereduction' => { 131 => 0xe6e }, + 'enablesharpening' => { 131 => 0x92e }, + 'encryptionkey' => { 370 => 0xa020 }, + 'endingpage' => { 462 => 'endingPage' }, + 'enduser' => { 288 => 'EndUser' }, + 'enduserid' => { 288 => [\'EndUser','EndUserEndUserID'] }, + 'endusername' => { 288 => [\'EndUser','EndUserEndUserName'] }, + 'engineer' => { 472 => 'engineer' }, + 'enhancedarktones' => { 247 => 0x8 }, + 'enhancement' => { 106 => 0x16, 107 => 0x3016 }, + 'enhancer' => { 282 => 0x300 }, + 'enhancervalues' => { 282 => 0x301 }, + 'envelopenumber' => { 126 => 0x28 }, + 'envelopepriority' => { 126 => 0x3c }, + 'enveloperecordversion' => { 126 => 0x0 }, + 'episode' => { 458 => 'Episode' }, + 'episodeidentifier' => { 458 => [\'Episode','EpisodeIdentifier'] }, + 'episodename' => { 458 => [\'Episode','EpisodeName'] }, + 'episodenumber' => { 458 => [\'Episode','EpisodeNumber'] }, + 'epsonimageheight' => { 283 => 0x20c }, + 'epsonimagewidth' => { 283 => 0x20b }, + 'epsonsoftware' => { 283 => 0x20d }, + 'equipmentinstitution' => { 429 => 'EquipmentInstitution' }, + 'equipmentmanufacturer' => { 429 => 'EquipmentManufacturer' }, + 'equipmentversion' => { 279 => 0x0 }, + 'ettlii' => { 78 => 0x304, 79 => 0xd, 80 => 0xe, 81 => 0x7, 82 => 0x7, 83 => 0xe }, + 'event' => { 430 => 'Event', 440 => 'Event', 458 => 'Event', 462 => 'event' }, + 'eventalias' => { 461 => 'eventAlias' }, + 'eventdate' => { 112 => [\'Event','EventEventDate'] }, + 'eventday' => { 112 => [\'Event','EventDay'] }, + 'eventearliestdate' => { 112 => [\'Event','EventEarliestDate'] }, + 'eventend' => { 461 => 'eventEnd' }, + 'eventenddayofyear' => { 112 => [\'Event','EventEndDayOfYear'] }, + 'eventfieldnotes' => { 112 => [\'Event','EventFieldNotes'] }, + 'eventfieldnumber' => { 112 => [\'Event','EventFieldNumber'] }, + 'eventhabitat' => { 112 => [\'Event','EventHabitat'] }, + 'eventid' => { 112 => [\'Event','EventEventID'] }, + 'eventlatestdate' => { 112 => [\'Event','EventLatestDate'] }, + 'eventmonth' => { 112 => [\'Event','EventMonth'] }, + 'eventnumber' => { 357 => 0x9, 358 => 0x37, 359 => 0x3a }, + 'eventparenteventid' => { 112 => [\'Event','EventParentEventID'] }, + 'eventremarks' => { 112 => [\'Event','EventEventRemarks'] }, + 'eventsamplesizeunit' => { 112 => [\'Event','EventSampleSizeUnit'] }, + 'eventsamplesizevalue' => { 112 => [\'Event','EventSampleSizeValue'] }, + 'eventsamplingeffort' => { 112 => [\'Event','EventSamplingEffort'] }, + 'eventsamplingprotocol' => { 112 => [\'Event','EventSamplingProtocol'] }, + 'eventstart' => { 461 => 'eventStart' }, + 'eventstartdayofyear' => { 112 => [\'Event','EventStartDayOfYear'] }, + 'eventsubtype' => { 461 => 'eventSubtype' }, + 'eventtime' => { 112 => [\'Event','EventEventTime'] }, + 'eventtype' => { 461 => 'eventType' }, + 'eventverbatimeventdate' => { 112 => [\'Event','EventVerbatimEventDate'] }, + 'eventyear' => { 112 => [\'Event','EventYear'] }, + 'evsteps' => { 317 => '1.2', 319 => 0x0 }, + 'evstepsize' => { 266 => '5.1', 267 => '6.1', 268 => '6.1', 272 => '0.7' }, + 'exclusivecoverage' => { 437 => 'ExclusiveCoverage' }, + 'exclusivityenddate' => { 465 => 'exclusivityEndDate' }, + 'excursiontolerance' => { 127 => 0x82 }, + 'exif' => { 114 => 'EXIF' }, + 'exifbyteorder' => { 114 => 'ExifByteOrder' }, + 'exifcamerainfo' => { 125 => 0xe8 }, + 'exifimageheight' => { 113 => 0xa003, 452 => 'PixelYDimension' }, + 'exifimagewidth' => { 113 => 0xa002, 452 => 'PixelXDimension' }, + 'exifunicodebyteorder' => { 114 => 'ExifUnicodeByteOrder' }, + 'exifversion' => { 113 => 0x9000, 452 => 'ExifVersion' }, + 'exitpupilposition' => { 207 => 0x4, 208 => 0x4, 212 => 0x4 }, + 'expirationdate' => { 125 => 0x25, 465 => 'expirationDate' }, + 'expirationtime' => { 125 => 0x26 }, + 'exposure' => { 113 => 0xfe51, 448 => 'Exposure' }, + 'exposure2012' => { 448 => 'Exposure2012' }, + 'exposureadj' => { 252 => 0x0 }, + 'exposureadj2' => { 252 => 0x12 }, + 'exposureadjust' => { 373 => 0xc }, + 'exposurebracketingindicatorlast' => { 174 => 0x52 }, + 'exposurebracketshotnumber' => { 177 => 0x2d, 392 => 0x2f }, + 'exposurebracketstepsize' => { 317 => 0x8 }, + 'exposurebracketvalue' => { 214 => 0x19 }, + 'exposurecompautocancel' => { 78 => 0x113 }, + 'exposurecompensation' => { 72 => 0x6, 87 => 0x0, 113 => 0x9204, 133 => 0x24, 147 => 'ExposureComp', 167 => 'ExposureCompensation', 171 => 0xd, 172 => 0x53, 173 => 0x1e, 177 => 0x49c0, 283 => 0x1006, 336 => 0x16, 345 => 0x402, 370 => 0xa013, 373 => [0xc,0x35,0x4d], 402 => 0x114c, 403 => 0x114c, 404 => 0x1128, 406 => 0x1180, 407 => 0x1038, 408 => 0x230, 409 => 0x230, 410 => 0x223, 452 => 'ExposureBiasValue' }, + 'exposurecompensation2' => { 399 => [0x24,0x26,0x2a] }, + 'exposurecompensationmode' => { 174 => 0x47, 177 => 0x2a }, + 'exposurecompensationset' => { 381 => 0x3, 382 => 0x3, 383 => 0x3, 399 => 0x1e }, + 'exposurecompensationsetting' => { 174 => 0x1 }, + 'exposurecompstepsize' => { 261 => '6.3', 262 => '7.3', 264 => '7.3', 265 => '7.3', 270 => '4.3', 274 => '7.3', 275 => '7.3' }, + 'exposurecontrolstep' => { 269 => '6.1', 271 => '6.1' }, + 'exposurecontrolstepsize' => { 261 => '6.2', 262 => '7.1', 264 => '7.1', 265 => '7.1', 270 => '4.2', 274 => '7.1', 275 => '7.1', 276 => '7.1' }, + 'exposurecount' => { 121 => 0x1032 }, + 'exposuredelaymode' => { 261 => '10.1', 262 => '11.1', 264 => '11.1', 265 => '11.1', 266 => '9.1', 267 => '10.1', 268 => '10.1', 270 => '10.4', 271 => '10.1', 272 => '6.4', 274 => '11.1', 275 => '11.1', 276 => '11.2' }, + 'exposuredifference' => { 214 => 0xe }, + 'exposuregaincustom' => { 131 => 0x89c }, + 'exposuregaindaylight' => { 131 => 0x898 }, + 'exposuregainflash' => { 131 => 0x89b }, + 'exposuregainfluorescent' => { 131 => 0x89a }, + 'exposuregaintungsten' => { 131 => 0x899 }, + 'exposureindex' => { 113 => 0xa215, 452 => 'ExposureIndex' }, + 'exposureindicator' => { 174 => 0x50 }, + 'exposurelevelincrements' => { 76 => 0x6, 77 => 0x6, 78 => 0x101, 79 => 0x5, 80 => 0x6, 81 => 0x5, 82 => 0x5, 83 => 0x6, 84 => 0x4, 381 => 0x58, 382 => 0x58 }, + 'exposurelockused' => { 435 => 'ExposureLockUsed' }, + 'exposuremode' => { 113 => 0xa402, 147 => 'ExposureMode', 171 => 0x1, 172 => 0xa, 173 => 0x0, 174 => 0x0, 177 => 0x34, 278 => 0x200, 298 => 0x40d, 373 => 0x8, 394 => 0xb041, 452 => 'ExposureMode' }, + 'exposuremodeinmanual' => { 78 => 0x10b }, + 'exposureprogram' => { 113 => 0x8822, 363 => 0x1001, 374 => [0x17e,0x43], 381 => 0x3c, 382 => 0x3c, 383 => 0x5, 387 => 0x14, 392 => 0x3f, 399 => 0x2, 402 => 0x1175, 403 => 0x1179, 404 => 0x1155, 405 => 0x11d1, 406 => 0x11ad, 407 => 0x1065, 408 => 0x25d, 409 => 0x25d, 410 => 0x24c, 419 => 0xb, 420 => 0xc, 421 => 0xb, 423 => 0x48, 452 => 'ExposureProgram' }, + 'exposureshift' => { 278 => 0x203 }, + 'exposurestandardadjustment' => { 394 => 0x202d }, + 'exposuretime' => { 6 => 0x4, 7 => 0x4, 8 => 0x4, 9 => 0x4, 10 => 0x4, 11 => 0x4, 12 => 0x4, 13 => 0x4, 14 => 0x4, 15 => 0x4, 16 => 0x4, 17 => 0x4, 18 => 0x4, 19 => 0x4, 20 => 0x4, 21 => 0x4, 22 => 0x4, 23 => 0x4, 24 => 0x4, 25 => 0x4, 26 => 0x4, 27 => 0x4, 28 => 0x4, 29 => 0x6, 30 => 0x7, 72 => 0x16, 113 => 0x829a, 130 => 0xfd05, 133 => 0x20, 135 => 0xfa24, 137 => 0xf104, 140 => 0x12, 142 => 0x38, 145 => 0x10, 147 => 'ExposureTime', 171 => 0x9, 172 => 0x35, 173 => 0x48, 174 => 0x8, 177 => 0x49b8, 336 => 0x12, 370 => 0xa018, 373 => [0x32,0x4a], 381 => 0x0, 382 => 0x0, 399 => [0x21,0x23,0x27], 423 => 0x10, 452 => 'ExposureTime' }, + 'exposuretime2' => { 373 => [0x33,0x4b] }, + 'exposuretuning' => { 214 => 0x1c }, + 'exposurevalue' => { 131 => 0x3 }, + 'exposurewarning' => { 121 => 0x1302 }, + 'exrauto' => { 121 => 0x1033 }, + 'exrmode' => { 121 => 0x1034 }, + 'extendedwbdetect' => { 278 => 0x902 }, + 'extender' => { 279 => 0x301 }, + 'extenderfirmwareversion' => { 279 => 0x304 }, + 'extendermagnification' => { 149 => 'Magnification' }, + 'extendermake' => { 149 => 'Make' }, + 'extendermodel' => { 149 => 'Model', 279 => 0x303 }, + 'extenderserialnumber' => { 149 => 'SerialNumber', 279 => 0x302 }, + 'extenderstatus' => { 334 => 0x3 }, + 'externalflash' => { 281 => 0x1201 }, + 'externalflashae1' => { 283 => 0x101f }, + 'externalflashae1_0' => { 283 => 0x101b }, + 'externalflashae2' => { 283 => 0x1020 }, + 'externalflashae2_0' => { 283 => 0x101c }, + 'externalflashbounce' => { 281 => 0x1204, 283 => 0x1026, 324 => 0x1a }, + 'externalflashcompensation' => { 200 => 0x1b }, + 'externalflashexposurecomp' => { 214 => 0x17, 324 => 0x19 }, + 'externalflashfirmware' => { 198 => 0x6, 199 => 0x6, 200 => 0x6, 201 => 0x6, 202 => 0x6 }, + 'externalflashflags' => { 198 => 0x8, 199 => 0x8, 200 => 0x8, 201 => 0x8 }, + 'externalflashguidenumber' => { 281 => 0x1203, 324 => '24.1' }, + 'externalflashgvalue' => { 283 => 0x1025 }, + 'externalflashmode' => { 283 => 0x1028, 324 => 0x2 }, + 'externalflashreadystate' => { 202 => '9.1' }, + 'externalflashstatus' => { 202 => '8.2' }, + 'externalflashzoom' => { 281 => 0x1205, 283 => 0x1027 }, + 'externalflashzoomoverride' => { 202 => '8.1' }, + 'externalmetadatalink' => { 458 => 'ExternalMetadataLink' }, + 'externalsensorbrightnessvalue' => { 296 => 0x311, 299 => 0x311, 300 => 0x311, 303 => 0x3408 }, + 'extrainfoversion' => { 385 => 0x1a }, + 'eyestartaf' => { 174 => 0x40 }, + 'fac100per' => { 131 => 0xe94 }, + 'fac170per' => { 131 => 0xe93 }, + 'fac18per' => { 131 => 0xe92 }, + 'face10position' => { 104 => 0x3f4, 105 => 0x1ec, 196 => 0x28, 321 => 0x12 }, + 'face10size' => { 322 => 0x12 }, + 'face11position' => { 196 => 0x2c, 321 => 0x14 }, + 'face11size' => { 322 => 0x14 }, + 'face12position' => { 196 => 0x30, 321 => 0x16 }, + 'face12size' => { 322 => 0x16 }, + 'face13position' => { 321 => 0x18 }, + 'face13size' => { 322 => 0x18 }, + 'face14position' => { 321 => 0x1a }, + 'face14size' => { 322 => 0x1a }, + 'face15position' => { 321 => 0x1c }, + 'face15size' => { 322 => 0x1c }, + 'face16position' => { 321 => 0x1e }, + 'face16size' => { 322 => 0x1e }, + 'face17position' => { 321 => 0x20 }, + 'face17size' => { 322 => 0x20 }, + 'face18position' => { 321 => 0x22 }, + 'face18size' => { 322 => 0x22 }, + 'face19position' => { 321 => 0x24 }, + 'face19size' => { 322 => 0x24 }, + 'face1position' => { 51 => 0x8, 104 => 0xd, 105 => 0x18, 196 => 0x4, 293 => 0x1, 321 => 0x0, 360 => 0xbc, 388 => 0x1, 389 => 0x0, 390 => 0x0, 391 => 0x5b }, + 'face1size' => { 322 => 0x0 }, + 'face20position' => { 321 => 0x26 }, + 'face20size' => { 322 => 0x26 }, + 'face21position' => { 321 => 0x28 }, + 'face21size' => { 322 => 0x28 }, + 'face22position' => { 321 => 0x2a }, + 'face22size' => { 322 => 0x2a }, + 'face23position' => { 321 => 0x2c }, + 'face23size' => { 322 => 0x2c }, + 'face24position' => { 321 => 0x2e }, + 'face24size' => { 322 => 0x2e }, + 'face25position' => { 321 => 0x30 }, + 'face25size' => { 322 => 0x30 }, + 'face26position' => { 321 => 0x32 }, + 'face26size' => { 322 => 0x32 }, + 'face27position' => { 321 => 0x34 }, + 'face27size' => { 322 => 0x34 }, + 'face28position' => { 321 => 0x36 }, + 'face28size' => { 322 => 0x36 }, + 'face29position' => { 321 => 0x38 }, + 'face29size' => { 322 => 0x38 }, + 'face2position' => { 51 => 0xa, 104 => 0x7c, 105 => 0x4c, 196 => 0x8, 293 => 0x5, 321 => 0x2, 360 => 0xc8, 388 => 0x6, 389 => 0x20, 390 => 0x25, 391 => 0x65 }, + 'face2size' => { 322 => 0x2 }, + 'face30position' => { 321 => 0x3a }, + 'face30size' => { 322 => 0x3a }, + 'face31position' => { 321 => 0x3c }, + 'face31size' => { 322 => 0x3c }, + 'face32position' => { 321 => 0x3e }, + 'face32size' => { 322 => 0x3e }, + 'face3position' => { 51 => 0xc, 104 => 0xeb, 105 => 0x80, 196 => 0xc, 293 => 0x9, 321 => 0x4, 360 => 0xd4, 388 => 0xb, 389 => 0x40, 390 => 0x4a, 391 => 0x6f }, + 'face3size' => { 322 => 0x4 }, + 'face4position' => { 51 => 0xe, 104 => 0x15a, 105 => 0xb4, 196 => 0x10, 293 => 0xd, 321 => 0x6, 360 => 0xe0, 388 => 0x10, 389 => 0x60, 390 => 0x6f, 391 => 0x79 }, + 'face4size' => { 322 => 0x6 }, + 'face5position' => { 51 => 0x10, 104 => 0x1c9, 105 => 0xe8, 196 => 0x14, 293 => 0x11, 321 => 0x8, 360 => 0xec, 388 => 0x15, 389 => 0x80, 390 => 0x94 }, + 'face5size' => { 322 => 0x8 }, + 'face6position' => { 51 => 0x12, 104 => 0x238, 105 => 0x11c, 196 => 0x18, 321 => 0xa, 360 => 0xf8, 388 => 0x1a, 389 => 0xa0, 390 => 0xb9 }, + 'face6size' => { 322 => 0xa }, + 'face7position' => { 51 => 0x14, 104 => 0x2a7, 105 => 0x150, 196 => 0x1c, 321 => 0xc, 360 => 0x104, 388 => 0x1f, 389 => 0xc0, 390 => 0xde }, + 'face7size' => { 322 => 0xc }, + 'face8position' => { 51 => 0x16, 104 => 0x316, 105 => 0x184, 196 => 0x20, 321 => 0xe, 360 => 0x110, 388 => 0x24, 389 => 0xe0, 390 => 0x103 }, + 'face8size' => { 322 => 0xe }, + 'face9position' => { 51 => 0x18, 104 => 0x385, 105 => 0x1b8, 196 => 0x24, 321 => 0x10 }, + 'face9size' => { 322 => 0x10 }, + 'facebalanceorigi' => { 441 => 'FaceBalanceOrigI' }, + 'facebalanceorigq' => { 441 => 'FaceBalanceOrigQ' }, + 'facebalancestrength' => { 441 => 'FaceBalanceStrength' }, + 'facebalancewarmth' => { 441 => 'FaceBalanceWarmth' }, + 'facedetect' => { 336 => 0x76, 370 => 0x100 }, + 'facedetectarea' => { 282 => 0x1201 }, + 'facedetectframecrop' => { 282 => 0x1207 }, + 'facedetectframesize' => { 51 => 0x3, 104 => 0x1, 105 => 0x4, 196 => 0x1, 282 => 0x1203, 336 => 0x77, 360 => 0xb6 }, + 'facedetection' => { 383 => 0x30, 399 => 0x19 }, + 'faceelementpositions' => { 121 => 0x4203 }, + 'faceelementselected' => { 121 => 0x4005 }, + 'faceelementtypes' => { 121 => 0x4201 }, + 'faceid' => { 443 => 'FaceID' }, + 'faceinfounknown' => { 107 => 0x2089 }, + 'facename' => { 370 => 0x123 }, + 'faceorientation' => { 105 => 0x8 }, + 'faceposition' => { 320 => 0x2, 371 => 0x4 }, + 'facepositions' => { 121 => 0x4103 }, + 'facerecognition' => { 370 => 0x120 }, + 'facesdetected' => { 51 => 0x2, 52 => 0x2, 53 => 0x3, 104 => 0x0, 105 => 0x2, 107 => 0x211c, 121 => 0x4100, 196 => 0x3, 282 => 0x1200, 301 => 0x3f, 320 => 0x0, 360 => 0xb5, 371 => 0x0, 388 => 0x0, 391 => 0x3, 401 => 0x30 }, + 'facesrecognized' => { 294 => 0x0 }, + 'facewidth' => { 52 => 0x1 }, + 'faithfuloutputhighlightpoint' => { 103 => 0x38 }, + 'faithfuloutputshadowpoint' => { 103 => 0x39 }, + 'faithfulrawcolortone' => { 103 => 0x31 }, + 'faithfulrawcontrast' => { 103 => 0x33 }, + 'faithfulrawhighlight' => { 103 => 0x79 }, + 'faithfulrawhighlightpoint' => { 103 => 0x36 }, + 'faithfulrawlinear' => { 103 => 0x34 }, + 'faithfulrawsaturation' => { 103 => 0x32 }, + 'faithfulrawshadow' => { 103 => 0x82 }, + 'faithfulrawshadowpoint' => { 103 => 0x37 }, + 'faithfulrawsharpness' => { 103 => 0x35 }, + 'faithfulunsharpmaskfineness' => { 103 => 0xac }, + 'faithfulunsharpmaskstrength' => { 103 => 0xaa }, + 'faithfulunsharpmaskthreshold' => { 103 => 0xae }, + 'far' => { 432 => 'Far' }, + 'fastresetlinetime' => { 131 => 0x1860 }, + 'feedidentifier' => { 458 => 'FeedIdentifier' }, + 'femicroadjustment' => { 78 => 0x111 }, + 'ffid' => { 450 => 'ffid' }, + 'field' => { 461 => 'field' }, + 'fieldcount' => { 283 => 0x103f }, + 'fifoenonepixeldelay' => { 131 => 0x1901 }, + 'filecreatedate' => { 114 => 'FileCreateDate' }, + 'filedatarate' => { 472 => 'fileDataRate' }, + 'fileformat' => { 89 => 0x0, 126 => 0x14, 373 => [0x22,0x26], 394 => 0xb000 }, + 'filegroupid' => { 114 => 'FileGroupID' }, + 'fileindex' => { 6 => 0x143, 8 => 0x2d0, 10 => 0x172, 12 => 0x22c, 13 => 0x133, 14 => 0x13f, 15 => 0x1d3, 16 => 0x19b, 17 => 0x1e4, 18 => 0xd0, 19 => 0x1bb, 20 => 0x28c, 21 => 0x1db, 22 => 0x1d9, 23 => [0x270,0x274], 24 => 0x2aa, 25 => 0x2b3, 27 => 0x1eb, 28 => 0x4ae, 302 => 0x0 }, + 'fileindex2' => { 20 => 0x290 }, + 'filemodifydate' => { 114 => 'FileModifyDate' }, + 'filename' => { 114 => 'FileName' }, + 'filenameasdelivered' => { 288 => 'FileNameAsDelivered' }, + 'filenumber' => { 54 => 0x1, 60 => 0x8, 91 => 0x1817, 108 => 'FileNumber', 197 => 0x4, 359 => 0x10 }, + 'filenumbermemory' => { 171 => 0x1a }, + 'filenumbersequence' => { 261 => '12.2', 266 => '3.1', 267 => '4.1', 268 => '4.1', 270 => '11.1', 271 => '4.3', 276 => '5.2' }, + 'filepermissions' => { 114 => 'FilePermissions' }, + 'filesource' => { 113 => 0xa300, 121 => 0x8000, 452 => 'FileSource' }, + 'fileuserid' => { 114 => 'FileUserID' }, + 'fileversion' => { 126 => 0x16 }, + 'fillflashautoreduction' => { 76 => 0xe, 77 => 0xe, 84 => 0xa }, + 'filllight' => { 448 => 'FillLight' }, + 'fillorder' => { 113 => 0x10a }, + 'filmgraineffect' => { 278 => 0x538 }, + 'filmmode' => { 121 => 0x1401, 298 => 0x412, 301 => 0x42 }, + 'filmtype' => { 222 => 0x2 }, + 'filtereffect' => { 54 => 0xe, 216 => 0x37, 217 => 0x3f, 218 => 0x47 }, + 'filtereffectauto' => { 67 => 0xa0 }, + 'filtereffectfaithful' => { 66 => 0x70, 67 => 0x70 }, + 'filtereffectlandscape' => { 66 => 0x40, 67 => 0x40 }, + 'filtereffectmonochrome' => { 18 => 0xff, 66 => 0x88, 67 => 0x88 }, + 'filtereffectneutral' => { 66 => 0x58, 67 => 0x58 }, + 'filtereffectportrait' => { 66 => 0x28, 67 => 0x28 }, + 'filtereffectstandard' => { 66 => 0x10, 67 => 0x10 }, + 'filtereffectuserdef1' => { 66 => 0xa0, 67 => 0xb8 }, + 'filtereffectuserdef2' => { 66 => 0xb8, 67 => 0xd0 }, + 'filtereffectuserdef3' => { 66 => 0xd0, 67 => 0xe8 }, + 'finderdisplayduringexposure' => { 77 => 0x1 }, + 'finesharpness' => { 336 => 0x70 }, + 'finetuneoptcenterweighted' => { 261 => '7.2', 262 => '9.1', 264 => '9.1', 265 => '9.1', 269 => '8.1', 274 => '9.1', 275 => '9.1', 276 => '9.1' }, + 'finetuneopthighlightweighted' => { 264 => '46.1', 265 => '46.1', 274 => '46.1', 275 => '46.1' }, + 'finetuneoptmatrixmetering' => { 261 => '8.1', 262 => '8.2', 264 => '8.2', 265 => '8.2', 269 => '7.2', 270 => '6.1', 274 => '8.2', 275 => '8.2', 276 => '8.2' }, + 'finetuneoptspotmetering' => { 261 => '8.2', 262 => '9.2', 264 => '9.2', 265 => '9.2', 269 => '8.2', 270 => '6.2', 274 => '9.2', 275 => '9.2', 276 => '9.2' }, + 'finishexposure' => { 131 => 0xdbd }, + 'finishfiletype' => { 131 => 0xdb8 }, + 'finishlook' => { 131 => 0xdbc }, + 'finishnoise' => { 131 => 0xdba }, + 'finishresolution' => { 131 => 0xdb9 }, + 'finishsharpening' => { 131 => 0xdbb }, + 'firmware' => { 283 => 0x405, 373 => [0x17,0x3b,0x57], 444 => 'Firmware' }, + 'firmwaredate' => { 106 => 0x15, 107 => 0x2001, 357 => 0x4, 359 => 0x30 }, + 'firmwareid' => { 178 => 0x0 }, + 'firmwarename' => { 370 => 0xa001 }, + 'firmwarerevision' => { 18 => 0xa4, 60 => 0x1e, 361 => 0x0 }, + 'firmwarerevision2' => { 361 => 0xc }, + 'firmwareversion' => { 6 => 0x10b, 10 => 0x136, 13 => 0xff, 14 => 0x107, 131 => [0x415,0xce5], 145 => 0x57, 147 => 'FirmwareVersion', 299 => 0x320, 301 => 0x2, 303 => 0x3109, 336 => 0x230, 358 => 0x18, 359 => 0x2a, 363 => 0x2 }, + 'firmwareversions' => { 345 => 0x301 }, + 'firstphotodate' => { 435 => 'FirstPhotoDate' }, + 'firstpublicationdate' => { 288 => 'FirstPublicationDate' }, + 'fixtureidentifier' => { 125 => 0x16, 442 => 'FixtureIdentifier' }, + 'flash' => { 108 => 'Flash', 113 => 0x9209, 172 => 0x1f, 173 => 0x15, 359 => 0x5a, 452 => 'Flash' }, + 'flashaction' => { 381 => 0x3e, 382 => 0x3e, 394 => 0x2017, 399 => [0x2a,0x2c,0x30] }, + 'flashaction2' => { 381 => 0x4c, 382 => 0x4c, 399 => 0x77 }, + 'flashactionexternal' => { 399 => [0x78,0x7c] }, + 'flashactivity' => { 33 => 0x1c }, + 'flashbatterylevel' => { 41 => 0x249 }, + 'flashbias' => { 301 => 0x24 }, + 'flashbits' => { 33 => 0x1d }, + 'flashbuttonfunction' => { 78 => 0x70e }, + 'flashchargelevel' => { 283 => 0x1010 }, + 'flashcolorfilter' => { 200 => 0x10, 201 => 0x10 }, + 'flashcommandermode' => { 198 => '9.1', 199 => '9.1', 200 => '9.1', 201 => '9.1' }, + 'flashcompensation' => { 131 => 0x3f3, 198 => 0xa, 199 => 0xa, 200 => 0xa, 201 => 0x27, 202 => 0xa, 444 => 'FlashCompensation' }, + 'flashcontrol' => { 381 => 0x23, 382 => 0x1f, 383 => 0x21 }, + 'flashcontrolbuilt-in' => { 270 => '16.1', 271 => '23.1', 273 => '23.1', 274 => '24.1' }, + 'flashcontrolmode' => { 198 => '9.2', 199 => '9.2', 200 => '9.2', 201 => '9.2', 278 => 0x404 }, + 'flashcurtain' => { 301 => 0x48 }, + 'flashdefault' => { 174 => 0x42 }, + 'flashdevice' => { 283 => 0x1005 }, + 'flashdistance' => { 107 => 0x2034 }, + 'flashenergy' => { 113 => 0xa20b, 452 => 'FlashEnergy' }, + 'flashexposurebracketvalue' => { 214 => 0x18 }, + 'flashexposurecomp' => { 72 => 0xf, 121 => 0x1011, 150 => 'ExposureComp', 171 => 0x23, 176 => 0x104, 177 => 0x49c1, 214 => 0x12, 278 => 0x401, 283 => 0x1023, 336 => 0x4d, 363 => 0x100b, 373 => [0x3a,0x56], 394 => 0x104 }, + 'flashexposurecomp2' => { 240 => 0x4d2 }, + 'flashexposurecomp3' => { 200 => 0x1d }, + 'flashexposurecomp4' => { 200 => 0x27 }, + 'flashexposurecomparea' => { 262 => '38.4', 264 => '38.4', 265 => '38.4', 274 => '38.4', 275 => '38.4' }, + 'flashexposurecompset' => { 174 => 0x10, 309 => 0xe, 381 => 0x14, 382 => 0x12, 383 => 0x23, 399 => 0x1f }, + 'flashexposurecompset2' => { 399 => [0x26,0x2c] }, + 'flashexposureindicator' => { 174 => 0x54 }, + 'flashexposureindicatorlast' => { 174 => 0x56 }, + 'flashexposureindicatornext' => { 174 => 0x55 }, + 'flashexposurelock' => { 54 => 0x19 }, + 'flashfired' => { 133 => 0x5d, 150 => 'Fired', 171 => 0x14, 239 => '590.3', 452 => [\'Flash','FlashFired'] }, + 'flashfiring' => { 78 => 0x306, 79 => 0x6, 80 => 0x7, 83 => 0x7 }, + 'flashfirmwareversion' => { 279 => 0x1002 }, + 'flashfocallength' => { 198 => 0xb, 199 => 0xc, 200 => 0xc, 201 => 0xc, 202 => 0xc }, + 'flashfunction' => { 177 => 0x31, 452 => [\'Flash','FlashFunction'] }, + 'flashgndistance' => { 198 => 0xe, 199 => 0xf, 200 => 0xf, 201 => 0xf, 202 => 0xf }, + 'flashgroupacompensation' => { 198 => 0x11, 199 => 0x12, 200 => 0x13, 201 => 0x28, 202 => 0x28 }, + 'flashgroupacontrolmode' => { 198 => 0xf, 199 => '16.1', 200 => '17.1', 201 => '17.1', 202 => '17.1' }, + 'flashgroupaoutput' => { 198 => 0x11, 199 => 0x12, 200 => 0x13, 201 => 0x28, 202 => 0x28 }, + 'flashgroupbcompensation' => { 198 => 0x12, 199 => 0x13, 200 => 0x14, 201 => 0x29, 202 => 0x29 }, + 'flashgroupbcontrolmode' => { 198 => 0x10, 199 => '17.1', 200 => '18.1', 201 => '18.1', 202 => '18.1' }, + 'flashgroupboutput' => { 198 => 0x12, 199 => 0x13, 200 => 0x14, 201 => 0x29, 202 => 0x29 }, + 'flashgroupccompensation' => { 199 => 0x14, 200 => 0x15, 201 => 0x2a, 202 => 0x2a }, + 'flashgroupccontrolmode' => { 199 => '17.2', 200 => '18.2', 201 => '18.2', 202 => '18.2' }, + 'flashgroupcoutput' => { 199 => 0x14, 200 => 0x15, 201 => 0x2a, 202 => 0x2a }, + 'flashguidenumber' => { 72 => 0xd, 88 => 0x0, 150 => 'GuideNumber' }, + 'flashintensity' => { 106 => [0x19,0x5], 278 => 0x405 }, + 'flashlevel' => { 263 => 0x9, 394 => 0xb048 }, + 'flashmake' => { 150 => 'Make' }, + 'flashmanufacturer' => { 169 => 'FlashManufacturer' }, + 'flashmetering' => { 171 => 0x3f, 174 => 0x1c }, + 'flashmeteringmode' => { 6 => 0x15, 12 => 0x15, 13 => 0x15, 14 => 0x15, 15 => 0x15, 16 => 0x15, 17 => 0x15, 19 => 0x15, 21 => 0x15, 27 => 0x15 }, + 'flashmeteringsegments' => { 336 => 0x20a }, + 'flashmode' => { 106 => 0x4, 131 => 0x3f2, 133 => 0x5c, 150 => 'Mode', 171 => 0x2, 172 => 0x20, 173 => 0x16, 174 => 0xf, 214 => 0x87, 278 => 0x400, 283 => 0x1004, 336 => 0xc, 343 => 0x4, 362 => 0x20, 363 => 0x100a, 372 => 0x225, 381 => 0x13, 382 => 0x7f, 383 => 0x20, 399 => 0x10, 402 => 0x1138, 403 => 0x1138, 404 => 0x1114, 405 => 0x1190, 406 => 0x116c, 407 => 0x1024, 408 => 0x21c, 409 => 0x21c, 410 => 0x211, 452 => [\'Flash','FlashMode'] }, + 'flashmodel' => { 150 => 'Model', 169 => 'FlashModel', 279 => 0x1001 }, + 'flashoptions' => { 317 => 0x2 }, + 'flashoptions2' => { 317 => 0x10 }, + 'flashoutput' => { 41 => 0x248, 72 => 0x21, 198 => 0xa, 199 => 0xa, 200 => 0xa, 201 => 0x27 }, + 'flashpixversion' => { 113 => 0xa000, 452 => 'FlashpixVersion' }, + 'flashredeyemode' => { 452 => [\'Flash','FlashRedEyeMode'] }, + 'flashremotecontrol' => { 278 => 0x403 }, + 'flashreturn' => { 452 => [\'Flash','FlashReturn'] }, + 'flashserialnumber' => { 150 => 'SerialNumber', 279 => 0x1003 }, + 'flashsetting' => { 214 => 0x8 }, + 'flashshutterspeed' => { 261 => '20.2', 262 => '23.2', 264 => '23.2', 265 => '23.2', 270 => '15.2', 271 => '22.2', 272 => '7.2', 273 => '22.2', 274 => '23.2', 275 => '23.2', 276 => '23.1' }, + 'flashsource' => { 198 => 0x4, 199 => 0x4, 200 => 0x4, 201 => 0x4, 202 => 0x4 }, + 'flashstatus' => { 324 => 0x0, 399 => [0x82,0x86], 412 => 0x31, 413 => 0x39 }, + 'flashstatusbuilt-in' => { 383 => [0x87,0x287] }, + 'flashstatusexternal' => { 383 => [0x88,0x288] }, + 'flashsyncspeed' => { 261 => '20.1', 262 => '23.1', 264 => '23.1', 265 => '23.1', 270 => '15.1', 271 => '22.1', 273 => '22.1', 274 => '23.1', 275 => '23.1' }, + 'flashsyncspeedav' => { 76 => 0x3, 78 => 0x10f, 79 => 0x2, 80 => 0x3, 81 => 0x2, 82 => 0x2, 83 => 0x3, 84 => 0x6 }, + 'flashthreshold' => { 88 => 0x1 }, + 'flashtype' => { 150 => 'Type', 174 => 0x59, 214 => 0x9, 279 => 0x1000 }, + 'flashwarning' => { 271 => '30.1', 272 => '7.1', 276 => '31.1', 301 => 0x62 }, + 'flexiblespotposition' => { 394 => 0x201d }, + 'flickerreduce' => { 372 => 0x218 }, + 'flickerreduction' => { 121 => 0x1446, 233 => 0xe84 }, + 'flickerreductionindicator' => { 233 => 0x5e2 }, + 'flightpitchdegree' => { 110 => 'FlightPitchDegree' }, + 'flightrolldegree' => { 110 => 'FlightRollDegree' }, + 'flightxspeed' => { 110 => 'FlightXSpeed' }, + 'flightyawdegree' => { 110 => 'FlightYawDegree' }, + 'flightyspeed' => { 110 => 'FlightYSpeed' }, + 'flightzspeed' => { 110 => 'FlightZSpeed' }, + 'fliphorizontal' => { 254 => 0x76a43206 }, + 'fnumber' => { 6 => 0x3, 8 => 0x3, 10 => 0x3, 12 => 0x3, 13 => 0x3, 14 => 0x3, 15 => 0x3, 16 => 0x3, 17 => 0x3, 18 => 0x3, 19 => 0x3, 20 => 0x3, 21 => 0x3, 22 => 0x3, 23 => 0x3, 24 => 0x3, 25 => 0x3, 26 => 0x3, 27 => 0x3, 28 => 0x3, 29 => 0x5, 30 => 0x6, 72 => 0x15, 113 => 0x829d, 130 => 0xfd04, 133 => 0x1e, 135 => 0xfa23, 137 => 0xf103, 140 => 0x13, 142 => 0x3c, 145 => 0xc, 154 => 'FNumber', 171 => 0xa, 172 => 0x36, 173 => 0x47, 174 => 0x9, 177 => 0x49c7, 212 => 0x38, 336 => 0x13, 370 => 0xa019, 373 => [0x31,0x49], 381 => 0x1, 382 => 0x1, 399 => [0x20,0x22,0x26], 452 => 'FNumber' }, + 'focaldistance' => { 433 => 'FocalDistance' }, + 'focallength' => { 6 => 0x1d, 7 => 0xa, 8 => 0x23, 9 => 0x9, 10 => 0x1d, 11 => 0x9, 12 => 0x1e, 13 => 0x1d, 14 => 0x1d, 15 => 0x1e, 16 => 0x1e, 17 => 0x1e, 18 => 0x28, 19 => 0x1e, 20 => 0x23, 21 => 0x1e, 22 => 0x1e, 23 => 0x23, 24 => 0x23, 25 => 0x23, 26 => 0x23, 27 => 0x1e, 28 => 0x23, 56 => 0x1, 107 => 0x1d, 113 => 0x920a, 140 => 0x1d, 154 => 'FocalLength', 171 => 0x12, 207 => 0xa, 208 => 0xb, 212 => [0xc,0x3c], 295 => 0x1, 336 => 0x1d, 345 => 0x403, 363 => 0x1500, 380 => 0xe, 406 => 0x1278, 407 => 0x1134, 408 => 0x32c, 409 => 0x32c, 410 => 0x30a, 452 => 'FocalLength' }, + 'focallength2' => { 399 => [0x23,0x25,0x29] }, + 'focallengthin35mmformat' => { 113 => 0xa405, 370 => 0xa01a, 452 => 'FocalLengthIn35mmFilm' }, + 'focallengthtelezoom' => { 380 => 0x10 }, + 'focalplaneafpointarea' => { 411 => 0x2 }, + 'focalplaneafpointlocation1' => { 411 => 0x6 }, + 'focalplaneafpointlocation10' => { 411 => 0x2a }, + 'focalplaneafpointlocation11' => { 411 => 0x2e }, + 'focalplaneafpointlocation12' => { 411 => 0x32 }, + 'focalplaneafpointlocation13' => { 411 => 0x36 }, + 'focalplaneafpointlocation14' => { 411 => 0x3a }, + 'focalplaneafpointlocation15' => { 411 => 0x3e }, + 'focalplaneafpointlocation2' => { 411 => 0xa }, + 'focalplaneafpointlocation3' => { 411 => 0xe }, + 'focalplaneafpointlocation4' => { 411 => 0x12 }, + 'focalplaneafpointlocation5' => { 411 => 0x16 }, + 'focalplaneafpointlocation6' => { 411 => 0x1a }, + 'focalplaneafpointlocation7' => { 411 => 0x1e }, + 'focalplaneafpointlocation8' => { 411 => 0x22 }, + 'focalplaneafpointlocation9' => { 411 => 0x26 }, + 'focalplaneafpointsused' => { 411 => 0x1 }, + 'focalplanediagonal' => { 279 => 0x103, 283 => 0x205 }, + 'focalplaneresolutionunit' => { 113 => 0xa210, 452 => 'FocalPlaneResolutionUnit' }, + 'focalplanexresolution' => { 113 => 0xa20e, 452 => 'FocalPlaneXResolution' }, + 'focalplanexsize' => { 56 => 0x2 }, + 'focalplanexunknown' => { 56 => 0x2 }, + 'focalplaneyresolution' => { 113 => 0xa20f, 452 => 'FocalPlaneYResolution' }, + 'focalplaneysize' => { 56 => 0x3 }, + 'focalplaneyunknown' => { 56 => 0x3 }, + 'focalpointx' => { 433 => 'FocalPointX' }, + 'focalpointy' => { 433 => 'FocalPointY' }, + 'focaltype' => { 9 => 0x2d, 56 => 0x0 }, + 'focalunits' => { 33 => 0x19 }, + 'focus' => { 244 => 0x8 }, + 'focusarea' => { 171 => 0x31 }, + 'focusareaselection' => { 272 => '15.2' }, + 'focuscontinuous' => { 33 => 0x20 }, + 'focusdisplayaiservoandmf' => { 78 => 0x515 }, + 'focusdistance' => { 154 => 'FocusDistance', 171 => 0x13, 177 => 0x49bb, 207 => 0x9, 208 => 0xa, 212 => 0xb, 281 => 0x305, 295 => 0x0, 299 => 0x304, 300 => 0x304 }, + 'focusdistancelower' => { 6 => 0x45, 8 => 0x8e, 10 => 0x45, 12 => 0x56, 13 => 0x45, 14 => 0x45, 15 => 0x52, 16 => 0x52, 17 => 0x56, 19 => 0x52, 20 => 0x8e, 21 => 0x59, 22 => 0x57, 23 => 0x8e, 24 => 0x94, 25 => 0x95, 26 => 0xa7, 27 => 0x56, 28 => 0xa7, 54 => 0x15, 72 => 0x14 }, + 'focusdistanceupper' => { 6 => 0x43, 8 => 0x8c, 10 => 0x43, 12 => 0x54, 13 => 0x43, 14 => 0x43, 15 => 0x50, 16 => 0x50, 17 => 0x54, 19 => 0x50, 20 => 0x8c, 21 => 0x57, 22 => 0x55, 23 => 0x8c, 24 => 0x92, 25 => 0x93, 26 => 0xa5, 27 => 0x54, 28 => 0xa5, 54 => 0x14, 72 => 0x13 }, + 'focusholdbutton' => { 174 => 0x44 }, + 'focusinfoversion' => { 281 => 0x0 }, + 'focusingscreen' => { 77 => 0x0, 78 => 0x80b, 83 => 0x0 }, + 'focuslocation' => { 394 => 0x2027 }, + 'focuslocked' => { 170 => 0x14 }, + 'focusmode' => { 33 => 0x7, 106 => 0x3, 107 => [0x3003,0xd], 121 => 0x1021, 131 => 0x3f5, 133 => 0x38, 147 => 'FocusMode', 171 => 0x30, 173 => 0xe, 174 => 0xc, 214 => 0x7, 278 => 0x301, 283 => 0x100b, 301 => 0x7, 336 => 0xd, 343 => 0x3, 363 => 0x1006, 374 => [0xb,0x5], 380 => [0x15,0x1d], 381 => 0x4d, 382 => 0x4d, 394 => [0xb042,0xb04e,0x201b], 399 => 0x13, 417 => 0x16 }, + 'focusmode2' => { 120 => '0.1', 317 => '3.1', 399 => [0x2c,0x2e,0x32] }, + 'focusmodesetting' => { 263 => '10.1', 378 => 0x14, 379 => 0x15, 381 => 0x10, 382 => 0xf, 383 => 0x6 }, + 'focusmodeswitch' => { 174 => 0x58, 381 => 0x2e }, + 'focuspixel' => { 121 => 0x1023 }, + 'focuspointwrap' => { 261 => '2.2', 262 => '2.2', 264 => '2.1', 265 => '2.1', 269 => '1.1', 270 => '2.2', 271 => '1.1', 274 => '2.2', 275 => '2.1', 276 => '2.5' }, + 'focusposition' => { 207 => 0x8, 208 => 0x8, 212 => 0x9, 336 => 0x10, 392 => 0x9bb }, + 'focusposition2' => { 399 => [0x29,0x2b,0x2f], 417 => 0x2d, 420 => 0x20 }, + 'focusprocess' => { 278 => 0x302 }, + 'focusrange' => { 33 => 0x12, 283 => 0x100a }, + 'focusrangeindex' => { 327 => '3.1' }, + 'focusringrotation' => { 78 => 0x713 }, + 'focussetting' => { 373 => 0x6 }, + 'focusstatus' => { 380 => 0x19, 381 => 0x53, 382 => 0x53 }, + 'focusstepcount' => { 281 => 0x301, 283 => 0x100e }, + 'focusstepinfinity' => { 281 => 0x303, 283 => 0x103b }, + 'focusstepnear' => { 281 => 0x304, 283 => 0x103c }, + 'focustrackinglockon' => { 261 => ['1.5','4.1'], 262 => '1.4', 269 => '0.4', 270 => '3.1', 271 => '0.4', 274 => '1.4' }, + 'focuswarning' => { 121 => 0x1301 }, + 'foldername' => { 171 => 0x27 }, + 'foldernumber' => { 381 => 0x9a, 383 => [0x402,0x114,0x316] }, + 'fontcomposite' => { 477 => [\'Fonts','FontsComposite'] }, + 'fontface' => { 477 => [\'Fonts','FontsFontFace'] }, + 'fontfamily' => { 477 => [\'Fonts','FontsFontFamily'] }, + 'fontfilename' => { 477 => [\'Fonts','FontsFontFileName'] }, + 'fontname' => { 477 => [\'Fonts','FontsFontName'] }, + 'fonts' => { 477 => 'Fonts' }, + 'fonttype' => { 477 => [\'Fonts','FontsFontType'] }, + 'fontversion' => { 477 => [\'Fonts','FontsVersionString'] }, + 'for' => { 352 => 'For' }, + 'forcewrite' => { 114 => 'ForceWrite' }, + 'format' => { 432 => 'Format', 449 => 'format', 470 => 'Format' }, + 'forwardlock' => { 467 => 'forwardlock' }, + 'forwardmatrix1' => { 113 => 0xc714 }, + 'forwardmatrix2' => { 113 => 0xc715 }, + 'fossilspecimen' => { 112 => 'FossilSpecimen' }, + 'fossilspecimenmaterialsampleid' => { 112 => [\'FossilSpecimen','FossilSpecimenMaterialSampleID'] }, + 'framecount' => { 63 => [0x2,0x4] }, + 'frameheight' => { 121 => 0x3822 }, + 'framenum' => { 347 => 0xd7 }, + 'framenumber' => { 121 => 0x8003, 177 => 0x3c, 336 => 0x29 }, + 'framerate' => { 63 => [0x1,0x6], 113 => 0xc764, 121 => 0x3820 }, + 'framewidth' => { 121 => 0x3821 }, + 'framing' => { 461 => 'framing' }, + 'freebytes' => { 91 => 0x1 }, + 'freememorycardimages' => { 172 => [0x37,0x54], 173 => [0x2d,0x4a], 174 => 0x32 }, + 'fujiflashmode' => { 121 => 0x1010 }, + 'fullimagesize' => { 394 => 0xb02b }, + 'fullpanoheightpixels' => { 435 => 'FullPanoHeightPixels', 436 => 'FullPanoHeightPixels' }, + 'fullpanowidthpixels' => { 435 => 'FullPanoWidthPixels', 436 => 'FullPanoWidthPixels' }, + 'fullpresssnap' => { 363 => 0x100d }, + 'fullsizeimage' => { 153 => 'data' }, + 'fullsizeimagename' => { 153 => '1Name' }, + 'fullsizeimagetype' => { 153 => '0Type' }, + 'func1button' => { 264 => '14.1', 265 => '14.1', 275 => '14.1' }, + 'func1buttonplusdials' => { 264 => '42.1', 265 => '42.1', 275 => '42.1' }, + 'func2button' => { 264 => '80.1', 265 => '80.1', 275 => '80.1' }, + 'func2buttonplusdials' => { 264 => '81.1' }, + 'func3button' => { 264 => '83.1' }, + 'funcbutton' => { 261 => ['14.1','15.1'], 262 => '14.1', 270 => '28.1', 271 => '13.1', 274 => '14.1', 276 => '14.1' }, + 'funcbuttonplusdials' => { 261 => ['14.2','15.2'], 262 => '14.2', 270 => '31.1', 274 => '42.1' }, + 'functionbutton' => { 268 => '13.1', 272 => '5.2' }, + 'gainbase' => { 282 => 0x610 }, + 'gaincontrol' => { 113 => 0xa407, 452 => 'GainControl' }, + 'gamma' => { 113 => 0xa500, 131 => 0x8fe, 306 => 0x11c, 453 => 'Gamma' }, + 'gammablackpoint' => { 99 => 0xc }, + 'gammacolortone' => { 99 => 0x3 }, + 'gammacompensatedvalue' => { 127 => 0x91 }, + 'gammacontrast' => { 99 => 0x2 }, + 'gammacurveoutputrange' => { 99 => 0xf }, + 'gammahighlight' => { 99 => 0xa }, + 'gammalinear' => { 97 => 0x20200 }, + 'gammamidpoint' => { 99 => 0xe }, + 'gammasaturation' => { 99 => 0x4 }, + 'gammashadow' => { 99 => 0x9 }, + 'gammasharpnessstrength' => { 99 => 0x8 }, + 'gammaunsharpmaskfineness' => { 99 => 0x6 }, + 'gammaunsharpmaskstrength' => { 99 => 0x5 }, + 'gammaunsharpmaskthreshold' => { 99 => 0x7 }, + 'gammawhitepoint' => { 99 => 0xd }, + 'geimagesize' => { 121 => 0x1304 }, + 'gemake' => { 123 => 0x300 }, + 'gemodel' => { 123 => 0x207 }, + 'genre' => { 458 => 'Genre', 462 => 'genre', 472 => 'genre' }, + 'genrecvid' => { 458 => [\'Genre','GenreCvId'] }, + 'genrecvtermid' => { 458 => [\'Genre','GenreCvTermId'] }, + 'genrecvtermname' => { 458 => [\'Genre','GenreCvTermName'] }, + 'genrecvtermrefinedabout' => { 458 => [\'Genre','GenreCvTermRefinedAbout'] }, + 'geography' => { 463 => 'geography' }, + 'geologicalcontext' => { 112 => 'GeologicalContext' }, + 'geologicalcontextbed' => { 112 => [\'GeologicalContext','GeologicalContextBed'] }, + 'geologicalcontextformation' => { 112 => [\'GeologicalContext','GeologicalContextFormation'] }, + 'geologicalcontextgroup' => { 112 => [\'GeologicalContext','GeologicalContextGroup'] }, + 'geologicalcontextid' => { 112 => [\'GeologicalContext','GeologicalContextGeologicalContextID'] }, + 'geologicalcontextmember' => { 112 => [\'GeologicalContext','GeologicalContextMember'] }, + 'geosync' => { 114 => 'Geosync' }, + 'geotag' => { 114 => 'Geotag' }, + 'geotiffasciiparams' => { 113 => 0x87b1 }, + 'geotiffdirectory' => { 113 => 0x87af }, + 'geotiffdoubleparams' => { 113 => 0x87b0 }, + 'geotime' => { 114 => 'Geotime' }, + 'giftftppriority' => { 437 => 'GIFTFtpPriority' }, + 'gimbalpitchdegree' => { 110 => 'GimbalPitchDegree' }, + 'gimbalreverse' => { 110 => 'GimbalReverse' }, + 'gimbalrolldegree' => { 110 => 'GimbalRollDegree' }, + 'gimbalyawdegree' => { 110 => 'GimbalYawDegree' }, + 'globalaltitude' => { 350 => 0x419 }, + 'globalangle' => { 350 => 0x40d }, + 'good' => { 472 => 'good' }, + 'googleplusuploadcode' => { 113 => 0x9009 }, + 'gpsaltitude' => { 124 => 0x6, 151 => 'Altitude', 452 => 'GPSAltitude' }, + 'gpsaltituderef' => { 124 => 0x5, 452 => 'GPSAltitudeRef' }, + 'gpsareainformation' => { 124 => 0x1c, 452 => 'GPSAreaInformation' }, + 'gpsdatestamp' => { 124 => 0x1d }, + 'gpsdatetime' => { 151 => 'DateTime', 452 => 'GPSTimeStamp' }, + 'gpsdestbearing' => { 124 => 0x18, 151 => 'Bearing', 452 => 'GPSDestBearing' }, + 'gpsdestbearingref' => { 124 => 0x17, 452 => 'GPSDestBearingRef' }, + 'gpsdestdistance' => { 124 => 0x1a, 151 => 'Distance', 452 => 'GPSDestDistance' }, + 'gpsdestdistanceref' => { 124 => 0x19, 452 => 'GPSDestDistanceRef' }, + 'gpsdestlatitude' => { 124 => 0x14, 452 => 'GPSDestLatitude' }, + 'gpsdestlatituderef' => { 124 => 0x13 }, + 'gpsdestlongitude' => { 124 => 0x16, 452 => 'GPSDestLongitude' }, + 'gpsdestlongituderef' => { 124 => 0x15 }, + 'gpsdifferential' => { 124 => 0x1e, 151 => 'Differential', 452 => 'GPSDifferential' }, + 'gpsdop' => { 124 => 0xb, 452 => 'GPSDOP' }, + 'gpshpositioningerror' => { 124 => 0x1f, 452 => 'GPSHPositioningError' }, + 'gpsimgdirection' => { 124 => 0x11, 452 => 'GPSImgDirection' }, + 'gpsimgdirectionref' => { 124 => 0x10, 452 => 'GPSImgDirectionRef' }, + 'gpslatitude' => { 110 => 'GpsLatitude', 124 => 0x2, 151 => 'Latitude', 452 => 'GPSLatitude' }, + 'gpslatituderef' => { 124 => 0x1 }, + 'gpslongitude' => { 110 => 'GpsLongitude', 124 => 0x4, 151 => 'Longitude', 452 => 'GPSLongitude' }, + 'gpslongituderef' => { 124 => 0x3 }, + 'gpslongtitude' => { 110 => 'GpsLongtitude' }, + 'gpsmapdatum' => { 124 => 0x12, 151 => 'Datum', 452 => 'GPSMapDatum' }, + 'gpsmeasuremode' => { 124 => 0xa, 151 => 'MeasureMode', 452 => 'GPSMeasureMode' }, + 'gpsprocessingmethod' => { 124 => 0x1b, 452 => 'GPSProcessingMethod' }, + 'gpssatellites' => { 124 => 0x8, 151 => 'Satellites', 452 => 'GPSSatellites' }, + 'gpsspeed' => { 124 => 0xd, 151 => 'Speed', 452 => 'GPSSpeed' }, + 'gpsspeedref' => { 124 => 0xc, 452 => 'GPSSpeedRef' }, + 'gpsstatus' => { 124 => 0x9, 452 => 'GPSStatus' }, + 'gpsstring' => { 131 => 0x402 }, + 'gpstimestamp' => { 124 => 0x7 }, + 'gpstrack' => { 124 => 0xf, 151 => 'Heading', 452 => 'GPSTrack' }, + 'gpstrackref' => { 124 => 0xe, 452 => 'GPSTrackRef' }, + 'gpsversionid' => { 124 => 0x0, 452 => 'GPSVersionID' }, + 'gradation' => { 278 => 0x50f }, + 'gradientbasedcorractive' => { 448 => [\'GradientBasedCorrections','GradientBasedCorrectionsCorrectionActive'] }, + 'gradientbasedcorramount' => { 448 => [\'GradientBasedCorrections','GradientBasedCorrectionsCorrectionAmount'] }, + 'gradientbasedcorrbrightness' => { 448 => [\'GradientBasedCorrections','GradientBasedCorrectionsLocalBrightness'] }, + 'gradientbasedcorrclarity' => { 448 => [\'GradientBasedCorrections','GradientBasedCorrectionsLocalClarity'] }, + 'gradientbasedcorrclarity2012' => { 448 => [\'GradientBasedCorrections','GradientBasedCorrectionsLocalClarity2012'] }, + 'gradientbasedcorrcontrast' => { 448 => [\'GradientBasedCorrections','GradientBasedCorrectionsLocalContrast'] }, + 'gradientbasedcorrcontrast2012' => { 448 => [\'GradientBasedCorrections','GradientBasedCorrectionsLocalContrast2012'] }, + 'gradientbasedcorrdefringe' => { 448 => [\'GradientBasedCorrections','GradientBasedCorrectionsLocalDefringe'] }, + 'gradientbasedcorrections' => { 448 => 'GradientBasedCorrections' }, + 'gradientbasedcorrexposure' => { 448 => [\'GradientBasedCorrections','GradientBasedCorrectionsLocalExposure'] }, + 'gradientbasedcorrexposure2012' => { 448 => [\'GradientBasedCorrections','GradientBasedCorrectionsLocalExposure2012'] }, + 'gradientbasedcorrhighlights2012' => { 448 => [\'GradientBasedCorrections','GradientBasedCorrectionsLocalHighlights2012'] }, + 'gradientbasedcorrhue' => { 448 => [\'GradientBasedCorrections','GradientBasedCorrectionsLocalToningHue'] }, + 'gradientbasedcorrluminancenoise' => { 448 => [\'GradientBasedCorrections','GradientBasedCorrectionsLocalLuminanceNoise'] }, + 'gradientbasedcorrmaskalpha' => { 448 => [\'GradientBasedCorrections','GradientBasedCorrectionsCorrectionMasksAlpha'] }, + 'gradientbasedcorrmaskangle' => { 448 => [\'GradientBasedCorrections','GradientBasedCorrectionsCorrectionMasksAngle'] }, + 'gradientbasedcorrmaskbottom' => { 448 => [\'GradientBasedCorrections','GradientBasedCorrectionsCorrectionMasksBottom'] }, + 'gradientbasedcorrmaskcentervalue' => { 448 => [\'GradientBasedCorrections','GradientBasedCorrectionsCorrectionMasksCenterValue'] }, + 'gradientbasedcorrmaskcenterweight' => { 448 => [\'GradientBasedCorrections','GradientBasedCorrectionsCorrectionMasksCenterWeight'] }, + 'gradientbasedcorrmaskdabs' => { 448 => [\'GradientBasedCorrections','GradientBasedCorrectionsCorrectionMasksDabs'] }, + 'gradientbasedcorrmaskfeather' => { 448 => [\'GradientBasedCorrections','GradientBasedCorrectionsCorrectionMasksFeather'] }, + 'gradientbasedcorrmaskflipped' => { 448 => [\'GradientBasedCorrections','GradientBasedCorrectionsCorrectionMasksFlipped'] }, + 'gradientbasedcorrmaskflow' => { 448 => [\'GradientBasedCorrections','GradientBasedCorrectionsCorrectionMasksFlow'] }, + 'gradientbasedcorrmaskfullx' => { 448 => [\'GradientBasedCorrections','GradientBasedCorrectionsCorrectionMasksFullX'] }, + 'gradientbasedcorrmaskfully' => { 448 => [\'GradientBasedCorrections','GradientBasedCorrectionsCorrectionMasksFullY'] }, + 'gradientbasedcorrmaskleft' => { 448 => [\'GradientBasedCorrections','GradientBasedCorrectionsCorrectionMasksLeft'] }, + 'gradientbasedcorrmaskmidpoint' => { 448 => [\'GradientBasedCorrections','GradientBasedCorrectionsCorrectionMasksMidpoint'] }, + 'gradientbasedcorrmaskperimetervalue' => { 448 => [\'GradientBasedCorrections','GradientBasedCorrectionsCorrectionMasksPerimeterValue'] }, + 'gradientbasedcorrmaskradius' => { 448 => [\'GradientBasedCorrections','GradientBasedCorrectionsCorrectionMasksRadius'] }, + 'gradientbasedcorrmaskright' => { 448 => [\'GradientBasedCorrections','GradientBasedCorrectionsCorrectionMasksRight'] }, + 'gradientbasedcorrmaskroundness' => { 448 => [\'GradientBasedCorrections','GradientBasedCorrectionsCorrectionMasksRoundness'] }, + 'gradientbasedcorrmasks' => { 448 => [\'GradientBasedCorrections','GradientBasedCorrectionsCorrectionMasks'] }, + 'gradientbasedcorrmasksizex' => { 448 => [\'GradientBasedCorrections','GradientBasedCorrectionsCorrectionMasksSizeX'] }, + 'gradientbasedcorrmasksizey' => { 448 => [\'GradientBasedCorrections','GradientBasedCorrectionsCorrectionMasksSizeY'] }, + 'gradientbasedcorrmasktop' => { 448 => [\'GradientBasedCorrections','GradientBasedCorrectionsCorrectionMasksTop'] }, + 'gradientbasedcorrmaskvalue' => { 448 => [\'GradientBasedCorrections','GradientBasedCorrectionsCorrectionMasksMaskValue'] }, + 'gradientbasedcorrmaskversion' => { 448 => [\'GradientBasedCorrections','GradientBasedCorrectionsCorrectionMasksVersion'] }, + 'gradientbasedcorrmaskwhat' => { 448 => [\'GradientBasedCorrections','GradientBasedCorrectionsCorrectionMasksWhat'] }, + 'gradientbasedcorrmaskx' => { 448 => [\'GradientBasedCorrections','GradientBasedCorrectionsCorrectionMasksX'] }, + 'gradientbasedcorrmasky' => { 448 => [\'GradientBasedCorrections','GradientBasedCorrectionsCorrectionMasksY'] }, + 'gradientbasedcorrmaskzerox' => { 448 => [\'GradientBasedCorrections','GradientBasedCorrectionsCorrectionMasksZeroX'] }, + 'gradientbasedcorrmaskzeroy' => { 448 => [\'GradientBasedCorrections','GradientBasedCorrectionsCorrectionMasksZeroY'] }, + 'gradientbasedcorrmoire' => { 448 => [\'GradientBasedCorrections','GradientBasedCorrectionsLocalMoire'] }, + 'gradientbasedcorrsaturation' => { 448 => [\'GradientBasedCorrections','GradientBasedCorrectionsLocalSaturation','GradientBasedCorrectionsLocalToningSaturation'] }, + 'gradientbasedcorrshadows2012' => { 448 => [\'GradientBasedCorrections','GradientBasedCorrectionsLocalShadows2012'] }, + 'gradientbasedcorrsharpness' => { 448 => [\'GradientBasedCorrections','GradientBasedCorrectionsLocalSharpness'] }, + 'gradientbasedcorrtemperature' => { 448 => [\'GradientBasedCorrections','GradientBasedCorrectionsLocalTemperature'] }, + 'gradientbasedcorrtint' => { 448 => [\'GradientBasedCorrections','GradientBasedCorrectionsLocalTint'] }, + 'gradientbasedcorrwhat' => { 448 => [\'GradientBasedCorrections','GradientBasedCorrectionsWhat'] }, + 'grainamount' => { 448 => 'GrainAmount' }, + 'graineffect' => { 121 => 0x1047 }, + 'grainfrequency' => { 448 => 'GrainFrequency' }, + 'grainsize' => { 448 => 'GrainSize' }, + 'graymixeraqua' => { 448 => 'GrayMixerAqua' }, + 'graymixerblue' => { 448 => 'GrayMixerBlue' }, + 'graymixergreen' => { 448 => 'GrayMixerGreen' }, + 'graymixermagenta' => { 448 => 'GrayMixerMagenta' }, + 'graymixerorange' => { 448 => 'GrayMixerOrange' }, + 'graymixerpurple' => { 448 => 'GrayMixerPurple' }, + 'graymixerred' => { 448 => 'GrayMixerRed' }, + 'graymixeryellow' => { 448 => 'GrayMixerYellow' }, + 'graypoint' => { 427 => 0x8021 }, + 'grayresponseunit' => { 113 => 0x122 }, + 'greencurvelimits' => { 102 => 0x1c4 }, + 'greencurvepoints' => { 101 => 0x53, 102 => 0x19a }, + 'greenhsl' => { 97 => 0x20913 }, + 'greenhue' => { 448 => 'GreenHue' }, + 'greensaturation' => { 448 => 'GreenSaturation' }, + 'griddisplay' => { 261 => '13.3', 262 => '4.3', 264 => '4.2', 265 => '4.2', 266 => '2.2', 270 => '10.5', 271 => '3.4', 272 => '6.1', 274 => '4.4', 275 => '4.2', 276 => '4.2' }, + 'gripbatteryadload' => { 315 => 0x5 }, + 'gripbatteryadnoload' => { 315 => 0x4 }, + 'gripbatterystate' => { 315 => '1.2' }, + 'groupareaafillumination' => { 262 => '46.4', 265 => '47.4', 274 => '47.4' }, + 'h2resetblackpixels' => { 131 => 0x18a6 }, + 'h3resetblackcolumns' => { 131 => 0x18ce }, + 'h3resetblackpixels' => { 131 => 0x18b0 }, + 'halftonehints' => { 113 => 0x141 }, + 'hardlink' => { 114 => 'HardLink' }, + 'hasalternative' => { 462 => 'hasAlternative' }, + 'hascorrection' => { 462 => 'hasCorrection' }, + 'hascorrectiona-lang' => { 462 => [\'hasCorrection','hasCorrectionA-lang'] }, + 'hascorrectiona-platform' => { 462 => [\'hasCorrection','hasCorrectionA-platform'] }, + 'hascorrectiontext' => { 462 => [\'hasCorrection','hasCorrectionText'] }, + 'hascrop' => { 448 => 'HasCrop' }, + 'hasextendedxmp' => { 474 => 'HasExtendedXMP' }, + 'hassettings' => { 448 => 'HasSettings' }, + 'hastranslation' => { 462 => 'hasTranslation' }, + 'hasvisibleoverprint' => { 477 => 'HasVisibleOverprint' }, + 'hasvisibletransparency' => { 477 => 'HasVisibleTransparency' }, + 'hdr' => { 57 => 0x1, 204 => 0x4, 301 => 0x9e, 336 => 0x85, 394 => 0x200a }, + 'hdreffect' => { 57 => 0x2 }, + 'hdrimagetype' => { 1 => 0xa }, + 'hdrinfoversion' => { 204 => 0x0 }, + 'hdrlevel' => { 204 => 0x5, 383 => 0x2e, 399 => 0x17 }, + 'hdrlevel2' => { 204 => 0x7 }, + 'hdrsetting' => { 383 => 0x2d, 399 => 0x16, 402 => 0x1148, 403 => 0x1148, 404 => 0x1124, 405 => 0x11a0, 406 => 0x117c, 407 => 0x1034, 408 => 0x22c, 409 => 0x22c, 410 => 0x21f }, + 'hdrshot' => { 301 => 0x76 }, + 'hdrsmoothing' => { 204 => 0x6 }, + 'headline' => { 125 => 0x69, 458 => 'Headline', 460 => 'Headline' }, + 'hierarchicalkeywords' => { 162 => [\'Keywords','KeywordsHierarchy'] }, + 'hierarchicalkeywords1' => { 162 => [\'Keywords','KeywordsHierarchyKeyword'] }, + 'hierarchicalkeywords1applied' => { 162 => [\'Keywords','KeywordsHierarchyApplied'] }, + 'hierarchicalkeywords1children' => { 162 => [\'Keywords','KeywordsHierarchyChildren'] }, + 'hierarchicalkeywords2' => { 162 => [\'Keywords','KeywordsHierarchyChildrenKeyword'] }, + 'hierarchicalkeywords2applied' => { 162 => [\'Keywords','KeywordsHierarchyChildrenApplied'] }, + 'hierarchicalkeywords2children' => { 162 => [\'Keywords','KeywordsHierarchyChildrenChildren'] }, + 'hierarchicalkeywords3' => { 162 => [\'Keywords','KeywordsHierarchyChildrenChildrenKeyword'] }, + 'hierarchicalkeywords3applied' => { 162 => [\'Keywords','KeywordsHierarchyChildrenChildrenApplied'] }, + 'hierarchicalkeywords3children' => { 162 => [\'Keywords','KeywordsHierarchyChildrenChildrenChildren'] }, + 'hierarchicalkeywords4' => { 162 => [\'Keywords','KeywordsHierarchyChildrenChildrenChildrenKeyword'] }, + 'hierarchicalkeywords4applied' => { 162 => [\'Keywords','KeywordsHierarchyChildrenChildrenChildrenApplied'] }, + 'hierarchicalkeywords4children' => { 162 => [\'Keywords','KeywordsHierarchyChildrenChildrenChildrenChildren'] }, + 'hierarchicalkeywords5' => { 162 => [\'Keywords','KeywordsHierarchyChildrenChildrenChildrenChildrenKeyword'] }, + 'hierarchicalkeywords5applied' => { 162 => [\'Keywords','KeywordsHierarchyChildrenChildrenChildrenChildrenApplied'] }, + 'hierarchicalkeywords5children' => { 162 => [\'Keywords','KeywordsHierarchyChildrenChildrenChildrenChildrenChildren'] }, + 'hierarchicalkeywords6' => { 162 => [\'Keywords','KeywordsHierarchyChildrenChildrenChildrenChildrenChildrenKeyword'] }, + 'hierarchicalkeywords6applied' => { 162 => [\'Keywords','KeywordsHierarchyChildrenChildrenChildrenChildrenChildrenApplied'] }, + 'hierarchicalsubject' => { 439 => 'hierarchicalSubject' }, + 'highestbiostratigraphiczone' => { 112 => [\'GeologicalContext','GeologicalContextHighestBiostratigraphicZone'] }, + 'highisomultiplierblue' => { 306 => 0x1a }, + 'highisomultipliergreen' => { 306 => 0x19 }, + 'highisomultiplierred' => { 306 => 0x18 }, + 'highisonoisereduction' => { 15 => 0xbc, 16 => 0xbd, 19 => 0xbd, 27 => 0xc9, 59 => 0x5, 78 => 0x202, 214 => 0xb1, 336 => 0x71, 381 => 0x2c, 382 => 0x26, 383 => 0x26, 394 => 0x2009, 399 => 0x12, 423 => 0x42 }, + 'highisonoisereduction2' => { 394 => 0xb050 }, + 'highlight' => { 373 => 0xf }, + 'highlightadj' => { 97 => 0x2030c }, + 'highlightcolordistortreduct' => { 427 => 0x8026 }, + 'highlightlinearitylimit' => { 370 => 0xa025 }, + 'highlightprotection' => { 253 => 0x6 }, + 'highlightrecovery' => { 448 => 'HighlightRecovery' }, + 'highlights' => { 441 => 'Highlights' }, + 'highlights2012' => { 448 => 'Highlights2012' }, + 'highlightsadj' => { 427 => 0x9019 }, + 'highlightshadow' => { 301 => 0xad }, + 'highlighttone' => { 121 => 0x1041 }, + 'highlighttonepriority' => { 12 => 0x7, 15 => 0x7, 16 => 0x7, 17 => 0x7, 19 => 0x7, 21 => 0x7, 27 => 0x7, 59 => 0x3, 78 => 0x203 }, + 'highlightwarning' => { 301 => 0x8002 }, + 'highlowkeyadj' => { 336 => 0x6c }, + 'highspeedsync' => { 174 => 0x5, 381 => 0x2, 382 => 0x2 }, + 'histogramxml' => { 254 => 0x83a1a25 }, + 'history' => { 460 => 'History', 473 => 'History' }, + 'historyaction' => { 473 => [\'History','HistoryAction'] }, + 'historychanged' => { 473 => [\'History','HistoryChanged'] }, + 'historyinstanceid' => { 473 => [\'History','HistoryInstanceID'] }, + 'historyparameters' => { 473 => [\'History','HistoryParameters'] }, + 'historysoftwareagent' => { 473 => [\'History','HistorySoftwareAgent'] }, + 'historywhen' => { 473 => [\'History','HistoryWhen'] }, + 'holefilldarkdeltathreshold' => { 131 => 0xc88 }, + 'holefilldeltathreshold' => { 131 => 0xc7e }, + 'hometowncity' => { 107 => 0x3006, 336 => 0x23, 342 => 0x2 }, + 'hometowncitycode' => { 343 => 0x1000 }, + 'hometowndst' => { 336 => 0x25, 342 => '0.2' }, + 'hostcomputer' => { 113 => 0x13c }, + 'hostsoftwarerendering' => { 131 => 0xce7 }, + 'hue' => { 179 => 0x3b, 217 => 0x3d, 218 => 0x45, 336 => 0x67 }, + 'hueadj' => { 257 => 0x2f, 427 => 0x8019 }, + 'hueadjust' => { 363 => 0x1016 }, + 'hueadjustment' => { 172 => 0x4a, 173 => 0x40, 214 => 0x92, 216 => 0x36 }, + 'hueadjustmentaqua' => { 448 => 'HueAdjustmentAqua' }, + 'hueadjustmentblue' => { 448 => 'HueAdjustmentBlue' }, + 'hueadjustmentgreen' => { 448 => 'HueAdjustmentGreen' }, + 'hueadjustmentmagenta' => { 448 => 'HueAdjustmentMagenta' }, + 'hueadjustmentorange' => { 448 => 'HueAdjustmentOrange' }, + 'hueadjustmentpurple' => { 448 => 'HueAdjustmentPurple' }, + 'hueadjustmentred' => { 448 => 'HueAdjustmentRed' }, + 'hueadjustmentyellow' => { 448 => 'HueAdjustmentYellow' }, + 'huesetting' => { 286 => 0x1011 }, + 'humanobservation' => { 112 => 'HumanObservation' }, + 'humanobservationday' => { 112 => [\'HumanObservation','HumanObservationDay'] }, + 'humanobservationearliestdate' => { 112 => [\'HumanObservation','HumanObservationEarliestDate'] }, + 'humanobservationenddayofyear' => { 112 => [\'HumanObservation','HumanObservationEndDayOfYear'] }, + 'humanobservationeventdate' => { 112 => [\'HumanObservation','HumanObservationEventDate'] }, + 'humanobservationeventid' => { 112 => [\'HumanObservation','HumanObservationEventID'] }, + 'humanobservationeventremarks' => { 112 => [\'HumanObservation','HumanObservationEventRemarks'] }, + 'humanobservationeventtime' => { 112 => [\'HumanObservation','HumanObservationEventTime'] }, + 'humanobservationfieldnotes' => { 112 => [\'HumanObservation','HumanObservationFieldNotes'] }, + 'humanobservationfieldnumber' => { 112 => [\'HumanObservation','HumanObservationFieldNumber'] }, + 'humanobservationhabitat' => { 112 => [\'HumanObservation','HumanObservationHabitat'] }, + 'humanobservationlatestdate' => { 112 => [\'HumanObservation','HumanObservationLatestDate'] }, + 'humanobservationmonth' => { 112 => [\'HumanObservation','HumanObservationMonth'] }, + 'humanobservationparenteventid' => { 112 => [\'HumanObservation','HumanObservationParentEventID'] }, + 'humanobservationsamplesizeunit' => { 112 => [\'HumanObservation','HumanObservationSampleSizeUnit'] }, + 'humanobservationsamplesizevalue' => { 112 => [\'HumanObservation','HumanObservationSampleSizeValue'] }, + 'humanobservationsamplingeffort' => { 112 => [\'HumanObservation','HumanObservationSamplingEffort'] }, + 'humanobservationsamplingprotocol' => { 112 => [\'HumanObservation','HumanObservationSamplingProtocol'] }, + 'humanobservationstartdayofyear' => { 112 => [\'HumanObservation','HumanObservationStartDayOfYear'] }, + 'humanobservationverbatimeventdate' => { 112 => [\'HumanObservation','HumanObservationVerbatimEventDate'] }, + 'humanobservationyear' => { 112 => [\'HumanObservation','HumanObservationYear'] }, + 'humidity' => { 113 => 0x9401, 453 => 'Humidity' }, + 'icc_profile' => { 114 => 'ICC_Profile' }, + 'iccprofilename' => { 460 => 'ICCProfile' }, + 'idccreativestyle' => { 427 => 0x8000 }, + 'idcpreviewlength' => { 427 => 0x202 }, + 'idcpreviewstart' => { 427 => 0x201 }, + 'identification' => { 112 => 'Identification' }, + 'identificationid' => { 112 => [\'Identification','IdentificationIdentificationID'] }, + 'identificationqualifier' => { 112 => [\'Identification','IdentificationIdentificationQualifier'] }, + 'identificationreferences' => { 112 => [\'Identification','IdentificationIdentificationReferences'] }, + 'identificationremarks' => { 112 => [\'Identification','IdentificationIdentificationRemarks'] }, + 'identificationverificationstatus' => { 112 => [\'Identification','IdentificationIdentificationVerificationStatus'] }, + 'identifiedby' => { 112 => [\'Identification','IdentificationIdentifiedBy'] }, + 'identifier' => { 449 => 'identifier', 470 => 'Identifier' }, + 'ifcameramodel' => { 131 => 0x9c8 }, + 'illumination' => { 272 => '0.5', 358 => 0x48 }, + 'imageabsolutex' => { 131 => 0x3fe }, + 'imageabsolutey' => { 131 => 0x3ff }, + 'imageadjustment' => { 214 => 0x80, 244 => 0x5 }, + 'imagealterationconstraints' => { 288 => 'ImageAlterationConstraints' }, + 'imagearea' => { 227 => 0x10, 230 => 0x10 }, + 'imageareaoffset' => { 336 => 0x38 }, + 'imageauthentication' => { 214 => 0x20 }, + 'imageboundary' => { 214 => 0x16 }, + 'imagecount' => { 121 => 0x1438, 214 => 0xa5, 397 => 0x11b }, + 'imagecreator' => { 288 => 'ImageCreator' }, + 'imagecreatorid' => { 288 => [\'ImageCreator','ImageCreatorImageCreatorID'] }, + 'imagecreatorimageid' => { 288 => 'ImageCreatorImageID' }, + 'imagecreatorname' => { 288 => [\'ImageCreator','ImageCreatorImageCreatorName'] }, + 'imagecropx' => { 131 => 0x41f }, + 'imagecropy' => { 131 => 0x420 }, + 'imagedata' => { 434 => 'Data' }, + 'imagedatasize' => { 214 => 0xa2 }, + 'imagedescription' => { 113 => 0x10e, 468 => 'ImageDescription' }, + 'imageduplicationconstraints' => { 288 => 'ImageDuplicationConstraints' }, + 'imagedustoff' => { 254 => 0xfe443a45 }, + 'imageeditcount' => { 336 => 0x41 }, + 'imageediting' => { 336 => 0x32 }, + 'imageeffects' => { 363 => 0x1010 }, + 'imagefileconstraints' => { 288 => 'ImageFileConstraints' }, + 'imagefileformatasdelivered' => { 288 => 'ImageFileFormatAsDelivered' }, + 'imagefilesizeasdelivered' => { 288 => 'ImageFileSizeAsDelivered' }, + 'imagegeneration' => { 121 => 0x1436 }, + 'imageheight' => { 113 => 0x101, 178 => 0xc, 345 => 0x10d, 432 => 'ImageHeight', 468 => 'ImageLength' }, + 'imagehistory' => { 113 => 0x9213, 451 => 'ImageHistory' }, + 'imageidnumber' => { 296 => 0x340 }, + 'imagemimetype' => { 434 => 'Mime' }, + 'imagenumber' => { 113 => 0x9211, 147 => 'ImageNumber', 172 => 0xae, 173 => 0x5e, 345 => 0x113, 381 => 0x9b, 383 => [0x400,'276.1',0x314], 444 => 'ImageNumber' }, + 'imagenumber2' => { 173 => 0x62 }, + 'imageoptimization' => { 214 => 0xa9 }, + 'imageorientation' => { 125 => 0x83 }, + 'imageprocessing' => { 214 => 0x1a }, + 'imageprocessingfiledatecreated' => { 131 => 0xc81 }, + 'imageprocessingfiletagsversionnumber' => { 131 => 0xc80 }, + 'imageprocessingversion' => { 282 => 0x0 }, + 'imagequality' => { 147 => 'ImageQuality', 229 => '723.2', 230 => '732.2', 239 => '708.1', 301 => 0x1 }, + 'imagequality2' => { 278 => 0x603 }, + 'imagerank' => { 437 => 'ImageRank' }, + 'imagerbiassettlingdelaymsec' => { 131 => 0x600 }, + 'imagerboardversion' => { 131 => 0x439 }, + 'imagercols' => { 131 => 0x17d4 }, + 'imageref' => { 456 => 'ImageRef' }, + 'imageresolution' => { 131 => 0x944 }, + 'imageresolutionjpg' => { 131 => 0x945 }, + 'imagereview' => { 263 => '0.4', 272 => '0.4' }, + 'imagereviewmonitorofftime' => { 262 => '21.1', 264 => '21.1', 265 => '21.1', 269 => '20.1', 274 => '21.1', 275 => '21.1' }, + 'imagereviewtime' => { 261 => '25.1', 263 => '2.1', 266 => '19.1', 267 => '20.1', 268 => '20.1', 270 => '9.2', 271 => '20.1', 276 => '21.2' }, + 'imagerfiledatecreated' => { 131 => 0x9c5 }, + 'imagerfileproductionlevel' => { 131 => 0x9c4 }, + 'imagerfiletagsversionstandard' => { 131 => 0x9c7 }, + 'imagerpowerondelaymsec' => { 131 => 0x5fd }, + 'imagerrows' => { 131 => 0x17de }, + 'imagesegmentlines' => { 131 => 0x184d }, + 'imagesegmentstartline' => { 131 => 0x184c }, + 'imagesize' => { 153 => 'ImageSize' }, + 'imagesizerestriction' => { 465 => 'imageSizeRestriction' }, + 'imagesourcedata' => { 113 => 0x935c }, + 'imagespace' => { 131 => 0x909 }, + 'imagestabilization' => { 33 => 0x22, 107 => 0x3020, 121 => 0x1422, 147 => 'ImageStabilization', 172 => 0xbd, 173 => 0x71, 174 => 0x57, 175 => 0x0, 176 => [0x18,0x107,0x113], 177 => 0x49c2, 214 => 0xac, 278 => 0x604, 281 => 0x1600, 301 => 0x1a, 386 => 0x12, 387 => 0x11, 394 => 0xb026 }, + 'imagestabilization2' => { 385 => 0xa }, + 'imagestabilizationsetting' => { 177 => 0x14, 381 => 0x3d, 382 => 0x3d, 392 => 0x14 }, + 'imagestyle' => { 381 => 0x2d, 382 => 0x27 }, + 'imagesupplier' => { 288 => 'ImageSupplier' }, + 'imagesupplierid' => { 288 => [\'ImageSupplier','ImageSupplierImageSupplierID'] }, + 'imagesupplierimageid' => { 288 => 'ImageSupplierImageID' }, + 'imagesuppliername' => { 288 => [\'ImageSupplier','ImageSupplierImageSupplierName'] }, + 'imagetemperaturemax' => { 115 => 0x1 }, + 'imagetemperaturemin' => { 115 => 0x2 }, + 'imagetone' => { 336 => 0x4f }, + 'imagetype' => { 125 => 0x82, 288 => 'ImageType' }, + 'imageuniqueid' => { 1 => 0x15, 60 => 0x28, 113 => 0xa420, 451 => 'ImageUniqueID', 452 => 'ImageUniqueID' }, + 'imagewidth' => { 113 => 0x100, 178 => 0xe, 345 => 0x10c, 432 => 'ImageWidth', 468 => 'ImageWidth' }, + 'inclinationangle' => { 427 => 0x900f }, + 'inclinationcorrection' => { 427 => 0x900e }, + 'incrementaltemperature' => { 448 => 'IncrementalTemperature' }, + 'incrementaltint' => { 448 => 'IncrementalTint' }, + 'industry' => { 462 => 'industry', 463 => 'industry' }, + 'infobuttonwhenshooting' => { 78 => 0x409 }, + 'infraredilluminator' => { 357 => 0x28 }, + 'ingredientexclusion' => { 464 => 'ingredientExclusion' }, + 'ingredients' => { 473 => 'Ingredients' }, + 'ingredientsalternatepaths' => { 473 => [\'Ingredients','IngredientsAlternatePaths'] }, + 'ingredientsdocumentid' => { 473 => [\'Ingredients','IngredientsDocumentID'] }, + 'ingredientsfilepath' => { 473 => [\'Ingredients','IngredientsFilePath'] }, + 'ingredientsfrompart' => { 473 => [\'Ingredients','IngredientsFromPart'] }, + 'ingredientsinstanceid' => { 473 => [\'Ingredients','IngredientsInstanceID'] }, + 'ingredientslastmodifydate' => { 473 => [\'Ingredients','IngredientsLastModifyDate'] }, + 'ingredientslasturl' => { 473 => [\'Ingredients','IngredientsLastURL'] }, + 'ingredientslinkcategory' => { 473 => [\'Ingredients','IngredientsLinkCategory'] }, + 'ingredientslinkform' => { 473 => [\'Ingredients','IngredientsLinkForm'] }, + 'ingredientsmanager' => { 473 => [\'Ingredients','IngredientsManager'] }, + 'ingredientsmanagervariant' => { 473 => [\'Ingredients','IngredientsManagerVariant'] }, + 'ingredientsmanageto' => { 473 => [\'Ingredients','IngredientsManageTo'] }, + 'ingredientsmanageui' => { 473 => [\'Ingredients','IngredientsManageUI'] }, + 'ingredientsmaskmarkers' => { 473 => [\'Ingredients','IngredientsMaskMarkers'] }, + 'ingredientsoriginaldocumentid' => { 473 => [\'Ingredients','IngredientsOriginalDocumentID'] }, + 'ingredientspartmapping' => { 473 => [\'Ingredients','IngredientsPartMapping'] }, + 'ingredientsplacedresolutionunit' => { 473 => [\'Ingredients','IngredientsPlacedResolutionUnit'] }, + 'ingredientsplacedxresolution' => { 473 => [\'Ingredients','IngredientsPlacedXResolution'] }, + 'ingredientsplacedyresolution' => { 473 => [\'Ingredients','IngredientsPlacedYResolution'] }, + 'ingredientsrenditionclass' => { 473 => [\'Ingredients','IngredientsRenditionClass'] }, + 'ingredientsrenditionparams' => { 473 => [\'Ingredients','IngredientsRenditionParams'] }, + 'ingredientstopart' => { 473 => [\'Ingredients','IngredientsToPart'] }, + 'ingredientsversionid' => { 473 => [\'Ingredients','IngredientsVersionID'] }, + 'initialafpointaiservoaf' => { 78 => 0x51e }, + 'initialafpointinservo' => { 2 => 0x13 }, + 'initialcameradolly' => { 435 => 'InitialCameraDolly' }, + 'initialhorizontalfovdegrees' => { 435 => 'InitialHorizontalFOVDegrees' }, + 'initialviewheadingdegrees' => { 435 => 'InitialViewHeadingDegrees', 436 => 'InitialViewHeadingDegrees' }, + 'initialviewpitchdegrees' => { 435 => 'InitialViewPitchDegrees', 436 => 'InitialViewPitchDegrees' }, + 'initialviewrolldegrees' => { 435 => 'InitialViewRollDegrees', 436 => 'InitialViewRollDegrees' }, + 'initialzoomliveview' => { 261 => '4.4' }, + 'initialzoomsetting' => { 261 => '9.3', 270 => '27.3' }, + 'inkset' => { 113 => 0x14c }, + 'inputprofile' => { 131 => 0x1389 }, + 'instanceid' => { 473 => 'InstanceID' }, + 'instantplaybacksetup' => { 174 => 0x3e }, + 'instantplaybacktime' => { 174 => 0x3d }, + 'instructions' => { 460 => 'Instructions' }, + 'instrument' => { 472 => 'instrument' }, + 'integrationtime' => { 131 => 0x423 }, + 'intellectualgenre' => { 457 => 'IntellectualGenre' }, + 'intelligentauto' => { 394 => 0xb052, 419 => 0xd, 420 => 0xe, 421 => 0xd }, + 'intelligentcontrast' => { 49 => 0x4 }, + 'intelligentd-range' => { 301 => 0x79 }, + 'intelligentexposure' => { 301 => 0x5d }, + 'intelligentresolution' => { 301 => 0x70 }, + 'interchangecolorspace' => { 127 => 0x40 }, + 'intergraphmatrix' => { 113 => 0x8480 }, + 'internalflash' => { 171 => 0x2b, 261 => '23.1', 263 => '8.1', 266 => '22.1', 268 => '23.1', 272 => '8.1', 276 => '24.1', 281 => 0x1208 }, + 'internalflashae1' => { 283 => 0x1021 }, + 'internalflashae1_0' => { 283 => 0x101d }, + 'internalflashae2' => { 283 => 0x1022 }, + 'internalflashae2_0' => { 283 => 0x101e }, + 'internalflashmode' => { 324 => 0x1 }, + 'internalflashstrength' => { 324 => 0x3 }, + 'internalflashtable' => { 283 => 0x1024 }, + 'internallensserialnumber' => { 370 => 0xa005 }, + 'internalndfilter' => { 301 => 0x9d }, + 'internalserialnumber' => { 60 => 0x96, 71 => 0x9, 121 => 0x10, 177 => 0x49dc, 277 => 0x18, 279 => 0x102, 298 => 0x500, 301 => 0x25, 316 => 0x4, 363 => 0x5, 412 => [0x7c,0xf0], 413 => 0x88 }, + 'interopindex' => { 113 => 0x1, 453 => 'InteroperabilityIndex' }, + 'interopversion' => { 113 => 0x2 }, + 'intervallength' => { 171 => 0x10 }, + 'intervalmode' => { 171 => 0x26 }, + 'intervalnumber' => { 171 => 0x11 }, + 'intervalshooting' => { 336 => 0x92 }, + 'introtime' => { 472 => 'introTime' }, + 'introtimescale' => { 472 => [\'introTime','introTimeScale'] }, + 'introtimevalue' => { 472 => [\'introTime','introTimeValue'] }, + 'ipaversion' => { 131 => 0xdae }, + 'ipfcameramodel' => { 131 => 0xe4d }, + 'iptc' => { 114 => 'IPTC' }, + 'iptc-naa' => { 113 => 0x83bb, 306 => 0x83bb }, + 'iptcbitspersample' => { 127 => 0x56 }, + 'iptcdigest' => { 350 => 0x425 }, + 'iptcimageheight' => { 127 => 0x1e }, + 'iptcimagerotation' => { 127 => 0x66 }, + 'iptcimagewidth' => { 127 => 0x14 }, + 'iptclastedited' => { 458 => 'IptcLastEdited' }, + 'iptcpicturenumber' => { 127 => 0xa }, + 'iptcpixelheight' => { 127 => 0x32 }, + 'iptcpixelwidth' => { 127 => 0x28 }, + 'isalternativeof' => { 462 => 'isAlternativeOf' }, + 'isbn' => { 462 => 'isbn' }, + 'iscorrectionof' => { 462 => 'isCorrectionOf' }, + 'iscustompicturestyle' => { 103 => 0x3 }, + 'ismergedhdr' => { 444 => 'IsMergedHDR' }, + 'ismergedpanorama' => { 444 => 'IsMergedPanorama' }, + 'iso' => { 6 => 0x6, 8 => 0x6, 9 => 0x75, 10 => 0x6, 11 => 0x79, 12 => 0x6, 13 => 0x6, 14 => 0x6, 15 => 0x6, 16 => 0x6, 17 => 0x6, 18 => 0x6, 19 => 0x6, 20 => 0x6, 21 => 0x6, 22 => 0x6, 23 => 0x6, 24 => 0x6, 25 => 0x6, 26 => 0x6, 27 => 0x6, 28 => 0x6, 29 => 0x0, 30 => 0x1, 106 => 0x14, 107 => [0x3014,0x14], 113 => 0x8827, 130 => 0xfd06, 131 => 0x1784, 133 => 0x60, 135 => [0xfa2e,0xfa46], 136 => [0x27,0x28], 137 => 0xf105, 140 => 0x14, 142 => 0x4e, 145 => 0x34, 147 => 'ISO', 171 => 0x8, 177 => 0x49ba, 205 => 0x0, 214 => 0x2, 306 => 0x17, 336 => [0x8b,0x14], 343 => 0x14, 345 => 0x105, 370 => 0xa014, 392 => 0x6f, 399 => [0x1f,0x21,0x25], 452 => 'ISOSpeedRatings' }, + 'iso2' => { 205 => 0x6, 224 => 0x265, 225 => 0x25c, 226 => 0x265, 227 => 0x221, 228 => 0x25d, 229 => 0x256, 230 => 0x25d, 234 => 0x2b5, 237 => 0x265, 243 => 0x2b5 }, + 'isoauto' => { 317 => '14.4' }, + 'isoautohilimit' => { 232 => 0x18eb, 233 => 0xe82, 241 => 0x185d }, + 'isoautomax' => { 393 => 0x4 }, + 'isoautomin' => { 393 => 0x2 }, + 'isoautoparameters' => { 336 => 0x7a }, + 'isoautoshuttertime' => { 232 => 0x18ea, 233 => 0xe81, 241 => 0x185c }, + 'isocalibrationgain' => { 131 => 0x89f }, + 'isodisplay' => { 264 => '4.1', 265 => '4.1', 266 => '2.3', 267 => '3.3', 268 => '3.3', 271 => '3.3', 274 => '4.3', 275 => '4.1', 276 => '4.3' }, + 'isoexpansion' => { 78 => 0x103, 79 => 0x7, 80 => 0x8, 83 => 0x8, 205 => 0x4 }, + 'isoexpansion2' => { 205 => 0xa }, + 'isofloor' => { 317 => 0x6 }, + 'isoselection' => { 214 => 0xf }, + 'isosensitivitystep' => { 269 => '6.2', 271 => '6.2' }, + 'isosetting' => { 133 => 0x5e, 147 => 'ISOSetting', 171 => 0x24, 172 => 0x26, 173 => 0x1c, 174 => 0x13, 179 => 0x6, 214 => 0x13, 317 => '17.3', 362 => 0x27, 381 => 0x16, 382 => 0x14, 383 => 0x2, 392 => 0x6d, 393 => 0x0 }, + 'isospeed' => { 113 => 0x8833, 453 => 'ISOSpeed' }, + 'isospeedexpansion' => { 77 => 0x3 }, + 'isospeedincrements' => { 78 => 0x102 }, + 'isospeedlatitudeyyy' => { 113 => 0x8834, 453 => 'ISOSpeedLatitudeyyy' }, + 'isospeedlatitudezzz' => { 113 => 0x8835, 453 => 'ISOSpeedLatitudezzz' }, + 'isospeedrange' => { 78 => 0x103 }, + 'isostepsize' => { 261 => '6.1', 262 => '7.2', 264 => '7.2', 265 => '7.2', 270 => '4.1', 274 => '7.2', 275 => '7.2' }, + 'isovalue' => { 283 => 0x1001 }, + 'issn' => { 462 => 'issn' }, + 'issueidentifier' => { 462 => 'issueIdentifier' }, + 'issuename' => { 462 => 'issueName' }, + 'issueteaser' => { 462 => 'issueTeaser' }, + 'issuetype' => { 462 => 'issueType' }, + 'istranslationof' => { 462 => 'isTranslationOf' }, + 'itemsubtype' => { 169 => 'ItemSubType' }, + 'jobid' => { 125 => 0xb8 }, + 'jobname' => { 454 => 'JobName' }, + 'jobref' => { 471 => 'JobRef' }, + 'jobrefid' => { 471 => [\'JobRef','JobRefId'] }, + 'jobrefname' => { 471 => [\'JobRef','JobRefName'] }, + 'jobrefurl' => { 471 => [\'JobRef','JobRefUrl'] }, + 'jobstatus' => { 454 => 'JobStatus' }, + 'jpeghandling' => { 448 => 'JPEGHandling' }, + 'jpegquality' => { 9 => 0x66, 301 => 0x43, 303 => 0x3034, 394 => 0xb047 }, + 'jpegsize' => { 303 => 0x303a }, + 'jpgcompression' => { 233 => 0x7d4 }, + 'jpgfromraw' => { 91 => 0x2007, 108 => 'JpgFromRaw', 306 => 0x2e }, + 'jpgfromrawlength' => { 113 => [0x117,0x202] }, + 'jpgfromrawstart' => { 113 => [0x111,0x201] }, + 'jpgrecordedpixels' => { 317 => '14.1' }, + 'jurisdiction' => { 445 => 'jurisdiction' }, + 'kelvinwb_01' => { 325 => 0x5 }, + 'kelvinwb_02' => { 325 => 0x9 }, + 'kelvinwb_03' => { 325 => 0xd }, + 'kelvinwb_04' => { 325 => 0x11 }, + 'kelvinwb_05' => { 325 => 0x15 }, + 'kelvinwb_06' => { 325 => 0x19 }, + 'kelvinwb_07' => { 325 => 0x1d }, + 'kelvinwb_08' => { 325 => 0x21 }, + 'kelvinwb_09' => { 325 => 0x25 }, + 'kelvinwb_10' => { 325 => 0x29 }, + 'kelvinwb_11' => { 325 => 0x2d }, + 'kelvinwb_12' => { 325 => 0x31 }, + 'kelvinwb_13' => { 325 => 0x35 }, + 'kelvinwb_14' => { 325 => 0x39 }, + 'kelvinwb_15' => { 325 => 0x3d }, + 'kelvinwb_16' => { 325 => 0x41 }, + 'kelvinwb_daylight' => { 325 => 0x1 }, + 'kerneldenominators' => { 131 => 0x933 }, + 'key' => { 472 => 'key' }, + 'keystonecompensation' => { 282 => 0x1900 }, + 'keystonedirection' => { 282 => 0x1901 }, + 'keystonevalue' => { 282 => 0x1906 }, + 'keyword' => { 462 => 'keyword' }, + 'keywordinfo' => { 162 => 'Keywords' }, + 'keywords' => { 125 => 0x19, 148 => 'Keywords', 287 => 'Keywords', 352 => 'Keywords', 442 => 'keywords', 459 => 'Keywords', 470 => 'Keywords' }, + 'killdate' => { 462 => 'killDate' }, + 'killdatea-platform' => { 462 => [\'killDate','killDateA-platform'] }, + 'killdatedate' => { 462 => [\'killDate','killDateDate'] }, + 'kodakimageheight' => { 130 => 0xf908, 133 => 0xe, 135 => [0xfa1e,0xfa52], 141 => 0x70 }, + 'kodakimagewidth' => { 130 => 0xf907, 133 => 0xc, 135 => [0xfa1d,0xfa51], 141 => 0x6c }, + 'kodakinfotype' => { 130 => 0xfa00 }, + 'kodaklook' => { 131 => 0xe4c }, + 'kodaklookprofile' => { 131 => 0x138a }, + 'kodakmaker' => { 141 => 0x8 }, + 'kodakmodel' => { 133 => 0x0, 141 => 0x28 }, + 'kodaktag' => { 131 => 0x3ea }, + 'kodakversion' => { 131 => 0x0 }, + 'label' => { 291 => 'Label', 470 => 'Label' }, + 'labelname1' => { 456 => [\'TagStructure','TagStructureLabelName'] }, + 'labelname2' => { 456 => [\'TagStructure','TagStructureSubLabelsLabelName'] }, + 'labelname3' => { 456 => [\'TagStructure','TagStructureSubLabelsSubLabelsLabelName'] }, + 'labelname4' => { 456 => [\'TagStructure','TagStructureSubLabelsSubLabelsSubLabelsLabelName'] }, + 'labelname5' => { 456 => [\'TagStructure','TagStructureSubLabelsSubLabelsSubLabelsSubLabelsLabelName'] }, + 'labelname6' => { 456 => [\'TagStructure','TagStructureSubLabelsSubLabelsSubLabelsSubLabelsSubLabelsLabelName'] }, + 'landmark' => { 301 => 0x6f }, + 'landscapeoutputhighlightpoint' => { 103 => 0x26 }, + 'landscapeoutputshadowpoint' => { 103 => 0x27 }, + 'landscaperawcolortone' => { 103 => 0x1f }, + 'landscaperawcontrast' => { 103 => 0x21 }, + 'landscaperawhighlight' => { 103 => 0x77 }, + 'landscaperawhighlightpoint' => { 103 => 0x24 }, + 'landscaperawlinear' => { 103 => 0x22 }, + 'landscaperawsaturation' => { 103 => 0x20 }, + 'landscaperawshadow' => { 103 => 0x80 }, + 'landscaperawshadowpoint' => { 103 => 0x25 }, + 'landscaperawsharpness' => { 103 => 0x23 }, + 'landscapeunsharpmaskfineness' => { 103 => 0xa0 }, + 'landscapeunsharpmaskstrength' => { 103 => 0x9e }, + 'landscapeunsharpmaskthreshold' => { 103 => 0xa2 }, + 'language' => { 449 => 'language' }, + 'languageidentifier' => { 125 => 0x87 }, + 'largestvalidinteriorrectheight' => { 435 => 'LargestValidInteriorRectHeight' }, + 'largestvalidinteriorrectleft' => { 435 => 'LargestValidInteriorRectLeft' }, + 'largestvalidinteriorrecttop' => { 435 => 'LargestValidInteriorRectTop' }, + 'largestvalidinteriorrectwidth' => { 435 => 'LargestValidInteriorRectWidth' }, + 'lastfilenumber' => { 171 => 0x1b }, + 'lastkeywordiptc' => { 169 => 'LastKeywordIPTC' }, + 'lastkeywordxmp' => { 169 => 'LastKeywordXMP' }, + 'lastphotodate' => { 435 => 'LastPhotoDate' }, + 'lasturl' => { 473 => 'LastURL' }, + 'lateralchromaticaberration' => { 394 => 0x2012 }, + 'lateralchromaticaberrationcorrectionalreadyapplied' => { 444 => 'LateralChromaticAberrationCorrectionAlreadyApplied' }, + 'latestageorhigheststage' => { 112 => [\'GeologicalContext','GeologicalContextLatestAgeOrHighestStage'] }, + 'latesteonorhighesteonothem' => { 112 => [\'GeologicalContext','GeologicalContextLatestEonOrHighestEonothem'] }, + 'latestepochorhighestseries' => { 112 => [\'GeologicalContext','GeologicalContextLatestEpochOrHighestSeries'] }, + 'latesteraorhighesterathem' => { 112 => [\'GeologicalContext','GeologicalContextLatestEraOrHighestErathem'] }, + 'latestperiodorhighestsystem' => { 112 => [\'GeologicalContext','GeologicalContextLatestPeriodOrHighestSystem'] }, + 'latitude' => { 110 => 'Latitude' }, + 'lc1' => { 327 => 0x2 }, + 'lc10' => { 327 => 0xb }, + 'lc11' => { 327 => 0xc }, + 'lc12' => { 327 => 0xd }, + 'lc14' => { 327 => 0xf }, + 'lc15' => { 327 => 0x10 }, + 'lc3' => { 327 => 0x4 }, + 'lc4' => { 327 => 0x5 }, + 'lc5' => { 327 => 0x6 }, + 'lc6' => { 327 => 0x7 }, + 'lc7' => { 327 => 0x8 }, + 'lc8' => { 327 => 0x9 }, + 'lcddisplayatpoweron' => { 78 => 0x811, 82 => 0xa }, + 'lcddisplayreturntoshoot' => { 83 => 0x12 }, + 'lcdillumination' => { 261 => '17.5', 262 => '5.2', 264 => '5.1', 265 => '5.1', 270 => '10.3', 271 => '4.2', 274 => '5.2', 275 => '5.1', 276 => '5.4' }, + 'lcdilluminationduringbulb' => { 78 => 0x408 }, + 'lcdmatrix' => { 131 => 0xe74 }, + 'lcdmatrixchickfix' => { 131 => 0xe75 }, + 'lcdmatrixmarvin' => { 131 => 0xe76 }, + 'lcdpanels' => { 77 => 0x8 }, + 'lcheditor' => { 254 => 0x8ae85e }, + 'legacyiptcdigest' => { 460 => 'LegacyIPTCDigest' }, + 'legalcode' => { 445 => 'legalcode' }, + 'lens' => { 113 => 0xfdea, 214 => 0x84, 444 => 'Lens' }, + 'lensafstopbutton' => { 76 => 0x11, 77 => 0x13, 78 => 0x506, 79 => 0x10, 80 => 0x12, 83 => 0x13, 84 => 0x9 }, + 'lensaperturerange' => { 373 => [0x30,0x48] }, + 'lenscorrectionsettings' => { 451 => 'LensCorrectionSettings' }, + 'lensdistortinfo' => { 444 => 'LensDistortInfo' }, + 'lensdistortionparams' => { 283 => 0x206 }, + 'lensdrivenoaf' => { 78 => 0x505 }, + 'lensdrivewhenafimpossible' => { 2 => 0xb }, + 'lense-mountversion' => { 383 => 0x3f0, 426 => 0xd }, + 'lensfirmware' => { 364 => 0x20, 370 => 0xa004 }, + 'lensfirmwareversion' => { 279 => 0x204, 301 => 0x60, 383 => 0x3f3, 426 => 0x14 }, + 'lensfocallength' => { 97 => 0xf0512, 327 => 0x9 }, + 'lensfocalrange' => { 373 => [0xa,0x2a] }, + 'lensfocusfunctionbuttons' => { 262 => '55.1', 264 => '52.1', 265 => '52.1', 274 => '52.1', 275 => '52.1' }, + 'lensformat' => { 406 => 0x1891, 408 => 0x18bd, 409 => 0x18ed, 410 => 0x17f1, 412 => 0x106, 413 => 0x106, 422 => 0x603, 423 => 0x5d }, + 'lensfstops' => { 206 => 0x7, 207 => 0xc, 208 => 0xd, 212 => 0xe, 214 => 0x8b, 327 => '0.3' }, + 'lensid' => { 444 => 'LensID' }, + 'lensidnumber' => { 206 => 0x6, 207 => 0xb, 208 => 0xc, 212 => 0xd }, + 'lensinfo' => { 113 => 0xa432, 333 => 0x2a, 444 => 'LensInfo', 453 => 'LensSpecification' }, + 'lenskind' => { 327 => 0x1 }, + 'lensmake' => { 113 => 0xa433, 154 => 'Make', 453 => 'LensMake' }, + 'lensmanualdistortionamount' => { 448 => 'LensManualDistortionAmount' }, + 'lensmanufacturer' => { 169 => 'LensManufacturer' }, + 'lensmaxaperturerange' => { 373 => 0x2b }, + 'lensmodel' => { 6 => 0x937, 13 => 0x92b, 14 => 0x933, 60 => 0x95, 113 => 0xa434, 154 => 'Model', 169 => 'LensModel', 209 => 0x18a, 210 => 0x18b, 211 => 0x2ac, 279 => 0x203, 333 => 0xc, 345 => 0x412, 453 => 'LensModel' }, + 'lensmodulationoptimizer' => { 121 => 0x1045 }, + 'lensmount' => { 383 => 0x99, 406 => 0x1892, 408 => 0x18be, 409 => 0x18ee, 410 => 0x17f2, 412 => 0x105, 413 => 0x105, 422 => 0x604, 423 => 0x5e }, + 'lensmount2' => { 426 => 0x8 }, + 'lensprofilechromaticaberrationscale' => { 448 => 'LensProfileChromaticAberrationScale' }, + 'lensprofiledigest' => { 448 => 'LensProfileDigest' }, + 'lensprofiledistortionscale' => { 448 => 'LensProfileDistortionScale' }, + 'lensprofileenable' => { 448 => 'LensProfileEnable' }, + 'lensprofilefilename' => { 448 => 'LensProfileFilename' }, + 'lensprofilematchkeycameramodelname' => { 448 => 'LensProfileMatchKeyCameraModelName' }, + 'lensprofilematchkeyexifmake' => { 448 => 'LensProfileMatchKeyExifMake' }, + 'lensprofilematchkeyexifmodel' => { 448 => 'LensProfileMatchKeyExifModel' }, + 'lensprofilematchkeyisraw' => { 448 => 'LensProfileMatchKeyIsRaw' }, + 'lensprofilematchkeylensid' => { 448 => 'LensProfileMatchKeyLensID' }, + 'lensprofilematchkeylensinfo' => { 448 => 'LensProfileMatchKeyLensInfo' }, + 'lensprofilematchkeylensname' => { 448 => 'LensProfileMatchKeyLensName' }, + 'lensprofilematchkeysensorformatfactor' => { 448 => 'LensProfileMatchKeySensorFormatFactor' }, + 'lensprofilename' => { 448 => 'LensProfileName' }, + 'lensprofilesetup' => { 448 => 'LensProfileSetup' }, + 'lensprofilevignettingscale' => { 448 => 'LensProfileVignettingScale' }, + 'lensproperties' => { 279 => 0x20b }, + 'lensserialnumber' => { 20 => 0x164, 31 => 0x16b, 58 => 0x0, 113 => 0xa435, 154 => 'SerialNumber', 279 => 0x202, 299 => 0x321, 301 => 0x52, 364 => 0x30, 444 => 'LensSerialNumber', 453 => 'LensSerialNumber' }, + 'lensshutterlock' => { 174 => 0x4a }, + 'lensspec' => { 378 => 0x0, 379 => 0x0, 380 => 0x0, 394 => 0xb02a }, + 'lensspecfeatures' => { 412 => [0x115,0x116], 413 => [0x116,0x21c,0x21e] }, + 'lenstemperature' => { 283 => 0x1008 }, + 'lenstype' => { 6 => 0xe2, 7 => 0xd, 8 => 0x1a7, 9 => 0xc, 10 => 0x111, 11 => 0xc, 12 => 0x14f, 13 => 0xd6, 14 => 0xde, 15 => 0xf6, 16 => 0xea, 17 => 0xff, 18 => [0xc,0x97], 19 => 0xe6, 20 => 0x153, 21 => 0xea, 22 => 0xe8, 23 => 0x127, 24 => 0x161, 25 => 0x166, 26 => 0x184, 27 => 0x112, 28 => 0x189, 33 => 0x16, 176 => 0x10c, 177 => 0x49bd, 214 => 0x83, 279 => 0x201, 292 => 0x16, 296 => 0x310, 298 => 0x303, 299 => 0x303, 301 => 0x51, 303 => 0x3405, 328 => 0x0, 329 => 0x0, 330 => 0x1, 331 => 0x1, 332 => 0x1, 334 => 0x0, 370 => 0xa003, 373 => 0x27, 394 => 0xb027, 406 => 0x1896, 408 => 0x18c2, 409 => 0x18f2, 410 => 0x17f6, 412 => 0x109, 413 => 0x109, 422 => 0x608, 423 => 0x62 }, + 'lenstype2' => { 383 => 0x3f7, 406 => 0x1893, 408 => 0x18bf, 409 => 0x18ef, 410 => 0x17f3, 412 => 0x107, 413 => 0x107, 422 => 0x605, 423 => 0x60 }, + 'lenstype3' => { 426 => 0x9 }, + 'lenszoomposition' => { 419 => 0x19, 420 => 0x1e, 423 => [0x342,0x35a] }, + 'levelindicator' => { 309 => 0x15 }, + 'levelorientation' => { 335 => 0x0 }, + 'license' => { 445 => 'license' }, + 'licensee' => { 288 => 'Licensee' }, + 'licenseeid' => { 288 => [\'Licensee','LicenseeLicenseeID'] }, + 'licenseeimageid' => { 288 => 'LicenseeImageID' }, + 'licenseeimagenotes' => { 288 => 'LicenseeImageNotes' }, + 'licenseename' => { 288 => [\'Licensee','LicenseeLicenseeName'] }, + 'licenseenddate' => { 288 => 'LicenseEndDate' }, + 'licenseeprojectreference' => { 288 => 'LicenseeProjectReference' }, + 'licenseetransactionid' => { 288 => 'LicenseeTransactionID' }, + 'licenseid' => { 288 => 'LicenseID' }, + 'licensestartdate' => { 288 => 'LicenseStartDate' }, + 'licensetransactiondate' => { 288 => 'LicenseTransactionDate' }, + 'licensetype' => { 450 => 'licensetype' }, + 'licensor' => { 288 => 'Licensor' }, + 'licensorcity' => { 288 => [\'Licensor','LicensorLicensorCity'] }, + 'licensorcountry' => { 288 => [\'Licensor','LicensorLicensorCountry'] }, + 'licensoremail' => { 288 => [\'Licensor','LicensorLicensorEmail'] }, + 'licensorextendedaddress' => { 288 => [\'Licensor','LicensorLicensorExtendedAddress'] }, + 'licensorid' => { 288 => [\'Licensor','LicensorLicensorID'] }, + 'licensorimageid' => { 288 => 'LicensorImageID' }, + 'licensorname' => { 288 => [\'Licensor','LicensorLicensorName'] }, + 'licensornotes' => { 288 => 'LicensorNotes' }, + 'licensorpostalcode' => { 288 => [\'Licensor','LicensorLicensorPostalCode'] }, + 'licensorregion' => { 288 => [\'Licensor','LicensorLicensorRegion'] }, + 'licensorstreetaddress' => { 288 => [\'Licensor','LicensorLicensorStreetAddress'] }, + 'licensortelephone1' => { 288 => [\'Licensor','LicensorLicensorTelephone1'] }, + 'licensortelephone2' => { 288 => [\'Licensor','LicensorLicensorTelephone2'] }, + 'licensortelephonetype1' => { 288 => [\'Licensor','LicensorLicensorTelephoneType1'] }, + 'licensortelephonetype2' => { 288 => [\'Licensor','LicensorLicensorTelephoneType2'] }, + 'licensortransactionid' => { 288 => 'LicensorTransactionID' }, + 'licensorurl' => { 288 => [\'Licensor','LicensorLicensorURL'] }, + 'lightcondition' => { 283 => 0x1009 }, + 'lightingmode' => { 107 => 0x302a }, + 'lightreading' => { 336 => 0x15 }, + 'lightsource' => { 113 => 0x9208, 214 => 0x90, 286 => 0x1000, 452 => 'LightSource' }, + 'lightsourcespecial' => { 372 => 0x21d }, + 'lightswitch' => { 274 => '0.1', 276 => '0.1' }, + 'lightvaluecenter' => { 283 => 0x103d }, + 'lightvalueperiphery' => { 283 => 0x103e }, + 'limitafareamodeselection' => { 262 => '51.1', 264 => '49.1', 265 => '49.1', 274 => '49.1', 275 => '49.1' }, + 'linearitylimitblue' => { 306 => 0x10 }, + 'linearitylimitgreen' => { 306 => 0xf }, + 'linearitylimitred' => { 306 => 0xe }, + 'linearityuppermargin' => { 42 => [0x2ba,0x2d1,0x2d5], 44 => 0x1e5, 45 => [0x1fe,0x2de], 46 => [0x232,0x310], 47 => 0x31e }, + 'linearizationtable' => { 113 => 0xc618 }, + 'linearresponselimit' => { 113 => 0xc62e }, + 'link' => { 462 => 'link' }, + 'linkaetoafpoint' => { 317 => '14.2' }, + 'linkedencodedrightsexpr' => { 458 => [\'LinkedEncRightsExpr','LinkedEncRightsExprLinkedRightsExpr'] }, + 'linkedencodedrightsexprlangid' => { 458 => [\'LinkedEncRightsExpr','LinkedEncRightsExprRightsExprLangId'] }, + 'linkedencodedrightsexprtype' => { 458 => [\'LinkedEncRightsExpr','LinkedEncRightsExprRightsExprEncType'] }, + 'linkedencrightsexpr' => { 458 => 'LinkedEncRightsExpr' }, + 'linlogcoring' => { 131 => 0x904 }, + 'lithostratigraphicterms' => { 112 => [\'GeologicalContext','GeologicalContextLithostratigraphicTerms'] }, + 'liveviewaf' => { 266 => '32.1', 276 => '34.1' }, + 'liveviewafareamode' => { 271 => '34.1' }, + 'liveviewafmethod' => { 399 => 0x20 }, + 'liveviewafmode' => { 271 => '34.2' }, + 'liveviewafsetting' => { 383 => 0x36 }, + 'liveviewbuttonoptions' => { 262 => '50.2', 264 => '48.2', 265 => '48.2', 274 => '48.2', 275 => '48.2' }, + 'liveviewexposuresimulation' => { 78 => 0x810 }, + 'liveviewfocusmode' => { 383 => [0x8b,0x28b] }, + 'liveviewmetering' => { 383 => [0x84,0x284] }, + 'liveviewmonitorofftime' => { 262 => '21.2', 264 => '21.2', 265 => '21.2', 267 => '20.2', 268 => '20.2', 269 => '20.2', 271 => '20.2', 274 => '21.2', 275 => '21.2' }, + 'liveviewshooting' => { 54 => 0x13 }, + 'livingspecimen' => { 112 => 'LivingSpecimen' }, + 'livingspecimenmaterialsampleid' => { 112 => [\'LivingSpecimen','LivingSpecimenMaterialSampleID'] }, + 'localcaption' => { 125 => 0x79 }, + 'localizedcameramodel' => { 113 => 0xc615 }, + 'locallocationname' => { 370 => 0x30 }, + 'location' => { 213 => 0x9, 301 => 0x67, 440 => 'Location', 457 => 'Location', 461 => 'location', 462 => 'location' }, + 'locationareacode' => { 446 => 'lac' }, + 'locationcreated' => { 458 => 'LocationCreated' }, + 'locationcreatedcity' => { 458 => [\'LocationCreated','LocationCreatedCity'] }, + 'locationcreatedcountrycode' => { 458 => [\'LocationCreated','LocationCreatedCountryCode'] }, + 'locationcreatedcountryname' => { 458 => [\'LocationCreated','LocationCreatedCountryName'] }, + 'locationcreatedgpsaltitude' => { 458 => [\'LocationCreated','LocationCreatedGPSAltitude'] }, + 'locationcreatedgpslatitude' => { 458 => [\'LocationCreated','LocationCreatedGPSLatitude'] }, + 'locationcreatedgpslongitude' => { 458 => [\'LocationCreated','LocationCreatedGPSLongitude'] }, + 'locationcreatedidentifier' => { 458 => [\'LocationCreated','LocationCreatedIdentifier'] }, + 'locationcreatedlocationid' => { 458 => [\'LocationCreated','LocationCreatedLocationId'] }, + 'locationcreatedlocationname' => { 458 => [\'LocationCreated','LocationCreatedLocationName'] }, + 'locationcreatedprovincestate' => { 458 => [\'LocationCreated','LocationCreatedProvinceState'] }, + 'locationcreatedsublocation' => { 458 => [\'LocationCreated','LocationCreatedSublocation'] }, + 'locationcreatedworldregion' => { 458 => [\'LocationCreated','LocationCreatedWorldRegion'] }, + 'locationinfoversion' => { 213 => 0x0 }, + 'locationname' => { 370 => 0x31 }, + 'locationshown' => { 458 => 'LocationShown' }, + 'locationshowncity' => { 458 => [\'LocationShown','LocationShownCity'] }, + 'locationshowncountrycode' => { 458 => [\'LocationShown','LocationShownCountryCode'] }, + 'locationshowncountryname' => { 458 => [\'LocationShown','LocationShownCountryName'] }, + 'locationshowngpsaltitude' => { 458 => [\'LocationShown','LocationShownGPSAltitude'] }, + 'locationshowngpslatitude' => { 458 => [\'LocationShown','LocationShownGPSLatitude'] }, + 'locationshowngpslongitude' => { 458 => [\'LocationShown','LocationShownGPSLongitude'] }, + 'locationshownidentifier' => { 458 => [\'LocationShown','LocationShownIdentifier'] }, + 'locationshownlocationid' => { 458 => [\'LocationShown','LocationShownLocationId'] }, + 'locationshownlocationname' => { 458 => [\'LocationShown','LocationShownLocationName'] }, + 'locationshownprovincestate' => { 458 => [\'LocationShown','LocationShownProvinceState'] }, + 'locationshownsublocation' => { 458 => [\'LocationShown','LocationShownSublocation'] }, + 'locationshownworldregion' => { 458 => [\'LocationShown','LocationShownWorldRegion'] }, + 'lockmicrophonebutton' => { 78 => 0x709 }, + 'logcomment' => { 472 => 'logComment' }, + 'logscale' => { 131 => 0x902 }, + 'longexposurenoisereduction' => { 59 => 0x4, 78 => 0x201, 79 => 0x1, 80 => 0x2, 81 => 0x1, 82 => 0x1, 83 => 0x2, 84 => 0x1, 301 => 0x49, 381 => 0x2b, 382 => 0x25, 383 => 0x25, 394 => 0x2008, 399 => 0x11, 423 => 0x44 }, + 'longexposurenoisereduction2' => { 54 => 0x8 }, + 'longitude' => { 110 => 'Longitude' }, + 'loop' => { 472 => 'loop' }, + 'lowestbiostratigraphiczone' => { 112 => [\'GeologicalContext','GeologicalContextLowestBiostratigraphicZone'] }, + 'luminanceadjustmentaqua' => { 448 => 'LuminanceAdjustmentAqua' }, + 'luminanceadjustmentblue' => { 448 => 'LuminanceAdjustmentBlue' }, + 'luminanceadjustmentgreen' => { 448 => 'LuminanceAdjustmentGreen' }, + 'luminanceadjustmentmagenta' => { 448 => 'LuminanceAdjustmentMagenta' }, + 'luminanceadjustmentorange' => { 448 => 'LuminanceAdjustmentOrange' }, + 'luminanceadjustmentpurple' => { 448 => 'LuminanceAdjustmentPurple' }, + 'luminanceadjustmentred' => { 448 => 'LuminanceAdjustmentRed' }, + 'luminanceadjustmentyellow' => { 448 => 'LuminanceAdjustmentYellow' }, + 'luminancecurvelimits' => { 102 => 0x150 }, + 'luminancecurvepoints' => { 102 => 0x126 }, + 'luminancenoisereduction' => { 97 => 0x20600, 103 => 0x5f, 373 => 0x1b }, + 'luminancenoisereductioncontrast' => { 448 => 'LuminanceNoiseReductionContrast' }, + 'luminancenoisereductiondetail' => { 448 => 'LuminanceNoiseReductionDetail' }, + 'luminancenr_tiff_jpeg' => { 103 => 0x6d }, + 'luminancesmoothing' => { 448 => 'LuminanceSmoothing' }, + 'lvshootingareadisplay' => { 78 => [0x40b,0x40c] }, + 'lyrics' => { 472 => 'lyrics' }, + 'm16cversion' => { 296 => 0x333 }, + 'macatom' => { 447 => 'macAtom' }, + 'macatomapplicationcode' => { 447 => [\'macAtom','macAtomApplicationCode'] }, + 'macatominvocationappleevent' => { 447 => [\'macAtom','macAtomInvocationAppleEvent'] }, + 'macatomposixprojectpath' => { 447 => [\'macAtom','macAtomPosixProjectPath'] }, + 'machineobservation' => { 112 => 'MachineObservation' }, + 'machineobservationday' => { 112 => [\'MachineObservation','MachineObservationDay'] }, + 'machineobservationearliestdate' => { 112 => [\'MachineObservation','MachineObservationEarliestDate'] }, + 'machineobservationenddayofyear' => { 112 => [\'MachineObservation','MachineObservationEndDayOfYear'] }, + 'machineobservationeventdate' => { 112 => [\'MachineObservation','MachineObservationEventDate'] }, + 'machineobservationeventid' => { 112 => [\'MachineObservation','MachineObservationEventID'] }, + 'machineobservationeventremarks' => { 112 => [\'MachineObservation','MachineObservationEventRemarks'] }, + 'machineobservationeventtime' => { 112 => [\'MachineObservation','MachineObservationEventTime'] }, + 'machineobservationfieldnotes' => { 112 => [\'MachineObservation','MachineObservationFieldNotes'] }, + 'machineobservationfieldnumber' => { 112 => [\'MachineObservation','MachineObservationFieldNumber'] }, + 'machineobservationhabitat' => { 112 => [\'MachineObservation','MachineObservationHabitat'] }, + 'machineobservationlatestdate' => { 112 => [\'MachineObservation','MachineObservationLatestDate'] }, + 'machineobservationmonth' => { 112 => [\'MachineObservation','MachineObservationMonth'] }, + 'machineobservationparenteventid' => { 112 => [\'MachineObservation','MachineObservationParentEventID'] }, + 'machineobservationsamplesizeunit' => { 112 => [\'MachineObservation','MachineObservationSampleSizeUnit'] }, + 'machineobservationsamplesizevalue' => { 112 => [\'MachineObservation','MachineObservationSampleSizeValue'] }, + 'machineobservationsamplingeffort' => { 112 => [\'MachineObservation','MachineObservationSamplingEffort'] }, + 'machineobservationsamplingprotocol' => { 112 => [\'MachineObservation','MachineObservationSamplingProtocol'] }, + 'machineobservationstartdayofyear' => { 112 => [\'MachineObservation','MachineObservationStartDayOfYear'] }, + 'machineobservationverbatimeventdate' => { 112 => [\'MachineObservation','MachineObservationVerbatimEventDate'] }, + 'machineobservationyear' => { 112 => [\'MachineObservation','MachineObservationYear'] }, + 'macro' => { 121 => 0x1020, 123 => 0x202, 283 => 0x202, 362 => 0x21, 372 => 0x202, 394 => 0xb040 }, + 'macroled' => { 281 => 0x120a }, + 'macromagnification' => { 6 => 0x1b, 10 => 0x1b, 13 => 0x1b, 14 => 0x1b, 18 => 0x1b, 19 => 0x1b, 54 => 0x10 }, + 'macromode' => { 33 => 0x1, 171 => 0xb, 278 => 0x300, 301 => 0x1c, 363 => 0x1009 }, + 'magentahsl' => { 97 => 0x20917 }, + 'magicfilter' => { 278 => 0x52c }, + 'magnifiedview' => { 80 => 0x11, 82 => 0x9 }, + 'mainboardversion' => { 131 => 0x438 }, + 'maindialexposurecomp' => { 272 => '0.6' }, + 'mainingredient' => { 464 => 'mainIngredient' }, + 'majorversion' => { 438 => 'MajorVersion' }, + 'make' => { 92 => 0x0, 109 => 0x1, 113 => 0x10f, 147 => 'Make', 291 => 'Make', 306 => 0x10f, 461 => 'make', 468 => 'Make' }, + 'makernote' => { 452 => 'MakerNote' }, + 'makernoteapple' => { 111 => 'MakN', 113 => 0x927c }, + 'makernotecanon' => { 111 => 'MakN', 113 => 0x927c }, + 'makernotecasio' => { 111 => 'MakN', 113 => 0x927c }, + 'makernotecasio2' => { 111 => 'MakN', 113 => 0x927c }, + 'makernotedji' => { 111 => 'MakN', 113 => 0x927c }, + 'makernoteflir' => { 111 => 'MakN', 113 => 0x927c }, + 'makernotefujifilm' => { 111 => 'MakN', 113 => 0x927c }, + 'makernotege' => { 111 => 'MakN', 113 => 0x927c }, + 'makernotege2' => { 111 => 'MakN', 113 => 0x927c }, + 'makernotehasselblad' => { 111 => 'MakN', 113 => 0x927c }, + 'makernotehp' => { 111 => 'MakN', 113 => 0x927c }, + 'makernotehp2' => { 111 => 'MakN', 113 => 0x927c }, + 'makernotehp4' => { 111 => 'MakN', 113 => 0x927c }, + 'makernotehp6' => { 111 => 'MakN', 113 => 0x927c }, + 'makernoteisl' => { 111 => 'MakN', 113 => 0x927c }, + 'makernotejvc' => { 111 => 'MakN', 113 => 0x927c }, + 'makernotejvctext' => { 111 => 'MakN', 113 => 0x927c }, + 'makernotekodak10' => { 111 => 'MakN', 113 => 0x927c }, + 'makernotekodak11' => { 111 => 'MakN', 113 => 0x927c }, + 'makernotekodak12' => { 111 => 'MakN', 113 => 0x927c }, + 'makernotekodak1a' => { 111 => 'MakN', 113 => 0x927c }, + 'makernotekodak1b' => { 111 => 'MakN', 113 => 0x927c }, + 'makernotekodak2' => { 111 => 'MakN', 113 => 0x927c }, + 'makernotekodak3' => { 111 => 'MakN', 113 => 0x927c }, + 'makernotekodak4' => { 111 => 'MakN', 113 => 0x927c }, + 'makernotekodak5' => { 111 => 'MakN', 113 => 0x927c }, + 'makernotekodak6a' => { 111 => 'MakN', 113 => 0x927c }, + 'makernotekodak6b' => { 111 => 'MakN', 113 => 0x927c }, + 'makernotekodak7' => { 111 => 'MakN', 113 => 0x927c }, + 'makernotekodak8a' => { 111 => 'MakN', 113 => 0x927c }, + 'makernotekodak8b' => { 111 => 'MakN', 113 => 0x927c }, + 'makernotekodak8c' => { 111 => 'MakN', 113 => 0x927c }, + 'makernotekodak9' => { 111 => 'MakN', 113 => 0x927c }, + 'makernotekodakunknown' => { 111 => 'MakN', 113 => 0x927c }, + 'makernotekyocera' => { 111 => 'MakN', 113 => 0x927c }, + 'makernoteleica' => { 111 => 'MakN', 113 => 0x927c }, + 'makernoteleica10' => { 111 => 'MakN', 113 => 0x927c }, + 'makernoteleica2' => { 111 => 'MakN', 113 => 0x927c }, + 'makernoteleica3' => { 111 => 'MakN', 113 => 0x927c }, + 'makernoteleica4' => { 111 => 'MakN', 113 => 0x927c }, + 'makernoteleica5' => { 111 => 'MakN', 113 => 0x927c }, + 'makernoteleica6' => { 111 => 'MakN', 113 => 0x927c }, + 'makernoteleica7' => { 111 => 'MakN', 113 => 0x927c }, + 'makernoteleica8' => { 111 => 'MakN', 113 => 0x927c }, + 'makernoteleica9' => { 111 => 'MakN', 113 => 0x927c }, + 'makernoteminolta' => { 111 => 'MakN', 113 => 0x927c }, + 'makernoteminolta2' => { 111 => 'MakN', 113 => 0x927c }, + 'makernoteminolta3' => { 111 => 'MakN', 113 => 0x927c }, + 'makernotemotorola' => { 111 => 'MakN', 113 => 0x927c }, + 'makernotenikon' => { 111 => 'MakN', 113 => 0x927c }, + 'makernotenikon2' => { 111 => 'MakN', 113 => 0x927c }, + 'makernotenikon3' => { 111 => 'MakN', 113 => 0x927c }, + 'makernotenintendo' => { 111 => 'MakN', 113 => 0x927c }, + 'makernoteoffset' => { 372 => 0xff }, + 'makernoteolympus' => { 111 => 'MakN', 113 => 0x927c }, + 'makernoteolympus2' => { 111 => 'MakN', 113 => 0x927c }, + 'makernotepanasonic' => { 111 => 'MakN', 113 => 0x927c }, + 'makernotepanasonic2' => { 111 => 'MakN', 113 => 0x927c }, + 'makernotepanasonic3' => { 111 => 'MakN', 113 => 0x927c }, + 'makernotepentax' => { 111 => 'MakN', 113 => 0x927c }, + 'makernotepentax2' => { 111 => 'MakN', 113 => 0x927c }, + 'makernotepentax3' => { 111 => 'MakN', 113 => 0x927c }, + 'makernotepentax4' => { 111 => 'MakN', 113 => 0x927c }, + 'makernotepentax5' => { 111 => 'MakN', 113 => 0x927c }, + 'makernotepentax6' => { 111 => 'MakN', 113 => 0x927c }, + 'makernotephaseone' => { 111 => 'MakN', 113 => 0x927c }, + 'makernotereconyx' => { 111 => 'MakN', 113 => 0x927c }, + 'makernotereconyx2' => { 111 => 'MakN', 113 => 0x927c }, + 'makernotereconyx3' => { 111 => 'MakN', 113 => 0x927c }, + 'makernotericoh' => { 111 => 'MakN', 113 => 0x927c }, + 'makernotericoh2' => { 111 => 'MakN', 113 => 0x927c }, + 'makernotericohpentax' => { 111 => 'MakN', 113 => 0x927c }, + 'makernotericohtext' => { 111 => 'MakN', 113 => 0x927c }, + 'makernotesafety' => { 113 => 0xc635 }, + 'makernotesamsung1a' => { 111 => 'MakN', 113 => 0x927c }, + 'makernotesamsung1b' => { 111 => 'MakN', 113 => 0x927c }, + 'makernotesamsung2' => { 111 => 'MakN', 113 => 0x927c }, + 'makernotesanyo' => { 111 => 'MakN', 113 => 0x927c }, + 'makernotesanyoc4' => { 111 => 'MakN', 113 => 0x927c }, + 'makernotesanyopatch' => { 111 => 'MakN', 113 => 0x927c }, + 'makernotesigma' => { 111 => 'MakN', 113 => 0x927c }, + 'makernotesony' => { 111 => 'MakN', 113 => 0x927c }, + 'makernotesony2' => { 111 => 'MakN', 113 => 0x927c }, + 'makernotesony3' => { 111 => 'MakN', 113 => 0x927c }, + 'makernotesony4' => { 111 => 'MakN', 113 => 0x927c }, + 'makernotesony5' => { 111 => 'MakN', 113 => 0x927c }, + 'makernotesonyericsson' => { 111 => 'MakN', 113 => 0x927c }, + 'makernotesonysrf' => { 111 => 'MakN', 113 => 0x927c }, + 'makernotetype' => { 363 => 0x1 }, + 'makernoteunknown' => { 111 => 'MakN', 113 => 0x927c }, + 'makernoteunknownbinary' => { 111 => 'MakN', 113 => 0x927c }, + 'makernoteunknowntext' => { 111 => 'MakN', 113 => 0x927c }, + 'makernoteversion' => { 176 => 0x0, 214 => 0x1, 283 => 0x0, 301 => 0x8000, 367 => 0x0, 370 => 0x1, 373 => [0x1d,0x1f], 384 => 0x2000 }, + 'managedfrom' => { 473 => 'ManagedFrom' }, + 'managedfromalternatepaths' => { 473 => [\'ManagedFrom','ManagedFromAlternatePaths'] }, + 'managedfromdocumentid' => { 473 => [\'ManagedFrom','ManagedFromDocumentID'] }, + 'managedfromfilepath' => { 473 => [\'ManagedFrom','ManagedFromFilePath'] }, + 'managedfromfrompart' => { 473 => [\'ManagedFrom','ManagedFromFromPart'] }, + 'managedfrominstanceid' => { 473 => [\'ManagedFrom','ManagedFromInstanceID'] }, + 'managedfromlastmodifydate' => { 473 => [\'ManagedFrom','ManagedFromLastModifyDate'] }, + 'managedfromlasturl' => { 473 => [\'ManagedFrom','ManagedFromLastURL'] }, + 'managedfromlinkcategory' => { 473 => [\'ManagedFrom','ManagedFromLinkCategory'] }, + 'managedfromlinkform' => { 473 => [\'ManagedFrom','ManagedFromLinkForm'] }, + 'managedfrommanager' => { 473 => [\'ManagedFrom','ManagedFromManager'] }, + 'managedfrommanagervariant' => { 473 => [\'ManagedFrom','ManagedFromManagerVariant'] }, + 'managedfrommanageto' => { 473 => [\'ManagedFrom','ManagedFromManageTo'] }, + 'managedfrommanageui' => { 473 => [\'ManagedFrom','ManagedFromManageUI'] }, + 'managedfrommaskmarkers' => { 473 => [\'ManagedFrom','ManagedFromMaskMarkers'] }, + 'managedfromoriginaldocumentid' => { 473 => [\'ManagedFrom','ManagedFromOriginalDocumentID'] }, + 'managedfrompartmapping' => { 473 => [\'ManagedFrom','ManagedFromPartMapping'] }, + 'managedfromplacedresolutionunit' => { 473 => [\'ManagedFrom','ManagedFromPlacedResolutionUnit'] }, + 'managedfromplacedxresolution' => { 473 => [\'ManagedFrom','ManagedFromPlacedXResolution'] }, + 'managedfromplacedyresolution' => { 473 => [\'ManagedFrom','ManagedFromPlacedYResolution'] }, + 'managedfromrenditionclass' => { 473 => [\'ManagedFrom','ManagedFromRenditionClass'] }, + 'managedfromrenditionparams' => { 473 => [\'ManagedFrom','ManagedFromRenditionParams'] }, + 'managedfromtopart' => { 473 => [\'ManagedFrom','ManagedFromToPart'] }, + 'managedfromversionid' => { 473 => [\'ManagedFrom','ManagedFromVersionID'] }, + 'manager' => { 473 => 'Manager' }, + 'managervariant' => { 473 => 'ManagerVariant' }, + 'manageto' => { 473 => 'ManageTo' }, + 'manageui' => { 473 => 'ManageUI' }, + 'manifest' => { 473 => 'Manifest' }, + 'manifestlinkform' => { 473 => [\'Manifest','ManifestLinkForm'] }, + 'manifestplacedresolutionunit' => { 473 => [\'Manifest','ManifestPlacedResolutionUnit'] }, + 'manifestplacedxresolution' => { 473 => [\'Manifest','ManifestPlacedXResolution'] }, + 'manifestplacedyresolution' => { 473 => [\'Manifest','ManifestPlacedYResolution'] }, + 'manifestreference' => { 473 => [\'Manifest','ManifestReference'] }, + 'manifestreferencealternatepaths' => { 473 => [\'Manifest','ManifestReferenceAlternatePaths'] }, + 'manifestreferencedocumentid' => { 473 => [\'Manifest','ManifestReferenceDocumentID'] }, + 'manifestreferencefilepath' => { 473 => [\'Manifest','ManifestReferenceFilePath'] }, + 'manifestreferencefrompart' => { 473 => [\'Manifest','ManifestReferenceFromPart'] }, + 'manifestreferenceinstanceid' => { 473 => [\'Manifest','ManifestReferenceInstanceID'] }, + 'manifestreferencelastmodifydate' => { 473 => [\'Manifest','ManifestReferenceLastModifyDate'] }, + 'manifestreferencelasturl' => { 473 => [\'Manifest','ManifestReferenceLastURL'] }, + 'manifestreferencelinkcategory' => { 473 => [\'Manifest','ManifestReferenceLinkCategory'] }, + 'manifestreferencelinkform' => { 473 => [\'Manifest','ManifestReferenceLinkForm'] }, + 'manifestreferencemanager' => { 473 => [\'Manifest','ManifestReferenceManager'] }, + 'manifestreferencemanagervariant' => { 473 => [\'Manifest','ManifestReferenceManagerVariant'] }, + 'manifestreferencemanageto' => { 473 => [\'Manifest','ManifestReferenceManageTo'] }, + 'manifestreferencemanageui' => { 473 => [\'Manifest','ManifestReferenceManageUI'] }, + 'manifestreferencemaskmarkers' => { 473 => [\'Manifest','ManifestReferenceMaskMarkers'] }, + 'manifestreferenceoriginaldocumentid' => { 473 => [\'Manifest','ManifestReferenceOriginalDocumentID'] }, + 'manifestreferencepartmapping' => { 473 => [\'Manifest','ManifestReferencePartMapping'] }, + 'manifestreferenceplacedresolutionunit' => { 473 => [\'Manifest','ManifestReferencePlacedResolutionUnit'] }, + 'manifestreferenceplacedxresolution' => { 473 => [\'Manifest','ManifestReferencePlacedXResolution'] }, + 'manifestreferenceplacedyresolution' => { 473 => [\'Manifest','ManifestReferencePlacedYResolution'] }, + 'manifestreferencerenditionclass' => { 473 => [\'Manifest','ManifestReferenceRenditionClass'] }, + 'manifestreferencerenditionparams' => { 473 => [\'Manifest','ManifestReferenceRenditionParams'] }, + 'manifestreferencetopart' => { 473 => [\'Manifest','ManifestReferenceToPart'] }, + 'manifestreferenceversionid' => { 473 => [\'Manifest','ManifestReferenceVersionID'] }, + 'manometerpressure' => { 278 => 0x900, 301 => 0x86 }, + 'manometerreading' => { 278 => 0x901 }, + 'manualafpointselectpattern' => { 78 => 0x513 }, + 'manualafpointselpattern' => { 2 => 0xf }, + 'manualflash' => { 281 => 0x1209 }, + 'manualflashoutput' => { 33 => 0x29, 263 => '8.2', 266 => '22.2', 267 => '23.1', 268 => '23.2', 270 => '16.2', 271 => '23.2', 272 => '8.2', 273 => '23.2', 276 => '24.2', 363 => 0x100c }, + 'manualflashstrength' => { 278 => 0x406 }, + 'manualfocusdistance' => { 214 => 0x85, 283 => 0x100c, 372 => 0x223 }, + 'manualtv' => { 77 => 0x5, 78 => 0x705 }, + 'manufacturedate' => { 181 => 0x6705, 316 => 0x1 }, + 'manufacturedate1' => { 365 => 0x4 }, + 'manufacturedate2' => { 365 => 0x5 }, + 'manufacturer' => { 432 => 'Manufacturer', 461 => 'manufacturer' }, + 'mariahchromablursize' => { 131 => 0xf0d }, + 'mariahmaphithreshold' => { 131 => 0xf0c }, + 'mariahmaplothreshold' => { 131 => 0xf0b }, + 'mariahsigmathreshold' => { 131 => 0xf0e }, + 'mariahtexturethreshold' => { 131 => 0xf0a }, + 'marked' => { 459 => 'Marked', 476 => 'Marked' }, + 'markers' => { 472 => 'markers' }, + 'markerscomment' => { 472 => [\'markers','markersComment'] }, + 'markerscuepointparams' => { 472 => [\'markers','markersCuePointParams'] }, + 'markerscuepointparamskey' => { 472 => [\'markers','markersCuePointParamsKey'] }, + 'markerscuepointparamsvalue' => { 472 => [\'markers','markersCuePointParamsValue'] }, + 'markerscuepointtype' => { 472 => [\'markers','markersCuePointType'] }, + 'markersduration' => { 472 => [\'markers','markersDuration'] }, + 'markerslocation' => { 472 => [\'markers','markersLocation'] }, + 'markersname' => { 472 => [\'markers','markersName'] }, + 'markersprobability' => { 472 => [\'markers','markersProbability'] }, + 'markersspeaker' => { 472 => [\'markers','markersSpeaker'] }, + 'markersstarttime' => { 472 => [\'markers','markersStartTime'] }, + 'markerstarget' => { 472 => [\'markers','markersTarget'] }, + 'markerstype' => { 472 => [\'markers','markersType'] }, + 'maskedareas' => { 113 => 0xc68e }, + 'masterdocumentid' => { 125 => 0xb9 }, + 'mastergain' => { 222 => 0x50 }, + 'materialsample' => { 112 => 'MaterialSample' }, + 'materialsampleid' => { 112 => [\'MaterialSample','MaterialSampleMaterialSampleID'] }, + 'matrixmetering' => { 262 => '50.1', 264 => '48.1', 265 => '48.1', 274 => '48.1', 275 => '48.1' }, + 'matrixselectk' => { 131 => 0x91b }, + 'matrixselectthreshold' => { 131 => 0x91a }, + 'matrixselectthreshold1' => { 131 => 0x91e }, + 'matrixselectthreshold2' => { 131 => 0x91f }, + 'matrixstructure' => { 356 => 0xa }, + 'maxaperture' => { 33 => 0x1a, 131 => 0x3f9, 137 => 0x6103, 154 => 'MaxAperture', 171 => 0x17, 177 => 0x49c5, 212 => 0x36, 279 => 0x20a, 327 => '14.1' }, + 'maxapertureatmaxfocal' => { 121 => 0x1407, 154 => 'MaxApertureAtMaxFocal', 206 => 0xb, 207 => 0x10, 208 => 0x11, 212 => 0x12, 279 => 0x206 }, + 'maxapertureatminfocal' => { 121 => 0x1406, 206 => 0xa, 207 => 0xf, 208 => 0x10, 212 => 0x11, 279 => 0x205 }, + 'maxaperturevalue' => { 113 => 0x9205, 345 => 0x414, 452 => 'MaxApertureValue' }, + 'maxavailheight' => { 458 => 'MaxAvailHeight' }, + 'maxavailwidth' => { 458 => 'MaxAvailWidth' }, + 'maxcontinuousrelease' => { 261 => 0xb, 262 => 0xc, 264 => '12.1', 265 => '12.1', 270 => 0xc, 271 => 0xb, 274 => '12.1', 275 => '12.1' }, + 'maxfaces' => { 282 => 0x1202 }, + 'maxfocallength' => { 6 => 0xe6, 7 => 0x10, 8 => 0x1ab, 9 => 0x13, 10 => 0x115, 11 => 0x13, 12 => 0x153, 13 => 0xda, 15 => 0xfa, 16 => 0xee, 17 => 0x103, 18 => 0x95, 19 => 0xea, 20 => 0x157, 21 => 0xee, 22 => 0xec, 23 => 0x12b, 24 => 0x165, 25 => 0x16a, 26 => 0x188, 27 => 0x116, 28 => 0x18d, 33 => 0x17, 121 => 0x1405, 154 => 'MaxFocalLength', 206 => 0x9, 207 => 0xe, 208 => 0xf, 212 => 0x10, 279 => 0x208, 406 => 0x127c, 407 => 0x1138, 408 => 0x330, 409 => 0x330, 410 => 0x30e }, + 'maximumdensityrange' => { 127 => 0x8c }, + 'maxpagesize' => { 477 => 'MaxPageSize' }, + 'maxpagesizeh' => { 477 => [\'MaxPageSize','MaxPageSizeH'] }, + 'maxpagesizeunit' => { 477 => [\'MaxPageSize','MaxPageSizeUnit'] }, + 'maxpagesizew' => { 477 => [\'MaxPageSize','MaxPageSizeW'] }, + 'maxpixelvaluethreshold' => { 131 => 0xc7d }, + 'maxsamplevalue' => { 113 => 0x119 }, + 'maxstorage' => { 467 => 'maxstorage' }, + 'mb-d10batteries' => { 261 => '12.6' }, + 'mb-d10batterytype' => { 270 => '13.3' }, + 'mb-d11batterytype' => { 271 => '2.3' }, + 'mb-d12batterytype' => { 274 => '3.2' }, + 'mb-d80batteries' => { 272 => '6.5' }, + 'mb-d80batterytype' => { 276 => '3.2' }, + 'mcuversion' => { 206 => 0xc, 207 => 0x11, 208 => 0x12, 212 => 0x13 }, + 'md5digest' => { 155 => 'zmd5' }, + 'mditemfindercomment' => { 164 => 'MDItemFinderComment' }, + 'mditemfscreationdate' => { 164 => 'MDItemFSCreationDate' }, + 'mditemfslabel' => { 164 => 'MDItemFSLabel' }, + 'mditemusertags' => { 164 => 'MDItemUserTags' }, + 'meal' => { 464 => 'meal' }, + 'measuredev' => { 27 => 0x9, 72 => 0x3, 91 => 0x1814, 147 => 'MeasuredEV' }, + 'measuredev2' => { 12 => 0x8, 27 => 0x8, 72 => 0x17 }, + 'measuredev3' => { 12 => 0x9 }, + 'measuredlv' => { 177 => 0x690, 296 => 0x312, 299 => 0x312, 300 => 0x312, 303 => 0x3407 }, + 'measuredrggb' => { 61 => 0x1 }, + 'measuredrggbdata' => { 41 => 0x287 }, + 'measurementaccuracy' => { 112 => [\'MeasurementOrFact','MeasurementOrFactMeasurementAccuracy'] }, + 'measurementdeterminedby' => { 112 => [\'MeasurementOrFact','MeasurementOrFactMeasurementDeterminedBy'] }, + 'measurementdetermineddate' => { 112 => [\'MeasurementOrFact','MeasurementOrFactMeasurementDeterminedDate'] }, + 'measurementid' => { 112 => [\'MeasurementOrFact','MeasurementOrFactMeasurementID'] }, + 'measurementmethod' => { 112 => [\'MeasurementOrFact','MeasurementOrFactMeasurementMethod'] }, + 'measurementorfact' => { 112 => 'MeasurementOrFact' }, + 'measurementremarks' => { 112 => [\'MeasurementOrFact','MeasurementOrFactMeasurementRemarks'] }, + 'measurementtype' => { 112 => [\'MeasurementOrFact','MeasurementOrFactMeasurementType'] }, + 'measurementunit' => { 112 => [\'MeasurementOrFact','MeasurementOrFactMeasurementUnit'] }, + 'measurementvalue' => { 112 => [\'MeasurementOrFact','MeasurementOrFactMeasurementValue'] }, + 'measuretype' => { 432 => 'MeasureType' }, + 'mechanicalshuttercount' => { 214 => 0x37 }, + 'mediaconstraints' => { 288 => 'MediaConstraints' }, + 'mediacreatedate' => { 353 => 0x1 }, + 'mediaeventiddate' => { 437 => 'MediaEventIdDate' }, + 'mediamodifydate' => { 353 => 0x2 }, + 'mediasummarycode' => { 288 => 'MediaSummaryCode' }, + 'memoaudioquality' => { 78 => 0x812 }, + 'memorycardconfiguration' => { 387 => 0x16 }, + 'memorycardnumber' => { 197 => 0x2 }, + 'menubuttondisplayposition' => { 76 => 0xb, 79 => 0xa, 80 => 0xb, 83 => 0xb }, + 'menubuttonreturn' => { 84 => 0xb }, + 'menumonitorofftime' => { 261 => '26.1', 262 => '22.1', 264 => '22.1', 265 => '22.1', 269 => '21.1', 270 => '8.2', 271 => '21.1', 274 => '22.1', 275 => '22.1', 276 => '22.1' }, + 'metadatadate' => { 470 => 'MetadataDate' }, + 'metadatamoddate' => { 472 => 'metadataModDate' }, + 'metaversion' => { 401 => 0x34 }, + 'meterinfo1row1' => { 395 => 0x0, 396 => 0x0 }, + 'meterinfo1row2' => { 395 => 0x6c, 396 => 0x5a }, + 'meterinfo1row3' => { 395 => 0xd8, 396 => 0xb4 }, + 'meterinfo1row4' => { 395 => 0x144, 396 => 0x10e }, + 'meterinfo1row5' => { 395 => 0x1b0, 396 => 0x168 }, + 'meterinfo1row6' => { 395 => 0x21c, 396 => 0x1c2 }, + 'meterinfo1row7' => { 395 => 0x288, 396 => 0x21c }, + 'meterinfo2row1' => { 395 => 0x2f4, 396 => 0x276 }, + 'meterinfo2row2' => { 395 => 0x378, 396 => 0x2e4 }, + 'meterinfo2row3' => { 395 => 0x3fc, 396 => 0x352 }, + 'meterinfo2row4' => { 395 => 0x480, 396 => 0x3c0 }, + 'meterinfo2row5' => { 395 => 0x504, 396 => 0x42e }, + 'meterinfo2row6' => { 395 => 0x588, 396 => 0x49c }, + 'meterinfo2row7' => { 395 => 0x60c, 396 => 0x50a }, + 'meterinfo2row8' => { 395 => 0x690, 396 => 0x578 }, + 'meterinfo2row9' => { 395 => 0x714, 396 => 0x5e6 }, + 'metering' => { 263 => '6.1' }, + 'meteringmode' => { 33 => 0x11, 113 => 0x9207, 133 => 0x1c, 171 => 0x7, 172 => 0x25, 174 => 0x12, 278 => 0x202, 336 => 0x17, 373 => 0x9, 381 => 0x15, 382 => 0x13, 383 => 0x7, 399 => 0x3, 402 => 0x1174, 403 => 0x1178, 404 => 0x1154, 405 => 0x11d0, 406 => 0x11ac, 407 => 0x1064, 408 => 0x25c, 409 => 0x25c, 410 => 0x24b, 452 => 'MeteringMode' }, + 'meteringmode2' => { 317 => '2.1', 394 => 0x202c }, + 'meteringmode3' => { 317 => '16.1' }, + 'meteringoffscaleindicator' => { 174 => 0x53 }, + 'meteringtime' => { 261 => '22.2', 263 => '3.2', 266 => '17.1', 267 => '18.1', 270 => '7.3', 271 => '18.1', 272 => '3.2', 276 => '19.1' }, + 'micro1version' => { 358 => 0x1f }, + 'micro2version' => { 358 => 0x2d }, + 'midrangesharpness' => { 218 => 0x3b }, + 'mieversion' => { 155 => '0Vers' }, + 'mime' => { 432 => 'Mime' }, + 'minaperture' => { 33 => 0x1b, 131 => 0x3f8, 154 => 'MinAperture', 327 => '0.2' }, + 'minaperturevalue' => { 345 => 0x415 }, + 'minfocallength' => { 6 => 0xe4, 7 => 0xe, 8 => 0x1a9, 9 => 0x11, 10 => 0x113, 11 => 0x11, 12 => 0x151, 13 => 0xd8, 15 => 0xf8, 16 => 0xec, 17 => 0x101, 18 => 0x93, 19 => 0xe8, 20 => 0x155, 21 => 0xec, 22 => 0xea, 23 => 0x129, 24 => 0x163, 25 => 0x168, 26 => 0x186, 27 => 0x114, 28 => 0x18b, 33 => 0x18, 121 => 0x1404, 154 => 'MinFocalLength', 206 => 0x8, 207 => 0xd, 208 => 0xe, 212 => 0xf, 279 => 0x207, 406 => 0x127a, 407 => 0x1136, 408 => 0x32e, 409 => 0x32e, 410 => 0x30c }, + 'minfocusdistance' => { 327 => 0x3 }, + 'minintegrationrows' => { 131 => 0x1874 }, + 'minoltadate' => { 171 => 0x15 }, + 'minoltaimagesize' => { 171 => 0x4, 172 => 0xc, 173 => 0x2, 176 => 0x103 }, + 'minoltamodelid' => { 171 => 0x25 }, + 'minoltaquality' => { 171 => 0x5, 172 => 0xd, 173 => 0x3, 176 => [0x102,0x103] }, + 'minoltatime' => { 171 => 0x16 }, + 'minormodelagedisclosure' => { 288 => 'MinorModelAgeDisclosure' }, + 'minorversion' => { 438 => 'MinorVersion' }, + 'minsamplevalue' => { 113 => 0x118 }, + 'mirrorlockup' => { 76 => 0xc, 77 => 0xc, 78 => 0x60f, 79 => 0xb, 80 => 0xc, 81 => 0x6, 82 => 0x6, 83 => 0xc, 84 => 0x3 }, + 'mobilecountrycode' => { 446 => 'mcc' }, + 'mobilenetworkcode' => { 446 => 'mnc' }, + 'moddate' => { 291 => 'modify-date', 459 => 'ModDate' }, + 'modedialposition' => { 387 => 0x14 }, + 'model' => { 92 => 0x6, 113 => 0x110, 147 => 'Model', 291 => 'Model', 306 => 0x110, 336 => 0x23f, 373 => 0x84, 432 => 'Model', 461 => 'model', 468 => 'Model' }, + 'modelage' => { 458 => 'ModelAge' }, + 'modelid' => { 277 => 0x0 }, + 'modelingflash' => { 261 => '21.4', 262 => '31.1', 264 => '31.1', 265 => '31.1', 270 => '26.4', 271 => '30.2', 272 => '7.4', 273 => '30.1', 274 => '31.1', 275 => '31.1', 276 => '31.3' }, + 'modelreleaseid' => { 288 => 'ModelReleaseID' }, + 'modelreleasestatus' => { 288 => 'ModelReleaseStatus' }, + 'modelreleaseyear' => { 414 => 0x52, 415 => 0x46, 416 => 0x53 }, + 'modeltiepoint' => { 113 => 0x8482 }, + 'modeltransform' => { 113 => 0x85d8 }, + 'modelyear' => { 461 => 'modelYear' }, + 'modificationdate' => { 462 => 'modificationDate' }, + 'modifiedcolortemp' => { 62 => 0x9 }, + 'modifieddigitalgain' => { 62 => 0xb }, + 'modifiedparamflag' => { 55 => 0x1 }, + 'modifiedpicturestyle' => { 62 => 0xa }, + 'modifiedsaturation' => { 278 => 0x504 }, + 'modifiedsensorbluelevel' => { 62 => 0x5 }, + 'modifiedsensorredlevel' => { 62 => 0x4 }, + 'modifiedsharpness' => { 62 => 0x2 }, + 'modifiedsharpnessfreq' => { 62 => 0x3 }, + 'modifiedtonecurve' => { 62 => 0x1 }, + 'modifiedwhitebalance' => { 62 => 0x8 }, + 'modifiedwhitebalanceblue' => { 62 => 0x7 }, + 'modifiedwhitebalancered' => { 62 => 0x6 }, + 'modifydate' => { 113 => 0x132, 148 => 'ModifyDate', 287 => 'ModDate', 289 => 'tIME', 352 => 'ModDate', 354 => 0x2, 470 => 'ModifyDate' }, + 'moirefilter' => { 113 => 0xfe58, 448 => 'MoireFilter' }, + 'monitordisplayoff' => { 174 => 0x4c }, + 'monitormatrix' => { 131 => 0x8fc }, + 'monitorofftime' => { 261 => '18.2', 263 => '3.1', 272 => '3.1' }, + 'monochromecolor' => { 278 => 0x53b }, + 'monochromecontrast' => { 103 => 0x3c }, + 'monochromefiltereffect' => { 97 => 0x20307, 103 => 0x3a, 336 => 0x73 }, + 'monochromelinear' => { 103 => 0x3d }, + 'monochromeoutputhighlightpoint' => { 103 => 0x41 }, + 'monochromeoutputshadowpoint' => { 103 => 0x42 }, + 'monochromeprofilesettings' => { 278 => 0x537 }, + 'monochromerawhighlight' => { 103 => 0x7a }, + 'monochromerawhighlightpoint' => { 103 => 0x3f }, + 'monochromerawshadow' => { 103 => 0x83 }, + 'monochromerawshadowpoint' => { 103 => 0x40 }, + 'monochromesharpness' => { 103 => 0x3e }, + 'monochrometoning' => { 336 => 0x74 }, + 'monochrometoningeffect' => { 97 => 0x20306, 103 => 0x3b }, + 'monochromeunsharpmaskfineness' => { 103 => 0xb2 }, + 'monochromeunsharpmaskstrength' => { 103 => 0xb0 }, + 'monochromeunsharpmaskthreshold' => { 103 => 0xb4 }, + 'monochromevignetting' => { 278 => 0x53a }, + 'monthdaycreated' => { 133 => 0x12, 142 => 0xe }, + 'moonphase' => { 357 => 0x12, 358 => 0x43, 359 => 0x4c }, + 'morepermissions' => { 445 => 'morePermissions' }, + 'motionsensitivity' => { 357 => 0x29, 359 => 0x60 }, + 'movieaelockbuttonassignment' => { 274 => '40.1' }, + 'moviefunc1button' => { 264 => '41.1', 265 => '41.1', 275 => '41.1' }, + 'moviefunctionbutton' => { 262 => '41.1', 274 => '41.1' }, + 'moviefunctionbuttonplusdials' => { 262 => '52.1' }, + 'moviepreviewbutton' => { 262 => '41.2', 264 => '41.2', 265 => '41.2', 274 => '41.2', 275 => '41.2' }, + 'moviepreviewbuttonplusdials' => { 262 => '52.2' }, + 'movieshutterbutton' => { 262 => '38.3', 264 => '38.3', 265 => '38.3', 274 => '38.3', 275 => '38.3' }, + 'moviesubselectorassignment' => { 262 => '48.2' }, + 'moviesubselectorassignmentplusdials' => { 262 => '53.1' }, + 'multiburstimageheight' => { 394 => 0x1002 }, + 'multiburstimagewidth' => { 394 => 0x1001 }, + 'multiburstmode' => { 394 => 0x1000 }, + 'multicontrollerwhilemetering' => { 78 => 0x517 }, + 'multiexposure' => { 64 => 0x1, 301 => 0xb4 }, + 'multiexposureautogain' => { 215 => 0x3 }, + 'multiexposurecontrol' => { 64 => 0x2 }, + 'multiexposuremode' => { 215 => 0x1 }, + 'multiexposureshots' => { 64 => 0x3, 215 => 0x2 }, + 'multiframenoisereduction' => { 383 => 0x35, 394 => 0x200b, 399 => 0x15 }, + 'multiframenreffect' => { 394 => 0x2023 }, + 'multifunctionlock' => { 78 => 0x70f }, + 'multipleexposuremode' => { 282 => 0x101c }, + 'multipleexposureset' => { 317 => '10.1' }, + 'multisample' => { 222 => 0x40 }, + 'multiselector' => { 261 => '9.4', 262 => '10.3', 264 => '10.3', 265 => '10.3', 270 => '27.4', 274 => '10.3', 275 => '10.3' }, + 'multiselectorliveview' => { 261 => '4.3', 264 => '37.1', 265 => '37.1', 274 => '37.1', 275 => '37.1' }, + 'multiselectorliveviewmode' => { 232 => 0x18c2 }, + 'multiselectorplaybackmode' => { 261 => ['13.5','9.2'], 262 => '10.2', 265 => '10.2', 270 => '27.2', 274 => '10.2', 275 => '10.2' }, + 'multiselectorshootmode' => { 261 => '9.1', 262 => '10.1', 264 => '10.1', 265 => '10.1', 270 => '27.1', 274 => '10.1', 275 => '10.1' }, + 'multishot' => { 306 => 0x121 }, + 'mycolormode' => { 65 => 0x2 }, + 'nationalcatalognumber' => { 462 => 'nationalCatalogNumber' }, + 'nativedigest' => { 452 => 'NativeDigest', 468 => 'NativeDigest' }, + 'ndfilter' => { 72 => 0x1c, 278 => 0x204, 363 => 0x1019 }, + 'near' => { 432 => 'Near' }, + 'nefbitdepth' => { 214 => 0xe22 }, + 'nefcompression' => { 214 => 0x93 }, + 'neflinearizationtable' => { 214 => 0x96 }, + 'negativecachelargepreviewsize' => { 448 => 'NegativeCacheLargePreviewSize' }, + 'negativecachemaximumsize' => { 448 => 'NegativeCacheMaximumSize' }, + 'negativecachepath' => { 448 => 'NegativeCachePath' }, + 'neutraldensityfilter' => { 336 => 0x88 }, + 'neutraloutputhighlightpoint' => { 103 => 0x2f }, + 'neutraloutputshadowpoint' => { 103 => 0x30 }, + 'neutralrawcolortone' => { 103 => 0x28 }, + 'neutralrawcontrast' => { 103 => 0x2a }, + 'neutralrawhighlight' => { 103 => 0x78 }, + 'neutralrawhighlightpoint' => { 103 => 0x2d }, + 'neutralrawlinear' => { 103 => 0x2b }, + 'neutralrawsaturation' => { 103 => 0x29 }, + 'neutralrawshadow' => { 103 => 0x81 }, + 'neutralrawshadowpoint' => { 103 => 0x2e }, + 'neutralrawsharpness' => { 103 => 0x2c }, + 'neutralunsharpmaskfineness' => { 103 => 0xa6 }, + 'neutralunsharpmaskthreshold' => { 103 => 0xa8 }, + 'neutraunsharpmaskstrength' => { 103 => 0xa4 }, + 'newrawimagedigest' => { 113 => 0xc7a7 }, + 'newsphotoversion' => { 127 => 0x0 }, + 'nickname' => { 470 => 'Nickname' }, + 'nikoncapturedata' => { 214 => 0xe01 }, + 'nikoncaptureeditversions' => { 214 => 0xe13 }, + 'nikoncaptureoutput' => { 214 => 0xe1e }, + 'nikoncaptureversion' => { 214 => 0xe09 }, + 'nikoniccprofile' => { 214 => 0xe1d }, + 'nikonimagesize' => { 229 => '723.1', 230 => '732.1', 239 => 0x2c4 }, + 'noisefilter' => { 278 => 0x527 }, + 'noiseprofile' => { 113 => 0xc761 }, + 'noisereduction' => { 121 => [0x100b,0x100e], 172 => 0xb0, 173 => 0x60, 174 => 0x3f, 214 => 0x95, 254 => 0x753dcbc0, 255 => 0x17, 278 => 0x50a, 283 => 0x103a, 301 => 0x2d, 336 => 0x49, 363 => 0x100f, 365 => 0x2a }, + 'noisereduction2' => { 282 => 0x1010 }, + 'noisereductionapplied' => { 113 => 0xc6f7 }, + 'noisereductionintensity' => { 255 => 0x9 }, + 'noisereductionmethod' => { 255 => 0x11 }, + 'noisereductionmode' => { 427 => 0x801e }, + 'noisereductionparametersatcapture' => { 131 => 0xe73 }, + 'noisereductionparameterscamera' => { 131 => 0xe72 }, + 'noisereductionparametershost3mp' => { 131 => 0xe71 }, + 'noisereductionparametershost6mp' => { 131 => 0xe70 }, + 'noisereductionparametershostrgb' => { 131 => 0xe6f }, + 'noisereductionparameterskhufu3mp' => { 131 => 0xe65 }, + 'noisereductionparameterskhufu6mp' => { 131 => 0xe64 }, + 'noisereductionparameterskhufurgb' => { 131 => 0xe63 }, + 'noisereductionparams' => { 306 => 0x1b }, + 'noisereductionsharpness' => { 255 => 0xd }, + 'noisereductionvalue' => { 427 => 0x8027 }, + 'nomemorycard' => { 261 => '22.1', 262 => '4.2', 263 => '0.3', 266 => '2.4', 267 => '3.2', 268 => '3.2', 270 => '33.7', 271 => '3.2', 272 => '0.3', 274 => '4.2', 276 => '4.5' }, + 'nominalmaxaperture' => { 327 => 0xa }, + 'nominalminaperture' => { 327 => '10.1' }, + 'normallinetime' => { 131 => 0x186a }, + 'normalwhitelevel' => { 42 => [0x2b8,0x2cf,0x2d3], 44 => 0x1e3, 45 => [0x1fc,0x2dc], 46 => [0x230,0x30e], 47 => 0x31c }, + 'notes' => { 428 => 'Notes', 442 => 'notes' }, + 'npages' => { 477 => 'NPages' }, + 'nullrecord' => { 91 => 0x0 }, + 'numafpoints' => { 313 => 0x2 }, + 'number' => { 462 => 'number' }, + 'numberofbeats' => { 472 => 'numberOfBeats' }, + 'numberoffocuspoints' => { 264 => '1.2', 265 => '1.2', 268 => '0.2', 269 => '0.3', 271 => '0.3' }, + 'numfaceelements' => { 121 => 0x4200 }, + 'numfacepositions' => { 293 => 0x0 }, + 'numindexentries' => { 127 => 0x54 }, + 'numwbentries' => { 307 => 0x0, 308 => 0x0 }, + 'object' => { 462 => 'object' }, + 'objectattributereference' => { 125 => 0x4 }, + 'objectcycle' => { 125 => 0x4b, 442 => 'ObjectCycle' }, + 'objectdescription' => { 461 => 'objectDescription' }, + 'objectdistance' => { 106 => 0x6, 107 => 0x2022 }, + 'objectname' => { 125 => 0x5 }, + 'objectpreviewdata' => { 125 => 0xca }, + 'objectpreviewfileformat' => { 125 => 0xc8 }, + 'objectpreviewfileversion' => { 125 => 0xc9 }, + 'objectsubtype' => { 461 => 'objectSubtype' }, + 'objecttype' => { 461 => 'objectType' }, + 'objecttypereference' => { 125 => 0x3 }, + 'occurrence' => { 112 => 'Occurrence' }, + 'occurrenceassociatedmedia' => { 112 => [\'Occurrence','OccurrenceAssociatedMedia'] }, + 'occurrenceassociatedoccurrences' => { 112 => [\'Occurrence','OccurrenceAssociatedOccurrences'] }, + 'occurrenceassociatedreferences' => { 112 => [\'Occurrence','OccurrenceAssociatedReferences'] }, + 'occurrenceassociatedsequences' => { 112 => [\'Occurrence','OccurrenceAssociatedSequences'] }, + 'occurrenceassociatedtaxa' => { 112 => [\'Occurrence','OccurrenceAssociatedTaxa'] }, + 'occurrencebehavior' => { 112 => [\'Occurrence','OccurrenceBehavior'] }, + 'occurrencecatalognumber' => { 112 => [\'Occurrence','OccurrenceCatalogNumber'] }, + 'occurrencedetails' => { 112 => [\'Occurrence','OccurrenceOccurrenceDetails'] }, + 'occurrencedisposition' => { 112 => [\'Occurrence','OccurrenceDisposition'] }, + 'occurrenceestablishmentmeans' => { 112 => [\'Occurrence','OccurrenceEstablishmentMeans'] }, + 'occurrenceid' => { 112 => [\'Occurrence','OccurrenceOccurrenceID'] }, + 'occurrenceindividualcount' => { 112 => [\'Occurrence','OccurrenceIndividualCount'] }, + 'occurrenceindividualid' => { 112 => [\'Occurrence','OccurrenceIndividualID'] }, + 'occurrencelifestage' => { 112 => [\'Occurrence','OccurrenceLifeStage'] }, + 'occurrenceorganismquantity' => { 112 => [\'Occurrence','OccurrenceOrganismQuantity'] }, + 'occurrenceorganismquantitytype' => { 112 => [\'Occurrence','OccurrenceOrganismQuantityType'] }, + 'occurrenceothercatalognumbers' => { 112 => [\'Occurrence','OccurrenceOtherCatalogNumbers'] }, + 'occurrencepreparations' => { 112 => [\'Occurrence','OccurrencePreparations'] }, + 'occurrencepreviousidentifications' => { 112 => [\'Occurrence','OccurrencePreviousIdentifications'] }, + 'occurrencerecordedby' => { 112 => [\'Occurrence','OccurrenceRecordedBy'] }, + 'occurrencerecordnumber' => { 112 => [\'Occurrence','OccurrenceRecordNumber'] }, + 'occurrenceremarks' => { 112 => [\'Occurrence','OccurrenceOccurrenceRemarks'] }, + 'occurrencereproductivecondition' => { 112 => [\'Occurrence','OccurrenceReproductiveCondition'] }, + 'occurrencesex' => { 112 => [\'Occurrence','OccurrenceSex'] }, + 'occurrencestatus' => { 112 => [\'Occurrence','OccurrenceOccurrenceStatus'] }, + 'oecfcolumns' => { 452 => [\'OECF','OECFColumns'] }, + 'oecfnames' => { 452 => [\'OECF','OECFNames'] }, + 'oecfrows' => { 452 => [\'OECF','OECFRows'] }, + 'oecfvalues' => { 452 => [\'OECF','OECFValues'] }, + 'offsaledate' => { 462 => 'offSaleDate' }, + 'offsaledatea-platform' => { 462 => [\'offSaleDate','offSaleDateA-platform'] }, + 'offsaledatedate' => { 462 => [\'offSaleDate','offSaleDateDate'] }, + 'offsetdacvalue' => { 131 => 0x190a }, + 'offsetschema' => { 113 => 0xea1d }, + 'offsettime' => { 113 => 0x9010 }, + 'offsettimedigitized' => { 113 => 0x9012 }, + 'offsettimeoriginal' => { 113 => 0x9011 }, + 'okbutton' => { 271 => '15.1', 276 => '16.1' }, + 'oldsubfiletype' => { 113 => 0xff }, + 'olympusimageheight' => { 283 => 0x102f }, + 'olympusimagewidth' => { 283 => 0x102e }, + 'omenatcapturestrength' => { 131 => 0xa60 }, + 'omenautostrength' => { 131 => 0xa5f }, + 'omenearlystrength' => { 131 => 0xa5e }, + 'omenfocallengthlimit' => { 131 => 0xa62 }, + 'omeninitialipfstrength' => { 131 => 0xa5d }, + 'omensurfaceindex' => { 131 => 0xa64 }, + 'oneshotafrelease' => { 2 => 0x9 }, + 'onetouchwb' => { 283 => 0x302 }, + 'onsaledate' => { 462 => 'onSaleDate' }, + 'onsaledatea-platform' => { 462 => [\'onSaleDate','onSaleDateA-platform'] }, + 'onsaledatedate' => { 462 => [\'onSaleDate','onSaleDateDate'] }, + 'onsaleday' => { 462 => 'onSaleDay' }, + 'onsaledaya-platform' => { 462 => [\'onSaleDay','onSaleDayA-platform'] }, + 'onsaledayday' => { 462 => [\'onSaleDay','onSaleDayDay'] }, + 'opcodelist1' => { 113 => 0xc740 }, + 'opcodelist2' => { 113 => 0xc741 }, + 'opcodelist3' => { 113 => 0xc74e }, + 'opticalzoom' => { 135 => 0xfa3d, 137 => [0x6006,0xf006], 138 => 0x1000, 139 => 0xf, 142 => 0x1e, 154 => 'OpticalZoom' }, + 'opticalzoomcode' => { 72 => 0xa }, + 'opticalzoommode' => { 301 => 0x34 }, + 'opticalzoomon' => { 372 => 0x219 }, + 'optionenddate' => { 465 => 'optionEndDate' }, + 'opto-electricconvfactor' => { 452 => 'OECF' }, + 'orangehsl' => { 97 => 0x20911 }, + 'ordernumber' => { 121 => 0x8002 }, + 'organisationinimagecode' => { 458 => 'OrganisationInImageCode' }, + 'organisationinimagename' => { 458 => 'OrganisationInImageName' }, + 'organism' => { 112 => 'Organism' }, + 'organismassociatedoccurrences' => { 112 => [\'Organism','OrganismAssociatedOccurrences'] }, + 'organismassociatedorganisms' => { 112 => [\'Organism','OrganismAssociatedOrganisms'] }, + 'organismid' => { 112 => [\'Organism','OrganismOrganismID'] }, + 'organismname' => { 112 => [\'Organism','OrganismOrganismName'] }, + 'organismpreviousidentifications' => { 112 => [\'Organism','OrganismPreviousIdentifications'] }, + 'organismremarks' => { 112 => [\'Organism','OrganismOrganismRemarks'] }, + 'organismscope' => { 112 => [\'Organism','OrganismOrganismScope'] }, + 'organization' => { 462 => 'organization' }, + 'orientation' => { 113 => 0x112, 306 => 0x112, 461 => 'orientation', 468 => 'Orientation' }, + 'orientation2' => { 399 => [0x28,0x2e] }, + 'orientationlinkedaf' => { 2 => 0xe }, + 'orientationlinkedafpoint' => { 78 => 0x516 }, + 'originalbestqualitysize' => { 113 => 0xc792 }, + 'originalcreatedatetime' => { 437 => 'OriginalCreateDateTime' }, + 'originaldecisiondata' => { 108 => 'OriginalDecisionData' }, + 'originaldecisiondataoffset' => { 60 => 0x83 }, + 'originaldefaultcropsize' => { 113 => 0xc793 }, + 'originaldefaultfinalsize' => { 113 => 0xc791 }, + 'originaldirectory' => { 298 => 0x408 }, + 'originaldocumentid' => { 473 => 'OriginalDocumentID' }, + 'originalfilename' => { 91 => 0x816, 131 => 0x3e9, 143 => 0x20, 298 => 0x407, 437 => 'OriginalFilename' }, + 'originalimageheight' => { 74 => 0xc, 117 => 0x1 }, + 'originalimagewidth' => { 74 => 0xb, 117 => 0x0 }, + 'originalrawfiledata' => { 113 => 0xc68c }, + 'originalrawfiledigest' => { 113 => 0xc71d }, + 'originalrawfilename' => { 113 => 0xc68b }, + 'originaltransmissionreference' => { 125 => 0x67 }, + 'originatingprogram' => { 125 => 0x41, 442 => 'OriginatingProgram' }, + 'originplatform' => { 462 => 'originPlatform' }, + 'os' => { 450 => 'os' }, + 'otherconditions' => { 288 => 'OtherConditions' }, + 'otherconstraints' => { 288 => 'OtherConstraints' }, + 'otherimage' => { 108 => 'OtherImage' }, + 'otherimageinfo' => { 288 => 'OtherImageInfo' }, + 'otherimagelength' => { 113 => 0x202 }, + 'otherimagestart' => { 113 => 0x201 }, + 'otherlicensedocuments' => { 288 => 'OtherLicenseDocuments' }, + 'otherlicenseinfo' => { 288 => 'OtherLicenseInfo' }, + 'otherlicenserequirements' => { 288 => 'OtherLicenseRequirements' }, + 'outcue' => { 472 => 'outCue' }, + 'outcuescale' => { 472 => [\'outCue','outCueScale'] }, + 'outcuevalue' => { 472 => [\'outCue','outCueValue'] }, + 'outputimageheight' => { 186 => 0x3 }, + 'outputimagewidth' => { 186 => 0x2 }, + 'outputlut' => { 301 => 0xa7 }, + 'outputprofile' => { 131 => 0x138b }, + 'outputresolution' => { 186 => 0x4 }, + 'overclockcols' => { 131 => 0x189c }, + 'overclockrows' => { 131 => 0x18c4 }, + 'owner' => { 476 => 'Owner' }, + 'ownerid' => { 125 => 0xbc }, + 'ownername' => { 14 => 0x10f, 60 => 0x9, 91 => 0x810, 113 => [0xa430,0xfde8], 147 => 'OwnerName', 444 => 'OwnerName', 453 => 'CameraOwnerName' }, + 'padding' => { 113 => 0xea1c }, + 'pagecount' => { 462 => 'pageCount' }, + 'pageimage' => { 470 => [\'PageInfo','PageInfoImage'] }, + 'pageimageformat' => { 470 => [\'PageInfo','PageInfoFormat'] }, + 'pageimageheight' => { 470 => [\'PageInfo','PageInfoHeight'] }, + 'pageimagepagenumber' => { 470 => [\'PageInfo','PageInfoPageNumber'] }, + 'pageimagewidth' => { 470 => [\'PageInfo','PageInfoWidth'] }, + 'pageinfo' => { 470 => 'PageInfo' }, + 'pagename' => { 113 => 0x11d }, + 'pagenumber' => { 113 => 0x129 }, + 'pageprogressiondirection' => { 462 => 'pageProgressionDirection' }, + 'pagerange' => { 462 => 'pageRange' }, + 'paintbasedcorrectionmasks' => { 448 => [\'PaintBasedCorrections','PaintBasedCorrectionsCorrectionMasks'] }, + 'paintbasedcorrections' => { 448 => 'PaintBasedCorrections' }, + 'paintcorrectionactive' => { 448 => [\'PaintBasedCorrections','PaintBasedCorrectionsCorrectionActive'] }, + 'paintcorrectionamount' => { 448 => [\'PaintBasedCorrections','PaintBasedCorrectionsCorrectionAmount'] }, + 'paintcorrectionbrightness' => { 448 => [\'PaintBasedCorrections','PaintBasedCorrectionsLocalBrightness'] }, + 'paintcorrectionclarity' => { 448 => [\'PaintBasedCorrections','PaintBasedCorrectionsLocalClarity'] }, + 'paintcorrectionclarity2012' => { 448 => [\'PaintBasedCorrections','PaintBasedCorrectionsLocalClarity2012'] }, + 'paintcorrectioncontrast' => { 448 => [\'PaintBasedCorrections','PaintBasedCorrectionsLocalContrast'] }, + 'paintcorrectioncontrast2012' => { 448 => [\'PaintBasedCorrections','PaintBasedCorrectionsLocalContrast2012'] }, + 'paintcorrectiondefringe' => { 448 => [\'PaintBasedCorrections','PaintBasedCorrectionsLocalDefringe'] }, + 'paintcorrectionexposure' => { 448 => [\'PaintBasedCorrections','PaintBasedCorrectionsLocalExposure'] }, + 'paintcorrectionexposure2012' => { 448 => [\'PaintBasedCorrections','PaintBasedCorrectionsLocalExposure2012'] }, + 'paintcorrectionhighlights2012' => { 448 => [\'PaintBasedCorrections','PaintBasedCorrectionsLocalHighlights2012'] }, + 'paintcorrectionhue' => { 448 => [\'PaintBasedCorrections','PaintBasedCorrectionsLocalToningHue'] }, + 'paintcorrectionluminancenoise' => { 448 => [\'PaintBasedCorrections','PaintBasedCorrectionsLocalLuminanceNoise'] }, + 'paintcorrectionmaskalpha' => { 448 => [\'PaintBasedCorrections','PaintBasedCorrectionsCorrectionMasksAlpha'] }, + 'paintcorrectionmaskangle' => { 448 => [\'PaintBasedCorrections','PaintBasedCorrectionsCorrectionMasksAngle'] }, + 'paintcorrectionmaskbottom' => { 448 => [\'PaintBasedCorrections','PaintBasedCorrectionsCorrectionMasksBottom'] }, + 'paintcorrectionmaskcentervalue' => { 448 => [\'PaintBasedCorrections','PaintBasedCorrectionsCorrectionMasksCenterValue'] }, + 'paintcorrectionmaskcenterweight' => { 448 => [\'PaintBasedCorrections','PaintBasedCorrectionsCorrectionMasksCenterWeight'] }, + 'paintcorrectionmaskdabs' => { 448 => [\'PaintBasedCorrections','PaintBasedCorrectionsCorrectionMasksDabs'] }, + 'paintcorrectionmaskfeather' => { 448 => [\'PaintBasedCorrections','PaintBasedCorrectionsCorrectionMasksFeather'] }, + 'paintcorrectionmaskflipped' => { 448 => [\'PaintBasedCorrections','PaintBasedCorrectionsCorrectionMasksFlipped'] }, + 'paintcorrectionmaskflow' => { 448 => [\'PaintBasedCorrections','PaintBasedCorrectionsCorrectionMasksFlow'] }, + 'paintcorrectionmaskfullx' => { 448 => [\'PaintBasedCorrections','PaintBasedCorrectionsCorrectionMasksFullX'] }, + 'paintcorrectionmaskfully' => { 448 => [\'PaintBasedCorrections','PaintBasedCorrectionsCorrectionMasksFullY'] }, + 'paintcorrectionmaskleft' => { 448 => [\'PaintBasedCorrections','PaintBasedCorrectionsCorrectionMasksLeft'] }, + 'paintcorrectionmaskmidpoint' => { 448 => [\'PaintBasedCorrections','PaintBasedCorrectionsCorrectionMasksMidpoint'] }, + 'paintcorrectionmaskperimetervalue' => { 448 => [\'PaintBasedCorrections','PaintBasedCorrectionsCorrectionMasksPerimeterValue'] }, + 'paintcorrectionmaskradius' => { 448 => [\'PaintBasedCorrections','PaintBasedCorrectionsCorrectionMasksRadius'] }, + 'paintcorrectionmaskright' => { 448 => [\'PaintBasedCorrections','PaintBasedCorrectionsCorrectionMasksRight'] }, + 'paintcorrectionmaskroundness' => { 448 => [\'PaintBasedCorrections','PaintBasedCorrectionsCorrectionMasksRoundness'] }, + 'paintcorrectionmasksizex' => { 448 => [\'PaintBasedCorrections','PaintBasedCorrectionsCorrectionMasksSizeX'] }, + 'paintcorrectionmasksizey' => { 448 => [\'PaintBasedCorrections','PaintBasedCorrectionsCorrectionMasksSizeY'] }, + 'paintcorrectionmasktop' => { 448 => [\'PaintBasedCorrections','PaintBasedCorrectionsCorrectionMasksTop'] }, + 'paintcorrectionmaskvalue' => { 448 => [\'PaintBasedCorrections','PaintBasedCorrectionsCorrectionMasksMaskValue'] }, + 'paintcorrectionmaskversion' => { 448 => [\'PaintBasedCorrections','PaintBasedCorrectionsCorrectionMasksVersion'] }, + 'paintcorrectionmaskwhat' => { 448 => [\'PaintBasedCorrections','PaintBasedCorrectionsCorrectionMasksWhat'] }, + 'paintcorrectionmaskx' => { 448 => [\'PaintBasedCorrections','PaintBasedCorrectionsCorrectionMasksX'] }, + 'paintcorrectionmasky' => { 448 => [\'PaintBasedCorrections','PaintBasedCorrectionsCorrectionMasksY'] }, + 'paintcorrectionmaskzerox' => { 448 => [\'PaintBasedCorrections','PaintBasedCorrectionsCorrectionMasksZeroX'] }, + 'paintcorrectionmaskzeroy' => { 448 => [\'PaintBasedCorrections','PaintBasedCorrectionsCorrectionMasksZeroY'] }, + 'paintcorrectionmoire' => { 448 => [\'PaintBasedCorrections','PaintBasedCorrectionsLocalMoire'] }, + 'paintcorrectionsaturation' => { 448 => [\'PaintBasedCorrections','PaintBasedCorrectionsLocalSaturation','PaintBasedCorrectionsLocalToningSaturation'] }, + 'paintcorrectionshadows2012' => { 448 => [\'PaintBasedCorrections','PaintBasedCorrectionsLocalShadows2012'] }, + 'paintcorrectionsharpness' => { 448 => [\'PaintBasedCorrections','PaintBasedCorrectionsLocalSharpness'] }, + 'paintcorrectiontemperature' => { 448 => [\'PaintBasedCorrections','PaintBasedCorrectionsLocalTemperature'] }, + 'paintcorrectiontint' => { 448 => [\'PaintBasedCorrections','PaintBasedCorrectionsLocalTint'] }, + 'paintcorrectionwhat' => { 448 => [\'PaintBasedCorrections','PaintBasedCorrectionsWhat'] }, + 'panasonicdatetime' => { 304 => 0x0 }, + 'panasonicexifversion' => { 301 => 0x26 }, + 'panasonicimageheight' => { 301 => 0x4c }, + 'panasonicimagewidth' => { 301 => 0x4b }, + 'panasonicrawversion' => { 306 => 0x1 }, + 'panasonictitle' => { 113 => 0xc6d2 }, + 'panasonictitle2' => { 113 => 0xc6d3 }, + 'panoramaangle' => { 121 => 0x1153 }, + 'panoramacropbottom' => { 400 => 0x7 }, + 'panoramacropleft' => { 400 => 0x4 }, + 'panoramacropright' => { 400 => 0x6 }, + 'panoramacroptop' => { 400 => 0x5 }, + 'panoramadirection' => { 68 => 0x5, 121 => 0x1154, 400 => 0x3 }, + 'panoramaframeheight' => { 400 => 0x9 }, + 'panoramaframenumber' => { 68 => 0x2 }, + 'panoramaframewidth' => { 400 => 0x8 }, + 'panoramafullheight' => { 400 => 0x2 }, + 'panoramafullwidth' => { 400 => 0x1 }, + 'panoramamode' => { 133 => 0x3c, 278 => 0x601 }, + 'panoramasize3d' => { 383 => 0x38 }, + 'panoramasourceheight' => { 400 => 0xb }, + 'panoramasourcewidth' => { 400 => 0xa }, + 'panoramicstitchcameramotion' => { 167 => 'PanoramicStitchCameraMotion', 168 => 0x1 }, + 'panoramicstitchmaptype' => { 167 => 'PanoramicStitchMapType', 168 => 0x2 }, + 'panoramicstitchphi0' => { 167 => 'PanoramicStitchPhi0', 168 => 0x5 }, + 'panoramicstitchphi1' => { 167 => 'PanoramicStitchPhi1', 168 => 0x6 }, + 'panoramicstitchtheta0' => { 167 => 'PanoramicStitchTheta0', 168 => 0x3 }, + 'panoramicstitchtheta1' => { 167 => 'PanoramicStitchTheta1', 168 => 0x4 }, + 'panoramicstitchversion' => { 168 => 0x0 }, + 'pantry' => { 473 => 'Pantry' }, + 'parallax' => { 121 => 0xb211, 277 => 0x28 }, + 'parametricdarks' => { 448 => 'ParametricDarks' }, + 'parametrichighlights' => { 448 => 'ParametricHighlights' }, + 'parametrichighlightsplit' => { 448 => 'ParametricHighlightSplit' }, + 'parametriclights' => { 448 => 'ParametricLights' }, + 'parametricmidtonesplit' => { 448 => 'ParametricMidtoneSplit' }, + 'parametricshadows' => { 448 => 'ParametricShadows' }, + 'parametricshadowsplit' => { 448 => 'ParametricShadowSplit' }, + 'parentmediaeventid' => { 437 => 'ParentMediaEventID' }, + 'parentmeid' => { 437 => 'ParentMEID' }, + 'parentreference1' => { 456 => [\'TagStructure','TagStructureParentReference'] }, + 'parentreference2' => { 456 => [\'TagStructure','TagStructureSubLabelsParentReference'] }, + 'parentreference3' => { 456 => [\'TagStructure','TagStructureSubLabelsSubLabelsParentReference'] }, + 'parentreference4' => { 456 => [\'TagStructure','TagStructureSubLabelsSubLabelsSubLabelsParentReference'] }, + 'parentreference5' => { 456 => [\'TagStructure','TagStructureSubLabelsSubLabelsSubLabelsSubLabelsParentReference'] }, + 'parentreference6' => { 456 => [\'TagStructure','TagStructureSubLabelsSubLabelsSubLabelsSubLabelsSubLabelsParentReference'] }, + 'partialactivecols1' => { 131 => 0x17e8 }, + 'partialactivecols2' => { 131 => 0x17f2 }, + 'partialactiverows1' => { 131 => 0x17fc }, + 'partialactiverows2' => { 131 => 0x1806 }, + 'partofcompilation' => { 472 => 'partOfCompilation' }, + 'patientbirthdate' => { 429 => 'PatientDOB' }, + 'patientid' => { 429 => 'PatientID' }, + 'patientname' => { 429 => 'PatientName' }, + 'patientsex' => { 429 => 'PatientSex' }, + 'patternareaheight' => { 131 => 0x963 }, + 'patternareawidth' => { 131 => 0x962 }, + 'patterncorrectionfactorscale' => { 131 => 0x969 }, + 'patterncropcols1' => { 131 => 0x96c }, + 'patterncropcols2' => { 131 => 0x96d }, + 'patterncroprows1' => { 131 => 0x96a }, + 'patterncroprows2' => { 131 => 0x96b }, + 'patternimagerheight' => { 131 => 0x961 }, + 'patternimagerwidth' => { 131 => 0x960 }, + 'patternx' => { 131 => 0x966 }, + 'patterny' => { 131 => 0x967 }, + 'pdfversion' => { 459 => 'PDFVersion' }, + 'pentaximagesize' => { 336 => 0x9 }, + 'pentaxmodelid' => { 316 => 0x0, 336 => 0x5 }, + 'pentaxmodeltype' => { 336 => 0x1 }, + 'pentaxversion' => { 336 => 0x0 }, + 'people' => { 430 => 'People', 440 => 'People' }, + 'perchannelblacklevel' => { 41 => 0xc4, 42 => [0x2b4,0x2cb,0x2cf], 43 => [0x108,0x14d], 44 => 0x1df, 45 => [0x1f8,0x2d8], 46 => [0x22c,0x30a], 47 => 0x149 }, + 'peripheralillumcentralradius' => { 427 => 0x8030 }, + 'peripheralillumcentralvalue' => { 427 => 0x8031 }, + 'peripheralillumination' => { 97 => 0x20702, 103 => 0x68 }, + 'peripheralilluminationcorr' => { 59 => 0x1, 326 => 0x2 }, + 'peripheralilluminationon' => { 97 => '0x20702.0', 103 => 0x64 }, + 'peripheralillumperiphvalue' => { 427 => 0x8032 }, + 'peripherallighting' => { 74 => 0x2 }, + 'peripherallightingsetting' => { 75 => 0x5 }, + 'peripherallightingvalue' => { 74 => 0x6 }, + 'permissions' => { 465 => 'permissions' }, + 'permits' => { 445 => 'permits' }, + 'person' => { 462 => 'person' }, + 'personality' => { 437 => 'Personality' }, + 'personheard' => { 458 => 'PersonHeard' }, + 'personheardidentifier' => { 458 => [\'PersonHeard','PersonHeardIdentifier'] }, + 'personheardname' => { 458 => [\'PersonHeard','PersonHeardName'] }, + 'personinimage' => { 458 => 'PersonInImage' }, + 'personinimagecharacteristic' => { 458 => [\'PersonInImageWDetails','PersonInImageWDetailsPersonCharacteristic'] }, + 'personinimagecvtermcvid' => { 458 => [\'PersonInImageWDetails','PersonInImageWDetailsPersonCharacteristicCvId'] }, + 'personinimagecvtermid' => { 458 => [\'PersonInImageWDetails','PersonInImageWDetailsPersonCharacteristicCvTermId'] }, + 'personinimagecvtermname' => { 458 => [\'PersonInImageWDetails','PersonInImageWDetailsPersonCharacteristicCvTermName'] }, + 'personinimagecvtermrefinedabout' => { 458 => [\'PersonInImageWDetails','PersonInImageWDetailsPersonCharacteristicCvTermRefinedAbout'] }, + 'personinimagedescription' => { 458 => [\'PersonInImageWDetails','PersonInImageWDetailsPersonDescription'] }, + 'personinimageid' => { 458 => [\'PersonInImageWDetails','PersonInImageWDetailsPersonId'] }, + 'personinimagename' => { 458 => [\'PersonInImageWDetails','PersonInImageWDetailsPersonName'] }, + 'personinimagewdetails' => { 458 => 'PersonInImageWDetails' }, + 'perspectiveaspect' => { 448 => 'PerspectiveAspect' }, + 'perspectivehorizontal' => { 448 => 'PerspectiveHorizontal' }, + 'perspectiverotate' => { 448 => 'PerspectiveRotate' }, + 'perspectivescale' => { 448 => 'PerspectiveScale' }, + 'perspectiveupright' => { 448 => 'PerspectiveUpright' }, + 'perspectivevertical' => { 448 => 'PerspectiveVertical' }, + 'perspectivex' => { 448 => 'PerspectiveX' }, + 'perspectivey' => { 448 => 'PerspectiveY' }, + 'pf0customfuncregistration' => { 86 => 0x1 }, + 'pf10retainprogramshift' => { 86 => 0xb }, + 'pf13drivepriority' => { 86 => 0xe }, + 'pf14disablefocussearch' => { 86 => 0xf }, + 'pf15disableafassistbeam' => { 86 => 0x10 }, + 'pf16autofocuspointshoot' => { 86 => 0x11 }, + 'pf17disableafpointsel' => { 86 => 0x12 }, + 'pf18enableautoafpointsel' => { 86 => 0x13 }, + 'pf19continuousshootspeed' => { 86 => 0x14 }, + 'pf19shootingspeedhigh' => { 85 => 0xa }, + 'pf19shootingspeedlow' => { 85 => 0x9 }, + 'pf1disableshootingmodes' => { 86 => 0x2 }, + 'pf1value' => { 85 => 0x1 }, + 'pf20limitcontinousshots' => { 86 => 0x15 }, + 'pf20maxcontinousshots' => { 85 => 0xb }, + 'pf21enablequietoperation' => { 86 => 0x16 }, + 'pf23felocktime' => { 85 => 0xd }, + 'pf23postreleasetime' => { 85 => 0xe }, + 'pf23settimerlengths' => { 86 => 0x18 }, + 'pf23shutterbuttontime' => { 85 => 0xc }, + 'pf24lightlcdduringbulb' => { 86 => 0x19 }, + 'pf25aemode' => { 85 => 0xf }, + 'pf25afmode' => { 85 => 0x12 }, + 'pf25afpointsel' => { 85 => 0x13 }, + 'pf25colormatrix' => { 85 => 0x17 }, + 'pf25defaultclearsettings' => { 86 => 0x1a }, + 'pf25drivemode' => { 85 => 0x11 }, + 'pf25imagesize' => { 85 => 0x14 }, + 'pf25meteringmode' => { 85 => 0x10 }, + 'pf25parameters' => { 85 => 0x16 }, + 'pf25wbmode' => { 85 => 0x15 }, + 'pf26shortenreleaselag' => { 86 => 0x1b }, + 'pf27reversedialrotation' => { 86 => 0x1c }, + 'pf27value' => { 85 => 0x18 }, + 'pf28noquickdialexpcomp' => { 86 => 0x1d }, + 'pf29quickdialswitchoff' => { 86 => 0x1e }, + 'pf2disablemeteringmodes' => { 86 => 0x3 }, + 'pf2value' => { 85 => 0x2 }, + 'pf30enlargementmode' => { 86 => 0x1f }, + 'pf31originaldecisiondata' => { 86 => 0x20 }, + 'pf3manualexposuremetering' => { 86 => 0x4 }, + 'pf3value' => { 85 => 0x3 }, + 'pf4exposuretimelimits' => { 86 => 0x5 }, + 'pf4exposuretimemax' => { 85 => 0x5 }, + 'pf4exposuretimemin' => { 85 => 0x4 }, + 'pf5aperturelimits' => { 86 => 0x6 }, + 'pf5aperturemax' => { 85 => 0x7 }, + 'pf5aperturemin' => { 85 => 0x6 }, + 'pf6presetshootingmodes' => { 86 => 0x7 }, + 'pf7bracketcontinuousshoot' => { 86 => 0x8 }, + 'pf8bracketshots' => { 85 => 0x8 }, + 'pf8setbracketshots' => { 86 => 0x9 }, + 'pf9changebracketsequence' => { 86 => 0xa }, + 'phasedetectaf' => { 183 => 0x6 }, + 'phonenumber' => { 148 => 'Phone' }, + 'photoeffect' => { 33 => 0x28 }, + 'photoeffecthistoryxml' => { 254 => 0xe9651831 }, + 'photoeffects' => { 254 => 0xab5eca5e }, + 'photoeffectsblue' => { 256 => 0x8 }, + 'photoeffectsgreen' => { 256 => 0x6 }, + 'photoeffectsred' => { 256 => 0x4 }, + 'photoeffectstype' => { 256 => 0x0 }, + 'photographicsensitivity' => { 453 => 'PhotographicSensitivity' }, + 'photoinfoplayback' => { 261 => '17.6', 270 => '33.6' }, + 'photometricinterpretation' => { 113 => 0x106, 468 => 'PhotometricInterpretation' }, + 'photoshootingmenubank' => { 233 => 0xe7d, 242 => 0xfbd }, + 'photoshootingmenubankimagearea' => { 233 => '3716.1', 242 => 0x791 }, + 'photoshopbgrthumbnail' => { 350 => 0x409 }, + 'photoshopquality' => { 349 => 0x0 }, + 'photoshopthumbnail' => { 350 => 0x40c }, + 'photostyle' => { 301 => 0x89 }, + 'picklabel' => { 451 => 'PickLabel' }, + 'pictinfo' => { 372 => 0x208 }, + 'picturecontrol' => { 254 => 0xe2173c47 }, + 'picturecontrolactive' => { 257 => 0x0 }, + 'picturecontroladjust' => { 216 => 0x30, 217 => 0x30, 218 => 0x36 }, + 'picturecontrolbase' => { 216 => 0x18, 217 => 0x18, 218 => 0x1c }, + 'picturecontroldata' => { 214 => [0xbd,0x23] }, + 'picturecontrolmode' => { 257 => 0x13 }, + 'picturecontrolname' => { 216 => 0x4, 217 => 0x4, 218 => 0x8 }, + 'picturecontrolquickadjust' => { 216 => 0x31, 217 => 0x31, 218 => 0x37 }, + 'pictureeffect' => { 394 => 0x200e }, + 'pictureeffect2' => { 402 => 0x1163, 403 => 0x1167, 404 => 0x1143, 405 => 0x11bf, 406 => 0x119b, 407 => 0x1053, 408 => 0x24b, 409 => 0x24b, 410 => 0x23c, 423 => 0x46 }, + 'picturefinish' => { 172 => 0x71 }, + 'picturemode' => { 121 => 0x1031, 278 => 0x520, 336 => [0xb,0x33], 373 => 0x3d }, + 'picturemode2' => { 317 => 0x0 }, + 'picturemodebwfilter' => { 278 => 0x525 }, + 'picturemodecontrast' => { 278 => 0x523 }, + 'picturemodeeffect' => { 278 => 0x52d }, + 'picturemodehue' => { 278 => 0x522 }, + 'picturemodesaturation' => { 278 => 0x521 }, + 'picturemodesharpness' => { 278 => 0x524 }, + 'picturemodetone' => { 278 => 0x526 }, + 'pictureprofile' => { 402 => [0x115e,0x115f], 403 => [0x1162,0x1163], 404 => [0x113e,0x113f], 405 => [0x11ba,0x11bb], 406 => [0x1196,0x1197], 407 => [0x104e,0x104f], 408 => [0x246,0x247], 409 => [0x246,0x247], 410 => [0x237,0x238] }, + 'picturestyle' => { 7 => [0x4b,0x51], 8 => 0xf4, 9 => 0x6c, 10 => 0x86, 11 => 0x73, 15 => 0xab, 16 => 0xa7, 17 => 0xb0, 18 => 0x6c, 19 => 0xa7, 20 => 0xf4, 21 => 0xb3, 23 => 0xf4, 24 => 0xfa, 26 => 0x169, 70 => 0xa, 97 => 0x20301, 103 => 0x2 }, + 'picturewizard' => { 370 => 0x21 }, + 'picturewizardcolor' => { 369 => 0x1 }, + 'picturewizardcontrast' => { 369 => 0x4 }, + 'picturewizardmode' => { 369 => 0x0 }, + 'picturewizardsaturation' => { 369 => 0x2 }, + 'picturewizardsharpness' => { 369 => 0x3 }, + 'pipelineversion' => { 167 => 'PipelineVersion' }, + 'pitch' => { 109 => 0x6, 262 => '4.1', 274 => '4.1' }, + 'pitchangle' => { 232 => 0x350f, 233 => 0x2c28, 241 => 0x36f8, 278 => 0x904, 301 => 0x91, 335 => 0x2, 368 => 0x1 }, + 'pixelclockfrequency' => { 131 => 0x40b }, + 'pixelcorrectionoffset' => { 131 => 0x972 }, + 'pixelcorrectionscale' => { 131 => 0x971 }, + 'pixelscale' => { 113 => 0x830e }, + 'pixelshiftinfo' => { 394 => 0x202f }, + 'pixelshiftresolution' => { 337 => 0x0 }, + 'pixelsperunitx' => { 290 => 0x0 }, + 'pixelsperunity' => { 290 => 0x4 }, + 'pixelunits' => { 290 => 0x8 }, + 'planarconfiguration' => { 113 => 0x11c, 468 => 'PlanarConfiguration' }, + 'planningref' => { 458 => 'PlanningRef' }, + 'planningrefidentifier' => { 458 => [\'PlanningRef','PlanningRefIdentifier'] }, + 'planningrefname' => { 458 => [\'PlanningRef','PlanningRefName'] }, + 'planningrefrole' => { 458 => [\'PlanningRef','PlanningRefRole'] }, + 'platenames' => { 477 => 'PlateNames' }, + 'platform' => { 462 => 'platform' }, + 'playbackmenustime' => { 266 => '20.1', 267 => '21.1', 268 => '21.1' }, + 'playbackmonitorofftime' => { 261 => '25.2', 262 => '36.1', 264 => '36.1', 265 => '36.1', 269 => '35.1', 270 => '8.1', 271 => '35.1', 274 => '36.1', 275 => '36.1', 276 => '21.1' }, + 'playbackzoom' => { 262 => '37.1' }, + 'playdisplay' => { 174 => 0x4e }, + 'plusversion' => { 288 => 'Version' }, + 'pmversion' => { 348 => 'PMVersion' }, + 'pngwarning' => { 291 => 'Warning' }, + 'poilevel' => { 213 => 0x8 }, + 'portraitoutputhighlightpoint' => { 103 => 0x1d }, + 'portraitoutputshadowpoint' => { 103 => 0x1e }, + 'portraitrawcolortone' => { 103 => 0x16 }, + 'portraitrawcontrast' => { 103 => 0x18 }, + 'portraitrawhighlight' => { 103 => 0x76 }, + 'portraitrawhighlightpoint' => { 103 => 0x1b }, + 'portraitrawlinear' => { 103 => 0x19 }, + 'portraitrawsaturation' => { 103 => 0x17 }, + 'portraitrawshadow' => { 103 => 0x7f }, + 'portraitrawshadowpoint' => { 103 => 0x1c }, + 'portraitrawsharpness' => { 103 => 0x1a }, + 'portraitrefiner' => { 107 => 0x302b }, + 'portraitunsharpmaskfineness' => { 103 => 0x9a }, + 'portraitunsharpmaskstrength' => { 103 => 0x98 }, + 'portraitunsharpmaskthreshold' => { 103 => 0x9c }, + 'poseheadingdegrees' => { 435 => 'PoseHeadingDegrees' }, + 'posepitchdegrees' => { 435 => 'PosePitchDegrees' }, + 'poserolldegrees' => { 435 => 'PoseRollDegrees' }, + 'positiondescriptor' => { 461 => 'positionDescriptor' }, + 'postalcode' => { 152 => 'PostalCode' }, + 'postcropvignetteamount' => { 448 => 'PostCropVignetteAmount' }, + 'postcropvignettefeather' => { 448 => 'PostCropVignetteFeather' }, + 'postcropvignettehighlightcontrast' => { 448 => 'PostCropVignetteHighlightContrast' }, + 'postcropvignettemidpoint' => { 448 => 'PostCropVignetteMidpoint' }, + 'postcropvignetteroundness' => { 448 => 'PostCropVignetteRoundness' }, + 'postcropvignettestyle' => { 448 => 'PostCropVignetteStyle' }, + 'potentialface1position' => { 391 => 0xb }, + 'potentialface2position' => { 391 => 0x15 }, + 'potentialface3position' => { 391 => 0x1f }, + 'potentialface4position' => { 391 => 0x29 }, + 'potentialface5position' => { 391 => 0x33 }, + 'potentialface6position' => { 391 => 0x3d }, + 'potentialface7position' => { 391 => 0x47 }, + 'potentialface8position' => { 391 => 0x51 }, + 'powersource' => { 315 => '0.1' }, + 'poweruptime' => { 214 => 0xb6 }, + 'precaptureframes' => { 283 => 0x300 }, + 'predictor' => { 113 => 0x13d }, + 'preflashreturnstrength' => { 230 => 0x28a }, + 'prefs' => { 125 => 0xdd, 348 => 'Prefs' }, + 'prereadfastresetcount' => { 131 => 0x187e }, + 'preservedfilename' => { 473 => 'PreservedFileName' }, + 'preservedspecimen' => { 112 => 'PreservedSpecimen' }, + 'preservedspecimenmaterialsampleid' => { 112 => [\'PreservedSpecimen','PreservedSpecimenMaterialSampleID'] }, + 'presetwhitebalance' => { 174 => 0x24, 427 => 0x8002 }, + 'presetwhitebalanceadj' => { 427 => 0x8014 }, + 'pressure' => { 113 => 0x9402, 453 => 'Pressure' }, + 'previewapplicationname' => { 113 => 0xc716 }, + 'previewapplicationversion' => { 113 => 0xc717 }, + 'previewbutton' => { 261 => ['14.1','15.1'], 262 => '15.1', 264 => '15.1', 265 => '15.1', 270 => '29.1', 271 => '14.1', 274 => '15.1', 275 => '15.1' }, + 'previewbuttonplusdials' => { 261 => ['14.2','15.2'], 262 => '15.2', 264 => '43.1', 265 => '43.1', 270 => '31.2', 274 => '43.1', 275 => '43.1' }, + 'previewcolorspace' => { 113 => 0xc71a }, + 'previewcropbottom' => { 347 => 0xef }, + 'previewcropleft' => { 347 => 0xec }, + 'previewcropright' => { 347 => 0xee }, + 'previewcroptop' => { 347 => 0xed }, + 'previewdate' => { 355 => 0x0 }, + 'previewdatetime' => { 113 => 0xc71b }, + 'previewimage' => { 107 => 0x2000, 108 => 'PreviewImage', 114 => 'PreviewImage', 116 => 0x4, 157 => 'data', 176 => 0x81, 283 => 0x280, 299 => 0x300, 394 => 0x2001 }, + 'previewimageborders' => { 336 => 0x3e }, + 'previewimageheight' => { 69 => 0x4, 135 => 0xfa58 }, + 'previewimagelength' => { 69 => 0x2, 107 => 0x3, 113 => [0x117,0x202], 176 => 0x89, 219 => 0x202, 278 => 0x102, 283 => 0x1037, 336 => 0x3, 362 => 0x1e, 367 => 0x3, 373 => [0x1b,0x1d], 384 => 0x202 }, + 'previewimagename' => { 157 => '1Name' }, + 'previewimagesize' => { 107 => 0x2, 140 => 0x2, 157 => 'ImageSize', 336 => 0x2, 373 => [0x1c,0x1e], 394 => 0xb02c, 427 => 0x9012 }, + 'previewimagestart' => { 69 => 0x5, 107 => 0x4, 113 => [0x111,0x201], 176 => 0x88, 219 => 0x201, 278 => 0x101, 283 => 0x1036, 336 => 0x4, 362 => 0x1c, 367 => 0x2, 373 => [0x1a,0x1c], 384 => 0x201 }, + 'previewimagetype' => { 157 => '0Type' }, + 'previewimagevalid' => { 278 => 0x100, 283 => 0x1035 }, + 'previewimagewidth' => { 69 => 0x3, 135 => 0xfa57 }, + 'previewquality' => { 69 => 0x1 }, + 'previewsettingsdigest' => { 113 => 0xc719 }, + 'previewsettingsname' => { 113 => 0xc718 }, + 'primaryafpoint' => { 183 => [0x44,0x7] }, + 'primarychromaticities' => { 113 => 0x13f, 468 => 'PrimaryChromaticities' }, + 'primaryftp' => { 437 => 'PrimaryFTP' }, + 'primaryslot' => { 233 => 0xe7f, 242 => 0xfbf }, + 'printim' => { 113 => 0xc4a5 }, + 'prioritysetinawb' => { 394 => 0x202b }, + 'prioritysetupshutterrelease' => { 174 => 0x1d, 381 => 0x28 }, + 'privatertkinfo' => { 439 => 'privateRTKInfo' }, + 'processbordercolsleft' => { 131 => 0xc61 }, + 'processbordercolsright' => { 131 => 0xc62 }, + 'processborderrowsbottom' => { 131 => 0xc64 }, + 'processborderrowstop' => { 131 => 0xc63 }, + 'processingsoftware' => { 113 => 0xb }, + 'processversion' => { 448 => 'ProcessVersion' }, + 'producer' => { 287 => 'Producer', 459 => 'Producer' }, + 'productcode' => { 462 => 'productCode' }, + 'productid' => { 126 => 0x32, 461 => 'productID' }, + 'productidtype' => { 461 => 'productIDType' }, + 'productinimage' => { 458 => 'ProductInImage' }, + 'productinimagedescription' => { 458 => [\'ProductInImage','ProductInImageProductDescription'] }, + 'productinimagegtin' => { 458 => [\'ProductInImage','ProductInImageProductGTIN'] }, + 'productinimagename' => { 458 => [\'ProductInImage','ProductInImageProductName'] }, + 'productioncode' => { 316 => 0x2 }, + 'productorserviceconstraints' => { 288 => 'ProductOrServiceConstraints' }, + 'profession' => { 462 => 'profession' }, + 'profilecalibrationsig' => { 113 => 0xc6f4 }, + 'profilecopyright' => { 113 => 0xc6fe }, + 'profileembedpolicy' => { 113 => 0xc6fd }, + 'profilehuesatmapdata1' => { 113 => 0xc6fa }, + 'profilehuesatmapdata2' => { 113 => 0xc6fb }, + 'profilehuesatmapdims' => { 113 => 0xc6f9 }, + 'profilehuesatmapencoding' => { 113 => 0xc7a3 }, + 'profilelooktabledata' => { 113 => 0xc726 }, + 'profilelooktabledims' => { 113 => 0xc725 }, + 'profilelooktableencoding' => { 113 => 0xc7a4 }, + 'profilename' => { 113 => 0xc6f8 }, + 'profiletonecurve' => { 113 => 0xc6fc }, + 'programiso' => { 301 => 0x3c }, + 'programline' => { 317 => '1.1' }, + 'programmode' => { 179 => 0x5 }, + 'programshift' => { 214 => 0xd }, + 'programversion' => { 125 => 0x46 }, + 'prohibits' => { 445 => 'prohibits' }, + 'projectiontype' => { 435 => 'ProjectionType', 436 => 'ProjectionType' }, + 'projectname' => { 472 => 'projectName' }, + 'projectref' => { 472 => 'projectRef' }, + 'projectrefpath' => { 472 => [\'projectRef','projectRefPath'] }, + 'projectreftype' => { 472 => [\'projectRef','projectRefType'] }, + 'propertyreleaseid' => { 288 => 'PropertyReleaseID' }, + 'propertyreleasestatus' => { 288 => 'PropertyReleaseStatus' }, + 'province-state' => { 125 => 0x5f }, + 'publicationdate' => { 462 => 'publicationDate' }, + 'publicationdatea-platform' => { 462 => [\'publicationDate','publicationDateA-platform'] }, + 'publicationdatedate' => { 462 => [\'publicationDate','publicationDateDate'] }, + 'publicationdisplaydate' => { 462 => 'publicationDisplayDate' }, + 'publicationdisplaydatea-platform' => { 462 => [\'publicationDisplayDate','publicationDisplayDateA-platform'] }, + 'publicationdisplaydatedate' => { 462 => [\'publicationDisplayDate','publicationDisplayDateDate'] }, + 'publicationevent' => { 458 => 'PublicationEvent' }, + 'publicationeventdate' => { 458 => [\'PublicationEvent','PublicationEventDate'] }, + 'publicationeventidentifier' => { 458 => [\'PublicationEvent','PublicationEventIdentifier'] }, + 'publicationeventname' => { 458 => [\'PublicationEvent','PublicationEventName'] }, + 'publicationname' => { 462 => 'publicationName' }, + 'publisher' => { 449 => 'publisher' }, + 'publishingfrequency' => { 462 => 'publishingFrequency' }, + 'pulldown' => { 472 => 'pullDown' }, + 'purplehsl' => { 97 => 0x20916 }, + 'pxshiftperiphedgenr' => { 427 => 0x9013 }, + 'pxshiftperiphedgenrvalue' => { 427 => 0x9014 }, + 'quality' => { 0 => 0x1, 33 => 0x3, 106 => 0x2, 107 => 0x3002, 121 => 0x1000, 133 => 0x9, 214 => 0x4, 244 => 0x3, 283 => 0x201, 296 => 0x300, 336 => 0x8, 343 => 0x2, 373 => 0x16, 381 => 0x56, 382 => 0x56, 383 => 0xb, 394 => [0x102,0x202e] }, + 'quality2' => { 402 => 0x1170, 403 => 0x1174, 404 => 0x1150, 406 => 0x11a8, 407 => 0x1060, 408 => 0x258, 409 => 0x258, 410 => 0x247, 414 => 0x29, 415 => 0x25, 416 => 0x2a }, + 'qualitymode' => { 107 => 0x8 }, + 'quantizationmethod' => { 127 => 0x78 }, + 'quickadjust' => { 257 => 0x2a }, + 'quickcontroldialinmeter' => { 78 => 0x703 }, + 'quickfix' => { 254 => 0x416391c6 }, + 'quickshot' => { 372 => 0x213 }, + 'quiettime' => { 131 => 0x188a }, + 'rangefinder' => { 266 => '4.1', 267 => '5.1', 268 => '5.1' }, + 'rasterizedcaption' => { 125 => 0x7d }, + 'rating' => { 113 => 0x4746, 121 => 0x1431, 347 => 0xdf, 394 => 0x2002, 442 => 'rating', 450 => 'rating', 458 => 'Rating', 462 => 'rating', 470 => 'Rating' }, + 'ratingpercent' => { 113 => 0x4749, 169 => 'Rating' }, + 'ratingratingregion' => { 458 => [\'Rating','RatingRatingRegion'] }, + 'ratingregioncity' => { 458 => [\'Rating','RatingRatingRegionCity'] }, + 'ratingregioncountrycode' => { 458 => [\'Rating','RatingRatingRegionCountryCode'] }, + 'ratingregioncountryname' => { 458 => [\'Rating','RatingRatingRegionCountryName'] }, + 'ratingregiongpsaltitude' => { 458 => [\'Rating','RatingRatingRegionGPSAltitude'] }, + 'ratingregiongpslatitude' => { 458 => [\'Rating','RatingRatingRegionGPSLatitude'] }, + 'ratingregiongpslongitude' => { 458 => [\'Rating','RatingRatingRegionGPSLongitude'] }, + 'ratingregionidentifier' => { 458 => [\'Rating','RatingRatingRegionIdentifier'] }, + 'ratingregionlocationid' => { 458 => [\'Rating','RatingRatingRegionLocationId'] }, + 'ratingregionlocationname' => { 458 => [\'Rating','RatingRatingRegionLocationName'] }, + 'ratingregionprovincestate' => { 458 => [\'Rating','RatingRatingRegionProvinceState'] }, + 'ratingregionsublocation' => { 458 => [\'Rating','RatingRatingRegionSublocation'] }, + 'ratingregionworldregion' => { 458 => [\'Rating','RatingRatingRegionWorldRegion'] }, + 'ratingscalemaxvalue' => { 458 => [\'Rating','RatingRatingScaleMaxValue'] }, + 'ratingscaleminvalue' => { 458 => [\'Rating','RatingRatingScaleMinValue'] }, + 'ratingsourcelink' => { 458 => [\'Rating','RatingRatingSourceLink'] }, + 'ratingvalue' => { 458 => [\'Rating','RatingRatingValue'] }, + 'ratingvaluelogolink' => { 458 => [\'Rating','RatingRatingValueLogoLink'] }, + 'rawandjpgrecording' => { 76 => 0x8, 176 => 0x109, 317 => 0xd }, + 'rawbrightnessadj' => { 97 => 0x20001, 102 => 0x38 }, + 'rawcoloradj' => { 102 => 0x2e }, + 'rawcropbottom' => { 347 => 0xd4 }, + 'rawcropleft' => { 347 => 0xd1 }, + 'rawcropright' => { 347 => 0xd3 }, + 'rawcroptop' => { 347 => 0xd2 }, + 'rawcustomsaturation' => { 102 => 0x30 }, + 'rawcustomtone' => { 102 => 0x34 }, + 'rawdata' => { 370 => 0xa048 }, + 'rawdatabyteorder' => { 370 => 0x40 }, + 'rawdatacfapattern' => { 370 => 0x50 }, + 'rawdatauniqueid' => { 113 => 0xc65d }, + 'rawdepth' => { 178 => 0x10 }, + 'rawdevartfilter' => { 285 => 0x121 }, + 'rawdevautogradation' => { 285 => 0x119 }, + 'rawdevcolorspace' => { 284 => 0x108, 285 => 0x109 }, + 'rawdevcontrastvalue' => { 284 => 0x106, 285 => 0x105 }, + 'rawdeveditstatus' => { 284 => 0x10b }, + 'rawdevelopmentprocess' => { 336 => 0x62 }, + 'rawdevengine' => { 284 => 0x109, 285 => 0x10b }, + 'rawdevexposurebiasvalue' => { 284 => 0x100, 285 => 0x100 }, + 'rawdevgradation' => { 285 => 0x112 }, + 'rawdevgraypoint' => { 284 => 0x103, 285 => 0x104 }, + 'rawdevmemorycoloremphasis' => { 284 => 0x105, 285 => 0x108 }, + 'rawdevnoisereduction' => { 284 => 0x10a, 285 => 0x10a }, + 'rawdevpicturemode' => { 285 => 0x10c }, + 'rawdevpm_bwfilter' => { 285 => 0x110 }, + 'rawdevpmcontrast' => { 285 => 0x10e }, + 'rawdevpmnoisefilter' => { 285 => 0x120 }, + 'rawdevpmpicturetone' => { 285 => 0x111 }, + 'rawdevpmsaturation' => { 285 => 0x10d }, + 'rawdevpmsharpness' => { 285 => 0x10f }, + 'rawdevsaturation3' => { 285 => 0x113 }, + 'rawdevsaturationemphasis' => { 284 => 0x104, 285 => 0x107 }, + 'rawdevsettings' => { 284 => 0x10c }, + 'rawdevsharpnessvalue' => { 284 => 0x107, 285 => 0x106 }, + 'rawdevversion' => { 284 => 0x0, 285 => 0x0 }, + 'rawdevwbfineadjustment' => { 284 => 0x102, 285 => 0x103 }, + 'rawdevwhitebalance' => { 285 => 0x101 }, + 'rawdevwhitebalancevalue' => { 284 => 0x101, 285 => 0x102 }, + 'rawfile' => { 113 => 0xfe4c }, + 'rawfilename' => { 448 => 'RawFileName' }, + 'rawfiletype' => { 394 => 0x2029 }, + 'rawformat' => { 306 => 0x2d, 345 => 0x10e }, + 'rawimagecenter' => { 214 => 0x99 }, + 'rawimagedigest' => { 113 => 0xc71c }, + 'rawimagesize' => { 336 => 0x39 }, + 'rawinfoversion' => { 286 => 0x0 }, + 'rawjpgheight' => { 93 => 0x4 }, + 'rawjpgquality' => { 54 => 0x6, 93 => 0x1 }, + 'rawjpgsize' => { 54 => 0x7, 93 => 0x2 }, + 'rawjpgwidth' => { 93 => 0x3 }, + 'rawmeasuredrggb' => { 40 => 0x26a, 42 => 0x280, 44 => 0x194, 45 => [0x1ad,0x26b] }, + 'rawrppused' => { 442 => 'rawrppused' }, + 'rawtopreviewgain' => { 113 => 0xc7a8 }, + 'readouttypeactual' => { 131 => 0x1903 }, + 'readouttyperequested' => { 131 => 0x1902 }, + 'reardisplay' => { 261 => '12.3', 262 => '6.2' }, + 'recdevice' => { 458 => 'RecDevice' }, + 'recdeviceattlensdescription' => { 458 => [\'RecDevice','RecDeviceAttLensDescription'] }, + 'recdevicemanufacturer' => { 458 => [\'RecDevice','RecDeviceManufacturer'] }, + 'recdevicemodelname' => { 458 => [\'RecDevice','RecDeviceModelName'] }, + 'recdeviceownersdeviceid' => { 458 => [\'RecDevice','RecDeviceOwnersDeviceId'] }, + 'recdeviceserialnumber' => { 458 => [\'RecDevice','RecDeviceSerialNumber'] }, + 'recipeendingpage' => { 464 => 'recipeEndingPage' }, + 'recipepagerange' => { 464 => 'recipePageRange' }, + 'recipesource' => { 464 => 'recipeSource' }, + 'recipestartingpage' => { 464 => 'recipeStartingPage' }, + 'recipetitle' => { 464 => 'recipeTitle' }, + 'recognizedface1age' => { 294 => 0x20 }, + 'recognizedface1name' => { 294 => 0x4 }, + 'recognizedface1position' => { 294 => 0x18 }, + 'recognizedface2age' => { 294 => 0x50 }, + 'recognizedface2name' => { 294 => 0x34 }, + 'recognizedface2position' => { 294 => 0x48 }, + 'recognizedface3age' => { 294 => 0x80 }, + 'recognizedface3name' => { 294 => 0x64 }, + 'recognizedface3position' => { 294 => 0x78 }, + 'recognizedfaceflags' => { 301 => 0x63 }, + 'recommendedexposureindex' => { 113 => 0x8832, 453 => 'RecommendedExposureIndex' }, + 'record' => { 112 => 'Record' }, + 'recordbasisofrecord' => { 112 => [\'Record','RecordBasisOfRecord'] }, + 'recordcollectioncode' => { 112 => [\'Record','RecordCollectionCode'] }, + 'recordcollectionid' => { 112 => [\'Record','RecordCollectionID'] }, + 'recorddatageneralizations' => { 112 => [\'Record','RecordDataGeneralizations'] }, + 'recorddatasetid' => { 112 => [\'Record','RecordDatasetID'] }, + 'recorddatasetname' => { 112 => [\'Record','RecordDatasetName'] }, + 'recorddisplay' => { 174 => 0x4d }, + 'recorddynamicproperties' => { 112 => [\'Record','RecordDynamicProperties'] }, + 'recordid' => { 91 => 0x1804 }, + 'recordinformationwithheld' => { 112 => [\'Record','RecordInformationWithheld'] }, + 'recordingformat' => { 363 => 0x1000 }, + 'recordingmode' => { 106 => 0x1, 343 => 0x1 }, + 'recordinstitutioncode' => { 112 => [\'Record','RecordInstitutionCode'] }, + 'recordinstitutionid' => { 112 => [\'Record','RecordInstitutionID'] }, + 'recordmode' => { 33 => 0x9, 107 => 0x3000 }, + 'recordownerinstitutioncode' => { 112 => [\'Record','RecordOwnerInstitutionCode'] }, + 'recordshutterrelease' => { 372 => 0x217 }, + 'redbalance' => { 283 => 0x1017, 306 => 0x11, 336 => 0x1c }, + 'redcurvelimits' => { 102 => 0x18a }, + 'redcurvepoints' => { 101 => 0x2d, 102 => 0x160 }, + 'redeyecorrection' => { 258 => 0x0 }, + 'redeyeinfo' => { 448 => 'RedEyeInfo' }, + 'redeyereduction' => { 174 => 0x41, 381 => 0x6a, 383 => 0x28 }, + 'redeyeremoval' => { 301 => 0xb9 }, + 'redhsl' => { 97 => 0x20910 }, + 'redhue' => { 448 => 'RedHue' }, + 'redsaturation' => { 448 => 'RedSaturation' }, + 'reductionmatrix1' => { 113 => 0xc625 }, + 'reductionmatrix2' => { 113 => 0xc626 }, + 'reelname' => { 113 => 0xc789 }, + 'reference1' => { 456 => [\'TagStructure','TagStructureReference'] }, + 'reference2' => { 456 => [\'TagStructure','TagStructureSubLabelsReference'] }, + 'reference3' => { 456 => [\'TagStructure','TagStructureSubLabelsSubLabelsReference'] }, + 'reference4' => { 456 => [\'TagStructure','TagStructureSubLabelsSubLabelsSubLabelsReference'] }, + 'reference5' => { 456 => [\'TagStructure','TagStructureSubLabelsSubLabelsSubLabelsSubLabelsReference'] }, + 'reference6' => { 456 => [\'TagStructure','TagStructureSubLabelsSubLabelsSubLabelsSubLabelsSubLabelsReference'] }, + 'referenceblackwhite' => { 113 => 0x214, 468 => 'ReferenceBlackWhite' }, + 'referencedate' => { 125 => 0x2f }, + 'referencenumber' => { 125 => 0x32 }, + 'references' => { 148 => 'References' }, + 'referenceservice' => { 125 => 0x2d }, + 'regionappliedtodimensions' => { 163 => [\'Regions','RegionsAppliedToDimensions'] }, + 'regionappliedtodimensionsh' => { 163 => [\'Regions','RegionsAppliedToDimensionsH'] }, + 'regionappliedtodimensionsunit' => { 163 => [\'Regions','RegionsAppliedToDimensionsUnit'] }, + 'regionappliedtodimensionsw' => { 163 => [\'Regions','RegionsAppliedToDimensionsW'] }, + 'regionarea' => { 163 => [\'Regions','RegionsRegionListArea'] }, + 'regionaread' => { 163 => [\'Regions','RegionsRegionListAreaD'] }, + 'regionareah' => { 163 => [\'Regions','RegionsRegionListAreaH'] }, + 'regionareaunit' => { 163 => [\'Regions','RegionsRegionListAreaUnit'] }, + 'regionareaw' => { 163 => [\'Regions','RegionsRegionListAreaW'] }, + 'regionareax' => { 163 => [\'Regions','RegionsRegionListAreaX'] }, + 'regionareay' => { 163 => [\'Regions','RegionsRegionListAreaY'] }, + 'regionbarcodevalue' => { 163 => [\'Regions','RegionsRegionListBarCodeValue'] }, + 'regionconstraints' => { 288 => 'RegionConstraints' }, + 'regiondescription' => { 163 => [\'Regions','RegionsRegionListDescription'] }, + 'regionextensions' => { 163 => [\'Regions','RegionsRegionListExtensions'] }, + 'regionfocususage' => { 163 => [\'Regions','RegionsRegionListFocusUsage'] }, + 'regioninfo' => { 163 => 'Regions' }, + 'regioninfodateregionsvalid' => { 166 => [\'RegionInfo','RegionInfoDateRegionsValid'] }, + 'regioninfomp' => { 166 => 'RegionInfo' }, + 'regioninforegions' => { 166 => [\'RegionInfo','RegionInfoRegions'] }, + 'regionlist' => { 163 => [\'Regions','RegionsRegionList'] }, + 'regionname' => { 163 => [\'Regions','RegionsRegionListName'] }, + 'regionpersondisplayname' => { 166 => [\'RegionInfo','RegionInfoRegionsPersonDisplayName'] }, + 'regionpersonemaildigest' => { 166 => [\'RegionInfo','RegionInfoRegionsPersonEmailDigest'] }, + 'regionpersonliveidcid' => { 166 => [\'RegionInfo','RegionInfoRegionsPersonLiveIdCID'] }, + 'regionpersonsourceid' => { 166 => [\'RegionInfo','RegionInfoRegionsPersonSourceID'] }, + 'regionrectangle' => { 166 => [\'RegionInfo','RegionInfoRegionsRectangle'] }, + 'regionrotation' => { 163 => [\'Regions','RegionsRegionListRotation'] }, + 'regionseealso' => { 163 => [\'Regions','RegionsRegionListSeeAlso'] }, + 'regiontype' => { 163 => [\'Regions','RegionsRegionListType'] }, + 'registryentryrole' => { 458 => [\'RegistryId','RegistryIdRegEntryRole'] }, + 'registryid' => { 458 => 'RegistryId' }, + 'registryitemid' => { 458 => [\'RegistryId','RegistryIdRegItemId'] }, + 'registryorganisationid' => { 458 => [\'RegistryId','RegistryIdRegOrgId'] }, + 'relatedaudiofile' => { 146 => 'data' }, + 'relatedaudiofilename' => { 146 => '1Name' }, + 'relatedaudiofiletype' => { 146 => '0Type' }, + 'relatedimagefileformat' => { 113 => 0x1000 }, + 'relatedimageheight' => { 113 => 0x1002 }, + 'relatedimagewidth' => { 113 => 0x1001 }, + 'relatedresourceid' => { 112 => [\'ResourceRelationship','ResourceRelationshipRelatedResourceID'] }, + 'relatedsoundfile' => { 113 => 0xa004, 452 => 'RelatedSoundFile' }, + 'relatedvideofile' => { 160 => 'data' }, + 'relatedvideofilename' => { 160 => '1Name' }, + 'relatedvideofiletype' => { 160 => '0Type' }, + 'relation' => { 449 => 'relation' }, + 'relationshipaccordingto' => { 112 => [\'ResourceRelationship','ResourceRelationshipRelationshipAccordingTo'] }, + 'relationshipestablisheddate' => { 112 => [\'ResourceRelationship','ResourceRelationshipRelationshipEstablishedDate'] }, + 'relationshipofresource' => { 112 => [\'ResourceRelationship','ResourceRelationshipRelationshipOfResource'] }, + 'relationshipremarks' => { 112 => [\'ResourceRelationship','ResourceRelationshipRelationshipRemarks'] }, + 'relativealtitude' => { 110 => 'RelativeAltitude' }, + 'relativepeakaudiofilepath' => { 472 => 'relativePeakAudioFilePath' }, + 'relativetimestamp' => { 472 => 'relativeTimestamp' }, + 'relativetimestampscale' => { 472 => [\'relativeTimestamp','relativeTimestampScale'] }, + 'relativetimestampvalue' => { 472 => [\'relativeTimestamp','relativeTimestampValue'] }, + 'releasebuttontousedial' => { 261 => '17.8', 262 => '18.5', 264 => '18.4', 265 => '18.4', 270 => '33.8', 271 => '17.6', 274 => '18.5', 275 => '18.4' }, + 'releasedate' => { 125 => 0x1e, 442 => 'ReleaseDate', 472 => 'releaseDate' }, + 'releasemode' => { 107 => 0x3001, 232 => 0x184d, 394 => 0xb049 }, + 'releasemode2' => { 402 => 0x112c, 403 => [0x112c,0x8], 404 => [0x1108,0x8], 405 => [0x1184,0x8], 406 => [0x1160,0x8], 407 => [0x4,0x1018], 408 => [0x4,0x210], 409 => [0x4,0x210], 410 => [0x4,0x208], 412 => [0x67,0x3f], 413 => [0x6b,0x6d,0x73,0x4b], 414 => 0x10, 415 => 0x10, 416 => 0x9, 423 => 0x34 }, + 'releasemode3' => { 402 => 0x1128, 403 => 0x1128, 404 => 0x1104, 405 => 0x1180, 406 => 0x115c, 407 => 0x1014, 408 => 0x20c, 409 => 0x20c, 410 => 0x204 }, + 'releaseready' => { 458 => 'ReleaseReady' }, + 'releasesetting' => { 91 => 0x1016 }, + 'releasetime' => { 125 => 0x23, 442 => 'ReleaseTime' }, + 'remoteonduration' => { 263 => '3.4', 266 => '17.2', 267 => '18.2', 268 => '18.2', 269 => '18.2', 271 => '18.2', 272 => '4.3', 276 => '19.2' }, + 'renditionclass' => { 473 => 'RenditionClass' }, + 'renditionof' => { 473 => 'RenditionOf' }, + 'renditionofalternatepaths' => { 473 => [\'RenditionOf','RenditionOfAlternatePaths'] }, + 'renditionofdocumentid' => { 473 => [\'RenditionOf','RenditionOfDocumentID'] }, + 'renditionoffilepath' => { 473 => [\'RenditionOf','RenditionOfFilePath'] }, + 'renditionoffrompart' => { 473 => [\'RenditionOf','RenditionOfFromPart'] }, + 'renditionofinstanceid' => { 473 => [\'RenditionOf','RenditionOfInstanceID'] }, + 'renditionoflastmodifydate' => { 473 => [\'RenditionOf','RenditionOfLastModifyDate'] }, + 'renditionoflasturl' => { 473 => [\'RenditionOf','RenditionOfLastURL'] }, + 'renditionoflinkcategory' => { 473 => [\'RenditionOf','RenditionOfLinkCategory'] }, + 'renditionoflinkform' => { 473 => [\'RenditionOf','RenditionOfLinkForm'] }, + 'renditionofmanager' => { 473 => [\'RenditionOf','RenditionOfManager'] }, + 'renditionofmanagervariant' => { 473 => [\'RenditionOf','RenditionOfManagerVariant'] }, + 'renditionofmanageto' => { 473 => [\'RenditionOf','RenditionOfManageTo'] }, + 'renditionofmanageui' => { 473 => [\'RenditionOf','RenditionOfManageUI'] }, + 'renditionofmaskmarkers' => { 473 => [\'RenditionOf','RenditionOfMaskMarkers'] }, + 'renditionoforiginaldocumentid' => { 473 => [\'RenditionOf','RenditionOfOriginalDocumentID'] }, + 'renditionofpartmapping' => { 473 => [\'RenditionOf','RenditionOfPartMapping'] }, + 'renditionofplacedresolutionunit' => { 473 => [\'RenditionOf','RenditionOfPlacedResolutionUnit'] }, + 'renditionofplacedxresolution' => { 473 => [\'RenditionOf','RenditionOfPlacedXResolution'] }, + 'renditionofplacedyresolution' => { 473 => [\'RenditionOf','RenditionOfPlacedYResolution'] }, + 'renditionofrenditionclass' => { 473 => [\'RenditionOf','RenditionOfRenditionClass'] }, + 'renditionofrenditionparams' => { 473 => [\'RenditionOf','RenditionOfRenditionParams'] }, + 'renditionoftopart' => { 473 => [\'RenditionOf','RenditionOfToPart'] }, + 'renditionofversionid' => { 473 => [\'RenditionOf','RenditionOfVersionID'] }, + 'renditionparams' => { 473 => 'RenditionParams' }, + 'repeatingflashcount' => { 198 => 0xd, 199 => 0xe, 200 => 0xe, 201 => 0xe, 202 => 0xe, 270 => '17.2', 271 => '24.2', 272 => '9.2', 273 => '24.2', 276 => '25.2' }, + 'repeatingflashcountbuilt-in' => { 240 => 0x4db }, + 'repeatingflashcountexternal' => { 240 => 0x4c3 }, + 'repeatingflashoutput' => { 270 => '17.1', 271 => '24.1', 272 => '9.1', 273 => '24.1', 276 => '25.1' }, + 'repeatingflashoutputexternal' => { 240 => 0x4c0 }, + 'repeatingflashrate' => { 198 => 0xc, 199 => 0xd, 200 => 0xd, 201 => 0xd, 202 => 0xd, 270 => '18.1', 271 => '25.1', 272 => '10.1', 273 => '25.1', 276 => '26.1' }, + 'repeatingflashratebuilt-in' => { 240 => 0x4da }, + 'repeatingflashrateexternal' => { 240 => 0x4c2 }, + 'requires' => { 445 => 'requires' }, + 'resampleparams' => { 472 => 'resampleParams' }, + 'resampleparamsquality' => { 472 => [\'resampleParams','resampleParamsQuality'] }, + 'resamplingkerneldenominators050' => { 131 => 0xe50 }, + 'resamplingkerneldenominators067' => { 131 => 0xe4f }, + 'resamplingkerneldenominators100' => { 131 => 0xe51 }, + 'resaved' => { 372 => 0x21e }, + 'resetblacksegrows' => { 131 => 0x181a }, + 'resolution' => { 153 => 'Resolution' }, + 'resolutionmode' => { 373 => 0x4 }, + 'resolutionunit' => { 113 => 0x128, 128 => 0x2, 468 => 'ResolutionUnit' }, + 'resourceid' => { 112 => [\'ResourceRelationship','ResourceRelationshipResourceID'] }, + 'resourcerelationship' => { 112 => 'ResourceRelationship' }, + 'resourcerelationshipid' => { 112 => [\'ResourceRelationship','ResourceRelationshipResourceRelationshipID'] }, + 'restrictdrivemodes' => { 78 => 0x612 }, + 'restrictions' => { 465 => 'restrictions' }, + 'retouchareafeather' => { 448 => [\'RetouchAreas','RetouchAreasFeather'] }, + 'retouchareamaskalpha' => { 448 => [\'RetouchAreas','RetouchAreasMasksAlpha'] }, + 'retouchareamaskangle' => { 448 => [\'RetouchAreas','RetouchAreasMasksAngle'] }, + 'retouchareamaskbottom' => { 448 => [\'RetouchAreas','RetouchAreasMasksBottom'] }, + 'retouchareamaskcentervalue' => { 448 => [\'RetouchAreas','RetouchAreasMasksCenterValue'] }, + 'retouchareamaskcenterweight' => { 448 => [\'RetouchAreas','RetouchAreasMasksCenterWeight'] }, + 'retouchareamaskdabs' => { 448 => [\'RetouchAreas','RetouchAreasMasksDabs'] }, + 'retouchareamaskfeather' => { 448 => [\'RetouchAreas','RetouchAreasMasksFeather'] }, + 'retouchareamaskflipped' => { 448 => [\'RetouchAreas','RetouchAreasMasksFlipped'] }, + 'retouchareamaskflow' => { 448 => [\'RetouchAreas','RetouchAreasMasksFlow'] }, + 'retouchareamaskfullx' => { 448 => [\'RetouchAreas','RetouchAreasMasksFullX'] }, + 'retouchareamaskfully' => { 448 => [\'RetouchAreas','RetouchAreasMasksFullY'] }, + 'retouchareamaskleft' => { 448 => [\'RetouchAreas','RetouchAreasMasksLeft'] }, + 'retouchareamaskmidpoint' => { 448 => [\'RetouchAreas','RetouchAreasMasksMidpoint'] }, + 'retouchareamaskperimetervalue' => { 448 => [\'RetouchAreas','RetouchAreasMasksPerimeterValue'] }, + 'retouchareamaskradius' => { 448 => [\'RetouchAreas','RetouchAreasMasksRadius'] }, + 'retouchareamaskright' => { 448 => [\'RetouchAreas','RetouchAreasMasksRight'] }, + 'retouchareamaskroundness' => { 448 => [\'RetouchAreas','RetouchAreasMasksRoundness'] }, + 'retouchareamasks' => { 448 => [\'RetouchAreas','RetouchAreasMasks'] }, + 'retouchareamasksizex' => { 448 => [\'RetouchAreas','RetouchAreasMasksSizeX'] }, + 'retouchareamasksizey' => { 448 => [\'RetouchAreas','RetouchAreasMasksSizeY'] }, + 'retouchareamasktop' => { 448 => [\'RetouchAreas','RetouchAreasMasksTop'] }, + 'retouchareamaskvalue' => { 448 => [\'RetouchAreas','RetouchAreasMasksMaskValue'] }, + 'retouchareamaskversion' => { 448 => [\'RetouchAreas','RetouchAreasMasksVersion'] }, + 'retouchareamaskwhat' => { 448 => [\'RetouchAreas','RetouchAreasMasksWhat'] }, + 'retouchareamaskx' => { 448 => [\'RetouchAreas','RetouchAreasMasksX'] }, + 'retouchareamasky' => { 448 => [\'RetouchAreas','RetouchAreasMasksY'] }, + 'retouchareamaskzerox' => { 448 => [\'RetouchAreas','RetouchAreasMasksZeroX'] }, + 'retouchareamaskzeroy' => { 448 => [\'RetouchAreas','RetouchAreasMasksZeroY'] }, + 'retouchareamethod' => { 448 => [\'RetouchAreas','RetouchAreasMethod'] }, + 'retouchareaoffsety' => { 448 => [\'RetouchAreas','RetouchAreasOffsetY'] }, + 'retouchareaopacity' => { 448 => [\'RetouchAreas','RetouchAreasOpacity'] }, + 'retouchareas' => { 448 => 'RetouchAreas' }, + 'retouchareaseed' => { 448 => [\'RetouchAreas','RetouchAreasSeed'] }, + 'retouchareasourcestate' => { 448 => [\'RetouchAreas','RetouchAreasSourceState'] }, + 'retouchareasourcex' => { 448 => [\'RetouchAreas','RetouchAreasSourceX'] }, + 'retouchareaspottype' => { 448 => [\'RetouchAreas','RetouchAreasSpotType'] }, + 'retouchhistory' => { 214 => 0x9e }, + 'retouchinfo' => { 448 => 'RetouchInfo' }, + 'retouchnefprocessing' => { 221 => 0x5 }, + 'retractlensonpoweroff' => { 78 => 0x814 }, + 'reuse' => { 288 => 'Reuse' }, + 'reuseallowed' => { 475 => 'ReuseAllowed' }, + 'reuseprohibited' => { 465 => 'reuseProhibited' }, + 'reverseexposurecompdial' => { 268 => '5.2' }, + 'reverseindicators' => { 261 => '12.1', 262 => '6.1', 264 => '6.1', 265 => '6.1', 266 => '4.3', 267 => '5.2', 268 => '5.4', 270 => '33.5', 271 => '5.1', 274 => '6.1', 275 => '6.1', 276 => '6.2' }, + 'reverseshutterspeedaperture' => { 268 => '5.3' }, + 'revision' => { 450 => 'revision' }, + 'rflensmffocusringsensitivity' => { 78 => 0x714 }, + 'rgbcurvelimits' => { 102 => 0x238 }, + 'rgbcurvepoints' => { 101 => 0x7, 102 => 0x20e }, + 'richtextcomment' => { 455 => 'RichTextComment' }, + 'ricohdate' => { 362 => 0x6 }, + 'ricohimageheight' => { 362 => 0x2 }, + 'ricohimagewidth' => { 362 => 0x0 }, + 'rightalbedo' => { 438 => 'RightAlbedo' }, + 'rightascension' => { 156 => 'RightAscension' }, + 'rights' => { 449 => 'rights' }, + 'rightsagent' => { 465 => 'rightsAgent' }, + 'rightsowner' => { 465 => 'rightsOwner' }, + 'roll' => { 109 => 0x8 }, + 'rollangle' => { 232 => 0x350b, 233 => 0x2c24, 241 => 0x36f4, 278 => 0x903, 301 => 0x90, 335 => 0x1, 368 => 0x2 }, + 'romoperationmode' => { 91 => 0x80d }, + 'rotation' => { 29 => 0x17, 30 => 0x18, 90 => 0x3, 97 => 0x10002, 102 => 0x26e, 108 => 'Rotation', 117 => 0x4, 156 => 'Rotation', 172 => [0x65,0x50], 173 => 0x46, 174 => 0x5a, 177 => 0x10, 232 => 0x3693, 233 => 0xca, 239 => '590.1', 254 => 0x76a43207, 301 => 0x30, 317 => '17.2', 347 => 0xd8, 381 => 0x3f, 382 => 0x3f, 392 => 0x10 }, + 'routedto' => { 454 => 'RoutedTo' }, + 'routing' => { 352 => 'Routing' }, + 'routingdestinations' => { 437 => 'RoutingDestinations' }, + 'routingexclusions' => { 437 => 'RoutingExclusions' }, + 'routingnotes' => { 454 => 'RoutingNotes' }, + 'rowsperstrip' => { 113 => 0x116 }, + 'rpp' => { 442 => 'rpp' }, + 'rtkflag' => { 110 => 'RtkFlag' }, + 'rtkstdhgt' => { 110 => 'RtkStdHgt' }, + 'rtkstdlat' => { 110 => 'RtkStdLat' }, + 'rtkstdlon' => { 110 => 'RtkStdLon' }, + 'safetyshift' => { 78 => 0x108 }, + 'safetyshiftinavortv' => { 76 => 0x10, 77 => 0x10, 79 => 0xf, 80 => 0x10, 83 => 0x10 }, + 'sameexposurefornewaperture' => { 78 => 0x112 }, + 'samplebits' => { 146 => 'SampleBits' }, + 'samplepagerange' => { 462 => 'samplePageRange' }, + 'samplerate' => { 146 => 'SampleRate' }, + 'samplesperpixel' => { 113 => 0x115, 306 => 0x8, 468 => 'SamplesPerPixel' }, + 'samplestructure' => { 127 => 0x5a }, + 'samsungmodelid' => { 370 => 0x3 }, + 'sanyoquality' => { 372 => 0x201 }, + 'sanyothumbnail' => { 372 => 0x100 }, + 'saturation' => { 9 => 0x6e, 11 => 0x76, 33 => 0xe, 48 => 0x1, 106 => 0xd, 107 => [0x3013,0x1f], 113 => [0xa409,0xfe55], 121 => 0x1003, 147 => 'Saturation', 171 => 0x1f, 172 => 0x32, 173 => 0x28, 174 => 0x1a, 179 => 0x1, 214 => [0x94,0xaa], 216 => 0x35, 217 => 0x3b, 218 => 0x43, 301 => 0x40, 303 => 0x300d, 336 => 0x1f, 343 => 0xd, 357 => 0x27, 359 => 0x58, 362 => 0x28, 363 => 0x1013, 373 => 0x10, 381 => 0x1e, 382 => 0x1b, 394 => 0x2005, 448 => 'Saturation', 452 => 'Saturation' }, + 'saturationadj' => { 97 => 0x20901, 102 => 0x116, 253 => 0x1, 257 => 0x2e, 427 => 0x8016 }, + 'saturationadjustmentaqua' => { 448 => 'SaturationAdjustmentAqua' }, + 'saturationadjustmentblue' => { 448 => 'SaturationAdjustmentBlue' }, + 'saturationadjustmentgreen' => { 448 => 'SaturationAdjustmentGreen' }, + 'saturationadjustmentmagenta' => { 448 => 'SaturationAdjustmentMagenta' }, + 'saturationadjustmentorange' => { 448 => 'SaturationAdjustmentOrange' }, + 'saturationadjustmentpurple' => { 448 => 'SaturationAdjustmentPurple' }, + 'saturationadjustmentred' => { 448 => 'SaturationAdjustmentRed' }, + 'saturationadjustmentyellow' => { 448 => 'SaturationAdjustmentYellow' }, + 'saturationauto' => { 67 => 0x98 }, + 'saturationfaithful' => { 18 => 0xfe, 66 => 0x68, 67 => 0x68 }, + 'saturationlandscape' => { 18 => 0xfc, 66 => 0x38, 67 => 0x38 }, + 'saturationmonochrome' => { 66 => 0x80, 67 => 0x80 }, + 'saturationneutral' => { 18 => 0xfd, 66 => 0x50, 67 => 0x50 }, + 'saturationportrait' => { 18 => 0xfb, 66 => 0x20, 67 => 0x20 }, + 'saturationsetting' => { 286 => 0x1010, 383 => 0x11, 399 => 0x9 }, + 'saturationstandard' => { 18 => 0xfa, 66 => 0x8, 67 => 0x8 }, + 'saturationuserdef1' => { 18 => 0x100, 66 => 0x98, 67 => 0xb0 }, + 'saturationuserdef2' => { 18 => 0x101, 66 => 0xb0, 67 => 0xc8 }, + 'saturationuserdef3' => { 18 => 0x102, 66 => 0xc8, 67 => 0xe0 }, + 'saveid' => { 473 => 'SaveID' }, + 'sbaanalysiscomplete' => { 131 => 0xc35 }, + 'sbablack' => { 131 => 0xc25 }, + 'sbagmoffset' => { 131 => 0xc4a }, + 'sbagray' => { 131 => 0xc26 }, + 'sbagreenmagentabal' => { 131 => 0xc33 }, + 'sbahighgray' => { 131 => 0xc46 }, + 'sbailloffset' => { 131 => 0xc49 }, + 'sbailluminantbal' => { 131 => 0xc34 }, + 'sbalowgray' => { 131 => 0xc47 }, + 'sbaneutralbal' => { 131 => 0xc32 }, + 'sbawhite' => { 131 => 0xc27 }, + 'scaletype' => { 472 => 'scaleType' }, + 'scanimageenhancer' => { 222 => 0x60 }, + 'scanningdirection' => { 127 => 0x64 }, + 'scene' => { 457 => 'Scene', 472 => 'scene' }, + 'scenearea' => { 281 => 0x211, 283 => 0x1031 }, + 'sceneassist' => { 214 => 0x9c }, + 'scenecapturetype' => { 113 => 0xa406, 452 => 'SceneCaptureType' }, + 'scenedetect' => { 281 => 0x210, 283 => 0x1030 }, + 'scenedetectdata' => { 281 => 0x212, 283 => 0x1033 }, + 'scenemode' => { 135 => 0xfa02, 176 => 0x100, 214 => 0x8f, 278 => 0x509, 283 => 0x403, 301 => 0x8001, 310 => 0xf, 394 => 0xb023 }, + 'scenemodeused' => { 137 => [0x6002,0xf002] }, + 'scenerecognition' => { 121 => 0x1425 }, + 'sceneselect' => { 372 => 0x21f }, + 'scenetype' => { 113 => 0xa301, 452 => 'SceneType' }, + 'screentips' => { 261 => '12.7', 262 => '5.3', 270 => '13.1', 271 => '4.4', 274 => '5.4', 276 => '5.1' }, + 'scriptversion' => { 131 => 0x1770 }, + 'season' => { 458 => 'Season', 461 => 'season' }, + 'seasonidentifier' => { 458 => [\'Season','SeasonIdentifier'] }, + 'seasonname' => { 458 => [\'Season','SeasonName'] }, + 'seasonnumber' => { 458 => [\'Season','SeasonNumber'] }, + 'secondaryftp' => { 437 => 'SecondaryFTP' }, + 'secondaryslotfunction' => { 232 => 0x1d0, 241 => 0x1d0 }, + 'section' => { 462 => 'section' }, + 'securityclassification' => { 113 => 0x9212 }, + 'selectableafpoint' => { 78 => 0x509 }, + 'selectafareaselectionmode' => { 2 => 0xc }, + 'selectafareaselectmode' => { 78 => 0x512 }, + 'selfdata' => { 110 => 'SelfData' }, + 'selftimer' => { 33 => 0x2, 301 => 0x2e, 372 => 0x214, 402 => 0x1134, 403 => 0x1134, 404 => 0x1110, 405 => 0x118c, 406 => 0x1168, 407 => 0x1020, 408 => 0x218, 409 => 0x218, 410 => 0x210 }, + 'selftimer2' => { 72 => 0x1d }, + 'selftimerinterval' => { 271 => '19.2' }, + 'selftimermode' => { 113 => 0x882b }, + 'selftimershotcount' => { 262 => '20.2', 264 => '20.3', 265 => '20.3', 266 => '18.2', 267 => '19.2', 268 => '19.2', 269 => '19.3', 271 => '19.3', 274 => '20.3', 275 => '20.3', 276 => '20.2' }, + 'selftimershotinterval' => { 262 => '20.3', 264 => '20.2', 265 => '20.2', 269 => '19.2', 274 => '20.2', 275 => '20.2' }, + 'selftimertime' => { 91 => 0x1806, 174 => 0x1f, 261 => '18.1', 262 => '20.1', 263 => '3.3', 264 => '20.1', 265 => '20.1', 266 => '18.1', 267 => '19.1', 268 => '19.1', 269 => '19.1', 270 => '7.2', 271 => '19.1', 272 => '3.3', 274 => '20.1', 275 => '20.1', 276 => '20.1' }, + 'sellingagency' => { 462 => 'sellingAgency' }, + 'seminfo' => { 113 => 0x8546 }, + 'sensingmethod' => { 113 => 0xa217, 452 => 'SensingMethod' }, + 'sensitivityadjust' => { 336 => 0x40 }, + 'sensitivitysteps' => { 317 => ['14.3','17.4'], 319 => 0x1 }, + 'sensitivitytype' => { 113 => 0x8830, 453 => 'SensitivityType' }, + 'sensor' => { 181 => 0x665e }, + 'sensorareas' => { 370 => 0xa010 }, + 'sensorbitdepth' => { 303 => 0x312d }, + 'sensorbluelevel' => { 70 => 0x5 }, + 'sensorcalibration' => { 282 => 0x805 }, + 'sensorcleaning' => { 84 => 0xd }, + 'sensorfullheight' => { 130 => 0xf904 }, + 'sensorfullwidth' => { 130 => 0xf903 }, + 'sensorheight' => { 130 => 0xf901, 135 => 0xfa21, 178 => 0x8, 303 => 0x312c, 345 => 0x109, 363 => 0x1602 }, + 'sensorimageheight' => { 131 => 0x3ee }, + 'sensorimagewidth' => { 131 => 0x3ed }, + 'sensorleftborder' => { 131 => 0x3eb }, + 'sensorleftmargin' => { 345 => 0x10a }, + 'sensorpixelsize' => { 214 => 0x9a }, + 'sensorredlevel' => { 70 => 0x4 }, + 'sensorserialnumber' => { 131 => 0x9ce }, + 'sensorsize' => { 147 => 'SensorSize', 336 => 0x35 }, + 'sensortemperature' => { 281 => 0x1500, 283 => 0x1007, 341 => 0xc, 345 => 0x210, 373 => [0x39,0x55] }, + 'sensortemperature2' => { 341 => 0xe, 345 => 0x211 }, + 'sensortopborder' => { 131 => 0x3ec }, + 'sensortopmargin' => { 345 => 0x10b }, + 'sensorwidth' => { 130 => 0xf900, 135 => 0xfa20, 178 => 0xa, 303 => 0x312b, 345 => 0x108, 363 => 0x1601 }, + 'sequence' => { 357 => 0x7, 358 => 0x35, 359 => 0x36 }, + 'sequencefilenumber' => { 403 => 0x4, 404 => 0x4, 405 => 0x4, 406 => 0x4, 414 => 0xc, 415 => 0xc, 416 => 0x1a }, + 'sequenceimagenumber' => { 403 => 0x0, 404 => 0x0, 405 => 0x0, 406 => 0x0, 414 => 0x8, 415 => 0x8, 416 => 0x12, 423 => 0x24 }, + 'sequencelength' => { 414 => 0x22, 415 => 0x1e, 416 => [0x16,0x1e] }, + 'sequencename' => { 461 => 'sequenceName' }, + 'sequencenumber' => { 72 => 0x9, 107 => 0x301c, 121 => 0x1101, 133 => 0x1d, 240 => 0x51c, 301 => 0x2b, 383 => [0x10c,0x30c], 394 => 0xb04a, 461 => 'sequenceNumber' }, + 'sequenceshotinterval' => { 372 => 0x224 }, + 'sequencetotalnumber' => { 461 => 'sequenceTotalNumber' }, + 'sequentialshot' => { 372 => 0x20e }, + 'serialnumber' => { 60 => 0xc, 91 => 0x180b, 113 => [0xa431,0xfde9], 130 => 0xfa04, 132 => 0xfa00, 134 => 0xc354, 135 => 0xfa19, 144 => 0x0, 147 => 'SerialNumber', 214 => [0xa0,0x1d], 279 => 0x101, 283 => [0x404,0x101a], 296 => 0x303, 298 => 0x305, 303 => 0x3103, 336 => 0x229, 345 => 0x102, 346 => 0x407, 357 => 0x15, 358 => 0x4b, 359 => 0x7e, 363 => 0x5, 370 => 0xa002, 373 => 0x2, 394 => 0x2031, 444 => 'SerialNumber', 453 => 'BodySerialNumber' }, + 'serialnumberformat' => { 60 => 0x15, 91 => 0x183b }, + 'series' => { 458 => 'Series' }, + 'seriesdatetime' => { 429 => 'SeriesDateTime' }, + 'seriesdescription' => { 429 => 'SeriesDescription' }, + 'seriesidentifier' => { 458 => [\'Series','SeriesIdentifier'] }, + 'seriesmodality' => { 429 => 'SeriesModality' }, + 'seriesname' => { 458 => [\'Series','SeriesName'] }, + 'seriesnumber' => { 429 => 'SeriesNumber', 462 => 'seriesNumber' }, + 'seriestitle' => { 462 => 'seriesTitle' }, + 'serviceidentifier' => { 126 => 0x1e }, + 'servingsize' => { 464 => 'servingSize' }, + 'setbuttoncrosskeysfunc' => { 81 => 0x0, 82 => 0x0 }, + 'setbuttonwhenshooting' => { 76 => 0x1, 78 => 0x704, 84 => 0xc }, + 'setfunctionwhenshooting' => { 79 => 0x0, 80 => 0x1, 83 => 0x1 }, + 'setting' => { 461 => 'setting' }, + 'shadingcompensation' => { 278 => 0x50c, 301 => 0x8a }, + 'shadingcompensation2' => { 282 => 0x1012 }, + 'shadow' => { 373 => 0xe }, + 'shadowadj' => { 97 => 0x2030b }, + 'shadowcorrection' => { 336 => 0x79 }, + 'shadowprotection' => { 253 => 0x0 }, + 'shadows' => { 113 => 0xfe52, 441 => 'Shadows', 448 => 'Shadows' }, + 'shadows2012' => { 448 => 'Shadows2012' }, + 'shadowsadj' => { 427 => 0x901a }, + 'shadowscale' => { 113 => 0xc633 }, + 'shadowtint' => { 448 => 'ShadowTint' }, + 'shadowtone' => { 121 => 0x1040 }, + 'shakereduction' => { 338 => 0x1, 339 => 0x1 }, + 'sharpendetail' => { 448 => 'SharpenDetail' }, + 'sharpenedgemasking' => { 448 => 'SharpenEdgeMasking' }, + 'sharpening' => { 303 => 0x300b }, + 'sharpeningadj' => { 257 => 0x2b }, + 'sharpeningkernel' => { 131 => 0x92f }, + 'sharpenradius' => { 448 => 'SharpenRadius' }, + 'sharpness' => { 7 => [0x42,0x48], 9 => 0x72, 11 => 0x74, 33 => 0xf, 70 => 0x2, 106 => 0xb, 107 => [0x3011,0x21], 113 => [0xa40a,0xfe56], 121 => 0x1001, 133 => 0x6b, 142 => 0x37, 147 => 'Sharpness', 171 => 0x21, 172 => 0x30, 173 => 0x26, 174 => 0x18, 179 => 0x3, 214 => 0x6, 216 => 0x32, 217 => 0x33, 218 => 0x39, 283 => 0x100f, 301 => 0x41, 336 => 0x21, 343 => 0xb, 357 => 0x26, 359 => 0x56, 362 => 0x22, 363 => [0x1003,0x1014], 373 => 0x11, 381 => 0x1c, 382 => 0x19, 394 => 0x2006, 423 => 0x52, 448 => 'Sharpness', 452 => 'Sharpness' }, + 'sharpnessadj' => { 97 => 0x20310, 102 => 0x25a, 427 => 0x801a }, + 'sharpnessadjon' => { 97 => '0x20310.0' }, + 'sharpnessauto' => { 67 => 0x94 }, + 'sharpnessfactor' => { 283 => 0x102a }, + 'sharpnessfaithful' => { 18 => 0xf5, 66 => 0x64, 67 => 0x64 }, + 'sharpnessfrequency' => { 7 => [0x41,0x47], 70 => 0x3 }, + 'sharpnesslandscape' => { 18 => 0xf3, 66 => 0x34, 67 => 0x34 }, + 'sharpnessmonochrome' => { 18 => 0xf6, 66 => 0x7c, 67 => 0x7c }, + 'sharpnessneutral' => { 18 => 0xf4, 66 => 0x4c, 67 => 0x4c }, + 'sharpnessovershoot' => { 427 => 0x801b }, + 'sharpnessportrait' => { 18 => 0xf2, 66 => 0x1c, 67 => 0x1c }, + 'sharpnesssetting' => { 278 => 0x506, 286 => 0x1013, 383 => 0x12, 399 => 0xa }, + 'sharpnessstandard' => { 18 => 0xf1, 66 => 0x4, 67 => 0x4 }, + 'sharpnessstrength' => { 97 => 0x20311 }, + 'sharpnessthreshold' => { 427 => 0x801d }, + 'sharpnessundershoot' => { 427 => 0x801c }, + 'sharpnessuserdef1' => { 18 => 0xf7, 66 => 0x94, 67 => 0xac }, + 'sharpnessuserdef2' => { 18 => 0xf8, 66 => 0xac, 67 => 0xc4 }, + 'sharpnessuserdef3' => { 18 => 0xf9, 66 => 0xc4, 67 => 0xdc }, + 'shiftcols' => { 131 => 0xc70 }, + 'shootid' => { 461 => 'shootID' }, + 'shootingdistance' => { 97 => 0x20701 }, + 'shootinginfodisplay' => { 261 => '13.2', 262 => '5.1', 270 => '10.2', 271 => '4.1', 274 => '5.1', 276 => '5.3' }, + 'shootinginfomonitorofftime' => { 261 => '26.2', 262 => '22.2', 264 => '22.2', 265 => '22.2', 269 => '21.2', 270 => '9.1', 271 => '21.2', 274 => '22.2', 275 => '22.2', 276 => '22.2' }, + 'shootingmode' => { 147 => 'ShootingMode', 214 => 0x89, 301 => 0x1f }, + 'shootingmodesetting' => { 263 => '5.1' }, + 'shortdescription' => { 450 => 'shortdescription' }, + 'shortdocumentid' => { 125 => 0xba }, + 'shortownername' => { 18 => 0xac }, + 'shortreleasetimelag' => { 78 => 0x80d }, + 'shotdate' => { 472 => 'shotDate' }, + 'shotday' => { 472 => 'shotDay' }, + 'shotlocation' => { 472 => 'shotLocation' }, + 'shotname' => { 472 => 'shotName' }, + 'shotnumber' => { 472 => 'shotNumber' }, + 'shotnumbersincepowerup' => { 398 => 0x44e, 414 => 0x1a, 415 => 0x16, 416 => 0xa }, + 'shotnumbersincepowerup2' => { 383 => 0x200 }, + 'shotsize' => { 472 => 'shotSize' }, + 'shownevent' => { 458 => 'EventExt' }, + 'showneventidentifier' => { 458 => [\'EventExt','EventExtIdentifier'] }, + 'showneventname' => { 458 => [\'EventExt','EventExtName'] }, + 'shutter' => { 413 => 0x2c }, + 'shutter-aelock' => { 76 => 0x4, 78 => 0x701, 79 => 0x3, 80 => 0x4, 81 => 0x3, 82 => 0x3, 83 => 0x4, 84 => 0x2 }, + 'shutteraelbutton' => { 77 => 0x4 }, + 'shutterbuttonafonbutton' => { 78 => 0x701 }, + 'shuttercount' => { 10 => 0x176, 54 => 0x1, 214 => 0xa7, 223 => [0x6a,0x157,0x24d], 224 => 0x286, 225 => 0x279, 226 => 0x284, 227 => 0x242, 228 => 0x280, 229 => 0x276, 230 => [0x27d,0x27f], 231 => 0x246, 234 => 0x2d6, 235 => 0x321, 236 => 0xbd8, 237 => 0x287, 238 => 0x320, 239 => 0x24a, 240 => 0x5fb, 243 => 0x2d5, 336 => 0x5d, 392 => 0x846, 397 => [0x125,0x14a], 412 => 0x32, 413 => 0x3a }, + 'shuttercount2' => { 412 => 0x4c, 413 => [0x50,0x52,0x58] }, + 'shuttercount3' => { 412 => [0x1a0,0x1aa,0x1bd], 413 => [0x19f,0x1cb,0x1cd] }, + 'shuttercurtainsync' => { 76 => 0xf, 77 => 0xf, 78 => 0x305, 79 => 0xe, 80 => 0xf, 81 => 0x8, 82 => 0x8, 83 => 0xf, 84 => 0x8 }, + 'shuttermode' => { 133 => 0x1b, 214 => 0x34 }, + 'shutterreleasebuttonae-l' => { 261 => '17.7', 262 => '18.4', 264 => '78.4', 265 => '78.4', 266 => '16.1', 267 => '17.1', 268 => '17.1', 269 => '17.1', 270 => '7.1', 271 => '17.5', 274 => '18.4', 275 => '78.4', 276 => '18.2' }, + 'shutterreleasemethod' => { 91 => 0x1010 }, + 'shutterreleasenocfcard' => { 76 => 0x2, 77 => 0x2, 84 => 0xf }, + 'shutterreleasetiming' => { 91 => 0x1011 }, + 'shutterreleasewithoutlens' => { 78 => 0x711 }, + 'shutterspeedlock' => { 262 => '38.1', 264 => '38.1', 265 => '38.1', 274 => '38.1', 275 => '38.1' }, + 'shutterspeedrange' => { 78 => 0x10c }, + 'shutterspeedsetting' => { 174 => 0x6, 381 => 0x2f, 382 => 0x28, 383 => 0x0 }, + 'shutterspeedvalue' => { 87 => 0x1, 113 => 0x9201, 283 => 0x1000, 345 => 0x400, 452 => 'ShutterSpeedValue' }, + 'shuttertype' => { 121 => 0x1050, 301 => 0x9f }, + 'sidecarforextension' => { 460 => 'SidecarForExtension' }, + 'sigmaimpulseparameters' => { 131 => 0xe0d }, + 'sigmascalingfactorcamera' => { 131 => 0xe0c }, + 'sigmascalingfactorlowres' => { 131 => 0xe0b }, + 'sigmasizetable' => { 131 => 0xe0f }, + 'similarityindex' => { 125 => 0xe4 }, + 'singleframebracketing' => { 174 => 0x21 }, + 'skilllevel' => { 464 => 'skillLevel' }, + 'skintonecorrection' => { 336 => 0x95 }, + 'skiplinetime' => { 131 => 0x184e }, + 'slaveflashmeteringsegments' => { 336 => 0x20b }, + 'slideshowname' => { 461 => 'slideshowName' }, + 'slideshownumber' => { 461 => 'slideshowNumber' }, + 'slideshowtotalnumber' => { 461 => 'slideshowTotalNumber' }, + 'slowshutter' => { 72 => 0x8 }, + 'slowsync' => { 121 => 0x1030 }, + 'smartalbumcolor' => { 370 => 0x20 }, + 'smartrange' => { 370 => 0xa012 }, + 'smileshutter' => { 383 => 0x31 }, + 'smileshuttermode' => { 383 => 0x27 }, + 'smoothness' => { 113 => 0xfe57, 448 => 'Smoothness' }, + 'snapshot' => { 458 => 'SnapshotLink' }, + 'snapshotformat' => { 458 => [\'SnapshotLink','SnapshotLinkFormat'] }, + 'snapshotheightpixels' => { 458 => [\'SnapshotLink','SnapshotLinkHeightPixels'] }, + 'snapshotimagerole' => { 458 => [\'SnapshotLink','SnapshotLinkImageRole'] }, + 'snapshotlink' => { 458 => [\'SnapshotLink','SnapshotLinkLink'] }, + 'snapshotlinkqualifier' => { 458 => [\'SnapshotLink','SnapshotLinkLinkQualifier'] }, + 'snapshots' => { 442 => 'Snapshots' }, + 'snapshotusedvideoframe' => { 458 => [\'SnapshotLink','SnapshotLinkUsedVideoFrame'] }, + 'snapshotusedvideoframetimeformat' => { 458 => [\'SnapshotLink','SnapshotLinkUsedVideoFrameTimeFormat'] }, + 'snapshotusedvideoframetimevalue' => { 458 => [\'SnapshotLink','SnapshotLinkUsedVideoFrameTimeValue'] }, + 'snapshotusedvideoframevalue' => { 458 => [\'SnapshotLink','SnapshotLinkUsedVideoFrameValue'] }, + 'snapshotwidthpixels' => { 458 => [\'SnapshotLink','SnapshotLinkWidthPixels'] }, + 'softskineffect' => { 394 => 0x200f }, + 'software' => { 113 => 0x131, 148 => 'Software', 291 => 'Software', 345 => 0x203, 373 => 0x18, 432 => 'Software', 468 => 'Software' }, + 'softwareversion' => { 372 => 0x207 }, + 'sonydatetime' => { 401 => 0x6, 403 => 0x1b6, 404 => 0x210, 405 => 0x1fe, 406 => 0x22c }, + 'sonydatetime2' => { 412 => 0x51 }, + 'sonyexposuretime' => { 412 => 0x3a, 413 => 0x46 }, + 'sonyexposuretime2' => { 423 => 0xe }, + 'sonyfnumber' => { 412 => 0x3c, 413 => 0x48, 423 => 0x14 }, + 'sonyimageheight' => { 401 => 0x1a, 414 => 0x44, 415 => 0x3f, 416 => 0x47 }, + 'sonyimageheightmax' => { 423 => 0x40 }, + 'sonyimagesize' => { 174 => 0x3b, 381 => 0x54, 382 => 0x54, 383 => 0x9 }, + 'sonyimagewidth' => { 401 => 0x1c }, + 'sonyimagewidthmax' => { 423 => 0x3e }, + 'sonyiso' => { 403 => 0x1218, 404 => 0x11f4, 405 => 0x1270, 406 => [0x1254,0x1258,0x1280], 407 => 0x113c, 408 => 0x344, 409 => 0x346, 410 => 0x320, 423 => 0x4 }, + 'sonymaxaperture' => { 412 => 0x0, 413 => 0x0 }, + 'sonymaxaperturevalue' => { 423 => 0x16 }, + 'sonyminaperture' => { 412 => 0x1, 413 => 0x1 }, + 'sonymodelid' => { 394 => 0xb001 }, + 'sonyquality' => { 174 => 0x3c }, + 'sonytimeminsec' => { 413 => 0x61 }, + 'source' => { 125 => 0x73, 291 => 'Source', 449 => 'source', 450 => 'source', 460 => 'Source' }, + 'sourcecount' => { 436 => 'SourceCount' }, + 'sourcedirectoryindex' => { 323 => 0x0 }, + 'sourcefileindex' => { 323 => 0x2 }, + 'sourcephotoscount' => { 435 => 'SourcePhotosCount' }, + 'sourceprofileprefix' => { 131 => 0x1390 }, + 'spatialfrequencyresponse' => { 452 => 'SpatialFrequencyResponse' }, + 'spatialfrequencyresponsecolumns' => { 452 => [\'SpatialFrequencyResponse','SpatialFrequencyResponseColumns'] }, + 'spatialfrequencyresponsenames' => { 452 => [\'SpatialFrequencyResponse','SpatialFrequencyResponseNames'] }, + 'spatialfrequencyresponserows' => { 452 => [\'SpatialFrequencyResponse','SpatialFrequencyResponseRows'] }, + 'spatialfrequencyresponsevalues' => { 452 => [\'SpatialFrequencyResponse','SpatialFrequencyResponseValues'] }, + 'speakerplacement' => { 472 => 'speakerPlacement' }, + 'specialeffectlevel' => { 107 => 0x3030 }, + 'specialeffectmode' => { 107 => 0x2076 }, + 'specialeffectsetting' => { 107 => 0x3031 }, + 'specialinstructions' => { 125 => 0x28 }, + 'specialmode' => { 283 => 0x200, 372 => 0x200 }, + 'specialoccasion' => { 464 => 'specialOccasion' }, + 'spectralsensitivity' => { 113 => 0x8824, 452 => 'SpectralSensitivity' }, + 'specularwhitelevel' => { 42 => [0x2b9,0x2d0,0x2d4], 44 => 0x1e4, 45 => [0x1fd,0x2dd], 46 => [0x231,0x30f], 47 => 0x31d }, + 'speedx' => { 109 => 0x3 }, + 'speedy' => { 109 => 0x4 }, + 'speedz' => { 109 => 0x5 }, + 'spherical' => { 436 => 'Spherical' }, + 'splitcolumn' => { 345 => 0x222 }, + 'splittoningbalance' => { 448 => 'SplitToningBalance' }, + 'splittoninghighlighthue' => { 448 => 'SplitToningHighlightHue' }, + 'splittoninghighlightsaturation' => { 448 => 'SplitToningHighlightSaturation' }, + 'splittoningshadowhue' => { 448 => 'SplitToningShadowHue' }, + 'splittoningshadowsaturation' => { 448 => 'SplitToningShadowSaturation' }, + 'sport' => { 462 => 'sport' }, + 'spotfocuspointx' => { 171 => 0x2d }, + 'spotfocuspointy' => { 171 => 0x2e }, + 'spotmeteringmode' => { 33 => 0x27 }, + 'spotmeterlinktoafpoint' => { 78 => 0x107 }, + 'sractive' => { 317 => '17.1' }, + 'srawquality' => { 33 => 0x2e }, + 'srfocallength' => { 338 => 0x3 }, + 'srhalfpresstime' => { 338 => 0x2 }, + 'srresult' => { 338 => 0x0, 339 => 0x0 }, + 'stackedimage' => { 278 => 0x804 }, + 'standardmatrixcustom' => { 131 => 0x7d4 }, + 'standardmatrixdaylight' => { 131 => 0x7d0 }, + 'standardmatrixflash' => { 131 => 0x7d3 }, + 'standardmatrixfluorescent' => { 131 => 0x7d2 }, + 'standardmatrixtungsten' => { 131 => 0x7d1 }, + 'standardoutputhighlightpoint' => { 103 => 0x14 }, + 'standardoutputsensitivity' => { 113 => 0x8831, 453 => 'StandardOutputSensitivity' }, + 'standardoutputshadowpoint' => { 103 => 0x15 }, + 'standardrawcolortone' => { 103 => 0xd }, + 'standardrawcontrast' => { 103 => 0xf }, + 'standardrawhighlight' => { 103 => 0x75 }, + 'standardrawhighlightpoint' => { 103 => 0x12 }, + 'standardrawlinear' => { 103 => 0x10 }, + 'standardrawsaturation' => { 103 => 0xe }, + 'standardrawshadow' => { 103 => 0x7e }, + 'standardrawshadowpoint' => { 103 => 0x13 }, + 'standardrawsharpness' => { 103 => 0x11 }, + 'standardunsharpmaskfineness' => { 103 => 0x94 }, + 'standardunsharpmaskstrength' => { 103 => 0x92 }, + 'standardunsharpmaskthreshold' => { 103 => 0x96 }, + 'standardwhitecustom' => { 131 => 0x838 }, + 'standardwhitedaylight' => { 131 => 0x834 }, + 'standardwhiteflash' => { 131 => 0x837 }, + 'standardwhitefluorescent' => { 131 => 0x836 }, + 'standardwhitetungsten' => { 131 => 0x835 }, + 'standbytimer' => { 262 => '19.1', 264 => '19.1', 265 => '19.1', 268 => '18.1', 269 => '18.1', 274 => '19.1', 275 => '19.1' }, + 'startingpage' => { 462 => 'startingPage' }, + 'startmovieshooting' => { 78 => 0x70d }, + 'starttimecode' => { 472 => 'startTimecode' }, + 'starttimecodetimeformat' => { 472 => [\'startTimecode','startTimecodeTimeFormat'] }, + 'starttimecodetimevalue' => { 472 => [\'startTimecode','startTimecodeTimeValue'] }, + 'starttimecodevalue' => { 472 => [\'startTimecode','startTimecodeValue'] }, + 'starttimesamplesize' => { 472 => 'startTimeSampleSize' }, + 'starttimescale' => { 472 => 'startTimeScale' }, + 'state' => { 152 => 'State', 301 => 0x6b, 460 => 'State' }, + 'status' => { 430 => 'Status', 440 => 'Status' }, + 'stereomode' => { 436 => 'StereoMode' }, + 'stitched' => { 436 => 'Stitched' }, + 'stitchingsoftware' => { 435 => 'StitchingSoftware', 436 => 'StitchingSoftware' }, + 'stopsabovebaseiso' => { 402 => 0x113e, 403 => 0x113e, 404 => 0x111a, 405 => 0x1196, 406 => 0x1172, 407 => 0x102a, 408 => 0x222, 409 => 0x222, 410 => 0x217, 423 => 0xa }, + 'storagemethod' => { 178 => 0x12 }, + 'storebyorientation' => { 262 => '46.3', 264 => '47.3', 265 => '47.3', 274 => '47.3', 275 => '47.3' }, + 'storylineidentifier' => { 458 => 'StorylineIdentifier' }, + 'straightenangle' => { 254 => 0x2fc08431 }, + 'streamready' => { 458 => 'StreamReady' }, + 'streamtype' => { 167 => 'StreamType' }, + 'stretchmode' => { 472 => 'stretchMode' }, + 'studydatetime' => { 429 => 'StudyDateTime' }, + 'studydescription' => { 429 => 'StudyDescription' }, + 'studyid' => { 429 => 'StudyID' }, + 'studyphysician' => { 429 => 'StudyPhysician' }, + 'styleperiod' => { 458 => 'StylePeriod' }, + 'sub-location' => { 125 => 0x5c }, + 'subfiledata' => { 155 => 'data' }, + 'subfiledirectory' => { 155 => '1Directory' }, + 'subfilemimetype' => { 155 => '2MIME' }, + 'subfilename' => { 155 => '1Name' }, + 'subfileresource' => { 155 => 'rsrc' }, + 'subfiletype' => { 113 => 0xfe, 155 => '0Type' }, + 'subject' => { 287 => 'Subject', 352 => 'Subject', 449 => 'subject', 459 => 'Subject', 473 => 'subject' }, + 'subjectarea' => { 113 => 0x9214, 452 => 'SubjectArea' }, + 'subjectcode' => { 457 => 'SubjectCode' }, + 'subjectdistance' => { 113 => 0x9206, 133 => 0x3e, 452 => 'SubjectDistance' }, + 'subjectdistancerange' => { 113 => 0xa40c, 452 => 'SubjectDistanceRange' }, + 'subjectlocation' => { 113 => 0xa214, 452 => 'SubjectLocation' }, + 'subjectmotion' => { 264 => '78.2', 265 => '78.2', 275 => '78.2' }, + 'subjectprogram' => { 171 => 0x22 }, + 'subjectreference' => { 125 => 0xc }, + 'sublabels4' => { 456 => [\'TagStructure','TagStructureSubLabelsSubLabelsSubLabelsSubLabels'] }, + 'sublabels5' => { 456 => [\'TagStructure','TagStructureSubLabelsSubLabelsSubLabelsSubLabelsSubLabels'] }, + 'sublables1' => { 456 => [\'TagStructure','TagStructureSubLabels'] }, + 'sublables2' => { 456 => [\'TagStructure','TagStructureSubLabelsSubLabels'] }, + 'sublables3' => { 456 => [\'TagStructure','TagStructureSubLabelsSubLabelsSubLabels'] }, + 'subseccreatedate' => { 108 => 'SubSecCreateDate' }, + 'subsecdatetimeoriginal' => { 108 => 'SubSecDateTimeOriginal' }, + 'subsecmodifydate' => { 108 => 'SubSecModifyDate' }, + 'subsectime' => { 113 => 0x9290 }, + 'subsectimedigitized' => { 113 => 0x9292 }, + 'subsectimeoriginal' => { 113 => 0x9291 }, + 'subsection1' => { 462 => 'subsection1' }, + 'subsection2' => { 462 => 'subsection2' }, + 'subsection3' => { 462 => 'subsection3' }, + 'subsection4' => { 462 => 'subsection4' }, + 'subselector' => { 262 => '49.1', 264 => '71.1', 265 => '71.1', 275 => '71.1' }, + 'subselectorassignment' => { 262 => '48.1' }, + 'subselectorcenter' => { 264 => '72.1', 265 => '72.1', 275 => '72.1' }, + 'subselectorplusdials' => { 262 => '49.2', 264 => '73.1', 265 => '73.1', 275 => '73.1' }, + 'subtitle' => { 462 => 'subtitle' }, + 'subversionfilename' => { 456 => [\'SubVersions','SubVersionsFileName'] }, + 'subversionreference' => { 456 => [\'SubVersions','SubVersionsVersRef'] }, + 'subversions' => { 456 => 'SubVersions' }, + 'superimposeddisplay' => { 76 => 0xa, 78 => 0x510, 79 => 0x9, 80 => 0xa, 83 => 0xa, 84 => 0xe }, + 'supermacro' => { 60 => 0x1a }, + 'supplementalcategories' => { 125 => 0x14, 460 => 'SupplementalCategories' }, + 'supplementaltype' => { 127 => 0x37 }, + 'supplementdisplayid' => { 462 => 'supplementDisplayID' }, + 'supplementstartingpage' => { 462 => 'supplementStartingPage' }, + 'supplementtitle' => { 462 => 'supplementTitle' }, + 'supplychainsource' => { 458 => 'SupplyChainSource' }, + 'supplychainsourceidentifier' => { 458 => [\'SupplyChainSource','SupplyChainSourceIdentifier'] }, + 'supplychainsourcename' => { 458 => [\'SupplyChainSource','SupplyChainSourceName'] }, + 'svisosetting' => { 317 => 0x14 }, + 'swatchcoloranta' => { 477 => [\'SwatchGroups','SwatchGroupsColorantsA'] }, + 'swatchcolorantb' => { 477 => [\'SwatchGroups','SwatchGroupsColorantsB'] }, + 'swatchcolorantblack' => { 477 => [\'SwatchGroups','SwatchGroupsColorantsBlack'] }, + 'swatchcolorantblue' => { 477 => [\'SwatchGroups','SwatchGroupsColorantsBlue'] }, + 'swatchcolorantcyan' => { 477 => [\'SwatchGroups','SwatchGroupsColorantsCyan'] }, + 'swatchcolorantgray' => { 477 => [\'SwatchGroups','SwatchGroupsColorantsGray'] }, + 'swatchcolorantgreen' => { 477 => [\'SwatchGroups','SwatchGroupsColorantsGreen'] }, + 'swatchcolorantl' => { 477 => [\'SwatchGroups','SwatchGroupsColorantsL'] }, + 'swatchcolorantmagenta' => { 477 => [\'SwatchGroups','SwatchGroupsColorantsMagenta'] }, + 'swatchcolorantmode' => { 477 => [\'SwatchGroups','SwatchGroupsColorantsMode'] }, + 'swatchcolorantred' => { 477 => [\'SwatchGroups','SwatchGroupsColorantsRed'] }, + 'swatchcolorantswatchname' => { 477 => [\'SwatchGroups','SwatchGroupsColorantsSwatchName'] }, + 'swatchcoloranttint' => { 477 => [\'SwatchGroups','SwatchGroupsColorantsTint'] }, + 'swatchcoloranttype' => { 477 => [\'SwatchGroups','SwatchGroupsColorantsType'] }, + 'swatchcolorantyellow' => { 477 => [\'SwatchGroups','SwatchGroupsColorantsYellow'] }, + 'swatchgroupname' => { 477 => [\'SwatchGroups','SwatchGroupsGroupName'] }, + 'swatchgroups' => { 477 => 'SwatchGroups' }, + 'swatchgroupscolorants' => { 477 => [\'SwatchGroups','SwatchGroupsColorants'] }, + 'swatchgrouptype' => { 477 => [\'SwatchGroups','SwatchGroupsGroupType'] }, + 'sweeppanoramadirection' => { 301 => 0x93, 383 => 0x33 }, + 'sweeppanoramafieldofview' => { 301 => 0x94 }, + 'sweeppanoramasize' => { 383 => 0x32 }, + 'switchtoregisteredafpoint' => { 77 => 0x12, 78 => 0x50a }, + 'syncreleasemode' => { 264 => '77.1', 265 => '77.1', 275 => '77.1' }, + 'system' => { 345 => 0x204 }, + 'tagged' => { 347 => 0xdd, 348 => 'Tagged', 442 => 'tagged' }, + 'tagslist' => { 451 => 'TagsList' }, + 'tagstructure' => { 456 => 'TagStructure' }, + 'takenumber' => { 472 => 'takeNumber' }, + 'tapename' => { 472 => 'tapeName' }, + 'targetaperture' => { 72 => 0x4 }, + 'targetcompressionratio' => { 89 => 0x1 }, + 'targetdistancesetting' => { 91 => 0x1807 }, + 'targetexposuretime' => { 72 => 0x5 }, + 'targetimagetype' => { 91 => 0x100a }, + 'targetprinter' => { 113 => 0x151 }, + 'taxon' => { 112 => 'Taxon' }, + 'taxonacceptednameusage' => { 112 => [\'Taxon','TaxonAcceptedNameUsage'] }, + 'taxonacceptednameusageid' => { 112 => [\'Taxon','TaxonAcceptedNameUsageID'] }, + 'taxonclass' => { 112 => [\'Taxon','TaxonClass'] }, + 'taxonconceptid' => { 112 => [\'Taxon','TaxonTaxonConceptID'] }, + 'taxonfamily' => { 112 => [\'Taxon','TaxonFamily'] }, + 'taxongenus' => { 112 => [\'Taxon','TaxonGenus'] }, + 'taxonhigherclassification' => { 112 => [\'Taxon','TaxonHigherClassification'] }, + 'taxonid' => { 112 => [\'Taxon','TaxonTaxonID'] }, + 'taxoninfraspecificepithet' => { 112 => [\'Taxon','TaxonInfraspecificEpithet'] }, + 'taxonkingdom' => { 112 => [\'Taxon','TaxonKingdom'] }, + 'taxonnameaccordingto' => { 112 => [\'Taxon','TaxonNameAccordingTo'] }, + 'taxonnameaccordingtoid' => { 112 => [\'Taxon','TaxonNameAccordingToID'] }, + 'taxonnamepublishedin' => { 112 => [\'Taxon','TaxonNamePublishedIn'] }, + 'taxonnamepublishedinid' => { 112 => [\'Taxon','TaxonNamePublishedInID'] }, + 'taxonnamepublishedinyear' => { 112 => [\'Taxon','TaxonNamePublishedInYear'] }, + 'taxonnomenclaturalcode' => { 112 => [\'Taxon','TaxonNomenclaturalCode'] }, + 'taxonnomenclaturalstatus' => { 112 => [\'Taxon','TaxonNomenclaturalStatus'] }, + 'taxonorder' => { 112 => [\'Taxon','TaxonOrder'] }, + 'taxonoriginalnameusage' => { 112 => [\'Taxon','TaxonOriginalNameUsage'] }, + 'taxonoriginalnameusageid' => { 112 => [\'Taxon','TaxonOriginalNameUsageID'] }, + 'taxonparentnameusage' => { 112 => [\'Taxon','TaxonParentNameUsage'] }, + 'taxonparentnameusageid' => { 112 => [\'Taxon','TaxonParentNameUsageID'] }, + 'taxonphylum' => { 112 => [\'Taxon','TaxonPhylum'] }, + 'taxonrank' => { 112 => [\'Taxon','TaxonTaxonRank'] }, + 'taxonremarks' => { 112 => [\'Taxon','TaxonTaxonRemarks'] }, + 'taxonscientificname' => { 112 => [\'Taxon','TaxonScientificName'] }, + 'taxonscientificnameauthorship' => { 112 => [\'Taxon','TaxonScientificNameAuthorship'] }, + 'taxonscientificnameid' => { 112 => [\'Taxon','TaxonScientificNameID'] }, + 'taxonspecificepithet' => { 112 => [\'Taxon','TaxonSpecificEpithet'] }, + 'taxonsubgenus' => { 112 => [\'Taxon','TaxonSubgenus'] }, + 'taxontaxonomicstatus' => { 112 => [\'Taxon','TaxonTaxonomicStatus'] }, + 'taxonverbatimtaxonrank' => { 112 => [\'Taxon','TaxonVerbatimTaxonRank'] }, + 'taxonvernacularname' => { 112 => [\'Taxon','TaxonVernacularName'] }, + 'tda1bandwidth' => { 131 => 0x196f }, + 'tda1edgepolarity' => { 131 => 0x1971 }, + 'tda1gain' => { 131 => 0x1970 }, + 'tda1offset' => { 131 => 0x196e }, + 'tda2bandwidth' => { 131 => 0x1979 }, + 'tda2edgepolarity' => { 131 => 0x197b }, + 'tda2gain' => { 131 => 0x197a }, + 'tda2offset' => { 131 => 0x1978 }, + 'tda3bandwidth' => { 131 => 0x1983 }, + 'tda3edgepolarity' => { 131 => 0x1985 }, + 'tda3gain' => { 131 => 0x1984 }, + 'tda3offset' => { 131 => 0x1982 }, + 'tda4bandwidth' => { 131 => 0x198d }, + 'tda4edgepolarity' => { 131 => 0x198f }, + 'tda4gain' => { 131 => 0x198e }, + 'tda4offset' => { 131 => 0x198c }, + 'teaser' => { 462 => 'teaser' }, + 'teleconverter' => { 176 => 0x105, 394 => 0x105 }, + 'tempampgainx100' => { 131 => 0x1914 }, + 'tempo' => { 472 => 'tempo' }, + 'temporalcoverage' => { 458 => 'TemporalCoverage' }, + 'temporalcoveragefrom' => { 458 => [\'TemporalCoverage','TemporalCoverageTempCoverageFrom'] }, + 'temporalcoverageto' => { 458 => [\'TemporalCoverage','TemporalCoverageTempCoverageTo'] }, + 'termsandconditionstext' => { 288 => 'TermsAndConditionsText' }, + 'termsandconditionsurl' => { 288 => 'TermsAndConditionsURL' }, + 'testname' => { 114 => 'TestName' }, + 'textencoding' => { 213 => 0x4 }, + 'textlayername' => { 460 => [\'TextLayers','TextLayersLayerName'] }, + 'textlayers' => { 460 => 'TextLayers' }, + 'textlayertext' => { 460 => [\'TextLayers','TextLayersLayerText'] }, + 'textstamp' => { 301 => [0x8008,0x8009,0x3b,0x3e] }, + 'three-dtrackingfacedetection' => { 264 => '1.3', 265 => '1.3', 275 => '1.4' }, + 'three-dtrackingwatcharea' => { 264 => '78.1', 265 => '78.1', 275 => '78.1' }, + 'thresholding' => { 113 => 0x107 }, + 'thumbnailfilename' => { 91 => 0x817 }, + 'thumbnailformat' => { 470 => [\'Thumbnails','ThumbnailsFormat'] }, + 'thumbnailheight' => { 135 => 0xfa55, 470 => [\'Thumbnails','ThumbnailsHeight'] }, + 'thumbnailimage' => { 91 => 0x2008, 108 => 'ThumbnailImage', 116 => 0x3, 158 => 'data', 283 => 0x100, 470 => [\'Thumbnails','ThumbnailsImage'] }, + 'thumbnailimagename' => { 158 => '1Name' }, + 'thumbnailimagesize' => { 158 => 'ImageSize' }, + 'thumbnailimagetype' => { 158 => '0Type' }, + 'thumbnailimagevalidarea' => { 60 => 0x13 }, + 'thumbnaillength' => { 113 => 0x202 }, + 'thumbnailoffset' => { 113 => 0x201 }, + 'thumbnails' => { 470 => 'Thumbnails' }, + 'thumbnailwidth' => { 135 => 0xfa54, 470 => [\'Thumbnails','ThumbnailsWidth'] }, + 'ticker' => { 462 => 'ticker' }, + 'tiffhandling' => { 448 => 'TIFFHandling' }, + 'tiffmeteringimage' => { 177 => 0x104c, 392 => 0x1110 }, + 'tilelength' => { 113 => 0x143 }, + 'tilewidth' => { 113 => 0x142 }, + 'time' => { 131 => 0x401, 336 => 0x7 }, + 'timecodes' => { 113 => 0xc763 }, + 'timecreated' => { 125 => 0x3c, 133 => 0x14, 142 => 0x10, 348 => 'TimeCreated' }, + 'timelapseshotnumber' => { 304 => 0x10 }, + 'timeperiod' => { 462 => 'timePeriod' }, + 'timerfunctionbutton' => { 263 => '5.2', 266 => '12.1', 267 => '13.1' }, + 'timerlength' => { 78 => 0x80c }, + 'timerrecording' => { 301 => 0x96 }, + 'timescaleparams' => { 472 => 'timeScaleParams' }, + 'timescaleparamsframeoverlappingpercentage' => { 472 => [\'timeScaleParams','timeScaleParamsFrameOverlappingPercentage'] }, + 'timescaleparamsframesize' => { 472 => [\'timeScaleParams','timeScaleParamsFrameSize'] }, + 'timescaleparamsquality' => { 472 => [\'timeScaleParams','timeScaleParamsQuality'] }, + 'timesent' => { 126 => 0x50 }, + 'timeshot' => { 437 => 'TimeShot' }, + 'timesignature' => { 472 => 'timeSignature' }, + 'timesincepoweron' => { 301 => 0x29 }, + 'timestamp' => { 10 => 0x45e, 18 => 0x11c, 277 => 0x8, 291 => 'TimeStamp', 301 => 0xaf, 436 => 'Timestamp', 443 => 'Timestamp', 456 => 'TimeStamp' }, + 'timestamp1' => { 10 => 0x45a }, + 'timezone' => { 73 => 0x1, 246 => 0x0, 366 => 0xa }, + 'timezonecity' => { 73 => 0x2 }, + 'timezonecode' => { 94 => 0x1 }, + 'timezoneinfo' => { 94 => 0x2 }, + 'timezoneoffset' => { 113 => 0x882a }, + 'tint' => { 448 => 'Tint' }, + 'title' => { 148 => 'Title', 287 => 'Title', 291 => 'Title', 301 => 0x65, 352 => 'Title', 449 => 'title', 459 => 'Title', 470 => 'Title' }, + 'tonecomp' => { 214 => 0x81 }, + 'tonecurve' => { 70 => 0x1, 336 => 0x402, 448 => 'ToneCurve' }, + 'tonecurveactive' => { 102 => 0x110 }, + 'tonecurveadobergb' => { 370 => 0xa043 }, + 'tonecurveadobergbdefault' => { 370 => 0xa041 }, + 'tonecurveblue' => { 448 => 'ToneCurveBlue' }, + 'tonecurvebluex' => { 427 => 0x9003 }, + 'tonecurvebluey' => { 427 => 0x9007 }, + 'tonecurvebrightness' => { 97 => 0x20410 }, + 'tonecurvebrightnessx' => { 427 => 0x9000 }, + 'tonecurvebrightnessy' => { 427 => 0x9004 }, + 'tonecurvecolorspace' => { 101 => 0x0 }, + 'tonecurvecontrast' => { 97 => 0x20411 }, + 'tonecurvegreen' => { 448 => 'ToneCurveGreen' }, + 'tonecurvegreenx' => { 427 => 0x9002 }, + 'tonecurvegreeny' => { 427 => 0x9006 }, + 'tonecurveinputrange' => { 101 => 0x3 }, + 'tonecurveinterpolation' => { 102 => 0x159 }, + 'tonecurvemode' => { 102 => 0x113 }, + 'tonecurvename' => { 448 => 'ToneCurveName' }, + 'tonecurvename2012' => { 448 => 'ToneCurveName2012' }, + 'tonecurveoriginal' => { 97 => '0x20400.1' }, + 'tonecurveoutputrange' => { 101 => 0x5 }, + 'tonecurveprofilename' => { 131 => 0x1391 }, + 'tonecurveproperty' => { 102 => 0x3c }, + 'tonecurvepv2012' => { 448 => 'ToneCurvePV2012' }, + 'tonecurvepv2012blue' => { 448 => 'ToneCurvePV2012Blue' }, + 'tonecurvepv2012green' => { 448 => 'ToneCurvePV2012Green' }, + 'tonecurvepv2012red' => { 448 => 'ToneCurvePV2012Red' }, + 'tonecurvered' => { 448 => 'ToneCurveRed' }, + 'tonecurveredx' => { 427 => 0x9001 }, + 'tonecurveredy' => { 427 => 0x9005 }, + 'tonecurves' => { 336 => 0x403 }, + 'tonecurveshape' => { 101 => 0x1 }, + 'tonecurvesrgb' => { 370 => 0xa042 }, + 'tonecurvesrgbdefault' => { 370 => 0xa040 }, + 'tonecurvex' => { 101 => 0xa }, + 'tonecurvey' => { 101 => 0xb }, + 'tonelevel' => { 278 => 0x52e }, + 'tonemapstrength' => { 448 => 'ToneMapStrength' }, + 'toningeffect' => { 54 => 0xf, 214 => 0xb3, 216 => 0x38, 217 => 0x40, 218 => 0x48, 363 => 0x1015 }, + 'toningeffectauto' => { 67 => 0xa4 }, + 'toningeffectfaithful' => { 66 => 0x74, 67 => 0x74 }, + 'toningeffectlandscape' => { 66 => 0x44, 67 => 0x44 }, + 'toningeffectmonochrome' => { 18 => 0x108, 66 => 0x8c, 67 => 0x8c }, + 'toningeffectneutral' => { 66 => 0x5c, 67 => 0x5c }, + 'toningeffectportrait' => { 66 => 0x2c, 67 => 0x2c }, + 'toningeffectstandard' => { 66 => 0x14, 67 => 0x14 }, + 'toningeffectuserdef1' => { 66 => 0xa4, 67 => 0xbc }, + 'toningeffectuserdef2' => { 66 => 0xbc, 67 => 0xd4 }, + 'toningeffectuserdef3' => { 66 => 0xd4, 67 => 0xec }, + 'toningsaturation' => { 216 => 0x39, 217 => 0x41, 218 => 0x49 }, + 'totalzoom' => { 133 => 0x62 }, + 'touchae' => { 301 => 0xab }, + 'trackcreatedate' => { 356 => 0x1 }, + 'trackmodifydate' => { 356 => 0x2 }, + 'tracknumber' => { 472 => 'trackNumber' }, + 'tracks' => { 472 => 'Tracks' }, + 'tracksframerate' => { 472 => [\'Tracks','TracksFrameRate'] }, + 'tracksmarkers' => { 472 => [\'Tracks','TracksMarkers'] }, + 'tracksmarkerscomment' => { 472 => [\'Tracks','TracksMarkersComment'] }, + 'tracksmarkerscuepointparams' => { 472 => [\'Tracks','TracksMarkersCuePointParams'] }, + 'tracksmarkerscuepointparamskey' => { 472 => [\'Tracks','TracksMarkersCuePointParamsKey'] }, + 'tracksmarkerscuepointparamsvalue' => { 472 => [\'Tracks','TracksMarkersCuePointParamsValue'] }, + 'tracksmarkerscuepointtype' => { 472 => [\'Tracks','TracksMarkersCuePointType'] }, + 'tracksmarkersduration' => { 472 => [\'Tracks','TracksMarkersDuration'] }, + 'tracksmarkerslocation' => { 472 => [\'Tracks','TracksMarkersLocation'] }, + 'tracksmarkersname' => { 472 => [\'Tracks','TracksMarkersName'] }, + 'tracksmarkersprobability' => { 472 => [\'Tracks','TracksMarkersProbability'] }, + 'tracksmarkersspeaker' => { 472 => [\'Tracks','TracksMarkersSpeaker'] }, + 'tracksmarkersstarttime' => { 472 => [\'Tracks','TracksMarkersStartTime'] }, + 'tracksmarkerstarget' => { 472 => [\'Tracks','TracksMarkersTarget'] }, + 'tracksmarkerstype' => { 472 => [\'Tracks','TracksMarkersType'] }, + 'trackstrackname' => { 472 => [\'Tracks','TracksTrackName'] }, + 'trackstracktype' => { 472 => [\'Tracks','TracksTrackType'] }, + 'trailersignature' => { 155 => 'zmie' }, + 'transcript' => { 458 => 'Transcript' }, + 'transcriptlink' => { 458 => 'TranscriptLink' }, + 'transcriptlinklink' => { 458 => [\'TranscriptLink','TranscriptLinkLink'] }, + 'transcriptlinklinkqualifier' => { 458 => [\'TranscriptLink','TranscriptLinkLinkQualifier'] }, + 'transferfunction' => { 113 => 0x12d, 468 => 'TransferFunction' }, + 'transfertimenormal' => { 131 => 0x1888 }, + 'transfertimetest' => { 131 => 0x1889 }, + 'transform' => { 301 => [0x8012,0x59] }, + 'transmissionreference' => { 460 => 'TransmissionReference' }, + 'trapped' => { 287 => 'Trapped', 459 => 'Trapped' }, + 'trashbuttonfunction' => { 78 => 0x710 }, + 'travelday' => { 301 => 0x36 }, + 'triggermode' => { 357 => 0x6, 358 => 0x34, 359 => 0x34 }, + 'tstop' => { 113 => 0xc772 }, + 'ttl_da_adown' => { 324 => 0x5 }, + 'ttl_da_aup' => { 324 => 0x4 }, + 'ttl_da_bdown' => { 324 => 0x7 }, + 'ttl_da_bup' => { 324 => 0x6 }, + 'tungstenawb' => { 314 => 0x1 }, + 'tvexposuretimesetting' => { 317 => 0x12 }, + 'type' => { 449 => 'type', 467 => 'type' }, + 'typestatus' => { 112 => [\'Identification','IdentificationTypeStatus'] }, + 'uniquecameramodel' => { 113 => 0xc614 }, + 'uniquedocumentid' => { 125 => 0xbb }, + 'uniquematrixauto' => { 131 => 0x7e9 }, + 'uniquematrixcustom' => { 131 => 0x7e8 }, + 'uniquematrixdaylight' => { 131 => 0x7e4 }, + 'uniquematrixflash' => { 131 => 0x7e7 }, + 'uniquematrixfluorescent' => { 131 => 0x7e6 }, + 'uniquematrixtungsten' => { 131 => 0x7e5 }, + 'uniqueobjectname' => { 126 => 0x64 }, + 'units' => { 432 => 'Units' }, + 'unknownblock' => { 336 => 0x405 }, + 'unknownblock1' => { 282 => 0x635 }, + 'unknownblock2' => { 282 => 0x636 }, + 'unknownblock3' => { 282 => 0x1103 }, + 'unknownblock4' => { 282 => 0x1104 }, + 'unknowncontrast' => { 103 => 0x45 }, + 'unknowndate' => { 345 => 0x212 }, + 'unknownev' => { 131 => 0x1 }, + 'unknownlinear' => { 103 => 0x46 }, + 'unknownnumber' => { 91 => 0x180b }, + 'unknownoutputhighlightpoint' => { 103 => 0x4a }, + 'unknownoutputshadowpoint' => { 103 => 0x4b }, + 'unknownrawhighlight' => { 103 => 0x7b }, + 'unknownrawhighlightpoint' => { 103 => 0x48 }, + 'unknownrawshadow' => { 103 => 0x84 }, + 'unknownrawshadowpoint' => { 103 => 0x49 }, + 'unknownsharpness' => { 103 => 0x47 }, + 'unknowntemperature' => { 115 => 0x4 }, + 'unsharp1color' => { 259 => 0x13 }, + 'unsharp1halowidth' => { 259 => 0x19 }, + 'unsharp1intensity' => { 259 => 0x17 }, + 'unsharp1threshold' => { 259 => 0x1b }, + 'unsharp2color' => { 259 => 0x2e }, + 'unsharp2halowidth' => { 259 => 0x34 }, + 'unsharp2intensity' => { 259 => 0x32 }, + 'unsharp2threshold' => { 259 => 0x36 }, + 'unsharp3color' => { 259 => 0x49 }, + 'unsharp3halowidth' => { 259 => 0x4f }, + 'unsharp3intensity' => { 259 => 0x4d }, + 'unsharp3threshold' => { 259 => 0x51 }, + 'unsharp4color' => { 259 => 0x64 }, + 'unsharp4halowidth' => { 259 => 0x6a }, + 'unsharp4intensity' => { 259 => 0x68 }, + 'unsharp4threshold' => { 259 => 0x6c }, + 'unsharpcount' => { 259 => 0x0 }, + 'unsharpmask' => { 103 => 0x90, 254 => 0x76a43200 }, + 'unsharpmaskfineness' => { 97 => 0x20309 }, + 'unsharpmaskstrength' => { 97 => 0x20308 }, + 'unsharpmaskthreshold' => { 97 => 0x2030a }, + 'uprightcentermode' => { 448 => 'UprightCenterMode' }, + 'uprightcenternormx' => { 448 => 'UprightCenterNormX' }, + 'uprightcenternormy' => { 448 => 'UprightCenterNormY' }, + 'uprightdependentdigest' => { 448 => 'UprightDependentDigest' }, + 'uprightfocallength35mm' => { 448 => 'UprightFocalLength35mm' }, + 'uprightfocalmode' => { 448 => 'UprightFocalMode' }, + 'uprightfoursegmentscount' => { 448 => 'UprightFourSegmentsCount' }, + 'uprightpreview' => { 448 => 'UprightPreview' }, + 'uprighttransform_0' => { 448 => 'UprightTransform_0' }, + 'uprighttransform_1' => { 448 => 'UprightTransform_1' }, + 'uprighttransform_2' => { 448 => 'UprightTransform_2' }, + 'uprighttransform_3' => { 448 => 'UprightTransform_3' }, + 'uprighttransform_4' => { 448 => 'UprightTransform_4' }, + 'uprighttransform_5' => { 448 => 'UprightTransform_5' }, + 'uprighttransformcount' => { 448 => 'UprightTransformCount' }, + 'uprightversion' => { 448 => 'UprightVersion' }, + 'urgency' => { 125 => 0xa, 460 => 'Urgency' }, + 'url' => { 148 => 'URL', 291 => 'URL', 350 => 0x40b, 462 => 'url' }, + 'url_list' => { 350 => 0x41e }, + 'urla-platform' => { 462 => [\'url','urlA-platform'] }, + 'urlurl' => { 462 => [\'url','urlUrl'] }, + 'usablemeteringmodes' => { 78 => 0x10a }, + 'usableshootingmodes' => { 78 => 0x109 }, + 'usage' => { 463 => 'usage' }, + 'usageterms' => { 476 => 'UsageTerms' }, + 'useguidelines' => { 445 => 'useGuidelines' }, + 'usepanoramaviewer' => { 435 => 'UsePanoramaViewer' }, + 'usercomment' => { 91 => 0x805, 113 => 0x9286, 452 => 'UserComment' }, + 'userdef1picturestyle' => { 18 => 0x10c, 66 => 0xd8, 67 => 0xf0 }, + 'userdef2picturestyle' => { 18 => 0x10e, 66 => 0xda, 67 => 0xf2 }, + 'userdef3picturestyle' => { 18 => 0x110, 66 => 0xdc, 67 => 0xf4 }, + 'userfields' => { 440 => 'UserFields' }, + 'userlabel' => { 357 => 0x2b, 358 => 0x5a, 359 => 0x68 }, + 'userprofile' => { 296 => 0x302, 303 => 0x3038 }, + 'usmlenselectronicmf' => { 2 => 0x7, 77 => 0x7, 78 => 0x501 }, + 'uspsnumber' => { 462 => 'uspsNumber' }, + 'utmeasting' => { 159 => 'Easting' }, + 'utmmapdatum' => { 159 => 'Datum' }, + 'utmnorthing' => { 159 => 'Northing' }, + 'utmzone' => { 159 => 'Zone' }, + 'uv-irfiltercorrection' => { 296 => 0x325 }, + 'validbits' => { 282 => 0x611, 283 => 0x102c }, + 'validpixeldepth' => { 286 => 0x611 }, + 'variablelowpassfilter' => { 394 => 0x2028 }, + 'variousmodes' => { 133 => 0x26 }, + 'variousmodes2' => { 133 => 0x3a }, + 'variprogram' => { 214 => 0xab }, + 'varraydacnominalvalues' => { 131 => 0x191e }, + 'version' => { 121 => 0x0, 352 => 'Version', 448 => 'Version' }, + 'versioncreatedate' => { 427 => 0xd100 }, + 'versionid' => { 473 => 'VersionID' }, + 'versionidentifier' => { 462 => 'versionIdentifier' }, + 'versionmodifydate' => { 427 => 0xd101 }, + 'versions' => { 473 => 'Versions' }, + 'versionscomments' => { 473 => [\'Versions','VersionsComments'] }, + 'versionsevent' => { 473 => [\'Versions','VersionsEvent'] }, + 'versionseventaction' => { 473 => [\'Versions','VersionsEventAction'] }, + 'versionseventchanged' => { 473 => [\'Versions','VersionsEventChanged'] }, + 'versionseventinstanceid' => { 473 => [\'Versions','VersionsEventInstanceID'] }, + 'versionseventparameters' => { 473 => [\'Versions','VersionsEventParameters'] }, + 'versionseventsoftwareagent' => { 473 => [\'Versions','VersionsEventSoftwareAgent'] }, + 'versionseventwhen' => { 473 => [\'Versions','VersionsEventWhen'] }, + 'versionsmodifier' => { 473 => [\'Versions','VersionsModifier'] }, + 'versionsmodifydate' => { 473 => [\'Versions','VersionsModifyDate'] }, + 'versionsversion' => { 473 => [\'Versions','VersionsVersion'] }, + 'verticalafonbutton' => { 261 => '3.2', 262 => '47.2', 264 => '79.1' }, + 'verticalclockoverlaps' => { 131 => 0x412 }, + 'verticalfuncbutton' => { 262 => '42.2', 264 => '67.1' }, + 'verticalfuncbuttonplusdials' => { 262 => '43.1' }, + 'verticalfuncplusdials' => { 264 => '68.1' }, + 'verticalmultiselector' => { 262 => '42.1', 264 => '66.1', 265 => '66.1', 275 => '66.1' }, + 'vfdisplayillumination' => { 2 => 0x11, 78 => [0x510,0x51d] }, + 'vibrance' => { 441 => 'Vibrance', 448 => 'Vibrance' }, + 'vibrationreduction' => { 223 => [0x75,0x82,0x1ae], 231 => '586.1', 239 => '590.2', 245 => 0x4 }, + 'videoalphamode' => { 472 => 'videoAlphaMode' }, + 'videoalphapremultiplecolor' => { 472 => 'videoAlphaPremultipleColor' }, + 'videoalphapremultiplecolora' => { 472 => [\'videoAlphaPremultipleColor','videoAlphaPremultipleColorA'] }, + 'videoalphapremultiplecolorb' => { 472 => [\'videoAlphaPremultipleColor','videoAlphaPremultipleColorB'] }, + 'videoalphapremultiplecolorblack' => { 472 => [\'videoAlphaPremultipleColor','videoAlphaPremultipleColorBlack'] }, + 'videoalphapremultiplecolorblue' => { 472 => [\'videoAlphaPremultipleColor','videoAlphaPremultipleColorBlue'] }, + 'videoalphapremultiplecolorcyan' => { 472 => [\'videoAlphaPremultipleColor','videoAlphaPremultipleColorCyan'] }, + 'videoalphapremultiplecolorgray' => { 472 => [\'videoAlphaPremultipleColor','videoAlphaPremultipleColorGray'] }, + 'videoalphapremultiplecolorgreen' => { 472 => [\'videoAlphaPremultipleColor','videoAlphaPremultipleColorGreen'] }, + 'videoalphapremultiplecolorl' => { 472 => [\'videoAlphaPremultipleColor','videoAlphaPremultipleColorL'] }, + 'videoalphapremultiplecolormagenta' => { 472 => [\'videoAlphaPremultipleColor','videoAlphaPremultipleColorMagenta'] }, + 'videoalphapremultiplecolormode' => { 472 => [\'videoAlphaPremultipleColor','videoAlphaPremultipleColorMode'] }, + 'videoalphapremultiplecolorred' => { 472 => [\'videoAlphaPremultipleColor','videoAlphaPremultipleColorRed'] }, + 'videoalphapremultiplecolorswatchname' => { 472 => [\'videoAlphaPremultipleColor','videoAlphaPremultipleColorSwatchName'] }, + 'videoalphapremultiplecolortint' => { 472 => [\'videoAlphaPremultipleColor','videoAlphaPremultipleColorTint'] }, + 'videoalphapremultiplecolortype' => { 472 => [\'videoAlphaPremultipleColor','videoAlphaPremultipleColorType'] }, + 'videoalphapremultiplecoloryellow' => { 472 => [\'videoAlphaPremultipleColor','videoAlphaPremultipleColorYellow'] }, + 'videoalphaunityistransparent' => { 472 => 'videoAlphaUnityIsTransparent' }, + 'videobitrate' => { 458 => 'videoBitRate' }, + 'videobitratemode' => { 458 => 'videoBitRateMode' }, + 'videoburstmode' => { 301 => 0xbb }, + 'videocodec' => { 63 => 0x74 }, + 'videocolorspace' => { 472 => 'videoColorSpace' }, + 'videocompressor' => { 472 => 'videoCompressor' }, + 'videodisplayaspectratio' => { 458 => 'videoDisplayAspectRatio' }, + 'videoencodingprofile' => { 458 => 'videoEncodingProfile' }, + 'videofieldorder' => { 472 => 'videoFieldOrder' }, + 'videoframerate' => { 472 => 'videoFrameRate' }, + 'videoframesize' => { 472 => 'videoFrameSize' }, + 'videoframesizeh' => { 472 => [\'videoFrameSize','videoFrameSizeH'] }, + 'videoframesizeunit' => { 472 => [\'videoFrameSize','videoFrameSizeUnit'] }, + 'videoframesizew' => { 472 => [\'videoFrameSize','videoFrameSizeW'] }, + 'videomoddate' => { 472 => 'videoModDate' }, + 'videopixelaspectratio' => { 472 => 'videoPixelAspectRatio' }, + 'videopixeldepth' => { 472 => 'videoPixelDepth' }, + 'videoquality' => { 107 => 0x4003 }, + 'videoshottype' => { 458 => 'VideoShotType' }, + 'videoshottypeidentifier' => { 458 => [\'VideoShotType','VideoShotTypeIdentifier'] }, + 'videoshottypename' => { 458 => [\'VideoShotType','VideoShotTypeName'] }, + 'videostreamscount' => { 458 => 'videoStreamsCount' }, + 'viewfinder' => { 345 => 0x455 }, + 'viewfinderdisplay' => { 261 => '12.4', 262 => '6.3' }, + 'viewfinderwarning' => { 261 => '13.4', 271 => '3.5', 272 => '6.2', 276 => '4.4' }, + 'viewfinderwarnings' => { 78 => 0x40a }, + 'viewinfoduringexposure' => { 78 => 0x407 }, + 'viewingmode' => { 383 => 0x2f, 399 => 0x18 }, + 'viewingmode2' => { 383 => [0x85,0x285] }, + 'viewpoint' => { 461 => 'viewpoint' }, + 'vignetteamount' => { 448 => 'VignetteAmount' }, + 'vignettecontrol' => { 214 => 0x2a, 254 => 0x76a43205 }, + 'vignettecontrolintensity' => { 254 => 0xac6bd5c0 }, + 'vignettecorrectionalreadyapplied' => { 444 => 'VignetteCorrectionAlreadyApplied' }, + 'vignettemidpoint' => { 448 => 'VignetteMidpoint' }, + 'vignetting' => { 363 => 0x1011, 370 => 0xa052 }, + 'vignettingcorrection' => { 113 => 0x7031, 370 => 0xa053, 394 => 0x2011 }, + 'vignettingcorrparams' => { 113 => 0x7032, 422 => 0x64a, 423 => [0x34a,0x350,0x35c,0x368] }, + 'vignettingsetting' => { 370 => 0xa054 }, + 'visualcolor' => { 458 => 'VisualColour' }, + 'visualtechnique' => { 461 => 'visualTechnique' }, + 'voicememo' => { 372 => 0x216 }, + 'volume' => { 462 => 'volume' }, + 'vr_0x66' => { 223 => 0x66 }, + 'vrdoffset' => { 60 => 0xd0 }, + 'vrmode' => { 245 => 0x6 }, + 'waterdepth' => { 113 => 0x9403, 453 => 'WaterDepth' }, + 'wb_bluelevel3500k' => { 177 => 0x19a }, + 'wb_bluelevel6500k' => { 177 => 0x18a }, + 'wb_bluelevelcustom' => { 177 => 0x18e }, + 'wb_bluelevelscloudy' => { 177 => 0x106 }, + 'wb_bluelevelsdaylight' => { 177 => 0xea }, + 'wb_bluelevelsflash' => { 177 => 0x122 }, + 'wb_bluelevelsfluorescent' => { 177 => [0x40a,0x15a] }, + 'wb_bluelevelskelvin' => { 177 => 0x254 }, + 'wb_bluelevelsshade' => { 177 => 0x176 }, + 'wb_bluelevelstungsten' => { 177 => 0xce }, + 'wb_gbrglevels' => { 177 => 0xae, 180 => 0x4 }, + 'wb_glevel' => { 282 => 0x11f }, + 'wb_glevel3000k' => { 282 => 0x113 }, + 'wb_glevel3300k' => { 282 => 0x114 }, + 'wb_glevel3600k' => { 282 => 0x115 }, + 'wb_glevel3900k' => { 282 => 0x116 }, + 'wb_glevel4000k' => { 282 => 0x117 }, + 'wb_glevel4300k' => { 282 => 0x118 }, + 'wb_glevel4500k' => { 282 => 0x119 }, + 'wb_glevel4800k' => { 282 => 0x11a }, + 'wb_glevel5300k' => { 282 => 0x11b }, + 'wb_glevel6000k' => { 282 => 0x11c }, + 'wb_glevel6600k' => { 282 => 0x11d }, + 'wb_glevel7500k' => { 282 => 0x11e }, + 'wb_grbglevels' => { 190 => 0x0 }, + 'wb_rbgglevels' => { 187 => 0x0 }, + 'wb_rblevels' => { 191 => 0x270, 214 => 0xc, 282 => 0x100 }, + 'wb_rblevels1' => { 307 => 0x2 }, + 'wb_rblevels2' => { 307 => 0x5 }, + 'wb_rblevels3' => { 307 => 0x8 }, + 'wb_rblevels3000k' => { 282 => 0x102 }, + 'wb_rblevels3300k' => { 282 => 0x103 }, + 'wb_rblevels3500k' => { 177 => 0x430 }, + 'wb_rblevels3600k' => { 282 => 0x104 }, + 'wb_rblevels3900k' => { 282 => 0x105 }, + 'wb_rblevels4' => { 307 => 0xb }, + 'wb_rblevels4000k' => { 282 => 0x106 }, + 'wb_rblevels4300k' => { 282 => 0x107 }, + 'wb_rblevels4500k' => { 282 => 0x108 }, + 'wb_rblevels4800k' => { 282 => 0x109 }, + 'wb_rblevels5' => { 307 => 0xe }, + 'wb_rblevels5300k' => { 282 => 0x10a }, + 'wb_rblevels6' => { 307 => 0x11 }, + 'wb_rblevels6000k' => { 282 => 0x10b }, + 'wb_rblevels6500k' => { 177 => 0x420 }, + 'wb_rblevels6600k' => { 282 => 0x10c }, + 'wb_rblevels7' => { 307 => 0x14 }, + 'wb_rblevels7500k' => { 282 => 0x10d }, + 'wb_rblevelsauto' => { 191 => 0x272, 286 => 0x110 }, + 'wb_rblevelscloudy' => { 177 => 0x3f0, 179 => 0x10, 191 => 0x296, 286 => 0x121 }, + 'wb_rblevelscoolwhitef' => { 177 => 0x308, 179 => 0x14 }, + 'wb_rblevelscoolwhitefluor' => { 286 => 0x132 }, + 'wb_rblevelscustom' => { 177 => 0x424 }, + 'wb_rblevelscwb1' => { 282 => 0x10e }, + 'wb_rblevelscwb2' => { 282 => 0x10f }, + 'wb_rblevelscwb3' => { 282 => 0x110 }, + 'wb_rblevelscwb4' => { 282 => 0x111 }, + 'wb_rblevelsdaylight' => { 177 => [0x3ec,0x528], 179 => 0xc, 191 => 0x274 }, + 'wb_rblevelsdaylightf' => { 179 => 0x24 }, + 'wb_rblevelsdaylightfluor' => { 286 => 0x130 }, + 'wb_rblevelsdaywhitef' => { 179 => 0x28 }, + 'wb_rblevelsdaywhitefluor' => { 286 => 0x131 }, + 'wb_rblevelseveningsunlight' => { 286 => 0x124 }, + 'wb_rblevelsfineweather' => { 286 => 0x122 }, + 'wb_rblevelsflash' => { 177 => [0x3f4,0x304], 179 => 0x18, 191 => 0x2a4 }, + 'wb_rblevelsfluorescent' => { 191 => 0x290 }, + 'wb_rblevelsincandescent' => { 191 => 0x282 }, + 'wb_rblevelsshade' => { 177 => 0x418, 179 => 0x20, 191 => 0x2b2, 286 => 0x120 }, + 'wb_rblevelstungsten' => { 177 => 0x3e8, 179 => 0x8, 286 => 0x123 }, + 'wb_rblevelsunknown' => { 179 => 0x1c }, + 'wb_rblevelsused' => { 286 => 0x100 }, + 'wb_rblevelswhitef' => { 179 => 0x2c }, + 'wb_rblevelswhitefluorescent' => { 286 => 0x133 }, + 'wb_redlevel3500k' => { 177 => 0x198 }, + 'wb_redlevel6500k' => { 177 => 0x188 }, + 'wb_redlevelcustom' => { 177 => 0x18c }, + 'wb_redlevelscloudy' => { 177 => 0xf8 }, + 'wb_redlevelsdaylight' => { 177 => 0xdc }, + 'wb_redlevelsflash' => { 177 => 0x114 }, + 'wb_redlevelsfluorescent' => { 177 => [0x3fc,0x14c] }, + 'wb_redlevelskelvin' => { 177 => 0x1be }, + 'wb_redlevelsshade' => { 177 => 0x168 }, + 'wb_redlevelstungsten' => { 177 => 0xc0 }, + 'wb_rgbglevels' => { 189 => 0x0 }, + 'wb_rgblevels' => { 177 => [0x546,0x96], 297 => 0xd, 298 => 0x413, 303 => 0x3036, 345 => 0x107, 402 => 0x117c, 403 => 0x1180, 404 => 0x115c, 405 => 0x11d8, 406 => 0x11b4, 407 => 0x106c, 408 => 0x264, 409 => 0x264, 410 => 0x252 }, + 'wb_rgblevels1' => { 308 => 0x2 }, + 'wb_rgblevels2' => { 308 => 0x6 }, + 'wb_rgblevels3' => { 308 => 0xa }, + 'wb_rgblevels4' => { 308 => 0xe }, + 'wb_rgblevels5' => { 308 => 0x12 }, + 'wb_rgblevels6' => { 308 => 0x16 }, + 'wb_rgblevels7' => { 308 => 0x1a }, + 'wb_rgbmuldaylight' => { 131 => 0x852 }, + 'wb_rgbmulflash' => { 131 => 0x855 }, + 'wb_rgbmulfluorescent' => { 131 => 0x854 }, + 'wb_rgbmultungsten' => { 131 => 0x853 }, + 'wb_rggbblacklevels' => { 34 => 0x25 }, + 'wb_rggblevels' => { 180 => 0x4, 188 => 0x0, 192 => 0x13e8, 193 => 0x38 }, + 'wb_rggblevelsasshot' => { 37 => 0x0, 38 => 0x0, 39 => 0x19, 40 => 0x22, 41 => 0x3f, 44 => 0x3f, 45 => 0x3f, 46 => 0x3f, 47 => 0x47 }, + 'wb_rggblevelsauto' => { 34 => 0x1, 37 => 0x5, 38 => 0x8, 39 => 0x1e, 40 => 0x18, 41 => 0x44, 44 => 0x44, 45 => 0x44, 46 => 0x44, 47 => 0x4c, 192 => 0x1478, 193 => 0x114, 370 => 0xa022 }, + 'wb_rggblevelsblack' => { 370 => 0xa028 }, + 'wb_rggblevelscloudy' => { 34 => 0xd, 37 => 0x1e, 38 => 0x30, 39 => 0x2d, 40 => 0x31, 41 => 0x58, 44 => 0x71, 45 => 0x8a, 46 => 0x8f, 47 => 0x92, 192 => 0x1408, 193 => 0x60, 336 => 0x20f, 344 => 0x14 }, + 'wb_rggblevelscustom' => { 34 => 0x1d, 41 => 0x80, 192 => 0x1468, 193 => 0x100 }, + 'wb_rggblevelscustom1' => { 39 => 0x41 }, + 'wb_rggblevelscustom2' => { 39 => 0x46 }, + 'wb_rggblevelsdaylight' => { 34 => 0x5, 37 => 0x14, 38 => 0x20, 39 => 0x23, 40 => 0x27, 41 => 0x4e, 44 => 0x67, 45 => 0x80, 46 => 0x85, 47 => 0x88, 192 => 0x13f8, 193 => 0x4c, 336 => 0x20d, 344 => 0x2 }, + 'wb_rggblevelsflash' => { 34 => 0x19, 37 => 0x32, 38 => 0x50, 39 => 0x3c, 40 => 0x45, 41 => 0x6c, 44 => 0x85, 45 => 0x9e, 46 => 0xa3, 47 => 0xa6, 192 => 0x1448, 336 => 0x214, 344 => 0x41 }, + 'wb_rggblevelsfluorescent' => { 34 => 0x15, 37 => 0x28, 38 => 0x40, 39 => 0x37, 40 => 0x3b, 41 => 0x62, 44 => 0x7b, 45 => 0x94, 46 => 0x99, 47 => 0x9c }, + 'wb_rggblevelsfluorescentd' => { 193 => 0xc4, 336 => 0x211, 344 => 0x26 }, + 'wb_rggblevelsfluorescentl' => { 344 => 0x4a }, + 'wb_rggblevelsfluorescentn' => { 193 => 0xb0, 336 => 0x212, 344 => 0x2f }, + 'wb_rggblevelsfluorescentw' => { 192 => 0x1438, 193 => 0x9c, 336 => 0x213, 344 => 0x38 }, + 'wb_rggblevelshtmercury' => { 193 => 0xd8 }, + 'wb_rggblevelsilluminator1' => { 370 => 0xa023 }, + 'wb_rggblevelsilluminator2' => { 370 => 0xa024 }, + 'wb_rggblevelskelvin' => { 34 => 0x21, 37 => 0x2d, 38 => 0x48, 40 => 0x40, 41 => 0x67, 44 => 0x80, 45 => 0x99, 46 => 0x9e, 47 => 0xa1 }, + 'wb_rggblevelsmeasured' => { 37 => 0xa, 38 => 0x10, 41 => 0x49, 44 => 0x49, 45 => 0x49, 46 => 0x49, 47 => 0x51 }, + 'wb_rggblevelspc1' => { 40 => 0x90, 41 => 0x71 }, + 'wb_rggblevelspc2' => { 40 => 0x95, 41 => 0x76 }, + 'wb_rggblevelspc3' => { 40 => 0x9a, 41 => 0x7b }, + 'wb_rggblevelsshade' => { 34 => 0x9, 37 => 0x19, 38 => 0x28, 39 => 0x28, 40 => 0x2c, 41 => 0x53, 44 => 0x6c, 45 => 0x85, 46 => 0x8a, 47 => 0x8d, 193 => 0x74, 336 => 0x20e, 344 => 0xb }, + 'wb_rggblevelstungsten' => { 34 => 0x11, 37 => 0x23, 38 => 0x38, 39 => 0x32, 40 => 0x36, 41 => 0x5d, 44 => 0x76, 45 => 0x8f, 46 => 0x94, 47 => 0x97, 192 => 0x1428, 193 => 0x88, 336 => 0x210, 344 => 0x1d }, + 'wb_rggblevelsuncorrected' => { 370 => 0xa021 }, + 'wb_rggblevelsunknown' => { 37 => 0xf, 38 => 0x18, 40 => 0x1d, 44 => 0x4e, 45 => 0x4e, 46 => 0x4e, 47 => 0x56, 344 => 0x53 }, + 'wb_rggblevelsunknown10' => { 37 => 0x5f, 38 => 0x98, 40 => 0x72, 44 => 0x9e, 45 => 0x7b, 46 => 0x7b, 47 => 0x83 }, + 'wb_rggblevelsunknown11' => { 37 => 0x64, 38 => 0xa0, 40 => 0x77, 44 => 0xa3, 45 => 0xa3, 46 => 0x80, 47 => 0xab }, + 'wb_rggblevelsunknown12' => { 37 => 0x69, 38 => 0xa8, 40 => 0x7c, 44 => 0xa8, 45 => 0xa8, 46 => 0xa8, 47 => 0xb0 }, + 'wb_rggblevelsunknown13' => { 37 => 0x6e, 38 => 0xb0, 40 => 0x81, 44 => 0xad, 45 => 0xad, 46 => 0xad, 47 => 0xb5 }, + 'wb_rggblevelsunknown14' => { 40 => 0x86, 44 => 0xb2, 45 => 0xb2, 46 => 0xb2, 47 => 0xba }, + 'wb_rggblevelsunknown15' => { 40 => 0x8b, 44 => 0xb7, 45 => 0xb7, 46 => 0xb7, 47 => 0xbf }, + 'wb_rggblevelsunknown16' => { 40 => 0x9f, 45 => 0xbc, 46 => 0xbc, 47 => 0xc4 }, + 'wb_rggblevelsunknown17' => { 45 => 0xc1, 46 => 0xc1, 47 => 0xc9 }, + 'wb_rggblevelsunknown18' => { 45 => 0xc6, 46 => 0xc6, 47 => 0xce }, + 'wb_rggblevelsunknown19' => { 45 => 0xcb, 46 => 0xcb, 47 => 0xd3 }, + 'wb_rggblevelsunknown2' => { 37 => 0x37, 38 => 0x58, 40 => 0x4a, 44 => 0x53, 45 => 0x53, 46 => 0x53, 47 => 0x5b }, + 'wb_rggblevelsunknown20' => { 45 => 0xd0, 46 => 0xd0, 47 => 0xd8 }, + 'wb_rggblevelsunknown21' => { 46 => 0xd5, 47 => 0xdd }, + 'wb_rggblevelsunknown22' => { 46 => 0xda, 47 => 0xe2 }, + 'wb_rggblevelsunknown23' => { 46 => 0xdf, 47 => 0xe7 }, + 'wb_rggblevelsunknown24' => { 46 => 0xe4, 47 => 0xec }, + 'wb_rggblevelsunknown25' => { 46 => 0xe9, 47 => 0xf1 }, + 'wb_rggblevelsunknown26' => { 46 => 0xee, 47 => 0xf6 }, + 'wb_rggblevelsunknown27' => { 46 => 0xf3, 47 => 0xfb }, + 'wb_rggblevelsunknown28' => { 46 => 0xf8, 47 => 0x100 }, + 'wb_rggblevelsunknown29' => { 46 => 0xfd, 47 => 0x105 }, + 'wb_rggblevelsunknown3' => { 37 => 0x3c, 38 => 0x60, 40 => 0x4f, 44 => 0x58, 45 => 0x58, 46 => 0x58, 47 => 0x60 }, + 'wb_rggblevelsunknown30' => { 46 => 0x102 }, + 'wb_rggblevelsunknown4' => { 37 => 0x41, 38 => 0x68, 40 => 0x54, 44 => 0x5d, 45 => 0x5d, 46 => 0x5d, 47 => 0x65 }, + 'wb_rggblevelsunknown5' => { 37 => 0x46, 38 => 0x70, 40 => 0x59, 44 => 0x62, 45 => 0x62, 46 => 0x62, 47 => 0x6a }, + 'wb_rggblevelsunknown6' => { 37 => 0x4b, 38 => 0x78, 40 => 0x5e, 44 => 0x8a, 45 => 0x67, 46 => 0x67, 47 => 0x6f }, + 'wb_rggblevelsunknown7' => { 37 => 0x50, 38 => 0x80, 40 => 0x63, 44 => 0x8f, 45 => 0x6c, 46 => 0x6c, 47 => 0x74 }, + 'wb_rggblevelsunknown8' => { 37 => 0x55, 38 => 0x88, 40 => 0x68, 44 => 0x94, 45 => 0x71, 46 => 0x71, 47 => 0x79 }, + 'wb_rggblevelsunknown9' => { 37 => 0x5a, 38 => 0x90, 40 => 0x6d, 44 => 0x99, 45 => 0x76, 46 => 0x76, 47 => 0x7e }, + 'wb_rggblevelsuserselected' => { 344 => 0x5c }, + 'wbadjblueamber' => { 97 => 0x20106 }, + 'wbadjbluebalance' => { 260 => 0x8 }, + 'wbadjcolortemp' => { 97 => 0x20102, 102 => 0x1a }, + 'wbadjlighting' => { 260 => 0x14 }, + 'wbadjmagentagreen' => { 97 => 0x20105 }, + 'wbadjmode' => { 260 => 0x10 }, + 'wbadjredbalance' => { 260 => 0x0 }, + 'wbadjrggblevels' => { 97 => 0x20125, 102 => 0x6 }, + 'wbadjtemperature' => { 260 => 0x18 }, + 'wbadjtint' => { 260 => 0x25 }, + 'wbbluelevel' => { 296 => 0x324, 301 => 0x8006, 306 => 0x26 }, + 'wbbracketingsteps' => { 232 => 0x174d, 233 => 0x87c, 241 => 0x1757 }, + 'wbbracketmode' => { 54 => 0x9 }, + 'wbbracketshotnumber' => { 177 => 0x2b, 363 => 0x101a }, + 'wbbracketvalueab' => { 54 => 0xc }, + 'wbbracketvaluegm' => { 54 => 0xd }, + 'wbfinetuneactive' => { 102 => 0x24 }, + 'wbfinetunesaturation' => { 102 => 0x28 }, + 'wbfinetunetone' => { 102 => 0x2c }, + 'wbgreenlevel' => { 296 => 0x323, 301 => 0x8005, 306 => 0x25 }, + 'wbmediaimagesizesetting' => { 78 => 0x708 }, + 'wbmode' => { 179 => 0x4, 283 => 0x1015 }, + 'wbredlevel' => { 296 => 0x322, 301 => 0x8004, 306 => 0x24 }, + 'wbscale' => { 180 => 0x0 }, + 'wbshiftab' => { 70 => 0xc, 301 => 0x46, 318 => 0x10 }, + 'wbshiftab_gm' => { 394 => 0x2014 }, + 'wbshiftab_gm_precise' => { 394 => 0x2026 }, + 'wbshiftcreativecontrol' => { 301 => 0x92 }, + 'wbshiftgm' => { 70 => 0xd, 301 => 0x47, 318 => 0x11 }, + 'wbshiftintelligentauto' => { 301 => 0x8b }, + 'wbtype1' => { 307 => 0x1, 308 => 0x1 }, + 'wbtype2' => { 307 => 0x4, 308 => 0x5 }, + 'wbtype3' => { 307 => 0x7, 308 => 0x9 }, + 'wbtype4' => { 307 => 0xa, 308 => 0xd }, + 'wbtype5' => { 307 => 0xd, 308 => 0x11 }, + 'wbtype6' => { 307 => 0x10, 308 => 0x15 }, + 'wbtype7' => { 307 => 0x13, 308 => 0x19 }, + 'webstatement' => { 476 => 'WebStatement' }, + 'what' => { 448 => 'What' }, + 'whitebalance' => { 6 => 0x6f, 7 => [0x44,0x4a], 8 => 0xbc, 9 => 0x36, 10 => 0x5e, 11 => 0x36, 12 => 0x78, 13 => 0x6f, 14 => 0x6f, 15 => 0x73, 16 => 0x6f, 17 => 0x78, 18 => 0x54, 19 => 0x6f, 20 => 0xbc, 21 => 0x7b, 23 => 0xbc, 24 => 0xc2, 26 => 0x131, 27 => 0x77, 70 => 0x8, 72 => 0x7, 106 => 0x7, 107 => [0x19,0x2012], 113 => [0xa403,0xfe4e], 121 => 0x1002, 131 => 0x3fc, 132 => 0xfa0d, 133 => 0x40, 171 => 0x3, 172 => 0xe, 173 => 0x4, 174 => 0xb, 176 => 0x115, 214 => 0x5, 244 => 0x7, 296 => 0x304, 301 => 0x3, 303 => 0x3033, 336 => 0x19, 343 => 0x7, 362 => 0x26, 363 => 0x1003, 373 => [0x3c,0x7,0x58], 381 => 0xf, 382 => 0xe, 394 => [0x115,0xb054], 448 => 'WhiteBalance', 452 => 'WhiteBalance' }, + 'whitebalance0' => { 167 => 'WhiteBalance0' }, + 'whitebalance1' => { 167 => 'WhiteBalance1' }, + 'whitebalance2' => { 167 => 'WhiteBalance2', 278 => 0x500 }, + 'whitebalanceadj' => { 97 => 0x20101, 102 => 0x18, 254 => 0x76a43204 }, + 'whitebalanceautoadjustment' => { 314 => 0x0 }, + 'whitebalancebias' => { 107 => 0x2011, 283 => 0x304, 301 => 0x23 }, + 'whitebalanceblue' => { 70 => 0x7 }, + 'whitebalancebracket' => { 278 => 0x502, 283 => 0x303 }, + 'whitebalancebracketing' => { 174 => 0x22, 177 => 0x2c, 392 => 0x2c }, + 'whitebalancecomp' => { 286 => 0x1001 }, + 'whitebalancedetected' => { 131 => 0x3fb }, + 'whitebalancefinetune' => { 121 => 0x100a, 174 => 0x38, 176 => 0x112, 214 => 0xb, 363 => 0x1004, 381 => 0x6, 382 => 0x5, 394 => 0x112 }, + 'whitebalancemode' => { 131 => 0x3fa, 336 => 0x1a }, + 'whitebalancered' => { 70 => 0x6 }, + 'whitebalanceset' => { 317 => 0xa }, + 'whitebalancesetting' => { 174 => 0x23, 381 => 0x5, 382 => 0x4, 383 => 0x16, 399 => 0xd }, + 'whitebalancesetup' => { 370 => 0x41 }, + 'whitebalancetemperature' => { 278 => 0x501 }, + 'whiteboard' => { 283 => 0x301 }, + 'whitelevel' => { 113 => 0xc61d, 336 => 0x7e }, + 'whitepoint' => { 113 => 0x13e, 336 => 0x201, 468 => 'WhitePoint' }, + 'whites2012' => { 448 => 'Whites2012' }, + 'whitesadj' => { 427 => 0x9017 }, + 'wideadapter' => { 363 => 0x1017 }, + 'widefocuszone' => { 171 => 0x2f }, + 'widerange' => { 372 => 0x20f }, + 'windmode' => { 131 => 0x3f4 }, + 'windowsatom' => { 447 => 'windowsAtom' }, + 'windowsatomextension' => { 447 => [\'windowsAtom','windowsAtomExtension'] }, + 'windowsatominvocationflags' => { 447 => [\'windowsAtom','windowsAtomInvocationFlags'] }, + 'windowsatomuncprojectpath' => { 447 => [\'windowsAtom','windowsAtomUncProjectPath'] }, + 'wordcount' => { 462 => 'wordCount' }, + 'workcolorspace' => { 97 => 0x10200, 102 => 0x270 }, + 'workflowtag' => { 458 => 'WorkflowTag' }, + 'workflowtagcvid' => { 458 => [\'WorkflowTag','WorkflowTagCvId'] }, + 'workflowtagcvtermid' => { 458 => [\'WorkflowTag','WorkflowTagCvTermId'] }, + 'workflowtagcvtermname' => { 458 => [\'WorkflowTag','WorkflowTagCvTermName'] }, + 'workflowtagcvtermrefinedabout' => { 458 => [\'WorkflowTag','WorkflowTagCvTermRefinedAbout'] }, + 'worktodo' => { 454 => 'WorkToDo' }, + 'worldtimelocation' => { 301 => 0x3a, 336 => 0x22, 342 => '0.1' }, + 'writer-editor' => { 125 => 0x7a }, + 'x3filllight' => { 373 => 0x12 }, + 'xattrquarantine' => { 165 => 'com.apple.quarantine' }, + 'xilinxversion' => { 131 => 0x414 }, + 'xml' => { 129 => 'xml ' }, + 'xmp' => { 100 => 0xffff00f6, 114 => 'XMP' }, + 'xmptoolkit' => { 469 => 'xmptk' }, + 'xpauthor' => { 113 => 0x9c9d }, + 'xpcomment' => { 113 => 0x9c9c }, + 'xpkeywords' => { 113 => 0x9c9e }, + 'xposition' => { 113 => 0x11e }, + 'xpsubject' => { 113 => 0x9c9f }, + 'xptitle' => { 113 => 0x9c9b }, + 'xresolution' => { 113 => 0x11a, 128 => 0x3, 351 => 0x0, 468 => 'XResolution' }, + 'xyresolution' => { 117 => 0x3 }, + 'yaw' => { 109 => 0x7 }, + 'yawangle' => { 232 => 0x3513, 233 => 0x2c2c, 241 => 0x36fc, 368 => 0x0 }, + 'ycbcrcoefficients' => { 113 => 0x211, 468 => 'YCbCrCoefficients' }, + 'ycbcrpositioning' => { 113 => 0x213, 468 => 'YCbCrPositioning' }, + 'ycbcrsubsampling' => { 113 => 0x212, 468 => 'YCbCrSubSampling' }, + 'yearcreated' => { 133 => 0x10, 142 => 0xc }, + 'yellowhsl' => { 97 => 0x20912 }, + 'yield' => { 464 => 'yield' }, + 'yposition' => { 113 => 0x11f }, + 'yresolution' => { 113 => 0x11b, 128 => 0x5, 351 => 0x4, 468 => 'YResolution' }, + 'zonematching' => { 176 => 0x10a, 179 => [0x3a,0x4a], 394 => 0xb024 }, + 'zonematchingmode' => { 174 => 0x14 }, + 'zonematchingon' => { 173 => 0x75 }, + 'zonematchingvalue' => { 381 => 0x1f }, + 'zoomedpreviewlength' => { 283 => 0xf05 }, + 'zoomedpreviewsize' => { 283 => 0xf06 }, + 'zoomedpreviewstart' => { 283 => 0xf04 }, + 'zoomsourcewidth' => { 33 => 0x24 }, + 'zoomstepcount' => { 281 => 0x300, 283 => 0x100d }, + 'zoomtargetwidth' => { 33 => 0x25 }, +); + +# lookup for non-writable tags to check if the name exists +my %tagExists = ( + '_ac3' => 1, + '_h264' => 1, + '_stream' => 1, + 'a100dataoffset' => 1, + 'aas' => 1, + 'abovecolor' => 1, + 'abstract' => 1, + 'abstractfilename' => 1, + 'accelerometertime' => 1, + 'accessdate' => 1, + 'accountname' => 1, + 'acdsee' => 1, + 'acquisitiontime' => 1, + 'acquisitiontimeday' => 1, + 'acquisitiontimemonth' => 1, + 'acquisitiontimeyear' => 1, + 'acquisitiontimeyearmonth' => 1, + 'acquisitiontimeyearmonthday' => 1, + 'acroform' => 1, + 'activebuf1cols' => 1, + 'activebuf1rows' => 1, + 'activebuf2cols' => 1, + 'activebuf2rows' => 1, + 'activecols' => 1, + 'activectemonitor1cols' => 1, + 'activectemonitor2cols' => 1, + 'activectemonitorrows' => 1, + 'activerows' => 1, + 'actor' => 1, + 'actualcompensation' => 1, + 'actualscalemax' => 1, + 'actualscalemin' => 1, + 'actualsoftpostpadding' => 1, + 'actualsoftprepadding' => 1, + 'adjustedtbnimageheight' => 1, + 'adjustedtbnimagewidth' => 1, + 'adobe_cm' => 1, + 'adobecmtype' => 1, + 'adobecrw' => 1, + 'adobekoda' => 1, + 'adobeleaf' => 1, + 'adobemrw' => 1, + 'adobepano' => 1, + 'adobephotoshop' => 1, + 'adoberaf' => 1, + 'adobesr2' => 1, + 'adoptedneutral' => 1, + 'adult' => 1, + 'advancedcontentencryption' => 1, + 'advancedmutualexcl' => 1, + 'advancedscenemode' => 1, + 'adventrevision' => 1, + 'adventscale' => 1, + 'aeflags' => 1, + 'aeinfo' => 1, + 'aeinfo2' => 1, + 'aeinfo3' => 1, + 'aeinfounknown' => 1, + 'afarea' => 1, + 'afareaheights' => 1, + 'afareawidths' => 1, + 'afareaxpositions' => 1, + 'afareaypositions' => 1, + 'afconfig' => 1, + 'afcp' => 1, + 'afcp_iptc' => 1, + 'afcsettings' => 1, + 'aff1' => 1, + 'aff5' => 1, + 'affheader' => 1, + 'affinetransformmat' => 1, + 'afinfo' => 1, + 'afinfo2' => 1, + 'afinfo2version' => 1, + 'afinfo3' => 1, + 'afinfocus' => 1, + 'afinfosize' => 1, + 'afm' => 1, + 'afpointinfo' => 1, + 'afpointsinfocus1d' => 1, + 'afsp' => 1, + 'afstatus15' => 1, + 'afstatus19' => 1, + 'afstatus79' => 1, + 'aftune' => 1, + 'aibuildnumber' => 1, + 'aicolormodel' => 1, + 'aicolorusage' => 1, + 'aicreatorversion' => 1, + 'aifileformat' => 1, + 'aimetadata' => 1, + 'ainumlayers' => 1, + 'aipdfprivatedata' => 1, + 'aiprivatedata' => 1, + 'airulerunits' => 1, + 'aitargetresolution' => 1, + 'album2' => 1, + 'albumartist' => 1, + 'albumartistsortorder' => 1, + 'albumcoverurl' => 1, + 'albumid' => 1, + 'albumidalbumartist' => 1, + 'albumname' => 1, + 'albumsortorder' => 1, + 'albumtitle' => 1, + 'albumtitleid' => 1, + 'albumtitlesortorder' => 1, + 'aliaslayermetadata' => 1, + 'alignment' => 1, + 'allcolorflatfield1' => 1, + 'allcolorflatfield2' => 1, + 'allcolorflatfield3' => 1, + 'alph' => 1, + 'alpha' => 1, + 'alphabitdepth' => 1, + 'alphabytecount' => 1, + 'alphachannelsnames' => 1, + 'alphacompression' => 1, + 'alphadatadiscard' => 1, + 'alphafilter' => 1, + 'alphafiltering' => 1, + 'alphaidentifiers' => 1, + 'alphainterlace' => 1, + 'alphamask' => 1, + 'alphaoffset' => 1, + 'alphapreprocessing' => 1, + 'alphasample' => 1, + 'alternateduotonecolors' => 1, + 'alternatesourceurl' => 1, + 'alternatespotcolors' => 1, + 'ambienceinfo' => 1, + 'angleaxis' => 1, + 'angularvelocity' => 1, + 'anim' => 1, + 'animation' => 1, + 'animationcontrol' => 1, + 'animationframes' => 1, + 'animationiterations' => 1, + 'animationloopcount' => 1, + 'animationplays' => 1, + 'anmf' => 1, + 'anniversary' => 1, + 'annotation' => 1, + 'annotations' => 1, + 'annotationusagerights' => 1, + 'announce' => 1, + 'announcelist1' => 1, + 'anoiselines' => 1, + 'anta' => 1, + 'aperture' => 1, + 'aperturedisplayed' => 1, + 'aperturemode' => 1, + 'apeversion' => 1, + 'app14flags0' => 1, + 'app14flags1' => 1, + 'app1_profile' => 1, + 'apple-fi' => 1, + 'applemaildatereceived' => 1, + 'applemailflagged' => 1, + 'applemailmessageid' => 1, + 'applemailpriority' => 1, + 'applemailread' => 1, + 'applemailrepliedto' => 1, + 'applestoreaccount' => 1, + 'applestoreaccounttype' => 1, + 'applestorecatalogid' => 1, + 'applestorecountry' => 1, + 'application' => 1, + 'applicationdata' => 1, + 'applicationmissingmsg' => 1, + 'applicationversion' => 1, + 'archivallocation' => 1, + 'archivedfilename' => 1, + 'ardronefile' => 1, + 'ardronetelemetry' => 1, + 'arranger' => 1, + 'arrangerkeywords' => 1, + 'artist2' => 1, + 'artistlen' => 1, + 'artisturl' => 1, + 'artwork' => 1, + 'ascender' => 1, + 'ascent' => 1, + 'asfleakybucketpairs' => 1, + 'asfpacketcount' => 1, + 'asfsecurityobjectssize' => 1, + 'asin' => 1, + 'asin2' => 1, + 'aspectinfo' => 1, + 'aspectratiox' => 1, + 'aspectratioy' => 1, + 'assistantsname' => 1, + 'assistantsphone' => 1, + 'association' => 1, + 'assumeddisplaysize' => 1, + 'assumeddistanceview' => 1, + 'atmospherictemperature' => 1, + 'atmospherictransalpha1' => 1, + 'atmospherictransalpha2' => 1, + 'atmospherictransbeta1' => 1, + 'atmospherictransbeta2' => 1, + 'atmospherictransx' => 1, + 'atob0' => 1, + 'atob1' => 1, + 'atob2' => 1, + 'atsccontent' => 1, + 'attachments' => 1, + 'attitude' => 1, + 'attitudetarget' => 1, + 'attributes' => 1, + 'audible_cvrx' => 1, + 'audible_meta' => 1, + 'audible_meta2' => 1, + 'audible_tags' => 1, + 'audible_tseg' => 1, + 'audiences' => 1, + 'audioattributes' => 1, + 'audioavailablebitraterange' => 1, + 'audioavailablenumberchannels' => 1, + 'audioavgbitrate' => 1, + 'audiobitratecontrolmode' => 1, + 'audiobytes' => 1, + 'audiochannellayout' => 1, + 'audiochanneltypes' => 1, + 'audiocodec' => 1, + 'audiocodecdescription' => 1, + 'audiocodecid' => 1, + 'audiocodecinfo' => 1, + 'audiocodecname' => 1, + 'audiocodecprimemethod' => 1, + 'audiocomponentversion' => 1, + 'audiocurrenttargetbitrate' => 1, + 'audiodelay' => 1, + 'audiodoessamplerateconversion' => 1, + 'audioencoding' => 1, + 'audioencodingparamsversion' => 1, + 'audioextendfrequencies' => 1, + 'audiofilesize' => 1, + 'audiofileurl' => 1, + 'audioformat' => 1, + 'audioframesize' => 1, + 'audiogain' => 1, + 'audiohasvariablepacketbytesizes' => 1, + 'audioheader' => 1, + 'audioinfo' => 1, + 'audioinputbuffersize' => 1, + 'audioisinitialized' => 1, + 'audiolayer' => 1, + 'audiomaxbitrate' => 1, + 'audiomaximumpacketbytesize' => 1, + 'audiominimumdelaymode' => 1, + 'audiominimumnumberinputpackets' => 1, + 'audiominimumnumberoutputpackets' => 1, + 'audiomode' => 1, + 'audiooutputprecedence' => 1, + 'audiopacketframesize' => 1, + 'audioprofile' => 1, + 'audioprofileversion' => 1, + 'audioqualitysetting' => 1, + 'audiorequirespacketdescription' => 1, + 'audiosamplecount' => 1, + 'audiosampledesc' => 1, + 'audiosamplesize' => 1, + 'audiosetting' => 1, + 'audiosize' => 1, + 'audiosourceurl' => 1, + 'audiostream' => 1, + 'audiostreamtype' => 1, + 'audiotrackid' => 1, + 'audiousedinputbuffersize' => 1, + 'audiouserecommendedsamplerate' => 1, + 'audiovbrquality' => 1, + 'audiovendorid' => 1, + 'audiozeroframespadded' => 1, + 'authenticationtime' => 1, + 'authenticationtype' => 1, + 'authoringsoftwarerelease' => 1, + 'authorlen' => 1, + 'authorship' => 1, + 'authorsortorder' => 1, + 'authorurl' => 1, + 'autoisomin' => 1, + 'autolowlightduration' => 1, + 'autorotation' => 1, + 'autosavefilepath' => 1, + 'autosaveformat' => 1, + 'autosummary' => 1, + 'aux' => 1, + 'auxiliaryimagetype' => 1, + 'avcconfiguration' => 1, + 'averagebitrate' => 1, + 'averagelevel' => 1, + 'avgbitrate' => 1, + 'avgbytespersec' => 1, + 'avgpacketsize' => 1, + 'avgpdusize' => 1, + 'avgwidth' => 1, + 'avi1' => 1, + 'avif' => 1, + 'aviheader' => 1, + 'awbinfo' => 1, + 'axisdistancex' => 1, + 'axisdistancey' => 1, + 'axisdistancez' => 1, + 'background' => 1, + 'backgroundcolor' => 1, + 'backgroundcolorindicator' => 1, + 'backgroundcolorvalue' => 1, + 'backgroundimageid' => 1, + 'backgroundtiling' => 1, + 'backlight' => 1, + 'backserial' => 1, + 'backuptime' => 1, + 'badfaxlines' => 1, + 'bahpver' => 1, + 'balance' => 1, + 'balpver' => 1, + 'band' => 1, + 'bandwidthsharing' => 1, + 'bannerimage' => 1, + 'bannerimagedata' => 1, + 'bannerimagetype' => 1, + 'bannerimageurl' => 1, + 'barcode' => 1, + 'barometerinfo' => 1, + 'barometerinfoversion' => 1, + 'baselinelength' => 1, + 'baseviewpointnum' => 1, + 'basisobject' => 1, + 'bass' => 1, + 'battery' => 1, + 'batterycapacity' => 1, + 'batterycurrent' => 1, + 'batteryinfo' => 1, + 'batterystatus' => 1, + 'batterytime' => 1, + 'batteryvoltage3' => 1, + 'batteryvoltage4' => 1, + 'bavpver' => 1, + 'bccaddresses' => 1, + 'bccnames' => 1, + 'beats-per-minute' => 1, + 'beatsperminute' => 1, + 'belowcolor' => 1, + 'beta' => 1, + 'bibligraphicfilename' => 1, + 'bikebroaccel' => 1, + 'bikebrogps' => 1, + 'billinginformation' => 1, + 'binaryfilter' => 1, + 'binaryxml' => 1, + 'birthday' => 1, + 'bitrate' => 1, + 'bitrateinfo' => 1, + 'bitratemutualexclusion' => 1, + 'bitsperextendedrunlength' => 1, + 'bitsperpixel' => 1, + 'bitsperrunlength' => 1, + 'blackadcountsperdacvolt' => 1, + 'blackclamp' => 1, + 'blackclampoffset' => 1, + 'blackcolsleft' => 1, + 'blackcolsright' => 1, + 'blackdacchannel' => 1, + 'blackdacsettlingmsec' => 1, + 'blackmaskbottomborder' => 1, + 'blackmaskleftborder' => 1, + 'blackmaskrightborder' => 1, + 'blackmasktopborder' => 1, + 'blackrowsbottom' => 1, + 'blackrowstop' => 1, + 'blacktarget' => 1, + 'blocklocation' => 1, + 'blocksize' => 1, + 'blocksizemax' => 1, + 'blocksizemin' => 1, + 'blockspercolumn' => 1, + 'blocksperframe' => 1, + 'blocksperrow' => 1, + 'blueadjust' => 1, + 'blueendpoint' => 1, + 'bluegain' => 1, + 'bluegrassscale1' => 1, + 'bluegrassscale2' => 1, + 'bluegrasstable' => 1, + 'bluemask' => 1, + 'bluematrixcolumn' => 1, + 'blueprimary' => 1, + 'bluesample' => 1, + 'bluetrc' => 1, + 'bluex' => 1, + 'bluey' => 1, + 'bmpversion' => 1, + 'boardtemperature' => 1, + 'bookname' => 1, + 'booktitle' => 1, + 'booktype' => 1, + 'bookversion' => 1, + 'bootidentifier' => 1, + 'bootrecord' => 1, + 'bootsystem' => 1, + 'bordercolor' => 1, + 'borderid' => 1, + 'borderinformation' => 1, + 'borderlocation' => 1, + 'bordername' => 1, + 'bordersversion' => 1, + 'bordertype' => 1, + 'bottomdarkrow1' => 1, + 'bottomdarkrow2' => 1, + 'bottommag' => 1, + 'boundaryorigin' => 1, + 'boundingbox' => 1, + 'bracketingcounter' => 1, + 'bracketinginfooffset' => 1, + 'bracketingmode' => 1, + 'bracketingoffset' => 1, + 'bracketingstep' => 1, + 'bracketshot' => 1, + 'brain' => 1, + 'brandingimageid' => 1, + 'brandingname' => 1, + 'breakchar' => 1, + 'brightdefectintegrationms' => 1, + 'brightdefectisocode' => 1, + 'brightdefectthreshold' => 1, + 'brightnessdata' => 1, + 'brightrowstop' => 1, + 'broadcast' => 1, + 'broadcastdate' => 1, + 'broadcastextension' => 1, + 'btoa0' => 1, + 'btoa1' => 1, + 'btoa2' => 1, + 'btod0' => 1, + 'btod1' => 1, + 'btod2' => 1, + 'btod3' => 1, + 'bufferaverage' => 1, + 'buffersize' => 1, + 'builddate' => 1, + 'buildversion' => 1, + 'businessaddress' => 1, + 'businesscity' => 1, + 'businesscountry-region' => 1, + 'businessfax' => 1, + 'businesshomepage' => 1, + 'businessphone' => 1, + 'businesspobox' => 1, + 'businesspostalcode' => 1, + 'businessstateorprovince' => 1, + 'businessstreet' => 1, + 'buynow' => 1, + 'buytickets' => 1, + 'bw_halftoninginfo' => 1, + 'bw_transferfunc' => 1, + 'bwfversion' => 1, + 'bytelength' => 1, + 'byteorder' => 1, + 'bytes' => 1, + 'bytesperline' => 1, + 'bytesperminute' => 1, + 'cachecontrol' => 1, + 'cachedimageheight' => 1, + 'cachedimagewidth' => 1, + 'calculatedscalemax' => 1, + 'calculatedscalemin' => 1, + 'calibrationdatetime' => 1, + 'calibrationlog' => 1, + 'callbacknumber' => 1, + 'callletters' => 1, + 'camcore' => 1, + 'camera' => 1, + 'camera1' => 1, + 'camera2' => 1, + 'cameraarrangementinterval' => 1, + 'camerabacktype' => 1, + 'camerabody' => 1, + 'camerabyteorder' => 1, + 'cameradatetime' => 1, + 'cameradirection' => 1, + 'cameraidentifier' => 1, + 'cameraifd' => 1, + 'camerainfo' => 1, + 'camerainfo2' => 1, + 'camerainfo3' => 1, + 'camerainfoa100' => 1, + 'camerainfounknown' => 1, + 'cameramaker' => 1, + 'cameramanufacturer' => 1, + 'cameramotion' => 1, + 'cameraname' => 1, + 'cameraobjbacktype' => 1, + 'cameraobject' => 1, + 'cameraobjname' => 1, + 'cameraobjtype' => 1, + 'cameraobjversion' => 1, + 'cameraoperator' => 1, + 'camerapartnumber' => 1, + 'cameraprofileversion' => 1, + 'camerascalemax' => 1, + 'camerascalemin' => 1, + 'camerasettings' => 1, + 'camerasettings2' => 1, + 'camerasettings3' => 1, + 'camerasettingsa100' => 1, + 'camerasettingsifd' => 1, + 'camerasettingsunknown' => 1, + 'camerasetup' => 1, + 'camerasoftware' => 1, + 'cameraspecification' => 1, + 'cameratemperaturemaxclip' => 1, + 'cameratemperaturemaxsaturated' => 1, + 'cameratemperaturemaxwarn' => 1, + 'cameratemperatureminclip' => 1, + 'cameratemperatureminsaturated' => 1, + 'cameratemperatureminwarn' => 1, + 'camm0' => 1, + 'camm1' => 1, + 'camm2' => 1, + 'camm3' => 1, + 'camm4' => 1, + 'camm5' => 1, + 'camm6' => 1, + 'camm7' => 1, + 'can_skip_backward' => 1, + 'can_skip_forward' => 1, + 'canon' => 1, + 'canon_afinfo2_0x000d' => 1, + 'canon_afinfo_0x000b' => 1, + 'canonafinfo' => 1, + 'canonafinfo2' => 1, + 'canoncamerainfo1000d' => 1, + 'canoncamerainfo1100d' => 1, + 'canoncamerainfo1200d' => 1, + 'canoncamerainfo1d' => 1, + 'canoncamerainfo1dmkii' => 1, + 'canoncamerainfo1dmkiii' => 1, + 'canoncamerainfo1dmkiin' => 1, + 'canoncamerainfo1dmkiv' => 1, + 'canoncamerainfo1dx' => 1, + 'canoncamerainfo40d' => 1, + 'canoncamerainfo450d' => 1, + 'canoncamerainfo500d' => 1, + 'canoncamerainfo50d' => 1, + 'canoncamerainfo550d' => 1, + 'canoncamerainfo5d' => 1, + 'canoncamerainfo5dmkii' => 1, + 'canoncamerainfo5dmkiii' => 1, + 'canoncamerainfo600d' => 1, + 'canoncamerainfo60d' => 1, + 'canoncamerainfo650d' => 1, + 'canoncamerainfo6d' => 1, + 'canoncamerainfo700d' => 1, + 'canoncamerainfo70d' => 1, + 'canoncamerainfo750d' => 1, + 'canoncamerainfo760d' => 1, + 'canoncamerainfo7d' => 1, + 'canoncamerainfo80d' => 1, + 'canoncamerainfopowershot' => 1, + 'canoncamerainfopowershot2' => 1, + 'canoncamerainfounknown' => 1, + 'canoncamerainfounknown16' => 1, + 'canoncamerainfounknown32' => 1, + 'canoncamerasettings' => 1, + 'canoncctp' => 1, + 'canoncnop' => 1, + 'canoncnth' => 1, + 'canoncolorinfo1' => 1, + 'canoncolorinfo2' => 1, + 'canonfileinfo' => 1, + 'canonflags' => 1, + 'canonfocallength' => 1, + 'canonimageheight' => 1, + 'canonimagewidth' => 1, + 'canonpanorama' => 1, + 'canonrawmakemodel' => 1, + 'canonshotinfo' => 1, + 'canonskip' => 1, + 'canseekontime' => 1, + 'canseektoend' => 1, + 'capheight' => 1, + 'captiontext' => 1, + 'captprofbacktype' => 1, + 'captprofname' => 1, + 'captproftype' => 1, + 'captprofversion' => 1, + 'captureconditionspar' => 1, + 'capturedevicefid' => 1, + 'captureheightresetblacksegnormal' => 1, + 'captureheightresetblacksegtest' => 1, + 'captureheighttest' => 1, + 'captureobjbacktype' => 1, + 'captureobjname' => 1, + 'captureobjtype' => 1, + 'captureobjversion' => 1, + 'captureprofile' => 1, + 'captureresolution' => 1, + 'captureserial' => 1, + 'capturesetup' => 1, + 'capturewidthresetblacksegnormal' => 1, + 'capturewidthresetblacksegtest' => 1, + 'capturexresolution' => 1, + 'capturexresolutionunit' => 1, + 'captureyresolution' => 1, + 'captureyresolutionunit' => 1, + 'carphone' => 1, + 'casio' => 1, + 'casiodata' => 1, + 'casiojunk' => 1, + 'casioquality' => 1, + 'casioqvmi' => 1, + 'cast' => 1, + 'cc' => 1, + 'ccaddresses' => 1, + 'ccdrect' => 1, + 'ccdvalidrect' => 1, + 'ccdvideorect' => 1, + 'ccnames' => 1, + 'cddb1info' => 1, + 'cddbdiscplaytime' => 1, + 'cddbdisctracks' => 1, + 'cddbtracknumber' => 1, + 'cdetype' => 1, + 'cdi1' => 1, + 'cdtrackenabled' => 1, + 'cell' => 1, + 'cellphone' => 1, + 'centerdarkrect' => 1, + 'cfagreenthreshold1' => 1, + 'cfagreenthreshold2' => 1, + 'cfalayout' => 1, + 'cfaplanecolor' => 1, + 'channel0lagkernel' => 1, + 'channel1coordinates' => 1, + 'channel1flags' => 1, + 'channel1label' => 1, + 'channel1lagkernel' => 1, + 'channel2coordinates' => 1, + 'channel2flags' => 1, + 'channel2label' => 1, + 'channel2lagkernel' => 1, + 'channel3coordinates' => 1, + 'channel3flags' => 1, + 'channel3label' => 1, + 'channel3lagkernel' => 1, + 'channel4coordinates' => 1, + 'channel4flags' => 1, + 'channel4label' => 1, + 'channel5coordinates' => 1, + 'channel5flags' => 1, + 'channel5label' => 1, + 'channel6coordinates' => 1, + 'channel6flags' => 1, + 'channel6label' => 1, + 'channel7coordinates' => 1, + 'channel7flags' => 1, + 'channel7label' => 1, + 'channel8coordinates' => 1, + 'channel8flags' => 1, + 'channel8label' => 1, + 'channelcoarsegainadjust' => 1, + 'channelmode' => 1, + 'channelnumber' => 1, + 'channelusage' => 1, + 'chapter' => 1, + 'chaptercount' => 1, + 'chapterlist' => 1, + 'chapterlisttrackid' => 1, + 'chaptername' => 1, + 'chapternum' => 1, + 'chapternumber' => 1, + 'characterescapesequence' => 1, + 'characters' => 1, + 'characterset' => 1, + 'characterswithspaces' => 1, + 'charcountwithspaces' => 1, + 'chartarget' => 1, + 'chartcontourinterval' => 1, + 'chartcorrdate' => 1, + 'chartcountryorigin' => 1, + 'chartdepthunits' => 1, + 'chartformat' => 1, + 'chartmagvar' => 1, + 'chartmagvarannchange' => 1, + 'chartmagvaryear' => 1, + 'chartrasteredition' => 1, + 'chartsoundingdatum' => 1, + 'chartsource' => 1, + 'chartsourcedate' => 1, + 'chartsourceedition' => 1, + 'chartwgsnsshift' => 1, + 'checkedby' => 1, + 'children' => 1, + 'chmversion' => 1, + 'chromaticaberrationparams' => 1, + 'chromaticadaptation' => 1, + 'chromaticities' => 1, + 'chromaticity' => 1, + 'chromaticitychannel1' => 1, + 'chromaticitychannel2' => 1, + 'chromaticitychannel3' => 1, + 'chromaticitychannel4' => 1, + 'chromaticitychannels' => 1, + 'chromaticitycolorant' => 1, + 'chunkoffset' => 1, + 'chunkoffset64' => 1, + 'ciff' => 1, + 'cinematographer' => 1, + 'cip3datafile' => 1, + 'cip3sheet' => 1, + 'cip3side' => 1, + 'circleofconfusion' => 1, + 'class' => 1, + 'classification' => 1, + 'cleanaperture' => 1, + 'cleanaperturedimensions' => 1, + 'cleanapertureheight' => 1, + 'cleanapertureoffsetx' => 1, + 'cleanapertureoffsety' => 1, + 'cleanaperturewidth' => 1, + 'cleanfaxdata' => 1, + 'clientid' => 1, + 'clipboundary' => 1, + 'clipfilename' => 1, + 'clipid' => 1, + 'clipobjects' => 1, + 'clippath' => 1, + 'clippingboundary' => 1, + 'clippinglimit' => 1, + 'clippingpathname' => 1, + 'cloneid' => 1, + 'cloneobject' => 1, + 'clonetype' => 1, + 'closedcaptioning' => 1, + 'cmmflags' => 1, + 'cmykequivalent' => 1, + 'coarsedata' => 1, + 'coarsemapimage' => 1, + 'coarsemapimageheight' => 1, + 'coarsemapimagetype' => 1, + 'coarsemapimagewidth' => 1, + 'codecflavorid' => 1, + 'codeclist' => 1, + 'codedframesize' => 1, + 'codepage' => 1, + 'codesize' => 1, + 'codestreamheader' => 1, + 'codestreamregistration' => 1, + 'codeversion' => 1, + 'codinghistory' => 1, + 'codingmethods' => 1, + 'codirectors' => 1, + 'colorant1coordinates' => 1, + 'colorant1name' => 1, + 'colorant2coordinates' => 1, + 'colorant2name' => 1, + 'colorant3coordinates' => 1, + 'colorant3name' => 1, + 'colorantcount' => 1, + 'colorantorder' => 1, + 'coloranttable' => 1, + 'coloranttableout' => 1, + 'coloraverages' => 1, + 'colorbalance0100' => 1, + 'colorbalance0102' => 1, + 'colorbalance0103' => 1, + 'colorbalance02' => 1, + 'colorbalance0205' => 1, + 'colorbalance0209' => 1, + 'colorbalance0211' => 1, + 'colorbalance0213' => 1, + 'colorbalance0215' => 1, + 'colorbalancea' => 1, + 'colorbalanceunknown' => 1, + 'colorbalanceunknown02' => 1, + 'colorbalanceunknown04' => 1, + 'colorbitdepth' => 1, + 'colorboostdata' => 1, + 'colorbw' => 1, + 'colorcalib' => 1, + 'colorcalib2' => 1, + 'colorcalibrationmatrix' => 1, + 'colorcasts' => 1, + 'colorcharacterization' => 1, + 'colorcoefs' => 1, + 'colorcoefs2' => 1, + 'colorcomponents' => 1, + 'colordata1' => 1, + 'colordata2' => 1, + 'colordata3' => 1, + 'colordata4' => 1, + 'colordata5' => 1, + 'colordata6' => 1, + 'colordata7' => 1, + 'colordata8' => 1, + 'colordata9' => 1, + 'colordataunknown' => 1, + 'colorgroup' => 1, + 'colorhalftoninginfo' => 1, + 'colorimetricintentimagestate' => 1, + 'colorimetry' => 1, + 'colorinfo' => 1, + 'colormap' => 1, + 'colorobjbacktype' => 1, + 'colorobjname' => 1, + 'colorobjtype' => 1, + 'colorobjversion' => 1, + 'colorpalette' => 1, + 'colorprimaries' => 1, + 'colorresolutiondepth' => 1, + 'colorresponseunit' => 1, + 'colors' => 1, + 'colorsamplersresource' => 1, + 'colorsamplersresource2' => 1, + 'colorsetup' => 1, + 'colorspacedata' => 1, + 'colorspecapproximation' => 1, + 'colorspecdata' => 1, + 'colorspecification' => 1, + 'colorspecmethod' => 1, + 'colorspecprecedence' => 1, + 'colortable' => 1, + 'colortemperatures' => 1, + 'colortransferfuncs' => 1, + 'colortransform' => 1, + 'colortwistmatrix' => 1, + 'colortype' => 1, + 'columngainfactors' => 1, + 'columnresetoffsets' => 1, + 'command' => 1, + 'commandlinearguments' => 1, + 'commentby' => 1, + 'commentlen' => 1, + 'comments' => 1, + 'commenttime' => 1, + 'commercialurl' => 1, + 'commissioned' => 1, + 'common' => 1, + 'commonnetworkrellink' => 1, + 'commonpathsuffix' => 1, + 'compactsamplesizes' => 1, + 'company' => 1, + 'companymainphone' => 1, + 'companyname' => 1, + 'compatibility' => 1, + 'compatiblebrands' => 1, + 'compatiblefontname' => 1, + 'compilation' => 1, + 'complete' => 1, + 'compobj' => 1, + 'compobjusertype' => 1, + 'compobjusertypelen' => 1, + 'componentbitdepth' => 1, + 'componentdefinition' => 1, + 'componentmapping' => 1, + 'componenttable' => 1, + 'composerkeywords' => 1, + 'composers' => 1, + 'composersortorder' => 1, + 'compositinglayerheader' => 1, + 'compositionmode' => 1, + 'compositionoptions' => 1, + 'compositiontimetosample' => 1, + 'compositiontodecodetimelinemapping' => 1, + 'compressed' => 1, + 'compressedannotation' => 1, + 'compresseddatalength' => 1, + 'compresseddataoffset' => 1, + 'compressedmovie' => 1, + 'compressedsize' => 1, + 'compressedtext' => 1, + 'compressionclass' => 1, + 'compressionlevel' => 1, + 'compressiontype' => 1, + 'compressorid' => 1, + 'compressorname' => 1, + 'compressorversion' => 1, + 'computedatmospherictrans' => 1, + 'computer' => 1, + 'concreteflag' => 1, + 'condition' => 1, + 'conditionalfec' => 1, + 'conductor' => 1, + 'conductors' => 1, + 'confirmedobjectsize' => 1, + 'connectionspaceilluminant' => 1, + 'consecutivebadfaxlines' => 1, + 'consoledata' => 1, + 'consolefedata' => 1, + 'cont' => 1, + 'contactnames' => 1, + 'containerversion' => 1, + 'contake' => 1, + 'contentbranding' => 1, + 'contentcreatedate' => 1, + 'contentdescribes' => 1, + 'contentdescription' => 1, + 'contentdescriptionnotes' => 1, + 'contentdisposition' => 1, + 'contentdistributor' => 1, + 'contentdistributorduration' => 1, + 'contentdistributorid' => 1, + 'contentdistributortype' => 1, + 'contentencryption' => 1, + 'contentgroupdescription' => 1, + 'contentid' => 1, + 'contentlanguage' => 1, + 'contentprotected' => 1, + 'contentprotectedpercent' => 1, + 'contentrating' => 1, + 'contents' => 1, + 'contentscripttype' => 1, + 'contentstyletype' => 1, + 'contiguouscodestream' => 1, + 'contrastadjustment' => 1, + 'contrastinfo' => 1, + 'controller' => 1, + 'convergenceangle' => 1, + 'convergencebaseimage' => 1, + 'convergencedistance' => 1, + 'conversationid' => 1, + 'copyrightfilename' => 1, + 'copyrightlen' => 1, + 'copyrighturl' => 1, + 'coringtablebest' => 1, + 'coringtablebetter' => 1, + 'coringtablegood' => 1, + 'correctionmethod' => 1, + 'costumedesigner' => 1, + 'count' => 1, + 'countinfo' => 1, + 'country-region' => 1, + 'coverart' => 1, + 'coverartmimetype' => 1, + 'coverarttype' => 1, + 'coveruri' => 1, + 'coyotesense' => 1, + 'coyotestatus' => 1, + 'cpuarchitecture' => 1, + 'cpubyteorder' => 1, + 'cpucount' => 1, + 'cpusubtype' => 1, + 'cputype' => 1, + 'cpuversions' => 1, + 'cr2cfapattern' => 1, + 'crcdevelparams' => 1, + 'crdinfo' => 1, + 'createdby' => 1, + 'creatingapplication' => 1, + 'creatingtransform' => 1, + 'creationpathvector' => 1, + 'creatorapplication' => 1, + 'creatorappversion' => 1, + 'creatoratom' => 1, + 'creatorbuildnumber' => 1, + 'creatorbuildnumber2' => 1, + 'creatorinfo' => 1, + 'creatormajorversion' => 1, + 'creatorminorversion' => 1, + 'creatorsoftware' => 1, + 'creatorversion' => 1, + 'crgbtoerimm0spline' => 1, + 'crgbtoerimm1spline' => 1, + 'crgbtoerimm2spline' => 1, + 'crgbtoerimm3spline' => 1, + 'crgbtoerimm4spline' => 1, + 'crgbtoerimm5spline' => 1, + 'crgbtoerimm6spline' => 1, + 'crgbtoerimm7spline' => 1, + 'crgbtoerimm8spline' => 1, + 'crgbtoerimm9spline' => 1, + 'cropdata' => 1, + 'cropinfo' => 1, + 'cropped' => 1, + 'cropxcommonoffset' => 1, + 'cropxoffset' => 1, + 'cropxoffset2' => 1, + 'cropxsize' => 1, + 'cropxviewpointnumber' => 1, + 'cropxviewpointnumber2' => 1, + 'cropycommonoffset' => 1, + 'cropyoffset' => 1, + 'cropyoffset2' => 1, + 'cropysize' => 1, + 'cropyviewpointnumber' => 1, + 'cropyviewpointnumber2' => 1, + 'cross-reference' => 1, + 'crossbarenable' => 1, + 'crossref' => 1, + 'crs' => 1, + 'crwparam' => 1, + 'cs1' => 1, + 'ctmd' => 1, + 'cubemapproj' => 1, + 'cuepoint' => 1, + 'cuepoints' => 1, + 'cuesheet' => 1, + 'currentbitrate' => 1, + 'currentiptcdigest' => 1, + 'currenttime' => 1, + 'currentuser' => 1, + 'cursorsize' => 1, + 'customfunctions10d' => 1, + 'customfunctions1d' => 1, + 'customfunctions2' => 1, + 'customfunctions20d' => 1, + 'customfunctions30d' => 1, + 'customfunctions350d' => 1, + 'customfunctions400d' => 1, + 'customfunctions5d' => 1, + 'customfunctionsd30' => 1, + 'customfunctionsd60' => 1, + 'customfunctionsunknown' => 1, + 'customsettingsd3' => 1, + 'customsettingsd300' => 1, + 'customsettingsd300s' => 1, + 'customsettingsd3s' => 1, + 'customsettingsd3x' => 1, + 'customsettingsd4' => 1, + 'customsettingsd40' => 1, + 'customsettingsd4s' => 1, + 'customsettingsd5' => 1, + 'customsettingsd500' => 1, + 'customsettingsd5000' => 1, + 'customsettingsd5100' => 1, + 'customsettingsd5200' => 1, + 'customsettingsd610' => 1, + 'customsettingsd700' => 1, + 'customsettingsd7000' => 1, + 'customsettingsd80' => 1, + 'customsettingsd800' => 1, + 'customsettingsd810' => 1, + 'customsettingsd850' => 1, + 'customsettingsd90' => 1, + 'customsettingsoffset' => 1, + 'cx' => 1, + 'cy' => 1, + 'd-lightinghqdata' => 1, + 'd-lightinghsdata' => 1, + 'daccountspervolt' => 1, + 'dacgainscoarse' => 1, + 'dacgainscoarseadjpreif41' => 1, + 'dacgainsfine' => 1, + 'dacvoltages' => 1, + 'dacvoltagesflush' => 1, + 'darkcorrectiontype' => 1, + 'darkmapscale' => 1, + 'darkrefoffsetnormal' => 1, + 'darkrefoffsettest' => 1, + 'darkthreshold' => 1, + 'darwindata' => 1, + 'data1' => 1, + 'data2' => 1, + 'databasename' => 1, + 'datacreatedate' => 1, + 'datadump' => 1, + 'datadump2' => 1, + 'datainfo' => 1, + 'datainformation' => 1, + 'datakey' => 1, + 'datalen' => 1, + 'datalength' => 1, + 'datalocation' => 1, + 'datamodifydate' => 1, + 'dataobject' => 1, + 'dataobjectid' => 1, + 'dataobjectstatus' => 1, + 'dataobjecttitle' => 1, + 'dataoffset' => 1, + 'dataoffsets' => 1, + 'datapackets' => 1, + 'datapreparer' => 1, + 'datarate' => 1, + 'dataref' => 1, + 'datareference' => 1, + 'datasign' => 1, + 'datasize' => 1, + 'datasize64' => 1, + 'datatype' => 1, + 'datawindow' => 1, + 'dateaccessed' => 1, + 'datearchived' => 1, + 'datecompleted' => 1, + 'dateimported' => 1, + 'datelastsaved' => 1, + 'datemodified' => 1, + 'datepicturetaken' => 1, + 'datereceived' => 1, + 'datereleased' => 1, + 'datetime1' => 1, + 'datetime2' => 1, + 'datetimecreated' => 1, + 'datetimeend' => 1, + 'datetimegenerated' => 1, + 'datevisited' => 1, + 'daymat0' => 1, + 'daymat1' => 1, + 'daymat2' => 1, + 'daymat3' => 1, + 'daymat4' => 1, + 'daymat5' => 1, + 'daymat6' => 1, + 'daymat7' => 1, + 'daymat8' => 1, + 'daymat9' => 1, + 'dblcoldcacthres1' => 1, + 'dblcoldcacthres2' => 1, + 'dc' => 1, + 'dcem' => 1, + 'dcme' => 1, + 'dcs3xxprocessinginfo' => 1, + 'dcs3xxprocessinginfoifd' => 1, + 'dctencodeversion' => 1, + 'dealeridnumber' => 1, + 'decimationmethod' => 1, + 'decimationprefilterwidth' => 1, + 'decode' => 1, + 'decodeconfig' => 1, + 'decodertable' => 1, + 'decodertablenumber' => 1, + 'decoderversion' => 1, + 'defaultaudiostream' => 1, + 'defaultchar' => 1, + 'defaultdisplayheight' => 1, + 'defaultdisplaywidth' => 1, + 'defaultimagecolor' => 1, + 'defaultrgb' => 1, + 'defaultstyle' => 1, + 'defectconcealartcorrectthres' => 1, + 'defectconcealthrestable' => 1, + 'defectcount' => 1, + 'defectlist' => 1, + 'defectlistpacked' => 1, + 'defineobject' => 1, + 'definequantizationtable' => 1, + 'delay' => 1, + 'delaycols' => 1, + 'delaytime' => 1, + 'delta12to8spline' => 1, + 'delta8to12spline' => 1, + 'deltapngheader' => 1, + 'deltatype' => 1, + 'deltaxy' => 1, + 'department' => 1, + 'dependentimage1entrynumber' => 1, + 'dependentimage2entrynumber' => 1, + 'depth' => 1, + 'depthmapdata' => 1, + 'depthmapheight' => 1, + 'depthmapname' => 1, + 'depthmaptiff' => 1, + 'depthmapwidth' => 1, + 'descender' => 1, + 'designer' => 1, + 'designerurl' => 1, + 'desiredreproductions' => 1, + 'destinationid' => 1, + 'detectedfacebounds' => 1, + 'detectedfaceid' => 1, + 'detectedfacerollangle' => 1, + 'detectedfaceyawangle' => 1, + 'detector' => 1, + 'detectorboard' => 1, + 'deviceattributes' => 1, + 'devicecontainer' => 1, + 'deviceid' => 1, + 'devicemanufacturer' => 1, + 'devicemfgdesc' => 1, + 'devicemodel' => 1, + 'devicemodeldesc' => 1, + 'devicename' => 1, + 'devicesettings' => 1, + 'dex' => 1, + 'dialect' => 1, + 'dicom' => 1, + 'dictionary' => 1, + 'dictionaryshortname' => 1, + 'difftilegains24t852822' => 1, + 'difftilegains602832' => 1, + 'digikam' => 1, + 'digitalcreationdatetime' => 1, + 'digitaleffectsname' => 1, + 'digitaleffectstype' => 1, + 'digitaleffectsversion' => 1, + 'digitalexposurebiases' => 1, + 'digitalexposuregains' => 1, + 'digitalimagebroker' => 1, + 'digitalsignature' => 1, + 'dimensions' => 1, + 'directors' => 1, + 'disableflagspresent' => 1, + 'discardobjects' => 1, + 'disknumber' => 1, + 'displayartist' => 1, + 'displayinfo' => 1, + 'displayresolution' => 1, + 'displaysize' => 1, + 'displayunits' => 1, + 'displaywindow' => 1, + 'displayxresolution' => 1, + 'displayxresolutionunit' => 1, + 'displayyresolution' => 1, + 'displayyresolutionunit' => 1, + 'dispose' => 1, + 'disposition' => 1, + 'distortinfo' => 1, + 'distortioninfo' => 1, + 'distortionversion' => 1, + 'distributedby' => 1, + 'distribution' => 1, + 'dittokey' => 1, + 'division' => 1, + 'djvuversion' => 1, + 'dlnaserverudn' => 1, + 'dlnasourceuri' => 1, + 'dlodata' => 1, + 'dlodatalength' => 1, + 'dloinfo' => 1, + 'dmeroderadius' => 1, + 'dmfillrejthresh' => 1, + 'dmnoisescale' => 1, + 'dmnumpatches' => 1, + 'dmpixelthresholdfactor' => 1, + 'dmsmoothrejthresh' => 1, + 'dmtrimfraction' => 1, + 'dmwindowthresholdfactor' => 1, + 'docclass' => 1, + 'docflags' => 1, + 'docmdp' => 1, + 'docrights' => 1, + 'docsecurity' => 1, + 'doctype' => 1, + 'documentinfo' => 1, + 'documentnumber' => 1, + 'documentusagerights' => 1, + 'dof' => 1, + 'donotshow' => 1, + 'dop' => 1, + 'dotrange' => 1, + 'dotsperinch' => 1, + 'downsampleby2hor' => 1, + 'downsampleby2hor3mpdcr' => 1, + 'downsampleby2ver' => 1, + 'downsampleby2ver3mpdcr' => 1, + 'downsampleby3hor' => 1, + 'downsampleby3ver' => 1, + 'downsampleby4hor' => 1, + 'downsampleby4ver' => 1, + 'downsampleby6hor' => 1, + 'downsampleby6ver' => 1, + 'dpxfilesize' => 1, + 'dr4' => 1, + 'dr4header' => 1, + 'driveserialnumber' => 1, + 'drivesettings' => 1, + 'drivetype' => 1, + 'drm' => 1, + 'drm_contentid' => 1, + 'drm_drmheader' => 1, + 'drm_drmheader_contentdistributor' => 1, + 'drm_drmheader_contentid' => 1, + 'drm_drmheader_individualizedversion' => 1, + 'drm_drmheader_keyid' => 1, + 'drm_drmheader_licenseacqurl' => 1, + 'drm_drmheader_subscriptioncontentid' => 1, + 'drm_e-bookbaseid' => 1, + 'drm_individualizedversion' => 1, + 'drm_keyid' => 1, + 'drm_lasignaturecert' => 1, + 'drm_lasignaturelicsrvcert' => 1, + 'drm_lasignatureprivkey' => 1, + 'drm_lasignaturerootcert' => 1, + 'drm_licenseacqurl' => 1, + 'drm_v1licenseacqurl' => 1, + 'drmcommerceid' => 1, + 'drmindividualizedversion' => 1, + 'drmkeyid' => 1, + 'drmserverid' => 1, + 'drone-dji' => 1, + 'dropbykeyword' => 1, + 'dropchunks' => 1, + 'dtcpiphost' => 1, + 'dtcpipport' => 1, + 'dtob0' => 1, + 'dtob1' => 1, + 'dtob2' => 1, + 'dtob3' => 1, + 'dtvcontent' => 1, + 'dualcameraimage' => 1, + 'dualcameraimagename' => 1, + 'dualshotinfo' => 1, + 'ducky' => 1, + 'duedate' => 1, + 'dummycolsleft' => 1, + 'dummycolsright' => 1, + 'duotonehalftoninginfo' => 1, + 'duotoneimageinfo' => 1, + 'duotonetransferfuncs' => 1, + 'dustdeleteapplied' => 1, + 'dustinfo' => 1, + 'dvdid' => 1, + 'dwc' => 1, + 'e-mail2' => 1, + 'e-mail3' => 1, + 'e-mailaddress' => 1, + 'e-maildisplayname' => 1, + 'e-maillist' => 1, + 'edgespline' => 1, + 'edgesplinehigh' => 1, + 'edgesplinelow' => 1, + 'edgesplinemed' => 1, + 'edit1' => 1, + 'edit2' => 1, + 'edit3' => 1, + 'edit4' => 1, + 'edit4data' => 1, + 'edit5' => 1, + 'edit6' => 1, + 'edit7' => 1, + 'edit8' => 1, + 'edit9' => 1, + 'editdata' => 1, + 'editedby' => 1, + 'editor' => 1, + 'edittagarray' => 1, + 'effect' => 1, + 'effectivebw' => 1, + 'effectsvisible' => 1, + 'eighteenpercentpoint' => 1, + 'eighthlanguage' => 1, + 'electronicvr' => 1, + 'elementarystreamtrack' => 1, + 'embeddedaudiofile' => 1, + 'embeddedaudiofilename' => 1, + 'embeddedfile' => 1, + 'embeddedfilename' => 1, + 'embeddedfileusagerights' => 1, + 'embeddedimage' => 1, + 'embeddedimagecolorspace' => 1, + 'embeddedimagefilter' => 1, + 'embeddedimageheight' => 1, + 'embeddedimagename' => 1, + 'embeddedimagetype' => 1, + 'embeddedimagewidth' => 1, + 'embeddedjpg' => 1, + 'embeddedpng' => 1, + 'embeddedvideofile' => 1, + 'embeddedvideotype' => 1, + 'emphasis' => 1, + 'empty' => 1, + 'encodedby' => 1, + 'encodedpixelsdimensions' => 1, + 'encodedusing' => 1, + 'encodedwith' => 1, + 'encoder' => 1, + 'encoderid' => 1, + 'encoderoptions' => 1, + 'encodersettings' => 1, + 'encodervendor' => 1, + 'encoderversion' => 1, + 'encodetime' => 1, + 'encoding' => 1, + 'encodingparams' => 1, + 'encodingprocess' => 1, + 'encodingscheme' => 1, + 'encodingsettings' => 1, + 'encodingtime' => 1, + 'encrypt' => 1, + 'encryption' => 1, + 'enddate' => 1, + 'endpoints' => 1, + 'endtime' => 1, + 'endtimecode' => 1, + 'entrypoint' => 1, + 'entrytype' => 1, + 'environmentmap' => 1, + 'envvardata' => 1, + 'episodeglobaluniqueid' => 1, + 'eppim' => 1, + 'eprint' => 1, + 'epsoptions' => 1, + 'equipment' => 1, + 'equipmentifd' => 1, + 'equirectangularproj' => 1, + 'erimmnonlinearityspline' => 1, + 'erimmtocrgb0spline' => 1, + 'erimmtocrgb1spline' => 1, + 'erimmtocrgb2spline' => 1, + 'erimmtocrgb3spline' => 1, + 'erimmtocrgb4spline' => 1, + 'erimmtocrgb5spline' => 1, + 'erimmtocrgb6spline' => 1, + 'erimmtocrgb7spline' => 1, + 'erimmtocrgb8spline' => 1, + 'erimmtocrgb9spline' => 1, + 'erimmtonescale0spline' => 1, + 'erimmtonescale1spline' => 1, + 'erimmtonescale2spline' => 1, + 'erimmtonescale3spline' => 1, + 'erimmtonescale4spline' => 1, + 'erimmtonescale5spline' => 1, + 'erimmtonescale6spline' => 1, + 'erimmtonescale7spline' => 1, + 'erimmtonescale8spline' => 1, + 'erimmtonescale9spline' => 1, + 'error' => 1, + 'errorcorrection' => 1, + 'errorcorrectiontype' => 1, + 'escapestatus' => 1, + 'escchar' => 1, + 'estimatedatmospherictrans' => 1, + 'evalstate' => 1, + 'eventlogcapture' => 1, + 'eventlogprocess' => 1, + 'events' => 1, + 'evstepinfo' => 1, + 'exif_profile' => 1, + 'exifdata' => 1, + 'exifex' => 1, + 'exififd' => 1, + 'exifinfo' => 1, + 'exifinfo2' => 1, + 'exifinfo7' => 1, + 'exifinfo8' => 1, + 'exifinfo9' => 1, + 'exifinformation' => 1, + 'exifoffset' => 1, + 'exiftoolversion' => 1, + 'expandfilm' => 1, + 'expandfilterlens' => 1, + 'expandflashlamp' => 1, + 'expandlens' => 1, + 'expandscanner' => 1, + 'expandsoftware' => 1, + 'expirationspan' => 1, + 'expires' => 1, + 'exportimage' => 1, + 'exposurebias' => 1, + 'exposureheadroomfactor' => 1, + 'exposureinfo' => 1, + 'exposurereferencegain' => 1, + 'exposurereferenceoffset' => 1, + 'exposuretimes' => 1, + 'exposureunknown' => 1, + 'expressionmedia' => 1, + 'exrversion' => 1, + 'extcache' => 1, + 'extendedaviheader' => 1, + 'extendedcontentdescr' => 1, + 'extendedcontentencryption' => 1, + 'extendedinfo' => 1, + 'extendedstreamprops' => 1, + 'extendedxmp' => 1, + 'extensionclassid' => 1, + 'extensioncreatedate' => 1, + 'extensiondescription' => 1, + 'extensionmodifydate' => 1, + 'extensionname' => 1, + 'extensionpersistence' => 1, + 'extensions' => 1, + 'extensis' => 1, + 'externalleading' => 1, + 'externaltriggercount' => 1, + 'extraflags' => 1, + 'extrainfo' => 1, + 'extrainfo2' => 1, + 'extrainfo3' => 1, + 'extrasamples' => 1, + 'extraticklocations' => 1, + 'f-stop' => 1, + 'face1birthday' => 1, + 'face1category' => 1, + 'face1name' => 1, + 'face2birthday' => 1, + 'face2category' => 1, + 'face2name' => 1, + 'face3birthday' => 1, + 'face3category' => 1, + 'face3name' => 1, + 'face4birthday' => 1, + 'face4category' => 1, + 'face4name' => 1, + 'face5birthday' => 1, + 'face5category' => 1, + 'face5name' => 1, + 'face6birthday' => 1, + 'face6category' => 1, + 'face6name' => 1, + 'face7birthday' => 1, + 'face7category' => 1, + 'face7name' => 1, + 'face8birthday' => 1, + 'face8category' => 1, + 'face8name' => 1, + 'facedetect1' => 1, + 'facedetect2' => 1, + 'facedetect3' => 1, + 'facedetected' => 1, + 'facedetinfo' => 1, + 'faceinfo' => 1, + 'faceinfo1' => 1, + 'faceinfo2' => 1, + 'faceinfoa' => 1, + 'faceinfolength' => 1, + 'faceinfooffset' => 1, + 'faceitem' => 1, + 'facenumbers' => 1, + 'facepos' => 1, + 'facerec' => 1, + 'facerecinfo' => 1, + 'facesize' => 1, + 'factorywhitegainsdaylight' => 1, + 'factorywhiteoffsetsdaylight' => 1, + 'farklewhitethreshold' => 1, + 'fastseek' => 1, + 'faxprofile' => 1, + 'faxrecvparams' => 1, + 'faxrecvtime' => 1, + 'faxsubaddress' => 1, + 'fdsc' => 1, + 'fedexedr' => 1, + 'fffheader' => 1, + 'fieldmdp' => 1, + 'fieldofview' => 1, + 'fieldpermissions' => 1, + 'fifthlanguage' => 1, + 'file1duration' => 1, + 'file1length' => 1, + 'file1md5sum' => 1, + 'file1media' => 1, + 'file1path' => 1, + 'file1pathutf-8' => 1, + 'fileaccessdate' => 1, + 'fileas' => 1, + 'fileattributes' => 1, + 'fileblockcount' => 1, + 'fileblocksize' => 1, + 'filecount' => 1, + 'filedescription' => 1, + 'filedeviceid' => 1, + 'filedevicenumber' => 1, + 'fileflags' => 1, + 'fileflagsmask' => 1, + 'filefunctionflags' => 1, + 'fileglobalprofile' => 1, + 'filehardlinks' => 1, + 'fileid' => 1, + 'fileinfo' => 1, + 'fileinfolen' => 1, + 'fileinfolen2' => 1, + 'fileinfoproperties' => 1, + 'fileinfoversion' => 1, + 'fileinodechangedate' => 1, + 'fileinodenumber' => 1, + 'filelength' => 1, + 'fileos' => 1, + 'fileowner' => 1, + 'filepath' => 1, + 'fileprofileversion' => 1, + 'fileproperties' => 1, + 'files' => 1, + 'filesequence' => 1, + 'filesize' => 1, + 'filesizebytes' => 1, + 'filesubtype' => 1, + 'filetype' => 1, + 'filetypeextension' => 1, + 'fileurl' => 1, + 'fileversionnumber' => 1, + 'fillattributes' => 1, + 'fillmethod' => 1, + 'filmbrand' => 1, + 'filmcategory' => 1, + 'filmframenumber' => 1, + 'filmgencode' => 1, + 'filmproductcode' => 1, + 'filmrollnumber' => 1, + 'filmsize' => 1, + 'filter' => 1, + 'filterinfo' => 1, + 'filtering' => 1, + 'filtermodel' => 1, + 'filterpartnumber' => 1, + 'filterserialnumber' => 1, + 'finalflushsequence' => 1, + 'finalframeblocks' => 1, + 'finishedfileprocessingrequest' => 1, + 'finishipaversion' => 1, + 'finishipfversion' => 1, + 'firmwareinfo' => 1, + 'firstchar' => 1, + 'firstflushsequence' => 1, + 'firstlanguage' => 1, + 'firstlines' => 1, + 'firstlinetransfertiming' => 1, + 'firstname' => 1, + 'firstobject' => 1, + 'firstobjectid' => 1, + 'fisheyefilter' => 1, + 'flac' => 1, + 'flagcolor' => 1, + 'flags' => 1, + 'flagstatus' => 1, + 'flashattributes' => 1, + 'flashexpcomp' => 1, + 'flashinfo' => 1, + 'flashinfo0100' => 1, + 'flashinfo0102' => 1, + 'flashinfo0103' => 1, + 'flashinfo0106' => 1, + 'flashinfo0107' => 1, + 'flashinfounknown' => 1, + 'flashinfoversion' => 1, + 'flashmat0' => 1, + 'flashmat1' => 1, + 'flashmat2' => 1, + 'flashmat3' => 1, + 'flashmat4' => 1, + 'flashmat5' => 1, + 'flashmat6' => 1, + 'flashmat7' => 1, + 'flashmat8' => 1, + 'flashmat9' => 1, + 'flashpixstreamfieldoffset' => 1, + 'flashpixstreampathname' => 1, + 'flashpower' => 1, + 'flashsyncmode' => 1, + 'flashttlmode' => 1, + 'flashused' => 1, + 'flashversion' => 1, + 'flavor' => 1, + 'flir' => 1, + 'flir_gps' => 1, + 'flir_moreinfo' => 1, + 'flir_params' => 1, + 'flir_parts' => 1, + 'flir_serial' => 1, + 'flir_unknown' => 1, + 'flir_unknownuuid' => 1, + 'fluormat0' => 1, + 'fluormat1' => 1, + 'fluormat2' => 1, + 'fluormat3' => 1, + 'fluormat4' => 1, + 'fluormat5' => 1, + 'fluormat6' => 1, + 'fluormat7' => 1, + 'fluormat8' => 1, + 'fluormat9' => 1, + 'flushtiming' => 1, + 'focalinfo' => 1, + 'focallength35efl' => 1, + 'focallength35mm' => 1, + 'focalplanecolorimetryestimates' => 1, + 'focalrange' => 1, + 'focusdistance2' => 1, + 'focusedgemap' => 1, + 'focusinfo' => 1, + 'focusinfoifd' => 1, + 'focuspos' => 1, + 'focussettings' => 1, + 'folder' => 1, + 'folderpath' => 1, + 'font' => 1, + 'fontsize' => 1, + 'fontsubfamily' => 1, + 'fontsubfamilyid' => 1, + 'fonttable' => 1, + 'fontweight' => 1, + 'footerposition' => 1, + 'footnotes' => 1, + 'form' => 1, + 'formattag' => 1, + 'formatter' => 1, + 'formatversion' => 1, + 'formatversiontime' => 1, + 'formextrausagerights' => 1, + 'formfields' => 1, + 'formusagerights' => 1, + 'forwardto' => 1, + 'fotostation' => 1, + 'fourcc' => 1, + 'fourcc1' => 1, + 'fourcc2' => 1, + 'fourcc2len' => 1, + 'fourcc3' => 1, + 'fourcc3len' => 1, + 'fourthlanguage' => 1, + 'fov' => 1, + 'fovcot' => 1, + 'fpfversion' => 1, + 'fpv' => 1, + 'fpxr' => 1, + 'fractalparameters' => 1, + 'fragmentlist' => 1, + 'fragmenttable' => 1, + 'frame' => 1, + 'frameexposuretime' => 1, + 'frameid' => 1, + 'frameinfo' => 1, + 'framepriority' => 1, + 'framereadouttime' => 1, + 'framesize' => 1, + 'framesizemax' => 1, + 'framesizemin' => 1, + 'framespersecond' => 1, + 'free' => 1, + 'free-busystatus' => 1, + 'freebytecounts' => 1, + 'freeoffsets' => 1, + 'frequency' => 1, + 'fromaddresses' => 1, + 'fromnames' => 1, + 'fstype' => 1, + 'fujifilm' => 1, + 'fujifilmffmv' => 1, + 'fujifilmmvtg' => 1, + 'fujifilmtags' => 1, + 'fujiifd' => 1, + 'fujilayout' => 1, + 'fullname' => 1, + 'fullscreen' => 1, + 'gain' => 1, + 'gaindeaddata' => 1, + 'gaindeadmapimage' => 1, + 'gaindeadmapimageheight' => 1, + 'gaindeadmapimagetype' => 1, + 'gaindeadmapimagewidth' => 1, + 'gammablue' => 1, + 'gammagreen' => 1, + 'gammainfo' => 1, + 'gammared' => 1, + 'gammatable' => 1, + 'gamut' => 1, + 'gapless' => 1, + 'gaudio' => 1, + 'gaussianweights' => 1, + 'gdalmetadata' => 1, + 'gdalnodata' => 1, + 'gdepth' => 1, + 'geminfo' => 1, + 'genbalance' => 1, + 'gender' => 1, + 'generator' => 1, + 'generatorversion' => 1, + 'genflags' => 1, + 'gengraphicsmode' => 1, + 'genmediaheader' => 1, + 'genmediainfo' => 1, + 'genmediaversion' => 1, + 'genopcolor' => 1, + 'genr' => 1, + 'genreid' => 1, + 'geo' => 1, + 'geogangularunits' => 1, + 'geogangularunitsize' => 1, + 'geogazimuthunits' => 1, + 'geogcitation' => 1, + 'geogellipsoid' => 1, + 'geoggeodeticdatum' => 1, + 'geoginvflattening' => 1, + 'geoglinearunits' => 1, + 'geoglinearunitsize' => 1, + 'geogprimemeridian' => 1, + 'geogprimemeridianlong' => 1, + 'geographictype' => 1, + 'geogsemimajoraxis' => 1, + 'geogsemiminoraxis' => 1, + 'geogtowgs84' => 1, + 'geometricdistortionparams' => 1, + 'geotiffversion' => 1, + 'getty' => 1, + 'gfocus' => 1, + 'gidcver' => 1, + 'gidpver' => 1, + 'gifapplicationextension' => 1, + 'gifgraphiccontrolextension' => 1, + 'gifplaintextextension' => 1, + 'gifversion' => 1, + 'gimage' => 1, + 'gimbalpitch' => 1, + 'gimbalroll' => 1, + 'gimbalyaw' => 1, + 'gipc_cpld' => 1, + 'gipcver' => 1, + 'givenname' => 1, + 'gixiver' => 1, + 'globalinfo' => 1, + 'globalparametersifd' => 1, + 'globalpixelsize' => 1, + 'googlebot' => 1, + 'googlehostheader' => 1, + 'googlepingmessage' => 1, + 'googlepingurl' => 1, + 'googlesourcedata' => 1, + 'googlestarttime' => 1, + 'googletrackduration' => 1, + 'gopro' => 1, + 'goprogpmf' => 1, + 'goprotype' => 1, + 'gpano' => 1, + 'gpmd' => 1, + 'gps' => 1, + 'gpsaltituderaw' => 1, + 'gpscoordinates' => 1, + 'gpsdatalist' => 1, + 'gpsdatetimeraw' => 1, + 'gpshorizontalaccuracy' => 1, + 'gpsinfo' => 1, + 'gpslatituderaw' => 1, + 'gpslog' => 1, + 'gpslongituderaw' => 1, + 'gpspos' => 1, + 'gpsposition' => 1, + 'gpsraw' => 1, + 'gpsspeed3d' => 1, + 'gpsspeedaccuracy' => 1, + 'gpsspeedraw' => 1, + 'gpsspeedx' => 1, + 'gpsspeedy' => 1, + 'gpsspeedz' => 1, + 'gpstrackraw' => 1, + 'gpsvalid' => 1, + 'gpsvelocityeast' => 1, + 'gpsvelocitynorth' => 1, + 'gpsvelocityup' => 1, + 'gpsverticalaccuracy' => 1, + 'grainybwfilter' => 1, + 'graphicconverter' => 1, + 'graphicsmode' => 1, + 'graphicstechnologystandardoutput' => 1, + 'grayresponsecurve' => 1, + 'graytrc' => 1, + 'greenadjust' => 1, + 'greenendpoint' => 1, + 'greengain' => 1, + 'greenmask' => 1, + 'greenmatrixcolumn' => 1, + 'greenprimary' => 1, + 'greensample' => 1, + 'greentrc' => 1, + 'greenx' => 1, + 'greeny' => 1, + 'gridguidesinfo' => 1, + 'group' => 1, + 'groupcaption' => 1, + 'grouping' => 1, + 'groupmutualexclusion' => 1, + 'gsensor' => 1, + 'gspherical' => 1, + 'gtcitation' => 1, + 'gtmodeltype' => 1, + 'gtrastertype' => 1, + 'guid' => 1, + 'gyroscope' => 1, + 'handler' => 1, + 'handlerclass' => 1, + 'handlerdescription' => 1, + 'handlertype' => 1, + 'handlervendorid' => 1, + 'hardpostpadding' => 1, + 'hardprepadding' => 1, + 'hasarbitrarydatastream' => 1, + 'hasattachedimages' => 1, + 'hasattachments' => 1, + 'hasaudio' => 1, + 'hascolormap' => 1, + 'hascuepoints' => 1, + 'hasfiletransferstream' => 1, + 'hasflag' => 1, + 'hasicc' => 1, + 'hasimage' => 1, + 'haskeyframes' => 1, + 'hasmetadata' => 1, + 'hasrealmergeddata' => 1, + 'hasscript' => 1, + 'hasvideo' => 1, + 'hasxfa' => 1, + 'hcusage' => 1, + 'hdcontent' => 1, + 'hdrinfo' => 1, + 'hdrl' => 1, + 'hdrtoninginfo' => 1, + 'hdvideo' => 1, + 'header' => 1, + 'header4' => 1, + 'headerext' => 1, + 'headerextension' => 1, + 'headersize' => 1, + 'headerversion' => 1, + 'headingpairs' => 1, + 'heightresolution' => 1, + 'hevcconfiguration' => 1, + 'hiddenslides' => 1, + 'highisomode' => 1, + 'highlightdata' => 1, + 'highlightendpoints' => 1, + 'hintformat' => 1, + 'hintheader' => 1, + 'hintinfo' => 1, + 'hintsampledesc' => 1, + 'hinttrackinfo' => 1, + 'hinttrackversion' => 1, + 'hintversion' => 1, + 'histogram' => 1, + 'historybuffersize' => 1, + 'hmaphandling' => 1, + 'hmcolrejthresh' => 1, + 'hmcolthresh' => 1, + 'hmpixthresh' => 1, + 'hmwsize' => 1, + 'hobbies' => 1, + 'homeaddress' => 1, + 'homecity' => 1, + 'homecountry-region' => 1, + 'homefax' => 1, + 'homephone' => 1, + 'homepobox' => 1, + 'homepostalcode' => 1, + 'homestateorprovince' => 1, + 'homestreet' => 1, + 'horizontalresolution' => 1, + 'horizontalscale' => 1, + 'hostsoftwareexportversion' => 1, + 'hotkey' => 1, + 'howpublished' => 1, + 'hp_tdhd' => 1, + 'hrnoiselines' => 1, + 'htcbinary' => 1, + 'htcinfo' => 1, + 'htctrack' => 1, + 'http-equiv' => 1, + 'httphostheader' => 1, + 'huffmantable' => 1, + 'huffmantablelength' => 1, + 'huffmantablevalue' => 1, + 'hyperfocaldistance' => 1, + 'hyperlinkbase' => 1, + 'hyperlinks' => 1, + 'hyperlinkschanged' => 1, + 'icc_untagged' => 1, + 'iccbased' => 1, + 'iconenvdata' => 1, + 'iconfilename' => 1, + 'iconindex' => 1, + 'iconuri' => 1, + 'ics' => 1, + 'id' => 1, + 'id3' => 1, + 'id3size' => 1, + 'id3v1' => 1, + 'id3v1_enh' => 1, + 'id3v2_2' => 1, + 'id3v2_3' => 1, + 'id3v2_4' => 1, + 'idc2_ifd' => 1, + 'idc_ifd' => 1, + 'idcpreviewimage' => 1, + 'idependentanddisposablesamples' => 1, + 'idlesequence' => 1, + 'idletiming' => 1, + 'idsbasevalue' => 1, + 'ifd0' => 1, + 'ifd0_offset' => 1, + 'ihl_exif' => 1, + 'ihldata' => 1, + 'illuminantdetectordata' => 1, + 'illuminantdetecttable' => 1, + 'illustrator' => 1, + 'im' => 1, + 'imaddresses' => 1, + 'image' => 1, + 'image2description' => 1, + 'image3description' => 1, + 'image4description' => 1, + 'image5description' => 1, + 'image6description' => 1, + 'image7description' => 1, + 'image8description' => 1, + 'imagearrangement' => 1, + 'imageboardid' => 1, + 'imagebounds' => 1, + 'imagebytecount' => 1, + 'imageclass' => 1, + 'imagecolor' => 1, + 'imagecolorindicator' => 1, + 'imagecolorvalue' => 1, + 'imagecompressiontable' => 1, + 'imagedatadiscard' => 1, + 'imagedataoffset' => 1, + 'imagedepth' => 1, + 'imageelements' => 1, + 'imageexpansiontable' => 1, + 'imagefields' => 1, + 'imagefilecharacteristics' => 1, + 'imagefilename' => 1, + 'imageformat' => 1, + 'imagefullheight' => 1, + 'imagefullwidth' => 1, + 'imageheader' => 1, + 'imageid' => 1, + 'imageinfo' => 1, + 'imagelayer' => 1, + 'imagelength' => 1, + 'imagelimitexposurebias' => 1, + 'imagemagnificationdescriptor' => 1, + 'imagemedium' => 1, + 'imagemodulationexposurebias' => 1, + 'imageoffset' => 1, + 'imagepixeldepth' => 1, + 'imagepixelformat' => 1, + 'imageprintstatus' => 1, + 'imageprocessingifd' => 1, + 'imageprofile' => 1, + 'imageprops' => 1, + 'imagerboardid' => 1, + 'imagereadydatasets' => 1, + 'imagereadyvariables' => 1, + 'imagereferencepoints' => 1, + 'imageresources' => 1, + 'imagerinitialtimingcode' => 1, + 'imagerlogicprogram' => 1, + 'imagerotated' => 1, + 'imagerotation' => 1, + 'imagerotationstatus' => 1, + 'imagertimingdata' => 1, + 'imagesensorgain' => 1, + 'imagesourceek' => 1, + 'imagespatialextent' => 1, + 'imagestatus' => 1, + 'imagetoolbar' => 1, + 'imageuidlist' => 1, + 'imageversion' => 1, + 'imageworkstationmake' => 1, + 'imgprofbacktype' => 1, + 'imgprofname' => 1, + 'imgproftype' => 1, + 'imgprofversion' => 1, + 'immediatedatabytes' => 1, + 'importance' => 1, + 'imprint' => 1, + 'inbandratingattributes' => 1, + 'inbandratinglevel' => 1, + 'inbandratingsystem' => 1, + 'includedfileid' => 1, + 'incomplete' => 1, + 'index' => 1, + 'index01' => 1, + 'index02' => 1, + 'index03' => 1, + 'index04' => 1, + 'index05' => 1, + 'index06' => 1, + 'index07' => 1, + 'index08' => 1, + 'index09' => 1, + 'index10' => 1, + 'index11' => 1, + 'index12' => 1, + 'index13' => 1, + 'index14' => 1, + 'index15' => 1, + 'index16' => 1, + 'indexable' => 1, + 'indexed' => 1, + 'indexedcolortablecount' => 1, + 'indexoffset' => 1, + 'indexparameters' => 1, + 'info' => 1, + 'information' => 1, + 'infourl' => 1, + 'ingrreserved' => 1, + 'initialdisplayeffect' => 1, + 'initializationvector' => 1, + 'initializeddatasize' => 1, + 'initialkey' => 1, + 'initialobjectdescriptor' => 1, + 'initials' => 1, + 'inknames' => 1, + 'inputdataobjectlist' => 1, + 'inputdevicename' => 1, + 'inputdeviceserialnumber' => 1, + 'insertmode' => 1, + 'insetnwpixelx' => 1, + 'insetnwpixely' => 1, + 'institution' => 1, + 'instructionset' => 1, + 'insv' => 1, + 'integratetiming' => 1, + 'intellectualproperty' => 1, + 'intellectualpropertynotes' => 1, + 'intensitystereo' => 1, + 'intergraphflagregisters' => 1, + 'intergraphpacketdata' => 1, + 'interlace' => 1, + 'interleavedfield' => 1, + 'internalidnumber' => 1, + 'internalleading' => 1, + 'internalname' => 1, + 'internalversionnumber' => 1, + 'internationaltext' => 1, + 'internetradiostationname' => 1, + 'internetradiostationowner' => 1, + 'internetradiostationurl' => 1, + 'interopoffset' => 1, + 'interpolationcoefficients' => 1, + 'interpolationcoefficients3mp' => 1, + 'interpolationcoefficients6mp' => 1, + 'interpretedby' => 1, + 'inversemonitormatrix' => 1, + 'inverserimnonlinearity' => 1, + 'inversesbalog12transform' => 1, + 'inversesbalogtransform' => 1, + 'invnifnonlinearity' => 1, + 'involvedpeople' => 1, + 'ipmpcontrol' => 1, + 'iptc_profile' => 1, + 'iptcapplication' => 1, + 'iptccore' => 1, + 'iptcdata' => 1, + 'iptcenvelope' => 1, + 'iptcext' => 1, + 'iptcfotostation' => 1, + 'iptcnewsphoto' => 1, + 'iptcobjectdata' => 1, + 'iptcpostobjectdata' => 1, + 'iptcpreobjectdata' => 1, + 'irwindowtemperature' => 1, + 'irwindowtransmission' => 1, + 'is_protected' => 1, + 'is_trusted' => 1, + 'isattachment' => 1, + 'isbasefont' => 1, + 'iscompleted' => 1, + 'isdeleted' => 1, + 'isfixedpitch' => 1, + 'isfixedv' => 1, + 'isinfoa100' => 1, + 'isnetworkfeed' => 1, + 'isocalibrationgaintable' => 1, + 'isoinfo' => 1, + 'isonline' => 1, + 'isospeeds' => 1, + 'isotherm1color' => 1, + 'isotherm2color' => 1, + 'isprotected' => 1, + 'isrc' => 1, + 'isrccode' => 1, + 'isrcnumber' => 1, + 'isrecurring' => 1, + 'isvbr' => 1, + 'it8header' => 1, + 'italic' => 1, + 'italicangle' => 1, + 'itch' => 1, + 'item' => 1, + 'item0032' => 1, + 'itemid' => 1, + 'iteminfoentry' => 1, + 'iteminformation' => 1, + 'itemlist' => 1, + 'itemlocation' => 1, + 'itemproperties' => 1, + 'itempropertyassociation' => 1, + 'itempropertycontainer' => 1, + 'itemprotection' => 1, + 'itemreference' => 1, + 'itemtool' => 1, + 'itemvendorid' => 1, + 'iterationcount' => 1, + 'iterationendaction' => 1, + 'iterationmax' => 1, + 'iterationminmax' => 1, + 'iterations' => 1, + 'itunesinfo' => 1, + 'itunesmediatype' => 1, + 'itunesu' => 1, + 'itunmovi' => 1, + 'itunsmpb' => 1, + 'ituntool' => 1, + 'jbigoptions' => 1, + 'jfif' => 1, + 'jfifversion' => 1, + 'jfxx' => 1, + 'jngheader' => 1, + 'jobtitle' => 1, + 'journal' => 1, + 'jp2header' => 1, + 'jp2signature' => 1, + 'jpeg-hdr' => 1, + 'jpeg-hdrversion' => 1, + 'jpeg-likedata' => 1, + 'jpeg_quality' => 1, + 'jpegactables' => 1, + 'jpegdctables' => 1, + 'jpegdigest' => 1, + 'jpegexifdata' => 1, + 'jpeginfo' => 1, + 'jpeglosslesspredictors' => 1, + 'jpegpointtransforms' => 1, + 'jpegproc' => 1, + 'jpegprocess' => 1, + 'jpegqtablebest' => 1, + 'jpegqtablebetter' => 1, + 'jpegqtablegood' => 1, + 'jpegqtables' => 1, + 'jpegqualityestimate' => 1, + 'jpegrestartinterval' => 1, + 'jpegtables' => 1, + 'jpginfooffset' => 1, + 'jplcartoifd' => 1, + 'jsonmetadata' => 1, + 'jumptoxpep' => 1, + 'junk' => 1, + 'kbytesize' => 1, + 'kdc_ifd' => 1, + 'keepuntil' => 1, + 'kelvinwb' => 1, + 'keycode' => 1, + 'keyframepositions' => 1, + 'keyframestimes' => 1, + 'keyid' => 1, + 'keys' => 1, + 'kf8coveruri' => 1, + 'khufui0thresholds' => 1, + 'khufui1thresholds' => 1, + 'khufui2thresholds' => 1, + 'khufui3thresholds' => 1, + 'khufui4thresholds' => 1, + 'khufui5thresholds' => 1, + 'khufulinearbluemixingcoefficient' => 1, + 'khufulineargreenmixingcoefficient' => 1, + 'khufulinearredmixingcoefficient' => 1, + 'khufusigmagaussianweights' => 1, + 'khufusigmascalingfactors14mp' => 1, + 'khufusigmascalingfactors3mp' => 1, + 'khufusigmascalingfactors6mp' => 1, + 'khufuuspacec2mixingcoefficient' => 1, + 'kids' => 1, + 'kinds' => 1, + 'klut' => 1, + 'klut12tolin12' => 1, + 'knownfolderdata' => 1, + 'kodak' => 1, + 'kodak_frea' => 1, + 'kodakbordersifd' => 1, + 'kodakdcmd' => 1, + 'kodakeffectsifd' => 1, + 'kodakfree' => 1, + 'kodakifd' => 1, + 'kodakmake' => 1, + 'kodaktags' => 1, + 'konicaminolta' => 1, + 'konicaminoltatags' => 1, + 'label0' => 1, + 'label1' => 1, + 'label2' => 1, + 'label3' => 1, + 'labelid' => 1, + 'labeltext' => 1, + 'lamebitrate' => 1, + 'lameheader' => 1, + 'lamelowpassfilter' => 1, + 'lamemethod' => 1, + 'lamequality' => 1, + 'lamestereomode' => 1, + 'lamevbrquality' => 1, + 'languagecode' => 1, + 'languagelist' => 1, + 'largestpacketduration' => 1, + 'largestpacketsize' => 1, + 'lastauthor' => 1, + 'lastbackupdate' => 1, + 'lastchar' => 1, + 'lastkeyframetime' => 1, + 'lastmodifiedby' => 1, + 'lastmodifier' => 1, + 'lastname' => 1, + 'lastobject' => 1, + 'lastobjectid' => 1, + 'lastprinted' => 1, + 'lastsavedby' => 1, + 'lasttimestamp' => 1, + 'lastupdate' => 1, + 'lastupdatetime' => 1, + 'layerblendmodes' => 1, + 'layercomps' => 1, + 'layercount' => 1, + 'layergroupsenabledid' => 1, + 'layerids' => 1, + 'layermodifydates' => 1, + 'layernames' => 1, + 'layeropacities' => 1, + 'layerrectangles' => 1, + 'layers' => 1, + 'layerselectionids' => 1, + 'layersgroupinfo' => 1, + 'layerunicodenames' => 1, + 'layout' => 1, + 'layoutflags' => 1, + 'lcdedgemapslope' => 1, + 'lcdedgemapx1' => 1, + 'lcdedgemapx2' => 1, + 'lcdedgemapx3' => 1, + 'lcdedgemapx4' => 1, + 'lcdedgespline' => 1, + 'lcdgammatable' => 1, + 'lcdgammatablechickfix' => 1, + 'lcdgammatablemarvin' => 1, + 'lcdhistlut0' => 1, + 'lcdhistlut1' => 1, + 'lcdhistlut2' => 1, + 'lcdhistlut3' => 1, + 'lcdhistlut4' => 1, + 'lcdhistlut5' => 1, + 'lcdhistlut6' => 1, + 'lcdhistlut7' => 1, + 'lcdhistlut8' => 1, + 'lcdhistlut9' => 1, + 'lcdlinearclipvalue' => 1, + 'lcdsharpeningf1' => 1, + 'lcdsharpeningf2' => 1, + 'lcdsharpeningf3' => 1, + 'lcdsharpeningf4' => 1, + 'lcdstepyvalues' => 1, + 'lcdstepyvalueschickfix' => 1, + 'lcdstepyvaluesmarvin' => 1, + 'leadperformer' => 1, + 'leafautoactive' => 1, + 'leafautobasename' => 1, + 'leafdata' => 1, + 'leafhotfolder' => 1, + 'leafopenprochdr' => 1, + 'leafoutputfiletype' => 1, + 'leafsaveselection' => 1, + 'leafsubifd' => 1, + 'leftdarkcol1' => 1, + 'leftdarkcol2' => 1, + 'leftdarkrect' => 1, + 'leftmag' => 1, + 'leftmargin' => 1, + 'legalcopyright' => 1, + 'legaltrademarks' => 1, + 'leicaleic' => 1, + 'length' => 1, + 'lens35efl' => 1, + 'lensattached' => 1, + 'lenscorr' => 1, + 'lensdata' => 1, + 'lensdata0100' => 1, + 'lensdata0101' => 1, + 'lensdata0201' => 1, + 'lensdata0204' => 1, + 'lensdata0400' => 1, + 'lensdata0402' => 1, + 'lensdata0403' => 1, + 'lensdata0800' => 1, + 'lensdataunknown' => 1, + 'lensdataversion' => 1, + 'lensinfoq' => 1, + 'lensmaker' => 1, + 'lensnumber' => 1, + 'lenspartnumber' => 1, + 'lensrec' => 1, + 'lensshading' => 1, + 'lenstableindex' => 1, + 'levelinfo' => 1, + 'levelmeter' => 1, + 'libraryid' => 1, + 'libraryname' => 1, + 'licenseinfourl' => 1, + 'lightingopt' => 1, + 'lightness' => 1, + 'lightroomworkflow' => 1, + 'lights' => 1, + 'lightvalue' => 1, + 'limage' => 1, + 'lin12toklut12' => 1, + 'lin12toklut8' => 1, + 'linearitysplinetags' => 1, + 'linearizationcoefficients1' => 1, + 'linearizationcoefficients2' => 1, + 'linearized' => 1, + 'lineorder' => 1, + 'lines' => 1, + 'linkedprofilename' => 1, + 'linkerversion' => 1, + 'linkinfo' => 1, + 'linkstatus' => 1, + 'linksuptodate' => 1, + 'linktarget' => 1, + 'linlogtable' => 1, + 'listtype' => 1, + 'lit' => 1, + 'ln0' => 1, + 'ln1' => 1, + 'localbasepath' => 1, + 'localdeltatype' => 1, + 'localeindicator' => 1, + 'localpositionned' => 1, + 'locationbody' => 1, + 'locationdate' => 1, + 'locationinfo' => 1, + 'locationinformation' => 1, + 'locationnote' => 1, + 'locationrole' => 1, + 'lockedpropertylist' => 1, + 'locks' => 1, + 'loglintable' => 1, + 'logoiconurl' => 1, + 'logourl' => 1, + 'longdescription' => 1, + 'lookheadbacktype' => 1, + 'lookheader' => 1, + 'lookheadname' => 1, + 'lookheadtype' => 1, + 'lookheadversion' => 1, + 'lookmat0' => 1, + 'lookmat1' => 1, + 'lookmat2' => 1, + 'lookmat3' => 1, + 'lookmat4' => 1, + 'lookmat5' => 1, + 'lookmat6' => 1, + 'lookmat7' => 1, + 'lookmat8' => 1, + 'lookmat9' => 1, + 'lookmodtransform' => 1, + 'lookuptable' => 1, + 'loopstyle' => 1, + 'lotus' => 1, + 'lr' => 1, + 'lslv' => 1, + 'luminance' => 1, + 'luminanceconsts' => 1, + 'lyricist' => 1, + 'lyrics_synchronised' => 1, + 'lyricsuri' => 1, + 'machineid' => 1, + 'machinetype' => 1, + 'macintoshnsprintinfo' => 1, + 'macintoshprintinfo' => 1, + 'magneticfield' => 1, + 'magnetometer' => 1, + 'magnification' => 1, + 'magnifyobject' => 1, + 'mailingaddress' => 1, + 'mailstop' => 1, + 'mainboard' => 1, + 'maininfo' => 1, + 'maininfoifd' => 1, + 'majorbrand' => 1, + 'makeandmodel' => 1, + 'makemodel' => 1, + 'makernotepentax5a' => 1, + 'makernotepentax5b' => 1, + 'makernotepentax5c' => 1, + 'makernotepentaxunknown' => 1, + 'makernotes' => 1, + 'makerurl' => 1, + 'mandatorybackground' => 1, + 'manufacturecode' => 1, + 'manufactureindex' => 1, + 'manufacturername' => 1, + 'mappingscheme' => 1, + 'mapscale' => 1, + 'mariahthresholds' => 1, + 'mariahthresholdslow' => 1, + 'mariahthresholdsnormal' => 1, + 'mariahthresholdsstrong' => 1, + 'markbits' => 1, + 'marker' => 1, + 'markerid' => 1, + 'markinfo' => 1, + 'matrixworldtocamera' => 1, + 'matrixworldtoscreen' => 1, + 'mattcolor' => 1, + 'matte' => 1, + 'matteing' => 1, + 'matter' => 1, + 'maxband' => 1, + 'maxbitrate' => 1, + 'maxdatarate' => 1, + 'maximumbitrate' => 1, + 'maximumimageindex' => 1, + 'maximumobjectsize' => 1, + 'maximumoperationindex' => 1, + 'maximumtransformindex' => 1, + 'maxjpegtableindex' => 1, + 'maxpacketsize' => 1, + 'maxpagenormal' => 1, + 'maxpdusize' => 1, + 'maxsubfilesize' => 1, + 'maxtransmissiontime' => 1, + 'maxval' => 1, + 'maxwidth' => 1, + 'mc' => 1, + 'mcdi' => 1, + 'md5signature' => 1, + 'md5sum' => 1, + 'mdcolortable' => 1, + 'mdfiletag' => 1, + 'mdfileunits' => 1, + 'mditemaccounthandles' => 1, + 'mditemaccountidentifier' => 1, + 'mditemacquisitionmake' => 1, + 'mditemacquisitionmodel' => 1, + 'mditemaltitude' => 1, + 'mditemaperture' => 1, + 'mditemauthoremailaddresses' => 1, + 'mditemauthors' => 1, + 'mditembitspersample' => 1, + 'mditembundleidentifier' => 1, + 'mditemcity' => 1, + 'mditemcolorspace' => 1, + 'mditemcomment' => 1, + 'mditemcontentcreationdate' => 1, + 'mditemcontentcreationdate_ranking' => 1, + 'mditemcontentmodificationdate' => 1, + 'mditemcontenttype' => 1, + 'mditemcontenttypetree' => 1, + 'mditemcontributors' => 1, + 'mditemcopyright' => 1, + 'mditemcountry' => 1, + 'mditemcreator' => 1, + 'mditemdateadded' => 1, + 'mditemdateadded_ranking' => 1, + 'mditemdescription' => 1, + 'mditemdisplayname' => 1, + 'mditemdownloadeddate' => 1, + 'mditememailconversationid' => 1, + 'mditemencodingapplications' => 1, + 'mditemexifgpsversion' => 1, + 'mditemexifversion' => 1, + 'mditemexposuremode' => 1, + 'mditemexposureprogram' => 1, + 'mditemexposuretimeseconds' => 1, + 'mditemflashonoff' => 1, + 'mditemfnumber' => 1, + 'mditemfocallength' => 1, + 'mditemfscontentchangedate' => 1, + 'mditemfscreatorcode' => 1, + 'mditemfsfinderflags' => 1, + 'mditemfshascustomicon' => 1, + 'mditemfsinvisible' => 1, + 'mditemfsisextensionhidden' => 1, + 'mditemfsisstationery' => 1, + 'mditemfsname' => 1, + 'mditemfsnodecount' => 1, + 'mditemfsownergroupid' => 1, + 'mditemfsowneruserid' => 1, + 'mditemfssize' => 1, + 'mditemfstypecode' => 1, + 'mditemgpsdatestamp' => 1, + 'mditemgpsstatus' => 1, + 'mditemgpstrack' => 1, + 'mditemhasalphachannel' => 1, + 'mditemidentifier' => 1, + 'mditemimagedirection' => 1, + 'mditeminterestingdate_ranking' => 1, + 'mditemisapplicationmanaged' => 1, + 'mditemisexistingthread' => 1, + 'mditemislikelyjunk' => 1, + 'mditemisospeed' => 1, + 'mditemkeywords' => 1, + 'mditemkind' => 1, + 'mditemlastuseddate' => 1, + 'mditemlatitude' => 1, + 'mditemlogicalsize' => 1, + 'mditemlongitude' => 1, + 'mditemmailboxes' => 1, + 'mditemmaildatereceived_ranking' => 1, + 'mditemnumberofpages' => 1, + 'mditemorientation' => 1, + 'mditemoriginapplicationidentifier' => 1, + 'mditemoriginmessageid' => 1, + 'mditemoriginsenderdisplayname' => 1, + 'mditemoriginsenderhandle' => 1, + 'mditemoriginsubject' => 1, + 'mditempageheight' => 1, + 'mditempagewidth' => 1, + 'mditemphysicalsize' => 1, + 'mditempixelcount' => 1, + 'mditempixelheight' => 1, + 'mditempixelwidth' => 1, + 'mditemprimaryrecipientemailaddresses' => 1, + 'mditemprofilename' => 1, + 'mditemrecipients' => 1, + 'mditemredeyeonoff' => 1, + 'mditemresolutionheightdpi' => 1, + 'mditemresolutionwidthdpi' => 1, + 'mditemsecuritymethod' => 1, + 'mditemspeed' => 1, + 'mditemstateorprovince' => 1, + 'mditemsubject' => 1, + 'mditemtimestamp' => 1, + 'mditemtitle' => 1, + 'mditemusecount' => 1, + 'mditemuseddates' => 1, + 'mditemversion' => 1, + 'mditemwherefroms' => 1, + 'mditemwhitebalance' => 1, + 'mdlabname' => 1, + 'mdpm' => 1, + 'mdpr' => 1, + 'mdprepdate' => 1, + 'mdpreptime' => 1, + 'mdsampleinfo' => 1, + 'mdscalepixel' => 1, + 'meas1label' => 1, + 'meas1params' => 1, + 'meas1type' => 1, + 'measuredcolor' => 1, + 'measuredinfo' => 1, + 'measurement' => 1, + 'measurementbacking' => 1, + 'measurementflare' => 1, + 'measurementgeometry' => 1, + 'measurementilluminant' => 1, + 'measurementinfo' => 1, + 'measurementobserver' => 1, + 'measurementscale' => 1, + 'mebx' => 1, + 'media' => 1, + 'mediablackpoint' => 1, + 'mediaclassprimaryid' => 1, + 'mediaclasssecondaryid' => 1, + 'mediacolor' => 1, + 'mediacontenttypes' => 1, + 'mediacreated' => 1, + 'mediacredits' => 1, + 'mediadata' => 1, + 'mediaduration' => 1, + 'mediaflags' => 1, + 'mediaheader' => 1, + 'mediaheaderversion' => 1, + 'mediaindex' => 1, + 'mediainfo' => 1, + 'mediaisdelay' => 1, + 'mediaisfinale' => 1, + 'mediaislive' => 1, + 'mediaismovie' => 1, + 'mediaispremiere' => 1, + 'mediaisrepeat' => 1, + 'mediaissap' => 1, + 'mediaissport' => 1, + 'mediaisstereo' => 1, + 'mediaissubtitled' => 1, + 'mediaistape' => 1, + 'mediajukebox' => 1, + 'medialanguagecode' => 1, + 'medianetworkaffiliation' => 1, + 'mediaoriginalbroadcastdatetime' => 1, + 'mediaoriginalchannel' => 1, + 'mediaoriginalchannelsubnumber' => 1, + 'mediaoriginalruntime' => 1, + 'mediapro' => 1, + 'mediastationcallsign' => 1, + 'mediastationname' => 1, + 'mediathumbaspectratiox' => 1, + 'mediathumbaspectratioy' => 1, + 'mediathumbheight' => 1, + 'mediathumbratingattributes' => 1, + 'mediathumbratinglevel' => 1, + 'mediathumbratingsystem' => 1, + 'mediathumbret' => 1, + 'mediathumbstride' => 1, + 'mediathumbtimestamp' => 1, + 'mediathumbwidth' => 1, + 'mediatimescale' => 1, + 'mediatrackbytes' => 1, + 'mediatype' => 1, + 'mediaweight' => 1, + 'mediawhitepoint' => 1, + 'medium' => 1, + 'megapixels' => 1, + 'melodicpolyphony' => 1, + 'message' => 1, + 'meta' => 1, + 'metadata' => 1, + 'metadatacreator' => 1, + 'metadataid' => 1, + 'metadatalibrary' => 1, + 'metadatanumber' => 1, + 'metadatasource' => 1, + 'metaformat' => 1, + 'metasampledesc' => 1, + 'metdata' => 1, + 'meterinfo' => 1, + 'meterlink' => 1, + 'metermode' => 1, + 'microsoft' => 1, + 'microsoftxtra' => 1, + 'middlename' => 1, + 'midicontrol' => 1, + 'midicontrolversion' => 1, + 'midisong' => 1, + 'mie' => 1, + 'mileage' => 1, + 'mimetype' => 1, + 'miniaturefilter' => 1, + 'miniaturefilterorientation' => 1, + 'miniaturefilterparameter' => 1, + 'miniaturefilterposition' => 1, + 'minimumbitrate' => 1, + 'minimumflushrows' => 1, + 'minimumversion' => 1, + 'minoltacamerasettings' => 1, + 'minoltacamerasettings2' => 1, + 'minoltacamerasettings5d' => 1, + 'minoltacamerasettings7d' => 1, + 'minoltacamerasettingsold' => 1, + 'minoltamakernote' => 1, + 'minoltamma0' => 1, + 'minoltamma1' => 1, + 'minoltaprd' => 1, + 'minoltarif' => 1, + 'minoltatags' => 1, + 'minoltattw' => 1, + 'minoltawbg' => 1, + 'minpacketsize' => 1, + 'mintransmissiontime' => 1, + 'mmclips' => 1, + 'mngheader' => 1, + 'mobitype' => 1, + 'mobiversion' => 1, + 'modeextension' => 1, + 'modeflags' => 1, + 'model2' => 1, + 'modelandversion' => 1, + 'modeltype' => 1, + 'modenumber' => 1, + 'modificationnumber' => 1, + 'modificationpermissions' => 1, + 'modifiedby' => 1, + 'modifiedinfo' => 1, + 'moiversion' => 1, + 'monomonitormatrix' => 1, + 'monotonescaletable' => 1, + 'monouniquematrix' => 1, + 'montage' => 1, + 'month' => 1, + 'mood' => 1, + 'moreinfo' => 1, + 'moreinfo0201' => 1, + 'moreinfo0401' => 1, + 'moreinfobannerimage' => 1, + 'moreinfobannerurl' => 1, + 'moreinfotext' => 1, + 'moreinfourl' => 1, + 'moresettings' => 1, + 'mosaicpattern' => 1, + 'movableinfo' => 1, + 'moveobjects' => 1, + 'movie' => 1, + 'moviedata' => 1, + 'moviedataoffset' => 1, + 'moviedatasize' => 1, + 'moviefragment' => 1, + 'movieheader' => 1, + 'movieheaderversion' => 1, + 'movieinfo' => 1, + 'moviestreamname' => 1, + 'mp' => 1, + 'mp1' => 1, + 'mpeg7binary' => 1, + 'mpegaudioversion' => 1, + 'mpf' => 1, + 'mpfversion' => 1, + 'mpimage' => 1, + 'mpimageflags' => 1, + 'mpimageformat' => 1, + 'mpimagelength' => 1, + 'mpimagelist' => 1, + 'mpimagestart' => 1, + 'mpimagetype' => 1, + 'mpindividualnum' => 1, + 'mrwinfo' => 1, + 'msdocumenttext' => 1, + 'msdocumenttextposition' => 1, + 'mspropertysetstorage' => 1, + 'msstereo' => 1, + 'multiexp' => 1, + 'multiexposureversion' => 1, + 'multimediatype' => 1, + 'multiprofiles' => 1, + 'multiquality' => 1, + 'multishoton' => 1, + 'multiview' => 1, + 'musicby' => 1, + 'musiccdidentifier' => 1, + 'musiciancredits' => 1, + 'mute' => 1, + 'mwg-coll' => 1, + 'mwg-kw' => 1, + 'mwg-rs' => 1, + 'mxfversion' => 1, + 'mycolors' => 1, + 'name' => 1, + 'namedcolor' => 1, + 'namedcolor2' => 1, + 'nametableversion' => 1, + 'nameutf-8' => 1, + 'narrator' => 1, + 'nativedisplayinfo' => 1, + 'nativeresolutionunit' => 1, + 'nativexresolution' => 1, + 'nativeyresolution' => 1, + 'ncc' => 1, + 'nemoblurkernel' => 1, + 'nemodarklimit' => 1, + 'nemogainfactors' => 1, + 'nemohighlight12limit' => 1, + 'nemotilesize' => 1, + 'nestedsignalstream' => 1, + 'nestlevel' => 1, + 'netexposurecompensation' => 1, + 'netname' => 1, + 'netprovidertype' => 1, + 'neutals' => 1, + 'neutobjbacktype' => 1, + 'neutobjname' => 1, + 'neutobjtype' => 1, + 'neutobjversion' => 1, + 'neutrals' => 1, + 'newbitdepth' => 1, + 'newcolortype' => 1, + 'newguid' => 1, + 'nexttrackid' => 1, + 'nifnonlinearity' => 1, + 'nifnonlinearity12bit' => 1, + 'nifnonlinearity12to16' => 1, + 'nifnonlinearity16bit' => 1, + 'nifnonlinearityext' => 1, + 'nikon' => 1, + 'nikoncaptureoffsets' => 1, + 'nikondata' => 1, + 'nikondatetime' => 1, + 'nikonncdb' => 1, + 'nikonncdt' => 1, + 'nikonnefinfo' => 1, + 'nikonscanifd' => 1, + 'nikontags' => 1, + 'nikonvers' => 1, + 'ninthlanguage' => 1, + 'nitf' => 1, + 'nitfversion' => 1, + 'noise' => 1, + 'noisereductiondata' => 1, + 'noisereductionkernel' => 1, + 'noisereductionparametershostlow' => 1, + 'noisereductionparametershostnormal' => 1, + 'noisereductionparametershoststrong' => 1, + 'nominalbitrate' => 1, + 'nominalframecount' => 1, + 'nominallayercount' => 1, + 'nominalplaytime' => 1, + 'nominalvideobitrate' => 1, + 'nomssmarttags' => 1, + 'normallinetransfertiming' => 1, + 'note' => 1, + 'notice' => 1, + 'now' => 1, + 'npts' => 1, + 'nrwdata' => 1, + 'nsc_address' => 1, + 'nsc_description' => 1, + 'nsc_email' => 1, + 'nsc_name' => 1, + 'nsc_phone' => 1, + 'nullmediaheader' => 1, + 'numberlist' => 1, + 'numberofcomponents' => 1, + 'numberofframes' => 1, + 'numberofimages' => 1, + 'numberofinks' => 1, + 'numberofparts' => 1, + 'numberofplanes' => 1, + 'numberofresolutions' => 1, + 'numberofsamples' => 1, + 'numberofsamples64' => 1, + 'numchanneldescriptions' => 1, + 'numchannels' => 1, + 'numcolors' => 1, + 'numfonts' => 1, + 'numhistorybuffers' => 1, + 'numimportantcolors' => 1, + 'numpackets' => 1, + 'numproperties' => 1, + 'numrules' => 1, + 'numsampleframes' => 1, + 'numslices' => 1, + 'numstreams' => 1, + 'objectfiletype' => 1, + 'objectflags' => 1, + 'objectid' => 1, + 'objectsizeannounced' => 1, + 'obsoletephotoshoptag1' => 1, + 'obsoletephotoshoptag2' => 1, + 'obsoletephotoshoptag3' => 1, + 'ocad' => 1, + 'ocadrevision' => 1, + 'oceapplicationselector' => 1, + 'oceidnumber' => 1, + 'oceimagelogic' => 1, + 'ocescanjobdesc' => 1, + 'office' => 1, + 'officelocation' => 1, + 'offlineavailability' => 1, + 'offlinestatus' => 1, + 'offsetmaphorizontal' => 1, + 'offsetmapvertical' => 1, + 'offsetorigin' => 1, + 'offsetx' => 1, + 'offsetxy' => 1, + 'offsety' => 1, + 'oldxmp' => 1, + 'olym' => 1, + 'olympus' => 1, + 'olympus2100' => 1, + 'olympus2100ifd' => 1, + 'olympus2200' => 1, + 'olympus2200ifd' => 1, + 'olympus2300' => 1, + 'olympus2300ifd' => 1, + 'olympus2400' => 1, + 'olympus2400ifd' => 1, + 'olympus2500' => 1, + 'olympus2500ifd' => 1, + 'olympus2600' => 1, + 'olympus2600ifd' => 1, + 'olympus2700' => 1, + 'olympus2700ifd' => 1, + 'olympus2800' => 1, + 'olympus2800ifd' => 1, + 'olympus2900' => 1, + 'olympus2900ifd' => 1, + 'olympusatom' => 1, + 'olympusdss' => 1, + 'olympusjunk' => 1, + 'olympusolym' => 1, + 'olympuspreview' => 1, + 'olympustags1' => 1, + 'olympustags2' => 1, + 'olympustags3' => 1, + 'olympustags4' => 1, + 'olympusthumbnail' => 1, + 'omenatcapturemode' => 1, + 'omenearlygobcolumns' => 1, + 'omenearlygobrows' => 1, + 'omenearlygobsurface' => 1, + 'omengradientexclusionlimits' => 1, + 'omengradientkernel' => 1, + 'omengradientkerneltaps' => 1, + 'omengradientoffset' => 1, + 'omeninitialcolumns' => 1, + 'omeninitialrows' => 1, + 'omeninitialscaling' => 1, + 'omenmeantostrength' => 1, + 'omenpercenttorationallimitsblue' => 1, + 'omenpercenttorationallimitsgob' => 1, + 'omenpercenttorationallimitsgor' => 1, + 'omenpercenttorationallimitsred' => 1, + 'omenrangeweighting' => 1, + 'omenratioclipfactors' => 1, + 'omenratioexclusionfactors' => 1, + 'omenroicoefficients' => 1, + 'omenroicoordinates' => 1, + 'omensmoothingkernel' => 1, + 'onionskins' => 1, + 'opacity' => 1, + 'opcolor' => 1, + 'opendml' => 1, + 'openwithapplication' => 1, + 'operatingsystem' => 1, + 'operation' => 1, + 'operationclassid' => 1, + 'operationid' => 1, + 'operationnumber' => 1, + 'opiproxy' => 1, + 'optics' => 1, + 'optimalbitrate' => 1, + 'optionalattendeeaddresses' => 1, + 'optionalattendees' => 1, + 'opus' => 1, + 'opusversion' => 1, + 'orderingrestrictions' => 1, + 'organizeraddress' => 1, + 'organizername' => 1, + 'orientationinfo' => 1, + 'orientationoffset' => 1, + 'originalalbum' => 1, + 'originalalbumtitle' => 1, + 'originalartist' => 1, + 'originaldocumentsize' => 1, + 'originalfilesize' => 1, + 'originalfiletype' => 1, + 'originalformat' => 1, + 'originalframerate' => 1, + 'originalimagebroker' => 1, + 'originallyricist' => 1, + 'originalmedia' => 1, + 'originalmedium' => 1, + 'originalrawcreator' => 1, + 'originalrawfiletype' => 1, + 'originalrawimage' => 1, + 'originalrawresource' => 1, + 'originalreleasetime' => 1, + 'originalreleaseyear' => 1, + 'originalscannedimagesize' => 1, + 'originalsoftpostpadding' => 1, + 'originalsoftprepadding' => 1, + 'originalthmcreator' => 1, + 'originalthmfiletype' => 1, + 'originalthmimage' => 1, + 'originalthmresource' => 1, + 'originator' => 1, + 'originatorreference' => 1, + 'originpathinfo' => 1, + 'osversion' => 1, + 'otheraddress' => 1, + 'othercity' => 1, + 'othercodecdescription' => 1, + 'othercodecname' => 1, + 'othercountry-region' => 1, + 'otherdate1' => 1, + 'otherdate2' => 1, + 'otherdate3' => 1, + 'otherfirmware' => 1, + 'otherformat' => 1, + 'otherinfo' => 1, + 'otherpobox' => 1, + 'otherpostalcode' => 1, + 'othersampledesc' => 1, + 'otherserialnumber' => 1, + 'otherstateorprovince' => 1, + 'otherstreet' => 1, + 'outputdataobjectlist' => 1, + 'outputgain' => 1, + 'outputresponse' => 1, + 'overclockcolsright' => 1, + 'overclockrowsbottom' => 1, + 'overflowcolor' => 1, + 'ownership' => 1, + 'packets' => 1, + 'packingmethod' => 1, + 'page' => 1, + 'pageenter' => 1, + 'pageexit' => 1, + 'pagefront' => 1, + 'pagelayout' => 1, + 'pagemode' => 1, + 'pagenormal' => 1, + 'pager' => 1, + 'pages' => 1, + 'pagespecial' => 1, + 'paintdata' => 1, + 'paintimage' => 1, + 'paintimageheight' => 1, + 'paintimagetype' => 1, + 'paintimagewidth' => 1, + 'paintingfilter' => 1, + 'palette' => 1, + 'palettecolors' => 1, + 'palettefilename' => 1, + 'palettehistogram' => 1, + 'paletteinfo' => 1, + 'palettemethod' => 1, + 'palettename' => 1, + 'palettestretch' => 1, + 'palmfiletype' => 1, + 'panasonic' => 1, + 'panasonicpana' => 1, + 'panorama' => 1, + 'panorientation' => 1, + 'panoverlaph' => 1, + 'panoverlapv' => 1, + 'paragraphs' => 1, + 'param0' => 1, + 'param1' => 1, + 'param2' => 1, + 'param3' => 1, + 'parameter' => 1, + 'parameterinfo' => 1, + 'parameters' => 1, + 'parasites' => 1, + 'parentalrating' => 1, + 'parentalratingreason' => 1, + 'parentproductid' => 1, + 'parentshorttitle' => 1, + 'parenttitle' => 1, + 'part' => 1, + 'partialactivecolsleft' => 1, + 'partialactivecolsright' => 1, + 'partialactiverowsbottom' => 1, + 'partialactiverowstop' => 1, + 'partialpalette' => 1, + 'partialsyncsamples' => 1, + 'participants' => 1, + 'partnumber' => 1, + 'partofset' => 1, + 'pastclippingboundary' => 1, + 'pasteimage' => 1, + 'path' => 1, + 'pathselectionstate' => 1, + 'pathtablelocation' => 1, + 'pathtablesize' => 1, + 'patternangle' => 1, + 'patterncorrectionfactors' => 1, + 'patterncorrectiongains' => 1, + 'patterncorrectionoffsets' => 1, + 'patterngainconversiontable' => 1, + 'payloadtype' => 1, + 'paymenturl' => 1, + 'pcscitation' => 1, + 'pdahistogram' => 1, + 'pdf' => 1, + 'pdfx' => 1, + 'peakbitrate' => 1, + 'peakspectralsensitivity' => 1, + 'peakvalue' => 1, + 'pefversion' => 1, + 'pentax' => 1, + 'pentaxdata' => 1, + 'pentaxdata2' => 1, + 'pentaxjunk' => 1, + 'pentaxjunk2' => 1, + 'pentaxpent' => 1, + 'pentaxpreview' => 1, + 'pentaxtags' => 1, + 'perceivedtype' => 1, + 'perceptualrenderingintentgamut' => 1, + 'percussivepolyphony' => 1, + 'performer' => 1, + 'performerkeywords' => 1, + 'performers' => 1, + 'performersortorder' => 1, + 'performerurl' => 1, + 'period' => 1, + 'perms' => 1, + 'perpicturenotes' => 1, + 'personalfunctions' => 1, + 'personalfunctionvalues' => 1, + 'personaltitle' => 1, + 'petype' => 1, + 'pfmheader' => 1, + 'pfmversion' => 1, + 'pgfversion' => 1, + 'photoeffectsdata' => 1, + 'photofinishername' => 1, + 'photomech' => 1, + 'photomechanic' => 1, + 'photoresolution' => 1, + 'photoshop' => 1, + 'photoshop2colortable' => 1, + 'photoshop2info' => 1, + 'photoshop_profile' => 1, + 'photoshopdata' => 1, + 'photoshopformat' => 1, + 'photoshopinfo' => 1, + 'photoshopsettings' => 1, + 'physicalpixel' => 1, + 'physicalstreamnumbermap' => 1, + 'physicalstreamnumbers' => 1, + 'physicalstreams' => 1, + 'pic_ifd' => 1, + 'picslabel' => 1, + 'picture' => 1, + 'picturebitsperpixel' => 1, + 'picturecontrolversion' => 1, + 'picturectrl' => 1, + 'picturedescription' => 1, + 'pictureformat' => 1, + 'pictureheight' => 1, + 'pictureindexedcolors' => 1, + 'pictureinfo' => 1, + 'picturelength' => 1, + 'picturemimetype' => 1, + 'picturestyleinfo' => 1, + 'picturestylepc' => 1, + 'picturestyleuserdef' => 1, + 'picturetype' => 1, + 'picturewidth' => 1, + 'pieceinfo' => 1, + 'piecelength' => 1, + 'pieces' => 1, + 'pip' => 1, + 'pipx1' => 1, + 'pipx2' => 1, + 'pipy1' => 1, + 'pipy2' => 1, + 'pitchandfamily' => 1, + 'pitchshift' => 1, + 'pixelaspectratio' => 1, + 'pixelaspectratiox' => 1, + 'pixelaspectratioy' => 1, + 'pixelcalibration' => 1, + 'pixelcorrectiongains' => 1, + 'pixelexposuretime' => 1, + 'pixelformat' => 1, + 'pixelinfo' => 1, + 'pixelintensityrange' => 1, + 'pixellive' => 1, + 'pixelmagicjbigoptions' => 1, + 'pixelspermeterx' => 1, + 'pixelspermetery' => 1, + 'pixheight' => 1, + 'pixwidth' => 1, + 'places' => 1, + 'planckb' => 1, + 'planckf' => 1, + 'plancko' => 1, + 'planckr1' => 1, + 'planckr2' => 1, + 'planes' => 1, + 'playallframes' => 1, + 'playcounter' => 1, + 'playerversion' => 1, + 'playgap' => 1, + 'playlistdelay' => 1, + 'playlistid' => 1, + 'playlistindex' => 1, + 'playmode' => 1, + 'playselection' => 1, + 'plus' => 1, + 'pmi' => 1, + 'pobox' => 1, + 'podcast' => 1, + 'podcastcategory' => 1, + 'podcastdescription' => 1, + 'podcastid' => 1, + 'podcastkeywords' => 1, + 'podcasturl' => 1, + 'pointsize' => 1, + 'popularimeter' => 1, + 'popupfillattributes' => 1, + 'popupflash' => 1, + 'portraitmatrix' => 1, + 'portraittonescaletable' => 1, + 'pose' => 1, + 'poseyawdegrees' => 1, + 'position' => 1, + 'postertime' => 1, + 'postscript2crd0' => 1, + 'postscript2crd1' => 1, + 'postscript2crd2' => 1, + 'postscript2crd3' => 1, + 'postscript2csa' => 1, + 'postscriptfont' => 1, + 'postscriptfontname' => 1, + 'pragma' => 1, + 'preferredfamily' => 1, + 'preferredrate' => 1, + 'preferredsubfamily' => 1, + 'preferredvolume' => 1, + 'preroll' => 1, + 'presentationformat' => 1, + 'presentationtarget' => 1, + 'preview' => 1, + 'preview0' => 1, + 'preview1' => 1, + 'preview2' => 1, + 'previewatomindex' => 1, + 'previewatomtype' => 1, + 'previewduration' => 1, + 'previewifd' => 1, + 'previewifd_offset' => 1, + 'previewimage1' => 1, + 'previewimage2' => 1, + 'previewimagedata' => 1, + 'previewimageinfo' => 1, + 'previewinfo' => 1, + 'previewpdf' => 1, + 'previewpict' => 1, + 'previewpng' => 1, + 'previewtiff' => 1, + 'previewtime' => 1, + 'previewversion' => 1, + 'previewwmf' => 1, + 'primarye-mail' => 1, + 'primaryitemreference' => 1, + 'primaryphone' => 1, + 'primaryplatform' => 1, + 'primaryvolume' => 1, + 'printflags' => 1, + 'printflagsinfo' => 1, + 'printimversion' => 1, + 'printinfo' => 1, + 'printinfo2' => 1, + 'printposition' => 1, + 'printquality' => 1, + 'printscale' => 1, + 'printscaleinfo' => 1, + 'printstyle' => 1, + 'printtovideo' => 1, + 'priority' => 1, + 'prioritysettings' => 1, + 'prism' => 1, + 'private' => 1, + 'privatebuild' => 1, + 'prl' => 1, + 'prm' => 1, + 'processing' => 1, + 'processinginfo' => 1, + 'processingparameters' => 1, + 'processingtime' => 1, + 'processparametersv2' => 1, + 'prod' => 1, + 'prodnotes' => 1, + 'producedby' => 1, + 'produceddate' => 1, + 'producednotice' => 1, + 'producerkeywords' => 1, + 'producers' => 1, + 'product' => 1, + 'productionaperturedimensions' => 1, + 'productiondate' => 1, + 'productiondesigner' => 1, + 'productionstudio' => 1, + 'productname' => 1, + 'producttype' => 1, + 'productversion' => 1, + 'productversionnumber' => 1, + 'profile' => 1, + 'profile1audiocodec' => 1, + 'profile1height' => 1, + 'profile1videocodec' => 1, + 'profile1width' => 1, + 'profileclass' => 1, + 'profilecmmtype' => 1, + 'profileconnectionspace' => 1, + 'profilecreator' => 1, + 'profiledataoffset' => 1, + 'profiledatetime' => 1, + 'profiledescription' => 1, + 'profiledescriptionml' => 1, + 'profilefilesignature' => 1, + 'profileheader' => 1, + 'profileid' => 1, + 'profileifd' => 1, + 'profiles' => 1, + 'profilesequencedesc' => 1, + 'profilesequenceidentifier' => 1, + 'profilesize' => 1, + 'profiletype' => 1, + 'profileversion' => 1, + 'progid' => 1, + 'programdescription' => 1, + 'programid' => 1, + 'programname' => 1, + 'progressivescans' => 1, + 'projazimuthangle' => 1, + 'projcentereasting' => 1, + 'projcenterlat' => 1, + 'projcenterlong' => 1, + 'projcenternorthing' => 1, + 'projcoordtrans' => 1, + 'project' => 1, + 'projectedcstype' => 1, + 'projection' => 1, + 'projectionboundsbottom' => 1, + 'projectionboundsleft' => 1, + 'projectionboundsright' => 1, + 'projectionboundstop' => 1, + 'projectionheader' => 1, + 'projects' => 1, + 'projfalseeasting' => 1, + 'projfalsenorthing' => 1, + 'projfalseorigineasting' => 1, + 'projfalseoriginlat' => 1, + 'projfalseoriginlong' => 1, + 'projfalseoriginnorthing' => 1, + 'projlinearunits' => 1, + 'projlinearunitsize' => 1, + 'projnatoriginlat' => 1, + 'projnatoriginlong' => 1, + 'projrectifiedgridangle' => 1, + 'projscaleatcenter' => 1, + 'projscaleatnatorigin' => 1, + 'projstdparallel1' => 1, + 'projstdparallel2' => 1, + 'projstraightvertpolelong' => 1, + 'promoteparent' => 1, + 'promotionurl' => 1, + 'prop' => 1, + 'properties' => 1, + 'propertysetidcodes' => 1, + 'propertysetpathname' => 1, + 'propertystoredata' => 1, + 'propertyvectorelements' => 1, + 'protect' => 1, + 'protected' => 1, + 'protectioninfo' => 1, + 'protectiontype' => 1, + 'protune' => 1, + 'provider' => 1, + 'providercopyright' => 1, + 'providerlogourl' => 1, + 'providerrating' => 1, + 'providerstyle' => 1, + 'providerurl' => 1, + 'ps2crdvmsize' => 1, + 'ps2renderingintent' => 1, + 'psfontinfo' => 1, + 'pstringcaption' => 1, + 'publishdate' => 1, + 'publishdatestart' => 1, + 'publisherlimit' => 1, + 'publisherurl' => 1, + 'pur' => 1, + 'purchasedate' => 1, + 'purchasefileformat' => 1, + 'purchaseinfo' => 1, + 'purpose' => 1, + 'pyramidlevels' => 1, + 'qtablelarge100pct' => 1, + 'qtablelarge25pct' => 1, + 'qtablelarge50pct' => 1, + 'qtablelarge67pct' => 1, + 'qtablemedium100pct' => 1, + 'qtablemedium25pct' => 1, + 'qtablemedium50pct' => 1, + 'qtablemedium67pct' => 1, + 'qtablesmall100pct' => 1, + 'qtablesmall25pct' => 1, + 'qtablesmall50pct' => 1, + 'qtablesmall67pct' => 1, + 'qualcomm' => 1, + 'quickedit' => 1, + 'quickmaskinfo' => 1, + 'qvci' => 1, + 'ra3' => 1, + 'ra4' => 1, + 'ra5' => 1, + 'radioband' => 1, + 'radioformat' => 1, + 'radiostationname' => 1, + 'radiostationowner' => 1, + 'rads' => 1, + 'rafdata' => 1, + 'rafversion' => 1, + 'rasterpadding' => 1, + 'rate' => 1, + 'rated' => 1, + 'ratingorg' => 1, + 'ratioimage' => 1, + 'rawcfacomponentaverages' => 1, + 'rawcodecversion' => 1, + 'rawdatalength' => 1, + 'rawdataoffset' => 1, + 'rawdatarotation' => 1, + 'rawdev2' => 1, + 'rawdev2ifd' => 1, + 'rawdevelopment' => 1, + 'rawdevelopmentifd' => 1, + 'rawexposurebias' => 1, + 'rawgsensor' => 1, + 'rawhistogram' => 1, + 'rawimagefullheight' => 1, + 'rawimagefullsize' => 1, + 'rawimagefullwidth' => 1, + 'rawimageheight' => 1, + 'rawimagemode' => 1, + 'rawimagesegmentation' => 1, + 'rawimagewidth' => 1, + 'rawinfo' => 1, + 'rawinfoifd' => 1, + 'rawjpginfo' => 1, + 'rawthermalimage' => 1, + 'rawthermalimageheight' => 1, + 'rawthermalimagetype' => 1, + 'rawthermalimagewidth' => 1, + 'rawvaluemedian' => 1, + 'rawvaluerange' => 1, + 'rawzorcreatorversion' => 1, + 'rawzorrequiredversion' => 1, + 'rdf' => 1, + 'readername' => 1, + 'readerrequirements' => 1, + 'reading1description' => 1, + 'reading1device' => 1, + 'reading1units' => 1, + 'reading1value' => 1, + 'reading2description' => 1, + 'reading2device' => 1, + 'reading2units' => 1, + 'reading2value' => 1, + 'reading3description' => 1, + 'reading3device' => 1, + 'reading3units' => 1, + 'reading3value' => 1, + 'reading4description' => 1, + 'reading4device' => 1, + 'reading4units' => 1, + 'reading4value' => 1, + 'readstatus' => 1, + 'real2ir' => 1, + 'realtimestreamingprotocol' => 1, + 'receivedfrom' => 1, + 'recengineer' => 1, + 'recinfo' => 1, + 'reclocation' => 1, + 'reconstructiontype' => 1, + 'recordedby' => 1, + 'recordeddate' => 1, + 'recordingcopyright' => 1, + 'recordingdates' => 1, + 'recordingtime' => 1, + 'recordingtimeday' => 1, + 'recordingtimemonth' => 1, + 'recordingtimeyear' => 1, + 'recordingtimeyearmonth' => 1, + 'recordingtimeyearmonthday' => 1, + 'recordlabelname' => 1, + 'recordlabelurl' => 1, + 'rect' => 1, + 'rectangleofinterest' => 1, + 'red1header' => 1, + 'red2header' => 1, + 'redadjust' => 1, + 'redblueflatfield' => 1, + 'redcodeversion' => 1, + 'redendpoint' => 1, + 'redeyedata' => 1, + 'redgain' => 1, + 'redmask' => 1, + 'redmatrixcolumn' => 1, + 'redprimary' => 1, + 'redsample' => 1, + 'redtrc' => 1, + 'redx' => 1, + 'redy' => 1, + 'reelnumber' => 1, + 'reeltimecode' => 1, + 'reference' => 1, + 'referencetemperature' => 1, + 'reflectedapparenttemperature' => 1, + 'reflectionhardcopyorigcolorimetry' => 1, + 'reflectionprintoutputcolorimetry' => 1, + 'refresh' => 1, + 'regionxformtackpoint' => 1, + 'registerreadtiming' => 1, + 'relatedimagefile' => 1, + 'relativeexposure' => 1, + 'relativehumidity' => 1, + 'relativelocation' => 1, + 'relativepath' => 1, + 'relativevolumeadjustment' => 1, + 'releasedateday' => 1, + 'releasedatemonth' => 1, + 'releasedateyear' => 1, + 'releasedateyearmonth' => 1, + 'releasedateyearmonthday' => 1, + 'rembrandtconsumertonescale' => 1, + 'rembrandtportraittonescale' => 1, + 'rembrandttonescale' => 1, + 'remindertime' => 1, + 'removehistoryduplicates' => 1, + 'renderingintent' => 1, + 'renderingtransform' => 1, + 'rentalexpirationdate' => 1, + 'rentalflag' => 1, + 'repeateddatabytes' => 1, + 'replaygainalbumgain' => 1, + 'replaygainalbumpeak' => 1, + 'replaygaintrackgain' => 1, + 'replaygaintrackpeak' => 1, + 'replyto' => 1, + 'representativedisparityfar' => 1, + 'representativedisparitynear' => 1, + 'representativeimage' => 1, + 'requestid' => 1, + 'requeststate' => 1, + 'requiredattendeeaddresses' => 1, + 'requiredattendees' => 1, + 'requirements' => 1, + 'rerun' => 1, + 'reserved1' => 1, + 'reserved5' => 1, + 'reservedblob2' => 1, + 'reservedblob3' => 1, + 'reservedblob4' => 1, + 'reservedblob5' => 1, + 'reservedblob6' => 1, + 'reservedblob7' => 1, + 'reservedblob8' => 1, + 'reservedblob9' => 1, + 'resolutioninfo' => 1, + 'resourcecount' => 1, + 'resourceforksize' => 1, + 'resources' => 1, + 'resourcesneeded' => 1, + 'resourcetype' => 1, + 'resultaspectratio' => 1, + 'retailprice' => 1, + 'retailpricecurrency' => 1, + 'retouchinfoversion' => 1, + 'review' => 1, + 'revisiondate' => 1, + 'revisionnumber' => 1, + 'revisitafter' => 1, + 'rgb_profile' => 1, + 'rgbcurves' => 1, + 'rgbtoev0' => 1, + 'rgbtoev1' => 1, + 'rgbtoev2' => 1, + 'rgbtoev3' => 1, + 'rgbtoev4' => 1, + 'rgbtoev5' => 1, + 'rgbtoev6' => 1, + 'rgbtoev7' => 1, + 'rgbtoev8' => 1, + 'rgbtoev9' => 1, + 'rgtable' => 1, + 'ricoh' => 1, + 'ricohjunk' => 1, + 'ricohmake' => 1, + 'ricohmodel' => 1, + 'ricohpitch' => 1, + 'ricohrdc2' => 1, + 'ricohrmkn' => 1, + 'ricohroll' => 1, + 'ricohrr1subdir' => 1, + 'ricohsubdir' => 1, + 'ricohsubdirifd' => 1, + 'riffsize64' => 1, + 'rightdarkcol1' => 1, + 'rightdarkcol2' => 1, + 'rightdarkrect' => 1, + 'rightmag' => 1, + 'rimm13toerimm12spline' => 1, + 'rimmtocrgb0spline' => 1, + 'rimmtocrgb1spline' => 1, + 'rimmtocrgb2spline' => 1, + 'rimmtocrgb3spline' => 1, + 'rimmtocrgb4spline' => 1, + 'rimmtocrgb5spline' => 1, + 'rimmtocrgb6spline' => 1, + 'rimmtocrgb7spline' => 1, + 'rimmtocrgb8spline' => 1, + 'rimmtocrgb9spline' => 1, + 'rimnonlinearity' => 1, + 'rimtonifcolortransform' => 1, + 'rimtonifscalefactor' => 1, + 'rippedby' => 1, + 'rjmd' => 1, + 'rmeta' => 1, + 'rnoiselines' => 1, + 'robots' => 1, + 'rocinfo' => 1, + 'roidescription' => 1, + 'rollguidelements' => 1, + 'rollingshutterskewtime' => 1, + 'root' => 1, + 'rootdirectorycreatedate' => 1, + 'rotationangle' => 1, + 'rotationinfooffset' => 1, + 'roundtripversion' => 1, + 'rowinterleavefactor' => 1, + 'rtmd' => 1, + 'rtptimescale' => 1, + 'runtime' => 1, + 'runtimeepoch' => 1, + 'runtimeflags' => 1, + 'runtimescale' => 1, + 'runtimesincepowerup' => 1, + 'runtimevalue' => 1, + 'runwindow' => 1, + 'rvmi_grev' => 1, + 'rvmi_srev' => 1, + 's2n' => 1, + 'sampleblacksequence' => 1, + 'sampledegradationpriority' => 1, + 'sampleduration' => 1, + 'sampleflag' => 1, + 'sampleformat' => 1, + 'samplegroupdescription' => 1, + 'samplepaddingbits' => 1, + 'samplerate2' => 1, + 'samplesize' => 1, + 'samplesizes' => 1, + 'sampletable' => 1, + 'sampletext' => 1, + 'sampletime' => 1, + 'sampletochunk' => 1, + 'sampletogroup' => 1, + 'samsung' => 1, + 'samsungifd' => 1, + 'samsunginfo' => 1, + 'samsungrawbyteorder' => 1, + 'samsungrawpointerslength' => 1, + 'samsungrawpointersoffset' => 1, + 'samsungrawunknown' => 1, + 'samsungsec' => 1, + 'samsungsmta' => 1, + 'samsungsvss' => 1, + 'samsungtags' => 1, + 'samsunguniqueid' => 1, + 'sanyomov' => 1, + 'sanyomp4' => 1, + 'sap' => 1, + 'saturationinfo' => 1, + 'saturationrenderingintentgamut' => 1, + 'saveobjbacktype' => 1, + 'saveobjects' => 1, + 'saveobjname' => 1, + 'saveobjtype' => 1, + 'saveobjversion' => 1, + 'savesetup' => 1, + 'sba_rgbshifts' => 1, + 'sbabluebalancelut' => 1, + 'sbaexposurerecord' => 1, + 'sbagreenbalancelut' => 1, + 'sbainputimagebitdepth' => 1, + 'sbainputimagecolorspace' => 1, + 'sbalog12transform' => 1, + 'sbalogtransform' => 1, + 'sbaredbalancelut' => 1, + 'scalado' => 1, + 'scale' => 1, + 'scalecrop' => 1, + 'scaledimu' => 1, + 'scaledpressure' => 1, + 'scalefactor' => 1, + 'scalefactor35efl' => 1, + 'scalingfactor' => 1, + 'scandate' => 1, + 'scannerfirmwaredate' => 1, + 'scannerfirmwareversion' => 1, + 'scannermake' => 1, + 'scannermodel' => 1, + 'scannerpixelsize' => 1, + 'scannerproductid' => 1, + 'scannerserialnumber' => 1, + 'scannervendorid' => 1, + 'scanoperatorid' => 1, + 'scansoftware' => 1, + 'scansoftwarerevisiondate' => 1, + 'scav11cols' => 1, + 'scav12cols' => 1, + 'scav21cols' => 1, + 'scav22cols' => 1, + 'sceneappearanceestimates' => 1, + 'scenebalancealgorithmcommand' => 1, + 'scenebalancealgorithmfilmid' => 1, + 'scenebalancealgorithmrevision' => 1, + 'scenecolorimetryestimates' => 1, + 'scheduleitemid' => 1, + 'schemeinfo' => 1, + 'schemetype' => 1, + 'schemeurl' => 1, + 'schemeversion' => 1, + 'school' => 1, + 'screenbuffersize' => 1, + 'screendescriptor' => 1, + 'screenheight' => 1, + 'screening' => 1, + 'screeningdesc' => 1, + 'screennail' => 1, + 'screenwidth' => 1, + 'screenwindowcenter' => 1, + 'screenwindowwidth' => 1, + 'screenwriters' => 1, + 'scriptcommand' => 1, + 'searchranking' => 1, + 'secondarygenre' => 1, + 'secondlanguage' => 1, + 'security' => 1, + 'seekable' => 1, + 'seekpoint' => 1, + 'seektable' => 1, + 'selection' => 1, + 'selectionduration' => 1, + 'selectiontime' => 1, + 'selobjbacktype' => 1, + 'selobjname' => 1, + 'selobjtype' => 1, + 'selobjversion' => 1, + 'sendduration' => 1, + 'senderaddress' => 1, + 'sendername' => 1, + 'sensitivity' => 1, + 'sensorbottomborder' => 1, + 'sensordefects' => 1, + 'sensorid' => 1, + 'sensorinfo' => 1, + 'sensorrightborder' => 1, + 'sequenceframenumber' => 1, + 'sequencenumberrandomoffset' => 1, + 'serialinfo' => 1, + 'serialnumberhash' => 1, + 'seriesuid' => 1, + 'serviceid' => 1, + 'serviceorganizationname' => 1, + 'setcookie' => 1, + 'setinfo' => 1, + 'setsubtitle' => 1, + 'seventhlanguage' => 1, + 'sfsboundary' => 1, + 'sglcoldcacthres1' => 1, + 'sglcoldcacthres2' => 1, + 'sglcoldcacthres3' => 1, + 'shadowendpoints' => 1, + 'shadowfilepath' => 1, + 'shadowsyncsampletable' => 1, + 'shakereductioninfo' => 1, + 'shared' => 1, + 'shareddata' => 1, + 'shareddoc' => 1, + 'shareduserrating' => 1, + 'sharedwith' => 1, + 'sharpenforthumbnail' => 1, + 'sharpeningon' => 1, + 'sharpinfo' => 1, + 'sharpmethod' => 1, + 'sharpnessapproximation' => 1, + 'sharpnessfreqtable' => 1, + 'sharpnesstable' => 1, + 'sharpobjbacktype' => 1, + 'sharpobjname' => 1, + 'sharpobjtype' => 1, + 'sharpobjversion' => 1, + 'sheetdisclosure' => 1, + 'shifttiming' => 1, + 'shimdata' => 1, + 'shootingcount' => 1, + 'shootingmenuoffset' => 1, + 'shootingrecord' => 1, + 'shootobjbacktype' => 1, + 'shootobjname' => 1, + 'shootobjtype' => 1, + 'shootobjversion' => 1, + 'shootsetup' => 1, + 'shorttitle' => 1, + 'shotinfo' => 1, + 'shotinfo02xx' => 1, + 'shotinfod300a' => 1, + 'shotinfod300b' => 1, + 'shotinfod300s' => 1, + 'shotinfod3a' => 1, + 'shotinfod3b' => 1, + 'shotinfod3s' => 1, + 'shotinfod3x' => 1, + 'shotinfod4' => 1, + 'shotinfod40' => 1, + 'shotinfod4s' => 1, + 'shotinfod5' => 1, + 'shotinfod500' => 1, + 'shotinfod5000' => 1, + 'shotinfod5100' => 1, + 'shotinfod5200' => 1, + 'shotinfod610' => 1, + 'shotinfod700' => 1, + 'shotinfod7000' => 1, + 'shotinfod80' => 1, + 'shotinfod800' => 1, + 'shotinfod810' => 1, + 'shotinfod850' => 1, + 'shotinfod90' => 1, + 'shotinfounknown' => 1, + 'shotinfoversion' => 1, + 'showmode' => 1, + 'showobjects' => 1, + 'shuttercurtainhack' => 1, + 'shutterspeed' => 1, + 'shutterspeeddisplayed' => 1, + 'sidebars' => 1, + 'sigma' => 1, + 'sigmanoisefiltercaltablev1' => 1, + 'sigmanoisefiltertablev1' => 1, + 'sigmanoisefiltertablev1version' => 1, + 'sigmanoisethreshtablev2' => 1, + 'signalnumber' => 1, + 'signature' => 1, + 'signature_name' => 1, + 'signatureusagerights' => 1, + 'signercontactinfo' => 1, + 'significantbits' => 1, + 'signingauthority' => 1, + 'signingdate' => 1, + 'signinglocation' => 1, + 'signingreason' => 1, + 'signtype' => 1, + 'simpleindex' => 1, + 'simplicityprofile' => 1, + 'singlequality' => 1, + 'site' => 1, + 'siteenter' => 1, + 'siteexit' => 1, + 'siunits' => 1, + 'sixthlanguage' => 1, + 'size' => 1, + 'sizemode' => 1, + 'skip' => 1, + 'slateinformation' => 1, + 'sliceinfo' => 1, + 'slicesgroupname' => 1, + 'slides' => 1, + 'slideshow' => 1, + 'smaxsamplevalue' => 1, + 'sminsamplevalue' => 1, + 'snapshotid' => 1, + 'snapshotname' => 1, + 'soctemperature' => 1, + 'softedit' => 1, + 'softfocusfilter' => 1, + 'softwarecomponents' => 1, + 'softwarerelease' => 1, + 'songwriter' => 1, + 'songwriterkeywords' => 1, + 'sony' => 1, + 'sonyrawfiletype' => 1, + 'sonytonecurve' => 1, + 'sortalbum' => 1, + 'sortalbumartist' => 1, + 'sortartist' => 1, + 'sortcomposer' => 1, + 'sortname' => 1, + 'sortshow' => 1, + 'soundfile' => 1, + 'soundschemetitle' => 1, + 'sourcecreatedate' => 1, + 'sourcecredits' => 1, + 'sourcedata' => 1, + 'sourcedate' => 1, + 'sourceedition' => 1, + 'sourcefilename' => 1, + 'sourceform' => 1, + 'sourceid' => 1, + 'sourceimagedirectory' => 1, + 'sourceimagefilename' => 1, + 'sourceimageheight' => 1, + 'sourceimagevolumename' => 1, + 'sourceimagewidth' => 1, + 'sourcepublisher' => 1, + 'sourcerights' => 1, + 'sourcetitle' => 1, + 'sourceurl' => 1, + 'spacefree' => 1, + 'spaceused' => 1, + 'spatialorientation' => 1, + 'spatialresolution' => 1, + 'specialbuild' => 1, + 'specialeffectsopticalfilter' => 1, + 'specialfolderdata' => 1, + 'specificationversion' => 1, + 'speed' => 1, + 'sphericalvideo' => 1, + 'sphericalvideoxml' => 1, + 'spiff' => 1, + 'spiffversion' => 1, + 'spothalftone' => 1, + 'spouse' => 1, + 'sr2dataifd' => 1, + 'sr2private' => 1, + 'sr2subifdkey' => 1, + 'sr2subifdlength' => 1, + 'sr2subifdoffset' => 1, + 'srawtype' => 1, + 'srf2key' => 1, + 'srf6offset' => 1, + 'srfdataoffset' => 1, + 'srgbrendering' => 1, + 'stampinfo' => 1, + 'stamptoolcount' => 1, + 'starring' => 1, + 'startdate' => 1, + 'startedgecode' => 1, + 'startofframe' => 1, + 'startreading' => 1, + 'starttime' => 1, + 'stateorprovince' => 1, + 'stationcallsign' => 1, + 'stationname' => 1, + 'statistics' => 1, + 'stdautoactive' => 1, + 'stdbasename' => 1, + 'stdhotfolder' => 1, + 'stdopeninphotoshop' => 1, + 'stdoutputbitdepth' => 1, + 'stdoutputcolormode' => 1, + 'stdoutputfiletype' => 1, + 'stdoxygen' => 1, + 'stdsaveselection' => 1, + 'stdscaledoutput' => 1, + 'stdsharpenoutput' => 1, + 'stereo' => 1, + 'stereoimage' => 1, + 'stereoscopic3d' => 1, + 'stim' => 1, + 'stimversion' => 1, + 'stitchcolumns' => 1, + 'stitchinfo' => 1, + 'stitchrows' => 1, + 'stonits' => 1, + 'storage-streampathname' => 1, + 'storageformatdate' => 1, + 'storageformattime' => 1, + 'storagemodel' => 1, + 'storageserialnumber' => 1, + 'storagetype' => 1, + 'store' => 1, + 'stream' => 1, + 'streamavgbitrate' => 1, + 'streamavgpacketsize' => 1, + 'streambitdepth' => 1, + 'streambitrateprops' => 1, + 'streamcolor' => 1, + 'streamcount' => 1, + 'streamdata' => 1, + 'streamduration' => 1, + 'streamheader' => 1, + 'streaminfo' => 1, + 'streamingdataprotocol' => 1, + 'streammaxbitrate' => 1, + 'streammaxpacketsize' => 1, + 'streammimelen' => 1, + 'streammimetype' => 1, + 'streamname' => 1, + 'streamnamelen' => 1, + 'streamnumber' => 1, + 'streampreroll' => 1, + 'streamprioritization' => 1, + 'streamproperties' => 1, + 'streamsamplecount' => 1, + 'streamsamplerate' => 1, + 'streamstarttime' => 1, + 'streamtypeinfo' => 1, + 'street' => 1, + 'stridable' => 1, + 'strikeout' => 1, + 'stripbytecounts' => 1, + 'stripoffsets' => 1, + 'striprowcounts' => 1, + 'strobe' => 1, + 'strobetime' => 1, + 'structuretype' => 1, + 'studio' => 1, + 'sub-sampleinformation' => 1, + 'subdir3000' => 1, + 'subdir3100' => 1, + 'subdir3400' => 1, + 'subdir3900' => 1, + 'subfile' => 1, + 'subifd' => 1, + 'subifd0' => 1, + 'subifd1' => 1, + 'subifd2' => 1, + 'subifd255' => 1, + 'subifd3' => 1, + 'subifd4' => 1, + 'subifd5' => 1, + 'subifd6' => 1, + 'subifd_offset' => 1, + 'subimagecolor' => 1, + 'subimagehdr' => 1, + 'subimageheight' => 1, + 'subimageicc_profile' => 1, + 'subimagenumericalformat' => 1, + 'subimageresolutions' => 1, + 'subimagetilecount' => 1, + 'subimagetileheight' => 1, + 'subimagetilewidth' => 1, + 'subimagewidth' => 1, + 'subjectpixelheight' => 1, + 'subjectpixelwidth' => 1, + 'subjectscale' => 1, + 'subjectunits' => 1, + 'subpacketh' => 1, + 'subpacketsize' => 1, + 'subscriptioncontentid' => 1, + 'subsystem' => 1, + 'subsystemversion' => 1, + 'subtileblocksize' => 1, + 'subtitledescription' => 1, + 'subtitlekeywords' => 1, + 'suffix' => 1, + 'suggestedpalette' => 1, + 'summary' => 1, + 'summaryinfo' => 1, + 'surroundmode' => 1, + 'surroundshotvideo' => 1, + 'surroundshotvideoname' => 1, + 'svgversion' => 1, + 'swf' => 1, + 'sync01' => 1, + 'sync02' => 1, + 'sync03' => 1, + 'sync04' => 1, + 'sync05' => 1, + 'sync06' => 1, + 'sync07' => 1, + 'sync08' => 1, + 'sync09' => 1, + 'sync10' => 1, + 'sync11' => 1, + 'sync12' => 1, + 'sync13' => 1, + 'sync14' => 1, + 'sync15' => 1, + 'sync16' => 1, + 'synchronizedlyricsdescription' => 1, + 'synchronizedlyricstext' => 1, + 'synchronizedlyricstype' => 1, + 'synconly' => 1, + 'syncsampletable' => 1, + 'syncstate' => 1, + 'synlyrics' => 1, + 'systemtime' => 1, + 't4options' => 1, + 't6options' => 1, + 't82options' => 1, + 't88options' => 1, + 'tag2010a' => 1, + 'tag2010b' => 1, + 'tag2010c' => 1, + 'tag2010d' => 1, + 'tag2010e' => 1, + 'tag2010f' => 1, + 'tag2010g' => 1, + 'tag2010h' => 1, + 'tag2010i' => 1, + 'tag202a' => 1, + 'tag900b' => 1, + 'tag9050a' => 1, + 'tag9050b' => 1, + 'tag9400a' => 1, + 'tag9400b' => 1, + 'tag9400c' => 1, + 'tag9401' => 1, + 'tag9402' => 1, + 'tag9403' => 1, + 'tag9404a' => 1, + 'tag9404b' => 1, + 'tag9404c' => 1, + 'tag9405a' => 1, + 'tag9405b' => 1, + 'tag9406' => 1, + 'tag940a' => 1, + 'tag940c' => 1, + 'tag940e' => 1, + 'taggedpdf' => 1, + 'taggingtime' => 1, + 'take' => 1, + 'tamper-proofkeys' => 1, + 'targetaudiences' => 1, + 'targetdeltatype' => 1, + 'targetfiledosname' => 1, + 'targetfilesize' => 1, + 'targetlayerid' => 1, + 'targetxy' => 1, + 'taskowner' => 1, + 'tattoo' => 1, + 'tcmediainfo' => 1, + 'tdat' => 1, + 'tdhd' => 1, + 'technician' => 1, + 'technology' => 1, + 'telephonenumber' => 1, + 'telex' => 1, + 'temperature' => 1, + 'tempinfo' => 1, + 'template' => 1, + 'temporary' => 1, + 'terminationaction' => 1, + 'terminationcondition' => 1, + 'termsofuse' => 1, + 'testtarget' => 1, + 'testtransfertiming' => 1, + 'text' => 1, + 'textcolor' => 1, + 'textface' => 1, + 'textfont' => 1, + 'textinfo' => 1, + 'textinfo1' => 1, + 'textinfo2' => 1, + 'textjunk' => 1, + 'textsize' => 1, + 'texttospeech' => 1, + 'textualdata' => 1, + 'textualinfo' => 1, + 'textureformat' => 1, + 'theora' => 1, + 'theoraversion' => 1, + 'thetasubdir' => 1, + 'things' => 1, + 'thirdlanguage' => 1, + 'thumbinfo' => 1, + 'thumbnail' => 1, + 'thumbnailbpg' => 1, + 'thumbnailclip' => 1, + 'thumbnailcompressiontable' => 1, + 'thumbnailexpansiontable' => 1, + 'thumbnailpng' => 1, + 'thumbnailresizeratio' => 1, + 'thumbnailtiff' => 1, + 'tickspersecond' => 1, + 'tiff' => 1, + 'tiff-epstandardid' => 1, + 'tiff_fxextensions' => 1, + 'tiffmeteringimageheight' => 1, + 'tiffmeteringimagewidth' => 1, + 'tiffpreview' => 1, + 'tilebytecounts' => 1, + 'tiledepth' => 1, + 'tilegaindeterminationtable' => 1, + 'tileoffsets' => 1, + 'tiles' => 1, + 'timecode' => 1, + 'timecodeindex' => 1, + 'timecodeindexparms' => 1, + 'timeinfo' => 1, + 'timelineinfo' => 1, + 'timeoffset' => 1, + 'timereference' => 1, + 'timescale' => 1, + 'timestamprandomoffset' => 1, + 'timetosampletable' => 1, + 'title2' => 1, + 'titlelen' => 1, + 'titlenum' => 1, + 'titleofparts' => 1, + 'titlesofparts' => 1, + 'titlesortorder' => 1, + 'toaddresses' => 1, + 'tocitems' => 1, + 'todotitle' => 1, + 'tomtomad' => 1, + 'tomtomhl' => 1, + 'tomtomid' => 1, + 'tomtommetadata' => 1, + 'tomtomvd' => 1, + 'tomtomvi' => 1, + 'tonames' => 1, + 'tonecurvematching' => 1, + 'tonecurvetable' => 1, + 'tonematrix' => 1, + 'toneobjbacktype' => 1, + 'toneobjname' => 1, + 'toneobjtype' => 1, + 'toneobjversion' => 1, + 'tones' => 1, + 'tonescale0' => 1, + 'tonescale0spline' => 1, + 'tonescale1' => 1, + 'tonescale1spline' => 1, + 'tonescale2' => 1, + 'tonescale2spline' => 1, + 'tonescale3' => 1, + 'tonescale3spline' => 1, + 'tonescale4' => 1, + 'tonescale4spline' => 1, + 'tonescale5' => 1, + 'tonescale5spline' => 1, + 'tonescale6' => 1, + 'tonescale6spline' => 1, + 'tonescale7' => 1, + 'tonescale7spline' => 1, + 'tonescale8' => 1, + 'tonescale8spline' => 1, + 'tonescale9' => 1, + 'tonescale9spline' => 1, + 'tonespaceflow' => 1, + 'tonscaletable' => 1, + 'tool_name' => 1, + 'tool_version' => 1, + 'toolname' => 1, + 'toolversion' => 1, + 'topdarkrow1' => 1, + 'topdarkrow2' => 1, + 'topmag' => 1, + 'topmargin' => 1, + 'totalbitrate' => 1, + 'totalbytes' => 1, + 'totalbytesnortpheaders' => 1, + 'totaldatarate' => 1, + 'totalduration' => 1, + 'totaleditingtime' => 1, + 'totaledittime' => 1, + 'totalfilesize' => 1, + 'totalframecount' => 1, + 'totalframes' => 1, + 'totalsamples' => 1, + 'totalsize' => 1, + 'toycamerafilter' => 1, + 'track' => 1, + 'trackaperture' => 1, + 'trackcategory' => 1, + 'trackcomments' => 1, + 'trackduration' => 1, + 'trackerdata' => 1, + 'trackfragment' => 1, + 'trackheader' => 1, + 'trackheaderversion' => 1, + 'trackid' => 1, + 'trackingid' => 1, + 'tracklayer' => 1, + 'tracklyrics' => 1, + 'trackproperty' => 1, + 'trackref' => 1, + 'tracktype' => 1, + 'trackvolume' => 1, + 'trademark' => 1, + 'transactionid' => 1, + 'transferrange' => 1, + 'transfersequence' => 1, + 'transformation' => 1, + 'transformcreatedate' => 1, + 'transformedimagetitle' => 1, + 'transformmodifydate' => 1, + 'transformnodeid' => 1, + 'transformparams' => 1, + 'transformtitle' => 1, + 'transparency' => 1, + 'transparencyindicator' => 1, + 'transparentindex' => 1, + 'trapindicator' => 1, + 'trashcolsright' => 1, + 'trashrowsbottom' => 1, + 'trebel' => 1, + 'tty-ttdphone' => 1, + 'tungmat0' => 1, + 'tungmat1' => 1, + 'tungmat2' => 1, + 'tungmat3' => 1, + 'tungmat4' => 1, + 'tungmat5' => 1, + 'tungmat6' => 1, + 'tungmat7' => 1, + 'tungmat8' => 1, + 'tungmat9' => 1, + 'tvepisode' => 1, + 'tvepisodeid' => 1, + 'tvnetworkname' => 1, + 'tvseason' => 1, + 'tvshow' => 1, + 'tx3g' => 1, + 'typeoforiginal' => 1, + 'typist' => 1, + 'ucrbg' => 1, + 'uic1tag' => 1, + 'uic2tag' => 1, + 'uic3tag' => 1, + 'uic4tag' => 1, + 'uncompressed' => 1, + 'uncompressedsize' => 1, + 'uncompressedtextlength' => 1, + 'underflowcolor' => 1, + 'underline' => 1, + 'underlineposition' => 1, + 'underlinethickness' => 1, + 'unicodealphanames' => 1, + 'uninitializeddatasize' => 1, + 'uniquefileidentifier' => 1, + 'uniqueid' => 1, + 'unknown' => 1, + 'unknown00' => 1, + 'unknown01' => 1, + 'unknown02' => 1, + 'unknown03' => 1, + 'unknown_aacr' => 1, + 'unknown_cdek' => 1, + 'unknown_cdet' => 1, + 'unknown_cndb' => 1, + 'unknown_slmt' => 1, + 'unknownd30' => 1, + 'unknowndata' => 1, + 'unknowninfo' => 1, + 'unknowninfo2' => 1, + 'unknowninfo2version' => 1, + 'unknowninfoifd' => 1, + 'unknowninfoversion' => 1, + 'unknownserial1' => 1, + 'unknownserial2' => 1, + 'unknownserial3' => 1, + 'unknownserial4' => 1, + 'unknowntags' => 1, + 'unknowntemperature1' => 1, + 'unknowntemperature2' => 1, + 'unknownthumbnail' => 1, + 'unsharpdata' => 1, + 'untitled0' => 1, + 'untitled1' => 1, + 'untitled2' => 1, + 'unused' => 1, + 'unusedblackcolsleftin' => 1, + 'unusedblackcolsleftout' => 1, + 'unusedblackcolsrightin' => 1, + 'unusedblackcolsrightout' => 1, + 'unusedblackrowsbottomin' => 1, + 'unusedblackrowsbottomout' => 1, + 'unusedblackrowstopin' => 1, + 'unusedblackrowstopout' => 1, + 'updatedtitle' => 1, + 'ur3' => 1, + 'urllist1' => 1, + 'urn' => 1, + 'usagerightsmessage' => 1, + 'usedextensionnumbers' => 1, + 'useraccess' => 1, + 'useradjsba_rgbshifts' => 1, + 'usercollection' => 1, + 'usercustom1' => 1, + 'usercustom2' => 1, + 'userdata' => 1, + 'userdefinedid' => 1, + 'userdefinedtext' => 1, + 'userdefinedurl' => 1, + 'usereffectiverating' => 1, + 'userid' => 1, + 'userlastplayedtime' => 1, + 'usermetadata' => 1, + 'username' => 1, + 'userplaycount' => 1, + 'userplaycountafternoon' => 1, + 'userplaycountevening' => 1, + 'userplaycountmorning' => 1, + 'userplaycountnight' => 1, + 'userplaycountweekday' => 1, + 'userplaycountweekend' => 1, + 'userrating' => 1, + 'userselectgrouptitle' => 1, + 'userservicerating' => 1, + 'userweburl' => 1, + 'usingtransforms' => 1, + 'usmparametershigh' => 1, + 'usmparametershost' => 1, + 'usmparametershost3mp' => 1, + 'usmparametershost6mp' => 1, + 'usmparameterslow' => 1, + 'usmparametersmed' => 1, + 'usptomiscellaneous' => 1, + 'usptooriginalcontenttype' => 1, + 'utm' => 1, + 'uuid-canon' => 1, + 'uuid-exif' => 1, + 'uuid-exif2' => 1, + 'uuid-exif_bad' => 1, + 'uuid-flip' => 1, + 'uuid-geojp2' => 1, + 'uuid-iptc' => 1, + 'uuid-iptc2' => 1, + 'uuid-photoshop' => 1, + 'uuid-prof' => 1, + 'uuid-unknown' => 1, + 'uuid-usmt' => 1, + 'uuid-xmp' => 1, + 'uuidinfo' => 1, + 'uuidlist' => 1, + 'validafpoints' => 1, + 'validate' => 1, + 'value0' => 1, + 'value1' => 1, + 'value2' => 1, + 'value3' => 1, + 'vary' => 1, + 'vbrbytes' => 1, + 'vbrframes' => 1, + 'vbrpeak' => 1, + 'vbrscale' => 1, + 'vddimdacnominalvalues' => 1, + 'vegasversionmajor' => 1, + 'vegasversionminor' => 1, + 'vendor' => 1, + 'vendorid' => 1, + 'vendorname' => 1, + 'vendorurl' => 1, + 'version1' => 1, + 'version2' => 1, + 'versionbf' => 1, + 'versionifd' => 1, + 'versioninfo' => 1, + 'versionrestrictions' => 1, + 'versionyear' => 1, + 'verticalcitation' => 1, + 'verticalcstype' => 1, + 'verticaldatum' => 1, + 'verticaldivergence' => 1, + 'verticalresolution' => 1, + 'verticalscale' => 1, + 'verticalunits' => 1, + 'video' => 1, + 'videoattributes' => 1, + 'videoavgbitrate' => 1, + 'videoavgframerate' => 1, + 'videocardgamma' => 1, + 'videoclosedcaptioning' => 1, + 'videocodecdescription' => 1, + 'videocodecid' => 1, + 'videocodecinfo' => 1, + 'videocodecname' => 1, + 'videocompression' => 1, + 'videoencoding' => 1, + 'videoformat' => 1, + 'videoframecount' => 1, + 'videoheader' => 1, + 'videoheight' => 1, + 'videomaxbitrate' => 1, + 'videomaxframerate' => 1, + 'videomode' => 1, + 'videoorientation' => 1, + 'videoprofile' => 1, + 'videoprofileversion' => 1, + 'videosampledesc' => 1, + 'videoscantype' => 1, + 'videosize' => 1, + 'videostreamtype' => 1, + 'videotrackid' => 1, + 'videowidth' => 1, + 'view' => 1, + 'viewable' => 1, + 'viewingconddesc' => 1, + 'viewingcondilluminant' => 1, + 'viewingcondilluminanttype' => 1, + 'viewingconditions' => 1, + 'viewingcondsurround' => 1, + 'viewtype' => 1, + 'vignettingcorr' => 1, + 'vignettingcorr2' => 1, + 'vignettingcorrunknown1' => 1, + 'vignettingcorrunknown2' => 1, + 'vignettingcorrversion' => 1, + 'vignettingparams' => 1, + 'virtualimageheight' => 1, + 'virtualimagewidth' => 1, + 'virtualpage' => 1, + 'virtualpageunits' => 1, + 'visibleoutputs' => 1, + 'vistaidlistdata' => 1, + 'visualflightruleshud' => 1, + 'vmaphandling' => 1, + 'vmcoldropthresh' => 1, + 'vmcolthresh' => 1, + 'vmnbands' => 1, + 'vmpatchreslimit' => 1, + 'vmpixthresh' => 1, + 'vmwsize' => 1, + 'volumeblockcount' => 1, + 'volumeblocksize' => 1, + 'volumecreatedate' => 1, + 'volumeeffectivedate' => 1, + 'volumeexpirationdate' => 1, + 'volumeid' => 1, + 'volumelabel' => 1, + 'volumemodifydate' => 1, + 'volumename' => 1, + 'volumenormalization' => 1, + 'volumesetdiskcount' => 1, + 'volumesetdisknumber' => 1, + 'volumesetname' => 1, + 'volumesize' => 1, + 'vorbis' => 1, + 'vorbiscomment' => 1, + 'vorbisversion' => 1, + 'vp8bitstream' => 1, + 'vp8l' => 1, + 'vp8version' => 1, + 'vp8x' => 1, + 'vrd1' => 1, + 'vrd2' => 1, + 'vrdstamptool' => 1, + 'vrdversion' => 1, + 'vrinfo' => 1, + 'vrinfoversion' => 1, + 'vw96' => 1, + 'wangannotation' => 1, + 'wangtag1' => 1, + 'wangtag3' => 1, + 'wangtag4' => 1, + 'warning' => 1, + 'warpquadrilateral' => 1, + 'watched' => 1, + 'watercolorfilter' => 1, + 'watermark' => 1, + 'watermarktype' => 1, + 'watermarkurl' => 1, + 'wave' => 1, + 'wb_bluelevelauto' => 1, + 'wb_cfa0_leveldaylight' => 1, + 'wb_cfa1_leveldaylight' => 1, + 'wb_cfa2_leveldaylight' => 1, + 'wb_cfa3_leveldaylight' => 1, + 'wb_grbglevelsauto' => 1, + 'wb_grblevels' => 1, + 'wb_grblevelsauto' => 1, + 'wb_grblevelsstandard' => 1, + 'wb_grgblevels' => 1, + 'wb_grgblevelsauto' => 1, + 'wb_grgblevelscloudy' => 1, + 'wb_grgblevelsdaylight' => 1, + 'wb_grgblevelsdaylightfluor' => 1, + 'wb_grgblevelsdaywhitefluor' => 1, + 'wb_grgblevelslivingroomwarmwhitefluor' => 1, + 'wb_grgblevelstungsten' => 1, + 'wb_grgblevelswarmwhitefluor' => 1, + 'wb_grgblevelswhitefluorescent' => 1, + 'wb_redlevelauto' => 1, + 'wb_rgbcoeffsdaylight' => 1, + 'wb_rgbcoeffsflash' => 1, + 'wb_rgbcoeffsfluorescent' => 1, + 'wb_rgbcoeffstungsten' => 1, + 'wb_rgblevels2500k' => 1, + 'wb_rgblevels3200k' => 1, + 'wb_rgblevels4500k' => 1, + 'wb_rgblevels6000k' => 1, + 'wb_rgblevels8500k' => 1, + 'wb_rgblevelsasshot' => 1, + 'wb_rgblevelsauto' => 1, + 'wb_rgblevelscloudy' => 1, + 'wb_rgblevelscustom' => 1, + 'wb_rgblevelsdaylight' => 1, + 'wb_rgblevelsflash' => 1, + 'wb_rgblevelsfluorescent' => 1, + 'wb_rgblevelsfluorescentm1' => 1, + 'wb_rgblevelsfluorescentp1' => 1, + 'wb_rgblevelsfluorescentp2' => 1, + 'wb_rgblevelsshade' => 1, + 'wb_rgblevelstungsten' => 1, + 'wbadjdata' => 1, + 'wbblueasshot' => 1, + 'wbbluecloudy' => 1, + 'wbbluedaylight' => 1, + 'wbblueflash' => 1, + 'wbbluefluorescent' => 1, + 'wbbluetungsten' => 1, + 'wbgreenasshot' => 1, + 'wbgreencloudy' => 1, + 'wbgreendaylight' => 1, + 'wbgreenflash' => 1, + 'wbgreenfluorescent' => 1, + 'wbgreentungsten' => 1, + 'wbinfo' => 1, + 'wbinfo2' => 1, + 'wbinfoa100' => 1, + 'wblevels' => 1, + 'wbredasshot' => 1, + 'wbredcloudy' => 1, + 'wbreddaylight' => 1, + 'wbredflash' => 1, + 'wbredfluorescent' => 1, + 'wbredtungsten' => 1, + 'wcsprofiles' => 1, + 'webpage' => 1, + 'weight' => 1, + 'whitebalancematching' => 1, + 'whitebalancergb' => 1, + 'whitebalancetable' => 1, + 'whiteluminance' => 1, + 'whitepointx' => 1, + 'whitepointy' => 1, + 'whitesample' => 1, + 'whitesamplebits' => 1, + 'whitesampleheight' => 1, + 'whitesampleleftborder' => 1, + 'whitesampletopborder' => 1, + 'whitesamplewidth' => 1, + 'wide' => 1, + 'widthbytes' => 1, + 'widthresolution' => 1, + 'windowlocation' => 1, + 'windoworigin' => 1, + 'windoworiginauto' => 1, + 'windowsdevmode' => 1, + 'windowsfilename' => 1, + 'windowsize' => 1, + 'windowtarget' => 1, + 'wm_collectiongroupid' => 1, + 'wm_collectionid' => 1, + 'wm_contentid' => 1, + 'wm_mediaclassprimaryid' => 1, + 'wm_mediaclasssecondaryid' => 1, + 'wm_provider' => 1, + 'wmadrcaveragereference' => 1, + 'wmadrcaveragetarget' => 1, + 'wmadrcpeakreference' => 1, + 'wmadrcpeaktarget' => 1, + 'wmcollectiongroupid' => 1, + 'wmcollectionid' => 1, + 'wmcontentid' => 1, + 'wmshadowfilesourcedrmtype' => 1, + 'wmshadowfilesourcefiletype' => 1, + 'word97' => 1, + 'worddocument' => 1, + 'words' => 1, + 'workflowurl' => 1, + 'workingdirectory' => 1, + 'workingpath' => 1, + 'worldtime' => 1, + 'worldtocamera' => 1, + 'worldtondc' => 1, + 'wrapmodes' => 1, + 'writer' => 1, + 'writername' => 1, + 'writers' => 1, + 'writtenby' => 1, + 'wwsfamilyname' => 1, + 'wwssubfamilyname' => 1, + 'x' => 1, + 'xattrfinderinfo' => 1, + 'xattrmditemdownloadeddate' => 1, + 'xattrmditemfindercomment' => 1, + 'xattrmditemwherefroms' => 1, + 'xattrmdlabel' => 1, + 'xattrresourcefork' => 1, + 'xcfversion' => 1, + 'xclippathunits' => 1, + 'xheight' => 1, + 'xmag' => 1, + 'xmethod' => 1, + 'xmldata' => 1, + 'xmlfiletype' => 1, + 'xmp_profile' => 1, + 'xmpbj' => 1, + 'xmpdm' => 1, + 'xmpmm' => 1, + 'xmpnote' => 1, + 'xmpplus' => 1, + 'xmprights' => 1, + 'xmptpg' => 1, + 'xobject' => 1, + 'xoffset' => 1, + 'xp_dip_xml' => 1, + 'xtranslayout' => 1, + 'xylocation' => 1, + 'xyoffsetinfo' => 1, + 'yclippathunits' => 1, + 'ycrcbmatrix' => 1, + 'year' => 1, + 'ylevel' => 1, + 'ymag' => 1, + 'ymethod' => 1, + 'yoffset' => 1, + 'ytarget' => 1, + 'zipbitflag' => 1, + 'zipcompressedsize' => 1, + 'zipcompression' => 1, + 'zipcrc' => 1, + 'zipfilename' => 1, + 'zipmodifydate' => 1, + 'ziprequiredversion' => 1, + 'zipuncompressedsize' => 1, + 'zoom' => 1, + 'zoomedpreviewimage' => 1, + 'zoompos' => 1, + 'zoomposition' => 1, + 'zxif' => 1, +); + +# module names for writable Composite tags +my %compositeModules = ( + 'filenumber' => 'Image::ExifTool::Canon', + 'flash' => 'Image::ExifTool::XMP', + 'jpgfromraw' => 'Image::ExifTool::Exif', + 'originaldecisiondata' => 'Image::ExifTool::Canon', + 'otherimage' => 'Image::ExifTool::Exif', + 'previewimage' => 'Image::ExifTool::Exif', + 'rotation' => 'Image::ExifTool::QuickTime', + 'subseccreatedate' => 'Image::ExifTool::Exif', + 'subsecdatetimeoriginal' => 'Image::ExifTool::Exif', + 'subsecmodifydate' => 'Image::ExifTool::Exif', + 'thumbnailimage' => 'Image::ExifTool::Exif', +); + +#++++ End automatically generated code ++++ + +my %specialStruct = ( + NAMESPACE => 1, + STRUCT_NAME => 1, + TYPE => 1, + NOTES => 1, + GROUPS => 1, +); + +# insert any user-defined tags into our tag lookup +if (%Image::ExifTool::UserDefined) { + my @userTables = sort keys %Image::ExifTool::UserDefined; + while (@userTables) { + my $table = shift @userTables; + AddTags($Image::ExifTool::UserDefined{$table}, $table); + } +} + +# insert any other queued tags from plug-in modules +if (@Image::ExifTool::pluginTags) { + my $args; + foreach $args (@Image::ExifTool::pluginTags) { + AddTags($$args[0], $$args[1]); + } + undef @Image::ExifTool::pluginTags; +} + + +#------------------------------------------------------------------------------ +# Add tag names corresponding to flattened XMP tags for all structure fields +# Inputs: 0) tag table ref for flattened tags, 1) tagID, 2) lowercase tag name, +# 3) tag ID list ref, 4) reference to list of lowercase tag names +# 5) table number in lookup, 6) tagInfo hash for parent structure +# 7) tag ID of top-level stucture +# Notes: Used only for user-defined structures +sub AddFields($$$$$$;$$) +{ + my ($tagTablePtr, $tagID, $lcTag, $tagIDs, $lcTags, $tnum, $tagInfo, $baseID) = @_; + return if length($tagID) > 500; # avoid deep recursion + unless ($tagInfo) { + $tagInfo = $$tagTablePtr{$tagID}; + $baseID = $tagID; + } + my $strTable = $$tagInfo{Struct}; + unless (ref $strTable) { + my $strName = $strTable; + $strTable = $Image::ExifTool::UserDefined::xmpStruct{$strTable}; + $strTable or warn("No definition for structure '${strName}'\n"), return; + $$strTable{STRUCT_NAME} or $$strTable{STRUCT_NAME} = "XMP $strName"; + $$tagInfo{Struct} = $strTable; # replace name with hash ref + delete $$tagInfo{SubDirectory}; # deprecated use of SubDirectory in Struct tags + } + # inherit NAMESPACE from parent table if it doesn't exist + $$strTable{NAMESPACE} = $$tagTablePtr{NAMESPACE} unless exists $$strTable{NAMESPACE}; + my $field; + foreach $field (keys %$strTable) { + next if $specialStruct{$field}; + my $id = $tagID . ucfirst($field); + # use name of existing flattened tag if already defined + my $flatInfo = $$tagTablePtr{$id}; + my $fieldInfo = $$strTable{$field}; + my $flatName; + $flatName = $$fieldInfo{FlatName} if ref $fieldInfo eq 'HASH'; + $flatName or ($flatName = $field) =~ tr/-_a-zA-Z0-9//dc; # remove illegal characters + my $lc = ($flatInfo and $$flatInfo{Name}) ? lc $$flatInfo{Name} : $lcTag . lc($flatName); + my $copyID = $baseID; + push @$tagIDs, \$copyID, $id; + push @$lcTags, $lc, $lc; + next unless ref $fieldInfo eq 'HASH' and $$fieldInfo{Struct}; + # recursively add flattened tags for all sub-fields + AddFields($tagTablePtr, $id, $lc, $tagIDs, $lcTags, $tnum, $fieldInfo, $baseID); + } +} + +#------------------------------------------------------------------------------ +# Add tags to the lookup (for user-defined tags, etc) +# Inputs: 0) tag table ref, 1) table name +my %tableNumHash; +sub AddTags($$) +{ + my ($tagTablePtr, $table) = @_; + + # generate lookup for table numbers if not done already + unless (%tableNumHash) { + my $tnum = 0; + my $tbl; + foreach $tbl (@tableList) { + $tableNumHash{$tbl} = $tnum++; + } + } + my (@moreTables, %moreTableRefs); + for (;;) { + my $tnum = $tableNumHash{$table}; + unless (defined $tnum) { + # add new table to list + $tnum = scalar @tableList; + push @tableList, $table; + } + my $tagID; + foreach $tagID (Image::ExifTool::TagTableKeys($tagTablePtr)) { + my $newInfo = $$tagTablePtr{$tagID}; + if (ref $newInfo eq 'HASH') { + $$newInfo{Name} or $$newInfo{Name} = Image::ExifTool::MakeTagName($tagID); + # use new ID of tag in Composite table in case it changed + $tagID = $$newInfo{NewTagID} if defined $$newInfo{NewTagID}; + } else { + $newInfo = $$tagTablePtr{$tagID} = { Name => $newInfo }; + } + my $lcTag = lc $$newInfo{Name}; + my (@lcTags, @tagIDs, $existed, $isFlat); + # if this is a structure, add all flattened tag names to lookup + if ($$newInfo{Struct}) { + AddFields($tagTablePtr, $tagID, $lcTag, \@tagIDs, \@lcTags, $tnum); + } + # add tags to lookup even though we don't know if they are writable + # (to save speed by not having to load the module) +Tags: for (;;) { + my $lookup = $tagLookup{$lcTag}; + $lookup or $lookup = $tagLookup{$lcTag} = { }; + if ($$lookup{$tnum}) { + my $le = $$lookup{$tnum}; + my $ids = (ref $le eq 'ARRAY') ? $le : [ $le ]; + if (ref $tagID) { + # a reference points to the tag ID of the base structure for + # a flattened tag. There must be only one of these, + # and it must come first. + unshift @$ids, $tagID unless ref $$ids[0]; + # only add new tag ID if it didn't already exist + } elsif (grep /^$tagID$/, @$ids) { + $existed = 1 unless $isFlat; + } else { + push @$ids, $tagID; + } + # only update lookup if there is now more than one entry + $$lookup{$tnum} = $ids if @$ids > 1; + } else { + $$lookup{$tnum} = $tagID; + } + last unless @tagIDs; + for (;;) { + $tagID = shift @tagIDs; + $lcTag = shift @lcTags; + last unless $$tagTablePtr{$tagID}; # don't waste time if it exists + last Tags unless @tagIDs; + } + $isFlat = 1; + } + # add any new subdirectory tables (unless done already) + next if $existed or not $$newInfo{SubDirectory}; + my $subTable = $$newInfo{SubDirectory}{TagTable}; + next unless $subTable and not defined $tableNumHash{$subTable}; + next if $moreTableRefs{$subTable}; + no strict 'refs'; + next unless %$subTable; + # save new table to process after this one + push @moreTables, $subTable; + $moreTableRefs{$subTable} = \%$subTable; + # save source table name so we can load it when necessary + $$subTable{SRC_TABLE} = $table; + } + $table = shift @moreTables or last; + $tagTablePtr = $moreTableRefs{$table}; + } +} + +#------------------------------------------------------------------------------ +# Return true if the tag exists +# Inputs: 0) tag name (case insensitive) +# Returns: true if tag exists +sub TagExists($) +{ + my $tag = lc($_[0]); + return 1 if $tagExists{$tag} or $tagLookup{$tag}; + return 0; +} + +#------------------------------------------------------------------------------ +# Find information for writable tags (case insensitive) +# Inputs: 0) tag name (case insensitive) +# Returns: Scalar context: tag info or false if none found +# List context: list of all matching tagInfo hashes +sub FindTagInfo($) +{ + local $_; + my $tag = shift; + my $lcTag = lc($tag); + my ($tableNum, @tagInfoList, @lookups); + my $lookup = $tagLookup{$lcTag}; + if (not $lookup and $lcTag =~ /[?*]/) { + # allow wildcards in tag name + my $pat = $lcTag; + $pat =~ s/\*/[-\\w]*/g; + $pat =~ s/\?/[-\\w]/g; + my @tags = grep(/^$pat$/, keys %tagLookup); + if (@tags) { + push @lookups, $tagLookup{$_} foreach sort @tags; + $lookup = shift @lookups; + } + } + while ($lookup) { + foreach $tableNum (sort { $a <=> $b } keys %$lookup) { + my $table = GetTagTable($tableList[$tableNum]); + my $le = $$lookup{$tableNum}; + my ($tagID, $tagIDs); + if (ref $le eq 'ARRAY') { + $tagIDs = $le; + # if first entry is a reference, it indicates that this is a + # flattened tag and refers to the tag ID of the containing top-level + # structure, so now is the time to generate the flattened tags + if (ref $$tagIDs[0]) { + # (remove from the lookup since we only need to do this once) + my $rootIDPtr = shift @$tagIDs; + require Image::ExifTool::XMP; + Image::ExifTool::XMP::AddFlattenedTags($table, $$rootIDPtr); + } + } else { + $tagIDs = [ $le ]; + } + foreach $tagID (@$tagIDs) { + my @infoList = GetTagInfoList($table,$tagID); + unless (@infoList) { + my $reload; + # call write proc if it exists in case it adds tags to the table + my $writeProc = $table->{WRITE_PROC}; + $reload = 1 if $writeProc and &$writeProc(); + # load module with composite tag if necessary + my $compMod = $compositeModules{$lcTag}; + $reload = 1 if $compMod and eval "require $compMod"; + @infoList = GetTagInfoList($table,$tagID) if $reload; + } + if (@infoList == 1) { + push @tagInfoList, @infoList; + } elsif (@infoList > 1) { + my $tagInfo; + # must check tag list in case tags have different names + foreach $tagInfo (@infoList) { + next unless $lcTag eq lc($$tagInfo{Name}); + push @tagInfoList, $tagInfo; + } + } + } + } + $lookup = shift @lookups; + } + if (wantarray) { + return @tagInfoList; + } else { + return $tagInfoList[0]; + } +} + + +1; # end + +__END__ + +=head1 NAME + +Image::ExifTool::TagLookup - Fast lookup for ExifTool tags + +=head1 SYNOPSIS + +This module is required by Image::ExifTool for writing tags. + +=head1 DESCRIPTION + +Provides a fast, case insensitive lookup for tag names. + +=head1 AUTHOR + +Copyright 2003-2019, Phil Harvey (phil at owl.phy.queensu.ca) + +This library is free software; you can redistribute it and/or modify it +under the same terms as Perl itself. + +=head1 SEE ALSO + +L<Image::ExifTool(3pm)|Image::ExifTool>, +L<Image::ExifTool::BuildTagLookup(3pm)|Image::ExifTool::BuildTagLookup>, +L<Image::ExifTool::TagNames(3pm)|Image::ExifTool::TagNames> + +=cut diff --git a/lib/Image/ExifTool/TagNames.pod b/lib/Image/ExifTool/TagNames.pod new file mode 100644 index 0000000..a254dd8 --- /dev/null +++ b/lib/Image/ExifTool/TagNames.pod @@ -0,0 +1,33624 @@ + +=head1 NAME + +Image::ExifTool::TagNames - ExifTool tag name documentation + +=head1 DESCRIPTION + +This document contains a complete list of ExifTool tag names, organized into +tables based on information type. Tag names are used to reference specific +meta information extracted from or written to a file. + +=head1 TAG TABLES + +The tables listed below give the names of all tags recognized by ExifTool. + +B<Tag ID>, B<Index#> or B<Sequence> is given in the first column of each +table. A B<Tag ID> is the computer-readable equivalent of a tag name, and +is the identifier that is actually stored in the file. B<Index#> refers to +the offset of a value when found at a fixed position within a data block +(B<#> is the multiplier for calculating a byte offset: B<1>, B<2>, B<4> or +B<8>). These offsets may have a decimal part which is used only to +differentiate tags with values stored at the same position. B<Sequence> +gives the order of values for a serial data stream. + +A B<Tag Name> is the handle by which the information is accessed in +ExifTool. In some instances, more than one name may correspond to a single +tag ID. In these cases, the actual name used depends on the context in +which the information is found. Case is not significant for tag names. A +question mark (C<?>) after a tag name indicates that the information is +either not understood, not verified, or not very useful -- these tags are +not extracted by ExifTool unless the Unknown (-u) option is enabled. Be +aware that some tag names are different than the descriptions printed out by +default when extracting information with exiftool. To see the tag names +instead of the descriptions, use C<exiftool -s>. + +The B<Writable> column indicates whether the tag is writable by ExifTool. +Anything but a C<no> in this column means the tag is writable. A C<yes> +indicates writable information that is either unformatted or written using +the existing format. Other expressions give details about the information +format, and vary depending on the general type of information. The format +name may be followed by a number in square brackets to indicate the number +of values written, or the number of characters in a fixed-length string +(including a null terminator which is added if required). + +A plus sign (C<+>) after an entry in the B<Writable> column indicates a +I<List> tag which supports multiple values and allows individual values to +be added and deleted. A slash (C</>) indicates a tag that ExifTool will +I<Avoid> when writing. These tags are not created when writing if another +same-named tag may be created instead. To write these tags, the group +should be specified. A tilde (C<~>) indicates a tag this is writable only +when the print conversion is disabled (by setting PrintConv to 0, using the +-n option, or suffixing the tag name with a C<#> character). An exclamation +point (C<!>) indicates a tag that is considered I<Unsafe> to write under +normal circumstances. These tags are not written unless specified +explicitly (ie. not when wildcards or "all" are used), and care should be +taken when editing them manually since they may affect the way an image is +rendered. An asterisk (C<*>) indicates a I<Protected> tag which is not +writable directly, but is written automatically by ExifTool (often when a +corresponding L<Composite|Image::ExifTool::TagNames/Composite Tags> or +L<Extra|Image::ExifTool::TagNames/Extra Tags> tag is written). A colon +(C<:>) indicates a I<Mandatory> tag which may be added automatically when +writing. + +The HTML version of these tables also lists possible B<Values> for +discrete-valued tags, as well as B<Notes> for some tags. The B<Values> are +listed as the computer-readable and human-readable values on the left and +right hand side of an equals sign (C<=>) respectively. The human-readable +values are used by default when reading and writing, but the +computer-readable values may be accessed by disabling the value conversion +with the -n option on the command line, by setting the ValueConv option to 0 +in the API, or or on a per-tag basis by adding a hash (C<#>) after the tag +name. + +B<Note>: If you are familiar with common meta-information tag names, you may +find that some ExifTool tag names are different than expected. The usual +reason for this is to make the tag names more consistent across different +types of meta information. To determine a tag name, either consult this +documentation or run C<exiftool -s> on a file containing the information in +question. + +I<(This documentation is the result of years of research, testing and +reverse engineering, and is the most complete metadata tag list available +anywhere on the internet. It is provided not only for ExifTool users, but +more importantly as a public service to help augment the collective +knowledge, and is often used as a primary source of information in the +development of other metadata software. Please help keep this documentation +as accurate and complete as possible, and feed any new discoveries back to +ExifTool. A big thanks to everyone who has helped with this so far!)> + +=head2 JPEG Tags + +This table lists information extracted by ExifTool from JPEG images. See +L<https://www.w3.org/Graphics/JPEG/jfif3.pdf> for the JPEG specification. + + Tag ID Tag Name Writable + ------ -------- -------- + 'APP0' JFIF JFIF + JFXX JFIF Extension + CIFF CanonRaw + AVI1 JPEG AVI1 + Ocad JPEG Ocad + 'APP1' EXIF EXIF + ExtendedXMP XMP + XMP XMP + QVCI Casio QVCI + FLIR FLIR FFF + 'APP2' ICC_Profile ICC_Profile + FPXR FlashPix + MPF MPF + PreviewImage no + 'APP3' Meta Kodak Meta + Stim Stim + PreviewImage no + 'APP4' Scalado Scalado + FPXR FlashPix + PreviewImage no + 'APP5' RMETA Ricoh RMETA + SamsungUniqueID Samsung APP5 + PreviewImage no + 'APP6' EPPIM JPEG EPPIM + NITF JPEG NITF + HP_TDHD HP TDHD + GoPro GoPro GPMF + 'APP7' Pentax Pentax + Qualcomm Qualcomm + 'APP8' SPIFF JPEG SPIFF + 'APP9' MediaJukebox JPEG MediaJukebox + 'APP10' Comment no + 'APP11' JPEG-HDR JPEG HDR + 'APP12' PictureInfo APP12 PictureInfo + Ducky APP12 Ducky + 'APP13' Photoshop Photoshop + Adobe_CM JPEG AdobeCM + 'APP14' Adobe JPEG Adobe + 'APP15' GraphicConverter JPEG GraphConv + 'COM' Comment yes + 'DQT' DefineQuantizationTable no + 'SOF' StartOfFrame JPEG SOF + 'Trailer' AFCP AFCP + CanonVRD CanonVRD + FotoStation FotoStation + PhotoMechanic PhotoMechanic + MIE MIE + Samsung Samsung Trailer + PreviewImage yes + +=head3 JPEG AVI1 Tags + +This information may be found in APP0 of JPEG image data from AVI videos. + + Index1 Tag Name Writable + ------ -------- -------- + 0 InterleavedField no + +=head3 JPEG Ocad Tags + +Tags extracted from the JPEG APP0 "Ocad" segment (found in Photobucket +images). + + Tag ID Tag Name Writable + ------ -------- -------- + 'Rev' OcadRevision no + +=head3 JPEG EPPIM Tags + +APP6 is used in by the Toshiba PDR-M700 to store a TIFF structure containing +PrintIM information. + + Tag ID Tag Name Writable + ------ -------- -------- + 0xc4a5 PrintIM PrintIM + +=head3 JPEG NITF Tags + +Information in APP6 used by the National Imagery Transmission Format. See +L<http://www.gwg.nga.mil/ntb/baseline/docs/n010697/bwcguide25aug98.pdf> for +the official specification. + + Index1 Tag Name Writable + ------ -------- -------- + 0 NITFVersion no + 2 ImageFormat no + 3 BlocksPerRow no + 5 BlocksPerColumn no + 7 ImageColor no + 8 BitDepth no + 9 ImageClass no + 10 JPEGProcess no + 11 Quality no + 12 StreamColor no + 13 StreamBitDepth no + 14 Flags no + +=head3 JPEG SPIFF Tags + +This information is found in APP8 of SPIFF-style JPEG images (the "official" +yet rarely used JPEG file format standard: Still Picture Interchange File +Format). See L<http://www.jpeg.org/public/spiff.pdf> for the official +specification. + + Index1 Tag Name Writable + ------ -------- -------- + 0 SPIFFVersion no + 2 ProfileID no + 3 ColorComponents no + 6 ImageHeight no + 10 ImageWidth no + 14 ColorSpace no + 15 BitsPerSample no + 16 Compression no + 17 ResolutionUnit no + 18 YResolution no + 22 XResolution no + +=head3 JPEG MediaJukebox Tags + +Tags found in the XML metadata of the APP9 "Media Jukebox" segment. + + Tag Name Writable + -------- -------- + Album no + Caption no + Date no + Keywords no + Name no + People no + Places no + Tool_Name no + Tool_Version no + +=head3 JPEG HDR Tags + +Information extracted from APP11 of a JPEG-HDR image. + + Tag ID Tag Name Writable + ------ -------- -------- + 'RatioImage' RatioImage no + 'alp' Alpha no + 'bet' Beta no + 'cor' CorrectionMethod no + 'ln0' Ln0 no + 'ln1' Ln1 no + 's2n' S2n no + 'ver' JPEG-HDRVersion no + +=head3 JPEG AdobeCM Tags + +The APP13 "Adobe_CM" segment presumably contains color management +information, but the meaning of the data is currently unknown. If anyone +has an idea about what this means, please let me know. + + Index2 Tag Name Writable + ------ -------- -------- + 0 AdobeCMType no + +=head3 JPEG Adobe Tags + +The APP14 "Adobe" segment stores image encoding information for DCT filters. +This segment may be copied or deleted as a block using the Extra "Adobe" +tag, but note that it is not deleted by default when deleting all metadata +because it may affect the appearance of the image. + + Index2 Tag Name Writable + ------ -------- -------- + 0 DCTEncodeVersion no + 1 APP14Flags0 no + 2 APP14Flags1 no + 3 ColorTransform no + +=head3 JPEG GraphConv Tags + +APP15 is used by GraphicConverter to store JPEG quality. + + Tag ID Tag Name Writable + ------ -------- -------- + 'Q' Quality no + +=head3 JPEG SOF Tags + +This information is extracted from the JPEG Start Of Frame segment. + + Tag Name Writable + -------- -------- + BitsPerSample no + ColorComponents no + EncodingProcess no + ImageHeight no + ImageWidth no + YCbCrSubSampling no + +=head2 EXIF Tags + +EXIF stands for "Exchangeable Image File Format". This type of information +is formatted according to the TIFF specification, and may be found in JPG, +TIFF, PNG, JP2, PGF, MIFF, HDP, PSP and XCF images, as well as many +TIFF-based RAW images, and even some AVI and MOV videos. + +The EXIF meta information is organized into different Image File Directories +(IFD's) within an image. The names of these IFD's correspond to the +ExifTool family 1 group names. When writing EXIF information, the default +B<Group> listed below is used unless another group is specified. + +Mandatory tags (indicated by a colon after the B<Writable> type) may be +added automatically with default values when creating a new IFD, and the IFD +is removed automatically when deleting tags if only default-valued mandatory +tags remain. + +The table below lists all EXIF tags. Also listed are TIFF, DNG, HDP and +other tags which are not part of the EXIF specification, but may co-exist +with EXIF tags in some images. Tags which are part of the EXIF 2.31 +specification have an underlined B<Tag Name> in the HTML version of this +documentation. See +L<http://www.cipa.jp/std/documents/e/DC-008-Translation-2016-E.pdf> for the +official EXIF 2.31 specification. + + Tag ID Tag Name Group Writable + ------ -------- ----- -------- + 0x0001 InteropIndex InteropIFD string! + 0x0002 InteropVersion InteropIFD undef!: + 0x000b ProcessingSoftware IFD0 string + 0x00fe SubfileType IFD0 int32u! + 0x00ff OldSubfileType IFD0 int16u! + 0x0100 ImageWidth IFD0 int32u! + 0x0101 ImageHeight IFD0 int32u! + 0x0102 BitsPerSample IFD0 int16u[n]! + 0x0103 Compression IFD0 int16u!: + 0x0106 PhotometricInterpretation IFD0 int16u! + 0x0107 Thresholding IFD0 int16u! + 0x0108 CellWidth IFD0 int16u! + 0x0109 CellLength IFD0 int16u! + 0x010a FillOrder IFD0 int16u! + 0x010d DocumentName IFD0 string + 0x010e ImageDescription IFD0 string + 0x010f Make IFD0 string + 0x0110 Model IFD0 string + 0x0111 StripOffsets - no + PreviewImageStart IFD0 int32u* + PreviewImageStart All int32u* + JpgFromRawStart SubIFD2 int32u* + 0x0112 Orientation IFD0 int16u + 0x0115 SamplesPerPixel IFD0 int16u! + 0x0116 RowsPerStrip IFD0 int32u! + 0x0117 StripByteCounts - no + PreviewImageLength IFD0 int32u* + PreviewImageLength All int32u* + JpgFromRawLength SubIFD2 int32u* + 0x0118 MinSampleValue IFD0 int16u + 0x0119 MaxSampleValue IFD0 int16u + 0x011a XResolution IFD0 rational64u: + 0x011b YResolution IFD0 rational64u: + 0x011c PlanarConfiguration IFD0 int16u! + 0x011d PageName IFD0 string + 0x011e XPosition IFD0 rational64u + 0x011f YPosition IFD0 rational64u + 0x0120 FreeOffsets - no + 0x0121 FreeByteCounts - no + 0x0122 GrayResponseUnit IFD0 int16u + 0x0123 GrayResponseCurve - no + 0x0124 T4Options - no + 0x0125 T6Options - no + 0x0128 ResolutionUnit IFD0 int16u: + 0x0129 PageNumber IFD0 int16u[2] + 0x012c ColorResponseUnit - no + 0x012d TransferFunction IFD0 int16u[768]! + 0x0131 Software IFD0 string + 0x0132 ModifyDate IFD0 string + 0x013b Artist IFD0 string + 0x013c HostComputer IFD0 string + 0x013d Predictor IFD0 int16u! + 0x013e WhitePoint IFD0 rational64u[2] + 0x013f PrimaryChromaticities IFD0 rational64u[6] + 0x0140 ColorMap - no + 0x0141 HalftoneHints IFD0 int16u[2] + 0x0142 TileWidth IFD0 int32u! + 0x0143 TileLength IFD0 int32u! + 0x0144 TileOffsets - no + 0x0145 TileByteCounts - no + 0x0146 BadFaxLines - no + 0x0147 CleanFaxData - no + 0x0148 ConsecutiveBadFaxLines - no + 0x014a SubIFD - EXIF + A100DataOffset IFD0 no + 0x014c InkSet IFD0 int16u + 0x014d InkNames - no + 0x014e NumberofInks - no + 0x0150 DotRange - no + 0x0151 TargetPrinter IFD0 string + 0x0152 ExtraSamples - no + 0x0153 SampleFormat SubIFD no + 0x0154 SMinSampleValue - no + 0x0155 SMaxSampleValue - no + 0x0156 TransferRange - no + 0x0157 ClipPath - no + 0x0158 XClipPathUnits - no + 0x0159 YClipPathUnits - no + 0x015a Indexed - no + 0x015b JPEGTables - no + 0x015f OPIProxy - no + 0x0190 GlobalParametersIFD - EXIF + 0x0191 ProfileType - no + 0x0192 FaxProfile - no + 0x0193 CodingMethods - no + 0x0194 VersionYear - no + 0x0195 ModeNumber - no + 0x01b1 Decode - no + 0x01b2 DefaultImageColor - no + 0x01b3 T82Options - no + 0x01b5 JPEGTables - no + 0x0200 JPEGProc - no + 0x0201 ThumbnailOffset IFD1 int32u* + ThumbnailOffset IFD0 int32u* + ThumbnailOffset SubIFD int32u* + PreviewImageStart MakerNotes int32u* + PreviewImageStart IFD0 int32u* + JpgFromRawStart SubIFD int32u* + JpgFromRawStart IFD2 int32u* + OtherImageStart SubIFD1 int32u* + OtherImageStart SubIFD2 int32u* + OtherImageStart - no + 0x0202 ThumbnailLength IFD1 int32u* + ThumbnailLength IFD0 int32u* + ThumbnailLength SubIFD int32u* + PreviewImageLength MakerNotes int32u* + PreviewImageLength IFD0 int32u* + JpgFromRawLength SubIFD int32u* + JpgFromRawLength IFD2 int32u* + OtherImageLength SubIFD1 int32u* + OtherImageLength SubIFD2 int32u* + OtherImageLength - no + 0x0203 JPEGRestartInterval - no + 0x0205 JPEGLosslessPredictors - no + 0x0206 JPEGPointTransforms - no + 0x0207 JPEGQTables - no + 0x0208 JPEGDCTables - no + 0x0209 JPEGACTables - no + 0x0211 YCbCrCoefficients IFD0 rational64u[3]! + 0x0212 YCbCrSubSampling IFD0 int16u[2]! + 0x0213 YCbCrPositioning IFD0 int16u!: + 0x0214 ReferenceBlackWhite IFD0 rational64u[6] + 0x022f StripRowCounts - no + 0x02bc ApplicationNotes IFD0 XMP + 0x03e7 USPTOMiscellaneous - no + 0x1000 RelatedImageFileFormat InteropIFD string! + 0x1001 RelatedImageWidth InteropIFD int16u! + 0x1002 RelatedImageHeight InteropIFD int16u! + 0x4746 Rating IFD0 int16u/ + 0x4747 XP_DIP_XML - no + 0x4748 StitchInfo - Microsoft Stitch + 0x4749 RatingPercent IFD0 int16u/ + 0x7000 SonyRawFileType - no + 0x7010 SonyToneCurve - no + 0x7031 VignettingCorrection SubIFD int16s! + 0x7032 VignettingCorrParams SubIFD int16s[17]! + 0x7034 ChromaticAberrationCorrection SubIFD int16s! + 0x7035 ChromaticAberrationCorrParams SubIFD int16s[33]! + 0x7036 DistortionCorrection SubIFD int16s! + 0x7037 DistortionCorrParams SubIFD int16s[17]! + 0x800d ImageID - no + 0x80a3 WangTag1 - no + 0x80a4 WangAnnotation - no + 0x80a5 WangTag3 - no + 0x80a6 WangTag4 - no + 0x80b9 ImageReferencePoints - no + 0x80ba RegionXformTackPoint - no + 0x80bb WarpQuadrilateral - no + 0x80bc AffineTransformMat - no + 0x80e3 Matteing - no + 0x80e4 DataType - no + 0x80e5 ImageDepth - no + 0x80e6 TileDepth - no + 0x8214 ImageFullWidth - no + 0x8215 ImageFullHeight - no + 0x8216 TextureFormat - no + 0x8217 WrapModes - no + 0x8218 FovCot - no + 0x8219 MatrixWorldToScreen - no + 0x821a MatrixWorldToCamera - no + 0x827d Model2 - no + 0x828d CFARepeatPatternDim SubIFD int16u[2]! + 0x828e CFAPattern2 SubIFD int8u[n]! + 0x828f BatteryLevel - no + 0x8290 KodakIFD - Kodak IFD + 0x8298 Copyright IFD0 string + 0x829a ExposureTime ExifIFD rational64u + 0x829d FNumber ExifIFD rational64u + 0x82a5 MDFileTag - no + 0x82a6 MDScalePixel - no + 0x82a7 MDColorTable - no + 0x82a8 MDLabName - no + 0x82a9 MDSampleInfo - no + 0x82aa MDPrepDate - no + 0x82ab MDPrepTime - no + 0x82ac MDFileUnits - no + 0x830e PixelScale IFD0 double[3] + 0x8335 AdventScale - no + 0x8336 AdventRevision - no + 0x835c UIC1Tag - no + 0x835d UIC2Tag - no + 0x835e UIC3Tag - no + 0x835f UIC4Tag - no + 0x83bb IPTC-NAA IFD0 IPTC + 0x847e IntergraphPacketData - no + 0x847f IntergraphFlagRegisters - no + 0x8480 IntergraphMatrix IFD0 double[n] + 0x8481 INGRReserved - no + 0x8482 ModelTiePoint IFD0 double[n] + 0x84e0 Site - no + 0x84e1 ColorSequence - no + 0x84e2 IT8Header - no + 0x84e3 RasterPadding - no + 0x84e4 BitsPerRunLength - no + 0x84e5 BitsPerExtendedRunLength - no + 0x84e6 ColorTable - no + 0x84e7 ImageColorIndicator - no + 0x84e8 BackgroundColorIndicator - no + 0x84e9 ImageColorValue - no + 0x84ea BackgroundColorValue - no + 0x84eb PixelIntensityRange - no + 0x84ec TransparencyIndicator - no + 0x84ed ColorCharacterization - no + 0x84ee HCUsage - no + 0x84ef TrapIndicator - no + 0x84f0 CMYKEquivalent - no + 0x8546 SEMInfo IFD0 string + 0x8568 AFCP_IPTC - IPTC + 0x85b8 PixelMagicJBIGOptions - no + 0x85d7 JPLCartoIFD - no + 0x85d8 ModelTransform IFD0 double[16] + 0x8602 WB_GRGBLevels - no + 0x8606 LeafData - Leaf + 0x8649 PhotoshopSettings IFD0 Photoshop + 0x8769 ExifOffset IFD0 EXIF + 0x8773 ICC_Profile IFD0 ICC_Profile + 0x877f TIFF_FXExtensions - no + 0x8780 MultiProfiles - no + 0x8781 SharedData - no + 0x8782 T88Options - no + 0x87ac ImageLayer - no + 0x87af GeoTiffDirectory IFD0 undef + 0x87b0 GeoTiffDoubleParams IFD0 undef + 0x87b1 GeoTiffAsciiParams IFD0 string + 0x87be JBIGOptions - no + 0x8822 ExposureProgram ExifIFD int16u + 0x8824 SpectralSensitivity ExifIFD string + 0x8825 GPSInfo IFD0 GPS + 0x8827 ISO ExifIFD int16u[n] + 0x8828 Opto-ElectricConvFactor - no + 0x8829 Interlace - no + 0x882a TimeZoneOffset ExifIFD int16s[n] + 0x882b SelfTimerMode ExifIFD int16u + 0x8830 SensitivityType ExifIFD int16u + 0x8831 StandardOutputSensitivity ExifIFD int32u + 0x8832 RecommendedExposureIndex ExifIFD int32u + 0x8833 ISOSpeed ExifIFD int32u + 0x8834 ISOSpeedLatitudeyyy ExifIFD int32u + 0x8835 ISOSpeedLatitudezzz ExifIFD int32u + 0x885c FaxRecvParams - no + 0x885d FaxSubAddress - no + 0x885e FaxRecvTime - no + 0x8871 FedexEDR - no + 0x888a LeafSubIFD - Leaf SubIFD + 0x9000 ExifVersion ExifIFD undef: + 0x9003 DateTimeOriginal ExifIFD string + 0x9004 CreateDate ExifIFD string + 0x9009 GooglePlusUploadCode ExifIFD undef[n] + 0x9010 OffsetTime ExifIFD string + 0x9011 OffsetTimeOriginal ExifIFD string + 0x9012 OffsetTimeDigitized ExifIFD string + 0x9101 ComponentsConfiguration ExifIFD undef[4]!: + 0x9102 CompressedBitsPerPixel ExifIFD rational64u! + 0x9201 ShutterSpeedValue ExifIFD rational64s + 0x9202 ApertureValue ExifIFD rational64u + 0x9203 BrightnessValue ExifIFD rational64s + 0x9204 ExposureCompensation ExifIFD rational64s + 0x9205 MaxApertureValue ExifIFD rational64u + 0x9206 SubjectDistance ExifIFD rational64u + 0x9207 MeteringMode ExifIFD int16u + 0x9208 LightSource ExifIFD int16u + 0x9209 Flash ExifIFD int16u + 0x920a FocalLength ExifIFD rational64u + 0x920b FlashEnergy - no + 0x920c SpatialFrequencyResponse - no + 0x920d Noise - no + 0x920e FocalPlaneXResolution - no + 0x920f FocalPlaneYResolution - no + 0x9210 FocalPlaneResolutionUnit - no + 0x9211 ImageNumber ExifIFD int32u + 0x9212 SecurityClassification ExifIFD string + 0x9213 ImageHistory ExifIFD string + 0x9214 SubjectArea ExifIFD int16u[n] + 0x9215 ExposureIndex - no + 0x9216 TIFF-EPStandardID - no + 0x9217 SensingMethod - no + 0x923a CIP3DataFile - no + 0x923b CIP3Sheet - no + 0x923c CIP3Side - no + 0x923f StoNits - no + 0x927c MakerNoteApple ExifIFD Apple + MakerNoteNikon ExifIFD Nikon + MakerNoteCanon ExifIFD Canon + MakerNoteCasio ExifIFD Casio + MakerNoteCasio2 ExifIFD Casio Type2 + MakerNoteDJI ExifIFD DJI + MakerNoteFLIR ExifIFD FLIR + MakerNoteFujiFilm ExifIFD FujiFilm + MakerNoteGE ExifIFD GE + MakerNoteGE2 ExifIFD FujiFilm + MakerNoteHasselblad ExifIFD Unknown + MakerNoteHP ExifIFD HP + MakerNoteHP2 ExifIFD HP Type2 + MakerNoteHP4 ExifIFD HP Type4 + MakerNoteHP6 ExifIFD HP Type6 + MakerNoteISL ExifIFD Unknown + MakerNoteJVC ExifIFD JVC + MakerNoteJVCText ExifIFD JVC Text + MakerNoteKodak1a ExifIFD Kodak + MakerNoteKodak1b ExifIFD Kodak + MakerNoteKodak2 ExifIFD Kodak Type2 + MakerNoteKodak3 ExifIFD Kodak Type3 + MakerNoteKodak4 ExifIFD Kodak Type4 + MakerNoteKodak5 ExifIFD Kodak Type5 + MakerNoteKodak6a ExifIFD Kodak Type6 + MakerNoteKodak6b ExifIFD Kodak Type6 + MakerNoteKodak7 ExifIFD Kodak Type7 + MakerNoteKodak8a ExifIFD Kodak Type8 + MakerNoteKodak8b ExifIFD Kodak Type8 + MakerNoteKodak8c ExifIFD Kodak Type8 + MakerNoteKodak9 ExifIFD Kodak Type9 + MakerNoteKodak10 ExifIFD Kodak Type10 + MakerNoteKodak11 ExifIFD Kodak Type11 + MakerNoteKodak12 ExifIFD Kodak Type11 + MakerNoteKodakUnknown ExifIFD Kodak Unknown + MakerNoteKyocera ExifIFD Unknown + MakerNoteMinolta ExifIFD Minolta + MakerNoteMinolta2 ExifIFD Olympus + MakerNoteMinolta3 ExifIFD undef + MakerNoteMotorola ExifIFD Motorola + MakerNoteNikon2 ExifIFD Nikon Type2 + MakerNoteNikon3 ExifIFD Nikon + MakerNoteNintendo ExifIFD Nintendo + MakerNoteOlympus ExifIFD Olympus + MakerNoteOlympus2 ExifIFD Olympus + MakerNoteLeica ExifIFD Panasonic + MakerNoteLeica2 ExifIFD Panasonic Leica2 + MakerNoteLeica3 ExifIFD Panasonic Leica3 + MakerNoteLeica4 ExifIFD Panasonic Leica4 + MakerNoteLeica5 ExifIFD Panasonic Leica5 + MakerNoteLeica6 ExifIFD Panasonic Leica6 + MakerNoteLeica7 ExifIFD Panasonic Leica6 + MakerNoteLeica8 ExifIFD Panasonic Leica5 + MakerNoteLeica9 ExifIFD Panasonic Leica9 + MakerNoteLeica10 ExifIFD Panasonic + MakerNotePanasonic ExifIFD Panasonic + MakerNotePanasonic2 ExifIFD Panasonic Type2 + MakerNotePanasonic3 ExifIFD Panasonic + MakerNotePentax ExifIFD Pentax + MakerNotePentax2 ExifIFD Pentax Type2 + MakerNotePentax3 ExifIFD Casio Type2 + MakerNotePentax4 ExifIFD Pentax Type4 + MakerNotePentax5 ExifIFD Pentax + MakerNotePentax6 ExifIFD Pentax S1 + MakerNotePhaseOne ExifIFD PhaseOne + MakerNoteReconyx ExifIFD Reconyx + MakerNoteReconyx2 ExifIFD Reconyx Type2 + MakerNoteReconyx3 ExifIFD Reconyx Type3 + MakerNoteRicohPentax ExifIFD Pentax + MakerNoteRicoh ExifIFD Ricoh + MakerNoteRicoh2 ExifIFD Ricoh Type2 + MakerNoteRicohText ExifIFD Ricoh Text + MakerNoteSamsung1a ExifIFD undef + MakerNoteSamsung1b ExifIFD Samsung + MakerNoteSamsung2 ExifIFD Samsung Type2 + MakerNoteSanyo ExifIFD Sanyo + MakerNoteSanyoC4 ExifIFD Sanyo + MakerNoteSanyoPatch ExifIFD Sanyo + MakerNoteSigma ExifIFD Sigma + MakerNoteSony ExifIFD Sony + MakerNoteSony2 ExifIFD Olympus + MakerNoteSony3 ExifIFD Olympus + MakerNoteSony4 ExifIFD Sony PIC + MakerNoteSony5 ExifIFD Sony + MakerNoteSonyEricsson ExifIFD Sony Ericsson + MakerNoteSonySRF ExifIFD Sony SRF + MakerNoteUnknownText ExifIFD undef + MakerNoteUnknownBinary ExifIFD undef + MakerNoteUnknown ExifIFD Unknown + 0x9286 UserComment ExifIFD undef + 0x9290 SubSecTime ExifIFD string + 0x9291 SubSecTimeOriginal ExifIFD string + 0x9292 SubSecTimeDigitized ExifIFD string + 0x932f MSDocumentText - no + 0x9330 MSPropertySetStorage - no + 0x9331 MSDocumentTextPosition - no + 0x935c ImageSourceData IFD0 Photoshop DocumentData + 0x9400 AmbientTemperature ExifIFD rational64s + 0x9401 Humidity ExifIFD rational64u + 0x9402 Pressure ExifIFD rational64u + 0x9403 WaterDepth ExifIFD rational64s + 0x9404 Acceleration ExifIFD rational64u + 0x9405 CameraElevationAngle ExifIFD rational64s + 0x9c9b XPTitle IFD0 int8u + 0x9c9c XPComment IFD0 int8u + 0x9c9d XPAuthor IFD0 int8u + 0x9c9e XPKeywords IFD0 int8u + 0x9c9f XPSubject IFD0 int8u + 0xa000 FlashpixVersion ExifIFD undef: + 0xa001 ColorSpace ExifIFD int16u: + 0xa002 ExifImageWidth ExifIFD int16u: + 0xa003 ExifImageHeight ExifIFD int16u: + 0xa004 RelatedSoundFile ExifIFD string + 0xa005 InteropOffset - EXIF + 0xa010 SamsungRawPointersOffset - no + 0xa011 SamsungRawPointersLength - no + 0xa101 SamsungRawByteOrder - no + 0xa102 SamsungRawUnknown? - no + 0xa20b FlashEnergy ExifIFD rational64u + 0xa20c SpatialFrequencyResponse - no + 0xa20d Noise - no + 0xa20e FocalPlaneXResolution ExifIFD rational64u + 0xa20f FocalPlaneYResolution ExifIFD rational64u + 0xa210 FocalPlaneResolutionUnit ExifIFD int16u + 0xa211 ImageNumber - no + 0xa212 SecurityClassification - no + 0xa213 ImageHistory - no + 0xa214 SubjectLocation ExifIFD int16u[2] + 0xa215 ExposureIndex ExifIFD rational64u + 0xa216 TIFF-EPStandardID - no + 0xa217 SensingMethod ExifIFD int16u + 0xa300 FileSource ExifIFD undef + 0xa301 SceneType ExifIFD undef + 0xa302 CFAPattern ExifIFD undef + 0xa401 CustomRendered ExifIFD int16u + 0xa402 ExposureMode ExifIFD int16u + 0xa403 WhiteBalance ExifIFD int16u + 0xa404 DigitalZoomRatio ExifIFD rational64u + 0xa405 FocalLengthIn35mmFormat ExifIFD int16u + 0xa406 SceneCaptureType ExifIFD int16u + 0xa407 GainControl ExifIFD int16u + 0xa408 Contrast ExifIFD int16u + 0xa409 Saturation ExifIFD int16u + 0xa40a Sharpness ExifIFD int16u + 0xa40b DeviceSettingDescription - no + 0xa40c SubjectDistanceRange ExifIFD int16u + 0xa420 ImageUniqueID ExifIFD string + 0xa430 OwnerName ExifIFD string + 0xa431 SerialNumber ExifIFD string + 0xa432 LensInfo ExifIFD rational64u[4] + 0xa433 LensMake ExifIFD string + 0xa434 LensModel ExifIFD string + 0xa435 LensSerialNumber ExifIFD string + 0xa480 GDALMetadata - no + 0xa481 GDALNoData - no + 0xa500 Gamma ExifIFD rational64u + 0xafc0 ExpandSoftware - no + 0xafc1 ExpandLens - no + 0xafc2 ExpandFilm - no + 0xafc3 ExpandFilterLens - no + 0xafc4 ExpandScanner - no + 0xafc5 ExpandFlashLamp - no + 0xbc01 PixelFormat - no + 0xbc02 Transformation - no + 0xbc03 Uncompressed - no + 0xbc04 ImageType - no + 0xbc80 ImageWidth - no + 0xbc81 ImageHeight - no + 0xbc82 WidthResolution - no + 0xbc83 HeightResolution - no + 0xbcc0 ImageOffset - no + 0xbcc1 ImageByteCount - no + 0xbcc2 AlphaOffset - no + 0xbcc3 AlphaByteCount - no + 0xbcc4 ImageDataDiscard - no + 0xbcc5 AlphaDataDiscard - no + 0xc427 OceScanjobDesc - no + 0xc428 OceApplicationSelector - no + 0xc429 OceIDNumber - no + 0xc42a OceImageLogic - no + 0xc44f Annotations - no + 0xc4a5 PrintIM IFD0 PrintIM + 0xc573 OriginalFileName - no + 0xc580 USPTOOriginalContentType - no + 0xc5e0 CR2CFAPattern - no + 0xc612 DNGVersion IFD0 int8u[4]! + 0xc613 DNGBackwardVersion IFD0 int8u[4]! + 0xc614 UniqueCameraModel IFD0 string + 0xc615 LocalizedCameraModel IFD0 string + 0xc616 CFAPlaneColor SubIFD no + 0xc617 CFALayout SubIFD no + 0xc618 LinearizationTable SubIFD int16u[n]! + 0xc619 BlackLevelRepeatDim SubIFD int16u[2]! + 0xc61a BlackLevel SubIFD rational64u[n]! + 0xc61b BlackLevelDeltaH SubIFD rational64s[n]! + 0xc61c BlackLevelDeltaV SubIFD rational64s[n]! + 0xc61d WhiteLevel SubIFD int32u[n]! + 0xc61e DefaultScale SubIFD rational64u[2]! + 0xc61f DefaultCropOrigin SubIFD int32u[2]! + 0xc620 DefaultCropSize SubIFD int32u[2]! + 0xc621 ColorMatrix1 IFD0 rational64s[n]! + 0xc622 ColorMatrix2 IFD0 rational64s[n]! + 0xc623 CameraCalibration1 IFD0 rational64s[n]! + 0xc624 CameraCalibration2 IFD0 rational64s[n]! + 0xc625 ReductionMatrix1 IFD0 rational64s[n]! + 0xc626 ReductionMatrix2 IFD0 rational64s[n]! + 0xc627 AnalogBalance IFD0 rational64u[n]! + 0xc628 AsShotNeutral IFD0 rational64u[n]! + 0xc629 AsShotWhiteXY IFD0 rational64u[2]! + 0xc62a BaselineExposure IFD0 rational64s! + 0xc62b BaselineNoise IFD0 rational64u! + 0xc62c BaselineSharpness IFD0 rational64u! + 0xc62d BayerGreenSplit SubIFD int32u! + 0xc62e LinearResponseLimit IFD0 rational64u! + 0xc62f CameraSerialNumber IFD0 string + 0xc630 DNGLensInfo IFD0 rational64u[4] + 0xc631 ChromaBlurRadius SubIFD rational64u! + 0xc632 AntiAliasStrength SubIFD rational64u! + 0xc633 ShadowScale IFD0 rational64u! + 0xc634 SR2Private IFD0 Sony SR2Private + DNGAdobeData IFD0 DNG AdobeData + MakerNotePentax IFD0 Pentax + MakerNotePentax5 IFD0 Pentax + MakerNoteRicohPentax IFD0 Pentax + DNGPrivateData IFD0 int8u! + 0xc635 MakerNoteSafety IFD0 int16u + 0xc640 RawImageSegmentation - no + 0xc65a CalibrationIlluminant1 IFD0 int16u! + 0xc65b CalibrationIlluminant2 IFD0 int16u! + 0xc65c BestQualityScale SubIFD rational64u! + 0xc65d RawDataUniqueID IFD0 int8u[16]! + 0xc660 AliasLayerMetadata - no + 0xc68b OriginalRawFileName IFD0 string! + 0xc68c OriginalRawFileData IFD0 DNG OriginalRaw + 0xc68d ActiveArea SubIFD int32u[4]! + 0xc68e MaskedAreas SubIFD int32u[n]! + 0xc68f AsShotICCProfile IFD0 ICC_Profile + 0xc690 AsShotPreProfileMatrix IFD0 rational64s[n]! + 0xc691 CurrentICCProfile IFD0 ICC_Profile + 0xc692 CurrentPreProfileMatrix IFD0 rational64s[n]! + 0xc6bf ColorimetricReference IFD0 int16u! + 0xc6c5 SRawType IFD0 no + 0xc6d2 PanasonicTitle IFD0 undef + 0xc6d3 PanasonicTitle2 IFD0 undef + 0xc6f3 CameraCalibrationSig IFD0 string! + 0xc6f4 ProfileCalibrationSig IFD0 string! + 0xc6f5 ProfileIFD IFD0 EXIF + 0xc6f6 AsShotProfileName IFD0 string! + 0xc6f7 NoiseReductionApplied SubIFD rational64u! + 0xc6f8 ProfileName IFD0 string! + 0xc6f9 ProfileHueSatMapDims IFD0 int32u[3]! + 0xc6fa ProfileHueSatMapData1 IFD0 float[n]! + 0xc6fb ProfileHueSatMapData2 IFD0 float[n]! + 0xc6fc ProfileToneCurve IFD0 float[n]! + 0xc6fd ProfileEmbedPolicy IFD0 int32u! + 0xc6fe ProfileCopyright IFD0 string! + 0xc714 ForwardMatrix1 IFD0 rational64s[n]! + 0xc715 ForwardMatrix2 IFD0 rational64s[n]! + 0xc716 PreviewApplicationName IFD0 string! + 0xc717 PreviewApplicationVersion IFD0 string! + 0xc718 PreviewSettingsName IFD0 string! + 0xc719 PreviewSettingsDigest IFD0 int8u! + 0xc71a PreviewColorSpace IFD0 int32u! + 0xc71b PreviewDateTime IFD0 string! + 0xc71c RawImageDigest IFD0 int8u[16]! + 0xc71d OriginalRawFileDigest IFD0 int8u[16]! + 0xc71e SubTileBlockSize - no + 0xc71f RowInterleaveFactor - no + 0xc725 ProfileLookTableDims IFD0 int32u[3]! + 0xc726 ProfileLookTableData IFD0 float[n]! + 0xc740 OpcodeList1 SubIFD undef! + 0xc741 OpcodeList2 SubIFD undef! + 0xc74e OpcodeList3 SubIFD undef! + 0xc761 NoiseProfile SubIFD double[n]! + 0xc763 TimeCodes IFD0 int8u[n] + 0xc764 FrameRate IFD0 rational64s + 0xc772 TStop IFD0 rational64u[n] + 0xc789 ReelName IFD0 string + 0xc791 OriginalDefaultFinalSize IFD0 int32u[2]! + 0xc792 OriginalBestQualitySize IFD0 int32u[2]! + 0xc793 OriginalDefaultCropSize IFD0 rational64u[2]! + 0xc7a1 CameraLabel IFD0 string + 0xc7a3 ProfileHueSatMapEncoding IFD0 int32u! + 0xc7a4 ProfileLookTableEncoding IFD0 int32u! + 0xc7a5 BaselineExposureOffset IFD0 rational64s! + 0xc7a6 DefaultBlackRender IFD0 int32u! + 0xc7a7 NewRawImageDigest IFD0 int8u[16]! + 0xc7a8 RawToPreviewGain IFD0 double! + 0xc7aa CacheVersion SubIFD2 int32u! + 0xc7b5 DefaultUserCrop SubIFD rational64u[4]! + 0xc7d5 NikonNEFInfo - Nikon NEFInfo + 0xea1c Padding ExifIFD undef! + 0xea1d OffsetSchema ExifIFD int32s! + 0xfde8 OwnerName ExifIFD string/ + 0xfde9 SerialNumber ExifIFD string/ + 0xfdea Lens ExifIFD string/ + 0xfe00 KDC_IFD - Kodak KDC_IFD + 0xfe4c RawFile ExifIFD string/ + 0xfe4d Converter ExifIFD string/ + 0xfe4e WhiteBalance ExifIFD string/ + 0xfe51 Exposure ExifIFD string/ + 0xfe52 Shadows ExifIFD string/ + 0xfe53 Brightness ExifIFD string/ + 0xfe54 Contrast ExifIFD string/ + 0xfe55 Saturation ExifIFD string/ + 0xfe56 Sharpness ExifIFD string/ + 0xfe57 Smoothness ExifIFD string/ + 0xfe58 MoireFilter ExifIFD string/ + +=head2 IPTC Tags + +The tags listed below are part of the International Press Telecommunications +Council (IPTC) and the Newspaper Association of America (NAA) Information +Interchange Model (IIM). This is an older meta information format, slowly +being phased out in favor of XMP -- the newer IPTCCore specification uses +XMP format. IPTC information may be found in JPG, TIFF, PNG, MIFF, PS, PDF, +PSD, XCF and DNG images. + +IPTC information is separated into different records, each of which has its +own set of tags. See +L<http://www.iptc.org/std/IIM/4.1/specification/IIMV4.1.pdf> for the +official IPTC IIM specification. + +This specification dictates a length for ASCII (C<string> or C<digits>) and +binary (C<undef>) values. These lengths are given in square brackets after +the B<Writable> format name. For tags where a range of lengths is allowed, +the minimum and maximum lengths are separated by a comma within the +brackets. When writing, ExifTool issues a minor warning and truncates the +value if it is longer than allowed by the IPTC specification. Minor errors +may be ignored with the IgnoreMinorErrors (-m) option, allowing longer +values to be written, but beware that values like this may cause problems +for some other IPTC readers. ExifTool will happily read IPTC values of any +length. + +Separate IPTC date and time tags may be written with a combined date/time +value and ExifTool automagically takes the appropriate part of the date/time +string depending on whether a date or time tag is being written. This is +very useful when copying date/time values to IPTC from other metadata +formats. + +IPTC time values include a timezone offset. If written with a value which +doesn't include a timezone then the current local timezone offset is used +(unless written with a combined date/time, in which case the local timezone +offset at the specified date/time is used, which may be different due to +changes in daylight savings time). + +Note that it is not uncommon for IPTC to be found in non-standard locations +in JPEG and TIFF-based images. When reading, the family 1 group name has a +number added for non-standard IPTC ("IPTC2", "IPTC3", etc), but when writing +only "IPTC" may be specified as the group. To keep the IPTC consistent, +ExifTool updates tags in all existing IPTC locations, but will create a new +IPTC group only in the standard location. + + Record Tag Name Writable + ------ -------- -------- + 1 IPTCEnvelope IPTC EnvelopeRecord + 2 IPTCApplication IPTC ApplicationRecord + 3 IPTCNewsPhoto IPTC NewsPhoto + 7 IPTCPreObjectData IPTC PreObjectData + 8 IPTCObjectData IPTC ObjectData + 9 IPTCPostObjectData IPTC PostObjectData + 240 IPTCFotoStation IPTC FotoStation + +=head3 IPTC EnvelopeRecord Tags + + Tag ID Tag Name Writable + ------ -------- -------- + 0 EnvelopeRecordVersion int16u: + 5 Destination string[0,1024]+ + 20 FileFormat int16u + 22 FileVersion int16u + 30 ServiceIdentifier string[0,10] + 40 EnvelopeNumber digits[8] + 50 ProductID string[0,32]+ + 60 EnvelopePriority digits[1] + 70 DateSent digits[8] + 80 TimeSent string[11] + 90 CodedCharacterSet string[0,32]! + 100 UniqueObjectName string[14,80] + 120 ARMIdentifier int16u + 122 ARMVersion int16u + +=head3 IPTC ApplicationRecord Tags + + Tag ID Tag Name Writable + ------ -------- -------- + 0 ApplicationRecordVersion int16u: + 3 ObjectTypeReference string[3,67] + 4 ObjectAttributeReference string[4,68]+ + 5 ObjectName string[0,64] + 7 EditStatus string[0,64] + 8 EditorialUpdate digits[2] + 10 Urgency digits[1] + 12 SubjectReference string[13,236]+ + 15 Category string[0,3] + 20 SupplementalCategories string[0,32]+ + 22 FixtureIdentifier string[0,32] + 25 Keywords string[0,64]+ + 26 ContentLocationCode string[3]+ + 27 ContentLocationName string[0,64]+ + 30 ReleaseDate digits[8] + 35 ReleaseTime string[11] + 37 ExpirationDate digits[8] + 38 ExpirationTime string[11] + 40 SpecialInstructions string[0,256] + 42 ActionAdvised digits[2] + 45 ReferenceService string[0,10]+ + 47 ReferenceDate digits[8]+ + 50 ReferenceNumber digits[8]+ + 55 DateCreated digits[8] + 60 TimeCreated string[11] + 62 DigitalCreationDate digits[8] + 63 DigitalCreationTime string[11] + 65 OriginatingProgram string[0,32] + 70 ProgramVersion string[0,10] + 75 ObjectCycle string[1] + 80 By-line string[0,32]+ + 85 By-lineTitle string[0,32]+ + 90 City string[0,32] + 92 Sub-location string[0,32] + 95 Province-State string[0,32] + 100 Country-PrimaryLocationCode string[3] + 101 Country-PrimaryLocationName string[0,64] + 103 OriginalTransmissionReference string[0,32] + 105 Headline string[0,256] + 110 Credit string[0,32] + 115 Source string[0,32] + 116 CopyrightNotice string[0,128] + 118 Contact string[0,128]+ + 120 Caption-Abstract string[0,2000] + 121 LocalCaption string[0,256] + 122 Writer-Editor string[0,32]+ + 125 RasterizedCaption undef[7360] + 130 ImageType string[2] + 131 ImageOrientation string[1] + 135 LanguageIdentifier string[2,3] + 150 AudioType string[2] + 151 AudioSamplingRate digits[6] + 152 AudioSamplingResolution digits[2] + 153 AudioDuration digits[6] + 154 AudioOutcue string[0,64] + 184 JobID string[0,64] + 185 MasterDocumentID string[0,256] + 186 ShortDocumentID string[0,64] + 187 UniqueDocumentID string[0,128] + 188 OwnerID string[0,128] + 200 ObjectPreviewFileFormat int16u + 201 ObjectPreviewFileVersion int16u + 202 ObjectPreviewData undef[0,256000] + 221 Prefs string[0,64] + 225 ClassifyState string[0,64] + 228 SimilarityIndex string[0,32] + 230 DocumentNotes string[0,1024] + 231 DocumentHistory string[0,256] + 232 ExifCameraInfo string[0,4096] + 255 CatalogSets string[0,256]+ + +=head3 IPTC NewsPhoto Tags + + Tag ID Tag Name Writable + ------ -------- -------- + 0 NewsPhotoVersion int16u: + 10 IPTCPictureNumber string[16] + 20 IPTCImageWidth int16u + 30 IPTCImageHeight int16u + 40 IPTCPixelWidth int16u + 50 IPTCPixelHeight int16u + 55 SupplementalType int8u + 60 ColorRepresentation int16u + 64 InterchangeColorSpace int8u + 65 ColorSequence int8u + 66 ICC_Profile no + 70 ColorCalibrationMatrix no + 80 LookupTable no + 84 NumIndexEntries int16u + 85 ColorPalette no + 86 IPTCBitsPerSample int8u + 90 SampleStructure int8u + 100 ScanningDirection int8u + 102 IPTCImageRotation int8u + 110 DataCompressionMethod int32u + 120 QuantizationMethod int8u + 125 EndPoints no + 130 ExcursionTolerance int8u + 135 BitsPerComponent int8u + 140 MaximumDensityRange int16u + 145 GammaCompensatedValue int16u + +=head3 IPTC PreObjectData Tags + + Tag ID Tag Name Writable + ------ -------- -------- + 10 SizeMode no + 20 MaxSubfileSize no + 90 ObjectSizeAnnounced no + 95 MaximumObjectSize no + +=head3 IPTC ObjectData Tags + + Tag ID Tag Name Writable + ------ -------- -------- + 10 SubFile no+ + +=head3 IPTC PostObjectData Tags + + Tag ID Tag Name Writable + ------ -------- -------- + 10 ConfirmedObjectSize no + +=head3 IPTC FotoStation Tags + + Tag ID Tag Name Writable + ------ -------- -------- + [no tags known] + +=head2 DJI Tags + +This table lists tags found in the maker notes of images from some DJI +Phantom drones. + + Tag ID Tag Name Writable + ------ -------- -------- + 0x0001 Make string + 0x0003 SpeedX float + 0x0004 SpeedY float + 0x0005 SpeedZ float + 0x0006 Pitch float + 0x0007 Yaw float + 0x0008 Roll float + 0x0009 CameraPitch float + 0x000a CameraYaw float + 0x000b CameraRoll float + +=head3 DJI XMP Tags + +XMP tags used by DJI for images from drones. + +These tags belong to the ExifTool XMP-drone-dji family 1 group. + + Tag Name Writable + -------- -------- + AbsoluteAltitude real + CalibratedFocalLength real + CalibratedOpticalCenterX real + CalibratedOpticalCenterY real + CamReverse string + DewarpData string + DewarpFlag string + FlightPitchDegree real + FlightRollDegree real + FlightXSpeed real + FlightYSpeed real + FlightYawDegree real + FlightZSpeed real + GPSLatitude real/ + GPSLongitude real/ + GPSLongtitude real + GimbalPitchDegree real + GimbalReverse string + GimbalRollDegree real + GimbalYawDegree real + Latitude real + Longitude real + RelativeAltitude real + RtkFlag string + RtkStdHgt real + RtkStdLat real + RtkStdLon real + SelfData string + +=head2 XMP Tags + +XMP stands for "Extensible Metadata Platform", an XML/RDF-based metadata +format which is being pushed by Adobe. Information in this format can be +embedded in many different image file types including JPG, JP2, TIFF, GIF, +EPS, PDF, PSD, IND, INX, PNG, DJVU, SVG, PGF, MIFF, XCF, CRW, DNG and a +variety of proprietary TIFF-based RAW images, as well as MOV, AVI, ASF, WMV, +FLV, SWF and MP4 videos, and WMA and audio formats supporting ID3v2 +information. + +The XMP B<Tag ID>'s aren't listed because in most cases they are identical +to the B<Tag Name> (aside from differences in case). Tags with different +ID's are mentioned in the B<Notes> column of the HTML version of this +document. + +All XMP information is stored as character strings. The B<Writable> column +specifies the information format: C<string> is an unformatted string, +C<integer> is a string of digits (possibly beginning with a '+' or '-'), +C<real> is a floating point number, C<rational> is entered as a floating +point number but stored as two C<integer> strings separated by a '/' +character, C<date> is a date/time string entered in the format "YYYY:mm:dd +HH:MM:SS[.ss][+/-HH:MM]", C<boolean> is either "True" or "False", C<struct> +indicates a structured tag, and C<lang-alt> is a tag that supports alternate +languages. + +When reading, C<struct> tags are extracted only if the Struct (-struct) +option is used. Otherwise the corresponding I<Flattened> tags, indicated by +an underline (C<_>) after the B<Writable> type, are extracted. When +copying, by default both structured and flattened tags are available, but +the flattened tags are considered "unsafe" so they they aren't copied unless +specified explicitly. The Struct option may be disabled by setting Struct +to 0 via the API or with --struct on the command line to copy only flattened +tags, or enabled by setting Struct to 1 via the API or with -struct on the +command line to copy only as structures. When writing, the Struct option +has no effect, and both structured and flattened tags may be written. See +L<http://owl.phy.queensu.ca/~phil/exiftool/struct.html> for more details. + +Individual languages for C<lang-alt> tags are accessed by suffixing the tag +name with a '-', followed by an RFC 3066 language code (eg. "XMP:Title-fr", +or "Rights-en-US"). (See L<http://www.ietf.org/rfc/rfc3066.txt> for the RFC +3066 specification.) A C<lang-alt> tag with no language code accesses the +"x-default" language, but causes other languages for this tag to be deleted +when writing. The "x-default" language code may be specified when writing +to preserve other existing languages (eg. "XMP-dc:Description-x-default"). +When reading, "x-default" is not specified. + +The XMP tags are organized according to schema B<Namespace> in the following +tables. The ExifTool family 1 group names are derived from the namespace +prefixes by adding a leading "XMP-" (eg. "XMP-dc"). A few of the longer +prefixes have been shortened (as mentioned in the documentation below) to +avoid excessively long ExifTool group names. The tags of any namespace may +be deleted as a group by specifying the family 1 group name (eg. +"-XMP-dc:all=" on the command line). This includes namespaces which are not +pre-defined by ExifTool. + +In cases where a tag name exists in more than one namespace, less common +namespaces are avoided when writing. However, a specific namespace may be +written by providing a family 1 group name for the tag (eg. XMP-crs:Contrast +or XMP-exif:Contrast). When deciding on which tags to add to an image, +using standard schemas such as L<dc|/XMP dc Tags>, L<xmp|/XMP xmp Tags>, +L<iptcCore|/XMP iptcCore Tags> and L<iptcExt|/XMP iptcExt Tags> is +recommended if possible. + +For structures, the heading of the first column is B<Field Name>. Field +names are very similar to tag names, except they are used to identify fields +inside structures instead of stand-alone tags. See +L<http://owl.phy.queensu.ca/~phil/exiftool/struct.html#Fields> for more +details. + +ExifTool will extract XMP information even if it is not listed in these +tables, but other tags are not writable unless added as user-defined tags in +the ExifTool config file. For example, the C<pdfx> namespace doesn't have a +predefined set of tag names because it is used to store application-defined +PDF information, so although this information will be extracted, it is only +writable if the corresponding user-defined tags have been created. + +The tables below list tags from the official XMP specification (with an +underlined B<Namespace> in the HTML version of this documentation), as well +as extensions from various other sources. See +L<http://www.adobe.com/devnet/xmp/> for the official XMP specification. + + Namespace Writable + --------- -------- + aas XMP aas + acdsee XMP acdsee + album XMP Album + apple-fi XMP apple_fi + aux XMP aux + cc XMP cc + cell XMP cell + creatorAtom XMP creatorAtom + crs XMP crs + dc XMP dc + dex XMP dex + DICOM XMP DICOM + digiKam XMP digiKam + drone-dji DJI XMP + dwc DarwinCore + exif XMP exif + exifEX XMP exifEX + expressionmedia XMP ExpressionMedia + extensis XMP extensis + fpv XMP fpv + GAudio XMP GAudio + GDepth XMP GDepth + getty XMP GettyImages + GFocus XMP GFocus + GImage XMP GImage + GPano XMP GPano + GSpherical XMP GSpherical + ics XMP ics + iptcCore XMP iptcCore + iptcExt XMP iptcExt + LImage XMP LImage + lr XMP Lightroom + mediapro XMP MediaPro + microsoft Microsoft XMP + MP Microsoft MP + MP1 Microsoft MP1 + mwg-coll MWG Collections + mwg-kw MWG Keywords + mwg-rs MWG Regions + pdf XMP pdf + pdfx XMP pdfx + photomech PhotoMechanic XMP + photoshop XMP photoshop + PixelLive XMP PixelLive + plus PLUS XMP + pmi XMP pmi + prism XMP prism + prl XMP prl + prm XMP prm + pur XMP pur + rdf XMP rdf + swf XMP swf + tiff XMP tiff + x XMP x + xmp XMP xmp + xmpBJ XMP xmpBJ + xmpDM XMP xmpDM + xmpMM XMP xmpMM + xmpNote XMP xmpNote + xmpPLUS XMP xmpPLUS + xmpRights XMP xmpRights + xmpTPg XMP xmpTPg + +=head3 XMP aas Tags + +Apple Adjustment Settings used by iPhone/iPad. + +These tags belong to the ExifTool XMP-aas family 1 group. + + Tag Name Writable + -------- -------- + AffineA real + AffineB real + AffineC real + AffineD real + AffineX real + AffineY real + CropH integer/ + CropW integer/ + CropX integer/ + CropY integer/ + Curve0x real + Curve0y real + Curve1x real + Curve1y real + Curve2x real + Curve2y real + Curve3x real + Curve3y real + Curve4x real + Curve4y real + FaceBalanceOrigI real + FaceBalanceOrigQ real + FaceBalanceStrength real + FaceBalanceWarmth real + Highlights real/ + Shadows real/ + Vibrance real/ + +=head3 XMP acdsee Tags + +ACD Systems ACDSee namespace tags. + +(A note to software developers: Re-inventing your own private tags instead +of using the equivalent tags in standard XMP namespaces defeats one of the +most valuable features of metadata: interoperability. Your applications +mumble to themselves instead of speaking out for the rest of the world to +hear.) + +These tags belong to the ExifTool XMP-acdsee family 1 group. + + Tag Name Writable + -------- -------- + Author string/ + Caption string/ + Categories string/ + Collections string/ + DateTime date/ + DPP lang-alt/ + EditStatus string/ + FixtureIdentifier string/ + Keywords string/+ + Notes string/ + ObjectCycle string/ + OriginatingProgram string/ + Rating real/ + Rawrppused boolean/ + ReleaseDate string/ + ReleaseTime string/ + RPP lang-alt/ + Snapshots string/+ + Tagged boolean/ + +=head3 XMP Album Tags + +Adobe Album namespace tags. + +These tags belong to the ExifTool XMP-album family 1 group. + + Tag Name Writable + -------- -------- + Notes string + +=head3 XMP apple_fi Tags + +Face information tags written by the Apple iPhone 5 inside the mwg-rs +RegionExtensions. + +These tags belong to the ExifTool XMP-apple-fi family 1 group. + + Tag Name Writable + -------- -------- + AngleInfoRoll integer + AngleInfoYaw integer + ConfidenceLevel integer + FaceID integer + TimeStamp integer + +=head3 XMP aux Tags + +Adobe-defined auxiliary EXIF tags. This namespace existed in the XMP +specification until it was dropped in 2012, presumably due to the +introduction of the EXIF 2.3 for XMP specification and the exifEX namespace +at this time. For this reason, tags below with equivalents in the +L<exifEX namespace|/XMP exifEX Tags> are avoided when writing. + +These tags belong to the ExifTool XMP-aux family 1 group. + + Tag Name Writable + -------- -------- + ApproximateFocusDistance rational + DistortionCorrectionAlreadyApplied boolean + Firmware string + FlashCompensation rational + ImageNumber string + IsMergedHDR boolean + IsMergedPanorama boolean + LateralChromaticAberrationCorrectionAlreadyApplied boolean + Lens string + LensDistortInfo string + LensID string + LensInfo string/ + LensSerialNumber string/ + OwnerName string/ + SerialNumber string/ + VignetteCorrectionAlreadyApplied boolean + +=head3 XMP cc Tags + +Creative Commons namespace tags. Note that the CC specification for XMP is +non-existent, so ExifTool must make some assumptions about the format of the +specific properties in XMP (see L<http://creativecommons.org/ns>). + +These tags belong to the ExifTool XMP-cc family 1 group. + + Tag Name Writable + -------- -------- + AttributionName string + AttributionURL string + DeprecatedOn date + Jurisdiction string + LegalCode string + License string + MorePermissions string + Permits string+ + Prohibits string+ + Requires string+ + UseGuidelines string + +=head3 XMP cell Tags + +Location tags written by some Sony Ericsson phones. + +These tags belong to the ExifTool XMP-cell family 1 group. + + Tag Name Writable + -------- -------- + CellTowerID string + CellGlobalID string + LocationAreaCode string + MobileCountryCode string + MobileNetworkCode string + CellR string + +=head3 XMP creatorAtom Tags + +Adobe creatorAtom tags, written by After Effects. + +These tags belong to the ExifTool XMP-creatorAtom family 1 group. + + Tag Name Writable + -------- -------- + AeProjectLink AEProjectLink Struct + AeProjectLinkCompositionID string_ + AeProjectLinkFullPath string_ + AeProjectLinkRenderOutputModuleIndex string_ + AeProjectLinkRenderQueueItemID string_ + AeProjectLinkRenderTimeStamp integer_ + MacAtom MacAtom Struct + MacAtomApplicationCode string_ + MacAtomInvocationAppleEvent string_ + MacAtomPosixProjectPath string_ + WindowsAtom WindowsAtom Struct + WindowsAtomExtension string_ + WindowsAtomInvocationFlags string_ + WindowsAtomUncProjectPath string_ + +=head3 XMP AEProjectLink Struct + + Field Name Writable + ---------- -------- + CompositionID string + FullPath string + RenderOutputModuleIndex string + RenderQueueItemID string + RenderTimeStamp integer + +=head3 XMP MacAtom Struct + + Field Name Writable + ---------- -------- + ApplicationCode string + InvocationAppleEvent string + PosixProjectPath string + +=head3 XMP WindowsAtom Struct + + Field Name Writable + ---------- -------- + Extension string + InvocationFlags string + UncProjectPath string + +=head3 XMP crs Tags + +Photoshop Camera Raw namespace tags. It is a shame that Adobe pollutes the +metadata space with these incredibly bulky image editing parameters. + +These tags belong to the ExifTool XMP-crs family 1 group. + + Tag Name Writable + -------- -------- + AlreadyApplied boolean + AutoBrightness boolean + AutoContrast boolean + AutoExposure boolean + AutoLateralCA integer + AutoShadows boolean + AutoTone boolean + AutoWhiteVersion integer + Blacks2012 integer + BlueHue integer + BlueSaturation integer + Brightness integer + CameraProfile string + CameraProfileDigest string + ChromaticAberrationB integer + ChromaticAberrationR integer + CircularGradientBasedCorrections Correction Struct+ + CircGradBasedCorrActive boolean_ + CircGradBasedCorrAmount real_ + CircGradBasedCorrMasks CorrectionMask Struct_+ + CircGradBasedCorrMaskAlpha real_ + CircGradBasedCorrMaskAngle real_ + CircGradBasedCorrMaskBottom real_ + CircGradBasedCorrMaskCenterValue real_ + CircGradBasedCorrMaskCenterWeight real_ + CircGradBasedCorrMaskDabs string_ + CircGradBasedCorrMaskFeather real_ + CircGradBasedCorrMaskFlipped boolean_ + CircGradBasedCorrMaskFlow real_ + CircGradBasedCorrMaskFullX real_ + CircGradBasedCorrMaskFullY real_ + CircGradBasedCorrMaskLeft real_ + CircGradBasedCorrMaskValue real_ + CircGradBasedCorrMaskMidpoint real_ + CircGradBasedCorrMaskPerimeterValue real_ + CircGradBasedCorrMaskRadius real_ + CircGradBasedCorrMaskRight real_ + CircGradBasedCorrMaskRoundness real_ + CircGradBasedCorrMaskSizeX real_ + CircGradBasedCorrMaskSizeY real_ + CircGradBasedCorrMaskTop real_ + CircGradBasedCorrMaskVersion integer_ + CircGradBasedCorrMaskWhat string_ + CircGradBasedCorrMaskX real_ + CircGradBasedCorrMaskY real_ + CircGradBasedCorrMaskZeroX real_ + CircGradBasedCorrMaskZeroY real_ + CircGradBasedCorrBrightness real_ + CircGradBasedCorrClarity real_ + CircGradBasedCorrClarity2012 real_ + CircGradBasedCorrContrast real_ + CircGradBasedCorrContrast2012 real_ + CircGradBasedCorrDefringe real_ + CircGradBasedCorrExposure real_ + CircGradBasedCorrExposure2012 real_ + CircGradBasedCorrHighlights2012 real_ + CircGradBasedCorrLuminanceNoise real_ + CircGradBasedCorrMoire real_ + CircGradBasedCorrSaturation real_ + CircGradBasedCorrShadows2012 real_ + CircGradBasedCorrSharpness real_ + CircGradBasedCorrTemperature real_ + CircGradBasedCorrTint real_ + CircGradBasedCorrHue real_ + CircGradBasedCorrSaturation real_ + CircGradBasedCorrWhat string_ + Clarity integer + Clarity2012 integer + ColorNoiseReduction integer + ColorNoiseReductionDetail integer + ColorNoiseReductionSmoothness integer + Contrast integer/ + Contrast2012 integer + Converter string + ConvertToGrayscale boolean + CropAngle real + CropBottom real + CropConstrainToWarp integer + CropHeight real + CropLeft real + CropRight real + CropTop real + CropUnit integer + CropUnits integer + CropWidth real + DefaultAutoGray boolean + DefaultAutoTone boolean + DefaultsSpecificToISO boolean + DefaultsSpecificToSerial boolean + Defringe integer + DefringeGreenAmount integer + DefringeGreenHueHi integer + DefringeGreenHueLo integer + DefringePurpleAmount integer + DefringePurpleHueHi integer + DefringePurpleHueLo integer + Dehaze real + DNGIgnoreSidecars boolean + Exposure real + Exposure2012 real + FillLight integer + GradientBasedCorrections Correction Struct+ + GradientBasedCorrActive boolean_ + GradientBasedCorrAmount real_ + GradientBasedCorrMasks CorrectionMask Struct_+ + GradientBasedCorrMaskAlpha real_ + GradientBasedCorrMaskAngle real_ + GradientBasedCorrMaskBottom real_ + GradientBasedCorrMaskCenterValue real_ + GradientBasedCorrMaskCenterWeight real_ + GradientBasedCorrMaskDabs string_ + GradientBasedCorrMaskFeather real_ + GradientBasedCorrMaskFlipped boolean_ + GradientBasedCorrMaskFlow real_ + GradientBasedCorrMaskFullX real_ + GradientBasedCorrMaskFullY real_ + GradientBasedCorrMaskLeft real_ + GradientBasedCorrMaskValue real_ + GradientBasedCorrMaskMidpoint real_ + GradientBasedCorrMaskPerimeterValue real_ + GradientBasedCorrMaskRadius real_ + GradientBasedCorrMaskRight real_ + GradientBasedCorrMaskRoundness real_ + GradientBasedCorrMaskSizeX real_ + GradientBasedCorrMaskSizeY real_ + GradientBasedCorrMaskTop real_ + GradientBasedCorrMaskVersion integer_ + GradientBasedCorrMaskWhat string_ + GradientBasedCorrMaskX real_ + GradientBasedCorrMaskY real_ + GradientBasedCorrMaskZeroX real_ + GradientBasedCorrMaskZeroY real_ + GradientBasedCorrBrightness real_ + GradientBasedCorrClarity real_ + GradientBasedCorrClarity2012 real_ + GradientBasedCorrContrast real_ + GradientBasedCorrContrast2012 real_ + GradientBasedCorrDefringe real_ + GradientBasedCorrExposure real_ + GradientBasedCorrExposure2012 real_ + GradientBasedCorrHighlights2012 real_ + GradientBasedCorrLuminanceNoise real_ + GradientBasedCorrMoire real_ + GradientBasedCorrSaturation real_ + GradientBasedCorrShadows2012 real_ + GradientBasedCorrSharpness real_ + GradientBasedCorrTemperature real_ + GradientBasedCorrTint real_ + GradientBasedCorrHue real_ + GradientBasedCorrSaturation real_ + GradientBasedCorrWhat string_ + GrainAmount integer + GrainFrequency integer + GrainSize integer + GrayMixerAqua integer + GrayMixerBlue integer + GrayMixerGreen integer + GrayMixerMagenta integer + GrayMixerOrange integer + GrayMixerPurple integer + GrayMixerRed integer + GrayMixerYellow integer + GreenHue integer + GreenSaturation integer + HasCrop boolean + HasSettings boolean + HighlightRecovery integer + Highlights2012 integer + HueAdjustmentAqua integer + HueAdjustmentBlue integer + HueAdjustmentGreen integer + HueAdjustmentMagenta integer + HueAdjustmentOrange integer + HueAdjustmentPurple integer + HueAdjustmentRed integer + HueAdjustmentYellow integer + IncrementalTemperature integer + IncrementalTint integer + JPEGHandling string + LensManualDistortionAmount integer + LensProfileChromaticAberrationScale integer + LensProfileDigest string + LensProfileDistortionScale integer + LensProfileEnable integer + LensProfileFilename string + LensProfileMatchKeyCameraModelName string + LensProfileMatchKeyExifMake string + LensProfileMatchKeyExifModel string + LensProfileMatchKeyIsRaw boolean + LensProfileMatchKeyLensID string + LensProfileMatchKeyLensInfo string + LensProfileMatchKeyLensName string + LensProfileMatchKeySensorFormatFactor real + LensProfileName string + LensProfileSetup string + LensProfileVignettingScale integer + LuminanceAdjustmentAqua integer + LuminanceAdjustmentBlue integer + LuminanceAdjustmentGreen integer + LuminanceAdjustmentMagenta integer + LuminanceAdjustmentOrange integer + LuminanceAdjustmentPurple integer + LuminanceAdjustmentRed integer + LuminanceAdjustmentYellow integer + LuminanceNoiseReductionContrast integer + LuminanceNoiseReductionDetail integer + LuminanceSmoothing integer + MoireFilter string + NegativeCacheLargePreviewSize integer + NegativeCacheMaximumSize real + NegativeCachePath string + PaintBasedCorrections Correction Struct+ + PaintCorrectionActive boolean_ + PaintCorrectionAmount real_ + PaintBasedCorrectionMasks CorrectionMask Struct_+ + PaintCorrectionMaskAlpha real_ + PaintCorrectionMaskAngle real_ + PaintCorrectionMaskBottom real_ + PaintCorrectionMaskCenterValue real_ + PaintCorrectionMaskCenterWeight real_ + PaintCorrectionMaskDabs string_ + PaintCorrectionMaskFeather real_ + PaintCorrectionMaskFlipped boolean_ + PaintCorrectionMaskFlow real_ + PaintCorrectionMaskFullX real_ + PaintCorrectionMaskFullY real_ + PaintCorrectionMaskLeft real_ + PaintCorrectionMaskValue real_ + PaintCorrectionMaskMidpoint real_ + PaintCorrectionMaskPerimeterValue real_ + PaintCorrectionMaskRadius real_ + PaintCorrectionMaskRight real_ + PaintCorrectionMaskRoundness real_ + PaintCorrectionMaskSizeX real_ + PaintCorrectionMaskSizeY real_ + PaintCorrectionMaskTop real_ + PaintCorrectionMaskVersion integer_ + PaintCorrectionMaskWhat string_ + PaintCorrectionMaskX real_ + PaintCorrectionMaskY real_ + PaintCorrectionMaskZeroX real_ + PaintCorrectionMaskZeroY real_ + PaintCorrectionBrightness real_ + PaintCorrectionClarity real_ + PaintCorrectionClarity2012 real_ + PaintCorrectionContrast real_ + PaintCorrectionContrast2012 real_ + PaintCorrectionDefringe real_ + PaintCorrectionExposure real_ + PaintCorrectionExposure2012 real_ + PaintCorrectionHighlights2012 real_ + PaintCorrectionLuminanceNoise real_ + PaintCorrectionMoire real_ + PaintCorrectionSaturation real_ + PaintCorrectionShadows2012 real_ + PaintCorrectionSharpness real_ + PaintCorrectionTemperature real_ + PaintCorrectionTint real_ + PaintCorrectionHue real_ + PaintCorrectionSaturation real_ + PaintCorrectionWhat string_ + ParametricDarks integer + ParametricHighlights integer + ParametricHighlightSplit integer + ParametricLights integer + ParametricMidtoneSplit integer + ParametricShadows integer + ParametricShadowSplit integer + PerspectiveAspect integer + PerspectiveHorizontal integer + PerspectiveRotate real + PerspectiveScale integer + PerspectiveUpright integer + PerspectiveVertical integer + PerspectiveX real + PerspectiveY real + PostCropVignetteAmount integer + PostCropVignetteFeather integer + PostCropVignetteHighlightContrast integer + PostCropVignetteMidpoint integer + PostCropVignetteRoundness integer + PostCropVignetteStyle integer + ProcessVersion string + RawFileName string + RedEyeInfo string+ + RedHue integer + RedSaturation integer + RetouchAreas RetouchArea Struct+ + RetouchAreaFeather real_ + RetouchAreaMasks CorrectionMask Struct_+ + RetouchAreaMaskAlpha real_ + RetouchAreaMaskAngle real_ + RetouchAreaMaskBottom real_ + RetouchAreaMaskCenterValue real_ + RetouchAreaMaskCenterWeight real_ + RetouchAreaMaskDabs string_ + RetouchAreaMaskFeather real_ + RetouchAreaMaskFlipped boolean_ + RetouchAreaMaskFlow real_ + RetouchAreaMaskFullX real_ + RetouchAreaMaskFullY real_ + RetouchAreaMaskLeft real_ + RetouchAreaMaskValue real_ + RetouchAreaMaskMidpoint real_ + RetouchAreaMaskPerimeterValue real_ + RetouchAreaMaskRadius real_ + RetouchAreaMaskRight real_ + RetouchAreaMaskRoundness real_ + RetouchAreaMaskSizeX real_ + RetouchAreaMaskSizeY real_ + RetouchAreaMaskTop real_ + RetouchAreaMaskVersion integer_ + RetouchAreaMaskWhat string_ + RetouchAreaMaskX real_ + RetouchAreaMaskY real_ + RetouchAreaMaskZeroX real_ + RetouchAreaMaskZeroY real_ + RetouchAreaMethod string_ + RetouchAreaOffsetY real_ + RetouchAreaOpacity real_ + RetouchAreaSeed integer_ + RetouchAreaSourceState string_ + RetouchAreaSourceX real_ + RetouchAreaSpotType string_ + RetouchInfo string+ + Saturation integer/ + SaturationAdjustmentAqua integer + SaturationAdjustmentBlue integer + SaturationAdjustmentGreen integer + SaturationAdjustmentMagenta integer + SaturationAdjustmentOrange integer + SaturationAdjustmentPurple integer + SaturationAdjustmentRed integer + SaturationAdjustmentYellow integer + Shadows integer + Shadows2012 integer + ShadowTint integer + SharpenDetail integer + SharpenEdgeMasking integer + SharpenRadius real + Sharpness integer/ + Smoothness integer + SplitToningBalance integer + SplitToningHighlightHue integer + SplitToningHighlightSaturation integer + SplitToningShadowHue integer + SplitToningShadowSaturation integer + ColorTemperature integer + TIFFHandling string + Tint integer + ToneCurve string+ + ToneCurveBlue string+ + ToneCurveGreen string+ + ToneCurveName string + ToneCurveName2012 string + ToneCurvePV2012 string+ + ToneCurvePV2012Blue string+ + ToneCurvePV2012Green string+ + ToneCurvePV2012Red string+ + ToneCurveRed string+ + ToneMapStrength real + UprightCenterMode integer + UprightCenterNormX real + UprightCenterNormY real + UprightDependentDigest string + UprightFocalLength35mm real + UprightFocalMode integer + UprightFourSegmentsCount integer + UprightPreview boolean + UprightTransform_0 string + UprightTransform_1 string + UprightTransform_2 string + UprightTransform_3 string + UprightTransform_4 string + UprightTransform_5 string + UprightTransformCount integer + UprightVersion integer + Version string + Vibrance integer + VignetteAmount integer + VignetteMidpoint integer + What string + WhiteBalance string/ + Whites2012 integer + +=head3 XMP Correction Struct + + Field Name Writable + ---------- -------- + CorrectionActive boolean + CorrectionAmount real + CorrectionMasks CorrectionMask Struct+ + LocalBrightness real + LocalClarity real + LocalClarity2012 real + LocalContrast real + LocalContrast2012 real + LocalDefringe real + LocalExposure real + LocalExposure2012 real + LocalHighlights2012 real + LocalLuminanceNoise real + LocalMoire real + LocalSaturation real + LocalShadows2012 real + LocalSharpness real + LocalTemperature real + LocalTint real + LocalToningHue real + LocalToningSaturation real + What string + +=head3 XMP CorrectionMask Struct + + Field Name Writable + ---------- -------- + Alpha real + Angle real + Bottom real + CenterValue real + CenterWeight real + Dabs string+ + Feather real + Flipped boolean + Flow real + FullX real + FullY real + Left real + MaskValue real + Midpoint real + PerimeterValue real + Radius real + Right real + Roundness real + SizeX real + SizeY real + Top real + Version integer + What string + X real + Y real + ZeroX real + ZeroY real + +=head3 XMP RetouchArea Struct + + Field Name Writable + ---------- -------- + Feather real + Masks CorrectionMask Struct+ + Method string + OffsetY real + Opacity real + Seed integer + SourceState string + SourceX real + SpotType string + +=head3 XMP dc Tags + +Dublin Core namespace tags. + +These tags belong to the ExifTool XMP-dc family 1 group. + + Tag Name Writable + -------- -------- + Contributor string+ + Coverage string + Creator string+ + Date date+ + Description lang-alt + Format string + Identifier string + Language string+ + Publisher string+ + Relation string+ + Rights lang-alt + Source string/ + Subject string+ + Title lang-alt + Type string+ + +=head3 XMP dex Tags + +Description Explorer namespace tags. These tags are not very common. The +Source and Rating tags are avoided when writing due to name conflicts with +other XMP tags. (see L<http://www.optimasc.com/products/fileid/>) + +These tags belong to the ExifTool XMP-dex family 1 group. + + Tag Name Writable + -------- -------- + CRC32 integer + FFID string + LicenseType string + OS integer + Rating string/ + Revision string + ShortDescription lang-alt + Source string/ + +=head3 XMP DICOM Tags + +DICOM namespace tags. These XMP tags allow some DICOM information to be +stored in files of other than DICOM format. See the +L<DICOM Tags documentation|Image::ExifTool::TagNames/DICOM Tags> for a list +of tags available in DICOM-format files. + +These tags belong to the ExifTool XMP-DICOM family 1 group. + + Tag Name Writable + -------- -------- + EquipmentInstitution string + EquipmentManufacturer string + PatientBirthDate date + PatientID string + PatientName string + PatientSex string + SeriesDateTime date + SeriesDescription string + SeriesModality string + SeriesNumber string + StudyDateTime date + StudyDescription string + StudyID string + StudyPhysician string + +=head3 XMP digiKam Tags + +DigiKam namespace tags. + +These tags belong to the ExifTool XMP-digiKam family 1 group. + + Tag Name Writable + -------- -------- + CaptionsAuthorNames lang-alt + CaptionsDateTimeStamps lang-alt + ColorLabel string + ImageHistory string/ + ImageUniqueID string/ + LensCorrectionSettings string + PickLabel string + TagsList string+ + +=head3 XMP exif Tags + +EXIF namespace for EXIF tags. See +L<http://www.cipa.jp/std/documents/e/DC-010-2017_E.pdf> for the +specification. + +These tags belong to the ExifTool XMP-exif family 1 group. + + Tag Name Writable + -------- -------- + ApertureValue rational + BrightnessValue rational + CFAPattern CFAPattern Struct + CFAPatternColumns integer_ + CFAPatternRows integer_ + CFAPatternValues integer_+ + ColorSpace integer + ComponentsConfiguration integer+ + CompressedBitsPerPixel rational + Contrast integer + CustomRendered integer + DateTimeDigitized date + DateTimeOriginal date + DeviceSettingDescription DeviceSettings Struct + DeviceSettingDescriptionColumns integer_ + DeviceSettingDescriptionRows integer_ + DeviceSettingDescriptionSettings string_+ + DigitalZoomRatio rational + ExifVersion string + ExposureCompensation rational + ExposureIndex rational + ExposureMode integer + ExposureProgram integer + ExposureTime rational + FileSource integer + Flash Flash Struct + FlashEnergy rational + FlashFired boolean_ + FlashFunction boolean_ + FlashMode integer_ + FlashpixVersion string + FlashRedEyeMode boolean_ + FlashReturn integer_ + FNumber rational + FocalLength rational + FocalLengthIn35mmFormat integer + FocalPlaneResolutionUnit integer + FocalPlaneXResolution rational + FocalPlaneYResolution rational + GainControl integer + GPSAltitude rational + GPSAltitudeRef integer + GPSAreaInformation string + GPSDestBearing rational + GPSDestBearingRef string + GPSDestDistance rational + GPSDestDistanceRef string + GPSDestLatitude string + GPSDestLongitude string + GPSDifferential integer + GPSDOP rational + GPSHPositioningError rational + GPSImgDirection rational + GPSImgDirectionRef string + GPSLatitude string + GPSLongitude string + GPSMapDatum string + GPSMeasureMode integer + GPSProcessingMethod string + GPSSatellites string + GPSSpeed rational + GPSSpeedRef string + GPSStatus string + GPSDateTime date + GPSTrack rational + GPSTrackRef string + GPSVersionID string + ImageUniqueID string + ISO integer+ + LightSource string + MakerNote string + MaxApertureValue rational + MeteringMode integer + NativeDigest string + Opto-ElectricConvFactor OECF Struct + OECFColumns integer_ + OECFNames string_+ + OECFRows integer_ + OECFValues rational_+ + ExifImageWidth integer + ExifImageHeight integer + RelatedSoundFile string + Saturation integer + SceneCaptureType integer + SceneType integer + SensingMethod integer + Sharpness integer + ShutterSpeedValue rational + SpatialFrequencyResponse OECF Struct + SpatialFrequencyResponseColumns integer_ + SpatialFrequencyResponseNames string_+ + SpatialFrequencyResponseRows integer_ + SpatialFrequencyResponseValues rational_+ + SpectralSensitivity string + SubjectArea integer+ + SubjectDistance rational + SubjectDistanceRange integer + SubjectLocation integer+ + UserComment lang-alt + WhiteBalance integer + +=head3 XMP CFAPattern Struct + + Field Name Writable + ---------- -------- + Columns integer + Rows integer + Values integer+ + +=head3 XMP DeviceSettings Struct + + Field Name Writable + ---------- -------- + Columns integer + Rows integer + Settings string+ + +=head3 XMP Flash Struct + + Field Name Writable + ---------- -------- + Fired boolean + Function boolean + Mode integer + RedEyeMode boolean + Return integer + +=head3 XMP OECF Struct + + Field Name Writable + ---------- -------- + Columns integer + Names string+ + Rows integer + Values rational+ + +=head3 XMP exifEX Tags + +EXIF tags added by the EXIF 2.31 for XMP specification (see +L<http://www.cipa.jp/std/documents/e/DC-010-2017_E.pdf>). + +These tags belong to the ExifTool XMP-exifEX family 1 group. + + Tag Name Writable + -------- -------- + Acceleration rational + SerialNumber string + CameraElevationAngle rational + OwnerName string + Gamma rational + Humidity rational + InteropIndex string + ISOSpeed integer + ISOSpeedLatitudeyyy integer + ISOSpeedLatitudezzz integer + LensMake string + LensModel string + LensSerialNumber string + LensInfo rational+ + PhotographicSensitivity integer + Pressure rational + RecommendedExposureIndex integer + SensitivityType integer + StandardOutputSensitivity integer + AmbientTemperature rational + WaterDepth rational + +=head3 XMP ExpressionMedia Tags + +Microsoft Expression Media namespace tags. These tags are avoided when +writing due to name conflicts with tags in other schemas. + +These tags belong to the ExifTool XMP-expressionmedia family 1 group. + + Tag Name Writable + -------- -------- + CatalogSets string/+ + Event string/ + People string/+ + Status string/ + +=head3 XMP extensis Tags + +Tags used by Extensis Portfolio. + +These tags belong to the ExifTool XMP-extensis family 1 group. + + Tag Name Writable + -------- -------- + Approved boolean + ApprovedBy string + ClientName string + JobName string + JobStatus string + RoutedTo string + RoutingNotes string + WorkToDo string + +=head3 XMP fpv Tags + +Fast Picture Viewer tags (see +L<http://www.fastpictureviewer.com/help/#rtfcomments>). + +These tags belong to the ExifTool XMP-fpv family 1 group. + + Tag Name Writable + -------- -------- + RichTextComment string + +=head3 XMP GAudio Tags + +These tags belong to the ExifTool XMP-GAudio family 1 group. + + Tag Name Writable + -------- -------- + AudioData string + AudioMimeType string + +=head3 XMP GDepth Tags + +Google depthmap information. See +L<https://developers.google.com/depthmap-metadata/> for the specification. + +These tags belong to the ExifTool XMP-GDepth family 1 group. + + Tag Name Writable + -------- -------- + Confidence string/ + ConfidenceMime string/ + Data string/ + Far real/ + Format string/ + ImageHeight real/ + ImageWidth real/ + Manufacturer string/ + MeasureType string/ + Mime string/ + Model string/ + Near real/ + Software string/ + Units string/ + +=head3 XMP GettyImages Tags + +The actual Getty Images namespace prefix is "GettyImagesGIFT", which is the +prefix recorded in the file, but ExifTool shortens this for the family 1 +group name. + +These tags belong to the ExifTool XMP-getty family 1 group. + + Tag Name Writable + -------- -------- + AssetID string + CallForImage string + CameraFilename string + CameraMakeModel string/ + CameraSerialNumber string/ + Composition string + ExclusiveCoverage string + GIFTFtpPriority string + ImageRank string + MediaEventIdDate string + OriginalCreateDateTime date/ + OriginalFileName string + ParentMediaEventID string + ParentMEID string + Personality string+ + PrimaryFTP string+ + RoutingDestinations string+ + RoutingExclusions string+ + SecondaryFTP string+ + TimeShot string + +=head3 XMP GFocus Tags + +Focus information found in Google depthmap images. + +These tags belong to the ExifTool XMP-GFocus family 1 group. + + Tag Name Writable + -------- -------- + BlurAtInfinity real + FocalDistance real + FocalPointX real + FocalPointY real + +=head3 XMP GImage Tags + +These tags belong to the ExifTool XMP-GImage family 1 group. + + Tag Name Writable + -------- -------- + ImageData string + ImageMimeType string + +=head3 XMP GPano Tags + +Panorama tags written by Google Photosphere. See +L<https://developers.google.com/panorama/metadata/> for the specification. + +These tags belong to the ExifTool XMP-GPano family 1 group. + + Tag Name Writable + -------- -------- + CaptureSoftware string + CroppedAreaImageHeightPixels real + CroppedAreaImageWidthPixels real + CroppedAreaLeftPixels real + CroppedAreaTopPixels real + ExposureLockUsed boolean + FirstPhotoDate date + FullPanoHeightPixels real + FullPanoWidthPixels real + InitialCameraDolly real + InitialHorizontalFOVDegrees real + InitialViewHeadingDegrees real + InitialViewPitchDegrees real + InitialViewRollDegrees real + LargestValidInteriorRectHeight real + LargestValidInteriorRectLeft real + LargestValidInteriorRectTop real + LargestValidInteriorRectWidth real + LastPhotoDate date + PoseHeadingDegrees real + PosePitchDegrees real + PoseRollDegrees real + ProjectionType string + SourcePhotosCount integer + StitchingSoftware string + UsePanoramaViewer boolean + +=head3 XMP GSpherical Tags + +Not actually XMP. These RDF/XML tags are used in Google spherical MP4 +videos. See +L<https://github.com/google/spatial-media/blob/master/docs/spherical-video-rfc.md> +for the specification. + +These tags belong to the ExifTool XMP-GSpherical family 1 group. + + Tag Name Writable + -------- -------- + CroppedAreaImageHeightPixels integer/ + CroppedAreaImageWidthPixels integer/ + CroppedAreaLeftPixels integer/ + CroppedAreaTopPixels integer/ + FullPanoHeightPixels integer/ + FullPanoWidthPixels integer/ + InitialViewHeadingDegrees real/ + InitialViewPitchDegrees real/ + InitialViewRollDegrees real/ + ProjectionType string/ + SourceCount integer/ + Spherical boolean/ + StereoMode string/ + Stitched boolean/ + StitchingSoftware string/ + TimeStamp integer/ + +=head3 XMP ics Tags + +Tags used by IDimager. Nested TagStructure structures are unrolled to an +arbitrary depth of 6 to avoid infinite recursion. + +These tags belong to the ExifTool XMP-ics family 1 group. + + Tag Name Writable + -------- -------- + AppVersion string/ + ImageRef string + SubVersions SubVersion Struct+ + SubVersionFileName string_+ + SubVersionReference string_+ + TagStructure TagStructure Struct+ + LabelName1 string_+ + ParentReference1 string_+ + Reference1 string_+ + SubLables1 TagStructure Struct_+ + LabelName2 string_+ + ParentReference2 string_+ + Reference2 string_+ + SubLables2 TagStructure Struct_+ + LabelName3 string_+ + ParentReference3 string_+ + Reference3 string_+ + SubLables3 TagStructure Struct_+ + LabelName4 string_+ + ParentReference4 string_+ + Reference4 string_+ + SubLabels4 TagStructure Struct_+ + LabelName5 string_+ + ParentReference5 string_+ + Reference5 string_+ + SubLabels5 TagStructure Struct_+ + LabelName6 string_+ + ParentReference6 string_+ + Reference6 string_+ + TimeStamp date/ + +=head3 XMP SubVersion Struct + + Field Name Writable + ---------- -------- + FileName string + VersRef string + +=head3 XMP TagStructure Struct + + Field Name Writable + ---------- -------- + LabelName string + ParentReference string + Reference string + SubLabels TagStructure Struct+ + +=head3 XMP iptcCore Tags + +IPTC Core namespace tags. The actual IPTC Core namespace prefix is +"Iptc4xmpCore", which is the prefix recorded in the file, but ExifTool +shortens this for the family 1 group name. (see +L<http://www.iptc.org/IPTC4XMP/>) + +These tags belong to the ExifTool XMP-iptcCore family 1 group. + + Tag Name Writable + -------- -------- + CountryCode string + CreatorContactInfo ContactInfo Struct + CreatorCity string_ + CreatorCountry string_ + CreatorAddress string_ + CreatorPostalCode string_ + CreatorRegion string_ + CreatorWorkEmail string_ + CreatorWorkTelephone string_ + CreatorWorkURL string_ + IntellectualGenre string + Location string + Scene string+ + SubjectCode string+ + +=head3 XMP ContactInfo Struct + + Field Name Writable + ---------- -------- + CiAdrCity string + CiAdrCtry string + CiAdrExtadr string + CiAdrPcode string + CiAdrRegion string + CiEmailWork string + CiTelWork string + CiUrlWork string + +=head3 XMP iptcExt Tags + +IPTC Extension namespace tags. The actual namespace prefix is +"Iptc4xmpExt", but ExifTool shortens this for the family 1 group name. (see +L<http://www.iptc.org/IPTC4XMP/>) + +These tags belong to the ExifTool XMP-iptcExt family 1 group. + + Tag Name Writable + -------- -------- + AboutCvTerm CVTermDetails Struct+ + AboutCvTermCvId string_+ + AboutCvTermId string_+ + AboutCvTermName lang-alt_+ + AboutCvTermRefinedAbout string_+ + AdditionalModelInformation string + ArtworkOrObject ArtworkOrObjectDetails Struct+ + ArtworkCircaDateCreated string!_+ + ArtworkContentDescription lang-alt_+ + ArtworkContributionDescription lang-alt_+ + ArtworkCopyrightNotice string_+ + ArtworkCreator string_+ + ArtworkCreatorID string_+ + ArtworkCopyrightOwnerID string_+ + ArtworkCopyrightOwnerName string_+ + ArtworkLicensorID string_+ + ArtworkLicensorName string_+ + ArtworkDateCreated date_+ + ArtworkPhysicalDescription lang-alt_+ + ArtworkSource string_+ + ArtworkSourceInventoryNo string_+ + ArtworkSourceInvURL string_+ + ArtworkStylePeriod string_+ + ArtworkTitle lang-alt_+ + AudioBitrate integer + AudioBitrateMode string + AudioBitsPerSample integer + AudioChannelCount integer + CircaDateCreated string + ContainerFormat Entity Struct + ContainerFormatIdentifier string_+ + ContainerFormatName lang-alt_ + Contributor EntityWithRole Struct+ + ContributorIdentifier string_+ + ContributorName lang-alt_+ + ContributorRole string_+ + CopyrightYear integer + Creator EntityWithRole Struct+ + CreatorIdentifier string_+ + CreatorName lang-alt_+ + CreatorRole string_+ + ControlledVocabularyTerm string+ + DataOnScreen TextRegion Struct+ + DataOnScreenRegion Area Struct_+ + DataOnScreenRegionD real_+ + DataOnScreenRegionH real_+ + DataOnScreenRegionText string_+ + DataOnScreenRegionUnit string_+ + DataOnScreenRegionW real_+ + DataOnScreenRegionX real_+ + DataOnScreenRegionY real_+ + DigitalImageGUID string + DigitalSourceFileType string + DigitalSourceType string + Dopesheet lang-alt + DopesheetLink QualifiedLink Struct+ + DopesheetLinkLink string_+ + DopesheetLinkLinkQualifier string_+ + EmbdEncRightsExpr EEREDetails Struct+ + EmbeddedEncodedRightsExpr string_+ + EmbeddedEncodedRightsExprType string_+ + EmbeddedEncodedRightsExprLangID string_+ + Episode EpisodeOrSeason Struct + EpisodeIdentifier string_ + EpisodeName string_ + EpisodeNumber string_ + Event lang-alt + ShownEvent Entity Struct+ + ShownEventIdentifier string_+ + ShownEventName lang-alt_+ + ExternalMetadataLink string+ + FeedIdentifier string + Genre CVTermDetails Struct+ + GenreCvId string_+ + GenreCvTermId string_+ + GenreCvTermName lang-alt_+ + GenreCvTermRefinedAbout string_+ + Headline lang-alt/ + IPTCLastEdited date + LinkedEncRightsExpr LEREDetails Struct+ + LinkedEncodedRightsExpr string_+ + LinkedEncodedRightsExprType string_+ + LinkedEncodedRightsExprLangID string_+ + LocationCreated LocationDetails Struct+ + LocationCreatedCity string_+ + LocationCreatedCountryCode string_+ + LocationCreatedCountryName string_+ + LocationCreatedGPSAltitude rational_+ + LocationCreatedGPSLatitude string_+ + LocationCreatedGPSLongitude string_+ + LocationCreatedIdentifier string_+ + LocationCreatedLocationId string_+ + LocationCreatedLocationName lang-alt_+ + LocationCreatedProvinceState string_+ + LocationCreatedSublocation string_+ + LocationCreatedWorldRegion string_+ + LocationShown LocationDetails Struct+ + LocationShownCity string_+ + LocationShownCountryCode string_+ + LocationShownCountryName string_+ + LocationShownGPSAltitude rational_+ + LocationShownGPSLatitude string_+ + LocationShownGPSLongitude string_+ + LocationShownIdentifier string_+ + LocationShownLocationId string_+ + LocationShownLocationName lang-alt_+ + LocationShownProvinceState string_+ + LocationShownSublocation string_+ + LocationShownWorldRegion string_+ + MaxAvailHeight integer + MaxAvailWidth integer + ModelAge integer+ + OrganisationInImageCode string+ + OrganisationInImageName string+ + PersonHeard Entity Struct+ + PersonHeardIdentifier string_+ + PersonHeardName lang-alt_+ + PersonInImage string+ + PersonInImageWDetails PersonDetails Struct+ + PersonInImageCharacteristic CVTermDetails Struct_+ + PersonInImageCvTermCvId string_+ + PersonInImageCvTermId string_+ + PersonInImageCvTermName lang-alt_+ + PersonInImageCvTermRefinedAbout string_+ + PersonInImageDescription lang-alt_+ + PersonInImageId string_+ + PersonInImageName lang-alt_+ + PlanningRef EntityWithRole Struct+ + PlanningRefIdentifier string_+ + PlanningRefName lang-alt_+ + PlanningRefRole string_+ + ProductInImage ProductDetails Struct+ + ProductInImageDescription lang-alt_+ + ProductInImageGTIN string_+ + ProductInImageName lang-alt_+ + PublicationEvent PublicationEvent Struct+ + PublicationEventDate date_+ + PublicationEventIdentifier string_+ + PublicationEventName string_+ + Rating Rating Struct+ + RatingRatingRegion LocationDetails Struct_+ + RatingRegionCity string_+ + RatingRegionCountryCode string_+ + RatingRegionCountryName string_+ + RatingRegionGPSAltitude rational_+ + RatingRegionGPSLatitude string_+ + RatingRegionGPSLongitude string_+ + RatingRegionIdentifier string_+ + RatingRegionLocationId string_+ + RatingRegionLocationName lang-alt_+ + RatingRegionProvinceState string_+ + RatingRegionSublocation string_+ + RatingRegionWorldRegion string_+ + RatingScaleMaxValue string_+ + RatingScaleMinValue string_+ + RatingSourceLink string_+ + RatingValue string_+ + RatingValueLogoLink string_+ + RecDevice Device Struct + RecDeviceAttLensDescription string_ + RecDeviceManufacturer string_ + RecDeviceModelName string_ + RecDeviceOwnersDeviceId string_ + RecDeviceSerialNumber string_ + RegistryID RegistryEntryDetails Struct+ + RegistryEntryRole string_+ + RegistryItemID string_+ + RegistryOrganisationID string_+ + ReleaseReady boolean + Season EpisodeOrSeason Struct + SeasonIdentifier string_ + SeasonName string_ + SeasonNumber string_ + Series Series Struct + SeriesIdentifier string_ + SeriesName string_ + Snapshot LinkedImage Struct+ + SnapshotFormat string_+ + SnapshotHeightPixels integer_+ + SnapshotImageRole string_+ + SnapshotLink string_+ + SnapshotLinkQualifier string_+ + SnapshotUsedVideoFrame Timecode Struct_+ + SnapshotUsedVideoFrameTimeFormat string_+ + SnapshotUsedVideoFrameTimeValue string_+ + SnapshotUsedVideoFrameValue integer_+ + SnapshotWidthPixels integer_+ + StorylineIdentifier string+ + StreamReady string + StylePeriod string + SupplyChainSource Entity Struct+ + SupplyChainSourceIdentifier string_+ + SupplyChainSourceName lang-alt_+ + TemporalCoverage TemporalCoverage Struct + TemporalCoverageFrom date_ + TemporalCoverageTo date_ + Transcript lang-alt + TranscriptLink QualifiedLink Struct+ + TranscriptLinkLink string_+ + TranscriptLinkLinkQualifier string_+ + VideoBitrate integer + VideoBitrateMode string + VideoDisplayAspectRatio rational + VideoEncodingProfile string + VideoShotType Entity Struct+ + VideoShotTypeIdentifier string_+ + VideoShotTypeName lang-alt_+ + VideoStreamsCount integer + VisualColor string + WorkflowTag CVTermDetails Struct + WorkflowTagCvId string_ + WorkflowTagCvTermId string_ + WorkflowTagCvTermName lang-alt_ + WorkflowTagCvTermRefinedAbout string_ + +=head3 XMP CVTermDetails Struct + + Field Name Writable + ---------- -------- + CvId string + CvTermId string + CvTermName lang-alt + CvTermRefinedAbout string + +=head3 XMP ArtworkOrObjectDetails Struct + + Field Name Writable + ---------- -------- + AOCircaDateCreated string + AOContentDescription lang-alt + AOContributionDescription lang-alt + AOCopyrightNotice string + AOCreator string+ + AOCreatorId string+ + AOCurrentCopyrightOwnerId string + AOCurrentCopyrightOwnerName string + AOCurrentLicensorId string + AOCurrentLicensorName string + AODateCreated date + AOPhysicalDescription lang-alt + AOSource string + AOSourceInvNo string + AOSourceInvURL string + AOStylePeriod string+ + AOTitle lang-alt + +=head3 XMP Entity Struct + + Field Name Writable + ---------- -------- + Identifier string+ + Name lang-alt + +=head3 XMP EntityWithRole Struct + + Field Name Writable + ---------- -------- + Identifier string+ + Name lang-alt + Role string+ + +=head3 XMP TextRegion Struct + + Field Name Writable + ---------- -------- + Region Area Struct + RegionText string + +=head3 XMP Area Struct + + Field Name Writable + ---------- -------- + D real + H real + Unit string + W real + X real + Y real + +=head3 XMP QualifiedLink Struct + + Field Name Writable + ---------- -------- + Link string + LinkQualifier string + +=head3 XMP EEREDetails Struct + + Field Name Writable + ---------- -------- + EncRightsExpr string + RightsExprEncType string + RightsExprLangId string + +=head3 XMP EpisodeOrSeason Struct + + Field Name Writable + ---------- -------- + Identifier string + Name string + Number string + +=head3 XMP LEREDetails Struct + + Field Name Writable + ---------- -------- + LinkedRightsExpr string + RightsExprEncType string + RightsExprLangId string + +=head3 XMP LocationDetails Struct + + Field Name Writable + ---------- -------- + City string + CountryCode string + CountryName string + GPSAltitude rational + GPSLatitude string + GPSLongitude string + GROUPS string + Identifier string+ + LocationId string+ + LocationName lang-alt + ProvinceState string + Sublocation string + WorldRegion string + +=head3 XMP PersonDetails Struct + + Field Name Writable + ---------- -------- + PersonCharacteristic CVTermDetails Struct+ + PersonDescription lang-alt + PersonId string+ + PersonName lang-alt + +=head3 XMP ProductDetails Struct + + Field Name Writable + ---------- -------- + ProductDescription lang-alt + ProductGTIN string + ProductName lang-alt + +=head3 XMP PublicationEvent Struct + + Field Name Writable + ---------- -------- + Date date + Identifier string + Name string + +=head3 XMP Rating Struct + + Field Name Writable + ---------- -------- + RatingRegion LocationDetails Struct+ + RatingScaleMaxValue string + RatingScaleMinValue string + RatingSourceLink string + RatingValue string + RatingValueLogoLink string + +=head3 XMP Device Struct + + Field Name Writable + ---------- -------- + AttLensDescription string + Manufacturer string + ModelName string + OwnersDeviceId string + SerialNumber string + +=head3 XMP RegistryEntryDetails Struct + + Field Name Writable + ---------- -------- + RegEntryRole string + RegItemId string + RegOrgId string + +=head3 XMP Series Struct + + Field Name Writable + ---------- -------- + Identifier string + Name string + +=head3 XMP LinkedImage Struct + + Field Name Writable + ---------- -------- + HeightPixels integer + ImageRole string + Link string + LinkQualifier string+ + UsedVideoFrame Timecode Struct + WidthPixels integer + Format string + +=head3 XMP Timecode Struct + + Field Name Writable + ---------- -------- + TimeFormat string + TimeValue string + Value integer + +=head3 XMP TemporalCoverage Struct + + Field Name Writable + ---------- -------- + TempCoverageFrom date + TempCoverageTo date + +=head3 XMP LImage Tags + +Tags written by RED smartphones. + +These tags belong to the ExifTool XMP-LImage family 1 group. + + Tag Name Writable + -------- -------- + MajorVersion string + MinorVersion string + RightAlbedo string + +=head3 XMP Lightroom Tags + +Adobe Lightroom "lr" namespace tags. + +These tags belong to the ExifTool XMP-lr family 1 group. + + Tag Name Writable + -------- -------- + HierarchicalSubject string+ + PrivateRTKInfo string + +=head3 XMP MediaPro Tags + +iView MediaPro namespace tags. + +These tags belong to the ExifTool XMP-mediapro family 1 group. + + Tag Name Writable + -------- -------- + CatalogSets string+ + Event string/ + Location string/ + People string+ + Status string + UserFields string+ + +=head3 XMP pdf Tags + +Adobe PDF namespace tags. The official XMP specification defines only +Keywords, PDFVersion, Producer and Trapped. The other tags are included +because they have been observed in PDF files, but some are avoided when +writing due to name conflicts with other XMP namespaces. + +These tags belong to the ExifTool XMP-pdf family 1 group. + + Tag Name Writable + -------- -------- + Author string + Copyright string/ + CreationDate date + Creator string/ + Keywords string + Marked boolean/ + ModDate date + PDFVersion string + Producer string + Subject string/ + Title string/ + Trapped string + +=head3 XMP pdfx Tags + +PDF extension tags. This namespace is used to store application-defined PDF +information, so there are no pre-defined tags. User-defined tags must be +created to enable writing of XMP-pdfx information. + +These tags belong to the ExifTool XMP-pdfx family 1 group. + + Tag Name Writable + -------- -------- + [no tags known] + +=head3 XMP photoshop Tags + +Adobe Photoshop namespace tags. + +These tags belong to the ExifTool XMP-photoshop family 1 group. + + Tag Name Writable + -------- -------- + AuthorsPosition string + CaptionWriter string + Category string + City string + ColorMode integer + Country string + Credit string + DateCreated date + DocumentAncestors string+ + EmbeddedXMPDigest string + Headline string + History string + ICCProfileName string + Instructions string + LegacyIPTCDigest string + SidecarForExtension string + Source string + State string + SupplementalCategories string+ + TextLayers Layer Struct+ + TextLayerName string_+ + TextLayerText string_+ + TransmissionReference string + Urgency integer + +=head3 XMP Layer Struct + + Field Name Writable + ---------- -------- + LayerName string + LayerText string + +=head3 XMP PixelLive Tags + +PixelLive namespace tags. These tags are not writable becase they are very +uncommon and I haven't been able to locate a reference which gives the +namespace URI. + +These tags belong to the ExifTool XMP-PixelLive family 1 group. + + Tag Name Writable + -------- -------- + Author no + Comments no + Copyright no + Date no + Genre no + Title no + +=head3 XMP pmi Tags + +PRISM Metadata for Images 3.0 namespace tags. (see +L<http://www.prismstandard.org/>) + +These tags belong to the ExifTool XMP-pmi family 1 group. + + Tag Name Writable + -------- -------- + Color string/ + ContactInfo string/ + DisplayName string/ + DistributorProductID string/ + EventAlias string/ + EventEnd string/ + EventStart string/ + EventSubtype string/ + EventType string/ + Field string/ + Framing string/ + Location string/ + Make string/ + Manufacturer string/ + Model string/ + ModelYear string/ + ObjectDescription string/ + ObjectSubtype string/ + ObjectType string/ + Orientation string/ + PositionDescriptor string/ + ProductID string/ + ProductIDType string/ + Season string/ + SequenceName string/ + SequenceNumber string/ + SequenceTotalNumber string/ + Setting string/ + ShootID string/ + SlideshowName string/ + SlideshowNumber integer/ + SlideshowTotalNumber integer/ + Viewpoint string/ + VisualTechnique string/ + +=head3 XMP prism Tags + +Publishing Requirements for Industry Standard Metadata 3.0 namespace +tags. (see L<http://www.prismstandard.org/>) + +These tags belong to the ExifTool XMP-prism family 1 group. + + Tag Name Writable + -------- -------- + AcademicField string/ + AggregateIssueNumber integer/ + AggregationType string/+ + AlternateTitle prismAlternateTitle Struct+ + AlternateTitleA-lang string_+ + AlternateTitleA-platform string_+ + AlternateTitleText string_+ + BlogTitle string/ + BlogURL string/ + BookEdition string/ + ByteCount integer/ + Channel prismChannel Struct+ + ChannelA-lang string_+ + ChannelChannel string_+ + ChannelSubchannel1 string_+ + ChannelSubchannel2 string_+ + ChannelSubchannel3 string_+ + ChannelSubchannel4 string_+ + ComplianceProfile string/ + ContentType string/ + CopyrightYear string/ + CorporateEntity string/+ + CoverDate date/ + CoverDisplayDate string/ + CreationDate date/ + DateRecieved date/ + Device string/ + Distributor string/ + DOI string/ + Edition string/ + EIssn string/ + EndingPage string/ + Event string/+ + Genre string/+ + HasAlternative string/+ + HasCorrection prismHasCorrection Struct + HasCorrectionA-lang string_ + HasCorrectionA-platform string_ + HasCorrectionText string_ + HasTranslation string/+ + Industry string/+ + IsAlternativeOf string/+ + ISBN string/+ + IsCorrectionOf string/+ + ISSN string/ + IssueIdentifier string/ + IssueName string/ + IssueTeaser string/ + IssueType string/ + IsTranslationOf string/ + Keyword string/+ + KillDate prismKillDate Struct + KillDateA-platform string_ + KillDateDate date_ + Link string/+ + Location string/+ + ModificationDate date/ + NationalCatalogNumber string/ + Number string/ + Object string/+ + OffSaleDate prismOffSaleDate Struct+ + OffSaleDateA-platform string_+ + OffSaleDateDate date_+ + OnSaleDate prismOnSaleDate Struct+ + OnSaleDateA-platform string_+ + OnSaleDateDate date_+ + OnSaleDay prismOnSaleDay Struct+ + OnSaleDayA-platform string_+ + OnSaleDayDay string_+ + Organization string/+ + OriginPlatform string/+ + PageCount integer/ + PageProgressionDirection string/ + PageRange string/+ + Person string/ + Platform string/ + ProductCode string/ + Profession string/ + PublicationDate prismPublicationDate Struct+ + PublicationDateA-platform string_+ + PublicationDateDate date_+ + PublicationDisplayDate prismPublicationDate Struct+ + PublicationDisplayDateA-platform string_+ + PublicationDisplayDateDate date_+ + PublicationName string/ + PublishingFrequency string/ + Rating string/ + SamplePageRange string/ + Section string/ + SellingAgency string/ + SeriesNumber integer/ + SeriesTitle string/ + Sport string/ + StartingPage string/ + Subsection1 string/ + Subsection2 string/ + Subsection3 string/ + Subsection4 string/ + Subtitle string/ + SupplementDisplayID string/ + SupplementStartingPage string/ + SupplementTitle string/ + Teaser string/+ + Ticker string/+ + TimePeriod string/ + URL prismUrl Struct+ + URLA-platform string_+ + URLUrl string_+ + UspsNumber string/ + VersionIdentifier string/ + Volume string/ + WordCount integer/ + +=head3 XMP prismAlternateTitle Struct + + Field Name Writable + ---------- -------- + A-lang string + A-platform string + Text string + +=head3 XMP prismChannel Struct + + Field Name Writable + ---------- -------- + A-lang string + Channel string + Subchannel1 string + Subchannel2 string + Subchannel3 string + Subchannel4 string + +=head3 XMP prismHasCorrection Struct + + Field Name Writable + ---------- -------- + A-lang string + A-platform string + Text string + +=head3 XMP prismKillDate Struct + + Field Name Writable + ---------- -------- + A-platform string + Date date + +=head3 XMP prismOffSaleDate Struct + + Field Name Writable + ---------- -------- + A-platform string + Date date + +=head3 XMP prismOnSaleDate Struct + + Field Name Writable + ---------- -------- + A-platform string + Date date + +=head3 XMP prismOnSaleDay Struct + + Field Name Writable + ---------- -------- + A-platform string + Day string + +=head3 XMP prismPublicationDate Struct + + Field Name Writable + ---------- -------- + A-platform string + Date date + +=head3 XMP prismUrl Struct + + Field Name Writable + ---------- -------- + A-platform string + Url string + +=head3 XMP prl Tags + +PRISM Rights Language 2.1 namespace tags. These tags have been deprecated +since the release of the PRISM Usage Rights 3.0. (see +L<http://www.prismstandard.org/>) + +These tags belong to the ExifTool XMP-prl family 1 group. + + Tag Name Writable + -------- -------- + Geography string/+ + Industry string/+ + Usage string/+ + +=head3 XMP prm Tags + +PRISM Recipe Metadata 3.0 namespace tags. (see +L<http://www.prismstandard.org/>) + +These tags belong to the ExifTool XMP-prm family 1 group. + + Tag Name Writable + -------- -------- + CookingEquipment string/ + CookingMethod string/ + Course string/ + Cuisine string/ + DietaryNeeds string/ + DishType string/ + Duration string/ + IngredientExclusion string/ + MainIngredient string/ + Meal string/ + RecipeEndingPage string/ + RecipePageRange string/ + RecipeSource string/ + RecipeStartingPage string/ + RecipeTitle string/ + ServingSize string/ + SkillLevel string/ + SpecialOccasion string/ + Yield string/ + +=head3 XMP pur Tags + +PRISM Usage Rights 3.0 namespace tags. (see +L<http://www.prismstandard.org/>) + +These tags belong to the ExifTool XMP-pur family 1 group. + + Tag Name Writable + -------- -------- + AdultContentWarning string/+ + Agreement string/+ + Copyright lang-alt/ + CreditLine string/+ + EmbargoDate date/+ + ExclusivityEndDate date/+ + ExpirationDate date/+ + ImageSizeRestriction string/ + OptionEndDate date/+ + Permissions string/+ + Restrictions string/+ + ReuseProhibited boolean/ + RightsAgent string/ + RightsOwner string/ + +=head3 XMP rdf Tags + +Most RDF attributes are handled internally, but the "about" attribute is +treated specially to allow it to be set to a specific value if required. + +These tags belong to the ExifTool XMP-rdf family 1 group. + + Tag Name Writable + -------- -------- + About string! + +=head3 XMP swf Tags + +Adobe SWF namespace tags. + +These tags belong to the ExifTool XMP-swf family 1 group. + + Tag Name Writable + -------- -------- + BackgroundAlpha integer + ForwardLock boolean + MaxStorage integer + Type string/ + +=head3 XMP tiff Tags + +EXIF namespace for TIFF tags. See +L<http://www.cipa.jp/std/documents/e/DC-010-2017_E.pdf> for the +specification. + +These tags belong to the ExifTool XMP-tiff family 1 group. + + Tag Name Writable + -------- -------- + Artist string + BitsPerSample integer+ + Compression integer + Copyright lang-alt + DateTime date + ImageDescription lang-alt + ImageHeight integer + ImageWidth integer + Make string + Model string + NativeDigest string + Orientation integer + PhotometricInterpretation integer + PlanarConfiguration integer + PrimaryChromaticities rational+ + ReferenceBlackWhite rational+ + ResolutionUnit integer + SamplesPerPixel integer + Software string + TransferFunction integer+ + WhitePoint rational+ + XResolution rational + YCbCrCoefficients rational+ + YCbCrPositioning integer + YCbCrSubSampling integer+ + YResolution rational + +=head3 XMP x Tags + +The "x" namespace is used for the "xmpmeta" wrapper, and may contain an +"xmptk" attribute that is extracted as the XMPToolkit tag. When writing, +the XMPToolkit tag is generated automatically by ExifTool unless +specifically set to another value. + +These tags belong to the ExifTool XMP-x family 1 group. + + Tag Name Writable + -------- -------- + XMPToolkit string! + +=head3 XMP xmp Tags + +XMP namespace tags. If the older "xap", "xapBJ", "xapMM" or "xapRights" +namespace prefixes are found, they are translated to the newer "xmp", +"xmpBJ", "xmpMM" and "xmpRights" prefixes for use in family 1 group names. + +These tags belong to the ExifTool XMP-xmp family 1 group. + + Tag Name Writable + -------- -------- + Advisory string+ + Author string/ + BaseURL string + CreateDate date + CreatorTool string + Description lang-alt/ + Format string/ + Identifier string/+ + Keywords string/ + Label string + MetadataDate date + ModifyDate date + Nickname string + PageInfo PageInfo Struct+ + PageImageFormat string_+ + PageImageHeight integer_+ + PageImage string_+ + PageImagePageNumber integer_+ + PageImageWidth integer_+ + Rating real + Thumbnails Thumbnail Struct+ + ThumbnailFormat string_+ + ThumbnailHeight integer_+ + ThumbnailImage string/_+ + ThumbnailWidth integer_+ + Title lang-alt/ + +=head3 XMP PageInfo Struct + + Field Name Writable + ---------- -------- + PageNumber integer + Format string + Height integer + Image string + Width integer + +=head3 XMP Thumbnail Struct + + Field Name Writable + ---------- -------- + Format string + Height integer + Image string + Width integer + +=head3 XMP xmpBJ Tags + +XMP Basic Job Ticket namespace tags. + +These tags belong to the ExifTool XMP-xmpBJ family 1 group. + + Tag Name Writable + -------- -------- + JobRef JobRef Struct+ + JobRefId string_+ + JobRefName string_+ + JobRefUrl string_+ + +=head3 XMP JobRef Struct + + Field Name Writable + ---------- -------- + Id string + Name string + Url string + +=head3 XMP xmpDM Tags + +XMP Dynamic Media namespace tags. + +These tags belong to the ExifTool XMP-xmpDM family 1 group. + + Tag Name Writable + -------- -------- + AbsPeakAudioFilePath string + Album string + AltTapeName string + AltTimecode Timecode Struct + AltTimecodeTimeFormat string_ + AltTimecodeTimeValue string_ + AltTimecodeValue integer_ + Artist string/ + AudioChannelType string + AudioCompressor string + AudioModDate date + AudioSampleRate integer + AudioSampleType string + BeatSpliceParams BeatSpliceStretch Struct + BeatSpliceParamsRiseInDecibel real_ + BeatSpliceParamsRiseInTimeDuration Time Struct_ + BeatSpliceParamsRiseInTimeDurationScale rational_ + BeatSpliceParamsRiseInTimeDurationValue integer_ + BeatSpliceParamsUseFileBeatsMarker boolean_ + CameraAngle string + CameraLabel string + CameraModel string + CameraMove string + Client string + DMComment string + Composer string + ContributedMedia Media Struct+ + ContributedMediaDuration Time Struct_+ + ContributedMediaDurationScale rational_+ + ContributedMediaDurationValue integer_+ + ContributedMediaManaged boolean_+ + ContributedMediaPath string_+ + ContributedMediaStartTime Time Struct_+ + ContributedMediaStartTimeScale rational_+ + ContributedMediaStartTimeValue integer_+ + ContributedMediaTrack string_+ + ContributedMediaWebStatement string_+ + Copyright string/ + Director string + DirectorPhotography string + DiscNumber string + Duration Time Struct + DurationScale rational_ + DurationValue integer_ + Engineer string + FileDataRate rational + Genre string + Good boolean + Instrument string + IntroTime Time Struct + IntroTimeScale rational_ + IntroTimeValue integer_ + Key string + LogComment string + Loop boolean + Lyrics string + Markers Marker Struct+ + MarkersComment string_+ + MarkersCuePointParams CuePointParam Struct_+ + MarkersCuePointParamsKey string_+ + MarkersCuePointParamsValue string_+ + MarkersCuePointType string_+ + MarkersDuration string_+ + MarkersLocation string_+ + MarkersName string_+ + MarkersProbability real_+ + MarkersSpeaker string_+ + MarkersStartTime string_+ + MarkersTarget string_+ + MarkersType string_+ + MetadataModDate date + NumberOfBeats real + OutCue Time Struct + OutCueScale rational_ + OutCueValue integer_ + PartOfCompilation boolean + ProjectName string + ProjectRef ProjectLink Struct + ProjectRefPath string_ + ProjectRefType string_ + PullDown string + RelativePeakAudioFilePath string + RelativeTimestamp Time Struct + RelativeTimestampScale rational_ + RelativeTimestampValue integer_ + ReleaseDate date + ResampleParams ResampleStretch Struct + ResampleParamsQuality string_ + ScaleType string + Scene string/ + ShotDate date + ShotDay string + ShotLocation string + ShotName string + ShotNumber string + ShotSize string + SpeakerPlacement string + StartTimecode Timecode Struct + StartTimecodeTimeFormat string_ + StartTimecodeTimeValue string_ + StartTimecodeValue integer_ + StartTimeSampleSize integer + StartTimeScale string + StretchMode string + TakeNumber integer + TapeName string + Tempo real + TimeScaleParams TimeScaleStretch Struct + TimeScaleParamsFrameOverlappingPercentage real_ + TimeScaleParamsFrameSize real_ + TimeScaleParamsQuality string_ + TimeSignature string + TrackNumber integer + Tracks Track Struct+ + TracksFrameRate string_+ + TracksMarkers Marker Struct_+ + TracksMarkersComment string_+ + TracksMarkersCuePointParams CuePointParam Struct_+ + TracksMarkersCuePointParamsKey string_+ + TracksMarkersCuePointParamsValue string_+ + TracksMarkersCuePointType string_+ + TracksMarkersDuration string_+ + TracksMarkersLocation string_+ + TracksMarkersName string_+ + TracksMarkersProbability real_+ + TracksMarkersSpeaker string_+ + TracksMarkersStartTime string_+ + TracksMarkersTarget string_+ + TracksMarkersType string_+ + TracksTrackName string_+ + TracksTrackType string_+ + VideoAlphaMode string + VideoAlphaPremultipleColor Colorant Struct + VideoAlphaPremultipleColorA integer_ + VideoAlphaPremultipleColorB integer_ + VideoAlphaPremultipleColorBlack real_ + VideoAlphaPremultipleColorBlue integer_ + VideoAlphaPremultipleColorCyan real_ + VideoAlphaPremultipleColorGray integer_ + VideoAlphaPremultipleColorGreen integer_ + VideoAlphaPremultipleColorL real_ + VideoAlphaPremultipleColorMagenta real_ + VideoAlphaPremultipleColorMode string_ + VideoAlphaPremultipleColorRed integer_ + VideoAlphaPremultipleColorSwatchName string_ + VideoAlphaPremultipleColorTint integer_ + VideoAlphaPremultipleColorType string_ + VideoAlphaPremultipleColorYellow real_ + VideoAlphaUnityIsTransparent boolean + VideoColorSpace string + VideoCompressor string + VideoFieldOrder string + VideoFrameRate real + VideoFrameSize Dimensions Struct + VideoFrameSizeH real_ + VideoFrameSizeUnit string_ + VideoFrameSizeW real_ + VideoModDate date + VideoPixelAspectRatio rational + VideoPixelDepth string + +=head3 XMP BeatSpliceStretch Struct + + Field Name Writable + ---------- -------- + RiseInDecibel real + RiseInTimeDuration Time Struct + UseFileBeatsMarker boolean + +=head3 XMP Time Struct + + Field Name Writable + ---------- -------- + Scale rational + Value integer + +=head3 XMP Media Struct + + Field Name Writable + ---------- -------- + Duration Time Struct + Managed boolean + Path string + StartTime Time Struct + Track string + WebStatement string + +=head3 XMP Marker Struct + + Field Name Writable + ---------- -------- + Comment string + CuePointParams CuePointParam Struct+ + CuePointType string + Duration string + Location string + Name string + Probability real + Speaker string + StartTime string + Target string + Type string + +=head3 XMP CuePointParam Struct + + Field Name Writable + ---------- -------- + Key string + Value string + +=head3 XMP ProjectLink Struct + + Field Name Writable + ---------- -------- + Path string + Type string + +=head3 XMP ResampleStretch Struct + + Field Name Writable + ---------- -------- + Quality string + +=head3 XMP TimeScaleStretch Struct + + Field Name Writable + ---------- -------- + FrameOverlappingPercentage real + FrameSize real + Quality string + +=head3 XMP Track Struct + + Field Name Writable + ---------- -------- + FrameRate string + Markers Marker Struct+ + TrackName string + TrackType string + +=head3 XMP Colorant Struct + + Field Name Writable + ---------- -------- + A integer + B integer + L real + Black real + Blue integer + Cyan real + Gray integer + Green integer + Magenta real + Mode string + Red integer + SwatchName string + Tint integer + Type string + Yellow real + +=head3 XMP Dimensions Struct + + Field Name Writable + ---------- -------- + H real + Unit string + W real + +=head3 XMP xmpMM Tags + +XMP Media Management namespace tags. + +These tags belong to the ExifTool XMP-xmpMM family 1 group. + + Tag Name Writable + -------- -------- + DerivedFrom ResourceRef Struct + DerivedFromAlternatePaths string_+ + DerivedFromDocumentID string_ + DerivedFromFilePath string_ + DerivedFromFromPart string_ + DerivedFromInstanceID string_ + DerivedFromLastModifyDate date_ + DerivedFromLastURL string_ + DerivedFromLinkCategory string_ + DerivedFromLinkForm string_ + DerivedFromManager string_ + DerivedFromManagerVariant string_ + DerivedFromManageTo string_ + DerivedFromManageUI string_ + DerivedFromMaskMarkers string_ + DerivedFromOriginalDocumentID string_ + DerivedFromPartMapping string_ + DerivedFromPlacedResolutionUnit string_ + DerivedFromPlacedXResolution string_ + DerivedFromPlacedYResolution string_ + DerivedFromRenditionClass string_ + DerivedFromRenditionParams string_ + DerivedFromToPart string_ + DerivedFromVersionID string_ + DocumentID string + History ResourceEvent Struct+ + HistoryAction string_+ + HistoryChanged string_+ + HistoryInstanceID string_+ + HistoryParameters string_+ + HistorySoftwareAgent string_+ + HistoryWhen date_+ + Ingredients ResourceRef Struct+ + IngredientsAlternatePaths string_+ + IngredientsDocumentID string_+ + IngredientsFilePath string_+ + IngredientsFromPart string_+ + IngredientsInstanceID string_+ + IngredientsLastModifyDate date_+ + IngredientsLastURL string_+ + IngredientsLinkCategory string_+ + IngredientsLinkForm string_+ + IngredientsManager string_+ + IngredientsManagerVariant string_+ + IngredientsManageTo string_+ + IngredientsManageUI string_+ + IngredientsMaskMarkers string_+ + IngredientsOriginalDocumentID string_+ + IngredientsPartMapping string_+ + IngredientsPlacedResolutionUnit string_+ + IngredientsPlacedXResolution string_+ + IngredientsPlacedYResolution string_+ + IngredientsRenditionClass string_+ + IngredientsRenditionParams string_+ + IngredientsToPart string_+ + IngredientsVersionID string_+ + InstanceID string + LastURL string + ManagedFrom ResourceRef Struct + ManagedFromAlternatePaths string_+ + ManagedFromDocumentID string_ + ManagedFromFilePath string_ + ManagedFromFromPart string_ + ManagedFromInstanceID string_ + ManagedFromLastModifyDate date_ + ManagedFromLastURL string_ + ManagedFromLinkCategory string_ + ManagedFromLinkForm string_ + ManagedFromManager string_ + ManagedFromManagerVariant string_ + ManagedFromManageTo string_ + ManagedFromManageUI string_ + ManagedFromMaskMarkers string_ + ManagedFromOriginalDocumentID string_ + ManagedFromPartMapping string_ + ManagedFromPlacedResolutionUnit string_ + ManagedFromPlacedXResolution string_ + ManagedFromPlacedYResolution string_ + ManagedFromRenditionClass string_ + ManagedFromRenditionParams string_ + ManagedFromToPart string_ + ManagedFromVersionID string_ + Manager string + ManagerVariant string + ManageTo string + ManageUI string + Manifest ManifestItem Struct+ + ManifestLinkForm string_+ + ManifestPlacedResolutionUnit string_+ + ManifestPlacedXResolution real_+ + ManifestPlacedYResolution real_+ + ManifestReference ResourceRef Struct_+ + ManifestReferenceAlternatePaths string_+ + ManifestReferenceDocumentID string_+ + ManifestReferenceFilePath string_+ + ManifestReferenceFromPart string_+ + ManifestReferenceInstanceID string_+ + ManifestReferenceLastModifyDate date_+ + ManifestReferenceLastURL string_+ + ManifestReferenceLinkCategory string_+ + ManifestReferenceLinkForm string_+ + ManifestReferenceManager string_+ + ManifestReferenceManagerVariant string_+ + ManifestReferenceManageTo string_+ + ManifestReferenceManageUI string_+ + ManifestReferenceMaskMarkers string_+ + ManifestReferenceOriginalDocumentID string_+ + ManifestReferencePartMapping string_+ + ManifestReferencePlacedResolutionUnit string_+ + ManifestReferencePlacedXResolution string_+ + ManifestReferencePlacedYResolution string_+ + ManifestReferenceRenditionClass string_+ + ManifestReferenceRenditionParams string_+ + ManifestReferenceToPart string_+ + ManifestReferenceVersionID string_+ + OriginalDocumentID string + Pantry PantryItem Struct+ + PreservedFileName string + RenditionClass string + RenditionOf ResourceRef Struct + RenditionOfAlternatePaths string_+ + RenditionOfDocumentID string_ + RenditionOfFilePath string_ + RenditionOfFromPart string_ + RenditionOfInstanceID string_ + RenditionOfLastModifyDate date_ + RenditionOfLastURL string_ + RenditionOfLinkCategory string_ + RenditionOfLinkForm string_ + RenditionOfManager string_ + RenditionOfManagerVariant string_ + RenditionOfManageTo string_ + RenditionOfManageUI string_ + RenditionOfMaskMarkers string_ + RenditionOfOriginalDocumentID string_ + RenditionOfPartMapping string_ + RenditionOfPlacedResolutionUnit string_ + RenditionOfPlacedXResolution string_ + RenditionOfPlacedYResolution string_ + RenditionOfRenditionClass string_ + RenditionOfRenditionParams string_ + RenditionOfToPart string_ + RenditionOfVersionID string_ + RenditionParams string + SaveID integer + Subject string/+ + VersionID string + Versions Version Struct+ + VersionsComments string_+ + VersionsEvent ResourceEvent Struct_+ + VersionsEventAction string_+ + VersionsEventChanged string_+ + VersionsEventInstanceID string_+ + VersionsEventParameters string_+ + VersionsEventSoftwareAgent string_+ + VersionsEventWhen date_+ + VersionsModifier string_+ + VersionsModifyDate date_+ + VersionsVersion string_+ + +=head3 XMP ResourceRef Struct + + Field Name Writable + ---------- -------- + AlternatePaths string+ + DocumentID string + FilePath string + FromPart string + InstanceID string + LastModifyDate date + LastURL string + LinkCategory string + LinkForm string + ManageTo string + ManageUI string + Manager string + ManagerVariant string + MaskMarkers string + OriginalDocumentID string + PartMapping string + PlacedResolutionUnit string + PlacedXResolution string + PlacedYResolution string + RenditionClass string + RenditionParams string + ToPart string + VersionID string + +=head3 XMP ResourceEvent Struct + + Field Name Writable + ---------- -------- + Action string + Changed string + InstanceID string + Parameters string + SoftwareAgent string + When date + +=head3 XMP ManifestItem Struct + + Field Name Writable + ---------- -------- + LinkForm string + PlacedResolutionUnit string + PlacedXResolution real + PlacedYResolution real + Reference ResourceRef Struct + +=head3 XMP PantryItem Struct + +This structure must have an InstanceID field, but may also contain any other +XMP properties. + + Field Name Writable + ---------- -------- + InstanceID string + +=head3 XMP Version Struct + + Field Name Writable + ---------- -------- + Comments string + Event ResourceEvent Struct + Modifier string + ModifyDate date + Version string + +=head3 XMP xmpNote Tags + +XMP Note namespace tags. + +These tags belong to the ExifTool XMP-xmpNote family 1 group. + + Tag Name Writable + -------- -------- + HasExtendedXMP string* + +=head3 XMP xmpPLUS Tags + +XMP Picture Licensing Universal System (PLUS) tags as written by some older +Adobe applications. See L<PLUS XMP Tags|Image::ExifTool::TagNames/PLUS XMP Tags> +for the current PLUS tags. + +These tags belong to the ExifTool XMP-xmpPLUS family 1 group. + + Tag Name Writable + -------- -------- + CreditLineReq boolean/ + ReuseAllowed boolean/ + +=head3 XMP xmpRights Tags + +XMP Rights Management namespace tags. + +These tags belong to the ExifTool XMP-xmpRights family 1 group. + + Tag Name Writable + -------- -------- + Certificate string + Marked boolean + Owner string+ + UsageTerms lang-alt + WebStatement string + +=head3 XMP xmpTPg Tags + +XMP Paged-Text namespace tags. + +These tags belong to the ExifTool XMP-xmpTPg family 1 group. + + Tag Name Writable + -------- -------- + Colorants Colorant Struct+ + ColorantA integer_+ + ColorantB integer_+ + ColorantBlack real_+ + ColorantBlue integer_+ + ColorantCyan real_+ + ColorantGray integer_+ + ColorantGreen integer_+ + ColorantL real_+ + ColorantMagenta real_+ + ColorantMode string_+ + ColorantRed integer_+ + ColorantSwatchName string_+ + ColorantTint integer_+ + ColorantType string_+ + ColorantYellow real_+ + Fonts Font Struct+ + ChildFontFiles string_+ + FontComposite boolean_+ + FontFace string_+ + FontFamily string_+ + FontFileName string_+ + FontName string_+ + FontType string_+ + FontVersion string_+ + HasVisibleOverprint boolean + HasVisibleTransparency boolean + MaxPageSize Dimensions Struct + MaxPageSizeH real_ + MaxPageSizeUnit string_ + MaxPageSizeW real_ + NPages integer + PlateNames string+ + SwatchGroups SwatchGroup Struct+ + SwatchGroupsColorants Colorant Struct_+ + SwatchColorantA integer_+ + SwatchColorantB integer_+ + SwatchColorantBlack real_+ + SwatchColorantBlue integer_+ + SwatchColorantCyan real_+ + SwatchColorantGray integer_+ + SwatchColorantGreen integer_+ + SwatchColorantL real_+ + SwatchColorantMagenta real_+ + SwatchColorantMode string_+ + SwatchColorantRed integer_+ + SwatchColorantSwatchName string_+ + SwatchColorantTint integer_+ + SwatchColorantType string_+ + SwatchColorantYellow real_+ + SwatchGroupName string_+ + SwatchGroupType integer_+ + +=head3 XMP Font Struct + + Field Name Writable + ---------- -------- + ChildFontFiles string+ + Composite boolean + FontFace string + FontFamily string + FontFileName string + FontName string + FontType string + VersionString string + +=head3 XMP SwatchGroup Struct + + Field Name Writable + ---------- -------- + Colorants Colorant Struct+ + GroupName string + GroupType integer + +=head3 XMP XML Tags + + Tag ID Tag Name Writable + ------ -------- -------- + 'dc' dc XMP dc + 'lastUpdate' LastUpdate no + +=head3 XMP SVG Tags + +SVG (Scalable Vector Graphics) image tags. By default, only the top-level +SVG and Metadata tags are extracted from these images, but all graphics tags +may be extracted by setting the Unknown option to 2 (-U on the command +line). The SVG tags are not part of XMP as such, but are included with the +XMP module for convenience. (see L<http://www.w3.org/TR/SVG11/>) + +These tags belong to the ExifTool XMP-svg family 1 group. + + Tag ID Tag Name Writable + ------ -------- -------- + 'height' ImageHeight no + 'id' ID no + 'metadataId' MetadataID no + 'version' SVGVersion no + 'width' ImageWidth no + +=head2 GPS Tags + +These GPS tags are part of the EXIF standard, and are stored in a separate +IFD within the EXIF information. + +ExifTool is very flexible about the input format when writing lat/long +coordinates, and will accept from 1 to 3 floating point numbers (for decimal +degrees, degrees and minutes, or degrees, minutes and seconds) separated by +just about anything, and will format them properly according to the EXIF +specification. + +Some GPS tags have values which are fixed-length strings. For these, the +indicated string lengths include a null terminator which is added +automatically by ExifTool. Remember that the descriptive values are used +when writing (eg. 'Above Sea Level', not '0') unless the print conversion is +disabled (with '-n' on the command line or the PrintConv option in the API, +or by suffixing the tag name with a C<#> character). + +When adding GPS information to an image, it is important to set all of the +following tags: GPSLatitude, GPSLatitudeRef, GPSLongitude, GPSLongitudeRef, +and GPSAltitude and GPSAltitudeRef if the altitude is known. ExifTool will +write the required GPSVersionID tag automatically if new a GPS IFD is added +to an image. + + Tag ID Tag Name Writable + ------ -------- -------- + 0x0000 GPSVersionID int8u[4]: + 0x0001 GPSLatitudeRef string[2] + 0x0002 GPSLatitude rational64u[3] + 0x0003 GPSLongitudeRef string[2] + 0x0004 GPSLongitude rational64u[3] + 0x0005 GPSAltitudeRef int8u + 0x0006 GPSAltitude rational64u + 0x0007 GPSTimeStamp rational64u[3] + 0x0008 GPSSatellites string + 0x0009 GPSStatus string[2] + 0x000a GPSMeasureMode string[2] + 0x000b GPSDOP rational64u + 0x000c GPSSpeedRef string[2] + 0x000d GPSSpeed rational64u + 0x000e GPSTrackRef string[2] + 0x000f GPSTrack rational64u + 0x0010 GPSImgDirectionRef string[2] + 0x0011 GPSImgDirection rational64u + 0x0012 GPSMapDatum string + 0x0013 GPSDestLatitudeRef string[2] + 0x0014 GPSDestLatitude rational64u[3] + 0x0015 GPSDestLongitudeRef string[2] + 0x0016 GPSDestLongitude rational64u[3] + 0x0017 GPSDestBearingRef string[2] + 0x0018 GPSDestBearing rational64u + 0x0019 GPSDestDistanceRef string[2] + 0x001a GPSDestDistance rational64u + 0x001b GPSProcessingMethod undef + 0x001c GPSAreaInformation undef + 0x001d GPSDateStamp string[11] + 0x001e GPSDifferential int16u + 0x001f GPSHPositioningError rational64u + +=head2 GeoTiff Tags + +ExifTool extracts the following tags from GeoTIFF images. See +L<http://www.remotesensing.org/geotiff/spec/geotiffhome.html> for the +complete GeoTIFF specification. Also included in the table below are +ChartTIFF tags (see L<http://www.charttiff.com/whitepapers.shtml>). GeoTIFF +tags are not writable individually, but they may be copied en mass via the +block tags GeoTiffDirectory, GeoTiffDoubleParams and GeoTiffAsciiParams. + + Tag ID Tag Name Writable + ------ -------- -------- + 0x0001 GeoTiffVersion no + 0x0400 GTModelType no + 0x0401 GTRasterType no + 0x0402 GTCitation no + 0x0800 GeographicType no + 0x0801 GeogCitation no + 0x0802 GeogGeodeticDatum no + 0x0803 GeogPrimeMeridian no + 0x0804 GeogLinearUnits no + 0x0805 GeogLinearUnitSize no + 0x0806 GeogAngularUnits no + 0x0807 GeogAngularUnitSize no + 0x0808 GeogEllipsoid no + 0x0809 GeogSemiMajorAxis no + 0x080a GeogSemiMinorAxis no + 0x080b GeogInvFlattening no + 0x080c GeogAzimuthUnits no + 0x080d GeogPrimeMeridianLong no + 0x080e GeogToWGS84 no + 0x0c00 ProjectedCSType no + 0x0c01 PCSCitation no + 0x0c02 Projection no + 0x0c03 ProjCoordTrans no + 0x0c04 ProjLinearUnits no + 0x0c05 ProjLinearUnitSize no + 0x0c06 ProjStdParallel1 no + 0x0c07 ProjStdParallel2 no + 0x0c08 ProjNatOriginLong no + 0x0c09 ProjNatOriginLat no + 0x0c0a ProjFalseEasting no + 0x0c0b ProjFalseNorthing no + 0x0c0c ProjFalseOriginLong no + 0x0c0d ProjFalseOriginLat no + 0x0c0e ProjFalseOriginEasting no + 0x0c0f ProjFalseOriginNorthing no + 0x0c10 ProjCenterLong no + 0x0c11 ProjCenterLat no + 0x0c12 ProjCenterEasting no + 0x0c13 ProjCenterNorthing no + 0x0c14 ProjScaleAtNatOrigin no + 0x0c15 ProjScaleAtCenter no + 0x0c16 ProjAzimuthAngle no + 0x0c17 ProjStraightVertPoleLong no + 0x0c18 ProjRectifiedGridAngle no + 0x1000 VerticalCSType no + 0x1001 VerticalCitation no + 0x1002 VerticalDatum no + 0x1003 VerticalUnits no + 0xb799 ChartFormat no + 0xb79a ChartSource no + 0xb79b ChartSourceEdition no + 0xb79c ChartSourceDate no + 0xb79d ChartCorrDate no + 0xb79e ChartCountryOrigin no + 0xb79f ChartRasterEdition no + 0xb7a0 ChartSoundingDatum no + 0xb7a1 ChartDepthUnits no + 0xb7a2 ChartMagVar no + 0xb7a3 ChartMagVarYear no + 0xb7a4 ChartMagVarAnnChange no + 0xb7a5 ChartWGSNSShift no + 0xb7a7 InsetNWPixelX no + 0xb7a8 InsetNWPixelY no + 0xb7a9 ChartContourInterval no + +=head2 PLUS Tags + +=head3 PLUS XMP Tags + +PLUS (Picture Licensing Universal System) License Data Format 1.2.1 XMP +tags. Note that all controlled-vocabulary tags in this table (ie. tags with +a fixed set of values) have raw values which begin with +"http://ns.useplus.org/ldf/vocab/", but to reduce clutter this prefix has +been removed from the values shown below. See L<http://ns.useplus.org/> for +the complete specification. + +These tags belong to the ExifTool XMP-plus family 1 group. + + Tag Name Writable + -------- -------- + AdultContentWarning string + CopyrightOwner CopyrightOwner Struct+ + CopyrightOwnerID string_+ + CopyrightOwnerName string_+ + CopyrightOwnerImageID string + CopyrightRegistrationNumber string + CopyrightStatus string + CreditLineRequired string + Custom1 lang-alt+ + Custom10 lang-alt+ + Custom2 lang-alt+ + Custom3 lang-alt+ + Custom4 lang-alt+ + Custom5 lang-alt+ + Custom6 lang-alt+ + Custom7 lang-alt+ + Custom8 lang-alt+ + Custom9 lang-alt+ + EndUser EndUser Struct+ + EndUserID string_+ + EndUserName string_+ + FileNameAsDelivered string + FirstPublicationDate date + ImageAlterationConstraints string+ + ImageCreator ImageCreator Struct+ + ImageCreatorID string_+ + ImageCreatorName string_+ + ImageCreatorImageID string + ImageDuplicationConstraints string + ImageFileConstraints string+ + ImageFileFormatAsDelivered string + ImageFileSizeAsDelivered string + ImageSupplier ImageSupplier Struct+ + ImageSupplierImageID string + ImageSupplierID string_+ + ImageSupplierName string_+ + ImageType string + Licensee Licensee Struct+ + LicenseeImageID string + LicenseeImageNotes lang-alt + LicenseeID string_+ + LicenseeName string_+ + LicenseEndDate date + LicenseeProjectReference string+ + LicenseeTransactionID string+ + LicenseID string + LicenseStartDate date + LicenseTransactionDate date + Licensor Licensor Struct+ + LicensorImageID string + LicensorCity string_+ + LicensorCountry string_+ + LicensorEmail string_+ + LicensorExtendedAddress string_+ + LicensorID string_+ + LicensorName string_+ + LicensorPostalCode string_+ + LicensorRegion string_+ + LicensorStreetAddress string_+ + LicensorTelephone1 string_+ + LicensorTelephone2 string_+ + LicensorTelephoneType1 string_+ + LicensorTelephoneType2 string_+ + LicensorURL string_+ + LicensorNotes lang-alt + LicensorTransactionID string+ + MediaConstraints lang-alt + MediaSummaryCode string + MinorModelAgeDisclosure string + ModelReleaseID string+ + ModelReleaseStatus string + OtherConditions lang-alt + OtherConstraints lang-alt + OtherImageInfo lang-alt + OtherLicenseDocuments string+ + OtherLicenseInfo lang-alt + OtherLicenseRequirements lang-alt + ProductOrServiceConstraints lang-alt + PropertyReleaseID string+ + PropertyReleaseStatus string + RegionConstraints lang-alt + Reuse string + TermsAndConditionsText lang-alt + TermsAndConditionsURL string + PLUSVersion string + +=head3 XMP CopyrightOwner Struct + + Field Name Writable + ---------- -------- + CopyrightOwnerID string + CopyrightOwnerName string + +=head3 XMP EndUser Struct + + Field Name Writable + ---------- -------- + EndUserID string + EndUserName string + +=head3 XMP ImageCreator Struct + + Field Name Writable + ---------- -------- + ImageCreatorID string + ImageCreatorName string + +=head3 XMP ImageSupplier Struct + + Field Name Writable + ---------- -------- + ImageSupplierID string + ImageSupplierName string + +=head3 XMP Licensee Struct + + Field Name Writable + ---------- -------- + LicenseeID string + LicenseeName string + +=head3 XMP Licensor Struct + + Field Name Writable + ---------- -------- + LicensorCity string + LicensorCountry string + LicensorEmail string + LicensorExtendedAddress string + LicensorID string + LicensorName string + LicensorPostalCode string + LicensorRegion string + LicensorStreetAddress string + LicensorTelephone1 string + LicensorTelephone2 string + LicensorTelephoneType1 string + LicensorTelephoneType2 string + LicensorURL string + +=head2 ICC_Profile Tags + +ICC profile information is used in many different file types including JPEG, +TIFF, PDF, PostScript, Photoshop, PNG, MIFF, PICT, QuickTime, XCF and some +RAW formats. While the tags listed below are not individually writable, the +entire profile itself can be accessed via the extra 'ICC_Profile' tag, but +this tag is neither extracted nor written unless specified explicitly. See +L<http://www.color.org/icc_specs2.xalter> for the official ICC +specification. + + Tag ID Tag Name Writable + ------ -------- -------- + 'A2B0' AToB0 no + 'A2B1' AToB1 no + 'A2B2' AToB2 no + 'B2A0' BToA0 no + 'B2A1' BToA1 no + 'B2A2' BToA2 no + 'B2D0' BToD0 no + 'B2D1' BToD1 no + 'B2D2' BToD2 no + 'B2D3' BToD3 no + 'D2B0' DToB0 no + 'D2B1' DToB1 no + 'D2B2' DToB2 no + 'D2B3' DToB3 no + 'Header' ProfileHeader ICC_Profile Header + 'MS00' WCSProfiles no + 'bTRC' BlueTRC no + 'bXYZ' BlueMatrixColumn no + 'bfd ' UCRBG no + 'bkpt' MediaBlackPoint no + 'calt' CalibrationDateTime no + 'chad' ChromaticAdaptation no + 'chrm' Chromaticity ICC_Profile Chromaticity + 'ciis' ColorimetricIntentImageState no + 'clot' ColorantTableOut no + 'clro' ColorantOrder no + 'clrt' ColorantTable ICC_Profile ColorantTable + 'cprt' ProfileCopyright no + 'crdi' CRDInfo no + 'desc' ProfileDescription no + 'devs' DeviceSettings no + 'dmdd' DeviceModelDesc no + 'dmnd' DeviceMfgDesc no + 'dscm' ProfileDescriptionML no + 'fpce' FocalPlaneColorimetryEstimates no + 'gTRC' GreenTRC no + 'gXYZ' GreenMatrixColumn no + 'gamt' Gamut no + 'kTRC' GrayTRC no + 'lumi' Luminance no + 'meas' Measurement ICC_Profile Measurement + 'meta' Metadata ICC_Profile Metadata + 'mmod' MakeAndModel no + 'ncl2' NamedColor2 no + 'ncol' NamedColor no + 'ndin' NativeDisplayInfo no + 'pre0' Preview0 no + 'pre1' Preview1 no + 'pre2' Preview2 no + 'ps2i' PS2RenderingIntent no + 'ps2s' PostScript2CSA no + 'psd0' PostScript2CRD0 no + 'psd1' PostScript2CRD1 no + 'psd2' PostScript2CRD2 no + 'psd3' PostScript2CRD3 no + 'pseq' ProfileSequenceDesc no + 'psid' ProfileSequenceIdentifier no + 'psvm' PS2CRDVMSize no + 'rTRC' RedTRC no + 'rXYZ' RedMatrixColumn no + 'resp' OutputResponse no + 'rhoc' ReflectionHardcopyOrigColorimetry no + 'rig0' PerceptualRenderingIntentGamut no + 'rig2' SaturationRenderingIntentGamut no + 'rpoc' ReflectionPrintOutputColorimetry no + 'sape' SceneAppearanceEstimates no + 'scoe' SceneColorimetryEstimates no + 'scrd' ScreeningDesc no + 'scrn' Screening no + 'targ' CharTarget no + 'tech' Technology no + 'vcgt' VideoCardGamma no + 'view' ViewingConditions ICC_Profile ViewingConditions + 'vued' ViewingCondDesc no + 'wtpt' MediaWhitePoint no + +=head3 ICC_Profile Header Tags + + Index1 Tag Name Writable + ------ -------- -------- + 4 ProfileCMMType no + 8 ProfileVersion no + 12 ProfileClass no + 16 ColorSpaceData no + 20 ProfileConnectionSpace no + 24 ProfileDateTime no + 36 ProfileFileSignature no + 40 PrimaryPlatform no + 44 CMMFlags no + 48 DeviceManufacturer no + 52 DeviceModel no + 56 DeviceAttributes no + 64 RenderingIntent no + 68 ConnectionSpaceIlluminant no + 80 ProfileCreator no + 84 ProfileID no + +=head3 ICC_Profile Chromaticity Tags + + Index1 Tag Name Writable + ------ -------- -------- + 8 ChromaticityChannels no + 10 ChromaticityColorant no + 12 ChromaticityChannel1 no + 20 ChromaticityChannel2 no + 28 ChromaticityChannel3 no + 36 ChromaticityChannel4 no + +=head3 ICC_Profile ColorantTable Tags + + Index1 Tag Name Writable + ------ -------- -------- + 8 ColorantCount no + 12 Colorant1Name no + 44 Colorant1Coordinates no + 50 Colorant2Name no + 82 Colorant2Coordinates no + 88 Colorant3Name no + 120 Colorant3Coordinates no + +=head3 ICC_Profile Measurement Tags + + Index1 Tag Name Writable + ------ -------- -------- + 8 MeasurementObserver no + 12 MeasurementBacking no + 24 MeasurementGeometry no + 28 MeasurementFlare no + 32 MeasurementIlluminant no + +=head3 ICC_Profile Metadata Tags + +Only these few tags have been pre-defined, but ExifTool will extract any +Metadata tags that exist. + + Tag Name Writable + -------- -------- + ManufacturerName no + MediaColor no + MediaWeight no + +=head3 ICC_Profile ViewingConditions Tags + + Index1 Tag Name Writable + ------ -------- -------- + 8 ViewingCondIlluminant no + 20 ViewingCondSurround no + 32 ViewingCondIlluminantType no + +=head2 PrintIM Tags + +The format of the PrintIM information is known, however no PrintIM tags have +been decoded. Use the Unknown (-u) option to extract PrintIM information. + + Tag ID Tag Name Writable + ------ -------- -------- + 'PrintIMVersion' PrintIMVersion no + +=head2 Photoshop Tags + +Photoshop tags are found in PSD and PSB files, as well as inside embedded +Photoshop information in many other file types (JPEG, TIFF, PDF, PNG to name +a few). + +Many Photoshop tags are marked as Unknown (indicated by a question mark +after the tag name) because the information they provide is not very useful +under normal circumstances. These unknown tags are not extracted unless the +Unknown (-u) option is used. See +L<http://www.adobe.com/devnet-apps/photoshop/fileformatashtml/> for the +official specification + +Photoshop path tags (Tag ID's 0x7d0 to 0xbb5) are not defined by default, +but a config file included in the full ExifTool distribution +(config_files/photoshop_paths.config) contains the tag definitions to allow +access to this information. + + Tag ID Tag Name Writable + ------ -------- -------- + 0x03e8 Photoshop2Info? no + 0x03e9 MacintoshPrintInfo? no + 0x03ea XMLData? no + 0x03eb Photoshop2ColorTable? no + 0x03ed ResolutionInfo Photoshop Resolution + 0x03ee AlphaChannelsNames no + 0x03ef DisplayInfo? no + 0x03f0 PStringCaption? no + 0x03f1 BorderInformation? no + 0x03f2 BackgroundColor? no + 0x03f3 PrintFlags? no + 0x03f4 BW_HalftoningInfo? no + 0x03f5 ColorHalftoningInfo? no + 0x03f6 DuotoneHalftoningInfo? no + 0x03f7 BW_TransferFunc? no + 0x03f8 ColorTransferFuncs? no + 0x03f9 DuotoneTransferFuncs? no + 0x03fa DuotoneImageInfo? no + 0x03fb EffectiveBW? no + 0x03fc ObsoletePhotoshopTag1? no + 0x03fd EPSOptions? no + 0x03fe QuickMaskInfo? no + 0x03ff ObsoletePhotoshopTag2? no + 0x0400 TargetLayerID? no + 0x0401 WorkingPath? no + 0x0402 LayersGroupInfo? no + 0x0403 ObsoletePhotoshopTag3? no + 0x0404 IPTCData IPTC + 0x0405 RawImageMode? no + 0x0406 JPEG_Quality Photoshop JPEG_Quality + 0x0408 GridGuidesInfo? no + 0x0409 PhotoshopBGRThumbnail undef! + 0x040a CopyrightFlag int8u + 0x040b URL string + 0x040c PhotoshopThumbnail undef! + 0x040d GlobalAngle int32u + 0x040e ColorSamplersResource? no + 0x040f ICC_Profile ICC_Profile + 0x0410 Watermark? no + 0x0411 ICC_Untagged? no + 0x0412 EffectsVisible? no + 0x0413 SpotHalftone? no + 0x0414 IDsBaseValue? no + 0x0415 UnicodeAlphaNames? no + 0x0416 IndexedColorTableCount? no + 0x0417 TransparentIndex? no + 0x0419 GlobalAltitude int32u + 0x041a SliceInfo Photoshop SliceInfo + 0x041b WorkflowURL no + 0x041c JumpToXPEP? no + 0x041d AlphaIdentifiers? no + 0x041e URL_List no+ + 0x0421 VersionInfo Photoshop VersionInfo + 0x0422 EXIFInfo EXIF + 0x0423 ExifInfo2? no + 0x0424 XMP XMP + 0x0425 IPTCDigest string! + 0x0426 PrintScaleInfo Photoshop PrintScaleInfo + 0x0428 PixelInfo Photoshop PixelInfo + 0x0429 LayerComps? no + 0x042a AlternateDuotoneColors? no + 0x042b AlternateSpotColors? no + 0x042d LayerSelectionIDs? no + 0x042e HDRToningInfo? no + 0x042f PrintInfo? no + 0x0430 LayerGroupsEnabledID? no + 0x0431 ColorSamplersResource2? no + 0x0432 MeasurementScale? no + 0x0433 TimelineInfo? no + 0x0434 SheetDisclosure? no + 0x0435 DisplayInfo? no + 0x0436 OnionSkins? no + 0x0438 CountInfo? no + 0x043a PrintInfo2? no + 0x043b PrintStyle? no + 0x043c MacintoshNSPrintInfo? no + 0x043d WindowsDEVMODE? no + 0x043e AutoSaveFilePath? no + 0x043f AutoSaveFormat? no + 0x0440 PathSelectionState? no + 0x0bb7 ClippingPathName no + 0x0bb8 OriginPathInfo? no + 0x1b58 ImageReadyVariables? no + 0x1b59 ImageReadyDataSets? no + 0x1f40 LightroomWorkflow? no + 0x2710 PrintFlagsInfo? no + +=head3 Photoshop Resolution Tags + + Index2 Tag Name Writable + ------ -------- -------- + 0 XResolution int32u + 2 DisplayedUnitsX int16u + 4 YResolution int32u + 6 DisplayedUnitsY int16u + +=head3 Photoshop JPEG_Quality Tags + + Index2 Tag Name Writable + ------ -------- -------- + 0 PhotoshopQuality int16s + 1 PhotoshopFormat no + 2 ProgressiveScans no + +=head3 Photoshop SliceInfo Tags + + Index1 Tag Name Writable + ------ -------- -------- + 20 SlicesGroupName no + 24 NumSlices no + +=head3 Photoshop VersionInfo Tags + + Index1 Tag Name Writable + ------ -------- -------- + 4 HasRealMergedData no + 5 WriterName no + 9 ReaderName no + +=head3 Photoshop PrintScaleInfo Tags + + Index1 Tag Name Writable + ------ -------- -------- + 0 PrintStyle no + 2 PrintPosition no + 10 PrintScale no + +=head3 Photoshop PixelInfo Tags + + Index1 Tag Name Writable + ------ -------- -------- + 4 PixelAspectRatio no + +=head3 Photoshop DocumentData Tags + + Tag ID Tag Name Writable + ------ -------- -------- + 'Layr' Layers Photoshop Layers + 'Lr16' Layers Photoshop Layers + +=head3 Photoshop Layers Tags + +Tags extracted from Photoshop layer information. + + Tag ID Tag Name Writable + ------ -------- -------- + '_xbnd' LayerBlendModes no+ + '_xcnt' LayerCount no + '_xnam' LayerNames no+ + '_xopc' LayerOpacities no+ + '_xrct' LayerRectangles no+ + 'luni' LayerUnicodeNames no+ + 'lyid' LayerIDs? no+ + 'shmd' LayerModifyDates no+ + +=head3 Photoshop Header Tags + +This information is found in the PSD file header. + + Index2 Tag Name Writable + ------ -------- -------- + 6 NumChannels no + 7 ImageHeight no + 9 ImageWidth no + 11 BitDepth no + 12 ColorMode no + +=head3 Photoshop ImageData Tags + + Index1 Tag Name Writable + ------ -------- -------- + 0 Compression no + +=head2 Apple Tags + +Tags extracted from the maker notes of iPhone images. + + Tag ID Tag Name Writable + ------ -------- -------- + 0x0003 RunTime Apple RunTime + 0x0008 AccelerationVector rational64s[3] + 0x000a HDRImageType int32s + 0x000b BurstUUID string + 0x0011 ContentIdentifier string + 0x0015 ImageUniqueID string + +=head3 Apple RunTime Tags + +This PLIST-format information contains the elements of a CMTime structure +representing the amount of time the phone has been running since the last +boot, not including standby time. + + Tag ID Tag Name Writable + ------ -------- -------- + 'epoch' RunTimeEpoch no + 'flags' RunTimeFlags no + 'timescale' RunTimeScale no + 'value' RunTimeValue no + +=head2 Canon Tags + + Tag ID Tag Name Writable + ------ -------- -------- + 0x0001 CanonCameraSettings Canon CameraSettings + 0x0002 CanonFocalLength Canon FocalLength + 0x0003 CanonFlashInfo? no + 0x0004 CanonShotInfo Canon ShotInfo + 0x0005 CanonPanorama Canon Panorama + 0x0006 CanonImageType string + 0x0007 CanonFirmwareVersion string + 0x0008 FileNumber int32u + 0x0009 OwnerName string + 0x000a UnknownD30 Canon UnknownD30 + 0x000c SerialNumber int32u + 0x000d CanonCameraInfo1D Canon CameraInfo1D + CanonCameraInfo1DmkII Canon CameraInfo1DmkII + CanonCameraInfo1DmkIIN Canon CameraInfo1DmkIIN + CanonCameraInfo1DmkIII Canon CameraInfo1DmkIII + CanonCameraInfo1DmkIV Canon CameraInfo1DmkIV + CanonCameraInfo1DX Canon CameraInfo1DX + CanonCameraInfo5D Canon CameraInfo5D + CanonCameraInfo5DmkII Canon CameraInfo5DmkII + CanonCameraInfo5DmkIII Canon CameraInfo5DmkIII + CanonCameraInfo6D Canon CameraInfo6D + CanonCameraInfo7D Canon CameraInfo7D + CanonCameraInfo40D Canon CameraInfo40D + CanonCameraInfo50D Canon CameraInfo50D + CanonCameraInfo60D Canon CameraInfo60D + CanonCameraInfo70D Canon CameraInfo70D + CanonCameraInfo80D Canon CameraInfo80D + CanonCameraInfo450D Canon CameraInfo450D + CanonCameraInfo500D Canon CameraInfo500D + CanonCameraInfo550D Canon CameraInfo550D + CanonCameraInfo600D Canon CameraInfo600D + CanonCameraInfo650D Canon CameraInfo650D + CanonCameraInfo700D Canon CameraInfo650D + CanonCameraInfo750D Canon CameraInfo750D + CanonCameraInfo760D Canon CameraInfo750D + CanonCameraInfo1000D Canon CameraInfo1000D + CanonCameraInfo1100D Canon CameraInfo600D + CanonCameraInfo1200D Canon CameraInfo60D + CanonCameraInfoPowerShot Canon CameraInfoPowerShot + CanonCameraInfoPowerShot2 Canon CameraInfoPowerShot2 + CanonCameraInfoUnknown32 Canon CameraInfoUnknown32 + CanonCameraInfoUnknown16 Canon CameraInfoUnknown16 + CanonCameraInfoUnknown Canon CameraInfoUnknown + 0x000e CanonFileLength int32u + 0x000f CustomFunctions1D CanonCustom Functions1D + CustomFunctions5D CanonCustom Functions5D + CustomFunctions10D CanonCustom Functions10D + CustomFunctions20D CanonCustom Functions20D + CustomFunctions30D CanonCustom Functions30D + CustomFunctions350D CanonCustom Functions350D + CustomFunctions400D CanonCustom Functions400D + CustomFunctionsD30 CanonCustom FunctionsD30 + CustomFunctionsD60 CanonCustom FunctionsD30 + CustomFunctionsUnknown CanonCustom FuncsUnknown + 0x0010 CanonModelID int32u + 0x0011 MovieInfo Canon MovieInfo + 0x0012 CanonAFInfo Canon AFInfo + 0x0013 ThumbnailImageValidArea int16u[4] + 0x0015 SerialNumberFormat int32u + 0x001a SuperMacro int16u + 0x001c DateStampMode int16u + 0x001d MyColors Canon MyColors + 0x001e FirmwareRevision int32u + 0x0023 Categories int32u[2] + 0x0024 FaceDetect1 Canon FaceDetect1 + 0x0025 FaceDetect2 Canon FaceDetect2 + 0x0026 CanonAFInfo2 Canon AFInfo2 + 0x0027 ContrastInfo Canon ContrastInfo + 0x0028 ImageUniqueID int8u + 0x002f FaceDetect3 Canon FaceDetect3 + 0x0035 TimeInfo Canon TimeInfo + 0x0038 BatteryType undef + 0x003c AFInfo3 Canon AFInfo2 + 0x0081 RawDataOffset no + 0x0083 OriginalDecisionDataOffset int32u* + 0x0090 CustomFunctions1D CanonCustom Functions1D + 0x0091 PersonalFunctions CanonCustom PersonalFuncs + 0x0092 PersonalFunctionValues CanonCustom PersonalFuncValues + 0x0093 CanonFileInfo Canon FileInfo + 0x0094 AFPointsInFocus1D no + 0x0095 LensModel string + 0x0096 SerialInfo Canon SerialInfo + InternalSerialNumber string + 0x0097 DustRemovalData undef! + 0x0098 CropInfo Canon CropInfo + 0x0099 CustomFunctions2 CanonCustom Functions2 + 0x009a AspectInfo Canon AspectInfo + 0x00a0 ProcessingInfo Canon Processing + 0x00a1 ToneCurveTable no + 0x00a2 SharpnessTable no + 0x00a3 SharpnessFreqTable no + 0x00a4 WhiteBalanceTable no + 0x00a9 ColorBalance Canon ColorBalance + 0x00aa MeasuredColor Canon MeasuredColor + 0x00ae ColorTemperature int16u + 0x00b0 CanonFlags Canon Flags + 0x00b1 ModifiedInfo Canon ModifiedInfo + 0x00b2 ToneCurveMatching no + 0x00b3 WhiteBalanceMatching no + 0x00b4 ColorSpace int16u + 0x00b6 PreviewImageInfo Canon PreviewImageInfo + 0x00d0 VRDOffset int32u* + 0x00e0 SensorInfo Canon SensorInfo + 0x4001 ColorData1 Canon ColorData1 + ColorData2 Canon ColorData2 + ColorData3 Canon ColorData3 + ColorData4 Canon ColorData4 + ColorData5 Canon ColorData5 + ColorData6 Canon ColorData6 + ColorData7 Canon ColorData7 + ColorData8 Canon ColorData8 + ColorData9 Canon ColorData9 + ColorDataUnknown Canon ColorDataUnknown + 0x4002 CRWParam? no + 0x4003 ColorInfo Canon ColorInfo + 0x4005 Flavor? no + 0x4008 PictureStyleUserDef [Values 0-2] + Canon PictureStyle + 0x4009 PictureStylePC [Values 0-2] + Canon PictureStyle + 0x4010 CustomPictureStyleFileName string + 0x4013 AFMicroAdj Canon AFMicroAdj + 0x4015 VignettingCorr Canon VignettingCorr + VignettingCorrUnknown1 Canon VignettingCorrUnknown + VignettingCorrUnknown2 Canon VignettingCorrUnknown + 0x4016 VignettingCorr2 Canon VignettingCorr2 + 0x4018 LightingOpt Canon LightingOpt + 0x4019 LensInfo Canon LensInfo + 0x4020 AmbienceInfo Canon Ambience + 0x4021 MultiExp Canon MultiExp + 0x4024 FilterInfo Canon FilterInfo + 0x4025 HDRInfo Canon HDRInfo + 0x4028 AFConfig Canon AFConfig + +=head3 Canon CameraSettings Tags + + Index2 Tag Name Writable + ------ -------- -------- + 1 MacroMode int16s + 2 SelfTimer int16s + 3 Quality int16s + 4 CanonFlashMode int16s + 5 ContinuousDrive int16s + 7 FocusMode int16s + 9 RecordMode int16s + 10 CanonImageSize int16s + 11 EasyMode int16s + 12 DigitalZoom int16s + 13 Contrast int16s + 14 Saturation int16s + 15 Sharpness int16s + 16 CameraISO int16s + 17 MeteringMode int16s + 18 FocusRange int16s + 19 AFPoint int16s + 20 CanonExposureMode int16s + 22 LensType int16u + 23 MaxFocalLength int16u + 24 MinFocalLength int16u + 25 FocalUnits int16s + 26 MaxAperture int16s + 27 MinAperture int16s + 28 FlashActivity int16s + 29 FlashBits int16s + 32 FocusContinuous int16s + 33 AESetting int16s + 34 ImageStabilization int16s + 35 DisplayAperture int16s + 36 ZoomSourceWidth int16s + 37 ZoomTargetWidth int16s + 39 SpotMeteringMode int16s + 40 PhotoEffect int16s + 41 ManualFlashOutput int16s + 42 ColorTone int16s + 46 SRAWQuality int16s + +=head3 Canon FocalLength Tags + + Index2 Tag Name Writable + ------ -------- -------- + 0 FocalType int16u + 1 FocalLength int16u + 2 FocalPlaneXSize int16u + FocalPlaneXUnknown? int16u + 3 FocalPlaneYSize int16u + FocalPlaneYUnknown? int16u + +=head3 Canon ShotInfo Tags + + Index2 Tag Name Writable + ------ -------- -------- + 1 AutoISO int16s + 2 BaseISO int16s + 3 MeasuredEV int16s + 4 TargetAperture int16s + 5 TargetExposureTime int16s + 6 ExposureCompensation int16s + 7 WhiteBalance int16s + 8 SlowShutter int16s + 9 SequenceNumber int16s + 10 OpticalZoomCode int16s + 12 CameraTemperature int16s + 13 FlashGuideNumber int16s + 14 AFPointsInFocus int16s + 15 FlashExposureComp int16s + 16 AutoExposureBracketing int16s + 17 AEBBracketValue int16s + 18 ControlMode int16s + 19 FocusDistanceUpper int16u + 20 FocusDistanceLower int16u + 21 FNumber int16s + 22 ExposureTime int16s + 23 MeasuredEV2 int16s + 24 BulbDuration int16s + 26 CameraType int16s + 27 AutoRotate int16s + 28 NDFilter int16s + 29 SelfTimer2 int16s + 33 FlashOutput int16s + +=head3 Canon Panorama Tags + + Index2 Tag Name Writable + ------ -------- -------- + 2 PanoramaFrameNumber int16s + 5 PanoramaDirection int16s + +=head3 Canon UnknownD30 Tags + + Index2 Tag Name Writable + ------ -------- -------- + [no tags known] + +=head3 Canon CameraInfo1D Tags + +Information in the "CameraInfo" records is tricky to decode because the +encodings are very different than in other Canon records (even sometimes +switching endianness between values within a single camera), plus there is +considerable variation in format from model to model. The first table below +lists CameraInfo tags for the 1D and 1DS. + + Index1 Tag Name Writable + ------ -------- -------- + 4 ExposureTime int8u + 10 FocalLength int16u + 13 LensType int16uRev + 14 MinFocalLength int16u + 16 MaxFocalLength int16u + 65 SharpnessFrequency int8u + 66 Sharpness int8s + 68 WhiteBalance int8u + 71 SharpnessFrequency int8u + 72 ColorTemperature int16u + Sharpness int8s + 74 WhiteBalance int8u + 75 PictureStyle int8u + 78 ColorTemperature int16u + 81 PictureStyle int8u + +=head3 Canon CameraInfo1DmkII Tags + +CameraInfo tags for the 1DmkII and 1DSmkII. + + Index1 Tag Name Writable + ------ -------- -------- + 4 ExposureTime int8u + 9 FocalLength int16uRev + 12 LensType int16uRev + 17 MinFocalLength int16uRev + 19 MaxFocalLength int16uRev + 45 FocalType int8u + 54 WhiteBalance int8u + 55 ColorTemperature int16uRev + 57 CanonImageSize int16u + 102 JPEGQuality int8u + 108 PictureStyle int8u + 110 Saturation int8s + 111 ColorTone int8s + 114 Sharpness int8s + 115 Contrast int8s + 117 ISO string[5] + +=head3 Canon CameraInfo1DmkIIN Tags + +CameraInfo tags for the 1DmkIIN. + + Index1 Tag Name Writable + ------ -------- -------- + 4 ExposureTime int8u + 9 FocalLength int16uRev + 12 LensType int16uRev + 17 MinFocalLength int16uRev + 19 MaxFocalLength int16uRev + 54 WhiteBalance int8u + 55 ColorTemperature int16uRev + 115 PictureStyle int8u + 116 Sharpness int8s + 117 Contrast int8s + 118 Saturation int8s + 119 ColorTone int8s + 121 ISO string[5] + +=head3 Canon CameraInfo1DmkIII Tags + +CameraInfo tags for the 1DmkIII and 1DSmkIII. + + Index1 Tag Name Writable + ------ -------- -------- + 3 FNumber int8u + 4 ExposureTime int8u + 6 ISO int8u + 24 CameraTemperature int8u + 27 MacroMagnification int8u + 29 FocalLength int16uRev + 48 CameraOrientation int8u + 67 FocusDistanceUpper int16uRev + 69 FocusDistanceLower int16uRev + 94 WhiteBalance int16u + 98 ColorTemperature int16u + 134 PictureStyle int8u + 273 LensType int16uRev + 275 MinFocalLength int16uRev + 277 MaxFocalLength int16uRev + 310 FirmwareVersion string[6] + 370 FileIndex int32u + 374 ShutterCount int32u + 382 DirectoryIndex int32u + 682 PictureStyleInfo Canon PSInfo + 1114 TimeStamp1 int32u + 1118 TimeStamp int32u + +=head3 Canon PSInfo Tags + +Custom picture style information for various models. + + Index1 Tag Name Writable + ------ -------- -------- + 0 ContrastStandard int32s + 4 SharpnessStandard int32s + 8 SaturationStandard int32s + 12 ColorToneStandard int32s + 16 FilterEffectStandard? int32s + 20 ToningEffectStandard? int32s + 24 ContrastPortrait int32s + 28 SharpnessPortrait int32s + 32 SaturationPortrait int32s + 36 ColorTonePortrait int32s + 40 FilterEffectPortrait? int32s + 44 ToningEffectPortrait? int32s + 48 ContrastLandscape int32s + 52 SharpnessLandscape int32s + 56 SaturationLandscape int32s + 60 ColorToneLandscape int32s + 64 FilterEffectLandscape? int32s + 68 ToningEffectLandscape? int32s + 72 ContrastNeutral int32s + 76 SharpnessNeutral int32s + 80 SaturationNeutral int32s + 84 ColorToneNeutral int32s + 88 FilterEffectNeutral? int32s + 92 ToningEffectNeutral? int32s + 96 ContrastFaithful int32s + 100 SharpnessFaithful int32s + 104 SaturationFaithful int32s + 108 ColorToneFaithful int32s + 112 FilterEffectFaithful? int32s + 116 ToningEffectFaithful? int32s + 120 ContrastMonochrome int32s + 124 SharpnessMonochrome int32s + 128 SaturationMonochrome? int32s + 132 ColorToneMonochrome? int32s + 136 FilterEffectMonochrome int32s + 140 ToningEffectMonochrome int32s + 144 ContrastUserDef1 int32s + 148 SharpnessUserDef1 int32s + 152 SaturationUserDef1 int32s + 156 ColorToneUserDef1 int32s + 160 FilterEffectUserDef1 int32s + 164 ToningEffectUserDef1 int32s + 168 ContrastUserDef2 int32s + 172 SharpnessUserDef2 int32s + 176 SaturationUserDef2 int32s + 180 ColorToneUserDef2 int32s + 184 FilterEffectUserDef2 int32s + 188 ToningEffectUserDef2 int32s + 192 ContrastUserDef3 int32s + 196 SharpnessUserDef3 int32s + 200 SaturationUserDef3 int32s + 204 ColorToneUserDef3 int32s + 208 FilterEffectUserDef3 int32s + 212 ToningEffectUserDef3 int32s + 216 UserDef1PictureStyle int16u + 218 UserDef2PictureStyle int16u + 220 UserDef3PictureStyle int16u + +=head3 Canon CameraInfo1DmkIV Tags + +CameraInfo tags for the EOS 1D Mark IV. Indices shown are for firmware +versions 1.0.x, but they may be different for other firmware versions. + + Index1 Tag Name Writable + ------ -------- -------- + 3 FNumber int8u + 4 ExposureTime int8u + 6 ISO int8u + 7 HighlightTonePriority int8u + 8 MeasuredEV2 int8u + 9 MeasuredEV3 int8u + 21 FlashMeteringMode int8u + 25 CameraTemperature int8u + 30 FocalLength int16uRev + 53 CameraOrientation int8u + 84 FocusDistanceUpper int16uRev + 86 FocusDistanceLower int16uRev + 120 WhiteBalance int16u + 124 ColorTemperature int16u + 335 LensType int16uRev + 337 MinFocalLength int16uRev + 339 MaxFocalLength int16uRev + 493 FirmwareVersion no + 556 FileIndex int32u + 568 DirectoryIndex int32u + 872 PictureStyleInfo Canon PSInfo + +=head3 Canon CameraInfo1DX Tags + +CameraInfo tags for the EOS 1D X. Indices shown are for firmware version +1.0.2, but they may be different for other firmware versions. + + Index1 Tag Name Writable + ------ -------- -------- + 3 FNumber int8u + 4 ExposureTime int8u + 6 ISO int8u + 27 CameraTemperature int8u + 35 FocalLength int16uRev + 125 CameraOrientation int8u + 140 FocusDistanceUpper int16uRev + 142 FocusDistanceLower int16uRev + 188 WhiteBalance int16u + 192 ColorTemperature int16u + 244 PictureStyle int8u + 423 LensType int16uRev + 425 MinFocalLength int16uRev + 427 MaxFocalLength int16uRev + 640 FirmwareVersion no + 720 FileIndex int32u + 732 DirectoryIndex int32u + 1012 PictureStyleInfo Canon PSInfo2 + +=head3 Canon PSInfo2 Tags + +Custom picture style information for the EOS 5DmkIII, 60D, 600D and 1100D. + + Index1 Tag Name Writable + ------ -------- -------- + 0 ContrastStandard int32s + 4 SharpnessStandard int32s + 8 SaturationStandard int32s + 12 ColorToneStandard int32s + 16 FilterEffectStandard? int32s + 20 ToningEffectStandard? int32s + 24 ContrastPortrait int32s + 28 SharpnessPortrait int32s + 32 SaturationPortrait int32s + 36 ColorTonePortrait int32s + 40 FilterEffectPortrait? int32s + 44 ToningEffectPortrait? int32s + 48 ContrastLandscape int32s + 52 SharpnessLandscape int32s + 56 SaturationLandscape int32s + 60 ColorToneLandscape int32s + 64 FilterEffectLandscape? int32s + 68 ToningEffectLandscape? int32s + 72 ContrastNeutral int32s + 76 SharpnessNeutral int32s + 80 SaturationNeutral int32s + 84 ColorToneNeutral int32s + 88 FilterEffectNeutral? int32s + 92 ToningEffectNeutral? int32s + 96 ContrastFaithful int32s + 100 SharpnessFaithful int32s + 104 SaturationFaithful int32s + 108 ColorToneFaithful int32s + 112 FilterEffectFaithful? int32s + 116 ToningEffectFaithful? int32s + 120 ContrastMonochrome int32s + 124 SharpnessMonochrome int32s + 128 SaturationMonochrome? int32s + 132 ColorToneMonochrome? int32s + 136 FilterEffectMonochrome int32s + 140 ToningEffectMonochrome int32s + 144 ContrastAuto int32s + 148 SharpnessAuto int32s + 152 SaturationAuto int32s + 156 ColorToneAuto int32s + 160 FilterEffectAuto int32s + 164 ToningEffectAuto int32s + 168 ContrastUserDef1 int32s + 172 SharpnessUserDef1 int32s + 176 SaturationUserDef1 int32s + 180 ColorToneUserDef1 int32s + 184 FilterEffectUserDef1 int32s + 188 ToningEffectUserDef1 int32s + 192 ContrastUserDef2 int32s + 196 SharpnessUserDef2 int32s + 200 SaturationUserDef2 int32s + 204 ColorToneUserDef2 int32s + 208 FilterEffectUserDef2 int32s + 212 ToningEffectUserDef2 int32s + 216 ContrastUserDef3 int32s + 220 SharpnessUserDef3 int32s + 224 SaturationUserDef3 int32s + 228 ColorToneUserDef3 int32s + 232 FilterEffectUserDef3 int32s + 236 ToningEffectUserDef3 int32s + 240 UserDef1PictureStyle int16u + 242 UserDef2PictureStyle int16u + 244 UserDef3PictureStyle int16u + +=head3 Canon CameraInfo5D Tags + +CameraInfo tags for the EOS 5D. + + Index1 Tag Name Writable + ------ -------- -------- + 3 FNumber int8u + 4 ExposureTime int8u + 6 ISO int8u + 12 LensType int16uRev + 23 CameraTemperature int8u + 27 MacroMagnification int8s + 39 CameraOrientation int8s + 40 FocalLength int16uRev + 56 AFPointsInFocus5D int16uRev + 84 WhiteBalance int16u + 88 ColorTemperature int16u + 108 PictureStyle int8u + 147 MinFocalLength int16uRev + 149 MaxFocalLength int16uRev + 151 LensType int16uRev + 164 FirmwareRevision string[8] + 172 ShortOwnerName string[16] + 204 DirectoryIndex int32u + 208 FileIndex int16u + 232 ContrastStandard int8s + 233 ContrastPortrait int8s + 234 ContrastLandscape int8s + 235 ContrastNeutral int8s + 236 ContrastFaithful int8s + 237 ContrastMonochrome int8s + 238 ContrastUserDef1 int8s + 239 ContrastUserDef2 int8s + 240 ContrastUserDef3 int8s + 241 SharpnessStandard int8s + 242 SharpnessPortrait int8s + 243 SharpnessLandscape int8s + 244 SharpnessNeutral int8s + 245 SharpnessFaithful int8s + 246 SharpnessMonochrome int8s + 247 SharpnessUserDef1 int8s + 248 SharpnessUserDef2 int8s + 249 SharpnessUserDef3 int8s + 250 SaturationStandard int8s + 251 SaturationPortrait int8s + 252 SaturationLandscape int8s + 253 SaturationNeutral int8s + 254 SaturationFaithful int8s + 255 FilterEffectMonochrome int8s + 256 SaturationUserDef1 int8s + 257 SaturationUserDef2 int8s + 258 SaturationUserDef3 int8s + 259 ColorToneStandard int8s + 260 ColorTonePortrait int8s + 261 ColorToneLandscape int8s + 262 ColorToneNeutral int8s + 263 ColorToneFaithful int8s + 264 ToningEffectMonochrome int8s + 265 ColorToneUserDef1 int8s + 266 ColorToneUserDef2 int8s + 267 ColorToneUserDef3 int8s + 268 UserDef1PictureStyle int16u + 270 UserDef2PictureStyle int16u + 272 UserDef3PictureStyle int16u + 284 TimeStamp int32u + +=head3 Canon CameraInfo5DmkII Tags + +CameraInfo tags for the EOS 5D Mark II. Indices shown are for firmware +version 1.0.6, but they may be different for other firmware versions. + + Index1 Tag Name Writable + ------ -------- -------- + 3 FNumber int8u + 4 ExposureTime int8u + 6 ISO int8u + 7 HighlightTonePriority int8u + 21 FlashMeteringMode int8u + 25 CameraTemperature int8u + 27 MacroMagnification int8u + 30 FocalLength int16uRev + 49 CameraOrientation int8u + 80 FocusDistanceUpper int16uRev + 82 FocusDistanceLower int16uRev + 111 WhiteBalance int16u + 115 ColorTemperature int16u + 167 PictureStyle int8u + 189 HighISONoiseReduction int8u + 191 AutoLightingOptimizer int8u + 230 LensType int16uRev + 232 MinFocalLength int16uRev + 234 MaxFocalLength int16uRev + 382 FirmwareVersion no + 443 FileIndex int32u + 455 DirectoryIndex int32u + 759 PictureStyleInfo Canon PSInfo + +=head3 Canon CameraInfo5DmkIII Tags + +CameraInfo tags for the EOS 5D Mark III. Indices shown are for firmware +versions 1.0.x, but they may be different for other firmware versions. + + Index1 Tag Name Writable + ------ -------- -------- + 3 FNumber int8u + 4 ExposureTime int8u + 6 ISO int8u + 27 CameraTemperature int8u + 35 FocalLength int16uRev + 125 CameraOrientation int8u + 140 FocusDistanceUpper int16uRev + 142 FocusDistanceLower int16uRev + 188 WhiteBalance int16u + 192 ColorTemperature int16u + 244 PictureStyle int8u + 339 LensType int16uRev + 341 MinFocalLength int16uRev + 343 MaxFocalLength int16uRev + 356 LensSerialNumber undef[5] + 572 FirmwareVersion no + 652 FileIndex int32u + 656 FileIndex2 int32u + 664 DirectoryIndex int32u + 668 DirectoryIndex2 int32u + 944 PictureStyleInfo Canon PSInfo2 + +=head3 Canon CameraInfo6D Tags + +CameraInfo tags for the EOS 6D. + + Index1 Tag Name Writable + ------ -------- -------- + 3 FNumber int8u + 4 ExposureTime int8u + 6 ISO int8u + 27 CameraTemperature int8u + 35 FocalLength int16uRev + 131 CameraOrientation int8u + 146 FocusDistanceUpper int16uRev + 148 FocusDistanceLower int16uRev + 194 WhiteBalance int16u + 198 ColorTemperature int16u + 250 PictureStyle int8u + 353 LensType int16uRev + 355 MinFocalLength int16uRev + 357 MaxFocalLength int16uRev + 598 FirmwareVersion no + 682 FileIndex int32u + 694 DirectoryIndex int32u + 966 PictureStyleInfo Canon PSInfo2 + +=head3 Canon CameraInfo7D Tags + +CameraInfo tags for the EOS 7D. Indices shown are for firmware versions +1.0.x, but they may be different for other firmware versions. + + Index1 Tag Name Writable + ------ -------- -------- + 3 FNumber int8u + 4 ExposureTime int8u + 6 ISO int8u + 7 HighlightTonePriority int8u + 8 MeasuredEV2 int8u + 9 MeasuredEV int8u + 21 FlashMeteringMode int8u + 25 CameraTemperature int8u + 30 FocalLength int16uRev + 53 CameraOrientation int8u + 84 FocusDistanceUpper int16uRev + 86 FocusDistanceLower int16uRev + 119 WhiteBalance int16u + 123 ColorTemperature int16u + 175 CameraPictureStyle int8u + 201 HighISONoiseReduction int8u + 274 LensType int16uRev + 276 MinFocalLength int16uRev + 278 MaxFocalLength int16uRev + 428 FirmwareVersion no + 491 FileIndex int32u + 503 DirectoryIndex int32u + 807 PictureStyleInfo Canon PSInfo + +=head3 Canon CameraInfo40D Tags + +CameraInfo tags for the EOS 40D. + + Index1 Tag Name Writable + ------ -------- -------- + 3 FNumber int8u + 4 ExposureTime int8u + 6 ISO int8u + 21 FlashMeteringMode int8u + 24 CameraTemperature int8u + 27 MacroMagnification int8u + 29 FocalLength int16uRev + 48 CameraOrientation int8u + 67 FocusDistanceUpper int16uRev + 69 FocusDistanceLower int16uRev + 111 WhiteBalance int16u + 115 ColorTemperature int16u + 214 LensType int16uRev + 216 MinFocalLength int16uRev + 218 MaxFocalLength int16uRev + 255 FirmwareVersion string[6] + 307 FileIndex int32u + 319 DirectoryIndex int32u + 603 PictureStyleInfo Canon PSInfo + 2347 LensModel string[64] + +=head3 Canon CameraInfo50D Tags + +CameraInfo tags for the EOS 50D. Indices shown are for firmware versions +1.0.x, but they may be different for other firmware versions. + + Index1 Tag Name Writable + ------ -------- -------- + 3 FNumber int8u + 4 ExposureTime int8u + 6 ISO int8u + 7 HighlightTonePriority int8u + 21 FlashMeteringMode int8u + 25 CameraTemperature int8u + 30 FocalLength int16uRev + 49 CameraOrientation int8u + 80 FocusDistanceUpper int16uRev + 82 FocusDistanceLower int16uRev + 111 WhiteBalance int16u + 115 ColorTemperature int16u + 167 PictureStyle int8u + 189 HighISONoiseReduction int8u + 191 AutoLightingOptimizer int8u + 234 LensType int16uRev + 236 MinFocalLength int16uRev + 238 MaxFocalLength int16uRev + 350 FirmwareVersion no + 411 FileIndex int32u + 423 DirectoryIndex int32u + 727 PictureStyleInfo Canon PSInfo + +=head3 Canon CameraInfo60D Tags + +CameraInfo tags for the EOS 60D and 1200D. + + Index1 Tag Name Writable + ------ -------- -------- + 3 FNumber int8u + 4 ExposureTime int8u + 6 ISO int8u + 25 CameraTemperature int8u + 30 FocalLength int16uRev + 54 CameraOrientation int8u + 85 FocusDistanceUpper int16uRev + 87 FocusDistanceLower int16uRev + 125 ColorTemperature int16u + 232 LensType int16uRev + 234 MinFocalLength int16uRev + 236 MaxFocalLength int16uRev + 409 FirmwareVersion no + 473 FileIndex int32u + 485 DirectoryIndex int32u + 761 PictureStyleInfo Canon PSInfo2 + 801 PictureStyleInfo Canon PSInfo2 + +=head3 Canon CameraInfo70D Tags + +CameraInfo tags for the EOS 70D. + + Index1 Tag Name Writable + ------ -------- -------- + 3 FNumber int8u + 4 ExposureTime int8u + 6 ISO int8u + 27 CameraTemperature int8u + 35 FocalLength int16uRev + 132 CameraOrientation int8u + 147 FocusDistanceUpper int16uRev + 149 FocusDistanceLower int16uRev + 199 ColorTemperature int16u + 358 LensType int16uRev + 360 MinFocalLength int16uRev + 362 MaxFocalLength int16uRev + 606 FirmwareVersion no + 691 FileIndex int32u + 703 DirectoryIndex int32u + 975 PictureStyleInfo Canon PSInfo2 + +=head3 Canon CameraInfo80D Tags + +CameraInfo tags for the EOS 70D. + + Index1 Tag Name Writable + ------ -------- -------- + 3 FNumber int8u + 4 ExposureTime int8u + 6 ISO int8u + 27 CameraTemperature int8u + 35 FocalLength int16uRev + 150 CameraOrientation int8u + 165 FocusDistanceUpper int16uRev + 167 FocusDistanceLower int16uRev + 314 ColorTemperature int16u + 393 LensType int16uRev + 395 MinFocalLength int16uRev + 397 MaxFocalLength int16uRev + 1114 FirmwareVersion no + 1198 FileIndex int32u + 1210 DirectoryIndex int32u + +=head3 Canon CameraInfo450D Tags + +CameraInfo tags for the EOS 450D. + + Index1 Tag Name Writable + ------ -------- -------- + 3 FNumber int8u + 4 ExposureTime int8u + 6 ISO int8u + 21 FlashMeteringMode int8u + 24 CameraTemperature int8u + 27 MacroMagnification int8u + 29 FocalLength int16uRev + 48 CameraOrientation int8u + 67 FocusDistanceUpper int16uRev + 69 FocusDistanceLower int16uRev + 111 WhiteBalance int16u + 115 ColorTemperature int16u + 222 LensType int16uRev + 263 FirmwareVersion string[6] + 271 OwnerName string[32] + 307 DirectoryIndex int32u + 319 FileIndex int32u + 611 PictureStyleInfo Canon PSInfo + 2355 LensModel string[64] + +=head3 Canon CameraInfo500D Tags + +CameraInfo tags for the EOS 500D. + + Index1 Tag Name Writable + ------ -------- -------- + 3 FNumber int8u + 4 ExposureTime int8u + 6 ISO int8u + 7 HighlightTonePriority int8u + 21 FlashMeteringMode int8u + 25 CameraTemperature int8u + 30 FocalLength int16uRev + 49 CameraOrientation int8u + 80 FocusDistanceUpper int16uRev + 82 FocusDistanceLower int16uRev + 115 WhiteBalance int16u + 119 ColorTemperature int16u + 171 PictureStyle int8u + 188 HighISONoiseReduction int8u + 190 AutoLightingOptimizer int8u + 246 LensType int16uRev + 248 MinFocalLength int16uRev + 250 MaxFocalLength int16uRev + 400 FirmwareVersion no + 467 FileIndex int32u + 479 DirectoryIndex int32u + 779 PictureStyleInfo Canon PSInfo + +=head3 Canon CameraInfo550D Tags + +CameraInfo tags for the EOS 550D. + + Index1 Tag Name Writable + ------ -------- -------- + 3 FNumber int8u + 4 ExposureTime int8u + 6 ISO int8u + 7 HighlightTonePriority int8u + 21 FlashMeteringMode int8u + 25 CameraTemperature int8u + 30 FocalLength int16uRev + 53 CameraOrientation int8u + 84 FocusDistanceUpper int16uRev + 86 FocusDistanceLower int16uRev + 120 WhiteBalance int16u + 124 ColorTemperature int16u + 176 PictureStyle int8u + 255 LensType int16uRev + 257 MinFocalLength int16uRev + 259 MaxFocalLength int16uRev + 420 FirmwareVersion no + 484 FileIndex int32u + 496 DirectoryIndex int32u + 796 PictureStyleInfo Canon PSInfo + +=head3 Canon CameraInfo600D Tags + +CameraInfo tags for the EOS 600D and 1100D. + + Index1 Tag Name Writable + ------ -------- -------- + 3 FNumber int8u + 4 ExposureTime int8u + 6 ISO int8u + 7 HighlightTonePriority int8u + 21 FlashMeteringMode int8u + 25 CameraTemperature int8u + 30 FocalLength int16uRev + 56 CameraOrientation int8u + 87 FocusDistanceUpper int16uRev + 89 FocusDistanceLower int16uRev + 123 WhiteBalance int16u + 127 ColorTemperature int16u + 179 PictureStyle int8u + 234 LensType int16uRev + 236 MinFocalLength int16uRev + 238 MaxFocalLength int16uRev + 411 FirmwareVersion no + 475 FileIndex int32u + 487 DirectoryIndex int32u + 763 PictureStyleInfo Canon PSInfo2 + +=head3 Canon CameraInfo650D Tags + +CameraInfo tags for the EOS 650D and 700D. + + Index1 Tag Name Writable + ------ -------- -------- + 3 FNumber int8u + 4 ExposureTime int8u + 6 ISO int8u + 27 CameraTemperature int8u + 35 FocalLength int16uRev + 125 CameraOrientation int8u + 140 FocusDistanceUpper int16uRev + 142 FocusDistanceLower int16uRev + 188 WhiteBalance int16u + 192 ColorTemperature int16u + 244 PictureStyle int8u + 295 LensType int16uRev + 297 MinFocalLength int16uRev + 299 MaxFocalLength int16uRev + 539 FirmwareVersion no + 544 FirmwareVersion no + 624 FileIndex int32u + 628 FileIndex int32u + 636 DirectoryIndex int32u + 640 DirectoryIndex int32u + 912 PictureStyleInfo Canon PSInfo2 + +=head3 Canon CameraInfo750D Tags + +CameraInfo tags for the EOS 750D and 760D. + + Index1 Tag Name Writable + ------ -------- -------- + 3 FNumber int8u + 4 ExposureTime int8u + 6 ISO int8u + 27 CameraTemperature int8u + 35 FocalLength int16uRev + 165 FocusDistanceUpper int16uRev + 167 FocusDistanceLower int16uRev + 305 WhiteBalance int16u + 309 ColorTemperature int16u + 361 PictureStyle int8u + 388 LensType int16uRev + 390 MinFocalLength int16uRev + 392 MaxFocalLength int16uRev + 1085 FirmwareVersion no + 1097 FirmwareVersion no + +=head3 Canon CameraInfo1000D Tags + +CameraInfo tags for the EOS 1000D. + + Index1 Tag Name Writable + ------ -------- -------- + 3 FNumber int8u + 4 ExposureTime int8u + 6 ISO int8u + 21 FlashMeteringMode int8u + 24 CameraTemperature int8u + 27 MacroMagnification int8u + 29 FocalLength int16uRev + 48 CameraOrientation int8u + 67 FocusDistanceUpper int16uRev + 69 FocusDistanceLower int16uRev + 111 WhiteBalance int16u + 115 ColorTemperature int16u + 226 LensType int16uRev + 228 MinFocalLength int16uRev + 230 MaxFocalLength int16uRev + 267 FirmwareVersion string[6] + 311 DirectoryIndex int32u + 323 FileIndex int32u + 615 PictureStyleInfo Canon PSInfo + 2359 LensModel string[64] + +=head3 Canon CameraInfoPowerShot Tags + +CameraInfo tags for PowerShot models such as the A450, A460, A550, A560, +A570, A630, A640, A650, A710, A720, G7, G9, S5, SD40, SD750, SD800, SD850, +SD870, SD900, SD950, SD1000, SX100 and TX1. + + Index4 Tag Name Writable + ------ -------- -------- + 0 ISO int32s + 5 FNumber int32s + 6 ExposureTime int32s + 23 Rotation int32s + 135 CameraTemperature int32s + 145 CameraTemperature int32s + +=head3 Canon CameraInfoPowerShot2 Tags + +CameraInfo tags for PowerShot models such as the A470, A480, A490, A495, +A580, A590, A1000, A1100, A2000, A2100, A3000, A3100, D10, E1, G10, G11, +S90, S95, SD770, SD780, SD790, SD880, SD890, SD940, SD960, SD970, SD980, +SD990, SD1100, SD1200, SD1300, SD1400, SD3500, SD4000, SD4500, SX1, SX10, +SX20, SX110, SX120, SX130, SX200 and SX210. + + Index4 Tag Name Writable + ------ -------- -------- + 1 ISO int32s + 6 FNumber int32s + 7 ExposureTime int32s + 24 Rotation int32s + 153 CameraTemperature int32s + 159 CameraTemperature int32s + 164 CameraTemperature int32s + 168 CameraTemperature int32s + 261 CameraTemperature int32s + +=head3 Canon CameraInfoUnknown32 Tags + +Unknown CameraInfo tags are divided into 3 tables based on format size. + + Index4 Tag Name Writable + ------ -------- -------- + 71 CameraTemperature int32s + 83 CameraTemperature int32s + 91 CameraTemperature int32s + 92 CameraTemperature int32s + 100 CameraTemperature int32s + -3 CameraTemperature int32s + +=head3 Canon CameraInfoUnknown16 Tags + + Index2 Tag Name Writable + ------ -------- -------- + [no tags known] + +=head3 Canon CameraInfoUnknown Tags + + Index1 Tag Name Writable + ------ -------- -------- + 363 LensSerialNumber undef[5] + +=head3 Canon MovieInfo Tags + +Tags written by some Canon cameras when recording video. + + Index2 Tag Name Writable + ------ -------- -------- + 1 FrameRate int16u + 2 FrameCount int16u + 4 FrameCount int32u + 6 FrameRate rational32u + 106 Duration int32u + 108 AudioBitrate int32u + 110 AudioSampleRate int32u + 112 AudioChannels int32u + 116 VideoCodec undef[4] + +=head3 Canon AFInfo Tags + +Auto-focus information used by many older Canon models. The values in this +record are sequential, and some have variable sizes based on the value of +NumAFPoints (which may be 1,5,7,9,15,45 or 53). The AFArea coordinates are +given in a system where the image has dimensions given by AFImageWidth and +AFImageHeight, and 0,0 is the image center. The direction of the Y axis +depends on the camera model, with positive Y upwards for EOS models, but +apparently downwards for PowerShot models. + + Sequence Tag Name Writable + -------- -------- -------- + 0 NumAFPoints no + 1 ValidAFPoints no + 2 CanonImageWidth no + 3 CanonImageHeight no + 4 AFImageWidth no + 5 AFImageHeight no + 6 AFAreaWidth no + 7 AFAreaHeight no + 8 AFAreaXPositions no + 9 AFAreaYPositions no + 10 AFPointsInFocus no + 11 PrimaryAFPoint no + Canon_AFInfo_0x000b? no + 12 PrimaryAFPoint no + +=head3 Canon MyColors Tags + + Index2 Tag Name Writable + ------ -------- -------- + 2 MyColorMode int16u + +=head3 Canon FaceDetect1 Tags + + Index2 Tag Name Writable + ------ -------- -------- + 2 FacesDetected int16u + 3 FaceDetectFrameSize int16u[2] + 8 Face1Position int16s[2] + 10 Face2Position int16s[2] + 12 Face3Position int16s[2] + 14 Face4Position int16s[2] + 16 Face5Position int16s[2] + 18 Face6Position int16s[2] + 20 Face7Position int16s[2] + 22 Face8Position int16s[2] + 24 Face9Position int16s[2] + +=head3 Canon FaceDetect2 Tags + + Index1 Tag Name Writable + ------ -------- -------- + 1 FaceWidth int8u + 2 FacesDetected int8u + +=head3 Canon AFInfo2 Tags + +Newer version of the AFInfo record containing much of the same information +(and coordinate confusion) as the older version. In this record, NumAFPoints +may be 7, 9, 11, 19, 31, 45 or 61, depending on the camera model. + + Sequence Tag Name Writable + -------- -------- -------- + 0 AFInfoSize? no + 1 AFAreaMode no + 2 NumAFPoints no + 3 ValidAFPoints no + 4 CanonImageWidth no + 5 CanonImageHeight no + 6 AFImageWidth no + 7 AFImageHeight no + 8 AFAreaWidths no + 9 AFAreaHeights no + 10 AFAreaXPositions no + 11 AFAreaYPositions no + 12 AFPointsInFocus no + 13 AFPointsSelected no + Canon_AFInfo2_0x000d? no + 14 PrimaryAFPoint no + +=head3 Canon ContrastInfo Tags + + Index2 Tag Name Writable + ------ -------- -------- + 4 IntelligentContrast int16u + +=head3 Canon FaceDetect3 Tags + + Index2 Tag Name Writable + ------ -------- -------- + 3 FacesDetected int16u + +=head3 Canon TimeInfo Tags + + Index4 Tag Name Writable + ------ -------- -------- + 1 TimeZone int32s + 2 TimeZoneCity int32s + 3 DaylightSavings int32s + +=head3 Canon FileInfo Tags + + Index2 Tag Name Writable + ------ -------- -------- + 1 FileNumber int32u + ShutterCount int32u + 3 BracketMode int16s + 4 BracketValue int16s + 5 BracketShotNumber int16s + 6 RawJpgQuality int16s + 7 RawJpgSize int16s + 8 LongExposureNoiseReduction2 int16s + 9 WBBracketMode int16s + 12 WBBracketValueAB int16s + 13 WBBracketValueGM int16s + 14 FilterEffect int16s + 15 ToningEffect int16s + 16 MacroMagnification int16s + 19 LiveViewShooting int16s + 20 FocusDistanceUpper int16u + 21 FocusDistanceLower int16u + 25 FlashExposureLock int16s + +=head3 Canon SerialInfo Tags + + Index1 Tag Name Writable + ------ -------- -------- + 9 InternalSerialNumber string + +=head3 Canon CropInfo Tags + + Index2 Tag Name Writable + ------ -------- -------- + 0 CropLeftMargin int16u + 1 CropRightMargin int16u + 2 CropTopMargin int16u + 3 CropBottomMargin int16u + +=head3 Canon AspectInfo Tags + + Index4 Tag Name Writable + ------ -------- -------- + 0 AspectRatio int32u + 1 CroppedImageWidth int32u + 2 CroppedImageHeight int32u + 3 CroppedImageLeft int32u + 4 CroppedImageTop int32u + +=head3 Canon Processing Tags + + Index2 Tag Name Writable + ------ -------- -------- + 1 ToneCurve int16s + 2 Sharpness int16s + 3 SharpnessFrequency int16s + 4 SensorRedLevel int16s + 5 SensorBlueLevel int16s + 6 WhiteBalanceRed int16s + 7 WhiteBalanceBlue int16s + 8 WhiteBalance int16s + 9 ColorTemperature int16s + 10 PictureStyle int16s + 11 DigitalGain int16s + 12 WBShiftAB int16s + 13 WBShiftGM int16s + +=head3 Canon ColorBalance Tags + +These tags are used by the 10D and 300D. + + Index2 Tag Name Writable + ------ -------- -------- + 1 WB_RGGBLevelsAuto int16s[4] + 5 WB_RGGBLevelsDaylight int16s[4] + 9 WB_RGGBLevelsShade int16s[4] + 13 WB_RGGBLevelsCloudy int16s[4] + 17 WB_RGGBLevelsTungsten int16s[4] + 21 WB_RGGBLevelsFluorescent int16s[4] + 25 WB_RGGBLevelsFlash int16s[4] + 29 WB_RGGBLevelsCustom int16s[4] + 33 WB_RGGBLevelsKelvin int16s[4] + 37 WB_RGGBBlackLevels int16s[4] + +=head3 Canon MeasuredColor Tags + + Index2 Tag Name Writable + ------ -------- -------- + 1 MeasuredRGGB int16u[4] + +=head3 Canon Flags Tags + + Index2 Tag Name Writable + ------ -------- -------- + 1 ModifiedParamFlag int16s + +=head3 Canon ModifiedInfo Tags + + Index2 Tag Name Writable + ------ -------- -------- + 1 ModifiedToneCurve int16s + 2 ModifiedSharpness int16s + 3 ModifiedSharpnessFreq int16s + 4 ModifiedSensorRedLevel int16s + 5 ModifiedSensorBlueLevel int16s + 6 ModifiedWhiteBalanceRed int16s + 7 ModifiedWhiteBalanceBlue int16s + 8 ModifiedWhiteBalance int16s + 9 ModifiedColorTemp int16s + 10 ModifiedPictureStyle int16s + 11 ModifiedDigitalGain int16s + +=head3 Canon PreviewImageInfo Tags + + Index4 Tag Name Writable + ------ -------- -------- + 1 PreviewQuality int32u + 2 PreviewImageLength int32u* + 3 PreviewImageWidth int32u + 4 PreviewImageHeight int32u + 5 PreviewImageStart int32u* + +=head3 Canon SensorInfo Tags + + Index2 Tag Name Writable + ------ -------- -------- + 1 SensorWidth no + 2 SensorHeight no + 5 SensorLeftBorder no + 6 SensorTopBorder no + 7 SensorRightBorder no + 8 SensorBottomBorder no + 9 BlackMaskLeftBorder no + 10 BlackMaskTopBorder no + 11 BlackMaskRightBorder no + 12 BlackMaskBottomBorder no + +=head3 Canon ColorData1 Tags + +These tags are used by the 20D and 350D. + + Index2 Tag Name Writable + ------ -------- -------- + 25 WB_RGGBLevelsAsShot int16s[4] + 29 ColorTempAsShot int16s + 30 WB_RGGBLevelsAuto int16s[4] + 34 ColorTempAuto int16s + 35 WB_RGGBLevelsDaylight int16s[4] + 39 ColorTempDaylight int16s + 40 WB_RGGBLevelsShade int16s[4] + 44 ColorTempShade int16s + 45 WB_RGGBLevelsCloudy int16s[4] + 49 ColorTempCloudy int16s + 50 WB_RGGBLevelsTungsten int16s[4] + 54 ColorTempTungsten int16s + 55 WB_RGGBLevelsFluorescent int16s[4] + 59 ColorTempFluorescent int16s + 60 WB_RGGBLevelsFlash int16s[4] + 64 ColorTempFlash int16s + 65 WB_RGGBLevelsCustom1 int16s[4] + 69 ColorTempCustom1 int16s + 70 WB_RGGBLevelsCustom2 int16s[4] + 74 ColorTempCustom2 int16s + 75 ColorCalib? Canon ColorCalib + +=head3 Canon ColorCalib Tags + +Camera color calibration data. For the 20D, 350D, 1DmkII and 1DSmkII the +order of the coefficients is A, B, C, Temperature, but for newer models it +is B, C, A, Temperature. These tags are extracted only when the Unknown +option is used. + + Index2 Tag Name Writable + ------ -------- -------- + 0 CameraColorCalibration01? int16s[4] + 4 CameraColorCalibration02? int16s[4] + 8 CameraColorCalibration03? int16s[4] + 12 CameraColorCalibration04? int16s[4] + 16 CameraColorCalibration05? int16s[4] + 20 CameraColorCalibration06? int16s[4] + 24 CameraColorCalibration07? int16s[4] + 28 CameraColorCalibration08? int16s[4] + 32 CameraColorCalibration09? int16s[4] + 36 CameraColorCalibration10? int16s[4] + 40 CameraColorCalibration11? int16s[4] + 44 CameraColorCalibration12? int16s[4] + 48 CameraColorCalibration13? int16s[4] + 52 CameraColorCalibration14? int16s[4] + 56 CameraColorCalibration15? int16s[4] + +=head3 Canon ColorData2 Tags + +These tags are used by the 1DmkII and 1DSmkII. + + Index2 Tag Name Writable + ------ -------- -------- + 24 WB_RGGBLevelsAuto int16s[4] + 28 ColorTempAuto int16s + 29 WB_RGGBLevelsUnknown? int16s[4] + 33 ColorTempUnknown? int16s + 34 WB_RGGBLevelsAsShot int16s[4] + 38 ColorTempAsShot int16s + 39 WB_RGGBLevelsDaylight int16s[4] + 43 ColorTempDaylight int16s + 44 WB_RGGBLevelsShade int16s[4] + 48 ColorTempShade int16s + 49 WB_RGGBLevelsCloudy int16s[4] + 53 ColorTempCloudy int16s + 54 WB_RGGBLevelsTungsten int16s[4] + 58 ColorTempTungsten int16s + 59 WB_RGGBLevelsFluorescent int16s[4] + 63 ColorTempFluorescent int16s + 64 WB_RGGBLevelsKelvin int16s[4] + 68 ColorTempKelvin int16s + 69 WB_RGGBLevelsFlash int16s[4] + 73 ColorTempFlash int16s + 74 WB_RGGBLevelsUnknown2? int16s[4] + 78 ColorTempUnknown2? int16s + 79 WB_RGGBLevelsUnknown3? int16s[4] + 83 ColorTempUnknown3? int16s + 84 WB_RGGBLevelsUnknown4? int16s[4] + 88 ColorTempUnknown4? int16s + 89 WB_RGGBLevelsUnknown5? int16s[4] + 93 ColorTempUnknown5? int16s + 94 WB_RGGBLevelsUnknown6? int16s[4] + 98 ColorTempUnknown6? int16s + 99 WB_RGGBLevelsUnknown7? int16s[4] + 103 ColorTempUnknown7? int16s + 104 WB_RGGBLevelsUnknown8? int16s[4] + 108 ColorTempUnknown8? int16s + 109 WB_RGGBLevelsUnknown9? int16s[4] + 113 ColorTempUnknown9? int16s + 114 WB_RGGBLevelsUnknown10? int16s[4] + 118 ColorTempUnknown10? int16s + 119 WB_RGGBLevelsUnknown11? int16s[4] + 123 ColorTempUnknown11? int16s + 124 WB_RGGBLevelsUnknown12? int16s[4] + 128 ColorTempUnknown12? int16s + 129 WB_RGGBLevelsUnknown13? int16s[4] + 133 ColorTempUnknown13? int16s + 134 WB_RGGBLevelsUnknown14? int16s[4] + 138 ColorTempUnknown14? int16s + 139 WB_RGGBLevelsUnknown15? int16s[4] + 143 ColorTempUnknown15? int16s + 144 WB_RGGBLevelsPC1 int16s[4] + 148 ColorTempPC1 int16s + 149 WB_RGGBLevelsPC2 int16s[4] + 153 ColorTempPC2 int16s + 154 WB_RGGBLevelsPC3 int16s[4] + 158 ColorTempPC3 int16s + 159 WB_RGGBLevelsUnknown16? int16s[4] + 163 ColorTempUnknown16? int16s + 164 ColorCalib? Canon ColorCalib + 618 RawMeasuredRGGB int32u[4] + +=head3 Canon ColorData3 Tags + +These tags are used by the 1DmkIIN, 5D, 30D and 400D. + + Index2 Tag Name Writable + ------ -------- -------- + 0 ColorDataVersion int16s + 63 WB_RGGBLevelsAsShot int16s[4] + 67 ColorTempAsShot int16s + 68 WB_RGGBLevelsAuto int16s[4] + 72 ColorTempAuto int16s + 73 WB_RGGBLevelsMeasured int16s[4] + 77 ColorTempMeasured int16s + 78 WB_RGGBLevelsDaylight int16s[4] + 82 ColorTempDaylight int16s + 83 WB_RGGBLevelsShade int16s[4] + 87 ColorTempShade int16s + 88 WB_RGGBLevelsCloudy int16s[4] + 92 ColorTempCloudy int16s + 93 WB_RGGBLevelsTungsten int16s[4] + 97 ColorTempTungsten int16s + 98 WB_RGGBLevelsFluorescent int16s[4] + 102 ColorTempFluorescent int16s + 103 WB_RGGBLevelsKelvin int16s[4] + 107 ColorTempKelvin int16s + 108 WB_RGGBLevelsFlash int16s[4] + 112 ColorTempFlash int16s + 113 WB_RGGBLevelsPC1 int16s[4] + 117 ColorTempPC1 int16s + 118 WB_RGGBLevelsPC2 int16s[4] + 122 ColorTempPC2 int16s + 123 WB_RGGBLevelsPC3 int16s[4] + 127 ColorTempPC3 int16s + 128 WB_RGGBLevelsCustom int16s[4] + 132 ColorTempCustom int16s + 133 ColorCalib? Canon ColorCalib + 196 PerChannelBlackLevel int16u[4] + 584 FlashOutput int16s + 585 FlashBatteryLevel int16s + 586 ColorTempFlashData int16s + 647 MeasuredRGGBData int32u[4] + +=head3 Canon ColorData4 Tags + +These tags are used by the 1DmkIII, 1DSmkIII, 1DmkIV, 5DmkII, 7D, 40D, 50D, +60D, 450D, 500D, 550D, 1000D and 1100D. + + Index2 Tag Name Writable + ------ -------- -------- + 0 ColorDataVersion int16s + 63 ColorCoefs Canon ColorCoefs + 168 ColorCalib? Canon ColorCalib + 231 AverageBlackLevel int16u[4] + 640 RawMeasuredRGGB int32u[4] + 692 PerChannelBlackLevel int16u[4] + 696 NormalWhiteLevel int16u + 697 SpecularWhiteLevel int16u + 698 LinearityUpperMargin int16u + 715 PerChannelBlackLevel int16u[4] + 719 NormalWhiteLevel int16u + PerChannelBlackLevel int16u[4] + 720 SpecularWhiteLevel int16u + 721 LinearityUpperMargin int16u + 723 NormalWhiteLevel int16u + 724 SpecularWhiteLevel int16u + 725 LinearityUpperMargin int16u + +=head3 Canon ColorCoefs Tags + + Index2 Tag Name Writable + ------ -------- -------- + 0 WB_RGGBLevelsAsShot int16s[4] + 4 ColorTempAsShot int16s + 5 WB_RGGBLevelsAuto int16s[4] + 9 ColorTempAuto int16s + 10 WB_RGGBLevelsMeasured int16s[4] + 14 ColorTempMeasured int16s + 15 WB_RGGBLevelsUnknown? int16s[4] + 19 ColorTempUnknown? int16s + 20 WB_RGGBLevelsDaylight int16s[4] + 24 ColorTempDaylight int16s + 25 WB_RGGBLevelsShade int16s[4] + 29 ColorTempShade int16s + 30 WB_RGGBLevelsCloudy int16s[4] + 34 ColorTempCloudy int16s + 35 WB_RGGBLevelsTungsten int16s[4] + 39 ColorTempTungsten int16s + 40 WB_RGGBLevelsFluorescent int16s[4] + 44 ColorTempFluorescent int16s + 45 WB_RGGBLevelsKelvin int16s[4] + 49 ColorTempKelvin int16s + 50 WB_RGGBLevelsFlash int16s[4] + 54 ColorTempFlash int16s + 55 WB_RGGBLevelsUnknown2? int16s[4] + 59 ColorTempUnknown2? int16s + 60 WB_RGGBLevelsUnknown3? int16s[4] + 64 ColorTempUnknown3? int16s + 65 WB_RGGBLevelsUnknown4? int16s[4] + 69 ColorTempUnknown4? int16s + 70 WB_RGGBLevelsUnknown5? int16s[4] + 74 ColorTempUnknown5? int16s + 75 WB_RGGBLevelsUnknown6? int16s[4] + 79 ColorTempUnknown6? int16s + 80 WB_RGGBLevelsUnknown7? int16s[4] + 84 ColorTempUnknown7? int16s + 85 WB_RGGBLevelsUnknown8? int16s[4] + 89 ColorTempUnknown8? int16s + 90 WB_RGGBLevelsUnknown9? int16s[4] + 94 ColorTempUnknown9? int16s + 95 WB_RGGBLevelsUnknown10? int16s[4] + 99 ColorTempUnknown10? int16s + 100 WB_RGGBLevelsUnknown11? int16s[4] + 104 ColorTempUnknown11? int16s + 105 WB_RGGBLevelsUnknown12? int16s[4] + 109 ColorTempUnknown12? int16s + 110 WB_RGGBLevelsUnknown13? int16s[4] + 114 ColorTempUnknown13? int16s + +=head3 Canon ColorData5 Tags + +These tags are used by many EOS M and PowerShot models. + + Index2 Tag Name Writable + ------ -------- -------- + 0 ColorDataVersion int16s + 71 ColorCoefs Canon ColorCoefs + ColorCoefs2 Canon ColorCoefs2 + 186 ColorCalib2? Canon ColorCalib2 + 255 ColorCalib2? Canon ColorCalib2 + 264 PerChannelBlackLevel int16s[4] + 333 PerChannelBlackLevel int16s[4] + +=head3 Canon ColorCoefs2 Tags + + Index2 Tag Name Writable + ------ -------- -------- + 0 WB_RGGBLevelsAsShot int16s[4] + 7 ColorTempAsShot int16s + 8 WB_RGGBLevelsAuto int16s[4] + 15 ColorTempAuto int16s + 16 WB_RGGBLevelsMeasured int16s[4] + 23 ColorTempMeasured int16s + 24 WB_RGGBLevelsUnknown? int16s[4] + 31 ColorTempUnknown? int16s + 32 WB_RGGBLevelsDaylight int16s[4] + 39 ColorTempDaylight int16s + 40 WB_RGGBLevelsShade int16s[4] + 47 ColorTempShade int16s + 48 WB_RGGBLevelsCloudy int16s[4] + 55 ColorTempCloudy int16s + 56 WB_RGGBLevelsTungsten int16s[4] + 63 ColorTempTungsten int16s + 64 WB_RGGBLevelsFluorescent int16s[4] + 71 ColorTempFluorescent int16s + 72 WB_RGGBLevelsKelvin int16s[4] + 79 ColorTempKelvin int16s + 80 WB_RGGBLevelsFlash int16s[4] + 87 ColorTempFlash int16s + 88 WB_RGGBLevelsUnknown2? int16s[4] + 95 ColorTempUnknown2? int16s + 96 WB_RGGBLevelsUnknown3? int16s[4] + 103 ColorTempUnknown3? int16s + 104 WB_RGGBLevelsUnknown4? int16s[4] + 111 ColorTempUnknown4? int16s + 112 WB_RGGBLevelsUnknown5? int16s[4] + 119 ColorTempUnknown5? int16s + 120 WB_RGGBLevelsUnknown6? int16s[4] + 127 ColorTempUnknown6? int16s + 128 WB_RGGBLevelsUnknown7? int16s[4] + 135 ColorTempUnknown7? int16s + 136 WB_RGGBLevelsUnknown8? int16s[4] + 143 ColorTempUnknown8? int16s + 144 WB_RGGBLevelsUnknown9? int16s[4] + 151 ColorTempUnknown9? int16s + 152 WB_RGGBLevelsUnknown10? int16s[4] + 159 ColorTempUnknown10? int16s + 160 WB_RGGBLevelsUnknown11? int16s[4] + 167 ColorTempUnknown11? int16s + 168 WB_RGGBLevelsUnknown12? int16s[4] + 175 ColorTempUnknown12? int16s + 176 WB_RGGBLevelsUnknown13? int16s[4] + 183 ColorTempUnknown13? int16s + +=head3 Canon ColorCalib2 Tags + +B, C, A, D, Temperature. + + Index2 Tag Name Writable + ------ -------- -------- + 0 CameraColorCalibration01? int16s[5] + 5 CameraColorCalibration02? int16s[5] + 10 CameraColorCalibration03? int16s[5] + 15 CameraColorCalibration04? int16s[5] + 20 CameraColorCalibration05? int16s[5] + 25 CameraColorCalibration06? int16s[5] + 30 CameraColorCalibration07? int16s[5] + 35 CameraColorCalibration08? int16s[5] + 40 CameraColorCalibration09? int16s[5] + 45 CameraColorCalibration10? int16s[5] + 50 CameraColorCalibration11? int16s[5] + 55 CameraColorCalibration12? int16s[5] + 60 CameraColorCalibration13? int16s[5] + 65 CameraColorCalibration14? int16s[5] + 70 CameraColorCalibration15? int16s[5] + +=head3 Canon ColorData6 Tags + +These tags are used by the EOS 600D and 1200D. + + Index2 Tag Name Writable + ------ -------- -------- + 0 ColorDataVersion int16s + 63 WB_RGGBLevelsAsShot int16s[4] + 67 ColorTempAsShot int16s + 68 WB_RGGBLevelsAuto int16s[4] + 72 ColorTempAuto int16s + 73 WB_RGGBLevelsMeasured int16s[4] + 77 ColorTempMeasured int16s + 78 WB_RGGBLevelsUnknown? int16s[4] + 82 ColorTempUnknown? int16s + 83 WB_RGGBLevelsUnknown2? int16s[4] + 87 ColorTempUnknown2? int16s + 88 WB_RGGBLevelsUnknown3? int16s[4] + 92 ColorTempUnknown3? int16s + 93 WB_RGGBLevelsUnknown4? int16s[4] + 97 ColorTempUnknown4? int16s + 98 WB_RGGBLevelsUnknown5? int16s[4] + 102 ColorTempUnknown5? int16s + 103 WB_RGGBLevelsDaylight int16s[4] + 107 ColorTempDaylight int16s + 108 WB_RGGBLevelsShade int16s[4] + 112 ColorTempShade int16s + 113 WB_RGGBLevelsCloudy int16s[4] + 117 ColorTempCloudy int16s + 118 WB_RGGBLevelsTungsten int16s[4] + 122 ColorTempTungsten int16s + 123 WB_RGGBLevelsFluorescent int16s[4] + 127 ColorTempFluorescent int16s + 128 WB_RGGBLevelsKelvin int16s[4] + 132 ColorTempKelvin int16s + 133 WB_RGGBLevelsFlash int16s[4] + 137 ColorTempFlash int16s + 138 WB_RGGBLevelsUnknown6? int16s[4] + 142 ColorTempUnknown6? int16s + 143 WB_RGGBLevelsUnknown7? int16s[4] + 147 ColorTempUnknown7? int16s + 148 WB_RGGBLevelsUnknown8? int16s[4] + 152 ColorTempUnknown8? int16s + 153 WB_RGGBLevelsUnknown9? int16s[4] + 157 ColorTempUnknown9? int16s + 158 WB_RGGBLevelsUnknown10? int16s[4] + 162 ColorTempUnknown10? int16s + 163 WB_RGGBLevelsUnknown11? int16s[4] + 167 ColorTempUnknown11? int16s + 168 WB_RGGBLevelsUnknown12? int16s[4] + 172 ColorTempUnknown12? int16s + 173 WB_RGGBLevelsUnknown13? int16s[4] + 177 ColorTempUnknown13? int16s + 178 WB_RGGBLevelsUnknown14? int16s[4] + 182 ColorTempUnknown14? int16s + 183 WB_RGGBLevelsUnknown15? int16s[4] + 187 ColorTempUnknown15? int16s + 188 ColorCalib? Canon ColorCalib + 251 AverageBlackLevel int16u[4] + 404 RawMeasuredRGGB int32u[4] + 479 PerChannelBlackLevel int16u[4] + 483 NormalWhiteLevel int16u + 484 SpecularWhiteLevel int16u + 485 LinearityUpperMargin int16u + +=head3 Canon ColorData7 Tags + +These tags are used by the EOS 1DX, 5DmkIII, 6D, 100D, 650D, 700D, M and 7DmkII. + + Index2 Tag Name Writable + ------ -------- -------- + 0 ColorDataVersion int16s + 63 WB_RGGBLevelsAsShot int16s[4] + 67 ColorTempAsShot int16s + 68 WB_RGGBLevelsAuto int16s[4] + 72 ColorTempAuto int16s + 73 WB_RGGBLevelsMeasured int16s[4] + 77 ColorTempMeasured int16s + 78 WB_RGGBLevelsUnknown? int16s[4] + 82 ColorTempUnknown? int16s + 83 WB_RGGBLevelsUnknown2? int16s[4] + 87 ColorTempUnknown2? int16s + 88 WB_RGGBLevelsUnknown3? int16s[4] + 92 ColorTempUnknown3? int16s + 93 WB_RGGBLevelsUnknown4? int16s[4] + 97 ColorTempUnknown4? int16s + 98 WB_RGGBLevelsUnknown5? int16s[4] + 102 ColorTempUnknown5? int16s + 103 WB_RGGBLevelsUnknown6? int16s[4] + 107 ColorTempUnknown6? int16s + 108 WB_RGGBLevelsUnknown7? int16s[4] + 112 ColorTempUnknown7? int16s + 113 WB_RGGBLevelsUnknown8? int16s[4] + 117 ColorTempUnknown8? int16s + 118 WB_RGGBLevelsUnknown9? int16s[4] + 122 ColorTempUnknown9? int16s + 123 WB_RGGBLevelsUnknown10? int16s[4] + 127 ColorTempUnknown10? int16s + 128 WB_RGGBLevelsDaylight int16s[4] + 132 ColorTempDaylight int16s + 133 WB_RGGBLevelsShade int16s[4] + 137 ColorTempShade int16s + 138 WB_RGGBLevelsCloudy int16s[4] + 142 ColorTempCloudy int16s + 143 WB_RGGBLevelsTungsten int16s[4] + 147 ColorTempTungsten int16s + 148 WB_RGGBLevelsFluorescent int16s[4] + 152 ColorTempFluorescent int16s + 153 WB_RGGBLevelsKelvin int16s[4] + 157 ColorTempKelvin int16s + 158 WB_RGGBLevelsFlash int16s[4] + 162 ColorTempFlash int16s + 163 WB_RGGBLevelsUnknown11? int16s[4] + 167 ColorTempUnknown11? int16s + 168 WB_RGGBLevelsUnknown12? int16s[4] + 172 ColorTempUnknown12? int16s + 173 WB_RGGBLevelsUnknown13? int16s[4] + 177 ColorTempUnknown13? int16s + 178 WB_RGGBLevelsUnknown14? int16s[4] + 182 ColorTempUnknown14? int16s + 183 WB_RGGBLevelsUnknown15? int16s[4] + 187 ColorTempUnknown15? int16s + 188 WB_RGGBLevelsUnknown16? int16s[4] + 192 ColorTempUnknown16? int16s + 193 WB_RGGBLevelsUnknown17? int16s[4] + 197 ColorTempUnknown17? int16s + 198 WB_RGGBLevelsUnknown18? int16s[4] + 202 ColorTempUnknown18? int16s + 203 WB_RGGBLevelsUnknown19? int16s[4] + 207 ColorTempUnknown19? int16s + 208 WB_RGGBLevelsUnknown20? int16s[4] + 212 ColorTempUnknown20? int16s + 213 ColorCalib? Canon ColorCalib + 276 AverageBlackLevel int16u[4] + 429 RawMeasuredRGGB int32u[4] + 504 PerChannelBlackLevel int16u[4] + 508 NormalWhiteLevel int16u + 509 SpecularWhiteLevel int16u + 510 LinearityUpperMargin int16u + 619 RawMeasuredRGGB int32u[4] + 728 PerChannelBlackLevel int16u[4] + 732 NormalWhiteLevel int16u + 733 SpecularWhiteLevel int16u + 734 LinearityUpperMargin int16u + +=head3 Canon ColorData8 Tags + + Index2 Tag Name Writable + ------ -------- -------- + 0 ColorDataVersion int16s + 63 WB_RGGBLevelsAsShot int16s[4] + 67 ColorTempAsShot int16s + 68 WB_RGGBLevelsAuto int16s[4] + 72 ColorTempAuto int16s + 73 WB_RGGBLevelsMeasured int16s[4] + 77 ColorTempMeasured int16s + 78 WB_RGGBLevelsUnknown? int16s[4] + 82 ColorTempUnknown? int16s + 83 WB_RGGBLevelsUnknown2? int16s[4] + 87 ColorTempUnknown2? int16s + 88 WB_RGGBLevelsUnknown3? int16s[4] + 92 ColorTempUnknown3? int16s + 93 WB_RGGBLevelsUnknown4? int16s[4] + 97 ColorTempUnknown4? int16s + 98 WB_RGGBLevelsUnknown5? int16s[4] + 102 ColorTempUnknown5? int16s + 103 WB_RGGBLevelsUnknown6? int16s[4] + 107 ColorTempUnknown6? int16s + 108 WB_RGGBLevelsUnknown7? int16s[4] + 112 ColorTempUnknown7? int16s + 113 WB_RGGBLevelsUnknown8? int16s[4] + 117 ColorTempUnknown8? int16s + 118 WB_RGGBLevelsUnknown9? int16s[4] + 122 ColorTempUnknown9? int16s + 123 WB_RGGBLevelsUnknown10? int16s[4] + 127 ColorTempUnknown10? int16s + 128 WB_RGGBLevelsUnknown11? int16s[4] + 132 ColorTempUnknown11? int16s + 133 WB_RGGBLevelsDaylight int16s[4] + 137 ColorTempDaylight int16s + 138 WB_RGGBLevelsShade int16s[4] + 142 ColorTempShade int16s + 143 WB_RGGBLevelsCloudy int16s[4] + 147 ColorTempCloudy int16s + 148 WB_RGGBLevelsTungsten int16s[4] + 152 ColorTempTungsten int16s + 153 WB_RGGBLevelsFluorescent int16s[4] + 157 ColorTempFluorescent int16s + 158 WB_RGGBLevelsKelvin int16s[4] + 162 ColorTempKelvin int16s + 163 WB_RGGBLevelsFlash int16s[4] + 167 ColorTempFlash int16s + 168 WB_RGGBLevelsUnknown12? int16s[4] + 172 ColorTempUnknown12? int16s + 173 WB_RGGBLevelsUnknown13? int16s[4] + 177 ColorTempUnknown13? int16s + 178 WB_RGGBLevelsUnknown14? int16s[4] + 182 ColorTempUnknown14? int16s + 183 WB_RGGBLevelsUnknown15? int16s[4] + 187 ColorTempUnknown15? int16s + 188 WB_RGGBLevelsUnknown16? int16s[4] + 192 ColorTempUnknown16? int16s + 193 WB_RGGBLevelsUnknown17? int16s[4] + 197 ColorTempUnknown17? int16s + 198 WB_RGGBLevelsUnknown18? int16s[4] + 202 ColorTempUnknown18? int16s + 203 WB_RGGBLevelsUnknown19? int16s[4] + 207 ColorTempUnknown19? int16s + 208 WB_RGGBLevelsUnknown20? int16s[4] + 212 ColorTempUnknown20? int16s + 213 WB_RGGBLevelsUnknown21? int16s[4] + 217 ColorTempUnknown21? int16s + 218 WB_RGGBLevelsUnknown22? int16s[4] + 222 ColorTempUnknown22? int16s + 223 WB_RGGBLevelsUnknown23? int16s[4] + 227 ColorTempUnknown23? int16s + 228 WB_RGGBLevelsUnknown24? int16s[4] + 232 ColorTempUnknown24? int16s + 233 WB_RGGBLevelsUnknown25? int16s[4] + 237 ColorTempUnknown25? int16s + 238 WB_RGGBLevelsUnknown26? int16s[4] + 242 ColorTempUnknown26? int16s + 243 WB_RGGBLevelsUnknown27? int16s[4] + 247 ColorTempUnknown27? int16s + 248 WB_RGGBLevelsUnknown28? int16s[4] + 252 ColorTempUnknown28? int16s + 253 WB_RGGBLevelsUnknown29? int16s[4] + 257 ColorTempUnknown29? int16s + 258 WB_RGGBLevelsUnknown30? int16s[4] + 262 ColorTempUnknown30? int16s + 263 ColorCalib? Canon ColorCalib + 326 AverageBlackLevel int16u[4] + 556 PerChannelBlackLevel int16u[4] + 560 NormalWhiteLevel int16u + 561 SpecularWhiteLevel int16u + 562 LinearityUpperMargin int16u + 778 PerChannelBlackLevel int16u[4] + 782 NormalWhiteLevel int16u + 783 SpecularWhiteLevel int16u + 784 LinearityUpperMargin int16u + +=head3 Canon ColorData9 Tags + + Index2 Tag Name Writable + ------ -------- -------- + 0 ColorDataVersion int16s + 71 WB_RGGBLevelsAsShot int16s[4] + 75 ColorTempAsShot int16s + 76 WB_RGGBLevelsAuto int16s[4] + 80 ColorTempAuto int16s + 81 WB_RGGBLevelsMeasured int16s[4] + 85 ColorTempMeasured int16s + 86 WB_RGGBLevelsUnknown? int16s[4] + 90 ColorTempUnknown? int16s + 91 WB_RGGBLevelsUnknown2? int16s[4] + 95 ColorTempUnknown2? int16s + 96 WB_RGGBLevelsUnknown3? int16s[4] + 100 ColorTempUnknown3? int16s + 101 WB_RGGBLevelsUnknown4? int16s[4] + 105 ColorTempUnknown4? int16s + 106 WB_RGGBLevelsUnknown5? int16s[4] + 110 ColorTempUnknown5? int16s + 111 WB_RGGBLevelsUnknown6? int16s[4] + 115 ColorTempUnknown6? int16s + 116 WB_RGGBLevelsUnknown7? int16s[4] + 120 ColorTempUnknown7? int16s + 121 WB_RGGBLevelsUnknown8? int16s[4] + 125 ColorTempUnknown8? int16s + 126 WB_RGGBLevelsUnknown9? int16s[4] + 130 ColorTempUnknown9? int16s + 131 WB_RGGBLevelsUnknown10? int16s[4] + 135 ColorTempUnknown10? int16s + 136 WB_RGGBLevelsDaylight int16s[4] + 140 ColorTempDaylight int16s + 141 WB_RGGBLevelsShade int16s[4] + 145 ColorTempShade int16s + 146 WB_RGGBLevelsCloudy int16s[4] + 150 ColorTempCloudy int16s + 151 WB_RGGBLevelsTungsten int16s[4] + 155 ColorTempTungsten int16s + 156 WB_RGGBLevelsFluorescent int16s[4] + 160 ColorTempFluorescent int16s + 161 WB_RGGBLevelsKelvin int16s[4] + 165 ColorTempKelvin int16s + 166 WB_RGGBLevelsFlash int16s[4] + 170 ColorTempFlash int16s + 171 WB_RGGBLevelsUnknown11? int16s[4] + 175 ColorTempUnknown11? int16s + 176 WB_RGGBLevelsUnknown12? int16s[4] + 180 ColorTempUnknown12? int16s + 181 WB_RGGBLevelsUnknown13? int16s[4] + 185 ColorTempUnknown13? int16s + 186 WB_RGGBLevelsUnknown14? int16s[4] + 190 ColorTempUnknown14? int16s + 191 WB_RGGBLevelsUnknown15? int16s[4] + 195 ColorTempUnknown15? int16s + 196 WB_RGGBLevelsUnknown16? int16s[4] + 200 ColorTempUnknown16? int16s + 201 WB_RGGBLevelsUnknown17? int16s[4] + 205 ColorTempUnknown17? int16s + 206 WB_RGGBLevelsUnknown18? int16s[4] + 210 ColorTempUnknown18? int16s + 211 WB_RGGBLevelsUnknown19? int16s[4] + 215 ColorTempUnknown19? int16s + 216 WB_RGGBLevelsUnknown20? int16s[4] + 220 ColorTempUnknown20? int16s + 221 WB_RGGBLevelsUnknown21? int16s[4] + 225 ColorTempUnknown21? int16s + 226 WB_RGGBLevelsUnknown22? int16s[4] + 230 ColorTempUnknown22? int16s + 231 WB_RGGBLevelsUnknown23? int16s[4] + 235 ColorTempUnknown23? int16s + 236 WB_RGGBLevelsUnknown24? int16s[4] + 240 ColorTempUnknown24? int16s + 241 WB_RGGBLevelsUnknown25? int16s[4] + 245 ColorTempUnknown25? int16s + 246 WB_RGGBLevelsUnknown26? int16s[4] + 250 ColorTempUnknown26? int16s + 251 WB_RGGBLevelsUnknown27? int16s[4] + 255 ColorTempUnknown27? int16s + 256 WB_RGGBLevelsUnknown28? int16s[4] + 260 ColorTempUnknown28? int16s + 261 WB_RGGBLevelsUnknown29? int16s[4] + 265 ColorTempUnknown29? int16s + 266 ColorCalib? Canon ColorCalib + 329 PerChannelBlackLevel int16u[4] + 796 NormalWhiteLevel int16u + 797 SpecularWhiteLevel int16u + 798 LinearityUpperMargin int16u + +=head3 Canon ColorDataUnknown Tags + + Index2 Tag Name Writable + ------ -------- -------- + 0 ColorDataVersion no + +=head3 Canon ColorInfo Tags + + Index2 Tag Name Writable + ------ -------- -------- + 1 Saturation int16s + 2 ColorTone int16s + 3 ColorSpace int16s + +=head3 Canon AFMicroAdj Tags + + Index4 Tag Name Writable + ------ -------- -------- + 1 AFMicroAdjMode int32s + 2 AFMicroAdjValue rational64s + +=head3 Canon VignettingCorr Tags + +This information is found in images from newer EOS models. + + Index2 Tag Name Writable + ------ -------- -------- + 0 VignettingCorrVersion no + 2 PeripheralLighting int16s + 4 ChromaticAberrationCorr int16s + 5 ChromaticAberrationCorr int16s + 6 PeripheralLightingValue int16s + 11 OriginalImageWidth int16s + 12 OriginalImageHeight int16s + +=head3 Canon VignettingCorrUnknown Tags + +Vignetting correction from PowerShot models. + + Index2 Tag Name Writable + ------ -------- -------- + 0 VignettingCorrVersion no + +=head3 Canon VignettingCorr2 Tags + + Index4 Tag Name Writable + ------ -------- -------- + 5 PeripheralLightingSetting int32s + 6 ChromaticAberrationSetting int32s + +=head3 Canon LightingOpt Tags + +This information is new in images from the EOS 7D. + + Index4 Tag Name Writable + ------ -------- -------- + 1 PeripheralIlluminationCorr int32s + 2 AutoLightingOptimizer int32s + 3 HighlightTonePriority int32s + 4 LongExposureNoiseReduction int32s + 5 HighISONoiseReduction int32s + +=head3 Canon LensInfo Tags + + Index1 Tag Name Writable + ------ -------- -------- + 0 LensSerialNumber undef[5] + +=head3 Canon Ambience Tags + + Index4 Tag Name Writable + ------ -------- -------- + 1 AmbienceSelection int32s + +=head3 Canon MultiExp Tags + + Index4 Tag Name Writable + ------ -------- -------- + 1 MultiExposure int32s + 2 MultiExposureControl int32s + 3 MultiExposureShots int32s + +=head3 Canon FilterInfo Tags + +Information about creative filter settings. + + Tag ID Tag Name Writable + ------ -------- -------- + 0x0101 GrainyBWFilter no + 0x0201 SoftFocusFilter no + 0x0301 ToyCameraFilter no + 0x0401 MiniatureFilter no + 0x0402 MiniatureFilterOrientation no + 0x0403 MiniatureFilterPosition no + 0x0404 MiniatureFilterParameter no + 0x0501 FisheyeFilter no + 0x0601 PaintingFilter no + 0x0701 WatercolorFilter no + +=head3 Canon HDRInfo Tags + + Index4 Tag Name Writable + ------ -------- -------- + 1 HDR int32s + 2 HDREffect int32s + +=head3 Canon AFConfig Tags + + Index4 Tag Name Writable + ------ -------- -------- + 1 AFConfigTool int32s + 2 AFTrackingSensitivity int32s + 3 AFAccelDecelTracking int32s + 4 AFPointSwitching int32s + 5 AIServoFirstImage int32s + 6 AIServoSecondImage int32s + 7 USMLensElectronicMF int32s + 8 AFAssistBeam int32s + 9 OneShotAFRelease int32s + 10 AutoAFPointSelEOSiTRAF int32s + 11 LensDriveWhenAFImpossible int32s + 12 SelectAFAreaSelectionMode int32s + 13 AFAreaSelectionMethod int32s + 14 OrientationLinkedAF int32s + 15 ManualAFPointSelPattern int32s + 16 AFPointDisplayDuringFocus int32s + 17 VFDisplayIllumination int32s + 18 AFStatusViewfinder int32s + 19 InitialAFPointInServo int32s + +=head3 Canon CDI1 Tags + + Tag ID Tag Name Writable + ------ -------- -------- + [no tags known] + +=head3 Canon CNOP Tags + + Tag ID Tag Name Writable + ------ -------- -------- + [no tags known] + +=head3 Canon CNTH Tags + +Canon-specific QuickTime tags found in the CNTH atom of MOV videos from some +cameras such as the PowerShot S95. + + Tag ID Tag Name Writable + ------ -------- -------- + 'CNDA' ThumbnailImage no + +=head3 Canon CTMD Tags + +Canon Timed MetaData tags found in CR3 images. The ExtractEmbedded option +is automatically applied when reading CR3 files to be able to extract this +information. + + Tag ID Tag Name Writable + ------ -------- -------- + 0x0001 TimeStamp no + 0x0004 FocalInfo Canon FocalInfo + 0x0005 ExposureInfo Canon ExposureInfo + 0x0007 ExifInfo7 Canon ExifInfo + 0x0008 ExifInfo8 Canon ExifInfo + 0x0009 ExifInfo9 Canon ExifInfo + +=head3 Canon FocalInfo Tags + + Index4 Tag Name Writable + ------ -------- -------- + 0 FocalLength no + +=head3 Canon ExposureInfo Tags + + Index4 Tag Name Writable + ------ -------- -------- + 0 FNumber no + 1 ExposureTime no + 2 ISO no + +=head3 Canon ExifInfo Tags + + Tag ID Tag Name Writable + ------ -------- -------- + 0x8769 ExifIFD EXIF + 0x927c MakerNoteCanon Canon + +=head3 Canon uuid Tags + +Tags extracted from the uuid atom of MP4 videos from cameras such as the +SX280, and CR3 images from cameras such as the EOS M50. + + Tag ID Tag Name Writable + ------ -------- -------- + 'CCTP' CanonCCTP Canon CCTP + 'CMT1' IFD0 EXIF + 'CMT2' ExifIFD EXIF + 'CMT3' MakerNoteCanon Canon + 'CMT4' GPSInfo GPS + 'CNCV' CompressorVersion no + 'CNOP' CanonCNOP Canon CNOP + 'CNTH' CanonCNTH Canon CNTH + 'THMB' ThumbnailImage no + +=head3 Canon CCTP Tags + + Tag ID Tag Name Writable + ------ -------- -------- + [no tags known] + +=head3 Canon Skip Tags + +Information found in the "skip" atom of Canon MOV videos. + + Tag ID Tag Name Writable + ------ -------- -------- + 'CNDB' Unknown_CNDB? no + +=head2 CanonCustom Tags + +=head3 CanonCustom Functions1D Tags + +These custom functions are used by all 1D models up to but not including the +Mark III. + + Tag ID Tag Name Writable + ------ -------- -------- + 0 FocusingScreen int8u + 1 FinderDisplayDuringExposure int8u + 2 ShutterReleaseNoCFCard int8u + 3 ISOSpeedExpansion int8u + 4 ShutterAELButton int8u + 5 ManualTv int8u + 6 ExposureLevelIncrements int8u + 7 USMLensElectronicMF int8u + 8 LCDPanels int8u + 9 AEBSequenceAutoCancel int8u + 10 AFPointIllumination int8u + 11 AFPointSelection int8u + 12 MirrorLockup int8u + 13 AFPointSpotMetering int8u + 14 FillFlashAutoReduction int8u + 15 ShutterCurtainSync int8u + 16 SafetyShiftInAvOrTv int8u + 17 AFPointActivationArea int8u + 18 SwitchToRegisteredAFPoint int8u + 19 LensAFStopButton int8u + 20 AIServoTrackingSensitivity int8u + 21 AIServoContinuousShooting int8u + +=head3 CanonCustom Functions5D Tags + + Tag ID Tag Name Writable + ------ -------- -------- + 0 FocusingScreen int8u + 1 SetFunctionWhenShooting int8u + 2 LongExposureNoiseReduction int8u + 3 FlashSyncSpeedAv int8u + 4 Shutter-AELock int8u + 5 AFAssistBeam int8u + 6 ExposureLevelIncrements int8u + 7 FlashFiring int8u + 8 ISOExpansion int8u + 9 AEBSequenceAutoCancel int8u + 10 SuperimposedDisplay int8u + 11 MenuButtonDisplayPosition int8u + 12 MirrorLockup int8u + 13 AFPointSelectionMethod int8u + 14 ETTLII int8u + 15 ShutterCurtainSync int8u + 16 SafetyShiftInAvOrTv int8u + 17 AFPointActivationArea int8u + 18 LCDDisplayReturnToShoot int8u + 19 LensAFStopButton int8u + 20 AddOriginalDecisionData int8u + +=head3 CanonCustom Functions10D Tags + + Tag ID Tag Name Writable + ------ -------- -------- + 1 SetButtonWhenShooting int8u + 2 ShutterReleaseNoCFCard int8u + 3 FlashSyncSpeedAv int8u + 4 Shutter-AELock int8u + 5 AFAssist int8u + 6 ExposureLevelIncrements int8u + 7 AFPointRegistration int8u + 8 RawAndJpgRecording int8u + 9 AEBSequenceAutoCancel int8u + 10 SuperimposedDisplay int8u + 11 MenuButtonDisplayPosition int8u + 12 MirrorLockup int8u + 13 AssistButtonFunction int8u + 14 FillFlashAutoReduction int8u + 15 ShutterCurtainSync int8u + 16 SafetyShiftInAvOrTv int8u + 17 LensAFStopButton int8u + +=head3 CanonCustom Functions20D Tags + + Tag ID Tag Name Writable + ------ -------- -------- + 0 SetFunctionWhenShooting int8u + 1 LongExposureNoiseReduction int8u + 2 FlashSyncSpeedAv int8u + 3 Shutter-AELock int8u + 4 AFAssistBeam int8u + 5 ExposureLevelIncrements int8u + 6 FlashFiring int8u + 7 ISOExpansion int8u + 8 AEBSequenceAutoCancel int8u + 9 SuperimposedDisplay int8u + 10 MenuButtonDisplayPosition int8u + 11 MirrorLockup int8u + 12 AFPointSelectionMethod int8u + 13 ETTLII int8u + 14 ShutterCurtainSync int8u + 15 SafetyShiftInAvOrTv int8u + 16 LensAFStopButton int8u + 17 AddOriginalDecisionData int8u + +=head3 CanonCustom Functions30D Tags + + Tag ID Tag Name Writable + ------ -------- -------- + 1 SetFunctionWhenShooting int8u + 2 LongExposureNoiseReduction int8u + 3 FlashSyncSpeedAv int8u + 4 Shutter-AELock int8u + 5 AFAssistBeam int8u + 6 ExposureLevelIncrements int8u + 7 FlashFiring int8u + 8 ISOExpansion int8u + 9 AEBSequenceAutoCancel int8u + 10 SuperimposedDisplay int8u + 11 MenuButtonDisplayPosition int8u + 12 MirrorLockup int8u + 13 AFPointSelectionMethod int8u + 14 ETTLII int8u + 15 ShutterCurtainSync int8u + 16 SafetyShiftInAvOrTv int8u + 17 MagnifiedView int8u + 18 LensAFStopButton int8u + 19 AddOriginalDecisionData int8u + +=head3 CanonCustom Functions350D Tags + + Tag ID Tag Name Writable + ------ -------- -------- + 0 SetButtonCrossKeysFunc int8u + 1 LongExposureNoiseReduction int8u + 2 FlashSyncSpeedAv int8u + 3 Shutter-AELock int8u + 4 AFAssistBeam int8u + 5 ExposureLevelIncrements int8u + 6 MirrorLockup int8u + 7 ETTLII int8u + 8 ShutterCurtainSync int8u + +=head3 CanonCustom Functions400D Tags + + Tag ID Tag Name Writable + ------ -------- -------- + 0 SetButtonCrossKeysFunc int8u + 1 LongExposureNoiseReduction int8u + 2 FlashSyncSpeedAv int8u + 3 Shutter-AELock int8u + 4 AFAssistBeam int8u + 5 ExposureLevelIncrements int8u + 6 MirrorLockup int8u + 7 ETTLII int8u + 8 ShutterCurtainSync int8u + 9 MagnifiedView int8u + 10 LCDDisplayAtPowerOn int8u + +=head3 CanonCustom FunctionsD30 Tags + +Custom functions for the EOS D30 and D60. + + Tag ID Tag Name Writable + ------ -------- -------- + 1 LongExposureNoiseReduction int8u + 2 Shutter-AELock int8u + 3 MirrorLockup int8u + 4 ExposureLevelIncrements int8u + 5 AFAssist int8u + 6 FlashSyncSpeedAv int8u + 7 AEBSequenceAutoCancel int8u + 8 ShutterCurtainSync int8u + 9 LensAFStopButton int8u + 10 FillFlashAutoReduction int8u + 11 MenuButtonReturn int8u + 12 SetButtonWhenShooting int8u + 13 SensorCleaning int8u + 14 SuperimposedDisplay int8u + 15 ShutterReleaseNoCFCard int8u + +=head3 CanonCustom FuncsUnknown Tags + + Tag ID Tag Name Writable + ------ -------- -------- + [no tags known] + +=head3 CanonCustom PersonalFuncs Tags + +Personal function settings for the EOS-1D. + + Index2 Tag Name Writable + ------ -------- -------- + 1 PF0CustomFuncRegistration int16u + 2 PF1DisableShootingModes int16u + 3 PF2DisableMeteringModes int16u + 4 PF3ManualExposureMetering int16u + 5 PF4ExposureTimeLimits int16u + 6 PF5ApertureLimits int16u + 7 PF6PresetShootingModes int16u + 8 PF7BracketContinuousShoot int16u + 9 PF8SetBracketShots int16u + 10 PF9ChangeBracketSequence int16u + 11 PF10RetainProgramShift int16u + 14 PF13DrivePriority int16u + 15 PF14DisableFocusSearch int16u + 16 PF15DisableAFAssistBeam int16u + 17 PF16AutoFocusPointShoot int16u + 18 PF17DisableAFPointSel int16u + 19 PF18EnableAutoAFPointSel int16u + 20 PF19ContinuousShootSpeed int16u + 21 PF20LimitContinousShots int16u + 22 PF21EnableQuietOperation int16u + 24 PF23SetTimerLengths int16u + 25 PF24LightLCDDuringBulb int16u + 26 PF25DefaultClearSettings int16u + 27 PF26ShortenReleaseLag int16u + 28 PF27ReverseDialRotation int16u + 29 PF28NoQuickDialExpComp int16u + 30 PF29QuickDialSwitchOff int16u + 31 PF30EnlargementMode int16u + 32 PF31OriginalDecisionData int16u + +=head3 CanonCustom PersonalFuncValues Tags + + Index2 Tag Name Writable + ------ -------- -------- + 1 PF1Value int16u + 2 PF2Value int16u + 3 PF3Value int16u + 4 PF4ExposureTimeMin int16u + 5 PF4ExposureTimeMax int16u + 6 PF5ApertureMin int16u + 7 PF5ApertureMax int16u + 8 PF8BracketShots int16u + 9 PF19ShootingSpeedLow int16u + 10 PF19ShootingSpeedHigh int16u + 11 PF20MaxContinousShots int16u + 12 PF23ShutterButtonTime int16u + 13 PF23FELockTime int16u + 14 PF23PostReleaseTime int16u + 15 PF25AEMode int16u + 16 PF25MeteringMode int16u + 17 PF25DriveMode int16u + 18 PF25AFMode int16u + 19 PF25AFPointSel int16u + 20 PF25ImageSize int16u + 21 PF25WBMode int16u + 22 PF25Parameters int16u + 23 PF25ColorMatrix int16u + 24 PF27Value int16u + +=head3 CanonCustom Functions2 Tags + +Beginning with the EOS 1D Mark III, Canon finally created a set of custom +function tags which are (reasonably) consistent across models. The EOS 1D +Mark III has 57 custom function tags divided into four main groups: 1. +Exposure (0x0101-0x010f), 2. Image (0x0201-0x0203), Flash Exposure +(0x0304-0x0306) and Display (0x0407-0x0409), 3. Auto Focus (0x0501-0x050e) +and Drive (0x060f-0x0611), and 4. Operation (0x0701-0x070a) and Others +(0x080b-0x0810). The table below lists tags used by the EOS 1D Mark III, as +well as newer tags and values added by later models. + + Tag ID Tag Name Writable + ------ -------- -------- + 0x0101 ExposureLevelIncrements int32s + 0x0102 ISOSpeedIncrements int32s + 0x0103 ISOSpeedRange int32s[3] + ISOExpansion int32s + 0x0104 AEBAutoCancel int32s + 0x0105 AEBSequence int32s + 0x0106 AEBShotCount int32s + AEBShotCount int32s[2] + 0x0107 SpotMeterLinkToAFPoint int32s + 0x0108 SafetyShift int32s + 0x0109 UsableShootingModes int32s[2] + 0x010a UsableMeteringModes int32s[2] + 0x010b ExposureModeInManual int32s + 0x010c ShutterSpeedRange int32s[3] + ShutterSpeedRange int32s[4] + 0x010d ApertureRange int32s[3] + ApertureRange int32s[4] + 0x010e ApplyShootingMeteringMode int32s[8] + 0x010f FlashSyncSpeedAv int32s + 0x0110 AEMicroadjustment int32s[3] + 0x0111 FEMicroadjustment int32s[3] + 0x0112 SameExposureForNewAperture int32s + 0x0113 ExposureCompAutoCancel int32s + 0x0114 AELockMeterModeAfterFocus int32s + 0x0201 LongExposureNoiseReduction int32s + 0x0202 HighISONoiseReduction int32s + 0x0203 HighlightTonePriority int32s + 0x0204 AutoLightingOptimizer int32s + 0x0304 ETTLII int32s + 0x0305 ShutterCurtainSync int32s + 0x0306 FlashFiring int32s + 0x0407 ViewInfoDuringExposure int32s + 0x0408 LCDIlluminationDuringBulb int32s + 0x0409 InfoButtonWhenShooting int32s + 0x040a ViewfinderWarnings int32s + 0x040b LVShootingAreaDisplay int32s + 0x040c LVShootingAreaDisplay int32s + 0x0501 USMLensElectronicMF int32s + 0x0502 AIServoTrackingSensitivity int32s + 0x0503 AIServoImagePriority int32s + 0x0504 AIServoTrackingMethod int32s + 0x0505 LensDriveNoAF int32s + 0x0506 LensAFStopButton int32s + 0x0507 AFMicroadjustment int32s[5] + 0x0508 AFPointAreaExpansion int32s + 0x0509 SelectableAFPoint int32s + 0x050a SwitchToRegisteredAFPoint int32s + 0x050b AFPointAutoSelection int32s + 0x050c AFPointDisplayDuringFocus int32s + 0x050d AFPointBrightness int32s + 0x050e AFAssistBeam int32s + 0x050f AFPointSelectionMethod int32s + 0x0510 VFDisplayIllumination int32s + SuperimposedDisplay int32s + 0x0511 AFDuringLiveView int32s + 0x0512 SelectAFAreaSelectMode int32s + 0x0513 ManualAFPointSelectPattern int32s + 0x0514 DisplayAllAFPoints int32s + 0x0515 FocusDisplayAIServoAndMF int32s + 0x0516 OrientationLinkedAFPoint int32s + 0x0517 MultiControllerWhileMetering int32s + 0x0518 AccelerationTracking int32s + 0x0519 AIServoFirstImagePriority int32s + 0x051a AIServoSecondImagePriority int32s + 0x051b AFAreaSelectMethod int32s + 0x051c AutoAFPointColorTracking int32s + 0x051d VFDisplayIllumination int32s + 0x051e InitialAFPointAIServoAF int32s + 0x060f MirrorLockup int32s + 0x0610 ContinuousShootingSpeed int32s[3] + 0x0611 ContinuousShotLimit int32s[2] + 0x0612 RestrictDriveModes int32s[2] + 0x0701 Shutter-AELock int32s + AFAndMeteringButtons int32s + ShutterButtonAFOnButton int32s + 0x0702 AFOnAELockButtonSwitch int32s + 0x0703 QuickControlDialInMeter int32s + 0x0704 SetButtonWhenShooting int32s + 0x0705 ManualTv int32s + 0x0706 DialDirectionTvAv int32s + 0x0707 AvSettingWithoutLens int32s + 0x0708 WBMediaImageSizeSetting int32s + 0x0709 LockMicrophoneButton int32s + 0x070a ButtonFunctionControlOff int32s + 0x070b AssignFuncButton int32s + 0x070c CustomControls int32s + 0x070d StartMovieShooting int32s + 0x070e FlashButtonFunction int32s + 0x070f MultiFunctionLock int32s + 0x0710 TrashButtonFunction int32s + 0x0711 ShutterReleaseWithoutLens int32s + 0x0712 ControlRingRotation int32s + 0x0713 FocusRingRotation int32s + 0x0714 RFLensMFFocusRingSensitivity int32s + 0x0715 CustomizeDials int32s + 0x080b FocusingScreen int32s + 0x080c TimerLength int32s[4] + 0x080d ShortReleaseTimeLag int32s + 0x080e AddAspectRatioInfo int32s + 0x080f AddOriginalDecisionData int32s + 0x0810 LiveViewExposureSimulation int32s + 0x0811 LCDDisplayAtPowerOn int32s + 0x0812 MemoAudioQuality int32s + 0x0813 DefaultEraseOption int32s + 0x0814 RetractLensOnPowerOff int32s + 0x0815 AddIPTCInformation int32s + +=head2 CanonVRD Tags + +Canon Digital Photo Professional writes VRD (Recipe Data) information as a +trailer record to JPEG, TIFF, CRW and CR2 images, or as stand-alone VRD or +DR4 files. The tags listed below represent information found in these +records. The complete VRD/DR4 data record may be accessed as a block using +the Extra 'CanonVRD' or 'CanonDR4' tag, but this tag is not extracted or +copied unless specified explicitly. + + Tag ID Tag Name Writable + ------ -------- -------- + 0xffff00f4 EditData CanonVRD Edit + 0xffff00f5 IHLData CanonVRD IHL + 0xffff00f6 XMP XMP + 0xffff00f7 Edit4Data CanonVRD Edit4 + +=head3 CanonVRD Edit Tags + +Canon VRD edit information. + + Index Tag Name Writable + ----- -------- -------- + 0 VRD1 CanonVRD Ver1 + 1 VRDStampTool CanonVRD StampTool + 2 VRD2 CanonVRD Ver2 + +=head3 CanonVRD Ver1 Tags + + Index1 Tag Name Writable + ------ -------- -------- + 2 VRDVersion no + 6 WBAdjRGGBLevels int16u[4] + 24 WhiteBalanceAdj int16u + 26 WBAdjColorTemp int16u + 36 WBFineTuneActive int16u + 40 WBFineTuneSaturation int16u + 44 WBFineTuneTone int16u + 46 RawColorAdj int16u + 48 RawCustomSaturation int32s + 52 RawCustomTone int32s + 56 RawBrightnessAdj int32s + 60 ToneCurveProperty int16u + 122 DynamicRangeMin int16u + 124 DynamicRangeMax int16u + 272 ToneCurveActive int16u + 275 ToneCurveMode int8u + 276 BrightnessAdj int8s + 277 ContrastAdj int8s + 278 SaturationAdj int16s + 286 ColorToneAdj int32s + 294 LuminanceCurvePoints int16u[21] + 336 LuminanceCurveLimits int16u[4] + 345 ToneCurveInterpolation int8u + 352 RedCurvePoints int16u[21] + 394 RedCurveLimits int16u[4] + 410 GreenCurvePoints int16u[21] + 452 GreenCurveLimits int16u[4] + 468 BlueCurvePoints int16u[21] + 510 BlueCurveLimits int16u[4] + 526 RGBCurvePoints int16u[21] + 568 RGBCurveLimits int16u[4] + 580 CropActive int16u + 582 CropLeft int16u + 584 CropTop int16u + 586 CropWidth int16u + 588 CropHeight int16u + 602 SharpnessAdj int16u + 608 CropAspectRatio int16u + 610 ConstrainedCropWidth float + 614 ConstrainedCropHeight float + 618 CheckMark int16u + 622 Rotation int16u + 624 WorkColorSpace int16u + +=head3 CanonVRD StampTool Tags + + Index1 Tag Name Writable + ------ -------- -------- + 0 StampToolCount no + +=head3 CanonVRD Ver2 Tags + +Tags added in DPP version 2.0 and later. + + Index2 Tag Name Writable + ------ -------- -------- + 2 PictureStyle int16s + 3 IsCustomPictureStyle int16s + 13 StandardRawColorTone int16s + 14 StandardRawSaturation int16s + 15 StandardRawContrast int16s + 16 StandardRawLinear int16s + 17 StandardRawSharpness int16s + 18 StandardRawHighlightPoint int16s + 19 StandardRawShadowPoint int16s + 20 StandardOutputHighlightPoint int16s + 21 StandardOutputShadowPoint int16s + 22 PortraitRawColorTone int16s + 23 PortraitRawSaturation int16s + 24 PortraitRawContrast int16s + 25 PortraitRawLinear int16s + 26 PortraitRawSharpness int16s + 27 PortraitRawHighlightPoint int16s + 28 PortraitRawShadowPoint int16s + 29 PortraitOutputHighlightPoint int16s + 30 PortraitOutputShadowPoint int16s + 31 LandscapeRawColorTone int16s + 32 LandscapeRawSaturation int16s + 33 LandscapeRawContrast int16s + 34 LandscapeRawLinear int16s + 35 LandscapeRawSharpness int16s + 36 LandscapeRawHighlightPoint int16s + 37 LandscapeRawShadowPoint int16s + 38 LandscapeOutputHighlightPoint int16s + 39 LandscapeOutputShadowPoint int16s + 40 NeutralRawColorTone int16s + 41 NeutralRawSaturation int16s + 42 NeutralRawContrast int16s + 43 NeutralRawLinear int16s + 44 NeutralRawSharpness int16s + 45 NeutralRawHighlightPoint int16s + 46 NeutralRawShadowPoint int16s + 47 NeutralOutputHighlightPoint int16s + 48 NeutralOutputShadowPoint int16s + 49 FaithfulRawColorTone int16s + 50 FaithfulRawSaturation int16s + 51 FaithfulRawContrast int16s + 52 FaithfulRawLinear int16s + 53 FaithfulRawSharpness int16s + 54 FaithfulRawHighlightPoint int16s + 55 FaithfulRawShadowPoint int16s + 56 FaithfulOutputHighlightPoint int16s + 57 FaithfulOutputShadowPoint int16s + 58 MonochromeFilterEffect int16s + 59 MonochromeToningEffect int16s + 60 MonochromeContrast int16s + 61 MonochromeLinear int16s + 62 MonochromeSharpness int16s + 63 MonochromeRawHighlightPoint int16s + 64 MonochromeRawShadowPoint int16s + 65 MonochromeOutputHighlightPoint int16s + 66 MonochromeOutputShadowPoint int16s + 69 UnknownContrast? int16s + 70 UnknownLinear? int16s + 71 UnknownSharpness? int16s + 72 UnknownRawHighlightPoint? int16s + 73 UnknownRawShadowPoint? int16s + 74 UnknownOutputHighlightPoint? int16s + 75 UnknownOutputShadowPoint? int16s + 76 CustomColorTone int16s + 77 CustomSaturation int16s + 78 CustomContrast int16s + 79 CustomLinear int16s + 80 CustomSharpness int16s + 81 CustomRawHighlightPoint int16s + 82 CustomRawShadowPoint int16s + 83 CustomOutputHighlightPoint int16s + 84 CustomOutputShadowPoint int16s + 88 CustomPictureStyleData no + 94 ChrominanceNoiseReduction int16s + 95 LuminanceNoiseReduction int16s + 96 ChrominanceNR_TIFF_JPEG int16s + 98 ChromaticAberrationOn int16s + 99 DistortionCorrectionOn int16s + 100 PeripheralIlluminationOn int16s + 101 ColorBlur int16s + 102 ChromaticAberration int16s + 103 DistortionCorrection int16s + 104 PeripheralIllumination int16s + 105 AberrationCorrectionDistance int16s + 106 ChromaticAberrationRed int16s + 107 ChromaticAberrationBlue int16s + 109 LuminanceNR_TIFF_JPEG int16s + 110 AutoLightingOptimizerOn int16s + 111 AutoLightingOptimizer int16s + 117 StandardRawHighlight int16s + 118 PortraitRawHighlight int16s + 119 LandscapeRawHighlight int16s + 120 NeutralRawHighlight int16s + 121 FaithfulRawHighlight int16s + 122 MonochromeRawHighlight int16s + 123 UnknownRawHighlight? int16s + 124 CustomRawHighlight int16s + 126 StandardRawShadow int16s + 127 PortraitRawShadow int16s + 128 LandscapeRawShadow int16s + 129 NeutralRawShadow int16s + 130 FaithfulRawShadow int16s + 131 MonochromeRawShadow int16s + 132 UnknownRawShadow? int16s + 133 CustomRawShadow int16s + 139 AngleAdj int32s + 142 CheckMark2 int16u + 144 UnsharpMask int16s + 146 StandardUnsharpMaskStrength int16s + 148 StandardUnsharpMaskFineness int16s + 150 StandardUnsharpMaskThreshold int16s + 152 PortraitUnsharpMaskStrength int16s + 154 PortraitUnsharpMaskFineness int16s + 156 PortraitUnsharpMaskThreshold int16s + 158 LandscapeUnsharpMaskStrength int16s + 160 LandscapeUnsharpMaskFineness int16s + 162 LandscapeUnsharpMaskThreshold int16s + 164 NeutraUnsharpMaskStrength int16s + 166 NeutralUnsharpMaskFineness int16s + 168 NeutralUnsharpMaskThreshold int16s + 170 FaithfulUnsharpMaskStrength int16s + 172 FaithfulUnsharpMaskFineness int16s + 174 FaithfulUnsharpMaskThreshold int16s + 176 MonochromeUnsharpMaskStrength int16s + 178 MonochromeUnsharpMaskFineness int16s + 180 MonochromeUnsharpMaskThreshold int16s + 182 CustomUnsharpMaskStrength int16s + 184 CustomUnsharpMaskFineness int16s + 186 CustomUnsharpMaskThreshold int16s + 188 CustomDefaultUnsharpStrength int16s + 190 CustomDefaultUnsharpFineness int16s + 192 CustomDefaultUnsharpThreshold int16s + 214 CropCircleActive int16s + 215 CropCircleX int16s + 216 CropCircleY int16s + 217 CropCircleRadius int16s + 220 DLOOn int16s + 221 DLOSetting int16s + 222 DLOShootingDistance int16s + 223 DLODataLength no + 224 DLOInfo CanonVRD DLOInfo + 225 CameraRawColorTone int16s + 226 CameraRawSaturation int16s + 227 CameraRawContrast int16s + 228 CameraRawLinear int16s + 229 CameraRawSharpness int16s + 230 CameraRawHighlightPoint int16s + 231 CameraRawShadowPoint int16s + 232 CameraRawOutputHighlightPoint int16s + 233 CameraRawOutputShadowPoint int16s + +=head3 CanonVRD DLOInfo Tags + +Tags added when DLO (Digital Lens Optimizer) is on. + + Index2 Tag Name Writable + ------ -------- -------- + 4 DLOSettingApplied int16s + 5 DLOVersion string[10] + 10 DLOData no + +=head3 CanonVRD IHL Tags + + Tag ID Tag Name Writable + ------ -------- -------- + 0x0001 IHL_EXIF EXIF + IHL_EXIF? no + 0x0003 ThumbnailImage no + 0x0004 PreviewImage no + 0x0005 RawCodecVersion no + 0x0006 CRCDevelParams? no + +=head3 CanonVRD Edit4 Tags + +Canon DPP version 4 edit information. + + Index Tag Name Writable + ----- -------- -------- + 0 DR4 CanonVRD DR4 + +=head3 CanonVRD DR4 Tags + +Tags written by Canon DPP version 4 in CanonVRD trailers and DR4 files. Each +tag has three associated flag words which are stored with the directory +entry, some of which are extracted as a separate tag, indicated in the table +below by a decimal appended to the tag ID (.0, .1 or .2). + + Tag ID Tag Name Writable + ------ -------- -------- + 'header' DR4Header CanonVRD DR4Header + 0x10002 Rotation yes + 0x10003 AngleAdj yes + 0x10021 CustomPictureStyle yes + 0x10101 CheckMark yes + 0x10200 WorkColorSpace yes + 0x20001 RawBrightnessAdj yes + 0x20101 WhiteBalanceAdj yes + 0x20102 WBAdjColorTemp yes + 0x20105 WBAdjMagentaGreen yes + 0x20106 WBAdjBlueAmber yes + 0x20125 WBAdjRGGBLevels yes + 0x20200 GammaLinear yes + 0x20301 PictureStyle yes + 0x20303 ContrastAdj yes + 0x20304 ColorToneAdj yes + 0x20305 ColorSaturationAdj yes + 0x20306 MonochromeToningEffect yes + 0x20307 MonochromeFilterEffect yes + 0x20308 UnsharpMaskStrength yes + 0x20309 UnsharpMaskFineness yes + 0x2030a UnsharpMaskThreshold yes + 0x2030b ShadowAdj yes + 0x2030c HighlightAdj yes + 0x20310 SharpnessAdj yes + 0x20310.0 SharpnessAdjOn yes + 0x20311 SharpnessStrength yes + 0x20400 ToneCurve CanonVRD ToneCurve + 0x20400.1 ToneCurveOriginal yes + 0x20410 ToneCurveBrightness yes + 0x20411 ToneCurveContrast yes + 0x20500 AutoLightingOptimizer yes + 0x20500.0 AutoLightingOptimizerOn yes + 0x20600 LuminanceNoiseReduction yes + 0x20601 ChrominanceNoiseReduction yes + 0x20670 ColorMoireReduction yes + 0x20670.0 ColorMoireReductionOn yes + 0x20701 ShootingDistance yes + 0x20702 PeripheralIllumination yes + 0x20702.0 PeripheralIlluminationOn yes + 0x20703 ChromaticAberration yes + 0x20703.0 ChromaticAberrationOn yes + 0x20704 ColorBlurOn yes + 0x20705 DistortionCorrection yes + 0x20705.0 DistortionCorrectionOn yes + 0x20706 DLOSetting yes + 0x20706.0 DLOOn yes + 0x20707 ChromaticAberrationRed yes + 0x20708 ChromaticAberrationBlue yes + 0x20709 DistortionEffect yes + 0x2070b DiffractionCorrectionOn yes + 0x20900 ColorHue yes + 0x20901 SaturationAdj yes + 0x20910 RedHSL yes + 0x20911 OrangeHSL yes + 0x20912 YellowHSL yes + 0x20913 GreenHSL yes + 0x20914 AquaHSL yes + 0x20915 BlueHSL yes + 0x20916 PurpleHSL yes + 0x20917 MagentaHSL yes + 0x20a00 GammaInfo CanonVRD GammaInfo + 0x30101 CropAspectRatio yes + 0x30102 CropAspectRatioCustom yes + 0xf0100 CropInfo CanonVRD CropInfo + 0xf0500 CustomPictureStyleData yes + 0xf0510 StampInfo CanonVRD StampInfo + 0xf0511 DustInfo CanonVRD DustInfo + 0xf0512 LensFocalLength yes + +=head3 CanonVRD DR4Header Tags + + Index4 Tag Name Writable + ------ -------- -------- + 3 DR4CameraModel int32u + +=head3 CanonVRD ToneCurve Tags + + Index4 Tag Name Writable + ------ -------- -------- + 0 ToneCurveColorSpace int32u + 1 ToneCurveShape int32u + 3 ToneCurveInputRange int32u[2] + 5 ToneCurveOutputRange int32u[2] + 7 RGBCurvePoints int32u[21] + 10 ToneCurveX int32u + 11 ToneCurveY int32u + 45 RedCurvePoints int32u[21] + 83 GreenCurvePoints int32u[21] + 121 BlueCurvePoints int32u[21] + +=head3 CanonVRD GammaInfo Tags + + Index8 Tag Name Writable + ------ -------- -------- + 2 GammaContrast double + 3 GammaColorTone double + 4 GammaSaturation double + 5 GammaUnsharpMaskStrength double + 6 GammaUnsharpMaskFineness double + 7 GammaUnsharpMaskThreshold double + 8 GammaSharpnessStrength double + 9 GammaShadow double + 10 GammaHighlight double + 12 GammaBlackPoint double + 13 GammaWhitePoint double + 14 GammaMidPoint double + 15 GammaCurveOutputRange double[2] + +=head3 CanonVRD CropInfo Tags + + Index4 Tag Name Writable + ------ -------- -------- + 0 CropActive int32s + 1 CropRotatedOriginalWidth int32s + 2 CropRotatedOriginalHeight int32s + 3 CropX int32s + 4 CropY int32s + 5 CropWidth int32s + 6 CropHeight int32s + 8 CropRotation double + 10 CropOriginalWidth int32s + 11 CropOriginalHeight int32s + +=head3 CanonVRD StampInfo Tags + + Index4 Tag Name Writable + ------ -------- -------- + 2 StampToolCount no + +=head3 CanonVRD DustInfo Tags + + Index4 Tag Name Writable + ------ -------- -------- + 2 DustDeleteApplied no + +=head2 Casio Tags + + Tag ID Tag Name Writable + ------ -------- -------- + 0x0001 RecordingMode int16u + 0x0002 Quality int16u + 0x0003 FocusMode int16u + 0x0004 FlashMode int16u + 0x0005 FlashIntensity int16u + 0x0006 ObjectDistance int32u + 0x0007 WhiteBalance int16u + 0x000a DigitalZoom int32u + 0x000b Sharpness int16u + 0x000c Contrast int16u + 0x000d Saturation int16u + 0x0014 ISO int16u + 0x0015 FirmwareDate string[18] + 0x0016 Enhancement int16u + 0x0017 ColorFilter int16u + 0x0018 AFPoint int16u + 0x0019 FlashIntensity int16u + 0x0e00 PrintIM PrintIM + +=head3 Casio Type2 Tags + + Tag ID Tag Name Writable + ------ -------- -------- + 0x0002 PreviewImageSize int16u[2] + 0x0003 PreviewImageLength int32u* + 0x0004 PreviewImageStart int32u* + 0x0008 QualityMode int16u + 0x0009 CasioImageSize int16u + 0x000d FocusMode int16u + 0x0014 ISO int16u + 0x0019 WhiteBalance int16u + 0x001d FocalLength rational64u + 0x001f Saturation int16u + 0x0020 Contrast int16u + 0x0021 Sharpness int16u + 0x0e00 PrintIM PrintIM + 0x2000 PreviewImage undef + 0x2001 FirmwareDate string[18] + 0x2011 WhiteBalanceBias int16u[2] + 0x2012 WhiteBalance int16u + 0x2021 AFPointPosition int16u[4]~ + 0x2022 ObjectDistance int32u + 0x2034 FlashDistance int16u + 0x2076 SpecialEffectMode int8u[3] + 0x2089 FaceInfo1 Casio FaceInfo1 + FaceInfo2 Casio FaceInfo2 + FaceInfoUnknown? yes + 0x211c FacesDetected int8u + 0x3000 RecordMode int16u + 0x3001 ReleaseMode int16u + 0x3002 Quality int16u + 0x3003 FocusMode int16u + 0x3006 HometownCity string + 0x3007 BestShotMode int16u + 0x3008 AutoISO int16u + 0x3009 AFMode int16u + 0x3011 Sharpness undef[2] + 0x3012 Contrast undef[2] + 0x3013 Saturation undef[2] + 0x3014 ISO int16u + 0x3015 ColorMode int16u + 0x3016 Enhancement int16u + 0x3017 ColorFilter int16u + 0x301b ArtMode int16u + 0x301c SequenceNumber int16u + 0x301d BracketSequence int16u[2] + 0x3020 ImageStabilization int16u + 0x302a LightingMode int16u + 0x302b PortraitRefiner int16u + 0x3030 SpecialEffectLevel int16u + 0x3031 SpecialEffectSetting int16u + 0x3103 DriveMode int16u + 0x310b ArtModeParameters int8u[3] + 0x4001 CaptureFrameRate int16u[n] + 0x4003 VideoQuality int16u + +=head3 Casio FaceInfo1 Tags + +Face-detect tags extracted from models such as the EX-H5. + + Index1 Tag Name Writable + ------ -------- -------- + 0 FacesDetected int8u + 1 FaceDetectFrameSize int16u[2] + 13 Face1Position int16u[4] + 124 Face2Position int16u[4] + 235 Face3Position int16u[4] + 346 Face4Position int16u[4] + 457 Face5Position int16u[4] + 568 Face6Position int16u[4] + 679 Face7Position int16u[4] + 790 Face8Position int16u[4] + 901 Face9Position int16u[4] + 1012 Face10Position int16u[4] + +=head3 Casio FaceInfo2 Tags + +Face-detect tags extracted from models such as the EX-H20G and EX-ZR100. + + Index1 Tag Name Writable + ------ -------- -------- + 2 FacesDetected int8u + 4 FaceDetectFrameSize int16u[2] + 8 FaceOrientation int8u + 24 Face1Position int16u[4] + 76 Face2Position int16u[4] + 128 Face3Position int16u[4] + 180 Face4Position int16u[4] + 232 Face5Position int16u[4] + 284 Face6Position int16u[4] + 336 Face7Position int16u[4] + 388 Face8Position int16u[4] + 440 Face9Position int16u[4] + 492 Face10Position int16u[4] + +=head3 Casio QVCI Tags + +This information is found in the APP1 QVCI segment of JPEG images from the +Casio QV-7000SX. + + Index1 Tag Name Writable + ------ -------- -------- + 44 CasioQuality no + 55 FocalRange? no + 77 DateTimeOriginal no + 98 ModelType no + 114 ManufactureIndex no + 124 ManufactureCode no + +=head3 Casio AVI Tags + +This information is found in Casio GV-10 AVI videos. + + Index1 Tag Name Writable + ------ -------- -------- + 0 Software no + +=head2 FLIR Tags + +Information extracted from the maker notes of JPEG images from thermal +imaging cameras by FLIR Systems Inc. + + Tag ID Tag Name Writable + ------ -------- -------- + 0x0001 ImageTemperatureMax rational64u + 0x0002 ImageTemperatureMin rational64u + 0x0003 Emissivity rational64u + 0x0004 UnknownTemperature? rational64u + 0x0005 CameraTemperatureRangeMax? rational64u + 0x0006 CameraTemperatureRangeMin? rational64u + +=head3 FLIR FFF Tags + +Information extracted from FLIR FFF images and the APP1 FLIR segment of JPEG +images. These tags may also be extracted from the first frame of an FLIR +SEQ file. + + Tag ID Tag Name Writable + ------ -------- -------- + '_header' FFFHeader FLIR Header + 0x0001 RawData FLIR RawData + 0x0005 GainDeadData FLIR GainDeadData + 0x0006 CoarseData FLIR CoarseData + 0x000e EmbeddedImage FLIR EmbeddedImage + 0x0020 CameraInfo FLIR CameraInfo + 0x0021 MeasurementInfo FLIR MeasInfo + 0x0022 PaletteInfo FLIR PaletteInfo + 0x0023 TextInfo FLIR TextInfo + 0x0024 EmbeddedAudioFile no + 0x0028 PaintData FLIR PaintData + 0x002a PiP FLIR PiP + 0x002b GPSInfo FLIR GPSInfo + 0x002c MeterLink FLIR MeterLink + 0x002e ParameterInfo FLIR ParamInfo + +=head3 FLIR Header Tags + +Tags extracted from the FLIR FFF/AFF header. + + Index1 Tag Name Writable + ------ -------- -------- + 4 CreatorSoftware no + +=head3 FLIR RawData Tags + +The thermal image data may be stored either as raw data, or in PNG format. +If stored as raw data, ExifTool adds a TIFF header to allow the data to be +viewed as a TIFF image. If stored in PNG format, the PNG image is extracted +as-is. Note that most FLIR cameras using the PNG format seem to write the +16-bit raw image data in the wrong byte order. + + Index2 Tag Name Writable + ------ -------- -------- + 1 RawThermalImageWidth no + 2 RawThermalImageHeight no + 16 RawThermalImageType no + 16.1 RawThermalImage no + +=head3 FLIR GainDeadData Tags + +Information found in FFF-format .GAN calibration image files. + + Index2 Tag Name Writable + ------ -------- -------- + 1 GainDeadMapImageWidth no + 2 GainDeadMapImageHeight no + 16 GainDeadMapImageType no + 16.1 GainDeadMapImage no + +=head3 FLIR CoarseData Tags + +Information found in FFF-format .CRS correction image files. + + Index2 Tag Name Writable + ------ -------- -------- + 1 CoarseMapImageWidth no + 2 CoarseMapImageHeight no + 16 CoarseMapImageType no + 16.1 CoarseMapImage no + +=head3 FLIR EmbeddedImage Tags + + Index2 Tag Name Writable + ------ -------- -------- + 1 EmbeddedImageWidth no + 2 EmbeddedImageHeight no + 16 EmbeddedImageType no + 16.1 EmbeddedImage no + +=head3 FLIR CameraInfo Tags + +FLIR camera information. The Planck tags are variables used in the +temperature calculation. See +L<http://u88.n24.queensu.ca/exiftool/forum/index.php?topic=4898.msg23972#msg23972> +for details. + + Index1 Tag Name Writable + ------ -------- -------- + 32 Emissivity no + 36 ObjectDistance no + 40 ReflectedApparentTemperature no + 44 AtmosphericTemperature no + 48 IRWindowTemperature no + 52 IRWindowTransmission no + 60 RelativeHumidity no + 88 PlanckR1 no + 92 PlanckB no + 96 PlanckF no + 112 AtmosphericTransAlpha1 no + 116 AtmosphericTransAlpha2 no + 120 AtmosphericTransBeta1 no + 124 AtmosphericTransBeta2 no + 128 AtmosphericTransX no + 144 CameraTemperatureRangeMax no + 148 CameraTemperatureRangeMin no + 152 CameraTemperatureMaxClip no + 156 CameraTemperatureMinClip no + 160 CameraTemperatureMaxWarn no + 164 CameraTemperatureMinWarn no + 168 CameraTemperatureMaxSaturated no + 172 CameraTemperatureMinSaturated no + 212 CameraModel no + 244 CameraPartNumber no + 260 CameraSerialNumber no + 276 CameraSoftware no + 368 LensModel no + 400 LensPartNumber no + 416 LensSerialNumber no + 436 FieldOfView no + 492 FilterModel no + 508 FilterPartNumber no + 540 FilterSerialNumber no + 776 PlanckO no + 780 PlanckR2 no + 824 RawValueMedian no + 828 RawValueRange no + 900 DateTimeOriginal no + 912 FocusStepCount no + 1116 FocusDistance no + 1124 FrameRate no + +=head3 FLIR MeasInfo Tags + +Tags listed below are only for the first measurement tool, however multiple +measurements may be added, and information is extracted for all of them. +Tags for subsequent measurements are generated as required with the prefixes +"Meas2", "Meas3", etc. + + Tag Name Writable + -------- -------- + Meas1Label no + Meas1Params no + Meas1Type no + +=head3 FLIR PaletteInfo Tags + + Index1 Tag Name Writable + ------ -------- -------- + 0 PaletteColors no + 6 AboveColor no + 9 BelowColor no + 12 OverflowColor no + 15 UnderflowColor no + 18 Isotherm1Color no + 21 Isotherm2Color no + 26 PaletteMethod no + 27 PaletteStretch no + 48 PaletteFileName no + 80 PaletteName no + 112 Palette no + +=head3 FLIR TextInfo Tags + + Tag Name Writable + -------- -------- + Label0 no + Label1 no + Label2 no + Label3 no + Value0 no + Value1 no + Value2 no + Value3 no + +=head3 FLIR PaintData Tags + +Information generated by FLIR Tools "Paint colors" tool. + + Index2 Tag Name Writable + ------ -------- -------- + 5 PaintImageWidth no + 6 PaintImageHeight no + 20 PaintImageType no + 20.1 PaintImage no + +=head3 FLIR PiP Tags + +FLIR Picture in Picture tags. + + Index2 Tag Name Writable + ------ -------- -------- + 0 Real2IR no + 2 OffsetX no + 3 OffsetY no + 4 PiPX1 no + 5 PiPX2 no + 6 PiPY1 no + 7 PiPY2 no + +=head3 FLIR GPSInfo Tags + + Index1 Tag Name Writable + ------ -------- -------- + 0 GPSValid no + 4 GPSVersionID no + 8 GPSLatitudeRef no + 10 GPSLongitudeRef no + 16 GPSLatitude no + 24 GPSLongitude no + 32 GPSAltitude no + 64 GPSDOP no + 68 GPSSpeedRef no + 70 GPSTrackRef no + 76 GPSSpeed no + 80 GPSTrack no + 88 GPSMapDatum no + +=head3 FLIR MeterLink Tags + +Tags containing Meterlink humidity meter information. + + Index1 Tag Name Writable + ------ -------- -------- + 26 Reading1Units no + 28 Reading1Description no + 32 Reading1Device no + 96 Reading1Value no + 126 Reading2Units no + 128 Reading2Description no + 132 Reading2Device no + 196 Reading2Value no + 226 Reading3Units no + 228 Reading3Description no + 232 Reading3Device no + 296 Reading3Value no + 326 Reading4Units no + 328 Reading4Description no + 332 Reading4Device no + 396 Reading4Value no + +=head3 FLIR ParamInfo Tags + + Tag Name Writable + -------- -------- + DateTimeGenerated no + Param0 no + Param1 no + Param2 no + Param3 no + +=head3 FLIR UserData Tags + +Tags written by some FLIR cameras in a top-level (!) "udta" atom of MP4 +videos. + + Tag ID Tag Name Writable + ------ -------- -------- + 'uuid' FLIR_Parts FLIR Parts + FLIR_Serial FLIR SerialNums + FLIR_Params FLIR Params + FLIR_UnknownUUID FLIR UnknownUUID + FLIR_GPS FLIR GPS_UUID + FLIR_MoreInfo FLIR MoreInfo + SoftwareComponents? no + FLIR_Unknown? no + Units no+ + ThumbnailImage no + +=head3 FLIR Parts Tags + +Tags extracted from the "uuid" box with ID 43c3993b0f94424b82056b66513f485d +in FLIR MP4 videos. + + Index1 Tag Name Writable + ------ -------- -------- + 4 BAHPVer no + BALPVer no + Battery no + BAVPVer no + CamCore no + DetectorBoard no + Detector no + GIDCVer no + GIDPVer no + GIPC_CPLD no + GIPCVer no + GIXIVer no + MainBoard no + Optics no + PartNumber no + +=head3 FLIR SerialNums Tags + +Tags extracted from the "uuid" box with ID 57f5b93e51e448afa0d9c3ef1b37f712 +in FLIR MP4 videos. + + Index1 Tag Name Writable + ------ -------- -------- + 12 UnknownSerial1? no + 45 UnknownSerial2? no + 78 UnknownSerial3? no + 111 UnknownSerial4? no + 123 UnknownNumber? no + 126 CameraSerialNumber no + +=head3 FLIR Params Tags + +Tags extracted from the "uuid" box with ID 41e5dcf9e80a41ceadfe7f0c58082c19 +in FLIR MP4 videos. + + Index4 Tag Name Writable + ------ -------- -------- + 1 ReflectedApparentTemperature no + 2 AtmosphericTemperature no + 3 Emissivity no + 4 ObjectDistance no + 5 RelativeHumidity no + 6 EstimatedAtmosphericTrans no + 7 IRWindowTemperature no + 8 IRWindowTransmission no + +=head3 FLIR UnknownUUID Tags + +Tags extracted from the "uuid" box with ID 574520502cbb44adae5415e9b839d903 +in FLIR MP4 videos. + + Index4 Tag Name Writable + ------ -------- -------- + [no tags known] + +=head3 FLIR GPS_UUID Tags + +Tags extracted from the "uuid" box with ID 7f2e21008b464918afb1de709a74f6f5 +in FLIR MP4 videos. + + Index4 Tag Name Writable + ------ -------- -------- + 1 GPSLatitude no + 2 GPSLongitude no + 3 GPSAltitude no + +=head3 FLIR MoreInfo Tags + +Tags extracted from the "uuid" box with ID 2b452fdc74354094baee22a6b23a7cf8 +in FLIR MP4 videos. + + Index1 Tag Name Writable + ------ -------- -------- + 5 LensModel no + 11 UnknownTemperature1? no + 15 UnknownTemperature2? no + +=head3 FLIR AFF Tags + +Tags extracted from FLIR "AFF" SEQ images. + + Tag ID Tag Name Writable + ------ -------- -------- + '_header' AFFHeader FLIR Header + 0x0001 AFF1 FLIR AFF1 + 0x0005 AFF5 FLIR AFF5 + +=head3 FLIR AFF1 Tags + + Index2 Tag Name Writable + ------ -------- -------- + 1 SensorWidth no + 2 SensorHeight no + +=head3 FLIR AFF5 Tags + + Index2 Tag Name Writable + ------ -------- -------- + 19 SensorWidth no + 20 SensorHeight no + +=head3 FLIR FPF Tags + +Tags extracted from FLIR Public image Format (FPF) files. + + Index1 Tag Name Writable + ------ -------- -------- + 32 FPFVersion no + 36 ImageDataOffset no + 40 ImageType no + 42 ImagePixelFormat no + 44 ImageWidth no + 46 ImageHeight no + 48 ExternalTriggerCount no + 52 SequenceFrameNumber no + 120 CameraModel no + 152 CameraPartNumber no + 184 CameraSerialNumber no + 216 CameraTemperatureRangeMin no + 220 CameraTemperatureRangeMax no + 224 LensModel no + 256 LensPartNumber no + 288 LensSerialNumber no + 320 FilterModel no + 336 FilterPartNumber no + 384 FilterSerialNumber no + 480 Emissivity no + 484 ObjectDistance no + 488 ReflectedApparentTemperature no + 492 AtmosphericTemperature no + 496 RelativeHumidity no + 500 ComputedAtmosphericTrans no + 504 EstimatedAtmosphericTrans no + 508 ReferenceTemperature no + 512 IRWindowTemperature no + 516 IRWindowTransmission no + 584 DateTimeOriginal no + 676 CameraScaleMin no + 680 CameraScaleMax no + 684 CalculatedScaleMin no + 688 CalculatedScaleMax no + 692 ActualScaleMin no + 696 ActualScaleMax no + +=head2 FujiFilm Tags + + Tag ID Tag Name Writable + ------ -------- -------- + 0x0000 Version undef + 0x0010 InternalSerialNumber string + 0x1000 Quality string + 0x1001 Sharpness int16u + 0x1002 WhiteBalance int16u + 0x1003 Saturation int16u + 0x1004 Contrast int16u + 0x1005 ColorTemperature int16u + 0x1006 Contrast int16u + 0x100a WhiteBalanceFineTune int32s[2] + 0x100b NoiseReduction int16u + 0x100e NoiseReduction int16u + 0x1010 FujiFlashMode int16u + 0x1011 FlashExposureComp rational64s + 0x1020 Macro int16u + 0x1021 FocusMode int16u + 0x1022 AFMode int16u + 0x1023 FocusPixel int16u[2] + 0x102b PrioritySettings FujiFilm PrioritySettings + 0x102d FocusSettings FujiFilm FocusSettings + 0x102e AFCSettings FujiFilm AFCSettings + 0x1030 SlowSync int16u + 0x1031 PictureMode int16u + 0x1032 ExposureCount int16u + 0x1033 EXRAuto int16u + 0x1034 EXRMode int16u + 0x1040 ShadowTone int32s + 0x1041 HighlightTone int32s + 0x1044 DigitalZoom int32u + 0x1045 LensModulationOptimizer int32u + 0x1047 GrainEffect int32s + 0x1048 ColorChromeEffect int32s + 0x1049 BWAdjustment int8s + 0x104d CropMode int16u + 0x1050 ShutterType int16u + 0x1100 AutoBracketing int16u + 0x1101 SequenceNumber int16u + 0x1103 DriveSettings FujiFilm DriveSettings + 0x1153 PanoramaAngle int16u + 0x1154 PanoramaDirection int16u + 0x1201 AdvancedFilter int32u + 0x1210 ColorMode int16u + 0x1300 BlurWarning int16u + 0x1301 FocusWarning int16u + 0x1302 ExposureWarning int16u + 0x1304 GEImageSize string + 0x1400 DynamicRange int16u + 0x1401 FilmMode int16u + 0x1402 DynamicRangeSetting int16u + 0x1403 DevelopmentDynamicRange int16u + 0x1404 MinFocalLength rational64s + 0x1405 MaxFocalLength rational64s + 0x1406 MaxApertureAtMinFocal rational64s + 0x1407 MaxApertureAtMaxFocal rational64s + 0x140b AutoDynamicRange int16u + 0x1422 ImageStabilization int16u[3] + 0x1425 SceneRecognition int16u + 0x1431 Rating int32u + 0x1436 ImageGeneration int16u + 0x1438 ImageCount int16u + 0x1443 DRangePriority int16u + 0x1444 DRangePriorityAuto int16u + 0x1445 DRangePriorityFixed int16u + 0x1446 FlickerReduction int32u + 0x3820 FrameRate int16u + 0x3821 FrameWidth int16u + 0x3822 FrameHeight int16u + 0x4005 FaceElementSelected int16u[4] + 0x4100 FacesDetected int16u + 0x4103 FacePositions int16u[n] + 0x4200 NumFaceElements int16u + 0x4201 FaceElementTypes int8u[n] + 0x4203 FaceElementPositions int16u[n] + 0x4282 FaceRecInfo FujiFilm FaceRecInfo + 0x8000 FileSource string + 0x8002 OrderNumber int32u + 0x8003 FrameNumber int16u + 0xb211 Parallax rational64s + +=head3 FujiFilm PrioritySettings Tags + + Index2 Tag Name Writable + ------ -------- -------- + 0.1 AF-SPriority int16u & 0x0f + 0.2 AF-CPriority int16u & 0xf0 + +=head3 FujiFilm FocusSettings Tags + + Index4 Tag Name Writable + ------ -------- -------- + 0.1 FocusMode2 int32u & 0xff + 0.2 AFAreaMode int32u & 0xf00 + 0.3 AFAreaPointSize int32u & 0xf000 + 0.4 AFAreaZoneSize int32u & 0xf0000 + +=head3 FujiFilm AFCSettings Tags + + Index4 Tag Name Writable + ------ -------- -------- + 0 AF-CSetting int32u + 0.1 AF-CTrackingSensitivity int32u & 0x0f + 0.2 AF-CSpeedTrackingSensitivity int32u & 0xf0 + 0.3 AF-CZoneAreaSwitching int32u & 0xf00 + +=head3 FujiFilm DriveSettings Tags + + Index4 Tag Name Writable + ------ -------- -------- + 0.1 DriveMode int32u & 0xff + 0.2 DriveSpeed int32u & 0xff000000 + +=head3 FujiFilm FaceRecInfo Tags + +Face recognition information. + + Tag Name Writable + -------- -------- + Face1Birthday no + Face1Category no + Face1Name no + Face2Birthday no + Face2Category no + Face2Name no + Face3Birthday no + Face3Category no + Face3Name no + Face4Birthday no + Face4Category no + Face4Name no + Face5Birthday no + Face5Category no + Face5Name no + Face6Birthday no + Face6Category no + Face6Name no + Face7Birthday no + Face7Category no + Face7Name no + Face8Birthday no + Face8Category no + Face8Name no + +=head3 FujiFilm RAF Tags + +FujiFilm RAF images contain meta information stored in a proprietary +FujiFilm RAF format, as well as EXIF information stored inside an embedded +JPEG preview image. The table below lists tags currently decoded from the +RAF-format information. + + Tag ID Tag Name Writable + ------ -------- -------- + 0x0100 RawImageFullSize no + 0x0121 RawImageSize no + 0x0130 FujiLayout no + 0x0131 XTransLayout no + 0x2000 WB_GRGBLevelsAuto no + 0x2100 WB_GRGBLevelsDaylight no + 0x2200 WB_GRGBLevelsCloudy no + 0x2300 WB_GRGBLevelsDaylightFluor no + 0x2301 WB_GRGBLevelsDayWhiteFluor no + 0x2302 WB_GRGBLevelsWhiteFluorescent no + 0x2310 WB_GRGBLevelsWarmWhiteFluor no + 0x2311 WB_GRGBLevelsLivingRoomWarmWhiteFluor no + 0x2400 WB_GRGBLevelsTungsten no + 0x2ff0 WB_GRGBLevels no + 0x9200 RelativeExposure no + 0x9650 RawExposureBias no + 0xc000 RAFData FujiFilm RAFData + +=head3 FujiFilm RAFData Tags + + Index1 Tag Name Writable + ------ -------- -------- + 0 RawImageWidth no + 4 RawImageWidth no + RawImageHeight no + 8 RawImageWidth no + RawImageHeight no + 12 RawImageHeight no + +=head3 FujiFilm IFD Tags + +Tags found in the FujiIFD information of RAF images from some models. + + Tag ID Tag Name Writable + ------ -------- -------- + 0xf000 FujiIFD FujiFilm IFD + 0xf001 RawImageFullWidth no + 0xf002 RawImageFullHeight no + 0xf003 BitsPerSample no + 0xf007 StripOffsets no + 0xf008 StripByteCounts no + 0xf00a BlackLevel no + 0xf00b GeometricDistortionParams no + 0xf00c WB_GRBLevelsStandard no + 0xf00d WB_GRBLevelsAuto no + 0xf00e WB_GRBLevels no + 0xf00f ChromaticAberrationParams no + 0xf010 VignettingParams no + +=head3 FujiFilm FFMV Tags + +Information found in the FFMV atom of MOV videos. + + Index1 Tag Name Writable + ------ -------- -------- + 0 MovieStreamName no + +=head3 FujiFilm MOV Tags + +This information is found in MOV videos from some FujiFilm cameras. + + Index1 Tag Name Writable + ------ -------- -------- + 0 Make no + 24 Model no + 46 ExposureTime no + 50 FNumber no + 58 ExposureCompensation no + +=head2 GE Tags + +This table lists tags found in the maker notes of some General Imaging +camera models. + + Tag ID Tag Name Writable + ------ -------- -------- + 0x0202 Macro int16u + 0x0207 GEModel string + 0x0300 GEMake string + +=head2 HP Tags + +These tables list tags found in the maker notes of some Hewlett-Packard +camera models. + +The first table lists tags found in the EXIF-format maker notes of the +PhotoSmart 720 (also used by the Vivitar ViviCam 3705, 3705B and 3715). + + Tag ID Tag Name Writable + ------ -------- -------- + 0x0e00 PrintIM PrintIM + +=head3 HP Type2 Tags + +These tags are used by the PhotoSmart E427. + + Tag ID Tag Name Writable + ------ -------- -------- + 'Lens Shading' LensShading no + 'PreviewImage' PreviewImage no + 'Serial Number' SerialNumber no + +=head3 HP Type4 Tags + +These tags are used by the PhotoSmart M627. + + Index1 Tag Name Writable + ------ -------- -------- + 12 MaxAperture no + 16 ExposureTime no + 20 CameraDateTime no + 52 ISO no + 92 SerialNumber no + +=head3 HP Type6 Tags + +These tags are used by the PhotoSmart M425, M525 and M527. + + Index1 Tag Name Writable + ------ -------- -------- + 12 FNumber no + 16 ExposureTime no + 20 CameraDateTime no + 52 ISO no + 88 SerialNumber no + +=head3 HP TDHD Tags + +These tags are extracted from the APP6 "TDHD" segment of Photosmart R837 +JPEG images. Many other unknown tags exist in is data, and can be seen with +the Unknown (-u) option. + + Tag ID Tag Name Writable + ------ -------- -------- + 'CMSN' SerialNumber no + 'FWRV' FirmwareVersion no + 'LSLV' LSLV HP TDHD + 'TDHD' TDHD HP TDHD + +=head2 JVC Tags + +JVC EXIF maker note tags. + + Tag ID Tag Name Writable + ------ -------- -------- + 0x0002 CPUVersions no + 0x0003 Quality no + +=head3 JVC Text Tags + +JVC/Victor text-based maker note tags. + + Tag ID Tag Name Writable + ------ -------- -------- + 'QTY' Quality no + 'VER' MakerNoteVersion no + +=head2 Kodak Tags + +Many Kodak models don't store the maker notes in standard IFD format, and +these formats vary with different models. Some information has been +decoded, but much of the Kodak information remains unknown. + +The table below contains the most common set of Kodak tags. The following +Kodak camera models have been tested and found to use these tags: C360, +C663, C875, CX6330, CX6445, CX7330, CX7430, CX7525, CX7530, DC4800, DC4900, +DX3500, DX3600, DX3900, DX4330, DX4530, DX4900, DX6340, DX6440, DX6490, +DX7440, DX7590, DX7630, EasyShare-One, LS420, LS443, LS633, LS743, LS753, +V530, V550, V570, V603, V610, V705, Z650, Z700, Z710, Z730, Z740, Z760 and +Z7590. + + Index1 Tag Name Writable + ------ -------- -------- + 0 KodakModel string[8] + 9 Quality int8u + 10 BurstMode int8u + 12 KodakImageWidth int16u + 14 KodakImageHeight int16u + 16 YearCreated int16u + 18 MonthDayCreated int8u[2] + 20 TimeCreated int8u[4] + 24 BurstMode2? int16u + 27 ShutterMode int8u + 28 MeteringMode int8u + 29 SequenceNumber int8u + 30 FNumber int16u + 32 ExposureTime int32u + 36 ExposureCompensation int16s + 38 VariousModes? int16u + 40 Distance1? int32u + 44 Distance2? int32u + 48 Distance3? int32u + 52 Distance4? int32u + 56 FocusMode int8u + 58 VariousModes2? int16u + 60 PanoramaMode? int16u + 62 SubjectDistance? int16u + 64 WhiteBalance int8u + 92 FlashMode int8u + 93 FlashFired int8u + 94 ISOSetting int16u + 96 ISO int16u + 98 TotalZoom int16u + 100 DateTimeStamp int16u + 102 ColorMode int16u + 104 DigitalZoom int16u + 107 Sharpness int8s + +=head3 Kodak IFD Tags + +These tags are found in a separate IFD of JPEG, TIFF, DCR and KDC images +from some older Kodak models such as the DC50, DC120, DCS760C, DCS Pro 14N, +14nx, SLR/n, Pro Back and Canon EOS D2000. + + Tag ID Tag Name Writable + ------ -------- -------- + 0x0000 KodakVersion int8u[4] + 0x0001 UnknownEV? rational64u + 0x0003 ExposureValue rational64u + 0x03e9 OriginalFileName string + 0x03ea KodakTag int32u + 0x03eb SensorLeftBorder int16u + 0x03ec SensorTopBorder int16u + 0x03ed SensorImageWidth int16u + 0x03ee SensorImageHeight int16u + 0x03ef BlackLevelTop int16u + 0x03f0 BlackLevelBottom int16u + 0x03f1 TextualInfo Kodak TextualInfo + 0x03f2 FlashMode? int16u + 0x03f3 FlashCompensation rational64s + 0x03f4 WindMode? int16u + 0x03f5 FocusMode? int16u + 0x03f8 MinAperture rational64u + 0x03f9 MaxAperture rational64u + 0x03fa WhiteBalanceMode? int16u + 0x03fb WhiteBalanceDetected? int16u + 0x03fc WhiteBalance int16u + 0x03fd Processing Kodak Processing + ProcessingParameters no + 0x03fe ImageAbsoluteX int16s + 0x03ff ImageAbsoluteY int16s + 0x0400 ApplicationKeyString string + 0x0401 Time string + 0x0402 GPSString string + 0x0403 EventLogCapture? no + 0x0404 ComponentTable? no + 0x0405 CustomIlluminant? int16u + 0x0406 CameraTemperature rational64s + CameraTemperature no + 0x0407 AdapterVoltage rational64u + 0x0408 BatteryVoltage rational64u + 0x0409 DacVoltages no + 0x040a IlluminantDetectorData? no + 0x040b PixelClockFrequency int32u + 0x040c CenterPixel int16u[3] + 0x040d BurstCount int16u + 0x040e BlackLevelRough int16u + 0x040f OffsetMapHorizontal? no + 0x0410 OffsetMapVertical? no + 0x0411 Histogram? no + 0x0412 VerticalClockOverlaps int16u[2] + 0x0413 SensorTemperature no + 0x0414 XilinxVersion string + 0x0415 FirmwareVersion int32u + 0x0416 BlackLevelRoughAfter int16u + 0x0417 BrightRowsTop no + 0x0418 EventLogProcess no + 0x0419 DacVoltagesFlush no + 0x041a FlashUsed no + 0x041b FlashType no + 0x041c SelfTimer no + 0x041d AFMode no + 0x041e LensType no + 0x041f ImageCropX int16s + 0x0420 ImageCropY int16s + 0x0421 AdjustedTbnImageWidth no + 0x0422 AdjustedTbnImageHeight no + 0x0423 IntegrationTime int32u + 0x0424 BracketingMode no + 0x0425 BracketingStep no + 0x0426 BracketingCounter no + 0x042e HuffmanTableLength no + 0x042f HuffmanTableValue no + 0x0438 MainBoardVersion int32u + 0x0439 ImagerBoardVersion int32u + 0x044c FocusEdgeMap no + 0x05e6 IdleTiming no + 0x05e7 FlushTiming no + 0x05e8 IntegrateTiming no + 0x05e9 RegisterReadTiming no + 0x05ea FirstLineTransferTiming no + 0x05eb ShiftTiming no + 0x05ec NormalLineTransferTiming no + 0x05ed TestTransferTiming no + 0x05fa MinimumFlushRows no + 0x05fd ImagerPowerOnDelayMsec int32u + 0x05fe ImagerInitialTimingCode no + 0x05ff ImagerLogicProgram no + 0x0600 ImagerBiasSettlingDelayMsec int32u + 0x0604 IdleSequence no + 0x0605 FirstFlushSequence no + 0x0606 FinalFlushSequence no + 0x0607 SampleBlackSequence no + 0x0608 TransferSequence no + 0x060e DacCountsPerVolt no + 0x060f BlackDacChannel no + 0x0610 BlackAdCountsPerDacVolt no + 0x0611 BlackTarget no + 0x0612 BlackDacSettlingMsec no + 0x07d0 StandardMatrixDaylight rational64s[9] + 0x07d1 StandardMatrixTungsten rational64s[9] + 0x07d2 StandardMatrixFluorescent rational64s[9] + 0x07d3 StandardMatrixFlash rational64s[9] + 0x07d4 StandardMatrixCustom rational64s[9] + 0x07da DeviantMatrixDaylight rational64s[9] + 0x07db DeviantMatrixTungsten rational64s[9] + 0x07dc DeviantMatrixFluorescent rational64s[9] + 0x07dd DeviantMatrixFlash rational64s[9] + 0x07de DeviantMatrixCustom rational64s[9] + 0x07e4 UniqueMatrixDaylight rational64s[9] + 0x07e5 UniqueMatrixTungsten rational64s[9] + 0x07e6 UniqueMatrixFluorescent rational64s[9] + 0x07e7 UniqueMatrixFlash rational64s[9] + 0x07e8 UniqueMatrixCustom rational64s[9] + 0x07e9 UniqueMatrixAuto rational64s[9] + 0x0834 StandardWhiteDaylight rational64s[3] + 0x0835 StandardWhiteTungsten rational64s[3] + 0x0836 StandardWhiteFluorescent rational64s[3] + 0x0837 StandardWhiteFlash rational64s[3] + 0x0838 StandardWhiteCustom rational64s[3] + 0x083e DeviantWhiteDaylight rational64s[3] + 0x083f DeviantWhiteTungsten rational64s[3] + 0x0840 DeviantWhiteFluorescent rational64s[3] + 0x0841 DeviantWhiteFlash rational64s[3] + 0x0842 DeviantWhiteCustom rational64s[3] + 0x0846 ColorTemperature int16u + 0x0847 WB_RGBLevelsAsShot no + 0x0848 WB_RGBLevelsDaylight no + 0x0849 WB_RGBLevelsTungsten no + 0x084a WB_RGBLevelsFluorescent no + 0x084b WB_RGBLevelsFlash no + 0x084c WB_RGBLevelsCustom no + 0x084d WB_RGBLevelsAuto no + 0x0852 WB_RGBMulDaylight rational64u[3] + 0x0853 WB_RGBMulTungsten rational64u[3] + 0x0854 WB_RGBMulFluorescent rational64u[3] + 0x0855 WB_RGBMulFlash rational64u[3] + 0x085c WB_RGBCoeffsDaylight no + 0x085d WB_RGBCoeffsTungsten no + 0x085e WB_RGBCoeffsFluorescent no + 0x085f WB_RGBCoeffsFlash no + 0x0898 ExposureGainDaylight rational64s + 0x0899 ExposureGainTungsten rational64s + 0x089a ExposureGainFluorescent rational64s + 0x089b ExposureGainFlash rational64s + 0x089c ExposureGainCustom rational64s + 0x089d AnalogISOTable rational64u[3] + 0x089e AnalogCaptureISO int32u + 0x089f ISOCalibrationGain rational64u + 0x08a0 ISOCalibrationGainTable no + 0x08a1 ExposureHeadroomFactor no + 0x08ab LinearitySplineTags no + 0x08fc MonitorMatrix rational64s[9] + 0x08fd TonScaleTable no + 0x08fe Gamma rational64u + 0x08ff LogLinTable no + 0x0900 LinLogTable no + 0x0901 GammaTable no + 0x0902 LogScale rational64u + 0x0903 BaseISO rational64u + 0x0904 LinLogCoring int16u + 0x0905 PatternGainConversionTable no + 0x0906 DefectCount no + 0x0907 DefectList no + 0x0908 DefectListPacked no + 0x0909 ImageSpace int16u + 0x090a ThumbnailCompressionTable no + 0x090b ThumbnailExpansionTable no + 0x090c ImageCompressionTable no + 0x090d ImageExpansionTable no + 0x090e EighteenPercentPoint no + 0x090f DefectIsoCode int16u + 0x0910 BaseISODaylight rational64u + 0x0911 BaseISOTungsten rational64u + 0x0912 BaseISOFluorescent rational64u + 0x0913 BaseISOFlash rational64u + 0x091a MatrixSelectThreshold int16s + 0x091b MatrixSelectK rational64u + 0x091c IlluminantDetectTable no + 0x091d RGTable no + 0x091e MatrixSelectThreshold1 int16s + 0x091f MatrixSelectThreshold2 int16s + 0x0924 PortraitMatrix no + 0x0925 PortraitToneScaleTable no + 0x092e EnableSharpening int16u + 0x092f SharpeningKernel int16s[25] + 0x0930 EdgeMapSlope int16u + 0x0931 EdgeMapX1 int16u + 0x0932 EdgeMapX2 int16u + 0x0933 KernelDenominators int16u[3] + 0x0934 EdgeMapX3 int16u + 0x0935 EdgeMapX4 int16u + 0x0936 SharpenForThumbnail no + 0x0937 EdgeSpline no + 0x0938 DownSampleBy2Hor no + 0x0939 DownSampleBy2Ver no + 0x093a DownSampleBy4Hor no + 0x093b DownSampleBy4Ver no + 0x093c DownSampleBy3Hor no + 0x093d DownSampleBy3Ver no + 0x093e DownSampleBy6Hor no + 0x093f DownSampleBy6Ver no + 0x0940 DownSampleBy2Hor3MPdcr no + 0x0941 DownSampleBy2Ver3MPdcr no + 0x0942 ThumbnailResizeRatio no + 0x0943 AtCaptureUserCrop int32u[4] + 0x0944 ImageResolution int32u + 0x0945 ImageResolutionJpg int32u + 0x094c USMParametersLow no + 0x094d USMParametersMed no + 0x094e USMParametersHigh no + 0x094f USMParametersHost no + 0x0950 EdgeSplineLow no + 0x0951 EdgeSplineMed no + 0x0952 EdgeSplineHigh no + 0x0953 USMParametersHost6MP no + 0x0954 USMParametersHost3MP no + 0x0960 PatternImagerWidth int16u + 0x0961 PatternImagerHeight int16u + 0x0962 PatternAreaWidth int16u + 0x0963 PatternAreaHeight int16u + 0x0964 PatternCorrectionGains no + 0x0965 PatternCorrectionOffsets no + 0x0966 PatternX int16u + 0x0967 PatternY int16u + 0x0968 PatternCorrectionFactors no + 0x0969 PatternCorrectionFactorScale int16u + 0x096a PatternCropRows1 int16u + 0x096b PatternCropRows2 int16u + 0x096c PatternCropCols1 int16u + 0x096d PatternCropCols2 int16u + 0x096e PixelCorrectionGains no + 0x096f StitchRows no + 0x0970 StitchColumns no + 0x0971 PixelCorrectionScale int16u + 0x0972 PixelCorrectionOffset int16u + 0x0988 LensTableIndex no + 0x0992 DiffTileGains602832 no + 0x0993 DiffTileGains24t852822 no + 0x099c TileGainDeterminationTable no + 0x099d NemoBlurKernel no + 0x099e NemoTileSize no + 0x099f NemoGainFactors no + 0x09a0 NemoDarkLimit no + 0x09a1 NemoHighlight12Limit no + 0x09c4 ImagerFileProductionLevel int16u + 0x09c5 ImagerFileDateCreated int32u + 0x09c6 CalibrationVersion string + 0x09c7 ImagerFileTagsVersionStandard int16u + 0x09c8 IFCameraModel string + 0x09c9 CalibrationHistory string + 0x09ca CalibrationLog no + 0x09ce SensorSerialNumber string + 0x09f6 DefectConcealArtCorrectThres no + 0x09f7 SglColDCACThres1 no + 0x09f8 SglColDCACThres2 no + 0x09f9 SglColDCACTHres3 no + 0x0a01 DblColDCACThres1 no + 0x0a02 DblColDCACThres2 no + 0x0a0a DefectConcealThresTable no + 0x0a28 MonoUniqueMatrix no + 0x0a29 MonoMonitorMatrix no + 0x0a2a MonoToneScaleTable no + 0x0a5a OmenInitialScaling no + 0x0a5b OmenInitialRows no + 0x0a5c OmenInitialColumns no + 0x0a5d OmenInitialIPFStrength int32s[4] + 0x0a5e OmenEarlyStrength int32s[4] + 0x0a5f OmenAutoStrength int32s[4] + 0x0a60 OmenAtCaptureStrength int32s[4] + 0x0a61 OmenAtCaptureMode no + 0x0a62 OmenFocalLengthLimit int16s + 0x0a64 OmenSurfaceIndex int16s + 0x0a65 OmenPercentToRationalLimitsRed no + 0x0a66 OmenPercentToRationalLimitsGoR no + 0x0a67 OmenPercentToRationalLimitsBlue no + 0x0a68 OmenPercentToRationalLimitsGoB no + 0x0a6e OmenEarlyGoBSurface no + 0x0a6f OmenEarlyGoBRows no + 0x0a70 OmenEarlyGoBColumns no + 0x0a73 OmenSmoothingKernel no + 0x0a74 OmenGradientOffset no + 0x0a75 OmenGradientKernel no + 0x0a76 OmenGradientKernelTaps no + 0x0a77 OmenRatioClipFactors no + 0x0a78 OmenRatioExclusionFactors no + 0x0a79 OmenGradientExclusionLimits no + 0x0a7a OmenROICoordinates no + 0x0a7b OmenROICoefficients no + 0x0a7c OmenRangeWeighting no + 0x0a7d OmenMeanToStrength no + 0x0bb8 FactoryWhiteGainsDaylight no + 0x0bb9 FactoryWhiteOffsetsDaylight no + 0x0bba DacGainsCoarse no + 0x0bbb DacGainsFine no + 0x0bbc DigitalExposureGains no + 0x0bbd DigitalExposureBiases no + 0x0bbe BlackClamp no + 0x0bbf ChannelCoarseGainAdjust no + 0x0bc0 BlackClampOffset no + 0x0bf4 DMPixelThresholdFactor no + 0x0bf5 DMWindowThresholdFactor no + 0x0bf6 DMTrimFraction no + 0x0bf7 DMSmoothRejThresh no + 0x0bf8 DMFillRejThresh no + 0x0bf9 VMWsize no + 0x0bfa DMErodeRadius no + 0x0bfb DMNumPatches no + 0x0bfc DMNoiseScale no + 0x0bfe BrightDefectThreshold no + 0x0bff BrightDefectIntegrationMS no + 0x0c00 BrightDefectIsoCode no + 0x0c03 TopDarkRow1 no + 0x0c04 TopDarkRow2 no + 0x0c05 BottomDarkRow1 no + 0x0c06 BottomDarkRow2 no + 0x0c07 LeftDarkCol1 no + 0x0c08 LeftDarkCol2 no + 0x0c09 RightDarkCol1 no + 0x0c0a RightDarkCol2 no + 0x0c0b HMPixThresh no + 0x0c0c HMColThresh no + 0x0c0d HMWsize no + 0x0c0e HMColRejThresh no + 0x0c0f VMPixThresh no + 0x0c10 VMColThresh no + 0x0c11 VMNbands no + 0x0c12 VMColDropThresh no + 0x0c13 VMPatchResLimit no + 0x0c14 MapScale no + 0x0c1c Klut no + 0x0c1d RimNonlinearity no + 0x0c1e InverseRimNonlinearity no + 0x0c1f RembrandtToneScale no + 0x0c20 RimToNifColorTransform no + 0x0c21 RimToNifScaleFactor no + 0x0c22 NifNonlinearity no + 0x0c23 SBALogTransform no + 0x0c24 InverseSBALogTransform no + 0x0c25 SBABlack int16u + 0x0c26 SBAGray int16u + 0x0c27 SBAWhite int16u + 0x0c28 GaussianWeights no + 0x0c29 SfsBoundary no + 0x0c2a CoringTableBest no + 0x0c2b CoringTableBetter no + 0x0c2c CoringTableGood no + 0x0c2d ExposureReferenceGain no + 0x0c2e ExposureReferenceOffset no + 0x0c2f SBARedBalanceLut no + 0x0c30 SBAGreenBalanceLut no + 0x0c31 SBABlueBalanceLut no + 0x0c32 SBANeutralBAL int32s + 0x0c33 SBAGreenMagentaBAL int32s + 0x0c34 SBAIlluminantBAL int32s + 0x0c35 SBAAnalysisComplete int8u + 0x0c36 JPEGQTableBest no + 0x0c37 JPEGQTableBetter no + 0x0c38 JPEGQTableGood no + 0x0c39 RembrandtPortraitToneScale no + 0x0c3a RembrandtConsumerToneScale no + 0x0c3b CFAGreenThreshold1 no + 0x0c3c CFAGreenThreshold2 no + 0x0c3d QTableLarge50Pct no + 0x0c3e QTableLarge67Pct no + 0x0c3f QTableLarge100Pct no + 0x0c40 QTableMedium50Pct no + 0x0c41 QTableMedium67Pct no + 0x0c42 QTableMedium100Pct no + 0x0c43 QTableSmall50Pct no + 0x0c44 QTableSmall67Pct no + 0x0c45 QTableSmall100Pct no + 0x0c46 SBAHighGray int16u + 0x0c47 SBALowGray int16u + 0x0c48 CaptureLook int16u + 0x0c49 SBAIllOffset int16s + 0x0c4a SBAGmOffset int16s + 0x0c4b NifNonlinearity12Bit no + 0x0c4c SharpeningOn no + 0x0c4d NifNonlinearity16Bit no + 0x0c4e RawHistogram no + 0x0c4f RawCFAComponentAverages no + 0x0c50 DisableFlagsPresent no + 0x0c51 DelayCols no + 0x0c52 DummyColsLeft no + 0x0c53 TrashColsRight no + 0x0c54 BlackColsRight no + 0x0c55 DummyColsRight no + 0x0c56 OverClockColsRight no + 0x0c57 UnusedBlackRowsTopOut no + 0x0c58 TrashRowsBottom no + 0x0c59 BlackRowsBottom no + 0x0c5a OverClockRowsBottom no + 0x0c5b BlackColsLeft no + 0x0c5c BlackRowsTop no + 0x0c5d PartialActiveColsLeft no + 0x0c5e PartialActiveColsRight no + 0x0c5f PartialActiveRowsTop no + 0x0c60 PartialActiveRowsBottom no + 0x0c61 ProcessBorderColsLeft int16u + 0x0c62 ProcessBorderColsRight int16u + 0x0c63 ProcessBorderRowsTop int16u + 0x0c64 ProcessBorderRowsBottom int16u + 0x0c65 ActiveCols no + 0x0c66 ActiveRows no + 0x0c67 FirstLines no + 0x0c68 UnusedBlackRowsTopIn no + 0x0c69 UnusedBlackRowsBottomIn no + 0x0c6a UnusedBlackRowsBottomOut no + 0x0c6b UnusedBlackColsLeftOut no + 0x0c6c UnusedBlackColsLeftIn no + 0x0c6d UnusedBlackColsRightIn no + 0x0c6e UnusedBlackColsRightOut no + 0x0c6f CFAOffsetRows int32u + 0x0c70 ShiftCols int16s + 0x0c71 CFAOffsetCols int32u + 0x0c76 DarkMapScale no + 0x0c77 HMapHandling no + 0x0c78 VMapHandling no + 0x0c79 DarkThreshold no + 0x0c7a DMDitherMatrix int16u + 0x0c7b DMDitherMatrixWidth int16u + 0x0c7c DMDitherMatrixHeight int16u + 0x0c7d MaxPixelValueThreshold int16u + 0x0c7e HoleFillDeltaThreshold int16u + 0x0c7f DarkPedestal int16u + 0x0c80 ImageProcessingFileTagsVersionNumber int16u + 0x0c81 ImageProcessingFileDateCreated string + 0x0c82 DoublingMicrovolts int32s + 0x0c83 DarkFrameShortExposure int32u + 0x0c84 DarkFrameLongExposure int32u + 0x0c85 DarkFrameCountFactor rational64u + 0x0c88 HoleFillDarkDeltaThreshold int16u + 0x0c89 FarkleWhiteThreshold no + 0x0c8a ColumnResetOffsets no + 0x0c8b ColumnGainFactors no + 0x0c8c Channel0LagKernel no + 0x0c8d Channel1LagKernel no + 0x0c8e Channel2LagKernel no + 0x0c8f Channel3LagKernel no + 0x0c90 BluegrassTable no + 0x0c91 BluegrassScale1 no + 0x0c92 BluegrassScale2 no + 0x0ce4 FinishedFileProcessingRequest no + 0x0ce5 FirmwareVersion string + 0x0ce6 HostSoftwareExportVersion no + 0x0ce7 HostSoftwareRendering int32u + 0x0dac DCS3XXProcessingInfoIFD no + 0x0dad DCS3XXProcessingInfo no + 0x0dae IPAVersion int32u + 0x0db6 FinishIPAVersion no + 0x0db7 FinishIPFVersion no + 0x0db8 FinishFileType int32u + 0x0db9 FinishResolution int32u + 0x0dba FinishNoise int32u + 0x0dbb FinishSharpening int32u + 0x0dbc FinishLook int32u + 0x0dbd FinishExposure int32u + 0x0e0b SigmaScalingFactorLowRes rational64u + 0x0e0c SigmaScalingFactorCamera rational64u + 0x0e0d SigmaImpulseParameters int16u[n] + 0x0e0e SigmaNoiseThreshTableV2 no + 0x0e0f SigmaSizeTable int16u[n] + 0x0e10 DacGainsCoarseAdjPreIF41 no + 0x0e11 SigmaNoiseFilterCalTableV1 no + 0x0e12 SigmaNoiseFilterTableV1 no + 0x0e13 Lin12ToKlut8 no + 0x0e14 SigmaNoiseFilterTableV1Version no + 0x0e15 Lin12ToKlut12 no + 0x0e16 Klut12ToLin12 no + 0x0e17 NifNonlinearity12To16 no + 0x0e18 SBALog12Transform no + 0x0e19 InverseSBALog12Transform no + 0x0e1a ToneScale0 no + 0x0e1b ToneScale1 no + 0x0e1c ToneScale2 no + 0x0e1d ToneScale3 no + 0x0e1e ToneScale4 no + 0x0e1f ToneScale5 no + 0x0e20 ToneScale6 no + 0x0e21 ToneScale7 no + 0x0e22 ToneScale8 no + 0x0e23 ToneScale9 no + 0x0e24 DayMat0 no + 0x0e25 DayMat1 no + 0x0e26 DayMat2 no + 0x0e27 DayMat3 no + 0x0e28 DayMat4 no + 0x0e29 DayMat5 no + 0x0e2a DayMat6 no + 0x0e2b DayMat7 no + 0x0e2c DayMat8 no + 0x0e2d DayMat9 no + 0x0e2e TungMat0 no + 0x0e2f TungMat1 no + 0x0e30 TungMat2 no + 0x0e31 TungMat3 no + 0x0e32 TungMat4 no + 0x0e33 TungMat5 no + 0x0e34 TungMat6 no + 0x0e35 TungMat7 no + 0x0e36 TungMat8 no + 0x0e37 TungMat9 no + 0x0e38 FluorMat0 no + 0x0e39 FluorMat1 no + 0x0e3a FluorMat2 no + 0x0e3b FluorMat3 no + 0x0e3c FluorMat4 no + 0x0e3d FluorMat5 no + 0x0e3e FluorMat6 no + 0x0e3f FluorMat7 no + 0x0e40 FluorMat8 no + 0x0e41 FluorMat9 no + 0x0e42 FlashMat0 no + 0x0e43 FlashMat1 no + 0x0e44 FlashMat2 no + 0x0e45 FlashMat3 no + 0x0e46 FlashMat4 no + 0x0e47 FlashMat5 no + 0x0e48 FlashMat6 no + 0x0e49 FlashMat7 no + 0x0e4a FlashMat8 no + 0x0e4b FlashMat9 no + 0x0e4c KodakLook string + 0x0e4d IPFCameraModel string + 0x0e4e AH2GreenInterpolationThreshold int16u + 0x0e4f ResamplingKernelDenominators067 int16u[3] + 0x0e50 ResamplingKernelDenominators050 int16u[3] + 0x0e51 ResamplingKernelDenominators100 int16u[3] + 0x0e56 LookMat0 no + 0x0e57 LookMat1 no + 0x0e58 LookMat2 no + 0x0e59 LookMat3 no + 0x0e5a LookMat4 no + 0x0e5b LookMat5 no + 0x0e5c LookMat6 no + 0x0e5d LookMat7 no + 0x0e5e LookMat8 no + 0x0e5f LookMat9 no + 0x0e60 CFAInterpolationAlgorithm int16u + 0x0e61 CFAInterpolationMetric int16u + 0x0e62 CFAZipperFixThreshold int16u + 0x0e63 NoiseReductionParametersKhufuRGB int16u[9] + 0x0e64 NoiseReductionParametersKhufu6MP int16u[9] + 0x0e65 NoiseReductionParametersKhufu3MP int16u[9] + 0x0e6a ChromaNoiseHighFThresh int32u[2] + 0x0e6b ChromaNoiseLowFThresh int32u[2] + 0x0e6c ChromaNoiseEdgeMapThresh int32u + 0x0e6d ChromaNoiseColorSpace int32u + 0x0e6e EnableChromaNoiseReduction int16u + 0x0e6f NoiseReductionParametersHostRGB int16u[9] + 0x0e70 NoiseReductionParametersHost6MP int16u[9] + 0x0e71 NoiseReductionParametersHost3MP int16u[9] + 0x0e72 NoiseReductionParametersCamera int16u[6] + 0x0e73 NoiseReductionParametersAtCapture int16u[6] + 0x0e74 LCDMatrix rational64s[9] + 0x0e75 LCDMatrixChickFix rational64s[9] + 0x0e76 LCDMatrixMarvin rational64s[9] + 0x0e7c LCDGammaTableChickFix no + 0x0e7d LCDGammaTableMarvin no + 0x0e7e LCDGammaTable no + 0x0e7f LCDSharpeningF1 no + 0x0e80 LCDSharpeningF2 no + 0x0e81 LCDSharpeningF3 no + 0x0e82 LCDSharpeningF4 no + 0x0e83 LCDEdgeMapX1 no + 0x0e84 LCDEdgeMapX2 no + 0x0e85 LCDEdgeMapX3 no + 0x0e86 LCDEdgeMapX4 no + 0x0e87 LCDEdgeMapSlope no + 0x0e88 YCrCbMatrix no + 0x0e89 LCDEdgeSpline no + 0x0e92 Fac18Per int16u + 0x0e93 Fac170Per int16u + 0x0e94 Fac100Per int16u + 0x0e9b ExtraTickLocations no + 0x0e9c RGBtoeV0 no + 0x0e9d RGBtoeV1 no + 0x0e9e RGBtoeV2 no + 0x0e9f RGBtoeV3 no + 0x0ea0 RGBtoeV4 no + 0x0ea1 RGBtoeV5 no + 0x0ea2 RGBtoeV6 no + 0x0ea3 RGBtoeV7 no + 0x0ea4 RGBtoeV8 no + 0x0ea5 RGBtoeV9 no + 0x0ea6 LCDHistLUT0 no + 0x0ea7 LCDHistLUT1 no + 0x0ea8 LCDHistLUT2 no + 0x0ea9 LCDHistLUT3 no + 0x0eaa LCDHistLUT4 no + 0x0eab LCDHistLUT5 no + 0x0eac LCDHistLUT6 no + 0x0ead LCDHistLUT7 no + 0x0eae LCDHistLUT8 no + 0x0eaf LCDHistLUT9 no + 0x0eb0 LCDLinearClipValue no + 0x0ece LCDStepYvalues no + 0x0ecf LCDStepYvaluesChickFix no + 0x0ed0 LCDStepYvaluesMarvin no + 0x0ed8 InterpolationCoefficients no + 0x0ed9 InterpolationCoefficients6MP no + 0x0eda InterpolationCoefficients3MP no + 0x0f00 NoiseReductionParametersHostNormal no + 0x0f01 NoiseReductionParametersHostStrong no + 0x0f02 NoiseReductionParametersHostLow no + 0x0f0a MariahTextureThreshold int16u + 0x0f0b MariahMapLoThreshold int16u + 0x0f0c MariahMapHiThreshold int16u + 0x0f0d MariahChromaBlurSize int16u + 0x0f0e MariahSigmaThreshold int16u + 0x0f0f MariahThresholds no + 0x0f10 MariahThresholdsNormal no + 0x0f11 MariahThresholdsStrong no + 0x0f12 MariahThresholdsLow no + 0x0f14 KhufuLinearRedMixingCoefficient no + 0x0f15 KhufuLinearGreenMixingCoefficient no + 0x0f16 KhufuLinearBlueMixingCoefficient no + 0x0f17 KhufuUSpaceC2MixingCoefficient no + 0x0f18 KhufuSigmaGaussianWeights no + 0x0f19 KhufuSigmaScalingFactors6MP no + 0x0f1a KhufuSigmaScalingFactors3MP no + 0x0f1b KhufuSigmaScalingFactors14MP no + 0x0f32 KhufuI0Thresholds no + 0x0f33 KhufuI1Thresholds no + 0x0f34 KhufuI2Thresholds no + 0x0f35 KhufuI3Thresholds no + 0x0f36 KhufuI4Thresholds no + 0x0f37 KhufuI5Thresholds no + 0x0f3c CondadoDayBVThresh int16u + 0x0f3d CondadoNeuRange int16u + 0x0f3e CondadoBVFactor int16s + 0x0f3f CondadoIllFactor int16s + 0x0f40 CondadoTunThresh int16s + 0x0f41 CondadoFluThresh int16s + 0x0f42 CondadoDayOffsets int16s[2] + 0x0f43 CondadoTunOffsets int16s[2] + 0x0f44 CondadoFluOffsets int16s[2] + 0x0f5a ERIMMToCRGB0Spline no + 0x0f5b ERIMMToCRGB1Spline no + 0x0f5c ERIMMToCRGB2Spline no + 0x0f5d ERIMMToCRGB3Spline no + 0x0f5e ERIMMToCRGB4Spline no + 0x0f5f ERIMMToCRGB5Spline no + 0x0f60 ERIMMToCRGB6Spline no + 0x0f61 ERIMMToCRGB7Spline no + 0x0f62 ERIMMToCRGB8Spline no + 0x0f63 ERIMMToCRGB9Spline no + 0x0f64 CRGBToERIMM0Spline no + 0x0f65 CRGBToERIMM1Spline no + 0x0f66 CRGBToERIMM2Spline no + 0x0f67 CRGBToERIMM3Spline no + 0x0f68 CRGBToERIMM4Spline no + 0x0f69 CRGBToERIMM5Spline no + 0x0f6a CRGBToERIMM6Spline no + 0x0f6b CRGBToERIMM7Spline no + 0x0f6c CRGBToERIMM8Spline no + 0x0f6d CRGBToERIMM9Spline no + 0x0f6e ERIMMNonLinearitySpline no + 0x0f6f Delta12To8Spline no + 0x0f70 Delta8To12Spline no + 0x0f71 InverseMonitorMatrix no + 0x0f72 NifNonlinearityExt no + 0x0f73 InvNifNonLinearity no + 0x0f74 RIMM13ToERIMM12Spline no + 0x0f78 ToneScale0Spline no + 0x0f79 ToneScale1Spline no + 0x0f7a ToneScale2Spline no + 0x0f7b ToneScale3Spline no + 0x0f7c ToneScale4Spline no + 0x0f7d ToneScale5Spline no + 0x0f7e ToneScale6Spline no + 0x0f7f ToneScale7Spline no + 0x0f80 ToneScale8Spline no + 0x0f81 ToneScale9Spline no + 0x0f82 ERIMMToneScale0Spline no + 0x0f83 ERIMMToneScale1Spline no + 0x0f84 ERIMMToneScale2Spline no + 0x0f85 ERIMMToneScale3Spline no + 0x0f86 ERIMMToneScale4Spline no + 0x0f87 ERIMMToneScale5Spline no + 0x0f88 ERIMMToneScale6Spline no + 0x0f89 ERIMMToneScale7Spline no + 0x0f8a ERIMMToneScale8Spline no + 0x0f8b ERIMMToneScale9Spline no + 0x0f8c RIMMToCRGB0Spline no + 0x0f8d RIMMToCRGB1Spline no + 0x0f8e RIMMToCRGB2Spline no + 0x0f8f RIMMToCRGB3Spline no + 0x0f90 RIMMToCRGB4Spline no + 0x0f91 RIMMToCRGB5Spline no + 0x0f92 RIMMToCRGB6Spline no + 0x0f93 RIMMToCRGB7Spline no + 0x0f94 RIMMToCRGB8Spline no + 0x0f95 RIMMToCRGB9Spline no + 0x0fa0 QTableLarge25Pct no + 0x0fa1 QTableMedium25Pct no + 0x0fa2 QTableSmall25Pct no + 0x1130 NoiseReductionKernel no + 0x1388 UserMetaData no + 0x1389 InputProfile undef + 0x138a KodakLookProfile undef + 0x138b OutputProfile undef + 0x1390 SourceProfilePrefix string + 0x1391 ToneCurveProfileName string + 0x1392 InputProfile ICC_Profile + 0x1393 ProcessParametersV2 no + 0x1394 ReservedBlob2 no + 0x1395 ReservedBlob3 no + 0x1396 ReservedBlob4 no + 0x1397 ReservedBlob5 no + 0x1398 ReservedBlob6 no + 0x1399 ReservedBlob7 no + 0x139a ReservedBlob8 no + 0x139b ReservedBlob9 no + 0x1770 ScriptVersion int32u + 0x177a ImagerTimingData no + 0x1784 ISO int32u + 0x17a2 Scav11Cols no + 0x17a3 Scav12Cols no + 0x17a4 Scav21Cols no + 0x17a5 Scav22Cols no + 0x17a6 ActiveCTEMonitor1Cols no + 0x17a7 ActiveCTEMonitor2Cols no + 0x17a8 ActiveCTEMonitorRows no + 0x17a9 ActiveBuf1Cols no + 0x17aa ActiveBuf2Cols no + 0x17ab ActiveBuf1Rows no + 0x17ac ActiveBuf2Rows no + 0x17c0 HRNoiseLines no + 0x17c1 RNoiseLines no + 0x17c2 ANoiseLines no + 0x17d4 ImagerCols int16u + 0x17de ImagerRows int16u + 0x17e8 PartialActiveCols1 int32u + 0x17f2 PartialActiveCols2 int32u + 0x17fc PartialActiveRows1 int32u + 0x1806 PartialActiveRows2 int32u + 0x1810 ElectricalBlackColumns int32u + 0x181a ResetBlackSegRows int32u + 0x1838 CaptureWidthNormal int32u + 0x1839 CaptureHeightNormal int32u + 0x183a CaptureWidthResetBlackSegNormal no + 0x183b CaptureHeightResetBlackSegNormal no + 0x183c DarkRefOffsetNormal no + 0x1842 CaptureWidthTest int32u + 0x1843 CaptureHeightTest no + 0x1844 CaptureWidthResetBlackSegTest no + 0x1845 CaptureHeightResetBlackSegTest no + 0x1846 DarkRefOffsetTest no + 0x184c ImageSegmentStartLine int32u + 0x184d ImageSegmentLines int32u + 0x184e SkipLineTime int32u + 0x1860 FastResetLineTime int32u + 0x186a NormalLineTime int32u + 0x1874 MinIntegrationRows int32u + 0x187e PreReadFastResetCount int32u + 0x1888 TransferTimeNormal int32u + 0x1889 TransferTimeTest int32u + 0x188a QuietTime int32u + 0x189c OverClockCols int16u + 0x18a6 H2ResetBlackPixels int32u + 0x18b0 H3ResetBlackPixels int32u + 0x18ba BlackAcquireRows int32u + 0x18c4 OverClockRows int16u + 0x18ce H3ResetBlackColumns int32u + 0x18d8 DarkBlackSegRows int32u + 0x1900 CrossbarEnable no + 0x1901 FifoenOnePixelDelay int32u + 0x1902 ReadoutTypeRequested int32u + 0x1903 ReadoutTypeActual int32u + 0x190a OffsetDacValue int32u + 0x1914 TempAmpGainX100 int32u + 0x191e VarrayDacNominalValues int32u[3] + 0x1928 VddimDacNominalValues no + 0x1964 C14Configuration int32u + 0x196e TDA1Offset int32u[3] + 0x196f TDA1Bandwidth int32u + 0x1970 TDA1Gain int32u[3] + 0x1971 TDA1EdgePolarity int32u + 0x1978 TDA2Offset int32u[3] + 0x1979 TDA2Bandwidth int32u + 0x197a TDA2Gain int32u[3] + 0x197b TDA2EdgePolarity int32u + 0x1982 TDA3Offset int32u[3] + 0x1983 TDA3Bandwidth int32u + 0x1984 TDA3Gain int32u[3] + 0x1985 TDA3EdgePolarity int32u + 0x198c TDA4Offset int32u[3] + 0x198d TDA4Bandwidth int32u + 0x198e TDA4Gain int32u[3] + 0x198f TDA4EdgePolarity int32u + 0xfde8 ComLenBlkSize int16u + +=head3 Kodak TextualInfo Tags + +Below is a list of tags which have been observed in the Kodak TextualInfo +data, however ExifTool will extract information from any tags found here. + + Tag ID Tag Name Writable + ------ -------- -------- + 'AF Function' AFMode no + 'Actual Compensation' ActualCompensation no + 'Aperture' Aperture no + 'Auto Bracket' AutoBracket no + 'Brightness Value' BrightnessValue no + 'Camera' CameraModel no + 'Camera body' CameraBody no + 'Compensation' ExposureCompensation no + 'Date' Date no + 'Exposure Bias' ExposureBias no + 'Exposure Mode' ExposureMode no + 'Firmware Version' FirmwareVersion no + 'Flash Compensation' FlashExposureComp no + 'Flash Fired' FlashFired no + 'Flash Sync Mode' FlashSyncMode no + 'Focal Length' FocalLength no + 'Height' KodakImageHeight no + 'ISO' ISO no + 'ISO Speed' ISO no + 'Image Number' ImageNumber no + 'Max Aperture' MaxAperture no + 'Meter Mode' MeterMode no + 'Min Aperture' MinAperture no + 'Popup Flash' PopupFlash no + 'Serial Number' SerialNumber no + 'Shooting Mode' ShootingMode no + 'Shutter' ShutterSpeed no + 'Temperature' Temperature no + 'Time' Time no + 'White balance' WhiteBalance no + 'Width' KodakImageWidth no + '_other_info' OtherInfo no + +=head3 Kodak Processing Tags + + Index2 Tag Name Writable + ------ -------- -------- + 20 WB_RGBLevels no + +=head3 Kodak Type2 Tags + +These tags are used by the Kodak DC220, DC260, DC265 and DC290, +Hewlett-Packard PhotoSmart 618, C500 and C912, Pentax EI-200 and EI-2000, +and Minolta EX1500Z. + + Index1 Tag Name Writable + ------ -------- -------- + 8 KodakMaker string[32] + 40 KodakModel string[32] + 108 KodakImageWidth int32u + 112 KodakImageHeight int32u + +=head3 Kodak Type3 Tags + +These tags are used by the DC240, DC280, DC3400 and DC5000. + + Index1 Tag Name Writable + ------ -------- -------- + 12 YearCreated int16u + 14 MonthDayCreated int8u[2] + 16 TimeCreated int8u[4] + 30 OpticalZoom int16u + 55 Sharpness int8s + 56 ExposureTime int32u + 60 FNumber int16u + 78 ISO int16u + +=head3 Kodak Type4 Tags + +These tags are used by the DC200 and DC215. + + Index1 Tag Name Writable + ------ -------- -------- + 32 OriginalFileName string[12] + +=head3 Kodak Type5 Tags + +These tags are used by the CX4200, CX4210, CX4230, CX4300, CX4310, CX6200 +and CX6230. + + Index1 Tag Name Writable + ------ -------- -------- + 20 ExposureTime int32u + 26 WhiteBalance int8u + 28 FNumber int16u + 30 ISO int16u + 32 OpticalZoom int16u + 34 DigitalZoom int16u + 39 FlashMode int8u + 42 ImageRotated int8u + 43 Macro int8u + +=head3 Kodak Type6 Tags + +These tags are used by the DX3215 and DX3700. + + Index1 Tag Name Writable + ------ -------- -------- + 16 ExposureTime int32u + 20 ISOSetting? int32u + 24 FNumber int16u + 26 ISO int16u + 28 OpticalZoom int16u + 30 DigitalZoom int16u + 34 Flash int16u + +=head3 Kodak Type7 Tags + +The maker notes of models such as the C340, C433, CC533, LS755, V803 and +V1003 seem to start with the camera serial number. The C310, C315, C330, +C643, C743, CD33, CD43, CX7220 and CX7300 maker notes are also decoded using +this table, although the strings for these cameras don't conform to the +usual Kodak serial number format, and instead have the model name followed +by 8 digits. + + Index1 Tag Name Writable + ------ -------- -------- + 0 SerialNumber string[16] + +=head3 Kodak Type8 Tags + +Kodak models such as the ZD710, P712, P850, P880, V1233, V1253, V1275, +V1285, Z612, Z712, Z812, Z885 use standard TIFF IFD format for the maker +notes. In keeping with Kodak's strategy of inconsistent makernotes, models +such as the M380, M1033, M1093, V1073, V1273, Z1012, Z1085 and Z8612 +also use these tags, but these makernotes begin with a TIFF header instead +of an IFD entry count and use relative instead of absolute offsets. There +is a large amount of information stored in these maker notes (apparently +with much duplication), but relatively few tags have so far been decoded. + + Tag ID Tag Name Writable + ------ -------- -------- + 0xfc00 SubIFD0 Kodak SubIFD0 + Kodak SubIFD0 + 0xfc01 SubIFD1 Kodak SubIFD1 + Kodak SubIFD1 + 0xfc02 SubIFD2 Kodak SubIFD2 + Kodak SubIFD2 + 0xfc03 SubIFD3 Kodak SubIFD3 + Kodak SubIFD3 + 0xfc04 SubIFD4 Kodak SubIFD4 + Kodak SubIFD4 + 0xfc05 SubIFD5 Kodak SubIFD5 + Kodak SubIFD5 + 0xfc06 SubIFD6 Kodak SubIFD6 + Kodak SubIFD6 + 0xfcff SubIFD255 Kodak SubIFD0 + 0xff00 CameraInfo Kodak CameraInfo + +=head3 Kodak SubIFD0 Tags + +SubIFD0 through SubIFD5 tags are written a number of newer Kodak models. + + Tag ID Tag Name Writable + ------ -------- -------- + 0xfa02 SceneMode int16u + 0xfa19 SerialNumber string + 0xfa1d KodakImageWidth int16u + 0xfa1e KodakImageHeight int16u + 0xfa20 SensorWidth int16u + 0xfa21 SensorHeight int16u + 0xfa23 FNumber int16u + 0xfa24 ExposureTime int32u + 0xfa2e ISO int16u + 0xfa3d OpticalZoom int16u + 0xfa46 ISO int16u + 0xfa51 KodakImageWidth int16u + 0xfa52 KodakImageHeight int16u + 0xfa54 ThumbnailWidth int16u + 0xfa55 ThumbnailHeight int16u + 0xfa57 PreviewImageWidth int16u + 0xfa58 PreviewImageHeight int16u + +=head3 Kodak SubIFD1 Tags + + Tag ID Tag Name Writable + ------ -------- -------- + 0x0027 ISO int16u + 0x0028 ISO int16u + +=head3 Kodak SubIFD2 Tags + + Tag ID Tag Name Writable + ------ -------- -------- + 0x6002 SceneModeUsed int32u + 0x6006 OpticalZoom int32u + 0x6103 MaxAperture int32u + 0xf002 SceneModeUsed int32u + 0xf006 OpticalZoom int32u + 0xf103 FNumber int32u + 0xf104 ExposureTime int32u + 0xf105 ISO int32u + +=head3 Kodak SubIFD3 Tags + + Tag ID Tag Name Writable + ------ -------- -------- + 0x1000 OpticalZoom int16u + +=head3 Kodak SubIFD4 Tags + + Tag ID Tag Name Writable + ------ -------- -------- + [no tags known] + +=head3 Kodak SubIFD5 Tags + + Tag ID Tag Name Writable + ------ -------- -------- + 0x000f OpticalZoom int16u + +=head3 Kodak SubIFD6 Tags + +SubIFD6 is written by the M580. + + Tag ID Tag Name Writable + ------ -------- -------- + [no tags known] + +=head3 Kodak CameraInfo Tags + +These tags are used by the P712, P850 and P880. + + Tag ID Tag Name Writable + ------ -------- -------- + 0xf900 SensorWidth int16u + 0xf901 SensorHeight int16u + 0xf902 BayerPattern string + 0xf903 SensorFullWidth int16u + 0xf904 SensorFullHeight int16u + 0xf907 KodakImageWidth int16u + 0xf908 KodakImageHeight int16u + 0xfa00 KodakInfoType string + 0xfa04 SerialNumber string + 0xfd04 FNumber int16u + 0xfd05 ExposureTime int32u + 0xfd06 ISO int16u + +=head3 Kodak Type9 Tags + +These tags are used by the Kodak C140, C180, C913, C1013, M320, M340 and +M550, as well as various cameras marketed by other manufacturers. + + Index1 Tag Name Writable + ------ -------- -------- + 12 FNumber int16u + 16 ExposureTime int32u + 20 DateTimeOriginal string[20] + 52 ISO int16u + 87 FirmwareVersion string[16] + 168 UnknownNumber no + 196 UnknownNumber no + +=head3 Kodak Type10 Tags + +Another variation of the IFD-format type, this time with just a byte order +indicator instead of a full TIFF header. These tags are used by the Z980. + + Tag ID Tag Name Writable + ------ -------- -------- + 0x0002 PreviewImageSize int16u[2] + 0x0012 ExposureTime int32u + 0x0013 FNumber int16u + 0x0014 ISO int16u + 0x001d FocalLength int32u + +=head3 Kodak Type11 Tags + +These tags are found in models such as the PixPro S-1. They are not +writable because the inconsistency of Kodak maker notes is beginning to get +on my nerves. + + Tag ID Tag Name Writable + ------ -------- -------- + 0x0104 FirmwareVersion no + 0x0203 PictureEffect no + 0x0207 KodakModel no + 0x0300 KodakMake no + 0x0308 LensSerialNumber no + 0x0309 LensModel no + 0x030d LevelMeter? no + 0x0311 Pitch no + 0x0312 Yaw no + 0x0313 Roll no + 0x0314 CX? no + 0x0315 CY? no + 0x0316 Rads? no + +=head3 Kodak Unknown Tags + + Index1 Tag Name Writable + ------ -------- -------- + [no tags known] + +=head3 Kodak Meta Tags + +These tags are found in the APP3 "Meta" segment of JPEG images from Kodak +cameras such as the DC280, DC3400, DC5000, MC3, M580, Z950 and Z981. The +structure of this segment is similar to the APP1 "Exif" segment, but a +different set of tags is used. + + Tag ID Tag Name Writable + ------ -------- -------- + 0xc350 FilmProductCode no + 0xc351 ImageSourceEK no + 0xc352 CaptureConditionsPAR no + 0xc353 CameraOwner undef + 0xc354 SerialNumber undef + 0xc355 UserSelectGroupTitle no + 0xc356 DealerIDNumber no + 0xc357 CaptureDeviceFID no + 0xc358 EnvelopeNumber no + 0xc359 FrameNumber no + 0xc35a FilmCategory no + 0xc35b FilmGencode no + 0xc35c ModelAndVersion no + 0xc35d FilmSize no + 0xc35e SBA_RGBShifts no + 0xc35f SBAInputImageColorspace no + 0xc360 SBAInputImageBitDepth no + 0xc361 SBAExposureRecord no + 0xc362 UserAdjSBA_RGBShifts no + 0xc363 ImageRotationStatus no + 0xc364 RollGuidElements no + 0xc365 MetadataNumber no + 0xc366 EditTagArray no + 0xc367 Magnification no + 0xc36c NativeXResolution no + 0xc36d NativeYResolution no + 0xc36e KodakEffectsIFD Kodak SpecialEffects + 0xc36f KodakBordersIFD Kodak Borders + 0xc37a NativeResolutionUnit no + 0xc418 SourceImageDirectory no + 0xc419 SourceImageFileName no + 0xc41a SourceImageVolumeName no + 0xc46c PrintQuality no + 0xc46e ImagePrintStatus no + +=head3 Kodak SpecialEffects Tags + +The Kodak SpecialEffects and Borders tags are found in sub-IFD's within the +Kodak JPEG APP3 "Meta" segment. + + Tag ID Tag Name Writable + ------ -------- -------- + 0x0000 DigitalEffectsVersion no + 0x0001 DigitalEffectsName no + 0x0002 DigitalEffectsType no + +=head3 Kodak Borders Tags + + Tag ID Tag Name Writable + ------ -------- -------- + 0x0000 BordersVersion no + 0x0001 BorderName no + 0x0002 BorderID no + 0x0003 BorderLocation no + 0x0004 BorderType no + 0x0008 WatermarkType no + +=head3 Kodak KDC_IFD Tags + +These tags are found in a separate IFD of KDC images from some newer Kodak +models such as the P880 and Z1015IS. + + Tag ID Tag Name Writable + ------ -------- -------- + 0xfa00 SerialNumber string + 0xfa0d WhiteBalance int8u + 0xfa25 WB_RGBLevelsAuto no + 0xfa27 WB_RGBLevelsTungsten no + 0xfa28 WB_RGBLevelsFluorescent no + 0xfa29 WB_RGBLevelsDaylight no + 0xfa2a WB_RGBLevelsShade no + +=head3 Kodak frea Tags + +Information stored in the "frea" atom of Kodak PixPro SP360 MP4 videos. + + Tag ID Tag Name Writable + ------ -------- -------- + 'scra' PreviewImage no + 'thma' ThumbnailImage no + 'tima' Duration no + 'ver ' KodakVersion no + +=head3 Kodak Free Tags + +Information stored in the "free" atom of Kodak MP4 videos. (VERY bad form +for Kodak to store useful information in an atom intended for unused space!) + + Tag ID Tag Name Writable + ------ -------- -------- + 'AprV' ApertureValue no + 'BrtV' BrightnessValue no + 'Expc' ExposureCompensation no + 'Expo' ExposureTime no + 'FL35' FocalLengthIn35mmFormat no + 'FNum' FNumber no + 'FoLn' FocalLength no + 'ISOS' ISO no + 'SVer' FirmwareVersion no + 'Scrn' PreviewInfo Kodak Scrn + 'Seri' SerialNumber no + 'StSV' ShutterSpeedValue no + +=head3 Kodak Scrn Tags + + Index2 Tag Name Writable + ------ -------- -------- + 0 PreviewImageWidth no + 1 PreviewImageHeight no + 2 PreviewImageLength no + 4 PreviewImage no + +=head3 Kodak DcMD Tags + +Metadata directory found in MOV and MP4 videos from some Kodak cameras. + + Tag ID Tag Name Writable + ------ -------- -------- + 'CMbo' CameraByteOrder no + 'Cmbo' CameraByteOrder no + 'DcEM' DcEM Kodak DcEM + 'DcME' DcME Kodak DcME + +=head3 Kodak DcEM Tags + + Tag ID Tag Name Writable + ------ -------- -------- + [no tags known] + +=head3 Kodak DcME Tags + + Tag ID Tag Name Writable + ------ -------- -------- + [no tags known] + +=head3 Kodak MOV Tags + +This information is found in the TAGS atom of MOV videos from Kodak models +such as the P880. + + Index1 Tag Name Writable + ------ -------- -------- + 0 Make no + 22 Model no + 64 ModelType no + 78 ExposureTime no + 82 FNumber no + 90 ExposureCompensation no + 112 FocalLength no + +=head3 Kodak pose Tags + +Streamed orientation information from the PixPro 4KVR360, extracted as +sub-documents when the Duplicates option is used. + + Tag ID Tag Name Writable + ------ -------- -------- + 'Accelerometer' Accelerometer no + 'AngularVelocity' AngularVelocity no + +=head2 Leaf Tags + +These tags are found in .MOS images from Leaf digital camera backs as +written by Creo Leaf Capture. They exist within the Leaf-specific directory +structure of EXIF tag 0x8606. The tables below list observed Leaf tags, +however ExifTool will extract any tags found in the Leaf directories even if +they don't appear in these tables. + + Tag ID Tag Name Writable + ------ -------- -------- + 'JPEG_preview_data' PreviewImage undef + 'JPEG_preview_info' PreviewInfo no + 'PDA_histogram_data' PDAHistogram no + 'back_serial_number' BackSerial no + 'camera_profile' CameraProfile Leaf CameraProfile + 'icc_camera_profile' ICC_Profile ICC_Profile + 'icc_camera_to_tone_matrix' ToneMatrix no + 'icc_camera_to_tone_space_flow' ToneSpaceFlow no + 'icc_rgb_ws_profile' RGB_Profile ICC_Profile + 'image_offset' ImageOffset no + 'pattern_ratation_angle' PatternAngle no + +=head3 Leaf CameraProfile Tags + +All B<Tag ID>'s in the following table have a leading 'CamProf_' which +has been removed. + + Tag ID Tag Name Writable + ------ -------- -------- + 'back_type' CameraBackType no + 'capture_profile' CaptureProfile Leaf CaptureProfile + 'image_profile' ImageProfile Leaf ImageProfile + 'name' CameraName no + 'type' CameraType no + 'version' CameraProfileVersion no + +=head3 Leaf CaptureProfile Tags + +All B<Tag ID>'s in the following table have a leading 'CaptProf_' which +has been removed. + + Tag ID Tag Name Writable + ------ -------- -------- + 'CCD_rect' CCDRect no + 'CCD_valid_rect' CCDValidRect no + 'CCD_video_rect' CCDVideoRect no + 'back_type' CaptProfBackType no + 'center_dark_rect' CenterDarkRect no + 'color_averages' ColorAverages no + 'color_matrix' ColorMatrix no + 'dark_correction_type' DarkCorrectionType no + 'image_bounds' ImageBounds no + 'image_fields' ImageFields no + 'image_offset' ImageOffset no + 'left_dark_rect' LeftDarkRect no + 'luminance_consts' LuminanceConsts no + 'mosaic_pattern' MosaicPattern no + 'name' CaptProfName no + 'number_of_planes' NumberOfPlanes no + 'raw_data_rotation' RawDataRotation no + 'reconstruction_type' ReconstructionType no + 'right_dark_rect' RightDarkRect no + 'serial_number' CaptureSerial no + 'type' CaptProfType no + 'version' CaptProfVersion no + 'xy_offset_info' XYOffsetInfo no + +=head3 Leaf ImageProfile Tags + +All B<Tag ID>'s in the following table have a leading 'ImgProf_' which +has been removed. + + Tag ID Tag Name Writable + ------ -------- -------- + 'back_type' ImgProfBackType no + 'image_status' ImageStatus no + 'name' ImgProfName no + 'rotation_angle' RotationAngle no + 'shoot_setup' ShootSetup Leaf ShootSetup + 'type' ImgProfType no + 'version' ImgProfVersion no + +=head3 Leaf ShootSetup Tags + +All B<Tag ID>'s in the following table have a leading 'ShootObj_' which +has been removed. + + Tag ID Tag Name Writable + ------ -------- -------- + 'back_type' ShootObjBackType no + 'camera_setup' CameraSetup Leaf CameraSetup + 'capture_setup' CaptureSetup Leaf CaptureSetup + 'color_setup' ColorSetup Leaf ColorSetup + 'look_header' LookHeader Leaf LookHeader + 'name' ShootObjName no + 'save_setup' SaveSetup Leaf SaveSetup + 'type' ShootObjType no + 'version' ShootObjVersion no + +=head3 Leaf CameraSetup Tags + +All B<Tag ID>'s in the following table have a leading 'CameraObj_' which +has been removed. + + Tag ID Tag Name Writable + ------ -------- -------- + 'ISO_speed' ISOSpeed no + 'back_type' CameraObjBackType no + 'camera_type' CameraType no + 'lens_ID' LensID no + 'lens_type' LensType no + 'name' CameraObjName no + 'strobe' Strobe no + 'type' CameraObjType no + 'version' CameraObjVersion no + +=head3 Leaf CaptureSetup Tags + +All B<Tag ID>'s in the following table have a leading 'CaptureObj_' which +has been removed. + + Tag ID Tag Name Writable + ------ -------- -------- + 'Multi_quality' MultiQuality no + 'back_type' CaptureObjBackType no + 'name' CaptureObjName no + 'neutals' Neutals Leaf Neutrals + 'selection' Selection Leaf Selection + 'sharpness' Sharpness Leaf Sharpness + 'single_quality' SingleQuality no + 'tone_curve' ToneCurve Leaf ToneCurve + 'type' CaptureObjType no + 'version' CaptureObjVersion no + +=head3 Leaf Neutrals Tags + +All B<Tag ID>'s in the following table have a leading 'NeutObj_' which +has been removed. + + Tag ID Tag Name Writable + ------ -------- -------- + 'back_type' NeutObjBackType no + 'color_casts' ColorCasts no + 'highlight_end_points' HighlightEndPoints no + 'name' NeutObjName no + 'neutrals' Neutrals no + 'shadow_end_points' ShadowEndPoints no + 'type' NeutObjType no + 'version' NeutObjVersion no + +=head3 Leaf Selection Tags + +All B<Tag ID>'s in the following table have a leading 'SelObj_' which +has been removed. + + Tag ID Tag Name Writable + ------ -------- -------- + 'back_type' SelObjBackType no + 'locks' Locks no + 'name' SelObjName no + 'orientation' Orientation no + 'rect' Rect no + 'resolution' Resolution no + 'scale' Scale no + 'type' SelObjType no + 'version' SelObjVersion no + +=head3 Leaf Sharpness Tags + +All B<Tag ID>'s in the following table have a leading 'SharpObj_' which +has been removed. + + Tag ID Tag Name Writable + ------ -------- -------- + 'back_type' SharpObjBackType no + 'data_len' DataLen no + 'name' SharpObjName no + 'sharp_info' SharpInfo no + 'sharp_method' SharpMethod no + 'type' SharpObjType no + 'version' SharpObjVersion no + +=head3 Leaf ToneCurve Tags + +All B<Tag ID>'s in the following table have a leading 'ToneObj_' which +has been removed. + + Tag ID Tag Name Writable + ------ -------- -------- + 'back_type' ToneObjBackType no + 'gamma' Gamma no + 'name' ToneObjName no + 'npts' Npts no + 'tones' Tones no + 'type' ToneObjType no + 'version' ToneObjVersion no + +=head3 Leaf ColorSetup Tags + +All B<Tag ID>'s in the following table have a leading 'ColorObj_' which +has been removed. + + Tag ID Tag Name Writable + ------ -------- -------- + 'back_type' ColorObjBackType no + 'color_mode' ColorMode no + 'color_type' ColorType no + 'has_ICC' HasICC no + 'input_profile' InputProfile no + 'name' ColorObjName no + 'output_profile' OutputProfile no + 'type' ColorObjType no + 'version' ColorObjVersion no + +=head3 Leaf LookHeader Tags + +All B<Tag ID>'s in the following table have a leading 'LookHead_' which +has been removed. + + Tag ID Tag Name Writable + ------ -------- -------- + 'back_type' LookHeadBackType no + 'name' LookHeadName no + 'type' LookHeadType no + 'version' LookHeadVersion no + +=head3 Leaf SaveSetup Tags + +All B<Tag ID>'s in the following table have a leading 'SaveObj_' which +has been removed. + + Tag ID Tag Name Writable + ------ -------- -------- + 'back_type' SaveObjBackType no + 'leaf_auto_active' LeafAutoActive no + 'leaf_auto_base_name' LeafAutoBaseName no + 'leaf_hot_folder' LeafHotFolder no + 'leaf_open_proc_HDR' LeafOpenProcHDR no + 'leaf_output_file_type' LeafOutputFileType no + 'leaf_save_selection' LeafSaveSelection no + 'name' SaveObjName no + 'std_auto_active' StdAutoActive no + 'std_base_name' StdBaseName no + 'std_hot_folder' StdHotFolder no + 'std_open_in_photoshop' StdOpenInPhotoshop no + 'std_output_bit_depth' StdOutputBitDepth no + 'std_output_color_mode' StdOutputColorMode no + 'std_output_file_type' StdOutputFileType no + 'std_oxygen' StdOxygen no + 'std_save_selection' StdSaveSelection no + 'std_scaled_output' StdScaledOutput no + 'std_sharpen_output' StdSharpenOutput no + 'type' SaveObjType no + 'version' SaveObjVersion no + +=head3 Leaf SubIFD Tags + +Leaf writes a TIFF-format sub-IFD inside IFD0 of a MOS image. No tags in +this sub-IFD are currently known, except for tags 0x8602 and 0x8606 which +really shouldn't be here anyway (so they don't appear in the table below) +because they duplicate references to the same data from tags with the same +ID in IFD0. + + Tag ID Tag Name Writable + ------ -------- -------- + [no tags known] + +=head2 Minolta Tags + +These tags are used by Minolta, Konica/Minolta as well as some Sony cameras. +Minolta doesn't make things easy for decoders because the meaning of some +tags and the location where some information is stored is different for +different camera models. (Take MinoltaQuality for example, which may be +located in 5 different places.) + + Tag ID Tag Name Writable + ------ -------- -------- + 0x0000 MakerNoteVersion undef[4] + 0x0001 MinoltaCameraSettingsOld Minolta CameraSettings + 0x0003 MinoltaCameraSettings Minolta CameraSettings + 0x0004 MinoltaCameraSettings7D Minolta CameraSettings7D + 0x0010 CameraInfoA100 Minolta CameraInfoA100 + 0x0018 ISInfoA100 Minolta ISInfoA100 + ImageStabilization no + 0x0020 WBInfoA100 Minolta WBInfoA100 + 0x0040 CompressedImageSize int32u + 0x0081 PreviewImage undef + 0x0088 PreviewImageStart int32u* + 0x0089 PreviewImageLength int32u* + 0x0100 SceneMode int32u + 0x0101 ColorMode int32u + 0x0102 MinoltaQuality int32u + 0x0103 MinoltaQuality int32u + MinoltaImageSize int32u + 0x0104 FlashExposureComp rational64s + 0x0105 Teleconverter int32u + 0x0107 ImageStabilization int32u + 0x0109 RawAndJpgRecording int32u + 0x010a ZoneMatching int32u + 0x010b ColorTemperature int32u + 0x010c LensType int32u + 0x0111 ColorCompensationFilter int32s + 0x0112 WhiteBalanceFineTune int32u + 0x0113 ImageStabilization int32u + 0x0114 MinoltaCameraSettings5D Minolta CameraSettings5D + CameraSettingsA100 Minolta CameraSettingsA100 + 0x0115 WhiteBalance int32u + 0x0e00 PrintIM PrintIM + 0x0f00 MinoltaCameraSettings2 no + +=head3 Minolta CameraSettings Tags + +There is some variability in CameraSettings information between different +models (and sometimes even between different firmware versions), so this +information may not be as reliable as it should be. Because of this, tags +in the following tables are set to lower priority to prevent them from +superseding the values of same-named tags in other locations when duplicate +tags are disabled. + + Index4 Tag Name Writable + ------ -------- -------- + 1 ExposureMode int32u + 2 FlashMode int32u + 3 WhiteBalance int32u~ + 4 MinoltaImageSize int32u + 5 MinoltaQuality int32u + 6 DriveMode int32u + 7 MeteringMode int32u + 8 ISO int32u + 9 ExposureTime int32u + 10 FNumber int32u + 11 MacroMode int32u + 12 DigitalZoom int32u + 13 ExposureCompensation int32u + 14 BracketStep int32u + 16 IntervalLength int32u + 17 IntervalNumber int32u + 18 FocalLength int32u + 19 FocusDistance int32u + 20 FlashFired int32u + 21 MinoltaDate int32u + 22 MinoltaTime int32u + 23 MaxAperture int32u + 26 FileNumberMemory int32u + 27 LastFileNumber int32u + 28 ColorBalanceRed int32u + 29 ColorBalanceGreen int32u + 30 ColorBalanceBlue int32u + 31 Saturation int32u + 32 Contrast int32u + 33 Sharpness int32u + 34 SubjectProgram int32u + 35 FlashExposureComp int32u + 36 ISOSetting int32u + 37 MinoltaModelID int32u + 38 IntervalMode int32u + 39 FolderName int32u + 40 ColorMode int32u + 41 ColorFilter int32u + 42 BWFilter int32u + 43 InternalFlash int32u + 44 Brightness int32u + 45 SpotFocusPointX int32u + 46 SpotFocusPointY int32u + 47 WideFocusZone int32u + 48 FocusMode int32u + 49 FocusArea int32u + 50 DECPosition int32u + 51 ColorProfile int32u + 52 DataImprint int32u + 63 FlashMetering int32u + +=head3 Minolta CameraSettings7D Tags + + Index2 Tag Name Writable + ------ -------- -------- + 0 ExposureMode int16u + 2 MinoltaImageSize int16u + 3 MinoltaQuality int16u + 4 WhiteBalance int16u + 14 FocusMode int16u + 16 AFPoints int16u + 21 Flash int16u + 22 FlashMode int16u + 28 ISOSetting int16u + 30 ExposureCompensation int16s + 37 ColorSpace int16u + 38 Sharpness int16u + 39 Contrast int16u + 40 Saturation int16u + 45 FreeMemoryCardImages int16u + 63 ColorTemperature int16s + 64 HueAdjustment int16u + 70 Rotation int16u + 71 FNumber int16u + 72 ExposureTime int16u + 74 FreeMemoryCardImages int16u + 94 ImageNumber int16u + 96 NoiseReduction int16u + 98 ImageNumber2 int16u + 113 ImageStabilization int16u + 117 ZoneMatchingOn int16u + +=head3 Minolta CameraInfoA100 Tags + +Camera information for the Sony DSLR-A100. + + Index1 Tag Name Writable + ------ -------- -------- + 1 AFSensorActive int8u + 2 AFStatusActiveSensor int16s + 4 AFStatusTop-right int16s + 6 AFStatusBottom-right int16s + 8 AFStatusBottom int16s + 10 AFStatusMiddleHorizontal int16s + 12 AFStatusCenterVertical int16s + 14 AFStatusTop int16s + 16 AFStatusTop-left int16s + 18 AFStatusBottom-left int16s + 20 FocusLocked int8u + 21 AFPoint int8u + 22 AFMode int8u + 45 AFStatusLeft int16s + 47 AFStatusCenterHorizontal int16s + 49 AFStatusRight int16s + 51 AFAreaMode int8u + +=head3 Minolta ISInfoA100 Tags + +Image stabilization information for the Sony DSLR-A100. + + Index1 Tag Name Writable + ------ -------- -------- + 0 ImageStabilization int16u + +=head3 Minolta WBInfoA100 Tags + +White balance information for the Sony DSLR-A100. + + Index1 Tag Name Writable + ------ -------- -------- + 14 DriveMode int8u + 16 Rotation int8u + 20 ImageStabilizationSetting int8u + 21 DynamicRangeOptimizerMode int8u + 42 ExposureCompensationMode int8u + 43 WBBracketShotNumber int8u + 44 WhiteBalanceBracketing int8u + 45 ExposureBracketShotNumber int8u + 49 FlashFunction int16u + 52 ExposureMode int16u + 54 ColorMode int16u + 56 AverageLV int16u + 60 FrameNumber int8u + 150 WB_RGBLevels int16u[3] + 174 WB_GBRGLevels int16u[4] + 192 WB_RedLevelsTungsten int16u[7] + 206 WB_BlueLevelsTungsten int16u[7] + 220 WB_RedLevelsDaylight int16u[7] + 234 WB_BlueLevelsDaylight int16u[7] + 248 WB_RedLevelsCloudy int16u[7] + 262 WB_BlueLevelsCloudy int16u[7] + 276 WB_RedLevelsFlash int16u[7] + 290 WB_BlueLevelsFlash int16u[7] + 332 WB_RedLevelsFluorescent int16u[7] + 346 WB_BlueLevelsFluorescent int16u[7] + 360 WB_RedLevelsShade int16u[7] + 374 WB_BlueLevelsShade int16u[7] + 392 WB_RedLevel6500K int16u + 394 WB_BlueLevel6500K int16u + 396 WB_RedLevelCustom int16u + 398 WB_BlueLevelCustom int16u + 408 WB_RedLevel3500K int16u + 410 WB_BlueLevel3500K int16u + 446 WB_RedLevelsKelvin int16u[75] + 596 WB_BlueLevelsKelvin int16u[75] + 772 WB_RBLevelsFlash int16u[2] + 776 WB_RBLevelsCoolWhiteF int16u[2] + 1000 WB_RBLevelsTungsten int16u[2] + 1004 WB_RBLevelsDaylight int16u[2] + 1008 WB_RBLevelsCloudy int16u[2] + 1012 WB_RBLevelsFlash int16u[2] + 1020 WB_RedLevelsFluorescent int16u[7] + 1034 WB_BlueLevelsFluorescent int16u[7] + 1048 WB_RBLevelsShade int16u[2] + 1056 WB_RBLevels6500K int16u[2] + 1060 WB_RBLevelsCustom int16u[2] + 1072 WB_RBLevels3500K int16u[2] + 1320 WB_RBLevelsDaylight int16u[2] + 1350 WB_RGBLevels int16u[3] + 1576 AEMeteringSegments int8u[40] + 1680 MeasuredLV int8u + 1681 BrightnessValue int8u + 4172 TiffMeteringImage no + 18872 ExposureTime int8u + 18874 ISO int8u + 18875 FocusDistance int8u + 18877 LensType int16uRev + 18880 ExposureCompensation int8s + 18881 FlashExposureComp int8s + 18882 ImageStabilization int8u + 18883 BrightnessValue int8u + 18885 MaxAperture int8u + 18887 FNumber int8u + 18908 InternalSerialNumber string[12] + +=head3 Minolta CameraSettings5D Tags + + Index2 Tag Name Writable + ------ -------- -------- + 10 ExposureMode int16u + 12 MinoltaImageSize int16u + 13 MinoltaQuality int16u + 14 WhiteBalance int16u + 31 Flash int16u + 32 FlashMode int16u + 37 MeteringMode int16u + 38 ISOSetting int16u + 47 ColorSpace int16u + 48 Sharpness int16u + 49 Contrast int16u + 50 Saturation int16u + 53 ExposureTime int16u + 54 FNumber int16u + 55 FreeMemoryCardImages int16u + 73 ColorTemperature int16s + 74 HueAdjustment int16u + 80 Rotation int16u + 83 ExposureCompensation int16u + 84 FreeMemoryCardImages int16u + 101 Rotation int16u + 110 ColorTemperature int16s + 113 PictureFinish int16u + 174 ImageNumber int16u + 176 NoiseReduction int16u + 189 ImageStabilization int16u + +=head3 Minolta CameraSettingsA100 Tags + +Camera settings information for the Sony DSLR-A100. + + Index2 Tag Name Writable + ------ -------- -------- + 0 ExposureMode int16u + 1 ExposureCompensationSetting int16u + 5 HighSpeedSync int16u + 6 ShutterSpeedSetting int16u + 7 ApertureSetting int16u + 8 ExposureTime int16u + 9 FNumber int16u + 10 DriveMode2 int16u + 11 WhiteBalance int16u + 12 FocusMode int16u + 13 AFPointSelected int16u + 14 AFAreaMode int16u + 15 FlashMode int16u + 16 FlashExposureCompSet int16u + 18 MeteringMode int16u + 19 ISOSetting int16u + 20 ZoneMatchingMode int16u + 21 DynamicRangeOptimizer int16u + 22 ColorMode int16u + 23 ColorSpace int16u + 24 Sharpness int16u + 25 Contrast int16u + 26 Saturation int16u + 28 FlashMetering int16u + 29 PrioritySetupShutterRelease int16u + 30 DriveMode int16u + 31 SelfTimerTime int16u + 32 ContinuousBracketing int16u + 33 SingleFrameBracketing int16u + 34 WhiteBalanceBracketing int16u + 35 WhiteBalanceSetting int16u + 36 PresetWhiteBalance int16u + 37 ColorTemperatureSetting int16u + 38 CustomWBSetting int16u + 39 DynamicRangeOptimizerSetting int16u + 50 FreeMemoryCardImages int16u + 52 CustomWBRedLevel int16u + 53 CustomWBGreenLevel int16u + 54 CustomWBBlueLevel int16u + 55 CustomWBError int16u + 56 WhiteBalanceFineTune int16s + 57 ColorTemperature int16u + 58 ColorCompensationFilter int16s + 59 SonyImageSize int16u + 60 SonyQuality int16u + 61 InstantPlaybackTime int16u + 62 InstantPlaybackSetup int16u + 63 NoiseReduction int16u + 64 EyeStartAF int16u + 65 RedEyeReduction int16u + 66 FlashDefault int16u + 67 AutoBracketOrder int16u + 68 FocusHoldButton int16u + 69 AELButton int16u + 70 ControlDialSet int16u + 71 ExposureCompensationMode int16u + 72 AFAssist int16u + 73 CardShutterLock int16u + 74 LensShutterLock int16u + 75 AFAreaIllumination int16u + 76 MonitorDisplayOff int16u + 77 RecordDisplay int16u + 78 PlayDisplay int16u + 80 ExposureIndicator int16u + 81 AELExposureIndicator int16u + 82 ExposureBracketingIndicatorLast int16u + 83 MeteringOffScaleIndicator int16u + 84 FlashExposureIndicator int16u + 85 FlashExposureIndicatorNext int16u + 86 FlashExposureIndicatorLast int16u + 87 ImageStabilization int16u + 88 FocusModeSwitch int16u + 89 FlashType int16u + 90 Rotation int16u + 91 AELock int16u + 94 ColorTemperature int16u + 95 ColorCompensationFilter int16s + 96 BatteryState int16u + +=head3 Minolta MMA Tags + +This information is found in MOV videos from Minolta models such as the +DiMAGE A2, S414 and 7Hi. + + Index1 Tag Name Writable + ------ -------- -------- + 0 Make no + 20 SoftwareVersion no + +=head3 Minolta MOV1 Tags + +This information is found in MOV videos from some Konica Minolta models such +as the DiMage Z10 and X50. + + Index1 Tag Name Writable + ------ -------- -------- + 0 Make no + 32 ModelType no + 46 ExposureTime no + 50 FNumber no + 58 ExposureCompensation no + 80 FocalLength no + +=head3 Minolta MOV2 Tags + +This information is found in MOV videos from some Minolta models such as the +DiMAGE X and Xt. + + Index1 Tag Name Writable + ------ -------- -------- + 0 Make no + 24 ModelType no + 38 ExposureTime no + 42 FNumber no + 50 ExposureCompensation no + 72 FocalLength no + +=head2 Motorola Tags + + Tag ID Tag Name Writable + ------ -------- -------- + 0x665e Sensor string + 0x6705 ManufactureDate string + +=head2 Nikon Tags + + Tag ID Tag Name Writable + ------ -------- -------- + 0x0001 MakerNoteVersion undef[4] + 0x0002 ISO int16u[2] + 0x0003 ColorMode string + 0x0004 Quality string + 0x0005 WhiteBalance string + 0x0006 Sharpness string + 0x0007 FocusMode string + 0x0008 FlashSetting string + 0x0009 FlashType string + 0x000b WhiteBalanceFineTune int16s[n] + 0x000c WB_RBLevels rational64u[4] + 0x000d ProgramShift undef[4] + 0x000e ExposureDifference undef[4] + 0x000f ISOSelection string + 0x0010 DataDump no + 0x0011 PreviewIFD Nikon PreviewIFD + 0x0012 FlashExposureComp undef[4] + 0x0013 ISOSetting int16u[2] + 0x0014 ColorBalanceA Nikon ColorBalanceA + NRWData Nikon ColorBalanceB + Nikon ColorBalanceC + 0x0016 ImageBoundary int16u[4] + 0x0017 ExternalFlashExposureComp undef[4] + 0x0018 FlashExposureBracketValue undef[4] + 0x0019 ExposureBracketValue rational64s + 0x001a ImageProcessing string + 0x001b CropHiSpeed int16u[7] + 0x001c ExposureTuning undef[3] + 0x001d SerialNumber string! + 0x001e ColorSpace int16u + 0x001f VRInfo Nikon VRInfo + 0x0020 ImageAuthentication int8u + 0x0021 FaceDetect Nikon FaceDetect + 0x0022 ActiveD-Lighting int16u + 0x0023 PictureControlData Nikon PictureControl + Nikon PictureControl2 + Nikon PictureControl3 + Nikon PictureControlUnknown + 0x0024 WorldTime Nikon WorldTime + 0x0025 ISOInfo Nikon ISOInfo + 0x002a VignetteControl int16u + 0x002b DistortInfo Nikon DistortInfo + 0x002c UnknownInfo Nikon UnknownInfo + 0x0032 UnknownInfo2 Nikon UnknownInfo2 + 0x0034 ShutterMode int16u + 0x0035 HDRInfo Nikon HDRInfo + 0x0037 MechanicalShutterCount int32u + 0x0039 LocationInfo Nikon LocationInfo + 0x003d BlackLevel int16u[4] + 0x004f ColorTemperatureAuto int16u + 0x0080 ImageAdjustment string + 0x0081 ToneComp string + 0x0082 AuxiliaryLens string + 0x0083 LensType int8u + 0x0084 Lens rational64u[4] + 0x0085 ManualFocusDistance rational64u + 0x0086 DigitalZoom rational64u + 0x0087 FlashMode int8u + 0x0088 AFInfo Nikon AFInfo + Nikon AFInfo + 0x0089 ShootingMode int16u~ + 0x008b LensFStops undef[4] + 0x008c ContrastCurve undef! + 0x008d ColorHue string + 0x008f SceneMode string + 0x0090 LightSource string + 0x0091 ShotInfoD40 Nikon ShotInfoD40 + ShotInfoD80 Nikon ShotInfoD80 + ShotInfoD90 Nikon ShotInfoD90 + ShotInfoD3a Nikon ShotInfoD3a + ShotInfoD3b Nikon ShotInfoD3b + ShotInfoD3X Nikon ShotInfoD3X + ShotInfoD3S Nikon ShotInfoD3S + ShotInfoD300a Nikon ShotInfoD300a + ShotInfoD300b Nikon ShotInfoD300b + ShotInfoD300S Nikon ShotInfoD300S + ShotInfoD700 Nikon ShotInfoD700 + ShotInfoD800 Nikon ShotInfoD800 + ShotInfoD810 Nikon ShotInfoD810 + ShotInfoD850 Nikon ShotInfoD850 + ShotInfoD5000 Nikon ShotInfoD5000 + ShotInfoD5100 Nikon ShotInfoD5100 + ShotInfoD5200 Nikon ShotInfoD5200 + ShotInfoD7000 Nikon ShotInfoD7000 + ShotInfoD4 Nikon ShotInfoD4 + ShotInfoD4S Nikon ShotInfoD4S + ShotInfoD5 Nikon ShotInfoD500 + ShotInfoD500 Nikon ShotInfoD500 + ShotInfoD610 Nikon ShotInfoD610 + ShotInfo02xx Nikon ShotInfo + ShotInfoUnknown Nikon ShotInfo + 0x0092 HueAdjustment int16s + 0x0093 NEFCompression int16u + 0x0094 Saturation int16s + 0x0095 NoiseReduction string + 0x0096 NEFLinearizationTable undef! + 0x0097 ColorBalance0100 Nikon ColorBalance1 + ColorBalance0102 Nikon ColorBalance2 + ColorBalance0103 Nikon ColorBalance3 + ColorBalance0205 Nikon ColorBalance2 + ColorBalance0209 Nikon ColorBalance4 + ColorBalance02 Nikon ColorBalance2 + ColorBalance0211 Nikon ColorBalance4 + ColorBalance0213 Nikon ColorBalance2 + ColorBalance0215 Nikon ColorBalance4 + ColorBalanceUnknown02 Nikon ColorBalanceUnknown + ColorBalanceUnknown04 Nikon ColorBalanceUnknown + ColorBalanceUnknown Nikon ColorBalanceUnknown + 0x0098 LensData0100 Nikon LensData00 + LensData0101 Nikon LensData01 + LensData0201 Nikon LensData01 + LensData0204 Nikon LensData0204 + LensData0400 Nikon LensData0400 + LensData0402 Nikon LensData0402 + LensData0403 Nikon LensData0403 + LensData0800 Nikon LensData0800 + LensDataUnknown Nikon LensDataUnknown + 0x0099 RawImageCenter int16u[2] + 0x009a SensorPixelSize rational64u[2] + 0x009c SceneAssist string + 0x009e RetouchHistory int16u[10] + 0x00a0 SerialNumber string + 0x00a2 ImageDataSize int32u + 0x00a5 ImageCount int32u + 0x00a6 DeletedImageCount int32u + 0x00a7 ShutterCount int32u! + 0x00a8 FlashInfo0100 Nikon FlashInfo0100 + FlashInfo0102 Nikon FlashInfo0102 + FlashInfo0103 Nikon FlashInfo0103 + FlashInfo0106 Nikon FlashInfo0106 + FlashInfo0107 Nikon FlashInfo0107 + FlashInfoUnknown Nikon FlashInfoUnknown + 0x00a9 ImageOptimization string + 0x00aa Saturation string + 0x00ab VariProgram string + 0x00ac ImageStabilization string + 0x00ad AFResponse string + 0x00b0 MultiExposure Nikon MultiExposure + Nikon MultiExposure + 0x00b1 HighISONoiseReduction int16u + 0x00b3 ToningEffect string + 0x00b6 PowerUpTime undef + 0x00b7 AFInfo2 Nikon AFInfo2 + 0x00b8 FileInfo Nikon FileInfo + Nikon FileInfo + 0x00b9 AFTune Nikon AFTune + 0x00bb RetouchInfo Nikon RetouchInfo + 0x00bd PictureControlData Nikon PictureControl + 0x00c3 BarometerInfo Nikon BarometerInfo + 0x0e00 PrintIM PrintIM + 0x0e01 NikonCaptureData NikonCapture + 0x0e09 NikonCaptureVersion string + 0x0e0e NikonCaptureOffsets Nikon CaptureOffsets + 0x0e10 NikonScanIFD Nikon Scan + 0x0e13 NikonCaptureEditVersions NikonCapture + NikonCaptureEditVersions undef! + 0x0e1d NikonICCProfile ICC_Profile + 0x0e1e NikonCaptureOutput Nikon CaptureOutput + 0x0e22 NEFBitDepth int16u[4]! + +=head3 Nikon PreviewIFD Tags + + Tag ID Tag Name Writable + ------ -------- -------- + 0x00fe SubfileType no + 0x0103 Compression no + 0x011a XResolution no + 0x011b YResolution no + 0x0128 ResolutionUnit no + 0x0201 PreviewImageStart int32u* + 0x0202 PreviewImageLength int32u* + 0x0213 YCbCrPositioning no + +=head3 Nikon ColorBalanceA Tags + + Index2 Tag Name Writable + ------ -------- -------- + 624 WB_RBLevels int16u[2]! + 626 WB_RBLevelsAuto int16u[2]! + 628 WB_RBLevelsDaylight int16u[14]! + 642 WB_RBLevelsIncandescent int16u[14]! + 656 WB_RBLevelsFluorescent int16u[6]! + 662 WB_RBLevelsCloudy int16u[14]! + 676 WB_RBLevelsFlash int16u[14]! + 690 WB_RBLevelsShade int16u[14]! + +=head3 Nikon ColorBalanceB Tags + +Color balance tags used by the P6000. + + Index1 Tag Name Writable + ------ -------- -------- + 4 ColorBalanceVersion undef[4] + 5096 WB_RGGBLevels int32u[4]! + 5112 WB_RGGBLevelsDaylight int32u[4]! + 5128 WB_RGGBLevelsCloudy int32u[4]! + 5160 WB_RGGBLevelsTungsten int32u[4]! + 5176 WB_RGGBLevelsFluorescentW int32u[4]! + 5192 WB_RGGBLevelsFlash int32u[4]! + 5224 WB_RGGBLevelsCustom int32u[4]! + 5240 WB_RGGBLevelsAuto int32u[4]! + +=head3 Nikon ColorBalanceC Tags + +Color balance tags used by the P1000, P7000, P7100 and B700. + + Index1 Tag Name Writable + ------ -------- -------- + 4 ColorBalanceVersion undef[4] + 32 BlackLevel int16u + 56 WB_RGGBLevels int32u[4]! + 76 WB_RGGBLevelsDaylight int32u[4]! + 96 WB_RGGBLevelsCloudy int32u[4]! + 116 WB_RGGBLevelsShade int32u[4]! + 136 WB_RGGBLevelsTungsten int32u[4]! + 156 WB_RGGBLevelsFluorescentW int32u[4]! + 176 WB_RGGBLevelsFluorescentN int32u[4]! + 196 WB_RGGBLevelsFluorescentD int32u[4]! + 216 WB_RGGBLevelsHTMercury int32u[4]! + 256 WB_RGGBLevelsCustom int32u[4]! + 276 WB_RGGBLevelsAuto int32u[4]! + +=head3 Nikon VRInfo Tags + + Index1 Tag Name Writable + ------ -------- -------- + 0 VRInfoVersion no + 4 VibrationReduction int8u + 6 VRMode int8u + +=head3 Nikon FaceDetect Tags + + Index2 Tag Name Writable + ------ -------- -------- + 1 FaceDetectFrameSize int16u[2] + 3 FacesDetected int16u + 4 Face1Position int16u[4] + 8 Face2Position int16u[4] + 12 Face3Position int16u[4] + 16 Face4Position int16u[4] + 20 Face5Position int16u[4] + 24 Face6Position int16u[4] + 28 Face7Position int16u[4] + 32 Face8Position int16u[4] + 36 Face9Position int16u[4] + 40 Face10Position int16u[4] + 44 Face11Position int16u[4] + 48 Face12Position int16u[4] + +=head3 Nikon PictureControl Tags + + Index1 Tag Name Writable + ------ -------- -------- + 0 PictureControlVersion no + 4 PictureControlName string[20] + 24 PictureControlBase string[20] + 48 PictureControlAdjust int8u + 49 PictureControlQuickAdjust int8u + 50 Sharpness int8u + 51 Contrast int8u + 52 Brightness int8u + 53 Saturation int8u + 54 HueAdjustment int8u + 55 FilterEffect int8u + 56 ToningEffect int8u + 57 ToningSaturation int8u + +=head3 Nikon PictureControl2 Tags + + Index1 Tag Name Writable + ------ -------- -------- + 0 PictureControlVersion no + 4 PictureControlName string[20] + 24 PictureControlBase string[20] + 48 PictureControlAdjust int8u + 49 PictureControlQuickAdjust int8u + 51 Sharpness int8u + 53 Clarity int8u + 55 Contrast int8u + 57 Brightness int8u + 59 Saturation int8u + 61 Hue int8u + 63 FilterEffect int8u + 64 ToningEffect int8u + 65 ToningSaturation int8u + +=head3 Nikon PictureControl3 Tags + + Index1 Tag Name Writable + ------ -------- -------- + 0 PictureControlVersion no + 8 PictureControlName string[20] + 28 PictureControlBase string[20] + 54 PictureControlAdjust int8u + 55 PictureControlQuickAdjust int8u + 57 Sharpness int8u + 59 MidRangeSharpness int8u + 61 Clarity int8u + 63 Contrast int8u + 65 Brightness int8u + 67 Saturation int8u + 69 Hue int8u + 71 FilterEffect int8u + 72 ToningEffect int8u + 73 ToningSaturation int8u + +=head3 Nikon PictureControlUnknown Tags + + Index1 Tag Name Writable + ------ -------- -------- + 0 PictureControlVersion no + +=head3 Nikon WorldTime Tags + + Index1 Tag Name Writable + ------ -------- -------- + 0 TimeZone int16s + 2 DaylightSavings int8u + 3 DateDisplayFormat int8u + +=head3 Nikon ISOInfo Tags + + Index1 Tag Name Writable + ------ -------- -------- + 0 ISO int8u + 4 ISOExpansion int16u + 6 ISO2 int8u + 10 ISOExpansion2 int16u + +=head3 Nikon DistortInfo Tags + + Index1 Tag Name Writable + ------ -------- -------- + 0 DistortionVersion? no + 4 AutoDistortionControl int8u + +=head3 Nikon UnknownInfo Tags + + Index4 Tag Name Writable + ------ -------- -------- + 0 UnknownInfoVersion? no + +=head3 Nikon UnknownInfo2 Tags + + Index4 Tag Name Writable + ------ -------- -------- + 0 UnknownInfo2Version? no + +=head3 Nikon HDRInfo Tags + + Index1 Tag Name Writable + ------ -------- -------- + 0 HDRInfoVersion string[4] + 4 HDR int8u + 5 HDRLevel int8u + 6 HDRSmoothing int8u + 7 HDRLevel2 int8u + +=head3 Nikon LocationInfo Tags + +Tags written by some Nikon GPS-equipped cameras like the AW100. + + Index1 Tag Name Writable + ------ -------- -------- + 0 LocationInfoVersion undef[4] + 4 TextEncoding int8u + 5 CountryCode undef[3] + 8 POILevel int8u + 9 Location undef[70] + +=head3 Nikon AFInfo Tags + + Index1 Tag Name Writable + ------ -------- -------- + 0 AFAreaMode int8u + 1 AFPoint int8u + 2 AFPointsInFocus int16u + +=head3 Nikon ShotInfoD40 Tags + +These tags are extracted from encrypted data in D40 and D40X images. + + Index Tag Name Writable + ----- -------- -------- + 0 ShotInfoVersion no + 582 ShutterCount int32u + 586.1 VibrationReduction int8u & 0x08 + 729 CustomSettingsD40 NikonCustom SettingsD40 + +=head3 Nikon ShotInfoD80 Tags + +These tags are extracted from encrypted data in D80 images. + + Index Tag Name Writable + ----- -------- -------- + 0 ShotInfoVersion no + 586 ShutterCount int32u + 590.1 Rotation int8u & 0x07 + 590.2 VibrationReduction int8u & 0x18 + 590.3 FlashFired int8u & 0xe0 + 708 NikonImageSize int8u & 0xf0 + 708.1 ImageQuality int8u & 0x0f + 748 CustomSettingsD80 NikonCustom SettingsD80 + +=head3 Nikon ShotInfoD90 Tags + +These tags are extracted from encrypted data in images from the D90 with +firmware 1.00. + + Index Tag Name Writable + ----- -------- -------- + 0 ShotInfoVersion no + 4 FirmwareVersion no + 693 ISO2 int8u + 725 ShutterCount int32u + 884 CustomSettingsD90 NikonCustom SettingsD90 + +=head3 Nikon ShotInfoD3a Tags + +These tags are extracted from encrypted data in images from the D3 with +firmware 1.00 and earlier. + + Index Tag Name Writable + ----- -------- -------- + 0 ShotInfoVersion no + 598 ISO2 int8u + 630 ShutterCount int32u + 723.1 NikonImageSize int8u & 0x18 + 723.2 ImageQuality int8u & 0x07 + 769 CustomSettingsD3 NikonCustom SettingsD3 + +=head3 Nikon ShotInfoD3b Tags + +These tags are extracted from encrypted data in images from the D3 with +firmware 1.10, 2.00, 2.01 and 2.02. + + Index Tag Name Writable + ----- -------- -------- + 0 ShotInfoVersion no + 4 FirmwareVersion no + 16 ImageArea int8u + 605 ISO2 int8u + 637 ShutterCount int32u + 639 ShutterCount int32u + 650 PreFlashReturnStrength int8u + 732.1 NikonImageSize int8u & 0x18 + 732.2 ImageQuality int8u & 0x07 + 778 CustomSettingsD3 NikonCustom SettingsD3 + +=head3 Nikon ShotInfoD3X Tags + +These tags are extracted from encrypted data in images from the D3X with +firmware 1.00. + + Index Tag Name Writable + ----- -------- -------- + 0 ShotInfoVersion no + 4 FirmwareVersion no + 605 ISO2 int8u + 640 ShutterCount int32u + 779 CustomSettingsD3X NikonCustom SettingsD3 + +=head3 Nikon ShotInfoD3S Tags + +These tags are extracted from encrypted data in images from the D3S with +firmware 1.00 and earlier. + + Index Tag Name Writable + ----- -------- -------- + 0 ShotInfoVersion no + 4 FirmwareVersion no + 16 ImageArea int8u + 545 ISO2 int8u + 578 ShutterCount int32u + 718 CustomSettingsD3S NikonCustom SettingsD3 + +=head3 Nikon ShotInfoD300a Tags + +These tags are extracted from encrypted data in images from the D300 with +firmware 1.00 and earlier. + + Index Tag Name Writable + ----- -------- -------- + 0 ShotInfoVersion no + 604 ISO2 int8u + 633 ShutterCount int32u + 721 AFFineTuneAdj int16u + 790 CustomSettingsD300 NikonCustom SettingsD3 + +=head3 Nikon ShotInfoD300b Tags + +These tags are extracted from encrypted data in images from the D300 with +firmware 1.10. + + Index Tag Name Writable + ----- -------- -------- + 0 ShotInfoVersion no + 4 FirmwareVersion no + 613 ISO2 int8u + 644 ShutterCount int32u + 732 AFFineTuneAdj int16u + 802 CustomSettingsD300 NikonCustom SettingsD3 + +=head3 Nikon ShotInfoD300S Tags + +These tags are extracted from encrypted data in images from the D300S with +firmware 1.00. + + Index Tag Name Writable + ----- -------- -------- + 0 ShotInfoVersion no + 4 FirmwareVersion no + 613 ISO2 int8u + 646 ShutterCount int32u + 804 CustomSettingsD300S NikonCustom SettingsD3 + +=head3 Nikon ShotInfoD700 Tags + +These tags are extracted from encrypted data in images from the D700 with +firmware 1.02f. + + Index Tag Name Writable + ----- -------- -------- + 0 ShotInfoVersion no + 4 FirmwareVersion no + 613 ISO2 int8u + 647 ShutterCount int32u + 804 CustomSettingsD700 NikonCustom SettingsD700 + +=head3 Nikon ShotInfoD800 Tags + +These tags are extracted from encrypted data in images from the D800. + + Index Tag Name Writable + ----- -------- -------- + 0 ShotInfoVersion no + 4 FirmwareVersion no + 1216 RepeatingFlashOutputExternal int8u + 1218 RepeatingFlashRateExternal int8u + 1219 RepeatingFlashCountExternal int8u + 1234 FlashExposureComp2 int8s + 1242 RepeatingFlashRateBuilt-in int8u + 1243 RepeatingFlashCountBuilt-in int8u + 1308 SequenceNumber int8u + 1531 ShutterCount int32u + 1772 CustomSettingsD800 NikonCustom SettingsD800 + +=head3 Nikon ShotInfoD810 Tags + +These tags are extracted from encrypted data in images from the D810. + + Index Tag Name Writable + ----- -------- -------- + 0 ShotInfoVersion no + 4 FirmwareVersion no + 36 BracketingOffset no + 64 CustomSettingsOffset no + 132 OrientationOffset no + 464 SecondarySlotFunction int8u & 0x03 + 5974 AEBracketingSteps int8u & 0xff + 5975 WBBracketingSteps int8u & 0xff + 5982 D810MeteringMode int8u & 0x03 + 6236 ISOAutoShutterTime int8u & 0x3f + 6237 ISOAutoHiLimit int8u & 0xff + 6315 CustomSettingsD810 NikonCustom SettingsD810 + 14068 RollAngle fixed32u + 14072 PitchAngle fixed32u + 14076 YawAngle fixed32u + +=head3 Nikon ShotInfoD850 Tags + +These tags are extracted from encrypted data in images from the D850. + + Index Tag Name Writable + ----- -------- -------- + 0 ShotInfoVersion no + 4 FirmwareVersion no + 88 CustomSettingsOffset no + 1937 PhotoShootingMenuBankImageArea int8u & 0x07 + 4029 PhotoShootingMenuBank int8u & 0x03 + 4031 PrimarySlot int8u & 0x80 + 4152 CustomSettingsD850 NikonCustom SettingsD850 + +=head3 Nikon ShotInfoD5000 Tags + +These tags are extracted from encrypted data in images from the D5000 with +firmware 1.00. + + Index Tag Name Writable + ----- -------- -------- + 0 ShotInfoVersion no + 4 FirmwareVersion no + 693 ISO2 int8u + 726 ShutterCount int32u + 888 CustomSettingsD5000 NikonCustom SettingsD5000 + +=head3 Nikon ShotInfoD5100 Tags + + Index Tag Name Writable + ----- -------- -------- + 0 ShotInfoVersion no + 4 FirmwareVersion no + 801 ShutterCount int32u + 1031 CustomSettingsD5100 NikonCustom SettingsD5100 + +=head3 Nikon ShotInfoD5200 Tags + + Index Tag Name Writable + ----- -------- -------- + 0 ShotInfoVersion no + 4 FirmwareVersion no + 3032 ShutterCount int32u + 3285 CustomSettingsD5200 NikonCustom SettingsD5200 + +=head3 Nikon ShotInfoD7000 Tags + +These tags are extracted from encrypted data in images from the D7000 with +firmware 1.01b. + + Index Tag Name Writable + ----- -------- -------- + 0 ShotInfoVersion no + 4 FirmwareVersion no + 800 ShutterCount int32u + 1028 CustomSettingsD7000 NikonCustom SettingsD7000 + +=head3 Nikon ShotInfoD4 Tags + +These tags are extracted from encrypted data in images from the D4. + + Index Tag Name Writable + ----- -------- -------- + 0 ShotInfoVersion no + 4 FirmwareVersion no + 1873 CustomSettingsD4 NikonCustom SettingsD4 + +=head3 Nikon ShotInfoD4S Tags + +These tags are extracted from encrypted data in images from the D4S. + + Index Tag Name Writable + ----- -------- -------- + 0 ShotInfoVersion no + 4 FirmwareVersion no + 464 SecondarySlotFunction int8u & 0x03 + 5964 AEBracketingSteps int8u & 0xff + 5965 WBBracketingSteps int8u & 0xff + 6221 ReleaseMode int8u & 0xff + 6301 CustomSettingsD4S NikonCustom SettingsD4 + 6338 MultiSelectorLiveViewMode int8u & 0xc0 + 6378 ISOAutoShutterTime int8u & 0x3f + 6379 ISOAutoHiLimit int8u & 0xff + 6461 CustomSettingsD4S NikonCustom SettingsD4 + 13579 RollAngle fixed32u + 13583 PitchAngle fixed32u + 13587 YawAngle fixed32u + 13971 Rotation int8u & 0x30 + +=head3 Nikon ShotInfoD500 Tags + +These tags are extracted from encrypted data in images from the D5 and D500. + + Index Tag Name Writable + ----- -------- -------- + 0 ShotInfoVersion no + 4 FirmwareVersion no + 16 RotationInfoOffset no + 20 JPGInfoOffset no + 44 BracketingInfoOffset no + 80 ShootingMenuOffset no + 88 CustomSettingsOffset no + 160 OrientationOffset no + 202 Rotation int8u & 0x03 + 1506 FlickerReductionIndicator int8u & 0x01 + 2004 JPGCompression int8u & 0x01 + 2171 AEBracketingSteps int8u & 0xff + 2172 WBBracketingSteps int8u & 0xff + 2179 ADLBracketingStep int8u & 0xf0 + 2180 ADLBracketingType int8u & 0x0f + 3709 PhotoShootingMenuBank int8u & 0x03 + 3711 PrimarySlot int8u & 0x80 + 3713 ISOAutoShutterTime int8u & 0x3f + 3714 ISOAutoHiLimit int8u & 0xff + 3716 FlickerReduction int8u & 0x20 + 3716.1 PhotoShootingMenuBankImageArea int8u & 0x07 + 3819 CustomSettingsD5 NikonCustom SettingsD5 + CustomSettingsD500 NikonCustom SettingsD500 + 11300 RollAngle fixed32u + 11304 PitchAngle fixed32u + 11308 YawAngle fixed32u + +=head3 Nikon ShotInfoD610 Tags + +These tags are extracted from encrypted data in images from the D610. + + Index Tag Name Writable + ----- -------- -------- + 0 ShotInfoVersion no + 4 FirmwareVersion no + 1999 CustomSettingsD610 NikonCustom SettingsD610 + +=head3 Nikon ShotInfo Tags + +This information is encrypted for ShotInfoVersion 02xx, and some tags are +only valid for specific models. + + Index1 Tag Name Writable + ------ -------- -------- + 0 ShotInfoVersion no + 4 FirmwareVersion no + 16 DistortionControl int8u + 102 VR_0x66? int8u + 106 ShutterCount int32u + 110 DeletedImageCount int32u + 117 VibrationReduction int8u + 130 VibrationReduction int8u + 343 ShutterCount undef[2] + 430 VibrationReduction int8u + 589 ShutterCount int32u + +=head3 Nikon ColorBalance1 Tags + + Index2 Tag Name Writable + ------ -------- -------- + 0 WB_RBGGLevels int16u[4]! + +=head3 Nikon ColorBalance2 Tags + +This information is encrypted for most camera models. + + Index2 Tag Name Writable + ------ -------- -------- + 0 WB_RGGBLevels int16u[4]! + +=head3 Nikon ColorBalance3 Tags + + Index2 Tag Name Writable + ------ -------- -------- + 0 WB_RGBGLevels int16u[4]! + +=head3 Nikon ColorBalance4 Tags + + Index2 Tag Name Writable + ------ -------- -------- + 0 WB_GRBGLevels int16u[4]! + +=head3 Nikon ColorBalanceUnknown Tags + + Index1 Tag Name Writable + ------ -------- -------- + 0 ColorBalanceVersion undef[4] + +=head3 Nikon LensData00 Tags + +This structure is used by the D100, and D1X with firmware version 1.1. + + Index1 Tag Name Writable + ------ -------- -------- + 0 LensDataVersion no + 6 LensIDNumber int8u + 7 LensFStops int8u + 8 MinFocalLength int8u + 9 MaxFocalLength int8u + 10 MaxApertureAtMinFocal int8u + 11 MaxApertureAtMaxFocal int8u + 12 MCUVersion int8u + +=head3 Nikon LensData01 Tags + +Nikon encrypts the LensData information below if LensDataVersion is 0201 or +higher, but the decryption algorithm is known so the information can be +extracted. + + Index1 Tag Name Writable + ------ -------- -------- + 0 LensDataVersion no + 4 ExitPupilPosition int8u + 5 AFAperture int8u + 8 FocusPosition int8u + 9 FocusDistance int8u + 10 FocalLength int8u + 11 LensIDNumber int8u + 12 LensFStops int8u + 13 MinFocalLength int8u + 14 MaxFocalLength int8u + 15 MaxApertureAtMinFocal int8u + 16 MaxApertureAtMaxFocal int8u + 17 MCUVersion int8u + 18 EffectiveMaxAperture int8u + +=head3 Nikon LensData0204 Tags + +Nikon encrypts the LensData information below if LensDataVersion is 0201 or +higher, but the decryption algorithm is known so the information can be +extracted. + + Index1 Tag Name Writable + ------ -------- -------- + 0 LensDataVersion no + 4 ExitPupilPosition int8u + 5 AFAperture int8u + 8 FocusPosition int8u + 10 FocusDistance int8u + 11 FocalLength int8u + 12 LensIDNumber int8u + 13 LensFStops int8u + 14 MinFocalLength int8u + 15 MaxFocalLength int8u + 16 MaxApertureAtMinFocal int8u + 17 MaxApertureAtMaxFocal int8u + 18 MCUVersion int8u + 19 EffectiveMaxAperture int8u + +=head3 Nikon LensData0400 Tags + +Tags extracted from the encrypted lens data of the Nikon 1J1/1V1/1J2. + + Index1 Tag Name Writable + ------ -------- -------- + 0 LensDataVersion no + 394 LensModel string[64] + +=head3 Nikon LensData0402 Tags + +Tags extracted from the encrypted lens data of the Nikon 1J3/1S1/1V2. + + Index1 Tag Name Writable + ------ -------- -------- + 0 LensDataVersion no + 395 LensModel string[64] + +=head3 Nikon LensData0403 Tags + +Tags extracted from the encrypted lens data of the Nikon 1J4/1J5. + + Index1 Tag Name Writable + ------ -------- -------- + 0 LensDataVersion no + 684 LensModel string[64] + +=head3 Nikon LensData0800 Tags + +Tags found in the encrypted LensData from cameras such as the Z6 and Z7. + + Index1 Tag Name Writable + ------ -------- -------- + 0 LensDataVersion no + 4 ExitPupilPosition int8u + 5 AFAperture int8u + 9 FocusPosition int8u + 11 FocusDistance int8u + 12 FocalLength int8u + 13 LensIDNumber int8u + 14 LensFStops int8u + 15 MinFocalLength int8u + 16 MaxFocalLength int8u + 17 MaxApertureAtMinFocal int8u + 18 MaxApertureAtMaxFocal int8u + 19 MCUVersion int8u + 20 EffectiveMaxAperture int8u + 54 MaxAperture int16u + 56 FNumber int16u + 60 FocalLength int16u + +=head3 Nikon LensDataUnknown Tags + + Index1 Tag Name Writable + ------ -------- -------- + 0 LensDataVersion no + +=head3 Nikon FlashInfo0100 Tags + +These tags are used by the D2H, D2Hs, D2X, D2Xs, D50, D70, D70s, D80 and +D200. + + Index1 Tag Name Writable + ------ -------- -------- + 0 FlashInfoVersion no + 4 FlashSource int8u + 6 ExternalFlashFirmware int8u[2] + 8 ExternalFlashFlags int8u + 9.1 FlashCommanderMode int8u & 0x80 + 9.2 FlashControlMode int8u & 0x7f + 10 FlashOutput int8u + FlashCompensation int8s + 11 FlashFocalLength int8u + 12 RepeatingFlashRate int8u + 13 RepeatingFlashCount int8u + 14 FlashGNDistance int8u + 15 FlashGroupAControlMode int8u & 0x0f + 16 FlashGroupBControlMode int8u & 0x0f + 17 FlashGroupAOutput int8u + FlashGroupACompensation int8s + 18 FlashGroupBOutput int8u + FlashGroupBCompensation int8s + +=head3 Nikon FlashInfo0102 Tags + +These tags are used by the D3 (firmware 1.x), D40, D40X, D60 and D300 +(firmware 1.00). + + Index1 Tag Name Writable + ------ -------- -------- + 0 FlashInfoVersion no + 4 FlashSource int8u + 6 ExternalFlashFirmware int8u[2] + 8 ExternalFlashFlags int8u + 9.1 FlashCommanderMode int8u & 0x80 + 9.2 FlashControlMode int8u & 0x7f + 10 FlashOutput int8u + FlashCompensation int8s + 12 FlashFocalLength int8u + 13 RepeatingFlashRate int8u + 14 RepeatingFlashCount int8u + 15 FlashGNDistance int8u + 16.1 FlashGroupAControlMode int8u & 0x0f + 17.1 FlashGroupBControlMode int8u & 0xf0 + 17.2 FlashGroupCControlMode int8u & 0x0f + 18 FlashGroupAOutput int8u + FlashGroupACompensation int8s + 19 FlashGroupBOutput int8u + FlashGroupBCompensation int8s + 20 FlashGroupCOutput int8u + FlashGroupCCompensation int8s + +=head3 Nikon FlashInfo0103 Tags + +These tags are used by the D3 (firmware 2.x), D3X, D3S, D4, D90, D300 +(firmware 1.10), D300S, D600, D700, D800, D3000, D3100, D3200, D5000, D5100, +D5200, D7000. + + Index1 Tag Name Writable + ------ -------- -------- + 0 FlashInfoVersion no + 4 FlashSource int8u + 6 ExternalFlashFirmware int8u[2] + 8 ExternalFlashFlags int8u + 9.1 FlashCommanderMode int8u & 0x80 + 9.2 FlashControlMode int8u & 0x7f + 10 FlashOutput int8u + FlashCompensation int8s + 12 FlashFocalLength int8u + 13 RepeatingFlashRate int8u + 14 RepeatingFlashCount int8u + 15 FlashGNDistance int8u + 16 FlashColorFilter int8u + 17.1 FlashGroupAControlMode int8u & 0x0f + 18.1 FlashGroupBControlMode int8u & 0xf0 + 18.2 FlashGroupCControlMode int8u & 0x0f + 19 FlashGroupAOutput int8u + FlashGroupACompensation int8s + 20 FlashGroupBOutput int8u + FlashGroupBCompensation int8s + 21 FlashGroupCOutput int8u + FlashGroupCCompensation int8s + 27 ExternalFlashCompensation int8s + 29 FlashExposureComp3 int8s + 39 FlashExposureComp4 int8s + +=head3 Nikon FlashInfo0106 Tags + +These tags are used by the Df, D610, D3300, D5300, D7100 and Coolpix A. + + Index1 Tag Name Writable + ------ -------- -------- + 0 FlashInfoVersion no + 4 FlashSource int8u + 6 ExternalFlashFirmware int8u[2] + 8 ExternalFlashFlags int8u + 9.1 FlashCommanderMode int8u & 0x80 + 9.2 FlashControlMode int8u & 0x7f + 12 FlashFocalLength int8u + 13 RepeatingFlashRate int8u + 14 RepeatingFlashCount int8u + 15 FlashGNDistance int8u + 16 FlashColorFilter int8u + 17.1 FlashGroupAControlMode int8u & 0x0f + 18.1 FlashGroupBControlMode int8u & 0xf0 + 18.2 FlashGroupCControlMode int8u & 0x0f + 39 FlashOutput int8u + FlashCompensation int8s + 40 FlashGroupAOutput int8u + FlashGroupACompensation int8s + 41 FlashGroupBOutput int8u + FlashGroupBCompensation int8s + 42 FlashGroupCOutput int8u + FlashGroupCCompensation int8s + +=head3 Nikon FlashInfo0107 Tags + +These tags are used by the D4S, D750, D810, D5500, D7200 (FlashInfoVersion +0107) and the D5, D500, D850 and D3400 (FlashInfoVersion 0108). + + Index1 Tag Name Writable + ------ -------- -------- + 0 FlashInfoVersion no + 4 FlashSource int8u + 6 ExternalFlashFirmware int8u[2] + 8.1 ExternalFlashZoomOverride int8u & 0x80 + 8.2 ExternalFlashStatus int8u & 0x01 + 9.1 ExternalFlashReadyState int8u & 0x07 + 10 FlashCompensation int8s + 12 FlashFocalLength int8u + 13 RepeatingFlashRate int8u + 14 RepeatingFlashCount int8u + 15 FlashGNDistance int8u + 17.1 FlashGroupAControlMode int8u & 0x0f + 18.1 FlashGroupBControlMode int8u & 0xf0 + 18.2 FlashGroupCControlMode int8u & 0x0f + 40 FlashGroupAOutput int8u + FlashGroupACompensation int8s + 41 FlashGroupBOutput int8u + FlashGroupBCompensation int8s + 42 FlashGroupCOutput int8u + FlashGroupCCompensation int8s + +=head3 Nikon FlashInfoUnknown Tags + + Index1 Tag Name Writable + ------ -------- -------- + 0 FlashInfoVersion no + +=head3 Nikon MultiExposure Tags + + Index4 Tag Name Writable + ------ -------- -------- + 0 MultiExposureVersion no + 1 MultiExposureMode int32u + 2 MultiExposureShots int32u + 3 MultiExposureAutoGain int32u + +=head3 Nikon AFInfo2 Tags + +These tags are written by Nikon DSLR's which have the live view feature. + + Index1 Tag Name Writable + ------ -------- -------- + 0 AFInfo2Version no + 4 ContrastDetectAF int8u + 5 AFAreaMode int8u + 6 PhaseDetectAF int8u + 7 PrimaryAFPoint int8u + 8 AFPointsUsed undef[7] + AFPointsUsed undef[2] + AFPointsUsed undef[5] + AFPointsUsed undef[17] + AFPointsUsed undef[21] + AFPointsUsed undef[29] + AFPointsUsed undef[20] + AFPointsUsed undef[62] + AFPointsUsed undef[7] + 16 AFImageWidth int16u + 18 AFImageHeight int16u + 20 AFAreaXPosition int16u + 22 AFAreaYPosition int16u + 24 AFAreaWidth int16u + 26 AFAreaHeight int16u + 28 ContrastDetectAFInFocus int8u + 42 AFImageWidth int16u + 44 AFImageHeight int16u + 46 AFAreaXPosition int16u + 48 AFAreaYPosition int16u + 50 AFAreaWidth int16u + 52 AFAreaHeight int16u + 68 PrimaryAFPoint int8u + 70 AFImageWidth int16u + 72 AFImageHeight int16u + 74 AFAreaXPosition int16u + 76 AFAreaYPosition int16u + 78 AFAreaWidth int16u + 80 AFAreaHeight int16u + 82 ContrastDetectAFInFocus int8u + +=head3 Nikon FileInfo Tags + + Index2 Tag Name Writable + ------ -------- -------- + 0 FileInfoVersion no + 2 MemoryCardNumber int16u + 3 DirectoryNumber int16u + 4 FileNumber int16u + +=head3 Nikon AFTune Tags + + Index1 Tag Name Writable + ------ -------- -------- + 0 AFFineTune int8u + 1 AFFineTuneIndex int8u + 2 AFFineTuneAdj int8s + +=head3 Nikon RetouchInfo Tags + + Index1 Tag Name Writable + ------ -------- -------- + 0 RetouchInfoVersion no + 5 RetouchNEFProcessing int8s + +=head3 Nikon BarometerInfo Tags + + Index1 Tag Name Writable + ------ -------- -------- + 0 BarometerInfoVersion no + 6 Altitude int32s + +=head3 Nikon CaptureOffsets Tags + + Tag ID Tag Name Writable + ------ -------- -------- + 0x0001 IFD0_Offset no + 0x0002 PreviewIFD_Offset no + 0x0003 SubIFD_Offset no + +=head3 Nikon Scan Tags + +This information is written by the Nikon Scan software. + + Tag ID Tag Name Writable + ------ -------- -------- + 0x0002 FilmType string + 0x0040 MultiSample string + 0x0041 BitDepth int16u + 0x0050 MasterGain rational64s + 0x0051 ColorGain rational64s[3] + 0x0060 ScanImageEnhancer int32u + 0x0100 DigitalICE string + 0x0110 ROCInfo Nikon ROC + 0x0120 GEMInfo Nikon GEM + 0x0200 DigitalDEEShadowAdj int32u + 0x0201 DigitalDEEThreshold int32u + 0x0202 DigitalDEEHighlightAdj int32u + +=head3 Nikon ROC Tags + + Index4 Tag Name Writable + ------ -------- -------- + 0 DigitalROC int32u + +=head3 Nikon GEM Tags + + Index4 Tag Name Writable + ------ -------- -------- + 0 DigitalGEM int32u + +=head3 Nikon CaptureOutput Tags + + Index4 Tag Name Writable + ------ -------- -------- + 2 OutputImageWidth int32u + 3 OutputImageHeight int32u + 4 OutputResolution int32u + +=head3 Nikon Type2 Tags + + Tag ID Tag Name Writable + ------ -------- -------- + 0x0003 Quality yes + 0x0004 ColorMode yes + 0x0005 ImageAdjustment yes + 0x0006 CCDSensitivity yes + 0x0007 WhiteBalance yes + 0x0008 Focus yes + 0x000a DigitalZoom yes + 0x000b Converter yes + +=head3 Nikon NEFInfo Tags + +As-yet unknown information found in SubIFD1 tag 0xc7d5 of NEF images from +cameras such as the Z6 and Z7, and NRW images from some Coolpix cameras. + + Tag ID Tag Name Writable + ------ -------- -------- + [no tags known] + +=head3 Nikon NCDT Tags + +Nikon-specific QuickTime tags found in the NCDT atom of MOV videos from +various Nikon models. + + Tag ID Tag Name Writable + ------ -------- -------- + 'NCDB' NikonNCDB Nikon NCDB + 'NCHD' MakerNoteVersion no + 'NCM1' PreviewImage1 no + 'NCM2' PreviewImage2 no + 'NCTG' NikonTags Nikon NCTG + 'NCTH' ThumbnailImage no + 'NCVW' PreviewImage no + +=head3 Nikon NCDB Tags + + Tag ID Tag Name Writable + ------ -------- -------- + [no tags known] + +=head3 Nikon NCTG Tags + +These tags are found in proprietary-format records of the NCTG atom in MOV +videos from some Nikon cameras. + + Tag ID Tag Name Writable + ------ -------- -------- + 0x0001 Make no + 0x0002 Model no + 0x0003 Software no + 0x0011 CreateDate no + 0x0012 DateTimeOriginal no + 0x0013 FrameCount no + 0x0016 FrameRate no + 0x0019 TimeZone no + 0x0022 FrameWidth no + 0x0023 FrameHeight no + 0x0032 AudioChannels no + 0x0033 AudioBitsPerSample no + 0x0034 AudioSampleRate no + 0x1002 NikonDateTime no + 0x1013 ElectronicVR no + 0x110829a ExposureTime no + 0x110829d FNumber no + 0x1108822 ExposureProgram no + 0x1109204 ExposureCompensation no + 0x1109207 MeteringMode no + 0x110920a FocalLength no + 0x110a431 SerialNumber no + 0x110a432 LensInfo no + 0x110a433 LensMake no + 0x110a434 LensModel no + 0x110a435 LensSerialNumber no + 0x1200000 GPSVersionID no + 0x1200001 GPSLatitudeRef no + 0x1200002 GPSLatitude no + 0x1200003 GPSLongitudeRef no + 0x1200004 GPSLongitude no + 0x1200005 GPSAltitudeRef no + 0x1200006 GPSAltitude no + 0x1200007 GPSTimeStamp no + 0x1200008 GPSSatellites no + 0x1200010 GPSImgDirectionRef no + 0x1200011 GPSImgDirection no + 0x1200012 GPSMapDatum no + 0x120001d GPSDateStamp no + 0x2000001 MakerNoteVersion no + 0x2000005 WhiteBalance no + 0x2000007 FocusMode string + 0x200000b WhiteBalanceFineTune no + 0x200001b CropHiSpeed int16u[7] + 0x200001e ColorSpace no + 0x200001f VRInfo Nikon VRInfo + 0x2000022 ActiveD-Lighting int16u + 0x2000023 PictureControlData Nikon PictureControl + Nikon PictureControl2 + Nikon PictureControl3 + Nikon PictureControlUnknown + 0x2000024 WorldTime Nikon WorldTime + 0x2000025 ISOInfo Nikon ISOInfo + 0x200002a VignetteControl int16u + 0x200002c UnknownInfo Nikon UnknownInfo + 0x2000032 UnknownInfo2 Nikon UnknownInfo2 + 0x2000039 LocationInfo Nikon LocationInfo + 0x2000083 LensType no + 0x2000084 Lens no + 0x2000087 FlashMode int8u + 0x2000098 LensData0100 Nikon LensData00 + LensData0101 Nikon LensData01 + LensData0201 Nikon LensData01 + LensData0204 Nikon LensData0204 + LensData0400 Nikon LensData0400 + LensData0402 Nikon LensData0402 + LensData0403 Nikon LensData0403 + LensData0800 Nikon LensData0800 + LensDataUnknown Nikon LensDataUnknown + 0x20000a7 ShutterCount no + 0x20000a8 FlashInfo0100 Nikon FlashInfo0100 + FlashInfo0102 Nikon FlashInfo0102 + FlashInfo0103 Nikon FlashInfo0103 + FlashInfo0106 Nikon FlashInfo0106 + FlashInfo0107 Nikon FlashInfo0107 + FlashInfoUnknown Nikon FlashInfoUnknown + 0x20000ab VariProgram string + 0x20000b1 HighISONoiseReduction int16u + 0x20000b7 AFInfo2 Nikon AFInfo2 + 0x20000c3 BarometerInfo Nikon BarometerInfo + +=head3 Nikon MOV Tags + +This information is found in MOV and QT videos from some Nikon cameras. + + Index1 Tag Name Writable + ------ -------- -------- + 0 Make no + 24 Model no + 38 ExposureTime no + 42 FNumber no + 50 ExposureCompensation no + 68 WhiteBalance no + 72 FocalLength no + 175 Software no + 223 ISO no + +=head3 Nikon AVI Tags + +Nikon-specific RIFF tags found in AVI videos. + + Tag ID Tag Name Writable + ------ -------- -------- + 'nctg' NikonTags Nikon AVITags + 'ncth' ThumbnailImage no + 'ncvr' NikonVers Nikon AVIVers + 'ncvw' PreviewImage no + +=head3 Nikon AVITags Tags + +These tags and the AVIVer tags below are found in proprietary-format records +of Nikon AVI videos. + + Tag ID Tag Name Writable + ------ -------- -------- + 0x0003 Make no + 0x0004 Model no + 0x0005 Software no + 0x0006 Equipment no + 0x0007 Orientation no + 0x0008 ExposureTime no + 0x0009 FNumber no + 0x000a ExposureCompensation no + 0x000b MaxApertureValue no + 0x000c MeteringMode no + 0x000f FocalLength no + 0x0010 XResolution no + 0x0011 YResolution no + 0x0012 ResolutionUnit no + 0x0013 DateTimeOriginal no + 0x0014 CreateDate no + 0x0016 Duration no + 0x0018 FocusMode no + 0x001b DigitalZoom no + 0x001d ColorMode no + 0x001e Sharpness no + 0x001f WhiteBalance no + 0x0020 NoiseReduction no + +=head3 Nikon AVIVers Tags + + Tag ID Tag Name Writable + ------ -------- -------- + 0x0001 MakerNoteType no + 0x0002 MakerNoteVersion no + +=head2 NikonCustom Tags + +Unfortunately, the NikonCustom settings are stored in a binary data block +which changes from model to model. This means that significant effort must +be spent in decoding these for each model, usually requiring hundreds of +test images from a dedicated Nikon owner. For this reason, the NikonCustom +settings have not been decoded for all models. The tables below list the +custom settings for the currently supported models. + +=head3 NikonCustom SettingsD40 Tags + +Custom settings for the Nikon D40. + + Index1 Tag Name Writable + ------ -------- -------- + 0.1 Beep int8u & 0x80 + 0.2 AFAssist int8u & 0x40 + 0.3 NoMemoryCard int8u & 0x20 + 0.4 ImageReview int8u & 0x10 + 1.1 AutoISO int8u & 0x80 + 1.2 AutoISOMax int8u & 0x30 + 1.3 AutoISOMinShutterSpeed int8u & 0x07 + 2.1 ImageReviewTime int8u & 0x07 + 3.1 MonitorOffTime int8u & 0xe0 + 3.2 MeteringTime int8u & 0x1c + 3.3 SelfTimerTime int8u & 0x03 + 3.4 RemoteOnDuration int8u & 0xc0 + 4.1 AELockButton int8u & 0x0e + 4.2 AELock int8u & 0x01 + 5.1 ShootingModeSetting int8u & 0x70 + 5.2 TimerFunctionButton int8u & 0x07 + 6.1 Metering int8u & 0x03 + 8.1 InternalFlash int8u & 0x10 + 8.2 ManualFlashOutput int8u & 0x07 + 9 FlashLevel int8s + 10.1 FocusModeSetting int8u & 0xc0 + 11.1 AFAreaModeSetting int8u & 0x30 + +=head3 NikonCustom SettingsD80 Tags + +Custom settings for the Nikon D80. + + Index1 Tag Name Writable + ------ -------- -------- + 0.1 Beep int8u & 0x80 + 0.2 AFAssist int8u & 0x40 + 0.3 NoMemoryCard int8u & 0x20 + 0.4 ImageReview int8u & 0x10 + 0.5 Illumination int8u & 0x08 + 0.6 MainDialExposureComp int8u & 0x04 + 0.7 EVStepSize int8u & 0x01 + 1.1 AutoISO int8u & 0x40 + 1.2 AutoISOMax int8u & 0x30 + 1.3 AutoISOMinShutterSpeed int8u & 0x0f + 2.1 AutoBracketSet int8u & 0xc0 + 2.2 AutoBracketOrder int8u & 0x20 + 3.1 MonitorOffTime int8u & 0xe0 + 3.2 MeteringTime int8u & 0x1c + 3.3 SelfTimerTime int8u & 0x03 + 4.1 AELockButton int8u & 0x1e + 4.2 AELock int8u & 0x01 + 4.3 RemoteOnDuration int8u & 0xc0 + 5.1 CommandDials int8u & 0x80 + 5.2 FunctionButton int8u & 0x78 + 6.1 GridDisplay int8u & 0x80 + 6.2 ViewfinderWarning int8u & 0x40 + 6.3 CenterWeightedAreaSize int8u & 0x0c + 6.4 ExposureDelayMode int8u & 0x20 + 6.5 MB-D80Batteries int8u & 0x03 + 7.1 FlashWarning int8u & 0x80 + 7.2 FlashShutterSpeed int8u & 0x78 + 7.3 AutoFP int8u & 0x04 + 7.4 ModelingFlash int8u & 0x02 + 8.1 InternalFlash int8u & 0xc0 + 8.2 ManualFlashOutput int8u & 0x07 + 9.1 RepeatingFlashOutput int8u & 0x70 + 9.2 RepeatingFlashCount int8u & 0x0f + 10.1 RepeatingFlashRate int8u & 0xf0 + 10.2 CommanderChannel int8u & 0x03 + 11.1 CommanderInternalFlash int8u & 0xc0 + 11.2 CommanderGroupAMode int8u & 0x30 + 11.3 CommanderGroupBMode int8u & 0x0c + 12.1 CommanderInternalTTLComp int8u & 0x1f + 12.2 CommanderInternalManualOutput int8u & 0xe0 + 13.1 CommanderGroupA_TTL-AAComp int8u & 0x1f + 13.2 CommanderGroupAManualOutput int8u & 0xe0 + 14.1 CommanderGroupB_TTL-AAComp int8u & 0x1f + 14.2 CommanderGroupBManualOutput int8u & 0xe0 + 15.1 CenterAFArea int8u & 0x80 + 15.2 FocusAreaSelection int8u & 0x04 + 15.3 AFAreaIllumination int8u & 0x03 + 16.1 AFAreaModeSetting int8u & 0xc0 + +=head3 NikonCustom SettingsD90 Tags + +Custom settings for the D90. + + Index1 Tag Name Writable + ------ -------- -------- + 0.1 LightSwitch int8u & 0x08 + 2.1 AFAreaModeSetting int8u & 0x60 + 2.2 CenterFocusPoint int8u & 0x10 + 2.3 AFAssist int8u & 0x01 + 2.4 AFPointIllumination int8u & 0x06 + 2.5 FocusPointWrap int8u & 0x08 + 3.1 AELockForMB-D80 int8u & 0x1c + 3.2 MB-D80BatteryType int8u & 0x03 + 4.1 Beep int8u & 0x40 + 4.2 GridDisplay int8u & 0x02 + 4.3 ISODisplay int8u & 0x0c + 4.4 ViewfinderWarning int8u & 0x01 + 4.5 NoMemoryCard int8u & 0x20 + 5.1 ScreenTips int8u & 0x04 + 5.2 FileNumberSequence int8u & 0x08 + 5.3 ShootingInfoDisplay int8u & 0xc0 + 5.4 LCDIllumination int8u & 0x20 + 6.1 EasyExposureComp int8u & 0x01 + 6.2 ReverseIndicators int8u & 0x80 + 7.1 ExposureControlStepSize int8u & 0x40 + 8.1 CenterWeightedAreaSize int8u & 0x60 + 8.2 FineTuneOptMatrixMetering int8u & 0x0f + 9.1 FineTuneOptCenterWeighted int8u & 0xf0 + 9.2 FineTuneOptSpotMetering int8u & 0x0f + 11.1 CLModeShootingSpeed int8u & 0x07 + 11.2 ExposureDelayMode int8u & 0x40 + 13.1 AutoBracketSet int8u & 0xe0 + 13.2 AutoBracketOrder int8u & 0x10 + 14.1 FuncButton int8u & 0x78 + 16.1 OKButton int8u & 0x18 + 17.1 AELockButton int8u & 0x38 + 18.1 CommandDialsReverseRotation int8u & 0x80 + 18.2 ShutterReleaseButtonAE-L int8u & 0x02 + 19.1 MeteringTime int8u & 0xf0 + 19.2 RemoteOnDuration int8u & 0x03 + 20.1 SelfTimerTime int8u & 0xc0 + 20.2 SelfTimerShotCount int8u & 0x1e + 21.1 PlaybackMonitorOffTime int8u & 0x1c + 21.2 ImageReviewTime int8u & 0xe0 + 22.1 MenuMonitorOffTime int8u & 0xe0 + 22.2 ShootingInfoMonitorOffTime int8u & 0x1c + 23.1 FlashShutterSpeed int8u & 0x0f + 24.1 InternalFlash int8u & 0xc0 + 24.2 ManualFlashOutput int8u & 0x1f + 25.1 RepeatingFlashOutput int8u & 0x70 + 25.2 RepeatingFlashCount int8u & 0x0f + 26.1 RepeatingFlashRate int8u & 0xf0 + 31.1 FlashWarning int8u & 0x80 + 31.2 CommanderInternalTTLComp int8u & 0x1f + 31.3 ModelingFlash int8u & 0x20 + 31.4 AutoFP int8u & 0x40 + 32.1 CommanderGroupA_TTLComp int8u & 0x1f + 33.1 CommanderGroupB_TTLComp int8u & 0x1f + 34.1 LiveViewAF int8u & 0xc0 + +=head3 NikonCustom SettingsD3 Tags + +Custom settings for the D3, D3S, D3X, D300 and D300S. + + Index1 Tag Name Writable + ------ -------- -------- + 0.1 CustomSettingsBank int8u & 0x03 + 0.2 CustomSettingsAllDefault int8u & 0x80 + 1.1 AF-CPrioritySelection int8u & 0xc0 + 1.2 AF-SPrioritySelection int8u & 0x20 + 1.3 AFPointSelection int8u & 0x10 + 1.4 DynamicAFArea int8u & 0x0c + 1.5 FocusTrackingLockOn int8u & 0x03 + 2.1 AFActivation int8u & 0x80 + 2.2 FocusPointWrap int8u & 0x08 + 2.3 AFPointIllumination int8u & 0x60 + AFPointIllumination int8u & 0x06 + 2.4 AFPointBrightness int8u & 0x06 + 2.5 AFAssist int8u & 0x01 + 3.1 AFOnButton int8u & 0x07 + 3.2 VerticalAFOnButton int8u & 0x70 + 3.3 AF-OnForMB-D10 int8u & 0x70 + 4.1 FocusTrackingLockOn int8u & 0x07 + 4.2 AssignBktButton int8u & 0x08 + 4.3 MultiSelectorLiveView int8u & 0xc0 + 4.4 InitialZoomLiveView int8u & 0x30 + 6.1 ISOStepSize int8u & 0xc0 + 6.2 ExposureControlStepSize int8u & 0x30 + 6.3 ExposureCompStepSize int8u & 0x0c + 6.4 EasyExposureCompensation int8u & 0x03 + 7.1 CenterWeightedAreaSize int8u & 0xe0 + 7.2 FineTuneOptCenterWeighted int8u & 0x0f + 8.1 FineTuneOptMatrixMetering int8u & 0xf0 + 8.2 FineTuneOptSpotMetering int8u & 0x0f + 9.1 MultiSelectorShootMode int8u & 0xc0 + 9.2 MultiSelectorPlaybackMode int8u & 0x30 + 9.3 InitialZoomSetting int8u & 0x0c + 9.4 MultiSelector int8u & 0x01 + 10.1 ExposureDelayMode int8u & 0x40 + 10.2 CLModeShootingSpeed int8u & 0x07 + 10.3 CHModeShootingSpeed int8u & 0x30 + 11 MaxContinuousRelease int8u + 12.1 ReverseIndicators int8u & 0x20 + 12.2 FileNumberSequence int8u & 0x02 + FileNumberSequence int8u & 0x08 + 12.3 RearDisplay int8u & 0x80 + 12.4 ViewfinderDisplay int8u & 0x40 + 12.5 BatteryOrder int8u & 0x04 + 12.6 MB-D10Batteries int8u & 0x03 + 12.7 ScreenTips int8u & 0x10 + 13.1 Beep int8u & 0xc0 + 13.2 ShootingInfoDisplay int8u & 0x30 + 13.3 GridDisplay int8u & 0x02 + 13.4 ViewfinderWarning int8u & 0x01 + 13.5 MultiSelectorPlaybackMode int8u & 0x03 + 14.1 PreviewButton int8u & 0xf8 + FuncButton int8u & 0xf8 + 14.2 PreviewButtonPlusDials int8u & 0x07 + FuncButtonPlusDials int8u & 0x07 + 15.1 FuncButton int8u & 0xf8 + PreviewButton int8u & 0xf8 + 15.2 FuncButtonPlusDials int8u & 0x07 + PreviewButtonPlusDials int8u & 0x07 + 16.1 AELockButton int8u & 0xf8 + 16.2 AELockButtonPlusDials int8u & 0x07 + 17.1 CommandDialsReverseRotation int8u & 0x80 + 17.2 CommandDialsChangeMainSub int8u & 0x40 + 17.3 CommandDialsApertureSetting int8u & 0x20 + 17.4 CommandDialsMenuAndPlayback int8u & 0x10 + 17.5 LCDIllumination int8u & 0x08 + 17.6 PhotoInfoPlayback int8u & 0x04 + 17.7 ShutterReleaseButtonAE-L int8u & 0x02 + 17.8 ReleaseButtonToUseDial int8u & 0x01 + 18.1 SelfTimerTime int8u & 0x18 + 18.2 MonitorOffTime int8u & 0x07 + 20.1 FlashSyncSpeed int8u & 0xe0 + FlashSyncSpeed int8u & 0xf0 + 20.2 FlashShutterSpeed int8u & 0x0f + 21.1 AutoBracketSet int8u & 0xc0 + AutoBracketSet int8u & 0xe0 + 21.2 AutoBracketModeM int8u & 0x30 + AutoBracketModeM int8u & 0x18 + 21.3 AutoBracketOrder int8u & 0x08 + AutoBracketOrder int8u & 0x04 + 21.4 ModelingFlash int8u & 0x01 + 22.1 NoMemoryCard int8u & 0x80 + 22.2 MeteringTime int8u & 0x0f + 23.1 InternalFlash int8u & 0xc0 + 25.1 ImageReviewTime int8u & 0xe0 + 25.2 PlaybackMonitorOffTime int8u & 0x1c + 26.1 MenuMonitorOffTime int8u & 0xe0 + 26.2 ShootingInfoMonitorOffTime int8u & 0x1c + +=head3 NikonCustom SettingsD700 Tags + +Custom settings for the D700. + + Index1 Tag Name Writable + ------ -------- -------- + 0.1 CustomSettingsBank int8u & 0x03 + 0.2 CustomSettingsAllDefault int8u & 0x80 + 1.1 AF-CPrioritySelection int8u & 0xc0 + 1.2 AF-SPrioritySelection int8u & 0x20 + 1.3 AFPointSelection int8u & 0x10 + 1.4 DynamicAFArea int8u & 0x0c + 2.1 AFActivation int8u & 0x80 + 2.2 FocusPointWrap int8u & 0x08 + 2.3 AFPointIllumination int8u & 0x06 + 2.4 AFAssist int8u & 0x01 + 3.1 FocusTrackingLockOn int8u & 0x07 + 3.2 AF-OnForMB-D10 int8u & 0x70 + 4.1 ISOStepSize int8u & 0xc0 + 4.2 ExposureControlStepSize int8u & 0x30 + 4.3 ExposureCompStepSize int8u & 0x0c + 4.4 EasyExposureCompensation int8u & 0x03 + 5.1 CenterWeightedAreaSize int8u & 0x70 + 6.1 FineTuneOptMatrixMetering int8u & 0xf0 + 6.2 FineTuneOptSpotMetering int8u & 0x0f + 7.1 ShutterReleaseButtonAE-L int8u & 0x80 + 7.2 SelfTimerTime int8u & 0x30 + 7.3 MeteringTime int8u & 0x0f + 8.1 PlaybackMonitorOffTime int8u & 0x38 + 8.2 MenuMonitorOffTime int8u & 0x07 + 9.1 ShootingInfoMonitorOffTime int8u & 0x38 + 9.2 ImageReviewTime int8u & 0x07 + 10.1 Beep int8u & 0xc0 + 10.2 ShootingInfoDisplay int8u & 0x30 + 10.3 LCDIllumination int8u & 0x08 + 10.4 ExposureDelayMode int8u & 0x04 + 10.5 GridDisplay int8u & 0x02 + 11.1 FileNumberSequence int8u & 0x40 + 11.2 CLModeShootingSpeed int8u & 0x07 + 12 MaxContinuousRelease int8u + 13.1 ScreenTips int8u & 0x08 + 13.2 BatteryOrder int8u & 0x04 + 13.3 MB-D10BatteryType int8u & 0x03 + 15.1 FlashSyncSpeed int8u & 0xf0 + 15.2 FlashShutterSpeed int8u & 0x0f + 16.1 FlashControlBuilt-in int8u & 0xc0 + 16.2 ManualFlashOutput int8u & 0x1f + 17.1 RepeatingFlashOutput int8u & 0x70 + 17.2 RepeatingFlashCount int8u & 0x0f + 18.1 RepeatingFlashRate int8u & 0xf0 + 18.2 CommanderInternalTTLChannel int8u & 0x03 + 20.1 CommanderInternalTTLCompBuiltin int8u & 0x1f + 21.1 CommanderInternalTTLCompGroupA int8u & 0x1f + 22.1 CommanderInternalTTLCompGroupB int8u & 0x1f + 26.1 AutoBracketSet int8u & 0xc0 + 26.2 AutoBracketModeM int8u & 0x30 + 26.3 AutoBracketOrder int8u & 0x08 + 26.4 ModelingFlash int8u & 0x01 + 27.1 MultiSelectorShootMode int8u & 0xc0 + 27.2 MultiSelectorPlaybackMode int8u & 0x30 + 27.3 InitialZoomSetting int8u & 0x0c + 27.4 MultiSelector int8u & 0x01 + 28.1 FuncButton int8u & 0xf8 + 29.1 PreviewButton int8u & 0xf8 + 30.1 AELockButton int8u & 0xf8 + 31.1 FuncButtonPlusDials int8u & 0x70 + 31.2 PreviewButtonPlusDials int8u & 0x07 + 32.1 AELockButtonPlusDials int8u & 0x70 + 33.1 CommandDialsReverseRotation int8u & 0x80 + 33.2 CommandDialsChangeMainSub int8u & 0x40 + 33.3 CommandDialsApertureSetting int8u & 0x20 + 33.4 CommandDialsMenuAndPlayback int8u & 0x10 + 33.5 ReverseIndicators int8u & 0x08 + 33.6 PhotoInfoPlayback int8u & 0x04 + 33.7 NoMemoryCard int8u & 0x02 + 33.8 ReleaseButtonToUseDial int8u & 0x01 + +=head3 NikonCustom SettingsD800 Tags + +Custom settings for the D800 and D800E. + + Index1 Tag Name Writable + ------ -------- -------- + 12.1 AutoBracketingSet int8u & 0xe0 + 12.2 AutoBracketOrder int8u & 0x10 + 12.3 AutoBracketingMode int8u & 0x0c + 22.1 FlashSyncSpeed int8u & 0xf0 + 22.2 FlashShutterSpeed int8u & 0x0f + 23.1 FlashControlBuilt-in int8u & 0xc0 + 23.2 ManualFlashOutput int8u & 0x1f + 24.1 RepeatingFlashOutput int8u & 0x70 + 24.2 RepeatingFlashCount int8u & 0x0f + 25.1 RepeatingFlashRate int8u & 0xf0 + 25.2 CommanderChannel int8u & 0x03 + 27.1 CommanderInternalFlash int8u & 0xc0 + 27.2 CommanderInternalManualOutput int8u & 0x1f + 28.1 CommanderGroupAMode int8u & 0xc0 + 28.2 CommanderGroupAManualOutput int8u & 0x1f + 29.1 CommanderGroupBMode int8u & 0xc0 + 29.2 CommanderGroupBManualOutput int8u & 0x1f + 30.1 ModelingFlash int8u & 0x20 + 30.2 CommanderInternalTTLComp int8u & 0x1f + 31.1 CommanderGroupA_TTL-AAComp int8u & 0x1f + 32.1 CommanderGroupB_TTL-AAComp int8u & 0x1f + +=head3 NikonCustom SettingsD810 Tags + +Custom settings for the D810. + + Index1 Tag Name Writable + ------ -------- -------- + 0.1 LightSwitch int8u & 0x08 + 0.2 CustomSettingsBank int8u & 0x03 + 1.1 AF-CPrioritySelection int8u & 0xc0 + 1.2 AF-SPrioritySelection int8u & 0x20 + 1.3 AFPointSelection int8u & 0x10 + 1.4 FocusTrackingLockOn int8u & 0x07 + 2.1 AFActivation int8u & 0x80 + 2.2 FocusPointWrap int8u & 0x08 + 2.3 AFPointBrightness int8u & 0x06 + 2.4 AFAssist int8u & 0x01 + 3.1 BatteryOrder int8u & 0x40 + 3.2 MB-D12BatteryType int8u & 0x03 + 4.1 Pitch int8u & 0x40 + 4.2 NoMemoryCard int8u & 0x20 + 4.3 ISODisplay int8u & 0x0c + 4.4 GridDisplay int8u & 0x02 + 5.1 ShootingInfoDisplay int8u & 0xc0 + 5.2 LCDIllumination int8u & 0x20 + 5.3 ElectronicFront-CurtainShutter int8u & 0x08 + 5.4 ScreenTips int8u & 0x04 + 5.5 Beep int8u & 0x03 + 6.1 ReverseIndicators int8u & 0x80 + 6.2 CommandDialsReverseRotation int8u & 0x18 + 6.3 EasyExposureCompensation int8u & 0x03 + 7.1 ExposureControlStepSize int8u & 0xc0 + 7.2 ISOStepSize int8u & 0x30 + 7.3 ExposureCompStepSize int8u & 0x0c + 8.1 CenterWeightedAreaSize int8u & 0xe0 + 8.2 FineTuneOptMatrixMetering int8u & 0x0f + 9.1 FineTuneOptCenterWeighted int8u & 0xf0 + 9.2 FineTuneOptSpotMetering int8u & 0x0f + 10.1 MultiSelectorShootMode int8u & 0xc0 + 10.2 MultiSelectorPlaybackMode int8u & 0x30 + 10.3 MultiSelector int8u & 0x01 + 11.1 ExposureDelayMode int8u & 0xc0 + 11.2 CLModeShootingSpeed int8u & 0x0f + 12.1 MaxContinuousRelease int8u + 13.1 AutoBracketSet int8u & 0xe0 + 13.2 AutoBracketOrder int8u & 0x10 + 13.3 AutoBracketModeM int8u & 0x0c + 14.1 FuncButton int8u & 0x1f + 15.1 PreviewButton int8u & 0x1f + 16.1 AssignBktButton int8u & 0x07 + 17.1 AELockButton int8u & 0x1f + 18.1 CommandDialsChangeMainSub int8u & 0xe0 + 18.2 CommandDialsMenuAndPlayback int8u & 0x18 + 18.3 CommandDialsApertureSetting int8u & 0x04 + 18.4 ShutterReleaseButtonAE-L int8u & 0x02 + 18.5 ReleaseButtonToUseDial int8u & 0x01 + 19.1 StandbyTimer int8u & 0xf0 + 20.1 SelfTimerTime int8u & 0xc0 + 20.2 SelfTimerShotInterval int8u & 0x30 + 20.3 SelfTimerShotCount int8u & 0x0f + 21.1 ImageReviewMonitorOffTime int8u & 0xe0 + 21.2 LiveViewMonitorOffTime int8u & 0x1c + 22.1 MenuMonitorOffTime int8u & 0xe0 + 22.2 ShootingInfoMonitorOffTime int8u & 0x1c + 23.1 FlashSyncSpeed int8u & 0xf0 + 23.2 FlashShutterSpeed int8u & 0x0f + 24.1 FlashControlBuilt-in int8u & 0xc0 + 31.1 ModelingFlash int8u & 0x20 + 36.1 PlaybackMonitorOffTime int8u & 0xe0 + 37.1 MultiSelectorLiveView int8u & 0xc0 + 38.1 ShutterSpeedLock int8u & 0x80 + 38.2 ApertureLock int8u & 0x40 + 38.3 MovieShutterButton int8u & 0x20 + 38.4 FlashExposureCompArea int8u & 0x04 + 40.1 MovieAELockButtonAssignment int8u & 0x0f + 41.1 MovieFunctionButton int8u & 0x70 + 41.2 MoviePreviewButton int8u & 0x07 + 42.1 FuncButtonPlusDials int8u & 0x0f + 43.1 PreviewButtonPlusDials int8u & 0x0f + 44.1 AELockButtonPlusDials int8u & 0x0f + 45.1 AssignMovieRecordButton int8u & 0x0f + 46.1 FineTuneOptHighlightWeighted int8u & 0x0f + 47.1 DynamicAreaAFDisplay int8u & 0x80 + 47.2 AFPointIllumination int8u & 0x40 + 47.3 StoreByOrientation int8u & 0x18 + 47.4 GroupAreaAFIllumination int8u & 0x04 + 48.1 MatrixMetering int8u & 0x80 + 48.2 LiveViewButtonOptions int8u & 0x30 + 48.3 AFModeRestrictions int8u & 0x03 + 49.1 LimitAFAreaModeSelection int8u & 0x7e + 50.1 AF-OnForMB-D12 int8u & 0x07 + 51.1 AssignRemoteFnButton int8u & 0x1f + 52.1 LensFocusFunctionButtons int8u & 0x3f + +=head3 NikonCustom SettingsD850 Tags + +Custom settings for the D850. + + Index1 Tag Name Writable + ------ -------- -------- + 0.2 CustomSettingsBank int8u & 0x03 + 1.1 AF-CPrioritySelection int8u & 0xc0 + 1.2 AF-SPrioritySelection int8u & 0x20 + 1.3 AFPointSelection int8u & 0x10 + 1.4 Three-DTrackingFaceDetection int8u & 0x08 + 1.5 BlockShotAFResponse int8u & 0x07 + 2.1 FocusPointWrap int8u & 0x08 + 2.2 AFPointBrightness int8u & 0x06 + 4.1 ISODisplay int8u & 0x08 + 4.2 GridDisplay int8u & 0x02 + 5.1 LCDIllumination int8u & 0x20 + 5.2 ElectronicFront-CurtainShutter int8u & 0x08 + 6.1 ReverseIndicators int8u & 0x80 + 6.2 CommandDialsReverseRotation int8u & 0x18 + 6.3 EasyExposureCompensation int8u & 0x03 + 7.1 ExposureControlStepSize int8u & 0xc0 + 7.2 ISOStepSize int8u & 0x30 + 7.3 ExposureCompStepSize int8u & 0x0c + 8.1 CenterWeightedAreaSize int8u & 0xe0 + 8.2 FineTuneOptMatrixMetering int8u & 0x0f + 9.1 FineTuneOptCenterWeighted int8u & 0xf0 + 9.2 FineTuneOptSpotMetering int8u & 0x0f + 10.1 MultiSelectorShootMode int8u & 0xe0 + 10.2 MultiSelectorPlaybackMode int8u & 0x0c + 10.3 MultiSelector int8u & 0x01 + 11.1 ExposureDelayMode int8u & 0xe0 + 11.2 CLModeShootingSpeed int8u & 0x0f + 12.1 MaxContinuousRelease int8u + 13.1 AutoBracketOrder int8u & 0x10 + 13.2 AutoBracketModeM int8u & 0x0c + 14.1 Func1Button int8u & 0x3f + 15.1 PreviewButton int8u & 0x3f + 16.1 AssignBktButton int8u & 0x07 + 18.1 CommandDialsChangeMainSub int8u & 0xe0 + 18.2 CommandDialsMenuAndPlayback int8u & 0x18 + 18.3 CommandDialsApertureSetting int8u & 0x04 + 18.4 ReleaseButtonToUseDial int8u & 0x01 + 19.1 StandbyTimer int8u & 0xf0 + 20.1 SelfTimerTime int8u & 0xc0 + 20.2 SelfTimerShotInterval int8u & 0x30 + 20.3 SelfTimerShotCount int8u & 0x0f + 21.1 ImageReviewMonitorOffTime int8u & 0xe0 + 21.2 LiveViewMonitorOffTime int8u & 0x1c + 22.1 MenuMonitorOffTime int8u & 0xe0 + 22.2 ShootingInfoMonitorOffTime int8u & 0x1c + 23.1 FlashSyncSpeed int8u & 0xf0 + 23.2 FlashShutterSpeed int8u & 0x0f + 31.1 ModelingFlash int8u & 0x20 + 36.1 PlaybackMonitorOffTime int8u & 0xe0 + 37.1 MultiSelectorLiveView int8u & 0xc0 + 38.1 ShutterSpeedLock int8u & 0x80 + 38.2 ApertureLock int8u & 0x40 + 38.3 MovieShutterButton int8u & 0x10 + 38.4 FlashExposureCompArea int8u & 0x04 + 38.5 AutoFlashISOSensitivity int8u & 0x02 + 41.1 MovieFunc1Button int8u & 0xf0 + 41.2 MoviePreviewButton int8u & 0x0f + 42.1 Func1ButtonPlusDials int8u & 0x0f + 43.1 PreviewButtonPlusDials int8u & 0x0f + 45.1 AssignMovieRecordButtonPlusDials int8u & 0x0f + 46.1 FineTuneOptHighlightWeighted int8u & 0x0f + 47.1 DynamicAreaAFDisplay int8u & 0x80 + 47.2 AFPointIllumination int8u & 0x40 + 47.3 StoreByOrientation int8u & 0x18 + 48.1 MatrixMetering int8u & 0x80 + 48.2 LiveViewButtonOptions int8u & 0x30 + 48.3 AFModeRestrictions int8u & 0x03 + 49.1 LimitAFAreaModeSelection int8u & 0x7e + 52.1 LensFocusFunctionButtons int8u & 0x3f + 66.1 VerticalMultiSelector int8u & 0xff + 67.1 AssignMB-D18FuncButton int8u & 0x3f + 68.1 AssignMB-D18FuncButtonPlusDials int8u & 0x0f + 70.1 AF-OnButton int8u & 0x3f + 71.1 SubSelector int8u & 0x80 + 72.1 SubSelectorCenter int8u & 0x3f + 73.1 SubSelectorPlusDials int8u & 0x0f + 74.1 AssignMovieSubselector int8u & 0xf0 + 75.1 AssignMovieFunc1ButtonPlusDials int8u & 0x10 + 75.2 AssignMoviePreviewButtonPlusDials int8u & 0x01 + 76.1 AssignMovieSubselectorPlusDials int8u & 0x10 + 77.1 SyncReleaseMode int8u & 0x80 + 77.2 ContinuousModeLiveView int8u & 0x40 + 78.1 Three-DTrackingWatchArea int8u & 0x80 + 78.2 SubjectMotion int8u & 0x60 + 78.3 AFActivation int8u & 0x08 + 78.4 ShutterReleaseButtonAE-L int8u & 0x03 + 79.1 AssignMB-D18AF-OnButton int8u & 0x7f + 80.1 Func2Button int8u & 0x3f + 82.1 AssignMovieFunc2Button int8u & 0x70 + +=head3 NikonCustom SettingsD5000 Tags + +Custom settings for the D5000. + + Index1 Tag Name Writable + ------ -------- -------- + 0.1 AFAreaModeSetting int8u & 0x60 + 0.2 AFAssist int8u & 0x01 + 2.1 Beep int8u & 0xc0 + 2.2 GridDisplay int8u & 0x02 + 2.3 ISODisplay int8u & 0x08 + 2.4 NoMemoryCard int8u & 0x20 + 3.1 FileNumberSequence int8u & 0x08 + 4.1 RangeFinder int8u & 0x10 + 4.2 DateImprint int8u & 0x08 + 4.3 ReverseIndicators int8u & 0x80 + 5.1 EVStepSize int8u & 0x40 + 9.1 ExposureDelayMode int8u & 0x40 + 11.1 AutoBracketSet int8u & 0xc0 + 12.1 TimerFunctionButton int8u & 0x38 + 15.1 AELockButton int8u & 0x38 + 16.1 ShutterReleaseButtonAE-L int8u & 0x02 + 16.2 CommandDialsReverseRotation int8u & 0x80 + 17.1 MeteringTime int8u & 0x70 + 17.2 RemoteOnDuration int8u & 0x03 + 18.1 SelfTimerTime int8u & 0xc0 + 18.2 SelfTimerShotCount int8u & 0x1e + 19.1 ImageReviewTime int8u & 0xe0 + 20.1 PlaybackMenusTime int8u & 0xe0 + 22.1 InternalFlash int8u & 0xc0 + 22.2 ManualFlashOutput int8u & 0x1f + 32.1 LiveViewAF int8u & 0x60 + +=head3 NikonCustom SettingsD5100 Tags + +Custom settings for the D5100. + + Index1 Tag Name Writable + ------ -------- -------- + 0.1 AF-CPrioritySelection int8u & 0x80 + 1.1 AFAssist int8u & 0x01 + 3.1 Beep int8u & 0xc0 + 3.2 NoMemoryCard int8u & 0x20 + 3.3 ISODisplay int8u & 0x08 + 4.1 FileNumberSequence int8u & 0x08 + 5.1 RangeFinder int8u & 0x10 + 5.2 ReverseIndicators int8u & 0x80 + 6.1 EVStepSize int8u & 0x40 + 10.1 ExposureDelayMode int8u & 0x40 + 12.1 AutoBracketSet int8u & 0xc0 + 13.1 TimerFunctionButton int8u & 0x38 + 16.1 AELockButton int8u & 0x38 + 17.1 ShutterReleaseButtonAE-L int8u & 0x02 + 17.2 CommandDialsReverseRotation int8u & 0x80 + 18.1 MeteringTime int8u & 0x70 + 18.2 RemoteOnDuration int8u & 0x03 + 19.1 SelfTimerTime int8u & 0xc0 + 19.2 SelfTimerShotCount int8u & 0x0f + 20.1 ImageReviewTime int8u & 0xe0 + 20.2 LiveViewMonitorOffTime int8u & 0x1c + 21.1 PlaybackMenusTime int8u & 0xe0 + 23.1 ManualFlashOutput int8u & 0x1f + +=head3 NikonCustom SettingsD5200 Tags + +Custom settings for the D5200. + + Index1 Tag Name Writable + ------ -------- -------- + 0.1 AF-CPrioritySelection int8u & 0x80 + 0.2 NumberOfFocusPoints int8u & 0x10 + 1.1 AFAssist int8u & 0x01 + 3.1 Beep int8u & 0xc0 + 3.2 NoMemoryCard int8u & 0x20 + 3.3 ISODisplay int8u & 0x08 + 4.1 FileNumberSequence int8u & 0x08 + 5.1 RangeFinder int8u & 0x04 + 5.2 ReverseExposureCompDial int8u & 0x10 + 5.3 ReverseShutterSpeedAperture int8u & 0x08 + 5.4 ReverseIndicators int8u & 0x80 + 6.1 EVStepSize int8u & 0x40 + 10.1 ExposureDelayMode int8u & 0x40 + 12.1 AutoBracketSet int8u & 0xc0 + 13.1 FunctionButton int8u & 0x1f + 16.1 AELockButton int8u & 0x0f + 17.1 ShutterReleaseButtonAE-L int8u & 0x02 + 18.1 StandbyTimer int8u & 0xe0 + 18.2 RemoteOnDuration int8u & 0x03 + 19.1 SelfTimerTime int8u & 0xc0 + 19.2 SelfTimerShotCount int8u & 0x0f + 20.1 ImageReviewTime int8u & 0xe0 + 20.2 LiveViewMonitorOffTime int8u & 0x1c + 21.1 PlaybackMenusTime int8u & 0xe0 + 23.1 InternalFlash int8u & 0xc0 + 23.2 ManualFlashOutput int8u & 0x1f + +=head3 NikonCustom SettingsD7000 Tags + +Custom settings for the D7000. + + Index1 Tag Name Writable + ------ -------- -------- + 0.1 AF-CPrioritySelection int8u & 0x80 + 0.2 AF-SPrioritySelection int8u & 0x20 + 0.3 NumberOfFocusPoints int8u & 0x10 + 0.4 FocusTrackingLockOn int8u & 0x07 + 1.1 FocusPointWrap int8u & 0x08 + 1.2 AFPointIllumination int8u & 0x06 + 1.3 AFAssist int8u & 0x01 + 2.1 BatteryOrder int8u & 0x40 + 2.2 AF-OnForMB-D11 int8u & 0x1c + 2.3 MB-D11BatteryType int8u & 0x03 + 3.1 BeepPitch int8u & 0xc0 + 3.2 NoMemoryCard int8u & 0x20 + 3.3 ISODisplay int8u & 0x0c + 3.4 GridDisplay int8u & 0x02 + 3.5 ViewfinderWarning int8u & 0x01 + 4.1 ShootingInfoDisplay int8u & 0xc0 + 4.2 LCDIllumination int8u & 0x20 + 4.3 FileNumberSequence int8u & 0x08 + 4.4 ScreenTips int8u & 0x04 + 4.5 BeepVolume int8u & 0x03 + 5.1 ReverseIndicators int8u & 0x80 + 5.2 EasyExposureCompensation int8u & 0x03 + 6.1 ExposureControlStep int8u & 0x40 + 6.2 ISOSensitivityStep int8u & 0x10 + 7.1 CenterWeightedAreaSize int8u & 0xe0 + 10.1 ExposureDelayMode int8u & 0x40 + 10.2 CLModeShootingSpeed int8u & 0x07 + 11 MaxContinuousRelease int8u + 12.1 AutoBracketSet int8u & 0xe0 + 12.2 AutoBracketOrder int8u & 0x10 + 13.1 FuncButton int8u & 0xf8 + 14.1 PreviewButton int8u & 0xf8 + 15.1 OKButton int8u & 0x18 + 16.1 AELockButton int8u & 0x38 + 17.1 CommandDialsReverseRotation int8u & 0x80 + 17.2 CommandDialsChangeMainSub int8u & 0x60 + 17.3 CommandDialsApertureSetting int8u & 0x04 + 17.4 CommandDialsMenuAndPlayback int8u & 0x18 + 17.5 ShutterReleaseButtonAE-L int8u & 0x02 + 17.6 ReleaseButtonToUseDial int8u & 0x01 + 18.1 MeteringTime int8u & 0xf0 + 18.2 RemoteOnDuration int8u & 0x03 + 19.1 SelfTimerTime int8u & 0xc0 + 19.2 SelfTimerInterval int8u & 0x30 + 19.3 SelfTimerShotCount int8u & 0x0f + 20.1 ImageReviewTime int8u & 0xe0 + 20.2 LiveViewMonitorOffTime int8u & 0x1c + 21.1 MenuMonitorOffTime int8u & 0xe0 + 21.2 ShootingInfoMonitorOffTime int8u & 0x1c + 22.1 FlashSyncSpeed int8u & 0xf0 + 22.2 FlashShutterSpeed int8u & 0x0f + 23.1 FlashControlBuilt-in int8u & 0xc0 + 23.2 ManualFlashOutput int8u & 0x1f + 24.1 RepeatingFlashOutput int8u & 0x70 + 24.2 RepeatingFlashCount int8u & 0x0f + 25.1 RepeatingFlashRate int8u & 0xf0 + 26.1 CommanderInternalTTLCompBuiltin int8u & 0x1f + 27.1 CommanderInternalTTLCompGroupA int8u & 0x1f + 28.1 CommanderInternalTTLCompGroupB int8u & 0x1f + 30.1 FlashWarning int8u & 0x80 + 30.2 ModelingFlash int8u & 0x20 + 34.1 LiveViewAFAreaMode int8u & 0x60 + 34.2 LiveViewAFMode int8u & 0x02 + 35.1 PlaybackMonitorOffTime int8u & 0xe0 + +=head3 NikonCustom SettingsD4 Tags + +Custom settings for the D4 and D4S. + + Index1 Tag Name Writable + ------ -------- -------- + 0.1 CustomSettingsBank int8u & 0x03 + 1.1 AF-CPrioritySelection int8u & 0xc0 + 1.2 AF-SPrioritySelection int8u & 0x20 + 1.3 AFPointSelection int8u & 0x10 + 1.4 FocusTrackingLockOn int8u & 0x07 + 2.1 AFActivation int8u & 0x80 + 2.2 FocusPointWrap int8u & 0x08 + 4.1 Pitch int8u & 0x40 + 4.2 NoMemoryCard int8u & 0x20 + 4.3 GridDisplay int8u & 0x02 + 5.1 ShootingInfoDisplay int8u & 0xc0 + 5.2 LCDIllumination int8u & 0x20 + 5.3 ScreenTips int8u & 0x04 + 5.4 Beep int8u & 0x03 + 6.1 ReverseIndicators int8u & 0x80 + 6.2 RearDisplay int8u & 0x40 + 6.3 ViewfinderDisplay int8u & 0x20 + 6.4 CommandDialsReverseRotation int8u & 0x18 + 6.5 EasyExposureCompensation int8u & 0x03 + 7.1 ExposureControlStepSize int8u & 0xc0 + 7.2 ISOStepSize int8u & 0x30 + 7.3 ExposureCompStepSize int8u & 0x0c + 8.1 CenterWeightedAreaSize int8u & 0xe0 + 8.2 FineTuneOptMatrixMetering int8u & 0x0f + 9.1 FineTuneOptCenterWeighted int8u & 0xf0 + 9.2 FineTuneOptSpotMetering int8u & 0x0f + 10.1 MultiSelectorShootMode int8u & 0xc0 + 10.2 MultiSelectorPlaybackMode int8u & 0x30 + 10.3 MultiSelector int8u & 0x01 + 11.1 ExposureDelayMode int8u & 0xc0 + 11.2 CHModeShootingSpeed int8u & 0x10 + 11.3 CLModeShootingSpeed int8u & 0x0f + 12 MaxContinuousRelease int8u + 13.1 AutoBracketSet int8u & 0xe0 + 13.2 AutoBracketOrder int8u & 0x10 + 13.3 AutoBracketModeM int8u & 0x0c + 14.1 FuncButton int8u & 0xf8 + 14.2 FuncButtonPlusDials int8u & 0x07 + 15.1 PreviewButton int8u & 0xf8 + 15.2 PreviewButtonPlusDials int8u & 0x07 + 16.1 AssignBktButton int8u & 0x07 + 18.1 CommandDialsChangeMainSub int8u & 0xe0 + 18.2 CommandDialsMenuAndPlayback int8u & 0x18 + 18.3 CommandDialsApertureSetting int8u & 0x04 + 18.4 ShutterReleaseButtonAE-L int8u & 0x02 + 18.5 ReleaseButtonToUseDial int8u & 0x01 + 19.1 StandbyTimer int8u & 0xf0 + 20.1 SelfTimerTime int8u & 0xc0 + 20.2 SelfTimerShotCount int8u & 0x0f + 20.3 SelfTimerShotInterval int8u & 0x30 + 21.1 ImageReviewMonitorOffTime int8u & 0xe0 + 21.2 LiveViewMonitorOffTime int8u & 0x1c + 22.1 MenuMonitorOffTime int8u & 0xe0 + 22.2 ShootingInfoMonitorOffTime int8u & 0x1c + 23.1 FlashSyncSpeed int8u & 0xf0 + 23.2 FlashShutterSpeed int8u & 0x0f + 31.1 ModelingFlash int8u & 0x20 + 36.1 PlaybackMonitorOffTime int8u & 0xe0 + 37.1 PlaybackZoom int8u & 0x01 + 38.1 ShutterSpeedLock int8u & 0x80 + 38.2 ApertureLock int8u & 0x40 + 38.3 MovieShutterButton int8u & 0x30 + 38.4 FlashExposureCompArea int8u & 0x04 + 41.1 MovieFunctionButton int8u & 0x70 + 41.2 MoviePreviewButton int8u & 0x07 + 42.1 VerticalMultiSelector int8u & 0x60 + 42.2 VerticalFuncButton int8u & 0x1f + 43.1 VerticalFuncButtonPlusDials int8u & 0xf0 + 43.2 AssignMovieRecordButton int8u & 0x07 + 46.1 DynamicAreaAFDisplay int8u & 0x80 + 46.2 AFPointIllumination int8u & 0x60 + 46.3 StoreByOrientation int8u & 0x18 + 46.4 GroupAreaAFIllumination int8u & 0x04 + 46.5 AFPointBrightness int8u & 0x03 + 47.1 AFOnButton int8u & 0x70 + 47.2 VerticalAFOnButton int8u & 0x07 + 48.1 SubSelectorAssignment int8u & 0x80 + 48.2 MovieSubSelectorAssignment int8u & 0x07 + 49.1 SubSelector int8u & 0xf8 + 49.2 SubSelectorPlusDials int8u & 0x07 + 50.1 MatrixMetering int8u & 0x80 + 50.2 LiveViewButtonOptions int8u & 0x30 + 50.3 AFModeRestrictions int8u & 0x03 + 51.1 LimitAFAreaModeSelection int8u & 0x7e + 52.1 MovieFunctionButtonPlusDials int8u & 0x10 + 52.2 MoviePreviewButtonPlusDials int8u & 0x01 + 53.1 MovieSubSelectorAssignmentPlusDials int8u & 0x10 + 54.1 AssignRemoteFnButton int8u & 0x1f + 55.1 LensFocusFunctionButtons int8u & 0x3f + +=head3 NikonCustom SettingsD5 Tags + +Custom settings for the D5. + + Index1 Tag Name Writable + ------ -------- -------- + 0.1 CustomSettingsBank int8u & 0x03 + 1.1 AF-CPrioritySelection int8u & 0xc0 + 1.2 NumberOfFocusPoints int8u & 0x10 + 1.3 Three-DTrackingFaceDetection int8u & 0x08 + 1.4 AF-SPrioritySelection int8u & 0x20 + 1.5 BlockShotAFResponse int8u & 0x07 + 2.1 FocusPointWrap int8u & 0x08 + 2.2 AFPointBrightness int8u & 0x06 + 4.1 ISODisplay int8u & 0x08 + 4.2 GridDisplay int8u & 0x02 + 5.1 LCDIllumination int8u & 0x20 + 5.2 ElectronicFront-CurtainShutter int8u & 0x08 + 6.1 ReverseIndicators int8u & 0x80 + 6.2 CommandDialsReverseRotation int8u & 0x18 + 6.3 EasyExposureCompensation int8u & 0x03 + 7.1 ExposureControlStepSize int8u & 0xc0 + 7.2 ISOStepSize int8u & 0x30 + 7.3 ExposureCompStepSize int8u & 0x0c + 8.1 CenterWeightedAreaSize int8u & 0xe0 + 8.2 FineTuneOptMatrixMetering int8u & 0x0f + 9.1 FineTuneOptCenterWeighted int8u & 0xf0 + 9.2 FineTuneOptSpotMetering int8u & 0x0f + 10.1 MultiSelectorShootMode int8u & 0xe0 + 10.3 MultiSelector int8u & 0x01 + 11.1 ExposureDelayMode int8u & 0xc0 + 11.2 CLModeShootingSpeed int8u & 0x0f + 12.1 MaxContinuousRelease int8u + 13.1 AutoBracketOrder int8u & 0x10 + 13.2 AutoBracketModeM int8u & 0x0c + 14.1 Func1Button int8u & 0x3f + 15.1 PreviewButton int8u & 0x3f + 16.1 AssignBktButton int8u & 0x07 + 18.1 CommandDialsChangeMainSub int8u & 0xe0 + 18.2 CommandDialsMenuAndPlayback int8u & 0x18 + 18.3 CommandDialsApertureSetting int8u & 0x04 + 18.4 ReleaseButtonToUseDial int8u & 0x01 + 19.1 StandbyTimer int8u & 0xf0 + 20.1 SelfTimerTime int8u & 0xc0 + 20.2 SelfTimerShotInterval int8u & 0x30 + 20.3 SelfTimerShotCount int8u & 0x0f + 21.1 ImageReviewMonitorOffTime int8u & 0xe0 + 21.2 LiveViewMonitorOffTime int8u & 0x1c + 22.1 MenuMonitorOffTime int8u & 0xe0 + 22.2 ShootingInfoMonitorOffTime int8u & 0x1c + 23.1 FlashSyncSpeed int8u & 0xf0 + 23.2 FlashShutterSpeed int8u & 0x0f + 31.1 ModelingFlash int8u & 0x20 + 36.1 PlaybackMonitorOffTime int8u & 0xe0 + 37.1 MultiSelectorLiveView int8u & 0xc0 + 38.1 ShutterSpeedLock int8u & 0x80 + 38.2 ApertureLock int8u & 0x40 + 38.3 MovieShutterButton int8u & 0x10 + 38.4 FlashExposureCompArea int8u & 0x04 + 38.5 AutoFlashISOSensitivity int8u & 0x02 + 41.1 MovieFunc1Button int8u & 0xf0 + 41.2 MoviePreviewButton int8u & 0x0f + 42.1 Func1ButtonPlusDials int8u & 0x0f + 43.1 PreviewButtonPlusDials int8u & 0x0f + 45.1 AssignMovieRecordButtonPlusDials int8u & 0x0f + 46.1 FineTuneOptHighlightWeighted int8u & 0x0f + 47.1 DynamicAreaAFDisplay int8u & 0x80 + 47.2 AFPointIllumination int8u & 0x40 + 47.3 StoreByOrientation int8u & 0x18 + 48.1 MatrixMetering int8u & 0x80 + 48.2 LiveViewButtonOptions int8u & 0x30 + 48.3 AFModeRestrictions int8u & 0x03 + 49.1 LimitAFAreaModeSelection int8u & 0x7e + 52.1 LensFocusFunctionButtons int8u & 0x3f + 66.1 VerticalMultiSelector int8u & 0xff + 67.1 VerticalFuncButton int8u & 0x3f + 68.1 VerticalFuncPlusDials int8u & 0x0f + 70.1 AF-OnButton int8u & 0x3f + 71.1 SubSelector int8u & 0x80 + 72.1 SubSelectorCenter int8u & 0x3f + 73.1 SubSelectorPlusDials int8u & 0x0f + 74.1 AssignMovieSubselector int8u & 0xf0 + 75.1 AssignMovieFunc1ButtonPlusDials int8u & 0x10 + 75.2 AssignMoviePreviewButtonPlusDials int8u & 0x01 + 76.1 AssignMovieSubselectorPlusDials int8u & 0x10 + 77.1 SyncReleaseMode int8u & 0x80 + 78.1 Three-DTrackingWatchArea int8u & 0x80 + 78.2 SubjectMotion int8u & 0x60 + 78.3 AFActivation int8u & 0x08 + 78.4 ShutterReleaseButtonAE-L int8u & 0x03 + 79.1 VerticalAFOnButton int8u & 0x7f + 80.1 Func2Button int8u & 0x3f + 81.1 Func2ButtonPlusDials int8u & 0x0f + 82.1 AssignMovieFunc2Button int8u & 0x70 + 83.1 Func3Button int8u & 0x03 + +=head3 NikonCustom SettingsD500 Tags + +Custom settings for the D500. + + Index1 Tag Name Writable + ------ -------- -------- + 0.1 CustomSettingsBank int8u & 0x03 + 1.1 AF-CPrioritySelection int8u & 0xc0 + 1.2 NumberOfFocusPoints int8u & 0x10 + 1.3 Three-DTrackingFaceDetection int8u & 0x08 + 1.4 AF-SPrioritySelection int8u & 0x20 + 1.5 BlockShotAFResponse int8u & 0x07 + 2.1 FocusPointWrap int8u & 0x08 + 2.2 AFPointBrightness int8u & 0x06 + 4.1 ISODisplay int8u & 0x08 + 4.2 GridDisplay int8u & 0x02 + 5.1 LCDIllumination int8u & 0x20 + 5.2 ElectronicFront-CurtainShutter int8u & 0x08 + 6.1 ReverseIndicators int8u & 0x80 + 6.2 CommandDialsReverseRotation int8u & 0x18 + 6.3 EasyExposureCompensation int8u & 0x03 + 7.1 ExposureControlStepSize int8u & 0xc0 + 7.2 ISOStepSize int8u & 0x30 + 7.3 ExposureCompStepSize int8u & 0x0c + 8.1 CenterWeightedAreaSize int8u & 0xe0 + 8.2 FineTuneOptMatrixMetering int8u & 0x0f + 9.1 FineTuneOptCenterWeighted int8u & 0xf0 + 9.2 FineTuneOptSpotMetering int8u & 0x0f + 10.1 MultiSelectorShootMode int8u & 0xe0 + 10.2 MultiSelectorPlaybackMode int8u & 0x0c + 10.3 MultiSelector int8u & 0x01 + 11.1 ExposureDelayMode int8u & 0xc0 + 11.2 CLModeShootingSpeed int8u & 0x0f + 12.1 MaxContinuousRelease int8u + 13.1 AutoBracketOrder int8u & 0x10 + 13.2 AutoBracketModeM int8u & 0x0c + 14.1 Func1Button int8u & 0x3f + 15.1 PreviewButton int8u & 0x3f + 16.1 AssignBktButton int8u & 0x07 + 18.1 CommandDialsChangeMainSub int8u & 0xe0 + 18.2 CommandDialsMenuAndPlayback int8u & 0x18 + 18.3 CommandDialsApertureSetting int8u & 0x04 + 18.4 ReleaseButtonToUseDial int8u & 0x01 + 19.1 StandbyTimer int8u & 0xf0 + 20.1 SelfTimerTime int8u & 0xc0 + 20.2 SelfTimerShotInterval int8u & 0x30 + 20.3 SelfTimerShotCount int8u & 0x0f + 21.1 ImageReviewMonitorOffTime int8u & 0xe0 + 21.2 LiveViewMonitorOffTime int8u & 0x1c + 22.1 MenuMonitorOffTime int8u & 0xe0 + 22.2 ShootingInfoMonitorOffTime int8u & 0x1c + 23.1 FlashSyncSpeed int8u & 0xf0 + 23.2 FlashShutterSpeed int8u & 0x0f + 31.1 ModelingFlash int8u & 0x20 + 36.1 PlaybackMonitorOffTime int8u & 0xe0 + 37.1 MultiSelectorLiveView int8u & 0xc0 + 38.1 ShutterSpeedLock int8u & 0x80 + 38.2 ApertureLock int8u & 0x40 + 38.3 MovieShutterButton int8u & 0x10 + 38.4 FlashExposureCompArea int8u & 0x04 + 38.5 AutoFlashISOSensitivity int8u & 0x02 + 41.1 MovieFunc1Button int8u & 0xf0 + 41.2 MoviePreviewButton int8u & 0x0f + 42.1 Func1ButtonPlusDials int8u & 0x0f + 43.1 PreviewButtonPlusDials int8u & 0x0f + 45.1 AssignMovieRecordButtonPlusDials int8u & 0x0f + 46.1 FineTuneOptHighlightWeighted int8u & 0x0f + 47.1 DynamicAreaAFDisplay int8u & 0x80 + 47.2 AFPointIllumination int8u & 0x40 + 47.3 StoreByOrientation int8u & 0x18 + 47.4 GroupAreaAFIllumination int8u & 0x04 + 48.1 MatrixMetering int8u & 0x80 + 48.2 LiveViewButtonOptions int8u & 0x30 + 48.3 AFModeRestrictions int8u & 0x03 + 49.1 LimitAFAreaModeSelection int8u & 0x7e + 52.1 LensFocusFunctionButtons int8u & 0x3f + 66.1 VerticalMultiSelector int8u & 0xff + 67.1 AssignMB-D17FuncButton int8u & 0x3f + 68.1 AssignMB-D17FuncButtonPlusDials int8u & 0x0f + 70.1 AF-OnButton int8u & 0x3f + 71.1 SubSelector int8u & 0x80 + 72.1 SubSelectorCenter int8u & 0x3f + 73.1 SubSelectorPlusDials int8u & 0x0f + 74.1 AssignMovieSubselector int8u & 0xf0 + 75.1 AssignMovieFunc1ButtonPlusDials int8u & 0x10 + 75.2 AssignMoviePreviewButtonPlusDials int8u & 0x01 + 76.1 AssignMovieSubselectorPlusDials int8u & 0x10 + 77.1 SyncReleaseMode int8u & 0x80 + 78.1 Three-DTrackingWatchArea int8u & 0x80 + 78.2 SubjectMotion int8u & 0x60 + 78.3 AFActivation int8u & 0x08 + 78.4 ShutterReleaseButtonAE-L int8u & 0x03 + 79.1 AssignMB-D17AF-OnButton int8u & 0x7f + 80.1 Func2Button int8u & 0x3f + 82.1 AssignMovieFunc2Button int8u & 0x70 + +=head3 NikonCustom SettingsD610 Tags + +Custom settings for the D610. + + Index1 Tag Name Writable + ------ -------- -------- + 0.1 AF-CPrioritySelection int8u & 0x80 + 0.2 AF-SPrioritySelection int8u & 0x20 + 0.3 NumberOfFocusPoints int8u & 0x10 + 0.4 FocusTrackingLockOn int8u & 0x07 + 1.1 FocusPointWrap int8u & 0x08 + 1.2 AFPointIllumination int8u & 0x06 + 1.3 AFAssist int8u & 0x01 + 5.1 EasyExposureCompensation int8u & 0x03 + 6.1 ExposureControlStep int8u & 0x40 + 6.2 ISOSensitivityStep int8u & 0x10 + 7.1 CenterWeightedAreaSize int8u & 0xe0 + 7.2 FineTuneOptMatrixMetering int8u & 0x0f + 8.1 FineTuneOptCenterWeighted int8u & 0xf0 + 8.2 FineTuneOptSpotMetering int8u & 0x0f + 17.1 ShutterReleaseButtonAE-L int8u & 0x02 + 18.1 StandbyTimer int8u & 0xf0 + 18.2 RemoteOnDuration int8u & 0x03 + 19.1 SelfTimerTime int8u & 0xc0 + 19.2 SelfTimerShotInterval int8u & 0x30 + 19.3 SelfTimerShotCount int8u & 0x0f + 20.1 ImageReviewMonitorOffTime int8u & 0xe0 + 20.2 LiveViewMonitorOffTime int8u & 0x1c + 21.1 MenuMonitorOffTime int8u & 0xe0 + 21.2 ShootingInfoMonitorOffTime int8u & 0x1c + 35.1 PlaybackMonitorOffTime int8u & 0xe0 + +=head2 NikonCapture Tags + +This information is written by the Nikon Capture software in tag 0x0e01 of +the maker notes of NEF images. + + Tag ID Tag Name Writable + ------ -------- -------- + 0x8ae85e LCHEditor int8u + 0x83a1a25 HistogramXML undef + 0xc89224b ColorAberrationControl int8u + 0x116fea21 HighlightData NikonCapture HighlightData + 0x2175eb78 D-LightingHQ int8u + 0x2fc08431 StraightenAngle double + 0x374233e0 CropData NikonCapture CropData + 0x39c456ac PictureCtrl NikonCapture PictureCtrl + 0x3cfc73c6 RedEyeData NikonCapture RedEyeData + 0x3d136244 EditVersionName string + 0x416391c6 QuickFix int8u + 0x56a54260 Exposure NikonCapture Exposure + 0x5f0e7d23 ColorBooster int8u + 0x6a6e36b6 D-LightingHQSelected int8u + 0x753dcbc0 NoiseReduction int8u + 0x76a43200 UnsharpMask int8u + 0x76a43201 Curves int8u + 0x76a43202 ColorBalanceAdj int8u + 0x76a43203 AdvancedRaw int8u + 0x76a43204 WhiteBalanceAdj int8u + 0x76a43205 VignetteControl int8u + 0x76a43206 FlipHorizontal int8u + 0x76a43207 Rotation int16u + 0x84589434 BrightnessData NikonCapture Brightness + 0x890ff591 D-LightingHQData NikonCapture DLightingHQ + 0x926f13e0 NoiseReductionData NikonCapture NoiseReduction + 0x9ef5f6e0 IPTCData IPTC + 0xab5eca5e PhotoEffects int8u + 0xac6bd5c0 VignetteControlIntensity int16s + 0xb0384e1e PhotoEffectsData NikonCapture PhotoEffects + 0xb999a36f ColorBoostData NikonCapture ColorBoost + 0xbf3c6c20 WBAdjData NikonCapture WBAdjData + 0xce5554aa D-LightingHS int8u + 0xe2173c47 PictureControl int8u + 0xe37b4337 D-LightingHSData NikonCapture DLightingHS + 0xe42b5161 UnsharpData NikonCapture UnsharpData + 0xe9651831 PhotoEffectHistoryXML undef + 0xfe28a44f AutoRedEye int8u + 0xfe443a45 ImageDustOff int8u + +=head3 NikonCapture HighlightData Tags + + Index1 Tag Name Writable + ------ -------- -------- + 0 ShadowProtection int8s + 1 SaturationAdj int8s + 6 HighlightProtection int8s + +=head3 NikonCapture CropData Tags + + Index1 Tag Name Writable + ------ -------- -------- + 30 CropLeft double + 38 CropTop double + 46 CropRight double + 54 CropBottom double + 142 CropOutputWidthInches double + 150 CropOutputHeightInches double + 158 CropScaledResolution double + 174 CropSourceResolution double + 182 CropOutputResolution double + 190 CropOutputScale double + 198 CropOutputWidth double + 206 CropOutputHeight double + 214 CropOutputPixels double + +=head3 NikonCapture PictureCtrl Tags + + Index1 Tag Name Writable + ------ -------- -------- + 0 PictureControlActive int8u + 19 PictureControlMode string[16] + 42 QuickAdjust int8u + 43 SharpeningAdj int8u + 44 ContrastAdj int8u + 45 BrightnessAdj int8u + 46 SaturationAdj int8u + 47 HueAdj int8u + +=head3 NikonCapture RedEyeData Tags + + Index1 Tag Name Writable + ------ -------- -------- + 0 RedEyeCorrection int8u + +=head3 NikonCapture Exposure Tags + + Index1 Tag Name Writable + ------ -------- -------- + 0 ExposureAdj int16s + 18 ExposureAdj2 double + 36 ActiveD-Lighting int8u + 37 ActiveD-LightingMode int8u + +=head3 NikonCapture Brightness Tags + + Index1 Tag Name Writable + ------ -------- -------- + 0 BrightnessAdj double + 8 EnhanceDarkTones int8u + +=head3 NikonCapture DLightingHQ Tags + + Index4 Tag Name Writable + ------ -------- -------- + 0 D-LightingHQShadow int32u + 1 D-LightingHQHighlight int32u + 2 D-LightingHQColorBoost int32u + +=head3 NikonCapture NoiseReduction Tags + + Index1 Tag Name Writable + ------ -------- -------- + 4 EdgeNoiseReduction int8u + 5 ColorMoireReductionMode int8u + 9 NoiseReductionIntensity int32u + 13 NoiseReductionSharpness int32u + 17 NoiseReductionMethod int16u + 21 ColorMoireReduction int8u + 23 NoiseReduction int8u + 24 ColorNoiseReductionIntensity int32u + 28 ColorNoiseReductionSharpness int32u + +=head3 NikonCapture PhotoEffects Tags + + Index1 Tag Name Writable + ------ -------- -------- + 0 PhotoEffectsType int8u + 4 PhotoEffectsRed int16s + 6 PhotoEffectsGreen int16s + 8 PhotoEffectsBlue int16s + +=head3 NikonCapture ColorBoost Tags + + Index1 Tag Name Writable + ------ -------- -------- + 0 ColorBoostType int8u + 1 ColorBoostLevel int32u + +=head3 NikonCapture WBAdjData Tags + + Index1 Tag Name Writable + ------ -------- -------- + 0 WBAdjRedBalance double + 8 WBAdjBlueBalance double + 16 WBAdjMode int8u + 20 WBAdjLighting int16u + 24 WBAdjTemperature int16u + 37 WBAdjTint int32s + +=head3 NikonCapture DLightingHS Tags + + Index4 Tag Name Writable + ------ -------- -------- + 0 D-LightingHSAdjustment int32u + 1 D-LightingHSColorBoost int32u + +=head3 NikonCapture UnsharpData Tags + + Index1 Tag Name Writable + ------ -------- -------- + 0 UnsharpCount int8u + 19 Unsharp1Color int16u + 23 Unsharp1Intensity int16u + 25 Unsharp1HaloWidth int16u + 27 Unsharp1Threshold int8u + 46 Unsharp2Color int16u + 50 Unsharp2Intensity int16u + 52 Unsharp2HaloWidth int16u + 54 Unsharp2Threshold int8u + 73 Unsharp3Color int16u + 77 Unsharp3Intensity int16u + 79 Unsharp3HaloWidth int16u + 81 Unsharp3Threshold int8u + 100 Unsharp4Color int16u + 104 Unsharp4Intensity int16u + 106 Unsharp4HaloWidth int16u + 108 Unsharp4Threshold int8u + +=head2 Nintendo Tags + + Tag ID Tag Name Writable + ------ -------- -------- + 0x1101 CameraInfo Nintendo CameraInfo + +=head3 Nintendo CameraInfo Tags + + Index1 Tag Name Writable + ------ -------- -------- + 0 ModelID undef[4] + 8 TimeStamp int32u + 24 InternalSerialNumber undef[4] + 40 Parallax float + 48 Category int16u + +=head2 Olympus Tags + +Tags 0x0000 through 0x0103 are used by some older Olympus cameras, and are +the same as Konica/Minolta tags. These tags are also used for some models +from other brands such as Acer, BenQ, Epson, Hitachi, HP, Maginon, Minolta, +Pentax, Ricoh, Samsung, Sanyo, SeaLife, Sony, Supra and Vivitar. + + Tag ID Tag Name Writable + ------ -------- -------- + 0x0000 MakerNoteVersion undef + 0x0001 MinoltaCameraSettingsOld Minolta CameraSettings + 0x0003 MinoltaCameraSettings Minolta CameraSettings + 0x0040 CompressedImageSize int32u + 0x0081 PreviewImageData no + 0x0088 PreviewImageStart no + 0x0089 PreviewImageLength no + 0x0100 ThumbnailImage undef + 0x0104 BodyFirmwareVersion string + 0x0200 SpecialMode int32u[3]~ + 0x0201 Quality int16u~ + 0x0202 Macro int16u + 0x0203 BWMode int16u + 0x0204 DigitalZoom rational64u + 0x0205 FocalPlaneDiagonal rational64u + 0x0206 LensDistortionParams int16s[6] + 0x0207 CameraType string + 0x0208 TextInfo Olympus TextInfo + 0x0209 CameraID string + 0x020b EpsonImageWidth int16u + 0x020c EpsonImageHeight int16u + 0x020d EpsonSoftware string + 0x0280 PreviewImage int8u + 0x0300 PreCaptureFrames int16u + 0x0301 WhiteBoard int16u + 0x0302 OneTouchWB int16u + 0x0303 WhiteBalanceBracket int16u + 0x0304 WhiteBalanceBias int16u + 0x0401 BlackLevel int32u[4] + 0x0403 SceneMode int16u + 0x0404 SerialNumber string + 0x0405 Firmware string + 0x0e00 PrintIM PrintIM + 0x0f00 DataDump no + 0x0f01 DataDump2 no + 0x0f04 ZoomedPreviewStart int32u* + 0x0f05 ZoomedPreviewLength int32u* + 0x0f06 ZoomedPreviewSize int16u[2] + 0x1000 ShutterSpeedValue rational64s + 0x1001 ISOValue rational64s + 0x1002 ApertureValue rational64s + 0x1003 BrightnessValue rational64s + 0x1004 FlashMode int16u + 0x1005 FlashDevice int16u + 0x1006 ExposureCompensation rational64s + 0x1007 SensorTemperature int16s + 0x1008 LensTemperature int16s + 0x1009 LightCondition int16u + 0x100a FocusRange int16u + 0x100b FocusMode int16u + 0x100c ManualFocusDistance rational64u + 0x100d ZoomStepCount int16u + 0x100e FocusStepCount int16u + 0x100f Sharpness int16u + 0x1010 FlashChargeLevel int16u + 0x1011 ColorMatrix int16u[9] + 0x1012 BlackLevel int16u[4] + 0x1013 ColorTemperatureBG? int16u + 0x1014 ColorTemperatureRG? int16u + 0x1015 WBMode int16u[2] + 0x1017 RedBalance int16u[2] + 0x1018 BlueBalance int16u[2] + 0x1019 ColorMatrixNumber int16u + 0x101a SerialNumber string + 0x101b ExternalFlashAE1_0? int32u + 0x101c ExternalFlashAE2_0? int32u + 0x101d InternalFlashAE1_0? int32u + 0x101e InternalFlashAE2_0? int32u + 0x101f ExternalFlashAE1? int32u + 0x1020 ExternalFlashAE2? int32u + 0x1021 InternalFlashAE1? int32u + 0x1022 InternalFlashAE2? int32u + 0x1023 FlashExposureComp rational64s + 0x1024 InternalFlashTable int16u + 0x1025 ExternalFlashGValue rational64s + 0x1026 ExternalFlashBounce int16u + 0x1027 ExternalFlashZoom int16u + 0x1028 ExternalFlashMode int16u + 0x1029 Contrast int16u + 0x102a SharpnessFactor int16u + 0x102b ColorControl int16u[6] + 0x102c ValidBits int16u[2] + 0x102d CoringFilter int16u + 0x102e OlympusImageWidth int32u + 0x102f OlympusImageHeight int32u + 0x1030 SceneDetect int16u + 0x1031 SceneArea? int32u[8] + 0x1033 SceneDetectData? int32u[720] + 0x1034 CompressionRatio rational64u + 0x1035 PreviewImageValid int32u + 0x1036 PreviewImageStart int32u* + 0x1037 PreviewImageLength int32u* + 0x1038 AFResult int16u + 0x1039 CCDScanMode int16u + 0x103a NoiseReduction int16u + 0x103b FocusStepInfinity int16u + 0x103c FocusStepNear int16u + 0x103d LightValueCenter rational64s + 0x103e LightValuePeriphery rational64s + 0x103f FieldCount? int16u + 0x2010 Equipment Olympus Equipment + EquipmentIFD Olympus Equipment + 0x2020 CameraSettings Olympus CameraSettings + CameraSettingsIFD Olympus CameraSettings + 0x2030 RawDevelopment Olympus RawDevelopment + RawDevelopmentIFD Olympus RawDevelopment + 0x2031 RawDev2 Olympus RawDevelopment2 + RawDev2IFD Olympus RawDevelopment2 + 0x2040 ImageProcessing Olympus ImageProcessing + ImageProcessingIFD Olympus ImageProcessing + 0x2050 FocusInfo Olympus FocusInfo + FocusInfoIFD Olympus FocusInfo + CameraParameters undef + 0x2100 Olympus2100 Olympus FE + Olympus2100IFD Olympus FE + 0x2200 Olympus2200 Olympus FE + Olympus2200IFD Olympus FE + 0x2300 Olympus2300 Olympus FE + Olympus2300IFD Olympus FE + 0x2400 Olympus2400 Olympus FE + Olympus2400IFD Olympus FE + 0x2500 Olympus2500 Olympus FE + Olympus2500IFD Olympus FE + 0x2600 Olympus2600 Olympus FE + Olympus2600IFD Olympus FE + 0x2700 Olympus2700 Olympus FE + Olympus2700IFD Olympus FE + 0x2800 Olympus2800 Olympus FE + Olympus2800IFD Olympus FE + 0x2900 Olympus2900 Olympus FE + Olympus2900IFD Olympus FE + 0x3000 RawInfo Olympus RawInfo + RawInfoIFD Olympus RawInfo + 0x4000 MainInfo Olympus + MainInfoIFD Olympus + 0x5000 UnknownInfo Olympus UnknownInfo + UnknownInfoIFD Olympus UnknownInfo + +=head3 Olympus TextInfo Tags + +This information is in text format (similar to APP12 information, but with +spaces instead of linefeeds). Below are tags which have been observed, but +any information found here will be extracted, even if the tag is not listed. + + Tag ID Tag Name Writable + ------ -------- -------- + 'Resolution' Resolution no + 'Type' CameraType no + +=head3 Olympus Equipment Tags + + Tag ID Tag Name Writable + ------ -------- -------- + 0x0000 EquipmentVersion undef[4] + 0x0100 CameraType2 string[6] + 0x0101 SerialNumber string[32] + 0x0102 InternalSerialNumber string[32] + 0x0103 FocalPlaneDiagonal rational64u + 0x0104 BodyFirmwareVersion int32u + 0x0201 LensType int8u[6] + 0x0202 LensSerialNumber string[32] + 0x0203 LensModel string + 0x0204 LensFirmwareVersion int32u + 0x0205 MaxApertureAtMinFocal int16u + 0x0206 MaxApertureAtMaxFocal int16u + 0x0207 MinFocalLength int16u + 0x0208 MaxFocalLength int16u + 0x020a MaxAperture int16u + 0x020b LensProperties int16u + 0x0301 Extender int8u[6] + 0x0302 ExtenderSerialNumber string[32] + 0x0303 ExtenderModel string + 0x0304 ExtenderFirmwareVersion int32u + 0x0403 ConversionLens string + 0x1000 FlashType int16u + 0x1001 FlashModel int16u + 0x1002 FlashFirmwareVersion int32u + 0x1003 FlashSerialNumber string[32] + +=head3 Olympus CameraSettings Tags + + Tag ID Tag Name Writable + ------ -------- -------- + 0x0000 CameraSettingsVersion undef[4] + 0x0100 PreviewImageValid int32u + 0x0101 PreviewImageStart int32u* + 0x0102 PreviewImageLength int32u* + 0x0200 ExposureMode int16u + 0x0201 AELock int16u + 0x0202 MeteringMode int16u + 0x0203 ExposureShift rational64s + 0x0204 NDFilter yes + 0x0300 MacroMode int16u + 0x0301 FocusMode int16u[n] + 0x0302 FocusProcess int16u[n] + 0x0303 AFSearch int16u + 0x0304 AFAreas int32u[64]~ + 0x0305 AFPointSelected rational64s[5] + 0x0306 AFFineTune int8u + 0x0307 AFFineTuneAdj int16s[3] + 0x0400 FlashMode int16u + 0x0401 FlashExposureComp rational64s + 0x0403 FlashRemoteControl int16u + 0x0404 FlashControlMode int16u[n] + 0x0405 FlashIntensity rational64s[n] + 0x0406 ManualFlashStrength rational64s[n] + 0x0500 WhiteBalance2 int16u + 0x0501 WhiteBalanceTemperature int16u + 0x0502 WhiteBalanceBracket int16s + 0x0503 CustomSaturation int16s[3]~ + 0x0504 ModifiedSaturation int16u + 0x0505 ContrastSetting int16s[3] + 0x0506 SharpnessSetting int16s[3] + 0x0507 ColorSpace int16u + 0x0509 SceneMode int16u + 0x050a NoiseReduction int16u + 0x050b DistortionCorrection int16u + 0x050c ShadingCompensation int16u + 0x050d CompressionFactor rational64u + 0x050f Gradation int16s[n] + 0x0520 PictureMode int16u[n] + 0x0521 PictureModeSaturation int16s[3] + 0x0522 PictureModeHue? int16s + 0x0523 PictureModeContrast int16s[3] + 0x0524 PictureModeSharpness int16s[3] + 0x0525 PictureModeBWFilter int16s + 0x0526 PictureModeTone int16s + 0x0527 NoiseFilter int16s[3] + 0x0529 ArtFilter int16u[4] + 0x052c MagicFilter int16u[4] + 0x052d PictureModeEffect int16s[3] + 0x052e ToneLevel yes + 0x052f ArtFilterEffect int16u[20] + 0x0532 ColorCreatorEffect int16s[6] + 0x0537 MonochromeProfileSettings int16s[6] + 0x0538 FilmGrainEffect int16s + 0x0539 ColorProfileSettings int16s[14] + 0x053a MonochromeVignetting int16s + 0x053b MonochromeColor int16s + 0x0600 DriveMode int16u[n]~ + 0x0601 PanoramaMode int16u~ + 0x0603 ImageQuality2 int16u + 0x0604 ImageStabilization int32u + 0x0804 StackedImage int32u[2] + 0x0900 ManometerPressure int16u + 0x0901 ManometerReading int32s[2] + 0x0902 ExtendedWBDetect int16u + 0x0903 RollAngle int16s[2] + 0x0904 PitchAngle int16s[2] + 0x0908 DateTimeUTC string + +=head3 Olympus RawDevelopment Tags + + Tag ID Tag Name Writable + ------ -------- -------- + 0x0000 RawDevVersion undef[4] + 0x0100 RawDevExposureBiasValue rational64s + 0x0101 RawDevWhiteBalanceValue int16u + 0x0102 RawDevWBFineAdjustment int16s + 0x0103 RawDevGrayPoint int16u[3] + 0x0104 RawDevSaturationEmphasis int16s[3] + 0x0105 RawDevMemoryColorEmphasis int16u + 0x0106 RawDevContrastValue int16s[3] + 0x0107 RawDevSharpnessValue int16s[3] + 0x0108 RawDevColorSpace int16u + 0x0109 RawDevEngine int16u + 0x010a RawDevNoiseReduction int16u + 0x010b RawDevEditStatus int16u + 0x010c RawDevSettings int16u + +=head3 Olympus RawDevelopment2 Tags + + Tag ID Tag Name Writable + ------ -------- -------- + 0x0000 RawDevVersion undef[4] + 0x0100 RawDevExposureBiasValue rational64s + 0x0101 RawDevWhiteBalance int16u + 0x0102 RawDevWhiteBalanceValue int16u + 0x0103 RawDevWBFineAdjustment int16s + 0x0104 RawDevGrayPoint int16u[3] + 0x0105 RawDevContrastValue int16s[3] + 0x0106 RawDevSharpnessValue int16s[3] + 0x0107 RawDevSaturationEmphasis int16s[3] + 0x0108 RawDevMemoryColorEmphasis int16u + 0x0109 RawDevColorSpace int16u + 0x010a RawDevNoiseReduction int16u + 0x010b RawDevEngine int16u + 0x010c RawDevPictureMode int16u + 0x010d RawDevPMSaturation int16s[3] + 0x010e RawDevPMContrast int16s[3] + 0x010f RawDevPMSharpness int16s[3] + 0x0110 RawDevPM_BWFilter int16u + 0x0111 RawDevPMPictureTone int16u + 0x0112 RawDevGradation int16s[3] + 0x0113 RawDevSaturation3 int16s[3] + 0x0119 RawDevAutoGradation int16u + 0x0120 RawDevPMNoiseFilter int16u + 0x0121 RawDevArtFilter int16u[4] + +=head3 Olympus ImageProcessing Tags + + Tag ID Tag Name Writable + ------ -------- -------- + 0x0000 ImageProcessingVersion undef[4] + 0x0100 WB_RBLevels int16u[2] + 0x0102 WB_RBLevels3000K int16u[2] + 0x0103 WB_RBLevels3300K int16u[2] + 0x0104 WB_RBLevels3600K int16u[2] + 0x0105 WB_RBLevels3900K int16u[2] + 0x0106 WB_RBLevels4000K int16u[2] + 0x0107 WB_RBLevels4300K int16u[2] + 0x0108 WB_RBLevels4500K int16u[2] + 0x0109 WB_RBLevels4800K int16u[2] + 0x010a WB_RBLevels5300K int16u[2] + 0x010b WB_RBLevels6000K int16u[2] + 0x010c WB_RBLevels6600K int16u[2] + 0x010d WB_RBLevels7500K int16u[2] + 0x010e WB_RBLevelsCWB1 int16u[2] + 0x010f WB_RBLevelsCWB2 int16u[2] + 0x0110 WB_RBLevelsCWB3 int16u[2] + 0x0111 WB_RBLevelsCWB4 int16u[2] + 0x0113 WB_GLevel3000K int16u + 0x0114 WB_GLevel3300K int16u + 0x0115 WB_GLevel3600K int16u + 0x0116 WB_GLevel3900K int16u + 0x0117 WB_GLevel4000K int16u + 0x0118 WB_GLevel4300K int16u + 0x0119 WB_GLevel4500K int16u + 0x011a WB_GLevel4800K int16u + 0x011b WB_GLevel5300K int16u + 0x011c WB_GLevel6000K int16u + 0x011d WB_GLevel6600K int16u + 0x011e WB_GLevel7500K int16u + 0x011f WB_GLevel int16u + 0x0200 ColorMatrix int16u[9] + 0x0300 Enhancer int16u + 0x0301 EnhancerValues int16u[7] + 0x0310 CoringFilter int16u + 0x0311 CoringValues int16u[7] + 0x0600 BlackLevel2 int16u[4] + 0x0610 GainBase int16u + 0x0611 ValidBits int16u[2] + 0x0612 CropLeft int16u[2] + 0x0613 CropTop int16u[2] + 0x0614 CropWidth int32u + 0x0615 CropHeight int32u + 0x0635 UnknownBlock1? undef + 0x0636 UnknownBlock2? undef + 0x0805 SensorCalibration int16s[2] + 0x1010 NoiseReduction2 int16u + 0x1011 DistortionCorrection2 int16u + 0x1012 ShadingCompensation2 int16u + 0x101c MultipleExposureMode int16u[2] + 0x1103 UnknownBlock3? undef + 0x1104 UnknownBlock4? undef + 0x1112 AspectRatio int8u[2] + 0x1113 AspectFrame int16u[4] + 0x1200 FacesDetected int32u[n] + 0x1201 FaceDetectArea int16s[n] + 0x1202 MaxFaces int32u[3] + 0x1203 FaceDetectFrameSize int16u[6] + 0x1207 FaceDetectFrameCrop int16s[12] + 0x1306 CameraTemperature no + 0x1900 KeystoneCompensation int8u[2] + 0x1901 KeystoneDirection int8u[2] + 0x1906 KeystoneValue int16s[3] + +=head3 Olympus FocusInfo Tags + + Tag ID Tag Name Writable + ------ -------- -------- + 0x0000 FocusInfoVersion undef[4] + 0x0209 AutoFocus? int16u + 0x0210 SceneDetect int16u + 0x0211 SceneArea? int32u[8] + 0x0212 SceneDetectData? int32u[720] + 0x0300 ZoomStepCount int16u + 0x0301 FocusStepCount int16u + 0x0303 FocusStepInfinity int16u + 0x0304 FocusStepNear int16u + 0x0305 FocusDistance rational64u + 0x0308 AFPoint int16u + 0x0328 AFInfo Olympus AFInfo + 0x1201 ExternalFlash int16u[2] + 0x1203 ExternalFlashGuideNumber? rational64s + 0x1204 ExternalFlashBounce int16u + 0x1205 ExternalFlashZoom rational64u + 0x1208 InternalFlash int16u[n] + 0x1209 ManualFlash int16u[2]~ + 0x120a MacroLED int16u + 0x1500 SensorTemperature int16s + 0x1600 ImageStabilization undef~ + +=head3 Olympus AFInfo Tags + + Index1 Tag Name Writable + ------ -------- -------- + [no tags known] + +=head3 Olympus FE Tags + +Some FE models write a large number of tags here, but most of this +information remains unknown. + + Tag ID Tag Name Writable + ------ -------- -------- + 0x0100 BodyFirmwareVersion string + +=head3 Olympus RawInfo Tags + +These tags are found only in ORF images of some models (eg. C8080WZ). + + Tag ID Tag Name Writable + ------ -------- -------- + 0x0000 RawInfoVersion undef[4] + 0x0100 WB_RBLevelsUsed int16u[2] + 0x0110 WB_RBLevelsAuto int16u[2] + 0x0120 WB_RBLevelsShade int16u[2] + 0x0121 WB_RBLevelsCloudy int16u[2] + 0x0122 WB_RBLevelsFineWeather int16u[2] + 0x0123 WB_RBLevelsTungsten int16u[2] + 0x0124 WB_RBLevelsEveningSunlight int16u[2] + 0x0130 WB_RBLevelsDaylightFluor int16u[2] + 0x0131 WB_RBLevelsDayWhiteFluor int16u[2] + 0x0132 WB_RBLevelsCoolWhiteFluor int16u[2] + 0x0133 WB_RBLevelsWhiteFluorescent int16u[2] + 0x0200 ColorMatrix2 int16u[9] + 0x0310 CoringFilter int16u + 0x0311 CoringValues int16u[11] + 0x0600 BlackLevel2 int16u[4] + 0x0601 YCbCrCoefficients no + 0x0611 ValidPixelDepth int16u[2] + 0x0612 CropLeft int16u + 0x0613 CropTop int16u + 0x0614 CropWidth int32u + 0x0615 CropHeight int32u + 0x1000 LightSource int16u + 0x1001 WhiteBalanceComp int16s[3] + 0x1010 SaturationSetting int16s[3] + 0x1011 HueSetting int16s[3] + 0x1012 ContrastSetting int16s[3] + 0x1013 SharpnessSetting int16s[3] + 0x2000 CMExposureCompensation rational64s + 0x2001 CMWhiteBalance int16u + 0x2002 CMWhiteBalanceComp int16s + 0x2010 CMWhiteBalanceGrayPoint int16u[3] + 0x2020 CMSaturation int16s[3] + 0x2021 CMHue int16s[3] + 0x2022 CMContrast int16s[3] + 0x2023 CMSharpness int16s[3] + +=head3 Olympus UnknownInfo Tags + + Tag ID Tag Name Writable + ------ -------- -------- + [no tags known] + +=head3 Olympus DSS Tags + +Information extracted from DSS/DS2 files and the ID3 XOLY frame of MP3 files +written by some Olympus voice recorders. + + Index1 Tag Name Writable + ------ -------- -------- + 12 Model no + 38 StartTime no + 50 EndTime no + 62 Duration no + 798 Comment no + +=head3 Olympus MOV1 Tags + +This information is found in MOV videos from Olympus models such as the +D540Z, D595Z, FE100, FE110, FE115, FE170 and FE200. + + Index1 Tag Name Writable + ------ -------- -------- + 0 Make no + 24 Model no + 38 ExposureUnknown? no + 42 FNumber no + 50 ExposureCompensation no + 72 FocalLength no + +=head3 Olympus MOV2 Tags + +This information is found in MOV videos from Olympus models such as the +FE120, FE140 and FE190. + + Index1 Tag Name Writable + ------ -------- -------- + 0 Make no + 24 Model no + 54 ExposureTime no + 58 FNumber no + 66 ExposureCompensation no + 88 FocalLength no + 193 ISO no + +=head3 Olympus MP4 Tags + +This information is found in MP4 videos from Olympus models such as the +u7040 and u9010. + + Index1 Tag Name Writable + ------ -------- -------- + 0 Make no + 24 Model no + 40 FNumber no + 48 ExposureCompensation no + 104 MovableInfo Olympus MovableInfo + 114 MovableInfo Olympus MovableInfo + +=head3 Olympus MovableInfo Tags + + Index1 Tag Name Writable + ------ -------- -------- + 4 ISO no + 44 EncoderVersion no + 60 DecoderVersion no + 131 Thumbnail Olympus Thumbnail + +=head3 Olympus Thumbnail Tags + + Index4 Tag Name Writable + ------ -------- -------- + 1 ThumbnailWidth no + 2 ThumbnailHeight no + 3 ThumbnailLength no + 4 ThumbnailOffset no + +=head3 Olympus MOV3 Tags + +QuickTime information found in the TAGS atom of MOV videos from the E-M5. + + Tag ID Tag Name Writable + ------ -------- -------- + 'OLYM' OlympusAtom Olympus OLYM2 + +=head3 Olympus OLYM2 Tags + + Tag ID Tag Name Writable + ------ -------- -------- + 'prms' MakerNotes Olympus prms + 'scrn' PreviewInfo Olympus scrn2 + 'thmb' ThumbInfo Olympus thmb2 + +=head3 Olympus prms Tags + +Information extracted from the "prms" atom in MOV videos from Olympus models +such as the OM E-M5. + + Index1 Tag Name Writable + ------ -------- -------- + 18 Make no + 44 Model no + 131 DateTime1 no + 157 DateTime2 no + +=head3 Olympus scrn2 Tags + + Index1 Tag Name Writable + ------ -------- -------- + 2 OlympusPreview Olympus scrn + +=head3 Olympus scrn Tags + +Information extracted from the "scrn" atom of Olympus MP4 videos. + + Index1 Tag Name Writable + ------ -------- -------- + 0 PreviewImageLength no + 4 PreviewImage no + +=head3 Olympus thmb2 Tags + + Index1 Tag Name Writable + ------ -------- -------- + 0 ThumbnailWidth no + 2 ThumbnailHeight no + 4 ThumbnailLength no + 8 ThumbnailImage no + +=head3 Olympus thmb Tags + +Information extracted from the "thmb" atom of Olympus MP4 videos. + + Index1 Tag Name Writable + ------ -------- -------- + 0 ThumbnailLength no + 4 ThumbnailImage no + +=head3 Olympus OLYM Tags + +Tags found in the OLYM atom of MP4 videos from the TG-810. + + Index1 Tag Name Writable + ------ -------- -------- + 14 Make no + 40 Model no + 90 FNumber no + 127 DateTimeOriginal no + 153 DateTime2 no + 265 ThumbnailWidth no + 267 ThumbnailHeight no + +=head3 Olympus AVI Tags + +This information is found in Olympus AVI videos. + + Index1 Tag Name Writable + ------ -------- -------- + 18 Make no + 44 Model no + 94 FNumber no + 131 DateTime1 no + 157 DateTime2 no + 297 ThumbInfo Olympus thmb2 + +=head3 Olympus WAV Tags + +This information is found in WAV files from Olympus PCM linear recorders +like the LS-5, LS-10, LS-11. + + Index1 Tag Name Writable + ------ -------- -------- + 12 Model no + 28 FileNumber no + 38 DateTimeOriginal no + 50 DateTimeEnd no + 62 RecordingTime no + 512 Duration no + 522 Index01 no + 532 Index02 no + 542 Index03 no + 552 Index04 no + 562 Index05 no + 572 Index06 no + 582 Index07 no + 592 Index08 no + 602 Index09 no + 612 Index10 no + 622 Index11 no + 632 Index12 no + 642 Index13 no + 652 Index14 no + 662 Index15 no + 672 Index16 no + +=head2 Panasonic Tags + +These tags are used in Panasonic/Leica cameras. + + Tag ID Tag Name Writable + ------ -------- -------- + 0x0001 ImageQuality int16u + 0x0002 FirmwareVersion undef + 0x0003 WhiteBalance int16u + 0x0007 FocusMode int16u + 0x000f AFAreaMode int8u[2] + 0x001a ImageStabilization int16u + 0x001c MacroMode int16u + 0x001f ShootingMode int16u + 0x0020 Audio int16u + 0x0021 DataDump no + 0x0023 WhiteBalanceBias int16s + 0x0024 FlashBias int16s + 0x0025 InternalSerialNumber undef[16] + 0x0026 PanasonicExifVersion undef + 0x0028 ColorEffect int16u + 0x0029 TimeSincePowerOn int32u + 0x002a BurstMode int16u + 0x002b SequenceNumber int32u + 0x002c ContrastMode int16u + 0x002d NoiseReduction int16u + 0x002e SelfTimer int16u + 0x0030 Rotation int16u + 0x0031 AFAssistLamp int16u + 0x0032 ColorMode int16u + 0x0033 BabyAge string + 0x0034 OpticalZoomMode int16u + 0x0035 ConversionLens int16u + 0x0036 TravelDay int16u + 0x0039 Contrast int16u + 0x003a WorldTimeLocation int16u + 0x003b TextStamp int16u + 0x003c ProgramISO int16u + 0x003d AdvancedSceneType int16u + 0x003e TextStamp int16u + 0x003f FacesDetected int16u + 0x0040 Saturation int16u + 0x0041 Sharpness int16u + 0x0042 FilmMode int16u + 0x0043 JPEGQuality int16u + 0x0044 ColorTempKelvin int16u + 0x0045 BracketSettings int16u + 0x0046 WBShiftAB int16u + 0x0047 WBShiftGM int16u + 0x0048 FlashCurtain int16u + 0x0049 LongExposureNoiseReduction int16u + 0x004b PanasonicImageWidth int32u + 0x004c PanasonicImageHeight int32u + 0x004d AFPointPosition rational64u[2] + 0x004e FaceDetInfo Panasonic FaceDetInfo + 0x0051 LensType string + 0x0052 LensSerialNumber string + 0x0053 AccessoryType string + 0x0054 AccessorySerialNumber string + 0x0059 Transform undef[4] + 0x005d IntelligentExposure int16u + 0x0060 LensFirmwareVersion undef[4] + 0x0061 FaceRecInfo Panasonic FaceRecInfo + 0x0062 FlashWarning int16u + 0x0063 RecognizedFaceFlags? undef[4] + 0x0065 Title undef + 0x0066 BabyName undef + 0x0067 Location undef + 0x0069 Country undef + 0x006b State undef + 0x006d City undef + 0x006f Landmark undef + 0x0070 IntelligentResolution int8u + 0x0076 HDRShot int16u + 0x0077 BurstSpeed int16u + 0x0079 IntelligentD-Range int16u + 0x007c ClearRetouch int16u + 0x0080 City2 undef + 0x0086 ManometerPressure int16u + 0x0089 PhotoStyle int16u + 0x008a ShadingCompensation int16u + 0x008b WBShiftIntelligentAuto int16u + 0x008c AccelerometerZ int16u + 0x008d AccelerometerX int16u + 0x008e AccelerometerY int16u + 0x008f CameraOrientation int8u + 0x0090 RollAngle int16u + 0x0091 PitchAngle int16u + 0x0092 WBShiftCreativeControl int8u + 0x0093 SweepPanoramaDirection int8u + 0x0094 SweepPanoramaFieldOfView int16u + 0x0096 TimerRecording int8u + 0x009d InternalNDFilter rational64u + 0x009e HDR int16u + 0x009f ShutterType int16u + 0x00a3 ClearRetouchValue rational64u + 0x00a7 OutputLUT yes + 0x00ab TouchAE int16u + 0x00ad HighlightShadow int16u[2] + 0x00af TimeStamp string + 0x00b4 MultiExposure int16u + 0x00b9 RedEyeRemoval int16u + 0x00bb VideoBurstMode int32u + 0x00bc DiffractionCorrection int16u + 0x0e00 PrintIM PrintIM + 0x2003 TimeInfo Panasonic TimeInfo + 0x8000 MakerNoteVersion undef + 0x8001 SceneMode int16u + 0x8002 HighlightWarning int16u + 0x8003 DarkFocusEnvironment int16u + 0x8004 WBRedLevel int16u + 0x8005 WBGreenLevel int16u + 0x8006 WBBlueLevel int16u + 0x8008 TextStamp int16u + 0x8009 TextStamp int16u + 0x8010 BabyAge string + 0x8012 Transform undef[4] + +=head3 Panasonic FaceDetInfo Tags + +Face detection position information. + + Index2 Tag Name Writable + ------ -------- -------- + 0 NumFacePositions int16u + 1 Face1Position int16u[4] + 5 Face2Position int16u[4] + 9 Face3Position int16u[4] + 13 Face4Position int16u[4] + 17 Face5Position int16u[4] + +=head3 Panasonic FaceRecInfo Tags + +Tags written by cameras with facial recognition. These cameras not only +detect faces in an image, but also recognize specific people based a +user-supplied set of known faces. + + Index1 Tag Name Writable + ------ -------- -------- + 0 FacesRecognized int16u + 4 RecognizedFace1Name string[20] + 24 RecognizedFace1Position int16u[4] + 32 RecognizedFace1Age string[20] + 52 RecognizedFace2Name string[20] + 72 RecognizedFace2Position int16u[4] + 80 RecognizedFace2Age string[20] + 100 RecognizedFace3Name string[20] + 120 RecognizedFace3Position int16u[4] + 128 RecognizedFace3Age string[20] + +=head3 Panasonic TimeInfo Tags + + Index1 Tag Name Writable + ------ -------- -------- + 0 PanasonicDateTime undef[8] + 16 TimeLapseShotNumber int32u + +=head3 Panasonic Leica2 Tags + +These tags are used by the Leica M8. + + Tag ID Tag Name Writable + ------ -------- -------- + 0x0300 Quality int16u + 0x0302 UserProfile int32u + 0x0303 SerialNumber int32u + 0x0304 WhiteBalance int16u + 0x0310 LensType int32u + 0x0311 ExternalSensorBrightnessValue rational64s + 0x0312 MeasuredLV rational64s + 0x0313 ApproximateFNumber rational64u + 0x0320 CameraTemperature int32s + 0x0321 ColorTemperature int32u + 0x0322 WBRedLevel rational64u + 0x0323 WBGreenLevel rational64u + 0x0324 WBBlueLevel rational64u + 0x0325 UV-IRFilterCorrection int32u + 0x0330 CCDVersion int32u + 0x0331 CCDBoardVersion int32u + 0x0332 ControllerBoardVersion int32u + 0x0333 M16CVersion int32u + 0x0340 ImageIDNumber int32u + +=head3 Panasonic Leica3 Tags + +These tags are used by the Leica R8 and R9 digital backs. + + Tag ID Tag Name Writable + ------ -------- -------- + 0x000b SerialInfo Panasonic SerialInfo + 0x000d WB_RGBLevels int16u[3] + +=head3 Panasonic SerialInfo Tags + + Index1 Tag Name Writable + ------ -------- -------- + 4 SerialNumber no + +=head3 Panasonic Leica4 Tags + +This information is written by the M9. + + Tag ID Tag Name Writable + ------ -------- -------- + 0x3000 Subdir3000 Panasonic Subdir + 0x3100 Subdir3100 Panasonic Subdir + 0x3400 Subdir3400 Panasonic Subdir + 0x3900 Subdir3900 Panasonic Subdir + +=head3 Panasonic Subdir Tags + + Tag ID Tag Name Writable + ------ -------- -------- + 0x300a Contrast int32u + 0x300b Sharpening int32u + 0x300d Saturation int32u + 0x3033 WhiteBalance int32u + 0x3034 JPEGQuality int32u + 0x3036 WB_RGBLevels rational64u[3] + 0x3038 UserProfile string + 0x303a JPEGSize int32u + 0x3103 SerialNumber string + 0x3109 FirmwareVersion string + 0x312a BaseISO int32u + 0x312b SensorWidth int32u + 0x312c SensorHeight int32u + 0x312d SensorBitDepth int32u + 0x3402 CameraTemperature int32s + 0x3405 LensType int32u + 0x3406 ApproximateFNumber rational64u + 0x3407 MeasuredLV int32s + 0x3408 ExternalSensorBrightnessValue int32s + 0x3901 Data1 Panasonic Data1 + 0x3902 Data2 Panasonic Data2 + +=head3 Panasonic Data1 Tags + + Index1 Tag Name Writable + ------ -------- -------- + 22 LensType int32u + +=head3 Panasonic Data2 Tags + + Index1 Tag Name Writable + ------ -------- -------- + [no tags known] + +=head3 Panasonic Leica5 Tags + +This information is written by the X1, X2, X VARIO and T. + + Tag ID Tag Name Writable + ------ -------- -------- + 0x0303 LensType string + 0x0305 SerialNumber int32u + 0x0407 OriginalFileName string + 0x0408 OriginalDirectory string + 0x040a FocusInfo Panasonic FocusInfo + 0x040d ExposureMode int8u[4] + 0x0410 ShotInfo Panasonic ShotInfo + 0x0412 FilmMode string + 0x0413 WB_RGBLevels rational64u[3] + 0x0500 InternalSerialNumber undef + +=head3 Panasonic FocusInfo Tags + + Index2 Tag Name Writable + ------ -------- -------- + 0 FocusDistance int16u + 1 FocalLength int16u + +=head3 Panasonic ShotInfo Tags + + Index1 Tag Name Writable + ------ -------- -------- + 0 FileIndex int16u + +=head3 Panasonic Leica6 Tags + +This information is written by the S2 and M (Typ 240), as a trailer in JPEG +images. + + Tag ID Tag Name Writable + ------ -------- -------- + 0x0300 PreviewImage undef + 0x0301 UnknownBlock? no + 0x0303 LensType string + 0x0304 FocusDistance int32u + 0x0311 ExternalSensorBrightnessValue rational64s + 0x0312 MeasuredLV rational64s + 0x0320 FirmwareVersion int8u[4] + 0x0321 LensSerialNumber int32u + +=head3 Panasonic Leica9 Tags + +This information is written by the Leica S (Typ 007). + + Tag ID Tag Name Writable + ------ -------- -------- + 0x0304 FocusDistance int32u + 0x0311 ExternalSensorBrightnessValue rational64s + 0x0312 MeasuredLV rational64s + +=head3 Panasonic Type2 Tags + +This type of maker notes is used by models such as the NV-DS65, PV-D2002, +PV-DC3000, PV-DV203, PV-DV401, PV-DV702, PV-L2001, PV-SD4090, PV-SD5000 and +iPalm. + + Index2 Tag Name Writable + ------ -------- -------- + 0 MakerNoteType no + 3 Gain no + +=head3 Panasonic PANA Tags + +Tags extracted from the PANA and LEIC user data found in MP4 videos from +various Panasonic and Leica models. + + Index1 Tag Name Writable + ------ -------- -------- + 0 Make no + 4 Model no + 12 Model no + 16 JPEG-likeData EXIF + 22 Model no + 52 Version1 no + 62 Version2 no + 80 MakerNoteLeica5 Panasonic Leica5 + 88 ThumbnailWidth no + 90 ThumbnailHeight no + 92 ThumbnailImage no + 1334 ThumbnailWidth no + 1338 ThumbnailHeight no + 1342 ThumbnailLength no + 1350 ThumbnailImage no + 1358 ThumbnailWidth no + 1362 ThumbnailHeight no + 1366 ThumbnailLength no + 1374 ThumbnailImage no + 16488 ExifData EXIF + 16512 ExifData EXIF + +=head2 Pentax Tags + +These tags are used in Pentax/Asahi cameras. + + Tag ID Tag Name Writable + ------ -------- -------- + 0x0000 PentaxVersion int8u[4] + 0x0001 PentaxModelType int16u + 0x0002 PreviewImageSize int16u[2] + 0x0003 PreviewImageLength int32u* + 0x0004 PreviewImageStart int32u* + 0x0005 PentaxModelID int32u + 0x0006 Date undef[4] + 0x0007 Time undef[3] + 0x0008 Quality int16u + 0x0009 PentaxImageSize int16u + 0x000b PictureMode int16u[n] + 0x000c FlashMode int16u[n] + 0x000d FocusMode int16u + 0x000e AFPointSelected int16u + 0x000f AFPointsInFocus int32u + AFPointsInFocus int16u + 0x0010 FocusPosition int16u + 0x0012 ExposureTime int32u + 0x0013 FNumber int16u + 0x0014 ISO int16u + 0x0015 LightReading int16u + 0x0016 ExposureCompensation int16u + ExposureCompensation int16u[2] + 0x0017 MeteringMode int16u + 0x0018 AutoBracketing int16u[n] + 0x0019 WhiteBalance int16u + 0x001a WhiteBalanceMode int16u + 0x001b BlueBalance int16u + 0x001c RedBalance int16u + 0x001d FocalLength int32u + 0x001e DigitalZoom int16u + 0x001f Saturation int16u[n] + 0x0020 Contrast int16u[n] + 0x0021 Sharpness int16u[n] + 0x0022 WorldTimeLocation int16u + 0x0023 HometownCity int16u + 0x0024 DestinationCity int16u + 0x0025 HometownDST int16u + 0x0026 DestinationDST int16u + 0x0027 DSPFirmwareVersion undef + 0x0028 CPUFirmwareVersion undef + 0x0029 FrameNumber int32u + 0x002d EffectiveLV int16u + EffectiveLV int32u + 0x0032 ImageEditing undef[4] + 0x0033 PictureMode int8u[3] + 0x0034 DriveMode int8u[4] + 0x0035 SensorSize int16u[2] + 0x0037 ColorSpace int16u + 0x0038 ImageAreaOffset int16u[2] + 0x0039 RawImageSize int16u[2]~ + 0x003c AFPointsInFocus no + 0x003d DataScaling int16u + 0x003e PreviewImageBorders int8u[4] + 0x003f LensRec Pentax LensRec + 0x0040 SensitivityAdjust int16u + 0x0041 ImageEditCount int16u + 0x0047 CameraTemperature int8s + 0x0048 AELock int16u + 0x0049 NoiseReduction int16u + 0x004d FlashExposureComp int32s + FlashExposureComp int8s[2] + 0x004f ImageTone int16u + 0x0050 ColorTemperature int16u + 0x0053 ColorTempDaylight undef[4] + 0x0054 ColorTempShade undef[4] + 0x0055 ColorTempCloudy undef[4] + 0x0056 ColorTempTungsten undef[4] + 0x0057 ColorTempFluorescentD undef[4] + 0x0058 ColorTempFluorescentN undef[4] + 0x0059 ColorTempFluorescentW undef[4] + 0x005a ColorTempFlash undef[4] + 0x005c ShakeReductionInfo Pentax SRInfo + Pentax SRInfo2 + 0x005d ShutterCount undef[4] + 0x0060 FaceInfo Pentax FaceInfo + 0x0062 RawDevelopmentProcess int16u + 0x0067 Hue int16u + 0x0068 AWBInfo Pentax AWBInfo + 0x0069 DynamicRangeExpansion undef[4] + 0x006b TimeInfo Pentax TimeInfo + 0x006c HighLowKeyAdj int16s[2] + 0x006d ContrastHighlight int16s[2] + 0x006e ContrastShadow int16s[2] + 0x006f ContrastHighlightShadowAdj int8u + 0x0070 FineSharpness int8u[n] + 0x0071 HighISONoiseReduction int8u + 0x0072 AFAdjustment int16s + 0x0073 MonochromeFilterEffect int16u + 0x0074 MonochromeToning int16u + 0x0076 FaceDetect int8u[2] + 0x0077 FaceDetectFrameSize int16u[2] + 0x0079 ShadowCorrection int8u[n] + 0x007a ISOAutoParameters int8u[2] + 0x007b CrossProcess int8u + 0x007d LensCorr Pentax LensCorr + 0x007e WhiteLevel int32u + 0x007f BleachBypassToning int16u + 0x0080 AspectRatio yes + 0x0082 BlurControl int8u[4] + 0x0085 HDR int8u[4] + 0x0088 NeutralDensityFilter int8u[n] + 0x008b ISO int32u + 0x0092 IntervalShooting int16u[2] + 0x0095 SkinToneCorrection int8s[2] + 0x0096 ClarityControl int8s[2] + 0x0200 BlackPoint int16u[4] + 0x0201 WhitePoint int16u[4] + 0x0203 ColorMatrixA int16s[9] + 0x0204 ColorMatrixB int16s[9] + 0x0205 CameraSettings Pentax CameraSettings + CameraSettingsUnknown Pentax CameraSettingsUnknown + 0x0206 AEInfo Pentax AEInfo + AEInfo2 Pentax AEInfo2 + AEInfo3 Pentax AEInfo3 + AEInfoUnknown Pentax AEInfoUnknown + 0x0207 LensInfo Pentax LensInfo + Pentax LensInfo2 + Pentax LensInfo3 + Pentax LensInfo4 + Pentax LensInfo5 + 0x0208 FlashInfo Pentax FlashInfo + FlashInfoUnknown Pentax FlashInfoUnknown + 0x0209 AEMeteringSegments int8u[n] + 0x020a FlashMeteringSegments int8u[n] + 0x020b SlaveFlashMeteringSegments int8u[n] + 0x020d WB_RGGBLevelsDaylight int16u[4] + 0x020e WB_RGGBLevelsShade int16u[4] + 0x020f WB_RGGBLevelsCloudy int16u[4] + 0x0210 WB_RGGBLevelsTungsten int16u[4] + 0x0211 WB_RGGBLevelsFluorescentD int16u[4] + 0x0212 WB_RGGBLevelsFluorescentN int16u[4] + 0x0213 WB_RGGBLevelsFluorescentW int16u[4] + 0x0214 WB_RGGBLevelsFlash int16u[4] + 0x0215 CameraInfo Pentax CameraInfo + 0x0216 BatteryInfo Pentax BatteryInfo + 0x021b SaturationInfo? no + 0x021f AFInfo Pentax AFInfo + 0x0220 HuffmanTable? no + 0x0221 KelvinWB Pentax KelvinWB + 0x0222 ColorInfo Pentax ColorInfo + 0x0224 EVStepInfo Pentax EVStepInfo + 0x0226 ShotInfo Pentax ShotInfo + 0x0227 FacePos Pentax FacePos + 0x0228 FaceSize Pentax FaceSize + 0x0229 SerialNumber string + 0x022a FilterInfo Pentax FilterInfo + 0x022b LevelInfo Pentax LevelInfo + 0x022d WBLevels Pentax WBLevels + 0x022e Artist string + 0x022f Copyright string + 0x0230 FirmwareVersion string + 0x0231 ContrastDetectAFArea int16u[4] + 0x0235 CrossProcessParams undef[10] + 0x0239 LensInfoQ Pentax LensInfoQ + 0x023f Model string + 0x0243 PixelShiftInfo Pentax PixelShiftInfo + 0x0245 AFPointInfo Pentax AFPointInfo + 0x03fe DataDump no + 0x03ff TempInfo Pentax TempInfo + UnknownInfo Pentax UnknownInfo + 0x0402 ToneCurve yes~ + 0x0403 ToneCurves yes~ + 0x0405 UnknownBlock? undef + 0x0e00 PrintIM PrintIM + +=head3 Pentax LensRec Tags + +This record stores the LensType, plus one or two unknown bytes for some +models. + + Index1 Tag Name Writable + ------ -------- -------- + 0 LensType int8u[2] + 3 ExtenderStatus int8u + +=head3 Pentax SRInfo Tags + +Shake reduction information. + + Index1 Tag Name Writable + ------ -------- -------- + 0 SRResult int8u + 1 ShakeReduction int8u + 2 SRHalfPressTime int8u + 3 SRFocalLength int8u + +=head3 Pentax SRInfo2 Tags + +Shake reduction information for the K-3. + + Index1 Tag Name Writable + ------ -------- -------- + 0 SRResult? int8u + 1 ShakeReduction int8u + +=head3 Pentax FaceInfo Tags + + Index1 Tag Name Writable + ------ -------- -------- + 0 FacesDetected int8u + 2 FacePosition int8u[2] + +=head3 Pentax AWBInfo Tags + + Index1 Tag Name Writable + ------ -------- -------- + 0 WhiteBalanceAutoAdjustment int8u + 1 TungstenAWB int8u + +=head3 Pentax TimeInfo Tags + + Index1 Tag Name Writable + ------ -------- -------- + 0.1 WorldTimeLocation int8u & 0x01 + 0.2 HometownDST int8u & 0x02 + 0.3 DestinationDST int8u & 0x04 + 2 HometownCity int8u + 3 DestinationCity int8u + +=head3 Pentax LensCorr Tags + + Index1 Tag Name Writable + ------ -------- -------- + 0 DistortionCorrection int8u + 1 ChromaticAberrationCorrection int8u + 2 PeripheralIlluminationCorr int8u + 3 DiffractionCorrection int8u + +=head3 Pentax CameraSettings Tags + +Camera settings information written by Pentax DSLR cameras. + + Index1 Tag Name Writable + ------ -------- -------- + 0 PictureMode2 int8u + 1.1 ProgramLine int8u & 0x03 + 1.2 EVSteps int8u & 0x20 + 1.3 E-DialInProgram int8u & 0x40 + 1.4 ApertureRingUse int8u & 0x80 + 2 FlashOptions int8u & 0xf0 + 2.1 MeteringMode2 int8u & 0x0f + 3 AFPointMode int8u & 0xf0 + 3.1 FocusMode2 int8u & 0x0f + 4 AFPointSelected2 int16u + 6 ISOFloor int8u + 7 DriveMode2 int8u + 8 ExposureBracketStepSize int8u + 9 BracketShotNumber int8u + 10 WhiteBalanceSet int8u & 0xf0 + 10.1 MultipleExposureSet int8u & 0x0f + 13 RawAndJpgRecording int8u + 14.1 JpgRecordedPixels int8u & 0x03 + 14.2 LinkAEToAFPoint int8u & 0x01 + 14.3 SensitivitySteps int8u & 0x02 + 14.4 ISOAuto int8u & 0x04 + 16 FlashOptions2 int8u & 0xf0 + 16.1 MeteringMode3 int8u & 0x0f + 17.1 SRActive int8u & 0x80 + 17.2 Rotation int8u & 0x60 + 17.3 ISOSetting int8u & 0x04 + 17.4 SensitivitySteps int8u & 0x02 + 18 TvExposureTimeSetting int8u + 19 AvApertureSetting int8u + 20 SvISOSetting int8u + 21 BaseExposureCompensation int8u + +=head3 Pentax CameraSettingsUnknown Tags + +This information has not yet been decoded for models such as the K-01. + + Index1 Tag Name Writable + ------ -------- -------- + [no tags known] + +=head3 Pentax AEInfo Tags + +Auto-exposure information for most Pentax models. + + Index1 Tag Name Writable + ------ -------- -------- + 0 AEExposureTime int8u + 1 AEAperture int8u + 2 AE_ISO int8u + 3 AEXv int8u + 4 AEBXv int8s + 5 AEMinExposureTime int8u + 6 AEProgramMode int8u + 7 AEFlags no + 8 AEApertureSteps int8u + 9 AEMaxAperture int8u + 10 AEMaxAperture2 int8u + 11 AEMinAperture int8u + 12 AEMeteringMode int8u + 13 AEWhiteBalance int8u & 0xf0 + 13.1 AEMeteringMode2 int8u & 0x0f + 14 FlashExposureCompSet int8s + 21 LevelIndicator int8u + +=head3 Pentax AEInfo2 Tags + +Auto-exposure information for the K-01. + + Index1 Tag Name Writable + ------ -------- -------- + 2 AEExposureTime int8u + 3 AEAperture int8u + 4 AE_ISO int8u + 5 AEXv int8u + 6 AEBXv int8s + 8 AEError int8s + 11 AEApertureSteps int8u + 15 SceneMode int8u + 16 AEMaxAperture int8u + 17 AEMaxAperture2 int8u + 18 AEMinAperture int8u + 19 AEMinExposureTime int8u + +=head3 Pentax AEInfo3 Tags + +Auto-exposure information for the K-3, K-30, K-50 and K-500. + + Index1 Tag Name Writable + ------ -------- -------- + 16 AEExposureTime int8u + 17 AEAperture int8u + 18 AE_ISO int8u + 28 AEMaxAperture int8u + 29 AEMaxAperture2 int8u + 30 AEMinAperture int8u + 31 AEMinExposureTime int8u + +=head3 Pentax AEInfoUnknown Tags + + Index1 Tag Name Writable + ------ -------- -------- + [no tags known] + +=head3 Pentax LensInfo Tags + +Pentax lens information structure for models such as the *istD. + + Index1 Tag Name Writable + ------ -------- -------- + 0 LensType int8u[2] + 3 LensData Pentax LensData + +=head3 Pentax LensInfo2 Tags + +Pentax lens information structure for models such as the K10D and K20D. + + Index1 Tag Name Writable + ------ -------- -------- + 0 LensType int8u[4] + 4 LensData Pentax LensData + +=head3 Pentax LensData Tags + +Pentax lens data information. Some of these tags require interesting binary +gymnastics to decode them into useful values. + + Index1 Tag Name Writable + ------ -------- -------- + 0.1 AutoAperture int8u & 0x01 + 0.2 MinAperture int8u & 0x06 + 0.3 LensFStops int8u & 0x70 + 1 LensKind? int8u + 2 LC1? int8u + 3 MinFocusDistance int8u & 0xf8 + 3.1 FocusRangeIndex int8u & 0x07 + 4 LC3? int8u + 5 LC4? int8u + 6 LC5? int8u + 7 LC6? int8u + 8 LC7? int8u + 9 LensFocalLength int8u + LC8? int8u + 10 NominalMaxAperture int8u & 0xf0 + 10.1 NominalMinAperture int8u & 0x0f + 11 LC10? int8u + 12 LC11? int8u + 13 LC12? int8u + 14.1 MaxAperture int8u & 0x7f + 15 LC14? int8u + 16 LC15? int8u + +=head3 Pentax LensInfo3 Tags + +Pentax lens information structure for 645D. + + Index1 Tag Name Writable + ------ -------- -------- + 1 LensType int8u[4] + 13 LensData Pentax LensData + +=head3 Pentax LensInfo4 Tags + +Pentax lens information structure for models such as the K-5 and K-r. + + Index1 Tag Name Writable + ------ -------- -------- + 1 LensType int8u[4] + 12 LensData Pentax LensData + +=head3 Pentax LensInfo5 Tags + +Pentax lens information structure for the K-01 and newer models. + + Index1 Tag Name Writable + ------ -------- -------- + 1 LensType int8u[5] + 15 LensData Pentax LensData + +=head3 Pentax FlashInfo Tags + +Flash information tags for the K10D, K20D and K200D. + + Index1 Tag Name Writable + ------ -------- -------- + 0 FlashStatus int8u + 1 InternalFlashMode int8u + 2 ExternalFlashMode int8u + 3 InternalFlashStrength int8u + 4 TTL_DA_AUp int8u + 5 TTL_DA_ADown int8u + 6 TTL_DA_BUp int8u + 7 TTL_DA_BDown int8u + 24.1 ExternalFlashGuideNumber int8u & 0x1f + 25 ExternalFlashExposureComp int8u + 26 ExternalFlashBounce int8u + +=head3 Pentax FlashInfoUnknown Tags + + Index1 Tag Name Writable + ------ -------- -------- + [no tags known] + +=head3 Pentax CameraInfo Tags + + Index4 Tag Name Writable + ------ -------- -------- + 0 PentaxModelID int32u + 1 ManufactureDate int32u + 2 ProductionCode int32u[2] + 4 InternalSerialNumber int32u + +=head3 Pentax BatteryInfo Tags + + Index1 Tag Name Writable + ------ -------- -------- + 0.1 PowerSource int8u & 0x0f + 1.1 BodyBatteryState int8u & 0xf0 + 1.2 GripBatteryState int8u & 0x0f + GripBatteryState? int8u & 0x0f + 2 BodyBatteryADNoLoad int8u + BodyBatteryVoltage1 int16u + 3 BodyBatteryADLoad int8u + 4 GripBatteryADNoLoad int8u + BodyBatteryVoltage2 int16u + 5 GripBatteryADLoad int8u + 6 BodyBatteryVoltage3 int16u + 8 BodyBatteryVoltage4 int16u + +=head3 Pentax AFInfo Tags + + Index1 Tag Name Writable + ------ -------- -------- + 0 AFPointsUnknown1? int16u + 2 AFPointsUnknown2? int16u + 4 AFPredictor int16s + 6 AFDefocus int8u + 7 AFIntegrationTime int8u + 11 AFPointsInFocus int8u + 509 AFHold int8u + +=head3 Pentax KelvinWB Tags + +White balance Blue/Red gains as a function of color temperature. + + Index2 Tag Name Writable + ------ -------- -------- + 1 KelvinWB_Daylight int16u[4] + 5 KelvinWB_01 int16u[4] + 9 KelvinWB_02 int16u[4] + 13 KelvinWB_03 int16u[4] + 17 KelvinWB_04 int16u[4] + 21 KelvinWB_05 int16u[4] + 25 KelvinWB_06 int16u[4] + 29 KelvinWB_07 int16u[4] + 33 KelvinWB_08 int16u[4] + 37 KelvinWB_09 int16u[4] + 41 KelvinWB_10 int16u[4] + 45 KelvinWB_11 int16u[4] + 49 KelvinWB_12 int16u[4] + 53 KelvinWB_13 int16u[4] + 57 KelvinWB_14 int16u[4] + 61 KelvinWB_15 int16u[4] + 65 KelvinWB_16 int16u[4] + +=head3 Pentax ColorInfo Tags + + Index1 Tag Name Writable + ------ -------- -------- + 16 WBShiftAB int8s + 17 WBShiftGM int8s + +=head3 Pentax EVStepInfo Tags + + Index1 Tag Name Writable + ------ -------- -------- + 0 EVSteps int8u + 1 SensitivitySteps int8u + +=head3 Pentax ShotInfo Tags + + Index1 Tag Name Writable + ------ -------- -------- + 1 CameraOrientation int8u + +=head3 Pentax FacePos Tags + + Index2 Tag Name Writable + ------ -------- -------- + 0 Face1Position int16u[2] + 2 Face2Position int16u[2] + 4 Face3Position int16u[2] + 6 Face4Position int16u[2] + 8 Face5Position int16u[2] + 10 Face6Position int16u[2] + 12 Face7Position int16u[2] + 14 Face8Position int16u[2] + 16 Face9Position int16u[2] + 18 Face10Position int16u[2] + 20 Face11Position int16u[2] + 22 Face12Position int16u[2] + 24 Face13Position int16u[2] + 26 Face14Position int16u[2] + 28 Face15Position int16u[2] + 30 Face16Position int16u[2] + 32 Face17Position int16u[2] + 34 Face18Position int16u[2] + 36 Face19Position int16u[2] + 38 Face20Position int16u[2] + 40 Face21Position int16u[2] + 42 Face22Position int16u[2] + 44 Face23Position int16u[2] + 46 Face24Position int16u[2] + 48 Face25Position int16u[2] + 50 Face26Position int16u[2] + 52 Face27Position int16u[2] + 54 Face28Position int16u[2] + 56 Face29Position int16u[2] + 58 Face30Position int16u[2] + 60 Face31Position int16u[2] + 62 Face32Position int16u[2] + +=head3 Pentax FaceSize Tags + + Index2 Tag Name Writable + ------ -------- -------- + 0 Face1Size int16u[2] + 2 Face2Size int16u[2] + 4 Face3Size int16u[2] + 6 Face4Size int16u[2] + 8 Face5Size int16u[2] + 10 Face6Size int16u[2] + 12 Face7Size int16u[2] + 14 Face8Size int16u[2] + 16 Face9Size int16u[2] + 18 Face10Size int16u[2] + 20 Face11Size int16u[2] + 22 Face12Size int16u[2] + 24 Face13Size int16u[2] + 26 Face14Size int16u[2] + 28 Face15Size int16u[2] + 30 Face16Size int16u[2] + 32 Face17Size int16u[2] + 34 Face18Size int16u[2] + 36 Face19Size int16u[2] + 38 Face20Size int16u[2] + 40 Face21Size int16u[2] + 42 Face22Size int16u[2] + 44 Face23Size int16u[2] + 46 Face24Size int16u[2] + 48 Face25Size int16u[2] + 50 Face26Size int16u[2] + 52 Face27Size int16u[2] + 54 Face28Size int16u[2] + 56 Face29Size int16u[2] + 58 Face30Size int16u[2] + 60 Face31Size int16u[2] + 62 Face32Size int16u[2] + +=head3 Pentax FilterInfo Tags + +The parameters associated with each type of digital filter are unique, and +these settings are also extracted with the DigitalFilter tag. Information +is not extracted for filters that are "Off" unless the Unknown option is +used. + + Index1 Tag Name Writable + ------ -------- -------- + 0 SourceDirectoryIndex int16u + 2 SourceFileIndex int16u + 5 DigitalFilter01 undef[17] + 22 DigitalFilter02 undef[17] + 39 DigitalFilter03 undef[17] + 56 DigitalFilter04 undef[17] + 73 DigitalFilter05 undef[17] + 90 DigitalFilter06 undef[17] + 107 DigitalFilter07 undef[17] + 124 DigitalFilter08 undef[17] + 141 DigitalFilter09 undef[17] + 158 DigitalFilter10 undef[17] + 175 DigitalFilter11 undef[17] + 192 DigitalFilter12 undef[17] + 209 DigitalFilter13 undef[17] + 226 DigitalFilter14 undef[17] + 243 DigitalFilter15 undef[17] + 260 DigitalFilter16 undef[17] + 277 DigitalFilter17 undef[17] + 294 DigitalFilter18 undef[17] + 311 DigitalFilter19 undef[17] + 328 DigitalFilter20 undef[17] + +=head3 Pentax LevelInfo Tags + +Tags decoded from the electronic level information for the K-5. May not be +valid for other models. + + Index1 Tag Name Writable + ------ -------- -------- + 0 LevelOrientation int8s & 0x0f + 0.1 CompositionAdjust int8s & 0xf0 + 1 RollAngle int8s + 2 PitchAngle int8s + 5 CompositionAdjustX int8s + 6 CompositionAdjustY int8s + 7 CompositionAdjustRotation int8s + +=head3 Pentax WBLevels Tags + + Index1 Tag Name Writable + ------ -------- -------- + 2 WB_RGGBLevelsDaylight int16u[4] + 11 WB_RGGBLevelsShade int16u[4] + 20 WB_RGGBLevelsCloudy int16u[4] + 29 WB_RGGBLevelsTungsten int16u[4] + 38 WB_RGGBLevelsFluorescentD int16u[4] + 47 WB_RGGBLevelsFluorescentN int16u[4] + 56 WB_RGGBLevelsFluorescentW int16u[4] + 65 WB_RGGBLevelsFlash int16u[4] + 74 WB_RGGBLevelsFluorescentL int16u[4] + 83 WB_RGGBLevelsUnknown? int16u[4] + 92 WB_RGGBLevelsUserSelected int16u[4] + +=head3 Pentax LensInfoQ Tags + +More lens information stored by the Pentax Q. + + Index1 Tag Name Writable + ------ -------- -------- + 12 LensModel string[30] + 42 LensInfo string[20] + +=head3 Pentax PixelShiftInfo Tags + +Pixel shift information stored by the K-3 II. + + Index1 Tag Name Writable + ------ -------- -------- + 0 PixelShiftResolution int8u + +=head3 Pentax AFPointInfo Tags + +AF point information written by the K-1. + + Index1 Tag Name Writable + ------ -------- -------- + 2 NumAFPoints int16u + 4 AFPointsInFocus int8u[9]~ + 4.1 AFPointsSelected int8u[9]~ + 4.2 AFPointsSpecial int8u[9]~ + +=head3 Pentax TempInfo Tags + +A number of additional temperature readings are extracted from this 256-byte +binary-data block in images from models such as the K-01, K-3, K-5, K-50 and +K-500. It is currently not known where the corresponding temperature +sensors are located in the camera. + + Index1 Tag Name Writable + ------ -------- -------- + 12 SensorTemperature int16s + 14 SensorTemperature2 int16s + 20 CameraTemperature4 int16s + 22 CameraTemperature5 int16s + +=head3 Pentax UnknownInfo Tags + + Index1 Tag Name Writable + ------ -------- -------- + [no tags known] + +=head3 Pentax Type2 Tags + +These tags are used by the Pentax Optio 330 and 430, and are similar to the +tags used by Casio. + + Tag ID Tag Name Writable + ------ -------- -------- + 0x0001 RecordingMode int16u + 0x0002 Quality int16u + 0x0003 FocusMode int16u + 0x0004 FlashMode int16u + 0x0007 WhiteBalance int16u + 0x000a DigitalZoom int32u + 0x000b Sharpness int16u + 0x000c Contrast int16u + 0x000d Saturation int16u + 0x0014 ISO int16u + 0x0017 ColorFilter int16u + 0x0e00 PrintIM PrintIM + 0x1000 HometownCityCode undef[4] + 0x1001 DestinationCityCode undef[4] + +=head3 Pentax Type4 Tags + +The following few tags are extracted from the wealth of information +available in maker notes of the Optio E20 and E25. These maker notes are +stored as ASCII text in a format very similar to some HP models. + + Tag ID Tag Name Writable + ------ -------- -------- + 'F/W Version' FirmwareVersion no + +=head3 Pentax S1 Tags + +Tags extracted from the maker notes of AVI videos from the Optio S1. + + Tag ID Tag Name Writable + ------ -------- -------- + 0x0000 MakerNoteVersion undef[4] + +=head3 Pentax PENT Tags + +Tags found in the PENT atom of MOV videos from the Optio WG-2 GPS. + + Index1 Tag Name Writable + ------ -------- -------- + 0 Make no + 26 Model no + 56 ExposureTime no + 60 FNumber no + 68 ExposureCompensation no + 84 FocalLength no + 113 DateTime1 no + 139 DateTime2 no + 167 ISO no + 199 GPSVersionID no + 207 GPSLatitudeRef no + 209 GPSLatitude no + 233 GPSLongitudeRef no + 235 GPSLongitude no + 259 GPSAltitudeRef no + 260 GPSAltitude no + 284 GPSTimeStamp no + 308 GPSSatellites no + 311 GPSStatus no + 313 GPSMeasureMode no + 315 GPSMapDatum no + 322 GPSDateStamp no + 371 AudioCodecID no + 2003 PreviewImage no + +=head3 Pentax PXTH Tags + +Tags found in the PXTH atom of MOV videos from the K-01. + + Index1 Tag Name Writable + ------ -------- -------- + 0 PreviewImageLength no + 4 PreviewImage no + +=head3 Pentax MOV Tags + +This information is found in MOV videos from cameras such as the Optio WP. + + Index1 Tag Name Writable + ------ -------- -------- + 0 Make no + 38 ExposureTime no + 42 FNumber no + 50 ExposureCompensation no + 68 WhiteBalance no + 72 FocalLength no + 175 ISO no + +=head3 Pentax Junk Tags + +Tags found in the JUNK chunk of AVI videos from the RS1000. + + Index1 Tag Name Writable + ------ -------- -------- + 12 Model no + +=head3 Pentax Junk2 Tags + +This information is found in AVI videos from the Optio RZ18. + + Index1 Tag Name Writable + ------ -------- -------- + 18 Make no + 44 Model no + 94 FNumber no + 131 DateTime1 no + 157 DateTime2 no + 299 ThumbnailWidth no + 301 ThumbnailHeight no + 303 ThumbnailLength no + 307 ThumbnailImage no + +=head3 Pentax AVI Tags + +Pentax-specific RIFF tags found in AVI videos. + + Tag ID Tag Name Writable + ------ -------- -------- + 'hymn' MakerNotes Pentax + 'mknt' MakerNotes Pentax + +=head2 PhaseOne Tags + +These tags are extracted from the maker notes of Phase One images. + + Tag ID Tag Name Writable + ------ -------- -------- + 0x0100 CameraOrientation no + 0x0102 SerialNumber string + 0x0105 ISO int32s + 0x0106 ColorMatrix1 float[9] + 0x0107 WB_RGBLevels float[3] + 0x0108 SensorWidth int32s + 0x0109 SensorHeight int32s + 0x010a SensorLeftMargin int32s + 0x010b SensorTopMargin int32s + 0x010c ImageWidth int32s + 0x010d ImageHeight int32s + 0x010e RawFormat int32s + 0x010f RawData no + 0x0110 SensorCalibration PhaseOne SensorCalibration + 0x0112 DateTimeOriginal no + 0x0113 ImageNumber int32s + 0x0203 Software string + 0x0204 System string + 0x0210 SensorTemperature float + 0x0211 SensorTemperature2 float + 0x0212 UnknownDate? int32u + 0x021c StripOffsets no + 0x021d BlackLevel int32s + 0x0222 SplitColumn int32s + 0x0223 BlackLevelData int16u[n] + 0x0226 ColorMatrix2 float[9] + 0x0267 AFAdjustment float + 0x0301 FirmwareVersions string + 0x0400 ShutterSpeedValue float + 0x0401 ApertureValue float + 0x0402 ExposureCompensation float + 0x0403 FocalLength float + 0x0410 CameraModel string + 0x0412 LensModel string + 0x0414 MaxApertureValue float + 0x0415 MinApertureValue float + 0x0455 Viewfinder string + +=head3 PhaseOne SensorCalibration Tags + + Tag ID Tag Name Writable + ------ -------- -------- + 0x0400 SensorDefects no + 0x0401 AllColorFlatField1? no + 0x0407 SerialNumber string + 0x040b RedBlueFlatField? no + 0x0410 AllColorFlatField2? no + 0x0416 AllColorFlatField3? no + 0x0419 LinearizationCoefficients1 no + 0x041a LinearizationCoefficients2 no + +=head2 Reconyx Tags + +The following tags are extracted from the maker notes of Reconyx Hyperfire +cameras such as the HC500, HC600 and PC900. + + Index2 Tag Name Writable + ------ -------- -------- + 0 MakerNoteVersion no + 1 FirmwareVersion no + 4 FirmwareDate int16u[2] + 6 TriggerMode string[2] + 7 Sequence int16u[2] + 9 EventNumber int16u[2] + 11 DateTimeOriginal int16u[6] + 18 MoonPhase int16u + 19 AmbientTemperatureFahrenheit int16s + 20 AmbientTemperature int16s + 21 SerialNumber undef[30] + 36 Contrast int16u + 37 Brightness int16u + 38 Sharpness int16u + 39 Saturation int16u + 40 InfraredIlluminator int16u + 41 MotionSensitivity int16u + 42 BatteryVoltage int16u + 43 UserLabel string[22] + +=head3 Reconyx Type2 Tags + +Tags extracted from models such as the UltraFire. + + Index1 Tag Name Writable + ------ -------- -------- + 24 FirmwareVersion undef[7] + 31 Micro1Version undef[7] + 38 BootLoaderVersion undef[7] + 45 Micro2Version undef[7] + 52 TriggerMode undef[1] + 53 Sequence int8u[2] + 55 EventNumber int32u + 59 DateTimeOriginal int8u[7] + 66 DayOfWeek int8u + 67 MoonPhase int8u + 68 AmbientTemperatureFahrenheit int16s + 70 AmbientTemperature int16s + 72 Illumination int8u + 73 BatteryVoltage int16u + 75 SerialNumber string[15] + 90 UserLabel string[21] + +=head3 Reconyx Type3 Tags + +Tags extracted from models such as the HP2X. + + Index1 Tag Name Writable + ------ -------- -------- + 16 FileNumber int16u + 18 DirectoryNumber int16u + 42 FirmwareVersion int16u[3] + 48 FirmwareDate int16u[2] + 52 TriggerMode string[2] + 54 Sequence int16u[2] + 58 EventNumber int16u[2] + 62 DateTimeOriginal int16u[6] + 74 DayOfWeek int16u + 76 MoonPhase int16u + 78 AmbientTemperatureFahrenheit int16s + 80 AmbientTemperature int16s + 82 Contrast int16u + 84 Brightness int16u + 86 Sharpness int16u + 88 Saturation int16u + 90 Flash int16u + 92 AmbientInfrared int16u + 94 AmbientLight int16u + 96 MotionSensitivity int16u + 98 BatteryVoltage int16u + 100 BatteryVoltageAvg int16u + 102 BatteryType int16u + 104 UserLabel string[22] + 126 SerialNumber unicode[15] + +=head2 Sanyo Tags + + Tag ID Tag Name Writable + ------ -------- -------- + 0x00ff MakerNoteOffset int32u + 0x0100 SanyoThumbnail undef + 0x0200 SpecialMode int32u[3] + 0x0201 SanyoQuality int16u + 0x0202 Macro int16u + 0x0204 DigitalZoom rational64u + 0x0207 SoftwareVersion yes + 0x0208 PictInfo yes + 0x0209 CameraID yes + 0x020e SequentialShot int16u + 0x020f WideRange int16u + 0x0210 ColorAdjustmentMode int16u + 0x0213 QuickShot int16u + 0x0214 SelfTimer int16u + 0x0216 VoiceMemo int16u + 0x0217 RecordShutterRelease int16u + 0x0218 FlickerReduce int16u + 0x0219 OpticalZoomOn int16u + 0x021b DigitalZoomOn int16u + 0x021d LightSourceSpecial int16u + 0x021e Resaved int16u + 0x021f SceneSelect int16u + 0x0223 ManualFocusDistance rational64u + FaceInfo - + 0x0224 SequenceShotInterval int16u + 0x0225 FlashMode int16u + 0x0e00 PrintIM PrintIM + 0x0f00 DataDump no + +=head3 Sanyo FaceInfo Tags + + Index4 Tag Name Writable + ------ -------- -------- + 0 FacesDetected int32u + 4 FacePosition int32u[4] + +=head3 Sanyo MOV Tags + +This information is found in Sanyo MOV videos. + + Index1 Tag Name Writable + ------ -------- -------- + 0 Make no + 24 Model no + 38 ExposureTime no + 42 FNumber no + 50 ExposureCompensation no + 68 WhiteBalance no + 72 FocalLength no + +=head3 Sanyo MP4 Tags + +This information is found in Sanyo MP4 videos. + + Index1 Tag Name Writable + ------ -------- -------- + 0 Make no + 24 Model no + 50 FNumber no + 58 ExposureCompensation no + 106 ISO no + 209 Software no + 210 Software no + 241 Thumbnail Sanyo Thumbnail + 242 Thumbnail Sanyo Thumbnail + +=head3 Sanyo Thumbnail Tags + + Index4 Tag Name Writable + ------ -------- -------- + 1 ThumbnailWidth no + 2 ThumbnailHeight no + 3 ThumbnailLength no + 4 ThumbnailOffset no + +=head2 Samsung Tags + +Tags found in the binary "STMN" format maker notes written by a number of +Samsung models. + + Index4 Tag Name Writable + ------ -------- -------- + 0 MakerNoteVersion undef[8] + 2 PreviewImageStart int32u* + 3 PreviewImageLength int32u* + 11 SamsungIFD Samsung IFD + +=head3 Samsung IFD Tags + +This is a standard-format IFD found in the maker notes of some Samsung +models, except that the entry count is a 4-byte integer and the offsets are +relative to the end of the IFD. Currently, no tags in this IFD are known, +so the Unknown (-u) or Verbose (-v) option must be used to see this +information. + + Tag ID Tag Name Writable + ------ -------- -------- + [no tags known] + +=head3 Samsung Type2 Tags + +Tags found in the EXIF-format maker notes of newer Samsung models. + + Tag ID Tag Name Writable + ------ -------- -------- + 0x0001 MakerNoteVersion undef[4] + 0x0002 DeviceType int32u + 0x0003 SamsungModelID int32u + 0x0011 OrientationInfo Samsung OrientationInfo + 0x0020 SmartAlbumColor int16u[2] + 0x0021 PictureWizard Samsung PictureWizard + 0x0030 LocalLocationName string + 0x0031 LocationName string + 0x0035 PreviewIFD Nikon PreviewIFD + Nikon PreviewIFD + 0x0040 RawDataByteOrder yes + 0x0041 WhiteBalanceSetup int32u + 0x0043 CameraTemperature rational64s + 0x0050 RawDataCFAPattern yes + 0x0100 FaceDetect int16u + 0x0120 FaceRecognition int32u + 0x0123 FaceName string + 0xa001 FirmwareName string + 0xa002 SerialNumber string + 0xa003 LensType int16u[n] + 0xa004 LensFirmware string + 0xa005 InternalLensSerialNumber string + 0xa010 SensorAreas int32u[8] + 0xa011 ColorSpace int16u + 0xa012 SmartRange int16u + 0xa013 ExposureCompensation rational64s + 0xa014 ISO int32u + 0xa018 ExposureTime rational64u + 0xa019 FNumber rational64u + 0xa01a FocalLengthIn35mmFormat int32u + 0xa020 EncryptionKey int32u[11]! + 0xa021 WB_RGGBLevelsUncorrected int32u[4] + 0xa022 WB_RGGBLevelsAuto int32u[4] + 0xa023 WB_RGGBLevelsIlluminator1 int32u[4] + 0xa024 WB_RGGBLevelsIlluminator2 int32u[4] + 0xa025 HighlightLinearityLimit int32u + 0xa028 WB_RGGBLevelsBlack int32s[4] + 0xa030 ColorMatrix int32s[9] + 0xa031 ColorMatrixSRGB int32s[9] + 0xa032 ColorMatrixAdobeRGB int32s[9] + 0xa033 CbCrMatrixDefault int32s[4] + 0xa034 CbCrMatrix int32s[4] + 0xa035 CbCrGainDefault int32u[2] + 0xa036 CbCrGain int32u[2] + 0xa040 ToneCurveSRGBDefault int32u[23] + 0xa041 ToneCurveAdobeRGBDefault int32u[23] + 0xa042 ToneCurveSRGB int32u[23] + 0xa043 ToneCurveAdobeRGB int32u[23] + 0xa048 RawData? int32s[12] + 0xa050 Distortion? int32s[8] + 0xa051 ChromaticAberration? int16u[22] + 0xa052 Vignetting? int16u[15] + 0xa053 VignettingCorrection? int16u[15] + 0xa054 VignettingSetting? int16u[15] + +=head3 Samsung OrientationInfo Tags + +Camera orientation information written by the Gear 360 (SM-C200). + + Index8 Tag Name Writable + ------ -------- -------- + 0 YawAngle? rational64s + 1 PitchAngle rational64s + 2 RollAngle rational64s + +=head3 Samsung PictureWizard Tags + + Index2 Tag Name Writable + ------ -------- -------- + 0 PictureWizardMode int16u + 1 PictureWizardColor int16u + 2 PictureWizardSaturation int16u + 3 PictureWizardSharpness int16u + 4 PictureWizardContrast int16u + +=head3 Samsung APP5 Tags + + Tag ID Tag Name Writable + ------ -------- -------- + 'ssuniqueid' UniqueID no + +=head3 Samsung Trailer Tags + +Tags extracted from the trailer of JPEG images written when using certain +features (such as "Sound & Shot" or "Shot & More") from Samsung models such +as the Galaxy S4 and Tab S. + + Tag Name Writable + -------- -------- + DepthMapData no + DepthMapName no + DualCameraImage no + DualCameraImageName no + DualShotInfo Samsung DualShotInfo + EmbeddedAudioFile no + EmbeddedAudioFileName no + EmbeddedImage no + EmbeddedImageName no + EmbeddedVideoFile no + EmbeddedVideoType no + SurroundShotVideo no + SurroundShotVideoName no + TimeStamp no + +=head3 Samsung DualShotInfo Tags + + Index4 Tag Name Writable + ------ -------- -------- + 9 DepthMapWidth no + 10 DepthMapHeight no + +=head3 Samsung sec Tags + +This information is found in the @sec atom of Samsung MP4 videos from models +such as the WB30F. + + Index1 Tag Name Writable + ------ -------- -------- + 0 Make no + 32 Model no + 512 ThumbnailWidth no + 516 ThumbnailHeight no + 520 ThumbnailLength no + 524 ThumbnailImage no + +=head3 Samsung INFO Tags + +This information is found in MP4 videos from Samsung models such as the +SMX-C20N. + + Tag ID Tag Name Writable + ------ -------- -------- + 'EFCT' Effect no + 'QLTY' Quality no + +=head3 Samsung MP4 Tags + +This information is found in Samsung MP4 videos from models such as the +WP10. + + Index1 Tag Name Writable + ------ -------- -------- + 0 Make no + 24 Model no + 46 ExposureTime no + 50 FNumber no + 58 ExposureCompensation no + 106 ISO no + 125 Software no + 244 Thumbnail Samsung Thumbnail + +=head3 Samsung Thumbnail Tags + + Index4 Tag Name Writable + ------ -------- -------- + 1 ThumbnailWidth no + 2 ThumbnailHeight no + 3 ThumbnailLength no + 4 ThumbnailOffset no + +=head3 Samsung smta Tags + +This information is found in the smta atom of Samsung MP4 videos from models +such as the Galaxy S4. + + Tag ID Tag Name Writable + ------ -------- -------- + 'svss' SamsungSvss Samsung svss + +=head3 Samsung svss Tags + +This information is found in the svss atom of Samsung MP4 videos from models +such as the Galaxy S4. + + Tag ID Tag Name Writable + ------ -------- -------- + [no tags known] + +=head2 Ricoh Tags + + Tag ID Tag Name Writable + ------ -------- -------- + 0x0001 MakerNoteType string + 0x0002 FirmwareVersion string + 0x0005 SerialNumber undef[16] + InternalSerialNumber undef[16] + 0x0e00 PrintIM PrintIM + 0x1000 RecordingFormat int16u + 0x1001 ImageInfo Ricoh ImageInfo + ExposureProgram int16u + 0x1002 DriveMode int16u + 0x1003 Sharpness int32u + WhiteBalance int16u + 0x1004 WhiteBalanceFineTune int16u + 0x1006 FocusMode int16u + 0x1007 AutoBracketing int16u + 0x1009 MacroMode int16u + 0x100a FlashMode int16u + 0x100b FlashExposureComp rational64s + 0x100c ManualFlashOutput rational64s + 0x100d FullPressSnap int16u + 0x100e DynamicRangeExpansion int16u + 0x100f NoiseReduction int16u + 0x1010 ImageEffects int16u + 0x1011 Vignetting int16u + 0x1012 Contrast int32u + 0x1013 Saturation int32u + 0x1014 Sharpness int32u + 0x1015 ToningEffect int16u + 0x1016 HueAdjust int16u + 0x1017 WideAdapter int16u + 0x1018 CropMode35mm int16u + 0x1019 NDFilter int16u + 0x101a WBBracketShotNumber int16u + 0x1200 AFStatus int16u + 0x1201 AFAreaXPosition1 int32u + 0x1202 AFAreaYPosition1 int32u + 0x1203 AFAreaXPosition int32u + 0x1204 AFAreaYPosition int32u + 0x1205 AFAreaMode int16u + 0x1307 ColorTempKelvin int32u + 0x1308 ColorTemperature int32u + 0x1500 FocalLength rational64u + 0x1601 SensorWidth int32u + 0x1602 SensorHeight int32u + 0x1603 CroppedImageWidth int32u + 0x1604 CroppedImageHeight int32u + 0x2001 RicohSubdir Ricoh Subdir + RicohSubdirIFD Ricoh Subdir + RicohRR1Subdir Ricoh Subdir + 0x4001 ThetaSubdir Ricoh ThetaSubdir + +=head3 Ricoh ImageInfo Tags + + Index1 Tag Name Writable + ------ -------- -------- + 0 RicohImageWidth int16u + 2 RicohImageHeight int16u + 6 RicohDate int8u[7] + 28 PreviewImageStart int16u* + 30 PreviewImageLength int16u* + 32 FlashMode int8u + 33 Macro int8u + 34 Sharpness int8u + 38 WhiteBalance int8u + 39 ISOSetting int8u + 40 Saturation int8u + +=head3 Ricoh Subdir Tags + + Tag ID Tag Name Writable + ------ -------- -------- + 0x0004 ManufactureDate1 string[20] + 0x0005 ManufactureDate2 string[20] + 0x001a FaceInfo Ricoh FaceInfo + 0x0029 FirmwareInfo Ricoh FirmwareInfo + 0x002a NoiseReduction int32u + 0x002c SerialInfo Ricoh SerialInfo + +=head3 Ricoh FaceInfo Tags + + Index1 Tag Name Writable + ------ -------- -------- + 181 FacesDetected int8u + 182 FaceDetectFrameSize int16u[2] + 188 Face1Position int16u[4] + 200 Face2Position int16u[4] + 212 Face3Position int16u[4] + 224 Face4Position int16u[4] + 236 Face5Position int16u[4] + 248 Face6Position int16u[4] + 260 Face7Position int16u[4] + 272 Face8Position int16u[4] + +=head3 Ricoh FirmwareInfo Tags + + Index1 Tag Name Writable + ------ -------- -------- + 0 FirmwareRevision string[12] + 12 FirmwareRevision2 string[12] + +=head3 Ricoh SerialInfo Tags + +This information is found in images from the GXR. + + Index1 Tag Name Writable + ------ -------- -------- + 0 BodyFirmware string[16] + 16 BodySerialNumber string[16] + 32 LensFirmware string[16] + 48 LensSerialNumber string[16] + +=head3 Ricoh ThetaSubdir Tags + + Tag ID Tag Name Writable + ------ -------- -------- + 0x0003 Accelerometer rational64s[2] + 0x0004 Compass rational64u + 0x000a TimeZone string + +=head3 Ricoh Type2 Tags + +Tags written by models such as the Ricoh HZ15 and the Pentax XG-1. These +are not writable due to numerous formatting errors as written by these +cameras. + + Tag ID Tag Name Writable + ------ -------- -------- + 0x0207 RicohModel string + 0x0300 RicohMake no + +=head3 Ricoh Text Tags + +Some Ricoh DC and RDC models use a text-based format for their maker notes +instead of the IFD format used by the Caplio models. Below is a list of known +tags in this information. + + Tag ID Tag Name Writable + ------ -------- -------- + 'Bg' BlueGain no + 'Gg' GreenGain no + 'Rev' FirmwareVersion no + 'Rg' RedGain no + 'Rv' FirmwareVersion no + +=head3 Ricoh RMETA Tags + +The Ricoh Caplio Pro G3 has the ability to add custom fields to the APP5 +"RMETA" segment of JPEG images. While only a few observed tags have been +defined below, ExifTool will extract any information found here. + + Tag ID Tag Name Writable + ------ -------- -------- + 'Azimuth' Azimuth no + 'Condition' Condition no + 'Lit' Lit no + 'Location' Location no + 'Sign type' SignType no + '_audio' SoundFile no + +=head3 Ricoh AVI Tags + + Tag ID Tag Name Writable + ------ -------- -------- + 'mnrt' MakerNoteRicoh Ricoh + 'rdc2' RicohRDC2? no + 'thum' ThumbnailImage no + 'ucmt' Comment no + +=head2 Sigma Tags + +These tags are written by Sigma/Foveon cameras. In the early days Sigma was +a class leader by releasing their maker note specification to the public, +but since then they have deviated from this standard and newer camera models +are less than consistent about their metadata formats. + + Tag ID Tag Name Writable + ------ -------- -------- + 0x0002 SerialNumber string + 0x0003 DriveMode string + 0x0004 ResolutionMode string + 0x0005 AFMode string + 0x0006 FocusSetting string + 0x0007 WhiteBalance string + 0x0008 ExposureMode string + 0x0009 MeteringMode string + 0x000a LensFocalRange string + 0x000b ColorSpace string + 0x000c ExposureCompensation string + ExposureAdjust? rational64s + 0x000d Contrast string + Contrast rational64s + 0x000e Shadow string + Shadow rational64s + 0x000f Highlight string + Highlight rational64s + 0x0010 Saturation string + Saturation rational64s + 0x0011 Sharpness string + Sharpness rational64s + 0x0012 X3FillLight string + X3FillLight rational64s + 0x0014 ColorAdjustment string + ColorAdjustment rational64s[3] + 0x0015 AdjustmentMode string + 0x0016 Quality string + 0x0017 Firmware string + 0x0018 Software string + 0x0019 AutoBracket string + 0x001a PreviewImageStart int32u* + ChrominanceNoiseReduction string + 0x001b PreviewImageLength int32u* + LuminanceNoiseReduction string + 0x001c PreviewImageSize int16u[2] + PreviewImageStart int32u* + 0x001d MakerNoteVersion undef + PreviewImageLength int32u* + 0x001e PreviewImageSize int16u[2] + 0x001f AFPoint string + MakerNoteVersion undef + 0x0022 FileFormat string + 0x0024 Calibration string + 0x0026 FileFormat string + 0x0027 LensType string + 0x002a LensFocalRange rational64u[2] + 0x002b LensMaxApertureRange rational64u[2] + 0x002c ColorMode int32u + 0x0030 LensApertureRange string + Calibration string + 0x0031 FNumber rational64u + 0x0032 ExposureTime rational64u + 0x0033 ExposureTime2 string + 0x0034 BurstShot int32u + 0x0035 ExposureCompensation rational64s + 0x0039 SensorTemperature string + 0x003a FlashExposureComp rational64s + 0x003b Firmware string + 0x003c WhiteBalance string + 0x003d PictureMode string + 0x0048 LensApertureRange string + 0x0049 FNumber rational64u + 0x004a ExposureTime rational64u + 0x004b ExposureTime2 string + 0x004d ExposureCompensation rational64s + 0x0055 SensorTemperature string + 0x0056 FlashExposureComp rational64s + 0x0057 Firmware string + 0x0058 WhiteBalance string + 0x0059 DigitalFilter string + 0x0084 Model string + +=head2 Sony Tags + +The following information has been decoded from the MakerNotes of Sony +cameras. Some of these tags have been inherited from the Minolta +MakerNotes. + + Tag ID Tag Name Writable + ------ -------- -------- + 0x0010 CameraInfo Sony CameraInfo + CameraInfo2 Sony CameraInfo2 + CameraInfo3 Sony CameraInfo3 + CameraInfoUnknown Sony CameraInfoUnknown + 0x0020 FocusInfo Sony FocusInfo + MoreInfo Sony MoreInfo + 0x0102 Quality int32u + 0x0104 FlashExposureComp rational64s + 0x0105 Teleconverter int32u + 0x0112 WhiteBalanceFineTune int32u + 0x0114 CameraSettings Sony CameraSettings + CameraSettings2 Sony CameraSettings2 + CameraSettings3 Sony CameraSettings3 + CameraSettingsUnknown Sony CameraSettingsUnknown + 0x0115 WhiteBalance int32u + 0x0116 ExtraInfo Sony ExtraInfo + ExtraInfo2 Sony ExtraInfo2 + ExtraInfo3 Sony ExtraInfo3 + 0x0e00 PrintIM PrintIM + 0x1000 MultiBurstMode undef + 0x1001 MultiBurstImageWidth int16u + 0x1002 MultiBurstImageHeight int16u + 0x1003 Panorama Sony Panorama + 0x2001 PreviewImage undef + 0x2002 Rating int32u + 0x2004 Contrast int32s + 0x2005 Saturation int32s + 0x2006 Sharpness int32s + 0x2007 Brightness int32s + 0x2008 LongExposureNoiseReduction int32u + 0x2009 HighISONoiseReduction int16u + 0x200a HDR int32u + 0x200b MultiFrameNoiseReduction int32u + 0x200e PictureEffect int16u + 0x200f SoftSkinEffect int32u + 0x2010 Tag2010a Sony Tag2010a + Tag2010b Sony Tag2010b + Tag2010c Sony Tag2010c + Tag2010d Sony Tag2010d + Tag2010e Sony Tag2010e + Tag2010f Sony Tag2010f + Tag2010g Sony Tag2010g + Tag2010h Sony Tag2010h + Tag2010i Sony Tag2010i + 0x2011 VignettingCorrection int32u + 0x2012 LateralChromaticAberration int32u + 0x2013 DistortionCorrectionSetting int32u + 0x2014 WBShiftAB_GM int32s[2] + 0x2016 AutoPortraitFramed int16u + 0x2017 FlashAction int32u + 0x201a ElectronicFrontCurtainShutter int32u + 0x201b FocusMode int8u + 0x201c AFAreaModeSetting int8u + 0x201d FlexibleSpotPosition int16u[2] + 0x201e AFPointSelected int8u + 0x2020 AFPointsUsed no + 0x2021 AFTracking int8u + 0x2022 FocalPlaneAFPointsUsed no + 0x2023 MultiFrameNREffect int32u + 0x2026 WBShiftAB_GM_Precise int32s[2]~ + 0x2027 FocusLocation int16u[4] + 0x2028 VariableLowPassFilter int16u[2] + 0x2029 RAWFileType int16u + 0x202a Tag202a Sony Tag202a + 0x202b PrioritySetInAWB int8u + 0x202c MeteringMode2 int16u + 0x202d ExposureStandardAdjustment rational64s + 0x202e Quality int16u[2] + 0x202f PixelShiftInfo undef + 0x2031 SerialNumber string + 0x3000 ShotInfo Sony ShotInfo + 0x900b Tag900b Sony Tag900b + 0x9050 Tag9050a Sony Tag9050a + Tag9050b Sony Tag9050b + 0x9400 Tag9400a Sony Tag9400a + Tag9400b Sony Tag9400b + Tag9400c Sony Tag9400c + 0x9401 Tag9401 Sony Tag9401 + 0x9402 Tag9402 Sony Tag9402 + 0x9403 Tag9403 Sony Tag9403 + 0x9404 Tag9404a Sony Tag9404a + Tag9404b Sony Tag9404b + Tag9404c Sony Tag9404c + 0x9405 Tag9405a Sony Tag9405a + Tag9405b Sony Tag9405b + 0x9406 Tag9406 Sony Tag9406 + 0x940a Tag940a Sony Tag940a + 0x940c Tag940c Sony Tag940c + 0x940e AFInfo Sony AFInfo + Tag940e Sony Tag940e + 0xb000 FileFormat int8u[4] + 0xb001 SonyModelID int16u + 0xb020 CreativeStyle string + 0xb021 ColorTemperature int32u + 0xb022 ColorCompensationFilter int32u + 0xb023 SceneMode int32u + 0xb024 ZoneMatching int32u + 0xb025 DynamicRangeOptimizer int32u + 0xb026 ImageStabilization int32u + 0xb027 LensType int32u + 0xb028 MinoltaMakerNote Minolta + 0xb029 ColorMode int32u + 0xb02a LensSpec int8u[8] + 0xb02b FullImageSize int32u[2] + 0xb02c PreviewImageSize int32u[2] + 0xb040 Macro int16u + 0xb041 ExposureMode int16u + 0xb042 FocusMode int16u + 0xb043 AFAreaMode int16u + 0xb044 AFIlluminator int16u + 0xb047 JPEGQuality int16u + 0xb048 FlashLevel int16s + 0xb049 ReleaseMode int16u + 0xb04a SequenceNumber int16u + 0xb04b Anti-Blur int16u + 0xb04e FocusMode int16u + 0xb04f DynamicRangeOptimizer int16u + 0xb050 HighISONoiseReduction2 int16u + 0xb052 IntelligentAuto int16u + 0xb054 WhiteBalance int16u + +=head3 Sony CameraInfo Tags + +Camera information for the A700, A850 and A900. + + Index1 Tag Name Writable + ------ -------- -------- + 0 LensSpec undef[8] + 20 FocusModeSetting int8u + 21 AFPointSelected int8u + 25 AFPoint int8u + 30 AFStatusActiveSensor int16s + 32 AFStatusUpper-left int16s + 34 AFStatusLeft int16s + 36 AFStatusLower-left int16s + 38 AFStatusFarLeft int16s + 40 AFStatusBottomAssist-left int16s + 42 AFStatusBottom int16s + 44 AFStatusBottomAssist-right int16s + 46 AFStatusCenter-7 int16s + 48 AFStatusCenter-horizontal int16s + 50 AFStatusCenter-9 int16s + 52 AFStatusCenter-10 int16s + 54 AFStatusCenter-11 int16s + 56 AFStatusCenter-12 int16s + 58 AFStatusCenter-vertical int16s + 60 AFStatusCenter-14 int16s + 62 AFStatusTopAssist-left int16s + 64 AFStatusTop int16s + 66 AFStatusTopAssist-right int16s + 68 AFStatusFarRight int16s + 70 AFStatusUpper-right int16s + 72 AFStatusRight int16s + 74 AFStatusLower-right int16s + 76 AFStatusCenterF2-8 int16s + 304 AFMicroAdjValue int8u + 305 AFMicroAdjMode int8u & 0x80 + 305.1 AFMicroAdjRegisteredLenses int8u & 0x7f + +=head3 Sony CameraInfo2 Tags + +Camera information for the DSLR-A200, A230, A290, A300, A330, A350, A380 and +A390. + + Index1 Tag Name Writable + ------ -------- -------- + 0 LensSpec undef[8] + 20 AFPointSelected int8u + 21 FocusModeSetting int8u + 24 AFPoint int8u + 27 AFStatusActiveSensor int16s + 29 AFStatusTop-right int16s + 31 AFStatusBottom-right int16s + 33 AFStatusBottom int16s + 35 AFStatusMiddleHorizontal int16s + 37 AFStatusCenterVertical int16s + 39 AFStatusTop int16s + 41 AFStatusTop-left int16s + 43 AFStatusBottom-left int16s + 45 AFStatusLeft int16s + 47 AFStatusCenterHorizontal int16s + 49 AFStatusRight int16s + +=head3 Sony CameraInfo3 Tags + +Camera information stored by the A33, A35, A55, A450, A500, A550, A560, +A580, NEX-3/5/5C/C3 and VG10E. Some tags are valid only for some of these +models. + + Index1 Tag Name Writable + ------ -------- -------- + 0 LensSpec undef[8] + 14 FocalLength int16u + 16 FocalLengthTeleZoom int16u + 20 AFPointSelected int8u + 21 FocusMode int8u + 24 AFPoint int8u + 25 FocusStatus int8u + 27 AFStatusActiveSensor int16s + 28 AFPointSelected int8u + 29 FocusMode int8u + AFStatusTop-right int16s + 31 AFStatusBottom-right int16s + 32 AFPoint int8u + 33 AFStatusActiveSensor int16s + AFStatusBottom int16s + 35 AFStatus15 Sony AFStatus15 + AFStatusMiddleHorizontal int16s + 37 AFStatusCenterVertical int16s + 39 AFStatusTop int16s + 41 AFStatusTop-left int16s + 43 AFStatusBottom-left int16s + 45 AFStatusLeft int16s + 47 AFStatusCenterHorizontal int16s + 49 AFStatusRight int16s + +=head3 Sony AFStatus15 Tags + +AF Status information for models with 15-point AF. + + Index1 Tag Name Writable + ------ -------- -------- + 0 AFStatusUpper-left int16s + 2 AFStatusLeft int16s + 4 AFStatusLower-left int16s + 6 AFStatusFarLeft int16s + 8 AFStatusTopHorizontal int16s + 10 AFStatusNearRight int16s + 12 AFStatusCenterHorizontal int16s + 14 AFStatusNearLeft int16s + 16 AFStatusBottomHorizontal int16s + 18 AFStatusTopVertical int16s + 20 AFStatusCenterVertical int16s + 22 AFStatusBottomVertical int16s + 24 AFStatusFarRight int16s + 26 AFStatusUpper-right int16s + 28 AFStatusRight int16s + 30 AFStatusLower-right int16s + 32 AFStatusUpper-middle int16s + 34 AFStatusLower-middle int16s + +=head3 Sony CameraInfoUnknown Tags + + Index1 Tag Name Writable + ------ -------- -------- + [no tags known] + +=head3 Sony FocusInfo Tags + +More camera settings and focus information decoded for models such as the +A200, A230, A290, A300, A330, A350, A380, A390, A700, A850 and A900. + + Index1 Tag Name Writable + ------ -------- -------- + 14 DriveMode2 int8u + 16 Rotation int8u + 20 ImageStabilizationSetting int8u + 21 DynamicRangeOptimizerMode int8u + 43 BracketShotNumber int8u + 44 WhiteBalanceBracketing int8u + 45 BracketShotNumber2 int8u + 46 DynamicRangeOptimizerBracket int8u + 47 ExposureBracketShotNumber int8u + 63 ExposureProgram int8u + 65 CreativeStyle int8u + 109 ISOSetting int8u + 111 ISO int8u + 119 DynamicRangeOptimizerMode int8u + 121 DynamicRangeOptimizerLevel int8u + 2118 ShutterCount int32u + 2491 FocusPosition int8u + 4368 TiffMeteringImage no + +=head3 Sony MoreInfo Tags + +More camera settings information decoded for the A450, A500, A550, A560, +A580, A33, A35, A55, NEX-3/5/C3 and VG10E. + + Tag ID Tag Name Writable + ------ -------- -------- + 0x0001 MoreSettings Sony MoreSettings + 0x0002 FaceInfo Sony FaceInfo + FaceInfoA Sony FaceInfoA + 0x0107 TiffMeteringImage no + 0x0201 MoreInfo0201 Sony MoreInfo0201 + 0x0401 MoreInfo0401 Sony MoreInfo0401 + +=head3 Sony MoreSettings Tags + + Index1 Tag Name Writable + ------ -------- -------- + 1 DriveMode2 int8u + 2 ExposureProgram int8u + 3 MeteringMode int8u + 4 DynamicRangeOptimizerSetting int8u + 5 DynamicRangeOptimizerLevel int8u + 6 ColorSpace int8u + 7 CreativeStyleSetting int8u + 8 ContrastSetting int8s + 9 SaturationSetting int8s + 10 SharpnessSetting int8s + 13 WhiteBalanceSetting int8u + 14 ColorTemperatureSetting int8u + 15 ColorCompensationFilterSet int8s + 16 FlashMode int8u + 17 LongExposureNoiseReduction int8u + 18 HighISONoiseReduction int8u + 19 FocusMode int8u + 21 MultiFrameNoiseReduction int8u + 22 HDRSetting int8u + 23 HDRLevel int8u + 24 ViewingMode int8u + 25 FaceDetection int8u + 26 CustomWB_RBLevels int16uRev[2] + 30 BrightnessValue int8u + ExposureCompensationSet int8u + 31 ISO int8u + FlashExposureCompSet int8u + 32 FNumber int8u + LiveViewAFMethod int8u + 33 ExposureTime int8u + ISO int8u + 34 FNumber int8u + 35 FocalLength2 int8u + ExposureTime int8u + 36 ExposureCompensation2 int16s + 37 FocalLength2 int8u + ISO int8u + 38 FlashExposureCompSet2 int16s + ExposureCompensation2 int16s + FNumber int8u + 39 ExposureTime int8u + 40 Orientation2 int8u + 41 FocusPosition2 int8u + FocalLength2 int8u + 42 FlashAction int8u + ExposureCompensation2 int16s + 43 FocusPosition2 int8u + 44 FocusMode2 int8u + FlashAction int8u + FlashExposureCompSet2 int16s + 46 FocusMode2 int8u + Orientation2 int8u + 47 FocusPosition2 int8u + 48 FlashAction int8u + 50 FocusMode2 int8u + 119 FlashAction2 int8u + 120 FlashActionExternal int8u + 124 FlashActionExternal int8u + 130 FlashStatus int8u + 134 FlashStatus int8u + +=head3 Sony FaceInfo Tags + + Index2 Tag Name Writable + ------ -------- -------- + 0 FacesDetected int16s + 1 Face1Position int16u[4] + 6 Face2Position int16u[4] + 11 Face3Position int16u[4] + 16 Face4Position int16u[4] + 21 Face5Position int16u[4] + 26 Face6Position int16u[4] + 31 Face7Position int16u[4] + 36 Face8Position int16u[4] + +=head3 Sony FaceInfoA Tags + + Index2 Tag Name Writable + ------ -------- -------- + 3 FacesDetected no + 11 PotentialFace1Position int16u[4] + 21 PotentialFace2Position int16u[4] + 31 PotentialFace3Position int16u[4] + 41 PotentialFace4Position int16u[4] + 51 PotentialFace5Position int16u[4] + 61 PotentialFace6Position int16u[4] + 71 PotentialFace7Position int16u[4] + 81 PotentialFace8Position int16u[4] + 91 Face1Position int16u[4] + 101 Face2Position int16u[4] + 111 Face3Position int16u[4] + 121 Face4Position int16u[4] + +=head3 Sony MoreInfo0201 Tags + + Index1 Tag Name Writable + ------ -------- -------- + 283 ImageCount int32u + 293 ShutterCount int32u + 330 ShutterCount int32u + +=head3 Sony MoreInfo0401 Tags + + Index1 Tag Name Writable + ------ -------- -------- + 1102 ShotNumberSincePowerUp int32u + +=head3 Sony CameraSettings Tags + +Camera settings for the A200, A300, A350, A700, A850 and A900. + + Index2 Tag Name Writable + ------ -------- -------- + 0 ExposureTime int16u + 1 FNumber int16u + 2 HighSpeedSync int16u + 3 ExposureCompensationSet int16u + 4 DriveMode int16u & 0xff + 5 WhiteBalanceSetting int16u + 6 WhiteBalanceFineTune int16u + 7 ColorTemperatureSet int16u + 8 ColorCompensationFilterSet int16u + 12 ColorTemperatureCustom int16u + 13 ColorCompensationFilterCustom int16u + 15 WhiteBalance int16u + 16 FocusModeSetting int16u + 17 AFAreaMode int16u + 18 AFPointSetting int16u + 19 FlashMode int16u + 20 FlashExposureCompSet int16u + 21 MeteringMode int16u + 22 ISOSetting int16u + 24 DynamicRangeOptimizerMode int16u + 25 DynamicRangeOptimizerLevel int16u + 26 CreativeStyle int16u + 27 ColorSpace int16u + 28 Sharpness int16u + 29 Contrast int16u + 30 Saturation int16u + 31 ZoneMatchingValue int16u + 34 Brightness int16u + 35 FlashControl int16u + 40 PrioritySetupShutterRelease int16u + 41 AFIlluminator int16u + 42 AFWithShutter int16u + 43 LongExposureNoiseReduction int16u + 44 HighISONoiseReduction int16u + 45 ImageStyle int16u + 46 FocusModeSwitch int16u + 47 ShutterSpeedSetting int16u + 48 ApertureSetting int16u + 60 ExposureProgram int16u + 61 ImageStabilizationSetting int16u + 62 FlashAction int16u + 63 Rotation int16u + 64 AELock int16u + 76 FlashAction2 int16u + 77 FocusMode int16u + 80 BatteryState int16u + 81 BatteryLevel int16u + 83 FocusStatus int16u + 84 SonyImageSize int16u + 85 AspectRatio int16u + 86 Quality int16u + 88 ExposureLevelIncrements int16u + 106 RedEyeReduction int16u + 154 FolderNumber int16u & 0x3ff + 155 ImageNumber int16u & 0x3fff + +=head3 Sony CameraSettings2 Tags + +Camera settings for the A230, A290, A330, A380 and A390. + + Index2 Tag Name Writable + ------ -------- -------- + 0 ExposureTime int16u + 1 FNumber int16u + 2 HighSpeedSync int16u + 3 ExposureCompensationSet int16u + 4 WhiteBalanceSetting int16u + 5 WhiteBalanceFineTune int16u + 6 ColorTemperatureSet int16u + 7 ColorCompensationFilterSet int16u + 8 CustomWB_RGBLevels int16u[3] + 11 ColorTemperatureCustom int16u + 12 ColorCompensationFilterCustom int16u + 14 WhiteBalance int16u + 15 FocusModeSetting int16u + 16 AFAreaMode int16u + 17 AFPointSetting int16u + 18 FlashExposureCompSet int16u + 19 MeteringMode int16u + 20 ISOSetting int16u + 22 DynamicRangeOptimizerMode int16u + 23 DynamicRangeOptimizerLevel int16u + 24 CreativeStyle int16u + 25 Sharpness int16u + 26 Contrast int16u + 27 Saturation int16u + 31 FlashControl int16u + 37 LongExposureNoiseReduction int16u + 38 HighISONoiseReduction int16u + 39 ImageStyle int16u + 40 ShutterSpeedSetting int16u + 41 ApertureSetting int16u + 60 ExposureProgram int16u + 61 ImageStabilizationSetting int16u + 62 FlashAction int16u + 63 Rotation int16u + 64 AELock int16u + 76 FlashAction2 int16u + 77 FocusMode int16u + 83 FocusStatus int16u + 84 SonyImageSize int16u + 85 AspectRatio int16u + 86 Quality int16u + 88 ExposureLevelIncrements int16u + 126 DriveMode int16u & 0xff + 127 FlashMode int16u + 131 ColorSpace int16u + +=head3 Sony CameraSettings3 Tags + +Camera settings for models such as the A33, A35, A55, A450, A500, A550, +A560, A580, NEX-3, NEX-5, NEX-C3 and NEX-VG10E. + + Index1 Tag Name Writable + ------ -------- -------- + 0 ShutterSpeedSetting int8u + 1 ApertureSetting int8u + 2 ISOSetting int8u + 3 ExposureCompensationSet int8u + 4 DriveModeSetting int8u + 5 ExposureProgram int8u + 6 FocusModeSetting int8u + 7 MeteringMode int8u + 9 SonyImageSize int8u + 10 AspectRatio int8u + 11 Quality int8u + 12 DynamicRangeOptimizerSetting int8u + 13 DynamicRangeOptimizerLevel int8u + 14 ColorSpace int8u + 15 CreativeStyleSetting int8u + 16 ContrastSetting int8s + 17 SaturationSetting int8s + 18 SharpnessSetting int8s + 22 WhiteBalanceSetting int8u + 23 ColorTemperatureSetting int8u + 24 ColorCompensationFilterSet int8s + 25 CustomWB_RGBLevels int16uRev[3] + 32 FlashMode int8u + 33 FlashControl int8u + 35 FlashExposureCompSet int8u + 36 AFAreaMode int8u + 37 LongExposureNoiseReduction int8u + 38 HighISONoiseReduction int8u + 39 SmileShutterMode int8u + 40 RedEyeReduction int8u + 45 HDRSetting int8u + 46 HDRLevel int8u + 47 ViewingMode int8u + 48 FaceDetection int8u + 49 SmileShutter int8u + 50 SweepPanoramaSize int8u + 51 SweepPanoramaDirection int8u + 52 DriveMode int8u + 53 MultiFrameNoiseReduction int8u + 54 LiveViewAFSetting int8u + 56 PanoramaSize3D int8u + 131 AFButtonPressed int8u + 132 LiveViewMetering int8u + 133 ViewingMode2 int8u + 134 AELock int8u + 135 FlashStatusBuilt-in int8u + 136 FlashStatusExternal int8u + 139 LiveViewFocusMode int8u + 153 LensMount int8u + 268 SequenceNumber int8u + 276 FolderNumber int32u & 0xffc000 + 276.1 ImageNumber int32u & 0x3fff + 512 ShotNumberSincePowerUp2 int32u + 643 AFButtonPressed int8u + 644 LiveViewMetering int8u + 645 ViewingMode2 int8u + 646 AELock int8u + 647 FlashStatusBuilt-in int8u + 648 FlashStatusExternal int8u + 651 LiveViewFocusMode int8u + 780 SequenceNumber int8u + 788 ImageNumber int16u & 0x3fff + 790 FolderNumber int16u & 0x3ff + 1008 LensE-mountVersion int16u + 1011 LensFirmwareVersion int16u~ + 1015 LensType2 int16u + 1024 ImageNumber int16u & 0x3fff + 1026 FolderNumber int16u & 0x3ff + +=head3 Sony CameraSettingsUnknown Tags + + Index2 Tag Name Writable + ------ -------- -------- + [no tags known] + +=head3 Sony ExtraInfo Tags + +Extra hardware information for the A850 and A900. + + Index1 Tag Name Writable + ------ -------- -------- + 1 BatteryTemperature int8u + 2 BatteryUnknown? no + 8 BatteryVoltage? no + 10 ImageStabilization2? int8u + 12 BatteryLevel int8u + 26 ExtraInfoVersion int8u[4] + +=head3 Sony ExtraInfo2 Tags + +Extra hardware information for the A230/290/330/380/390. + + Index1 Tag Name Writable + ------ -------- -------- + 4 BatteryLevel int8u + 18 ImageStabilization int8u + +=head3 Sony ExtraInfo3 Tags + +Extra hardware information for the A33, A35, A55, A450, A500, A550, A560, +A580 and NEX-3/5/C3/VG10. + + Index1 Tag Name Writable + ------ -------- -------- + 0 BatteryUnknown? int16u + 2 BatteryTemperature int8u + 4 BatteryLevel int8u + 6 BatteryVoltage1 int16u + 8 BatteryVoltage2 int16u + 17 ImageStabilization int8u + 20 BatteryState int8u + ExposureProgram int8u + ModeDialPosition int8u + 22 MemoryCardConfiguration int8u & 0xc0 + CameraOrientation int8u + 24 CameraOrientation int8u & 0x30 + +=head3 Sony Panorama Tags + +Tags found in panorama images from various Sony DSC, NEX, SLT and DSLR +cameras. The width/height values of these tags are not affected by camera +rotation -- the width is always the longer dimension. + + Index4 Tag Name Writable + ------ -------- -------- + 1 PanoramaFullWidth int32u + 2 PanoramaFullHeight int32u + 3 PanoramaDirection int32u + 4 PanoramaCropLeft int32u + 5 PanoramaCropTop int32u + 6 PanoramaCropRight int32u + 7 PanoramaCropBottom int32u + 8 PanoramaFrameWidth int32u + 9 PanoramaFrameHeight int32u + 10 PanoramaSourceWidth int32u + 11 PanoramaSourceHeight int32u + +=head3 Sony Tag2010a Tags + +Valid for NEX-5N. + + Tag ID Tag Name Writable + ------ -------- -------- + 0x04b0 MeterInfo? Sony MeterInfo + 0x1128 ReleaseMode3 int8u + 0x112c ReleaseMode2 int8u + 0x1134 SelfTimer int8u + 0x1138 FlashMode int8u + 0x113e StopsAboveBaseISO int16u + 0x1140 BrightnessValue int16u + 0x1144 DynamicRangeOptimizer int8u + 0x1148 HDRSetting int8u + 0x114c ExposureCompensation int16s + 0x115e PictureProfile int8u + 0x115f PictureProfile int8u + 0x1163 PictureEffect2 int8u + 0x1170 Quality2 int8u + 0x1174 MeteringMode int8u + 0x1175 ExposureProgram int8u + 0x117c WB_RGBLevels int16u[3] + +=head3 Sony MeterInfo Tags + +Information possibly related to metering. Extracted only if the Unknown +option is used. + + Index1 Tag Name Writable + ------ -------- -------- + 0 MeterInfo1Row1 int32u[27] + 108 MeterInfo1Row2 int32u[27] + 216 MeterInfo1Row3 int32u[27] + 324 MeterInfo1Row4 int32u[27] + 432 MeterInfo1Row5 int32u[27] + 540 MeterInfo1Row6 int32u[27] + 648 MeterInfo1Row7 int32u[27] + 756 MeterInfo2Row1 int32u[33] + 888 MeterInfo2Row2 int32u[33] + 1020 MeterInfo2Row3 int32u[33] + 1152 MeterInfo2Row4 int32u[33] + 1284 MeterInfo2Row5 int32u[33] + 1416 MeterInfo2Row6 int32u[33] + 1548 MeterInfo2Row7 int32u[33] + 1680 MeterInfo2Row8 int32u[33] + 1812 MeterInfo2Row9 int32u[33] + +=head3 Sony Tag2010b Tags + +Valid for SLT-A65/A77, NEX-7/VG20E. + + Tag ID Tag Name Writable + ------ -------- -------- + 0x0000 SequenceImageNumber int32u + 0x0004 SequenceFileNumber int32u + 0x0008 ReleaseMode2 int32u + 0x01b6 SonyDateTime undef[7] + 0x0324 DynamicRangeOptimizer int8u + 0x04b4 MeterInfo? Sony MeterInfo + 0x1128 ReleaseMode3 int8u + 0x112c ReleaseMode2 int8u + 0x1134 SelfTimer int8u + 0x1138 FlashMode int8u + 0x113e StopsAboveBaseISO int16u + 0x1140 BrightnessValue int16u + 0x1144 DynamicRangeOptimizer int8u + 0x1148 HDRSetting int8u + 0x114c ExposureCompensation int16s + 0x1162 PictureProfile int8u + 0x1163 PictureProfile int8u + 0x1167 PictureEffect2 int8u + 0x1174 Quality2 int8u + 0x1178 MeteringMode int8u + 0x1179 ExposureProgram int8u + 0x1180 WB_RGBLevels int16u[3] + 0x1218 SonyISO int16u + 0x1a23 DistortionCorrParams int16s[16] + +=head3 Sony Tag2010c Tags + +Valid for SLT-A37/A57 and NEX-F3. + + Tag ID Tag Name Writable + ------ -------- -------- + 0x0000 SequenceImageNumber int32u + 0x0004 SequenceFileNumber int32u + 0x0008 ReleaseMode2 int32u + 0x0200 DigitalZoomRatio int8u + 0x0210 SonyDateTime undef[7] + 0x0300 DynamicRangeOptimizer int8u + 0x0490 MeterInfo? Sony MeterInfo + 0x1104 ReleaseMode3 int8u + 0x1108 ReleaseMode2 int8u + 0x1110 SelfTimer int8u + 0x1114 FlashMode int8u + 0x111a StopsAboveBaseISO int16u + 0x111c BrightnessValue int16u + 0x1120 DynamicRangeOptimizer int8u + 0x1124 HDRSetting int8u + 0x1128 ExposureCompensation int16s + 0x113e PictureProfile int8u + 0x113f PictureProfile int8u + 0x1143 PictureEffect2 int8u + 0x1150 Quality2 int8u + 0x1154 MeteringMode int8u + 0x1155 ExposureProgram int8u + 0x115c WB_RGBLevels int16u[3] + 0x11f4 SonyISO int16u + +=head3 Sony Tag2010d Tags + +Valid for DSC-HX10V/HX20V/HX200V/TX66/TX200V/TX300V/WX50/WX100/WX150, but +not valid for panorama images. + + Tag ID Tag Name Writable + ------ -------- -------- + 0x0000 SequenceImageNumber int32u + 0x0004 SequenceFileNumber int32u + 0x0008 ReleaseMode2 int32u + 0x01fe SonyDateTime undef[7] + 0x037c DynamicRangeOptimizer int8u + 0x050c MeterInfo? Sony MeterInfo + 0x1180 ReleaseMode3 int8u + 0x1184 ReleaseMode2 int8u + 0x118c SelfTimer int8u + 0x1190 FlashMode int8u + 0x1196 StopsAboveBaseISO int16u + 0x1198 BrightnessValue int16u + 0x119c DynamicRangeOptimizer int8u + 0x11a0 HDRSetting int8u + 0x11ba PictureProfile int8u + 0x11bb PictureProfile int8u + 0x11bf PictureEffect2 int8u + 0x11d0 MeteringMode int8u + 0x11d1 ExposureProgram int8u + 0x11d8 WB_RGBLevels int16u[3] + 0x1270 SonyISO int16u + +=head3 Sony Tag2010e Tags + +Valid for SLT-A58/A99, ILCE-3000/3500, NEX-3N/5R/5T/6/VG30E/VG900, DSC-RX100, +DSC-RX1/RX1R. Also valid for DSC-HX300/HX50V/TX30/WX60/WX200/WX300, but not +for panorama images. + + Tag ID Tag Name Writable + ------ -------- -------- + 0x0000 SequenceImageNumber int32u + 0x0004 SequenceFileNumber int32u + 0x0008 ReleaseMode2 int32u + 0x021c DigitalZoomRatio int8u + 0x022c SonyDateTime undef[7] + 0x0328 DynamicRangeOptimizer int8u + 0x04b8 MeterInfo? Sony MeterInfo + 0x115c ReleaseMode3 int8u + 0x1160 ReleaseMode2 int8u + 0x1168 SelfTimer int8u + 0x116c FlashMode int8u + 0x1172 StopsAboveBaseISO int16u + 0x1174 BrightnessValue int16u + 0x1178 DynamicRangeOptimizer int8u + 0x117c HDRSetting int8u + 0x1180 ExposureCompensation int16s + 0x1196 PictureProfile int8u + 0x1197 PictureProfile int8u + 0x119b PictureEffect2 int8u + 0x11a8 Quality2 int8u + 0x11ac MeteringMode int8u + 0x11ad ExposureProgram int8u + 0x11b4 WB_RGBLevels int16u[3] + 0x1254 SonyISO int16u + 0x1258 SonyISO int16u + 0x1278 FocalLength int16u + 0x127a MinFocalLength int16u + 0x127c MaxFocalLength int16u + 0x1280 SonyISO int16u + 0x1870 DistortionCorrParams int16s[16] + 0x1891 LensFormat int8u + 0x1892 LensMount int8u + 0x1893 LensType2 int16u + 0x1896 LensType int16u + 0x1898 DistortionCorrParamsPresent int8u + 0x1899 DistortionCorrParamsNumber int8u + +=head3 Sony Tag2010f Tags + +Valid for DSC-RX100M2, DSC-QX10/QX100. + + Tag ID Tag Name Writable + ------ -------- -------- + 0x0004 ReleaseMode2 int32u + 0x0050 DynamicRangeOptimizer int8u + 0x01e0 MeterInfo? Sony MeterInfo + 0x1014 ReleaseMode3 int8u + 0x1018 ReleaseMode2 int8u + 0x1020 SelfTimer int8u + 0x1024 FlashMode int8u + 0x102a StopsAboveBaseISO int16u + 0x102c BrightnessValue int16u + 0x1030 DynamicRangeOptimizer int8u + 0x1034 HDRSetting int8u + 0x1038 ExposureCompensation int16s + 0x104e PictureProfile int8u + 0x104f PictureProfile int8u + 0x1053 PictureEffect2 int8u + 0x1060 Quality2 int8u + 0x1064 MeteringMode int8u + 0x1065 ExposureProgram int8u + 0x106c WB_RGBLevels int16u[3] + 0x1134 FocalLength int16u + 0x1136 MinFocalLength int16u + 0x1138 MaxFocalLength int16u + 0x113c SonyISO int16u + +=head3 Sony Tag2010g Tags + +Valid for DSC-HX60V/HX350/HX400V/QX30/RX10/RX100M3/WX220/WX350, +ILCE-7/7R/7S/7M2/5000/5100/6000/QX1, ILCA-68/77M2. + + Tag ID Tag Name Writable + ------ -------- -------- + 0x0004 ReleaseMode2 int32u + 0x0050 DynamicRangeOptimizer int8u + 0x020c ReleaseMode3 int8u + 0x0210 ReleaseMode2 int8u + 0x0218 SelfTimer int8u + 0x021c FlashMode int8u + 0x0222 StopsAboveBaseISO int16u + 0x0224 BrightnessValue int16u + 0x0228 DynamicRangeOptimizer int8u + 0x022c HDRSetting int8u + 0x0230 ExposureCompensation int16s + 0x0246 PictureProfile int8u + 0x0247 PictureProfile int8u + 0x024b PictureEffect2 int8u + 0x0258 Quality2 int8u + 0x025c MeteringMode int8u + 0x025d ExposureProgram int8u + 0x0264 WB_RGBLevels int16u[3] + 0x032c FocalLength int16u + 0x032e MinFocalLength int16u + 0x0330 MaxFocalLength int16u + 0x0344 SonyISO int16u + 0x0388 MeterInfo? Sony MeterInfo + 0x189c DistortionCorrParams int16s[16] + 0x18bd LensFormat int8u + 0x18be LensMount int8u + 0x18bf LensType2 int16u + 0x18c2 LensType int16u + 0x18c4 DistortionCorrParamsPresent int8u + 0x18c5 DistortionCorrParamsNumber int8u + +=head3 Sony Tag2010h Tags + +Valid for DSC-HX80/HX90V/RX0/RX1RM2/RX10M2/RX10M3/RX100M4/RX100M5/WX500, +ILCE-6300/6500/7RM2/7SM2, ILCA-99M2. + + Tag ID Tag Name Writable + ------ -------- -------- + 0x0004 ReleaseMode2 int32u + 0x0050 DynamicRangeOptimizer int8u + 0x020c ReleaseMode3 int8u + 0x0210 ReleaseMode2 int8u + 0x0218 SelfTimer int8u + 0x021c FlashMode int8u + 0x0222 StopsAboveBaseISO int16u + 0x0224 BrightnessValue int16u + 0x0228 DynamicRangeOptimizer int8u + 0x022c HDRSetting int8u + 0x0230 ExposureCompensation int16s + 0x0246 PictureProfile int8u + 0x0247 PictureProfile int8u + 0x024b PictureEffect2 int8u + 0x0258 Quality2 int8u + 0x025c MeteringMode int8u + 0x025d ExposureProgram int8u + 0x0264 WB_RGBLevels int16u[3] + 0x032c FocalLength int16u + 0x032e MinFocalLength int16u + 0x0330 MaxFocalLength int16u + 0x0346 SonyISO int16u + 0x0388 MeterInfo? Sony MeterInfo + 0x0398 MeterInfo? Sony MeterInfo + 0x18cc DistortionCorrParams int16s[16] + 0x18ed LensFormat int8u + 0x18ee LensMount int8u + 0x18ef LensType2 int16u + 0x18f2 LensType int16u + 0x18f4 DistortionCorrParamsPresent int8u + 0x18f5 DistortionCorrParamsNumber int8u + +=head3 Sony Tag2010i Tags + +Valid for ILCE-6400/7M3/7RM3/9, DSC-RX10M4/RX100M6/RX100M5A/HX99. + + Tag ID Tag Name Writable + ------ -------- -------- + 0x0004 ReleaseMode2 int32u + 0x004e DynamicRangeOptimizer int8u + 0x0204 ReleaseMode3 int8u + 0x0208 ReleaseMode2 int8u + 0x0210 SelfTimer int8u + 0x0211 FlashMode int8u + 0x0217 StopsAboveBaseISO int16u + 0x0219 BrightnessValue int16u + 0x021b DynamicRangeOptimizer int8u + 0x021f HDRSetting int8u + 0x0223 ExposureCompensation int16s + 0x0237 PictureProfile int8u + 0x0238 PictureProfile int8u + 0x023c PictureEffect2 int8u + 0x0247 Quality2 int8u + 0x024b MeteringMode int8u + 0x024c ExposureProgram int8u + 0x0252 WB_RGBLevels int16u[3] + 0x030a FocalLength int16u + 0x030c MinFocalLength int16u + 0x030e MaxFocalLength int16u + 0x0320 SonyISO int16u + 0x036d MeterInfo? Sony MeterInfo9 + 0x17d0 DistortionCorrParams int16s[16] + 0x17f1 LensFormat int8u + 0x17f2 LensMount int8u + 0x17f3 LensType2 int16u + 0x17f6 LensType int16u + 0x17f8 DistortionCorrParamsPresent int8u + 0x17f9 DistortionCorrParamsNumber int8u + +=head3 Sony MeterInfo9 Tags + +Information possibly related to metering. Extracted only if the Unknown +option is used. + + Index1 Tag Name Writable + ------ -------- -------- + 0 MeterInfo1Row1 no + 90 MeterInfo1Row2 no + 180 MeterInfo1Row3 no + 270 MeterInfo1Row4 no + 360 MeterInfo1Row5 no + 450 MeterInfo1Row6 no + 540 MeterInfo1Row7 no + 630 MeterInfo2Row1 no + 740 MeterInfo2Row2 no + 850 MeterInfo2Row3 no + 960 MeterInfo2Row4 no + 1070 MeterInfo2Row5 no + 1180 MeterInfo2Row6 no + 1290 MeterInfo2Row7 no + 1400 MeterInfo2Row8 no + 1510 MeterInfo2Row9 no + +=head3 Sony Tag202a Tags + + Index1 Tag Name Writable + ------ -------- -------- + 1 FocalPlaneAFPointsUsed int8u + 2 FocalPlaneAFPointArea int16u[2] + 6 FocalPlaneAFPointLocation1 int16u[2] + 10 FocalPlaneAFPointLocation2 int16u[2] + 14 FocalPlaneAFPointLocation3 int16u[2] + 18 FocalPlaneAFPointLocation4 int16u[2] + 22 FocalPlaneAFPointLocation5 int16u[2] + 26 FocalPlaneAFPointLocation6 int16u[2] + 30 FocalPlaneAFPointLocation7 int16u[2] + 34 FocalPlaneAFPointLocation8 int16u[2] + 38 FocalPlaneAFPointLocation9 int16u[2] + 42 FocalPlaneAFPointLocation10 int16u[2] + 46 FocalPlaneAFPointLocation11 int16u[2] + 50 FocalPlaneAFPointLocation12 int16u[2] + 54 FocalPlaneAFPointLocation13 int16u[2] + 58 FocalPlaneAFPointLocation14 int16u[2] + 62 FocalPlaneAFPointLocation15 int16u[2] + +=head3 Sony ShotInfo Tags + + Index1 Tag Name Writable + ------ -------- -------- + 2 FaceInfoOffset no + 6 SonyDateTime string[20] + 26 SonyImageHeight int16u + 28 SonyImageWidth int16u + 48 FacesDetected int16u + 50 FaceInfoLength no + 52 MetaVersion string[16] + 72 FaceInfo1 Sony FaceInfo1 + 94 FaceInfo2 Sony FaceInfo2 + +=head3 Sony FaceInfo1 Tags + + Index1 Tag Name Writable + ------ -------- -------- + 0 Face1Position int16u[4] + 32 Face2Position int16u[4] + 64 Face3Position int16u[4] + 96 Face4Position int16u[4] + 128 Face5Position int16u[4] + 160 Face6Position int16u[4] + 192 Face7Position int16u[4] + 224 Face8Position int16u[4] + +=head3 Sony FaceInfo2 Tags + + Index1 Tag Name Writable + ------ -------- -------- + 0 Face1Position int16u[4] + 37 Face2Position int16u[4] + 74 Face3Position int16u[4] + 111 Face4Position int16u[4] + 148 Face5Position int16u[4] + 185 Face6Position int16u[4] + 222 Face7Position int16u[4] + 259 Face8Position int16u[4] + +=head3 Sony Tag900b Tags + + Tag ID Tag Name Writable + ------ -------- -------- + 0x0002 FacesDetected no + 0x00bd FaceDetection no + +=head3 Sony Tag9050a Tags + +Data for tags 0x9050, 0x94xx and 0x2010 is encrypted by a simple +substitution cipher, but the deciphered values are listed below. + + Tag ID Tag Name Writable + ------ -------- -------- + 0x0000 SonyMaxAperture int8u + 0x0001 SonyMinAperture int8u + 0x0031 FlashStatus int8u + 0x0032 ShutterCount int32u + 0x003a SonyExposureTime int16u + 0x003c SonyFNumber int16u + 0x003f ReleaseMode2 int8u + 0x004c ShutterCount2 int32u + 0x0051 SonyDateTime2 undef[6] + 0x0067 ReleaseMode2 int8u + 0x007c InternalSerialNumber int8u[4]~ + 0x00f0 InternalSerialNumber int8u[5] + 0x0105 LensMount int8u + 0x0106 LensFormat int8u + 0x0107 LensType2 int16u + 0x0109 LensType int16u + 0x010b DistortionCorrParamsPresent int8u + 0x0115 LensSpecFeatures undef[2] + 0x0116 LensSpecFeatures undef[2] + 0x01a0 ShutterCount3 int32u + 0x01aa ShutterCount3 int32u + 0x01bd ShutterCount3 int32u + +=head3 Sony Tag9050b Tags + +Valid from July 2015 for ILCE-6300/6400/6500/7M3/7RM2/7RM3/7SM2/9, +ILCA-99M2. + + Tag ID Tag Name Writable + ------ -------- -------- + 0x0000 SonyMaxAperture int8u + 0x0001 SonyMinAperture int8u + 0x002c Shutter int8u + 0x0039 FlashStatus int8u + 0x003a ShutterCount int32u + 0x0046 SonyExposureTime int16u + 0x0048 SonyFNumber int16u + 0x004b ReleaseMode2 int8u + 0x0050 ShutterCount2 int32u + 0x0052 ShutterCount2 int32u + 0x0058 ShutterCount2 int32u + 0x0061 SonyTimeMinSec no + 0x006b ReleaseMode2 int8u + 0x006d ReleaseMode2 int8u + 0x0073 ReleaseMode2 int8u + 0x0088 InternalSerialNumber int8u[6]~ + 0x0105 LensMount int8u + 0x0106 LensFormat int8u + 0x0107 LensType2 int16u + 0x0109 LensType int16u + 0x010b DistortionCorrParamsPresent int8u + 0x0116 LensSpecFeatures undef[2] + 0x019f ShutterCount3 int32u + 0x01cb ShutterCount3 int32u + 0x01cd ShutterCount3 int32u + 0x021c LensSpecFeatures undef[2] + 0x021e LensSpecFeatures undef[2] + +=head3 Sony Tag9400a Tags + +Valid for many DSC, NEX and SLT models + + Tag ID Tag Name Writable + ------ -------- -------- + 0x0008 SequenceImageNumber int32u + 0x000c SequenceFileNumber int32u + 0x0010 ReleaseMode2 int8u + 0x0012 DigitalZoom int8u + 0x001a ShotNumberSincePowerUp int32u + 0x0022 SequenceLength int8u + 0x0028 CameraOrientation int8u + 0x0029 Quality2 int8u + 0x0044 SonyImageHeight int16u~ + 0x0052 ModelReleaseYear int8u~ + +=head3 Sony Tag9400b Tags + +Valid for NEX-3N, ILCE-3000/3500, SLT-A58, DSC-WX60, DSC-WX300, DSC-RX100M2, +DSC-HX50V, DSC-QX10/QX100. + + Tag ID Tag Name Writable + ------ -------- -------- + 0x0008 SequenceImageNumber int32u + 0x000c SequenceFileNumber int32u + 0x0010 ReleaseMode2 int8u + 0x0012 DigitalZoom int8u + 0x0016 ShotNumberSincePowerUp int32u + 0x001e SequenceLength int8u + 0x0024 CameraOrientation int8u + 0x0025 Quality2 int8u + 0x003f SonyImageHeight int16u~ + 0x0046 ModelReleaseYear int8u~ + +=head3 Sony Tag9400c Tags + +Valid for DSC-HX60V/HX80/HX90V/HX99/HX350/HX400V/QX30/RX0/RX1RM2/RX10/ +RX10M2/RX10M3/RX10M4/RX100M3/RX100M4/RX100M5/RX100M5A/RX100M6/WX220/WX350/ +WX500, ILCE-7/7R/7S/7M2/7M3/7RM2/7RM3/7SM2/9/5000/5100/6000/6300/6400/6500/ +QX1, ILCA-68/77M2/99M2. + + Tag ID Tag Name Writable + ------ -------- -------- + 0x0009 ReleaseMode2 int8u + 0x000a ShotNumberSincePowerUp int8u + ShotNumberSincePowerUp int32u + 0x0012 SequenceImageNumber int32u + 0x0016 SequenceLength int8u + 0x001a SequenceFileNumber int32u + 0x001e SequenceLength int8u + 0x0029 CameraOrientation int8u + 0x002a Quality2 int8u + 0x0047 SonyImageHeight int16u~ + 0x0053 ModelReleaseYear int8u~ + +=head3 Sony Tag9401 Tags + + Tag ID Tag Name Writable + ------ -------- -------- + 0x059d ISOInfo Sony ISOInfo + 0x0634 ISOInfo Sony ISOInfo + 0x0636 ISOInfo Sony ISOInfo + 0x064c ISOInfo Sony ISOInfo + 0x0653 ISOInfo Sony ISOInfo + 0x0678 ISOInfo Sony ISOInfo + 0x06b8 ISOInfo Sony ISOInfo + 0x06de ISOInfo Sony ISOInfo + 0x06e7 ISOInfo Sony ISOInfo + +=head3 Sony ISOInfo Tags + + Index1 Tag Name Writable + ------ -------- -------- + 0 ISOSetting int8u + 2 ISOAutoMin int8u + 4 ISOAutoMax int8u + +=head3 Sony Tag9402 Tags + + Tag ID Tag Name Writable + ------ -------- -------- + 0x0004 AmbientTemperature int8s + 0x0016 FocusMode int8u & 0x7f + 0x0017 AFAreaMode int8u + 0x002d FocusPosition2 int8u + +=head3 Sony Tag9403 Tags + + Tag ID Tag Name Writable + ------ -------- -------- + 0x0005 CameraTemperature int8s + +=head3 Sony Tag9404a Tags + + Tag ID Tag Name Writable + ------ -------- -------- + 0x000b ExposureProgram int8u + 0x000d IntelligentAuto int8u + 0x0019 LensZoomPosition int16u + +=head3 Sony Tag9404b Tags + + Tag ID Tag Name Writable + ------ -------- -------- + 0x000c ExposureProgram int8u + 0x000e IntelligentAuto int8u + 0x001e LensZoomPosition int16u + 0x0020 FocusPosition2 int8u + +=head3 Sony Tag9404c Tags + + Tag ID Tag Name Writable + ------ -------- -------- + 0x000b ExposureProgram int8u + 0x000d IntelligentAuto int8u + +=head3 Sony Tag9405a Tags + +Valid for SLT, NEX, ILCE-3000/3500 and several DSC models. + + Tag ID Tag Name Writable + ------ -------- -------- + 0x0600 DistortionCorrParamsPresent int8u + 0x0601 DistortionCorrection int8u + 0x0603 LensFormat int8u + 0x0604 LensMount int8u + 0x0605 LensType2 int16u + 0x0608 LensType int16u + 0x064a VignettingCorrParams int16s[16] + 0x066a ChromaticAberrationCorrParams int16s[32] + 0x06ca DistortionCorrParams int16s[16] + +=head3 Sony Tag9405b Tags + +Valid for DSC-HX60V/HX80/HX90V/HX99/HX350/HX400V/QX30/RX0/RX10/RX10M2/ +RX10M3/RX10M4/RX100M3/RX100M4/RX100M5/RX100M5A/RX100M6/WX220/WX350, ILCE-7/ +7M2/7M3/7R/7RM2/7S/7SM2/9/5000/5100/6000/6300/6500/QX1, ILCA-68/77M2/99M2. + + Tag ID Tag Name Writable + ------ -------- -------- + 0x0004 SonyISO int16u + 0x0006 BaseISO int16u + 0x000a StopsAboveBaseISO int16u + 0x000e SonyExposureTime2 int16u + 0x0010 ExposureTime rational32u + 0x0014 SonyFNumber int16u + 0x0016 SonyMaxApertureValue int16u + 0x0024 SequenceImageNumber int32u + 0x0034 ReleaseMode2 int8u + 0x003e SonyImageWidthMax int16u + 0x0040 SonyImageHeightMax int16u + 0x0042 HighISONoiseReduction int8u + 0x0044 LongExposureNoiseReduction int8u + 0x0046 PictureEffect2 int8u + 0x0048 ExposureProgram int8u + 0x004a CreativeStyle int8u + 0x0052 Sharpness int8s + 0x005a DistortionCorrParamsPresent int8u + 0x005b DistortionCorrection int8u + 0x005d LensFormat int8u + 0x005e LensMount int8u + 0x0060 LensType2 int16u + 0x0062 LensType int16u + 0x0064 DistortionCorrParams int16s[16] + 0x0342 LensZoomPosition int16u + 0x034a VignettingCorrParams int16s[16] + 0x0350 VignettingCorrParams int16s[16] + 0x035a LensZoomPosition int16u + 0x035c VignettingCorrParams int16s[16] + 0x0368 VignettingCorrParams int16s[16] + 0x037c ChromaticAberrationCorrParams int16s[32] + 0x0384 ChromaticAberrationCorrParams int16s[32] + 0x039c ChromaticAberrationCorrParams int16s[32] + 0x03b0 ChromaticAberrationCorrParams int16s[32] + 0x03b8 ChromaticAberrationCorrParams int16s[32] + +=head3 Sony Tag9406 Tags + + Tag ID Tag Name Writable + ------ -------- -------- + 0x0005 BatteryTemperature int8u + 0x0006 BatteryLevelGrip1 int8u + 0x0007 BatteryLevel int8u + 0x0008 BatteryLevelGrip2 int8u + +=head3 Sony Tag940a Tags + +These tags are currently extracted for SLT models only. + + Tag ID Tag Name Writable + ------ -------- -------- + 0x0004 AFPointsSelected int32u + +=head3 Sony Tag940c Tags + +NEX and ILCE models only. + + Tag ID Tag Name Writable + ------ -------- -------- + 0x0008 LensMount2 int8u + 0x0009 LensType3 int16u + 0x000b CameraE-mountVersion int16u + 0x000d LensE-mountVersion int16u + 0x0014 LensFirmwareVersion int16u~ + +=head3 Sony AFInfo Tags + +These tags are currently extracted for SLT models only. + + Tag ID Tag Name Writable + ------ -------- -------- + 0x0002 AFType int8u + 0x0004 AFStatusActiveSensor int16s + 0x0005 FocusMode int8u + 0x0007 AFPoint int8u + 0x0008 AFPointInFocus int8u + 0x0009 AFPointAtShutterRelease int8u + 0x000a AFAreaMode int8u + 0x000b FocusMode int8u + 0x0010 AFPointsUsed int8u[10] + 0x0011 AFStatus15 Sony AFStatus15 + AFStatus19 Sony AFStatus19 + 0x0037 AFPoint int8u + 0x0038 AFPointInFocus int8u + 0x0039 AFPointAtShutterRelease int8u + 0x003a AFAreaMode int8u + 0x003b AFStatusActiveSensor int16s + 0x0043 ExposureProgram int8u + 0x0050 AFMicroAdj int8s + 0x007d AFStatus79 Sony AFStatus79 + 0x016e AFPointsUsed int32u + 0x017d AFMicroAdj int8s + 0x017e ExposureProgram int8u + +=head3 Sony AFStatus19 Tags + +AF Status information for models with 19-point AF. + + Index1 Tag Name Writable + ------ -------- -------- + 0 AFStatusUpperFarLeft int16s + 2 AFStatusUpper-leftHorizontal int16s + 4 AFStatusFarLeftHorizontal int16s + 6 AFStatusLeftHorizontal int16s + 8 AFStatusLowerFarLeft int16s + 10 AFStatusLower-leftHorizontal int16s + 12 AFStatusUpper-leftVertical int16s + 14 AFStatusLeftVertical int16s + 16 AFStatusLower-leftVertical int16s + 18 AFStatusFarLeftVertical int16s + 20 AFStatusTopHorizontal int16s + 22 AFStatusNearRight int16s + 24 AFStatusCenterHorizontal int16s + 26 AFStatusNearLeft int16s + 28 AFStatusBottomHorizontal int16s + 30 AFStatusTopVertical int16s + 32 AFStatusUpper-middle int16s + 34 AFStatusCenterVertical int16s + 36 AFStatusLower-middle int16s + 38 AFStatusBottomVertical int16s + 40 AFStatusUpperFarRight int16s + 42 AFStatusUpper-rightHorizontal int16s + 44 AFStatusFarRightHorizontal int16s + 46 AFStatusRightHorizontal int16s + 48 AFStatusLowerFarRight int16s + 50 AFStatusLower-rightHorizontal int16s + 52 AFStatusFarRightVertical int16s + 54 AFStatusUpper-rightVertical int16s + 56 AFStatusRightVertical int16s + 58 AFStatusLower-rightVertical int16s + +=head3 Sony AFStatus79 Tags + +AF Status information for models with 79-point AF. + + Index1 Tag Name Writable + ------ -------- -------- + 0 AFStatus_00_B4 int16s + 2 AFStatus_01_C4 int16s + 4 AFStatus_02_D4 int16s + 6 AFStatus_03_E4 int16s + 8 AFStatus_04_F4 int16s + 10 AFStatus_05_G4 int16s + 12 AFStatus_06_H4 int16s + 14 AFStatus_07_B3 int16s + 16 AFStatus_08_C3 int16s + 18 AFStatus_09_D3 int16s + 20 AFStatus_10_E3 int16s + 22 AFStatus_11_F3 int16s + 24 AFStatus_12_G3 int16s + 26 AFStatus_13_H3 int16s + 28 AFStatus_14_B2 int16s + 30 AFStatus_15_C2 int16s + 32 AFStatus_16_D2 int16s + 34 AFStatus_17_E2 int16s + 36 AFStatus_18_F2 int16s + 38 AFStatus_19_G2 int16s + 40 AFStatus_20_H2 int16s + 42 AFStatus_21_C1 int16s + 44 AFStatus_22_D1 int16s + 46 AFStatus_23_E1 int16s + 48 AFStatus_24_F1 int16s + 50 AFStatus_25_G1 int16s + 52 AFStatus_26_A7_Vertical int16s + 54 AFStatus_27_A6_Vertical int16s + 56 AFStatus_28_A5_Vertical int16s + 58 AFStatus_29_C7_Vertical int16s + 60 AFStatus_30_C6_Vertical int16s + 62 AFStatus_31_C5_Vertical int16s + 64 AFStatus_32_E7_Vertical int16s + 66 AFStatus_33_E6_Center_Vertical int16s + 68 AFStatus_34_E5_Vertical int16s + 70 AFStatus_35_G7_Vertical int16s + 72 AFStatus_36_G6_Vertical int16s + 74 AFStatus_37_G5_Vertical int16s + 76 AFStatus_38_I7_Vertical int16s + 78 AFStatus_39_I6_Vertical int16s + 80 AFStatus_40_I5_Vertical int16s + 82 AFStatus_41_A7 int16s + 84 AFStatus_42_B7 int16s + 86 AFStatus_43_C7 int16s + 88 AFStatus_44_D7 int16s + 90 AFStatus_45_E7 int16s + 92 AFStatus_46_F7 int16s + 94 AFStatus_47_G7 int16s + 96 AFStatus_48_H7 int16s + 98 AFStatus_49_I7 int16s + 100 AFStatus_50_A6 int16s + 102 AFStatus_51_B6 int16s + 104 AFStatus_52_C6 int16s + 106 AFStatus_53_D6 int16s + 108 AFStatus_54_E6_Center int16s + 110 AFStatus_55_F6 int16s + 112 AFStatus_56_G6 int16s + 114 AFStatus_57_H6 int16s + 116 AFStatus_58_I6 int16s + 118 AFStatus_59_A5 int16s + 120 AFStatus_60_B5 int16s + 122 AFStatus_61_C5 int16s + 124 AFStatus_62_D5 int16s + 126 AFStatus_63_E5 int16s + 128 AFStatus_64_F5 int16s + 130 AFStatus_65_G5 int16s + 132 AFStatus_66_H5 int16s + 134 AFStatus_67_I5 int16s + 136 AFStatus_68_C11 int16s + 138 AFStatus_69_D11 int16s + 140 AFStatus_70_E11 int16s + 142 AFStatus_71_F11 int16s + 144 AFStatus_72_G11 int16s + 146 AFStatus_73_B10 int16s + 148 AFStatus_74_C10 int16s + 150 AFStatus_75_D10 int16s + 152 AFStatus_76_E10 int16s + 154 AFStatus_77_F10 int16s + 156 AFStatus_78_G10 int16s + 158 AFStatus_79_H10 int16s + 160 AFStatus_80_B9 int16s + 162 AFStatus_81_C9 int16s + 164 AFStatus_82_D9 int16s + 166 AFStatus_83_E9 int16s + 168 AFStatus_84_F9 int16s + 170 AFStatus_85_G9 int16s + 172 AFStatus_86_H9 int16s + 174 AFStatus_87_B8 int16s + 176 AFStatus_88_C8 int16s + 178 AFStatus_89_D8 int16s + 180 AFStatus_90_E8 int16s + 182 AFStatus_91_F8 int16s + 184 AFStatus_92_G8 int16s + 186 AFStatus_93_H8 int16s + 188 AFStatus_94_E6_Center_F2-8 int16s + +=head3 Sony Tag940e Tags + +E-mount models. + + Tag ID Tag Name Writable + ------ -------- -------- + 0x1a06 TiffMeteringImageWidth no + 0x1a07 TiffMeteringImageHeight no + 0x1a08 TiffMeteringImage no + +=head3 Sony PIC Tags + +The TextInfo data is extracted as a block to preserve the formatting, and +some of the more interesting information is extracted as separate tags. + + Tag ID Tag Name Writable + ------ -------- -------- + 'BC:' Barcode no + 'BarCode:' Barcode no + 'Capt:' SensorTemperature no + 'FWVer:' FirmwareVersion no + 'IFD' PIC_IFD Sony + 'Temp:' CameraTemperature no + 'Temp:Clbt:' BoardTemperature no + 'TextInfo1' TextInfo1 no + 'TextInfo2' TextInfo2 no + 'VR Enable C:' VibrationReduction no + 'barcode:' Barcode no + +=head3 Sony Ericsson Tags + +Maker notes found in images from some Sony Ericsson phones. + + Tag ID Tag Name Writable + ------ -------- -------- + 0x0201 PreviewImageStart int32u* + 0x0202 PreviewImageLength int32u* + 0x2000 MakerNoteVersion undef[4] + +=head3 Sony SRF Tags + +The maker notes in SRF (Sony Raw Format) images contain 7 IFD's with family +1 group names SRF0 through SRF6. SRF0 and SRF1 use the tags in this table, +while SRF2 through SRF5 use the tags in the next table, and SRF6 uses +standard EXIF tags. All information other than SRF0 is encrypted, but +thanks to Dave Coffin the decryption algorithm is known. SRF images are +written by the Sony DSC-F828 and DSC-V3. + + Tag ID Tag Name Writable + ------ -------- -------- + 0x0000 SRF2Key no + 0x0001 DataKey no + +=head3 Sony SRF2 Tags + +These tags are found in the SRF2 through SRF5 IFD's. + + Tag ID Tag Name Writable + ------ -------- -------- + 0x0002 SRF6Offset no + 0x0003 SRFDataOffset? no + 0x0004 RawDataOffset no + 0x0005 RawDataLength no + 0x0043 MaxApertureAtMaxFocal no + 0x0044 MaxApertureAtMinFocal no + 0x0045 MinFocalLength no + 0x0046 MaxFocalLength no + 0x00c0 WBRedDaylight no + 0x00c1 WBGreenDaylight no + 0x00c2 WBBlueDaylight no + 0x00c3 WBRedCloudy no + 0x00c4 WBGreenCloudy no + 0x00c5 WBBlueCloudy no + 0x00c6 WBRedFluorescent no + 0x00c7 WBGreenFluorescent no + 0x00c8 WBBlueFluorescent no + 0x00c9 WBRedTungsten no + 0x00ca WBGreenTungsten no + 0x00cb WBBlueTungsten no + 0x00cc WBRedFlash no + 0x00cd WBGreenFlash no + 0x00ce WBBlueFlash no + 0x00d0 WBRedAsShot no + 0x00d1 WBGreenAsShot no + 0x00d2 WBBlueAsShot no + +=head3 Sony SR2Private Tags + +The SR2 format uses the DNGPrivateData tag to reference a private IFD +containing these tags. SR2 images are written by the Sony DSC-R1, but +this information is also written to ARW images by other models. + + Tag ID Tag Name Writable + ------ -------- -------- + 0x7200 SR2SubIFDOffset no + 0x7201 SR2SubIFDLength no + 0x7221 SR2SubIFDKey no + 0x7240 IDC_IFD SonyIDC + 0x7241 IDC2_IFD SonyIDC + 0x7250 MRWInfo MinoltaRaw + +=head3 Sony SR2SubIFD Tags + +Tags in the encrypted SR2SubIFD + + Tag ID Tag Name Writable + ------ -------- -------- + 0x7300 BlackLevel no + 0x7302 WB_GRBGLevelsAuto no + 0x7303 WB_GRBGLevels no + 0x7310 BlackLevel no + 0x7312 WB_RGGBLevelsAuto no + 0x7313 WB_RGGBLevels no + 0x7480 WB_RGBLevelsDaylight no + 0x7481 WB_RGBLevelsCloudy no + 0x7482 WB_RGBLevelsTungsten no + 0x7483 WB_RGBLevelsFlash no + 0x7484 WB_RGBLevels4500K no + 0x7486 WB_RGBLevelsFluorescent no + 0x74a0 MaxApertureAtMaxFocal no + 0x74a1 MaxApertureAtMinFocal no + 0x74a2 MaxFocalLength no + 0x74a3 MinFocalLength no + 0x74c0 SR2DataIFD Sony SR2DataIFD + 0x7800 ColorMatrix no + 0x7820 WB_RGBLevelsDaylight no + 0x7821 WB_RGBLevelsCloudy no + 0x7822 WB_RGBLevelsTungsten no + 0x7823 WB_RGBLevelsFlash no + 0x7824 WB_RGBLevels4500K no + 0x7825 WB_RGBLevelsShade no + 0x7826 WB_RGBLevelsFluorescent no + 0x7827 WB_RGBLevelsFluorescentP1 no + 0x7828 WB_RGBLevelsFluorescentP2 no + 0x7829 WB_RGBLevelsFluorescentM1 no + 0x782a WB_RGBLevels8500K no + 0x782b WB_RGBLevels6000K no + 0x782c WB_RGBLevels3200K no + 0x782d WB_RGBLevels2500K no + 0x787f WhiteLevel no + 0x797d VignettingCorrParams no + 0x7980 ChromaticAberrationCorrParams no + 0x7982 DistortionCorrParams no + +=head3 Sony SR2DataIFD Tags + + Tag ID Tag Name Writable + ------ -------- -------- + 0x7770 ColorMode no + +=head3 Sony PMP Tags + +These tags are written in the proprietary-format header of PMP images from +the DSC-F1. + + Index1 Tag Name Writable + ------ -------- -------- + 8 JpgFromRawStart no + 12 JpgFromRawLength no + 22 SonyImageWidth no + 24 SonyImageHeight no + 27 Orientation no + 29 ImageQuality no + 52 Comment no + 76 DateTimeOriginal no + 84 ModifyDate no + 102 ExposureTime no + 106 FNumber no + 108 ExposureCompensation no + 112 FocalLength no + 118 Flash no + +=head3 Sony rtmd Tags + +These tags are extracted from the 'rtmd' timed metadata of MP4 videos from +some models when the ExtractEmbedded option is used. + + Tag ID Tag Name Writable + ------ -------- -------- + 0xe304 DateTime no + +=head2 SonyIDC Tags + +Tags written by the Sony Image Data Converter utility in ARW images. + + Tag ID Tag Name Writable + ------ -------- -------- + 0x0201 IDCPreviewStart int32u* + 0x0202 IDCPreviewLength int32u* + 0x8000 IDCCreativeStyle int32u + 0x8001 CreativeStyleWasChanged int32u + 0x8002 PresetWhiteBalance int32u + 0x8013 ColorTemperatureAdj int16u + 0x8014 PresetWhiteBalanceAdj int32s + 0x8015 ColorCorrection int32s + 0x8016 SaturationAdj int32s + 0x8017 ContrastAdj int32s + 0x8018 BrightnessAdj int32s + 0x8019 HueAdj int32s + 0x801a SharpnessAdj int32s + 0x801b SharpnessOvershoot int32s + 0x801c SharpnessUndershoot int32s + 0x801d SharpnessThreshold int32s + 0x801e NoiseReductionMode int16u + 0x8021 GrayPoint int16u[4] + 0x8022 D-RangeOptimizerMode int16u + 0x8023 D-RangeOptimizerValue int32s + 0x8024 D-RangeOptimizerHighlight int32s + 0x8026 HighlightColorDistortReduct int16u + 0x8027 NoiseReductionValue int32s + 0x8028 EdgeNoiseReduction int32s + 0x8029 ColorNoiseReduction int32s + 0x802d D-RangeOptimizerShadow int32s + 0x8030 PeripheralIllumCentralRadius int32s + 0x8031 PeripheralIllumCentralValue int32s + 0x8032 PeripheralIllumPeriphValue int32s + 0x8040 DistortionCompensation int32s + 0x9000 ToneCurveBrightnessX int16u[n] + 0x9001 ToneCurveRedX int16u[n] + 0x9002 ToneCurveGreenX int16u[n] + 0x9003 ToneCurveBlueX int16u[n] + 0x9004 ToneCurveBrightnessY int16u[n] + 0x9005 ToneCurveRedY int16u[n] + 0x9006 ToneCurveGreenY int16u[n] + 0x9007 ToneCurveBlueY int16u[n] + 0x900d ChromaticAberrationCorrection int32s + 0x900e InclinationCorrection int32u + 0x900f InclinationAngle int32s + 0x9010 Cropping int32u + 0x9011 CropArea int32u[4] + 0x9012 PreviewImageSize int32u[2] + 0x9013 PxShiftPeriphEdgeNR int32s + 0x9014 PxShiftPeriphEdgeNRValue int32s + 0x9017 WhitesAdj int32s + 0x9018 BlacksAdj int32s + 0x9019 HighlightsAdj int32s + 0x901a ShadowsAdj int32s + 0xd000 CurrentVersion int32u + 0xd001 VersionIFD SonyIDC + 0xd100 VersionCreateDate string + 0xd101 VersionModifyDate string + +=head2 Unknown Tags + +The following tags are decoded in unsupported maker notes. Use the Unknown +(-u) option to display other unknown tags. + + Tag ID Tag Name Writable + ------ -------- -------- + 0x0e00 PrintIM PrintIM + +=head2 DNG Tags + +The main DNG tags are found in the EXIF table. The tables below define only +information found within structures of these main DNG tag values. See +L<http://www.adobe.com/products/dng/> for the official DNG specification. + +=head3 DNG AdobeData Tags + +This information is found in the "Adobe" DNGPrivateData. + +The maker notes ('MakN') are processed by ExifTool, but some information may +have been lost by the Adobe DNG Converter. This is because the Adobe DNG +Converter (as of version 6.3) doesn't properly handle information referenced +from inside the maker notes that lies outside the original maker notes +block. This information is lost when only the maker note block is copied to +the DNG image. While this doesn't effect all makes of cameras, it is a +problem for some major brands such as Olympus and Sony. + +Other entries in this table represent proprietary information that is +extracted from the original RAW image and restructured to a different (but +still proprietary) Adobe format. + + Tag ID Tag Name Writable + ------ -------- -------- + 'CRW ' AdobeCRW CanonRaw + 'Koda' AdobeKoda Kodak IFD + 'Leaf' AdobeLeaf Leaf SubIFD + 'MRW ' AdobeMRW MinoltaRaw + 'MakN' MakerNoteApple Apple + MakerNoteNikon Nikon + MakerNoteCanon Canon + MakerNoteCasio Casio + MakerNoteCasio2 Casio Type2 + MakerNoteDJI DJI + MakerNoteFLIR FLIR + MakerNoteFujiFilm FujiFilm + MakerNoteGE GE + MakerNoteGE2 FujiFilm + MakerNoteHasselblad Unknown + MakerNoteHP HP + MakerNoteHP2 HP Type2 + MakerNoteHP4 HP Type4 + MakerNoteHP6 HP Type6 + MakerNoteISL Unknown + MakerNoteJVC JVC + MakerNoteJVCText JVC Text + MakerNoteKodak1a Kodak + MakerNoteKodak1b Kodak + MakerNoteKodak2 Kodak Type2 + MakerNoteKodak3 Kodak Type3 + MakerNoteKodak4 Kodak Type4 + MakerNoteKodak5 Kodak Type5 + MakerNoteKodak6a Kodak Type6 + MakerNoteKodak6b Kodak Type6 + MakerNoteKodak7 Kodak Type7 + MakerNoteKodak8a Kodak Type8 + MakerNoteKodak8b Kodak Type8 + MakerNoteKodak8c Kodak Type8 + MakerNoteKodak9 Kodak Type9 + MakerNoteKodak10 Kodak Type10 + MakerNoteKodak11 Kodak Type11 + MakerNoteKodak12 Kodak Type11 + MakerNoteKodakUnknown Kodak Unknown + MakerNoteKyocera Unknown + MakerNoteMinolta Minolta + MakerNoteMinolta2 Olympus + MakerNoteMinolta3 undef + MakerNoteMotorola Motorola + MakerNoteNikon2 Nikon Type2 + MakerNoteNikon3 Nikon + MakerNoteNintendo Nintendo + MakerNoteOlympus Olympus + MakerNoteOlympus2 Olympus + MakerNoteLeica Panasonic + MakerNoteLeica2 Panasonic Leica2 + MakerNoteLeica3 Panasonic Leica3 + MakerNoteLeica4 Panasonic Leica4 + MakerNoteLeica5 Panasonic Leica5 + MakerNoteLeica6 Panasonic Leica6 + MakerNoteLeica7 Panasonic Leica6 + MakerNoteLeica8 Panasonic Leica5 + MakerNoteLeica9 Panasonic Leica9 + MakerNoteLeica10 Panasonic + MakerNotePanasonic Panasonic + MakerNotePanasonic2 Panasonic Type2 + MakerNotePanasonic3 Panasonic + MakerNotePentax Pentax + MakerNotePentax2 Pentax Type2 + MakerNotePentax3 Casio Type2 + MakerNotePentax4 Pentax Type4 + MakerNotePentax5 Pentax + MakerNotePentax6 Pentax S1 + MakerNotePhaseOne PhaseOne + MakerNoteReconyx Reconyx + MakerNoteReconyx2 Reconyx Type2 + MakerNoteReconyx3 Reconyx Type3 + MakerNoteRicohPentax Pentax + MakerNoteRicoh Ricoh + MakerNoteRicoh2 Ricoh Type2 + MakerNoteRicohText Ricoh Text + MakerNoteSamsung1a undef + MakerNoteSamsung1b Samsung + MakerNoteSamsung2 Samsung Type2 + MakerNoteSanyo Sanyo + MakerNoteSanyoC4 Sanyo + MakerNoteSanyoPatch Sanyo + MakerNoteSigma Sigma + MakerNoteSony Sony + MakerNoteSony2 Olympus + MakerNoteSony3 Olympus + MakerNoteSony4 Sony PIC + MakerNoteSony5 Sony + MakerNoteSonyEricsson Sony Ericsson + MakerNoteSonySRF Sony SRF + MakerNoteUnknownText undef + MakerNoteUnknownBinary undef + MakerNoteUnknown Unknown + 'Pano' AdobePano PanasonicRaw + 'RAF ' AdobeRAF FujiFilm RAF + 'SR2 ' AdobeSR2 Sony SR2Private + +=head3 DNG OriginalRaw Tags + +This table defines tags extracted from the DNG OriginalRawFileData +information. + + Tag ID Tag Name Writable + ------ -------- -------- + 0x0000 OriginalRawImage no + 0x0001 OriginalRawResource no + 0x0002 OriginalRawFileType no + 0x0003 OriginalRawCreator no + 0x0004 OriginalTHMImage no + 0x0005 OriginalTHMResource no + 0x0006 OriginalTHMFileType no + 0x0007 OriginalTHMCreator no + +=head2 CanonRaw Tags + +These tags apply to CRW-format Canon RAW files and information in the APP0 +"CIFF" segment of JPEG images. When writing CanonRaw/CIFF information, the +length of the information is preserved (and the new information is truncated +or padded as required) unless B<Writable> is C<resize>. Currently, only +JpgFromRaw and ThumbnailImage are allowed to change size. + +CRW images also support the addition of a CanonVRD trailer, which in turn +supports XMP. This trailer is created automatically if necessary when +ExifTool is used to write XMP to a CRW image. + + Tag ID Tag Name Writable + ------ -------- -------- + 0x0000 NullRecord undef + 0x0001 FreeBytes undef + 0x0032 CanonColorInfo1 no + 0x0805 CanonFileDescription string[32] + UserComment string[256] + 0x080a CanonRawMakeModel CanonRaw MakeModel + 0x080b CanonFirmwareVersion string[32] + 0x080c ComponentVersion string + 0x080d ROMOperationMode string[8] + 0x0810 OwnerName string[32] + 0x0815 CanonImageType string[32] + 0x0816 OriginalFileName string[32] + 0x0817 ThumbnailFileName string[32] + 0x100a TargetImageType int16u + 0x1010 ShutterReleaseMethod int16u + 0x1011 ShutterReleaseTiming int16u + 0x1016 ReleaseSetting int16u + 0x101c BaseISO int16u + 0x1028 CanonFlashInfo? int16u[4] + 0x1029 CanonFocalLength Canon FocalLength + 0x102a CanonShotInfo Canon ShotInfo + 0x102c CanonColorInfo2 no + 0x102d CanonCameraSettings Canon CameraSettings + 0x1030 WhiteSample CanonRaw WhiteSample + 0x1031 SensorInfo Canon SensorInfo + 0x1033 CustomFunctions10D CanonCustom Functions10D + CustomFunctionsD30 CanonCustom FunctionsD30 + CustomFunctionsD60 CanonCustom FunctionsD30 + CustomFunctionsUnknown CanonCustom FuncsUnknown + 0x1038 CanonAFInfo Canon AFInfo + 0x1093 CanonFileInfo Canon FileInfo + 0x10a9 ColorBalance Canon ColorBalance + 0x10ae ColorTemperature int16u + 0x10b4 ColorSpace int16u + 0x10b5 RawJpgInfo CanonRaw RawJpgInfo + 0x1803 ImageFormat CanonRaw ImageFormat + 0x1804 RecordID int32u + 0x1806 SelfTimerTime int32u + 0x1807 TargetDistanceSetting float + 0x180b SerialNumber int32u + UnknownNumber? yes + 0x180e TimeStamp CanonRaw TimeStamp + 0x1810 ImageInfo CanonRaw ImageInfo + 0x1813 FlashInfo CanonRaw FlashInfo + 0x1814 MeasuredEV float + 0x1817 FileNumber int32u + 0x1818 ExposureInfo CanonRaw ExposureInfo + 0x1834 CanonModelID int32u + 0x1835 DecoderTable CanonRaw DecoderTable + 0x183b SerialNumberFormat int32u + 0x2005 RawData no + 0x2007 JpgFromRaw resize + 0x2008 ThumbnailImage resize + 0x2804 ImageDescription CanonRaw + 0x2807 CameraObject CanonRaw + 0x3002 ShootingRecord CanonRaw + 0x3003 MeasuredInfo CanonRaw + 0x3004 CameraSpecification CanonRaw + 0x300a ImageProps CanonRaw + 0x300b ExifInformation CanonRaw + +=head3 CanonRaw MakeModel Tags + + Index1 Tag Name Writable + ------ -------- -------- + 0 Make string[6] + 6 Model string + +=head3 CanonRaw WhiteSample Tags + + Index2 Tag Name Writable + ------ -------- -------- + 1 WhiteSampleWidth no + 2 WhiteSampleHeight no + 3 WhiteSampleLeftBorder no + 4 WhiteSampleTopBorder no + 5 WhiteSampleBits no + +=head3 CanonRaw RawJpgInfo Tags + + Index2 Tag Name Writable + ------ -------- -------- + 1 RawJpgQuality int16u + 2 RawJpgSize int16u + 3 RawJpgWidth int16u + 4 RawJpgHeight int16u + +=head3 CanonRaw ImageFormat Tags + + Index4 Tag Name Writable + ------ -------- -------- + 0 FileFormat int32u + 1 TargetCompressionRatio float + +=head3 CanonRaw TimeStamp Tags + + Index4 Tag Name Writable + ------ -------- -------- + 0 DateTimeOriginal int32u + 1 TimeZoneCode int32s + 2 TimeZoneInfo int32u + +=head3 CanonRaw ImageInfo Tags + + Index4 Tag Name Writable + ------ -------- -------- + 0 ImageWidth no + 1 ImageHeight no + 2 PixelAspectRatio no + 3 Rotation int32s + 4 ComponentBitDepth no + 5 ColorBitDepth no + 6 ColorBW no + +=head3 CanonRaw FlashInfo Tags + + Index4 Tag Name Writable + ------ -------- -------- + 0 FlashGuideNumber float + 1 FlashThreshold float + +=head3 CanonRaw ExposureInfo Tags + + Index4 Tag Name Writable + ------ -------- -------- + 0 ExposureCompensation float + 1 ShutterSpeedValue float + 2 ApertureValue float + +=head3 CanonRaw DecoderTable Tags + + Index4 Tag Name Writable + ------ -------- -------- + 0 DecoderTableNumber no + 2 CompressedDataOffset no + 3 CompressedDataLength no + +=head2 KyoceraRaw Tags + +Tags for Kyocera Contax N Digital RAW images. + + Index1 Tag Name Writable + ------ -------- -------- + 1 FirmwareVersion no + 12 Model no + 25 Make no + 33 DateTimeOriginal no + 52 ISO no + 56 ExposureTime no + 60 WB_RGGBLevels no + 88 FNumber no + 104 MaxAperture no + 112 FocalLength no + 124 Lens no + +=head2 MinoltaRaw Tags + +These tags are used in Minolta RAW format (MRW) images. + + Tag ID Tag Name Writable + ------ -------- -------- + "\0PRD" MinoltaPRD MinoltaRaw PRD + "\0RIF" MinoltaRIF MinoltaRaw RIF + "\0TTW" MinoltaTTW EXIF + "\0WBG" MinoltaWBG MinoltaRaw WBG + +=head3 MinoltaRaw PRD Tags + + Index1 Tag Name Writable + ------ -------- -------- + 0 FirmwareID string[8] + 8 SensorHeight int16u + 10 SensorWidth int16u + 12 ImageHeight int16u + 14 ImageWidth int16u + 16 RawDepth int8u + 17 BitDepth int8u + 18 StorageMethod int8u + 23 BayerPattern int8u + +=head3 MinoltaRaw RIF Tags + + Index1 Tag Name Writable + ------ -------- -------- + 1 Saturation int8s + 2 Contrast int8s + 3 Sharpness int8s + 4 WBMode int8u~ + 5 ProgramMode int8u + 6 ISOSetting int8u + 7 ColorMode int32u[0.25] + 8 WB_RBLevelsTungsten int16u[2] + 12 WB_RBLevelsDaylight int16u[2] + 16 WB_RBLevelsCloudy int16u[2] + 20 WB_RBLevelsCoolWhiteF int16u[2] + 24 WB_RBLevelsFlash int16u[2] + 28 WB_RBLevelsUnknown? int16u[2] + 32 WB_RBLevelsShade int16u[2] + 36 WB_RBLevelsDaylightF int16u[2] + 40 WB_RBLevelsDayWhiteF int16u[2] + 44 WB_RBLevelsWhiteF int16u[2] + 56 ColorFilter int8s + 57 BWFilter int8u + 58 ZoneMatching int8u + 59 Hue int8s + 60 ColorTemperature int8u + 74 ZoneMatching int8u + 76 ColorTemperature int8u + 77 ColorFilter int8u + 78 ColorTemperature int8u + 79 ColorFilter int8u + 80 RawDataLength no + +=head3 MinoltaRaw WBG Tags + + Index1 Tag Name Writable + ------ -------- -------- + 0 WBScale int8u[4] + 4 WB_GBRGLevels int16u[4] + WB_RGGBLevels int16u[4] + +=head2 PanasonicRaw Tags + +These tags are found in IFD0 of Panasonic/Leica RAW, RW2 and RWL images. + + Tag ID Tag Name Writable + ------ -------- -------- + 0x0001 PanasonicRawVersion undef + 0x0002 SensorWidth no + 0x0003 SensorHeight no + 0x0004 SensorTopBorder no + 0x0005 SensorLeftBorder no + 0x0006 SensorBottomBorder no + 0x0007 SensorRightBorder no + 0x0008 SamplesPerPixel int16u! + 0x0009 CFAPattern int16u! + 0x000a BitsPerSample int16u! + 0x000b Compression int16u! + 0x000e LinearityLimitRed int16u + 0x000f LinearityLimitGreen int16u + 0x0010 LinearityLimitBlue int16u + 0x0011 RedBalance int16u + 0x0012 BlueBalance int16u + 0x0013 WBInfo PanasonicRaw WBInfo + 0x0017 ISO int16u + 0x0018 HighISOMultiplierRed int16u + 0x0019 HighISOMultiplierGreen int16u + 0x001a HighISOMultiplierBlue int16u + 0x001b NoiseReductionParams undef[n]! + 0x001c BlackLevelRed int16u + 0x001d BlackLevelGreen int16u + 0x001e BlackLevelBlue int16u + 0x0024 WBRedLevel int16u + 0x0025 WBGreenLevel int16u + 0x0026 WBBlueLevel int16u + 0x0027 WBInfo2 PanasonicRaw WBInfo2 + 0x002d RawFormat int16u! + 0x002e JpgFromRaw JPEG + 0x002f CropTop int16u + 0x0030 CropLeft int16u + 0x0031 CropBottom int16u + 0x0032 CropRight int16u + 0x010f Make string + 0x0110 Model string + 0x0111 StripOffsets no + 0x0112 Orientation int16u + 0x0116 RowsPerStrip no + 0x0117 StripByteCounts no + 0x0118 RawDataOffset no + 0x0119 DistortionInfo PanasonicRaw DistortionInfo + 0x011c Gamma int16u + 0x0120 CameraIFD PanasonicRaw CameraIFD + 0x0121 Multishot int32u + 0x02bc ApplicationNotes XMP + 0x83bb IPTC-NAA IPTC + 0x8769 ExifOffset EXIF + 0x8825 GPSInfo GPS + +=head3 PanasonicRaw WBInfo Tags + + Index2 Tag Name Writable + ------ -------- -------- + 0 NumWBEntries int16u + 1 WBType1 int16u + 2 WB_RBLevels1 int16u[2] + 4 WBType2 int16u + 5 WB_RBLevels2 int16u[2] + 7 WBType3 int16u + 8 WB_RBLevels3 int16u[2] + 10 WBType4 int16u + 11 WB_RBLevels4 int16u[2] + 13 WBType5 int16u + 14 WB_RBLevels5 int16u[2] + 16 WBType6 int16u + 17 WB_RBLevels6 int16u[2] + 19 WBType7 int16u + 20 WB_RBLevels7 int16u[2] + +=head3 PanasonicRaw WBInfo2 Tags + + Index2 Tag Name Writable + ------ -------- -------- + 0 NumWBEntries int16u + 1 WBType1 int16u + 2 WB_RGBLevels1 int16u[3] + 5 WBType2 int16u + 6 WB_RGBLevels2 int16u[3] + 9 WBType3 int16u + 10 WB_RGBLevels3 int16u[3] + 13 WBType4 int16u + 14 WB_RGBLevels4 int16u[3] + 17 WBType5 int16u + 18 WB_RGBLevels5 int16u[3] + 21 WBType6 int16u + 22 WB_RGBLevels6 int16u[3] + 25 WBType7 int16u + 26 WB_RGBLevels7 int16u[3] + +=head3 PanasonicRaw DistortionInfo Tags + +Lens distortion correction information. + + Tag ID Tag Name Writable + ------ -------- -------- + 0x0002 DistortionParam02 int16s + 0x0004 DistortionParam04 int16s + 0x0005 DistortionScale int16s + 7.1 DistortionCorrection int16s & 0x0f + 0x0008 DistortionParam08 int16s + 0x0009 DistortionParam09 int16s + 0x000b DistortionParam11 int16s + 0x000c DistortionN? int16s + +=head3 PanasonicRaw CameraIFD Tags + + Tag ID Tag Name Writable + ------ -------- -------- + 0x1001 MultishotOn int32u + 0x1100 FocusStepNear int16s + 0x1101 FocusStepCount int16s + 0x1102 FlashFired int32u + 0x1105 ZoomPosition int32u + 0x1200 LensAttached int32u + 0x1203 FocalLengthIn35mmFormat int16u + 0x1305 HighISOMode int16u + 0x3200 WB_CFA0_LevelDaylight int16u + 0x3201 WB_CFA1_LevelDaylight int16u + 0x3202 WB_CFA2_LevelDaylight int16u + 0x3203 WB_CFA3_LevelDaylight int16u + 0x3300 WhiteBalanceSet int8u + 0x3420 WB_RedLevelAuto int16u + 0x3421 WB_BlueLevelAuto int16u + 0x3501 Orientation int8u + 0x3600 WhiteBalanceDetected int8u + +=head2 SigmaRaw Tags + +These tags are used in Sigma and Foveon RAW (.X3F) images. Metadata is also +extracted from the JpgFromRaw image if it exists (all models but the SD9 and +SD10). Currently, metadata may only be written to the embedded JpgFromRaw. + + Tag ID Tag Name Writable + ------ -------- -------- + 'Header' Header SigmaRaw Header + 'Header4' Header4 SigmaRaw Header4 + 'HeaderExt' HeaderExt SigmaRaw HeaderExt + 'IMA2' PreviewImage no + JpgFromRaw no + 'IMAG' PreviewImage no + 'PROP' Properties SigmaRaw Properties + +=head3 SigmaRaw Header Tags + +Information extracted from the header of an X3F file. + + Tag ID Tag Name Writable + ------ -------- -------- + 0x0001 FileVersion no + 0x0002 ImageUniqueID no + 0x0006 MarkBits no + 0x0007 ImageWidth no + 0x0008 ImageHeight no + 0x0009 Rotation no + 0x000a WhiteBalance no + 0x0012 SceneCaptureType no + +=head3 SigmaRaw Header4 Tags + +Header information for version 4.0 or greater X3F. + + Index4 Tag Name Writable + ------ -------- -------- + 1 FileVersion no + 10 ImageWidth no + 11 ImageHeight no + 12 Rotation no + +=head3 SigmaRaw HeaderExt Tags + +Extended header data found in version 2.1 and 2.2 files + + Tag ID Tag Name Writable + ------ -------- -------- + 0x0000 Unused no + 0x0001 ExposureAdjust no + 0x0002 Contrast no + 0x0003 Shadow no + 0x0004 Highlight no + 0x0005 Saturation no + 0x0006 Sharpness no + 0x0007 RedAdjust no + 0x0008 GreenAdjust no + 0x0009 BlueAdjust no + 0x000a X3FillLight no + +=head3 SigmaRaw Properties Tags + + Tag ID Tag Name Writable + ------ -------- -------- + 'AEMODE' MeteringMode no + 'AFAREA' AFArea no + 'AFINFOCUS' AFInFocus no + 'AFMODE' FocusMode no + 'APERTURE' FNumber no + 'AP_DESC' ApertureDisplayed no + 'BRACKET' BracketShot no + 'BURST' BurstShot no + 'CAMMANUF' Make no + 'CAMMODEL' Model no + 'CAMNAME' CameraName no + 'CAMSERIAL' SerialNumber no + 'CM_DESC' SceneCaptureType no + 'COLORSPACE' ColorSpace no + 'DRIVE' DriveMode no + 'EVAL_STATE' EvalState no + 'EXPCOMP' ExposureCompensation no + 'EXPNET' NetExposureCompensation no + 'EXPTIME' IntegrationTime no + 'FIRMVERS' FirmwareVersion no + 'FLASH' FlashMode no + 'FLASHEXPCOMP' FlashExpComp no + 'FLASHPOWER' FlashPower no + 'FLASHTTLMODE' FlashTTLMode no + 'FLASHTYPE' FlashType no + 'FLENGTH' FocalLength no + 'FLEQ35MM' FocalLengthIn35mmFormat no + 'FOCUS' Focus no + 'IMAGEBOARDID' ImageBoardID no + 'IMAGERBOARDID' ImagerBoardID no + 'IMAGERTEMP' SensorTemperature no + 'ISO' ISO no + 'LENSARANGE' LensApertureRange no + 'LENSFRANGE' LensFocalRange no + 'LENSMODEL' LensType no + 'PMODE' ExposureProgram no + 'RESOLUTION' Quality no + 'SENSORID' SensorID no + 'SHUTTER' ExposureTime no + 'SH_DESC' ShutterSpeedDisplayed no + 'TIME' DateTimeOriginal no + 'VERSION_BF' VersionBF no + 'WB_DESC' WhiteBalance no + +=head2 Lytro Tags + +Tag definitions for Lytro Light Field Picture (LFP) files. ExifTool +extracts the full JSON metadata blocks, as well as breaking them down into +individual tags. All available tags are extracted from the JSON metadata, +even if they don't appear in the table below. + + Tag Name Writable + -------- -------- + AccelerometerTime no + AccelerometerX no + AccelerometerY no + AccelerometerZ no + CameraType no + DateTimeOriginal no + EmbeddedImage no + ExposureTime no + FNumber no + FirmwareVersion no + FocalLength no + FocalPlaneXResolution no + FrameExposureTime no + ISO no + ImageLimitExposureBias no + ImageModulationExposureBias no + JSONMetadata no+ + LensTemperature no + Make no + Model no + Orientation no + SensorSerialNumber no + SerialNumber no + SocTemperature no + +=head2 JFIF Tags + +The following information is extracted from the JPEG JFIF header. See +L<https://www.w3.org/Graphics/JPEG/jfif3.pdf> for the JFIF 1.02 +specification. + + Index1 Tag Name Writable + ------ -------- -------- + 0 JFIFVersion no: + 2 ResolutionUnit int8u: + 3 XResolution int16u: + 5 YResolution int16u: + 7 ThumbnailWidth no + 8 ThumbnailHeight no + 9 ThumbnailTIFF no + +=head3 JFIF Extension Tags + +Thumbnail images extracted from the JFXX segment. + + Tag ID Tag Name Writable + ------ -------- -------- + 0x0010 ThumbnailImage no + 0x0011 ThumbnailTIFF no + 0x0013 ThumbnailTIFF no + +=head2 FlashPix Tags + +The FlashPix file format, introduced in 1996, was developed by Kodak, +Hewlett-Packard and Microsoft. Internally the FPX file structure mimics +that of an old DOS disk with fixed-sized "sectors" (usually 512 bytes) and a +"file allocation table" (FAT). No wonder this image format never became +popular. However, some of the structures used in FlashPix streams are part +of the EXIF specification, and are still being used in the APP2 FPXR segment +of JPEG images by some digital cameras from manufacturers such as FujiFilm, +Hewlett-Packard, Kodak and Sanyo. + +ExifTool extracts FlashPix information from both FPX images and the APP2 +FPXR segment of JPEG images. As well, FlashPix information is extracted +from DOC, PPT, XLS (Microsoft Word, PowerPoint and Excel) documents, VSD +(Microsoft Visio) drawings, and FLA (Macromedia/Adobe Flash project) files +since these are based on the same file format as FlashPix (the Windows +Compound Binary File format). See +L<http://graphcomp.com/info/specs/livepicture/fpx.pdf> for the FlashPix +specification. + + Tag ID Tag Name Writable + ------ -------- -------- + "\x01CompObj" CompObj FlashPix CompObj + "\x05Audio Info" AudioInfo FlashPix AudioInfo + "\x05Data Object" DataObject FlashPix DataObject + "\x05DocumentSummaryInformation" DocumentInfo FlashPix DocumentInfo + "\x05Extension List" Extensions FlashPix Extensions + "\x05Global Info" GlobalInfo FlashPix GlobalInfo + "\x05Image Contents" Image FlashPix Image + "\x05Image Info" ImageInfo FlashPix ImageInfo + "\x05Operation" Operation FlashPix Operation + "\x05Screen Nail" ScreenNail no + "\x05SummaryInformation" SummaryInfo FlashPix SummaryInfo + "\x05Transform" Transform FlashPix Transform + 'Audio Stream' AudioStream no + 'Contents' Contents XMP + 'Current User' CurrentUser no + 'ICC Profile 0001' ICC_Profile ICC_Profile + 'Preview' PreviewImage no + 'Property' PreviewInfo FlashPix PreviewInfo + 'Subimage 0000 Header' SubimageHdr FlashPix SubimageHdr + 'WordDocument' WordDocument FlashPix WordDocument + +=head3 FlashPix CompObj Tags + + Index4 Tag Name Writable + ------ -------- -------- + 0 CompObjUserTypeLen no + 1 CompObjUserType no + +=head3 FlashPix AudioInfo Tags + + Tag ID Tag Name Writable + ------ -------- -------- + [no tags known] + +=head3 FlashPix DataObject Tags + + Tag ID Tag Name Writable + ------ -------- -------- + 0x10000 DataObjectID no + 0x10002 LockedPropertyList no + 0x10003 DataObjectTitle no + 0x10004 LastModifier no + 0x10005 RevisionNumber no + 0x10006 DataCreateDate no + 0x10007 DataModifyDate no + 0x10008 CreatingApplication no + 0x10100 DataObjectStatus no + 0x10101 CreatingTransform no + 0x10102 UsingTransforms no + 0x10000000 CachedImageHeight no + 0x10000001 CachedImageWidth no + +=head3 FlashPix DocumentInfo Tags + +The DocumentSummaryInformation property set includes a UserDefined property +set for which only the Hyperlinks and HyperlinkBase tags are pre-defined. +However, ExifTool will also extract any other information found in the +UserDefined properties. + + Tag ID Tag Name Writable + ------ -------- -------- + 0x0002 Category no + 0x0003 PresentationTarget no + 0x0004 Bytes no + 0x0005 Lines no + 0x0006 Paragraphs no + 0x0007 Slides no + 0x0008 Notes no + 0x0009 HiddenSlides no + 0x000a MMClips no + 0x000b ScaleCrop no + 0x000c HeadingPairs no + 0x000d TitleOfParts no + 0x000e Manager no + 0x000f Company no + 0x0010 LinksUpToDate no + 0x0011 CharCountWithSpaces no + 0x0013 SharedDoc no + 0x0016 HyperlinksChanged no + 0x0017 AppVersion no + '_PID_HLINKS' Hyperlinks no + '_PID_LINKBASE' HyperlinkBase no + +=head3 FlashPix Extensions Tags + + Tag ID Tag Name Writable + ------ -------- -------- + 0x0001 ExtensionName no + 0x0002 ExtensionClassID no + 0x0003 ExtensionPersistence no + 0x0004 ExtensionCreateDate no + 0x0005 ExtensionModifyDate no + 0x0006 CreatingApplication no + 0x0007 ExtensionDescription no + 0x1000 Storage-StreamPathname no + 0x2000 FlashPixStreamPathname no + 0x2001 FlashPixStreamFieldOffset no + 0x3000 PropertySetPathname no + 0x3001 PropertySetIDCodes no + 0x3002 PropertyVectorElements no + 0x4000 SubimageResolutions no + 0x10000000 UsedExtensionNumbers no + +=head3 FlashPix GlobalInfo Tags + + Tag ID Tag Name Writable + ------ -------- -------- + 0x10002 LockedPropertyList no + 0x10003 TransformedImageTitle no + 0x10004 LastModifier no + 0x10100 VisibleOutputs no + 0x10101 MaximumImageIndex no + 0x10102 MaximumTransformIndex no + 0x10103 MaximumOperationIndex no + +=head3 FlashPix Image Tags + + Tag ID Tag Name Writable + ------ -------- -------- + 0x1000000 NumberOfResolutions no + 0x1000002 ImageWidth no + 0x1000003 ImageHeight no + 0x1000004 DefaultDisplayHeight no + 0x1000005 DefaultDisplayWidth no + 0x1000006 DisplayUnits no + 0x2000000 SubimageWidth no + 0x2000001 SubimageHeight no + 0x2000002 SubimageColor no + 0x2000003 SubimageNumericalFormat no + 0x2000004 DecimationMethod no + 0x2000005 DecimationPrefilterWidth no + 0x2000007 SubimageICC_Profile no + 0x3000001 JPEGTables no + 0x3000002 MaxJPEGTableIndex no + +=head3 FlashPix ImageInfo Tags + + Tag ID Tag Name Writable + ------ -------- -------- + 0x21000000 FileSource no + 0x21000001 SceneType no + 0x21000002 CreationPathVector no + 0x21000003 SoftwareRelease no + 0x21000004 UserDefinedID no + 0x21000005 SharpnessApproximation no + 0x22000000 Copyright no + 0x22000001 OriginalImageBroker no + 0x22000002 DigitalImageBroker no + 0x22000003 Authorship no + 0x22000004 IntellectualPropertyNotes no + 0x23000000 TestTarget no + 0x23000002 GroupCaption no + 0x23000003 CaptionText no + 0x23000004 People no + 0x23000007 Things no + 0x2300000a DateTimeOriginal no + 0x2300000b Events no + 0x2300000c Places no + 0x2300000f ContentDescriptionNotes no + 0x24000000 Make no + 0x24000001 Model no + 0x24000002 SerialNumber no + 0x25000000 CreateDate no + 0x25000001 ExposureTime no + 0x25000002 FNumber no + 0x25000003 ExposureProgram no + 0x25000004 BrightnessValue no + 0x25000005 ExposureCompensation no + 0x25000006 SubjectDistance no + 0x25000007 MeteringMode no + 0x25000008 LightSource no + 0x25000009 FocalLength no + 0x2500000a MaxApertureValue no + 0x2500000b Flash no + 0x2500000c FlashEnergy no + 0x2500000d FlashReturn no + 0x2500000e BackLight no + 0x2500000f SubjectLocation no + 0x25000010 ExposureIndex no + 0x25000011 SpecialEffectsOpticalFilter no + 0x25000012 PerPictureNotes no + 0x26000000 SensingMethod no + 0x26000001 FocalPlaneXResolution no + 0x26000002 FocalPlaneYResolution no + 0x26000003 FocalPlaneResolutionUnit no + 0x26000004 SpatialFrequencyResponse no + 0x26000005 CFAPattern no + 0x26000007 ISO no + 0x26000008 Opto-ElectricConvFactor no + 0x27000000 FilmBrand no + 0x27000001 FilmCategory no + 0x27000002 FilmSize no + 0x27000003 FilmRollNumber no + 0x27000004 FilmFrameNumber no + 0x28000000 ScannerMake no + 0x28000001 ScannerModel no + 0x28000002 ScannerSerialNumber no + 0x28000003 ScanSoftware no + 0x28000004 ScanSoftwareRevisionDate no + 0x28000005 ServiceOrganizationName no + 0x28000006 ScanOperatorID no + 0x28000008 ScanDate no + 0x28000009 ModifyDate no + 0x2800000a ScannerPixelSize no + 0x29000000 OriginalScannedImageSize no + 0x29000001 OriginalDocumentSize no + 0x29000002 OriginalMedium no + 0x29000003 TypeOfOriginal no + +=head3 FlashPix Operation Tags + + Tag ID Tag Name Writable + ------ -------- -------- + 0x10000 OperationID no + +=head3 FlashPix SummaryInfo Tags + +The Dictionary, CodePage and LocalIndicator tags are common to all FlashPix +property tables, even though they are only listed in the SummaryInfo table. + + Tag ID Tag Name Writable + ------ -------- -------- + 0x0000 Dictionary no + 0x0001 CodePage no + 0x0002 Title no + 0x0003 Subject no + 0x0004 Author no + 0x0005 Keywords no + 0x0006 Comments no + 0x0007 Template no + 0x0008 LastModifiedBy no + 0x0009 RevisionNumber no + 0x000a TotalEditTime no + 0x000b LastPrinted no + 0x000c CreateDate no + 0x000d ModifyDate no + 0x000e Pages no + 0x000f Words no + 0x0010 Characters no + 0x0011 ThumbnailClip no + 0x0012 Software no + 0x0013 Security no + 0x0022 CreatedBy no + 0x0023 DocumentID no + 0x80000000 LocaleIndicator no + +=head3 FlashPix Transform Tags + + Tag ID Tag Name Writable + ------ -------- -------- + 0x10000 TransformNodeID no + 0x10001 OperationClassID no + 0x10002 LockedPropertyList no + 0x10003 TransformTitle no + 0x10004 LastModifier no + 0x10005 RevisionNumber no + 0x10006 TransformCreateDate no + 0x10007 TransformModifyDate no + 0x10008 CreatingApplication no + 0x10100 InputDataObjectList no + 0x10101 OutputDataObjectList no + 0x10102 OperationNumber no + 0x10000000 ResultAspectRatio no + 0x10000001 RectangleOfInterest no + 0x10000002 Filtering no + 0x10000003 SpatialOrientation no + 0x10000004 ColorTwistMatrix no + 0x10000005 ContrastAdjustment no + +=head3 FlashPix PreviewInfo Tags + +Preview information written by some FujiFilm models. + + Index1 Tag Name Writable + ------ -------- -------- + 13 PreviewImageWidth no + 23 PreviewImageHeight no + +=head3 FlashPix SubimageHdr Tags + + Index4 Tag Name Writable + ------ -------- -------- + 1 SubimageWidth no + 2 SubimageHeight no + 3 SubimageTileCount no + 4 SubimageTileWidth no + 5 SubimageTileHeight no + 6 NumChannels no + +=head3 FlashPix WordDocument Tags + +Tags extracted from the Microsoft Word document stream. + + Tag ID Tag Name Writable + ------ -------- -------- + 0x0000 Identification no + 0x0003 LanguageCode no + 0x0005 DocFlags no + 9.1 System no + 9.2 Word97 no + +=head3 FlashPix DocTable Tags + +Tags extracted from the Microsoft Word document table. + + Tag Name Writable + -------- -------- + CommentBy no + DOP FlashPix DOP + LastSavedBy no + ModifyDate no + +=head3 FlashPix DOP Tags + +Microsoft office document properties. + + Index1 Tag Name Writable + ------ -------- -------- + 20 CreateDate no + 24 ModifyDate no + 28 LastPrinted no + 32 RevisionNumber no + 34 TotalEditTime no + 38 Words no + 42 Characters no + 46 Pages no + 48 Paragraphs no + 56 Lines no + +=head2 MPF Tags + +These tags are part of the CIPA Multi-Picture Format specification, and are +found in the APP2 "MPF" segment of JPEG images. MPImage data referenced +from this segment is stored as a JPEG trailer. The MPF tags are not +writable, however the MPF segment may be deleted as a group (with "MPF:All") +but then the JPEG trailer should also be deleted (with "Trailer:All"). See +L<http://www.cipa.jp/std/documents/e/DC-007_E.pdf> for the official +specification. + + Tag ID Tag Name Writable + ------ -------- -------- + 0xb000 MPFVersion no + 0xb001 NumberOfImages no + 0xb002 MPImageList MPF MPImage + 0xb003 ImageUIDList no + 0xb004 TotalFrames no + 0xb101 MPIndividualNum no + 0xb201 PanOrientation no + 0xb202 PanOverlapH no + 0xb203 PanOverlapV no + 0xb204 BaseViewpointNum no + 0xb205 ConvergenceAngle no + 0xb206 BaselineLength no + 0xb207 VerticalDivergence no + 0xb208 AxisDistanceX no + 0xb209 AxisDistanceY no + 0xb20a AxisDistanceZ no + 0xb20b YawAngle no + 0xb20c PitchAngle no + 0xb20d RollAngle no + +=head3 MPF MPImage Tags + +The first MPF "Large Thumbnail" image is extracted as PreviewImage, and the +rest of the embedded MPF images are extracted as MPImage#. The +ExtractEmbedded (-ee) option may be used to extract information from these +embedded images. + + Index1 Tag Name Writable + ------ -------- -------- + 0.1 MPImageFlags no + 0.2 MPImageFormat no + 0.3 MPImageType no + 4 MPImageLength no + 8 MPImageStart no + 12 DependentImage1EntryNumber no + 14 DependentImage2EntryNumber no + +=head2 Stim Tags + +These tags are part of the CIPA Stereo Still Image specification, and are +found in the APP3 "Stim" segment of JPEG images. See +L<http://www.cipa.jp/std/documents/e/DC-006_E.pdf> for the +official specification. + + Tag ID Tag Name Writable + ------ -------- -------- + 0x0000 StimVersion no + 0x0001 ApplicationData no + 0x0002 ImageArrangement no + 0x0003 ImageRotation no + 0x0004 ScalingFactor no + 0x0005 CropXSize no + 0x0006 CropYSize no + 0x0007 CropX Stim CropX + 0x0008 CropY Stim CropY + 0x0009 ViewType no + 0x000a RepresentativeImage no + 0x000b ConvergenceBaseImage no + 0x000c AssumedDisplaySize no + 0x000d AssumedDistanceView no + 0x000e RepresentativeDisparityNear no + 0x000f RepresentativeDisparityFar no + 0x0010 InitialDisplayEffect no + 0x0011 ConvergenceDistance no + 0x0012 CameraArrangementInterval no + 0x0013 ShootingCount no + +=head3 Stim CropX Tags + + Index1 Tag Name Writable + ------ -------- -------- + 0 CropXCommonOffset no + 2 CropXViewpointNumber no + 3 CropXOffset no + 7 CropXViewpointNumber2 no + 8 CropXOffset2 no + +=head3 Stim CropY Tags + + Index1 Tag Name Writable + ------ -------- -------- + 0 CropYCommonOffset no + 2 CropYViewpointNumber no + 3 CropYOffset no + 7 CropYViewpointNumber2 no + 8 CropYOffset2 no + +=head2 Scalado Tags + +Tags extracted from the JPEG APP4 "SCALADO" segment found in images from +HTC, LG and Samsung phones. (Presumably written by Scalado mobile software, +L<http://www.scalado.com/>.) + + Tag ID Tag Name Writable + ------ -------- -------- + 'HGHT' PreviewImageHeight no + 'QUAL' PreviewQuality no + 'SPMO' DataLength? no + 'WDTH' PreviewImageWidth no + +=head2 GoPro Tags + +=head3 GoPro GPMF Tags + +Tags extracted from the GPMF box of GoPro MP4 videos, the APP6 "GoPro" segment +of JPEG files, and from the "gpmd" timed metadata if the ExtractEmbedded option +is enabled. Many more tags exist, but are currently unknown and extracted only +with the -u option. Please let me know if you discover the meaning of any of +these unknown tags. See L<https://github.com/gopro/gpmf-parser> for details +about this format. + + Tag ID Tag Name Writable + ------ -------- -------- + 'ACCL' Accelerometer no + 'ALLD' AutoLowLightDuration no + 'ATTD' Attitude no + 'ATTR' AttitudeTarget no + 'AUDO' AudioSetting no + 'BPOS' Controller? no + 'CASN' CameraSerialNumber no + 'CSEN' CoyoteSense no + 'CYTS' CoyoteStatus no + 'DEVC' DeviceContainer GoPro GPMF + 'DVID' DeviceID? no + 'DVNM' DeviceName no + 'DZOM' DigitalZoom no + 'EMPT' Empty? no + 'ESCS' EscapeStatus? no + 'FACE' FaceDetected no + 'FCNM' FaceNumbers no + 'FMWR' FirmwareVersion no + 'FWVS' OtherFirmware no + 'GLPI' GPSPos GoPro GLPI + 'GPRI' GPSRaw? GoPro GPRI + 'GPS5' GPSInfo GoPro GPS5 + 'GPSF' GPSMeasureMode no + 'GPSP' GPSHPositioningError no + 'GPSU' GPSDateTime no + 'GYRO' Gyroscope no + 'ISOE' ISOSpeeds no + 'ISOG' ImageSensorGain no + 'KBAT' BatteryStatus GoPro KBAT + 'LNED' LocalPositionNED no + 'MAGN' Magnetometer no + 'MINF' Model no + 'OREN' AutoRotation no + 'PHDR' HDRSetting no + 'PIMN' AutoISOMin no + 'PIMX' AutoISOMax no + 'PRES' PhotoResolution no + 'PRTN' ProTune no + 'PTCL' ColorMode no + 'PTEV' ExposureCompensation no + 'PTSH' Sharpness no + 'PTWB' WhiteBalance no + 'RATE' Rate no + 'RMRK' Comments no + 'SCAL' ScaleFactor? no + 'SCPR' ScaledPressure no + 'SHUT' ExposureTimes no + 'SIMU' ScaledIMU no + 'SIUN' SIUnits? no + 'STMP' TimeStamp no + 'STNM' StreamName? no + 'STRM' NestedSignalStream GoPro GPMF + 'SYST' SystemTime no + 'TMPC' CameraTemperature no + 'TSMP' TotalSamples? no + 'TYPE' StructureType? no + 'UNIT' Units? no + 'VFOV' FieldOfView no + 'VFRH' VisualFlightRulesHUD no + 'WBAL' ColorTemperatures no + 'WRGB' WhiteBalanceRGB no + +=head3 GoPro GLPI Tags + + Index Tag Name Writable + ----- -------- -------- + 0 GPSDateTime no + 1 GPSLatitude no + 2 GPSLongitude no + 3 GPSAltitude no + 5 GPSSpeedX no + 6 GPSSpeedY no + 7 GPSSpeedZ no + 8 GPSTrack no + +=head3 GoPro GPRI Tags + + Index Tag Name Writable + ----- -------- -------- + 0 GPSDateTimeRaw no + 1 GPSLatitudeRaw no + 2 GPSLongitudeRaw no + 3 GPSAltitudeRaw no + 6 GPSSpeedRaw no + 7 GPSTrackRaw no + +=head3 GoPro GPS5 Tags + + Index Tag Name Writable + ----- -------- -------- + 0 GPSLatitude no + 1 GPSLongitude no + 2 GPSAltitude no + 3 GPSSpeed no + 4 GPSSpeed3D no + +=head3 GoPro KBAT Tags + +Battery status information found in GoPro Karma videos. + + Index Tag Name Writable + ----- -------- -------- + 0 BatteryCurrent no + 1 BatteryCapacity no + 3 BatteryTemperature no + 4 BatteryVoltage1 no + 5 BatteryVoltage2 no + 6 BatteryVoltage3 no + 7 BatteryVoltage4 no + 8 BatteryTime no + 14 BatteryLevel no + +=head3 GoPro fdsc Tags + +Tags extracted from the MP4 "fdsc" timed metadata when the ExtractEmbedded +option is used. + + Index1 Tag Name Writable + ------ -------- -------- + 8 FirmwareVersion no + 23 SerialNumber no + 87 OtherSerialNumber no + 102 Model no + +=head2 Qualcomm Tags + +The tags below have been observed in the JPEG APP7 "Qualcomm Camera +Attributes" segment written by some cameras such as the HP iPAQ Voice +Messenger. ExifTool will extract any information found from this segment, +even if it is not listed in this table. + + Tag Name Writable + -------- -------- + AECAggressiveness no + AECCurrentExpIndex no + AECCurrentSensorLuma no + AECEnable no + AECExposureIndexAdjStep no + AECHighLumaRegionCount no + AECHighLumaRegionThreshold no + AECIndoorIdx no + AECLumaTarget no + AECLumaTolerance no + AECMode no + AECOdoorIdx no + AECOutdoorBrightDiscarded no + AECOutdoorBrightEnable no + AECOutdoorBrightReduction no + AECOutdoorBrightThresholdHI no + AECOutdoorBrightThresholdLO no + AECOutdoorGammaIndex no + AECSnapshotDigitalGain no + AECSnapshotExposureTimeMs no + AECSnapshotLineCount no + AECSnapshotSensorGain no + AECVfeLuma no + AFBoundary no + AFCollectEndStat no + AFEnable no + AFFarEnd no + AFFineSrchPoints no + AFFineStep no + AFFocusTime no + AFGrossStep no + AFMode no + AFNearEnd no + AFPosDefMacro no + AFPosDefNorm no + AFPosition no + AFProcess no + AFREnable no + AFRFaster0ExpMod no + AFRFaster0Trigger no + AFRFaster1ExpMod no + AFRFaster1Trigger no + AFRFaster2ExpMod no + AFRFaster2Trigger no + AFRFaster3ExpMod no + AFRFaster3Trigger no + AFRFaster4ExpMod no + AFRFaster4Trigger no + AFRPossibleFrameCnt no + AFRSlower0ExpMod no + AFRSlower0Trigger no + AFRSlower1ExpMod no + AFRSlower1Trigger no + AFRSlower2ExpMod no + AFRSlower2Trigger no + AFRSlower3ExpMod no + AFRSlower3Trigger no + AFRSlower4ExpMod no + AFRSlower4Trigger no + AFResetLensAfterSnap no + AFStepsNearFar no + AFStepsNearInfinity no + AFTestMode no + AFTracePositions00 no + AFTracePositions01 no + AFTracePositions02 no + AFTracePositions03 no + AFTracePositions04 no + AFTracePositions05 no + AFTracePositions06 no + AFTracePositions07 no + AFTracePositions08 no + AFTracePositions09 no + AFTracePositions10 no + AFTracePositions11 no + AFTracePositions12 no + AFTracePositions13 no + AFTracePositions14 no + AFTracePositions15 no + AFTracePositions16 no + AFTracePositions17 no + AFTracePositions18 no + AFTracePositions19 no + AFTracePositions20 no + AFTracePositions21 no + AFTracePositions22 no + AFTracePositions23 no + AFTracePositions24 no + AFTracePositions25 no + AFTracePositions26 no + AFTracePositions27 no + AFTracePositions28 no + AFTracePositions29 no + AFTracePositions30 no + AFTracePositions31 no + AFTracePositions32 no + AFTracePositions33 no + AFTracePositions34 no + AFTracePositions35 no + AFTracePositions36 no + AFTracePositions37 no + AFTracePositions38 no + AFTracePositions39 no + AFTracePositions40 no + AFTracePositions41 no + AFTracePositions42 no + AFTracePositions43 no + AFTracePositions44 no + AFTracePositions45 no + AFTracePositions46 no + AFTracePositions47 no + AFTracePositions48 no + AFTracePositions49 no + AFTraceStats00 no + AFTraceStats01 no + AFTraceStats02 no + AFTraceStats03 no + AFTraceStats04 no + AFTraceStats05 no + AFTraceStats06 no + AFTraceStats07 no + AFTraceStats08 no + AFTraceStats09 no + AFTraceStats10 no + AFTraceStats11 no + AFTraceStats12 no + AFTraceStats13 no + AFTraceStats14 no + AFTraceStats15 no + AFTraceStats16 no + AFTraceStats17 no + AFTraceStats18 no + AFTraceStats19 no + AFTraceStats20 no + AFTraceStats21 no + AFTraceStats22 no + AFTraceStats23 no + AFTraceStats24 no + AFTraceStats25 no + AFTraceStats26 no + AFTraceStats27 no + AFTraceStats28 no + AFTraceStats29 no + AFTraceStats30 no + AFTraceStats31 no + AFTraceStats32 no + AFTraceStats33 no + AFTraceStats34 no + AFTraceStats35 no + AFTraceStats36 no + AFTraceStats37 no + AFTraceStats38 no + AFTraceStats39 no + AFTraceStats40 no + AFTraceStats41 no + AFTraceStats42 no + AFTraceStats43 no + AFTraceStats44 no + AFTraceStats45 no + AFTraceStats46 no + AFTraceStats47 no + AFTraceStats48 no + AFTraceStats49 no + AFUndershootProtect no + AFVfeHorzOffset no + AFVfeHorzWidth no + AFVfeMetricMax no + AFVfeVertHeight no + AFVfeVertOffset no + ASF3EdgeDetect no + ASF3EdgeFilterA11 no + ASF3EdgeFilterA12 no + ASF3EdgeFilterA13 no + ASF3EdgeFilterA21 no + ASF3EdgeFilterA22 no + ASF3EdgeFilterA23 no + ASF3EdgeFilterA31 no + ASF3EdgeFilterA32 no + ASF3EdgeFilterA33 no + ASF3Enable no + ASF3LowerThreshold no + ASF3NoiseFilterA11 no + ASF3NoiseFilterA12 no + ASF3NoiseFilterA13 no + ASF3NoiseFilterA21 no + ASF3NoiseFilterA22 no + ASF3NoiseFilterA23 no + ASF3NoiseFilterA31 no + ASF3NoiseFilterA32 no + ASF3NoiseFilterA33 no + ASF3UpperThreshold no + ASF5BrtLoThres no + ASF5BrtShrpDegF1 no + ASF5BrtShrpDegF2 no + ASF5BrtSmthPercent no + ASF5BrtUpThres no + ASF5Enable no + ASF5ExposureIndex1 no + ASF5ExposureIndex2 no + ASF5Filter1A11 no + ASF5Filter1A12 no + ASF5Filter1A13 no + ASF5Filter1A14 no + ASF5Filter1A15 no + ASF5Filter1A21 no + ASF5Filter1A22 no + ASF5Filter1A23 no + ASF5Filter1A24 no + ASF5Filter1A25 no + ASF5Filter1A31 no + ASF5Filter1A32 no + ASF5Filter1A33 no + ASF5Filter1A34 no + ASF5Filter1A35 no + ASF5Filter1A41 no + ASF5Filter1A42 no + ASF5Filter1A43 no + ASF5Filter1A44 no + ASF5Filter1A45 no + ASF5Filter1A51 no + ASF5Filter1A52 no + ASF5Filter1A53 no + ASF5Filter1A54 no + ASF5Filter1A55 no + ASF5Filter2A11 no + ASF5Filter2A12 no + ASF5Filter2A13 no + ASF5Filter2A14 no + ASF5Filter2A15 no + ASF5Filter2A21 no + ASF5Filter2A22 no + ASF5Filter2A23 no + ASF5Filter2A24 no + ASF5Filter2A25 no + ASF5Filter2A31 no + ASF5Filter2A32 no + ASF5Filter2A33 no + ASF5Filter2A34 no + ASF5Filter2A35 no + ASF5Filter2A41 no + ASF5Filter2A42 no + ASF5Filter2A43 no + ASF5Filter2A44 no + ASF5Filter2A45 no + ASF5Filter2A51 no + ASF5Filter2A52 no + ASF5Filter2A53 no + ASF5Filter2A54 no + ASF5Filter2A55 no + ASF5FilterMode no + ASF5LowLoThres no + ASF5LowShrpDegF1 no + ASF5LowShrpDegF2 no + ASF5LowSmthPrcnt no + ASF5LowUpThres no + ASF5LumaFilter00 no + ASF5LumaFilter01 no + ASF5LumaFilter02 no + ASF5LumaFilter03 no + ASF5LumaFilter04 no + ASF5LumaFilter05 no + ASF5LumaFilter06 no + ASF5LumaFilter07 no + ASF5LumaFilter08 no + ASF5MaxExposureIndex no + ASF5NrmLoThres no + ASF5NrmShrpDegF1 no + ASF5NrmShrpDegF2 no + ASF5NrmSmthPrcnt no + ASF5NrmUpThres no + ASF5NrmizeFactor1 no + ASF5NrmizeFactor2 no + AWBAggressiveness no + AWBAgwGridDist2Thresh no + AWBAlgorithm no + AWBAveBgRatio no + AWBAveRgRatio no + AWBBlueGainAdjRef1 no + AWBBlueGainAdjRef2 no + AWBBlueGainAdjRef3 no + AWBBlueGainAdjRef4 no + AWBBlueGainAdjRef5 no + AWBBlueGainAdjRef6 no + AWBBlueGainAdjRef7 no + AWBBlueGainAdjRef8 no + AWBBlueGainRef1 no + AWBBlueGainRef2 no + AWBBlueGainRef3 no + AWBBlueGainRef4 no + AWBBlueGainRef5 no + AWBBlueGainRef6 no + AWBBlueGainRef7 no + AWBBlueGainRef8 no + AWBCcBias no + AWBCompactClusterR2 no + AWBEnable no + AWBGreenOffsetBg no + AWBGreenOffsetRg no + AWBIndoorSampleInfluence no + AWBLoVfeC1 no + AWBLoVfeC2 no + AWBLoVfeC3 no + AWBLoVfeC4 no + AWBLoVfeM1 no + AWBLoVfeM2 no + AWBLoVfeM3 no + AWBLoVfeM4 no + AWBLoVfeMaxY no + AWBLoVfeMinY no + AWBLowLigColCorEna no + AWBMaxBGain no + AWBMaxGGain no + AWBMaxRGain no + AWBMinBGain no + AWBMinGGain no + AWBMinRGain no + AWBNormVfeC1 no + AWBNormVfeC2 no + AWBNormVfeC3 no + AWBNormVfeC4 no + AWBNormVfeM1 no + AWBNormVfeM2 no + AWBNormVfeM3 no + AWBNormVfeM4 no + AWBNormVfeMaxY no + AWBNormVfeMinY no + AWBOudorVfeC1 no + AWBOudorVfeC2 no + AWBOudorVfeC3 no + AWBOudorVfeC4 no + AWBOudorVfeM1 no + AWBOudorVfeM2 no + AWBOudorVfeM3 no + AWBOudorVfeM4 no + AWBOudorVfeMaxY no + AWBOudorVfeMinY no + AWBOutdoorSampleInfluence no + AWBPrevWbBgain no + AWBPrevWbGgain no + AWBPrevWbRgain no + AWBRedGainAdjRef1 no + AWBRedGainAdjRef2 no + AWBRedGainAdjRef3 no + AWBRedGainAdjRef4 no + AWBRedGainAdjRef5 no + AWBRedGainAdjRef6 no + AWBRedGainAdjRef7 no + AWBRedGainAdjRef8 no + AWBRedGainRef1 no + AWBRedGainRef2 no + AWBRedGainRef3 no + AWBRedGainRef4 no + AWBRedGainRef5 no + AWBRedGainRef6 no + AWBRedGainRef7 no + AWBRedGainRef8 no + AWBSampleDecision no + AWBSnapshotBGain no + AWBSnapshotRGain no + AntiBadingPixelClk no + AntiBadingPixelClkPerLine no + AntibandingEnable no + BlckLvlEvenCols no + BlckLvlOddCols no + CamMclkHz no + ChroSupChroThres1 no + ChroSupChroThres2 no + ChroSupLumaThres1 no + ChroSupLumaThres2 no + ChroSupLumaThres3 no + ChroSupLumaThres4 no + ChromSupress no + ClipToAfRato no + CurrResol no + DayltConvChrmA_M no + DayltConvChrmA_P no + DayltConvChrmB_M no + DayltConvChrmB_P no + DayltConvChrmC_M no + DayltConvChrmC_P no + DayltConvChrmD_M no + DayltConvChrmD_P no + DayltConvChrmKCb no + DayltConvChrmKCr no + DayltConvLumaK no + DayltConvLumaV0 no + DayltConvLumaV1 no + DayltConvLumaV2 no + DefConvChrmA_M no + DefConvChrmA_P no + DefConvChrmB_M no + DefConvChrmB_P no + DefConvChrmC_M no + DefConvChrmC_P no + DefConvChrmD_M no + DefConvChrmD_P no + DefConvChrmKCb no + DefConvChrmKCr no + DefConvLumaK no + DefConvLumaV0 no + DefConvLumaV1 no + DefConvLumaV2 no + DefCorC0 no + DefCorC1 no + DefCorC2 no + DefCorC3 no + DefCorC4 no + DefCorC5 no + DefCorC6 no + DefCorC7 no + DefCorC8 no + DefCorK0 no + DefCorK1 no + DefCorK2 no + DefLumaGammaMode no + DefRgbGammaMode no + DefectPixCorEnable no + DefectPixMaxThresh no + DefectPixMinThresh no + DiscardFrstFrm no + FrmSkipPttrn no + GammaEnable no + HJREnable no + HJRMaxNumFrames no + HJROneToTwoOffset no + HJRTextureThreshold no + HJR_NReductionFlat no + HJR_NReductionTexture no + IncandConvChrmA_M no + IncandConvChrmA_P no + IncandConvChrmB_M no + IncandConvChrmB_P no + IncandConvChrmC_M no + IncandConvChrmC_P no + IncandConvChrmD_M no + IncandConvChrmD_P no + IncandConvChrmKCb no + IncandConvChrmKCr no + IncandConvLumaK no + IncandConvLumaV0 no + IncandConvLumaV1 no + IncandConvLumaV2 no + LADetect no + LAEnable no + MaxPrviewFps no + MaxVideoFps no + NghtshtFps no + NightshotMode no + OutlierDistance no + PclkInvert no + PrviewFps no + PrviewResol no + R2ABlueCtbl00 no + R2ABlueCtbl01 no + R2ABlueCtbl02 no + R2ABlueCtbl03 no + R2ABlueCtbl04 no + R2ABlueCtbl05 no + R2ABlueCtbl06 no + R2ABlueCtbl07 no + R2ABlueCtbl08 no + R2ABlueCtbl09 no + R2ABlueCtbl10 no + R2ABlueCtbl11 no + R2ABlueCtbl12 no + R2ABlueCtbl13 no + R2ABlueCtbl14 no + R2ABlueCtbl15 no + R2ABlueCtbl16 no + R2ABlueCtbl17 no + R2ABlueCtbl18 no + R2ABlueCtbl19 no + R2ABlueCtbl20 no + R2ABlueCtbl21 no + R2ABlueCtbl22 no + R2ABlueCtbl23 no + R2ABlueCtbl24 no + R2ABlueCtbl25 no + R2ABlueCtbl26 no + R2ABlueCtbl27 no + R2ABlueCtbl28 no + R2ABlueCtbl29 no + R2ABlueCtbl30 no + R2ABlueCtbl31 no + R2ABlueStbl00 no + R2ABlueStbl01 no + R2ABlueStbl02 no + R2ABlueStbl03 no + R2ABlueStbl04 no + R2ABlueStbl05 no + R2ABlueStbl06 no + R2ABlueStbl07 no + R2ABlueStbl08 no + R2ABlueStbl09 no + R2ABlueStbl10 no + R2ABlueStbl11 no + R2ABlueStbl12 no + R2ABlueStbl13 no + R2ABlueStbl14 no + R2ABlueStbl15 no + R2ABlueStbl16 no + R2ABlueStbl17 no + R2ABlueStbl18 no + R2ABlueStbl19 no + R2ABlueStbl20 no + R2ABlueStbl21 no + R2ABlueStbl22 no + R2ABlueStbl23 no + R2ABlueStbl24 no + R2ABlueStbl25 no + R2ABlueStbl26 no + R2ABlueStbl27 no + R2ABlueStbl28 no + R2ABlueStbl29 no + R2ABlueStbl30 no + R2ABlueStbl31 no + R2ACx no + R2ACy no + R2AGreenCtbl00 no + R2AGreenCtbl01 no + R2AGreenCtbl02 no + R2AGreenCtbl03 no + R2AGreenCtbl04 no + R2AGreenCtbl05 no + R2AGreenCtbl06 no + R2AGreenCtbl07 no + R2AGreenCtbl08 no + R2AGreenCtbl09 no + R2AGreenCtbl10 no + R2AGreenCtbl11 no + R2AGreenCtbl12 no + R2AGreenCtbl13 no + R2AGreenCtbl14 no + R2AGreenCtbl15 no + R2AGreenCtbl16 no + R2AGreenCtbl17 no + R2AGreenCtbl18 no + R2AGreenCtbl19 no + R2AGreenCtbl20 no + R2AGreenCtbl21 no + R2AGreenCtbl22 no + R2AGreenCtbl23 no + R2AGreenCtbl24 no + R2AGreenCtbl25 no + R2AGreenCtbl26 no + R2AGreenCtbl27 no + R2AGreenCtbl28 no + R2AGreenCtbl29 no + R2AGreenCtbl30 no + R2AGreenCtbl31 no + R2AGreenStbl00 no + R2AGreenStbl01 no + R2AGreenStbl02 no + R2AGreenStbl03 no + R2AGreenStbl04 no + R2AGreenStbl05 no + R2AGreenStbl06 no + R2AGreenStbl07 no + R2AGreenStbl08 no + R2AGreenStbl09 no + R2AGreenStbl10 no + R2AGreenStbl11 no + R2AGreenStbl12 no + R2AGreenStbl13 no + R2AGreenStbl14 no + R2AGreenStbl15 no + R2AGreenStbl16 no + R2AGreenStbl17 no + R2AGreenStbl18 no + R2AGreenStbl19 no + R2AGreenStbl20 no + R2AGreenStbl21 no + R2AGreenStbl22 no + R2AGreenStbl23 no + R2AGreenStbl24 no + R2AGreenStbl25 no + R2AGreenStbl26 no + R2AGreenStbl27 no + R2AGreenStbl28 no + R2AGreenStbl29 no + R2AGreenStbl30 no + R2AGreenStbl31 no + R2AHeight no + R2AIntervals no + R2ARedCtbl00 no + R2ARedCtbl01 no + R2ARedCtbl02 no + R2ARedCtbl03 no + R2ARedCtbl04 no + R2ARedCtbl05 no + R2ARedCtbl06 no + R2ARedCtbl07 no + R2ARedCtbl08 no + R2ARedCtbl09 no + R2ARedCtbl10 no + R2ARedCtbl11 no + R2ARedCtbl12 no + R2ARedCtbl13 no + R2ARedCtbl14 no + R2ARedCtbl15 no + R2ARedCtbl16 no + R2ARedCtbl17 no + R2ARedCtbl18 no + R2ARedCtbl19 no + R2ARedCtbl20 no + R2ARedCtbl21 no + R2ARedCtbl22 no + R2ARedCtbl23 no + R2ARedCtbl24 no + R2ARedCtbl25 no + R2ARedCtbl26 no + R2ARedCtbl27 no + R2ARedCtbl28 no + R2ARedCtbl29 no + R2ARedCtbl30 no + R2ARedCtbl31 no + R2ARedStbl00 no + R2ARedStbl01 no + R2ARedStbl02 no + R2ARedStbl03 no + R2ARedStbl04 no + R2ARedStbl05 no + R2ARedStbl06 no + R2ARedStbl07 no + R2ARedStbl08 no + R2ARedStbl09 no + R2ARedStbl10 no + R2ARedStbl11 no + R2ARedStbl12 no + R2ARedStbl13 no + R2ARedStbl14 no + R2ARedStbl15 no + R2ARedStbl16 no + R2ARedStbl17 no + R2ARedStbl18 no + R2ARedStbl19 no + R2ARedStbl20 no + R2ARedStbl21 no + R2ARedStbl22 no + R2ARedStbl23 no + R2ARedStbl24 no + R2ARedStbl25 no + R2ARedStbl26 no + R2ARedStbl27 no + R2ARedStbl28 no + R2ARedStbl29 no + R2ARedStbl30 no + R2ARedStbl31 no + R2ATbl00 no + R2ATbl01 no + R2ATbl02 no + R2ATbl03 no + R2ATbl04 no + R2ATbl05 no + R2ATbl06 no + R2ATbl07 no + R2ATbl08 no + R2ATbl09 no + R2ATbl10 no + R2ATbl11 no + R2ATbl12 no + R2ATbl13 no + R2ATbl14 no + R2ATbl15 no + R2ATbl16 no + R2ATbl17 no + R2ATbl18 no + R2ATbl19 no + R2ATbl20 no + R2ATbl21 no + R2ATbl22 no + R2ATbl23 no + R2ATbl24 no + R2ATbl25 no + R2ATbl26 no + R2ATbl27 no + R2ATbl28 no + R2ATbl29 no + R2ATbl30 no + R2ATbl31 no + R2AWidth no + R2D65BlueCtbl00 no + R2D65BlueCtbl01 no + R2D65BlueCtbl02 no + R2D65BlueCtbl03 no + R2D65BlueCtbl04 no + R2D65BlueCtbl05 no + R2D65BlueCtbl06 no + R2D65BlueCtbl07 no + R2D65BlueCtbl08 no + R2D65BlueCtbl09 no + R2D65BlueCtbl10 no + R2D65BlueCtbl11 no + R2D65BlueCtbl12 no + R2D65BlueCtbl13 no + R2D65BlueCtbl14 no + R2D65BlueCtbl15 no + R2D65BlueCtbl16 no + R2D65BlueCtbl17 no + R2D65BlueCtbl18 no + R2D65BlueCtbl19 no + R2D65BlueCtbl20 no + R2D65BlueCtbl21 no + R2D65BlueCtbl22 no + R2D65BlueCtbl23 no + R2D65BlueCtbl24 no + R2D65BlueCtbl25 no + R2D65BlueCtbl26 no + R2D65BlueCtbl27 no + R2D65BlueCtbl28 no + R2D65BlueCtbl29 no + R2D65BlueCtbl30 no + R2D65BlueCtbl31 no + R2D65BlueStbl00 no + R2D65BlueStbl01 no + R2D65BlueStbl02 no + R2D65BlueStbl03 no + R2D65BlueStbl04 no + R2D65BlueStbl05 no + R2D65BlueStbl06 no + R2D65BlueStbl07 no + R2D65BlueStbl08 no + R2D65BlueStbl09 no + R2D65BlueStbl10 no + R2D65BlueStbl11 no + R2D65BlueStbl12 no + R2D65BlueStbl13 no + R2D65BlueStbl14 no + R2D65BlueStbl15 no + R2D65BlueStbl16 no + R2D65BlueStbl17 no + R2D65BlueStbl18 no + R2D65BlueStbl19 no + R2D65BlueStbl20 no + R2D65BlueStbl21 no + R2D65BlueStbl22 no + R2D65BlueStbl23 no + R2D65BlueStbl24 no + R2D65BlueStbl25 no + R2D65BlueStbl26 no + R2D65BlueStbl27 no + R2D65BlueStbl28 no + R2D65BlueStbl29 no + R2D65BlueStbl30 no + R2D65BlueStbl31 no + R2D65Cx no + R2D65Cy no + R2D65GreenCtbl00 no + R2D65GreenCtbl01 no + R2D65GreenCtbl02 no + R2D65GreenCtbl03 no + R2D65GreenCtbl04 no + R2D65GreenCtbl05 no + R2D65GreenCtbl06 no + R2D65GreenCtbl07 no + R2D65GreenCtbl08 no + R2D65GreenCtbl09 no + R2D65GreenCtbl10 no + R2D65GreenCtbl11 no + R2D65GreenCtbl12 no + R2D65GreenCtbl13 no + R2D65GreenCtbl14 no + R2D65GreenCtbl15 no + R2D65GreenCtbl16 no + R2D65GreenCtbl17 no + R2D65GreenCtbl18 no + R2D65GreenCtbl19 no + R2D65GreenCtbl20 no + R2D65GreenCtbl21 no + R2D65GreenCtbl22 no + R2D65GreenCtbl23 no + R2D65GreenCtbl24 no + R2D65GreenCtbl25 no + R2D65GreenCtbl26 no + R2D65GreenCtbl27 no + R2D65GreenCtbl28 no + R2D65GreenCtbl29 no + R2D65GreenCtbl30 no + R2D65GreenCtbl31 no + R2D65GreenStbl00 no + R2D65GreenStbl01 no + R2D65GreenStbl02 no + R2D65GreenStbl03 no + R2D65GreenStbl04 no + R2D65GreenStbl05 no + R2D65GreenStbl06 no + R2D65GreenStbl07 no + R2D65GreenStbl08 no + R2D65GreenStbl09 no + R2D65GreenStbl10 no + R2D65GreenStbl11 no + R2D65GreenStbl12 no + R2D65GreenStbl13 no + R2D65GreenStbl14 no + R2D65GreenStbl15 no + R2D65GreenStbl16 no + R2D65GreenStbl17 no + R2D65GreenStbl18 no + R2D65GreenStbl19 no + R2D65GreenStbl20 no + R2D65GreenStbl21 no + R2D65GreenStbl22 no + R2D65GreenStbl23 no + R2D65GreenStbl24 no + R2D65GreenStbl25 no + R2D65GreenStbl26 no + R2D65GreenStbl27 no + R2D65GreenStbl28 no + R2D65GreenStbl29 no + R2D65GreenStbl30 no + R2D65GreenStbl31 no + R2D65Height no + R2D65Intervals no + R2D65RedCtbl00 no + R2D65RedCtbl01 no + R2D65RedCtbl02 no + R2D65RedCtbl03 no + R2D65RedCtbl04 no + R2D65RedCtbl05 no + R2D65RedCtbl06 no + R2D65RedCtbl07 no + R2D65RedCtbl08 no + R2D65RedCtbl09 no + R2D65RedCtbl10 no + R2D65RedCtbl11 no + R2D65RedCtbl12 no + R2D65RedCtbl13 no + R2D65RedCtbl14 no + R2D65RedCtbl15 no + R2D65RedCtbl16 no + R2D65RedCtbl17 no + R2D65RedCtbl18 no + R2D65RedCtbl19 no + R2D65RedCtbl20 no + R2D65RedCtbl21 no + R2D65RedCtbl22 no + R2D65RedCtbl23 no + R2D65RedCtbl24 no + R2D65RedCtbl25 no + R2D65RedCtbl26 no + R2D65RedCtbl27 no + R2D65RedCtbl28 no + R2D65RedCtbl29 no + R2D65RedCtbl30 no + R2D65RedCtbl31 no + R2D65RedStbl00 no + R2D65RedStbl01 no + R2D65RedStbl02 no + R2D65RedStbl03 no + R2D65RedStbl04 no + R2D65RedStbl05 no + R2D65RedStbl06 no + R2D65RedStbl07 no + R2D65RedStbl08 no + R2D65RedStbl09 no + R2D65RedStbl10 no + R2D65RedStbl11 no + R2D65RedStbl12 no + R2D65RedStbl13 no + R2D65RedStbl14 no + R2D65RedStbl15 no + R2D65RedStbl16 no + R2D65RedStbl17 no + R2D65RedStbl18 no + R2D65RedStbl19 no + R2D65RedStbl20 no + R2D65RedStbl21 no + R2D65RedStbl22 no + R2D65RedStbl23 no + R2D65RedStbl24 no + R2D65RedStbl25 no + R2D65RedStbl26 no + R2D65RedStbl27 no + R2D65RedStbl28 no + R2D65RedStbl29 no + R2D65RedStbl30 no + R2D65RedStbl31 no + R2D65Tbl00 no + R2D65Tbl01 no + R2D65Tbl02 no + R2D65Tbl03 no + R2D65Tbl04 no + R2D65Tbl05 no + R2D65Tbl06 no + R2D65Tbl07 no + R2D65Tbl08 no + R2D65Tbl09 no + R2D65Tbl10 no + R2D65Tbl11 no + R2D65Tbl12 no + R2D65Tbl13 no + R2D65Tbl14 no + R2D65Tbl15 no + R2D65Tbl16 no + R2D65Tbl17 no + R2D65Tbl18 no + R2D65Tbl19 no + R2D65Tbl20 no + R2D65Tbl21 no + R2D65Tbl22 no + R2D65Tbl23 no + R2D65Tbl24 no + R2D65Tbl25 no + R2D65Tbl26 no + R2D65Tbl27 no + R2D65Tbl28 no + R2D65Tbl29 no + R2D65Tbl30 no + R2D65Tbl31 no + R2D65Width no + R2TL84BlueCtbl00 no + R2TL84BlueCtbl01 no + R2TL84BlueCtbl02 no + R2TL84BlueCtbl03 no + R2TL84BlueCtbl04 no + R2TL84BlueCtbl05 no + R2TL84BlueCtbl06 no + R2TL84BlueCtbl07 no + R2TL84BlueCtbl08 no + R2TL84BlueCtbl09 no + R2TL84BlueCtbl10 no + R2TL84BlueCtbl11 no + R2TL84BlueCtbl12 no + R2TL84BlueCtbl13 no + R2TL84BlueCtbl14 no + R2TL84BlueCtbl15 no + R2TL84BlueCtbl16 no + R2TL84BlueCtbl17 no + R2TL84BlueCtbl18 no + R2TL84BlueCtbl19 no + R2TL84BlueCtbl20 no + R2TL84BlueCtbl21 no + R2TL84BlueCtbl22 no + R2TL84BlueCtbl23 no + R2TL84BlueCtbl24 no + R2TL84BlueCtbl25 no + R2TL84BlueCtbl26 no + R2TL84BlueCtbl27 no + R2TL84BlueCtbl28 no + R2TL84BlueCtbl29 no + R2TL84BlueCtbl30 no + R2TL84BlueCtbl31 no + R2TL84BlueStbl00 no + R2TL84BlueStbl01 no + R2TL84BlueStbl02 no + R2TL84BlueStbl03 no + R2TL84BlueStbl04 no + R2TL84BlueStbl05 no + R2TL84BlueStbl06 no + R2TL84BlueStbl07 no + R2TL84BlueStbl08 no + R2TL84BlueStbl09 no + R2TL84BlueStbl10 no + R2TL84BlueStbl11 no + R2TL84BlueStbl12 no + R2TL84BlueStbl13 no + R2TL84BlueStbl14 no + R2TL84BlueStbl15 no + R2TL84BlueStbl16 no + R2TL84BlueStbl17 no + R2TL84BlueStbl18 no + R2TL84BlueStbl19 no + R2TL84BlueStbl20 no + R2TL84BlueStbl21 no + R2TL84BlueStbl22 no + R2TL84BlueStbl23 no + R2TL84BlueStbl24 no + R2TL84BlueStbl25 no + R2TL84BlueStbl26 no + R2TL84BlueStbl27 no + R2TL84BlueStbl28 no + R2TL84BlueStbl29 no + R2TL84BlueStbl30 no + R2TL84BlueStbl31 no + R2TL84Cx no + R2TL84Cy no + R2TL84GreenCtbl00 no + R2TL84GreenCtbl01 no + R2TL84GreenCtbl02 no + R2TL84GreenCtbl03 no + R2TL84GreenCtbl04 no + R2TL84GreenCtbl05 no + R2TL84GreenCtbl06 no + R2TL84GreenCtbl07 no + R2TL84GreenCtbl08 no + R2TL84GreenCtbl09 no + R2TL84GreenCtbl10 no + R2TL84GreenCtbl11 no + R2TL84GreenCtbl12 no + R2TL84GreenCtbl13 no + R2TL84GreenCtbl14 no + R2TL84GreenCtbl15 no + R2TL84GreenCtbl16 no + R2TL84GreenCtbl17 no + R2TL84GreenCtbl18 no + R2TL84GreenCtbl19 no + R2TL84GreenCtbl20 no + R2TL84GreenCtbl21 no + R2TL84GreenCtbl22 no + R2TL84GreenCtbl23 no + R2TL84GreenCtbl24 no + R2TL84GreenCtbl25 no + R2TL84GreenCtbl26 no + R2TL84GreenCtbl27 no + R2TL84GreenCtbl28 no + R2TL84GreenCtbl29 no + R2TL84GreenCtbl30 no + R2TL84GreenCtbl31 no + R2TL84GreenStbl00 no + R2TL84GreenStbl01 no + R2TL84GreenStbl02 no + R2TL84GreenStbl03 no + R2TL84GreenStbl04 no + R2TL84GreenStbl05 no + R2TL84GreenStbl06 no + R2TL84GreenStbl07 no + R2TL84GreenStbl08 no + R2TL84GreenStbl09 no + R2TL84GreenStbl10 no + R2TL84GreenStbl11 no + R2TL84GreenStbl12 no + R2TL84GreenStbl13 no + R2TL84GreenStbl14 no + R2TL84GreenStbl15 no + R2TL84GreenStbl16 no + R2TL84GreenStbl17 no + R2TL84GreenStbl18 no + R2TL84GreenStbl19 no + R2TL84GreenStbl20 no + R2TL84GreenStbl21 no + R2TL84GreenStbl22 no + R2TL84GreenStbl23 no + R2TL84GreenStbl24 no + R2TL84GreenStbl25 no + R2TL84GreenStbl26 no + R2TL84GreenStbl27 no + R2TL84GreenStbl28 no + R2TL84GreenStbl29 no + R2TL84GreenStbl30 no + R2TL84GreenStbl31 no + R2TL84Height no + R2TL84Intervals no + R2TL84RedCtbl00 no + R2TL84RedCtbl01 no + R2TL84RedCtbl02 no + R2TL84RedCtbl03 no + R2TL84RedCtbl04 no + R2TL84RedCtbl05 no + R2TL84RedCtbl06 no + R2TL84RedCtbl07 no + R2TL84RedCtbl08 no + R2TL84RedCtbl09 no + R2TL84RedCtbl10 no + R2TL84RedCtbl11 no + R2TL84RedCtbl12 no + R2TL84RedCtbl13 no + R2TL84RedCtbl14 no + R2TL84RedCtbl15 no + R2TL84RedCtbl16 no + R2TL84RedCtbl17 no + R2TL84RedCtbl18 no + R2TL84RedCtbl19 no + R2TL84RedCtbl20 no + R2TL84RedCtbl21 no + R2TL84RedCtbl22 no + R2TL84RedCtbl23 no + R2TL84RedCtbl24 no + R2TL84RedCtbl25 no + R2TL84RedCtbl26 no + R2TL84RedCtbl27 no + R2TL84RedCtbl28 no + R2TL84RedCtbl29 no + R2TL84RedCtbl30 no + R2TL84RedCtbl31 no + R2TL84RedStbl00 no + R2TL84RedStbl01 no + R2TL84RedStbl02 no + R2TL84RedStbl03 no + R2TL84RedStbl04 no + R2TL84RedStbl05 no + R2TL84RedStbl06 no + R2TL84RedStbl07 no + R2TL84RedStbl08 no + R2TL84RedStbl09 no + R2TL84RedStbl10 no + R2TL84RedStbl11 no + R2TL84RedStbl12 no + R2TL84RedStbl13 no + R2TL84RedStbl14 no + R2TL84RedStbl15 no + R2TL84RedStbl16 no + R2TL84RedStbl17 no + R2TL84RedStbl18 no + R2TL84RedStbl19 no + R2TL84RedStbl20 no + R2TL84RedStbl21 no + R2TL84RedStbl22 no + R2TL84RedStbl23 no + R2TL84RedStbl24 no + R2TL84RedStbl25 no + R2TL84RedStbl26 no + R2TL84RedStbl27 no + R2TL84RedStbl28 no + R2TL84RedStbl29 no + R2TL84RedStbl30 no + R2TL84RedStbl31 no + R2TL84Tbl00 no + R2TL84Tbl01 no + R2TL84Tbl02 no + R2TL84Tbl03 no + R2TL84Tbl04 no + R2TL84Tbl05 no + R2TL84Tbl06 no + R2TL84Tbl07 no + R2TL84Tbl08 no + R2TL84Tbl09 no + R2TL84Tbl10 no + R2TL84Tbl11 no + R2TL84Tbl12 no + R2TL84Tbl13 no + R2TL84Tbl14 no + R2TL84Tbl15 no + R2TL84Tbl16 no + R2TL84Tbl17 no + R2TL84Tbl18 no + R2TL84Tbl19 no + R2TL84Tbl20 no + R2TL84Tbl21 no + R2TL84Tbl22 no + R2TL84Tbl23 no + R2TL84Tbl24 no + R2TL84Tbl25 no + R2TL84Tbl26 no + R2TL84Tbl27 no + R2TL84Tbl28 no + R2TL84Tbl29 no + R2TL84Tbl30 no + R2TL84Tbl31 no + R2TL84Width no + RolloffEnable no + SensorFmt no + SensorType no + SensrFulHght no + SensrFulWdth no + SensrQtrHght no + SensrQtrWdth no + SnapshotResol no + TL84ConvChrmA_M no + TL84ConvChrmA_P no + TL84ConvChrmB_M no + TL84ConvChrmB_P no + TL84ConvChrmC_M no + TL84ConvChrmC_P no + TL84ConvChrmD_M no + TL84ConvChrmD_P no + TL84ConvChrmKCb no + TL84ConvChrmKCr no + TL84ConvLumaK no + TL84ConvLumaV0 no + TL84ConvLumaV1 no + TL84ConvLumaV2 no + VideoFps no + YhiYloConvChrmA_M no + YhiYloConvChrmA_P no + YhiYloConvChrmB_M no + YhiYloConvChrmB_P no + YhiYloConvChrmC_M no + YhiYloConvChrmC_P no + YhiYloConvChrmD_M no + YhiYloConvChrmD_P no + YhiYloConvChrmKCb no + YhiYloConvChrmKCr no + YhiYloConvLumaK no + YhiYloConvLumaV0 no + YhiYloConvLumaV1 no + YhiYloConvLumaV2 no + YhiYloCorC0 no + YhiYloCorC1 no + YhiYloCorC2 no + YhiYloCorC3 no + YhiYloCorC4 no + YhiYloCorC5 no + YhiYloCorC6 no + YhiYloCorC7 no + YhiYloCorC8 no + YhiYloCorK0 no + YhiYloCorK1 no + YhiYloCorK2 no + +=head2 APP12 Tags + +=head3 APP12 PictureInfo Tags + +The JPEG APP12 "Picture Info" segment was used by some older cameras, and +contains ASCII-based meta information. Below are some tags which have been +observed Agfa and Polaroid images, however ExifTool will extract information +from any tags found in this segment. + + Tag ID Tag Name Writable + ------ -------- -------- + 'Aperture' Aperture no + 'ColorMode' ColorMode no + 'ConTake' ConTake no + 'ExpBias' ExposureCompensation no + 'FNumber' FNumber no + 'FWare' FirmwareVersion no + 'Flash' Flash no + 'FocusMode' FocusMode no + 'FocusPos' FocusPos no + 'ID' ID no + 'ImageSize' ImageSize no + 'LightS' LightS no + 'Macro' Macro no + 'Protect' Protect no + 'Quality' Quality no + 'Resolution' Resolution no + 'Serial#' SerialNumber no + 'Shutter' ExposureTime no + 'StrobeTime' StrobeTime no + 'TimeDate' DateTimeOriginal no + 'Type' CameraType no + 'Version' Version no + 'Ytarget' YTarget no + 'Zoom' Zoom no + 'ZoomPos' ZoomPos no + 'shtr' ExposureTime no + 'ylevel' YLevel no + +=head3 APP12 Ducky Tags + +Photoshop uses the JPEG APP12 "Ducky" segment to store some information in +"Save for Web" images. + + Tag ID Tag Name Writable + ------ -------- -------- + 0x0001 Quality int32u/ + 0x0002 Comment string/ + 0x0003 Copyright string/ + +=head2 AFCP Tags + +AFCP stands for AXS File Concatenation Protocol, and is a poorly designed +protocol for appending information to the end of files. This can be used as +an auxiliary technique to store IPTC information in images, but is +incompatible with some file formats. + +ExifTool will read and write (but not create) AFCP IPTC information in JPEG +and TIFF images. + +See +L<http://web.archive.org/web/20080828211305/http://www.tocarte.com/media/axs_afcp_spec.pdf> +for the AFCP specification. + + Tag ID Tag Name Writable + ------ -------- -------- + 'IPTC' IPTC IPTC + 'Nail' ThumbnailImage no + 'PrVw' PreviewImage no + 'TEXT' Text no + +=head2 DarwinCore Tags + +Tags defined in the Darwin Core (dwc) XMP namespace. See +L<http://rs.tdwg.org/dwc/index.htm> for the official specification. + +These tags belong to the ExifTool XMP-dwc family 1 group. + + Tag Name Writable + -------- -------- + DCTermsLocation DarwinCore DCTermsLocation Struct + DCContinent string_ + DCCoordinatePrecision string_ + DCCoordinateUncertaintyInMeters string_ + DCCountry string_ + DCCountryCode string_ + DCCounty string_ + DCDecimalLatitude string_ + DCDecimalLongitude string_ + DCFootprintSpatialFit string_ + DCFootprintSRS string_ + DCFootprintWKT string_ + DCGeodeticDatum string_ + DCGeoreferencedBy string_ + DCGeoreferencedDate string_ + DCGeoreferenceProtocol string_ + DCGeoreferenceRemarks string_ + DCGeoreferenceSources string_ + DCGeoreferenceVerificationStatus string_ + DCHigherGeography string_ + DCHigherGeographyID string_ + DCIsland string_ + DCIslandGroup string_ + DCLocality string_ + DCLocationAccordingTo string_ + DCLocationID string_ + DCLocationRemarks string_ + DCMaximumDepthInMeters string_ + DCMaximumDistanceAboveSurfaceInMeters string_ + DCMaximumElevationInMeters string_ + DCMinimumDepthInMeters string_ + DCMinimumDistanceAboveSurfaceInMeters string_ + DCMinimumElevationInMeters string_ + DCMunicipality string_ + DCPointRadiusSpatialFit string_ + DCStateProvince string_ + DCVerbatimCoordinates string_ + DCVerbatimCoordinateSystem string_ + DCVerbatimDepth string_ + DCVerbatimElevation string_ + DCVerbatimLatitude string_ + DCVerbatimLocality string_ + DCVerbatimLongitude string_ + DCVerbatimSRS string_ + DCWaterBody string_ + DCEvent DarwinCore Event Struct + EventDay integer_ + EventEarliestDate date_ + EventEndDayOfYear integer_ + EventDate date_ + EventID string_ + EventRemarks lang-alt_ + EventTime date_ + EventFieldNotes string_ + EventFieldNumber string_ + EventHabitat string_ + EventLatestDate date_ + EventMonth integer_ + EventParentEventID string_ + EventSampleSizeUnit string_ + EventSampleSizeValue string_ + EventSamplingEffort string_ + EventSamplingProtocol string_ + EventStartDayOfYear integer_ + EventVerbatimEventDate string_ + EventYear integer_ + FossilSpecimen DarwinCore MaterialSample Struct + FossilSpecimenMaterialSampleID string_ + GeologicalContext DarwinCore GeologicalContext Struct + GeologicalContextBed string_ + EarliestAgeOrLowestStage string_ + EarliestEonOrLowestEonothem string_ + EarliestEpochOrLowestSeries string_ + EarliestEraOrLowestErathem string_ + EarliestPeriodOrLowestSystem string_ + GeologicalContextFormation string_ + GeologicalContextID string_ + GeologicalContextGroup string_ + HighestBiostratigraphicZone string_ + LatestAgeOrHighestStage string_ + LatestEonOrHighestEonothem string_ + LatestEpochOrHighestSeries string_ + LatestEraOrHighestErathem string_ + LatestPeriodOrHighestSystem string_ + LithostratigraphicTerms string_ + LowestBiostratigraphicZone string_ + GeologicalContextMember string_ + HumanObservation DarwinCore Event Struct + HumanObservationDay integer_ + HumanObservationEarliestDate date_ + HumanObservationEndDayOfYear integer_ + HumanObservationEventDate date_ + HumanObservationEventID string_ + HumanObservationEventRemarks lang-alt_ + HumanObservationEventTime date_ + HumanObservationFieldNotes string_ + HumanObservationFieldNumber string_ + HumanObservationHabitat string_ + HumanObservationLatestDate date_ + HumanObservationMonth integer_ + HumanObservationParentEventID string_ + HumanObservationSampleSizeUnit string_ + HumanObservationSampleSizeValue string_ + HumanObservationSamplingEffort string_ + HumanObservationSamplingProtocol string_ + HumanObservationStartDayOfYear integer_ + HumanObservationVerbatimEventDate string_ + HumanObservationYear integer_ + Identification DarwinCore Identification Struct + DateIdentified date_ + IdentificationID string_ + IdentificationQualifier string_ + IdentificationReferences string_ + IdentificationRemarks string_ + IdentificationVerificationStatus string_ + IdentifiedBy string_ + TypeStatus string_ + LivingSpecimen DarwinCore MaterialSample Struct + LivingSpecimenMaterialSampleID string_ + MachineObservation DarwinCore Event Struct + MachineObservationDay integer_ + MachineObservationEarliestDate date_ + MachineObservationEndDayOfYear integer_ + MachineObservationEventDate date_ + MachineObservationEventID string_ + MachineObservationEventRemarks lang-alt_ + MachineObservationEventTime date_ + MachineObservationFieldNotes string_ + MachineObservationFieldNumber string_ + MachineObservationHabitat string_ + MachineObservationLatestDate date_ + MachineObservationMonth integer_ + MachineObservationParentEventID string_ + MachineObservationSampleSizeUnit string_ + MachineObservationSampleSizeValue string_ + MachineObservationSamplingEffort string_ + MachineObservationSamplingProtocol string_ + MachineObservationStartDayOfYear integer_ + MachineObservationVerbatimEventDate string_ + MachineObservationYear integer_ + MaterialSample DarwinCore MaterialSample Struct + MaterialSampleID string_ + MeasurementOrFact DarwinCore MeasurementOrFact Struct + MeasurementAccuracy string_ + MeasurementDeterminedBy string_ + MeasurementDeterminedDate date_ + MeasurementID string_ + MeasurementMethod string_ + MeasurementRemarks string_ + MeasurementType string_ + MeasurementUnit string_ + MeasurementValue string_ + Occurrence DarwinCore Occurrence Struct + OccurrenceAssociatedMedia string_ + OccurrenceAssociatedOccurrences string_ + OccurrenceAssociatedReferences string_ + OccurrenceAssociatedSequences string_ + OccurrenceAssociatedTaxa string_ + OccurrenceBehavior string_ + OccurrenceCatalogNumber string_ + OccurrenceDisposition string_ + OccurrenceEstablishmentMeans string_ + OccurrenceIndividualCount string_ + OccurrenceIndividualID string_ + OccurrenceLifeStage string_ + OccurrenceDetails string_ + OccurrenceID string_ + OccurrenceRemarks string_ + OccurrenceStatus string_ + OccurrenceOrganismQuantity string_ + OccurrenceOrganismQuantityType string_ + OccurrenceOtherCatalogNumbers string_ + OccurrencePreparations string_ + OccurrencePreviousIdentifications string_ + OccurrenceRecordedBy string_ + OccurrenceRecordNumber string_ + OccurrenceReproductiveCondition string_ + OccurrenceSex string_ + Organism DarwinCore Organism Struct + OrganismAssociatedOccurrences string_ + OrganismAssociatedOrganisms string_ + OrganismID string_ + OrganismName string_ + OrganismRemarks string_ + OrganismScope string_ + OrganismPreviousIdentifications string_ + PreservedSpecimen DarwinCore MaterialSample Struct + PreservedSpecimenMaterialSampleID string_ + Record DarwinCore Record Struct + RecordBasisOfRecord string_ + RecordCollectionCode string_ + RecordCollectionID string_ + RecordDataGeneralizations string_ + RecordDatasetID string_ + RecordDatasetName string_ + RecordDynamicProperties string_ + RecordInformationWithheld string_ + RecordInstitutionCode string_ + RecordInstitutionID string_ + RecordOwnerInstitutionCode string_ + ResourceRelationship DarwinCore ResourceRelationship Struct + RelatedResourceID string_ + RelationshipAccordingTo string_ + RelationshipEstablishedDate date_ + RelationshipOfResource string_ + RelationshipRemarks string_ + ResourceID string_ + ResourceRelationshipID string_ + Taxon DarwinCore Taxon Struct + TaxonAcceptedNameUsage string_ + TaxonAcceptedNameUsageID string_ + TaxonClass string_ + TaxonFamily string_ + TaxonGenus string_ + TaxonHigherClassification string_ + TaxonInfraspecificEpithet string_ + TaxonKingdom string_ + TaxonNameAccordingTo string_ + TaxonNameAccordingToID string_ + TaxonNamePublishedIn string_ + TaxonNamePublishedInID string_ + TaxonNamePublishedInYear string_ + TaxonNomenclaturalCode string_ + TaxonNomenclaturalStatus string_ + TaxonOrder string_ + TaxonOriginalNameUsage string_ + TaxonOriginalNameUsageID string_ + TaxonParentNameUsage string_ + TaxonParentNameUsageID string_ + TaxonPhylum string_ + TaxonScientificName string_ + TaxonScientificNameAuthorship string_ + TaxonScientificNameID string_ + TaxonSpecificEpithet string_ + TaxonSubgenus string_ + TaxonConceptID string_ + TaxonID string_ + TaxonTaxonomicStatus string_ + TaxonRank string_ + TaxonRemarks string_ + TaxonVerbatimTaxonRank string_ + TaxonVernacularName lang-alt_ + +=head3 DarwinCore DCTermsLocation Struct + + Field Name Writable + ---------- -------- + Continent string + CoordinatePrecision string + CoordinateUncertaintyInMeters string + Country string + CountryCode string + County string + DecimalLatitude string + DecimalLongitude string + FootprintSRS string + FootprintSpatialFit string + FootprintWKT string + GeodeticDatum string + GeoreferenceProtocol string + GeoreferenceRemarks string + GeoreferenceSources string + GeoreferenceVerificationStatus string + GeoreferencedBy string + GeoreferencedDate string + HigherGeography string + HigherGeographyID string + Island string + IslandGroup string + Locality string + LocationAccordingTo string + LocationID string + LocationRemarks string + MaximumDepthInMeters string + MaximumDistanceAboveSurfaceInMeters string + MaximumElevationInMeters string + MinimumDepthInMeters string + MinimumDistanceAboveSurfaceInMeters string + MinimumElevationInMeters string + Municipality string + PointRadiusSpatialFit string + StateProvince string + VerbatimCoordinateSystem string + VerbatimCoordinates string + VerbatimDepth string + VerbatimElevation string + VerbatimLatitude string + VerbatimLocality string + VerbatimLongitude string + VerbatimSRS string + WaterBody string + +=head3 DarwinCore Event Struct + + Field Name Writable + ---------- -------- + Day integer + EarliestDate date + EndDayOfYear integer + EventDate date + EventID string + EventRemarks lang-alt + EventTime date + FieldNotes string + FieldNumber string + Habitat string + LatestDate date + Month integer + ParentEventID string + SampleSizeUnit string + SampleSizeValue string + SamplingEffort string + SamplingProtocol string + StartDayOfYear integer + VerbatimEventDate string + Year integer + +=head3 DarwinCore MaterialSample Struct + + Field Name Writable + ---------- -------- + MaterialSampleID string + +=head3 DarwinCore GeologicalContext Struct + + Field Name Writable + ---------- -------- + Bed string + EarliestAgeOrLowestStage string + EarliestEonOrLowestEonothem string + EarliestEpochOrLowestSeries string + EarliestEraOrLowestErathem string + EarliestPeriodOrLowestSystem string + Formation string + GeologicalContextID string + Group string + HighestBiostratigraphicZone string + LatestAgeOrHighestStage string + LatestEonOrHighestEonothem string + LatestEpochOrHighestSeries string + LatestEraOrHighestErathem string + LatestPeriodOrHighestSystem string + LithostratigraphicTerms string + LowestBiostratigraphicZone string + Member string + +=head3 DarwinCore Identification Struct + + Field Name Writable + ---------- -------- + DateIdentified date + IdentificationID string + IdentificationQualifier string + IdentificationReferences string + IdentificationRemarks string + IdentificationVerificationStatus string + IdentifiedBy string + TypeStatus string + +=head3 DarwinCore MeasurementOrFact Struct + + Field Name Writable + ---------- -------- + MeasurementAccuracy string + MeasurementDeterminedBy string + MeasurementDeterminedDate date + MeasurementID string + MeasurementMethod string + MeasurementRemarks string + MeasurementType string + MeasurementUnit string + MeasurementValue string + +=head3 DarwinCore Occurrence Struct + + Field Name Writable + ---------- -------- + AssociatedMedia string + AssociatedOccurrences string + AssociatedReferences string + AssociatedSequences string + AssociatedTaxa string + Behavior string + CatalogNumber string + Disposition string + EstablishmentMeans string + IndividualCount string + IndividualID string + LifeStage string + OccurrenceDetails string + OccurrenceID string + OccurrenceRemarks string + OccurrenceStatus string + OrganismQuantity string + OrganismQuantityType string + OtherCatalogNumbers string + Preparations string + PreviousIdentifications string + RecordNumber string + RecordedBy string + ReproductiveCondition string + Sex string + +=head3 DarwinCore Organism Struct + + Field Name Writable + ---------- -------- + AssociatedOccurrences string + AssociatedOrganisms string + OrganismID string + OrganismName string + OrganismRemarks string + OrganismScope string + PreviousIdentifications string + +=head3 DarwinCore Record Struct + + Field Name Writable + ---------- -------- + BasisOfRecord string + CollectionCode string + CollectionID string + DataGeneralizations string + DatasetID string + DatasetName string + DynamicProperties string + InformationWithheld string + InstitutionCode string + InstitutionID string + OwnerInstitutionCode string + +=head3 DarwinCore ResourceRelationship Struct + + Field Name Writable + ---------- -------- + RelatedResourceID string + RelationshipAccordingTo string + RelationshipEstablishedDate date + RelationshipOfResource string + RelationshipRemarks string + ResourceID string + ResourceRelationshipID string + +=head3 DarwinCore Taxon Struct + + Field Name Writable + ---------- -------- + AcceptedNameUsage string + AcceptedNameUsageID string + Class string + Family string + Genus string + HigherClassification string + InfraspecificEpithet string + Kingdom string + NameAccordingTo string + NameAccordingToID string + NamePublishedIn string + NamePublishedInID string + NamePublishedInYear string + NomenclaturalCode string + NomenclaturalStatus string + Order string + OriginalNameUsage string + OriginalNameUsageID string + ParentNameUsage string + ParentNameUsageID string + Phylum string + ScientificName string + ScientificNameAuthorship string + ScientificNameID string + SpecificEpithet string + Subgenus string + TaxonConceptID string + TaxonID string + TaxonRank string + TaxonRemarks string + TaxonomicStatus string + VerbatimTaxonRank string + VernacularName lang-alt + +=head2 FotoStation Tags + +The following tables define information found in the FotoWare FotoStation +trailer. + + Tag ID Tag Name Writable + ------ -------- -------- + 0x0001 IPTC IPTC + 0x0002 SoftEdit FotoStation SoftEdit + 0x0003 ThumbnailImage yes + 0x0004 PreviewImage yes + +=head3 FotoStation SoftEdit Tags + + Index4 Tag Name Writable + ------ -------- -------- + 0 OriginalImageWidth int32s + 1 OriginalImageHeight int32s + 2 ColorPlanes int32s + 3 XYResolution int32s + 4 Rotation int32s + 6 CropLeft int32s + 7 CropTop int32s + 8 CropRight int32s + 9 CropBottom int32s + 11 CropRotation int32s + +=head2 PhotoMechanic Tags + +The Photo Mechanic trailer contains data in an IPTC-format structure, with +soft edit information stored under record number 2. + + Record Tag Name Writable + ------ -------- -------- + 2 SoftEdit PhotoMechanic SoftEdit + +=head3 PhotoMechanic SoftEdit Tags + + Tag ID Tag Name Writable + ------ -------- -------- + 209 RawCropLeft int32s + 210 RawCropTop int32s + 211 RawCropRight int32s + 212 RawCropBottom int32s + 213 ConstrainedCropWidth int32s + 214 ConstrainedCropHeight int32s + 215 FrameNum int32s + 216 Rotation int32s + 217 CropLeft int32s + 218 CropTop int32s + 219 CropRight int32s + 220 CropBottom int32s + 221 Tagged int32s + 222 ColorClass int32s + 223 Rating int32s + 236 PreviewCropLeft int32s + 237 PreviewCropTop int32s + 238 PreviewCropRight int32s + 239 PreviewCropBottom int32s + +=head3 PhotoMechanic XMP Tags + +Below is a list of the observed PhotoMechanic XMP tags. The actual +namespace prefix is "photomechanic" but ExifTool shortens this in +the family 1 group name. + +These tags belong to the ExifTool XMP-photomech family 1 group. + + Tag Name Writable + -------- -------- + ColorClass integer + CountryCode string/ + EditStatus string + PMVersion string + Prefs string + Tagged boolean + TimeCreated string/ + +=head2 Microsoft Tags + +=head3 Microsoft XMP Tags + +Microsoft Photo 1.0 schema XMP tags. This is likely not a complete list, +but represents tags which have been observed in sample images. The actual +namespace prefix is "MicrosoftPhoto", but ExifTool shortens this in the +family 1 group name. + +These tags belong to the ExifTool XMP-microsoft family 1 group. + + Tag Name Writable + -------- -------- + CameraSerialNumber string + CreatorAppID string + CreatorOpenWithUIOptions string + DateAcquired date + FlashManufacturer string + FlashModel string + ItemSubType string + LastKeywordIPTC string+ + LastKeywordXMP string+ + LensManufacturer string + LensModel string/ + RatingPercent string + +=head3 Microsoft MP1 Tags + +Microsoft Photo 1.1 schema XMP tags which have been observed. + +These tags belong to the ExifTool XMP-MP1 family 1 group. + + Tag Name Writable + -------- -------- + Brightness string/ + CameraModelID string/ + Contrast string/ + ExposureCompensation string/ + PanoramicStitchCameraMotion string + PanoramicStitchMapType string + PanoramicStitchPhi0 real + PanoramicStitchPhi1 real + PanoramicStitchTheta0 real + PanoramicStitchTheta1 real + PipelineVersion string + StreamType string + WhiteBalance0 real + WhiteBalance1 real + WhiteBalance2 real + +=head3 Microsoft MP Tags + +Microsoft Photo 1.2 schema XMP tags which have been observed. + +These tags belong to the ExifTool XMP-MP family 1 group. + + Tag Name Writable + -------- -------- + RegionInfoDateRegionsValid date_ + RegionInfoMP Microsoft RegionInfo Struct + RegionInfoRegions Microsoft Regions Struct_+ + RegionPersonDisplayName string_+ + RegionPersonEmailDigest string_+ + RegionPersonLiveIdCID string_+ + RegionPersonSourceID string_+ + RegionRectangle string_+ + +=head3 Microsoft RegionInfo Struct + + Field Name Writable + ---------- -------- + DateRegionsValid date + Regions Microsoft Regions Struct+ + +=head3 Microsoft Regions Struct + +Note that PersonLiveIdCID element is called PersonLiveCID according to the +Microsoft specification, but in practice their software actually writes +PersonLiveIdCID, so ExifTool uses this too. + + Field Name Writable + ---------- -------- + PersonDisplayName string + PersonEmailDigest string + PersonLiveIdCID string + PersonSourceID string + Rectangle string + +=head3 Microsoft Stitch Tags + +Information found in the Microsoft custom EXIF tag 0x4748, as written by +Windows Live Photo Gallery. + + Index4 Tag Name Writable + ------ -------- -------- + 0 PanoramicStitchVersion int32u + 1 PanoramicStitchCameraMotion int32u + 2 PanoramicStitchMapType int32u + 3 PanoramicStitchTheta0 float + 4 PanoramicStitchTheta1 float + 5 PanoramicStitchPhi0 float + 6 PanoramicStitchPhi1 float + +=head3 Microsoft Xtra Tags + +Tags extracted from the Microsoft "Xtra" atom of QuickTime videos. Tag ID's +are not shown because some are unruly GUID's. + + Tag Name Writable + -------- -------- + Abstract no + AccountName no + AcquisitionTime no + AcquisitionTimeDay no + AcquisitionTimeMonth no + AcquisitionTimeYear no + AcquisitionTimeYearMonth no + AcquisitionTimeYearMonthDay no + AlbumArtist no + AlbumArtist no + AlbumArtistSortOrder no + AlbumCoverURL no + AlbumID no + AlbumIDAlbumArtist no + AlbumTitle no + AlbumTitle no + AlbumTitleSortOrder no + AlternateSourceURL no + Anniversary no + Artist no + AssistantsName no + AssistantsPhone no + Attachments no + Attributes no + AudioBitrate no + AudioFormat no + AudioSampleRate no + AudioSampleSize no + Author no + Author no + AuthorSortOrder no + AutoSummary no + AverageLevel no + BccAddresses no + BccNames no + Beats-per-minute no + BeatsPerMinute no + BillingInformation no + Birthday no + BitDepth no + Bitrate no + Bitrate no + BroadcastDate no + BusinessAddress no + BusinessCity no + BusinessCountry-Region no + BusinessFax no + BusinessHomePage no + BusinessPOBox no + BusinessPhone no + BusinessPostalCode no + BusinessStateOrProvince no + BusinessStreet no + BuyNow no + BuyTickets no + CDTrackEnabled no + CallLetters no + CallbackNumber no + CameraMaker no + CameraManufacturer no + CameraModel no + CameraModel no + CarPhone no + Category no + Category no + CcAddresses no + CcNames no + CellPhone no + ChannelNumber no + Channels no + Channels no + ChapterNum no + Children no + City no + ClientID no + ClosedCaptioning no + Color no + Comment no + Comments no + Company no + CompanyMainPhone no + Complete no + Composer no + Composers no + Computer no + Conductor no + Conductors no + ContactNames no + ContentDistributor no + ContentDistributorDuration no + ContentDistributorType no + ContentGroupDescription no + ContentType no + Contributors no + ConversationID no + Copyright no + Copyright no + Count no + Country-Region no + Creator no + CurrentBitrate no + DLNAServerUDN no + DLNASourceURI no + DRMIndividualizedVersion no + DRMKeyID no + DTCPIPHost no + DTCPIPPort no + DVDID no + DataRate no + Date no + DateAccessed no + DateAcquired no + DateArchived no + DateCompleted no + DateCreated no + DateImported no + DateLastSaved no + DateModified no + DatePictureTaken no + DateReceived no + DateReleased no + DateSent no + DateVisited no + Department no + Description no + Description no + Description no + Dimensions no + Director no + Directors no + DisplayArtist no + Division no + DocumentID no + DueDate no + Duration no + Duration no + Duration no + E-mail2 no + E-mail3 no + E-mailAddress no + E-mailDisplayName no + E-mailList no + EncodedBy no + EncodingTime no + EndDate no + EntryType no + EpisodeName no + Event no + Event no + ExifVersion no + ExposureBias no + ExposureProgram no + ExposureTime no + F-stop no + FileAs no + FileCount no + FileSize no + FileType no + FileVersion no + FirstName no + FlagColor no + FlagStatus no + FlashMode no + FocalLength no + FocalLength35mm no + Folder no + FolderName no + FolderPath no + FormatTag no + FourCC no + FrameHeight no + FrameRate no + FrameRate no + FrameWidth no + Free-busyStatus no + Frequency no + FromAddresses no + FromNames no + FullName no + Gender no + Genre no + Genre no + GenreID no + GivenName no + HasAttachments no + HasFlag no + Hobbies no + HomeAddress no + HomeCity no + HomeCountry-Region no + HomeFax no + HomePOBox no + HomePhone no + HomePostalCode no + HomeStateOrProvince no + HomeStreet no + HorizontalResolution no + IMAddresses no + ISOSpeed no + Importance no + Incomplete no + InitialKey no + InitialKey no + Initials no + IsAttachment no + IsCompleted no + IsDeleted no + IsNetworkFeed no + IsOnline no + IsProtected no + IsRecurring no + IsVBR no + JobTitle no + Keywords no + Kinds no + Label no + Language no + Language no + LastName no + LastPrinted no + LeadPerformer no + LegalTrademarks no + LensMaker no + LensModel no + LibraryID no + LibraryName no + LightSource no + LinkStatus no + LinkTarget no + Location no + Location no + Lyrics no + MCDI no + MailingAddress no + MaxAperture no + MediaClassPrimaryID no + MediaClassSecondaryID no + MediaContentTypes no + MediaCreated no + MediaOriginalBroadcastDateTime no + MediaOriginalChannel no + MediaStationName no + MediaType no + MeteringMode no + MiddleName no + Mileage no + ModifiedBy no + Mood no + Mood no + MoreInfo no + Name no + Nickname no + OfficeLocation no + OfflineAvailability no + OfflineStatus no + OptionalAttendeeAddresses no + OptionalAttendees no + OrganizerAddress no + OrganizerName no + Orientation no + OriginalAlbumTitle no + OriginalArtist no + OriginalLyricist no + OtherAddress no + OtherCity no + OtherCountry-Region no + OtherPOBox no + OtherPostalCode no + OtherStateOrProvince no + OtherStreet no + Owner no + POBox no + Pager no + Pages no + ParentalRating no + ParentalRating no + ParentalRatingReason no + PartOfSet no + PartOfSet no + PartOfSet no + Participants no + Path no + PeakValue no + PerceivedType no + Period no + Period no + PersonalTitle no + PixelAspectRatioX no + PixelAspectRatioY no + PlaylistIndex no + PostalCode no + PrimaryE-mail no + PrimaryPhone no + Priority no + Producer no + Producers no + ProductName no + ProductVersion no + Profession no + ProgramDescription no + ProgramMode no + ProgramName no + Project no + Protected no + ProtectionType no + Provider no + Provider no + ProviderLogoURL no + ProviderRating no + ProviderStyle no + ProviderURL no + Publisher no + Publisher no + RadioBand no + RadioFormat no + Rating no + RatingOrg no + ReadStatus no + RecordingTime no + RecordingTime no + RecordingTimeDay no + RecordingTimeMonth no + RecordingTimeYear no + RecordingTimeYearMonth no + RecordingTimeYearMonthDay no + ReleaseDate no + ReleaseDateDay no + ReleaseDateMonth no + ReleaseDateYear no + ReleaseDateYearMonth no + ReleaseDateYearMonthDay no + ReminderTime no + RequestState no + RequiredAttendeeAddresses no + RequiredAttendees no + Rerun no + Resources no + SAP no + Saturation no + SearchRanking no + SenderAddress no + SenderName no + Sensitivity no + ShadowFilePath no + Shared no + SharedUserRating no + SharedWith no + Size no + Slides no + Source no + SourceURL no + SpaceFree no + SpaceUsed no + Spouse no + StartDate no + StateOrProvince no + StationCallSign no + StationName no + Status no + Status no + Store no + Street no + Subject no + Subject no + SubjectDistance no + SubscriptionContentID no + Subtitle no + Subtitle no + SubtitleDescription no + Suffix no + Summary no + Sync01 no + Sync02 no + Sync03 no + Sync04 no + Sync05 no + Sync06 no + Sync07 no + Sync08 no + Sync09 no + Sync10 no + Sync11 no + Sync12 no + Sync13 no + Sync14 no + Sync15 no + Sync16 no + SyncOnly no + SyncState no + TTY-TTDPhone no + TaskOwner no + Telex no + Temporary no + Title no + Title no + TitleNum no + TitleSortOrder no + ToAddresses no + ToDoTitle no + ToNames no + TotalBitrate no + TotalDuration no + TotalEditingTime no + TotalFileSize no + TotalSize no + TrackNumber no + TrackNumber no + TrackingID no + Type no + Type no + URL no + UniqueFileIdentifier no + Untitled0 no + Untitled1 no + Untitled2 no + UserCustom1 no + UserCustom2 no + UserEffectiveRating no + UserLastPlayedTime no + UserPlayCount no + UserPlaycountAfternoon no + UserPlaycountEvening no + UserPlaycountMorning no + UserPlaycountNight no + UserPlaycountWeekday no + UserPlaycountWeekend no + UserRating no + UserServiceRating no + UserWebURL no + VerticalResolution no + VideoBitrate no + VideoCompression no + VideoFormat no + VideoFrameRate no + VideoHeight no + VideoWidth no + WMCollectionGroupID no + WMCollectionID no + WMContentID no + WMShadowFileSourceDRMType no + WMShadowFileSourceFileType no + Webpage no + WhiteBalance no + WindowsFileName no + WordCount no + Writer no + Writers no + Year no + Year no + +=head2 GIMP Tags + +The GNU Image Manipulation Program (GIMP) writes these tags in its native +XCF (eXperimental Computing Facilty) images. + + Tag ID Tag Name Writable + ------ -------- -------- + 'header' Header GIMP Header + 0x0011 Compression no + 0x0013 Resolution GIMP Resolution + 0x0014 Tattoo no + 0x0015 Parasites GIMP Parasite + 0x0016 Units no + +=head3 GIMP Header Tags + + Index1 Tag Name Writable + ------ -------- -------- + 9 XCFVersion no + 14 ImageWidth no + 18 ImageHeight no + 22 ColorMode no + +=head3 GIMP Resolution Tags + + Index4 Tag Name Writable + ------ -------- -------- + 0 XResolution no + 1 YResolution no + +=head3 GIMP Parasite Tags + + Tag ID Tag Name Writable + ------ -------- -------- + 'exif-data' ExifData EXIF + 'gimp-comment' Comment no + 'gimp-image-metadata' XML XMP XML + 'gimp-metadata' XMP XMP + 'icc-profile' ICC_Profile ICC_Profile + 'icc-profile-name' ICCProfileName no + 'iptc-data' IPTCData IPTC + 'jpeg-exif-data' JPEGExifData EXIF + +=head2 MIE Tags + +MIE is a flexible format which may be used as a stand-alone meta information +format, for encapsulation of other files and information, or as a trailer +appended to other file formats. The tables below represent currently +defined MIE tags, however ExifTool will also extract any other information +present in a MIE file. + +When writing MIE information, some special features are supported: + +1) String values may be written as ASCII (ISO 8859-1) or UTF-8. ExifTool +automatically detects the presence of wide characters and treats the string +appropriately. Internally, UTF-8 text may be converted to UTF-16 or UTF-32 +and stored in this format in the file if it is more compact. + +2) All MIE string-value tags support localized text. Localized values are +written by adding a language/country code to the tag name in the form +C<TAG-xx_YY>, where C<TAG> is the tag name, C<xx> is a 2-character lower +case ISO 639-1 language code, and C<YY> is a 2-character upper case ISO +3166-1 alpha 2 country code (eg. C<Title-en_US>). But as usual, the user +interface is case-insensitive, and ExifTool will write the correct case to +the file. + +3) Some numerical MIE tags allow units of measurement to be specified. For +these tags, units may be added in brackets immediately following the value +(eg. C<55(mi/h)>). If no units are specified, the default units are +written. + +4) ExifTool writes compressed metadata to MIE files if the Compress (-z) +option is used and Compress::Zlib is available. + +See L<http://owl.phy.queensu.ca/~phil/exiftool/MIE1.1-20070121.pdf> for the +official MIE specification. + + Tag ID Tag Name Writable + ------ -------- -------- + '0Type' SubfileType string + '0Vers' MIEVersion string + '1Directory' SubfileDirectory string + '1Name' SubfileName string + '2MIME' SubfileMIMEType string + 'Meta' Meta MIE Meta + 'data' SubfileData undef + 'rsrc' SubfileResource undef + 'zmd5' MD5Digest string + 'zmie' TrailerSignature undef + +=head3 MIE Meta Tags + + Tag ID Tag Name Writable + ------ -------- -------- + 'Audio' Audio MIE Audio + 'Camera' Camera MIE Camera + 'Document' Document MIE Doc + 'EXIF' EXIF EXIF + 'Geo' Geo MIE Geo + 'ICCProfile' ICC_Profile ICC_Profile + 'ID3' ID3 ID3 + 'IPTC' IPTC IPTC + 'Image' Image MIE Image + 'MakerNotes' MakerNotes MIE MakerNotes + 'Preview' Preview MIE Preview + 'Thumbnail' Thumbnail MIE Thumbnail + 'Video' Video MIE Video + 'XMP' XMP XMP + +=head3 MIE Audio Tags + +For the Audio group (and any other group containing a 'data' element), tags +refer to the contained data if present, otherwise they refer to the main +SubfileData. The C<0Type> and C<1Name> elements should exist only if C<data> +is present. + + Tag ID Tag Name Writable + ------ -------- -------- + '0Type' RelatedAudioFileType string + '1Name' RelatedAudioFileName string + 'Channels' Channels int8u + 'Compression' AudioCompression string + 'Duration' Duration rational64u~ + 'SampleBits' SampleBits int16u + 'SampleRate' SampleRate int32u + 'data' RelatedAudioFile undef + +=head3 MIE Camera Tags + + Tag ID Tag Name Writable + ------ -------- -------- + 'Brightness' Brightness int8s + 'ColorBalance' ColorBalance rational64u[3] + 'ColorTemperature' ColorTemperature int32u + 'Contrast' Contrast int8s + 'DigitalZoom' DigitalZoom rational64u + 'ExposureComp' ExposureCompensation rational64s + 'ExposureMode' ExposureMode string + 'ExposureTime' ExposureTime rational64u + 'FirmwareVersion' FirmwareVersion string + 'Flash' Flash MIE Flash + 'FocusMode' FocusMode string + 'ISO' ISO int16u + 'ISOSetting' ISOSetting int16u + 'ImageNumber' ImageNumber int32u + 'ImageQuality' ImageQuality string + 'ImageStabilization' ImageStabilization int8u + 'Lens' Lens MIE Lens + 'Make' Make string + 'MeasuredEV' MeasuredEV rational64s + 'Model' Model string + 'Orientation' Orientation MIE Orient + 'OwnerName' OwnerName string + 'Saturation' Saturation int8s + 'SensorSize' SensorSize rational64u[2] + 'SerialNumber' SerialNumber string + 'Sharpness' Sharpness int8s + 'ShootingMode' ShootingMode string + +=head3 MIE Flash Tags + + Tag ID Tag Name Writable + ------ -------- -------- + 'ExposureComp' FlashExposureComp rational64s + 'Fired' FlashFired int8u + 'GuideNumber' FlashGuideNumber string + 'Make' FlashMake string + 'Mode' FlashMode string + 'Model' FlashModel string + 'SerialNumber' FlashSerialNumber string + 'Type' FlashType string + +=head3 MIE Lens Tags + +All recorded lens parameters (focal length, aperture, etc) include the +effects of the extender if present. + + Tag ID Tag Name Writable + ------ -------- -------- + 'Extender' Extender MIE Extender + 'FNumber' FNumber rational64u + 'FocalLength' FocalLength rational64u + 'FocusDistance' FocusDistance rational64u + 'Make' LensMake string + 'MaxAperture' MaxAperture rational64u + 'MaxApertureAtMaxFocal' MaxApertureAtMaxFocal rational64u + 'MaxFocalLength' MaxFocalLength rational64u + 'MinAperture' MinAperture rational64u + 'MinFocalLength' MinFocalLength rational64u + 'Model' LensModel string + 'OpticalZoom' OpticalZoom rational64u + 'SerialNumber' LensSerialNumber string + +=head3 MIE Extender Tags + + Tag ID Tag Name Writable + ------ -------- -------- + 'Magnification' ExtenderMagnification rational64s + 'Make' ExtenderMake string + 'Model' ExtenderModel string + 'SerialNumber' ExtenderSerialNumber string + +=head3 MIE Orient Tags + +These tags describe the camera orientation. + + Tag ID Tag Name Writable + ------ -------- -------- + 'Azimuth' Azimuth rational64s + 'Declination' Declination rational64s + 'Elevation' Elevation rational64s + 'RightAscension' RightAscension rational64s + 'Rotation' Rotation rational64s + +=head3 MIE Doc Tags + +Information describing the main document, image or file. + + Tag ID Tag Name Writable + ------ -------- -------- + 'Author' Author string + 'Comment' Comment string + 'Contributors' Contributors string+ + 'Copyright' Copyright string + 'CreateDate' CreateDate string + 'EMail' Email string + 'Keywords' Keywords string+ + 'ModifyDate' ModifyDate string + 'OriginalDate' DateTimeOriginal string + 'Phone' PhoneNumber string + 'References' References string+ + 'Software' Software string + 'Title' Title string + 'URL' URL string + +=head3 MIE Geo Tags + +Information related to geographic location. + + Tag ID Tag Name Writable + ------ -------- -------- + 'Address' Address string + 'City' City string + 'Country' Country string + 'GPS' GPS MIE GPS + 'PostalCode' PostalCode string + 'State' State string + 'UTM' UTM MIE UTM + +=head3 MIE GPS Tags + + Tag ID Tag Name Writable + ------ -------- -------- + 'Altitude' GPSAltitude rational64s + 'Bearing' GPSDestBearing rational64s + 'DateTime' GPSDateTime string + 'Datum' GPSMapDatum string + 'Differential' GPSDifferential int8u + 'Distance' GPSDestDistance rational64s + 'Heading' GPSTrack rational64s + 'Latitude' GPSLatitude rational64s[n] + 'Longitude' GPSLongitude rational64s[n] + 'MeasureMode' GPSMeasureMode int8u + 'Satellites' GPSSatellites string + 'Speed' GPSSpeed rational64s + +=head3 MIE UTM Tags + + Tag ID Tag Name Writable + ------ -------- -------- + 'Datum' UTMMapDatum string + 'Easting' UTMEasting string + 'Northing' UTMNorthing string + 'Zone' UTMZone int8s + +=head3 MIE Image Tags + + Tag ID Tag Name Writable + ------ -------- -------- + '0Type' FullSizeImageType string + '1Name' FullSizeImageName string + 'BitDepth' BitDepth int16u + 'ColorSpace' ColorSpace string + 'Components' ComponentsConfiguration string + 'Compression' CompressionRatio rational32u + 'ImageSize' ImageSize int16u[n] + 'Resolution' Resolution rational64u[n] + 'data' FullSizeImage undef + +=head3 MIE MakerNotes Tags + +MIE maker notes are contained within separate groups for each manufacturer +to avoid name conflicts. + + Tag ID Tag Name Writable + ------ -------- -------- + 'Canon' Canon MIE Canon + 'Casio' Casio MIE Unknown + 'FujiFilm' FujiFilm MIE Unknown + 'Kodak' Kodak MIE Unknown + 'KonicaMinolta' KonicaMinolta MIE Unknown + 'Nikon' Nikon MIE Unknown + 'Olympus' Olympus MIE Unknown + 'Panasonic' Panasonic MIE Unknown + 'Pentax' Pentax MIE Unknown + 'Ricoh' Ricoh MIE Unknown + 'Sigma' Sigma MIE Unknown + 'Sony' Sony MIE Unknown + +=head3 MIE Canon Tags + + Tag ID Tag Name Writable + ------ -------- -------- + 'VRD' CanonVRD CanonVRD + +=head3 MIE Unknown Tags + + Tag ID Tag Name Writable + ------ -------- -------- + [no tags known] + +=head3 MIE Preview Tags + + Tag ID Tag Name Writable + ------ -------- -------- + '0Type' PreviewImageType string + '1Name' PreviewImageName string + 'ImageSize' PreviewImageSize int16u[n] + 'data' PreviewImage undef + +=head3 MIE Thumbnail Tags + + Tag ID Tag Name Writable + ------ -------- -------- + '0Type' ThumbnailImageType string + '1Name' ThumbnailImageName string + 'ImageSize' ThumbnailImageSize int16u[n] + 'data' ThumbnailImage undef + +=head3 MIE Video Tags + + Tag ID Tag Name Writable + ------ -------- -------- + '0Type' RelatedVideoFileType string + '1Name' RelatedVideoFileName string + 'Codec' Codec string + 'Duration' Duration rational64u~ + 'data' RelatedVideoFile undef + +=head2 Jpeg2000 Tags + +The tags below are extracted from JPEG 2000 images, however ExifTool +currently writes only EXIF, IPTC and XMP tags in these images. + + Tag ID Tag Name Writable + ------ -------- -------- + 'asoc' Association no + 'bfil' BinaryFilter no + 'bpcc' BitsPerComponent no + 'cdef' ComponentDefinition no + 'cgrp' ColorGroup no + 'chck' DigitalSignature no + 'cmap' ComponentMapping no + 'colr' ColorSpecification Jpeg2000 ColorSpec + 'comp' Composition no + 'copt' CompositionOptions no + 'cref' Cross-Reference no + 'creg' CodestreamRegistration no + 'drep' DesiredReproductions no + 'dtbl' DataReference no + 'flst' FragmentList no + 'free' Free no + 'ftbl' FragmentTable no + 'ftyp' FileType Jpeg2000 FileType + 'gtso' GraphicsTechnologyStandardOutput no + 'ihdr' ImageHeader Jpeg2000 ImageHeader + 'inst' InstructionSet no + 'jP ' JP2Signature no + 'jp2c' ContiguousCodestream no + 'jp2h' JP2Header Jpeg2000 + 'jp2i' IntellectualProperty XMP + 'jpch' CodestreamHeader Jpeg2000 + 'jplh' CompositingLayerHeader Jpeg2000 + 'lbl ' Label no + 'mdat' MediaData no + 'mp7b' MPEG7Binary no + 'nlst' NumberList no + 'opct' Opacity no + 'pclr' Palette no + 'prfl' Profile no + 'res ' Resolution Jpeg2000 + 'resc' CaptureResolution Jpeg2000 CaptureResolution + 'resd' DisplayResolution Jpeg2000 DisplayResolution + 'roid' ROIDescription no + 'rreq' ReaderRequirements no + 'uinf' UUIDInfo Jpeg2000 + 'ulst' UUIDList no + 'url ' URL no + 'uuid' UUID-EXIF EXIF + UUID-EXIF2 EXIF + UUID-EXIF_bad EXIF + UUID-IPTC IPTC + UUID-IPTC2 IPTC + UUID-XMP XMP + UUID-GeoJP2 EXIF + UUID-Photoshop Photoshop + UUID-Unknown no + 'xml ' XML XMP + +=head3 Jpeg2000 ColorSpec Tags + + Index1 Tag Name Writable + ------ -------- -------- + 0 ColorSpecMethod no + 1 ColorSpecPrecedence no + 2 ColorSpecApproximation no + 3 ICC_Profile ICC_Profile + ColorSpace no + ColorSpecData no + +=head3 Jpeg2000 FileType Tags + + Index4 Tag Name Writable + ------ -------- -------- + 0 MajorBrand no + 1 MinorVersion no + 2 CompatibleBrands no + +=head3 Jpeg2000 ImageHeader Tags + + Index1 Tag Name Writable + ------ -------- -------- + 0 ImageHeight no + 4 ImageWidth no + 8 NumberOfComponents no + 10 BitsPerComponent no + 11 Compression no + +=head3 Jpeg2000 CaptureResolution Tags + + Index1 Tag Name Writable + ------ -------- -------- + 0 CaptureYResolution no + 4 CaptureXResolution no + 8 CaptureYResolutionUnit no + 9 CaptureXResolutionUnit no + +=head3 Jpeg2000 DisplayResolution Tags + + Index1 Tag Name Writable + ------ -------- -------- + 0 DisplayYResolution no + 4 DisplayXResolution no + 8 DisplayYResolutionUnit no + 9 DisplayXResolutionUnit no + +=head2 GIF Tags + +This table lists information extracted from GIF images. See +L<http://www.w3.org/Graphics/GIF/spec-gif89a.txt> for the official GIF89a +specification. + + Tag Name Writable + -------- -------- + Comment yes + Duration no + Extensions GIF Extensions + FrameCount no + GIFVersion no + ScreenDescriptor GIF Screen + Text no + +=head3 GIF Extensions Tags + +Tags extracted from GIF89a application extensions. + + Tag ID Tag Name Writable + ------ -------- -------- + 'ICCRGBG1/012' ICC_Profile ICC_Profile + 'MIDICTRL/Jon' MIDIControl GIF MIDIControl + 'MIDISONG/Dm7' MIDISong no + 'NETSCAPE/2.0' Animation GIF Animation + 'XMP Data/XMP' XMP XMP + +=head3 GIF MIDIControl Tags + +Information extracted from the MIDI control block extension. + + Index1 Tag Name Writable + ------ -------- -------- + 0 MIDIControlVersion no + 1 SequenceNumber no + 2 MelodicPolyphony no + 3 PercussivePolyphony no + 4 ChannelUsage no + 6 DelayTime no + +=head3 GIF Animation Tags + +Information extracted from the "NETSCAPE2.0" animation extension. + + Index1 Tag Name Writable + ------ -------- -------- + 1 AnimationIterations no + +=head3 GIF Screen Tags + +Information extracted from the GIF logical screen descriptor. + + Index1 Tag Name Writable + ------ -------- -------- + 0 ImageWidth no + 2 ImageHeight no + 4.1 HasColorMap no + 4.2 ColorResolutionDepth no + 4.3 BitsPerPixel no + 5 BackgroundColor no + +=head2 BMP Tags + +There really isn't much meta information in a BMP file as such, just a bit +of image related information. + + Index1 Tag Name Writable + ------ -------- -------- + 0 BMPVersion no + 4 ImageWidth no + 8 ImageHeight no + 12 Planes no + 14 BitDepth no + 16 Compression no + 20 ImageLength no + 24 PixelsPerMeterX no + 28 PixelsPerMeterY no + 32 NumColors no + 36 NumImportantColors no + 40 RedMask no + 44 GreenMask no + 48 BlueMask no + 52 AlphaMask no + 56 ColorSpace no + 60 RedEndpoint no + 72 GreenEndpoint no + 84 BlueEndpoint no + 96 GammaRed no + 100 GammaGreen no + 104 GammaBlue no + 108 RenderingIntent no + 112 ProfileDataOffset no + 116 ProfileSize no + +=head3 BMP OS2 Tags + +Information extracted from OS/2-format BMP images. + + Index1 Tag Name Writable + ------ -------- -------- + 0 BMPVersion no + 4 ImageWidth no + 6 ImageHeight no + 8 Planes no + 10 BitDepth no + +=head3 BMP Extra Tags + +Extra information extracted from some BMP images. + + Tag Name Writable + -------- -------- + EmbeddedJPG no + EmbeddedPNG no + ICC_Profile ICC_Profile + LinkedProfileName no + +=head2 BPG Tags + +The information listed below is extracted from BPG (Better Portable +Graphics) images. See L<http://bellard.org/bpg/> for the specification. + + Index1 Tag Name Writable + ------ -------- -------- + 4 PixelFormat no + 4.1 Alpha no + 4.2 BitDepth no + 4.3 ColorSpace no + 4.4 Flags no + 6 ImageWidth no + 7 ImageHeight no + 8 ImageLength no + +=head3 BPG Extensions Tags + + Tag ID Tag Name Writable + ------ -------- -------- + 0x0001 EXIF EXIF + 0x0002 ICC_Profile ICC_Profile + 0x0003 XMP XMP + 0x0004 ThumbnailBPG no + 0x0005 AnimationControl? no + +=head2 PICT Tags + +The PICT format contains no true meta information, except for the possible +exception of the LongComment opcode. By default, only ImageWidth, +ImageHeight and X/YResolution are extracted from a PICT image. Tags in the +following table represent image opcodes. Extraction of these tags is +experimental, and is only enabled with the Verbose or Unknown options. + + Tag ID Tag Name Writable + ------ -------- -------- + 0x0000 Nop no + 0x0001 ClipRgn no + 0x0002 BkPat no + 0x0003 TxFont no + 0x0004 TxFace no + 0x0005 TxMode no + 0x0006 SpExtra no + 0x0007 PnSize no + 0x0008 PnMode no + 0x0009 PnPat no + 0x000a FillPat no + 0x000b OvSize no + 0x000c Origin no + 0x000d TxSize no + 0x000e FgColor no + 0x000f BkColor no + 0x0010 TxRatio no + 0x0011 VersionOp no + 0x0012 BkPixPat no + 0x0013 PnPixPat no + 0x0014 FillPixPat no + 0x0015 PnLocHFrac no + 0x0016 ChExtra no + 0x0017 Reserved no + 0x001a RGBFgCol no + 0x001b RGBBkCol no + 0x001c HiliteMode no + 0x001d HiliteColor no + 0x001e DefHilite no + 0x001f OpColor no + 0x0020 Line no + 0x0021 LineFrom no + 0x0022 ShortLine no + 0x0023 ShortLineFrom no + 0x0024 Reserved no + 0x0028 LongText no + 0x0029 DHText no + 0x002a DVText no + 0x002b DHDVText no + 0x002c FontName no + 0x002d LineJustify no + 0x002e GlyphState no + 0x002f Reserved no + 0x0030 FrameRect no + 0x0031 PaintRect no + 0x0032 EraseRect no + 0x0033 InvertRect no + 0x0034 FillRect no + 0x0035 Reserved no + 0x0038 FrameSameRect no + 0x0039 PaintSameRect no + 0x003a EraseSameRect no + 0x003b InvertSameRect no + 0x003c FillSameRect no + 0x003d Reserved no + 0x0040 FrameRRect no + 0x0041 PaintRRect no + 0x0042 EraseRRect no + 0x0043 InvertRRect no + 0x0044 FillRRect no + 0x0045 Reserved no + 0x0048 FrameSameRRect no + 0x0049 PaintSameRRect no + 0x004a EraseSameRRect no + 0x004b InvertSameRRect no + 0x004c FillSameRRect no + 0x004d Reserved no + 0x0050 FrameOval no + 0x0051 PaintOval no + 0x0052 EraseOval no + 0x0053 InvertOval no + 0x0054 FillOval no + 0x0055 Reserved no + 0x0058 FrameSameOval no + 0x0059 PaintSameOval no + 0x005a EraseSameOval no + 0x005b InvertSameOval no + 0x005c FillSameOval no + 0x005d Reserved no + 0x0060 FrameArc no + 0x0061 PaintArc no + 0x0062 EraseArc no + 0x0063 InvertArc no + 0x0064 FillArc no + 0x0065 Reserved no + 0x0068 FrameSameArc no + 0x0069 PaintSameArc no + 0x006a EraseSameArc no + 0x006b InvertSameArc no + 0x006c FillSameArc no + 0x006d Reserved no + 0x0070 FramePoly no + 0x0071 PaintPoly no + 0x0072 ErasePoly no + 0x0073 InvertPoly no + 0x0074 FillPoly no + 0x0075 Reserved no + 0x0078 FrameSamePoly no + 0x0079 PaintSamePoly no + 0x007a EraseSamePoly no + 0x007b InvertSamePoly no + 0x007c FillSamePoly no + 0x007d Reserved no + 0x0080 FrameRgn no + 0x0081 PaintRgn no + 0x0082 EraseRgn no + 0x0083 InvertRgn no + 0x0084 FillRgn no + 0x0085 Reserved no + 0x0088 FrameSameRgn no + 0x0089 PaintSameRgn no + 0x008a EraseSameRgn no + 0x008b InvertSameRgn no + 0x008c FillSameRgn no + 0x008d Reserved no + 0x0090 BitsRect no + 0x0091 BitsRgn no + 0x0092 Reserved no + 0x0098 PackBitsRect no + 0x0099 PackBitsRgn no + 0x009a DirectBitsRect no + 0x009b DirectBitsRgn no + 0x009c Reserved no + 0x009d Reserved no + 0x009e Reserved no + 0x009f Reserved no + 0x00a0 ShortComment no + 0x00a1 LongComment Photoshop + ICC_Profile + 0x00a2 Reserved no + 0x00b0 Reserved no + 0x00d0 Reserved no + 0x00ff OpEndPic no + 0x0100 Reserved no + 0x0200 Reserved no + 0x02ff Version no + 0x0300 Reserved no + 0x0bff Reserved no + 0x0c00 HeaderOp no + 0x0c01 Reserved no + 0x7f00 Reserved no + 0x8000 Reserved no + 0x8100 Reserved no + 0x8200 CompressedQuickTime no + 0x8201 UncompressedQuickTime no + 0xffff Reserved no + +=head2 PNG Tags + +Tags extracted from PNG images. See +L<http://www.libpng.org/pub/png/spec/1.2/> for the official PNG 1.2 +specification. + +According to the specification, a PNG file should end at the IEND chunk, +however ExifTool will preserve any data found after this when writing unless +it is specifically deleted with C<-Trailer:All=>. When reading, a minor +warning is issued if this trailer exists, and ExifTool will attempt to parse +this data as additional PNG chunks. + + Tag ID Tag Name Writable + ------ -------- -------- + 'IHDR' ImageHeader PNG ImageHeader + 'PLTE' Palette no + 'acTL' AnimationControl PNG AnimationControl + 'bKGD' BackgroundColor no + 'cHRM' PrimaryChromaticities PNG PrimaryChromaticities + 'dSIG' DigitalSignature no + 'eXIf' eXIf EXIF + 'fRAc' FractalParameters no + 'gAMA' Gamma no + 'gIFg' GIFGraphicControlExtension no + 'gIFt' GIFPlainTextExtension no + 'gIFx' GIFApplicationExtension no + 'hIST' PaletteHistogram no + 'iCCP' ICC_Profile ICC_Profile + 'iCCP-name' ProfileName no + 'iTXt' InternationalText PNG TextualData + 'oFFs' ImageOffset no + 'pCAL' PixelCalibration no + 'pHYs' PhysicalPixel PNG PhysicalPixel + 'sBIT' SignificantBits no + 'sCAL' SubjectScale PNG SubjectScale + 'sPLT' SuggestedPalette no + 'sRGB' SRGBRendering no + 'sTER' StereoImage PNG StereoImage + 'tEXt' TextualData PNG TextualData + 'tIME' ModifyDate yes + 'tRNS' Transparency no + 'tXMP' XMP XMP + 'vpAg' VirtualPage PNG VirtualPage + 'zTXt' CompressedText PNG TextualData + 'zxIf' zxIf EXIF + +=head3 PNG ImageHeader Tags + + Index1 Tag Name Writable + ------ -------- -------- + 0 ImageWidth no + 4 ImageHeight no + 8 BitDepth no + 9 ColorType no + 10 Compression no + 11 Filter no + 12 Interlace no + +=head3 PNG AnimationControl Tags + +Tags found in the Animation Conrol chunk. See +L<https://wiki.mozilla.org/APNG_Specification> for details. + + Index4 Tag Name Writable + ------ -------- -------- + 0 AnimationFrames no + 1 AnimationPlays no + +=head3 PNG PrimaryChromaticities Tags + + Index4 Tag Name Writable + ------ -------- -------- + 0 WhitePointX no + 1 WhitePointY no + 2 RedX no + 3 RedY no + 4 GreenX no + 5 GreenY no + 6 BlueX no + 7 BlueY no + +=head3 PNG TextualData Tags + +The PNG TextualData format allows arbitrary tag names to be used. The tags +listed below are the only ones that can be written (unless new user-defined +tags are added via the configuration file), however ExifTool will extract +any other TextualData tags that are found. All TextualData tags (including +tags not listed below) are removed when deleting all PNG tags. + +These tags may be stored as tEXt, zTXt or iTXt chunks in the PNG image. By +default ExifTool writes new string-value tags as as uncompressed tEXt, or +compressed zTXt if the Compress (-z) option is used and Compress::Zlib is +available. Alternate language tags and values containing special characters +(unless the Latin character set is used) are written as iTXt, and compressed +if the Compress option is used and Compress::Zlib is available. Raw profile +information is always created as compressed zTXt if Compress::Zlib is +available, or tEXt otherwise. Standard XMP is written as uncompressed iTXt. + +Alternate languages are accessed by suffixing the tag name with a '-', +followed by an RFC 3066 language code (eg. "PNG:Comment-fr", or +"Title-en-US"). See L<http://www.ietf.org/rfc/rfc3066.txt> for the RFC 3066 +specification. + +Some of the tags below are not registered as part of the PNG specification, +but are included here because they are generated by other software such as +ImageMagick. + + Tag ID Tag Name Writable + ------ -------- -------- + 'Artist' Artist string + 'Author' Author string + 'Collection' Collection string + 'Comment' Comment string + 'Copyright' Copyright string + 'Creation Time' CreationTime string + 'Description' Description string + 'Disclaimer' Disclaimer string + 'Document' Document string + 'Label' Label string + 'Make' Make string + 'Model' Model string + 'Raw profile type 8bim' Photoshop_Profile Photoshop + 'Raw profile type APP1' APP1_Profile EXIF + XMP + 'Raw profile type exif' EXIF_Profile EXIF + 'Raw profile type icc' ICC_Profile ICC_Profile + 'Raw profile type icm' ICC_Profile ICC_Profile + 'Raw profile type iptc' IPTC_Profile Photoshop + 'Raw profile type xmp' XMP_Profile XMP + 'Software' Software string + 'Source' Source string + 'TimeStamp' TimeStamp string + 'Title' Title string + 'URL' URL string + 'Warning' PNGWarning string + 'XML:com.adobe.xmp' XMP XMP + 'create-date' CreateDate string + 'modify-date' ModDate string + +=head3 PNG PhysicalPixel Tags + +These tags are found in the PNG pHYs chunk and belong to the PNG-pHYs family +1 group. They are all created together with default values if necessary +when any of these tags is written, and may only be deleted as a group. + + Index1 Tag Name Writable + ------ -------- -------- + 0 PixelsPerUnitX int32u + 4 PixelsPerUnitY int32u + 8 PixelUnits int8u + +=head3 PNG SubjectScale Tags + + Index1 Tag Name Writable + ------ -------- -------- + 0 SubjectUnits no + 1 SubjectPixelWidth no + 2 SubjectPixelHeight no + +=head3 PNG StereoImage Tags + + Index1 Tag Name Writable + ------ -------- -------- + 0 StereoMode no + +=head3 PNG VirtualPage Tags + + Index4 Tag Name Writable + ------ -------- -------- + 0 VirtualImageWidth no + 1 VirtualImageHeight no + 2 VirtualPageUnits no + +=head2 MNG Tags + +This table contains definitions for tags found in MNG and JNG images. MNG +is a superset of PNG and JNG, so a MNG image may contain any of these tags +as well as any PNG tags. Conversely, only some of these tags are valid for +JNG images. + + Tag ID Tag Name Writable + ------ -------- -------- + 'BACK' Background MNG Background + 'BASI' BasisObject MNG BasisObject + 'CLIP' ClipObjects MNG ClipObjects + 'CLON' CloneObject MNG CloneObject + 'DBYK' DropByKeyword no + 'DEFI' DefineObject MNG DefineObject + 'DHDR' DeltaPNGHeader MNG DeltaPNGHeader + 'DISC' DiscardObjects no + 'DROP' DropChunks no + 'FRAM' Frame no + 'JHDR' JNGHeader MNG JNGHeader + 'LOOP' Loop MNG Loop + 'MAGN' MagnifyObject MNG MagnifyObject + 'MHDR' MNGHeader MNG MNGHeader + 'MOVE' MoveObjects MNG MoveObjects + 'ORDR' OrderingRestrictions no + 'PAST' PasteImage MNG PasteImage + 'PPLT' PartialPalette no + 'PROM' PromoteParent MNG PromoteParent + 'SAVE' SaveObjects no + 'SEEK' SeekPoint no + 'SHOW' ShowObjects MNG ShowObjects + 'TERM' TerminationAction MNG TerminationAction + 'eXPi' ExportImage MNG ExportImage + 'fPRI' FramePriority MNG FramePriority + 'nEED' ResourcesNeeded no + 'pHYg' GlobalPixelSize PNG PhysicalPixel + +=head3 MNG Background Tags + + Index1 Tag Name Writable + ------ -------- -------- + 0 BackgroundColor no + 6 MandatoryBackground no + 7 BackgroundImageID no + 9 BackgroundTiling no + +=head3 MNG BasisObject Tags + + Index1 Tag Name Writable + ------ -------- -------- + 0 ImageWidth no + 4 ImageHeight no + 8 BitDepth no + 9 ColorType no + 10 Compression no + 11 Filter no + 12 Interlace no + 13 RedSample no + 17 GreenSample no + 21 BlueSample no + 25 AlphaSample no + 26 Viewable no + +=head3 MNG ClipObjects Tags + + Index1 Tag Name Writable + ------ -------- -------- + 0 FirstObject no + 2 LastObject no + 4 DeltaType no + 5 ClipBoundary no + +=head3 MNG CloneObject Tags + + Index1 Tag Name Writable + ------ -------- -------- + 0 SourceID no + 2 CloneID no + 4 CloneType no + 5 DoNotShow no + 6 ConcreteFlag no + 7 LocalDeltaType no + 8 DeltaXY no + +=head3 MNG DefineObject Tags + + Index1 Tag Name Writable + ------ -------- -------- + 0 ObjectID no + 2 DoNotShow no + 3 ConcreteFlag no + 4 XYLocation no + 12 ClippingBoundary no + +=head3 MNG DeltaPNGHeader Tags + + Index1 Tag Name Writable + ------ -------- -------- + 0 ObjectID no + 2 ImageType no + 3 DeltaType no + 4 BlockSize no + 12 BlockLocation no + +=head3 MNG JNGHeader Tags + + Index1 Tag Name Writable + ------ -------- -------- + 0 ImageWidth no + 4 ImageHeight no + 8 ColorType no + 9 BitDepth no + 10 Compression no + 11 Interlace no + 12 AlphaBitDepth no + 13 AlphaCompression no + 14 AlphaFilter no + 15 AlphaInterlace no + +=head3 MNG Loop Tags + + Index1 Tag Name Writable + ------ -------- -------- + 0 NestLevel no + 1 IterationCount no + 5 TerminationCondition no + 6 IterationMinMax no + 14 SignalNumber no + +=head3 MNG MagnifyObject Tags + + Index1 Tag Name Writable + ------ -------- -------- + 0 FirstObjectID no + 2 LastObjectID no + 4 XMethod no + 5 XMag no + 7 YMag no + 9 LeftMag no + 11 RightMag no + 13 TopMag no + 15 BottomMag no + 17 YMethod no + +=head3 MNG MNGHeader Tags + + Index4 Tag Name Writable + ------ -------- -------- + 0 ImageWidth no + 1 ImageHeight no + 2 TicksPerSecond no + 3 NominalLayerCount no + 4 NominalFrameCount no + 5 NominalPlayTime no + 6 SimplicityProfile no + +=head3 MNG MoveObjects Tags + + Index1 Tag Name Writable + ------ -------- -------- + 0 FirstObject no + 2 LastObject no + 4 DeltaType no + 5 DeltaXY no + +=head3 MNG PasteImage Tags + + Index1 Tag Name Writable + ------ -------- -------- + 0 DestinationID no + 2 TargetDeltaType no + 3 TargetXY no + 11 SourceID no + 13 CompositionMode no + 14 Orientation no + 15 OffsetOrigin no + 16 OffsetXY no + 24 BoundaryOrigin no + 25 PastClippingBoundary no + +=head3 MNG PromoteParent Tags + + Index1 Tag Name Writable + ------ -------- -------- + 0 NewColorType no + 1 NewBitDepth no + 2 FillMethod no + +=head3 MNG ShowObjects Tags + + Index1 Tag Name Writable + ------ -------- -------- + 0 FirstObject no + 2 LastObject no + 4 ShowMode no + +=head3 MNG TerminationAction Tags + + Index1 Tag Name Writable + ------ -------- -------- + 0 TerminationAction no + 1 IterationEndAction no + 2 Delay no + 6 IterationMax no + +=head3 MNG ExportImage Tags + + Index1 Tag Name Writable + ------ -------- -------- + 0 SnapshotID no + 2 SnapshotName no + +=head3 MNG FramePriority Tags + + Index1 Tag Name Writable + ------ -------- -------- + 0 DeltaType no + 2 Priority no + +=head2 FLIF Tags + +Information extracted from Free Lossless Image Format files. See +L<http://flif.info/> for more information. + + Tag ID Tag Name Writable + ------ -------- -------- + 0 ImageType no + 1 BitDepth no + 2 ImageWidth no + 3 ImageHeight no + 4 AnimationFrames no + 5 Encoding no + 'eXif' EXIF EXIF + 'eXmp' XMP XMP + 'iCCP' ICC_Profile ICC_Profile + +=head2 DjVu Tags + +Information is extracted from the following chunks in DjVu images. See +L<http://www.djvu.org/> for the DjVu specification. + + Tag ID Tag Name Writable + ------ -------- -------- + 'ANTa' ANTa DjVu Ant + 'ANTz' CompressedAnnotation DjVu Ant + 'FORM' FORM DjVu Form + 'INCL' IncludedFileID no + 'INFO' INFO DjVu Info + +=head3 DjVu Ant Tags + +Information extracted from annotation chunks. + + Tag ID Tag Name Writable + ------ -------- -------- + 'metadata' Metadata DjVu Meta + 'xmp' XMP XMP + +=head3 DjVu Meta Tags + +This table lists the standard DjVu metadata tags, but ExifTool will extract +any tags that exist even if they don't appear here. The DjVu v3 +documentation endorses tags borrowed from two standards: 1) BibTeX +bibliography system tags (all lowercase Tag ID's in the table below), and 2) +PDF DocInfo tags (capitalized Tag ID's). + + Tag ID Tag Name Writable + ------ -------- -------- + 'Author' Author no + 'CreationDate' CreateDate no + 'Creator' Creator no + 'Keywords' Keywords no + 'ModDate' ModifyDate no + 'Producer' Producer no + 'Subject' Subject no + 'Title' Title no + 'Trapped' Trapped no + 'address' Address no + 'annote' Annotation no + 'author' Author no + 'booktitle' BookTitle no + 'chapter' Chapter no + 'crossref' CrossRef no + 'edition' Edition no + 'eprint' EPrint no + 'howpublished' HowPublished no + 'institution' Institution no + 'journal' Journal no + 'key' Key no + 'month' Month no + 'note' Note no + 'number' Number no + 'organization' Organization no + 'pages' Pages no + 'publisher' Publisher no + 'school' School no + 'series' Series no + 'title' Title no + 'type' Type no + 'url' URL no + 'volume' Volume no + 'year' Year no + +=head3 DjVu Form Tags + + Index1 Tag Name Writable + ------ -------- -------- + 0 SubfileType no + +=head3 DjVu Info Tags + + Index1 Tag Name Writable + ------ -------- -------- + 0 ImageWidth no + 2 ImageHeight no + 4 DjVuVersion no + 6 SpatialResolution no + 8 Gamma no + 9 Orientation no + +=head2 DPX Tags + +Tags extracted from DPX (Digital Picture Exchange) images. + + Index1 Tag Name Writable + ------ -------- -------- + 0 ByteOrder no + 8 HeaderVersion no + 16 DPXFileSize no + 20 DittoKey no + 36 ImageFileName no + 136 CreateDate no + 160 Creator no + 260 Project no + 460 Copyright no + 660 EncryptionKey no + 768 Orientation no + 770 ImageElements no + 772 ImageWidth no + 776 ImageHeight no + 780 DataSign no + 800 ComponentsConfiguration no + 803 BitDepth no + 820 ImageDescription no + 892 Image2Description no + 964 Image3Description no + 1036 Image4Description no + 1108 Image5Description no + 1180 Image6Description no + 1252 Image7Description no + 1324 Image8Description no + 1432 SourceFileName no + 1532 SourceCreateDate no + 1556 InputDeviceName no + 1588 InputDeviceSerialNumber no + 1724 FrameRate no + 1732 FrameID no + 1764 SlateInformation no + 1972 Reserved5? no + 2048 UserID no + +=head2 OpenEXR Tags + +Information extracted from EXR images. See L<http://www.openexr.com/> for +the official specification. + + Tag ID Tag Name Writable + ------ -------- -------- + '_lay' Layout no + '_ver' EXRVersion no + 'adoptedNeutral' AdoptedNeutral no + 'altitude' GPSAltitude no + 'aperture' Aperture no + 'capDate' DateTimeOriginal no + 'channels' Channels no + 'chromaticities' Chromaticities no + 'comments' Comments no + 'compression' Compression no + 'dataWindow' DataWindow no + 'displayWindow' DisplayWindow no + 'envmap' EnvironmentMap no + 'expTime' ExposureTime no + 'focus' FocusDistance no + 'framesPerSecond' FramesPerSecond no + 'isoSpeed' ISO no + 'keyCode' KeyCode no + 'latitude' GPSLatitude no + 'lineOrder' LineOrder no + 'longitude' GPSLongitude no + 'lookModTransform' LookModTransform no + 'multiView' MultiView no + 'owner' Owner no + 'pixelAspectRatio' PixelAspectRatio no + 'preview' Preview no + 'renderingTransform' RenderingTransform no + 'screenWindowCenter' ScreenWindowCenter no + 'screenWindowWidth' ScreenWindowWidth no + 'tiles' Tiles no + 'timeCode' TimeCode no + 'utcOffset' TimeZone no + 'whiteLuminance' WhiteLuminance no + 'worldToCamera' WorldToCamera no + 'worldToNDC' WorldToNDC no + 'wrapmodes' WrapModes no + 'xDensity' XResolution no + +=head2 MIFF Tags + +The MIFF (Magick Image File Format) format allows aribrary tag names to be +used. Only the standard tag names are listed below, however ExifTool will +decode any tags found in the image. + + Tag ID Tag Name Writable + ------ -------- -------- + 'background-color' BackgroundColor no + 'blue-primary' BluePrimary no + 'border-color' BorderColor no + 'class' Class no + 'colors' Colors no + 'colorspace' ColorSpace no + 'columns' ImageWidth no + 'compression' Compression no + 'delay' Delay no + 'depth' Depth no + 'dispose' Dispose no + 'gamma' Gamma no + 'green-primary' GreenPrimary no + 'id' ID no + 'iterations' Iterations no + 'label' Label no + 'matt-color' MattColor no + 'matte' Matte no + 'montage' Montage no + 'packets' Packets no + 'page' Page no + 'profile-APP1' APP1_Profile EXIF + XMP + 'profile-exif' EXIF_Profile EXIF + 'profile-icc' ICC_Profile ICC_Profile + 'profile-iptc' IPTC_Profile Photoshop + 'profile-xmp' XMP_Profile XMP + 'red-primary' RedPrimary no + 'rendering-intent' RenderingIntent no + 'resolution' Resolution no + 'rows' ImageHeight no + 'scene' Scene no + 'signature' Signature no + 'units' Units no + 'white-point' WhitePoint no + +=head2 PCX Tags + +Tags extracted from PC Paintbrush images. + + Index1 Tag Name Writable + ------ -------- -------- + 0 Manufacturer no + 1 Software no + 2 Encoding no + 3 BitsPerPixel no + 4 LeftMargin no + 6 TopMargin no + 8 ImageWidth no + 10 ImageHeight no + 12 XResolution no + 14 YResolution no + 65 ColorPlanes no + 66 BytesPerLine no + 68 ColorMode no + 70 ScreenWidth no + 72 ScreenHeight no + +=head2 PGF Tags + +The following table lists information extracted from the header of +Progressive Graphics File (PGF) images. As well, information is extracted +from the embedded PNG metadata image if it exists. See +L<http://www.libpgf.org/> for the PGF specification. + + Index1 Tag Name Writable + ------ -------- -------- + 3 PGFVersion no + 8 ImageWidth no + 12 ImageHeight no + 16 PyramidLevels no + 17 Quality no + 18 BitsPerPixel no + 19 ColorComponents no + 20 ColorMode no + 21 BackgroundColor no + +=head2 PSP Tags + +Tags extracted from Paint Shop Pro images (PSP, PSPIMAGE, PSPFRAME, +PSPSHAPE, PSPTUBE and TUB extensions). + + Tag ID Tag Name Writable + ------ -------- -------- + 'FileVersion' FileVersion no + 0x0000 ImageInfo PSP Image + PSP Image + 0x0001 CreatorInfo PSP Creator + 0x000a ExtendedInfo PSP Ext + +=head3 PSP Image Tags + + Index1 Tag Name Writable + ------ -------- -------- + 0 ImageWidth no + 4 ImageHeight no + 8 ImageResolution no + 16 ResolutionUnit no + 17 Compression no + 19 BitsPerSample no + 21 Planes no + 23 NumColors no + +=head3 PSP Creator Tags + + Tag ID Tag Name Writable + ------ -------- -------- + 0x0000 Title no + 0x0001 CreateDate no + 0x0002 ModifyDate no + 0x0003 Artist no + 0x0004 Copyright no + 0x0005 Description no + 0x0006 CreatorAppID no + 0x0007 CreatorAppVersion no + +=head3 PSP Ext Tags + + Tag ID Tag Name Writable + ------ -------- -------- + 0x0003 EXIFInfo EXIF + +=head2 PhotoCD Tags + +Tags extracted from Kodak Photo CD Image Pac (PCD) files. + + Index1 Tag Name Writable + ------ -------- -------- + 7 SpecificationVersion no + 9 AuthoringSoftwareRelease no + 11 ImageMagnificationDescriptor no + 13 CreateDate no + 17 ModifyDate no + 21 ImageMedium no + 22 ProductType no + 42 ScannerVendorID no + 62 ScannerProductID no + 78 ScannerFirmwareVersion no + 82 ScannerFirmwareDate no + 90 ScannerSerialNumber no + 110 ScannerPixelSize no + 112 ImageWorkstationMake no + 132 CharacterSet no + 133 CharacterEscapeSequence? no + 165 PhotoFinisherName no + 228 SceneBalanceAlgorithmRevision no + 230 SceneBalanceAlgorithmCommand no + 325 SceneBalanceAlgorithmFilmID no + 331 CopyrightStatus no + 332 CopyrightFileName no + 1538 Orientation no + 1538.1 ImageWidth no + 1538.2 ImageHeight no + 1538.3 CompressionClass no + +=head2 Radiance Tags + +Information extracted from Radiance RGBE HDR images. Tag ID's are all +uppercase as stored in the file, but converted to lowercase by when +extracting to avoid conflicts with internal ExifTool variables. See +L<http://radsite.lbl.gov/radiance/refer/filefmts.pdf> and +L<http://www.graphics.cornell.edu/online/formats/rgbe/> for the +specification. + + Tag ID Tag Name Writable + ------ -------- -------- + '_command' Command no + '_orient' Orientation no + 'colorcorr' ColorCorrection no + 'exposure' Exposure no + 'format' Format no + 'gamma' Gamma no + 'pixaspect' PixelAspectRatio no + 'primaries' ColorPrimaries no + 'software' Software no + 'view' View no + +=head2 PDF Tags + +The tags listed in the PDF tables below are those which are used by ExifTool +to extract meta information, but they are only a small fraction of the total +number of available PDF tags. See +L<http://www.adobe.com/devnet/pdf/pdf_reference.html> for the official PDF +specification. + +ExifTool supports reading and writing PDF documents up to version 1.7 +extension level 3, including support for RC4, AES-128 and AES-256 +encryption. A Password option is provided to allow processing of +password-protected PDF files. + +ExifTool may be used to write native PDF and XMP metadata to PDF files. It +uses an incremental update technique that has the advantages of being both +fast and reversible. If ExifTool was used to modify a PDF file, the +original may be recovered by deleting the C<PDF-update> pseudo-group (with +C<-PDF-update:all=> on the command line). However, there are two main +disadvantages to this technique: + +1) A linearized PDF file is no longer linearized after the update, so it +must be subsequently re-linearized if this is required. + +2) All metadata edits are reversible. While this would normally be +considered an advantage, it is a potential security problem because old +information is never actually deleted from the file. (However, after +running ExifTool the old information may be removed permanently using the +"qpdf" utility with this command: "qpdf --linearize in.pdf out.pdf".) + + Tag ID Tag Name Writable + ------ -------- -------- + 'Encrypt' Encrypt PDF Encrypt + 'Info' Info PDF Info + 'Root' Root PDF Root + '_linearized' Linearized no + +=head3 PDF Encrypt Tags + +Tags extracted from the document Encrypt dictionary. + + Tag ID Tag Name Writable + ------ -------- -------- + 'Filter' Encryption no + 'P' UserAccess no + +=head3 PDF Info Tags + +As well as the tags listed below, the PDF specification allows for +user-defined tags to exist in the Info dictionary. These tags, which should +have corresponding XMP-pdfx entries in the XMP of the PDF XML Metadata +object, are also extracted by ExifTool. + +B<Writable> specifies the value format, and may be C<string>, C<date>, +C<integer>, C<real>, C<boolean> or C<name> for PDF tags. + + Tag ID Tag Name Writable + ------ -------- -------- + 'AAPL:Keywords' AppleKeywords string+ + 'Author' Author string + 'CreationDate' CreateDate date + 'Creator' Creator string + 'Keywords' Keywords string+ + 'ModDate' ModifyDate date + 'Producer' Producer string + 'Subject' Subject string + 'Title' Title string + 'Trapped' Trapped string! + +=head3 PDF Root Tags + +This is the PDF document catalog. + + Tag ID Tag Name Writable + ------ -------- -------- + 'AcroForm' AcroForm PDF AcroForm + 'Lang' Language no + 'MarkInfo' MarkInfo PDF MarkInfo + 'Metadata' Metadata PDF Metadata + 'PageLayout' PageLayout no + 'PageMode' PageMode no + 'Pages' Pages PDF Pages + 'Perms' Perms PDF Perms + 'Version' PDFVersion no + +=head3 PDF AcroForm Tags + + Tag ID Tag Name Writable + ------ -------- -------- + '_has_xfa' HasXFA no + +=head3 PDF MarkInfo Tags + + Tag ID Tag Name Writable + ------ -------- -------- + 'Marked' TaggedPDF no + +=head3 PDF Metadata Tags + + Tag ID Tag Name Writable + ------ -------- -------- + 'XML_stream' XMP XMP + +=head3 PDF Pages Tags + + Tag ID Tag Name Writable + ------ -------- -------- + 'Count' PageCount no + 'Kids' Kids PDF Kids + +=head3 PDF Kids Tags + + Tag ID Tag Name Writable + ------ -------- -------- + 'Kids' Kids PDF Kids + 'Metadata' Metadata PDF Metadata + 'PieceInfo' PieceInfo PDF PieceInfo + 'Resources' Resources PDF Resources + +=head3 PDF PieceInfo Tags + + Tag ID Tag Name Writable + ------ -------- -------- + 'AdobePhotoshop' AdobePhotoshop PDF AdobePhotoshop + 'Illustrator' Illustrator PDF Illustrator + +=head3 PDF AdobePhotoshop Tags + + Tag ID Tag Name Writable + ------ -------- -------- + 'Private' Private PDF Private + +=head3 PDF Private Tags + + Tag ID Tag Name Writable + ------ -------- -------- + 'ImageResources' ImageResources PDF ImageResources + +=head3 PDF ImageResources Tags + + Tag ID Tag Name Writable + ------ -------- -------- + '_stream' _stream Photoshop + +=head3 PDF Illustrator Tags + + Tag ID Tag Name Writable + ------ -------- -------- + 'Private' Private PDF AIPrivate + +=head3 PDF AIPrivate Tags + + Tag ID Tag Name Writable + ------ -------- -------- + 'AIMetaData' AIMetaData PDF AIMetaData + 'AIPDFPrivateData' AIPDFPrivateData PostScript + 'AIPrivateData' AIPrivateData PostScript + 'ContainerVersion' ContainerVersion no + 'CreatorVersion' CreatorVersion no + 'RoundTripVersion' RoundTripVersion no + +=head3 PDF AIMetaData Tags + + Tag ID Tag Name Writable + ------ -------- -------- + '_stream' _stream PostScript + +=head3 PDF Resources Tags + + Tag ID Tag Name Writable + ------ -------- -------- + 'ColorSpace' ColorSpace PDF ColorSpace + 'Properties' Properties PDF Properties + 'XObject' XObject PDF XObject + +=head3 PDF ColorSpace Tags + + Tag ID Tag Name Writable + ------ -------- -------- + 'Cs1' Cs1 PDF Cs1 + 'DefaultRGB' DefaultRGB PDF DefaultRGB + +=head3 PDF Cs1 Tags + + Tag ID Tag Name Writable + ------ -------- -------- + '_stream' _stream ICC_Profile + +=head3 PDF DefaultRGB Tags + + Tag ID Tag Name Writable + ------ -------- -------- + 'ICCBased' ICCBased PDF ICCBased + +=head3 PDF ICCBased Tags + + Tag ID Tag Name Writable + ------ -------- -------- + '_stream' _stream ICC_Profile + +=head3 PDF Properties Tags + + Tag ID Tag Name Writable + ------ -------- -------- + 'MC' MC PDF MC + +=head3 PDF MC Tags + + Tag ID Tag Name Writable + ------ -------- -------- + 'Metadata' Metadata PDF Metadata + +=head3 PDF XObject Tags + + Tag ID Tag Name Writable + ------ -------- -------- + 'Im' Im PDF Im + +=head3 PDF Im Tags + +Information extracted from embedded images with the ExtractEmbedded option. +The EmbeddedImage and its metadata are extracted only for JPEG and Jpeg2000 +image formats. + + Tag ID Tag Name Writable + ------ -------- -------- + 'ColorSpace' EmbeddedImageColorSpace no+ + 'Filter' EmbeddedImageFilter no+ + 'Height' EmbeddedImageHeight no + 'Image_stream' EmbeddedImage no + 'Width' EmbeddedImageWidth no + +=head3 PDF Perms Tags + +Additional document permissions imposed by digital signatures. + + Tag ID Tag Name Writable + ------ -------- -------- + 'DocMDP' DocMDP PDF Signature + 'FieldMDP' FieldMDP PDF Signature + 'UR3' UR3 PDF Signature + +=head3 PDF Signature Tags + + Tag ID Tag Name Writable + ------ -------- -------- + 'ContactInfo' SignerContactInfo no + 'Location' SigningLocation no + 'M' SigningDate no + 'Name' SigningAuthority no + 'Prop_AuthTime' AuthenticationTime no + 'Prop_AuthType' AuthenticationType no + 'Reason' SigningReason no + 'Reference' Reference PDF Reference + +=head3 PDF Reference Tags + + Tag ID Tag Name Writable + ------ -------- -------- + 'TransformParams' TransformParams PDF TransformParams + +=head3 PDF TransformParams Tags + + Tag ID Tag Name Writable + ------ -------- -------- + 'Action' FieldPermissions no + 'Annots' AnnotationUsageRights no+ + 'Document' DocumentUsageRights no+ + 'EF' EmbeddedFileUsageRights no+ + 'Fields' FormFields no+ + 'Form' FormUsageRights no+ + 'FormEX' FormExtraUsageRights no+ + 'Msg' UsageRightsMessage no + 'P' ModificationPermissions no + 'Signature' SignatureUsageRights no+ + +=head2 PostScript Tags + + Tag ID Tag Name Writable + ------ -------- -------- + 'AI12_BuildNumber' AIBuildNumber no + 'AI3_ColorUsage' AIColorUsage no + 'AI5_FileFormat' AIFileFormat no + 'AI5_NumLayers' AINumLayers no + 'AI5_RulerUnits' AIRulerUnits no + 'AI5_TargetResolution' AITargetResolution no + 'AI8_CreatorVersion' AICreatorVersion no + 'AI9_ColorModel' AIColorModel no + 'Author' Author string + 'BeginDocument' EmbeddedFile PostScript + 'BeginICCProfile' ICC_Profile ICC_Profile + 'BeginPhotoshop' PhotoshopData Photoshop + 'BoundingBox' BoundingBox no + 'Copyright' Copyright string + 'CreationDate' CreateDate string + 'Creator' Creator string + 'EmbeddedFileName' EmbeddedFileName no + 'For' For string + 'ImageData' ImageData no + 'Keywords' Keywords string + 'ModDate' ModifyDate string + 'Pages' Pages no + 'Routing' Routing string + 'Subject' Subject string + 'TIFFPreview' TIFFPreview no + 'Title' Title string + 'Version' Version string + 'begin_xml_packet' XMP XMP + +=head2 ID3 Tags + +ExifTool extracts ID3 information from MP3, MPEG, AIFF, OGG, FLAC, APE, MPC +and RealAudio files. ID3v2 tags which support multiple languages (eg. +Comment and Lyrics) are extracted by specifying the tag name, followed by a +dash ('-'), then a 3-character ISO 639-2 language code (eg. "Comment-spa"). +See L<http://www.id3.org/> for the official ID3 specification and +L<http://www.loc.gov/standards/iso639-2/php/code_list.php> for a list of ISO +639-2 language codes. + + Tag Name Writable + -------- -------- + ID3v1 ID3 v1 + ID3v1_Enh ID3 v1_Enh + ID3v2_2 ID3 v2_2 + ID3v2_3 ID3 v2_3 + ID3v2_4 ID3 v2_4 + +=head3 ID3 v1 Tags + + Index1 Tag Name Writable + ------ -------- -------- + 3 Title no + 33 Artist no + 63 Album no + 93 Year no + 97 Comment no + 125 Track no + 127 Genre no + +=head3 ID3 v1_Enh Tags + +ID3 version 1 "Enhanced TAG" information (not part of the official spec). + + Index1 Tag Name Writable + ------ -------- -------- + 4 Title2 no + 64 Artist2 no + 124 Album2 no + 184 Speed no + 185 Genre no + 215 StartTime no + 221 EndTime no + +=head3 ID3 v2_2 Tags + +ExifTool extracts mainly text-based tags from ID3v2 information. The tags +in the tables below are those extracted by ExifTool, and don't represent a +complete list of available ID3v2 tags. + +ID3 version 2.2 tags. (These are the tags written by iTunes 5.0.) + + Tag ID Tag Name Writable + ------ -------- -------- + 'CNT' PlayCounter no + 'COM' Comment no + 'IPL' InvolvedPeople no + 'ITU' iTunesU? no + 'PCS' Podcast? no + 'PIC' Picture no + 'PIC-1' PictureFormat no + 'PIC-2' PictureType no + 'PIC-3' PictureDescription no + 'POP' Popularimeter no + 'RVA' RelativeVolumeAdjustment no + 'SLT' SynLyrics ID3 SynLyrics + 'TAL' Album no + 'TBP' BeatsPerMinute no + 'TCM' Composer no + 'TCO' Genre no + 'TCP' Compilation no + 'TCR' Copyright no + 'TDA' Date no + 'TDY' PlaylistDelay no + 'TEN' EncodedBy no + 'TFT' FileType no + 'TIM' Time no + 'TKE' InitialKey no + 'TLA' Language no + 'TLE' Length no + 'TMT' Media no + 'TOA' OriginalArtist no + 'TOF' OriginalFileName no + 'TOL' OriginalLyricist no + 'TOR' OriginalReleaseYear no + 'TOT' OriginalAlbum no + 'TP1' Artist no + 'TP2' Band no + 'TP3' Conductor no + 'TP4' InterpretedBy no + 'TPA' PartOfSet no + 'TPB' Publisher no + 'TRC' ISRC no + 'TRD' RecordingDates no + 'TRK' Track no + 'TS2' AlbumArtistSortOrder no + 'TSA' AlbumSortOrder no + 'TSC' ComposerSortOrder no + 'TSI' Size no + 'TSP' PerformerSortOrder no + 'TSS' EncoderSettings no + 'TST' TitleSortOrder no + 'TT1' Grouping no + 'TT2' Title no + 'TT3' Subtitle no + 'TXT' Lyricist no + 'TXX' UserDefinedText no + 'TYE' Year no + 'ULT' Lyrics no + 'WAF' FileURL no + 'WAR' ArtistURL no + 'WAS' SourceURL no + 'WCM' CommercialURL no + 'WCP' CopyrightURL no + 'WPB' PublisherURL no + 'WXX' UserDefinedURL no + +=head3 ID3 SynLyrics Tags + +The following tags are extracted from synchronized lyrics/text frames. + + Tag Name Writable + -------- -------- + SynchronizedLyricsDescription no + SynchronizedLyricsText no+ + SynchronizedLyricsType no + +=head3 ID3 v2_3 Tags + +ID3 version 2.3 tags. Includes some non-standard tags written by other +software. + + Tag ID Tag Name Writable + ------ -------- -------- + 'APIC' Picture no + 'APIC-1' PictureMIMEType no + 'APIC-2' PictureType no + 'APIC-3' PictureDescription no + 'COMM' Comment no + 'IPLS' InvolvedPeople no + 'ITNU' iTunesU? no + 'MCDI' MusicCDIdentifier no + 'OWNE' Ownership no + 'PCNT' PlayCounter no + 'PCST' Podcast? no + 'POPM' Popularimeter no + 'PRIV' Private ID3 Private + 'SYLT' SynLyrics ID3 SynLyrics + 'TALB' Album no + 'TBPM' BeatsPerMinute no + 'TCAT' PodcastCategory no + 'TCMP' Compilation no + 'TCOM' Composer no + 'TCON' Genre no + 'TCOP' Copyright no + 'TDAT' Date no + 'TDES' PodcastDescription no + 'TDLY' PlaylistDelay no + 'TENC' EncodedBy no + 'TEXT' Lyricist no + 'TFLT' FileType no + 'TGID' PodcastID no + 'TIME' Time no + 'TIT1' Grouping no + 'TIT2' Title no + 'TIT3' Subtitle no + 'TKEY' InitialKey no + 'TKWD' PodcastKeywords no + 'TLAN' Language no + 'TLEN' Length no + 'TMED' Media no + 'TOAL' OriginalAlbum no + 'TOFN' OriginalFileName no + 'TOLY' OriginalLyricist no + 'TOPE' OriginalArtist no + 'TORY' OriginalReleaseYear no + 'TOWN' FileOwner no + 'TPE1' Artist no + 'TPE2' Band no + 'TPE3' Conductor no + 'TPE4' InterpretedBy no + 'TPOS' PartOfSet no + 'TPUB' Publisher no + 'TRCK' Track no + 'TRDA' RecordingDates no + 'TRSN' InternetRadioStationName no + 'TRSO' InternetRadioStationOwner no + 'TSIZ' Size no + 'TSO2' AlbumArtistSortOrder no + 'TSOC' ComposerSortOrder no + 'TSRC' ISRC no + 'TSSE' EncoderSettings no + 'TXXX' UserDefinedText no + 'TYER' Year no + 'USER' TermsOfUse no + 'USLT' Lyrics no + 'WCOM' CommercialURL no + 'WCOP' CopyrightURL no + 'WFED' PodcastURL no + 'WOAF' FileURL no + 'WOAR' ArtistURL no + 'WOAS' SourceURL no + 'WORS' InternetRadioStationURL no + 'WPAY' PaymentURL no + 'WPUB' PublisherURL no + 'WXXX' UserDefinedURL no + 'XDOR' OriginalReleaseTime no + 'XOLY' OlympusDSS Olympus DSS + 'XSOA' AlbumSortOrder no + 'XSOP' PerformerSortOrder no + 'XSOT' TitleSortOrder no + +=head3 ID3 Private Tags + +ID3 private (PRIV) tags. ExifTool will decode any private tags found, even +if they do not appear in this table. + + Tag Name Writable + -------- -------- + AverageLevel no + PeakValue no + WM_CollectionGroupID no + WM_CollectionID no + WM_ContentID no + WM_MediaClassPrimaryID no + WM_MediaClassSecondaryID no + WM_Provider no + XMP XMP + +=head3 ID3 v2_4 Tags + +ID3 version 2.4 tags. Includes some non-standard tags written by other +software. + + Tag ID Tag Name Writable + ------ -------- -------- + 'APIC' Picture no + 'APIC-1' PictureMIMEType no + 'APIC-2' PictureType no + 'APIC-3' PictureDescription no + 'COMM' Comment no + 'ITNU' iTunesU? no + 'MCDI' MusicCDIdentifier no + 'OWNE' Ownership no + 'PCNT' PlayCounter no + 'PCST' Podcast? no + 'POPM' Popularimeter no + 'PRIV' Private ID3 Private + 'RVA2' RelativeVolumeAdjustment no + 'SYLT' SynLyrics ID3 SynLyrics + 'TALB' Album no + 'TBPM' BeatsPerMinute no + 'TCAT' PodcastCategory no + 'TCMP' Compilation no + 'TCOM' Composer no + 'TCON' Genre no + 'TCOP' Copyright no + 'TDEN' EncodingTime no + 'TDES' PodcastDescription no + 'TDLY' PlaylistDelay no + 'TDOR' OriginalReleaseTime no + 'TDRC' RecordingTime no + 'TDRL' ReleaseTime no + 'TDTG' TaggingTime no + 'TENC' EncodedBy no + 'TEXT' Lyricist no + 'TFLT' FileType no + 'TGID' PodcastID no + 'TIPL' InvolvedPeople no + 'TIT1' Grouping no + 'TIT2' Title no + 'TIT3' Subtitle no + 'TKEY' InitialKey no + 'TKWD' PodcastKeywords no + 'TLAN' Language no + 'TLEN' Length no + 'TMCL' MusicianCredits no + 'TMED' Media no + 'TMOO' Mood no + 'TOAL' OriginalAlbum no + 'TOFN' OriginalFileName no + 'TOLY' OriginalLyricist no + 'TOPE' OriginalArtist no + 'TOWN' FileOwner no + 'TPE1' Artist no + 'TPE2' Band no + 'TPE3' Conductor no + 'TPE4' InterpretedBy no + 'TPOS' PartOfSet no + 'TPRO' ProducedNotice no + 'TPUB' Publisher no + 'TRCK' Track no + 'TRSN' InternetRadioStationName no + 'TRSO' InternetRadioStationOwner no + 'TSO2' AlbumArtistSortOrder no + 'TSOA' AlbumSortOrder no + 'TSOC' ComposerSortOrder no + 'TSOP' PerformerSortOrder no + 'TSOT' TitleSortOrder no + 'TSRC' ISRC no + 'TSSE' EncoderSettings no + 'TSST' SetSubtitle no + 'TXXX' UserDefinedText no + 'USER' TermsOfUse no + 'USLT' Lyrics no + 'WCOM' CommercialURL no + 'WCOP' CopyrightURL no + 'WFED' PodcastURL no + 'WOAF' FileURL no + 'WOAR' ArtistURL no + 'WOAS' SourceURL no + 'WORS' InternetRadioStationURL no + 'WPAY' PaymentURL no + 'WPUB' PublisherURL no + 'WXXX' UserDefinedURL no + 'XDOR' OriginalReleaseTime no + 'XOLY' OlympusDSS Olympus DSS + 'XSOA' AlbumSortOrder no + 'XSOP' PerformerSortOrder no + 'XSOT' TitleSortOrder no + +=head2 ITC Tags + +This information is found in iTunes Cover Flow data files. + + Tag ID Tag Name Writable + ------ -------- -------- + 'data' ImageData no + 'itch' Itch ITC Header + 'item' Item ITC Item + +=head3 ITC Header Tags + + Index1 Tag Name Writable + ------ -------- -------- + 16 DataType no + +=head3 ITC Item Tags + + Index4 Tag Name Writable + ------ -------- -------- + 0 LibraryID no + 2 TrackID no + 4 DataLocation no + 5 ImageType no + 7 ImageWidth no + 8 ImageHeight no + +=head2 FLAC Tags + +Free Lossless Audio Codec (FLAC) meta information. ExifTool also extracts +ID3 information from these files. + + Tag ID Tag Name Writable + ------ -------- -------- + 0x0000 StreamInfo FLAC StreamInfo + 0x0001 Padding? no + 0x0002 Application? no + 0x0003 SeekTable? no + 0x0004 VorbisComment Vorbis Comments + 0x0005 CueSheet? no + 0x0006 Picture FLAC Picture + +=head3 FLAC StreamInfo Tags + +FLAC is big-endian, so bit 0 is the high-order bit in this table. + + Tag ID Tag Name Writable + ------ -------- -------- + 'Bit000-015' BlockSizeMin no + 'Bit016-031' BlockSizeMax no + 'Bit032-055' FrameSizeMin no + 'Bit056-079' FrameSizeMax no + 'Bit080-099' SampleRate no + 'Bit100-102' Channels no + 'Bit103-107' BitsPerSample no + 'Bit108-143' TotalSamples no + 'Bit144-271' MD5Signature no + +=head3 FLAC Picture Tags + + Index4 Tag Name Writable + ------ -------- -------- + 0 PictureType no + 1 PictureMIMEType no + 2 PictureDescription no + 3 PictureWidth no + 4 PictureHeight no + 5 PictureBitsPerPixel no + 6 PictureIndexedColors no + 7 PictureLength no + 8 Picture no + +=head2 Ogg Tags + +ExifTool extracts the following types of information from Ogg files. See +L<http://www.xiph.org/vorbis/doc/> for the Ogg specification. + + Tag ID Tag Name Writable + ------ -------- -------- + 'FLAC' FLAC FLAC + 'ID3' ID3 ID3 + 'Opus' Opus Opus + 'theora' Theora Theora + 'vorbis' Vorbis Vorbis + +=head2 Vorbis Tags + +Information extracted from Ogg Vorbis files. See +L<http://www.xiph.org/vorbis/doc/> for the Vorbis specification. + + Tag ID Tag Name Writable + ------ -------- -------- + 0x0001 Identification Vorbis Identification + 0x0003 Comments Vorbis Comments + +=head3 Vorbis Comments Tags + +The tags below are only some common tags found in the Vorbis comments of Ogg +Vorbis and Ogg FLAC audio files, however ExifTool will extract values from +any tag found, even if not listed here. + + Tag ID Tag Name Writable + ------ -------- -------- + 'ACTOR' Actor no + 'ALBUM' Album no + 'ARTIST' Artist no+ + 'COMMENT' Comment no + 'COMPOSER' Composer no + 'CONTACT' Contact no+ + 'COPYRIGHT' Copyright no + 'COVERART' CoverArt no + 'COVERARTMIME' CoverArtMIMEType no + 'DATE' Date no + 'DESCRIPTION' Description no + 'DIRECTOR' Director no + 'ENCODED_BY' EncodedBy no + 'ENCODED_USING' EncodedUsing no + 'ENCODER' Encoder no + 'ENCODER_OPTIONS' EncoderOptions no + 'GENRE' Genre no + 'ISRC' ISRCNumber no + 'LICENSE' License no + 'LOCATION' Location no + 'METADATA_BLOCK_PICTURE' Picture FLAC Picture + 'ORGANIZATION' Organization no + 'PERFORMER' Performer no+ + 'PRODUCER' Producer no + 'REPLAYGAIN_ALBUM_GAIN' ReplayGainAlbumGain no + 'REPLAYGAIN_ALBUM_PEAK' ReplayGainAlbumPeak no + 'REPLAYGAIN_TRACK_GAIN' ReplayGainTrackGain no + 'REPLAYGAIN_TRACK_PEAK' ReplayGainTrackPeak no + 'TITLE' Title no + 'TRACKNUMBER' TrackNumber no + 'VERSION' Version no + 'vendor' Vendor no + +=head3 Vorbis Identification Tags + + Index1 Tag Name Writable + ------ -------- -------- + 0 VorbisVersion no + 4 AudioChannels no + 5 SampleRate no + 9 MaximumBitrate no + 13 NominalBitrate no + 17 MinimumBitrate no + +=head2 Opus Tags + +Information extracted from Ogg Opus files. See +L<https://www.opus-codec.org/docs/> for the specification. + + Tag ID Tag Name Writable + ------ -------- -------- + 'OpusHead' Header Opus Header + 'OpusTags' Comments Vorbis Comments + +=head3 Opus Header Tags + + Index1 Tag Name Writable + ------ -------- -------- + 0 OpusVersion no + 1 AudioChannels no + 4 SampleRate no + 8 OutputGain no + +=head2 Theora Tags + +Information extracted from Ogg Theora video files. See +L<http://www.theora.org/doc/Theora.pdf> for the Theora specification. + + Tag ID Tag Name Writable + ------ -------- -------- + 0x0080 Identification Theora Identification + 0x0081 Comments Vorbis Comments + +=head3 Theora Identification Tags + +Tags extracted from the Theora identification header. + + Index1 Tag Name Writable + ------ -------- -------- + 0 TheoraVersion no + 7 ImageWidth no + 10 ImageHeight no + 13 XOffset no + 14 YOffset no + 15 FrameRate no + 23 PixelAspectRatio no + 29 ColorSpace no + 30 NominalVideoBitrate no + 33 Quality no + 34 PixelFormat no + +=head2 APE Tags + +Tags found in Monkey's Audio (APE) information. Only a few common tags are +listed below, but ExifTool will extract any tag found. ExifTool supports +APEv1 and APEv2 tags, as well as ID3 information in APE files, and will also +read APE metadata from MP3 and MPC files. + + Tag ID Tag Name Writable + ------ -------- -------- + 'Album' Album no + 'Artist' Artist no + 'DURATION' Duration no + 'Genre' Genre no + 'Title' Title no + 'Tool Name' ToolName no + 'Tool Version' ToolVersion no + 'Track' Track no + 'Year' Year no + +=head3 APE NewHeader Tags + +APE MAC audio header for version 3.98 or later. + + Index2 Tag Name Writable + ------ -------- -------- + 0 CompressionLevel no + 2 BlocksPerFrame no + 4 FinalFrameBlocks no + 6 TotalFrames no + 8 BitsPerSample no + 9 Channels no + 10 SampleRate no + +=head3 APE OldHeader Tags + +APE MAC audio header for version 3.97 or earlier. + + Index2 Tag Name Writable + ------ -------- -------- + 0 APEVersion no + 1 CompressionLevel no + 3 Channels no + 4 SampleRate no + 10 TotalFrames no + 12 FinalFrameBlocks no + +=head2 Audible Tags + +ExifTool will extract any information found in the metadata dictionary of +Audible .AA files, even if not listed in the table below. + + Tag ID Tag Name Writable + ------ -------- -------- + '_chapter_count' ChapterCount no + '_cover_art' CoverArt no + 'author' Author no + 'copyright' Copyright no + 'pub_date_start' PublishDateStart no + 'pubdate' PublishDate no + +=head3 Audible tags Tags + +Information found in "tags" atom of Audible M4B audio books. + + Tag ID Tag Name Writable + ------ -------- -------- + 'cvrx' Audible_cvrx Audible cvrx + 'meta' Audible_meta Audible meta + 'tseg' Audible_tseg Audible tseg + +=head3 Audible cvrx Tags + +Audible cover art information in M4B audio books. + + Tag Name Writable + -------- -------- + CoverArt no + CoverArtType no + +=head3 Audible meta Tags + +Information found in Audible M4B "meta" atom. + + Tag ID Tag Name Writable + ------ -------- -------- + 'ALBUMARTIST' AlbumArtist no + 'Album' Album no + 'Artist' Artist no + 'Comment' Comment no + 'Genre' Genre no + 'SUBTITLE' Subtitle no + 'TOOL' CreatorTool no + 'Title' Title no + 'Year' Year no + 'itunesmediatype' iTunesMediaType no + 'track' ChapterName no + +=head3 Audible tseg Tags + + Tag ID Tag Name Writable + ------ -------- -------- + 'meta' Audible_meta2 Audible meta + 'tshd' ChapterNumber no + +=head2 MPC Tags + +Tags used in Musepack (MPC) audio files. ExifTool also extracts ID3 and APE +information from these files. + + Tag ID Tag Name Writable + ------ -------- -------- + 'Bit032-063' TotalFrames no + 'Bit080-081' SampleRate no + 'Bit084-087' Quality no + 'Bit088-093' MaxBand no + 'Bit096-111' ReplayGainTrackPeak no + 'Bit112-127' ReplayGainTrackGain no + 'Bit128-143' ReplayGainAlbumPeak no + 'Bit144-159' ReplayGainAlbumGain no + 'Bit179' FastSeek no + 'Bit191' Gapless no + 'Bit216-223' EncoderVersion no + +=head2 MPEG Tags + +The MPEG format doesn't specify any file-level meta information. In lieu of +this, information is extracted from the first audio and video frame headers +in the file. + +=head3 MPEG Audio Tags + + Tag ID Tag Name Writable + ------ -------- -------- + 'Bit11-12' MPEGAudioVersion no + 'Bit13-14' AudioLayer no + 'Bit16-19' AudioBitrate no + 'Bit20-21' SampleRate no + 'Bit24-25' ChannelMode no + 'Bit26' MSStereo no + 'Bit26-27' ModeExtension no + 'Bit27' IntensityStereo no + 'Bit28' CopyrightFlag no + 'Bit29' OriginalMedia no + 'Bit30-31' Emphasis no + +=head3 MPEG Video Tags + + Tag ID Tag Name Writable + ------ -------- -------- + 'Bit00-11' ImageWidth no + 'Bit12-23' ImageHeight no + 'Bit24-27' AspectRatio no + 'Bit28-31' FrameRate no + 'Bit32-49' VideoBitrate no + +=head3 MPEG Xing Tags + +These tags are extracted from the Xing/Info frame. + + Tag Name Writable + -------- -------- + Encoder no + LameHeader MPEG Lame + LameQuality no + LameVBRQuality no + VBRBytes no + VBRFrames no + VBRScale no + +=head3 MPEG Lame Tags + +Tags extracted from Lame 3.90 or later header. + + Index1 Tag Name Writable + ------ -------- -------- + 9 LameMethod no + 10 LameLowPassFilter no + 20 LameBitrate no + 24 LameStereoMode no + +=head2 M2TS Tags + +The MPEG-2 transport stream is used as a container for many different +audio/video formats (including AVCHD). This table lists information +extracted from M2TS files. + + Tag Name Writable + -------- -------- + AudioStreamType no + Duration no + VideoStreamType no + _AC3 M2TS AC3 + _H264 H264 + +=head3 M2TS AC3 Tags + +Tags extracted from AC-3 audio streams. + + Tag Name Writable + -------- -------- + AudioBitrate no + AudioChannels no + AudioSampleRate no + SurroundMode no + +=head2 H264 Tags + +Tags extracted from H.264 video streams. The metadata for AVCHD videos is +stored in this stream. + + Tag Name Writable + -------- -------- + ImageHeight no + ImageWidth no + MDPM H264 MDPM + +=head3 H264 MDPM Tags + +The following tags are decoded from the Modified Digital Video Pack Metadata +(MDPM) of the unregistered user data with UUID +17ee8c60f84d11d98cd60800200c9a66 in the H.264 Supplemental Enhancement +Information (SEI). I<[Yes, this description is confusing, but nothing +compared to the challenge of actually decoding the data!]> This information +may exist at regular intervals through the entire video, but only the first +occurrence is extracted unless the ExtractEmbedded (-ee) option is used (in +which case subsequent occurrences are extracted as sub-documents). + + Tag ID Tag Name Writable + ------ -------- -------- + 0x0013 TimeCode no + 0x0018 DateTimeOriginal no + 0x0070 Camera1 H264 Camera1 + 0x0071 Camera2 H264 Camera2 + 0x007f Shutter H264 Shutter + 0x00a0 ExposureTime no + 0x00a1 FNumber no + 0x00a2 ExposureProgram no + 0x00a3 BrightnessValue no + 0x00a4 ExposureCompensation no + 0x00a5 MaxApertureValue no + 0x00a6 Flash no + 0x00a7 CustomRendered no + 0x00a8 WhiteBalance no + 0x00a9 FocalLengthIn35mmFormat no + 0x00aa SceneCaptureType no + 0x00b0 GPSVersionID no + 0x00b1 GPSLatitudeRef no + 0x00b2 GPSLatitude no + 0x00b5 GPSLongitudeRef no + 0x00b6 GPSLongitude no + 0x00b9 GPSAltitudeRef no + 0x00ba GPSAltitude no + 0x00bb GPSTimeStamp no + 0x00be GPSStatus no + 0x00bf GPSMeasureMode no + 0x00c0 GPSDOP no + 0x00c1 GPSSpeedRef no + 0x00c2 GPSSpeed no + 0x00c3 GPSTrackRef no + 0x00c4 GPSTrack no + 0x00c5 GPSImgDirectionRef no + 0x00c6 GPSImgDirection no + 0x00c7 GPSMapDatum no + 0x00e0 MakeModel H264 MakeModel + 0x00e1 RecInfo H264 RecInfo + 0x00e4 Model no + 0x00ee FrameInfo H264 FrameInfo + +=head3 H264 Camera1 Tags + + Index1 Tag Name Writable + ------ -------- -------- + 0 ApertureSetting no + 1 Gain no + 1.1 ExposureProgram no + 2.1 WhiteBalance no + 3 Focus no + +=head3 H264 Camera2 Tags + + Index1 Tag Name Writable + ------ -------- -------- + 1 ImageStabilization no + +=head3 H264 Shutter Tags + + Index2 Tag Name Writable + ------ -------- -------- + 1.1 ExposureTime no + +=head3 H264 MakeModel Tags + + Index2 Tag Name Writable + ------ -------- -------- + 0 Make no + +=head3 H264 RecInfo Tags + +Recording information stored by some Canon video cameras. + + Index1 Tag Name Writable + ------ -------- -------- + 0 RecordingMode no + +=head3 H264 FrameInfo Tags + +Frame rate information stored by some Canon video cameras. + + Index1 Tag Name Writable + ------ -------- -------- + 0 CaptureFrameRate no + 1 VideoFrameRate no + +=head2 QuickTime Tags + +The QuickTime format is used for many different types of audio, video and +image files (most notably, MOV/MP4 videos and HEIC/CR3 images). Exiftool +extracts standard meta information a variety of audio, video and image +parameters, as well as proprietary information written by many camera +models. Tags with a question mark after their name are not extracted unless +the Unknown option is set. + +ExifTool currently has a very limited ability to write metadata in +QuickTime-format videos. It can edit/create/delete any XMP tags, but may +only be used to edit certain date/time tags and the video orientation in +native QuickTime metadata. + +According to the specification, many QuickTime date/time tags should be +stored as UTC. Unfortunately, digital cameras often store local time values +instead (presumably because they don't know the time zone). For this +reason, by default ExifTool does not assume a time zone for these values. +However, if the QuickTimeUTC API option is set, then ExifTool will assume +these values are properly stored as UTC, and will convert them to local time +when extracting. + +See +L<http://developer.apple.com/mac/library/documentation/QuickTime/QTFF/QTFFChap1/qtff1.html> +for the official specification. + + Tag ID Tag Name Writable + ------ -------- -------- + 'PICT' PreviewPICT no + '_htc' HTCInfo QuickTime HTCInfo + 'ardt' ARDroneFile no + 'frea' Kodak_frea Kodak frea + 'free' KodakFree Kodak Free + Free? no + 'ftyp' FileType QuickTime FileType + 'junk' Junk? no + 'mdat' MovieData? no + 'mdat-offset' MovieDataOffset no + 'mdat-size' MovieDataSize no + 'meta' Meta QuickTime Meta + 'moof' MovieFragment QuickTime MovieFragment + 'moov' Movie QuickTime Movie + 'pict' PreviewPICT no + 'pnot' Preview QuickTime Preview + 'prrt' ARDroneTelemetry no + 'skip' CanonSkip Canon Skip + Skip? no + 'thum' ThumbnailImage no + 'udat' GPSLog no + 'udta' UserData FLIR UserData + 'uuid' XMP XMP + UUID-PROF QuickTime Profile + UUID-Flip QuickTime Flip + PreviewImage no + UUID-Unknown? no + 'wide' Wide? no + +=head3 QuickTime HTCInfo Tags + +Tags written by some HTC camera phones. + + Tag ID Tag Name Writable + ------ -------- -------- + 'slmt' Unknown_slmt? no + +=head3 QuickTime FileType Tags + + Index4 Tag Name Writable + ------ -------- -------- + 0 MajorBrand no + 1 MinorVersion no + 2 CompatibleBrands no + +=head3 QuickTime Meta Tags + + Tag ID Tag Name Writable + ------ -------- -------- + 'bxml' BinaryXML? no + 'dinf' DataInformation? no + 'free' Free? no + 'hdlr' Handler QuickTime Handler + 'iinf' ItemInformation QuickTime ItemInfo + QuickTime ItemInfo + 'iloc' ItemLocation no + 'ilst' ItemList QuickTime ItemList + 'ipmc' IPMPControl? no + 'ipro' ItemProtection? no + 'iprp' ItemProperties QuickTime ItemProp + 'iref' ItemReference QuickTime ItemRef + 'keys' Keys QuickTime Keys + 'pitm' PrimaryItemReference no + 'xml ' XML XMP XML + +=head3 QuickTime Handler Tags + + Index1 Tag Name Writable + ------ -------- -------- + 4 HandlerClass no + 8 HandlerType no + 12 HandlerVendorID no + 24 HandlerDescription no + +=head3 QuickTime ItemInfo Tags + + Tag ID Tag Name Writable + ------ -------- -------- + 'infe' ItemInfoEntry no + +=head3 QuickTime ItemList Tags + +As well as these tags, the "mdta" handler uses numerical tag ID's which are +added dynamically to this table after processing the Meta Keys information. + + Tag ID Tag Name Writable + ------ -------- -------- + '----' iTunesInfo QuickTime iTunesInfo + '@PST' ParentShortTitle no + '@ppi' ParentProductID no + '@pti' ParentTitle no + '@sti' ShortTitle no + 'AACR' Unknown_AACR? no + 'CDEK' Unknown_CDEK? no + 'CDET' Unknown_CDET? no + 'GUID' GUID no + 'VERS' ProductVersion no + 'aART' AlbumArtist no + 'akID' AppleStoreAccountType no + 'albm' Album no + 'apID' AppleStoreAccount no + 'atID' AlbumTitleID no + 'auth' Author no + 'catg' Category no + 'cnID' AppleStoreCatalogID no + 'covr' CoverArt no + 'cpil' Compilation no + 'cprt' Copyright no + 'desc' Description no + 'disk' DiskNumber no + 'dscp' Description no + 'egid' EpisodeGlobalUniqueID no + 'geID' GenreID no + 'gnre' Genre no + 'grup' Grouping no + 'gshh' GoogleHostHeader no + 'gspm' GooglePingMessage no + 'gspu' GooglePingURL no + 'gssd' GoogleSourceData no + 'gsst' GoogleStartTime no + 'gstd' GoogleTrackDuration no + 'hdvd' HDVideo no + 'itnu' iTunesU no + 'keyw' Keyword no + 'ldes' LongDescription no + 'pcst' Podcast no + 'perf' Performer no + 'pgap' PlayGap no + 'plID' PlayListID no + 'prID' ProductID no + 'purd' PurchaseDate no + 'purl' PodcastURL no + 'rate' RatingPercent no + 'rldt' ReleaseDate no + 'rtng' Rating no + 'sfID' AppleStoreCountry no + 'soaa' SortAlbumArtist no + 'soal' SortAlbum no + 'soar' SortArtist no + 'soco' SortComposer no + 'sonm' SortName no + 'sosn' SortShow no + 'stik' MediaType no + 'titl' Title no + 'tmpo' BeatsPerMinute no + 'trkn' TrackNumber no + 'tven' TVEpisodeID no + 'tves' TVEpisode no + 'tvnn' TVNetworkName no + 'tvsh' TVShow no + 'tvsn' TVSeason no + 'yrrc' Year no + "\xa9ART" Artist no + "\xa9alb" Album no + "\xa9cmt" Comment no + "\xa9com" Composer no + "\xa9cpy" Copyright no + "\xa9day" ContentCreateDate no + "\xa9des" Description no + "\xa9enc" EncodedBy no + "\xa9gen" Genre no + "\xa9grp" Grouping no + "\xa9lyr" Lyrics no + "\xa9nam" Title no + "\xa9nrt" Narrator no + "\xa9pub" Publisher no + "\xa9too" Encoder no + "\xa9trk" Track no + "\xa9wrt" Composer no + +=head3 QuickTime iTunesInfo Tags + +ExifTool will extract any iTunesInfo tags that exist, even if they are not +defined in this table. + + Tag ID Tag Name Writable + ------ -------- -------- + 'DISCNUMBER' DiscNumber no + 'Encoding Params' EncodingParams QuickTime EncodingParams + 'TRACKNUMBER' TrackNumber no + 'iTunEXTC' ContentRating no + 'iTunMOVI' iTunMOVI PLIST + 'iTunNORM' VolumeNormalization no + 'iTunSMPB' iTunSMPB no + 'iTunes_CDDB_1' CDDB1Info no + 'iTunes_CDDB_TrackNumber' CDDBTrackNumber no + 'popularimeter' Popularimeter no + 'tool' iTunTool no + +=head3 QuickTime EncodingParams Tags + + Tag ID Tag Name Writable + ------ -------- -------- + 'abrt' AudioAvailableBitRateRange no + 'acbf' AudioBitRateControlMode no + 'acef' AudioExtendFrequencies no + 'brat' AudioCurrentTargetBitRate no + 'cdcv' AudioComponentVersion no + 'cmnc' AudioAvailableNumberChannels no + 'init' AudioIsInitialized no + 'lmrc' AudioDoesSampleRateConversion no + 'mdel' AudioMinimumDelayMode no + 'mnip' AudioMinimumNumberInputPackets no + 'mnop' AudioMinimumNumberOutputPackets no + 'oppr' AudioOutputPrecedence no + 'pad0' AudioZeroFramesPadded no + 'pakb' AudioMaximumPacketByteSize no + 'pakd' AudioRequiresPacketDescription no + 'pakf' AudioPacketFrameSize no + 'prmm' AudioCodecPrimeMethod no + 'srcq' AudioQualitySetting no + 'tbuf' AudioInputBufferSize no + 'ubuf' AudioUsedInputBufferSize no + 'ursr' AudioUseRecommendedSampleRate no + 'vbrq' AudioVBRQuality no + 'vers' AudioEncodingParamsVersion no + 'vpk?' AudioHasVariablePacketByteSizes no + +=head3 QuickTime ItemProp Tags + + Tag ID Tag Name Writable + ------ -------- -------- + 'ipco' ItemPropertyContainer QuickTime ItemPropCont + 'ipma' ItemPropertyAssociation no + +=head3 QuickTime ItemPropCont Tags + + Tag ID Tag Name Writable + ------ -------- -------- + 'auxC' AuxiliaryImageType no + 'clap' CleanAperture no + 'colr' ICC_Profile ICC_Profile + 'hvcC' HEVCConfiguration? no + 'irot' Rotation no + 'ispe' ImageSpatialExtent no + 'pasp' PixelAspectRatio no + 'pixi' ImagePixelDepth no + 'rloc' RelativeLocation no + +=head3 QuickTime ItemRef Tags + + Tag ID Tag Name Writable + ------ -------- -------- + 'cdsc' ContentDescribes no + +=head3 QuickTime Keys Tags + +This directory contains a list of key names which are used to decode +ItemList tags written by the "mdta" handler. The prefix of +"com.apple.quicktime." has been removed from all TagID's below. + + Tag ID Tag Name Writable + ------ -------- -------- + 'Encoded_With' EncodedWith no + 'album' Album no + 'artist' Artist no + 'artwork' Artwork no + 'author' Author no + 'camera.framereadouttimeinmicroseconds' + FrameReadoutTime no + 'camera.identifier' CameraIdentifier no + 'collection.user' UserCollection no + 'comment' Comment no + 'copyright' Copyright no + 'creationdate' CreationDate no + 'description' Description no + 'detected-face' FaceInfo QuickTime FaceInfo + 'detected-face.bounds' DetectedFaceBounds no + 'detected-face.face-id' DetectedFaceID no + 'detected-face.roll-angle' + DetectedFaceRollAngle no + 'detected-face.yaw-angle' + DetectedFaceYawAngle no + 'direction.facing' CameraDirection no + 'direction.motion' CameraMotion no + 'director' Director no + 'genre' Genre no + 'information' Information no + 'keywords' Keywords no + 'location.ISO6709' GPSCoordinates no + 'location.body' LocationBody no + 'location.date' LocationDate no + 'location.name' LocationName no + 'location.note' LocationNote no + 'location.role' LocationRole no + 'make' Make no + 'model' Model no + 'player.movie.audio.balance' Balance no + 'player.movie.audio.bass' Bass no + 'player.movie.audio.gain' AudioGain no + 'player.movie.audio.mute' Mute no + 'player.movie.audio.pitchshift' PitchShift no + 'player.movie.audio.treble' Trebel no + 'player.movie.visual.brightness' Brightness no + 'player.movie.visual.color' Color no + 'player.movie.visual.contrast' Contrast no + 'player.movie.visual.tint' Tint no + 'player.version' PlayerVersion no + 'producer' Producer no + 'publisher' Publisher no + 'rating.user' UserRating no + 'software' Software no + 'title' Title no + 'version' Version no + 'video-orientation' VideoOrientation no + 'year' Year no + +=head3 QuickTime FaceInfo Tags + + Tag ID Tag Name Writable + ------ -------- -------- + 'crec' FaceRec QuickTime FaceRec + +=head3 QuickTime FaceRec Tags + + Tag ID Tag Name Writable + ------ -------- -------- + 'cits' FaceItem QuickTime Keys + +=head3 QuickTime MovieFragment Tags + + Tag ID Tag Name Writable + ------ -------- -------- + 'traf' TrackFragment QuickTime TrackFragment + +=head3 QuickTime TrackFragment Tags + + Tag ID Tag Name Writable + ------ -------- -------- + [no tags known] + +=head3 QuickTime Movie Tags + + Tag ID Tag Name Writable + ------ -------- -------- + 'cmov' CompressedMovie QuickTime CMovie + 'gps ' GPSDataList? no + 'htka' HTCTrack QuickTime Track + 'iods' InitialObjectDescriptor? no + 'meta' Meta QuickTime Meta + 'mvhd' MovieHeader QuickTime MovieHeader + 'trak' Track QuickTime Track + 'udta' UserData QuickTime UserData + 'uuid' UUID-USMT QuickTime UserMedia + UUID-Canon Canon uuid + UUID-Unknown? no + +=head3 QuickTime CMovie Tags + + Tag ID Tag Name Writable + ------ -------- -------- + 'dcom' Compression no + +=head3 QuickTime Track Tags + + Tag ID Tag Name Writable + ------ -------- -------- + 'mdia' Media QuickTime Media + 'meta' Meta QuickTime Meta + 'tapt' TrackAperture QuickTime TrackAperture + 'tkhd' TrackHeader QuickTime TrackHeader + 'tref' TrackRef QuickTime TrackRef + 'udta' UserData QuickTime UserData + 'uuid' UUID-USMT QuickTime UserMedia + SphericalVideoXML XMP + UUID-Unknown? no + +=head3 QuickTime Media Tags + +MP4 media box. + + Tag ID Tag Name Writable + ------ -------- -------- + 'hdlr' Handler QuickTime Handler + 'mdhd' MediaHeader QuickTime MediaHeader + 'minf' MediaInfo QuickTime MediaInfo + +=head3 QuickTime MediaHeader Tags + + Index4 Tag Name Writable + ------ -------- -------- + 0 MediaHeaderVersion no + 1 MediaCreateDate int32u + 2 MediaModifyDate int32u + 3 MediaTimeScale no + 4 MediaDuration no + 5 MediaLanguageCode no + +=head3 QuickTime MediaInfo Tags + +MP4 media info box. + + Tag ID Tag Name Writable + ------ -------- -------- + 'dinf' DataInfo QuickTime DataInfo + 'gmhd' GenMediaHeader QuickTime GenMediaHeader + 'hdlr' Handler QuickTime Handler + 'hmhd' HintHeader QuickTime HintHeader + 'nmhd' NullMediaHeader? no + 'smhd' AudioHeader QuickTime AudioHeader + 'stbl' SampleTable QuickTime SampleTable + 'vmhd' VideoHeader QuickTime VideoHeader + +=head3 QuickTime DataInfo Tags + +MP4 data information box. + + Tag ID Tag Name Writable + ------ -------- -------- + 'dref' DataRef QuickTime DataRef + +=head3 QuickTime DataRef Tags + +MP4 data reference box. + + Tag ID Tag Name Writable + ------ -------- -------- + "url\0" URL no + 'url ' URL no + 'urn ' URN no + +=head3 QuickTime GenMediaHeader Tags + + Tag ID Tag Name Writable + ------ -------- -------- + 'gmin' GenMediaInfo QuickTime GenMediaInfo + 'text' Text? no + 'tmcd' TimeCode QuickTime TimeCode + +=head3 QuickTime GenMediaInfo Tags + + Index1 Tag Name Writable + ------ -------- -------- + 0 GenMediaVersion no + 1 GenFlags no + 4 GenGraphicsMode no + 6 GenOpColor no + 12 GenBalance no + +=head3 QuickTime TimeCode Tags + + Tag ID Tag Name Writable + ------ -------- -------- + 'tcmi' TCMediaInfo QuickTime TCMediaInfo + +=head3 QuickTime TCMediaInfo Tags + + Index1 Tag Name Writable + ------ -------- -------- + 4 TextFont no + 6 TextFace no + 8 TextSize no + 12 TextColor no + 18 BackgroundColor no + 24 FontName no + +=head3 QuickTime HintHeader Tags + +MP4 hint media header. + + Index2 Tag Name Writable + ------ -------- -------- + 2 MaxPDUSize no + 3 AvgPDUSize no + 4 MaxBitrate no + 6 AvgBitrate no + +=head3 QuickTime AudioHeader Tags + +MP4 audio media header. + + Index2 Tag Name Writable + ------ -------- -------- + 2 Balance no + +=head3 QuickTime SampleTable Tags + +MP4 sample table box. + + Tag ID Tag Name Writable + ------ -------- -------- + 'co64' ChunkOffset64? no + 'cslg' CompositionToDecodeTimelineMapping? no + 'ctts' CompositionTimeToSample? no + 'padb' SamplePaddingBits? no + 'sbgp' SampleToGroup? no + 'sdtp' IdependentAndDisposableSamples? no + 'sgpd' SampleGroupDescription? no + 'stco' ChunkOffset? no + 'stdp' SampleDegradationPriority? no + 'stps' PartialSyncSamples no + 'stsc' SampleToChunk? no + 'stsd' AudioSampleDesc QuickTime AudioSampleDesc + VideoSampleDesc QuickTime ImageDesc + HintSampleDesc QuickTime HintSampleDesc + MetaSampleDesc QuickTime MetaSampleDesc + OtherSampleDesc QuickTime OtherSampleDesc + 'stsh' ShadowSyncSampleTable? no + 'stss' SyncSampleTable? no + 'stsz' SampleSizes? no + 'stts' VideoFrameRate no + TimeToSampleTable? no + 'stz2' CompactSampleSizes? no + 'subs' Sub-sampleInformation? no + +=head3 QuickTime AudioSampleDesc Tags + +MP4 audio sample description. This hybrid atom contains both data and child +atoms. + + ID/Index Tag Name Writable + -------- -------- -------- + 4 AudioFormat no + 20 AudioVendorID no + 24 AudioChannels no + 26 AudioBitsPerSample no + 32 AudioSampleRate no + 'chan' AudioChannelLayout QuickTime ChannelLayout + 'damr' DecodeConfig QuickTime DecodeConfig + 'pinf' PurchaseInfo QuickTime ProtectionInfo + 'sinf' ProtectionInfo QuickTime ProtectionInfo + 'wave' Wave QuickTime Wave + +=head3 QuickTime ChannelLayout Tags + +Audio channel layout. + + Index1 Tag Name Writable + ------ -------- -------- + 4 LayoutFlags no + 6 AudioChannels no + 8 AudioChannelTypes no + 12 NumChannelDescriptions no + 16 Channel1Label no + 20 Channel1Flags no + 24 Channel1Coordinates no + 36 Channel2Label no + 40 Channel2Flags no + 44 Channel2Coordinates no + 56 Channel3Label no + 60 Channel3Flags no + 64 Channel3Coordinates no + 76 Channel4Label no + 80 Channel4Flags no + 84 Channel4Coordinates no + 96 Channel5Label no + 100 Channel5Flags no + 104 Channel5Coordinates no + 116 Channel6Label no + 120 Channel6Flags no + 124 Channel6Coordinates no + 136 Channel7Label no + 140 Channel7Flags no + 144 Channel7Coordinates no + 156 Channel8Label no + 160 Channel8Flags no + 164 Channel8Coordinates no + +=head3 QuickTime DecodeConfig Tags + + Index1 Tag Name Writable + ------ -------- -------- + 0 EncoderVendor no + 4 EncoderVersion no + +=head3 QuickTime ProtectionInfo Tags + +Child atoms found in "sinf" and/or "pinf" atoms. + + Tag ID Tag Name Writable + ------ -------- -------- + 'frma' OriginalFormat no + 'schi' SchemeInfo QuickTime SchemeInfo + 'schm' SchemeType QuickTime SchemeType + +=head3 QuickTime SchemeInfo Tags + + Tag ID Tag Name Writable + ------ -------- -------- + 'cert' Certificate no + 'iviv' InitializationVector no + 'key ' KeyID no + 'name' UserName no + 'righ' Rights QuickTime Rights + 'user' UserID no + +=head3 QuickTime Rights Tags + + Tag ID Tag Name Writable + ------ -------- -------- + 'aver' VersionRestrictions no + 'medi' MediaFlags no + 'mode' ModeFlags no + 'plat' Platform no + 'song' ItemID no + 'tool' ItemTool no + 'tran' TransactionID no + 'veID' ItemVendorID no + +=head3 QuickTime SchemeType Tags + + Index1 Tag Name Writable + ------ -------- -------- + 4 SchemeType no + 8 SchemeVersion no + 10 SchemeURL no + +=head3 QuickTime Wave Tags + + Tag ID Tag Name Writable + ------ -------- -------- + 'frma' PurchaseFileFormat no + +=head3 QuickTime ImageDesc Tags + + ID/Index Tag Name Writable + -------- -------- -------- + 2 CompressorID no + 10 VendorID no + 16 SourceImageWidth no + 17 SourceImageHeight no + 18 XResolution no + 20 YResolution no + 25 CompressorName no + 41 BitDepth no + 'CDI1' CDI1 Canon CDI1 + 'JPEG' JPEGInfo? no + 'avcC' AVCConfiguration? no + 'btrt' BitrateInfo QuickTime Bitrate + 'clap' CleanAperture QuickTime CleanAperture + 'colr' ColorRepresentation no + 'fiel' VideoFieldOrder no + 'gama' Gamma no + 'pasp' PixelAspectRatio no + 'st3d' Stereoscopic3D no + 'sv3d' SphericalVideo QuickTime sv3d + +=head3 QuickTime Bitrate Tags + + Index4 Tag Name Writable + ------ -------- -------- + 0 BufferSize no + 1 MaxBitrate no + 2 AverageBitrate no + +=head3 QuickTime CleanAperture Tags + + Index8 Tag Name Writable + ------ -------- -------- + 0 CleanApertureWidth no + 1 CleanApertureHeight no + 2 CleanApertureOffsetX no + 3 CleanApertureOffsetY no + +=head3 QuickTime sv3d Tags + +Tags defined by the Spherical Video V2 specification. See +L<https://github.com/google/spatial-media/blob/master/docs/spherical-video-v2-rfc.md> +for the specification. + + Tag ID Tag Name Writable + ------ -------- -------- + 'proj' Projection QuickTime proj + 'svhd' MetadataSource no + +=head3 QuickTime proj Tags + + Tag ID Tag Name Writable + ------ -------- -------- + 'cbmp' CubemapProj QuickTime cbmp + 'equi' EquirectangularProj QuickTime equi + 'prhd' ProjectionHeader QuickTime prhd + +=head3 QuickTime cbmp Tags + + Index4 Tag Name Writable + ------ -------- -------- + 1 Layout no + 2 Padding no + +=head3 QuickTime equi Tags + + Index4 Tag Name Writable + ------ -------- -------- + 1 ProjectionBoundsTop no + 2 ProjectionBoundsBottom no + 3 ProjectionBoundsLeft no + 4 ProjectionBoundsRight no + +=head3 QuickTime prhd Tags + + Index4 Tag Name Writable + ------ -------- -------- + 1 PoseYawDegrees no + 2 PosePitchDegrees no + 3 PoseRollDegrees no + +=head3 QuickTime HintSampleDesc Tags + +MP4 hint sample description. + + ID/Index Tag Name Writable + -------- -------- -------- + 4 HintFormat no + 16 HintTrackVersion no + 20 MaxPacketSize no + 'snro' SequenceNumberRandomOffset no + 'tims' RTPTimeScale no + 'tsro' TimestampRandomOffset no + +=head3 QuickTime MetaSampleDesc Tags + +MP4 metadata sample description. + + Tag ID Tag Name Writable + ------ -------- -------- + 0x0004 MetaFormat no + 'btrt' BitrateInfo QuickTime Bitrate + 'keys' Keys QuickTime Keys + +=head3 QuickTime OtherSampleDesc Tags + + Tag ID Tag Name Writable + ------ -------- -------- + 0x0004 OtherFormat no + 'ftab' FontTable no + +=head3 QuickTime VideoHeader Tags + +MP4 video media header. + + Index2 Tag Name Writable + ------ -------- -------- + 2 GraphicsMode no + 3 OpColor no + +=head3 QuickTime TrackAperture Tags + + Tag ID Tag Name Writable + ------ -------- -------- + 'clef' CleanApertureDimensions no + 'enof' EncodedPixelsDimensions no + 'prof' ProductionApertureDimensions no + +=head3 QuickTime TrackHeader Tags + + Index4 Tag Name Writable + ------ -------- -------- + 0 TrackHeaderVersion no + 1 TrackCreateDate int32u + 2 TrackModifyDate int32u + 3 TrackID no + 5 TrackDuration no + 8 TrackLayer no + 9 TrackVolume no + 10 MatrixStructure fixed32s[9] + 19 ImageWidth no + 20 ImageHeight no + +=head3 QuickTime TrackRef Tags + + Tag ID Tag Name Writable + ------ -------- -------- + 'cdsc' ContentDescribes no + 'chap' ChapterListTrackID no + 'mpod' ElementaryStreamTrack no + 'tmcd' TimeCode no + +=head3 QuickTime UserData Tags + +Tag ID's beginning with the copyright symbol (hex 0xa9) are multi-language +text. Alternate language tags are accessed by adding a dash followed by the +language/country code to the tag name. ExifTool will extract any +multi-language user data tags found, even if they don't exist in this table. + + Tag ID Tag Name Writable + ------ -------- -------- + '@sec' SamsungSec Samsung sec + 'AllF' PlayAllFrames no + 'CAME' SerialNumberHash no + 'CNCV' CompressorVersion no + 'CNFV' FirmwareVersion no + 'CNMN' Model no + 'CNOP' CanonCNOP Canon CNOP + 'CNTH' CanonCNTH Canon CNTH + 'DcMD' KodakDcMD Kodak DcMD + 'FFMV' FujiFilmFFMV FujiFilm FFMV + 'FIRM' FirmwareVersion no + "FOV\0" FieldOfView no + 'GPMF' GoProGPMF GoPro GPMF + 'GoPr' GoProType no + 'INFO' SamsungINFO Samsung INFO + 'LEIC' LeicaLEIC Panasonic PANA + 'LENS' LensSerialNumber no + 'LOOP' LoopStyle no + 'Lvlm' LevelMeter? no + 'MMA0' MinoltaMMA0 Minolta MMA + 'MMA1' MinoltaMMA1 Minolta MMA + 'MVTG' FujiFilmMVTG EXIF + 'NCDT' NikonNCDT Nikon NCDT + 'PANA' PanasonicPANA Panasonic PANA + 'PENT' PentaxPENT Pentax PENT + 'PXMN' MakerNotePentax5b Pentax + MakerNotePentax5c Pentax + MakerNotePentaxUnknown no + 'PXTH' PentaxPreview Pentax PXTH + 'QVMI' CasioQVMI EXIF + 'RMKN' RicohRMKN EXIF + 'RTHU' PreviewImage no + 'SDLN' PlayMode no + 'SNum' SerialNumber no + 'SelO' PlaySelection no + 'TAGS' FujiFilmTags FujiFilm MOV + KodakTags Kodak MOV + KonicaMinoltaTags Minolta MOV1 + MinoltaTags Minolta MOV2 + NikonTags Nikon MOV + OlympusTags1 Olympus MOV1 + OlympusTags2 Olympus MOV2 + OlympusTags3 Olympus MP4 + OlympusTags4 Olympus MOV3 + PentaxTags Pentax MOV + SamsungTags Samsung MP4 + SanyoMOV Sanyo MOV + SanyoMP4 Sanyo MP4 + UnknownTags? no + 'TTMD' TomTomMetaData QuickTime TomTom + 'WLOC' WindowLocation no + 'XMP_' XMP XMP + 'Xtra' MicrosoftXtra Microsoft Xtra + '_cx_' CX? no + '_cy_' CY? no + '_yaw' Yaw no + 'albm' Album no + 'albr' AlbumArtist no + 'angl' CameraAngle no + 'apmd' ApertureMode no + 'auth' Author no + 'ccid' ContentID no + 'cdis' ContentDistributorID no + 'chpl' ChapterList no + 'clfn' ClipFileName no + 'clid' ClipID no + 'clsf' Classification no + 'cmid' CameraID no + 'cmnm' Model no + 'coll' CollectionName no + 'cprt' Copyright no + 'cver' CodeVersion no + 'cvru' CoverURI no + 'date' DateTimeOriginal no + 'dscp' Description no + 'gnre' Genre no + 'hinf' HintTrackInfo QuickTime HintTrackInfo + 'hinv' HintVersion no + 'hnti' HintInfo QuickTime HintInfo + 'htcb' HTCBinary QuickTime HTCBinary + 'icnu' IconURI no + 'infu' InfoURL no + 'kgtt' TrackType no + 'kywd' Keywords no + 'loci' LocationInformation no + 'lrcu' LyricsURI no + 'lvlm' LevelMeter? no + 'manu' Make no + 'meta' Meta QuickTime Meta + 'modl' Model no + 'name' Name no + 'perf' Performer no + 'pose' pose Kodak pose + 'ptch' Pitch no + 'ptv ' PrintToVideo QuickTime Video + 'rads' Rads? no + 'reel' ReelName no + 'roll' Roll no + 'rtng' Rating no + 'scen' Scene no + 'scrn' OlympusPreview Olympus scrn + 'shot' ShotName no + 'slno' SerialNumber no + 'smta' SamsungSmta Samsung smta + 'tags' Audible_tags Audible tags + 'thmb' MakerNotePentax5a Pentax + OlympusThumbnail Olympus thmb + ThumbnailImage no + ThumbnailPNG no + UnknownThumbnail no + 'titl' Title no + 'urat' UserRating no + 'vndr' Vendor no + 'yrrc' Year no + "\xa9ART" Artist no + "\xa9TSC" StartTimeScale no + "\xa9TSZ" StartTimeSampleSize no + "\xa9alb" Album no + "\xa9arg" Arranger no + "\xa9ark" ArrangerKeywords no + "\xa9cmt" Comment no + "\xa9cok" ComposerKeywords no + "\xa9com" Composer no + "\xa9cpy" Copyright no + "\xa9day" ContentCreateDate no + "\xa9dir" Director no + "\xa9ed1" Edit1 no + "\xa9ed2" Edit2 no + "\xa9ed3" Edit3 no + "\xa9ed4" Edit4 no + "\xa9ed5" Edit5 no + "\xa9ed6" Edit6 no + "\xa9ed7" Edit7 no + "\xa9ed8" Edit8 no + "\xa9ed9" Edit9 no + "\xa9enc" EncoderID no + "\xa9fmt" Format no + "\xa9fpt" Pitch no + "\xa9frl" Roll no + "\xa9fyw" Yaw no + "\xa9gen" Genre no + "\xa9gpt" CameraPitch no + "\xa9grl" CameraRoll no + "\xa9grp" Grouping no + "\xa9gyw" CameraYaw no + "\xa9inf" Information no + "\xa9isr" ISRCCode no + "\xa9lab" RecordLabelName no + "\xa9lal" RecordLabelURL no + "\xa9lyr" Lyrics no + "\xa9mak" Make no + "\xa9mal" MakerURL no + "\xa9mdl" Model no + "\xa9mod" Model no + "\xa9nam" Title no + "\xa9pdk" ProducerKeywords no + "\xa9phg" RecordingCopyright no + "\xa9prd" Producer no + "\xa9prf" Performers no + "\xa9prk" PerformerKeywords no + "\xa9prl" PerformerURL no + "\xa9req" Requirements no + "\xa9snk" SubtitleKeywords no + "\xa9snm" Subtitle no + "\xa9src" SourceCredits no + "\xa9swf" SongWriter no + "\xa9swk" SongWriterKeywords no + "\xa9swr" SoftwareVersion no + "\xa9too" Encoder no + "\xa9trk" Track no + "\xa9wrt" Composer no + "\xa9xsp" SpeedX no + "\xa9xyz" GPSCoordinates no + "\xa9ysp" SpeedY no + "\xa9zsp" SpeedZ no + +=head3 QuickTime TomTom Tags + +Tags found in TomTom Bandit Action Cam MP4 videos. + + Tag ID Tag Name Writable + ------ -------- -------- + 'TTAD' TomTomAD QuickTime Stream + 'TTHL' TomTomHL? no + 'TTID' TomTomID no + 'TTVD' TomTomVD no + 'TTVI' TomTomVI? no + +=head3 QuickTime Stream Tags + +Timed metadata extracted from QuickTime movie data and some AVI videos when +the ExtractEmbedded option is used. + + Tag Name Writable + -------- -------- + Accelerometer no + AngularVelocity no + CTMD Canon CTMD + CameraDateTime no + FrameNumber no + GPSAltitude no + GPSDOP no + GPSDateTime no + GPSLatitude no + GPSLongitude no + GPSSatellites no + GPSSpeed no + GPSSpeedRef no + GPSTimeStamp no + GPSTrack no + GPSTrackRef no + INSV QuickTime INSV_MakerNotes + JpgFromRaw no + PreviewInfo QuickTime PreviewInfo + RVMI_gReV QuickTime RVMI_gReV + RVMI_sReV QuickTime RVMI_sReV + RawGSensor no + SampleDuration no + SampleTime no + Text no + TimeCode no + Unknown00? no + Unknown01? no + Unknown02? no + Unknown03? no + UserLabel no + camm0 QuickTime camm0 + camm1 QuickTime camm1 + camm2 QuickTime camm2 + camm3 QuickTime camm3 + camm4 QuickTime camm4 + camm5 QuickTime camm5 + camm6 QuickTime camm6 + camm7 QuickTime camm7 + fdsc GoPro fdsc + gpmd GoPro GPMF + mebx QuickTime Keys + rtmd Sony rtmd + tx3g QuickTime tx3g + +=head3 QuickTime INSV_MakerNotes Tags + + Tag ID Tag Name Writable + ------ -------- -------- + 0x000a SerialNumber no + 0x0012 Model no + 0x001a Firmware no + 0x002a Parameters no + +=head3 QuickTime PreviewInfo Tags + +Preview stored by TomTom Bandit ActionCam. + + Index1 Tag Name Writable + ------ -------- -------- + 8 PreviewImage no + +=head3 QuickTime RVMI_gReV Tags + +GPS information extracted from the RVMI box of MOV videos. + + Index1 Tag Name Writable + ------ -------- -------- + 4 GPSLatitude no + 8 GPSLongitude no + 16 GPSSpeed no + 18 GPSTrack no + +=head3 QuickTime RVMI_sReV Tags + +G-sensor information extracted from the RVMI box of MOV videos. + + Index1 Tag Name Writable + ------ -------- -------- + 4 GSensor no + +=head3 QuickTime camm0 Tags + +The camm0 through camm7 tables define tags extracted from the Google Street +View Camera Motion Metadata of MP4 videos. See +L<https://developers.google.com/streetview/publish/camm-spec> for the +specification. + + Index1 Tag Name Writable + ------ -------- -------- + 4 AngleAxis no + +=head3 QuickTime camm1 Tags + + Index1 Tag Name Writable + ------ -------- -------- + 4 PixelExposureTime no + 8 RollingShutterSkewTime no + +=head3 QuickTime camm2 Tags + + Index1 Tag Name Writable + ------ -------- -------- + 4 AngularVelocity no + +=head3 QuickTime camm3 Tags + + Index1 Tag Name Writable + ------ -------- -------- + 4 Acceleration no + +=head3 QuickTime camm4 Tags + + Index1 Tag Name Writable + ------ -------- -------- + 4 Position no + +=head3 QuickTime camm5 Tags + + Index1 Tag Name Writable + ------ -------- -------- + 4 GPSLatitude no + 12 GPSLongitude no + 20 GPSAltitude no + +=head3 QuickTime camm6 Tags + + Index1 Tag Name Writable + ------ -------- -------- + 4 GPSDateTime no + 12 GPSMeasureMode no + 16 GPSLatitude no + 24 GPSLongitude no + 32 GPSAltitude no + 36 GPSHorizontalAccuracy no + 40 GPSVerticalAccuracy no + 44 GPSVelocityEast no + 48 GPSVelocityNorth no + 52 GPSVelocityUp no + 56 GPSSpeedAccuracy no + +=head3 QuickTime camm7 Tags + + Index1 Tag Name Writable + ------ -------- -------- + 4 MagneticField no + +=head3 QuickTime tx3g Tags + +Tags extracted from the tx3g sbtl timed metadata of Yuneec drones. + + Tag ID Tag Name Writable + ------ -------- -------- + 'Alt' GPSAltitude no + 'GimPitch' GimbalPitch no + 'GimRoll' GimbalRoll no + 'GimYaw' GimbalYaw no + 'Lat' GPSLatitude no + 'Lon' GPSLongitude no + 'Pitch' Pitch no + 'Roll' Roll no + 'Yaw' Yaw no + +=head3 QuickTime HintTrackInfo Tags + + Tag ID Tag Name Writable + ------ -------- -------- + 'dimm' ImmediateDataBytes no + 'dmax' LargestPacketDuration no + 'dmed' MediaTrackBytes no + 'drep' RepeatedDataBytes no + 'maxr' MaxDataRate no + 'npck' NumPackets no + 'nump' NumPackets no + 'payt' PayloadType no + 'pmax' LargestPacketSize no + 'tmax' MaxTransmissionTime no + 'tmin' MinTransmissionTime no + 'totl' TotalBytes no + 'tpaY' TotalBytesNoRTPHeaders no + 'tpay' TotalBytesNoRTPHeaders no + 'tpyl' TotalBytesNoRTPHeaders no + 'trpY' TotalBytes no + 'trpy' TotalBytes no + +=head3 QuickTime HintInfo Tags + + Tag ID Tag Name Writable + ------ -------- -------- + 'rtp ' RealtimeStreamingProtocol no + 'sdp ' StreamingDataProtocol no + +=head3 QuickTime HTCBinary Tags + + Index4 Tag Name Writable + ------ -------- -------- + [no tags known] + +=head3 QuickTime Video Tags + + Index1 Tag Name Writable + ------ -------- -------- + 0 DisplaySize no + 6 SlideShow no + +=head3 QuickTime UserMedia Tags + + Tag ID Tag Name Writable + ------ -------- -------- + 'MTDT' MetaData QuickTime MetaData + +=head3 QuickTime MetaData Tags + + Tag ID Tag Name Writable + ------ -------- -------- + 0x0001 Title no + 0x0003 ProductionDate no + 0x0004 Software no + 0x0005 Product no + 0x000a TrackProperty no + 0x000b TimeZone no + 0x000c ModifyDate no + +=head3 QuickTime MovieHeader Tags + + Index4 Tag Name Writable + ------ -------- -------- + 0 MovieHeaderVersion no + 1 CreateDate int32u + 2 ModifyDate int32u + 3 TimeScale no + 4 Duration no + 5 PreferredRate no + 6 PreferredVolume no + 9 MatrixStructure no + 18 PreviewTime no + 19 PreviewDuration no + 20 PosterTime no + 21 SelectionTime no + 22 SelectionDuration no + 23 CurrentTime no + 24 NextTrackID no + +=head3 QuickTime Preview Tags + + Index2 Tag Name Writable + ------ -------- -------- + 0 PreviewDate int32u + 2 PreviewVersion no + 3 PreviewAtomType no + 5 PreviewAtomIndex no + +=head3 QuickTime Profile Tags + + Tag ID Tag Name Writable + ------ -------- -------- + 'APRF' AudioProfile QuickTime AudioProf + 'FPRF' FileGlobalProfile QuickTime FileProf + 'OLYM' OlympusOLYM Olympus OLYM + 'VPRF' VideoProfile QuickTime VideoProf + +=head3 QuickTime AudioProf Tags + + Index4 Tag Name Writable + ------ -------- -------- + 0 AudioProfileVersion? no + 1 AudioTrackID no + 2 AudioCodec no + 3 AudioCodecInfo? no + 4 AudioAttributes no + 5 AudioAvgBitrate no + 6 AudioMaxBitrate no + 7 AudioSampleRate no + 8 AudioChannels no + +=head3 QuickTime FileProf Tags + + Index4 Tag Name Writable + ------ -------- -------- + 0 FileProfileVersion? no + 1 FileFunctionFlags no + +=head3 QuickTime VideoProf Tags + + Index4 Tag Name Writable + ------ -------- -------- + 0 VideoProfileVersion? no + 1 VideoTrackID no + 2 VideoCodec no + 3 VideoCodecInfo? no + 4 VideoAttributes no + 5 VideoAvgBitrate no + 6 VideoMaxBitrate no + 7 VideoAvgFrameRate no + 8 VideoMaxFrameRate no + 9 VideoSize no + 10 PixelAspectRatio no + +=head3 QuickTime Flip Tags + +Found in MP4 files from Flip Video cameras. + + Index4 Tag Name Writable + ------ -------- -------- + 1 PreviewImageWidth no + 2 PreviewImageHeight no + 13 PreviewImageLength no + 14 SerialNumber no + 28 PreviewImage no + +=head3 QuickTime ImageFile Tags + +Tags used in QTIF QuickTime Image Files. + + Tag ID Tag Name Writable + ------ -------- -------- + 'idat' ImageData no + 'idsc' ImageDescription QuickTime ImageDesc + 'iicc' ICC_Profile ICC_Profile + +=head2 PLIST Tags + +Apple Property List tags. ExifTool reads both XML and binary-format PLIST +files, and will extract any existing tags even if they aren't listed below. +These tags belong to the family 0 "PLIST" group, but family 1 group may be +either "XML" or "PLIST" depending on whether the format is XML or binary. + + Tag ID Tag Name Writable + ------ -------- -------- + 'MetaDataList//DateTimeOriginal' + DateTimeOriginal no + 'MetaDataList//Duration' Duration no + 'MetaDataList//Geolocation/Latitude' + GPSLatitude no + 'MetaDataList//Geolocation/Longitude' + GPSLongitude no + 'MetaDataList//Geolocation/MapDatum' + GPSMapDatum no + 'XMLFileType' XMLFileType no + 'cast//name' Cast no+ + 'codirectors//name' Codirectors no+ + 'directors//name' Directors no+ + 'producers//name' Producers no+ + 'screenwriters//name' Screenwriters no+ + 'studio//name' Studio no+ + +=head2 Matroska Tags + +The following tags are extracted from Matroska multimedia container files. +This container format is used by file types such as MKA, MKV, MKS and WEBM. +For speed, ExifTool extracts tags only up to the first Cluster unless the +Verbose (-v) or Unknown = 2 (-U) option is used. See +L<http://www.matroska.org/technical/specs/index.html> for the official +Matroska specification. + + Tag ID Tag Name Writable + ------ -------- -------- + 0x0000 ChapterDisplay Matroska + 0x0003 TrackType no + 0x0005 ChapterString no + 0x0006 VideoCodecID no + AudioCodecID no + CodecID no + 0x0008 TrackDefault no + 0x0009 ChapterTrackNumber? no + 0x000e Slices Matroska + 0x000f ChapterTrack Matroska + 0x0011 ChapterTimeStart no + 0x0012 ChapterTimeEnd no + 0x0016 CueRefTime? no + 0x0017 CueRefCluster? no + 0x0018 ChapterFlagHidden? no + 0x001a VideoScanType no + 0x001b BlockDuration? no + 0x001c TrackLacing? no + 0x001f AudioChannels no + 0x0020 BlockGroup Matroska + 0x0021 Block? no + 0x0022 BlockVirtual? no + 0x0023 SimpleBlock? no + 0x0024 CodecState? no + 0x0025 BlockAdditional? no + 0x0026 BlockMore Matroska + 0x0027 Position no + 0x002a CodecDecodeAll no + 0x002b PrevSize no + 0x002e TrackEntry Matroska + 0x002f EncryptedBlock? no + 0x0030 ImageWidth no + 0x0033 CueTime? no + 0x0035 AudioSampleRate no + 0x0036 ChapterAtom Matroska + 0x0037 CueTrackPositions Matroska + 0x0039 TrackUsed no + 0x003a ImageHeight no + 0x003b CuePoint Matroska + 0x003f CRC-32? no + 0x004b BlockAdditionalID? no + 0x004c LaceNumber? no + 0x004d FrameNumber? no + 0x004e Delay? no + 0x004f ClusterDuration? no + 0x0057 TrackNumber no + 0x005b CueReference Matroska + 0x0060 Video Matroska + 0x0061 Audio Matroska + 0x0067 TimeCode? no + 0x0068 TimeSlice Matroska + 0x006a CueCodecState? no + 0x006b CueRefCodecState? no + 0x006c Void? no + 0x006e BlockAddID? no + 0x0071 CueClusterPosition? no + 0x0077 CueTrack? no + 0x007a ReferencePriority? no + 0x007b ReferenceBlock? no + 0x007d ReferenceVirtual? no + 0x0254 ContentCompressionAlgorithm no + 0x0255 ContentCompressionSettings? no + 0x0282 DocType no + 0x0285 DocTypeReadVersion no + 0x0286 EBMLVersion no + 0x0287 DocTypeVersion no + 0x02f2 EBMLMaxIDLength? no + 0x02f3 EBMLMaxSizeLength? no + 0x02f7 EBMLReadVersion no + 0x037c ChapterLanguage no + 0x037e ChapterCountry no + 0x0444 SegmentFamily? no + 0x0461 DateTimeOriginal no + 0x047a TagLanguage no + 0x0484 TagDefault no + 0x0485 TagBinary no + 0x0487 TagString no + 0x0489 Duration no + 0x050d ChapterProcessPrivate? no + 0x0598 ChapterFlagEnabled? no + 0x05a3 TagName no + 0x05b9 EditionEntry Matroska + 0x05bc EditionUID? no + 0x05bd EditionFlagHidden? no + 0x05db EditionFlagDefault? no + 0x05dd EditionFlagOrdered? no + 0x065c AttachedFileData no + 0x0660 AttachedFileMIMEType no + 0x066e AttachedFileName no + 0x0675 AttachedFileReferral? no + 0x067e AttachedFileDescription no + 0x06ae AttachedFileUID no + 0x07e1 ContentEncryptionAlgorithm no + 0x07e2 ContentEncryptionKeyID? no + 0x07e3 ContentSignature? no + 0x07e4 ContentSignatureKeyID? no + 0x07e5 ContentSignatureAlgorithm no + 0x07e6 ContentSignatureHashAlgorithm no + 0x0d80 MuxingApp no + 0x0dbb Seek Matroska + 0x1031 ContentEncodingOrder? no + 0x1032 ContentEncodingScope? no + 0x1033 ContentEncodingType no + 0x1034 ContentCompression Matroska + 0x1035 ContentEncryption Matroska + 0x135f CueRefNumber? no + 0x136e TrackName no + 0x1378 CueBlockNumber? no + 0x137f TrackOffset? no + 0x13ab SeekID? no + 0x13ac SeekPosition? no + 0x13b8 Stereo3DMode no + 0x14aa CropBottom no + 0x14b0 DisplayWidth no + 0x14b2 DisplayUnit no + 0x14b3 AspectRatioType no + 0x14ba DisplayHeight no + 0x14bb CropTop no + 0x14cc CropLeft no + 0x14dd CropRight no + 0x15aa TrackForced no + 0x15ee MaxBlockAdditionID? no + 0x1741 WritingApp no + 0x1854 SilentTracks Matroska + 0x18d7 SilentTrackNumber no + 0x21a7 AttachedFile Matroska + 0x2240 ContentEncoding Matroska + 0x2264 AudioBitsPerSample no + 0x23a2 CodecPrivate? no + 0x23c0 Targets Matroska + 0x23c3 ChapterPhysicalEquivalent no + 0x23c4 TagChapterUID? no + 0x23c5 TagTrackUID? no + 0x23c6 TagAttachmentUID? no + 0x23c9 TagEditionUID? no + 0x23ca TargetType no + 0x2532 SignedElement? no + 0x2624 TrackTranslate Matroska + 0x26a5 TrackTranslateTrackID? no + 0x26bf TrackTranslateCodec no + 0x26fc TrackTranslateEditionUID? no + 0x27c8 SimpleTag Matroska + 0x28ca TargetTypeValue no + 0x2911 ChapterProcessCommand Matroska + 0x2922 ChapterProcessTime? no + 0x2924 ChapterTranslate Matroska + 0x2933 ChapterProcessData? no + 0x2944 ChapterProcess Matroska + 0x2955 ChapterProcessCodecID? no + 0x29a5 ChapterTranslateID? no + 0x29bf ChapterTranslateCodec no + 0x29fc ChapterTranslateEditionUID? no + 0x2d80 ContentEncodings Matroska + 0x2de7 MinCache? no + 0x2df8 MaxCache? no + 0x2e67 ChapterSegmentUID? no + 0x2ebc ChapterSegmentEditionUID? no + 0x2fab TrackOverlay? no + 0x3373 Tag Matroska + 0x3384 SegmentFileName no + 0x33a4 SegmentUID? no + 0x33c4 ChapterUID? no + 0x33c5 TrackUID? no + 0x3446 TrackAttachmentUID no + 0x35a1 BlockAdditions Matroska + 0x38b5 OutputAudioSampleRate no + 0x3ba9 Title no + 0x3d7b ChannelPositions? no + 0x3e5b SignatureElements Matroska + 0x3e7b SignatureElementList Matroska + 0x3e8a SignatureAlgo no + 0x3e9a SignatureHash no + 0x3ea5 SignaturePublicKey? no + 0x3eb5 Signature? no + 0x7670 Projection Matroska Projection + 0x2b59c TrackLanguage no + 0x3314f TrackTimecodeScale no + 0x383e3 FrameRate no + 0x3e383 VideoFrameRate no + DefaultDuration no + 0x58688 VideoCodecName no + AudioCodecName no + CodecName no + 0x6b240 CodecDownloadURL no + 0xad7b1 TimecodeScale no + 0xeb524 ColorSpace? no + 0xfb523 Gamma no + 0x1a9697 CodecSettings no + 0x1b4040 CodecInfoURL no + 0x1c83ab PrevFileName no + 0x1cb923 PrevUID? no + 0x1e83bb NextFileName no + 0x1eb923 NextUID? no + 0x43a770 Chapters Matroska + 0x14d9b74 SeekHead Matroska + 0x254c367 Tags Matroska + 0x549a966 Info Matroska + 0x654ae6b Tracks Matroska + 0x8538067 SegmentHeader Matroska + 0x941a469 Attachments Matroska + 0xa45dfa3 EBMLHeader Matroska + 0xb538667 SignatureSlot Matroska + 0xc53bb6b Cues Matroska + 0xf43b675 Cluster Matroska + +=head3 Matroska Projection Tags + +Projection tags defined by the Spherical Video V2 specification. See +L<https://github.com/google/spatial-media/blob/master/docs/spherical-video-v2-rfc.md> +for the specification. + + Tag ID Tag Name Writable + ------ -------- -------- + 0x7671 ProjectionType no + 0x7672 EquirectangularProj QuickTime equi + CubemapProj QuickTime cbmp + 0x7673 ProjectionPosYaw no + 0x7674 ProjectionPosPitch no + 0x7675 ProjectionPosRoll no + +=head2 MOI Tags + +MOI files store information about associated MOD or TOD files, and are +written by some JVC, Canon and Panasonic camcorders. + + Index1 Tag Name Writable + ------ -------- -------- + 0 MOIVersion no + 6 DateTimeOriginal no + 14 Duration no + 128 AspectRatio no + 132 AudioCodec no + 134 AudioBitrate no + 218 VideoBitrate no + +=head2 MXF Tags + +Tags extracted from Material Exchange Format files. Tag ID's are not listed +because they are bulky 16-byte binary values. + + Tag Name Writable + -------- -------- + AAFManufacturerID? no + AES3PCMDescriptor MXF + AFDAndBarData? no + AGICOAID? no + AICI? no + AIFCSummary? no + ANCPacketCount no + ANCPayloadByteArray no + ANCPayloadSampleCoding no + ANCPayloadSampleCount no + ANCWrappingType no + Abstract no + Abstract no + AccountingReferenceNumber no + ActiveFormatDescriptor no + ActiveLinesperFrame no + ActiveSamplesperLine no + ActiveState no + Ad-ID? no + Address MXF + AddressLine no + AddressLine no + AddressNameValueSets? no + AddressSets? no + AdvertisingMaterialReference no + AestheticValue no + AlphaMaximumRef no + AlphaMinimumRef no + AlphaSampleDepth no + AlphaTransparency no + AlternateName no + AlternateName no + Alternates? no + AnalogDataCodingKind no + AnalogMetadataCarrier no + AnalogMonitoringAndControlCodingKind no + AnalogSystem no + AnalogVideoSystemName no + AnalogVideoSystemName? no + AnamorphicLensCharacteristic no + AnchorOffset no + AncillaryResourceID? no + AngleToNorth no + AngularUnitKind no + Annotation? no + Annotation MXF + AnnotationCueWordsSet? no + AnnotationDescription no + AnnotationDescription no + AnnotationKind no + AnnotationKind no + AnnotationParticipantSets? no + AnnotationSets? no + AnnotationSynopsis no + AnnotationSynopsis no + ApplicationEnvironmentID no + ApplicationInformationArray? no + ApplicationName no + ApplicationName no + ApplicationPlatform no + ApplicationPlatform no + ApplicationPlug-InBatch? no + ApplicationPlug-InInstanceID? no + ApplicationProductID? no + ApplicationScheme? no + ApplicationSchemeBatch? no + ApplicationSupplierName no + ApplicationSupplierName no + ApplicationVersionNumber no + ApplicationVersionString no + ApplicationVersionString no + ApproximateImageContainerSize no + ArchiveID no + AssetValue no + AssignedCategoryName no + AssignedCategoryName no + AssignedCategoryValue no + AssignedCategoryValue no + AssociatedMetadataDefinition? no + AstronomicalBodyName no + AstronomicalBodyName no + AudienceAppreciation no + AudienceRating no + AudienceReach no + AudienceShare no + AudioAverageBitrate no + AudioCodingSchemeCode no + AudioCodingSchemeID? no + AudioCodingSchemeName no + AudioCompressionAlgorithm no + AudioDeviceKind no + AudioDeviceParameter no + AudioDeviceParameterSetting no + AudioEnhancementOrModificationDescription no + AudioFirstMix-DownProcess no + AudioFixedBitrateFlag no + AudioMonoChannelCount no + AudioNoiseReductionAlgorithm no + AudioReferenceLevel no + AudioReferenceLevel no + AudioSampleRate no + AudioSampleRate no + AudioStereoChannelCount no + AudioWatermarkKind no + AuthenticationFlag no + AuxiliaryBitsMode no + AvailableRepresentations? no + AverageBytesPerSecond no + Award MXF + AwardCategory no + AwardCategory no + AwardName no + AwardName no + AwardParticipantSets? no + AwardSets? no + BICI? no + BackgroundMusicFlag no + BankDetailsSet? no + BeginAnchor no + BeginAnchor no + BextCodingHistory no + BextCodingHistory no + Bitrate no + BitsPerAudioSample no + BitsPerPixel no + BitsPerPixel no + BitsPerSample no + BlackReferenceLevel no + BlockAlign no + BlockContinuityCount no + BlockStartOffset no + BoundingRectangle? no + BrandMainTitle no + BrandMainTitle no + BrandOriginalTitle no + BrandOriginalTitle no + Branding MXF + BrandingSets? no + BroadcastChannel no + BroadcastDate no + BroadcastMediumCode no + BroadcastMediumKind no + BroadcastOrganizationName no + BroadcastOrganizationName no + BroadcastRegion no + BroadcastRegion no + BroadcastServiceName no + BroadcastTime no + BroadcasterRightsToCopy no + BufferDelay? no + BuildingName no + BuildingName no + Bypass no + BypassOverride no + ByteOffset no + ByteOrder no + CBEStartOffset no + CDCIEssenceDescriptor MXF + CISACLegalEntityID? no + CaptionDescription MXF + CaptionDescriptionSets? no + CaptionKind no + CaptionKind no + CaptionTitles no + CaptionsDescriptionParticipantSets? no + CaptionsViaTeletext no + CaptureAspectRatio no + CaptureFilmFrameRate no + CaptureGammaEquation no + CaptureGammaEquation no + CaptureGammaEquation? no + CatalogDataStatus no + CatalogDataStatus no + CatalogPrefixNumber no + CatalogingSystemName no + CentralTelephoneNumber no + ChannelAssignment? no + ChannelCount no + ChannelHandle no + ChannelID no + ChannelIDs no + ChannelStatusMode no + CipherAlgorithm? no + CipherAlgorithmAES128CBC? no + Citizenship no + Citizenship no + CityName no + CityName no + ClassDefinitions? no + Classification MXF + ClassificationAndMarkingSystem no + ClassificationComment no + ClassificationComment no + ClassificationNameValueSets? no + ClassificationReason no + ClassificationSets? no + ClassifiedBy no + ClassifyingCountryCode no + ClipCreationDateTime no + ClipFramework MXF + ClipID no + ClipIDArray? no + ClipKind no + ClipNumber no + ClipNumber no + ClipShotSets? no + CloneCount no + ClosedBodyPartition? no + ClosedCaptionSubtitlesFlag no + ClosedCompleteBodyPartition? no + ClosedCompleteHeader MXF Header + ClosedGOPIndicator no + ClosedHeader MXF Header + CodecDefinition? no + CodecDefinition? no + CodecDefinitions? no + CodecEssenceDescriptor? no + CodecEssenceKinds? no + CodedContentScanningKind no + CodingLawKind no + CodingLawName no + CodingStyleDefault? no + CollectionName no + CollectionName no + ColorDescriptor no + ColorDescriptor no + ColorFieldCode no + ColorPrimaries no + ColorPrimaries? no + ColorRangeLevels no + ColorSiting no + ColorimetryCode no + ColorimetryCode? no + CommunicationSets? no + Communications MXF + CompleteFooter? no + ComponentAttributes? no + ComponentDataDefinition no + ComponentDepth no + ComponentKLVData? no + ComponentMaximumRef no + ComponentMinimumRef no + ComponentUserComments? no + ComponentsInSequence? no + CompositionRendering? no + ComputedKeyData no + ComputedKeyFrames no + ComputedKeySounds no + ComputedKeywords no + ComputedKeywords no + ComputedObjectKind no + ComputedObjectKind no + ComputedStratumKind no + ConstantBPictureFlag no + ConsumerRightsToCopy no + ContactDepartmentName no + ContactDepartmentName no + ContactID? no + ContactKind no + ContactKind no + ContactNameValueSets? no + ContactsList MXF + ContactsListSet? no + ContainerDefinitions? no + ContainerLastModifyDate no + ContainerVersion no + ContentClassification no + ContentClassification no + ContentCodingSystem no + ContentMaturityDescription no + ContentMaturityGraphic no + ContentMaturityRating no + ContentPackageIndexArray? no + ContentPackageMetadataLink no + ContentStorage? no + ContentStorageSet MXF + ContentValue no + ContextDescription no + ContiguousDataFlag no + Contract MXF + ContractClauseDescription no + ContractClauseDescription no + ContractDateTime no + ContractEntity no + ContractInstallmentPercentage no + ContractLineCode no + ContractLineName no + ContractLineName no + ContractParticipantSets? no + ContractSets? no + ContractTermsOfBusiness no + ContractTermsOfBusiness no + ContractType no + ContractType no + ContractTypeCode no + ContractTypeLink no + ContributionStatus no + ContributionStatus no + ControlPointList? no + ControlPointTime no + CopyCount no + CopyrightLicenseCountryCode no + CopyrightLicenseRegionCode no + CopyrightLicenseRegionName no + CopyrightOwnerName no + CopyrightOwnerName no + CopyrightStatus no + CopyrightStatus no + CornerLatitudePoint1 no + CornerLatitudePoint1 no + CornerLatitudePoint2 no + CornerLatitudePoint2 no + CornerLatitudePoint3 no + CornerLatitudePoint3 no + CornerLatitudePoint4 no + CornerLatitudePoint4 no + CornerLongitudePoint1 no + CornerLongitudePoint1 no + CornerLongitudePoint2 no + CornerLongitudePoint2 no + CornerLongitudePoint3 no + CornerLongitudePoint3 no + CornerLongitudePoint4 no + CornerLongitudePoint4 no + CountryCodeMethod no + CountryCodeMethod no + CountryName no + CountryName no + CountryName no + CountryName no + CreateDate no + CryptographicContext MXF + CryptographicContextID? no + CryptographicContextLink? no + CryptographicContextObject? no + CryptographicFramework MXF + CryptographicFrameworkLabel? no + CryptographicKeyID? no + Csiz no + Cue-InWords no + Cue-InWords no + Cue-OutWords no + Cue-OutWords no + CueWords MXF + CulturalValue no + CurrencyCode no + CurrencyName no + CurrentNumberInSequence no + CurrentNumberInSequence no + CurrentRepeatNumber no + CutPoint no + DMFramework MXF + DMSegment MXF + DMSet MXF + DMSourceClip MXF + DOI? no + DVBParentalRating no + DataDefinition? no + DataDefinitions? no + DataDeviceKind no + DataDeviceParameterName no + DataDeviceParameterSetting no + DataEnhancementOrModificationDescription no + DataEssenceCoding no + DataEssenceCodingID? no + DateTimeDropFrameFlag no + DateTimeEmbeddedFlag no + DateTimeKind? no + DateTimeRate no + DeclassificationDate no + DefaultDataValue? no + DefaultFadeDuration no + DefaultFadeEditRate no + DefaultFadeType? no + DefaultNamespaceURI no + DefaultNamespaceURI no + DefaultObject? no + DefinedName no + DefinedName no + DefinitionObjectID? no + DefinitionObjectName no + DefinitionObjectName no + DegradedEffects? no + DeltaEntryArray? no + DerivedFrom no + Description no + Description no + DescriptionKind no + DescriptionKind no + DescriptiveComment no + DescriptiveComment no + DescriptiveMetadataApplicationEnvironmentID no + DescriptiveMetadataFramework? no + DescriptiveMetadataPlug-InID? no + DescriptiveMetadataScheme? no + DescriptiveMetadataSchemes? no + DescriptiveMetadataSetReferences? no + DescriptiveMetadataSets? no + DescriptiveMetadataTrackIDs no + DeviceAbsoluteHeading no + DeviceAbsolutePositionalAccuracy no + DeviceAbsoluteSpeed no + DeviceAltitude no + DeviceAltitude no + DeviceAssetNumber no + DeviceDesignation no + DeviceIDKind no + DeviceKind no + DeviceKind no + DeviceKindCode no + DeviceLatitude no + DeviceLatitude no + DeviceLatitude no + DeviceLongitude no + DeviceLongitude no + DeviceLongitude no + DeviceManufacturerName no + DeviceManufacturerName no + DeviceModel no + DeviceParameterNameValueSets? no + DeviceParameters MXF + DeviceParametersSets? no + DeviceRelativeHeading no + DeviceRelativePositionX no + DeviceRelativePositionY no + DeviceRelativePositionZ no + DeviceRelativePositionalAccuracy no + DeviceRelativeSpeed no + DeviceSerialNumber no + DeviceUsageDescription no + DeviceUsageDescription no + DeviceXDimension no + DeviceYDimension no + DialNorm no + Dictionary? no + DictionaryDescription no + DictionaryDescription no + DictionaryIdentifier? no + DigitalEncodingBitrate no + DigitalMetadataCarrier no + DigitalOrAnalogOrigination no + DigitalVideoFileFormat no + DirectorName no + DiscPartitionCapacity no + DisplayF2Offset no + DisplayHeight no + DisplayUnits no + DisplayUnits no + DisplayWidth no + DisplayXOffset no + DisplayYOffset no + Dither no + DropFrame no + Duration no + DynamicSourcePackageID? no + DynamicSourceTrackIDs no + E-mailAddress no + E-mailAddress no + EPGProgramSynopsis no + EdgeCode no + EdgeCodeFilmGauge? no + EdgeCodeFormat? no + EdgeCodeHeader? no + EdgeCodeStart no + EditHint? no + EditRate no + EditUnitFlags no + EditUnitLength no + EditingEventComment no + EditingEventComment no + EffectRendering? no + ElectrospatialFormulation no + ElementCount no + ElementDelta no + ElementLength no + ElementNameList no + Emphasis no + EncryptedContainerLabel? no + EncryptedSourceValue? no + EncryptedTrackFileID? no + EndAnchor no + EndAnchor no + EnhancementOrModificationDescription no + EnumerationUnderlyingIntegerType? no + EpisodeEndNumber no + EpisodeNumber no + EpisodeNumber no + EpisodeStartNumber no + EpisodicItemSets? no + EssenceContainerArray? no + EssenceContainerDataSet MXF + EssenceContainerFormat? no + EssenceContainerFormat? no + EssenceContainers? no + EssenceData? no + EssenceDescription? no + EssenceIsIdentified no + EssenceLength no + EssenceLocators? no + EssenceStreamID no + Event MXF + EventAbsoluteDuration no + EventAbsoluteDuration? no + EventAbsoluteDurationFrameCount no + EventAnnotationSets? no + EventElapsedTimeToEnd no + EventElapsedTimeToStart no + EventEndTimeOffset no + EventEndTimecodeOffset? no + EventIndication no + EventIndication no + EventOrigin no + EventSets? no + EventStart no + EventStartTimeOffset no + EventStartTimecodeOffset? no + EventTrack MXF + EventTrackEditRate no + ExCCIData? no + ExposedAspectRatio no + ExtendedCaptionsLanguageCode no + ExtendedClipID no + ExtendedClipIDArray? no + ExtendedTextLanguageCode no + ExtendibleElementNameList no + FNumber no + Fade-InDuration no + Fade-InType? no + Fade-OutDuration no + Fade-OutType? no + FamilyName no + FamilyName no + FaxNumber no + FaxNumber no + FemaleLeadActressName no + FestivalName no + FestivalName no + FieldDominance no + FieldFrameTypeCode no + FieldOfViewHorizontal no + FieldOfViewHorizontal no + FieldOfViewVertical no + FieldOfViewVerticalFP no + FieldRate no + FileDescriptor MXF + FileDescriptors? no + FileSecurityReport no + FileSecurityWave no + FillerData? no + FilmBatchNumber no + FilmBatchNumber no + FilmCaptureAperture no + FilmColorProcess no + FilmFormatName no + FilmFormatName no + FilmFormatName? no + FilmGauge? no + FilmStockKind no + FilmStockKind no + FilmStockManufacturerName no + FilmStockManufacturerName no + FilmTestParameter no + FilmTestResult no + FilmTestResult? no + FilmToVideoTransferDirection? no + FilmToVideoTransferKind? no + FilmToVideoTransferPhase? no + FilteringApplied no + FilteringCode no + FirstBroadcastFlag no + FirstGivenName no + FirstGivenName no + FirstNumberInSequence no + FirstNumberInSequence no + FirstTransmissionInfo no + FixedArrayElementType? no + FixedChannelStatusData? no + FixedUserData? no + FocalLength no + FocalLength no + Footer? no + FormatDescriptor no + FormatDescriptor no + FormerFamilyName no + FormerFamilyName no + FrameCenterElevation no + FrameCenterLatitude no + FrameCenterLatitude no + FrameCenterLatitude no + FrameCenterLatitudeLongitude no + FrameCenterLongitude no + FrameCenterLongitude no + FrameCenterLongitude no + FrameCode no + FrameCount no + FrameCountOffset no + FrameLayout no + FramePositionalAccuracy no + FrameRate no + FrameworkExtendedTextLanguageCode no + FrameworkTextLanguageCode no + FrameworkThesaurusName no + FrameworkThesaurusName no + FrameworkTitle no + FrameworkTitle no + GenerationCloneNumber no + GenerationCopyNumber no + GenerationID? no + GenericDataEssenceDescriptor MXF + GenericPackage MXF + GenericPayloads? no + GenericPictureEssenceDescriptor MXF + GenericSoundEssenceDescriptor MXF + GenericTrack MXF + Genre no + Genre no + GeographicAreaNorthwest? no + GeographicAreaSourceDatum no + GeographicAreaSoutheast? no + GeographicLocation? no + GeographicPolygonCoordinates? no + GeographicPolygonSourceDatum no + GeographicalCoordinates? no + GlobalNumber no + GraphicKind no + GraphicUsageKind no + GraphicUsageKind no + GroupRelationship MXF + GroupSet? no + GroupSets? no + GroupSynopsis no + GroupSynopsis no + HMACAlgorithmSHA1128? no + HTMLDOCTYPE no + HTMLDOCTYPE no + HTMLMetaDescription no + HTMLMetaDescription no + HardwareAcceleratorFlag no + HasAudioWatermark no + HasVideoWatermark no + HeaderByteCount no + HistoricalValue no + HonorsAndQualifications no + HonorsAndQualifications no + HorizontalActionSafePercentage no + HorizontalDatum no + HorizontalGraphicsSafePercentage no + HorizontalSubsampling no + IBTN? no + IEEEDeviceID no + IEEEManufacturerID no + ISAN? no + ISBD? no + ISBN? no + ISCI? no + ISMN? no + ISO3166CountryCode no + ISO639-1LanguageCode no + ISO639-1LanguageCode no + ISO639CaptionsLanguageCode no + ISO639TextLanguageCode no + ISRC? no + ISRN? no + ISSN? no + ISTC? no + ISWC? no + IdenticalGOPIndicator no + Identification MXF + Identification MXF + IdentificationList? no + IdentificationSets? no + IdentificationUL? no + IdentifierIssuingAuthority no + IdentifierIssuingAuthority no + IdentifierKind no + IdentifierValue no + ImageAlignmentOffset no + ImageCategory no + ImageCoordinateSystem no + ImageEndOffset no + ImageFormatSet? no + ImageHeight no + ImageSourceDeviceKind no + ImageSourceDeviceKind no + ImageStartOffset no + ImageWidth no + IncludeSync no + IndexByteCount no + IndexDuration no + IndexEditRate no + IndexEntryArray? no + IndexStreamID no + IndexTableSegment? no + IndexingStartPosition no + IndividualAwardName no + InkNumber no + InputSegment? no + InputSegmentCount no + InputSegments? no + InsertMusicFlag no + InstallmentNumber no + InstanceUID? no + IntegrationIndication no + IntegrationIndication no + IntellectualPropertyDescription no + IntellectualPropertyDescription no + IntellectualPropertyLicenseCountryCode no + IntellectualPropertyLicenseRegionCode no + IntellectualPropertyLicenseRegionName no + IntellectualPropertyRights no + IntellectualPropertyRights no + IntendedAFD no + IntentDescriptor no + IntentDescriptor no + InterestedPartyName no + Interpolation? no + InterpolationDefinitions? no + IsConcrete no + IsDubbed no + IsLiveProduction no + IsLiveTransmission no + IsOptional no + IsRecording no + IsRepeat no + IsSearchable no + IsSigned no + IsUniqueIdentifier no + IsVoiceover no + ItemDesignatorID? no + ItemID no + ItemName no + ItemName no + ItemValue no + ItemValue no + JFIFMarkerDescription no + JFIFMarkerDescription no + JPEG2000PictureSubDescriptor MXF + JPEGTableID? no + JobFunctionCode no + JobFunctionName no + JobFunctionName no + JobTitle no + JobTitle no + Jurisdiction no + Jurisdiction no + KAGSize no + KLVDataDefinitions? no + KLVDataParentProperties? no + KLVDataType? no + KLVDataValue? no + KLVMetadataSequence? no + KeyCode? no + KeyData no + KeyDataOrProgram no + KeyFrame no + KeyFrameSampleCount no + KeyFrames no + KeyPoint MXF + KeyPointSets? no + KeySound no + KeySounds no + KeyText no + KeyTimePoint no + KeypointKind no + KeypointKind no + KeypointValue no + KeypointValue no + Keywords no + Keywords no + LUID no + LanguageName no + LanguageName no + LastNumberInSequence no + LastNumberInSequence no + LayerNumber no + LeadingLines no + LengthSystemName no + LengthUnitKind no + LicenseOptionsDescription no + LineNumber no + LinkedApplicationPlug-InInstanceID? no + LinkedDescriptiveFrameworkPlug-InID? no + LinkedDescriptiveObjectPlug-InID? no + LinkedGenerationID? no + LinkedPackageID? no + LinkedTimecodeTrackID? no + LinkedTrackID no + LinkingName no + LinkingName no + LocalCreationDateTime no + LocalDatumAbsolutePositionAccuracy no + LocalDatumRelativePositionAccuracy no + LocalEndDateTime no + LocalEventEndDateTime no + LocalEventEndDateTime no + LocalEventStartDateTime no + LocalEventStartDateTime no + LocalFestivalDateTime no + LocalFilePath no + LocalFilePath no + LocalID no + LocalLastModifyDate no + LocalModifyDate no + LocalStartDateTime no + LocalTagEntries? no + LocalTagUniqueID? no + LocalTagValue no + LocalTapeNumber no + LocalTargetID no + LocalTargetID no + LocalUserDateTime no + Location MXF + LocationDescription no + LocationDescription no + LocationKind no + LocationKind no + LocationSets? no + LockedIndicator no + LogoFlag no + LowDelayIndicator no + LumaEquation no + LuminanceSampleRate no + MIC? no + MICAlgorithm? no + MIMECharSet no + MIMECharSet no + MIMEEncoding no + MIMEEncoding no + MIMEMediaType no + MIMEMediaType no + MPEG2VideoDescriptor MXF + MPEG7BiMAccessUnitFrame1? no + MPEG7BiMAccessUnitFrame2? no + MPEG7BiMAccessUnitFrame3? no + MPEG7BiMAccessUnitFrame4? no + MPEG7BiMAccessUnitFrame5? no + MPEG7BiMAccessUnitFrame6? no + MPEG7BiMAccessUnitFrame7? no + MPEG7BiMAccessUnitFrame8? no + MPEG7BiMDecoderInitFrame1? no + MPEG7BiMDecoderInitFrame2? no + MPEG7BiMDecoderInitFrame3? no + MPEG7BiMDecoderInitFrame4? no + MPEG7BiMDecoderInitFrame5? no + MPEG7BiMDecoderInitFrame6? no + MPEG7BiMDecoderInitFrame7? no + MPEG7BiMDecoderInitFrame8? no + MPEGAudioBitrate no + MPEGAudioRecodingDataset? no + MPEGVideoRecodingDataset? no + MagneticDiskNumber no + MagneticTrack no + MainCatalogNumber no + MainName no + MainName no + MainSponsorName no + MainTitle no + MainTitle no + MajorVersion no + MaleLeadActorName no + ManufacturerID? no + ManufacturerInformationObject? no + MapDatumUsed no + MarkIn no + MarkOut no + MaterialAbsoluteDuration no + MaterialAbsoluteDuration? no + MaterialEndTimeOffset no + MaterialEndTimecodeOffset? no + MaterialPackage MXF + MaximumAPIVersion no + MaximumBPictureCount no + MaximumGOPSize no + MaximumSupportedEngineVersion no + MaximumSupportedPlatformVersion no + MaximumUseCount no + MediaLocation no + MemberNameList no + MemberTypes? no + MetadataEncodingSchemeCode no + MetadataItemName no + MetadataItemName no + MetadataServerLocators? no + MicrophonePlacementTechniques no + MinimumAPIVersion no + MinimumSupportedEngineVersion no + MinimumSupportedPlatformVersion no + MinorVersion no + MissionID no + MissionID no + MobileTelephoneNumber no + ModifyDate no + MonoSourceTrackIDs no + MultipleDescriptor MXF + NITFLayerTargetID no + NITFLayerTargetID no + NMEADocumentText no + NOLACode no + NameSuffix no + NameSuffix no + NameValue MXF + NamespacePrefix no + NamespacePrefix no + NamespacePrefixes no + NamespacePrefixes no + NamespaceURI no + NamespaceURI no + NamespaceURIs no + NamespaceURIs no + Nationality no + Nationality no + NatureOfPersonality no + NatureOfPersonality no + NetworkLocator MXF + NextNumberInSequence no + NextNumberInSequence no + NielsenStreamIdentifier no + NominationCategory no + NominationCategory no + Non-USClassifyingCountryCode no + ObjectAreaDimension no + ObjectClass? no + ObjectClassDefinition? no + ObjectCountryCode no + ObjectCountryCode no + ObjectCountryCodeMethod no + ObjectDescription no + ObjectDescription no + ObjectDescriptionCode no + ObjectHorizontalAverageDimension no + ObjectIdentificationConfidence no + ObjectKind no + ObjectKind no + ObjectModelVersion no + ObjectName no + ObjectRegionCode no + ObjectRegionName no + ObjectVerticalAverageDimension no + ObliquityAngle no + OffsetToIndexTable no + OffsetToIndexTable no + OffsetToMetadata no + OffsetToMetadata no + OpenBodyPartition? no + OpenCompleteBodyPartition? no + OpenCompleteHeader MXF Header + OpenHeader MXF Header + OperatingSystemInterpretations no + OperationCategory? no + OperationDataDefinition? no + OperationDefinitionID? no + OperationDefinitions? no + OperationParameters? no + OperationalPatternUL? no + OpticalDiscNumber no + OpticalTestParameterName no + OpticalTestResult no + OpticalTestResult no + OpticalTrack no + Organisation MXF + OrganizationCode no + OrganizationCode no + OrganizationID no + OrganizationID no + OrganizationIDKind no + OrganizationIDKind no + OrganizationKind no + OrganizationKind no + OrganizationMainName no + OrganizationMainName no + OrganizationSets? no + OrganizationalProgramNumber no + OrganizationalProgramNumber no + Origin no + OriginCode no + OriginalExtendedSpokenPrimaryLanguageCode no + OriginalProducerName no + OriginalProducerName no + OriginalTitle no + OriginalTitle no + OtherGivenNames no + OtherGivenNames no + OtherValues no + PII? no + POSIXMicroseconds no + PURL no + PackLength no + PackageAttributes? no + PackageID? no + PackageKLVData? no + PackageLastModifyDate no + PackageMarkInPosition no + PackageMarkOutPosition no + PackageMarker? no + PackageName no + PackageName no + PackageTimelineMarkerRef? no + PackageTracks? no + PackageUsageKind? no + PackageUserComments? no + Packages? no + PaddingBits no + Palette? no + PaletteLayout? no + PanScanInformation? no + ParameterDataType? no + ParameterDefinition? no + ParameterDefinitions? no + Parameters? no + ParentClass? no + Participant MXF + ParticipantID? no + ParticipantOrganizationSets? no + PartitionMetadata? no + Password no + Password no + PayeeAccountName no + PayeeAccountNumber no + PayeeAccountSortCode no + PayerAccountName no + PayerAccountNumber no + PayerAccountSortCode no + PaymentDueDateTime no + PaymentsSets? no + PeakChannelCount no + PeakEnvelope no + PeakEnvelopeBlockSize no + PeakEnvelopeData? no + PeakEnvelopeData? no + PeakEnvelopeFormat no + PeakEnvelopeTimestamp no + PeakEnvelopeVersion no + PeakFrameCount no + PeakOfPeaksPosition no + PerceivedDisplayFormatCode no + PerceivedDisplayFormatName no + PerforationsPerFrame no + PerforationsPerFrame no + Person MXF + PersonDescription no + PersonDescription no + PersonOrganizationSets? no + PersonSets? no + PhysicalInstanceKind no + PhysicalMediaLength? no + PhysicalMediaLocation no + PictureComponentSizing? no + PictureDisplayRate no + PictureFormat MXF + PixelLayout? no + PlaceKeyword no + PlaceKeyword no + PlaceName no + PlaceName no + PlaintextOffset no + PlatformDesignation no + PlatformDesignation no + PlatformHeadingAngle no + PlatformModel no + PlatformPitchAngle no + PlatformRollAngle no + PlatformSerialNumber no + Plug-InAPIID? no + Plug-InCategoryID? no + Plug-InDefinitions? no + Plug-InEngineID? no + Plug-InLocatorSet? no + Plug-InPlatformID? no + PointsPerPeakValue no + PolarCharacteristic no + PosTableArray? no + PositionInSequence no + PositionTable? no + PositionTableCount no + PositionTableIndexing no + PositionWithinViewportImageXCoordinate no + PositionWithinViewportImageYCoordinate no + PostCodeForPostbox no + PostalCode no + PostalCode no + PostalTown no + PostalTown no + PostboxNumber no + Preface MXF + PresentationAspectRatio no + PresentationGammaEquation no + PresentationGammaEquation? no + PresenterName no + PreviousNumberInSequence no + PreviousNumberInSequence no + PreviousRepeatNumber no + PrimaryExtendedSpokenLanguageCode no + PrimaryOriginalLanguageCode no + PrimaryPackage? no + PrimarySpokenLanguageCode no + Primer MXF + Processing MXF + ProcessingSet? no + ProducerName no + ProductFormat no + ProductFormat no + ProductionFramework MXF + ProductionOrganizationRole no + ProductionOrganizationRole no + ProductionScriptReference no + ProductionScriptReference no + ProductionSettingPeriodSets? no + ProfileAndLevel no + ProgramAwardName no + ProgramCommercialMaterialReference no + ProgramIdentifier no + ProgramIdentifierString no + ProgramKind no + ProgramMaterialClassificationCode no + ProgramNumber no + ProgramSupportMaterialReference no + ProgrammingGroupKind no + ProgrammingGroupKind no + ProgrammingGroupTitle no + ProgrammingGroupTitle no + ProjectName no + ProjectName no + ProjectNumber no + ProjectSet? no + Projects MXF + Properties? no + PropertyType? no + Publication MXF + PublicationSets? no + PublishingMediumName no + PublishingMediumName no + PublishingOrganizationName no + PublishingOrganizationName no + PublishingRegionName no + PublishingRegionName no + PublishingServiceName no + PublishingServiceName no + PulldownFieldDominance no + PulldownSequence? no + PurchaserAccountName no + PurchaserAccountName no + PurchaserAccountNumber no + PurchaserIdentificationKind no + PurchaserIdentificationValue no + PurchasingDepartment no + PurchasingOrganizationName no + Purpose no + Purpose no + QltyBasicData no + QltyBasicData no + QltyCueSheet no + QltyCueSheet no + QltyEndOfModulation no + QltyEndOfModulation no + QltyOperatorComment no + QltyOperatorComment no + QltyQualityEvent no + QltyQualityEvent no + QltyQualityParameter no + QltyQualityParameter no + QltyStartOfModulation no + QltyStartOfModulation no + QualityFlag no + QuantizationDefault? no + RGBAEssenceDescriptor MXF + RIFFChunkData? no + RIFFChunkID no + RIFFChunkLength no + RP217DataStreamPID no + RP217VideoStreamPID no + RandomIndexMetadata? no + RandomIndexMetadataV10? no + Rating no + RecordedFormat no + RecordedFormat no + RecordedTrackNumber no + RecordingLabelName no + RecordingLabelName no + ReelOrRollNumber no + RegionCode no + RegionName no + RegionName no + RegisterAction no + RegisterAdministrationArray? no + RegisterAdministrationNotes no + RegisterAdministrationObject? no + RegisterApproverName no + RegisterChildEntryArray? no + RegisterCreationTime no + RegisterEditorName no + RegisterEntryAdministrationObject? no + RegisterEntryArray? no + RegisterEntryStatus? no + RegisterItemDefiningDocumentName no + RegisterItemDefinition no + RegisterItemHierarchyLevel no + RegisterItemIntroductionVersion no + RegisterItemName no + RegisterItemNotes no + RegisterItemOriginatorName no + RegisterItemStatusChangeDateTime no + RegisterItemSymbol? no + RegisterItemUL? no + RegisterKind? no + RegisterReleaseDateTime no + RegisterStatusKind? no + RegisterUserName no + RegisterUserTime no + RegisterVersion no + RegistrantName no + RelatedMaterialDescription no + RelatedMaterialDescription no + RelatedMaterialLocators? no + RelativePositionInSequenceName no + RelativePositionInSequenceOffset no + RelativeScope no + RelativeTrack no + ReleasableCountryCode no + ReleasableCountryCode no + RenamedType? no + ResourceID? no + RestrictionsonUse no + ReversePlay no + ReversedByteOrder no + Rights MXF + RightsComment no + RightsComment no + RightsConditionDescription no + RightsConditionDescription no + RightsManagementAuthority no + RightsManagementAuthority no + RightsSets? no + RightsStartDateTime no + RightsStopDateTime no + Rightsholder no + Rightsholder no + RoleName no + RoleName no + RoomNumber no + RoomNumber no + RoomOrSuiteName no + RoomOrSuiteName no + RootFormatVersion no + RootMetaDictionary? no + RootObjectDirectory? no + RootPreface? no + RoundedCaptureFilmFrameRate no + RoundedTimecodeTimebase no + RoundingLaw no + RoundingMethodCode no + RoyaltyIncomeInformation no + RoyaltyPaymentInformation no + Rsiz no + SDKVersion no + SICI? no + SMPTE12MUserDateTime? no + SMPTE309MUserDateTime? no + SMPTE337MDataStreamNumber no + SMPTEUL? no + SalesContractNumber no + Salutation no + Salutation no + SampleIndex? no + SampleRate no + SampledHeight no + SampledWidth no + SampledXOffset no + SampledYOffset no + SamplingHierarchyCode no + SamplingStructureCode no + ScanningDirection no + SceneFramework MXF + SceneNumber no + SceneNumber no + SceneSettingPeriodSets? no + SceneShotSets? no + ScramblingKeyKind no + ScramblingKeyValue no + Scripting MXF + ScriptingKind no + ScriptingKind no + ScriptingLocators? no + ScriptingSets? no + ScriptingText no + ScriptingText no + SeasonEpisodeNumber no + SeasonEpisodeTitle no + SecondGivenName no + SecondGivenName no + SecondaryExtendedSpokenLanguageCode no + SecondaryOriginalExtendedSpokenLanguageCode no + SecondaryOriginalLanguageCode no + SecondarySpokenLanguageCode no + SecondaryTitle no + SecondaryTitle no + SectorSize no + SecurityClassification no + SecurityClassification no + SecurityClassificationCaveats no + SecurityClassificationCaveats no + Selected? no + SensorMode no + SensorRollAngle no + SensorSize no + SensorType no + SensorTypeCode no + Sequence? no + SequenceOffset no + SequenceSet MXF + SeriesNumber no + SeriesNumber no + SeriesinaSeriesGroupCount no + SetElementType? no + SettingCityName no + SettingCityName no + SettingCountryCode no + SettingCountryName no + SettingCountryName no + SettingDateTime no + SettingDescription no + SettingDescription no + SettingPeriod MXF + SettingPeriodDescription no + SettingPeriodDescription no + SettingPostalCode no + SettingPostalCode no + SettingRegionCode no + SettingRegionName no + SettingRoomNumber no + SettingRoomNumber no + SettingStateOrProvinceOrCountyName no + SettingStateOrProvinceOrCountyName no + SettingStreetName no + SettingStreetName no + SettingStreetNumberOrBuildingName no + SettingStreetNumberOrBuildingName no + SettingTownName no + SettingTownName no + ShimName no + ShootingCountryCode no + ShootingRegionCode no + ShootingRegionName no + Shot MXF + ShotComment no + ShotComment no + ShotCommentKind no + ShotCommentKind no + ShotCueWordsSet? no + ShotDescription no + ShotDescription no + ShotDuration no + ShotList no + ShotLocationSets? no + ShotParticipantRoleSets? no + ShotPersonSets? no + ShotStartPosition no + ShotTrackIDs no + SideNumber no + Signal-to-NoiseRatio no + SignalFormCode no + SignalStandard no + SignalStandard no + SignatureTuneFlag no + SimpleFlaggingCount no + SingleSequenceFlag no + Size no + SlantRange no + SlateInformation no + SlateTitle no + SliceCount no + SliceNumber no + SliceOffsetList? no + Software-OnlySupportFlag no + SourceClip? no + SourceContainerFormat? no + SourceImageCenterXCoordinate no + SourceImageCenterYCoordinate no + SourceIndex? no + SourceKey? no + SourceLength no + SourceOrganization no + SourceOrganization no + SourcePackage MXF + SourcePackageID? no + SourceSpecies? no + SourceTrackID no + SourceTrackIDs no + SourceValue? no + SpeedChangeEffectFlag no + SplicingMetadata? no + StartTimeRelativeToReference no + StartTimeRelativeToReference no + StartTimecode no + StartTimecodeRelativeToReference? no + StateOrProvinceOrCountyName no + StateOrProvinceOrCountyName no + StaticTrack MXF + StillFrame? no + StorageDeviceKind no + StorageKind no + StorageKind no + StorageKindCode no + StorageMediaID no + StorageMediaKind no + StoredANCLineNumber no + StoredF2Offset no + StoredVBILineNumber no + StratumKind no + StreamData? no + StreamElementType? no + StreamID no + StreamOffset no + StreamPositionIndicator no + StreamPositionIndicator no + StreamPositionIndicator no + StreamPositionIndicator no + StreetName no + StreetName no + StreetNumber no + StreetNumber no + StringElementType? no + StructuralComponent MXF + Sub-descriptors? no + SubDescriptor? no + SubDescriptors? no + SubjectAbsoluteHeading no + SubjectAbsoluteSpeed no + SubjectDistance no + SubjectName no + SubjectName no + SubjectRelativeHeading no + SubjectRelativePositionalAccuracy no + SubjectRelativeSpeed no + SubtitleDatafileFlag no + SubtitlesPresent no + SupplementaryName no + SupplementaryName no + SupplementaryOrganizationName no + SupplementaryOrganizationName no + SupplierAccountName no + SupplierAccountName no + SupplierAccountNumber no + SupplierIdentificationKind no + SupplierIdentificationValue no + SupplyContractNumber no + SupplyingDepartmentName no + SupportOrAdministrationStatus no + SupportOrAdministrationStatus no + SupportOrganizationRole no + SupportOrganizationRole no + SystemNameOrNumber no + TIFFSummary? no + TaggedValueDefinitions? no + TaggedValueParentProperties? no + TakeNumber no + TapeBatchNumber no + TapeBatchNumber no + TapeCapacity no + TapeFormat? no + TapeFormulation no + TapeFormulation no + TapeManufacturer no + TapeManufacturer no + TapePartitionCapacity no + TapeShellKind no + TapeShellKind no + TapeStock no + TapeStock no + TargetAudience no + TargetAudience no + TargetClassOfStrongReference? no + TargetClassOfWeakReference? no + TargetSet? no + TargetWidth no + TechnicalValue no + TelephoneNumber no + TelephoneNumber no + TeletextSubtitlesAvailable no + TeletextSubtitlesFlag no + TemporalOffset no + TerminatingFillerData no + TextLocator MXF + TextlessBlackDuration no + TextlessMaterial no + TextualDescriptionKind no + TextualDescriptionKind no + Theme no + Theme no + ThemeMusicFlag no + ThesaurusName no + ThesaurusName no + ThirdGivenName no + ThirdGivenName no + TimePeriodName no + TimePeriodName no + TimeSystemOffset no + TimeUnitKind no + TimebaseReferenceTrackID no + TimecodeArray? no + TimecodeComponent MXF + TimecodeCreationDateTime? no + TimecodeEndDateTime? no + TimecodeEventEndDateTime? no + TimecodeEventStartDateTime? no + TimecodeKind no + TimecodeLastModifyDate? no + TimecodeModifyDate? no + TimecodeSourceKind no + TimecodeStartDateTime? no + TimecodeStreamData? no + TimecodeTimebase no + TimecodeTimebase no + TimecodeUserBitsFlag no + TimepointValue? no + TimingBiasCorrection no + TimingBiasCorrectionDescription no + TitleKind no + TitleKind no + Titles MXF + TitlesSets? no + ToleranceInterpolationMethod? no + ToleranceMode? no + ToleranceWindow? no + ToolkitVersion no + TotalCurrencyAmount no + TotalEpisodeCount no + TotalIncome no + TotalLinesperFrame no + TotalNumberInSequence no + TotalPayment no + TotalSamplesperLine no + Track MXF + TrackID no + TrackName no + TrackName no + TrackNumber no + TrackNumberBatch no + Tracks? no + TrafficID no + TrailingLines no + TranscriptReference no + TranscriptReference no + TransferFilmFrameRate no + TransitionEffect? no + TransmissionID no + TransportStreamID no + TripletSequenceNumber no + TypeDefinitionElementValueList no + TypeDefinitionExtendibleElementValues? no + TypeDefinitions? no + UCSEncoding no + UPID? no + UPN? no + URL no + URL no + URL no + URL no + URN no + UTCEndDateTime no + UTCEventEndDateTime no + UTCEventEndDateTime no + UTCEventStartDateTime no + UTCEventStartDateTime no + UTCInstantDateTime no + UTCInstantDateTime no + UTCLastModifyDate no + UTCLastModifyDate no + UTCStartDateTime no + UTCStartDateTime no + UTCUserDateTime no + UniformDataFlag no + UnknownBWFChunks? no + UpstreamAudioCompressionAlgorithm no + UseDefaultValue no + UserDataMode? no + UserName no + UserName no + UserPosition no + V10IndexTableSegment? no + VBEEndOffset no + VBIDataDescriptor MXF + VBILineCount no + VBIPayloadByteArray no + VBIPayloadSampleCoding no + VBIPayloadSampleCount no + VBIWrappingType no + VC-1AverageBitrate no + VC-1BPictureCount no + VC-1CodedContentType no + VC-1IdenticalGOP no + VC-1InitializationMetadata? no + VC-1Level no + VC-1MaximumBitrate no + VC-1MaximumGOP no + VC-1Profile no + VC-1SingleSequence no + Value? no + VariableArrayElementType? no + VersionNumber no + VersionNumberString no + VersionNumberString no + VersionTitle no + VersionTitle no + VerticalActionSafePercentage no + VerticalDatum no + VerticalGraphicsSafePercentage no + VerticalSub-sampling no + VideoAndFilmFrameRelationship no + VideoAverageBitrate no + VideoClipDuration no + VideoCodingSchemeID? no + VideoColorKind no + VideoCompressionAlgorithm no + VideoDeviceKind no + VideoDeviceParameterName no + VideoDeviceParameterSetting no + VideoFixedBitrate no + VideoIndexArray? no + VideoLineMap no + VideoNoiseReductionAlgorithm no + VideoOrImageCompressionAlgorithm no + VideoPayloadIdentifier no + VideoPayloadIdentifier2002 no + VideoTestParameter no + VideoTestResult no + VideoTestResult no + VideoWatermarkKind no + ViewportAspectRatio no + ViewportHeight no + ViewportImageCenterCCoordinate no + ViewportImageCenterYCoordinate no + ViewportWidth no + VoiceTalentName no + WAVESummary? no + WaveAudioDescriptor MXF + Weighting no + WhiteReferenceLevel no + Work-in-ProgressFlag no + WorkingTitle no + WorkingTitle no + XMLDocumentText? no + XMLDocumentText no + XMLDocumentText no + XMLDocumentText? no + XOsiz no + XTOsiz no + XTsiz no + Xsiz no + YOsiz no + YTOsiz no + YTsiz no + Ysiz no + +=head3 MXF Header Tags + + Index1 Tag Name Writable + ------ -------- -------- + 0 MXFVersion no + 24 FooterPosition no + 32 HeaderSize no + +=head2 DV Tags + +The following tags are extracted from DV videos. + + Tag Name Writable + -------- -------- + AspectRatio no + AudioBitsPerSample no + AudioChannels no + AudioSampleRate no + Colorimetry no + DateTimeOriginal no + Duration no + FrameRate no + ImageHeight no + ImageWidth no + TotalBitrate no + VideoFormat no + VideoScanType no + +=head2 Flash Tags + +The information below is extracted from SWF (Shockwave Flash) files. Tags +with string ID's represent information extracted from the file header. + + Tag ID Tag Name Writable + ------ -------- -------- + 'Compressed' Compressed no + 'Duration' Duration no + 'FlashVersion' FlashVersion no + 'FrameCount' FrameCount no + 'FrameRate' FrameRate no + 'ImageHeight' ImageHeight no + 'ImageWidth' ImageWidth no + 0x0045 FlashAttributes no + 0x004d XMP XMP + +=head3 Flash FLV Tags + +Information is extracted from the following packets in FLV (Flash Video) +files. + + Tag ID Tag Name Writable + ------ -------- -------- + 0x0008 Audio Flash Audio + 0x0009 Video Flash Video + 0x0012 Meta Flash Meta + +=head3 Flash Audio Tags + +Information extracted from the Flash Audio header. + + Tag ID Tag Name Writable + ------ -------- -------- + 'Bit0-3' AudioEncoding no + 'Bit4-5' AudioSampleRate no + 'Bit6' AudioBitsPerSample no + 'Bit7' AudioChannels no + +=head3 Flash Video Tags + +Information extracted from the Flash Video header. + + Tag ID Tag Name Writable + ------ -------- -------- + 'Bit4-7' VideoEncoding no + +=head3 Flash Meta Tags + +Below are a few observed FLV Meta tags, but ExifTool will attempt to extract +information from any tag found. + + Tag ID Tag Name Writable + ------ -------- -------- + 'audiocodecid' AudioCodecID no + 'audiodatarate' AudioBitrate no + 'audiodelay' AudioDelay no + 'audiosamplerate' AudioSampleRate no + 'audiosamplesize' AudioSampleSize no + 'audiosize' AudioSize no + 'bytelength' ByteLength no + 'canSeekToEnd' CanSeekToEnd no + 'canseekontime' CanSeekOnTime no + 'createdby' CreatedBy no + 'creationdate' CreateDate no + 'cuePoints' CuePoint Flash CuePoint + 'datasize' DataSize no + 'duration' Duration no + 'filesize' FileSizeBytes no + 'framerate' FrameRate no + 'hasAudio' HasAudio no + 'hasCuePoints' HasCuePoints no + 'hasKeyframes' HasKeyFrames no + 'hasMetadata' HasMetadata no + 'hasVideo' HasVideo no + 'height' ImageHeight no + 'httphostheader' HTTPHostHeader no + 'keyframesFilepositions' KeyFramePositions no + 'keyframesTimes' KeyFramesTimes no + 'lastkeyframetimestamp' LastKeyFrameTime no + 'lasttimestamp' LastTimeStamp no + 'liveXML' XMP XMP + 'metadatacreator' MetadataCreator no + 'metadatadate' MetadataDate no + 'pmsg' Message no + 'purl' URL no + 'sourcedata' SourceData no + 'starttime' StartTime no + 'stereo' Stereo no + 'totaldatarate' TotalDataRate no + 'totalduration' TotalDuration no + 'videocodecid' VideoCodecID no + 'videodatarate' VideoBitrate no + 'videosize' VideoSize no + 'width' ImageWidth no + +=head3 Flash CuePoint Tags + +These tag names are added to the CuePoint name to generate complete tag +names like "CuePoint0Name". + + Tag ID Tag Name Writable + ------ -------- -------- + 'name' Name no + 'parameters' Parameter Flash Parameter + 'time' Time no + 'type' Type no + +=head3 Flash Parameter Tags + +There are no pre-defined parameter tags, but ExifTool will extract any +existing parameters, with tag names like "CuePoint0ParameterXxx". + + Tag ID Tag Name Writable + ------ -------- -------- + [no tags known] + +=head2 Real Tags + +ExifTool recognizes three basic types of Real audio/video files: 1) +RealMedia (RM, RV and RMVB), 2) RealAudio (RA), and 3) Real Metafile (RAM +and RPM). + +=head3 Real Media Tags + +These B<Tag ID>'s are Chunk ID's used in RealMedia and RealVideo (RM, RV and +RMVB) files. + + Tag ID Tag Name Writable + ------ -------- -------- + 'CONT' CONT Real ContentDescr + 'MDPR' MDPR Real MediaProps + 'PROP' PROP Real Properties + 'RJMD' RJMD Real Metadata + +=head3 Real ContentDescr Tags + + Sequence Tag Name Writable + -------- -------- -------- + 0 TitleLen? no + 1 Title no + 2 AuthorLen? no + 3 Author no + 4 CopyrightLen? no + 5 Copyright no + 6 CommentLen? no + 7 Comment no + +=head3 Real MediaProps Tags + + Sequence Tag Name Writable + -------- -------- -------- + 0 StreamNumber no + 1 StreamMaxBitrate no + 2 StreamAvgBitrate no + 3 StreamMaxPacketSize no + 4 StreamAvgPacketSize no + 5 StreamStartTime no + 6 StreamPreroll no + 7 StreamDuration no + 8 StreamNameLen? no + 9 StreamName no + 10 StreamMimeLen? no + 11 StreamMimeType no + 12 FileInfoLen? no + 13 FileInfoLen2? no + 14 FileInfoVersion no + 15 PhysicalStreams? no + 16 PhysicalStreamNumbers? no + 17 DataOffsets? no + 18 NumRules? no + 19 PhysicalStreamNumberMap? no + 20 NumProperties? no + 21 FileInfoProperties Real FileInfo + +=head3 Real FileInfo Tags + +The following tags have been observed in the FileInfo properties, but any +other existing information will also be extracted. + + Tag ID Tag Name Writable + ------ -------- -------- + 'Audiences' Audiences no + 'Audio Format' AudioFormat no + 'Content Rating' ContentRating no + 'Creation Date' CreateDate no + 'Description' Description no + 'File ID' FileID no + 'Generated By' Software no + 'Indexable' Indexable no + 'Keywords' Keywords no + 'Modification Date' ModifyDate no + 'Target Audiences' TargetAudiences no + 'Video Quality' VideoQuality no + 'audioMode' AudioMode no + 'videoMode' VideoMode no + +=head3 Real Properties Tags + + Sequence Tag Name Writable + -------- -------- -------- + 0 MaxBitrate no + 1 AvgBitrate no + 2 MaxPacketSize no + 3 AvgPacketSize no + 4 NumPackets no + 5 Duration no + 6 Preroll no + 7 IndexOffset? no + 8 DataOffset? no + 9 NumStreams no + 10 Flags no + +=head3 Real Metadata Tags + +The tags below represent information which has been observed in the Real +Metadata format, but ExifTool will extract any information it finds in this +format. (As far as I can tell from the referenced documentation, string +values should be plain text, but this is not the case for the only sample +file I have been able to obtain containing this information. These tags +could also be split into separate sub-directories, but this will wait until +I have better documentation or a more complete set of samples.) + + Tag ID Tag Name Writable + ------ -------- -------- + 'Album/Name' AlbumName no + 'Track/Category' TrackCategory no + 'Track/Comments' TrackComments no + 'Track/Lyrics' TrackLyrics no + +=head3 Real Audio Tags + +Tags in the following table reference information extracted from various +versions of RealAudio (RA) files. + + Tag ID Tag Name Writable + ------ -------- -------- + '.ra3' RA3 Real AudioV3 + '.ra4' RA4 Real AudioV4 + '.ra5' RA5 Real AudioV5 + +=head3 Real AudioV3 Tags + + Sequence Tag Name Writable + -------- -------- -------- + 0 Channels no + 1 Unknown? no + 2 BytesPerMinute no + 3 AudioBytes no + 4 TitleLen? no + 5 Title no + 6 ArtistLen? no + 7 Artist no + 8 CopyrightLen? no + 9 Copyright no + 10 CommentLen? no + 11 Comment no + +=head3 Real AudioV4 Tags + + Sequence Tag Name Writable + -------- -------- -------- + 0 FourCC1? no + 1 AudioFileSize? no + 2 Version2? no + 3 HeaderSize? no + 4 CodecFlavorID? no + 5 CodedFrameSize? no + 6 AudioBytes no + 7 BytesPerMinute no + 8 Unknown? no + 9 SubPacketH? no + 10 AudioFrameSize no + 11 SubPacketSize? no + 12 Unknown? no + 13 SampleRate no + 14 Unknown? no + 15 BitsPerSample no + 16 Channels no + 17 FourCC2Len? no + 18 FourCC2? no + 19 FourCC3Len? no + 20 FourCC3? no + 21 Unknown? no + 22 Unknown? no + 23 TitleLen? no + 24 Title no + 25 ArtistLen? no + 26 Artist no + 27 CopyrightLen? no + 28 Copyright no + 29 CommentLen? no + 30 Comment no + +=head3 Real AudioV5 Tags + + Sequence Tag Name Writable + -------- -------- -------- + 0 FourCC1? no + 1 AudioFileSize? no + 2 Version2? no + 3 HeaderSize? no + 4 CodecFlavorID? no + 5 CodedFrameSize? no + 6 AudioBytes no + 7 BytesPerMinute no + 8 Unknown? no + 9 SubPacketH? no + 10 FrameSize? no + 11 SubPacketSize? no + 12 SampleRate no + 13 SampleRate2? no + 14 BitsPerSample no + 15 Channels no + 16 Genr? no + 17 FourCC3? no + +=head3 Real Metafile Tags + +Tags representing information extracted from Real Audio Metafile and +RealMedia Plug-in Metafile (RAM and RPM) files. + + Tag ID Tag Name Writable + ------ -------- -------- + 'txt' Text no + 'url' URL no + +=head2 Red Tags + +Tags extracted from Redcode R3D video files. + + Tag ID Tag Name Writable + ------ -------- -------- + 'RED1' Red1Header Red RED1 + 'RED2' Red2Header Red RED2 + 0x1000 StartEdgeCode no + 0x1001 StartTimecode no + 0x1002 OtherDate1 no + 0x1003 OtherDate2 no + 0x1004 OtherDate3 no + 0x1005 DateTimeOriginal no + 0x1006 SerialNumber no + 0x1019 CameraType no + 0x101a ReelNumber no + 0x101b Take no + 0x1023 DateCreated no + 0x1024 TimeCreated no + 0x1025 FirmwareVersion no + 0x1029 ReelTimecode no + 0x102a StorageType no + 0x1030 StorageFormatDate no + 0x1031 StorageFormatTime no + 0x1032 StorageSerialNumber no + 0x1033 StorageModel no + 0x1036 AspectRatio no + 0x1042 Revision no + 0x1056 OriginalFileName no + 0x106e LensMake no + 0x106f LensNumber no + 0x1070 LensModel no + 0x1071 Model no + 0x107c CameraOperator no + 0x1086 VideoFormat no + 0x1096 Filter no + 0x10a0 Brain no + 0x10a1 Sensor no + 0x200d ColorTemperature no + 0x204b RGBCurves no + 0x2066 OriginalFrameRate no + 0x4037 CropArea no + 0x403b ISO no + 0x406a FNumber no + 0x406b FocalLength no + 0x606c FocusDistance no + +=head3 Red RED1 Tags + +Redcode version 1 header. + + Index1 Tag Name Writable + ------ -------- -------- + 7 RedcodeVersion no + 54 ImageWidth no + 58 ImageHeight no + 62 FrameRate no + 67 OriginalFileName no + +=head3 Red RED2 Tags + +Redcode version 2 header. + + Index1 Tag Name Writable + ------ -------- -------- + 7 RedcodeVersion no + 76 ImageWidth no + 80 ImageHeight no + 86 FrameRate no + +=head2 RIFF Tags + +The RIFF container format is used various types of fines including AVI, WAV, +WEBP, LA, OFR, PAC and WV. According to the EXIF specification, Meta +information is embedded in two types of RIFF C<LIST> chunks: C<INFO> and +C<exif>, and information about the audio content is stored in the C<fmt > +chunk. As well as this information, some video information and proprietary +manufacturer-specific information is also extracted. + +Large AVI videos may be a concatenation of two or more RIFF chunks. For +these files, information is extracted from subsequent RIFF chunks as +sub-documents, but the Duration is calculated for the full video. + + Tag ID Tag Name Writable + ------ -------- -------- + 'ALPH' ALPH RIFF ALPH + 'ANIM' ANIM RIFF ANIM + 'ANMF' ANMF RIFF ANMF + 'CSET' CharacterSet RIFF CSET + 'EXIF' EXIF EXIF + 'ICCP' ICC_Profile ICC_Profile + 'IDIT' DateTimeOriginal no + 'JUNK' OlympusJunk Olympus AVI + CasioJunk EXIF + RicohJunk Ricoh AVI + PentaxJunk Pentax Junk + PentaxJunk2 Pentax Junk2 + TextJunk no + 'JUNQ' OldXMP no + 'LIST_INFO' Info RIFF Info + 'LIST_Tdat' Tdat RIFF Tdat + 'LIST_exif' Exif RIFF Exif + 'LIST_hdrl' Hdrl RIFF Hdrl + 'LIST_hydt' PentaxData Pentax AVI + 'LIST_ncdt' NikonData Nikon AVI + 'LIST_pntx' PentaxData2 Pentax AVI + 'SGLT' BikeBroAccel QuickTime Stream + 'SLLT' BikeBroGPS QuickTime Stream + 'VP8 ' VP8Bitstream RIFF VP8 + 'VP8L' VP8L RIFF VP8L + 'VP8X' VP8X RIFF VP8X + 'XMP ' XMP XMP + '_PMX' XMP XMP + 'afsp' Afsp no + 'bext' BroadcastExtension RIFF BroadcastExt + 'cue ' CuePoints no + 'ds64' DataSize64 RIFF DS64 + 'fact' NumberOfSamples no + 'fmt ' AudioFormat RIFF AudioFormat + 'labl' Label RIFF Label + 'list' ListType no + 'olym' Olym Olympus WAV + +=head3 RIFF ALPH Tags + +WebP alpha chunk. + + Index1 Tag Name Writable + ------ -------- -------- + 0 AlphaPreprocessing no + 0.1 AlphaFiltering no + 0.2 AlphaCompression no + +=head3 RIFF ANIM Tags + +WebP animation chunk. + + Index1 Tag Name Writable + ------ -------- -------- + 0 BackgroundColor no + 4 AnimationLoopCount no + +=head3 RIFF ANMF Tags + +WebP animation frame chunk. + + Index1 Tag Name Writable + ------ -------- -------- + 12 Duration no + +=head3 RIFF CSET Tags + + Tag ID Tag Name Writable + ------ -------- -------- + 0x0000 CodePage no + 0x0001 CountryCode no + 0x0002 LanguageCode no + 0x0003 Dialect no + +=head3 RIFF Info Tags + +RIFF INFO tags found in AVI video and WAV audio files. Tags which are part +of the EXIF 2.3 specification have an underlined Tag Name in the HTML +version of this documentation. Other tags are found in AVI files generated +by some software. + + Tag ID Tag Name Writable + ------ -------- -------- + 'AGES' Rated no + 'CMNT' Comment no + 'CODE' EncodedBy no + 'COMM' Comments no + 'DIRC' Directory no + 'DISP' SoundSchemeTitle no + 'DTIM' DateTimeOriginal no + 'GENR' Genre no + 'IARL' ArchivalLocation no + 'IART' Artist no + 'IAS1' FirstLanguage no + 'IAS2' SecondLanguage no + 'IAS3' ThirdLanguage no + 'IAS4' FourthLanguage no + 'IAS5' FifthLanguage no + 'IAS6' SixthLanguage no + 'IAS7' SeventhLanguage no + 'IAS8' EighthLanguage no + 'IAS9' NinthLanguage no + 'IBSU' BaseURL no + 'ICAS' DefaultAudioStream no + 'ICDS' CostumeDesigner no + 'ICMS' Commissioned no + 'ICMT' Comment no + 'ICNM' Cinematographer no + 'ICNT' Country no + 'ICOP' Copyright no + 'ICRD' DateCreated no + 'ICRP' Cropped no + 'IDIM' Dimensions no + 'IDIT' DateTimeOriginal no + 'IDPI' DotsPerInch no + 'IDST' DistributedBy no + 'IEDT' EditedBy no + 'IENC' EncodedBy no + 'IENG' Engineer no + 'IGNR' Genre no + 'IKEY' Keywords no + 'ILGT' Lightness no + 'ILGU' LogoURL no + 'ILIU' LogoIconURL no + 'ILNG' Language no + 'IMBI' MoreInfoBannerImage no + 'IMBU' MoreInfoBannerURL no + 'IMED' Medium no + 'IMIT' MoreInfoText no + 'IMIU' MoreInfoURL no + 'IMUS' MusicBy no + 'INAM' Title no + 'IPDS' ProductionDesigner no + 'IPLT' NumColors no + 'IPRD' Product no + 'IPRO' ProducedBy no + 'IRIP' RippedBy no + 'IRTD' Rating no + 'ISBJ' Subject no + 'ISFT' Software no + 'ISGN' SecondaryGenre no + 'ISHP' Sharpness no + 'ISMP' TimeCode no + 'ISRC' Source no + 'ISRF' SourceForm no + 'ISTD' ProductionStudio no + 'ISTR' Starring no + 'ITCH' Technician no + 'IWMU' WatermarkURL no + 'IWRI' WrittenBy no + 'LANG' Language no + 'LOCA' Location no + 'PRT1' Part no + 'PRT2' NumberOfParts no + 'RATE' Rate no + 'STAR' Starring no + 'STAT' Statistics no + 'TAPE' TapeName no + 'TCDO' EndTimecode no + 'TCOD' StartTimecode no + 'TITL' Title no + 'TLEN' Length no + 'TORG' Organization no + 'TRCK' TrackNumber no + 'TURL' URL no + 'TVER' Version no + 'VMAJ' VegasVersionMajor no + 'VMIN' VegasVersionMinor no + 'YEAR' Year no + +=head3 RIFF Tdat Tags + + Tag ID Tag Name Writable + ------ -------- -------- + [no tags known] + +=head3 RIFF Exif Tags + +These tags are part of the EXIF 2.3 specification for WAV audio files. + + Tag ID Tag Name Writable + ------ -------- -------- + 'ecor' Make no + 'emdl' Model no + 'emnt' MakerNotes no + 'erel' RelatedImageFile no + 'etim' TimeCreated no + 'eucm' UserComment no + 'ever' ExifVersion no + +=head3 RIFF Hdrl Tags + + Tag ID Tag Name Writable + ------ -------- -------- + 'IDIT' DateTimeOriginal no + 'ISMP' TimeCode no + 'LIST_odml' OpenDML RIFF OpenDML + 'LIST_strl' Stream RIFF Stream + 'avih' AVIHeader RIFF AVIHeader + +=head3 RIFF OpenDML Tags + + Tag ID Tag Name Writable + ------ -------- -------- + 'dmlh' ExtendedAVIHeader RIFF ExtAVIHdr + +=head3 RIFF ExtAVIHdr Tags + + Index4 Tag Name Writable + ------ -------- -------- + 0 TotalFrameCount no + +=head3 RIFF Stream Tags + + Tag ID Tag Name Writable + ------ -------- -------- + 'strd' StreamData RIFF StreamData + 'strf' AudioFormat RIFF AudioFormat + VideoFormat BMP + 'strh' StreamHeader RIFF StreamHeader + 'strn' StreamName no + +=head3 RIFF StreamData Tags + +This chunk is used to store proprietary information in AVI videos from some +cameras. The first 4 characters of the data are used as the Tag ID below. + + Tag ID Tag Name Writable + ------ -------- -------- + 'AVIF' AVIF EXIF + 'CASI' CasioData Casio AVI + 'Zora' VendorName no + 'unknown' UnknownData no + +=head3 RIFF AudioFormat Tags + + Index2 Tag Name Writable + ------ -------- -------- + 0 Encoding no + 1 NumChannels no + 2 SampleRate no + 4 AvgBytesPerSec no + 7 BitsPerSample no + +=head3 RIFF StreamHeader Tags + + Index4 Tag Name Writable + ------ -------- -------- + 0 StreamType no + 1 AudioCodec no + VideoCodec no + Codec no + 5 AudioSampleRate no + VideoFrameRate no + StreamSampleRate no + 8 AudioSampleCount no + VideoFrameCount no + StreamSampleCount no + 10 Quality no + 11 SampleSize no + +=head3 RIFF AVIHeader Tags + + Index4 Tag Name Writable + ------ -------- -------- + 0 FrameRate no + 1 MaxDataRate no + 4 FrameCount no + 6 StreamCount no + 8 ImageWidth no + 9 ImageHeight no + +=head3 RIFF VP8 Tags + +This chunk is found in simple-format (lossy) WebP files. See +L<https://developers.google.com/speed/webp/docs/riff_container> for the WebP +container specification. + + Index1 Tag Name Writable + ------ -------- -------- + 0 VP8Version no + 6 ImageWidth no + 6.1 HorizontalScale no + 8 ImageHeight no + 8.1 VerticalScale no + +=head3 RIFF VP8L Tags + +This chunk is found in lossless WebP files. + + Index1 Tag Name Writable + ------ -------- -------- + 1 ImageWidth no + 2 ImageHeight no + +=head3 RIFF VP8X Tags + +This chunk is found in extended WebP files. + + Index1 Tag Name Writable + ------ -------- -------- + 4 ImageWidth no + 6 ImageHeight no + +=head3 RIFF BroadcastExt Tags + +Information found in the Broadcast Audio Extension chunk (see +L<http://tech.ebu.ch/docs/tech/tech3285.pdf>). + + Index1 Tag Name Writable + ------ -------- -------- + 0 Description no + 256 Originator no + 288 OriginatorReference no + 320 DateTimeOriginal no + 338 TimeReference no + 346 BWFVersion no + 602 CodingHistory no + +=head3 RIFF DS64 Tags + +64-bit data sizes for MBWF/RF64 files. See +L<https://tech.ebu.ch/docs/tech/tech3306-2009.pdf> for the specification. + + Index8 Tag Name Writable + ------ -------- -------- + 0 RIFFSize64 no + 1 DataSize64 no + 2 NumberOfSamples64 no + +=head3 RIFF Label Tags + + Index4 Tag Name Writable + ------ -------- -------- + 0 LabelID no + 1 LabelText no + +=head2 AIFF Tags + +Tags extracted from Audio Interchange File Format (AIFF) files. See +L<http://www-mmsp.ece.mcgill.ca/Documents/AudioFormats/AIFF/AIFF.html> for +the AIFF specification. + + Tag ID Tag Name Writable + ------ -------- -------- + '(c) ' Copyright no + 'ANNO' Annotation no + 'AUTH' Author no + 'COMM' Common AIFF Common + 'COMT' Comment AIFF Comment + 'FVER' FormatVersion AIFF FormatVers + 'ID3 ' ID3 ID3 + 'NAME' Name no + +=head3 AIFF Common Tags + + Index2 Tag Name Writable + ------ -------- -------- + 0 NumChannels no + 1 NumSampleFrames no + 3 SampleSize no + 4 SampleRate no + 9 CompressionType no + 11 CompressorName no + +=head3 AIFF Comment Tags + + Tag ID Tag Name Writable + ------ -------- -------- + 0x0000 CommentTime no + 0x0001 MarkerID no + 0x0002 Comment no + +=head3 AIFF FormatVers Tags + + Index4 Tag Name Writable + ------ -------- -------- + 0 FormatVersionTime no + +=head2 ASF Tags + +The ASF format is used by Windows WMA and WMV files, and DIVX videos. Tag +ID's aren't listed because they are huge 128-bit GUID's that would ruin the +formatting of this table. + + Tag Name Writable + -------- -------- + SimpleIndex no + TimecodeIndex no + Header ASF Header + Data no + XMP XMP + Index no + MediaIndex no + +=head3 ASF Header Tags + + Tag Name Writable + -------- -------- + Padding no + ScriptCommand no + ContentBranding ASF ContentBranding + ContentEncryption no + DigitalSignature no + ExtendedContentEncryption no + HeaderExtension ASF HeaderExtension + ContentDescription ASF ContentDescr + ErrorCorrection no + StreamBitrateProps no + CodecList ASF CodecList + FileProperties ASF FileProperties + StreamProperties ASF StreamProperties + ExtendedContentDescr ASF ExtendedDescr + BitrateMutualExclusion no + Marker no + +=head3 ASF ContentBranding Tags + + Tag Name Writable + -------- -------- + BannerImageType no + BannerImage no + BannerImageURL no + CopyrightURL no + +=head3 ASF HeaderExtension Tags + + Tag Name Writable + -------- -------- + ExtendedStreamProps no + AdvancedContentEncryption no + MetadataLibrary ASF ExtendedDescr + TimecodeIndexParms no + Compatibility no + LanguageList no + AdvancedMutualExcl no + BandwidthSharing no + Reserved1 no + Metadata ASF ExtendedDescr + GroupMutualExclusion no + StreamPrioritization no + IndexParameters no + +=head3 ASF ExtendedDescr Tags + + Tag Name Writable + -------- -------- + ASFLeakyBucketPairs no + ASFPacketCount no + ASFSecurityObjectsSize no + AlbumArtist no + AlbumCoverURL no + AlbumTitle no + AspectRatioX no + AspectRatioY no + AudioFileURL no + AudioSourceURL no + Author no + AuthorURL no + AverageLevel no + BannerImageData no + BannerImageType no + BannerImageURL no + BeatsPerMinute no + Bitrate no + Broadcast no + BufferAverage no + Can_Skip_Backward no + Can_Skip_Forward no + Category no + Codec no + Composer no + Conductor no + ContainerFormat no + ContentDistributor no + ContentGroupDescription no + Copyright no + CopyrightURL no + CurrentBitrate no + DRM no + DRM_ContentID no + DRM_DRMHeader no + DRM_DRMHeader_ContentDistributor no + DRM_DRMHeader_ContentID no + DRM_DRMHeader_IndividualizedVersion no + DRM_DRMHeader_KeyID no + DRM_DRMHeader_LicenseAcqURL no + DRM_DRMHeader_SubscriptionContentID no + DRM_IndividualizedVersion no + DRM_KeyID no + DRM_LASignatureCert no + DRM_LASignatureLicSrvCert no + DRM_LASignaturePrivKey no + DRM_LASignatureRootCert no + DRM_LicenseAcqURL no + DRM_V1LicenseAcqURL no + DVDID no + Description no + Director no + Duration no + EncodedBy no + EncodingSettings no + EncodingTime no + FileSize no + Genre no + GenreID no + HasArbitraryDataStream no + HasAttachedImages no + HasAudio no + HasFileTransferStream no + HasImage no + HasScript no + HasVideo no + ISRC no + InitialKey no + IsVBR no + Is_Protected no + Is_Trusted no + Language no + Lyrics no + Lyrics_Synchronised no + MCDI no + MediaClassPrimaryID no + MediaClassSecondaryID no + MediaCredits no + MediaIsDelay no + MediaIsFinale no + MediaIsLive no + MediaIsPremiere no + MediaIsRepeat no + MediaIsSAP no + MediaIsStereo no + MediaIsSubtitled no + MediaIsTape no + MediaNetworkAffiliation no + MediaOriginalBroadcastDateTime no + MediaOriginalChannel no + MediaStationCallSign no + MediaStationName no + ModifiedBy no + Mood no + NSC_Address no + NSC_Description no + NSC_Email no + NSC_Name no + NSC_Phone no + NumberOfFrames no + OptimalBitrate no + OriginalAlbumTitle no + OriginalArtist no + OriginalFileName no + OriginalLyricist no + OriginalReleaseTime no + OriginalReleaseYear no + ParentalRating no + ParentalRatingReason no + PartOfSet no + PeakBitrate no + PeakValue no + Period no + Picture ASF Picture + PlaylistDelay no + Producer no + PromotionURL no + ProtectionType no + Provider no + ProviderCopyright no + ProviderRating no + ProviderStyle no + Publisher no + RadioStationName no + RadioStationOwner no + Rating no + Seekable no + SharedUserRating no + Signature_Name no + StreamTypeInfo no + Stridable no + Subtitle no + SubtitleDescription no + SubscriptionContentID no + Text no + Title no + ToolName no + ToolVersion no + Track no + TrackNumber no + UniqueFileIdentifier no + UserWebURL no + VBRPeak no + VideoClosedCaptioning no + VideoFrameRate no + VideoHeight no + VideoWidth no + WMADRCAverageReference no + WMADRCAverageTarget no + WMADRCPeakReference no + WMADRCPeakTarget no + WMCollectionGroupID no + WMCollectionID no + WMContentID no + Writer no + Year no + +=head3 ASF Picture Tags + + Tag Name Writable + -------- -------- + PictureType no + PictureMIMEType no + PictureDescription no + Picture no + +=head3 ASF ContentDescr Tags + + Tag Name Writable + -------- -------- + Title no + Author no + Copyright no + Description no + Rating no + +=head3 ASF CodecList Tags + + Tag Name Writable + -------- -------- + AudioCodecDescription no + AudioCodecName no + OtherCodecDescription no + OtherCodecName no + VideoCodecDescription no + VideoCodecName no + +=head3 ASF FileProperties Tags + + Index1 Tag Name Writable + ------ -------- -------- + 0 FileID no + 16 FileLength no + 24 CreationDate no + 32 DataPackets no + 40 Duration no + 48 SendDuration no + 56 Preroll no + 64 Flags no + 68 MinPacketSize no + 72 MaxPacketSize no + 76 MaxBitrate no + +=head3 ASF StreamProperties Tags + +Tags with index 54 and greater are conditional based on the StreamType. + + Index1 Tag Name Writable + ------ -------- -------- + 0 StreamType no + 16 ErrorCorrectionType no + 32 TimeOffset no + 48 StreamNumber no + 54 AudioCodecID no + ImageWidth no + 56 AudioChannels no + 58 AudioSampleRate no + ImageHeight no + +=head2 WTV Tags + +Tags found in Windows recorded TV (WTV) videos. + + Tag ID Tag Name Writable + ------ -------- -------- + 'table.0.entries.legacy_attrib' Metdata WTV Metadata + +=head3 WTV Metadata Tags + +ExifTool will extract any tag found, even if not in this table. + + Tag Name Writable + -------- -------- + ATSCContent no + ActualSoftPostPadding no + ActualSoftPrePadding no + Bitrate? no + BrandingImageID no + BrandingName no + ContentProtected no + ContentProtectedPercent no + DTVContent no + Duration no + EncodeTime no + EndTime no + ExpirationDate? no + ExpirationSpan? no + Genre no + HDContent no + HardPostPadding no + HardPrePadding no + InBandRatingAttributes no + InBandRatingLevel no + InBandRatingSystem no + KeepUntil no + Language no + MediaClassPrimaryID no + MediaClassSecondaryID no + MediaCredits no + MediaIsDelay no + MediaIsFinale no + MediaIsLive no + MediaIsMovie no + MediaIsPremiere no + MediaIsRepeat no + MediaIsSAP no + MediaIsSport no + MediaIsStereo no + MediaIsSubtitled no + MediaIsTape no + MediaNetworkAffiliation no + MediaOriginalBroadcastDateTime no + MediaOriginalChannel no + MediaOriginalChannelSubNumber no + MediaOriginalRunTime no + MediaStationCallSign no + MediaStationName no + MediaThumbAspectRatioX no + MediaThumbAspectRatioY no + MediaThumbHeight no + MediaThumbRatingAttributes no + MediaThumbRatingLevel no + MediaThumbRatingSystem no + MediaThumbRet no + MediaThumbStride no + MediaThumbTimeStamp? no + MediaThumbWidth no + OriginalReleaseTime no + OriginalSoftPostPadding no + OriginalSoftPrePadding no + ParentalRating no + ParentalRatingReason no + ProgramID no + Provider no + ProviderCopyright no + ProviderRating no + Quality no + RequestID no + ScheduleItemID no + SeriesUID no + ServiceID no + Subtitle no + SubtitleDescription no + Title no + VideoClosedCaptioning no + Watched no + +=head2 DICOM Tags + +The DICOM format is based on the ACR-NEMA specification, but adds a file +header and a number of new tags. ExifTool will extract information from +either type of file. The Tag ID's in the following table are the tag group +and element numbers in hexadecimal, as given in the DICOM specification (see +L<http://medical.nema.org/>). The table below contains tags from the DICOM +2009 and earlier specifications plus some vendor-specific private tags. + +Note that DICOM information may be saved in other file formats using the +L<XMP DICOM Tags|Image::ExifTool::TagNames/XMP DICOM Tags>. + + Tag ID Tag Name Writable + ------ -------- -------- + 0002,0000 FileMetaInfoGroupLength no + 0002,0001 FileMetaInfoVersion no + 0002,0002 MediaStorageSOPClassUID no + 0002,0003 MediaStorageSOPInstanceUID no + 0002,0010 TransferSyntaxUID no + 0002,0012 ImplementationClassUID no + 0002,0013 ImplementationVersionName no + 0002,0016 SourceApplicationEntityTitle no + 0002,0100 PrivateInformationCreatorUID no + 0002,0102 PrivateInformation no + 0004,1130 FileSetID no + 0004,1141 FileSetDescriptorFileID no + 0004,1142 SpecificCharacterSetOfFile no + 0004,1200 FirstDirectoryRecordOffset no + 0004,1202 LastDirectoryRecordOffset no + 0004,1212 FileSetConsistencyFlag no + 0004,1220 DirectoryRecordSequence no + 0004,1400 OffsetOfNextDirectoryRecord no + 0004,1410 RecordInUseFlag no + 0004,1420 LowerLevelDirectoryEntityOffset no + 0004,1430 DirectoryRecordType no + 0004,1432 PrivateRecordUID no + 0004,1500 ReferencedFileID no + 0004,1504 MRDRDirectoryRecordOffset no + 0004,1510 ReferencedSOPClassUIDInFile no + 0004,1511 ReferencedSOPInstanceUIDInFile no + 0004,1512 ReferencedTransferSyntaxUIDInFile no + 0004,151A ReferencedRelatedSOPClassUIDInFile no + 0004,1600 NumberOfReferences no + 0008,0000 IdentifyingGroupLength no + 0008,0001 LengthToEnd no + 0008,0005 SpecificCharacterSet no + 0008,0006 LanguageCodeSequence no + 0008,0008 ImageType no + 0008,0010 RecognitionCode no + 0008,0012 InstanceCreationDate no + 0008,0013 InstanceCreationTime no + 0008,0014 InstanceCreatorUID no + 0008,0016 SOPClassUID no + 0008,0018 SOPInstanceUID no + 0008,001A RelatedGeneralSOPClassUID no + 0008,001B OriginalSpecializedSOPClassUID no + 0008,0020 StudyDate no + 0008,0021 SeriesDate no + 0008,0022 AcquisitionDate no + 0008,0023 ContentDate no + 0008,0024 OverlayDate no + 0008,0025 CurveDate no + 0008,002A AcquisitionDateTime no + 0008,0030 StudyTime no + 0008,0031 SeriesTime no + 0008,0032 AcquisitionTime no + 0008,0033 ContentTime no + 0008,0034 OverlayTime no + 0008,0035 CurveTime no + 0008,0040 DataSetType no + 0008,0041 DataSetSubtype no + 0008,0042 NuclearMedicineSeriesType no + 0008,0050 AccessionNumber no + 0008,0052 QueryRetrieveLevel no + 0008,0054 RetrieveAETitle no + 0008,0056 InstanceAvailability no + 0008,0058 FailedSOPInstanceUIDList no + 0008,0060 Modality no + 0008,0061 ModalitiesInStudy no + 0008,0062 SOPClassesInStudy no + 0008,0064 ConversionType no + 0008,0068 PresentationIntentType no + 0008,0070 Manufacturer no + 0008,0080 InstitutionName no + 0008,0081 InstitutionAddress no + 0008,0082 InstitutionCodeSequence no + 0008,0090 ReferringPhysicianName no + 0008,0092 ReferringPhysicianAddress no + 0008,0094 ReferringPhysicianTelephoneNumber no + 0008,0096 ReferringPhysicianIDSequence no + 0008,0100 CodeValue no + 0008,0102 CodingSchemeDesignator no + 0008,0103 CodingSchemeVersion no + 0008,0104 CodeMeaning no + 0008,0105 MappingResource no + 0008,0106 ContextGroupVersion no + 0008,0107 ContextGroupLocalVersion no + 0008,010B ContextGroupExtensionFlag no + 0008,010C CodingSchemeUID no + 0008,010D ContextGroupExtensionCreatorUID no + 0008,010F ContextIdentifier no + 0008,0110 CodingSchemeIDSequence no + 0008,0112 CodingSchemeRegistry no + 0008,0114 CodingSchemeExternalID no + 0008,0115 CodingSchemeName no + 0008,0116 ResponsibleOrganization no + 0008,0117 ContextUID no + 0008,0201 TimezoneOffsetFromUTC no + 0008,1000 NetworkID no + 0008,1010 StationName no + 0008,1030 StudyDescription no + 0008,1032 ProcedureCodeSequence no + 0008,103E SeriesDescription no + 0008,1040 InstitutionalDepartmentName no + 0008,1048 PhysiciansOfRecord no + 0008,1049 PhysiciansOfRecordIDSequence no + 0008,1050 PerformingPhysicianName no + 0008,1052 PerformingPhysicianIDSequence no + 0008,1060 NameOfPhysicianReadingStudy no + 0008,1062 PhysicianReadingStudyIDSequence no + 0008,1070 OperatorsName no + 0008,1072 OperatorIDSequence no + 0008,1080 AdmittingDiagnosesDescription no + 0008,1084 AdmittingDiagnosesCodeSequence no + 0008,1090 ManufacturersModelName no + 0008,1100 ReferencedResultsSequence no + 0008,1110 ReferencedStudySequence no + 0008,1111 ReferencedProcedureStepSequence no + 0008,1115 ReferencedSeriesSequence no + 0008,1120 ReferencedPatientSequence no + 0008,1125 ReferencedVisitSequence no + 0008,1130 ReferencedOverlaySequence no + 0008,113A ReferencedWaveformSequence no + 0008,1140 ReferencedImageSequence no + 0008,1145 ReferencedCurveSequence no + 0008,114A ReferencedInstanceSequence no + 0008,1150 ReferencedSOPClassUID no + 0008,1155 ReferencedSOPInstanceUID no + 0008,115A SOPClassesSupported no + 0008,1160 ReferencedFrameNumber no + 0008,1161 SimpleFrameList no + 0008,1162 CalculatedFrameList no + 0008,1163 TimeRange no + 0008,1164 FrameExtractionSequence no + 0008,1195 TransactionUID no + 0008,1197 FailureReason no + 0008,1198 FailedSOPSequence no + 0008,1199 ReferencedSOPSequence no + 0008,1200 OtherReferencedStudiesSequence no + 0008,1250 RelatedSeriesSequence no + 0008,2110 LossyImageCompression no + 0008,2111 DerivationDescription no + 0008,2112 SourceImageSequence no + 0008,2120 StageName no + 0008,2122 StageNumber no + 0008,2124 NumberOfStages no + 0008,2127 ViewName no + 0008,2128 ViewNumber no + 0008,2129 NumberOfEventTimers no + 0008,212A NumberOfViewsInStage no + 0008,2130 EventElapsedTimes no + 0008,2132 EventTimerNames no + 0008,2133 EventTimerSequence no + 0008,2134 EventTimeOffset no + 0008,2135 EventCodeSequence no + 0008,2142 StartTrim no + 0008,2143 StopTrim no + 0008,2144 RecommendedDisplayFrameRate no + 0008,2200 TransducerPosition no + 0008,2204 TransducerOrientation no + 0008,2208 AnatomicStructure no + 0008,2218 AnatomicRegionSequence no + 0008,2220 AnatomicRegionModifierSequence no + 0008,2228 PrimaryAnatomicStructureSequence no + 0008,2229 AnatomicStructureOrRegionSequence no + 0008,2230 AnatomicStructureModifierSequence no + 0008,2240 TransducerPositionSequence no + 0008,2242 TransducerPositionModifierSequence no + 0008,2244 TransducerOrientationSequence no + 0008,2246 TransducerOrientationModifierSeq no + 0008,2253 AnatomicEntrancePortalCodeSeqTrial no + 0008,2255 AnatomicApproachDirCodeSeqTrial no + 0008,2256 AnatomicPerspectiveDescrTrial no + 0008,2257 AnatomicPerspectiveCodeSeqTrial no + 0008,3001 AlternateRepresentationSequence no + 0008,3010 IrradiationEventUID no + 0008,4000 IdentifyingComments no + 0008,9007 FrameType no + 0008,9092 ReferencedImageEvidenceSequence no + 0008,9121 ReferencedRawDataSequence no + 0008,9123 CreatorVersionUID no + 0008,9124 DerivationImageSequence no + 0008,9154 SourceImageEvidenceSequence no + 0008,9205 PixelPresentation no + 0008,9206 VolumetricProperties no + 0008,9207 VolumeBasedCalculationTechnique no + 0008,9208 ComplexImageComponent no + 0008,9209 AcquisitionContrast no + 0008,9215 DerivationCodeSequence no + 0008,9237 GrayscalePresentationStateSequence no + 0008,9410 ReferencedOtherPlaneSequence no + 0008,9458 FrameDisplaySequence no + 0008,9459 RecommendedDisplayFrameRateInFloat no + 0008,9460 SkipFrameRangeFlag no + 0009,1001 FullFidelity no + 0009,1002 SuiteID no + 0009,1004 ProductID no + 0009,1027 ImageActualDate no + 0009,1030 ServiceID no + 0009,1031 MobileLocationNumber no + 0009,10E3 EquipmentUID no + 0009,10E6 GenesisVersionNow no + 0009,10E7 ExamRecordChecksum no + 0009,10E9 ActualSeriesDataTimeStamp no + 0010,0000 PatientGroupLength no + 0010,0010 PatientName no + 0010,0020 PatientID no + 0010,0021 IssuerOfPatientID no + 0010,0022 TypeOfPatientID no + 0010,0030 PatientBirthDate no + 0010,0032 PatientBirthTime no + 0010,0040 PatientSex no + 0010,0050 PatientInsurancePlanCodeSequence no + 0010,0101 PatientPrimaryLanguageCodeSeq no + 0010,0102 PatientPrimaryLanguageCodeModSeq no + 0010,1000 OtherPatientIDs no + 0010,1001 OtherPatientNames no + 0010,1002 OtherPatientIDsSequence no + 0010,1005 PatientBirthName no + 0010,1010 PatientAge no + 0010,1020 PatientSize no + 0010,1030 PatientWeight no + 0010,1040 PatientAddress no + 0010,1050 InsurancePlanIdentification no + 0010,1060 PatientMotherBirthName no + 0010,1080 MilitaryRank no + 0010,1081 BranchOfService no + 0010,1090 MedicalRecordLocator no + 0010,2000 MedicalAlerts no + 0010,2110 Allergies no + 0010,2150 CountryOfResidence no + 0010,2152 RegionOfResidence no + 0010,2154 PatientTelephoneNumbers no + 0010,2160 EthnicGroup no + 0010,2180 Occupation no + 0010,21A0 SmokingStatus no + 0010,21B0 AdditionalPatientHistory no + 0010,21C0 PregnancyStatus no + 0010,21D0 LastMenstrualDate no + 0010,21F0 PatientReligiousPreference no + 0010,2201 PatientSpeciesDescription no + 0010,2202 PatientSpeciesCodeSequence no + 0010,2203 PatientSexNeutered no + 0010,2210 AnatomicalOrientationType no + 0010,2292 PatientBreedDescription no + 0010,2293 PatientBreedCodeSequence no + 0010,2294 BreedRegistrationSequence no + 0010,2295 BreedRegistrationNumber no + 0010,2296 BreedRegistryCodeSequence no + 0010,2297 ResponsiblePerson no + 0010,2298 ResponsiblePersonRole no + 0010,2299 ResponsibleOrganization no + 0010,4000 PatientComments no + 0010,9431 ExaminedBodyThickness no + 0011,1010 PatientStatus no + 0012,0010 ClinicalTrialSponsorName no + 0012,0020 ClinicalTrialProtocolID no + 0012,0021 ClinicalTrialProtocolName no + 0012,0030 ClinicalTrialSiteID no + 0012,0031 ClinicalTrialSiteName no + 0012,0040 ClinicalTrialSubjectID no + 0012,0042 ClinicalTrialSubjectReadingID no + 0012,0050 ClinicalTrialTimePointID no + 0012,0051 ClinicalTrialTimePointDescription no + 0012,0060 ClinicalTrialCoordinatingCenter no + 0012,0062 PatientIdentityRemoved no + 0012,0063 DeidentificationMethod no + 0012,0064 DeidentificationMethodCodeSequence no + 0012,0071 ClinicalTrialSeriesID no + 0012,0072 ClinicalTrialSeriesDescription no + 0012,0084 DistributionType no + 0012,0085 ConsentForDistributionFlag no + 0018,0000 AcquisitionGroupLength no + 0018,0010 ContrastBolusAgent no + 0018,0012 ContrastBolusAgentSequence no + 0018,0014 ContrastBolusAdministrationRoute no + 0018,0015 BodyPartExamined no + 0018,0020 ScanningSequence no + 0018,0021 SequenceVariant no + 0018,0022 ScanOptions no + 0018,0023 MRAcquisitionType no + 0018,0024 SequenceName no + 0018,0025 AngioFlag no + 0018,0026 InterventionDrugInformationSeq no + 0018,0027 InterventionDrugStopTime no + 0018,0028 InterventionDrugDose no + 0018,0029 InterventionDrugSequence no + 0018,002A AdditionalDrugSequence no + 0018,0030 Radionuclide no + 0018,0031 Radiopharmaceutical no + 0018,0032 EnergyWindowCenterline no + 0018,0033 EnergyWindowTotalWidth no + 0018,0034 InterventionDrugName no + 0018,0035 InterventionDrugStartTime no + 0018,0036 InterventionSequence no + 0018,0037 TherapyType no + 0018,0038 InterventionStatus no + 0018,0039 TherapyDescription no + 0018,003A InterventionDescription no + 0018,0040 CineRate no + 0018,0042 InitialCineRunState no + 0018,0050 SliceThickness no + 0018,0060 KVP no + 0018,0070 CountsAccumulated no + 0018,0071 AcquisitionTerminationCondition no + 0018,0072 EffectiveDuration no + 0018,0073 AcquisitionStartCondition no + 0018,0074 AcquisitionStartConditionData no + 0018,0075 AcquisitionEndConditionData no + 0018,0080 RepetitionTime no + 0018,0081 EchoTime no + 0018,0082 InversionTime no + 0018,0083 NumberOfAverages no + 0018,0084 ImagingFrequency no + 0018,0085 ImagedNucleus no + 0018,0086 EchoNumber no + 0018,0087 MagneticFieldStrength no + 0018,0088 SpacingBetweenSlices no + 0018,0089 NumberOfPhaseEncodingSteps no + 0018,0090 DataCollectionDiameter no + 0018,0091 EchoTrainLength no + 0018,0093 PercentSampling no + 0018,0094 PercentPhaseFieldOfView no + 0018,0095 PixelBandwidth no + 0018,1000 DeviceSerialNumber no + 0018,1002 DeviceUID no + 0018,1003 DeviceID no + 0018,1004 PlateID no + 0018,1005 GeneratorID no + 0018,1006 GridID no + 0018,1007 CassetteID no + 0018,1008 GantryID no + 0018,1010 SecondaryCaptureDeviceID no + 0018,1011 HardcopyCreationDeviceID no + 0018,1012 DateOfSecondaryCapture no + 0018,1014 TimeOfSecondaryCapture no + 0018,1016 SecondaryCaptureDeviceManufacturer no + 0018,1017 HardcopyDeviceManufacturer no + 0018,1018 SecondaryCaptureDeviceModelName no + 0018,1019 SecondaryCaptureDeviceSoftwareVers no + 0018,101A HardcopyDeviceSoftwareVersion no + 0018,101B HardcopyDeviceModelName no + 0018,1020 SoftwareVersion no + 0018,1022 VideoImageFormatAcquired no + 0018,1023 DigitalImageFormatAcquired no + 0018,1030 ProtocolName no + 0018,1040 ContrastBolusRoute no + 0018,1041 ContrastBolusVolume no + 0018,1042 ContrastBolusStartTime no + 0018,1043 ContrastBolusStopTime no + 0018,1044 ContrastBolusTotalDose no + 0018,1045 SyringeCounts no + 0018,1046 ContrastFlowRate no + 0018,1047 ContrastFlowDuration no + 0018,1048 ContrastBolusIngredient no + 0018,1049 ContrastBolusConcentration no + 0018,1050 SpatialResolution no + 0018,1060 TriggerTime no + 0018,1061 TriggerSourceOrType no + 0018,1062 NominalInterval no + 0018,1063 FrameTime no + 0018,1064 CardiacFramingType no + 0018,1065 FrameTimeVector no + 0018,1066 FrameDelay no + 0018,1067 ImageTriggerDelay no + 0018,1068 MultiplexGroupTimeOffset no + 0018,1069 TriggerTimeOffset no + 0018,106A SynchronizationTrigger no + 0018,106C SynchronizationChannel no + 0018,106E TriggerSamplePosition no + 0018,1070 RadiopharmaceuticalRoute no + 0018,1071 RadiopharmaceuticalVolume no + 0018,1072 RadiopharmaceuticalStartTime no + 0018,1073 RadiopharmaceuticalStopTime no + 0018,1074 RadionuclideTotalDose no + 0018,1075 RadionuclideHalfLife no + 0018,1076 RadionuclidePositronFraction no + 0018,1077 RadiopharmaceuticalSpecActivity no + 0018,1078 RadiopharmaceuticalStartDateTime no + 0018,1079 RadiopharmaceuticalStopDateTime no + 0018,1080 BeatRejectionFlag no + 0018,1081 LowRRValue no + 0018,1082 HighRRValue no + 0018,1083 IntervalsAcquired no + 0018,1084 IntervalsRejected no + 0018,1085 PVCRejection no + 0018,1086 SkipBeats no + 0018,1088 HeartRate no + 0018,1090 CardiacNumberOfImages no + 0018,1094 TriggerWindow no + 0018,1100 ReconstructionDiameter no + 0018,1110 DistanceSourceToDetector no + 0018,1111 DistanceSourceToPatient no + 0018,1114 EstimatedRadiographicMagnification no + 0018,1120 GantryDetectorTilt no + 0018,1121 GantryDetectorSlew no + 0018,1130 TableHeight no + 0018,1131 TableTraverse no + 0018,1134 TableMotion no + 0018,1135 TableVerticalIncrement no + 0018,1136 TableLateralIncrement no + 0018,1137 TableLongitudinalIncrement no + 0018,1138 TableAngle no + 0018,113A TableType no + 0018,1140 RotationDirection no + 0018,1141 AngularPosition no + 0018,1142 RadialPosition no + 0018,1143 ScanArc no + 0018,1144 AngularStep no + 0018,1145 CenterOfRotationOffset no + 0018,1146 RotationOffset no + 0018,1147 FieldOfViewShape no + 0018,1149 FieldOfViewDimensions no + 0018,1150 ExposureTime no + 0018,1151 XRayTubeCurrent no + 0018,1152 Exposure no + 0018,1153 ExposureInMicroAmpSec no + 0018,1154 AveragePulseWidth no + 0018,1155 RadiationSetting no + 0018,1156 RectificationType no + 0018,115A RadiationMode no + 0018,115E ImageAreaDoseProduct no + 0018,1160 FilterType no + 0018,1161 TypeOfFilters no + 0018,1162 IntensifierSize no + 0018,1164 ImagerPixelSpacing no + 0018,1166 Grid no + 0018,1170 GeneratorPower no + 0018,1180 CollimatorGridName no + 0018,1181 CollimatorType no + 0018,1182 FocalDistance no + 0018,1183 XFocusCenter no + 0018,1184 YFocusCenter no + 0018,1190 FocalSpots no + 0018,1191 AnodeTargetMaterial no + 0018,11A0 BodyPartThickness no + 0018,11A2 CompressionForce no + 0018,1200 DateOfLastCalibration no + 0018,1201 TimeOfLastCalibration no + 0018,1210 ConvolutionKernel no + 0018,1240 UpperLowerPixelValues no + 0018,1242 ActualFrameDuration no + 0018,1243 CountRate no + 0018,1244 PreferredPlaybackSequencing no + 0018,1250 ReceiveCoilName no + 0018,1251 TransmitCoilName no + 0018,1260 PlateType no + 0018,1261 PhosphorType no + 0018,1300 ScanVelocity no + 0018,1301 WholeBodyTechnique no + 0018,1302 ScanLength no + 0018,1310 AcquisitionMatrix no + 0018,1312 InPlanePhaseEncodingDirection no + 0018,1314 FlipAngle no + 0018,1315 VariableFlipAngleFlag no + 0018,1316 SAR no + 0018,1318 DB-Dt no + 0018,1400 AcquisitionDeviceProcessingDescr no + 0018,1401 AcquisitionDeviceProcessingCode no + 0018,1402 CassetteOrientation no + 0018,1403 CassetteSize no + 0018,1404 ExposuresOnPlate no + 0018,1405 RelativeXRayExposure no + 0018,1450 ColumnAngulation no + 0018,1460 TomoLayerHeight no + 0018,1470 TomoAngle no + 0018,1480 TomoTime no + 0018,1490 TomoType no + 0018,1491 TomoClass no + 0018,1495 NumberOfTomosynthesisSourceImages no + 0018,1500 PositionerMotion no + 0018,1508 PositionerType no + 0018,1510 PositionerPrimaryAngle no + 0018,1511 PositionerSecondaryAngle no + 0018,1520 PositionerPrimaryAngleIncrement no + 0018,1521 PositionerSecondaryAngleIncrement no + 0018,1530 DetectorPrimaryAngle no + 0018,1531 DetectorSecondaryAngle no + 0018,1600 ShutterShape no + 0018,1602 ShutterLeftVerticalEdge no + 0018,1604 ShutterRightVerticalEdge no + 0018,1606 ShutterUpperHorizontalEdge no + 0018,1608 ShutterLowerHorizontalEdge no + 0018,1610 CenterOfCircularShutter no + 0018,1612 RadiusOfCircularShutter no + 0018,1620 VerticesOfPolygonalShutter no + 0018,1622 ShutterPresentationValue no + 0018,1623 ShutterOverlayGroup no + 0018,1624 ShutterPresentationColorCIELabVal no + 0018,1700 CollimatorShape no + 0018,1702 CollimatorLeftVerticalEdge no + 0018,1704 CollimatorRightVerticalEdge no + 0018,1706 CollimatorUpperHorizontalEdge no + 0018,1708 CollimatorLowerHorizontalEdge no + 0018,1710 CenterOfCircularCollimator no + 0018,1712 RadiusOfCircularCollimator no + 0018,1720 VerticesOfPolygonalCollimator no + 0018,1800 AcquisitionTimeSynchronized no + 0018,1801 TimeSource no + 0018,1802 TimeDistributionProtocol no + 0018,1803 NTPSourceAddress no + 0018,2001 PageNumberVector no + 0018,2002 FrameLabelVector no + 0018,2003 FramePrimaryAngleVector no + 0018,2004 FrameSecondaryAngleVector no + 0018,2005 SliceLocationVector no + 0018,2006 DisplayWindowLabelVector no + 0018,2010 NominalScannedPixelSpacing no + 0018,2020 DigitizingDeviceTransportDirection no + 0018,2030 RotationOfScannedFilm no + 0018,3100 IVUSAcquisition no + 0018,3101 IVUSPullbackRate no + 0018,3102 IVUSGatedRate no + 0018,3103 IVUSPullbackStartFrameNumber no + 0018,3104 IVUSPullbackStopFrameNumber no + 0018,3105 LesionNumber no + 0018,4000 AcquisitionComments no + 0018,5000 OutputPower no + 0018,5010 TransducerData no + 0018,5012 FocusDepth no + 0018,5020 ProcessingFunction no + 0018,5021 PostprocessingFunction no + 0018,5022 MechanicalIndex no + 0018,5024 BoneThermalIndex no + 0018,5026 CranialThermalIndex no + 0018,5027 SoftTissueThermalIndex no + 0018,5028 SoftTissueFocusThermalIndex no + 0018,5029 SoftTissueSurfaceThermalIndex no + 0018,5030 DynamicRange no + 0018,5040 TotalGain no + 0018,5050 DepthOfScanField no + 0018,5100 PatientPosition no + 0018,5101 ViewPosition no + 0018,5104 ProjectionEponymousNameCodeSeq no + 0018,5210 ImageTransformationMatrix no + 0018,5212 ImageTranslationVector no + 0018,6000 Sensitivity no + 0018,6011 SequenceOfUltrasoundRegions no + 0018,6012 RegionSpatialFormat no + 0018,6014 RegionDataType no + 0018,6016 RegionFlags no + 0018,6018 RegionLocationMinX0 no + 0018,601A RegionLocationMinY0 no + 0018,601C RegionLocationMaxX1 no + 0018,601E RegionLocationMaxY1 no + 0018,6020 ReferencePixelX0 no + 0018,6022 ReferencePixelY0 no + 0018,6024 PhysicalUnitsXDirection no + 0018,6026 PhysicalUnitsYDirection no + 0018,6028 ReferencePixelPhysicalValueX no + 0018,602A ReferencePixelPhysicalValueY no + 0018,602C PhysicalDeltaX no + 0018,602E PhysicalDeltaY no + 0018,6030 TransducerFrequency no + 0018,6031 TransducerType no + 0018,6032 PulseRepetitionFrequency no + 0018,6034 DopplerCorrectionAngle no + 0018,6036 SteeringAngle no + 0018,6038 DopplerSampleVolumeXPosRetired no + 0018,6039 DopplerSampleVolumeXPosition no + 0018,603A DopplerSampleVolumeYPosRetired no + 0018,603B DopplerSampleVolumeYPosition no + 0018,603C TMLinePositionX0Retired no + 0018,603D TMLinePositionX0 no + 0018,603E TMLinePositionY0Retired no + 0018,603F TMLinePositionY0 no + 0018,6040 TMLinePositionX1Retired no + 0018,6041 TMLinePositionX1 no + 0018,6042 TMLinePositionY1Retired no + 0018,6043 TMLinePositionY1 no + 0018,6044 PixelComponentOrganization no + 0018,6046 PixelComponentMask no + 0018,6048 PixelComponentRangeStart no + 0018,604A PixelComponentRangeStop no + 0018,604C PixelComponentPhysicalUnits no + 0018,604E PixelComponentDataType no + 0018,6050 NumberOfTableBreakPoints no + 0018,6052 TableOfXBreakPoints no + 0018,6054 TableOfYBreakPoints no + 0018,6056 NumberOfTableEntries no + 0018,6058 TableOfPixelValues no + 0018,605A TableOfParameterValues no + 0018,6060 RWaveTimeVector no + 0018,7000 DetectorConditionsNominalFlag no + 0018,7001 DetectorTemperature no + 0018,7004 DetectorType no + 0018,7005 DetectorConfiguration no + 0018,7006 DetectorDescription no + 0018,7008 DetectorMode no + 0018,700A DetectorID no + 0018,700C DateOfLastDetectorCalibration no + 0018,700E TimeOfLastDetectorCalibration no + 0018,7010 DetectorExposuresSinceCalibration no + 0018,7011 DetectorExposuresSinceManufactured no + 0018,7012 DetectorTimeSinceLastExposure no + 0018,7014 DetectorActiveTime no + 0018,7016 DetectorActiveOffsetFromExposure no + 0018,701A DetectorBinning no + 0018,7020 DetectorElementPhysicalSize no + 0018,7022 DetectorElementSpacing no + 0018,7024 DetectorActiveShape no + 0018,7026 DetectorActiveDimensions no + 0018,7028 DetectorActiveOrigin no + 0018,702A DetectorManufacturerName no + 0018,702B DetectorManufacturersModelName no + 0018,7030 FieldOfViewOrigin no + 0018,7032 FieldOfViewRotation no + 0018,7034 FieldOfViewHorizontalFlip no + 0018,7040 GridAbsorbingMaterial no + 0018,7041 GridSpacingMaterial no + 0018,7042 GridThickness no + 0018,7044 GridPitch no + 0018,7046 GridAspectRatio no + 0018,7048 GridPeriod no + 0018,704C GridFocalDistance no + 0018,7050 FilterMaterial no + 0018,7052 FilterThicknessMinimum no + 0018,7054 FilterThicknessMaximum no + 0018,7060 ExposureControlMode no + 0018,7062 ExposureControlModeDescription no + 0018,7064 ExposureStatus no + 0018,7065 PhototimerSetting no + 0018,8150 ExposureTimeInMicroSec no + 0018,8151 XRayTubeCurrentInMicroAmps no + 0018,9004 ContentQualification no + 0018,9005 PulseSequenceName no + 0018,9006 MRImagingModifierSequence no + 0018,9008 EchoPulseSequence no + 0018,9009 InversionRecovery no + 0018,9010 FlowCompensation no + 0018,9011 MultipleSpinEcho no + 0018,9012 MultiPlanarExcitation no + 0018,9014 PhaseContrast no + 0018,9015 TimeOfFlightContrast no + 0018,9016 Spoiling no + 0018,9017 SteadyStatePulseSequence no + 0018,9018 EchoPlanarPulseSequence no + 0018,9019 TagAngleFirstAxis no + 0018,9020 MagnetizationTransfer no + 0018,9021 T2Preparation no + 0018,9022 BloodSignalNulling no + 0018,9024 SaturationRecovery no + 0018,9025 SpectrallySelectedSuppression no + 0018,9026 SpectrallySelectedExcitation no + 0018,9027 SpatialPresaturation no + 0018,9028 Tagging no + 0018,9029 OversamplingPhase no + 0018,9030 TagSpacingFirstDimension no + 0018,9032 GeometryOfKSpaceTraversal no + 0018,9033 SegmentedKSpaceTraversal no + 0018,9034 RectilinearPhaseEncodeReordering no + 0018,9035 TagThickness no + 0018,9036 PartialFourierDirection no + 0018,9037 CardiacSynchronizationTechnique no + 0018,9041 ReceiveCoilManufacturerName no + 0018,9042 MRReceiveCoilSequence no + 0018,9043 ReceiveCoilType no + 0018,9044 QuadratureReceiveCoil no + 0018,9045 MultiCoilDefinitionSequence no + 0018,9046 MultiCoilConfiguration no + 0018,9047 MultiCoilElementName no + 0018,9048 MultiCoilElementUsed no + 0018,9049 MRTransmitCoilSequence no + 0018,9050 TransmitCoilManufacturerName no + 0018,9051 TransmitCoilType no + 0018,9052 SpectralWidth no + 0018,9053 ChemicalShiftReference no + 0018,9054 VolumeLocalizationTechnique no + 0018,9058 MRAcquisitionFrequencyEncodeSteps no + 0018,9059 Decoupling no + 0018,9060 DecoupledNucleus no + 0018,9061 DecouplingFrequency no + 0018,9062 DecouplingMethod no + 0018,9063 DecouplingChemicalShiftReference no + 0018,9064 KSpaceFiltering no + 0018,9065 TimeDomainFiltering no + 0018,9066 NumberOfZeroFills no + 0018,9067 BaselineCorrection no + 0018,9069 ParallelReductionFactorInPlane no + 0018,9070 CardiacRRIntervalSpecified no + 0018,9073 AcquisitionDuration no + 0018,9074 FrameAcquisitionDateTime no + 0018,9075 DiffusionDirectionality no + 0018,9076 DiffusionGradientDirectionSequence no + 0018,9077 ParallelAcquisition no + 0018,9078 ParallelAcquisitionTechnique no + 0018,9079 InversionTimes no + 0018,9080 MetaboliteMapDescription no + 0018,9081 PartialFourier no + 0018,9082 EffectiveEchoTime no + 0018,9083 MetaboliteMapCodeSequence no + 0018,9084 ChemicalShiftSequence no + 0018,9085 CardiacSignalSource no + 0018,9087 DiffusionBValue no + 0018,9089 DiffusionGradientOrientation no + 0018,9090 VelocityEncodingDirection no + 0018,9091 VelocityEncodingMinimumValue no + 0018,9093 NumberOfKSpaceTrajectories no + 0018,9094 CoverageOfKSpace no + 0018,9095 SpectroscopyAcquisitionPhaseRows no + 0018,9096 ParallelReductFactorInPlaneRetired no + 0018,9098 TransmitterFrequency no + 0018,9100 ResonantNucleus no + 0018,9101 FrequencyCorrection no + 0018,9103 MRSpectroscopyFOV-GeometrySequence no + 0018,9104 SlabThickness no + 0018,9105 SlabOrientation no + 0018,9106 MidSlabPosition no + 0018,9107 MRSpatialSaturationSequence no + 0018,9112 MRTimingAndRelatedParametersSeq no + 0018,9114 MREchoSequence no + 0018,9115 MRModifierSequence no + 0018,9117 MRDiffusionSequence no + 0018,9118 CardiacTriggerSequence no + 0018,9119 MRAveragesSequence no + 0018,9125 MRFOV-GeometrySequence no + 0018,9126 VolumeLocalizationSequence no + 0018,9127 SpectroscopyAcquisitionDataColumns no + 0018,9147 DiffusionAnisotropyType no + 0018,9151 FrameReferenceDateTime no + 0018,9152 MRMetaboliteMapSequence no + 0018,9155 ParallelReductionFactorOutOfPlane no + 0018,9159 SpectroscopyOutOfPlanePhaseSteps no + 0018,9166 BulkMotionStatus no + 0018,9168 ParallelReductionFactSecondInPlane no + 0018,9169 CardiacBeatRejectionTechnique no + 0018,9170 RespiratoryMotionCompTechnique no + 0018,9171 RespiratorySignalSource no + 0018,9172 BulkMotionCompensationTechnique no + 0018,9173 BulkMotionSignalSource no + 0018,9174 ApplicableSafetyStandardAgency no + 0018,9175 ApplicableSafetyStandardDescr no + 0018,9176 OperatingModeSequence no + 0018,9177 OperatingModeType no + 0018,9178 OperatingMode no + 0018,9179 SpecificAbsorptionRateDefinition no + 0018,9180 GradientOutputType no + 0018,9181 SpecificAbsorptionRateValue no + 0018,9182 GradientOutput no + 0018,9183 FlowCompensationDirection no + 0018,9184 TaggingDelay no + 0018,9185 RespiratoryMotionCompTechDescr no + 0018,9186 RespiratorySignalSourceID no + 0018,9195 ChemicalShiftsMinIntegrateLimitHz no + 0018,9196 ChemicalShiftsMaxIntegrateLimitHz no + 0018,9197 MRVelocityEncodingSequence no + 0018,9198 FirstOrderPhaseCorrection no + 0018,9199 WaterReferencedPhaseCorrection no + 0018,9200 MRSpectroscopyAcquisitionType no + 0018,9214 RespiratoryCyclePosition no + 0018,9217 VelocityEncodingMaximumValue no + 0018,9218 TagSpacingSecondDimension no + 0018,9219 TagAngleSecondAxis no + 0018,9220 FrameAcquisitionDuration no + 0018,9226 MRImageFrameTypeSequence no + 0018,9227 MRSpectroscopyFrameTypeSequence no + 0018,9231 MRAcqPhaseEncodingStepsInPlane no + 0018,9232 MRAcqPhaseEncodingStepsOutOfPlane no + 0018,9234 SpectroscopyAcqPhaseColumns no + 0018,9236 CardiacCyclePosition no + 0018,9239 SpecificAbsorptionRateSequence no + 0018,9240 RFEchoTrainLength no + 0018,9241 GradientEchoTrainLength no + 0018,9295 ChemicalShiftsMinIntegrateLimitPPM no + 0018,9296 ChemicalShiftsMaxIntegrateLimitPPM no + 0018,9301 CTAcquisitionTypeSequence no + 0018,9302 AcquisitionType no + 0018,9303 TubeAngle no + 0018,9304 CTAcquisitionDetailsSequence no + 0018,9305 RevolutionTime no + 0018,9306 SingleCollimationWidth no + 0018,9307 TotalCollimationWidth no + 0018,9308 CTTableDynamicsSequence no + 0018,9309 TableSpeed no + 0018,9310 TableFeedPerRotation no + 0018,9311 SpiralPitchFactor no + 0018,9312 CTGeometrySequence no + 0018,9313 DataCollectionCenterPatient no + 0018,9314 CTReconstructionSequence no + 0018,9315 ReconstructionAlgorithm no + 0018,9316 ConvolutionKernelGroup no + 0018,9317 ReconstructionFieldOfView no + 0018,9318 ReconstructionTargetCenterPatient no + 0018,9319 ReconstructionAngle no + 0018,9320 ImageFilter no + 0018,9321 CTExposureSequence no + 0018,9322 ReconstructionPixelSpacing no + 0018,9323 ExposureModulationType no + 0018,9324 EstimatedDoseSaving no + 0018,9325 CTXRayDetailsSequence no + 0018,9326 CTPositionSequence no + 0018,9327 TablePosition no + 0018,9328 ExposureTimeInMilliSec no + 0018,9329 CTImageFrameTypeSequence no + 0018,9330 XRayTubeCurrentInMilliAmps no + 0018,9332 ExposureInMilliAmpSec no + 0018,9333 ConstantVolumeFlag no + 0018,9334 FluoroscopyFlag no + 0018,9335 SourceToDataCollectionCenterDist no + 0018,9337 ContrastBolusAgentNumber no + 0018,9338 ContrastBolusIngredientCodeSeq no + 0018,9340 ContrastAdministrationProfileSeq no + 0018,9341 ContrastBolusUsageSequence no + 0018,9342 ContrastBolusAgentAdministered no + 0018,9343 ContrastBolusAgentDetected no + 0018,9344 ContrastBolusAgentPhase no + 0018,9345 CTDIvol no + 0018,9346 CTDIPhantomTypeCodeSequence no + 0018,9351 CalciumScoringMassFactorPatient no + 0018,9352 CalciumScoringMassFactorDevice no + 0018,9353 EnergyWeightingFactor no + 0018,9360 CTAdditionalXRaySourceSequence no + 0018,9401 ProjectionPixelCalibrationSequence no + 0018,9402 DistanceSourceToIsocenter no + 0018,9403 DistanceObjectToTableTop no + 0018,9404 ObjectPixelSpacingInCenterOfBeam no + 0018,9405 PositionerPositionSequence no + 0018,9406 TablePositionSequence no + 0018,9407 CollimatorShapeSequence no + 0018,9412 XA-XRFFrameCharacteristicsSequence no + 0018,9417 FrameAcquisitionSequence no + 0018,9420 XRayReceptorType no + 0018,9423 AcquisitionProtocolName no + 0018,9424 AcquisitionProtocolDescription no + 0018,9425 ContrastBolusIngredientOpaque no + 0018,9426 DistanceReceptorPlaneToDetHousing no + 0018,9427 IntensifierActiveShape no + 0018,9428 IntensifierActiveDimensions no + 0018,9429 PhysicalDetectorSize no + 0018,9430 PositionOfIsocenterProjection no + 0018,9432 FieldOfViewSequence no + 0018,9433 FieldOfViewDescription no + 0018,9434 ExposureControlSensingRegionsSeq no + 0018,9435 ExposureControlSensingRegionShape no + 0018,9436 ExposureControlSensRegionLeftEdge no + 0018,9437 ExposureControlSensRegionRightEdge no + 0018,9440 CenterOfCircExposControlSensRegion no + 0018,9441 RadiusOfCircExposControlSensRegion no + 0018,9447 ColumnAngulationPatient no + 0018,9449 BeamAngle no + 0018,9451 FrameDetectorParametersSequence no + 0018,9452 CalculatedAnatomyThickness no + 0018,9455 CalibrationSequence no + 0018,9456 ObjectThicknessSequence no + 0018,9457 PlaneIdentification no + 0018,9461 FieldOfViewDimensionsInFloat no + 0018,9462 IsocenterReferenceSystemSequence no + 0018,9463 PositionerIsocenterPrimaryAngle no + 0018,9464 PositionerIsocenterSecondaryAngle no + 0018,9465 PositionerIsocenterDetRotAngle no + 0018,9466 TableXPositionToIsocenter no + 0018,9467 TableYPositionToIsocenter no + 0018,9468 TableZPositionToIsocenter no + 0018,9469 TableHorizontalRotationAngle no + 0018,9470 TableHeadTiltAngle no + 0018,9471 TableCradleTiltAngle no + 0018,9472 FrameDisplayShutterSequence no + 0018,9473 AcquiredImageAreaDoseProduct no + 0018,9474 CArmPositionerTabletopRelationship no + 0018,9476 XRayGeometrySequence no + 0018,9477 IrradiationEventIDSequence no + 0018,9504 XRay3DFrameTypeSequence no + 0018,9506 ContributingSourcesSequence no + 0018,9507 XRay3DAcquisitionSequence no + 0018,9508 PrimaryPositionerScanArc no + 0018,9509 SecondaryPositionerScanArc no + 0018,9510 PrimaryPositionerScanStartAngle no + 0018,9511 SecondaryPositionerScanStartAngle no + 0018,9514 PrimaryPositionerIncrement no + 0018,9515 SecondaryPositionerIncrement no + 0018,9516 StartAcquisitionDateTime no + 0018,9517 EndAcquisitionDateTime no + 0018,9524 ApplicationName no + 0018,9525 ApplicationVersion no + 0018,9526 ApplicationManufacturer no + 0018,9527 AlgorithmType no + 0018,9528 AlgorithmDescription no + 0018,9530 XRay3DReconstructionSequence no + 0018,9531 ReconstructionDescription no + 0018,9538 PerProjectionAcquisitionSequence no + 0018,9601 DiffusionBMatrixSequence no + 0018,9602 DiffusionBValueXX no + 0018,9603 DiffusionBValueXY no + 0018,9604 DiffusionBValueXZ no + 0018,9605 DiffusionBValueYY no + 0018,9606 DiffusionBValueYZ no + 0018,9607 DiffusionBValueZZ no + 0018,9701 DecayCorrectionDateTime no + 0018,9715 StartDensityThreshold no + 0018,9722 TerminationTimeThreshold no + 0018,9725 DetectorGeometry no + 0018,9727 AxialDetectorDimension no + 0018,9735 PETPositionSequence no + 0018,9739 NumberOfIterations no + 0018,9740 NumberOfSubsets no + 0018,9751 PETFrameTypeSequence no + 0018,9756 ReconstructionType no + 0018,9758 DecayCorrected no + 0018,9759 AttenuationCorrected no + 0018,9760 ScatterCorrected no + 0018,9761 DeadTimeCorrected no + 0018,9762 GantryMotionCorrected no + 0018,9763 PatientMotionCorrected no + 0018,9765 RandomsCorrected no + 0018,9767 SensitivityCalibrated no + 0018,9801 DepthsOfFocus no + 0018,9804 ExclusionStartDatetime no + 0018,9805 ExclusionDuration no + 0018,9807 ImageDataTypeSequence no + 0018,9808 DataType no + 0018,980B AliasedDataType no + 0018,A001 ContributingEquipmentSequence no + 0018,A002 ContributionDateTime no + 0018,A003 ContributionDescription no + 0019,1002 NumberOfCellsIInDetector no + 0019,1003 CellNumberAtTheta no + 0019,1004 CellSpacing no + 0019,100F HorizFrameOfRef no + 0019,1011 SeriesContrast no + 0019,1012 LastPseq no + 0019,1013 StartNumberForBaseline no + 0019,1014 EndNumberForBaseline no + 0019,1015 StartNumberForEnhancedScans no + 0019,1016 EndNumberForEnhancedScans no + 0019,1017 SeriesPlane no + 0019,1018 FirstScanRas no + 0019,1019 FirstScanLocation no + 0019,101A LastScanRas no + 0019,101B LastScanLoc no + 0019,101E DisplayFieldOfView no + 0019,1023 TableSpeed no + 0019,1024 MidScanTime no + 0019,1025 MidScanFlag no + 0019,1026 DegreesOfAzimuth no + 0019,1027 GantryPeriod no + 0019,102A XRayOnPosition no + 0019,102B XRayOffPosition no + 0019,102C NumberOfTriggers no + 0019,102E AngleOfFirstView no + 0019,102F TriggerFrequency no + 0019,1039 ScanFOVType no + 0019,1040 StatReconFlag no + 0019,1041 ComputeType no + 0019,1042 SegmentNumber no + 0019,1043 TotalSegmentsRequested no + 0019,1044 InterscanDelay no + 0019,1047 ViewCompressionFactor no + 0019,104A TotalNoOfRefChannels no + 0019,104B DataSizeForScanData no + 0019,1052 ReconPostProcflag no + 0019,1057 CTWaterNumber no + 0019,1058 CTBoneNumber no + 0019,105A AcquisitionDuration no + 0019,105E NumberOfChannels no + 0019,105F IncrementBetweenChannels no + 0019,1060 StartingView no + 0019,1061 NumberOfViews no + 0019,1062 IncrementBetweenViews no + 0019,106A DependantOnNoViewsProcessed no + 0019,106B FieldOfViewInDetectorCells no + 0019,1070 ValueOfBackProjectionButton no + 0019,1071 SetIfFatqEstimatesWereUsed no + 0019,1072 ZChanAvgOverViews no + 0019,1073 AvgOfLeftRefChansOverViews no + 0019,1074 MaxLeftChanOverViews no + 0019,1075 AvgOfRightRefChansOverViews no + 0019,1076 MaxRightChanOverViews no + 0019,107D SecondEcho no + 0019,107E NumberOfEchoes no + 0019,107F TableDelta no + 0019,1081 Contiguous no + 0019,1084 PeakSAR no + 0019,1085 MonitorSAR no + 0019,1087 CardiacRepetitionTime no + 0019,1088 ImagesPerCardiacCycle no + 0019,108A ActualReceiveGainAnalog no + 0019,108B ActualReceiveGainDigital no + 0019,108D DelayAfterTrigger no + 0019,108F Swappf no + 0019,1090 PauseInterval no + 0019,1091 PulseTime no + 0019,1092 SliceOffsetOnFreqAxis no + 0019,1093 CenterFrequency no + 0019,1094 TransmitGain no + 0019,1095 AnalogReceiverGain no + 0019,1096 DigitalReceiverGain no + 0019,1097 BitmapDefiningCVs no + 0019,1098 CenterFreqMethod no + 0019,109B PulseSeqMode no + 0019,109C PulseSeqName no + 0019,109D PulseSeqDate no + 0019,109E InternalPulseSeqName no + 0019,109F TransmittingCoil no + 0019,10A0 SurfaceCoilType no + 0019,10A1 ExtremityCoilFlag no + 0019,10A2 RawDataRunNumber no + 0019,10A3 CalibratedFieldStrength no + 0019,10A4 SATFatWaterBone no + 0019,10A5 ReceiveBandwidth no + 0019,10A7 UserData01 no + 0019,10A8 UserData02 no + 0019,10A9 UserData03 no + 0019,10AA UserData04 no + 0019,10AB UserData05 no + 0019,10AC UserData06 no + 0019,10AD UserData07 no + 0019,10AE UserData08 no + 0019,10AF UserData09 no + 0019,10B0 UserData10 no + 0019,10B1 UserData11 no + 0019,10B2 UserData12 no + 0019,10B3 UserData13 no + 0019,10B4 UserData14 no + 0019,10B5 UserData15 no + 0019,10B6 UserData16 no + 0019,10B7 UserData17 no + 0019,10B8 UserData18 no + 0019,10B9 UserData19 no + 0019,10BA UserData20 no + 0019,10BB UserData21 no + 0019,10BC UserData22 no + 0019,10BD UserData23 no + 0019,10BE ProjectionAngle no + 0019,10C0 SaturationPlanes no + 0019,10C1 SurfaceCoilIntensity no + 0019,10C2 SATLocationR no + 0019,10C3 SATLocationL no + 0019,10C4 SATLocationA no + 0019,10C5 SATLocationP no + 0019,10C6 SATLocationH no + 0019,10C7 SATLocationF no + 0019,10C8 SATThicknessR-L no + 0019,10C9 SATThicknessA-P no + 0019,10CA SATThicknessH-F no + 0019,10CB PrescribedFlowAxis no + 0019,10CC VelocityEncoding no + 0019,10CD ThicknessDisclaimer no + 0019,10CE PrescanType no + 0019,10CF PrescanStatus no + 0019,10D0 RawDataType no + 0019,10D2 ProjectionAlgorithm no + 0019,10D3 ProjectionAlgorithm no + 0019,10D5 FractionalEcho no + 0019,10D6 PrepPulse no + 0019,10D7 CardiacPhases no + 0019,10D8 VariableEchoflag no + 0019,10D9 ConcatenatedSAT no + 0019,10DA ReferenceChannelUsed no + 0019,10DB BackProjectorCoefficient no + 0019,10DC PrimarySpeedCorrectionUsed no + 0019,10DD OverrangeCorrectionUsed no + 0019,10DE DynamicZAlphaValue no + 0019,10DF UserData no + 0019,10E0 UserData no + 0019,10E2 VelocityEncodeScale no + 0019,10F2 FastPhases no + 0019,10F9 TransmissionGain no + 0020,0000 RelationshipGroupLength no + 0020,000D StudyInstanceUID no + 0020,000E SeriesInstanceUID no + 0020,0010 StudyID no + 0020,0011 SeriesNumber no + 0020,0012 AcquisitionNumber no + 0020,0013 InstanceNumber no + 0020,0014 IsotopeNumber no + 0020,0015 PhaseNumber no + 0020,0016 IntervalNumber no + 0020,0017 TimeSlotNumber no + 0020,0018 AngleNumber no + 0020,0019 ItemNumber no + 0020,0020 PatientOrientation no + 0020,0022 OverlayNumber no + 0020,0024 CurveNumber no + 0020,0026 LookupTableNumber no + 0020,0030 ImagePosition no + 0020,0032 ImagePositionPatient no + 0020,0035 ImageOrientation no + 0020,0037 ImageOrientationPatient no + 0020,0050 Location no + 0020,0052 FrameOfReferenceUID no + 0020,0060 Laterality no + 0020,0062 ImageLaterality no + 0020,0070 ImageGeometryType no + 0020,0080 MaskingImage no + 0020,0100 TemporalPositionIdentifier no + 0020,0105 NumberOfTemporalPositions no + 0020,0110 TemporalResolution no + 0020,0200 SynchronizationFrameOfReferenceUID no + 0020,1000 SeriesInStudy no + 0020,1001 AcquisitionsInSeries no + 0020,1002 ImagesInAcquisition no + 0020,1003 ImagesInSeries no + 0020,1004 AcquisitionsInStudy no + 0020,1005 ImagesInStudy no + 0020,1020 Reference no + 0020,1040 PositionReferenceIndicator no + 0020,1041 SliceLocation no + 0020,1070 OtherStudyNumbers no + 0020,1200 NumberOfPatientRelatedStudies no + 0020,1202 NumberOfPatientRelatedSeries no + 0020,1204 NumberOfPatientRelatedInstances no + 0020,1206 NumberOfStudyRelatedSeries no + 0020,1208 NumberOfStudyRelatedInstances no + 0020,1209 NumberOfSeriesRelatedInstances no + 0020,31xx SourceImageIDs no + 0020,3401 ModifyingDeviceID no + 0020,3402 ModifiedImageID no + 0020,3403 ModifiedImageDate no + 0020,3404 ModifyingDeviceManufacturer no + 0020,3405 ModifiedImageTime no + 0020,3406 ModifiedImageDescription no + 0020,4000 ImageComments no + 0020,5000 OriginalImageIdentification no + 0020,5002 OriginalImageIdentNomenclature no + 0020,9056 StackID no + 0020,9057 InStackPositionNumber no + 0020,9071 FrameAnatomySequence no + 0020,9072 FrameLaterality no + 0020,9111 FrameContentSequence no + 0020,9113 PlanePositionSequence no + 0020,9116 PlaneOrientationSequence no + 0020,9128 TemporalPositionIndex no + 0020,9153 TriggerDelayTime no + 0020,9156 FrameAcquisitionNumber no + 0020,9157 DimensionIndexValues no + 0020,9158 FrameComments no + 0020,9161 ConcatenationUID no + 0020,9162 InConcatenationNumber no + 0020,9163 InConcatenationTotalNumber no + 0020,9164 DimensionOrganizationUID no + 0020,9165 DimensionIndexPointer no + 0020,9167 FunctionalGroupPointer no + 0020,9213 DimensionIndexPrivateCreator no + 0020,9221 DimensionOrganizationSequence no + 0020,9222 DimensionIndexSequence no + 0020,9228 ConcatenationFrameOffsetNumber no + 0020,9238 FunctionalGroupPrivateCreator no + 0020,9241 NominalPercentageOfCardiacPhase no + 0020,9245 NominalPercentOfRespiratoryPhase no + 0020,9246 StartingRespiratoryAmplitude no + 0020,9247 StartingRespiratoryPhase no + 0020,9248 EndingRespiratoryAmplitude no + 0020,9249 EndingRespiratoryPhase no + 0020,9250 RespiratoryTriggerType no + 0020,9251 RRIntervalTimeNominal no + 0020,9252 ActualCardiacTriggerDelayTime no + 0020,9253 RespiratorySynchronizationSequence no + 0020,9254 RespiratoryIntervalTime no + 0020,9255 NominalRespiratoryTriggerDelayTime no + 0020,9256 RespiratoryTriggerDelayThreshold no + 0020,9257 ActualRespiratoryTriggerDelayTime no + 0020,9301 ImagePositionVolume no + 0020,9302 ImageOrientationVolume no + 0020,9308 ApexPosition no + 0020,9421 DimensionDescriptionLabel no + 0020,9450 PatientOrientationInFrameSequence no + 0020,9453 FrameLabel no + 0020,9518 AcquisitionIndex no + 0020,9529 ContributingSOPInstancesRefSeq no + 0020,9536 ReconstructionIndex no + 0021,1003 SeriesFromWhichPrescribed no + 0021,1005 GenesisVersionNow no + 0021,1007 SeriesRecordChecksum no + 0021,1018 GenesisVersionNow no + 0021,1019 AcqreconRecordChecksum no + 0021,1020 TableStartLocation no + 0021,1035 SeriesFromWhichPrescribed no + 0021,1036 ImageFromWhichPrescribed no + 0021,1037 ScreenFormat no + 0021,104A AnatomicalReferenceForScout no + 0021,104F LocationsInAcquisition no + 0021,1050 GraphicallyPrescribed no + 0021,1051 RotationFromSourceXRot no + 0021,1052 RotationFromSourceYRot no + 0021,1053 RotationFromSourceZRot no + 0021,1054 ImagePosition no + 0021,1055 ImageOrientation no + 0021,1056 IntegerSlop no + 0021,1057 IntegerSlop no + 0021,1058 IntegerSlop no + 0021,1059 IntegerSlop no + 0021,105A IntegerSlop no + 0021,105B FloatSlop no + 0021,105C FloatSlop no + 0021,105D FloatSlop no + 0021,105E FloatSlop no + 0021,105F FloatSlop no + 0021,1081 AutoWindowLevelAlpha no + 0021,1082 AutoWindowLevelBeta no + 0021,1083 AutoWindowLevelWindow no + 0021,1084 ToWindowLevelLevel no + 0021,1090 TubeFocalSpotPosition no + 0021,1091 BiopsyPosition no + 0021,1092 BiopsyTLocation no + 0021,1093 BiopsyRefLocation no + 0022,0001 LightPathFilterPassThroughWavelen no + 0022,0002 LightPathFilterPassBand no + 0022,0003 ImagePathFilterPassThroughWavelen no + 0022,0004 ImagePathFilterPassBand no + 0022,0005 PatientEyeMovementCommanded no + 0022,0006 PatientEyeMovementCommandCodeSeq no + 0022,0007 SphericalLensPower no + 0022,0008 CylinderLensPower no + 0022,0009 CylinderAxis no + 0022,000A EmmetropicMagnification no + 0022,000B IntraOcularPressure no + 0022,000C HorizontalFieldOfView no + 0022,000D PupilDilated no + 0022,000E DegreeOfDilation no + 0022,0010 StereoBaselineAngle no + 0022,0011 StereoBaselineDisplacement no + 0022,0012 StereoHorizontalPixelOffset no + 0022,0013 StereoVerticalPixelOffset no + 0022,0014 StereoRotation no + 0022,0015 AcquisitionDeviceTypeCodeSequence no + 0022,0016 IlluminationTypeCodeSequence no + 0022,0017 LightPathFilterTypeStackCodeSeq no + 0022,0018 ImagePathFilterTypeStackCodeSeq no + 0022,0019 LensesCodeSequence no + 0022,001A ChannelDescriptionCodeSequence no + 0022,001B RefractiveStateSequence no + 0022,001C MydriaticAgentCodeSequence no + 0022,001D RelativeImagePositionCodeSequence no + 0022,0020 StereoPairsSequence no + 0022,0021 LeftImageSequence no + 0022,0022 RightImageSequence no + 0022,0030 AxialLengthOfTheEye no + 0022,0031 OphthalmicFrameLocationSequence no + 0022,0032 ReferenceCoordinates no + 0022,0035 DepthSpatialResolution no + 0022,0036 MaximumDepthDistortion no + 0022,0037 AlongScanSpatialResolution no + 0022,0038 MaximumAlongScanDistortion no + 0022,0039 OphthalmicImageOrientation no + 0022,0041 DepthOfTransverseImage no + 0022,0042 MydriaticAgentConcUnitsSeq no + 0022,0048 AcrossScanSpatialResolution no + 0022,0049 MaximumAcrossScanDistortion no + 0022,004E MydriaticAgentConcentration no + 0022,0055 IlluminationWaveLength no + 0022,0056 IlluminationPower no + 0022,0057 IlluminationBandwidth no + 0022,0058 MydriaticAgentSequence no + 0023,1001 NumberOfSeriesInStudy no + 0023,1002 NumberOfUnarchivedSeries no + 0023,1010 ReferenceImageField no + 0023,1050 SummaryImage no + 0023,1070 StartTimeSecsInFirstAxial no + 0023,1074 NoofUpdatesToHeader no + 0023,107D IndicatesIfTheStudyHasCompleteInfo no + 0025,1006 LastPulseSequenceUsed no + 0025,1007 ImagesInSeries no + 0025,1010 LandmarkCounter no + 0025,1011 NumberOfAcquisitions no + 0025,1014 IndicatesNoofUpdatesToHeader no + 0025,1017 SeriesCompleteFlag no + 0025,1018 NumberOfImagesArchived no + 0025,1019 LastImageNumberUsed no + 0025,101A PrimaryReceiverSuiteAndHost no + 0027,1006 ImageArchiveFlag no + 0027,1010 ScoutType no + 0027,101C VmaMamp no + 0027,101D VmaPhase no + 0027,101E VmaMod no + 0027,101F VmaClip no + 0027,1020 SmartScanOnOffFlag no + 0027,1030 ForeignImageRevision no + 0027,1031 ImagingMode no + 0027,1032 PulseSequence no + 0027,1033 ImagingOptions no + 0027,1035 PlaneType no + 0027,1036 ObliquePlane no + 0027,1040 RASLetterOfImageLocation no + 0027,1041 ImageLocation no + 0027,1042 CenterRCoordOfPlaneImage no + 0027,1043 CenterACoordOfPlaneImage no + 0027,1044 CenterSCoordOfPlaneImage no + 0027,1045 NormalRCoord no + 0027,1046 NormalACoord no + 0027,1047 NormalSCoord no + 0027,1048 RCoordOfTopRightCorner no + 0027,1049 ACoordOfTopRightCorner no + 0027,104A SCoordOfTopRightCorner no + 0027,104B RCoordOfBottomRightCorner no + 0027,104C ACoordOfBottomRightCorner no + 0027,104D SCoordOfBottomRightCorner no + 0027,1050 TableStartLocation no + 0027,1051 TableEndLocation no + 0027,1052 RASLetterForSideOfImage no + 0027,1053 RASLetterForAnteriorPosterior no + 0027,1054 RASLetterForScoutStartLoc no + 0027,1055 RASLetterForScoutEndLoc no + 0027,1060 ImageDimensionX no + 0027,1061 ImageDimensionY no + 0027,1062 NumberOfExcitations no + 0028,0000 ImagePresentationGroupLength no + 0028,0002 SamplesPerPixel no + 0028,0003 SamplesPerPixelUsed no + 0028,0004 PhotometricInterpretation no + 0028,0005 ImageDimensions no + 0028,0006 PlanarConfiguration no + 0028,0008 NumberOfFrames no + 0028,0009 FrameIncrementPointer no + 0028,000A FrameDimensionPointer no + 0028,0010 Rows no + 0028,0011 Columns no + 0028,0012 Planes no + 0028,0014 UltrasoundColorDataPresent no + 0028,0030 PixelSpacing no + 0028,0031 ZoomFactor no + 0028,0032 ZoomCenter no + 0028,0034 PixelAspectRatio no + 0028,0040 ImageFormat no + 0028,0050 ManipulatedImage no + 0028,0051 CorrectedImage no + 0028,005F CompressionRecognitionCode no + 0028,0060 CompressionCode no + 0028,0061 CompressionOriginator no + 0028,0062 CompressionLabel no + 0028,0063 CompressionDescription no + 0028,0065 CompressionSequence no + 0028,0066 CompressionStepPointers no + 0028,0068 RepeatInterval no + 0028,0069 BitsGrouped no + 0028,0070 PerimeterTable no + 0028,0071 PerimeterValue no + 0028,0080 PredictorRows no + 0028,0081 PredictorColumns no + 0028,0082 PredictorConstants no + 0028,0090 BlockedPixels no + 0028,0091 BlockRows no + 0028,0092 BlockColumns no + 0028,0093 RowOverlap no + 0028,0094 ColumnOverlap no + 0028,0100 BitsAllocated no + 0028,0101 BitsStored no + 0028,0102 HighBit no + 0028,0103 PixelRepresentation no + 0028,0104 SmallestValidPixelValue no + 0028,0105 LargestValidPixelValue no + 0028,0106 SmallestImagePixelValue no + 0028,0107 LargestImagePixelValue no + 0028,0108 SmallestPixelValueInSeries no + 0028,0109 LargestPixelValueInSeries no + 0028,0110 SmallestImagePixelValueInPlane no + 0028,0111 LargestImagePixelValueInPlane no + 0028,0120 PixelPaddingValue no + 0028,0121 PixelPaddingRangeLimit no + 0028,0200 ImageLocation no + 0028,0300 QualityControlImage no + 0028,0301 BurnedInAnnotation no + 0028,0400 TransformLabel no + 0028,0401 TransformVersionNumber no + 0028,0402 NumberOfTransformSteps no + 0028,0403 SequenceOfCompressedData no + 0028,0404 DetailsOfCoefficients no + 0028,04x2 CoefficientCoding no + 0028,04x3 CoefficientCodingPointers no + 0028,0700 DCTLabel no + 0028,0701 DataBlockDescription no + 0028,0702 DataBlock no + 0028,0710 NormalizationFactorFormat no + 0028,0720 ZonalMapNumberFormat no + 0028,0721 ZonalMapLocation no + 0028,0722 ZonalMapFormat no + 0028,0730 AdaptiveMapFormat no + 0028,0740 CodeNumberFormat no + 0028,08x0 CodeLabel no + 0028,08x2 NumberOfTables no + 0028,08x3 CodeTableLocation no + 0028,08x4 BitsForCodeWord no + 0028,08x8 ImageDataLocation no + 0028,0A02 PixelSpacingCalibrationType no + 0028,0A04 PixelSpacingCalibrationDescription no + 0028,1040 PixelIntensityRelationship no + 0028,1041 PixelIntensityRelationshipSign no + 0028,1050 WindowCenter no + 0028,1051 WindowWidth no + 0028,1052 RescaleIntercept no + 0028,1053 RescaleSlope no + 0028,1054 RescaleType no + 0028,1055 WindowCenterAndWidthExplanation no + 0028,1056 VOI_LUTFunction no + 0028,1080 GrayScale no + 0028,1090 RecommendedViewingMode no + 0028,1100 GrayLookupTableDescriptor no + 0028,1101 RedPaletteColorTableDescriptor no + 0028,1102 GreenPaletteColorTableDescriptor no + 0028,1103 BluePaletteColorTableDescriptor no + 0028,1111 LargeRedPaletteColorTableDescr no + 0028,1112 LargeGreenPaletteColorTableDescr no + 0028,1113 LargeBluePaletteColorTableDescr no + 0028,1199 PaletteColorTableUID no + 0028,1200 GrayLookupTableData no + 0028,1201 RedPaletteColorTableData no + 0028,1202 GreenPaletteColorTableData no + 0028,1203 BluePaletteColorTableData no + 0028,1211 LargeRedPaletteColorTableData no + 0028,1212 LargeGreenPaletteColorTableData no + 0028,1213 LargeBluePaletteColorTableData no + 0028,1214 LargePaletteColorLookupTableUID no + 0028,1221 SegmentedRedColorTableData no + 0028,1222 SegmentedGreenColorTableData no + 0028,1223 SegmentedBlueColorTableData no + 0028,1300 BreastImplantPresent no + 0028,1350 PartialView no + 0028,1351 PartialViewDescription no + 0028,1352 PartialViewCodeSequence no + 0028,135A SpatialLocationsPreserved no + 0028,1402 DataPathAssignment no + 0028,1404 BlendingLUT1Sequence no + 0028,1406 BlendingWeightConstant no + 0028,1408 BlendingLookupTableData no + 0028,140C BlendingLUT2Sequence no + 0028,140E DataPathID no + 0028,140F RGBLUTTransferFunction no + 0028,1410 AlphaLUTTransferFunction no + 0028,2000 ICCProfile no + 0028,2110 LossyImageCompression no + 0028,2112 LossyImageCompressionRatio no + 0028,2114 LossyImageCompressionMethod no + 0028,3000 ModalityLUTSequence no + 0028,3002 LUTDescriptor no + 0028,3003 LUTExplanation no + 0028,3004 ModalityLUTType no + 0028,3006 LUTData no + 0028,3010 VOILUTSequence no + 0028,3110 SoftcopyVOILUTSequence no + 0028,4000 ImagePresentationComments no + 0028,5000 BiPlaneAcquisitionSequence no + 0028,6010 RepresentativeFrameNumber no + 0028,6020 FrameNumbersOfInterest no + 0028,6022 FrameOfInterestDescription no + 0028,6023 FrameOfInterestType no + 0028,6030 MaskPointers no + 0028,6040 RWavePointer no + 0028,6100 MaskSubtractionSequence no + 0028,6101 MaskOperation no + 0028,6102 ApplicableFrameRange no + 0028,6110 MaskFrameNumbers no + 0028,6112 ContrastFrameAveraging no + 0028,6114 MaskSubPixelShift no + 0028,6120 TIDOffset no + 0028,6190 MaskOperationExplanation no + 0028,7FE0 PixelDataProviderURL no + 0028,9001 DataPointRows no + 0028,9002 DataPointColumns no + 0028,9003 SignalDomainColumns no + 0028,9099 LargestMonochromePixelValue no + 0028,9108 DataRepresentation no + 0028,9110 PixelMeasuresSequence no + 0028,9132 FrameVOILUTSequence no + 0028,9145 PixelValueTransformationSequence no + 0028,9235 SignalDomainRows no + 0028,9411 DisplayFilterPercentage no + 0028,9415 FramePixelShiftSequence no + 0028,9416 SubtractionItemID no + 0028,9422 PixelIntensityRelationshipLUTSeq no + 0028,9443 FramePixelDataPropertiesSequence no + 0028,9444 GeometricalProperties no + 0028,9445 GeometricMaximumDistortion no + 0028,9446 ImageProcessingApplied no + 0028,9454 MaskSelectionMode no + 0028,9474 LUTFunction no + 0028,9478 MaskVisibilityPercentage no + 0028,9501 PixelShiftSequence no + 0028,9502 RegionPixelShiftSequence no + 0028,9503 VerticesOfTheRegion no + 0028,9506 PixelShiftFrameRange no + 0028,9507 LUTFrameRange no + 0028,9520 ImageToEquipmentMappingMatrix no + 0028,9537 EquipmentCoordinateSystemID no + 0029,1004 LowerRangeOfPixels1a no + 0029,1005 LowerRangeOfPixels1b no + 0029,1006 LowerRangeOfPixels1c no + 0029,1007 LowerRangeOfPixels1d no + 0029,1008 LowerRangeOfPixels1e no + 0029,1009 LowerRangeOfPixels1f no + 0029,100A LowerRangeOfPixels1g no + 0029,1015 LowerRangeOfPixels1h no + 0029,1016 LowerRangeOfPixels1i no + 0029,1017 LowerRangeOfPixels2 no + 0029,1018 UpperRangeOfPixels2 no + 0029,101A LenOfTotHdrInBytes no + 0029,1026 VersionOfTheHdrStruct no + 0029,1034 AdvantageCompOverflow no + 0029,1035 AdvantageCompUnderflow no + 0032,0000 StudyGroupLength no + 0032,000A StudyStatusID no + 0032,000C StudyPriorityID no + 0032,0012 StudyIDIssuer no + 0032,0032 StudyVerifiedDate no + 0032,0033 StudyVerifiedTime no + 0032,0034 StudyReadDate no + 0032,0035 StudyReadTime no + 0032,1000 ScheduledStudyStartDate no + 0032,1001 ScheduledStudyStartTime no + 0032,1010 ScheduledStudyStopDate no + 0032,1011 ScheduledStudyStopTime no + 0032,1020 ScheduledStudyLocation no + 0032,1021 ScheduledStudyLocationAETitle no + 0032,1030 ReasonForStudy no + 0032,1031 RequestingPhysicianIDSequence no + 0032,1032 RequestingPhysician no + 0032,1033 RequestingService no + 0032,1040 StudyArrivalDate no + 0032,1041 StudyArrivalTime no + 0032,1050 StudyCompletionDate no + 0032,1051 StudyCompletionTime no + 0032,1055 StudyComponentStatusID no + 0032,1060 RequestedProcedureDescription no + 0032,1064 RequestedProcedureCodeSequence no + 0032,1070 RequestedContrastAgent no + 0032,4000 StudyComments no + 0038,0004 ReferencedPatientAliasSequence no + 0038,0008 VisitStatusID no + 0038,0010 AdmissionID no + 0038,0011 IssuerOfAdmissionID no + 0038,0016 RouteOfAdmissions no + 0038,001A ScheduledAdmissionDate no + 0038,001B ScheduledAdmissionTime no + 0038,001C ScheduledDischargeDate no + 0038,001D ScheduledDischargeTime no + 0038,001E ScheduledPatientInstitResidence no + 0038,0020 AdmittingDate no + 0038,0021 AdmittingTime no + 0038,0030 DischargeDate no + 0038,0032 DischargeTime no + 0038,0040 DischargeDiagnosisDescription no + 0038,0044 DischargeDiagnosisCodeSequence no + 0038,0050 SpecialNeeds no + 0038,0060 ServiceEpisodeID no + 0038,0061 IssuerOfServiceEpisodeID no + 0038,0062 ServiceEpisodeDescription no + 0038,0100 PertinentDocumentsSequence no + 0038,0300 CurrentPatientLocation no + 0038,0400 PatientInstitutionResidence no + 0038,0500 PatientState no + 0038,0502 PatientClinicalTrialParticipSeq no + 0038,4000 VisitComments no + 003A,0004 WaveformOriginality no + 003A,0005 NumberOfWaveformChannels no + 003A,0010 NumberOfWaveformSamples no + 003A,001A SamplingFrequency no + 003A,0020 MultiplexGroupLabel no + 003A,0200 ChannelDefinitionSequence no + 003A,0202 WaveformChannelNumber no + 003A,0203 ChannelLabel no + 003A,0205 ChannelStatus no + 003A,0208 ChannelSourceSequence no + 003A,0209 ChannelSourceModifiersSequence no + 003A,020A SourceWaveformSequence no + 003A,020C ChannelDerivationDescription no + 003A,0210 ChannelSensitivity no + 003A,0211 ChannelSensitivityUnitsSequence no + 003A,0212 ChannelSensitivityCorrectionFactor no + 003A,0213 ChannelBaseline no + 003A,0214 ChannelTimeSkew no + 003A,0215 ChannelSampleSkew no + 003A,0218 ChannelOffset no + 003A,021A WaveformBitsStored no + 003A,0220 FilterLowFrequency no + 003A,0221 FilterHighFrequency no + 003A,0222 NotchFilterFrequency no + 003A,0223 NotchFilterBandwidth no + 003A,0230 WaveformDataDisplayScale no + 003A,0231 WaveformDisplayBkgCIELabValue no + 003A,0240 WaveformPresentationGroupSequence no + 003A,0241 PresentationGroupNumber no + 003A,0242 ChannelDisplaySequence no + 003A,0244 ChannelRecommendDisplayCIELabValue no + 003A,0245 ChannelPosition no + 003A,0246 DisplayShadingFlag no + 003A,0247 FractionalChannelDisplayScale no + 003A,0248 AbsoluteChannelDisplayScale no + 003A,0300 MultiplexAudioChannelsDescrCodeSeq no + 003A,0301 ChannelIdentificationCode no + 003A,0302 ChannelMode no + 0040,0001 ScheduledStationAETitle no + 0040,0002 ScheduledProcedureStepStartDate no + 0040,0003 ScheduledProcedureStepStartTime no + 0040,0004 ScheduledProcedureStepEndDate no + 0040,0005 ScheduledProcedureStepEndTime no + 0040,0006 ScheduledPerformingPhysiciansName no + 0040,0007 ScheduledProcedureStepDescription no + 0040,0008 ScheduledProtocolCodeSequence no + 0040,0009 ScheduledProcedureStepID no + 0040,000A StageCodeSequence no + 0040,000B ScheduledPerformingPhysicianIDSeq no + 0040,0010 ScheduledStationName no + 0040,0011 ScheduledProcedureStepLocation no + 0040,0012 PreMedication no + 0040,0020 ScheduledProcedureStepStatus no + 0040,0031 LocalNamespaceEntityID no + 0040,0032 UniversalEntityID no + 0040,0033 UniversalEntityIDType no + 0040,0035 IdentifierTypeCode no + 0040,0036 AssigningFacilitySequence no + 0040,0100 ScheduledProcedureStepSequence no + 0040,0220 ReferencedNonImageCompositeSOPSeq no + 0040,0241 PerformedStationAETitle no + 0040,0242 PerformedStationName no + 0040,0243 PerformedLocation no + 0040,0244 PerformedProcedureStepStartDate no + 0040,0245 PerformedProcedureStepStartTime no + 0040,0250 PerformedProcedureStepEndDate no + 0040,0251 PerformedProcedureStepEndTime no + 0040,0252 PerformedProcedureStepStatus no + 0040,0253 PerformedProcedureStepID no + 0040,0254 PerformedProcedureStepDescription no + 0040,0255 PerformedProcedureTypeDescription no + 0040,0260 PerformedProtocolCodeSequence no + 0040,0261 PerformedProtocolType no + 0040,0270 ScheduledStepAttributesSequence no + 0040,0275 RequestAttributesSequence no + 0040,0280 CommentsOnPerformedProcedureStep no + 0040,0281 ProcStepDiscontinueReasonCodeSeq no + 0040,0293 QuantitySequence no + 0040,0294 Quantity no + 0040,0295 MeasuringUnitsSequence no + 0040,0296 BillingItemSequence no + 0040,0300 TotalTimeOfFluoroscopy no + 0040,0301 TotalNumberOfExposures no + 0040,0302 EntranceDose no + 0040,0303 ExposedArea no + 0040,0306 DistanceSourceToEntrance no + 0040,0307 DistanceSourceToSupport no + 0040,030E ExposureDoseSequence no + 0040,0310 CommentsOnRadiationDose no + 0040,0312 XRayOutput no + 0040,0314 HalfValueLayer no + 0040,0316 OrganDose no + 0040,0318 OrganExposed no + 0040,0320 BillingProcedureStepSequence no + 0040,0321 FilmConsumptionSequence no + 0040,0324 BillingSuppliesAndDevicesSequence no + 0040,0330 ReferencedProcedureStepSequence no + 0040,0340 PerformedSeriesSequence no + 0040,0400 CommentsOnScheduledProcedureStep no + 0040,0440 ProtocolContextSequence no + 0040,0441 ContentItemModifierSequence no + 0040,050A SpecimenAccessionNumber no + 0040,0512 ContainerIdentifier no + 0040,051A ContainerDescription no + 0040,0550 SpecimenSequence no + 0040,0551 SpecimenIdentifier no + 0040,0552 SpecimenDescriptionSequenceTrial no + 0040,0553 SpecimenDescriptionTrial no + 0040,0554 SpecimenUID no + 0040,0555 AcquisitionContextSequence no + 0040,0556 AcquisitionContextDescription no + 0040,059A SpecimenTypeCodeSequence no + 0040,0600 SpecimenShortDescription no + 0040,06FA SlideIdentifier no + 0040,071A ImageCenterPointCoordinatesSeq no + 0040,072A XOffsetInSlideCoordinateSystem no + 0040,073A YOffsetInSlideCoordinateSystem no + 0040,074A ZOffsetInSlideCoordinateSystem no + 0040,08D8 PixelSpacingSequence no + 0040,08DA CoordinateSystemAxisCodeSequence no + 0040,08EA MeasurementUnitsCodeSequence no + 0040,09F8 VitalStainCodeSequenceTrial no + 0040,1001 RequestedProcedureID no + 0040,1002 ReasonForRequestedProcedure no + 0040,1003 RequestedProcedurePriority no + 0040,1004 PatientTransportArrangements no + 0040,1005 RequestedProcedureLocation no + 0040,1006 PlacerOrderNumber-Procedure no + 0040,1007 FillerOrderNumber-Procedure no + 0040,1008 ConfidentialityCode no + 0040,1009 ReportingPriority no + 0040,100A ReasonForRequestedProcedureCodeSeq no + 0040,1010 NamesOfIntendedRecipientsOfResults no + 0040,1011 IntendedRecipientsOfResultsIDSeq no + 0040,1101 PersonIdentificationCodeSequence no + 0040,1102 PersonAddress no + 0040,1103 PersonTelephoneNumbers no + 0040,1400 RequestedProcedureComments no + 0040,2001 ReasonForImagingServiceRequest no + 0040,2004 IssueDateOfImagingServiceRequest no + 0040,2005 IssueTimeOfImagingServiceRequest no + 0040,2006 PlacerOrderNum-ImagingServiceReq no + 0040,2007 FillerOrderNum-ImagingServiceReq no + 0040,2008 OrderEnteredBy no + 0040,2009 OrderEntererLocation no + 0040,2010 OrderCallbackPhoneNumber no + 0040,2016 PlacerOrderNum-ImagingServiceReq no + 0040,2017 FillerOrderNum-ImagingServiceReq no + 0040,2400 ImagingServiceRequestComments no + 0040,3001 ConfidentialityOnPatientDataDescr no + 0040,4001 GenPurposeScheduledProcStepStatus no + 0040,4002 GenPurposePerformedProcStepStatus no + 0040,4003 GenPurposeSchedProcStepPriority no + 0040,4004 SchedProcessingApplicationsCodeSeq no + 0040,4005 SchedProcedureStepStartDateAndTime no + 0040,4006 MultipleCopiesFlag no + 0040,4007 PerformedProcessingAppsCodeSeq no + 0040,4009 HumanPerformerCodeSequence no + 0040,4010 SchedProcStepModificationDateTime no + 0040,4011 ExpectedCompletionDateAndTime no + 0040,4015 ResultingGenPurposePerfProcStepSeq no + 0040,4016 RefGenPurposeSchedProcStepSeq no + 0040,4018 ScheduledWorkitemCodeSequence no + 0040,4019 PerformedWorkitemCodeSequence no + 0040,4020 InputAvailabilityFlag no + 0040,4021 InputInformationSequence no + 0040,4022 RelevantInformationSequence no + 0040,4023 RefGenPurSchedProcStepTransUID no + 0040,4025 ScheduledStationNameCodeSequence no + 0040,4026 ScheduledStationClassCodeSequence no + 0040,4027 SchedStationGeographicLocCodeSeq no + 0040,4028 PerformedStationNameCodeSequence no + 0040,4029 PerformedStationClassCodeSequence no + 0040,4030 PerformedStationGeogLocCodeSeq no + 0040,4031 RequestedSubsequentWorkItemCodeSeq no + 0040,4032 NonDICOMOutputCodeSequence no + 0040,4033 OutputInformationSequence no + 0040,4034 ScheduledHumanPerformersSequence no + 0040,4035 ActualHumanPerformersSequence no + 0040,4036 HumanPerformersOrganization no + 0040,4037 HumanPerformerName no + 0040,4040 RawDataHandling no + 0040,8302 EntranceDoseInMilliGy no + 0040,9094 RefImageRealWorldValueMappingSeq no + 0040,9096 RealWorldValueMappingSequence no + 0040,9098 PixelValueMappingCodeSequence no + 0040,9210 LUTLabel no + 0040,9211 RealWorldValueLastValueMapped no + 0040,9212 RealWorldValueLUTData no + 0040,9216 RealWorldValueFirstValueMapped no + 0040,9224 RealWorldValueIntercept no + 0040,9225 RealWorldValueSlope no + 0040,A010 RelationshipType no + 0040,A027 VerifyingOrganization no + 0040,A030 VerificationDateTime no + 0040,A032 ObservationDateTime no + 0040,A040 ValueType no + 0040,A043 ConceptNameCodeSequence no + 0040,A050 ContinuityOfContent no + 0040,A073 VerifyingObserverSequence no + 0040,A075 VerifyingObserverName no + 0040,A078 AuthorObserverSequence no + 0040,A07A ParticipantSequence no + 0040,A07C CustodialOrganizationSequence no + 0040,A080 ParticipationType no + 0040,A082 ParticipationDateTime no + 0040,A084 ObserverType no + 0040,A088 VerifyingObserverIdentCodeSequence no + 0040,A090 EquivalentCDADocumentSequence no + 0040,A0B0 ReferencedWaveformChannels no + 0040,A120 DateTime no + 0040,A121 Date no + 0040,A122 Time no + 0040,A123 PersonName no + 0040,A124 UID no + 0040,A130 TemporalRangeType no + 0040,A132 ReferencedSamplePositions no + 0040,A136 ReferencedFrameNumbers no + 0040,A138 ReferencedTimeOffsets no + 0040,A13A ReferencedDateTime no + 0040,A160 TextValue no + 0040,A168 ConceptCodeSequence no + 0040,A170 PurposeOfReferenceCodeSequence no + 0040,A180 AnnotationGroupNumber no + 0040,A195 ModifierCodeSequence no + 0040,A300 MeasuredValueSequence no + 0040,A301 NumericValueQualifierCodeSequence no + 0040,A30A NumericValue no + 0040,A353 AddressTrial no + 0040,A354 TelephoneNumberTrial no + 0040,A360 PredecessorDocumentsSequence no + 0040,A370 ReferencedRequestSequence no + 0040,A372 PerformedProcedureCodeSequence no + 0040,A375 CurrentRequestedProcEvidenceSeq no + 0040,A385 PertinentOtherEvidenceSequence no + 0040,A390 HL7StructuredDocumentRefSeq no + 0040,A491 CompletionFlag no + 0040,A492 CompletionFlagDescription no + 0040,A493 VerificationFlag no + 0040,A494 ArchiveRequested no + 0040,A496 PreliminaryFlag no + 0040,A504 ContentTemplateSequence no + 0040,A525 IdenticalDocumentsSequence no + 0040,A730 ContentSequence no + 0040,B020 AnnotationSequence no + 0040,DB00 TemplateIdentifier no + 0040,DB06 TemplateVersion no + 0040,DB07 TemplateLocalVersion no + 0040,DB0B TemplateExtensionFlag no + 0040,DB0C TemplateExtensionOrganizationUID no + 0040,DB0D TemplateExtensionCreatorUID no + 0040,DB73 ReferencedContentItemIdentifier no + 0040,E001 HL7InstanceIdentifier no + 0040,E004 HL7DocumentEffectiveTime no + 0040,E006 HL7DocumentTypeCodeSequence no + 0040,E010 RetrieveURI no + 0040,E011 RetrieveLocationUID no + 0042,0010 DocumentTitle no + 0042,0011 EncapsulatedDocument no + 0042,0012 MIMETypeOfEncapsulatedDocument no + 0042,0013 SourceInstanceSequence no + 0042,0014 ListOfMIMETypes no + 0043,1001 BitmapOfPrescanOptions no + 0043,1002 GradientOffsetInX no + 0043,1003 GradientOffsetInY no + 0043,1004 GradientOffsetInZ no + 0043,1005 ImgIsOriginalOrUnoriginal no + 0043,1006 NumberOfEPIShots no + 0043,1007 ViewsPerSegment no + 0043,1008 RespiratoryRateBpm no + 0043,1009 RespiratoryTriggerPoint no + 0043,100A TypeOfReceiverUsed no + 0043,100B PeakRateOfChangeOfGradientField no + 0043,100C LimitsInUnitsOfPercent no + 0043,100D PSDEstimatedLimit no + 0043,100E PSDEstimatedLimitInTeslaPerSecond no + 0043,100F Saravghead no + 0043,1010 WindowValue no + 0043,1011 TotalInputViews no + 0043,1012 X-RayChain no + 0043,1013 DeconKernelParameters no + 0043,1014 CalibrationParameters no + 0043,1015 TotalOutputViews no + 0043,1016 NumberOfOverranges no + 0043,1017 IBHImageScaleFactors no + 0043,1018 BBHCoefficients no + 0043,1019 NumberOfBBHChainsToBlend no + 0043,101A StartingChannelNumber no + 0043,101B PpscanParameters no + 0043,101C GEImageIntegrity no + 0043,101D LevelValue no + 0043,101E DeltaStartTime no + 0043,101F MaxOverrangesInAView no + 0043,1020 AvgOverrangesAllViews no + 0043,1021 CorrectedAfterGlowTerms no + 0043,1025 ReferenceChannels no + 0043,1026 NoViewsRefChansBlocked no + 0043,1027 ScanPitchRatio no + 0043,1028 UniqueImageIden no + 0043,1029 HistogramTables no + 0043,102A UserDefinedData no + 0043,102B PrivateScanOptions no + 0043,102C EffectiveEchoSpacing no + 0043,102D StringSlopField1 no + 0043,102E StringSlopField2 no + 0043,102F RawDataType no + 0043,1030 RawDataType no + 0043,1031 RACordOfTargetReconCenter no + 0043,1032 RawDataType no + 0043,1033 NegScanspacing no + 0043,1034 OffsetFrequency no + 0043,1035 UserUsageTag no + 0043,1036 UserFillMapMSW no + 0043,1037 UserFillMapLSW no + 0043,1038 User25-48 no + 0043,1039 SlopInt6-9 no + 0043,1040 TriggerOnPosition no + 0043,1041 DegreeOfRotation no + 0043,1042 DASTriggerSource no + 0043,1043 DASFpaGain no + 0043,1044 DASOutputSource no + 0043,1045 DASAdInput no + 0043,1046 DASCalMode no + 0043,1047 DASCalFrequency no + 0043,1048 DASRegXm no + 0043,1049 DASAutoZero no + 0043,104A StartingChannelOfView no + 0043,104B DASXmPattern no + 0043,104C TGGCTriggerMode no + 0043,104D StartScanToXrayOnDelay no + 0043,104E DurationOfXrayOn no + 0043,1060 SlopInt10-17 no + 0043,1061 ScannerStudyEntityUID no + 0043,1062 ScannerStudyID no + 0043,106f ScannerTableEntry no + 0044,0001 ProductPackageIdentifier no + 0044,0002 SubstanceAdministrationApproval no + 0044,0003 ApprovalStatusFurtherDescription no + 0044,0004 ApprovalStatusDateTime no + 0044,0007 ProductTypeCodeSequence no + 0044,0008 ProductName no + 0044,0009 ProductDescription no + 0044,000A ProductLotIdentifier no + 0044,000B ProductExpirationDateTime no + 0044,0010 SubstanceAdministrationDateTime no + 0044,0011 SubstanceAdministrationNotes no + 0044,0012 SubstanceAdministrationDeviceID no + 0044,0013 ProductParameterSequence no + 0044,0019 SubstanceAdminParameterSeq no + 0045,1001 NumberOfMacroRowsInDetector no + 0045,1002 MacroWidthAtISOCenter no + 0045,1003 DASType no + 0045,1004 DASGain no + 0045,1005 DASTemperature no + 0045,1006 TableDirectionInOrOut no + 0045,1007 ZSmoothingFactor no + 0045,1008 ViewWeightingMode no + 0045,1009 SigmaRowNumberWhichRowsWereUsed no + 0045,100A MinimumDasValueFoundInTheScanData no + 0045,100B MaximumOffsetShiftValueUsed no + 0045,100C NumberOfViewsShifted no + 0045,100D ZTrackingFlag no + 0045,100E MeanZError no + 0045,100F ZTrackingMaximumError no + 0045,1010 StartingViewForRow2a no + 0045,1011 NumberOfViewsInRow2a no + 0045,1012 StartingViewForRow1a no + 0045,1013 SigmaMode no + 0045,1014 NumberOfViewsInRow1a no + 0045,1015 StartingViewForRow2b no + 0045,1016 NumberOfViewsInRow2b no + 0045,1017 StartingViewForRow1b no + 0045,1018 NumberOfViewsInRow1b no + 0045,1019 AirFilterCalibrationDate no + 0045,101A AirFilterCalibrationTime no + 0045,101B PhantomCalibrationDate no + 0045,101C PhantomCalibrationTime no + 0045,101D ZSlopeCalibrationDate no + 0045,101E ZSlopeCalibrationTime no + 0045,101F CrosstalkCalibrationDate no + 0045,1020 CrosstalkCalibrationTime no + 0045,1021 IterboneOptionFlag no + 0045,1022 PeristalticFlagOption no + 0046,0012 LensDescription no + 0046,0014 RightLensSequence no + 0046,0015 LeftLensSequence no + 0046,0018 CylinderSequence no + 0046,0028 PrismSequence no + 0046,0030 HorizontalPrismPower no + 0046,0032 HorizontalPrismBase no + 0046,0034 VerticalPrismPower no + 0046,0036 VerticalPrismBase no + 0046,0038 LensSegmentType no + 0046,0040 OpticalTransmittance no + 0046,0042 ChannelWidth no + 0046,0044 PupilSize no + 0046,0046 CornealSize no + 0046,0060 DistancePupillaryDistance no + 0046,0062 NearPupillaryDistance no + 0046,0064 OtherPupillaryDistance no + 0046,0075 RadiusOfCurvature no + 0046,0076 KeratometricPower no + 0046,0077 KeratometricAxis no + 0046,0092 BackgroundColor no + 0046,0094 Optotype no + 0046,0095 OptotypePresentation no + 0046,0100 AddNearSequence no + 0046,0101 AddIntermediateSequence no + 0046,0102 AddOtherSequence no + 0046,0104 AddPower no + 0046,0106 ViewingDistance no + 0046,0125 ViewingDistanceType no + 0046,0135 VisualAcuityModifiers no + 0046,0137 DecimalVisualAcuity no + 0046,0139 OptotypeDetailedDefinition no + 0046,0146 SpherePower no + 0046,0147 CylinderPower no + 0050,0004 CalibrationImage no + 0050,0010 DeviceSequence no + 0050,0014 DeviceLength no + 0050,0015 ContainerComponentWidth no + 0050,0016 DeviceDiameter no + 0050,0017 DeviceDiameterUnits no + 0050,0018 DeviceVolume no + 0050,0019 InterMarkerDistance no + 0050,001B ContainerComponentID no + 0050,0020 DeviceDescription no + 0054,0010 EnergyWindowVector no + 0054,0011 NumberOfEnergyWindows no + 0054,0012 EnergyWindowInformationSequence no + 0054,0013 EnergyWindowRangeSequence no + 0054,0014 EnergyWindowLowerLimit no + 0054,0015 EnergyWindowUpperLimit no + 0054,0016 RadiopharmaceuticalInformationSeq no + 0054,0017 ResidualSyringeCounts no + 0054,0018 EnergyWindowName no + 0054,0020 DetectorVector no + 0054,0021 NumberOfDetectors no + 0054,0022 DetectorInformationSequence no + 0054,0030 PhaseVector no + 0054,0031 NumberOfPhases no + 0054,0032 PhaseInformationSequence no + 0054,0033 NumberOfFramesInPhase no + 0054,0036 PhaseDelay no + 0054,0038 PauseBetweenFrames no + 0054,0039 PhaseDescription no + 0054,0050 RotationVector no + 0054,0051 NumberOfRotations no + 0054,0052 RotationInformationSequence no + 0054,0053 NumberOfFramesInRotation no + 0054,0060 RRIntervalVector no + 0054,0061 NumberOfRRIntervals no + 0054,0062 GatedInformationSequence no + 0054,0063 DataInformationSequence no + 0054,0070 TimeSlotVector no + 0054,0071 NumberOfTimeSlots no + 0054,0072 TimeSlotInformationSequence no + 0054,0073 TimeSlotTime no + 0054,0080 SliceVector no + 0054,0081 NumberOfSlices no + 0054,0090 AngularViewVector no + 0054,0100 TimeSliceVector no + 0054,0101 NumberOfTimeSlices no + 0054,0200 StartAngle no + 0054,0202 TypeOfDetectorMotion no + 0054,0210 TriggerVector no + 0054,0211 NumberOfTriggersInPhase no + 0054,0220 ViewCodeSequence no + 0054,0222 ViewModifierCodeSequence no + 0054,0300 RadionuclideCodeSequence no + 0054,0302 AdministrationRouteCodeSequence no + 0054,0304 RadiopharmaceuticalCodeSequence no + 0054,0306 CalibrationDataSequence no + 0054,0308 EnergyWindowNumber no + 0054,0400 ImageID no + 0054,0410 PatientOrientationCodeSequence no + 0054,0412 PatientOrientationModifierCodeSeq no + 0054,0414 PatientGantryRelationshipCodeSeq no + 0054,0500 SliceProgressionDirection no + 0054,1000 SeriesType no + 0054,1001 Units no + 0054,1002 CountsSource no + 0054,1004 ReprojectionMethod no + 0054,1100 RandomsCorrectionMethod no + 0054,1101 AttenuationCorrectionMethod no + 0054,1102 DecayCorrection no + 0054,1103 ReconstructionMethod no + 0054,1104 DetectorLinesOfResponseUsed no + 0054,1105 ScatterCorrectionMethod no + 0054,1200 AxialAcceptance no + 0054,1201 AxialMash no + 0054,1202 TransverseMash no + 0054,1203 DetectorElementSize no + 0054,1210 CoincidenceWindowWidth no + 0054,1220 SecondaryCountsType no + 0054,1300 FrameReferenceTime no + 0054,1310 PrimaryCountsAccumulated no + 0054,1311 SecondaryCountsAccumulated no + 0054,1320 SliceSensitivityFactor no + 0054,1321 DecayFactor no + 0054,1322 DoseCalibrationFactor no + 0054,1323 ScatterFractionFactor no + 0054,1324 DeadTimeFactor no + 0054,1330 ImageIndex no + 0054,1400 CountsIncluded no + 0054,1401 DeadTimeCorrectionFlag no + 0060,3000 HistogramSequence no + 0060,3002 HistogramNumberOfBins no + 0060,3004 HistogramFirstBinValue no + 0060,3006 HistogramLastBinValue no + 0060,3008 HistogramBinWidth no + 0060,3010 HistogramExplanation no + 0060,3020 HistogramData no + 0062,0001 SegmentationType no + 0062,0002 SegmentSequence no + 0062,0003 SegmentedPropertyCategoryCodeSeq no + 0062,0004 SegmentNumber no + 0062,0005 SegmentLabel no + 0062,0006 SegmentDescription no + 0062,0008 SegmentAlgorithmType no + 0062,0009 SegmentAlgorithmName no + 0062,000A SegmentIdentificationSequence no + 0062,000B ReferencedSegmentNumber no + 0062,000C RecommendedDisplayGrayscaleValue no + 0062,000D RecommendedDisplayCIELabValue no + 0062,000E MaximumFractionalValue no + 0062,000F SegmentedPropertyTypeCodeSequence no + 0062,0010 SegmentationFractionalType no + 0064,0002 DeformableRegistrationSequence no + 0064,0003 SourceFrameOfReferenceUID no + 0064,0005 DeformableRegistrationGridSequence no + 0064,0007 GridDimensions no + 0064,0008 GridResolution no + 0064,0009 VectorGridData no + 0064,000F PreDeformationMatrixRegistSeq no + 0064,0010 PostDeformationMatrixRegistSeq no + 0066,0001 NumberOfSurfaces no + 0066,0002 SurfaceSequence no + 0066,0003 SurfaceNumber no + 0066,0004 SurfaceComments no + 0066,0009 SurfaceProcessing no + 0066,000A SurfaceProcessingRatio no + 0066,000E FiniteVolume no + 0066,0010 Manifold no + 0066,0011 SurfacePointsSequence no + 0066,0015 NumberOfSurfacePoints no + 0066,0016 PointCoordinatesData no + 0066,0017 PointPositionAccuracy no + 0066,0018 MeanPointDistance no + 0066,0019 MaximumPointDistance no + 0066,001B AxisOfRotation no + 0066,001C CenterOfRotation no + 0066,001E NumberOfVectors no + 0066,001F VectorDimensionality no + 0066,0020 VectorAccuracy no + 0066,0021 VectorCoordinateData no + 0066,0023 TrianglePointIndexList no + 0066,0024 EdgePointIndexList no + 0066,0025 VertexPointIndexList no + 0066,0026 TriangleStripSequence no + 0066,0027 TriangleFanSequence no + 0066,0028 LineSequence no + 0066,0029 PrimitivePointIndexList no + 0066,002A SurfaceCount no + 0066,002F AlgorithmFamilyCodeSequ no + 0066,0031 AlgorithmVersion no + 0066,0032 AlgorithmParameters no + 0066,0034 FacetSequence no + 0066,0036 AlgorithmName no + 0070,0001 GraphicAnnotationSequence no + 0070,0002 GraphicLayer no + 0070,0003 BoundingBoxAnnotationUnits no + 0070,0004 AnchorPointAnnotationUnits no + 0070,0005 GraphicAnnotationUnits no + 0070,0006 UnformattedTextValue no + 0070,0008 TextObjectSequence no + 0070,0009 GraphicObjectSequence no + 0070,0010 BoundingBoxTopLeftHandCorner no + 0070,0011 BoundingBoxBottomRightHandCorner no + 0070,0012 BoundingBoxTextHorizJustification no + 0070,0014 AnchorPoint no + 0070,0015 AnchorPointVisibility no + 0070,0020 GraphicDimensions no + 0070,0021 NumberOfGraphicPoints no + 0070,0022 GraphicData no + 0070,0023 GraphicType no + 0070,0024 GraphicFilled no + 0070,0040 ImageRotationRetired no + 0070,0041 ImageHorizontalFlip no + 0070,0042 ImageRotation no + 0070,0050 DisplayedAreaTopLeftTrial no + 0070,0051 DisplayedAreaBottomRightTrial no + 0070,0052 DisplayedAreaTopLeft no + 0070,0053 DisplayedAreaBottomRight no + 0070,005A DisplayedAreaSelectionSequence no + 0070,0060 GraphicLayerSequence no + 0070,0062 GraphicLayerOrder no + 0070,0066 GraphicLayerRecDisplayGraysclValue no + 0070,0067 GraphicLayerRecDisplayRGBValue no + 0070,0068 GraphicLayerDescription no + 0070,0080 ContentLabel no + 0070,0081 ContentDescription no + 0070,0082 PresentationCreationDate no + 0070,0083 PresentationCreationTime no + 0070,0084 ContentCreatorName no + 0070,0086 ContentCreatorIDCodeSequence no + 0070,0100 PresentationSizeMode no + 0070,0101 PresentationPixelSpacing no + 0070,0102 PresentationPixelAspectRatio no + 0070,0103 PresentationPixelMagRatio no + 0070,0306 ShapeType no + 0070,0308 RegistrationSequence no + 0070,0309 MatrixRegistrationSequence no + 0070,030A MatrixSequence no + 0070,030C FrameOfRefTransformationMatrixType no + 0070,030D RegistrationTypeCodeSequence no + 0070,030F FiducialDescription no + 0070,0310 FiducialIdentifier no + 0070,0311 FiducialIdentifierCodeSequence no + 0070,0312 ContourUncertaintyRadius no + 0070,0314 UsedFiducialsSequence no + 0070,0318 GraphicCoordinatesDataSequence no + 0070,031A FiducialUID no + 0070,031C FiducialSetSequence no + 0070,031E FiducialSequence no + 0070,0401 GraphicLayerRecomDisplayCIELabVal no + 0070,0402 BlendingSequence no + 0070,0403 RelativeOpacity no + 0070,0404 ReferencedSpatialRegistrationSeq no + 0070,0405 BlendingPosition no + 0072,0002 HangingProtocolName no + 0072,0004 HangingProtocolDescription no + 0072,0006 HangingProtocolLevel no + 0072,0008 HangingProtocolCreator no + 0072,000A HangingProtocolCreationDateTime no + 0072,000C HangingProtocolDefinitionSequence no + 0072,000E HangingProtocolUserIDCodeSequence no + 0072,0010 HangingProtocolUserGroupName no + 0072,0012 SourceHangingProtocolSequence no + 0072,0014 NumberOfPriorsReferenced no + 0072,0020 ImageSetsSequence no + 0072,0022 ImageSetSelectorSequence no + 0072,0024 ImageSetSelectorUsageFlag no + 0072,0026 SelectorAttribute no + 0072,0028 SelectorValueNumber no + 0072,0030 TimeBasedImageSetsSequence no + 0072,0032 ImageSetNumber no + 0072,0034 ImageSetSelectorCategory no + 0072,0038 RelativeTime no + 0072,003A RelativeTimeUnits no + 0072,003C AbstractPriorValue no + 0072,003E AbstractPriorCodeSequence no + 0072,0040 ImageSetLabel no + 0072,0050 SelectorAttributeVR no + 0072,0052 SelectorSequencePointer no + 0072,0054 SelectorSeqPointerPrivateCreator no + 0072,0056 SelectorAttributePrivateCreator no + 0072,0060 SelectorATValue no + 0072,0062 SelectorCSValue no + 0072,0064 SelectorISValue no + 0072,0066 SelectorLOValue no + 0072,0068 SelectorLTValue no + 0072,006A SelectorPNValue no + 0072,006C SelectorSHValue no + 0072,006E SelectorSTValue no + 0072,0070 SelectorUTValue no + 0072,0072 SelectorDSValue no + 0072,0074 SelectorFDValue no + 0072,0076 SelectorFLValue no + 0072,0078 SelectorULValue no + 0072,007A SelectorUSValue no + 0072,007C SelectorSLValue no + 0072,007E SelectorSSValue no + 0072,0080 SelectorCodeSequenceValue no + 0072,0100 NumberOfScreens no + 0072,0102 NominalScreenDefinitionSequence no + 0072,0104 NumberOfVerticalPixels no + 0072,0106 NumberOfHorizontalPixels no + 0072,0108 DisplayEnvironmentSpatialPosition no + 0072,010A ScreenMinimumGrayscaleBitDepth no + 0072,010C ScreenMinimumColorBitDepth no + 0072,010E ApplicationMaximumRepaintTime no + 0072,0200 DisplaySetsSequence no + 0072,0202 DisplaySetNumber no + 0072,0203 DisplaySetLabel no + 0072,0204 DisplaySetPresentationGroup no + 0072,0206 DisplaySetPresentationGroupDescr no + 0072,0208 PartialDataDisplayHandling no + 0072,0210 SynchronizedScrollingSequence no + 0072,0212 DisplaySetScrollingGroup no + 0072,0214 NavigationIndicatorSequence no + 0072,0216 NavigationDisplaySet no + 0072,0218 ReferenceDisplaySets no + 0072,0300 ImageBoxesSequence no + 0072,0302 ImageBoxNumber no + 0072,0304 ImageBoxLayoutType no + 0072,0306 ImageBoxTileHorizontalDimension no + 0072,0308 ImageBoxTileVerticalDimension no + 0072,0310 ImageBoxScrollDirection no + 0072,0312 ImageBoxSmallScrollType no + 0072,0314 ImageBoxSmallScrollAmount no + 0072,0316 ImageBoxLargeScrollType no + 0072,0318 ImageBoxLargeScrollAmount no + 0072,0320 ImageBoxOverlapPriority no + 0072,0330 CineRelativeToRealTime no + 0072,0400 FilterOperationsSequence no + 0072,0402 FilterByCategory no + 0072,0404 FilterByAttributePresence no + 0072,0406 FilterByOperator no + 0072,0432 SynchronizedImageBoxList no + 0072,0434 TypeOfSynchronization no + 0072,0500 BlendingOperationType no + 0072,0510 ReformattingOperationType no + 0072,0512 ReformattingThickness no + 0072,0514 ReformattingInterval no + 0072,0516 ReformattingOpInitialViewDir no + 0072,0520 RenderingType3D no + 0072,0600 SortingOperationsSequence no + 0072,0602 SortByCategory no + 0072,0604 SortingDirection no + 0072,0700 DisplaySetPatientOrientation no + 0072,0702 VOIType no + 0072,0704 PseudoColorType no + 0072,0706 ShowGrayscaleInverted no + 0072,0710 ShowImageTrueSizeFlag no + 0072,0712 ShowGraphicAnnotationFlag no + 0072,0714 ShowPatientDemographicsFlag no + 0072,0716 ShowAcquisitionTechniquesFlag no + 0072,0717 DisplaySetHorizontalJustification no + 0072,0718 DisplaySetVerticalJustification no + 0074,1000 UnifiedProcedureStepState no + 0074,1002 UPSProgressInformationSequence no + 0074,1004 UnifiedProcedureStepProgress no + 0074,1006 UnifiedProcedureStepProgressDescr no + 0074,1008 UnifiedProcedureStepComURISeq no + 0074,100a ContactURI no + 0074,100c ContactDisplayName no + 0074,1020 BeamTaskSequence no + 0074,1022 BeamTaskType no + 0074,1024 BeamOrderIndex no + 0074,1030 DeliveryVerificationImageSequence no + 0074,1032 VerificationImageTiming no + 0074,1034 DoubleExposureFlag no + 0074,1036 DoubleExposureOrdering no + 0074,1038 DoubleExposureMeterset no + 0074,103A DoubleExposureFieldDelta no + 0074,1040 RelatedReferenceRTImageSequence no + 0074,1042 GeneralMachineVerificationSequence no + 0074,1044 ConventionalMachineVerificationSeq no + 0074,1046 IonMachineVerificationSequence no + 0074,1048 FailedAttributesSequence no + 0074,104A OverriddenAttributesSequence no + 0074,104C ConventionalControlPointVerifySeq no + 0074,104E IonControlPointVerificationSeq no + 0074,1050 AttributeOccurrenceSequence no + 0074,1052 AttributeOccurrencePointer no + 0074,1054 AttributeItemSelector no + 0074,1056 AttributeOccurrencePrivateCreator no + 0074,1200 ScheduledProcedureStepPriority no + 0074,1202 WorklistLabel no + 0074,1204 ProcedureStepLabel no + 0074,1210 ScheduledProcessingParametersSeq no + 0074,1212 PerformedProcessingParametersSeq no + 0074,1216 UPSPerformedProcedureSequence no + 0074,1220 RelatedProcedureStepSequence no + 0074,1222 ProcedureStepRelationshipType no + 0074,1230 DeletionLock no + 0074,1234 ReceivingAE no + 0074,1236 RequestingAE no + 0074,1238 ReasonForCancellation no + 0074,1242 SCPStatus no + 0074,1244 SubscriptionListStatus no + 0074,1246 UPSListStatus no + 0088,0130 StorageMediaFileSetID no + 0088,0140 StorageMediaFileSetUID no + 0088,0200 IconImageSequence no + 0088,0904 TopicTitle no + 0088,0906 TopicSubject no + 0088,0910 TopicAuthor no + 0088,0912 TopicKeywords no + 0100,0410 SOPInstanceStatus no + 0100,0420 SOPAuthorizationDateAndTime no + 0100,0424 SOPAuthorizationComment no + 0100,0426 AuthorizationEquipmentCertNumber no + 0400,0005 MACIDNumber no + 0400,0010 MACCalculationTransferSyntaxUID no + 0400,0015 MACAlgorithm no + 0400,0020 DataElementsSigned no + 0400,0100 DigitalSignatureUID no + 0400,0105 DigitalSignatureDateTime no + 0400,0110 CertificateType no + 0400,0115 CertificateOfSigner no + 0400,0120 Signature no + 0400,0305 CertifiedTimestampType no + 0400,0310 CertifiedTimestamp no + 0400,0401 DigitalSignaturePurposeCodeSeq no + 0400,0402 ReferencedDigitalSignatureSeq no + 0400,0403 ReferencedSOPInstanceMACSeq no + 0400,0404 MAC no + 0400,0500 EncryptedAttributesSequence no + 0400,0510 EncryptedContentTransferSyntaxUID no + 0400,0520 EncryptedContent no + 0400,0550 ModifiedAttributesSequence no + 0400,0561 OriginalAttributesSequence no + 0400,0562 AttributeModificationDateTime no + 0400,0563 ModifyingSystem no + 0400,0564 SourceOfPreviousValues no + 0400,0565 ReasonForTheAttributeModification no + 1000,xxx0 EscapeTriplet no + 1000,xxx1 RunLengthTriplet no + 1000,xxx2 HuffmanTableSize no + 1000,xxx3 HuffmanTableTriplet no + 1000,xxx4 ShiftTableSize no + 1000,xxx5 ShiftTableTriplet no + 1010,xxxx ZonalMap no + 2000,0010 NumberOfCopies no + 2000,001E PrinterConfigurationSequence no + 2000,0020 PrintPriority no + 2000,0030 MediumType no + 2000,0040 FilmDestination no + 2000,0050 FilmSessionLabel no + 2000,0060 MemoryAllocation no + 2000,0061 MaximumMemoryAllocation no + 2000,0062 ColorImagePrintingFlag no + 2000,0063 CollationFlag no + 2000,0065 AnnotationFlag no + 2000,0067 ImageOverlayFlag no + 2000,0069 PresentationLUTFlag no + 2000,006A ImageBoxPresentationLUTFlag no + 2000,00A0 MemoryBitDepth no + 2000,00A1 PrintingBitDepth no + 2000,00A2 MediaInstalledSequence no + 2000,00A4 OtherMediaAvailableSequence no + 2000,00A8 SupportedImageDisplayFormatSeq no + 2000,0500 ReferencedFilmBoxSequence no + 2000,0510 ReferencedStoredPrintSequence no + 2010,0010 ImageDisplayFormat no + 2010,0030 AnnotationDisplayFormatID no + 2010,0040 FilmOrientation no + 2010,0050 FilmSizeID no + 2010,0052 PrinterResolutionID no + 2010,0054 DefaultPrinterResolutionID no + 2010,0060 MagnificationType no + 2010,0080 SmoothingType no + 2010,00A6 DefaultMagnificationType no + 2010,00A7 OtherMagnificationTypesAvailable no + 2010,00A8 DefaultSmoothingType no + 2010,00A9 OtherSmoothingTypesAvailable no + 2010,0100 BorderDensity no + 2010,0110 EmptyImageDensity no + 2010,0120 MinDensity no + 2010,0130 MaxDensity no + 2010,0140 Trim no + 2010,0150 ConfigurationInformation no + 2010,0152 ConfigurationInformationDescr no + 2010,0154 MaximumCollatedFilms no + 2010,015E Illumination no + 2010,0160 ReflectedAmbientLight no + 2010,0376 PrinterPixelSpacing no + 2010,0500 ReferencedFilmSessionSequence no + 2010,0510 ReferencedImageBoxSequence no + 2010,0520 ReferencedBasicAnnotationBoxSeq no + 2020,0010 ImageBoxPosition no + 2020,0020 Polarity no + 2020,0030 RequestedImageSize no + 2020,0040 RequestedDecimate-CropBehavior no + 2020,0050 RequestedResolutionID no + 2020,00A0 RequestedImageSizeFlag no + 2020,00A2 DecimateCropResult no + 2020,0110 BasicGrayscaleImageSequence no + 2020,0111 BasicColorImageSequence no + 2020,0130 ReferencedImageOverlayBoxSequence no + 2020,0140 ReferencedVOILUTBoxSequence no + 2030,0010 AnnotationPosition no + 2030,0020 TextString no + 2040,0010 ReferencedOverlayPlaneSequence no + 2040,0011 ReferencedOverlayPlaneGroups no + 2040,0020 OverlayPixelDataSequence no + 2040,0060 OverlayMagnificationType no + 2040,0070 OverlaySmoothingType no + 2040,0072 OverlayOrImageMagnification no + 2040,0074 MagnifyToNumberOfColumns no + 2040,0080 OverlayForegroundDensity no + 2040,0082 OverlayBackgroundDensity no + 2040,0090 OverlayMode no + 2040,0100 ThresholdDensity no + 2040,0500 ReferencedImageBoxSequence no + 2050,0010 PresentationLUTSequence no + 2050,0020 PresentationLUTShape no + 2050,0500 ReferencedPresentationLUTSequence no + 2100,0010 PrintJobID no + 2100,0020 ExecutionStatus no + 2100,0030 ExecutionStatusInfo no + 2100,0040 CreationDate no + 2100,0050 CreationTime no + 2100,0070 Originator no + 2100,0140 DestinationAE no + 2100,0160 OwnerID no + 2100,0170 NumberOfFilms no + 2100,0500 ReferencedPrintJobSequence no + 2110,0010 PrinterStatus no + 2110,0020 PrinterStatusInfo no + 2110,0030 PrinterName no + 2110,0099 PrintQueueID no + 2120,0010 QueueStatus no + 2120,0050 PrintJobDescriptionSequence no + 2120,0070 ReferencedPrintJobSequence no + 2130,0010 PrintManagementCapabilitiesSeq no + 2130,0015 PrinterCharacteristicsSequence no + 2130,0030 FilmBoxContentSequence no + 2130,0040 ImageBoxContentSequence no + 2130,0050 AnnotationContentSequence no + 2130,0060 ImageOverlayBoxContentSequence no + 2130,0080 PresentationLUTContentSequence no + 2130,00A0 ProposedStudySequence no + 2130,00C0 OriginalImageSequence no + 2200,0001 LabelFromInfoExtractedFromInstance no + 2200,0002 LabelText no + 2200,0003 LabelStyleSelection no + 2200,0004 MediaDisposition no + 2200,0005 BarcodeValue no + 2200,0006 BarcodeSymbology no + 2200,0007 AllowMediaSplitting no + 2200,0008 IncludeNonDICOMObjects no + 2200,0009 IncludeDisplayApplication no + 2200,000A SaveCompInstancesAfterMediaCreate no + 2200,000B TotalNumberMediaPiecesCreated no + 2200,000C RequestedMediaApplicationProfile no + 2200,000D ReferencedStorageMediaSequence no + 2200,000E FailureAttributes no + 2200,000F AllowLossyCompression no + 2200,0020 RequestPriority no + 3002,0002 RTImageLabel no + 3002,0003 RTImageName no + 3002,0004 RTImageDescription no + 3002,000A ReportedValuesOrigin no + 3002,000C RTImagePlane no + 3002,000D XRayImageReceptorTranslation no + 3002,000E XRayImageReceptorAngle no + 3002,0010 RTImageOrientation no + 3002,0011 ImagePlanePixelSpacing no + 3002,0012 RTImagePosition no + 3002,0020 RadiationMachineName no + 3002,0022 RadiationMachineSAD no + 3002,0024 RadiationMachineSSD no + 3002,0026 RTImageSID no + 3002,0028 SourceToReferenceObjectDistance no + 3002,0029 FractionNumber no + 3002,0030 ExposureSequence no + 3002,0032 MetersetExposure no + 3002,0034 DiaphragmPosition no + 3002,0040 FluenceMapSequence no + 3002,0041 FluenceDataSource no + 3002,0042 FluenceDataScale no + 3002,0051 FluenceMode no + 3002,0052 FluenceModeID no + 3004,0001 DVHType no + 3004,0002 DoseUnits no + 3004,0004 DoseType no + 3004,0006 DoseComment no + 3004,0008 NormalizationPoint no + 3004,000A DoseSummationType no + 3004,000C GridFrameOffsetVector no + 3004,000E DoseGridScaling no + 3004,0010 RTDoseROISequence no + 3004,0012 DoseValue no + 3004,0014 TissueHeterogeneityCorrection no + 3004,0040 DVHNormalizationPoint no + 3004,0042 DVHNormalizationDoseValue no + 3004,0050 DVHSequence no + 3004,0052 DVHDoseScaling no + 3004,0054 DVHVolumeUnits no + 3004,0056 DVHNumberOfBins no + 3004,0058 DVHData no + 3004,0060 DVHReferencedROISequence no + 3004,0062 DVHROIContributionType no + 3004,0070 DVHMinimumDose no + 3004,0072 DVHMaximumDose no + 3004,0074 DVHMeanDose no + 3006,0002 StructureSetLabel no + 3006,0004 StructureSetName no + 3006,0006 StructureSetDescription no + 3006,0008 StructureSetDate no + 3006,0009 StructureSetTime no + 3006,0010 ReferencedFrameOfReferenceSequence no + 3006,0012 RTReferencedStudySequence no + 3006,0014 RTReferencedSeriesSequence no + 3006,0016 ContourImageSequence no + 3006,0020 StructureSetROISequence no + 3006,0022 ROINumber no + 3006,0024 ReferencedFrameOfReferenceUID no + 3006,0026 ROIName no + 3006,0028 ROIDescription no + 3006,002A ROIDisplayColor no + 3006,002C ROIVolume no + 3006,0030 RTRelatedROISequence no + 3006,0033 RTROIRelationship no + 3006,0036 ROIGenerationAlgorithm no + 3006,0038 ROIGenerationDescription no + 3006,0039 ROIContourSequence no + 3006,0040 ContourSequence no + 3006,0042 ContourGeometricType no + 3006,0044 ContourSlabThickness no + 3006,0045 ContourOffsetVector no + 3006,0046 NumberOfContourPoints no + 3006,0048 ContourNumber no + 3006,0049 AttachedContours no + 3006,0050 ContourData no + 3006,0080 RTROIObservationsSequence no + 3006,0082 ObservationNumber no + 3006,0084 ReferencedROINumber no + 3006,0085 ROIObservationLabel no + 3006,0086 RTROIIdentificationCodeSequence no + 3006,0088 ROIObservationDescription no + 3006,00A0 RelatedRTROIObservationsSequence no + 3006,00A4 RTROIInterpretedType no + 3006,00A6 ROIInterpreter no + 3006,00B0 ROIPhysicalPropertiesSequence no + 3006,00B2 ROIPhysicalProperty no + 3006,00B4 ROIPhysicalPropertyValue no + 3006,00B6 ROIElementalCompositionSequence no + 3006,00B7 ROIElementalCompAtomicNumber no + 3006,00B8 ROIElementalCompAtomicMassFraction no + 3006,00C0 FrameOfReferenceRelationshipSeq no + 3006,00C2 RelatedFrameOfReferenceUID no + 3006,00C4 FrameOfReferenceTransformType no + 3006,00C6 FrameOfReferenceTransformMatrix no + 3006,00C8 FrameOfReferenceTransformComment no + 3008,0010 MeasuredDoseReferenceSequence no + 3008,0012 MeasuredDoseDescription no + 3008,0014 MeasuredDoseType no + 3008,0016 MeasuredDoseValue no + 3008,0020 TreatmentSessionBeamSequence no + 3008,0021 TreatmentSessionIonBeamSequence no + 3008,0022 CurrentFractionNumber no + 3008,0024 TreatmentControlPointDate no + 3008,0025 TreatmentControlPointTime no + 3008,002A TreatmentTerminationStatus no + 3008,002B TreatmentTerminationCode no + 3008,002C TreatmentVerificationStatus no + 3008,0030 ReferencedTreatmentRecordSequence no + 3008,0032 SpecifiedPrimaryMeterset no + 3008,0033 SpecifiedSecondaryMeterset no + 3008,0036 DeliveredPrimaryMeterset no + 3008,0037 DeliveredSecondaryMeterset no + 3008,003A SpecifiedTreatmentTime no + 3008,003B DeliveredTreatmentTime no + 3008,0040 ControlPointDeliverySequence no + 3008,0041 IonControlPointDeliverySequence no + 3008,0042 SpecifiedMeterset no + 3008,0044 DeliveredMeterset no + 3008,0045 MetersetRateSet no + 3008,0046 MetersetRateDelivered no + 3008,0047 ScanSpotMetersetsDelivered no + 3008,0048 DoseRateDelivered no + 3008,0050 TreatmentSummaryCalcDoseRefSeq no + 3008,0052 CumulativeDoseToDoseReference no + 3008,0054 FirstTreatmentDate no + 3008,0056 MostRecentTreatmentDate no + 3008,005A NumberOfFractionsDelivered no + 3008,0060 OverrideSequence no + 3008,0061 ParameterSequencePointer no + 3008,0062 OverrideParameterPointer no + 3008,0063 ParameterItemIndex no + 3008,0064 MeasuredDoseReferenceNumber no + 3008,0065 ParameterPointer no + 3008,0066 OverrideReason no + 3008,0068 CorrectedParameterSequence no + 3008,006A CorrectionValue no + 3008,0070 CalculatedDoseReferenceSequence no + 3008,0072 CalculatedDoseReferenceNumber no + 3008,0074 CalculatedDoseReferenceDescription no + 3008,0076 CalculatedDoseReferenceDoseValue no + 3008,0078 StartMeterset no + 3008,007A EndMeterset no + 3008,0080 ReferencedMeasuredDoseReferenceSeq no + 3008,0082 ReferencedMeasuredDoseReferenceNum no + 3008,0090 ReferencedCalculatedDoseRefSeq no + 3008,0092 ReferencedCalculatedDoseRefNumber no + 3008,00A0 BeamLimitingDeviceLeafPairsSeq no + 3008,00B0 RecordedWedgeSequence no + 3008,00C0 RecordedCompensatorSequence no + 3008,00D0 RecordedBlockSequence no + 3008,00E0 TreatmentSummaryMeasuredDoseRefSeq no + 3008,00F0 RecordedSnoutSequence no + 3008,00F2 RecordedRangeShifterSequence no + 3008,00F4 RecordedLateralSpreadingDeviceSeq no + 3008,00F6 RecordedRangeModulatorSequence no + 3008,0100 RecordedSourceSequence no + 3008,0105 SourceSerialNumber no + 3008,0110 TreatmentSessionAppSetupSeq no + 3008,0116 ApplicationSetupCheck no + 3008,0120 RecordedBrachyAccessoryDeviceSeq no + 3008,0122 ReferencedBrachyAccessoryDeviceNum no + 3008,0130 RecordedChannelSequence no + 3008,0132 SpecifiedChannelTotalTime no + 3008,0134 DeliveredChannelTotalTime no + 3008,0136 SpecifiedNumberOfPulses no + 3008,0138 DeliveredNumberOfPulses no + 3008,013A SpecifiedPulseRepetitionInterval no + 3008,013C DeliveredPulseRepetitionInterval no + 3008,0140 RecordedSourceApplicatorSequence no + 3008,0142 ReferencedSourceApplicatorNumber no + 3008,0150 RecordedChannelShieldSequence no + 3008,0152 ReferencedChannelShieldNumber no + 3008,0160 BrachyControlPointDeliveredSeq no + 3008,0162 SafePositionExitDate no + 3008,0164 SafePositionExitTime no + 3008,0166 SafePositionReturnDate no + 3008,0168 SafePositionReturnTime no + 3008,0200 CurrentTreatmentStatus no + 3008,0202 TreatmentStatusComment no + 3008,0220 FractionGroupSummarySequence no + 3008,0223 ReferencedFractionNumber no + 3008,0224 FractionGroupType no + 3008,0230 BeamStopperPosition no + 3008,0240 FractionStatusSummarySequence no + 3008,0250 TreatmentDate no + 3008,0251 TreatmentTime no + 300A,0002 RTPlanLabel no + 300A,0003 RTPlanName no + 300A,0004 RTPlanDescription no + 300A,0006 RTPlanDate no + 300A,0007 RTPlanTime no + 300A,0009 TreatmentProtocols no + 300A,000A PlanIntent no + 300A,000B TreatmentSites no + 300A,000C RTPlanGeometry no + 300A,000E PrescriptionDescription no + 300A,0010 DoseReferenceSequence no + 300A,0012 DoseReferenceNumber no + 300A,0013 DoseReferenceUID no + 300A,0014 DoseReferenceStructureType no + 300A,0015 NominalBeamEnergyUnit no + 300A,0016 DoseReferenceDescription no + 300A,0018 DoseReferencePointCoordinates no + 300A,001A NominalPriorDose no + 300A,0020 DoseReferenceType no + 300A,0021 ConstraintWeight no + 300A,0022 DeliveryWarningDose no + 300A,0023 DeliveryMaximumDose no + 300A,0025 TargetMinimumDose no + 300A,0026 TargetPrescriptionDose no + 300A,0027 TargetMaximumDose no + 300A,0028 TargetUnderdoseVolumeFraction no + 300A,002A OrganAtRiskFullVolumeDose no + 300A,002B OrganAtRiskLimitDose no + 300A,002C OrganAtRiskMaximumDose no + 300A,002D OrganAtRiskOverdoseVolumeFraction no + 300A,0040 ToleranceTableSequence no + 300A,0042 ToleranceTableNumber no + 300A,0043 ToleranceTableLabel no + 300A,0044 GantryAngleTolerance no + 300A,0046 BeamLimitingDeviceAngleTolerance no + 300A,0048 BeamLimitingDeviceToleranceSeq no + 300A,004A BeamLimitingDevicePositionTol no + 300A,004B SnoutPositionTolerance no + 300A,004C PatientSupportAngleTolerance no + 300A,004E TableTopEccentricAngleTolerance no + 300A,004F TableTopPitchAngleTolerance no + 300A,0050 TableTopRollAngleTolerance no + 300A,0051 TableTopVerticalPositionTolerance no + 300A,0052 TableTopLongitudinalPositionTol no + 300A,0053 TableTopLateralPositionTolerance no + 300A,0055 RTPlanRelationship no + 300A,0070 FractionGroupSequence no + 300A,0071 FractionGroupNumber no + 300A,0072 FractionGroupDescription no + 300A,0078 NumberOfFractionsPlanned no + 300A,0079 NumberFractionPatternDigitsPerDay no + 300A,007A RepeatFractionCycleLength no + 300A,007B FractionPattern no + 300A,0080 NumberOfBeams no + 300A,0082 BeamDoseSpecificationPoint no + 300A,0084 BeamDose no + 300A,0086 BeamMeterset no + 300A,0088 BeamDosePointDepth no + 300A,0089 BeamDosePointEquivalentDepth no + 300A,008A BeamDosePointSSD no + 300A,00A0 NumberOfBrachyApplicationSetups no + 300A,00A2 BrachyAppSetupDoseSpecPoint no + 300A,00A4 BrachyApplicationSetupDose no + 300A,00B0 BeamSequence no + 300A,00B2 TreatmentMachineName no + 300A,00B3 PrimaryDosimeterUnit no + 300A,00B4 SourceAxisDistance no + 300A,00B6 BeamLimitingDeviceSequence no + 300A,00B8 RTBeamLimitingDeviceType no + 300A,00BA SourceToBeamLimitingDeviceDistance no + 300A,00BB IsocenterToBeamLimitingDeviceDist no + 300A,00BC NumberOfLeafJawPairs no + 300A,00BE LeafPositionBoundaries no + 300A,00C0 BeamNumber no + 300A,00C2 BeamName no + 300A,00C3 BeamDescription no + 300A,00C4 BeamType no + 300A,00C6 RadiationType no + 300A,00C7 HighDoseTechniqueType no + 300A,00C8 ReferenceImageNumber no + 300A,00CA PlannedVerificationImageSequence no + 300A,00CC ImagingDeviceSpecificAcqParams no + 300A,00CE TreatmentDeliveryType no + 300A,00D0 NumberOfWedges no + 300A,00D1 WedgeSequence no + 300A,00D2 WedgeNumber no + 300A,00D3 WedgeType no + 300A,00D4 WedgeID no + 300A,00D5 WedgeAngle no + 300A,00D6 WedgeFactor no + 300A,00D7 TotalWedgeTrayWaterEquivThickness no + 300A,00D8 WedgeOrientation no + 300A,00D9 IsocenterToWedgeTrayDistance no + 300A,00DA SourceToWedgeTrayDistance no + 300A,00DB WedgeThinEdgePosition no + 300A,00DC BolusID no + 300A,00DD BolusDescription no + 300A,00E0 NumberOfCompensators no + 300A,00E1 MaterialID no + 300A,00E2 TotalCompensatorTrayFactor no + 300A,00E3 CompensatorSequence no + 300A,00E4 CompensatorNumber no + 300A,00E5 CompensatorID no + 300A,00E6 SourceToCompensatorTrayDistance no + 300A,00E7 CompensatorRows no + 300A,00E8 CompensatorColumns no + 300A,00E9 CompensatorPixelSpacing no + 300A,00EA CompensatorPosition no + 300A,00EB CompensatorTransmissionData no + 300A,00EC CompensatorThicknessData no + 300A,00ED NumberOfBoli no + 300A,00EE CompensatorType no + 300A,00F0 NumberOfBlocks no + 300A,00F2 TotalBlockTrayFactor no + 300A,00F3 TotalBlockTrayWaterEquivThickness no + 300A,00F4 BlockSequence no + 300A,00F5 BlockTrayID no + 300A,00F6 SourceToBlockTrayDistance no + 300A,00F7 IsocenterToBlockTrayDistance no + 300A,00F8 BlockType no + 300A,00F9 AccessoryCode no + 300A,00FA BlockDivergence no + 300A,00FB BlockMountingPosition no + 300A,00FC BlockNumber no + 300A,00FE BlockName no + 300A,0100 BlockThickness no + 300A,0102 BlockTransmission no + 300A,0104 BlockNumberOfPoints no + 300A,0106 BlockData no + 300A,0107 ApplicatorSequence no + 300A,0108 ApplicatorID no + 300A,0109 ApplicatorType no + 300A,010A ApplicatorDescription no + 300A,010C CumulativeDoseReferenceCoefficient no + 300A,010E FinalCumulativeMetersetWeight no + 300A,0110 NumberOfControlPoints no + 300A,0111 ControlPointSequence no + 300A,0112 ControlPointIndex no + 300A,0114 NominalBeamEnergy no + 300A,0115 DoseRateSet no + 300A,0116 WedgePositionSequence no + 300A,0118 WedgePosition no + 300A,011A BeamLimitingDevicePositionSequence no + 300A,011C LeafJawPositions no + 300A,011E GantryAngle no + 300A,011F GantryRotationDirection no + 300A,0120 BeamLimitingDeviceAngle no + 300A,0121 BeamLimitingDeviceRotateDirection no + 300A,0122 PatientSupportAngle no + 300A,0123 PatientSupportRotationDirection no + 300A,0124 TableTopEccentricAxisDistance no + 300A,0125 TableTopEccentricAngle no + 300A,0126 TableTopEccentricRotateDirection no + 300A,0128 TableTopVerticalPosition no + 300A,0129 TableTopLongitudinalPosition no + 300A,012A TableTopLateralPosition no + 300A,012C IsocenterPosition no + 300A,012E SurfaceEntryPoint no + 300A,0130 SourceToSurfaceDistance no + 300A,0134 CumulativeMetersetWeight no + 300A,0140 TableTopPitchAngle no + 300A,0142 TableTopPitchRotationDirection no + 300A,0144 TableTopRollAngle no + 300A,0146 TableTopRollRotationDirection no + 300A,0148 HeadFixationAngle no + 300A,014A GantryPitchAngle no + 300A,014C GantryPitchRotationDirection no + 300A,014E GantryPitchAngleTolerance no + 300A,0180 PatientSetupSequence no + 300A,0182 PatientSetupNumber no + 300A,0183 PatientSetupLabel no + 300A,0184 PatientAdditionalPosition no + 300A,0190 FixationDeviceSequence no + 300A,0192 FixationDeviceType no + 300A,0194 FixationDeviceLabel no + 300A,0196 FixationDeviceDescription no + 300A,0198 FixationDevicePosition no + 300A,0199 FixationDevicePitchAngle no + 300A,019A FixationDeviceRollAngle no + 300A,01A0 ShieldingDeviceSequence no + 300A,01A2 ShieldingDeviceType no + 300A,01A4 ShieldingDeviceLabel no + 300A,01A6 ShieldingDeviceDescription no + 300A,01A8 ShieldingDevicePosition no + 300A,01B0 SetupTechnique no + 300A,01B2 SetupTechniqueDescription no + 300A,01B4 SetupDeviceSequence no + 300A,01B6 SetupDeviceType no + 300A,01B8 SetupDeviceLabel no + 300A,01BA SetupDeviceDescription no + 300A,01BC SetupDeviceParameter no + 300A,01D0 SetupReferenceDescription no + 300A,01D2 TableTopVerticalSetupDisplacement no + 300A,01D4 TableTopLongitudinalSetupDisplace no + 300A,01D6 TableTopLateralSetupDisplacement no + 300A,0200 BrachyTreatmentTechnique no + 300A,0202 BrachyTreatmentType no + 300A,0206 TreatmentMachineSequence no + 300A,0210 SourceSequence no + 300A,0212 SourceNumber no + 300A,0214 SourceType no + 300A,0216 SourceManufacturer no + 300A,0218 ActiveSourceDiameter no + 300A,021A ActiveSourceLength no + 300A,0222 SourceEncapsulationNomThickness no + 300A,0224 SourceEncapsulationNomTransmission no + 300A,0226 SourceIsotopeName no + 300A,0228 SourceIsotopeHalfLife no + 300A,0229 SourceStrengthUnits no + 300A,022A ReferenceAirKermaRate no + 300A,022B SourceStrength no + 300A,022C SourceStrengthReferenceDate no + 300A,022E SourceStrengthReferenceTime no + 300A,0230 ApplicationSetupSequence no + 300A,0232 ApplicationSetupType no + 300A,0234 ApplicationSetupNumber no + 300A,0236 ApplicationSetupName no + 300A,0238 ApplicationSetupManufacturer no + 300A,0240 TemplateNumber no + 300A,0242 TemplateType no + 300A,0244 TemplateName no + 300A,0250 TotalReferenceAirKerma no + 300A,0260 BrachyAccessoryDeviceSequence no + 300A,0262 BrachyAccessoryDeviceNumber no + 300A,0263 BrachyAccessoryDeviceID no + 300A,0264 BrachyAccessoryDeviceType no + 300A,0266 BrachyAccessoryDeviceName no + 300A,026A BrachyAccessoryDeviceNomThickness no + 300A,026C BrachyAccessoryDevNomTransmission no + 300A,0280 ChannelSequence no + 300A,0282 ChannelNumber no + 300A,0284 ChannelLength no + 300A,0286 ChannelTotalTime no + 300A,0288 SourceMovementType no + 300A,028A NumberOfPulses no + 300A,028C PulseRepetitionInterval no + 300A,0290 SourceApplicatorNumber no + 300A,0291 SourceApplicatorID no + 300A,0292 SourceApplicatorType no + 300A,0294 SourceApplicatorName no + 300A,0296 SourceApplicatorLength no + 300A,0298 SourceApplicatorManufacturer no + 300A,029C SourceApplicatorWallNomThickness no + 300A,029E SourceApplicatorWallNomTrans no + 300A,02A0 SourceApplicatorStepSize no + 300A,02A2 TransferTubeNumber no + 300A,02A4 TransferTubeLength no + 300A,02B0 ChannelShieldSequence no + 300A,02B2 ChannelShieldNumber no + 300A,02B3 ChannelShieldID no + 300A,02B4 ChannelShieldName no + 300A,02B8 ChannelShieldNominalThickness no + 300A,02BA ChannelShieldNominalTransmission no + 300A,02C8 FinalCumulativeTimeWeight no + 300A,02D0 BrachyControlPointSequence no + 300A,02D2 ControlPointRelativePosition no + 300A,02D4 ControlPoint3DPosition no + 300A,02D6 CumulativeTimeWeight no + 300A,02E0 CompensatorDivergence no + 300A,02E1 CompensatorMountingPosition no + 300A,02E2 SourceToCompensatorDistance no + 300A,02E3 TotalCompTrayWaterEquivThickness no + 300A,02E4 IsocenterToCompensatorTrayDistance no + 300A,02E5 CompensatorColumnOffset no + 300A,02E6 IsocenterToCompensatorDistances no + 300A,02E7 CompensatorRelStoppingPowerRatio no + 300A,02E8 CompensatorMillingToolDiameter no + 300A,02EA IonRangeCompensatorSequence no + 300A,02EB CompensatorDescription no + 300A,0302 RadiationMassNumber no + 300A,0304 RadiationAtomicNumber no + 300A,0306 RadiationChargeState no + 300A,0308 ScanMode no + 300A,030A VirtualSourceAxisDistances no + 300A,030C SnoutSequence no + 300A,030D SnoutPosition no + 300A,030F SnoutID no + 300A,0312 NumberOfRangeShifters no + 300A,0314 RangeShifterSequence no + 300A,0316 RangeShifterNumber no + 300A,0318 RangeShifterID no + 300A,0320 RangeShifterType no + 300A,0322 RangeShifterDescription no + 300A,0330 NumberOfLateralSpreadingDevices no + 300A,0332 LateralSpreadingDeviceSequence no + 300A,0334 LateralSpreadingDeviceNumber no + 300A,0336 LateralSpreadingDeviceID no + 300A,0338 LateralSpreadingDeviceType no + 300A,033A LateralSpreadingDeviceDescription no + 300A,033C LateralSpreadingDevWaterEquivThick no + 300A,0340 NumberOfRangeModulators no + 300A,0342 RangeModulatorSequence no + 300A,0344 RangeModulatorNumber no + 300A,0346 RangeModulatorID no + 300A,0348 RangeModulatorType no + 300A,034A RangeModulatorDescription no + 300A,034C BeamCurrentModulationID no + 300A,0350 PatientSupportType no + 300A,0352 PatientSupportID no + 300A,0354 PatientSupportAccessoryCode no + 300A,0356 FixationLightAzimuthalAngle no + 300A,0358 FixationLightPolarAngle no + 300A,035A MetersetRate no + 300A,0360 RangeShifterSettingsSequence no + 300A,0362 RangeShifterSetting no + 300A,0364 IsocenterToRangeShifterDistance no + 300A,0366 RangeShifterWaterEquivThickness no + 300A,0370 LateralSpreadingDeviceSettingsSeq no + 300A,0372 LateralSpreadingDeviceSetting no + 300A,0374 IsocenterToLateralSpreadingDevDist no + 300A,0380 RangeModulatorSettingsSequence no + 300A,0382 RangeModulatorGatingStartValue no + 300A,0384 RangeModulatorGatingStopValue no + 300A,038A IsocenterToRangeModulatorDistance no + 300A,0390 ScanSpotTuneID no + 300A,0392 NumberOfScanSpotPositions no + 300A,0394 ScanSpotPositionMap no + 300A,0396 ScanSpotMetersetWeights no + 300A,0398 ScanningSpotSize no + 300A,039A NumberOfPaintings no + 300A,03A0 IonToleranceTableSequence no + 300A,03A2 IonBeamSequence no + 300A,03A4 IonBeamLimitingDeviceSequence no + 300A,03A6 IonBlockSequence no + 300A,03A8 IonControlPointSequence no + 300A,03AA IonWedgeSequence no + 300A,03AC IonWedgePositionSequence no + 300A,0401 ReferencedSetupImageSequence no + 300A,0402 SetupImageComment no + 300A,0410 MotionSynchronizationSequence no + 300A,0412 ControlPointOrientation no + 300A,0420 GeneralAccessorySequence no + 300A,0421 GeneralAccessoryID no + 300A,0422 GeneralAccessoryDescription no + 300A,0423 GeneralAccessoryType no + 300A,0424 GeneralAccessoryNumber no + 300C,0002 ReferencedRTPlanSequence no + 300C,0004 ReferencedBeamSequence no + 300C,0006 ReferencedBeamNumber no + 300C,0007 ReferencedReferenceImageNumber no + 300C,0008 StartCumulativeMetersetWeight no + 300C,0009 EndCumulativeMetersetWeight no + 300C,000A ReferencedBrachyAppSetupSeq no + 300C,000C ReferencedBrachyAppSetupNumber no + 300C,000E ReferencedSourceNumber no + 300C,0020 ReferencedFractionGroupSequence no + 300C,0022 ReferencedFractionGroupNumber no + 300C,0040 ReferencedVerificationImageSeq no + 300C,0042 ReferencedReferenceImageSequence no + 300C,0050 ReferencedDoseReferenceSequence no + 300C,0051 ReferencedDoseReferenceNumber no + 300C,0055 BrachyReferencedDoseReferenceSeq no + 300C,0060 ReferencedStructureSetSequence no + 300C,006A ReferencedPatientSetupNumber no + 300C,0080 ReferencedDoseSequence no + 300C,00A0 ReferencedToleranceTableNumber no + 300C,00B0 ReferencedBolusSequence no + 300C,00C0 ReferencedWedgeNumber no + 300C,00D0 ReferencedCompensatorNumber no + 300C,00E0 ReferencedBlockNumber no + 300C,00F0 ReferencedControlPointIndex no + 300C,00F2 ReferencedControlPointSequence no + 300C,00F4 ReferencedStartControlPointIndex no + 300C,00F6 ReferencedStopControlPointIndex no + 300C,0100 ReferencedRangeShifterNumber no + 300C,0102 ReferencedLateralSpreadingDevNum no + 300C,0104 ReferencedRangeModulatorNumber no + 300E,0002 ApprovalStatus no + 300E,0004 ReviewDate no + 300E,0005 ReviewTime no + 300E,0008 ReviewerName no + 4000,0000 TextGroupLength no + 4000,0010 Arbitrary no + 4000,4000 TextComments no + 4008,0040 ResultsID no + 4008,0042 ResultsIDIssuer no + 4008,0050 ReferencedInterpretationSequence no + 4008,0100 InterpretationRecordedDate no + 4008,0101 InterpretationRecordedTime no + 4008,0102 InterpretationRecorder no + 4008,0103 ReferenceToRecordedSound no + 4008,0108 InterpretationTranscriptionDate no + 4008,0109 InterpretationTranscriptionTime no + 4008,010A InterpretationTranscriber no + 4008,010B InterpretationText no + 4008,010C InterpretationAuthor no + 4008,0111 InterpretationApproverSequence no + 4008,0112 InterpretationApprovalDate no + 4008,0113 InterpretationApprovalTime no + 4008,0114 PhysicianApprovingInterpretation no + 4008,0115 InterpretationDiagnosisDescription no + 4008,0117 InterpretationDiagnosisCodeSeq no + 4008,0118 ResultsDistributionListSequence no + 4008,0119 DistributionName no + 4008,011A DistributionAddress no + 4008,0200 InterpretationID no + 4008,0202 InterpretationIDIssuer no + 4008,0210 InterpretationTypeID no + 4008,0212 InterpretationStatusID no + 4008,0300 Impressions no + 4008,4000 ResultsComments no + 4FFE,0001 MACParametersSequence no + 50xx,0005 CurveDimensions no + 50xx,0010 NumberOfPoints no + 50xx,0020 TypeOfData no + 50xx,0022 CurveDescription no + 50xx,0030 AxisUnits no + 50xx,0040 AxisLabels no + 50xx,0103 DataValueRepresentation no + 50xx,0104 MinimumCoordinateValue no + 50xx,0105 MaximumCoordinateValue no + 50xx,0106 CurveRange no + 50xx,0110 CurveDataDescriptor no + 50xx,0112 CoordinateStartValue no + 50xx,0114 CoordinateStepValue no + 50xx,1001 CurveActivationLayer no + 50xx,2000 AudioType no + 50xx,2002 AudioSampleFormat no + 50xx,2004 NumberOfChannels no + 50xx,2006 NumberOfSamples no + 50xx,2008 SampleRate no + 50xx,200A TotalTime no + 50xx,200C AudioSampleData no + 50xx,200E AudioComments no + 50xx,2500 CurveLabel no + 50xx,2600 ReferencedOverlaySequence no + 50xx,2610 ReferencedOverlayGroup no + 50xx,3000 CurveData no + 5200,9229 SharedFunctionalGroupsSequence no + 5200,9230 PerFrameFunctionalGroupsSequence no + 5400,0100 WaveformSequence no + 5400,0110 ChannelMinimumValue no + 5400,0112 ChannelMaximumValue no + 5400,1004 WaveformBitsAllocated no + 5400,1006 WaveformSampleInterpretation no + 5400,100A WaveformPaddingValue no + 5400,1010 WaveformData no + 5600,0010 FirstOrderPhaseCorrectionAngle no + 5600,0020 SpectroscopyData no + 6000,0000 OverlayGroupLength no + 60xx,0010 OverlayRows no + 60xx,0011 OverlayColumns no + 60xx,0012 OverlayPlanes no + 60xx,0015 NumberOfFramesInOverlay no + 60xx,0022 OverlayDescription no + 60xx,0040 OverlayType no + 60xx,0045 OverlaySubtype no + 60xx,0050 OverlayOrigin no + 60xx,0051 ImageFrameOrigin no + 60xx,0052 OverlayPlaneOrigin no + 60xx,0060 OverlayCompressionCode no + 60xx,0061 OverlayCompressionOriginator no + 60xx,0062 OverlayCompressionLabel no + 60xx,0063 OverlayCompressionDescription no + 60xx,0066 OverlayCompressionStepPointers no + 60xx,0068 OverlayRepeatInterval no + 60xx,0069 OverlayBitsGrouped no + 60xx,0100 OverlayBitsAllocated no + 60xx,0102 OverlayBitPosition no + 60xx,0110 OverlayFormat no + 60xx,0200 OverlayLocation no + 60xx,0800 OverlayCodeLabel no + 60xx,0802 OverlayNumberOfTables no + 60xx,0803 OverlayCodeTableLocation no + 60xx,0804 OverlayBitsForCodeWord no + 60xx,1001 OverlayActivationLayer no + 60xx,1100 OverlayDescriptorGray no + 60xx,1101 OverlayDescriptorRed no + 60xx,1102 OverlayDescriptorGreen no + 60xx,1103 OverlayDescriptorBlue no + 60xx,1200 OverlaysGray no + 60xx,1201 OverlaysRed no + 60xx,1202 OverlaysGreen no + 60xx,1203 OverlaysBlue no + 60xx,1301 ROIArea no + 60xx,1302 ROIMean no + 60xx,1303 ROIStandardDeviation no + 60xx,1500 OverlayLabel no + 60xx,3000 OverlayData no + 60xx,4000 OverlayComments no + 7Fxx,0000 PixelDataGroupLength no + 7Fxx,0010 PixelData no + 7Fxx,0011 VariableNextDataGroup no + 7Fxx,0020 VariableCoefficientsSDVN no + 7Fxx,0030 VariableCoefficientsSDHN no + 7Fxx,0040 VariableCoefficientsSDDN no + FFFA,FFFA DigitalSignaturesSequence no + FFFC,FFFC DataSetTrailingPadding no + FFFE,E000 StartOfItem no + FFFE,E00D EndOfItems no + FFFE,E0DD EndOfSequence no + +=head2 JSON Tags + +No JSON tags have been pre-defined, but ExifTool will read any existing +tags from basic JSON-formatted files. + + Tag ID Tag Name Writable + ------ -------- -------- + [no tags known] + +=head2 HTML Tags + +Meta information extracted from the header of HTML and XHTML files. This is +a mix of information found in the C<META> elements, C<XML> element, and the +C<TITLE> element. + + Tag ID Tag Name Writable + ------ -------- -------- + 'abstract' Abstract no + 'author' Author no + 'classification' Classification no + 'content-language' ContentLanguage no + 'copyright' Copyright no + 'dc' DC HTML dc + 'description' Description no + 'distribution' Distribution no + 'doc-class' DocClass no + 'doc-rights' DocRights no + 'doc-type' DocType no + 'formatter' Formatter no + 'generator' Generator no + 'generatorversion' GeneratorVersion no + 'googlebot' GoogleBot no + 'http-equiv' HTTP-equiv HTML equiv + 'keywords' Keywords no+ + 'mssmarttagspreventparsing' NoMSSmartTags no + 'ncc' NCC HTML ncc + 'o' Office HTML Office + 'originator' Originator no + 'owner' Owner no + 'prod' Prod HTML prod + 'progid' ProgID no + 'rating' Rating no + 'refresh' Refresh no + 'resource-type' ResourceType no + 'revisit-after' RevisitAfter no + 'robots' Robots no+ + 'title' Title no + 'vw96' VW96 HTML vw96 + +=head3 HTML dc Tags + +Dublin Core schema tags (also used in XMP). + + Tag ID Tag Name Writable + ------ -------- -------- + 'contributor' Contributor no+ + 'coverage' Coverage no + 'creator' Creator no+ + 'date' Date no+ + 'description' Description no + 'format' Format no + 'identifier' Identifier no + 'language' Language no+ + 'publisher' Publisher no+ + 'relation' Relation no+ + 'rights' Rights no + 'source' Source no + 'subject' Subject no+ + 'title' Title no + 'type' Type no+ + +=head3 HTML equiv Tags + +These tags have a family 1 group name of "HTTP-equiv". + + Tag ID Tag Name Writable + ------ -------- -------- + 'cache-control' CacheControl no + 'content-disposition' ContentDisposition no + 'content-language' ContentLanguage no + 'content-script-type' ContentScriptType no + 'content-style-type' ContentStyleType no + 'content-type' ContentType no + 'default-style' DefaultStyle no + 'expires' Expires no + 'ext-cache' ExtCache no + 'imagetoolbar' ImageToolbar no + 'lotus' Lotus no + 'page-enter' PageEnter no + 'page-exit' PageExit no + 'pics-label' PicsLabel no + 'pragma' Pragma no + 'refresh' Refresh no + 'reply-to' ReplyTo no + 'set-cookie' SetCookie no + 'site-enter' SiteEnter no + 'site-exit' SiteExit no + 'vary' Vary no + 'window-target' WindowTarget no + +=head3 HTML ncc Tags + + Tag ID Tag Name Writable + ------ -------- -------- + 'charset' CharacterSet no + 'depth' Depth no + 'files' Files no + 'footnotes' Footnotes no + 'generator' Generator no + 'kbytesize' KByteSize no + 'maxpagenormal' MaxPageNormal no + 'multimediatype' MultimediaType no + 'narrator' Narrator no + 'pagefront' PageFront no + 'pagenormal' PageNormal no + 'pagespecial' PageSpecial no + 'prodnotes' ProdNotes no + 'produceddate' ProducedDate no + 'producer' Producer no + 'revision' Revision no + 'revisiondate' RevisionDate no + 'setinfo' SetInfo no + 'sidebars' Sidebars no + 'sourcedate' SourceDate no + 'sourceedition' SourceEdition no + 'sourcepublisher' SourcePublisher no + 'sourcerights' SourceRights no + 'sourcetitle' SourceTitle no + 'tocitems' TOCItems no + 'totaltime' Duration no + +=head3 HTML Office Tags + +Tags written by Microsoft Office applications. + + Tag ID Tag Name Writable + ------ -------- -------- + 'Author' Author no + 'Category' Category no + 'Characters' Characters no + 'CharactersWithSpaces' CharactersWithSpaces no + 'Company' Company no + 'Created' CreateDate no + 'Description' Description no + 'Keywords' Keywords no + 'LastAuthor' LastAuthor no + 'LastPrinted' LastPrinted no + 'LastSaved' ModifyDate no + 'Lines' Lines no + 'Manager' Manager no + 'Pages' Pages no + 'Paragraphs' Paragraphs no + 'Revision' RevisionNumber no + 'Subject' Subject no + 'Template' Template no + 'TotalTime' TotalEditTime no + 'Version' RevisionNumber no + 'Words' Words no + +=head3 HTML prod Tags + + Tag ID Tag Name Writable + ------ -------- -------- + 'recengineer' RecEngineer no + 'reclocation' RecLocation no + +=head3 HTML vw96 Tags + + Tag ID Tag Name Writable + ------ -------- -------- + 'objecttype' ObjectType no + +=head2 Palm Tags + +Information extracted from Palm database files (PDB and PRC extensions), +Mobipocket electronic books (MOBI), and Amazon Kindle KF7 and KF8 books (AZW +and AZW3). + + Index4 Tag Name Writable + ------ -------- -------- + 0 DatabaseName no + 9 CreateDate no + 10 ModifyDate no + 11 LastBackupDate no + 12 ModificationNumber no + 15 PalmFileType no + +=head3 Palm MOBI Tags + +Information extracted from the MOBI header of Mobipocket and Amazon Kindle +KF7 and KF8 files. + + Index4 Tag Name Writable + ------ -------- -------- + 0 Compression no + 1 UncompressedTextLength no + 3 Encryption no + 6 MobiType no + 7 CodePage no + 9 MobiVersion no + 21 BookName no + 26 MinimumVersion no + +=head3 Palm EXTH Tags + +Information extracted from the MOBI extended header. + + Tag ID Tag Name Writable + ------ -------- -------- + 0x0001 DRMServerID no + 0x0002 DRMCommerceID no + 0x0003 DRM_E-BookBaseID no + 0x0064 Author no + 0x0065 Publisher no + 0x0066 Imprint no + 0x0067 Description no + 0x0068 ISBN no + 0x0069 Subject no+ + 0x006a PublishDate no + 0x006b Review no + 0x006c Contributor no + 0x006d Rights no + 0x006e SubjectCode no + 0x006f BookType no + 0x0070 Source no + 0x0071 ASIN no + 0x0072 BookVersion no + 0x0073 SampleFlag no + 0x0074 StartReading no + 0x0075 Adult no + 0x0076 RetailPrice no + 0x0077 RetailPriceCurrency no + 0x007d ResourceCount no + 0x0081 KF8CoverURI no + 0x00c8 DictionaryShortName no + 0x00cc CreatorSoftware no + 0x00cd CreatorMajorVersion no + 0x00ce CreatorMinorVersion no + 0x00cf CreatorBuildNumber no + 0x00d0 Watermark no + 0x00d1 Tamper-proofKeys no + 0x0191 ClippingLimit no + 0x0192 PublisherLimit no + 0x0194 TextToSpeech no + 0x0195 RentalFlag no + 0x0196 RentalExpirationDate no + 0x01f5 CDEType no + 0x01f6 LastUpdateTime no + 0x01f7 UpdatedTitle no + 0x01f8 ASIN2 no + 0x020c Language no + 0x020d Alignment no + 0x0217 CreatorBuildNumber2 no + +=head2 Torrent Tags + +Below are tags commonly found in BitTorrent files. As well as these tags, +any other existing tags will be extracted. For convenience, list items are +expanded into individual tags with an index in the tag name, but only the +tags with index "1" are listed in the tables below. See +L<https://wiki.theory.org/BitTorrentSpecification> for the BitTorrent +specification. + + Tag ID Tag Name Writable + ------ -------- -------- + 'announce' Announce no + 'announce-list' AnnounceList1 no + 'comment' Comment no + 'created by' Creator no + 'creation date' CreateDate no + 'encoding' Encoding no + 'info' Info Torrent Info + 'url-list' URLList1 no + +=head3 Torrent Info Tags + + Tag ID Tag Name Writable + ------ -------- -------- + 'file-duration' File1Duration no + 'file-media' File1Media no + 'files' Files Torrent Files + 'length' Length no + 'md5sum' MD5Sum no + 'name' Name no + 'name.utf-8' NameUTF-8 no + 'piece length' PieceLength no + 'pieces' Pieces no + 'private' Private no + 'profiles' Profiles Torrent Profiles + +=head3 Torrent Files Tags + + Tag ID Tag Name Writable + ------ -------- -------- + 'length' File1Length no + 'md5sum' File1MD5Sum no + 'path' File1Path no + 'path.utf-8' File1PathUTF-8 no + +=head3 Torrent Profiles Tags + + Tag ID Tag Name Writable + ------ -------- -------- + 'acodec' Profile1AudioCodec no + 'height' Profile1Height no + 'vcodec' Profile1VideoCodec no + 'width' Profile1Width no + +=head2 EXE Tags + +This module extracts information from various types of Windows, MacOS and +Unix executable and library files. The first table below lists information +extracted from the header of Windows PE (Portable Executable) EXE files and +DLL libraries. + + Index2 Tag Name Writable + ------ -------- -------- + 0 MachineType no + 2 TimeStamp no + 9 ImageFileCharacteristics no + 10 PEType no + 11 LinkerVersion no + 12 CodeSize no + 14 InitializedDataSize no + 16 UninitializedDataSize no + 18 EntryPoint no + 30 OSVersion no + 32 ImageVersion no + 34 SubsystemVersion no + 44 Subsystem no + +=head3 EXE PEVersion Tags + +Information extracted from the VS_VERSION_INFO structure of Windows PE +files. + + Index4 Tag Name Writable + ------ -------- -------- + 2 FileVersionNumber no + 4 ProductVersionNumber no + 6 FileFlagsMask no + 7 FileFlags no + 8 FileOS no + 9 ObjectFileType no + 10 FileSubtype no + +=head3 EXE PEString Tags + +Resource strings found in Windows PE files. The B<TagID>'s are not shown +because they are the same as the B<Tag Name>. ExifTool will extract any +existing StringFileInfo tags even if not listed in this table. + + Tag Name Writable + -------- -------- + BuildDate no + BuildVersion no + CharacterSet no + Comments no + CompanyName no + Copyright no + FileDescription no + FileVersion no + InternalName no + LanguageCode no + LegalCopyright no + LegalTrademarks no + OriginalFileName no + PrivateBuild no + ProductName no + ProductVersion no + SpecialBuild no + +=head3 EXE MachO Tags + +Information extracted from Mach-O (Mac OS X) executable files and DYLIB +libraries. + + Index Tag Name Writable + ----- -------- -------- + 0 CPUArchitecture no + 1 CPUByteOrder no + 2 CPUCount no + 3 CPUType no+ + 4 CPUSubtype no+ + 5 ObjectFileType no + 6 ObjectFlags no + +=head3 EXE PEF Tags + +Information extracted from PEF (Classic MacOS) executable files and +libraries. + + Index4 Tag Name Writable + ------ -------- -------- + 2 CPUArchitecture no + 3 PEFVersion no + 4 TimeStamp no + +=head3 EXE ELF Tags + +Information extracted from ELF (Unix) executable files and SO libraries. + + Index1 Tag Name Writable + ------ -------- -------- + 4 CPUArchitecture no + 5 CPUByteOrder no + 16 ObjectFileType no + 18 CPUType no + +=head3 EXE AR Tags + +Information extracted from static libraries. + + Index1 Tag Name Writable + ------ -------- -------- + 16 CreateDate no + +=head3 EXE CHM Tags + +Tags extracted from Microsoft Compiled HTML files. + + Index4 Tag Name Writable + ------ -------- -------- + 1 CHMVersion no + 5 LanguageCode no + +=head2 LNK Tags + +Information extracted from MS Shell Link (Windows shortcut) files. + + Index1 Tag Name Writable + ------ -------- -------- + 0x0014 Flags no + 0x0018 FileAttributes no + 0x001c CreateDate no + 0x0024 AccessDate no + 0x002c ModifyDate no + 0x0034 TargetFileSize no + 0x0038 IconIndex no + 0x003c RunWindow no + 0x0040 HotKey no + 0x10000 ItemID LNK ItemID + 0x20000 LinkInfo LNK LinkInfo + 0x30004 Description no + 0x30008 RelativePath no + 0x30010 WorkingDirectory no + 0x30020 CommandLineArguments no + 0x30040 IconFileName no + 0xa0000000 UnknownData LNK UnknownData + 0xa0000001 EnvVarData LNK UnknownData + 0xa0000002 ConsoleData LNK ConsoleData + 0xa0000003 TrackerData LNK TrackerData + 0xa0000004 ConsoleFEData LNK ConsoleFEData + 0xa0000005 SpecialFolderData LNK UnknownData + 0xa0000006 DarwinData LNK UnknownData + 0xa0000007 IconEnvData LNK UnknownData + 0xa0000008 ShimData LNK UnknownData + 0xa0000009 PropertyStoreData LNK UnknownData + 0xa000000b KnownFolderData LNK UnknownData + 0xa000000c VistaIDListData LNK UnknownData + +=head3 LNK ItemID Tags + + Tag ID Tag Name Writable + ------ -------- -------- + 0x0032 Item0032 LNK Item0032 + +=head3 LNK Item0032 Tags + + Index1 Tag Name Writable + ------ -------- -------- + 14 TargetFileDOSName no + +=head3 LNK LinkInfo Tags + + Tag Name Writable + -------- -------- + CommonNetworkRelLink no + CommonPathSuffix no + DeviceName no + DriveSerialNumber no + DriveType no + LocalBasePath no + NetName no + NetProviderType no + VolumeID no + VolumeLabel no + +=head3 LNK UnknownData Tags + + Index1 Tag Name Writable + ------ -------- -------- + [no tags known] + +=head3 LNK ConsoleData Tags + + Index1 Tag Name Writable + ------ -------- -------- + 8 FillAttributes no + 10 PopupFillAttributes no + 12 ScreenBufferSize no + 16 WindowSize no + 20 WindowOrigin no + 32 FontSize no + 36 FontFamily no + 40 FontWeight no + 44 FontName no + 108 CursorSize no + 112 FullScreen no + 116 QuickEdit no + 120 InsertMode no + 124 WindowOriginAuto no + 128 HistoryBufferSize no + 132 NumHistoryBuffers no + 136 RemoveHistoryDuplicates no + +=head3 LNK TrackerData Tags + + Index1 Tag Name Writable + ------ -------- -------- + 16 MachineID no + +=head3 LNK ConsoleFEData Tags + + Index1 Tag Name Writable + ------ -------- -------- + 8 CodePage no + +=head2 Font Tags + +This table contains a collection of tags found in font files of various +formats. ExifTool current recognizes OTF, TTF, TTC, DFONT, PFA, PFB, PFM, +AFM, ACFM and AMFM font files. + + Tag ID Tag Name Writable + ------ -------- -------- + 'AFM' AFM Font AFM + 'PFM' PFMHeader Font PFM + 'PSInfo' PSFontInfo Font PSInfo + 'fontname' FontName no + 'name' Name Font Name + 'numfonts' NumFonts no + 'postfont' PostScriptFontName no + +=head3 Font AFM Tags + +Tags extracted from Adobe Font Metrics files (AFM, ACFM and AMFM). + + Tag ID Tag Name Writable + ------ -------- -------- + 'Ascender' Ascender no + 'CapHeight' CapHeight no + 'CharacterSet' CharacterSet no + 'Characters' Characters no + 'Creation Date' CreateDate no + 'Descender' Descender no + 'EncodingScheme' EncodingScheme no + 'EscChar' EscChar no + 'FamilyName' FontFamily no + 'FontName' FontName no + 'FullName' FullName no + 'IsBaseFont' IsBaseFont no + 'IsFixedV' IsFixedV no + 'MappingScheme' MappingScheme no + 'Notice' Notice no + 'Version' Version no + 'Weight' Weight no + 'XHeight' XHeight no + +=head3 Font PFM Tags + +Tags extracted from the PFM file header. + + Index1 Tag Name Writable + ------ -------- -------- + 0 PFMVersion no + 6 Copyright no + 66 FontType no + 68 PointSize no + 70 YResolution no + 72 XResolution no + 74 Ascent no + 76 InternalLeading no + 78 ExternalLeading no + 80 Italic no + 81 Underline no + 82 Strikeout no + 83 Weight no + 85 CharacterSet no + 86 PixWidth no + 88 PixHeight no + 90 PitchAndFamily no + 91 AvgWidth no + 93 MaxWidth no + 95 FirstChar no + 96 LastChar no + 97 DefaultChar no + 98 BreakChar no + 99 WidthBytes no + +=head3 Font PSInfo Tags + +Tags extracted from PostScript font files (PFA and PFB). + + Tag ID Tag Name Writable + ------ -------- -------- + 'Copyright' Copyright no + 'FSType' FSType no + 'FamilyName' FontFamily no + 'FontName' FontName no + 'FontType' FontType no + 'FullName' FullName no + 'ItalicAngle' ItalicAngle no + 'Notice' Notice no + 'UnderlinePosition' UnderlinePosition no + 'UnderlineThickness' UnderlineThickness no + 'Weight' Weight no + 'isFixedPitch' IsFixedPitch no + 'version' Version no + +=head3 Font Name Tags + +The following tags are extracted from the TrueType font "name" table found +in OTF, TTF, TTC and DFONT files. These tags support localized languages by +adding a hyphen followed by a language code to the end of the tag name (eg. +"Copyright-fr" or "License-en-US"). Tags with no language code use the +default language of "en". + + Tag ID Tag Name Writable + ------ -------- -------- + 0x0000 Copyright no + 0x0001 FontFamily no + 0x0002 FontSubfamily no + 0x0003 FontSubfamilyID no + 0x0004 FontName no + 0x0005 NameTableVersion no + 0x0006 PostScriptFontName no + 0x0007 Trademark no + 0x0008 Manufacturer no + 0x0009 Designer no + 0x000a Description no + 0x000b VendorURL no + 0x000c DesignerURL no + 0x000d License no + 0x000e LicenseInfoURL no + 0x0010 PreferredFamily no + 0x0011 PreferredSubfamily no + 0x0012 CompatibleFontName no + 0x0013 SampleText no + 0x0014 PostScriptFontName no + 0x0015 WWSFamilyName no + 0x0016 WWSSubfamilyName no + +=head2 VCard Tags + +This table lists common vCard tags, but ExifTool will also extract any other +vCard tags found. Tag names may have "Pref" added to indicate the preferred +instance of a vCard property, and other "TYPE" parameters may also added to +the tag name. VCF files may contain multiple vCard entries which are +distinguished by the ExifTool family 3 group name (document number). See +L<http://tools.ietf.org/html/rfc6350> for the vCard 4.0 specification. + + Tag ID Tag Name Writable + ------ -------- -------- + 'Adr' Address no + 'Anniversary' Anniversary no + 'Bday' Birthday no + 'Email' Email no + 'Fn' FormattedName no + 'Gender' Gender no + 'Geo' Geolocation no + 'Impp' IMPP no + 'Lang' Language no + 'Logo' Logo no + 'N' Name no + 'Nickname' Nickname no + 'Note' Note no + 'Org' Organization no + 'Photo' Photo no + 'Prodid' Software no + 'Rev' Revision no + 'Sound' Sound no + 'Tel' Telephone no + 'Title' JobTitle no + 'Tz' TimeZone no + 'Uid' UID no + 'Url' URL no + 'Version' VCardVersion no + 'X-abdate' ABDate no + 'X-ablabel' ABLabel no + 'X-abrelatednames' ABRelatedNames no + 'X-abuid' AB_UID no + 'X-aim' AIM no + 'X-icq' ICQ no + 'X-socialprofile' SocialProfile no + +=head3 VCard VCalendar Tags + +The VCard module is also used to process iCalendar ICS files since they use +a format similar to vCard. The following table lists standard iCalendar +tags, but any existing tags will be extracted. Top-level iCalendar +components (eg. Event, Todo, Timezone, etc.) are used for the family 1 group +names, and embedded components (eg. Alarm) are added as a prefix to the tag +name. See L<http://tools.ietf.org/html/rfc5545> for the official iCalendar +2.0 specification. + + Tag ID Tag Name Writable + ------ -------- -------- + 'Acknowledged' Acknowledged no + 'Action' Action no + 'Attach' Attachment no + 'Attendee' Attendee no + 'Calscale' CalendarScale no + 'Categories' Categories no + 'Class' Classification no + 'Comment' Comment no + 'Completed' DateTimeCompleted no + 'Contact' Contact no + 'Created' DateCreated no + 'Description' Description no + 'Dtend' DateTimeEnd no + 'Dtstamp' DateTimeStamp no + 'Dtstart' DateTimeStart no + 'Due' DateTimeDue no + 'Duration' Duration no + 'Exdate' ExceptionDateTimes no + 'Freebusy' FreeBusyTime no + 'Geo' Geolocation no + 'Last-modified' ModifyDate no + 'Location' Location no + 'Method' Method no + 'Organizer' Organizer no + 'Percent-complete' PercentComplete no + 'Priority' Priority no + 'Prodid' Software no + 'Rdate' RecurrenceDateTimes no + 'Recurrence-id' RecurrenceID no + 'Related-to' RelatedTo no + 'Repeat' Repeat no + 'Request-status' RequestStatus no + 'Resources' Resources no + 'Rrule' RecurrenceRule no + 'Sequence' SequenceNumber no + 'Status' Status no + 'Summary' Summary no + 'Transp' TimeTransparency no + 'Trigger' Trigger no + 'Tzid' TimezoneID no + 'Tzname' TimezoneName no + 'Tzoffsetfrom' TimezoneOffsetFrom no + 'Tzoffsetto' TimezoneOffsetTo no + 'Tzurl' TimeZoneURL no + 'Uid' UID no + 'Url' URL no + 'Version' VCalendarVersion no + 'X-apple-calendar-color' CalendarColor no + 'X-apple-default-alarm' DefaultAlarm no + 'X-apple-local-default-alarm' + LocalDefaultAlarm no + 'X-microsoft-cdo-alldayevent' AllDayEvent no + 'X-microsoft-cdo-appt-sequence' + AppointmentSequence no + 'X-microsoft-cdo-busystatus' BusyStatus no + 'X-microsoft-cdo-importance' Importance no + 'X-microsoft-cdo-insttype' InstanceType no + 'X-microsoft-cdo-intendedstatus' + IntendedBusyStatus no + 'X-microsoft-cdo-ownerapptid' + OwnerAppointmentID no + 'X-microsoft-disallow-counter' + DisallowCounterProposal no + 'X-microsoft-donotforwardmeeting' + DoNotForwardMeeting no + 'X-microsoft-locations' MeetingLocations no + 'X-wr-alarmuid' AlarmUID no + 'X-wr-caldesc' CalendarDescription no + 'X-wr-calname' CalendarName no + 'X-wr-relcalid' CalendarID no + 'X-wr-timezone' TimeZone2 no + +=head2 RSRC Tags + +Tags extracted from Mac OS resource files and DFONT files. These tags may +also be extracted from the resource fork of any file in OS X, either by +adding "/..namedfork/rsrc" to the filename to process the resource fork +alone, or by using the ExtractEmbedded (-ee) option to process the resource +fork as a sub-document of the main file. When writing, ExifTool preserves +the Mac OS resource fork by default, but it may deleted with C<-rsrc:all=> +on the command line. + + Tag ID Tag Name Writable + ------ -------- -------- + '8BIM' PhotoshopInfo Photoshop + 'POST_0x01f5' PostscriptFont PostScript + 'STR _0xbff3' ApplicationMissingMsg no + 'STR _0xbff4' CreatorApplication no + 'STR#_0x0080' Keywords no + 'TEXT_0x0080' Description no + 'sfnt' Font Font Name + 'usro_0x0000' OpenWithApplication no + 'vers_0x0001' ApplicationVersion no + +=head2 Rawzor Tags + +Rawzor files store compressed images of other formats. As well as the +information listed below, exiftool uncompresses and extracts the meta +information from the original image. + + Tag Name Writable + -------- -------- + CompressionFactor no + OriginalFileSize no + OriginalFileType no + RawzorCreatorVersion no + RawzorRequiredVersion no + +=head2 ZIP Tags + +The following tags are extracted from ZIP archives. ExifTool also extracts +additional meta information from compressed documents inside some ZIP-based +files such Office Open XML (DOCX, PPTX and XLSX), Open Document (ODB, ODC, +ODF, ODG, ODI, ODP, ODS and ODT), iWork (KEY, PAGES, NUMBERS), Capture One +Enhanced Image Package (EIP), Adobe InDesign Markup Language (IDML), +Electronic Publication (EPUB), and Sketch design files (SKETCH). The +ExifTool family 3 groups may be used to organize ZIP tags by embedded +document number (ie. the exiftool C<-g3> option). + + Index2 Tag Name Writable + ------ -------- -------- + 2 ZipRequiredVersion no + 3 ZipBitFlag no + 4 ZipCompression no + 5 ZipModifyDate no + 7 ZipCRC no + 9 ZipCompressedSize no + 11 ZipUncompressedSize no + 15 ZipFileName no + +=head3 ZIP GZIP Tags + +These tags are extracted from GZIP (GNU ZIP) archives, but currently only +for the first file in the archive. + + Index1 Tag Name Writable + ------ -------- -------- + 2 Compression no + 3 Flags no + 4 ModifyDate no + 8 ExtraFlags no + 9 OperatingSystem no + 10 ArchivedFileName no + 11 Comment no + +=head3 ZIP RAR Tags + +These tags are extracted from RAR archive files. + + Index1 Tag Name Writable + ------ -------- -------- + 0 CompressedSize no + 4 UncompressedSize no + 8 OperatingSystem no + 13 ModifyDate no + 18 PackingMethod no + 25 ArchivedFileName no + +=head2 RTF Tags + +This table lists standard tags of the RTF information group, but ExifTool +will also extract any non-standard tags found in this group. As well, +ExifTool will extract any custom properties that are found. See +L<http://www.microsoft.com/en-ca/download/details.aspx?id=10725> for the +specification. + + Tag ID Tag Name Writable + ------ -------- -------- + 'author' Author no + 'buptim' BackupTime no + 'category' Category no + 'comment' Comment no + 'company' Company no + 'copyright' Copyright no + 'creatim' CreateDate no + 'doccomm' Comments no + 'edmins' TotalEditTime no + 'hlinkbase' HyperlinkBase no + 'id' InternalIDNumber no + 'keywords' Keywords no + 'manager' Manager no + 'nofchars' Characters no + 'nofcharsws' CharactersWithSpaces no + 'nofpages' Pages no + 'nofwords' Words no + 'operator' LastModifiedBy no + 'printim' LastPrinted no + 'revtim' ModifyDate no + 'subject' Subject no + 'title' Title no + 'vern' InternalVersionNumber no + 'version' RevisionNumber no + +=head2 OOXML Tags + +The Office Open XML (OOXML) format was introduced with Microsoft Office 2007 +and is used by file types such as DOCX, PPTX and XLSX. These are +essentially ZIP archives containing XML files. The table below lists some +tags which have been observed in OOXML documents, but ExifTool will extract +any tags found from XML files of the OOXML document properties ("docProps") +directory. + +B<Tips:> + +1) Structural ZIP tags may be ignored (if desired) with C<--ZIP:all> on the +command line. + +2) Tags may be grouped by their document number in the ZIP archive with the +C<-g3> or C<-G3> option. + + Tag Name Writable + -------- -------- + AppVersion no + Application no + Category no + Characters no + CharactersWithSpaces no + CheckedBy no + Client no + Company no + CreateDate no + DateCompleted no + Department no + Destination no + Disposition no + Division no + DocSecurity no + DocumentNumber no + Editor no + ForwardTo no + Group no + HeadingPairs no + HiddenSlides no + HyperlinkBase no + HyperlinksChanged no + Keywords no + Language no + LastModifiedBy no + LastPrinted no + Lines no + LinksUpToDate no + MMClips no + Mailstop no + Manager no + Matter no + ModifyDate no + Notes no + Office no + Owner no + Pages no + Paragraphs no + PresentationFormat no + Project no + Publisher no + Purpose no + ReceivedFrom no + RecordedBy no + RecordedDate no + Reference no + RevisionNumber no + ScaleCrop no + SharedDoc no + Slides no + Source no + Status no + TelephoneNumber no + Template no + TitlesOfParts no + TotalEditTime no + Typist no + Words no + +=head2 iWork Tags + +The Apple iWork '09 file format is a ZIP archive containing XML files +similar to the Office Open XML (OOXML) format. Metadata tags in iWork +files are extracted even if they don't appear below. + + Tag Name Writable + -------- -------- + Author no + Comment no + Copyright no + Keywords no + Projects no+ + Title no + +=head2 ISO Tags + +Tags extracted from ISO 9660 disk images. + + Tag ID Tag Name Writable + ------ -------- -------- + 0x0000 BootRecord ISO BootRecord + 0x0001 PrimaryVolume ISO PrimaryVolume + +=head3 ISO BootRecord Tags + + Index1 Tag Name Writable + ------ -------- -------- + 7 BootSystem no + 39 BootIdentifier no + +=head3 ISO PrimaryVolume Tags + + Index1 Tag Name Writable + ------ -------- -------- + 8 System no + 40 VolumeName no + 80 VolumeBlockCount no + 120 VolumeSetDiskCount? no + 124 VolumeSetDiskNumber? no + 128 VolumeBlockSize no + 132 PathTableSize? no + 140 PathTableLocation? no + 174 RootDirectoryCreateDate no + 190 VolumeSetName no + 318 Publisher no + 446 DataPreparer no + 574 Software no + 702 CopyrightFileName no + 740 AbstractFileName no + 776 BibligraphicFileName no + 813 VolumeCreateDate no + 830 VolumeModifyDate no + 847 VolumeExpirationDate no + 864 VolumeEffectiveDate no + +=head2 MacOS Tags + +On MacOS systems, there are a number of additional tags with names beginning +with "MDItem" and "XAttr" that may be extracted. These tags are not +extracted by default -- they must be specifically requested or enabled via +an API option. + +The tables below list some of the tags that may be extracted, but ExifTool +will extract all available information even for tags not listed. + +Tags in these tables are referred to as "pseudo" tags because their +information is not stored in the file itself. As such, B<Writable> tags in +these tables may be changed without having to rewrite the file. + +=head3 MacOS MDItem Tags + +MDItem tags are extracted using the "mdls" utility. They are extracted if +any "MDItem*" tag or the MacOS group is specifically requested, or by +setting the MDItemTags API option to 1 or the RequestAll API option to 2 or +higher. Note that these tags do not necessarily reflect the current +metadata of a file -- it may take some time for the MacOS mdworker daemon to +index the file after the metadata changes. + + Tag Name Writable + -------- -------- + AppleMailDateReceived no + AppleMailFlagged no + AppleMailMessageID no + AppleMailPriority no + AppleMailRead no + AppleMailRepliedTo no + MDItemAccountHandles no + MDItemAccountIdentifier no + MDItemAcquisitionMake no + MDItemAcquisitionModel no + MDItemAltitude no + MDItemAperture no + MDItemAuthorEmailAddresses no + MDItemAuthors no + MDItemBitsPerSample no + MDItemBundleIdentifier no + MDItemCity no + MDItemColorSpace no + MDItemComment no + MDItemContentCreationDate no + MDItemContentCreationDate_Ranking no + MDItemContentModificationDate no + MDItemContentType no + MDItemContentTypeTree no + MDItemContributors no + MDItemCopyright no + MDItemCountry no + MDItemCreator no + MDItemDateAdded no + MDItemDateAdded_Ranking no + MDItemDescription no + MDItemDisplayName no + MDItemDownloadedDate no + MDItemEXIFGPSVersion no + MDItemEXIFVersion no + MDItemEmailConversationID no + MDItemEncodingApplications no + MDItemExposureMode no + MDItemExposureProgram no + MDItemExposureTimeSeconds no + MDItemFNumber no + MDItemFSContentChangeDate no + MDItemFSCreationDate yes! + MDItemFSCreatorCode no + MDItemFSFinderFlags no + MDItemFSHasCustomIcon no + MDItemFSInvisible no + MDItemFSIsExtensionHidden no + MDItemFSIsStationery no + MDItemFSLabel yes! + MDItemFSName no + MDItemFSNodeCount no + MDItemFSOwnerGroupID no + MDItemFSOwnerUserID no + MDItemFSSize no + MDItemFSTypeCode no + MDItemFinderComment yes! + MDItemFlashOnOff no + MDItemFocalLength no + MDItemGPSDateStamp no + MDItemGPSStatus no + MDItemGPSTrack no + MDItemHasAlphaChannel no + MDItemISOSpeed no + MDItemIdentifier no + MDItemImageDirection no + MDItemInterestingDate_Ranking no + MDItemIsApplicationManaged no + MDItemIsExistingThread no + MDItemIsLikelyJunk no + MDItemKeywords no + MDItemKind no + MDItemLastUsedDate no + MDItemLatitude no + MDItemLogicalSize no + MDItemLongitude no + MDItemMailDateReceived_Ranking no + MDItemMailboxes no + MDItemNumberOfPages no + MDItemOrientation no + MDItemOriginApplicationIdentifier no + MDItemOriginMessageID no + MDItemOriginSenderDisplayName no + MDItemOriginSenderHandle no + MDItemOriginSubject no + MDItemPageHeight no + MDItemPageWidth no + MDItemPhysicalSize no + MDItemPixelCount no + MDItemPixelHeight no + MDItemPixelWidth no + MDItemPrimaryRecipientEmailAddresses no + MDItemProfileName no + MDItemRecipients no + MDItemRedEyeOnOff no + MDItemResolutionHeightDPI no + MDItemResolutionWidthDPI no + MDItemSecurityMethod no + MDItemSpeed no + MDItemStateOrProvince no + MDItemSubject no + MDItemTimestamp no + MDItemTitle no + MDItemUseCount no + MDItemUsedDates no + MDItemUserTags yes!+ + MDItemVersion no + MDItemWhereFroms no + MDItemWhiteBalance no + +=head3 MacOS XAttr Tags + +XAttr tags are extracted using the "xattr" utility. They are extracted if +any "XAttr*" tag or the MacOS group is specifically requested, or by setting +the XAttrTags API option to 1 or the RequestAll API option to 2 or higher. + + Tag Name Writable + -------- -------- + XAttrFinderInfo no + XAttrMDItemDownloadedDate no + XAttrMDItemFinderComment no + XAttrMDItemWhereFroms no + XAttrMDLabel no + XAttrQuarantine yes! + XAttrResourceFork no + +=head2 Extra Tags + +The extra tags provide extra features or extra information extracted or +generated by ExifTool that is not directly associated with another tag +group. The B<Group> column lists the family 1 group name when reading. +Tags with a "-" in this column are write-only. + +Tags in the family 1 "System" group are referred to as "pseudo" tags because +they don't represent real metadata in the file. Instead, this information +is stored in the directory structure of the filesystem. The B<Writable> +System "pseudo" tags in this table may be written without modifying the file +itself. The TestName tag is used for dry-run testing before writing +FileName. + + Tag Name Group Writable + -------- ----- -------- + Adobe Adobe yes! + CanonDR4 CanonVRD yes! + CanonVRD CanonVRD yes! + Comment File yes + CurrentIPTCDigest File no + Directory System yes! + EXIF EXIF yes! + Error ExifTool no + ExifByteOrder File yes + ExifToolVersion ExifTool no + ExifUnicodeByteOrder - yes + FileAccessDate System no + FileAttributes System no + FileBlockCount System no + FileBlockSize System no + FileCreateDate System yes! + FileDeviceID System no + FileDeviceNumber System no + FileGroupID System yes! + FileHardLinks System no + FileInodeChangeDate System no + FileInodeNumber System no + FileModifyDate System yes! + FileName System yes! + FilePath System no + FilePermissions System yes! + FileSequence ExifTool no + FileSize System no + FileType File no + FileTypeExtension File no + FileUserID System yes! + ForceWrite - yes + Geosync - yes + Geotag - yes + Geotime - yes + HardLink - yes! + ICC_Profile ICC_Profile yes! + ID3Size File no + IPTC IPTC yes! + ImageHeight File no + ImageWidth File no + JPEGDigest File no + JPEGQualityEstimate File no + MIMEType File no + MaxVal File no + NewGUID ExifTool no + Now ExifTool no + OtherImage File no + PreviewImage File yes + PreviewPDF File no + PreviewPNG File no + PreviewTIFF File no + PreviewWMF File no + ProcessingTime ExifTool no + RAFVersion File no + ResourceForkSize System no + TestName - yes! + ThumbnailImage File no + Validate ExifTool no + Warning ExifTool no + XMP XMP yes! + XResolution File no + YResolution File no + +=head2 Composite Tags + +The values of the composite tags are B<Derived From> the values of other +tags. These are convenience tags which are calculated after all other +information is extracted. Only a few of these tags are writable directly, +the others are changed by writing the corresponding B<Derived From> tags. +User-defined Composite tags, also useful for custom-formatting of tag +values, may created via the ExifTool configuration file. + + Tag Name Derived From Writable + -------- ------------ -------- + AdvancedSceneMode Model no + SceneMode + AdvancedSceneType + Aperture FNumber no + ApertureValue + AudioBitrate MPEG:MPEGAudioVersion no + MPEG:SampleRate + MPEG:VBRBytes + MPEG:VBRFrames + AutoFocus Nikon:PhaseDetectAF no + Nikon:ContrastDetectAF + AvgBitrate QuickTime::MovieDataSize no + QuickTime::Duration + BlueBalance WB_RGGBLevels no + WB_RGBGLevels + WB_RBGGLevels + WB_GRBGLevels + WB_GRGBLevels + WB_GBRGLevels + WB_RGBLevels + WB_GRBLevels + WB_RBLevels + WBBlueLevel + WBGreenLevel + CDDBDiscPlayTime CDDB1Info no + CDDBDiscTracks CDDB1Info no + CFAPattern CFARepeatPatternDim no + CFAPattern2 + CircleOfConfusion ScaleFactor35efl no + ConditionalFEC FlashExposureComp no + FlashBits + DOF FocalLength no + Aperture + CircleOfConfusion + FocusDistance + SubjectDistance + ObjectDistance + ApproximateFocusDistance + FocusDistanceLower + FocusDistanceUpper + DateCreated Kodak:YearCreated no + Kodak:MonthDayCreated + DateTimeCreated IPTC:DateCreated no + IPTC:TimeCreated + DateTimeOriginal DateTimeCreated no + DateCreated + TimeCreated + DateTimeOriginal ID3:RecordingTime no + ID3:Year + ID3:Date + ID3:Time + DepthMapTiff DepthMapData no + DepthMapWidth + DepthMapHeight + DigitalCreationDateTime IPTC:DigitalCreationDate no + IPTC:DigitalCreationTime + DigitalZoom Canon:ZoomSourceWidth no + Canon:ZoomTargetWidth + Canon:DigitalZoom + DriveMode ContinuousDrive no + SelfTimer + Duration FLAC:SampleRate no + FLAC:TotalSamples + Duration Vorbis:NominalBitrate no + FileSize + Duration APE:SampleRate no + APE:TotalFrames + APE:BlocksPerFrame + APE:FinalFrameBlocks + Duration FileSize no + ID3Size + MPEG:AudioBitrate + MPEG:VideoBitrate + MPEG:VBRFrames + MPEG:SampleRate + MPEG:MPEGAudioVersion + Duration RIFF:FrameRate no + RIFF:FrameCount + VideoFrameRate + VideoFrameCount + Duration RIFF:AvgBytesPerSec no + FileSize + FrameCount + VideoFrameCount + Duration AIFF:SampleRate no + AIFF:NumSampleFrames + ExtenderStatus Olympus:Extender no + Olympus:LensType + MaxApertureValue + FOV FocalLength no + ScaleFactor35efl + FocusDistance + FileNumber DirectoryIndex yes + FileIndex + Flash XMP:FlashFired yes + XMP:FlashReturn + XMP:FlashMode + XMP:FlashFunction + XMP:FlashRedEyeMode + XMP:Flash + FlashType FlashBits no + FocalLength35efl FocalLength no + ScaleFactor35efl + FocusDistance Sony:FocusPosition no + FocalLength + FocusDistance2 Sony:FocusPosition2 no + FocalLengthIn35mmFormat + GPSAltitude GPS:GPSAltitude no + GPS:GPSAltitudeRef + XMP:GPSAltitude + XMP:GPSAltitudeRef + GPSAltitude QuickTime:GPSCoordinates no + GPSAltitude QuickTime:LocationInformation no + GPSAltitudeRef QuickTime:GPSCoordinates no + GPSAltitudeRef QuickTime:LocationInformation no + GPSDateTime GPS:GPSDateStamp no + GPS:GPSTimeStamp + GPSDestLatitude GPS:GPSDestLatitude no + GPS:GPSDestLatitudeRef + GPSDestLatitudeRef XMP:GPSDestLatitude no + GPSDestLongitude GPS:GPSDestLongitude no + GPS:GPSDestLongitudeRef + GPSDestLongitudeRef XMP:GPSDestLongitude no + GPSLatitude GPS:GPSLatitude no + GPS:GPSLatitudeRef + GPSLatitude QuickTime:GPSCoordinates no + GPSLatitude QuickTime:LocationInformation no + GPSLatitudeRef XMP:GPSLatitude no + GPSLongitude GPS:GPSLongitude no + GPS:GPSLongitudeRef + GPSLongitude QuickTime:GPSCoordinates no + GPSLongitude QuickTime:LocationInformation no + GPSLongitudeRef XMP:GPSLongitude no + GPSPosition GPSLatitude no + GPSLongitude + HyperfocalDistance FocalLength no + Aperture + CircleOfConfusion + IDCPreviewImage IDCPreviewStart no + IDCPreviewLength + ISO Canon:CameraISO no + Canon:BaseISO + Canon:AutoISO + ImageHeight Main:PostScript:ImageData no + PostScript:BoundingBox + ImageHeight IFD0:SensorTopBorder no + IFD0:SensorBottomBorder + ImageSize ImageWidth no + ImageHeight + ExifImageWidth + ExifImageHeight + ImageWidth Main:PostScript:ImageData no + PostScript:BoundingBox + ImageWidth IFD0:SensorLeftBorder no + IFD0:SensorRightBorder + JpgFromRaw JpgFromRawStart yes + JpgFromRawLength + Lens Canon:MinFocalLength no + Canon:MaxFocalLength + Lens35efl Canon:MinFocalLength no + Canon:MaxFocalLength + Lens + ScaleFactor35efl + LensID LensType no + FocalLength + MaxAperture + MaxApertureValue + MinFocalLength + MaxFocalLength + LensModel + LensFocalRange + LensSpec + LensType2 + LensFocalLength + LensID XMP-aux:LensID no + Make + LensInfo + FocalLength + LensModel + MaxApertureValue + LensID Nikon:LensIDNumber no + LensFStops + MinFocalLength + MaxFocalLength + MaxApertureAtMinFocal + MaxApertureAtMaxFocal + MCUVersion + Nikon:LensType + LensID Ricoh:LensFirmware no + LensSpec Nikon:Lens no + Nikon:LensType + LightValue Aperture no + ShutterSpeed + ISO + MPImage MPImageStart no + MPImageLength + MPImageType + Megapixels ImageSize no + OriginalDecisionData OriginalDecisionDataOffset yes! + OtherImage OtherImageStart yes + OtherImageLength + PeakSpectralSensitivity FLIR:PlanckB no + PreviewImage PreviewImageStart yes + PreviewImageLength + PreviewImageValid + PreviewImageStart (1) + PreviewImageLength (1) + PreviewImage ScreenNail no + PreviewImageSize PreviewImageWidth no + PreviewImageHeight + RedBalance WB_RGGBLevels no + WB_RGBGLevels + WB_RBGGLevels + WB_GRBGLevels + WB_GRGBLevels + WB_GBRGLevels + WB_RGBLevels + WB_GRBLevels + WB_RBLevels + WBRedLevel + WBGreenLevel + RedEyeReduction CanonFlashMode no + FlashBits + RicohPitch Ricoh:Accelerometer no + RicohRoll Ricoh:Accelerometer no + Rotation QuickTime:MatrixStructure yes + QuickTime:HandlerType + RunTimeSincePowerUp Apple:RunTimeValue no + Apple:RunTimeScale + ScaleFactor35efl FocalLength no + FocalLengthIn35mmFormat + Composite:DigitalZoom + FocalPlaneDiagonal + SensorSize + FocalPlaneXSize + FocalPlaneYSize + FocalPlaneResolutionUnit + FocalPlaneXResolution + FocalPlaneYResolution + ExifImageWidth + ExifImageHeight + CanonImageWidth + CanonImageHeight + ImageWidth + ImageHeight + ShootingMode CanonExposureMode no + EasyMode + BulbDuration + ShutterCurtainHack FlashBits no + ShutterCurtainSync + ShutterSpeed ExposureTime no + ShutterSpeedValue + BulbDuration + SubSecCreateDate EXIF:CreateDate yes + SubSecTimeDigitized + OffsetTimeDigitized + SubSecDateTimeOriginal EXIF:DateTimeOriginal yes + SubSecTimeOriginal + OffsetTimeOriginal + SubSecModifyDate EXIF:ModifyDate yes + SubSecTime + OffsetTime + ThumbnailImage ThumbnailOffset yes + ThumbnailLength + ThumbnailTIFF SubfileType no + Compression + ImageWidth + ImageHeight + BitsPerSample + PhotometricInterpretation + StripOffsets + SamplesPerPixel + RowsPerStrip + StripByteCounts + PlanarConfiguration + Orientation + VolumeSize ISO:VolumeBlockCount no + ISO:VolumeBlockSize + WB_RGBLevels KDC_IFD:WhiteBalance no + WB_RGBLevelsAuto + WB_RGBLevelsFluorescent + WB_RGBLevelsTungsten + WB_RGBLevelsDaylight + WB_RGBLevels4 + WB_RGBLevels5 + WB_RGBLevelsShade + WB_RGBLevels KodakIFD:WhiteBalance no + WB_RGBMul0 + WB_RGBMul1 + WB_RGBMul2 + WB_RGBMul3 + WB_RGBCoeffs0 + WB_RGBCoeffs1 + WB_RGBCoeffs2 + WB_RGBCoeffs3 + KodakIFD:ColorTemperature + Kodak:WB_RGBLevels + WB_RGGBLevels Canon:WhiteBalance no + WB_RGGBLevelsAsShot + WB_RGGBLevelsAuto + WB_RGGBLevelsDaylight + WB_RGGBLevelsCloudy + WB_RGGBLevelsTungsten + WB_RGGBLevelsFluorescent + WB_RGGBLevelsFlash + WB_RGGBLevelsCustom + WB_RGGBLevelsShade + WB_RGGBLevelsKelvin + WB_RGGBLevels WB_RGGBLevelsUncorrected no + WB_RGGBLevelsBlack + ZoomedPreviewImage ZoomedPreviewStart no + ZoomedPreviewLength + +=head2 Shortcuts Tags + +Shortcut tags are convenience tags that represent one or more other tag +names. They are used like regular tags to read and write the information +for a specified set of tags. + +The shortcut tags below have been pre-defined, but user-defined shortcuts +may be added via the %Image::ExifTool::UserDefined::Shortcuts lookup in the +=/.ExifTool_config file. See the Image::ExifTool::Shortcuts documentation +for more details. + + Tag Name Refers To Writable + -------- --------- -------- + AllDates DateTimeOriginal yes + CreateDate + ModifyDate + Canon FileName yes + Model + DateTimeOriginal + ShootingMode + ShutterSpeed + Aperture + MeteringMode + ExposureCompensation + ISO + Lens + FocalLength + ImageSize + Quality + Flash + FlashType + ConditionalFEC + RedEyeReduction + ShutterCurtainHack + WhiteBalance + FocusMode + Contrast + Sharpness + Saturation + ColorTone + ColorSpace + LongExposureNoiseReduction + FileSize + FileNumber + DriveMode + OwnerName + SerialNumber + ColorSpaceTags ExifIFD:ColorSpace yes + ExifIFD:Gamma + InteropIFD:InteropIndex + ICC_Profile + Common FileName yes + FileSize + Model + DateTimeOriginal + ImageSize + Quality + FocalLength + ShutterSpeed + Aperture + ISO + WhiteBalance + Flash + CommonIFD0 IFD0:ImageDescription yes + IFD0:Make + IFD0:Model + IFD0:Software + IFD0:ModifyDate + IFD0:Artist + IFD0:Copyright + IFD0:Rating + IFD0:RatingPercent + IFD0:DNGLensInfo + IFD0:PanasonicTitle + IFD0:PanasonicTitle2 + IFD0:XPTitle + IFD0:XPComment + IFD0:XPAuthor + IFD0:XPKeywords + IFD0:XPSubject + LargeTags CanonVRD yes + DLOData + EXIF + ICC_Profile + IDCPreviewImage + ImageData + IPTC + JpgFromRaw + OriginalRawImage + OtherImage + PreviewImage + ThumbnailImage + TIFFPreview + XML + XMP + ZoomedPreviewImage + MakerNotes MakerNotes yes + MakerNoteApple + MakerNoteCanon + MakerNoteCasio + MakerNoteCasio2 + MakerNoteDJI + MakerNoteFLIR + MakerNoteFujiFilm + MakerNoteGE + MakerNoteGE2 + MakerNoteHasselblad + MakerNoteHP + MakerNoteHP2 + MakerNoteHP4 + MakerNoteHP6 + MakerNoteISL + MakerNoteJVC + MakerNoteJVCText + MakerNoteKodak1a + MakerNoteKodak1b + MakerNoteKodak2 + MakerNoteKodak3 + MakerNoteKodak4 + MakerNoteKodak5 + MakerNoteKodak6a + MakerNoteKodak6b + MakerNoteKodak7 + MakerNoteKodak8a + MakerNoteKodak8b + MakerNoteKodak8c + MakerNoteKodak9 + MakerNoteKodak10 + MakerNoteKodak11 + MakerNoteKodak12 + MakerNoteKodakUnknown + MakerNoteKyocera + MakerNoteMinolta + MakerNoteMinolta2 + MakerNoteMinolta3 + MakerNoteMotorola + MakerNoteNikon + MakerNoteNikon2 + MakerNoteNikon3 + MakerNoteNintendo + MakerNoteOlympus + MakerNoteOlympus2 + MakerNoteLeica + MakerNoteLeica2 + MakerNoteLeica3 + MakerNoteLeica4 + MakerNoteLeica5 + MakerNoteLeica6 + MakerNoteLeica7 + MakerNoteLeica8 + MakerNoteLeica9 + MakerNoteLeica10 + MakerNotePanasonic + MakerNotePanasonic2 + MakerNotePanasonic3 + MakerNotePentax + MakerNotePentax2 + MakerNotePentax3 + MakerNotePentax4 + MakerNotePentax5 + MakerNotePentax6 + MakerNotePhaseOne + MakerNoteReconyx + MakerNoteReconyx2 + MakerNoteReconyx3 + MakerNoteRicoh + MakerNoteRicoh2 + MakerNoteRicohPentax + MakerNoteRicohText + MakerNoteSamsung1a + MakerNoteSamsung1b + MakerNoteSamsung2 + MakerNoteSanyo + MakerNoteSanyoC4 + MakerNoteSanyoPatch + MakerNoteSigma + MakerNoteSony + MakerNoteSony2 + MakerNoteSony3 + MakerNoteSony4 + MakerNoteSony5 + MakerNoteSonyEricsson + MakerNoteSonySRF + MakerNoteUnknownText + MakerNoteUnknownBinary + MakerNoteUnknown + Nikon Model yes + SubSecDateTimeOriginal + ShutterCount + LensSpec + FocalLength + ImageSize + ShutterSpeed + Aperture + ISO + NoiseReduction + ExposureProgram + ExposureCompensation + WhiteBalance + WhiteBalanceFineTune + ShootingMode + Quality + MeteringMode + FocusMode + ImageOptimization + ToneComp + ColorHue + ColorSpace + HueAdjustment + Saturation + Sharpness + Flash + FlashMode + FlashExposureComp + Unsafe IFD0:YCbCrPositioning yes + IFD0:YCbCrCoefficients + IFD0:TransferFunction + ExifIFD:ComponentsConfiguration + ExifIFD:CompressedBitsPerPixel + InteropIFD:InteropIndex + InteropIFD:InteropVersion + InteropIFD:RelatedImageWidth + InteropIFD:RelatedImageHeight + +=head2 MWG Tags + +The Metadata Working Group (MWG) recommends techniques to allow certain +overlapping EXIF, IPTC and XMP tags to be reconciled when reading, and +synchronized when writing. The MWG Composite tags below are designed to aid +in the implementation of these recommendations. As well, the MWG defines +new XMP tags which are listed in the subsequent tables below. See +L<http://www.metadataworkinggroup.org/> for the official MWG specification. + +=head3 MWG Composite Tags + +The table below lists special Composite tags which are used to access other +tags based on the MWG 2.0 recommendations. These tags are only accessible +when explicitly loaded, but this is done automatically by the exiftool +application if MWG is specified as a group for any tag on the command line, +or manually with the C<-use MWG> option. Via the API, the MWG Composite +tags are loaded by calling "C<Image::ExifTool::MWG::Load()>". + +When reading, the value of each MWG tag is B<Derived From> the specified +tags based on the MWG guidelines. When writing, the appropriate associated +tags are written. The value of the IPTCDigest tag is updated automatically +when the IPTC is changed if either the IPTCDigest tag didn't exist +beforehand or its value agreed with the original IPTC digest (indicating +that the XMP is synchronized with the IPTC). IPTC information is written +only if the original file contained IPTC. + +Loading the MWG module activates "strict MWG conformance mode", which has +the effect of causing EXIF, IPTC and XMP in non-standard locations to be +ignored when reading, as per the MWG recommendations. Instead, a "Warning" +tag is generated when non-standard metadata is encountered. This feature +may be disabled by setting C<$Image::ExifTool::MWG::strict = 0> in the +ExifTool config file (or from your Perl script when using the API). Note +that the behaviour when writing is not changed: ExifTool always creates new +records only in the standard location, but writes new tags to any +EXIF/IPTC/XMP records that exist. + +Contrary to the EXIF specification, the MWG recommends that EXIF "ASCII" +string values be stored as UTF-8. To honour this, the exiftool application +sets the default internal EXIF string encoding to "UTF8" when the MWG module +is loaded, but via the API this must be done manually by setting the +CharsetEXIF option. + +A complication of the MWG specification is that although the MWG:Creator +property may consist of multiple values, the associated EXIF tag +(EXIF:Artist) is only a simple string. To resolve this discrepancy the MWG +recommends a technique which allows a list of values to be stored in a +string by using a semicolon-space separator (with quotes around values if +necessary). When the MWG module is loaded, ExifTool automatically +implements this policy and changes EXIF:Artist to a list-type tag. + + Tag Name Derived From Writable + -------- ------------ -------- + City IPTC:City yes + XMP-photoshop:City + XMP-iptcExt:LocationShownCity + CurrentIPTCDigest + IPTCDigest + Copyright EXIF:Copyright yes + IPTC:CopyrightNotice + XMP-dc:Rights + CurrentIPTCDigest + IPTCDigest + Country IPTC:Country-PrimaryLocationName yes + XMP-photoshop:Country + XMP-iptcExt:LocationShownCountryName + CurrentIPTCDigest + IPTCDigest + CreateDate Composite:SubSecCreateDate yes + EXIF:CreateDate + IPTC:DigitalCreationDate + IPTC:DigitalCreationTime + XMP-xmp:CreateDate + CurrentIPTCDigest + IPTCDigest + Creator EXIF:Artist yes+ + IPTC:By-line + XMP-dc:Creator + CurrentIPTCDigest + IPTCDigest + DateTimeOriginal Composite:SubSecDateTimeOriginal yes + EXIF:DateTimeOriginal + IPTC:DateCreated + IPTC:TimeCreated + XMP-photoshop:DateCreated + CurrentIPTCDigest + IPTCDigest + Description EXIF:ImageDescription yes + IPTC:Caption-Abstract + XMP-dc:Description + CurrentIPTCDigest + IPTCDigest + Keywords IPTC:Keywords yes+ + XMP-dc:Subject + CurrentIPTCDigest + IPTCDigest + Location IPTC:Sub-location yes + XMP-iptcCore:Location + XMP-iptcExt:LocationShownSublocation + CurrentIPTCDigest + IPTCDigest + ModifyDate Composite:SubSecModifyDate yes + EXIF:ModifyDate + XMP-xmp:ModifyDate + CurrentIPTCDigest + IPTCDigest + Orientation EXIF:Orientation yes + Rating XMP-xmp:Rating yes + State IPTC:Province-State yes + XMP-photoshop:State + XMP-iptcExt:LocationShownProvinceState + CurrentIPTCDigest + IPTCDigest + +=head3 MWG Regions Tags + +Image region metadata defined by the MWG 2.0 specification. These tags +may be accessed without the need to load the MWG Composite tags above. See +L<http://www.metadataworkinggroup.org/> for the official specification. + +These tags belong to the ExifTool XMP-mwg-rs family 1 group. + + Tag Name Writable + -------- -------- + RegionInfo MWG RegionInfo Struct + RegionAppliedToDimensions Dimensions Struct_ + RegionAppliedToDimensionsH real_ + RegionAppliedToDimensionsUnit string_ + RegionAppliedToDimensionsW real_ + RegionList MWG RegionStruct Struct_+ + RegionArea Area Struct_+ + RegionAreaD real_+ + RegionAreaH real_+ + RegionAreaUnit string_+ + RegionAreaW real_+ + RegionAreaX real_+ + RegionAreaY real_+ + RegionBarCodeValue string_+ + RegionDescription string_+ + RegionExtensions MWG Extensions Struct_+ + RegionFocusUsage string_+ + RegionName string_+ + RegionRotation real_+ + RegionSeeAlso string_+ + RegionType string_+ + +=head3 MWG RegionInfo Struct + + Field Name Writable + ---------- -------- + AppliedToDimensions Dimensions Struct + RegionList MWG RegionStruct Struct+ + +=head3 MWG RegionStruct Struct + + Field Name Writable + ---------- -------- + Area Area Struct + BarCodeValue string + Description string + Extensions MWG Extensions Struct + FocusUsage string + Name string + Rotation real + Type string + SeeAlso string + +=head3 MWG Extensions Struct + +This structure may contain any top-level XMP tags, but none have been +pre-defined in ExifTool. Since no flattened tags have been pre-defined, +RegionExtensions is writable only as a structure (eg. +C<{xmp-dc:creator=me,rating=5}>). Fields for this structure are identified +using the standard ExifTool tag name (with optional leading group name, +and/or trailing language code, and/or trailing C<#> symbol to disable print +conversion). + + Field Name Writable + ---------- -------- + [no tags known] + +=head3 MWG Keywords Tags + +Hierarchical keywords metadata defined by the MWG 2.0 specification. +ExifTool unrolls keyword structures to an arbitrary depth of 6 to allow +individual levels to be accessed with different tag names, and to avoid +infinite recursion. See L<http://www.metadataworkinggroup.org/> for the +official specification. + +These tags belong to the ExifTool XMP-mwg-kw family 1 group. + + Tag Name Writable + -------- -------- + KeywordInfo MWG KeywordInfo Struct + HierarchicalKeywords MWG KeywordStruct Struct_+ + HierarchicalKeywords1Applied boolean_+ + HierarchicalKeywords1Children MWG KeywordStruct Struct_+ + HierarchicalKeywords2Applied boolean_+ + HierarchicalKeywords2Children MWG KeywordStruct Struct_+ + HierarchicalKeywords3Applied boolean_+ + HierarchicalKeywords3Children MWG KeywordStruct Struct_+ + HierarchicalKeywords4Applied boolean_+ + HierarchicalKeywords4Children MWG KeywordStruct Struct_+ + HierarchicalKeywords5Applied boolean_+ + HierarchicalKeywords5Children MWG KeywordStruct Struct_+ + HierarchicalKeywords6Applied boolean_+ + HierarchicalKeywords6 string_+ + HierarchicalKeywords5 string_+ + HierarchicalKeywords4 string_+ + HierarchicalKeywords3 string_+ + HierarchicalKeywords2 string_+ + HierarchicalKeywords1 string_+ + +=head3 MWG KeywordInfo Struct + + Field Name Writable + ---------- -------- + Hierarchy MWG KeywordStruct Struct+ + +=head3 MWG KeywordStruct Struct + + Field Name Writable + ---------- -------- + Applied boolean + Children MWG KeywordStruct Struct+ + Keyword string + +=head3 MWG Collections Tags + +Collections metadata defined by the MWG 2.0 specification. See +L<http://www.metadataworkinggroup.org/> for the official specification. + +These tags belong to the ExifTool XMP-mwg-coll family 1 group. + + Tag Name Writable + -------- -------- + Collections MWG CollectionInfo Struct+ + CollectionName string_+ + CollectionURI string_+ + +=head3 MWG CollectionInfo Struct + + Field Name Writable + ---------- -------- + CollectionName string + CollectionURI string + +=head1 NOTES + +This document generated automatically by +L<Image::ExifTool::BuildTagLookup|Image::ExifTool::BuildTagLookup>. + +=head1 AUTHOR + +Copyright 2003-2019, Phil Harvey (phil at owl.phy.queensu.ca) + +This library is free software; you can redistribute it and/or modify it +under the same terms as Perl itself. + +=head1 SEE ALSO + +L<Image::ExifTool(3pm)|Image::ExifTool> + +=cut diff --git a/lib/Image/ExifTool/Theora.pm b/lib/Image/ExifTool/Theora.pm new file mode 100644 index 0000000..4026179 --- /dev/null +++ b/lib/Image/ExifTool/Theora.pm @@ -0,0 +1,145 @@ +#------------------------------------------------------------------------------ +# File: Theora.pm +# +# Description: Read Theora video meta information +# +# Revisions: 2011/07/13 - P. Harvey Created +# +# References: 1) http://www.theora.org/doc/Theora.pdf +#------------------------------------------------------------------------------ + +package Image::ExifTool::Theora; + +use strict; +use vars qw($VERSION); +use Image::ExifTool qw(:DataAccess :Utils); + +$VERSION = '1.00'; + +# Theora header types +%Image::ExifTool::Theora::Main = ( + NOTES => q{ + Information extracted from Ogg Theora video files. See + L<http://www.theora.org/doc/Theora.pdf> for the Theora specification. + }, + 0x80 => { + Name => 'Identification', + SubDirectory => { + TagTable => 'Image::ExifTool::Theora::Identification', + ByteOrder => 'BigEndian', + }, + }, + 0x81 => { + Name => 'Comments', + SubDirectory => { + TagTable => 'Image::ExifTool::Vorbis::Comments', + }, + }, + # 0x82 - Setup +); + +# tags extracted from Theora Idenfication header +%Image::ExifTool::Theora::Identification = ( + PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData, + GROUPS => { 2 => 'Video' }, + NOTES => 'Tags extracted from the Theora identification header.', + 0 => { + Name => 'TheoraVersion', + Format => 'int8u[3]', + PrintConv => '$val =~ tr/ /./; $val', + }, + 7 => { + Name => 'ImageWidth', + Format => 'int32u', + ValueConv => '$val >> 8', + }, + 10 => { + Name => 'ImageHeight', + Format => 'int32u', + ValueConv => '$val >> 8', + }, + 13 => 'XOffset', + 14 => 'YOffset', + 15 => { + Name => 'FrameRate', + Format => 'rational64u', + PrintConv => 'int($val * 1000 + 0.5) / 1000', + }, + 23 => { + Name => 'PixelAspectRatio', + Format => 'int16u[3]', + ValueConv => 'my @a=split(" ",$val); (($a[0]<<8)+($a[1]>>8)) / ((($a[1]&0xff)<<8)+$a[2])', + PrintConv => 'int($val * 1000 + 0.5) / 1000', + }, + 29 => { + Name => 'ColorSpace', + PrintConv => { + 0 => 'Undefined', + 1 => 'Rec. 470M', + 2 => 'Rec. 470BG', + }, + }, + 30 => { + Name => 'NominalVideoBitrate', + Format => 'int32u', + ValueConv => '$val >> 8', + PrintConv => { + 0 => 'Unspecified', + OTHER => \&Image::ExifTool::ConvertBitrate, + }, + }, + 33 => { + Name => 'Quality', + ValueConv => '$val >> 2', + }, + 34 => { + Name => 'PixelFormat', + ValueConv => '($val >> 3) & 0x3', + PrintConv => { + 0 => '4:2:0', + 2 => '4:2:2', + 3 => '4:4:4', + }, + }, +); + +1; # end + +__END__ + +=head1 NAME + +Image::ExifTool::Theora - Read Theora video meta information + +=head1 SYNOPSIS + +This module is used by Image::ExifTool + +=head1 DESCRIPTION + +This module contains definitions required by Image::ExifTool to extract meta +information from Theora video streams. + +=head1 AUTHOR + +Copyright 2003-2019, Phil Harvey (phil at owl.phy.queensu.ca) + +This library is free software; you can redistribute it and/or modify it +under the same terms as Perl itself. + +=head1 REFERENCES + +=over 4 + +=item L<http://www.theora.org/doc/Theora.pdf> + +=back + +=head1 SEE ALSO + +L<Image::ExifTool::TagNames/Theora Tags>, +L<Image::ExifTool::TagNames/Ogg Tags>, +L<Image::ExifTool(3pm)|Image::ExifTool> + +=cut + diff --git a/lib/Image/ExifTool/Torrent.pm b/lib/Image/ExifTool/Torrent.pm new file mode 100644 index 0000000..f2eb67e --- /dev/null +++ b/lib/Image/ExifTool/Torrent.pm @@ -0,0 +1,317 @@ +#------------------------------------------------------------------------------ +# File: Torrent.pm +# +# Description: Read information from BitTorrent file +# +# Revisions: 2013/08/27 - P. Harvey Created +# +# References: 1) https://wiki.theory.org/BitTorrentSpecification +#------------------------------------------------------------------------------ + +package Image::ExifTool::Torrent; + +use strict; +use vars qw($VERSION); +use Image::ExifTool qw(:DataAccess :Utils); + +$VERSION = '1.03'; + +sub ReadBencode($$); +sub ExtractTags($$$;$$@); + +# tags extracted from BitTorrent files +%Image::ExifTool::Torrent::Main = ( + GROUPS => { 2 => 'Document' }, + NOTES => q{ + Below are tags commonly found in BitTorrent files. As well as these tags, + any other existing tags will be extracted. For convenience, list items are + expanded into individual tags with an index in the tag name, but only the + tags with index "1" are listed in the tables below. See + L<https://wiki.theory.org/BitTorrentSpecification> for the BitTorrent + specification. + }, + 'announce' => { }, + 'announce-list' => { Name => 'AnnounceList1' }, + 'comment' => { }, + 'created by' => { Name => 'Creator' }, # software used to create the torrent + 'creation date' => { + Name => 'CreateDate', + Groups => { 2 => 'Time' }, + ValueConv => 'ConvertUnixTime($val,1)', + PrintConv => '$self->ConvertDateTime($val)', + }, + 'encoding' => { }, + 'info' => { SubDirectory => { TagTable => 'Image::ExifTool::Torrent::Info' } }, + 'url-list' => { Name => 'URLList1' }, +); + +%Image::ExifTool::Torrent::Info = ( + GROUPS => { 2 => 'Document' }, + 'file-duration' => { Name => 'File1Duration' }, + 'file-media' => { Name => 'File1Media' }, + 'files' => { SubDirectory => { TagTable => 'Image::ExifTool::Torrent::Files' } }, + 'length' => { }, + 'md5sum' => { Name => 'MD5Sum' }, + 'name' => { }, + 'name.utf-8' => { Name => 'NameUTF-8' }, + 'piece length' => { Name => 'PieceLength' }, + 'pieces' => { + Name => 'Pieces', + Notes => 'concatenation of 20-byte SHA-1 digests for each piece', + }, + 'private' => { }, + 'profiles' => { SubDirectory => { TagTable => 'Image::ExifTool::Torrent::Profiles' } }, +); + +%Image::ExifTool::Torrent::Profiles = ( + GROUPS => { 2 => 'Document' }, + 'width' => { Name => 'Profile1Width' }, + 'height' => { Name => 'Profile1Height' }, + 'acodec' => { Name => 'Profile1AudioCodec' }, + 'vcodec' => { Name => 'Profile1VideoCodec' }, +); + +%Image::ExifTool::Torrent::Files = ( + GROUPS => { 2 => 'Document' }, + 'length' => { Name => 'File1Length', PrintConv => 'ConvertFileSize($val)' }, + 'md5sum' => { Name => 'File1MD5Sum' }, + 'path' => { Name => 'File1Path', JoinPath => 1 }, + 'path.utf-8' => { Name => 'File1PathUTF-8', JoinPath => 1 }, +); + +#------------------------------------------------------------------------------ +# Read 64kB more data into buffer +# Inputs: 0) RAF ref, 1) buffer ref +# Returns: number of bytes read +# Notes: Sets BencodeEOF element of RAF on end of file +sub ReadMore($$) +{ + my ($raf, $dataPt) = @_; + my $buf2; + my $n = $raf->Read($buf2, 65536); + $$raf{BencodeEOF} = 1 if $n != 65536; + $$dataPt = substr($$dataPt, pos($$dataPt)) . $buf2 if $n; + return $n; +} + +#------------------------------------------------------------------------------ +# Read bencoded value +# Inputs: 0) input file, 1) buffer (pos must be set to current position) +# Returns: HASH ref, ARRAY ref, SCALAR ref, SCALAR, or undef on error or end of data +# Notes: Sets BencodeError element of RAF on any error +sub ReadBencode($$) +{ + my ($raf, $dataPt) = @_; + + # read more if necessary (keep a minimum of 64 bytes in the buffer) + my $pos = pos($$dataPt); + return undef unless defined $pos; + my $remaining = length($$dataPt) - $pos; + ReadMore($raf, $dataPt) if $remaining < 64 and not $$raf{BencodeEOF}; + + # read next token + $$dataPt =~ /(.)/sg or return undef; + + my $val; + my $tok = $1; + if ($tok eq 'i') { # integer + $$dataPt =~ /\G(-?\d+)e/g or return $val; + $val = $1; + } elsif ($tok eq 'd') { # dictionary + $val = { }; + for (;;) { + my $k = ReadBencode($raf, $dataPt); + last unless defined $k; + # the key must be a byte string + if (ref $k) { + ref $k ne 'SCALAR' and $$raf{BencodeError} = 'Bad dictionary key', last; + $k = $$k; + } + my $v = ReadBencode($raf, $dataPt); + last unless defined $v; + $$val{$k} = $v; + } + } elsif ($tok eq 'l') { # list + $val = [ ]; + for (;;) { + my $v = ReadBencode($raf, $dataPt); + last unless defined $v; + push @$val, $v; + } + } elsif ($tok eq 'e') { # end of dictionary or list + # return undef (no error) + } elsif ($tok =~ /^\d$/ and $$dataPt =~ /\G(\d*):/g) { # byte string + my $len = $tok . $1; + my $more = $len - (length($$dataPt) - pos($$dataPt)); + my $value; + if ($more <= 0) { + $value = substr($$dataPt,pos($$dataPt),$len); + pos($$dataPt) = pos($$dataPt) + $len; + } elsif ($more > 10000000) { + # just skip over really long values + $val = \ "(Binary data $len bytes)" if $raf->Seek($more, 1); + } else { + # need to read more from file + my $buff; + my $n = $raf->Read($buff, $more); + if ($n == $more) { + $value = substr($$dataPt,pos($$dataPt)) . $buff; + $$dataPt = ''; + pos($$dataPt) = 0; + } + } + if (defined $value) { + # return as binary data unless it is a reasonable-length ASCII string + if (length($value) > 256 or $value =~ /[^\t\x20-\x7e]/) { + $val = \$value; + } else { + $val = $value; + } + } elsif (not defined $val) { + $$raf{BencodeError} = 'Truncated byte string'; + } + } else { + $$raf{BencodeError} = 'Bad format'; + } + return $val; +} + +#------------------------------------------------------------------------------ +# Extract tags from dictionary hash +# Inputs: 0) ExifTool ref, 1) dictionary hash reference, 2) tag table ref, +# 3) parent hash ID, 4) parent hash name, 5-N) list indices +# Returns: number of tags extracted +sub ExtractTags($$$;$$@) +{ + my ($et, $hashPtr, $tagTablePtr, $baseID, $baseName, @index) = @_; + my $count = 0; + my $tag; + foreach $tag (sort keys %$hashPtr) { + my $val = $$hashPtr{$tag}; + my ($i, $j, @more); + for (; defined $val; $val = shift @more) { + my $id = defined $baseID ? "$baseID/$tag" : $tag; + unless ($$tagTablePtr{$id}) { + my $name = ucfirst $tag; + # capitalize all words in tag name and remove illegal characters + $name =~ s/[^-_a-zA-Z0-9]+(.?)/\U$1/g; + $name = "Tag$name" if length($name) < 2 or $name !~ /^[A-Z]/; + $name = $baseName . $name if defined $baseName; # add base name if necessary + AddTagToTable($tagTablePtr, $id, { Name => $name }); + $et->VPrint(0, " [adding $id '${name}']\n"); + } + my $tagInfo = $et->GetTagInfo($tagTablePtr, $id) or next; + if (ref $val eq 'ARRAY') { + if ($$tagInfo{JoinPath}) { + $val = join '/', @$val; + } else { + push @more, @$val; + next if ref $more[0] eq 'ARRAY'; # continue expanding nested lists + $val = shift @more; + $i or $i = 0, push(@index, $i); + } + } + $index[-1] = ++$i if defined $i; + if (@index) { + $id .= join '_', @index; # add instance number(s) to tag ID + unless ($$tagTablePtr{$id}) { + my $name = $$tagInfo{Name}; + # embed indices at position of '1' in tag name + my $n = ($name =~ tr/1/#/); + for ($j=0; $j<$n; ++$j) { + my $idx = $index[$j] || ''; + $name =~ s/#/$idx/; + } + # put remaining indices at end of tag name + for (; $j<@index; ++$j) { + $name .= '_' if $name =~ /\d$/; + $name .= $index[$j]; + } + AddTagToTable($tagTablePtr, $id, { %$tagInfo, Name => $name }); + } + $tagInfo = $et->GetTagInfo($tagTablePtr, $id) or next; + } + if (ref $val eq 'HASH') { + # extract tags from this dictionary + my ($table, $rootID, $rootName); + if ($$tagInfo{SubDirectory}) { + $table = GetTagTable($$tagInfo{SubDirectory}{TagTable}); + } else { + $table = $tagTablePtr; + # use hash ID and Name as base for contained tags to avoid conflicts + $rootID = $id; + $rootName = $$tagInfo{Name}; + } + $count += ExtractTags($et, $val, $table, $rootID, $rootName, @index); + } else { + # handle this simple tag value + $et->HandleTag($tagTablePtr, $id, $val); + ++$count; + } + } + pop @index if defined $i; + } + return $count; +} + +#------------------------------------------------------------------------------ +# Process BitTorrent file +# Inputs: 0) ExifTool object reference, 1) dirInfo reference (with RAF set) +# Returns: 1 on success, 0 if this wasn't a valid BitTorrent file +sub ProcessTorrent($$) +{ + my ($et, $dirInfo) = @_; + my $success = 0; + my $raf = $$dirInfo{RAF}; + my $buff = ''; + pos($buff) = 0; + my $dict = ReadBencode($raf, \$buff); + my $err = $$raf{BencodeError}; + $et->Warn("Bencode error: $err") if $err; + if (ref $dict eq 'HASH' and $$dict{announce}) { + $et->SetFileType(); + my $tagTablePtr = GetTagTable('Image::ExifTool::Torrent::Main'); + ExtractTags($et, $dict, $tagTablePtr) and $success = 1; + } + return $success; +} + +1; # end + +__END__ + +=head1 NAME + +Image::ExifTool::Torrent - Read information from BitTorrent file + +=head1 SYNOPSIS + +This module is used by Image::ExifTool + +=head1 DESCRIPTION + +This module contains definitions required by Image::ExifTool to read +bencoded information from BitTorrent files. + +=head1 AUTHOR + +Copyright 2003-2019, Phil Harvey (phil at owl.phy.queensu.ca) + +This library is free software; you can redistribute it and/or modify it +under the same terms as Perl itself. + +=head1 REFERENCES + +=over 4 + +=item L<https://wiki.theory.org/BitTorrentSpecification> + +=back + +=head1 SEE ALSO + +L<Image::ExifTool::TagNames/Torrent Tags>, +L<Image::ExifTool(3pm)|Image::ExifTool> + +=cut + diff --git a/lib/Image/ExifTool/Unknown.pm b/lib/Image/ExifTool/Unknown.pm new file mode 100644 index 0000000..5621b54 --- /dev/null +++ b/lib/Image/ExifTool/Unknown.pm @@ -0,0 +1,66 @@ +#------------------------------------------------------------------------------ +# File: Unknown.pm +# +# Description: Unknown EXIF maker notes tags +# +# Revisions: 04/07/2004 - P. Harvey Created +#------------------------------------------------------------------------------ + +package Image::ExifTool::Unknown; + +use strict; +use vars qw($VERSION); +use Image::ExifTool::Exif; + +$VERSION = '1.13'; + +# Unknown maker notes +%Image::ExifTool::Unknown::Main = ( + WRITE_PROC => \&Image::ExifTool::Exif::WriteExif, + CHECK_PROC => \&Image::ExifTool::Exif::CheckExif, + GROUPS => { 0 => 'MakerNotes', 1 => 'MakerUnknown', 2 => 'Camera' }, + + # this seems to be a common fixture, so look for it in unknown maker notes + 0x0e00 => { + Name => 'PrintIM', + Description => 'Print Image Matching', + SubDirectory => { + TagTable => 'Image::ExifTool::PrintIM::Main', + }, + }, +); + + +1; # end + +__END__ + +=head1 NAME + +Image::ExifTool::Unknown - Unknown EXIF maker notes tags + +=head1 SYNOPSIS + +This module is loaded automatically by Image::ExifTool when required. + +=head1 DESCRIPTION + +Image::ExifTool has definitions for the maker notes from many manufacturers, +however information can sometimes be extracted from unknown manufacturers if +the maker notes are in standard IFD format. This module contains the +definitions necessary for Image::ExifTool to read the maker notes from +unknown manufacturers. + +=head1 AUTHOR + +Copyright 2003-2019, Phil Harvey (phil at owl.phy.queensu.ca) + +This library is free software; you can redistribute it and/or modify it +under the same terms as Perl itself. + +=head1 SEE ALSO + +L<Image::ExifTool::TagNames/Unknown Tags>, +L<Image::ExifTool(3pm)|Image::ExifTool> + +=cut diff --git a/lib/Image/ExifTool/VCard.pm b/lib/Image/ExifTool/VCard.pm new file mode 100644 index 0000000..e63f836 --- /dev/null +++ b/lib/Image/ExifTool/VCard.pm @@ -0,0 +1,443 @@ +#------------------------------------------------------------------------------ +# File: VCard.pm +# +# Description: Read vCard and iCalendar meta information +# +# Revisions: 2015/04/05 - P. Harvey Created +# 2015/05/02 - PH Added iCalendar support +# +# References: 1) http://en.m.wikipedia.org/wiki/VCard +# 2) http://tools.ietf.org/html/rfc6350 +# 3) http://tools.ietf.org/html/rfc5545 +#------------------------------------------------------------------------------ + +package Image::ExifTool::VCard; + +use strict; +use vars qw($VERSION); +use Image::ExifTool qw(:DataAccess :Utils); + +$VERSION = '1.06'; + +my %unescapeVCard = ( '\\'=>'\\', ','=>',', 'n'=>"\n", 'N'=>"\n" ); + +# lookup for iCalendar components (used to generate family 1 group names if top level) +my %isComponent = ( Event=>1, Todo=>1, Journal=>1, Freebusy=>1, Timezone=>1, Alarm=>1 ); + +my %timeInfo = ( + # convert common date/time formats to EXIF style + ValueConv => q{ + $val =~ s/(\d{4})(\d{2})(\d{2})T(\d{2})(\d{2})(\d{2})(Z?)/$1:$2:$3 $4:$5:$6$7/g; + $val =~ s/(\d{4})(\d{2})(\d{2})/$1:$2:$3/g; + $val =~ s/(\d{4})-(\d{2})-(\d{2})/$1:$2:$3/g; + return $val; + }, + PrintConv => '$self->ConvertDateTime($val)', +); + +# vCard tags (ref 1/2/PH) +# Note: The case of all tag ID's is normalized to lowercase with uppercase first letter +%Image::ExifTool::VCard::Main = ( + GROUPS => { 2 => 'Document' }, + VARS => { NO_LOOKUP => 1 }, # omit tags from lookup + NOTES => q{ + This table lists common vCard tags, but ExifTool will also extract any other + vCard tags found. Tag names may have "Pref" added to indicate the preferred + instance of a vCard property, and other "TYPE" parameters may also added to + the tag name. VCF files may contain multiple vCard entries which are + distinguished by the ExifTool family 3 group name (document number). See + L<http://tools.ietf.org/html/rfc6350> for the vCard 4.0 specification. + }, + Version => { Name => 'VCardVersion', Description => 'VCard Version' }, + Fn => { Name => 'FormattedName', Groups => { 2 => 'Author' } }, + N => { Name => 'Name', Groups => { 2 => 'Author' } }, + Bday => { Name => 'Birthday', Groups => { 2 => 'Time' }, %timeInfo }, + Tz => { Name => 'TimeZone', Groups => { 2 => 'Time' } }, + Adr => { Name => 'Address', Groups => { 2 => 'Location' } }, + Geo => { + Name => 'Geolocation', + Groups => { 2 => 'Location' }, + # when used as a parameter, VCard 4.0 adds a "geo:" prefix that we need to remove + ValueConv => '$val =~ s/^geo://; $val', + }, + Anniversary => { }, + Email => { }, + Gender => { }, + Impp => 'IMPP', + Lang => 'Language', + Logo => { }, + Nickname => { }, + Note => { }, + Org => 'Organization', + Photo => { Groups => { 2 => 'Preview' } }, + Prodid => 'Software', + Rev => 'Revision', + Sound => { }, + Tel => 'Telephone', + Title => 'JobTitle', + Uid => 'UID', + Url => 'URL', + 'X-ablabel' => { Name => 'ABLabel', PrintConv => '$val =~ s/^_\$!<(.*)>!\$_$/$1/; $val' }, + 'X-abdate' => { Name => 'ABDate', Groups => { 2 => 'Time' }, %timeInfo }, + 'X-aim' => 'AIM', + 'X-icq' => 'ICQ', + 'X-abuid' => 'AB_UID', + 'X-abrelatednames' => 'ABRelatedNames', + 'X-socialprofile' => 'SocialProfile', +); + +%Image::ExifTool::VCard::VCalendar = ( + GROUPS => { 1 => 'VCalendar', 2 => 'Document' }, + VARS => { + NO_LOOKUP => 1, # omit tags from lookup + LONG_TAGS => 6, # some X-microsoft tags have unavoidably long ID's + }, + NOTES => q{ + The VCard module is also used to process iCalendar ICS files since they use + a format similar to vCard. The following table lists standard iCalendar + tags, but any existing tags will be extracted. Top-level iCalendar + components (eg. Event, Todo, Timezone, etc.) are used for the family 1 group + names, and embedded components (eg. Alarm) are added as a prefix to the tag + name. See L<http://tools.ietf.org/html/rfc5545> for the official iCalendar + 2.0 specification. + }, + Version => { Name => 'VCalendarVersion', Description => 'VCalendar Version' }, + Calscale => 'CalendarScale', + Method => { }, + Prodid => 'Software', + Attach => 'Attachment', + Categories => { }, + Class => 'Classification', + Comment => { }, + Description => { }, + Geo => { + Name => 'Geolocation', + Groups => { 2 => 'Location' }, + ValueConv => '$val =~ s/^geo://; $val', + }, + Location => { Name => 'Location', Groups => { 2 => 'Location' } }, + 'Percent-complete' => 'PercentComplete', + Priority => { }, + Resources => { }, + Status => { }, + Summary => { }, + Completed => { Name => 'DateTimeCompleted', Groups => { 2 => 'Time' }, %timeInfo }, + Dtend => { Name => 'DateTimeEnd', Groups => { 2 => 'Time' }, %timeInfo }, + Due => { Name => 'DateTimeDue', Groups => { 2 => 'Time' }, %timeInfo }, + Dtstart => { Name => 'DateTimeStart', Groups => { 2 => 'Time' }, %timeInfo }, + Duration => { }, + Freebusy => 'FreeBusyTime', + Transp => 'TimeTransparency', + Tzid => { Name => 'TimezoneID', Groups => { 2 => 'Time' } }, + Tzname => { Name => 'TimezoneName', Groups => { 2 => 'Time' } }, + Tzoffsetfrom=> { Name => 'TimezoneOffsetFrom', Groups => { 2 => 'Time' } }, + Tzoffsetto => { Name => 'TimezoneOffsetTo', Groups => { 2 => 'Time' } }, + Tzurl => { Name => 'TimeZoneURL', Groups => { 2 => 'Time' } }, + Attendee => { }, + Contact => { }, + Organizer => { }, + 'Recurrence-id' => 'RecurrenceID', + 'Related-to' => 'RelatedTo', + Url => 'URL', + Uid => 'UID', + Exdate => { Name => 'ExceptionDateTimes', Groups => { 2 => 'Time' }, %timeInfo }, + Rdate => { Name => 'RecurrenceDateTimes', Groups => { 2 => 'Time' }, %timeInfo }, + Rrule => { Name => 'RecurrenceRule', Groups => { 2 => 'Time' } }, + Action => { }, + Repeat => { }, + Trigger => { }, + Created => { Name => 'DateCreated', Groups => { 2 => 'Time' }, %timeInfo }, + Dtstamp => { Name => 'DateTimeStamp', Groups => { 2 => 'Time' }, %timeInfo }, + 'Last-modified' => { Name => 'ModifyDate', Groups => { 2 => 'Time' }, %timeInfo }, + Sequence => 'SequenceNumber', + 'Request-status' => 'RequestStatus', + Acknowledged=> { Name => 'Acknowledged', Groups => { 2 => 'Time' }, %timeInfo }, +# +# Observed X-tags (not a comprehensive list): +# + 'X-apple-calendar-color'=> 'CalendarColor', + 'X-apple-default-alarm' => 'DefaultAlarm', + 'X-apple-local-default-alarm' => 'LocalDefaultAlarm', + 'X-microsoft-cdo-appt-sequence' => 'AppointmentSequence', + 'X-microsoft-cdo-ownerapptid' => 'OwnerAppointmentID', + 'X-microsoft-cdo-busystatus' => 'BusyStatus', + 'X-microsoft-cdo-intendedstatus' => 'IntendedBusyStatus', + 'X-microsoft-cdo-alldayevent' => 'AllDayEvent', + 'X-microsoft-cdo-importance' => { + Name => 'Importance', + PrintConv => { + 0 => 'Low', + 1 => 'Normal', + 2 => 'High', + }, + }, + 'X-microsoft-cdo-insttype' => { + Name => 'InstanceType', + PrintConv => { + 0 => 'Non-recurring Appointment', + 1 => 'Recurring Appointment', + 2 => 'Single Instance of Recurring Appointment', + 3 => 'Exception to Recurring Appointment', + }, + }, + 'X-microsoft-donotforwardmeeting' => 'DoNotForwardMeeting', + 'X-microsoft-disallow-counter' => 'DisallowCounterProposal', + 'X-microsoft-locations' => { Name => 'MeetingLocations', Groups => { 2 => 'Location' } }, + 'X-wr-caldesc' => 'CalendarDescription', + 'X-wr-calname' => 'CalendarName', + 'X-wr-relcalid' => 'CalendarID', + 'X-wr-timezone' => { Name => 'TimeZone2', Groups => { 2 => 'Time' } }, + 'X-wr-alarmuid' => 'AlarmUID', +); + +#------------------------------------------------------------------------------ +# Get vCard tag, creating if necessary +# Inputs: 0) ExifTool ref, 1) tag table ref, 2) tag ID, 3) tag Name, +# 4) source tagInfo ref, 5) lang code +# Returns: tagInfo ref +sub GetVCardTag($$$$;$$) +{ + my ($et, $tagTablePtr, $tag, $name, $srcInfo, $langCode) = @_; + my $tagInfo = $$tagTablePtr{$tag}; + unless ($tagInfo) { + if ($srcInfo) { + $tagInfo = { %$srcInfo }; + } else { + $tagInfo = { }; + $et->VPrint(0, $$et{INDENT}, "[adding $tag]\n"); + } + $$tagInfo{Name} = $name; + delete $$tagInfo{Description}; # create new description + AddTagToTable($tagTablePtr, $tag, $tagInfo); + } + # handle alternate languages (the "language" parameter) + $tagInfo = Image::ExifTool::GetLangInfo($tagInfo, $langCode) if $langCode; + return $tagInfo; +} + +#------------------------------------------------------------------------------ +# Decode vCard text +# Inputs: 0) ExifTool ref, 1) vCard text, 2) encoding +# Returns: decoded text (or array ref for a list of values) +sub DecodeVCardText($$;$) +{ + my ($et, $val, $enc) = @_; + $enc = defined($enc) ? lc $enc : ''; + if ($enc eq 'b' or $enc eq 'base64') { + require Image::ExifTool::XMP; + $val = Image::ExifTool::XMP::DecodeBase64($val); + } else { + if ($enc eq 'quoted-printable') { + # convert "=HH" hex codes to characters + $val =~ s/=([0-9a-f]{2})/chr(hex($1))/ige; + } + $val = $et->Decode($val, 'UTF8'); # convert from UTF-8 + # convert unescaped commas to nulls to separate list items + $val =~ s/(\\.)|(,)/$1 || "\0"/sge; + # unescape necessary characters in value + $val =~ s/\\(.)/$unescapeVCard{$1}||$1/sge; + # split into list if necessary + my @vals = split /\0/, $val; + $val = \@vals if @vals > 1; + } + return $val; +} + +#------------------------------------------------------------------------------ +# Read information in a vCard file +# Inputs: 0) ExifTool ref, 1) dirInfo ref +# Returns: 1 on success, 0 if this wasn't a valid vCard file +sub ProcessVCard($$) +{ + local $_; + my ($et, $dirInfo) = @_; + my $raf = $$dirInfo{RAF}; + my ($buff, $val, $ok, $component, %compNum, @count); + + return 0 unless $raf->Read($buff, 24) and $raf->Seek(0,0) and $buff=~/^BEGIN:(VCARD|VCALENDAR)\r\n/i; + my ($type, $lbl, $tbl, $ext) = uc($1) eq 'VCARD' ? qw(VCard vCard Main VCF) : qw(ICS iCalendar VCalendar ICS); + $et->SetFileType($type, undef, $ext); + return 1 if $$et{OPTIONS}{FastScan} and $$et{OPTIONS}{FastScan} == 3; + local $/ = "\r\n"; + my $tagTablePtr = GetTagTable("Image::ExifTool::VCard::$tbl"); + my $more = $raf->ReadLine($buff); # read first line + chomp $buff if $more; + while ($more) { + # retrieve previous line from $buff + $val = $buff if defined $buff; + # read ahead to next line to see if is a continuation + $more = $raf->ReadLine($buff); + if ($more) { + chomp $buff; + # add continuation line if necessary + $buff =~ s/^[ \t]// and $val .= $buff, undef($buff), next; + } + if ($val =~ /^(BEGIN|END):(V?)(\w+)$/i) { + my ($begin, $v, $what) = ((lc($1) eq 'begin' ? 1 : 0), $2, ucfirst lc $3); + if ($what eq 'Card' or $what eq 'Calendar') { + if ($begin) { + @count = ( { } ); # reset group counters + } else { + $ok = 1; # ok if we read at least on full VCARD or VCALENDAR + } + next; + } + # absorb top-level component into family 1 group name + if ($isComponent{$what}) { + if ($begin) { + unless ($component) { + # begin a new top-level component + @count = ( { } ); + $component = $what; + $compNum{$component} = ($compNum{$component} || 0) + 1; + next; + } + } elsif ($component and $component eq $what) { + # this top-level component has ended + undef $component; + next; + } + } + # keep count of each component at this level + if ($begin) { + $count[-1]{$what} = ($count[-1]{$what} || 0) + 1 if $v; + push @count, { obj => $what }; + } elsif (@count > 1) { + pop @count; + } + next; + } elsif ($ok) { + $ok = 0; + $$et{DOC_NUM} = ++$$et{DOC_COUNT}; # read next card as a new document + } + unless ($val =~ s/^([-A-Za-z0-9.]+)//) { + $et->WarnOnce("Unrecognized line in $lbl file"); + next; + } + my $tag = $1; + # set group if it exists + if ($tag =~ s/^([-A-Za-z0-9]+)\.//) { + $$et{SET_GROUP1} = ucfirst lc $1; + } elsif ($component) { + $$et{SET_GROUP1} = $component . $compNum{$component}; + } else { + delete $$et{SET_GROUP1}; + } + my ($name, %param, $p, @val); + # vCard tag ID's are case-insensitive, so normalize to lowercase with + # an uppercase first letter for use as a tag name + $name = ucfirst $tag if $tag =~ /[a-z]/; # preserve mixed case in name if it exists + $tag = ucfirst lc $tag; + # get source tagInfo reference + my $srcInfo = $et->GetTagInfo($tagTablePtr, $tag); + if ($srcInfo) { + $name = $$srcInfo{Name}; # use our name + } else { + $name or $name = $tag; + # remove leading "X-" from name if it exists + $name =~ s/^X-// and $name = ucfirst $name; + } + # add object name(s) to tag if necessary + if (@count > 1) { + my $i; + for ($i=$#count-1; $i>=0; --$i) { + my $pre = $count[$i-1]{obj}; # use containing object name as tag prefix + my $c = $count[$i]{$pre}; # add index for object number + $c = '' unless defined $c; + $tag = $pre . $c . $tag; + $name = $pre . $c . $name; + } + } + # parse parameters + while ($val =~ s/^;([-A-Za-z0-9]*)(=?)//) { + $p = ucfirst lc $1; + # convert old vCard 2.x parameters to the new "TYPE=" format + $2 or $val = $1 . $val, $p = 'Type'; + # read parameter value + for (;;) { + last unless $val =~ s/^"([^"]*)",?// or $val =~ s/^([^";:,]+,?)//; + my $v = $p eq 'Type' ? ucfirst lc $1 : $1; + $param{$p} = defined($param{$p}) ? $param{$p} . $v : $v; + } + if (defined $param{$p}) { + $param{$p} =~ s/\\(.)/$unescapeVCard{$1}||$1/sge; + } else { + $param{$p} = ''; + } + } + $val =~ s/^:// or $et->WarnOnce("Invalid line in $lbl file"), next; + # add 'Type' parameter to id and name if it exists + $param{Type} and $tag .= $param{Type}, $name .= $param{Type}; + # convert base64-encoded data + if ($val =~ s{^data:(\w+)/(\w+);base64,}{}) { + my $xtra = ucfirst(lc $1) . ucfirst(lc $2); + $tag .= $xtra; + $name .= $xtra; + $param{Encoding} = 'base64'; + } + $val = DecodeVCardText($et, $val, $param{Encoding}); + my $tagInfo = GetVCardTag($et, $tagTablePtr, $tag, $name, $srcInfo, $param{Language}); + $et->HandleTag($tagTablePtr, $tag, $val, TagInfo => $tagInfo); + # handle some other parameters that we care about (ignore the rest for now) + foreach $p (qw(Geo Label Tzid)) { + next unless defined $param{$p}; + # use tag attributes from our table if it exists + my $srcTag2 = $et->GetTagInfo($tagTablePtr, $p); + my $pn = $srcTag2 ? $$srcTag2{Name} : $p; + $val = DecodeVCardText($et, $param{$p}); + # add parameter to tag ID and name + my ($tg, $nm) = ($tag . $p, $name . $pn); + $tagInfo = GetVCardTag($et, $tagTablePtr, $tg, $nm, $srcTag2, $param{Language}); + $et->HandleTag($tagTablePtr, $tg, $val, TagInfo => $tagInfo); + } + } + delete $$et{SET_GROUP1}; + delete $$et{DOC_NUM}; + $ok or $et->Warn("Missing $lbl end"); + return 1; +} + +1; # end + +__END__ + +=head1 NAME + +Image::ExifTool::VCard - Read vCard and iCalendar meta information + +=head1 SYNOPSIS + +This module is used by Image::ExifTool + +=head1 DESCRIPTION + +This module contains definitions required by Image::ExifTool to read meta +information from vCard VCF and iCalendar ICS files. + +=head1 AUTHOR + +Copyright 2003-2019, Phil Harvey (phil at owl.phy.queensu.ca) + +This library is free software; you can redistribute it and/or modify it +under the same terms as Perl itself. + +=head1 REFERENCES + +=over 4 + +=item L<http://en.m.wikipedia.org/wiki/VCard> + +=item L<http://tools.ietf.org/html/rfc6350> + +=item L<http://tools.ietf.org/html/rfc5545> + +=back + +=head1 SEE ALSO + +L<Image::ExifTool::TagNames/VCard Tags>, +L<Image::ExifTool::TagNames/VCard VCalendar Tags>, +L<Image::ExifTool(3pm)|Image::ExifTool> + +=cut + diff --git a/lib/Image/ExifTool/Validate.pm b/lib/Image/ExifTool/Validate.pm new file mode 100644 index 0000000..055a68e --- /dev/null +++ b/lib/Image/ExifTool/Validate.pm @@ -0,0 +1,626 @@ +#------------------------------------------------------------------------------ +# File: Validate.pm +# +# Description: Additional metadata validation +# +# Created: 2017/01/18 - P. Harvey +# +# Notes: My apologies for the convoluted logic contained herein, but it +# is done this way to retro-fit the Validate feature into the +# existing ExifTool code while reducing the possibility of +# introducing bugs or slowing down processing when this feature +# is not used. +#------------------------------------------------------------------------------ + +package Image::ExifTool::Validate; + +use strict; +use vars qw($VERSION %exifSpec); + +$VERSION = '1.14'; + +use Image::ExifTool qw(:Utils); +use Image::ExifTool::Exif; + +# EXIF table tag ID's which are part of the EXIF 2.31 specification +# (also used by BuildTagLookup to add underlines in HTML version of EXIF Tag Table) +%exifSpec = ( + 0x1 => 1, + 0x100 => 1, 0x8298 => 1, 0x9207 => 1, 0xa217 => 1, + 0x101 => 1, 0x829a => 1, 0x9208 => 1, 0xa300 => 1, + 0x102 => 1, 0x829d => 1, 0x9209 => 1, 0xa301 => 1, + 0x103 => 1, 0x8769 => 1, 0x920a => 1, 0xa302 => 1, + 0x106 => 1, 0x8822 => 1, 0x9214 => 1, 0xa401 => 1, + 0x10e => 1, 0x8824 => 1, 0x927c => 1, 0xa402 => 1, + 0x10f => 1, 0x8825 => 1, 0x9286 => 1, 0xa403 => 1, + 0x110 => 1, 0x8827 => 1, 0x9290 => 1, 0xa404 => 1, + 0x111 => 1, 0x8828 => 1, 0x9291 => 1, 0xa405 => 1, + 0x112 => 1, 0x8830 => 1, 0x9292 => 1, 0xa406 => 1, + 0x115 => 1, 0x8831 => 1, 0x9400 => 1, 0xa407 => 1, + 0x116 => 1, 0x8832 => 1, 0x9401 => 1, 0xa408 => 1, + 0x117 => 1, 0x8833 => 1, 0x9402 => 1, 0xa409 => 1, + 0x11a => 1, 0x8834 => 1, 0x9403 => 1, 0xa40a => 1, + 0x11b => 1, 0x8835 => 1, 0x9404 => 1, 0xa40b => 1, + 0x11c => 1, 0x9000 => 1, 0x9405 => 1, 0xa40c => 1, + 0x128 => 1, 0x9003 => 1, 0xa000 => 1, 0xa420 => 1, + 0x12d => 1, 0x9004 => 1, 0xa001 => 1, 0xa430 => 1, + 0x131 => 1, 0x9010 => 1, 0xa002 => 1, 0xa431 => 1, + 0x132 => 1, 0x9011 => 1, 0xa003 => 1, 0xa432 => 1, + 0x13b => 1, 0x9012 => 1, 0xa004 => 1, 0xa433 => 1, + 0x13e => 1, 0x9101 => 1, 0xa005 => 1, 0xa434 => 1, + 0x13f => 1, 0x9102 => 1, 0xa20b => 1, 0xa435 => 1, + 0x201 => 1, 0x9201 => 1, 0xa20c => 1, + 0x202 => 1, 0x9202 => 1, 0xa20e => 1, + 0x211 => 1, 0x9203 => 1, 0xa20f => 1, + 0x212 => 1, 0x9204 => 1, 0xa210 => 1, + 0x213 => 1, 0x9205 => 1, 0xa214 => 1, + 0x214 => 1, 0x9206 => 1, 0xa215 => 1, +); + +# tags standard in various RAW file formats +my %otherSpec = ( + CR2 => { 0xc5d8 => 1, 0xc5d9 => 1, 0xc5e0 => 1, 0xc640 => 1, 0xc6dc => 1, 0xc6dd => 1 }, + NEF => { 0x9216 => 1, 0x9217 => 1 }, + DNG => { 0x882a => 1, 0x9211 => 1, 0x9216 => 1 }, + ARW => { 0x7000 => 1, 0x7001 => 1, 0x7010 => 1, 0x7011 => 1, 0x7020 => 1, + 0x7031 => 1, 0x7032 => 1, 0x7034 => 1, 0x7035 => 1, 0x7036 => 1, 0x7037 => 1, + 0x7310 => 1, 0x7313 => 1, 0x7316 => 1, 0x74c7 => 1, 0x74c8 => 1, 0xa500 => 1 }, + RW2 => { All => 1 }, # ignore all unknown tags in RW2 + RWL => { All => 1 }, + RAF => { All => 1 }, # (temporary) + DCR => { All => 1 }, + KDC => { All => 1 }, + JXR => { All => 1 }, + SRW => { 0xa010 => 1, 0xa011 => 1, 0xa101 => 1, 0xa102 => 1 }, + NRW => { 0x9216 => 1, 0x9217 => 1 }, + X3F => { 0xa500 => 1 }, +); + +# standard format for tags (not necessary for exifSpec or GPS tags where Writable is defined) +my %stdFormat = ( + ExifIFD => { + 0xa002 => 'int(16|32)u', + 0xa003 => 'int(16|32)u', + }, + InteropIFD => { + 0x01 => 'string', + 0x02 => 'undef', + 0x1000 => 'string', + 0x1001 => 'int(16|32)u', + 0x1002 => 'int(16|32)u', + }, + IFD => { + # TIFF, EXIF, XMP, IPTC, ICC_Profile and PrintIM standard tags: + 0xfe => 'int32u', 0x11f => 'rational64u', 0x14a => 'int32u', 0x205 => 'int16u', + 0xff => 'int16u', 0x120 => 'int32u', 0x14c => 'int16u', 0x206 => 'int16u', + 0x100 => 'int(16|32)u', 0x121 => 'int32u', 0x14d => 'string', 0x207 => 'int32u', + 0x101 => 'int(16|32)u', 0x122 => 'int16u', 0x14e => 'int16u', 0x208 => 'int32u', + 0x107 => 'int16u', 0x123 => 'int16u', 0x150 => 'int(8|16)u', 0x209 => 'int32u', + 0x108 => 'int16u', 0x124 => 'int32u', 0x151 => 'string', 0x211 => 'rational64u', + 0x109 => 'int16u', 0x125 => 'int32u', 0x152 => 'int16u', 0x212 => 'int16u', + 0x10a => 'int16u', 0x129 => 'int16u', 0x153 => 'int16u', 0x213 => 'int16u', + 0x10d => 'string', 0x13c => 'string', 0x154 => '.*', 0x214 => 'rational64u', + 0x111 => 'int(16|32)u', 0x13d => 'int16u', 0x155 => '.*', 0x2bc => 'int8u', + 0x116 => 'int(16|32)u', 0x140 => 'int16u', 0x156 => 'int16u', 0x828d => 'int16u', + 0x117 => 'int(16|32)u', 0x141 => 'int16u', 0x15b => 'undef', 0x828e => 'int8u', + 0x118 => 'int16u', 0x142 => 'int(16|32)u', 0x200 => 'int16u', 0x83bb => 'int32u', + 0x119 => 'int16u', 0x143 => 'int(16|32)u', 0x201 => 'int32u', 0x8649 => 'int8u', + 0x11d => 'string', 0x144 => 'int32u', 0x202 => 'int32u', 0x8773 => 'undef', + 0x11e => 'rational64u', 0x145 => 'int(16|32)u', 0x203 => 'int16u', 0xc4a5 => 'undef', + # Windows Explorer tags: + 0x9c9b => 'int8u', 0x9c9d => 'int8u', 0x9c9f => 'int8u', + 0x9c9c => 'int8u', 0x9c9e => 'int8u', + # GeoTiff tags: + 0x830e => 'double', 0x8482 => 'double', 0x87af => 'int16u', 0x87b1 => 'string', + 0x8480 => 'double', 0x85d8 => 'double', 0x87b0 => 'double', + # DNG tags: + 0xc615 => '(string|int8u)', 0xc6d3 => '', + 0xc61a => '(int16u|int32u|rational64u)', 0xc6f4 => '(string|int8u)', + 0xc61d => 'int(16|32)u', 0xc6f6 => '(string|int8u)', + 0xc61f => '(int16u|int32u|rational64u)', 0xc6f8 => '(string|int8u)', + 0xc620 => '(int16u|int32u|rational64u)', 0xc6fe => '(string|int8u)', + 0xc628 => '(int16u|rational64u)', 0xc716 => '(string|int8u)', + 0xc634 => 'int8u', 0xc717 => '(string|int8u)', + 0xc640 => '', 0xc718 => '(string|int8u)', + 0xc660 => '', 0xc71e => 'int(16|32)u', + 0xc68b => '(string|int8u)', 0xc71f => 'int(16|32)u', + 0xc68d => 'int(16|32)u', 0xc791 => 'int(16|32)u', + 0xc68e => 'int(16|32)u', 0xc792 => 'int(16|32)u', + 0xc6d2 => '', 0xc793 => '(int16u|int32u|rational64u)', + }, +); + +# generate lookup for any IFD +my %stdFormatAnyIFD = map { %{$stdFormat{$_}} } keys %stdFormat; + +# tag values to validate based on file type (from EXIF specification) +# - validation code may access $val and %val, and returns 1 on success, +# or error message otherwise ('' for a generic message) +# - entry is undef if tag must not exist (same as 'not defined $val' in code) +my %validValue = ( + JPEG => { + IFD0 => { + 0x100 => undef, # ImageWidth + 0x101 => undef, # ImageLength + 0x102 => undef, # BitsPerSample + 0x103 => undef, # Compression + 0x106 => undef, # PhotometricInterpretation + 0x111 => undef, # StripOffsets + 0x115 => undef, # SamplesPerPixel + 0x116 => undef, # RowsPerStrip + 0x117 => undef, # StripByteCounts + 0x11a => 'defined $val', # XResolution + 0x11b => 'defined $val', # YResolution + 0x11c => undef, # PlanarConfiguration + 0x128 => '$val =~ /^[123]$/', # ResolutionUnit + 0x201 => undef, # JPEGInterchangeFormat + 0x202 => undef, # JPEGInterchangeFormatLength + 0x212 => undef, # YCbCrSubSampling + 0x213 => '$val =~ /^[12]$/', # YCbCrPositioning + }, + IFD1 => { + 0x100 => undef, # ImageWidth + 0x101 => undef, # ImageLength + 0x102 => undef, # BitsPerSample + 0x103 => '$val == 6', # Compression + 0x106 => undef, # PhotometricInterpretation + 0x111 => undef, # StripOffsets + 0x115 => undef, # SamplesPerPixel + 0x116 => undef, # RowsPerStrip + 0x117 => undef, # StripByteCounts + 0x11a => 'defined $val', # XResolution + 0x11b => 'defined $val', # YResolution + 0x11c => undef, # PlanarConfiguration + 0x128 => '$val =~ /^[123]$/', # ResolutionUnit + 0x201 => 'defined $val', # JPEGInterchangeFormat + 0x202 => 'defined $val', # JPEGInterchangeFormatLength + 0x212 => undef, # YCbCrSubSampling + }, + ExifIFD => { + 0x9000 => 'defined $val', # ExifVersion + 0x9101 => 'defined $val', # ComponentsConfiguration + 0xa000 => 'defined $val', # FlashpixVersion + 0xa001 => '$val == 1 or $val == 0xffff', # ColorSpace + 0xa002 => 'defined $val', # PixelXDimension + 0xa003 => 'defined $val', # PixelYDimension + }, + }, + TIFF => { + IFD0 => { + 0x100 => 'defined $val', # ImageWidth + 0x101 => 'defined $val', # ImageLength + 0x102 => 'defined $val', # BitsPerSample + 0x103 => q{ + not defined $val or $val =~ /^(1|5|6|32773)$/ or + ($val == 2 and (not defined $val{0x102} or $val{0x102} == 1)); + }, # Compression + 0x106 => '$val =~ /^[0123]$/', # PhotometricInterpretation + 0x111 => 'defined $val', # StripOffsets + # SamplesPerPixel + 0x115 => q{ + my $pi = $val{0x106} || 0; + my $xtra = ($val{0x152} ? scalar(split ' ', $val{0x152}) : 0); + if ($pi == 2 or $pi == 6) { + return $val == 3 + $xtra; + } elsif ($pi == 5) { + return $val == 4 + $xtra; + } else { + return 1; + } + }, + 0x116 => 'defined $val', # RowsPerStrip + 0x117 => 'defined $val', # StripByteCounts + 0x11a => 'defined $val', # XResolution + 0x11b => 'defined $val', # YResolution + 0x128 => '$val =~ /^[123]$/', # ResolutionUnit + # ColorMap (must be palette image with correct number of colors) + 0x140 => q{ + return '' if defined $val{0x106} and $val{0x106} == 3 xor defined $val; + return 1 if not defined $val or length($val) == 6 * 2 ** ($val{0x102} || 0); + return 'Invalid count for'; + }, + 0x201 => undef, # JPEGInterchangeFormat + 0x202 => undef, # JPEGInterchangeFormatLength + }, + ExifIFD => { + 0x9000 => 'defined $val', # ExifVersion + 0x9101 => undef, # ComponentsConfiguration + 0x9102 => undef, # CompressedBitsPerPixel + 0xa000 => 'defined $val', # FlashpixVersion + 0xa001 => '$val == 1 or $val == 0xffff', # ColorSpace + 0xa002 => undef, # PixelXDimension + 0xa003 => undef, # PixelYDimension + }, + InteropIFD => { + 0x0001 => undef, # InteropIndex + }, + }, +); + +# validity ranges for constrained date/time fields +my @validDateField = ( + [ 'Month', 1, 12 ], + [ 'Day', 1, 31 ], + [ 'Hour', 0, 23 ], + [ 'Minutes', 0, 59 ], + [ 'Seconds', 0, 59 ], + [ 'TZhr', 0, 14 ], + [ 'TZmin', 0, 59 ], +); + +# "Validate" tag information +my %validateInfo = ( + Groups => { 0 => 'ExifTool', 1 => 'ExifTool', 2 => 'ExifTool' }, + Notes => q{ + generated only if specifically requested. Requesting this tag automatically + enables the L<API Validate option|../ExifTool.html#Validate>, imposing + additional validation checks when extracting metadata. Returns the number + of errors, warnings and minor warnings encountered. Note that the Validate + feature focuses mainly on validation of TIFF/EXIF metadata and files + }, + PrintConv => { + '0 0 0' => 'OK', + OTHER => sub { + my @val = split ' ', shift; + my @rtn; + push @rtn, sprintf('%d Error%s', $val[0], $val[0] == 1 ? '' : 's') if $val[0]; + push @rtn, sprintf('%d Warning%s', $val[1], $val[1] == 1 ? '' : 's') if $val[1]; + if ($val[2]) { + my $str = ($val[1] == $val[2] ? ($val[1] == 1 ? '' : 'all ') : "$val[2] "); + $rtn[-1] .= " (${str}minor)"; + } + return join(' and ', @rtn); + }, + }, +); + +# add "Validate" tag to Extra table +AddTagToTable(\%Image::ExifTool::Extra, Validate => \%validateInfo, 1); + +#------------------------------------------------------------------------------ +# Validate the raw value of a tag +# Inputs: 0) ExifTool ref, 1) tag key, 2) raw tag value +# Returns: nothing, but issues a minor Warning if a problem was detected +sub ValidateRaw($$$) +{ + my ($self, $tag, $val) = @_; + my $tagInfo = $$self{TAG_INFO}{$tag}; + my $wrn; + + # evaluate Validate code if specified + if ($$tagInfo{Validate}) { + local $SIG{'__WARN__'} = \&Image::ExifTool::SetWarning; + undef $Image::ExifTool::evalWarning; + #### eval Validate ($self, $val, $tagInfo) + my $wrn = eval $$tagInfo{Validate}; + my $err = $Image::ExifTool::evalWarning || $@; + if ($wrn or $err) { + my $name = $$tagInfo{Table}{GROUPS}{0} . ':' . Image::ExifTool::GetTagName($tag); + $self->Warn("Validate $name: $err", 1) if $err; + $self->Warn("$wrn for $name", 1) if $wrn; + } + } + # check for unknown values in PrintConv lookup for all standard EXIF tags + if (ref $$tagInfo{PrintConv} eq 'HASH' and ($$tagInfo{Table}{SHORT_NAME} eq 'GPS::Main' or + ($$tagInfo{Table} eq \%Image::ExifTool::Exif::Main and $exifSpec{$$tagInfo{TagID}}))) + { + my $prt = $self->GetValue($tag, 'PrintConv'); + $wrn = 'Unknown value for' if $prt and $prt =~ /^Unknown \(/; + } + $wrn = 'Undefined value for' if $val eq 'undef'; + if ($wrn) { + my $name = $$self{DIR_NAME} . ':' . Image::ExifTool::GetTagName($tag); + $self->Warn("$wrn $name", 1); + } +} + +#------------------------------------------------------------------------------ +# Validate raw EXIF date/time value +# Inputs: 0) date/time value +# Returns: error string +sub ValidateExifDate($) +{ + my $val = shift; + if ($val =~ /^\d{4}:(\d{2}):(\d{2}) (\d{2}):(\d{2}):(\d{2})$/) { + my @a = ($1,$2,$3,$4,$5); + my ($i, @bad); + for ($i=0; $i<@a; ++$i) { + next if $a[$i] eq ' ' or ($a[$i] >= $validDateField[$i][1] and $a[$i] <= $validDateField[$i][2]); + push @bad, $validDateField[$i][0]; + } + return join('+', @bad) . ' out of range' if @bad; + # the EXIF specification allows blank fields or an entire blank value + } elsif ($val ne ' : : : : ' and $val ne ' ') { + return 'Invalid date/time format'; + } + return undef; # OK! +} + +#------------------------------------------------------------------------------ +# Validate EXIF-reformatted XMP date/time value +# Inputs: 0) date/time value +# Returns: error string +sub ValidateXMPDate($) +{ + my $val = shift; + if ($val =~ /^\d{4}$/ or + $val =~ /^\d{4}:(\d{2})$/ or + $val =~ /^\d{4}:(\d{2}):(\d{2})$/ or + $val =~ /^\d{4}:(\d{2}):(\d{2}) (\d{2}):(\d{2})()(Z|[-+](\d{2}):(\d{2}))?$/ or + $val =~ /^\d{4}:(\d{2}):(\d{2}) (\d{2}):(\d{2}):(\d{2})(Z|[-+](\d{2}):(\d{2}))?$/ or + $val =~ /^\d{4}:(\d{2}):(\d{2}) (\d{2}):(\d{2}):(\d{2})\.?\d*(Z|[-+](\d{2}):(\d{2}))?$/) + { + my @a = ($1,$2,$3,$4,$5,$7,$8); + my ($i, @bad); + for ($i=0; $i<@a; ++$i) { + last unless defined $a[$i]; + next if $a[$i] eq '' or ($a[$i] >= $validDateField[$i][1] and $a[$i] <= $validDateField[$i][2]); + push @bad, $validDateField[$i][0]; + } + return join('+', @bad) . ' out of range' if @bad; + } else { + return 'Invalid date/time format'; + } + return undef; # OK! +} + +#------------------------------------------------------------------------------ +# Validate EXIF tag +# Inputs: 0) ExifTool ref, 1) tag table ref, 2) tag ID, 3) tagInfo ref, +# 4) previous tag ID, 5) IFD name, 6) number of values, 7) value format string +# Returns: Nothing, but sets Warning tags if any problems are found +sub ValidateExif($$$$$$$$) +{ + my ($et, $tagTablePtr, $tag, $tagInfo, $lastTag, $ifd, $count, $formatStr) = @_; + + $et->WarnOnce("Entries in $ifd are out of order") if $tag <= $lastTag; + + # (get tagInfo for unknown tags if Unknown option not used) + if (not defined $tagInfo and $$tagTablePtr{$tag} and ref $$tagTablePtr{$tag} eq 'HASH') { + $tagInfo = $$tagTablePtr{$tag}; + } + if (defined $tagInfo) { + my $ti = $tagInfo || $$tagTablePtr{$tag}; + $ti = $$ti[-1] if ref $ti eq 'ARRAY'; + my $stdFmt = $stdFormat{$ifd} || $stdFormat{IFD}; + if (defined $$stdFmt{All} or ($tagTablePtr eq \%Image::ExifTool::Exif::Main and + ($exifSpec{$tag} or $$stdFmt{$tag} or + ($tag >= 0xc612 and $tag <= 0xc7b5 and not defined $$stdFmt{$tag}))) or # (DNG tags) + $$tagTablePtr{SHORT_NAME} eq 'GPS::Main') + { + my $wgp = $$ti{WriteGroup} || $$tagTablePtr{WRITE_GROUP}; + if ($wgp and $wgp ne $ifd and $wgp ne 'All' and not $$ti{OffsetPair} and + ($ifd =~ /^(Sub|Profile)?IFD\d*$/ xor $wgp =~ /^(Sub)?IFD\d*$/) and + ($$ti{Writable} or $$ti{WriteGroup}) and $ifd !~ /^SRF\d+$/) + { + $et->Warn(sprintf('Wrong IFD for 0x%.4x %s (should be %s not %s)', $tag, $$ti{Name}, $wgp, $ifd)); + } + my $fmt = $$stdFmt{$tag} || $$ti{Writable}; + if ($fmt and $formatStr !~ /^$fmt$/ and (not $tagInfo or + not $$tagInfo{IsOffset} or $Image::ExifTool::Exif::intFormat{$formatStr})) + { + $et->Warn(sprintf('Non-standard format (%s) for %s 0x%.4x %s', $formatStr, $ifd, $tag, $$ti{Name})) + } + } elsif ($stdFormatAnyIFD{$tag}) { + if ($$ti{Writable} || $$ti{WriteGroup}) { + my $wgp = $$ti{WriteGroup} || $$tagTablePtr{WRITE_GROUP}; + if ($wgp and $wgp ne $ifd) { + $et->Warn(sprintf('Wrong IFD for 0x%.4x %s (should be %s not %s)', $tag, $$ti{Name}, $wgp, $ifd)); + } + } + } elsif (not $otherSpec{$$et{VALUE}{FileType}} or + (not $otherSpec{$$et{VALUE}{FileType}}{$tag} and not $otherSpec{$$et{VALUE}{FileType}}{All})) + { + if ($tagTablePtr eq \%Image::ExifTool::Exif::Main or $$tagInfo{Unknown}) { + $et->Warn(sprintf('Non-standard %s tag 0x%.4x %s', $ifd, $tag, $$ti{Name}), 1); + } + } + # change expected count from read Format to Writable size + my $tiCount = $$ti{Count}; + if ($tiCount) { + if ($$ti{Format} and $$ti{Writable} and + $Image::ExifTool::Exif::formatNumber{$$ti{Format}} and + $Image::ExifTool::Exif::formatNumber{$$ti{Writable}}) + { + my $s1 = $Image::ExifTool::Exif::formatSize[$Image::ExifTool::Exif::formatNumber{$$ti{Format}}]; + my $s2 = $Image::ExifTool::Exif::formatSize[$Image::ExifTool::Exif::formatNumber{$$ti{Writable}}]; + $tiCount = int($tiCount * $s1 / $s2); + } + if ($tiCount > 0 and $count != $tiCount) { + $et->Warn(sprintf('Non-standard count (%d) for %s 0x%.4x %s', $count, $ifd, $tag, $$ti{Name})); + } + } + } elsif (not $otherSpec{$$et{VALUE}{FileType}} or + (not $otherSpec{$$et{VALUE}{FileType}}{$tag} and not $otherSpec{$$et{VALUE}{FileType}}{All})) + { + $et->Warn(sprintf('Unknown %s tag 0x%.4x', $ifd, $tag), 1); + } +} + +#------------------------------------------------------------------------------ +# Validate image data offsets/sizes +# Inputs: 0) ExifTool ref, 1) offset info hash ref (arrays of tagInfo/value pairs, keyed by tagID) +# 2) directory name, 3) optional flag for minor warning +sub ValidateOffsetInfo($$$;$) +{ + local $_; + my ($et, $offsetInfo, $dirName, $minor) = @_; + + my $fileSize = $$et{VALUE}{FileSize} or return; + + # (don't test RWZ files and some other file types) + return if $$et{DontValidateImageData}; + # (Minolta A200 uses wrong byte order for these) + return if $$et{TIFF_TYPE} eq 'MRW' and $dirName eq 'IFD0' and $$et{Model} =~ /^DiMAGE A200/; + # (don't test 3FR, RWL or RW2 files) + return if $$et{TIFF_TYPE} =~ /^(3FR|RWL|RW2)$/; + + Image::ExifTool::Exif::ValidateImageData($et, $offsetInfo, $dirName); + + # loop through all offsets + while (%$offsetInfo) { + my ($id1) = sort keys %$offsetInfo; + my $offsets = $$offsetInfo{$id1}; + delete $$offsetInfo{$id1}; + next unless ref $offsets eq 'ARRAY'; + my $id2 = $$offsets[0]{OffsetPair}; + unless (defined $id2 and $$offsetInfo{$id2}) { + unless ($$offsets[0]{NotRealPair} or (defined $id2 and $id2 == -1)) { + my $corr = $$offsets[0]{IsOffset} ? 'size' : 'offset'; + $et->Warn("$dirName:$$offsets[0]{Name} is missing the corresponding $corr tag") unless $minor; + } + next; + } + my $sizes = $$offsetInfo{$id2}; + delete $$offsetInfo{$id2}; + ($sizes, $offsets) = ($offsets, $sizes) if $$sizes[0]{IsOffset}; + my @offsets = split ' ', $$offsets[1]; + my @sizes = split ' ', $$sizes[1]; + if (@sizes != @offsets) { + $et->Warn(sprintf('Wrong number of values in %s 0x%.4x %s', + $dirName, $$offsets[0]{TagID}, $$offsets[0]{Name}), $minor); + next; + } + while (@offsets) { + my $start = pop @offsets; + my $end = $start + pop @sizes; + $et->WarnOnce("$dirName:$$offsets[0]{Name} is zero", $minor) if $start == 0; + $et->WarnOnce("$dirName:$$sizes[0]{Name} is zero", $minor) if $start == $end; + next unless $end > $fileSize; + if ($start >= $fileSize) { + if ($start == 0xffffffff) { + $et->Warn("$dirName:$$offsets[0]{Name} is invalid (0xffffffff)", $minor); + } else { + $et->Warn("$dirName:$$offsets[0]{Name} is past end of file", $minor); + } + } else { + $et->Warn("$dirName:$$offsets[0]{Name}+$$sizes[0]{Name} runs past end of file", $minor); + } + last; + } + } +} + +#------------------------------------------------------------------------------ +# Finish Validating tags +# Inputs: 0) ExifTool ref, 1) True to generate Validate tag +sub FinishValidate($$) +{ + my ($et, $mkTag) = @_; + + my $fileType = $$et{FILE_TYPE} || ''; + $fileType = $$et{TIFF_TYPE} if $fileType eq 'TIFF'; + + if ($validValue{$fileType}) { + my ($grp, $tag, %val); + local $SIG{'__WARN__'} = \&Image::ExifTool::SetWarning; + foreach $grp (sort keys %{$validValue{$fileType}}) { + next unless $$et{FOUND_DIR}{$grp}; + # get all tags in this group + my ($key, %val, %info, $minor); + foreach $key (keys %{$$et{VALUE}}) { + next unless $et->GetGroup($key, 1) eq $grp; + next if $$et{TAG_EXTRA}{$key} and $$et{TAG_EXTRA}{$key}{G3}; # ignore sub-documents + # fill in %val lookup with values based on tag ID + my $tag = $$et{TAG_INFO}{$key}{TagID}; + $val{$tag} = $$et{VALUE}{$key}; + # save TagInfo ref for later + $info{$tag} = $$et{TAG_INFO}{$key}; + } + # make quick lookup for values based on tag ID + my $validValue = $validValue{$fileType}{$grp}; + foreach $tag (sort { $a <=> $b } keys %$validValue) { + my $val = $val{$tag}; + my ($pre, $post); + if (defined $$validValue{$tag}) { + #### eval ($val, %val) + my $result = eval $$validValue{$tag}; + if (not defined $result) { + $pre = 'Internal error validating'; + } elsif ($result eq '') { + $pre = defined $val ? 'Invalid value for' : "Missing required $fileType"; + } else { + next if $result == '1'; + $pre = $result; + } + } else { + next unless defined $val; + $post = "is not allowed in $fileType"; + $minor = 1; + } + my $name; + if ($info{$tag}) { + $name = $info{$tag}{Name}; + } else { + my $table = 'Image::ExifTool::'.($grp eq 'GPS' ? 'GPS' : 'Exif').'::Main'; + my $tagInfo = GetTagTable($table)->{$tag}; + $tagInfo = $$tagInfo[0] if ref $tagInfo eq 'ARRAY'; + $name = $tagInfo ? $$tagInfo{Name} : '<unknown>'; + } + next if $$et{WrongFormat} and $$et{WrongFormat}{"$grp:$name"}; + $pre ? ($pre .= ' ') : ($pre = ''); + $post ? ($post = ' '.$post) : ($post = ''); + $et->Warn(sprintf('%s%s tag 0x%.4x %s%s', $pre, $grp, $tag, $name, $post), $minor); + } + } + } + # validate file extension + if ($$et{FILENAME} ne '') { + my $fileExt = ($$et{FILENAME} =~ /^.*\.([^.]+)$/s) ? uc($1) : ''; + my $extFileType = Image::ExifTool::GetFileType($fileExt); + if ($extFileType and $extFileType ne $fileType) { + my $normExt = $$et{VALUE}{FileTypeExtension}; + if ($normExt and $normExt ne $fileExt) { + my $lkup = $Image::ExifTool::fileTypeLookup{$fileExt}; + if (ref $lkup or $lkup ne $normExt) { + $et->Warn("File has wrong extension (should be $normExt, not $fileExt)"); + } + } + } + } + # issue warning if FastScan option used + $et->Warn('Validation incomplete because FastScan option used') if $et->Options('FastScan'); + + # generate Validate tag if necessary + if ($mkTag) { + my (@num, $key); + push @num, $$et{VALUE}{Error} ? ($$et{DUPL_TAG}{Error} || 0) + 1 : 0, + $$et{VALUE}{Warning} ? ($$et{DUPL_TAG}{Warning} || 0) + 1 : 0, 0; + for ($key = 'Warning'; ; ) { + ++$num[2] if $$et{VALUE}{$key} and $$et{VALUE}{$key} =~ /^\[minor\]/i; + $key = $et->NextTagKey($key) or last; + } + $et->FoundTag(Validate => "@num"); + } +} + +1; # end + +__END__ + +=head1 NAME + +Image::ExifTool::Validate - Additional metadata validation + +=head1 SYNOPSIS + +This module is used by Image::ExifTool + +=head1 DESCRIPTION + +This module contains additional routines and definitions used when the +ExifTool Validate option is enabled. + +=head1 AUTHOR + +Copyright 2003-2019, Phil Harvey (phil at owl.phy.queensu.ca) + +This library is free software; you can redistribute it and/or modify it +under the same terms as Perl itself. + +=head1 SEE ALSO + +L<Image::ExifTool(3pm)|Image::ExifTool>, +L<Image::ExifTool::TagNames/Extra Tags> + +=cut diff --git a/lib/Image/ExifTool/Vorbis.pm b/lib/Image/ExifTool/Vorbis.pm new file mode 100644 index 0000000..6efd253 --- /dev/null +++ b/lib/Image/ExifTool/Vorbis.pm @@ -0,0 +1,255 @@ +#------------------------------------------------------------------------------ +# File: Vorbis.pm +# +# Description: Read Ogg Vorbis audio meta information +# +# Revisions: 2006/11/10 - P. Harvey Created +# 2011/07/12 - PH Moved Ogg to a separate module and added Theora +# +# References: 1) http://www.xiph.org/vorbis/doc/ +# 2) http://flac.sourceforge.net/ogg_mapping.html +# 3) http://www.theora.org/doc/Theora.pdf +#------------------------------------------------------------------------------ + +package Image::ExifTool::Vorbis; + +use strict; +use vars qw($VERSION); +use Image::ExifTool qw(:DataAccess :Utils); + +$VERSION = '1.08'; + +sub ProcessComments($$$); + +# Vorbis header types +%Image::ExifTool::Vorbis::Main = ( + NOTES => q{ + Information extracted from Ogg Vorbis files. See + L<http://www.xiph.org/vorbis/doc/> for the Vorbis specification. + }, + 1 => { + Name => 'Identification', + SubDirectory => { TagTable => 'Image::ExifTool::Vorbis::Identification' }, + }, + 3 => { + Name => 'Comments', + SubDirectory => { TagTable => 'Image::ExifTool::Vorbis::Comments' }, + }, +); + +%Image::ExifTool::Vorbis::Identification = ( + PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData, + GROUPS => { 2 => 'Audio' }, + 0 => { + Name => 'VorbisVersion', + Format => 'int32u', + }, + 4 => 'AudioChannels', + 5 => { + Name => 'SampleRate', + Format => 'int32u', + }, + 9 => { + Name => 'MaximumBitrate', + Format => 'int32u', + RawConv => '$val || undef', + PrintConv => 'ConvertBitrate($val)', + }, + 13 => { + Name => 'NominalBitrate', + Format => 'int32u', + RawConv => '$val || undef', + PrintConv => 'ConvertBitrate($val)', + }, + 17 => { + Name => 'MinimumBitrate', + Format => 'int32u', + RawConv => '$val || undef', + PrintConv => 'ConvertBitrate($val)', + }, +); + +%Image::ExifTool::Vorbis::Comments = ( + PROCESS_PROC => \&ProcessComments, + GROUPS => { 2 => 'Audio' }, + NOTES => q{ + The tags below are only some common tags found in the Vorbis comments of Ogg + Vorbis and Ogg FLAC audio files, however ExifTool will extract values from + any tag found, even if not listed here. + }, + vendor => { Notes => 'from comment header' }, + TITLE => { Name => 'Title' }, + VERSION => { Name => 'Version' }, + ALBUM => { Name => 'Album' }, + TRACKNUMBER=>{ Name => 'TrackNumber' }, + ARTIST => { Name => 'Artist', Groups => { 2 => 'Author' }, List => 1 }, + PERFORMER => { Name => 'Performer', Groups => { 2 => 'Author' }, List => 1 }, + COPYRIGHT => { Name => 'Copyright', Groups => { 2 => 'Author' } }, + LICENSE => { Name => 'License', Groups => { 2 => 'Author' } }, + ORGANIZATION=>{Name => 'Organization', Groups => { 2 => 'Author' } }, + DESCRIPTION=>{ Name => 'Description' }, + GENRE => { Name => 'Genre' }, + DATE => { Name => 'Date', Groups => { 2 => 'Time' } }, + LOCATION => { Name => 'Location', Groups => { 2 => 'Location' } }, + CONTACT => { Name => 'Contact', Groups => { 2 => 'Author' }, List => 1 }, + ISRC => { Name => 'ISRCNumber' }, + COVERARTMIME => { Name => 'CoverArtMIMEType' }, + COVERART => { + Name => 'CoverArt', + Groups => { 2 => 'Preview' }, + Notes => 'base64-encoded image', + ValueConv => q{ + require Image::ExifTool::XMP; + Image::ExifTool::XMP::DecodeBase64($val); + }, + }, + REPLAYGAIN_TRACK_PEAK => { Name => 'ReplayGainTrackPeak' }, + REPLAYGAIN_TRACK_GAIN => { Name => 'ReplayGainTrackGain' }, + REPLAYGAIN_ALBUM_PEAK => { Name => 'ReplayGainAlbumPeak' }, + REPLAYGAIN_ALBUM_GAIN => { Name => 'ReplayGainAlbumGain' }, + # observed in "Xiph.Org libVorbis I 20020717" ogg: + ENCODED_USING => { Name => 'EncodedUsing' }, + ENCODED_BY => { Name => 'EncodedBy' }, + COMMENT => { Name => 'Comment' }, + # in Theora documentation (ref 3) + DIRECTOR => { Name => 'Director' }, + PRODUCER => { Name => 'Producer' }, + COMPOSER => { Name => 'Composer' }, + ACTOR => { Name => 'Actor' }, + # Opus tags + ENCODER => { Name => 'Encoder' }, + ENCODER_OPTIONS => { Name => 'EncoderOptions' }, + METADATA_BLOCK_PICTURE => { + Name => 'Picture', + Binary => 1, + # ref https://wiki.xiph.org/VorbisComment#METADATA_BLOCK_PICTURE + RawConv => q{ + require Image::ExifTool::XMP; + Image::ExifTool::XMP::DecodeBase64($val); + }, + SubDirectory => { + TagTable => 'Image::ExifTool::FLAC::Picture', + ByteOrder => 'BigEndian', + }, + }, +); + +# Vorbis composite tags +%Image::ExifTool::Vorbis::Composite = ( + Duration => { + Require => { + 0 => 'Vorbis:NominalBitrate', + 1 => 'FileSize', + }, + RawConv => '$val[0] ? $val[1] * 8 / $val[0] : undef', + PrintConv => 'ConvertDuration($val) . " (approx)"', # (only approximate) + }, +); + +# add our composite tags +Image::ExifTool::AddCompositeTags('Image::ExifTool::Vorbis'); + + +#------------------------------------------------------------------------------ +# Process Vorbis Comments +# Inputs: 0) ExifTool object ref, 1) dirInfo ref, 2) tag table ref +# Returns: 1 on success, otherwise returns 0 and sets a Warning +sub ProcessComments($$$) +{ + my ($et, $dirInfo, $tagTablePtr) = @_; + my $dataPt = $$dirInfo{DataPt}; + my $dataPos = $$dirInfo{DataPos}; + my $pos = $$dirInfo{DirStart} || 0; + my $end = $$dirInfo{DirLen} ? $pos + $$dirInfo{DirLen} : length $$dataPt; + my ($num, $index); + + SetByteOrder('II'); + for (;;) { + last if $pos + 4 > $end; + my $len = Get32u($dataPt, $pos); + last if $pos + 4 + $len > $end; + my $start = $pos + 4; + my $buff = substr($$dataPt, $start, $len); + $pos = $start + $len; + my ($tag, $val); + if (defined $num) { + $buff =~ /(.*?)=(.*)/s or last; + ($tag, $val) = (uc $1, $2); + # Vorbis tag ID's are all capitals, so they may conflict with our internal tags + # --> protect against this by adding a trailing underline if necessary + $tag .= '_' if $Image::ExifTool::specialTags{$tag}; + } else { + $tag = 'vendor'; + $val = $buff; + $num = ($pos + 4 < $end) ? Get32u($dataPt, $pos) : 0; + $et->VPrint(0, " + [Vorbis comments with $num entries]\n"); + $pos += 4; + } + # add tag to table unless it exists already + unless ($$tagTablePtr{$tag}) { + my $name = ucfirst(lc($tag)); + # remove invalid characters in tag name and capitalize following letters + $name =~ s/[^\w-]+(.?)/\U$1/sg; + $name =~ s/([a-z0-9])_([a-z])/$1\U$2/g; + $et->VPrint(0, " | [adding $tag]\n"); + AddTagToTable($tagTablePtr, $tag, { Name => $name }); + } + $et->HandleTag($tagTablePtr, $tag, $et->Decode($val, 'UTF8'), + Index => $index, + DataPt => $dataPt, + DataPos => $dataPos, + Start => $start, + Size => $len, + ); + # all done if this was our last tag + $num-- or return 1; + $index = (defined $index) ? $index + 1 : 0; + } + $et->Warn('Format error in Vorbis comments'); + return 0; +} + +1; # end + +__END__ + +=head1 NAME + +Image::ExifTool::Vorbis - Read Ogg Vorbis audio meta information + +=head1 SYNOPSIS + +This module is used by Image::ExifTool + +=head1 DESCRIPTION + +This module contains definitions required by Image::ExifTool to extract meta +information from Ogg Vorbis audio headers. + +=head1 AUTHOR + +Copyright 2003-2019, Phil Harvey (phil at owl.phy.queensu.ca) + +This library is free software; you can redistribute it and/or modify it +under the same terms as Perl itself. + +=head1 REFERENCES + +=over 4 + +=item L<http://www.xiph.org/vorbis/doc/> + +=item L<http://flac.sourceforge.net/ogg_mapping.html> + +=item L<http://www.theora.org/doc/Theora.pdf> + +=back + +=head1 SEE ALSO + +L<Image::ExifTool::TagNames/Vorbis Tags>, +L<Image::ExifTool::TagNames/Ogg Tags>, +L<Image::ExifTool(3pm)|Image::ExifTool> + +=cut + diff --git a/lib/Image/ExifTool/WTV.pm b/lib/Image/ExifTool/WTV.pm new file mode 100644 index 0000000..9ba3cce --- /dev/null +++ b/lib/Image/ExifTool/WTV.pm @@ -0,0 +1,319 @@ +#------------------------------------------------------------------------------ +# File: WTV.pm +# +# Description: Read WTV meta information +# +# Revisions: 2018-05-30 - P. Harvey Created +# +# References: 1) https://wiki.multimedia.cx/index.php?title=WTV +#------------------------------------------------------------------------------ + +package Image::ExifTool::WTV; + +use strict; +use vars qw($VERSION); +use Image::ExifTool qw(:DataAccess :Utils); + +$VERSION = '1.00'; + +sub ProcessMetadata($$$); + +my %timeInfo = ( + # time looks like 100 ns intervals since 0:00 UTC Jan 1, 0001 (ref PH) + ValueConv => q{ # (719162 days from 0001:01:01 to 1970:01:01) + my $t = $val / 1e7 - 719162*24*3600; + return Image::ExifTool::ConvertUnixTime($t) . 'Z'; + }, + PrintConv => '$self->ConvertDateTime($val)', +); + +my %bool = ( PrintConv => { 0 => 'No', 1 => 'Yes' }, PrintConvColumns => 2 ); + +# WTV chunks +%Image::ExifTool::WTV::Main = ( + GROUPS => { 0 => 'WTV', 1 => 'WTV', 2 => 'Video' }, + NOTES => 'Tags found in Windows recorded TV (WTV) videos.', + # 'timeline.table.0.header.Events' (not decoded) + # 'timeline.table.0.entries.Events' (not decoded) + # 'timeline' (not decoded) + # 'table.0.header.legacy_attrib' (not decoded) + 'table.0.entries.legacy_attrib' => { + Name => 'Metdata', + SubDirectory => { TagTable => 'Image::ExifTool::WTV::Metadata' }, + }, + # 'table.0.redirector.legacy_attrib' (not decoded) + # 'table.0.header.time' (not decoded) + # 'table.0.entries.time' (not decoded) +); + +# Note: Many of these tags are similar to those found in Image::ExifTool::Microsoft::Xtra +# and Image::ExifTool::ASF::ExtendedDescr +%Image::ExifTool::WTV::Metadata = ( + GROUPS => { 0 => 'WTV', 1 => 'WTV', 2 => 'Video' }, + PROCESS_PROC => \&ProcessMetadata, + NOTES => 'ExifTool will extract any tag found, even if not in this table.', + VARS => { NO_ID => 1 }, + 'Duration' => { + Name => 'Duration', + ValueConv => '$val/1e7', + PrintConv => 'ConvertDuration($val)', + }, + 'Title' => { }, + 'WM/Genre' => 'Genre', + 'WM/Language' => 'Language', + 'WM/MediaClassPrimaryID' => 'MediaClassPrimaryID', + 'WM/MediaClassSecondaryID' => 'MediaClassSecondaryID', + 'WM/MediaCredits' => 'MediaCredits', + 'WM/MediaIsDelay' => { Name => 'MediaIsDelay', %bool }, + 'WM/MediaIsFinale' => { Name => 'MediaIsFinale', %bool }, + 'WM/MediaIsLive' => { Name => 'MediaIsLive', %bool }, + 'WM/MediaIsMovie' => { Name => 'MediaIsMovie', %bool }, + 'WM/MediaIsPremiere' => { Name => 'MediaIsPremiere', %bool }, + 'WM/MediaIsRepeat' => { Name => 'MediaIsRepeat', %bool }, + 'WM/MediaIsSAP' => { Name => 'MediaIsSAP', %bool }, + 'WM/MediaIsSport' => { Name => 'MediaIsSport', %bool }, + 'WM/MediaIsStereo' => { Name => 'MediaIsStereo', %bool, Groups => { 2 => 'Audio' } }, + 'WM/MediaIsSubtitled' => { Name => 'MediaIsSubtitled',%bool }, + 'WM/MediaIsTape' => { Name => 'MediaIsTape', %bool }, + 'WM/MediaNetworkAffiliation'=> 'MediaNetworkAffiliation', + 'WM/MediaOriginalBroadcastDateTime' => { + Name => 'MediaOriginalBroadcastDateTime', + Groups => { 2 => 'Time' }, + ValueConv => '$val =~ tr/-T/: /; $val', + PrintConv => '$self->ConvertDateTime($val)', + }, + 'WM/MediaOriginalChannel' => { Name => 'MediaOriginalChannel' }, + 'WM/MediaOriginalChannelSubNumber' => { Name => 'MediaOriginalChannelSubNumber' }, + 'WM/MediaOriginalRunTime' => { + Name => 'MediaOriginalRunTime', + ValueConv => '$val / 1e7', + PrintConv => 'ConvertDuration($val)', + }, + 'WM/MediaStationCallSign' => 'MediaStationCallSign', + 'WM/MediaStationName' => 'MediaStationName', + 'WM/MediaThumbAspectRatioX' => 'MediaThumbAspectRatioX', + 'WM/MediaThumbAspectRatioY' => 'MediaThumbAspectRatioY', + 'WM/MediaThumbHeight' => 'MediaThumbHeight', + 'WM/MediaThumbRatingAttributes' => { Name => 'MediaThumbRatingAttributes' }, + 'WM/MediaThumbRatingLevel' => 'MediaThumbRatingLevel', + 'WM/MediaThumbRatingSystem' => 'MediaThumbRatingSystem', + 'WM/MediaThumbRet' => 'MediaThumbRet', + 'WM/MediaThumbStride' => 'MediaThumbStride', + 'WM/MediaThumbTimeStamp' => { Name => 'MediaThumbTimeStamp', Notes => 'unknown units', Unknown => 1 }, + 'WM/MediaThumbWidth' => 'MediaThumbWidth', + 'WM/OriginalReleaseTime' => { + Name => 'OriginalReleaseTime', + Groups => { 2 => 'Time' }, + ValueConv => '$val=~tr/-T/: /; $val', + PrintConv => '$self->ConvertDateTime($val)', + }, + 'WM/ParentalRating' => 'ParentalRating', + 'WM/ParentalRatingReason' => 'ParentalRatingReason', + 'WM/Provider' => 'Provider', + 'WM/ProviderCopyright' => 'ProviderCopyright', + 'WM/ProviderRating' => 'ProviderRating', + 'WM/SubTitle' => 'Subtitle', + 'WM/SubTitleDescription' => 'SubtitleDescription', + 'WM/VideoClosedCaptioning' => { Name => 'VideoClosedCaptioning', %bool }, + 'WM/WMRVATSCContent' => { Name => 'ATSCContent', %bool }, + 'WM/WMRVActualSoftPostPadding' => 'ActualSoftPostPadding', + 'WM/WMRVActualSoftPrePadding' => 'ActualSoftPrePadding', + 'WM/WMRVBitrate' => { Name => 'Bitrate', Notes => 'unknown units', Unknown => 1 }, + 'WM/WMRVBrandingImageID' => 'BrandingImageID', + 'WM/WMRVBrandingName' => 'BrandingName', + 'WM/WMRVContentProtected' => { Name => 'ContentProtected', %bool }, + 'WM/WMRVContentProtectedPercent' => 'ContentProtectedPercent', + 'WM/WMRVDTVContent' => { Name => 'DTVContent', %bool }, + 'WM/WMRVEncodeTime' => { Name => 'EncodeTime', Groups => { 2 => 'Time' }, %timeInfo }, + 'WM/WMRVEndTime' => { Name => 'EndTime', Groups => { 2 => 'Time' }, %timeInfo }, + 'WM/WMRVExpirationDate' => { Name => 'ExpirationDate', Groups => { 2 => 'Time' }, %timeInfo, Unknown => 1 }, + 'WM/WMRVExpirationSpan' => { Name => 'ExpirationSpan', Notes => 'unknown units', Unknown => 1 }, + 'WM/WMRVHDContent' => { Name => 'HDContent', %bool }, + 'WM/WMRVHardPostPadding' => 'HardPostPadding', + 'WM/WMRVHardPrePadding' => 'HardPrePadding', + 'WM/WMRVInBandRatingAttributes' => 'InBandRatingAttributes', + 'WM/WMRVInBandRatingLevel' => 'InBandRatingLevel', + 'WM/WMRVInBandRatingSystem' => 'InBandRatingSystem', + 'WM/WMRVKeepUntil' => 'KeepUntil', + 'WM/WMRVOriginalSoftPostPadding'=> 'OriginalSoftPostPadding', + 'WM/WMRVOriginalSoftPrePadding' => 'OriginalSoftPrePadding', + 'WM/WMRVProgramID' => 'ProgramID', + 'WM/WMRVQuality' => 'Quality', + 'WM/WMRVRequestID' => 'RequestID', + 'WM/WMRVScheduleItemID' => 'ScheduleItemID', + 'WM/WMRVSeriesUID' => 'SeriesUID', + 'WM/WMRVServiceID' => 'ServiceID', + 'WM/WMRVWatched' => { Name => 'Watched', %bool }, +); + +#------------------------------------------------------------------------------ +# Read specified sectors from the file +# Inputs: 0) raf ref, 1) sector table ref, 2) offset in sector table, 3) sector size +# Returns: Data or undef on error +sub ReadSectors($$$$) +{ + my ($raf, $secPt, $pos, $secSize) = @_; + my ($data, $buff); + while ($pos <= length($$secPt) - 4) { + my $sec = Get32u($secPt, $pos); + return undef if $sec == 0xffff; # (just in case) + last unless $sec; # a null marks the end of the sector table + defined($data) ? ($data .= $buff) : ($data = $buff); + return undef unless $raf->Seek($sec*$secSize,0) and $raf->Read($buff,$secSize) == $secSize; + $pos += 4; + } + return defined($data) ? $data . $buff : $buff; +} + +#------------------------------------------------------------------------------ +# Process WTV metadata +# Inputs: 0) ExifTool object reference, 1) dirInfo reference, 2) tag table ref +# Returns: 1 on success +sub ProcessMetadata($$$) +{ + my ($et, $dirInfo, $tagTablePtr) = @_; + my $dataPt = $$dirInfo{DataPt}; + my $pos = 0; + my $end = length $$dataPt; + $et->VerboseDir('WTV Metadata', undef, $end); + while ($pos + 0x18 < $end) { + last unless substr($$dataPt,$pos,16) eq "\x5a\xfe\xd7\x6d\xc8\x1d\x8f\x4a\x99\x22\xfa\xb1\x1c\x38\x14\x53"; + my $fmt = Get32u($dataPt, $pos + 0x10); + my $len = Get32u($dataPt, $pos + 0x14); + my $str = ''; + $pos += 0x18; + for (;;) { + $pos + 2 > $end and $et->Warn('Corrupt metadata directory'), last; + my $ch = substr($$dataPt, $pos, 2); + $pos += 2; + last if $ch eq "\0\0"; + $str .= $ch; + } + last if $pos + $len > $end; + my $tag = $et->Decode($str, 'UCS2', undef, 'UTF8'); + my $dat = substr($$dataPt, $pos, $len); + # add tag if not already there + unless ($$tagTablePtr{$tag}) { + my $name = $tag; + $name =~ s{^(WTV_Metadata_)?WM/(WMRV)?}{}; + AddTagToTable($tagTablePtr, $tag, $name); + $et->VPrint(0, $$et{INDENT}, "[adding WTV:$name]\n"); + } + my $val; + if ($fmt==0 or $fmt==3) { # int32u or boolean32 + $val = Get32s(\$dat, 0); + } elsif ($fmt == 1) { # string + $val = $et->Decode($dat, 'UCS2'); + } elsif ($fmt == 6) { # GUID + $val = unpack('H*', $dat); + } elsif ($fmt == 4) { # int64u (date/time values use this) + $val = Get64u(\$dat, 0); + } else { + $val = $dat; + $fmt = "Unknown($fmt)"; + } + $et->HandleTag($tagTablePtr, $tag, $val, + Format => "format $fmt", + Size => length $dat, + ); + $et->VerboseDump(\$dat); + $pos += $len; + } +} + +#------------------------------------------------------------------------------ +# Extract information from a WTV video +# Inputs: 0) ExifTool object reference, 1) dirInfo reference +# Returns: 1 on success, 0 if this wasn't a valid WTV file +sub ProcessWTV($$) +{ + my ($et, $dirInfo) = @_; + my $raf = $$dirInfo{RAF}; + my $verbose = $et->Options('Verbose'); + my ($buff, $tagTablePtr, $pos, $len); + + # verify this is a valid WTV file + return 0 unless $raf->Read($buff, 0x60) == 0x60; + return 0 unless $buff =~ /^\xb7\xd8\x00\x20\x37\x49\xda\x11\xa6\x4e\x00\x07\xe9\x5e\xad\x8d/; + $et->SetFileType(); + SetByteOrder('II'); + # 0x28 - int32u: sector size? (=0x1000) (PH NC) + # 0x38 - int32u: sector number for main WTV directory (PH assume this is a sector table, NC) + # 0x58 - int32u: total number of sectors in file + my $secSize = Get32u(\$buff, 0x28); + # in case I'm wrong about this, constrain sector size to + # either 0x1000 (standard) or 0x100 (ExifTool test file) - PH + $secSize = 0x1000 unless $secSize == 0x1000 or $secSize == 0x100; + $buff = ReadSectors($raf, \$buff, 0x38, $secSize); # read the WTV directory + return 0 unless defined $buff; + $tagTablePtr = GetTagTable('Image::ExifTool::WTV::Main'); + # parse the WTV directory + $et->VerboseDir('WTV'); + for ($pos=0; $pos<length($buff)-0x28; $pos+=$len) { + unless (substr($buff,$pos,0x10) eq "\x92\xb7\x74\x91\x59\x70\x70\x44\x88\xdf\x06\x3b\x82\xcc\x21\x3d") { + $et->Warn("WTV directory wasn't at expected location") unless $pos; + last; + } + $len = Get32u(\$buff, $pos+0x10); + last if $pos + $len > length($buff); + my $n = Get32u(\$buff, $pos + 0x20); + 0x28 + $n*2 + 8 > $len and $et->Warn('WTV directory error'), last; + my $tag = $et->Decode(substr($buff,$pos+0x28,$n*2), 'UCS2', undef, 'UTF8'); + my $ptr = $pos + 0x28 + $n * 2; + my $flg = Get32u(\$buff, $ptr + 4); + if ($verbose) { + my $s = Get32s(\$buff, $ptr); + $s = sprintf('0x%x', $s) unless $s < 0; + $et->VPrint(1,"- Tag '$tag' (sector=$s, flag=$flg)"); + } + next unless $$tagTablePtr{$tag} and ($flg == 0 or $flg == 1); + my $sec = substr($buff, $ptr, 4); + my $data = ReadSectors($raf, \$sec, 0, $secSize); + last unless defined $data; + # read sectors from table if necessary (flag=1 indicates a sector table) + $data = ReadSectors($raf, \$data, 0, $secSize) if $flg == 1; + defined $data or $et->Warn("Error fetching data for $tag"), next; + $et->HandleTag($tagTablePtr, $tag, $data); + } + return 1; +} + +1; # end + +__END__ + +=head1 NAME + +Image::ExifTool::WTV - Read WTV meta information + +=head1 SYNOPSIS + +This module is used by Image::ExifTool + +=head1 DESCRIPTION + +This module contains definitions required by Image::ExifTool to read WTV +(Windows recorded TV show) videos. + +=head1 AUTHOR + +Copyright 2003-2019, Phil Harvey (phil at owl.phy.queensu.ca) + +This library is free software; you can redistribute it and/or modify it +under the same terms as Perl itself. + +=head1 REFERENCES + +=over 4 + +=item L<https://wiki.multimedia.cx/index.php?title=WTV> + +=back + +=head1 SEE ALSO + +L<Image::ExifTool::TagNames/WTV Tags>, +L<Image::ExifTool(3pm)|Image::ExifTool> + +=cut + diff --git a/lib/Image/ExifTool/WriteCanonRaw.pl b/lib/Image/ExifTool/WriteCanonRaw.pl new file mode 100644 index 0000000..abbafff --- /dev/null +++ b/lib/Image/ExifTool/WriteCanonRaw.pl @@ -0,0 +1,637 @@ +#------------------------------------------------------------------------------ +# File: WriteCanonRaw.pl +# +# Description: Write Canon RAW (CRW and CR2) meta information +# +# Revisions: 01/25/2005 - P. Harvey Created +# 09/16/2010 - PH Added ability to write XMP in CRW images +#------------------------------------------------------------------------------ +package Image::ExifTool::CanonRaw; + +use strict; +use vars qw($VERSION $AUTOLOAD %crwTagFormat); +use Image::ExifTool::Fixup; + +# map for adding directories to CRW +my %crwMap = ( + XMP => 'CanonVRD', + CanonVRD => 'Trailer', +); + +# mappings to from RAW tagID to MakerNotes tagID +# (Note: upper two bits of RawTagID are zero) +my %mapRawTag = ( + # RawTagID => Canon TagID + 0x080b => 0x07, # CanonFirmwareVersion + 0x0810 => 0x09, # OwnerName + 0x0815 => 0x06, # CanonImageType + 0x1028 => 0x03, # (unknown if no tag name specified) + 0x1029 => 0x02, # FocalLength + 0x102a => 0x04, # CanonShotInfo + 0x102d => 0x01, # CanonCameraSettings + 0x1033 => 0x0f, # CanonCustomFunctions (only verified for 10D) + 0x1038 => 0x12, # CanonAFInfo + 0x1039 => 0x13, + 0x1093 => 0x93, + 0x10a8 => 0xa8, + 0x10a9 => 0xa9, # WhiteBalanceTable + 0x10aa => 0xaa, + 0x10ae => 0xae, # ColorTemperature + 0x10b4 => 0xb4, # ColorSpace + 0x10b5 => 0xb5, + 0x10c0 => 0xc0, + 0x10c1 => 0xc1, + 0x180b => 0x0c, # SerialNumber + 0x1817 => 0x08, # FileNumber + 0x1834 => 0x10, + 0x183b => 0x15, +); +# translation from Rotation to Orientation values +my %mapRotation = ( + 0 => 1, + 90 => 6, + 180 => 3, + 270 => 8, +); + + +#------------------------------------------------------------------------------ +# Initialize buffers for building MakerNotes from RAW data +# Inputs: 0) ExifTool object reference +sub InitMakerNotes($) +{ + my $et = shift; + $$et{MAKER_NOTE_INFO} = { + Entries => { }, # directory entries keyed by tagID + ValBuff => "\0\0\0\0", # value data buffer (start with zero nextIFD pointer) + FixupTags => { }, # flags for tags with data in value buffer + }; +} + +#------------------------------------------------------------------------------ +# Build maker notes from CanonRaw information +# Inputs: 0) ExifTool object reference, 1) raw tag ID, 2) reference to tagInfo +# 3) reference to value, 4) format name, 5) count +# Notes: This will build the directory in the order the tags are found in the CRW +# file, which isn't sequential (but Canon's version isn't sequential either...) +sub BuildMakerNotes($$$$$$) +{ + my ($et, $rawTag, $tagInfo, $valuePt, $formName, $count) = @_; + + my $tagID = $mapRawTag{$rawTag} || return; + $formName or warn(sprintf "No format for tag 0x%x!\n",$rawTag), return; + # special case: ignore user comment because it gets saved in EXIF + # (and has the same raw tagID as CanonFileDescription) + return if $tagInfo and $$tagInfo{Name} eq 'UserComment'; + my $format = $Image::ExifTool::Exif::formatNumber{$formName}; + my $fsiz = $Image::ExifTool::Exif::formatSize[$format]; + my $size = length($$valuePt); + my $value; + if ($count and $size != $count * $fsiz) { + if ($size < $count * $fsiz) { + warn sprintf("Value too short for raw tag 0x%x\n",$rawTag); + return; + } + # shorten value appropriately + $size = $count * $fsiz; + $value = substr($$valuePt, 0, $size); + } else { + $count = $size / $fsiz; + $value = $$valuePt; + } + my $offsetVal; + my $makerInfo = $$et{MAKER_NOTE_INFO}; + if ($size > 4) { + my $len = length $makerInfo->{ValBuff}; + $offsetVal = Set32u($len); + $makerInfo->{ValBuff} .= $value; + # pad to an even number of bytes + $size & 0x01 and $makerInfo->{ValBuff} .= "\0"; + # set flag indicating that this tag needs a fixup + $makerInfo->{FixupTags}->{$tagID} = 1; + } else { + $offsetVal = $value; + $size < 4 and $offsetVal .= "\0" x (4 - $size); + } + $makerInfo->{Entries}->{$tagID} = Set16u($tagID) . Set16u($format) . + Set32u($count) . $offsetVal; +} + +#------------------------------------------------------------------------------ +# Finish building and save MakerNotes +# Inputs: 0) ExifTool object reference +sub SaveMakerNotes($) +{ + my $et = shift; + # save maker notes + my $makerInfo = $$et{MAKER_NOTE_INFO}; + delete $$et{MAKER_NOTE_INFO}; + my $dirEntries = $makerInfo->{Entries}; + my $numEntries = scalar(keys %$dirEntries); + my $fixup = new Image::ExifTool::Fixup; + return unless $numEntries; + # build the MakerNotes directory + my $makerNotes = Set16u($numEntries); + my $tagID; + # write the entries in proper tag order (even though Canon doesn't do this...) + foreach $tagID (sort { $a <=> $b } keys %$dirEntries) { + $makerNotes .= $$dirEntries{$tagID}; + next unless $makerInfo->{FixupTags}->{$tagID}; + # add fixup for this pointer + $fixup->AddFixup(length($makerNotes) - 4); + } + # save position of maker notes for pointer fixups + $fixup->{Shift} += length($makerNotes); + $$et{MAKER_NOTE_FIXUP} = $fixup; + $$et{MAKER_NOTE_BYTE_ORDER} = GetByteOrder(); + # add value data + $makerNotes .= $makerInfo->{ValBuff}; + # get MakerNotes tag info + my $tagTablePtr = Image::ExifTool::GetTagTable('Image::ExifTool::Exif::Main'); + my $tagInfo = $et->GetTagInfo($tagTablePtr, 0x927c, \$makerNotes); + # save the MakerNotes + $et->FoundTag($tagInfo, $makerNotes); + # save the garbage collection some work later + delete $makerInfo->{Entries}; + delete $makerInfo->{ValBuff}; + delete $makerInfo->{FixupTags}; + # also generate Orientation tag since Rotation isn't transferred from RAW info + my $rotation = $et->GetValue('Rotation', 'ValueConv'); + if (defined $rotation and defined $mapRotation{$rotation}) { + $tagInfo = $et->GetTagInfo($tagTablePtr, 0x112); + $et->FoundTag($tagInfo, $mapRotation{$rotation}); + } +} + +#------------------------------------------------------------------------------ +# Check CanonRaw information +# Inputs: 0) ExifTool object reference, 1) tagInfo hash reference, +# 2) raw value reference +# Returns: error string or undef (and may change value) on success +sub CheckCanonRaw($$$) +{ + my ($et, $tagInfo, $valPtr) = @_; + my $tagName = $$tagInfo{Name}; + if ($tagName eq 'JpgFromRaw' or $tagName eq 'ThumbnailImage') { + unless ($$valPtr =~ /^\xff\xd8/ or $et->Options('IgnoreMinorErrors')) { + return '[Minor] Not a valid image'; + } + } else { + my $format = $$tagInfo{Format}; + my $count = $$tagInfo{Count}; + unless ($format) { + my $tagType = ($$tagInfo{TagID} >> 8) & 0x38; + $format = $crwTagFormat{$tagType}; + } + $format and return Image::ExifTool::CheckValue($valPtr, $format, $count); + } + return undef; +} + +#------------------------------------------------------------------------------ +# Write CR2 file +# Inputs: 0) ExifTool ref, 1) dirInfo reference (must have read first 16 bytes) +# 2) tag table reference +# Returns: true on success +sub WriteCR2($$$) +{ + my ($et, $dirInfo, $tagTablePtr) = @_; + my $dataPt = $$dirInfo{DataPt} or return 0; + my $outfile = $$dirInfo{OutFile} or return 0; + $$dirInfo{RAF} or return 0; + + # check CR2 signature + if ($$dataPt !~ /^.{8}CR\x02\0/s) { + my ($msg, $minor); + if ($$dataPt =~ /^.{8}CR/s) { + $msg = 'Unsupported Canon RAW file. May cause problems if rewritten'; + $minor = 1; + } elsif ($$dataPt =~ /^.{8}\xba\xb0\xac\xbb/s) { + $msg = 'Can not currently write Canon 1D RAW images'; + } else { + $msg = 'Unrecognized Canon RAW file'; + } + return 0 if $et->Error($msg, $minor); + } + + # CR2 has a 16-byte header + $$dirInfo{NewDataPos} = 16; + my $newData = $et->WriteDirectory($dirInfo, $tagTablePtr); + return 0 unless defined $newData; + unless ($$dirInfo{LastIFD}) { + $et->Error("CR2 image IFD may not be deleted"); + return 0; + } + + if (length($newData)) { + # build 16 byte header for Canon RAW file + my $header = substr($$dataPt, 0, 16); + # set IFD0 pointer (may not be 16 if edited by PhotoMechanic) + Set32u(16, \$header, 4); + # last 4 bytes of header is pointer to last IFD + Set32u($$dirInfo{LastIFD}, \$header, 12); + Write($outfile, $header, $newData) or return 0; + undef $newData; # free memory + + # copy over image data now if necessary + if (ref $$dirInfo{ImageData}) { + $et->CopyImageData($$dirInfo{ImageData}, $outfile) or return 0; + delete $$dirInfo{ImageData}; + } + } + return 1; +} + +#------------------------------------------------------------------------------ +# Write CanonRaw (CRW) information +# Inputs: 0) ExifTool object reference, 1) source dirInfo reference, +# 2) tag table reference +# Returns: true on success +# Notes: Increments ExifTool CHANGED flag for each tag changed This routine is +# different from all of the other write routines because Canon RAW files are +# designed well! So it isn't necessary to buffer the data in memory before +# writing it out. Therefore this routine doesn't return the directory data as +# the rest of the Write routines do. Instead, it writes to the dirInfo +# OutFile on the fly --> much faster, efficient, and less demanding on memory! +sub WriteCanonRaw($$$) +{ + my ($et, $dirInfo, $tagTablePtr) = @_; + $et or return 1; # allow dummy access to autoload this package + my $blockStart = $$dirInfo{DirStart}; + my $blockSize = $$dirInfo{DirLen}; + my $raf = $$dirInfo{RAF} or return 0; + my $outfile = $$dirInfo{OutFile} or return 0; + my $outPos = $$dirInfo{OutPos} or return 0; + my $outBase = $outPos; + my $verbose = $et->Options('Verbose'); + my $out = $et->Options('TextOut'); + my ($buff, $tagInfo); + + # 4 bytes at end of block give directory position within block + $raf->Seek($blockStart+$blockSize-4, 0) or return 0; + $raf->Read($buff, 4) == 4 or return 0; + my $dirOffset = Get32u(\$buff,0) + $blockStart; + $raf->Seek($dirOffset, 0) or return 0; + $raf->Read($buff, 2) == 2 or return 0; + my $entries = Get16u(\$buff,0); # get number of entries in directory + # read the directory (10 bytes per entry) + $raf->Read($buff, 10 * $entries) == 10 * $entries or return 0; + my $newDir = ''; + + # get hash of new information keyed by tagID + my $newTags = $et->GetNewTagInfoHash($tagTablePtr); + + # generate list of tags to add or delete (currently, we only allow JpgFromRaw + # and ThumbnailImage, to be added or deleted from the root CanonRaw directory) + my (@addTags, %delTag); + if ($$dirInfo{Nesting} == 0) { + my $tagID; + foreach $tagID (keys %$newTags) { + my $permanent = $newTags->{$tagID}->{Permanent}; + push(@addTags, $tagID) if defined($permanent) and not $permanent; + } + } + + my $index; + for ($index=0; ; ++$index) { + my ($pt, $tag, $size, $valuePtr, $ptr, $value); + if ($index<$entries) { + $pt = 10 * $index; + $tag = Get16u(\$buff, $pt); + $size = Get32u(\$buff, $pt+2); + $valuePtr = Get32u(\$buff, $pt+6); + $ptr = $valuePtr + $blockStart; # all pointers relative to block start + } + # add any required new tags + # NOTE: can't currently add tags where value is stored in directory + if (@addTags and (not defined($tag) or $tag >= $addTags[0])) { + my $addTag = shift @addTags; + $tagInfo = $$newTags{$addTag}; + my $newVal = $et->GetNewValue($tagInfo); + if (defined $newVal) { + # pad value to an even length (Canon ImageBrowser and ZoomBrowser + # version 6.1.1 have problems with odd-sized embedded JPEG images + # even if the value is padded to maintain alignment, so do this + # before calculating the size for the directory entry) + $newVal .= "\0" if length($newVal) & 0x01; + # add new directory entry + $newDir .= Set16u($addTag) . Set32u(length($newVal)) . + Set32u($outPos - $outBase); + # write new value data + Write($outfile, $newVal) or return 0; + $outPos += length($newVal); # update current position + $verbose > 1 and print $out " + CanonRaw:$$tagInfo{Name}\n"; + ++$$et{CHANGED}; + } + # set flag to delete this tag if found later + $delTag{$addTag} = 1; + } + last unless defined $tag; # all done if no more directory entries + return 0 if $tag & 0x8000; # top bit should not be set + my $tagID = $tag & 0x3fff; # get tag ID + my $tagType = ($tag >> 8) & 0x38; # get tag type + my $valueInDir = ($tag & 0x4000); # flag for value in directory + + my $tagInfo = $et->GetTagInfo($tagTablePtr,$tagID); + my $format = $crwTagFormat{$tagType}; + my ($count, $subdir); + if ($tagInfo) { + $subdir = $$tagInfo{SubDirectory}; + $format = $$tagInfo{Format} if $$tagInfo{Format}; + $count = $$tagInfo{Count}; + } + if ($valueInDir) { + $size = 8; + $value = substr($buff, $pt+2, $size); + # set count to 1 by default for normal values in directory + $count = 1 if not defined $count and $format and + $format ne 'string' and not $subdir; + } else { + if ($tagType==0x28 or $tagType==0x30) { + # this type of tag specifies a raw subdirectory + my $name; + $tagInfo and $name = $$tagInfo{Name}; + $name or $name = sprintf("CanonRaw_0x%.4x", $tagID); + my %subdirInfo = ( + DirName => $name, + DataLen => 0, + DirStart => $ptr, + DirLen => $size, + Nesting => $$dirInfo{Nesting} + 1, + RAF => $raf, + Parent => $$dirInfo{DirName}, + OutFile => $outfile, + OutPos => $outPos, + ); + my $result = $et->WriteDirectory(\%subdirInfo, $tagTablePtr); + return 0 unless $result; + # set size and pointer for this new directory + $size = $subdirInfo{OutPos} - $outPos; + $valuePtr = $outPos - $outBase; + $outPos = $subdirInfo{OutPos}; + } else { + # verify that the value data is within this block + $valuePtr + $size <= $blockSize or return 0; + # read value from file + $raf->Seek($ptr, 0) or return 0; + $raf->Read($value, $size) == $size or return 0; + } + } + # set count from tagInfo count if necessary + if ($format and not $count) { + # set count according to format and size + my $fnum = $Image::ExifTool::Exif::formatNumber{$format}; + my $fsiz = $Image::ExifTool::Exif::formatSize[$fnum]; + $count = int($size / $fsiz); + } + # edit subdirectory if necessary + if ($tagInfo) { + if ($subdir and $$subdir{TagTable}) { + my $name = $$tagInfo{Name}; + my $newTagTable = Image::ExifTool::GetTagTable($$subdir{TagTable}); + return 0 unless $newTagTable; + my $subdirStart = 0; + #### eval Start () + $subdirStart = eval $$subdir{Start} if $$subdir{Start}; + my $dirData = \$value; + my %subdirInfo = ( + Name => $name, + DataPt => $dirData, + DataLen => $size, + DirStart => $subdirStart, + DirLen => $size - $subdirStart, + Nesting => $$dirInfo{Nesting} + 1, + RAF => $raf, + Parent => $$dirInfo{DirName}, + ); + #### eval Validate ($dirData, $subdirStart, $size) + if (defined $$subdir{Validate} and not eval $$subdir{Validate}) { + $et->Warn("Invalid $name data"); + } else { + $subdir = $et->WriteDirectory(\%subdirInfo, $newTagTable); + if (defined $subdir and length $subdir) { + if ($subdirStart) { + # add header before data directory + $value = substr($value, 0, $subdirStart) . $subdir; + } else { + $value = $subdir; + } + } + } + } elsif ($$newTags{$tagID}) { + if ($delTag{$tagID}) { + $verbose > 1 and print $out " - CanonRaw:$$tagInfo{Name}\n"; + ++$$et{CHANGED}; + next; # next since we already added this tag + } + my $oldVal; + if ($format) { + $oldVal = ReadValue(\$value, 0, $format, $count, $size); + } else { + $oldVal = $value; + } + my $nvHash = $et->GetNewValueHash($tagInfo); + if ($et->IsOverwriting($nvHash, $oldVal)) { + my $newVal = $et->GetNewValue($nvHash); + my $verboseVal; + $verboseVal = $newVal if $verbose > 1; + # convert to specified format if necessary + if (defined $newVal and $format) { + $newVal = WriteValue($newVal, $format, $count); + } + if (defined $newVal) { + $value = $newVal; + ++$$et{CHANGED}; + $et->VerboseValue("- CanonRaw:$$tagInfo{Name}", $oldVal); + $et->VerboseValue("+ CanonRaw:$$tagInfo{Name}", $verboseVal); + } + } + } + } + if ($valueInDir) { + my $len = length $value; + if ($len < 8) { + # pad with original garbage in case it contained something useful + $value .= substr($buff, $pt+2+8-$len, 8-$len); + } elsif ($len > 8) { # this shouldn't happen + warn "Value too long! -- trucated\n"; + $value = substr($value, 0, 8); + } + # create new directory entry + $newDir .= Set16u($tag) . $value; + next; # all done this entry + } + if (defined $value) { + # don't allow value to change length unless Writable is 'resize' + my $writable = $$tagInfo{Writable}; + my $diff = length($value) - $size; + if ($diff) { + if ($writable and $writable eq 'resize') { + $size += $diff; # allow size to change + } elsif ($diff > 0) { + $value .= ("\0" x $diff); + } else { + $value = substr($value, 0, $size); + } + } + # pad value if necessary to align on even-byte boundary (as per CIFF spec) + $value .= "\0" if $size & 0x01; + $valuePtr = $outPos - $outBase; + # write out value data + Write($outfile, $value) or return 0; + $outPos += length($value); # update current position in outfile + } + # create new directory entry + $newDir .= Set16u($tag) . Set32u($size) . Set32u($valuePtr); + } + # add the directory counts and offset to the directory start, + $entries = length($newDir) / 10; + $newDir = Set16u($entries) . $newDir . Set32u($outPos - $outBase); + # write directory data + Write($outfile, $newDir) or return 0; + + # update current output file position in dirInfo + $$dirInfo{OutPos} = $outPos + length($newDir); + # save outfile directory start (needed for rewriting VRD trailer) + $$dirInfo{OutDirStart} = $outPos - $outBase; + + return 1; +} + +#------------------------------------------------------------------------------ +# write Canon RAW (CRW) file +# Inputs: 0) ExifTool object reference, 1) dirInfo reference +# Returns: 1 on success, 0 if this wasn't a valid CRW file, +# or -1 if a write error occurred +sub WriteCRW($$) +{ + my ($et, $dirInfo) = @_; + my $outfile = $$dirInfo{OutFile}; + my $raf = $$dirInfo{RAF}; + my $rtnVal = 0; + my ($buff, $err, $sig); + + $raf->Read($buff,2) == 2 or return 0; + SetByteOrder($buff) or return 0; + $raf->Read($buff,4) == 4 or return 0; + $raf->Read($sig,8) == 8 or return 0; # get file signature + $sig =~ /^HEAP(CCDR|JPGM)/ or return 0; # validate signature + my $type = $1; + my $hlen = Get32u(\$buff, 0); # get header length + + if ($$et{DEL_GROUP}{MakerNotes}) { + if ($type eq 'CCDR') { + $et->Error("Can't delete MakerNotes group in CRW file"); + return 0; + } else { + ++$$et{CHANGED}; + return 1; + } + } + # make XMP the preferred group for CRW files + if ($$et{FILE_TYPE} eq 'CRW') { + $et->InitWriteDirs(\%crwMap, 'XMP'); + } + + # write header + $raf->Seek(0, 0) or return 0; + $raf->Read($buff, $hlen) == $hlen or return 0; + Write($outfile, $buff) or $err = 1; + + $raf->Seek(0, 2) or return 0; # seek to end of file + my $filesize = $raf->Tell() or return 0; + + # build directory information for main raw directory + my %dirInfo = ( + DataLen => 0, + DirStart => $hlen, + DirLen => $filesize - $hlen, + Nesting => 0, + RAF => $raf, + Parent => 'CRW', + OutFile => $outfile, + OutPos => $hlen, + ); + # process the raw directory + my $tagTablePtr = Image::ExifTool::GetTagTable('Image::ExifTool::CanonRaw::Main'); + my $success = $et->WriteDirectory(\%dirInfo, $tagTablePtr); + + my $trailPt; + while ($success) { + # check to see if trailer(s) exist(s) + my $trailInfo = Image::ExifTool::IdentifyTrailer($raf) or last; + # rewrite the trailer(s) + $buff = ''; + $$trailInfo{OutFile} = \$buff; + $success = $et->ProcessTrailers($trailInfo) or last; + $trailPt = $$trailInfo{OutFile}; + # nothing to write if trailers were deleted + undef $trailPt if length($$trailPt) < 4; + last; + } + if ($success) { + # add CanonVRD trailer if writing as a block + $trailPt = $et->AddNewTrailers($trailPt,'CanonVRD'); + if (not $trailPt and $$et{ADD_DIRS}{CanonVRD}) { + # create CanonVRD from scratch if necessary + my $outbuff = ''; + my $saveOrder = GetByteOrder(); + require Image::ExifTool::CanonVRD; + if (Image::ExifTool::CanonVRD::ProcessCanonVRD($et, { OutFile => \$outbuff }) > 0) { + $trailPt = \$outbuff; + } + SetByteOrder($saveOrder); + } + # write trailer + if ($trailPt) { + # must append DirStart pointer to end of trailer + my $newDirStart = Set32u($dirInfo{OutDirStart}); + my $len = length $$trailPt; + my $pad = ($len & 0x01) ? ' ' : ''; # add pad byte if necessary + Write($outfile, $pad, substr($$trailPt,0,$len-4), $newDirStart) or $err = 1; + } + $rtnVal = $err ? -1 : 1; + } else { + $et->Error('Error rewriting CRW file'); + } + return $rtnVal; +} + +1; # end + +__END__ + +=head1 NAME + +Image::ExifTool::WriteCanonRaw.pl - Write Canon RAW (CRW and CR2) information + +=head1 SYNOPSIS + +These routines are autoloaded by Image::ExifTool::CanonRaw. + +=head1 DESCRIPTION + +This file contains routines used by ExifTool to write Canon CRW and CR2 +files and metadata. + +=head1 NOTES + +The CRW format is a pleasure to work with. All pointer offsets are relative +to the start of the data for each directory. If TIFF/EXIF had implemented +pointers in this way, it would be MUCH easier to read and write TIFF/JPEG +files, and would lead to far fewer problems with corrupted metadata. + +=head1 AUTHOR + +Copyright 2003-2019, Phil Harvey (phil at owl.phy.queensu.ca) + +This library is free software; you can redistribute it and/or modify it +under the same terms as Perl itself. + +=head1 SEE ALSO + +L<Image::ExifTool::CanonRaw(3pm)|Image::ExifTool::CanonRaw>, +L<Image::ExifTool(3pm)|Image::ExifTool>, +L<http://owl.phy.queensu.ca/~phil/exiftool/canon_raw.html> + +=cut diff --git a/lib/Image/ExifTool/WriteExif.pl b/lib/Image/ExifTool/WriteExif.pl new file mode 100644 index 0000000..b9014d6 --- /dev/null +++ b/lib/Image/ExifTool/WriteExif.pl @@ -0,0 +1,2563 @@ +#------------------------------------------------------------------------------ +# File: WriteExif.pl +# +# Description: Write EXIF meta information +# +# Revisions: 12/13/2004 - P. Harvey Created +#------------------------------------------------------------------------------ + +package Image::ExifTool::Exif; + +use strict; +use vars qw($VERSION $AUTOLOAD @formatSize @formatName %formatNumber + %compression %photometricInterpretation %orientation); + +use Image::ExifTool::Fixup; + +# some information may be stored in different IFD's with the same meaning. +# Use this lookup to decide when we should delete information that is stored +# in another IFD when we write it to the preferred IFD. +my %crossDelete = ( + ExifIFD => 'IFD0', + IFD0 => 'ExifIFD', +); + +# mandatory tag default values +my %mandatory = ( + IFD0 => { + 0x011a => 72, # XResolution + 0x011b => 72, # YResolution + 0x0128 => 2, # ResolutionUnit (inches) + 0x0213 => 1, # YCbCrPositioning (centered) + # 0x8769 => ????, # ExifOffset + }, + IFD1 => { + 0x0103 => 6, # Compression (JPEG) + 0x011a => 72, # XResolution + 0x011b => 72, # YResolution + 0x0128 => 2, # ResolutionUnit (inches) + }, + ExifIFD => { + 0x9000 => '0231', # ExifVersion + 0x9101 => "1 2 3 0",# ComponentsConfiguration + 0xa000 => '0100', # FlashpixVersion + 0xa001 => 0xffff, # ColorSpace (uncalibrated) + # 0xa002 => ????, # ExifImageWidth + # 0xa003 => ????, # ExifImageHeight + }, + GPS => { + 0x0000 => '2 3 0 0',# GPSVersionID + }, + InteropIFD => { + 0x0002 => '0100', # InteropVersion + }, +); + +#------------------------------------------------------------------------------ +# Inverse print conversion for LensInfo +# Inputs: 0) lens info string +# Returns: PrintConvInv of string +sub ConvertLensInfo($) +{ + my $val = shift; + my @a = GetLensInfo($val, 1); # (allow unknown "?" values) + return @a ? join(' ', @a) : $val; +} + +#------------------------------------------------------------------------------ +# Get binary CFA Pattern from a text string +# Inputs: Print-converted CFA pattern (eg. '[Blue,Green][Green,Red]') +# Returns: CFA pattern as a string of numbers +sub GetCFAPattern($) +{ + my $val = shift; + my @rows = split /\]\s*\[/, $val; + @rows or warn("Rows not properly bracketed by '[]'\n"), return undef; + my @cols = split /,/, $rows[0]; + @cols or warn("Colors not separated by ','\n"), return undef; + my $ny = @cols; + my @a = (scalar(@rows), scalar(@cols)); + my %cfaLookup = (red=>0, green=>1, blue=>2, cyan=>3, magenta=>4, yellow=>5, white=>6); + my $row; + foreach $row (@rows) { + @cols = split /,/, $row; + @cols == $ny or warn("Inconsistent number of colors in each row\n"), return undef; + foreach (@cols) { + tr/ \]\[//d; # remove remaining brackets and any spaces + my $c = $cfaLookup{lc($_)}; + defined $c or warn("Unknown color '${_}'\n"), return undef; + push @a, $c; + } + } + return "@a"; +} + +#------------------------------------------------------------------------------ +# validate raw values for writing +# Inputs: 0) ExifTool ref, 1) tagInfo hash ref, 2) raw value ref +# Returns: error string or undef (and possibly changes value) on success +sub CheckExif($$$) +{ + my ($et, $tagInfo, $valPtr) = @_; + my $format = $$tagInfo{Format} || $$tagInfo{Writable} || $$tagInfo{Table}{WRITABLE}; + if (not $format or $format eq '1') { + if ($$tagInfo{Groups}{0} eq 'MakerNotes') { + return undef; # OK to have no format for makernotes + } else { + return 'No writable format'; + } + } + return Image::ExifTool::CheckValue($valPtr, $format, $$tagInfo{Count}); +} + +#------------------------------------------------------------------------------ +# encode exif ASCII/Unicode text from UTF8 or Latin +# Inputs: 0) ExifTool ref, 1) text string +# Returns: encoded string +# Note: MUST be called Raw conversion time so the EXIF byte order is known! +sub EncodeExifText($$) +{ + my ($et, $val) = @_; + # does the string contain special characters? + if ($val =~ /[\x80-\xff]/) { + my $order = $et->GetNewValue('ExifUnicodeByteOrder'); + return "UNICODE\0" . $et->Encode($val,'UTF16',$order); + } else { + return "ASCII\0\0\0$val"; + } +} + +#------------------------------------------------------------------------------ +# rebuild maker notes to properly contain all value data +# (some manufacturers put value data outside maker notes!!) +# Inputs: 0) ExifTool object ref, 1) dirInfo ref, 2) tag table ref +# Returns: new maker note data (and creates MAKER_NOTE_FIXUP), or undef on error +sub RebuildMakerNotes($$$) +{ + my ($et, $dirInfo, $tagTablePtr) = @_; + my $dirStart = $$dirInfo{DirStart}; + my $dirLen = $$dirInfo{DirLen}; + my $dataPt = $$dirInfo{DataPt}; + my $dataPos = $$dirInfo{DataPos} || 0; + my $rtnValue; + my %subdirInfo = %$dirInfo; + + delete $$et{MAKER_NOTE_FIXUP}; + + # don't need to rebuild text, BinaryData or PreviewImage maker notes + my $tagInfo = $$dirInfo{TagInfo}; + my $subdir = $$tagInfo{SubDirectory}; + my $proc = $$subdir{ProcessProc} || $$tagTablePtr{PROCESS_PROC} || \&ProcessExif; + if (($proc ne \&ProcessExif and $$tagInfo{Name} =~ /Text/) or + $proc eq \&Image::ExifTool::ProcessBinaryData or + ($$tagInfo{PossiblePreview} and $dirLen > 6 and + substr($$dataPt, $dirStart, 3) eq "\xff\xd8\xff")) + { + return substr($$dataPt, $dirStart, $dirLen); + } + my $saveOrder = GetByteOrder(); + my $loc = Image::ExifTool::MakerNotes::LocateIFD($et,\%subdirInfo); + if (defined $loc) { + my $makerFixup = $subdirInfo{Fixup} = new Image::ExifTool::Fixup; + # create new exiftool object to rewrite the directory without changing it + my $newTool = new Image::ExifTool; + $newTool->Options( + IgnoreMinorErrors => $$et{OPTIONS}{IgnoreMinorErrors}, + FixBase => $$et{OPTIONS}{FixBase}, + ); + $newTool->Init(); # must do this before calling WriteDirectory()! + # don't copy over preview image + $newTool->SetNewValue(PreviewImage => ''); + # copy all transient members over in case they are used for writing + # (Make, Model, etc) + foreach (grep /[a-z]/, keys %$et) { + $$newTool{$_} = $$et{$_}; + } + # fix base offsets if specified + $newTool->Options(FixBase => $et->Options('FixBase')); + # set GENERATE_PREVIEW_INFO flag so PREVIEW_INFO will be generated + $$newTool{GENERATE_PREVIEW_INFO} = 1; + # drop any large tags + $$newTool{DropTags} = 1; + # initialize other necessary data members + $$newTool{FILE_TYPE} = $$et{FILE_TYPE}; + $$newTool{TIFF_TYPE} = $$et{TIFF_TYPE}; + # rewrite maker notes + $rtnValue = $newTool->WriteDirectory(\%subdirInfo, $tagTablePtr); + if (defined $rtnValue and length $rtnValue) { + # add the dummy/empty preview image if necessary + if ($$newTool{PREVIEW_INFO}) { + $makerFixup->SetMarkerPointers(\$rtnValue, 'PreviewImage', length($rtnValue)); + $rtnValue .= $$newTool{PREVIEW_INFO}{Data}; + delete $$newTool{PREVIEW_INFO}; + } + # add makernote header + if ($loc) { + my $hdr = substr($$dataPt, $dirStart, $loc); + # special case: convert Pentax/Samsung DNG maker notes to JPEG style + # (in JPEG, Pentax makernotes are absolute and start with "AOC\0" for some + # models, but in DNG images they are stored in tag 0xc634 of IFD0 and + # start with either "PENTAX \0" or "SAMSUNG\0") + if ($$dirInfo{Parent} eq 'IFD0' and $hdr =~ /^(PENTAX |SAMSUNG)\0/) { + # convert to JPEG-style AOC maker notes if used by this model + # (Note: this expression also appears in Exif.pm) + if ($$et{Model} =~ /\b(K(-[57mrx]|(10|20|100|110|200)D|2000)|GX(10|20))\b/) { + $hdr =~ s/^(PENTAX |SAMSUNG)\0/AOC\0/; + # save fixup because AOC maker notes have absolute offsets + $$et{MAKER_NOTE_FIXUP} = $makerFixup; + } + } + $rtnValue = $hdr . $rtnValue; + # adjust fixup for shift in start position + $$makerFixup{Start} += length $hdr; + } + # shift offsets according to original position of maker notes, + # and relative to the makernotes Base + $$makerFixup{Shift} += $dataPos + $dirStart + + $$dirInfo{Base} - $subdirInfo{Base}; + # repair incorrect offsets if offsets were fixed + $$makerFixup{Shift} += $subdirInfo{FixedBy} || 0; + # fix up pointers to the specified offset + $makerFixup->ApplyFixup(\$rtnValue); + # save fixup information unless offsets were relative + unless ($subdirInfo{Relative}) { + # set shift so offsets are all relative to start of maker notes + $$makerFixup{Shift} -= $dataPos + $dirStart; + $$et{MAKER_NOTE_FIXUP} = $makerFixup; # save fixup for later + } + } + } + SetByteOrder($saveOrder); + + return $rtnValue; +} + +#------------------------------------------------------------------------------ +# Sort IFD directory entries +# Inputs: 0) data reference, 1) directory start, 2) number of entries, +# 3) flag to treat 0 as a valid tag ID (as opposed to an empty IFD entry) +sub SortIFD($$$;$) +{ + my ($dataPt, $dirStart, $numEntries, $allowZero) = @_; + my ($index, %entries); + # split the directory into separate entries + for ($index=0; $index<$numEntries; ++$index) { + my $entry = $dirStart + 2 + 12 * $index; + my $tagID = Get16u($dataPt, $entry); + my $entryData = substr($$dataPt, $entry, 12); + # silly software can pad directories with zero entries -- put these at the end + $tagID = 0x10000 unless $tagID or $index == 0 or $allowZero; + # add new entry (allow for duplicate tag ID's, which shouldn't normally happen) + if ($entries{$tagID}) { + $entries{$tagID} .= $entryData; + } else { + $entries{$tagID} = $entryData; + } + } + # sort the directory entries + my @sortedTags = sort { $a <=> $b } keys %entries; + # generate the sorted IFD + my $newDir = ''; + foreach (@sortedTags) { + $newDir .= $entries{$_}; + } + # replace original directory with new, sorted one + substr($$dataPt, $dirStart + 2, 12 * $numEntries) = $newDir; +} + +#------------------------------------------------------------------------------ +# Validate IFD entries (strict validation to test possible chained IFD's) +# Inputs: 0) dirInfo ref (must have RAF set), 1) optional DirStart +# Returns: true if IFD looks OK +sub ValidateIFD($;$) +{ + my ($dirInfo, $dirStart) = @_; + my $raf = $$dirInfo{RAF} or return 0; + my $base = $$dirInfo{Base}; + $dirStart = $$dirInfo{DirStart} || 0 unless defined $dirStart; + my $offset = $dirStart + ($$dirInfo{DataPos} || 0); + my ($buff, $index); + $raf->Seek($offset + $base, 0) and $raf->Read($buff,2) == 2 or return 0; + my $numEntries = Get16u(\$buff,0); + $numEntries > 1 and $numEntries < 64 or return 0; + my $len = 12 * $numEntries; + $raf->Read($buff, $len) == $len or return 0; + my $lastID = -1; + for ($index=0; $index<$numEntries; ++$index) { + my $entry = 12 * $index; + my $tagID = Get16u(\$buff, $entry); + $tagID > $lastID or $$dirInfo{AllowOutOfOrderTags} or return 0; + my $format = Get16u(\$buff, $entry+2); + $format > 0 and $format <= 13 or return 0; + my $count = Get32u(\$buff, $entry+4); + $count > 0 or return 0; + $lastID = $tagID; + } + return 1; +} + +#------------------------------------------------------------------------------ +# Get sorted list of offsets used in IFD +# Inputs: 0) data ref, 1) directory start, 2) dataPos, 3) IFD entries, 4) tag table ref +# Returns: 0) sorted list of offsets (only offsets after the end of the IFD) +# 1) hash of list indices keyed by offset value +# Notes: This is used in a patch to fix the count for tags in Kodak SubIFD3 +sub GetOffList($$$$$) +{ + my ($dataPt, $dirStart, $dataPos, $numEntries, $tagTablePtr) = @_; + my $ifdEnd = $dirStart + 2 + 12 * $numEntries + $dataPos; + my ($index, $offset, %offHash); + for ($index=0; $index<$numEntries; ++$index) { + my $entry = $dirStart + 2 + 12 * $index; + my $format = Get16u($dataPt, $entry + 2); + next if $format < 1 or $format > 13; + my $count = Get16u($dataPt, $entry + 4); + my $size = $formatSize[$format] * $count; + if ($size <= 4) { + my $tagID = Get16u($dataPt, $entry); + next unless ref $$tagTablePtr{$tagID} eq 'HASH' and $$tagTablePtr{$tagID}{FixCount}; + } + my $offset = Get16u($dataPt, $entry + 8); + $offHash{$offset} = 1 if $offset >= $ifdEnd; + } + # set offset hash values to indices in list + my @offList = sort keys %offHash; + $index = 0; + foreach $offset (@offList) { + $offHash{$offset} = $index++; + } + return(\@offList, \%offHash); +} + +#------------------------------------------------------------------------------ +# Update TIFF_END member if defined +# Inputs: 0) ExifTool ref, 1) end of valid TIFF data +sub UpdateTiffEnd($$) +{ + my ($et, $end) = @_; + if (defined $$et{TIFF_END} and + $$et{TIFF_END} < $end) + { + $$et{TIFF_END} = $end; + } +} + +#------------------------------------------------------------------------------ +# Validate image data size +# Inputs: 0) ExifTool ref, 1) validate info hash ref, +# 2) flag to issue error (ie. we're writing) +# - issues warning or error if problems found +sub ValidateImageData($$$;$) +{ + local $_; + my ($et, $vInfo, $dirName, $errFlag) = @_; + + # determine the expected size of the image data for an uncompressed image + # (0x102 BitsPerSample, 0x103 Compression and 0x115 SamplesPerPixel + # all default to a value of 1 if they don't exist) + if ((not defined $$vInfo{0x103} or $$vInfo{0x103} eq '1') and + $$vInfo{0x100} and $$vInfo{0x101} and ($$vInfo{0x117} or $$vInfo{0x145})) + { + my $samplesPerPix = $$vInfo{0x115} || 1; + my @bitsPerSample = $$vInfo{0x102} ? split(' ',$$vInfo{0x102}) : (1) x $samplesPerPix; + my $byteCountInfo = $$vInfo{0x117} || $$vInfo{0x145}; + my $byteCounts = $$byteCountInfo[1]; + my $totalBytes = 0; + $totalBytes += $_ foreach split ' ', $byteCounts; + my $minor; + $minor = 1 if $$et{DOC_NUM} or $$et{FILE_TYPE} ne 'TIFF'; + unless (@bitsPerSample == $samplesPerPix) { + # (just a warning for this problem) + my $s = $samplesPerPix eq '1' ? '' : 's'; + $et->Warn("$dirName BitsPerSample should have $samplesPerPix value$s", $minor); + push @bitsPerSample, $bitsPerSample[0] while @bitsPerSample < $samplesPerPix; + foreach (@bitsPerSample) { + $et->WarnOnce("$dirName BitsPerSample values are different", $minor) if $_ ne $bitsPerSample[0]; + $et->WarnOnce("Invalid $dirName BitsPerSample value", $minor) if $_ < 1 or $_ > 32; + } + } + my $bitsPerPixel = 0; + $bitsPerPixel += $_ foreach @bitsPerSample; + my $expectedBytes = int(($$vInfo{0x100} * $$vInfo{0x101} * $bitsPerPixel + 7) / 8); + if ($expectedBytes != $totalBytes and + # (this problem seems normal for certain types of RAW files...) + $$et{TIFF_TYPE} !~ /^(K25|KDC|MEF|ORF|SRF)$/) + { + my ($adj, $minor); + if ($expectedBytes > $totalBytes) { + $adj = 'Under'; # undersized is a bigger problem because we may lose data + $minor = 0 unless $errFlag; + } else { + $adj = 'Over'; + $minor = 1; + } + my $msg = "${adj}sized $dirName $$byteCountInfo[0]{Name} ($totalBytes bytes, but expected $expectedBytes)"; + if (not defined $minor) { + # this is a serious error if we are writing the file and there + # is a chance that we may not copy all of the image data + # (but make it minor to allow the file to be written anyway) + $et->Error($msg, 1); + } else { + $et->Warn($msg, $minor); + } + } + } +} + +#------------------------------------------------------------------------------ +# Handle error while writing EXIF +# Inputs: 0) ExifTool ref, 1) error string, 2) tag table ref +# Returns: undef on fatal error, or '' if minor error is ignored +sub ExifErr($$$) +{ + my ($et, $errStr, $tagTablePtr) = @_; + # MakerNote errors are minor by default + my $minor = ($$tagTablePtr{GROUPS}{0} eq 'MakerNotes'); + if ($$tagTablePtr{VARS} and $$tagTablePtr{VARS}{MINOR_ERRORS}) { + $et->Warn("$errStr. IFD dropped.") and return '' if $minor; + $minor = 1; + } + return undef if $et->Error($errStr, $minor); + return ''; +} + +#------------------------------------------------------------------------------ +# Read/Write IFD with TIFF-like header (used by DNG 1.2) +# Inputs: 0) ExifTool object ref, 1) dirInfo ref, 2) tag table ref +# Returns: Reading: 1 on success, otherwise returns 0 and sets a Warning +# Writing: new data block or undef on error +sub ProcessTiffIFD($$$) +{ + my ($et, $dirInfo, $tagTablePtr) = @_; + $et or return 1; # allow dummy access + my $raf = $$dirInfo{RAF}; + my $base = $$dirInfo{Base} || 0; + my $dirName = $$dirInfo{DirName}; + my $magic = $$dirInfo{Subdir}{Magic} || 0x002a; + my $buff; + + # structured with a TIFF-like header and relative offsets + $raf->Seek($base, 0) and $raf->Read($buff, 8) == 8 or return 0; + unless (SetByteOrder(substr($buff,0,2)) and Get16u(\$buff, 2) == $magic) { + my $msg = "Invalid $dirName header"; + if ($$dirInfo{IsWriting}) { + $et->Error($msg); + return undef; + } else { + $et->Warn($msg); + return 0; + } + } + my $offset = Get32u(\$buff, 4); + my %dirInfo = ( + DirName => $$dirInfo{DirName}, + Parent => $$dirInfo{Parent}, + Base => $base, + DataPt => \$buff, + DataLen => length $buff, + DataPos => 0, + DirStart => $offset, + DirLen => length($buff) - $offset, + RAF => $raf, + NewDataPos => 8, + ); + if ($$dirInfo{IsWriting}) { + # rewrite the Camera Profile IFD + my $newDir = WriteExif($et, \%dirInfo, $tagTablePtr); + # don't add header if error writing directory ($newDir is undef) + # or if directory is being deleted ($newDir is empty) + return $newDir unless $newDir; + # return directory with TIFF-like header + return GetByteOrder() . Set16u($magic) . Set32u(8) . $newDir; + } + if ($$et{HTML_DUMP}) { + my $tip = sprintf("Byte order: %s endian\nIdentifier: 0x%.4x\n%s offset: 0x%.4x", + (GetByteOrder() eq 'II') ? 'Little' : 'Big', $magic, $dirName, $offset); + $et->HDump($base, 8, "$dirName header", $tip, 0); + } + return ProcessExif($et, \%dirInfo, $tagTablePtr); +} + +#------------------------------------------------------------------------------ +# Write EXIF directory +# Inputs: 0) ExifTool object ref, 1) source dirInfo ref, 2) tag table ref +# Returns: Exif data block (may be empty if no Exif data) or undef on error +# Notes: Increments ExifTool CHANGED flag for each tag changed. Also updates +# TIFF_END if defined with location of end of original TIFF image. +# Returns IFD data in the following order: +# 1. IFD0 directory followed by its data +# 2. SubIFD directory followed by its data, thumbnail and image +# 3. GlobalParameters, EXIF, GPS, Interop IFD's each with their data +# 4. IFD1,IFD2,... directories each followed by their data +# 5. Thumbnail and/or image data for each IFD, with IFD0 image last +sub WriteExif($$$) +{ + my ($et, $dirInfo, $tagTablePtr) = @_; + $et or return 1; # allow dummy access to autoload this package + my $origDirInfo = $dirInfo; # save original dirInfo + my $dataPt = $$dirInfo{DataPt}; + unless ($dataPt) { + my $emptyData = ''; + $dataPt = \$emptyData; + } + my $dataPos = $$dirInfo{DataPos} || 0; + my $dirStart = $$dirInfo{DirStart} || 0; + my $dataLen = $$dirInfo{DataLen} || length($$dataPt); + my $dirLen = $$dirInfo{DirLen} || ($dataLen - $dirStart); + my $base = $$dirInfo{Base} || 0; + my $firstBase = $base; + my $raf = $$dirInfo{RAF}; + my $dirName = $$dirInfo{DirName} || 'unknown'; + my $fixup = $$dirInfo{Fixup} || new Image::ExifTool::Fixup; + my $imageDataFlag = $$dirInfo{ImageData} || ''; + my $verbose = $et->Options('Verbose'); + my $out = $et->Options('TextOut'); + my ($nextIfdPos, %offsetData, $inMakerNotes); + my (@offsetInfo, %validateInfo, %xDelete, $strEnc); + my $deleteAll = 0; + my $newData = ''; # initialize buffer to receive new directory data + my @imageData; # image data blocks to copy later if requested + my $name = $$dirInfo{Name}; + $name = $dirName unless $name and $dirName eq 'MakerNotes' and $name !~ /^MakerNote/; + + # set encoding for strings + $strEnc = $et->Options('CharsetEXIF') if $$tagTablePtr{GROUPS}{0} eq 'EXIF'; + + # allow multiple IFD's in IFD0-IFD1-IFD2... chain + $$dirInfo{Multi} = 1 if $dirName =~ /^(IFD0|SubIFD)$/ and not defined $$dirInfo{Multi}; + $inMakerNotes = 1 if $$tagTablePtr{GROUPS}{0} eq 'MakerNotes'; + my $ifd; + +#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +# loop through each IFD +# + for ($ifd=0; ; ++$ifd) { # loop through multiple IFD's + + # make sure that Compression and SubfileType are defined for this IFD (for Condition's) + $$et{Compression} = $$et{SubfileType} = ''; + + # save pointer to start of this IFD within the newData + my $newStart = length($newData); + my @subdirs; # list of subdirectory data and tag table pointers + # determine if directory is contained within our data + my $mustRead; + if ($dirStart < 0 or $dirStart > $dataLen-2) { + $mustRead = 1; + } elsif ($dirLen > 2) { + my $len = 2 + 12 * Get16u($dataPt, $dirStart); + $mustRead = 1 if $dirStart + $len > $dataLen; + } + # read IFD from file if necessary + if ($mustRead) { + if ($raf) { + # read the count of entries in this IFD + my $offset = $dirStart + $dataPos; + my ($buff, $buf2); + unless ($raf->Seek($offset + $base, 0) and $raf->Read($buff,2) == 2) { + return ExifErr($et, "Bad IFD or truncated file in $name", $tagTablePtr); + } + my $len = 12 * Get16u(\$buff,0); + # (also read next IFD pointer if available) + unless ($raf->Read($buf2, $len+4) >= $len) { + return ExifErr($et, "Error reading $name", $tagTablePtr); + } + $buff .= $buf2; + # make copy of dirInfo since we're going to modify it + my %newDirInfo = %$dirInfo; + $dirInfo = \%newDirInfo; + # update directory parameters for the newly loaded IFD + $dataPt = $$dirInfo{DataPt} = \$buff; + $dirStart = $$dirInfo{DirStart} = 0; + $dataPos = $$dirInfo{DataPos} = $offset; + $dataLen = $$dirInfo{DataLen} = length $buff; + $dirLen = $$dirInfo{DirLen} = $dataLen; + # only account for nextIFD pointer if we are going to use it + $len += 4 if $dataLen==$len+6 and ($$dirInfo{Multi} or $buff =~ /\0{4}$/); + UpdateTiffEnd($et, $offset+$base+2+$len); + } elsif ($dirLen) { + # error if we can't load IFD (unless we are creating + # from scratch, in which case dirLen will be zero) + my $str = $et->Options('IgnoreMinorErrors') ? 'Deleted bad' : 'Bad'; + $et->Error("$str $name directory", 1); + } + } + my ($index, $dirEnd, $numEntries); + if ($dirStart + 4 < $dataLen) { + $numEntries = Get16u($dataPt, $dirStart); + $dirEnd = $dirStart + 2 + 12 * $numEntries; + if ($dirEnd > $dataLen) { + return ExifErr($et, "Truncated $name directory", $tagTablePtr); + } + # sort entries if necessary (but not in maker notes IFDs) + unless ($inMakerNotes) { + my $lastID = -1; + for ($index=0; $index<$numEntries; ++$index) { + my $tagID = Get16u($dataPt, $dirStart + 2 + 12 * $index); + # check for proper sequence (but ignore null entries at end) + if ($tagID < $lastID and ($tagID or $$tagTablePtr{0})) { + SortIFD($dataPt, $dirStart, $numEntries, $$tagTablePtr{0}); + $et->Warn("Entries in $name were out of sequence. Fixed.",1); + last; + } + $lastID = $tagID; + } + } + } else { + $numEntries = 0; + $dirEnd = $dirStart; + } + + # loop through new values and accumulate all information for this IFD + my (%set, %mayDelete, $tagInfo); + my $wrongDir = $crossDelete{$dirName}; + my @newTagInfo = $et->GetNewTagInfoList($tagTablePtr); + foreach $tagInfo (@newTagInfo) { + my $tagID = $$tagInfo{TagID}; + # must evaluate Condition later when we have all DataMember's available + $set{$tagID} = (ref $$tagTablePtr{$tagID} eq 'ARRAY' or $$tagInfo{Condition}) ? '' : $tagInfo; + } + + # fix base offsets (some cameras incorrectly write maker notes in IFD0) + if ($dirName eq 'MakerNotes' and $$dirInfo{Parent} =~ /^(ExifIFD|IFD0)$/ and + $$et{TIFF_TYPE} !~ /^(ARW|SR2)$/ and not $$et{LeicaTrailerPos} and + Image::ExifTool::MakerNotes::FixBase($et, $dirInfo)) + { + # update local variables from fixed values + $base = $$dirInfo{Base}; + $dataPos = $$dirInfo{DataPos}; + # changed if ForceWrite tag was was set to "FixBase" + ++$$et{CHANGED} if $$et{FORCE_WRITE}{FixBase}; + if ($$et{TIFF_TYPE} eq 'SRW' and $$et{Make} eq 'SAMSUNG' and $$et{Model} eq 'EK-GN120') { + $et->Error("EK-GN120 SRW files are too buggy to write"); + } + } + + # initialize variables to handle mandatory tags + my $mandatory = $mandatory{$dirName}; + my ($allMandatory, $addMandatory); + if ($mandatory) { + # use X/Y resolution values from JFIF if available + if ($dirName eq 'IFD0' and defined $$et{JFIFYResolution}) { + my %ifd0Vals = %$mandatory; + $ifd0Vals{0x011a} = $$et{JFIFXResolution}; + $ifd0Vals{0x011b} = $$et{JFIFYResolution}; + $ifd0Vals{0x0128} = $$et{JFIFResolutionUnit} + 1; + $mandatory = \%ifd0Vals; + } + $allMandatory = $addMandatory = 0; # initialize to zero + # add mandatory tags if creating a new directory + unless ($numEntries) { + foreach (keys %$mandatory) { + defined $set{$_} or $set{$_} = $$tagTablePtr{$_}; + } + } + } else { + undef $deleteAll; # don't remove directory (no mandatory entries) + } + my ($addDirs, @newTags); + if ($inMakerNotes) { + $addDirs = { }; # can't currently add new directories in MakerNotes + # allow non-permanent makernotes tags to be added + # (note: we may get into trouble if there are too many of these + # because we allow out-of-order tags in MakerNote IFD's but our + # logic to add new tags relies on ordered entries) + foreach (keys %set) { + next unless $set{$_}; + my $perm = $set{$_}{Permanent}; + push @newTags, $_ if defined $perm and not $perm; + } + @newTags = sort { $a <=> $b } @newTags if @newTags > 1; + } else { + # get a hash of directories we will be writing in this one + $addDirs = $et->GetAddDirHash($tagTablePtr, $dirName); + # make a union of tags & dirs (can set whole dirs, like MakerNotes) + my %allTags = ( %set, %$addDirs ); + # make sorted list of new tags to be added + @newTags = sort { $a <=> $b } keys(%allTags); + } + my $dirBuff = ''; # buffer for directory data + my $valBuff = ''; # buffer for value data + my @valFixups; # list of fixups for offsets in valBuff + # fixup for offsets in dirBuff + my $dirFixup = new Image::ExifTool::Fixup; + my $entryBasedFixup; + my $lastTagID = -1; + my ($oldInfo, $oldFormat, $oldFormName, $oldCount, $oldSize, $oldValue, $oldImageData); + my ($readFormat, $readFormName, $readCount); # format for reading old value(s) + my ($entry, $valueDataPt, $valueDataPos, $valueDataLen, $valuePtr, $valEnd); + my ($offList, $offHash, $ignoreCount, $fixCount); + my $oldID = -1; + my $newID = -1; + + # patch for Canon EOS 40D firmware 1.0.4 bug (incorrect directory counts) + if ($inMakerNotes and $$et{Model} eq 'Canon EOS 40D') { + my $fmt = Get16u($dataPt, $dirStart + 2 + 12 * ($numEntries - 1) + 2); + if ($fmt < 1 or $fmt > 13) { + # adjust the number of directory entries + --$numEntries; + $dirEnd -= 12; + $ignoreCount = 1; + } + } +#.............................................................................. +# loop through entries in new directory +# + $index = 0; +Entry: for (;;) { + + if (defined $oldID and $oldID == $newID) { +# +# read next entry from existing directory +# + if ($index < $numEntries) { + $entry = $dirStart + 2 + 12 * $index; + $oldID = Get16u($dataPt, $entry); + $readFormat = $oldFormat = Get16u($dataPt, $entry+2); + $readCount = $oldCount = Get32u($dataPt, $entry+4); + undef $oldImageData; + if ($oldFormat < 1 or $oldFormat > 13) { + my $msg = "Bad format ($oldFormat) for $name entry $index"; + # patch to preserve invalid directory entries in SubIFD3 of + # various Kodak Z-series cameras (Z812, Z1085IS, Z1275) + # and some Sony cameras such as the DSC-P10 + if ($dirName eq 'MakerNotes' and (($$et{Make}=~/KODAK/i and + $$dirInfo{Name} and $$dirInfo{Name} eq 'SubIFD3') or + ($numEntries == 12 and $$et{Make} eq 'SONY' and $index >= 8))) + { + $dirBuff .= substr($$dataPt, $entry, 12); + ++$index; + $newID = $oldID; # we wrote this + $et->Warn($msg, 1); + next; + } + # don't write out null directory entry + if ($oldFormat==0 and $index and $oldCount==0) { + $ignoreCount = ($ignoreCount || 0) + 1; + # must keep same directory size to avoid messing up our fixed offsets + $dirBuff .= ("\0" x 12) if $$dirInfo{FixBase}; + ++$index; + $newID = $oldID; # pretend we wrote this + next; + } + return ExifErr($et, $msg, $tagTablePtr); + } + $readFormName = $oldFormName = $formatName[$oldFormat]; + $valueDataPt = $dataPt; + $valueDataPos = $dataPos; + $valueDataLen = $dataLen; + $valuePtr = $entry + 8; + # try direct method first for speed + $oldInfo = $$tagTablePtr{$oldID}; + if (ref $oldInfo ne 'HASH' or $$oldInfo{Condition}) { + # must get unknown tags too + # (necessary so we don't miss a tag we want to Drop) + my $unk = $et->Options(Unknown => 1); + $oldInfo = $et->GetTagInfo($tagTablePtr, $oldID); + $et->Options(Unknown => $unk); + } + # patch incorrect count in Kodak SubIFD3 tags + if ($oldCount < 2 and $oldInfo and $$oldInfo{FixCount}) { + $offList or ($offList, $offHash) = GetOffList($dataPt, $dirStart, $dataPos, + $numEntries, $tagTablePtr); + my $i = $$offHash{Get32u($dataPt, $valuePtr)}; + if (defined $i and $i < $#$offList) { + $oldCount = int(($$offList[$i+1] - $$offList[$i]) / $formatSize[$oldFormat]); + $fixCount = ($fixCount || 0) + 1 if $oldCount != $readCount; + } + } + $oldSize = $oldCount * $formatSize[$oldFormat]; + my $readFromFile; + if ($oldSize > 4) { + $valuePtr = Get32u($dataPt, $valuePtr); + # fix valuePtr if necessary + if ($$dirInfo{FixOffsets}) { + $valEnd or $valEnd = $dataPos + $dirStart + 2 + 12 * $numEntries + 4; + my ($tagID, $size, $wFlag) = ($oldID, $oldSize, 1); + #### eval FixOffsets ($valuePtr, $valEnd, $size, $tagID, $wFlag) + eval $$dirInfo{FixOffsets}; + unless (defined $valuePtr) { + unless ($$et{DropTags}) { + my $tagStr = $oldInfo ? $$oldInfo{Name} : sprintf("tag 0x%.4x",$oldID); + return undef if $et->Error("Bad $name offset for $tagStr", $inMakerNotes); + } + ++$index; $oldID = $newID; next; # drop this tag + } + } + # offset shouldn't point into TIFF or IFD header + my $suspect = ($valuePtr < 8); + # convert offset to pointer in $$dataPt + if ($$dirInfo{EntryBased} or (ref $$tagTablePtr{$oldID} eq 'HASH' and + $$tagTablePtr{$oldID}{EntryBased})) + { + $valuePtr += $entry; + } else { + $valuePtr -= $dataPos; + } + # value shouldn't overlap our directory + $suspect = 1 if $valuePtr < $dirEnd and $valuePtr+$oldSize > $dirStart; + # get value by seeking in file if we are allowed + if ($valuePtr < 0 or $valuePtr+$oldSize > $dataLen) { + my ($pos, $tagStr, $invalidPreview, $tmpInfo, $leicaTrailer); + if ($oldInfo) { + $tagStr = $$oldInfo{Name}; + $leicaTrailer = $$oldInfo{LeicaTrailer}; + } elsif (defined $oldInfo) { + $tmpInfo = $et->GetTagInfo($tagTablePtr, $oldID, \ '', $oldFormName, $oldCount); + if ($tmpInfo) { + $tagStr = $$tmpInfo{Name}; + $leicaTrailer = $$tmpInfo{LeicaTrailer}; + } + } + $tagStr or $tagStr = sprintf("tag 0x%.4x",$oldID); + # allow PreviewImage to run outside EXIF segment in JPEG images + if (not $raf) { + if ($tagStr eq 'PreviewImage') { + $raf = $$et{RAF}; + if ($raf) { + $pos = $raf->Tell(); + if ($oldInfo and $$oldInfo{ChangeBase}) { + # adjust base offset for this tag only + #### eval ChangeBase ($dirStart,$dataPos) + my $newBase = eval $$oldInfo{ChangeBase}; + $valuePtr += $newBase; + } + } else { + $invalidPreview = 1; + } + } elsif ($leicaTrailer) { + # save information about Leica makernote trailer + $$et{LeicaTrailer} = { + TagInfo => $oldInfo || $tmpInfo, + Offset => $base + $valuePtr + $dataPos, + Size => $oldSize, + Fixup => new Image::ExifTool::Fixup, + }, + $invalidPreview = 2; + # remove SubDirectory to prevent processing (for now) + my %copy = %{$oldInfo || $tmpInfo}; + delete $copy{SubDirectory}; + delete $copy{MakerNotes}; + $oldInfo = \%copy; + } + } + if ($oldSize > BINARY_DATA_LIMIT and $$origDirInfo{ImageData} and + (not defined $oldInfo or ($oldInfo and + (not $$oldInfo{SubDirectory} or $$oldInfo{ReadFromRAF})))) + { + # copy huge data blocks later instead of loading into memory + $oldValue = ''; # dummy empty value + # copy this value later unless writing a new value + unless (defined $set{$oldID}) { + my $pad = $oldSize & 0x01 ? 1 : 0; + # save block information to copy later (set directory offset later) + $oldImageData = [$base+$valuePtr+$dataPos, $oldSize, $pad]; + } + } elsif ($raf) { + my $success = ($raf->Seek($base+$valuePtr+$dataPos, 0) and + $raf->Read($oldValue, $oldSize) == $oldSize); + if (defined $pos) { + $raf->Seek($pos, 0); + undef $raf; + # (sony A700 has 32-byte header on PreviewImage) + unless ($success and $oldValue =~ /^(\xff\xd8\xff|(.|.{33})\xd8\xff\xdb)/s) { + $invalidPreview = 1; + $success = 1; # continue writing directory anyway + } + } + unless ($success) { + return undef if $et->Error("Error reading value for $name entry $index", $inMakerNotes); + ++$index; $oldID = $newID; next; # drop this tag + } + } elsif (not $invalidPreview) { + return undef if $et->Error("Bad $name offset for $tagStr", $inMakerNotes); + ++$index; $oldID = $newID; next; # drop this tag + } + if ($invalidPreview) { + # set value for invalid preview + if ($$et{FILE_TYPE} eq 'JPEG') { + # define dummy value for preview (or Leica MakerNote) to write later + # (value must be larger than 4 bytes to generate PREVIEW_INFO, + # and an even number of bytes so it won't be padded) + $oldValue = 'LOAD_PREVIEW'; + } else { + $oldValue = 'none'; + $oldSize = length $oldValue; + } + $valuePtr = 0; + } else { + UpdateTiffEnd($et, $base+$valuePtr+$dataPos+$oldSize); + } + # update pointers for value just read from file + $valueDataPt = \$oldValue; + $valueDataPos = $valuePtr + $dataPos; + $valueDataLen = $oldSize; + $valuePtr = 0; + $readFromFile = 1; + } + if ($suspect) { + my $tagStr = $oldInfo ? $$oldInfo{Name} : sprintf('tag 0x%.4x', $oldID); + my $str = "Suspicious $name offset for $tagStr"; + if ($inMakerNotes) { + $et->Warn($str, 1); + } else { + return undef if $et->Error($str, 1); + } + } + } + # read value if we haven't already + $oldValue = substr($$valueDataPt, $valuePtr, $oldSize) unless $readFromFile; + # get tagInfo using value if necessary + if (defined $oldInfo and not $oldInfo) { + my $unk = $et->Options(Unknown => 1); + $oldInfo = $et->GetTagInfo($tagTablePtr, $oldID, \$oldValue, $oldFormName, $oldCount); + $et->Options(Unknown => $unk); + # now that we have the value, we can resolve the Condition to finally + # determine whether we want to delete this tag or not + if ($mayDelete{$oldID} and $oldInfo and (not @newTags or $newTags[0] != $oldID)) { + my $nvHash = $et->GetNewValueHash($oldInfo, $dirName); + if (not $nvHash and $wrongDir) { + # delete from wrong directory if necessary + $nvHash = $et->GetNewValueHash($oldInfo, $wrongDir); + $nvHash and $xDelete{$oldID} = 1; + } + if ($nvHash) { + # we want to delete this tag after all, so insert it into our list + $set{$oldID} = $oldInfo; + unshift @newTags, $oldID; + } + } + } + # make sure we are handling the 'ifd' format properly + if (($oldFormat == 13 or $oldFormat == 18) and + (not $oldInfo or not $$oldInfo{SubIFD})) + { + my $str = sprintf('%s tag 0x%.4x IFD format not handled', $name, $oldID); + $et->Error($str, $inMakerNotes); + } + # override format we use to read the value if specified + if ($oldInfo) { + # check for tags which must be integers + if (($$oldInfo{IsOffset} or $$oldInfo{SubIFD}) and + not $intFormat{$oldFormName}) + { + $et->Error("Invalid format ($oldFormName) for $name $$oldInfo{Name}", $inMakerNotes); + ++$index; $oldID = $newID; next; # drop this tag + } + if ($$oldInfo{Drop} and $$et{DropTags} and + ($$oldInfo{Drop} == 1 or $$oldInfo{Drop} < $oldSize)) + { + ++$index; $oldID = $newID; next; # drop this tag + } + if ($$oldInfo{Format}) { + $readFormName = $$oldInfo{Format}; + $readFormat = $formatNumber{$readFormName}; + unless ($readFormat) { + # we aren't reading in a standard EXIF format, so rewrite in old format + $readFormName = $oldFormName; + $readFormat = $oldFormat; + } + if ($$oldInfo{FixedSize}) { + $oldSize = $$oldInfo{FixedSize} if $$oldInfo{FixedSize}; + $oldValue = substr($$valueDataPt, $valuePtr, $oldSize); + } + # adjust number of items to read if format size changed + $readCount = $oldSize / $formatSize[$readFormat]; + } + } + if ($oldID <= $lastTagID and not $inMakerNotes) { + my $str = $oldInfo ? "$$oldInfo{Name} tag" : sprintf('tag 0x%x',$oldID); + if ($oldID == $lastTagID) { + $et->Warn("Duplicate $str in $name"); + # put this tag back into the newTags list if necessary + unshift @newTags, $oldID if defined $set{$oldID}; + } else { + $et->Warn("\u$str out of sequence in $name"); + } + } + $lastTagID = $oldID; + ++$index; # increment index for next time + } else { + undef $oldID; # no more existing entries + } + } +# +# write out all new tags, up to and including this one +# + $newID = $newTags[0]; + my $isNew; # -1=tag is old, 0=tag same as existing, 1=tag is new + if (not defined $oldID) { + last unless defined $newID; + $isNew = 1; + } elsif (not defined $newID) { + # maker notes will have no new tags defined + if (defined $set{$oldID}) { + $newID = $oldID; + $isNew = 0; + } else { + $isNew = -1; + } + } else { + $isNew = $oldID <=> $newID; + } + my $newInfo = $oldInfo; + my $newFormat = $oldFormat; + my $newFormName = $oldFormName; + my $newCount = $oldCount; + my $ifdFormName; + my $newValue; + my $newValuePt = $isNew >= 0 ? \$newValue : \$oldValue; + my $isOverwriting; + + if ($isNew >= 0) { + # add, edit or delete this tag + shift @newTags; # remove from list + my $curInfo = $set{$newID}; + unless ($curInfo or $$addDirs{$newID}) { + # we can finally get the specific tagInfo reference for this tag + # (because we can now evaluate the Condition statement since all + # DataMember's have been obtained for tags up to this one) + $curInfo = $et->GetTagInfo($tagTablePtr, $newID); + if (defined $curInfo and not $curInfo) { + # need value to evaluate the condition + # (tricky because we need the tagInfo ref to get the value, + # so we must loop through all new tagInfo's...) + foreach $tagInfo (@newTagInfo) { + next unless $$tagInfo{TagID} == $newID; + my $val = $et->GetNewValue($tagInfo); + defined $val or $mayDelete{$newID} = 1, next; + # must convert to binary for evaluating in Condition + my $fmt = $$tagInfo{Format} || $$tagInfo{Writable}; + if ($fmt) { + $val = WriteValue($val, $fmt, $$tagInfo{Count}); + defined $val or $mayDelete{$newID} = 1, next; + } + $curInfo = $et->GetTagInfo($tagTablePtr, $newID, \$val, $oldFormName, $oldCount); + if ($curInfo) { + last if $curInfo eq $tagInfo; + undef $curInfo; + } + } + # may want to delete this, but we need to see the old value first + $mayDelete{$newID} = 1 unless $curInfo; + } + # don't set this tag unless valid for the current condition + if ($curInfo and $$et{NEW_VALUE}{$curInfo}) { + $set{$newID} = $curInfo; + } else { + next if $isNew > 0; + $isNew = -1; + undef $curInfo; + } + } + if ($curInfo) { + if ($$curInfo{WriteCondition}) { + my $self = $et; # set $self to be used in eval + #### eval WriteCondition ($self) + unless (eval $$curInfo{WriteCondition}) { + $@ and warn $@; + goto NoWrite; # GOTO ! + } + } + my $nvHash; + $nvHash = $et->GetNewValueHash($curInfo, $dirName) if $isNew >= 0; + unless ($nvHash or defined $$mandatory{$newID}) { + goto NoWrite unless $wrongDir; # GOTO ! + # delete stuff from the wrong directory if setting somewhere else + $nvHash = $et->GetNewValueHash($curInfo, $wrongDir); + # don't cross delete if not overwriting + goto NoWrite unless $et->IsOverwriting($nvHash); # GOTO ! + # don't cross delete if specifically deleting from the other directory + # (Note: don't call GetValue() here because it shouldn't be called + # if IsOverwriting returns < 0 -- eg. when shifting) + if (not defined $$nvHash{Value} and $$nvHash{WantGroup} and + lc($$nvHash{WantGroup}) eq lc($wrongDir)) + { + goto NoWrite; # GOTO ! + } else { + # remove this tag if found in this IFD + $xDelete{$newID} = 1; + } + } + } elsif (not $$addDirs{$newID}) { +NoWrite: next if $isNew > 0; + delete $set{$newID}; + $isNew = -1; + } + if ($set{$newID}) { +# +# set the new tag value (or 'next' if deleting tag) +# + $newInfo = $set{$newID}; + $newCount = $$newInfo{Count}; + my ($val, $newVal, $n); + my $nvHash = $et->GetNewValueHash($newInfo, $dirName); + if ($isNew > 0) { + # don't create new entry unless requested + if ($nvHash) { + next unless $$nvHash{IsCreating}; + if ($$newInfo{IsOverwriting}) { + my $proc = $$newInfo{IsOverwriting}; + $isOverwriting = &$proc($et, $nvHash, $val, \$newVal); + } else { + $isOverwriting = $et->IsOverwriting($nvHash); + } + } else { + next if $xDelete{$newID}; # don't create if cross deleting + $newVal = $$mandatory{$newID}; # get value for mandatory tag + $isOverwriting = 1; + } + # convert using new format + if ($$newInfo{Format}) { + $newFormName = $$newInfo{Format}; + # use Writable flag to specify IFD format code + $ifdFormName = $$newInfo{Writable}; + } else { + $newFormName = $$newInfo{Writable}; + unless ($newFormName) { + warn("No format for $name $$newInfo{Name}\n"); + next; + } + } + $newFormat = $formatNumber{$newFormName}; + } elsif ($nvHash or $xDelete{$newID}) { + unless ($nvHash) { + $nvHash = $et->GetNewValueHash($newInfo, $wrongDir); + } + # read value + if (length $oldValue >= $oldSize) { + $val = ReadValue(\$oldValue, 0, $readFormName, $readCount, $oldSize); + } else { + $val = ''; + } + # determine write format (by default, use 'Writable' format) + my $writable = $$newInfo{Writable}; + # (or use existing format if 'Writable' not specified) + $writable = $oldFormName unless $writable and $writable ne '1'; + # (and override write format with 'Format' if specified) + my $writeForm = $$newInfo{Format} || $writable; + if ($writeForm ne $newFormName) { + # write in specified format + $newFormName = $writeForm; + $newFormat = $formatNumber{$newFormName}; + # use different IFD format code if necessary + if ($inMakerNotes) { + # always preserve IFD format in maker notes + $ifdFormName = $oldFormName; + } elsif ($writable ne $newFormName) { + # use specified IFD format + $ifdFormName = $writable; + } + } + if ($inMakerNotes and $readFormName ne 'string' and $readFormName ne 'undef') { + # keep same size in maker notes unless string or binary + $newCount = $oldCount * $formatSize[$oldFormat] / $formatSize[$newFormat]; + } + if ($$newInfo{IsOverwriting}) { + my $proc = $$newInfo{IsOverwriting}; + $isOverwriting = &$proc($et, $nvHash, $val, \$newVal); + } else { + $isOverwriting = $et->IsOverwriting($nvHash, $val); + } + } + if ($isOverwriting) { + $newVal = $et->GetNewValue($nvHash) unless defined $newVal; + # value undefined if deleting this tag + # (also delete tag if cross-deleting and this isn't a date/time shift) + if (not defined $newVal or ($xDelete{$newID} and not defined $$nvHash{Shift})) { + if (not defined $newVal and $$newInfo{RawConvInv} and defined $$nvHash{Value}) { + # error in RawConvInv, so rewrite existing tag + goto NoOverwrite; # GOTO! + } + unless ($isNew) { + ++$$et{CHANGED}; + $et->VerboseValue("- $dirName:$$newInfo{Name}", $val); + } + next; + } + if ($newCount and $newCount < 0) { + # set count to number of values if variable + my @vals = split ' ',$newVal; + $newCount = @vals; + } + # convert to binary format + $newValue = WriteValue($newVal, $newFormName, $newCount); + unless (defined $newValue) { + $et->Warn("Invalid value for $dirName:$$newInfo{Name}"); + goto NoOverwrite; # GOTO! + } + if (length $newValue) { + # limit maximum value length in JPEG images + # (max segment size is 65533 bytes and the min EXIF size is 96 incl an additional IFD entry) + if ($$et{FILE_TYPE} eq 'JPEG' and length($newValue) > 65436 and + $$newInfo{Name} ne 'PreviewImage') + { + my $name = $$newInfo{MakerNotes} ? 'MakerNotes' : $$newInfo{Name}; + $et->Warn("Writing large value for $name",1); + } + # re-code if necessary + if ($strEnc and $newFormName eq 'string') { + $newValue = $et->Encode($newValue, $strEnc); + } + } else { + $et->Warn("Can't write zero length $$newInfo{Name} in $$tagTablePtr{GROUPS}{1}"); + goto NoOverwrite; # GOTO! + } + if ($isNew >= 0) { + $newCount = length($newValue) / $formatSize[$newFormat]; + ++$$et{CHANGED}; + if (defined $allMandatory) { + # not all mandatory if we are writing any tag specifically + if ($nvHash) { + undef $allMandatory; + undef $deleteAll; + } else { + ++$addMandatory; # count mandatory tags that we added + } + } + if ($verbose > 1) { + $et->VerboseValue("- $dirName:$$newInfo{Name}", $val) unless $isNew; + if ($$newInfo{OffsetPair} and $newVal eq '4277010157') { # (0xfeedfeed) + print { $$et{OPTIONS}{TextOut} } " + $dirName:$$newInfo{Name} = <tbd>\n"; + } else { + my $str = $nvHash ? '' : ' (mandatory)'; + $et->VerboseValue("+ $dirName:$$newInfo{Name}", $newVal, $str); + } + } + } + } else { +NoOverwrite: next if $isNew > 0; + $isNew = -1; # rewrite existing tag + } + # set format for EXIF IFD if different than conversion format + if ($ifdFormName) { + $newFormName = $ifdFormName; + $newFormat = $formatNumber{$newFormName}; + } + + } elsif ($isNew > 0) { +# +# create new subdirectory +# + # newInfo may not be defined if we try to add a mandatory tag + # to a directory that doesn't support it (eg. IFD1 in RW2 images) + $newInfo = $$addDirs{$newID} or next; + # make sure we don't try to generate a new MakerNotes directory + # or a SubIFD + next if $$newInfo{MakerNotes} or $$newInfo{Name} eq 'SubIFD'; + my $subTable; + if ($$newInfo{SubDirectory}{TagTable}) { + $subTable = Image::ExifTool::GetTagTable($$newInfo{SubDirectory}{TagTable}); + } else { + $subTable = $tagTablePtr; + } + # create empty source directory + my %sourceDir = ( + Parent => $dirName, + Fixup => new Image::ExifTool::Fixup, + ); + $sourceDir{DirName} = $$newInfo{Groups}{1} if $$newInfo{SubIFD}; + $newValue = $et->WriteDirectory(\%sourceDir, $subTable); + # only add new directory if it isn't empty + next unless defined $newValue and length($newValue); + # set the fixup start location + if ($$newInfo{SubIFD}) { + # subdirectory is referenced by an offset in value buffer + my $subdir = $newValue; + $newValue = Set32u(0xfeedf00d); + push @subdirs, { + DataPt => \$subdir, + Table => $subTable, + Fixup => $sourceDir{Fixup}, + Offset => length($dirBuff) + 8, + Where => 'dirBuff', + }; + $newFormName = 'int32u'; + $newFormat = $formatNumber{$newFormName}; + } else { + # subdirectory goes directly into value buffer + $sourceDir{Fixup}{Start} += length($valBuff); + # use Writable to set format, otherwise 'undef' + $newFormName = $$newInfo{Writable}; + unless ($newFormName and $formatNumber{$newFormName}) { + $newFormName = 'undef'; + } + $newFormat = $formatNumber{$newFormName}; + push @valFixups, $sourceDir{Fixup}; + } + } elsif ($$newInfo{Format} and $$newInfo{Writable} and $$newInfo{Writable} ne '1') { + # use specified write format + $newFormName = $$newInfo{Writable}; + $newFormat = $formatNumber{$newFormName}; + } elsif ($$addDirs{$newID} and $newInfo ne $$addDirs{$newID}) { + # this can happen if we are trying to add a directory that doesn't exist + # in this type of file (eg. try adding a SubIFD tag to an A100 image) + $isNew = -1; + } + } + if ($isNew < 0) { + # just rewrite existing tag + $newID = $oldID; + $newValue = $oldValue; + $newFormat = $oldFormat; # (just in case it changed) + $newFormName = $oldFormName; + # set offset of this entry in the directory so we can update the pointer + # and save block information to copy this large block later + if ($oldImageData) { + $$oldImageData[3] = $newStart + length($dirBuff) + 2; + push @imageData, $oldImageData; + $$origDirInfo{ImageData} = \@imageData; + } + } + if ($newInfo) { +# +# load necessary data for this tag (thumbnail image, etc) +# + if ($$newInfo{DataTag} and $isNew >= 0) { + my $dataTag = $$newInfo{DataTag}; + # load data for this tag + unless (defined $offsetData{$dataTag} or $dataTag eq 'LeicaTrailer') { + # prefer tag from Composite table if it exists (otherwise + # PreviewImage data would be taken from Extra tag) + my $compInfo = $Image::ExifTool::Composite{$dataTag}; + $offsetData{$dataTag} = $et->GetNewValue($compInfo || $dataTag); + my $err; + if (defined $offsetData{$dataTag}) { + my $len = length $offsetData{$dataTag}; + if ($dataTag eq 'PreviewImage') { + # must set DEL_PREVIEW flag now if preview fit into IFD + $$et{DEL_PREVIEW} = 1 if $len <= 4; + } + } else { + $err = "$dataTag not found"; + } + if ($err) { + $et->Warn($err) if $$newInfo{IsOffset}; + delete $set{$newID}; # remove from list of tags we are setting + next; + } + } + } +# +# write maker notes +# + if ($$newInfo{MakerNotes}) { + # don't write new makernotes if we are deleting this group + if ($$et{DEL_GROUP}{MakerNotes} and + ($$et{DEL_GROUP}{MakerNotes} != 2 or $isNew <= 0)) + { + if ($isNew <= 0) { + ++$$et{CHANGED}; + $verbose and print $out " Deleting MakerNotes\n"; + } + next; + } + my $saveOrder = GetByteOrder(); + if ($isNew >= 0 and defined $set{$newID}) { + # we are writing a whole new maker note block + # --> add fixup information if necessary + my $nvHash = $et->GetNewValueHash($newInfo, $dirName); + if ($nvHash and $$nvHash{MAKER_NOTE_FIXUP}) { + # must clone fixup because we will be shifting it + my $makerFixup = $$nvHash{MAKER_NOTE_FIXUP}->Clone(); + my $valLen = length($valBuff); + $$makerFixup{Start} += $valLen; + push @valFixups, $makerFixup; + } + } else { + # update maker notes if possible + my %subdirInfo = ( + Base => $base, + DataPt => $valueDataPt, + DataPos => $valueDataPos, + DataLen => $valueDataLen, + DirStart => $valuePtr, + DirLen => $oldSize, + DirName => 'MakerNotes', + Name => $$newInfo{Name}, + Parent => $dirName, + TagInfo => $newInfo, + RAF => $raf, + ); + my ($subTable, $subdir, $loc, $writeProc, $notIFD); + if ($$newInfo{SubDirectory}) { + my $sub = $$newInfo{SubDirectory}; + $subdirInfo{FixBase} = 1 if $$sub{FixBase}; + $subdirInfo{FixOffsets} = $$sub{FixOffsets}; + $subdirInfo{EntryBased} = $$sub{EntryBased}; + $subdirInfo{NoFixBase} = 1 if defined $$sub{Base}; + $subdirInfo{AutoFix} = $$sub{AutoFix}; + SetByteOrder($$sub{ByteOrder}) if $$sub{ByteOrder}; + } + # get the proper tag table for these maker notes + if ($oldInfo and $$oldInfo{SubDirectory}) { + $subTable = $$oldInfo{SubDirectory}{TagTable}; + $subTable and $subTable = Image::ExifTool::GetTagTable($subTable); + $writeProc = $$oldInfo{SubDirectory}{WriteProc}; + $notIFD = $$oldInfo{NotIFD}; + } else { + $et->Warn('Internal problem getting maker notes tag table'); + } + $writeProc or $writeProc = $$subTable{WRITE_PROC} if $subTable; + $subTable or $subTable = $tagTablePtr; + if ($writeProc and + $writeProc eq \&Image::ExifTool::MakerNotes::WriteUnknownOrPreview and + $oldValue =~ /^\xff\xd8\xff/) + { + $loc = 0; + } elsif (not $notIFD) { + # look for IFD-style maker notes + $loc = Image::ExifTool::MakerNotes::LocateIFD($et,\%subdirInfo); + } + if (defined $loc) { + # we need fixup data for this subdirectory + $subdirInfo{Fixup} = new Image::ExifTool::Fixup; + # rewrite maker notes + my $changed = $$et{CHANGED}; + $subdir = $et->WriteDirectory(\%subdirInfo, $subTable, $writeProc); + if ($changed == $$et{CHANGED} and $subdirInfo{Fixup}->IsEmpty()) { + # return original data if nothing changed and no fixups + undef $subdir; + } + } elsif ($$subTable{PROCESS_PROC} and + $$subTable{PROCESS_PROC} eq \&Image::ExifTool::ProcessBinaryData) + { + my $sub = $$oldInfo{SubDirectory}; + if (defined $$sub{Start}) { + #### eval Start ($valuePtr) + my $start = eval $$sub{Start}; + $loc = $start - $valuePtr; + $subdirInfo{DirStart} = $start; + $subdirInfo{DirLen} -= $loc; + } else { + $loc = 0; + } + # rewrite maker notes + $subdir = $et->WriteDirectory(\%subdirInfo, $subTable); + } elsif ($notIFD) { + if ($writeProc) { + $loc = 0; + $subdir = $et->WriteDirectory(\%subdirInfo, $subTable); + } + } else { + my $msg = 'Maker notes could not be parsed'; + if ($$et{FILE_TYPE} eq 'JPEG') { + $et->Warn($msg, 1); + } else { + $et->Error($msg, 1); + } + } + if (defined $subdir) { + length $subdir or SetByteOrder($saveOrder), next; + my $valLen = length($valBuff); + # restore existing header and substitute the new + # maker notes for the old value + $newValue = substr($oldValue, 0, $loc) . $subdir; + my $makerFixup = $subdirInfo{Fixup}; + my $previewInfo = $$et{PREVIEW_INFO}; + if ($subdirInfo{Relative}) { + # apply a one-time fixup to $loc since offsets are relative + $$makerFixup{Start} += $loc; + # shift all offsets to be relative to new base + my $baseShift = $valueDataPos + $valuePtr + $base - $subdirInfo{Base}; + $$makerFixup{Shift} += $baseShift; + $makerFixup->ApplyFixup(\$newValue); + if ($previewInfo) { + # remove all but PreviewImage fixup (since others shouldn't change) + foreach (keys %{$$makerFixup{Pointers}}) { + /_PreviewImage$/ or delete $$makerFixup{Pointers}{$_}; + } + # zero pointer so we can see how it gets shifted later + $makerFixup->SetMarkerPointers(\$newValue, 'PreviewImage', 0); + # set the pointer to the start of the EXIF information + # add preview image fixup to list of value fixups + $$makerFixup{Start} += $valLen; + push @valFixups, $makerFixup; + $$previewInfo{BaseShift} = $baseShift; + $$previewInfo{Relative} = 1; + } + # don't shift anything if relative flag set to zero (Pentax patch) + } elsif (not defined $subdirInfo{Relative}) { + # shift offset base if shifted in the original image or if FixBase + # was used, but be careful of automatic FixBase with negative shifts + # since they may lead to negative (invalid) offsets (casio_edit_problem.jpg) + my $baseShift = $base - $subdirInfo{Base}; + if ($subdirInfo{AutoFix}) { + $baseShift = 0; + } elsif ($subdirInfo{FixBase} and $baseShift < 0 and + # allow negative base shift if offsets are bigger (PentaxOptioWP.jpg) + (not $subdirInfo{MinOffset} or $subdirInfo{MinOffset} + $baseShift < 0)) + { + my $fixBase = $et->Options('FixBase'); + if (not defined $fixBase) { + my $str = $et->Options('IgnoreMinorErrors') ? 'ignored' : 'fix or ignore?'; + $et->Error("MakerNotes offsets may be incorrect ($str)", 1); + } elsif ($fixBase eq '') { + $et->Warn('Fixed incorrect MakerNotes offsets'); + $baseShift = 0; + } + } + $$makerFixup{Start} += $valLen + $loc; + $$makerFixup{Shift} += $baseShift; + # permanently fix makernote offset errors + $$makerFixup{Shift} += $subdirInfo{FixedBy} || 0; + push @valFixups, $makerFixup; + if ($previewInfo and not $$previewInfo{NoBaseShift}) { + $$previewInfo{BaseShift} = $baseShift; + } + } + $newValuePt = \$newValue; # write new value + } + } + SetByteOrder($saveOrder); + + # process existing subdirectory unless we are overwriting it entirely + } elsif ($$newInfo{SubDirectory} and $isNew <= 0 and not $isOverwriting + # don't edit directory if Writable is set to 0 + and (not defined $$newInfo{Writable} or $$newInfo{Writable}) and + not $$newInfo{ReadFromRAF}) + { + + my $subdir = $$newInfo{SubDirectory}; + if ($$newInfo{SubIFD}) { +# +# rewrite existing sub IFD's +# + my $subTable = $tagTablePtr; + if ($$subdir{TagTable}) { + $subTable = Image::ExifTool::GetTagTable($$subdir{TagTable}); + } + # determine directory name for this IFD + my $subdirName = $$newInfo{Groups}{1} || $$newInfo{Name}; + # all makernotes directory names must be 'MakerNotes' + $subdirName = 'MakerNotes' if $$subTable{GROUPS}{0} eq 'MakerNotes'; + # must handle sub-IFD's specially since the values + # are actually offsets to subdirectories + unless ($readCount) { # can't have zero count + return undef if $et->Error("$name entry $index has zero count", 2); + next; + } + my $writeCount = 0; + my $i; + $newValue = ''; # reset value because we regenerate it below + for ($i=0; $i<$readCount; ++$i) { + my $off = $i * $formatSize[$readFormat]; + my $val = ReadValue($valueDataPt, $valuePtr + $off, + $readFormName, 1, $oldSize - $off); + my $subdirStart = $val - $dataPos; + my $subdirBase = $base; + my $hdrLen; + if (defined $$subdir{Start}) { + #### eval Start ($val) + my $newStart = eval $$subdir{Start}; + unless (Image::ExifTool::IsInt($newStart)) { + $et->Error("Bad subdirectory start for $$newInfo{Name}"); + next; + } + $newStart -= $dataPos; + $hdrLen = $newStart - $subdirStart; + $subdirStart = $newStart; + } + if ($$subdir{Base}) { + my $start = $subdirStart + $dataPos; + #### eval Base ($start,$base) + $subdirBase += eval $$subdir{Base}; + } + # add IFD number if more than one + $subdirName =~ s/\d*$/$i/ if $i; + my %subdirInfo = ( + Base => $subdirBase, + DataPt => $dataPt, + DataPos => $dataPos - $subdirBase + $base, + DataLen => $dataLen, + DirStart => $subdirStart, + DirName => $subdirName, + Name => $$newInfo{Name}, + TagInfo => $newInfo, + Parent => $dirName, + Fixup => new Image::ExifTool::Fixup, + RAF => $raf, + Subdir => $subdir, + # set ImageData only for 1st level SubIFD's + ImageData=> $imageDataFlag eq 'Main' ? 'SubIFD' : undef, + ); + # pass on header pointer only for certain sub IFD's + $subdirInfo{HeaderPtr} = $$dirInfo{HeaderPtr} if $$newInfo{SubIFD} == 2; + if ($$subdir{RelativeBase}) { + # apply one-time fixup if offsets are relative (Sony IDC hack) + delete $subdirInfo{Fixup}; + delete $subdirInfo{ImageData}; + } + # is the subdirectory outside our current data? + if ($subdirStart < 0 or $subdirStart + 2 > $dataLen) { + if ($raf) { + # reset SubDirectory buffer (we will load it later) + my $buff = ''; + $subdirInfo{DataPt} = \$buff; + $subdirInfo{DataLen} = 0; + } else { + my @err = ("Can't read $subdirName data", $inMakerNotes); + if ($$subTable{VARS} and $$subTable{VARS}{MINOR_ERRORS}) { + $et->Warn($err[0] . '. Ignored.'); + } elsif ($et->Error(@err)) { + return undef; + } + next Entry; # don't write this directory + } + } + my $subdirData = $et->WriteDirectory(\%subdirInfo, $subTable, $$subdir{WriteProc}); + unless (defined $subdirData) { + # WriteDirectory should have issued an error, but check just in case + $et->Error("Error writing $subdirName") unless $$et{VALUE}{Error}; + return undef; + } + # add back original header if necessary (eg. Ricoh GR) + if ($hdrLen and $hdrLen > 0 and $subdirStart <= $dataLen) { + $subdirData = substr($$dataPt, $subdirStart - $hdrLen, $hdrLen) . $subdirData; + $subdirInfo{Fixup}{Start} += $hdrLen; + } + unless (length $subdirData) { + next unless $inMakerNotes; + # don't delete MakerNote Sub-IFD's, write empty IFD instead + $subdirData = "\0" x 6; + # reset SubIFD ImageData and Fixup just to be safe + delete $subdirInfo{ImageData}; + delete $subdirInfo{Fixup}; + } + # handle data blocks that we will transfer later + if (ref $subdirInfo{ImageData}) { + push @imageData, @{$subdirInfo{ImageData}}; + $$origDirInfo{ImageData} = \@imageData; + } + # temporarily set value to subdirectory index + # (will set to actual offset later when we know what it is) + $newValue .= Set32u(0xfeedf00d); + my ($offset, $where); + if ($readCount > 1) { + $offset = length($valBuff) + $i * 4; + $where = 'valBuff'; + } else { + $offset = length($dirBuff) + 8; + $where = 'dirBuff'; + } + # add to list of subdirectories we will append later + push @subdirs, { + DataPt => \$subdirData, + Table => $subTable, + Fixup => $subdirInfo{Fixup}, + Offset => $offset, + Where => $where, + ImageData => $subdirInfo{ImageData}, + }; + ++$writeCount; # count number of subdirs written + } + next unless length $newValue; + # must change location of subdir offset if we deleted + # a directory and only one remains + if ($writeCount < $readCount and $writeCount == 1) { + $subdirs[-1]{Where} = 'dirBuff'; + $subdirs[-1]{Offset} = length($dirBuff) + 8; + } + # set new format to int32u for IFD + $newFormName = $$newInfo{FixFormat} || 'int32u'; + $newFormat = $formatNumber{$newFormName}; + $newValuePt = \$newValue; + + } elsif ((not defined $$subdir{Start} or + $$subdir{Start} =~ /\$valuePtr/) and + $$subdir{TagTable}) + { +# +# rewrite other existing subdirectories ('$valuePtr' type only) +# + # set subdirectory Start and Base + my $subdirStart = $valuePtr; + if ($$subdir{Start}) { + #### eval Start ($valuePtr) + $subdirStart = eval $$subdir{Start}; + # must adjust directory size if start changed + $oldSize -= $subdirStart - $valuePtr; + } + my $subdirBase = $base; + if ($$subdir{Base}) { + my $start = $subdirStart + $valueDataPos; + #### eval Base ($start,$base) + $subdirBase += eval $$subdir{Base}; + } + my $subFixup = new Image::ExifTool::Fixup; + my %subdirInfo = ( + Base => $subdirBase, + DataPt => $valueDataPt, + DataPos => $valueDataPos - $subdirBase + $base, + DataLen => $valueDataLen, + DirStart => $subdirStart, + DirName => $$subdir{DirName}, + DirLen => $oldSize, + Parent => $dirName, + Fixup => $subFixup, + RAF => $raf, + TagInfo => $newInfo, + ); + unless ($oldSize) { + # replace with dummy data if empty to prevent WriteDirectory + # routines from accessing data they shouldn't + my $tmp = ''; + $subdirInfo{DataPt} = \$tmp; + $subdirInfo{DataLen} = 0; + $subdirInfo{DirStart} = 0; + $subdirInfo{DataPos} += $subdirStart; + } + my $subTable = Image::ExifTool::GetTagTable($$subdir{TagTable}); + my $oldOrder = GetByteOrder(); + SetByteOrder($$subdir{ByteOrder}) if $$subdir{ByteOrder}; + $newValue = $et->WriteDirectory(\%subdirInfo, $subTable, $$subdir{WriteProc}); + SetByteOrder($oldOrder); + if (defined $newValue) { + my $hdrLen = $subdirStart - $valuePtr; + if ($hdrLen) { + $newValue = substr($$valueDataPt, $valuePtr, $hdrLen) . $newValue; + $$subFixup{Start} += $hdrLen; + } + $newValuePt = \$newValue; + } else { + $newValuePt = \$oldValue; + } + unless (length $$newValuePt) { + # don't delete a previously empty makernote directory + next if $oldSize or not $inMakerNotes; + } + if ($$subFixup{Pointers} and $subdirInfo{Base} == $base) { + $$subFixup{Start} += length $valBuff; + push @valFixups, $subFixup; + } else { + # apply fixup in case we added a header ($hdrLen above) + $subFixup->ApplyFixup(\$newValue); + } + } + + } elsif ($$newInfo{OffsetPair}) { +# +# keep track of offsets +# + my $dataTag = $$newInfo{DataTag} || ''; + if ($dataTag eq 'CanonVRD') { + # must decide now if we will write CanonVRD information + my $hasVRD; + if ($$et{NEW_VALUE}{$Image::ExifTool::Extra{CanonVRD}}) { + # adding or deleting as a block + $hasVRD = $et->GetNewValue('CanonVRD') ? 1 : 0; + } elsif ($$et{DEL_GROUP}{CanonVRD} or + $$et{DEL_GROUP}{Trailer}) + { + $hasVRD = 0; # deleting as a group + } else { + $hasVRD = ($$newValuePt ne "\0\0\0\0"); + } + if ($hasVRD) { + # add a fixup, and set this offset later + $dirFixup->AddFixup(length($dirBuff) + 8, $dataTag); + } else { + # there is (or will soon be) no VRD information, so set pointer to zero + $newValue = "\0" x length($$newValuePt); + $newValuePt = \$newValue; + } + } elsif ($dataTag eq 'OriginalDecisionData') { + # handle Canon OriginalDecisionData (no associated length tag) + # - I'm going out of my way here to preserve data which is + # invalidated anyway by our edits + my $odd; + my $oddInfo = $Image::ExifTool::Composite{OriginalDecisionData}; + if ($oddInfo and $$et{NEW_VALUE}{$oddInfo}) { + $odd = $et->GetNewValue($dataTag); + if ($verbose > 1) { + print $out " - $dirName:$dataTag\n" if $$newValuePt ne "\0\0\0\0"; + print $out " + $dirName:$dataTag\n" if $odd; + } + ++$$et{CHANGED}; + } elsif ($$newValuePt ne "\0\0\0\0") { + if (length($$newValuePt) == 4) { + require Image::ExifTool::Canon; + my $offset = Get32u($newValuePt,0); + # absolute offset in JPEG images only + $offset += $base unless $$et{FILE_TYPE} eq 'JPEG'; + $odd = Image::ExifTool::Canon::ReadODD($et, $offset); + $odd = $$odd if ref $odd; + } else { + $et->Error("Invalid $$newInfo{Name}",1); + } + } + if ($odd) { + my $newOffset = length($valBuff); + # (ODD offset is absolute in JPEG, so add base offset!) + $newOffset += $base if $$et{FILE_TYPE} eq 'JPEG'; + $newValue = Set32u($newOffset); + $dirFixup->AddFixup(length($dirBuff) + 8, $dataTag); + $valBuff .= $odd; # add original decision data + } else { + $newValue = "\0\0\0\0"; + } + $newValuePt = \$newValue; + } else { + my $offsetInfo = $offsetInfo[$ifd]; + # save original values (for updating TIFF_END later) + my @vals; + if ($isNew <= 0) { + my $oldOrder = GetByteOrder(); + # Minolta A200 stores these in the wrong byte order! + SetByteOrder($$newInfo{ByteOrder}) if $$newInfo{ByteOrder}; + @vals = ReadValue(\$oldValue, 0, $readFormName, $readCount, $oldSize); + SetByteOrder($oldOrder); + $validateInfo{$newID} = [$newInfo, join(' ',@vals)] unless $$newInfo{IsOffset}; + } + # only support int32 pointers (for now) + if ($formatSize[$newFormat] != 4 and $$newInfo{IsOffset}) { + $isNew > 0 and warn("Internal error (Offset not int32)"), return undef; + $newCount != $readCount and warn("Wrong count!"), return undef; + # change to int32 + $newFormName = 'int32u'; + $newFormat = $formatNumber{$newFormName}; + $newValue = WriteValue(join(' ',@vals), $newFormName, $newCount); + unless (defined $newValue) { + warn "Internal error writing offsets for $$newInfo{Name}\n"; + return undef; + } + } + $offsetInfo or $offsetInfo = $offsetInfo[$ifd] = { }; + # save location of valuePtr in new directory + # (notice we add 10 instead of 8 for valuePtr because + # we will put a 2-byte count at start of directory later) + my $ptr = $newStart + length($dirBuff) + 10; + $newCount or $newCount = 1; # make sure count is set for offsetInfo + # save value pointer and value count for each tag + $$offsetInfo{$newID} = [$newInfo, $ptr, $newCount, \@vals, $newFormat]; + } + + } elsif ($$newInfo{DataMember}) { + + # save any necessary data members (Make, Model, etc) + my $formatStr = $newFormName; + my $count = $newCount; + # change to specified format if necessary + if ($$newInfo{Format} and $$newInfo{Format} ne $formatStr) { + $formatStr = $$newInfo{Format}; + my $format = $formatNumber{$formatStr}; + # adjust number of items for new format size + $count = int(length($$newValuePt) / $formatSize[$format]) if $format; + } + my $val = ReadValue($newValuePt,0,$formatStr,$count,length($$newValuePt)); + my $conv = $$newInfo{RawConv}; + if ($conv) { + # let the RawConv store the (possibly converted) data member + if (ref $conv eq 'CODE') { + &$conv($val, $et); + } else { + my ($priority, @grps); + my ($self, $tag, $tagInfo) = ($et, $$newInfo{Name}, $newInfo); + #### eval RawConv ($self, $val, $tag, $tagInfo, $priority, @grps) + eval $conv; + } + } else { + $$et{$$newInfo{DataMember}} = $val; + } + } + } +# +# write out the directory entry +# + my $newSize = length($$newValuePt); + my $fsize = $formatSize[$newFormat]; + my $offsetVal; + # set proper count + $newCount = int(($newSize + $fsize - 1) / $fsize) unless $oldInfo and $$oldInfo{FixedSize}; + if ($saveForValidate{$newID} and $tagTablePtr eq \%Image::ExifTool::Exif::Main) { + my @vals = ReadValue(\$newValue, 0, $newFormName, $newCount, $newSize); + $validateInfo{$newID} = join ' ',@vals; + } + if ($newSize > 4) { + # zero-pad to an even number of bytes (required by EXIF standard) + # and make sure we are a multiple of the format size + while ($newSize & 0x01 or $newSize < $newCount * $fsize) { + $$newValuePt .= "\0"; + ++$newSize; + } + my $entryBased; + if ($$dirInfo{EntryBased} or ($newInfo and $$newInfo{EntryBased})) { + $entryBased = 1; + $offsetVal = Set32u(length($valBuff) - length($dirBuff)); + } else { + $offsetVal = Set32u(length $valBuff); + } + my ($dataTag, $putFirst); + ($dataTag, $putFirst) = @$newInfo{'DataTag','PutFirst'} if $newInfo; + if ($dataTag) { + if ($dataTag eq 'PreviewImage' and ($$et{FILE_TYPE} eq 'JPEG' or + $$et{GENERATE_PREVIEW_INFO})) + { + # hold onto the PreviewImage until we can determine if it fits + $$et{PREVIEW_INFO} or $$et{PREVIEW_INFO} = { + Data => $$newValuePt, + Fixup => new Image::ExifTool::Fixup, + }; + $$et{PREVIEW_INFO}{ChangeBase} = 1 if $$newInfo{ChangeBase}; + if ($$newInfo{IsOffset} and $$newInfo{IsOffset} eq '2') { + $$et{PREVIEW_INFO}{NoBaseShift} = 1; + } + # use original preview size if we will attempt to load it later + $newCount = $oldCount if $$newValuePt eq 'LOAD_PREVIEW'; + $$newValuePt = ''; + } elsif ($dataTag eq 'LeicaTrailer' and $$et{LeicaTrailer}) { + $$newValuePt = ''; + } + } + if ($putFirst and $$dirInfo{HeaderPtr}) { + my $hdrPtr = $$dirInfo{HeaderPtr}; + # place this value immediately after the TIFF header (eg. IIQ maker notes) + $offsetVal = Set32u(length $$hdrPtr); + $$hdrPtr .= $$newValuePt; + } else { + $valBuff .= $$newValuePt; # add value data to buffer + # must save a fixup pointer for every pointer in the directory + if ($entryBased) { + $entryBasedFixup or $entryBasedFixup = new Image::ExifTool::Fixup; + $entryBasedFixup->AddFixup(length($dirBuff) + 8, $dataTag); + } else { + $dirFixup->AddFixup(length($dirBuff) + 8, $dataTag); + } + } + } else { + $offsetVal = $$newValuePt; # save value in offset if 4 bytes or less + # must pad value with zeros if less than 4 bytes + $newSize < 4 and $offsetVal .= "\0" x (4 - $newSize); + } + # write the directory entry + $dirBuff .= Set16u($newID) . Set16u($newFormat) . + Set32u($newCount) . $offsetVal; + # update flag to keep track of mandatory tags + while (defined $allMandatory) { + if (defined $$mandatory{$newID}) { + # values must correspond to mandatory values + my $form = $$newInfo{Format} || $newFormName; + my $mandVal = WriteValue($$mandatory{$newID}, $form, $newCount); + if (defined $mandVal and $mandVal eq $$newValuePt) { + ++$allMandatory; # count mandatory tags + last; + } + } + undef $deleteAll; + undef $allMandatory; + } + } + if (%validateInfo) { + ValidateImageData($et, \%validateInfo, $dirName, 1); + undef %validateInfo; + } + if ($ignoreCount) { + my $y = $ignoreCount > 1 ? 'ies' : 'y'; + my $verb = $$dirInfo{FixBase} ? 'Ignored' : 'Removed'; + $et->Warn("$verb $ignoreCount invalid entr$y from $name", 1); + } + if ($fixCount) { + my $s = $fixCount > 1 ? 's' : ''; + $et->Warn("Fixed invalid count$s for $fixCount $name tag$s", 1); + } +#.............................................................................. +# write directory counts and nextIFD pointer and add value data to end of IFD +# + # determine now if there is or will be another IFD after this one + my $nextIfdOffset; + if ($dirEnd + 4 <= $dataLen) { + $nextIfdOffset = Get32u($dataPt, $dirEnd); + } else { + $nextIfdOffset = 0; + } + my $isNextIFD = ($$dirInfo{Multi} and ($nextIfdOffset or + # account for the case where we will create the next IFD + # (IFD1 only, but not in TIFF-format images) + ($dirName eq 'IFD0' and $$et{ADD_DIRS}{'IFD1'} and + $$et{FILE_TYPE} ne 'TIFF'))); + # calculate number of entries in new directory + my $newEntries = length($dirBuff) / 12; + # delete entire directory if we deleted a tag and only mandatory tags remain or we + # attempted to create a directory with only mandatory tags and there is no nextIFD + if ($allMandatory and not $isNextIFD and ($newEntries < $numEntries or $numEntries == 0)) { + $newEntries = 0; + $dirBuff = ''; + $valBuff = ''; + undef $dirFixup; # no fixups in this directory + ++$deleteAll if defined $deleteAll; + $verbose > 1 and print $out " - $allMandatory mandatory tag(s)\n"; + $$et{CHANGED} -= $addMandatory; # didn't change these after all + } + if ($ifd and not $newEntries) { + $verbose and print $out " Deleting IFD1\n"; + last; # don't write IFD1 if empty + } + # apply one-time fixup for entry-based offsets + if ($entryBasedFixup) { + $$entryBasedFixup{Shift} = length($dirBuff) + 4; + $entryBasedFixup->ApplyFixup(\$dirBuff); + undef $entryBasedFixup; + } + # initialize next IFD pointer to zero + my $nextIFD = Set32u(0); + # some cameras use a different amount of padding after the makernote IFD + if ($dirName eq 'MakerNotes' and $$dirInfo{Parent} =~ /^(ExifIFD|IFD0)$/) { + my ($rel, $pad) = Image::ExifTool::MakerNotes::GetMakerNoteOffset($et); + $nextIFD = "\0" x $pad if defined $pad and ($pad==0 or ($pad>4 and $pad<=32)); + } + # add directory entry count to start of IFD and next IFD pointer to end + $newData .= Set16u($newEntries) . $dirBuff . $nextIFD; + # get position of value data in newData + my $valPos = length($newData); + # go back now and set next IFD pointer if this isn't the first IFD + if ($nextIfdPos) { + # set offset to next IFD + Set32u($newStart, \$newData, $nextIfdPos); + $fixup->AddFixup($nextIfdPos,'NextIFD'); # add fixup for this offset in newData + } + # remember position of 'next IFD' pointer so we can set it next time around + $nextIfdPos = length($nextIFD) ? $valPos - length($nextIFD) : undef; + # add value data after IFD + $newData .= $valBuff; +# +# add any subdirectories, adding fixup information +# + if (@subdirs) { + my $subdir; + foreach $subdir (@subdirs) { + my $len = length($newData); # position of subdirectory in data + my $subdirFixup = $$subdir{Fixup}; + if ($subdirFixup) { + $$subdirFixup{Start} += $len; + $fixup->AddFixup($subdirFixup); + } + my $imageData = $$subdir{ImageData}; + my $blockSize = 0; + # must also update start position for ImageData fixups + if (ref $imageData) { + my $blockInfo; + foreach $blockInfo (@$imageData) { + my ($pos, $size, $pad, $entry, $subFix) = @$blockInfo; + if ($subFix) { + $$subFix{Start} += $len; + # save expected image data offset for calculating shift later + $$subFix{BlockLen} = length(${$$subdir{DataPt}}) + $blockSize; + } + $blockSize += $size + $pad; + } + } + $newData .= ${$$subdir{DataPt}}; # add subdirectory to our data + undef ${$$subdir{DataPt}}; # free memory now + # set the pointer + my $offset = $$subdir{Offset}; + # if offset is in valBuff, it was added to the end of dirBuff + # (plus 4 bytes for nextIFD pointer) + $offset += length($dirBuff) + 4 if $$subdir{Where} eq 'valBuff'; + $offset += $newStart + 2; # get offset in newData + # check to be sure we got the right offset + unless (Get32u(\$newData, $offset) == 0xfeedf00d) { + $et->Error("Internal error while rewriting $name"); + return undef; + } + # set the offset to the subdirectory data + Set32u($len, \$newData, $offset); + $fixup->AddFixup($offset); # add fixup for this offset in newData + } + } + # add fixup for all offsets in directory according to value data position + # (which is at the end of this directory) + if ($dirFixup) { + $$dirFixup{Start} = $newStart + 2; + $$dirFixup{Shift} = $valPos - $$dirFixup{Start}; + $fixup->AddFixup($dirFixup); + } + # add valueData fixups, adjusting for position of value data + my $valFixup; + foreach $valFixup (@valFixups) { + $$valFixup{Start} += $valPos; + $fixup->AddFixup($valFixup); + } + # stop if no next IFD pointer + last unless $isNextIFD; # stop unless scanning for multiple IFD's + if ($nextIfdOffset) { + # continue with next IFD + $dirStart = $nextIfdOffset - $dataPos; + } else { + # create IFD1 if necessary + $verbose and print $out " Creating IFD1\n"; + my $ifd1 = "\0" x 2; # empty IFD1 data (zero entry count) + $dataPt = \$ifd1; + $dirStart = 0; + $dirLen = $dataLen = 2; + } + # increment IFD name + my $ifdNum = $dirName =~ s/(\d+)$// ? $1 : 0; + $dirName .= $ifdNum + 1; + $name =~ s/\d+$//; + $name .= $ifdNum + 1; + $$et{DIR_NAME} = $$et{PATH}[-1] = $dirName; + next unless $nextIfdOffset; + + # guard against writing the same directory twice + my $addr = $nextIfdOffset + $base; + if ($$et{PROCESSED}{$addr}) { + $et->Error("$name pointer references previous $$et{PROCESSED}{$addr} directory", 1); + last; + } + $$et{PROCESSED}{$addr} = $name; + + if ($dirName eq 'SubIFD1' and not ValidateIFD($dirInfo, $dirStart)) { + if ($$et{TIFF_TYPE} eq 'TIFF') { + $et->Error('Ignored bad IFD linked from SubIFD', 1); + } elsif ($verbose) { + $et->Warn('Ignored bad IFD linked from SubIFD'); + } + last; # don't write bad IFD + } + if ($$et{DEL_GROUP}{$dirName}) { + $verbose and print $out " Deleting $dirName\n"; + $raf and $et->Error("Deleting $dirName also deletes subsequent" . + " IFD's and possibly image data", 1); + ++$$et{CHANGED}; + if ($$et{DEL_GROUP}{$dirName} == 2 and + $$et{ADD_DIRS}{$dirName}) + { + my $emptyIFD = "\0" x 2; # start with empty IFD + $dataPt = \$emptyIFD; + $dirStart = 0; + $dirLen = $dataLen = 2; + } else { + last; # don't write this IFD (or any subsequent IFD) + } + } else { + $verbose and print $out " Rewriting $name\n"; + } + } +#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + # do our fixups now so we can more easily calculate offsets below + $fixup->ApplyFixup(\$newData); +# +# determine total block size for deferred data +# + my $numBlocks = scalar @imageData; # save this so we scan only existing blocks later + my $blockSize = 0; # total size of blocks to copy later + my $blockInfo; + foreach $blockInfo (@imageData) { + my ($pos, $size, $pad) = @$blockInfo; + $blockSize += $size + $pad; + } +# +# copy over image data for IFD's, starting with the last IFD first +# + if (@offsetInfo) { + my $ttwLen; # length of MRW TTW segment + my @writeLater; # write image data last + for ($ifd=$#offsetInfo; $ifd>=-1; --$ifd) { + # build list of offsets to process + my @offsetList; + if ($ifd >= 0) { + my $offsetInfo = $offsetInfo[$ifd] or next; + # patch Panasonic RAW/RW2 StripOffsets/StripByteCounts if necessary + my $stripOffsets = $$offsetInfo{0x111}; + if ($stripOffsets and $$stripOffsets[0]{PanasonicHack}) { + require Image::ExifTool::PanasonicRaw; + my $err = Image::ExifTool::PanasonicRaw::PatchRawDataOffset($offsetInfo, $raf, $ifd); + $err and $et->Error($err); + } + my $tagID; + # loop through all tags in reverse order so we save thumbnail + # data before main image data if both exist in the same IFD + foreach $tagID (reverse sort keys %$offsetInfo) { + my $tagInfo = $$offsetInfo{$tagID}[0]; + next unless $$tagInfo{IsOffset}; # handle byte counts with offsets + my $sizeInfo = $$offsetInfo{$$tagInfo{OffsetPair}}; + $sizeInfo or $et->Error("No size tag for $dirName:$$tagInfo{Name}"), next; + my $dataTag = $$tagInfo{DataTag}; + # write TIFF image data (strips or tiles) later if requested + if ($raf and defined $$origDirInfo{ImageData} and + ($tagID == 0x111 or $tagID == 0x144 or + # also defer writing of other big data such as JpgFromRaw in NEF + ($$sizeInfo[3][0] and + # (calculate approximate combined size of all blocks) + $$sizeInfo[3][0] * scalar(@{$$sizeInfo[3]}) > 1000000)) and + # but don't defer writing if replacing with new value + (not defined $dataTag or not defined $offsetData{$dataTag})) + { + push @writeLater, [ $$offsetInfo{$tagID}, $sizeInfo ]; + } else { + push @offsetList, [ $$offsetInfo{$tagID}, $sizeInfo ]; + } + } + } else { + last unless @writeLater; + @offsetList = @writeLater; + } + my $offsetPair; + foreach $offsetPair (@offsetList) { + my ($tagInfo, $offsets, $count, $oldOffset) = @{$$offsetPair[0]}; + my ($cntInfo, $byteCounts, $count2, $oldSize, $format) = @{$$offsetPair[1]}; + # must be the same number of offset and byte count values + unless ($count == $count2) { + $et->Error("Offsets/ByteCounts disagree on count for $$tagInfo{Name}"); + return undef; + } + my $formatStr = $formatName[$format]; + # follow pointer to value data if necessary + $count > 1 and $offsets = Get32u(\$newData, $offsets); + my $n = $count * $formatSize[$format]; + $n > 4 and $byteCounts = Get32u(\$newData, $byteCounts); + if ($byteCounts < 0 or $byteCounts + $n > length($newData)) { + $et->Error("Error reading $$tagInfo{Name} byte counts"); + return undef; + } + # get offset base and data pos (abnormal for some preview images) + my ($dbase, $dpos, $wrongBase, $subIfdDataFixup); + if ($$tagInfo{IsOffset} eq '2') { + $dbase = $firstBase; + $dpos = $dataPos + $base - $firstBase; + } else { + $dbase = $base; + $dpos = $dataPos; + } + # use different base if necessary for some offsets (Minolta A200) + if ($$tagInfo{WrongBase}) { + my $self = $et; + #### eval WrongBase ($self) + $wrongBase = eval $$tagInfo{WrongBase} || 0; + $dbase += $wrongBase; + $dpos -= $wrongBase; + } else { + $wrongBase = 0; + } + my $oldOrder = GetByteOrder(); + my $dataTag = $$tagInfo{DataTag}; + # use different byte order for values of this offset pair if required (Minolta A200) + SetByteOrder($$tagInfo{ByteOrder}) if $$tagInfo{ByteOrder}; + # transfer the data referenced by all offsets of this tag + for ($n=0; $n<$count; ++$n) { + my ($oldEnd, $size); + if (@$oldOffset and @$oldSize) { + # calculate end offset of this block + $oldEnd = $$oldOffset[$n] + $$oldSize[$n]; + # update TIFF_END as if we read this data from file + UpdateTiffEnd($et, $oldEnd + $dbase); + } + my $offsetPos = $offsets + $n * 4; + my $byteCountPos = $byteCounts + $n * $formatSize[$format]; + if ($$tagInfo{PanasonicHack}) { + # use actual raw data length (may be different than StripByteCounts!) + $size = $$oldSize[$n]; + } else { + # use size of new data + $size = ReadValue(\$newData, $byteCountPos, $formatStr, 1, 4); + } + my $offset = $$oldOffset[$n]; + if (defined $offset) { + $offset -= $dpos; + } elsif ($size != 0xfeedfeed) { + $et->Error('Internal error (no offset)'); + return undef; + } + my $newOffset = length($newData) - $wrongBase; + my $buff; + # look for 'feed' code to use our new data + if ($size == 0xfeedfeed) { + unless (defined $dataTag) { + $et->Error("No DataTag defined for $$tagInfo{Name}"); + return undef; + } + unless (defined $offsetData{$dataTag}) { + $et->Error("Internal error (no $dataTag)"); + return undef; + } + if ($count > 1) { + $et->Error("Can't modify $$tagInfo{Name} with count $count"); + return undef; + } + $buff = $offsetData{$dataTag}; + if ($formatSize[$format] != 4) { + $et->Error("$$cntInfo{Name} is not int32"); + return undef; + } + # set the data size + $size = length($buff); + Set32u($size, \$newData, $byteCountPos); + } elsif ($ifd < 0) { + # pad if necessary (but don't pad contiguous image blocks) + my $pad = 0; + ++$pad if $size & 0x01 and ($n+1 >= $count or not $oldEnd or + $oldEnd != $$oldOffset[$n+1]); + # preserve original image padding if specified + if ($$origDirInfo{PreserveImagePadding} and $n+1 < $count and + $oldEnd and $$oldOffset[$n+1] > $oldEnd) + { + $pad = $$oldOffset[$n+1] - $oldEnd; + } + # copy data later + push @imageData, [$offset+$dbase+$dpos, $size, $pad]; + $newOffset += $blockSize; # data comes after other deferred data + # create fixup for SubIFD ImageData + if ($imageDataFlag eq 'SubIFD' and not $subIfdDataFixup) { + $subIfdDataFixup = new Image::ExifTool::Fixup; + $imageData[-1][4] = $subIfdDataFixup; + } + $size += $pad; # account for pad byte if necessary + # return ImageData list + $$origDirInfo{ImageData} = \@imageData; + } elsif ($offset >= 0 and $offset+$size <= $dataLen) { + # take data from old dir data buffer + $buff = substr($$dataPt, $offset, $size); + } elsif ($$et{TIFF_TYPE} eq 'MRW') { + # TTW segment must be an even 4 bytes long, so pad now if necessary + my $n = length $newData; + $buff = ($n & 0x03) ? "\0" x (4 - ($n & 0x03)) : ''; + $size = length($buff); + # data exists after MRW TTW segment + $ttwLen = length($newData) + $size unless defined $ttwLen; + $newOffset = $offset + $dpos + $ttwLen - $dataLen; + } elsif ($raf and $raf->Seek($offset+$dbase+$dpos,0) and + $raf->Read($buff,$size) == $size) + { + # (data was read OK) + # patch incorrect ThumbnailOffset in Sony A100 1.00 ARW images + if ($$et{TIFF_TYPE} eq 'ARW' and $$tagInfo{Name} eq 'ThumbnailOffset' and + $$et{Model} eq 'DSLR-A100' and $buff !~ /^\xff\xd8\xff/) + { + my $pos = $offset + $dbase + $dpos; + my $try; + if ($pos < 0x10000 and $raf->Seek($pos+0x10000,0) and + $raf->Read($try,$size) == $size and $try =~ /^\xff\xd8\xff/) + { + $buff = $try; + $et->Warn('Adjusted incorrect A100 ThumbnailOffset', 1); + } else { + $et->Error('Invalid ThumbnailImage'); + } + } + } elsif ($$tagInfo{Name} eq 'ThumbnailOffset' and $offset>=0 and $offset<$dataLen) { + # Grrr. The Canon 350D writes the thumbnail with an incorrect byte count + my $diff = $offset + $size - $dataLen; + $et->Warn("ThumbnailImage runs outside EXIF data by $diff bytes (truncated)",1); + # set the size to the available data + $size -= $diff; + unless (WriteValue($size, $formatStr, 1, \$newData, $byteCountPos)) { + warn 'Internal error writing thumbnail size'; + } + # get the truncated image + $buff = substr($$dataPt, $offset, $size); + } elsif ($$tagInfo{Name} eq 'PreviewImageStart' and $$et{FILE_TYPE} eq 'JPEG') { + # try to load the preview image using the specified offset + undef $buff; + my $r = $$et{RAF}; + if ($r and not $raf) { + my $tell = $r->Tell(); + # read and validate + undef $buff unless $r->Seek($offset+$base+$dataPos,0) and + $r->Read($buff,$size) == $size and + $buff =~ /^.\xd8\xff[\xc4\xdb\xe0-\xef]/s; + $r->Seek($tell, 0) or $et->Error('Seek error'), return undef; + } + # set flag if we must load PreviewImage + $buff = 'LOAD_PREVIEW' unless defined $buff; + } else { + my $dataName = $dataTag || $$tagInfo{Name}; + return undef if $et->Error("Error reading $dataName data in $name", $inMakerNotes); + $buff = ''; + } + if ($$tagInfo{Name} eq 'PreviewImageStart') { + if ($$et{FILE_TYPE} eq 'JPEG' and not $$tagInfo{MakerPreview}) { + # hold onto the PreviewImage until we can determine if it fits + $$et{PREVIEW_INFO} or $$et{PREVIEW_INFO} = { + Data => $buff, + Fixup => new Image::ExifTool::Fixup, + }; + if ($$tagInfo{IsOffset} and $$tagInfo{IsOffset} eq '2') { + $$et{PREVIEW_INFO}{NoBaseShift} = 1; + } + if ($offset >= 0 and $offset+$size <= $dataLen) { + # set flag indicating this preview wasn't in a trailer + $$et{PREVIEW_INFO}{WasContained} = 1; + } + $buff = ''; + } elsif ($$et{TIFF_TYPE} eq 'ARW' and $$et{Model} eq 'DSLR-A100') { + # the A100 double-references the same preview, so ignore the + # second one (the offset and size will be patched later) + next if $$et{A100PreviewLength}; + $$et{A100PreviewLength} = length $buff if defined $buff; + } + } + # update offset accordingly and add to end of new data + Set32u($newOffset, \$newData, $offsetPos); + # add a pointer to fix up this offset value (marked with DataTag name) + $fixup->AddFixup($offsetPos, $dataTag); + # also add to subIfdDataFixup if necessary + $subIfdDataFixup->AddFixup($offsetPos, $dataTag) if $subIfdDataFixup; + # must also (sometimes) update StripOffsets in Panasonic RW2 images + my $otherPos = $$offsetPair[0][5]; + if ($otherPos and $$tagInfo{PanasonicHack}) { + Set32u($newOffset, \$newData, $otherPos); + $fixup->AddFixup($otherPos, $dataTag); + } + if ($ifd >= 0) { + # buff length must be even (Note: may have changed since $size was set) + $buff .= "\0" if length($buff) & 0x01; + $newData .= $buff; # add this strip to the data + } else { + $blockSize += $size; # keep track of total size + } + } + SetByteOrder($oldOrder); + } + } + # verify that nothing else got written after determining TTW length + if (defined $ttwLen and $ttwLen != length($newData)) { + $et->Error('Internal error writing MRW TTW'); + } + } +# +# set offsets and generate fixups for tag values which were too large for memory +# + $blockSize = 0; + foreach $blockInfo (@imageData) { + my ($pos, $size, $pad, $entry, $subFix) = @$blockInfo; + if (defined $entry) { + my $format = Get16u(\$newData, $entry + 2); + if ($format < 1 or $format > 13) { + $et->Error('Internal error copying huge value'); + last; + } else { + # set count and offset in directory entry + Set32u($size / $formatSize[$format], \$newData, $entry + 4); + Set32u(length($newData)+$blockSize, \$newData, $entry + 8); + $fixup->AddFixup($entry + 8); + # create special fixup for SubIFD data + if ($imageDataFlag eq 'SubIFD') { + my $subIfdDataFixup = new Image::ExifTool::Fixup; + $subIfdDataFixup->AddFixup($entry + 8); + # save fixup in imageData list + $$blockInfo[4] = $subIfdDataFixup; + } + # must reset entry pointer so we don't use it again in a parent IFD! + $$blockInfo[3] = undef; + } + } + # apply additional shift required for contained SubIFD image data offsets + if ($subFix and defined $$subFix{BlockLen} and $numBlocks > 0) { + # our offset expects the data at the end of the SubIFD block (BlockLen + Start), + # but it will actually be at length($newData) + $blockSize. So adjust + # accordingly (and subtract an extra Start because this shift is applied later) + $$subFix{Shift} += length($newData) - $$subFix{BlockLen} - 2 * $$subFix{Start} + $blockSize; + $subFix->ApplyFixup(\$newData); + } + $blockSize += $size + $pad; + --$numBlocks; + } +# +# apply final shift to new data position if this is the top level IFD +# + unless ($$dirInfo{Fixup}) { + my $hdrPtr = $$dirInfo{HeaderPtr}; + my $newDataPos = $hdrPtr ? length $$hdrPtr : $$dirInfo{NewDataPos} || 0; + # adjust CanonVRD offset to point to end of regular TIFF if necessary + # (NOTE: This will be incorrect if multiple trailers exist, + # but it is unlikely that it could ever be correct in this case anyway. + # Also, this doesn't work for JPEG images (but CanonDPP doesn't set + # this when editing JPEG images anyway)) + $fixup->SetMarkerPointers(\$newData, 'CanonVRD', length($newData) + $blockSize); + if ($newDataPos) { + $$fixup{Shift} += $newDataPos; + $fixup->ApplyFixup(\$newData); + } + # save fixup for adjusting Leica trailer offset if necessary + $$et{LeicaTrailer}{Fixup}->AddFixup($fixup) if $$et{LeicaTrailer}; + # save fixup for PreviewImage in JPEG file if necessary + my $previewInfo = $$et{PREVIEW_INFO}; + if ($previewInfo) { + my $pt = \$$previewInfo{Data}; # image data or 'LOAD_PREVIEW' flag + # now that we know the size of the EXIF data, first test to see if our new image fits + # inside the EXIF segment (remember about the TIFF and EXIF headers: 8+6 bytes) + if (($$pt ne 'LOAD_PREVIEW' and length($$pt) + length($newData) + 14 <= 0xfffd and + not $$previewInfo{IsTrailer}) or + $$previewInfo{IsShort}) # must fit in this segment if using short pointers + { + # It fits! (or must exist in EXIF segment), so fixup the + # PreviewImage pointers and stuff the preview image in here + my $newPos = length($newData) + $newDataPos; + $newPos += ($$previewInfo{BaseShift} || 0); + if ($$previewInfo{Relative}) { + # calculate our base by looking at how far the pointer got shifted + $newPos -= ($fixup->GetMarkerPointers(\$newData, 'PreviewImage') || 0); + } + $fixup->SetMarkerPointers(\$newData, 'PreviewImage', $newPos); + $newData .= $$pt; + # set flag to delete old preview unless it was contained in the EXIF + $$et{DEL_PREVIEW} = 1 unless $$et{PREVIEW_INFO}{WasContained}; + delete $$et{PREVIEW_INFO}; # done with our preview data + } else { + # Doesn't fit, or we still don't know, so save fixup information + # and put the preview at the end of the file + $$previewInfo{Fixup} or $$previewInfo{Fixup} = new Image::ExifTool::Fixup; + $$previewInfo{Fixup}->AddFixup($fixup); + } + } elsif (defined $newData and $deleteAll) { + $newData = ''; # delete both IFD0 and IFD1 since only mandatory tags remain + } elsif ($$et{A100PreviewLength}) { + # save preview image start for patching A100 quirks later + $$et{A100PreviewStart} = $fixup->GetMarkerPointers(\$newData, 'PreviewImage'); + } + # save location of last IFD for use in Canon RAW header + if ($newDataPos == 16) { + my @ifdPos = $fixup->GetMarkerPointers(\$newData,'NextIFD'); + $$origDirInfo{LastIFD} = pop @ifdPos; + } + # recrypt SR2 SubIFD data if necessary + my $key = $$et{SR2SubIFDKey}; + if ($key) { + my $start = $fixup->GetMarkerPointers(\$newData, 'SR2SubIFDOffset'); + my $len = $$et{SR2SubIFDLength}; + # (must subtract 8 for size of TIFF header) + if ($start and $start - 8 + $len <= length $newData) { + require Image::ExifTool::Sony; + Image::ExifTool::Sony::Decrypt(\$newData, $start - 8, $len, $key); + } + } + } + # return empty string if no entries in directory + # (could be up to 10 bytes and still be empty) + $newData = '' if defined $newData and length($newData) < 12; + + # set changed if ForceWrite tag was set to "EXIF" + ++$$et{CHANGED} if defined $newData and length $newData and $$et{FORCE_WRITE}{EXIF}; + + return $newData; # return our directory data +} + +1; # end + +__END__ + +=head1 NAME + +Image::ExifTool::WriteExif.pl - Write EXIF meta information + +=head1 SYNOPSIS + +This file is autoloaded by Image::ExifTool::Exif. + +=head1 DESCRIPTION + +This file contains routines to write EXIF metadata. + +=head1 AUTHOR + +Copyright 2003-2019, Phil Harvey (phil at owl.phy.queensu.ca) + +This library is free software; you can redistribute it and/or modify it +under the same terms as Perl itself. + +=head1 SEE ALSO + +L<Image::ExifTool::Exif(3pm)|Image::ExifTool::Exif>, +L<Image::ExifTool(3pm)|Image::ExifTool> + +=cut diff --git a/lib/Image/ExifTool/WriteIPTC.pl b/lib/Image/ExifTool/WriteIPTC.pl new file mode 100644 index 0000000..dea4005 --- /dev/null +++ b/lib/Image/ExifTool/WriteIPTC.pl @@ -0,0 +1,728 @@ +#------------------------------------------------------------------------------ +# File: WriteIPTC.pl +# +# Description: Write IPTC meta information +# +# Revisions: 12/15/2004 - P. Harvey Created +#------------------------------------------------------------------------------ + +package Image::ExifTool::IPTC; + +use strict; + +# mandatory IPTC tags for each record +my %mandatory = ( + 1 => { + 0 => 4, # EnvelopeRecordVersion + }, + 2 => { + 0 => 4, # ApplicationRecordVersion + }, + 3 => { + 0 => 4, # NewsPhotoVersion + }, +); + +# manufacturer strings for IPTCPictureNumber +my %manufacturer = ( + 1 => 'Associated Press, USA', + 2 => 'Eastman Kodak Co, USA', + 3 => 'Hasselblad Electronic Imaging, Sweden', + 4 => 'Tecnavia SA, Switzerland', + 5 => 'Nikon Corporation, Japan', + 6 => 'Coatsworth Communications Inc, Canada', + 7 => 'Agence France Presse, France', + 8 => 'T/One Inc, USA', + 9 => 'Associated Newspapers, UK', + 10 => 'Reuters London', + 11 => 'Sandia Imaging Systems Inc, USA', + 12 => 'Visualize, Spain', +); + +my %iptcCharsetInv = ( 'UTF8' => "\x1b%G", 'UTF-8' => "\x1b%G" ); + +# ISO 2022 Character Coding Notes +# ------------------------------- +# Character set designation: (0x1b I F, or 0x1b I I F) +# Initial character 0x1b (ESC) +# Intermediate character I: +# 0x28 ('(') - G0, 94 chars +# 0x29 (')') - G1, 94 chars +# 0x2a ('*') - G2, 94 chars +# 0x2b ('+') - G3, 94 chars +# 0x2c (',') - G1, 96 chars +# 0x2d ('-') - G2, 96 chars +# 0x2e ('.') - G3, 96 chars +# 0x24 I ('$I') - multiple byte graphic sets (I from above) +# I 0x20 ('I ') - dynamically redefinable character sets +# Final character: +# 0x30 - 0x3f = private character set +# 0x40 - 0x7f = standardized character set +# Character set invocation: +# G0 : SI = 0x15 +# G1 : SO = 0x14, LS1R = 0x1b 0x7e ('~') +# G2 : LS2 = 0x1b 0x6e ('n'), LS2R = 0x1b 0x7d ('}') +# G3 : LS3 = 0x1b 0x6f ('o'), LS3R = 0x1b 0x7c ('|') +# (the locking shift "R" codes shift into 0x80-0xff space) +# Single character invocation: +# G2 : SS2 = 0x1b 0x8e (or 0x4e in 7-bit) +# G3 : SS3 = 0x1b 0x8f (or 0x4f in 7-bit) +# Control chars (designated and invoked) +# C0 : 0x1b 0x21 F (0x21 = '!') +# C1 : 0x1b 0x22 F (0x22 = '"') +# Complete codes (control+graphics, designated and invoked) +# 0x1b 0x25 F (0x25 = '%') +# 0x1b 0x25 I F +# 0x1b 0x25 0x47 ("\x1b%G") - UTF-8 +# 0x1b 0x25 0x40 ("\x1b%@") - return to ISO 2022 +# ------------------------------- + +#------------------------------------------------------------------------------ +# Inverse print conversion for CodedCharacterSet +# Inputs: 0) value +sub PrintInvCodedCharset($) +{ + my $val = shift; + my $code = $iptcCharsetInv{uc($val)}; + unless ($code) { + if (($code = $val) =~ s/ESC */\x1b/ig) { # translate ESC chars + $code =~ s/, \x1b/\x1b/g; # remove comma separators + $code =~ tr/ //d; # remove spaces + } else { + warn "Bad syntax (use 'UTF8' or 'ESC X Y[, ...]')\n"; + } + } + return $code; +} + +#------------------------------------------------------------------------------ +# validate raw values for writing +# Inputs: 0) ExifTool object ref, 1) tagInfo hash ref, 2) raw value ref +# Returns: error string or undef (and possibly changes value) on success +sub CheckIPTC($$$) +{ + my ($et, $tagInfo, $valPtr) = @_; + my $format = $$tagInfo{Format} || $$tagInfo{Table}{FORMAT} || ''; + if ($format =~ /^int(\d+)/) { + my $bytes = int(($1 || 0) / 8); + if ($bytes ne 1 and $bytes ne 2 and $bytes ne 4) { + return "Can't write $bytes-byte integer"; + } + my $val = $$valPtr; + unless (Image::ExifTool::IsInt($val)) { + return 'Not an integer' unless Image::ExifTool::IsHex($val); + $val = $$valPtr = hex($val); + } + my $n; + for ($n=0; $n<$bytes; ++$n) { $val >>= 8; } + return "Value too large for $bytes-byte format" if $val; + } elsif ($format =~ /^(string|digits|undef)\[?(\d+),?(\d*)\]?$/) { + my ($fmt, $minlen, $maxlen) = ($1, $2, $3); + my $len = length $$valPtr; + if ($fmt eq 'digits') { + return 'Non-numeric characters in value' unless $$valPtr =~ /^\d*$/; + if ($len < $minlen and $len) { + # left pad with zeros if necessary + $$valPtr = ('0' x ($minlen - $len)) . $$valPtr; + $len = $minlen; + } + } + if (defined $minlen and $fmt ne 'string') { # (must truncate strings later, after recoding) + $maxlen or $maxlen = $minlen; + if ($len < $minlen) { + unless ($$et{OPTIONS}{IgnoreMinorErrors}) { + return "[Minor] String too short (minlen is $minlen)"; + } + $$et{CHECK_WARN} = "String too short for IPTC:$$tagInfo{Name} (written anyway)"; + } elsif ($len > $maxlen and not $$et{OPTIONS}{IgnoreMinorErrors}) { + $$et{CHECK_WARN} = "[Minor] IPTC:$$tagInfo{Name} exceeds length limit (truncated)"; + $$valPtr = substr($$valPtr, 0, $maxlen); + } + } + } else { + return "Bad IPTC Format ($format)"; + } + return undef; +} + +#------------------------------------------------------------------------------ +# format IPTC data for writing +# Inputs: 0) ExifTool object ref, 1) tagInfo pointer, +# 2) value reference (changed if necessary), +# 3) reference to character set for translation (changed if necessary) +# 4) record number, 5) flag set to read value (instead of write) +sub FormatIPTC($$$$$;$) +{ + my ($et, $tagInfo, $valPtr, $xlatPtr, $rec, $read) = @_; + my $format = $$tagInfo{Format} || $$tagInfo{Table}{FORMAT}; + return unless $format; + if ($format =~ /^int(\d+)/) { + if ($read) { + my $len = length($$valPtr); + if ($len <= 8) { # limit integer conversion to 8 bytes long + my $val = 0; + my $i; + for ($i=0; $i<$len; ++$i) { + $val = $val * 256 + ord(substr($$valPtr, $i, 1)); + } + $$valPtr = $val; + } + } else { + my $len = int(($1 || 0) / 8); + if ($len == 1) { # 1 byte + $$valPtr = chr($$valPtr); + } elsif ($len == 2) { # 2-byte integer + $$valPtr = pack('n', $$valPtr); + } else { # 4-byte integer + $$valPtr = pack('N', $$valPtr); + } + } + } elsif ($format =~ /^string/) { + if ($rec == 1) { + if ($$tagInfo{Name} eq 'CodedCharacterSet') { + $$xlatPtr = HandleCodedCharset($et, $$valPtr); + } + } elsif ($$xlatPtr and $rec < 7 and $$valPtr =~ /[\x80-\xff]/) { + TranslateCodedString($et, $valPtr, $xlatPtr, $read); + } + # must check length now (after any string recoding) + if (not $read and $format =~ /^string\[(\d+),?(\d*)\]$/) { + my ($minlen, $maxlen) = ($1, $2); + my $len = length $$valPtr; + $maxlen or $maxlen = $minlen; + if ($len < $minlen) { + if ($et->Warn("String to short for IPTC:$$tagInfo{Name} (padded)", 2)) { + $$valPtr .= ' ' x ($minlen - $len); + } + } elsif ($len > $maxlen) { + if ($et->Warn("IPTC:$$tagInfo{Name} exceeds length limit (truncated)", 2)) { + $$valPtr = substr($$valPtr, 0, $maxlen); + # make sure UTF-8 is still valid + if (($$xlatPtr || $et->Options('Charset')) eq 'UTF8') { + require Image::ExifTool::XMP; + Image::ExifTool::XMP::FixUTF8($valPtr,'.'); + } + } + } + } + } +} + +#------------------------------------------------------------------------------ +# generate IPTC-format date +# Inputs: 0) EXIF-format date string (YYYY:mm:dd) or date/time string +# Returns: IPTC-format date string (YYYYmmdd), or undef and issue warning on error +sub IptcDate($) +{ + my $val = shift; + unless ($val =~ s/^.*(\d{4}):?(\d{2}):?(\d{2}).*/$1$2$3/s) { + warn "Invalid date format (use YYYY:mm:dd)\n"; + undef $val; + } + return $val; +} + +#------------------------------------------------------------------------------ +# generate IPTC-format time +# Inputs: 0) EXIF-format time string (HH:MM:SS[+/-HH:MM]) or date/time string +# Returns: IPTC-format time string (HHMMSS+HHMM), or undef and issue warning on error +sub IptcTime($) +{ + my $val = shift; + if ($val =~ /(.*?)\b(\d{1,2})(:?)(\d{2})(:?)(\d{2})(\S*)\s*$/s and ($3 or not $5)) { + $val = sprintf("%.2d%.2d%.2d",$2,$4,$6); + my ($date, $tz) = ($1, $7); + if ($tz =~ /([+-]\d{1,2}):?(\d{2})/) { + $tz = sprintf("%+.2d%.2d",$1,$2); + } elsif ($tz =~ /Z/i) { + $tz = '+0000'; # UTC + } else { + # use local system timezone by default + my (@tm, $time); + if ($date and $date =~ /^(\d{4}):(\d{2}):(\d{2})\s*$/ and eval { require Time::Local }) { + # we were given a date too, so determine the local timezone + # offset at the specified date/time + my @d = ($3,$2-1,$1-1900); + $val =~ /(\d{2})(\d{2})(\d{2})/; + @tm = ($3,$2,$1,@d); + $time = Image::ExifTool::TimeLocal(@tm); + } else { + # it is difficult to get the proper local timezone offset for this + # time because the date tag is written separately. (The offset may be + # different on a different date due to daylight savings time.) In this + # case the best we can do easily is to use the current timezone offset. + $time = time; + @tm = localtime($time); + } + ($tz = Image::ExifTool::TimeZoneString(\@tm, $time)) =~ tr/://d; + } + $val .= $tz; + } else { + warn "Invalid time format (use HH:MM:SS[+/-HH:MM])\n"; + undef $val; # time format error + } + return $val; +} + +#------------------------------------------------------------------------------ +# Inverse print conversion for IPTC date or time value +# Inputs: 0) ExifTool ref, 1) IPTC date or 'now' +# Returns: IPTC date +sub InverseDateOrTime($$) +{ + my ($et, $val) = @_; + return $et->TimeNow() if lc($val) eq 'now'; + return $val; +} + +#------------------------------------------------------------------------------ +# Convert picture number +# Inputs: 0) value +# Returns: Converted value +sub ConvertPictureNumber($) +{ + my $val = shift; + if ($val eq "\0" x 16) { + $val = 'Unknown'; + } elsif (length $val >= 16) { + my @vals = unpack('nNA8n', $val); + $val = $vals[0]; + my $manu = $manufacturer{$val}; + $val .= " ($manu)" if $manu; + $val .= ', equip ' . $vals[1]; + $vals[2] =~ s/(\d{4})(\d{2})(\d{2})/$1:$2:$3/; + $val .= ", $vals[2], no. $vals[3]"; + } else { + $val = '<format error>' + } + return $val; +} + +#------------------------------------------------------------------------------ +# Inverse picture number conversion +# Inputs: 0) value +# Returns: Converted value (or undef on error) +sub InvConvertPictureNumber($) +{ + my $val = shift; + $val =~ s/\(.*\)//g; # remove manufacturer description + $val =~ tr/://d; # remove date separators + $val =~ tr/0-9/ /c; # turn remaining non-numbers to spaces + my @vals = split ' ', $val; + if (@vals >= 4) { + $val = pack('nNA8n', @vals); + } elsif ($val =~ /unknown/i) { + $val = "\0" x 16; + } else { + undef $val; + } + return $val; +} + +#------------------------------------------------------------------------------ +# Write IPTC data record +# Inputs: 0) ExifTool object ref, 1) source dirInfo ref, 2) tag table ref +# Returns: IPTC data block (may be empty if no IPTC data) +# Notes: Increments ExifTool CHANGED flag for each tag changed +sub DoWriteIPTC($$$) +{ + my ($et, $dirInfo, $tagTablePtr) = @_; + my $verbose = $et->Options('Verbose'); + my $out = $et->Options('TextOut'); + + # avoid editing IPTC directory unless necessary: + # - improves speed + # - avoids changing current MD5 digest unnecessarily + # - avoids adding mandatory tags unless some other IPTC is changed + unless (exists $$et{EDIT_DIRS}{$$dirInfo{DirName}} or + # standard IPTC tags in other locations should be edited too (eg. AFCP_IPTC) + ($tagTablePtr eq \%Image::ExifTool::IPTC::Main and exists $$et{EDIT_DIRS}{IPTC})) + { + print $out "$$et{INDENT} [nothing changed]\n" if $verbose; + return undef; + } + my $dataPt = $$dirInfo{DataPt}; + unless ($dataPt) { + my $emptyData = ''; + $dataPt = \$emptyData; + } + my $start = $$dirInfo{DirStart} || 0; + my $dirLen = $$dirInfo{DirLen}; + my ($tagInfo, %iptcInfo, $tag); + + # start by assuming default IPTC encoding + my $xlat = $et->Options('CharsetIPTC'); + undef $xlat if $xlat eq $et->Options('Charset'); + + # make sure our dataLen is defined (note: allow zero length directory) + unless (defined $dirLen) { + my $dataLen = $$dirInfo{DataLen}; + $dataLen = length($$dataPt) unless defined $dataLen; + $dirLen = $dataLen - $start; + } + # quick check for improperly byte-swapped IPTC + if ($dirLen >= 4 and substr($$dataPt, $start, 1) ne "\x1c" and + substr($$dataPt, $start + 3, 1) eq "\x1c") + { + $et->Warn('IPTC data was improperly byte-swapped'); + my $newData = pack('N*', unpack('V*', substr($$dataPt, $start, $dirLen) . "\0\0\0")); + $dataPt = \$newData; + $start = 0; + # NOTE: MUST NOT access $dirInfo DataPt, DirStart or DataLen after this! + } + # generate lookup so we can find the record numbers + my %recordNum; + foreach $tag (Image::ExifTool::TagTableKeys($tagTablePtr)) { + $tagInfo = $$tagTablePtr{$tag}; + $$tagInfo{SubDirectory} or next; + my $table = $$tagInfo{SubDirectory}{TagTable} or next; + my $subTablePtr = Image::ExifTool::GetTagTable($table); + $recordNum{$subTablePtr} = $tag; + } + + # loop through new values and accumulate all IPTC information + # into lists based on their IPTC record type + foreach $tagInfo ($et->GetNewTagInfoList()) { + my $table = $$tagInfo{Table}; + my $record = $recordNum{$table}; + # ignore tags we aren't writing to this directory + next unless defined $record; + $iptcInfo{$record} = [] unless defined $iptcInfo{$record}; + push @{$iptcInfo{$record}}, $tagInfo; + } + + # get sorted list of records used. Might as well be organized and + # write our records in order of record number first, then tag number + my @recordList = sort { $a <=> $b } keys %iptcInfo; + my ($record, %set); + foreach $record (@recordList) { + # sort tagInfo lists by tagID + @{$iptcInfo{$record}} = sort { $$a{TagID} <=> $$b{TagID} } @{$iptcInfo{$record}}; + # build hash of all tagIDs to set + foreach $tagInfo (@{$iptcInfo{$record}}) { + $set{$record}->{$$tagInfo{TagID}} = $tagInfo; + } + } + # run through the old IPTC data, inserting our records in + # sequence and deleting existing records where necessary + # (the IPTC specification states that records must occur in + # numerical order, but tags within records need not be ordered) + my $pos = $start; + my $tail = $pos; # old data written up to this point + my $dirEnd = $start + $dirLen; + my $newData = ''; + my $lastRec = -1; + my $lastRecPos = 0; + my $allMandatory = 0; + my %foundRec; # found flags: 0x01-existed before, 0x02-deleted, 0x04-created + my $addNow; + + for (;;$tail=$pos) { + # get next IPTC record from input directory + my ($id, $rec, $tag, $len, $valuePtr); + if ($pos + 5 <= $dirEnd) { + my $buff = substr($$dataPt, $pos, 5); + ($id, $rec, $tag, $len) = unpack("CCCn", $buff); + if ($id == 0x1c) { + if ($rec < $lastRec) { + if ($rec == 0) { + return undef if $et->Warn("IPTC record 0 encountered, subsequent records ignored", 2); + undef $rec; + $pos = $dirEnd; + $len = 0; + } else { + return undef if $et->Warn("IPTC doesn't conform to spec: Records out of sequence", 2); + } + } + # handle extended IPTC entry if necessary + $pos += 5; # step to after field header + if ($len & 0x8000) { + my $n = $len & 0x7fff; # get num bytes in length field + if ($pos + $n <= $dirEnd and $n <= 8) { + # determine length (a big-endian, variable sized int) + for ($len = 0; $n; ++$pos, --$n) { + $len = $len * 256 + ord(substr($$dataPt, $pos, 1)); + } + } else { + $len = $dirEnd; # invalid length + } + } + $valuePtr = $pos; + $pos += $len; # step $pos to next entry + # make sure we don't go past the end of data + # (this can only happen if original data is bad) + $pos = $dirEnd if $pos > $dirEnd; + } else { + undef $rec; + } + } + # write out all our records that come before this one + my $writeRec = (not defined $rec or $rec != $lastRec); + if ($writeRec or $addNow) { + for (;;) { + my $newRec = $recordList[0]; + if ($addNow) { + $tagInfo = $addNow; + } elsif (not defined $newRec or $newRec != $lastRec) { + # handle mandatory tags in last record unless it was empty + if (length $newData > $lastRecPos) { + if ($allMandatory > 1) { + # entire lastRec contained mandatory tags, and at least one tag + # was deleted, so delete entire record unless we specifically + # added a mandatory tag + my $num = 0; + foreach (keys %{$foundRec{$lastRec}}) { + my $code = $foundRec{$lastRec}->{$_}; + $num = 0, last if $code & 0x04; + ++$num if ($code & 0x03) == 0x01; + } + if ($num) { + $newData = substr($newData, 0, $lastRecPos); + $verbose > 1 and print $out " - $num mandatory tags\n"; + } + } elsif ($mandatory{$lastRec} and + $tagTablePtr eq \%Image::ExifTool::IPTC::Main) + { + # add required mandatory tags + my $mandatory = $mandatory{$lastRec}; + my ($mandTag, $subTablePtr); + foreach $mandTag (sort { $a <=> $b } keys %$mandatory) { + next if $foundRec{$lastRec}->{$mandTag}; + unless ($subTablePtr) { + $tagInfo = $$tagTablePtr{$lastRec}; + $tagInfo and $$tagInfo{SubDirectory} or warn("WriteIPTC: Internal error 1\n"), next; + $$tagInfo{SubDirectory}{TagTable} or next; + $subTablePtr = Image::ExifTool::GetTagTable($$tagInfo{SubDirectory}{TagTable}); + } + $tagInfo = $$subTablePtr{$mandTag} or warn("WriteIPTC: Internal error 2\n"), next; + my $value = $$mandatory{$mandTag}; + $et->VerboseValue("+ IPTC:$$tagInfo{Name}", $value, ' (mandatory)'); + # apply necessary format conversions + FormatIPTC($et, $tagInfo, \$value, \$xlat, $lastRec); + $len = length $value; + # generate our new entry + my $entry = pack("CCCn", 0x1c, $lastRec, $mandTag, length($value)); + $newData .= $entry . $value; # add entry to new IPTC data + # (don't mark as changed if just mandatory tags changed) + # ++$$et{CHANGED}; + } + } + } + last unless defined $newRec; + $lastRec = $newRec; + $lastRecPos = length $newData; + $allMandatory = 1; + } + unless ($addNow) { + # compare current entry with entry next in line to write out + # (write out our tags in numerical order even though + # this isn't required by the IPTC spec) + last if defined $rec and $rec <= $newRec; + $tagInfo = ${$iptcInfo{$newRec}}[0]; + } + my $newTag = $$tagInfo{TagID}; + my $nvHash = $et->GetNewValueHash($tagInfo); + # only add new values if... + my ($doSet, @values); + my $found = $foundRec{$newRec}->{$newTag} || 0; + if ($found & 0x02) { + # ...tag existed before and was deleted (unless we already added it) + $doSet = 1 unless $found & 0x04; + } elsif ($$tagInfo{List}) { + # ...tag is List and it existed before or we are creating it + $doSet = 1 if $found ? not $$nvHash{CreateOnly} : $$nvHash{IsCreating}; + } else { + # ...tag didn't exist before and we are creating it + $doSet = 1 if not $found and $$nvHash{IsCreating}; + } + if ($doSet) { + @values = $et->GetNewValue($nvHash); + @values and $foundRec{$newRec}->{$newTag} = $found | 0x04; + # write tags for each value in list + my $value; + foreach $value (@values) { + $et->VerboseValue("+ $$dirInfo{DirName}:$$tagInfo{Name}", $value); + # reset allMandatory flag if a non-mandatory tag is written + if ($allMandatory) { + my $mandatory = $mandatory{$newRec}; + $allMandatory = 0 unless $mandatory and $$mandatory{$newTag}; + } + # apply necessary format conversions + FormatIPTC($et, $tagInfo, \$value, \$xlat, $newRec); + # (note: IPTC string values are NOT null terminated) + $len = length $value; + # generate our new entry + my $entry = pack("CCC", 0x1c, $newRec, $newTag); + if ($len <= 0x7fff) { + $entry .= pack("n", $len); + } else { + # extended dataset tag + $entry .= pack("nN", 0x8004, $len); + } + $newData .= $entry . $value; # add entry to new IPTC data + ++$$et{CHANGED}; + } + } + # continue on with regular programming if done adding tag now + if ($addNow) { + undef $addNow; + next if $writeRec; + last; + } + # remove this tagID from the sorted write list + shift @{$iptcInfo{$newRec}}; + shift @recordList unless @{$iptcInfo{$newRec}}; + } + if ($writeRec) { + # all done if no more records to write + last unless defined $rec; + # update last record variables + $lastRec = $rec; + $lastRecPos = length $newData; + $allMandatory = 1; + } + } + # set flag indicating we found this tag + $foundRec{$rec}->{$tag} = ($foundRec{$rec}->{$tag} || 0) || 0x01; + # write out this record unless we are setting it with a new value + $tagInfo = $set{$rec}->{$tag}; + if ($tagInfo) { + my $nvHash = $et->GetNewValueHash($tagInfo); + $len = $pos - $valuePtr; + my $val = substr($$dataPt, $valuePtr, $len); + # remove null terminator if it exists (written by braindead software like Picasa 2.0) + $val =~ s/\0+$// if $$tagInfo{Format} and $$tagInfo{Format} =~ /^string/; + my $oldXlat = $xlat; + FormatIPTC($et, $tagInfo, \$val, \$xlat, $rec, 1); + if ($et->IsOverwriting($nvHash, $val)) { + $xlat = $oldXlat; # don't change translation (not writing this value) + $et->VerboseValue("- $$dirInfo{DirName}:$$tagInfo{Name}", $val); + ++$$et{CHANGED}; + # set deleted flag to indicate we found and deleted this tag + $foundRec{$rec}->{$tag} |= 0x02; + # increment allMandatory flag to indicate a tag was removed + $allMandatory and ++$allMandatory; + # write this tag now if overwriting an existing value + if ($$nvHash{Value} and @{$$nvHash{Value}} and @recordList and + $recordList[0] == $rec and not $foundRec{$rec}->{$tag} & 0x04) + { + $addNow = $tagInfo; + } + next; + } + } elsif ($rec == 1 and $tag == 90) { + # handle CodedCharacterSet tag + my $val = substr($$dataPt, $valuePtr, $pos - $valuePtr); + $xlat = HandleCodedCharset($et, $val); + } + # reset allMandatory flag if a non-mandatory tag is written + if ($allMandatory) { + my $mandatory = $mandatory{$rec}; + unless ($mandatory and $$mandatory{$tag}) { + $allMandatory = 0; + } + } + # write out the record + $newData .= substr($$dataPt, $tail, $pos-$tail); + } + # make sure the rest of the data is zero + if ($tail < $dirEnd) { + my $pad = substr($$dataPt, $tail, $dirEnd-$tail); + if ($pad =~ /[^\0]/) { + return undef if $et->Warn('Unrecognized data in IPTC padding', 2); + } + } + return $newData; +} + +#------------------------------------------------------------------------------ +# Write IPTC data record and calculate NewIPTCDigest +# Inputs: 0) ExifTool object ref, 1) source dirInfo ref, 2) tag table ref +# Returns: IPTC data block (may be empty if no IPTC data) +# Notes: Increments ExifTool CHANGED flag for each tag changed +sub WriteIPTC($$$) +{ + my ($et, $dirInfo, $tagTablePtr) = @_; + $et or return 1; # allow dummy access to autoload this package + + my $newData = DoWriteIPTC($et, $dirInfo, $tagTablePtr); + + # calculate standard IPTC digests only if we are writing or deleting + # Photoshop:IPTCDigest with a value of 'new' or 'old' + while ($Image::ExifTool::Photoshop::iptcDigestInfo) { + my $nvHash = $$et{NEW_VALUE}{$Image::ExifTool::Photoshop::iptcDigestInfo}; + last unless defined $nvHash; + last unless IsStandardIPTC($et->MetadataPath()); + my @values = $et->GetNewValue($nvHash); + push @values, @{$$nvHash{DelValue}} if $$nvHash{DelValue}; + my $new = grep /^new$/, @values; + my $old = grep /^old$/, @values; + last unless $new or $old; + unless (eval { require Digest::MD5 }) { + $et->Warn('Digest::MD5 must be installed to calculate IPTC digest'); + last; + } + my $dataPt; + if ($new) { + if (defined $newData) { + $dataPt = \$newData; + } else { + $dataPt = $$dirInfo{DataPt}; + if ($$dirInfo{DirStart} or length($$dataPt) != $$dirInfo{DirLen}) { + my $buff = substr($$dataPt, $$dirInfo{DirStart}, $$dirInfo{DirLen}); + $dataPt = \$buff; + } + } + # set NewIPTCDigest data member unless IPTC is being deleted + $$et{NewIPTCDigest} = Digest::MD5::md5($$dataPt) if length $$dataPt; + } + if ($old) { + if ($new and not defined $newData) { + $$et{OldIPTCDigest} = $$et{NewIPTCDigest}; + } elsif ($$dirInfo{DataPt}) { #(may be undef if creating new IPTC) + $dataPt = $$dirInfo{DataPt}; + if ($$dirInfo{DirStart} or length($$dataPt) != $$dirInfo{DirLen}) { + my $buff = substr($$dataPt, $$dirInfo{DirStart}, $$dirInfo{DirLen}); + $dataPt = \$buff; + } + $$et{OldIPTCDigest} = Digest::MD5::md5($$dataPt) if length $$dataPt; + } + } + last; + } + # set changed if ForceWrite tag was set to "IPTC" + ++$$et{CHANGED} if defined $newData and length $newData and $$et{FORCE_WRITE}{IPTC}; + return $newData; +} + + +1; # end + +__END__ + +=head1 NAME + +Image::ExifTool::WriteIPTC.pl - Write IPTC meta information + +=head1 SYNOPSIS + +This file is autoloaded by Image::ExifTool::IPTC. + +=head1 DESCRIPTION + +This file contains routines to write IPTC metadata, plus a few other +seldom-used routines. + +=head1 AUTHOR + +Copyright 2003-2019, Phil Harvey (phil at owl.phy.queensu.ca) + +This library is free software; you can redistribute it and/or modify it +under the same terms as Perl itself. + +=head1 SEE ALSO + +L<Image::ExifTool::IPTC(3pm)|Image::ExifTool::IPTC>, +L<Image::ExifTool(3pm)|Image::ExifTool> + +=cut diff --git a/lib/Image/ExifTool/WritePDF.pl b/lib/Image/ExifTool/WritePDF.pl new file mode 100644 index 0000000..c54a2ed --- /dev/null +++ b/lib/Image/ExifTool/WritePDF.pl @@ -0,0 +1,772 @@ +#------------------------------------------------------------------------------ +# File: WritePDF.pl +# +# Description: Write PDF meta information +# +# Revisions: 12/08/2007 - P. Harvey Created +# +# References: 1) http://partners.adobe.com/public/developer/pdf/index_reference.html +# +# Notes: The special "PDF-update" group can be deleted to revert exiftool updates +#------------------------------------------------------------------------------ +package Image::ExifTool::PDF; + +use strict; +use vars qw($lastFetched); + +sub WriteObject($$); +sub EncodeString($); +sub CryptObject($); + +# comments to mark beginning and end of ExifTool incremental update +my $beginComment = '%BeginExifToolUpdate'; +my $endComment = '%EndExifToolUpdate '; + +my $keyExt; # crypt key extension +my $pdfVer; # version of PDF file we are currently writing + +# internal tags used in dictionary objects +my %myDictTags = ( + _tags => 1, _stream => 1, _decrypted => 1, _needCrypt => 1, + _filtered => 1, _entry_size => 1, _table => 1, +); + +# map for directories that we can add +my %pdfMap = ( + XMP => 'PDF', +); + +#------------------------------------------------------------------------------ +# Validate raw PDF values for writing (string date integer real boolean name) +# Inputs: 0) ExifTool object ref, 1) tagInfo hash ref, 2) raw value ref +# Returns: error string or undef (and possibly changes value) on success +sub CheckPDF($$$) +{ + my ($et, $tagInfo, $valPtr) = @_; + my $format = $$tagInfo{Writable} || $tagInfo->{Table}->{WRITABLE}; + if (not $format) { + return 'No writable format'; + } elsif ($format eq 'string') { + # (encode later because list-type string tags need to be encoded as a unit) + } elsif ($format eq 'date') { + # be flexible about this for now + return 'Bad date format' unless $$valPtr =~ /^\d{4}/; + } elsif ($format eq 'integer') { + return 'Not an integer' unless Image::ExifTool::IsInt($$valPtr); + } elsif ($format eq 'real') { + return 'Not a real number' unless $$valPtr =~ /^[+-]?(?=\d|\.\d)\d*(\.\d*)?$/; + } elsif ($format eq 'boolean') { + $$valPtr = ($$valPtr and $$valPtr !~ /^f/i) ? 'true' : 'false'; + } elsif ($format eq 'name') { + return 'Invalid PDF name' if $$valPtr =~ /\0/; + } else { + return "Invalid PDF format '${format}'"; + } + return undef; # value is OK +} + +#------------------------------------------------------------------------------ +# Format value for writing to PDF file +# Inputs: 0) ExifTool ref, 1) value, 2) format string (string,date,integer,real,boolean,name) +# Returns: formatted value or undef on error +# Notes: Called at write time, so $pdfVer may be checked +sub WritePDFValue($$$) +{ + my ($et, $val, $format) = @_; + if (not $format) { + return undef; + } elsif ($format eq 'string') { + # encode as UCS2 if it contains any special characters + $val = "\xfe\xff" . $et->Encode($val,'UCS2','MM') if $val =~ /[\x80-\xff]/; + EncodeString(\$val); + } elsif ($format eq 'date') { + # convert date to "D:YYYYmmddHHMMSS+-HH'MM'" format + $val =~ s/([-+]\d{2}):(\d{2})/${1}'${2}'/; # change timezone delimiters if necessary + $val =~ tr/ ://d; # remove spaces and colons + $val = "D:$val"; # add leading "D:" + EncodeString(\$val); + } elsif ($format =~ /^(integer|real|boolean)$/) { + # no reformatting necessary + } elsif ($format eq 'name') { + return undef if $val =~ /\0/; + if ($pdfVer >= 1.2) { + $val =~ s/([\t\n\f\r ()<>[\]{}\/%#])/sprintf('#%.2x',ord $1)/sge; + } else { + return undef if $val =~ /[\t\n\f\r ()<>[\]{}\/%]/; + } + $val = "/$val"; # add leading '/' + } else { + return undef; + } + return $val; +} + +#------------------------------------------------------------------------------ +# Encode PDF string +# Inputs: 0) reference to PDF string +# Returns: (updates string with encoded data) +sub EncodeString($) +{ + my $strPt = shift; + if (ref $$strPt eq 'ARRAY') { + my $str; + foreach $str (@{$$strPt}) { + EncodeString(\$str); + } + return; + } + Crypt($strPt, $keyExt, 1); # encrypt if necessary + # encode as hex if we have any control characters (except tab) + if ($$strPt=~/[\x00-\x08\x0a-\x1f\x7f\xff]/) { + # encode as hex + my $str=''; + my $len = length $$strPt; + my $i = 0; + for (;;) { + my $n = $len - $i or last; + $n = 40 if $n > 40; # break into reasonable-length lines + $str .= $/ if $i; + $str .= unpack('H*', substr($$strPt, $i, $n)); + $i += $n; + } + $$strPt = "<$str>"; + } else { + $$strPt =~ s/([()\\])/\\$1/g; # must escape round brackets and backslashes + $$strPt = "($$strPt)"; + } +} + +#------------------------------------------------------------------------------ +# Encrypt an object +# Inputs: 0) PDF object (encrypts in place) +# Notes: Encrypts according to "_needCrypt" dictionary entry, +# then deletes "_needCrypt" when done +sub CryptObject($) +{ + my $obj = $_[0]; + if (not ref $obj) { + # only literal strings and hex strings are encrypted + if ($obj =~ /^[(<]/) { + undef $lastFetched; # (reset this just in case) + my $val = ReadPDFValue($obj); + EncodeString(\$val); + $_[0] = $val; + } + } elsif (ref $obj eq 'HASH') { + my $tag; + my $needCrypt = $$obj{_needCrypt}; + foreach $tag (keys %$obj) { + next if $myDictTags{$tag}; + # re-encrypt necessary objects only (others are still encrypted) + # (this is really annoying, but is necessary because objects stored + # in encrypted streams are decrypted when extracting, but strings stored + # as direct objects are decrypted later since they must be decoded + # before being decrypted) + if ($needCrypt) { + next unless defined $$needCrypt{$tag} ? $$needCrypt{$tag} : $$needCrypt{'*'}; + } + CryptObject($$obj{$tag}); + } + delete $$obj{_needCrypt}; # avoid re-re-crypting + } elsif (ref $obj eq 'ARRAY') { + my $val; + foreach $val (@$obj) { + CryptObject($val); + } + } +} + +#------------------------------------------------------------------------------ +# Get free entries from xref stream dictionary that we wrote previously +# Inputs: 0) xref dictionary reference +# Returns: free entry hash (keys are object numbers, values are xref entry list refs) +sub GetFreeEntries($) +{ + my $dict = shift; + my %xrefFree; + # from the start we have only written xref stream entries in 'CNn' format, + # so we can simplify things for now and only support this type of entry + my $w = $$dict{W}; + if (ref $w eq 'ARRAY' and "@$w" eq '1 4 2') { + my $size = $$dict{_entry_size}; # this will be 7 for 'CNn' + my $index = $$dict{Index}; + my $len = length $$dict{_stream}; + # scan the table for free objects + my $num = scalar(@$index) / 2; + my $pos = 0; + my ($i, $j); + for ($i=0; $i<$num; ++$i) { + my $start = $$index[$i*2]; + my $count = $$index[$i*2+1]; + for ($j=0; $j<$count; ++$j) { + last if $pos + $size > $len; + my @t = unpack("x$pos CNn", $$dict{_stream}); + # add entry if object was free + $xrefFree{$start+$j} = [ $t[1], $t[2], 'f' ] if $t[0] == 0; + $pos += $size; # step to next entry + } + } + } + return \%xrefFree; +} + +#------------------------------------------------------------------------------ +# Write PDF object +# Inputs: 0) output file or scalar ref, 1) PDF object +# Returns: true on success +# Notes: inserts white space before object, but none afterward +sub WriteObject($$) +{ + my ($outfile, $obj) = @_; + if (ref $obj eq 'SCALAR') { + Write($outfile, ' ', $$obj) or return 0; + } elsif (ref $obj eq 'ARRAY') { + # write array + Write($outfile, @$obj > 10 ? $/ : ' ', '[') or return 0; + my $item; + foreach $item (@$obj) { + WriteObject($outfile, $item) or return 0; + } + Write($outfile, ' ]') or return 0; + } elsif (ref $obj eq 'HASH') { + # write dictionary + my $tag; + Write($outfile, $/, '<<') or return 0; + # prepare object as required if it has a stream + if ($$obj{_stream}) { + # encrypt stream if necessary (must be done before determining Length) + CryptStream($obj, $keyExt) if $$obj{_decrypted}; + # write "Length" entry in dictionary + $$obj{Length} = length $$obj{_stream}; + push @{$$obj{_tags}}, 'Length'; + # delete Filter-related entries since we don't yet write filtered streams + delete $$obj{Filter}; + delete $$obj{DecodeParms}; + delete $$obj{DL}; + } + # don't write my internal entries + my %wrote = %myDictTags; + # write tags in original order, adding new ones later alphabetically + foreach $tag (@{$$obj{_tags}}, sort keys %$obj) { + # ignore already-written or missing entries + next if $wrote{$tag} or not defined $$obj{$tag}; + Write($outfile, $/, "/$tag") or return 0; + WriteObject($outfile, $$obj{$tag}) or return 0; + $wrote{$tag} = 1; + } + Write($outfile, $/, '>>') or return 0; + if ($$obj{_stream}) { + # write object stream + # (a single 0x0d may not follow 'stream', so use 0x0d+0x0a here to be sure) + Write($outfile, $/, "stream\x0d\x0a") or return 0; + Write($outfile, $$obj{_stream}, $/, 'endstream') or return 0; + } + } else { + # write string, number, name or object reference + Write($outfile, ' ', $obj); + } + return 1; +} + +#------------------------------------------------------------------------------ +# Write PDF File +# Inputs: 0) ExifTool object reference, 1) dirInfo reference +# Returns: 1 on success, 0 if not valid PDF file, -1 on write error +# Notes: dictionary structure: Main --+--> Info +# +--> Root --> Metadata +sub WritePDF($$) +{ + my ($et, $dirInfo) = @_; + my $raf = $$dirInfo{RAF}; + my $outfile = $$dirInfo{OutFile}; + my ($buff, %capture, %newXRef, %newObj, $objRef); + my ($out, $id, $gen, $obj); + + # make sure this is a PDF file + my $pos = $raf->Tell(); + $raf->Read($buff, 1024) >= 8 or return 0; + $buff =~ /^(\s*)%PDF-(\d+\.\d+)/ or return 0; + $$et{PDFBase} = length $1; + $raf->Seek($pos, 0); + + # create a new ExifTool object and use it to read PDF and XMP information + my $newTool = new Image::ExifTool; + $newTool->Options(List => 1); + $newTool->Options(Password => $et->Options('Password')); + $$newTool{PDF_CAPTURE} = \%capture; + my $info = $newTool->ImageInfo($raf, 'XMP', 'PDF:*', 'Error', 'Warning'); + # not a valid PDF file unless we got a version number + # (note: can't just check $$info{PDFVersion} due to possibility of XMP-pdf:PDFVersion) + my $vers = $newTool->GetInfo('PDF:PDFVersion'); + ($pdfVer) = values %$vers; + $pdfVer or $et->Error('Missing PDF:PDFVersion'), return 0; + # check version number + if ($pdfVer > 1.7) { + if ($pdfVer >= 2.0) { + $et->Error("Can't yet write PDF version $pdfVer"); # (future major version changes) + return 1; + } + $et->Warn("ExifTool is untested with PDF version $pdfVer files", 1); + } + # fail if we had any serious errors while extracting information + if ($capture{Error} or $$info{Error}) { + $et->Error($capture{Error} || $$info{Error}); + return 1; + } + # make sure we have everything we need to rewrite this file + foreach $obj (qw(Main Root xref)) { + next if $capture{$obj}; + # any warning we received may give a clue about why this object is missing + $et->Error($$info{Warning}) if $$info{Warning}; + $et->Error("Can't find $obj object"); + return 1; + } + $et->InitWriteDirs(\%pdfMap, 'XMP'); + + # copy file up to start of previous exiftool update or end of file + # (comment, startxref & EOF with 11-digit offsets and 2-byte newlines is 63 bytes) + $raf->Seek(-64,2) and $raf->Read($buff,64) and $raf->Seek(0,0) or return -1; + my $rtn = 1; + my $prevUpdate; + # (now $endComment is before "startxref", but pre-7.41 we wrote it after the EOF) + if ($buff =~ /$endComment(\d+)\s+(startxref\s+\d+\s+%%EOF\s+)?$/s) { + $prevUpdate = $1; + # rewrite the file up to the original EOF + Image::ExifTool::CopyBlock($raf, $outfile, $prevUpdate + $$et{PDFBase}) or $rtn = -1; + # verify that we are now at the start of an ExifTool update + unless ($raf->Read($buff, length $beginComment) and $buff eq $beginComment) { + $et->Error('Previous ExifTool update is corrupted'); + return $rtn; + } + $raf->Seek($prevUpdate+$$et{PDFBase}, 0) or $rtn = -1; + if ($$et{DEL_GROUP}{'PDF-update'}) { + $et->VPrint(0, " Reverted previous ExifTool updates\n"); + ++$$et{CHANGED}; + return $rtn; + } + } elsif ($$et{DEL_GROUP}{'PDF-update'}) { + $et->Error('File contains no previous ExifTool update'); + return $rtn; + } else { + # rewrite the whole file + while ($raf->Read($buff, 65536)) { + Write($outfile, $buff) or $rtn = -1; + } + } + $out = $et->Options('TextOut') if $et->Options('Verbose'); +# +# create our new PDF objects to write +# + my $xref = $capture{xref}; + my $mainDict = $capture{Main}; + my $metaRef = $capture{Root}->{Metadata}; + my $nextObject; + + # start by finding reference for info object in case it was deleted + # in a previous edit so we can re-use it here if adding PDF Info + my $prevInfoRef; + if ($prevUpdate) { + unless ($capture{Prev}) { + $et->Error("Can't locate trailer dictionary prior to last edit"); + return $rtn; + } + $prevInfoRef = $capture{Prev}->{Info}; + # start from previous size so the xref table doesn't continue + # to grow if we repeatedly add and delete the Metadata object + $nextObject = $capture{Prev}->{Size}; + # don't re-use Meta reference if object was added in a previous update + undef $metaRef if $metaRef and $$metaRef=~/^(\d+)/ and $1 >= $nextObject; + } else { + $prevInfoRef = $$mainDict{Info}; + $nextObject = $$mainDict{Size}; + } + + # delete entire PDF group if specified + my $infoChanged = 0; + if ($$et{DEL_GROUP}{PDF} and $capture{Info}) { + delete $capture{Info}; + $info = { XMP => $$info{XMP} }; # remove extracted PDF tags + print $out " Deleting PDF Info dictionary\n" if $out; + ++$infoChanged; + } + + # create new Info dictionary if necessary + $capture{Info} = { _tags => [ ] } unless $capture{Info}; + my $infoDict = $capture{Info}; + + # must pre-determine Info reference to be used in encryption + my $infoRef = $prevInfoRef || \ "$nextObject 0 R"; + $keyExt = $$infoRef; + + # must encrypt all values in dictionary if they came from an encrypted stream + CryptObject($infoDict) if $$infoDict{_needCrypt}; + + # must set line separator before calling WritePDFValue() + local $/ = $capture{newline}; + + # rewrite PDF Info tags + my $newTags = $et->GetNewTagInfoHash(\%Image::ExifTool::PDF::Info); + my $tagID; + foreach $tagID (sort keys %$newTags) { + my $tagInfo = $$newTags{$tagID}; + my $nvHash = $et->GetNewValueHash($tagInfo); + my (@vals, $deleted); + my $tag = $$tagInfo{Name}; + my $val = $$info{$tag}; + my $tagKey = $tag; + unless (defined $val) { + # must check for tag key with copy number + ($tagKey) = grep /^$tag/, keys %$info; + $val = $$info{$tagKey} if $tagKey; + } + if (defined $val) { + my @oldVals; + if (ref $val eq 'ARRAY') { + @oldVals = @$val; + $val = shift @oldVals; + } + for (;;) { + if ($et->IsOverwriting($nvHash, $val) > 0) { + $deleted = 1; + $et->VerboseValue("- PDF:$tag", $val); + ++$infoChanged; + } else { + push @vals, $val; + } + last unless @oldVals; + $val = shift @oldVals; + } + # don't write this out if we deleted all values + delete $$infoDict{$tagID} unless @vals; + } elsif ($$nvHash{EditOnly}) { + next; + } + # decide whether we want to write this tag + # (native PDF information is always preferred, so don't check IsCreating) + next unless $deleted or $$tagInfo{List} or not exists $$infoDict{$tagID}; + + # add new values to existing ones + my @newVals = $et->GetNewValue($nvHash); + if (@newVals) { + push @vals, @newVals; + ++$infoChanged; + if ($out) { + foreach $val (@newVals) { + $et->VerboseValue("+ PDF:$tag", $val); + } + } + } + unless (@vals) { + # remove this entry from the Info dictionary if no values remain + delete $$infoDict{$tagID}; + next; + } + # format value(s) for writing to PDF file + my $writable = $$tagInfo{Writable} || $Image::ExifTool::PDF::Info{WRITABLE}; + if (not $$tagInfo{List}) { + $val = WritePDFValue($et, shift(@vals), $writable); + } elsif ($$tagInfo{List} eq 'array') { + foreach $val (@vals) { + $val = WritePDFValue($et, $val, $writable); + defined $val or undef(@vals), last; + } + $val = @vals ? \@vals : undef; + } else { + $val = WritePDFValue($et, join($et->Options('ListSep'), @vals), $writable); + } + if (defined $val) { + $$infoDict{$tagID} = $val; + ++$infoChanged; + } else { + $et->Warn("Error converting $$tagInfo{Name} value"); + } + } + if ($infoChanged) { + $$et{CHANGED} += $infoChanged; + } elsif ($prevUpdate) { + # must still write Info dictionary if it was previously updated + my $oldPos = LocateObject($xref, $$infoRef); + $infoChanged = 1 if $oldPos and $oldPos > $prevUpdate; + } + + # create new Info dictionary if necessary + if ($infoChanged) { + # increment object count if we used a new object here + if (scalar(keys %{$capture{Info}}) > 1) { + $newObj{$$infoRef} = $capture{Info};# save to write later + $$mainDict{Info} = $infoRef; # add reference to trailer dictionary + ++$nextObject unless $prevInfoRef; + } else { + # remove Info from Main (trailer) dictionary + delete $$mainDict{Info}; + # write free entry in xref table if Info existed prior to all edits + $newObj{$$infoRef} = '' if $prevInfoRef; + } + } + + # rewrite XMP + my %xmpInfo = ( + DataPt => $$info{XMP}, + Parent => 'PDF', + ); + my $xmpTable = Image::ExifTool::GetTagTable('Image::ExifTool::XMP::Main'); + my $oldChanged = $$et{CHANGED}; + my $newXMP = $et->WriteDirectory(\%xmpInfo, $xmpTable); + $newXMP = $$info{XMP} ? ${$$info{XMP}} : '' unless defined $newXMP; + + # WriteDirectory() will increment CHANGED erroneously if non-existent + # XMP is deleted as a block -- so check for this + unless ($newXMP or $$info{XMP}) { + $$et{CHANGED} = $oldChanged; + $et->VPrint(0, " (XMP not changed -- still empty)\n"); + } + my ($metaChanged, $rootChanged); + + if ($$et{CHANGED} != $oldChanged and defined $newXMP) { + $metaChanged = 1; + } elsif ($prevUpdate and $capture{Root}->{Metadata}) { + # must still write Metadata dictionary if it was previously updated + my $oldPos = LocateObject($xref, ${$capture{Root}->{Metadata}}); + $metaChanged = 1 if $oldPos and $oldPos > $prevUpdate; + } + if ($metaChanged) { + if ($newXMP) { + unless ($metaRef) { + # allocate new PDF object + $metaRef = \ "$nextObject 0 R"; + ++$nextObject; + $capture{Root}->{Metadata} = $metaRef; + $rootChanged = 1; # set flag to replace Root dictionary + } + # create the new metadata dictionary to write later + $newObj{$$metaRef} = { + Type => '/Metadata', + Subtype => '/XML', + # Length => length $newXMP, (set by WriteObject) + _tags => [ qw(Type Subtype) ], + _stream => $newXMP, + _decrypted => 1, # (this will be ignored if EncryptMetadata is false) + }; + } elsif ($capture{Root}->{Metadata}) { + # free existing metadata object + $newObj{${$capture{Root}->{Metadata}}} = ''; + delete $capture{Root}->{Metadata}; + $rootChanged = 1; # set flag to replace Root dictionary + } + } + # add new Root dictionary if necessary + my $rootRef = $$mainDict{Root}; + unless ($rootRef) { + $et->Error("Can't find Root dictionary"); + return $rtn; + } + if (not $rootChanged and $prevUpdate) { + # must still write Root dictionary if it was previously updated + my $oldPos = LocateObject($xref, $$rootRef); + $rootChanged = 1 if $oldPos and $oldPos > $prevUpdate; + } + $newObj{$$rootRef} = $capture{Root} if $rootChanged; +# +# write incremental update if anything was changed +# + if ($$et{CHANGED}) { + # remember position of original EOF + my $oldEOF = Tell($outfile) - $$et{PDFBase}; + Write($outfile, $beginComment) or $rtn = -1; + + # write new objects + foreach $objRef (sort keys %newObj) { + $objRef =~ /^(\d+) (\d+)/ or $rtn = -1, last; + ($id, $gen) = ($1, $2); + if (not $newObj{$objRef}) { + ++$gen if $gen < 65535; + # write free entry in xref table + $newXRef{$id} = [ 0, $gen, 'f' ]; + next; + } + # create new entry for xref table + $newXRef{$id} = [ Tell($outfile) - $$et{PDFBase} + length($/), $gen, 'n' ]; + $keyExt = "$id $gen obj"; # (must set for stream encryption) + Write($outfile, $/, $keyExt) or $rtn = -1; + WriteObject($outfile, $newObj{$objRef}) or $rtn = -1; + Write($outfile, $/, 'endobj') or $rtn = -1; + } + + # Prev points to old xref table + $$mainDict{Prev} = $capture{startxref} unless $prevUpdate; + + # add xref entry for head of free-object list + $newXRef{0} = [ 0, 65535, 'f' ]; + + # must insert free xref entries from previous exiftool update if applicable + if ($prevUpdate) { + my $mainFree; + # extract free entries from our previous Main xref stream + if ($$mainDict{Type} and $$mainDict{Type} eq '/XRef') { + $mainFree = GetFreeEntries($xref->{dicts}->[0]); + } else { + # free entries from Main xref table already captured for us + $mainFree = $capture{mainFree}; + } + foreach $id (sort { $a <=> $b } keys %$mainFree) { + $newXRef{$id} = $$mainFree{$id} unless $newXRef{$id}; + } + } + + # connect linked list of free object in our xref table + my $prevFree = 0; + foreach $id (sort { $b <=> $a } keys %newXRef) { # (reverse sort) + next unless $newXRef{$id}->[2] eq 'f'; # skip if not free + # no need to add free entry for objects added by us + # in previous edits then freed again + if ($id >= $nextObject) { + delete $newXRef{$id}; # Note: deleting newXRef entry! + next; + } + $newXRef{$id}->[0] = $prevFree; + $prevFree = $id; + } + + # prepare our main dictionary for writing + $$mainDict{Size} = $nextObject; # update number of objects + # must change the ID if it exists + if (ref $$mainDict{ID} eq 'ARRAY' and @{$$mainDict{ID}} > 1) { + # increment first byte since this is an easy change to make + $id = $mainDict->{ID}->[1]; + if ($id =~ /^<([0-9a-f]{2})/i) { + my $byte = unpack('H2',chr((hex($1) + 1) & 0xff)); + substr($id, 1, 2) = $byte; + } elsif ($id =~ /^\((.)/s and $1 ne '\\' and $1 ne ')' and $1 ne '(') { + my $ch = chr((ord($1) + 1) & 0xff); + # avoid generating characters that could cause problems + $ch = 'a' if $ch =~ /[()\\\x00-\x08\x0a-\x1f\x7f\xff]/; + substr($id, 1, 1) = $ch; + } + $mainDict->{ID}->[1] = $id; + } + + # remember position of xref table in file (we will write this next) + my $startxref = Tell($outfile) - $$et{PDFBase} + length($/); + + # must write xref as a stream in xref-stream-only files + if ($$mainDict{Type} and $$mainDict{Type} eq '/XRef') { + + # create entry for the xref stream object itself + $newXRef{$nextObject++} = [ Tell($outfile) - $$et{PDFBase} + length($/), 0, 'n' ]; + $$mainDict{Size} = $nextObject; + # create xref stream and Index entry + $$mainDict{W} = [ 1, 4, 2 ]; # int8u, int32u, int16u ('CNn') + $$mainDict{Index} = [ ]; + $$mainDict{_stream} = ''; + my @ids = sort { $a <=> $b } keys %newXRef; + while (@ids) { + my $startID = $ids[0]; + for (;;) { + $id = shift @ids; + my ($pos, $gen, $type) = @{$newXRef{$id}}; + if ($pos > 0xffffffff) { + $et->Error('Huge files not yet supported'); + last; + } + $$mainDict{_stream} .= pack('CNn', $type eq 'f' ? 0 : 1, $pos, $gen); + last if not @ids or $ids[0] != $id + 1; + } + # add Index entries for this section of the xref stream + push @{$$mainDict{Index}}, $startID, $id - $startID + 1; + } + # write the xref stream object + $keyExt = "$id 0 obj"; # (set anyway, but xref stream should NOT be encrypted) + Write($outfile, $/, $keyExt) or $rtn = -1; + WriteObject($outfile, $mainDict) or $rtn = -1; + Write($outfile, $/, 'endobj') or $rtn = -1; + + } else { + + # write new xref table + Write($outfile, $/, 'xref', $/) or $rtn = -1; + # lines must be exactly 20 bytes, so pad newline if necessary + my $endl = (length($/) == 1 ? ' ' : '') . $/; + my @ids = sort { $a <=> $b } keys %newXRef; + while (@ids) { + my $startID = $ids[0]; + $buff = ''; + for (;;) { + $id = shift @ids; + $buff .= sprintf("%.10d %.5d %s%s", @{$newXRef{$id}}, $endl); + last if not @ids or $ids[0] != $id + 1; + } + # write this (contiguous-numbered object) section of the xref table + Write($outfile, $startID, ' ', $id - $startID + 1, $/, $buff) or $rtn = -1; + } + + # write main (trailer) dictionary + Write($outfile, 'trailer') or $rtn = -1; + WriteObject($outfile, $mainDict) or $rtn = -1; + } + # write trailing comment (marker to allow edits to be reverted) + Write($outfile, $/, $endComment, $oldEOF, $/) or $rtn = -1; + + # write pointer to main xref table and EOF marker + Write($outfile, 'startxref', $/, $startxref, $/, '%%EOF', $/) or $rtn = -1; + + } elsif ($prevUpdate) { + + # nothing new changed, so copy over previous incremental update + $raf->Seek($prevUpdate+$$et{PDFBase}, 0) or $rtn = -1; + while ($raf->Read($buff, 65536)) { + Write($outfile, $buff) or $rtn = -1; + } + } + if ($rtn > 0 and $$et{CHANGED} and ($$et{DEL_GROUP}{PDF} or $$et{DEL_GROUP}{XMP})) { + $et->Warn('ExifTool PDF edits are reversible. Deleted tags may be recovered!', 1); + } + undef $newTool; + undef %capture; + return $rtn; +} + + +1; # end + +__END__ + +=head1 NAME + +Image::ExifTool::WritePDF.pl - Write PDF meta information + +=head1 SYNOPSIS + +These routines are autoloaded by Image::ExifTool::PDF. + +=head1 DESCRIPTION + +This file contains routines to write PDF metadata. + +=head1 NOTES + +When writing a PDF, exiftool does not modify the existing data. Instead, +the PDF file is appended with an incremental update which can easily be +removed to revert the file (by using ExifTool to delete the special +C<PDF-update> pseudo group). + +=head1 AUTHOR + +Copyright 2003-2019, Phil Harvey (phil at owl.phy.queensu.ca) + +This library is free software; you can redistribute it and/or modify it +under the same terms as Perl itself. + +=head1 REFERENCES + +=over 4 + +=item L<http://partners.adobe.com/public/developer/pdf/index_reference.html> + +=back + +=head1 SEE ALSO + +L<Image::ExifTool::PDF(3pm)|Image::ExifTool::PDF>, +L<Image::ExifTool(3pm)|Image::ExifTool> + +=cut diff --git a/lib/Image/ExifTool/WritePNG.pl b/lib/Image/ExifTool/WritePNG.pl new file mode 100644 index 0000000..a693021 --- /dev/null +++ b/lib/Image/ExifTool/WritePNG.pl @@ -0,0 +1,408 @@ +#------------------------------------------------------------------------------ +# File: WritePNG.pl +# +# Description: Write PNG meta information +# +# Revisions: 09/16/2005 - P. Harvey Created +# +# References: 1) http://www.libpng.org/pub/png/spec/1.2/ +#------------------------------------------------------------------------------ +package Image::ExifTool::PNG; + +use strict; + +#------------------------------------------------------------------------------ +# Calculate CRC or update running CRC (ref 1) +# Inputs: 0) data reference, 1) running crc to update (undef intially) +# 2) data position (undef for 0), 3) data length (undef for all data), +# Returns: updated CRC +my @crcTable; +sub CalculateCRC($;$$$) +{ + my ($dataPt, $crc, $pos, $len) = @_; + $crc = 0 unless defined $crc; + $pos = 0 unless defined $pos; + $len = length($$dataPt) - $pos unless defined $len; + $crc ^= 0xffffffff; # undo 1's complement + # build lookup table unless done already + unless (@crcTable) { + my ($c, $n, $k); + for ($n=0; $n<256; ++$n) { + for ($k=0, $c=$n; $k<8; ++$k) { + $c = ($c & 1) ? 0xedb88320 ^ ($c >> 1) : $c >> 1; + } + $crcTable[$n] = $c; + } + } + # calculate the CRC + foreach (unpack("x${pos}C$len", $$dataPt)) { + $crc = $crcTable[($crc^$_) & 0xff] ^ ($crc >> 8); + } + return $crc ^ 0xffffffff; # return 1's complement +} + +#------------------------------------------------------------------------------ +# Encode data in ASCII Hex +# Inputs: 0) input data reference +# Returns: Hex-encoded data (max 72 chars per line) +sub HexEncode($) +{ + my $dataPt = shift; + my $len = length($$dataPt); + my $hex = ''; + my $pos; + for ($pos = 0; $pos < $len; $pos += 36) { + my $n = $len - $pos; + $n > 36 and $n = 36; + $hex .= unpack('H*',substr($$dataPt,$pos,$n)) . "\n"; + } + return $hex; +} + +#------------------------------------------------------------------------------ +# Write profile chunk (possibly compressed if Zlib is available) +# Inputs: 0) outfile, 1) Raw profile type, 2) data ref +# 3) profile header type (undef if not a text profile) +# Returns: 1 on success +sub WriteProfile($$$;$) +{ + my ($outfile, $rawType, $dataPt, $profile) = @_; + my ($buff, $prefix, $chunk, $deflate); + if ($rawType ne $stdCase{exif} and eval { require Compress::Zlib }) { + $deflate = Compress::Zlib::deflateInit(); + } + if (not defined $profile) { + # write ICC profile as compressed iCCP chunk if possible + if ($rawType eq 'icm') { + return 0 unless $deflate; + $chunk = 'iCCP'; + $prefix = "$rawType\0\0"; + } else { + $chunk = $rawType; + if ($rawType eq $stdCase{zxif}) { + $prefix = "\0" . pack('N', length $$dataPt); + } else { + $prefix = ''; + } + } + if ($deflate) { + $buff = $deflate->deflate($$dataPt); + return 0 unless defined $buff; + $buff .= $deflate->flush(); + $dataPt = \$buff; + } + } else { + # write as ASCII-hex encoded profile in tEXt or zTXt chunk + my $txtHdr = sprintf("\n$profile profile\n%8d\n", length($$dataPt)); + $buff = $txtHdr . HexEncode($dataPt); + $chunk = 'tEXt'; # write as tEXt if deflate not available + $prefix = "Raw profile type $rawType\0"; + $dataPt = \$buff; + # write profile as zTXt chunk if possible + if ($deflate) { + my $buf2 = $deflate->deflate($buff); + if (defined $buf2) { + $dataPt = \$buf2; + $buf2 .= $deflate->flush(); + $chunk = 'zTXt'; + $prefix .= "\0"; # compression type byte (0=deflate) + } + } + } + my $hdr = pack('Na4', length($prefix) + length($$dataPt), $chunk) . $prefix; + my $crc = CalculateCRC(\$hdr, undef, 4); + $crc = CalculateCRC($dataPt, $crc); + return Write($outfile, $hdr, $$dataPt, pack('N',$crc)); +} + +#------------------------------------------------------------------------------ +# Add iCCP to the PNG image if necessary (must come before PLTE and IDAT) +# Inputs: 0) ExifTool object ref, 1) output file or scalar ref +# Returns: true on success +sub Add_iCCP($$) +{ + my ($et, $outfile) = @_; + if ($$et{ADD_DIRS}{ICC_Profile}) { + # write new ICC data + my $tagTablePtr = Image::ExifTool::GetTagTable('Image::ExifTool::ICC_Profile::Main'); + my %dirInfo = ( Parent => 'PNG', DirName => 'ICC_Profile' ); + my $buff = $et->WriteDirectory(\%dirInfo, $tagTablePtr); + if (defined $buff and length $buff and WriteProfile($outfile, 'icm', \$buff)) { + $et->VPrint(0, "Created ICC profile\n"); + delete $$et{ADD_DIRS}{ICC_Profile}; # don't add it again + $$et{PNGDoneDir}{ICC_Profile} = 2; + } + } + return 1; +} + +#------------------------------------------------------------------------------ +# This routine is called after we edit an existing directory +# Inputs: 0) ExifTool ref, 1) dir name, 2) output data ref +# 3) flag set if location is non-standard (to update, but not create from scratch) +# - on return, $$outBuff is set to '' if the directory is to be deleted +sub DoneDir($$$;$) +{ + my ($et, $dir, $outBuff, $nonStandard) = @_; + $dir = 'IFD0' if $dir eq 'EXIF'; + # don't add this directory again unless this is in a non-standard location + delete $$et{ADD_DIRS}{$dir} unless $nonStandard; + # handle problem with duplicate XMP when using PNGEarlyXMP option + return unless $dir eq 'XMP' and defined $$outBuff and length $$outBuff; + if ($nonStandard and $$et{DEL_GROUP}{$dir}) { + $et->VPrint(0," Deleting non-standard $dir\n"); + $$outBuff = ''; + } elsif (not $$et{PNGDoneDir}{$dir}) { + $$et{PNGDoneDir}{$dir} = 1; # set flag indicating the directory exists + } elsif ($$et{OPTIONS}{PNGEarlyXMP}) { + if ($$et{PNGDoneDir}{$dir} == 2) { + if ($$et{OPTIONS}{IgnoreMinorErrors}) { + $et->Warn("Deleted existing $dir"); + } else { + $et->Error("Duplicate $dir created. Ignore to delete existing $dir", 1); + return; + } + } elsif ($et->Warn("Duplicate $dir. Ignore to delete", 2)) { + return; # warning not ignored: don't delete the duplicate + } + $et->VPrint(0," Deleting duplicate $dir\n"); + $$outBuff = ''; + } +} + +#------------------------------------------------------------------------------ +# Generate tEXt, zTXt or iTXt data for writing +# Inputs: 0) ExifTool ref, 1) tagID, 2) tagInfo ref, 3) value string, 4) language code +# Returns: chunk data (not including 8-byte chunk header) +# Notes: Sets ExifTool TextChunkType member to the type of chunk written +sub BuildTextChunk($$$$$) +{ + my ($et, $tag, $tagInfo, $val, $lang) = @_; + my ($xtra, $compVal, $iTXt, $comp); + if ($$tagInfo{SubDirectory}) { + if ($$tagInfo{Name} eq 'XMP') { + $iTXt = 2; # write as iTXt but flag to avoid encoding + # (never compress XMP) + } else { + $comp = 2; # compress raw profile if possible + } + } else { + # compress if specified + $comp = 1 if $et->Options('Compress'); + if ($lang) { + $iTXt = 1; # write as iTXt if it has a language code + $tag =~ s/-$lang$//; # remove language code from tagID + } elsif ($$et{OPTIONS}{Charset} ne 'Latin' and $val =~ /[\x80-\xff]/) { + $iTXt = 1; # write as iTXt if it contains non-Latin special characters + } + } + if ($comp) { + my $warn; + if (eval { require Compress::Zlib }) { + my $deflate = Compress::Zlib::deflateInit(); + $compVal = $deflate->deflate($val) if $deflate; + if (defined $compVal) { + $compVal .= $deflate->flush(); + # only compress if it actually saves space + unless (length($compVal) < length($val)) { + undef $compVal; + $warn = 'uncompressed data is smaller'; + } + } else { + $warn = 'deflate error'; + } + } else { + $warn = 'Compress::Zlib not available'; + } + # warn if any user-specified compression fails + if ($warn and $comp == 1) { + $et->Warn("PNG:$$tagInfo{Name} not compressed ($warn)", 1); + } + } + # decide whether to write as iTXt, zTXt or tEXt + if ($iTXt) { + $$et{TextChunkType} = 'iTXt'; + $xtra = (defined $compVal ? "\x01\0" : "\0\0") . ($lang || '') . "\0\0"; + # iTXt is encoded as UTF-8 (but note that XMP is already UTF-8) + $val = $et->Encode($val, 'UTF8') if $iTXt == 1; + } elsif (defined $compVal) { + $$et{TextChunkType} = 'zTXt'; + $xtra = "\0"; + } else { + $$et{TextChunkType} = 'tEXt'; + $xtra = ''; + } + return $tag . "\0" . $xtra . (defined $compVal ? $compVal : $val); +} + +#------------------------------------------------------------------------------ +# Add any outstanding new chunks to the PNG image +# Inputs: 0) ExifTool object ref, 1) output file or scalar ref +# 2-N) dirs to add (empty to add all, including PNG tags) +# Returns: true on success +sub AddChunks($$;@) +{ + my ($et, $outfile, @add) = @_; + my ($addTags, $tag, $dir, $err, $tagTablePtr); + + if (@add) { + $addTags = { }; # don't add any PNG tags + } else { + $addTags = $$et{ADD_PNG}; # add all PNG tags... + delete $$et{ADD_PNG}; # ...once + # add all directories + @add = sort keys %{$$et{ADD_DIRS}}; + } + # write any outstanding PNG tags + foreach $tag (sort keys %$addTags) { + my $tagInfo = $$addTags{$tag}; + my $nvHash = $et->GetNewValueHash($tagInfo); + # (native PNG information is always preferred, so don't check IsCreating) + next unless $et->IsOverwriting($nvHash); + my $val = $et->GetNewValue($nvHash); + if (defined $val) { + next if $$nvHash{EditOnly}; + my $data; + if ($$tagInfo{Table} eq \%Image::ExifTool::PNG::TextualData) { + $data = BuildTextChunk($et, $tag, $tagInfo, $val, $$tagInfo{LangCode}); + $data = $$et{TextChunkType} . $data; + delete $$et{TextChunkType}; + } else { + $data = "$tag$val"; + } + my $hdr = pack('N', length($data) - 4); + my $cbuf = pack('N', CalculateCRC(\$data, undef)); + Write($outfile, $hdr, $data, $cbuf) or $err = 1; + $et->VerboseValue("+ PNG:$$tagInfo{Name}", $val); + $$et{PNGDoneTag}{$tag} = 1; # set flag indicating this tag was added + ++$$et{CHANGED}; + } + } + # create any necessary directories + foreach $dir (@add) { + next unless $$et{ADD_DIRS}{$dir}; # make sure we want to add it first + my $buff; + my %dirInfo = ( + Parent => 'PNG', + DirName => $dir, + ); + if ($dir eq 'IFD0') { + my $chunk = $stdCase{exif}; + # (zxIf was not adopted) + #if ($et->Options('Compress')) { + # if (eval { require Compress::Zlib }) { + # $chunk = $stdCase{zxif}; + # } else { + # $et->Warn("Creating uncompressed $stdCase{exif} chunk (Compress::Zlib not available)"); + # } + #} + $et->VPrint(0, "Creating $chunk chunk:\n"); + $$et{TIFF_TYPE} = 'APP1'; + $tagTablePtr = Image::ExifTool::GetTagTable('Image::ExifTool::Exif::Main'); + $buff = $et->WriteDirectory(\%dirInfo, $tagTablePtr, \&Image::ExifTool::WriteTIFF); + if (defined $buff and length $buff) { + WriteProfile($outfile, $chunk, \$buff) or $err = 1; + } + } elsif ($dir eq 'XMP') { + $et->VPrint(0, "Creating XMP iTXt chunk:\n"); + $tagTablePtr = Image::ExifTool::GetTagTable('Image::ExifTool::XMP::Main'); + $dirInfo{ReadOnly} = 1; + $buff = $et->WriteDirectory(\%dirInfo, $tagTablePtr); + if (defined $buff and length $buff and + # the packet is read-only (because of CRC) + Image::ExifTool::XMP::ValidateXMP(\$buff, 'r')) + { + # (previously, XMP was created as a non-standard XMP profile chunk) + # $buff = $Image::ExifTool::xmpAPP1hdr . $buff; + # WriteProfile($outfile, 'APP1', \$buff, 'generic') or $err = 1; + # (but now write XMP iTXt chunk according to XMP specification) + $buff = "iTXtXML:com.adobe.xmp\0\0\0\0\0" . $buff; + my $hdr = pack('N', length($buff) - 4); + my $cbuf = pack('N', CalculateCRC(\$buff, undef)); + Write($outfile, $hdr, $buff, $cbuf) or $err = 1; + } + } elsif ($dir eq 'IPTC') { + $et->Warn('Creating non-standard EXIF in PNG', 1); + $et->VPrint(0, "Creating IPTC profile:\n"); + # write new IPTC data (stored in a Photoshop directory) + $dirInfo{DirName} = 'Photoshop'; + $tagTablePtr = Image::ExifTool::GetTagTable('Image::ExifTool::Photoshop::Main'); + $buff = $et->WriteDirectory(\%dirInfo, $tagTablePtr); + if (defined $buff and length $buff) { + WriteProfile($outfile, 'iptc', \$buff, 'IPTC') or $err = 1; + } + } elsif ($dir eq 'ICC_Profile') { + $et->VPrint(0, "Creating ICC profile:\n"); + # write new ICC data (only done if we couldn't create iCCP chunk) + $tagTablePtr = Image::ExifTool::GetTagTable('Image::ExifTool::ICC_Profile::Main'); + $buff = $et->WriteDirectory(\%dirInfo, $tagTablePtr); + if (defined $buff and length $buff) { + WriteProfile($outfile, 'icm', \$buff, 'ICC') or $err = 1; + $et->Warn('Wrote ICC as a raw profile (no Compress::Zlib)'); + } + } elsif ($dir eq 'PNG-pHYs') { + $et->VPrint(0, "Creating pHYs chunk:\n"); + $tagTablePtr = Image::ExifTool::GetTagTable('Image::ExifTool::PNG::PhysicalPixel'); + my $blank = "\0\0\x0b\x12\0\0\x0b\x12\x01"; # 2834 pixels per meter (72 dpi) + $dirInfo{DataPt} = \$blank; + $buff = $et->WriteDirectory(\%dirInfo, $tagTablePtr); + if (defined $buff and length $buff) { + $buff = 'pHYs' . $buff; # CRC includes chunk name + my $hdr = pack('N', length($buff) - 4); + my $cbuf = pack('N', CalculateCRC(\$buff, undef)); + Write($outfile, $hdr, $buff, $cbuf) or $err = 1; + } + } else { + next; + } + delete $$et{ADD_DIRS}{$dir}; # don't add again + # keep track of the directories that we added + $$et{PNGDoneDir}{$dir} = 2 if defined $buff and length $buff; + } + return not $err; +} + + +1; # end + +__END__ + +=head1 NAME + +Image::ExifTool::WritePNG.pl - Write PNG meta information + +=head1 SYNOPSIS + +These routines are autoloaded by Image::ExifTool::PNG. + +=head1 DESCRIPTION + +This file contains routines to write PNG metadata. + +=head1 NOTES + +Compress::Zlib is required to write compressed text. + +Existing text tags are always rewritten in their original form (compressed +zTXt, uncompressed tEXt or international iTXt), so pre-existing compressed +information can only be modified if Compress::Zlib is available. + +Newly created textual information is written in uncompressed tEXt form by +default, or as compressed zTXt if the Compress option is used and +Compress::Zlib is available (but only if the resulting compressed data is +smaller than the original text, which isn't always the case for short text +strings). + +=head1 AUTHOR + +Copyright 2003-2019, Phil Harvey (phil at owl.phy.queensu.ca) + +This library is free software; you can redistribute it and/or modify it +under the same terms as Perl itself. + +=head1 SEE ALSO + +L<Image::ExifTool::PNG(3pm)|Image::ExifTool::PNG>, +L<Image::ExifTool(3pm)|Image::ExifTool> + +=cut diff --git a/lib/Image/ExifTool/WritePhotoshop.pl b/lib/Image/ExifTool/WritePhotoshop.pl new file mode 100644 index 0000000..ba72643 --- /dev/null +++ b/lib/Image/ExifTool/WritePhotoshop.pl @@ -0,0 +1,266 @@ +#------------------------------------------------------------------------------ +# File: WritePhotoshop.pl +# +# Description: Write Photoshop IRB meta information +# +# Revisions: 12/17/2004 - P. Harvey Created +#------------------------------------------------------------------------------ + +package Image::ExifTool::Photoshop; + +use strict; + +#------------------------------------------------------------------------------ +# Strip resource name from value prepare resource name for writing into IRB +# Inputs: 0) tagInfo ref, 1) resource name (padded pascal string), 2) new value ref +# Returns: none (updates name and value if necessary) +sub SetResourceName($$$) +{ + my ($tagInfo, $name, $valPt) = @_; + my $setName = $$tagInfo{SetResourceName}; + if (defined $setName) { + # extract resource name from value + if ($$valPt =~ m{.*/#(.{0,255})#/$}s) { + $name = $1; + # strip name from value + $$valPt = substr($$valPt, 0, -4 - length($name)); + } elsif ($setName eq '1') { + return; # use old name + } else { + $name = $setName; + } + # convert to padded pascal string + $name = chr(length $name) . $name; + $name .= "\0" if length($name) & 0x01; + $_[1] = $name; # return new name + } +} + +#------------------------------------------------------------------------------ +# Write Photoshop IRB resource +# Inputs: 0) ExifTool object reference, 1) source dirInfo reference, +# 2) tag table reference +# Returns: IRB resource data (may be empty if no Photoshop data) +# Notes: Increments ExifTool CHANGED flag for each tag changed +sub WritePhotoshop($$$) +{ + my ($et, $dirInfo, $tagTablePtr) = @_; + $et or return 1; # allow dummy access to autoload this package + my $dataPt = $$dirInfo{DataPt}; + unless ($dataPt) { + my $emptyData = ''; + $dataPt = \$emptyData; + } + my $start = $$dirInfo{DirStart} || 0; + my $dirLen = $$dirInfo{DirLen} || (length($$dataPt) - $start); + my $dirEnd = $start + $dirLen; + my $newData = ''; + + # make a hash of new tag info, keyed on tagID + my $newTags = $et->GetNewTagInfoHash($tagTablePtr); + + my ($addDirs, $editDirs) = $et->GetAddDirHash($tagTablePtr); + + SetByteOrder('MM'); # Photoshop is always big-endian +# +# rewrite existing tags in the old directory, deleting ones as necessary +# (the Photoshop directory entries aren't in any particular order) +# + # Format: 0) Type, 4 bytes - '8BIM' (or the rare 'PHUT', 'DCSR', 'AgHg' or 'MeSa') + # 1) TagID,2 bytes + # 2) Name, pascal string padded to even no. bytes + # 3) Size, 4 bytes - N + # 4) Data, N bytes + my ($pos, $value, $size, $tagInfo, $tagID); + for ($pos=$start; $pos+8<$dirEnd; $pos+=$size) { + # each entry must be on same even byte boundary as directory start + ++$pos if ($pos ^ $start) & 0x01; + my $type = substr($$dataPt, $pos, 4); + if ($type !~ /^(8BIM|PHUT|DCSR|AgHg|MeSa)$/) { + $et->Error("Bad Photoshop IRB resource"); + undef $newData; + last; + } + $tagID = Get16u($dataPt, $pos + 4); + # get resource block name (pascal string padded to an even # of bytes) + my $namelen = 1 + Get8u($dataPt, $pos + 6); + ++$namelen if $namelen & 0x01; + if ($pos + $namelen + 10 > $dirEnd) { + $et->Error("Bad APP13 resource block"); + undef $newData; + last; + } + my $name = substr($$dataPt, $pos + 6, $namelen); + $size = Get32u($dataPt, $pos + 6 + $namelen); + $pos += $namelen + 10; + if ($size + $pos > $dirEnd) { + $et->Error("Bad APP13 resource data size $size"); + undef $newData; + last; + } + if ($$newTags{$tagID} and $type eq '8BIM') { + $tagInfo = $$newTags{$tagID}; + delete $$newTags{$tagID}; + my $nvHash = $et->GetNewValueHash($tagInfo); + # check to see if we are overwriting this tag + $value = substr($$dataPt, $pos, $size); + my $isOverwriting = $et->IsOverwriting($nvHash, $value); + # handle special 'new' and 'old' values for IPTCDigest + if (not $isOverwriting and $tagInfo eq $iptcDigestInfo) { + if (grep /^new$/, @{$$nvHash{DelValue}}) { + $isOverwriting = 1 if $$et{NewIPTCDigest} and + $$et{NewIPTCDigest} eq $value; + } + if (grep /^old$/, @{$$nvHash{DelValue}}) { + $isOverwriting = 1 if $$et{OldIPTCDigest} and + $$et{OldIPTCDigest} eq $value; + } + } + if ($isOverwriting) { + $et->VerboseValue("- Photoshop:$$tagInfo{Name}", $value); + # handle IPTCDigest specially because we want to write it last + # so the new IPTC digest will be known + if ($tagInfo eq $iptcDigestInfo) { + $$newTags{$tagID} = $tagInfo; # add later + $value = undef; + } else { + $value = $et->GetNewValue($nvHash); + } + ++$$et{CHANGED}; + next unless defined $value; # next if tag is being deleted + # set resource name if necessary + SetResourceName($tagInfo, $name, \$value); + $et->VerboseValue("+ Photoshop:$$tagInfo{Name}", $value); + } + } else { + if ($type eq '8BIM') { + $tagInfo = $$editDirs{$tagID}; + unless ($tagInfo) { + # process subdirectory anyway if writable (except EXIF to avoid recursion) + # --> this allows IPTC to be processed if found here in TIFF images + my $tmpInfo = $et->GetTagInfo($tagTablePtr, $tagID); + if ($tmpInfo and $$tmpInfo{SubDirectory} and + $tmpInfo->{SubDirectory}->{TagTable} ne 'Image::ExifTool::Exif::Main') + { + my $table = Image::ExifTool::GetTagTable($tmpInfo->{SubDirectory}->{TagTable}); + $tagInfo = $tmpInfo if $$table{WRITE_PROC}; + } + } + } + if ($tagInfo) { + $$addDirs{$tagID} and delete $$addDirs{$tagID}; + my %subdirInfo = ( + DataPt => $dataPt, + DirStart => $pos, + DataLen => $dirLen, + DirLen => $size, + Parent => $$dirInfo{DirName}, + ); + my $subTable = Image::ExifTool::GetTagTable($tagInfo->{SubDirectory}->{TagTable}); + my $writeProc = $tagInfo->{SubDirectory}->{WriteProc}; + my $newValue = $et->WriteDirectory(\%subdirInfo, $subTable, $writeProc); + if (defined $newValue) { + next unless length $newValue; # remove subdirectory entry + $value = $newValue; + SetResourceName($tagInfo, $name, \$value); + } else { + $value = substr($$dataPt, $pos, $size); # rewrite old directory + } + } else { + $value = substr($$dataPt, $pos, $size); + } + } + my $newSize = length $value; + # write this directory entry + $newData .= $type . Set16u($tagID) . $name . Set32u($newSize) . $value; + $newData .= "\0" if $newSize & 0x01; # must null pad to even byte + } +# +# write any remaining entries we didn't find in the old directory +# (might as well write them in numerical tag order) +# + my @tagsLeft = sort { $a <=> $b } keys(%$newTags), keys(%$addDirs); + foreach $tagID (@tagsLeft) { + my $name = "\0\0"; + if ($$newTags{$tagID}) { + $tagInfo = $$newTags{$tagID}; + my $nvHash = $et->GetNewValueHash($tagInfo); + $value = $et->GetNewValue($nvHash); + # handle new IPTCDigest value specially + if ($tagInfo eq $iptcDigestInfo and defined $value) { + if ($value eq 'new') { + $value = $$et{NewIPTCDigest}; + } elsif ($value eq 'old') { + $value = $$et{OldIPTCDigest}; + } + # (we already know we want to create this tag) + } else { + # don't add this tag unless specified + next unless $$nvHash{IsCreating}; + } + next unless defined $value; # next if tag is being deleted + $et->VerboseValue("+ Photoshop:$$tagInfo{Name}", $value); + ++$$et{CHANGED}; + } else { + $tagInfo = $$addDirs{$tagID}; + # create new directory + my %subdirInfo = ( + Parent => $$dirInfo{DirName}, + ); + my $subTable = Image::ExifTool::GetTagTable($tagInfo->{SubDirectory}->{TagTable}); + my $writeProc = $tagInfo->{SubDirectory}->{WriteProc}; + $value = $et->WriteDirectory(\%subdirInfo, $subTable, $writeProc); + next unless $value; + } + # set resource name if necessary + SetResourceName($tagInfo, $name, \$value); + $size = length($value); + # write the new directory entry + $newData .= '8BIM' . Set16u($tagID) . $name . Set32u($size) . $value; + $newData .= "\0" if $size & 0x01; # must null pad to even numbered byte + ++$$et{CHANGED}; + } + return $newData; +} + + +1; # end + +__END__ + +=head1 NAME + +Image::ExifTool::WritePhotoshop.pl - Write Photoshop IRB meta information + +=head1 SYNOPSIS + +This file is autoloaded by Image::ExifTool::Photoshop. + +=head1 DESCRIPTION + +This file contains routines to write Photoshop metadata. + +=head1 NOTES + +Photoshop IRB blocks may have an associated resource name. By default, the +existing name is preserved when rewriting a resource, and an empty name is +used when creating a new resource. However, a different resource name may +be specified by defining a C<SetResourceName> entry in the tag information +hash. With this defined, a new resource name may be appended to the value +in the form "VALUE/#NAME#/" (the slashes and hashes are literal). If +C<SetResourceName> is anything other than '1', the value is used as a +default resource name, and applied if no appended name is provided. + +=head1 AUTHOR + +Copyright 2003-2019, Phil Harvey (phil at owl.phy.queensu.ca) + +This library is free software; you can redistribute it and/or modify it +under the same terms as Perl itself. + +=head1 SEE ALSO + +L<Image::ExifTool::Photoshop(3pm)|Image::ExifTool::Photoshop>, +L<Image::ExifTool(3pm)|Image::ExifTool> + +=cut diff --git a/lib/Image/ExifTool/WritePostScript.pl b/lib/Image/ExifTool/WritePostScript.pl new file mode 100644 index 0000000..9b45e4b --- /dev/null +++ b/lib/Image/ExifTool/WritePostScript.pl @@ -0,0 +1,772 @@ +#------------------------------------------------------------------------------ +# File: WritePostScript.pl +# +# Description: Write PostScript meta information +# +# Revisions: 03/03/2006 - P. Harvey Created +# +# References: (see references in PostScript.pm, plus:) +# 1) http://www.adobe.com/products/postscript/pdfs/PLRM.pdf +# 2) http://www-cdf.fnal.gov/offline/PostScript/PLRM2.pdf +# 3) http://partners.adobe.com/public/developer/en/acrobat/sdk/pdf/pdf_creation_apis_and_specs/pdfmarkReference.pdf +# 4) http://www.npes.org/standards/Tools/DCS20Spec.pdf +# +# Notes: (see NOTES in POD doc below) +#------------------------------------------------------------------------------ + +package Image::ExifTool::PostScript; + +use strict; + +# Structure of a DSC PS/EPS document: +# +# %!PS-Adobe-3.0 [plus " EPSF-3.0" for EPS] +# <comments> +# %%EndComments [optional] +# %%BeginXxxx +# <stuff to ignore> +# %%EndXxxx +# %%BeginProlog +# <prolog stuff> +# %%EndProlog +# %%BeginSetup +# <setup stuff> +# %%EndSetup +# %ImageData x x x x [written by Photoshop] +# %BeginPhotoshop: xxxx +# <ascii-hex IRB information> +# %EndPhotosop +# %%BeginICCProfile: (name) <num> <type> +# <ICC Profile info> +# %%EndICCProfile +# %begin_xml_code +# <postscript code to define and read the XMP stream object> +# %begin_xml_packet: xxxx +# <XMP data> +# %end_xml_packet +# <postscript code to add XMP stream to dictionary> +# %end_xml_code +# %%Page: x x [PS only (optional?)] +# <graphics commands> +# %%PageTrailer +# %%Trailer +# <a bit more code to bracket EPS content for distiller> +# %%EOF + +# map of where information is stored in PS image +my %psMap = ( + XMP => 'PostScript', + Photoshop => 'PostScript', + IPTC => 'Photoshop', + EXIFInfo => 'Photoshop', + IFD0 => 'EXIFInfo', + IFD1 => 'IFD0', + ICC_Profile => 'PostScript', + ExifIFD => 'IFD0', + GPS => 'IFD0', + SubIFD => 'IFD0', + GlobParamIFD => 'IFD0', + PrintIM => 'IFD0', + InteropIFD => 'ExifIFD', + MakerNotes => 'ExifIFD', +); + + +#------------------------------------------------------------------------------ +# Write XMP directory to file, with begin/end tokens if necessary +# Inputs: 0) outfile ref, 1) flags hash ref, 2-N) data to write +# Returns: true on success +sub WriteXMPDir($$@) +{ + my $outfile = shift; + my $flags = shift; + my $success = 1; + Write($outfile, "%begin_xml_code$/") or $success = 0 unless $$flags{WROTE_BEGIN}; + Write($outfile, @_) or $success = 0; + Write($outfile, "%end_xml_code$/") or $success = 0 unless $$flags{WROTE_BEGIN}; + return $success; +} + +#------------------------------------------------------------------------------ +# Write a directory inside a PS document +# Inputs: 0) ExifTool object ref, 1) output file reference, +# 2) Directory name, 3) data reference, 4) flags hash ref +# Returns: 0=error, 1=nothing written, 2=dir written ok +sub WritePSDirectory($$$$$) +{ + my ($et, $outfile, $dirName, $dataPt, $flags) = @_; + my $success = 2; + my $len = $dataPt ? length($$dataPt) : 0; + my $create = $len ? 0 : 1; + my %dirInfo = ( + DataPt => $dataPt, + DataLen => $len, + DirStart => 0, + DirLen => $len, + DirName => $dirName, + Parent => 'PostScript', + ); + # Note: $$flags{WROTE_BEGIN} may be 1 for XMP (it is always 0 for + # other dirs, but if 1, the begin/end markers were already written) +# +# prepare necessary postscript code to support embedded XMP +# + my ($beforeXMP, $afterXMP, $reportedLen); + if ($dirName eq 'XMP' and $len) { + # isolate the XMP + pos($$dataPt) = 0; + unless ($$dataPt =~ /(.*)(<\?xpacket begin=.{7,13}W5M0MpCehiHzreSzNTczkc9d)/sg) { + $et->Warn('No XMP packet start'); + return WriteXMPDir($outfile, $flags, $$dataPt); + } + $beforeXMP = $1; + my $xmp = $2; + my $p1 = pos($$dataPt); + unless ($$dataPt =~ m{<\?xpacket end=.(w|r).\?>}sg) { + $et->Warn('No XMP packet end'); + return WriteXMPDir($outfile, $flags, $$dataPt); + } + my $p2 = pos($$dataPt); + $xmp .= substr($$dataPt, $p1, $p2-$p1); + $afterXMP = substr($$dataPt, $p2); + # determine if we can adjust the XMP size + if ($beforeXMP =~ /%begin_xml_packet: (\d+)/s) { + $reportedLen = $1; + my @matches= ($beforeXMP =~ /\b$reportedLen\b/sg); + undef $reportedLen unless @matches == 2; + } + # must edit in place if we can't reliably change the XMP length + $dirInfo{InPlace} = 1 unless $reportedLen; + # process XMP only + $dirInfo{DataLen} = $dirInfo{DirLen} = length $xmp; + $dirInfo{DataPt} = \$xmp; + } + my $tagTablePtr = Image::ExifTool::GetTagTable("Image::ExifTool::${dirName}::Main"); + my $val = $et->WriteDirectory(\%dirInfo, $tagTablePtr); + if (defined $val) { + $dataPt = \$val; # use modified directory + $len = length $val; + } elsif ($dirName eq 'XMP') { + return 1 unless $len; + # just write the original XMP + return WriteXMPDir($outfile, $flags, $$dataPt); + } + unless ($len) { + return 1 if $create or $dirName ne 'XMP'; # nothing to create + # it would be really difficult to delete the XMP, + # so instead we write a blank XMP record + $val = <<EMPTY_XMP; +<?xpacket begin='' id='W5M0MpCehiHzreSzNTczkc9d'?> +<x:xmpmeta xmlns:x='adobe:ns:meta/' x:xmptk='Image::ExifTool $Image::ExifTool::VERSION'> +</x:xmpmeta> +EMPTY_XMP + $val .= ((' ' x 100) . "\n") x 24 unless $et->Options('Compact'); + $val .= q{<?xpacket end='w'?>}; + $dataPt = \$val; + $len = length $val; + } +# +# write XMP directory +# + if ($dirName eq 'XMP') { + if ($create) { + # create necessary PS/EPS code to support XMP + $beforeXMP = <<HDR_END; +/pdfmark where {pop true} {false} ifelse +/currentdistillerparams where {pop currentdistillerparams +/CoreDistVersion get 5000 ge } {false} ifelse +and not {userdict /pdfmark /cleartomark load put} if +[/NamespacePush pdfmark +[/_objdef {exiftool_metadata_stream} /type /stream /OBJ pdfmark +[{exiftool_metadata_stream} 2 dict begin /Type /Metadata def + /Subtype /XML def currentdict end /PUT pdfmark +/MetadataString $len string def % exact length of metadata +/TempString 100 string def +/ConsumeMetadata { +currentfile TempString readline pop pop +currentfile MetadataString readstring pop pop +} bind def +ConsumeMetadata +%begin_xml_packet: $len +HDR_END + # note: use q() to get necessary linefeed before %end_xml_packet + $afterXMP = q( +%end_xml_packet +[{exiftool_metadata_stream} MetadataString /PUT pdfmark +); + if ($$flags{EPS}) { + $afterXMP .= <<EPS_AFTER; +[/Document 1 dict begin + /Metadata {exiftool_metadata_stream} def currentdict end /BDC pdfmark +[/NamespacePop pdfmark +EPS_AFTER + # write this at end of file + $$flags{TRAILER} = "[/EMC pdfmark$/"; + } else { # PS + $afterXMP .= <<PS_AFTER; +[{Catalog} {exiftool_metadata_stream} /Metadata pdfmark +[/NamespacePop pdfmark +PS_AFTER + } + $beforeXMP =~ s{\n}{$/}sg; # use proper newline characters + $afterXMP =~ s{\n}{$/}sg; + } else { + # replace xmp size in PS code + $reportedLen and $beforeXMP =~ s/\b$reportedLen\b/$len/sg; + } + WriteXMPDir($outfile, $flags, $beforeXMP, $$dataPt, $afterXMP) or $success = 0; +# +# Write Photoshop or ICC_Profile directory +# + } elsif ($dirName eq 'Photoshop' or $dirName eq 'ICC_Profile') { + my ($startToken, $endToken); + if ($dirName eq 'Photoshop') { + $startToken = "%BeginPhotoshop: $len"; + $endToken = '%EndPhotoshop'; + } else { + $startToken = '%%BeginICCProfile: (Photoshop Profile) -1 Hex'; + $endToken = '%%EndICCProfile'; + } + Write($outfile, $startToken, $/) or $success = 0; + # write as an ASCII-hex comment + my $i; + my $wid = 32; + for ($i=0; $i<$len; $i+=$wid) { + $wid > $len-$i and $wid = $len-$i; + my $dat = substr($$dataPt, $i, $wid); + Write($outfile, "% ", uc(unpack('H*',$dat)), $/) or $success = 0; + } + Write($outfile, $endToken, $/) or $success = 0; + } else { + $et->Warn("Can't write PS directory $dirName"); + } + undef $val; + return $success; +} + +#------------------------------------------------------------------------------ +# Encode postscript tag/value +# Inputs: 0) tag ID, 1) value +# Returns: postscript comment +# - adds brackets, escapes special characters, and limits line length +sub EncodeTag($$) +{ + my ($tag, $val) = @_; + unless ($val =~ /^\d+$/) { + $val =~ s/([()\\])/\\$1/g; # escape brackets and backslashes + $val =~ s/\n/\\n/g; # escape newlines + $val =~ s/\r/\\r/g; # escape carriage returns + $val =~ s/\t/\\t/g; # escape tabs + # use octal escape codes for other control characters + $val =~ s/([\x00-\x1f\x7f\xff])/sprintf("\\%.3o",ord($1))/ge; + $val = "($val)"; + } + my $line = "%%$tag: $val"; + # postscript line limit is 255 characters (but it seems that + # the limit may be 254 characters if the DOS CR/LF is used) + # --> split if necessary using continuation comment "%%+" + my $n; + for ($n=254; length($line)>$n; $n+=254+length($/)) { + substr($line, $n, 0) = "$/%%+"; + } + return $line . $/; +} + +#------------------------------------------------------------------------------ +# Write new tags information in comments section +# Inputs: 0) ExifTool object ref, 1) output file ref, 2) reference to new tag hash +# Returns: true on success +sub WriteNewTags($$$) +{ + my ($et, $outfile, $newTags) = @_; + my $success = 1; + my $tag; + + # get XMP hint and remove from tags hash + my $xmpHint = $$newTags{XMP_HINT}; + delete $$newTags{XMP_HINT}; + + foreach $tag (sort keys %$newTags) { + my $tagInfo = $$newTags{$tag}; + my $nvHash = $et->GetNewValueHash($tagInfo); + next unless $$nvHash{IsCreating}; + my $val = $et->GetNewValue($nvHash); + $et->VerboseValue("+ PostScript:$$tagInfo{Name}", $val); + Write($outfile, EncodeTag($tag, $val)) or $success = 0; + ++$$et{CHANGED}; + } + # write XMP hint if necessary + Write($outfile, "%ADO_ContainsXMP: MainFirst$/") or $success = 0 if $xmpHint; + + %$newTags = (); # all done with new tags + return $success; +} + +#------------------------------------------------------------------------------ +# check to be sure we haven't read past end of PS data in DOS-style file +# Inputs: 0) RAF ref, 1) pointer to end of PS, 2) data +# - modifies data and sets RAF to EOF if end of PS is reached +sub CheckPSEnd($$$) +{ + my $pos = $_[0]->Tell(); + if ($pos >= $_[1]) { + $_[0]->Seek(0, 2); # seek to end of file so we can't read any more + $_[2] = substr($_[2], 0, length($_[2]) - $pos + $_[1]) if $pos > $_[1]; + } +} + +#------------------------------------------------------------------------------ +# Split into lines ending in any CR, LF or CR+LF combination +# (this is annoying, and could be avoided if EPS files didn't mix linefeeds!) +# Inputs: 0) data pointer, 1) reference to lines array +# Notes: Updates data to contain next line and fills list with remaining lines +sub SplitLine($$) +{ + my ($dataPt, $lines) = @_; + for (;;) { + my $endl; + # find the position of the first LF (\x0a) + $endl = pos($$dataPt), pos($$dataPt) = 0 if $$dataPt =~ /\x0a/g; + if ($$dataPt =~ /\x0d/g) { # find the first CR (\x0d) + if (defined $endl) { + # (remember, CR+LF is a DOS newline...) + $endl = pos($$dataPt) if pos($$dataPt) < $endl - 1; + } else { + $endl = pos($$dataPt); + } + } elsif (not defined $endl) { + push @$lines, $$dataPt; + last; + } + # split into separate lines + if (length $$dataPt == $endl) { + push @$lines, $$dataPt; + last; + } else { + push @$lines, substr($$dataPt, 0, $endl); + $$dataPt = substr($$dataPt, $endl); + } + } + $$dataPt = shift @$lines; # set $$dataPt to first line +} + +#------------------------------------------------------------------------------ +# Write PS file +# Inputs: 0) ExifTool object reference, 1) source dirInfo reference +# Returns: 1 on success, 0 if this wasn't a valid PS file, +# or -1 if a write error occurred +sub WritePS($$) +{ + my ($et, $dirInfo) = @_; + $et or return 1; # allow dummy access to autoload this package + my $tagTablePtr = Image::ExifTool::GetTagTable('Image::ExifTool::PostScript::Main'); + my $raf = $$dirInfo{RAF}; + my $outfile = $$dirInfo{OutFile}; + my $verbose = $et->Options('Verbose'); + my $out = $et->Options('TextOut'); + my ($data, $buff, %flags, $err, $mode, $endToken); + my ($dos, $psStart, $psEnd, $psNewStart, $xmpHint); + + $raf->Read($data, 4) == 4 or return 0; + return 0 unless $data =~ /^(%!PS|%!Ad|\xc5\xd0\xd3\xc6)/; + + if ($data =~ /^%!Ad/) { + # I've seen PS files start with "%!Adobe-PS"... + return 0 unless $raf->Read($buff, 6) == 6 and $buff eq "obe-PS"; + $data .= $buff; + + } elsif ($data =~ /^\xc5\xd0\xd3\xc6/) { +# +# process DOS binary PS files +# + # save DOS header then seek ahead and check PS header + $raf->Read($dos, 26) == 26 or return 0; + $dos = $data . $dos; + SetByteOrder('II'); + $psStart = Get32u(\$dos, 4); + unless ($raf->Seek($psStart, 0) and + $raf->Read($data, 4) == 4 and $data eq '%!PS') + { + $et->Error('Invalid PS header'); + return 1; + } + $psEnd = $psStart + Get32u(\$dos, 8); + my $base = Get32u(\$dos, 20); + Set16u(0xffff, \$dos, 28); # ignore checksum + if ($base) { + my %dirInfo = ( + Parent => 'PS', + RAF => $raf, + Base => $base, + NoTiffEnd => 1, # no end-of-TIFF check + ); + $buff = $et->WriteTIFF(\%dirInfo); + SetByteOrder('II'); # (WriteTIFF may change this) + if ($buff) { + $buff = substr($buff, $base); # remove header written by WriteTIFF() + } else { + # error rewriting TIFF, so just copy over original data + my $len = Get32u(\$dos, 24); + unless ($raf->Seek($base, 0) and $raf->Read($buff, $len) == $len) { + $et->Error('Error reading embedded TIFF'); + return 1; + } + $et->Warn('Bad embedded TIFF'); + } + Set32u(0, \$dos, 12); # zero metafile pointer + Set32u(0, \$dos, 16); # zero metafile length + Set32u(length($dos), \$dos, 20); # set TIFF pointer + Set32u(length($buff), \$dos, 24); # set TIFF length + } elsif (($base = Get32u(\$dos, 12)) != 0) { + # copy over metafile section + my $len = Get32u(\$dos, 16); + unless ($raf->Seek($base, 0) and $raf->Read($buff, $len) == $len) { + $et->Error('Error reading metafile section'); + return 1; + } + Set32u(length($dos), \$dos, 12); # set metafile pointer + } else { + $buff = ''; + } + $psNewStart = length($dos) + length($buff); + Set32u($psNewStart, \$dos, 4); # set pointer to start of PS + Write($outfile, $dos, $buff) or $err = 1; + $raf->Seek($psStart + 4, 0); # seek back to where we were + } +# +# rewrite PostScript data +# + local $/ = GetInputRecordSeparator($raf); + unless ($/ and $raf->ReadLine($buff)) { + $et->Error('Invalid PostScript data'); + return 1; + } + $data .= $buff; + unless ($data =~ /^%!PS-Adobe-3\.(\d+)\b/ and $1 < 2) { + if ($et->Error("Document does not conform to DSC spec. Metadata may be unreadable by other apps", 2)) { + return 1; + } + } + my $psRev = $1; # save PS revision number (3.x) + Write($outfile, $data) or $err = 1; + $flags{EPS} = 1 if $data =~ /EPSF/; + + # get hash of new information keyed by tagID and directories to add/edit + my $newTags = $et->GetNewTagInfoHash($tagTablePtr); + + # figure out which directories we need to write (PostScript takes priority) + $et->InitWriteDirs(\%psMap, 'PostScript'); + my $addDirs = $$et{ADD_DIRS}; + my $editDirs = $$et{EDIT_DIRS}; + my %doneDir; + + # set XMP hint flag (1 for adding, 0 for deleting, undef for no change) + $xmpHint = 1 if $$addDirs{XMP}; + $xmpHint = 0 if $$et{DEL_GROUP}{XMP}; + $$newTags{XMP_HINT} = $xmpHint if $xmpHint; # add special tag to newTags list + + my (@lines, $changedNL); + my $altnl = ($/ eq "\x0d") ? "\x0a" : "\x0d"; + + for (;;) { + if (@lines) { + $data = shift @lines; + } else { + $raf->ReadLine($data) or last; + $dos and CheckPSEnd($raf, $psEnd, $data); + # split line if it contains other newline sequences + if ($data =~ /$altnl/) { + if (length($data) > 500000 and IsPC()) { + # patch for Windows memory problem + unless ($changedNL) { + $changedNL = 1; + my $t = $/; + $/ = $altnl; + $altnl = $t; + $raf->Seek(-length($data), 1); + next; + } + } else { + # split into separate lines + SplitLine(\$data, \@lines); + } + } + } + undef $changedNL; + if ($endToken) { + # look for end token + if ($data =~ m/^$endToken\s*$/is) { + undef $endToken; + # found end: process this information + if ($mode) { + $doneDir{$mode} and $et->Error("Multiple $mode directories", 1); + $doneDir{$mode} = 1; + WritePSDirectory($et, $outfile, $mode, \$buff, \%flags) or $err = 1; + # write end token if we wrote the begin token + Write($outfile, $data) or $err = 1 if $flags{WROTE_BEGIN}; + undef $buff; + } else { + Write($outfile, $data) or $err = 1; + } + } else { + # buffer data in current begin/end block + if (not defined $mode) { + # pick up XMP in unrecognized blocks for editing in place + if ($data =~ /^<\?xpacket begin=.{7,13}W5M0MpCehiHzreSzNTczkc9d/ and + $$editDirs{XMP}) + { + $buff = $data; + $mode = 'XMP'; + } else { + Write($outfile, $data) or $err = 1; + } + } elsif ($mode eq 'XMP') { + $buff .= $data; + } else { + # data is ASCII-hex encoded + $data =~ tr/0-9A-Fa-f//dc; # remove all but hex characters + $buff .= pack('H*', $data); # translate from hex + } + } + next; + } elsif ($data =~ m{^(%{1,2})(Begin)(?!Object:)(.*?)[:\x0d\x0a]}i) { + # comments section is over... write any new tags now + WriteNewTags($et, $outfile, $newTags) or $err = 1 if %$newTags; + undef $xmpHint; + # the beginning of a data block (can only write XMP and Photoshop) + my %modeLookup = ( + _xml_code => 'XMP', + photoshop => 'Photoshop', + iccprofile => 'ICC_Profile', + ); + $verbose > 1 and print $out "$2$3\n"; + $endToken = $1 . ($2 eq 'begin' ? 'end' : 'End') . $3; + $mode = $modeLookup{lc($3)}; + if ($mode and $$editDirs{$mode}) { + $buff = ''; # initialize buffer for this block + $flags{WROTE_BEGIN} = 0; + } else { + undef $mode; # not editing this directory + Write($outfile, $data) or $err = 1; + $flags{WROTE_BEGIN} = 1; + } + next; + } elsif ($data =~ /^%%(?!Page:|PlateFile:|BeginObject:)(\w+): ?(.*)/s) { + # rewrite information from PostScript tags in comments + my ($tag, $val) = ($1, $2); + # handle Adobe Illustrator files specially + # - EVENTUALLY IT WOULD BE BETTER TO FIND ANOTHER IDENTIFICATION METHOD + # (because Illustrator doesn't care if the Creator is changed) + if ($tag eq 'Creator' and $val =~ /^Adobe Illustrator/) { + # disable writing XMP to PostScript-format Adobe Illustrator files + # because it confuses Illustrator + if ($$editDirs{XMP}) { + $et->Warn("Can't write XMP to PostScript-format Illustrator files"); + # pretend like we wrote it already so we won't try to add it later + $doneDir{XMP} = 1; + } + # don't allow "Creator" to be changed in Illustrator files + # (we need it to be able to recognize these files) + # --> find a better way to do this! + if ($$newTags{$tag}) { + $et->Warn("Can't change Postscript:Creator of Illustrator files"); + delete $$newTags{$tag}; + } + } + if ($$newTags{$tag}) { + my $tagInfo = $$newTags{$tag}; + delete $$newTags{$tag}; # write it then forget it + next unless ref $tagInfo; + # decode comment string (reading continuation lines if necessary) + $val = DecodeComment($val, $raf, \@lines, \$data); + $val = join $et->Options('ListSep'), @$val if ref $val eq 'ARRAY'; + my $nvHash = $et->GetNewValueHash($tagInfo); + if ($et->IsOverwriting($nvHash, $val)) { + $et->VerboseValue("- PostScript:$$tagInfo{Name}", $val); + $val = $et->GetNewValue($nvHash); + ++$$et{CHANGED}; + next unless defined $val; # next if tag is being deleted + $et->VerboseValue("+ PostScript:$$tagInfo{Name}", $val); + $data = EncodeTag($tag, $val); + } + } + # (note: Adobe InDesign doesn't put colon after %ADO_ContainsXMP -- doh!) + } elsif (defined $xmpHint and $data =~ m{^%ADO_ContainsXMP:? ?(.+?)[\x0d\x0a]*$}s) { + # change the XMP hint if necessary + if ($xmpHint) { + $data = "%ADO_ContainsXMP: MainFirst$/" if $1 eq 'NoMain'; + } else { + $data = "%ADO_ContainsXMP: NoMain$/"; + } + # delete XMP hint flags + delete $$newTags{XMP_HINT}; + undef $xmpHint; + } else { + # look for end of comments section + if (%$newTags and ($data !~ /^%\S/ or + $data =~ /^%(%EndComments|%Page:|%PlateFile:|%BeginObject:|.*BeginLayer)/)) + { + # write new tags at end of comments section + WriteNewTags($et, $outfile, $newTags) or $err = 1; + undef $xmpHint; + } + # look for start of drawing commands (AI uses "%AI5_BeginLayer", + # and Helios uses "%%BeginObject:") + if ($data =~ /^%(%Page:|%PlateFile:|%BeginObject:|.*BeginLayer)/ or + $data !~ m{^(%.*|\s*)$}s) + { + # we have reached the first page or drawing command, so create necessary + # directories and copy the rest of the file, then all done + my $dir; + my $plateFile = ($data =~ /^%%PlateFile:/); + # create Photoshop first, then XMP if necessary + foreach $dir (qw{Photoshop ICC_Profile XMP}) { + next unless $$editDirs{$dir} and not $doneDir{$dir}; + if ($plateFile) { + # PlateFile comments may contain offsets so we can't edit these files! + $et->Warn("Can only edit PostScript information DCS Plate files"); + last; + } + next unless $$addDirs{$dir} or $dir eq 'XMP'; + $flags{WROTE_BEGIN} = 0; + WritePSDirectory($et, $outfile, $dir, undef, \%flags) or $err = 1; + $doneDir{$dir} = 1; + } + # copy rest of file + if ($flags{TRAILER}) { + # write trailer before %%EOF + for (;;) { + Write($outfile, $data) or $err = 1; + if (@lines) { + $data = shift @lines; + } else { + $raf->ReadLine($data) or undef($data), last; + $dos and CheckPSEnd($raf, $psEnd, $data); + if ($data =~ /[\x0d\x0a]%%EOF\b/g) { + # split data before "%%EOF" + # (necessary if data contains other newline sequences) + my $pos = pos($data) - 5; + push @lines, substr($data, $pos); + $data = substr($data, 0, $pos); + } + } + last if $data =~ /^%%EOF\b/; + } + Write($outfile, $flags{TRAILER}) or $err = 1; + } + # simply copy the rest of the file if any data is left + if (defined $data) { + Write($outfile, $data) or $err = 1; + Write($outfile, @lines) or $err = 1 if @lines; + while ($raf->Read($data, 65536)) { + $dos and CheckPSEnd($raf, $psEnd, $data); + Write($outfile, $data) or $err = 1; + } + } + last; # all done! + } + } + # write new information or copy existing line + Write($outfile, $data) or $err = 1; + } + if ($dos and not $err) { + # must go back and set length of PS section in DOS header (very dumb design) + if (ref $outfile eq 'SCALAR') { + Set32u(length($$outfile) - $psNewStart, $outfile, 8); + } else { + my $pos = tell $outfile; + unless (seek($outfile, 8, 0) and + print $outfile Set32u($pos - $psNewStart) and + seek($outfile, $pos, 0)) + { + $et->Error("Can't write DOS-style PS files in non-seekable stream"); + $err = 1; + } + } + } + # issue warning if we couldn't write any information + unless ($err) { + my (@notDone, $dir); + delete $$newTags{XMP_HINT}; + push @notDone, 'PostScript' if %$newTags; + foreach $dir (qw{Photoshop ICC_Profile XMP}) { + push @notDone, $dir if $$editDirs{$dir} and not $doneDir{$dir} and + not $$et{DEL_GROUP}{$dir}; + } + @notDone and $et->Warn("Couldn't write ".join('/',@notDone).' information'); + } + $endToken and $et->Error("File missing $endToken"); + return $err ? -1 : 1; +} + + +1; # end + +__END__ + +=head1 NAME + +Image::ExifTool::WritePostScript.pl - Write PostScript meta information + +=head1 SYNOPSIS + +This file is autoloaded by Image::ExifTool::PostScript. + +=head1 DESCRIPTION + +This file contains routines to write meta information in PostScript +documents. Six forms of meta information may be written: + + 1) PostScript comments (Adobe DSC specification) + 2) XMP information embedded in a document-level XMP stream + 3) EXIF information embedded in a Photoshop record + 4) IPTC information embedded in a PhotoShop record + 5) ICC_Profile information embedded in an ICCProfile record + 6) TIFF information embedded in DOS-style binary header + +=head1 NOTES + +Currently, information is written only in the outer-level document. + +Photoshop will discard meta information in a PostScript document if it has +to rasterize the image, and it will rasterize anything that doesn't contain +the Photoshop-specific 'ImageData' tag. So don't expect Photoshop to read +any meta information added to EPS images that it didn't create. + +The following two acronyms may be confusing since they are so similar and +have different meanings with respect to PostScript documents: + + DSC = Document Structuring Conventions + DCS = Desktop Color Separation + +=head1 REFERENCES + +See references in L<PostScript.pm|Image::ExifTool::PostScript>, plus: + +=over 4 + +=item L<http://www.adobe.com/products/postscript/pdfs/PLRM.pdf> + +=item L<http://www-cdf.fnal.gov/offline/PostScript/PLRM2.pdf> + +=item L<http://partners.adobe.com/public/developer/en/acrobat/sdk/pdf/pdf_creation_apis_and_specs/pdfmarkReference.pdf> + +=back + +=head1 ACKNOWLEDGEMENTS + +Thanks to Tim Kordick for his help testing the EPS writer. + +=head1 AUTHOR + +Copyright 2003-2019, Phil Harvey (phil at owl.phy.queensu.ca) + +This library is free software; you can redistribute it and/or modify it +under the same terms as Perl itself. + +=head1 SEE ALSO + +L<Image::ExifTool::PostScript(3pm)|Image::ExifTool::PostScript>, +L<Image::ExifTool(3pm)|Image::ExifTool> + +=cut diff --git a/lib/Image/ExifTool/WriteQuickTime.pl b/lib/Image/ExifTool/WriteQuickTime.pl new file mode 100644 index 0000000..e092a9d --- /dev/null +++ b/lib/Image/ExifTool/WriteQuickTime.pl @@ -0,0 +1,384 @@ +#------------------------------------------------------------------------------ +# File: WriteQuickTime.pl +# +# Description: Write XMP to QuickTime (MOV and MP4) files +# +# Revisions: 2013-10-29 - P. Harvey Created +#------------------------------------------------------------------------------ +package Image::ExifTool::QuickTime; + +use strict; + +# map for adding directories to QuickTime-format files +my %movMap = ( + # MOV (no 'ftyp', or 'ftyp'='qt ') -> 'moov'-'udta'-'XMP_' + XMP => 'UserData', + UserData => 'Movie', + Movie => 'MOV', +); +my %mp4Map = ( + # MP4 ('ftyp' compatible brand 'mp41', 'mp42' or 'f4v ') -> top level 'uuid' + XMP => 'MOV', +); +my %dirMap = ( + MOV => \%movMap, + MP4 => \%mp4Map, + HEIC => { }, # can't currently write XMP to HEIC files +); + +#------------------------------------------------------------------------------ +# Check to see if path is current +# Inputs: 0) ExifTool object ref, 1) directory name +# Returns: true if current path is the root of the specified directory +sub IsCurPath($$) +{ + local $_; + my ($et, $dir) = @_; + $dir = $$et{DirMap}{$dir} and $dir eq $_ or last foreach reverse @{$$et{PATH}}; + return($dir and $dir eq 'MOV'); +} + +#------------------------------------------------------------------------------ +# Write a series of QuickTime atoms from file or in memory +# Inputs: 0) ExifTool ref, 1) dirInfo ref, 2) tag table ref +# Returns: A) if dirInfo contains DataPt: new directory data +# B) otherwise: true on success, 0 if a write error occurred +# (true but sets an Error on a file format error) +sub WriteQuickTime($$$) +{ + my ($et, $dirInfo, $tagTablePtr) = @_; + my ($foundMDAT, $lengthChanged, @hold, $track); + my $outfile = $$dirInfo{OutFile} or return 0; + my $raf = $$dirInfo{RAF}; + my $dataPt = $$dirInfo{DataPt}; + my $dirName = $$dirInfo{DirName}; + my $parent = $$dirInfo{Parent}; + my $addDirs = $$et{ADD_DIRS}; + my $rtnVal = 1; + + if ($dataPt) { + $raf = new File::RandomAccess($dataPt); + my $outBuff = ''; + $outfile = \$outBuff; + } else { + return 0 unless $raf; + } + for (;;) { + my ($hdr, $buff); + my $n = $raf->Read($hdr, 8); + unless ($n == 8) { + if ($n == 4 and $hdr eq "\0\0\0\0") { + # "for historical reasons" the udta is optionally terminated by 4 zeros (ref 1) + # --> hold this terminator to the end + push @hold, $hdr; + } elsif ($n != 0) { + $et->Error('File format error'); + } + last; + } + my ($size, $tag) = unpack('Na4', $hdr); + if ($size >= 8) { + $size -= 8; + } elsif ($size == 1) { + # read the extended size + $raf->Read($buff, 8) == 8 or $et->Error('Truncated extended atom'), last; + $hdr .= $buff; + my ($hi, $lo) = unpack('NN', $buff); + $size = $hi * 4294967296 + $lo - 16; + $size < 0 and $et->Error('Invalid extended atom size'), last; + } elsif (not $size and not $dataPt) { + # size of zero is only valid for top-level atom, and + # indicates the atom extends to the end of file + if (not $raf->{FILE_PT}) { + # get file size from image in memory + $size = length ${$$raf{BUFF_PT}}; + } else { + $size = -s $$raf{FILE_PT}; + } + if ($size and ($size -= $raf->Tell()) >= 0 and $size <= 0x7fffffff) { + Set32u($size + 8, \$hdr, 0); + } elsif (@hold) { + $et->Error("Sorry, can't yet add tags to this type of QuickTime file"); + return $rtnVal; + } else { + # blindly copy the rest of the file + Write($outfile, $hdr) or $rtnVal = 0; + while ($raf->Read($buff, 65536)) { + Write($outfile, $buff) or $rtnVal = 0, last; + } + return $rtnVal; + } + } else { + $et->Error('Invalid atom size'); + last; + } + + # set flag if we have passed the 'mdat' atom + if ($tag eq 'mdat') { + if ($dataPt) { + $et->Error("'mdat' not at top level"); + } elsif ($foundMDAT and $foundMDAT == 1 and $lengthChanged and + not $et->Options('FixCorruptedMOV')) + { + $et->Error("Multiple 'mdat' blocks! Can only edit existing tags"); + $foundMDAT = 2; + } else { + $foundMDAT = 1; + } + } + + # rewrite this atom + my $tagInfo = $et->GetTagInfo($tagTablePtr, $tag); + if (defined $tagInfo and not $tagInfo) { + my $n = $size < 256 ? $size : 256; + unless ($raf->Read($buff, $n) == $n and $raf->Seek(-$n, 1)) { + $et->Error("Read/seek error in $tag atom"); + last; + } + $tagInfo = $et->GetTagInfo($tagTablePtr, $tag, \$buff); + } + if ($tagInfo) { + if ($$tagInfo{Unknown}) { + undef $tagInfo; + } elsif ($size > 100000000) { + # limit maximum size of atom that we load into memory + my $mb = $size / 0x100000; + $et->Warn("Not editing metadata in $tag atom. $mb MB is too big"); + undef $tagInfo; + } + } + if ($tagInfo and (not defined $$tagInfo{Writable} or $$tagInfo{Writable})) { + # read the atom data + $raf->Read($buff, $size) == $size or $et->Error("Error reading $tag data"), last; + my $subdir = $$tagInfo{SubDirectory}; + my $newData; + if ($subdir) { + my $subName = $$subdir{DirName} || $$tagInfo{Name}; + my $start = $$subdir{Start} || 0; + my $base = ($$dirInfo{Base} || 0) + $raf->Tell() - $size; + my $dPos = 0; + my $hdrLen = $start; + if ($$subdir{Base}) { + my $localBase = eval $$subdir{Base}; + $dPos -= $localBase; + $base -= $dPos; + # get length of header before base offset + $hdrLen -= $localBase if $localBase <= $hdrLen; + } + my %subdirInfo = ( + Parent => $dirName, + DirName => $subName, + DataPt => \$buff, + DataLen => $size, + DataPos => $dPos, + DirStart => $start, + DirLen => $size - $start, + Base => $base, + HasData => $$subdir{HasData}, # necessary? + Multi => $$subdir{Multi}, # necessary? + OutFile => $outfile, + InPlace => 2, # (to write fixed-length XMP if possible) + ); + # pass the header pointer if necessary (for EXIF IFD's + # where the Base offset is at the end of the header) + if ($hdrLen and $hdrLen < $size) { + my $header = substr($buff,0,$hdrLen); + $subdirInfo{HeaderPtr} = \$header; + } + SetByteOrder('II') if $$subdir{ByteOrder} and $$subdir{ByteOrder} =~ /^Little/; + my $oldWriteGroup = $$et{CUR_WRITE_GROUP}; + if ($subName eq 'Track') { + $track or $track = 0; + $$et{CUR_WRITE_GROUP} = 'Track' . (++$track); + } + my $subTable = GetTagTable($$subdir{TagTable}); + # demote non-QuickTime errors to warnings + $$et{DemoteErrors} = 1 unless $$subTable{GROUPS}{0} eq 'QuickTime'; + my $oldChanged = $$et{CHANGED}; + $newData = $et->WriteDirectory(\%subdirInfo, $subTable); + if ($$et{DemoteErrors}) { + # just copy existing subdirectory a non-quicktime error occurred + $$et{CHANGED} = $oldChanged if $$et{DemoteErrors} > 1; + delete $$et{DemoteErrors}; + } + undef $newData if $$et{CHANGED} == $oldChanged; # don't change unless necessary + $$et{CUR_WRITE_GROUP} = $oldWriteGroup; + SetByteOrder('MM'); + # add back header if necessary + if ($start and defined $newData and length $newData) { + $newData = substr($buff,0,$start) . $newData; + } + # the directory exists, so we don't need to add it + delete $$addDirs{$subName} if IsCurPath($et, $subName); + } else { + # --> this is where individual QuickTime tags would be edited, + # (this is such a can of worms, so don't implement this for now) + } + if (defined $newData) { + my $len = length $newData; + $len > 0x7ffffff7 and $et->Error("$tag to large to write"), last; + if ($len == $size or $dataPt or $foundMDAT) { + # write the updated directory now (unless length is zero, or it is needed as padding) + if ($len or (not $dataPt and not $foundMDAT) or + ($et->Options('FixCorruptedMOV') and $tag eq 'udta')) + { + Write($outfile, Set32u($len+8), $tag, $newData) or $rtnVal = 0, last; + $lengthChanged = 1 if $len != $size; + } else { + $lengthChanged = 1; # (we deleted this atom) + } + next; + } else { + # bad things happen if 'mdat' atom is moved (eg. Adobe Bridge crashes -- + # there are absolute offsets that point into mdat), so hold this atom + # and write it out later + if ($len) { + push @hold, Set32u($len+8), $tag, $newData; + $et->VPrint(0," Moving '${tag}' atom to after 'mdat'"); + } else { + $et->VPrint(0," Freeing '${tag}' atom (and zeroing data)"); + } + # write a 'free' atom here to keep 'mdat' at the same offset + substr($hdr, 4, 4) = 'free'; + $buff = "\0" x length($buff); # zero out old data + } + } + # write out the existing atom (or 'free' padding) + Write($outfile, $hdr, $buff) or $rtnVal = 0, last; + } else { + # write the unknown/large atom header + Write($outfile, $hdr) or $rtnVal = 0, last; + next unless $size; + # copy the atom data + my $result = Image::ExifTool::CopyBlock($raf, $outfile, $size); + defined $result or $rtnVal = 0, last; + $result or $et->Error("Truncated $tag atom"), last; + } + } + # add new directories at this level if necessary + if (exists $$et{EDIT_DIRS}{$dirName}) { + # get a hash of tagInfo references to add to this directory + my $dirs = $et->GetAddDirHash($tagTablePtr, $dirName); + # make sorted list of new tags to be added + my @addTags = sort keys(%$dirs); + my $tag; + foreach $tag (@addTags) { + my $tagInfo = $$dirs{$tag}; + my $subdir = $$tagInfo{SubDirectory} or next; + my $subName = $$subdir{DirName} || $$tagInfo{Name}; + # QuickTime hierarchy is complex, so check full directory path before adding + next unless IsCurPath($et, $subName); + my $buff = ''; # write from scratch + my %subdirInfo = ( + Parent => $dirName, + DirName => $subName, + DataPt => \$buff, + DirStart => 0, + OutFile => $outfile, + ); + my $subTable = GetTagTable($$subdir{TagTable}); + my $newData = $et->WriteDirectory(\%subdirInfo, $subTable); + if ($newData and length($newData) <= 0x7ffffff7) { + my $uuid = ''; + # add atom ID if necessary (obtain from Condition expression) + if ($$subdir{Start}) { + my $cond = $$tagInfo{Condition}; + $uuid = eval qq("$1") if $cond and $cond =~ m{=~\s*\/\^(.*)/}; + length($uuid) == $$subdir{Start} or $et->Error('Internal UUID error'); + } + my $newHdr = Set32u(8+length($newData)+length($uuid)) . $tag . $uuid; + Write($outfile, $newHdr, $newData) or $rtnVal = 0; + $lengthChanged = 1; + } + delete $$addDirs{$subName}; # add only once (must delete _after_ call to WriteDirectory()) + } + } + # write out any atoms that we are holding until the end + Write($outfile, @hold) or $rtnVal = 0 if @hold; + + # issue minor error if we didn't find an 'mdat' atom + # (we could duplicate atoms indefinitely through repeated editing if we + # held back some atoms here, so in this case it isn't a minor error) + $dataPt or $foundMDAT or $et->Error('No mdat atom found', @hold ? 0 : 1); + + return $dataPt ? ($rtnVal ? $$outfile : undef) : $rtnVal; +} + +#------------------------------------------------------------------------------ +# Write QuickTime-format MOV/MP4 file +# Inputs: 0) ExifTool ref, 1) dirInfo ref +# Returns: 1 on success, 0 if this wasn't a valid QuickTime file, +# or -1 if a write error occurred +sub WriteMOV($$) +{ + my ($et, $dirInfo) = @_; + $et or return 1; + my $raf = $$dirInfo{RAF} or return 0; + my ($buff, $ftype); + + # read the first atom header + return 0 unless $raf->Read($buff, 8) == 8; + my ($size, $tag) = unpack('Na4', $buff); + return 0 if $size < 8 and $size != 1; + + # validate the file format + my $tagTablePtr = GetTagTable('Image::ExifTool::QuickTime::Main'); + return 0 unless $$tagTablePtr{$tag}; + + # determine the file type + if ($tag eq 'ftyp' and $size >= 12 and $size < 100000 and + $raf->Read($buff, $size-8) == $size-8 and + $buff !~ /^(....)+(qt )/s) + { + # file is MP4 format if 'ftyp' exists without 'qt ' as a compatible brand + if ($buff =~ /^(heic|mif1|msf1|heix|hevc|hevx)/) { + $ftype = 'HEIC'; + $et->Error("Can't currently write HEIC/HEIF files"); + } else { + $ftype = 'MP4'; + } + } else { + $ftype = 'MOV'; + } + $et->SetFileType($ftype); # need to set "FileType" tag for a Condition + $et->InitWriteDirs($dirMap{$ftype}, 'XMP'); + $$et{DirMap} = $dirMap{$ftype}; # need access to directory map when writing + SetByteOrder('MM'); + $raf->Seek(0,0); + + # write the file + $$dirInfo{Parent} = ''; + $$dirInfo{DirName} = 'MOV'; + return WriteQuickTime($et, $dirInfo, $tagTablePtr) ? 1 : -1; +} + +1; # end + +__END__ + +=head1 NAME + +Image::ExifTool::WriteQuickTime.pl - Write XMP to QuickTime (MOV and MP4) files + +=head1 SYNOPSIS + +These routines are autoloaded by Image::ExifTool::QuickTime. + +=head1 DESCRIPTION + +This file contains routines used by ExifTool to write XMP metadata to +QuickTime-based file formats like MOV and MP4. + +=head1 AUTHOR + +Copyright 2003-2019, Phil Harvey (phil at owl.phy.queensu.ca) + +This library is free software; you can redistribute it and/or modify it +under the same terms as Perl itself. + +=head1 SEE ALSO + +L<Image::ExifTool::QuickTime(3pm)|Image::ExifTool::QuickTime>, +L<Image::ExifTool(3pm)|Image::ExifTool> + +=cut diff --git a/lib/Image/ExifTool/WriteXMP.pl b/lib/Image/ExifTool/WriteXMP.pl new file mode 100644 index 0000000..47c2e49 --- /dev/null +++ b/lib/Image/ExifTool/WriteXMP.pl @@ -0,0 +1,1505 @@ +#------------------------------------------------------------------------------ +# File: WriteXMP.pl +# +# Description: Write XMP meta information +# +# Revisions: 12/19/2004 - P. Harvey Created +#------------------------------------------------------------------------------ +package Image::ExifTool::XMP; + +use strict; +use vars qw(%specialStruct %dateTimeInfo %stdXlatNS); + +use Image::ExifTool qw(:DataAccess :Utils); + +sub CheckXMP($$$); +sub CaptureXMP($$$;$); +sub SetPropertyPath($$;$$$$); + +my $debug = 0; +my $numPadLines = 24; # number of blank padding lines + +# when writing extended XMP, resources bigger than this get placed in their own +# rdf:Description so they can be moved to the extended segments if necessary +my $newDescThresh = 10240; # 10 kB + +# individual resources and namespaces to place last in separate rdf:Description's +# so they can be moved to extended XMP segments if required (see Oct. 2008 XMP spec) +my %extendedRes = ( + 'photoshop:History' => 1, + 'xap:Thumbnails' => 1, + 'xmp:Thumbnails' => 1, + 'crs' => 1, + 'crss' => 1, +); + +my $rdfDesc = 'rdf:Description'; +# +# packet/xmp/rdf headers and trailers +# +my $pktOpen = "<?xpacket begin='\xef\xbb\xbf' id='W5M0MpCehiHzreSzNTczkc9d'?>\n"; +my $xmlOpen = "<?xml version='1.0' encoding='UTF-8'?>\n"; +my $xmpOpenPrefix = "<x:xmpmeta xmlns:x='$nsURI{x}'"; +my $rdfOpen = "<rdf:RDF xmlns:rdf='$nsURI{rdf}'>\n"; +my $rdfClose = "</rdf:RDF>\n"; +my $xmpClose = "</x:xmpmeta>\n"; +my $pktCloseW = "<?xpacket end='w'?>"; # writable by default +my $pktCloseR = "<?xpacket end='r'?>"; +my $noPad; + +#------------------------------------------------------------------------------ +# Get XMP opening tag (and set x:xmptk appropriately) +# Inputs: 0) ExifTool object ref +# Returns: x:xmpmeta opening tag +sub XMPOpen($) +{ + my $et = shift; + my $nv = $$et{NEW_VALUE}{$Image::ExifTool::XMP::x{xmptk}}; + my $tk; + if (defined $nv) { + $tk = $et->GetNewValue($nv); + $et->VerboseValue(($tk ? '+' : '-') . ' XMP-x:XMPToolkit', $tk); + ++$$et{CHANGED}; + } else { + $tk = "Image::ExifTool $Image::ExifTool::VERSION"; + } + my $str = $tk ? (" x:xmptk='" . EscapeXML($tk) . "'") : ''; + return "$xmpOpenPrefix$str>\n"; +} + +#------------------------------------------------------------------------------ +# Validate XMP packet and set read or read/write mode +# Inputs: 0) XMP data reference, 1) 'r' = read only, 'w' or undef = read/write +# Returns: true if XMP is good (and adds packet header/trailer if necessary) +sub ValidateXMP($;$) +{ + my ($xmpPt, $mode) = @_; + $$xmpPt =~ s/^\s*<!--.*?-->\s*//s; # remove leading comment if it exists + unless ($$xmpPt =~ /^\0*<\0*\?\0*x\0*p\0*a\0*c\0*k\0*e\0*t/) { + return '' unless $$xmpPt =~ /^<x(mp)?:x[ma]pmeta/; + # add required xpacket header/trailer + $$xmpPt = $pktOpen . $$xmpPt . $pktCloseW; + } + $mode = 'w' unless $mode; + my $end = substr($$xmpPt, -32, 32); + # check for proper xpacket trailer and set r/w mode if necessary + return '' unless $end =~ s/(e\0*n\0*d\0*=\0*['"]\0*)([rw])(\0*['"]\0*\?\0*>)/$1$mode$3/; + substr($$xmpPt, -32, 32) = $end if $2 ne $mode; + return 1; +} + +#------------------------------------------------------------------------------ +# Validate XMP property +# Inputs: 0) ExifTool ref, 1) validate hash ref +# - issues warnings if problems detected +sub ValidateProperty($$) +{ + my ($et, $propList) = @_; + + if ($$et{XmpValidate} and @$propList > 2) { + if ($$propList[0] =~ /^x:x[ma]pmeta$/ and + $$propList[1] eq 'rdf:RDF' and + $$propList[2] =~ /rdf:Description( |$)/) + { + if (@$propList > 3) { + if ($$propList[-1] =~ /^rdf:(Bag|Seq|Alt)$/) { + $et->Warn("Ignored empty $$propList[-1] list for $$propList[-2]", 1); + } else { + my $xmpValidate = $$et{XmpValidate}; + my $path = join('/', @$propList[3..$#$propList]); + if (defined $$xmpValidate{$path}) { + $et->Warn("Duplicate XMP property: $path") if defined $$xmpValidate{$path}; + } else { + $$xmpValidate{$path} = 1; + } + } + } + } elsif ($$propList[0] ne 'rdf:RDF' or + $$propList[1] !~ /rdf:Description( |$)/) + { + $et->Warn('Improperly enclosed XMP property: ' . join('/',@$propList)); + } + } +} + +#------------------------------------------------------------------------------ +# Check XMP date values for validity and format accordingly +# Inputs: 1) date string +# Returns: XMP date/time string (or undef on error) +sub FormatXMPDate($) +{ + my $val = shift; + my ($y, $m, $d, $t, $tz); + if ($val =~ /(\d{4}):(\d{2}):(\d{2}) (\d{2}:\d{2}(?::\d{2}(?:\.\d*)?)?)(.*)/) { + ($y, $m, $d, $t, $tz) = ($1, $2, $3, $4, $5); + $val = "$y-$m-${d}T$t"; + } elsif ($val =~ /^\s*\d{4}(:\d{2}){0,2}\s*$/) { + # this is just a date (YYYY, YYYY-mm or YYYY-mm-dd) + $val =~ tr/:/-/; + } elsif ($val =~ /^\s*(\d{2}:\d{2}(?::\d{2}(?:\.\d*)?)?)(.*)\s*$/) { + # this is just a time + ($t, $tz) = ($1, $2); + $val = $t; + } else { + return undef; + } + if ($tz) { + $tz =~ /^(Z|[+-]\d{2}:\d{2})$/ or return undef; + $val .= $tz; + } + return $val; +} + +#------------------------------------------------------------------------------ +# Check XMP values for validity and format accordingly +# Inputs: 0) ExifTool object ref, 1) tagInfo hash ref, 2) raw value ref +# Returns: error string or undef (and may change value) on success +# Note: copies structured information to avoid conflicts with calling code +sub CheckXMP($$$) +{ + my ($et, $tagInfo, $valPtr) = @_; + + if ($$tagInfo{Struct}) { + require 'Image/ExifTool/XMPStruct.pl'; + my ($item, $err, $w, $warn); + unless (ref $$valPtr) { + ($$valPtr, $warn) = InflateStruct($valPtr); + # expect a structure HASH ref or ARRAY of structures + unless (ref $$valPtr) { + $$valPtr eq '' and $$valPtr = { }, return undef; # allow empty structures + return 'Improperly formed structure'; + } + } + if (ref $$valPtr eq 'ARRAY') { + return 'Not a list tag' unless $$tagInfo{List}; + my @copy = ( @{$$valPtr} ); # copy the list for ExifTool to use + $$valPtr = \@copy; # return the copy + foreach $item (@copy) { + unless (ref $item eq 'HASH') { + ($item, $w) = InflateStruct(\$item); # deserialize structure + $w and $warn = $w; + next if ref $item eq 'HASH'; + $err = 'Improperly formed structure'; + last; + } + ($item, $err) = CheckStruct($et, $item, $$tagInfo{Struct}); + last if $err; + } + } else { + ($$valPtr, $err) = CheckStruct($et, $$valPtr, $$tagInfo{Struct}); + } + $warn and $$et{CHECK_WARN} = $warn; + return $err; + } + my $format = $$tagInfo{Writable}; + # (if no format specified, value is a simple string) + if (not $format or $format eq 'string' or $format eq 'lang-alt') { + # convert value to UTF8 if necessary + if ($$et{OPTIONS}{Charset} ne 'UTF8') { + if ($$valPtr =~ /[\x80-\xff]/) { + # convert from Charset to UTF-8 + $$valPtr = $et->Encode($$valPtr,'UTF8'); + } + } else { + # translate invalid XML characters to "." + $$valPtr =~ tr/\0-\x08\x0b\x0c\x0e-\x1f/./; + # fix any malformed UTF-8 characters + if (FixUTF8($valPtr) and not $$et{WarnBadUTF8}) { + $et->Warn('Malformed UTF-8 character(s)'); + $$et{WarnBadUTF8} = 1; + } + } + return undef; # success + } + if ($format eq 'rational' or $format eq 'real') { + # make sure the value is a valid floating point number + unless (Image::ExifTool::IsFloat($$valPtr) or + # allow 'inf' and 'undef' rational values + ($format eq 'rational' and ($$valPtr eq 'inf' or + $$valPtr eq 'undef' or Image::ExifTool::IsRational($$valPtr)))) + { + return 'Not a floating point number'; + } + if ($format eq 'rational') { + $$valPtr = join('/', Image::ExifTool::Rationalize($$valPtr)); + } + } elsif ($format eq 'integer') { + # make sure the value is integer + if (Image::ExifTool::IsInt($$valPtr)) { + # no conversion required (converting to 'int' would remove leading '+') + } elsif (Image::ExifTool::IsHex($$valPtr)) { + $$valPtr = hex($$valPtr); + } else { + return 'Not an integer'; + } + } elsif ($format eq 'date') { + my $newDate = FormatXMPDate($$valPtr); + return "Invalid date/time (use YYYY:mm:dd HH:MM:SS[.ss][+/-HH:MM|Z])" unless $newDate; + $$valPtr = $newDate; + } elsif ($format eq 'boolean') { + if (not $$valPtr or $$valPtr =~ /false/i or $$valPtr =~ /^no$/i) { + $$valPtr = 'False'; + } else { + $$valPtr = 'True'; + } + } elsif ($format eq '1') { + # this is the entire XMP data block + return 'Invalid XMP data' unless ValidateXMP($valPtr); + } else { + return "Unknown XMP format: $format"; + } + return undef; # success! +} + +#------------------------------------------------------------------------------ +# Get PropertyPath for specified tagInfo +# Inputs: 0) tagInfo reference +# Returns: PropertyPath string +sub GetPropertyPath($) +{ + my $tagInfo = shift; + SetPropertyPath($$tagInfo{Table}, $$tagInfo{TagID}) unless $$tagInfo{PropertyPath}; + return $$tagInfo{PropertyPath}; +} + +#------------------------------------------------------------------------------ +# Set PropertyPath for specified tag (also for associated flattened tags and structure elements) +# Inputs: 0) tagTable reference, 1) tagID, 2) tagID of parent structure, +# 3) structure definition ref (or undef), 4) property list up to this point (or undef), +# 5) flag set if any containing structure has a TYPE +# Notes: also generates flattened tags if they don't already exist +sub SetPropertyPath($$;$$$$) +{ + my ($tagTablePtr, $tagID, $parentID, $structPtr, $propList, $isType) = @_; + my $table = $structPtr || $tagTablePtr; + my $tagInfo = $$table{$tagID}; + my $flatInfo; + + return if ref($tagInfo) ne 'HASH'; # (shouldn't happen) + + if ($structPtr) { + my $flatID = $parentID . ucfirst($tagID); + $flatInfo = $$tagTablePtr{$flatID}; + if ($flatInfo) { + return if $$flatInfo{PropertyPath}; + } else { + # flattened tag doesn't exist, so create it now + # (could happen if we were just writing a structure) + $flatInfo = { Name => ucfirst($flatID), Flat => 1 }; + AddTagToTable($tagTablePtr, $flatID, $flatInfo); + } + $isType = 1 if $$structPtr{TYPE}; + } else { + # don't override existing main table entry if already set by a Struct + return if $$tagInfo{PropertyPath}; + # use property path from original tagInfo if this is an alternate-language tag + my $srcInfo = $$tagInfo{SrcTagInfo}; + $$tagInfo{PropertyPath} = GetPropertyPath($srcInfo) if $srcInfo; + return if $$tagInfo{PropertyPath}; + # set property path for all flattened tags in structure if necessary + if ($$tagInfo{RootTagInfo}) { + SetPropertyPath($tagTablePtr, $$tagInfo{RootTagInfo}{TagID}); + return if $$tagInfo{PropertyPath}; + warn "Internal Error: Didn't set path from root for $tagID\n"; + warn "(Is the Struct NAMESPACE defined?)\n"; + } + } + my $ns = $$tagInfo{Namespace} || $$table{NAMESPACE}; + $ns or warn("No namespace for $tagID\n"), return; + my (@propList, $listType); + $propList and @propList = @$propList; + push @propList, "$ns:$tagID"; + # lang-alt lists are handled specially, signified by Writable='lang-alt' + if ($$tagInfo{Writable} and $$tagInfo{Writable} eq 'lang-alt') { + $listType = 'Alt'; + # remove language code from property path if it exists + $propList[-1] =~ s/-$$tagInfo{LangCode}$// if $$tagInfo{LangCode}; + # handle lists of lang-alt lists (eg. XMP-plus:Custom tags) + if ($$tagInfo{List} and $$tagInfo{List} ne '1') { + push @propList, "rdf:$$tagInfo{List}", 'rdf:li 10'; + } + } else { + $listType = $$tagInfo{List}; + } + # add required properties if this is a list + push @propList, "rdf:$listType", 'rdf:li 10' if $listType and $listType ne '1'; + # set PropertyPath for all flattened tags of this structure if necessary + # (note: don't do this for variable-namespace structures (undef NAMESPACE)) + my $strTable = $$tagInfo{Struct}; + if ($strTable and $$strTable{NAMESPACE} and not ($parentID and + # must test NoSubStruct flag to avoid infinite recursion + (($$tagTablePtr{$parentID} and $$tagTablePtr{$parentID}{NoSubStruct}) or + length $parentID > 500))) # avoid deep recursion + { + # make sure the structure namespace has been registered + # (user-defined namespaces may not have been) + RegisterNamespace($strTable) if ref $$strTable{NAMESPACE}; + my $tag; + foreach $tag (keys %$strTable) { + # ignore special fields and any lang-alt fields we may have added + next if $specialStruct{$tag} or $$strTable{$tag}{LangCode}; + my $fullID = $parentID ? $parentID . ucfirst($tagID) : $tagID; + SetPropertyPath($tagTablePtr, $tag, $fullID, $strTable, \@propList, $isType); + } + } + # if this was a structure field and not a normal tag, + # we set PropertyPath in the corresponding flattened tag + if ($structPtr) { + $tagInfo = $flatInfo; + # set StructType flag if any containing structure has a TYPE + $$tagInfo{StructType} = 1 if $isType; + } + # set property path for tagInfo in main table + $$tagInfo{PropertyPath} = join '/', @propList; +} + +#------------------------------------------------------------------------------ +# Save XMP property name/value for rewriting +# Inputs: 0) ExifTool object reference +# 1) reference to array of XMP property path (last is current property) +# 2) property value, 3) optional reference to hash of property attributes +sub CaptureXMP($$$;$) +{ + my ($et, $propList, $val, $attrs) = @_; + return unless defined $val and @$propList > 2; + if ($$propList[0] =~ /^x:x[ma]pmeta$/ and + $$propList[1] eq 'rdf:RDF' and + $$propList[2] =~ /$rdfDesc( |$)/) + { + # no properties to save yet if this is just the description + return unless @$propList > 3; + # ignore empty list properties + if ($$propList[-1] =~ /^rdf:(Bag|Seq|Alt)$/) { + $et->Warn("Ignored empty $$propList[-1] list for $$propList[-2]", 1); + return; + } + # save information about this property + my $capture = $$et{XMP_CAPTURE}; + my $path = join('/', @$propList[3..$#$propList]); + if (defined $$capture{$path}) { + $$et{XMP_ERROR} = "Duplicate XMP property: $path"; + } else { + $$capture{$path} = [$val, $attrs || { }]; + } + } elsif ($$propList[0] eq 'rdf:RDF' and + $$propList[1] =~ /$rdfDesc( |$)/) + { + # set flag so we don't write x:xmpmeta element + $$et{XMP_NO_XMPMETA} = 1; + # add missing x:xmpmeta element and try again + unshift @$propList, 'x:xmpmeta'; + CaptureXMP($et, $propList, $val, $attrs); + } else { + $$et{XMP_ERROR} = 'Improperly enclosed XMP property: ' . join('/',@$propList); + } +} + +#------------------------------------------------------------------------------ +# Save information about resource containing blank node with nodeID +# Inputs: 0) reference to blank node information hash +# 1) reference to property list +# 2) property value +# 3) [optional] reference to attribute hash +# Notes: This routine and ProcessBlankInfo() are also used for reading information, but +# are uncommon so are put in this file to reduce compile time for the common case +sub SaveBlankInfo($$$;$) +{ + my ($blankInfo, $propListPt, $val, $attrs) = @_; + + my $propPath = join '/', @$propListPt; + my @ids = ($propPath =~ m{ #([^ /]*)}g); + my $id; + # split the property path at each nodeID + foreach $id (@ids) { + my ($pre, $prop, $post) = ($propPath =~ m{^(.*?)/([^/]*) #$id((/.*)?)$}); + defined $pre or warn("internal error parsing nodeID's"), next; + # the element with the nodeID should be in the path prefix for subject + # nodes and the path suffix for object nodes + unless ($prop eq $rdfDesc) { + if ($post) { + $post = "/$prop$post"; + } else { + $pre = "$pre/$prop"; + } + } + $$blankInfo{Prop}{$id}{Pre}{$pre} = 1; + if ((defined $post and length $post) or (defined $val and length $val)) { + # save the property value and attributes for each unique path suffix + $$blankInfo{Prop}{$id}{Post}{$post} = [ $val, $attrs, $propPath ]; + } + } +} + +#------------------------------------------------------------------------------ +# Process blank-node information +# Inputs: 0) ExifTool object ref, 1) tag table ref, +# 2) blank node information hash ref, 3) flag set for writing +sub ProcessBlankInfo($$$;$) +{ + my ($et, $tagTablePtr, $blankInfo, $isWriting) = @_; + $et->VPrint(1, " [Elements with nodeID set:]\n") unless $isWriting; + my ($id, $pre, $post); + # handle each nodeID separately + foreach $id (sort keys %{$$blankInfo{Prop}}) { + my $path = $$blankInfo{Prop}{$id}; + # flag all resource names so we can warn later if some are unused + my %unused; + foreach $post (keys %{$$path{Post}}) { + $unused{$post} = 1; + } + # combine property paths for all possible paths through this node + foreach $pre (sort keys %{$$path{Pre}}) { + # there will be no description for the object of a blank node + next unless $pre =~ m{/$rdfDesc/}; + foreach $post (sort keys %{$$path{Post}}) { + my @propList = split m{/}, "$pre$post"; + my ($val, $attrs) = @{$$path{Post}{$post}}; + if ($isWriting) { + CaptureXMP($et, \@propList, $val, $attrs); + } else { + FoundXMP($et, $tagTablePtr, \@propList, $val); + } + delete $unused{$post}; + } + } + # save information from unused properties (if RDF is malformed like f-spot output) + if (%unused) { + $et->Options('Verbose') and $et->Warn('An XMP resource is about nothing'); + foreach $post (sort keys %unused) { + my ($val, $attrs, $propPath) = @{$$path{Post}{$post}}; + my @propList = split m{/}, $propPath; + if ($isWriting) { + CaptureXMP($et, \@propList, $val, $attrs); + } else { + FoundXMP($et, $tagTablePtr, \@propList, $val); + } + } + } + } +} + +#------------------------------------------------------------------------------ +# Convert path to namespace used in file (this is a pain, but the XMP +# spec only suggests 'preferred' namespace prefixes...) +# Inputs: 0) ExifTool object reference, 1) property path +# Returns: conforming property path +sub ConformPathToNamespace($$) +{ + my ($et, $path) = @_; + my @propList = split('/',$path); + my $nsUsed = $$et{XMP_NS}; + my $prop; + foreach $prop (@propList) { + my ($ns, $tag) = $prop =~ /(.+?):(.*)/; + next if $$nsUsed{$ns}; + my $uri = $nsURI{$ns}; + unless ($uri) { + warn "No URI for namepace prefix $ns!\n"; + next; + } + my $ns2; + foreach $ns2 (keys %$nsUsed) { + next unless $$nsUsed{$ns2} eq $uri; + # use the existing namespace prefix instead of ours + $prop = "$ns2:$tag"; + last; + } + } + return join('/',@propList); +} + +#------------------------------------------------------------------------------ +# Add necessary rdf:type element when writing structure +# Inputs: 0) ExifTool ref, 1) tag table ref, 2) capture hash ref, 3) path string +# 4) optional base path (already conformed to namespace) for elements in +# variable-namespace structures +sub AddStructType($$$$;$) +{ + my ($et, $tagTablePtr, $capture, $path, $basePath) = @_; + my @props = split '/', $path; + my %doneID; + for (;;) { + pop @props; + last unless @props; + my $tagID = GetXMPTagID(\@props); + next if $doneID{$tagID}; + $doneID{$tagID} = 1; + my $tagInfo = $$tagTablePtr{$tagID}; + last unless ref $tagInfo eq 'HASH'; + if ($$tagInfo{Struct}) { + my $type = $$tagInfo{Struct}{TYPE}; + if ($type) { + my $pat = $$tagInfo{PropertyPath}; + $pat or warn("Missing PropertyPath in AddStructType\n"), last; + $pat = ConformPathToNamespace($et, $pat); + $pat =~ s/ \d+/ \\d\+/g; + $path =~ /^($pat)/ or warn("Wrong path in AddStructType\n"), last; + my $p = $1 . '/rdf:type'; + $p = "$basePath/$p" if $basePath; + $$capture{$p} = [ '', { 'rdf:resource' => $type } ] unless $$capture{$p}; + } + } + last unless $$tagInfo{StructType}; + } +} + +#------------------------------------------------------------------------------ +# Utility routine to encode data in base64 +# Inputs: 0) binary data string, 1) flag to avoid inserting newlines +# Returns: base64-encoded string +sub EncodeBase64($;$) +{ + # encode the data in 45-byte chunks + my $chunkSize = 45; + my $len = length $_[0]; + my $str = ''; + my $i; + for ($i=0; $i<$len; $i+=$chunkSize) { + my $n = $len - $i; + $n = $chunkSize if $n > $chunkSize; + # add uuencoded data to output (minus size byte, but including trailing newline) + $str .= substr(pack('u', substr($_[0], $i, $n)), 1); + } + # convert to base64 (remember that "\0" may be encoded as ' ' or '`') + $str =~ tr/` -_/AA-Za-z0-9+\//; + # convert pad characters at the end (remember to account for trailing newline) + my $pad = 3 - ($len % 3); + substr($str, -$pad-1, $pad) = ('=' x $pad) if $pad < 3; + $str =~ tr/\n//d if $_[1]; # remove newlines if specified + return $str; +} + +#------------------------------------------------------------------------------ +# sort tagInfo hash references by tag name +sub ByTagName +{ + return $$a{Name} cmp $$b{Name}; +} + +#------------------------------------------------------------------------------ +# sort alphabetically, but with rdf:type first in the structure +sub TypeFirst +{ + if ($a =~ /rdf:type$/) { + return substr($a, 0, -8) cmp $b unless $b =~ /rdf:type$/; + } elsif ($b =~ /rdf:type$/) { + return $a cmp substr($b, 0, -8); + } + return $a cmp $b; +} + +#------------------------------------------------------------------------------ +# Limit size of XMP +# Inputs: 0) ExifTool object ref, 1) XMP data ref (written up to start of $rdfClose), +# 2) max XMP len, 3) rdf:about string, 4) list ref for description start offsets +# 5) start offset of first description recommended for extended XMP +# Returns: 0) extended XMP ref, 1) GUID and updates $$dataPt (or undef if no extended XMP) +sub LimitXMPSize($$$$$$) +{ + my ($et, $dataPt, $maxLen, $about, $startPt, $extStart) = @_; + + # return straight away if it isn't too big + return undef if length($$dataPt) < $maxLen; + + push @$startPt, length($$dataPt); # add end offset to list + my $newData = substr($$dataPt, 0, $$startPt[0]); + my $guid = '0' x 32; + my $sp = $noPad ? '' : ' '; + # write the required xmpNote:HasExtendedXMP property + $newData .= "\n$sp<$rdfDesc rdf:about='${about}'\n$sp${sp}xmlns:xmpNote='$nsURI{xmpNote}'"; + if ($et->Options('XMPShorthand')) { + $newData .= "\n$sp${sp}xmpNote:HasExtendedXMP='${guid}'/>\n"; + } else { + $newData .= ">\n$sp$sp<xmpNote:HasExtendedXMP>$guid</xmpNote:HasExtendedXMP>\n$sp</$rdfDesc>\n"; + } + + my ($i, %descSize, $start); + # calculate all description block sizes + for ($i=1; $i<@$startPt; ++$i) { + $descSize{$$startPt[$i-1]} = $$startPt[$i] - $$startPt[$i-1]; + } + pop @$startPt; # remove end offset + # write the descriptions from smallest to largest, as many in main XMP as possible + my @descStart = sort { $descSize{$a} <=> $descSize{$b} } @$startPt; + my $extData = XMPOpen($et) . $rdfOpen; + for ($i=0; $i<2; ++$i) { + foreach $start (@descStart) { + # write main XMP first (in order of size), then extended XMP afterwards (in order) + next if $i xor $start >= $extStart; + my $pt = (length($newData) + $descSize{$start} > $maxLen) ? \$extData : \$newData; + $$pt .= substr($$dataPt, $start, $descSize{$start}); + } + } + $extData .= $rdfClose . $xmpClose; # close rdf:RDF and x:xmpmeta + # calculate GUID from MD5 of extended XMP data + if (eval { require Digest::MD5 }) { + $guid = uc unpack('H*', Digest::MD5::md5($extData)); + $newData =~ s/0{32}/$guid/; # update GUID in main XMP segment + } + $et->VerboseValue('+ XMP-xmpNote:HasExtendedXMP', $guid); + $$dataPt = $newData; # return main XMP block + return (\$extData, $guid); # return extended XMP and its GUID +} + +#------------------------------------------------------------------------------ +# Close out bottom-level property +# Inputs: 0) current property path list ref, 1) longhand properties at each resource +# level, 2) shorthand properties at each resource level, 3) resource flag for +# each property path level (set only if XMPShorthand is enabled) +sub CloseProperty($$$$) +{ + my ($curPropList, $long, $short, $resFlag) = @_; + + my $prop = pop @$curPropList; + $prop =~ s/ .*//; # remove list index if it exists + my $pad = $noPad ? '' : ' ' x (scalar(@$curPropList) + 1); + if ($$resFlag[@$curPropList]) { + # close this XMP structure with possible shorthand properties + if (length $$short[-1]) { + if (length $$long[-1]) { + # require a new Description if both longhand and shorthand properties + $$long[-2] .= ">\n$pad<$rdfDesc"; + $$short[-1] .= ">\n"; + $$long[-1] .= "$pad</$rdfDesc>\n"; + } else { + # simply close empty property if all shorthand + $$short[-1] .= "/>\n"; + } + } else { + # use "parseType" instead of opening a new Description + $$long[-2] .= ' rdf:parseType="Resource"'; + $$short[-1] = length $$long[-1] ? ">\n" : "/>\n"; + } + $$long[-1] .= "$pad</$prop>\n" if length $$long[-1]; + $$long[-2] .= $$short[-1] . $$long[-1]; + pop @$short; + pop @$long; + } elsif (defined $$resFlag[@$curPropList]) { + # close this top level Description with possible shorthand values + if (length $$long[-1]) { + $$long[-2] .= $$short[-1] . ">\n" . $$long[-1] . "$pad</$prop>\n"; + } else { + $$long[-2] .= $$short[-1] . "/>\n"; # empty element (ie. all shorthand) + } + $$short[-1] = $$long[-1] = ''; + } else { + # close this property (no chance of shorthand) + $$long[-1] .= "$pad</$prop>\n"; + unless (@$curPropList) { + # add properties now that this top-level Description is complete + $$long[-2] .= ">\n" . $$long[-1]; + $$long[-1] = ''; + } + } + $#$resFlag = $#$curPropList; # remove expired resource flags +} + +#------------------------------------------------------------------------------ +# Write XMP information +# Inputs: 0) ExifTool object reference, 1) source dirInfo reference, +# 2) [optional] tag table reference +# Returns: with tag table: new XMP data (may be empty if no XMP data) or undef on error +# without tag table: 1 on success, 0 if not valid XMP file, -1 on write error +# Notes: May set dirInfo InPlace flag to rewrite with specified DirLen (=2 to allow larger) +# May set dirInfo ReadOnly flag to write as read-only XMP ('r' mode and no padding) +# May set dirInfo Compact flag to force compact (drops 2kB of padding) +# May set dirInfo MaxDataLen to limit output data length -- this causes ExtendedXMP +# and ExtendedGUID to be returned in dirInfo if extended XMP was required +sub WriteXMP($$;$) +{ + my ($et, $dirInfo, $tagTablePtr) = @_; + $et or return 1; # allow dummy access to autoload this package + my $dataPt = $$dirInfo{DataPt}; + my (%capture, %nsUsed, $xmpErr, $about); + my $changed = 0; + my $xmpFile = (not $tagTablePtr); # this is an XMP data file if no $tagTablePtr + # prefer XMP over other metadata formats in some types of files + my $preferred = $xmpFile || ($$et{PreferredGroup} and $$et{PreferredGroup} eq 'XMP'); + my $verbose = $et->Options('Verbose'); + my $compact = $et->Options('Compact') || 0; + my $dirLen = $$dirInfo{DirLen}; + $dirLen = length($$dataPt) if not defined $dirLen and $dataPt; + $noPad = ($compact > 1); +# +# extract existing XMP information into %capture hash +# + # define hash in ExifTool object to capture XMP information (also causes + # CaptureXMP() instead of FoundXMP() to be called from ParseXMPElement()) + # + # The %capture hash is keyed on the complete property path beginning after + # rdf:RDF/rdf:Description/. The values are array references with the + # following entries: 0) value, 1) attribute hash reference. + $$et{XMP_CAPTURE} = \%capture; + $$et{XMP_NS} = \%nsUsed; + delete $$et{XMP_NO_XMPMETA}; + delete $$et{XMP_NO_XPACKET}; + delete $$et{XMP_IS_XML}; + delete $$et{XMP_IS_SVG}; + + # get value for new rdf:about + my $tagInfo = $Image::ExifTool::XMP::rdf{about}; + if (defined $$et{NEW_VALUE}{$tagInfo}) { + $about = $et->GetNewValue($$et{NEW_VALUE}{$tagInfo}) || ''; + } + + if ($xmpFile or $dirLen) { + delete $$et{XMP_ERROR}; + # extract all existing XMP information (to the XMP_CAPTURE hash) + my $success = ProcessXMP($et, $dirInfo, $tagTablePtr); + # don't continue if there is nothing to parse or if we had a parsing error + unless ($success and not $$et{XMP_ERROR}) { + my $err = $$et{XMP_ERROR} || 'Error parsing XMP'; + # may ignore this error only if we were successful + if ($xmpFile) { + my $raf = $$dirInfo{RAF}; + # allow empty XMP data so we can create something from nothing + if ($success or not $raf->Seek(0,2) or $raf->Tell()) { + # no error message if not an XMP file + return 0 unless $$et{XMP_ERROR}; + if ($et->Error($err, $success)) { + delete $$et{XMP_CAPTURE}; + return 0; + } + } + } else { + $success = 2 if $success and $success eq '1'; + if ($et->Warn($err, $success)) { + delete $$et{XMP_CAPTURE}; + return undef; + } + } + } + if (defined $about) { + if ($verbose > 1) { + my $wasAbout = $$et{XmpAbout}; + $et->VerboseValue('- XMP-rdf:About', UnescapeXML($wasAbout)) if defined $wasAbout; + $et->VerboseValue('+ XMP-rdf:About', $about); + } + $about = EscapeXML($about); # must escape for XML + ++$changed; + } else { + $about = $$et{XmpAbout} || ''; + } + delete $$et{XMP_ERROR}; + + # call InitWriteDirs to initialize FORCE_WRITE flags if necessary + $et->InitWriteDirs({}, 'XMP') if $xmpFile and $et->GetNewValue('ForceWrite'); + # set changed if we are ForceWrite tag was set to "XMP" + ++$changed if $$et{FORCE_WRITE}{XMP}; + + } elsif (defined $about) { + $et->VerboseValue('+ XMP-rdf:About', $about); + $about = EscapeXML($about); # must escape for XML + # (don't increment $changed here because we need another tag to be written) + } else { + $about = ''; + } +# +# handle writing XMP as a block to XMP file +# + if ($xmpFile) { + $tagInfo = $Image::ExifTool::Extra{XMP}; + if ($tagInfo and $$et{NEW_VALUE}{$tagInfo}) { + my $rtnVal = 1; + my $newVal = $et->GetNewValue($$et{NEW_VALUE}{$tagInfo}); + if (defined $newVal and length $newVal) { + $et->VPrint(0, " Writing XMP as a block\n"); + ++$$et{CHANGED}; + Write($$dirInfo{OutFile}, $newVal) or $rtnVal = -1; + } + delete $$et{XMP_CAPTURE}; + return $rtnVal; + } + } +# +# delete groups in family 1 if requested +# + if (%{$$et{DEL_GROUP}} and (grep /^XMP-.+$/, keys %{$$et{DEL_GROUP}} or + # (logic is a bit more complex for group names in exiftool XML files) + grep m{^http://ns.exiftool.ca/}, values %nsUsed)) + { + my $del = $$et{DEL_GROUP}; + my $path; + foreach $path (keys %capture) { + my @propList = split('/',$path); # get property list + my ($tag, $ns) = GetXMPTagID(\@propList); + # translate namespace if necessary + $ns = $stdXlatNS{$ns} if $stdXlatNS{$ns}; + my ($grp, @g); + # no "XMP-" added to most groups in exiftool RDF/XML output file + if ($nsUsed{$ns} and (@g = ($nsUsed{$ns} =~ m{^http://ns.exiftool.ca/(.*?)/(.*?)/}))) { + if ($g[1] =~ /^\d/) { + $grp = "XML-$g[0]"; + #(all XML-* groups stored as uppercase DEL_GROUP key) + my $ucg = uc $grp; + next unless $$del{$ucg} or ($$del{'XML-*'} and not $$del{"-$ucg"}); + } else { + $grp = $g[1]; + next unless $$del{$grp} or ($$del{$g[0]} and not $$del{"-$grp"}); + } + } else { + $grp = "XMP-$ns"; + my $ucg = uc $grp; + next unless $$del{$ucg} or ($$del{'XMP-*'} and not $$del{"-$ucg"}); + } + $et->VerboseValue("- $grp:$tag", $capture{$path}->[0]); + delete $capture{$path}; + ++$changed; + } + } + # delete HasExtendedXMP tag (we create it as needed) + my $hasExtTag = 'xmpNote:HasExtendedXMP'; + if ($capture{$hasExtTag}) { + $et->VerboseValue("- XMP-$hasExtTag", $capture{$hasExtTag}->[0]); + delete $capture{$hasExtTag}; + } + # set $xmpOpen now to to handle xmptk tag first + my $xmpOpen = $$et{XMP_NO_XMPMETA} ? '' : XMPOpen($et); +# +# add, delete or change information as specified +# + # get hash of all information we want to change + # (sorted by tag name so alternate languages come last, but with structures + # first so flattened tags may be used to override individual structure elements) + my @tagInfoList; + foreach $tagInfo (sort ByTagName $et->GetNewTagInfoList()) { + next unless $et->GetGroup($tagInfo, 0) eq 'XMP'; + next if $$tagInfo{Name} eq 'XMP'; # (ignore full XMP block if we didn't write it already) + if ($$tagInfo{Struct}) { + unshift @tagInfoList, $tagInfo; + } else { + push @tagInfoList, $tagInfo; + } + } + foreach $tagInfo (@tagInfoList) { + my $tag = $$tagInfo{TagID}; + my $path = GetPropertyPath($tagInfo); + unless ($path) { + $et->Warn("Can't write XMP:$tag (namespace unknown)"); + next; + } + # skip tags that were handled specially + if ($path eq 'rdf:about' or $path eq 'x:xmptk') { + ++$changed; + next; + } + my $isStruct = $$tagInfo{Struct}; + # change our property path namespace prefixes to conform + # to the ones used in this file + $path = ConformPathToNamespace($et, $path); + # find existing property + my $cap = $capture{$path}; + # MicrosoftPhoto screws up the case of some tags, and some other software, + # including Adobe software, has been known to write the wrong list type or + # not properly enclose properties in a list, so we check for this + until ($cap) { + # find and fix all incorrect property names if this is a structure or a flattened tag + my @fixInfo; + if ($isStruct or defined $$tagInfo{Flat}) { + # get tagInfo for all containing (possibly nested) structures + my @props = split '/', $path; + my $tbl = $$tagInfo{Table}; + while (@props) { + my $info = $$tbl{GetXMPTagID(\@props)}; + unshift @fixInfo, $info if ref $info eq 'HASH' and $$info{Struct} and + (not @fixInfo or $fixInfo[0] ne $info); + pop @props; + } + $et->WarnOnce("Error finding parent structure for $$tagInfo{Name}") unless @fixInfo; + } + # fix property path for this tag (last in the @fixInfo list) + push @fixInfo, $tagInfo unless @fixInfo and $isStruct; + # start from outermost containing structure, fixing incorrect list types, etc, + # finally fixing the actual tag properties after all containing structures + my $err; + while (@fixInfo) { + my $fixInfo = shift @fixInfo; + my $fixPath = ConformPathToNamespace($et, GetPropertyPath($fixInfo)); + my $regex = quotemeta($fixPath); + $regex =~ s/ \d+/ \\d\+/g; # match any list index + my $ok = $regex; + my ($ok2, $match, $i, @fixed, %fixed, $fixed); + # check for incorrect list types + if ($regex =~ s{\\/rdf\\:(Bag|Seq|Alt)\\/}{/rdf:(Bag|Seq|Alt)/}g) { + # also look for missing bottom-level list + if ($regex =~ s{/rdf:\(Bag\|Seq\|Alt\)\/rdf\\:li\\ \\d\+$}{}) { + $regex .= '(/.*)?' unless @fixInfo; + } + } elsif (not @fixInfo) { + $ok2 = $regex; + # check for properties in lists that shouldn't be (ref forum4325) + $regex .= '(/rdf:(Bag|Seq|Alt)/rdf:li \d+)?'; + } + if (@fixInfo) { + $regex .= '(/.*)?'; + $ok .= '(/.*)?'; + } + my @matches = sort grep m{^$regex$}i, keys %capture; + last unless @matches; + if ($matches[0] =~ m{^$ok$}) { + unless (@fixInfo) { + $path = $matches[0]; + $cap = $capture{$path}; + } + next; + } + # needs fixing... + my @fixProps = split '/', $fixPath; + foreach $match (@matches) { + my @matchProps = split '/', $match; + # remove superfluous list properties if necessary + $#matchProps = $#fixProps if $ok2 and $#matchProps > $#fixProps; + for ($i=0; $i<@fixProps; ++$i) { + defined $matchProps[$i] or $matchProps[$i] = $fixProps[$i], next; + next if $matchProps[$i] =~ / \d+$/ or $matchProps[$i] eq $fixProps[$i]; + $matchProps[$i] = $fixProps[$i]; + } + $fixed = join '/', @matchProps; + $err = 1 if $fixed{$fixed} or ($capture{$fixed} and $match ne $fixed); + push @fixed, $fixed; + $fixed{$fixed} = 1; + } + my $tg = $et->GetGroup($fixInfo, 1) . ':' . $$fixInfo{Name}; + my $wrn = lc($fixed[0]) eq lc($matches[0]) ? 'tag ID case' : 'list type'; + if ($err) { + $et->Warn("Incorrect $wrn for existing $tg (not changed)"); + } else { + # fix the incorrect property paths for all values of this tag + my $didFix; + foreach $fixed (@fixed) { + my $match = shift @matches; + next if $fixed eq $match; + $capture{$fixed} = $capture{$match}; + delete $capture{$match}; + # remove xml:lang attribute from incorrect lang-alt list if necessary + delete $capture{$fixed}[1]{'xml:lang'} if $ok2 and $match !~ /^$ok2$/; + $didFix = 1; + } + $cap = $capture{$path} || $capture{$fixed[0]} unless @fixInfo; + if ($didFix) { + $et->Warn("Fixed incorrect $wrn for $tg", 1); + ++$changed; + } + } + } + last; + } + my $nvHash = $et->GetNewValueHash($tagInfo); + my $overwrite = $et->IsOverwriting($nvHash); + my $writable = $$tagInfo{Writable} || ''; + my (%attrs, $deleted, $added, $existed); + # delete existing entry if necessary + if ($isStruct) { + # delete all structure (or pseudo-structure) elements + require 'Image/ExifTool/XMPStruct.pl'; + ($deleted, $added, $existed) = DeleteStruct($et, \%capture, \$path, $nvHash, \$changed); + next unless $deleted or $added or $et->IsOverwriting($nvHash); + next if $existed and $$nvHash{CreateOnly}; + } elsif ($cap) { + next if $$nvHash{CreateOnly}; # (necessary for List-type tags) + # take attributes from old values if they exist + %attrs = %{$$cap[1]}; + if ($overwrite) { + my ($delPath, $oldLang, $delLang, $addLang, @matchingPaths); + # check to see if this is an indexed list item + if ($path =~ / /) { + my $pp; + ($pp = $path) =~ s/ \d+/ \\d\+/g; + @matchingPaths = sort grep(/^$pp$/, keys %capture); + } else { + push @matchingPaths, $path; + } + foreach $path (@matchingPaths) { + my ($val, $attrs) = @{$capture{$path}}; + if ($writable eq 'lang-alt') { + unless (defined $addLang) { + # add to lang-alt list by default if creating this tag from scratch + $addLang = $$nvHash{IsCreating} ? 1 : 0; + } + # get original language code (lc for comparisons) + $oldLang = lc($$attrs{'xml:lang'} || 'x-default'); + if ($overwrite < 0) { + my $newLang = lc($$tagInfo{LangCode} || 'x-default'); + next unless $oldLang eq $newLang; + # only add new tag if we are overwriting this one + # (note: this won't match if original XML contains CDATA!) + $addLang = $et->IsOverwriting($nvHash, UnescapeXML($val)); + next unless $addLang; + } + # delete all if deleting "x-default" and writing with no LangCode + # (XMP spec requires x-default language exist and be first in list) + if ($oldLang eq 'x-default' and not $$tagInfo{LangCode}) { + $delLang = 1; # delete all languages + $overwrite = 1; # force overwrite + } elsif ($$tagInfo{LangCode} and not $delLang) { + # only overwrite specified language + next unless lc($$tagInfo{LangCode}) eq $oldLang; + } + } elsif ($overwrite < 0) { + # only overwrite specific values + if ($$nvHash{Shift}) { + # values to be shifted are checked (hence re-formatted) late, + # so we must un-format the to-be-shifted value for IsOverwriting() + my $fmt = $$tagInfo{Writable} || ''; + if ($fmt eq 'rational') { + ConvertRational($val); + } elsif ($fmt eq 'date') { + $val = ConvertXMPDate($val); + } + } + # (note: this won't match if original XML contains CDATA!) + next unless $et->IsOverwriting($nvHash, UnescapeXML($val)); + } + if ($verbose > 1) { + my $grp = $et->GetGroup($tagInfo, 1); + my $tagName = $$tagInfo{Name}; + $tagName =~ s/-$$tagInfo{LangCode}$// if $$tagInfo{LangCode}; + $tagName .= '-' . $$attrs{'xml:lang'} if $$attrs{'xml:lang'}; + $et->VerboseValue("- $grp:$tagName", $val); + } + # save attributes and path from first deleted property + # so we can replace it exactly + unless ($delPath) { + %attrs = %$attrs; + $delPath = $path; + } + # delete this tag + delete $capture{$path}; + ++$changed; + # delete rdf:type tag if it is the only thing left in this structure + if ($path =~ /^(.*)\// and $capture{"$1/rdf:type"}) { + my $pp = $1; + my @a = grep /^\Q$pp\E\/[^\/]+/, keys %capture; + delete $capture{"$pp/rdf:type"} if @a == 1; + } + } + next unless $delPath or $$tagInfo{List} or $addLang; + if ($delPath) { + $path = $delPath; + $deleted = 1; + } else { + # don't change tag if we couldn't delete old copy + # unless this is a list or an lang-alt tag + next unless $$tagInfo{List} or $oldLang; + # (match last index to put in same lang-alt list for Bag of lang-alt items) + $path =~ m/.* (\d+)/g or warn "Internal error: no list index!\n", next; + $added = $1; + } + } else { + # we are never overwriting, so we must be adding to a list + # match the last index unless this is a list of lang-alt lists + my $pat = $writable eq 'lang-alt' ? '.* (\d+)(.*? \d+)' : '.* (\d+)'; + if ($path =~ m/$pat/g) { + $added = $1; + # set position to end of matching index number + pos($path) = pos($path) - length($2) if $2; + } + } + if (defined $added) { + my $len = length $added; + my $pos = pos($path) - $len; + my $nxt = substr($added, 1) + 1; + # always insert x-default lang-alt entry first (as per XMP spec) + # (need to test $overwrite because this will be a new lang-alt entry otherwise) + if ($overwrite and $writable eq 'lang-alt' and (not $$tagInfo{LangCode} or + $$tagInfo{LangCode} eq 'x-default')) + { + my $saveCap = $capture{$path}; + for (;;) { + my $p = $path; + substr($p, $pos, $len) = length($nxt) . $nxt; + # increment index in the path of the existing item + my $nextCap = $capture{$p}; + $capture{$p} = $saveCap; + last unless $nextCap; + $saveCap = $nextCap; + ++$nxt; + } + } else { + # add to end of list + for (;;) { + my $try = length($nxt) . $nxt; + substr($path, $pos, $len) = $try; + last unless $capture{$path}; + $len = length $try; + ++$nxt; + } + } + } + } + # check to see if we want to create this tag + # (create non-avoided tags in XMP data files by default) + my $isCreating = ($$nvHash{IsCreating} or (($isStruct or + ($preferred and not $$tagInfo{Avoid} and + not defined $$nvHash{Shift})) and not $$nvHash{EditOnly})); + + # don't add new values unless... + # ...tag existed before and was deleted, or we added it to a list + next unless $deleted or defined $added or + # ...tag didn't exist before and we are creating it + (not $cap and $isCreating); + + # get list of new values (all done if no new values specified) + my @newValues = $et->GetNewValue($nvHash) or next; + + # set language attribute for lang-alt lists + $attrs{'xml:lang'} = $$tagInfo{LangCode} || 'x-default' if $writable eq 'lang-alt'; + + # add new value(s) to %capture hash + my $subIdx; + for (;;) { + my $newValue = shift @newValues; + if ($isStruct) { + ++$changed if AddNewStruct($et, $tagInfo, \%capture, + $path, $newValue, $$tagInfo{Struct}); + } else { + $newValue = EscapeXML($newValue); + for (;;) { # (a cheap 'goto') + if ($$tagInfo{Resource}) { + # only store as a resource if it doesn't contain any illegal characters + if ($newValue !~ /[^a-z0-9\:\/\?\#\[\]\@\!\$\&\'\(\)\*\+\,\;\=\.\-\_\~]/i) { + $capture{$path} = [ '', { %attrs, 'rdf:resource' => $newValue } ]; + last; + } + my $grp = $et->GetGroup($tagInfo, 1); + $et->Warn("$grp:$$tagInfo{Name} written as a literal because value is not a valid URI", 1); + # fall through to write as a string literal + } + delete $attrs{'rdf:resource'}; # (remove existing resource if necessary) + $capture{$path} = [ $newValue, \%attrs ]; + last; + } + if ($verbose > 1) { + my $grp = $et->GetGroup($tagInfo, 1); + $et->VerboseValue("+ $grp:$$tagInfo{Name}", $newValue); + } + ++$changed; + # add rdf:type if necessary + if ($$tagInfo{StructType}) { + AddStructType($et, $$tagInfo{Table}, \%capture, $path); + } + } + last unless @newValues; + # match last index except for lang-alt items where we want to put each + # item in a different lang-alt list (so match the 2nd-last for these) + my $pat = $writable eq 'lang-alt' ? '.* (\d+)(.*? \d+)' : '.* (\d+)'; + $path =~ m/$pat/g or warn("Internal error: no list index for $tag!\n"), next; + my $idx = $1; + my $len = length $1; + my $pos = pos($path) - $len - ($2 ? length $2 : 0); + # generate unique list sub-indices to store additional values in sequence + if ($subIdx) { + $idx = substr($idx, 0, -length($subIdx)); # remove old sub-index + $subIdx = substr($subIdx, 1) + 1; + $subIdx = length($subIdx) . $subIdx; + } else { + $subIdx = '10'; + } + substr($path, $pos, $len) = $idx . $subIdx; + } + # make sure any empty structures are deleted + # (ExifTool shouldn't write these, but other software may) + if (defined $$tagInfo{Flat}) { + my $p = $path; + while ($p =~ s/\/[^\/]+$//) { + next unless $capture{$p}; + # it is an error if this property has a value + $et->Error("Improperly structured XMP ($p)",1) if $capture{$p}[0] =~ /\S/; + delete $capture{$p}; # delete the (hopefully) empty structure + } + } + } + # remove the ExifTool members we created + delete $$et{XMP_CAPTURE}; + delete $$et{XMP_NS}; + + my $maxDataLen = $$dirInfo{MaxDataLen}; + # get DataPt again because it may have been set by ProcessXMP + $dataPt = $$dirInfo{DataPt}; + + # return now if we didn't change anything + unless ($changed or ($maxDataLen and $dataPt and defined $$dataPt and + length($$dataPt) > $maxDataLen)) + { + return undef unless $xmpFile; # just rewrite original XMP + Write($$dirInfo{OutFile}, $$dataPt) or return -1 if $dataPt and defined $$dataPt; + return 1; + } +# +# write out the new XMP information (serialize it) +# + # start writing the XMP data + my $useShorthand = $et->Options('XMPShorthand'); + my (@long, @short, @resFlag); + $long[0] = $long[1] = $short[0] = ''; + if ($$et{XMP_NO_XPACKET}) { + # write BOM if flag is set + $long[-2] .= "\xef\xbb\xbf" if $$et{XMP_NO_XPACKET} == 2; + } else { + $long[-2] .= $pktOpen; + } + $long[-2] .= $xmlOpen if $$et{XMP_IS_XML}; + $long[-2] .= $xmpOpen . $rdfOpen; + + # initialize current property path list + my (@curPropList, @writeLast, @descStart, $extStart); + my (%nsCur, $prop, $n, $path); + my @pathList = sort TypeFirst keys %capture; + # order properties to write large values last if we have a MaxDataLen limit + if ($maxDataLen and @pathList) { + my @pathTmp; + my ($lastProp, $lastNS, $propSize) = ('', '', 0); + my @pathLoop = (@pathList, ''); # add empty path to end of list for loop + undef @pathList; + foreach $path (@pathLoop) { + $path =~ /^((\w*)[^\/]*)/; # get path element ($1) and ns ($2) + if ($1 eq $lastProp) { + push @pathTmp, $path; # accumulate all paths with same root + } else { + # put in list to write last if recommended or values are too large + if ($extendedRes{$lastProp} or $extendedRes{$lastNS} or + $propSize > $newDescThresh) + { + push @writeLast, @pathTmp; + } else { + push @pathList, @pathTmp; + } + last unless $path; # all done if we hit empty path + @pathTmp = ( $path ); + ($lastProp, $lastNS, $propSize) = ($1, $2, 0); + } + $propSize += length $capture{$path}->[0]; + } + } + + # write out all properties + for (;;) { + my (%nsNew, $newDesc); + unless (@pathList) { + last unless @writeLast; + @pathList = @writeLast; + undef @writeLast; + $newDesc = 2; # start with a new description for the extended data + } + $path = shift @pathList; + my @propList = split('/',$path); # get property list + # must open/close rdf:Description too + unshift @propList, $rdfDesc; + # make sure we have defined all necessary namespaces + foreach $prop (@propList) { + $prop =~ /(.*):/ or next; + $1 eq 'rdf' and next; # rdf namespace already defined + my $uri = $nsUsed{$1}; + unless ($uri) { + $uri = $nsURI{$1}; # we must have added a namespace + $uri or $xmpErr = "Undefined XMP namespace: $1", next; + } + $nsNew{$1} = $uri; + # need a new description if any new namespaces + $newDesc = 1 unless $nsCur{$1}; + } + my $closeTo = 0; + if ($newDesc) { + # look forward to see if we will want to also open other namespaces + # at this level (this is necessary to keep lists and structures from + # being broken if a property introduces a new namespace; plus it + # improves formatting) + my ($path2, $ns2); + foreach $path2 (@pathList) { + my @ns2s = ($path2 =~ m{(?:^|/)([^/]+?):}g); + my $opening = 0; + foreach $ns2 (@ns2s) { + next if $ns2 eq 'rdf'; + $nsNew{$ns2} and ++$opening, next; + last unless $opening; + # get URI for this existing or new namespace + my $uri = $nsUsed{$ns2} || $nsURI{$ns2} or last; + $nsNew{$ns2} = $uri; # also open this namespace + } + last unless $opening; + } + } else { + # find first property where the current path differs from the new path + for ($closeTo=0; $closeTo<@curPropList; ++$closeTo) { + last unless $closeTo < @propList; + last unless $propList[$closeTo] eq $curPropList[$closeTo]; + } + } + # close out properties down to the common base path + CloseProperty(\@curPropList, \@long, \@short, \@resFlag) while @curPropList > $closeTo; + + # open new description if necessary + if ($newDesc) { + $extStart = length($long[-2]) if $newDesc == 2; # extended data starts after this + # save rdf:Description start positions so we can reorder them if necessary + push @descStart, length($long[-2]) if $maxDataLen; + # open the new description + $prop = $rdfDesc; + %nsCur = %nsNew; # save current namespaces + my $sp = $noPad ? '' : ' '; + my @ns = sort keys %nsCur; + $long[-2] .= "\n$sp<$prop rdf:about='${about}'"; + # generate et:toolkit attribute if this is an exiftool RDF/XML output file + if (@ns and $nsCur{$ns[0]} =~ m{^http://ns.exiftool.ca/}) { + $long[-2] .= "\n$sp${sp}xmlns:et='http://ns.exiftool.ca/1.0/'" . + " et:toolkit='Image::ExifTool $Image::ExifTool::VERSION'"; + } + $long[-2] .= "\n$sp${sp}xmlns:$_='$nsCur{$_}'" foreach @ns; + push @curPropList, $prop; + # set resFlag to 0 to indicate base description when XMPShorthand enabled + $resFlag[0] = 0 if $useShorthand; + } + my ($val, $attrs) = @{$capture{$path}}; + $debug and print "$path = $val\n"; + # open new properties if necessary + my ($attr, $dummy); + for ($n=@curPropList; $n<$#propList; ++$n) { + $prop = $propList[$n]; + push @curPropList, $prop; + $prop =~ s/ .*//; # remove list index if it exists + # (we may add parseType and shorthand properties later, + # so leave off the trailing ">" for now) + $long[-1] .= ($noPad ? '' : ' ' x scalar(@curPropList)) . "<$prop"; + if ($prop ne $rdfDesc and ($propList[$n+1] !~ /^rdf:/ or + ($propList[$n+1] eq 'rdf:type' and $n+1 == $#propList))) + { + # check for empty structure + if ($propList[$n+1] =~ /:~dummy~$/) { + $long[-1] .= " rdf:parseType='Resource'/>\n"; + pop @curPropList; + $dummy = 1; + last; + } + if ($useShorthand) { + $resFlag[$#curPropList] = 1; + push @long, ''; + push @short, ''; + } else { + # use rdf:parseType='Resource' to avoid new 'rdf:Description' + $long[-1] .= " rdf:parseType='Resource'>\n"; + } + } else { + $long[-1] .= ">\n"; # (will be no shorthand properties) + } + } + my $prop2 = pop @propList; # get new property name + # add element unless it was a dummy structure field + unless ($dummy or ($val eq '' and $prop2 =~ /:~dummy~$/)) { + $prop2 =~ s/ .*//; # remove list index if it exists + my $pad = $noPad ? '' : ' ' x (scalar(@curPropList) + 1); + # (can't write as shortcut if it has attributes or CDATA) + if (defined $resFlag[$#curPropList] and not %$attrs and $val !~ /<!\[CDATA\[/) { + $short[-1] .= "\n$pad$prop2='${val}'"; + } else { + $long[-1] .= "$pad<$prop2"; + # write out attributes + foreach $attr (sort keys %$attrs) { + my $attrVal = $$attrs{$attr}; + my $quot = ($attrVal =~ /'/) ? '"' : "'"; + $long[-1] .= " $attr=$quot$attrVal$quot"; + } + $long[-1] .= length $val ? ">$val</$prop2>\n" : "/>\n"; + } + } + } + # close out all open properties + CloseProperty(\@curPropList, \@long, \@short, \@resFlag) while @curPropList; + + # limit XMP length and re-arrange if necessary to fit inside specified size + if ($maxDataLen) { + # adjust maxDataLen to allow room for closing elements + $maxDataLen -= length($rdfClose) + length($xmpClose) + length($pktCloseW); + $extStart or $extStart = length $long[-2]; + my @rtn = LimitXMPSize($et, \$long[-2], $maxDataLen, $about, \@descStart, $extStart); + # return extended XMP information in $dirInfo + $$dirInfo{ExtendedXMP} = $rtn[0]; + $$dirInfo{ExtendedGUID} = $rtn[1]; + # compact if necessary to fit + $compact = 1 if length($long[-2]) + 101 * $numPadLines > $maxDataLen; + } + $compact = 1 if $$dirInfo{Compact}; +# +# close out the XMP, clean up, and return our data +# + $long[-2] .= $rdfClose; + $long[-2] .= $xmpClose unless $$et{XMP_NO_XMPMETA}; + + # remove the ExifTool members we created + delete $$et{XMP_CAPTURE}; + delete $$et{XMP_NS}; + delete $$et{XMP_NO_XMPMETA}; + + # (the XMP standard recommends writing 2k-4k of white space before the + # packet trailer, with a newline every 100 characters) + unless ($$et{XMP_NO_XPACKET}) { + my $pad = (' ' x 100) . "\n"; + # get current XMP length without padding + my $len = length($long[-2]) + length($pktCloseW); + if ($$dirInfo{InPlace} and not ($$dirInfo{InPlace} == 2 and $len > $dirLen)) { + # pad to specified DirLen + if ($len > $dirLen) { + my $str = 'Not enough room to edit XMP in place'; + $str .= '. Try XMPShorthand option' unless $$et{OPTIONS}{XMPShorthand}; + $et->Warn($str); + return undef; + } + my $num = int(($dirLen - $len) / length($pad)); + if ($num) { + $long[-2] .= $pad x $num; + $len += length($pad) * $num; + } + $len < $dirLen and $long[-2] .= (' ' x ($dirLen - $len - 1)) . "\n"; + } elsif (not $compact and not $xmpFile and not $$dirInfo{ReadOnly}) { + $long[-2] .= $pad x $numPadLines; + } + $long[-2] .= ($$dirInfo{ReadOnly} ? $pktCloseR : $pktCloseW); + } + # return empty data if no properties exist and this is allowed + unless (%capture or $xmpFile or $$dirInfo{InPlace} or $$dirInfo{NoDelete}) { + $long[-2] = ''; + } + if ($xmpErr) { + if ($xmpFile) { + $et->Error($xmpErr); + return -1; + } + $et->Warn($xmpErr); + return undef; + } + $$et{CHANGED} += $changed; + $debug > 1 and $long[-2] and print $long[-2],"\n"; + return $long[-2] unless $xmpFile; + Write($$dirInfo{OutFile}, $long[-2]) or return -1; + return 1; +} + + +1; # end + +__END__ + +=head1 NAME + +Image::ExifTool::WriteXMP.pl - Write XMP meta information + +=head1 SYNOPSIS + +These routines are autoloaded by Image::ExifTool::XMP. + +=head1 DESCRIPTION + +This file contains routines to write XMP metadata. + +=head1 AUTHOR + +Copyright 2003-2019, Phil Harvey (phil at owl.phy.queensu.ca) + +This library is free software; you can redistribute it and/or modify it +under the same terms as Perl itself. + +=head1 SEE ALSO + +L<Image::ExifTool::XMP(3pm)|Image::ExifTool::XMP>, +L<Image::ExifTool(3pm)|Image::ExifTool> + +=cut diff --git a/lib/Image/ExifTool/Writer.pl b/lib/Image/ExifTool/Writer.pl new file mode 100644 index 0000000..dba9d7b --- /dev/null +++ b/lib/Image/ExifTool/Writer.pl @@ -0,0 +1,6730 @@ +#------------------------------------------------------------------------------ +# File: Writer.pl +# +# Description: ExifTool write routines +# +# Notes: Also contains some less used ExifTool functions +# +# URL: http://owl.phy.queensu.ca/~phil/exiftool/ +# +# Revisions: 12/16/2004 - P. Harvey Created +#------------------------------------------------------------------------------ + +package Image::ExifTool; + +use strict; + +use Image::ExifTool::TagLookup qw(FindTagInfo TagExists); +use Image::ExifTool::Fixup; + +sub AssembleRational($$@); +sub LastInList($); +sub CreateDirectory($$); +sub NextFreeTagKey($$); +sub RemoveNewValueHash($$$); +sub RemoveNewValuesForGroup($$); +sub GetWriteGroup1($$); +sub Sanitize($$); +sub ConvInv($$$$$;$$); + +my $loadedAllTables; # flag indicating we loaded all tables +my $advFmtSelf; # ExifTool during evaluation of advanced formatting expr + +# the following is a road map of where we write each directory +# in the different types of files. +my %tiffMap = ( + IFD0 => 'TIFF', + IFD1 => 'IFD0', + XMP => 'IFD0', + ICC_Profile => 'IFD0', + ExifIFD => 'IFD0', + GPS => 'IFD0', + SubIFD => 'IFD0', + GlobParamIFD => 'IFD0', + PrintIM => 'IFD0', + IPTC => 'IFD0', + Photoshop => 'IFD0', + InteropIFD => 'ExifIFD', + MakerNotes => 'ExifIFD', + CanonVRD => 'MakerNotes', # (so VRDOffset will get updated) + NikonCapture => 'MakerNotes', # (to allow delete by group) +); +my %exifMap = ( + IFD1 => 'IFD0', + EXIF => 'IFD0', # to write EXIF as a block + ExifIFD => 'IFD0', + GPS => 'IFD0', + SubIFD => 'IFD0', + GlobParamIFD => 'IFD0', + PrintIM => 'IFD0', + InteropIFD => 'ExifIFD', + MakerNotes => 'ExifIFD', + NikonCapture => 'MakerNotes', # (to allow delete by group) + # (no CanonVRD trailer allowed) +); +my %jpegMap = ( + %exifMap, # covers all JPEG EXIF mappings + JFIF => 'APP0', + CIFF => 'APP0', + IFD0 => 'APP1', + XMP => 'APP1', + ICC_Profile => 'APP2', + FlashPix => 'APP2', + MPF => 'APP2', + Meta => 'APP3', + MetaIFD => 'Meta', + RMETA => 'APP5', + Ducky => 'APP12', + Photoshop => 'APP13', + Adobe => 'APP14', + IPTC => 'Photoshop', + MakerNotes => ['ExifIFD', 'CIFF'], # (first parent is the default) + CanonVRD => 'MakerNotes', # (so VRDOffset will get updated) + NikonCapture => 'MakerNotes', # (to allow delete by group) + Comment => 'COM', +); +my %dirMap = ( + JPEG => \%jpegMap, + EXV => \%jpegMap, + TIFF => \%tiffMap, + ORF => \%tiffMap, + RAW => \%tiffMap, + EXIF => \%exifMap, +); + +# module names and write functions for each writable file type +# (defaults to "$type" and "Process$type" if not defined) +# - types that are handled specially will not appear in this list +my %writableType = ( + CRW => [ 'CanonRaw', 'WriteCRW' ], + DR4 => 'CanonVRD', + EPS => [ 'PostScript', 'WritePS' ], + FLIF=> [ undef, 'WriteFLIF'], + GIF => undef, + ICC => [ 'ICC_Profile', 'WriteICC' ], + IND => 'InDesign', + JP2 => 'Jpeg2000', + MIE => undef, + MOV => [ 'QuickTime', 'WriteMOV' ], + MRW => 'MinoltaRaw', + PDF => [ undef, 'WritePDF' ], + PNG => undef, + PPM => undef, + PS => [ 'PostScript', 'WritePS' ], + PSD => 'Photoshop', + RAF => [ 'FujiFilm', 'WriteRAF' ], + VRD => 'CanonVRD', + X3F => 'SigmaRaw', + XMP => [ undef, 'WriteXMP' ], +); + +# groups we are allowed to delete +# Notes: +# 1) these names must either exist in %dirMap, or be translated in InitWriteDirs()) +# 2) any dependencies must be added to %excludeGroups +my @delGroups = qw( + Adobe AFCP APP0 APP1 APP2 APP3 APP4 APP5 APP6 APP7 APP8 APP9 APP10 APP11 APP12 + APP13 APP14 APP15 CanonVRD CIFF Ducky EXIF ExifIFD File FlashPix FotoStation + GlobParamIFD GPS ICC_Profile IFD0 IFD1 InteropIFD IPTC JFIF Jpeg2000 MakerNotes + Meta MetaIFD MIE MPF NikonCapture PDF PDF-update PhotoMechanic Photoshop PNG + PNG-pHYs PrintIM RMETA RSRC SubIFD Trailer XML XML-* XMP XMP-* +); +# family 2 group names that we can delete +my @delGroup2 = qw( + Audio Author Camera Document ExifTool Image Location Other Preview Printing + Time Video +); + +# lookup for all valid family 2 groups (lower case) +my %family2groups = map { lc $_ => 1 } @delGroup2, 'Unknown'; + +# groups we don't delete when deleting all information +my $protectedGroups = '(IFD1|SubIFD|InteropIFD|GlobParamIFD|PDF-update|Adobe)'; + +# other group names of new tag values to remove when deleting an entire group +my %removeGroups = ( + IFD0 => [ 'EXIF', 'MakerNotes' ], + EXIF => [ 'MakerNotes' ], + ExifIFD => [ 'MakerNotes', 'InteropIFD' ], + Trailer => [ 'CanonVRD' ], #(because we can add back CanonVRD as a block) +); +# related family 0/1 groups in @delGroups (and not already in %jpegMap) +# that must be removed from delete list when excluding a group +my %excludeGroups = ( + EXIF => [ qw(IFD0 IFD1 ExifIFD GPS MakerNotes GlobParamIFD InteropIFD PrintIM SubIFD) ], + IFD0 => [ 'EXIF' ], + IFD1 => [ 'EXIF' ], + ExifIFD => [ 'EXIF' ], + GPS => [ 'EXIF' ], + MakerNotes => [ 'EXIF' ], + InteropIFD => [ 'EXIF' ], + GlobParamIFD => [ 'EXIF' ], + PrintIM => [ 'EXIF' ], + CIFF => [ 'MakerNotes' ], + # technically correct, but very uncommon and not a good reason to avoid deleting trailer + # IPTC => [ qw(AFCP FotoStation Trailer) ], + AFCP => [ 'Trailer' ], + FotoStation => [ 'Trailer' ], + CanonVRD => [ 'Trailer' ], + PhotoMechanic=> [ 'Trailer' ], + MIE => [ 'Trailer' ], +); +# translate (lower case) wanted group when writing for tags where group name may change +my %translateWantGroup = ( + ciff => 'canonraw', +); +# group names to translate for writing +my %translateWriteGroup = ( + EXIF => 'ExifIFD', + Meta => 'MetaIFD', + File => 'Comment', + # any entry in this table causes the write group to be set from the + # tag information instead of whatever the user specified... + MIE => 'MIE', + APP14 => 'APP14', +); +# names of valid EXIF and Meta directories (lower case keys): +my %exifDirs = ( + gps => 'GPS', + exififd => 'ExifIFD', + subifd => 'SubIFD', + globparamifd => 'GlobParamIFD', + interopifd => 'InteropIFD', + previewifd => 'PreviewIFD', # (in MakerNotes) + metaifd => 'MetaIFD', # Kodak APP3 Meta + makernotes => 'MakerNotes', +); +# valid family 0 groups when WriteGroup is set to "All" +my %allFam0 = ( + exif => 1, + makernotes => 1, +); + +my @writableMacOSTags = qw( + FileCreateDate MDItemFinderComment MDItemFSCreationDate MDItemFSLabel MDItemUserTags + XAttrQuarantine +); + +# min/max values for integer formats +my %intRange = ( + 'int8u' => [0, 0xff], + 'int8s' => [-0x80, 0x7f], + 'int16u' => [0, 0xffff], + 'int16uRev' => [0, 0xffff], + 'int16s' => [-0x8000, 0x7fff], + 'int32u' => [0, 0xffffffff], + 'int32s' => [-0x80000000, 0x7fffffff], + 'int64u' => [0, 18446744073709551615], + 'int64s' => [-9223372036854775808, 9223372036854775807], +); +# lookup for file types with block-writable EXIF +my %blockExifTypes = map { $_ => 1 } qw(JPEG PNG JP2 MIE EXIF FLIF); + +my $maxSegmentLen = 0xfffd; # maximum length of data in a JPEG segment +my $maxXMPLen = $maxSegmentLen; # maximum length of XMP data in JPEG + +# value separators when conversion list is used (in SetNewValue) +my %listSep = ( PrintConv => '; ?', ValueConv => ' ' ); + +# printConv hash keys to ignore when doing reverse lookup +my %ignorePrintConv = map { $_ => 1 } qw(OTHER BITMASK Notes); + +#------------------------------------------------------------------------------ +# Set tag value +# Inputs: 0) ExifTool object reference +# 1) tag key, tag name, or '*' (optionally prefixed by group name), +# or undef to reset all previous SetNewValue() calls +# 2) new value (scalar, scalar ref or list ref), or undef to delete tag +# 3-N) Options: +# Type => PrintConv, ValueConv or Raw - specifies value type +# AddValue => true to add to list of existing values instead of overwriting +# DelValue => true to delete this existing value value from a list, or +# or doing a conditional delete, or to shift a time value +# Group => family 0 or 1 group name (case insensitive) +# Replace => 0, 1 or 2 - overwrite previous new values (2=reset) +# Protected => bitmask to write tags with specified protections +# EditOnly => true to only edit existing tags (don't create new tag) +# EditGroup => true to only edit existing groups (don't create new group) +# Shift => undef, 0, +1 or -1 - shift value if possible +# NoFlat => treat flattened tags as 'unsafe' +# NoShortcut => true to prevent looking up shortcut tags +# ProtectSaved => protect existing new values with a save count greater than this +# CreateGroups => [internal use] createGroups hash ref from related tags +# ListOnly => [internal use] set only list or non-list tags +# SetTags => [internal use] hash ref to return tagInfo refs of set tags +# Sanitized => [internal use] set to avoid double-sanitizing the value +# Returns: number of tags set (plus error string in list context) +# Notes: For tag lists (like Keywords), call repeatedly with the same tag name for +# each value in the list. Internally, the new information is stored in +# the following members of the $$self{NEW_VALUE}{$tagInfo} hash: +# TagInfo - tag info ref +# DelValue - list ref for values to delete +# Value - list ref for values to add (not defined if deleting the tag) +# IsCreating - must be set for the tag to be added for the standard file types, +# otherwise just changed if it already exists. This may be +# overridden for file types with a PREFERRED metadata type. +# Set to 2 to create inidividual tags but not new groups +# EditOnly - flag set if tag should never be created (regardless of file type). +# If this is set, then IsCreating must be false +# CreateOnly - flag set if creating only (never edit existing tag) +# CreateGroups - hash of all family 0 group names where tag may be created +# WriteGroup - group name where information is being written (correct case) +# WantGroup - group name as specified in call to function (case insensitive) +# Next - pointer to next new value hash (if more than one) +# NoReplace - set if value was created with Replace=0 +# AddBefore - number of list items added by a subsequent Replace=0 call +# IsNVH - Flag indicating this is a new value hash +# Shift - shift value +# Save - counter used by SaveNewValues()/RestoreNewValues() +# MAKER_NOTE_FIXUP - pointer to fixup if necessary for a maker note value +sub SetNewValue($;$$%) +{ + local $_; + my ($self, $tag, $value, %options) = @_; + my ($err, $tagInfo, $family); + my $verbose = $$self{OPTIONS}{Verbose}; + my $out = $$self{OPTIONS}{TextOut}; + my $protected = $options{Protected} || 0; + my $listOnly = $options{ListOnly}; + my $setTags = $options{SetTags}; + my $noFlat = $options{NoFlat}; + my $numSet = 0; + + unless (defined $tag) { + delete $$self{NEW_VALUE}; + $$self{SAVE_COUNT} = 0; + $$self{DEL_GROUP} = { }; + return 1; + } + # allow value to be scalar or list reference + if (ref $value) { + if (ref $value eq 'ARRAY') { + # value is an ARRAY so it may have more than one entry + # - set values both separately and as a combined string if there are more than one + if (@$value > 1) { + # set all list-type tags first + my $replace = $options{Replace}; + my $noJoin; + foreach (@$value) { + $noJoin = 1 if ref $_; + my ($n, $e) = SetNewValue($self, $tag, $_, %options, ListOnly => 1); + $err = $e if $e; + $numSet += $n; + delete $options{Replace}; # don't replace earlier values in list + } + return $numSet if $noJoin; # don't join if list contains objects + # and now set only non-list tags + $value = join $$self{OPTIONS}{ListSep}, @$value; + $options{Replace} = $replace; + $listOnly = $options{ListOnly} = 0; + } else { + $value = $$value[0]; + $value = $$value if ref $value eq 'SCALAR'; # (handle single scalar ref in a list) + } + } elsif (ref $value eq 'SCALAR') { + $value = $$value; + } + } + # un-escape as necessary and make sure the Perl UTF-8 flag is OFF for the value + # if perl is 5.6 or greater (otherwise our byte manipulations get corrupted!!) + $self->Sanitize(\$value) if defined $value and not ref $value and not $options{Sanitized}; + + # set group name in options if specified + ($options{Group}, $tag) = ($1, $2) if $tag =~ /(.*):(.+)/; + + # allow trailing '#' for ValueConv value + $options{Type} = 'ValueConv' if $tag =~ s/#$//; + my $convType = $options{Type} || ($$self{OPTIONS}{PrintConv} ? 'PrintConv' : 'ValueConv'); + + my (@wantGroup, $family2); + my $wantGroup = $options{Group}; + if ($wantGroup) { + foreach (split /:/, $wantGroup) { + next unless length($_) and /^(\d+)?(.*)/; # separate family number and group name + my ($f, $g) = ($1, lc $2); + # save group/family unless '*' or 'all' + push @wantGroup, [ $f, $g ] unless $g eq '*' or $g eq 'all'; + if (defined $f) { + $f > 2 and return 0; # only allow family 0, 1 or 2 + $family2 = 1 if $f == 2; # set flag indicating family 2 was used + } else { + $family2 = 1 if $family2groups{$g}; + } + } + undef $wantGroup unless @wantGroup; + } + + $tag =~ s/ .*//; # convert from tag key to tag name if necessary + $tag = '*' if lc($tag) eq 'all'; # use '*' instead of 'all' +# +# handle group delete +# + while ($tag eq '*' and not defined $value and not $family2 and @wantGroup < 2) { + # set groups to delete + my (@del, $grp); + my $remove = ($options{Replace} and $options{Replace} > 1); + if ($wantGroup) { + @del = grep /^$wantGroup$/i, @delGroups unless $wantGroup =~ /^XM[LP]-\*$/i; + # remove associated groups when excluding from mass delete + if (@del and $remove) { + # remove associated groups in other family + push @del, @{$excludeGroups{$del[0]}} if $excludeGroups{$del[0]}; + # remove upstream groups according to JPEG map + my $dirName = $del[0]; + my @dirNames; + for (;;) { + my $parent = $jpegMap{$dirName}; + if (ref $parent) { + push @dirNames, @$parent; + $parent = pop @dirNames; + } + $dirName = $parent || shift @dirNames or last; + push @del, $dirName; # exclude this too + } + } + # allow MIE groups to be deleted by number, + # and allow any XMP family 1 group to be deleted + push @del, uc($wantGroup) if $wantGroup =~ /^(MIE\d+|XM[LP]-[-\w]*\w)$/i; + } else { + # push all groups plus '*', except the protected groups + push @del, (grep !/^$protectedGroups$/, @delGroups), '*'; + } + if (@del) { + ++$numSet; + my @donegrps; + my $delGroup = $$self{DEL_GROUP}; + foreach $grp (@del) { + if ($remove) { + my $didExcl; + if ($grp =~ /^(XM[LP])(-.*)?$/) { + my $x = $1; + if ($grp eq $x) { + # exclude all related family 1 groups too + foreach (keys %$delGroup) { + next unless /^(-?)$x-/; + push @donegrps, $_ unless $1; + delete $$delGroup{$_}; + } + } elsif ($$delGroup{"$x-*"} and not $$delGroup{"-$grp"}) { + # must also exclude XMP or XML to prevent bulk delete + if ($$delGroup{$x}) { + push @donegrps, $x; + delete $$delGroup{$x}; + } + # flag XMP/XML family 1 group for exclusion with leading '-' + $$delGroup{"-$grp"} = 1; + $didExcl = 1; + } + } + if (exists $$delGroup{$grp}) { + delete $$delGroup{$grp}; + } else { + next unless $didExcl; + } + } else { + $$delGroup{$grp} = 1; + # add flag for XMP/XML family 1 groups if deleting all XMP + if ($grp =~ /^XM[LP]$/) { + $$delGroup{"$grp-*"} = 1; + push @donegrps, "$grp-*"; + } + # remove all of this group from previous new values + $self->RemoveNewValuesForGroup($grp); + } + push @donegrps, $grp; + } + if ($verbose > 1 and @donegrps) { + @donegrps = sort @donegrps; + my $msg = $remove ? 'Excluding from deletion' : 'Deleting tags in'; + print $out " $msg: @donegrps\n"; + } + } elsif (grep /^$wantGroup$/i, @delGroup2) { + last; # allow tags to be deleted by group2 name + } else { + $err = "Not a deletable group: $wantGroup"; + } + # all done + return ($numSet, $err) if wantarray; + $err and warn "$err\n"; + return $numSet; + } + + # initialize write/create flags + my $createOnly; + my $editOnly = $options{EditOnly}; + my $editGroup = $options{EditGroup}; + my $writeMode = $$self{OPTIONS}{WriteMode}; + if ($writeMode ne 'wcg') { + $createOnly = 1 if $writeMode !~ /w/i; # don't write existing tags + if ($writeMode !~ /c/i) { + return 0 if $createOnly; # nothing to do unless writing existing tags + $editOnly = 1; # don't create new tags + } elsif ($writeMode !~ /g/i) { + $editGroup = 1; # don't create new groups + } + } + my ($ifdName, $mieGroup, $movGroup, $fg); + # set family 1 group names + foreach $fg (@wantGroup) { + next if defined $$fg[0] and $$fg[0] != 1; + $_ = $$fg[1]; + # set $ifdName if this group is a valid IFD or SubIFD name + my $grpName; + if (/^IFD(\d+)$/i) { + $grpName = $ifdName = "IFD$1"; + } elsif (/^SubIFD(\d+)$/i) { + $grpName = $ifdName = "SubIFD$1"; + } elsif (/^Version(\d+)$/i) { + $grpName = $ifdName = "Version$1"; # Sony IDC VersionIFD + } elsif ($exifDirs{$_}) { + $grpName = $exifDirs{$_}; + $ifdName = $grpName unless $ifdName and $allFam0{$_}; + } elsif ($allFam0{$_}) { + $grpName = $allFam0{$_}; + } elsif (/^Track(\d+)$/i) { + $grpName = $movGroup = "Track$1"; # QuickTime track + } elsif (/^MIE(\d*-?)(\w+)$/i) { + $grpName = $mieGroup = "MIE$1" . ucfirst(lc($2)); + } elsif (not $ifdName and /^XMP\b/i) { + # must load XMP table to set group1 names + my $table = GetTagTable('Image::ExifTool::XMP::Main'); + my $writeProc = $$table{WRITE_PROC}; + $writeProc and &$writeProc(); + } + # fix case for known groups + $wantGroup =~ s/$grpName/$grpName/i if $grpName and $grpName ne $_; + } +# +# get list of tags we want to set +# + my $origTag = $tag; + my @matchingTags = FindTagInfo($tag); + until (@matchingTags) { + my $langCode; + # allow language suffix of form "-en_CA" or "-<rfc3066>" on tag name + if ($tag =~ /^([?*\w]+)-([a-z]{2})(_[a-z]{2})$/i or # MIE + $tag =~ /^([?*\w]+)-([a-z]{2,3}|[xi])(-[a-z\d]{2,8}(-[a-z\d]{1,8})*)?$/i) # XMP/PNG + { + $tag = $1; + # normalize case of language codes + $langCode = lc($2); + $langCode .= (length($3) == 3 ? uc($3) : lc($3)) if $3; + my @newMatches = FindTagInfo($tag); + foreach $tagInfo (@newMatches) { + # only allow language codes in tables which support them + next unless $$tagInfo{Table}; + my $langInfoProc = $$tagInfo{Table}{LANG_INFO} or next; + my $langInfo = &$langInfoProc($tagInfo, $langCode); + push @matchingTags, $langInfo if $langInfo; + } + last if @matchingTags; + } elsif (not $options{NoShortcut}) { + # look for a shortcut or alias + require Image::ExifTool::Shortcuts; + my ($match) = grep /^\Q$tag\E$/i, keys %Image::ExifTool::Shortcuts::Main; + undef $err; + if ($match) { + $options{NoShortcut} = $options{Sanitized} = 1; + foreach $tag (@{$Image::ExifTool::Shortcuts::Main{$match}}) { + my ($n, $e) = $self->SetNewValue($tag, $value, %options); + $numSet += $n; + $e and $err = $e; + } + undef $err if $numSet; # no error if any set successfully + return ($numSet, $err) if wantarray; + $err and warn "$err\n"; + return $numSet; + } + } + unless ($listOnly) { + if (not TagExists($tag)) { + if ($tag =~ /^[-\w*?]+$/) { + my $pre = $wantGroup ? $wantGroup . ':' : ''; + $err = "Tag '$pre${origTag}' is not defined"; + $err .= ' or has a bad language code' if $origTag =~ /-/; + } else { + $err = "Invalid tag name '${tag}'"; + $err .= " (remove the leading '\$')" if $tag =~ /^\$/; + } + } elsif ($langCode) { + $err = "Tag '${tag}' does not support alternate languages"; + } elsif ($wantGroup) { + $err = "Sorry, $wantGroup:$origTag doesn't exist or isn't writable"; + } else { + $err = "Sorry, $origTag is not writable"; + } + $verbose > 2 and print $out "$err\n"; + } + # all done + return ($numSet, $err) if wantarray; + $err and warn "$err\n"; + return $numSet; + } + # get group name that we're looking for + my $foundMatch = 0; +# +# determine the groups for all tags found, and the tag with +# the highest priority group +# + my (@tagInfoList, @writeAlsoList, %writeGroup, %preferred, %tagPriority); + my (%avoid, $wasProtected, $noCreate, %highestPriority); + +TAG: foreach $tagInfo (@matchingTags) { + $tag = $$tagInfo{Name}; # get tag name for warnings + my $lcTag = lc $tag; # get lower-case tag name for use in variables + # initialize highest priority if we are starting a new tag + $highestPriority{$lcTag} = -999 unless defined $highestPriority{$lcTag}; + my ($priority, $writeGroup); + if ($wantGroup) { + # a WriteGroup of All is special + my $wgAll = ($$tagInfo{WriteGroup} and $$tagInfo{WriteGroup} eq 'All'); + my @grp = $self->GetGroup($tagInfo); + foreach $fg (@wantGroup) { + my ($fam, $lcWant) = @$fg; + $lcWant = $translateWantGroup{$lcWant} if $translateWantGroup{$lcWant}; + # only set tag in specified group + if (not defined $fam) { + if ($lcWant eq lc $grp[0]) { + # don't go to more generate write group of "All" + # if something more specific was wanted + $writeGroup = $grp[0] if $wgAll and not $writeGroup; + next; + } + next if $lcWant eq lc $grp[2]; + } elsif ($fam != 1 and not $$tagInfo{AllowGroup}) { + next if $lcWant eq lc $grp[$fam]; + if ($wgAll and not $fam and $allFam0{$lcWant}) { + $writeGroup or $writeGroup = $allFam0{$lcWant}; + next; + } + next TAG; # wrong group + } + # handle family 1 groups specially + if ($grp[0] eq 'EXIF' or $grp[0] eq 'SonyIDC' or $wgAll) { + unless ($ifdName and $lcWant eq lc $ifdName) { + next TAG unless $wgAll and not $fam and $allFam0{$lcWant}; + $writeGroup = $allFam0{$lcWant} unless $writeGroup; + next; + } + next TAG if $wgAll and $allFam0{$lcWant} and $fam; + # can't yet write PreviewIFD tags (except for image) + $lcWant eq 'PreviewIFD' and ++$foundMatch, next TAG; + $writeGroup = $ifdName; # write to the specified IFD + } elsif ($grp[0] eq 'QuickTime' and $grp[1] eq 'Track#') { + next TAG unless $movGroup and $lcWant eq lc($movGroup); + $writeGroup = $movGroup; + } elsif ($grp[0] eq 'MIE') { + next TAG unless $mieGroup and $lcWant eq lc($mieGroup); + $writeGroup = $mieGroup; # write to specific MIE group + # set specific write group with document number if specified + if ($writeGroup =~ /^MIE\d+$/ and $$tagInfo{Table}{WRITE_GROUP}) { + $writeGroup = $$tagInfo{Table}{WRITE_GROUP}; + $writeGroup =~ s/^MIE/$mieGroup/; + } + } elsif (not $$tagInfo{AllowGroup} or $lcWant !~ /^$$tagInfo{AllowGroup}$/i) { + # allow group1 name to be specified + next TAG unless $lcWant eq lc $grp[1]; + } + } + $writeGroup or $writeGroup = ($$tagInfo{WriteGroup} || $grp[0]); + $priority = 1000; # highest priority since group was specified + } + ++$foundMatch; + # must do a dummy call to the write proc to autoload write package + # before checking Writable flag + my $table = $$tagInfo{Table}; + my $writeProc = $$table{WRITE_PROC}; + # load source table if this was a user-defined table + if ($$table{SRC_TABLE}) { + my $src = GetTagTable($$table{SRC_TABLE}); + $writeProc = $$src{WRITE_PROC} unless $writeProc; + } + next unless $writeProc and &$writeProc(); + # must still check writable flags in case of UserDefined tags + my $writable = $$tagInfo{Writable}; + next unless $writable or ($$table{WRITABLE} and + not defined $writable and not $$tagInfo{SubDirectory}); + # set specific write group (if we didn't already) + if (not $writeGroup or ($translateWriteGroup{$writeGroup} and + (not $$tagInfo{WriteGroup} or $$tagInfo{WriteGroup} ne 'All'))) + { + # use default write group + $writeGroup = $$tagInfo{WriteGroup} || $$tagInfo{Table}{WRITE_GROUP}; + # use group 0 name if no WriteGroup specified + my $group0 = $self->GetGroup($tagInfo, 0); + $writeGroup or $writeGroup = $group0; + # get priority for this group + unless ($priority) { + $priority = $$self{WRITE_PRIORITY}{lc($writeGroup)}; + unless ($priority) { + $priority = $$self{WRITE_PRIORITY}{lc($group0)} || 0; + } + } + } + # don't write tag if protected + my $prot = $$tagInfo{Protected}; + $prot = 1 if $noFlat and defined $$tagInfo{Flat}; + if ($prot) { + $prot &= ~$protected; + if ($prot) { + my %lkup = ( 1=>'unsafe', 2=>'protected', 3=>'unsafe and protected'); + $wasProtected = $lkup{$prot}; + if ($verbose > 1) { + my $wgrp1 = $self->GetWriteGroup1($tagInfo, $writeGroup); + print $out "Sorry, $wgrp1:$tag is $wasProtected for writing\n"; + } + next; + } + } + # set priority for this tag + $tagPriority{$tagInfo} = $priority; + if ($priority > $highestPriority{$lcTag}) { + $highestPriority{$lcTag} = $priority; + $preferred{$lcTag} = { $tagInfo => 1 }; + $avoid{$lcTag} = $$tagInfo{Avoid} ? 1 : 0; + } elsif ($priority == $highestPriority{$lcTag}) { + # create all tags with highest priority + $preferred{$lcTag}{$tagInfo} = 1; + ++$avoid{$lcTag} if $$tagInfo{Avoid}; + } + if ($$tagInfo{WriteAlso}) { + # store WriteAlso tags separately so we can set them first + push @writeAlsoList, $tagInfo; + } else { + push @tagInfoList, $tagInfo; + } + $writeGroup{$tagInfo} = $writeGroup; + } + # sort tag info list in reverse order of priority (higest number last) + # so we get the highest priority error message in the end + @tagInfoList = sort { $tagPriority{$a} <=> $tagPriority{$b} } @tagInfoList; + # must write any tags which also write other tags first + unshift @tagInfoList, @writeAlsoList if @writeAlsoList; + + # check priorities for each set of tags we are writing + my $lcTag; + foreach $lcTag (keys %preferred) { + # don't create tags with priority 0 if group priorities are set + if ($preferred{$lcTag} and $highestPriority{$lcTag} == 0 and + %{$$self{WRITE_PRIORITY}}) + { + delete $preferred{$lcTag} + } + # avoid creating tags with 'Avoid' flag set if there are other alternatives + if ($avoid{$lcTag} and $preferred{$lcTag}) { + if ($avoid{$lcTag} < scalar(keys %{$preferred{$lcTag}})) { + # just remove the 'Avoid' tags since there are other preferred tags + foreach $tagInfo (@tagInfoList) { + next unless $lcTag eq lc $$tagInfo{Name}; + delete $preferred{$lcTag}{$tagInfo} if $$tagInfo{Avoid}; + } + } elsif ($highestPriority{$lcTag} < 1000) { + # look for another priority tag to create instead + my $nextHighest = 0; + my @nextBestTags; + foreach $tagInfo (@tagInfoList) { + next unless $lcTag eq lc $$tagInfo{Name}; + my $priority = $tagPriority{$tagInfo} or next; + next if $priority == $highestPriority{$lcTag}; + next if $priority < $nextHighest; + next if $$tagInfo{Avoid} or $$tagInfo{Permanent}; + next if $writeGroup{$tagInfo} eq 'MakerNotes'; + if ($nextHighest < $priority) { + $nextHighest = $priority; + undef @nextBestTags; + } + push @nextBestTags, $tagInfo; + } + if (@nextBestTags) { + # change our preferred tags to the next best tags + delete $preferred{$lcTag}; + foreach $tagInfo (@nextBestTags) { + $preferred{$lcTag}{$tagInfo} = 1; + } + } + } + } + } +# +# generate new value hash for each tag +# + my ($prioritySet, $createGroups, %alsoWrote); + + delete $$self{CHECK_WARN}; # reset CHECK_PROC warnings + + # loop through all valid tags to find the one(s) to write + foreach $tagInfo (@tagInfoList) { + next if $alsoWrote{$tagInfo}; # don't rewrite tags we already wrote + # only process List or non-List tags if specified + next if defined $listOnly and ($listOnly xor $$tagInfo{List}); + my $noConv; + my $writeGroup = $writeGroup{$tagInfo}; + my $permanent = $$tagInfo{Permanent}; + $writeGroup eq 'MakerNotes' and $permanent = 1 unless defined $permanent; + my $wgrp1 = $self->GetWriteGroup1($tagInfo, $writeGroup); + $tag = $$tagInfo{Name}; # get tag name for warnings + my $pref = $preferred{lc $tag} || { }; + my $shift = $options{Shift}; + my $addValue = $options{AddValue}; + if (defined $shift) { + # (can't currently shift list-type tags) + my $shiftable; + if ($$tagInfo{List}) { + $shiftable = ''; # can add/delete but not shift + } else { + $shiftable = $$tagInfo{Shift}; + unless ($shift) { + # set shift according to AddValue/DelValue + $shift = 1 if $addValue; + # can shift a date/time with -=, but this is + # a conditional delete operation for other tags + $shift = -1 if $options{DelValue} and defined $shiftable and $shiftable eq 'Time'; + } + if ($shift and (not defined $value or not length $value)) { + # (now allow -= to be used for shiftable tag - v8.05) + #$err = "No value for time shift of $wgrp1:$tag"; + #$verbose > 2 and print $out "$err\n"; + #next; + undef $shift; + } + } + # can't shift List-type tag + if ((defined $shiftable and not $shiftable) and + # and don't try to conditionally delete if Shift is "0" + ($shift or ($shiftable eq '0' and $options{DelValue}))) + { + $err = "$wgrp1:$tag is not shiftable"; + $verbose > 2 and print $out "$err\n"; + next; + } + } + my $val = $value; + if (defined $val) { + # check to make sure this is a List or Shift tag if adding + if ($addValue and not ($shift or $$tagInfo{List})) { + if ($addValue eq '2') { + undef $addValue; # quitely reset this option + } else { + $err = "Can't add $wgrp1:$tag (not a List type)"; + $verbose > 2 and print $out "$err\n"; + next; + } + } + if ($shift) { + if ($$tagInfo{Shift} and $$tagInfo{Shift} eq 'Time') { + # add '+' or '-' prefix to indicate shift direction + $val = ($shift > 0 ? '+' : '-') . $val; + # check the shift for validity + require 'Image/ExifTool/Shift.pl'; + my $err2 = CheckShift($$tagInfo{Shift}, $val); + if ($err2) { + $err = "$err2 for $wgrp1:$tag"; + $verbose > 2 and print $out "$err\n"; + next; + } + } elsif (IsFloat($val)) { + $val *= $shift; + } else { + $err = "Shift value for $wgrp1:$tag is not a number"; + $verbose > 2 and print $out "$err\n"; + next; + } + $noConv = 1; # no conversions if shifting tag + } elsif (not length $val and $options{DelValue}) { + $noConv = 1; # no conversions for deleting empty value + } elsif (ref $val eq 'HASH' and not $$tagInfo{Struct}) { + $err = "Can't write a structure to $wgrp1:$tag"; + $verbose > 2 and print $out "$err\n"; + next; + } + } elsif ($permanent) { + # can't delete permanent tags, so set them to DelValue or empty string instead + if (defined $$tagInfo{DelValue}) { + $val = $$tagInfo{DelValue}; + $noConv = 1; # DelValue is the raw value, so no conversion necessary + } else { + $val = ''; + } + } elsif ($addValue or $options{DelValue}) { + $err = "No value to add or delete in $wgrp1:$tag"; + $verbose > 2 and print $out "$err\n"; + next; + } else { + if ($$tagInfo{DelCheck}) { + #### eval DelCheck ($self, $tagInfo, $wantGroup) + my $err2 = eval $$tagInfo{DelCheck}; + $@ and warn($@), $err2 = 'Error evaluating DelCheck'; + if (defined $err2) { + # (allow other tags to be set using DelCheck as a hook) + $err2 or goto WriteAlso; # GOTO! + $err2 .= ' for' unless $err2 =~ /delete$/; + $err = "$err2 $wgrp1:$tag"; + $verbose > 2 and print $out "$err\n"; + next; + } + } + $noConv = 1; # value is not defined, so don't do conversion + } + # apply inverse PrintConv and ValueConv conversions + # save ValueConv setting for use in ConvInv() + unless ($noConv) { + # set default conversion type used by ConvInv() and CHECK_PROC routines + $$self{ConvType} = $convType; + my $e; + ($val,$e) = $self->ConvInv($val,$tagInfo,$tag,$wgrp1,$$self{ConvType},$wantGroup); + if (defined $e) { + # empty error string causes error to be ignored without setting the value + $e or goto WriteAlso; # GOTO! + $err = $e; + } + } + if (not defined $val and defined $value) { + # if value conversion failed, we must still add a NEW_VALUE + # entry for this tag it it was a DelValue + next unless $options{DelValue}; + $val = 'xxx never delete xxx'; + } + $$self{NEW_VALUE} or $$self{NEW_VALUE} = { }; + if ($options{Replace}) { + # delete the previous new value + $self->GetNewValueHash($tagInfo, $writeGroup, 'delete', $options{ProtectSaved}); + # also delete related tag previous new values + if ($$tagInfo{WriteAlso}) { + my ($wgrp, $wtag); + if ($$tagInfo{WriteGroup} and $$tagInfo{WriteGroup} eq 'All' and $writeGroup) { + $wgrp = $writeGroup . ':'; + } else { + $wgrp = ''; + } + foreach $wtag (keys %{$$tagInfo{WriteAlso}}) { + my ($n,$e) = $self->SetNewValue($wgrp . $wtag, undef, Replace=>2); + $numSet += $n; + } + } + $options{Replace} == 2 and ++$numSet, next; + } + + if (defined $val) { + # we are editing this tag, so create a NEW_VALUE hash entry + my $nvHash = $self->GetNewValueHash($tagInfo, $writeGroup, 'create', + $options{ProtectSaved}, ($options{DelValue} and not $shift)); + # ignore new values protected with ProtectSaved + $nvHash or ++$numSet, next; # (increment $numSet to avoid warning) + $$nvHash{NoReplace} = 1 if $$tagInfo{List} and not $options{Replace}; + $$nvHash{WantGroup} = $wantGroup; + $$nvHash{EditOnly} = 1 if $editOnly; + # save maker note information if writing maker notes + if ($$tagInfo{MakerNotes}) { + $$nvHash{MAKER_NOTE_FIXUP} = $$self{MAKER_NOTE_FIXUP}; + } + if ($createOnly) { # create only (never edit) + # empty item in DelValue list to never edit existing value + $$nvHash{DelValue} = [ '' ]; + $$nvHash{CreateOnly} = 1; + } elsif ($options{DelValue} or $addValue or $shift) { + # flag any AddValue or DelValue by creating the DelValue list + $$nvHash{DelValue} or $$nvHash{DelValue} = [ ]; + if ($shift) { + # add shift value to list + $$nvHash{Shift} = $val; + } elsif ($options{DelValue}) { + # don't create if we are replacing a specific value + $$nvHash{IsCreating} = 0 unless $val eq '' or $$tagInfo{List}; + # add delete value to list + push @{$$nvHash{DelValue}}, ref $val eq 'ARRAY' ? @$val : $val; + if ($verbose > 1) { + my $verb = $permanent ? 'Replacing' : 'Deleting'; + my $fromList = $$tagInfo{List} ? ' from list' : ''; + my @vals = (ref $val eq 'ARRAY' ? @$val : $val); + foreach (@vals) { + if (ref $_ eq 'HASH') { + require 'Image/ExifTool/XMPStruct.pl'; + $_ = Image::ExifTool::XMP::SerializeStruct($_); + } + print $out "$verb $wgrp1:$tag$fromList if value is '${_}'\n"; + } + } + } + } + # set priority flag to add only the high priority info + # (will only create the priority tag if it doesn't exist, + # others get changed only if they already exist) + if ($$pref{$tagInfo} or $$tagInfo{Table}{PREFERRED}) { + if ($permanent or $shift) { + # don't create permanent or Shift-ed tag but define IsCreating + # so we know that it is the preferred tag + $$nvHash{IsCreating} = 0; + } elsif (($$tagInfo{List} and not $options{DelValue}) or + not ($$nvHash{DelValue} and @{$$nvHash{DelValue}}) or + # also create tag if any DelValue value is empty ('') + grep(/^$/,@{$$nvHash{DelValue}})) + { + $$nvHash{IsCreating} = $editOnly ? 0 : ($editGroup ? 2 : 1); + # add to hash of groups where this tag is being created + $createGroups or $createGroups = $options{CreateGroups} || { }; + $$createGroups{$self->GetGroup($tagInfo, 0)} = 1; + $$nvHash{CreateGroups} = $createGroups; + } + } + if ($$nvHash{IsCreating}) { + if (%{$$self{DEL_GROUP}}) { + my ($grp, @grps); + foreach $grp (keys %{$$self{DEL_GROUP}}) { + next if $$self{DEL_GROUP}{$grp} == 2; + # set flag indicating tags were written after this group was deleted + $$self{DEL_GROUP}{$grp} = 2; + push @grps, $grp; + } + if ($verbose > 1 and @grps) { + @grps = sort @grps; + print $out " Writing new tags after deleting groups: @grps\n"; + } + } + } elsif ($createOnly) { + $noCreate = $permanent ? 'permanent' : ($$tagInfo{Avoid} ? 'avoided' : ''); + $noCreate or $noCreate = $shift ? 'shifting' : 'not preferred'; + $verbose > 2 and print $out "Not creating $wgrp1:$tag ($noCreate)\n"; + next; # nothing to do (not creating and not editing) + } + if ($shift or not $options{DelValue}) { + $$nvHash{Value} or $$nvHash{Value} = [ ]; + if (not $$tagInfo{List}) { + # not a List tag -- overwrite existing value + $$nvHash{Value}[0] = $val; + } elsif (defined $$nvHash{AddBefore} and @{$$nvHash{Value}} >= $$nvHash{AddBefore}) { + # values from a later argument have been added (ie. Replace=0) + # to this list, so the new values should come before these + splice @{$$nvHash{Value}}, -$$nvHash{AddBefore}, 0, ref $val eq 'ARRAY' ? @$val : $val; + } else { + # add at end of existing list + push @{$$nvHash{Value}}, ref $val eq 'ARRAY' ? @$val : $val; + } + if ($verbose > 1) { + my $ifExists = $$nvHash{IsCreating} ? ( $createOnly ? + ($$nvHash{IsCreating} == 2 ? + " if $writeGroup exists and tag doesn't" : + " if tag doesn't exist") : + ($$nvHash{IsCreating} == 2 ? " if $writeGroup exists" : '')) : + (($$nvHash{DelValue} and @{$$nvHash{DelValue}}) ? + ' if tag was deleted' : ' if tag exists'); + my $verb = ($shift ? 'Shifting' : ($addValue ? 'Adding' : 'Writing')); + print $out "$verb $wgrp1:$tag$ifExists\n"; + } + } + } elsif ($permanent) { + $err = "Can't delete Permanent tag $wgrp1:$tag"; + $verbose > 1 and print $out "$err\n"; + next; + } elsif ($addValue or $options{DelValue}) { + $verbose > 1 and print $out "Adding/Deleting nothing does nothing\n"; + next; + } else { + # create empty new value hash entry to delete this tag + $self->GetNewValueHash($tagInfo, $writeGroup, 'delete'); + my $nvHash = $self->GetNewValueHash($tagInfo, $writeGroup, 'create'); + $$nvHash{WantGroup} = $wantGroup; + $verbose > 1 and print $out "Deleting $wgrp1:$tag\n"; + } + $$setTags{$tagInfo} = 1 if $setTags; + $prioritySet = 1 if $$pref{$tagInfo}; +WriteAlso: + ++$numSet; + # also write related tags + my $writeAlso = $$tagInfo{WriteAlso}; + if ($writeAlso) { + my ($wgrp, $wtag, $n); + if ($$tagInfo{WriteGroup} and $$tagInfo{WriteGroup} eq 'All' and $writeGroup) { + $wgrp = $writeGroup . ':'; + } else { + $wgrp = ''; + } + local $SIG{'__WARN__'} = \&SetWarning; + foreach $wtag (keys %$writeAlso) { + my %opts = ( + Type => 'ValueConv', + Protected => $protected | 0x02, + AddValue => $addValue, + DelValue => $options{DelValue}, + Shift => $options{Shift}, + Replace => $options{Replace}, # handle lists properly + CreateGroups=> $createGroups, + SetTags => \%alsoWrote, # remember tags already written + ); + undef $evalWarning; + #### eval WriteAlso ($val) + my $v = eval $$writeAlso{$wtag}; + $@ and $evalWarning = $@; + unless ($evalWarning) { + ($n,$evalWarning) = $self->SetNewValue($wgrp . $wtag, $v, %opts); + $numSet += $n; + # count this as being set if any related tag is set + $prioritySet = 1 if $n and $$pref{$tagInfo}; + } + if ($evalWarning and (not $err or $verbose > 2)) { + my $str = CleanWarning(); + if ($str) { + $str .= " for $wtag" unless $str =~ / for [-\w:]+$/; + $str .= " in $wgrp1:$tag (WriteAlso)"; + $err or $err = $str; + print $out "$str\n" if $verbose > 2; + } + } + } + } + } + # print warning if we couldn't set our priority tag + if (defined $err and not $prioritySet) { + warn "$err\n" if $err and not wantarray; + } elsif (not $numSet) { + my $pre = $wantGroup ? $wantGroup . ':' : ''; + if ($wasProtected) { + $verbose = 0; # we already printed this verbose message + unless ($options{Replace} and $options{Replace} == 2) { + $err = "Sorry, $pre$tag is $wasProtected for writing"; + } + } elsif (not $listOnly) { + if ($origTag =~ /[?*]/) { + if ($noCreate) { + $err = "No tags matching 'pre${origTag}' will be created"; + $verbose = 0; # (already printed) + } elsif ($foundMatch) { + $err = "Sorry, no writable tags matching '$pre${origTag}'"; + } else { + $err = "No matching tags for '$pre${origTag}'"; + } + } elsif ($noCreate) { + $err = "Not creating $pre$tag"; + $verbose = 0; # (already printed) + } elsif ($foundMatch) { + $err = "Sorry, $pre$tag is not writable"; + } elsif ($wantGroup and @matchingTags) { + $err = "Sorry, $pre$tag doesn't exist or isn't writable"; + } else { + $err = "Tag '$pre${tag}' is not defined"; + } + } + if ($err) { + $verbose > 2 and print $out "$err\n"; + warn "$err\n" unless wantarray; + } + } elsif ($$self{CHECK_WARN}) { + $err = $$self{CHECK_WARN}; + $verbose > 2 and print $out "$err\n"; + } elsif ($err and not $verbose) { + undef $err; + } + return ($numSet, $err) if wantarray; + return $numSet; +} + +#------------------------------------------------------------------------------ +# set new values from information in specified file +# Inputs: 0) ExifTool object reference, 1) source file name or reference, etc +# 2-N) List of tags to set (or all if none specified), or reference(s) to +# hash for options to pass to SetNewValue. The Replace option defaults +# to 1 for SetNewValuesFromFile -- set this to 0 to allow multiple tags +# to be copied to a list +# Returns: Hash of information set successfully (includes Warning or Error messages) +# Notes: Tag names may contain a group prefix, a leading '-' to exclude from copy, +# and/or a trailing '#' to copy the ValueConv value. The tag name '*' may +# be used to represent all tags in a group. An optional destination tag +# may be specified with '>DSTTAG' ('DSTTAG<TAG' also works, but in this +# case the source tag may also be an expression involving tag names). +sub SetNewValuesFromFile($$;@) +{ + local $_; + my ($self, $srcFile, @setTags) = @_; + my ($key, $tag, @exclude, @reqTags); + + # get initial SetNewValuesFromFile options + my %opts = ( Replace => 1 ); # replace existing list items by default + while (ref $setTags[0] eq 'HASH') { + $_ = shift @setTags; + foreach $key (keys %$_) { + $opts{$key} = $$_{$key}; + } + } + # expand shortcuts + @setTags and ExpandShortcuts(\@setTags); + my $srcExifTool = new Image::ExifTool; + # set flag to indicate we are being called from inside SetNewValuesFromFile() + $$srcExifTool{TAGS_FROM_FILE} = 1; + # synchronize and increment the file sequence number + $$srcExifTool{FILE_SEQUENCE} = $$self{FILE_SEQUENCE}++; + # set options for our extraction tool + my $options = $$self{OPTIONS}; + # copy both structured and flattened tags by default (but flattened tags are "unsafe") + my $structOpt = defined $$options{Struct} ? $$options{Struct} : 2; + # copy structures only if no tags specified (since flattened tags are "unsafe") + $structOpt = 1 if $structOpt eq '2' and not @setTags; + # +------------------------------------------+ + # ! DON'T FORGET!! Must consider each new ! + # ! option to decide how it is handled here. ! + # +------------------------------------------+ + $srcExifTool->Options( + Binary => 1, + Charset => $$options{Charset}, + CharsetEXIF => $$options{CharsetEXIF}, + CharsetFileName => $$options{CharsetFileName}, + CharsetID3 => $$options{CharsetID3}, + CharsetIPTC => $$options{CharsetIPTC}, + CharsetPhotoshop=> $$options{CharsetPhotoshop}, + Composite => $$options{Composite}, + CoordFormat => $$options{CoordFormat} || '%d %d %.8f', # copy coordinates at high resolution unless otherwise specified + DateFormat => $$options{DateFormat}, + Duplicates => 1, + Escape => $$options{Escape}, + # Exclude (set below) + ExtendedXMP => $$options{ExtendedXMP}, + ExtractEmbedded => $$options{ExtractEmbedded}, + FastScan => $$options{FastScan}, + Filter => $$options{Filter}, + FixBase => $$options{FixBase}, + GlobalTimeShift => $$options{GlobalTimeShift}, + IgnoreMinorErrors=>$$options{IgnoreMinorErrors}, + Lang => $$options{Lang}, + LargeFileSupport=> $$options{LargeFileSupport}, + List => 1, + ListItem => $$options{ListItem}, + ListSep => $$options{ListSep}, + MakerNotes => $$options{FastScan} && $$options{FastScan} > 1 ? undef : 1, + MDItemTags => $$options{MDItemTags}, + MissingTagValue => $$options{MissingTagValue}, + NoPDFList => $$options{NoPDFList}, + Password => $$options{Password}, + PrintConv => $$options{PrintConv}, + QuickTimeUTC => $$options{QuickTimeUTC}, + RequestAll => $$options{RequestAll} || 1, # (is this still necessary now that RequestTags are being set?) + RequestTags => $$options{RequestTags}, + ScanForXMP => $$options{ScanForXMP}, + StrictDate => defined $$options{StrictDate} ? $$options{StrictDate} : 1, + Struct => $structOpt, + SystemTags => $$options{SystemTags}, + TimeZone => $$options{TimeZone}, + Unknown => $$options{Unknown}, + UserParam => $$options{UserParam}, + Validate => $$options{Validate}, + XAttrTags => $$options{XAttrTags}, + XMPAutoConv => $$options{XMPAutoConv}, + ); + $$srcExifTool{GLOBAL_TIME_OFFSET} = $$self{GLOBAL_TIME_OFFSET}; + foreach $tag (@setTags) { + next if ref $tag; + if ($tag =~ /^-(.*)/) { + # avoid extracting tags that are excluded + push @exclude, $1; + next; + } + # add specified tags to list of requested tags + $_ = $tag; + if (/(.+?)\s*(>|<)\s*(.+)/) { + if ($2 eq '>') { + $_ = $1; + } else { + $_ = $3; + /\$/ and push(@reqTags, /\$\{?(?:[-\w]+:)*([-\w?*]+)/g), next; + } + } + push @reqTags, $2 if /(^|:)([-\w?*]+)#?$/; + } + if (@exclude) { + ExpandShortcuts(\@exclude, 1); + $srcExifTool->Options(Exclude => \@exclude); + } + $srcExifTool->Options(RequestTags => \@reqTags) if @reqTags; + my $printConv = $$options{PrintConv}; + if ($opts{Type}) { + # save source type separately because it may be different than dst Type + $opts{SrcType} = $opts{Type}; + # override PrintConv option with initial Type if given + $printConv = ($opts{Type} eq 'PrintConv' ? 1 : 0); + $srcExifTool->Options(PrintConv => $printConv); + } + my $srcType = $printConv ? 'PrintConv' : 'ValueConv'; + + # get all tags from source file (including MakerNotes block) + my $info = $srcExifTool->ImageInfo($srcFile); + return $info if $$info{Error} and $$info{Error} eq 'Error opening file'; + delete $$srcExifTool{VALUE}{Error}; # delete so we can check this later + + # sort tags in reverse order so we get priority tag last + my @tags = reverse sort keys %$info; +# +# simply transfer all tags from source image if no tags specified +# + unless (@setTags) { + # transfer maker note information to this object + $$self{MAKER_NOTE_FIXUP} = $$srcExifTool{MAKER_NOTE_FIXUP}; + $$self{MAKER_NOTE_BYTE_ORDER} = $$srcExifTool{MAKER_NOTE_BYTE_ORDER}; + foreach $tag (@tags) { + # don't try to set errors or warnings + next if $tag =~ /^(Error|Warning)\b/; + # get approprite value type if necessary + if ($opts{SrcType} and $opts{SrcType} ne $srcType) { + $$info{$tag} = $srcExifTool->GetValue($tag, $opts{SrcType}); + } + # set value for this tag + my ($n, $e) = $self->SetNewValue($tag, $$info{$tag}, %opts); + # delete this tag if we could't set it + $n or delete $$info{$tag}; + } + return $info; + } +# +# transfer specified tags in the proper order +# + # 1) loop through input list of tags to set, and build @setList + my (@setList, $set, %setMatches, $t); + foreach $t (@setTags) { + if (ref $t eq 'HASH') { + # update current options + foreach $key (keys %$t) { + $opts{$key} = $$t{$key}; + } + next; + } + # make a copy of the current options for this setTag + # (also use this hash to store expression and wildcard flags, EXPR and WILD) + my $opts = { %opts }; + $tag = lc $t; # change tag/group names to all lower case + my (@fg, $grp, $dst, $dstGrp, $dstTag, $isExclude); + # handle redirection to another tag + if ($tag =~ /(.+?)\s*(>|<)\s*(.+)/) { + $dstGrp = ''; + my $opt; + if ($2 eq '>') { + ($tag, $dstTag) = ($1, $3); + # flag add and delete (eg. '+<' and '-<') redirections + $opt = $1 if $tag =~ s/\s*([-+])$// or $dstTag =~ s/^([-+])\s*//; + } else { + ($tag, $dstTag) = ($3, $1); + $opt = $1 if $dstTag =~ s/\s*([-+])$//; + # handle expressions + if ($tag =~ /\$/) { + $tag = $t; # restore original case + # recover leading whitespace (except for initial single space) + $tag =~ s/(.+?)\s*(>|<) ?//; + $$opts{EXPR} = 1; # flag this expression + } else { + $opt = $1 if $tag =~ s/^([-+])\s*//; + } + } + # validate tag name(s) + $$opts{EXPR} or ValidTagName($tag) or $self->Warn("Invalid tag name '${tag}'"), next; + ValidTagName($dstTag) or $self->Warn("Invalid tag name '${dstTag}'"), next; + # translate '+' and '-' to appropriate SetNewValue option + if ($opt) { + $$opts{{ '+' => 'AddValue', '-' => 'DelValue' }->{$opt}} = 1; + $$opts{Shift} = 0; # shift if shiftable + } + ($dstGrp, $dstTag) = ($1, $2) if $dstTag =~ /(.*):(.+)/; + # ValueConv may be specified separately on the destination with '#' + $$opts{Type} = 'ValueConv' if $dstTag =~ s/#$//; + # replace tag name of 'all' with '*' + $dstTag = '*' if $dstTag eq 'all'; + } + unless ($$opts{EXPR}) { + $isExclude = ($tag =~ s/^-//); + if ($tag =~ /(.*):(.+)/) { + ($grp, $tag) = ($1, $2); + foreach (split /:/, $grp) { + # save family/groups in list (ignoring 'all' and '*') + next unless length($_) and /^(\d+)?(.*)/; + push @fg, [ $1, $2 ] unless $2 eq '*' or $2 eq 'all'; + } + } + # allow ValueConv to be specified by a '#' on the tag name + if ($tag =~ s/#$//) { + $$opts{SrcType} = 'ValueConv'; + $$opts{Type} = 'ValueConv' unless $dstTag; + } + # replace 'all' with '*' in tag and group names + $tag = '*' if $tag eq 'all'; + # allow wildcards in tag names (handle differently from all tags: '*') + if ($tag =~ /[?*]/ and $tag ne '*') { + $$opts{WILD} = 1; # set flag indicating wildcards were used in source tag + $tag =~ s/\*/[-\\w]*/g; + $tag =~ s/\?/[-\\w]/g; + } + } + # redirect, exclude or set this tag (Note: @fg is empty if we don't care about the group) + if ($dstTag) { + # redirect this tag + $isExclude and return { Error => "Can't redirect excluded tag" }; + # set destination group the same as source if necessary + # (removed in 7.72 so '-*:*<xmp:*' will preserve XMP family 1 groups) + # $dstGrp = $grp if $dstGrp eq '*' and $grp; + # write to specified destination group/tag + $dst = [ $dstGrp, $dstTag ]; + } elsif ($isExclude) { + # implicitly assume '*' if first entry is an exclusion + unshift @setList, [ [ ], '*', [ '', '*' ], $opts ] unless @setList; + # exclude this tag by leaving $dst undefined + } else { + $dst = [ $grp || '', $$opts{WILD} ? '*' : $tag ]; # use same group name for dest + } + # save in reverse order so we don't set tags before an exclude + unshift @setList, [ \@fg, $tag, $dst, $opts ]; + } + # 2) initialize lists of matching tags for each setTag + foreach $set (@setList) { + $$set[2] and $setMatches{$set} = [ ]; + } + # 3) loop through all tags in source image and save tags matching each setTag + my %rtnInfo; + foreach $tag (@tags) { + # don't try to set errors or warnings + if ($tag =~ /^(Error|Warning)( |$)/) { + $rtnInfo{$tag} = $$info{$tag}; + next; + } + # only set specified tags + my $lcTag = lc(GetTagName($tag)); + my (@grp, %grp); +SET: foreach $set (@setList) { + # check first for matching tag + unless ($$set[1] eq $lcTag or $$set[1] eq '*') { + # handle wildcards + next unless $$set[3]{WILD} and $lcTag =~ /^$$set[1]$/; + } + # then check for matching group + if (@{$$set[0]}) { + # get lower case group names if not done already + unless (@grp) { + @grp = map(lc, $srcExifTool->GetGroup($tag)); + $grp{$_} = 1 foreach @grp; + } + foreach (@{$$set[0]}) { + my ($f, $g) = @$_; + if (defined $f) { + next SET unless defined $grp[$f] and $g eq $grp[$f]; + } else { + next SET unless $grp{$g}; + } + } + } + last unless $$set[2]; # all done if we hit an exclude + # add to the list of tags matching this setTag + push @{$setMatches{$set}}, $tag; + } + } + # 4) loop through each setTag in original order, setting new tag values + foreach $set (reverse @setList) { + # get options for SetNewValue + my $opts = $$set[3]; + # handle expressions + if ($$opts{EXPR}) { + my $val = $srcExifTool->InsertTagValues(\@tags, $$set[1], 'Error'); + if ($$srcExifTool{VALUE}{Error}) { + # pass on any error as a warning + $tag = NextFreeTagKey(\%rtnInfo, 'Warning'); + $rtnInfo{$tag} = $$srcExifTool{VALUE}{Error}; + delete $$srcExifTool{VALUE}{Error}; + next unless defined $val; + } + my ($dstGrp, $dstTag) = @{$$set[2]}; + $$opts{Protected} = 1 unless $dstTag =~ /[?*]/ and $dstTag ne '*'; + $$opts{Group} = $dstGrp if $dstGrp; + my @rtnVals = $self->SetNewValue($dstTag, $val, %$opts); + $rtnInfo{$dstTag} = $val if $rtnVals[0]; # tag was set successfully + next; + } + foreach $tag (@{$setMatches{$set}}) { + my ($val, $noWarn); + if ($$opts{SrcType} and $$opts{SrcType} ne $srcType) { + $val = $srcExifTool->GetValue($tag, $$opts{SrcType}); + } else { + $val = $$info{$tag}; + } + my ($dstGrp, $dstTag) = @{$$set[2]}; + if ($dstGrp) { + my @dstGrp = split /:/, $dstGrp; + # destination group of '*' writes to same group as source tag + # (family 1 unless otherwise specified) + foreach (@dstGrp) { + next unless /^(\d*)(all|\*)$/i; + $_ = $1 . $srcExifTool->GetGroup($tag, length $1 ? $1 : 1); + $noWarn = 1; # don't warn on wildcard destinations + } + $$opts{Group} = join ':', @dstGrp; + } else { + delete $$opts{Group}; + } + # transfer maker note information if setting this tag + if ($$srcExifTool{TAG_INFO}{$tag}{MakerNotes}) { + $$self{MAKER_NOTE_FIXUP} = $$srcExifTool{MAKER_NOTE_FIXUP}; + $$self{MAKER_NOTE_BYTE_ORDER} = $$srcExifTool{MAKER_NOTE_BYTE_ORDER}; + } + if ($dstTag eq '*') { + $dstTag = $tag; + $noWarn = 1; + } + if ($$set[1] eq '*' or $$set[3]{WILD}) { + # don't copy from protected binary tags when using wildcards + next if $$srcExifTool{TAG_INFO}{$tag}{Protected} and + $$srcExifTool{TAG_INFO}{$tag}{Binary}; + # don't copy to protected tags when using wildcards + delete $$opts{Protected}; + # don't copy flattened tags if copying structures too when copying all + $$opts{NoFlat} = $structOpt eq '2' ? 1 : 0; + } else { + # allow protected tags to be copied if specified explicitly + $$opts{Protected} = 1 unless $dstTag =~ /[?*]/; + delete $$opts{NoFlat}; + } + # set value(s) for this tag + my ($rtn, $wrn) = $self->SetNewValue($dstTag, $val, %$opts); + # this was added in version 9.14, and allowed actions like "-subject<all" to + # write values of multiple tags into a list, but it had the side effect of + # duplicating items if there were multiple list tags with the same name + # (eg. -use mwg "-creator<creator"), so disable this as of ExifTool 9.36: + # $$opts{Replace} = 0; # accumulate values from tags matching a single argument + if ($wrn and not $noWarn) { + # return this warning + $rtnInfo{NextFreeTagKey(\%rtnInfo, 'Warning')} = $wrn; + $noWarn = 1; + } + $rtnInfo{$tag} = $val if $rtn; # tag was set successfully + } + } + return \%rtnInfo; # return information that we set +} + +#------------------------------------------------------------------------------ +# Get new value(s) for tag +# Inputs: 0) ExifTool object reference, 1) tag name or tagInfo hash ref +# 2) optional pointer to return new value hash reference (not part of public API) +# or 0) ExifTool ref, 1) new value hash reference (not part of public API) +# Returns: List of new Raw values (list may be empty if tag is being deleted) +# Notes: 1) Preferentially returns new value from Extra table if writable Extra tag exists +# 2) Must call AFTER IsOverwriting() returns 1 to get proper value for shifted times +# 3) Tag name is case sensitive and may be prefixed by family 0 or 1 group name +# 4) Value may have been modified by CHECK_PROC routine after ValueConv +sub GetNewValue($$;$) +{ + local $_; + my $self = shift; + my $tag = shift; + my $nvHash; + if ((ref $tag eq 'HASH' and $$tag{IsNVH}) or not defined $tag) { + $nvHash = $tag; + } else { + my $newValueHashPt = shift; + if ($$self{NEW_VALUE}) { + my ($group, $tagInfo); + if (ref $tag) { + $nvHash = $self->GetNewValueHash($tag); + } elsif (defined($tagInfo = $Image::ExifTool::Extra{$tag}) and + $$tagInfo{Writable}) + { + $nvHash = $self->GetNewValueHash($tagInfo); + } else { + # separate group from tag name + $group = $1 if $tag =~ s/(.*)://; + my @tagInfoList = FindTagInfo($tag); + # decide which tag we want +GNV_TagInfo: foreach $tagInfo (@tagInfoList) { + my $nvh = $self->GetNewValueHash($tagInfo) or next; + # select tag in specified group if necessary + while ($group and $group ne $$nvh{WriteGroup}) { + my @grps = $self->GetGroup($tagInfo); + if ($grps[0] eq $$nvh{WriteGroup}) { + # check family 1 group only if WriteGroup is not specific + last if $group eq $grps[1]; + } else { + # otherwise check family 0 group + last if $group eq $grps[0]; + } + # step to next entry in list + $nvh = $$nvh{Next} or next GNV_TagInfo; + } + $nvHash = $nvh; + # give priority to the one we are creating + last if defined $$nvHash{IsCreating}; + } + } + } + # return new value hash if requested + $newValueHashPt and $$newValueHashPt = $nvHash; + } + unless ($nvHash and $$nvHash{Value}) { + return () if wantarray; # return empty list + return undef; + } + my $vals = $$nvHash{Value}; + # do inverse raw conversion if necessary + # - must also check after doing a Shift + if ($$nvHash{TagInfo}{RawConvInv} or $$nvHash{Shift}) { + my @copyVals = @$vals; # modify a copy of the values + $vals = \@copyVals; + my $tagInfo = $$nvHash{TagInfo}; + my $conv = $$tagInfo{RawConvInv}; + my $table = $$tagInfo{Table}; + my ($val, $checkProc); + $checkProc = $$table{CHECK_PROC} if $$nvHash{Shift} and $table; + local $SIG{'__WARN__'} = \&SetWarning; + undef $evalWarning; + foreach $val (@$vals) { + # must check value now if it was shifted + if ($checkProc) { + my $err = &$checkProc($self, $tagInfo, \$val); + if ($err or not defined $val) { + $err or $err = 'Error generating raw value'; + $self->WarnOnce("$err for $$tagInfo{Name}"); + @$vals = (); + last; + } + next unless $conv; + } else { + last unless $conv; + } + # do inverse raw conversion + if (ref($conv) eq 'CODE') { + $val = &$conv($val, $self); + } else { + #### eval RawConvInv ($self, $val, $tagInfo) + $val = eval $conv; + $@ and $evalWarning = $@; + } + if ($evalWarning) { + # an empty warning ("\n") ignores tag with no error + if ($evalWarning ne "\n") { + my $err = CleanWarning() . " in $$tagInfo{Name} (RawConvInv)"; + $self->WarnOnce($err); + } + @$vals = (); + last; + } + } + } + # return our value(s) + return @$vals if wantarray; + return $$vals[0]; +} + +#------------------------------------------------------------------------------ +# Return the total number of new values set +# Inputs: 0) ExifTool object reference +# Returns: Scalar context) Number of new values that have been set (incl pseudo) +# List context) Number of new values (incl pseudo), number of "pseudo" values +# ("pseudo" values are those which don't require rewriting the file to change) +sub CountNewValues($) +{ + my $self = shift; + my $newVal = $$self{NEW_VALUE}; + my ($num, $pseudo) = (0, 0); + if ($newVal) { + $num = scalar keys %$newVal; + my $nv; + foreach $nv (values %$newVal) { + my $tagInfo = $$nv{TagInfo}; + # don't count tags that don't write anything + $$tagInfo{WriteNothing} and --$num, next; + # count the number of pseudo tags included + $$tagInfo{WritePseudo} and ++$pseudo; + } + } + $num += scalar keys %{$$self{DEL_GROUP}}; + return $num unless wantarray; + return ($num, $pseudo); +} + +#------------------------------------------------------------------------------ +# Save new values for subsequent restore +# Inputs: 0) ExifTool object reference +# Returns: Number of times new values have been saved +# Notes: increments SAVE_COUNT flag each time routine is called +sub SaveNewValues($) +{ + my $self = shift; + my $newValues = $$self{NEW_VALUE}; + my $saveCount = ++$$self{SAVE_COUNT}; + my $key; + foreach $key (keys %$newValues) { + my $nvHash = $$newValues{$key}; + while ($nvHash) { + # set Save count if not done already + $$nvHash{Save} or $$nvHash{Save} = $saveCount; + $nvHash = $$nvHash{Next}; + } + } + # initialize hash for saving overwritten new values + $$self{SAVE_NEW_VALUE} = { }; + # make a copy of the delete group hash + my %delGrp = %{$$self{DEL_GROUP}}; + $$self{SAVE_DEL_GROUP} = \%delGrp; + return $saveCount; +} + +#------------------------------------------------------------------------------ +# Restore new values to last saved state +# Inputs: 0) ExifTool object reference +# Notes: Restores saved new values, but currently doesn't restore them in the +# original order, so there may be some minor side-effects when restoring tags +# with overlapping groups. eg) XMP:Identifier, XMP-dc:Identifier +sub RestoreNewValues($) +{ + my $self = shift; + my $newValues = $$self{NEW_VALUE}; + my $savedValues = $$self{SAVE_NEW_VALUE}; + my $key; + # 1) remove any new values which don't have the Save flag set + if ($newValues) { + my @keys = keys %$newValues; + foreach $key (@keys) { + my $lastHash; + my $nvHash = $$newValues{$key}; + while ($nvHash) { + if ($$nvHash{Save}) { + $lastHash = $nvHash; + } else { + # remove this entry from the list + if ($lastHash) { + $$lastHash{Next} = $$nvHash{Next}; + } elsif ($$nvHash{Next}) { + $$newValues{$key} = $$nvHash{Next}; + } else { + delete $$newValues{$key}; + } + } + $nvHash = $$nvHash{Next}; + } + } + } + # 2) restore saved new values + if ($savedValues) { + $newValues or $newValues = $$self{NEW_VALUE} = { }; + foreach $key (keys %$savedValues) { + if ($$newValues{$key}) { + # add saved values to end of list + my $nvHash = LastInList($$newValues{$key}); + $$nvHash{Next} = $$savedValues{$key}; + } else { + $$newValues{$key} = $$savedValues{$key}; + } + } + $$self{SAVE_NEW_VALUE} = { }; # reset saved new values + } + # 3) restore delete groups + my %delGrp = %{$$self{SAVE_DEL_GROUP}}; + $$self{DEL_GROUP} = \%delGrp; +} + +#------------------------------------------------------------------------------ +# Set filesystem time from from FileModifyDate or FileCreateDate tag +# Inputs: 0) ExifTool object reference, 1) file name or file ref +# 2) time (-M or -C) of original file (used for shift; obtained from file if not given) +# 3) tag name to write (undef for 'FileModifyDate') +# 4) flag set if argument 2 has already been converted to Unix seconds +# Returns: 1=time changed OK, 0=nothing done, -1=error setting time +# (increments CHANGED flag and sets corresponding WRITTEN tag) +sub SetFileModifyDate($$;$$$) +{ + my ($self, $file, $originalTime, $tag, $isUnixTime) = @_; + my $nvHash; + $tag = 'FileModifyDate' unless defined $tag; + my $val = $self->GetNewValue($tag, \$nvHash); + return 0 unless defined $val; + my $isOverwriting = $self->IsOverwriting($nvHash); + return 0 unless $isOverwriting; + # can currently only set creation date on Windows systems + # (and Mac now too, but that is handled with the MacOS tags) + return 0 if $tag eq 'FileCreateDate' and $^O ne 'MSWin32'; + if ($isOverwriting < 0) { # are we shifting time? + # use original time of this file if not specified + unless (defined $originalTime) { + my ($aTime, $mTime, $cTime) = $self->GetFileTime($file); + $originalTime = ($tag eq 'FileCreateDate') ? $cTime : $mTime; + return 0 unless defined $originalTime; + $isUnixTime = 1; + } + $originalTime = int($^T - $originalTime*(24*3600) + 0.5) unless $isUnixTime; + return 0 unless $self->IsOverwriting($nvHash, $originalTime); + $val = $$nvHash{Value}[0]; # get shifted value + } + my ($aTime, $mTime, $cTime); + if ($tag eq 'FileCreateDate') { + eval { require Win32::API } or $self->WarnOnce("Install Win32::API to set $tag"), return -1; + eval { require Win32API::File } or $self->WarnOnce("Install Win32API::File to set $tag"), return -1; + $cTime = $val; + } else { + $aTime = $mTime = $val; + } + $self->SetFileTime($file, $aTime, $mTime, $cTime, 1) or $self->Warn("Error setting $tag"), return -1; + ++$$self{CHANGED}; + $$self{WRITTEN}{$tag} = $val; # remember that we wrote this tag + $self->VerboseValue("+ $tag", $val); + return 1; +} + +#------------------------------------------------------------------------------ +# Change file name and/or directory from FileName and Directory tags +# Inputs: 0) ExifTool object reference, 1) current file name (including path) +# 2) new name (or undef to build from FileName and Directory tags) +# 3) option: 'Link' to create link instead of renaming file +# 'Test' to only print new file name +# 4) 0 to indicate that a file will no longer exist (used for 'Test' only) +# Returns: 1=name changed OK, 0=nothing changed, -1=error changing name +# (and increments CHANGED flag if filename changed) +# Notes: Will not overwrite existing file. Creates directories as necessary. +sub SetFileName($$;$$$) +{ + my ($self, $file, $newName, $opt, $usedFlag) = @_; + my ($nvHash, $doName, $doDir); + + $opt or $opt = ''; + # determine the new file name + unless (defined $newName) { + if ($opt) { + if ($opt eq 'Link') { + $newName = $self->GetNewValue('HardLink'); + } elsif ($opt eq 'Test') { + $newName = $self->GetNewValue('TestName'); + } + return 0 unless defined $newName; + } else { + my $filename = $self->GetNewValue('FileName', \$nvHash); + $doName = 1 if defined $filename and $self->IsOverwriting($nvHash, $file); + my $dir = $self->GetNewValue('Directory', \$nvHash); + $doDir = 1 if defined $dir and $self->IsOverwriting($nvHash, $file); + return 0 unless $doName or $doDir; # nothing to do + if ($doName) { + $newName = GetNewFileName($file, $filename); + $newName = GetNewFileName($newName, $dir) if $doDir; + } else { + $newName = GetNewFileName($file, $dir); + } + } + } + # validate new file name in Windows + if ($^O eq 'MSWin32') { + if ($newName =~ /[\0-\x1f<>"|*]/) { + $self->Warn('New file name not allowed in Windows (contains reserved characters)'); + return -1; + } + if ($newName =~ /:/ and $newName !~ /^[A-Z]:[^:]*$/i) { + $self->Warn("New file name not allowed in Windows (contains ':')"); + return -1; + } + if ($newName =~ /\?/ and $newName !~ m{^[\\/]{2}\?[\\/][^?]*$}) { + $self->Warn("New file name not allowed in Windows (contains '?')"); + return -1; + } + if ($newName =~ m{(^|[\\/])(CON|PRN|AUX|NUL|COM[1-9]|LPT[1-9])(\.[^.]*)?$}i) { + $self->Warn('New file name not allowed in Windows (reserved device name)'); + return -1; + } + if ($newName =~ /([. ])$/) { + $self->Warn("New file name not recommended for Windows (ends with '${1}')", 2) and return -1; + } + if (length $newName > 259 and $newName !~ /\?/) { + $self->Warn('New file name not recommended for Windows (exceeds 260 chars)', 2) and return -1; + } + } else { + $newName =~ tr/\0//d; # make sure name doesn't contain nulls + } + # protect against empty file name + length $newName or $self->Warn('New file name is empty'), return -1; + # don't replace existing file + if ($self->Exists($newName) and (not defined $usedFlag or $usedFlag)) { + if ($file ne $newName or $opt eq 'Link') { + # allow for case-insensitive filesystem + if ($opt eq 'Link' or not $self->IsSameFile($file, $newName)) { + $self->Warn("File '${newName}' already exists"); + return -1; + } + } else { + $self->Warn('File name is unchanged'); + return 0; + } + } + if ($opt eq 'Test') { + my $out = $$self{OPTIONS}{TextOut}; + print $out "'${file}' --> '${newName}'\n"; + return 1; + } + # create directory for new file if necessary + my $result; + if (($result = $self->CreateDirectory($newName)) != 0) { + if ($result < 0) { + $self->Warn("Error creating directory for '${newName}'"); + return -1; + } + $self->VPrint(0, "Created directory for '${newName}'"); + } + if ($opt eq 'Link') { + unless (link $file, $newName) { + $self->Warn("Error creating link '${newName}'"); + return -1; + } + ++$$self{CHANGED}; + $self->VerboseValue('+ HardLink', $newName); + return 1; + } + # attempt to rename the file + unless ($self->Rename($file, $newName)) { + local (*EXIFTOOL_SFN_IN, *EXIFTOOL_SFN_OUT); + # renaming didn't work, so copy the file instead + unless ($self->Open(\*EXIFTOOL_SFN_IN, $file)) { + $self->Warn("Error opening '${file}'"); + return -1; + } + unless ($self->Open(\*EXIFTOOL_SFN_OUT, $newName, '>')) { + close EXIFTOOL_SFN_IN; + $self->Warn("Error creating '${newName}'"); + return -1; + } + binmode EXIFTOOL_SFN_IN; + binmode EXIFTOOL_SFN_OUT; + my ($buff, $err); + while (read EXIFTOOL_SFN_IN, $buff, 65536) { + print EXIFTOOL_SFN_OUT $buff or $err = 1; + } + close EXIFTOOL_SFN_OUT or $err = 1; + close EXIFTOOL_SFN_IN; + if ($err) { + $self->Unlink($newName); # erase bad output file + $self->Warn("Error writing '${newName}'"); + return -1; + } + # preserve modification time + my ($aTime, $mTime, $cTime) = $self->GetFileTime($file); + $self->SetFileTime($newName, $aTime, $mTime, $cTime); + # remove the original file + $self->Unlink($file) or $self->Warn('Error removing old file'); + } + $$self{NewName} = $newName; # remember new file name + ++$$self{CHANGED}; + $self->VerboseValue('+ FileName', $newName); + return 1; +} + +#------------------------------------------------------------------------------ +# Set file permissions, group/user id and various MDItem tags from new tag values +# Inputs: 0) Exiftool ref, 1) file name or glob (must be a name for MDItem tags) +# Returns: 1=something was set OK, 0=didn't try, -1=error (and warning set) +# Notes: There may be errors even if 1 is returned +sub SetSystemTags($$) +{ + my ($self, $file) = @_; + my $result = 0; + + my $perm = $self->GetNewValue('FilePermissions'); + if (defined $perm) { + if (eval { chmod($perm & 07777, $file) }) { + $self->VerboseValue('+ FilePermissions', $perm); + $result = 1; + } else { + $self->WarnOnce('Error setting FilePermissions'); + $result = -1; + } + } + my $uid = $self->GetNewValue('FileUserID'); + my $gid = $self->GetNewValue('FileGroupID'); + if (defined $uid or defined $gid) { + defined $uid or $uid = -1; + defined $gid or $gid = -1; + if (eval { chown($uid, $gid, $file) }) { + $self->VerboseValue('+ FileUserID', $uid) if $uid >= 0; + $self->VerboseValue('+ FileGroupID', $gid) if $gid >= 0; + $result = 1; + } else { + $self->WarnOnce('Error setting FileGroup/UserID'); + $result = -1 unless $result; + } + } + my $tag; + foreach $tag (@writableMacOSTags) { + my $nvHash; + my $val = $self->GetNewValue($tag, \$nvHash); + next unless $nvHash; + if ($^O eq 'darwin') { + ref $file and $self->Warn('Setting MDItem tags requires a file name'), last; + require Image::ExifTool::MacOS; + my $res = Image::ExifTool::MacOS::SetMacOSTags($self, $file, \@writableMacOSTags); + $result = $res if $res == 1 or not $result; + last; + } elsif ($tag ne 'FileCreateDate') { + $self->WarnOnce('Can only set MDItem tags on OS X'); + last; + } + } + return $result; +} + +#------------------------------------------------------------------------------ +# Write information back to file +# Inputs: 0) ExifTool object reference, +# 1) input filename, file ref, RAF ref, or scalar ref (or '' or undef to create from scratch) +# 2) output filename, file ref, or scalar ref (or undef to overwrite) +# 3) optional output file type (required only if input file is not specified +# and output file is a reference) +# Returns: 1=file written OK, 2=file written but no changes made, 0=file write error +sub WriteInfo($$;$$) +{ + local ($_, *EXIFTOOL_FILE2, *EXIFTOOL_OUTFILE); + my ($self, $infile, $outfile, $outType) = @_; + my (@fileTypeList, $fileType, $tiffType, $hdr, $seekErr, $type, $tmpfile, $hardLink, $testName); + my ($inRef, $outRef, $closeIn, $closeOut, $outPos, $outBuff, $eraseIn, $raf, $fileExt); + my $oldRaf = $$self{RAF}; + my $rtnVal = 0; + + # initialize member variables + $self->Init(); + + # first, save original file modify date if necessary + # (do this now in case we are modifying file in place and shifting date) + my ($nvHash, $nvHash2, $originalTime, $createTime); + my $setModDate = defined $self->GetNewValue('FileModifyDate', \$nvHash); + my $setCreateDate = defined $self->GetNewValue('FileCreateDate', \$nvHash2); + my ($aTime, $mTime, $cTime); + if ($setModDate and $self->IsOverwriting($nvHash) < 0 and + defined $infile and ref $infile ne 'SCALAR') + { + ($aTime, $mTime, $cTime) = $self->GetFileTime($infile); + $originalTime = $mTime; + } + if ($setCreateDate and $self->IsOverwriting($nvHash2) < 0 and + defined $infile and ref $infile ne 'SCALAR') + { + ($aTime, $mTime, $cTime) = $self->GetFileTime($infile) unless defined $cTime; + $createTime = $cTime; + } +# +# do quick in-place change of file dir/name or date if that is all we are doing +# + my ($numNew, $numPseudo) = $self->CountNewValues(); + if (not defined $outfile and defined $infile) { + $hardLink = $self->GetNewValue('HardLink'); + $testName = $self->GetNewValue('TestName'); + undef $hardLink if defined $hardLink and not length $hardLink; + undef $testName if defined $testName and not length $testName; + my $newFileName = $self->GetNewValue('FileName', \$nvHash); + my $newDir = $self->GetNewValue('Directory'); + if (defined $newDir and length $newDir) { + $newDir .= '/' unless $newDir =~ m{/$}; + } else { + undef $newDir; + } + if ($numNew == $numPseudo) { + $rtnVal = 2; + if (not ref $infile or UNIVERSAL::isa($infile,'GLOB')) { + $self->SetFileModifyDate($infile) > 0 and $rtnVal = 1 if $setModDate; + $self->SetFileModifyDate($infile, undef, 'FileCreateDate') > 0 and $rtnVal = 1 if $setCreateDate; + $self->SetSystemTags($infile) > 0 and $rtnVal = 1; + } + if ((defined $newFileName or defined $newDir) and not ref $infile) { + $self->SetFileName($infile) > 0 and $rtnVal = 1; + } + if (defined $hardLink or defined $testName) { + my $src = $$self{NewName}; + $src = $infile unless defined $src; + $hardLink and $self->SetFileName($src, $hardLink, 'Link') and $rtnVal = 1; + $testName and $self->SetFileName($src, $testName, 'Test') and $rtnVal = 1; + } + return $rtnVal; + } elsif (defined $newFileName and length $newFileName) { + # can't simply rename file, so just set the output name if new FileName + # --> in this case, must erase original copy + if (ref $infile) { + $outfile = $newFileName; + # can't delete original + } elsif ($self->IsOverwriting($nvHash, $infile)) { + $outfile = GetNewFileName($infile, $newFileName); + $eraseIn = 1; # delete original + } + } + # set new directory if specified + if (defined $newDir) { + $outfile = $infile unless defined $outfile or ref $infile; + if (defined $outfile) { + $outfile = GetNewFileName($outfile, $newDir); + $eraseIn = 1 unless ref $infile; + } + } + } +# +# set up input file +# + if (ref $infile) { + $inRef = $infile; + if (UNIVERSAL::isa($inRef,'GLOB')) { + seek($inRef, 0, 0); # make sure we are at the start of the file + } elsif (UNIVERSAL::isa($inRef,'File::RandomAccess')) { + $inRef->Seek(0); + $raf = $inRef; + } elsif ($] >= 5.006 and (eval { require Encode; Encode::is_utf8($$inRef) } or $@)) { + # convert image data from UTF-8 to character stream if necessary + my $buff = $@ ? pack('C*',unpack($] < 5.010000 ? 'U0C*' : 'C0C*',$$inRef)) : Encode::encode('utf8',$$inRef); + if (defined $outfile) { + $inRef = \$buff; + } else { + $$inRef = $buff; + } + } + } elsif (defined $infile and $infile ne '') { + # write to a temporary file if no output file given + $outfile = $tmpfile = "${infile}_exiftool_tmp" unless defined $outfile; + if ($self->Open(\*EXIFTOOL_FILE2, $infile)) { + $fileExt = GetFileExtension($infile); + $fileType = GetFileType($infile); + @fileTypeList = GetFileType($infile); + $tiffType = $$self{FILE_EXT} = GetFileExtension($infile); + $self->VPrint(0, "Rewriting $infile...\n"); + $inRef = \*EXIFTOOL_FILE2; + $closeIn = 1; # we must close the file since we opened it + } else { + $self->Error('Error opening file'); + return 0; + } + } elsif (not defined $outfile) { + $self->Error("WriteInfo(): Must specify infile or outfile\n"); + return 0; + } else { + # create file from scratch + $outType = GetFileExtension($outfile) unless $outType or ref $outfile; + if (CanCreate($outType)) { + if ($$self{OPTIONS}{WriteMode} =~ /g/i) { + $fileType = $tiffType = $outType; # use output file type if no input file + $infile = "$fileType file"; # make bogus file name + $self->VPrint(0, "Creating $infile...\n"); + $inRef = \ ''; # set $inRef to reference to empty data + } else { + $self->Error("Not creating new $outType file (disallowed by WriteMode)"); + return 0; + } + } elsif ($outType) { + $self->Error("Can't create $outType files"); + return 0; + } else { + $self->Error("Can't create file (unknown type)"); + return 0; + } + } + unless (@fileTypeList) { + if ($fileType) { + @fileTypeList = ( $fileType ); + } else { + @fileTypeList = @fileTypes; + $tiffType = 'TIFF'; + } + } +# +# set up output file +# + if (ref $outfile) { + $outRef = $outfile; + if (UNIVERSAL::isa($outRef,'GLOB')) { + binmode($outRef); + $outPos = tell($outRef); + } else { + # initialize our output buffer if necessary + defined $$outRef or $$outRef = ''; + $outPos = length($$outRef); + } + } elsif (not defined $outfile) { + # editing in place, so write to memory first + # (only when infile is a file ref or scalar ref) + if ($raf) { + $self->Error("Can't edit File::RandomAccess object in place"); + return 0; + } + $outBuff = ''; + $outRef = \$outBuff; + $outPos = 0; + } elsif ($self->Exists($outfile)) { + $self->Error("File already exists: $outfile"); + } elsif ($self->Open(\*EXIFTOOL_OUTFILE, $outfile, '>')) { + $outRef = \*EXIFTOOL_OUTFILE; + $closeOut = 1; # we must close $outRef + binmode($outRef); + $outPos = 0; + } else { + my $tmp = $tmpfile ? ' temporary' : ''; + $self->Error("Error creating$tmp file: $outfile"); + } +# +# write the file +# + until ($$self{VALUE}{Error}) { + # create random access file object (disable seek test in case of straight copy) + $raf or $raf = new File::RandomAccess($inRef, 1); + $raf->BinMode(); + if ($numNew == $numPseudo) { + $rtnVal = 1; + # just do a straight copy of the file (no "real" tags are being changed) + my $buff; + while ($raf->Read($buff, 65536)) { + Write($outRef, $buff) or $rtnVal = -1, last; + } + last; + } elsif (not ref $infile and ($infile eq '-' or $infile =~ /\|$/)) { + # patch for Windows command shell pipe + $$raf{TESTED} = -1; # force buffering + } else { + $raf->SeekTest(); + } + # $raf->Debug() and warn " RAF debugging enabled!\n"; + my $inPos = $raf->Tell(); + $$self{RAF} = $raf; + my %dirInfo = ( + RAF => $raf, + OutFile => $outRef, + ); + $raf->Read($hdr, 1024) or $hdr = ''; + $raf->Seek($inPos, 0) or $seekErr = 1; + my $wrongType; + until ($seekErr) { + $type = shift @fileTypeList; + # do quick test to see if this is the right file type + if ($magicNumber{$type} and length($hdr) and $hdr !~ /^$magicNumber{$type}/s) { + next if @fileTypeList; + $wrongType = 1; + last; + } + # save file type in member variable + $dirInfo{Parent} = $$self{FILE_TYPE} = $$self{PATH}[0] = $type; + # determine which directories we must write for this file type + $self->InitWriteDirs($type); + if ($type eq 'JPEG' or $type eq 'EXV') { + $rtnVal = $self->WriteJPEG(\%dirInfo); + } elsif ($type eq 'TIFF') { + # disallow writing of some TIFF-based RAW images: + if (grep /^$tiffType$/, @{$noWriteFile{TIFF}}) { + $fileType = $tiffType; + undef $rtnVal; + } else { + $dirInfo{Parent} = $tiffType; + $rtnVal = $self->ProcessTIFF(\%dirInfo); + } + } elsif (exists $writableType{$type}) { + my ($module, $func); + if (ref $writableType{$type} eq 'ARRAY') { + $module = $writableType{$type}[0] || $type; + $func = $writableType{$type}[1]; + } else { + $module = $writableType{$type} || $type; + } + require "Image/ExifTool/$module.pm"; + $func = "Image::ExifTool::${module}::" . ($func || "Process$type"); + no strict 'refs'; + $rtnVal = &$func($self, \%dirInfo); + use strict 'refs'; + } elsif ($type eq 'ORF' or $type eq 'RAW') { + $rtnVal = $self->ProcessTIFF(\%dirInfo); + } elsif ($type eq 'EXIF') { + # go through WriteDirectory so block writes, etc are handled + my $tagTablePtr = GetTagTable('Image::ExifTool::Exif::Main'); + my $buff = $self->WriteDirectory(\%dirInfo, $tagTablePtr, \&WriteTIFF); + if (defined $buff) { + $rtnVal = Write($outRef, $buff) ? 1 : -1; + } else { + $rtnVal = 0; + } + } else { + undef $rtnVal; # flag that we don't write this type of file + } + # all done unless we got the wrong type + last if $rtnVal; + last unless @fileTypeList; + # seek back to original position in files for next try + $raf->Seek($inPos, 0) or $seekErr = 1, last; + if (UNIVERSAL::isa($outRef,'GLOB')) { + seek($outRef, 0, $outPos); + } else { + $$outRef = substr($$outRef, 0, $outPos); + } + } + # print file format errors + unless ($rtnVal) { + my $err; + if ($seekErr) { + $err = 'Error seeking in file'; + } elsif ($fileType and defined $rtnVal) { + if ($$self{VALUE}{Error}) { + # existing error message will do + } elsif ($fileType eq 'RAW') { + $err = 'Writing this type of RAW file is not supported'; + } else { + if ($wrongType) { + my $type = $fileExt || ($fileType eq 'TIFF' ? $tiffType : $fileType); + $err = "Not a valid $type"; + # do a quick check to see what this file looks like + foreach $type (@fileTypes) { + next unless $magicNumber{$type}; + next unless $hdr =~ /^$magicNumber{$type}/s; + $err .= " (looks more like a $type)"; + last; + } + } else { + $err = 'Format error in file'; + } + } + } elsif ($fileType) { + # get specific type of file from extension + $fileType = GetFileExtension($infile) if $infile and GetFileType($infile); + $err = "Writing of $fileType files is not yet supported"; + } else { + $err = 'Writing of this type of file is not supported'; + } + $self->Error($err) if $err; + $rtnVal = 0; # (in case it was undef) + } + # $raf->Close(); # only used to force debug output + last; # (didn't really want to loop) + } + # don't return success code if any error occurred + if ($rtnVal > 0) { + if ($outType and $type and $outType ne $type) { + my @types = GetFileType($outType); + unless (grep /^$type$/, @types) { + $self->Error("Can't create $outType file from $type"); + $rtnVal = 0; + } + } + if ($rtnVal > 0 and not Tell($outRef) and not $$self{VALUE}{Error}) { + # don't write a file with zero length + if (defined $hdr and length $hdr) { + $type = '<unk>' unless defined $type; + $self->Error("Can't delete all meta information from $type file"); + } else { + $self->Error('Nothing to write'); + } + } + $rtnVal = 0 if $$self{VALUE}{Error}; + } + + # rewrite original file in place if required + if (defined $outBuff) { + if ($rtnVal <= 0 or not $$self{CHANGED}) { + # nothing changed, so no need to write $outBuff + } elsif (UNIVERSAL::isa($inRef,'GLOB')) { + my $len = length($outBuff); + my $size; + $rtnVal = -1 unless + seek($inRef, 0, 2) and # seek to the end of file + ($size = tell $inRef) >= 0 and # get the file size + seek($inRef, 0, 0) and # seek back to the start + print $inRef $outBuff and # write the new data + ($len >= $size or # if necessary: + eval { truncate($inRef, $len) }); # shorten output file + } else { + $$inRef = $outBuff; # replace original data + } + $outBuff = ''; # free memory but leave $outBuff defined + } + # close input file if we opened it + if ($closeIn) { + # errors on input file are significant if we edited the file in place + $rtnVal and $rtnVal = -1 unless close($inRef) or not defined $outBuff; + if ($rtnVal > 0) { + # copy Mac OS resource fork if it exists + if ($^O eq 'darwin' and -s "$infile/..namedfork/rsrc") { + if ($$self{DEL_GROUP}{RSRC}) { + $self->VPrint(0,"Deleting Mac OS resource fork\n"); + ++$$self{CHANGED}; + } else { + $self->VPrint(0,"Copying Mac OS resource fork\n"); + my ($buf, $err); + local (*SRC, *DST); + if ($self->Open(\*SRC, "$infile/..namedfork/rsrc")) { + if ($self->Open(\*DST, "$outfile/..namedfork/rsrc", '>')) { + binmode SRC; # (not necessary for Darwin, but let's be thorough) + binmode DST; + while (read SRC, $buf, 65536) { + print DST $buf or $err = 'copying', last; + } + close DST or $err or $err = 'closing'; + } else { + # (this is normal if the destination filesystem isn't Mac OS) + $self->Warn('Error creating Mac OS resource fork'); + } + close SRC; + } else { + $err = 'opening'; + } + $rtnVal = 0 if $err and $self->Error("Error $err Mac OS resource fork", 2); + } + } + # erase input file if renaming while editing information in place + $self->Unlink($infile) or $self->Warn('Error erasing original file') if $eraseIn; + } + } + # close output file if we created it + if ($closeOut) { + # close file and set $rtnVal to -1 if there was an error + $rtnVal and $rtnVal = -1 unless close($outRef); + # erase the output file if we weren't successful + if ($rtnVal <= 0) { + $self->Unlink($outfile); + # else rename temporary file if necessary + } elsif ($tmpfile) { + $self->CopyFileAttrs($infile, $tmpfile); # copy attributes to new file + unless ($self->Rename($tmpfile, $infile)) { + # some filesystems won't overwrite with 'rename', so try erasing original + if (not $self->Unlink($infile)) { + $self->Unlink($tmpfile); + $self->Error('Error renaming temporary file'); + $rtnVal = 0; + } elsif (not $self->Rename($tmpfile, $infile)) { + $self->Error('Error renaming temporary file after deleting original'); + $rtnVal = 0; + } + } + # the output file should now have the name of the original infile + $outfile = $infile if $rtnVal > 0; + } + } + # set filesystem attributes if requested (and if possible!) + if ($rtnVal > 0 and ($closeOut or (defined $outBuff and ($closeIn or UNIVERSAL::isa($infile,'GLOB'))))) { + my $target = $closeOut ? $outfile : $infile; + # set file permissions if requested + ++$$self{CHANGED} if $self->SetSystemTags($target) > 0; + if ($closeIn) { # (no use setting file times unless the input file is closed) + ++$$self{CHANGED} if $setModDate and $self->SetFileModifyDate($target, $originalTime, undef, 1) > 0; + # set FileCreateDate if requested (and if possible!) + ++$$self{CHANGED} if $setCreateDate and $self->SetFileModifyDate($target, $createTime, 'FileCreateDate', 1) > 0; + # create hard link if requested and no output filename specified (and if possible!) + ++$$self{CHANGED} if defined $hardLink and $self->SetFileName($target, $hardLink, 'Link'); + defined $testName and $self->SetFileName($target, $testName, 'Test'); + } + } + # check for write error and set appropriate error message and return value + if ($rtnVal < 0) { + $self->Error('Error writing output file') unless $$self{VALUE}{Error}; + $rtnVal = 0; # return 0 on failure + } elsif ($rtnVal > 0) { + ++$rtnVal unless $$self{CHANGED}; + } + # set things back to the way they were + $$self{RAF} = $oldRaf; + + return $rtnVal; +} + +#------------------------------------------------------------------------------ +# Get list of all available tags for specified group +# Inputs: 0) optional group name (or string of names separated by colons) +# Returns: tag list (sorted alphabetically) +# Notes: Can't get tags for specific IFD +sub GetAllTags(;$) +{ + local $_; + my $group = shift; + my (%allTags, @groups); + @groups = split ':', $group if $group; + + my $et = new Image::ExifTool; + LoadAllTables(); # first load all our tables + my @tableNames = keys %allTables; + + # loop through all tables and save tag names to %allTags hash + while (@tableNames) { + my $table = GetTagTable(pop @tableNames); + # generate flattened tag names for structure fields if this is an XMP table + if ($$table{GROUPS} and $$table{GROUPS}{0} eq 'XMP') { + Image::ExifTool::XMP::AddFlattenedTags($table); + } + my $tagID; + foreach $tagID (TagTableKeys($table)) { + my @infoArray = GetTagInfoList($table,$tagID); + my $tagInfo; +GATInfo: foreach $tagInfo (@infoArray) { + my $tag = $$tagInfo{Name}; + $tag or warn("no name for tag!\n"), next; + # don't list subdirectories unless they are writable + next if $$tagInfo{SubDirectory} and not $$tagInfo{Writable}; + next if $$tagInfo{Hidden}; # ignore hidden tags + if (@groups) { + my @tg = $et->GetGroup($tagInfo); + foreach $group (@groups) { + next GATInfo unless grep /^$group$/i, @tg; + } + } + $allTags{$tag} = 1; + } + } + } + return sort keys %allTags; +} + +#------------------------------------------------------------------------------ +# Get list of all writable tags +# Inputs: 0) optional group name (or names separated by colons) +# Returns: tag list (sorted alphabetically) +sub GetWritableTags(;$) +{ + local $_; + my $group = shift; + my (%writableTags, @groups); + @groups = split ':', $group if $group; + + my $et = new Image::ExifTool; + LoadAllTables(); + my @tableNames = keys %allTables; + + while (@tableNames) { + my $tableName = pop @tableNames; + my $table = GetTagTable($tableName); + # generate flattened tag names for structure fields if this is an XMP table + if ($$table{GROUPS} and $$table{GROUPS}{0} eq 'XMP') { + Image::ExifTool::XMP::AddFlattenedTags($table); + } + # attempt to load Write tables if autoloaded + my @parts = split(/::/,$tableName); + if (@parts > 3) { + my $i = $#parts - 1; + $parts[$i] = "Write$parts[$i]"; # add 'Write' before class name + my $module = join('::',@parts[0..$i]); + eval { require $module }; # (fails silently if nothing loaded) + } + my $tagID; + foreach $tagID (TagTableKeys($table)) { + my @infoArray = GetTagInfoList($table,$tagID); + my $tagInfo; +GWTInfo: foreach $tagInfo (@infoArray) { + my $tag = $$tagInfo{Name}; + $tag or warn("no name for tag!\n"), next; + my $writable = $$tagInfo{Writable}; + next unless $writable or ($$table{WRITABLE} and + not defined $writable and not $$tagInfo{SubDirectory}); + next if $$tagInfo{Hidden}; # ignore hidden tags + if (@groups) { + my @tg = $et->GetGroup($tagInfo); + foreach $group (@groups) { + next GWTInfo unless grep /^$group$/i, @tg; + } + } + $writableTags{$tag} = 1; + } + } + } + return sort keys %writableTags; +} + +#------------------------------------------------------------------------------ +# Get list of all group names +# Inputs: 0) Group family number +# Returns: List of group names (sorted alphabetically) +sub GetAllGroups($) +{ + local $_; + my $family = shift || 0; + + $family == 3 and return('Doc#', 'Main'); + $family == 4 and return('Copy#'); + + LoadAllTables(); # first load all our tables + + my @tableNames = keys %allTables; + + # loop through all tag tables and get all group names + my %allGroups; + while (@tableNames) { + my $table = GetTagTable(pop @tableNames); + my ($grps, $grp, $tag, $tagInfo); + $allGroups{$grp} = 1 if ($grps = $$table{GROUPS}) and ($grp = $$grps{$family}); + foreach $tag (TagTableKeys($table)) { + my @infoArray = GetTagInfoList($table, $tag); + foreach $tagInfo (@infoArray) { + next unless ($grps = $$tagInfo{Groups}) and ($grp = $$grps{$family}); + $allGroups{$grp} = 1; + } + } + } + delete $allGroups{'*'}; # (not a real group) + return sort keys %allGroups; +} + +#------------------------------------------------------------------------------ +# get priority group list for new values +# Inputs: 0) ExifTool object reference +# Returns: List of group names +sub GetNewGroups($) +{ + my $self = shift; + return @{$$self{WRITE_GROUPS}}; +} + +#------------------------------------------------------------------------------ +# Get list of all deletable group names +# Returns: List of group names (sorted alphabetically) +sub GetDeleteGroups() +{ + return sort @delGroups, @delGroup2; +} + +#------------------------------------------------------------------------------ +# Add user-defined tags at run time +# Inputs: 0) destination table name, 1) tagID/tagInfo pairs for tags to add +# Returns: number of tags added +# Notes: will replace existing tags +sub AddUserDefinedTags($%) +{ + local $_; + my ($tableName, %addTags) = @_; + my $table = GetTagTable($tableName) or return 0; + # add tags to writer lookup + Image::ExifTool::TagLookup::AddTags(\%addTags, $tableName); + my $tagID; + my $num = 0; + foreach $tagID (keys %addTags) { + next if $specialTags{$tagID}; + delete $$table{$tagID}; # delete old entry if it existed + AddTagToTable($table, $tagID, $addTags{$tagID}, 1); + ++$num; + } + return $num; +} + +#============================================================================== +# Functions below this are not part of the public API + +#------------------------------------------------------------------------------ +# Maintain backward compatibility for old GetNewValues function name +sub GetNewValues($$;$) +{ + my ($self, $tag, $nvHashPt) = @_; + return $self->GetNewValue($tag, $nvHashPt); +} + +#------------------------------------------------------------------------------ +# Un-escape string according to options settings and clear UTF-8 flag +# Inputs: 0) ExifTool ref, 1) string ref or string ref ref +# Notes: also de-references SCALAR values +sub Sanitize($$) +{ + my ($self, $valPt) = @_; + # de-reference SCALAR references + $$valPt = $$$valPt if ref $$valPt eq 'SCALAR'; + # make sure the Perl UTF-8 flag is OFF for the value if perl 5.6 or greater + # (otherwise our byte manipulations get corrupted!!) + if ($] >= 5.006 and (eval { require Encode; Encode::is_utf8($$valPt) } or $@)) { + local $SIG{'__WARN__'} = \&SetWarning; + # repack by hand if Encode isn't available + $$valPt = $@ ? pack('C*',unpack($] < 5.010000 ? 'U0C*' : 'C0C*',$$valPt)) : Encode::encode('utf8',$$valPt); + } + # un-escape value if necessary + if ($$self{OPTIONS}{Escape}) { + # (XMP.pm and HTML.pm were require'd as necessary when option was set) + if ($$self{OPTIONS}{Escape} eq 'XML') { + $$valPt = Image::ExifTool::XMP::UnescapeXML($$valPt); + } elsif ($$self{OPTIONS}{Escape} eq 'HTML') { + $$valPt = Image::ExifTool::HTML::UnescapeHTML($$valPt, $$self{OPTIONS}{Charset}); + } + } +} + +#------------------------------------------------------------------------------ +# Apply inverse conversions +# Inputs: 0) ExifTool ref, 1) value, 2) tagInfo (or Struct item) ref, +# 3) tag name, 4) group 1 name, 5) conversion type (or undef), +# 6) [optional] want group ("" for structure field) +# Returns: 0) converted value, 1) error string (or undef on success) +# Notes: +# - uses ExifTool "ConvType" member when conversion type is undef +# - conversion types other than 'ValueConv' and 'PrintConv' are treated as 'Raw' +sub ConvInv($$$$$;$$) +{ + my ($self, $val, $tagInfo, $tag, $wgrp1, $convType, $wantGroup) = @_; + my ($err, $type); + +Conv: for (;;) { + if (not defined $type) { + # split value into list if necessary + if ($$tagInfo{List}) { + my $listSplit = $$tagInfo{AutoSplit} || $$self{OPTIONS}{ListSplit}; + if (defined $listSplit and not $$tagInfo{Struct} and + ($wantGroup or not defined $wantGroup)) + { + $listSplit = ',?\s+' if $listSplit eq '1' and $$tagInfo{AutoSplit}; + my @splitVal = split /$listSplit/, $val; + $val = \@splitVal if @splitVal > 1; + } + } + $type = $convType || $$self{ConvType} || 'PrintConv'; + } elsif ($type eq 'PrintConv') { + $type = 'ValueConv'; + } else { + # split raw value if necessary + if ($$tagInfo{RawJoin} and $$tagInfo{List} and not ref $val) { + my @splitVal = split ' ', $val; + $val = \@splitVal if @splitVal > 1; + } + # finally, do our value check + my ($err2, $v); + if ($$tagInfo{WriteCheck}) { + #### eval WriteCheck ($self, $tagInfo, $val) + $err2 = eval $$tagInfo{WriteCheck}; + $@ and warn($@), $err2 = 'Error evaluating WriteCheck'; + } + unless ($err2) { + my $table = $$tagInfo{Table}; + if ($table and $$table{CHECK_PROC} and not $$tagInfo{RawConvInv}) { + my $checkProc = $$table{CHECK_PROC}; + if (ref $val eq 'ARRAY') { + # loop through array values + foreach $v (@$val) { + $err2 = &$checkProc($self, $tagInfo, \$v); + last if $err2; + } + } else { + $err2 = &$checkProc($self, $tagInfo, \$val); + } + } + } + if (defined $err2) { + if ($err2) { + $err = "$err2 for $wgrp1:$tag"; + $self->VPrint(2, "$err\n"); + undef $val; # value was invalid + } else { + $err = $err2; # empty error (quietly don't write tag) + } + } + last; + } + my $conv = $$tagInfo{$type}; + my $convInv = $$tagInfo{"${type}Inv"}; + # nothing to do at this level if no conversion defined + next unless defined $conv or defined $convInv; + + my (@valList, $index, $convList, $convInvList); + if (ref $val eq 'ARRAY') { + # handle ValueConv of ListSplit and AutoSplit values + @valList = @$val; + $val = $valList[$index = 0]; + } elsif (ref $conv eq 'ARRAY' or ref $convInv eq 'ARRAY') { + # handle conversion lists + @valList = split /$listSep{$type}/, $val; + $val = $valList[$index = 0]; + if (ref $conv eq 'ARRAY') { + $convList = $conv; + $conv = $$conv[0]; + } + if (ref $convInv eq 'ARRAY') { + $convInvList = $convInv; + $convInv = $$convInv[0]; + } + } + # loop through multiple values if necessary + for (;;) { + if ($convInv) { + # capture eval warnings too + local $SIG{'__WARN__'} = \&SetWarning; + undef $evalWarning; + if (ref($convInv) eq 'CODE') { + $val = &$convInv($val, $self); + } else { + #### eval PrintConvInv/ValueConvInv ($val, $self, $wantGroup) + $val = eval $convInv; + $@ and $evalWarning = $@; + } + if ($evalWarning) { + # an empty warning ("\n") ignores tag with no error + if ($evalWarning eq "\n") { + $err = '' unless defined $err; + } else { + $err = CleanWarning() . " in $wgrp1:$tag (${type}Inv)"; + $self->VPrint(2, "$err\n"); + } + undef $val; + last Conv; + } elsif (not defined $val) { + $err = "Error converting value for $wgrp1:$tag (${type}Inv)"; + $self->VPrint(2, "$err\n"); + last Conv; + } + } elsif ($conv) { + if (ref $conv eq 'HASH') { + my ($multi, $lc); + # insert alternate language print conversions if required + if ($$self{CUR_LANG} and $type eq 'PrintConv' and + ref($lc = $$self{CUR_LANG}{$tag}) eq 'HASH' and + ($lc = $$lc{PrintConv})) + { + my %newConv; + foreach (keys %$conv) { + my $val = $$conv{$_}; + defined $$lc{$val} or $newConv{$_} = $val, next; + $newConv{$_} = $self->Decode($$lc{$val}, 'UTF8'); + } + if ($$conv{BITMASK}) { + foreach (keys %{$$conv{BITMASK}}) { + my $val = $$conv{BITMASK}{$_}; + defined $$lc{$val} or $newConv{BITMASK}{$_} = $val, next; + $newConv{BITMASK}{$_} = $self->Decode($$lc{$val}, 'UTF8'); + } + } + $conv = \%newConv; + } + undef $evalWarning; + if ($$conv{BITMASK}) { + my $lookupBits = $$conv{BITMASK}; + my ($wbits, $tbits) = @$tagInfo{'BitsPerWord','BitsTotal'}; + my ($val2, $err2) = EncodeBits($val, $lookupBits, $wbits, $tbits); + if ($err2) { + # ok, try matching a straight value + ($val, $multi) = ReverseLookup($val, $conv); + unless (defined $val) { + $err = "Can't encode $wgrp1:$tag ($err2)"; + $self->VPrint(2, "$err\n"); + last Conv; + } + } elsif (defined $val2) { + $val = $val2; + } else { + delete $$conv{BITMASK}; + ($val, $multi) = ReverseLookup($val, $conv); + $$conv{BITMASK} = $lookupBits; + } + } else { + ($val, $multi) = ReverseLookup($val, $conv); + } + if (not defined $val) { + my $prob = $evalWarning ? lcfirst CleanWarning() : ($multi ? 'matches more than one ' : 'not in ') . $type; + $err = "Can't convert $wgrp1:$tag ($prob)"; + $self->VPrint(2, "$err\n"); + last Conv; + } elsif ($evalWarning) { + $self->VPrint(2, CleanWarning() . " for $wgrp1:$tag\n"); + } + } elsif (not $$tagInfo{WriteAlso}) { + $err = "Can't convert value for $wgrp1:$tag (no ${type}Inv)"; + $self->VPrint(2, "$err\n"); + undef $val; + last Conv; + } + } + last unless @valList; + $valList[$index] = $val; + if (++$index >= @valList) { + # leave AutoSplit lists in ARRAY form, or join conversion lists + $val = $$tagInfo{List} ? \@valList : join ' ', @valList; + last; + } + $conv = $$convList[$index] if $convList; + $convInv = $$convInvList[$index] if $convInvList; + $val = $valList[$index]; + } + } # end ValueConv/PrintConv loop + + return($val, $err); +} + +#------------------------------------------------------------------------------ +# convert tag names to values in a string (eg. '${EXIF:ISO}x $$' --> '100x $') +# Inputs: 0) ExifTool object ref, 1) reference to list of found tags +# 2) string with embedded tag names, 3) Options: +# undef - set missing tags to '' +# 'Error' - issue minor error on missing tag (and return undef) +# 'Warn' - issue minor warning on missing tag (and return undef) +# 'Silent' - just return undef on missing tag (no errors/warnings) +# Hash ref - hash for return of tag/value pairs +# 4) document group name if extracting from a specific document +# 5) hash ref to cache tag keys for subsequent calls in document loop +# Returns: string with embedded tag values (or '$info{TAGNAME}' entries with Hash ref option) +# Notes: +# - tag names are not case sensitive and may end with '#' for ValueConv value +# - uses MissingTagValue option if set +# - '$GROUP:all' evaluates to 1 if any tag from GROUP exists, or 0 otherwise +# - advanced feature allows Perl expressions inside braces (eg. '${model;tr/ //d}') +# - an error/warning in an advanced expression ("${TAG;EXPR}") generates an error +# if option set to 'Error', or a warning otherwise +sub InsertTagValues($$$;$$$) +{ + local $_; + my ($self, $foundTags, $line, $opt, $docGrp, $cache) = @_; + my $rtnStr = ''; + my $docNum; + if ($docGrp) { + $docNum = $docGrp =~ /(\d+)$/ ? $1 : 0; + } else { + undef $cache; # no cache if no document groups + } + while ($line =~ s/(.*?)\$(\{\s*)?([-\w]*\w|\$|\/)//s) { + my ($pre, $bra, $var) = ($1, $2, $3); + my (@tags, $val, $tg, @val, $type, $expr, $didExpr, $level, $asList); + # "$$" represents a "$" symbol, and "$/" is a newline + if ($var eq '$' or $var eq '/') { + $var = "\n" if $var eq '/'; + $rtnStr .= "$pre$var"; + $line =~ s/^\s*\}// if $bra; + next; + } + # allow multiple group names + while ($line =~ /^:([-\w]*\w)(.*)/s) { + my $group = $var; + ($var, $line) = ($1, $2); + $var = "$group:$var"; + } + # allow trailing '#' to indicate ValueConv value + $type = 'ValueConv' if $line =~ s/^#//; + # (undocumented feature to allow '@' to evaluate list values separately, but only in braces) + if ($bra and $line =~ s/^\@(#)?//) { + $asList = 1; + $type = 'ValueConv' if $1; + } + # remove trailing bracket if there was a leading one + # and extract Perl expression from inside brackets if it exists + if ($bra and $line !~ s/^\s*\}// and $line =~ s/^\s*;\s*(.*?)\s*\}//s) { + my $part = $1; + $expr = ''; + for ($level=0; ; --$level) { + # increase nesting level for each opening brace + ++$level while $part =~ /\{/g; + $expr .= $part; + last unless $level and $line =~ s/^(.*?)\s*\}//s; # get next part + $part = $1; + $expr .= '}'; # this brace was part of the expression + } + # use default Windows filename filter if expression is empty + $expr = 'tr(/\\\\?*:|"<>\\0)()d' unless length $expr; + } + push @tags, $var; + ExpandShortcuts(\@tags); + @tags or $rtnStr .= $pre, next; + # save advanced formatting expression to allow access by user-defined ValueConv + $$self{FMT_EXPR} = $expr; + + for (;;) { + # temporarily reset ListJoin option if evaluating list values separately + my $oldListJoin = $self->Options(ListJoin => undef) if $asList; + my $tag = shift @tags; + my $lcTag = lc $tag; + if ($cache and $lcTag !~ /(^|:)all$/) { + # remove group from tag name (but not lower-case version) + my $group; + $tag =~ s/^(.*):// and $group = $1; + # cache tag keys to speed processing for a large number of sub-documents + # (similar to code in BuildCompositeTags(), but this is case-insensitive) + my $cacheTag = $$cache{$lcTag}; + unless ($cacheTag) { + $cacheTag = $$cache{$lcTag} = [ ]; + # find all matching keys, organize into groups, and store in cache + my $ex = $$self{TAG_EXTRA}; + my @matches = grep /^$tag(\s|$)/i, @$foundTags; + @matches = $self->GroupMatches($group, \@matches) if defined $group; + foreach (@matches) { + my $doc = $$ex{$_} ? $$ex{$_}{G3} || 0 : 0; + if (defined $$cacheTag[$doc]) { + next unless $$cacheTag[$doc] =~ / \((\d+)\)$/; + my $cur = $1; + # keep the most recently extracted tag + next if / \((\d+)\)$/ and $1 < $cur; + } + $$cacheTag[$doc] = $_; + } + } + my $doc = $lcTag =~ /\b(main|doc(\d+)):/ ? ($2 || 0) : $docNum; + $val = $self->GetValue($$cacheTag[$doc], $type) if $$cacheTag[$doc]; + } else { + # add document number to tag if specified and it doesn't already exist + if ($docGrp and $lcTag !~ /\b(main|doc\d+):/) { + $tag = $docGrp . ':' . $tag; + $lcTag = lc $tag; + } + if ($lcTag eq 'all') { + $val = 1; # always some tag available + } elsif (defined $$self{OPTIONS}{UserParam}{$lcTag}) { + $val = $$self{OPTIONS}{UserParam}{$lcTag}; + } elsif ($tag =~ /(.*):(.+)/) { + my $group; + ($group, $tag) = ($1, $2); + if (lc $tag eq 'all') { + # see if any tag from the specified group exists + my $match = $self->GroupMatches($group, $foundTags); + $val = $match ? 1 : 0; + } else { + # find the specified tag + my @matches = grep /^$tag(\s|$)/i, @$foundTags; + @matches = $self->GroupMatches($group, \@matches); + foreach $tg (@matches) { + if (defined $val and $tg =~ / \((\d+)\)$/) { + # take the most recently extracted tag + my $tagNum = $1; + next if $tag !~ / \((\d+)\)$/ or $1 > $tagNum; + } + $val = $self->GetValue($tg, $type); + $tag = $tg; + last unless $tag =~ / /; # all done if we got our best match + } + } + } else { + # get the tag value + $val = $self->GetValue($tag, $type); + unless (defined $val) { + # check for tag name with different case + ($tg) = grep /^$tag$/i, @$foundTags; + if (defined $tg) { + $val = $self->GetValue($tg, $type); + $tag = $tg; + } + } + } + } + $self->Options(ListJoin => $oldListJoin) if $asList; + if (ref $val eq 'ARRAY') { + push @val, @$val; + undef $val; + last unless @tags; + } elsif (ref $val eq 'SCALAR') { + if ($$self{OPTIONS}{Binary} or $$val =~ /^Binary data/) { + $val = $$val; + } else { + $val = 'Binary data ' . length($$val) . ' bytes'; + } + } elsif (ref $val eq 'HASH') { + require 'Image/ExifTool/XMPStruct.pl'; + $val = Image::ExifTool::XMP::SerializeStruct($val); + } elsif (not defined $val) { + $val = $$self{OPTIONS}{MissingTagValue} if $asList; + } + last unless @tags; + push @val, $val if defined $val; + undef $val; + } + if (@val) { + push @val, $val if defined $val; + $val = join $$self{OPTIONS}{ListSep}, @val; + } else { + push @val, $val if defined $val; # (so the eval has access to @val if required) + } + # evaluate advanced formatting expression if given (eg. "${TAG;EXPR}") + if (defined $expr and defined $val) { + local $SIG{'__WARN__'} = \&SetWarning; + undef $evalWarning; + $advFmtSelf = $self; + if ($asList) { + foreach (@val) { + #### eval advanced formatting expression ($_, $self, @val, $advFmtSelf) + eval $expr; + $@ and $evalWarning = $@; + } + # join back together if any values are still defined + @val = grep defined, @val; + $val = @val ? join $$self{OPTIONS}{ListSep}, @val : undef; + } else { + $_ = $val; + #### eval advanced formatting expression ($_, $self, @val, $advFmtSelf) + eval $expr; + $@ and $evalWarning = $@; + $val = ref $_ eq 'ARRAY' ? join($$self{OPTIONS}{ListSep}, @$_): $_; + } + if ($evalWarning) { + my $g3 = ($docGrp and $var !~ /\b(main|doc\d+):/i) ? $docGrp . ':' : ''; + my $str = CleanWarning() . " for '$g3${var}'"; + if ($opt) { + if ($opt eq 'Error') { + $self->Error($str); + } elsif ($opt ne 'Silent') { + $self->Warn($str); + } + } + } + undef $advFmtSelf; + $didExpr = 1; # set flag indicating an expression was evaluated + } + unless (defined $val or ref $opt) { + $val = $$self{OPTIONS}{MissingTagValue}; + unless (defined $val) { + my $g3 = ($docGrp and $var !~ /\b(main|doc\d+):/i) ? $docGrp . ':' : ''; + my $msg = $didExpr ? "Advanced formatting expression returned undef for '$g3${var}'" : + "Tag '$g3${var}' not defined"; + no strict 'refs'; + $opt and ($opt eq 'Silent' or &$opt($self, $msg, 2)) and return $$self{FMT_EXPR} = undef; + $val = ''; + } + } + if (ref $opt eq 'HASH') { + $var .= '#' if $type; + if (defined $expr) { + # generate unique variable name for this modified tag value + my $i = 1; + ++$i while exists $$opt{"$var.expr$i"}; + $var .= '.expr' . $i; + } + $rtnStr .= "$pre\$info{'${var}'}"; + $$opt{$var} = $val; + } else { + $rtnStr .= "$pre$val"; + } + } + $$self{FMT_EXPR} = undef; + return $rtnStr . $line; +} + +#------------------------------------------------------------------------------ +# Reformat date/time value in $_ based on specified format string +# Inputs: 0) date/time format string +sub DateFmt($) +{ + my $et = bless { OPTIONS => { DateFormat => shift, StrictDate => 1 } }; + my $shift; + if ($advFmtSelf and defined($shift = $$advFmtSelf{OPTIONS}{GlobalTimeShift})) { + $$et{OPTIONS}{GlobalTimeShift} = $shift; + $$et{GLOBAL_TIME_OFFSET} = $$advFmtSelf{GLOBAL_TIME_OFFSET}; + } + $_ = $et->ConvertDateTime($_); + defined $_ or warn "Error converting date/time\n"; + $$advFmtSelf{GLOBAL_TIME_OFFSET} = $$et{GLOBAL_TIME_OFFSET} if $shift; +} + +#------------------------------------------------------------------------------ +# Utility routine to remove duplicate items from default input string +# Inputs: 0) true to set $_ to undef if not changed +# Notes: - for use only in advanced formatting expressions +sub NoDups +{ + my %seen; + my $sep = $advFmtSelf ? $$advFmtSelf{OPTIONS}{ListSep} : ', '; + my $new = join $sep, grep { !$seen{$_}++ } split /\Q$sep\E/, $_; + $_ = ($_[0] and $new eq $_) ? undef : $new; +} + +#------------------------------------------------------------------------------ +# Is specified tag writable +# Inputs: 0) tag name, case insensitive (optional group name currently ignored) +# Returns: 0=exists but not writable, 1=writable, undef=doesn't exist +sub IsWritable($) +{ + my $tag = shift; + $tag =~ s/^(.*)://; # ignore group name + my @tagInfo = FindTagInfo($tag); + unless (@tagInfo) { + return 0 if TagExists($tag); + return undef; + } + my $tagInfo; + foreach $tagInfo (@tagInfo) { + return $$tagInfo{Writable} ? 1 : 0 if defined $$tagInfo{Writable}; + return 1 if $$tagInfo{Table}{WRITABLE}; + # must call WRITE_PROC to autoload writer because this may set the writable tag + my $writeProc = $$tagInfo{Table}{WRITE_PROC}; + next unless $writeProc; + &$writeProc(); # dummy call to autoload writer + return 1 if $$tagInfo{Writable}; + } + return 0; +} + +#------------------------------------------------------------------------------ +# Check to see if these are the same file +# Inputs: 0) ExifTool ref, 1) first file name, 2) second file name +# Returns: true if file names reference the same file +sub IsSameFile($$$) +{ + my ($self, $file, $file2) = @_; + return 0 unless lc $file eq lc $file2; # (only looking for differences in case) + my ($isSame, $interrupted); + my $tmp1 = "${file}_ExifTool_tmp_$$"; + my $tmp2 = "${file2}_ExifTool_tmp_$$"; + { + local *TMP1; + local $SIG{INT} = sub { $interrupted = 1 }; + if ($self->Open(\*TMP1, $tmp1, '>')) { + close TMP1; + $isSame = 1 if $self->Exists($tmp2); + $self->Unlink($tmp1); + } + } + if ($interrupted and $SIG{INT}) { + no strict 'refs'; + &{$SIG{INT}}(); + } + return $isSame; +} + +#------------------------------------------------------------------------------ +# Create directory for specified file +# Inputs: 0) ExifTool ref, 1) complete file name including path +# Returns: 1 = directory created, 0 = nothing done, -1 = error +my $k32CreateDir; +sub CreateDirectory($$) +{ + local $_; + my ($self, $file) = @_; + my $rtnVal = 0; + my $enc = $$self{OPTIONS}{CharsetFileName}; + my $dir; + ($dir = $file) =~ s/[^\/]*$//; # remove filename from path specification + # recode as UTF-8 if necessary + if ($dir and not $self->IsDirectory($dir)) { + my @parts = split /\//, $dir; + $dir = ''; + foreach (@parts) { + $dir .= $_; + if (length $dir and not $self->IsDirectory($dir)) { + # create directory since it doesn't exist + my $d2 = $dir; # (must make a copy in case EncodeFileName recodes it) + if ($self->EncodeFileName($d2)) { + # handle Windows Unicode directory names + unless (eval { require Win32::API }) { + $self->Warn('Install Win32::API to create directories with Unicode names'); + return -1; + } + unless ($k32CreateDir) { + return -1 if defined $k32CreateDir; + $k32CreateDir = new Win32::API('KERNEL32', 'CreateDirectoryW', 'PP', 'I'); + unless ($k32CreateDir) { + $self->Warn('Error calling Win32::API::CreateDirectoryW'); + $k32CreateDir = 0; + return -1; + } + } + $k32CreateDir->Call($d2, 0) or return -1; + } else { + mkdir($d2, 0777) or return -1; + } + $rtnVal = 1; + } + $dir .= '/'; + } + } + return $rtnVal; +} + +#------------------------------------------------------------------------------ +# Copy file attributes from one file to another +# Inputs: 0) ExifTool ref, 1) source file name, 2) destination file name +# Notes: eventually add support for extended attributes? +sub CopyFileAttrs($$$) +{ + my ($self, $src, $dst) = @_; + my ($mode, $uid, $gid) = (stat($src))[2, 4, 5]; + # copy file attributes unless we already set them + if (defined $mode and not defined $self->GetNewValue('FilePermissions')) { + eval { chmod($mode & 07777, $dst) }; + } + my $newUid = $self->GetNewValue('FileUserID'); + my $newGid = $self->GetNewValue('FileGroupID'); + if (defined $uid and defined $gid and (not defined $newUid or not defined $newGid)) { + defined $newGid and $gid = $newGid; + defined $newUid and $uid = $newUid; + eval { chown($uid, $gid, $dst) }; + } +} + +#------------------------------------------------------------------------------ +# Get new file path name +# Inputs: 0) existing name (may contain directory), +# 1) new file name, new directory, or new path (dir+name) +# Returns: new file path name +sub GetNewFileName($$) +{ + my ($oldName, $newName) = @_; + my ($dir, $name) = ($oldName =~ m{(.*/)(.*)}); + ($dir, $name) = ('', $oldName) unless defined $dir; + if ($newName =~ m{/$}) { + $newName = "$newName$name"; # change dir only + } elsif ($newName !~ m{/}) { + $newName = "$dir$newName"; # change name only if newname doesn't specify dir + } # else change dir and name + return $newName; +} + +#------------------------------------------------------------------------------ +# Get next available tag key +# Inputs: 0) hash reference (keys are tag keys), 1) tag name +# Returns: next available tag key +sub NextFreeTagKey($$) +{ + my ($info, $tag) = @_; + return $tag unless exists $$info{$tag}; + my $i; + for ($i=1; ; ++$i) { + my $key = "$tag ($i)"; + return $key unless exists $$info{$key}; + } +} + +#------------------------------------------------------------------------------ +# Reverse hash lookup +# Inputs: 0) value, 1) hash reference +# Returns: Hash key or undef if not found (plus flag for multiple matches in list context) +sub ReverseLookup($$) +{ + my ($val, $conv) = @_; + return undef unless defined $val; + my $multi; + if ($val =~ /^Unknown\s*\((.*)\)$/i) { + $val = $1; # was unknown + if ($val =~ /^0x([\da-fA-F]+)$/) { + # disable "Hexadecimal number > 0xffffffff non-portable" warning + local $SIG{'__WARN__'} = sub { }; + $val = hex($val); # convert hex value + } + } else { + my $qval = $val; + $qval =~ s/\s+$//; # remove trailing whitespace + $qval = quotemeta $qval; + my @patterns = ( + "^$qval\$", # exact match + "^(?i)$qval\$", # case-insensitive + "^(?i)$qval", # beginning of string + "(?i)$qval", # substring + ); + # hash entries to ignore in reverse lookup + my ($pattern, $found, $matches); +PAT: foreach $pattern (@patterns) { + $matches = scalar grep /$pattern/, values(%$conv); + next unless $matches; + # multiple matches are bad unless they were exact + if ($matches > 1 and $pattern !~ /\$$/) { + # don't match entries that we should ignore + foreach (keys %ignorePrintConv) { + --$matches if defined $$conv{$_} and $$conv{$_} =~ /$pattern/; + } + last if $matches > 1; + } + foreach (sort keys %$conv) { + next if $$conv{$_} !~ /$pattern/ or $ignorePrintConv{$_}; + $val = $_; + $found = 1; + last PAT; + } + } + unless ($found) { + # call OTHER conversion routine if available + if ($$conv{OTHER}) { + local $SIG{'__WARN__'} = \&SetWarning; + undef $evalWarning; + $val = &{$$conv{OTHER}}($val,1,$conv); + } else { + $val = undef; + } + $multi = 1 if $matches > 1; + } + } + return ($val, $multi) if wantarray; + return $val; +} + +#------------------------------------------------------------------------------ +# Return true if we are deleting or overwriting the specified tag +# Inputs: 0) ExifTool object ref, 1) new value hash reference +# 2) optional tag value (before RawConv) if deleting specific values +# Returns: >0 - tag should be overwritten +# =0 - the tag should be preserved +# <0 - not sure, we need the value to know +# Notes: $$nvHash{Value} is updated with the new value when shifting a value +sub IsOverwriting($$;$) +{ + my ($self, $nvHash, $val) = @_; + return 0 unless $nvHash; + # overwrite regardless if no DelValues specified + return 1 unless $$nvHash{DelValue}; + # never overwrite if DelValue list exists but is empty + my $shift = $$nvHash{Shift}; + return 0 unless @{$$nvHash{DelValue}} or defined $shift; + # return "don't know" if we don't have a value to test + return -1 unless defined $val; + # apply raw conversion if necessary + my $tagInfo = $$nvHash{TagInfo}; + my $conv = $$tagInfo{RawConv}; + if ($conv) { + local $SIG{'__WARN__'} = \&SetWarning; + undef $evalWarning; + if (ref $conv eq 'CODE') { + $val = &$conv($val, $self); + } else { + my ($priority, @grps); + my $tag = $$tagInfo{Name}; + #### eval RawConv ($self, $val, $tag, $tagInfo, $priority, @grps) + $val = eval $conv; + $@ and $evalWarning = $@; + } + return -1 unless defined $val; + } + # do not overwrite if only creating + return 0 if $$nvHash{CreateOnly}; + # apply time/number shift if necessary + if (defined $shift) { + my $shiftType = $$tagInfo{Shift}; + unless ($shiftType and $shiftType eq 'Time') { + unless (IsFloat($val)) { + # do the ValueConv to try to get a number + my $conv = $$tagInfo{ValueConv}; + if (defined $conv) { + local $SIG{'__WARN__'} = \&SetWarning; + undef $evalWarning; + if (ref $conv eq 'CODE') { + $val = &$conv($val, $self); + } elsif (not ref $conv) { + #### eval ValueConv ($val, $self) + $val = eval $conv; + $@ and $evalWarning = $@; + } + if ($evalWarning) { + $self->Warn("ValueConv $$tagInfo{Name}: " . CleanWarning()); + return 0; + } + } + unless (defined $val and IsFloat($val)) { + $self->Warn("Can't shift $$tagInfo{Name} (not a number)"); + return 0; + } + } + $shiftType = 'Number'; # allow any number to be shifted + } + require 'Image/ExifTool/Shift.pl'; + my $err = $self->ApplyShift($shiftType, $shift, $val, $nvHash); + if ($err) { + $self->Warn("$err when shifting $$tagInfo{Name}"); + return 0; + } + # ensure that the shifted value is valid and reformat if necessary + my $checkVal = $self->GetNewValue($nvHash); + return 0 unless defined $checkVal; + # don't bother overwriting if value is the same + return 0 if $val eq $$nvHash{Value}[0]; + return 1; + } + # return 1 if value matches a DelValue + my $delVal; + foreach $delVal (@{$$nvHash{DelValue}}) { + return 1 if $val eq $delVal; + } + return 0; +} + +#------------------------------------------------------------------------------ +# Get write group for specified tag +# Inputs: 0) new value hash reference +# Returns: Write group name +sub GetWriteGroup($) +{ + return $_[0]{WriteGroup}; +} + +#------------------------------------------------------------------------------ +# Get name of write group or family 1 group +# Inputs: 0) ExifTool ref, 1) tagInfo ref, 2) write group name +# Returns: Name of group for verbose message +sub GetWriteGroup1($$) +{ + my ($self, $tagInfo, $writeGroup) = @_; + return $writeGroup unless $writeGroup =~ /^(MakerNotes|XMP|Composite)$/; + return $self->GetGroup($tagInfo, 1); +} + +#------------------------------------------------------------------------------ +# Get new value hash for specified tagInfo/writeGroup +# Inputs: 0) ExifTool object reference, 1) reference to tag info hash +# 2) Write group name, 3) Options: 'delete' or 'create' new value hash +# 4) optional ProtectSaved value, 5) true if we are deleting a value +# Returns: new value hash reference for specified write group +# (or first new value hash in linked list if write group not specified) +# Notes: May return undef when 'create' is used with ProtectSaved +sub GetNewValueHash($$;$$$$) +{ + my ($self, $tagInfo, $writeGroup, $opts) = @_; + my $nvHash = $$self{NEW_VALUE}{$tagInfo}; + + my %opts; # quick lookup for options + $opts and $opts{$opts} = 1; + $writeGroup = '' unless defined $writeGroup; + + if ($writeGroup) { + # find the new value in the list with the specified write group + # (QuickTime and All are special cases because all group1 tags may be updated at once) + while ($nvHash and $$nvHash{WriteGroup} ne $writeGroup and + $$nvHash{WriteGroup} !~ /^(QuickTime|All)$/) + { + $nvHash = $$nvHash{Next}; + } + } + # remove this entry if deleting, or if creating a new entry and + # this entry is marked with "Save" flag + if (defined $nvHash and ($opts{'delete'} or ($opts{'create'} and $$nvHash{Save}))) { + my $protect = (defined $_[4] and defined $$nvHash{Save} and $$nvHash{Save} > $_[4]); + # this is a bit tricky: we want to add to a protected nvHash only if we + # are adding a conditional delete ($_[5] true or DelValue with no Shift) + # or accumulating List items (NoReplace true) + if ($protect and not ($opts{create} and ($$nvHash{NoReplace} or $_[5] or + ($$nvHash{DelValue} and not defined $$nvHash{Shift})))) + { + return undef; # honour ProtectSaved value by not writing this tag + } elsif ($opts{'delete'}) { + $self->RemoveNewValueHash($nvHash, $tagInfo); + undef $nvHash; + } else { + # save a copy of this new value hash + my %copy = %$nvHash; + # make copy of Value and DelValue lists + my $key; + foreach $key (keys %copy) { + next unless ref $copy{$key} eq 'ARRAY'; + $copy{$key} = [ @{$copy{$key}} ]; + } + my $saveHash = $$self{SAVE_NEW_VALUE}; + # add to linked list of saved new value hashes + $copy{Next} = $$saveHash{$tagInfo}; + $$saveHash{$tagInfo} = \%copy; + delete $$nvHash{Save}; # don't save it again + $$nvHash{AddBefore} = scalar @{$$nvHash{Value}} if $protect and $$nvHash{Value}; + } + } + if (not defined $nvHash and $opts{'create'}) { + # create a new entry + $nvHash = { + TagInfo => $tagInfo, + WriteGroup => $writeGroup, + IsNVH => 1, # set flag so we can recognize a new value hash + }; + # add entry to our NEW_VALUE hash + if ($$self{NEW_VALUE}{$tagInfo}) { + # add to end of linked list + my $lastHash = LastInList($$self{NEW_VALUE}{$tagInfo}); + $$lastHash{Next} = $nvHash; + } else { + $$self{NEW_VALUE}{$tagInfo} = $nvHash; + } + } + return $nvHash; +} + +#------------------------------------------------------------------------------ +# Load all tag tables +sub LoadAllTables() +{ + return if $loadedAllTables; + + # load all of our non-referenced tables (first our modules) + my $table; + foreach $table (@loadAllTables) { + my $tableName = "Image::ExifTool::$table"; + $tableName .= '::Main' unless $table =~ /:/; + GetTagTable($tableName); + } + # (then our special tables) + GetTagTable('Image::ExifTool::Extra'); + GetTagTable('Image::ExifTool::Composite'); + # recursively load all tables referenced by the current tables + my @tableNames = keys %allTables; + my %pushedTables; + while (@tableNames) { + $table = GetTagTable(shift @tableNames); + # call write proc if it exists in case it adds tags to the table + my $writeProc = $$table{WRITE_PROC}; + $writeProc and &$writeProc(); + # recursively scan through tables in subdirectories + foreach (TagTableKeys($table)) { + my @infoArray = GetTagInfoList($table,$_); + my $tagInfo; + foreach $tagInfo (@infoArray) { + my $subdir = $$tagInfo{SubDirectory} or next; + my $tableName = $$subdir{TagTable} or next; + # next if table already loaded or queued for loading + next if $allTables{$tableName} or $pushedTables{$tableName}; + push @tableNames, $tableName; # must scan this one too + $pushedTables{$tableName} = 1; + } + } + } + $loadedAllTables = 1; +} + +#------------------------------------------------------------------------------ +# Remove new value hash from linked list (and save if necessary) +# Inputs: 0) ExifTool object reference, 1) new value hash ref, 2) tagInfo ref +sub RemoveNewValueHash($$$) +{ + my ($self, $nvHash, $tagInfo) = @_; + my $firstHash = $$self{NEW_VALUE}{$tagInfo}; + if ($nvHash eq $firstHash) { + # remove first entry from linked list + if ($$nvHash{Next}) { + $$self{NEW_VALUE}{$tagInfo} = $$nvHash{Next}; + } else { + delete $$self{NEW_VALUE}{$tagInfo}; + } + } else { + # find the list element pointing to this hash + $firstHash = $$firstHash{Next} while $$firstHash{Next} ne $nvHash; + # remove from linked list + $$firstHash{Next} = $$nvHash{Next}; + } + # save the existing entry if necessary + if ($$nvHash{Save}) { + my $saveHash = $$self{SAVE_NEW_VALUE}; + # add to linked list of saved new value hashes + $$nvHash{Next} = $$saveHash{$tagInfo}; + $$saveHash{$tagInfo} = $nvHash; + } +} + +#------------------------------------------------------------------------------ +# Remove all new value entries for specified group +# Inputs: 0) ExifTool object reference, 1) group name +sub RemoveNewValuesForGroup($$) +{ + my ($self, $group) = @_; + + return unless $$self{NEW_VALUE}; + + # make list of all groups we must remove + my @groups = ( $group ); + push @groups, @{$removeGroups{$group}} if $removeGroups{$group}; + + my ($out, @keys, $hashKey); + $out = $$self{OPTIONS}{TextOut} if $$self{OPTIONS}{Verbose} > 1; + + # loop though all new values, and remove any in this group + @keys = keys %{$$self{NEW_VALUE}}; + foreach $hashKey (@keys) { + my $nvHash = $$self{NEW_VALUE}{$hashKey}; + # loop through each entry in linked list + for (;;) { + my $nextHash = $$nvHash{Next}; + my $tagInfo = $$nvHash{TagInfo}; + my ($grp0,$grp1) = $self->GetGroup($tagInfo); + my $wgrp = $$nvHash{WriteGroup}; + # use group1 if write group is not specific + $wgrp = $grp1 if $wgrp eq $grp0; + if (grep /^($grp0|$wgrp)$/i, @groups) { + $out and print $out "Removed new value for $wgrp:$$tagInfo{Name}\n"; + # remove from linked list + $self->RemoveNewValueHash($nvHash, $tagInfo); + } + $nvHash = $nextHash or last; + } + } +} + +#------------------------------------------------------------------------------ +# Get list of tagInfo hashes for all new data +# Inputs: 0) ExifTool object reference, 1) optional tag table pointer +# Returns: list of tagInfo hashes +sub GetNewTagInfoList($;$) +{ + my ($self, $tagTablePtr) = @_; + my @tagInfoList; + my $nv = $$self{NEW_VALUE}; + if ($nv) { + my $hashKey; + foreach $hashKey (keys %$nv) { + my $tagInfo = $$nv{$hashKey}{TagInfo}; + next if $tagTablePtr and $tagTablePtr ne $$tagInfo{Table}; + push @tagInfoList, $tagInfo; + } + } + return @tagInfoList; +} + +#------------------------------------------------------------------------------ +# Get hash of tagInfo references keyed on tagID for a specific table +# Inputs: 0) ExifTool object reference, 1-N) tag table pointers +# Returns: hash reference +# Notes: returns only one tagInfo ref for each conditional list +sub GetNewTagInfoHash($@) +{ + my $self = shift; + my (%tagInfoHash, $hashKey); + my $nv = $$self{NEW_VALUE}; + while ($nv) { + my $tagTablePtr = shift || last; + foreach $hashKey (keys %$nv) { + my $tagInfo = $$nv{$hashKey}{TagInfo}; + next if $tagTablePtr and $tagTablePtr ne $$tagInfo{Table}; + $tagInfoHash{$$tagInfo{TagID}} = $tagInfo; + } + } + return \%tagInfoHash; +} + +#------------------------------------------------------------------------------ +# Get a tagInfo/tagID hash for subdirectories we need to add +# Inputs: 0) ExifTool object reference, 1) parent tag table reference +# 2) parent directory name (taken from GROUP0 of tag table if not defined) +# Returns: Reference to Hash of subdirectory tagInfo references keyed by tagID +# (plus Reference to edit directory hash in list context) +sub GetAddDirHash($$;$) +{ + my ($self, $tagTablePtr, $parent) = @_; + $parent or $parent = $$tagTablePtr{GROUPS}{0}; + my $tagID; + my %addDirHash; + my %editDirHash; + my $addDirs = $$self{ADD_DIRS}; + my $editDirs = $$self{EDIT_DIRS}; + foreach $tagID (TagTableKeys($tagTablePtr)) { + my @infoArray = GetTagInfoList($tagTablePtr,$tagID); + my $tagInfo; + foreach $tagInfo (@infoArray) { + next unless $$tagInfo{SubDirectory}; + # get name for this sub directory + # (take directory name from SubDirectory DirName if it exists, + # otherwise Group0 name of SubDirectory TagTable or tag Group1 name) + my $dirName = $$tagInfo{SubDirectory}{DirName}; + unless ($dirName) { + # use tag name for directory name and save for next time + $dirName = $$tagInfo{Name}; + $$tagInfo{SubDirectory}{DirName} = $dirName; + } + # save this directory information if we are writing it + if ($$editDirs{$dirName} and $$editDirs{$dirName} eq $parent) { + $editDirHash{$tagID} = $tagInfo; + $addDirHash{$tagID} = $tagInfo if $$addDirs{$dirName}; + } + } + } + return (\%addDirHash, \%editDirHash) if wantarray; + return \%addDirHash; +} + +#------------------------------------------------------------------------------ +# Get localized version of tagInfo hash (used by MIE, XMP, PNG and QuickTime) +# Inputs: 0) tagInfo hash ref, 1) locale code (eg. "en_CA" for MIE) +# Returns: new tagInfo hash ref, or undef if invalid +# - sets LangCode member in new tagInfo +sub GetLangInfo($$) +{ + my ($tagInfo, $langCode) = @_; + # make a new tagInfo hash for this locale + my $table = $$tagInfo{Table}; + my $tagID = $$tagInfo{TagID} . '-' . $langCode; + my $langInfo = $$table{$tagID}; + unless ($langInfo) { + # make a new tagInfo entry for this locale + $langInfo = { + %$tagInfo, + Name => $$tagInfo{Name} . '-' . $langCode, + Description => Image::ExifTool::MakeDescription($$tagInfo{Name}) . + " ($langCode)", + LangCode => $langCode, + SrcTagInfo => $tagInfo, # save reference to original tagInfo + }; + AddTagToTable($table, $tagID, $langInfo); + } + return $langInfo; +} + +#------------------------------------------------------------------------------ +# initialize ADD_DIRS and EDIT_DIRS hashes for all directories that need +# to be created or will have tags changed in them +# Inputs: 0) ExifTool object reference, 1) file type string (or map hash ref) +# 2) preferred family 0 group name for creating tags +# Notes: +# - the ADD_DIRS and EDIT_DIRS keys are the directory names, and the values +# are the names of the parent directories (undefined for a top-level directory) +# - also initializes FORCE_WRITE lookup +sub InitWriteDirs($$;$) +{ + my ($self, $fileType, $preferredGroup) = @_; + my $editDirs = $$self{EDIT_DIRS} = { }; + my $addDirs = $$self{ADD_DIRS} = { }; + my $fileDirs = $dirMap{$fileType}; + unless ($fileDirs) { + return unless ref $fileType eq 'HASH'; + $fileDirs = $fileType; + } + my @tagInfoList = $self->GetNewTagInfoList(); + my ($tagInfo, $nvHash); + + # save the preferred group + $$self{PreferredGroup} = $preferredGroup; + + foreach $tagInfo (@tagInfoList) { + # cycle through all hashes in linked list + for ($nvHash=$self->GetNewValueHash($tagInfo); $nvHash; $nvHash=$$nvHash{Next}) { + # are we creating this tag? (otherwise just deleting or editing it) + my $isCreating = $$nvHash{IsCreating}; + if ($isCreating) { + # if another group is taking priority, only create + # directory if specifically adding tags to this group + # or if this tag isn't being added to the priority group + $isCreating = 0 if $preferredGroup and + $preferredGroup ne $self->GetGroup($tagInfo, 0) and + $$nvHash{CreateGroups}{$preferredGroup}; + } else { + # creating this directory if any tag is preferred and has a value + $isCreating = 1 if ($preferredGroup and $$nvHash{Value} and + $preferredGroup eq $self->GetGroup($tagInfo, 0)) and + not $$nvHash{EditOnly}; + } + # tag belongs to directory specified by WriteGroup, or by + # the Group0 name if WriteGroup not defined + my $dirName = $$nvHash{WriteGroup}; + # remove MIE copy number(s) if they exist + if ($dirName =~ /^MIE\d*(-[a-z]+)?\d*$/i) { + $dirName = 'MIE' . ($1 || ''); + } + my @dirNames; + # allow a group name of '*' to force writing EXIF/IPTC/XMP (ForceWrite tag) + if ($dirName eq '*' and $$nvHash{Value}) { + my $val = $$nvHash{Value}[0]; + if ($val) { + foreach (qw(EXIF IPTC XMP FixBase)) { + next unless $val =~ /\b($_|All)\b/i; + push @dirNames, $_; + push @dirNames, 'EXIF' if $_ eq 'FixBase'; + $$self{FORCE_WRITE}{$_} = 1; + } + } + $dirName = shift @dirNames; + } + while ($dirName) { + my $parent = $$fileDirs{$dirName}; + if (ref $parent) { + push @dirNames, reverse @$parent; + $parent = pop @dirNames; + } + $$editDirs{$dirName} = $parent; + $$addDirs{$dirName} = $parent if $isCreating and $isCreating != 2; + $dirName = $parent || shift @dirNames + } + } + } + if (%{$$self{DEL_GROUP}}) { + # add delete groups to list of edited groups + foreach (keys %{$$self{DEL_GROUP}}) { + next if /^-/; # ignore excluded groups + my $dirName = $_; + # translate necessary group 0 names + $dirName = $translateWriteGroup{$dirName} if $translateWriteGroup{$dirName}; + # convert XMP group 1 names + $dirName = 'XMP' if $dirName =~ /^XMP-/; + my @dirNames; + while ($dirName) { + my $parent = $$fileDirs{$dirName}; + if (ref $parent) { + push @dirNames, reverse @$parent; + $parent = pop @dirNames; + } + $$editDirs{$dirName} = $parent; + $dirName = $parent || shift @dirNames + } + } + } + # special case to edit JFIF to get resolutions if editing EXIF information + if ($$editDirs{IFD0} and $$fileDirs{JFIF}) { + $$editDirs{JFIF} = 'IFD1'; + $$editDirs{APP0} = undef; + } + + if ($$self{OPTIONS}{Verbose}) { + my $out = $$self{OPTIONS}{TextOut}; + print $out " Editing tags in: "; + foreach (sort keys %$editDirs) { print $out "$_ "; } + print $out "\n"; + return unless $$self{OPTIONS}{Verbose} > 1; + print $out " Creating tags in: "; + foreach (sort keys %$addDirs) { print $out "$_ "; } + print $out "\n"; + } +} + +#------------------------------------------------------------------------------ +# Write an image directory +# Inputs: 0) ExifTool object reference, 1) source directory information reference +# 2) tag table reference, 3) optional reference to writing procedure +# Returns: New directory data or undefined on error (or empty string to delete directory) +sub WriteDirectory($$$;$) +{ + my ($self, $dirInfo, $tagTablePtr, $writeProc) = @_; + my ($out, $nvHash); + + $tagTablePtr or return undef; + $out = $$self{OPTIONS}{TextOut} if $$self{OPTIONS}{Verbose}; + # set directory name from default group0 name if not done already + my $dirName = $$dirInfo{DirName}; + my $dataPt = $$dirInfo{DataPt}; + my $grp0 = $$tagTablePtr{GROUPS}{0}; + $dirName or $dirName = $$dirInfo{DirName} = $grp0; + if (%{$$self{DEL_GROUP}}) { + my $delGroup = $$self{DEL_GROUP}; + # delete entire directory if specified + my $grp1 = $dirName; + my $delFlag = ($$delGroup{$grp0} or $$delGroup{$grp1}); + if ($delFlag) { + unless ($blockExifTypes{$$self{FILE_TYPE}}) { + # restrict delete logic to prevent entire tiff image from being killed + # (don't allow IFD0 to be deleted, and delete only ExifIFD if EXIF specified) + if ($$self{FILE_TYPE} eq 'PSD') { + # don't delete Photoshop directories from PSD image + undef $grp1 if $grp0 eq 'Photoshop'; + } elsif ($$self{FILE_TYPE} =~ /^(EPS|PS)$/) { + # allow anything to be deleted from PostScript files + } elsif ($grp1 eq 'IFD0') { + my $type = $$self{TIFF_TYPE} || $$self{FILE_TYPE}; + $$delGroup{IFD0} and $self->Warn("Can't delete IFD0 from $type",1); + undef $grp1; + } elsif ($grp0 eq 'EXIF' and $$delGroup{$grp0}) { + undef $grp1 unless $$delGroup{$grp1} or $grp1 eq 'ExifIFD'; + } + } + if ($grp1) { + if ($dataPt or $$dirInfo{RAF}) { + ++$$self{CHANGED}; + $out and print $out " Deleting $grp1\n"; + # can no longer validate TIFF_END if deleting an entire IFD + delete $$self{TIFF_END} if $dirName =~ /IFD/; + } + # don't add back into the wrong location + my $right = $$self{ADD_DIRS}{$grp1}; + # (take care because EXIF directory name may be either EXIF or IFD0, + # but IFD0 will be the one that appears in the directory map) + $right = $$self{ADD_DIRS}{IFD0} if not $right and $grp1 eq 'EXIF'; + if ($delFlag == 2 and $right) { + # also check grandparent because some routines create 2 levels in 1 + my $right2 = $$self{ADD_DIRS}{$right} || ''; + my $parent = $$dirInfo{Parent}; + if (not $parent or $parent eq $right or $parent eq $right2) { + # prevent duplicate directories from being recreated at the same path + my $path = join '-', @{$$self{PATH}}, $dirName; + $$self{Recreated} or $$self{Recreated} = { }; + if ($$self{Recreated}{$path}) { + my $p = $parent ? " in $parent" : ''; + $self->Warn("Not recreating duplicate $grp1$p",1); + return ''; + } + $$self{Recreated}{$path} = 1; + # empty the directory + my $data = ''; + $$dirInfo{DataPt} = \$data; + $$dirInfo{DataLen} = 0; + $$dirInfo{DirStart} = 0; + $$dirInfo{DirLen} = 0; + delete $$dirInfo{RAF}; + delete $$dirInfo{Base}; + delete $$dirInfo{DataPos}; + } else { + $self->Warn("Not recreating $grp1 in $parent (should be in $right)",1); + return ''; + } + } else { + return '' unless $$dirInfo{NoDelete}; + } + } + } + } + # use default proc from tag table if no proc specified + $writeProc or $writeProc = $$tagTablePtr{WRITE_PROC} or return undef; + + # are we rewriting a pre-existing directory? + my $isRewriting = ($$dirInfo{DirLen} or (defined $dataPt and length $$dataPt) or $$dirInfo{RAF}); + + # copy or delete new directory as a block if specified + my $blockName = $dirName; + $blockName = 'EXIF' if $blockName eq 'IFD0'; + my $tagInfo = $Image::ExifTool::Extra{$blockName} || $$dirInfo{TagInfo}; + while ($tagInfo and ($nvHash = $$self{NEW_VALUE}{$tagInfo}) and + $self->IsOverwriting($nvHash) and not ($$nvHash{CreateOnly} and $isRewriting)) + { + # protect against writing EXIF to wrong file types, etc + if ($blockName eq 'EXIF') { + unless ($blockExifTypes{$$self{FILE_TYPE}}) { + $self->Warn("Can't write EXIF as a block to $$self{FILE_TYPE} file"); + last; + } + # this can happen if we call WriteDirectory for an EXIF directory without going + # through WriteTIFF as the WriteProc (which happens if conditionally replacing + # the EXIF block and the condition fails), but we never want to do a block write + # in this case because the EXIF block would end up with two TIFF headers + last unless $writeProc eq \&Image::ExifTool::WriteTIFF; + } + last unless $self->IsOverwriting($nvHash, $dataPt ? $$dataPt : ''); + my $verb = 'Writing'; + my $newVal = $self->GetNewValue($nvHash); + unless (defined $newVal and length $newVal) { + return '' unless $dataPt or $$dirInfo{RAF}; # nothing to do if block never existed + $verb = 'Deleting'; + $newVal = ''; + } + $$dirInfo{BlockWrite} = 1; # set flag indicating we did a block write + $out and print $out " $verb $blockName as a block\n"; + ++$$self{CHANGED}; + return $newVal; + } + # guard against writing the same directory twice + if (defined $dataPt and defined $$dirInfo{DirStart} and defined $$dirInfo{DataPos}) { + my $addr = $$dirInfo{DirStart} + $$dirInfo{DataPos} + ($$dirInfo{Base}||0) + $$self{BASE}; + # (Phase One P25 IIQ files have ICC_Profile duplicated in IFD0 and IFD1) + if ($$self{PROCESSED}{$addr} and ($dirName ne 'ICC_Profile' or $$self{TIFF_TYPE} ne 'IIQ')) { + if (defined $$dirInfo{DirLen} and not $$dirInfo{DirLen} and $dirName ne $$self{PROCESSED}{$addr}) { + # it is hypothetically possible to have 2 different directories + # with the same address if one has a length of zero + } elsif ($self->Error("$dirName pointer references previous $$self{PROCESSED}{$addr} directory", 2)) { + return undef; + } else { + $self->Warn("Deleting duplicate $dirName directory"); + $out and print $out " Deleting $dirName\n"; + # delete the duplicate directory (don't recreate it when writing new + # tags to prevent propagating a duplicate IFD in cases like when the + # same ExifIFD exists in both IFD0 and IFD1) + return ''; + } + } else { + $$self{PROCESSED}{$addr} = $dirName; + } + } + my $oldDir = $$self{DIR_NAME}; + my @save = @$self{'Compression','SubfileType'}; + my $name; + if ($out) { + $name = ($dirName eq 'MakerNotes' and $$dirInfo{TagInfo}) ? + $$dirInfo{TagInfo}{Name} : $dirName; + if (not defined $oldDir or $oldDir ne $name) { + my $verb = $isRewriting ? 'Rewriting' : 'Creating'; + print $out " $verb $name\n"; + } + } + my $saveOrder = GetByteOrder(); + my $oldChanged = $$self{CHANGED}; + $$self{DIR_NAME} = $dirName; + push @{$$self{PATH}}, $dirName; + $$dirInfo{IsWriting} = 1; + my $newData = &$writeProc($self, $dirInfo, $tagTablePtr); + pop @{$$self{PATH}}; + # nothing changed if error occurred or nothing was created + $$self{CHANGED} = $oldChanged unless defined $newData and (length($newData) or $isRewriting); + $$self{DIR_NAME} = $oldDir; + @$self{'Compression','SubfileType'} = @save; + SetByteOrder($saveOrder); + print $out " Deleting $name\n" if $out and defined $newData and not length $newData; + return $newData; +} + +#------------------------------------------------------------------------------ +# Uncommon utility routines to for reading binary data values +# Inputs: 0) data reference, 1) offset into data +sub Get64s($$) +{ + my ($dataPt, $pos) = @_; + my $pt = GetByteOrder() eq 'MM' ? 0 : 4; # get position of high word + my $hi = Get32s($dataPt, $pos + $pt); # preserve sign bit of high word + my $lo = Get32u($dataPt, $pos + 4 - $pt); + return $hi * 4294967296 + $lo; +} +sub Get64u($$) +{ + my ($dataPt, $pos) = @_; + my $pt = GetByteOrder() eq 'MM' ? 0 : 4; # get position of high word + my $hi = Get32u($dataPt, $pos + $pt); # (unsigned this time) + my $lo = Get32u($dataPt, $pos + 4 - $pt); + return $hi * 4294967296 + $lo; +} +sub GetFixed64s($$) +{ + my ($dataPt, $pos) = @_; + my $val = Get64s($dataPt, $pos) / 4294967296; + # remove insignificant digits + return int($val * 1e10 + ($val>0 ? 0.5 : -0.5)) / 1e10; +} +# Decode extended 80-bit float used by Apple SANE and Intel 8087 +# (note: different than the IEEE standard 80-bit float) +sub GetExtended($$) +{ + my ($dataPt, $pos) = @_; + my $pt = GetByteOrder() eq 'MM' ? 0 : 2; # get position of exponent + my $exp = Get16u($dataPt, $pos + $pt); + my $sig = Get64u($dataPt, $pos + 2 - $pt); # get significand as int64u + my $sign = $exp & 0x8000 ? -1 : 1; + $exp = ($exp & 0x7fff) - 16383 - 63; # (-63 to fractionalize significand) + return $sign * $sig * 2 ** $exp; +} + +#------------------------------------------------------------------------------ +# Dump data in hex and ASCII to console +# Inputs: 0) data reference, 1) length or undef, 2-N) Options: +# Options: Start => offset to start of data (default=0) +# Addr => address to print for data start (default=DataPos+Base+Start) +# DataPos => position of data within block (relative to Base) +# Base => base offset for pointers from start of file +# Width => width of printout (bytes, default=16) +# Prefix => prefix to print at start of line (default='') +# MaxLen => maximum length to dump +# Out => output file reference +# Len => data length +sub HexDump($;$%) +{ + my $dataPt = shift; + my $len = shift; + my %opts = @_; + my $start = $opts{Start} || 0; + my $addr = $opts{Addr}; + my $wid = $opts{Width} || 16; + my $prefix = $opts{Prefix} || ''; + my $out = $opts{Out} || \*STDOUT; + my $maxLen = $opts{MaxLen}; + my $datLen = length($$dataPt) - $start; + my $more; + $len = $opts{Len} if defined $opts{Len}; + + $addr = $start + ($opts{DataPos} || 0) + ($opts{Base} || 0) unless defined $addr; + $len = $datLen unless defined $len; + if ($maxLen and $len > $maxLen) { + # print one line less to allow for $more line below + $maxLen = int(($maxLen - 1) / $wid) * $wid; + $more = $len - $maxLen; + $len = $maxLen; + } + if ($len > $datLen) { + print $out "$prefix Warning: Attempted dump outside data\n"; + print $out "$prefix ($len bytes specified, but only $datLen available)\n"; + $len = $datLen; + } + my $format = sprintf("%%-%ds", $wid * 3); + my $tmpl = 'H2' x $wid; # ('(H2)*' would have been nice, but older perl versions don't support it) + my $i; + for ($i=0; $i<$len; $i+=$wid) { + $wid > $len-$i and $wid = $len-$i, $tmpl = 'H2' x $wid; + printf $out "$prefix%8.4x: ", $addr+$i; + my $dat = substr($$dataPt, $i+$start, $wid); + my $s = join(' ', unpack($tmpl, $dat)); + printf $out $format, $s; + $dat =~ tr /\x00-\x1f\x7f-\xff/./; + print $out "[$dat]\n"; + } + $more and print $out "$prefix [snip $more bytes]\n"; +} + +#------------------------------------------------------------------------------ +# Print verbose tag information +# Inputs: 0) ExifTool object reference, 1) tag ID +# 2) tag info reference (or undef) +# 3-N) extra parms: +# Parms: Index => Index of tag in menu (starting at 0) +# Value => Tag value +# DataPt => reference to value data block +# DataPos => location of data block in file +# Base => base added to all offsets +# Size => length of value data within block +# Format => value format string +# Count => number of values +# Extra => Extra Verbose=2 information to put after tag number +# Table => Reference to tag table +# --> plus any of these HexDump() options: Start, Addr, Width +sub VerboseInfo($$$%) +{ + my ($self, $tagID, $tagInfo, %parms) = @_; + my $verbose = $$self{OPTIONS}{Verbose}; + my $out = $$self{OPTIONS}{TextOut}; + my ($tag, $line, $hexID); + + # generate hex number if tagID is numerical + if (defined $tagID) { + $tagID =~ /^\d+$/ and $hexID = sprintf("0x%.4x", $tagID); + } else { + $tagID = 'Unknown'; + } + # get tag name + if ($tagInfo and $$tagInfo{Name}) { + $tag = $$tagInfo{Name}; + } else { + my $prefix; + $prefix = $parms{Table}{TAG_PREFIX} if $parms{Table}; + if ($prefix or $hexID) { + $prefix = 'Unknown' unless $prefix; + $tag = $prefix . '_' . ($hexID ? $hexID : $tagID); + } else { + $tag = $tagID; + } + } + my $dataPt = $parms{DataPt}; + my $size = $parms{Size}; + $size = length $$dataPt unless defined $size or not $dataPt; + my $indent = $$self{INDENT}; + + # Level 1: print tag/value information + $line = $indent; + my $index = $parms{Index}; + if (defined $index) { + $line .= $index . ') '; + $line .= ' ' if length($index) < 2; + $indent .= ' '; # indent everything else to align with tag name + } + $line .= $tag; + if ($tagInfo and $$tagInfo{SubDirectory}) { + $line .= ' (SubDirectory) -->'; + } else { + my $maxLen = 90 - length($line); + my $val = $parms{Value}; + if (defined $val) { + $val = '[' . join(',',@$val) . ']' if ref $val eq 'ARRAY'; + $line .= ' = ' . $self->Printable($val, $maxLen); + } elsif ($dataPt) { + my $start = $parms{Start} || 0; + $line .= ' = ' . $self->Printable(substr($$dataPt,$start,$size), $maxLen); + } + } + print $out "$line\n"; + + # Level 2: print detailed information about the tag + if ($verbose > 1 and ($parms{Extra} or $parms{Format} or + $parms{DataPt} or defined $size or $tagID =~ /\//)) + { + $line = $indent . '- Tag '; + if ($hexID) { + $line .= $hexID; + } else { + $tagID =~ s/([\0-\x1f\x7f-\xff])/sprintf('\\x%.2x',ord $1)/ge; + $line .= "'${tagID}'"; + } + $line .= $parms{Extra} if defined $parms{Extra}; + my $format = $parms{Format}; + if ($format or defined $size) { + $line .= ' ('; + if (defined $size) { + $line .= "$size bytes"; + $line .= ', ' if $format; + } + if ($format) { + $line .= $format; + $line .= '['.$parms{Count}.']' if $parms{Count}; + } + $line .= ')'; + } + $line .= ':' if $verbose > 2 and $parms{DataPt}; + print $out "$line\n"; + } + + # Level 3: do hex dump of value + if ($verbose > 2 and $parms{DataPt} and (not $tagInfo or not $$tagInfo{ReadFromRAF})) { + $parms{Out} = $out; + $parms{Prefix} = $indent; + # limit dump length if Verbose < 5 + $parms{MaxLen} = $verbose == 3 ? 96 : 2048 if $verbose < 5; + HexDump($dataPt, $size, %parms); + } +} + +#------------------------------------------------------------------------------ +# Dump trailer information +# Inputs: 0) ExifTool object ref, 1) dirInfo hash (RAF, DirName, DataPos, DirLen) +# Notes: Restores current file position before returning +sub DumpTrailer($$) +{ + my ($self, $dirInfo) = @_; + my $raf = $$dirInfo{RAF}; + my $curPos = $raf->Tell(); + my $trailer = $$dirInfo{DirName} || 'Unknown'; + my $pos = $$dirInfo{DataPos}; + my $verbose = $$self{OPTIONS}{Verbose}; + my $htmlDump = $$self{HTML_DUMP}; + my ($buff, $buf2); + my $size = $$dirInfo{DirLen}; + $pos = $curPos unless defined $pos; + + # get full trailer size if not specified + for (;;) { + unless ($size) { + $raf->Seek(0, 2) or last; + $size = $raf->Tell() - $pos; + last unless $size; + } + $raf->Seek($pos, 0) or last; + if ($htmlDump) { + my $num = $raf->Read($buff, $size) or return; + my $desc = "$trailer trailer"; + $desc = "[$desc]" if $trailer eq 'Unknown'; + $self->HDump($pos, $num, $desc, undef, 0x08); + last; + } + my $out = $$self{OPTIONS}{TextOut}; + printf $out "$trailer trailer (%d bytes at offset 0x%.4x):\n", $size, $pos; + last unless $verbose > 2; + my $num = $size; # number of bytes to read + # limit size if not very verbose + if ($verbose < 5) { + my $limit = $verbose < 4 ? 96 : 512; + $num = $limit if $num > $limit; + } + $raf->Read($buff, $num) == $num or return; + # read the end of the trailer too if not done already + if ($size > 2 * $num) { + $raf->Seek($pos + $size - $num, 0); + $raf->Read($buf2, $num); + } elsif ($size > $num) { + $raf->Seek($pos + $num, 0); + $raf->Read($buf2, $size - $num); + $buff .= $buf2; + undef $buf2; + } + HexDump(\$buff, undef, Addr => $pos, Out => $out); + if (defined $buf2) { + print $out " [snip ", $size - $num * 2, " bytes]\n"; + HexDump(\$buf2, undef, Addr => $pos + $size - $num, Out => $out); + } + last; + } + $raf->Seek($curPos, 0); +} + +#------------------------------------------------------------------------------ +# Dump unknown trailer information +# Inputs: 0) ExifTool ref, 1) dirInfo ref (with RAF, DataPos and DirLen defined) +# Notes: changes dirInfo elements +sub DumpUnknownTrailer($$) +{ + my ($self, $dirInfo) = @_; + my $pos = $$dirInfo{DataPos}; + my $endPos = $pos + $$dirInfo{DirLen}; + # account for preview/MPF image trailer + my $prePos = $$self{VALUE}{PreviewImageStart} || $$self{PreviewImageStart}; + my $preLen = $$self{VALUE}{PreviewImageLength} || $$self{PreviewImageLength}; + my $tag = 'PreviewImage'; + my $mpImageNum = 0; + my (%image, $lastOne); + for (;;) { + # add to Preview block list if valid and in the trailer + $image{$prePos} = [$tag, $preLen] if $prePos and $preLen and $prePos+$preLen > $pos; + last if $lastOne; # checked all images + # look for MPF images (in the the proper order) + ++$mpImageNum; + $prePos = $$self{VALUE}{"MPImageStart ($mpImageNum)"}; + if (defined $prePos) { + $preLen = $$self{VALUE}{"MPImageLength ($mpImageNum)"}; + } else { + $prePos = $$self{VALUE}{'MPImageStart'}; + $preLen = $$self{VALUE}{'MPImageLength'}; + $lastOne = 1; + } + $tag = "MPImage$mpImageNum"; + } + # dump trailer sections in order + $image{$endPos} = [ '', 0 ]; # add terminator "image" + foreach $prePos (sort { $a <=> $b } keys %image) { + if ($pos < $prePos) { + # dump unknown trailer data + $$dirInfo{DirName} = 'Unknown'; + $$dirInfo{DataPos} = $pos; + $$dirInfo{DirLen} = $prePos - $pos; + $self->DumpTrailer($dirInfo); + } + ($tag, $preLen) = @{$image{$prePos}}; + last unless $preLen; + # dump image if verbose (it is htmlDump'd by ExtractImage) + if ($$self{OPTIONS}{Verbose}) { + $$dirInfo{DirName} = $tag; + $$dirInfo{DataPos} = $prePos; + $$dirInfo{DirLen} = $preLen; + $self->DumpTrailer($dirInfo); + } + $pos = $prePos + $preLen; + } +} + +#------------------------------------------------------------------------------ +# Find last element in linked list +# Inputs: 0) element in list +# Returns: Last element in list +sub LastInList($) +{ + my $element = shift; + while ($$element{Next}) { + $element = $$element{Next}; + } + return $element; +} + +#------------------------------------------------------------------------------ +# Print verbose value while writing +# Inputs: 0) ExifTool object ref, 1) heading "eg. '+ IPTC:Keywords', +# 2) value, 3) [optional] extra text after value +sub VerboseValue($$$;$) +{ + return unless $_[0]{OPTIONS}{Verbose} > 1; + my ($self, $str, $val, $xtra) = @_; + my $out = $$self{OPTIONS}{TextOut}; + $xtra or $xtra = ''; + my $maxLen = 81 - length($str) - length($xtra); + $val = $self->Printable($val, $maxLen); + print $out " $str = '${val}'$xtra\n"; +} + +#------------------------------------------------------------------------------ +# Pack Unicode numbers into UTF8 string +# Inputs: 0-N) list of Unicode numbers +# Returns: Packed UTF-8 string +sub PackUTF8(@) +{ + my @out; + while (@_) { + my $ch = pop; + unshift(@out, $ch), next if $ch < 0x80; + unshift(@out, 0x80 | ($ch & 0x3f)); + $ch >>= 6; + unshift(@out, 0xc0 | $ch), next if $ch < 0x20; + unshift(@out, 0x80 | ($ch & 0x3f)); + $ch >>= 6; + unshift(@out, 0xe0 | $ch), next if $ch < 0x10; + unshift(@out, 0x80 | ($ch & 0x3f)); + $ch >>= 6; + unshift(@out, 0xf0 | ($ch & 0x07)); + } + return pack('C*', @out); +} + +#------------------------------------------------------------------------------ +# Unpack numbers from UTF8 string +# Inputs: 0) UTF-8 string +# Returns: List of Unicode numbers (sets $evalWarning on error) +sub UnpackUTF8($) +{ + my (@out, $pos); + pos($_[0]) = $pos = 0; # start at beginning of string + for (;;) { + my ($ch, $newPos, $val, $byte); + if ($_[0] =~ /([\x80-\xff])/g) { + $ch = ord($1); + $newPos = pos($_[0]) - 1; + } else { + $newPos = length $_[0]; + } + # unpack 7-bit characters + my $len = $newPos - $pos; + push @out, unpack("x${pos}C$len",$_[0]) if $len; + last unless defined $ch; + $pos = $newPos + 1; + # minimum lead byte for 2-byte sequence is 0xc2 (overlong sequences + # not allowed), 0xf8-0xfd are restricted by RFC 3629 (no 5 or 6 byte + # sequences), and 0xfe and 0xff are not valid in UTF-8 strings + if ($ch < 0xc2 or $ch >= 0xf8) { + push @out, ord('?'); # invalid UTF-8 + $evalWarning = 'Bad UTF-8'; + next; + } + # decode 2, 3 and 4-byte sequences + my $n = 1; + if ($ch < 0xe0) { + $val = $ch & 0x1f; # 2-byte sequence + } elsif ($ch < 0xf0) { + $val = $ch & 0x0f; # 3-byte sequence + ++$n; + } else { + $val = $ch & 0x07; # 4-byte sequence + $n += 2; + } + unless ($_[0] =~ /\G([\x80-\xbf]{$n})/g) { + pos($_[0]) = $pos; # restore position + push @out, ord('?'); # invalid UTF-8 + $evalWarning = 'Bad UTF-8'; + next; + } + foreach $byte (unpack 'C*', $1) { + $val = ($val << 6) | ($byte & 0x3f); + } + push @out, $val; # save Unicode character value + $pos += $n; # position at end of UTF-8 character + } + return @out; +} + +#------------------------------------------------------------------------------ +# Generate a new, random GUID +# Inputs: <none> +# Returns: GUID string +my $guidCount; +sub NewGUID() +{ + my @tm = localtime time; + $guidCount = 0 unless defined $guidCount and ++$guidCount < 0x100; + return sprintf('%.4d%.2d%.2d%.2d%.2d%.2d%.2X%.4X%.4X%.4X%.4X', + $tm[5]+1900, $tm[4]+1, $tm[3], $tm[2], $tm[1], $tm[0], $guidCount, + $$ & 0xffff, rand(0x10000), rand(0x10000), rand(0x10000)); +} + +#------------------------------------------------------------------------------ +# Make TIFF header for raw data +# Inputs: 0) width, 1) height, 2) num colour components, 3) bits, 4) resolution +# 5) color-map data for palette-color image (8 or 16 bit) +# Returns: TIFF header +# Notes: Multi-byte data must be little-endian +sub MakeTiffHeader($$$$;$$) +{ + my ($w, $h, $cols, $bits, $res, $cmap) = @_; + $res or $res = 72; + my $saveOrder = GetByteOrder(); + SetByteOrder('II'); + if (not $cmap) { + $cmap = ''; + } elsif (length $cmap == 3 * 2**$bits) { + # convert to short + $cmap = pack 'v*', map { $_ | ($_<<8) } unpack 'C*', $cmap; + } elsif (length $cmap != 6 * 2**$bits) { + $cmap = ''; + } + my $cmo = $cmap ? 12 : 0; # offset due to ColorMap IFD entry + my $hdr = + "\x49\x49\x2a\0\x08\0\0\0\x0e\0" . # 0x00 14 menu entries: + "\xfe\x00\x04\0\x01\0\0\0\x00\0\0\0" . # 0x0a SubfileType = 0 + "\x00\x01\x04\0\x01\0\0\0" . Set32u($w) . # 0x16 ImageWidth + "\x01\x01\x04\0\x01\0\0\0" . Set32u($h) . # 0x22 ImageHeight + "\x02\x01\x03\0" . Set32u($cols) . # 0x2e BitsPerSample + Set32u($cols == 1 ? $bits : 0xb6 + $cmo) . + "\x03\x01\x03\0\x01\0\0\0\x01\0\0\0" . # 0x3a Compression = 1 + "\x06\x01\x03\0\x01\0\0\0" . # 0x46 PhotometricInterpretation + Set32u($cmap ? 3 : $cols == 1 ? 1 : 2) . + "\x11\x01\x04\0\x01\0\0\0" . # 0x52 StripOffsets + Set32u(0xcc + $cmo + length($cmap)) . + "\x15\x01\x03\0\x01\0\0\0" . Set32u($cols) . # 0x5e SamplesPerPixel + "\x16\x01\x04\0\x01\0\0\0" . Set32u($h) . # 0x6a RowsPerStrip + "\x17\x01\x04\0\x01\0\0\0" . # 0x76 StripByteCounts + Set32u($w * $h * $cols * int(($bits+7)/8)) . + "\x1a\x01\x05\0\x01\0\0\0" . Set32u(0xbc + $cmo) . # 0x82 XResolution + "\x1b\x01\x05\0\x01\0\0\0" . Set32u(0xc4 + $cmo) . # 0x8e YResolution + "\x1c\x01\x03\0\x01\0\0\0\x01\0\0\0" . # 0x9a PlanarConfiguration = 1 + "\x28\x01\x03\0\x01\0\0\0\x02\0\0\0" . # 0xa6 ResolutionUnit = 2 + ($cmap ? # 0xb2 ColorMap [optional] + "\x40\x01\x03\0" . Set32u(3 * 2**$bits) . "\xd8\0\0\0" : '') . + "\0\0\0\0" . # 0xb2+$cmo (no IFD1) + (Set16u($bits) x 3) . # 0xb6+$cmo BitsPerSample value + Set32u($res) . "\x01\0\0\0" . # 0xbc+$cmo XResolution = 72 + Set32u($res) . "\x01\0\0\0" . # 0xc4+$cmo YResolution = 72 + $cmap; # 0xcc or 0xd8 (cmap and data go here) + SetByteOrder($saveOrder); + return $hdr; +} + +#------------------------------------------------------------------------------ +# Return current time in EXIF format +# Inputs: 0) [optional] ExifTool ref, 1) flag to include timezone (0 to disable, +# undef or 1 to include) +# Returns: time string +# - a consistent value is returned for each processed file +sub TimeNow(;$$) +{ + my ($self, $tzFlag) = @_; + my $timeNow; + ref $self or $tzFlag = $self, $self = { }; + if ($$self{Now}) { + $timeNow = $$self{Now}[0]; + } else { + my $time = time(); + my @tm = localtime $time; + my $tz = TimeZoneString(\@tm, $time); + $timeNow = sprintf("%4d:%.2d:%.2d %.2d:%.2d:%.2d", + $tm[5]+1900, $tm[4]+1, $tm[3], + $tm[2], $tm[1], $tm[0]); + $$self{Now} = [ $timeNow, $tz ]; + } + $timeNow .= $$self{Now}[1] if $tzFlag or not defined $tzFlag; + return $timeNow; +} + +#------------------------------------------------------------------------------ +# Inverse date/time print conversion (reformat to YYYY:mm:dd HH:MM:SS[.ss][+-HH:MM|Z]) +# Inputs: 0) ExifTool object ref, 1) Date/Time string, 2) timezone flag: +# 0 - remove timezone and sub-seconds if they exist +# 1 - add timezone if it doesn't exist +# undef - leave timezone alone +# 3) flag to allow date-only (YYYY, YYYY:mm or YYYY:mm:dd) or time without seconds +# Returns: formatted date/time string (or undef and issues warning on error) +# Notes: currently accepts different separators, but doesn't use DateFormat yet +my $strptimeLib; # strptime library name if available +sub InverseDateTime($$;$$) +{ + my ($self, $val, $tzFlag, $dateOnly) = @_; + my ($rtnVal, $tz); + # strip off timezone first if it exists + if ($val =~ s/([+-])(\d{1,2}):?(\d{2})\s*(DST)?$//i) { + $tz = sprintf("$1%.2d:$3", $2); + } elsif ($val =~ s/Z$//i) { + $tz = 'Z'; + } else { + $tz = ''; + # allow special value of 'now' + return $self->TimeNow($tzFlag) if lc($val) eq 'now'; + } + my $fmt = $$self{OPTIONS}{DateFormat}; + # only convert date if a format was specified and the date is recognizable + if ($fmt) { + unless (defined $strptimeLib) { + if (eval { require POSIX::strptime }) { + $strptimeLib = 'POSIX::strptime'; + } elsif (eval { require Time::Piece }) { + $strptimeLib = 'Time::Piece'; + # (call use_locale() to convert localized date/time, + # only available in Time::Piece 1.32 and later) + eval { Time::Piece->use_locale() }; + } else { + $strptimeLib = ''; + } + } + my ($lib, $wrn, @a); +TryLib: for ($lib=$strptimeLib; ; $lib='') { + if (not $lib) { + last unless $$self{OPTIONS}{StrictDate}; + warn $wrn || "Install POSIX::strptime or Time::Piece for inverse date/time conversions\n"; + return undef; + } elsif ($lib eq 'POSIX::strptime') { + @a = eval { POSIX::strptime($val, $fmt) }; + } else { + @a = eval { + my $t = Time::Piece->strptime($val, $fmt); + return ($t->sec, $t->min, $t->hour, $t->mday, $t->_mon, $t->_year); + }; + } + if (defined $a[5] and length $a[5]) { + $a[5] += 1900; # add 1900 to year + } else { + $wrn = "Invalid date/time (no year) using $lib\n"; + next; + } + ++$a[4] if defined $a[4] and length $a[4]; # add 1 to month + my $i; + foreach $i (0..4) { + if (not defined $a[$i] or not length $a[$i]) { + if ($i < 2 or $dateOnly) { # (allow missing minutes/seconds) + $a[$i] = ' '; + } else { + $wrn = "Incomplete date/time specification using $lib\n"; + next TryLib; + } + } elsif (length($a[$i]) < 2) { + $$a[$i] = "0$a[$i]";# pad to 2 digits if necessary + } + } + $val = join(':', @a[5,4,3]) . ' ' . join(':', @a[2,1,0]); + last; + } + } + if ($val =~ /(\d{4})/g) { # get YYYY + my $yr = $1; + my @a = ($val =~ /\d{1,2}/g); # get mm, dd, HH, and maybe MM, SS + length($_) < 2 and $_ = "0$_" foreach @a; # pad to 2 digits if necessary + if (@a >= 3) { + my $ss = $a[4]; # get SS + push @a, '00' while @a < 5; # add MM, SS if not given + # get sub-seconds if they exist (must be after SS, and have leading ".") + my $fs = (@a > 5 and $val =~ /(\.\d+)\s*$/) ? $1 : ''; + # add/remove timezone if necessary + if ($tzFlag) { + if (not $tz) { + if (eval { require Time::Local }) { + # determine timezone offset for this time + my @args = ($a[4],$a[3],$a[2],$a[1],$a[0]-1,$yr-1900); + my $diff = Time::Local::timegm(@args) - TimeLocal(@args); + $tz = TimeZoneString($diff / 60); + } else { + $tz = 'Z'; # don't know time zone + } + } + } elsif (defined $tzFlag) { + $tz = $fs = ''; # remove timezone and sub-seconds + } + if (defined $ss) { + $ss = ":$ss"; + } elsif ($dateOnly) { + $ss = ''; + } else { + $ss = ':00'; + } + # construct properly formatted date/time string + $rtnVal = "$yr:$a[0]:$a[1] $a[2]:$a[3]$ss$fs$tz"; + } elsif ($dateOnly) { + $rtnVal = join ':', $yr, @a; + } + } + $rtnVal or warn "Invalid date/time (use YYYY:mm:dd HH:MM:SS[.ss][+/-HH:MM|Z])\n"; + return $rtnVal; +} + +#------------------------------------------------------------------------------ +# Set byte order according to our current preferences +# Inputs: 0) ExifTool object ref +# Returns: new byte order ('II' or 'MM') and sets current byte order +# Notes: takes the first of the following that is valid: +# 1) ByteOrder option +# 2) new value for ExifByteOrder +# 3) makenote byte order from last file read +# 4) big endian +sub SetPreferredByteOrder($) +{ + my $self = shift; + my $byteOrder = $self->Options('ByteOrder') || + $self->GetNewValue('ExifByteOrder') || + $$self{MAKER_NOTE_BYTE_ORDER} || 'MM'; + unless (SetByteOrder($byteOrder)) { + warn "Invalid byte order '${byteOrder}'\n" if $self->Options('Verbose'); + $byteOrder = $$self{MAKER_NOTE_BYTE_ORDER} || 'MM'; + SetByteOrder($byteOrder); + } + return GetByteOrder(); +} + +#------------------------------------------------------------------------------ +# Assemble a continuing fraction into a rational value +# Inputs: 0) numerator, 1) denominator +# 2-N) list of fraction denominators, deepest first +# Returns: numerator, denominator (in list context) +sub AssembleRational($$@) +{ + @_ < 3 and return @_; + my ($num, $denom, $frac) = splice(@_, 0, 3); + return AssembleRational($frac*$num+$denom, $num, @_); +} + +#------------------------------------------------------------------------------ +# Convert a floating point number (or 'inf' or 'undef' or a fraction) into a rational +# Inputs: 0) floating point number, 1) optional maximum value (defaults to 0x7fffffff) +# Returns: numerator, denominator (in list context) +# Notes: +# - the returned rational will be accurate to at least 8 significant figures if possible +# - eg. an input of 3.14159265358979 returns a rational of 104348/33215, +# which equals 3.14159265392142 and is accurate to 10 significant figures +# - the returned rational will be reduced to the lowest common denominator except when +# the input is a fraction in which case the input is returned unchanged +# - these routines were a bit tricky, but fun to write! +sub Rationalize($;$) +{ + my $val = shift; + return (1, 0) if $val eq 'inf'; + return (0, 0) if $val eq 'undef'; + return ($1,$2) if $val =~ m{^([-+]?\d+)/(\d+)$}; # accept fractional values + # Note: Just testing "if $val" doesn't work because '0.0' is true! (ugghh!) + return (0, 1) if $val == 0; + my $sign = $val < 0 ? ($val = -$val, -1) : 1; + my ($num, $denom, @fracs); + my $frac = $val; + my $maxInt = shift || 0x7fffffff; + for (;;) { + my ($n, $d) = AssembleRational(int($frac + 0.5), 1, @fracs); + if ($n > $maxInt or $d > $maxInt) { + last if defined $num; + return ($sign, $maxInt) if $val < 1; + return ($sign * $maxInt, 1); + } + ($num, $denom) = ($n, $d); # save last good values + my $err = ($n/$d-$val) / $val; # get error of this rational + last if abs($err) < 1e-8; # all done if error is small + my $int = int($frac); + unshift @fracs, $int; + last unless $frac -= $int; + $frac = 1 / $frac; + } + return ($num * $sign, $denom); +} + +#------------------------------------------------------------------------------ +# Utility routines to for writing binary data values +# Inputs: 0) value, 1) data ref, 2) offset +# Notes: prototype is (@) so values can be passed from list if desired +sub Set16s(@) +{ + my $val = shift; + $val < 0 and $val += 0x10000; + return Set16u($val, @_); +} +sub Set32s(@) +{ + my $val = shift; + $val < 0 and $val += 0xffffffff, ++$val; + return Set32u($val, @_); +} +sub Set64u(@) +{ + my $val = shift; + my $hi = int($val / 4294967296); + my $lo = Set32u($val - $hi * 4294967296); + $hi = Set32u($hi); + $val = GetByteOrder() eq 'MM' ? $hi . $lo : $lo . $hi; + $_[1] and substr(${$_[1]}, $_[2], length($val)) = $val; + return $val; +} +sub SetRational64u(@) { + my ($numer,$denom) = Rationalize($_[0],0xffffffff); + my $val = Set32u($numer) . Set32u($denom); + $_[1] and substr(${$_[1]}, $_[2], length($val)) = $val; + return $val; +} +sub SetRational64s(@) { + my ($numer,$denom) = Rationalize($_[0]); + my $val = Set32s($numer) . Set32u($denom); + $_[1] and substr(${$_[1]}, $_[2], length($val)) = $val; + return $val; +} +sub SetRational32u(@) { + my ($numer,$denom) = Rationalize($_[0],0xffff); + my $val = Set16u($numer) . Set16u($denom); + $_[1] and substr(${$_[1]}, $_[2], length($val)) = $val; + return $val; +} +sub SetRational32s(@) { + my ($numer,$denom) = Rationalize($_[0],0x7fff); + my $val = Set16s($numer) . Set16u($denom); + $_[1] and substr(${$_[1]}, $_[2], length($val)) = $val; + return $val; +} +sub SetFixed16u(@) { + my $val = int(shift() * 0x100 + 0.5); + return Set16u($val, @_); +} +sub SetFixed16s(@) { + my $val = shift; + return Set16s(int($val * 0x100 + ($val < 0 ? -0.5 : 0.5)), @_); +} +sub SetFixed32u(@) { + my $val = int(shift() * 0x10000 + 0.5); + return Set32u($val, @_); +} +sub SetFixed32s(@) { + my $val = shift; + return Set32s(int($val * 0x10000 + ($val < 0 ? -0.5 : 0.5)), @_); +} +sub SetFloat(@) { + my $val = SwapBytes(pack('f',$_[0]), 4); + $_[1] and substr(${$_[1]}, $_[2], length($val)) = $val; + return $val; +} +sub SetDouble(@) { + # swap 32-bit words (ARM quirk) and bytes if necessary + my $val = SwapBytes(SwapWords(pack('d',$_[0])), 8); + $_[1] and substr(${$_[1]}, $_[2], length($val)) = $val; + return $val; +} +#------------------------------------------------------------------------------ +# hash lookups for writing binary data values +my %writeValueProc = ( + int8s => \&Set8s, + int8u => \&Set8u, + int16s => \&Set16s, + int16u => \&Set16u, + int16uRev => \&Set16uRev, + int32s => \&Set32s, + int32u => \&Set32u, + int64u => \&Set64u, + rational32s => \&SetRational32s, + rational32u => \&SetRational32u, + rational64s => \&SetRational64s, + rational64u => \&SetRational64u, + fixed16u => \&SetFixed16u, + fixed16s => \&SetFixed16s, + fixed32u => \&SetFixed32u, + fixed32s => \&SetFixed32s, + float => \&SetFloat, + double => \&SetDouble, + ifd => \&Set32u, +); +# verify that we can write floats on this platform +{ + my %writeTest = ( + float => [ -3.14159, 'c0490fd0' ], + double => [ -3.14159, 'c00921f9f01b866e' ], + ); + my $format; + my $oldOrder = GetByteOrder(); + SetByteOrder('MM'); + foreach $format (keys %writeTest) { + my ($val, $hex) = @{$writeTest{$format}}; + # add floating point entries if we can write them + next if unpack('H*', &{$writeValueProc{$format}}($val)) eq $hex; + delete $writeValueProc{$format}; # we can't write them + } + SetByteOrder($oldOrder); +} + +#------------------------------------------------------------------------------ +# write binary data value (with current byte ordering) +# Inputs: 0) value, 1) format string +# 2) number of values: +# undef = 1 for numerical types, or data length for string/undef types +# -1 = number of space-delimited values in the input string +# 3) optional data reference, 4) value offset (may be negative for bytes from end) +# Returns: packed value (and sets value in data) or undef on error +# Notes: May modify input value to round for integer formats +sub WriteValue($$;$$$$) +{ + my ($val, $format, $count, $dataPt, $offset) = @_; + my $proc = $writeValueProc{$format}; + my $packed; + + if ($proc) { + my @vals = split(' ',$val); + if ($count) { + $count = @vals if $count < 0; + } else { + $count = 1; # assume 1 if count not specified + } + $packed = ''; + while ($count--) { + $val = shift @vals; + return undef unless defined $val; + # validate numerical formats + if ($format =~ /^int/) { + unless (IsInt($val) or IsHex($val)) { + return undef unless IsFloat($val); + # round to nearest integer + $val = int($val + ($val < 0 ? -0.5 : 0.5)); + $_[0] = $val; + } + } elsif (not IsFloat($val)) { + return undef unless $format =~ /^rational/ and ($val eq 'inf' or + $val eq 'undef' or IsRational($val)); + } + $packed .= &$proc($val); + } + } elsif ($format eq 'string' or $format eq 'undef') { + $format eq 'string' and $val .= "\0"; # null-terminate strings + if ($count and $count > 0) { + my $diff = $count - length($val); + if ($diff) { + #warn "wrong string length!\n"; + # adjust length of string to match specified count + if ($diff < 0) { + if ($format eq 'string') { + return undef unless $count; + $val = substr($val, 0, $count - 1) . "\0"; + } else { + $val = substr($val, 0, $count); + } + } else { + $val .= "\0" x $diff; + } + } + } else { + $count = length($val); + } + $dataPt and substr($$dataPt, $offset, $count) = $val; + return $val; + } else { + warn "Sorry, Can't write $format values on this platform\n"; + return undef; + } + $dataPt and substr($$dataPt, $offset, length($packed)) = $packed; + return $packed; +} + +#------------------------------------------------------------------------------ +# Encode bit mask (the inverse of DecodeBits()) +# Inputs: 0) value to encode, 1) Reference to hash for encoding (or undef) +# 2) optional number of bits per word (defaults to 32), 3) total bits +# Returns: bit mask or undef on error (plus error string in list context) +sub EncodeBits($$;$$) +{ + my ($val, $lookup, $bits, $num) = @_; + $bits or $bits = 32; + $num or $num = $bits; + my $words = int(($num + $bits - 1) / $bits); + my @outVal = (0) x $words; + if ($val ne '(none)') { + my @vals = split /\s*,\s*/, $val; + foreach $val (@vals) { + my $bit; + if ($lookup) { + $bit = ReverseLookup($val, $lookup); + # (Note: may get non-numerical $bit values from Unknown() tags) + unless (defined $bit) { + if ($val =~ /\[(\d+)\]/) { # numerical bit specification + $bit = $1; + } else { + # don't return error string unless more than one value + return undef unless @vals > 1 and wantarray; + return (undef, "no match for '${val}'"); + } + } + } else { + $bit = $val; + } + unless (IsInt($bit) and $bit < $num) { + return undef unless wantarray; + return (undef, IsInt($bit) ? 'bit number too high' : 'not an integer'); + } + my $word = int($bit / $bits); + $outVal[$word] |= (1 << ($bit - $word * $bits)); + } + } + return "@outVal"; +} + +#------------------------------------------------------------------------------ +# get current position in output file (or end of file if a scalar reference) +# Inputs: 0) file or scalar reference +# Returns: Current position or -1 on error +sub Tell($) +{ + my $outfile = shift; + if (UNIVERSAL::isa($outfile,'GLOB')) { + return tell($outfile); + } else { + return length($$outfile); + } +} + +#------------------------------------------------------------------------------ +# write to file or memory +# Inputs: 0) file or scalar reference, 1-N) list of stuff to write +# Returns: true on success +sub Write($@) +{ + my $outfile = shift; + if (UNIVERSAL::isa($outfile,'GLOB')) { + return print $outfile @_; + } elsif (ref $outfile eq 'SCALAR') { + $$outfile .= join('', @_); + return 1; + } + return 0; +} + +#------------------------------------------------------------------------------ +# Write trailer buffer to file (applying fixups if necessary) +# Inputs: 0) ExifTool object ref, 1) trailer dirInfo ref, 2) output file ref +# Returns: 1 on success +sub WriteTrailerBuffer($$$) +{ + my ($self, $trailInfo, $outfile) = @_; + if ($$self{DEL_GROUP}{Trailer}) { + $self->VPrint(0, " Deleting trailer ($$trailInfo{Offset} bytes)\n"); + ++$$self{CHANGED}; + return 1; + } + my $pos = Tell($outfile); + my $trailPt = $$trailInfo{OutFile}; + # apply fixup if necessary (AFCP requires this) + if ($$trailInfo{Fixup}) { + if ($pos > 0) { + # shift offsets to final AFCP location and write it out + $$trailInfo{Fixup}{Shift} += $pos; + $$trailInfo{Fixup}->ApplyFixup($trailPt); + } else { + $self->Error("Can't get file position for trailer offset fixup",1); + } + } + return Write($outfile, $$trailPt); +} + +#------------------------------------------------------------------------------ +# Add trailers as a block +# Inputs: 0) ExifTool object ref, 1) [optional] trailer data raf, +# 1 or 2-N) trailer types to add (or none to add all) +# Returns: new trailer ref, or undef +# - increments CHANGED if trailer was added +sub AddNewTrailers($;@) +{ + my ($self, @types) = @_; + my $trailPt; + ref $types[0] and $trailPt = shift @types; + $types[0] or shift @types; # (in case undef data ref is passed) + # add all possible trailers if none specified (currently only CanonVRD) + @types or @types = qw(CanonVRD CanonDR4); + # add trailers as a block (if not done already) + my $type; + foreach $type (@types) { + next unless $$self{NEW_VALUE}{$Image::ExifTool::Extra{$type}}; + next if $$self{"Did$type"}; + my $val = $self->GetNewValue($type) or next; + # DR4 record must be wrapped in VRD trailer package + if ($type eq 'CanonDR4') { + next if $$self{DidCanonVRD}; # (only allow one VRD trailer) + require Image::ExifTool::CanonVRD; + $val = Image::ExifTool::CanonVRD::WrapDR4($val); + $$self{DidCanonVRD} = 1; + } + my $verb = $trailPt ? 'Writing' : 'Adding'; + $self->VPrint(0, " $verb $type as a block\n"); + if ($trailPt) { + $$trailPt .= $val; + } else { + $trailPt = \$val; + } + $$self{"Did$type"} = 1; + ++$$self{CHANGED}; + } + return $trailPt; +} + +#------------------------------------------------------------------------------ +# Write segment, splitting up into multiple segments if necessary +# Inputs: 0) file or scalar reference, 1) segment marker +# 2) segment header, 3) segment data ref, 4) segment type +# Returns: number of segments written, or 0 on error +# Notes: Writes a single empty segment if data is empty +sub WriteMultiSegment($$$$;$) +{ + my ($outfile, $marker, $header, $dataPt, $type) = @_; + $type or $type = ''; + my $len = length($$dataPt); + my $hdr = "\xff" . chr($marker); + my $count = 0; + my $maxLen = $maxSegmentLen - length($header); + $maxLen -= 2 if $type eq 'ICC'; # leave room for segment counters + my $num = int(($len + $maxLen - 1) / $maxLen); # number of segments to write + my $n = 0; + # write data, splitting into multiple segments if necessary + # (each segment gets its own header) + for (;;) { + ++$count; + my $size = $len - $n; + if ($size > $maxLen) { + $size = $maxLen; + # avoid starting an Extended EXIF segment with a valid TIFF header + # (because we would interpret that as a separate EXIF segment) + --$size if $type eq 'EXIF' and $n+$maxLen <= $len-4 and + substr($$dataPt, $n+$maxLen, 4) =~ /^(MM\0\x2a|II\x2a\0)/; + } + my $buff = substr($$dataPt,$n,$size); + $n += $size; + $size += length($header); + if ($type eq 'ICC') { + $buff = pack('CC', $count, $num) . $buff; + $size += 2; + } + # write the new segment with appropriate header + my $segHdr = $hdr . pack('n', $size + 2); + Write($outfile, $segHdr, $header, $buff) or return 0; + last if $n >= $len; + } + return $count; +} + +#------------------------------------------------------------------------------ +# Write XMP segment(s) to JPEG file +# Inputs: 0) ExifTool object ref, 1) outfile ref, 2) XMP data ref, +# 3) extended XMP data ref, 4) 32-char extended XMP GUID (or undef if no extended data) +# Returns: true on success, false on write error +sub WriteMultiXMP($$$$$) +{ + my ($self, $outfile, $dataPt, $extPt, $guid) = @_; + my $success = 1; + + # write main XMP segment + my $size = length($$dataPt) + length($xmpAPP1hdr); + if ($size > $maxXMPLen) { + $self->Error("XMP block too large for JPEG segment! ($size bytes)", 1); + return 1; + } + my $app1hdr = "\xff\xe1" . pack('n', $size + 2); + Write($outfile, $app1hdr, $xmpAPP1hdr, $$dataPt) or $success = 0; + # write extended XMP segment(s) if necessary + if (defined $guid) { + $size = length($$extPt); + my $maxLen = $maxXMPLen - 75; # maximum size without 75-byte header + my $off; + for ($off=0; $off<$size; $off+=$maxLen) { + # header(75) = signature(35) + guid(32) + size(4) + offset(4) + my $len = $size - $off; + $len = $maxLen if $len > $maxLen; + $app1hdr = "\xff\xe1" . pack('n', $len + 75 + 2); + $self->VPrint(0, "Writing extended XMP segment ($len bytes)\n"); + Write($outfile, $app1hdr, $xmpExtAPP1hdr, $guid, pack('N2', $size, $off), + substr($$extPt, $off, $len)) or $success = 0; + } + } + return $success; +} + +#------------------------------------------------------------------------------ +# WriteJPEG : Write JPEG image +# Inputs: 0) ExifTool object reference, 1) dirInfo reference +# Returns: 1 on success, 0 if this wasn't a valid JPEG file, or -1 if +# an output file was specified and a write error occurred +sub WriteJPEG($$) +{ + my ($self, $dirInfo) = @_; + my $outfile = $$dirInfo{OutFile}; + my $raf = $$dirInfo{RAF}; + my ($ch, $s, $length,$err, %doneDir, $isEXV, $creatingEXV); + my $verbose = $$self{OPTIONS}{Verbose}; + my $out = $$self{OPTIONS}{TextOut}; + my $rtnVal = 0; + my %dumpParms = ( Out => $out ); + my ($writeBuffer, $oldOutfile); # used to buffer writing until PreviewImage position is known + + # check to be sure this is a valid JPG or EXV file + unless ($raf->Read($s,2) == 2 and $s eq "\xff\xd8") { + if (defined $s and length $s) { + return 0 unless $s eq "\xff\x01" and $raf->Read($s,5) == 5 and $s eq 'Exiv2'; + } else { + return 0 unless $$self{FILE_TYPE} eq 'EXV'; + $s = 'Exiv2'; + $creatingEXV = 1; + } + Write($outfile,"\xff\x01") or $err = 1; + $isEXV = 1; + } + $dumpParms{MaxLen} = 128 unless $verbose > 3; + + delete $$self{PREVIEW_INFO}; # reset preview information + delete $$self{DEL_PREVIEW}; # reset flag to delete preview + + Write($outfile, $s) or $err = 1; + # figure out what segments we need to write for the tags we have set + my $addDirs = $$self{ADD_DIRS}; + my $editDirs = $$self{EDIT_DIRS}; + my $delGroup = $$self{DEL_GROUP}; + my $path = $$self{PATH}; + my $pn = scalar @$path; + + # set input record separator to 0xff (the JPEG marker) to make reading quicker + local $/ = "\xff"; +# +# pre-scan image to determine if any create-able segment already exists +# + my $pos = $raf->Tell(); + my ($marker, @dirOrder, %dirCount); + Prescan: for (;;) { + # read up to next marker (JPEG markers begin with 0xff) + $raf->ReadLine($s) or last; + # JPEG markers can be padded with unlimited 0xff's + for (;;) { + $raf->Read($ch, 1) or last Prescan; + $marker = ord($ch); + last unless $marker == 0xff; + } + my $dirName; + # stop pre-scan at SOS (end of meta information) or EOI (end of image) + if ($marker == 0xda or $marker == 0xd9) { + $dirName = $jpegMarker{$marker}; + push(@dirOrder, $dirName); + $dirCount{$dirName} = 1; + last; + } + # handle SOF markers: SOF0-SOF15, except DHT(0xc4), JPGA(0xc8) and DAC(0xcc) + if (($marker & 0xf0) == 0xc0 and ($marker == 0xc0 or $marker & 0x03)) { + last unless $raf->Seek(7, 1); + # read data for all markers except stand-alone + # markers 0x00, 0x01 and 0xd0-0xd7 (NULL, TEM, RST0-RST7) + } elsif ($marker!=0x00 and $marker!=0x01 and ($marker<0xd0 or $marker>0xd7)) { + # read record length word + last unless $raf->Read($s, 2) == 2; + my $len = unpack('n',$s); # get data length + last unless defined($len) and $len >= 2; + $len -= 2; # subtract size of length word + if (($marker & 0xf0) == 0xe0) { # is this an APP segment? + my $n = $len < 64 ? $len : 64; + $raf->Read($s, $n) == $n or last; + $len -= $n; + # Note: only necessary to recognize APP segments that we can create, + # or delete as a group (and the names below should match @delGroups) + if ($marker == 0xe0) { + $s =~ /^JFIF\0/ and $dirName = 'JFIF'; + $s =~ /^JFXX\0\x10/ and $dirName = 'JFXX'; + $s =~ /^(II|MM).{4}HEAPJPGM/s and $dirName = 'CIFF'; + } elsif ($marker == 0xe1) { + if ($s =~ /^(.{0,4})$exifAPP1hdr(.{1,4})/is) { + $dirName = 'IFD0'; + my ($junk, $bytes) = ($1, $2); + # support multi-segment EXIF + if (@dirOrder and $dirOrder[-1] =~ /^(IFD0|ExtendedEXIF)$/ and + not length $junk and $bytes !~ /^(MM\0\x2a|II\x2a\0)/) + { + $dirName = 'ExtendedEXIF'; + } + } + $s =~ /^$xmpAPP1hdr/ and $dirName = 'XMP'; + $s =~ /^$xmpExtAPP1hdr/ and $dirName = 'XMP'; + } elsif ($marker == 0xe2) { + $s =~ /^ICC_PROFILE\0/ and $dirName = 'ICC_Profile'; + $s =~ /^FPXR\0/ and $dirName = 'FlashPix'; + $s =~ /^MPF\0/ and $dirName = 'MPF'; + } elsif ($marker == 0xe3) { + $s =~ /^(Meta|META|Exif)\0\0/ and $dirName = 'Meta'; + } elsif ($marker == 0xe5) { + $s =~ /^RMETA\0/ and $dirName = 'RMETA'; + } elsif ($marker == 0xec) { + $s =~ /^Ducky/ and $dirName = 'Ducky'; + } elsif ($marker == 0xed) { + $s =~ /^$psAPP13hdr/ and $dirName = 'Photoshop'; + } elsif ($marker == 0xee) { + $s =~ /^Adobe/ and $dirName = 'Adobe'; + } + # initialize doneDir as a flag that the directory exists + # (unless we are deleting it anyway) + $doneDir{$dirName} = 0 if defined $dirName and not $$delGroup{$dirName}; + } + $raf->Seek($len, 1) or last; + } + $dirName or $dirName = JpegMarkerName($marker); + $dirCount{$dirName} = ($dirCount{$dirName} || 0) + 1; + push @dirOrder, $dirName; + } + unless ($marker and $marker == 0xda) { + $isEXV or $self->Error('Corrupted JPEG image'), return 1; + $marker and $marker ne 0xd9 and $self->Error('Corrupted EXV file'), return 1; + } + $raf->Seek($pos, 0) or $self->Error('Seek error'), return 1; +# +# re-write the image +# + my ($combinedSegData, $segPos, $firstSegPos, %extendedXMP); + my (@iccChunk, $iccChunkCount, $iccChunksTotal); + # read through each segment in the JPEG file + Marker: for (;;) { + + # read up to next marker (JPEG markers begin with 0xff) + my $segJunk; + $raf->ReadLine($segJunk) or $segJunk = ''; + # remove the 0xff but write the rest of the junk up to this point + # (this will handle the data after the first 7 bytes of SOF segments) + chomp($segJunk); + Write($outfile, $segJunk) if length $segJunk; + # JPEG markers can be padded with unlimited 0xff's + for (;;) { + if ($raf->Read($ch, 1)) { + $marker = ord($ch); + last unless $marker == 0xff; + } elsif ($creatingEXV) { + # create EXV from scratch + $marker = 0xd9; # EOI + push @dirOrder, 'EOI'; + $dirCount{EOI} = 1; + last; + } else { + $self->Error('Format error'); + return 1; + } + } + # read the segment data + my $segData; + # handle SOF markers: SOF0-SOF15, except DHT(0xc4), JPGA(0xc8) and DAC(0xcc) + if (($marker & 0xf0) == 0xc0 and ($marker == 0xc0 or $marker & 0x03)) { + last unless $raf->Read($segData, 7) == 7; + # read data for all markers except stand-alone + # markers 0x00, 0x01 and 0xd0-0xd7 (NULL, TEM, EOI, RST0-RST7) + } elsif ($marker!=0x00 and $marker!=0x01 and $marker!=0xd9 and + ($marker<0xd0 or $marker>0xd7)) + { + # read record length word + last unless $raf->Read($s, 2) == 2; + my $len = unpack('n',$s); # get data length + last unless defined($len) and $len >= 2; + $segPos = $raf->Tell(); + $len -= 2; # subtract size of length word + last unless $raf->Read($segData, $len) == $len; + } + # initialize variables for this segment + my $hdr = "\xff" . chr($marker); # segment header + my $markerName = JpegMarkerName($marker); + my $dirName = shift @dirOrder; # get directory name +# +# create all segments that must come before this one +# (nothing comes before SOI or after SOS) +# + while ($markerName ne 'SOI') { + if (exists $$addDirs{JFIF} and not defined $doneDir{JFIF}) { + $doneDir{JFIF} = 1; + if (defined $doneDir{Adobe}) { + # JFIF overrides Adobe APP14 colour components, so don't allow this + # (ref https://docs.oracle.com/javase/8/docs/api/javax/imageio/metadata/doc-files/jpeg_metadata.html) + $self->Warn('Not creating JFIF in JPEG with Adobe APP14'); + } else { + if ($verbose) { + print $out "Creating APP0:\n"; + print $out " Creating JFIF with default values\n"; + } + my $jfif = "\x01\x02\x01\0\x48\0\x48\0\0"; + SetByteOrder('MM'); + my $tagTablePtr = GetTagTable('Image::ExifTool::JFIF::Main'); + my %dirInfo = ( + DataPt => \$jfif, + DirStart => 0, + DirLen => length $jfif, + Parent => 'JFIF', + ); + # must temporarily remove JFIF from DEL_GROUP so we can + # delete JFIF and add it back again in a single step + my $delJFIF = $$delGroup{JFIF}; + delete $$delGroup{JFIF}; + $$path[$pn] = 'JFIF'; + my $newData = $self->WriteDirectory(\%dirInfo, $tagTablePtr); + $$delGroup{JFIF} = $delJFIF if defined $delJFIF; + if (defined $newData and length $newData) { + my $app0hdr = "\xff\xe0" . pack('n', length($newData) + 7); + Write($outfile,$app0hdr,"JFIF\0",$newData) or $err = 1; + } + } + } + # don't create anything before APP0 or APP1 EXIF (containing IFD0) + last if $markerName eq 'APP0' or $dirCount{IFD0} or $dirCount{ExtendedEXIF}; + # EXIF information must come immediately after APP0 + if (exists $$addDirs{IFD0} and not defined $doneDir{IFD0}) { + $doneDir{IFD0} = 1; + $verbose and print $out "Creating APP1:\n"; + # write new EXIF data + $$self{TIFF_TYPE} = 'APP1'; + my $tagTablePtr = GetTagTable('Image::ExifTool::Exif::Main'); + my %dirInfo = ( + DirName => 'IFD0', + Parent => 'APP1', + ); + $$path[$pn] = 'APP1'; + my $buff = $self->WriteDirectory(\%dirInfo, $tagTablePtr, \&WriteTIFF); + if (defined $buff and length $buff) { + if (length($buff) + length($exifAPP1hdr) > $maxSegmentLen) { + $self->Warn('Creating multi-segment EXIF',1); + } + # switch to buffered output if required + if (($$self{PREVIEW_INFO} or $$self{LeicaTrailer}) and not $oldOutfile) { + $writeBuffer = ''; + $oldOutfile = $outfile; + $outfile = \$writeBuffer; + # account for segment, EXIF and TIFF headers + $$self{PREVIEW_INFO}{Fixup}{Start} += 18 if $$self{PREVIEW_INFO}; + $$self{LeicaTrailer}{Fixup}{Start} += 18 if $$self{LeicaTrailer}; + } + # write as multi-segment + my $n = WriteMultiSegment($outfile, 0xe1, $exifAPP1hdr, \$buff, 'EXIF'); + if (not $n) { + $err = 1; + } elsif ($n > 1 and $oldOutfile) { + # (punt on this because updating the pointers would be a real pain) + $self->Error("Can't write multi-segment EXIF with external pointers"); + } + ++$$self{CHANGED}; + } + } + # APP13 Photoshop segment next + last if $dirCount{Photoshop}; + if (exists $$addDirs{Photoshop} and not defined $doneDir{Photoshop}) { + $doneDir{Photoshop} = 1; + $verbose and print $out "Creating APP13:\n"; + # write new APP13 Photoshop record to memory + my $tagTablePtr = GetTagTable('Image::ExifTool::Photoshop::Main'); + my %dirInfo = ( + Parent => 'APP13', + ); + $$path[$pn] = 'APP13'; + my $buff = $self->WriteDirectory(\%dirInfo, $tagTablePtr); + if (defined $buff and length $buff) { + WriteMultiSegment($outfile, 0xed, $psAPP13hdr, \$buff) or $err = 1; + ++$$self{CHANGED}; + } + } + # then APP1 XMP segment + last if $dirCount{XMP}; + if (exists $$addDirs{XMP} and not defined $doneDir{XMP}) { + $doneDir{XMP} = 1; + $verbose and print $out "Creating APP1:\n"; + # write new XMP data + my $tagTablePtr = GetTagTable('Image::ExifTool::XMP::Main'); + my %dirInfo = ( + Parent => 'APP1', + # specify MaxDataLen so XMP is split if required + MaxDataLen => $maxXMPLen - length($xmpAPP1hdr), + ); + $$path[$pn] = 'APP1'; + my $buff = $self->WriteDirectory(\%dirInfo, $tagTablePtr); + if (defined $buff and length $buff) { + WriteMultiXMP($self, $outfile, \$buff, $dirInfo{ExtendedXMP}, + $dirInfo{ExtendedGUID}) or $err = 1; + } + } + # then APP2 ICC_Profile segment + last if $dirCount{ICC_Profile}; + if (exists $$addDirs{ICC_Profile} and not defined $doneDir{ICC_Profile}) { + $doneDir{ICC_Profile} = 1; + next if $$delGroup{ICC_Profile} and $$delGroup{ICC_Profile} != 2; + $verbose and print $out "Creating APP2:\n"; + # write new ICC_Profile data + my $tagTablePtr = GetTagTable('Image::ExifTool::ICC_Profile::Main'); + my %dirInfo = ( + Parent => 'APP2', + ); + $$path[$pn] = 'APP2'; + my $buff = $self->WriteDirectory(\%dirInfo, $tagTablePtr); + if (defined $buff and length $buff) { + WriteMultiSegment($outfile, 0xe2, "ICC_PROFILE\0", \$buff, 'ICC') or $err = 1; + ++$$self{CHANGED}; + } + } + # then APP12 Ducky segment + last if $dirCount{Ducky}; + if (exists $$addDirs{Ducky} and not defined $doneDir{Ducky}) { + $doneDir{Ducky} = 1; + $verbose and print $out "Creating APP12 Ducky:\n"; + # write new Ducky segment data + my $tagTablePtr = GetTagTable('Image::ExifTool::APP12::Ducky'); + my %dirInfo = ( + Parent => 'APP12', + ); + $$path[$pn] = 'APP12'; + my $buff = $self->WriteDirectory(\%dirInfo, $tagTablePtr); + if (defined $buff and length $buff) { + my $size = length($buff) + 5; + if ($size <= $maxSegmentLen) { + # write the new segment with appropriate header + my $app12hdr = "\xff\xec" . pack('n', $size + 2); + Write($outfile, $app12hdr, 'Ducky', $buff) or $err = 1; + } else { + $self->Warn("APP12 Ducky segment too large! ($size bytes)"); + } + } + } + # then APP14 Adobe segment + last if $dirCount{Adobe}; + if (exists $$addDirs{Adobe} and not defined $doneDir{Adobe}) { + $doneDir{Adobe} = 1; + my $buff = $self->GetNewValue('Adobe'); + if ($buff) { + $verbose and print $out "Creating APP14:\n Creating Adobe segment\n"; + my $size = length($buff); + if ($size <= $maxSegmentLen) { + # write the new segment with appropriate header + my $app14hdr = "\xff\xee" . pack('n', $size + 2); + Write($outfile, $app14hdr, $buff) or $err = 1; + ++$$self{CHANGED}; + } else { + $self->Warn("APP14 Adobe segment too large! ($size bytes)"); + } + } + } + # finally, COM segment + last if $dirCount{COM}; + if (exists $$addDirs{COM} and not defined $doneDir{COM}) { + $doneDir{COM} = 1; + next if $$delGroup{File} and $$delGroup{File} != 2; + my $newComment = $self->GetNewValue('Comment'); + if (defined $newComment) { + if ($verbose) { + print $out "Creating COM:\n"; + $self->VerboseValue('+ Comment', $newComment); + } + WriteMultiSegment($outfile, 0xfe, '', \$newComment) or $err = 1; + ++$$self{CHANGED}; + } + } + last; # didn't want to loop anyway + } + $$path[$pn] = $markerName; + # decrement counter for this directory since we are about to process it + --$dirCount{$dirName}; +# +# rewrite existing segments +# + # handle SOF markers: SOF0-SOF15, except DHT(0xc4), JPGA(0xc8) and DAC(0xcc) + if (($marker & 0xf0) == 0xc0 and ($marker == 0xc0 or $marker & 0x03)) { + $verbose and print $out "JPEG $markerName:\n"; + Write($outfile, $hdr, $segData) or $err = 1; + next; + } elsif ($marker == 0xda) { # SOS + pop @$path; + $verbose and print $out "JPEG SOS\n"; + # write SOS segment + $s = pack('n', length($segData) + 2); + Write($outfile, $hdr, $s, $segData) or $err = 1; + my ($buff, $endPos, $trailInfo); + my $delPreview = $$self{DEL_PREVIEW}; + $trailInfo = IdentifyTrailer($raf) unless $$delGroup{Trailer}; + unless ($oldOutfile or $delPreview or $trailInfo or $$delGroup{Trailer}) { + # blindly copy the rest of the file + while ($raf->Read($buff, 65536)) { + Write($outfile, $buff) or $err = 1, last; + } + $rtnVal = 1; # success unless we have a file write error + last; # all done + } + # write the rest of the image (as quickly as possible) up to the EOI + my $endedWithFF; + for (;;) { + my $n = $raf->Read($buff, 65536) or last Marker; + if (($endedWithFF and $buff =~ m/^\xd9/sg) or + $buff =~ m/\xff\xd9/sg) + { + $rtnVal = 1; # the JPEG is OK + # write up to the EOI + my $pos = pos($buff); + Write($outfile, substr($buff, 0, $pos)) or $err = 1; + $buff = substr($buff, $pos); + last; + } + unless ($n == 65536) { + $self->Error('JPEG EOI marker not found'); + last Marker; + } + Write($outfile, $buff) or $err = 1; + $endedWithFF = substr($buff, 65535, 1) eq "\xff" ? 1 : 0; + } + # remember position of last data copied + $endPos = $raf->Tell() - length($buff); + # rewrite trailers if they exist + if ($trailInfo) { + my $tbuf = ''; + $raf->Seek(-length($buff), 1); # seek back to just after EOI + $$trailInfo{OutFile} = \$tbuf; # rewrite the trailer + $$trailInfo{ScanForAFCP} = 1; # scan if necessary + $self->ProcessTrailers($trailInfo) or undef $trailInfo; + } + if (not $oldOutfile) { + # do nothing special + } elsif ($$self{LeicaTrailer}) { + my $trailLen; + if ($trailInfo) { + $trailLen = $$trailInfo{DataPos} - $endPos; + } else { + $raf->Seek(0, 2) or $err = 1; + $trailLen = $raf->Tell() - $endPos; + } + my $fixup = $$self{LeicaTrailer}{Fixup}; + $$self{LeicaTrailer}{TrailPos} = $endPos; + $$self{LeicaTrailer}{TrailLen} = $trailLen; + # get _absolute_ position of new Leica trailer + my $absPos = Tell($oldOutfile) + length($$outfile); + require Image::ExifTool::Panasonic; + my $dat = Image::ExifTool::Panasonic::ProcessLeicaTrailer($self, $absPos); + # allow some junk before Leica trailer (just in case) + my $junk = $$self{LeicaTrailerPos} - $endPos; + # set MakerNote pointer and size (subtract 10 for segment and EXIF headers) + $fixup->SetMarkerPointers($outfile, 'LeicaTrailer', length($$outfile) - 10 + $junk); + # use this fixup to set the size too (sneaky) + my $trailSize = defined($dat) ? length($dat) - $junk : $$self{LeicaTrailer}{Size}; + $$fixup{Start} -= 4; $$fixup{Shift} += 4; + $fixup->SetMarkerPointers($outfile, 'LeicaTrailer', $trailSize) if defined $trailSize; + $$fixup{Start} += 4; $$fixup{Shift} -= 4; + # clean up and write the buffered data + $outfile = $oldOutfile; + undef $oldOutfile; + Write($outfile, $writeBuffer) or $err = 1; + undef $writeBuffer; + if (defined $dat) { + Write($outfile, $dat) or $err = 1; # write new Leica trailer + $delPreview = 1; # delete existing Leica trailer + } + } else { + # locate preview image and fix up preview offsets + my $scanLen = $$self{Make} =~ /^SONY/i ? 65536 : 1024; + if (length($buff) < $scanLen) { # make sure we have enough trailer to scan + my $buf2; + $buff .= $buf2 if $raf->Read($buf2, $scanLen - length($buff)); + } + # get new preview image position, relative to EXIF base + my $newPos = length($$outfile) - 10; # (subtract 10 for segment and EXIF headers) + my $junkLen; + # adjust position if image isn't at the start (eg. Olympus E-1/E-300) + if ($buff =~ /(\xff\xd8\xff.|.\xd8\xff\xdb)(..)/sg) { + my ($jpegHdr, $segLen) = ($1, $2); + $junkLen = pos($buff) - 6; + # Sony previewimage trailer has a 32 byte header + if ($$self{Make} =~ /^SONY/i and $junkLen > 32) { + # with some newer Sony models, the makernotes preview pointer + # points to JPEG at end of EXIF inside MPImage preview (what a pain!) + if ($jpegHdr eq "\xff\xd8\xff\xe1") { # is the first segment EXIF? + $segLen = unpack('n', $segLen); # the EXIF segment length + # Sony PreviewImage starts with last 2 bytes of EXIF segment + # (and first byte is usually "\0", not "\xff", so don't check this) + if (length($buff) > $junkLen + $segLen + 6 and + substr($buff, $junkLen + $segLen + 3, 3) eq "\xd8\xff\xdb") + { + $junkLen += $segLen + 2; + # (note: this will not copy the trailer after PreviewImage, + # which is a 14kB block full of zeros for the A77) + } + } + $junkLen -= 32; + } + $newPos += $junkLen; + } + # fix up the preview offsets to point to the start of the new image + my $previewInfo = $$self{PREVIEW_INFO}; + delete $$self{PREVIEW_INFO}; + my $fixup = $$previewInfo{Fixup}; + $newPos += ($$previewInfo{BaseShift} || 0); + # adjust to absolute file offset if necessary (Samsung STMN) + $newPos += Tell($oldOutfile) + 10 if $$previewInfo{Absolute}; + if ($$previewInfo{Relative}) { + # adjust for our base by looking at how far the pointer got shifted + $newPos -= ($fixup->GetMarkerPointers($outfile, 'PreviewImage') || 0); + } elsif ($$previewInfo{ChangeBase}) { + # Leica S2 uses relative offsets for the preview only (leica sucks) + my $makerOffset = $fixup->GetMarkerPointers($outfile, 'LeicaTrailer'); + $newPos -= $makerOffset if $makerOffset; + } + $fixup->SetMarkerPointers($outfile, 'PreviewImage', $newPos); + # clean up and write the buffered data + $outfile = $oldOutfile; + undef $oldOutfile; + Write($outfile, $writeBuffer) or $err = 1; + undef $writeBuffer; + # write preview image + if ($$previewInfo{Data} ne 'LOAD_PREVIEW') { + # write any junk that existed before the preview image + Write($outfile, substr($buff,0,$junkLen)) or $err = 1 if $junkLen; + # write the saved preview image + Write($outfile, $$previewInfo{Data}) or $err = 1; + delete $$previewInfo{Data}; + # (don't increment CHANGED because we could be rewriting existing preview) + $delPreview = 1; # remove old preview + } + } + # copy over preview image if necessary + unless ($delPreview) { + my $extra; + if ($trailInfo) { + # copy everything up to start of first processed trailer + $extra = $$trailInfo{DataPos} - $endPos; + } else { + # copy everything up to end of file + $raf->Seek(0, 2) or $err = 1; + $extra = $raf->Tell() - $endPos; + } + if ($extra > 0) { + if ($$delGroup{Trailer}) { + $verbose and print $out " Deleting unknown trailer ($extra bytes)\n"; + ++$$self{CHANGED}; + } else { + # copy over unknown trailer + $verbose and print $out " Preserving unknown trailer ($extra bytes)\n"; + $raf->Seek($endPos, 0) or $err = 1; + CopyBlock($raf, $outfile, $extra) or $err = 1; + } + } + } + # write trailer if necessary + if ($trailInfo) { + $self->WriteTrailerBuffer($trailInfo, $outfile) or $err = 1; + undef $trailInfo; + } + last; # all done parsing file + + } elsif ($marker==0xd9 and $isEXV) { + # write EXV EOI (any trailer will be lost) + Write($outfile, "\xff\xd9") or $err = 1; + $rtnVal = 1; + last; + + } elsif ($marker==0x00 or $marker==0x01 or ($marker>=0xd0 and $marker<=0xd7)) { + $verbose and $marker and print $out "JPEG $markerName:\n"; + # handle stand-alone markers 0x00, 0x01 and 0xd0-0xd7 (NULL, TEM, RST0-RST7) + Write($outfile, $hdr) or $err = 1; + next; + } + # + # NOTE: A 'next' statement after this point will cause $$segDataPt + # not to be written if there is an output file, so in this case + # the $$self{CHANGED} flags must be updated + # + my $segDataPt = \$segData; + $length = length($segData); + if ($verbose) { + print $out "JPEG $markerName ($length bytes):\n"; + if ($verbose > 2 and $markerName =~ /^APP/) { + HexDump($segDataPt, undef, %dumpParms); + } + } + # group delete of APP segements + if ($$delGroup{$dirName}) { + $verbose and print $out " Deleting $dirName segment\n"; + ++$$self{CHANGED}; + next Marker; + } + my ($segType, $del); + # rewrite this segment only if we are changing a tag which is contained in its + # directory (or deleting '*', in which case we need to identify the segment type) + while (exists $$editDirs{$markerName} or $$delGroup{'*'}) { + if ($marker == 0xe0) { # APP0 (JFIF, CIFF) + if ($$segDataPt =~ /^JFIF\0/) { + $segType = 'JFIF'; + $$delGroup{JFIF} and $del = 1, last; + last unless $$editDirs{JFIF}; + SetByteOrder('MM'); + my $tagTablePtr = GetTagTable('Image::ExifTool::JFIF::Main'); + my %dirInfo = ( + DataPt => $segDataPt, + DataPos => $segPos, + DataLen => $length, + DirStart => 5, # directory starts after identifier + DirLen => $length-5, + Parent => $markerName, + ); + my $newData = $self->WriteDirectory(\%dirInfo, $tagTablePtr); + if (defined $newData and length $newData) { + $$segDataPt = "JFIF\0" . $newData; + } + } elsif ($$segDataPt =~ /^JFXX\0\x10/) { + $segType = 'JFXX'; + $$delGroup{JFIF} and $del = 1; + } elsif ($$segDataPt =~ /^(II|MM).{4}HEAPJPGM/s) { + $segType = 'CIFF'; + $$delGroup{CIFF} and $del = 1, last; + last unless $$editDirs{CIFF}; + my $newData = ''; + my %dirInfo = ( + RAF => new File::RandomAccess($segDataPt), + OutFile => \$newData, + ); + require Image::ExifTool::CanonRaw; + if (Image::ExifTool::CanonRaw::WriteCRW($self, \%dirInfo) > 0) { + if (length $newData) { + $$segDataPt = $newData; + } else { + undef $segDataPt; + $del = 1; # delete this segment + } + } + } + } elsif ($marker == 0xe1) { # APP1 (EXIF, XMP) + # check for EXIF data + if ($$segDataPt =~ /^(.{0,4})$exifAPP1hdr/is) { + my $hdrLen = length $exifAPP1hdr; + if (length $1) { + $hdrLen += length $1; + $self->Error('Unknown garbage at start of EXIF segment',1); + } elsif ($$segDataPt !~ /^Exif\0/) { + $self->Error('Incorrect EXIF segment identifier',1); + } + $segType = 'EXIF'; + last unless $$editDirs{IFD0}; + # add this data to the combined data if it exists + if (defined $combinedSegData) { + $combinedSegData .= substr($$segDataPt,$hdrLen); + $segDataPt = \$combinedSegData; + $segPos = $firstSegPos; + $length = length $combinedSegData; # update length + } + # peek ahead to see if the next segment is extended EXIF + if ($dirOrder[0] eq 'ExtendedEXIF') { + # initialize combined data if necessary + unless (defined $combinedSegData) { + $combinedSegData = $$segDataPt; + $firstSegPos = $segPos; + $self->Warn('File contains multi-segment EXIF',1); + } + next Marker; # get the next segment to combine + } + $doneDir{IFD0} and $self->Warn('Multiple APP1 EXIF records'); + $doneDir{IFD0} = 1; + # check del groups now so we can change byte order in one step + if ($$delGroup{IFD0} or $$delGroup{EXIF}) { + delete $doneDir{IFD0}; # delete so we will create a new one + $del = 1; + last; + } + # rewrite EXIF as if this were a TIFF file in memory + my %dirInfo = ( + DataPt => $segDataPt, + DataPos => -$hdrLen, # (remember: relative to Base!) + DirStart => $hdrLen, + Base => $segPos + $hdrLen, + Parent => $markerName, + DirName => 'IFD0', + ); + # write new EXIF data to memory + my $tagTablePtr = GetTagTable('Image::ExifTool::Exif::Main'); + my $buff = $self->WriteDirectory(\%dirInfo, $tagTablePtr, \&WriteTIFF); + if (defined $buff) { + undef $$segDataPt; # free the old buffer + $segDataPt = \$buff; + } else { + last Marker unless $self->Options('IgnoreMinorErrors'); + } + # delete segment if IFD contains no entries + length $$segDataPt or $del = 1, last; + if (length($$segDataPt) + length($exifAPP1hdr) > $maxSegmentLen) { + $self->Warn('Writing multi-segment EXIF',1); + } + # switch to buffered output if required + if (($$self{PREVIEW_INFO} or $$self{LeicaTrailer}) and not $oldOutfile) { + $writeBuffer = ''; + $oldOutfile = $outfile; + $outfile = \$writeBuffer; + # must account for segment, EXIF and TIFF headers + $$self{PREVIEW_INFO}{Fixup}{Start} += 18 if $$self{PREVIEW_INFO}; + $$self{LeicaTrailer}{Fixup}{Start} += 18 if $$self{LeicaTrailer}; + } + # write as multi-segment + my $n = WriteMultiSegment($outfile, $marker, $exifAPP1hdr, $segDataPt, 'EXIF'); + if (not $n) { + $err = 1; + } elsif ($n > 1 and $oldOutfile) { + # (punt on this because updating the pointers would be a real pain) + $self->Error("Can't write multi-segment EXIF with external pointers"); + } + undef $combinedSegData; + undef $$segDataPt; + next Marker; + # check for XMP data + } elsif ($$segDataPt =~ /^($xmpAPP1hdr|$xmpExtAPP1hdr)/) { + $segType = 'XMP'; + $$delGroup{XMP} and $del = 1, last; + $doneDir{XMP} = ($doneDir{XMP} || 0) + 1; + last unless $$editDirs{XMP}; + if ($doneDir{XMP} + $dirCount{XMP} > 1) { + # must assemble all XMP segments before writing + my ($guid, $extXMP); + if ($$segDataPt =~ /^$xmpExtAPP1hdr/) { + # save extended XMP data + if (length $$segDataPt < 75) { + $extendedXMP{Error} = 'Truncated data'; + } else { + my ($size, $off) = unpack('x67N2', $$segDataPt); + $guid = substr($$segDataPt, 35, 32); + if ($guid =~ /[^A-Za-z0-9]/) { # (technically, should be uppercase) + $extendedXMP{Error} = 'Invalid GUID'; + } else { + # remember extended data for each GUID + $extXMP = $extendedXMP{$guid}; + if ($extXMP) { + $size == $$extXMP{Size} or $extendedXMP{Error} = 'Inconsistent size'; + } else { + $extXMP = $extendedXMP{$guid} = { }; + } + $$extXMP{Size} = $size; + $$extXMP{$off} = substr($$segDataPt, 75); + } + } + } else { + # save all main XMP segments (should normally be only one) + $extendedXMP{Main} = [] unless $extendedXMP{Main}; + push @{$extendedXMP{Main}}, substr($$segDataPt, length $xmpAPP1hdr); + } + # continue processing only if we have read all the segments + next Marker if $dirCount{XMP}; + # reconstruct an XMP super-segment + $$segDataPt = $xmpAPP1hdr; + my $goodGuid = ''; + foreach (@{$extendedXMP{Main}}) { + # get the HasExtendedXMP GUID if it exists + if (/:HasExtendedXMP\s*(=\s*['"]|>)(\w{32})/) { + # warn of subsequent XMP blocks specifying a different + # HasExtendedXMP (have never seen this) + if ($goodGuid and $goodGuid ne $2) { + $self->WarnOnce('Multiple XMP segments specifying different extended XMP GUID'); + } + $goodGuid = $2; # GUID for the standard extended XMP + } + $$segDataPt .= $_; + } + # GUID of the extended XMP that we want to read + my $readGuid = $$self{OPTIONS}{ExtendedXMP} || 0; + $readGuid = $goodGuid if $readGuid eq '1'; + foreach $guid (sort keys %extendedXMP) { + next unless length $guid == 32; # ignore other (internal) keys + if ($guid ne $readGuid and $readGuid ne '2') { + my $non = $guid eq $goodGuid ? '' : 'non-'; + $self->Warn("Ignored ${non}standard extended XMP (GUID $guid)"); + next; + } + if ($guid ne $goodGuid) { + $self->Warn("Reading non-standard extended XMP (GUID $guid)"); + } + $extXMP = $extendedXMP{$guid}; + next unless ref $extXMP eq 'HASH'; # (just to be safe) + my $size = $$extXMP{Size}; + my (@offsets, $off); + for ($off=0; $off<$size; ) { + last unless defined $$extXMP{$off}; + push @offsets, $off; + $off += length $$extXMP{$off}; + } + if ($off == $size) { + # add all XMP to super-segment + $$segDataPt .= $$extXMP{$_} foreach @offsets; + } else { + $self->Error("Incomplete extended XMP (GUID $guid)", 1); + } + } + $self->Error("$extendedXMP{Error} in extended XMP", 1) if $extendedXMP{Error}; + } + my $start = length $xmpAPP1hdr; + my $tagTablePtr = GetTagTable('Image::ExifTool::XMP::Main'); + my %dirInfo = ( + DataPt => $segDataPt, + DirStart => $start, + Parent => $markerName, + # limit XMP size and create extended XMP if necessary + MaxDataLen => $maxXMPLen - length($xmpAPP1hdr), + ); + my $newData = $self->WriteDirectory(\%dirInfo, $tagTablePtr); + if (defined $newData) { + undef %extendedXMP; + if (length $newData) { + # write multi-segment XMP (XMP plus extended XMP if necessary) + WriteMultiXMP($self, $outfile, \$newData, $dirInfo{ExtendedXMP}, + $dirInfo{ExtendedGUID}) or $err = 1; + undef $$segDataPt; # free the old buffer + next Marker; + } else { + $$segDataPt = ''; # delete the XMP + } + } else { + $verbose and print $out " [XMP rewritten with no changes]\n"; + if ($doneDir{XMP} > 1) { + # re-write original multi-segment XMP + my ($dat, $guid, $extXMP, $off); + foreach $dat (@{$extendedXMP{Main}}) { # main XMP + next unless length $dat; + $s = pack('n', length($xmpAPP1hdr) + length($dat) + 2); + Write($outfile, $hdr, $s, $xmpAPP1hdr, $dat) or $err = 1; + } + foreach $guid (sort keys %extendedXMP) { # extended XMP + next unless length $guid == 32; + $extXMP = $extendedXMP{$guid}; + next unless ref $extXMP eq 'HASH'; + my $size = $$extXMP{Size} or next; + for ($off=0; defined $$extXMP{$off}; $off += length $$extXMP{$off}) { + $s = pack('n', length($xmpExtAPP1hdr) + length($$extXMP{$off}) + 42); + Write($outfile, $hdr, $s, $xmpExtAPP1hdr, $guid, + pack('N2', $size, $off), $$extXMP{$off}) or $err = 1; + } + } + undef $$segDataPt; # free the old buffer + undef %extendedXMP; + next Marker; + } + # continue on to re-write original single-segment XMP + } + $del = 1 unless length $$segDataPt; + } elsif ($$segDataPt =~ /^http/ or $$segDataPt =~ /<exif:/) { + $self->Warn('Ignored APP1 XMP segment with non-standard header', 1); + } + } elsif ($marker == 0xe2) { # APP2 (ICC Profile, FPXR, MPF) + if ($$segDataPt =~ /^ICC_PROFILE\0/ and $length >= 14) { + $segType = 'ICC_Profile'; + $$delGroup{ICC_Profile} and $del = 1, last; + # must concatenate blocks of profile + my $chunkNum = Get8u($segDataPt, 12); + my $chunksTot = Get8u($segDataPt, 13); + if (defined $iccChunksTotal) { + # abort parsing ICC_Profile if the total chunk count is inconsistent + if ($chunksTot != $iccChunksTotal and defined $iccChunkCount) { + # an error because the accumulated profile data will be lost + $self->Error('Inconsistent ICC_Profile chunk count', 1); + undef $iccChunkCount; # abort ICC_Profile parsing + undef $chunkNum; # avoid 2nd warning below + ++$$self{CHANGED}; # we are deleting the bad chunks before this one + } + } else { + $iccChunkCount = 0; + $iccChunksTotal = $chunksTot; + $self->Warn('ICC_Profile chunk count is zero') if !$chunksTot; + } + if (defined $iccChunkCount) { + # save this chunk + if (defined $iccChunk[$chunkNum]) { + $self->Warn("Duplicate ICC_Profile chunk number $chunkNum"); + $iccChunk[$chunkNum] .= substr($$segDataPt, 14); + } else { + $iccChunk[$chunkNum] = substr($$segDataPt, 14); + } + # continue accumulating chunks unless we have all of them + next Marker unless ++$iccChunkCount >= $iccChunksTotal; + undef $iccChunkCount; # prevent reprocessing + $doneDir{ICC_Profile} = 1; + # combine the ICC_Profile chunks + my $icc_profile = ''; + defined $_ and $icc_profile .= $_ foreach @iccChunk; + undef @iccChunk; # free memory + $segDataPt = \$icc_profile; + $length = length $icc_profile; + my $tagTablePtr = GetTagTable('Image::ExifTool::ICC_Profile::Main'); + my %dirInfo = ( + DataPt => $segDataPt, + DataPos => $segPos + 14, + DataLen => $length, + DirStart => 0, + DirLen => $length, + Parent => $markerName, + ); + my $newData = $self->WriteDirectory(\%dirInfo, $tagTablePtr); + if (defined $newData) { + undef $$segDataPt; # free the old buffer + $segDataPt = \$newData; + } + length $$segDataPt or $del = 1, last; + # write as ICC multi-segment + WriteMultiSegment($outfile, $marker, "ICC_PROFILE\0", $segDataPt, 'ICC') or $err = 1; + undef $$segDataPt; + next Marker; + } elsif (defined $chunkNum) { + $self->WarnOnce('Invalid or extraneous ICC_Profile chunk(s)'); + # fall through to preserve this extra profile... + } + } elsif ($$segDataPt =~ /^FPXR\0/) { + $segType = 'FPXR'; + $$delGroup{FlashPix} and $del = 1; + } elsif ($$segDataPt =~ /^MPF\0/) { + $segType = 'MPF'; + $$delGroup{MPF} and $del = 1; + } + } elsif ($marker == 0xe3) { # APP3 (Kodak Meta) + if ($$segDataPt =~ /^(Meta|META|Exif)\0\0/) { + $segType = 'Kodak Meta'; + $$delGroup{Meta} and $del = 1, last; + $doneDir{Meta} and $self->Warn('Multiple APP3 Meta segments'); + $doneDir{Meta} = 1; + last unless $$editDirs{Meta}; + # rewrite Meta IFD as if this were a TIFF file in memory + my %dirInfo = ( + DataPt => $segDataPt, + DataPos => -6, # (remember: relative to Base!) + DirStart => 6, + Base => $segPos + 6, + Parent => $markerName, + DirName => 'Meta', + ); + # write new data to memory + my $tagTablePtr = GetTagTable('Image::ExifTool::Kodak::Meta'); + my $buff = $self->WriteDirectory(\%dirInfo, $tagTablePtr, \&WriteTIFF); + if (defined $buff) { + # update segment with new data + $$segDataPt = substr($$segDataPt,0,6) . $buff; + } else { + last Marker unless $self->Options('IgnoreMinorErrors'); + } + # delete segment if IFD contains no entries + $del = 1 unless length($$segDataPt) > 6; + } + } elsif ($marker == 0xe5) { # APP5 (Ricoh RMETA) + if ($$segDataPt =~ /^RMETA\0/) { + $segType = 'Ricoh RMETA'; + $$delGroup{RMETA} and $del = 1; + } + } elsif ($marker == 0xec) { # APP12 (Ducky) + if ($$segDataPt =~ /^Ducky/) { + $segType = 'Ducky'; + $$delGroup{Ducky} and $del = 1, last; + $doneDir{Ducky} and $self->Warn('Multiple APP12 Ducky segments'); + $doneDir{Ducky} = 1; + last unless $$editDirs{Ducky}; + my $tagTablePtr = GetTagTable('Image::ExifTool::APP12::Ducky'); + my %dirInfo = ( + DataPt => $segDataPt, + DataPos => $segPos, + DataLen => $length, + DirStart => 5, # directory starts after identifier + DirLen => $length-5, + Parent => $markerName, + ); + my $newData = $self->WriteDirectory(\%dirInfo, $tagTablePtr); + if (defined $newData) { + undef $$segDataPt; # free the old buffer + # add header to new segment unless empty + $newData = 'Ducky' . $newData if length $newData; + $segDataPt = \$newData; + } + $del = 1 unless length $$segDataPt; + } + } elsif ($marker == 0xed) { # APP13 (Photoshop) + if ($$segDataPt =~ /^$psAPP13hdr/) { + $segType = 'Photoshop'; + # add this data to the combined data if it exists + if (defined $combinedSegData) { + $combinedSegData .= substr($$segDataPt,length($psAPP13hdr)); + $segDataPt = \$combinedSegData; + $length = length $combinedSegData; # update length + } + # peek ahead to see if the next segment is photoshop data too + if ($dirOrder[0] eq 'Photoshop') { + # initialize combined data if necessary + $combinedSegData = $$segDataPt unless defined $combinedSegData; + next Marker; # get the next segment to combine + } + if ($doneDir{Photoshop}) { + $self->Warn('Multiple Photoshop records'); + # only rewrite the first Photoshop segment when deleting this group + # (to remove multiples when deleting and adding back in one step) + $$delGroup{Photoshop} and $del = 1, last; + } + $doneDir{Photoshop} = 1; + # process APP13 Photoshop record + my $tagTablePtr = GetTagTable('Image::ExifTool::Photoshop::Main'); + my %dirInfo = ( + DataPt => $segDataPt, + DataPos => $segPos, + DataLen => $length, + DirStart => 14, # directory starts after identifier + DirLen => $length-14, + Parent => $markerName, + ); + my $newData = $self->WriteDirectory(\%dirInfo, $tagTablePtr); + if (defined $newData) { + undef $$segDataPt; # free the old buffer + $segDataPt = \$newData; + } + length $$segDataPt or $del = 1, last; + # write as multi-segment + WriteMultiSegment($outfile, $marker, $psAPP13hdr, $segDataPt) or $err = 1; + undef $combinedSegData; + undef $$segDataPt; + next Marker; + } + } elsif ($marker == 0xee) { # APP14 (Adobe) + if ($$segDataPt =~ /^Adobe/) { + $segType = 'Adobe'; + # delete it and replace it later if editing + if ($$delGroup{Adobe} or $$editDirs{Adobe}) { + $del = 1; + undef $doneDir{Adobe}; # so we can add it back again above + } + } + } elsif ($marker == 0xfe) { # COM (JPEG comment) + my $newComment; + unless ($doneDir{COM}) { + $doneDir{COM} = 1; + unless ($$delGroup{File} and $$delGroup{File} != 2) { + my $tagInfo = $Image::ExifTool::Extra{Comment}; + my $nvHash = $self->GetNewValueHash($tagInfo); + my $val = $segData; + $val =~ s/\0+$//; # allow for stupid software that adds NULL terminator + if ($self->IsOverwriting($nvHash, $val) or $$delGroup{File}) { + $newComment = $self->GetNewValue($nvHash); + } else { + delete $$editDirs{COM}; # we aren't editing COM after all + last; + } + } + } + $self->VerboseValue('- Comment', $$segDataPt); + if (defined $newComment) { + # write out the comments + $self->VerboseValue('+ Comment', $newComment); + WriteMultiSegment($outfile, 0xfe, '', \$newComment) or $err = 1; + } else { + $verbose and print $out " Deleting COM segment\n"; + } + ++$$self{CHANGED}; # increment the changed flag + undef $segDataPt; # don't write existing comment + } + last; # didn't want to loop anyway + } + + # delete necessary segments (including unknown segments if deleting all) + if ($del or ($$delGroup{'*'} and not $segType and $marker>=0xe0 and $marker<=0xef)) { + $segType = 'unknown' unless $segType; + $verbose and print $out " Deleting $markerName $segType segment\n"; + ++$$self{CHANGED}; + next Marker; + } + # write out this segment if $segDataPt is still defined + if (defined $segDataPt and defined $$segDataPt) { + # write the data for this record (the data could have been + # modified, so recalculate the length word) + my $size = length($$segDataPt); + if ($size > $maxSegmentLen) { + $segType or $segType = 'Unknown'; + $self->Error("$segType $markerName segment too large! ($size bytes)"); + $err = 1; + } else { + $s = pack('n', length($$segDataPt) + 2); + Write($outfile, $hdr, $s, $$segDataPt) or $err = 1; + } + undef $$segDataPt; # free the buffer + undef $segDataPt; + } + } + # make sure the ICC_Profile was complete + $self->Error('Incomplete ICC_Profile record', 1) if defined $iccChunkCount; + pop @$path if @$path > $pn; + # if oldOutfile is still set, there was an error copying the JPEG + $oldOutfile and return 0; + if ($rtnVal) { + # add any new trailers we are creating + my $trailPt = $self->AddNewTrailers(); + Write($outfile, $$trailPt) or $err = 1 if $trailPt; + } + # set return value to -1 if we only had a write error + $rtnVal = -1 if $rtnVal and $err; + if ($creatingEXV and $rtnVal > 0 and not $$self{CHANGED}) { + $self->Error('Nothing written'); + $rtnVal = -1; + } + return $rtnVal; +} + +#------------------------------------------------------------------------------ +# Validate an image for writing +# Inputs: 0) ExifTool object reference, 1) raw value reference +# Returns: error string or undef on success +sub CheckImage($$) +{ + my ($self, $valPtr) = @_; + if (length($$valPtr) and $$valPtr!~/^\xff\xd8/ and not + $self->Options('IgnoreMinorErrors')) + { + return '[Minor] Not a valid image'; + } + return undef; +} + +#------------------------------------------------------------------------------ +# check a value for validity +# Inputs: 0) value reference, 1) format string, 2) optional count +# Returns: error string, or undef on success +# Notes: May modify value (if a count is specified for a string, it is null-padded +# to the specified length, and floating point values are rounded to integer if required) +sub CheckValue($$;$) +{ + my ($valPtr, $format, $count) = @_; + my (@vals, $val, $n); + + if ($format eq 'string' or $format eq 'undef') { + return undef unless $count and $count > 0; + my $len = length($$valPtr); + if ($format eq 'string') { + $len >= $count and return 'String too long'; + } else { + $len > $count and return 'Data too long'; + } + if ($len < $count) { + $$valPtr .= "\0" x ($count - $len); + } + return undef; + } + if ($count and $count != 1) { + @vals = split(' ',$$valPtr); + $count < 0 and ($count = @vals or return undef); + } else { + $count = 1; + @vals = ( $$valPtr ); + } + if (@vals != $count) { + my $str = @vals > $count ? 'Too many' : 'Not enough'; + return "$str values specified ($count required)"; + } + for ($n=0; $n<$count; ++$n) { + $val = shift @vals; + if ($format =~ /^int/) { + # make sure the value is integer + unless (IsInt($val)) { + if (IsHex($val)) { + $val = $$valPtr = hex($val); + } else { + # round single floating point values to the nearest integer + return 'Not an integer' unless IsFloat($val) and $count == 1; + $val = $$valPtr = int($val + ($val < 0 ? -0.5 : 0.5)); + } + } + my $rng = $intRange{$format} or return "Bad int format: $format"; + return "Value below $format minimum" if $val < $$rng[0]; + # (allow 0xfeedfeed code as value for 16-bit pointers) + return "Value above $format maximum" if $val > $$rng[1] and $val != 0xfeedfeed; + } elsif ($format =~ /^rational/ or $format eq 'float' or $format eq 'double') { + # make sure the value is a valid floating point number + unless (IsFloat($val)) { + # allow 'inf', 'undef' and fractional rational values + if ($format =~ /^rational/) { + next if $val eq 'inf' or $val eq 'undef'; + if ($val =~ m{^([-+]?\d+)/(\d+)$}) { + next unless $1 < 0 and $format =~ /u$/; + return 'Must be an unsigned rational'; + } + } + return 'Not a floating point number'; + } + if ($format =~ /^rational\d+u$/ and $val < 0) { + return 'Must be a positive number'; + } + } + } + return undef; # success! +} + +#------------------------------------------------------------------------------ +# check new value for binary data block +# Inputs: 0) ExifTool object ref, 1) tagInfo hash ref, 2) raw value ref +# Returns: error string or undef (and may modify value) on success +sub CheckBinaryData($$$) +{ + my ($self, $tagInfo, $valPtr) = @_; + my $format = $$tagInfo{Format}; + unless ($format) { + my $table = $$tagInfo{Table}; + if ($table and $$table{FORMAT}) { + $format = $$table{FORMAT}; + } else { + # use default 'int8u' unless specified + $format = 'int8u'; + } + } + my $count; + if ($format =~ /(.*)\[(.*)\]/) { + $format = $1; + $count = $2; + # can't evaluate $count now because we don't know $size yet + undef $count if $count =~ /\$size/; + } + return CheckValue($valPtr, $format, $count); +} + +#------------------------------------------------------------------------------ +# Rename a file (with patch for Windows Unicode file names, and other problem) +# Inputs: 0) ExifTool ref, 1) old name, 2) new name +# Returns: true on success +sub Rename($$$) +{ + my ($self, $old, $new) = @_; + my ($result, $try, $winUni); + + if ($self->EncodeFileName($old)) { + $self->EncodeFileName($new, 1); + $winUni = 1; + } elsif ($self->EncodeFileName($new)) { + $old = $_[1]; + $self->EncodeFileName($old, 1); + $winUni = 1; + } + for (;;) { + if ($winUni) { + $result = eval { Win32API::File::MoveFileExW($old, $new, + Win32API::File::MOVEFILE_REPLACE_EXISTING() | + Win32API::File::MOVEFILE_COPY_ALLOWED()) }; + } else { + $result = rename($old, $new); + } + last if $result or $^O ne 'MSWin32'; + # keep trying for up to 0.5 seconds + # (patch for Windows denial-of-service susceptibility) + $try = ($try || 1) + 1; + last if $try > 50; + select(undef,undef,undef,0.01); # sleep for 0.01 sec + } + return $result; +} + +#------------------------------------------------------------------------------ +# Delete a file (with patch for Windows Unicode file names) +# Inputs: 0) ExifTool ref, 1-N) names of files to delete +# Returns: number of files deleted +sub Unlink($@) +{ + my $self = shift; + my $result = 0; + while (@_) { + my $file = shift; + if ($self->EncodeFileName($file)) { + ++$result if eval { Win32API::File::DeleteFileW($file) }; + } else { + ++$result if unlink $file; + } + } + return $result; +} + +#------------------------------------------------------------------------------ +# Set file times (Unix seconds since the epoch) +# Inputs: 0) ExifTool ref, 1) file name or ref, 2) access time, 3) modification time, +# 4) inode change or creation time (or undef for any time to avoid setting) +# 5) flag to suppress warning +# Returns: 1 on success, 0 on error +my $k32SetFileTime; +sub SetFileTime($$;$$$$) +{ + my ($self, $file, $atime, $mtime, $ctime, $noWarn) = @_; + my $saveFile; + local *FH; + + # open file by name if necessary + unless (ref $file) { + # (file will be automatically closed when *FH goes out of scope) + $self->Open(\*FH, $file, '+<') or $self->Warn('Error opening file for update'), return 0; + $saveFile = $file; + $file = \*FH; + } + # on Windows, try to work around incorrect file times when daylight saving time is in effect + if ($^O eq 'MSWin32') { + if (not eval { require Win32::API }) { + $self->WarnOnce('Install Win32::API for proper handling of Windows file times'); + } elsif (not eval { require Win32API::File }) { + $self->WarnOnce('Install Win32API::File for proper handling of Windows file times'); + } else { + # get Win32 handle, needed for SetFileTime + my $win32Handle = eval { Win32API::File::GetOsFHandle($file) }; + unless ($win32Handle) { + $self->Warn('Win32API::File::GetOsFHandle returned invalid handle'); + return 0; + } + # convert Unix seconds to FILETIME structs + my $time; + foreach $time ($atime, $mtime, $ctime) { + # set to NULL if not defined (i.e. do not change) + defined $time or $time = 0, next; + # convert to 100 ns intervals since 0:00 UTC Jan 1, 1601 + # (89 leap years between 1601 and 1970) + my $wt = ($time + (((1970-1601)*365+89)*24*3600)) * 1e7; + my $hi = int($wt / 4294967296); + $time = pack 'LL', int($wt - $hi * 4294967296), $hi; # pack FILETIME struct + } + unless ($k32SetFileTime) { + return 0 if defined $k32SetFileTime; + $k32SetFileTime = new Win32::API('KERNEL32', 'SetFileTime', 'NPPP', 'I'); + unless ($k32SetFileTime) { + $self->Warn('Error calling Win32::API::SetFileTime'); + $k32SetFileTime = 0; + return 0; + } + } + unless ($k32SetFileTime->Call($win32Handle, $ctime, $atime, $mtime)) { + $self->Warn('Win32::API::SetFileTime returned ' . Win32::GetLastError()); + return 0; + } + return 1; + } + } + # other OS (or Windows fallback) + if (defined $atime and defined $mtime) { + my $success; + local $SIG{'__WARN__'} = \&SetWarning; # (this may not be necessary) + for (;;) { + undef $evalWarning; + # (this may fail on the first try if futimes is not implemented) + $success = eval { utime($atime, $mtime, $file) }; + last if $success or not defined $saveFile; + close $file; + $file = $saveFile; + undef $saveFile; + } + unless ($noWarn) { + if ($@ or $evalWarning) { + $self->Warn(CleanWarning($@ || $evalWarning)); + } elsif (not $success) { + $self->Warn('Error setting file time'); + } + } + return $success; + } + return 1; # (nothing to do) +} + +#------------------------------------------------------------------------------ +# Copy data block from RAF to output file in max 64kB chunks +# Inputs: 0) RAF ref, 1) outfile ref, 2) block size +# Returns: 1 on success, 0 on read error, undef on write error +sub CopyBlock($$$) +{ + my ($raf, $outfile, $size) = @_; + my $buff; + for (;;) { + last unless $size > 0; + my $n = $size > 65536 ? 65536 : $size; + $raf->Read($buff, $n) == $n or return 0; + Write($outfile, $buff) or return undef; + $size -= $n; + } + return 1; +} + +#------------------------------------------------------------------------------ +# copy image data from one file to another +# Inputs: 0) ExifTool object reference +# 1) reference to list of image data [ position, size, pad bytes ] +# 2) output file ref +# Returns: true on success +sub CopyImageData($$$) +{ + my ($self, $imageDataBlocks, $outfile) = @_; + my $raf = $$self{RAF}; + my ($dataBlock, $err); + my $num = @$imageDataBlocks; + $self->VPrint(0, " Copying $num image data blocks\n") if $num; + foreach $dataBlock (@$imageDataBlocks) { + my ($pos, $size, $pad) = @$dataBlock; + $raf->Seek($pos, 0) or $err = 'read', last; + my $result = CopyBlock($raf, $outfile, $size); + $result or $err = defined $result ? 'read' : 'writ'; + # pad if necessary + Write($outfile, "\0" x $pad) or $err = 'writ' if $pad; + last if $err; + } + if ($err) { + $self->Error("Error ${err}ing image data"); + return 0; + } + return 1; +} + +#------------------------------------------------------------------------------ +# write to binary data block +# Inputs: 0) ExifTool object ref, 1) source dirInfo ref, 2) tag table ref +# Returns: Binary data block or undefined on error +sub WriteBinaryData($$$) +{ + my ($self, $dirInfo, $tagTablePtr) = @_; + $self or return 1; # allow dummy access to autoload this package + + # get default format ('int8u' unless specified) + my $dataPt = $$dirInfo{DataPt} or return undef; + my $defaultFormat = $$tagTablePtr{FORMAT} || 'int8u'; + my $increment = FormatSize($defaultFormat); + unless ($increment) { + warn "Unknown format $defaultFormat\n"; + return undef; + } + # extract data members first if necessary + my @varOffsets; + if ($$tagTablePtr{DATAMEMBER}) { + $$dirInfo{DataMember} = $$tagTablePtr{DATAMEMBER}; + $$dirInfo{VarFormatData} = \@varOffsets; + $self->ProcessBinaryData($dirInfo, $tagTablePtr); + delete $$dirInfo{DataMember}; + delete $$dirInfo{VarFormatData}; + } + my $dirStart = $$dirInfo{DirStart} || 0; + my $dirLen = $$dirInfo{DirLen} || length($$dataPt) - $dirStart; + my $newData = substr($$dataPt, $dirStart, $dirLen) or return undef; + my $dirName = $$dirInfo{DirName}; + my $varSize = 0; + my @varInfo = @varOffsets; + my $tagInfo; + $dataPt = \$newData; + foreach $tagInfo (sort { $$a{TagID} <=> $$b{TagID} } $self->GetNewTagInfoList($tagTablePtr)) { + my $tagID = $$tagInfo{TagID}; + # evaluate conditional tags now if necessary + if (ref $$tagTablePtr{$tagID} eq 'ARRAY' or $$tagInfo{Condition}) { + my $writeInfo = $self->GetTagInfo($tagTablePtr, $tagID); + next unless $writeInfo and $writeInfo eq $tagInfo; + } + # add offsets for variable-sized tags if necessary + my $varFmt; + while (@varInfo and $varInfo[0][0] < $tagID) { + $varSize = $varInfo[0][1]; # get accumulated variable size + shift @varInfo; + } + my $count = 1; + my $format = $$tagInfo{Format}; + my $entry = int($tagID) * $increment + $varSize; # relative offset of this entry + if ($format) { + if ($format =~ /(.*)\[(.*)\]/) { + $format = $1; + $count = $2; + my $size = $dirLen; # used in eval + # evaluate count to allow count to be based on previous values + #### eval Format size ($size, $self) - NOTE: %val not supported for writing + $count = eval $count; + $@ and warn($@), next; + } elsif ($format eq 'string') { + # string with no specified count runs to end of block + $count = ($dirLen > $entry) ? $dirLen - $entry : 0; + } + } else { + $format = $defaultFormat; + } + # read/write using variable format if changed in Hook + $format = $varInfo[0][2] if @varInfo and $varInfo[0][0] == $tagID; + my $val = ReadValue($dataPt, $entry, $format, $count, $dirLen-$entry); + next unless defined $val; + my $nvHash = $self->GetNewValueHash($tagInfo, $$self{CUR_WRITE_GROUP}); + next unless $self->IsOverwriting($nvHash, $val); + my $newVal = $self->GetNewValue($nvHash); + next unless defined $newVal; # can't delete from a binary table + # only write masked bits if specified + my $mask = $$tagInfo{Mask}; + $newVal = (($newVal << $$tagInfo{BitShift}) & $mask) | ($val & ~$mask) if $mask; + # set the size + if ($$tagInfo{DataTag} and not $$tagInfo{IsOffset}) { + warn 'Internal error' unless $newVal == 0xfeedfeed; + my $data = $self->GetNewValue($$tagInfo{DataTag}); + $newVal = length($data) if defined $data; + my $format = $$tagInfo{Format} || $$tagTablePtr{FORMAT} || 'int32u'; + if ($format =~ /^int16/ and $newVal > 0xffff) { + $self->Error("$$tagInfo{DataTag} is too large (64 kB max. for this file)"); + } + } + my $rtnVal = WriteValue($newVal, $format, $count, $dataPt, $entry); + if (defined $rtnVal) { + $self->VerboseValue("- $dirName:$$tagInfo{Name}", $val); + $self->VerboseValue("+ $dirName:$$tagInfo{Name}", $newVal); + ++$$self{CHANGED}; + } + } + # add necessary fixups for any offsets + if ($$tagTablePtr{IS_OFFSET} and $$dirInfo{Fixup}) { + $varSize = 0; + @varInfo = @varOffsets; + my $fixup = $$dirInfo{Fixup}; + my $tagID; + foreach $tagID (@{$$tagTablePtr{IS_OFFSET}}) { + $tagInfo = $self->GetTagInfo($tagTablePtr, $tagID) or next; + while (@varInfo and $varInfo[0][0] < $tagID) { + $varSize = $varInfo[0][1]; + shift @varInfo; + } + my $entry = $tagID * $increment + $varSize; # (no offset to dirStart for new dir data) + next unless $entry <= $dirLen - 4; + # (Ricoh has 16-bit preview image offsets, so can't just assume int32u) + my $format = $$tagInfo{Format} || $$tagTablePtr{FORMAT} || 'int32u'; + my $offset = ReadValue($dataPt, $entry, $format, 1, $dirLen-$entry); + # ignore if offset is zero (eg. Ricoh DNG uses this to indicate no preview) + next unless $offset; + $fixup->AddFixup($entry, $$tagInfo{DataTag}, $format); + # handle the preview image now if this is a JPEG file + next unless $$self{FILE_TYPE} eq 'JPEG' and $$tagInfo{DataTag} and + $$tagInfo{DataTag} eq 'PreviewImage' and defined $$tagInfo{OffsetPair}; + # NOTE: here we assume there are no var-sized tags between the + # OffsetPair tags. If this ever becomes possible we must recalculate + # $varSize for the OffsetPair tag here! + $entry = $$tagInfo{OffsetPair} * $increment + $varSize; + my $size = ReadValue($dataPt, $entry, $format, 1, $dirLen-$entry); + my $previewInfo = $$self{PREVIEW_INFO}; + $previewInfo or $previewInfo = $$self{PREVIEW_INFO} = { + Fixup => new Image::ExifTool::Fixup, + }; + # set flag indicating we are using short pointers + $$previewInfo{IsShort} = 1 unless $format eq 'int32u'; + $$previewInfo{Absolute} = 1 if $$tagInfo{IsOffset} and $$tagInfo{IsOffset} eq '3'; + # get the value of the Composite::PreviewImage tag + $$previewInfo{Data} = $self->GetNewValue($Image::ExifTool::Composite{PreviewImage}); + unless (defined $$previewInfo{Data}) { + if ($offset >= 0 and $offset + $size <= $$dirInfo{DataLen}) { + $$previewInfo{Data} = substr(${$$dirInfo{DataPt}},$offset,$size); + } else { + $$previewInfo{Data} = 'LOAD_PREVIEW'; # flag to load preview later + } + } + } + } + # write any necessary SubDirectories + if ($$tagTablePtr{IS_SUBDIR}) { + $varSize = 0; + @varInfo = @varOffsets; + my $tagID; + foreach $tagID (@{$$tagTablePtr{IS_SUBDIR}}) { + my $tagInfo = $self->GetTagInfo($tagTablePtr, $tagID); + next unless defined $tagInfo; + while (@varInfo and $varInfo[0][0] < $tagID) { + $varSize = $varInfo[0][1]; + shift @varInfo; + } + my $entry = int($tagID) * $increment + $varSize; + last if $entry >= $dirLen; + # get value for Condition if necessary + unless ($tagInfo) { + my $more = $dirLen - $entry; + $more = 128 if $more > 128; + my $v = substr($newData, $entry, $more); + $tagInfo = $self->GetTagInfo($tagTablePtr, $tagID, \$v); + next unless $tagInfo; + } + next unless $$tagInfo{SubDirectory}; # (just to be safe) + my %subdirInfo = ( DataPt => \$newData, DirStart => $entry ); + my $subTablePtr = GetTagTable($$tagInfo{SubDirectory}{TagTable}); + my $dat = $self->WriteDirectory(\%subdirInfo, $subTablePtr); + substr($newData, $entry) = $dat if defined $dat and length $dat; + } + } + return $newData; +} + +#------------------------------------------------------------------------------ +# Write TIFF as a directory +# Inputs: 0) ExifTool object ref, 1) dirInfo ref, 2) tag table ref +# Returns: New directory data or undefined on error +sub WriteTIFF($$$) +{ + my ($self, $dirInfo, $tagTablePtr) = @_; + my $buff = ''; + $$dirInfo{OutFile} = \$buff; + return $buff if $self->ProcessTIFF($dirInfo, $tagTablePtr) > 0; + return undef; +} + +1; # end + +__END__ + +=head1 NAME + +Image::ExifTool::Writer.pl - ExifTool routines for writing meta information + +=head1 SYNOPSIS + +These routines are autoloaded by Image::ExifTool when required. + +=head1 DESCRIPTION + +This module contains ExifTool write routines and other infrequently +used routines. + +=head1 AUTHOR + +Copyright 2003-2019, Phil Harvey (phil at owl.phy.queensu.ca) + +This library is free software; you can redistribute it and/or modify it +under the same terms as Perl itself. + +=head1 SEE ALSO + +L<Image::ExifTool(3pm)|Image::ExifTool> + +=cut diff --git a/lib/Image/ExifTool/XMP.pm b/lib/Image/ExifTool/XMP.pm new file mode 100644 index 0000000..5f90ee2 --- /dev/null +++ b/lib/Image/ExifTool/XMP.pm @@ -0,0 +1,4041 @@ +#------------------------------------------------------------------------------ +# File: XMP.pm +# +# Description: Read XMP meta information +# +# Revisions: 11/25/2003 - P. Harvey Created +# 10/28/2004 - P. Harvey Major overhaul to conform with XMP spec +# 02/27/2005 - P. Harvey Also read UTF-16 and UTF-32 XMP +# 08/30/2005 - P. Harvey Split tag tables into separate namespaces +# 10/24/2005 - P. Harvey Added ability to parse .XMP files +# 08/25/2006 - P. Harvey Added ability to handle blank nodes +# 08/22/2007 - P. Harvey Added ability to handle alternate language tags +# 09/26/2008 - P. Harvey Added Iptc4xmpExt tags (version 1.0 rev 2) +# +# References: 1) http://www.adobe.com/products/xmp/pdfs/xmpspec.pdf +# 2) http://www.w3.org/TR/rdf-syntax-grammar/ (20040210) +# 3) http://www.portfoliofaq.com/pfaq/v7mappings.htm +# 4) http://www.iptc.org/IPTC4XMP/ +# 5) http://creativecommons.org/technology/xmp +# --> changed to http://wiki.creativecommons.org/Companion_File_metadata_specification (2007/12/21) +# 6) http://www.optimasc.com/products/fileid/xmp-extensions.pdf +# 7) Lou Salkind private communication +# 8) http://partners.adobe.com/public/developer/en/xmp/sdk/XMPspecification.pdf +# 9) http://www.w3.org/TR/SVG11/ +# 10) http://www.adobe.com/devnet/xmp/pdfs/XMPSpecificationPart2.pdf (Oct 2008) +# 11) http://www.extensis.com/en/support/kb_article.jsp?articleNumber=6102211 +# 12) http://www.cipa.jp/std/documents/e/DC-010-2012_E.pdf +# 13) http://www.cipa.jp/std/documents/e/DC-010-2017_E.pdf +# +# Notes: - Property qualifiers are handled as if they were separate +# properties (with no associated namespace). +# +# - Currently, there is no special treatment of the following +# properties which could potentially affect the extracted +# information: xml:base, rdf:parseType (note that parseType +# Literal isn't allowed by the XMP spec). +# +# - The family 2 group names will be set to 'Unknown' for any XMP +# tags not found in the XMP or Exif tag tables. +#------------------------------------------------------------------------------ + +package Image::ExifTool::XMP; + +use strict; +use vars qw($VERSION $AUTOLOAD @ISA @EXPORT_OK %stdXlatNS %nsURI %latConv %longConv + %dateTimeInfo %xmpTableDefaults %specialStruct %sDimensions %sArea %sColorant); +use Image::ExifTool qw(:Utils); +use Image::ExifTool::Exif; +use Image::ExifTool::GPS; +require Exporter; + +$VERSION = '3.21'; +@ISA = qw(Exporter); +@EXPORT_OK = qw(EscapeXML UnescapeXML); + +sub ProcessXMP($$;$); +sub WriteXMP($$;$); +sub CheckXMP($$$); +sub ParseXMPElement($$$;$$$$); +sub DecodeBase64($); +sub EncodeBase64($;$); +sub SaveBlankInfo($$$;$); +sub ProcessBlankInfo($$$;$); +sub ValidateXMP($;$); +sub ValidateProperty($$); +sub UnescapeChar($$;$); +sub AddFlattenedTags($;$$); +sub FormatXMPDate($); +sub ConvertRational($); +sub ConvertRationalList($); + +# lookup for translating to ExifTool namespaces (and family 1 group names) +%stdXlatNS = ( + # shorten ugly namespace prefixes + 'Iptc4xmpCore' => 'iptcCore', + 'Iptc4xmpExt' => 'iptcExt', + 'photomechanic'=> 'photomech', + 'MicrosoftPhoto' => 'microsoft', + 'prismusagerights' => 'pur', + 'GettyImagesGIFT' => 'getty', +); + +# translate ExifTool XMP family 1 group names back to standard XMP namespace prefixes +my %xmpNS = ( + 'iptcCore' => 'Iptc4xmpCore', + 'iptcExt' => 'Iptc4xmpExt', + 'photomech'=> 'photomechanic', + 'microsoft' => 'MicrosoftPhoto', + 'getty' => 'GettyImagesGIFT', + # (prism changed their spec to now use 'pur') + # 'pur' => 'prismusagerights', +); + +# Lookup to translate standard XMP namespace prefixes into URI's. This list +# need not be complete, but it must contain an entry for each namespace prefix +# (NAMESPACE) for writable tags in the XMP tables or in structures that doesn't +# define a URI. Also, the namespace must be defined here for non-standard +# namespace prefixes to be recognized. +%nsURI = ( + aux => 'http://ns.adobe.com/exif/1.0/aux/', + album => 'http://ns.adobe.com/album/1.0/', + cc => 'http://creativecommons.org/ns#', # changed 2007/12/21 - PH + crs => 'http://ns.adobe.com/camera-raw-settings/1.0/', + crss => 'http://ns.adobe.com/camera-raw-saved-settings/1.0/', + dc => 'http://purl.org/dc/elements/1.1/', + exif => 'http://ns.adobe.com/exif/1.0/', + exifEX => 'http://cipa.jp/exif/1.0/', + iX => 'http://ns.adobe.com/iX/1.0/', + pdf => 'http://ns.adobe.com/pdf/1.3/', + pdfx => 'http://ns.adobe.com/pdfx/1.3/', + photoshop => 'http://ns.adobe.com/photoshop/1.0/', + rdf => 'http://www.w3.org/1999/02/22-rdf-syntax-ns#', + rdfs => 'http://www.w3.org/2000/01/rdf-schema#', + stDim => 'http://ns.adobe.com/xap/1.0/sType/Dimensions#', + stEvt => 'http://ns.adobe.com/xap/1.0/sType/ResourceEvent#', + stFnt => 'http://ns.adobe.com/xap/1.0/sType/Font#', + stJob => 'http://ns.adobe.com/xap/1.0/sType/Job#', + stRef => 'http://ns.adobe.com/xap/1.0/sType/ResourceRef#', + stVer => 'http://ns.adobe.com/xap/1.0/sType/Version#', + stMfs => 'http://ns.adobe.com/xap/1.0/sType/ManifestItem#', + tiff => 'http://ns.adobe.com/tiff/1.0/', + 'x' => 'adobe:ns:meta/', + xmpG => 'http://ns.adobe.com/xap/1.0/g/', + xmpGImg => 'http://ns.adobe.com/xap/1.0/g/img/', + xmp => 'http://ns.adobe.com/xap/1.0/', + xmpBJ => 'http://ns.adobe.com/xap/1.0/bj/', + xmpDM => 'http://ns.adobe.com/xmp/1.0/DynamicMedia/', + xmpMM => 'http://ns.adobe.com/xap/1.0/mm/', + xmpRights => 'http://ns.adobe.com/xap/1.0/rights/', + xmpNote => 'http://ns.adobe.com/xmp/note/', + xmpTPg => 'http://ns.adobe.com/xap/1.0/t/pg/', + xmpidq => 'http://ns.adobe.com/xmp/Identifier/qual/1.0/', + xmpPLUS => 'http://ns.adobe.com/xap/1.0/PLUS/', + dex => 'http://ns.optimasc.com/dex/1.0/', + mediapro => 'http://ns.iview-multimedia.com/mediapro/1.0/', + expressionmedia => 'http://ns.microsoft.com/expressionmedia/1.0/', + Iptc4xmpCore => 'http://iptc.org/std/Iptc4xmpCore/1.0/xmlns/', + Iptc4xmpExt => 'http://iptc.org/std/Iptc4xmpExt/2008-02-29/', + MicrosoftPhoto => 'http://ns.microsoft.com/photo/1.0', + MP1 => 'http://ns.microsoft.com/photo/1.1', #PH (MP1 is fabricated) + MP => 'http://ns.microsoft.com/photo/1.2/', + MPRI => 'http://ns.microsoft.com/photo/1.2/t/RegionInfo#', + MPReg => 'http://ns.microsoft.com/photo/1.2/t/Region#', + lr => 'http://ns.adobe.com/lightroom/1.0/', + DICOM => 'http://ns.adobe.com/DICOM/', + 'drone-dji'=> 'http://www.dji.com/drone-dji/1.0/', + svg => 'http://www.w3.org/2000/svg', + et => 'http://ns.exiftool.ca/1.0/', +# +# namespaces defined in XMP2.pl: +# + plus => 'http://ns.useplus.org/ldf/xmp/1.0/', + # (prism recommendations from http://www.prismstandard.org/specifications/3.0/Image_Guide_3.0.htm) + prism => 'http://prismstandard.org/namespaces/basic/2.0/', + prl => 'http://prismstandard.org/namespaces/prl/2.1/', + pur => 'http://prismstandard.org/namespaces/prismusagerights/2.1/', + pmi => 'http://prismstandard.org/namespaces/pmi/2.2/', + prm => 'http://prismstandard.org/namespaces/prm/3.0/', + acdsee => 'http://ns.acdsee.com/iptc/1.0/', + digiKam => 'http://www.digikam.org/ns/1.0/', + swf => 'http://ns.adobe.com/swf/1.0/', + cell => 'http://developer.sonyericsson.com/cell/1.0/', + aas => 'http://ns.apple.com/adjustment-settings/1.0/', + 'mwg-rs' => 'http://www.metadataworkinggroup.com/schemas/regions/', + 'mwg-kw' => 'http://www.metadataworkinggroup.com/schemas/keywords/', + 'mwg-coll' => 'http://www.metadataworkinggroup.com/schemas/collections/', + stArea => 'http://ns.adobe.com/xmp/sType/Area#', + extensis => 'http://ns.extensis.com/extensis/1.0/', + ics => 'http://ns.idimager.com/ics/1.0/', + fpv => 'http://ns.fastpictureviewer.com/fpv/1.0/', + creatorAtom=>'http://ns.adobe.com/creatorAtom/1.0/', + 'apple-fi' => 'http://ns.apple.com/faceinfo/1.0/', + GAudio => 'http://ns.google.com/photos/1.0/audio/', + GImage => 'http://ns.google.com/photos/1.0/image/', + GPano => 'http://ns.google.com/photos/1.0/panorama/', + GSpherical=> 'http://ns.google.com/videos/1.0/spherical/', + GDepth => 'http://ns.google.com/photos/1.0/depthmap/', + GFocus => 'http://ns.google.com/photos/1.0/focus/', + dwc => 'http://rs.tdwg.org/dwc/index.htm', + GettyImagesGIFT => 'http://xmp.gettyimages.com/gift/1.0/', + LImage => 'http://ns.leiainc.com/photos/1.0/image/', +); + +# build reverse namespace lookup +my %uri2ns; +{ + my $ns; + foreach $ns (keys %nsURI) { + $uri2ns{$nsURI{$ns}} = $ns; + } +} + +# conversions for GPS coordinates +%latConv = ( + ValueConv => 'Image::ExifTool::GPS::ToDegrees($val, 1)', + ValueConvInv => 'Image::ExifTool::GPS::ToDMS($self, $val, 2, "N")', + PrintConv => 'Image::ExifTool::GPS::ToDMS($self, $val, 1, "N")', + PrintConvInv => 'Image::ExifTool::GPS::ToDegrees($val, 1)', +); +%longConv = ( + ValueConv => 'Image::ExifTool::GPS::ToDegrees($val, 1)', + ValueConvInv => 'Image::ExifTool::GPS::ToDMS($self, $val, 2, "E")', + PrintConv => 'Image::ExifTool::GPS::ToDMS($self, $val, 1, "E")', + PrintConvInv => 'Image::ExifTool::GPS::ToDegrees($val, 1)', +); +%dateTimeInfo = ( + # NOTE: Do NOT put "Groups" here because Groups hash must not be common! + Writable => 'date', + Shift => 'Time', + Validate => 'ValidateXMPDate($val)', + PrintConv => '$self->ConvertDateTime($val)', + PrintConvInv => '$self->InverseDateTime($val,undef,1)', +); + +# this conversion allows alternate language support for designated boolean tags +my %boolConv = ( + PrintConv => { + OTHER => sub { # (inverse conversion is the same) + my $val = shift; + return 'False' if lc $val eq 'false'; + return 'True' if lc $val eq 'true'; + return $val; + }, + True => 'True', + False => 'False', + }, +); + +# XMP namespaces which we don't want to contribute to generated EXIF tag names +# (Note: namespaces with non-standard prefixes aren't currently ignored) +my %ignoreNamespace = ( 'x'=>1, rdf=>1, xmlns=>1, xml=>1, svg=>1, et=>1, office=>1 ); + +# XMP properties to ignore (set dynamically via dirInfo IgnoreProp) +my %ignoreProp; + +# these are the attributes that we handle for properties that contain +# sub-properties. Attributes for simple properties are easy, and we +# just copy them over. These are harder since we don't store attributes +# for properties without simple values. (maybe this will change...) +# (special attributes are indicated by a list reference of tag information) +my %recognizedAttrs = ( + 'rdf:about' => [ 'Image::ExifTool::XMP::rdf', 'about', 'About' ], + 'x:xmptk' => [ 'Image::ExifTool::XMP::x', 'xmptk', 'XMPToolkit' ], + 'x:xaptk' => [ 'Image::ExifTool::XMP::x', 'xmptk', 'XMPToolkit' ], + 'rdf:parseType' => 1, + 'rdf:nodeID' => 1, + 'et:toolkit' => 1, + 'rdf:xmlns' => 1, # this is presumably the default namespace, which we currently ignore + 'lastUpdate' => [ 'Image::ExifTool::XMP::XML', 'lastUpdate', 'LastUpdate' ], # found in XML from Sony ILCE-7S MP4 +); + +# special tags in structures below +# NOTE: this lookup is duplicated in TagLookup.pm!! +%specialStruct = ( + STRUCT_NAME => 1, # [optional] name of structure + NAMESPACE => 1, # [mandatory] namespace prefix used for fields of this structure + NOTES => 1, # [optional] notes for documentation about this structure + TYPE => 1, # [optional] rdf:type resource for struct (if used, the StructType flag + # will be set automatically for all derived flattened tags when writing) + GROUPS => 1, # [optional] specifies family group 2 name for the structure +); +# XMP structures (each structure is similar to a tag table so we can +# recurse through them in SetPropertyPath() as if they were tag tables) +# The main differences between structure field information and tagInfo hashes are: +# 1) Field information hashes do not contain Name, Groups or Table entries, and +# 2) The TagID entry is optional, and is used only if the key in the structure hash +# is different from the TagID (currently only true for alternate language fields) +# 3) Field information hashes support a additional "Namespace" property. +my %sResourceRef = ( + STRUCT_NAME => 'ResourceRef', + NAMESPACE => 'stRef', + documentID => { }, + instanceID => { }, + manager => { }, + managerVariant => { }, + manageTo => { }, + manageUI => { }, + renditionClass => { }, + renditionParams => { }, + versionID => { }, + # added Oct 2008 + alternatePaths => { List => 'Seq' }, + filePath => { }, + fromPart => { }, + lastModifyDate => { %dateTimeInfo, Groups => { 2 => 'Time' } }, + maskMarkers => { PrintConv => { All => 'All', None => 'None' } }, + partMapping => { }, + toPart => { }, + # added May 2010 + originalDocumentID => { }, # (undocumented property written by Adobe InDesign) + # added Aug 2016 (INDD again) + lastURL => { }, + linkForm => { }, + linkCategory => { }, + placedXResolution => { }, + placedYResolution => { }, + placedResolutionUnit => { }, +); +my %sResourceEvent = ( + STRUCT_NAME => 'ResourceEvent', + NAMESPACE => 'stEvt', + action => { }, + instanceID => { }, + parameters => { }, + softwareAgent => { }, + when => { %dateTimeInfo, Groups => { 2 => 'Time' } }, + # added Oct 2008 + changed => { }, +); +my %sJobRef = ( + STRUCT_NAME => 'JobRef', + NAMESPACE => 'stJob', + id => { }, + name => { }, + url => { }, +); +my %sVersion = ( + STRUCT_NAME => 'Version', + NAMESPACE => 'stVer', + comments => { }, + event => { Struct => \%sResourceEvent }, + modifier => { }, + modifyDate => { %dateTimeInfo, Groups => { 2 => 'Time' } }, + version => { }, +); +my %sThumbnail = ( + STRUCT_NAME => 'Thumbnail', + NAMESPACE => 'xmpGImg', + height => { Writable => 'integer' }, + width => { Writable => 'integer' }, + 'format' => { }, + image => { + Avoid => 1, + Groups => { 2 => 'Preview' }, + ValueConv => 'Image::ExifTool::XMP::DecodeBase64($val)', + ValueConvInv => 'Image::ExifTool::XMP::EncodeBase64($val)', + }, +); +my %sPageInfo = ( + STRUCT_NAME => 'PageInfo', + NAMESPACE => 'xmpGImg', + PageNumber => { Writable => 'integer', Namespace => 'xmpTPg' }, # override default namespace + height => { Writable => 'integer' }, + width => { Writable => 'integer' }, + 'format' => { }, + image => { + Groups => { 2 => 'Preview' }, + ValueConv => 'Image::ExifTool::XMP::DecodeBase64($val)', + ValueConvInv => 'Image::ExifTool::XMP::EncodeBase64($val)', + }, +); +#my %sIdentifierScheme = ( +# NAMESPACE => 'xmpidq', +# Scheme => { }, # qualifier for xmp:Identifier only +#); +%sDimensions = ( + STRUCT_NAME => 'Dimensions', + NAMESPACE => 'stDim', + w => { Writable => 'real' }, + h => { Writable => 'real' }, + unit => { }, +); +%sArea = ( + STRUCT_NAME => 'Area', + NAMESPACE => 'stArea', + 'x' => { Writable => 'real' }, + 'y' => { Writable => 'real' }, + w => { Writable => 'real' }, + h => { Writable => 'real' }, + d => { Writable => 'real' }, + unit => { }, +); +%sColorant = ( + STRUCT_NAME => 'Colorant', + NAMESPACE => 'xmpG', + swatchName => { }, + mode => { PrintConv => { CMYK=>'CMYK', RGB=>'RGB', LAB=>'Lab' } }, + # note: do not implement closed choice for "type" because Adobe can't + # get the case right: spec. says "PROCESS" but Indesign writes "Process" + type => { }, + cyan => { Writable => 'real' }, + magenta => { Writable => 'real' }, + yellow => { Writable => 'real' }, + black => { Writable => 'real' }, + red => { Writable => 'integer' }, + green => { Writable => 'integer' }, + blue => { Writable => 'integer' }, + gray => { Writable => 'integer' }, + L => { Writable => 'real' }, + A => { Writable => 'integer' }, + B => { Writable => 'integer' }, + # 'tint' observed in INDD sample - PH + tint => { Writable => 'integer', Notes => 'not part of 2010 XMP specification' }, +); +my %sSwatchGroup = ( + STRUCT_NAME => 'SwatchGroup', + NAMESPACE => 'xmpG', + groupName => { }, + groupType => { Writable => 'integer' }, + Colorants => { + FlatName => 'SwatchColorant', + Struct => \%sColorant, + List => 'Seq', + }, +); +my %sFont = ( + STRUCT_NAME => 'Font', + NAMESPACE => 'stFnt', + fontName => { }, + fontFamily => { }, + fontFace => { }, + fontType => { }, + versionString => { }, + composite => { Writable => 'boolean' }, + fontFileName=> { }, + childFontFiles => { List => 'Seq' }, +); +my %sOECF = ( + STRUCT_NAME => 'OECF', + NAMESPACE => 'exif', + Columns => { Writable => 'integer' }, + Rows => { Writable => 'integer' }, + Names => { List => 'Seq' }, + Values => { List => 'Seq', Writable => 'rational' }, +); + +# new LR2 crs structures (PH) +my %sCorrectionMask = ( + STRUCT_NAME => 'CorrectionMask', + NAMESPACE => 'crs', + # disable List behaviour of flattened Gradient/PaintBasedCorrections + # because these are nested in lists and the flattened tags can't + # do justice to this complex structure + What => { List => 0 }, + MaskValue => { Writable => 'real', List => 0, FlatName => 'Value' }, + Radius => { Writable => 'real', List => 0 }, + Flow => { Writable => 'real', List => 0 }, + CenterWeight => { Writable => 'real', List => 0 }, + Dabs => { List => 'Seq' }, + ZeroX => { Writable => 'real', List => 0 }, + ZeroY => { Writable => 'real', List => 0 }, + FullX => { Writable => 'real', List => 0 }, + FullY => { Writable => 'real', List => 0 }, + # new elements used in CircularGradientBasedCorrections CorrectionMasks + # and RetouchAreas Masks + Top => { Writable => 'real', List => 0 }, + Left => { Writable => 'real', List => 0 }, + Bottom => { Writable => 'real', List => 0 }, + Right => { Writable => 'real', List => 0 }, + Angle => { Writable => 'real', List => 0 }, + Midpoint => { Writable => 'real', List => 0 }, + Roundness => { Writable => 'real', List => 0 }, + Feather => { Writable => 'real', List => 0 }, + Flipped => { Writable => 'boolean', List => 0 }, + Version => { Writable => 'integer', List => 0 }, + SizeX => { Writable => 'real', List => 0 }, + SizeY => { Writable => 'real', List => 0 }, + X => { Writable => 'real', List => 0 }, + Y => { Writable => 'real', List => 0 }, + Alpha => { Writable => 'real', List => 0 }, + CenterValue => { Writable => 'real', List => 0 }, + PerimeterValue=>{ Writable => 'real', List => 0 }, +); +my %sCorrection = ( + STRUCT_NAME => 'Correction', + NAMESPACE => 'crs', + What => { List => 0 }, + CorrectionAmount => { FlatName => 'Amount', Writable => 'real', List => 0 }, + CorrectionActive => { FlatName => 'Active', Writable => 'boolean', List => 0 }, + LocalExposure => { FlatName => 'Exposure', Writable => 'real', List => 0 }, + LocalSaturation => { FlatName => 'Saturation', Writable => 'real', List => 0 }, + LocalContrast => { FlatName => 'Contrast', Writable => 'real', List => 0 }, + LocalClarity => { FlatName => 'Clarity', Writable => 'real', List => 0 }, + LocalSharpness => { FlatName => 'Sharpness', Writable => 'real', List => 0 }, + LocalBrightness => { FlatName => 'Brightness', Writable => 'real', List => 0 }, + LocalToningHue => { FlatName => 'Hue', Writable => 'real', List => 0 }, + LocalToningSaturation => { FlatName => 'Saturation', Writable => 'real', List => 0 }, + LocalExposure2012 => { FlatName => 'Exposure2012', Writable => 'real', List => 0 }, + LocalContrast2012 => { FlatName => 'Contrast2012', Writable => 'real', List => 0 }, + LocalHighlights2012 => { FlatName => 'Highlights2012', Writable => 'real', List => 0 }, + LocalShadows2012 => { FlatName => 'Shadows2012', Writable => 'real', List => 0 }, + LocalClarity2012 => { FlatName => 'Clarity2012', Writable => 'real', List => 0 }, + LocalLuminanceNoise => { FlatName => 'LuminanceNoise', Writable => 'real', List => 0 }, + LocalMoire => { FlatName => 'Moire', Writable => 'real', List => 0 }, + LocalDefringe => { FlatName => 'Defringe', Writable => 'real', List => 0 }, + LocalTemperature => { FlatName => 'Temperature',Writable => 'real', List => 0 }, + LocalTint => { FlatName => 'Tint', Writable => 'real', List => 0 }, + CorrectionMasks => { + FlatName => 'Mask', + Struct => \%sCorrectionMask, + List => 'Seq', + }, +); +my %sRetouchArea = ( + STRUCT_NAME => 'RetouchArea', + NAMESPACE => 'crs', + SpotType => { List => 0 }, + SourceState => { List => 0 }, + Method => { List => 0 }, + SourceX => { Writable => 'real', List => 0 }, + OffsetY => { Writable => 'real', List => 0 }, + Opacity => { Writable => 'real', List => 0 }, + Feather => { Writable => 'real', List => 0 }, + Seed => { Writable => 'integer', List => 0 }, + Masks => { + FlatName => 'Mask', + Struct => \%sCorrectionMask, + List => 'Seq', + }, +); + +# main XMP tag table (tag ID's are used for the family 1 group names) +%Image::ExifTool::XMP::Main = ( + GROUPS => { 2 => 'Unknown' }, + PROCESS_PROC => \&ProcessXMP, + WRITE_PROC => \&WriteXMP, + dc => { + Name => 'dc', # (otherwise generated name would be 'Dc') + SubDirectory => { TagTable => 'Image::ExifTool::XMP::dc' }, + }, + xmp => { + Name => 'xmp', + SubDirectory => { TagTable => 'Image::ExifTool::XMP::xmp' }, + }, + xmpDM => { + Name => 'xmpDM', + SubDirectory => { TagTable => 'Image::ExifTool::XMP::xmpDM' }, + }, + xmpRights => { + Name => 'xmpRights', + SubDirectory => { TagTable => 'Image::ExifTool::XMP::xmpRights' }, + }, + xmpNote => { + Name => 'xmpNote', + SubDirectory => { TagTable => 'Image::ExifTool::XMP::xmpNote' }, + }, + xmpMM => { + Name => 'xmpMM', + SubDirectory => { TagTable => 'Image::ExifTool::XMP::xmpMM' }, + }, + xmpBJ => { + Name => 'xmpBJ', + SubDirectory => { TagTable => 'Image::ExifTool::XMP::xmpBJ' }, + }, + xmpTPg => { + Name => 'xmpTPg', + SubDirectory => { TagTable => 'Image::ExifTool::XMP::xmpTPg' }, + }, + pdf => { + Name => 'pdf', + SubDirectory => { TagTable => 'Image::ExifTool::XMP::pdf' }, + }, + pdfx => { + Name => 'pdfx', + SubDirectory => { TagTable => 'Image::ExifTool::XMP::pdfx' }, + }, + photoshop => { + Name => 'photoshop', + SubDirectory => { TagTable => 'Image::ExifTool::XMP::photoshop' }, + }, + crs => { + Name => 'crs', + SubDirectory => { TagTable => 'Image::ExifTool::XMP::crs' }, + }, + # crss - it would be tedious to add the ability to write this + aux => { + Name => 'aux', + SubDirectory => { TagTable => 'Image::ExifTool::XMP::aux' }, + }, + tiff => { + Name => 'tiff', + SubDirectory => { TagTable => 'Image::ExifTool::XMP::tiff' }, + }, + exif => { + Name => 'exif', + SubDirectory => { TagTable => 'Image::ExifTool::XMP::exif' }, + }, + exifEX => { + Name => 'exifEX', + SubDirectory => { TagTable => 'Image::ExifTool::XMP::exifEX' }, + }, + iptcCore => { + Name => 'iptcCore', + SubDirectory => { TagTable => 'Image::ExifTool::XMP::iptcCore' }, + }, + iptcExt => { + Name => 'iptcExt', + SubDirectory => { TagTable => 'Image::ExifTool::XMP::iptcExt' }, + }, + PixelLive => { + SubDirectory => { TagTable => 'Image::ExifTool::XMP::PixelLive' }, + }, + xmpPLUS => { + Name => 'xmpPLUS', + SubDirectory => { TagTable => 'Image::ExifTool::XMP::xmpPLUS' }, + }, + plus => { + Name => 'plus', + SubDirectory => { TagTable => 'Image::ExifTool::PLUS::XMP' }, + }, + cc => { + Name => 'cc', + SubDirectory => { TagTable => 'Image::ExifTool::XMP::cc' }, + }, + dex => { + Name => 'dex', + SubDirectory => { TagTable => 'Image::ExifTool::XMP::dex' }, + }, + photomech => { + Name => 'photomech', + SubDirectory => { TagTable => 'Image::ExifTool::PhotoMechanic::XMP' }, + }, + mediapro => { + Name => 'mediapro', + SubDirectory => { TagTable => 'Image::ExifTool::XMP::MediaPro' }, + }, + expressionmedia => { + Name => 'expressionmedia', + SubDirectory => { TagTable => 'Image::ExifTool::XMP::ExpressionMedia' }, + }, + microsoft => { + Name => 'microsoft', + SubDirectory => { TagTable => 'Image::ExifTool::Microsoft::XMP' }, + }, + MP => { + Name => 'MP', + SubDirectory => { TagTable => 'Image::ExifTool::Microsoft::MP' }, + }, + MP1 => { + Name => 'MP1', + SubDirectory => { TagTable => 'Image::ExifTool::Microsoft::MP1' }, + }, + lr => { + Name => 'lr', + SubDirectory => { TagTable => 'Image::ExifTool::XMP::Lightroom' }, + }, + DICOM => { + Name => 'DICOM', + SubDirectory => { TagTable => 'Image::ExifTool::XMP::DICOM' }, + }, + album => { + Name => 'album', + SubDirectory => { TagTable => 'Image::ExifTool::XMP::Album' }, + }, + prism => { + Name => 'prism', + SubDirectory => { TagTable => 'Image::ExifTool::XMP::prism' }, + }, + prl => { + Name => 'prl', + SubDirectory => { TagTable => 'Image::ExifTool::XMP::prl' }, + }, + pur => { + Name => 'pur', + SubDirectory => { TagTable => 'Image::ExifTool::XMP::pur' }, + }, + pmi => { + Name => 'pmi', + SubDirectory => { TagTable => 'Image::ExifTool::XMP::pmi' }, + }, + prm => { + Name => 'prm', + SubDirectory => { TagTable => 'Image::ExifTool::XMP::prm' }, + }, + rdf => { + Name => 'rdf', + SubDirectory => { TagTable => 'Image::ExifTool::XMP::rdf' }, + }, + 'x' => { + Name => 'x', + SubDirectory => { TagTable => 'Image::ExifTool::XMP::x' }, + }, + acdsee => { + Name => 'acdsee', + SubDirectory => { TagTable => 'Image::ExifTool::XMP::acdsee' }, + }, + digiKam => { + Name => 'digiKam', + SubDirectory => { TagTable => 'Image::ExifTool::XMP::digiKam' }, + }, + swf => { + Name => 'swf', + SubDirectory => { TagTable => 'Image::ExifTool::XMP::swf' }, + }, + cell => { + Name => 'cell', + SubDirectory => { TagTable => 'Image::ExifTool::XMP::cell' }, + }, + aas => { + Name => 'aas', + SubDirectory => { TagTable => 'Image::ExifTool::XMP::aas' }, + }, + 'mwg-rs' => { + Name => 'mwg-rs', + SubDirectory => { TagTable => 'Image::ExifTool::MWG::Regions' }, + }, + 'mwg-kw' => { + Name => 'mwg-kw', + SubDirectory => { TagTable => 'Image::ExifTool::MWG::Keywords' }, + }, + 'mwg-coll' => { + Name => 'mwg-coll', + SubDirectory => { TagTable => 'Image::ExifTool::MWG::Collections' }, + }, + extensis => { + Name => 'extensis', + SubDirectory => { TagTable => 'Image::ExifTool::XMP::extensis' }, + }, + ics => { + Name => 'ics', + SubDirectory => { TagTable => 'Image::ExifTool::XMP::ics' }, + }, + fpv => { + Name => 'fpv', + SubDirectory => { TagTable => 'Image::ExifTool::XMP::fpv' }, + }, + creatorAtom => { + Name => 'creatorAtom', + SubDirectory => { TagTable => 'Image::ExifTool::XMP::creatorAtom' }, + }, + 'apple-fi' => { + Name => 'apple-fi', + SubDirectory => { TagTable => 'Image::ExifTool::XMP::apple_fi' }, + }, + GAudio => { + Name => 'GAudio', + SubDirectory => { TagTable => 'Image::ExifTool::XMP::GAudio' }, + }, + GImage => { + Name => 'GImage', + SubDirectory => { TagTable => 'Image::ExifTool::XMP::GImage' }, + }, + GPano => { + Name => 'GPano', + SubDirectory => { TagTable => 'Image::ExifTool::XMP::GPano' }, + }, + GSpherical => { + Name => 'GSpherical', + SubDirectory => { TagTable => 'Image::ExifTool::XMP::GSpherical' }, + }, + GDepth => { + Name => 'GDepth', + SubDirectory => { TagTable => 'Image::ExifTool::XMP::GDepth' }, + }, + GFocus => { + Name => 'GFocus', + SubDirectory => { TagTable => 'Image::ExifTool::XMP::GFocus' }, + }, + dwc => { + Name => 'dwc', + SubDirectory => { TagTable => 'Image::ExifTool::DarwinCore::Main' }, + }, + getty => { + Name => 'getty', + SubDirectory => { TagTable => 'Image::ExifTool::XMP::GettyImages' }, + }, + 'drone-dji' => { + Name => 'drone-dji', + SubDirectory => { TagTable => 'Image::ExifTool::DJI::XMP' }, + }, + LImage => { + Name => 'LImage', + SubDirectory => { TagTable => 'Image::ExifTool::XMP::LImage' }, + }, +); + +# hack to allow XML containing Dublin Core metadata to be handled like XMP (eg. EPUB - see ZIP.pm) +%Image::ExifTool::XMP::XML = ( + GROUPS => { 0 => 'XML', 1 => 'XML', 2 => 'Unknown' }, + PROCESS_PROC => \&ProcessXMP, + dc => { + Name => 'dc', + SubDirectory => { TagTable => 'Image::ExifTool::XMP::dc' }, + }, + lastUpdate => { + Groups => { 2 => 'Time' }, + ValueConv => 'Image::ExifTool::XMP::ConvertXMPDate($val)', + PrintConv => '$self->ConvertDateTime($val)', + }, +); + +# +# Tag tables for all XMP namespaces: +# +# Writable - only need to define this for writable tags if not plain text +# (boolean, integer, rational, real, date or lang-alt) +# List - XMP list type (Bag, Seq or Alt, or set to 1 for elements in Struct lists -- +# this is necessary to obtain proper list behaviour when reading/writing) +# +# (Note that family 1 group names are generated from the property namespace, not +# the group1 names below which exist so the groups will appear in the list.) +# +%xmpTableDefaults = ( + WRITE_PROC => \&WriteXMP, + CHECK_PROC => \&CheckXMP, + WRITABLE => 'string', + LANG_INFO => \&GetLangInfo, +); + +# rdf attributes extracted +%Image::ExifTool::XMP::rdf = ( + %xmpTableDefaults, + GROUPS => { 1 => 'XMP-rdf', 2 => 'Document' }, + NAMESPACE => 'rdf', + NOTES => q{ + Most RDF attributes are handled internally, but the "about" attribute is + treated specially to allow it to be set to a specific value if required. + }, + about => { Protected => 1 }, +); + +# x attributes extracted +%Image::ExifTool::XMP::x = ( + %xmpTableDefaults, + GROUPS => { 1 => 'XMP-x', 2 => 'Document' }, + NAMESPACE => 'x', + NOTES => qq{ + The "x" namespace is used for the "xmpmeta" wrapper, and may contain an + "xmptk" attribute that is extracted as the XMPToolkit tag. When writing, + the XMPToolkit tag is generated automatically by ExifTool unless + specifically set to another value. + }, + xmptk => { Name => 'XMPToolkit', Protected => 1 }, +); + +# Dublin Core namespace properties (dc) +%Image::ExifTool::XMP::dc = ( + %xmpTableDefaults, + GROUPS => { 1 => 'XMP-dc', 2 => 'Other' }, + NAMESPACE => 'dc', + TABLE_DESC => 'XMP Dublin Core', + NOTES => 'Dublin Core namespace tags.', + contributor => { Groups => { 2 => 'Author' }, List => 'Bag' }, + coverage => { }, + creator => { Groups => { 2 => 'Author' }, List => 'Seq' }, + date => { Groups => { 2 => 'Time' }, List => 'Seq', %dateTimeInfo }, + description => { Groups => { 2 => 'Image' }, Writable => 'lang-alt' }, + 'format' => { Groups => { 2 => 'Image' } }, + identifier => { Groups => { 2 => 'Image' } }, + language => { List => 'Bag' }, + publisher => { Groups => { 2 => 'Author' }, List => 'Bag' }, + relation => { List => 'Bag' }, + rights => { Groups => { 2 => 'Author' }, Writable => 'lang-alt' }, + source => { Groups => { 2 => 'Author' }, Avoid => 1 }, + subject => { Groups => { 2 => 'Image' }, List => 'Bag' }, + title => { Groups => { 2 => 'Image' }, Writable => 'lang-alt' }, + type => { Groups => { 2 => 'Image' }, List => 'Bag' }, +); + +# XMP namespace properties (xmp, xap) +%Image::ExifTool::XMP::xmp = ( + %xmpTableDefaults, + GROUPS => { 1 => 'XMP-xmp', 2 => 'Image' }, + NAMESPACE => 'xmp', + NOTES => q{ + XMP namespace tags. If the older "xap", "xapBJ", "xapMM" or "xapRights" + namespace prefixes are found, they are translated to the newer "xmp", + "xmpBJ", "xmpMM" and "xmpRights" prefixes for use in family 1 group names. + }, + Advisory => { List => 'Bag', Notes => 'deprecated' }, + BaseURL => { }, + # (date/time tags not as reliable as EXIF) + CreateDate => { Groups => { 2 => 'Time' }, %dateTimeInfo, Priority => 0 }, + CreatorTool => { }, + Identifier => { Avoid => 1, List => 'Bag' }, + Label => { }, + MetadataDate=> { Groups => { 2 => 'Time' }, %dateTimeInfo }, + ModifyDate => { Groups => { 2 => 'Time' }, %dateTimeInfo, Priority => 0 }, + Nickname => { }, + Rating => { Writable => 'real', Notes => 'a value from 0 to 5, or -1 for "rejected"' }, + Thumbnails => { + FlatName => 'Thumbnail', + Struct => \%sThumbnail, + List => 'Alt', + }, + # the following written by Adobe InDesign, not part of XMP spec: + PageInfo => { + FlatName => 'PageImage', + Struct => \%sPageInfo, + List => 'Seq', + }, + PageInfoImage => { Name => 'PageImage', Flat => 1 }, + Title => { Avoid => 1, Notes => 'non-standard', Writable => 'lang-alt' }, #11 + Author => { Avoid => 1, Notes => 'non-standard', Groups => { 2 => 'Author' } }, #11 + Keywords => { Avoid => 1, Notes => 'non-standard' }, #11 + Description => { Avoid => 1, Notes => 'non-standard', Writable => 'lang-alt' }, #11 + Format => { Avoid => 1, Notes => 'non-standard' }, #11 +); + +# XMP Rights Management namespace properties (xmpRights, xapRights) +%Image::ExifTool::XMP::xmpRights = ( + %xmpTableDefaults, + GROUPS => { 1 => 'XMP-xmpRights', 2 => 'Author' }, + NAMESPACE => 'xmpRights', + NOTES => 'XMP Rights Management namespace tags.', + Certificate => { }, + Marked => { Writable => 'boolean' }, + Owner => { List => 'Bag' }, + UsageTerms => { Writable => 'lang-alt' }, + WebStatement => { }, +); + +# XMP Note namespace properties (xmpNote) +%Image::ExifTool::XMP::xmpNote = ( + %xmpTableDefaults, + GROUPS => { 1 => 'XMP-xmpNote' }, + NAMESPACE => 'xmpNote', + NOTES => 'XMP Note namespace tags.', + HasExtendedXMP => { + Notes => q{ + this tag is protected so it is not writable directly. Instead, it is set + automatically to the GUID of the extended XMP when writing extended XMP to a + JPEG image + }, + Protected => 2, + }, +); + +# XMP xmpMM ManifestItem struct (ref PH, written by Adobe PDF library 8.0) +my %sManifestItem = ( + STRUCT_NAME => 'ManifestItem', + NAMESPACE => 'stMfs', + linkForm => { }, + placedXResolution => { Namespace => 'xmpMM', Writable => 'real' }, + placedYResolution => { Namespace => 'xmpMM', Writable => 'real' }, + placedResolutionUnit=> { Namespace => 'xmpMM' }, + reference => { Struct => \%sResourceRef }, +); + +# the xmpMM Pantry +my %sPantryItem = ( + STRUCT_NAME => 'PantryItem', + NAMESPACE => undef, # stores any top-level XMP tags + NOTES => q{ + This structure must have an InstanceID field, but may also contain any other + XMP properties. + }, + InstanceID => { Namespace => 'xmpMM' }, +); + +# XMP Media Management namespace properties (xmpMM, xapMM) +%Image::ExifTool::XMP::xmpMM = ( + %xmpTableDefaults, + GROUPS => { 1 => 'XMP-xmpMM', 2 => 'Other' }, + NAMESPACE => 'xmpMM', + TABLE_DESC => 'XMP Media Management', + NOTES => 'XMP Media Management namespace tags.', + DerivedFrom => { Struct => \%sResourceRef }, + DocumentID => { }, + History => { Struct => \%sResourceEvent, List => 'Seq' }, + # we treat these like list items since History is a list + Ingredients => { Struct => \%sResourceRef, List => 'Bag' }, + InstanceID => { }, #PH (CS3) + ManagedFrom => { Struct => \%sResourceRef }, + Manager => { Groups => { 2 => 'Author' } }, + ManageTo => { Groups => { 2 => 'Author' } }, + ManageUI => { }, + ManagerVariant => { }, + Manifest => { Struct => \%sManifestItem, List => 'Bag' }, + OriginalDocumentID=> { }, + Pantry => { Struct => \%sPantryItem, List => 'Bag' }, + PreservedFileName => { }, # undocumented + RenditionClass => { }, + RenditionParams => { }, + VersionID => { }, + Versions => { Struct => \%sVersion, List => 'Seq' }, + LastURL => { }, # (deprecated) + RenditionOf => { Struct => \%sResourceRef }, # (deprecated) + SaveID => { Writable => 'integer' }, # (deprecated) + subject => { List => 'Seq', Avoid => 1, Notes => 'undocumented' }, +); + +# XMP Basic Job Ticket namespace properties (xmpBJ, xapBJ) +%Image::ExifTool::XMP::xmpBJ = ( + %xmpTableDefaults, + GROUPS => { 1 => 'XMP-xmpBJ', 2 => 'Other' }, + NAMESPACE => 'xmpBJ', + TABLE_DESC => 'XMP Basic Job Ticket', + NOTES => 'XMP Basic Job Ticket namespace tags.', + # Note: JobRef is a List of structures. To accomplish this, we set the XMP + # List=>'Bag', but since SubDirectory is defined, this tag isn't writable + # directly. Then we need to set List=>1 for the members so the Writer logic + # will allow us to add list items. + JobRef => { Struct => \%sJobRef, List => 'Bag' }, +); + +# XMP Paged-Text namespace properties (xmpTPg) +%Image::ExifTool::XMP::xmpTPg = ( + %xmpTableDefaults, + GROUPS => { 1 => 'XMP-xmpTPg', 2 => 'Image' }, + NAMESPACE => 'xmpTPg', + TABLE_DESC => 'XMP Paged-Text', + NOTES => 'XMP Paged-Text namespace tags.', + MaxPageSize => { Struct => \%sDimensions }, + NPages => { Writable => 'integer' }, + Fonts => { + FlatName => '', + Struct => \%sFont, + List => 'Bag', + }, + FontsVersionString => { Name => 'FontVersion', Flat => 1 }, + FontsComposite => { Name => 'FontComposite', Flat => 1 }, + Colorants => { + FlatName => 'Colorant', + Struct => \%sColorant, + List => 'Seq', + }, + PlateNames => { List => 'Seq' }, + # the following found in an AI file: + HasVisibleTransparency => { Writable => 'boolean' }, + HasVisibleOverprint => { Writable => 'boolean' }, + SwatchGroups => { + Struct => \%sSwatchGroup, + List => 'Seq', + }, + SwatchGroupsColorants => { Name => 'SwatchGroupsColorants', Flat => 1 }, + SwatchGroupsGroupName => { Name => 'SwatchGroupName', Flat => 1 }, + SwatchGroupsGroupType => { Name => 'SwatchGroupType', Flat => 1 }, +); + +# PDF namespace properties (pdf) +%Image::ExifTool::XMP::pdf = ( + %xmpTableDefaults, + GROUPS => { 1 => 'XMP-pdf', 2 => 'Image' }, + NAMESPACE => 'pdf', + TABLE_DESC => 'XMP PDF', + NOTES => q{ + Adobe PDF namespace tags. The official XMP specification defines only + Keywords, PDFVersion, Producer and Trapped. The other tags are included + because they have been observed in PDF files, but some are avoided when + writing due to name conflicts with other XMP namespaces. + }, + Author => { Groups => { 2 => 'Author' } }, #PH + ModDate => { Groups => { 2 => 'Time' }, %dateTimeInfo }, #PH + CreationDate=> { Groups => { 2 => 'Time' }, %dateTimeInfo }, #PH + Creator => { Groups => { 2 => 'Author' }, Avoid => 1 }, + Copyright => { Groups => { 2 => 'Author' }, Avoid => 1 }, #PH + Marked => { Avoid => 1, Writable => 'boolean' }, #PH + Subject => { Avoid => 1 }, + Title => { Avoid => 1 }, + Trapped => { #PH + # remove leading '/' from '/True' or '/False' + ValueConv => '$val=~s{^/}{}; $val', + ValueConvInv => '"/$val"', + PrintConv => { True => 'True', False => 'False', Unknown => 'Unknown' }, + }, + Keywords => { Priority => -1 }, # (-1 to get below Priority 0 PDF:Keywords) + PDFVersion => { }, + Producer => { Groups => { 2 => 'Author' } }, +); + +# PDF extension namespace properties (pdfx) +%Image::ExifTool::XMP::pdfx = ( + %xmpTableDefaults, + GROUPS => { 1 => 'XMP-pdfx', 2 => 'Document' }, + NAMESPACE => 'pdfx', + NOTES => q{ + PDF extension tags. This namespace is used to store application-defined PDF + information, so there are no pre-defined tags. User-defined tags must be + created to enable writing of XMP-pdfx information. + }, +); + +# Photoshop namespace properties (photoshop) +%Image::ExifTool::XMP::photoshop = ( + %xmpTableDefaults, + GROUPS => { 1 => 'XMP-photoshop', 2 => 'Image' }, + NAMESPACE => 'photoshop', + TABLE_DESC => 'XMP Photoshop', + NOTES => 'Adobe Photoshop namespace tags.', + AuthorsPosition => { Groups => { 2 => 'Author' } }, + CaptionWriter => { Groups => { 2 => 'Author' } }, + Category => { }, + City => { Groups => { 2 => 'Location' } }, + ColorMode => { + Writable => 'integer', # (as of July 2010 spec, courtesy of yours truly) + PrintConvColumns => 2, + PrintConv => { + 0 => 'Bitmap', + 1 => 'Grayscale', + 2 => 'Indexed', + 3 => 'RGB', + 4 => 'CMYK', + 7 => 'Multichannel', + 8 => 'Duotone', + 9 => 'Lab', + }, + }, + Country => { Groups => { 2 => 'Location' } }, + Credit => { Groups => { 2 => 'Author' } }, + DateCreated => { Groups => { 2 => 'Time' }, %dateTimeInfo }, + DocumentAncestors => { + List => 'Bag', + # Contrary to their own XMP specification, Adobe writes this as a simple Bag + # of strings instead of structures, so comment out the structure definition... + # FlatName => 'Document', + # Struct => { + # STRUCT_NAME => 'Ancestor', + # NAMESPACE => 'photoshop', + # AncestorID => { }, + # }, + }, + Headline => { }, + History => { }, #PH (CS3) + ICCProfile => { Name => 'ICCProfileName' }, #PH + Instructions => { }, + LegacyIPTCDigest=> { }, #PH + SidecarForExtension => { }, #PH (CS3) + Source => { Groups => { 2 => 'Author' } }, + State => { Groups => { 2 => 'Location' } }, + # the XMP spec doesn't show SupplementalCategories as a 'Bag', but + # that's the way Photoshop writes it [fixed in the June 2005 XMP spec]. + # Also, it is incorrectly listed as "SupplementalCategory" in the + # IPTC Standard Photo Metadata docs (2008rev2 and July 2009rev1) - PH + SupplementalCategories => { List => 'Bag' }, + TextLayers => { + FlatName => 'Text', + List => 'Seq', + Struct => { + STRUCT_NAME => 'Layer', + NAMESPACE => 'photoshop', + LayerName => { }, + LayerText => { }, + }, + }, + TransmissionReference => { }, + Urgency => { + Writable => 'integer', + Notes => 'should be in the range 1-8 to conform with the XMP spec', + PrintConv => { # (same values as IPTC:Urgency) + 0 => '0 (reserved)', # (not standard XMP) + 1 => '1 (most urgent)', + 2 => 2, + 3 => 3, + 4 => 4, + 5 => '5 (normal urgency)', + 6 => 6, + 7 => 7, + 8 => '8 (least urgent)', + 9 => '9 (user-defined priority)', # (not standard XMP) + }, + }, + EmbeddedXMPDigest => { }, #PH (LR5) +); + +# Photoshop Camera Raw namespace properties (crs) - (ref 8,PH) +%Image::ExifTool::XMP::crs = ( + %xmpTableDefaults, + GROUPS => { 1 => 'XMP-crs', 2 => 'Image' }, + NAMESPACE => 'crs', + TABLE_DESC => 'Photoshop Camera Raw namespace', + NOTES => q{ + Photoshop Camera Raw namespace tags. It is a shame that Adobe pollutes the + metadata space with these incredibly bulky image editing parameters. + }, + AlreadyApplied => { Writable => 'boolean' }, #PH (written by LightRoom beta 4.1) + AutoBrightness => { Writable => 'boolean' }, + AutoContrast => { Writable => 'boolean' }, + AutoExposure => { Writable => 'boolean' }, + AutoShadows => { Writable => 'boolean' }, + BlueHue => { Writable => 'integer' }, + BlueSaturation => { Writable => 'integer' }, + Brightness => { Writable => 'integer' }, + CameraProfile => { }, + ChromaticAberrationB=> { Writable => 'integer' }, + ChromaticAberrationR=> { Writable => 'integer' }, + ColorNoiseReduction => { Writable => 'integer' }, + Contrast => { Writable => 'integer', Avoid => 1 }, + Converter => { }, #PH guess (found in EXIF) + CropTop => { Writable => 'real' }, + CropLeft => { Writable => 'real' }, + CropBottom => { Writable => 'real' }, + CropRight => { Writable => 'real' }, + CropAngle => { Writable => 'real' }, + CropWidth => { Writable => 'real' }, + CropHeight => { Writable => 'real' }, + CropUnits => { + Writable => 'integer', + PrintConv => { + 0 => 'pixels', + 1 => 'inches', + 2 => 'cm', + }, + }, + Exposure => { Writable => 'real' }, + GreenHue => { Writable => 'integer' }, + GreenSaturation => { Writable => 'integer' }, + HasCrop => { Writable => 'boolean' }, + HasSettings => { Writable => 'boolean' }, + LuminanceSmoothing => { Writable => 'integer' }, + MoireFilter => { PrintConv => { Off=>'Off', On=>'On' } }, + RawFileName => { }, + RedHue => { Writable => 'integer' }, + RedSaturation => { Writable => 'integer' }, + Saturation => { Writable => 'integer', Avoid => 1 }, + Shadows => { Writable => 'integer' }, + ShadowTint => { Writable => 'integer' }, + Sharpness => { Writable => 'integer', Avoid => 1 }, + Smoothness => { Writable => 'integer' }, + Temperature => { Writable => 'integer', Name => 'ColorTemperature' }, + Tint => { Writable => 'integer' }, + ToneCurve => { List => 'Seq' }, + ToneCurveName => { + PrintConv => { + Linear => 'Linear', + 'Medium Contrast' => 'Medium Contrast', + 'Strong Contrast' => 'Strong Contrast', + Custom => 'Custom', + }, + }, + Version => { }, + VignetteAmount => { Writable => 'integer' }, + VignetteMidpoint=> { Writable => 'integer' }, + WhiteBalance => { + Avoid => 1, + PrintConv => { + 'As Shot' => 'As Shot', + Auto => 'Auto', + Daylight => 'Daylight', + Cloudy => 'Cloudy', + Shade => 'Shade', + Tungsten => 'Tungsten', + Fluorescent => 'Fluorescent', + Flash => 'Flash', + Custom => 'Custom', + }, + }, + # new tags observed in Adobe Lightroom output - PH + CameraProfileDigest => { }, + Clarity => { Writable => 'integer' }, + ConvertToGrayscale => { Writable => 'boolean' }, + Defringe => { Writable => 'integer' }, + FillLight => { Writable => 'integer' }, + HighlightRecovery => { Writable => 'integer' }, + HueAdjustmentAqua => { Writable => 'integer' }, + HueAdjustmentBlue => { Writable => 'integer' }, + HueAdjustmentGreen => { Writable => 'integer' }, + HueAdjustmentMagenta => { Writable => 'integer' }, + HueAdjustmentOrange => { Writable => 'integer' }, + HueAdjustmentPurple => { Writable => 'integer' }, + HueAdjustmentRed => { Writable => 'integer' }, + HueAdjustmentYellow => { Writable => 'integer' }, + IncrementalTemperature => { Writable => 'integer' }, + IncrementalTint => { Writable => 'integer' }, + LuminanceAdjustmentAqua => { Writable => 'integer' }, + LuminanceAdjustmentBlue => { Writable => 'integer' }, + LuminanceAdjustmentGreen => { Writable => 'integer' }, + LuminanceAdjustmentMagenta => { Writable => 'integer' }, + LuminanceAdjustmentOrange => { Writable => 'integer' }, + LuminanceAdjustmentPurple => { Writable => 'integer' }, + LuminanceAdjustmentRed => { Writable => 'integer' }, + LuminanceAdjustmentYellow => { Writable => 'integer' }, + ParametricDarks => { Writable => 'integer' }, + ParametricHighlights => { Writable => 'integer' }, + ParametricHighlightSplit => { Writable => 'integer' }, + ParametricLights => { Writable => 'integer' }, + ParametricMidtoneSplit => { Writable => 'integer' }, + ParametricShadows => { Writable => 'integer' }, + ParametricShadowSplit => { Writable => 'integer' }, + SaturationAdjustmentAqua => { Writable => 'integer' }, + SaturationAdjustmentBlue => { Writable => 'integer' }, + SaturationAdjustmentGreen => { Writable => 'integer' }, + SaturationAdjustmentMagenta => { Writable => 'integer' }, + SaturationAdjustmentOrange => { Writable => 'integer' }, + SaturationAdjustmentPurple => { Writable => 'integer' }, + SaturationAdjustmentRed => { Writable => 'integer' }, + SaturationAdjustmentYellow => { Writable => 'integer' }, + SharpenDetail => { Writable => 'integer' }, + SharpenEdgeMasking => { Writable => 'integer' }, + SharpenRadius => { Writable => 'real' }, + SplitToningBalance => { Writable => 'integer' }, + SplitToningHighlightHue => { Writable => 'integer' }, + SplitToningHighlightSaturation => { Writable => 'integer' }, + SplitToningShadowHue => { Writable => 'integer' }, + SplitToningShadowSaturation => { Writable => 'integer' }, + Vibrance => { Writable => 'integer' }, + # new tags written by LR 1.4 (not sure in what version they first appeared) + GrayMixerRed => { Writable => 'integer' }, + GrayMixerOrange => { Writable => 'integer' }, + GrayMixerYellow => { Writable => 'integer' }, + GrayMixerGreen => { Writable => 'integer' }, + GrayMixerAqua => { Writable => 'integer' }, + GrayMixerBlue => { Writable => 'integer' }, + GrayMixerPurple => { Writable => 'integer' }, + GrayMixerMagenta => { Writable => 'integer' }, + RetouchInfo => { List => 'Seq' }, + RedEyeInfo => { List => 'Seq' }, + # new tags written by LR 2.0 (ref PH) + CropUnit => { # was the XMP documentation wrong with "CropUnits"?? + Writable => 'integer', + PrintConv => { + 0 => 'pixels', + 1 => 'inches', + 2 => 'cm', + # have seen a value of 3 here! - PH + }, + }, + PostCropVignetteAmount => { Writable => 'integer' }, + PostCropVignetteMidpoint => { Writable => 'integer' }, + PostCropVignetteFeather => { Writable => 'integer' }, + PostCropVignetteRoundness => { Writable => 'integer' }, + PostCropVignetteStyle => { Writable => 'integer' }, + # disable List behaviour of flattened Gradient/PaintBasedCorrections + # because these are nested in lists and the flattened tags can't + # do justice to this complex structure + GradientBasedCorrections => { + FlatName => 'GradientBasedCorr', + Struct => \%sCorrection, + List => 'Seq', + }, + GradientBasedCorrectionsCorrectionMasks => { + Name => 'GradientBasedCorrMasks', + FlatName => 'GradientBasedCorrMask', + Flat => 1 + }, + GradientBasedCorrectionsCorrectionMasksDabs => { + Name => 'GradientBasedCorrMaskDabs', + Flat => 1, List => 0, + }, + PaintBasedCorrections => { + FlatName => 'PaintCorrection', + Struct => \%sCorrection, + List => 'Seq', + }, + PaintBasedCorrectionsCorrectionMasks => { + Name => 'PaintBasedCorrectionMasks', + FlatName => 'PaintCorrectionMask', + Flat => 1, + }, + PaintBasedCorrectionsCorrectionMasksDabs => { + Name => 'PaintCorrectionMaskDabs', + Flat => 1, List => 0, + }, + # new tags written by LR 3 (thanks Wolfgang Guelcker) + ProcessVersion => { }, + LensProfileEnable => { Writable => 'integer' }, + LensProfileSetup => { }, + LensProfileName => { }, + LensProfileFilename => { }, + LensProfileDigest => { }, + LensProfileDistortionScale => { Writable => 'integer' }, + LensProfileChromaticAberrationScale => { Writable => 'integer' }, + LensProfileVignettingScale => { Writable => 'integer' }, + LensManualDistortionAmount => { Writable => 'integer' }, + PerspectiveVertical => { Writable => 'integer' }, + PerspectiveHorizontal => { Writable => 'integer' }, + PerspectiveRotate => { Writable => 'real' }, + PerspectiveScale => { Writable => 'integer' }, + CropConstrainToWarp => { Writable => 'integer' }, + LuminanceNoiseReductionDetail => { Writable => 'integer' }, + LuminanceNoiseReductionContrast => { Writable => 'integer' }, + ColorNoiseReductionDetail => { Writable => 'integer' }, + GrainAmount => { Writable => 'integer' }, + GrainSize => { Writable => 'integer' }, + GrainFrequency => { Writable => 'integer' }, + # new tags written by LR4 + AutoLateralCA => { Writable => 'integer' }, + Exposure2012 => { Writable => 'real' }, + Contrast2012 => { Writable => 'integer' }, + Highlights2012 => { Writable => 'integer' }, + Shadows2012 => { Writable => 'integer' }, + Whites2012 => { Writable => 'integer' }, + Blacks2012 => { Writable => 'integer' }, + Clarity2012 => { Writable => 'integer' }, + PostCropVignetteHighlightContrast => { Writable => 'integer' }, + ToneCurveName2012 => { }, + ToneCurveRed => { List => 'Seq' }, + ToneCurveGreen => { List => 'Seq' }, + ToneCurveBlue => { List => 'Seq' }, + ToneCurvePV2012 => { List => 'Seq' }, + ToneCurvePV2012Red => { List => 'Seq' }, + ToneCurvePV2012Green => { List => 'Seq' }, + ToneCurvePV2012Blue => { List => 'Seq' }, + DefringePurpleAmount => { Writable => 'integer' }, + DefringePurpleHueLo => { Writable => 'integer' }, + DefringePurpleHueHi => { Writable => 'integer' }, + DefringeGreenAmount => { Writable => 'integer' }, + DefringeGreenHueLo => { Writable => 'integer' }, + DefringeGreenHueHi => { Writable => 'integer' }, + # new tags written by LR5 + AutoWhiteVersion => { Writable => 'integer' }, + CircularGradientBasedCorrections => { + FlatName => 'CircGradBasedCorr', + Struct => \%sCorrection, + List => 'Seq', + }, + CircularGradientBasedCorrectionsCorrectionMasks => { + Name => 'CircGradBasedCorrMasks', + FlatName => 'CircGradBasedCorrMask', + Flat => 1 + }, + CircularGradientBasedCorrectionsCorrectionMasksDabs => { + Name => 'CircGradBasedCorrMaskDabs', + Flat => 1, List => 0, + }, + ColorNoiseReductionSmoothness => { Writable => 'integer' }, + PerspectiveAspect => { Writable => 'integer' }, + PerspectiveUpright => { Writable => 'integer' }, + RetouchAreas => { + FlatName => 'RetouchArea', + Struct => \%sRetouchArea, + List => 'Seq', + }, + RetouchAreasMasks => { + Name => 'RetouchAreaMasks', + FlatName => 'RetouchAreaMask', + Flat => 1 + }, + RetouchAreasMasksDabs => { + Name => 'RetouchAreaMaskDabs', + Flat => 1, List => 0, + }, + UprightVersion => { Writable => 'integer' }, + UprightCenterMode => { Writable => 'integer' }, + UprightCenterNormX => { Writable => 'real' }, + UprightCenterNormY => { Writable => 'real' }, + UprightFocalMode => { Writable => 'integer' }, + UprightFocalLength35mm => { Writable => 'real' }, + UprightPreview => { Writable => 'boolean' }, + UprightTransformCount => { Writable => 'integer' }, + UprightDependentDigest => { }, + UprightTransform_0 => { }, + UprightTransform_1 => { }, + UprightTransform_2 => { }, + UprightTransform_3 => { }, + UprightTransform_4 => { }, + UprightTransform_5 => { }, + # more stuff seen in lens profile file (unknown source) + What => { }, # (with value "LensProfileDefaultSettings") + LensProfileMatchKeyExifMake => { }, + LensProfileMatchKeyExifModel => { }, + LensProfileMatchKeyCameraModelName => { }, + LensProfileMatchKeyLensInfo => { }, + LensProfileMatchKeyLensID => { }, + LensProfileMatchKeyLensName => { }, + LensProfileMatchKeyIsRaw => { Writable => 'boolean' }, + LensProfileMatchKeySensorFormatFactor=>{ Writable => 'real' }, + # more stuff (ref forum6993) + DefaultAutoTone => { Writable => 'boolean' }, + DefaultAutoGray => { Writable => 'boolean' }, + DefaultsSpecificToSerial => { Writable => 'boolean' }, + DefaultsSpecificToISO => { Writable => 'boolean' }, + DNGIgnoreSidecars => { Writable => 'boolean' }, + NegativeCachePath => { }, + NegativeCacheMaximumSize => { Writable => 'real' }, + NegativeCacheLargePreviewSize => { Writable => 'integer' }, + JPEGHandling => { }, + TIFFHandling => { }, + Dehaze => { Writable => 'real' }, + ToneMapStrength => { Writable => 'real' }, + # yet more + PerspectiveX => { Writable => 'real' }, + PerspectiveY => { Writable => 'real' }, + UprightFourSegmentsCount => { Writable => 'integer' }, + AutoTone => { Writable => 'boolean' }, +); + +# Tiff namespace properties (tiff) +%Image::ExifTool::XMP::tiff = ( + %xmpTableDefaults, + GROUPS => { 1 => 'XMP-tiff', 2 => 'Image' }, + NAMESPACE => 'tiff', + PRIORITY => 0, # not as reliable as actual TIFF tags + TABLE_DESC => 'XMP TIFF', + NOTES => q{ + EXIF namespace for TIFF tags. See + L<http://www.cipa.jp/std/documents/e/DC-010-2017_E.pdf> for the + specification. + }, + ImageWidth => { Writable => 'integer' }, + ImageLength => { Writable => 'integer', Name => 'ImageHeight' }, + BitsPerSample => { Writable => 'integer', List => 'Seq', AutoSplit => 1 }, + Compression => { + Writable => 'integer', + SeparateTable => 'EXIF Compression', + PrintConv => \%Image::ExifTool::Exif::compression, + }, + PhotometricInterpretation => { + Writable => 'integer', + PrintConv => \%Image::ExifTool::Exif::photometricInterpretation, + }, + Orientation => { + Writable => 'integer', + PrintConv => \%Image::ExifTool::Exif::orientation, + }, + SamplesPerPixel => { Writable => 'integer' }, + PlanarConfiguration => { + Writable => 'integer', + PrintConv => { + 1 => 'Chunky', + 2 => 'Planar', + }, + }, + YCbCrSubSampling => { + Writable => 'integer', + List => 'Seq', + # join the raw values before conversion to allow PrintConv to operate on + # the combined string as it does for the corresponding EXIF tag + RawJoin => 1, + Notes => q{ + while technically this is a list-type tag, for compatibility with its EXIF + counterpart it is written and read as a simple string + }, + PrintConv => \%Image::ExifTool::JPEG::yCbCrSubSampling, + }, + YCbCrPositioning => { + Writable => 'integer', + PrintConv => { + 1 => 'Centered', + 2 => 'Co-sited', + }, + }, + XResolution => { Writable => 'rational' }, + YResolution => { Writable => 'rational' }, + ResolutionUnit => { + Writable => 'integer', + Notes => 'the value 1 is not standard EXIF', + PrintConv => { + 1 => 'None', + 2 => 'inches', + 3 => 'cm', + }, + }, + TransferFunction => { Writable => 'integer', List => 'Seq', AutoSplit => 1 }, + WhitePoint => { Writable => 'rational', List => 'Seq', AutoSplit => 1 }, + PrimaryChromaticities => { Writable => 'rational', List => 'Seq', AutoSplit => 1 }, + YCbCrCoefficients => { Writable => 'rational', List => 'Seq', AutoSplit => 1 }, + ReferenceBlackWhite => { Writable => 'rational', List => 'Seq', AutoSplit => 1 }, + DateTime => { # (EXIF tag named ModifyDate, but this exists in XMP-xmp) + Description => 'Date/Time Modified', + Groups => { 2 => 'Time' }, + %dateTimeInfo, + }, + ImageDescription => { Writable => 'lang-alt' }, + Make => { + Groups => { 2 => 'Camera' }, + RawConv => '$$self{Make} ? $val : $$self{Make} = $val', + }, + Model => { + Groups => { 2 => 'Camera' }, + Description => 'Camera Model Name', + RawConv => '$$self{Model} ? $val : $$self{Model} = $val', + }, + Software => { }, + Artist => { Groups => { 2 => 'Author' } }, + Copyright => { Groups => { 2 => 'Author' }, Writable => 'lang-alt' }, + NativeDigest => { }, #PH +); + +# Exif namespace properties (exif) +%Image::ExifTool::XMP::exif = ( + %xmpTableDefaults, + GROUPS => { 1 => 'XMP-exif', 2 => 'Image' }, + NAMESPACE => 'exif', + PRIORITY => 0, # not as reliable as actual EXIF tags + NOTES => q{ + EXIF namespace for EXIF tags. See + L<http://www.cipa.jp/std/documents/e/DC-010-2017_E.pdf> for the + specification. + }, + ExifVersion => { }, + FlashpixVersion => { }, + ColorSpace => { + Writable => 'integer', + # (some applications incorrectly write -1 as a long integer) + ValueConv => '$val == 0xffffffff ? 0xffff : $val', + ValueConvInv => '$val', + PrintConv => { + 1 => 'sRGB', + 2 => 'Adobe RGB', + 0xffff => 'Uncalibrated', + }, + }, + ComponentsConfiguration => { + Writable => 'integer', + List => 'Seq', + AutoSplit => 1, + PrintConvColumns => 2, + PrintConv => { + 0 => '-', + 1 => 'Y', + 2 => 'Cb', + 3 => 'Cr', + 4 => 'R', + 5 => 'G', + 6 => 'B', + }, + }, + CompressedBitsPerPixel => { Writable => 'rational' }, + PixelXDimension => { Name => 'ExifImageWidth', Writable => 'integer' }, + PixelYDimension => { Name => 'ExifImageHeight', Writable => 'integer' }, + MakerNote => { }, + UserComment => { Writable => 'lang-alt' }, + RelatedSoundFile => { }, + DateTimeOriginal => { + Description => 'Date/Time Original', + Groups => { 2 => 'Time' }, + %dateTimeInfo, + }, + DateTimeDigitized => { # (EXIF tag named CreateDate, but this exists in XMP-xmp) + Description => 'Date/Time Digitized', + Groups => { 2 => 'Time' }, + %dateTimeInfo, + }, + ExposureTime => { + Writable => 'rational', + PrintConv => 'Image::ExifTool::Exif::PrintExposureTime($val)', + PrintConvInv => '$val', + }, + FNumber => { + Writable => 'rational', + PrintConv => 'Image::ExifTool::Exif::PrintFNumber($val)', + PrintConvInv => '$val', + }, + ExposureProgram => { + Groups => { 2 => 'Camera' }, + Writable => 'integer', + PrintConv => { + 0 => 'Not Defined', + 1 => 'Manual', + 2 => 'Program AE', + 3 => 'Aperture-priority AE', + 4 => 'Shutter speed priority AE', + 5 => 'Creative (Slow speed)', + 6 => 'Action (High speed)', + 7 => 'Portrait', + 8 => 'Landscape', + }, + }, + SpectralSensitivity => { Groups => { 2 => 'Camera' } }, + ISOSpeedRatings => { + Name => 'ISO', + Writable => 'integer', + List => 'Seq', + AutoSplit => 1, + }, + OECF => { + Name => 'Opto-ElectricConvFactor', + FlatName => 'OECF', + Groups => { 2 => 'Camera' }, + Struct => \%sOECF, + }, + ShutterSpeedValue => { + Writable => 'rational', + ValueConv => 'abs($val)<100 ? 1/(2**$val) : 0', + PrintConv => 'Image::ExifTool::Exif::PrintExposureTime($val)', + ValueConvInv => '$val>0 ? -log($val)/log(2) : 0', + PrintConvInv => 'Image::ExifTool::Exif::ConvertFraction($val)', + }, + ApertureValue => { + Writable => 'rational', + ValueConv => 'sqrt(2) ** $val', + PrintConv => 'sprintf("%.1f",$val)', + ValueConvInv => '$val>0 ? 2*log($val)/log(2) : 0', + PrintConvInv => '$val', + }, + BrightnessValue => { Writable => 'rational' }, + ExposureBiasValue => { + Name => 'ExposureCompensation', + Writable => 'rational', + PrintConv => 'Image::ExifTool::Exif::PrintFraction($val)', + PrintConvInv => '$val', + }, + MaxApertureValue => { + Groups => { 2 => 'Camera' }, + Writable => 'rational', + ValueConv => 'sqrt(2) ** $val', + PrintConv => 'sprintf("%.1f",$val)', + ValueConvInv => '$val>0 ? 2*log($val)/log(2) : 0', + PrintConvInv => '$val', + }, + SubjectDistance => { + Groups => { 2 => 'Camera' }, + Writable => 'rational', + PrintConv => '$val =~ /^(inf|undef)$/ ? $val : "$val m"', + PrintConvInv => '$val=~s/\s*m$//;$val', + }, + MeteringMode => { + Groups => { 2 => 'Camera' }, + Writable => 'integer', + PrintConv => { + 1 => 'Average', + 2 => 'Center-weighted average', + 3 => 'Spot', + 4 => 'Multi-spot', + 5 => 'Multi-segment', + 6 => 'Partial', + 255 => 'Other', + }, + }, + LightSource => { + Groups => { 2 => 'Camera' }, + SeparateTable => 'EXIF LightSource', + PrintConv => \%Image::ExifTool::Exif::lightSource, + }, + Flash => { + Groups => { 2 => 'Camera' }, + Struct => { + STRUCT_NAME => 'Flash', + NAMESPACE => 'exif', + Fired => { Writable => 'boolean', %boolConv }, + Return => { + Writable => 'integer', + PrintConv => { + 0 => 'No return detection', + 2 => 'Return not detected', + 3 => 'Return detected', + }, + }, + Mode => { + Writable => 'integer', + PrintConv => { + 0 => 'Unknown', + 1 => 'On', + 2 => 'Off', + 3 => 'Auto', + }, + }, + Function => { Writable => 'boolean', %boolConv }, + RedEyeMode => { Writable => 'boolean', %boolConv }, + }, + }, + FocalLength=> { + Groups => { 2 => 'Camera' }, + Writable => 'rational', + PrintConv => 'sprintf("%.1f mm",$val)', + PrintConvInv => '$val=~s/\s*mm$//;$val', + }, + SubjectArea => { Writable => 'integer', List => 'Seq', AutoSplit => 1 }, + FlashEnergy => { Groups => { 2 => 'Camera' }, Writable => 'rational' }, + SpatialFrequencyResponse => { + Groups => { 2 => 'Camera' }, + Struct => \%sOECF, + }, + FocalPlaneXResolution => { Groups => { 2 => 'Camera' }, Writable => 'rational' }, + FocalPlaneYResolution => { Groups => { 2 => 'Camera' }, Writable => 'rational' }, + FocalPlaneResolutionUnit => { + Groups => { 2 => 'Camera' }, + Writable => 'integer', + Notes => 'values 1, 4 and 5 are not standard EXIF', + PrintConv => { + 1 => 'None', # (not standard EXIF) + 2 => 'inches', + 3 => 'cm', + 4 => 'mm', # (not standard EXIF) + 5 => 'um', # (not standard EXIF) + }, + }, + SubjectLocation => { Writable => 'integer', List => 'Seq', AutoSplit => 1 }, + ExposureIndex => { Writable => 'rational' }, + SensingMethod => { + Groups => { 2 => 'Camera' }, + Writable => 'integer', + Notes => 'values 1 and 6 are not standard EXIF', + PrintConv => { + 1 => 'Monochrome area', # (not standard EXIF) + 2 => 'One-chip color area', + 3 => 'Two-chip color area', + 4 => 'Three-chip color area', + 5 => 'Color sequential area', + 6 => 'Monochrome linear', # (not standard EXIF) + 7 => 'Trilinear', + 8 => 'Color sequential linear', + }, + }, + FileSource => { + Writable => 'integer', + PrintConv => { + 1 => 'Film Scanner', + 2 => 'Reflection Print Scanner', + 3 => 'Digital Camera', + } + }, + SceneType => { Writable => 'integer', PrintConv => { 1 => 'Directly photographed' } }, + CFAPattern => { + Struct => { + STRUCT_NAME => 'CFAPattern', + NAMESPACE => 'exif', + Columns => { Writable => 'integer' }, + Rows => { Writable => 'integer' }, + Values => { Writable => 'integer', List => 'Seq' }, + }, + }, + CustomRendered => { + Writable => 'integer', + PrintConv => { + 0 => 'Normal', + 1 => 'Custom', + }, + }, + ExposureMode => { + Groups => { 2 => 'Camera' }, + Writable => 'integer', + PrintConv => { + 0 => 'Auto', + 1 => 'Manual', + 2 => 'Auto bracket', + }, + }, + WhiteBalance => { + Groups => { 2 => 'Camera' }, + Writable => 'integer', + PrintConv => { + 0 => 'Auto', + 1 => 'Manual', + }, + }, + DigitalZoomRatio => { Writable => 'rational' }, + FocalLengthIn35mmFilm => { + Name => 'FocalLengthIn35mmFormat', + Writable => 'integer', + Groups => { 2 => 'Camera' }, + PrintConv => '"$val mm"', + PrintConvInv => '$val=~s/\s*mm$//;$val', + }, + SceneCaptureType => { + Groups => { 2 => 'Camera' }, + Writable => 'integer', + PrintConv => { + 0 => 'Standard', + 1 => 'Landscape', + 2 => 'Portrait', + 3 => 'Night', + }, + }, + GainControl => { + Groups => { 2 => 'Camera' }, + Writable => 'integer', + PrintConv => { + 0 => 'None', + 1 => 'Low gain up', + 2 => 'High gain up', + 3 => 'Low gain down', + 4 => 'High gain down', + }, + }, + Contrast => { + Groups => { 2 => 'Camera' }, + Writable => 'integer', + PrintConv => { + 0 => 'Normal', + 1 => 'Low', + 2 => 'High', + }, + PrintConvInv => 'Image::ExifTool::Exif::ConvertParameter($val)', + }, + Saturation => { + Groups => { 2 => 'Camera' }, + Writable => 'integer', + PrintConv => { + 0 => 'Normal', + 1 => 'Low', + 2 => 'High', + }, + PrintConvInv => 'Image::ExifTool::Exif::ConvertParameter($val)', + }, + Sharpness => { + Groups => { 2 => 'Camera' }, + Writable => 'integer', + PrintConv => { + 0 => 'Normal', + 1 => 'Soft', + 2 => 'Hard', + }, + PrintConvInv => 'Image::ExifTool::Exif::ConvertParameter($val)', + }, + DeviceSettingDescription => { + Groups => { 2 => 'Camera' }, + Struct => { + STRUCT_NAME => 'DeviceSettings', + NAMESPACE => 'exif', + Columns => { Writable => 'integer' }, + Rows => { Writable => 'integer' }, + Settings => { List => 'Seq' }, + }, + }, + SubjectDistanceRange => { + Groups => { 2 => 'Camera' }, + Writable => 'integer', + PrintConv => { + 0 => 'Unknown', + 1 => 'Macro', + 2 => 'Close', + 3 => 'Distant', + }, + }, + ImageUniqueID => { }, + GPSVersionID => { Groups => { 2 => 'Location' } }, + GPSLatitude => { Groups => { 2 => 'Location' }, %latConv }, + GPSLongitude => { Groups => { 2 => 'Location' }, %longConv }, + GPSAltitudeRef => { + Groups => { 2 => 'Location' }, + Writable => 'integer', + PrintConv => { + 0 => 'Above Sea Level', + 1 => 'Below Sea Level', + }, + }, + GPSAltitude => { + Groups => { 2 => 'Location' }, + Writable => 'rational', + # extricate unsigned decimal number from string + ValueConvInv => '$val=~/((?=\d|\.\d)\d*(?:\.\d*)?)/ ? $1 : undef', + PrintConv => '$val =~ /^(inf|undef)$/ ? $val : "$val m"', + PrintConvInv => '$val=~s/\s*m$//;$val', + }, + GPSTimeStamp => { + Name => 'GPSDateTime', + Description => 'GPS Date/Time', + Groups => { 2 => 'Time' }, + Notes => q{ + a date/time tag called GPSTimeStamp by the XMP specification. This tag is + renamed here to prevent direct copy from EXIF:GPSTimeStamp which is a + time-only tag. Instead, the value of this tag should be taken from + Composite:GPSDateTime when copying from EXIF + }, + %dateTimeInfo, + }, + GPSSatellites => { Groups => { 2 => 'Location' } }, + GPSStatus => { + Groups => { 2 => 'Location' }, + PrintConv => { + A => 'Measurement Active', + V => 'Measurement Void', + }, + }, + GPSMeasureMode => { + Groups => { 2 => 'Location' }, + Writable => 'integer', + PrintConv => { + 2 => '2-Dimensional', + 3 => '3-Dimensional', + }, + }, + GPSDOP => { Groups => { 2 => 'Location' }, Writable => 'rational' }, + GPSSpeedRef => { + Groups => { 2 => 'Location' }, + PrintConv => { + K => 'km/h', + M => 'mph', + N => 'knots', + }, + }, + GPSSpeed => { Groups => { 2 => 'Location' }, Writable => 'rational' }, + GPSTrackRef => { + Groups => { 2 => 'Location' }, + PrintConv => { + M => 'Magnetic North', + T => 'True North', + }, + }, + GPSTrack => { Groups => { 2 => 'Location' }, Writable => 'rational' }, + GPSImgDirectionRef => { + Groups => { 2 => 'Location' }, + PrintConv => { + M => 'Magnetic North', + T => 'True North', + }, + }, + GPSImgDirection => { Groups => { 2 => 'Location' }, Writable => 'rational' }, + GPSMapDatum => { Groups => { 2 => 'Location' } }, + GPSDestLatitude => { Groups => { 2 => 'Location' }, %latConv }, + GPSDestLongitude=> { Groups => { 2 => 'Location' }, %longConv }, + GPSDestBearingRef => { + Groups => { 2 => 'Location' }, + PrintConv => { + M => 'Magnetic North', + T => 'True North', + }, + }, + GPSDestBearing => { Groups => { 2 => 'Location' }, Writable => 'rational' }, + GPSDestDistanceRef => { + Groups => { 2 => 'Location' }, + PrintConv => { + K => 'Kilometers', + M => 'Miles', + N => 'Nautical Miles', + }, + }, + GPSDestDistance => { + Groups => { 2 => 'Location' }, + Writable => 'rational', + }, + GPSProcessingMethod => { Groups => { 2 => 'Location' } }, + GPSAreaInformation => { Groups => { 2 => 'Location' } }, + GPSDifferential => { + Groups => { 2 => 'Location' }, + Writable => 'integer', + PrintConv => { + 0 => 'No Correction', + 1 => 'Differential Corrected', + }, + }, + GPSHPositioningError => { #12 + Description => 'GPS Horizontal Positioning Error', + Groups => { 2 => 'Location' }, + Writable => 'rational', + PrintConv => '"$val m"', + PrintConvInv => '$val=~s/\s*m$//; $val', + }, + NativeDigest => { }, #PH +); + +# Exif extended properties (exifEX, ref 12) +%Image::ExifTool::XMP::exifEX = ( + %xmpTableDefaults, + GROUPS => { 1 => 'XMP-exifEX', 2 => 'Image' }, + NAMESPACE => 'exifEX', + PRIORITY => 0, # not as reliable as actual EXIF tags + NOTES => q{ + EXIF tags added by the EXIF 2.31 for XMP specification (see + L<http://www.cipa.jp/std/documents/e/DC-010-2017_E.pdf>). + }, + Gamma => { Writable => 'rational' }, + PhotographicSensitivity => { Writable => 'integer' }, + SensitivityType => { + Writable => 'integer', + PrintConv => { + 0 => 'Unknown', + 1 => 'Standard Output Sensitivity', + 2 => 'Recommended Exposure Index', + 3 => 'ISO Speed', + 4 => 'Standard Output Sensitivity and Recommended Exposure Index', + 5 => 'Standard Output Sensitivity and ISO Speed', + 6 => 'Recommended Exposure Index and ISO Speed', + 7 => 'Standard Output Sensitivity, Recommended Exposure Index and ISO Speed', + }, + }, + StandardOutputSensitivity => { Writable => 'integer' }, + RecommendedExposureIndex => { Writable => 'integer' }, + ISOSpeed => { Writable => 'integer' }, + ISOSpeedLatitudeyyy => { + Description => 'ISO Speed Latitude yyy', + Writable => 'integer', + }, + ISOSpeedLatitudezzz => { + Description => 'ISO Speed Latitude zzz', + Writable => 'integer', + }, + CameraOwnerName => { Name => 'OwnerName' }, + BodySerialNumber => { Name => 'SerialNumber' }, + LensSpecification => { + Name => 'LensInfo', + Writable => 'rational', + List => 'Seq', + RawJoin => 1, # join list into a string before ValueConv + ValueConv => \&ConvertRationalList, + ValueConvInv => sub { + my $val = shift; + my @vals = split ' ', $val; + return $val unless @vals == 4; + foreach (@vals) { + $_ eq 'inf' and $_ = '1/0', next; + $_ eq 'undef' and $_ = '0/0', next; + Image::ExifTool::IsFloat($_) or return $val; + my @a = Image::ExifTool::Rationalize($_); + $_ = join '/', @a; + } + return \@vals; # return list reference (List-type tag) + }, + PrintConv => \&Image::ExifTool::Exif::PrintLensInfo, + PrintConvInv => \&Image::ExifTool::Exif::ConvertLensInfo, + Notes => q{ + unfortunately the EXIF 2.3 for XMP specification defined this new tag + instead of using the existing XMP-aux:LensInfo + }, + }, + LensMake => { }, + LensModel => { }, + LensSerialNumber => { }, + InteroperabilityIndex => { + Name => 'InteropIndex', + Description => 'Interoperability Index', + PrintConv => { + R98 => 'R98 - DCF basic file (sRGB)', + R03 => 'R03 - DCF option file (Adobe RGB)', + THM => 'THM - DCF thumbnail file', + }, + }, + # new in Exif 2.31 + Temperature => { Writable => 'rational', Name => 'AmbientTemperature' }, + Humidity => { Writable => 'rational' }, + Pressure => { Writable => 'rational' }, + WaterDepth => { Writable => 'rational' }, + Acceleration => { Writable => 'rational' }, + CameraElevationAngle=> { Writable => 'rational' }, +); + +# Auxiliary namespace properties (aux) - not fully documented (ref PH) +%Image::ExifTool::XMP::aux = ( + %xmpTableDefaults, + GROUPS => { 1 => 'XMP-aux', 2 => 'Camera' }, + NAMESPACE => 'aux', + NOTES => q{ + Adobe-defined auxiliary EXIF tags. This namespace existed in the XMP + specification until it was dropped in 2012, presumably due to the + introduction of the EXIF 2.3 for XMP specification and the exifEX namespace + at this time. For this reason, tags below with equivalents in the + L<exifEX namespace|/XMP exifEX Tags> are avoided when writing. + }, + Firmware => { }, #7 + FlashCompensation => { Writable => 'rational' }, #7 + ImageNumber => { }, #7 + LensInfo => { #7 + Notes => '4 rational values giving focal and aperture ranges', + Avoid => 1, + # convert to floating point values (or 'inf' or 'undef') + ValueConv => \&ConvertRationalList, + ValueConvInv => sub { + my $val = shift; + my @vals = split ' ', $val; + return $val unless @vals == 4; + foreach (@vals) { + $_ eq 'inf' and $_ = '1/0', next; + $_ eq 'undef' and $_ = '0/0', next; + Image::ExifTool::IsFloat($_) or return $val; + my @a = Image::ExifTool::Rationalize($_); + $_ = join '/', @a; + } + return join ' ', @vals; # return string (string tag) + }, + # convert to the form "12-20mm f/3.8-4.5" or "50mm f/1.4" + PrintConv => \&Image::ExifTool::Exif::PrintLensInfo, + PrintConvInv => \&Image::ExifTool::Exif::ConvertLensInfo, + }, + Lens => { }, + OwnerName => { Avoid => 1 }, #7 + SerialNumber => { Avoid => 1 }, + LensSerialNumber=> { Avoid => 1 }, + LensID => { + Priority => 0, + # prevent this from getting set from a LensID that has been converted + ValueConvInv => q{ + warn "Expected one or more integer values" if $val =~ /[^\d ]/; + return $val; + }, + }, + ApproximateFocusDistance => { Writable => 'rational' }, #PH (LR3) + # the following new in LR6 (ref forum6497) + IsMergedPanorama => { Writable => 'boolean' }, + IsMergedHDR => { Writable => 'boolean' }, + DistortionCorrectionAlreadyApplied => { Writable => 'boolean' }, + VignetteCorrectionAlreadyApplied => { Writable => 'boolean' }, + LateralChromaticAberrationCorrectionAlreadyApplied => { Writable => 'boolean' }, + LensDistortInfo => { }, # (LR 7.5.1, 4 signed rational values) +); + +# IPTC Core namespace properties (Iptc4xmpCore) (ref 4) +%Image::ExifTool::XMP::iptcCore = ( + %xmpTableDefaults, + GROUPS => { 1 => 'XMP-iptcCore', 2 => 'Author' }, + NAMESPACE => 'Iptc4xmpCore', + TABLE_DESC => 'XMP IPTC Core', + NOTES => q{ + IPTC Core namespace tags. The actual IPTC Core namespace prefix is + "Iptc4xmpCore", which is the prefix recorded in the file, but ExifTool + shortens this for the family 1 group name. (see + L<http://www.iptc.org/IPTC4XMP/>) + }, + CountryCode => { Groups => { 2 => 'Location' } }, + CreatorContactInfo => { + Struct => { + STRUCT_NAME => 'ContactInfo', + NAMESPACE => 'Iptc4xmpCore', + CiAdrCity => { }, + CiAdrCtry => { }, + CiAdrExtadr => { }, + CiAdrPcode => { }, + CiAdrRegion => { }, + CiEmailWork => { }, + CiTelWork => { }, + CiUrlWork => { }, + }, + }, + CreatorContactInfoCiAdrCity => { Flat => 1, Name => 'CreatorCity' }, + CreatorContactInfoCiAdrCtry => { Flat => 1, Name => 'CreatorCountry' }, + CreatorContactInfoCiAdrExtadr => { Flat => 1, Name => 'CreatorAddress' }, + CreatorContactInfoCiAdrPcode => { Flat => 1, Name => 'CreatorPostalCode' }, + CreatorContactInfoCiAdrRegion => { Flat => 1, Name => 'CreatorRegion' }, + CreatorContactInfoCiEmailWork => { Flat => 1, Name => 'CreatorWorkEmail' }, + CreatorContactInfoCiTelWork => { Flat => 1, Name => 'CreatorWorkTelephone' }, + CreatorContactInfoCiUrlWork => { Flat => 1, Name => 'CreatorWorkURL' }, + IntellectualGenre => { Groups => { 2 => 'Other' } }, + Location => { Groups => { 2 => 'Location' } }, + Scene => { Groups => { 2 => 'Other' }, List => 'Bag' }, + SubjectCode => { Groups => { 2 => 'Other' }, List => 'Bag' }, +); + +# Adobe Lightroom namespace properties (lr) (ref PH) +%Image::ExifTool::XMP::Lightroom = ( + %xmpTableDefaults, + GROUPS => { 1 => 'XMP-lr', 2 => 'Image' }, + NAMESPACE => 'lr', + TABLE_DESC => 'XMP Adobe Lightroom', + NOTES => 'Adobe Lightroom "lr" namespace tags.', + privateRTKInfo => { }, + hierarchicalSubject => { List => 'Bag' }, +); + +# Adobe Album namespace properties (album) (ref PH) +%Image::ExifTool::XMP::Album = ( + %xmpTableDefaults, + GROUPS => { 1 => 'XMP-album', 2 => 'Image' }, + NAMESPACE => 'album', + TABLE_DESC => 'XMP Adobe Album', + NOTES => 'Adobe Album namespace tags.', + Notes => { }, +); + +# table to add tags in other namespaces +%Image::ExifTool::XMP::other = ( + GROUPS => { 2 => 'Unknown' }, + LANG_INFO => \&GetLangInfo, +); + +# Composite XMP tags +%Image::ExifTool::XMP::Composite = ( + # get latitude/logitude reference from XMP lat/long tags + # (used to set EXIF GPS position from XMP tags) + GPSLatitudeRef => { + Require => 'XMP:GPSLatitude', + ValueConv => q{ + IsFloat($val[0]) and return $val[0] < 0 ? "S" : "N"; + $val[0] =~ /^.*([NS])/; + return $1; + }, + PrintConv => { N => 'North', S => 'South' }, + }, + GPSLongitudeRef => { + Require => 'XMP:GPSLongitude', + ValueConv => q{ + IsFloat($val[0]) and return $val[0] < 0 ? "W" : "E"; + $val[0] =~ /^.*([EW])/; + return $1; + }, + PrintConv => { E => 'East', W => 'West' }, + }, + GPSDestLatitudeRef => { + Require => 'XMP:GPSDestLatitude', + ValueConv => q{ + IsFloat($val[0]) and return $val[0] < 0 ? "S" : "N"; + $val[0] =~ /^.*([NS])/; + return $1; + }, + PrintConv => { N => 'North', S => 'South' }, + }, + GPSDestLongitudeRef => { + Require => 'XMP:GPSDestLongitude', + ValueConv => q{ + IsFloat($val[0]) and return $val[0] < 0 ? "W" : "E"; + $val[0] =~ /^.*([EW])/; + return $1; + }, + PrintConv => { E => 'East', W => 'West' }, + }, + LensID => { + Notes => 'attempt to convert numerical XMP-aux:LensID stored by Adobe applications', + Require => { + 0 => 'XMP-aux:LensID', + 1 => 'Make', + }, + Desire => { + 2 => 'LensInfo', + 3 => 'FocalLength', + 4 => 'LensModel', + 5 => 'MaxApertureValue', + }, + Inhibit => { + 6 => 'Composite:LensID', # don't override existing Composite:LensID + }, + ValueConv => '$val', + PrintConv => 'Image::ExifTool::XMP::PrintLensID($self, @val)', + }, + Flash => { + Notes => 'facilitates copying camera flash information between XMP and EXIF', + Desire => { + 0 => 'XMP:FlashFired', + 1 => 'XMP:FlashReturn', + 2 => 'XMP:FlashMode', + 3 => 'XMP:FlashFunction', + 4 => 'XMP:FlashRedEyeMode', + 5 => 'XMP:Flash', # handle structured flash information too + }, + Writable => 1, + PrintHex => 1, + SeparateTable => 'EXIF Flash', + ValueConv => q{ + if (ref $val[5] eq 'HASH') { + # copy structure fields into value array + my $i = 0; + $val[$i++] = $val[5]{$_} foreach qw(Fired Return Mode Function RedEyeMode); + } + return (($val[0] and lc($val[0]) eq 'true') ? 0x01 : 0) | + (($val[1] || 0) << 1) | + (($val[2] || 0) << 3) | + (($val[3] and lc($val[3]) eq 'true') ? 0x20 : 0) | + (($val[4] and lc($val[4]) eq 'true') ? 0x40 : 0); + }, + PrintConv => \%Image::ExifTool::Exif::flash, + WriteAlso => { + 'XMP:FlashFired' => '$val & 0x01 ? "True" : "False"', + 'XMP:FlashReturn' => '($val & 0x06) >> 1', + 'XMP:FlashMode' => '($val & 0x18) >> 3', + 'XMP:FlashFunction' => '$val & 0x20 ? "True" : "False"', + 'XMP:FlashRedEyeMode' => '$val & 0x40 ? "True" : "False"', + }, + }, +); + +# add our composite tags +Image::ExifTool::AddCompositeTags('Image::ExifTool::XMP'); + +#------------------------------------------------------------------------------ +# AutoLoad our writer routines when necessary +# +sub AUTOLOAD +{ + return Image::ExifTool::DoAutoLoad($AUTOLOAD, @_); +} + +#------------------------------------------------------------------------------ +# Escape necessary XML characters in UTF-8 string +# Inputs: 0) string to be escaped +# Returns: escaped string +my %charName = ('"'=>'quot', '&'=>'amp', "'"=>'#39', '<'=>'lt', '>'=>'gt'); +sub EscapeXML($) +{ + my $str = shift; + $str =~ s/([&><'"])/&$charName{$1};/sg; # escape necessary XML characters + return $str; +} + +#------------------------------------------------------------------------------ +# Unescape XML character references (entities and numerical) +# Inputs: 0) string to be unescaped +# 1) optional hash reference to convert entity names to numbers +# 2) optional character encoding +# Returns: unescaped string +my %charNum = ('quot'=>34, 'amp'=>38, 'apos'=>39, 'lt'=>60, 'gt'=>62); +sub UnescapeXML($;$$) +{ + my ($str, $conv, $enc) = @_; + $conv = \%charNum unless $conv; + $str =~ s/&(#?\w+);/UnescapeChar($1,$conv,$enc)/sge; + return $str; +} + +#------------------------------------------------------------------------------ +# Escape string for XML, ensuring valid XML and UTF-8 +# Inputs: 0) string +# Returns: escaped string +sub FullEscapeXML($) +{ + my $str = shift; + $str =~ s/([&><'"])/&$charName{$1};/sg; # escape necessary XML characters + $str =~ s/\\/&#92;/sg; # escape backslashes too + # then use C-escape sequences for invalid characters + if ($str =~ /[\0-\x1f]/ or IsUTF8(\$str) < 0) { + $str =~ s/([\0-\x1f\x80-\xff])/sprintf("\\x%.2x",ord $1)/sge; + } + return $str; +} + +#------------------------------------------------------------------------------ +# Unescape XML/C escaped string +# Inputs: 0) string +# Returns: unescaped string +sub FullUnescapeXML($) +{ + my $str = shift; + # unescape C escape sequences first + $str =~ s/\\x([\da-f]{2})/chr(hex($1))/sge; + my $conv = \%charNum; + $str =~ s/&(#?\w+);/UnescapeChar($1,$conv)/sge; + return $str; +} + +#------------------------------------------------------------------------------ +# Convert XML character reference to UTF-8 +# Inputs: 0) XML character reference stripped of the '&' and ';' (eg. 'quot', '#34', '#x22') +# 1) hash reference for looking up character numbers by name +# 2) optional character encoding (default 'UTF8') +# Returns: UTF-8 equivalent (or original character on conversion error) +sub UnescapeChar($$;$) +{ + my ($ch, $conv, $enc) = @_; + my $val = $$conv{$ch}; + unless (defined $val) { + if ($ch =~ /^#x([0-9a-fA-F]+)$/) { + $val = hex($1); + } elsif ($ch =~ /^#(\d+)$/) { + $val = $1; + } else { + return "&$ch;"; # should issue a warning here? [no] + } + } + return chr($val) if $val < 0x80; # simple ASCII + $val = $] >= 5.006001 ? pack('C0U', $val) : Image::ExifTool::PackUTF8($val); + $val = Image::ExifTool::Decode(undef, $val, 'UTF8', undef, $enc) if $enc and $enc ne 'UTF8'; + return $val; +} + +#------------------------------------------------------------------------------ +# Does a string contain valid UTF-8 characters? +# Inputs: 0) string reference +# Returns: 0=regular ASCII, -1=invalid UTF-8, 1=valid UTF-8 with maximum 16-bit +# wide characters, 2=valid UTF-8 requiring 32-bit wide characters +# Notes: Changes current string position +# (see http://www.fileformat.info/info/unicode/utf8.htm for help understanding this) +sub IsUTF8($) +{ + my $strPt = shift; + pos($$strPt) = 0; # start at beginning of string + return 0 unless $$strPt =~ /([\x80-\xff])/g; + my $rtnVal = 1; + for (;;) { + my $ch = ord($1); + # minimum lead byte for 2-byte sequence is 0xc2 (overlong sequences + # not allowed), 0xf8-0xfd are restricted by RFC 3629 (no 5 or 6 byte + # sequences), and 0xfe and 0xff are not valid in UTF-8 strings + return -1 if $ch < 0xc2 or $ch >= 0xf8; + # determine number of bytes remaining in sequence + my $n; + if ($ch < 0xe0) { + $n = 1; + } elsif ($ch < 0xf0) { + $n = 2; + } else { + $n = 3; + # character code is greater than 0xffff if more than 2 extra bytes + # were required in the UTF-8 character + $rtnVal = 2; + } + return -1 unless $$strPt =~ /\G([\x80-\xbf]{$n})/g; + # the following is ref https://www.cl.cam.ac.uk/%7Emgk25/ucs/utf8_check.c + if ($n == 2) { + return -1 if ($ch == 0xe0 and (ord($1) & 0xe0) == 0x80) or + ($ch == 0xed and (ord($1) & 0xe0) == 0xa0) or + ($ch == 0xef and ord($1) == 0xbf and + (ord(substr $1, 1) & 0xfe) == 0xbe); + } else { + return -1 if ($ch == 0xf0 and (ord($1) & 0xf0) == 0x80) or + ($ch == 0xf4 and ord($1) > 0x8f) or $ch > 0xf4; + } + last unless $$strPt =~ /([\x80-\xff])/g; + } + return $rtnVal; +} + +#------------------------------------------------------------------------------ +# Fix malformed UTF8 (by replacing bad bytes with specified character) +# Inputs: 0) string reference, 1) string to replace each bad byte, +# may be '' to delete bad bytes, or undef to use '?' +# Returns: true if string was fixed, and updates string +sub FixUTF8($;$) +{ + my ($strPt, $bad) = @_; + my $fixed; + pos($$strPt) = 0; # start at beginning of string + for (;;) { + last unless $$strPt =~ /([\x80-\xff])/g; + my $ch = ord($1); + my $pos = pos($$strPt); + # (see comments in IsUTF8() above) + if ($ch >= 0xc2 and $ch < 0xf8) { + my $n = $ch < 0xe0 ? 1 : ($ch < 0xf0 ? 2 : 3); + if ($$strPt =~ /\G([\x80-\xbf]{$n})/g) { + next if $n == 1; + if ($n == 2) { + next unless ($ch == 0xe0 and (ord($1) & 0xe0) == 0x80) or + ($ch == 0xed and (ord($1) & 0xe0) == 0xa0) or + ($ch == 0xef and ord($1) == 0xbf and + (ord(substr $1, 1) & 0xfe) == 0xbe); + } else { + next unless ($ch == 0xf0 and (ord($1) & 0xf0) == 0x80) or + ($ch == 0xf4 and ord($1) > 0x8f) or $ch > 0xf4; + } + } + } + # replace bad character + $bad = '?' unless defined $bad; + substr($$strPt, $pos-1, 1) = $bad; + pos($$strPt) = $pos-1 + length $bad; + $fixed = 1; + } + return $fixed; +} + +#------------------------------------------------------------------------------ +# Utility routine to decode a base64 string +# Inputs: 0) base64 string +# Returns: reference to decoded data +sub DecodeBase64($) +{ + local($^W) = 0; # unpack('u',...) gives bogus warning in 5.00[123] + my $str = shift; + + # truncate at first unrecognized character (base 64 data + # may only contain A-Z, a-z, 0-9, +, /, =, or white space) + $str =~ s/[^A-Za-z0-9+\/= \t\n\r\f].*//s; + # translate to uucoded and remove padding and white space + $str =~ tr/A-Za-z0-9+\/= \t\n\r\f/ -_/d; + + # convert the data to binary in chunks + my $chunkSize = 60; + my $uuLen = pack('c', 32 + $chunkSize * 3 / 4); # calculate length byte + my $dat = ''; + my ($i, $substr); + # loop through the whole chunks + my $len = length($str) - $chunkSize; + for ($i=0; $i<=$len; $i+=$chunkSize) { + $substr = substr($str, $i, $chunkSize); # get a chunk of the data + $dat .= unpack('u', $uuLen . $substr); # decode it + } + $len += $chunkSize; + # handle last partial chunk if necessary + if ($i < $len) { + $uuLen = pack('c', 32 + ($len-$i) * 3 / 4); # recalculate length + $substr = substr($str, $i, $len-$i); # get the last partial chunk + $dat .= unpack('u', $uuLen . $substr); # decode it + } + return \$dat; +} + +#------------------------------------------------------------------------------ +# Generate a tag ID for this XMP tag +# Inputs: 0) tag property name list ref, 1) array ref for receiving structure property list +# 2) array for receiving namespace list +# Returns: tagID and outtermost interesting namespace (or '' if no namespace) +sub GetXMPTagID($;$$) +{ + my ($props, $structProps, $nsList) = @_; + my ($tag, $prop, $namespace); + foreach $prop (@$props) { + # split name into namespace and property name + # (Note: namespace can be '' for property qualifiers) + my ($ns, $nm) = ($prop =~ /(.*?):(.*)/) ? ($1, $2) : ('', $prop); + if ($ignoreNamespace{$ns} or $ignoreProp{$prop}) { + # special case: don't ignore rdf numbered items + # (not technically allowed in XMP, but used in RDF/XML) + unless ($prop =~ /^rdf:(_\d+)$/) { + # save list index if necessary for structures + if ($structProps and @$structProps and $prop =~ /^rdf:li (\d+)$/) { + push @{$$structProps[-1]}, $1; + } + next; + } + $tag .= $1 if defined $tag; + } else { + $nm =~ s/ .*//; # remove nodeID if it exists + # all uppercase is ugly, so convert it + if ($nm !~ /[a-z]/) { + my $xlat = $stdXlatNS{$ns} || $ns; + my $info = $Image::ExifTool::XMP::Main{$xlat}; + my $table; + if (ref $info eq 'HASH' and $$info{SubDirectory}) { + $table = GetTagTable($$info{SubDirectory}{TagTable}); + } + unless ($table and $$table{$nm}) { + $nm = lc($nm); + $nm =~ s/_([a-z])/\u$1/g; + } + } + if (defined $tag) { + $tag .= ucfirst($nm); # add to tag name + } else { + $tag = $nm; + } + # save structure information if necessary + if ($structProps) { + push @$structProps, [ $nm ]; + push @$nsList, $ns if $nsList; + } + } + # save namespace of first property to contribute to tag name + $namespace = $ns unless $namespace; + } + if (wantarray) { + return ($tag, $namespace || ''); + } else { + return $tag; + } +} + +#------------------------------------------------------------------------------ +# Register namespace for specified user-defined table +# Inputs: 0) tag/structure table ref +# Returns: namespace prefix +sub RegisterNamespace($) +{ + my $table = shift; + return $$table{NAMESPACE} unless ref $$table{NAMESPACE}; + my $nsRef = $$table{NAMESPACE}; + # recognize as either a list or hash + my $ns; + if (ref $nsRef eq 'ARRAY') { + $ns = $$nsRef[0]; + $nsURI{$ns} = $$nsRef[1]; + $uri2ns{$$nsRef[1]} = $ns; + } else { # must be a hash + my @ns = sort keys %$nsRef; # allow multiple namespace definitions + while (@ns) { + $ns = pop @ns; + if ($nsURI{$ns} and $nsURI{$ns} ne $$nsRef{$ns}) { + warn "User-defined namespace prefix '${ns}' conflicts with existing namespace\n"; + } + $nsURI{$ns} = $$nsRef{$ns}; + $uri2ns{$$nsRef{$ns}} = $ns; + } + } + return $$table{NAMESPACE} = $ns; +} + +#------------------------------------------------------------------------------ +# Generate flattened tags and add to table +# Inputs: 0) tag table ref, 1) tag ID for Struct tag (if not defined, whole table is done), +# 2) flag to not expand sub-structures +# Returns: number of tags added (not counting those just initialized) +# Notes: Must have verified that $$tagTablePtr{$tagID}{Struct} exists before calling this routine +# - makes sure that the tagInfo Struct is a HASH reference +sub AddFlattenedTags($;$$) +{ + local $_; + my ($tagTablePtr, $tagID, $noSubStruct) = @_; + my $count = 0; + my @tagIDs; + + if (defined $tagID) { + push @tagIDs, $tagID; + } else { + foreach $tagID (TagTableKeys($tagTablePtr)) { + my $tagInfo = $$tagTablePtr{$tagID}; + next unless ref $tagInfo eq 'HASH' and $$tagInfo{Struct}; + push @tagIDs, $tagID; + } + } + + # loop through specified tags + foreach $tagID (@tagIDs) { + + my $tagInfo = $$tagTablePtr{$tagID}; + + $$tagInfo{Flattened} and next; # only generate flattened tags once + $$tagInfo{Flattened} = 1; + + my $strTable = $$tagInfo{Struct}; + unless (ref $strTable) { # (allow a structure name for backward compatibility only) + my $strName = $strTable; + $strTable = $Image::ExifTool::UserDefined::xmpStruct{$strTable} or next; + $$strTable{STRUCT_NAME} or $$strTable{STRUCT_NAME} = "XMP $strName"; + $$tagInfo{Struct} = $strTable; # replace old-style name with HASH ref + delete $$tagInfo{SubDirectory}; # deprecated use of SubDirectory in Struct tags + } + # do not add flattened tags to variable-namespace structures + next if exists $$strTable{NAMESPACE} and not defined $$strTable{NAMESPACE}; + + # get prefix for flattened tag names + my $flat = (defined $$tagInfo{FlatName} ? $$tagInfo{FlatName} : $$tagInfo{Name}); + + # get family 2 group name for this structure tag + my ($tagG2, $field); + $tagG2 = $$tagInfo{Groups}{2} if $$tagInfo{Groups}; + $tagG2 or $tagG2 = $$tagTablePtr{GROUPS}{2}; + + foreach $field (keys %$strTable) { + next if $specialStruct{$field}; + my $fieldInfo = $$strTable{$field}; + next if $$fieldInfo{LangCode}; # don't flatten lang-alt tags + next if $$fieldInfo{Struct} and $noSubStruct; # don't expand sub-structures if specified + # build a tag ID for the corresponding flattened tag + my $fieldName = ucfirst($field); + my $flatField = $$fieldInfo{FlatName} || $fieldName; + my $flatID = $tagID . $fieldName; + my $flatInfo = $$tagTablePtr{$flatID}; + if ($flatInfo) { + ref $flatInfo eq 'HASH' or warn("$flatInfo is not a HASH!\n"), next; # (to be safe) + # pre-defined flattened tags should have Flat flag set + if (not defined $$flatInfo{Flat} and $Image::ExifTool::debug) { + warn "Missing Flat flag for $$flatInfo{Name}\n"; + } + $$flatInfo{Flat} = 0; + # copy all missing entries from field information + foreach (keys %$fieldInfo) { + # must not copy PropertyPath (but can't delete it afterwards + # because the flat tag may already have this set) + next if $_ eq 'PropertyPath' or defined $$flatInfo{$_}; + # copy the property (making a copy of the Groups hash) + $$flatInfo{$_} = $_ eq 'Groups' ? { %{$$fieldInfo{$_}} } : $$fieldInfo{$_}; + } + # (NOTE: Can NOT delete Groups because we need them if GotGroups was done) + # re-generate List flag unless it is set to 0 + delete $$flatInfo{List} if $$flatInfo{List}; + } else { + # generate new flattened tag information based on structure field + my $flatName = $flat . $flatField; + $flatInfo = { %$fieldInfo, Name => $flatName, Flat => 0 }; + # make a copy of the Groups hash if necessary + $$flatInfo{Groups} = { %{$$fieldInfo{Groups}} } if $$fieldInfo{Groups}; + # add new flattened tag to table + AddTagToTable($tagTablePtr, $flatID, $flatInfo); + ++$count; + } + # propagate List flag (unless set to 0 in pre-defined flattened tag) + unless (defined $$flatInfo{List}) { + $$flatInfo{List} = $$fieldInfo{List} || 1 if $$fieldInfo{List} or $$tagInfo{List}; + } + # set group 2 name from the first existing family 2 group in the: + # 1) structure field Groups, 2) structure table GROUPS, 3) structure tag Groups + if ($$fieldInfo{Groups} and $$fieldInfo{Groups}{2}) { + $$flatInfo{Groups}{2} = $$fieldInfo{Groups}{2}; + } elsif ($$strTable{GROUPS} and $$strTable{GROUPS}{2}) { + $$flatInfo{Groups}{2} = $$strTable{GROUPS}{2}; + } else { + $$flatInfo{Groups}{2} = $tagG2; + } + # save reference to top-level structure + $$flatInfo{RootTagInfo} = $$tagInfo{RootTagInfo} || $tagInfo; + # recursively generate flattened tags for sub-structures + next unless $$flatInfo{Struct}; + length($flatID) > 250 and warn("Possible deep recursion for tag $flatID\n"), last; + # reset flattened tag just in case we flattened hierarchy in the wrong order + # because we must start from the outtermost structure to get the List flags right + # (this should only happen when building tag tables) + delete $$flatInfo{Flattened}; + $count += AddFlattenedTags($tagTablePtr, $flatID, $$flatInfo{NoSubStruct}); + } + } + return $count; +} + +#------------------------------------------------------------------------------ +# Get localized version of tagInfo hash +# Inputs: 0) tagInfo hash ref, 1) language code (eg. "x-default") +# Returns: new tagInfo hash ref, or undef if invalid +sub GetLangInfo($$) +{ + my ($tagInfo, $langCode) = @_; + # only allow alternate language tags in lang-alt lists + return undef unless $$tagInfo{Writable} and $$tagInfo{Writable} eq 'lang-alt'; + $langCode =~ tr/_/-/; # RFC 3066 specifies '-' as a separator + my $langInfo = Image::ExifTool::GetLangInfo($tagInfo, $langCode); + return $langInfo; +} + +#------------------------------------------------------------------------------ +# Get standard case for language code +# Inputs: 0) Language code +# Returns: Language code in standard case +sub StandardLangCase($) +{ + my $lang = shift; + # make 2nd subtag uppercase only if it is 2 letters + return lc($1) . uc($2) . lc($3) if $lang =~ /^([a-z]{2,3}|[xi])(-[a-z]{2})\b(.*)/i; + return lc($lang); +} + +#------------------------------------------------------------------------------ +# Scan for XMP in a file +# Inputs: 0) ExifTool object ref, 1) RAF reference +# Returns: 1 if xmp was found, 0 otherwise +# Notes: Currently only recognizes UTF8-encoded XMP +sub ScanForXMP($$) +{ + my ($et, $raf) = @_; + my ($buff, $xmp); + my $lastBuff = ''; + + $et->VPrint(0,"Scanning for XMP\n"); + for (;;) { + defined $buff or $raf->Read($buff, 65536) or return 0; + unless (defined $xmp) { + $lastBuff .= $buff; + unless ($lastBuff =~ /(<\?xpacket begin=)/g) { + # must keep last 15 bytes to match 16-byte "xpacket begin" string + $lastBuff = length($buff) <= 15 ? $buff : substr($buff, -15); + undef $buff; + next; + } + $xmp = $1; + $buff = substr($lastBuff, pos($lastBuff)); + } + my $pos = length($xmp) - 18; # (18 = length("<?xpacket end...") - 1) + $xmp .= $buff; # add new data to our XMP + pos($xmp) = $pos if $pos > 0; # set start for "xpacket end" scan + if ($xmp =~ /<\?xpacket end=['"][wr]['"]\?>/g) { + $buff = substr($xmp, pos($xmp)); # save data after end of XMP + $xmp = substr($xmp, 0, pos($xmp)); # isolate XMP + # check XMP for validity (not valid if it contains null bytes) + $pos = rindex($xmp, "\0") + 1 or last; + $lastBuff = substr($xmp, $pos); # re-parse beginning after last null byte + undef $xmp; + } else { + undef $buff; + } + } + unless ($$et{VALUE}{FileType}) { + $$et{FILE_TYPE} = $$et{FILE_EXT}; + $et->SetFileType('<unknown file containing XMP>', undef, ''); + } + my %dirInfo = ( + DataPt => \$xmp, + DirLen => length $xmp, + DataLen => length $xmp, + ); + ProcessXMP($et, \%dirInfo); + return 1; +} + +#------------------------------------------------------------------------------ +# Print conversion for XMP-aux:LensID +# Inputs: 0) ExifTool ref, 1) LensID, 2) Make, 3) LensInfo, 4) FocalLength, +# 5) LensModel, 6) MaxApertureValue +# (yes, this is ugly -- blame Adobe) +sub PrintLensID(@) +{ + local $_; + my ($et, $id, $make, $info, $focalLength, $lensModel, $maxAv) = @_; + my ($mk, $printConv); + my %alt = ( Pentax => 'Ricoh' ); # Pentax changed its name to Ricoh + # missing: Olympus (no XMP:LensID written by Adobe) + foreach $mk (qw(Canon Nikon Pentax Sony Sigma Samsung Leica)) { + next unless $make =~ /$mk/i or ($alt{$mk} and $make =~ /$alt{$mk}/i); + # get name of module containing the lens lookup (default "Make.pm") + my $mod = { Sigma => 'SigmaRaw', Leica => 'Panasonic' }->{$mk} || $mk; + require "Image/ExifTool/$mod.pm"; + # get the name of the lens name lookup (default "makeLensTypes") + # (canonLensTypes, pentaxLensTypes, nikonLensIDs, etc) + my $convName = "Image::ExifTool::${mod}::" . + ({ Nikon => 'nikonLensIDs' }->{$mk} || lc($mk) . 'LensTypes'); + no strict 'refs'; + %$convName or last; + my $printConv = \%$convName; + use strict 'refs'; + # sf = short focal + # lf = long focal + # sa = max aperture at short focal + # la = max aperture at long focal + my ($sf, $lf, $sa, $la); + if ($info) { + my @a = split ' ', $info; + $_ eq 'undef' and $_ = undef foreach @a; + ($sf, $lf, $sa, $la) = @a; + # for Sony and ambiguous LensID, $info data may be incorrect: + # use only if it agrees with $focalLength and $maxAv (ref JR) + if ($mk eq 'Sony' and + (($focalLength and (($sf and $focalLength < $sf - 0.5) or + ($lf and $focalLength > $lf + 0.5))) or + ($maxAv and (($sa and $maxAv < $sa - 0.15) or + ($la and $maxAv > $la + 0.15))))) + { + undef $sf; + undef $lf; + undef $sa; + undef $la; + } elsif ($maxAv) { + # (using the short-focal-length max aperture in place of MaxAperture + # is a bad approximation, so don't do this if MaxApertureValue exists) + undef $sa; + } + } + if ($mk eq 'Pentax' and $id =~ /^\d+$/) { + # for Pentax, CS4 stores an int16u, but we use 2 x int8u + $id = join(' ', unpack('C*', pack('n', $id))); + } + my $str = $$printConv{$id} || "Unknown ($id)"; + # Nikon is a special case because Adobe doesn't store the full LensID + if ($mk eq 'Nikon') { + my $hex = sprintf("%.2X", $id); + my (%newConv, %used); + my $i = 0; + foreach (grep /^$hex /, keys %$printConv) { + my $lens = $$printConv{$_}; + next if $used{$lens}; # avoid duplicates + $used{$lens} = 1; + $newConv{$i ? "$id.$i" : $id} = $lens; + ++$i; + } + $printConv = \%newConv; + } + return Image::ExifTool::Exif::PrintLensID($et, $str, $printConv, + undef, $id, $focalLength, $sa, $maxAv, $sf, $lf, $lensModel); + } + return "Unknown ($id)"; +} + +#------------------------------------------------------------------------------ +# Convert XMP date/time to EXIF format +# Inputs: 0) XMP date/time string, 1) set if we aren't sure this is a date +# Returns: EXIF date/time +sub ConvertXMPDate($;$) +{ + my ($val, $unsure) = @_; + if ($val =~ /^(\d{4})-(\d{2})-(\d{2})[T ](\d{2}:\d{2})(:\d{2})?\s*(\S*)$/) { + my $s = $5 || ''; # seconds may be missing + $val = "$1:$2:$3 $4$s$6"; # convert back to EXIF time format + } elsif (not $unsure and $val =~ /^(\d{4})(-\d{2}){0,2}/) { + $val =~ tr/-/:/; + } + return $val; +} + +#------------------------------------------------------------------------------ +# Convert rational string value +# Inputs: 0) string (converted to number, 'inf' or 'undef' on return if rational) +# Returns: true if value was converted +sub ConvertRational($) +{ + my $val = $_[0]; + $val =~ m{^(-?\d+)/(-?\d+)$} or return undef; + if ($2 != 0) { + $_[0] = $1 / $2; # calculate quotient + } elsif ($1) { + $_[0] = 'inf'; + } else { + $_[0] = 'undef'; + } + return 1; +} + +#------------------------------------------------------------------------------ +# Convert a string of floating point values to rationals +# Inputs: 0) string of floating point numbers separated by spaces +# Returns: string of rational numbers separated by spaces +sub ConvertRationalList($) +{ + my $val = shift; + my @vals = split ' ', $val; + return $val unless @vals == 4; + foreach (@vals) { + ConvertRational($_) or return $val; + } + return join ' ', @vals; +} + +#------------------------------------------------------------------------------ +# We found an XMP property name/value +# Inputs: 0) ExifTool object ref, 1) Pointer to tag table +# 2) reference to array of XMP property names (last is current property) +# 3) property value, 4) attribute hash ref (for 'xml:lang' or 'rdf:datatype') +# Returns: 1 if valid tag was found +sub FoundXMP($$$$;$) +{ + local $_; + my ($et, $tagTablePtr, $props, $val, $attrs) = @_; + my ($lang, @structProps, $rawVal, $rational); + my ($tag, $ns) = GetXMPTagID($props, $$et{OPTIONS}{Struct} ? \@structProps : undef); + return 0 unless $tag; # ignore things that aren't valid tags + + # translate namespace if necessary + $ns = $stdXlatNS{$ns} if $stdXlatNS{$ns}; + my $info = $$tagTablePtr{$ns}; + my ($table, $added, $xns, $tagID); + if ($info) { + $table = $$info{SubDirectory}{TagTable} or warn "Missing TagTable for $tag!\n"; + } elsif ($$props[0] eq 'svg:svg') { + if (not $ns) { + # disambiguate MetadataID by adding back the 'metadata' we ignored + $tag = 'metadataId' if $tag eq 'id' and $$props[1] eq 'svg:metadata'; + # use SVG namespace in SVG files if nothing better to use + $table = 'Image::ExifTool::XMP::SVG'; + } elsif (not grep /^rdf:/, @$props) { + # only other SVG information if not inside RDF (call it XMP if in RDF) + $table = 'Image::ExifTool::XMP::otherSVG'; + } + } + + if (not $ns and $$tagTablePtr{GROUPS}{0} ne 'XMP') { + # this is a simple XML table (no namespaces) + $tagID = $tag; + } else { + # look up this tag in the appropriate table + $table or $table = 'Image::ExifTool::XMP::other'; + $tagTablePtr = GetTagTable($table); + if ($$tagTablePtr{NAMESPACE}) { + $tagID = $tag; + } else { + # add XMP namespace prefix to avoid collisions in variable-namespace tables + $xns = $xmpNS{$ns} || $ns; + $tagID = "$xns:$tag"; + # add namespace to top-level structure property + $structProps[0][0] = "$xns:" . $structProps[0][0] if @structProps; + } + } + my $tagInfo = $et->GetTagInfo($tagTablePtr, $tagID); + + $lang = $$attrs{'xml:lang'} if $attrs; + + # must add a new tag table entry if this tag isn't pre-defined + # (or initialize from structure field if this is a pre-defined flattened tag) +NoLoop: + while (not $tagInfo or $$tagInfo{Flat}) { + my (@tagList, @nsList); + GetXMPTagID($props, \@tagList, \@nsList); + my ($ta, $t, $ti, $addedFlat, $i, $j); + # build tag ID strings for each level in the property path + foreach $ta (@tagList) { + # insert tag ID in index 1 of tagList list + $t = $$ta[1] = $t ? $t . ucfirst($$ta[0]) : $$ta[0]; + # generate flattened tags for top-level structure if necessary + next if defined $addedFlat; + $ti = $$tagTablePtr{$t} or next; + next unless ref $ti eq 'HASH' and $$ti{Struct}; + $addedFlat = AddFlattenedTags($tagTablePtr, $t); + if ($tagInfo) { + # all done if we just wanted to initialize the flattened tag + if ($$tagInfo{Flat}) { + warn "Orphan tagInfo with Flat flag set: $$tagInfo{Name}\n"; + delete $$tagInfo{Flat}; + } + last NoLoop; + } + # all done if we generated the tag we are looking for + $tagInfo = $$tagTablePtr{$tagID} and last NoLoop if $addedFlat; + } + my $name = ucfirst($tag); + + # search for the innermost containing structure + # (in case tag is an unknown field in a known structure) + # (only necessary if we found a structure above) + if (defined $addedFlat) { + my $t2 = ''; + for ($i=$#tagList-1; $i>=0; --$i) { + $t = $tagList[$i][1]; + $t2 = $tagList[$i+1][0] . ucfirst($t2); # build relative tag id + $ti = $$tagTablePtr{$t} or next; + next unless ref $ti eq 'HASH'; + my $strTable = $$ti{Struct} or next; + my $flat = (defined $$ti{FlatName} ? $$ti{FlatName} : $$ti{Name}); + $name = $flat . ucfirst($t2); + # don't continue if structure is known but field is not + last if $$strTable{NAMESPACE} or not exists $$strTable{NAMESPACE}; + # this is a variable-namespace structure, so we must: + # 1) get tagInfo from corresponding top-level XMP tag if it exists + # 2) add new entry in this tag table, but with namespace prefix on tag ID + my $n = $nsList[$i+1]; # namespace of structure field + # translate to standard ExifTool namespace + $n = $stdXlatNS{$n} if $stdXlatNS{$n}; + my $xn = $xmpNS{$n} || $n; # standard XMP namespace + # no need to continue with variable-namespace logic if + # we are in our own namespace (right?) + last if $xn eq ($$tagTablePtr{NAMESPACE} || ''); + $tagID = "$xn:$tag"; # add namespace to avoid collisions + # change structure properties to add the standard XMP namespace + # prefix for this field (needed for variable-namespace fields) + if (@structProps) { + $structProps[$i+1][0] = "$xn:" . $structProps[$i+1][0]; + } + # copy tagInfo entries from the existing top-level XMP tag + my $tg = $Image::ExifTool::XMP::Main{$n}; + last unless ref $tg eq 'HASH' and $$tg{SubDirectory}; + my $tbl = GetTagTable($$tg{SubDirectory}{TagTable}) or last; + my $sti = $et->GetTagInfo($tbl, $t2); + if (not $sti or $$sti{Flat}) { + # again, we must initialize flattened tags if necessary + # (but don't bother to recursively apply full logic to + # allow nested variable-namespace strucures until someone + # actually wants to do such a silly thing) + my $t3 = ''; + for ($j=$i+1; $j<@tagList; ++$j) { + $t3 = $tagList[$j][0] . ucfirst($t3); + my $ti3 = $$tbl{$t3} or next; + next unless ref $ti3 eq 'HASH' and $$ti3{Struct}; + last unless AddFlattenedTags($tbl, $t3); + $sti = $$tbl{$t2}; + last; + } + last unless $sti; + } + $tagInfo = { + %$sti, + Name => $flat . $$sti{Name}, + WasAdded => 1, + }; + # be careful not to copy elements we shouldn't... + delete $$tagInfo{Description}; # Description will be different + # can't copy group hash because group 1 will be different and + # we need to check this when writing tag to a specific group + delete $$tagInfo{Groups}; + $$tagInfo{Groups}{2} = $$sti{Groups}{2} if $$sti{Groups}; + last; + } + } + $tagInfo or $tagInfo = { Name => $name, WasAdded => 1, Priority => 0 }; + + # add tag Namespace entry for tags in variable-namespace tables + $$tagInfo{Namespace} = $xns if $xns; + if ($$et{curURI}{$ns} and $$et{curURI}{$ns} =~ m{^http://ns.exiftool.ca/(.*?)/(.*?)/}) { + my %grps = ( 0 => $1, 1 => $2 ); + # apply a little magic to recover original group names + # from this exiftool-written RDF/XML file + if ($grps{1} =~ /^\d/) { + # URI's with only family 0 are internal tags from the source file, + # so change the group name to avoid confusion with tags from this file + $grps{1} = "XML-$grps{0}"; + $grps{0} = 'XML'; + } + $$tagInfo{Groups} = \%grps; + # flag to avoid setting group 1 later + $$tagInfo{StaticGroup1} = 1; + } + # construct tag information for this unknown tag + # -> make this a List or lang-alt tag if necessary + if (@$props > 2 and $$props[-1] =~ /^rdf:li \d+$/ and + $$props[-2] =~ /^rdf:(Bag|Seq|Alt)$/) + { + if ($lang and $1 eq 'Alt') { + $$tagInfo{Writable} = 'lang-alt'; + } else { + $$tagInfo{List} = $1; + } + # tried this, but maybe not a good idea for complex structures: + #} elsif (grep / /, @$props) { + # $$tagInfo{List} = 1; + } + AddTagToTable($tagTablePtr, $tagID, $tagInfo); + $added = 1; + last; + } + # decode value if necessary (et:encoding was used before exiftool 7.71) + if ($attrs) { + my $enc = $$attrs{'rdf:datatype'} || $$attrs{'et:encoding'}; + if ($enc and $enc =~ /base64/) { + $val = DecodeBase64($val); # (now a value ref) + $val = $$val unless length $$val > 100 or $$val =~ /[\0-\x08\x0b\0x0c\x0e-\x1f]/; + } + } + if (defined $lang and lc($lang) ne 'x-default') { + $lang = StandardLangCase($lang); + my $langInfo = GetLangInfo($tagInfo, $lang); + $tagInfo = $langInfo if $langInfo; + } + # un-escape XML character entities (handling CDATA) + pos($val) = 0; + if ($val =~ /<!\[CDATA\[(.*?)\]\]>/sg) { + my $p = pos $val; + # unescape everything up to the start of the CDATA section + # (the length of "<[[CDATA[]]>" is 12 characters) + my $v = UnescapeXML(substr($val, 0, $p - length($1) - 12)) . $1; + while ($val =~ /<!\[CDATA\[(.*?)\]\]>/sg) { + my $p1 = pos $val; + $v .= UnescapeXML(substr($val, $p, $p1 - length($1) - 12)) . $1; + $p = $p1; + } + $val = $v . UnescapeXML(substr($val, $p)); + } else { + $val = UnescapeXML($val); + } + # decode from UTF8 + $val = $et->Decode($val, 'UTF8'); + # convert rational and date values to a more sensible format + my $fmt = $$tagInfo{Writable}; + my $new = $$tagInfo{WasAdded} && $$et{OPTIONS}{XMPAutoConv}; + if ($fmt or $new) { + $rawVal = $val; # save raw value for verbose output + if (($new or $fmt eq 'rational') and ConvertRational($val)) { + $rational = $rawVal; + } else { + $val = ConvertXMPDate($val, $new) if $new or $fmt eq 'date'; + } + # protect against large binary data in unknown tags + $$tagInfo{Binary} = 1 if $new and length($val) > 65536; + } + # store the value for this tag + my $key = $et->FoundTag($tagInfo, $val) or return 0; + # save original components of rational numbers (used when copying) + $$et{RATIONAL}{$key} = $rational if defined $rational; + # save structure/list information if necessary + if (@structProps and (@structProps > 1 or defined $structProps[0][1]) and + not $$et{NO_STRUCT}) + { + $$et{TAG_EXTRA}{$key}{Struct} = \@structProps; + $$et{IsStruct} = 1; + } + if ($ns and not $$tagInfo{StaticGroup1}) { + # set group1 dynamically according to the namespace + $et->SetGroup($key, "$$tagTablePtr{GROUPS}{0}-$ns"); + } + if ($$et{OPTIONS}{Verbose}) { + if ($added) { + my $g1 = $et->GetGroup($key, 1); + $et->VPrint(0, $$et{INDENT}, "[adding $g1:$tag]\n"); + } + my $tagID = join('/',@$props); + $et->VerboseInfo($tagID, $tagInfo, Value => $rawVal || $val); + } + return 1; +} + +#------------------------------------------------------------------------------ +# Recursively parse nested XMP data element +# Inputs: 0) ExifTool ref, 1) tag table ref, 2) XMP data ref +# 3) offset to start of XMP element, 4) offset to end of XMP element +# 5) reference to array of enclosing XMP property names (undef if none) +# 6) reference to blank node information hash +# Returns: Number of contained XMP elements +sub ParseXMPElement($$$;$$$$) +{ + local $_; + my ($et, $tagTablePtr, $dataPt, $start, $end, $propList, $blankInfo) = @_; + my ($count, $nItems) = (0, 0); + my $isWriting = $$et{XMP_CAPTURE}; + my $isSVG = $$et{XMP_IS_SVG}; + my $saveNS; # save xlatNS lookup if changed for the scope of this element + my (%definedNS, %usedNS); # namespaces defined and used in this scope + + # get our parse procs + my ($attrProc, $foundProc); + if ($$et{XMPParseOpts}) { + $attrProc = $$et{XMPParseOpts}{AttrProc}; + $foundProc = $$et{XMPParseOpts}{FoundProc} || \&FoundXMP; + } else { + $foundProc = \&FoundXMP; + } + $start or $start = 0; + $end or $end = length $$dataPt; + $propList or $propList = [ ]; + + my $processBlankInfo; + # create empty blank node information hash if necessary + $blankInfo or $blankInfo = $processBlankInfo = { Prop => { } }; + # keep track of current nodeID at this nesting level + my $oldNodeID = $$blankInfo{NodeID}; + pos($$dataPt) = $start; + + # lookup for translating namespace prefixes + my $xlatNS = $$et{xlatNS}; + + Element: for (;;) { + # all done if there isn't enough data for another element + # (the smallest possible element is 4 bytes, eg. "<a/>") + last if pos($$dataPt) > $end - 4; + # reset nodeID before processing each element + my $nodeID = $$blankInfo{NodeID} = $oldNodeID; + # get next element + last if $$dataPt !~ m{<([?/]?)([-\w:.\x80-\xff]+|!--)([^>]*)>}sg or pos($$dataPt) > $end; + # (the only reason we match '<[?/]' is to keep from scanning past the + # "<?xpacket end..." terminator or other closing token, so + next if $1; + my ($prop, $attrs) = ($2, $3); + # skip comments + if ($prop eq '!--') { + next if $attrs =~ /--$/ or $$dataPt =~ /-->/sg; + last; + } + my $valStart = pos($$dataPt); + my $valEnd; + # only look for closing token if this is not an empty element + # (empty elements end with '/', eg. <a:b/>) + if ($attrs !~ s/\/$//) { + my $nesting = 1; + my $tok; + for (;;) { +# this match fails with perl 5.6.2 (perl bug!), but it works without +# the '(.*?)', so we must do it differently... +# $$dataPt =~ m/(.*?)<\/$prop>/sg or last Element; +# my $val2 = $1; + # find next matching closing token, or the next opening token + # of a nested same-named element + if ($$dataPt !~ m{<(/?)$prop([-\w:.\x80-\xff]*)(.*?(/?))>}sg or + pos($$dataPt) > $end) + { + $et->Warn("XMP format error (no closing tag for $prop)"); + last Element; + } + next if $2; # ignore opening properties with different names + if ($1) { + next if --$nesting; + $valEnd = pos($$dataPt) - length($prop) - length($3) - 3; + last; # this element is complete + } + # this is a nested opening token (or empty element) + ++$nesting unless $4; + } + } else { + $valEnd = $valStart; + } + $start = pos($$dataPt); # start from here the next time around + + # extract property attributes + my ($parseResource, %attrs, @attrs); + while ($attrs =~ m/(\S+?)\s*=\s*(['"])(.*?)\2/sg) { + my ($attr, $val) = ($1, $3); + # handle namespace prefixes (defined by xmlns:PREFIX, or used with PREFIX:tag) + if ($attr =~ /(.*?):/) { + if ($1 eq 'xmlns') { + my $ns = substr($attr, 6); + my $stdNS = $uri2ns{$val}; + # keep track of namespace prefixes defined in this scope (for Validate) + $$et{definedNS}{$ns} = $definedNS{$ns} = 1 unless $$et{definedNS}{$ns}; + unless ($stdNS) { + my $try = $val; + # patch for Nikon NX2 URI bug for Microsoft PhotoInfo namespace + $try =~ s{/$}{} or $try .= '/'; + $stdNS = $uri2ns{$try}; + if ($stdNS) { + $val = $try; + $et->WarnOnce("Fixed incorrect URI for xmlns:$ns", 1); + } else { + # look for same namespace with different version number + $try = quotemeta $val; # (note: escapes slashes too) + $try =~ s{\\/\d+\\\.\d+(\\/|$)}{\\/\\d+\\\.\\d+$1}; + my ($good) = grep /^$try$/, keys %uri2ns; + if ($good) { + $stdNS = $uri2ns{$good}; + $et->VPrint(0, $$et{INDENT}, "[different $stdNS version: $val]\n"); + } + } + } + # tame wild namespace prefixes (patches Microsoft stupidity) + my $newNS; + if ($stdNS) { + # use standard namespace prefix if pre-defined + if ($stdNS ne $ns) { + $newNS = $stdNS; + } elsif ($$xlatNS{$ns}) { + # this prefix is re-defined to the standard prefix in this scope + $newNS = ''; + } + } elsif ($$et{curNS}{$val}) { + # use a consistent prefix over the entire XMP for a given namespace URI + $newNS = $$et{curNS}{$val} if $$et{curNS}{$val} ne $ns; + } else { + my $curURI = $$et{curURI}; + my $curNS = $$et{curNS}; + my $usedNS = $ns; + # use unique prefixes for all namespaces across the entire XMP + if ($$curURI{$ns} or $nsURI{$ns}) { + # generate a temporary namespace prefix to resolve any conflict + my $i = 0; + ++$i while $$curURI{"tmp$i"}; + $newNS = $usedNS = "tmp$i"; + } + # keep track of the namespace prefixes and URI's used in this XMP + $$curNS{$val} = $usedNS; + $$curURI{$usedNS} = $val; + } + if (defined $newNS) { + # save translation used in containing scope if necessary + # create new namespace translation for the scope of this element + $saveNS or $saveNS = $xlatNS, $xlatNS = $$et{xlatNS} = { %$xlatNS }; + if (length $newNS) { + # use the new namespace prefix + $$xlatNS{$ns} = $newNS; + $attr = 'xmlns:' . $newNS; + # must go through previous attributes and change prefixes if necessary + foreach (@attrs) { + next unless /(.*?):/ and $1 eq $ns and $1 ne $newNS; + my $newAttr = $newNS . substr($_, length($ns)); + $attrs{$newAttr} = $attrs{$_}; + delete $attrs{$_}; + $_ = $newAttr; + } + } else { + delete $$xlatNS{$ns}; + } + } + } else { + $attr = $$xlatNS{$1} . substr($attr, length($1)) if $$xlatNS{$1}; + $usedNS{$1} = 1; + } + } + push @attrs, $attr; # preserve order + $attrs{$attr} = $val; + } + if ($prop =~ /(.*?):/) { + $usedNS{$1} = 1; + # tame wild namespace prefixes (patch for Microsoft stupidity) + $prop = $$xlatNS{$1} . substr($prop, length($1)) if $$xlatNS{$1}; + } + + if ($prop eq 'rdf:li') { + # impose a reasonable maximum on the number of items in a list + if ($nItems == 1000) { + my ($tg,$ns) = GetXMPTagID($propList); + if ($isWriting) { + $et->Warn("Excessive number of items for $ns:$tg. Processing may be slow", 1); + } elsif (not $$et{OPTIONS}{IgnoreMinorErrors}) { + $et->Warn("Extracted only 1000 $ns:$tg items. Ignore minor errors to extract all", 2); + last; + } + } + # add index to list items so we can keep them in order + # (this also enables us to keep structure elements grouped properly + # for lists of structures, like JobRef) + # Note: the list index is prefixed by the number of digits so sorting + # alphabetically gives the correct order while still allowing a flexible + # number of digits -- this scheme allows up to 9 digits in the index, + # with index numbers ranging from 0 to 999999999. The sequence is: + # 10,11,12-19,210,211-299,3100,3101-3999,41000...9999999999. + $prop .= ' ' . length($nItems) . $nItems; + # reset LIST_TAGS at the start of the outtermost list + # (avoids accumulating incorrectly-written elements in a correctly-written list) + if (not $nItems and not grep /^rdf:li /, @$propList) { + $$et{LIST_TAGS} = { }; + } + ++$nItems; + } elsif ($prop eq 'rdf:Description') { + # remove unnecessary rdf:Description elements since parseType='Resource' + # is more efficient (also necessary to make property path consistent) + $parseResource = 1 if grep /^rdf:Description$/, @$propList; + } elsif ($prop eq 'xmp:xmpmeta') { + # patch MicrosoftPhoto unconformity + $prop = 'x:xmpmeta'; + $et->Warn('Wrong namespace for xmpmeta') if $$et{XmpValidate}; + } + + # hook for special parsing of attributes + my $val; + if ($attrProc) { + $val = substr($$dataPt, $valStart, $valEnd - $valStart); + if (&$attrProc(\@attrs, \%attrs, \$prop, \$val)) { + # the value was changed, so reset $valStart/$valEnd to use $val instead + $valStart = $valEnd; + } + } + + # add nodeID to property path (with leading ' #') if it exists + if (defined $attrs{'rdf:nodeID'}) { + $nodeID = $$blankInfo{NodeID} = $attrs{'rdf:nodeID'}; + delete $attrs{'rdf:nodeID'}; + $prop .= ' #' . $nodeID; + undef $parseResource; # can't ignore if this is a node + } + + # push this property name onto our hierarchy list + push @$propList, $prop unless $parseResource; + + if ($isSVG) { + # ignore everything but top level SVG tags and metadata unless Unknown set + unless ($$et{OPTIONS}{Unknown} > 1 or $$et{OPTIONS}{Verbose}) { + if (@$propList > 1 and $$propList[1] !~ /\b(metadata|desc|title)$/) { + pop @$propList; + next; + } + } + if ($prop eq 'svg' or $prop eq 'metadata') { + # add svg namespace prefix if missing to ignore these entries in the tag name + $$propList[-1] = "svg:$prop"; + } + } + + # handle properties inside element attributes (RDF shorthand format): + # (attributes take the form a:b='c' or a:b="c") + my ($shortName, $shorthand, $ignored); + foreach $shortName (@attrs) { + next unless defined $attrs{$shortName}; + my $propName = $shortName; + my ($ns, $name); + if ($propName =~ /(.*?):(.*)/) { + $ns = $1; # specified namespace + $name = $2; + } elsif ($prop =~ /(\S*?):/) { + $ns = $1; # assume same namespace as parent + $name = $propName; + $propName = "$ns:$name"; # generate full property name + } else { + # a property qualifier is the only property name that may not + # have a namespace, and a qualifier shouldn't have attributes, + # but what the heck, let's allow this anyway + $ns = ''; + $name = $propName; + } + if ($propName eq 'rdf:about') { + if (not $$et{XmpAbout}) { + $$et{XmpAbout} = $attrs{$shortName}; + } elsif ($$et{XmpAbout} ne $attrs{$shortName}) { + if ($isWriting) { + my $str = "Different 'rdf:about' attributes not handled"; + unless ($$et{WARNED_ONCE}{$str}) { + $et->Error($str, 1); + $$et{WARNED_ONCE}{$str} = 1; + } + } elsif ($$et{XmpValidate}) { + $et->WarnOnce("Different 'rdf:about' attributes"); + } + } + } + if ($isWriting) { + # keep track of our namespaces when writing + if ($ns eq 'xmlns') { + my $stdNS = $uri2ns{$attrs{$shortName}}; + unless ($stdNS and ($stdNS eq 'x' or $stdNS eq 'iX')) { + my $nsUsed = $$et{XMP_NS}; + $$nsUsed{$name} = $attrs{$shortName} unless defined $$nsUsed{$name}; + } + delete $attrs{$shortName}; # (handled by namespace logic) + next; + } elsif ($recognizedAttrs{$propName}) { + next; + } + } + my $shortVal = $attrs{$shortName}; + if ($ignoreNamespace{$ns} or $ignoreProp{$prop}) { + $ignored = $propName; + # handle special attributes (extract as tags only once if not empty) + if (ref $recognizedAttrs{$propName} and $shortVal) { + my ($tbl, $id, $name) = @{$recognizedAttrs{$propName}}; + my $tval = UnescapeXML($shortVal); + unless (defined $$et{VALUE}{$name} and $$et{VALUE}{$name} eq $tval) { + $et->HandleTag(GetTagTable($tbl), $id, $tval); + } + } + next; + } + delete $attrs{$shortName}; # don't re-use this attribute + push @$propList, $propName; + # save this shorthand XMP property + if (defined $nodeID) { + SaveBlankInfo($blankInfo, $propList, $shortVal); + } elsif ($isWriting) { + CaptureXMP($et, $propList, $shortVal); + } else { + ValidateProperty($et, $propList) if $$et{XmpValidate}; + &$foundProc($et, $tagTablePtr, $propList, $shortVal); + } + pop @$propList; + $shorthand = 1; + } + if ($isWriting) { + if (ParseXMPElement($et, $tagTablePtr, $dataPt, $valStart, $valEnd, + $propList, $blankInfo)) + { + # (no value since we found more properties within this one) + # set an error on any ignored attributes here, because they will be lost + $$et{XMP_ERROR} = "Can't handle XMP attribute '${ignored}'" if $ignored; + } elsif (not $shorthand or $valEnd != $valStart) { + $val = substr($$dataPt, $valStart, $valEnd - $valStart); + # remove comments and whitespace from rdf:Description only + if ($prop eq 'rdf:Description') { + $val =~ s/<!--.*?-->//g; $val =~ s/^\s+//; $val =~ s/\s+$//; + } + if (defined $nodeID) { + SaveBlankInfo($blankInfo, $propList, $val, \%attrs); + } else { + CaptureXMP($et, $propList, $val, \%attrs); + } + } + } else { + # look for additional elements contained within this one + if ($valStart == $valEnd or + !ParseXMPElement($et, $tagTablePtr, $dataPt, $valStart, $valEnd, + $propList, $blankInfo)) + { + my $wasEmpty; + unless (defined $val) { + $val = substr($$dataPt, $valStart, $valEnd - $valStart); + # remove comments and whitespace from rdf:Description only + if ($prop eq 'rdf:Description' and $val) { + $val =~ s/<!--.*?-->//g; $val =~ s/^\s+//; $val =~ s/\s+$//; + } + # if element value is empty, take value from RDF 'value' or 'resource' attribute + # (preferentially) or 'about' attribute (if no 'value' or 'resource') + if ($val eq '' and ($attrs =~ /\brdf:(?:value|resource)=(['"])(.*?)\1/ or + $attrs =~ /\brdf:about=(['"])(.*?)\1/)) + { + $val = $2; + $wasEmpty = 1; + } + } + # there are no contained elements, so this must be a simple property value + # (unless we already extracted shorthand values from this element) + if (length $val or not $shorthand) { + my $lastProp = $$propList[-1]; + if (defined $nodeID) { + SaveBlankInfo($blankInfo, $propList, $val); + } elsif ($lastProp eq 'rdf:type' and $wasEmpty) { + # do not extract empty structure types (for now) + } elsif ($lastProp =~ /^et:(desc|prt|val)$/ and ($count or $1 eq 'desc')) { + # ignore et:desc, and et:val if preceded by et:prt + --$count; + } else { + ValidateProperty($et, $propList) if $$et{XmpValidate}; + &$foundProc($et, $tagTablePtr, $propList, $val, \%attrs); + } + } + } + } + pop @$propList unless $parseResource; + ++$count; + + # validate namespace prefixes used at this level if necessary + if ($$et{XmpValidate}) { + foreach (sort keys %usedNS) { + next if $$et{definedNS}{$_} or $_ eq 'xml'; + if (defined $$et{definedNS}{$_}) { + $et->Warn("XMP namespace $_ is used out of scope"); + } else { + $et->Warn("Undefined XMP namespace: $_"); + } + $$et{definedNS}{$_} = -1; # (don't warn again for this namespace) + } + # reset namespaces that went out of scope + $$et{definedNS}{$_} = 0 foreach keys %definedNS; + undef %usedNS; + undef %definedNS; + } + + last if $start >= $end; + pos($$dataPt) = $start; + $$dataPt =~ /\G\s+/gc; # skip white space after closing token + } +# +# process resources referenced by blank nodeID's +# + if ($processBlankInfo and %{$$blankInfo{Prop}}) { + ProcessBlankInfo($et, $tagTablePtr, $blankInfo, $isWriting); + %$blankInfo = (); # free some memory + } + # restore namespace lookup from the containing scope + $$et{xlatNS} = $saveNS if $saveNS; + + return $count; # return the number of elements found at this level +} + +#------------------------------------------------------------------------------ +# Process XMP data +# Inputs: 0) ExifTool object reference, 1) DirInfo reference, 2) Pointer to tag table +# Returns: 1 on success +# Notes: The following flavours of XMP files are currently recognized: +# - standard XMP with xpacket, x:xmpmeta and rdf:RDF elements +# - XMP that is missing the xpacket and/or x:xmpmeta elements +# - mutant Microsoft XMP with xmp:xmpmeta element +# - XML files beginning with "<xml" +# - SVG files that begin with "<svg" or "<!DOCTYPE svg" +# - XMP and XML files beginning with a UTF-8 byte order mark +# - UTF-8, UTF-16 and UTF-32 encoded XMP +# - erroneously double-UTF8 encoded XMP +# - otherwise valid files with leading XML comment +sub ProcessXMP($$;$) +{ + my ($et, $dirInfo, $tagTablePtr) = @_; + my $dataPt = $$dirInfo{DataPt}; + my ($dirStart, $dirLen, $dataLen, $double); + my ($buff, $fmt, $hasXMP, $isXML, $isRDF, $isSVG); + my $rtnVal = 0; + my $bom = 0; + + # namespaces and prefixes currently in effect while parsing the file, + # and lookup to translate brain-dead-Microsoft-Photo-software prefixes + $$et{curURI} = { }; + $$et{curNS} = { }; + $$et{xlatNS} = { }; + $$et{definedNS} = { }; + delete $$et{XmpAbout}; + delete $$et{XmpValidate}; # don't validate by default + + # ignore non-standard XMP while in strict MWG compatibility mode + if (($Image::ExifTool::MWG::strict or $$et{OPTIONS}{Validate}) and + not ($$et{XMP_CAPTURE} or $$et{DOC_NUM}) and + (($$dirInfo{DirName} || '') eq 'XMP' or $$et{FILE_TYPE} eq 'XMP')) + { + $$et{XmpValidate} = { } if $$et{OPTIONS}{Validate}; + my $path = $et->MetadataPath(); + my $nonStd; + if ($$et{FILE_TYPE} =~ /^(JPEG|TIFF|PSD)$/ and $path !~ /^(JPEG-APP1-XMP|TIFF-IFD0-XMP|PSD-XMP)$/) { + $nonStd = 1; + } + if ($nonStd and $Image::ExifTool::MWG::strict) { + $et->Warn("Ignored non-standard XMP at $path"); + return 1; + } + if ($nonStd) { + $et->Warn("Non-standard XMP at $path", 1); + } elsif (not $$dirInfo{IsExtended}) { + $et->Warn("Duplicate XMP at $path") if $$et{DIR_COUNT}{XMP}; + $$et{DIR_COUNT}{XMP} = ($$et{DIR_COUNT}{XMP} || 0) + 1; # count standard XMP + } + } + if ($dataPt) { + $dirStart = $$dirInfo{DirStart} || 0; + $dirLen = $$dirInfo{DirLen} || (length($$dataPt) - $dirStart); + $dataLen = $$dirInfo{DataLen} || length($$dataPt); + # check leading BOM (may indicate double-encoded UTF) + pos($$dataPt) = $dirStart; + $double = $1 if $$dataPt =~ /\G((\0\0)?\xfe\xff|\xff\xfe(\0\0)?|\xef\xbb\xbf)\0*<\0*\?\0*x\0*p\0*a\0*c\0*k\0*e\0*t/g; + } else { + my ($type, $mime, $buf2, $buf3); + # read information from XMP file + my $raf = $$dirInfo{RAF} or return 0; + $raf->Read($buff, 256) or return 0; + ($buf2 = $buff) =~ tr/\0//d; # cheap conversion to UTF-8 + # remove leading comments if they exist (eg. ImageIngester) + while ($buf2 =~ /^\s*<!--/) { + # remove the comment if it is complete + if ($buf2 =~ s/^\s*<!--.*?-->\s+//s) { + # continue with parsing if we have more than 128 bytes remaining + next if length $buf2 > 128; + } else { + # don't read more than 10k when looking for the end of comment + return 0 if length($buf2) > 10000; + } + $raf->Read($buf3, 256) or last; # read more data if available + $buff .= $buf3; + $buf3 =~ tr/\0//d; + $buf2 .= $buf3; + } + # check to see if this is XMP format + # (CS2 writes .XMP files without the "xpacket begin") + if ($buf2 =~ /^\s*(<\?xpacket begin=|<x(mp)?:x[ma]pmeta)/) { + $hasXMP = 1; + } else { + # also recognize XML files and .XMP files with BOM and without x:xmpmeta + if ($buf2 =~ /^(\xfe\xff)(<\?xml|<rdf:RDF|<x(mp)?:x[ma]pmeta)/g) { + $fmt = 'n'; # UTF-16 or 32 MM with BOM + } elsif ($buf2 =~ /^(\xff\xfe)(<\?xml|<rdf:RDF|<x(mp)?:x[ma]pmeta)/g) { + $fmt = 'v'; # UTF-16 or 32 II with BOM + } elsif ($buf2 =~ /^(\xef\xbb\xbf)?(<\?xml|<rdf:RDF|<x(mp)?:x[ma]pmeta)/g) { + $fmt = 0; # UTF-8 with BOM or unknown encoding without BOM + } elsif ($buf2 =~ /^(\xfe\xff|\xff\xfe|\xef\xbb\xbf)(<\?xpacket begin=)/g) { + $double = $1; # double-encoded UTF + } else { + return 0; # not recognized XMP or XML + } + $bom = 1 if $1; + if ($2 eq '<?xml') { + if (defined $fmt and not $fmt and $buf2 =~ /^[^\n\r]*[\n\r]+<\?aid /s) { + undef $$et{XmpValidate}; # don't validate INX + if ($$et{XMP_CAPTURE}) { + $et->Error("ExifTool does not yet support writing of INX files"); + return 0; + } + $type = 'INX'; + } elsif ($buf2 =~ /<x(mp)?:x[ma]pmeta/) { + $hasXMP = 1; + } else { + undef $$et{XmpValidate}; # don't validate XML + # identify SVG images and PLIST files by DOCTYPE if available + if ($buf2 =~ /<!DOCTYPE\s+(\w+)/) { + if ($1 eq 'svg') { + $isSVG = 1; + } elsif ($1 eq 'plist') { + $type = 'PLIST'; + } elsif ($1 eq 'REDXIF') { + $type = 'RMD'; + $mime = 'application/xml'; + } else { + return 0; + } + } elsif ($buf2 =~ /<svg[\s>]/) { + $isSVG = 1; + } elsif ($buf2 =~ /<rdf:RDF/) { + $isRDF = 1; + } elsif ($buf2 =~ /<plist[\s>]/) { + $type = 'PLIST'; + } + if ($isSVG and $$et{XMP_CAPTURE}) { + $et->Error("ExifTool does not yet support writing of SVG images"); + return 0; + } + } + $isXML = 1; + } elsif ($2 eq '<rdf:RDF') { + $isRDF = 1; # recognize XMP without x:xmpmeta element + } + if ($buff =~ /^\0\0/) { + $fmt = 'N'; # UTF-32 MM with or without BOM + } elsif ($buff =~ /^..\0\0/s) { + $fmt = 'V'; # UTF-32 II with or without BOM + } elsif (not $fmt) { + if ($buff =~ /^\0/) { + $fmt = 'n'; # UTF-16 MM without BOM + } elsif ($buff =~ /^.\0/s) { + $fmt = 'v'; # UTF-16 II without BOM + } + } + } + my $size; + if ($type) { + if ($type eq 'PLIST') { + my $ext = $$et{FILE_EXT}; + $type = $ext if $ext and $ext eq 'MODD'; + $tagTablePtr = GetTagTable('Image::ExifTool::PLIST::Main'); + $$dirInfo{XMPParseOpts}{FoundProc} = \&Image::ExifTool::PLIST::FoundTag; + } + } else { + if ($isSVG) { + $type = 'SVG'; + } elsif ($isXML and not $hasXMP and not $isRDF) { + $type = 'XML'; + my $ext = $$et{FILE_EXT}; + $type = $ext if $ext and $ext eq 'COS'; # recognize COS by extension + } + } + $et->SetFileType($type, $mime); + + my $fast = $et->Options('FastScan'); + return 1 if $fast and $fast == 3; + + if ($type and $type eq 'INX') { + # brute force search for first XMP packet in INX file + # start: '<![CDATA[<?xpacket begin' (24 bytes) + # end: '<?xpacket end="r"?>]]>' (22 bytes) + $raf->Seek(0, 0) or return 0; + $raf->Read($buff, 65536) or return 1; + for (;;) { + last if $buff =~ /<!\[CDATA\[<\?xpacket begin/g; + $raf->Read($buf2, 65536) or return 1; + $buff = substr($buff, -24) . $buf2; + } + $buff = substr($buff, pos($buff) - 15); # (discard '<![CDATA[' and before) + for (;;) { + last if $buff =~ /<\?xpacket end="[rw]"\?>\]\]>/g; + my $n = length $buff; + $raf->Read($buf2, 65536) or $et->Warn('Missing xpacket end'), return 1; + $buff .= $buf2; + pos($buff) = $n - 22; # don't miss end pattern if it was split + } + $size = pos($buff) - 3; # (discard ']]>' and after) + $buff = substr($buff, 0, $size); + } else { + # read the entire file + $raf->Seek(0, 2) or return 0; + $size = $raf->Tell() or return 0; + $raf->Seek(0, 0) or return 0; + $raf->Read($buff, $size) == $size or return 0; + } + $dataPt = \$buff; + $dirStart = 0; + $dirLen = $dataLen = $size; + } + + # decode the first layer of double-encoded UTF text (if necessary) + if ($double) { + my ($buf2, $fmt); + $buff = substr($$dataPt, $dirStart + length $double); # remove leading BOM + Image::ExifTool::SetWarning(undef); # clear old warning + local $SIG{'__WARN__'} = \&Image::ExifTool::SetWarning; + # assume that character data has been re-encoded in UTF, so re-pack + # as characters and look for warnings indicating a false assumption + if ($double eq "\xef\xbb\xbf") { + require Image::ExifTool::Charset; + my $uni = Image::ExifTool::Charset::Decompose(undef,$buff,'UTF8'); + $buf2 = pack('C*', @$uni); + } else { + if (length($double) == 2) { + $fmt = ($double eq "\xfe\xff") ? 'n' : 'v'; + } else { + $fmt = ($double eq "\0\0\xfe\xff") ? 'N' : 'V'; + } + $buf2 = pack('C*', unpack("$fmt*",$buff)); + } + if (Image::ExifTool::GetWarning()) { + $et->Warn('Superfluous BOM at start of XMP'); + $dataPt = \$buff; # use XMP with the BOM removed + } else { + $et->Warn('XMP is double UTF-encoded'); + $dataPt = \$buf2; # use the decoded XMP + } + $dirStart = 0; + $dirLen = $dataLen = length $$dataPt; + } + + # extract XMP as a block if specified + my $blockName = $$dirInfo{BlockInfo} ? $$dirInfo{BlockInfo}{Name} : 'XMP'; + if (($$et{REQ_TAG_LOOKUP}{lc $blockName} or ($$et{TAGS_FROM_FILE} and + not $$et{EXCL_TAG_LOOKUP}{lc $blockName})) and + ($$dirInfo{DirName} and $$dirInfo{DirName} eq 'XMP')) + { + $et->FoundTag($$dirInfo{BlockInfo} || 'XMP', substr($$dataPt, $dirStart, $dirLen)); + } + + $tagTablePtr or $tagTablePtr = GetTagTable('Image::ExifTool::XMP::Main'); + if ($et->Options('Verbose') and not $$et{XMP_CAPTURE}) { + my $dirType = $isSVG ? 'SVG' : $$tagTablePtr{GROUPS}{1}; + $et->VerboseDir($dirType, 0, $dirLen); + } +# +# convert UTF-16 or UTF-32 encoded XMP to UTF-8 if necessary +# + my $begin = '<?xpacket begin='; + my $dirEnd = $dirStart + $dirLen; + pos($$dataPt) = $dirStart; + delete $$et{XMP_IS_XML}; + delete $$et{XMP_IS_SVG}; + if ($isXML or $isRDF) { + $$et{XMP_IS_XML} = $isXML; + $$et{XMP_IS_SVG} = $isSVG; + $$et{XMP_NO_XPACKET} = 1 + $bom; + } elsif ($$dataPt =~ /\G\Q$begin\E/gc) { + delete $$et{XMP_NO_XPACKET}; + } elsif ($$dataPt =~ /<x(mp)?:x[ma]pmeta/gc and + pos($$dataPt) > $dirStart and pos($$dataPt) < $dirEnd) + { + $$et{XMP_NO_XPACKET} = 1 + $bom; + } else { + delete $$et{XMP_NO_XPACKET}; + # check for UTF-16 encoding (insert one \0 between characters) + $begin = join "\0", split //, $begin; + # must reset pos because it was killed by previous unsuccessful //g match + pos($$dataPt) = $dirStart; + if ($$dataPt =~ /\G(\0)?\Q$begin\E\0./sg) { + # validate byte ordering by checking for U+FEFF character + if ($1) { + # should be big-endian since we had a leading \0 + $fmt = 'n' if $$dataPt =~ /\G\xfe\xff/g; + } else { + $fmt = 'v' if $$dataPt =~ /\G\0\xff\xfe/g; + } + } else { + # check for UTF-32 encoding (with three \0's between characters) + $begin =~ s/\0/\0\0\0/g; + pos($$dataPt) = $dirStart; + if ($$dataPt !~ /\G(\0\0\0)?\Q$begin\E\0\0\0./sg) { + $fmt = 0; # set format to zero as indication we didn't find encoded XMP + } elsif ($1) { + # should be big-endian + $fmt = 'N' if $$dataPt =~ /\G\0\0\xfe\xff/g; + } else { + $fmt = 'V' if $$dataPt =~ /\G\0\0\0\xff\xfe\0\0/g; + } + } + defined $fmt or $et->Warn('XMP character encoding error'); + } + if ($fmt) { + # trim if necessary to avoid converting non-UTF data + if ($dirStart or $dirEnd != length($$dataPt)) { + $buff = substr($$dataPt, $dirStart, $dirLen); + $dataPt = \$buff; + } + # convert into UTF-8 + if ($] >= 5.006001) { + $buff = pack('C0U*', unpack("$fmt*",$$dataPt)); + } else { + $buff = Image::ExifTool::PackUTF8(unpack("$fmt*",$$dataPt)); + } + $dataPt = \$buff; + $dirStart = 0; + $dirLen = length $$dataPt; + $dirEnd = $dirStart + $dirLen; + } + # avoid scanning for XMP later in case ScanForXMP is set + $$et{FoundXMP} = 1 if $tagTablePtr eq \%Image::ExifTool::XMP::Main; + + # set XMP parsing options + $$et{XMPParseOpts} = $$dirInfo{XMPParseOpts}; + + # ignore any specified properties (XML hack) + if ($$dirInfo{IgnoreProp}) { + %ignoreProp = %{$$dirInfo{IgnoreProp}}; + } else { + undef %ignoreProp; + } + + # need to preserve list indices to be able to handle multi-dimensional lists + my $keepFlat; + if ($$et{OPTIONS}{Struct}) { + if ($$et{OPTIONS}{Struct} eq '2') { + $keepFlat = 1; # preserve flattened tags + # setting NO_LIST to 0 combines list items in a TAG_EXTRA "NoList" element + # to allow them to be re-listed later if necessary. A "NoListDel" element + # is also created for tags that wouldn't have existed. + $$et{NO_LIST} = 0; + } else { + $$et{NO_LIST} = 1; + } + } + + # don't generate structures if this isn't real XMP + $$et{NO_STRUCT} = 1 if $$dirInfo{BlockInfo} or $$dirInfo{NoStruct}; + + # parse the XMP + if (ParseXMPElement($et, $tagTablePtr, $dataPt, $dirStart, $dirEnd)) { + $rtnVal = 1; + } elsif ($$dirInfo{DirName} and $$dirInfo{DirName} eq 'XMP') { + # if DirName was 'XMP' we expect well-formed XMP, so set Warning since it wasn't + # (but allow empty XMP as written by some PhaseOne cameras) + my $xmp = substr($$dataPt, $dirStart, $dirLen); + if ($xmp =~ /^ *\0*$/) { + $et->Warn('Invalid XMP'); + } else { + $et->Warn('Empty XMP',1); + $rtnVal = 1; + } + } + delete $$et{NO_STRUCT}; + + # return DataPt if successful in case we want it for writing + $$dirInfo{DataPt} = $dataPt if $rtnVal and $$dirInfo{RAF}; + + # restore structures if necessary + if ($$et{IsStruct}) { + require 'Image/ExifTool/XMPStruct.pl'; + RestoreStruct($et, $keepFlat); + delete $$et{IsStruct}; + } + # reset NO_LIST flag (must do this _after_ RestoreStruct() above) + delete $$et{NO_LIST}; + delete $$et{XMPParseOpts}; + delete $$et{curURI}; + delete $$et{curNS}; + delete $$et{xlatNS}; + delete $$et{definedNS}; + + return $rtnVal; +} + + +1; #end + +__END__ + +=head1 NAME + +Image::ExifTool::XMP - Read XMP meta information + +=head1 SYNOPSIS + +This module is loaded automatically by Image::ExifTool when required. + +=head1 DESCRIPTION + +XMP stands for Extensible Metadata Platform. It is a format based on XML +that Adobe developed for embedding metadata information in image files. +This module contains the definitions required by Image::ExifTool to read XMP +information. + +=head1 AUTHOR + +Copyright 2003-2019, Phil Harvey (phil at owl.phy.queensu.ca) + +This library is free software; you can redistribute it and/or modify it +under the same terms as Perl itself. + +=head1 REFERENCES + +=over 4 + +=item L<http://www.adobe.com/devnet/xmp/> + +=item L<http://www.w3.org/TR/rdf-syntax-grammar/> + +=item L<http://www.iptc.org/IPTC4XMP/> + +=back + +=head1 SEE ALSO + +L<Image::ExifTool::TagNames/XMP Tags>, +L<Image::ExifTool(3pm)|Image::ExifTool> + +=cut diff --git a/lib/Image/ExifTool/XMP2.pl b/lib/Image/ExifTool/XMP2.pl new file mode 100644 index 0000000..34cbe3f --- /dev/null +++ b/lib/Image/ExifTool/XMP2.pl @@ -0,0 +1,1831 @@ +#------------------------------------------------------------------------------ +# File: XMP2.pl +# +# Description: Additional XMP namespace definitions +# +# Revisions: 10/12/2008 - P. Harvey Created +# +# References: 1) PLUS - http://ns.useplus.org/ +# 2) PRISM - http://www.prismstandard.org/ +# 3) http://www.portfoliofaq.com/pfaq/v7mappings.htm +# 4) http://www.iptc.org/IPTC4XMP/ +# 5) http://creativecommons.org/technology/xmp +# --> changed to http://wiki.creativecommons.org/Companion_File_metadata_specification (2007/12/21) +# 6) http://www.optimasc.com/products/fileid/xmp-extensions.pdf +# 9) http://www.w3.org/TR/SVG11/ +# 11) http://www.extensis.com/en/support/kb_article.jsp?articleNumber=6102211 +# 12) XMPSpecificationPart3_May2013, page 58 +#------------------------------------------------------------------------------ + +package Image::ExifTool::XMP; + +use strict; +use Image::ExifTool qw(:Utils); +use Image::ExifTool::XMP; + +#------------------------------------------------------------------------------ + +# xmpDM structure definitions +my %sCuePointParam = ( + STRUCT_NAME => 'CuePointParam', + NAMESPACE => 'xmpDM', + key => { }, + value => { }, +); +my %sMarker = ( + STRUCT_NAME => 'Marker', + NAMESPACE => 'xmpDM', + comment => { }, + duration => { }, + location => { }, + name => { }, + startTime => { }, + target => { }, + type => { }, + # added Oct 2008 + cuePointParams => { Struct => \%sCuePointParam, List => 'Seq' }, + cuePointType=> { }, + probability => { Writable => 'real' }, + speaker => { }, +); +my %sTime = ( + STRUCT_NAME => 'Time', + NAMESPACE => 'xmpDM', + scale => { Writable => 'rational' }, + value => { Writable => 'integer' }, +); +my %sTimecode = ( + STRUCT_NAME => 'Timecode', + NAMESPACE => 'xmpDM', + timeFormat => { + PrintConv => { + '24Timecode' => '24 fps', + '25Timecode' => '25 fps', + '2997DropTimecode' => '29.97 fps (drop)', + '2997NonDropTimecode' => '29.97 fps (non-drop)', + '30Timecode' => '30 fps', + '50Timecode' => '50 fps', + '5994DropTimecode' => '59.94 fps (drop)', + '5994NonDropTimecode' => '59.94 fps (non-drop)', + '60Timecode' => '60 fps', + '23976Timecode' => '23.976 fps', + }, + }, + timeValue => { }, + value => { Writable => 'integer', Notes => 'only in XMP 2008 spec; an error?' }, +); + +# XMP Dynamic Media namespace properties (xmpDM) +%Image::ExifTool::XMP::xmpDM = ( + %xmpTableDefaults, + GROUPS => { 1 => 'XMP-xmpDM', 2 => 'Image' }, + NAMESPACE => 'xmpDM', + NOTES => 'XMP Dynamic Media namespace tags.', + absPeakAudioFilePath=> { }, + album => { }, + altTapeName => { }, + altTimecode => { Struct => \%sTimecode }, + artist => { Avoid => 1, Groups => { 2 => 'Author' } }, + audioModDate => { Groups => { 2 => 'Time' }, %dateTimeInfo }, + audioSampleRate => { Writable => 'integer' }, + audioSampleType => { + PrintConv => { + '8Int' => '8-bit integer', + '16Int' => '16-bit integer', + '24Int' => '24-bit integer', + '32Int' => '32-bit integer', + '32Float' => '32-bit float', + 'Compressed' => 'Compressed', + 'Packed' => 'Packed', + 'Other' => 'Other', + }, + }, + audioChannelType => { + PrintConv => { + 'Mono' => 'Mono', + 'Stereo' => 'Stereo', + '5.1' => '5.1', + '7.1' => '7.1', + '16 Channel' => '16 Channel', + 'Other' => 'Other', + }, + }, + audioCompressor => { }, + beatSpliceParams => { + Struct => { + STRUCT_NAME => 'BeatSpliceStretch', + NAMESPACE => 'xmpDM', + riseInDecibel => { Writable => 'real' }, + riseInTimeDuration => { Struct => \%sTime }, + useFileBeatsMarker => { Writable => 'boolean' }, + }, + }, + cameraAngle => { }, + cameraLabel => { }, + cameraModel => { }, + cameraMove => { }, + client => { }, + comment => { Name => 'DMComment' }, + composer => { Groups => { 2 => 'Author' } }, + contributedMedia => { + Struct => { + STRUCT_NAME => 'Media', + NAMESPACE => 'xmpDM', + duration => { Struct => \%sTime }, + managed => { Writable => 'boolean' }, + path => { }, + startTime => { Struct => \%sTime }, + track => { }, + webStatement=> { }, + }, + List => 'Bag', + }, + copyright => { Avoid => 1, Groups => { 2 => 'Author' } }, # (deprecated) + director => { }, + directorPhotography => { }, + discNumber => { }, #12 + duration => { Struct => \%sTime }, + engineer => { }, + fileDataRate => { Writable => 'rational' }, + genre => { }, + good => { Writable => 'boolean' }, + instrument => { }, + introTime => { Struct => \%sTime }, + key => { + PrintConvColumns => 3, + PrintConv => { + 'C' => 'C', 'C#' => 'C#', 'D' => 'D', 'D#' => 'D#', + 'E' => 'E', 'F' => 'F', 'F#' => 'F#', 'G' => 'G', + 'G#' => 'G#', 'A' => 'A', 'A#' => 'A#', 'B' => 'B', + }, + }, + logComment => { }, + loop => { Writable => 'boolean' }, + lyrics => { }, #12 + numberOfBeats => { Writable => 'real' }, + markers => { Struct => \%sMarker, List => 'Seq' }, + metadataModDate => { Groups => { 2 => 'Time' }, %dateTimeInfo }, + outCue => { Struct => \%sTime }, + partOfCompilation=>{ Writable => 'boolean' }, #12 + projectName => { }, + projectRef => { + Struct => { + STRUCT_NAME => 'ProjectLink', + NAMESPACE => 'xmpDM', + path => { }, + type => { + PrintConv => { + movie => 'Movie', + still => 'Still Image', + audio => 'Audio', + custom => 'Custom', + }, + }, + }, + }, + pullDown => { + PrintConvColumns => 2, + PrintConv => { + 'WSSWW' => 'WSSWW', 'SSWWW' => 'SSWWW', + 'SWWWS' => 'SWWWS', 'WWWSS' => 'WWWSS', + 'WWSSW' => 'WWSSW', 'WWWSW' => 'WWWSW', + 'WWSWW' => 'WWSWW', 'WSWWW' => 'WSWWW', + 'SWWWW' => 'SWWWW', 'WWWWS' => 'WWWWS', + }, + }, + relativePeakAudioFilePath => { }, + relativeTimestamp => { Struct => \%sTime }, + releaseDate => { Groups => { 2 => 'Time' }, %dateTimeInfo }, + resampleParams => { + Struct => { + STRUCT_NAME => 'ResampleStretch', + NAMESPACE => 'xmpDM', + quality => { PrintConv => { Low => 'Low', Medium => 'Medium', High => 'High' } }, + }, + }, + scaleType => { + PrintConv => { + Major => 'Major', + Minor => 'Minor', + Both => 'Both', + Neither => 'Neither', + }, + }, + scene => { Avoid => 1 }, + shotDate => { Groups => { 2 => 'Time' }, %dateTimeInfo }, + shotDay => { }, + shotLocation => { }, + shotName => { }, + shotNumber => { }, + shotSize => { }, + speakerPlacement=> { }, + startTimecode => { Struct => \%sTimecode }, + startTimeSampleSize => { Writable => 'integer' }, #PH + startTimeScale => { }, #PH (real?) + stretchMode => { + PrintConv => { + 'Fixed length' => 'Fixed length', + 'Time-Scale' => 'Time-Scale', + 'Resample' => 'Resample', + 'Beat Splice' => 'Beat Splice', + 'Hybrid' => 'Hybrid', + }, + }, + takeNumber => { Writable => 'integer' }, + tapeName => { }, + tempo => { Writable => 'real' }, + timeScaleParams => { + Struct => { + STRUCT_NAME => 'TimeScaleStretch', + NAMESPACE => 'xmpDM', + frameOverlappingPercentage => { Writable => 'real' }, + frameSize => { Writable => 'real' }, + quality => { PrintConv => { Low => 'Low', Medium => 'Medium', High => 'High' } }, + }, + }, + timeSignature => { + PrintConvColumns => 3, + PrintConv => { + '2/4' => '2/4', '3/4' => '3/4', '4/4' => '4/4', + '5/4' => '5/4', '7/4' => '7/4', '6/8' => '6/8', + '9/8' => '9/8', '12/8'=> '12/8', 'other' => 'other', + }, + }, + trackNumber => { Writable => 'integer' }, + Tracks => { + Struct => { + STRUCT_NAME => 'Track', + NAMESPACE => 'xmpDM', + frameRate => { }, + markers => { Struct => \%sMarker, List => 'Seq' }, + trackName => { }, + trackType => { }, + }, + List => 'Bag', + }, + videoAlphaMode => { + PrintConv => { + 'straight' => 'Straight', + 'pre-multiplied', => 'Pre-multiplied', + 'none' => 'None', + }, + }, + videoAlphaPremultipleColor => { Struct => \%sColorant }, + videoAlphaUnityIsTransparent => { Writable => 'boolean' }, + videoColorSpace => { + PrintConv => { + 'sRGB' => 'sRGB', + 'CCIR-601' => 'CCIR-601', + 'CCIR-709' => 'CCIR-709', + }, + }, + videoCompressor => { }, + videoFieldOrder => { + PrintConv => { + Upper => 'Upper', + Lower => 'Lower', + Progressive => 'Progressive', + }, + }, + videoFrameRate => { Writable => 'real' }, + videoFrameSize => { Struct => \%sDimensions }, + videoModDate => { Groups => { 2 => 'Time' }, %dateTimeInfo }, + videoPixelAspectRatio => { Writable => 'rational' }, + videoPixelDepth => { + PrintConv => { + '8Int' => '8-bit integer', + '16Int' => '16-bit integer', + '24Int' => '24-bit integer', + '32Int' => '32-bit integer', + '32Float' => '32-bit float', + 'Other' => 'Other', + }, + }, +); + +#------------------------------------------------------------------------------ +# IPTC Extensions version 1.3 (+ proposed video extensions) + +# IPTC Extension 1.0 structures +my %sLocationDetails = ( + STRUCT_NAME => 'LocationDetails', + NAMESPACE => 'Iptc4xmpExt', + GROUPS => { 2 => 'Location' }, + Identifier => { List => 'Bag', Namespace => 'xmp' }, + City => { }, + CountryCode => { }, + CountryName => { }, + ProvinceState => { }, + Sublocation => { }, + WorldRegion => { }, + LocationId => { List => 'Bag' }, + LocationName => { Writable => 'lang-alt' }, + GPSLatitude => { Namespace => 'exif', %latConv }, + GPSLongitude => { Namespace => 'exif', %longConv }, + GPSAltitude => { + Namespace => 'exif', + Writable => 'rational', + PrintConv => '$val =~ /^(inf|undef)$/ ? $val : "$val m"', + PrintConvInv => '$val=~s/\s*m$//;$val', + }, +); +my %sCVTermDetails = ( + STRUCT_NAME => 'CVTermDetails', + NAMESPACE => 'Iptc4xmpExt', + CvTermId => { }, + CvTermName => { Writable => 'lang-alt' }, + CvId => { }, + CvTermRefinedAbout => { }, +); + +# IPTC video extensions +my %sPublicationEvent = ( + STRUCT_NAME => 'PublicationEvent', + NAMESPACE => 'Iptc4xmpExt', + Date => { Groups => { 2 => 'Time' }, %dateTimeInfo }, + Name => { }, + Identifier => { }, +); +my %sEntity = ( + STRUCT_NAME => 'Entity', + NAMESPACE => 'Iptc4xmpExt', + Identifier => { List => 'Bag', Namespace => 'xmp' }, + Name => { Writable => 'lang-alt' }, +); +my %sEntityWithRole = ( + STRUCT_NAME => 'EntityWithRole', + NAMESPACE => 'Iptc4xmpExt', + Identifier => { List => 'Bag', Namespace => 'xmp' }, + Name => { Writable => 'lang-alt' }, + Role => { List => 'Bag' }, +); +# (no longer used) +#my %sFrameSize = ( +# STRUCT_NAME => 'FrameSize', +# NAMESPACE => 'Iptc4xmpExt', +# WidthPixels => { Writable => 'integer' }, +# HeightPixels => { Writable => 'integer' }, +#); +my %sRating = ( + STRUCT_NAME => 'Rating', + NAMESPACE => 'Iptc4xmpExt', + RatingValue => { FlatName => 'Value' }, + RatingSourceLink => { FlatName => 'SourceLink' }, + RatingScaleMinValue => { FlatName => 'ScaleMinValue' }, + RatingScaleMaxValue => { FlatName => 'ScaleMaxValue' }, + RatingValueLogoLink => { FlatName => 'ValueLogoLink' }, + RatingRegion => { + FlatName => 'RatingRegion', + Struct => \%sLocationDetails, + List => 'Bag', + }, +); +my %sEpisode = ( + STRUCT_NAME => 'EpisodeOrSeason', + NAMESPACE => 'Iptc4xmpExt', + Name => { }, + Number => { }, + Identifier => { }, +); +my %sSeries = ( + STRUCT_NAME => 'Series', + NAMESPACE => 'Iptc4xmpExt', + Name => { }, + Identifier => { }, +); +my %sTemporalCoverage = ( + STRUCT_NAME => 'TemporalCoverage', + NAMESPACE => 'Iptc4xmpExt', + tempCoverageFrom => { FlatName => 'From', %dateTimeInfo, Groups => { 2 => 'Time' } }, + tempCoverageTo => { FlatName => 'To', %dateTimeInfo, Groups => { 2 => 'Time' } }, +); +my %sQualifiedLink = ( + STRUCT_NAME => 'QualifiedLink', + NAMESPACE => 'Iptc4xmpExt', + Link => { }, + LinkQualifier => { }, +); +my %sTextRegion = ( + STRUCT_NAME => 'TextRegion', + NAMESPACE => 'Iptc4xmpExt', + RegionText => { }, + Region => { Struct => \%Image::ExifTool::XMP::sArea }, +); +my %sLinkedImage = ( + STRUCT_NAME => 'LinkedImage', + NAMESPACE => 'Iptc4xmpExt', + Link => { }, + LinkQualifier => { List => 'Bag' }, + ImageRole => { }, + 'format' => { Namespace => 'dc' }, + WidthPixels => { Writable => 'integer' }, + HeightPixels=> { Writable => 'integer' }, + UsedVideoFrame => { Struct => \%sTimecode }, +); + +# IPTC Extension namespace properties (Iptc4xmpExt) (ref 4) +%Image::ExifTool::XMP::iptcExt = ( + %xmpTableDefaults, + GROUPS => { 1 => 'XMP-iptcExt', 2 => 'Author' }, + NAMESPACE => 'Iptc4xmpExt', + TABLE_DESC => 'XMP IPTC Extension', + NOTES => q{ + IPTC Extension namespace tags. The actual namespace prefix is + "Iptc4xmpExt", but ExifTool shortens this for the family 1 group name. (see + L<http://www.iptc.org/IPTC4XMP/>) + }, + AboutCvTerm => { + Struct => \%sCVTermDetails, + List => 'Bag', + }, + AboutCvTermCvId => { Flat => 1, Name => 'AboutCvTermCvId' }, + AboutCvTermCvTermId => { Flat => 1, Name => 'AboutCvTermId' }, + AboutCvTermCvTermName => { Flat => 1, Name => 'AboutCvTermName' }, + AboutCvTermCvTermRefinedAbout => { Flat => 1, Name => 'AboutCvTermRefinedAbout' }, + AddlModelInfo => { Name => 'AdditionalModelInformation' }, + ArtworkOrObject => { + Struct => { + STRUCT_NAME => 'ArtworkOrObjectDetails', + NAMESPACE => 'Iptc4xmpExt', + AOCopyrightNotice => { }, + AOCreator => { List => 'Seq' }, + AODateCreated=> { Groups => { 2 => 'Time' }, %dateTimeInfo }, + AOSource => { }, + AOSourceInvNo=> { }, + AOTitle => { Writable => 'lang-alt' }, + AOCurrentCopyrightOwnerName => { }, + AOCurrentCopyrightOwnerId => { }, + AOCurrentLicensorName => { }, + AOCurrentLicensorId => { }, + AOCreatorId => { List => 'Seq' }, + AOCircaDateCreated => { Groups => { 2 => 'Time' }, Protected => 1 }, + AOStylePeriod => { List => 'Bag' }, + AOSourceInvURL => { }, + AOContentDescription => { Writable => 'lang-alt' }, + AOContributionDescription => { Writable => 'lang-alt' }, + AOPhysicalDescription => { Writable => 'lang-alt' }, + }, + List => 'Bag', + }, + ArtworkOrObjectAOCopyrightNotice => { Flat => 1, Name => 'ArtworkCopyrightNotice' }, + ArtworkOrObjectAOCreator => { Flat => 1, Name => 'ArtworkCreator' }, + ArtworkOrObjectAODateCreated => { Flat => 1, Name => 'ArtworkDateCreated' }, + ArtworkOrObjectAOSource => { Flat => 1, Name => 'ArtworkSource' }, + ArtworkOrObjectAOSourceInvNo => { Flat => 1, Name => 'ArtworkSourceInventoryNo' }, + ArtworkOrObjectAOTitle => { Flat => 1, Name => 'ArtworkTitle' }, + ArtworkOrObjectAOCurrentCopyrightOwnerName => { Flat => 1, Name => 'ArtworkCopyrightOwnerName' }, + ArtworkOrObjectAOCurrentCopyrightOwnerId => { Flat => 1, Name => 'ArtworkCopyrightOwnerID' }, + ArtworkOrObjectAOCurrentLicensorName => { Flat => 1, Name => 'ArtworkLicensorName' }, + ArtworkOrObjectAOCurrentLicensorId => { Flat => 1, Name => 'ArtworkLicensorID' }, + ArtworkOrObjectAOCreatorId => { Flat => 1, Name => 'ArtworkCreatorID' }, + ArtworkOrObjectAOCircaDateCreated => { Flat => 1, Name => 'ArtworkCircaDateCreated' }, + ArtworkOrObjectAOStylePeriod => { Flat => 1, Name => 'ArtworkStylePeriod' }, + ArtworkOrObjectAOSourceInvURL => { Flat => 1, Name => 'ArtworkSourceInvURL' }, + ArtworkOrObjectAOContentDescription => { Flat => 1, Name => 'ArtworkContentDescription' }, + ArtworkOrObjectAOContributionDescription => { Flat => 1, Name => 'ArtworkContributionDescription' }, + ArtworkOrObjectAOPhysicalDescription => { Flat => 1, Name => 'ArtworkPhysicalDescription' }, + CVterm => { + Name => 'ControlledVocabularyTerm', + List => 'Bag', + Notes => 'deprecated by version 1.2', + }, + DigImageGUID => { Name => 'DigitalImageGUID' }, + DigitalSourcefileType => { + Name => 'DigitalSourceFileType', + Notes => 'now deprecated -- replaced by DigitalSourceType', + }, + DigitalSourceType => { Name => 'DigitalSourceType' }, + EmbdEncRightsExpr => { + Struct => { + STRUCT_NAME => 'EEREDetails', + NAMESPACE => 'Iptc4xmpExt', + EncRightsExpr => { }, + RightsExprEncType => { }, + RightsExprLangId => { }, + }, + List => 'Bag', + }, + EmbdEncRightsExprEncRightsExpr => { Flat => 1, Name => 'EmbeddedEncodedRightsExpr' }, + EmbdEncRightsExprRightsExprEncType => { Flat => 1, Name => 'EmbeddedEncodedRightsExprType' }, + EmbdEncRightsExprRightsExprLangId => { Flat => 1, Name => 'EmbeddedEncodedRightsExprLangID' }, + Event => { Writable => 'lang-alt' }, + IptcLastEdited => { + Name => 'IPTCLastEdited', + Groups => { 2 => 'Time' }, + %dateTimeInfo, + }, + LinkedEncRightsExpr => { + Struct => { + STRUCT_NAME => 'LEREDetails', + NAMESPACE => 'Iptc4xmpExt', + LinkedRightsExpr => { }, + RightsExprEncType => { }, + RightsExprLangId => { }, + }, + List => 'Bag', + }, + LinkedEncRightsExprLinkedRightsExpr => { Flat => 1, Name => 'LinkedEncodedRightsExpr' }, + LinkedEncRightsExprRightsExprEncType => { Flat => 1, Name => 'LinkedEncodedRightsExprType' }, + LinkedEncRightsExprRightsExprLangId => { Flat => 1, Name => 'LinkedEncodedRightsExprLangID' }, + LocationCreated => { + Struct => \%sLocationDetails, + Groups => { 2 => 'Location' }, + List => 'Bag', + }, + LocationShown => { + Struct => \%sLocationDetails, + Groups => { 2 => 'Location' }, + List => 'Bag', + }, + MaxAvailHeight => { Writable => 'integer' }, + MaxAvailWidth => { Writable => 'integer' }, + ModelAge => { List => 'Bag', Writable => 'integer' }, + OrganisationInImageCode => { List => 'Bag' }, + OrganisationInImageName => { List => 'Bag' }, + PersonInImage => { List => 'Bag' }, + PersonInImageWDetails => { + Struct => { + STRUCT_NAME => 'PersonDetails', + NAMESPACE => 'Iptc4xmpExt', + PersonId => { List => 'Bag' }, + PersonName => { Writable => 'lang-alt' }, + PersonCharacteristic => { + Struct => \%sCVTermDetails, + List => 'Bag', + }, + PersonDescription => { Writable => 'lang-alt' }, + }, + List => 'Bag', + }, + PersonInImageWDetailsPersonId => { Flat => 1, Name => 'PersonInImageId' }, + PersonInImageWDetailsPersonName => { Flat => 1, Name => 'PersonInImageName' }, + PersonInImageWDetailsPersonCharacteristic => { Flat => 1, Name => 'PersonInImageCharacteristic' }, + PersonInImageWDetailsPersonCharacteristicCvId => { Flat => 1, Name => 'PersonInImageCvTermCvId' }, + PersonInImageWDetailsPersonCharacteristicCvTermId => { Flat => 1, Name => 'PersonInImageCvTermId' }, + PersonInImageWDetailsPersonCharacteristicCvTermName => { Flat => 1, Name => 'PersonInImageCvTermName' }, + PersonInImageWDetailsPersonCharacteristicCvTermRefinedAbout => { Flat => 1, Name => 'PersonInImageCvTermRefinedAbout' }, + PersonInImageWDetailsPersonDescription => { Flat => 1, Name => 'PersonInImageDescription' }, + ProductInImage => { + Struct => { + STRUCT_NAME => 'ProductDetails', + NAMESPACE => 'Iptc4xmpExt', + ProductName => { Writable => 'lang-alt' }, + ProductGTIN => { }, + ProductDescription => { Writable => 'lang-alt' }, + }, + List => 'Bag', + }, + ProductInImageProductName => { Flat => 1, Name => 'ProductInImageName' }, + ProductInImageProductGTIN => { Flat => 1, Name => 'ProductInImageGTIN' }, + ProductInImageProductDescription => { Flat => 1, Name => 'ProductInImageDescription' }, + RegistryId => { + Name => 'RegistryID', + Struct => { + STRUCT_NAME => 'RegistryEntryDetails', + NAMESPACE => 'Iptc4xmpExt', + RegItemId => { }, + RegOrgId => { }, + RegEntryRole=> { }, # (new in 1.3) + }, + List => 'Bag', + }, + RegistryIdRegItemId => { Flat => 1, Name => 'RegistryItemID' }, + RegistryIdRegOrgId => { Flat => 1, Name => 'RegistryOrganisationID' }, + RegistryIdRegEntryRole => { Flat => 1, Name => 'RegistryEntryRole' }, + + # new Extension 1.3 properties + Genre => { Groups => { 2 => 'Image' }, List => 'Bag', Struct => \%sCVTermDetails }, + + # new video properties (Oct 2016, ref Michael Steidl) + # (see http://www.iptc.org/std/videometadatahub/recommendation/IPTC-VideoMetadataHub-props-Rec_1.0.html) + CircaDateCreated=> { Groups => { 2 => 'Time' } }, + Episode => { Groups => { 2 => 'Video' }, Struct => \%sEpisode }, + ExternalMetadataLink => { Groups => { 2 => 'Other' }, List => 'Bag' }, + FeedIdentifier => { Groups => { 2 => 'Video' } }, + PublicationEvent=> { Groups => { 2 => 'Video' }, List => 'Bag', Struct => \%sPublicationEvent }, + Rating => { + Groups => { 2 => 'Other' }, + Struct => \%sRating, + List => 'Bag', + }, + ReleaseReady => { Groups => { 2 => 'Other' }, Writable => 'boolean' }, + Season => { Groups => { 2 => 'Video' }, Struct => \%sEpisode }, + Series => { Groups => { 2 => 'Video' }, Struct => \%sSeries }, + StorylineIdentifier => { Groups => { 2 => 'Video' }, List => 'Bag' }, + StylePeriod => { Groups => { 2 => 'Video' } }, + TemporalCoverage=> { Groups => { 2 => 'Video' }, Struct => \%sTemporalCoverage }, + WorkflowTag => { Groups => { 2 => 'Video' }, Struct => \%sCVTermDetails }, + DataOnScreen => { Groups => { 2 => 'Video' }, List => 'Bag', Struct => \%sTextRegion }, + Dopesheet => { Groups => { 2 => 'Video' }, Writable => 'lang-alt' }, + DopesheetLink => { Groups => { 2 => 'Video' }, List => 'Bag', Struct => \%sQualifiedLink }, + Headline => { Groups => { 2 => 'Video' }, Writable => 'lang-alt', Avoid => 1 }, + PersonHeard => { Groups => { 2 => 'Audio' }, List => 'Bag', Struct => \%sEntity }, + VideoShotType => { Groups => { 2 => 'Video' }, List => 'Bag', Struct => \%sEntity }, + EventExt => { Groups => { 2 => 'Video' }, List => 'Bag', Struct => \%sEntity, Name => 'ShownEvent' }, + Transcript => { Groups => { 2 => 'Video' }, Writable => 'lang-alt' }, + TranscriptLink => { Groups => { 2 => 'Video' }, List => 'Bag', Struct => \%sQualifiedLink }, + VisualColour => { + Name => 'VisualColor', + Groups => { 2 => 'Video' }, + PrintConv => { + 'bw-monochrome' => 'Monochrome', + 'colour' => 'Color', + }, + }, + Contributor => { List => 'Bag', Struct => \%sEntityWithRole }, + CopyrightYear => { Groups => { 2 => 'Time' }, Writable => 'integer' }, + Creator => { List => 'Bag', Struct => \%sEntityWithRole }, + SupplyChainSource => { Groups => { 2 => 'Other' }, List => 'Bag', Struct => \%sEntity }, + audioBitRate => { Groups => { 2 => 'Audio' }, Writable => 'integer', Name => 'AudioBitrate' }, + audioBitRateMode=> { + Name => 'AudioBitrateMode', + Groups => { 2 => 'Audio' }, + PrintConv => { + fixed => 'Fixed', + variable => 'Variable', + }, + }, + audioChannelCount => { Groups => { 2 => 'Audio' }, Writable => 'integer' }, + videoDisplayAspectRatio => { Groups => { 2 => 'Audio' }, Writable => 'rational' }, + ContainerFormat => { Groups => { 2 => 'Video' }, Struct => \%sEntity }, + StreamReady => { + Groups => { 2 => 'Video' }, + PrintConv => { + true => 'True', + false => 'False', + unknown => 'Unknown', + }, + }, + videoBitRate => { Groups => { 2 => 'Video' }, Writable => 'integer', Name => 'VideoBitrate' }, + videoBitRateMode => { + Name => 'VideoBitrateMode', + Groups => { 2 => 'Video' }, + PrintConv => { + fixed => 'Fixed', + variable => 'Variable', + }, + }, + videoEncodingProfile => { Groups => { 2 => 'Video' } }, + videoStreamsCount => { Groups => { 2 => 'Video' }, Writable => 'integer' }, + # new IPTC video metadata 1.1 properties + # (ref https://www.iptc.org/std/videometadatahub/recommendation/IPTC-VideoMetadataHub-props-Rec_1.1.html) + SnapshotLink => { Groups => { 2 => 'Image' }, List => 'Bag', Struct => \%sLinkedImage, Name => 'Snapshot' }, + # new IPTC video metadata 1.2 properties + # (ref http://www.iptc.org/std/videometadatahub/recommendation/IPTC-VideoMetadataHub-props-Rec_1.2.html) + RecDevice => { + Struct => { + STRUCT_NAME => 'Device', + NAMESPACE => 'Iptc4xmpExt', + Manufacturer => { }, + ModelName => { }, + SerialNumber => { }, + AttLensDescription => { }, + OwnersDeviceId => { }, + }, + }, + PlanningRef => { List => 'Bag', Struct => \%sEntityWithRole }, + audioBitsPerSample => { Writable => 'integer' }, +); + +#------------------------------------------------------------------------------ +# PRISM +# +# NOTE: The "Avoid" flag is set for all PRISM tags (via tag table AVOID flag) + +# my %obsolete = ( +# Notes => 'obsolete in 2.0', +# ValueConvInv => sub { +# my ($val, $self) = @_; +# unless ($self->Options('IgnoreMinorErrors')) { +# warn "Warning: [minor] Attempt to write obsolete tag\n"; +# return undef; +# } +# return $val; +# } +# ); + +# PRISM structure definitions +my %prismPublicationDate = ( + STRUCT_NAME => 'prismPublicationDate', + NAMESPACE => 'prism', + date => { %dateTimeInfo, Groups => { 2 => 'Time'} }, + 'a-platform'=> { }, +); + +# Publishing Requirements for Industry Standard Metadata (prism) (ref 2) +%Image::ExifTool::XMP::prism = ( + %xmpTableDefaults, + GROUPS => { 0 => 'XMP', 1 => 'XMP-prism', 2 => 'Document' }, + NAMESPACE => 'prism', + AVOID => 1, + NOTES => q{ + Publishing Requirements for Industry Standard Metadata 3.0 namespace + tags. (see L<http://www.prismstandard.org/>) + }, + academicField => { }, # (3.0) + aggregateIssueNumber => { Writable => 'integer' }, # (3.0) + aggregationType => { List => 'Bag' }, + alternateTitle => { + List => 'Bag', + Struct => { # (becomes a structure in 3.0) + STRUCT_NAME => 'prismAlternateTitle', + NAMESPACE => 'prism', + text => { }, + 'a-platform'=> { }, + 'a-lang' => { }, + }, + }, + blogTitle => { }, # (3.0) + blogURL => { }, # (3.0) + bookEdition => { }, # (3.0) + byteCount => { Writable => 'integer' }, + channel => { + List => 'Bag', + Struct => { # (becomes a structure in 3.0) + STRUCT_NAME => 'prismChannel', + NAMESPACE => 'prism', + channel => { }, + subchannel1 => { }, + subchannel2 => { }, + subchannel3 => { }, + subchannel4 => { }, + 'a-lang' => { }, + }, + }, + complianceProfile=>{ PrintConv => { three => 'Three' } }, + contentType => { }, # (3.0) + copyrightYear => { }, # (3.0) + # copyright => { Groups => { 2 => 'Author' } }, # (deprecated in 3.0) + corporateEntity => { List => 'Bag' }, + coverDate => { %dateTimeInfo, Groups => { 2 => 'Time'} }, + coverDisplayDate=> { }, + creationDate => { %dateTimeInfo, Groups => { 2 => 'Time'} }, + dateRecieved => { %dateTimeInfo, Groups => { 2 => 'Time'} }, + device => { }, # (3.0) + distributor => { }, + doi => { Name => 'DOI', Description => 'Digital Object Identifier' }, + edition => { }, + eIssn => { }, + #embargoDate => { List => 'Bag', %dateTimeInfo, Groups => { 2 => 'Time'} }, # (deprecated in 3.0) + endingPage => { }, + event => { List => 'Bag' }, + #expirationDate => { List => 'Bag', %dateTimeInfo, Groups => { 2 => 'Time'} }, # (deprecated in 3.0) + genre => { List => 'Bag' }, + hasAlternative => { List => 'Bag' }, + hasCorrection => { + Struct => { # (becomes a structure in 3.0) + STRUCT_NAME => 'prismHasCorrection', + NAMESPACE => 'prism', + text => { }, + 'a-platform'=> { }, + 'a-lang' => { }, + }, + }, + # hasPreviousVersion => { }, # (not in 3.0) + hasTranslation => { List => 'Bag' }, + industry => { List => 'Bag' }, + isAlternativeOf => { List => 'Bag' }, # (3.0) + isbn => { Name => 'ISBN', List => 'Bag' }, # 2.1 (becomes a list in 3.0) + isCorrectionOf => { List => 'Bag' }, + issn => { Name => 'ISSN' }, + issueIdentifier => { }, + issueName => { }, + issueTeaser => { }, # (3.0) + issueType => { }, # (3.0) + isTranslationOf => { }, + keyword => { List => 'Bag' }, + killDate => { + Struct => { # (becomes a structure in 3.0) + STRUCT_NAME => 'prismKillDate', + NAMESPACE => 'prism', + date => { %dateTimeInfo, Groups => { 2 => 'Time'} }, + 'a-platform'=> { }, #PH (missed in spec?) + }, + }, + 'link' => { List => 'Bag' }, # (3.0) + location => { List => 'Bag' }, + # metadataContainer => { }, (not valid for PRISM XMP) + modificationDate=> { %dateTimeInfo, Groups => { 2 => 'Time'} }, + nationalCatalogNumber => { }, # (3.0) + number => { }, + object => { List => 'Bag' }, + onSaleDate => { # (3.0) + List => 'Bag', + Struct => { + STRUCT_NAME => 'prismOnSaleDate', + NAMESPACE => 'prism', + date => { %dateTimeInfo, Groups => { 2 => 'Time'} }, + 'a-platform'=> { }, + }, + }, + onSaleDay => { # (3.0) + List => 'Bag', + Struct => { + STRUCT_NAME => 'prismOnSaleDay', + NAMESPACE => 'prism', + day => { }, #PH (not named in spec) + 'a-platform'=> { }, + }, + }, + offSaleDate => { # (3.0) + List => 'Bag', + Struct => { + STRUCT_NAME => 'prismOffSaleDate', + NAMESPACE => 'prism', + date => { %dateTimeInfo, Groups => { 2 => 'Time'} }, + 'a-platform'=> { }, + }, + }, + organization => { List => 'Bag' }, + originPlatform => { + List => 'Bag', + PrintConv => { + email => 'E-Mail', + mobile => 'Mobile', + broadcast => 'Broadcast', + web => 'Web', + 'print' => 'Print', + recordableMedia => 'Recordable Media', + other => 'Other', + }, + }, + pageCount => { Writable => 'integer' }, # (3.0) + pageProgressionDirection => { # (3.0) + PrintConv => { LTR => 'Left to Right', RTL => 'Right to Left' }, + }, + pageRange => { List => 'Bag' }, + person => { }, + platform => { }, # (3.0) + productCode => { }, # (3.0) + profession => { }, # (3.0) + publicationDate => { + List => 'Bag', + Struct => \%prismPublicationDate, # (becomes a structure in 3.0) + }, + publicationDisplayDate => { # (3.0) + List => 'Bag', + Struct => \%prismPublicationDate, + }, + publicationName => { }, + publishingFrequency => { }, # (3.0) + rating => { }, + # rightsAgent => { }, # (deprecated in 3.0) + samplePageRange => { }, # (3.0) + section => { }, + sellingAgency => { }, # (3.0) + seriesNumber => { Writable => 'integer' }, # (3.0) + seriesTitle => { }, # (3.0) + sport => { }, # (3.0) + startingPage => { }, + subsection1 => { }, + subsection2 => { }, + subsection3 => { }, + subsection4 => { }, + subtitle => { }, # (3.0) + supplementDisplayID => { }, # (3.0) + supplementStartingPage => { }, # (3.0) + supplementTitle => { }, # (3.0) + teaser => { List => 'Bag' }, + ticker => { List => 'Bag' }, + timePeriod => { }, + url => { + Name => 'URL', + List => 'Bag', + Struct => { # (becomes a structure in 3.0) + STRUCT_NAME => 'prismUrl', + NAMESPACE => 'prism', + url => { }, + 'a-platform'=> { }, + }, + }, + uspsNumber => { }, # (3.0) + versionIdentifier => { }, + volume => { }, + wordCount => { Writable => 'integer' }, +# tags that existed in version 1.3 +# category => { %obsolete, List => 'Bag' }, +# hasFormat => { %obsolete, List => 'Bag' }, +# hasPart => { %obsolete, List => 'Bag' }, +# isFormatOf => { %obsolete, List => 'Bag' }, +# isPartOf => { %obsolete }, +# isReferencedBy => { %obsolete, List => 'Bag' }, +# isRequiredBy => { %obsolete, List => 'Bag' }, +# isVersionOf => { %obsolete }, +# objectTitle => { %obsolete, List => 'Bag' }, +# receptionDate => { %obsolete }, +# references => { %obsolete, List => 'Bag' }, +# requires => { %obsolete, List => 'Bag' }, +# tags in older versions +# page +# contentLength +# creationTime +# expirationTime +# hasVersion +# isAlternativeFor +# isBasedOn +# isBasisFor +# modificationTime +# publicationTime +# receptionTime +# releaseTime +); + +# PRISM Rights Language namespace (prl) (ref 2) +%Image::ExifTool::XMP::prl = ( + %xmpTableDefaults, + GROUPS => { 0 => 'XMP', 1 => 'XMP-prl', 2 => 'Document' }, + NAMESPACE => 'prl', + AVOID => 1, + NOTES => q{ + PRISM Rights Language 2.1 namespace tags. These tags have been deprecated + since the release of the PRISM Usage Rights 3.0. (see + L<http://www.prismstandard.org/>) + }, + geography => { List => 'Bag' }, + industry => { List => 'Bag' }, + usage => { List => 'Bag' }, +); + +# PRISM Usage Rights namespace (prismusagerights) (ref 2) +%Image::ExifTool::XMP::pur = ( + %xmpTableDefaults, + GROUPS => { 0 => 'XMP', 1 => 'XMP-pur', 2 => 'Document' }, + NAMESPACE => 'pur', + AVOID => 1, + NOTES => q{ + PRISM Usage Rights 3.0 namespace tags. (see + L<http://www.prismstandard.org/>) + }, + adultContentWarning => { List => 'Bag' }, + agreement => { List => 'Bag' }, + copyright => { + # (not clear in 3.0 spec, which lists only "bag Text", and called + # "copyrightDate" instead of "copyright" the PRISM basic 3.0 spec) + Writable => 'lang-alt', + Groups => { 2 => 'Author' }, + }, + creditLine => { List => 'Bag' }, + embargoDate => { List => 'Bag', %dateTimeInfo, Groups => { 2 => 'Time'} }, + exclusivityEndDate => { List => 'Bag', %dateTimeInfo, Groups => { 2 => 'Time'} }, + expirationDate => { List => 'Bag', %dateTimeInfo, Groups => { 2 => 'Time'} }, + imageSizeRestriction=> { }, + optionEndDate => { List => 'Bag', %dateTimeInfo, Groups => { 2 => 'Time'} }, + permissions => { List => 'Bag' }, + restrictions => { List => 'Bag' }, + reuseProhibited => { Writable => 'boolean' }, + rightsAgent => { }, + rightsOwner => { }, + # usageFee => { List => 'Bag' }, # (not in 3.0) +); + +# PRISM Metadata for Images namespace (pmi) (ref 2) +%Image::ExifTool::XMP::pmi = ( + %xmpTableDefaults, + GROUPS => { 0 => 'XMP', 1 => 'XMP-pmi', 2 => 'Image' }, + NAMESPACE => 'pmi', + AVOID => 1, + NOTES => q{ + PRISM Metadata for Images 3.0 namespace tags. (see + L<http://www.prismstandard.org/>) + }, + color => { + PrintConv => { + bw => 'BW', + color => 'Color', + sepia => 'Sepia', + duotone => 'Duotone', + tritone => 'Tritone', + quadtone => 'Quadtone', + }, + }, + contactInfo => { }, + displayName => { }, + distributorProductID => { }, + eventAlias => { }, + eventEnd => { }, + eventStart => { }, + eventSubtype => { }, + eventType => { }, + field => { }, + framing => { }, + location => { }, + make => { }, + manufacturer => { }, + model => { }, + modelYear => { }, + objectDescription=>{ }, + objectSubtype => { }, + objectType => { }, + orientation => { + PrintConv => { + horizontal => 'Horizontal', + vertical => 'Vertical', + } + }, + positionDescriptor => { }, + productID => { }, + productIDType => { }, + season => { + PrintConv => { + spring => 'Spring', + summer => 'Summer', + fall => 'Fall', + winter => 'Winter', + }, + }, + sequenceName => { }, + sequenceNumber => { }, + sequenceTotalNumber => { }, + setting => { }, + shootID => { }, + slideshowName => { }, + slideshowNumber => { Writable => 'integer' }, + slideshowTotalNumber => { Writable => 'integer' }, + viewpoint => { }, + visualTechnique => { }, +); + +# PRISM Recipe Metadata (prm) (ref 2) +%Image::ExifTool::XMP::prm = ( + %xmpTableDefaults, + GROUPS => { 0 => 'XMP', 1 => 'XMP-prm', 2 => 'Document' }, + NAMESPACE => 'prm', + AVOID => 1, + NOTES => q{ + PRISM Recipe Metadata 3.0 namespace tags. (see + L<http://www.prismstandard.org/>) + }, + cookingEquipment => { }, + cookingMethod => { }, + course => { }, + cuisine => { }, + dietaryNeeds => { }, + dishType => { }, + duration => { }, + ingredientExclusion => { }, + mainIngredient => { }, + meal => { }, + recipeEndingPage => { }, + recipePageRange => { }, + recipeSource => { }, + recipeStartingPage => { }, + recipeTitle => { }, + servingSize => { }, + skillLevel => { }, + specialOccasion => { }, + yield => { }, +); + +#------------------------------------------------------------------------------ + +# DICOM namespace properties (DICOM) (ref PH, written by CS3) +%Image::ExifTool::XMP::DICOM = ( + %xmpTableDefaults, + GROUPS => { 1 => 'XMP-DICOM', 2 => 'Image' }, + NAMESPACE => 'DICOM', + NOTES => q{ + DICOM namespace tags. These XMP tags allow some DICOM information to be + stored in files of other than DICOM format. See the + L<DICOM Tags documentation|Image::ExifTool::TagNames/DICOM Tags> for a list + of tags available in DICOM-format files. + }, + # change some tag names to correspond with DICOM tags + PatientName => { }, + PatientID => { }, + PatientSex => { }, + PatientDOB => { + Name => 'PatientBirthDate', + Groups => { 2 => 'Time' }, + %dateTimeInfo, + }, + StudyID => { }, + StudyPhysician => { }, + StudyDateTime => { Groups => { 2 => 'Time' }, %dateTimeInfo }, + StudyDescription => { }, + SeriesNumber => { }, + SeriesModality => { }, + SeriesDateTime => { Groups => { 2 => 'Time' }, %dateTimeInfo }, + SeriesDescription => { }, + EquipmentInstitution => { }, + EquipmentManufacturer => { }, +); + +# PixelLive namespace properties (PixelLive) (ref 3) +%Image::ExifTool::XMP::PixelLive = ( + GROUPS => { 1 => 'XMP-PixelLive', 2 => 'Image' }, + NAMESPACE => 'PixelLive', + AVOID => 1, + NOTES => q{ + PixelLive namespace tags. These tags are not writable becase they are very + uncommon and I haven't been able to locate a reference which gives the + namespace URI. + }, + AUTHOR => { Name => 'Author', Groups => { 2 => 'Author' } }, + COMMENTS => { Name => 'Comments' }, + COPYRIGHT => { Name => 'Copyright', Groups => { 2 => 'Author' } }, + DATE => { Name => 'Date', Groups => { 2 => 'Time' } }, + GENRE => { Name => 'Genre' }, + TITLE => { Name => 'Title' }, +); + +# Extensis Portfolio tags (extensis) (ref 11) +%Image::ExifTool::XMP::extensis = ( + %xmpTableDefaults, + GROUPS => { 1 => 'XMP-extensis', 2 => 'Image' }, + NAMESPACE => 'extensis', + NOTES => 'Tags used by Extensis Portfolio.', + Approved => { Writable => 'boolean' }, + ApprovedBy => { }, + ClientName => { }, + JobName => { }, + JobStatus => { }, + RoutedTo => { }, + RoutingNotes => { }, + WorkToDo => { }, +); + +# IDimager structures (ref PH) +my %sTagStruct; +%sTagStruct = ( + STRUCT_NAME => 'TagStructure', + NAMESPACE => 'ics', + LabelName => { }, + Reference => { }, + ParentReference => { }, + SubLabels => { Struct => \%sTagStruct, List => 'Bag' }, +); +my %sSubVersion = ( + STRUCT_NAME => 'SubVersion', + NAMESPACE => 'ics', + VersRef => { }, + FileName => { }, +); + +# IDimager namespace (ics) (ref PH) +%Image::ExifTool::XMP::ics = ( + %xmpTableDefaults, + GROUPS => { 0 => 'XMP', 1 => 'XMP-ics', 2 => 'Image' }, + NAMESPACE => 'ics', + NOTES => q{ + Tags used by IDimager. Nested TagStructure structures are unrolled to an + arbitrary depth of 6 to avoid infinite recursion. + }, + ImageRef => { }, + TagStructure => { Struct => \%sTagStruct, List => 'Bag' }, + TagStructureLabelName => { Name => 'LabelName1', Flat => 1 }, + TagStructureReference => { Name => 'Reference1', Flat => 1 }, + TagStructureSubLabels => { Name => 'SubLables1', Flat => 1 }, + TagStructureParentReference => { Name => 'ParentReference1', Flat => 1 }, + TagStructureSubLabelsLabelName => { Name => 'LabelName2', Flat => 1 }, + TagStructureSubLabelsReference => { Name => 'Reference2', Flat => 1 }, + TagStructureSubLabelsSubLabels => { Name => 'SubLables2', Flat => 1 }, + TagStructureSubLabelsParentReference => { Name => 'ParentReference2', Flat => 1 }, + TagStructureSubLabelsSubLabelsLabelName => { Name => 'LabelName3', Flat => 1 }, + TagStructureSubLabelsSubLabelsReference => { Name => 'Reference3', Flat => 1 }, + TagStructureSubLabelsSubLabelsSubLabels => { Name => 'SubLables3', Flat => 1 }, + TagStructureSubLabelsSubLabelsParentReference => { Name => 'ParentReference3', Flat => 1 }, + TagStructureSubLabelsSubLabelsSubLabelsLabelName => { Name => 'LabelName4', Flat => 1 }, + TagStructureSubLabelsSubLabelsSubLabelsReference => { Name => 'Reference4', Flat => 1 }, + TagStructureSubLabelsSubLabelsSubLabelsSubLabels => { Name => 'SubLabels4', Flat => 1 }, + TagStructureSubLabelsSubLabelsSubLabelsParentReference => { Name => 'ParentReference4', Flat => 1 }, + TagStructureSubLabelsSubLabelsSubLabelsSubLabelsLabelName => { Name => 'LabelName5', Flat => 1 }, + TagStructureSubLabelsSubLabelsSubLabelsSubLabelsReference => { Name => 'Reference5', Flat => 1 }, + TagStructureSubLabelsSubLabelsSubLabelsSubLabelsSubLabels => { Name => 'SubLabels5', Flat => 1, NoSubStruct => 1 }, # break infinite recursion + TagStructureSubLabelsSubLabelsSubLabelsSubLabelsParentReference => { Name => 'ParentReference5', Flat => 1 }, + TagStructureSubLabelsSubLabelsSubLabelsSubLabelsSubLabelsLabelName => { Name => 'LabelName6', Flat => 1 }, + TagStructureSubLabelsSubLabelsSubLabelsSubLabelsSubLabelsReference => { Name => 'Reference6', Flat => 1 }, + TagStructureSubLabelsSubLabelsSubLabelsSubLabelsSubLabelsParentReference => { Name => 'ParentReference6', Flat => 1 }, + SubVersions => { Struct => \%sSubVersion, List => 'Bag' }, + SubVersionsVersRef => { Name => 'SubVersionReference', Flat => 1 }, + SubVersionsFileName => { Name => 'SubVersionFileName', Flat => 1 }, + TimeStamp => { Avoid => 1, Groups => { 2 => 'Time' }, %dateTimeInfo }, + AppVersion => { Avoid => 1 }, +); + +# ACDSee namespace (acdsee) (ref PH) +%Image::ExifTool::XMP::acdsee = ( + %xmpTableDefaults, + GROUPS => { 0 => 'XMP', 1 => 'XMP-acdsee', 2 => 'Image' }, + NAMESPACE => 'acdsee', + AVOID => 1, + NOTES => q{ + ACD Systems ACDSee namespace tags. + + (A note to software developers: Re-inventing your own private tags instead + of using the equivalent tags in standard XMP namespaces defeats one of the + most valuable features of metadata: interoperability. Your applications + mumble to themselves instead of speaking out for the rest of the world to + hear.) + }, + author => { Groups => { 2 => 'Author' } }, + caption => { }, + categories => { }, + collections=> { }, + datetime => { Name => 'DateTime', Groups => { 2 => 'Time' }, %dateTimeInfo }, + keywords => { List => 'Bag' }, + notes => { }, + rating => { Writable => 'real' }, # integer? + tagged => { Writable => 'boolean' }, + rawrppused => { Writable => 'boolean' }, + rpp => { + Name => 'RPP', + Writable => 'lang-alt', + Notes => 'raw processing settings in XML format', + Binary => 1, + }, + dpp => { + Name => 'DPP', + Writable => 'lang-alt', + Notes => 'newer version of XML raw processing settings', + Binary => 1, + }, + # more tags (ref forum6840) + FixtureIdentifier => { }, + EditStatus => { }, + ReleaseDate => { }, + ReleaseTime => { }, + OriginatingProgram => { }, + ObjectCycle => { }, + Snapshots => { List => 'Bag', Binary => 1 }, +); + +# Picture Licensing Universal System namespace properties (xmpPLUS) +%Image::ExifTool::XMP::xmpPLUS = ( + %xmpTableDefaults, + GROUPS => { 1 => 'XMP-xmpPLUS', 2 => 'Author' }, + NAMESPACE => 'xmpPLUS', + AVOID => 1, + NOTES => q{ + XMP Picture Licensing Universal System (PLUS) tags as written by some older + Adobe applications. See L<PLUS XMP Tags|Image::ExifTool::TagNames/PLUS XMP Tags> + for the current PLUS tags. + }, + CreditLineReq => { Writable => 'boolean' }, + ReuseAllowed => { Writable => 'boolean' }, +); + +# Creative Commons namespace properties (cc) (ref 5) +%Image::ExifTool::XMP::cc = ( + %xmpTableDefaults, + GROUPS => { 1 => 'XMP-cc', 2 => 'Author' }, + NAMESPACE => 'cc', + NOTES => q{ + Creative Commons namespace tags. Note that the CC specification for XMP is + non-existent, so ExifTool must make some assumptions about the format of the + specific properties in XMP (see L<http://creativecommons.org/ns>). + }, + # Work properties + license => { Resource => 1 }, + attributionName => { }, + attributionURL => { Resource => 1 }, + morePermissions => { Resource => 1 }, + useGuidelines => { Resource => 1 }, + # License properties + permits => { + List => 'Bag', + Resource => 1, + PrintConv => { + 'cc:Sharing' => 'Sharing', + 'cc:DerivativeWorks' => 'Derivative Works', + 'cc:Reproduction' => 'Reproduction', + 'cc:Distribution' => 'Distribution', + }, + }, + requires => { + List => 'Bag', + Resource => 1, + PrintConv => { + 'cc:Copyleft' => 'Copyleft', + 'cc:LesserCopyleft' => 'Lesser Copyleft', + 'cc:SourceCode' => 'Source Code', + 'cc:ShareAlike' => 'Share Alike', + 'cc:Notice' => 'Notice', + 'cc:Attribution' => 'Attribution', + }, + }, + prohibits => { + List => 'Bag', + Resource => 1, + PrintConv => { + 'cc:HighIncomeNationUse' => 'High Income Nation Use', + 'cc:CommercialUse' => 'Commercial Use', + }, + }, + jurisdiction => { Resource => 1 }, + legalcode => { Name => 'LegalCode', Resource => 1 }, + deprecatedOn => { %dateTimeInfo, Groups => { 2 => 'Time' } }, +); + +# Description Explorer namespace properties (dex) (ref 6) +%Image::ExifTool::XMP::dex = ( + %xmpTableDefaults, + GROUPS => { 1 => 'XMP-dex', 2 => 'Image' }, + NAMESPACE => 'dex', + NOTES => q{ + Description Explorer namespace tags. These tags are not very common. The + Source and Rating tags are avoided when writing due to name conflicts with + other XMP tags. (see L<http://www.optimasc.com/products/fileid/>) + }, + crc32 => { Name => 'CRC32', Writable => 'integer' }, + source => { Avoid => 1 }, + shortdescription => { + Name => 'ShortDescription', + Writable => 'lang-alt', + }, + licensetype => { + Name => 'LicenseType', + PrintConv => { + unknown => 'Unknown', + shareware => 'Shareware', + freeware => 'Freeware', + adware => 'Adware', + demo => 'Demo', + commercial => 'Commercial', + 'public domain' => 'Public Domain', + 'open source' => 'Open Source', + }, + }, + revision => { }, + rating => { Avoid => 1 }, + os => { Name => 'OS', Writable => 'integer' }, + ffid => { Name => 'FFID' }, +); + +# iView MediaPro namespace properties (mediapro) (ref PH) +%Image::ExifTool::XMP::MediaPro = ( + %xmpTableDefaults, + GROUPS => { 1 => 'XMP-mediapro', 2 => 'Image' }, + NAMESPACE => 'mediapro', + NOTES => 'iView MediaPro namespace tags.', + Event => { + Avoid => 1, + Notes => 'avoided due to conflict with XMP-iptcExt:Event', + }, + Location => { + Avoid => 1, + Groups => { 2 => 'Location' }, + Notes => 'avoided due to conflict with XMP-iptcCore:Location', + }, + Status => { }, + People => { List => 'Bag' }, + UserFields => { List => 'Bag' }, + CatalogSets => { List => 'Bag' }, +); + +# Microsoft ExpressionMedia namespace properties (expressionmedia) +# (ref http://u88.n24.queensu.ca/exiftool/forum/index.php/topic,4235.0.html) +%Image::ExifTool::XMP::ExpressionMedia = ( + %xmpTableDefaults, + GROUPS => { 1 => 'XMP-expressionmedia', 2 => 'Image' }, + NAMESPACE => 'expressionmedia', + AVOID => 1, + NOTES => q{ + Microsoft Expression Media namespace tags. These tags are avoided when + writing due to name conflicts with tags in other schemas. + }, + Event => { }, + Status => { }, + People => { List => 'Bag' }, + CatalogSets => { List => 'Bag' }, +); + +# DigiKam namespace tags (ref PH) +%Image::ExifTool::XMP::digiKam = ( + %xmpTableDefaults, + GROUPS => { 1 => 'XMP-digiKam', 2 => 'Image' }, + NAMESPACE => 'digiKam', + NOTES => 'DigiKam namespace tags.', + CaptionsAuthorNames => { Writable => 'lang-alt' }, + CaptionsDateTimeStamps => { Writable => 'lang-alt', Groups => { 2 => 'Time' } }, + TagsList => { List => 'Seq' }, + ColorLabel => { }, + PickLabel => { }, + ImageHistory => { Avoid => 1, Notes => 'different format from EXIF:ImageHistory' }, + LensCorrectionSettings => { }, + ImageUniqueID => { Avoid => 1 }, +); + +# SWF namespace tags (ref PH) +%Image::ExifTool::XMP::swf = ( + %xmpTableDefaults, + GROUPS => { 1 => 'XMP-swf', 2 => 'Image' }, + NAMESPACE => 'swf', + NOTES => 'Adobe SWF namespace tags.', + type => { Avoid => 1 }, + bgalpha => { Name => 'BackgroundAlpha', Writable => 'integer' }, + forwardlock => { Name => 'ForwardLock', Writable => 'boolean' }, + maxstorage => { Name => 'MaxStorage', Writable => 'integer' }, # (CS5) +); + +# Sony Ericsson cell phone location tags +# refs: http://www.opencellid.org/api +# http://zonetag.research.yahoo.com/faq_location.php +# http://www.cs.columbia.edu/sip/drafts/LIF%20TS%20101%20v2.0.0.pdf +%Image::ExifTool::XMP::cell = ( + %xmpTableDefaults, + GROUPS => { 1 => 'XMP-cell', 2 => 'Location' }, + NAMESPACE => 'cell', + NOTES => 'Location tags written by some Sony Ericsson phones.', + mcc => { Name => 'MobileCountryCode' }, + mnc => { Name => 'MobileNetworkCode' }, + lac => { Name => 'LocationAreaCode' }, + cellid => { Name => 'CellTowerID' }, + cgi => { Name => 'CellGlobalID' }, + r => { Name => 'CellR' }, # (what is this? Radius?) +); + +# Apple adjustment settings (ref PH) +%Image::ExifTool::XMP::aas = ( + %xmpTableDefaults, + GROUPS => { 1 => 'XMP-aas', 2 => 'Image' }, + NAMESPACE => 'aas', + NOTES => 'Apple Adjustment Settings used by iPhone/iPad.', + CropX => { Writable => 'integer', Avoid => 1 }, + CropY => { Writable => 'integer', Avoid => 1 }, + CropW => { Writable => 'integer', Avoid => 1 }, + CropH => { Writable => 'integer', Avoid => 1 }, + AffineA => { Writable => 'real' }, + AffineB => { Writable => 'real' }, + AffineC => { Writable => 'real' }, + AffineD => { Writable => 'real' }, + AffineX => { Writable => 'real' }, + AffineY => { Writable => 'real' }, + Vibrance => { Writable => 'real', Avoid => 1 }, + Curve0x => { Writable => 'real' }, + Curve0y => { Writable => 'real' }, + Curve1x => { Writable => 'real' }, + Curve1y => { Writable => 'real' }, + Curve2x => { Writable => 'real' }, + Curve2y => { Writable => 'real' }, + Curve3x => { Writable => 'real' }, + Curve3y => { Writable => 'real' }, + Curve4x => { Writable => 'real' }, + Curve4y => { Writable => 'real' }, + Shadows => { Writable => 'real', Avoid => 1 }, + Highlights => { Writable => 'real', Avoid => 1 }, + # the following from StarGeek + FaceBalanceOrigI => { Writable => 'real' }, + FaceBalanceOrigQ => { Writable => 'real' }, + FaceBalanceStrength => { Writable => 'real' }, + FaceBalanceWarmth => { Writable => 'real' }, +); + +# Adobe creatorAtom properties (ref PH) +%Image::ExifTool::XMP::creatorAtom = ( + %xmpTableDefaults, + GROUPS => { 1 => 'XMP-creatorAtom', 2 => 'Image' }, + NAMESPACE => 'creatorAtom', + NOTES => 'Adobe creatorAtom tags, written by After Effects.', + macAtom => { + Struct => { + STRUCT_NAME => 'MacAtom', + NAMESPACE => 'creatorAtom', + applicationCode => { }, + invocationAppleEvent => { }, + posixProjectPath => { }, + }, + }, + windowsAtom => { + Struct => { + STRUCT_NAME => 'WindowsAtom', + NAMESPACE => 'creatorAtom', + extension => { }, + invocationFlags => { }, + uncProjectPath => { }, + }, + }, + aeProjectLink => { # (After Effects Project Link) + Struct => { + STRUCT_NAME => 'AEProjectLink', + NAMESPACE => 'creatorAtom', + renderTimeStamp => { Writable => 'integer' }, + compositionID => { }, + renderQueueItemID => { }, + renderOutputModuleIndex => { }, + fullPath => { }, + }, + }, +); + +# FastPictureViewer namespace properties (http://www.fastpictureviewer.com/help/#rtfcomments) +%Image::ExifTool::XMP::fpv = ( + %xmpTableDefaults, + GROUPS => { 1 => 'XMP-fpv', 2 => 'Image' }, + NAMESPACE => 'fpv', + NOTES => q{ + Fast Picture Viewer tags (see + L<http://www.fastpictureviewer.com/help/#rtfcomments>). + }, + RichTextComment => { }, +); + +# Apple FaceInfo namespace properties (ref PH) +%Image::ExifTool::XMP::apple_fi = ( + %xmpTableDefaults, + GROUPS => { 1 => 'XMP-apple-fi', 2 => 'Image' }, + NAMESPACE => 'apple-fi', + NOTES => q{ + Face information tags written by the Apple iPhone 5 inside the mwg-rs + RegionExtensions. + }, + Timestamp => { + Name => 'TimeStamp', + Writable => 'integer', + # (don't know how to convert this) + }, + FaceID => { Writable => 'integer' }, + AngleInfoRoll => { Writable => 'integer' }, + AngleInfoYaw => { Writable => 'integer' }, + ConfidenceLevel => { Writable => 'integer' }, +); + +# Google audio namespace +%Image::ExifTool::XMP::GAudio = ( + %xmpTableDefaults, + GROUPS => { 1 => 'XMP-GAudio', 2 => 'Audio' }, + NAMESPACE => 'GAudio', + Data => { + Name => 'AudioData', + ValueConv => 'Image::ExifTool::XMP::DecodeBase64($val)', + ValueConvInv => 'Image::ExifTool::XMP::EncodeBase64($val)', + }, + Mime => { Name => 'AudioMimeType' }, +); + +# Google image namespace +%Image::ExifTool::XMP::GImage = ( + %xmpTableDefaults, + GROUPS => { 1 => 'XMP-GImage', 2 => 'Image' }, + NAMESPACE => 'GImage', + Data => { + Name => 'ImageData', + ValueConv => 'Image::ExifTool::XMP::DecodeBase64($val)', + ValueConvInv => 'Image::ExifTool::XMP::EncodeBase64($val)', + }, + Mime => { Name => 'ImageMimeType' }, +); + +# Google panorama namespace properties +# (ref http://u88.n24.queensu.ca/exiftool/forum/index.php/topic,4569.0.html) +%Image::ExifTool::XMP::GPano = ( + %xmpTableDefaults, + GROUPS => { 1 => 'XMP-GPano', 2 => 'Image' }, + NAMESPACE => 'GPano', + NOTES => q{ + Panorama tags written by Google Photosphere. See + L<https://developers.google.com/panorama/metadata/> for the specification. + }, + UsePanoramaViewer => { Writable => 'boolean' }, + CaptureSoftware => { }, + StitchingSoftware => { }, + ProjectionType => { }, + PoseHeadingDegrees => { Writable => 'real' }, + PosePitchDegrees => { Writable => 'real' }, + PoseRollDegrees => { Writable => 'real' }, + InitialViewHeadingDegrees => { Writable => 'real' }, + InitialViewPitchDegrees => { Writable => 'real' }, + InitialViewRollDegrees => { Writable => 'real' }, + InitialHorizontalFOVDegrees => { Writable => 'real' }, + FirstPhotoDate => { %dateTimeInfo, Groups => { 2 => 'Time' } }, + LastPhotoDate => { %dateTimeInfo, Groups => { 2 => 'Time' } }, + SourcePhotosCount => { Writable => 'integer' }, + ExposureLockUsed => { Writable => 'boolean' }, + CroppedAreaImageWidthPixels => { Writable => 'real' }, + CroppedAreaImageHeightPixels => { Writable => 'real' }, + FullPanoWidthPixels => { Writable => 'real' }, + FullPanoHeightPixels => { Writable => 'real' }, + CroppedAreaLeftPixels => { Writable => 'real' }, + CroppedAreaTopPixels => { Writable => 'real' }, + InitialCameraDolly => { Writable => 'real' }, + # (the following have been observed, but are not in the specification) + LargestValidInteriorRectLeft => { Writable => 'real' }, + LargestValidInteriorRectTop => { Writable => 'real' }, + LargestValidInteriorRectWidth => { Writable => 'real' }, + LargestValidInteriorRectHeight => { Writable => 'real' }, +); + +# Google Spherical Images namespace (ref https://github.com/google/spatial-media/blob/master/docs/spherical-video-rfc.md) +%Image::ExifTool::XMP::GSpherical = ( + %xmpTableDefaults, + GROUPS => { 1 => 'XMP-GSpherical', 2 => 'Image' }, + NAMESPACE => 'GSpherical', + AVOID => 1, + NOTES => q{ + Not actually XMP. These RDF/XML tags are used in Google spherical MP4 + videos. See + L<https://github.com/google/spatial-media/blob/master/docs/spherical-video-rfc.md> + for the specification. + }, + # (avoid due to conflicts with XMP-GPano tags) + Spherical => { Writable => 'boolean' }, + Stitched => { Writable => 'boolean' }, + StitchingSoftware => { }, + ProjectionType => { }, + StereoMode => { }, + SourceCount => { Writable => 'integer' }, + InitialViewHeadingDegrees => { Writable => 'real' }, + InitialViewPitchDegrees => { Writable => 'real' }, + InitialViewRollDegrees => { Writable => 'real' }, + Timestamp => { + Name => 'TimeStamp', + Groups => { 2 => 'Time' }, + Writable => 'integer', + Shift => 'Time', + ValueConv => 'ConvertUnixTime($val)', #(NC) + ValueConvInv => 'GetUnixTime($val)', + PrintConv => '$self->ConvertDateTime($val)', + PrintConvInv => '$self->InverseDateTime($val)', + }, + FullPanoWidthPixels => { Writable => 'integer' }, + FullPanoHeightPixels => { Writable => 'integer' }, + CroppedAreaImageWidthPixels => { Writable => 'integer' }, + CroppedAreaImageHeightPixels=> { Writable => 'integer' }, + CroppedAreaLeftPixels => { Writable => 'integer' }, + CroppedAreaTopPixels => { Writable => 'integer' }, +); + +# Google depthmap information (ref https://developers.google.com/depthmap-metadata/reference) +%Image::ExifTool::XMP::GDepth = ( + GROUPS => { 0 => 'XMP', 1 => 'XMP-GDepth', 2 => 'Image' }, + NAMESPACE => { 'GDepth' => 'http://ns.google.com/photos/1.0/depthmap/' }, + AVOID => 1, # (too potential tag name conflicts) + NOTES => q{ + Google depthmap information. See + L<https://developers.google.com/depthmap-metadata/> for the specification. + }, + WRITABLE => 'string', # (default to string-type tags) + PRIORITY => 0, + Format => { + PrintConv => { + RangeInverse => 'RangeInverse', + RangeLinear => 'RangeLinear', + }, + }, + Near => { Writable => 'real' }, + Far => { Writable => 'real' }, + Mime => { }, + Data => { + ValueConv => 'Image::ExifTool::XMP::DecodeBase64($val)', + ValueConvInv => 'Image::ExifTool::XMP::EncodeBase64($val)', + }, + Units => { }, + MeasureType => { + PrintConv => { + OpticalAxis => 'OpticalAxis', + OpticalRay => 'OpticalRay', + }, + }, + ConfidenceMime => { }, + Confidence => { + ValueConv => 'Image::ExifTool::XMP::DecodeBase64($val)', + ValueConvInv => 'Image::ExifTool::XMP::EncodeBase64($val)', + }, + Manufacturer=> { }, + Model => { }, + Software => { }, + ImageWidth => { Writable => 'real' }, + ImageHeight => { Writable => 'real' }, +); + +# Google focus namespace +%Image::ExifTool::XMP::GFocus = ( + %xmpTableDefaults, + GROUPS => { 1 => 'XMP-GFocus', 2 => 'Image' }, + NAMESPACE => 'GFocus', + NOTES => 'Focus information found in Google depthmap images.', + BlurAtInfinity => { Writable => 'real' }, + FocalDistance => { Writable => 'real' }, + FocalPointX => { Writable => 'real' }, + FocalPointY => { Writable => 'real' }, +); + +# Getty Images namespace (ref PH) +%Image::ExifTool::XMP::GettyImages = ( + %xmpTableDefaults, + GROUPS => { 1 => 'XMP-getty', 2 => 'Image' }, + NAMESPACE => 'GettyImagesGIFT', + NOTES => q{ + The actual Getty Images namespace prefix is "GettyImagesGIFT", which is the + prefix recorded in the file, but ExifTool shortens this for the family 1 + group name. + }, + Personality => { List => 'Bag' }, + OriginalFilename => { Name => 'OriginalFileName' }, + ParentMEID => { }, + # the following from StarGeek + AssetID => { }, + CallForImage => { }, + CameraFilename => { }, + CameraMakeModel => { Avoid => 1 }, + Composition => { }, + CameraSerialNumber => { Avoid => 1 }, + ExclusiveCoverage => { }, + GIFTFtpPriority => { }, + ImageRank => { }, + MediaEventIdDate => { }, + OriginalCreateDateTime => { %dateTimeInfo, Groups => { 2 => 'Time' }, Avoid => 1 }, + ParentMediaEventID => { }, + PrimaryFTP => { List => 'Bag' }, + RoutingDestinations => { List => 'Bag' }, + RoutingExclusions => { List => 'Bag' }, + SecondaryFTP => { List => 'Bag' }, + TimeShot => { }, +); + +# RED smartphone images (ref PH) +%Image::ExifTool::XMP::LImage = ( + %xmpTableDefaults, + GROUPS => { 1 => 'XMP-LImage', 2 => 'Image' }, + NAMESPACE => 'LImage', + NOTES => 'Tags written by RED smartphones.', + MajorVersion => { }, + MinorVersion => { }, + RightAlbedo => { + Notes => 'Right stereoscopic image', + Groups => { 2 => 'Preview' }, + ValueConv => 'Image::ExifTool::XMP::DecodeBase64($val)', + ValueConvInv => 'Image::ExifTool::XMP::EncodeBase64($val)', + }, +); + +# SVG namespace properties (ref 9) +%Image::ExifTool::XMP::SVG = ( + GROUPS => { 0 => 'SVG', 1 => 'SVG', 2 => 'Image' }, + NAMESPACE => 'svg', + LANG_INFO => \&GetLangInfo, + NOTES => q{ + SVG (Scalable Vector Graphics) image tags. By default, only the top-level + SVG and Metadata tags are extracted from these images, but all graphics tags + may be extracted by setting the Unknown option to 2 (-U on the command + line). The SVG tags are not part of XMP as such, but are included with the + XMP module for convenience. (see L<http://www.w3.org/TR/SVG11/>) + }, + version => 'SVGVersion', + id => 'ID', + metadataId => 'MetadataID', + width => { + Name => 'ImageWidth', + ValueConv => '$val =~ s/px$//; $val', + }, + height => { + Name => 'ImageHeight', + ValueConv => '$val =~ s/px$//; $val', + }, +); + +# table to add tags in other namespaces +%Image::ExifTool::XMP::otherSVG = ( + GROUPS => { 0 => 'SVG', 2 => 'Unknown' }, + LANG_INFO => \&GetLangInfo, + NAMESPACE => undef, # variable namespace +); + +1; #end + +__END__ + +=head1 NAME + +Image::ExifTool::XMP2.pl - Additional XMP namespace definitions + +=head1 SYNOPSIS + +This module is loaded automatically by Image::ExifTool when required. + +=head1 DESCRIPTION + +This file contains definitions for less common XMP namespaces. + +=head1 AUTHOR + +Copyright 2003-2019, Phil Harvey (phil at owl.phy.queensu.ca) + +This library is free software; you can redistribute it and/or modify it +under the same terms as Perl itself. + +=head1 REFERENCES + +=over 4 + +=item L<http://ns.useplus.org/> + +=item L<http://www.prismstandard.org/> + +=item L<http://www.portfoliofaq.com/pfaq/v7mappings.htm> + +=item L<http://www.iptc.org/IPTC4XMP/> + +=item L<http://creativecommons.org/technology/xmp> + +=item L<http://www.optimasc.com/products/fileid/xmp-extensions.pdf> + +=item L<http://www.w3.org/TR/SVG11/> + +=back + +=head1 SEE ALSO + +L<Image::ExifTool::TagNames/XMP Tags>, +L<Image::ExifTool(3pm)|Image::ExifTool> + +=cut diff --git a/lib/Image/ExifTool/XMPStruct.pl b/lib/Image/ExifTool/XMPStruct.pl new file mode 100644 index 0000000..51a6eec --- /dev/null +++ b/lib/Image/ExifTool/XMPStruct.pl @@ -0,0 +1,846 @@ +#------------------------------------------------------------------------------ +# File: XMPStruct.pl +# +# Description: XMP structure support +# +# Revisions: 01/01/2011 - P. Harvey Created +#------------------------------------------------------------------------------ + +package Image::ExifTool::XMP; + +use strict; +use vars qw(%specialStruct %stdXlatNS); + +use Image::ExifTool qw(:Utils); +use Image::ExifTool::XMP; + +sub SerializeStruct($;$); +sub InflateStruct($;$); +sub DumpStruct($;$); +sub CheckStruct($$$); +sub AddNewStruct($$$$$$); +sub ConvertStruct($$$$;$); + +#------------------------------------------------------------------------------ +# Serialize a structure (or other object) into a simple string +# Inputs: 0) HASH ref, ARRAY ref, or SCALAR, 1) closing bracket (or undef) +# Returns: serialized structure string +# eg) "{field=text with {braces|}|, and a comma, field2=val2,field3={field4=[a,b]}}" +sub SerializeStruct($;$) +{ + my ($obj, $ket) = @_; + my ($key, $val, @vals, $rtnVal); + + if (ref $obj eq 'HASH') { + foreach $key (sort keys %$obj) { + push @vals, $key . '=' . SerializeStruct($$obj{$key}, '}'); + } + $rtnVal = '{' . join(',', @vals) . '}'; + } elsif (ref $obj eq 'ARRAY') { + foreach $val (@$obj) { + push @vals, SerializeStruct($val, ']'); + } + $rtnVal = '[' . join(',', @vals) . ']'; + } elsif (defined $obj) { + $obj = $$obj if ref $obj eq 'SCALAR'; + # escape necessary characters in string (closing bracket plus "," and "|") + my $pat = $ket ? "\\$ket|,|\\|" : ',|\\|'; + ($rtnVal = $obj) =~ s/($pat)/|$1/g; + # also must escape opening bracket or whitespace at start of string + $rtnVal =~ s/^([\s\[\{])/|$1/; + } else { + $rtnVal = ''; # allow undefined list items + } + return $rtnVal; +} + +#------------------------------------------------------------------------------ +# Inflate structure (or other object) from a serialized string +# Inputs: 0) reference to object in string form (serialized using the '|' escape) +# 1) extra delimiter for scalar values delimiters +# Returns: 0) object as a SCALAR, HASH ref, or ARRAY ref (or undef on error), +# 1) warning string (or undef) +# Notes: modifies input string to remove parsed objects +sub InflateStruct($;$) +{ + my ($obj, $delim) = @_; + my ($val, $warn, $part); + + if ($$obj =~ s/^\s*\{//) { + my %struct; + while ($$obj =~ s/^\s*([-\w:]+#?)\s*=//s) { + my $tag = $1; + my ($v, $w) = InflateStruct($obj, '}'); + $warn = $w if $w and not $warn; + return(undef, $warn) unless defined $v; + $struct{$tag} = $v; + # eat comma separator, or all done if there wasn't one + last unless $$obj =~ s/^\s*,//s; + } + # eat closing brace and warn if we didn't find one + unless ($$obj =~ s/^\s*\}//s or $warn) { + if (length $$obj) { + ($part = $$obj) =~ s/^\s*//s; + $part =~ s/[\x0d\x0a].*//s; + $part = substr($part,0,27) . '...' if length($part) > 30; + $warn = "Invalid structure field at '${part}'"; + } else { + $warn = 'Missing closing brace for structure'; + } + } + $val = \%struct; + } elsif ($$obj =~ s/^\s*\[//) { + my @list; + for (;;) { + my ($v, $w) = InflateStruct($obj, ']'); + $warn = $w if $w and not $warn; + return(undef, $warn) unless defined $v; + push @list, $v; + last unless $$obj =~ s/^\s*,//s; + } + # eat closing bracket and warn if we didn't find one + $$obj =~ s/^\s*\]//s or $warn or $warn = 'Missing closing bracket for list'; + $val = \@list; + } else { + $$obj =~ s/^\s+//s; # remove leading whitespace + # read scalar up to specified delimiter (or "," if not defined) + $val = ''; + $delim = $delim ? "\\$delim|,|\\||\$" : ',|\\||$'; + for (;;) { + $$obj =~ s/^(.*?)($delim)//s and $val .= $1; + last unless $2; + $2 eq '|' or $$obj = $2 . $$obj, last; + $$obj =~ s/^(.)//s and $val .= $1; # add escaped character + } + } + return($val, $warn); +} + +#------------------------------------------------------------------------------ +# Get XMP language code from tag name string +# Inputs: 0) tag name string +# Returns: 0) separated tag name, 1) language code (in standard case), or '' if +# language code was 'x-default', or undef if the tag had no language code +sub GetLangCode($) +{ + my $tag = shift; + if ($tag =~ /^(\w+)[-_]([a-z]{2,3}|[xi])([-_][a-z\d]{2,8}([-_][a-z\d]{1,8})*)?$/i) { + # normalize case of language codes + my ($tg, $langCode) = ($1, lc($2)); + $langCode .= (length($3) == 3 ? uc($3) : lc($3)) if $3; + $langCode =~ tr/_/-/; # RFC 3066 specifies '-' as a separator + $langCode = '' if lc($langCode) eq 'x-default'; + return($tg, $langCode); + } else { + return($tag, undef); + } +} + +#------------------------------------------------------------------------------ +# Debugging routine to dump a structure, list or scalar +# Inputs: 0) scalar, ARRAY ref or HASH ref, 1) indent (or undef) +sub DumpStruct($;$) +{ + local $_; + my ($obj, $indent) = @_; + + $indent or $indent = ''; + if (ref $obj eq 'HASH') { + print "{\n"; + foreach (sort keys %$obj) { + print "$indent $_ = "; + DumpStruct($$obj{$_}, "$indent "); + } + print $indent, "},\n"; + } elsif (ref $obj eq 'ARRAY') { + print "[\n"; + foreach (@$obj) { + print "$indent "; + DumpStruct($_, "$indent "); + } + print $indent, "],\n", + } else { + print "\"$obj\",\n"; + } +} + +#------------------------------------------------------------------------------ +# Recursively validate structure fields (tags) +# Inputs: 0) ExifTool ref, 1) Structure ref, 2) structure table definition ref +# Returns: 0) validated structure ref, 1) error string, or undef on success +# Notes: +# - fixes field names in structure and applies inverse conversions to values +# - copies structure to avoid interdependencies with calling code on referenced values +# - handles lang-alt tags, and '#' on field names +# - resets UTF-8 flag of SCALAR values +# - un-escapes for XML or HTML as per Escape option setting +sub CheckStruct($$$) +{ + my ($et, $struct, $strTable) = @_; + + my $strName = $$strTable{STRUCT_NAME} || ('XMP ' . RegisterNamespace($strTable)); + ref $struct eq 'HASH' or return wantarray ? (undef, "Expecting $strName structure") : undef; + + my ($key, $err, $warn, %copy, $rtnVal, $val); +Key: + foreach $key (keys %$struct) { + my $tag = $key; + # allow trailing '#' to disable print conversion on a per-field basis + my ($type, $fieldInfo); + $type = 'ValueConv' if $tag =~ s/#$//; + $fieldInfo = $$strTable{$tag} unless $specialStruct{$tag}; + # fix case of field name if necessary + unless ($fieldInfo) { + # (sort in reverse to get lower case (not special) tags first) + my ($fix) = reverse sort grep /^$tag$/i, keys %$strTable; + $fieldInfo = $$strTable{$tag = $fix} if $fix and not $specialStruct{$fix}; + } + until (ref $fieldInfo eq 'HASH') { + # generate wildcard fields on the fly (eg. mwg-rs:Extensions) + unless ($$strTable{NAMESPACE}) { + my ($grp, $tg, $langCode); + ($grp, $tg) = $tag =~ /^(.+):(.+)/ ? (lc $1, $2) : ('', $tag); + undef $grp if $grp eq 'XMP'; # (a group of 'XMP' is implied) + require Image::ExifTool::TagLookup; + my @matches = Image::ExifTool::TagLookup::FindTagInfo($tg); + # also look for lang-alt tags + unless (@matches) { + ($tg, $langCode) = GetLangCode($tg); + @matches = Image::ExifTool::TagLookup::FindTagInfo($tg) if defined $langCode; + } + my ($tagInfo, $priority, $ti, $g1); + # find best matching tag + foreach $ti (@matches) { + my @grps = $et->GetGroup($ti); + next unless $grps[0] eq 'XMP'; + next if $grp and $grp ne lc $grps[1]; + # must be lang-alt tag if we are writing an alternate language + next if defined $langCode and not ($$ti{Writable} and $$ti{Writable} eq 'lang-alt'); + my $pri = $$ti{Priority} || 1; + $pri -= 10 if $$ti{Avoid}; + next if defined $priority and $priority >= $pri; + $priority = $pri; + $tagInfo = $ti; + $g1 = $grps[1]; + } + $tagInfo or $warn = "'${tag}' is not a writable XMP tag", next Key; + GetPropertyPath($tagInfo); # make sure property path is generated for this tag + $tag = $$tagInfo{Name}; + $tag = "$g1:$tag" if $grp; + $tag .= "-$langCode" if $langCode; + $fieldInfo = $$strTable{$tag}; + # create new structure field if necessary + $fieldInfo or $fieldInfo = $$strTable{$tag} = { + %$tagInfo, # (also copies the necessary TagID and PropertyPath) + Namespace => $$tagInfo{Table}{NAMESPACE}, + LangCode => $langCode, + }; + # delete stuff we don't need (shouldn't cause harm, but better safe than sorry) + # - need to keep StructType and Table in case we need to call AddStructType later + delete $$fieldInfo{Description}; + delete $$fieldInfo{Groups}; + last; # write this dynamically-generated field + } + # generate lang-alt fields on the fly (eg. Iptc4xmpExt:AOTitle) + my ($tg, $langCode) = GetLangCode($tag); + if (defined $langCode) { + $fieldInfo = $$strTable{$tg} unless $specialStruct{$tg}; + unless ($fieldInfo) { + my ($fix) = reverse sort grep /^$tg$/i, keys %$strTable; + $fieldInfo = $$strTable{$tg = $fix} if $fix and not $specialStruct{$fix}; + } + if (ref $fieldInfo eq 'HASH' and $$fieldInfo{Writable} and + $$fieldInfo{Writable} eq 'lang-alt') + { + my $srcInfo = $fieldInfo; + $tag = $tg . '-' . $langCode if $langCode; + $fieldInfo = $$strTable{$tag}; + # create new structure field if necessary + $fieldInfo or $fieldInfo = $$strTable{$tag} = { + %$srcInfo, + TagID => $tg, + LangCode => $langCode, + }; + last; # write this lang-alt field + } + } + $warn = "'${tag}' is not a field of $strName"; + next Key; + } + if (ref $$struct{$key} eq 'HASH') { + $$fieldInfo{Struct} or $warn = "$tag is not a structure in $strName", next Key; + # recursively check this structure + ($val, $err) = CheckStruct($et, $$struct{$key}, $$fieldInfo{Struct}); + $err and $warn = $err, next Key; + $copy{$tag} = $val; + } elsif (ref $$struct{$key} eq 'ARRAY') { + $$fieldInfo{List} or $warn = "$tag is not a list in $strName", next Key; + # check all items in the list + my ($item, @copy); + my $i = 0; + foreach $item (@{$$struct{$key}}) { + if (not ref $item) { + $item = '' unless defined $item; # use empty string for missing items + if ($$fieldInfo{Struct}) { + # (allow empty structures) + $item =~ /^\s*$/ or $warn = "$tag items are not valid structures", next Key; + $copy[$i] = { }; # create hash for empty structure + } else { + $et->Sanitize(\$item); + ($copy[$i],$err) = $et->ConvInv($item,$fieldInfo,$tag,$strName,$type,''); + $copy[$i] = '' unless defined $copy[$i]; # avoid undefined item + $err and $warn = $err, next Key; + $err = CheckXMP($et, $fieldInfo, \$copy[$i]); + $err and $warn = "$err in $strName $tag", next Key; + } + } elsif (ref $item eq 'HASH') { + $$fieldInfo{Struct} or $warn = "$tag is not a structure in $strName", next Key; + ($copy[$i], $err) = CheckStruct($et, $item, $$fieldInfo{Struct}); + $err and $warn = $err, next Key; + } else { + $warn = "Invalid value for $tag in $strName"; + next Key; + } + ++$i; + } + $copy{$tag} = \@copy; + } elsif ($$fieldInfo{Struct}) { + $warn = "Improperly formed structure in $strName $tag"; + } else { + $et->Sanitize(\$$struct{$key}); + ($val,$err) = $et->ConvInv($$struct{$key},$fieldInfo,$tag,$strName,$type,''); + $err and $warn = $err, next Key; + next Key unless defined $val; # check for undefined + $err = CheckXMP($et, $fieldInfo, \$val); + $err and $warn = "$err in $strName $tag", next Key; + # turn this into a list if necessary + $copy{$tag} = $$fieldInfo{List} ? [ $val ] : $val; + } + } + if (%copy or not $warn) { + $rtnVal = \%copy; + undef $err; + $$et{CHECK_WARN} = $warn if $warn; + } else { + $err = $warn; + } + return wantarray ? ($rtnVal, $err) : $rtnVal; +} + +#------------------------------------------------------------------------------ +# Delete matching structures from existing linearized XMP +# Inputs: 0) ExifTool ref, 1) capture hash ref, 2) structure path ref, +# 3) new value hash ref, 4) reference to change counter +# Returns: 0) delete flag, 1) list index of deleted structure if adding to list +# 2) flag set if structure existed +# Notes: updates path to new base path for structure to be added +sub DeleteStruct($$$$$) +{ + my ($et, $capture, $pathPt, $nvHash, $changed) = @_; + my ($deleted, $added, $existed, $p, $pp, $val, $delPath); + my (@structPaths, @matchingPaths, @delPaths); + + # find all existing elements belonging to this structure + ($pp = $$pathPt) =~ s/ \d+/ \\d\+/g; + @structPaths = sort grep(/^$pp(\/|$)/, keys %$capture); + $existed = 1 if @structPaths; + # delete only structures with matching fields if necessary + if ($$nvHash{DelValue}) { + if (@{$$nvHash{DelValue}}) { + my $strTable = $$nvHash{TagInfo}{Struct}; + # all fields must match corresponding elements in the same + # root structure for it to be deleted + foreach $val (@{$$nvHash{DelValue}}) { + next unless ref $val eq 'HASH'; + my (%cap, $p2, %match); + next unless AddNewStruct(undef, undef, \%cap, $$pathPt, $val, $strTable); + foreach $p (keys %cap) { + if ($p =~ / /) { + ($p2 = $p) =~ s/ \d+/ \\d\+/g; + @matchingPaths = sort grep(/^$p2$/, @structPaths); + } else { + push @matchingPaths, $p; + } + foreach $p2 (@matchingPaths) { + $p2 =~ /^($pp)/ or next; + # language attribute must also match if it exists + my $attr = $cap{$p}[1]; + if ($$attr{'xml:lang'}) { + my $a2 = $$capture{$p2}[1]; + next unless $$a2{'xml:lang'} and $$a2{'xml:lang'} eq $$attr{'xml:lang'}; + } + if ($$capture{$p2} and $$capture{$p2}[0] eq $cap{$p}[0]) { + # ($1 contains root path for this structure) + $match{$1} = ($match{$1} || 0) + 1; + } + } + } + my $num = scalar(keys %cap); + foreach $p (keys %match) { + # do nothing unless all fields matched the same structure + next unless $match{$p} == $num; + # delete all elements of this structure + foreach $p2 (@structPaths) { + push @delPaths, $p2 if $p2 =~ /^$p/; + } + # remember path of first deleted structure + $delPath = $p if not $delPath or $delPath gt $p; + } + } + } # (else don't delete anything) + } elsif (@structPaths) { + @delPaths = @structPaths; # delete all + $structPaths[0] =~ /^($pp)/; + $delPath = $1; + } + if (@delPaths) { + my $verbose = $et->Options('Verbose'); + @delPaths = sort @delPaths if $verbose > 1; + foreach $p (@delPaths) { + $et->VerboseValue("- XMP-$p", $$capture{$p}[0]) if $verbose > 1; + delete $$capture{$p}; + $deleted = 1; + ++$$changed; + } + $delPath or warn("Internal error 1 in DeleteStruct\n"), return(undef,undef,$existed); + $$pathPt = $delPath; # return path of first element deleted + } elsif ($$nvHash{TagInfo}{List}) { + # NOTE: we don't yet properly handle lang-alt elements!!!! + if (@structPaths) { + $structPaths[-1] =~ /^($pp)/ or warn("Internal error 2 in DeleteStruct\n"), return(undef,undef,$existed); + my $path = $1; + # delete any improperly formatted xmp + if ($$capture{$path}) { + my $cap = $$capture{$path}; + # an error unless this was an empty structure + $et->Error("Improperly structured XMP ($path)",1) if ref $cap ne 'ARRAY' or $$cap[0]; + delete $$capture{$path}; + } + # (match last index to put in same lang-alt list for Bag of lang-alt items) + $path =~ m/.* (\d+)/g or warn("Internal error 3 in DeleteStruct\n"), return(undef,undef,$existed); + $added = $1; + # add after last item in list + my $len = length $added; + my $pos = pos($path) - $len; + my $nxt = substr($added, 1) + 1; + substr($path, $pos, $len) = length($nxt) . $nxt; + $$pathPt = $path; + } else { + $added = '10'; + } + } + return($deleted, $added, $existed); +} + +#------------------------------------------------------------------------------ +# Add new element to XMP capture hash +# Inputs: 0) ExifTool ref, 1) TagInfo ref, 2) capture hash ref, +# 3) resource path, 4) value ref, 5) hash ref for last used index numbers +sub AddNewTag($$$$$$) +{ + my ($et, $tagInfo, $capture, $path, $valPtr, $langIdx) = @_; + my $val = EscapeXML($$valPtr); + my %attrs; + # support writing RDF "resource" values + if ($$tagInfo{Resource}) { + $attrs{'rdf:resource'} = $val; + $val = ''; + } + if ($$tagInfo{Writable} and $$tagInfo{Writable} eq 'lang-alt') { + # write the lang-alt tag + my $langCode = $$tagInfo{LangCode}; + # add indexed lang-alt list properties + my $i = $$langIdx{$path} || 0; + $$langIdx{$path} = $i + 1; # save next list index + if ($i) { + my $idx = length($i) . $i; + $path =~ s/(.*) \d+/$1 $idx/; # set list index + } + $attrs{'xml:lang'} = $langCode || 'x-default'; + } + $$capture{$path} = [ $val, \%attrs ]; + # print verbose message + if ($et and $et->Options('Verbose') > 1) { + $et->VerboseValue("+ XMP-$path", $val); + } +} + +#------------------------------------------------------------------------------ +# Add new structure to capture hash for writing +# Inputs: 0) ExifTool object ref (or undef for no warnings), +# 1) tagInfo ref (or undef if no ExifTool), 2) capture hash ref, +# 3) base path, 4) struct ref, 5) struct hash ref +# Returns: number of tags changed +# Notes: Escapes values for XML +sub AddNewStruct($$$$$$) +{ + my ($et, $tagInfo, $capture, $basePath, $struct, $strTable) = @_; + my $verbose = $et ? $et->Options('Verbose') : 0; + my ($tag, %langIdx); + + my $ns = $$strTable{NAMESPACE} || ''; + my $changed = 0; + + # add dummy field to allow empty structures (name starts with '~' so it will come + # after all valid structure fields, which is necessary when serializing the XMP later) + %$struct or $$struct{'~dummy~'} = ''; + + foreach $tag (sort keys %$struct) { + my $fieldInfo = $$strTable{$tag}; + unless ($fieldInfo) { + next unless $tag eq '~dummy~'; # check for dummy field + $fieldInfo = { }; # create dummy field info for dummy structure + } + my $val = $$struct{$tag}; + my $propPath = $$fieldInfo{PropertyPath}; + unless ($propPath) { + $propPath = ($$fieldInfo{Namespace} || $ns) . ':' . ($$fieldInfo{TagID} || $tag); + if ($$fieldInfo{List}) { + $propPath .= "/rdf:$$fieldInfo{List}/rdf:li 10"; + } + if ($$fieldInfo{Writable} and $$fieldInfo{Writable} eq 'lang-alt') { + $propPath .= "/rdf:Alt/rdf:li 10"; + } + $$fieldInfo{PropertyPath} = $propPath; # save for next time + } + my $path = $basePath . '/' . ConformPathToNamespace($et, $propPath); + my $addedTag; + if (ref $val eq 'HASH') { + my $subStruct = $$fieldInfo{Struct} or next; + $changed += AddNewStruct($et, $tagInfo, $capture, $path, $val, $subStruct); + } elsif (ref $val eq 'ARRAY') { + next unless $$fieldInfo{List}; + my $i = 0; + my ($item, $p); + # loop through all list items (note: can't yet write multi-dimensional lists) + foreach $item (@{$val}) { + if ($i) { + # update first index in field property (may be list of lang-alt lists) + $p = ConformPathToNamespace($et, $propPath); + my $idx = length($i) . $i; + $p =~ s/ \d+/ $idx/; + $p = "$basePath/$p"; + } else { + $p = $path; + } + if (ref $item eq 'HASH') { + my $subStruct = $$fieldInfo{Struct} or next; + AddNewStruct($et, $tagInfo, $capture, $p, $item, $subStruct) or next; + } elsif (length $item) { # don't write empty items in list + AddNewTag($et, $fieldInfo, $capture, $p, \$item, \%langIdx); + $addedTag = 1; + } + ++$changed; + ++$i; + } + } else { + AddNewTag($et, $fieldInfo, $capture, $path, \$val, \%langIdx); + $addedTag = 1; + ++$changed; + } + # this is tricky, but we must add the rdf:type for contained structures + # in the case that a whole hierarchy was added at once by writing a + # flattened tag inside a variable-namespace structure + if ($addedTag and $$fieldInfo{StructType} and $$fieldInfo{Table}) { + AddStructType($et, $$fieldInfo{Table}, $capture, $propPath, $basePath); + } + } + # add 'rdf:type' property if necessary + if ($$strTable{TYPE} and $changed) { + my $path = $basePath . '/' . ConformPathToNamespace($et, "rdf:type"); + unless ($$capture{$path}) { + $$capture{$path} = [ '', { 'rdf:resource' => $$strTable{TYPE} } ]; + $et->VerboseValue("+ XMP-$path", $$strTable{TYPE}) if $verbose > 1; + } + } + return $changed; +} + +#------------------------------------------------------------------------------ +# Convert structure field values for printing +# Inputs: 0) ExifTool ref, 1) tagInfo ref for structure tag, 2) value, +# 3) conversion type: PrintConv, ValueConv or Raw (Both not allowed) +# 4) tagID of parent structure (needed only if there was no flattened tag) +# Notes: Makes a copy of the hash so any applied escapes won't affect raw values +sub ConvertStruct($$$$;$) +{ + my ($et, $tagInfo, $value, $type, $parentID) = @_; + if (ref $value eq 'HASH') { + my (%struct, $key); + my $table = $$tagInfo{Table}; + $parentID = $$tagInfo{TagID} unless $parentID; + foreach $key (keys %$value) { + my $tagID = $parentID . ucfirst($key); + my $flatInfo = $$table{$tagID}; + unless ($flatInfo) { + # handle variable-namespace structures + if ($key =~ /^XMP-(.*?:)(.*)/) { + $tagID = $1 . $parentID . ucfirst($2); + $flatInfo = $$table{$tagID}; + } + $flatInfo or $flatInfo = $tagInfo; + } + my $v = $$value{$key}; + if (ref $v) { + $v = ConvertStruct($et, $flatInfo, $v, $type, $tagID); + } else { + $v = $et->GetValue($flatInfo, $type, $v); + } + $struct{$key} = $v if defined $v; # save the converted value + } + return \%struct; + } elsif (ref $value eq 'ARRAY') { + if (defined $$et{OPTIONS}{ListItem}) { + my $li = $$et{OPTIONS}{ListItem}; + return undef unless defined $$value[$li]; + undef $$et{OPTIONS}{ListItem}; # only do top-level list + my $val = ConvertStruct($et, $tagInfo, $$value[$li], $type, $parentID); + $$et{OPTIONS}{ListItem} = $li; + return $val; + } else { + my (@list, $val); + foreach $val (@$value) { + my $v = ConvertStruct($et, $tagInfo, $val, $type, $parentID); + push @list, $v if defined $v; + } + return \@list; + } + } else { + return $et->GetValue($tagInfo, $type, $value); + } +} + +#------------------------------------------------------------------------------ +# Restore XMP structures in extracted information +# Inputs: 0) ExifTool object ref, 1) flag to keep original flattened tags +# Notes: also restores lists (including multi-dimensional) +sub RestoreStruct($;$) +{ + local $_; + my ($et, $keepFlat) = @_; + my ($key, %structs, %var, %lists, $si, %listKeys, @siList); + my $ex = $$et{TAG_EXTRA}; + my $valueHash = $$et{VALUE}; + my $tagExtra = $$et{TAG_EXTRA}; + foreach $key (keys %{$$et{TAG_INFO}}) { + $$ex{$key} or next; + my $structProps = $$ex{$key}{Struct} or next; + delete $$ex{$key}{Struct}; # (don't re-use) + my $tagInfo = $$et{TAG_INFO}{$key}; # tagInfo for flattened tag + my $table = $$tagInfo{Table}; + my $prop = shift @$structProps; + my $tag = $$prop[0]; + # get reference to structure tag (or normal list tag if not a structure) + my $strInfo = @$structProps ? $$table{$tag} : $tagInfo; + if ($strInfo) { + ref $strInfo eq 'HASH' or next; # (just to be safe) + if (@$structProps and not $$strInfo{Struct}) { + # this could happen for invalid XMP containing mixed lists + # (or for something like this -- what should we do here?: + # <meta:user-defined meta:name="License">test</meta:user-defined>) + $et->Warn("$$strInfo{Name} is not a structure!") unless $$et{NO_STRUCT_WARN}; + next; + } + } else { + # create new entry in tag table for this structure + my $g1 = $$table{GROUPS}{0} || 'XMP'; + my $name = $tag; + # tag keys will have a group 1 prefix when coming from import of XML from -X option + if ($tag =~ /(.+):(.+)/) { + my $ns; + ($ns, $name) = ($1, $2); + $ns =~ s/^XMP-//; # remove leading "XMP-" if it exists because we add it later + $ns = $stdXlatNS{$ns} if $stdXlatNS{$ns}; + $g1 .= "-$ns"; + } + $strInfo = { + Name => ucfirst $name, + Groups => { 1 => $g1 }, + Struct => 'Unknown', + }; + # add Struct entry if this is a structure + if (@$structProps) { + # this is a structure + $$strInfo{Struct} = { STRUCT_NAME => 'XMP Unknown' } if @$structProps; + } elsif ($$tagInfo{LangCode}) { + # this is lang-alt list + $tag = $tag . '-' . $$tagInfo{LangCode}; + $$strInfo{LangCode} = $$tagInfo{LangCode}; + } + AddTagToTable($table, $tag, $strInfo); + } + # use strInfo ref for base key to avoid collisions + $tag = $strInfo; + my $struct = \%structs; + my $oldStruct = $structs{$strInfo}; + # (fyi: 'lang-alt' Writable type will be valid even if tag is not pre-defined) + my $writable = $$tagInfo{Writable} || ''; + # walk through the stored structure property information + # to rebuild this structure + my ($err, $i); + for (;;) { + my $index = $$prop[1]; + if ($index and not @$structProps) { + # ignore this list if it is a simple lang-alt tag + if ($writable eq 'lang-alt') { + pop @$prop; # remove lang-alt index + undef $index if @$prop < 2; + } + # add language code if necessary + if ($$tagInfo{LangCode} and not ref $tag) { + $tag = $tag . '-' . $$tagInfo{LangCode}; + } + } + my $nextStruct = $$struct{$tag}; + if (defined $index) { + # the field is a list + $index = substr $index, 1; # remove digit count + if ($nextStruct) { + ref $nextStruct eq 'ARRAY' or $err = 2, last; + $struct = $nextStruct; + } else { + $struct = $$struct{$tag} = [ ]; + } + $nextStruct = $$struct[$index]; + # descend into multi-dimensional lists + for ($i=2; $$prop[$i]; ++$i) { + if ($nextStruct) { + ref $nextStruct eq 'ARRAY' or last; + $struct = $nextStruct; + } else { + $lists{$struct} = $struct; + $struct = $$struct[$index] = [ ]; + } + $nextStruct = $$struct[$index]; + $index = substr $$prop[$i], 1; + } + if (ref $nextStruct eq 'HASH') { + $struct = $nextStruct; # continue building sub-structure + } elsif (@$structProps) { + $lists{$struct} = $struct; + $struct = $$struct[$index] = { }; + } else { + $lists{$struct} = $struct; + $$struct[$index] = $$valueHash{$key}; + last; + } + } else { + if ($nextStruct) { + ref $nextStruct eq 'HASH' or $err = 3, last; + $struct = $nextStruct; + } elsif (@$structProps) { + $struct = $$struct{$tag} = { }; + } else { + $$struct{$tag} = $$valueHash{$key}; + last; + } + } + $prop = shift @$structProps or last; + $tag = $$prop[0]; + if ($tag =~ /(.+):(.+)/) { + # tag in variable-namespace tables will have a leading + # XMP namespace on the tag name. In this case, add + # the corresponding group1 name to the tag ID. + my ($ns, $name) = ($1, $2); + $ns = $stdXlatNS{$ns} if $stdXlatNS{$ns}; + $tag = "XMP-$ns:" . ucfirst $name; + } else { + $tag = ucfirst $tag; + } + } + if ($err) { + # this may happen if we have a structural error in the XMP + # (like an improperly contained list for example) + unless ($$et{NO_STRUCT_WARN}) { + my $ns = $$tagInfo{Namespace} || $$tagInfo{Table}{NAMESPACE} || ''; + $et->Warn("Error $err placing $ns:$$tagInfo{TagID} in structure or list", 1); + } + delete $structs{$strInfo} unless $oldStruct; + } elsif ($tagInfo eq $strInfo) { + # just a regular list tag (or an empty structure) + if ($oldStruct) { + # keep tag with lowest numbered key (well, not exactly, since + # "Tag (10)" is lt "Tag (2)", but at least "Tag" is lt + # everything else, and this is really what we care about) + my $k = $listKeys{$oldStruct}; + if ($k) { # ($k will be undef for an empty structure) + $k lt $key and $et->DeleteTag($key), next; + $et->DeleteTag($k); # remove tag with greater copy number + } + } + # replace existing value with new list + $$valueHash{$key} = $structs{$strInfo}; + $listKeys{$structs{$strInfo}} = $key; # save key for this list tag + } else { + # save strInfo ref and file order + if ($var{$strInfo}) { + # set file order to just before the first associated flattened tag + if ($var{$strInfo}[1] > $$et{FILE_ORDER}{$key}) { + $var{$strInfo}[1] = $$et{FILE_ORDER}{$key} - 0.5; + } + } else { + $var{$strInfo} = [ $strInfo, $$et{FILE_ORDER}{$key} - 0.5 ]; + } + # preserve original flattened tags if requested + if ($keepFlat) { + my $extra = $$tagExtra{$key} or next; + # restore list behaviour of this flattened tag + if ($$extra{NoList}) { + $$valueHash{$key} = $$extra{NoList}; + delete $$extra{NoList}; + } elsif ($$extra{NoListDel}) { + # delete this tag since its value was included another list + $et->DeleteTag($key); + } + } else { + $et->DeleteTag($key); # delete the flattened tag + } + } + } + # fill in undefined items in lists. In theory, undefined list items should + # be fine, but in practice the calling code may not check for this (and + # historically this wasn't necessary, so do this for backward compatibility) + foreach $si (keys %lists) { + defined $_ or $_ = '' foreach @{$lists{$si}}; + } + # make a list of all new structures we generated + $var{$_} and push @siList, $_ foreach keys %structs; + # save new structures in the same order they were read from file + foreach $si (sort { $var{$a}[1] <=> $var{$b}[1] } @siList) { + $key = $et->FoundTag($var{$si}[0], ''); + $$valueHash{$key} = $structs{$si}; + $$et{FILE_ORDER}{$key} = $var{$si}[1]; + } +} + + +1; #end + +__END__ + +=head1 NAME + +Image::ExifTool::XMPStruct.pl - XMP structure support + +=head1 SYNOPSIS + +This module is loaded automatically by Image::ExifTool when required. + +=head1 DESCRIPTION + +This file contains routines to provide read/write support of structured XMP +information. + +=head1 AUTHOR + +Copyright 2003-2019, Phil Harvey (phil at owl.phy.queensu.ca) + +This library is free software; you can redistribute it and/or modify it +under the same terms as Perl itself. + +=head1 SEE ALSO + +L<Image::ExifTool::TagNames/XMP Tags>, +L<Image::ExifTool(3pm)|Image::ExifTool> + +=cut diff --git a/lib/Image/ExifTool/ZIP.pm b/lib/Image/ExifTool/ZIP.pm new file mode 100644 index 0000000..c7e2b7c --- /dev/null +++ b/lib/Image/ExifTool/ZIP.pm @@ -0,0 +1,712 @@ +#------------------------------------------------------------------------------ +# File: ZIP.pm +# +# Description: Read ZIP archive meta information +# +# Revisions: 10/28/2007 - P. Harvey Created +# +# References: 1) http://www.pkware.com/documents/casestudies/APPNOTE.TXT +# 2) http://www.cpanforum.com/threads/9046 +# 3) http://www.gzip.org/zlib/rfc-gzip.html +# 4) http://DataCompression.info/ArchiveFormats/RAR202.txt +# 5) https://jira.atlassian.com/browse/CONF-21706 +# 6) http://wwwimages.adobe.com/www.adobe.com/content/dam/Adobe/en/devnet/indesign/cs55-docs/IDML/idml-specification.pdf +#------------------------------------------------------------------------------ + +package Image::ExifTool::ZIP; + +use strict; +use vars qw($VERSION $warnString); +use Image::ExifTool qw(:DataAccess :Utils); + +$VERSION = '1.24'; + +sub WarnProc($) { $warnString = $_[0]; } + +# file types for recognized Open Document "mimetype" values +my %openDocType = ( + 'application/vnd.oasis.opendocument.database' => 'ODB', #5 + 'application/vnd.oasis.opendocument.chart' => 'ODC', #5 + 'application/vnd.oasis.opendocument.formula' => 'ODF', #5 + 'application/vnd.oasis.opendocument.graphics' => 'ODG', #5 + 'application/vnd.oasis.opendocument.image' => 'ODI', #5 + 'application/vnd.oasis.opendocument.presentation' => 'ODP', + 'application/vnd.oasis.opendocument.spreadsheet' => 'ODS', + 'application/vnd.oasis.opendocument.text' => 'ODT', + 'application/vnd.adobe.indesign-idml-package' => 'IDML', #6 (not open doc) + 'application/epub+zip' => 'EPUB', #PH (not open doc) +); + +# iWork file types based on names of files found in the zip archive +my %iWorkFile = ( + 'Index/Slide.iwa' => 'KEY', + 'Index/Tables/DataList.iwa' => 'NUMBERS', +); + +my %iWorkType = ( + NUMBERS => 'NUMBERS', + PAGES => 'PAGES', + KEY => 'KEY', + KTH => 'KTH', + NMBTEMPLATE => 'NMBTEMPLATE', +); + +# ZIP metadata blocks +%Image::ExifTool::ZIP::Main = ( + PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData, + GROUPS => { 2 => 'Other' }, + FORMAT => 'int16u', + NOTES => q{ + The following tags are extracted from ZIP archives. ExifTool also extracts + additional meta information from compressed documents inside some ZIP-based + files such Office Open XML (DOCX, PPTX and XLSX), Open Document (ODB, ODC, + ODF, ODG, ODI, ODP, ODS and ODT), iWork (KEY, PAGES, NUMBERS), Capture One + Enhanced Image Package (EIP), Adobe InDesign Markup Language (IDML), + Electronic Publication (EPUB), and Sketch design files (SKETCH). The + ExifTool family 3 groups may be used to organize ZIP tags by embedded + document number (ie. the exiftool C<-g3> option). + }, + 2 => 'ZipRequiredVersion', + 3 => { + Name => 'ZipBitFlag', + PrintConv => '$val ? sprintf("0x%.4x",$val) : $val', + }, + 4 => { + Name => 'ZipCompression', + PrintConv => { + 0 => 'None', + 1 => 'Shrunk', + 2 => 'Reduced with compression factor 1', + 3 => 'Reduced with compression factor 2', + 4 => 'Reduced with compression factor 3', + 5 => 'Reduced with compression factor 4', + 6 => 'Imploded', + 7 => 'Tokenized', + 8 => 'Deflated', + 9 => 'Enhanced Deflate using Deflate64(tm)', + 10 => 'Imploded (old IBM TERSE)', + 12 => 'BZIP2', + 14 => 'LZMA (EFS)', + 18 => 'IBM TERSE (new)', + 19 => 'IBM LZ77 z Architecture (PFS)', + 96 => 'JPEG recompressed', #2 + 97 => 'WavPack compressed', #2 + 98 => 'PPMd version I, Rev 1', + }, + }, + 5 => { + Name => 'ZipModifyDate', + Format => 'int32u', + Groups => { 2 => 'Time' }, + ValueConv => sub { + my $val = shift; + return sprintf('%.4d:%.2d:%.2d %.2d:%.2d:%.2d', + ($val >> 25) + 1980, # year + ($val >> 21) & 0x0f, # month + ($val >> 16) & 0x1f, # day + ($val >> 11) & 0x1f, # hour + ($val >> 5) & 0x3f, # minute + ($val & 0x1f) * 2 # second + ); + }, + PrintConv => '$self->ConvertDateTime($val)', + }, + 7 => { Name => 'ZipCRC', Format => 'int32u', PrintConv => 'sprintf("0x%.8x",$val)' }, + 9 => { Name => 'ZipCompressedSize', Format => 'int32u' }, + 11 => { Name => 'ZipUncompressedSize', Format => 'int32u' }, + 13 => { + Name => 'ZipFileNameLength', + # don't store a tag -- just extract the value for use with ZipFileName + Hidden => 1, + RawConv => '$$self{ZipFileNameLength} = $val; undef', + }, + # 14 => 'ZipExtraFieldLength', + 15 => { + Name => 'ZipFileName', + Format => 'string[$$self{ZipFileNameLength}]', + }, +); + +# GNU ZIP tags (ref 3) +%Image::ExifTool::ZIP::GZIP = ( + PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData, + GROUPS => { 2 => 'Other' }, + NOTES => q{ + These tags are extracted from GZIP (GNU ZIP) archives, but currently only + for the first file in the archive. + }, + 2 => { + Name => 'Compression', + PrintConv => { + 8 => 'Deflated', + }, + }, + 3 => { + Name => 'Flags', + PrintConv => { BITMASK => { + 0 => 'Text', + 1 => 'CRC16', + 2 => 'ExtraFields', + 3 => 'FileName', + 4 => 'Comment', + }}, + }, + 4 => { + Name => 'ModifyDate', + Format => 'int32u', + Groups => { 2 => 'Time' }, + ValueConv => 'ConvertUnixTime($val,1)', + PrintConv => '$self->ConvertDateTime($val)', + }, + 8 => { + Name => 'ExtraFlags', + PrintConv => { + 0 => '(none)', + 2 => 'Maximum Compression', + 4 => 'Fastest Algorithm', + }, + }, + 9 => { + Name => 'OperatingSystem', + PrintConv => { + 0 => 'FAT filesystem (MS-DOS, OS/2, NT/Win32)', + 1 => 'Amiga', + 2 => 'VMS (or OpenVMS)', + 3 => 'Unix', + 4 => 'VM/CMS', + 5 => 'Atari TOS', + 6 => 'HPFS filesystem (OS/2, NT)', + 7 => 'Macintosh', + 8 => 'Z-System', + 9 => 'CP/M', + 10 => 'TOPS-20', + 11 => 'NTFS filesystem (NT)', + 12 => 'QDOS', + 13 => 'Acorn RISCOS', + 255 => 'unknown', + }, + }, + 10 => 'ArchivedFileName', + 11 => 'Comment', +); + +# RAR tags (ref 4) +%Image::ExifTool::ZIP::RAR = ( + PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData, + GROUPS => { 2 => 'Other' }, + NOTES => 'These tags are extracted from RAR archive files.', + 0 => { + Name => 'CompressedSize', + Format => 'int32u', + }, + 4 => { + Name => 'UncompressedSize', + Format => 'int32u', + }, + 8 => { + Name => 'OperatingSystem', + PrintConv => { + 0 => 'MS-DOS', + 1 => 'OS/2', + 2 => 'Win32', + 3 => 'Unix', + }, + }, + 13 => { + Name => 'ModifyDate', + Format => 'int32u', + Groups => { 2 => 'Time' }, + ValueConv => sub { + my $val = shift; + return sprintf('%.4d:%.2d:%.2d %.2d:%.2d:%.2d', + ($val >> 25) + 1980, # year + ($val >> 21) & 0x0f, # month + ($val >> 16) & 0x1f, # day + ($val >> 11) & 0x1f, # hour + ($val >> 5) & 0x3f, # minute + ($val & 0x1f) * 2 # second + ); + }, + PrintConv => '$self->ConvertDateTime($val)', + }, + 18 => { + Name => 'PackingMethod', + PrintHex => 1, + PrintConv => { + 0x30 => 'Stored', + 0x31 => 'Fastest', + 0x32 => 'Fast', + 0x33 => 'Normal', + 0x34 => 'Good Compression', + 0x35 => 'Best Compression', + }, + }, + 19 => { + Name => 'FileNameLength', + Format => 'int16u', + Hidden => 1, + RawConv => '$$self{FileNameLength} = $val; undef', + }, + 25 => { + Name => 'ArchivedFileName', + Format => 'string[$$self{FileNameLength}]', + }, +); + +#------------------------------------------------------------------------------ +# Extract information from a RAR file (ref 4) +# Inputs: 0) ExifTool object reference, 1) dirInfo reference +# Returns: 1 on success, 0 if this wasn't a valid RAR file +sub ProcessRAR($$) +{ + my ($et, $dirInfo) = @_; + my $raf = $$dirInfo{RAF}; + my ($flags, $buff); + + return 0 unless $raf->Read($buff, 7) and $buff eq "Rar!\x1a\x07\0"; + + $et->SetFileType(); + SetByteOrder('II'); + my $tagTablePtr = GetTagTable('Image::ExifTool::ZIP::RAR'); + my $docNum = 0; + + for (;;) { + # read block header + $raf->Read($buff, 7) == 7 or last; + my ($type, $flags, $size) = unpack('xxCvv', $buff); + $size -= 7; + if ($flags & 0x8000) { + $raf->Read($buff, 4) == 4 or last; + $size += unpack('V',$buff) - 4; + } + last if $size < 0; + next unless $size; # ignore blocks with no data + # don't try to read very large blocks unless LargeFileSupport is enabled + if ($size > 0x80000000 and not $et->Options('LargeFileSupport')) { + $et->Warn('Large block encountered. Aborting.'); + last; + } + # process the block + if ($type == 0x74) { # file block + # read maximum 4 KB from a file block + my $n = $size > 4096 ? 4096 : $size; + $raf->Read($buff, $n) == $n or last; + # add compressed size to start of data so we can extract it with the other tags + $buff = pack('V',$size) . $buff; + $$et{DOC_NUM} = ++$docNum; + $et->ProcessDirectory({ DataPt => \$buff }, $tagTablePtr); + $size -= $n; + } elsif ($type == 0x75 and $size > 6) { # comment block + $raf->Read($buff, $size) == $size or last; + # save comment, only if "Stored" (this is untested) + if (Get8u(\$buff, 3) == 0x30) { + $et->FoundTag('Comment', substr($buff, 6)); + } + next; + } + # seek to the start of the next block + $raf->Seek($size, 1) or last if $size; + } + $$et{DOC_NUM} = 0; + + return 1; +} + +#------------------------------------------------------------------------------ +# Extract information from a GNU ZIP file (ref 3) +# Inputs: 0) ExifTool object reference, 1) dirInfo reference +# Returns: 1 on success, 0 if this wasn't a valid GZIP file +sub ProcessGZIP($$) +{ + my ($et, $dirInfo) = @_; + my $raf = $$dirInfo{RAF}; + my ($flags, $buff); + + return 0 unless $raf->Read($buff, 10) and $buff =~ /^\x1f\x8b\x08/; + + $et->SetFileType(); + SetByteOrder('II'); + + my $tagTablePtr = GetTagTable('Image::ExifTool::ZIP::GZIP'); + $et->HandleTag($tagTablePtr, 2, Get8u(\$buff, 2)); + $et->HandleTag($tagTablePtr, 3, $flags = Get8u(\$buff, 3)); + $et->HandleTag($tagTablePtr, 4, Get32u(\$buff, 4)); + $et->HandleTag($tagTablePtr, 8, Get8u(\$buff, 8)); + $et->HandleTag($tagTablePtr, 9, Get8u(\$buff, 9)); + + # extract file name and comment if they exist + if ($flags & 0x18) { + if ($flags & 0x04) { + # skip extra field + $raf->Read($buff, 2) == 2 or return 1; + my $len = Get16u(\$buff, 0); + $raf->Read($buff, $len) == $len or return 1; + } + $raf->Read($buff, 4096) or return 1; + my $pos = 0; + my $tagID; + # loop for ArchivedFileName (10) and Comment (11) tags + foreach $tagID (10, 11) { + my $mask = $tagID == 10 ? 0x08 : 0x10; + next unless $flags & $mask; + my $end = $buff =~ /\0/g ? pos($buff) - 1 : length($buff); + # (the doc specifies the string should be ISO 8859-1, + # but in OS X it seems to be UTF-8, so don't translate + # it because I could just as easily screw it up) + my $str = substr($buff, $pos, $end - $pos); + $et->HandleTag($tagTablePtr, $tagID, $str); + last if $end >= length $buff; + $pos = $end + 1; + } + } + return 1; +} + +#------------------------------------------------------------------------------ +# Call HandleTags for attributes of an Archive::Zip member +# Inputs: 0) ExifTool object ref, 1) member ref, 2) optional tag table ref +sub HandleMember($$;$) +{ + my ($et, $member, $tagTablePtr) = @_; + $tagTablePtr or $tagTablePtr = GetTagTable('Image::ExifTool::ZIP::Main'); + $et->HandleTag($tagTablePtr, 2, $member->versionNeededToExtract()); + $et->HandleTag($tagTablePtr, 3, $member->bitFlag()); + $et->HandleTag($tagTablePtr, 4, $member->compressionMethod()); + $et->HandleTag($tagTablePtr, 5, $member->lastModFileDateTime()); + $et->HandleTag($tagTablePtr, 7, $member->crc32()); + $et->HandleTag($tagTablePtr, 9, $member->compressedSize()); + $et->HandleTag($tagTablePtr, 11, $member->uncompressedSize()); + $et->HandleTag($tagTablePtr, 15, $member->fileName()); +} + +#------------------------------------------------------------------------------ +# Extract information from a ZIP file +# Inputs: 0) ExifTool object reference, 1) dirInfo reference +# Returns: 1 on success, 0 if this wasn't a valid ZIP file +sub ProcessZIP($$) +{ + my ($et, $dirInfo) = @_; + my $raf = $$dirInfo{RAF}; + my ($buff, $buf2, $zip, $docNum); + + return 0 unless $raf->Read($buff, 30) == 30 and $buff =~ /^PK\x03\x04/; + + my $tagTablePtr = GetTagTable('Image::ExifTool::ZIP::Main'); + + # use Archive::Zip if avilable + for (;;) { + unless (eval { require Archive::Zip } and eval { require IO::File }) { + if ($$et{FILE_EXT} and $$et{FILE_EXT} ne 'ZIP') { + $et->Warn("Install Archive::Zip to decode compressed ZIP information"); + } + last; + } + # Archive::Zip requires a seekable IO::File object + my $fh; + if ($raf->{TESTED} >= 0) { + unless (eval { require IO::File }) { + # (this shouldn't happen because IO::File is a prerequisite of Archive::Zip) + $et->Warn("Install IO::File to decode compressed ZIP information"); + last; + } + $raf->Seek(0,0); + $fh = $raf->{FILE_PT}; + bless $fh, 'IO::File'; # Archive::Zip expects an IO::File object + } elsif (eval { require IO::String }) { + # read the whole file into memory (what else can I do?) + $raf->Slurp(); + $fh = new IO::String ${$raf->{BUFF_PT}}; + } else { + my $type = $raf->{FILE_PT} ? 'pipe or socket' : 'scalar reference'; + $et->Warn("Install IO::String to decode compressed ZIP information from a $type"); + last; + } + $et->VPrint(1, " --- using Archive::Zip ---\n"); + $zip = new Archive::Zip; + # catch all warnings! (Archive::Zip is bad for this) + local $SIG{'__WARN__'} = \&WarnProc; + my $status = $zip->readFromFileHandle($fh); + if ($status eq '4' and $raf->{TESTED} >= 0 and eval { require IO::String } and + $raf->Seek(0,2) and $raf->Tell() < 100000000) + { + # try again, reading it ourself this time in an attempt to avoid + # a failed test with Perl 5.6.2 GNU/Linux 2.6.32-5-686 i686-linux-64int-ld + $raf->Seek(0,0); + $raf->Slurp(); + $fh = new IO::String ${$raf->{BUFF_PT}}; + $zip = new Archive::Zip; + $status = $zip->readFromFileHandle($fh); + } + if ($status) { + undef $zip; + my %err = ( 1=>'Stream end error', 3=>'Format error', 4=>'IO error' ); + my $err = $err{$status} || "Error $status"; + $et->Warn("$err reading ZIP file"); + last; + } + $$dirInfo{ZIP} = $zip; + + # check for an Office Open file (DOCX, etc) + # --> read '[Content_Types].xml' to determine the file type + my ($mime, @members, $epub); + my $cType = $zip->memberNamed('[Content_Types].xml'); + if ($cType) { + ($buff, $status) = $zip->contents($cType); + if (not $status and $buff =~ /ContentType\s*=\s*(['"])([^"']+)\.main(\+xml)?\1/) { + $mime = $2; + } + } + # check for docProps if we couldn't find a MIME type + $mime or @members = $zip->membersMatching('^docProps/.*\.(xml|XML)$'); + if ($mime or @members) { + $$dirInfo{MIME} = $mime; + require Image::ExifTool::OOXML; + Image::ExifTool::OOXML::ProcessDOCX($et, $dirInfo); + delete $$dirInfo{MIME}; + last; + } + + # check for an EIP file + @members = $zip->membersMatching('^CaptureOne/.*\.(cos|COS)$'); + if (@members) { + require Image::ExifTool::CaptureOne; + Image::ExifTool::CaptureOne::ProcessEIP($et, $dirInfo); + last; + } + + # check for an iWork file + @members = $zip->membersMatching('(?i)^(index\.(xml|apxl)|QuickLook/Thumbnail\.jpg|[^/]+\.(pages|numbers|key)/Index.(zip|xml|apxl))$'); + if (@members) { + require Image::ExifTool::iWork; + Image::ExifTool::iWork::Process_iWork($et, $dirInfo); + last; + } + + # check for an Open Document, IDML or EPUB file + my $mType = $zip->memberNamed('mimetype'); + if ($mType) { + ($mime, $status) = $zip->contents($mType); + if (not $status and $mime =~ /([\x21-\xfe]+)/s) { + # clean up MIME type just in case (note that MIME is case insensitive) + $mime = lc $1; + $et->SetFileType($openDocType{$mime} || 'ZIP', $mime); + $et->Warn("Unrecognized MIMEType $mime") unless $openDocType{$mime}; + # extract Open Document metadata from "meta.xml" + my $meta = $zip->memberNamed('meta.xml'); + # IDML files have metadata in a different place (ref 6) + $meta or $meta = $zip->memberNamed('META-INF/metadata.xml'); + if ($meta) { + ($buff, $status) = $zip->contents($meta); + unless ($status) { + my %dirInfo = ( + DirName => 'XML', + DataPt => \$buff, + DirLen => length $buff, + DataLen => length $buff, + ); + # (avoid structure warnings when copying from XML) + my $oldWarn = $$et{NO_STRUCT_WARN}; + $$et{NO_STRUCT_WARN} = 1; + $et->ProcessDirectory(\%dirInfo, GetTagTable('Image::ExifTool::XMP::Main')); + $$et{NO_STRUCT_WARN} = $oldWarn; + } + } + # process rootfile of EPUB container if applicable + for (;;) { + last if $meta and $mime ne 'application/epub+zip'; + my $container = $zip->memberNamed('META-INF/container.xml'); + ($buff, $status) = $zip->contents($container); + last if $status; + $buff =~ /<rootfile\s+[^>]*?\bfull-path=(['"])(.*?)\1/s or last; + # load the rootfile data (OPF extension; contains XML metadata) + my $meta2 = $zip->memberNamed($2) or last; + $meta = $meta2; + ($buff, $status) = $zip->contents($meta); + last if $status; + # use opf:event to generate more meaningful tag names for dc:date + while ($buff =~ s{<dc:date opf:event="(\w+)">([^<]+)</dc:date>}{<dc:${1}Date>$2</dc:${1}Date>}s) { + my $dcTable = GetTagTable('Image::ExifTool::XMP::dc'); + my $tag = "${1}Date"; + AddTagToTable($dcTable, $tag, { + Name => ucfirst $tag, + Groups => { 2 => 'Time' }, + List => 'Seq', + %Image::ExifTool::XMP::dateTimeInfo + }) unless $$dcTable{$tag}; + } + my %dirInfo = ( + DataPt => \$buff, + DirLen => length $buff, + DataLen => length $buff, + IgnoreProp => { 'package' => 1, metadata => 1 }, + ); + # (avoid structure warnings when copying from XML) + my $oldWarn = $$et{NO_STRUCT_WARN}; + $$et{NO_STRUCT_WARN} = 1; + $et->ProcessDirectory(\%dirInfo, GetTagTable('Image::ExifTool::XMP::XML')); + $$et{NO_STRUCT_WARN} = $oldWarn; + last; + } + if ($openDocType{$mime} or $meta) { + # extract preview image(s) from "Thumbnails" directory if they exist + my $type; + my %tag = ( jpg => 'PreviewImage', png => 'PreviewPNG' ); + foreach $type ('jpg', 'png') { + my $thumb = $zip->memberNamed("Thumbnails/thumbnail.$type"); + next unless $thumb; + ($buff, $status) = $zip->contents($thumb); + $et->FoundTag($tag{$type}, $buff) unless $status; + } + last; # all done since we recognized the MIME type or found metadata + } + # continue on to list ZIP contents... + } + } + + # otherwise just extract general ZIP information + $et->SetFileType(); + @members = $zip->members(); + $docNum = 0; + my ($member, $iWorkType); + # special files to extract + my %extract = ( + 'meta.json' => 1, + 'previews/preview.png' => 'PreviewPNG', + 'preview.jpg' => 'PreviewImage', # (iWork 2013 files) + 'preview-web.jpg' => 'OtherImage', # (iWork 2013 files) + 'preview-micro.jpg' => 'ThumbnailImage', # (iWork 2013 files) + 'QuickLook/Thumbnail.jpg' => 'ThumbnailImage', # (iWork 2009 files) + 'QuickLook/Preview.pdf' => 'PreviewPDF', # (iWork 2009 files) + ); + foreach $member (@members) { + $$et{DOC_NUM} = ++$docNum; + HandleMember($et, $member, $tagTablePtr); + my $file = $member->fileName(); + # extract things from Sketch files + if ($extract{$file}) { + ($buff, $status) = $zip->contents($member); + $status and $et->Warn("Error extracting $file"), next; + if ($file eq 'meta.json') { + $et->ExtractInfo(\$buff, { ReEntry => 1 }); + if ($$et{VALUE}{App} and $$et{VALUE}{App} =~ /sketch/i) { + $et->OverrideFileType('SKETCH'); + } + } else { + $et->FoundTag($extract{$file} => $buff); + } + } elsif ($file eq 'Index/Document.iwa' and not $iWorkType) { + my $type = $iWorkType{$$et{FILE_EXT} || ''}; + $iWorkType = $type || 'PAGES'; + } elsif ($iWorkFile{$file}) { + $iWorkType = $iWorkFile{$file}; + } + } + $et->OverrideFileType($iWorkType) if $iWorkType; + last; + } + # all done if we processed this using Archive::Zip + if ($zip) { + delete $$dirInfo{ZIP}; + delete $$et{DOC_NUM}; + return 1; + } +# +# process the ZIP file by hand (funny, but this seems easier than using Archive::Zip) +# + $docNum = 0; + $et->VPrint(1, " -- processing as binary data --\n"); + $raf->Seek(30, 0); + $et->SetFileType(); + SetByteOrder('II'); + + # A. Local file header: + # local file header signature 0) 4 bytes (0x04034b50) + # version needed to extract 4) 2 bytes + # general purpose bit flag 6) 2 bytes + # compression method 8) 2 bytes + # last mod file time 10) 2 bytes + # last mod file date 12) 2 bytes + # crc-32 14) 4 bytes + # compressed size 18) 4 bytes + # uncompressed size 22) 4 bytes + # file name length 26) 2 bytes + # extra field length 28) 2 bytes + for (;;) { + my $len = Get16u(\$buff, 26) + Get16u(\$buff, 28); + $raf->Read($buf2, $len) == $len or last; + + $$et{DOC_NUM} = ++$docNum; + $buff .= $buf2; + my %dirInfo = ( + DataPt => \$buff, + DataPos => $raf->Tell() - 30 - $len, + DataLen => 30 + $len, + DirStart => 0, + DirLen => 30 + $len, + ); + $et->ProcessDirectory(\%dirInfo, $tagTablePtr); + my $flags = Get16u(\$buff, 6); + if ($flags & 0x08) { + # we don't yet support skipping stream mode data + # (when this happens, the CRC, compressed size and uncompressed + # sizes are set to 0 in the header. Instead, they are stored + # after the compressed data with an optional header of 0x08074b50) + $et->Warn('Stream mode data encountered, file list may be incomplete'); + last; + } + $len = Get32u(\$buff, 18); # file data length + $raf->Seek($len, 1) or last; # skip file data + $raf->Read($buff, 30) == 30 and $buff =~ /^PK\x03\x04/ or last; + } + delete $$et{DOC_NUM}; + return 1; +} + +1; # end + +__END__ + +=head1 NAME + +Image::ExifTool::ZIP - Read ZIP archive meta information + +=head1 SYNOPSIS + +This module is used by Image::ExifTool + +=head1 DESCRIPTION + +This module contains definitions required by Image::ExifTool to extract meta +information from ZIP, GZIP and RAR archives. This includes ZIP-based file +types like Office Open XML (DOCX, PPTX and XLSX), Open Document (ODB, ODC, +ODF, ODG, ODI, ODP, ODS and ODT), iWork (KEY, PAGES, NUMBERS), Capture One +Enhanced Image Package (EIP), Adobe InDesign Markup Language (IDML), +Electronic Publication (EPUB), and Sketch design files (SKETCH). + +=head1 AUTHOR + +Copyright 2003-2019, Phil Harvey (phil at owl.phy.queensu.ca) + +This library is free software; you can redistribute it and/or modify it +under the same terms as Perl itself. + +=head1 REFERENCES + +=over 4 + +=item L<http://www.pkware.com/documents/casestudies/APPNOTE.TXT> + +=item L<http://www.gzip.org/zlib/rfc-gzip.html> + +=item L<http://DataCompression.info/ArchiveFormats/RAR202.txt> + +=back + +=head1 SEE ALSO + +L<Image::ExifTool::TagNames/ZIP Tags>, +L<Image::ExifTool::TagNames/OOXML Tags>, +L<Image::ExifTool(3pm)|Image::ExifTool> + +=cut + diff --git a/lib/Image/ExifTool/iWork.pm b/lib/Image/ExifTool/iWork.pm new file mode 100644 index 0000000..15081c6 --- /dev/null +++ b/lib/Image/ExifTool/iWork.pm @@ -0,0 +1,230 @@ +#------------------------------------------------------------------------------ +# File: iWork.pm +# +# Description: Read Apple iWork '09 XML+ZIP files +# +# Revisions: 2009/11/11 - P. Harvey Created +#------------------------------------------------------------------------------ + +package Image::ExifTool::iWork; + +use strict; +use vars qw($VERSION); +use Image::ExifTool qw(:DataAccess :Utils); +use Image::ExifTool::XMP; +use Image::ExifTool::ZIP; + +$VERSION = '1.06'; + +# test for recognized iWork document extensions and outer XML elements +my %iWorkType = ( + # file extensions + NUMBERS => 'NUMBERS', + PAGES => 'PAGES', + KEY => 'KEY', + KTH => 'KTH', + NMBTEMPLATE => 'NMBTEMPLATE', + # we don't support double extensions -- + # "PAGES.TEMPLATE" => 'Apple Pages Template', + # outer XML elements + 'ls:document' => 'NUMBERS', + 'sl:document' => 'PAGES', + 'key:presentation' => 'KEY', +); + +# MIME types for iWork files (Apple has not registered these yet, but these +# are my best guess after doing some googling. I'm not 100% sure what "sff" +# indicates, but I think it refers to the new "flattened" package format) +my %mimeType = ( + 'NUMBERS' => 'application/x-iwork-numbers-sffnumbers', + 'PAGES' => 'application/x-iwork-pages-sffpages', + 'KEY' => 'application/x-iWork-keynote-sffkey', + 'NMBTEMPLATE' => 'application/x-iwork-numbers-sfftemplate', + 'PAGES.TEMPLATE'=> 'application/x-iwork-pages-sfftemplate', + 'KTH' => 'application/x-iWork-keynote-sffkth', +); + +# iWork tags +%Image::ExifTool::iWork::Main = ( + GROUPS => { 0 => 'XML', 1 => 'XML', 2 => 'Document' }, + PROCESS_PROC => \&Image::ExifTool::XMP::ProcessXMP, + VARS => { NO_ID => 1 }, + NOTES => q{ + The Apple iWork '09 file format is a ZIP archive containing XML files + similar to the Office Open XML (OOXML) format. Metadata tags in iWork + files are extracted even if they don't appear below. + }, + authors => { Name => 'Author', Groups => { 2 => 'Author' } }, + comment => { }, + copyright => { Groups => { 2 => 'Author' } }, + keywords => { }, + projects => { List => 1 }, + title => { }, +); + +#------------------------------------------------------------------------------ +# Generate a tag ID for this XML tag +# Inputs: 0) tag property name list ref +# Returns: tagID +sub GetTagID($) +{ + my $props = shift; + return 0 if $$props[-1] =~ /^\w+:ID$/; # ignore ID tags + return ($$props[0] =~ /^.*?:(.*)/) ? $1 : $$props[0]; +} + +#------------------------------------------------------------------------------ +# We found an XMP property name/value +# Inputs: 0) ExifTool object ref, 1) tag table ref +# 2) reference to array of XMP property names (last is current property) +# 3) property value, 4) attribute hash ref (not used here) +# Returns: 1 if valid tag was found +sub FoundTag($$$$;$) +{ + my ($et, $tagTablePtr, $props, $val, $attrs) = @_; + return 0 unless @$props; + my $verbose = $et->Options('Verbose'); + + $et->VPrint(0, " | - Tag '", join('/',@$props), "'\n") if $verbose > 1; + + # un-escape XML character entities + $val = Image::ExifTool::XMP::UnescapeXML($val); + # convert from UTF8 to ExifTool Charset + $val = $et->Decode($val, 'UTF8'); + my $tag = GetTagID($props) or return 0; + + # add any unknown tags to table + unless ($$tagTablePtr{$tag}) { + $et->VPrint(0, " [adding $tag]\n") if $verbose; + AddTagToTable($tagTablePtr, $tag, { Name => ucfirst $tag }); + } + # save the tag + $et->HandleTag($tagTablePtr, $tag, $val); + + return 1; +} + +#------------------------------------------------------------------------------ +# Extract information from an iWork file +# Inputs: 0) ExifTool object reference, 1) dirInfo reference +# Returns: 1 +# Notes: Upon entry to this routine, the file type has already been verified +# as ZIP and the dirInfo hash contains a 'ZIP' Archive::Zip object reference +sub Process_iWork($$) +{ + my ($et, $dirInfo) = @_; + my $zip = $$dirInfo{ZIP}; + my ($type, $index, $indexFile, $status); + + # try to determine the file type + local $SIG{'__WARN__'} = \&Image::ExifTool::ZIP::WarnProc; + # trust type given by file extension if available + $type = $iWorkType{$$et{FILE_EXT}} if $$et{FILE_EXT}; + unless ($type) { + # read the index file + my @members = $zip->membersMatching('^index\.(xml|apxl)$'); + if (@members) { + ($index, $status) = $zip->contents($members[0]); + unless ($status) { + $indexFile = $members[0]->fileName(); + if ($index =~ /^\s*<\?xml version=[^<]+<(\w+:\w+)/s) { + $type = $iWorkType{$1} if $iWorkType{$1}; + } + } + } else { + @members = $zip->membersMatching('(?i)^.*\.(pages|numbers|key)/Index.*'); + if (@members) { + my $tmp = $members[0]->fileName(); + $type = $iWorkType{uc $1} if $tmp =~ /\.(pages|numbers|key)/i; + } + } + $type or $type = 'ZIP'; # assume ZIP by default + } + $et->SetFileType($type, $mimeType{$type}); + + my @members = $zip->members(); + my $docNum = 0; + my $member; + foreach $member (@members) { + # get filename of this ZIP member + my $file = $member->fileName(); + next unless defined $file; + $et->VPrint(0, "File: $file\n"); + # set the document number and extract ZIP tags + $$et{DOC_NUM} = ++$docNum; + Image::ExifTool::ZIP::HandleMember($et, $member); + + # process only the index XML and JPEG thumbnail/preview files + next unless $file =~ m{^(index\.(xml|apxl)|QuickLook/Thumbnail\.jpg|[^/]+/preview(-micro|-web)?.jpg)$}i; + # get the file contents if necessary + # (CAREFUL! $buff MUST be local since we hand off a value ref to PreviewImage) + my ($buff, $buffPt); + if ($indexFile and $indexFile eq $file) { + # use the index file we already loaded + $buffPt = \$index; + } else { + ($buff, $status) = $zip->contents($member); + $status and $et->Warn("Error extracting $file"), next; + $buffPt = \$buff; + } + # extract JPEG as PreviewImage (should only be QuickLook/Thumbnail.jpg) + if ($file =~ /\.jpg$/) { + my $type = ($file =~ /preview-(\w+)/) ? ($1 eq 'web' ? 'Other' : 'Thumbnail') : 'Preview'; + $et->FoundTag($type . 'Image', $buffPt); + next; + } + # process "metadata" section of XML index file + next unless $$buffPt =~ /<(\w+):metadata>/g; + my $ns = $1; + my $p1 = pos $$buffPt; + next unless $$buffPt =~ m{</${ns}:metadata>}g; + # construct XML data from "metadata" section only + $$buffPt = '<?xml version="1.0"?>' . substr($$buffPt, $p1, pos($$buffPt)-$p1); + my %dirInfo = ( + DataPt => $buffPt, + DirLen => length $$buffPt, + DataLen => length $$buffPt, + XMPParseOpts => { + FoundProc => \&FoundTag, + }, + ); + my $tagTablePtr = GetTagTable('Image::ExifTool::iWork::Main'); + $et->ProcessDirectory(\%dirInfo, $tagTablePtr); + undef $$buffPt; # (free memory now) + } + delete $$et{DOC_NUM}; + return 1; +} + +1; # end + +__END__ + +=head1 NAME + +Image::ExifTool::iWork - Read Apple iWork '09 XML+ZIP files + +=head1 SYNOPSIS + +This module is used by Image::ExifTool + +=head1 DESCRIPTION + +This module contains definitions required by Image::ExifTool to extract meta +information from Apple iWork '09 XML+ZIP files. + +=head1 AUTHOR + +Copyright 2003-2019, Phil Harvey (phil at owl.phy.queensu.ca) + +This library is free software; you can redistribute it and/or modify it +under the same terms as Perl itself. + +=head1 SEE ALSO + +L<Image::ExifTool::TagNames/iWork Tags>, +L<Image::ExifTool::TagNames/OOXML Tags>, +L<Image::ExifTool(3pm)|Image::ExifTool> + +=cut + diff --git a/lib/Image/Size.pm b/lib/Image/Size.pm new file mode 100644 index 0000000..875bd7a --- /dev/null +++ b/lib/Image/Size.pm @@ -0,0 +1,982 @@ +#line 1 "Image/Size.pm" +#line 1 "Image/Size.pm" +############################################################################### +# +# This file copyright (c) 2015 by Randy J. Ray, all rights reserved +# +# Copying and distribution are permitted under the terms of the Artistic +# License 2.0 (http://www.opensource.org/licenses/artistic-license-2.0.php) or +# the GNU LGPL (http://www.opensource.org/licenses/lgpl-2.1.php). +# +############################################################################### +# +# Once upon a time, this code was lifted almost verbatim from wwwis by Alex +# Knowles, alex@ed.ac.uk. Since then, even I barely recognize it. It has +# contributions, fixes, additions and enhancements from all over the world. +# +# See the file ChangeLog for change history. +# +############################################################################### + +package Image::Size; + +require 5.006001; + +# These are the Perl::Critic policies that are being turned off globally: +## no critic(RequireBriefOpen) +## no critic(ProhibitAutomaticExportation) + +use strict; +use warnings; +use bytes; +use vars qw( + @EXPORT @EXPORT_OK %EXPORT_TAGS $VERSION $NO_CACHE %CACHE + $GIF_BEHAVIOR @TYPE_MAP %PCD_MAP $PCD_SCALE $READ_IN $LAST_POS +); + +use Exporter 'import'; + +BEGIN +{ + @EXPORT = qw(imgsize); + @EXPORT_OK = qw(imgsize html_imgsize attr_imgsize + %CACHE $NO_CACHE $PCD_SCALE $GIF_BEHAVIOR); + %EXPORT_TAGS = ('all' => [ @EXPORT_OK ]); + + $VERSION = '3.300'; + $VERSION = eval $VERSION; ## no critic(ProhibitStringyEval) + + # Default behavior for GIFs is to return the "screen" size + $GIF_BEHAVIOR = 0; +} + +# This allows people to specifically request that the cache not be used +$NO_CACHE = 0; + +# Package lexicals - invisible to outside world, used only in imgsize +# +# Mapping of patterns to the sizing routines +@TYPE_MAP = ( + qr{^GIF8[79]a} => \&gifsize, + qr{^\xFF\xD8} => \&jpegsize, + qr{^\x89PNG\x0d\x0a\x1a\x0a} => \&pngsize, + qr{^P[1-7]} => \&ppmsize, # also XVpics + qr{#define\s+\S+\s+\d+} => \&xbmsize, + qr{/[*] XPM [*]/} => \&xpmsize, + qr{^MM\x00\x2a} => \&tiffsize, + qr{^II\x2a\x00} => \&tiffsize, + qr{^BM} => \&bmpsize, + qr{^8BPS} => \&psdsize, + qr{^PCD_OPA} => \&pcdsize, + qr{^FWS} => \&swfsize, + qr{^CWS} => \&swfmxsize, + qr{^\x8aMNG\x0d\x0a\x1a\x0a} => \&mngsize, + qr{^\x01\x00\x00\x00} => \&emfsize, + qr{^RIFF(?s:....)WEBP} => \&webpsize, + qr{^\x00\x00\x01\x00} => \&icosize, + qr{^\x00\x00\x02\x00} => \&cursize, +); +# Kodak photo-CDs are weird. Don't ask me why, you really don't want details. +%PCD_MAP = ( 'base/16' => [ 192, 128 ], + 'base/4' => [ 384, 256 ], + 'base' => [ 768, 512 ], + 'base4' => [ 1536, 1024 ], + 'base16' => [ 3072, 2048 ], + 'base64' => [ 6144, 4096 ], ); +# Default scale for PCD images +$PCD_SCALE = 'base'; + +# These are lexically-scoped anonymous subroutines for reading the three +# types of input streams. When the input to imgsize() is typed, then the +# lexical "read_in" is assigned one of these, thus allowing the individual +# routines to operate on these streams abstractly. + +my $read_io = sub { + my $handle = shift; + my ($length, $offset) = @_; + + if (defined($offset) && ($offset != $LAST_POS)) + { + $LAST_POS = $offset; + return q{} if (! seek $handle, $offset, 0); + } + + my ($buffer, $rtn) = (q{}, 0); + $rtn = read $handle, $buffer, $length; + if (! $rtn) + { + $buffer = q{}; + } + $LAST_POS = tell $handle; + + return $buffer; +}; + +my $read_buf = sub { + my $buf = shift; + my ($length, $offset) = @_; + + if (defined($offset) && ($offset != $LAST_POS)) + { + $LAST_POS = $offset; + return q{} if ($LAST_POS > length ${$buf}); + } + + my $content = substr ${$buf}, $LAST_POS, $length; + $LAST_POS += length $content; + + return $content; +}; + +sub imgsize ## no critic(ProhibitExcessComplexity) +{ + my $stream = shift; + + my ($handle, $header); + my ($x, $y, $id, $mtime, @list); + # These only used if $stream is an existing open FH + my ($save_pos, $need_restore) = (0, 0); + # This is for when $stream is a locally-opened file + my $need_close = 0; + # This will contain the file name, if we got one + my $file_name = undef; + + $header = q{}; + + if (ref($stream) eq 'SCALAR') + { + $handle = $stream; + $READ_IN = $read_buf; + $header = substr ${$handle} || q{}, 0, 256; + } + elsif (ref $stream) + { + # I no longer require $stream to be in the IO::* space. So I'm assuming + # you don't hose yourself by passing a ref that can't do fileops. If + # you do, you fix it. + $handle = $stream; + $READ_IN = $read_io; + $save_pos = tell $handle; + $need_restore = 1; + + # First alteration (didn't wait long, did I?) to the existing handle: + # + # assist dain-bramaged operating systems -- SWD + # SWD: I'm a bit uncomfortable with changing the mode on a file + # that something else "owns" ... the change is global, and there + # is no way to reverse it. + # But image files ought to be handled as binary anyway. + binmode $handle; + seek $handle, 0, 0; + read $handle, $header, 256; + seek $handle, 0, 0; + } + else + { + if (! $NO_CACHE) + { + require Cwd; + require File::Spec; + + if (! File::Spec->file_name_is_absolute($stream)) + { + $stream = File::Spec->catfile(Cwd::cwd(), $stream); + } + $mtime = (stat $stream)[9]; + if (-e "$stream" and exists $CACHE{$stream}) + { + @list = split /,/, $CACHE{$stream}, 4; + + # Don't return the cache if the file is newer. + if ($mtime <= $list[0]) + { + return @list[1 .. 3]; + } + # In fact, clear it + delete $CACHE{$stream}; + } + } + + # first try to open the stream + require Symbol; + $handle = Symbol::gensym(); + if (! open $handle, '<', $stream) + { + return (undef, undef, "Can't open image file $stream: $!"); + } + + $need_close = 1; + # assist dain-bramaged operating systems -- SWD + binmode $handle; + read $handle, $header, 256; + seek $handle, 0, 0; + $READ_IN = $read_io; + $file_name = $stream; + } + $LAST_POS = 0; + + # Right now, $x, $y and $id are undef. If the while-loop below doesn't + # match the header to a file-type and call a subroutine, then the later + # block that tried Image::Magick will default to setting the id/error to + # "unknown file type". + my $tm_idx = 0; + while ($tm_idx < @TYPE_MAP) + { + if ($header =~ $TYPE_MAP[$tm_idx]) + { + ($x, $y, $id) = $TYPE_MAP[$tm_idx + 1]->($handle); + last; + } + $tm_idx += 2; + } + + # Added as an afterthought: I'm probably not the only one who uses the + # same shaded-sphere image for several items on a bulleted list: + if (! ($NO_CACHE or (ref $stream) or (! defined $x))) + { + $CACHE{$stream} = join q{,}, $mtime, $x, $y, $id; + } + + # If we were passed an existing file handle, we need to restore the + # old filepos: + if ($need_restore) + { + seek $handle, $save_pos, 0; + } + # ...and if we opened the file ourselves, we need to close it + if ($need_close) + { + close $handle; ## no critic(RequireCheckedClose) + } + + if (! defined $id) + { + if ($file_name) + { + # Image::Magick operates on file names. + ($x, $y, $id) = imagemagick_size($file_name); + } + else + { + $id = 'Data stream is not a known image file format'; + } + } + + # results: + return (wantarray) ? ($x, $y, $id) : (); +} + +sub imagemagick_size +{ + my $file_name = shift; + + my $module_name; + # First see if we have already loaded Graphics::Magick or Image::Magick + # If so, just use whichever one is already loaded. + if (exists $INC{'Graphics/Magick.pm'}) + { + $module_name = 'Graphics::Magick'; + } + elsif (exists $INC{'Image/Magick.pm'}) + { + $module_name = 'Image::Magick'; + } + # If neither are already loaded, try loading either one. + elsif (_load_magick_module('Graphics::Magick')) + { + $module_name = 'Graphics::Magick'; + } + elsif (_load_magick_module('Image::Magick')) + { + $module_name = 'Image::Magick'; + } + + if ($module_name) + { + my $img = $module_name->new(); + my $x = $img->Read($file_name); + # Image::Magick error handling is a bit weird, see + # <http://www.simplesystems.org/ImageMagick/www/perl.html#erro> + if("$x") { + return (undef, undef, "$x"); + } else { + return ($img->Get('width', 'height', 'format')); + } + + } + else { + return (undef, undef, 'Data stream is not a known image file format'); + } +} + +# load Graphics::Magick or Image::Magick if one is not already loaded. +sub _load_magick_module { + my $module_name = shift; + my $retval = eval { + local $SIG{__DIE__} = q{}; + require $module_name; + 1; + }; + return $retval ? 1 : 0; +} + + +sub html_imgsize +{ + my @args = @_; + @args = imgsize(@args); + + # Use lowercase and quotes so that it works with xhtml. + return ((defined $args[0]) ? + sprintf('width="%d" height="%d"', @args[0,1]) : + undef); +} + +sub attr_imgsize +{ + my @args = @_; + @args = imgsize(@args); + + return ((defined $args[0]) ? + (('-width', '-height', @args)[0, 2, 1, 3]) : + undef); +} + +# This used only in gifsize: +sub img_eof +{ + my $stream = shift; + + if (ref($stream) eq 'SCALAR') + { + return ($LAST_POS >= length ${$stream}); + } + + return eof $stream; +} + +# Simple converter-routine used by SWF and CWS code +sub _bin2int +{ + my $val = shift; + # "no critic" because I want it clear which args are being used by + # substr() versus unpack(). + ## no critic (ProhibitParensWithBuiltins) + return unpack 'N', pack 'B32', substr(('0' x 32) . $val, -32); +} + +########################################################################### +# Subroutine gets the size of the specified GIF +########################################################################### +sub gifsize ## no critic(ProhibitExcessComplexity) +{ + my $stream = shift; + + my ($cmapsize, $buf, $sh, $sw, $x, $y, $type); + + my $gif_blockskip = sub { + my ($skip, $blocktype) = @_; + my ($lbuf); + + $READ_IN->($stream, $skip); # Skip header (if any) + while (1) + { + if (img_eof($stream)) + { + return (undef, undef, + "Invalid/Corrupted GIF (at EOF in GIF $blocktype)"); + } + $lbuf = $READ_IN->($stream, 1); # Block size + last if ord($lbuf) == 0; # Block terminator + $READ_IN->($stream, ord $lbuf); # Skip data + } + }; + + if ($GIF_BEHAVIOR > 2) + { + return (undef, undef, + "\$Image::Size::GIF_BEHAVIOR out of range: $GIF_BEHAVIOR"); + } + + # Skip over the identifying string, since we already know this is a GIF + $type = $READ_IN->($stream, 6); + if (length($buf = $READ_IN->($stream, 7)) != 7 ) + { + return (undef, undef, 'Invalid/Corrupted GIF (bad header)'); + } + ($sw, $sh, $x) = unpack 'vv C', $buf; + if ($GIF_BEHAVIOR == 0) + { + return ($sw, $sh, 'GIF'); + } + + if ($x & 0x80) + { + $cmapsize = 3 * (2**(($x & 0x07) + 1)); + if (! $READ_IN->($stream, $cmapsize)) + { + return (undef, undef, + 'Invalid/Corrupted GIF (global color map too small?)'); + } + } + + # Before we start this loop, set $sw and $sh to 0s and use them to track + # the largest sub-image in the overall GIF. + $sw = $sh = 0; + + FINDIMAGE: + while (1) + { + if (img_eof($stream)) + { + # At this point, if we haven't returned then the user wants the + # largest of the sub-images. So, if $sh and $sw are still 0s, then + # we didn't see even one Image Descriptor block. Otherwise, return + # those two values. + if ($sw and $sh) + { + return ($sw, $sh, 'GIF'); + } + else + { + return (undef, undef, + 'Invalid/Corrupted GIF (no Image Descriptors)'); + } + } + $buf = $READ_IN->($stream, 1); + ($x) = unpack 'C', $buf; + if ($x == 0x2c) + { + # Image Descriptor (GIF87a, GIF89a 20.c.i) + if (length($buf = $READ_IN->($stream, 8)) != 8) + { + return (undef, undef, + 'Invalid/Corrupted GIF (missing image header?)'); + } + ($x, $y) = unpack 'x4 vv', $buf; + return ($x, $y, 'GIF') if ($GIF_BEHAVIOR == 1); + if ($x > $sw and $y > $sh) + { + $sw = $x; + $sh = $y; + } + } + if ($x == 0x21) + { + # Extension Introducer (GIF89a 23.c.i, could also be in GIF87a) + $buf = $READ_IN->($stream, 1); + ($x) = unpack 'C', $buf; + if ($x == 0xF9) + { + # Graphic Control Extension (GIF89a 23.c.ii) + $READ_IN->($stream, 6); # Skip it + next FINDIMAGE; # Look again for Image Descriptor + } + elsif ($x == 0xFE) + { + # Comment Extension (GIF89a 24.c.ii) + $gif_blockskip->(0, 'Comment'); + next FINDIMAGE; # Look again for Image Descriptor + } + elsif ($x == 0x01) + { + # Plain Text Label (GIF89a 25.c.ii) + $gif_blockskip->(13, 'text data'); + next FINDIMAGE; # Look again for Image Descriptor + } + elsif ($x == 0xFF) + { + # Application Extension Label (GIF89a 26.c.ii) + $gif_blockskip->(12, 'application data'); + next FINDIMAGE; # Look again for Image Descriptor + } + else + { + return (undef, undef, + sprintf 'Invalid/Corrupted GIF (Unknown ' . + 'extension %#x)', $x); + } + } + else + { + return (undef, undef, + sprintf 'Invalid/Corrupted GIF (Unknown code %#x)', $x); + } + } + + return (undef, undef, 'gifsize fell through to the end, error'); +} + +sub xbmsize +{ + my $stream = shift; + + my $input; + my ($x, $y, $id) = (undef, undef, 'Could not determine XBM size'); + + $input = $READ_IN->($stream, 1024); + if ($input =~ /^\#define\s*\S*\s*(\d+)\s*\n\#define\s*\S*\s*(\d+)/ix) + { + ($x, $y) = ($1, $2); + $id = 'XBM'; + } + + return ($x, $y, $id); +} + +# Added by Randy J. Ray, 30 Jul 1996 +# Size an XPM file by looking for the "X Y N W" line, where X and Y are +# dimensions, N is the total number of colors defined, and W is the width of +# a color in the ASCII representation, in characters. We only care about X & Y. +sub xpmsize +{ + my $stream = shift; + + my $line; + my ($x, $y, $id) = (undef, undef, 'Could not determine XPM size'); + + while ($line = $READ_IN->($stream, 1024)) + { + if ($line =~ /"\s*(\d+)\s+(\d+)(\s+\d+\s+\d+){1,2}\s*"/) + { + ($x, $y) = ($1, $2); + $id = 'XPM'; + last; + } + } + + return ($x, $y, $id); +} + +# pngsize : gets the width & height (in pixels) of a png file +# cor this program is on the cutting edge of technology! (pity it's blunt!) +# +# Re-written and tested by tmetro@vl.com +sub pngsize +{ + my $stream = shift; + + my ($x, $y, $id) = (undef, undef, 'Could not determine PNG size'); + my ($offset, $length); + + # Offset to first Chunk Type code = 8-byte ident + 4-byte chunk length + 1 + $offset = 12; $length = 4; + if ($READ_IN->($stream, $length, $offset) eq 'IHDR') + { + # IHDR = Image Header + $length = 8; + ($x, $y) = unpack 'NN', $READ_IN->($stream, $length); + $id = 'PNG'; + } + + return ($x, $y, $id); +} + +# mngsize: gets the width and height (in pixels) of an MNG file. +# See <URL:http://www.libpng.org/pub/mng/spec/> for the specification. +# +# Basically a copy of pngsize. +sub mngsize +{ + my $stream = shift; + + my ($x, $y, $id) = (undef, undef, 'Could not determine MNG size'); + my ($offset, $length); + + # Offset to first Chunk Type code = 8-byte ident + 4-byte chunk length + 1 + $offset = 12; $length = 4; + if ($READ_IN->($stream, $length, $offset) eq 'MHDR') + { + # MHDR = Image Header + $length = 8; + ($x, $y) = unpack 'NN', $READ_IN->($stream, $length); + $id = 'MNG'; + } + + return ($x, $y, $id); +} + +# jpegsize: gets the width and height (in pixels) of a jpeg file +# Andrew Tong, werdna@ugcs.caltech.edu February 14, 1995 +# modified slightly by alex@ed.ac.uk +# and further still by rjray@blackperl.com +# optimization and general re-write from tmetro@vl.com +sub jpegsize +{ + my $stream = shift; + + my $MARKER = chr 0xff; # Section marker + + my $SIZE_FIRST = 0xC0; # Range of segment identifier codes + my $SIZE_LAST = 0xC3; # that hold size info. + + my ($x, $y, $id) = (undef, undef, 'Could not determine JPEG size'); + + my ($marker, $code, $length); + my $segheader; + + # Dummy read to skip header ID + $READ_IN->($stream, 2); + while (1) + { + $segheader = $READ_IN->($stream, 2); + + # Extract the segment header. + ($marker, $code) = unpack 'a a', $segheader; + + while ( $code eq $MARKER && ($marker = $code) ) { + $segheader = $READ_IN->($stream, 1); + ($code) = unpack 'a', $segheader; + } + $segheader = $READ_IN->($stream, 2); + $length = unpack 'n', $segheader; + + # Verify that it's a valid segment. + if ($marker ne $MARKER) + { + # Was it there? + $id = 'JPEG marker not found'; + last; + } + elsif ((ord($code) >= $SIZE_FIRST) && (ord($code) <= $SIZE_LAST)) + { + # Segments that contain size info + $length = 5; + my $buf = $READ_IN->($stream, $length); + # unpack dies on truncated data + last if (length($buf) < $length); + ($y, $x) = unpack 'xnn', $buf; + $id = 'JPG'; + last; + } + else + { + # Dummy read to skip over data + $READ_IN->($stream, ($length - 2)); + } + } + + return ($x, $y, $id); +} + +# ppmsize: gets data on the PPM/PGM/PBM family. +# +# Contributed by Carsten Dominik <dominik@strw.LeidenUniv.nl> +sub ppmsize +{ + my $stream = shift; + + my ($x, $y, $id) = + (undef, undef, 'Unable to determine size of PPM/PGM/PBM data'); + my $n; + my @table = qw(nil PBM PGM PPM PBM PGM PPM); + + my $header = $READ_IN->($stream, 1024); + + # PPM file of some sort + $header =~ s/^\#.*//mg; + if ($header =~ /^(?:P([1-7]))\s+(\d+)\s+(\d+)/) + { + ($n, $x, $y) = ($1, $2, $3); + + if ($n == 7) + { + # John Bradley's XV thumbnail pics (from inwap@jomis.Tymnet.COM) + $id = 'XV'; + ($x, $y) = ($header =~ /IMGINFO:(\d+)x(\d+)/s); + } + else + { + $id = $table[$n]; + } + } + + return ($x, $y, $id); +} + +# tiffsize: size a TIFF image +# +# Contributed by Cloyce Spradling <cloyce@headgear.org> +sub tiffsize +{ + my $stream = shift; + + my ($x, $y, $id) = (undef, undef, 'Unable to determine size of TIFF data'); + + my $endian = 'n'; # Default to big-endian; I like it better + my $header = $READ_IN->($stream, 4); + if ($header =~ /II\x2a\x00/o) + { + # little-endian + $endian = 'v'; + } + + # Set up an association between data types and their corresponding + # pack/unpack specification. Don't take any special pains to deal with + # signed numbers; treat them as unsigned because none of the image + # dimensions should ever be negative. (I hope.) + my @packspec = ( undef, # nothing (shouldn't happen) + 'C', # BYTE (8-bit unsigned integer) + undef, # ASCII + $endian, # SHORT (16-bit unsigned integer) + uc $endian, # LONG (32-bit unsigned integer) + undef, # RATIONAL + 'c', # SBYTE (8-bit signed integer) + undef, # UNDEFINED + $endian, # SSHORT (16-bit unsigned integer) + uc $endian, # SLONG (32-bit unsigned integer) + ); + + my $offset = $READ_IN->($stream, 4, 4); # Get offset to IFD + $offset = unpack uc $endian, $offset; # Fix it so we can use it + + my $ifd = $READ_IN->($stream, 2, $offset); # Get num. of directory entries + my $num_dirent = unpack $endian, $ifd; # Make it useful + $offset += 2; + $num_dirent = $offset + ($num_dirent * 12); # Calc. maximum offset of IFD + + # Do all the work + $ifd = q{}; + my $tag = 0; + my $type = 0; + while ((! defined $x) || (! defined$y)) { + $ifd = $READ_IN->($stream, 12, $offset); # Get first directory entry + last if (($ifd eq q{}) || ($offset > $num_dirent)); + $offset += 12; + $tag = unpack $endian, $ifd; # ...and decode its tag + $type = unpack $endian, substr $ifd, 2, 2; # ...and the data type + # Check the type for sanity. + next if (($type > @packspec+0) || (! defined $packspec[$type])); + if ($tag == 0x0100) # ImageWidth (x) + { + # Decode the value + $x = unpack $packspec[$type], substr $ifd, 8, 4; + } + elsif ($tag == 0x0101) # ImageLength (y) + { + # Decode the value + $y = unpack $packspec[$type], substr $ifd, 8, 4; + } + } + + # Decide if we were successful or not + if (defined $x and defined $y) + { + $id = 'TIF'; + } + else + { + $id = q{}; + if (! defined $x) + { + $id = 'ImageWidth '; + } + if (! defined $y) + { + if ($id ne q{}) + { + $id .= 'and '; + } + $id .= 'ImageLength '; + } + $id .= 'tag(s) could not be found'; + } + + return ($x, $y, $id); +} + +# bmpsize: size a Windows-ish BitMaP image +# +# Adapted from code contributed by Aldo Calpini <a.calpini@romagiubileo.it> +sub bmpsize +{ + my $stream = shift; + + my ($x, $y, $id) = (undef, undef, 'Unable to determine size of BMP data'); + my $buffer; + + $buffer = $READ_IN->($stream, 26); + my $header_size = unpack 'x14V', $buffer; + if ($header_size == 12) + { + ($x, $y) = unpack 'x18vv', $buffer; # old OS/2 header + } + else + { + ($x, $y) = unpack 'x18VV', $buffer; # modern Windows header + } + if (defined $x and defined $y) + { + $id = 'BMP'; + } + + return ($x, $y, $id); +} + +# psdsize: determine the size of a PhotoShop save-file (*.PSD) +sub psdsize +{ + my $stream = shift; + + my ($x, $y, $id) = (undef, undef, 'Unable to determine size of PSD data'); + my $buffer; + + $buffer = $READ_IN->($stream, 26); + ($y, $x) = unpack 'x14NN', $buffer; + if (defined $x and defined $y) + { + $id = 'PSD'; + } + + return ($x, $y, $id); +} + +# swfsize: determine size of ShockWave/Flash files. Adapted from code sent by +# Dmitry Dorofeev <dima@yasp.com> +sub swfsize +{ + my $image = shift; + my $header = $READ_IN->($image, 33); + + my $ver = _bin2int(unpack 'B8', substr $header, 3, 1); + my $bs = unpack 'B133', substr $header, 8, 17; + my $bits = _bin2int(substr $bs, 0, 5); + my $x = int _bin2int(substr $bs, 5+$bits, $bits)/20; + my $y = int _bin2int(substr $bs, 5+$bits*3, $bits)/20; + + return ($x, $y, 'SWF'); +} + +# Suggested by Matt Mueller <mueller@wetafx.co.nz>, and based on a piece of +# sample Perl code by a currently-unknown author. Credit will be placed here +# once the name is determined. +sub pcdsize +{ + my $stream = shift; + + my ($x, $y, $id) = (undef, undef, 'Unable to determine size of PCD data'); + my $buffer = $READ_IN->($stream, 0xf00); + + # Second-tier sanity check + if (substr($buffer, 0x800, 3) ne 'PCD') + { + return ($x, $y, $id); + } + + my $orient = ord(substr $buffer, 0x0e02, 1) & 1; # Clear down to one bit + ($x, $y) = @{$Image::Size::PCD_MAP{lc $Image::Size::PCD_SCALE}} + [($orient ? (0, 1) : (1, 0))]; + + return ($x, $y, 'PCD'); +} + +# swfmxsize: determine size of compressed ShockWave/Flash MX files. Adapted +# from code sent by Victor Kuriashkin <victor@yasp.com> +sub swfmxsize +{ + my $image = shift; + + my $retval = eval { + local $SIG{__DIE__} = q{}; + require Compress::Zlib; + 1; + }; + if (! $retval) + { + return (undef, undef, "Error loading Compress::Zlib: $@"); + } + + my $header = $READ_IN->($image, 1058); + my $ver = _bin2int(unpack 'B8', substr $header, 3, 1); + + my ($d, $status) = Compress::Zlib::inflateInit(); + $header = substr $header, 8, 1024; + $header = $d->inflate($header); + + my $bs = unpack 'B133', substr $header, 0, 17; + my $bits = _bin2int(substr $bs, 0, 5); + my $x = int _bin2int(substr $bs, 5+$bits, $bits)/20; + my $y = int _bin2int(substr $bs, 5+$bits*3, $bits)/20; + + return ($x, $y, 'CWS'); +} + +# Windows EMF files, requested by Jan v/d Zee +sub emfsize +{ + my $image = shift; + + my ($x, $y); + my $buffer = $READ_IN->($image, 24); + + my ($topleft_x, $topleft_y, $bottomright_x, $bottomright_y) = + unpack 'x8V4', $buffer; + + # The four values describe a box *around* the image, not *of* the image. + # In other words, the dimensions are not inclusive. + $x = $bottomright_x - $topleft_x - 1; + $y = $bottomright_y - $topleft_y - 1; + + return ($x, $y, 'EMF'); +} + +# WEBP files, see https://developers.google.com/speed/webp/docs/riff_container +# Added by Baldur Kristinsson, github.com/bk +sub webpsize { + my $img = shift; + + # There are 26 bytes of lead-in, before the width and height info: + # 1. WEBP container + # - 'RIFF', 4 bytes + # - filesize, 4 bytes + # - 'WEBP', 4 bytes + # 2. VP8 frame + # - 'VP8', 3 bytes + # - frame meta, 8 bytes + # - marker, 3 bytes + my $buf = $READ_IN->($img, 4, 26); + my ($raw_w, $raw_h) = unpack 'SS', $buf; + my $b14 = 2**14 - 1; + + # The width and height values contain a 2-bit scaling factor, + # which is left-shifted by 14 bits. We ignore this, since it seems + # not to be relevant for our purposes. WEBP images in actual use + # all seem to have a scaling factor of 0, anyway. (The meaning + # of the scaling factor is as follows: 0=no upscale, 1=upscale by 5/4, + # 2=upscale by 5/3, 3=upscale by 2). + # + # my $wscale = $raw_w >> 14; + # my $hscale = $raw_h >> 14; + my $x = $raw_w & $b14; + my $y = $raw_h & $b14; + + return ($x, $y, 'WEBP'); +} + +# ICO files, originally contributed by Thomas Walloschke <thw@cpan.org>, +# see https://rt.cpan.org/Public/Bug/Display.html?id=46279 +# (revised by Baldur Kristinsson, github.com/bk) +sub icosize { + my $img = shift; + my ($x, $y) = unpack 'CC', $READ_IN->($img, 2, 6); + if ($x == 0) { $x = 256; } + if ($y == 0) { $y = 256; } + return ($x, $y, 'ICO'); +} + +# CUR files, originally contributed by Thomas Walloschke <thw@cpan.org>, +# see https://rt.cpan.org/Public/Bug/Display.html?id=46279 +# (revised by Baldur Kristinsson, github.com/bk) +sub cursize { + my ($x, $y, $ico) = icosize(shift); + return ($x, $y, 'CUR'); +} + + +1; + +__END__ + + + +#line 1469 diff --git a/lib/JSON/PP.pm b/lib/JSON/PP.pm index 5534b14..80c5d71 100644 --- a/lib/JSON/PP.pm +++ b/lib/JSON/PP.pm @@ -1,4 +1,6 @@ #line 1 "JSON/PP.pm" +#line 1 "JSON/PP.pm" +#line 1 "JSON/PP.pm" package JSON::PP; # JSON-2.0 diff --git a/lib/JSON/PP/Boolean.pm b/lib/JSON/PP/Boolean.pm index 8776805..2f34e3e 100644 --- a/lib/JSON/PP/Boolean.pm +++ b/lib/JSON/PP/Boolean.pm @@ -1,4 +1,6 @@ #line 1 "JSON/PP/Boolean.pm" +#line 1 "JSON/PP/Boolean.pm" +#line 1 "JSON/PP/Boolean.pm" package JSON::PP::Boolean; use strict; diff --git a/lib/PDF/API2.pm b/lib/PDF/API2.pm new file mode 100644 index 0000000..b796d13 --- /dev/null +++ b/lib/PDF/API2.pm @@ -0,0 +1,1429 @@ +#line 1 "PDF/API2.pm" +#line 1 "PDF/API2.pm" +package PDF::API2; + +use strict; +no warnings qw[ deprecated recursion uninitialized ]; + +our $VERSION = '2.033'; # VERSION + +use Carp; +use Encode qw(:all); +use FileHandle; + +use PDF::API2::Basic::PDF::Utils; +use PDF::API2::Util; + +use PDF::API2::Basic::PDF::File; +use PDF::API2::Basic::PDF::Pages; +use PDF::API2::Page; + +use PDF::API2::Resource::XObject::Form::Hybrid; + +use PDF::API2::Resource::ExtGState; +use PDF::API2::Resource::Pattern; +use PDF::API2::Resource::Shading; + +use PDF::API2::NamedDestination; + +use Scalar::Util qw(weaken); + +our @FontDirs = ( (map { "$_/PDF/API2/fonts" } @INC), + qw[ /usr/share/fonts /usr/local/share/fonts c:/windows/fonts c:/winnt/fonts ] ); + +#line 95 + +sub new { + my ($class, %options) = @_; + + my $self = {}; + bless $self, $class; + $self->{'pdf'} = PDF::API2::Basic::PDF::File->new(); + + $self->{'pdf'}->{' version'} = 4; + $self->{'pages'} = PDF::API2::Basic::PDF::Pages->new($self->{'pdf'}); + $self->{'pages'}->proc_set(qw(PDF Text ImageB ImageC ImageI)); + $self->{'pages'}->{'Resources'} ||= PDFDict(); + $self->{'pdf'}->new_obj($self->{'pages'}->{'Resources'}) unless $self->{'pages'}->{'Resources'}->is_obj($self->{'pdf'}); + $self->{'catalog'} = $self->{'pdf'}->{'Root'}; + weaken $self->{'catalog'}; + $self->{'fonts'} = {}; + $self->{'pagestack'} = []; + $self->{'forcecompress'} = 1; + $self->preferences(%options); + if ($options{'-file'}) { + $self->{' filed'} = $options{'-file'}; + $self->{'pdf'}->create_file($options{'-file'}); + } + $self->{'infoMeta'}=[qw(Author CreationDate ModDate Creator Producer Title Subject Keywords)]; + + my $version = eval { $PDF::API2::VERSION } || '(Unreleased Version)'; + $self->info('Producer' => "PDF::API2 $version [$^O]"); + + return $self; +} + +#line 141 + +sub open { + my ($class, $file, %options) = @_; + croak "File '$file' does not exist" unless -f $file; + croak "File '$file' is not readable" unless -r $file; + + my $content; + my $scalar_fh = FileHandle->new(); + CORE::open($scalar_fh, '+<', \$content) or die "Can't begin scalar IO"; + binmode $scalar_fh, ':raw'; + + my $disk_fh = FileHandle->new(); + CORE::open($disk_fh, '<', $file) or die "Can't open $file for reading: $!"; + binmode $disk_fh, ':raw'; + $disk_fh->seek(0, 0); + my $data; + while (not $disk_fh->eof()) { + $disk_fh->read($data, 512); + $scalar_fh->print($data); + } + $disk_fh->close(); + $scalar_fh->seek(0, 0); + + my $self = $class->open_scalar($content, %options); + $self->{'pdf'}->{' fname'} = $file; + + return $self; +} + +#line 186 + +# Deprecated (renamed) +sub openScalar { return open_scalar(@_); } ## no critic + +sub open_scalar { + my ($class, $content, %options) = @_; + + my $self = {}; + bless $self, $class; + foreach my $parameter (keys %options) { + $self->default($parameter, $options{$parameter}); + } + + $self->{'content_ref'} = \$content; + my $fh; + CORE::open($fh, '+<', \$content) or die "Can't begin scalar IO"; + + $self->{'pdf'} = PDF::API2::Basic::PDF::File->open($fh, 1); + $self->{'pdf'}->{'Root'}->realise(); + $self->{'pages'} = $self->{'pdf'}->{'Root'}->{'Pages'}->realise(); + weaken $self->{'pages'}; + $self->{'pdf'}->{' version'} ||= 3; + my @pages = proc_pages($self->{'pdf'}, $self->{'pages'}); + $self->{'pagestack'} = [sort { $a->{' pnum'} <=> $b->{' pnum'} } @pages]; + weaken $self->{'pagestack'}->[$_] for (0 .. scalar @{$self->{'pagestack'}}); + $self->{'catalog'} = $self->{'pdf'}->{'Root'}; + weaken $self->{'catalog'}; + $self->{'reopened'} = 1; + $self->{'forcecompress'} = 1; + $self->{'fonts'} = {}; + $self->{'infoMeta'} = [qw(Author CreationDate ModDate Creator Producer Title Subject Keywords)]; + + return $self; +} + +#line 407 + +sub preferences { + my ($self, %options) = @_; + + # Page Mode Options + if ($options{'-fullscreen'}) { + $self->{'catalog'}->{'PageMode'} = PDFName('FullScreen'); + } + elsif ($options{'-thumbs'}) { + $self->{'catalog'}->{'PageMode'} = PDFName('UseThumbs'); + } + elsif ($options{'-outlines'}) { + $self->{'catalog'}->{'PageMode'} = PDFName('UseOutlines'); + } + else { + $self->{'catalog'}->{'PageMode'} = PDFName('UseNone'); + } + + # Page Layout Options + if ($options{'-singlepage'}) { + $self->{'catalog'}->{'PageLayout'} = PDFName('SinglePage'); + } + elsif ($options{'-onecolumn'}) { + $self->{'catalog'}->{'PageLayout'} = PDFName('OneColumn'); + } + elsif ($options{'-twocolumnleft'}) { + $self->{'catalog'}->{'PageLayout'} = PDFName('TwoColumnLeft'); + } + elsif ($options{'-twocolumnright'}) { + $self->{'catalog'}->{'PageLayout'} = PDFName('TwoColumnRight'); + } + else { + $self->{'catalog'}->{'PageLayout'} = PDFName('SinglePage'); + } + + # Viewer Preferences + $self->{'catalog'}->{'ViewerPreferences'} ||= PDFDict(); + $self->{'catalog'}->{'ViewerPreferences'}->realise(); + + if ($options{'-hidetoolbar'}) { + $self->{'catalog'}->{'ViewerPreferences'}->{'HideToolbar'} = PDFBool(1); + } + if ($options{'-hidemenubar'}) { + $self->{'catalog'}->{'ViewerPreferences'}->{'HideMenubar'} = PDFBool(1); + } + if ($options{'-hidewindowui'}) { + $self->{'catalog'}->{'ViewerPreferences'}->{'HideWindowUI'} = PDFBool(1); + } + if ($options{'-fitwindow'}) { + $self->{'catalog'}->{'ViewerPreferences'}->{'FitWindow'} = PDFBool(1); + } + if ($options{'-centerwindow'}) { + $self->{'catalog'}->{'ViewerPreferences'}->{'CenterWindow'} = PDFBool(1); + } + if ($options{'-displaytitle'}) { + $self->{'catalog'}->{'ViewerPreferences'}->{'DisplayDocTitle'} = PDFBool(1); + } + if ($options{'-righttoleft'}) { + $self->{'catalog'}->{'ViewerPreferences'}->{'Direction'} = PDFName('R2L'); + } + + if ($options{'-afterfullscreenthumbs'}) { + $self->{'catalog'}->{'ViewerPreferences'}->{'NonFullScreenPageMode'} = PDFName('UseThumbs'); + } + elsif ($options{'-afterfullscreenoutlines'}) { + $self->{'catalog'}->{'ViewerPreferences'}->{'NonFullScreenPageMode'} = PDFName('UseOutlines'); + } + else { + $self->{'catalog'}->{'ViewerPreferences'}->{'NonFullScreenPageMode'} = PDFName('UseNone'); + } + + if ($options{'-printscalingnone'}) { + $self->{'catalog'}->{'ViewerPreferences'}->{'PrintScaling'} = PDFName('None'); + } + + if ($options{'-simplex'}) { + $self->{'catalog'}->{'ViewerPreferences'}->{'Duplex'} = PDFName('Simplex'); + } + elsif ($options{'-duplexfliplongedge'}) { + $self->{'catalog'}->{'ViewerPreferences'}->{'Duplex'} = PDFName('DuplexFlipLongEdge'); + } + elsif ($options{'-duplexflipshortedge'}) { + $self->{'catalog'}->{'ViewerPreferences'}->{'Duplex'} = PDFName('DuplexFlipShortEdge'); + } + + # Open Action + if ($options{'-firstpage'}) { + my ($page, %args) = @{$options{-firstpage}}; + $args{'-fit'} = 1 unless scalar keys %args; + + # $page can be either a page number (which needs to be wrapped + # in PDFNum) or a page object (which doesn't). + $page = PDFNum($page) unless ref($page); + + if (defined $args{'-fit'}) { + $self->{'catalog'}->{'OpenAction'} = PDFArray($page, PDFName('Fit')); + } + elsif (defined $args{'-fith'}) { + $self->{'catalog'}->{'OpenAction'} = PDFArray($page, PDFName('FitH'), PDFNum($args{'-fith'})); + } + elsif (defined $args{'-fitb'}) { + $self->{'catalog'}->{'OpenAction'} = PDFArray($page, PDFName('FitB')); + } + elsif (defined $args{'-fitbh'}) { + $self->{'catalog'}->{'OpenAction'} = PDFArray($page, PDFName('FitBH'), PDFNum($args{'-fitbh'})); + } + elsif (defined $args{'-fitv'}) { + $self->{'catalog'}->{'OpenAction'} = PDFArray($page, PDFName('FitV'), PDFNum($args{'-fitv'})); + } + elsif (defined $args{'-fitbv'}) { + $self->{'catalog'}->{'OpenAction'} = PDFArray($page, PDFName('FitBV'), PDFNum($args{'-fitbv'})); + } + elsif (defined $args{'-fitr'}) { + croak 'insufficient parameters to -fitr => []' unless scalar @{$args{'-fitr'}} == 4; + $self->{'catalog'}->{'OpenAction'} = PDFArray($page, PDFName('FitR'), map { PDFNum($_) } @{$args{'-fitr'}}); + } + elsif (defined $args{'-xyz'}) { + croak 'insufficient parameters to -xyz => []' unless scalar @{$args{'-xyz'}} == 3; + $self->{'catalog'}->{'OpenAction'} = PDFArray($page, PDFName('XYZ'), map { PDFNum($_) } @{$args{'-xyz'}}); + } + } + $self->{'pdf'}->out_obj($self->{'catalog'}); + + return $self; +} + +#line 560 + +sub default { + my ($self, $parameter, $value) = @_; + + # Parameter names may consist of lowercase letters, numbers, and underscores + $parameter = lc $parameter; + $parameter =~ s/[^a-z\d_]//g; + + my $previous_value = $self->{$parameter}; + if (defined $value) { + $self->{$parameter} = $value; + } + return $previous_value; +} + +#line 580 + +sub version { + my $self = shift(); + if (scalar @_) { + my $version = shift(); + croak "Invalid version $version" unless $version =~ /^(?:1\.)?([0-9]+)$/; + $self->{'pdf'}->{' version'} = $1; + } + return '1.' . $self->{'pdf'}->{' version'}; +} + +#line 596 + +sub isEncrypted { + my $self = shift(); + return defined($self->{'pdf'}->{'Encrypt'}) ? 1 : 0; +} + +#line 621 + +sub info { + my ($self, %opt) = @_; + + if (not defined($self->{'pdf'}->{'Info'})) { + $self->{'pdf'}->{'Info'} = PDFDict(); + $self->{'pdf'}->new_obj($self->{'pdf'}->{'Info'}); + } + else { + $self->{'pdf'}->{'Info'}->realise(); + } + + # Maintenance Note: Since we're not shifting at the beginning of + # this sub, this "if" will always be true + if (scalar @_) { + foreach my $k (@{$self->{'infoMeta'}}) { + next unless defined $opt{$k}; + if (is_utf8($opt{$k})) { + $self->{'pdf'}->{'Info'}->{$k} = PDFUtf($opt{$k} || 'NONE'); + } + #elsif (is_utf8($opt{$k}) || utf8::valid($opt{$k})) { + # $self->{'pdf'}->{'Info'}->{$k} = PDFUtf($opt{$k} || 'NONE'); + #} + else { + $self->{'pdf'}->{'Info'}->{$k} = PDFStr($opt{$k} || 'NONE'); + } + } + $self->{'pdf'}->out_obj($self->{'pdf'}->{'Info'}); + } + + if (defined $self->{'pdf'}->{'Info'}) { + %opt = (); + foreach my $k (@{$self->{'infoMeta'}}) { + next unless defined $self->{'pdf'}->{'Info'}->{$k}; + $opt{$k} = $self->{'pdf'}->{'Info'}->{$k}->val(); + if ((unpack('n', $opt{$k}) == 0xfffe) or (unpack('n', $opt{$k}) == 0xfeff)) { + $opt{$k} = decode('UTF-16', $self->{'pdf'}->{'Info'}->{$k}->val()); + } + } + } + + return %opt; +} + +#line 678 + +sub infoMetaAttributes { + my ($self, @attr) = @_; + + if (scalar @attr) { + my %at = map { $_ => 1 } @{$self->{'infoMeta'}}, @attr; + @{$self->{'infoMeta'}} = keys %at; + } + + return @{$self->{'infoMeta'}}; +} + +#line 751 + +sub xmpMetadata { + my ($self, $value) = @_; + + if (not defined($self->{'catalog'}->{'Metadata'})) { + $self->{'catalog'}->{'Metadata'} = PDFDict(); + $self->{'catalog'}->{'Metadata'}->{'Type'} = PDFName('Metadata'); + $self->{'catalog'}->{'Metadata'}->{'Subtype'} = PDFName('XML'); + $self->{'pdf'}->new_obj($self->{'catalog'}->{'Metadata'}); + } + else { + $self->{'catalog'}->{'Metadata'}->realise(); + $self->{'catalog'}->{'Metadata'}->{' stream'} = unfilter($self->{'catalog'}->{'Metadata'}->{'Filter'}, $self->{'catalog'}->{'Metadata'}->{' stream'}); + delete $self->{'catalog'}->{'Metadata'}->{' nofilt'}; + delete $self->{'catalog'}->{'Metadata'}->{'Filter'}; + } + + my $md = $self->{'catalog'}->{'Metadata'}; + + if (defined $value) { + $md->{' stream'} = $value; + delete $md->{'Filter'}; + delete $md->{' nofilt'}; + $self->{'pdf'}->out_obj($md); + $self->{'pdf'}->out_obj($self->{'catalog'}); + } + + return $md->{' stream'}; +} + +#line 835 + +sub pageLabel { + my $self = shift(); + + $self->{'catalog'}->{'PageLabels'} ||= PDFDict(); + $self->{'catalog'}->{'PageLabels'}->{'Nums'} ||= PDFArray(); + + my $nums = $self->{'catalog'}->{'PageLabels'}->{'Nums'}; + while (scalar @_) { + my $index = shift(); + my $opts = shift(); + + $nums->add_elements(PDFNum($index)); + + my $d = PDFDict(); + $d->{'S'} = PDFName($opts->{'-style'} eq 'Roman' ? 'R' : + $opts->{'-style'} eq 'roman' ? 'r' : + $opts->{'-style'} eq 'Alpha' ? 'A' : + $opts->{'-style'} eq 'alpha' ? 'a' : 'D'); + + if (defined $opts->{'-prefix'}) { + $d->{'P'} = PDFStr($opts->{'-prefix'}); + } + + if (defined $opts->{'-start'}) { + $d->{'St'} = PDFNum($opts->{'-start'}); + } + + $nums->add_elements($d); + } +} + +#line 880 + +sub finishobjects { + my ($self, @objs) = @_; + + if ($self->{'reopened'}) { + die "invalid method invocation: no file, use 'saveas' instead."; + } + elsif ($self->{' filed'}) { + $self->{'pdf'}->ship_out(@objs); + } + else { + die "invalid method invocation: no file, use 'saveas' instead."; + } +} + +sub proc_pages { + my ($pdf, $object) = @_; + + if (defined $object->{'Resources'}) { + eval { + $object->{'Resources'}->realise(); + }; + } + + my @pages; + $pdf->{' apipagecount'} ||= 0; + foreach my $page ($object->{'Kids'}->elementsof()) { + $page->realise(); + if ($page->{'Type'}->val() eq 'Pages') { + push @pages, proc_pages($pdf, $page); + } + else { + $pdf->{' apipagecount'}++; + $page->{' pnum'} = $pdf->{' apipagecount'}; + if (defined $page->{'Resources'}) { + eval { + $page->{'Resources'}->realise(); + }; + } + push @pages, $page; + } + } + + return @pages; +} + +#line 937 + +sub update { + my $self = shift(); + $self->saveas($self->{'pdf'}->{' fname'}); +} + +#line 954 + +sub saveas { + my ($self, $file) = @_; + + if ($self->{'reopened'}) { + $self->{'pdf'}->append_file(); + my $fh; + CORE::open($fh, '>', $file) or die "Unable to open $file for writing: $!"; + binmode($fh, ':raw'); + print $fh ${$self->{'content_ref'}}; + CORE::close($fh); + } + elsif ($self->{' filed'}) { + $self->{'pdf'}->close_file(); + } + else { + $self->{'pdf'}->out_file($file); + } + + $self->end(); +} + +sub save { + my ($self, $file) = @_; + + if ($self->{'reopened'}) { + die "invalid method invocation: use 'saveas' instead."; + } + elsif ($self->{' filed'}) { + $self->{'pdf'}->close_file(); + } + else { + die "invalid method invocation: use 'saveas' instead."; + } + + $self->end(); +} + +#line 1003 + +# Maintainer's note: The object is being destroyed because it contains +# circular references that would otherwise result in memory not being +# freed if the object merely goes out of scope. If possible, the +# circular references should be eliminated so that stringify doesn't +# need to be destructive. +# +# I've opted not to just require a separate call to release() because +# it would likely introduce memory leaks in many existing programs +# that use this module. + +sub stringify { + my $self = shift(); + + my $str; + if ((defined $self->{'reopened'}) and ($self->{'reopened'} == 1)) { + $self->{'pdf'}->append_file(); + $str = ${$self->{'content_ref'}}; + } + else { + my $fh = FileHandle->new(); + CORE::open($fh, '>', \$str) || die "Can't begin scalar IO"; + $self->{'pdf'}->out_file($fh); + $fh->close(); + } + $self->end(); + + return $str; +} + +sub release { + my $self = shift(); + $self->end(); + return; +} + +#line 1050 + +sub end { + my $self = shift(); + $self->{'pdf'}->release() if defined $self->{'pdf'}; + + foreach my $key (keys %$self) { + $self->{$key} = undef; + delete $self->{$key}; + } + + return; +} + +#line 1091 + +sub page { + my $self = shift(); + my $index = shift() || 0; + my $page; + if ($index == 0) { + $page = PDF::API2::Page->new($self->{'pdf'}, $self->{'pages'}); + } + else { + $page = PDF::API2::Page->new($self->{'pdf'}, $self->{'pages'}, $index - 1); + } + $page->{' apipdf'} = $self->{'pdf'}; + $page->{' api'} = $self; + weaken $page->{' apipdf'}; + weaken $page->{' api'}; + $self->{'pdf'}->out_obj($page); + $self->{'pdf'}->out_obj($self->{'pages'}); + if ($index == 0) { + push @{$self->{'pagestack'}}, $page; + weaken $self->{'pagestack'}->[-1]; + } + elsif ($index < 0) { + splice @{$self->{'pagestack'}}, $index, 0, $page; + weaken $self->{'pagestack'}->[$index]; + } + else { + splice @{$self->{'pagestack'}}, $index - 1, 0, $page; + weaken $self->{'pagestack'}->[$index - 1]; + } + # $page->{'Resources'} = $self->{'pages'}->{'Resources'}; + return $page; +} + +#line 1140 + +sub openpage { + my $self = shift(); + my $index = shift() || 0; + my ($page, $rotate, $media, $trans); + + if ($index == 0) { + $page = $self->{'pagestack'}->[-1]; + } + elsif ($index < 0) { + $page = $self->{'pagestack'}->[$index]; + } + else { + $page = $self->{'pagestack'}->[$index - 1]; + } + return unless ref($page); + + if (ref($page) ne 'PDF::API2::Page') { + bless $page, 'PDF::API2::Page'; + $page->{' apipdf'} = $self->{'pdf'}; + $page->{' api'} = $self; + weaken $page->{' apipdf'}; + weaken $page->{' api'}; + $self->{'pdf'}->out_obj($page); + if (($rotate = $page->find_prop('Rotate')) and (not defined($page->{' fixed'}) or $page->{' fixed'} < 1)) { + $rotate = ($rotate->val() + 360) % 360; + + if ($rotate != 0 and not $self->default('nounrotate')) { + $page->{'Rotate'} = PDFNum(0); + foreach my $mediatype (qw(MediaBox CropBox BleedBox TrimBox ArtBox)) { + if ($media = $page->find_prop($mediatype)) { + $media = [ map { $_->val() } $media->elementsof() ]; + } + else { + $media = [0, 0, 612, 792]; + next if $mediatype ne 'MediaBox'; + } + if ($rotate == 90) { + $trans = "0 -1 1 0 0 $media->[2] cm" if $mediatype eq 'MediaBox'; + $media = [$media->[1], $media->[0], $media->[3], $media->[2]]; + } + elsif ($rotate == 180) { + $trans = "-1 0 0 -1 $media->[2] $media->[3] cm" if $mediatype eq 'MediaBox'; + } + elsif ($rotate == 270) { + $trans = "0 1 -1 0 $media->[3] 0 cm" if $mediatype eq 'MediaBox'; + $media = [$media->[1], $media->[0], $media->[3], $media->[2]]; + } + $page->{$mediatype} = PDFArray(map { PDFNum($_) } @$media); + } + } + else { + $trans = ''; + } + } + else { + $trans = ''; + } + + if (defined $page->{'Contents'} and (not defined($page->{' fixed'}) or $page->{' fixed'} < 1)) { + $page->fixcontents(); + my $uncontent = delete $page->{'Contents'}; + my $content = $page->gfx(); + $content->add(" $trans "); + + if ($self->default('pageencaps')) { + $content->{' stream'} .= ' q '; + } + foreach my $k ($uncontent->elementsof()) { + $k->realise(); + $content->{' stream'} .= ' ' . unfilter($k->{'Filter'}, $k->{' stream'}) . ' '; + } + if ($self->default('pageencaps')) { + $content->{' stream'} .= ' Q '; + } + + ## $content->{'Length'} = PDFNum(length($content->{' stream'})); + # this will be fixed by the following code or content or filters + + ## if we like compress we will do it now to do quicker saves + if ($self->{'forcecompress'} > 0) { + # $content->compressFlate(); + $content->{' stream'} = dofilter($content->{'Filter'}, $content->{' stream'}); + $content->{' nofilt'} = 1; + delete $content->{'-docompress'}; + $content->{'Length'} = PDFNum(length($content->{' stream'})); + } + } + $page->{' fixed'} = 1; + } + + $self->{'pdf'}->out_obj($page); + $self->{'pdf'}->out_obj($self->{'pages'}); + $page->{' apipdf'} = $self->{'pdf'}; + $page->{' api'} = $self; + weaken $page->{' apipdf'}; + weaken $page->{' api'}; + $page->{' reopened'} = 1; + return $page; +} + + +sub walk_obj { + my ($object_cache, $source_pdf, $target_pdf, $source_object, @keys) = @_; + + if (ref($source_object) =~ /Objind$/) { + $source_object->realise(); + } + + return $object_cache->{scalar $source_object} if defined $object_cache->{scalar $source_object}; + # die "infinite loop while copying objects" if $source_object->{' copied'}; + + my $target_object = $source_object->copy($source_pdf); ## thanks to: yaheath // Fri, 17 Sep 2004 + + # $source_object->{' copied'} = 1; + $target_pdf->new_obj($target_object) if $source_object->is_obj($source_pdf); + + $object_cache->{scalar $source_object} = $target_object; + + if (ref($source_object) =~ /Array$/) { + $target_object->{' val'} = []; + foreach my $k ($source_object->elementsof()) { + $k->realise() if ref($k) =~ /Objind$/; + $target_object->add_elements(walk_obj($object_cache, $source_pdf, $target_pdf, $k)); + } + } + elsif (ref($source_object) =~ /Dict$/) { + @keys = keys(%$target_object) unless scalar @keys; + foreach my $k (@keys) { + next if $k =~ /^ /; + next unless defined $source_object->{$k}; + $target_object->{$k} = walk_obj($object_cache, $source_pdf, $target_pdf, $source_object->{$k}); + } + if ($source_object->{' stream'}) { + if ($target_object->{'Filter'}) { + $target_object->{' nofilt'} = 1; + } + else { + delete $target_object->{' nofilt'}; + $target_object->{'Filter'} = PDFArray(PDFName('FlateDecode')); + } + $target_object->{' stream'} = $source_object->{' stream'}; + } + } + delete $target_object->{' streamloc'}; + delete $target_object->{' streamsrc'}; + + return $target_object; +} + +#line 1318 + +sub importPageIntoForm { + my ($self, $s_pdf, $s_idx) = @_; + $s_idx ||= 0; + + unless (ref($s_pdf) and $s_pdf->isa('PDF::API2')) { + die "Invalid usage: first argument must be PDF::API2 instance, not: " . ref($s_pdf); + } + + my ($s_page, $xo); + + $xo = $self->xo_form(); + + if (ref($s_idx) eq 'PDF::API2::Page') { + $s_page = $s_idx; + } + else { + $s_page = $s_pdf->openpage($s_idx); + } + + $self->{'apiimportcache'} ||= {}; + $self->{'apiimportcache'}->{$s_pdf} ||= {}; + + # This should never get past MediaBox, since it's a required object. + foreach my $k (qw(MediaBox ArtBox TrimBox BleedBox CropBox)) { + # next unless defined $s_page->{$k}; + # my $box = walk_obj($self->{'apiimportcache'}->{$s_pdf}, $s_pdf->{'pdf'}, $self->{'pdf'}, $s_page->{$k}); + next unless defined $s_page->find_prop($k); + my $box = walk_obj($self->{'apiimportcache'}->{$s_pdf}, $s_pdf->{'pdf'}, $self->{'pdf'}, $s_page->find_prop($k)); + $xo->bbox(map { $_->val() } $box->elementsof()); + last; + } + $xo->bbox(0, 0, 612, 792) unless defined $xo->{'BBox'}; + + foreach my $k (qw(Resources)) { + $s_page->{$k} = $s_page->find_prop($k); + next unless defined $s_page->{$k}; + $s_page->{$k}->realise() if ref($s_page->{$k}) =~ /Objind$/; + + foreach my $sk (qw(XObject ExtGState Font ProcSet Properties ColorSpace Pattern Shading)) { + next unless defined $s_page->{$k}->{$sk}; + $s_page->{$k}->{$sk}->realise() if ref($s_page->{$k}->{$sk}) =~ /Objind$/; + foreach my $ssk (keys %{$s_page->{$k}->{$sk}}) { + next if $ssk =~ /^ /; + $xo->resource($sk, $ssk, walk_obj($self->{'apiimportcache'}->{$s_pdf}, $s_pdf->{'pdf'}, $self->{'pdf'}, $s_page->{$k}->{$sk}->{$ssk})); + } + } + } + + # create a whole content stream + ## technically it is possible to submit an unfinished + ## (eg. newly created) source-page, but thats nonsense, + ## so we expect a page fixed by openpage and die otherwise + die "page not processed via openpage ..." unless $s_page->{' fixed'} == 1; + + # since the source page comes from openpage it may already + # contain the required starting 'q' without the final 'Q' + # if forcecompress is in effect + if (defined $s_page->{'Contents'}) { + $s_page->fixcontents(); + + $xo->{' stream'} = ''; + # openpage pages only contain one stream + my ($k) = $s_page->{'Contents'}->elementsof(); + $k->realise(); + if ($k->{' nofilt'}) { + # we have a finished stream here + # so we unfilter + $xo->add('q', unfilter($k->{'Filter'}, $k->{' stream'}), 'Q'); + } + else { + # stream is an unfinished/unfiltered content + # so we just copy it and add the required "qQ" + $xo->add('q', $k->{' stream'}, 'Q'); + } + $xo->compressFlate() if $self->{'forcecompress'} > 0; + } + + return $xo; +} + +#line 1424 + +# Deprecated (renamed) +sub importpage { return import_page(@_); } ## no critic + +sub import_page { + my ($self, $s_pdf, $s_idx, $t_idx) = @_; + $s_idx ||= 0; + $t_idx ||= 0; + my ($s_page, $t_page); + + unless (ref($s_pdf) and $s_pdf->isa('PDF::API2')) { + die "Invalid usage: first argument must be PDF::API2 instance, not: " . ref($s_pdf); + } + + if (ref($s_idx) eq 'PDF::API2::Page') { + $s_page = $s_idx; + } + else { + $s_page = $s_pdf->openpage($s_idx); + } + + if (ref($t_idx) eq 'PDF::API2::Page') { + $t_page = $t_idx; + } + else { + if ($self->pages() < $t_idx) { + $t_page = $self->page(); + } + else { + $t_page = $self->page($t_idx); + } + } + + $self->{'apiimportcache'} = $self->{'apiimportcache'} || {}; + $self->{'apiimportcache'}->{$s_pdf} = $self->{'apiimportcache'}->{$s_pdf} || {}; + + # we now import into a form to keep + # all that nasty resources from polluting + # our very own resource naming space. + my $xo = $self->importPageIntoForm($s_pdf, $s_page); + + # copy all page dimensions + foreach my $k (qw(MediaBox ArtBox TrimBox BleedBox CropBox)) { + my $prop = $s_page->find_prop($k); + next unless defined $prop; + + my $box = walk_obj({}, $s_pdf->{'pdf'}, $self->{'pdf'}, $prop); + my $method = lc $k; + + $t_page->$method(map { $_->val() } $box->elementsof()); + } + + $t_page->gfx->formimage($xo, 0, 0, 1); + + # copy annotations and/or form elements as well + if (exists $s_page->{'Annots'} and $s_page->{'Annots'} and $self->{'copyannots'}) { + # first set up the AcroForm, if required + my $AcroForm; + if (my $a = $s_pdf->{'pdf'}->{'Root'}->realise->{'AcroForm'}) { + $a->realise(); + + $AcroForm = walk_obj({}, $s_pdf->{'pdf'}, $self->{'pdf'}, $a, qw(NeedAppearances SigFlags CO DR DA Q)); + } + my @Fields = (); + my @Annots = (); + foreach my $a ($s_page->{'Annots'}->elementsof()) { + $a->realise(); + my $t_a = PDFDict(); + $self->{'pdf'}->new_obj($t_a); + # these objects are likely to be both annotations and Acroform fields + # key names are copied from PDF Reference 1.4 (Tables) + my @k = ( + qw( Type Subtype Contents P Rect NM M F BS Border AP AS C CA T Popup A AA StructParent Rotate + ), # Annotations - Common (8.10) + qw( Subtype Contents Open Name ), # Text Annotations (8.15) + qw( Subtype Contents Dest H PA ), # Link Annotations (8.16) + qw( Subtype Contents DA Q ), # Free Text Annotations (8.17) + qw( Subtype Contents L BS LE IC ) , # Line Annotations (8.18) + qw( Subtype Contents BS IC ), # Square and Circle Annotations (8.20) + qw( Subtype Contents QuadPoints ), # Markup Annotations (8.21) + qw( Subtype Contents Name ), # Rubber Stamp Annotations (8.22) + qw( Subtype Contents InkList BS ), # Ink Annotations (8.23) + qw( Subtype Contents Parent Open ), # Popup Annotations (8.24) + qw( Subtype FS Contents Name ), # File Attachment Annotations (8.25) + qw( Subtype Sound Contents Name ), # Sound Annotations (8.26) + qw( Subtype Movie Contents A ), # Movie Annotations (8.27) + qw( Subtype Contents H MK ), # Widget Annotations (8.28) + # Printers Mark Annotations (none) + # Trap Network Annotations (none) + ); + + push @k, ( + qw( Subtype FT Parent Kids T TU TM Ff V DV AA + ), # Fields - Common (8.49) + qw( DR DA Q ), # Fields containing variable text (8.51) + qw( Opt ), # Checkbox field (8.54) + qw( Opt ), # Radio field (8.55) + qw( MaxLen ), # Text field (8.57) + qw( Opt TI I ), # Choice field (8.59) + ) if $AcroForm; + + # sorting out dups + my %ky = map { $_ => 1 } @k; + # we do P separately, as it points to the page the Annotation is on + delete $ky{'P'}; + # copy everything else + foreach my $k (keys %ky) { + next unless defined $a->{$k}; + $a->{$k}->realise(); + $t_a->{$k} = walk_obj({}, $s_pdf->{'pdf'}, $self->{'pdf'}, $a->{$k}); + } + $t_a->{'P'} = $t_page; + push @Annots, $t_a; + push @Fields, $t_a if ($AcroForm and $t_a->{'Subtype'}->val() eq 'Widget'); + } + $t_page->{'Annots'} = PDFArray(@Annots); + $AcroForm->{'Fields'} = PDFArray(@Fields) if $AcroForm; + $self->{'pdf'}->{'Root'}->{'AcroForm'} = $AcroForm; + } + $t_page->{' imported'} = 1; + + $self->{'pdf'}->out_obj($t_page); + $self->{'pdf'}->out_obj($self->{'pages'}); + + return $t_page; +} + +#line 1556 + +sub pages { + my $self = shift(); + return scalar @{$self->{'pagestack'}}; +} + +#line 1588 + +sub mediabox { + my ($self, $x1, $y1, $x2, $y2) = @_; + $self->{'pages'}->{'MediaBox'} = PDFArray(map { PDFNum(float($_)) } page_size($x1, $y1, $x2, $y2)); + return $self; +} + +#line 1604 + +sub cropbox { + my ($self, $x1, $y1, $x2, $y2) = @_; + $self->{'pages'}->{'CropBox'} = PDFArray(map { PDFNum(float($_)) } page_size($x1, $y1, $x2, $y2)); + return $self; +} + +#line 1620 + +sub bleedbox { + my ($self, $x1, $y1, $x2, $y2) = @_; + $self->{'pages'}->{'BleedBox'} = PDFArray(map { PDFNum(float($_)) } page_size($x1, $y1, $x2, $y2)); + return $self; +} + +#line 1636 + +sub trimbox { + my ($self, $x1, $y1, $x2, $y2) = @_; + $self->{'pages'}->{'TrimBox'} = PDFArray(map { PDFNum(float($_)) } page_size($x1, $y1, $x2, $y2)); + return $self; +} + +#line 1652 + +sub artbox { + my ($self, $x1, $y1, $x2, $y2) = @_; + $self->{'pages'}->{'ArtBox'} = PDFArray(map { PDFNum(float($_)) } page_size($x1, $y1, $x2, $y2)); + return $self; +} + +#line 1673 + +sub addFontDirs { + my @dirs = @_; + push @FontDirs, @dirs; + return @FontDirs; +} + +sub _findFont { + my $font = shift(); + my @fonts = ($font, map { "$_/$font" } @FontDirs); + shift @fonts while scalar(@fonts) and not -f $fonts[0]; + return $fonts[0]; +} + +#line 1715 + +sub corefont { + my ($self, $name, %opts) = @_; + require PDF::API2::Resource::Font::CoreFont; + my $obj = PDF::API2::Resource::Font::CoreFont->new($self->{'pdf'}, $name, %opts); + $self->{'pdf'}->out_obj($self->{'pages'}); + $obj->tounicodemap() if $opts{-unicodemap} == 1; + return $obj; +} + +#line 1758 + +sub psfont { + my ($self, $psf, %opts) = @_; + + foreach my $o (qw(-afmfile -pfmfile)) { + next unless defined $opts{$o}; + $opts{$o} = _findFont($opts{$o}); + } + $psf = _findFont($psf); + require PDF::API2::Resource::Font::Postscript; + my $obj = PDF::API2::Resource::Font::Postscript->new($self->{'pdf'}, $psf, %opts); + + $self->{'pdf'}->out_obj($self->{'pages'}); + $obj->tounicodemap() if $opts{-unicodemap} == 1; + + return $obj; +} + +#line 1808 + +sub ttfont { + my ($self, $file, %opts) = @_; + + # PDF::API2 doesn't set BaseEncoding for TrueType fonts, so text + # isn't searchable unless a ToUnicode CMap is included. Include + # the ToUnicode CMap by default, but allow it to be disabled (for + # performance and file size reasons) by setting -unicodemap to 0. + $opts{-unicodemap} = 1 unless exists $opts{-unicodemap}; + + $file = _findFont($file); + require PDF::API2::Resource::CIDFont::TrueType; + my $obj = PDF::API2::Resource::CIDFont::TrueType->new($self->{'pdf'}, $file, %opts); + + $self->{'pdf'}->out_obj($self->{'pages'}); + $obj->tounicodemap() if $opts{-unicodemap}; + + return $obj; +} + +#line 1850 + +sub cjkfont { + my ($self, $name, %opts) = @_; + + require PDF::API2::Resource::CIDFont::CJKFont; + my $obj = PDF::API2::Resource::CIDFont::CJKFont->new($self->{'pdf'}, $name, %opts); + + $self->{'pdf'}->out_obj($self->{'pages'}); + $obj->tounicodemap() if $opts{-unicodemap} == 1; + + return $obj; +} + +#line 1899 + +sub synfont { + my ($self, $font, %opts) = @_; + + # PDF::API2 doesn't set BaseEncoding for TrueType fonts, so text + # isn't searchable unless a ToUnicode CMap is included. Include + # the ToUnicode CMap by default, but allow it to be disabled (for + # performance and file size reasons) by setting -unicodemap to 0. + $opts{-unicodemap} = 1 unless exists $opts{-unicodemap}; + + require PDF::API2::Resource::Font::SynFont; + my $obj = PDF::API2::Resource::Font::SynFont->new($self->{'pdf'}, $font, %opts); + + $self->{'pdf'}->out_obj($self->{'pages'}); + $obj->tounicodemap() if $opts{-unicodemap}; + + return $obj; +} + +#line 1925 + +sub bdfont { + my ($self, @opts) = @_; + + require PDF::API2::Resource::Font::BdFont; + my $obj = PDF::API2::Resource::Font::BdFont->new($self->{'pdf'}, @opts); + + $self->{'pdf'}->out_obj($self->{'pages'}); + # $obj->tounicodemap(); # does not support Unicode + + return $obj; +} + +#line 1957 + +sub unifont { + my ($self, @opts) = @_; + + require PDF::API2::Resource::UniFont; + my $obj = PDF::API2::Resource::UniFont->new($self->{'pdf'}, @opts); + + return $obj; +} + +#line 1978 + +sub image_jpeg { + my ($self, $file, %opts) = @_; + + require PDF::API2::Resource::XObject::Image::JPEG; + my $obj = PDF::API2::Resource::XObject::Image::JPEG->new($self->{'pdf'}, $file); + + $self->{'pdf'}->out_obj($self->{'pages'}); + + return $obj; +} + +#line 1995 + +sub image_tiff { + my ($self, $file, %opts) = @_; + + require PDF::API2::Resource::XObject::Image::TIFF; + my $obj = PDF::API2::Resource::XObject::Image::TIFF->new($self->{'pdf'}, $file); + + $self->{'pdf'}->out_obj($self->{'pages'}); + + return $obj; +} + +#line 2012 + +sub image_pnm { + my ($self, $file, %opts) = @_; + + require PDF::API2::Resource::XObject::Image::PNM; + my $obj = PDF::API2::Resource::XObject::Image::PNM->new($self->{'pdf'}, $file); + + $self->{'pdf'}->out_obj($self->{'pages'}); + + return $obj; +} + +#line 2029 + +sub image_png { + my ($self, $file, %opts) = @_; + + require PDF::API2::Resource::XObject::Image::PNG; + my $obj = PDF::API2::Resource::XObject::Image::PNG->new($self->{'pdf'}, $file); + + $self->{'pdf'}->out_obj($self->{'pages'}); + + return $obj; +} + +#line 2046 + +sub image_gif { + my ($self, $file, %opts) = @_; + + require PDF::API2::Resource::XObject::Image::GIF; + my $obj = PDF::API2::Resource::XObject::Image::GIF->new($self->{'pdf'}, $file); + + $self->{'pdf'}->out_obj($self->{'pages'}); + + return $obj; +} + +#line 2065 + +sub image_gd { + my ($self, $gd, %opts) = @_; + + require PDF::API2::Resource::XObject::Image::GD; + my $obj = PDF::API2::Resource::XObject::Image::GD->new($self->{'pdf'}, $gd, undef, %opts); + + $self->{'pdf'}->out_obj($self->{'pages'}); + + return $obj; +} + +#line 2091 + +sub colorspace_act { + my ($self, $file, %opts) = @_; + + require PDF::API2::Resource::ColorSpace::Indexed::ACTFile; + my $obj = PDF::API2::Resource::ColorSpace::Indexed::ACTFile->new($self->{'pdf'}, $file); + + $self->{'pdf'}->out_obj($self->{'pages'}); + + return $obj; +} + +#line 2108 + +sub colorspace_web { + my ($self, $file, %opts) = @_; + + require PDF::API2::Resource::ColorSpace::Indexed::WebColor; + my $obj = PDF::API2::Resource::ColorSpace::Indexed::WebColor->new($self->{'pdf'}); + + $self->{'pdf'}->out_obj($self->{'pages'}); + + return $obj; +} + +#line 2127 + +sub colorspace_hue { + my ($self, $file, %opts)=@_; + + require PDF::API2::Resource::ColorSpace::Indexed::Hue; + my $obj = PDF::API2::Resource::ColorSpace::Indexed::Hue->new($self->{'pdf'}); + + $self->{'pdf'}->out_obj($self->{'pages'}); + + return $obj; +} + +#line 2154 + +sub colorspace_separation { + my ($self, $name, @clr)=@_; + + require PDF::API2::Resource::ColorSpace::Separation; + my $obj = PDF::API2::Resource::ColorSpace::Separation->new($self->{'pdf'}, pdfkey(), $name, @clr); + + $self->{'pdf'}->out_obj($self->{'pages'}); + + return $obj; +} + +#line 2185 + +sub colorspace_devicen { + my ($self, $clrs, $samples) = @_; + $samples ||= 2; + + require PDF::API2::Resource::ColorSpace::DeviceN; + my $obj = PDF::API2::Resource::ColorSpace::DeviceN->new($self->{'pdf'}, pdfkey(), $clrs, $samples); + + $self->{'pdf'}->out_obj($self->{'pages'}); + + return $obj; +} + +#line 2217 + +sub xo_code128 { + my ($self, @opts) = @_; + + require PDF::API2::Resource::XObject::Form::BarCode::code128; + my $obj = PDF::API2::Resource::XObject::Form::BarCode::code128->new($self->{'pdf'}, @opts); + + $self->{'pdf'}->out_obj($self->{'pages'}); + + return $obj; +} + +sub xo_codabar { + my ($self, @opts) = @_; + + require PDF::API2::Resource::XObject::Form::BarCode::codabar; + my $obj = PDF::API2::Resource::XObject::Form::BarCode::codabar->new($self->{'pdf'}, @opts); + + $self->{'pdf'}->out_obj($self->{'pages'}); + + return $obj; +} + +sub xo_2of5int { + my ($self, @opts) = @_; + + require PDF::API2::Resource::XObject::Form::BarCode::int2of5; + my $obj = PDF::API2::Resource::XObject::Form::BarCode::int2of5->new($self->{'pdf'}, @opts); + + $self->{'pdf'}->out_obj($self->{'pages'}); + + return $obj; +} + +sub xo_3of9 { + my ($self, @opts) = @_; + + require PDF::API2::Resource::XObject::Form::BarCode::code3of9; + my $obj = PDF::API2::Resource::XObject::Form::BarCode::code3of9->new($self->{'pdf'}, @opts); + + $self->{'pdf'}->out_obj($self->{'pages'}); + + return $obj; +} + +sub xo_ean13 { + my ($self, @opts) = @_; + + require PDF::API2::Resource::XObject::Form::BarCode::ean13; + my $obj = PDF::API2::Resource::XObject::Form::BarCode::ean13->new($self->{'pdf'}, @opts); + + $self->{'pdf'}->out_obj($self->{'pages'}); + + return $obj; +} + +#line 2284 + +sub xo_form { + my $self = shift(); + + my $obj = PDF::API2::Resource::XObject::Form::Hybrid->new($self->{'pdf'}); + + $self->{'pdf'}->out_obj($self->{'pages'}); + + return $obj; +} + +#line 2300 + +sub egstate { + my $self = shift(); + + my $obj = PDF::API2::Resource::ExtGState->new($self->{'pdf'}, pdfkey()); + + $self->{'pdf'}->out_obj($self->{'pages'}); + + return $obj; +} + +#line 2316 + +sub pattern { + my ($self, %opts) = @_; + + my $obj = PDF::API2::Resource::Pattern->new($self->{'pdf'}, undef, %opts); + + $self->{'pdf'}->out_obj($self->{'pages'}); + + return $obj; +} + +#line 2332 + +sub shading { + my ($self, %opts) = @_; + + my $obj = PDF::API2::Resource::Shading->new($self->{'pdf'}, undef, %opts); + + $self->{'pdf'}->out_obj($self->{'pages'}); + + return $obj; +} + +#line 2348 + +sub outlines { + my $self = shift(); + + require PDF::API2::Outlines; + $self->{'pdf'}->{'Root'}->{'Outlines'} ||= PDF::API2::Outlines->new($self); + + my $obj = $self->{'pdf'}->{'Root'}->{'Outlines'}; + + $self->{'pdf'}->new_obj($obj) unless $obj->is_obj($self->{'pdf'}); + $self->{'pdf'}->out_obj($obj); + $self->{'pdf'}->out_obj($self->{'pdf'}->{'Root'}); + + return $obj; +} + +sub named_destination { + my ($self, $cat, $name, $obj) = @_; + my $root = $self->{'catalog'}; + + $root->{'Names'} ||= PDFDict(); + $root->{'Names'}->{$cat} ||= PDFDict(); + $root->{'Names'}->{$cat}->{'-vals'} ||= {}; + $root->{'Names'}->{$cat}->{'Limits'} ||= PDFArray(); + $root->{'Names'}->{$cat}->{'Names'} ||= PDFArray(); + + unless (defined $obj) { + $obj = PDF::API2::NamedDestination->new($self->{'pdf'}); + } + $root->{'Names'}->{$cat}->{'-vals'}->{$name} = $obj; + + my @names = sort {$a cmp $b} keys %{$root->{'Names'}->{$cat}->{'-vals'}}; + + $root->{'Names'}->{$cat}->{'Limits'}->{' val'}->[0] = PDFStr($names[0]); + $root->{'Names'}->{$cat}->{'Limits'}->{' val'}->[1] = PDFStr($names[-1]); + + @{$root->{'Names'}->{$cat}->{'Names'}->{' val'}} = (); + + foreach my $k (@names) { + push @{$root->{'Names'}->{$cat}->{'Names'}->{' val'}}, ( + PDFStr($k), + $root->{'Names'}->{$cat}->{'-vals'}->{$k} + ); + } + + return $obj; +} + +1; + +__END__ + +#line 2413 diff --git a/lib/PDF/API2/Annotation.pm b/lib/PDF/API2/Annotation.pm new file mode 100644 index 0000000..890e470 --- /dev/null +++ b/lib/PDF/API2/Annotation.pm @@ -0,0 +1,278 @@ +#line 1 "PDF/API2/Annotation.pm" +#line 1 "PDF/API2/Annotation.pm" +package PDF::API2::Annotation; + +use base 'PDF::API2::Basic::PDF::Dict'; + +use strict; +no warnings qw[ deprecated recursion uninitialized ]; + +our $VERSION = '2.033'; # VERSION + +use Encode qw(:all); + +use PDF::API2::Basic::PDF::Utils; +use PDF::API2::Util; + +#line 28 + +sub new +{ + my ($class,%opts)=@_; + my $self=$class->SUPER::new; + $self->{Type}=PDFName('Annot'); + $self->{Border}=PDFArray(PDFNum(0),PDFNum(0),PDFNum(0)); + return($self); +} + +sub outobjdeep +{ + my ($self, @opts) = @_; + foreach my $k (qw[ api apipdf apipage ]) + { + $self->{" $k"}=undef; + delete($self->{" $k"}); + } + $self->SUPER::outobjdeep(@opts); +} + +#line 55 + +sub link +{ + my ($self,$page,%opts)=@_; + $self->{Subtype}=PDFName('Link'); + if(ref $page) + { + $self->{A}=PDFDict(); + $self->{A}->{S}=PDFName('GoTo'); + } + $self->dest($page,%opts); + $self->rect(@{$opts{-rect}}) if(defined $opts{-rect}); + $self->border(@{$opts{-border}}) if(defined $opts{-border}); + return($self); +} + +#line 77 + +sub url +{ + my ($self,$url,%opts)=@_; + $self->{Subtype}=PDFName('Link'); + $self->{A}=PDFDict(); + $self->{A}->{S}=PDFName('URI'); + if(is_utf8($url)) + { + # URI must be 7-bit ascii + utf8::downgrade($url); + } + $self->{A}->{URI}=PDFStr($url); + # this will come again -- since the utf8 urls are coming ! + # -- fredo + #if(is_utf8($url) || utf8::valid($url)) { + # $self->{A}->{URI}=PDFUtf($url); + #} else { + # $self->{A}->{URI}=PDFStr($url); + #} + $self->rect(@{$opts{-rect}}) if(defined $opts{-rect}); + $self->border(@{$opts{-border}}) if(defined $opts{-border}); + return($self); +} + +#line 108 + +sub file +{ + my ($self,$url,%opts)=@_; + $self->{Subtype}=PDFName('Link'); + $self->{A}=PDFDict(); + $self->{A}->{S}=PDFName('Launch'); + if(is_utf8($url)) + { + # URI must be 7-bit ascii + utf8::downgrade($url); + } + $self->{A}->{F}=PDFStr($url); + # this will come again -- since the utf8 urls are coming ! + # -- fredo + #if(is_utf8($url) || utf8::valid($url)) { + # $self->{A}->{F}=PDFUtf($url); + #} else { + # $self->{A}->{F}=PDFStr($url); + #} + $self->rect(@{$opts{-rect}}) if(defined $opts{-rect}); + $self->border(@{$opts{-border}}) if(defined $opts{-border}); + return($self); +} + +#line 139 + +sub pdfile +{ + my ($self,$url,$pnum,%opts)=@_; + $self->{Subtype}=PDFName('Link'); + $self->{A}=PDFDict(); + $self->{A}->{S}=PDFName('GoToR'); + if(is_utf8($url)) + { + # URI must be 7-bit ascii + utf8::downgrade($url); + } + $self->{A}->{F}=PDFStr($url); + # this will come again -- since the utf8 urls are coming ! + # -- fredo + #if(is_utf8($url) || utf8::valid($url)) { + # $self->{A}->{F}=PDFUtf($url); + #} else { + # $self->{A}->{F}=PDFStr($url); + #} + + $self->dest(PDFNum($pnum),%opts); + + $self->rect(@{$opts{-rect}}) if(defined $opts{-rect}); + $self->border(@{$opts{-border}}) if(defined $opts{-border}); + + return($self); +} + +#line 174 + +sub text +{ + my ($self,$text,%opts)=@_; + $self->{Subtype}=PDFName('Text'); + $self->content($text); + $self->rect(@{$opts{-rect}}) if(defined $opts{-rect}); + $self->open($opts{-open}) if(defined $opts{-open}); + return($self); +} + +#line 191 + +sub movie +{ + my ($self,$file,$contentype,%opts)=@_; + $self->{Subtype}=PDFName('Movie'); + $self->{A}=PDFBool(1); + $self->{Movie}=PDFDict(); + $self->{Movie}->{F}=PDFDict(); + $self->{' apipdf'}->new_obj($self->{Movie}->{F}); + my $f=$self->{Movie}->{F}; + $f->{Type}=PDFName('EmbeddedFile'); + $f->{Subtype}=PDFName($contentype); + $f->{' streamfile'}=$file; + $self->rect(@{$opts{-rect}}) if(defined $opts{-rect}); + return($self); +} + +#line 213 + +sub rect +{ + my ($self,@r)=@_; + die "insufficient parameters to annotation->rect( ) " unless(scalar @r == 4); + $self->{Rect}=PDFArray( map { PDFNum($_) } $r[0],$r[1],$r[2],$r[3], ); + return($self); +} + +#line 227 + +sub border +{ + my ($self,@r)=@_; + die "insufficient parameters to annotation->border( ) " unless(scalar @r == 3); + $self->{Border}=PDFArray( map { PDFNum($_) } $r[0],$r[1],$r[2] ); + return($self); +} + +#line 241 + +sub content +{ + my ($self,@t)=@_; + my $t=join("\n",@t); + if(is_utf8($t) || utf8::valid($t)) + { + $self->{Contents}=PDFUtf($t); + } + else + { + $self->{Contents}=PDFStr($t); + } + return($self); +} + +sub name +{ + my ($self,$n)=@_; + $self->{Name}=PDFName($n); + return($self); +} + +#line 269 + +sub open +{ + my ($self,$n)=@_; + $self->{Open}=PDFBool( $n ? 1 : 0 ); + return($self); +} + +#line 337 + +sub dest +{ + my ($self,$page,%opts)=@_; + + if(ref $page) + { + $opts{-xyz}=[undef,undef,undef] if(scalar(keys %opts)<1); + + $self->{A}||=PDFDict(); + + if(defined $opts{-fit}) + { + $self->{A}->{D}=PDFArray($page,PDFName('Fit')); + } + elsif(defined $opts{-fith}) + { + $self->{A}->{D}=PDFArray($page,PDFName('FitH'),PDFNum($opts{-fith})); + } + elsif(defined $opts{-fitb}) + { + $self->{A}->{D}=PDFArray($page,PDFName('FitB')); + } + elsif(defined $opts{-fitbh}) + { + $self->{A}->{D}=PDFArray($page,PDFName('FitBH'),PDFNum($opts{-fitbh})); + } + elsif(defined $opts{-fitv}) + { + $self->{A}->{D}=PDFArray($page,PDFName('FitV'),PDFNum($opts{-fitv})); + } + elsif(defined $opts{-fitbv}) + { + $self->{A}->{D}=PDFArray($page,PDFName('FitBV'),PDFNum($opts{-fitbv})); + } + elsif(defined $opts{-fitr}) + { + die "insufficient parameters to ->dest( page, -fitr => [] ) " unless(scalar @{$opts{-fitr}} == 4); + $self->{A}->{D}=PDFArray($page,PDFName('FitR'),map {PDFNum($_)} @{$opts{-fitr}}); + } + elsif(defined $opts{-xyz}) + { + die "insufficient parameters to ->dest( page, -xyz => [] ) " unless(scalar @{$opts{-xyz}} == 3); + $self->{A}->{D}=PDFArray($page,PDFName('XYZ'),map {defined $_ ? PDFNum($_) : PDFNull()} @{$opts{-xyz}}); + } + } + else + { + $self->{Dest}=PDFStr($page); + } + + return($self); +} + +#line 394 + +1; diff --git a/lib/PDF/API2/Basic/PDF/Array.pm b/lib/PDF/API2/Basic/PDF/Array.pm new file mode 100644 index 0000000..bcdb3e4 --- /dev/null +++ b/lib/PDF/API2/Basic/PDF/Array.pm @@ -0,0 +1,102 @@ +#line 1 "PDF/API2/Basic/PDF/Array.pm" +#line 1 "PDF/API2/Basic/PDF/Array.pm" +#======================================================================= +# +# THIS IS A REUSED PERL MODULE, FOR PROPER LICENCING TERMS SEE BELOW: +# +# Copyright Martin Hosken <Martin_Hosken@sil.org> +# +# No warranty or expression of effectiveness, least of all regarding +# anyone's safety, is implied in this software or documentation. +# +# This specific module is licensed under the Perl Artistic License. +# +#======================================================================= +package PDF::API2::Basic::PDF::Array; + +use base 'PDF::API2::Basic::PDF::Objind'; + +use strict; + +our $VERSION = '2.033'; # VERSION + +#line 33 + +sub new { + my ($class, @vals) = @_; + my $self = {}; + + $self->{' val'} = [@vals]; + $self->{' realised'} = 1; + bless $self, $class; + return $self; +} + +#line 49 + +sub outobjdeep { + my ($self, $fh, $pdf, %opts) = @_; + + $fh->print('[ '); + foreach my $obj (@{$self->{' val'}}) { + $obj->outobj($fh, $pdf); + $fh->print(' '); + } + $fh->print(']'); +} + +#line 66 + +sub removeobj { + my ($self, $elem) = @_; + + $self->{' val'} = [grep($_ ne $elem, @{$self->{' val'}})]; +} + +#line 81 + +sub elementsof { + return wantarray ? @{$_[0]->{' val'}} : scalar @{$_[0]->{' val'}}; +} + +sub elements { + my $self = shift(); + return @{$self->{' val'}}; +} + +#line 97 + +sub add_elements { + my $self = shift(); + + foreach my $e (@_) { + push @{$self->{' val'}}, $e if defined $e; + } + return $self; +} + +#line 113 + +sub val { + return $_[0]->{' val'}; +} + +#line 124 + +sub copy { + my ($self, $pdf) = @_; + my $res = $self->SUPER::copy($pdf); + + $res->{' val'} = []; + foreach my $e (@{$self->{' val'}}) { + if (ref($e) and $e->can('is_obj') and not $e->is_obj($pdf)) { + push(@{$res->{' val'}}, $e->copy($pdf)); + } + else { + push(@{$res->{' val'}}, $e); + } + } + return $res; +} + +1; diff --git a/lib/PDF/API2/Basic/PDF/Bool.pm b/lib/PDF/API2/Basic/PDF/Bool.pm new file mode 100644 index 0000000..9fa231a --- /dev/null +++ b/lib/PDF/API2/Basic/PDF/Bool.pm @@ -0,0 +1,35 @@ +#line 1 "PDF/API2/Basic/PDF/Bool.pm" +#line 1 "PDF/API2/Basic/PDF/Bool.pm" +#======================================================================= +# +# THIS IS A REUSED PERL MODULE, FOR PROPER LICENCING TERMS SEE BELOW: +# +# Copyright Martin Hosken <Martin_Hosken@sil.org> +# +# No warranty or expression of effectiveness, least of all regarding +# anyone's safety, is implied in this software or documentation. +# +# This specific module is licensed under the Perl Artistic License. +# +#======================================================================= +package PDF::API2::Basic::PDF::Bool; + +use base 'PDF::API2::Basic::PDF::String'; + +use strict; + +our $VERSION = '2.033'; # VERSION + +#line 33 + +sub convert { + return $_[1] eq 'true'; +} + +#line 43 + +sub as_pdf { + return $_[0]->{'val'} ? 'true' : 'false'; +} + +1; diff --git a/lib/PDF/API2/Basic/PDF/Dict.pm b/lib/PDF/API2/Basic/PDF/Dict.pm new file mode 100644 index 0000000..a9bb020 --- /dev/null +++ b/lib/PDF/API2/Basic/PDF/Dict.pm @@ -0,0 +1,273 @@ +#line 1 "PDF/API2/Basic/PDF/Dict.pm" +#line 1 "PDF/API2/Basic/PDF/Dict.pm" +#======================================================================= +# +# THIS IS A REUSED PERL MODULE, FOR PROPER LICENCING TERMS SEE BELOW: +# +# Copyright Martin Hosken <Martin_Hosken@sil.org> +# +# No warranty or expression of effectiveness, least of all regarding +# anyone's safety, is implied in this software or documentation. +# +# This specific module is licensed under the Perl Artistic License. +# +#======================================================================= +package PDF::API2::Basic::PDF::Dict; + +use base 'PDF::API2::Basic::PDF::Objind'; + +use strict; +no warnings qw[ deprecated recursion uninitialized ]; + +our $VERSION = '2.033'; # VERSION + +our $mincache = 16 * 1024 * 1024; + +use File::Temp; +use PDF::API2::Basic::PDF::Array; +use PDF::API2::Basic::PDF::Filter; +use PDF::API2::Basic::PDF::Name; + +#line 59 + +sub new { + my ($class) = @_; + $class = ref($class) if ref($class); + + my $self = $class->SUPER::new(@_); + $self->{' realised'} = 1; + return $self; +} + +#line 74 + +sub type { + my $self = shift(); + if (scalar @_) { + my $type = shift(); + $self->{'Type'} = ref($type) ? $type : PDF::API2::Basic::PDF::Name->new($type); + } + return unless exists $self->{'Type'}; + return $self->{'Type'}->val(); +} + +#line 90 + +sub filter { + my ($self, @filters) = @_; + + # Developer's Note: the PDF specification allows Filter to be + # either a name or an array, but other parts of this codebase + # expect an array. If these are updated uncomment the + # commented-out lines in order to accept both types. + + # if (scalar @filters == 1) { + # $self->{'Filter'} = ref($filters[0]) ? $filters[0] : PDF::API2::Basic::PDF::Name->new($filters[0]); + # } + # elsif (scalar @filters) { + @filters = map { ref($_) ? $_ : PDF::API2::Basic::PDF::Name->new($_) } @filters; + $self->{'Filter'} = PDF::API2::Basic::PDF::Array->new(@filters); + # } +} + +# Undocumented alias, which may be removed in a future release +sub filters { return filter(@_); } + +#line 120 + +sub outobjdeep { + my ($self, $fh, $pdf, %opts) = @_; + + if (defined $self->{' stream'} or defined $self->{' streamfile'} or defined $self->{' streamloc'}) { + if ($self->{'Filter'} and $self->{' nofilt'}) { + $self->{'Length'} ||= PDF::API2::Basic::PDF::Number->new(length($self->{' stream'})); + } + elsif ($self->{'Filter'} or not defined $self->{' stream'}) { + $self->{'Length'} = PDF::API2::Basic::PDF::Number->new(0) unless defined $self->{'Length'}; + $pdf->new_obj($self->{'Length'}) unless $self->{'Length'}->is_obj($pdf); + } + else { + $self->{'Length'} = PDF::API2::Basic::PDF::Number->new(length($self->{' stream'})); + ## $self->{'Length'} = PDF::API2::Basic::PDF::Number->new(length($self->{' stream'}) + 1); + ## this old code seams to burp acro6, lets see what breaks next -- fredo + } + } + + $fh->print('<< '); + foreach my $key (sort { + $a eq 'Type' ? -1 : $b eq 'Type' ? 1 : + $a eq 'Subtype' ? -1 : $b eq 'Subtype' ? 1 : $a cmp $b + } keys %$self) { + next if $key =~ m/^[\s\-]/o; + next unless $self->{$key}; + $fh->print('/' . PDF::API2::Basic::PDF::Name::string_to_name($key, $pdf) . ' '); + $self->{$key}->outobj($fh, $pdf, %opts); + $fh->print(' '); + } + $fh->print('>>'); + + # Now handle the stream (if any) + my (@filters, $loc); + + if (defined $self->{' streamloc'} and not defined $self->{' stream'}) { + # read a stream if in file + $loc = $fh->tell(); + $self->read_stream(); + $fh->seek($loc, 0); + } + + if (not $self->{' nofilt'} and defined $self->{'Filter'} and (defined $self->{' stream'} or defined $self->{' streamfile'})) { + my $hasflate = -1; + for my $i (0 .. scalar(@{$self->{'Filter'}{' val'}}) - 1) { + my $filter = $self->{'Filter'}{' val'}[$i]->val(); + # hack to get around LZW patent + if ($filter eq 'LZWDecode') { + if ($hasflate < -1) { + $hasflate = $i; + next; + } + $filter = 'FlateDecode'; + $self->{'Filter'}{' val'}[$i]{'val'} = $filter; # !!! + } + elsif ($filter eq 'FlateDecode') { + $hasflate = -2; + } + my $filter_class = "PDF::API2::Basic::PDF::Filter::$filter"; + push (@filters, $filter_class->new()); + } + splice(@{$self->{'Filter'}{' val'}}, $hasflate, 1) if $hasflate > -1; + } + + if (defined $self->{' stream'}) { + $fh->print(" stream\n"); + $loc = $fh->tell(); + my $stream = $self->{' stream'}; + unless ($self->{' nofilt'}) { + foreach my $filter (reverse @filters) { + $stream = $filter->outfilt($stream, 1); + } + } + $fh->print($stream); + ## $fh->print("\n"); # newline goes into endstream + + } + elsif (defined $self->{' streamfile'}) { + open(my $dictfh, "<", $self->{' streamfile'}) || die "Unable to open $self->{' streamfile'}"; + binmode($dictfh, ':raw'); + + $fh->print(" stream\n"); + $loc = $fh->tell(); + my $stream; + while (read($dictfh, $stream, 4096)) { + unless ($self->{' nofilt'}) { + foreach my $filter (reverse @filters) { + $stream = $filter->outfilt($stream, 0); + } + } + $fh->print($stream); + } + close $dictfh; + unless ($self->{' nofilt'}) { + $stream = ''; + foreach my $filter (reverse @filters) { + $stream = $filter->outfilt($stream, 1); + } + $fh->print($stream); + } + ## $fh->print("\n"); # newline goes into endstream + } + + if (defined $self->{' stream'} or defined $self->{' streamfile'}) { + my $length = $fh->tell() - $loc; + unless ($self->{'Length'}{'val'} == $length) { + $self->{'Length'}{'val'} = $length; + $pdf->out_obj($self->{'Length'}) if $self->{'Length'}->is_obj($pdf); + } + + $fh->print("\nendstream"); # next is endobj which has the final cr + } +} + +#line 244 + +sub read_stream { + my ($self, $force_memory) = @_; + + my $fh = $self->{' streamsrc'}; + my $len = $self->{'Length'}->val(); + + $self->{' stream'} = ''; + + my @filters; + if (defined $self->{'Filter'}) { + my $i = 0; + foreach my $filter ($self->{'Filter'}->elementsof()) { + my $filter_class = "PDF::API2::Basic::PDF::Filter::" . $filter->val(); + unless ($self->{'DecodeParms'}) { + push(@filters, $filter_class->new()); + } + elsif ($self->{'Filter'}->isa('PDF::API2::Basic::PDF::Name') and $self->{'DecodeParms'}->isa('PDF::API2::Basic::PDF::Dict')) { + push(@filters, $filter_class->new($self->{'DecodeParms'})); + } + elsif ($self->{'DecodeParms'}->isa('PDF::API2::Basic::PDF::Array')) { + my $parms = $self->{'DecodeParms'}->val->[$i]; + push(@filters, $filter_class->new($parms)); + } + else { + push(@filters, $filter_class->new()); + } + $i++; + } + } + + my $last = 0; + if (defined $self->{' streamfile'}) { + unlink ($self->{' streamfile'}); + $self->{' streamfile'} = undef; + } + seek $fh, $self->{' streamloc'}, 0; + + my $dictfh; + my $readlen = 4096; + for (my $i = 0; $i < $len; $i += $readlen) { + my $data; + unless ($i + $readlen > $len) { + read $fh, $data, $readlen; + } + else { + $last = 1; + read $fh, $data, $len - $i; + } + + foreach my $filter (@filters) { + $data = $filter->infilt($data, $last); + } + + # Start using a temporary file if the stream gets too big + if (not $force_memory and not defined $self->{' streamfile'} and (length($self->{' stream'}) + length($data)) > $mincache) { + $dictfh = File::Temp->new(TEMPLATE => 'pdfXXXXX', SUFFIX => 'dat', TMPDIR => 1); + $self->{' streamfile'} = $dictfh->filename(); + print $dictfh $self->{' stream'}; + undef $self->{' stream'}; + } + + if (defined $self->{' streamfile'}) { + print $dictfh $data; + } + else { + $self->{' stream'} .= $data; + } + } + + close $dictfh if defined $self->{' streamfile'}; + $self->{' nofilt'} = 0; + return $self; +} + +#line 324 + +sub val { + return $_[0]; +} + +1; diff --git a/lib/PDF/API2/Basic/PDF/File.pm b/lib/PDF/API2/Basic/PDF/File.pm new file mode 100644 index 0000000..695fcc2 --- /dev/null +++ b/lib/PDF/API2/Basic/PDF/File.pm @@ -0,0 +1,1099 @@ +#line 1 "PDF/API2/Basic/PDF/File.pm" +#line 1 "PDF/API2/Basic/PDF/File.pm" +#======================================================================= +# +# THIS IS A REUSED PERL MODULE, FOR PROPER LICENCING TERMS SEE BELOW: +# +# Copyright Martin Hosken <Martin_Hosken@sil.org> +# +# Modified for PDF::API2 by Alfred Reibenschuh <alfredreibenschuh@gmx.net> +# +# No warranty or expression of effectiveness, least of all regarding +# anyone's safety, is implied in this software or documentation. +# +# This specific module is licensed under the Perl Artistic License. +# +#======================================================================= +package PDF::API2::Basic::PDF::File; + +use strict; + +our $VERSION = '2.033'; # VERSION + +#line 142 + +use Scalar::Util qw(blessed weaken); + +use vars qw($cr $irreg_char $reg_char $ws_char $delim_char %types); + +$ws_char = '[ \t\r\n\f\0]'; +$delim_char = '[][<>{}()/%]'; +$reg_char = '[^][<>{}()/% \t\r\n\f\0]'; +$irreg_char = '[][<>{}()/% \t\r\n\f\0]'; +$cr = '\s*(?:\015|\012|(?:\015\012))'; + +my $re_comment = qr/(?:\%[^\r\n]*)/; +my $re_whitespace = qr/(?:[ \t\r\n\f\0]|$re_comment)/; + +%types = ( + 'Page' => 'PDF::API2::Basic::PDF::Page', + 'Pages' => 'PDF::API2::Basic::PDF::Pages', +); + +my $readDebug = 0; + +use Carp; +use IO::File; + +# Now for the basic PDF types +use PDF::API2::Basic::PDF::Utils; + +use PDF::API2::Basic::PDF::Array; +use PDF::API2::Basic::PDF::Bool; +use PDF::API2::Basic::PDF::Dict; +use PDF::API2::Basic::PDF::Name; +use PDF::API2::Basic::PDF::Number; +use PDF::API2::Basic::PDF::Objind; +use PDF::API2::Basic::PDF::String; +use PDF::API2::Basic::PDF::Page; +use PDF::API2::Basic::PDF::Pages; +use PDF::API2::Basic::PDF::Null; +use POSIX qw(ceil floor); + +no warnings qw[ deprecated recursion uninitialized ]; + + +#line 191 + +sub new { + my ($class, $root) = @_; + my $self = $class->_new(); + + unless ($root) { + $root = PDFDict(); + $root->{'Type'} = PDFName('Catalog'); + } + $self->new_obj($root); + $self->{'Root'} = $root; + return $self; +} + + +#line 217 + +sub open { + my ($class, $filename, $update) = @_; + my ($fh, $buffer); + + my $self = $class->_new(); + if (ref $filename) { + $self->{' INFILE'} = $filename; + if ($update) { + $self->{' update'} = 1; + $self->{' OUTFILE'} = $filename; + } + $fh = $filename; + } + else { + die "File '$filename' does not exist !" unless -f $filename; + $fh = IO::File->new(($update ? '+' : '') . "<$filename") || return; + $self->{' INFILE'} = $fh; + if ($update) { + $self->{' update'} = 1; + $self->{' OUTFILE'} = $fh; + $self->{' fname'} = $filename; + } + } + binmode $fh, ':raw'; + $fh->seek(0, 0); # go to start of file + $fh->read($buffer, 255); + unless ($buffer =~ m/^\%PDF\-1\.(\d)+\s*$cr/mo) { + die "$filename not a PDF file version 1.x"; + } + $self->{' version'} = $1; + + $fh->seek(0, 2); # go to end of file + my $end = $fh->tell(); + $self->{' epos'} = $end; + foreach my $offset (1..64) { + $fh->seek($end - 16 * $offset, 0); + $fh->read($buffer, 16 * $offset); + last if $buffer =~ m/startxref($cr|\s*)\d+($cr|\s*)\%\%eof.*?/i; + } + unless ($buffer =~ m/startxref[^\d]+([0-9]+)($cr|\s*)\%\%eof.*?/i) { + die "Malformed PDF file $filename"; + } + my $xpos = $1; + $self->{' xref_position'} = $xpos; + + my $tdict = $self->readxrtr($xpos, $self); + foreach my $key (keys %$tdict) { + $self->{$key} = $tdict->{$key}; + } + return $self; +} + +#line 288 + +# Maintainer's Question: Couldn't this be handled by a DESTROY method +# instead of requiring an explicit call to release()? +sub release { + my $self = shift(); + + return $self unless ref($self); + my @tofree = values %$self; + + foreach my $key (keys %$self) { + $self->{$key} = undef; + delete $self->{$key}; + } + + while (my $item = shift @tofree) { + if (blessed($item) and $item->can('release')) { + $item->release(1); + } + elsif (ref($item) eq 'ARRAY') { + push @tofree, @$item; + } + elsif (ref($item) eq 'HASH') { + push @tofree, values %$item; + foreach my $key (keys %$item) { + $item->{$key} = undef; + delete $item->{$key}; + } + } + else { + $item = undef; + } + } +} + +#line 327 + +sub append_file { + my $self = shift(); + return unless $self->{' update'}; + + my $fh = $self->{' INFILE'}; + + # hack to upgrade pdf-version number to support + # requested features in higher versions than + # the pdf was originally created. + my $version = $self->{' version'} || 4; + $fh->seek(0, 0); + $fh->print("%PDF-1.$version\n"); + + my $tdict = PDFDict(); + $tdict->{'Prev'} = PDFNum($self->{' loc'}); + $tdict->{'Info'} = $self->{'Info'}; + if (defined $self->{' newroot'}) { + $tdict->{'Root'} = $self->{' newroot'}; + } + else { + $tdict->{'Root'} = $self->{'Root'}; + } + $tdict->{'Size'} = $self->{'Size'}; + + foreach my $key (grep { $_ !~ m/^\s/ } keys %$self) { + $tdict->{$key} = $self->{$key} unless defined $tdict->{$key}; + } + + $fh->seek($self->{' epos'}, 0); + $self->out_trailer($tdict, $self->{' update'}); + close $self->{' OUTFILE'}; +} + + +#line 371 + +sub out_file { + my ($self, $fname) = @_; + + $self->create_file($fname); + $self->close_file(); + return $self; +} + + +#line 388 + +sub create_file { + my ($self, $filename) = @_; + my $fh; + + $self->{' fname'} = $filename; + if (ref $filename) { + $fh = $filename; + } + else { + $fh = IO::File->new(">$filename") || die "Unable to open $filename for writing"; + binmode($fh,':raw'); + } + + $self->{' OUTFILE'} = $fh; + $fh->print('%PDF-1.' . ($self->{' version'} || '2') . "\n"); + $fh->print("%\xC6\xCD\xCD\xB5\n"); # and some binary stuff in a comment + return $self; +} + + +#line 414 + +sub close_file { + my $self = shift(); + + my $tdict = PDFDict(); + $tdict->{'Info'} = $self->{'Info'} if defined $self->{'Info'}; + $tdict->{'Root'} = (defined $self->{' newroot'} and $self->{' newroot'} ne '') ? $self->{' newroot'} : $self->{'Root'}; + + # remove all freed objects from the outlist, AND the outlist_cache if not updating + # NO! Don't do that thing! In fact, let out_trailer do the opposite! + + $tdict->{'Size'} = $self->{'Size'} || PDFNum(1); + $tdict->{'Prev'} = PDFNum($self->{' loc'}) if $self->{' loc'}; + if ($self->{' update'}) { + foreach my $key (grep ($_ !~ m/^[\s\-]/, keys %$self)) { + $tdict->{$key} = $self->{$key} unless defined $tdict->{$key}; + } + + my $fh = $self->{' INFILE'}; + $fh->seek($self->{' epos'}, 0); + } + + $self->out_trailer($tdict, $self->{' update'}); + close($self->{' OUTFILE'}); + if ($^O eq 'MacOS' and not ref($self->{' fname'})) { + MacPerl::SetFileInfo('CARO', 'TEXT', $self->{' fname'}); + } + + return $self; +} + +#line 455 + +sub readval { + my ($self, $str, %opts) = @_; + my $fh = $self->{' INFILE'}; + my ($result, $value); + + my $update = defined($opts{update}) ? $opts{update} : 1; + $str = update($fh, $str) if $update; + + $str =~ s/^$ws_char+//; # Ignore initial white space + $str =~ s/^\%[^\015\012]*$ws_char+//; # Ignore comments + + # Dictionary + if ($str =~ m/^<</s) { + $str = substr ($str, 2); + $str = update($fh, $str) if $update; + $result = PDFDict(); + + while ($str !~ m/^>>/) { + $str =~ s/^$ws_char+//; # Ignore initial white space + $str =~ s/^\%[^\015\012]*$ws_char+//; # Ignore comments + + if ($str =~ s|^/($reg_char+)||) { + my $key = PDF::API2::Basic::PDF::Name::name_to_string($1, $self); + ($value, $str) = $self->readval($str, %opts); + $result->{$key} = $value; + } + elsif ($str =~ s|^/$ws_char+||) { + # fixes a broken key problem of acrobat. -- fredo + ($value, $str) = $self->readval($str, %opts); + $result->{'null'} = $value; + } + elsif ($str =~ s|^//|/|) { + # fixes again a broken key problem of illustrator/enfocus. -- fredo + ($value, $str) = $self->readval($str, %opts); + $result->{'null'} = $value; + } + else { + die "Invalid dictionary key"; + } + $str = update($fh, $str) if $update; # thanks gareth.jones@stud.man.ac.uk + } + $str =~ s/^>>//; + $str = update($fh, $str) if $update; + # streams can't be followed by a lone carriage-return. + # fredo: yes they can !!! -- use the MacOS Luke. + if (($str =~ s/^stream(?:(?:\015\012)|\012|\015)//) and ($result->{'Length'}->val != 0)) { # stream + my $length = $result->{'Length'}->val; + $result->{' streamsrc'} = $fh; + $result->{' streamloc'} = $fh->tell - length($str); + + unless ($opts{'nostreams'}) { + if ($length > length($str)) { + $value = $str; + $length -= length($str); + read $fh, $str, $length + 11; # slurp the whole stream! + } + else { + $value = ''; + } + $value .= substr($str, 0, $length); + $result->{' stream'} = $value; + $result->{' nofilt'} = 1; + $str = update($fh, $str, 1) if $update; # tell update we are in-stream and only need an endstream + $str = substr($str, index($str, 'endstream') + 9); + } + } + + if (defined $result->{'Type'} and defined $types{$result->{'Type'}->val}) { + bless $result, $types{$result->{'Type'}->val}; + } + # gdj: FIXME: if any of the ws chars were crs, then the whole + # string might not have been read. + } + + # Indirect Object + elsif ($str =~ m/^([0-9]+)(?:$ws_char|$re_comment)+([0-9]+)(?:$ws_char|$re_comment)+R/s) { + my $num = $1; + $value = $2; + $str =~ s/^([0-9]+)(?:$ws_char|$re_comment)+([0-9]+)(?:$ws_char|$re_comment)+R//s; + unless ($result = $self->test_obj($num, $value)) { + $result = PDF::API2::Basic::PDF::Objind->new(); + $result->{' objnum'} = $num; + $result->{' objgen'} = $value; + $self->add_obj($result, $num, $value); + } + $result->{' parent'} = $self; + weaken $result->{' parent'}; + $result->{' realised'} = 0; + # gdj: FIXME: if any of the ws chars were crs, then the whole + # string might not have been read. + } + + # Object + elsif ($str =~ m/^([0-9]+)(?:$ws_char|$re_comment)+([0-9]+)(?:$ws_char|$re_comment)+obj/s) { + my $obj; + my $num = $1; + $value = $2; + $str =~ s/^([0-9]+)(?:$ws_char|$re_comment)+([0-9]+)(?:$ws_char|$re_comment)+obj//s; + ($obj, $str) = $self->readval($str, %opts); + if ($result = $self->test_obj($num, $value)) { + $result->merge($obj); + } + else { + $result = $obj; + $self->add_obj($result, $num, $value); + $result->{' realised'} = 1; + } + $str = update($fh, $str) if $update; # thanks to kundrat@kundrat.sk + $str =~ s/^endobj//; + } + + # Name + elsif ($str =~ m|^/($reg_char*)|s) { + $value = $1; + $str =~ s|^/($reg_char*)||s; + $result = PDF::API2::Basic::PDF::Name->from_pdf($value, $self); + } + + # Literal String + elsif ($str =~ m/^\(/) { + # We now need to find an unbalanced, unescaped right-paren. + # This can't be done with a regex. + my $value = '('; + $str = substr($str, 1); + + my $nested_level = 1; + while (1) { + # Ignore everything up to the first escaped or parenthesis character + if ($str =~ /^([^\\()]+)(.*)/s) { + $value .= $1; + $str = $2; + } + + # Ignore escaped parentheses + if ($str =~ /^(\\[()])/) { + $value .= $1; + $str = substr($str, 2); + } + + # Left parenthesis: increase nesting + elsif ($str =~ /^\(/) { + $value .= '('; + $str = substr($str, 1); + $nested_level++; + } + + # Right parenthesis: decrease nesting + elsif ($str =~ /^\)/) { + $value .= ')'; + $str = substr($str, 1); + $nested_level--; + last unless $nested_level; + } + + # Other escaped character + elsif ($str =~ /^(\\[^()])/) { + $value .= $1; + $str = substr($str, 2); + } + + # If there wasn't an escaped or parenthesis character, + # read some more. + else { + # We don't use update because we don't want to remove + # whitespace or comments. + $fh->read($str, 255, length($str)) or die 'Unterminated string.'; + } + } + + $result = PDF::API2::Basic::PDF::String->from_pdf($value); + } + + # Hex String + elsif ($str =~ m/^</) { + $str =~ s/^<//; + $fh->read($str, 255, length($str)) while (0 > index($str, '>')); + ($value, $str) = ($str =~ /^(.*?)>(.*)/s); + $result = PDF::API2::Basic::PDF::String->from_pdf('<' . $value . '>'); + } + + # Array + elsif ($str =~ m/^\[/) { + $str =~ s/^\[//; + $str = update($fh, $str) if $update; + $result = PDFArray(); + while ($str !~ m/^\]/) { + $str =~ s/^$ws_char+//; # Ignore initial white space + $str =~ s/^\%[^\015\012]*$ws_char+//; # Ignore comments + + ($value, $str) = $self->readval($str, %opts); + $result->add_elements($value); + $str = update($fh, $str) if $update; # str might just be exhausted! + } + $str =~ s/^\]//; + } + + # Boolean + elsif ($str =~ m/^(true|false)($irreg_char|$)/) { + $value = $1; + $str =~ s/^(?:true|false)//; + $result = PDF::API2::Basic::PDF::Bool->from_pdf($value); + } + + # Number + elsif ($str =~ m/^([+-.0-9]+)($irreg_char|$)/) { + $value = $1; + $str =~ s/^([+-.0-9]+)//; + + # If $str only consists of whitespace (or is empty), call update to + # see if this is the beginning of an indirect object or reference + if ($update and ($str =~ /^$re_whitespace*$/s or $str =~ /^$re_whitespace+[0-9]+$re_whitespace*$/s)) { + $str =~ s/^$re_whitespace+/ /s; + $str =~ s/$re_whitespace+$/ /s; + $str = update($fh, $str); + if ($str =~ m/^$re_whitespace*([0-9]+)$re_whitespace+(?:R|obj)/s) { + return $self->readval("$value $str", %opts); + } + } + + $result = PDF::API2::Basic::PDF::Number->from_pdf($value); + } + + # Null + elsif ($str =~ m/^null($irreg_char|$)/) { + $str =~ s/^null//; + $result = PDF::API2::Basic::PDF::Null->new; + } + + else { + die "Can't parse `$str' near " . ($fh->tell()) . " length " . length($str) . "."; + } + + $str =~ s/^$ws_char+//s; + return ($result, $str); +} + + +#line 699 + +sub read_obj { + my ($self, $objind, %opts) = @_; + + my $res = $self->read_objnum($objind->{' objnum'}, $objind->{' objgen'}, %opts) || return; + $objind->merge($res) unless $objind eq $res; + return $objind; +} + + +#line 714 + +sub read_objnum { + my ($self, $num, $gen, %opts) = @_; + croak 'Undefined object number in call to read_objnum($num, $gen)' unless defined $num; + croak 'Undefined object generation in call to read_objnum($num, $gen)' unless defined $gen; + croak "Invalid object number '$num' in call to read_objnum" unless $num =~ /^[0-9]+$/; + croak "Invalid object generation '$gen' in call to read_objnum" unless $gen =~ /^[0-9]+$/; + + my $object_location = $self->locate_obj($num, $gen) || return; + my $object; + + # Compressed object + if (ref($object_location)) { + my ($object_stream_num, $object_stream_pos) = @{$object_location}; + + my $object_stream = $self->read_objnum($object_stream_num, 0, %opts); + die 'Cannot find the compressed object stream' unless $object_stream; + + $object_stream->read_stream() if $object_stream->{' nofilt'}; + + # An object stream starts with pairs of integers containing object numbers and + # stream offsets relative to the First key + my $fh; + my $pairs; + unless ($object_stream->{' streamfile'}) { + $pairs = substr($object_stream->{' stream'}, 0, $object_stream->{'First'}->val); + } + else { + CORE::open($fh, '<', $object_stream->{' streamfile'}); + read($fh, $pairs, $object_stream->{'First'}->val()); + } + my @map = split /\s+/, $pairs; + + # Find the offset of the object in the stream + my $index = $object_stream_pos * 2; + die "Objind $num does not exist at index $index" unless $map[$index] == $num; + my $start = $map[$index + 1]; + + # Unless this is the last object in the stream, its length is determined by the + # offset of the next object + my $last_object_in_stream = $map[-2]; + my $length; + if ($last_object_in_stream == $num) { + if ($object_stream->{' stream'}) { + $length = length($object_stream->{' stream'}) - $object_stream->{'First'}->val() - $start; + } + else { + $length = (-s $object_stream->{' streamfile'}) - $object_stream->{'First'}->val() - $start; + } + } + else { + my $next_start = $map[$index + 3]; + $length = $next_start - $start; + } + + # Read the object from the stream + my $stream = "$num 0 obj "; + unless ($object_stream->{' streamfile'}) { + $stream .= substr($object_stream->{' stream'}, $object_stream->{'First'}->val() + $start, $length); + } + else { + seek($fh, $object_stream->{'First'}->val() + $start, 0); + read($fh, $stream, $length, length($stream)); + close $fh; + } + + ($object) = $self->readval($stream, %opts, update => 0); + return $object; + } + + my $current_location = $self->{' INFILE'}->tell; + $self->{' INFILE'}->seek($object_location, 0); + ($object) = $self->readval('', %opts); + $self->{' INFILE'}->seek($current_location, 0); + return $object; +} + + +#line 799 + +sub new_obj { + my ($self, $base) = @_; + my $res; + + if (defined $self->{' free'} and scalar @{$self->{' free'}} > 0) { + $res = shift(@{$self->{' free'}}); + if (defined $base) { + my ($num, $gen) = @{$self->{' objects'}{$res->uid}}; + $self->remove_obj($res); + $self->add_obj($base, $num, $gen); + return $self->out_obj($base); + } + else { + $self->{' objects'}{$res->uid}[2] = 0; + return $res; + } + } + + my $tdict = $self; + my $i; + while (defined $tdict) { + $i = $tdict->{' xref'}{defined($i) ? $i : ''}[0]; + while (defined $i and $i != 0) { + my ($ni, $ng) = @{$tdict->{' xref'}{$i}}; + unless (defined $self->locate_obj($i, $ng)) { + if (defined $base) { + $self->add_obj($base, $i, $ng); + return $base; + } + else { + $res = $self->test_obj($i, $ng) || $self->add_obj(PDF::API2::Basic::PDF::Objind->new(), $i, $ng); + $self->out_obj($res); + return $res; + } + } + $i = $ni; + } + $tdict = $tdict->{' prev'}; + } + + $i = $self->{' maxobj'}++; + if (defined $base) { + $self->add_obj($base, $i, 0); + $self->out_obj($base); + return $base; + } + else { + $res = $self->add_obj(PDF::API2::Basic::PDF::Objind->new(), $i, 0); + $self->out_obj($res); + return $res; + } +} + + +#line 860 + +sub out_obj { + my ($self, $obj) = @_; + + # This is why we've been keeping the outlist CACHE around; to speed + # up this method by orders of magnitude (it saves up from having to + # grep the full outlist each time through as we'll just do a lookup + # in the hash) (which is super-fast). + unless (exists $self->{' outlist_cache'}{$obj}) { + push @{$self->{' outlist'}}, $obj; + # weaken $self->{' outlist'}->[-1]; + $self->{' outlist_cache'}{$obj} = 1; + } + return $obj; +} + + +#line 882 + +sub free_obj { + my ($self, $obj) = @_; + + push @{$self->{' free'}}, $obj; + $self->{' objects'}{$obj->uid()}[2] = 1; + $self->out_obj($obj); +} + + +#line 897 + +sub remove_obj { + my ($self, $objind) = @_; + + # who says it has to be fast + delete $self->{' objects'}{$objind->uid()}; + delete $self->{' outlist_cache'}{$objind}; + delete $self->{' printed_cache'}{$objind}; + @{$self->{' outlist'}} = grep($_ ne $objind, @{$self->{' outlist'}}); + @{$self->{' printed'}} = grep($_ ne $objind, @{$self->{' printed'}}); + $self->{' objcache'}{$objind->{' objnum'}, $objind->{' objgen'}} = undef + if $self->{' objcache'}{$objind->{' objnum'}, $objind->{' objgen'}} eq $objind; + return $self; +} + + +#line 923 + +sub ship_out { + my ($self, @objs) = @_; + + return unless defined $self->{' OUTFILE'}; + my $fh = $self->{' OUTFILE'}; + seek($fh, 0, 2); # go to the end of the file + + @objs = @{$self->{' outlist'}} unless scalar @objs > 0; + foreach my $objind (@objs) { + next unless $objind->is_obj($self); + my $j = -1; + for (my $i = 0; $i < scalar @{$self->{' outlist'}}; $i++) { + if ($self->{' outlist'}[$i] eq $objind) { + $j = $i; + last; + } + } + next if $j < 0; + splice(@{$self->{' outlist'}}, $j, 1); + delete $self->{' outlist_cache'}{$objind}; + next if grep { $_ eq $objind } @{$self->{' free'}}; + + map { $fh->print("\% $_ \n") } split(/$cr/, $objind->{' comments'}) if $objind->{' comments'}; + $self->{' locs'}{$objind->uid()} = $fh->tell(); + my ($objnum, $objgen) = @{$self->{' objects'}{$objind->uid()}}[0..1]; + $fh->printf('%d %d obj ', $objnum, $objgen); + $objind->outobjdeep($fh, $self, 'objnum' => $objnum, 'objgen' => $objgen); + $fh->print(" endobj\n"); + + # Note that we've output this obj, not forgetting to update + # the cache of whats printed. + unless (exists $self->{' printed_cache'}{$objind}) { + push @{$self->{' printed'}}, $objind; + $self->{' printed_cache'}{$objind}++; + } + } + return $self; +} + +#line 969 + +sub copy { + my ($self, $out, $filter) = @_; + my ($obj, $minl, $mini, $ming); + + foreach my $key (grep { not m/^[\s\-]/ } keys %$self) { + $out->{$key} = $self->{$key} unless defined $out->{$key}; + } + + my $tdict = $self; + while (defined $tdict) { + foreach my $i (sort {$a <=> $b} keys %{$tdict->{' xref'}}) { + my ($nl, $ng, $nt) = @{$tdict->{' xref'}{$i}}; + next unless $nt eq 'n'; + + if ($nl < $minl or $mini == 0) { + $mini = $i; + $ming = $ng; + $minl = $nl; + } + unless ($obj = $self->test_obj($i, $ng)) { + $obj = PDF::API2::Basic::PDF::Objind->new(); + $obj->{' objnum'} = $i; + $obj->{' objgen'} = $ng; + $self->add_obj($obj, $i, $ng); + $obj->{' parent'} = $self; + weaken $obj->{' parent'}; + $obj->{' realised'} = 0; + } + $obj->realise; + my $res = defined $filter ? &{$filter}($obj) : $obj; + $out->new_obj($res) unless (!$res || $res->is_obj($out)); + } + $tdict = $tdict->{' prev'}; + } + + # test for linearized and remove it from output + $obj = $self->test_obj($mini, $ming); + if ($obj->isa('PDF::API2::Basic::PDF::Dict') && $obj->{'Linearized'}) { + $out->free_obj($obj); + } + + return $self; +} + + +#line 1027 + +sub locate_obj { + my ($self, $num, $gen) = @_; + + my $tdict = $self; + while (defined $tdict) { + if (ref $tdict->{' xref'}{$num}) { + my $ref = $tdict->{' xref'}{$num}; + return $ref unless scalar(@$ref) == 3; + + if ($ref->[1] == $gen) { + return $ref->[0] if $ref->[2] eq 'n'; + return; # if $ref->[2] eq 'f'; + } + } + $tdict = $tdict->{' prev'}; + } + return; +} + + +#line 1055 + +sub update { + my ($fh, $str, $instream) = @_; + print STDERR 'fpos=' . tell($fh) . ' strlen=' . length($str) . "\n" if $readDebug; + if ($instream) { + # we are inside a (possible binary) stream + # so we fetch data till we see an 'endstream' + # -- fredo/2004-09-03 + while ($str !~ m/endstream/ and not $fh->eof()) { + print STDERR 'fpos=' . tell($fh) . ' strlen=' . length($str) . "\n" if $readDebug; + $fh->read($str, 314, length($str)); + } + } + else { + $str =~ s/^$ws_char*//; + while ($str !~ m/$cr/ and not $fh->eof()) { + print STDERR 'fpos=' . tell($fh) . ' strlen=' . length($str) . "\n" if $readDebug; + $fh->read($str, 314, length($str)); + $str =~ s/^$ws_char*//so; + } + while ($str =~ m/^\%/) { # restructured by fredo/2003-03-23 + print STDERR 'fpos=' . tell($fh) . ' strlen=' . length($str) . "\n" if $readDebug; + $fh->read($str, 314, length($str)) while ($str !~ m/$cr/ and not $fh->eof()); + $str =~ s/^\%[^\015\012]*$ws_char*//so; # fixed for reportlab -- fredo + } + } + + return $str; +} + +#line 1091 + +sub test_obj { + my ($self, $num, $gen) = @_; + return $self->{' objcache'}{$num, $gen}; +} + + +#line 1103 + +sub add_obj { + my ($self, $obj, $num, $gen) = @_; + + $self->{' objcache'}{$num, $gen} = $obj; + $self->{' objects'}{$obj->uid()} = [$num, $gen]; + # weaken $self->{' objcache'}{$num, $gen}; + return $obj; +} + + +#line 1129 + +sub _unpack_xref_stream { + my ($self, $width, $data) = @_; + + return unpack('C', $data) if $width == 1; + return unpack('n', $data) if $width == 2; + return unpack('N', "\x00$data") if $width == 3; + return unpack('N', $data) if $width == 4; + + die "Invalid column width: $width"; +} + +sub readxrtr { + my ($self, $xpos) = @_; + my ($tdict, $buf, $xmin, $xnum, $xdiff); + + my $fh = $self->{' INFILE'}; + $fh->seek($xpos, 0); + $fh->read($buf, 22); + $buf = update($fh, $buf); # fix for broken JAWS xref calculation. + + my $xlist = {}; + + ## seams that some products calculate wrong prev entries (short) + ## so we seek ahead to find one -- fredo; save for now + #while($buf !~ m/^xref$cr/i && !eof($fh)) + #{ + # $buf =~ s/^(\s+|\S+|.)//i; + # $buf=update($fh,$buf); + #} + + if ($buf =~ s/^xref$cr//i) { + # Plain XRef tables. + while ($buf =~ m/^$ws_char*([0-9]+)$ws_char+([0-9]+)$ws_char*$cr(.*?)$/s) { + my $old_buf = $buf; + $xmin = $1; + $xnum = $2; + $buf = $3; + unless ($old_buf =~ /^[0-9]+ [0-9]+$cr/) { + # See PDF 1.7 section 7.5.4: Cross-Reference Table + warn q{Malformed xref in PDF file: subsection shall begin with a line containing two numbers separated by a SPACE (20h)}; + } + $xdiff = length($buf); + + $fh->read($buf, 20 * $xnum - $xdiff + 15, $xdiff); + while ($xnum-- > 0 and $buf =~ s/^0*([0-9]*)$ws_char+0*([0-9]+)$ws_char+([nf])$cr//) { + $xlist->{$xmin} = [$1, $2, $3] unless exists $xlist->{$xmin}; + $xmin++; + } + } + + if ($buf !~ /^\s*trailer\b/i) { + die "Malformed trailer in PDF file $self->{' fname'} at " . ($fh->tell - length($buf)); + } + + $buf =~ s/^\s*trailer\b//i; + + ($tdict, $buf) = $self->readval($buf); + } + elsif ($buf =~ m/^(\d+)\s+(\d+)\s+obj/i) { + my ($xref_obj, $xref_gen) = ($1, $2); + + # XRef streams. + ($tdict, $buf) = $self->readval($buf); + + unless ($tdict->{' stream'}) { + die "Malformed XRefStm at $xref_obj $xref_gen obj in PDF file $self->{' fname'}"; + } + $tdict->read_stream(1); + + my $stream = $tdict->{' stream'}; + my @widths = map { $_->val } @{$tdict->{W}->val}; + + my $start = 0; + my $last; + + my @index; + if (defined $tdict->{Index}) { + @index = map { $_->val() } @{$tdict->{Index}->val}; + } + else { + @index = (0, $tdict->{Size}->val); + } + + while (scalar @index) { + $start = shift(@index); + $last = $start + shift(@index) - 1; + + for my $i ($start...$last) { + # Replaced "for $xmin" because it creates a loop-specific local variable, and we + # need $xmin to be correct for maxobj below. + $xmin = $i; + + my @cols; + + for my $w (@widths) { + my $data; + $data = $self->_unpack_xref_stream($w, substr($stream, 0, $w, '')) if $w; + + push @cols, $data; + } + + $cols[0] = 1 unless defined $cols[0]; + if ($cols[0] > 2) { + die "Invalid XRefStm entry type ($cols[0]) at $xref_obj $xref_gen obj"; + } + + next if exists $xlist->{$xmin}; + + my @objind = ($cols[1], defined($cols[2]) ? $cols[2] : ($xmin ? 0 : 65535)); + push @objind, ($cols[0] == 0 ? 'f' : 'n') if $cols[0] < 2; + + $xlist->{$xmin} = \@objind; + } + } + } + else { + die "Malformed xref in PDF file $self->{' fname'}"; + } + + $tdict->{' loc'} = $xpos; + $tdict->{' xref'} = $xlist; + $self->{' maxobj'} = $xmin + 1 if $xmin + 1 > $self->{' maxobj'}; + $tdict->{' prev'} = $self->readxrtr($tdict->{'Prev'}->val) + if (defined $tdict->{'Prev'} and $tdict->{'Prev'}->val != 0); + delete $tdict->{' prev'} unless defined $tdict->{' prev'}; + return $tdict; +} + + +#line 1266 + +sub out_trailer { + my ($self, $tdict, $update) = @_; + my $fh = $self->{' OUTFILE'}; + + while (@{$self->{' outlist'}}) { + $self->ship_out(); + } + + # $size = @{$self->{' printed'}} + @{$self->{' free'}}; + # $tdict->{'Size'} = PDFNum($tdict->{'Size'}->val + $size); + # PDFSpec 1.3 says for /Size: (Required) Total number of entries in the file's + # cross-reference table, including the original table and all updates. Which + # is what the previous two lines implement. + # But this seems to make Acrobat croak on saving so we try the following from + # basil.duval@epfl.ch + $tdict->{'Size'} = PDFNum($self->{' maxobj'}); + + my $tloc = $fh->tell(); + $fh->print("xref\n"); + + my @xreflist = sort { $self->{' objects'}{$a->uid}[0] <=> $self->{' objects'}{$b->uid}[0] } (@{$self->{' printed'} || []}, @{$self->{' free'} || []}); + + my ($i, $j, $k); + unless ($update) { + $i = 1; + for ($j = 0; $j < @xreflist; $j++) { + my @inserts; + $k = $xreflist[$j]; + while ($i < $self->{' objects'}{$k->uid}[0]) { + my ($n) = PDF::API2::Basic::PDF::Objind->new(); + $self->add_obj($n, $i, 0); + $self->free_obj($n); + push(@inserts, $n); + $i++; + } + splice(@xreflist, $j, 0, @inserts); + $j += @inserts; + $i++; + } + } + + my @freelist = sort { $self->{' objects'}{$a->uid}[0] <=> $self->{' objects'}{$b->uid}[0] } @{$self->{' free'} || []}; + + $j = 0; my $first = -1; $k = 0; + for ($i = 0; $i <= $#xreflist + 1; $i++) { +# if ($i == 0) { +# $first = $i; $j = $xreflist[0]->{' objnum'}; +# $fh->printf("0 1\n%010d 65535 f \n", $ff); +# } + if ($i > $#xreflist || $self->{' objects'}{$xreflist[$i]->uid}[0] != $j + 1) { + $fh->print(($first == -1 ? "0 " : "$self->{' objects'}{$xreflist[$first]->uid}[0] ") . ($i - $first) . "\n"); + if ($first == -1) { + $fh->printf("%010d 65535 f \n", defined $freelist[$k] ? $self->{' objects'}{$freelist[$k]->uid}[0] : 0); + $first = 0; + } + for ($j = $first; $j < $i; $j++) { + my $xref = $xreflist[$j]; + if (defined $freelist[$k] && defined $xref && "$freelist[$k]" eq "$xref") { + $k++; + $fh->print(pack("A10AA5A4", + sprintf("%010d", (defined $freelist[$k] ? + $self->{' objects'}{$freelist[$k]->uid}[0] : 0)), " ", + sprintf("%05d", $self->{' objects'}{$xref->uid}[1] + 1), + " f \n")); + } + else { + $fh->print(pack("A10AA5A4", sprintf("%010d", $self->{' locs'}{$xref->uid}), " ", + sprintf("%05d", $self->{' objects'}{$xref->uid}[1]), + " n \n")); + } + } + $first = $i; + $j = $self->{' objects'}{$xreflist[$i]->uid}[0] if ($i < scalar @xreflist); + } + else { + $j++; + } + } + $fh->print("trailer\n"); + $tdict->outobjdeep($fh, $self); + $fh->print("\nstartxref\n$tloc\n%%EOF\n"); +} + + +#line 1356 + +sub _new { + my $class = shift(); + my $self = {}; + + bless $self, $class; + $self->{' outlist'} = []; + $self->{' outlist_cache'} = {}; # A cache of whats in the 'outlist' + $self->{' maxobj'} = 1; + $self->{' objcache'} = {}; + $self->{' objects'} = {}; + + return $self; +} + +1; + +#line 1381 \ No newline at end of file diff --git a/lib/PDF/API2/Basic/PDF/Filter.pm b/lib/PDF/API2/Basic/PDF/Filter.pm new file mode 100644 index 0000000..71fcb72 --- /dev/null +++ b/lib/PDF/API2/Basic/PDF/Filter.pm @@ -0,0 +1,68 @@ +#line 1 "PDF/API2/Basic/PDF/Filter.pm" +#line 1 "PDF/API2/Basic/PDF/Filter.pm" +#======================================================================= +# +# THIS IS A REUSED PERL MODULE, FOR PROPER LICENCING TERMS SEE BELOW: +# +# Copyright Martin Hosken <Martin_Hosken@sil.org> +# +# No warranty or expression of effectiveness, least of all regarding +# anyone's safety, is implied in this software or documentation. +# +# This specific module is licensed under the Perl Artistic License. +# +#======================================================================= +package PDF::API2::Basic::PDF::Filter; + +use strict; +use warnings; + +our $VERSION = '2.033'; # VERSION + +use PDF::API2::Basic::PDF::Filter::ASCII85Decode; +use PDF::API2::Basic::PDF::Filter::ASCIIHexDecode; +use PDF::API2::Basic::PDF::Filter::FlateDecode; +use PDF::API2::Basic::PDF::Filter::LZWDecode; +use PDF::API2::Basic::PDF::Filter::RunLengthDecode; +use Scalar::Util qw(blessed reftype); + +#line 76 + +sub new { + my $class = shift(); + my $self = {}; + + bless $self, $class; + + return $self; +} + +sub release { + my $self = shift(); + return $self unless ref($self); + + # delete stuff that we know we can, here + my @tofree = map { delete $self->{$_} } keys %$self; + + while (my $item = shift @tofree) { + my $ref = ref($item); + if (blessed($item) and $item->can('release')) { + $item->release(); + } + elsif ($ref eq 'ARRAY') { + push @tofree, @$item; + } + elsif (defined(reftype($ref)) and reftype($ref) eq 'HASH') { + release($item); + } + } + + # check that everything has gone + foreach my $key (keys %$self) { + # warn ref($self) . " still has '$key' key left after release.\n"; + $self->{$key} = undef; + delete $self->{$key}; + } +} + +1; diff --git a/lib/PDF/API2/Basic/PDF/Filter/ASCII85Decode.pm b/lib/PDF/API2/Basic/PDF/Filter/ASCII85Decode.pm new file mode 100644 index 0000000..18633c4 --- /dev/null +++ b/lib/PDF/API2/Basic/PDF/Filter/ASCII85Decode.pm @@ -0,0 +1,90 @@ +#line 1 "PDF/API2/Basic/PDF/Filter/ASCII85Decode.pm" +#line 1 "PDF/API2/Basic/PDF/Filter/ASCII85Decode.pm" +package PDF::API2::Basic::PDF::Filter::ASCII85Decode; + +use base 'PDF::API2::Basic::PDF::Filter'; + +use strict; +use warnings; + +our $VERSION = '2.033'; # VERSION + +sub outfilt { + my ($self, $str, $isend) = @_; + my ($res, $i, $j, $b, @c); + + if (exists $self->{'outcache'} and $self->{'outcache'} ne "") { + $str = $self->{'outcache'} . $str; + $self->{'outcache'} = ""; + } + for ($i = 0; $i + 4 <= length($str); $i += 4) { + $b = unpack("N", substr($str, $i, 4)); + if ($b == 0) { + $res .= "z"; + next; + } + for ($j = 0; $j < 4; $j++) { + $c[$j] = $b - int($b / 85) * 85 + 33; $b /= 85; + } + $res .= pack("C5", $b + 33, reverse @c); + $res .= "\n" if ($i % 60 == 56); + } + if ($isend && $i < length($str)) { + $str = substr($str, $i); + $b = unpack("N", $str . ("\000" x (4 - length($str)))); + for ($j = 0; $j < 4; $j++) { + $c[$j] = $b - int($b / 85) * 85 + 33; $b /= 85; + } + push @c, $b + 33; + $res .= substr(pack("C5", reverse @c), 0, length($str) + 1) . '~>'; + } + elsif ($isend) { + $res .= '~>'; + } + elsif ($i + 4 > length($str)) { + $self->{'outcache'} = substr($str, $i); + } + + return $res; +} + +sub infilt { + my ($self, $str, $isend) = @_; + my ($res, $i, $j, @c, $b, $num); + $num = 0; + if (exists($self->{'incache'}) && $self->{'incache'} ne "") { + $str = $self->{'incache'} . $str; + $self->{'incache'} = ""; + } + $str =~ s/(\r|\n)\n?//og; + for ($i = 0; $i < length($str); $i += 5) { + last if $isend and substr($str, $i, 6) eq '~>'; + $b = 0; + if (substr($str, $i, 1) eq "z") { + $i -= 4; + $res .= pack("N", 0); + next; + } + elsif ($isend && substr($str, $i, 6) =~ m/^(.{2,4})\~\>$/o) { + $num = 5 - length($1); + @c = unpack("C5", $1 . ("u" x (4 - $num))); # pad with 84 to sort out rounding + $i = length($str); + } + else { + @c = unpack("C5", substr($str, $i, 5)); + } + + for ($j = 0; $j < 5; $j++) { + $b *= 85; + $b += $c[$j] - 33; + } + $res .= substr(pack("N", $b), 0, 4 - $num); + } + if (!$isend && $i > length($str)) { + $self->{'incache'} = substr($str, $i - 5); + } + + return $res; +} + +1; diff --git a/lib/PDF/API2/Basic/PDF/Filter/ASCIIHexDecode.pm b/lib/PDF/API2/Basic/PDF/Filter/ASCIIHexDecode.pm new file mode 100644 index 0000000..36d8544 --- /dev/null +++ b/lib/PDF/API2/Basic/PDF/Filter/ASCIIHexDecode.pm @@ -0,0 +1,60 @@ +#line 1 "PDF/API2/Basic/PDF/Filter/ASCIIHexDecode.pm" +#line 1 "PDF/API2/Basic/PDF/Filter/ASCIIHexDecode.pm" +package PDF::API2::Basic::PDF::Filter::ASCIIHexDecode; + +use base 'PDF::API2::Basic::PDF::Filter'; + +use strict; +use warnings; + +our $VERSION = '2.033'; # VERSION + +# Maintainer's Note: ASCIIHexDecode is described in the PDF 1.7 spec +# in section 7.4.2. + +sub outfilt { + my ($self, $string, $include_eod) = @_; + + # Each byte of the input string gets encoded as two hexadecimal + # characters. + $string =~ s/(.)/sprintf('%02x', ord($1))/oge; + + # The EOD (end-of-document) marker is a greater-than sign + $string .= '>' if $include_eod; + + return $string; +} + +sub infilt { + my ($self, $string) = @_; + + # "All white-space characters shall be ignored." + $string =~ s/\s//og; + + # "A GREATER-THAN SIGN (3Eh) indicates EOD." + my $has_eod_marker = 0; + if (substr($string, -1, 1) eq '>') { + $has_eod_marker = 1; + chop $string; + } + + # "Any other characters [than 0-9, A-F, or a-f] shall cause an + # error." + die "Illegal character found in ASCII hex-encoded stream" + if $string =~ /[^0-9A-Fa-f]/; + + # "If the filter encounters the EOD marker after reading an odd + # number of hexadecimal digits, it shall behave as if a 0 (zero) + # followed the last digit." + if ($has_eod_marker and length($string) % 2 == 1) { + $string .= '0'; + } + + # "The ASCIIHexDecode filter shall produce one byte of binary data + # for each pair of ASCII hexadecimal digits." + $string =~ s/([0-9A-Fa-f]{2})/pack("C", hex($1))/oge; + + return $string; +} + +1; diff --git a/lib/PDF/API2/Basic/PDF/Filter/FlateDecode.pm b/lib/PDF/API2/Basic/PDF/Filter/FlateDecode.pm new file mode 100644 index 0000000..9b7a4e4 --- /dev/null +++ b/lib/PDF/API2/Basic/PDF/Filter/FlateDecode.pm @@ -0,0 +1,152 @@ +#line 1 "PDF/API2/Basic/PDF/Filter/FlateDecode.pm" +#line 1 "PDF/API2/Basic/PDF/Filter/FlateDecode.pm" +package PDF::API2::Basic::PDF::Filter::FlateDecode; + +use base 'PDF::API2::Basic::PDF::Filter'; + +use strict; +no warnings qw[ deprecated recursion uninitialized ]; + +our $VERSION = '2.033'; # VERSION + +use POSIX qw(ceil floor); + +our $havezlib; + +BEGIN +{ + eval { require Compress::Zlib }; + $havezlib = !$@; +} + +sub new +{ + return unless $havezlib; + my ($class, $decode_parms) = @_; + my ($self) = { + DecodeParms => $decode_parms, + }; + + $self->{'outfilt'} = Compress::Zlib::deflateInit( + -Level=>9, + -Bufsize=>32768, + ); + $self->{'infilt'} = Compress::Zlib::inflateInit(); + bless $self, $class; +} + +sub outfilt +{ + my ($self, $str, $isend) = @_; + my ($res); + + $res = $self->{'outfilt'}->deflate($str); + $res .= $self->{'outfilt'}->flush() if ($isend); + $res; +} + +sub infilt +{ + my ($self, $dat, $last) = @_; + my ($res, $status) = $self->{'infilt'}->inflate("$dat"); + + if ($self->{'DecodeParms'} and $self->{'DecodeParms'}->{'Predictor'}) { + my $predictor = $self->{'DecodeParms'}->{'Predictor'}->val(); + if ($predictor == 2) { + die "The TIFF predictor logic has not been implemented"; + } + elsif ($predictor >= 10 and $predictor <= 15) { + $res = $self->_depredict_png($res); + } + else { + die "Invalid predictor: $predictor"; + } + } + + return $res; +} + +sub _depredict_png { + my ($self, $stream) = @_; + my $param = $self->{'DecodeParms'}; + + my $prev = ''; + $stream = $self->{'_depredict_next'} . $stream if defined $self->{'_depredict_next'}; + $prev = $self->{'_depredict_prev'} if defined $self->{'_depredict_prev'}; + + my $alpha = $param->{Alpha} ? $param->{Alpha}->val() : 0; + my $bpc = $param->{BitsPerComponent} ? $param->{BitsPerComponent}->val() : 8; + my $colors = $param->{Colors} ? $param->{Colors}->val() : 1; + my $columns = $param->{Columns} ? $param->{Columns}->val() : 1; + my $height = $param->{Height} ? $param->{Height}->val() : 0; + + my $comp = $colors + $alpha; + my $bpp = ceil($bpc * $comp / 8); + my $scanline = 1 + ceil($bpp * $columns); + + my $clearstream = ''; + my $lastrow = ($height || int(length($stream) / $scanline)) - 1; + foreach my $n (0 .. $lastrow) { + # print STDERR "line $n:"; + my $line = substr($stream, $n * $scanline, $scanline); + my $filter = vec($line, 0, 8); + my $clear = ''; + $line = substr($line, 1); + # print STDERR " filter=$filter "; + if ($filter == 0) { + $clear = $line; + } + elsif ($filter == 1) { + foreach my $x (0 .. length($line) - 1) { + vec($clear, $x, 8) = (vec($line, $x, 8) + vec($clear, $x - $bpp, 8)) % 256; + } + } + elsif ($filter == 2) { + foreach my $x (0 .. length($line) - 1) { + vec($clear, $x, 8) = (vec($line, $x, 8) + vec($prev, $x, 8)) % 256; + } + } + elsif ($filter == 3) { + foreach my $x (0 .. length($line) - 1) { + vec($clear, $x, 8) = (vec($line, $x, 8) + floor((vec($clear, $x - $bpp, 8) + vec($prev, $x, 8)) / 2)) % 256; + } + } + elsif ($filter == 4) { + foreach my $x (0 .. length($line) - 1) { + vec($clear, $x, 8) = (vec($line, $x, 8) + _paeth_predictor(vec($clear, $x - $bpp, 8), vec($prev, $x, 8), vec($prev, $x - $bpp, 8))) % 256; + } + } + else { + die "Unexpected depredictor algorithm $filter requested on line $n (valid options are 0-4)"; + } + $prev = $clear; + foreach my $x (0 .. ($columns * $comp) - 1) { + vec($clearstream, ($n * $columns * $comp) + $x, $bpc) = vec($clear, $x, $bpc); + # print STDERR "" . vec($clear, $x, $bpc) . ","; + } + # print STDERR "\n"; + } + $self->{'_depredict_next'} = substr($stream, ($lastrow + 1) * $scanline); + $self->{'_depredict_prev'} = $prev; + + return $clearstream; +} + +sub _paeth_predictor { + my ($a, $b, $c) = @_; + my $p = $a + $b - $c; + my $pa = abs($p - $a); + my $pb = abs($p - $b); + my $pc = abs($p - $c); + if ($pa <= $pb && $pa <= $pc) { + return $a; + } + elsif ($pb <= $pc) { + return $b; + } + else { + return $c; + } +} + +1; diff --git a/lib/PDF/API2/Basic/PDF/Filter/LZWDecode.pm b/lib/PDF/API2/Basic/PDF/Filter/LZWDecode.pm new file mode 100644 index 0000000..f1b0852 --- /dev/null +++ b/lib/PDF/API2/Basic/PDF/Filter/LZWDecode.pm @@ -0,0 +1,99 @@ +#line 1 "PDF/API2/Basic/PDF/Filter/LZWDecode.pm" +#line 1 "PDF/API2/Basic/PDF/Filter/LZWDecode.pm" +package PDF::API2::Basic::PDF::Filter::LZWDecode; + +use base 'PDF::API2::Basic::PDF::Filter::FlateDecode'; + +use strict; +no warnings qw[ deprecated recursion uninitialized ]; + +our $VERSION = '2.033'; # VERSION + +sub new { + my ($class, $decode_parms) = @_; + my $self = { + DecodeParms => $decode_parms, + }; + + $self->{'table'} = [map { pack('C', $_) } (0 .. 255, 0, 0)]; + $self->{'initial_code_length'} = 9; + $self->{'code_length'} = 9; + $self->{'clear_table'} = 256; + $self->{'eod_marker'} = 257; + $self->{'next_code'} = 258; + + bless $self, $class; + return $self; +} + +sub infilt { + my ($self, $data, $is_last) = @_; + my ($code, $result); + my $partial_code = $self->{'partial_code'}; + my $partial_bits = $self->{'partial_bits'}; + + my $early_change = 1; + if ($self->{'DecodeParms'} and $self->{'DecodeParms'}->{'EarlyChange'}) { + $early_change = $self->{'DecodeParms'}->{'EarlyChange'}->val(); + } + + while ($data ne '') { + ($code, $partial_code, $partial_bits) = $self->read_dat(\$data, $partial_code, $partial_bits, $self->{'code_length'}); + last unless defined $code; + + unless ($early_change) { + if ($self->{'next_code'} == (1 << $self->{'code_length'}) and $self->{'code_length'} < 12) { + $self->{'code_length'}++; + } + } + + if ($code == $self->{'clear_table'}) { + $self->{'code_length'} = $self->{'initial_code_length'}; + $self->{'next_code'} = $self->{'eod_marker'} + 1; + next; + } + elsif ($code == $self->{'eod_marker'}) { + last; + } + elsif ($code > $self->{'eod_marker'}) { + $self->{'table'}[$self->{'next_code'}] = $self->{'table'}[$code]; + $self->{'table'}[$self->{'next_code'}] .= substr($self->{'table'}[$code + 1], 0, 1); + $result .= $self->{'table'}[$self->{'next_code'}]; + $self->{'next_code'}++; + } + else { + $self->{'table'}[$self->{'next_code'}] = $self->{'table'}[$code]; + $result .= $self->{'table'}[$self->{'next_code'}]; + $self->{'next_code'}++; + } + + if ($early_change) { + if ($self->{'next_code'} == (1 << $self->{'code_length'}) and $self->{'code_length'} < 12) { + $self->{'code_length'}++; + } + } + } + $self->{'partial_code'} = $partial_code; + $self->{'partial_bits'} = $partial_bits; + return $result; +} + +sub read_dat { + my ($self, $data_ref, $partial_code, $partial_bits, $code_length) = @_; + $partial_bits = 0 unless defined $partial_bits; + + while ($partial_bits < $code_length) { + return (undef, $partial_code, $partial_bits) unless length($$data_ref); + $partial_code = ($partial_code << 8) + unpack('C', $$data_ref); + substr($$data_ref, 0, 1) = ''; + $partial_bits += 8; + } + + my $code = $partial_code >> ($partial_bits - $code_length); + $partial_code &= (1 << ($partial_bits - $code_length)) - 1; + $partial_bits -= $code_length; + + return ($code, $partial_code, $partial_bits); +} + +1; diff --git a/lib/PDF/API2/Basic/PDF/Filter/RunLengthDecode.pm b/lib/PDF/API2/Basic/PDF/Filter/RunLengthDecode.pm new file mode 100644 index 0000000..7f95e64 --- /dev/null +++ b/lib/PDF/API2/Basic/PDF/Filter/RunLengthDecode.pm @@ -0,0 +1,111 @@ +#line 1 "PDF/API2/Basic/PDF/Filter/RunLengthDecode.pm" +#line 1 "PDF/API2/Basic/PDF/Filter/RunLengthDecode.pm" +package PDF::API2::Basic::PDF::Filter::RunLengthDecode; + +use base 'PDF::API2::Basic::PDF::Filter'; + +use strict; +use warnings; + +our $VERSION = '2.033'; # VERSION + +# Maintainer's Note: RunLengthDecode is described in the PDF 1.7 spec +# in section 7.4.5. + +sub outfilt { + my ($self, $input, $include_eod) = @_; + my $output; + + while ($input ne '') { + my ($unrepeated, $repeated); + + # Look for a repeated character (which can be repeated up to + # 127 times) + if ($input =~ m/^(.*?)((.)\3{1,127})(.*)$/so) { + $unrepeated = $1; + $repeated = $2; + $input = $4; + } + else { + $unrepeated = $input; + $input = ''; + } + + # Print any non-repeating bytes at the beginning of the input + # in chunks of up to 128 bytes, prefixed with a run-length (0 + # to 127, signifying 1 to 128 bytes) + while (length($unrepeated) > 127) { + $output .= pack('C', 127) . substr($unrepeated, 0, 128); + substr($unrepeated, 0, 128) = ''; + } + $output .= pack('C', length($unrepeated) - 1) . $unrepeated if length($unrepeated) > 0; + + # Then print the number of times the repeated byte was + # repeated (using the formula "257 - length" to give a result + # in the 129-255 range) followed by the byte to be repeated + if (length($repeated)) { + $output .= pack('C', 257 - length($repeated)) . substr($repeated, 0, 1); + } + } + + # A byte value of 128 signifies that we're done. + $output .= "\x80" if $include_eod; + + return $output; +} + +sub infilt { + my ($self, $input, $is_terminated) = @_; + my ($output, $length); + + # infilt may be called multiple times, and is expected to continue + # where it left off + if (exists $self->{'incache'}) { + $input = $self->{'incache'} . $input; + delete $self->{'incache'}; + } + + while (length($input)) { + # Read a length byte + $length = unpack("C", $input); + + # A "length" of 128 represents the end of the document + if ($length == 128) { + return $output; + } + + # Any other length needs to be followed by at least one other byte + if (length($input) == 1 and not $is_terminated) { + die "Premature end to RunLengthEncoded data"; + } + + # A length of 129-255 represents a repeated string + # (number of repeats = 257 - length) + if ($length > 128) { + if (length($input) == 1) { + # Out of data. Defer until the next call. + $self->{'incache'} = $input; + return $output; + } + $output .= substr($input, 1, 1) x (257 - $length); + substr($input, 0, 2) = ''; + } + + # Any other length (under 128) represents a non-repeated + # stream of bytes (with a length of 0 to 127 representing 1 to + # 128 bytes) + else { + if (length($input) < $length + 2) { + # Insufficient data. Defer until the next call. + $self->{'incache'} = $input; + return $output; + } + $output .= substr($input, 1, $length + 1); + substr($input, 0, $length + 2) = ''; + } + } + + return $output; +} + +1; diff --git a/lib/PDF/API2/Basic/PDF/Literal.pm b/lib/PDF/API2/Basic/PDF/Literal.pm new file mode 100644 index 0000000..6254854 --- /dev/null +++ b/lib/PDF/API2/Basic/PDF/Literal.pm @@ -0,0 +1,89 @@ +#line 1 "PDF/API2/Basic/PDF/Literal.pm" +#line 1 "PDF/API2/Basic/PDF/Literal.pm" +# Literal PDF Object for Dirty Hacks ... +package PDF::API2::Basic::PDF::Literal; + +use base 'PDF::API2::Basic::PDF::Objind'; + +use strict; + +our $VERSION = '2.033'; # VERSION + +use PDF::API2::Basic::PDF::Filter; +use PDF::API2::Basic::PDF::Name; +use Scalar::Util qw(blessed); + +no warnings qw[ deprecated recursion uninitialized ]; + +sub new +{ + my ($class, @opts) = @_; + my ($self); + + $class = ref $class if ref $class; + $self = $class->SUPER::new(@_); + $self->{' realised'} = 1; + if(scalar @opts > 1) { + $self->{-isdict}=1; + my %opt=@opts; + foreach my $k (keys %opt) { + $self->{$k} = $opt{$k}; + } + } elsif(scalar @opts == 1) { + $self->{-literal}=$opts[0]; + } + return $self; +} + +sub outobjdeep +{ + my ($self, $fh, $pdf, %opts) = @_; + if($self->{-isdict}) + { + if(defined $self->{' stream'}) + { + $self->{Length} = length($self->{' stream'}) + 1; + } + else + { + delete $self->{Length}; + } + $fh->print("<< "); + foreach my $k (sort keys %{$self}) + { + next if($k=~m|^[ \-]|o); + $fh->print('/'.PDF::API2::Basic::PDF::Name::string_to_name($k).' '); + if(ref($self->{$k}) eq 'ARRAY') + { + $fh->print('['.join(' ',@{$self->{$k}})."]\n"); + } + elsif(ref($self->{$k}) eq 'HASH') + { + $fh->print('<<'.join(' ', map { '/'.PDF::API2::Basic::PDF::Name::string_to_name($_).' '.$self->{$k}->{$_} } sort keys %{$self->{$k}})." >>\n"); + } + elsif(blessed($self->{$k}) and $self->{$k}->can('outobj')) + { + $self->{$k}->outobj($fh, $pdf, %opts); + $fh->print("\n"); + } + else + { + $fh->print("$self->{$k}\n"); + } + } + $fh->print(">>\n"); + if(defined $self->{' stream'}) + { + $fh->print("stream\n$self->{' stream'}\nendstream"); # next is endobj which has the final cr + } + } + else + { + $fh->print($self->{-literal}); # next is endobj which has the final cr + } +} + +sub val +{ $_[0]; } + +1; diff --git a/lib/PDF/API2/Basic/PDF/Name.pm b/lib/PDF/API2/Basic/PDF/Name.pm new file mode 100644 index 0000000..990082d --- /dev/null +++ b/lib/PDF/API2/Basic/PDF/Name.pm @@ -0,0 +1,84 @@ +#line 1 "PDF/API2/Basic/PDF/Name.pm" +#line 1 "PDF/API2/Basic/PDF/Name.pm" +#======================================================================= +# +# THIS IS A REUSED PERL MODULE, FOR PROPER LICENCING TERMS SEE BELOW: +# +# Copyright Martin Hosken <Martin_Hosken@sil.org> +# +# No warranty or expression of effectiveness, least of all regarding +# anyone's safety, is implied in this software or documentation. +# +# This specific module is licensed under the Perl Artistic License. +# +#======================================================================= +package PDF::API2::Basic::PDF::Name; + +use base 'PDF::API2::Basic::PDF::String'; + +use strict; + +our $VERSION = '2.033'; # VERSION + +#line 35 + +sub from_pdf { + my ($class, $string, $pdf) = @_; + my ($self) = $class->SUPER::from_pdf($string); + + $self->{'val'} = name_to_string($self->{'val'}, $pdf); + return $self; +} + +#line 50 + +sub convert { + my ($self, $string, $pdf) = @_; + + $string = name_to_string($string, $pdf); + return $string; +} + +#line 64 + +sub as_pdf { + my ($self, $pdf) = @_; + my $string = $self->{'val'}; + + $string = string_to_name($string, $pdf); + return '/' . $string; +} + + +# Prior to PDF version 1.2, '#' was a literal character. Embedded +# spaces were implicitly allowed in names as well but it would be best +# to ignore that (PDF 1.3, section H.3.2.4.3). + +#line 84 + +sub string_to_name { + my ($string, $pdf) = @_; + + # PDF 1.0 and 1.1 didn't treat the # symbol as an escape character + unless ($pdf and $pdf->{' version'} and $pdf->{' version'} < 2) { + $string =~ s|([\x00-\x20\x7f-\xff%()\[\]{}<>#/])|'#' . sprintf('%02X', ord($1))|oge; + } + + return $string; +} + +#line 103 + +sub name_to_string { + my ($string, $pdf) = @_; + $string =~ s|^/||o; + + # PDF 1.0 and 1.1 didn't treat the # symbol as an escape character + unless ($pdf and $pdf->{' version'} and $pdf->{' version'} < 2) { + $string =~ s/#([0-9a-f]{2})/chr(hex($1))/oige; + } + + return $string; +} + +1; diff --git a/lib/PDF/API2/Basic/PDF/Null.pm b/lib/PDF/API2/Basic/PDF/Null.pm new file mode 100644 index 0000000..2d20c61 --- /dev/null +++ b/lib/PDF/API2/Basic/PDF/Null.pm @@ -0,0 +1,65 @@ +#line 1 "PDF/API2/Basic/PDF/Null.pm" +#line 1 "PDF/API2/Basic/PDF/Null.pm" +#======================================================================= +# +# THIS IS A REUSED PERL MODULE, FOR PROPER LICENCING TERMS SEE BELOW: +# +# Copyright Martin Hosken <Martin_Hosken@sil.org> +# +# No warranty or expression of effectiveness, least of all regarding +# anyone's safety, is implied in this software or documentation. +# +# This specific module is licensed under the Perl Artistic License. +# +#======================================================================= +package PDF::API2::Basic::PDF::Null; + +use base 'PDF::API2::Basic::PDF::Objind'; + +use strict; + +our $VERSION = '2.033'; # VERSION + +#line 29 + +# There is only one null object (section 3.2.8). +my $null_obj = bless {}, 'PDF::API2::Basic::PDF::Null'; + +#line 38 + +sub new { + return $null_obj; +} + +#line 48 + +sub realise { + return $null_obj; +} + +#line 58 + +sub outobjdeep { + my ($self, $fh, $pdf) = @_; + $fh->print('null'); +} + +#line 69 + +sub is_obj { + return 0; +} + +#line 79 + +sub copy { + return $null_obj; +} + +#line 89 + +sub val { + return undef; ## no critic (undef is intentional) +} + +1; diff --git a/lib/PDF/API2/Basic/PDF/Number.pm b/lib/PDF/API2/Basic/PDF/Number.pm new file mode 100644 index 0000000..eafa32c --- /dev/null +++ b/lib/PDF/API2/Basic/PDF/Number.pm @@ -0,0 +1,35 @@ +#line 1 "PDF/API2/Basic/PDF/Number.pm" +#line 1 "PDF/API2/Basic/PDF/Number.pm" +#======================================================================= +# +# THIS IS A REUSED PERL MODULE, FOR PROPER LICENCING TERMS SEE BELOW: +# +# Copyright Martin Hosken <Martin_Hosken@sil.org> +# +# No warranty or expression of effectiveness, least of all regarding +# anyone's safety, is implied in this software or documentation. +# +# This specific module is licensed under the Perl Artistic License. +# +#======================================================================= +package PDF::API2::Basic::PDF::Number; + +use base 'PDF::API2::Basic::PDF::String'; + +use strict; + +our $VERSION = '2.033'; # VERSION + +#line 32 + +sub convert { + return $_[1]; +} + +#line 42 + +sub as_pdf { + return $_[0]->{'val'}; +} + +1; diff --git a/lib/PDF/API2/Basic/PDF/Objind.pm b/lib/PDF/API2/Basic/PDF/Objind.pm new file mode 100644 index 0000000..a359e5b --- /dev/null +++ b/lib/PDF/API2/Basic/PDF/Objind.pm @@ -0,0 +1,182 @@ +#line 1 "PDF/API2/Basic/PDF/Objind.pm" +#line 1 "PDF/API2/Basic/PDF/Objind.pm" +#======================================================================= +# +# THIS IS A REUSED PERL MODULE, FOR PROPER LICENCING TERMS SEE BELOW: +# +# Copyright Martin Hosken <Martin_Hosken@sil.org> +# +# No warranty or expression of effectiveness, least of all regarding +# anyone's safety, is implied in this software or documentation. +# +# This specific module is licensed under the Perl Artistic License. +# +#======================================================================= +package PDF::API2::Basic::PDF::Objind; + +use strict; +use warnings; + +our $VERSION = '2.033'; # VERSION + +#line 62 + +use Scalar::Util qw(blessed reftype weaken); + +use vars qw($uidc @inst %inst); +$uidc = "pdfuid000"; + +# protected keys during emptying and copying, etc. +@inst = qw(parent objnum objgen isfree nextfree uid realised); +$inst{" $_"} = 1 for @inst; + +#line 77 + +sub new { + my ($class) = @_; + + bless {}, ref $class || $class; +} + +#line 89 + +sub uid { + $_[0]->{' uid'} || ($_[0]->{' uid'} = $uidc++); +} + +#line 109 + +# Maintainer's Question: Couldn't this be handled by a DESTROY method +# instead of requiring an explicit call to release()? +sub release { + my ($self) = @_; + + my @tofree = values %$self; + %$self = (); + + while (my $item = shift @tofree) { + # common case: value is not reference + my $ref = ref($item) || next; + + if (blessed($item) and $item->can('release')) { + $item->release(); + } + elsif ($ref eq 'ARRAY') { + push @tofree, @$item; + } + elsif (defined(reftype($ref)) and reftype($ref) eq 'HASH') { + release($item); + } + } +} + +#line 143 + +sub val { + my ($self) = @_; + + $self->{' parent'}->read_obj(@_)->val unless $self->{' realised'}; +} + +#line 155 + +sub realise { + $_[0]->{' realised'} ? $_[0] : $_[0]->{' objnum'} ? $_[0]->{' parent'}->read_obj(@_) : $_[0]; +} + +#line 166 + +sub outobjdeep { + my ($self, $fh, $pdf, %opts) = @_; + + $self->{' parent'}->read_obj($self)->outobjdeep($fh, $pdf, %opts) unless $self->{' realised'}; +} + +#line 179 + +sub outobj { + my ($self, $fh, $pdf, %opts) = @_; + + if (defined $pdf->{' objects'}{$self->uid}) { + $fh->printf("%d %d R", @{$pdf->{' objects'}{$self->uid}}[0..1]); + } + else { + $self->outobjdeep($fh, $pdf, %opts); + } +} + +#line 197 + +sub elementsof { + my ($self) = @_; + + if ($self->{' realised'}) { + return $self; + } + else { + return $self->{' parent'}->read_obj($self)->elementsof; + } +} + + +#line 217 + +sub empty { + my ($self) = @_; + + for my $k (keys %$self) { + undef $self->{$k} unless $inst{$k}; + } + + return $self; +} + + +#line 237 + +sub merge { + my ($self, $other) = @_; + + for my $k (keys %$other) { + next if $inst{$k}; + $self->{$k} = $other->{$k}; + + # This doesn't seem like the right place to do this, but I haven't + # yet found all of the places where Parent is being set + weaken $self->{$k} if $k eq 'Parent'; + } + $self->{' realised'} = 1; + bless $self, ref($other); +} + + +#line 261 + +sub is_obj { + return defined $_[1]->{' objects'}{$_[0]->uid}; +} + + +#line 282 + +sub copy { + my ($self, $pdf, $res) = @_; + + unless (defined $res) { + $res = {}; + bless $res, ref($self); + } + foreach my $k (keys %$self) { + next if $inst{$k}; + next if defined $res->{$k}; + if (blessed($self->{$k}) and $self->{$k}->can('is_obj') and not $self->{$k}->is_obj($pdf)) { + $res->{$k} = $self->{$k}->copy($pdf); + } + else { + $res->{$k} = $self->{$k}; + } + } + return $res; +} + +1; diff --git a/lib/PDF/API2/Basic/PDF/Page.pm b/lib/PDF/API2/Basic/PDF/Page.pm new file mode 100644 index 0000000..a9a834f --- /dev/null +++ b/lib/PDF/API2/Basic/PDF/Page.pm @@ -0,0 +1,80 @@ +#line 1 "PDF/API2/Basic/PDF/Page.pm" +#line 1 "PDF/API2/Basic/PDF/Page.pm" +#======================================================================= +# +# THIS IS A REUSED PERL MODULE, FOR PROPER LICENCING TERMS SEE BELOW: +# +# Copyright Martin Hosken <Martin_Hosken@sil.org> +# +# No warranty or expression of effectiveness, least of all regarding +# anyone's safety, is implied in this software or documentation. +# +# This specific module is licensed under the Perl Artistic License. +# +#======================================================================= +package PDF::API2::Basic::PDF::Page; + +use base 'PDF::API2::Basic::PDF::Pages'; + +use strict; +no warnings qw[ deprecated recursion uninitialized ]; + +our $VERSION = '2.033'; # VERSION + +use PDF::API2::Basic::PDF::Dict; +use PDF::API2::Basic::PDF::Utils; + +#line 66 + +sub new +{ + my ($class, $pdf, $parent, $index) = @_; + my ($self) = {}; + + $class = ref $class if ref $class; + $self = $class->SUPER::new($pdf, $parent); + $self->{'Type'} = PDFName('Page'); + delete $self->{'Count'}; + delete $self->{'Kids'}; + $parent->add_page($self, $index); + $self; +} + + +#line 91 + +sub add +{ + my ($self, $str) = @_; + my ($strm) = $self->{' curstrm'}; + + if (!defined $strm) + { + $strm = PDF::API2::Basic::PDF::Dict->new; + foreach (@{$self->{' outto'}}) + { $_->new_obj($strm); } + $self->{'Contents'} = PDFArray() unless defined $self->{'Contents'}; + unless (ref $self->{'Contents'} eq "PDF::API2::Basic::PDF::Array") + { $self->{'Contents'} = PDFArray($self->{'Contents'}); } + $self->{'Contents'}->add_elements($strm); + $self->{' curstrm'} = $strm; + } + + $strm->{' stream'} .= $str; + $self; +} + + +#line 119 + +sub ship_out +{ + my ($self, $pdf) = @_; + + $pdf->ship_out($self); + if (defined $self->{'Contents'}) + { $pdf->ship_out($self->{'Contents'}->elementsof); } + $self; +} + +1; diff --git a/lib/PDF/API2/Basic/PDF/Pages.pm b/lib/PDF/API2/Basic/PDF/Pages.pm new file mode 100644 index 0000000..4950012 --- /dev/null +++ b/lib/PDF/API2/Basic/PDF/Pages.pm @@ -0,0 +1,356 @@ +#line 1 "PDF/API2/Basic/PDF/Pages.pm" +#line 1 "PDF/API2/Basic/PDF/Pages.pm" +#======================================================================= +# +# THIS IS A REUSED PERL MODULE, FOR PROPER LICENCING TERMS SEE BELOW: +# +# Copyright Martin Hosken <Martin_Hosken@sil.org> +# +# No warranty or expression of effectiveness, least of all regarding +# anyone's safety, is implied in this software or documentation. +# +# This specific module is licensed under the Perl Artistic License. +# +#======================================================================= +package PDF::API2::Basic::PDF::Pages; + +use strict; +no warnings qw[ deprecated recursion uninitialized ]; + +use base 'PDF::API2::Basic::PDF::Dict'; + +our $VERSION = '2.033'; # VERSION + +use PDF::API2::Basic::PDF::Array; +use PDF::API2::Basic::PDF::Dict; +use PDF::API2::Basic::PDF::Utils; + +use Scalar::Util qw(weaken); + +our %inst = map {$_ => 1} qw(Parent Type); + +#line 51 + +sub new +{ + my ($class, $pdfs, $parent) = @_; + my ($self); + + $class = ref $class if ref $class; + $self = $class->SUPER::new($pdfs, $parent); + $self->{'Type'} = PDFName("Pages"); + $self->{'Parent'} = $parent if defined $parent; + $self->{'Count'} = PDFNum(0); + $self->{'Kids'} = PDF::API2::Basic::PDF::Array->new; + $self->{' outto'} = ref $pdfs eq 'ARRAY' ? $pdfs : [$pdfs]; + $self->out_obj(1); + + weaken $_ for @{$self->{' outto'}}; + weaken $self->{'Parent'} if defined $parent; + + $self; +} + + +sub init +{ + my ($self, $pdf) = @_; + $self->{' outto'} = [$pdf]; + weaken $self->{' outto'}->[0] if defined $pdf; + $self; +} + +#line 90 + +sub out_obj +{ + my ($self, $isnew) = @_; + + foreach (@{$self->{' outto'}}) + { + if ($isnew) + { $_->new_obj($self); } + else + { $_->out_obj($self); } + + unless (defined $self->{'Parent'}) + { + $_->{'Root'}{'Pages'} = $self; + $_->out_obj($_->{'Root'}); + } + } + $self; +} + + +#line 118 + +sub find_page +{ + my ($self, $pnum) = @_; + my ($top) = $self->get_top; + + $top->find_page_recurse(\$pnum); +} + + +sub find_page_recurse +{ + my ($self, $rpnum) = @_; + my $res; + + if ($self->{'Count'}->realise->val <= $$rpnum) + { + $$rpnum -= $self->{'Count'}->val; + return; + } + + foreach my $k ($self->{'Kids'}->realise->elementsof) + { + if ($k->{'Type'}->realise->val eq 'Page') + { + return $k if ($$rpnum == 0); + $$rpnum--; + } + elsif ($res = $k->realise->find_page_recurse($rpnum)) + { return $res; } + } + return; +} + +#line 165 + +sub add_page +{ + my ($self, $page, $pnum) = @_; + my ($top) = $self->get_top; + my ($ppage, $ppages, $pindex, $ppnum); + + $pnum = -1 unless (defined $pnum && $pnum <= $top->{'Count'}->val); + if ($pnum == -1) + { $ppage = $top->find_page($top->{'Count'}->val - 1); } + else + { + $pnum = $top->{'Count'}->val + $pnum + 1 if ($pnum < 0); + $ppage = $top->find_page($pnum); + } + + if (defined $ppage->{'Parent'}) + { $ppages = $ppage->{'Parent'}->realise; } + else + { $ppages = $self; } + + $ppnum = scalar $ppages->{'Kids'}->realise->elementsof; + + if ($pnum == -1) + { $pindex = -1; } + else + { + for ($pindex = 0; $pindex < $ppnum; $pindex++) + { last if ($ppages->{'Kids'}{' val'}[$pindex] eq $ppage); } + $pindex = -1 if ($pindex == $ppnum); + } + + $ppages->add_page_recurse($page->realise, $pindex); + for ($ppages = $page->{'Parent'}; defined $ppages->{'Parent'}; $ppages = $ppages->{'Parent'}->realise) + { $ppages->out_obj->{'Count'}->realise->{'val'}++; } + $ppages->out_obj->{'Count'}->realise->{'val'}++; + $page; +} + + +sub add_page_recurse +{ + my ($self, $page, $index) = @_; + my ($newpages, $ppages, $pindex, $ppnum); + + if (scalar $self->{'Kids'}->elementsof >= 8 && $self->{'Parent'} && $index < 1) + { + $ppages = $self->{'Parent'}->realise; + $newpages = $self->new($self->{' outto'}, $ppages); + if ($ppages) + { + $ppnum = scalar $ppages->{'Kids'}->realise->elementsof; + for ($pindex = 0; $pindex < $ppnum; $pindex++) + { last if ($ppages->{'Kids'}{' val'}[$pindex] eq $self); } + $pindex = -1 if ($pindex == $ppnum); + $ppages->add_page_recurse($newpages, $pindex); + } + } + else + { $newpages = $self->out_obj; } + + if ($index < 0) + { push (@{$newpages->{'Kids'}->realise->{' val'}}, $page); } + else + { splice (@{$newpages->{'Kids'}{' val'}}, $index, 0, $page); } + $page->{'Parent'} = $newpages; + weaken $page->{'Parent'}; +} + + +#line 244 + +sub rebuild_tree +{ + my ($self, @pglist) = @_; +} + + +#line 256 + +sub get_pages +{ + my ($self) = @_; + + return $self->get_top->get_kids; +} + + +# only call this on the top level or anything you want pages below +sub get_kids +{ + my ($self) = @_; + my @pglist; + + foreach my $pgref ($self->{'Kids'}->elementsof) + { + $pgref->realise; + if ($pgref->{'Type'}->val =~ m/^Pages$/oi) + { push (@pglist, $pgref->get_kids()); } + else + { push (@pglist, $pgref); } + } + @pglist; +} + +#line 287 + +sub find_prop +{ + my ($self, $prop) = @_; + + if (defined $self->{$prop}) + { + if (ref $self->{$prop} && $self->{$prop}->isa("PDF::API2::Basic::PDF::Objind")) + { return $self->{$prop}->realise; } + else + { return $self->{$prop}; } + } elsif (defined $self->{'Parent'}) + { return $self->{'Parent'}->find_prop($prop); } + return; +} + + +#line 310 + +sub add_font +{ + my ($self, $font, $pdf) = @_; + my ($name) = $font->{'Name'}->val; + my ($dict) = $self->find_prop('Resources'); + my ($rdict); + + return $self if ($dict ne "" && defined $dict->{'Font'} && defined $dict->{'Font'}{$name}); + unless (defined $self->{'Resources'}) + { + $dict = $dict ne "" ? $dict->copy($pdf) : PDFDict(); + $self->{'Resources'} = $dict; + } + else + { $dict = $self->{'Resources'}; } + $dict->{'Font'} = PDFDict() unless defined $self->{'Resources'}{'Font'}; + $rdict = $dict->{'Font'}->val; + $rdict->{$name} = $font unless ($rdict->{$name}); + if (ref $dict ne 'HASH' && $dict->is_obj($pdf)) + { $pdf->out_obj($dict); } + if (ref $rdict ne 'HASH' && $rdict->is_obj($pdf)) + { $pdf->out_obj($rdict); } + $self; +} + + +#line 344 + +sub bbox +{ + my ($self, @bbox) = @_; + my ($str) = $bbox[4] || 'MediaBox'; + my ($inh) = $self->find_prop($str); + my ($test, $i); + + if ($inh ne "") + { + $test = 1; $i = 0; + foreach my $e ($inh->elementsof) + { $test &= $e->val == $bbox[$i++]; } + return $self if $test && $i == 4; + } + + $inh = PDF::API2::Basic::PDF::Array->new; + foreach my $e (@bbox[0..3]) + { $inh->add_elements(PDFNum($e)); } + $self->{$str} = $inh; + $self; +} + + +#line 374 + +sub proc_set +{ + my ($self, @entries) = @_; + my (@temp) = @entries; + my $dict; + + $dict = $self->find_prop('Resource'); + if ($dict ne "" && defined $dict->{'ProcSet'}) + { + foreach my $e ($dict->{'ProcSet'}->elementsof) + { @temp = grep($_ ne $e, @temp); } + return $self if (scalar @temp == 0); + @entries = @temp if defined $self->{'Resources'}; + } + + unless (defined $self->{'Resources'}) + { $self->{'Resources'} = $dict ne "" ? $dict->copy : PDFDict(); } + + $self->{'Resources'}{'ProcSet'} = PDFArray() unless defined $self->{'ProcSet'}; + + foreach my $e (@entries) + { $self->{'Resources'}{'ProcSet'}->add_elements(PDFName($e)); } + $self; +} + +sub empty +{ + my ($self) = @_; + my $parent = $self->{'Parent'}; + + $self->SUPER::empty; + if (defined $parent) { + $self->{'Parent'} = $parent; + weaken $self->{'Parent'}; + } + + $self; +} + +sub dont_copy +{ return $inst{$_[1]} || $_[0]->SUPER::dont_copy($_[1]); } + + +#line 423 + +sub get_top +{ + my ($self) = @_; + my ($p); + + for ($p = $self; defined $p->{'Parent'}; $p = $p->{'Parent'}) + { } + + $p->realise; +} + +1; diff --git a/lib/PDF/API2/Basic/PDF/String.pm b/lib/PDF/API2/Basic/PDF/String.pm new file mode 100644 index 0000000..36e51d1 --- /dev/null +++ b/lib/PDF/API2/Basic/PDF/String.pm @@ -0,0 +1,188 @@ +#line 1 "PDF/API2/Basic/PDF/String.pm" +#line 1 "PDF/API2/Basic/PDF/String.pm" +#======================================================================= +# +# THIS IS A REUSED PERL MODULE, FOR PROPER LICENCING TERMS SEE BELOW: +# +# Copyright Martin Hosken <Martin_Hosken@sil.org> +# +# No warranty or expression of effectiveness, least of all regarding +# anyone's safety, is implied in this software or documentation. +# +# This specific module is licensed under the Perl Artistic License. +# +#======================================================================= +package PDF::API2::Basic::PDF::String; + +use base 'PDF::API2::Basic::PDF::Objind'; + +use strict; + +our $VERSION = '2.033'; # VERSION + +#line 29 + +our %trans = ( + 'n' => "\n", + 'r' => "\r", + 't' => "\t", + 'b' => "\b", + 'f' => "\f", + "\\" => "\\", + '(' => '(', + ')' => ')', +); + +our %out_trans = ( + "\n" => 'n', + "\r" => 'r', + "\t" => 't', + "\b" => 'b', + "\f" => 'f', + "\\" => "\\", + '(' => '(', + ')' => ')', +); + +#line 59 + +sub from_pdf { + my ($class, $str) = @_; + my $self = {}; + + bless $self, $class; + $self->{'val'} = $self->convert($str); + $self->{' realised'} = 1; + return $self; +} + +#line 77 + +sub new { + my ($class, $str) = @_; + my $self = {}; + + bless $self, $class; + $self->{'val'} = $str; + $self->{' realised'} = 1; + return $self; +} + +#line 93 + +sub convert { + my ($self, $input) = @_; + my $output = ''; + + # Hexadecimal Strings (PDF 1.7 section 7.3.4.3) + if ($input =~ m|^\s*\<|o) { + $self->{' ishex'} = 1; + $output = $input; + + # Remove any extraneous characters to simplify processing + $output =~ s/[^0-9a-f]+//gio; + $output = "<$output>"; + + # Convert each sequence of two hexadecimal characters into a byte + 1 while $output =~ s/\<([0-9a-f]{2})/chr(hex($1)) . '<'/oige; + + # If a single hexadecimal character remains, append 0 and + # convert it into a byte. + $output =~ s/\<([0-9a-f])\>/chr(hex($1 . '0'))/oige; + + # Remove surrounding angle brackets + $output =~ s/\<\>//og; + } + + # Literal Strings (PDF 1.7 section 7.3.4.2) + else { + # Remove surrounding parentheses + $input =~ s/^\s*\((.*)\)\s*$/$1/os; + + my $cr = '(?:\015\012|\015|\012)'; + my $prev_input; + while ($input) { + if (defined $prev_input and $input eq $prev_input) { + die "Infinite loop while parsing literal string"; + } + $prev_input = $input; + + # Convert bachslash followed by up to three octal digits + # into that binary byte + if ($input =~ /^\\([0-7]{1,3})(.*)/os) { + $output .= chr(oct($1)); + $input = $2; + } + # Convert backslash followed by an escaped character into that + # character + elsif ($input =~ /^\\([nrtbf\\\(\)])(.*)/osi) { + $output .= $trans{$1}; + $input = $2; + } + # Ignore backslash followed by an end-of-line marker + elsif ($input =~ /^\\$cr(.*)/os) { + $input = $1; + } + # Convert an unescaped end-of-line marker to a line-feed + elsif ($input =~ /^\015\012?(.*)/os) { + $output .= "\012"; + $input = $1; + } + # Check to see if there are any other special sequences + elsif ($input =~ /^(.*?)((?:\\(?:[nrtbf\\\(\)0-7]|$cr)|\015\012?).*)/os) { + $output .= $1; + $input = $2; + } + else { + $output .= $input; + $input = undef; + } + } + } + + return $output; +} + + +#line 173 + +sub val { + return $_[0]->{'val'}; +} + + +#line 184 + +sub as_pdf { + my ($self) = @_; + my $str = $self->{'val'}; + + if ($self->{' isutf'}) { + $str = join('', map { sprintf('%04X' , $_) } unpack('U*', $str) ); + return "<FEFF$str>"; + } + elsif ($self->{' ishex'}) { # imported as hex ? + $str = unpack('H*', $str); + return "<$str>"; + } + else { + if ($str =~ m/[^\n\r\t\b\f\040-\176\200-\377]/oi) { + $str =~ s/(.)/sprintf('%02X', ord($1))/oge; + return "<$str>"; + } + else { + $str =~ s/([\n\r\t\b\f\\()])/\\$out_trans{$1}/ogi; + return "($str)"; + } + } +} + +#line 214 + +sub outobjdeep { + my ($self, $fh, $pdf, %opts) = @_; + + $fh->print($self->as_pdf($pdf)); +} + +1; diff --git a/lib/PDF/API2/Basic/PDF/Utils.pm b/lib/PDF/API2/Basic/PDF/Utils.pm new file mode 100644 index 0000000..b4b6d51 --- /dev/null +++ b/lib/PDF/API2/Basic/PDF/Utils.pm @@ -0,0 +1,96 @@ +#line 1 "PDF/API2/Basic/PDF/Utils.pm" +#line 1 "PDF/API2/Basic/PDF/Utils.pm" +#======================================================================= +# +# THIS IS A REUSED PERL MODULE, FOR PROPER LICENCING TERMS SEE BELOW: +# +# Copyright Martin Hosken <Martin_Hosken@sil.org> +# +# No warranty or expression of effectiveness, least of all regarding +# anyone's safety, is implied in this software or documentation. +# +# This specific module is licensed under the Perl Artistic License. +# +#======================================================================= +package PDF::API2::Basic::PDF::Utils; + +use strict; + +our $VERSION = '2.033'; # VERSION + +#line 30 + +use PDF::API2::Basic::PDF::Array; +use PDF::API2::Basic::PDF::Bool; +use PDF::API2::Basic::PDF::Dict; +use PDF::API2::Basic::PDF::Name; +use PDF::API2::Basic::PDF::Null; +use PDF::API2::Basic::PDF::Number; +use PDF::API2::Basic::PDF::String; +use PDF::API2::Basic::PDF::Literal; + +use Exporter; +use vars qw(@EXPORT @ISA); +@ISA = qw(Exporter); +@EXPORT = qw(PDFBool PDFArray PDFDict PDFName PDFNull + PDFNum PDFStr PDFStrHex PDFUtf); + +#line 51 + +sub PDFBool { + return PDF::API2::Basic::PDF::Bool->new(@_); +} + +#line 61 + +sub PDFArray { + return PDF::API2::Basic::PDF::Array->new(@_); +} + +#line 71 + +sub PDFDict { + return PDF::API2::Basic::PDF::Dict->new(@_); +} + +#line 81 + +sub PDFName { + return PDF::API2::Basic::PDF::Name->new(@_); +} + +#line 91 + +sub PDFNull { + return PDF::API2::Basic::PDF::Null->new(@_); +} + +#line 101 + +sub PDFNum { + return PDF::API2::Basic::PDF::Number->new(@_); +} + +#line 111 + +sub PDFStr { + return PDF::API2::Basic::PDF::String->new(@_); +} + +#line 121 + +sub PDFStrHex { + my $string = PDF::API2::Basic::PDF::String->new(@_); + $string->{' ishex'} = 1; + return $string; +} + +#line 133 + +sub PDFUtf { + my $string = PDF::API2::Basic::PDF::String->new(@_); + $string->{' isutf'} = 1; + return $string; +} + +1; diff --git a/lib/PDF/API2/Content.pm b/lib/PDF/API2/Content.pm new file mode 100644 index 0000000..b0b3b84 --- /dev/null +++ b/lib/PDF/API2/Content.pm @@ -0,0 +1,1652 @@ +#line 1 "PDF/API2/Content.pm" +#line 1 "PDF/API2/Content.pm" +package PDF::API2::Content; + +use base 'PDF::API2::Basic::PDF::Dict'; + +use strict; +no warnings qw( deprecated recursion uninitialized ); + +our $VERSION = '2.033'; # VERSION + +use Carp; +use Compress::Zlib qw(); +use Encode; +use Math::Trig; +use PDF::API2::Matrix; + +use PDF::API2::Basic::PDF::Utils; +use PDF::API2::Util; + +#line 38 + +sub new { + my ($class)=@_; + my $self = $class->SUPER::new(@_); + $self->{' stream'}=''; + $self->{' poststream'}=''; + $self->{' font'}=undef; + $self->{' fontset'}=0; + $self->{' fontsize'}=0; + $self->{' charspace'}=0; + $self->{' hscale'}=100; + $self->{' wordspace'}=0; + $self->{' lead'}=0; + $self->{' rise'}=0; + $self->{' render'}=0; + $self->{' matrix'}=[1,0,0,1,0,0]; + $self->{' textmatrix'}=[1,0,0,1,0,0]; + $self->{' textlinematrix'}=[0,0]; + $self->{' fillcolor'}=[0]; + $self->{' strokecolor'}=[0]; + $self->{' translate'}=[0,0]; + $self->{' scale'}=[1,1]; + $self->{' skew'}=[0,0]; + $self->{' rotate'}=0; + $self->{' apiistext'}=0; + return $self; +} + +sub outobjdeep { + my $self = shift @_; + $self->textend; + foreach my $k (qw[ api apipdf apiistext apipage font fontset fontsize + charspace hscale wordspace lead rise render matrix + textmatrix textlinematrix fillcolor strokecolor + translate scale skew rotate ]) { + $self->{" $k"}=undef; + delete($self->{" $k"}); + } + if ($self->{-docompress}==1 && $self->{Filter}) { + $self->{' stream'}=Compress::Zlib::compress($self->{' stream'}); + $self->{' nofilt'}=1; + delete $self->{-docompress}; + } + $self->SUPER::outobjdeep(@_); +} + +#line 101 + +sub _translate { + my ($x,$y)=@_; + return(1,0,0,1,$x,$y); +} + +sub translate { + my ($self,$x,$y)=@_; + $self->transform(-translate=>[$x,$y]); +} + +#line 119 + +sub _rotate { + my ($a)=@_; + return (cos(deg2rad($a)), sin(deg2rad($a)),-sin(deg2rad($a)), cos(deg2rad($a)),0,0); +} + +sub rotate { + my ($self,$a)=@_; + $self->transform(-rotate=>$a); +} + +#line 135 + +sub _scale { + my ($x,$y)=@_; + return ($x,0,0,$y,0,0); +} + +sub scale { + my ($self,$sx,$sy)=@_; + $self->transform(-scale=>[$sx,$sy]); +} + +#line 152 + +sub _skew { + my ($a,$b)=@_; + return (1, tan(deg2rad($a)),tan(deg2rad($b)),1,0,0); +} + +sub skew { + my ($self,$a,$b)=@_; + $self->transform(-skew=>[$a,$b]); +} + +#line 179 + +sub _transform { + my (%opt)=@_; + my $mtx=PDF::API2::Matrix->new([1,0,0],[0,1,0],[0,0,1]); + foreach my $o (qw( -matrix -skew -scale -rotate -translate )) { + next unless(defined($opt{$o})); + if ($o eq '-translate') { + my @mx=_translate(@{$opt{$o}}); + $mtx=$mtx->multiply(PDF::API2::Matrix->new( + [$mx[0],$mx[1],0], + [$mx[2],$mx[3],0], + [$mx[4],$mx[5],1] + )); + } + elsif ($o eq '-rotate') { + my @mx=_rotate($opt{$o}); + $mtx=$mtx->multiply(PDF::API2::Matrix->new( + [$mx[0],$mx[1],0], + [$mx[2],$mx[3],0], + [$mx[4],$mx[5],1] + )); + } + elsif ($o eq '-scale') { + my @mx=_scale(@{$opt{$o}}); + $mtx=$mtx->multiply(PDF::API2::Matrix->new( + [$mx[0],$mx[1],0], + [$mx[2],$mx[3],0], + [$mx[4],$mx[5],1] + )); + } + elsif ($o eq '-skew') { + my @mx=_skew(@{$opt{$o}}); + $mtx=$mtx->multiply(PDF::API2::Matrix->new( + [$mx[0],$mx[1],0], + [$mx[2],$mx[3],0], + [$mx[4],$mx[5],1] + )); + } + elsif ($o eq '-matrix') { + my @mx=@{$opt{$o}}; + $mtx=$mtx->multiply(PDF::API2::Matrix->new( + [$mx[0],$mx[1],0], + [$mx[2],$mx[3],0], + [$mx[4],$mx[5],1] + )); + } + } + if ($opt{-point}) { + my $mp=PDF::API2::Matrix->new([$opt{-point}->[0],$opt{-point}->[1],1]); + $mp=$mp->multiply($mtx); + return($mp->[0][0],$mp->[0][1]); + } + return ( + $mtx->[0][0],$mtx->[0][1], + $mtx->[1][0],$mtx->[1][1], + $mtx->[2][0],$mtx->[2][1] + ); +} + +sub transform { + my ($self,%opt)=@_; + $self->matrix(_transform(%opt)); + if ($opt{-translate}) { + @{$self->{' translate'}}=@{$opt{-translate}}; + } + else { + @{$self->{' translate'}}=(0,0); + } + if ($opt{-rotate}) { + $self->{' rotate'}=$opt{-rotate}; + } + else { + $self->{' rotate'}=0; + } + if ($opt{-scale}) { + @{$self->{' scale'}}=@{$opt{-scale}}; + } + else { + @{$self->{' scale'}}=(1,1); + } + if ($opt{-skew}) { + @{$self->{' skew'}}=@{$opt{-skew}}; + } + else { + @{$self->{' skew'}}=(0,0); + } + return $self; +} + +#line 274 + +sub transform_rel { + my ($self,%opt)=@_; + my ($sa1,$sb1)=@{$opt{-skew} ? $opt{-skew} : [0,0]}; + my ($sa0,$sb0)=@{$self->{" skew"}}; + + my ($sx1,$sy1)=@{$opt{-scale} ? $opt{-scale} : [1,1]}; + my ($sx0,$sy0)=@{$self->{" scale"}}; + + my $rot1=$opt{"-rotate"} || 0; + my $rot0=$self->{" rotate"}; + + my ($tx1,$ty1)=@{$opt{-translate} ? $opt{-translate} : [0,0]}; + my ($tx0,$ty0)=@{$self->{" translate"}}; + + $self->transform( + -skew=>[$sa0+$sa1,$sb0+$sb1], + -scale=>[$sx0*$sx1,$sy0*$sy1], + -rotate=>$rot0+$rot1, + -translate=>[$tx0+$tx1,$ty0+$ty1], + ); + return $self; +} + +#line 305 + +sub _matrix_text { + my ($a,$b,$c,$d,$e,$f)=@_; + return (floats($a,$b,$c,$d,$e,$f),'Tm'); +} + +sub _matrix_gfx { + my ($a,$b,$c,$d,$e,$f)=@_; + return (floats($a,$b,$c,$d,$e,$f),'cm'); +} + +sub matrix { + my $self=shift @_; + my ($a,$b,$c,$d,$e,$f)=@_; + if (defined $a) { + if ($self->_in_text_object()) { + $self->add(_matrix_text($a,$b,$c,$d,$e,$f)); + @{$self->{' textmatrix'}}=($a,$b,$c,$d,$e,$f); + @{$self->{' textlinematrix'}}=(0,0); + } + else { + $self->add(_matrix_gfx($a,$b,$c,$d,$e,$f)); + } + } + if ($self->_in_text_object()) { + return @{$self->{' textmatrix'}}; + } + else { + return $self; + } +} + +sub matrix_update { + my ($self,$tx,$ty)=@_; + $self->{' textlinematrix'}->[0]+=$tx; + $self->{' textlinematrix'}->[1]+=$ty; + return $self; +} + +#line 355 + +sub _save { + return 'q'; +} + +sub save { + my $self = shift; + unless ($self->_in_text_object()) { + $self->add(_save()); + } +} + +#line 373 + +sub _restore { + return 'Q'; +} + +sub restore { + my $self = shift; + unless ($self->_in_text_object()) { + $self->add(_restore()); + } +} + +#line 390 + +sub _linewidth { + my ($linewidth)=@_; + return ($linewidth, 'w'); +} +sub linewidth { + my ($this,$linewidth)=@_; + $this->add(_linewidth($linewidth)); +} + +#line 422 + +sub _linecap { + my ($linecap)=@_; + return ($linecap, 'J'); +} + +sub linecap { + my ($self,$linecap)=@_; + $self->add(_linecap($linecap)); +} + +#line 457 + +sub _linejoin { + my ($linejoin)=@_; + return ($linejoin, 'j'); +} +sub linejoin { + my ($this,$linejoin)=@_; + $this->add(_linejoin($linejoin)); +} + +#line 480 + +sub miterlimit { + my ($self, $limit) = @_; + $self->add(_miterlimit($limit)); +} + +sub _miterlimit { + my ($limit) = @_; + return ($limit, 'M'); +} + +# Deprecated: miterlimit was originally named incorrectly +sub meterlimit { return miterlimit(@_) } +sub _meterlimit { return _miterlimit(@_) } + +#line 517 + +sub _linedash { + my @a = @_; + unless (scalar @a) { + return ('[', ']', '0', 'd'); + } + else { + if ($a[0] =~ /^\-/) { + my %a = @a; + + # Deprecated: the -full and -clear options will be removed in a future release + $a{'-pattern'} = [$a{'-full'} || 0, $a{'-clear'} || 0] unless exists $a{'-pattern'}; + + return ('[', floats(@{$a{'-pattern'}}), ']', ($a{'-shift'} || 0), 'd'); + } + else { + return ('[', floats(@a), '] 0 d'); + } + } +} + +sub linedash { + my ($self,@a)=@_; + $self->add(_linedash(@a)); +} + +#line 549 + +sub _flatness { + my ($flatness)=@_; + return ($flatness, 'i'); +} + +sub flatness { + my ($self,$flatness)=@_; + $self->add(_flatness($flatness)); +} + +#line 566 + +sub egstate { + my $self = shift; + my $egs = shift; + $self->add('/'.$egs->name,'gs'); + $self->resource('ExtGState',$egs->name,$egs); + return $self; +} + +#line 586 + +sub _move { + my($x,$y)=@_; + return (floats($x,$y), 'm'); +} +sub move { + my $self=shift @_; + my ($x,$y); + while(defined($x = shift)) { + $y = shift; + $self->{' x'}=$x; + $self->{' y'}=$y; + $self->{' mx'}=$x; + $self->{' my'}=$y; + if ($self->_in_text_object()) { + $self->add_post(floats($x,$y), 'm'); + } + else { + $self->add(floats($x,$y), 'm'); + } + } + return $self; +} + +#line 619 + +sub _line { + my ($x,$y) = @_; + return (floats($x,$y), 'l'); +} + +sub line { + my $self = shift; + my ($x,$y); + while(defined($x = shift)) { + $y = shift; + $self->{' x'}=$x; + $self->{' y'}=$y; + if ($self->_in_text_object()) { + $self->add_post(floats($x,$y), 'l'); + } + else { + $self->add(floats($x,$y), 'l'); + } + } + return $self; +} + +#line 650 + +sub hline { + my ($self, $x) = @_; + if ($self->_in_text_object()) { + $self->add_post(floats($x,$self->{' y'}),'l'); + } + else { + $self->add(floats($x,$self->{' y'}),'l'); + } + $self->{' x'}=$x; + return $self; +} + +sub vline { + my ($self, $y) = @_; + if ($self->_in_text_object()) { + $self->add_post(floats($self->{' x'},$y),'l'); + } + else { + $self->add(floats($self->{' x'},$y),'l'); + } + $self->{' y'}=$y; + return $self; +} + +#line 681 + +sub poly { + my $self = shift; + my $x = shift; + my $y = shift; + $self->move($x,$y); + $self->line(@_); + return $self; +} + +#line 700 + +sub curve { + my $self = shift; + my($x1,$y1,$x2,$y2,$x3,$y3); + while (defined($x1 = shift)) { + $y1 = shift; + $x2 = shift; + $y2 = shift; + $x3 = shift; + $y3 = shift; + if ($self->_in_text_object()) { + $self->add_post(floats($x1,$y1,$x2,$y2,$x3,$y3),'c'); + } + else { + $self->add(floats($x1,$y1,$x2,$y2,$x3,$y3),'c'); + } + $self->{' x'}=$x3; + $self->{' y'}=$y3; + } + return $self; +} + +#line 731 + +sub spline { + my $self = shift; + + while(scalar @_ >= 4) { + my $cx = shift; + my $cy = shift; + my $x = shift; + my $y = shift; + my $c1x = (2*$cx+$self->{' x'})/3; + my $c1y = (2*$cy+$self->{' y'})/3; + my $c2x = (2*$cx+$x)/3; + my $c2y = (2*$cy+$y)/3; + $self->curve($c1x,$c1y,$c2x,$c2y,$x,$y); + } +} + +#line 759 + +# Private +sub arctocurve { + my ($a,$b,$alpha,$beta) = @_; + if (abs($beta-$alpha) > 30) { + return ( + arctocurve($a,$b,$alpha,($beta+$alpha)/2), + arctocurve($a,$b,($beta+$alpha)/2,$beta) + ); + } + else { + $alpha = ($alpha * pi / 180); + $beta = ($beta * pi / 180); + + my $bcp = (4.0/3 * (1 - cos(($beta - $alpha)/2)) / sin(($beta - $alpha)/2)); + my $sin_alpha = sin($alpha); + my $sin_beta = sin($beta); + my $cos_alpha = cos($alpha); + my $cos_beta = cos($beta); + + my $p0_x = $a * $cos_alpha; + my $p0_y = $b * $sin_alpha; + my $p1_x = $a * ($cos_alpha - $bcp * $sin_alpha); + my $p1_y = $b * ($sin_alpha + $bcp * $cos_alpha); + my $p2_x = $a * ($cos_beta + $bcp * $sin_beta); + my $p2_y = $b * ($sin_beta - $bcp * $cos_beta); + my $p3_x = $a * $cos_beta; + my $p3_y = $b * $sin_beta; + + return ($p0_x,$p0_y,$p1_x,$p1_y,$p2_x,$p2_y,$p3_x,$p3_y); + } +} + +sub arc { + my ($self,$x,$y,$a,$b,$alpha,$beta,$move) = @_; + my @points = arctocurve($a,$b,$alpha,$beta); + my ($p0_x,$p0_y,$p1_x,$p1_y,$p2_x,$p2_y,$p3_x,$p3_y); + + $p0_x= $x + shift @points; + $p0_y= $y + shift @points; + + $self->move($p0_x,$p0_y) if($move); + + while (scalar @points > 0) { + $p1_x = $x + shift @points; + $p1_y = $y + shift @points; + $p2_x = $x + shift @points; + $p2_y = $y + shift @points; + $p3_x = $x + shift @points; + $p3_y = $y + shift @points; + $self->curve($p1_x,$p1_y,$p2_x,$p2_y,$p3_x,$p3_y); + shift @points; + shift @points; + $self->{' x'}=$p3_x; + $self->{' y'}=$p3_y; + } + return $self; +} + +#line 839 + +sub bogen { + my ($self,$x1,$y1,$x2,$y2,$r,$move,$larc,$spf) = @_; + my ($p0_x,$p0_y,$p1_x,$p1_y,$p2_x,$p2_y,$p3_x,$p3_y); + my $x = $x2-$x1; + my $y = $y2-$y1; + my $z = sqrt($x**2+$y**2); + my $alpha_rad = asin($y/$z); + + $alpha_rad+=pi/2 if($x<0 and $y>0); + $alpha_rad-=pi/2 if($x<0 and $y<0); + + my $alpha=rad2deg($alpha_rad); + # use the complement angle for span + $alpha -= 180 if($spf>0); + + my $d=2*$r; + my ($beta,$beta_rad,@points); + + $beta=rad2deg(2*asin($z/$d)); + $beta=360-$beta if($larc>0); + + $beta_rad=deg2rad($beta); + + @points=arctocurve($r,$r,90+$alpha+$beta/2,90+$alpha-$beta/2); + + if ($spf>0) { + my @pts=@points; + @points=(); + while ($y=pop @pts) { + $x=pop @pts; + push(@points,$x,$y); + } + } + + $p0_x=shift @points; + $p0_y=shift @points; + $x=$x1-$p0_x; + $y=$y1-$p0_y; + + $self->move($x1,$y1) if($move); + + while(scalar @points > 0) { + $p1_x= $x + shift @points; + $p1_y= $y + shift @points; + $p2_x= $x + shift @points; + $p2_y= $y + shift @points; + # if we run out of data points, use the end point instead + if (scalar @points == 0) { + $p3_x = $x2; + $p3_y = $y2; + } + else { + $p3_x= $x + shift @points; + $p3_y= $y + shift @points; + } + $self->curve($p1_x,$p1_y,$p2_x,$p2_y,$p3_x,$p3_y); + shift @points; + shift @points; + } + return $self; +} + +#line 908 + +sub close { + my $self = shift; + $self->add('h'); + $self->{' x'}=$self->{' mx'}; + $self->{' y'}=$self->{' my'}; + return $self; +} + +#line 922 + +sub endpath { + my $self = shift; + $self->add('n'); + return $self; +} + +#line 937 + +sub ellipse { + my ($self,$x,$y,$a,$b) = @_; + $self->arc($x,$y,$a,$b,0,360,1); + $self->close; + return $self; +} + +#line 953 + +sub circle { + my ($self,$x,$y,$r) = @_; + $self->arc($x,$y,$r,$r,0,360,1); + $self->close; + return $self; +} + +#line 971 + +sub pie { + my $self = shift; + my ($x,$y,$a,$b,$alpha,$beta)=@_; + my ($p0_x,$p0_y)=arctocurve($a,$b,$alpha,$beta); + $self->move($x,$y); + $self->line($p0_x+$x,$p0_y+$y); + $self->arc($x,$y,$a,$b,$alpha,$beta); + $self->close; +} + +#line 990 + +sub rect { + my $self = shift; + my ($x,$y,$w,$h); + while (defined($x = shift)) { + $y = shift; + $w = shift; + $h = shift; + $self->add(floats($x,$y,$w,$h),'re'); + } + $self->{' x'}=$x; + $self->{' y'}=$y; + return $self; +} + +#line 1013 + +sub rectxy { + my ($self,$x,$y,$x2,$y2)=@_; + $self->rect($x,$y,($x2-$x),($y2-$y)); + return $self; +} + +#line 1031 + +sub _stroke { + return 'S'; +} + +sub stroke { + my $self = shift; + $self->add(_stroke); + return $self; +} + +#line 1054 + +sub fill { + my $self = shift; + $self->add(shift() ? 'f*' : 'f'); + return $self; +} + +#line 1066 + +sub fillstroke { + my $self = shift; + $self->add(shift() ? 'B*' : 'B'); + return $self; +} + +#line 1079 + +sub clip { + my $self = shift; + $self->add(shift() ? 'W*' : 'W'); + return $self; +} + +#line 1112 + +# default colorspaces: rgb/hsv/named cmyk/hsl lab +# ... only one text string +# +# pattern or shading space +# ... only one object +# +# legacy greylevel +# ... only one value +# +# + +sub _makecolor { + my ($self, $sf, @clr) = @_; + + if ($clr[0] =~ /^[a-z\#\!]+/) { + # colorname or #! specifier + # with rgb target colorspace + # namecolor returns always a RGB + return namecolor($clr[0]), ($sf ? 'rg' : 'RG'); + } + elsif ($clr[0] =~ /^[\%]+/) { + # % specifier + # with cmyk target colorspace + return namecolor_cmyk($clr[0]), ($sf ? 'k' : 'K'); + } + elsif ($clr[0] =~ /^[\$\&]/) { + # &$ specifier + # with L*a*b target colorspace + if (!defined $self->resource('ColorSpace', 'LabS')) { + my $dc = PDFDict(); + my $cs = PDFArray(PDFName('Lab'), $dc); + $dc->{'WhitePoint'} = PDFArray(map { PDFNum($_) } qw(1 1 1)); + $dc->{'Range'} = PDFArray(map { PDFNum($_) } qw(-128 127 -128 127)); + $dc->{'Gamma'} = PDFArray(map { PDFNum($_) } qw(2.2 2.2 2.2)); + $self->resource('ColorSpace', 'LabS', $cs); + } + return '/LabS', ($sf ? 'cs' : 'CS'), namecolor_lab($clr[0]), ($sf ? 'sc' : 'SC'); + } + elsif (scalar @clr == 1 and ref($clr[0])) { + # pattern or shading space + return '/Pattern', ($sf ? 'cs' : 'CS'), '/' . ($clr[0]->name()), ($sf ? 'scn' : 'SCN'); + } + elsif (scalar @clr == 1) { + # grey color spec. + return $clr[0], $sf ? 'g' : 'G'; + } + elsif (scalar @clr > 1 and ref($clr[0])) { + # indexed colorspace plus color-index + # or custom colorspace plus param + my $cs = shift(@clr); + return '/' . $cs->name(), ($sf ? 'cs' : 'CS'), $cs->param(@clr), ($sf ? 'sc' : 'SC'); + } + elsif (scalar @clr == 2) { + # indexed colorspace plus color-index + # or custom colorspace plus param + return '/' . $clr[0]->name(), ($sf ? 'cs' : 'CS'), $clr[0]->param($clr[1]), ($sf ? 'sc' : 'SC'); + } + elsif (scalar @clr == 3) { + # legacy rgb color-spec (0 <= x <= 1) + return floats($clr[0], $clr[1], $clr[2]), ($sf ? 'rg' : 'RG'); + } + elsif (scalar @clr == 4) { + # legacy cmyk color-spec (0 <= x <= 1) + return floats($clr[0], $clr[1], $clr[2], $clr[3]), ($sf ? 'k' : 'K'); + } + else { + die 'invalid color specification.'; + } +} + +sub _fillcolor { + my ($self,@clrs)=@_; + if (ref($clrs[0]) =~ m|^PDF::API2::Resource::ColorSpace|) { + $self->resource('ColorSpace',$clrs[0]->name,$clrs[0]); + } + elsif (ref($clrs[0]) =~ m|^PDF::API2::Resource::Pattern|) { + $self->resource('Pattern',$clrs[0]->name,$clrs[0]); + } + + return $self->_makecolor(1,@clrs); +} + +sub fillcolor { + my $self = shift; + if (scalar @_) { + @{$self->{' fillcolor'}}=@_; + $self->add($self->_fillcolor(@_)); + } + return @{$self->{' fillcolor'}}; +} + +sub _strokecolor { + my ($self,@clrs)=@_; + if (ref($clrs[0]) =~ m|^PDF::API2::Resource::ColorSpace|) { + $self->resource('ColorSpace',$clrs[0]->name,$clrs[0]); + } + elsif (ref($clrs[0]) =~ m|^PDF::API2::Resource::Pattern|) { + $self->resource('Pattern',$clrs[0]->name,$clrs[0]); + } + return $self->_makecolor(0,@clrs); +} + +sub strokecolor { + my $self = shift; + if (scalar @_) { + @{$self->{' strokecolor'}}=@_; + $self->add($self->_strokecolor(@_)); + } + return @{$self->{' strokecolor'}}; +} + + +sub shade { + my $self = shift; + my $shade = shift; + my @cord = @_; + my @tm = ( + $cord[2]-$cord[0] , 0, + 0 , $cord[3]-$cord[1], + $cord[0] , $cord[1] + ); + $self->save; + $self->matrix(@tm); + $self->add('/'.$shade->name,'sh'); + + $self->resource('Shading',$shade->name,$shade); + + $self->restore; + return $self; +} + +#line 1272 + +sub image { + my $self = shift; + my $img = shift; + my ($x,$y,$w,$h) = @_; + if (defined $img->{Metadata}) { + $self->metaStart('PPAM:PlacedImage',$img->{Metadata}); + } + $self->save; + if (!defined $w) { + $h=$img->height; + $w=$img->width; + } + elsif (!defined $h) { + $h=$img->height*$w; + $w=$img->width*$w; + } + $self->matrix($w,0,0,$h,$x,$y); + $self->add("/".$img->name,'Do'); + $self->restore; + $self->{' x'}=$x; + $self->{' y'}=$y; + $self->resource('XObject',$img->name,$img); + if(defined $img->{Metadata}) { + $self->metaEnd; + } + return $self; +} + +#line 1308 + +sub formimage { + my $self = shift; + my $img = shift; + my ($x,$y,$s) = @_; + $self->save; + if (!defined $s) { + $self->matrix(1,0,0,1,$x,$y); + } + else { + $self->matrix($s,0,0,$s,$x,$y); + } + $self->add('/'.$img->name,'Do'); + $self->restore; + $self->resource('XObject',$img->name,$img); + return $self; +} + +#line 1341 + +sub _charspace { + my ($para) = @_; + return float($para, 6) . ' Tc'; +} +sub charspace { + my ($self, $para) = @_; + if (defined $para) { + $self->{' charspace'}=$para; + $self->add(_charspace($para)); + } + return $self->{' charspace'}; +} + +#line 1367 + +sub _wordspace { + my ($para) = @_; + return float($para, 6) . ' Tw'; +} + +sub wordspace { + my ($self, $para) = @_; + if (defined $para) { + $self->{' wordspace'}=$para; + $self->add(_wordspace($para)); + } + return $self->{' wordspace'}; +} + +#line 1389 + +sub _hscale { + my ($scale) = @_; + return float($scale, 6) . ' Tz'; +} + +sub hscale { + my ($self, $scale) = @_; + if (defined $scale) { + $self->{' hscale'} = $scale; + $self->add(_hscale($scale)); + } + return $self->{' hscale'}; +} + +# Deprecated: hscale was originally named incorrectly (as hspace) +sub hspace { return hscale(@_) } +sub _hspace { return _hscale(@_) } + +#line 1415 + +sub _lead { + my ($para) = @_; + return float($para) . ' TL'; +} +sub lead { + my ($self,$para) = @_; + if (defined ($para)) { + $self->{' lead'} = $para; + $self->add(_lead($para)); + } + return $self->{' lead'}; +} + +#line 1454 + +sub _render { + my ($para) = @_; + return intg($para) . ' Tr'; +} + +sub render { + my ($self, $para) = @_; + if (defined ($para)) { + $self->{' render'} = $para; + $self->add(_render($para)); + } + return $self->{' render'}; +} + +#line 1478 + +sub _rise { + my ($para) = @_; + return float($para) . ' Ts'; +} + +sub rise { + my ($self, $para) = @_; + if (defined ($para)) { + $self->{' rise'} = $para; + $self->add(_rise($para)); + } + return $self->{' rise'}; +} + +#line 1503 + +sub textstate { + my $self = shift; + my %state; + if (scalar @_) { + %state = @_; + foreach my $k (qw( charspace hscale wordspace lead rise render )) { + next unless($state{$k}); + $self->can($k)->($self, $state{$k}); + } + if ($state{font} && $state{fontsize}) { + $self->font($state{font},$state{fontsize}); + } + if ($state{textmatrix}) { + $self->matrix(@{$state{textmatrix}}); + @{$self->{' translate'}}=@{$state{translate}}; + $self->{' rotate'}=$state{rotate}; + @{$self->{' scale'}}=@{$state{scale}}; + @{$self->{' skew'}}=@{$state{skew}}; + } + if ($state{fillcolor}) { + $self->fillcolor(@{$state{fillcolor}}); + } + if ($state{strokecolor}) { + $self->strokecolor(@{$state{strokecolor}}); + } + %state = (); + } + else { + foreach my $k (qw( font fontsize charspace hscale wordspace lead rise render )) { + $state{$k}=$self->{" $k"}; + } + $state{matrix}=[@{$self->{" matrix"}}]; + $state{textmatrix}=[@{$self->{" textmatrix"}}]; + $state{textlinematrix}=[@{$self->{" textlinematrix"}}]; + $state{rotate}=$self->{" rotate"}; + $state{scale}=[@{$self->{" scale"}}]; + $state{skew}=[@{$self->{" skew"}}]; + $state{translate}=[@{$self->{" translate"}}]; + $state{fillcolor}=[@{$self->{" fillcolor"}}]; + $state{strokecolor}=[@{$self->{" strokecolor"}}]; + } + return %state; +} + +#line 1558 + +sub _font { + my ($font, $size) = @_; + if ($font->isvirtual == 1) { + return('/'.$font->fontlist->[0]->name.' '.float($size).' Tf'); + } + else { + return('/'.$font->name.' '.float($size).' Tf'); + } +} +sub font { + my ($self, $font, $size) = @_; + unless ($size) { + croak q{A font size is required}; + } + $self->fontset($font, $size); + $self->add(_font($font, $size)); + $self->{' fontset'} = 1; + return $self; +} + +sub fontset { + my ($self,$font,$size)=@_; + $self->{' font'}=$font; + $self->{' fontsize'}=$size; + $self->{' fontset'}=0; + + if ($font->isvirtual == 1) { + foreach my $f (@{$font->fontlist}) { + $self->resource('Font', $f->name, $f); + } + } + else { + $self->resource('Font', $font->name, $font); + } + + return $self; +} + +#line 1612 + +sub distance { + my ($self,$dx,$dy)=@_; + $self->add(float($dx),float($dy),'Td'); + $self->matrix_update($dx,$dy); + $self->{' textlinematrix'}->[0]=$dx; +} + +#line 1636 + +sub cr { + my ($self, $offset) = @_; + if (defined $offset) { + $self->add(0, float($offset), 'Td'); + $self->matrix_update(0, $offset); + } + else { + $self->add('T*'); + $self->matrix_update(0, $self->lead() * -1); + } + $self->{' textlinematrix'}->[0] = 0; +} + +#line 1655 + +sub nl { + my $self = shift(); + $self->add('T*'); + $self->matrix_update(0, $self->lead() * -1); + $self->{' textlinematrix'}->[0] = 0; +} + +#line 1670 + +sub _textpos { + my ($self,@xy)=@_; + my ($x,$y)=(0,0); + while (scalar @xy > 0) { + $x+=shift @xy; + $y+=shift @xy; + } + my (@m)=_transform( + -matrix=>$self->{" textmatrix"}, + -point=>[$x,$y] + ); + return($m[0],$m[1]); +} +sub textpos { + my $self=shift @_; + return($self->_textpos(@{$self->{" textlinematrix"}})); +} +sub textpos2 { + my $self=shift @_; + return(@{$self->{" textlinematrix"}}); +} + +#line 1726 + +sub _text_underline { + my ($self,$xy1,$xy2,$underline,$color) = @_; + $color||='black'; + my @underline=(); + if (ref($underline) eq 'ARRAY') { + @underline=@{$underline}; + } + else { + @underline=($underline,1); + } + push @underline,1 if(@underline%2); + + my $underlineposition=(-$self->{' font'}->underlineposition()*$self->{' fontsize'}/1000||1); + my $underlinethickness=($self->{' font'}->underlinethickness()*$self->{' fontsize'}/1000||1); + my $pos=1; + + while(@underline) { + $self->add_post(_save); + + my $distance=shift @underline; + my $thickness=shift @underline; + my $scolor=$color; + if (ref $thickness) { + ($thickness,$scolor)=@{$thickness}; + } + + if ($distance eq 'auto') { + $distance=$pos*$underlineposition; + } + if ($thickness eq 'auto') { + $thickness=$underlinethickness; + } + + my ($x1,$y1)=$self->_textpos(@{$xy1},0,-($distance+($thickness/2))); + my ($x2,$y2)=$self->_textpos(@{$xy2},0,-($distance+($thickness/2))); + + $self->add_post($self->_strokecolor($scolor)); + $self->add_post(_linewidth($thickness)); + $self->add_post(_move($x1,$y1)); + $self->add_post(_line($x2,$y2)); + $self->add_post(_stroke); + + $self->add_post(_restore); + $pos++; + } +} + +sub text { + my ($self, $text, %opt) = @_; + my $wd = 0; + if ($self->{' fontset'}==0) { + unless (defined $self->{' font'} and $self->{' fontsize'}) { + croak q{Can't add text without first setting a font and font size}; + } + $self->font($self->{' font'},$self->{' fontsize'}); + $self->{' fontset'}=1; + } + if (defined $opt{-indent}) { + $wd+=$opt{-indent}; + $self->matrix_update($wd,0); + } + my $ulxy1=[$self->textpos2]; + + if (defined $opt{-indent}) { + # changed fot acrobat 8 and possible others + # $self->add('[',(-$opt{-indent}*(1000/$self->{' fontsize'})*(100/$self->hscale())),']','TJ'); + $self->add($self->{' font'}->text($text, $self->{' fontsize'}, (-$opt{-indent}*(1000/$self->{' fontsize'})*(100/$self->hscale())))); + } + else { + $self->add($self->{' font'}->text($text,$self->{' fontsize'})); + } + + $wd = $self->advancewidth($text); + $self->matrix_update($wd,0); + + my $ulxy2 = [$self->textpos2]; + + if (defined $opt{-underline}) { + $self->_text_underline($ulxy1,$ulxy2,$opt{-underline},$opt{-strokecolor}); + } + + return $wd; +} + +#line 1816 + +sub text_center { + my ($self,$text,@opts)=@_; + my $width=$self->advancewidth($text); + return $self->text($text,-indent=>-($width/2),@opts); +} + +#line 1828 + +sub text_right { + my ($self,$text,@opts) = @_; + my $width=$self->advancewidth($text); + return $self->text($text,-indent=>-$width,@opts); +} + +#line 1841 + +sub advancewidth { + my ($self,$text,@opts) = @_; + return 0 unless defined($text) and length($text); + if(scalar @opts > 1) { + my %opts=@opts; + foreach my $k (qw[ font fontsize wordspace charspace hscale]) { + $opts{$k}=$self->{" $k"} unless(defined $opts{$k}); + } + my $glyph_width = $opts{font}->width($text)*$opts{fontsize}; + my $num_space = $text =~ y/\x20/\x20/; + my $num_char = length($text); + my $word_spaces = $opts{wordspace}*$num_space; + my $char_spaces = $opts{charspace}*($num_char - 1); + my $advance = ($glyph_width+$word_spaces+$char_spaces)*$opts{hscale}/100; + return $advance; + } + else { + my $glyph_width = $self->{' font'}->width($text)*$self->{' fontsize'}; + my $num_space = $text =~ y/\x20/\x20/; + my $num_char = length($text); + my $word_spaces = $self->wordspace*$num_space; + my $char_spaces = $self->charspace*($num_char - 1); + my $advance = ($glyph_width+$word_spaces+$char_spaces)*$self->hscale()/100; + return $advance; + } +} + +#line 1872 + +sub text_justified { + my ($self,$text,$width,%opts) = @_; + my $initial_width = $self->advancewidth($text); + my $space_count = scalar split /\s/, $text; + my $ws = $self->wordspace(); + $self->wordspace(($width - $initial_width) / $space_count) if $space_count > 0; + $self->text($text,%opts); + $self->wordspace($ws); + return $width; +} + +sub _text_fill_line { + my ($self,$text,$width,$over) = @_; + my @txt = split(/\x20/,$text); + my @line = (); + local $"; + $"=' '; + while (@txt) { + push @line,(shift @txt); + last if($self->advancewidth("@line")>$width); + } + if (!$over && (scalar @line > 1) && ($self->advancewidth("@line") > $width)) { + unshift @txt,pop @line; + } + my $ret = "@txt"; + my $line = "@line"; + return ($line,$ret); +} + +sub text_fill_left { + my ($self,$text,$width,%opts) = @_; + my $over=(not(defined($opts{-spillover}) and $opts{-spillover} == 0)); + my ($line,$ret)=$self->_text_fill_line($text,$width,$over); + $width=$self->text($line,%opts); + return ($width,$ret); +} + +sub text_fill_center { + my ($self,$text,$width,%opts) = @_; + my $over=(not(defined($opts{-spillover}) and $opts{-spillover} == 0)); + my ($line,$ret)=$self->_text_fill_line($text,$width,$over); + $width=$self->text_center($line,%opts); + return ($width,$ret); +} + +sub text_fill_right { + my ($self,$text,$width,%opts) = @_; + my $over=(not(defined($opts{-spillover}) and $opts{-spillover} == 0)); + my ($line,$ret)=$self->_text_fill_line($text,$width,$over); + $width=$self->text_right($line,%opts); + return ($width,$ret); +} + +sub text_fill_justified { + my ($self,$text,$width,%opts) = @_; + my $over=(not(defined($opts{-spillover}) and $opts{-spillover} == 0)); + my ($line,$ret)=$self->_text_fill_line($text,$width,$over); + my $ws=$self->wordspace(); + my $w=$self->advancewidth($line); + my $space_count = scalar split /\s/, $line; + if (($ret||$w>=$width) and $space_count) { + $self->wordspace(($width - $w) / $space_count); + } + $width=$self->text($line,%opts); + $self->wordspace($ws); + return($width,$ret); +} + +# =item $overflow_text = $txt->paragraph $text, $width, $height, %options +# +# ** DEVELOPER METHOD ** +# +# Apply the text within the rectangle and return any leftover text. +# +# B<Options> +# +# =over 4 +# +# =item -align => $choice +# +# Choice is 'justified', 'right', 'center', 'left' +# Default is 'left' +# +# =item -underline => $distance +# +# =item -underline => [ $distance, $thickness, ... ] +# +# If a scalar, distance below baseline, +# else array reference with pairs of distance and line thickness. +# +# =item -spillover => $over +# +# Controls if words in a line which exceed the given width should be "spilled over" the bounds or if a new line should be used for this word. +# +# Over is 1 or 0 +# Default is 1 +# +# =back +# +# B<Example:> +# +# $txt->font($font,$fontsize); +# $txt->lead($lead); +# $txt->translate($x,$y); +# $overflow = $txt->paragraph( 'long paragraph here ...', +# $width, +# $y+$lead-$bottom_margin ); +# +# =cut + +sub paragraph { + my ($self,$text,$width,$height,%opts) = @_; + my @line=(); + my $nwidth=0; + my $lead=$self->lead(); + while (length($text)>0) { + last if ($height -= $lead) < 0; + if ($opts{-align}=~/^j/i) { + ($nwidth,$text)=$self->text_fill_justified($text,$width,%opts); + } + elsif ($opts{-align}=~/^r/i) { + ($nwidth,$text)=$self->text_fill_right($text,$width,%opts); + } + elsif ($opts{-align}=~/^c/i) { + ($nwidth,$text)=$self->text_fill_center($text,$width,%opts); + } + else { + ($nwidth,$text)=$self->text_fill_left($text,$width,%opts); + } + $self->nl; + } + if (wantarray) { + return ($text,$height); + } + return $text; +} + +# =item $overflow_text = $txt->section $text, $width, $height, %options +# +# ** DEVELOPER METHOD ** +# +# Split paragraphs by newline and loop over them, reassemble leftovers +# when box is full and apply the text within the rectangle and return +# any leftover text. +# +# =cut + +sub section { + my ($self,$text,$width,$height,%opts)=@_; + my $overflow = ''; + + foreach my $para (split(/\n/,$text)) { + if(length($overflow) > 0) { + $overflow .= "\n" . $para; + next; + } + ($para,$height) = $self->paragraph($para,$width,$height,%opts); + $overflow .= $para if (length($para) > 0); + } + if (wantarray) { + return ($overflow,$height); + } + return $overflow; +} + +sub textlabel { + my ($self,$x,$y,$font,$size,$text,%opts,$wht) = @_; + my %trans_opts=( -translate => [$x,$y] ); + my %text_state=(); + $trans_opts{-rotate} = $opts{-rotate} if($opts{-rotate}); + + my $wastext = $self->_in_text_object; + if ($wastext) { + %text_state=$self->textstate; + $self->textend; + } + $self->save; + $self->textstart; + + $self->transform(%trans_opts); + + $self->fillcolor(ref($opts{-color}) ? @{$opts{-color}} : $opts{-color}) if($opts{-color}); + $self->strokecolor(ref($opts{-strokecolor}) ? @{$opts{-strokecolor}} : $opts{-strokecolor}) if($opts{-strokecolor}); + + $self->font($font,$size); + + $self->charspace($opts{-charspace}) if($opts{-charspace}); + $self->hscale($opts{-hscale}) if($opts{-hscale}); + $self->wordspace($opts{-wordspace}) if($opts{-wordspace}); + $self->render($opts{-render}) if($opts{-render}); + + if ($opts{-right} || $opts{-align}=~/^r/i) { + $wht = $self->text_right($text,%opts); + } + elsif ($opts{-center} || $opts{-align}=~/^c/i) { + $wht = $self->text_center($text,%opts); + } + else { + $wht = $self->text($text,%opts); + } + + $self->textend; + $self->restore; + + if ($wastext) { + $self->textstart; + $self->textstate(%text_state); + } + return $wht; +} + +sub metaStart { + my $self=shift @_; + my $tag=shift @_; + my $obj=shift @_; + $self->add("/$tag"); + if (defined $obj) { + my $dict=PDFDict(); + $dict->{Metadata}=$obj; + $self->resource('Properties',$obj->name,$dict); + $self->add('/'.($obj->name)); + $self->add('BDC'); + } + else { + $self->add('BMC'); + } + return $self; +} + +sub metaEnd { + my $self=shift @_; + $self->add('EMC'); + return $self; +} + +#line 2118 + +sub add_post { + my $self = shift; + if (scalar @_) { + $self->{' poststream'} .= ($self->{' poststream'} =~ m|\s$|o ? '' : ' ') . join(' ', @_) . ' '; + } + return $self; +} +sub add { + my $self = shift; + if (scalar @_) { + $self->{' stream'} .= encode('iso-8859-1', ($self->{' stream'} =~ m|\s$|o ? '' : ' ') . join(' ', @_) . ' '); + } + return $self; +} + +# Shortcut method for determining if we're inside a text object +# (i.e. between BT and ET). See textstart and textend. +sub _in_text_object { + my $self = shift(); + return defined($self->{' apiistext'}) && $self->{' apiistext'} == 1; +} + +#line 2147 + +sub compressFlate { + my $self=shift @_; + $self->{'Filter'}=PDFArray(PDFName('FlateDecode')); + $self->{-docompress}=1; + return $self; +} + +#line 2161 + +sub textstart { + my ($self) = @_; + unless ($self->_in_text_object()) { + $self->add(' BT '); + $self->{' apiistext'}=1; + $self->{' font'}=undef; + $self->{' fontset'}=0; + $self->{' fontsize'}=0; + $self->{' charspace'}=0; + $self->{' hscale'}=100; + $self->{' wordspace'}=0; + $self->{' lead'}=0; + $self->{' rise'}=0; + $self->{' render'}=0; + @{$self->{' matrix'}}=(1,0,0,1,0,0); + @{$self->{' textmatrix'}}=(1,0,0,1,0,0); + @{$self->{' textlinematrix'}}=(0,0); + @{$self->{' fillcolor'}}=(0); + @{$self->{' strokecolor'}}=(0); + @{$self->{' translate'}}=(0,0); + @{$self->{' scale'}}=(1,1); + @{$self->{' skew'}}=(0,0); + $self->{' rotate'}=0; + } + return $self; +} + +#line 2194 + +sub textend { + my ($self) = @_; + if ($self->_in_text_object()) { + $self->add(' ET ', $self->{' poststream'}); + $self->{' apiistext'} = 0; + $self->{' poststream'} = ''; + } + return $self; +} + +#line 2208 + +sub resource { + my ($self, $type, $key, $obj, $force) = @_; + if ($self->{' apipage'}) { + # we are a content stream on a page. + return $self->{' apipage'}->resource($type, $key, $obj, $force); + } + else { + # we are a self-contained content stream. + $self->{Resources}||=PDFDict(); + + my $dict=$self->{Resources}; + $dict->realise if(ref($dict)=~/Objind$/); + + $dict->{$type}||= PDFDict(); + $dict->{$type}->realise if(ref($dict->{$type})=~/Objind$/); + unless (defined $obj) { + return($dict->{$type}->{$key} || undef); + } + else { + if ($force) { + $dict->{$type}->{$key}=$obj; + } + else { + $dict->{$type}->{$key}||=$obj; + } + return $dict; + } + } +} + +1; diff --git a/lib/PDF/API2/Content/Text.pm b/lib/PDF/API2/Content/Text.pm new file mode 100644 index 0000000..6e4e6a2 --- /dev/null +++ b/lib/PDF/API2/Content/Text.pm @@ -0,0 +1,19 @@ +#line 1 "PDF/API2/Content/Text.pm" +#line 1 "PDF/API2/Content/Text.pm" +package PDF::API2::Content::Text; + +use base 'PDF::API2::Content'; + +use strict; +use warnings; + +our $VERSION = '2.033'; # VERSION + +sub new { + my ($class) = @_; + my $self = $class->SUPER::new(@_); + $self->textstart(); + return $self; +} + +1; diff --git a/lib/PDF/API2/Matrix.pm b/lib/PDF/API2/Matrix.pm new file mode 100644 index 0000000..07333b4 --- /dev/null +++ b/lib/PDF/API2/Matrix.pm @@ -0,0 +1,74 @@ +#line 1 "PDF/API2/Matrix.pm" +#line 1 "PDF/API2/Matrix.pm" +#======================================================================= +# +# PDF::API2::Matrix +# Original Copyright 1995-96 Ulrich Pfeifer. +# modified by Alfred Reibenschuh <areibens@cpan.org> for PDF::API2 +# +# This library is free software; you can redistribute it +# and/or modify it under the same terms as Perl itself. +# +#======================================================================= +package PDF::API2::Matrix; + +use strict; + +our $VERSION = '2.033'; # VERSION + +sub new { + my $type = shift; + my $self = []; + my $len = scalar(@{$_[0]}); + for (@_) { + return if scalar(@{$_}) != $len; + push(@{$self}, [@{$_}]); + } + bless $self, $type; +} + +sub transpose { + my $self = shift; + my @result; + my $m; + + for my $col (@{$self->[0]}) { + push @result, []; + } + for my $row (@{$self}) { + $m = 0; + for my $col (@{$row}) { + push(@{$result[$m++]}, $col); + } + } + return PDF::API2::Matrix->new(@result); +} + +sub vekpro { + my ($a, $b) = @_; + my $result = 0; + + for my $i (0 .. $#{$a}) { + $result += $a->[$i] * $b->[$i]; + } + return $result; +} + +sub multiply { + my $self = shift; + my $other = shift->transpose; + my @result; + my $m; + + return if $#{$self->[0]} != $#{$other->[0]}; + for my $row (@{$self}) { + my $rescol = []; + for my $col (@{$other}) { + push(@{$rescol}, vekpro($row,$col)); + } + push(@result, $rescol); + } + return PDF::API2::Matrix->new(@result); +} + +1; diff --git a/lib/PDF/API2/NamedDestination.pm b/lib/PDF/API2/NamedDestination.pm new file mode 100644 index 0000000..a58b943 --- /dev/null +++ b/lib/PDF/API2/NamedDestination.pm @@ -0,0 +1,179 @@ +#line 1 "PDF/API2/NamedDestination.pm" +#line 1 "PDF/API2/NamedDestination.pm" +package PDF::API2::NamedDestination; + +use base 'PDF::API2::Basic::PDF::Dict'; + +use strict; +no warnings qw[ recursion uninitialized ]; + +our $VERSION = '2.033'; # VERSION + +use Encode qw(:all); + +use PDF::API2::Util; +use PDF::API2::Basic::PDF::Utils; + +#line 26 + +sub new +{ + my ($class,$pdf) = @_; + my ($self); + + $class = ref $class if ref $class; + $self = $class->SUPER::new($pdf); + + $pdf->new_obj($self) unless($self->is_obj($pdf)); + + return($self); +} + +# Deprecated (warning added in 2.031) +sub new_api { + my ($class, $api2, @options) = @_; + warnings::warnif('deprecated', q{Call to deprecated method "new_api($api2, ...)". Replace with "new($api2->{'pdf'}, ...)"}); + + my $destination = $class->new($api2->{'pdf'}, @options); + return $destination; +} + +#line 55 + +sub link +{ + my ($self,$page,%opts)=@_; + + $self->{S}=PDFName('GoTo'); + $self->dest($page,%opts); + + return($self); +} + +#line 72 + +sub url +{ + my ($self,$url,%opts)=@_; + + $self->{S}=PDFName('URI'); + if(is_utf8($url)) + { + # URI must be 7-bit ascii + utf8::downgrade($url); + } + $self->{URI}=PDFStr($url); + + # this will come again -- since the utf8 urls are coming ! + # -- fredo + #if(is_utf8($url) || utf8::valid($url)) { + # $self->{URI}=PDFUtf($url); + #} else { + # $self->{URI}=PDFStr($url); + #} + return($self); +} + +#line 101 + +sub file +{ + my ($self,$url,%opts)=@_; + + $self->{S}=PDFName('Launch'); + if(is_utf8($url)) + { + # URI must be 7-bit ascii + utf8::downgrade($url); + } + $self->{F}=PDFStr($url); + + # this will come again -- since the utf8 urls are coming ! + # -- fredo + #if(is_utf8($url) || utf8::valid($url)) { + # $self->{F}=PDFUtf($url); + #} else { + # $self->{F}=PDFStr($url); + #} + return($self); +} + +#line 130 + +sub pdfile +{ + my ($self,$url,$pnum,%opts)=@_; + + $self->{S}=PDFName('GoToR'); + if(is_utf8($url)) + { + # URI must be 7-bit ascii + utf8::downgrade($url); + } + $self->{F}=PDFStr($url); + + # this will come again -- since the utf8 urls are coming ! + # -- fredo + #if(is_utf8($url) || utf8::valid($url)) { + # $self->{F}=PDFUtf($url); + #} else { + # $self->{F}=PDFStr($url); + #} + + $self->dest(PDFNum($pnum),%opts); + + return($self); +} + +#line 212 + +sub dest +{ + my ($self,$page,%opts)=@_; + + if(ref $page) + { + $opts{-xyz}=[undef,undef,undef] if(scalar(keys %opts)<1); + + if(defined $opts{-fit}) + { + $self->{D}=PDFArray($page,PDFName('Fit')); + } + elsif(defined $opts{-fith}) + { + $self->{D}=PDFArray($page,PDFName('FitH'),PDFNum($opts{-fith})); + } + elsif(defined $opts{-fitb}) + { + $self->{D}=PDFArray($page,PDFName('FitB')); + } + elsif(defined $opts{-fitbh}) + { + $self->{D}=PDFArray($page,PDFName('FitBH'),PDFNum($opts{-fitbh})); + } + elsif(defined $opts{-fitv}) + { + $self->{D}=PDFArray($page,PDFName('FitV'),PDFNum($opts{-fitv})); + } + elsif(defined $opts{-fitbv}) + { + $self->{D}=PDFArray($page,PDFName('FitBV'),PDFNum($opts{-fitbv})); + } + elsif(defined $opts{-fitr}) + { + die "insufficient parameters to ->dest( page, -fitr => [] ) " unless(scalar @{$opts{-fitr}} == 4); + $self->{D}=PDFArray($page,PDFName('FitR'),map {PDFNum($_)} @{$opts{-fitr}}); + } + elsif(defined $opts{-xyz}) + { + die "insufficient parameters to ->dest( page, -xyz => [] ) " unless(scalar @{$opts{-xyz}} == 3); + $self->{D}=PDFArray($page,PDFName('XYZ'),map {defined $_ ? PDFNum($_) : PDFNull()} @{$opts{-xyz}}); + } + } + + return($self); +} + +#line 263 + +1; diff --git a/lib/PDF/API2/Outline.pm b/lib/PDF/API2/Outline.pm new file mode 100644 index 0000000..21f7d30 --- /dev/null +++ b/lib/PDF/API2/Outline.pm @@ -0,0 +1,244 @@ +#line 1 "PDF/API2/Outline.pm" +#line 1 "PDF/API2/Outline.pm" +package PDF::API2::Outline; + +use base 'PDF::API2::Basic::PDF::Dict'; + +use strict; +no warnings qw[ deprecated recursion uninitialized ]; + +our $VERSION = '2.033'; # VERSION + +use PDF::API2::Basic::PDF::Utils; +use PDF::API2::Util; +use Scalar::Util qw(weaken); + +#line 27 + +sub new { + my ($class,$api,$parent,$prev)=@_; + my $self = $class->SUPER::new; + $self->{' apipdf'}=$api->{pdf}; + $self->{' api'}=$api; + weaken $self->{' apipdf'}; + weaken $self->{' api'}; + $self->{Parent}=$parent if(defined $parent); + $self->{Prev}=$prev if(defined $prev); + return($self); +} + +sub parent { + my $self=shift @_; + if(defined $_[0]) { + $self->{Parent}=shift @_; + } + return $self->{Parent}; +} + +sub prev { + my $self=shift @_; + if(defined $_[0]) { + $self->{Prev}=shift @_; + } + return $self->{Prev}; +} + +sub next { + my $self=shift @_; + if(defined $_[0]) { + $self->{Next}=shift @_; + } + return $self->{Next}; +} + +sub first { + my $self=shift @_; + $self->{First}=$self->{' childs'}->[0] if(defined $self->{' childs'} && defined $self->{' childs'}->[0]); + return $self->{First} ; +} + +sub last { + my $self=shift @_; + $self->{Last}=$self->{' childs'}->[-1] if(defined $self->{' childs'} && defined $self->{' childs'}->[-1]); + return $self->{Last}; +} + +sub count { + my $self=shift @_; + my $cnt=scalar @{$self->{' childs'}||[]}; + map { $cnt+=$_->count();} @{$self->{' childs'}}; + $self->{Count}=PDFNum($self->{' closed'} ? -$cnt : $cnt) if($cnt>0); + return $cnt; +} + +sub fix_outline { + my ($self)=@_; + $self->first; + $self->last; + $self->count; +} + +#line 96 + +sub title { + my ($self,$txt)=@_; + $self->{Title}=PDFStr($txt); + return($self); +} + +#line 108 + +sub closed { + my $self=shift @_; + $self->{' closed'}=1; + return $self; +} + +#line 120 + +sub open { + my $self=shift @_; + delete $self->{' closed'}; + return $self; +} + +#line 132 + +sub outline { + my $self=shift @_; + my $obj=PDF::API2::Outline->new($self->{' api'},$self); + $obj->prev($self->{' childs'}->[-1]) if(defined $self->{' childs'}); + $self->{' childs'}->[-1]->next($obj) if(defined $self->{' childs'}); + push(@{$self->{' childs'}},$obj); + $self->{' api'}->{pdf}->new_obj($obj) if(!$obj->is_obj($self->{' api'}->{pdf})); + return $obj; +} + +#line 207 + +sub dest +{ + my ($self,$page,%opts)=@_; + + if(ref $page) + { + $opts{-xyz}=[undef,undef,undef] if(scalar(keys %opts)<1); + + if(defined $opts{-fit}) + { + $self->{Dest}=PDFArray($page,PDFName('Fit')); + } + elsif(defined $opts{-fith}) + { + $self->{Dest}=PDFArray($page,PDFName('FitH'),PDFNum($opts{-fith})); + } + elsif(defined $opts{-fitb}) + { + $self->{Dest}=PDFArray($page,PDFName('FitB')); + } + elsif(defined $opts{-fitbh}) + { + $self->{Dest}=PDFArray($page,PDFName('FitBH'),PDFNum($opts{-fitbh})); + } + elsif(defined $opts{-fitv}) + { + $self->{Dest}=PDFArray($page,PDFName('FitV'),PDFNum($opts{-fitv})); + } + elsif(defined $opts{-fitbv}) + { + $self->{Dest}=PDFArray($page,PDFName('FitBV'),PDFNum($opts{-fitbv})); + } + elsif(defined $opts{-fitr}) + { + die "insufficient parameters to ->dest( page, -fitr => [] ) " unless(scalar @{$opts{-fitr}} == 4); + $self->{Dest}=PDFArray($page,PDFName('FitR'),map {PDFNum($_)} @{$opts{-fitr}}); + } + elsif(defined $opts{-xyz}) + { + die "insufficient parameters to ->dest( page, -xyz => [] ) " unless(scalar @{$opts{-xyz}} == 3); + $self->{Dest}=PDFArray($page,PDFName('XYZ'),map {defined $_ ? PDFNum($_) : PDFNull()} @{$opts{-xyz}}); + } + } + else + { + $self->{Dest}=PDFStr($page); + } + return($self); +} + +#line 263 + +sub url { + my ($self,$url,%opts)=@_; + delete $self->{Dest}; + $self->{A}=PDFDict(); + $self->{A}->{S}=PDFName('URI'); + $self->{A}->{URI}=PDFStr($url); + return($self); +} + +#line 278 + +sub file { + my ($self,$file,%opts)=@_; + delete $self->{Dest}; + $self->{A}=PDFDict(); + $self->{A}->{S}=PDFName('Launch'); + $self->{A}->{F}=PDFStr($file); + return($self); +} + +#line 294 + +sub pdfile { + my ($self,$file,$pnum,%opts)=@_; + delete $self->{Dest}; + $self->{A}=PDFDict(); + $self->{A}->{S}=PDFName('GoToR'); + $self->{A}->{F}=PDFStr($file); + if(defined $opts{-fit}) { + $self->{A}->{D}=PDFArray(PDFNum($pnum),PDFName('Fit')); + } elsif(defined $opts{-fith}) { + $self->{A}->{D}=PDFArray(PDFNum($pnum),PDFName('FitH'),PDFNum($opts{-fith})); + } elsif(defined $opts{-fitb}) { + $self->{A}->{D}=PDFArray(PDFNum($pnum),PDFName('FitB')); + } elsif(defined $opts{-fitbh}) { + $self->{A}->{D}=PDFArray(PDFNum($pnum),PDFName('FitBH'),PDFNum($opts{-fitbh})); + } elsif(defined $opts{-fitv}) { + $self->{A}->{D}=PDFArray(PDFNum($pnum),PDFName('FitV'),PDFNum($opts{-fitv})); + } elsif(defined $opts{-fitbv}) { + $self->{A}->{D}=PDFArray(PDFNum($pnum),PDFName('FitBV'),PDFNum($opts{-fitbv})); + } elsif(defined $opts{-fitr}) { + die "insufficient parameters to ->dest( page, -fitr => [] ) " unless(scalar @{$opts{-fitr}} == 4); + $self->{A}->{D}=PDFArray(PDFNum($pnum),PDFName('FitR'),map {PDFNum($_)} @{$opts{-fitr}}); + } elsif(defined $opts{-xyz}) { + die "insufficient parameters to dest( page, -xyz => [] ) " unless(scalar @{$opts{-fitr}} == 3); + $self->{A}->{D}=PDFArray(PDFNum($pnum),PDFName('XYZ'),map {PDFNum($_)} @{$opts{-xyz}}); + } + return($self); +} + +sub out_obj { + my ($self,@param)=@_; + $self->fix_outline; + return $self->SUPER::out_obj(@param); +} + +sub outobjdeep { + my ($self,@param)=@_; + $self->fix_outline; + foreach my $k (qw/ api apipdf apipage /) { + $self->{" $k"}=undef; + delete($self->{" $k"}); + } + my @ret=$self->SUPER::outobjdeep(@param); + foreach my $k (qw/ First Parent Next Last Prev /) { + $self->{$k}=undef; + delete($self->{$k}); + } + return @ret; +} + +#line 347 + +1; diff --git a/lib/PDF/API2/Outlines.pm b/lib/PDF/API2/Outlines.pm new file mode 100644 index 0000000..b153a5b --- /dev/null +++ b/lib/PDF/API2/Outlines.pm @@ -0,0 +1,22 @@ +#line 1 "PDF/API2/Outlines.pm" +#line 1 "PDF/API2/Outlines.pm" +package PDF::API2::Outlines; + +use base 'PDF::API2::Outline'; + +use strict; +use warnings; + +our $VERSION = '2.033'; # VERSION + +use PDF::API2::Basic::PDF::Utils; + +sub new { + my ($class, $api) = @_; + my $self = $class->SUPER::new($api); + $self->{'Type'} = PDFName('Outlines'); + + return $self; +} + +1; diff --git a/lib/PDF/API2/Page.pm b/lib/PDF/API2/Page.pm new file mode 100644 index 0000000..76c678c --- /dev/null +++ b/lib/PDF/API2/Page.pm @@ -0,0 +1,301 @@ +#line 1 "PDF/API2/Page.pm" +#line 1 "PDF/API2/Page.pm" +package PDF::API2::Page; + +use base 'PDF::API2::Basic::PDF::Pages'; + +use strict; +no warnings qw[ deprecated recursion uninitialized ]; + +our $VERSION = '2.033'; # VERSION + +use POSIX qw(floor); + +use PDF::API2::Content; +use PDF::API2::Content::Text; + +use PDF::API2::Basic::PDF::Utils; +use PDF::API2::Util; + +use Scalar::Util qw(weaken); + +#line 33 + +sub new { + my ($class, $pdf, $parent, $index) = @_; + my ($self) = {}; + + $class = ref $class if ref $class; + $self = $class->SUPER::new($pdf, $parent); + $self->{'Type'} = PDFName('Page'); + $self->proc_set(qw( PDF Text ImageB ImageC ImageI )); + delete $self->{'Count'}; + delete $self->{'Kids'}; + $parent->add_page($self, $index); + $self; +} + +#line 53 + +sub coerce { + my ($class, $pdf, $page) = @_; + my $self = $page; + bless($self,$class); + $self->{' apipdf'}=$pdf; + weaken $self->{' apipdf'}; + return($self); +} + +#line 68 + +sub update { + my ($self) = @_; + $self->{' apipdf'}->out_obj($self); + $self; +} + +#line 88 + +sub _set_bbox { + my ($box, $self, @values) = @_; + $self->{$box} = PDFArray( map { PDFNum(float($_)) } page_size(@values) ); + return $self; +} + +sub _get_bbox { + my ($self, $box_order) = @_; + + # Default to letter + my @media = (0, 0, 612, 792); + + foreach my $mediatype (@{$box_order}) { + my $mediaobj = $self->find_prop($mediatype); + if ($mediaobj) { + @media = map { $_->val } $mediaobj->elementsof; + last; + } + } + + return @media; +} + + +sub mediabox { + return _set_bbox('MediaBox', @_); +} + +#line 122 + +sub get_mediabox { + my $self = shift(); + return _get_bbox($self, [qw(MediaBox CropBox BleedBox TrimBox ArtBox)]); +} + +#line 137 + +sub cropbox { + return _set_bbox('CropBox', @_); +} + +#line 147 + +sub get_cropbox { + my $self = shift(); + return _get_bbox($self, [qw(CropBox MediaBox BleedBox TrimBox ArtBox)]); +} + +#line 162 + +sub bleedbox { + return _set_bbox('BleedBox', @_); +} + +#line 172 + +sub get_bleedbox { + my $self = shift(); + return _get_bbox($self, [qw(BleedBox CropBox MediaBox TrimBox ArtBox)]); +} + +#line 185 + +sub trimbox { + return _set_bbox('TrimBox', @_); +} + +#line 195 + +sub get_trimbox { + my $self = shift(); + return _get_bbox($self, [qw(TrimBox CropBox MediaBox ArtBox BleedBox)]); +} + +#line 210 + +sub artbox { + return _set_bbox('ArtBox', @_); +} + +#line 220 + +sub get_artbox { + my $self = shift(); + return _get_bbox($self, [qw(ArtBox CropBox MediaBox TrimBox BleedBox)]); +} + +#line 233 + +sub rotate { + my ($self, $degrees) = @_; + + # Ignore rotation of 360 or more (in either direction) + $degrees = $degrees % 360; + + $self->{'Rotate'} = PDFNum($degrees); + + return $self; +} + +#line 251 + +sub fixcontents { + my ($self) = @_; + $self->{'Contents'} = $self->{'Contents'} || PDFArray(); + if(ref($self->{'Contents'})=~/Objind$/) { + $self->{'Contents'}->realise; + } + if(ref($self->{'Contents'})!~/Array$/) { + $self->{'Contents'} = PDFArray($self->{'Contents'}); + } +} + +sub content { + my ($self,$obj,$dir) = @_; + if(defined($dir) && $dir>0) { + $self->precontent($obj); + } else { + $self->addcontent($obj); + } + $self->{' apipdf'}->new_obj($obj) unless($obj->is_obj($self->{' apipdf'})); + $obj->{' apipdf'}=$self->{' apipdf'}; + $obj->{' api'}=$self->{' api'}; + $obj->{' apipage'}=$self; + + weaken $obj->{' apipdf'}; + weaken $obj->{' api'}; + weaken $obj->{' apipage'}; + + return($obj); +} + +sub addcontent { + my ($self,@objs) = @_; + $self->fixcontents; + $self->{'Contents'}->add_elements(@objs); +} +sub precontent { + my ($self,@objs) = @_; + $self->fixcontents; + unshift(@{$self->{'Contents'}->val},@objs); +} + +sub gfx { + my ($self,$dir) = @_; + my $gfx=PDF::API2::Content->new(); + $self->content($gfx,$dir); + $gfx->compressFlate() if($self->{' api'}->{forcecompress}); + return($gfx); +} + +#line 307 + +sub text { + my ($self,$dir) = @_; + my $text=PDF::API2::Content::Text->new(); + $self->content($text,$dir); + $text->compressFlate() if($self->{' api'}->{forcecompress}); + return($text); +} + +#line 321 + +sub annotation { + my $self = shift(); + + unless (exists $self->{'Annots'}) { + $self->{'Annots'} = PDFArray(); + $self->update(); + } + elsif (ref($self->{'Annots'}) =~ /Objind/) { + $self->{'Annots'}->realise(); + } + + require PDF::API2::Annotation; + my $ant = PDF::API2::Annotation->new(); + $self->{'Annots'}->add_elements($ant); + $self->{' apipdf'}->new_obj($ant); + $ant->{' apipdf'} = $self->{' apipdf'}; + $ant->{' apipage'} = $self; + weaken $ant->{' apipdf'}; + weaken $ant->{' apipage'}; + + if ($self->{'Annots'}->is_obj($self->{' apipdf'})) { + $self->{' apipdf'}->out_obj($self->{'Annots'}); + } + + return $ant; +} + +#line 365 + +sub resource { + my ($self, $type, $key, $obj, $force) = @_; + my ($dict) = $self->find_prop('Resources'); + + $dict = $dict || $self->{Resources} || PDFDict(); + + $dict->realise if(ref($dict)=~/Objind$/); + + $dict->{$type} = $dict->{$type} || PDFDict(); + $dict->{$type}->realise if(ref($dict->{$type})=~/Objind$/); + + unless(defined $obj) { + return($dict->{$type}->{$key} || undef); + } else { + if($force) { + $dict->{$type}->{$key} = $obj; + } else { + $dict->{$type}->{$key} = $dict->{$type}->{$key} || $obj; + } + + $self->{' apipdf'}->out_obj($dict) if($dict->is_obj($self->{' apipdf'})); + $self->{' apipdf'}->out_obj($dict->{$type}) if($dict->{$type}->is_obj($self->{' apipdf'})); + $self->{' apipdf'}->out_obj($obj) if($obj->is_obj($self->{' apipdf'})); + $self->{' apipdf'}->out_obj($self); + + return($dict); + } +} + +sub ship_out +{ + my ($self, $pdf) = @_; + + $pdf->ship_out($self); + if (defined $self->{'Contents'}) + { $pdf->ship_out($self->{'Contents'}->elementsof); } + $self; +} + +sub outobjdeep { + my ($self, @opts) = @_; + foreach my $k (qw/ api apipdf /) { + $self->{" $k"}=undef; + delete($self->{" $k"}); + } + $self->SUPER::outobjdeep(@opts); +} + +#line 417 + +1; diff --git a/lib/PDF/API2/Resource.pm b/lib/PDF/API2/Resource.pm new file mode 100644 index 0000000..513c3af --- /dev/null +++ b/lib/PDF/API2/Resource.pm @@ -0,0 +1,64 @@ +#line 1 "PDF/API2/Resource.pm" +#line 1 "PDF/API2/Resource.pm" +package PDF::API2::Resource; + +use base 'PDF::API2::Basic::PDF::Dict'; + +use strict; +use warnings; + +our $VERSION = '2.033'; # VERSION + +use PDF::API2::Util qw(pdfkey); +use PDF::API2::Basic::PDF::Utils; # PDFName + +use Scalar::Util qw(weaken); + +#line 28 + +sub new { + my ($class, $pdf, $name) = @_; + $class = ref($class) if ref($class); + + my $self = $class->SUPER::new(); + + $pdf->new_obj($self) unless $self->is_obj($pdf); + + $self->name($name or pdfkey()); + + $self->{' apipdf'} = $pdf; + weaken $self->{' apipdf'}; + + return $self; +} + +# Deprecated (warning added in 2.031) +sub new_api { + my ($class, $api2, @options) = @_; + warnings::warnif('deprecated', q{Call to deprecated method "new_api($api2, ...)". Replace with "new($api2->{'pdf'}, ...)"}); + + my $resource = $class->new($api2->{'pdf'}, @options); + return $resource; +} + +#line 61 + +sub name { + my $self = shift @_; + if (scalar @_ and defined $_[0]) { + $self->{'Name'} = PDFName($_[0]); + } + return $self->{'Name'}->val(); +} + +sub outobjdeep { + my ($self, $fh, $pdf, %options) = @_; + + delete $self->{' api'}; + delete $self->{' apipdf'}; + $self->SUPER::outobjdeep($fh, $pdf, %options); +} + +#line 81 + +1; diff --git a/lib/PDF/API2/Resource/BaseFont.pm b/lib/PDF/API2/Resource/BaseFont.pm new file mode 100644 index 0000000..899a58d --- /dev/null +++ b/lib/PDF/API2/Resource/BaseFont.pm @@ -0,0 +1,572 @@ +#line 1 "PDF/API2/Resource/BaseFont.pm" +#line 1 "PDF/API2/Resource/BaseFont.pm" +package PDF::API2::Resource::BaseFont; + +use base 'PDF::API2::Resource'; + +use strict; +no warnings qw[ deprecated recursion uninitialized ]; + +our $VERSION = '2.033'; # VERSION + +use Compress::Zlib; +use Encode qw(:all); +use PDF::API2::Basic::PDF::Utils; +use PDF::API2::Util; +use Scalar::Util qw(weaken); + +#line 29 + +sub new { + my ($class,$pdf,$name) = @_; + my $self; + + $class = ref $class if ref $class; + $self=$class->SUPER::new($pdf,$name); + + $pdf->new_obj($self) unless($self->is_obj($pdf)); + + $self->{Type} = PDFName('Font'); + + $self->{' apipdf'}=$pdf; + weaken $self->{' apipdf'}; + return($self); +} + +sub data { return( $_[0]->{' data'} ); } + +#line 53 + +sub descrByData { + my $self=shift @_; + + my $des=PDFDict(); + $self->{' apipdf'}->new_obj($des); + + ### $self->{'FontDescriptor'}=$des; + + $des->{'Type'}=PDFName('FontDescriptor'); + $des->{'FontName'}=PDFName($self->fontname); + + my @w = map { PDFNum($_ || 0) } $self->fontbbox; + $des->{'FontBBox'}=PDFArray(@w); + + # unless($self->issymbol) { + $des->{'Ascent'}=PDFNum($self->ascender || 0); + $des->{'Descent'}=PDFNum($self->descender || 0); + $des->{'ItalicAngle'}=PDFNum($self->italicangle || 0.0); + $des->{'XHeight'}=PDFNum($self->xheight || (($self->fontbbox)[3]*0.5) || 500); + $des->{'CapHeight'}=PDFNum($self->capheight || ($self->fontbbox)[3] || 800); + $des->{'StemV'}=PDFNum($self->stemv || 0); + $des->{'StemH'}=PDFNum($self->stemh || 0); + $des->{'AvgWidth'}=PDFNum($self->avgwidth || 300); + $des->{'MissingWidth'}=PDFNum($self->missingwidth || 300); + $des->{'MaxWidth'}=PDFNum($self->maxwidth || $self->missingwidth || ($self->fontbbox)[2]); + $des->{'Flags'}=PDFNum($self->flags || 0) unless($self->data->{iscore}); + if(defined $self->data->{panose}) { + $des->{Style}=PDFDict(); + $des->{Style}->{Panose}=PDFStrHex($self->data->{panose}); + } + $des->{FontFamily}=PDFStr($self->data->{fontfamily}) + if(defined $self->data->{fontfamily}); + $des->{FontWeight}=PDFNum($self->data->{fontweight}) + if(defined $self->data->{fontweight}); + $des->{FontStretch}=PDFName($self->data->{fontstretch}) + if(defined $self->data->{fontstretch}); + # } + + return($des); +} + +sub tounicodemap { + my $self=shift @_; + + return($self) if(defined $self->{ToUnicode}); + + my $cmap=qq|\%\% Custom\n\%\% CMap\n\%\%\n/CIDInit /ProcSet findresource begin\n|; + $cmap.=qq|12 dict begin begincmap\n|; + $cmap.=qq|/CIDSystemInfo <<\n|; + $cmap.=sprintf(qq| /Registry (%s)\n|,$self->name); + $cmap.=qq| /Ordering (XYZ)\n|; + $cmap.=qq| /Supplement 0\n|; + $cmap.=qq|>> def\n|; + $cmap.=sprintf(qq|/CMapName /pdfapi2-%s+0 def\n|,$self->name); + if($self->can('uniByCId') and $self->can('glyphNum')) { + # this is a type0 font + $cmap.=sprintf(qq|1 begincodespacerange <0000> <%04X> endcodespacerange\n|,$self->glyphNum-1); + for(my $j=0;$j<$self->glyphNum;$j++) { + my $i = $self->glyphNum - $j > 100 ? 100 : $self->glyphNum - $j; + if($j==0) { + $cmap.=qq|$i beginbfrange\n|; + } elsif($j%100 == 0) { + $cmap.=qq|endbfrange\n|; + $cmap.=qq|$i beginbfrange\n|; + } + $cmap.=sprintf(qq|<%04x> <%04x> <%04x>\n|,$j,$j,$self->uniByCId($j)); + } + $cmap.="endbfrange\n"; + } else { + # everything else is single byte font + $cmap.=qq|1 begincodespacerange\n<00> <FF>\nendcodespacerange\n|; + $cmap.=qq|256 beginbfchar\n|; + for(my $j=0; $j<256;$j++) { + $cmap.=sprintf(qq|<%02X> <%04X>\n|,$j,$self->uniByEnc($j)); + } + $cmap.=qq|endbfchar\n|; + } + $cmap.=qq|endcmap CMapName currendict /CMap defineresource pop end end\n|; + + my $tuni=PDFDict(); + $tuni->{Type}=PDFName('CMap'); + $tuni->{CMapName}=PDFName(sprintf(qq|pdfapi2-%s+0|,$self->name)); + $tuni->{CIDSystemInfo}=PDFDict(); + $tuni->{CIDSystemInfo}->{Registry}=PDFStr($self->name); + $tuni->{CIDSystemInfo}->{Ordering}=PDFStr('XYZ'); + $tuni->{CIDSystemInfo}->{Supplement}=PDFNum(0); + + $self->{' apipdf'}->new_obj($tuni); + $tuni->{' nofilt'}=1; + $tuni->{' stream'}=Compress::Zlib::compress($cmap); + $tuni->{Filter}=PDFArray(PDFName('FlateDecode')); + $self->{ToUnicode}=$tuni; + return($self); +} + + +#line 161 + +sub fontname { return( $_[0]->data->{fontname} ); } + +#line 169 + +sub altname { return( $_[0]->data->{altname} ); } + +#line 177 + +sub subname { return( $_[0]->data->{subname} ); } + +#line 185 + +sub apiname { return( $_[0]->data->{apiname} ); } + +#line 193 + +sub issymbol { return( $_[0]->data->{issymbol} ); } + +#line 201 + +sub iscff { return( $_[0]->data->{iscff} ); } + +#line 215 + +sub fontbbox { return( @{$_[0]->data->{fontbbox}} ); } + +#line 223 + +sub capheight { return( $_[0]->data->{capheight} ); } + +#line 231 + +sub xheight { return( $_[0]->data->{xheight} ); } + +#line 239 + +sub missingwidth { return( $_[0]->data->{missingwidth} ); } + +#line 247 + +sub maxwidth { return( $_[0]->data->{maxwidth} ); } + +#line 255 + +sub avgwidth { + my ($self) = @_; + my $aw=$self->data->{avgwidth}; + $aw||=(( + $self->wxByGlyph('a')*64 + + $self->wxByGlyph('b')*14 + + $self->wxByGlyph('c')*27 + + $self->wxByGlyph('d')*35 + + $self->wxByGlyph('e')*100 + + $self->wxByGlyph('f')*20 + + $self->wxByGlyph('g')*14 + + $self->wxByGlyph('h')*42 + + $self->wxByGlyph('i')*63 + + $self->wxByGlyph('j')* 3 + + $self->wxByGlyph('k')* 6 + + $self->wxByGlyph('l')*35 + + $self->wxByGlyph('m')*20 + + $self->wxByGlyph('n')*56 + + $self->wxByGlyph('o')*56 + + $self->wxByGlyph('p')*17 + + $self->wxByGlyph('q')* 4 + + $self->wxByGlyph('r')*49 + + $self->wxByGlyph('s')*56 + + $self->wxByGlyph('t')*71 + + $self->wxByGlyph('u')*31 + + $self->wxByGlyph('v')*10 + + $self->wxByGlyph('w')*18 + + $self->wxByGlyph('x')* 3 + + $self->wxByGlyph('y')*18 + + $self->wxByGlyph('z')* 2 + + $self->wxByGlyph('A')*64 + + $self->wxByGlyph('B')*14 + + $self->wxByGlyph('C')*27 + + $self->wxByGlyph('D')*35 + + $self->wxByGlyph('E')*100 + + $self->wxByGlyph('F')*20 + + $self->wxByGlyph('G')*14 + + $self->wxByGlyph('H')*42 + + $self->wxByGlyph('I')*63 + + $self->wxByGlyph('J')* 3 + + $self->wxByGlyph('K')* 6 + + $self->wxByGlyph('L')*35 + + $self->wxByGlyph('M')*20 + + $self->wxByGlyph('N')*56 + + $self->wxByGlyph('O')*56 + + $self->wxByGlyph('P')*17 + + $self->wxByGlyph('Q')* 4 + + $self->wxByGlyph('R')*49 + + $self->wxByGlyph('S')*56 + + $self->wxByGlyph('T')*71 + + $self->wxByGlyph('U')*31 + + $self->wxByGlyph('V')*10 + + $self->wxByGlyph('W')*18 + + $self->wxByGlyph('X')* 3 + + $self->wxByGlyph('Y')*18 + + $self->wxByGlyph('Z')* 2 + + $self->wxByGlyph('space')*332 + ) / 2000); + return( int($aw) ); +} + +#line 322 + +sub flags { return( $_[0]->data->{flags} ); } + +#line 330 + +sub stemv { return( $_[0]->data->{stemv} ); } + +#line 338 + +sub stemh { return( $_[0]->data->{stemh} ); } + +#line 346 + +sub italicangle { return( $_[0]->data->{italicangle} ); } + +#line 354 + +sub isfixedpitch { return( $_[0]->data->{isfixedpitch} ); } + +#line 362 + +sub underlineposition { return( $_[0]->data->{underlineposition} ); } + +#line 370 + +sub underlinethickness { return( $_[0]->data->{underlinethickness} ); } + +#line 378 + +sub ascender { return( $_[0]->data->{ascender} ); } + +#line 386 + +sub descender { return( $_[0]->data->{descender} ); } + +#line 400 + +sub glyphNames { return ( keys %{$_[0]->data->{wx}} ); } + +#line 408 + +sub glyphNum { return ( scalar keys %{$_[0]->data->{wx}} ); } + +#line 416 + +sub uniByGlyph { return( $_[0]->data->{n2u}->{$_[1]} ); } + +#line 424 + +sub uniByEnc { return($_[0]->data->{e2u}->[$_[1]] ); } + +#line 432 + +sub uniByMap { return($_[0]->data->{uni}->[$_[1]]); } + +#line 440 + +sub encByGlyph { return( $_[0]->data->{n2e}->{$_[1]} || 0 ); } + +#line 448 + +sub encByUni { return( $_[0]->data->{u2e}->{$_[1]} || $_[0]->data->{u2c}->{$_[1]} || 0 ); } + +#line 456 + +sub mapByGlyph { return( $_[0]->data->{n2c}->{$_[1]} || 0 ); } + +#line 464 + +sub mapByUni { return( $_[0]->data->{u2c}->{$_[1]} || 0 ); } + +#line 474 + +sub glyphByUni { return ( $_[0]->data->{u2n}->{$_[1]} || '.notdef' ); } + +#line 482 + +sub glyphByEnc { + my ($self,$e)=@_; + my $g=$self->data->{e2n}->[$e]; + return( $g ); +} + +#line 494 + +sub glyphByMap { return ( $_[0]->data->{char}->[$_[1]] ); } + +#line 502 + +sub wxByGlyph +{ + my $self=shift; + my $val=shift; + my $ret=undef; + if(ref($self->data->{wx}) eq 'HASH') + { + $ret=$self->data->{wx}->{$val}; + if(!defined($ret)) + { + $ret=$self->missingwidth; + } + if(!defined($ret)) + { + $ret=300; + } + } + else + { + my $cid=$self->cidByUni(uniByName($val)); + $ret=$self->data->{wx}->[$cid]; + if(!defined($ret)) + { + $ret=$self->missingwidth; + } + if(!defined($ret)) + { + $ret=300; + } + } + return $ret; +} + +#line 541 + +sub wxByUni +{ + my $self=shift; + my $val=shift; + my $gid=$self->glyphByUni($val); + my $ret=$self->data->{wx}->{$gid}; + if(!defined($ret)) + { + $ret=$self->missingwidth; + } + if(!defined($ret)) + { + $ret=300; + } + return $ret; +} + +#line 564 + +sub wxByEnc +{ + my ($self,$e)=@_; + my $g=$self->glyphByEnc($e); + my $ret=$self->data->{wx}->{$g}; + if(!defined($ret)) + { + $ret=$self->missingwidth; + } + if(!defined($ret)) + { + $ret=300; + } + return $ret; +} + +#line 586 + +sub wxByMap +{ + my ($self,$m)=@_; + my $g=$self->glyphByMap($m); + my $ret=$self->data->{wx}->{$g}; + if(!defined($ret)) + { + $ret=$self->missingwidth; + } + if(!defined($ret)) + { + $ret=300; + } + return $ret; +} + +#line 610 + +sub width { + my ($self,$text)=@_; + my $width=0; + my @widths_cache; + if(is_utf8($text)) { + $text=$self->strByUtf($text) + } + + my $kern = $self->{-dokern} && ref($self->data->{kern}); + my $lastglyph=''; + foreach my $n (unpack('C*',$text)) + { + $widths_cache[$n] = $self->wxByEnc($n) unless defined $widths_cache[$n]; + $width += $widths_cache[$n]; + if ($kern) + { + $width+=$self->data->{kern}->{$lastglyph.':'.$self->data->{e2n}->[$n]}; + $lastglyph=$self->data->{e2n}->[$n]; + } + } + $width/=1000; + return($width); +} + +#line 640 + +sub width_array { + my ($self,$text)=@_; + if(!is_utf8($text)) { + $text=$self->utfByStr($text); + } + my @text=split(/\s+/,$text); + my @widths=map { $self->width($_) } @text; + return(@widths); +} + +#line 662 + +sub utfByStr { + my ($self,$s)=@_; + $s=pack('U*',map { $self->uniByEnc($_) } unpack('C*',$s)); + utf8::upgrade($s); + return($s); +} + +#line 675 + +sub strByUtf { + my ($self,$s)=@_; + $s=pack('C*',map { $self->encByUni($_) & 0xFF } unpack('U*',$s)); + utf8::downgrade($s); + return($s); +} + +#line 688 + +sub textByStr +{ + my ($self,$text)=@_; + my $newtext=''; + if(is_utf8($text)) + { + $text=$self->strByUtf($text); + } + $newtext=$text; + $newtext=~s/\\/\\\\/go; + $newtext=~s/([\x00-\x1f])/sprintf('\%03lo',ord($1))/ge; + $newtext=~s/([\{\}\[\]\(\)])/\\$1/g; + return($newtext); +} + +sub textByStrKern +{ + my ($self,$text)=@_; + if($self->{-dokern} && ref($self->data->{kern})) + { + my $newtext=' '; + if(is_utf8($text)) + { + $text=$self->strByUtf($text); + } + + my $lastglyph=''; + my $tBefore=0; + foreach my $n (unpack('C*',$text)) + { + if(defined $self->data->{kern}->{$lastglyph.':'.$self->data->{e2n}->[$n]}) + { + $newtext.=') ' if($tBefore); + $newtext.=sprintf('%i ',-($self->data->{kern}->{$lastglyph.':'.$self->data->{e2n}->[$n]})); + $tBefore=0; + } + $lastglyph=$self->data->{e2n}->[$n]; + my $t=pack('C',$n); + $t=~s/\\/\\\\/go; + $t=~s/([\x00-\x1f])/sprintf('\%03lo',ord($1))/ge; + $t=~s/([\{\}\[\]\(\)])/\\$1/g; + $newtext.='(' if(!$tBefore); + $newtext.="$t"; + $tBefore=1; + } + $newtext.=') ' if($tBefore); + return($newtext); + } + else + { + return('('.$self->textByStr($text).')'); + } +} + +sub text +{ + my ($self,$text,$size,$ident)=@_; + + my $newtext=$self->textByStr($text); + + if(defined $size && $self->{-dokern}) + { + $newtext=$self->textByStrKern($text); + if(defined($ident) && $ident!=0) + { + return("[ $ident $newtext ] TJ"); + } + else + { + return("[ $newtext ] TJ"); + } + } + elsif(defined $size) + { + if(defined($ident) && $ident!=0) + { + return("[ $ident ($newtext) ] TJ"); + } + else + { + return("[ ($newtext) ] TJ"); + } + } + else + { + return("($newtext)"); + } +} + +sub isvirtual { return(0); } + +#line 783 + +1; diff --git a/lib/PDF/API2/Resource/CIDFont.pm b/lib/PDF/API2/Resource/CIDFont.pm new file mode 100644 index 0000000..dbe2625 --- /dev/null +++ b/lib/PDF/API2/Resource/CIDFont.pm @@ -0,0 +1,328 @@ +#line 1 "PDF/API2/Resource/CIDFont.pm" +#line 1 "PDF/API2/Resource/CIDFont.pm" +package PDF::API2::Resource::CIDFont; + +use base 'PDF::API2::Resource::BaseFont'; + +use strict; +no warnings qw[ deprecated recursion uninitialized ]; + +our $VERSION = '2.033'; # VERSION + +use Encode qw(:all); + +use PDF::API2::Basic::PDF::Utils; +use PDF::API2::Util; + +#line 28 + +sub new +{ + my ($class,$pdf,$name,@opts) = @_; + my %opts=(); + %opts=@opts if((scalar @opts)%2 == 0); + + $class = ref $class if ref $class; + my $self=$class->SUPER::new($pdf,$name); + $pdf->new_obj($self) if(defined($pdf) && !$self->is_obj($pdf)); + + $self->{Type} = PDFName('Font'); + $self->{'Subtype'} = PDFName('Type0'); + $self->{'Encoding'} = PDFName('Identity-H'); + + my $de=PDFDict(); + $pdf->new_obj($de); + $self->{'DescendantFonts'} = PDFArray($de); + + $de->{'Type'} = PDFName('Font'); + $de->{'CIDSystemInfo'} = PDFDict(); + $de->{'CIDSystemInfo'}->{Registry} = PDFStr('Adobe'); + $de->{'CIDSystemInfo'}->{Ordering} = PDFStr('Identity'); + $de->{'CIDSystemInfo'}->{Supplement} = PDFNum(0); + $de->{'CIDToGIDMap'} = PDFName('Identity'); + + $self->{' de'} = $de; + + return($self); +} + +sub glyphByCId { return( $_[0]->data->{g2n}->[$_[1]] ); } + +sub uniByCId { return( $_[0]->data->{g2u}->[$_[1]] ); } + +sub cidByUni { return( $_[0]->data->{u2g}->{$_[1]} ); } + +sub cidByEnc { return( $_[0]->data->{e2g}->[$_[1]] ); } + +sub wxByCId +{ + my $self=shift @_; + my $g=shift @_; + my $w; + + if(ref($self->data->{wx}) eq 'ARRAY' && defined $self->data->{wx}->[$g]) + { + $w = int($self->data->{wx}->[$g]); + } + elsif(ref($self->data->{wx}) eq 'HASH' && defined $self->data->{wx}->{$g}) + { + $w = int($self->data->{wx}->{$g}); + } + else + { + $w = $self->missingwidth; + } + + return($w); +} + +sub wxByUni { return( $_[0]->wxByCId($_[0]->data->{u2g}->{$_[1]}) ); } +sub wxByEnc { return( $_[0]->wxByCId($_[0]->data->{e2g}->[$_[1]]) ); } + +sub width +{ + my ($self,$text)=@_; + return($self->width_cid($self->cidsByStr($text))); +} + +sub width_cid +{ + my ($self,$text)=@_; + my $width=0; + my $lastglyph=0; + foreach my $n (unpack('n*',$text)) + { + $width+=$self->wxByCId($n); + if($self->{-dokern} && $self->haveKernPairs()) + { + if($self->kernPairCid($lastglyph, $n)) + { + $width-=$self->kernPairCid($lastglyph, $n); + } + } + $lastglyph=$n; + } + $width/=1000; + return($width); +} + +#line 124 + +sub _cidsByStr +{ + my ($self,$s)=@_; + $s=pack('n*',map { $self->cidByEnc($_) } unpack('C*',$s)); + return($s); +} + +sub cidsByStr +{ + my ($self,$text)=@_; + if(is_utf8($text) && defined $self->data->{decode} && $self->data->{decode} ne 'ident') + { + $text=encode($self->data->{decode},$text); + } + elsif(is_utf8($text) && $self->data->{decode} eq 'ident') + { + $text=$self->cidsByUtf($text); + } + elsif(!is_utf8($text) && defined $self->data->{encode} && $self->data->{decode} eq 'ident') + { + $text=$self->cidsByUtf(decode($self->data->{encode},$text)); + } + elsif(!is_utf8($text) && $self->can('issymbol') && $self->issymbol && $self->data->{decode} eq 'ident') + { + $text=pack('U*',(map { $_+0xf000 } unpack('C*',$text))); + $text=$self->cidsByUtf($text); + } + else + { + $text=$self->_cidsByStr($text); + } + return($text); +} + +#line 164 + +sub cidsByUtf { + my ($self,$s)=@_; + $s=pack('n*',map { $self->cidByUni($_) } (map { $_>0x7f && $_<0xA0 ? uniByName(nameByUni($_)): $_ } unpack('U*',$s))); + utf8::downgrade($s); + return($s); +} + +sub textByStr +{ + my ($self,$text)=@_; + return($self->text_cid($self->cidsByStr($text))); +} + +sub textByStrKern +{ + my ($self,$text,$size,$ident)=@_; + return($self->text_cid_kern($self->cidsByStr($text),$size,$ident)); +} + +sub text +{ + my ($self,$text,$size,$ident)=@_; + my $newtext=$self->textByStr($text); + if(defined $size && $self->{-dokern}) + { + $newtext=$self->textByStrKern($text,$size,$ident); + return($newtext); + } + elsif(defined $size) + { + if(defined($ident) && $ident!=0) + { + return("[ $ident $newtext ] TJ"); + } + else + { + return("$newtext Tj"); + } + } + else + { + return($newtext); + } +} + +sub text_cid +{ + my ($self,$text,$size)=@_; + if($self->can('fontfile')) + { + foreach my $g (unpack('n*',$text)) + { + $self->fontfile->subsetByCId($g); + } + } + my $newtext=unpack('H*',$text); + if(defined $size) + { + return("<$newtext> Tj"); + } + else + { + return("<$newtext>"); + } +} + +sub text_cid_kern +{ + my ($self,$text,$size,$ident)=@_; + if($self->can('fontfile')) + { + foreach my $g (unpack('n*',$text)) + { + $self->fontfile->subsetByCId($g); + } + } + if(defined $size && $self->{-dokern} && $self->haveKernPairs()) + { + my $newtext=' '; + my $lastglyph=0; + my $tBefore=0; + foreach my $n (unpack('n*',$text)) + { + if($self->kernPairCid($lastglyph, $n)) + { + $newtext.='> ' if($tBefore); + $newtext.=sprintf('%i ',$self->kernPairCid($lastglyph, $n)); + $tBefore=0; + } + $lastglyph=$n; + my $t=sprintf('%04X',$n); + $newtext.='<' if(!$tBefore); + $newtext.=$t; + $tBefore=1; + } + $newtext.='> ' if($tBefore); + if(defined($ident) && $ident!=0) + { + return("[ $ident $newtext ] TJ"); + } + else + { + return("[ $newtext ] TJ"); + } + } + elsif(defined $size) + { + my $newtext=unpack('H*',$text); + if(defined($ident) && $ident!=0) + { + return("[ $ident <$newtext> ] TJ"); + } + else + { + return("<$newtext> Tj"); + } + } + else + { + my $newtext=unpack('H*',$text); + return("<$newtext>"); + } +} + +sub kernPairCid +{ + return(0); +} + +sub haveKernPairs +{ + return(0); +} + +sub encodeByName +{ + my ($self,$enc) = @_; + return if($self->issymbol); + + $self->data->{e2u}=[ map { $_>0x7f && $_<0xA0 ? uniByName(nameByUni($_)): $_ } unpack('U*',decode($enc, pack('C*',0..255))) ] if(defined $enc); + $self->data->{e2n}=[ map { $self->data->{g2n}->[$self->data->{u2g}->{$_} || 0] || '.notdef' } @{$self->data->{e2u}} ]; + $self->data->{e2g}=[ map { $self->data->{u2g}->{$_} || 0 } @{$self->data->{e2u}} ]; + + $self->data->{u2e}={}; + foreach my $n (reverse 0..255) + { + $self->data->{u2e}->{$self->data->{e2u}->[$n]}=$n unless(defined $self->data->{u2e}->{$self->data->{e2u}->[$n]}); + } + + return($self); +} + +sub subsetByCId +{ + return(1); +} + +sub subvec +{ + return(1); +} + +sub glyphNum +{ + my $self=shift @_; + if(defined $self->data->{glyphs}) + { + return ( $self->data->{glyphs} ); + } + return ( scalar @{$self->data->{wx}} ); +} + +sub outobjdeep +{ + my ($self, $fh, $pdf, %opts) = @_; + + $self->SUPER::outobjdeep($fh, $pdf, %opts); +} + +#line 347 + +1; diff --git a/lib/PDF/API2/Resource/CIDFont/CJKFont.pm b/lib/PDF/API2/Resource/CIDFont/CJKFont.pm new file mode 100644 index 0000000..ae4c519 --- /dev/null +++ b/lib/PDF/API2/Resource/CIDFont/CJKFont.pm @@ -0,0 +1,300 @@ +#line 1 "PDF/API2/Resource/CIDFont/CJKFont.pm" +#line 1 "PDF/API2/Resource/CIDFont/CJKFont.pm" +package PDF::API2::Resource::CIDFont::CJKFont; + +use base 'PDF::API2::Resource::CIDFont'; + +use strict; +no warnings qw[ deprecated recursion uninitialized ]; + +our $VERSION = '2.033'; # VERSION + +use PDF::API2::Util; +use PDF::API2::Basic::PDF::Utils; + +our $fonts = {}; +our $cmap = {}; +our $alias; +our $subs; + +#line 45 + +sub _look_for_font { + my $fname=lc(shift); + $fname=~s/[^a-z0-9]+//gi; + $fname=$alias->{$fname} if(defined $alias->{$fname}); + return({%{$fonts->{$fname}}}) if(defined $fonts->{$fname}); + + if(defined $subs->{$fname}) { + my $data=_look_for_font($subs->{$fname}->{-alias}); + foreach my $k (keys %{$subs->{$fname}}) { + next if($k=~/^\-/); + if(substr($k,0,1) eq '+') + { + $data->{substr($k,1)}.=$subs->{$fname}->{$k}; + } + else + { + $data->{$k}=$subs->{$fname}->{$k}; + } + } + $fonts->{$fname}=$data; + return({%{$data}}) + } + + eval "require 'PDF/API2/Resource/CIDFont/CJKFont/$fname.data'"; + unless($@){ + return({%{$fonts->{$fname}}}); + } else { + die "requested font '$fname' not installed "; + } +} + +sub _look_for_cmap { + my $fname=lc(shift); + $fname=~s/[^a-z0-9]+//gi; + return({%{$cmap->{$fname}}}) if(defined $cmap->{$fname}); + eval "require \"PDF/API2/Resource/CIDFont/CMap/$fname.cmap\""; + unless($@){ + return({%{$cmap->{$fname}}}); + } else { + die "requested cmap '$fname' not installed "; + } +} +sub new { + my ($class,$pdf,$name,@opts) = @_; + my %opts=(); + %opts=@opts if((scalar @opts)%2 == 0); + $opts{-encode}||='ident'; + + my $data = _look_for_font($name); + + my $cmap = _look_for_cmap($data->{cmap}); + + $data->{u2g} = { %{$cmap->{u2g}} }; + $data->{g2u} = [ @{$cmap->{g2u}} ]; + + $class = ref $class if ref $class; + my $self=$class->SUPER::new($pdf,$data->{apiname}.pdfkey()); + $pdf->new_obj($self) if(defined($pdf) && !$self->is_obj($pdf)); + + $self->{' data'}=$data; + + my $des=$self->descrByData; + + my $de=$self->{' de'}; + + if(defined $opts{-encode} && $opts{-encode} ne 'ident') { + $self->data->{encode}=$opts{-encode}; + } + + my $emap={ + 'reg'=>'Adobe', + 'ord'=>'Identity', + 'sup'=> 0, + 'map'=>'Identity', + 'dir'=>'H', + 'dec'=>'ident', + }; + + if(defined $cmap->{ccs}) { + $emap->{reg}=$cmap->{ccs}->[0]; + $emap->{ord}=$cmap->{ccs}->[1]; + $emap->{sup}=$cmap->{ccs}->[2]; + } + + #if(defined $cmap->{cmap} && defined $cmap->{cmap}->{$opts{-encode}} ) { + # $emap->{dec}=$cmap->{cmap}->{$opts{-encode}}->[0]; + # $emap->{map}=$cmap->{cmap}->{$opts{-encode}}->[1]; + #} elsif(defined $cmap->{cmap} && defined $cmap->{cmap}->{'utf8'} ) { + # $emap->{dec}=$cmap->{cmap}->{'utf8'}->[0]; + # $emap->{map}=$cmap->{cmap}->{'utf8'}->[1]; + #} + + $self->data->{decode}=$emap->{dec}; + + $self->{'BaseFont'} = PDFName($self->fontname."-$emap->{map}-$emap->{dir}"); + $self->{'Encoding'} = PDFName("$emap->{map}-$emap->{dir}"); + + $de->{'FontDescriptor'} = $des; + $de->{'Subtype'} = PDFName('CIDFontType0'); + $de->{'BaseFont'} = PDFName($self->fontname); + $de->{'DW'} = PDFNum($self->missingwidth); + $de->{'CIDSystemInfo'}->{Registry} = PDFStr($emap->{reg}); + $de->{'CIDSystemInfo'}->{Ordering} = PDFStr($emap->{ord}); + $de->{'CIDSystemInfo'}->{Supplement} = PDFNum($emap->{sup}); + ## $de->{'CIDToGIDMap'} = PDFName($emap->{map}); # ttf only + + return($self); +} + +sub tounicodemap { + my $self=shift @_; + # noop since pdf knows its char-collection + return($self); +} + +sub glyphByCId +{ + my ($self,$cid)=@_; + my $uni = $self->uniByCId($cid); + return( nameByUni($uni) ); +} + +sub outobjdeep { + my ($self, $fh, $pdf, %opts) = @_; + + my $notdefbefore=1; + + my $wx=PDFArray(); + $self->{' de'}->{'W'} = $wx; + my $ml; + + foreach my $w (0..(scalar @{$self->data->{g2u}} - 1 )) { + if(ref($self->data->{wx}) eq 'ARRAY' + && (defined $self->data->{wx}->[$w]) + && ($self->data->{wx}->[$w] != $self->missingwidth) + && $notdefbefore==1) + { + $notdefbefore=0; + $ml=PDFArray(); + $wx->add_elements(PDFNum($w),$ml); + $ml->add_elements(PDFNum($self->data->{wx}->[$w])); + } + elsif(ref($self->data->{wx}) eq 'HASH' + && (defined $self->data->{wx}->{$w}) + && ($self->data->{wx}->{$w} != $self->missingwidth) + && $notdefbefore==1) + { + $notdefbefore=0; + $ml=PDFArray(); + $wx->add_elements(PDFNum($w),$ml); + $ml->add_elements(PDFNum($self->data->{wx}->{$w})); + } + elsif(ref($self->data->{wx}) eq 'ARRAY' + && (defined $self->data->{wx}->[$w]) + && ($self->data->{wx}->[$w] != $self->missingwidth) + && $notdefbefore==0) + { + $notdefbefore=0; + $ml->add_elements(PDFNum($self->data->{wx}->[$w])); + } + elsif(ref($self->data->{wx}) eq 'HASH' + && (defined $self->data->{wx}->{$w}) + && ($self->data->{wx}->{$w} != $self->missingwidth) + && $notdefbefore==0) + { + $notdefbefore=0; + $ml->add_elements(PDFNum($self->data->{wx}->{$w})); + } + else + { + $notdefbefore=1; + } + } + + $self->SUPER::outobjdeep($fh, $pdf, %opts); +} + +BEGIN { + + $alias={ + 'traditional' => 'adobemingstdlightacro', + 'traditionalbold' => 'mingbold', + 'traditionalitalic' => 'mingitalic', + 'traditionalbolditalic' => 'mingbolditalic', + 'ming' => 'adobemingstdlightacro', + + 'simplified' => 'adobesongstdlightacro', + 'simplifiedbold' => 'songbold', + 'simplifieditalic' => 'songitalic', + 'simplifiedbolditalic' => 'songbolditalic', + 'song' => 'adobesongstdlightacro', + + 'korean' => 'adobemyungjostdmediumacro', + 'koreanbold' => 'myungjobold', + 'koreanitalic' => 'myungjoitalic', + 'koreanbolditalic' => 'myungjobolditalic', + 'myungjo' => 'adobemyungjostdmediumacro', + + 'japanese' => 'kozminproregularacro', + 'japanesebold' => 'kozminbold', + 'japaneseitalic' => 'kozminitalic', + 'japanesebolditalic' => 'kozminbolditalic', + 'kozmin' => 'kozminproregularacro', + 'kozgo' => 'kozgopromediumacro', + + }; + $subs={ + # Chinese Traditional (ie. Taiwan) Fonts + 'mingitalic' => { + '-alias' => 'adobemingstdlightacro', + '+fontname' => ',Italic', + }, + 'mingbold' => { + '-alias' => 'adobemingstdlightacro', + '+fontname' => ',Bold', + }, + 'mingbolditalic' => { + '-alias' => 'adobemingstdlightacro', + '+fontname' => ',BoldItalic', + }, + # Chinese Simplified (ie. Mainland China) Fonts + 'songitalic' => { + '-alias' => 'adobesongstdlightacro', + '+fontname' => ',Italic', + }, + 'songbold' => { + '-alias' => 'adobesongstdlightacro', + '+fontname' => ',Bold', + }, + 'songbolditalic' => { + '-alias' => 'adobesongstdlightacro', + '+fontname' => ',BoldItalic', + }, + # Japanese Gothic (ie. sans) Fonts + 'kozgoitalic' => { + '-alias' => 'kozgopromediumacro', + '+fontname' => ',Italic', + }, + 'kozgobold' => { + '-alias' => 'kozgopromediumacro', + '+fontname' => ',Bold', + }, + 'kozgobolditalic' => { + '-alias' => 'kozgopromediumacro', + '+fontname' => ',BoldItalic', + }, + # Japanese Mincho (ie. serif) Fonts + 'kozminitalic' => { + '-alias' => 'kozminproregularacro', + '+fontname' => ',Italic', + }, + 'kozminbold' => { + '-alias' => 'kozminproregularacro', + '+fontname' => ',Bold', + }, + 'kozminbolditalic' => { + '-alias' => 'kozminproregularacro', + '+fontname' => ',BoldItalic', + }, + # Korean Fonts + 'myungjoitalic' => { + '-alias' => 'adobemyungjostdmediumacro', + '+fontname' => ',Italic', + }, + 'myungjobold' => { + '-alias' => 'adobemyungjostdmediumacro', + '+fontname' => ',Bold', + }, + 'myungjobolditalic' => { + '-alias' => 'adobemyungjostdmediumacro', + '+fontname' => ',BoldItalic', + }, + }; + +} + +#line 325 + +1; diff --git a/lib/PDF/API2/Resource/CIDFont/TrueType.pm b/lib/PDF/API2/Resource/CIDFont/TrueType.pm new file mode 100644 index 0000000..b27758b --- /dev/null +++ b/lib/PDF/API2/Resource/CIDFont/TrueType.pm @@ -0,0 +1,166 @@ +#line 1 "PDF/API2/Resource/CIDFont/TrueType.pm" +#line 1 "PDF/API2/Resource/CIDFont/TrueType.pm" +package PDF::API2::Resource::CIDFont::TrueType; + +use base 'PDF::API2::Resource::CIDFont'; + +use strict; +no warnings qw[ deprecated recursion uninitialized ]; + +our $VERSION = '2.033'; # VERSION + +use PDF::API2::Basic::PDF::Utils; +use PDF::API2::Resource::CIDFont::TrueType::FontFile; +use PDF::API2::Util; + +#line 33 + +sub new { + my ($class,$pdf,$file,@opts) = @_; + my %opts=(); + %opts=@opts if((scalar @opts)%2 == 0); + $opts{-encode}||='latin1'; + my ($ff,$data)=PDF::API2::Resource::CIDFont::TrueType::FontFile->new($pdf,$file,@opts); + + $class = ref $class if ref $class; + my $self=$class->SUPER::new($pdf,$data->{apiname}.pdfkey().'~'.time()); + $pdf->new_obj($self) if(defined($pdf) && !$self->is_obj($pdf)); + + $self->{' data'}=$data; + + my $des=$self->descrByData; + + $self->{'BaseFont'} = PDFName($self->fontname); + + my $de=$self->{' de'}; + + $de->{'FontDescriptor'} = $des; + $de->{'Subtype'} = PDFName($self->iscff ? 'CIDFontType0' : 'CIDFontType2'); + ## $de->{'BaseFont'} = PDFName(pdfkey().'+'.($self->fontname).'~'.time()); + $de->{'BaseFont'} = PDFName($self->fontname); + $de->{'DW'} = PDFNum($self->missingwidth); + if($opts{-noembed} != 1) + { + $des->{$self->data->{iscff} ? 'FontFile3' : 'FontFile2'}=$ff; + } + unless($self->issymbol) { + $self->encodeByName($opts{-encode}); + $self->data->{encode}=$opts{-encode}; + $self->data->{decode}='ident'; + } + + if($opts{-nosubset}) { + $self->data->{nosubset}=1; + } + + + $self->{' ff'} = $ff; + $pdf->new_obj($ff); + + $self->{-dokern}=1 if($opts{-dokern}); + + return($self); +} + + +sub fontfile { return( $_[0]->{' ff'} ); } +sub fontobj { return( $_[0]->data->{obj} ); } + +sub wxByCId +{ + my $self=shift @_; + my $g=shift @_; + my $t = $self->fontobj->{'hmtx'}->read->{'advance'}[$g]; + my $w; + + if(defined $t) + { + $w = int($t*1000/$self->data->{upem}); + } + else + { + $w = $self->missingwidth; + } + + return($w); +} + +sub haveKernPairs +{ + my $self = shift @_; + return($self->fontfile->haveKernPairs(@_)); +} + +sub kernPairCid +{ + my $self = shift @_; + return($self->fontfile->kernPairCid(@_)); +} + +sub subsetByCId +{ + my $self = shift @_; + return if($self->iscff); + my $g = shift @_; + $self->fontfile->subsetByCId($g); +} +sub subvec +{ + my $self = shift @_; + return(1) if($self->iscff); + my $g = shift @_; + $self->fontfile->subvec($g); +} + +sub glyphNum { return ( $_[0]->fontfile->glyphNum ); } + +sub outobjdeep +{ + my ($self, $fh, $pdf, %opts) = @_; + + my $notdefbefore=1; + + my $wx=PDFArray(); + $self->{' de'}->{'W'} = $wx; + my $ml; + + foreach my $w (0..(scalar @{$self->data->{g2u}} - 1 )) + { + if($self->subvec($w) && $notdefbefore==1) + { + $notdefbefore=0; + $ml=PDFArray(); + $wx->add_elements(PDFNum($w),$ml); + # $ml->add_elements(PDFNum($self->data->{wx}->[$w])); + $ml->add_elements(PDFNum($self->wxByCId($w))); + } + elsif($self->subvec($w) && $notdefbefore==0) + { + $notdefbefore=0; + # $ml->add_elements(PDFNum($self->data->{wx}->[$w])); + $ml->add_elements(PDFNum($self->wxByCId($w))); + } + else + { + $notdefbefore=1; + } + # optimization for cjk + #if($self->subvec($w) && $notdefbefore==1 && $self->data->{wx}->[$w]!=$self->missingwidth) { + # $notdefbefore=0; + # $ml=PDFArray(); + # $wx->add_elements(PDFNum($w),$ml); + # $ml->add_elements(PDFNum($self->data->{wx}->[$w])); + #} elsif($self->subvec($w) && $notdefbefore==0 && $self->data->{wx}->[$w]!=$self->missingwidth) { + # $notdefbefore=0; + # $ml->add_elements(PDFNum($self->data->{wx}->[$w])); + #} else { + # $notdefbefore=1; + #} + } + + $self->SUPER::outobjdeep($fh, $pdf, %opts); +} + +#line 183 + +1; diff --git a/lib/PDF/API2/Resource/CIDFont/TrueType/FontFile.pm b/lib/PDF/API2/Resource/CIDFont/TrueType/FontFile.pm new file mode 100644 index 0000000..5869fbb --- /dev/null +++ b/lib/PDF/API2/Resource/CIDFont/TrueType/FontFile.pm @@ -0,0 +1,682 @@ +#line 1 "PDF/API2/Resource/CIDFont/TrueType/FontFile.pm" +#line 1 "PDF/API2/Resource/CIDFont/TrueType/FontFile.pm" +package PDF::API2::Resource::CIDFont::TrueType::FontFile; + +use base 'PDF::API2::Basic::PDF::Dict'; + +use strict; +no warnings qw[ recursion uninitialized ]; + +our $VERSION = '2.033'; # VERSION + +use Encode qw(:all); +use Font::TTF::Font; +use POSIX qw(ceil floor); + +use PDF::API2::Util; +use PDF::API2::Basic::PDF::Utils; + +our $cmap = {}; + +sub _look_for_cmap { + my $fname=lc(shift); + $fname=~s/[^a-z0-9]+//gi; + return({%{$cmap->{$fname}}}) if(defined $cmap->{$fname}); + eval "require 'PDF/API2/Resource/CIDFont/CMap/$fname.cmap'"; + unless($@){ + return({%{$cmap->{$fname}}}); + } else { + die "requested cmap '$fname' not installed "; + } +} + +sub readcffindex +{ + my ($fh,$off,$buf)=@_; + my @idx=(); + my $index=[]; + seek($fh,$off,0); + read($fh,$buf,3); + my ($count,$offsize)=unpack('nC',$buf); + foreach (0..$count) + { + read($fh,$buf,$offsize); + $buf=substr("\x00\x00\x00$buf",-4,4); + my $id=unpack('N',$buf); + push @idx,$id; + } + my $dataoff=tell($fh)-1; + + foreach my $i (0..$count-1) + { + push @{$index},{ 'OFF' => $dataoff+$idx[$i], 'LEN' => $idx[$i+1]-$idx[$i] }; + } + return($index); +} + +sub readcffdict +{ + my ($fh,$off,$len,$foff,$buf)=@_; + my @idx=(); + my $dict={}; + seek($fh,$off,0); + my @st=(); + while(tell($fh)<($off+$len)) + { + read($fh,$buf,1); + my $b0=unpack('C',$buf); + my $v=''; + + if($b0==12) # two byte commands + { + read($fh,$buf,1); + my $b1=unpack('C',$buf); + if($b1==0) + { + $dict->{Copyright}={ 'SID' => splice(@st,-1) }; + } + elsif($b1==1) + { + $dict->{isFixedPitch}=splice(@st,-1); + } + elsif($b1==2) + { + $dict->{ItalicAngle}=splice(@st,-1); + } + elsif($b1==3) + { + $dict->{UnderlinePosition}=splice(@st,-1); + } + elsif($b1==4) + { + $dict->{UnderlineThickness}=splice(@st,-1); + } + elsif($b1==5) + { + $dict->{PaintType}=splice(@st,-1); + } + elsif($b1==6) + { + $dict->{CharstringType}=splice(@st,-1); + } + elsif($b1==7) + { + $dict->{FontMatrix}=[ splice(@st,-4) ]; + } + elsif($b1==8) + { + $dict->{StrokeWidth}=splice(@st,-1); + } + elsif($b1==20) + { + $dict->{SyntheticBase}=splice(@st,-1); + } + elsif($b1==21) + { + $dict->{PostScript}={ 'SID' => splice(@st,-1) }; + } + elsif($b1==22) + { + $dict->{BaseFontName}={ 'SID' => splice(@st,-1) }; + } + elsif($b1==23) + { + $dict->{BaseFontBlend}=[ splice(@st,0) ]; + } + elsif($b1==24) + { + $dict->{MultipleMaster}=[ splice(@st,0) ]; + } + elsif($b1==25) + { + $dict->{BlendAxisTypes}=[ splice(@st,0) ]; + } + elsif($b1==30) + { + $dict->{ROS}=[ splice(@st,-3) ]; + } + elsif($b1==31) + { + $dict->{CIDFontVersion}=splice(@st,-1); + } + elsif($b1==32) + { + $dict->{CIDFontRevision}=splice(@st,-1); + } + elsif($b1==33) + { + $dict->{CIDFontType}=splice(@st,-1); + } + elsif($b1==34) + { + $dict->{CIDCount}=splice(@st,-1); + } + elsif($b1==35) + { + $dict->{UIDBase}=splice(@st,-1); + } + elsif($b1==36) + { + $dict->{FDArray}={ 'OFF' => $foff+splice(@st,-1) }; + } + elsif($b1==37) + { + $dict->{FDSelect}={ 'OFF' => $foff+splice(@st,-1) }; + } + elsif($b1==38) + { + $dict->{FontName}={ 'SID' => splice(@st,-1) }; + } + elsif($b1==39) + { + $dict->{Chameleon}=splice(@st,-1); + } + next; + } + elsif($b0<28) # commands + { + if($b0==0) + { + $dict->{Version}={ 'SID' => splice(@st,-1) }; + } + elsif($b0==1) + { + $dict->{Notice}={ 'SID' => splice(@st,-1) }; + } + elsif($b0==2) + { + $dict->{FullName}={ 'SID' => splice(@st,-1) }; + } + elsif($b0==3) + { + $dict->{FamilyName}={ 'SID' => splice(@st,-1) }; + } + elsif($b0==4) + { + $dict->{Weight}={ 'SID' => splice(@st,-1) }; + } + elsif($b0==5) + { + $dict->{FontBBX}=[ splice(@st,-4) ]; + } + elsif($b0==13) + { + $dict->{UniqueID}=splice(@st,-1); + } + elsif($b0==14) + { + $dict->{XUID}=[splice(@st,0)]; + } + elsif($b0==15) + { + $dict->{CharSet}={ 'OFF' => $foff+splice(@st,-1) }; + } + elsif($b0==16) + { + $dict->{Encoding}={ 'OFF' => $foff+splice(@st,-1) }; + } + elsif($b0==17) + { + $dict->{CharStrings}={ 'OFF' => $foff+splice(@st,-1) }; + } + elsif($b0==18) + { + $dict->{Private}={ 'LEN' => splice(@st,-1), 'OFF' => $foff+splice(@st,-1) }; + } + next; + } + elsif($b0==28) # int16 + { + read($fh,$buf,2); + $v=unpack('n',$buf); + $v=-(0x10000-$v) if($v>0x7fff); + } + elsif($b0==29) # int32 + { + read($fh,$buf,4); + $v=unpack('N',$buf); + $v=-$v+0xffffffff+1 if($v>0x7fffffff); + } + elsif($b0==30) # float + { + my $e=1; + while($e) + { + read($fh,$buf,1); + my $v0=unpack('C',$buf); + foreach my $m ($v0>>8,$v0&0xf) + { + if($m<10) + { + $v.=$m; + } + elsif($m==10) + { + $v.='.'; + } + elsif($m==11) + { + $v.='E+'; + } + elsif($m==12) + { + $v.='E-'; + } + elsif($m==14) + { + $v.='-'; + } + elsif($m==15) + { + $e=0; + last; + } + } + } + } + elsif($b0==31) # command + { + $v="c=$b0"; + next; + } + elsif($b0<247) # 1 byte signed + { + $v=$b0-139; + } + elsif($b0<251) # 2 byte plus + { + read($fh,$buf,1); + $v=unpack('C',$buf); + $v=($b0-247)*256+($v+108); + } + elsif($b0<255) # 2 byte minus + { + read($fh,$buf,1); + $v=unpack('C',$buf); + $v=-($b0-251)*256-$v-108; + } + push @st,$v; + } + + return($dict); +} + +sub read_kern_table +{ + my $font=shift @_; + my $upem=shift @_; + my $self=shift @_; + my $fh=$font->{' INFILE'}; + my $data=undef; + + return(undef) unless($font->{kern}); + + my $buf = undef; + + seek($fh,$font->{kern}->{' OFFSET'}+2,0); + read($fh,$buf, 2); + my $num=unpack('n',$buf); + foreach my $n (1..$num) + { + read($fh, $buf, 6); + my ($ver, $len, $cov) = unpack('n3', $buf); + $len-=6; + my $fmt=$cov>>8; + if($fmt==0) + { + $data||={}; + read($fh, $buf, 8); + my $nc = unpack('n', $buf); + foreach (1..$nc) + { + read($fh, $buf, 6); + my ($idx1,$idx2,$val)=unpack('nnn',$buf); + $val-=65536 if($val>32767); + $val= $val < 0 ? -floor($val*1000/$upem) : -ceil($val*1000/$upem); + if($val != 0) + { + $data->{"$idx1:$idx2"}=$val; + $data->{$self->data->{g2n}->[$idx1].':'.$self->data->{g2n}->[$idx2]}=$val; + } + } + } + elsif($fmt==2) + { + read($fh, $buf, $len); + } + else + { + read($fh, $buf, $len); + } + } + return($data); +} + +sub readcffstructs +{ + my $font=shift @_; + my $fh=$font->{' INFILE'}; + my $data={}; + # read CFF table + seek($fh,$font->{'CFF '}->{' OFFSET'},0); + my $buf; + read($fh,$buf, 4); + my ($cffmajor,$cffminor,$cffheadsize,$cffglobaloffsize)=unpack('C4',$buf); + + $data->{name}=readcffindex($fh,$font->{'CFF '}->{' OFFSET'}+$cffheadsize); + foreach my $dict (@{$data->{name}}) + { + seek($fh,$dict->{OFF},0); + read($fh,$dict->{VAL},$dict->{LEN}); + } + + $data->{topdict}=readcffindex($fh,$data->{name}->[-1]->{OFF}+$data->{name}->[-1]->{LEN}); + foreach my $dict (@{$data->{topdict}}) + { + $dict->{VAL}=readcffdict($fh,$dict->{OFF},$dict->{LEN},$font->{'CFF '}->{' OFFSET'}); + } + + $data->{string}=readcffindex($fh,$data->{topdict}->[-1]->{OFF}+$data->{topdict}->[-1]->{LEN}); + foreach my $dict (@{$data->{string}}) + { + seek($fh,$dict->{OFF},0); + read($fh,$dict->{VAL},$dict->{LEN}); + } + push @{$data->{string}},{ 'VAL' => '001.000' }; + push @{$data->{string}},{ 'VAL' => '001.001' }; + push @{$data->{string}},{ 'VAL' => '001.002' }; + push @{$data->{string}},{ 'VAL' => '001.003' }; + push @{$data->{string}},{ 'VAL' => 'Black' }; + push @{$data->{string}},{ 'VAL' => 'Bold' }; + push @{$data->{string}},{ 'VAL' => 'Book' }; + push @{$data->{string}},{ 'VAL' => 'Light' }; + push @{$data->{string}},{ 'VAL' => 'Medium' }; + push @{$data->{string}},{ 'VAL' => 'Regular' }; + push @{$data->{string}},{ 'VAL' => 'Roman' }; + push @{$data->{string}},{ 'VAL' => 'Semibold' }; + + foreach my $dict (@{$data->{topdict}}) + { + foreach my $k (keys %{$dict->{VAL}}) + { + my $dt=$dict->{VAL}->{$k}; + if($k eq 'ROS') + { + $dict->{VAL}->{$k}->[0]=$data->{string}->[$dict->{VAL}->{$k}->[0]-391]->{VAL}; + $dict->{VAL}->{$k}->[1]=$data->{string}->[$dict->{VAL}->{$k}->[1]-391]->{VAL}; + next; + } + next unless(ref($dt) eq 'HASH' && defined $dt->{SID}); + if($dt->{SID}>=379) + { + $dict->{VAL}->{$k}=$data->{string}->[$dt->{SID}-391]->{VAL}; + } + } + } + my $dict={}; + foreach my $k (qw[ CIDCount CIDFontVersion FamilyName FontBBX FullName ROS Weight XUID ]) + { + $dict->{$k}=$data->{topdict}->[0]->{VAL}->{$k} if(defined $data->{topdict}->[0]->{VAL}->{$k}); + } + return($dict); +} + +sub new { + my ($class,$pdf,$file,%opts)=@_; + my $data={}; + + die "cannot find font '$file' ..." unless(-f $file); + my $font=Font::TTF::Font->open($file); + $data->{obj}=$font; + + $class = ref $class if ref $class; + my $self=$class->SUPER::new(); + + $self->{Filter}=PDFArray(PDFName('FlateDecode')); + $self->{' font'}=$font; + $self->{' data'}=$data; + + $data->{noembed} = $opts{-noembed}==1 ? 1 : 0; + $data->{iscff} = (defined $font->{'CFF '}) ? 1 : 0; + + $self->{Subtype}=PDFName('CIDFontType0C') if($data->{iscff}); + + $data->{fontfamily}=$font->{'name'}->read->find_name(1); + $data->{fontname}=$font->{'name'}->read->find_name(4); + + $font->{'OS/2'}->read; + my @stretch=qw[ + Normal + UltraCondensed + ExtraCondensed + Condensed + SemiCondensed + Normal + SemiExpanded + Expanded + ExtraExpanded + UltraExpanded + ]; + $data->{fontstretch}=$stretch[$font->{'OS/2'}->{usWidthClass}] || 'Normal'; + + $data->{fontweight}=$font->{'OS/2'}->{usWeightClass}; + + $data->{panose}=pack('n',$font->{'OS/2'}->{sFamilyClass}); + + foreach my $p (qw[bFamilyType bSerifStyle bWeight bProportion bContrast bStrokeVariation bArmStyle bLetterform bMidline bXheight]) + { + $data->{panose}.=pack('C',$font->{'OS/2'}->{$p}); + } + + $data->{apiname}=join('', map { ucfirst(lc(substr($_, 0, 2))) } split m/[^A-Za-z0-9\s]+/, $data->{fontname}); + $data->{fontname}=~s/[\x00-\x1f\s]//og; + + $data->{altname}=$font->{'name'}->find_name(1); + $data->{altname}=~s/[\x00-\x1f\s]//og; + + $data->{subname}=$font->{'name'}->find_name(2); + $data->{subname}=~s/[\x00-\x1f\s]//og; + + $font->{cmap}->read->find_ms($opts{-isocmap}||0); + if(defined $font->{cmap}->find_ms) + { + $data->{issymbol} = ($font->{cmap}->find_ms->{'Platform'} == 3 && $font->{cmap}->read->find_ms->{'Encoding'} == 0) || 0; + } + else + { + $data->{issymbol} = 0; + } + + $data->{upem}=$font->{'head'}->read->{'unitsPerEm'}; + + $data->{fontbbox}=[ + int($font->{'head'}->{'xMin'} * 1000 / $data->{upem}), + int($font->{'head'}->{'yMin'} * 1000 / $data->{upem}), + int($font->{'head'}->{'xMax'} * 1000 / $data->{upem}), + int($font->{'head'}->{'yMax'} * 1000 / $data->{upem}) + ]; + + $data->{stemv}=0; + $data->{stemh}=0; + + $data->{missingwidth}=int($font->{'hhea'}->read->{'advanceWidthMax'} * 1000 / $data->{upem}) || 1000; + $data->{maxwidth}=int($font->{'hhea'}->{'advanceWidthMax'} * 1000 / $data->{upem}); + $data->{ascender}=int($font->{'hhea'}->read->{'Ascender'} * 1000 / $data->{upem}); + $data->{descender}=int($font->{'hhea'}{'Descender'} * 1000 / $data->{upem}); + + $data->{flags} = 0; + $data->{flags} |= 1 if ($font->{'OS/2'}->read->{'bProportion'} == 9); + $data->{flags} |= 2 unless ($font->{'OS/2'}{'bSerifStyle'} > 10 && $font->{'OS/2'}{'bSerifStyle'} < 14); + $data->{flags} |= 8 if ($font->{'OS/2'}{'bFamilyType'} == 2); + $data->{flags} |= 32; # if ($font->{'OS/2'}{'bFamilyType'} > 3); + $data->{flags} |= 64 if ($font->{'OS/2'}{'bLetterform'} > 8);; + + $data->{capheight}=$font->{'OS/2'}->{CapHeight} || int($data->{fontbbox}->[3]*0.8); + $data->{xheight}=$font->{'OS/2'}->{xHeight} || int($data->{fontbbox}->[3]*0.4); + + if($data->{issymbol}) + { + $data->{e2u}=[0xf000 .. 0xf0ff]; + } + else + { + $data->{e2u}=[ unpack('U*',decode('cp1252', pack('C*',0..255))) ]; + } + + if(($font->{'post'}->read->{FormatType} == 3) && defined($font->{cmap}->read->find_ms)) + { + $data->{g2n} = []; + foreach my $u (sort {$a<=>$b} keys %{$font->{cmap}->read->find_ms->{val}}) + { + my $n=nameByUni($u); + $data->{g2n}->[$font->{cmap}->read->find_ms->{val}->{$u}]=$n; + } + } + else + { + $data->{g2n} = [ map { $_ || '.notdef' } @{$font->{'post'}->read->{'VAL'}} ]; + } + + $data->{italicangle}=$font->{'post'}->{italicAngle}; + $data->{isfixedpitch}=$font->{'post'}->{isFixedPitch}; + $data->{underlineposition}=$font->{'post'}->{underlinePosition}; + $data->{underlinethickness}=$font->{'post'}->{underlineThickness}; + + if($self->iscff) + { + $data->{cff}=readcffstructs($font); + } + + if(defined $data->{cff}->{ROS}) + { + my %cffcmap=( + 'Adobe:Japan1'=>'japanese', + 'Adobe:Korea1'=>'korean', + 'Adobe:CNS1'=>'traditional', + 'Adobe:GB1'=>'simplified', + ); + my $ccmap=_look_for_cmap($cffcmap{"$data->{cff}->{ROS}->[0]:$data->{cff}->{ROS}->[1]"}); + $data->{u2g}=$ccmap->{u2g}; + $data->{g2u}=$ccmap->{g2u}; + } + else + { + $data->{u2g} = {}; + + my $gmap=$font->{cmap}->read->find_ms->{val}; + foreach my $u (sort {$a<=>$b} keys %{$gmap}) + { + my $uni=$u||0; + $data->{u2g}->{$uni}=$gmap->{$uni}; + } + $data->{g2u}=[ map { $_ || 0 } $font->{'cmap'}->read->reverse ]; + } + + if($data->{issymbol}) + { + map { $data->{u2g}->{$_} ||= $font->{'cmap'}->read->ms_lookup($_) } (0xf000 .. 0xf0ff); + map { $data->{u2g}->{$_ & 0xff} ||= $font->{'cmap'}->read->ms_lookup($_) } (0xf000 .. 0xf0ff); + } + + $data->{e2n}=[ map { $data->{g2n}->[$data->{u2g}->{$_} || 0] || '.notdef' } @{$data->{e2u}} ]; + + $data->{e2g}=[ map { $data->{u2g}->{$_ || 0} || 0 } @{$data->{e2u}} ]; + $data->{u2e}={}; + foreach my $n (reverse 0..255) + { + $data->{u2e}->{$data->{e2u}->[$n]}=$n unless(defined $data->{u2e}->{$data->{e2u}->[$n]}); + } + + $data->{u2n}={ map { $data->{g2u}->[$_] => $data->{g2n}->[$_] } (0 .. (scalar @{$data->{g2u}} -1)) }; + + $data->{wx}=[]; + foreach my $w (0..(scalar @{$data->{g2u}}-1)) + { + $data->{wx}->[$w]=int($font->{'hmtx'}->read->{'advance'}[$w]*1000/$data->{upem}) + || $data->{missingwidth}; + } + + $data->{kern}=read_kern_table($font,$data->{upem},$self); + delete $data->{kern} unless(defined $data->{kern}); + + $data->{fontname}=~s/\s+//og; + $data->{fontfamily}=~s/\s+//og; + $data->{apiname}=~s/\s+//og; + $data->{altname}=~s/\s+//og; + $data->{subname}=~s/\s+//og; + + $self->subsetByCId(0); + + return($self,$data); +} + +sub font { return( $_[0]->{' font'} ); } +sub data { return( $_[0]->{' data'} ); } +sub iscff { return( $_[0]->data->{iscff} ); } + +sub haveKernPairs { return( $_[0]->data->{kern} ? 1 : 0 ); } + +sub kernPairCid +{ + my ($self, $i1, $i2) = @_; + return(0) if($i1==0 || $i2==0); + return($self->data->{kern}->{"$i1:$i2"} || 0); +} + +sub subsetByCId +{ + my $self = shift @_; + my $g = shift @_; + $self->data->{subset}=1; + vec($self->data->{subvec},$g,1)=1; + return if($self->iscff); + if(defined $self->font->{loca}->read->{glyphs}->[$g]) { + $self->font->{loca}->read->{glyphs}->[$g]->read; + map { vec($self->data->{subvec},$_,1)=1; } $self->font->{loca}->{glyphs}->[$g]->get_refs; + } +} + +sub subvec { + my $self = shift @_; + return(1) if($self->iscff); + my $g = shift @_; + return(vec($self->data->{subvec},$g,1)); +} + +sub glyphNum { return ( $_[0]->font->{'maxp'}->read->{'numGlyphs'} ); } + +sub outobjdeep { + my ($self, $fh, $pdf, %opts) = @_; + + my $f = $self->font; + + if($self->iscff) { + $f->{'CFF '}->read_dat; + $self->{' stream'} = $f->{'CFF '}->{' dat'}; + } else { + if ($self->data->{subset} && !$self->data->{nosubset}) { + $f->{'glyf'}->read; + for (my $i = 0; $i < $self->glyphNum; $i++) { + next if($self->subvec($i)); + $f->{'loca'}{'glyphs'}->[$i] = undef; + # print STDERR "$i,"; + } + } + + if($self->data->{noembed} != 1) + { + $self->{' stream'} = ""; + my $ffh; + CORE::open($ffh, '+>', \$self->{' stream'}); + binmode($ffh,':raw'); + $f->out($ffh, 'cmap', 'cvt ', 'fpgm', 'glyf', 'head', 'hhea', 'hmtx', 'loca', 'maxp', 'prep'); + $self->{'Length1'}=PDFNum(length($self->{' stream'})); + CORE::close($ffh); + } + } + + $self->SUPER::outobjdeep($fh, $pdf, %opts); +} + + +1; diff --git a/lib/PDF/API2/Resource/ColorSpace.pm b/lib/PDF/API2/Resource/ColorSpace.pm new file mode 100644 index 0000000..e046802 --- /dev/null +++ b/lib/PDF/API2/Resource/ColorSpace.pm @@ -0,0 +1,66 @@ +#line 1 "PDF/API2/Resource/ColorSpace.pm" +#line 1 "PDF/API2/Resource/ColorSpace.pm" +package PDF::API2::Resource::ColorSpace; + +use base 'PDF::API2::Basic::PDF::Array'; + +use strict; +no warnings qw[ deprecated recursion uninitialized ]; + +our $VERSION = '2.033'; # VERSION + +use PDF::API2::Basic::PDF::Utils; +use PDF::API2::Util; +use Scalar::Util qw(weaken); + +#line 27 + +sub new { + my ($class,$pdf,$key,%opts)=@_; + + $class = ref $class if ref $class; + my $self=$class->SUPER::new(); + $pdf->new_obj($self) unless($self->is_obj($pdf)); + $self->name($key || pdfkey()); + $self->{' apipdf'}=$pdf; + weaken $self->{' apipdf'}; + + return($self); +} + +#line 46 + +sub name { + my $self=shift @_; + if(scalar @_ >0 && defined($_[0])) { + $self->{' name'}=$_[0]; + } + return($self->{' name'}); +} +sub type { + my $self=shift @_; + if(scalar @_ >0 && defined($_[0])) { + $self->{' type'}=$_[0]; + } + return($self->{' type'}); +} + +#line 67 + +sub param { + my $self=shift @_; + return(@_); +} + +sub outobjdeep { + my ($self, @opts) = @_; + foreach my $k (qw/ api apipdf /) { + $self->{" $k"}=undef; + delete($self->{" $k"}); + } + $self->SUPER::outobjdeep(@opts); +} + +#line 85 + +1; diff --git a/lib/PDF/API2/Resource/ColorSpace/DeviceN.pm b/lib/PDF/API2/Resource/ColorSpace/DeviceN.pm new file mode 100644 index 0000000..70d25c0 --- /dev/null +++ b/lib/PDF/API2/Resource/ColorSpace/DeviceN.pm @@ -0,0 +1,88 @@ +#line 1 "PDF/API2/Resource/ColorSpace/DeviceN.pm" +#line 1 "PDF/API2/Resource/ColorSpace/DeviceN.pm" +package PDF::API2::Resource::ColorSpace::DeviceN; + +use base 'PDF::API2::Resource::ColorSpace'; + +use strict; +no warnings qw[ deprecated recursion uninitialized ]; + +our $VERSION = '2.033'; # VERSION + +use PDF::API2::Basic::PDF::Utils; +use PDF::API2::Util; +use Scalar::Util qw(weaken); + +sub new { + my ($class,$pdf,$key,@opts)=@_; + my ($clrs,$sampled)=@opts; + + $sampled=2; + + $class = ref $class if ref $class; + my $self=$class->SUPER::new($pdf,$key); + $pdf->new_obj($self) unless($self->is_obj($pdf)); + $self->{' apipdf'}=$pdf; + weaken $self->{' apipdf'}; + + my $fct=PDFDict(); + + my $csname=$clrs->[0]->type; + my @xclr=map { $_->color } @{$clrs}; + my @xnam=map { $_->tintname } @{$clrs}; + # $self->{' comments'}="DeviceN ColorSpace\n"; + if($csname eq 'DeviceCMYK') { + @xclr=map { [ namecolor_cmyk($_) ] } @xclr; + + $fct->{FunctionType}=PDFNum(0); + $fct->{Order}=PDFNum(3); + $fct->{Range}=PDFArray(map {PDFNum($_)} (0,1,0,1,0,1,0,1)); + $fct->{BitsPerSample}=PDFNum(8); + $fct->{Domain}=PDFArray(); + $fct->{Size}=PDFArray(); + foreach (@xclr) { + $fct->{Size}->add_elements(PDFNum($sampled)); + $fct->{Domain}->add_elements(PDFNum(0),PDFNum(1)); + } + my @spec=(); + foreach my $xc (0..(scalar @xclr)-1) { + foreach my $n (0..($sampled**(scalar @xclr))-1) { + $spec[$n]||=[0,0,0,0]; + my $factor=($n/($sampled**$xc)) % $sampled; + # $self->{' comments'}.="C($n): xc=$xc i=$factor "; + my @thiscolor=map { ($_*$factor)/($sampled-1) } @{$xclr[$xc]}; + # $self->{' comments'}.="(@{$xclr[$xc]}) --> (@thiscolor) "; + foreach my $s (0..3) { + $spec[$n]->[$s]+=$thiscolor[$s]; + } + @{$spec[$n]}=map { $_>1?1:$_ } @{$spec[$n]}; + # $self->{' comments'}.="--> (@{$spec[$n]})\n"; + # $self->{' comments'}.="\n"; + } + } + my @b=(); + foreach my $s (@spec) { + push @b,(map { pack('C',($_*255)) } @{$s}); + } + $fct->{' stream'}=join('',@b); + } else { + die "unsupported colorspace specification (=$csname)."; + } + $fct->{Filter}=PDFArray(PDFName('ASCIIHexDecode')); + $self->type($csname); + $pdf->new_obj($fct); + my $attr=PDFDict(); + foreach my $cs (@{$clrs}) { + $attr->{$cs->tintname}=$cs; + } + $self->add_elements(PDFName('DeviceN'), PDFArray(map { PDFName($_) } @xnam), PDFName($csname), $fct); + + return($self); +} + +sub param { + my $self=shift @_; + return(@_); +} + +1; diff --git a/lib/PDF/API2/Resource/ColorSpace/Indexed.pm b/lib/PDF/API2/Resource/ColorSpace/Indexed.pm new file mode 100644 index 0000000..d49e02b --- /dev/null +++ b/lib/PDF/API2/Resource/ColorSpace/Indexed.pm @@ -0,0 +1,116 @@ +#line 1 "PDF/API2/Resource/ColorSpace/Indexed.pm" +#line 1 "PDF/API2/Resource/ColorSpace/Indexed.pm" +package PDF::API2::Resource::ColorSpace::Indexed; + +use base 'PDF::API2::Resource::ColorSpace'; + +use strict; +no warnings qw[ deprecated recursion uninitialized ]; + +our $VERSION = '2.033'; # VERSION + +use PDF::API2::Basic::PDF::Utils; +use PDF::API2::Util; +use Scalar::Util qw(weaken); + +sub new { + my ($class,$pdf,$key,%opts)=@_; + + $class = ref $class if ref $class; + my $self=$class->SUPER::new($pdf,$key,%opts); + $pdf->new_obj($self) unless($self->is_obj($pdf)); + $self->{' apipdf'}=$pdf; + weaken $self->{' apipdf'}; + + $self->add_elements(PDFName('Indexed')); + $self->type('Indexed'); + + return($self); +} + +sub enumColors { + my $self=shift @_; + my %col=(); + foreach my $n (0..255) { + my $k='#'.uc(unpack('H*',substr($self->{' csd'}->{' stream'},$n*3,3))); + $col{$k}=$n unless(defined $col{$k}); + } + return(%col); +} + +sub nameColor { + my $self=shift @_; + my $n=shift @_; + my %col=(); + my $k='#'.uc(unpack('H*',substr($self->{' csd'}->{' stream'},$n*3,3))); + return($k); +} + +sub resolveNearestRGB { + my $self=shift @_; + my ($r,$g,$b)=@_; # need to be in 0-255 + my $c=0; + my $w=768**2; + foreach my $n (0..255) { + my @e=unpack('C*',substr($self->{' csd'}->{' stream'},$n*3,3)); + my $d=($e[0]-$r)**2 + ($e[1]-$g)**2 + ($e[2]-$b)**2; + if($d<$w) { $c=$n; $w=$d; } + } + return($c); +} + +1; + +__END__ + +} elsif($opts{-type} eq 'Indexed') { + +$opts{-base}||='DeviceRGB'; +$opts{-whitepoint}||=[ 0.95049, 1, 1.08897 ]; +$opts{-blackpoint}||=[ 0, 0, 0 ]; +$opts{-gamma}||=[ 2.22218, 2.22218, 2.22218 ]; + +# my $csd=PDFDict(); +# $csd->{WhitePoint}=PDFArray(map {PDFNum($_)} @{$opts{-whitepoint}}); +# $csd->{BlackPoint}=PDFArray(map {PDFNum($_)} @{$opts{-blackpoint}}); +# $csd->{Gamma}=PDFArray(map {PDFNum($_)} @{$opts{-gamma}}); + +my $csd=PDFDict(); +$pdf->new_obj($csd); +$csd->{Filter}=PDFArray(PDFName('FlateDecode')); +$self->{' index'}=[]; + +if(defined $opts{-actfile}) { +} elsif(defined $opts{-acofile}) { +} elsif(defined $opts{-colors}) { +$opts{-maxindex}||=scalar(@{$opts{-colors}})-1; + +foreach my $col (@{$opts{-colors}}) { +map { $csd->{' stream'}.=pack('C',$_); } @{$col}; +} + +foreach my $col (0..$opts{-maxindex}) { +if($opts{-base}=~/RGB/i) { +my $r=(shift(@{$opts{-colors}})||0)/255; +my $g=(shift(@{$opts{-colors}})||0)/255; +my $b=(shift(@{$opts{-colors}})||0)/255; +push(@{$self->{' index'}},[$r,$g,$b]); +} elsif($opts{-base}=~/CMYK/i) { +my $c=(shift(@{$opts{-colors}})||0)/255; +my $m=(shift(@{$opts{-colors}})||0)/255; +my $y=(shift(@{$opts{-colors}})||0)/255; +my $k=(shift(@{$opts{-colors}})||0)/255; +push(@{$self->{' index'}},[$c,$m,$y,$k]); +} +} +} else { +die "unspecified color index table."; +} + + $self->add_elements(PDFName('Indexed'),PDFName($opts{-base}),PDFNum($opts{-maxindex}),$csd); + +$self->{' type'}='index-'.( +$opts{-base}=~/RGB/i ? 'rgb' : +$opts{-base}=~/CMYK/i ? 'cmyk' : 'unknown' +); + diff --git a/lib/PDF/API2/Resource/ColorSpace/Indexed/ACTFile.pm b/lib/PDF/API2/Resource/ColorSpace/Indexed/ACTFile.pm new file mode 100644 index 0000000..ef02bd6 --- /dev/null +++ b/lib/PDF/API2/Resource/ColorSpace/Indexed/ACTFile.pm @@ -0,0 +1,51 @@ +#line 1 "PDF/API2/Resource/ColorSpace/Indexed/ACTFile.pm" +#line 1 "PDF/API2/Resource/ColorSpace/Indexed/ACTFile.pm" +package PDF::API2::Resource::ColorSpace::Indexed::ACTFile; + +use base 'PDF::API2::Resource::ColorSpace::Indexed'; + +use strict; +no warnings qw[ deprecated recursion uninitialized ]; + +our $VERSION = '2.033'; # VERSION + +use PDF::API2::Basic::PDF::Utils; +use PDF::API2::Util; +use Scalar::Util qw(weaken); + +#line 32 + +sub new { + my ($class,$pdf,$file)=@_; + die "could not find act-file '$file'." unless(-f $file); + $class = ref $class if ref $class; + my $self=$class->SUPER::new($pdf,pdfkey()); + $pdf->new_obj($self) unless($self->is_obj($pdf)); + $self->{' apipdf'}=$pdf; + weaken $self->{' apipdf'}; + my $csd=PDFDict(); + $pdf->new_obj($csd); + $csd->{Filter}=PDFArray(PDFName('FlateDecode')); + + $csd->{WhitePoint}=PDFArray(map {PDFNum($_)} (0.95049, 1, 1.08897)); + $csd->{BlackPoint}=PDFArray(map {PDFNum($_)} (0, 0, 0)); + $csd->{Gamma}=PDFArray(map {PDFNum($_)} (2.22218, 2.22218, 2.22218)); + + my $fh; + open($fh, "<", $file) or die "$!: $file"; + binmode($fh,':raw'); + read($fh,$csd->{' stream'},768); + close($fh); + + $csd->{' stream'}.="\x00" x 768; + $csd->{' stream'}=substr($csd->{' stream'},0,768); + + $self->add_elements(PDFName('DeviceRGB'),PDFNum(255),$csd); + $self->{' csd'}=$csd; + + return($self); +} + +#line 67 + +1; diff --git a/lib/PDF/API2/Resource/ColorSpace/Indexed/Hue.pm b/lib/PDF/API2/Resource/ColorSpace/Indexed/Hue.pm new file mode 100644 index 0000000..b80a0c1 --- /dev/null +++ b/lib/PDF/API2/Resource/ColorSpace/Indexed/Hue.pm @@ -0,0 +1,53 @@ +#line 1 "PDF/API2/Resource/ColorSpace/Indexed/Hue.pm" +#line 1 "PDF/API2/Resource/ColorSpace/Indexed/Hue.pm" +package PDF::API2::Resource::ColorSpace::Indexed::Hue; + +use base 'PDF::API2::Resource::ColorSpace::Indexed'; + +use strict; +no warnings qw[ deprecated recursion uninitialized ]; + +our $VERSION = '2.033'; # VERSION + +use PDF::API2::Basic::PDF::Utils; +use PDF::API2::Util; +use Scalar::Util qw(weaken); + +sub new { + my ($class,$pdf)=@_; + + $class = ref $class if ref $class; + my $self=$class->SUPER::new($pdf,pdfkey()); + $pdf->new_obj($self) unless($self->is_obj($pdf)); + $self->{' apipdf'}=$pdf; + weaken $self->{' apipdf'}; + my $csd=PDFDict(); + $pdf->new_obj($csd); + $csd->{Filter}=PDFArray(PDFName('FlateDecode')); + + ## $csd->{WhitePoint}=PDFArray(map { PDFNum($_) } (0.95049, 1, 1.08897)); + ## $csd->{BlackPoint}=PDFArray(map { PDFNum($_) } (0, 0, 0)); + ## $csd->{Gamma}=PDFArray(map { PDFNum($_) } (2.22218, 2.22218, 2.22218)); + + $csd->{' stream'}=''; + + my %cc=(); + + foreach my $s (4,3,2,1) { + foreach my $v (4,3) { + foreach my $r (0..31) { + $csd->{' stream'}.=pack('CCC',map { $_*255 } namecolor('!'.sprintf('%02X',$r*255/31).sprintf('%02X',$s*255/4).sprintf('%02X',$v*255/4))); + } + } + } + + $csd->{' stream'}.="\x00" x 768; + $csd->{' stream'}=substr($csd->{' stream'},0,768); + + $self->add_elements(PDFName('DeviceRGB'),PDFNum(255),$csd); + $self->{' csd'}=$csd; + + return($self); +} + +1; diff --git a/lib/PDF/API2/Resource/ColorSpace/Indexed/WebColor.pm b/lib/PDF/API2/Resource/ColorSpace/Indexed/WebColor.pm new file mode 100644 index 0000000..c4fed85 --- /dev/null +++ b/lib/PDF/API2/Resource/ColorSpace/Indexed/WebColor.pm @@ -0,0 +1,61 @@ +#line 1 "PDF/API2/Resource/ColorSpace/Indexed/WebColor.pm" +#line 1 "PDF/API2/Resource/ColorSpace/Indexed/WebColor.pm" +package PDF::API2::Resource::ColorSpace::Indexed::WebColor; + +use base 'PDF::API2::Resource::ColorSpace::Indexed'; + +use strict; +no warnings qw[ deprecated recursion uninitialized ]; + +our $VERSION = '2.033'; # VERSION + +use PDF::API2::Basic::PDF::Utils; +use PDF::API2::Util; +use Scalar::Util qw(weaken); + +sub new { + my ($class,$pdf)=@_; + + $class = ref $class if ref $class; + my $self=$class->SUPER::new($pdf,pdfkey()); + $pdf->new_obj($self) unless($self->is_obj($pdf)); + $self->{' apipdf'}=$pdf; + weaken $self->{' apipdf'}; + my $csd=PDFDict(); + $pdf->new_obj($csd); + $csd->{Filter}=PDFArray(PDFName('ASCIIHexDecode')); + + $csd->{WhitePoint}=PDFArray(map {PDFNum($_)} (0.95049, 1, 1.08897)); + $csd->{BlackPoint}=PDFArray(map {PDFNum($_)} (0, 0, 0)); + $csd->{Gamma}=PDFArray(map {PDFNum($_)} (2.22218, 2.22218, 2.22218)); + + $csd->{' stream'}=''; + + foreach my $r (0,0x33,0x66,0x99,0xCC,0xFF) { + foreach my $g (0,0x33,0x66,0x99,0xCC,0xFF) { + foreach my $b (0,0x33,0x66,0x99,0xCC,0xFF) { + $csd->{' stream'}.=pack('CCC',$r,$g,$b); + } + } + } # 0-215 + + foreach my $r (0,0x11,0x22,0x33,0x44,0x55,0x66,0x77,0x88,0x99,0xAA,0xBB,0xCC,0xDD,0xEE,0xFF) { + $csd->{' stream'}.=pack('CCC',$r,$r,$r); + } # 216-231 + foreach my $r (0,0x11,0x22,0x33,0x44,0x55,0x66,0x77,0x88,0x99,0xAA,0xBB,0xCC,0xDD,0xEE,0xFF) { + $csd->{' stream'}.=pack('CCC',map { $_*255 } namecolor('!'.sprintf('%02X',$r).'FFFF')); + } # 232-247 + foreach my $r (0,0x22,0x44,0x66,0x88,0xAA,0xCC,0xEE) { + $csd->{' stream'}.=pack('CCC',map { $_*255 } namecolor('!'.sprintf('%02X',$r).'FF99')); + } # 232-247 + + $csd->{' stream'}.="\x00" x 768; + $csd->{' stream'}=substr($csd->{' stream'},0,768); + + $self->add_elements(PDFName('DeviceRGB'),PDFNum(255),$csd); + $self->{' csd'}=$csd; + + return($self); +} + +1; diff --git a/lib/PDF/API2/Resource/ColorSpace/Separation.pm b/lib/PDF/API2/Resource/ColorSpace/Separation.pm new file mode 100644 index 0000000..13d6f7b --- /dev/null +++ b/lib/PDF/API2/Resource/ColorSpace/Separation.pm @@ -0,0 +1,129 @@ +#line 1 "PDF/API2/Resource/ColorSpace/Separation.pm" +#line 1 "PDF/API2/Resource/ColorSpace/Separation.pm" +package PDF::API2::Resource::ColorSpace::Separation; + +use base 'PDF::API2::Resource::ColorSpace'; + +use strict; +no warnings qw[ deprecated recursion uninitialized ]; + +our $VERSION = '2.033'; # VERSION + +use PDF::API2::Basic::PDF::Utils; +use PDF::API2::Util; +use Scalar::Util qw(weaken); + +#line 27 + +sub new { + my ($class,$pdf,$key,@opts)=@_; + my ($name,@clr)=@opts; + + $class = ref $class if ref $class; + my $self=$class->SUPER::new($pdf,$key,@opts); + $pdf->new_obj($self) unless($self->is_obj($pdf)); + $self->{' apipdf'}=$pdf; + weaken $self->{' apipdf'}; + + my $fct=PDFDict(); + + my $csname='DeviceRGB'; + $clr[0]=lc($clr[0]); + $self->color(@clr); + if($clr[0]=~/^[a-z\#\!]+/) { + # colorname or #! specifier + # with rgb target colorspace + # namecolor returns always a RGB + my ($r,$g,$b)=namecolor($clr[0]); + + $fct->{FunctionType}=PDFNum(0); + $fct->{Size}=PDFArray(PDFNum(2)); + $fct->{Range}=PDFArray(map {PDFNum($_)} ($r,1,$g,1,$b,1)); + $fct->{Domain}=PDFArray(PDFNum(0),PDFNum(1)); + $fct->{BitsPerSample}=PDFNum(8); + $fct->{' stream'}="\xff\xff\xff\x00\x00\x00"; + } elsif($clr[0]=~/^[\%]+/) { + # % specifier + # with cmyk target colorspace + my ($c,$m,$y,$k)=namecolor_cmyk($clr[0]); + $csname='DeviceCMYK'; + + $fct->{FunctionType}=PDFNum(0); + $fct->{Size}=PDFArray(PDFNum(2)); + $fct->{Range}=PDFArray(map {PDFNum($_)} (0,$c,0,$m,0,$y,0,$k)); + $fct->{Domain}=PDFArray(PDFNum(0),PDFNum(1)); + $fct->{BitsPerSample}=PDFNum(8); + $fct->{' stream'}="\x00\x00\x00\x00\xff\xff\xff\xff"; + } elsif(scalar @clr == 1) { + # grey color spec. + while($clr[0]>1) { $clr[0]/=255; } + # adjusted for 8/16/32bit spec. + my $g=$clr[0]; + $csname='DeviceGray'; + + $fct->{FunctionType}=PDFNum(0); + $fct->{Size}=PDFArray(PDFNum(2)); + $fct->{Range}=PDFArray(map {PDFNum($_)} (0,$g)); + $fct->{Domain}=PDFArray(PDFNum(0),PDFNum(1)); + $fct->{BitsPerSample}=PDFNum(8); + $fct->{' stream'}="\xff\x00"; + } elsif(scalar @clr == 3) { + # legacy rgb color-spec (0 <= x <= 1) + my ($r,$g,$b)=@clr; + + $fct->{FunctionType}=PDFNum(0); + $fct->{Size}=PDFArray(PDFNum(2)); + $fct->{Range}=PDFArray(map {PDFNum($_)} ($r,1,$g,1,$b,1)); + $fct->{Domain}=PDFArray(PDFNum(0),PDFNum(1)); + $fct->{BitsPerSample}=PDFNum(8); + $fct->{' stream'}="\xff\xff\xff\x00\x00\x00"; + } elsif(scalar @clr == 4) { + # legacy cmyk color-spec (0 <= x <= 1) + my ($c,$m,$y,$k)=@clr; + $csname='DeviceCMYK'; + + $fct->{FunctionType}=PDFNum(0); + $fct->{Size}=PDFArray(PDFNum(2)); + $fct->{Range}=PDFArray(map {PDFNum($_)} (0,$c,0,$m,0,$y,0,$k)); + $fct->{Domain}=PDFArray(PDFNum(0),PDFNum(1)); + $fct->{BitsPerSample}=PDFNum(8); + $fct->{' stream'}="\x00\x00\x00\x00\xff\xff\xff\xff"; + } else { + die 'invalid color specification.'; + } + $self->type($csname); + $pdf->new_obj($fct); + $self->add_elements(PDFName('Separation'), PDFName($name), PDFName($csname), $fct); + $self->tintname($name); + return($self); +} + +#line 116 + +sub color { + my $self=shift @_; + if(scalar @_ >0 && defined($_[0])) { + $self->{' color'}=[@_]; + } + return(@{$self->{' color'}}); +} + +#line 130 + +sub tintname { + my $self=shift @_; + if(scalar @_ >0 && defined($_[0])) { + $self->{' tintname'}=[@_]; + } + return(@{$self->{' tintname'}}); +} + + +sub param { + my $self=shift @_; + return($_[0]); +} + +#line 148 + +1; diff --git a/lib/PDF/API2/Resource/Colors.pm b/lib/PDF/API2/Resource/Colors.pm new file mode 100644 index 0000000..36ed0a1 --- /dev/null +++ b/lib/PDF/API2/Resource/Colors.pm @@ -0,0 +1,697 @@ +#line 1 "PDF/API2/Resource/Colors.pm" +#line 1 "PDF/API2/Resource/Colors.pm" +package PDF::API2::Resource::Colors; + +use strict; +use warnings; + +our $VERSION = '2.033'; # VERSION + +sub get_colors { + return ( + aliceblue => '#EFF7FF', + antiquewhite => '#F9EAD7', + antiquewhite1 => '#FFEEDB', + antiquewhite2 => '#EDDFCC', + antiquewhite3 => '#CDBFB0', + antiquewhite4 => '#8A8278', + aqua => '#00FFFF', + aquamarine => '#7FFFD4', + aquamarine1 => '#7FFFD4', + aquamarine2 => '#76EDC5', + aquamarine3 => '#66CDAA', + aquamarine4 => '#458A74', + azure => '#EFFFFF', + azure1 => '#EFFFFF', + azure2 => '#E0EDED', + azure3 => '#C0CDCD', + azure4 => '#828A8A', + beige => '#F4F4DC', + bisque => '#FFE4C3', + bisque1 => '#FFE4C3', + bisque2 => '#EDD5B6', + bisque3 => '#CDB69E', + bisque4 => '#8A7D6B', + black => '#000000', + blanchedalmond => '#FFEACD', + blue => '#0000FF', + blue1 => '#0000FF', + blue2 => '#0000ED', + blue3 => '#0000CD', + blue4 => '#00008A', + blueviolet => '#9F5E9F', + brass => '#B4A642', + brightgold => '#D9D918', + bronze => '#8B7852', + bronzeii => '#A67D3D', + brown => '#A52929', + brown1 => '#FF4040', + brown2 => '#ED3B3B', + brown3 => '#CD3333', + brown4 => '#8A2222', + burlywood => '#DEB786', + burlywood1 => '#FFD39B', + burlywood2 => '#EDC490', + burlywood3 => '#CDAA7D', + burlywood4 => '#8A7354', + cadetblue => '#5E9EA0', + cadetblue1 => '#98F4FF', + cadetblue2 => '#8DE5ED', + cadetblue3 => '#7AC4CD', + cadetblue4 => '#52858A', + chartreuse => '#7FFF00', + chartreuse1 => '#7FFF00', + chartreuse2 => '#76ED00', + chartreuse3 => '#66CD00', + chartreuse4 => '#458A00', + chocolate => '#D2691D', + chocolate1 => '#FF7F23', + chocolate2 => '#ED7620', + chocolate3 => '#CD661C', + chocolate4 => '#8A4512', + coolcopper => '#D98618', + coral => '#FF7F4F', + coral1 => '#FF7255', + coral2 => '#ED6A4F', + coral3 => '#CD5A45', + coral4 => '#8A3E2E', + cornflowerblue => '#6394EC', + cornsilk => '#FFF7DC', + cornsilk1 => '#FFF7DC', + cornsilk2 => '#EDE7CD', + cornsilk3 => '#CDC7B1', + cornsilk4 => '#8A8778', + crimson => '#DC143C', + cyan => '#00FFFF', + cyan1 => '#00FFFF', + cyan2 => '#00EDED', + cyan3 => '#00CDCD', + cyan4 => '#008A8A', + darkblue => '#00008A', + darkcyan => '#008A8A', + darkgoldenrod => '#B7850B', + darkgoldenrod1 => '#FFB80E', + darkgoldenrod2 => '#EDAD0D', + darkgoldenrod3 => '#CD940C', + darkgoldenrod4 => '#8A6507', + darkgray => '#A9A9A9', + darkgreen => '#006300', + darkgrey => '#A9A9A9', + darkkhaki => '#BCB66B', + darkmagenta => '#8A008A', + darkolivegreen => '#546B2E', + darkolivegreen1 => '#CAFF70', + darkolivegreen2 => '#BBED68', + darkolivegreen3 => '#A2CD59', + darkolivegreen4 => '#6E8A3D', + darkorange => '#FF8B00', + darkorange1 => '#FF7F00', + darkorange2 => '#ED7600', + darkorange3 => '#CD6600', + darkorange4 => '#8A4500', + darkorchid => '#9931CC', + darkorchid1 => '#BE3EFF', + darkorchid2 => '#B13AED', + darkorchid3 => '#9A31CD', + darkorchid4 => '#68218A', + darkred => '#8A0000', + darksalmon => '#E8957A', + darkseagreen => '#8EBB8E', + darkseagreen1 => '#C0FFC0', + darkseagreen2 => '#B4EDB4', + darkseagreen3 => '#9BCD9B', + darkseagreen4 => '#698A69', + darkslateblue => '#483D8A', + darkslategray => '#2E4E4E', + darkslategray1 => '#97FFFF', + darkslategray2 => '#8CEDED', + darkslategray3 => '#79CDCD', + darkslategray4 => '#518A8A', + darkslategrey => '#2E4E4E', + darkturquoise => '#00CED1', + darkviolet => '#9300D3', + darkwood => '#845D42', + deeppink => '#FF1492', + deeppink1 => '#FF1492', + deeppink2 => '#ED1188', + deeppink3 => '#CD1076', + deeppink4 => '#8A0A4F', + deepskyblue => '#00BEFF', + deepskyblue1 => '#00BEFF', + deepskyblue2 => '#00B1ED', + deepskyblue3 => '#009ACD', + deepskyblue4 => '#00688A', + dimgray => '#696969', + dimgrey => '#696969', + dodgerblue => '#1D8FFF', + dodgerblue1 => '#1D8FFF', + dodgerblue2 => '#1B85ED', + dodgerblue3 => '#1774CD', + dodgerblue4 => '#104D8A', + dustyrose => '#846262', + feldspar => '#D19175', + firebrick => '#B12121', + firebrick1 => '#FF2F2F', + firebrick2 => '#ED2B2B', + firebrick3 => '#CD2525', + firebrick4 => '#8A1919', + flesh => '#F4CCB0', + floralwhite => '#FFF9EF', + forestgreen => '#218A21', + fuchsia => '#FF00FF', + gainsboro => '#DCDCDC', + ghostwhite => '#F7F7FF', + gold => '#FFD700', + gold1 => '#FFD700', + gold2 => '#EDC900', + gold3 => '#CDAD00', + gold4 => '#8A7500', + goldenrod => '#DAA51F', + goldenrod1 => '#FFC024', + goldenrod2 => '#EDB421', + goldenrod3 => '#CD9B1C', + goldenrod4 => '#8A6914', + gray => '#7F7F7F', + gray0 => '#000000', + gray1 => '#020202', + gray10 => '#191919', + gray100 => '#FFFFFF', + gray11 => '#1B1B1B', + gray12 => '#1E1E1E', + gray13 => '#202020', + gray14 => '#232323', + gray15 => '#252525', + gray16 => '#282828', + gray17 => '#2A2A2A', + gray18 => '#2D2D2D', + gray19 => '#2F2F2F', + gray2 => '#050505', + gray20 => '#333333', + gray21 => '#363636', + gray22 => '#383838', + gray23 => '#3B3B3B', + gray24 => '#3D3D3D', + gray25 => '#404040', + gray26 => '#424242', + gray27 => '#454545', + gray28 => '#474747', + gray29 => '#4A4A4A', + gray3 => '#070707', + gray30 => '#4C4C4C', + gray31 => '#4E4E4E', + gray32 => '#515151', + gray33 => '#535353', + gray34 => '#565656', + gray35 => '#585858', + gray36 => '#5B5B5B', + gray37 => '#5D5D5D', + gray38 => '#606060', + gray39 => '#626262', + gray4 => '#0A0A0A', + gray40 => '#666666', + gray41 => '#696969', + gray42 => '#6B6B6B', + gray43 => '#6E6E6E', + gray44 => '#707070', + gray45 => '#737373', + gray46 => '#757575', + gray47 => '#787878', + gray48 => '#7A7A7A', + gray49 => '#7D7D7D', + gray5 => '#0C0C0C', + gray50 => '#7F7F7F', + gray51 => '#818181', + gray52 => '#848484', + gray53 => '#868686', + gray54 => '#898989', + gray55 => '#8B8B8B', + gray56 => '#8E8E8E', + gray57 => '#909090', + gray58 => '#939393', + gray59 => '#959595', + gray6 => '#0E0E0E', + gray60 => '#999999', + gray61 => '#9C9C9C', + gray62 => '#9E9E9E', + gray63 => '#A1A1A1', + gray64 => '#A3A3A3', + gray65 => '#A6A6A6', + gray66 => '#A8A8A8', + gray67 => '#ABABAB', + gray68 => '#ADADAD', + gray69 => '#B0B0B0', + gray7 => '#111111', + gray70 => '#B2B2B2', + gray71 => '#B4B4B4', + gray72 => '#B7B7B7', + gray73 => '#B9B9B9', + gray74 => '#BCBCBC', + gray75 => '#BEBEBE', + gray76 => '#C1C1C1', + gray77 => '#C3C3C3', + gray78 => '#C6C6C6', + gray79 => '#C9C9C9', + gray8 => '#141414', + gray80 => '#CCCCCC', + gray81 => '#CFCFCF', + gray82 => '#D1D1D1', + gray83 => '#D4D4D4', + gray84 => '#D6D6D6', + gray85 => '#D9D9D9', + gray86 => '#DBDBDB', + gray87 => '#DEDEDE', + gray88 => '#E0E0E0', + gray89 => '#E2E2E2', + gray9 => '#161616', + gray90 => '#E5E5E5', + gray91 => '#E7E7E7', + gray92 => '#EAEAEA', + gray93 => '#ECECEC', + gray94 => '#EFEFEF', + gray95 => '#F1F1F1', + gray96 => '#F4F4F4', + gray97 => '#F6F6F6', + gray98 => '#F9F9F9', + gray99 => '#FBFBFB', + green => '#007F00', + green1 => '#00FF00', + green2 => '#00ED00', + green3 => '#00CD00', + green4 => '#008A00', + greencopper => '#846262', + greenyellow => '#D19175', + grey => '#BDBDBD', + grey0 => '#000000', + grey1 => '#020202', + grey10 => '#191919', + grey100 => '#FFFFFF', + grey11 => '#1B1B1B', + grey12 => '#1E1E1E', + grey13 => '#202020', + grey14 => '#232323', + grey15 => '#252525', + grey16 => '#282828', + grey17 => '#2A2A2A', + grey18 => '#2D2D2D', + grey19 => '#2F2F2F', + grey2 => '#050505', + grey20 => '#333333', + grey21 => '#363636', + grey22 => '#383838', + grey23 => '#3B3B3B', + grey24 => '#3D3D3D', + grey25 => '#404040', + grey26 => '#424242', + grey27 => '#454545', + grey28 => '#474747', + grey29 => '#4A4A4A', + grey3 => '#070707', + grey30 => '#4C4C4C', + grey31 => '#4E4E4E', + grey32 => '#515151', + grey33 => '#535353', + grey34 => '#565656', + grey35 => '#585858', + grey36 => '#5B5B5B', + grey37 => '#5D5D5D', + grey38 => '#606060', + grey39 => '#626262', + grey4 => '#0A0A0A', + grey40 => '#666666', + grey41 => '#696969', + grey42 => '#6B6B6B', + grey43 => '#6E6E6E', + grey44 => '#707070', + grey45 => '#737373', + grey46 => '#757575', + grey47 => '#787878', + grey48 => '#7A7A7A', + grey49 => '#7D7D7D', + grey5 => '#0C0C0C', + grey50 => '#7F7F7F', + grey51 => '#818181', + grey52 => '#848484', + grey53 => '#868686', + grey54 => '#898989', + grey55 => '#8B8B8B', + grey56 => '#8E8E8E', + grey57 => '#909090', + grey58 => '#939393', + grey59 => '#959595', + grey6 => '#0E0E0E', + grey60 => '#999999', + grey61 => '#9C9C9C', + grey62 => '#9E9E9E', + grey63 => '#A1A1A1', + grey64 => '#A3A3A3', + grey65 => '#A6A6A6', + grey66 => '#A8A8A8', + grey67 => '#ABABAB', + grey68 => '#ADADAD', + grey69 => '#B0B0B0', + grey7 => '#111111', + grey70 => '#B2B2B2', + grey71 => '#B4B4B4', + grey72 => '#B7B7B7', + grey73 => '#B9B9B9', + grey74 => '#BCBCBC', + grey75 => '#BEBEBE', + grey76 => '#C1C1C1', + grey77 => '#C3C3C3', + grey78 => '#C6C6C6', + grey79 => '#C9C9C9', + grey8 => '#141414', + grey80 => '#CCCCCC', + grey81 => '#CFCFCF', + grey82 => '#D1D1D1', + grey83 => '#D4D4D4', + grey84 => '#D6D6D6', + grey85 => '#D9D9D9', + grey86 => '#DBDBDB', + grey87 => '#DEDEDE', + grey88 => '#E0E0E0', + grey89 => '#E2E2E2', + grey9 => '#161616', + grey90 => '#E5E5E5', + grey91 => '#E7E7E7', + grey92 => '#EAEAEA', + grey93 => '#ECECEC', + grey94 => '#EFEFEF', + grey95 => '#F1F1F1', + grey96 => '#F4F4F4', + grey97 => '#F6F6F6', + grey98 => '#F9F9F9', + grey99 => '#FBFBFB', + honeydew => '#EFFFEF', + honeydew1 => '#EFFFEF', + honeydew2 => '#E0EDE0', + honeydew3 => '#C0CDC0', + honeydew4 => '#828A82', + hotpink => '#FF69B4', + hotpink1 => '#FF6EB4', + hotpink2 => '#ED6AA7', + hotpink3 => '#CD5F8F', + hotpink4 => '#8A3A61', + indianred => '#F4CCB0', + indianred1 => '#FF6A6A', + indianred2 => '#ED6262', + indianred3 => '#CD5454', + indianred4 => '#8A3A3A', + indigo => '#4B0081', + ivory => '#FFFFEF', + ivory1 => '#FFFFEF', + ivory2 => '#EDEDE0', + ivory3 => '#CDCDC0', + ivory4 => '#8A8A82', + khaki => '#EFE68B', + khaki1 => '#FFF58E', + khaki2 => '#EDE684', + khaki3 => '#CDC573', + khaki4 => '#8A854D', + lavender => '#E6E6F9', + lavenderblush => '#FFEFF4', + lavenderblush1 => '#FFEFF4', + lavenderblush2 => '#EDE0E5', + lavenderblush3 => '#CDC0C4', + lavenderblush4 => '#8A8285', + lawngreen => '#7CFB00', + lemonchiffon => '#FFF9CD', + lemonchiffon1 => '#FFF9CD', + lemonchiffon2 => '#EDE8BE', + lemonchiffon3 => '#CDC9A5', + lemonchiffon4 => '#8A8870', + lightblue => '#ADD8E6', + lightblue1 => '#BEEEFF', + lightblue2 => '#B1DFED', + lightblue3 => '#9ABFCD', + lightblue4 => '#68828A', + lightcoral => '#EF7F7F', + lightcyan => '#E0FFFF', + lightcyan1 => '#E0FFFF', + lightcyan2 => '#D1EDED', + lightcyan3 => '#B4CDCD', + lightcyan4 => '#7A8A8A', + lightgoldenrod => '#EDDD81', + lightgoldenrod1 => '#FFEB8A', + lightgoldenrod2 => '#EDDC81', + lightgoldenrod3 => '#CDBD70', + lightgoldenrod4 => '#8A804C', + lightgoldenrodyellow => '#F9F9D2', + lightgray => '#D3D3D3', + lightgreen => '#8FED8F', + lightgrey => '#D3D3D3', + lightpink => '#FFB5C0', + lightpink1 => '#FFAEB8', + lightpink2 => '#EDA2AD', + lightpink3 => '#CD8B94', + lightpink4 => '#8A5E65', + lightsalmon => '#FFA07A', + lightsalmon1 => '#FFA07A', + lightsalmon2 => '#ED9472', + lightsalmon3 => '#CD8061', + lightsalmon4 => '#8A5642', + lightseagreen => '#1FB1AA', + lightskyblue => '#86CEF9', + lightskyblue1 => '#B0E2FF', + lightskyblue2 => '#A4D3ED', + lightskyblue3 => '#8CB5CD', + lightskyblue4 => '#5F7B8A', + lightslateblue => '#8370FF', + lightslategray => '#778799', + lightslategrey => '#778799', + lightsteelblue => '#B0C3DE', + lightsteelblue1 => '#CAE1FF', + lightsteelblue2 => '#BBD2ED', + lightsteelblue3 => '#A2B4CD', + lightsteelblue4 => '#6E7B8A', + lightyellow => '#FFFFE0', + lightyellow1 => '#FFFFE0', + lightyellow2 => '#EDEDD1', + lightyellow3 => '#CDCDB4', + lightyellow4 => '#8A8A7A', + lime => '#00FF00', + limegreen => '#31CD31', + linen => '#F9EFE6', + magenta => '#FF00FF', + magenta1 => '#FF00FF', + magenta2 => '#ED00ED', + magenta3 => '#CD00CD', + magenta4 => '#8A008A', + mandarianorange => '#8D2222', + maroon => '#7F0000', + maroon1 => '#FF34B2', + maroon2 => '#ED2FA7', + maroon3 => '#CD288F', + maroon4 => '#8A1B61', + mediumaquamarine => '#66CDAA', + mediumblue => '#0000CD', + mediumorchid => '#B954D3', + mediumorchid1 => '#E066FF', + mediumorchid2 => '#D15EED', + mediumorchid3 => '#B451CD', + mediumorchid4 => '#7A378A', + mediumpurple => '#9270DB', + mediumpurple1 => '#AB81FF', + mediumpurple2 => '#9F79ED', + mediumpurple3 => '#8868CD', + mediumpurple4 => '#5C478A', + mediumseagreen => '#3CB271', + mediumslateblue => '#7B68ED', + mediumspringgreen => '#00F99A', + mediumturquoise => '#48D1CC', + mediumvioletred => '#C61584', + midnightblue => '#2E2E4E', + mintcream => '#F4FFF9', + mistyrose => '#FFE4E1', + mistyrose1 => '#FFE4E1', + mistyrose2 => '#EDD5D2', + mistyrose3 => '#CDB6B4', + mistyrose4 => '#8A7D7B', + moccasin => '#FFE4B4', + navajowhite => '#FFDEAD', + navajowhite1 => '#FFDEAD', + navajowhite2 => '#EDCFA1', + navajowhite3 => '#CDB28A', + navajowhite4 => '#8A795D', + navy => '#00007F', + navyblue => '#00007F', + neonblue => '#4C4CFF', + neonpink => '#FF6EC6', + none => '#000000', + oldlace => '#FCF4E6', + olive => '#7F7F00', + olivedrab => '#6B8D22', + olivedrab1 => '#BFFF3E', + olivedrab2 => '#B2ED3A', + olivedrab3 => '#9ACD31', + olivedrab4 => '#698A21', + orange => '#FFA500', + orange1 => '#FFA500', + orange2 => '#ED9A00', + orange3 => '#CD8400', + orange4 => '#8A5900', + orangered => '#FF4500', + orangered1 => '#FF4500', + orangered2 => '#ED4000', + orangered3 => '#CD3700', + orangered4 => '#8A2400', + orchid => '#DA70D6', + orchid1 => '#FF82F9', + orchid2 => '#ED7AE8', + orchid3 => '#CD69C9', + orchid4 => '#8A4788', + palegoldenrod => '#EDE7AA', + palegreen => '#98FB98', + palegreen1 => '#9AFF9A', + palegreen2 => '#8FED8F', + palegreen3 => '#7CCD7C', + palegreen4 => '#538A53', + paleturquoise => '#AFEDED', + paleturquoise1 => '#BAFFFF', + paleturquoise2 => '#AEEDED', + paleturquoise3 => '#95CDCD', + paleturquoise4 => '#668A8A', + palevioletred => '#DB7092', + palevioletred1 => '#FF81AB', + palevioletred2 => '#ED799F', + palevioletred3 => '#CD6888', + palevioletred4 => '#8A475C', + papayawhip => '#FFEED5', + peachpuff => '#FFDAB8', + peachpuff1 => '#FFDAB8', + peachpuff2 => '#EDCBAD', + peachpuff3 => '#CDAF94', + peachpuff4 => '#8A7765', + peru => '#CD843F', + pink => '#FFBFCB', + pink1 => '#FFB4C4', + pink2 => '#EDA9B7', + pink3 => '#CD909E', + pink4 => '#8A626C', + plum => '#DDA0DD', + plum1 => '#FFBAFF', + plum2 => '#EDAEED', + plum3 => '#CD95CD', + plum4 => '#8A668A', + powderblue => '#B0E0E6', + purple => '#7F007F', + purple1 => '#9B2FFF', + purple2 => '#902BED', + purple3 => '#7D25CD', + purple4 => '#54198A', + quartz => '#D9D9F2', + red => '#FF0000', + red1 => '#FF0000', + red2 => '#ED0000', + red3 => '#CD0000', + red4 => '#8A0000', + richblue => '#5858AB', + rosybrown => '#BB8E8E', + rosybrown1 => '#FFC0C0', + rosybrown2 => '#EDB4B4', + rosybrown3 => '#CD9B9B', + rosybrown4 => '#8A6969', + royalblue => '#4169E1', + royalblue1 => '#4876FF', + royalblue2 => '#436EED', + royalblue3 => '#3A5ECD', + royalblue4 => '#26408A', + saddlebrown => '#8A4512', + salmon => '#F97F72', + salmon1 => '#FF8B69', + salmon2 => '#ED8161', + salmon3 => '#CD7053', + salmon4 => '#8A4C39', + sandybrown => '#F3A45F', + seagreen => '#2D8A56', + seagreen1 => '#53FF9F', + seagreen2 => '#4DED93', + seagreen3 => '#43CD7F', + seagreen4 => '#2D8A56', + seashell => '#FFF4ED', + seashell1 => '#FFF4ED', + seashell2 => '#EDE5DE', + seashell3 => '#CDC4BE', + seashell4 => '#8A8581', + sienna => '#A0512C', + sienna1 => '#FF8147', + sienna2 => '#ED7942', + sienna3 => '#CD6839', + sienna4 => '#8A4725', + silver => '#BFBFBF', + skyblue => '#86CEEA', + skyblue1 => '#86CEFF', + skyblue2 => '#7EBFED', + skyblue3 => '#6CA6CD', + skyblue4 => '#4A708A', + slateblue => '#6A59CD', + slateblue1 => '#826FFF', + slateblue2 => '#7A67ED', + slateblue3 => '#6958CD', + slateblue4 => '#473C8A', + slategray => '#707F8F', + slategray1 => '#C5E2FF', + slategray2 => '#B8D3ED', + slategray3 => '#9FB5CD', + slategray4 => '#6C7B8A', + slategrey => '#707F8F', + snow => '#FFF9F9', + snow1 => '#FFF9F9', + snow2 => '#EDE8E8', + snow3 => '#CDC9C9', + snow4 => '#8A8888', + springgreen => '#00FF7F', + springgreen1 => '#00FF7F', + springgreen2 => '#00ED76', + springgreen3 => '#00CD66', + springgreen4 => '#008A45', + steelblue => '#4681B4', + steelblue1 => '#62B7FF', + steelblue2 => '#5BACED', + steelblue3 => '#4E93CD', + steelblue4 => '#36638A', + summersky => '#38B0DE', + tan => '#D2B48B', + tan1 => '#FFA54E', + tan2 => '#ED9A49', + tan3 => '#CD843F', + tan4 => '#8A592A', + teal => '#007F7F', + thistle => '#D8BED8', + thistle1 => '#FFE1FF', + thistle2 => '#EDD2ED', + thistle3 => '#CDB4CD', + thistle4 => '#8A7B8A', + tomato => '#FF6247', + tomato1 => '#FF6247', + tomato2 => '#ED5B42', + tomato3 => '#CD4E39', + tomato4 => '#8A3625', + turquoise => '#40E0D0', + turquoise1 => '#00F4FF', + turquoise2 => '#00E5ED', + turquoise3 => '#00C4CD', + turquoise4 => '#00858A', + violet => '#ED81ED', + violetred => '#D01F8F', + violetred1 => '#FF3E95', + violetred2 => '#ED3A8B', + violetred3 => '#CD3178', + violetred4 => '#8A2151', + wheat => '#F4DEB2', + wheat1 => '#FFE6B9', + wheat2 => '#EDD8AE', + wheat3 => '#CDB995', + wheat4 => '#8A7E66', + white => '#FFFFFF', + whitesmoke => '#F4F4F4', + yellow => '#FFFF00', + yellow1 => '#FFFF00', + yellow2 => '#EDED00', + yellow3 => '#CDCD00', + yellow4 => '#8A8A00', + yellowgreen => '#99CC31', + ); +} + +1; diff --git a/lib/PDF/API2/Resource/ExtGState.pm b/lib/PDF/API2/Resource/ExtGState.pm new file mode 100644 index 0000000..65aa3df --- /dev/null +++ b/lib/PDF/API2/Resource/ExtGState.pm @@ -0,0 +1,270 @@ +#line 1 "PDF/API2/Resource/ExtGState.pm" +#line 1 "PDF/API2/Resource/ExtGState.pm" +package PDF::API2::Resource::ExtGState; + +use base 'PDF::API2::Resource'; + +use strict; +no warnings qw[ deprecated recursion uninitialized ]; + +our $VERSION = '2.033'; # VERSION + +use PDF::API2::Basic::PDF::Utils; +use PDF::API2::Util; + +#line 26 + +sub new { + my ($class,$pdf,$key)=@_; + my $self = $class->SUPER::new($pdf,$key); + $self->{Type}=PDFName('ExtGState'); + return($self); +} + +#line 37 + +sub strokeadjust { + my ($self,$var)=@_; + $self->{SA}=PDFBool($var); + return($self); +} + +#line 47 + +sub strokeoverprint { + my ($self,$var)=@_; + $self->{OP}=PDFBool($var); + return($self); +} + +#line 57 + +sub filloverprint { + my ($self,$var)=@_; + $self->{op}=PDFBool($var); + return($self); +} + +#line 67 + +sub overprintmode { + my ($self,$var)=@_; + $self->{OPM}=PDFNum($var); + return($self); +} + +#line 77 + +sub blackgeneration { + my ($self,$obj)=@_; + $self->{BG}=$obj; + return($self); +} + +#line 87 + +sub blackgeneration2 { + my ($self,$obj)=@_; + $self->{BG2}=$obj; + return($self); +} + +#line 97 + +sub undercolorremoval { + my ($self,$obj)=@_; + $self->{UCR}=$obj; + return($self); +} + +#line 107 + +sub undercolorremoval2 { + my ($self,$obj)=@_; + $self->{UCR2}=$obj; + return($self); +} + +#line 117 + +sub transfer { + my ($self,$obj)=@_; + $self->{TR}=$obj; + return($self); +} + +#line 127 + +sub transfer2 { + my ($self,$obj)=@_; + $self->{TR2}=$obj; + return($self); +} + +#line 137 + +sub halftone { + my ($self,$obj)=@_; + $self->{HT}=$obj; + return($self); +} + +#line 147 + +# Per RT #113514, this was last present in version 1.2 of the PDF +# spec, so it can probably be removed. +sub halftonephase { + my ($self,$obj)=@_; + $self->{HTP}=$obj; + return($self); +} + +#line 159 + +sub smoothness { + my ($self,$var)=@_; + $self->{SM}=PDFNum($var); + return($self); +} + +#line 169 + +sub font { + my ($self,$font,$size)=@_; + $self->{Font}=PDFArray(PDFName($font->{' apiname'}),PDFNum($size)); + return($self); +} + +#line 179 + +sub linewidth { + my ($self,$var)=@_; + $self->{LW}=PDFNum($var); + return($self); +} + +#line 189 + +sub linecap { + my ($self,$var)=@_; + $self->{LC}=PDFNum($var); + return($self); +} + +#line 199 + +sub linejoin { + my ($self,$var)=@_; + $self->{LJ}=PDFNum($var); + return($self); +} + +#line 209 + +sub miterlimit { + my ($self,$var)=@_; + $self->{ML}=PDFNum($var); + return($self); +} + +# Deprecated: miterlimit was originally named incorrectly +sub meterlimit { return miterlimit(@_) } + +#line 222 + +sub dash { + my ($self,@dash)=@_; + $self->{D}=PDFArray(PDFArray( map { PDFNum($_); } @dash), PDFNum(0)); + return($self); +} + +#line 232 + +sub flatness { + my ($self,$var)=@_; + $self->{FL}=PDFNum($var); + return($self); +} + +#line 242 + +sub renderingintent { + my ($self,$var)=@_; + $self->{RI}=PDFName($var); + return($self); +} + +#line 256 + +sub strokealpha { + my ($self,$var)=@_; + $self->{CA}=PDFNum($var); + return($self); +} + +#line 268 + +sub fillalpha { + my ($self,$var)=@_; + $self->{ca}=PDFNum($var); + return($self); +} + +#line 283 + +sub blendmode { + my ($self,$var)=@_; + if(ref($var)) { + $self->{BM}=$var; + } else { + $self->{BM}=PDFName($var); + } + return($self); +} + +#line 302 + +sub alphaisshape { + my ($self,$var)=@_; + $self->{AIS}=PDFBool($var); + return($self); +} + +#line 316 + +sub textknockout { + my ($self,$var)=@_; + $self->{TK}=PDFBool($var); + return($self); +} + +#line 329 + +sub transparency { + my ($self,$var)=@_; + $self->strokealpha(1-$var); + $self->fillalpha(1-$var); + return($self); +} + +#line 343 + +sub opacity { + my ($self,$var)=@_; + $self->strokealpha($var); + $self->fillalpha($var); + return($self); +} + +sub outobjdeep { + my ($self, @opts) = @_; + foreach my $k (qw/ api apipdf /) { + $self->{" $k"}=undef; + delete($self->{" $k"}); + } + $self->SUPER::outobjdeep(@opts); +} + +#line 363 + +1; diff --git a/lib/PDF/API2/Resource/Font.pm b/lib/PDF/API2/Resource/Font.pm new file mode 100644 index 0000000..b297c37 --- /dev/null +++ b/lib/PDF/API2/Resource/Font.pm @@ -0,0 +1,213 @@ +#line 1 "PDF/API2/Resource/Font.pm" +#line 1 "PDF/API2/Resource/Font.pm" +package PDF::API2::Resource::Font; + +use base 'PDF::API2::Resource::BaseFont'; + +use strict; +no warnings qw[ deprecated recursion uninitialized ]; + +our $VERSION = '2.033'; # VERSION + +use Encode qw(:all); + +use PDF::API2::Util; +use PDF::API2::Basic::PDF::Utils; + +sub encodeByData { + my ($self,$encoding)=@_; + my $data=$self->data; + + my ($firstChar,$lastChar); + + if($self->issymbol || $encoding eq 'asis') { + $encoding=undef; + } + + if(defined $encoding && $encoding=~m|^uni(\d+)$|o) + { + my $blk=$1; + $data->{e2u}=[ map { $blk*256+$_ } (0..255) ]; + $data->{e2n}=[ map { nameByUni($_) || '.notdef' } @{$data->{e2u}} ]; + $data->{firstchar} = 0; + } + elsif(defined $encoding) + { + $data->{e2u}=[ unpack('U*',decode($encoding,pack('C*',(0..255)))) ]; + $data->{e2n}=[ map { nameByUni($_) || '.notdef' } @{$data->{e2u}} ]; + } + elsif(defined $data->{uni}) + { + $data->{e2u}=[ @{$data->{uni}} ]; + $data->{e2n}=[ map { $_ || '.notdef' } @{$data->{char}} ]; + } + else + { + $data->{e2u}=[ map { uniByName($_) } @{$data->{char}} ]; + $data->{e2n}=[ map { $_ || '.notdef' } @{$data->{char}} ]; + } + + $data->{u2c}={}; + $data->{u2e}={}; + $data->{u2n}={}; + $data->{n2c}={}; + $data->{n2e}={}; + $data->{n2u}={}; + + foreach my $n (0..255) { + my $xchar=undef; + my $xuni=undef; + if(defined $data->{char}->[$n]) { + $xchar=$data->{char}->[$n]; + } else { + $xchar='.notdef'; + } + $data->{n2c}->{$xchar}=$n unless(defined $data->{n2c}->{$xchar}); + + if(defined $data->{e2n}->[$n]) { + $xchar=$data->{e2n}->[$n]; + } else { + $xchar='.notdef'; + } + $data->{n2e}->{$xchar}=$n unless(defined $data->{n2e}->{$xchar}); + + $data->{n2u}->{$xchar}=$data->{e2u}->[$n] unless(defined $data->{n2u}->{$xchar}); + + if(defined $data->{char}->[$n]) { + $xchar=$data->{char}->[$n]; + } else { + $xchar='.notdef'; + } + if(defined $data->{uni}->[$n]) { + $xuni=$data->{uni}->[$n]; + } else { + $xuni=0; + } + $data->{n2u}->{$xchar}=$xuni unless(defined $data->{n2u}->{$xchar}); + + $data->{u2c}->{$xuni}||=$n unless(defined $data->{u2c}->{$xuni}); + + if(defined $data->{e2u}->[$n]) { + $xuni=$data->{e2u}->[$n]; + } else { + $xuni=0; + } + $data->{u2e}->{$xuni}||=$n unless(defined $data->{u2e}->{$xuni}); + + if(defined $data->{e2n}->[$n]) { + $xchar=$data->{e2n}->[$n]; + } else { + $xchar='.notdef'; + } + $data->{u2n}->{$xuni}=$xchar unless(defined $data->{u2n}->{$xuni}); + + if(defined $data->{char}->[$n]) { + $xchar=$data->{char}->[$n]; + } else { + $xchar='.notdef'; + } + if(defined $data->{uni}->[$n]) { + $xuni=$data->{uni}->[$n]; + } else { + $xuni=0; + } + $data->{u2n}->{$xuni}=$xchar unless(defined $data->{u2n}->{$xuni}); + } + + my $en = PDFDict(); + $self->{Encoding}=$en; + + $en->{Type}=PDFName('Encoding'); + $en->{BaseEncoding}=PDFName('WinAnsiEncoding'); + + $en->{Differences}=PDFArray(PDFNum(0)); + foreach my $n (0..255) { + $en->{Differences}->add_elements( PDFName($self->glyphByEnc($n) || '.notdef') ); + } + + $self->{'FirstChar'} = PDFNum($data->{firstchar}); + $self->{'LastChar'} = PDFNum($data->{lastchar}); + + $self->{Widths}=PDFArray(); + foreach my $n ($data->{firstchar}..$data->{lastchar}) { + $self->{Widths}->add_elements( PDFNum($self->wxByEnc($n)) ); + } + + return($self); +} + +sub automap { + my ($self)=@_; + my $data=$self->data; + + my %gl=map { $_=>defineName($_) } keys %{$data->{wx}}; + + foreach my $n (0..255) { + delete $gl{$data->{e2n}->[$n]}; + } + + if(defined $data->{comps} && !$self->{-nocomps}) + { + foreach my $n (keys %{$data->{comps}}) + { + delete $gl{$n}; + } + } + + my @nm=sort { $gl{$a} <=> $gl{$b} } keys %gl; + + my @fnts=(); + my $count=0; + while(my @glyphs=splice(@nm,0,223)) + { + my $obj=$self->SUPER::new($self->{' apipdf'},$self->name.'am'.$count); + $obj->{' data'}={ %{$data} }; + $obj->data->{firstchar}=32; + $obj->data->{lastchar}=32+scalar(@glyphs); + push @fnts,$obj; + foreach my $key (qw( Subtype BaseFont FontDescriptor )) + { + $obj->{$key}=$self->{$key} if(defined $self->{$key}); + } + $obj->data->{char}=[]; + $obj->data->{uni}=[]; + foreach my $n (0..31) + { + $obj->data->{char}->[$n]='.notdef'; + $obj->data->{uni}->[$n]=0; + } + $obj->data->{char}->[32]='space'; + $obj->data->{uni}->[32]=32; + foreach my $n (33..$obj->data->{lastchar}) + { + $obj->data->{char}->[$n]=$glyphs[$n-33]; + $obj->data->{uni}->[$n]=$gl{$glyphs[$n-33]}; + } + foreach my $n (($obj->data->{lastchar}+1)..255) + { + $obj->data->{char}->[$n]='.notdef'; + $obj->data->{uni}->[$n]=0; + } + $obj->encodeByData(undef); + + $count++; + } + + return(@fnts); +} + +sub remap { + my ($self,$enc)=@_; + + my $obj=$self->SUPER::new($self->{' apipdf'},$self->name.'rm'.pdfkey()); + $obj->{' data'}={ %{$self->data} }; + foreach my $key (qw( Subtype BaseFont FontDescriptor )) { + $obj->{$key}=$self->{$key} if(defined $self->{$key}); + } + + $obj->encodeByData($enc); + + return($obj); +} + +1; diff --git a/lib/PDF/API2/Resource/Font/BdFont.pm b/lib/PDF/API2/Resource/Font/BdFont.pm new file mode 100644 index 0000000..2d2803c --- /dev/null +++ b/lib/PDF/API2/Resource/Font/BdFont.pm @@ -0,0 +1,205 @@ +#line 1 "PDF/API2/Resource/Font/BdFont.pm" +#line 1 "PDF/API2/Resource/Font/BdFont.pm" +package PDF::API2::Resource::Font::BdFont; + +use base 'PDF::API2::Resource::Font'; + +use strict; +no warnings qw[ deprecated recursion uninitialized ]; + +our $VERSION = '2.033'; # VERSION + +use PDF::API2::Util; +use PDF::API2::Basic::PDF::Utils; + +our $BmpNum = 0; + +#line 33 + +#line 39 + +#line 53 + +sub new { + my ($class,$pdf,$file,@opts) = @_; + my ($self,$data); + my %opts=@opts; + + $class = ref $class if ref $class; + $self = $class->SUPER::new($pdf, sprintf('%s+Bdf%02i',pdfkey(),++$BmpNum).'~'.time()); + $pdf->new_obj($self) unless($self->is_obj($pdf)); + + # adobe bitmap distribution font + $self->{' data'}=$self->readBDF($file); + + my $first=1; + my $last=255; + + $self->{'Subtype'} = PDFName('Type3'); + $self->{'FirstChar'} = PDFNum($first); + $self->{'LastChar'} = PDFNum($last); + $self->{'FontMatrix'} = PDFArray(map { PDFNum($_) } ( 0.001, 0, 0, 0.001, 0, 0 ) ); + $self->{'FontBBox'} = PDFArray(map { PDFNum($_) } ( $self->fontbbox ) ); + + my $xo=PDFDict(); + $self->{'Encoding'}=$xo; + $xo->{Type}=PDFName('Encoding'); + $xo->{BaseEncoding}=PDFName('WinAnsiEncoding'); + $xo->{Differences}=PDFArray(PDFNum('0'),(map { PDFName($_||'.notdef') } @{$self->data->{char}})); + + my $procs=PDFDict(); + $pdf->new_obj($procs); + $self->{'CharProcs'} = $procs; + + $self->{Resources}=PDFDict(); + $self->{Resources}->{ProcSet}=PDFArray(map { PDFName($_) } qw(PDF Text ImageB ImageC ImageI)); + foreach my $w ($first..$last) { + $self->data->{uni}->[$w]=uniByName($self->data->{char}->[$w]); + $self->data->{u2e}->{$self->data->{uni}->[$w]}=$w; + } + my @widths=(); + foreach my $w (@{$self->data->{char2}}) { + $widths[$w->{ENCODING}]=$self->data->{wx}->{$w->{NAME}}; + my @bbx=@{$w->{BBX}}; + my $stream=pack('H*',$w->{hex}); + my $y=$bbx[1]; + my $char=PDFDict(); + $char->{Filter}=PDFArray(PDFName('FlateDecode')); + ## $char->{' stream'}=$widths[$w->{ENCODING}]." 0 ".join(' ',map { int($_) } $self->fontbbox)." d1\n"; + $char->{' stream'}=$widths[$w->{ENCODING}]." 0 d0\n"; + $char->{Comment}=PDFStr("N='$w->{NAME}' C=($w->{ENCODING})"); + $procs->{$w->{NAME}}=$char; + @bbx=map { $_*1000/$self->data->{upm} } @bbx; + if($y==0) { + $char->{' stream'}.="q Q\n"; + } else { + my $x=8*length($stream)/$y; # q $x 0 0 $y 50 50 cm + my $img=qq|BI\n/Interpolate true/Mask[0 0.1]/Decode[1 0]/H $y/W $x/BPC 1/CS/G\nID $stream\nEI\n|; + $procs->{$self->data->{char}->[$w]}=$char; + $char->{' stream'}.="$bbx[0] 0 0 $bbx[1] $bbx[2] $bbx[3] cm\n$img\n"; + } + $pdf->new_obj($char); + } + $procs->{'.notdef'}=$procs->{$self->data->{char}->[32]}; + delete $procs->{''}; + $self->{Widths}=PDFArray(map { PDFNum($widths[$_]||0) } ($first..$last)); + $self->data->{e2n}=$self->data->{char}; + $self->data->{e2u}=$self->data->{uni}; + + $self->data->{u2c}={}; + $self->data->{u2e}={}; + $self->data->{u2n}={}; + $self->data->{n2c}={}; + $self->data->{n2e}={}; + $self->data->{n2u}={}; + + foreach my $n (reverse 0..255) { + $self->data->{n2c}->{$self->data->{char}->[$n] || '.notdef'}=$n unless(defined $self->data->{n2c}->{$self->data->{char}->[$n] || '.notdef'}); + $self->data->{n2e}->{$self->data->{e2n}->[$n] || '.notdef'}=$n unless(defined $self->data->{n2e}->{$self->data->{e2n}->[$n] || '.notdef'}); + + $self->data->{n2u}->{$self->data->{e2n}->[$n] || '.notdef'}=$self->data->{e2u}->[$n] unless(defined $self->data->{n2u}->{$self->data->{e2n}->[$n] || '.notdef'}); + $self->data->{n2u}->{$self->data->{char}->[$n] || '.notdef'}=$self->data->{uni}->[$n] unless(defined $self->data->{n2u}->{$self->data->{char}->[$n] || '.notdef'}); + + $self->data->{u2c}->{$self->data->{uni}->[$n]}=$n unless(defined $self->data->{u2c}->{$self->data->{uni}->[$n]}); + $self->data->{u2e}->{$self->data->{e2u}->[$n]}=$n unless(defined $self->data->{u2e}->{$self->data->{e2u}->[$n]}); + + $self->data->{u2n}->{$self->data->{e2u}->[$n]}=($self->data->{e2n}->[$n] || '.notdef') unless(defined $self->data->{u2n}->{$self->data->{e2u}->[$n]}); + $self->data->{u2n}->{$self->data->{uni}->[$n]}=($self->data->{char}->[$n] || '.notdef') unless(defined $self->data->{u2n}->{$self->data->{uni}->[$n]}); + } + + return($self); +} + +sub readBDF { + my ($self,$file)=@_; + my $data={}; + $data->{char}=[]; + $data->{char2}=[]; + $data->{wx}={}; + + if(! -e $file) {die "file='$file' not existant.";} + open(my $afmf, "<", $file) or die "Can't find the BDF file for $file"; + local($/, $_) = ("\n", undef); # ensure correct $INPUT_RECORD_SEPARATOR + while ($_=<$afmf>) { + chomp($_); + if (/^STARTCHAR/ .. /^ENDCHAR/) { + if (/^STARTCHAR\s+(\S+)/) { + my $name=$1; + $name=~s|^(\d+.*)$|X_$1|; + push @{$data->{char2}},{'NAME'=>$name}; + } elsif (/^BITMAP/ .. /^ENDCHAR/) { + next if(/^BITMAP/); + if(/^ENDCHAR/){ + $data->{char2}->[-1]->{NAME}||='E_'.$data->{char2}->[-1]->{ENCODING}; + $data->{char}->[$data->{char2}->[-1]->{ENCODING}]=$data->{char2}->[-1]->{NAME}; + ($data->{wx}->{$data->{char2}->[-1]->{NAME}})=split(/\s+/,$data->{char2}->[-1]->{SWIDTH}); + $data->{char2}->[-1]->{BBX}=[split(/\s+/,$data->{char2}->[-1]->{BBX})]; + } else { + $data->{char2}->[-1]->{hex}.=$_; + } + } else { + m|^(\S+)\s+(.+)$|; + $data->{char2}->[-1]->{uc($1)}.=$2; + } + ## } elsif(/^STARTPROPERTIES/ .. /^ENDPROPERTIES/) { + } else { + m|^(\S+)\s+(.+)$|; + $data->{uc($1)}.=$2; + } + } + close($afmf); + unless (exists $data->{wx}->{'.notdef'}) { + $data->{wx}->{'.notdef'} = 0; + $data->{bbox}{'.notdef'} = [0, 0, 0, 0]; + } + + $data->{fontname}=pdfkey().pdfkey().'~'.time(); + $data->{apiname}=$data->{fontname}; + $data->{flags} = 34; + $data->{fontbbox} = [ split(/\s+/,$data->{FONTBOUNDINGBOX}) ]; + $data->{upm}=$data->{PIXEL_SIZE} || ($data->{fontbbox}->[1] - $data->{fontbbox}->[3]); + @{$data->{fontbbox}} = map { int($_*1000/$data->{upm}) } @{$data->{fontbbox}}; + + foreach my $n (0..255) { + $data->{char}->[$n]||='.notdef'; + # $data->{wx}->{$data->{char}->[$n]}=int($data->{wx}->{$data->{char}->[$n]}*1000/$data->{upm}); + } + + $data->{uni}||=[]; + foreach my $n (0..255) { + $data->{uni}->[$n]=uniByName($data->{char}->[$n] || '.notdef') || 0; + } + $data->{ascender}=$data->{RAW_ASCENT} + || int($data->{FONT_ASCENT}*1000/$data->{upm}); + $data->{descender}=$data->{RAW_DESCENT} + || int($data->{FONT_DESCENT}*1000/$data->{upm}); + + $data->{type}='Type3'; + $data->{capheight}=1000; + $data->{iscore}=0; + $data->{issymbol} = 0; + $data->{isfixedpitch}=0; + $data->{italicangle}=0; + $data->{missingwidth}=$data->{AVERAGE_WIDTH} + || int($data->{FONT_AVERAGE_WIDTH}*1000/$data->{upm}) + || $data->{RAW_AVERAGE_WIDTH} + || 500; + $data->{underlineposition}=-200; + $data->{underlinethickness}=10; + $data->{xheight}=$data->{RAW_XHEIGHT} + || int($data->{FONT_XHEIGHT}*1000/$data->{upm}) + || int($data->{ascender}/2); + $data->{firstchar}=1; + $data->{lastchar}=255; + + delete $data->{wx}->{''}; + + return($data); +} + +1; + +__END__ + +#line 242 + diff --git a/lib/PDF/API2/Resource/Font/CoreFont.pm b/lib/PDF/API2/Resource/Font/CoreFont.pm new file mode 100644 index 0000000..be56bd5 --- /dev/null +++ b/lib/PDF/API2/Resource/Font/CoreFont.pm @@ -0,0 +1,297 @@ +#line 1 "PDF/API2/Resource/Font/CoreFont.pm" +#line 1 "PDF/API2/Resource/Font/CoreFont.pm" +package PDF::API2::Resource::Font::CoreFont; + +use base 'PDF::API2::Resource::Font'; + +use strict; +no warnings qw[ deprecated recursion uninitialized ]; + +our $VERSION = '2.033'; # VERSION + +use File::Basename; + +use PDF::API2::Util; +use PDF::API2::Basic::PDF::Utils; + +our $fonts; +our $alias; +our $subs; + +#line 41 + +#line 55 + +sub _look_for_font +{ + my $fname=shift; + ## return(%{$fonts->{$fname}}) if(defined $fonts->{$fname}); + eval "require PDF::API2::Resource::Font::CoreFont::$fname; "; + unless($@) + { + my $class = "PDF::API2::Resource::Font::CoreFont::$fname"; + $fonts->{$fname} = deep_copy($class->data()); + $fonts->{$fname}->{uni}||=[]; + foreach my $n (0..255) + { + $fonts->{$fname}->{uni}->[$n]=uniByName($fonts->{$fname}->{char}->[$n]) unless(defined $fonts->{$fname}->{uni}->[$n]); + } + return(%{$fonts->{$fname}}); + } + else + { + die "requested font '$fname' not installed "; + } +} + +# +# Deep copy something, thanks to Randal L. Schwartz +# Changed to deal w/ CODE refs, in which case it doesn't try to deep copy +# +sub deep_copy +{ + my $this = shift; + if (not ref $this) + { + $this; + } + elsif (ref $this eq "ARRAY") + { + [map &deep_copy($_), @$this]; + } + elsif (ref $this eq "HASH") + { + +{map { $_ => &deep_copy($this->{$_}) } keys %$this}; + } + elsif (ref $this eq "CODE") + { + # Can't deep copy code refs + return $this; + } + else + { + die "what type is $_?"; + } +} + +sub new +{ + my ($class,$pdf,$name,@opts) = @_; + my ($self,$data); + my %opts=(); + if(-f $name) + { + eval "require '$name'; "; + $name=basename($name,'.pm'); + } + my $lookname=lc($name); + $lookname=~s/[^a-z0-9]+//gi; + %opts=@opts if((scalar @opts)%2 == 0); + $opts{-encode}||='asis'; + + $lookname = defined($alias->{$lookname}) ? $alias->{$lookname} : $lookname ; + + if(defined $subs->{$lookname}) + { + $data={_look_for_font($subs->{$lookname}->{-alias})}; + foreach my $k (keys %{$subs->{$lookname}}) + { + next if($k=~/^\-/); + $data->{$k}=$subs->{$lookname}->{$k}; + } + } + else + { + unless(defined $opts{-metrics}) + { + $data={_look_for_font($lookname)}; + } + else + { + $data={%{$opts{-metrics}}}; + } + } + + die "Undefined Font '$name($lookname)'" unless($data->{fontname}); + + # we have data now here so we need to check if + # there is a -ttfile or -afmfile/-pfmfile/-pfbfile + # and proxy the call to the relevant modules + # + #if(defined $data->{-ttfile} && $data->{-ttfile}=_look_for_fontfile($data->{-ttfile})) + #{ + # return(PDF::API2::Resource::CIDFont::TrueType->new($pdf,$data->{-ttfile},@opts)); + #} + #elsif(defined $data->{-pfbfile} && $data->{-pfbfile}=_look_for_fontfile($data->{-pfbfile})) + #{ + # $data->{-afmfile}=_look_for_fontfile($data->{-afmfile}); + # return(PDF::API2::Resource::Font::Postscript->new($pdf,$data->{-pfbfile},$data->{-afmfile},@opts)); + #} + #elsif(defined $data->{-gfx}) + #{ # to be written and tested in 'Maki' first! + # return(PDF::API2::Resource::Font::gFont->new($pdf,$data,@opts); + #} + + $class = ref $class if ref $class; + $self = $class->SUPER::new($pdf, $data->{apiname}.pdfkey().'~'.time()); + $pdf->new_obj($self) unless($self->is_obj($pdf)); + $self->{' data'}=$data; + $self->{-dokern}=1 if($opts{-dokern}); + + $self->{'Subtype'} = PDFName($self->data->{type}); + $self->{'BaseFont'} = PDFName($self->fontname); + if($opts{-pdfname}) + { + $self->name($opts{-pdfname}); + } + + unless($self->data->{iscore}) + { + $self->{'FontDescriptor'}=$self->descrByData(); + } + + $self->encodeByData($opts{-encode}); + + return($self); +} + +#line 194 + +sub loadallfonts +{ + foreach my $f (qw[ + courier courierbold courierboldoblique courieroblique + georgia georgiabold georgiabolditalic georgiaitalic + helveticaboldoblique helveticaoblique helveticabold helvetica + symbol + timesbolditalic timesitalic timesroman timesbold + verdana verdanabold verdanabolditalic verdanaitalic + webdings + wingdings + zapfdingbats + ]) + { + _look_for_font($f); + } +} + +# andalemono +# arialrounded +# bankgothic +# impact +# ozhandicraft +# trebuchet +# trebuchetbold +# trebuchetbolditalic +# trebuchetitalic + +BEGIN +{ + + $alias = { + ## Windows Fonts with Type1 equivalence + 'arial' => 'helvetica', + 'arialitalic' => 'helveticaoblique', + 'arialbold' => 'helveticabold', + 'arialbolditalic' => 'helveticaboldoblique', + + 'times' => 'timesroman', + 'timesnewromanbolditalic' => 'timesbolditalic', + 'timesnewromanbold' => 'timesbold', + 'timesnewromanitalic' => 'timesitalic', + 'timesnewroman' => 'timesroman', + + 'couriernewbolditalic' => 'courierboldoblique', + 'couriernewbold' => 'courierbold', + 'couriernewitalic' => 'courieroblique', + 'couriernew' => 'courier', + }; + + $subs = { + #'bankgothicbold' => { + # 'apiname' => 'Bg2', + # '-alias' => 'bankgothic', + # 'fontname' => 'BankGothicMediumBT,Bold', + # 'flags' => 32+262144, + #}, + #'bankgothicbolditalic' => { + # 'apiname' => 'Bg3', + # '-alias' => 'bankgothic', + # 'fontname' => 'BankGothicMediumBT,BoldItalic', + # 'italicangle' => -15, + # 'flags' => 96+262144, + #}, + #'bankgothicitalic' => { + # 'apiname' => 'Bg4', + # '-alias' => 'bankgothic', + # 'fontname' => 'BankGothicMediumBT,Italic', + # 'italicangle' => -15, + # 'flags' => 96, + #}, + # 'impactitalic' => { + # 'apiname' => 'Imp2', + # '-alias' => 'impact', + # 'fontname' => 'Impact,Italic', + # 'italicangle' => -12, + # }, + # 'ozhandicraftbold' => { + # 'apiname' => 'Oz2', + # '-alias' => 'ozhandicraft', + # 'fontname' => 'OzHandicraftBT,Bold', + # 'italicangle' => 0, + # 'flags' => 32+262144, + # }, + # 'ozhandicraftitalic' => { + # 'apiname' => 'Oz3', + # '-alias' => 'ozhandicraft', + # 'fontname' => 'OzHandicraftBT,Italic', + # 'italicangle' => -15, + # 'flags' => 96, + # }, + # 'ozhandicraftbolditalic' => { + # 'apiname' => 'Oz4', + # '-alias' => 'ozhandicraft', + # 'fontname' => 'OzHandicraftBT,BoldItalic', + # 'italicangle' => -15, + # 'flags' => 96+262144, + # }, + # 'arialroundeditalic' => { + # 'apiname' => 'ArRo2', + # '-alias' => 'arialrounded', + # 'fontname' => 'ArialRoundedMTBold,Italic', + # 'italicangle' => -15, + # 'flags' => 96+262144, + # }, + # 'arialitalic' => { + # 'apiname' => 'Ar2', + # '-alias' => 'arial', + # 'fontname' => 'Arial,Italic', + # 'italicangle' => -15, + # 'flags' => 96, + # }, + # 'arialbolditalic' => { + # 'apiname' => 'Ar3', + # '-alias' => 'arial', + # 'fontname' => 'Arial,BoldItalic', + # 'italicangle' => -15, + # 'flags' => 96+262144, + # }, + # 'arialbold' => { + # 'apiname' => 'Ar4', + # '-alias' => 'arial', + # 'fontname' => 'Arial,Bold', + # 'flags' => 32+262144, + # }, + }; + + $fonts = { }; + +} + +1; + +__END__ + +#line 373 + + diff --git a/lib/PDF/API2/Resource/Font/CoreFont/bankgothic.pm b/lib/PDF/API2/Resource/Font/CoreFont/bankgothic.pm new file mode 100644 index 0000000..3a402ed --- /dev/null +++ b/lib/PDF/API2/Resource/Font/CoreFont/bankgothic.pm @@ -0,0 +1,517 @@ +#line 1 "PDF/API2/Resource/Font/CoreFont/bankgothic.pm" +#line 1 "PDF/API2/Resource/Font/CoreFont/bankgothic.pm" +package PDF::API2::Resource::Font::CoreFont::bankgothic; + +use strict; +use warnings; + +our $VERSION = '2.033'; # VERSION + +sub data { return { + 'fontname' => 'BankGothicMediumBT', + 'type' => 'TrueType', + 'apiname' => 'BaGo', + 'ascender' => '812', + 'capheight' => '517', + 'descender' => '-235', + 'isfixedpitch' => '0', + 'issymbol' => '0', + 'italicangle' => '0', + 'underlineposition' => '-170', + 'underlinethickness' => '143', + 'xheight' => '423', + 'firstchar' => '32', + 'lastchar' => '255', + 'flags' => '262176', + 'char' => [ # DEF. ENCODING GLYPH TABLE + '.notdef', # C+0x00 # U+0x0000 + '.notdef', # C+0x01 # U+0x0000 + '.notdef', # C+0x02 # U+0x0000 + '.notdef', # C+0x03 # U+0x0000 + '.notdef', # C+0x04 # U+0x0000 + '.notdef', # C+0x05 # U+0x0000 + '.notdef', # C+0x06 # U+0x0000 + '.notdef', # C+0x07 # U+0x0000 + '.notdef', # C+0x08 # U+0x0000 + '.notdef', # C+0x09 # U+0x0000 + '.notdef', # C+0x0A # U+0x0000 + '.notdef', # C+0x0B # U+0x0000 + '.notdef', # C+0x0C # U+0x0000 + '.notdef', # C+0x0D # U+0x0000 + '.notdef', # C+0x0E # U+0x0000 + '.notdef', # C+0x0F # U+0x0000 + '.notdef', # C+0x10 # U+0x0000 + '.notdef', # C+0x11 # U+0x0000 + '.notdef', # C+0x12 # U+0x0000 + '.notdef', # C+0x13 # U+0x0000 + '.notdef', # C+0x14 # U+0x0000 + '.notdef', # C+0x15 # U+0x0000 + '.notdef', # C+0x16 # U+0x0000 + '.notdef', # C+0x17 # U+0x0000 + '.notdef', # C+0x18 # U+0x0000 + '.notdef', # C+0x19 # U+0x0000 + '.notdef', # C+0x1A # U+0x0000 + '.notdef', # C+0x1B # U+0x0000 + '.notdef', # C+0x1C # U+0x0000 + '.notdef', # C+0x1D # U+0x0000 + '.notdef', # C+0x1E # U+0x0000 + '.notdef', # C+0x1F # U+0x0000 + 'space', # C+0x20 # U+0x0020 + 'exclam', # C+0x21 # U+0x0021 + 'quotedbl', # C+0x22 # U+0x0022 + 'numbersign', # C+0x23 # U+0x0023 + 'dollar', # C+0x24 # U+0x0024 + 'percent', # C+0x25 # U+0x0025 + 'ampersand', # C+0x26 # U+0x0026 + 'quotesingle', # C+0x27 # U+0x0027 + 'parenleft', # C+0x28 # U+0x0028 + 'parenright', # C+0x29 # U+0x0029 + 'asterisk', # C+0x2A # U+0x002A + 'plus', # C+0x2B # U+0x002B + 'comma', # C+0x2C # U+0x002C + 'hyphen', # C+0x2D # U+0x002D + 'period', # C+0x2E # U+0x002E + 'slash', # C+0x2F # U+0x002F + 'zero', # C+0x30 # U+0x0030 + 'one', # C+0x31 # U+0x0031 + 'two', # C+0x32 # U+0x0032 + 'three', # C+0x33 # U+0x0033 + 'four', # C+0x34 # U+0x0034 + 'five', # C+0x35 # U+0x0035 + 'six', # C+0x36 # U+0x0036 + 'seven', # C+0x37 # U+0x0037 + 'eight', # C+0x38 # U+0x0038 + 'nine', # C+0x39 # U+0x0039 + 'colon', # C+0x3A # U+0x003A + 'semicolon', # C+0x3B # U+0x003B + 'less', # C+0x3C # U+0x003C + 'equal', # C+0x3D # U+0x003D + 'greater', # C+0x3E # U+0x003E + 'question', # C+0x3F # U+0x003F + 'at', # C+0x40 # U+0x0040 + 'A', # C+0x41 # U+0x0041 + 'B', # C+0x42 # U+0x0042 + 'C', # C+0x43 # U+0x0043 + 'D', # C+0x44 # U+0x0044 + 'E', # C+0x45 # U+0x0045 + 'F', # C+0x46 # U+0x0046 + 'G', # C+0x47 # U+0x0047 + 'H', # C+0x48 # U+0x0048 + 'I', # C+0x49 # U+0x0049 + 'J', # C+0x4A # U+0x004A + 'K', # C+0x4B # U+0x004B + 'L', # C+0x4C # U+0x004C + 'M', # C+0x4D # U+0x004D + 'N', # C+0x4E # U+0x004E + 'O', # C+0x4F # U+0x004F + 'P', # C+0x50 # U+0x0050 + 'Q', # C+0x51 # U+0x0051 + 'R', # C+0x52 # U+0x0052 + 'S', # C+0x53 # U+0x0053 + 'T', # C+0x54 # U+0x0054 + 'U', # C+0x55 # U+0x0055 + 'V', # C+0x56 # U+0x0056 + 'W', # C+0x57 # U+0x0057 + 'X', # C+0x58 # U+0x0058 + 'Y', # C+0x59 # U+0x0059 + 'Z', # C+0x5A # U+0x005A + 'bracketleft', # C+0x5B # U+0x005B + 'backslash', # C+0x5C # U+0x005C + 'bracketright', # C+0x5D # U+0x005D + 'asciicircum', # C+0x5E # U+0x005E + 'underscore', # C+0x5F # U+0x005F + 'grave', # C+0x60 # U+0x0060 + 'a', # C+0x61 # U+0x0061 + 'b', # C+0x62 # U+0x0062 + 'c', # C+0x63 # U+0x0063 + 'd', # C+0x64 # U+0x0064 + 'e', # C+0x65 # U+0x0065 + 'f', # C+0x66 # U+0x0066 + 'g', # C+0x67 # U+0x0067 + 'h', # C+0x68 # U+0x0068 + 'i', # C+0x69 # U+0x0069 + 'j', # C+0x6A # U+0x006A + 'k', # C+0x6B # U+0x006B + 'l', # C+0x6C # U+0x006C + 'm', # C+0x6D # U+0x006D + 'n', # C+0x6E # U+0x006E + 'o', # C+0x6F # U+0x006F + 'p', # C+0x70 # U+0x0070 + 'q', # C+0x71 # U+0x0071 + 'r', # C+0x72 # U+0x0072 + 's', # C+0x73 # U+0x0073 + 't', # C+0x74 # U+0x0074 + 'u', # C+0x75 # U+0x0075 + 'v', # C+0x76 # U+0x0076 + 'w', # C+0x77 # U+0x0077 + 'x', # C+0x78 # U+0x0078 + 'y', # C+0x79 # U+0x0079 + 'z', # C+0x7A # U+0x007A + 'braceleft', # C+0x7B # U+0x007B + 'bar', # C+0x7C # U+0x007C + 'braceright', # C+0x7D # U+0x007D + 'asciitilde', # C+0x7E # U+0x007E + 'bullet', # C+0x7F # U+0x2022 + '.notdef', # C+0x80 # U+0x0000 + 'bullet', # C+0x81 # U+0x2022 + 'quotesinglbase', # C+0x82 # U+0x201A + 'florin', # C+0x83 # U+0x0192 + 'quotedblbase', # C+0x84 # U+0x201E + 'ellipsis', # C+0x85 # U+0x2026 + 'dagger', # C+0x86 # U+0x2020 + 'daggerdbl', # C+0x87 # U+0x2021 + 'circumflex', # C+0x88 # U+0x02C6 + 'perthousand', # C+0x89 # U+0x2030 + 'Scaron', # C+0x8A # U+0x0160 + 'guilsinglleft', # C+0x8B # U+0x2039 + 'OE', # C+0x8C # U+0x0152 + 'bullet', # C+0x8D # U+0x2022 + 'Zcaron', # C+0x8E # U+0x017D + 'bullet', # C+0x8F # U+0x2022 + 'bullet', # C+0x90 # U+0x2022 + 'quoteleft', # C+0x91 # U+0x2018 + 'quoteright', # C+0x92 # U+0x2019 + 'quotedblleft', # C+0x93 # U+0x201C + 'quotedblright', # C+0x94 # U+0x201D + 'bullet', # C+0x95 # U+0x2022 + 'endash', # C+0x96 # U+0x2013 + 'emdash', # C+0x97 # U+0x2014 + 'tilde', # C+0x98 # U+0x02DC + 'trademark', # C+0x99 # U+0x2122 + 'scaron', # C+0x9A # U+0x0161 + 'guilsinglright', # C+0x9B # U+0x203A + 'oe', # C+0x9C # U+0x0153 + 'bullet', # C+0x9D # U+0x2022 + 'zcaron', # C+0x9E # U+0x017E + 'Ydieresis', # C+0x9F # U+0x0178 + 'space', # C+0xA0 # U+0x0020 + 'exclamdown', # C+0xA1 # U+0x00A1 + 'cent', # C+0xA2 # U+0x00A2 + 'sterling', # C+0xA3 # U+0x00A3 + 'currency', # C+0xA4 # U+0x00A4 + 'yen', # C+0xA5 # U+0x00A5 + 'brokenbar', # C+0xA6 # U+0x00A6 + 'section', # C+0xA7 # U+0x00A7 + 'dieresis', # C+0xA8 # U+0x00A8 + 'copyright', # C+0xA9 # U+0x00A9 + 'ordfeminine', # C+0xAA # U+0x00AA + 'guillemotleft', # C+0xAB # U+0x00AB + 'logicalnot', # C+0xAC # U+0x00AC + 'hyphen', # C+0xAD # U+0x002D + 'registered', # C+0xAE # U+0x00AE + '.notdef', # C+0xAF # U+0x0000 + 'degree', # C+0xB0 # U+0x00B0 + 'plusminus', # C+0xB1 # U+0x00B1 + 'twosuperior', # C+0xB2 # U+0x00B2 + 'threesuperior', # C+0xB3 # U+0x00B3 + 'acute', # C+0xB4 # U+0x00B4 + '.notdef', # C+0xB5 # U+0x0000 + 'paragraph', # C+0xB6 # U+0x00B6 + 'periodcentered', # C+0xB7 # U+0x00B7 + 'cedilla', # C+0xB8 # U+0x00B8 + 'onesuperior', # C+0xB9 # U+0x00B9 + 'ordmasculine', # C+0xBA # U+0x00BA + 'guillemotright', # C+0xBB # U+0x00BB + 'onequarter', # C+0xBC # U+0x00BC + 'onehalf', # C+0xBD # U+0x00BD + 'threequarters', # C+0xBE # U+0x00BE + 'questiondown', # C+0xBF # U+0x00BF + 'Agrave', # C+0xC0 # U+0x00C0 + 'Aacute', # C+0xC1 # U+0x00C1 + 'Acircumflex', # C+0xC2 # U+0x00C2 + 'Atilde', # C+0xC3 # U+0x00C3 + 'Adieresis', # C+0xC4 # U+0x00C4 + 'Aring', # C+0xC5 # U+0x00C5 + 'AE', # C+0xC6 # U+0x00C6 + 'Ccedilla', # C+0xC7 # U+0x00C7 + 'Egrave', # C+0xC8 # U+0x00C8 + 'Eacute', # C+0xC9 # U+0x00C9 + 'Ecircumflex', # C+0xCA # U+0x00CA + 'Edieresis', # C+0xCB # U+0x00CB + 'Igrave', # C+0xCC # U+0x00CC + 'Iacute', # C+0xCD # U+0x00CD + 'Icircumflex', # C+0xCE # U+0x00CE + 'Idieresis', # C+0xCF # U+0x00CF + 'Eth', # C+0xD0 # U+0x00D0 + 'Ntilde', # C+0xD1 # U+0x00D1 + 'Ograve', # C+0xD2 # U+0x00D2 + 'Oacute', # C+0xD3 # U+0x00D3 + 'Ocircumflex', # C+0xD4 # U+0x00D4 + 'Otilde', # C+0xD5 # U+0x00D5 + 'Odieresis', # C+0xD6 # U+0x00D6 + 'multiply', # C+0xD7 # U+0x00D7 + 'Oslash', # C+0xD8 # U+0x00D8 + 'Ugrave', # C+0xD9 # U+0x00D9 + 'Uacute', # C+0xDA # U+0x00DA + 'Ucircumflex', # C+0xDB # U+0x00DB + 'Udieresis', # C+0xDC # U+0x00DC + 'Yacute', # C+0xDD # U+0x00DD + 'Thorn', # C+0xDE # U+0x00DE + 'germandbls', # C+0xDF # U+0x00DF + 'agrave', # C+0xE0 # U+0x00E0 + 'aacute', # C+0xE1 # U+0x00E1 + 'acircumflex', # C+0xE2 # U+0x00E2 + 'atilde', # C+0xE3 # U+0x00E3 + 'adieresis', # C+0xE4 # U+0x00E4 + 'aring', # C+0xE5 # U+0x00E5 + 'ae', # C+0xE6 # U+0x00E6 + 'ccedilla', # C+0xE7 # U+0x00E7 + 'egrave', # C+0xE8 # U+0x00E8 + 'eacute', # C+0xE9 # U+0x00E9 + 'ecircumflex', # C+0xEA # U+0x00EA + 'edieresis', # C+0xEB # U+0x00EB + 'igrave', # C+0xEC # U+0x00EC + 'iacute', # C+0xED # U+0x00ED + 'icircumflex', # C+0xEE # U+0x00EE + 'idieresis', # C+0xEF # U+0x00EF + 'eth', # C+0xF0 # U+0x00F0 + 'ntilde', # C+0xF1 # U+0x00F1 + 'ograve', # C+0xF2 # U+0x00F2 + 'oacute', # C+0xF3 # U+0x00F3 + 'ocircumflex', # C+0xF4 # U+0x00F4 + 'otilde', # C+0xF5 # U+0x00F5 + 'odieresis', # C+0xF6 # U+0x00F6 + 'divide', # C+0xF7 # U+0x00F7 + 'oslash', # C+0xF8 # U+0x00F8 + 'ugrave', # C+0xF9 # U+0x00F9 + 'uacute', # C+0xFA # U+0x00FA + 'ucircumflex', # C+0xFB # U+0x00FB + 'udieresis', # C+0xFC # U+0x00FC + 'yacute', # C+0xFD # U+0x00FD + 'thorn', # C+0xFE # U+0x00FE + 'ydieresis', # C+0xFF # U+0x00FF + ], # DEF. ENCODING GLYPH TABLE + 'fontbbox' => [ -166, -235, 1290, 812 ], + 'wx' => { # HORIZ. WIDTH TABLE + 'space' => '388', # C+0x20 # U+0x0020 + 'exclam' => '384', # C+0x21 # U+0x0021 + 'quotedbl' => '300', # C+0x22 # U+0x0022 + 'numbersign' => '770', # C+0x23 # U+0x0023 + 'dollar' => '773', # C+0x24 # U+0x0024 + 'percent' => '799', # C+0x25 # U+0x0025 + 'ampersand' => '825', # C+0x26 # U+0x0026 + 'quotesingle' => '155', # C+0x27 # U+0x0027 + 'parenleft' => '332', # C+0x28 # U+0x0028 + 'parenright' => '332', # C+0x29 # U+0x0029 + 'asterisk' => '500', # C+0x2A # U+0x002A + 'plus' => '834', # C+0x2B # U+0x002B + 'comma' => '332', # C+0x2C # U+0x002C + 'hyphen' => '331', # C+0x2D # U+0x002D + 'period' => '332', # C+0x2E # U+0x002E + 'slash' => '278', # C+0x2F # U+0x002F + 'zero' => '773', # C+0x30 # U+0x0030 + 'one' => '773', # C+0x31 # U+0x0031 + 'two' => '773', # C+0x32 # U+0x0032 + 'three' => '773', # C+0x33 # U+0x0033 + 'four' => '773', # C+0x34 # U+0x0034 + 'five' => '773', # C+0x35 # U+0x0035 + 'six' => '773', # C+0x36 # U+0x0036 + 'seven' => '773', # C+0x37 # U+0x0037 + 'eight' => '773', # C+0x38 # U+0x0038 + 'nine' => '773', # C+0x39 # U+0x0039 + 'colon' => '332', # C+0x3A # U+0x003A + 'semicolon' => '332', # C+0x3B # U+0x003B + 'less' => '834', # C+0x3C # U+0x003C + 'equal' => '834', # C+0x3D # U+0x003D + 'greater' => '834', # C+0x3E # U+0x003E + 'question' => '663', # C+0x3F # U+0x003F + 'at' => '1000', # C+0x40 # U+0x0040 + 'A' => '771', # C+0x41 # U+0x0041 + 'B' => '794', # C+0x42 # U+0x0042 + 'C' => '801', # C+0x43 # U+0x0043 + 'D' => '848', # C+0x44 # U+0x0044 + 'E' => '755', # C+0x45 # U+0x0045 + 'F' => '671', # C+0x46 # U+0x0046 + 'G' => '855', # C+0x47 # U+0x0047 + 'H' => '880', # C+0x48 # U+0x0048 + 'I' => '384', # C+0x49 # U+0x0049 + 'J' => '667', # C+0x4A # U+0x004A + 'K' => '794', # C+0x4B # U+0x004B + 'L' => '684', # C+0x4C # U+0x004C + 'M' => '926', # C+0x4D # U+0x004D + 'N' => '870', # C+0x4E # U+0x004E + 'O' => '878', # C+0x4F # U+0x004F + 'P' => '744', # C+0x50 # U+0x0050 + 'Q' => '878', # C+0x51 # U+0x0051 + 'R' => '802', # C+0x52 # U+0x0052 + 'S' => '810', # C+0x53 # U+0x0053 + 'T' => '625', # C+0x54 # U+0x0054 + 'U' => '847', # C+0x55 # U+0x0055 + 'V' => '682', # C+0x56 # U+0x0056 + 'W' => '926', # C+0x57 # U+0x0057 + 'X' => '718', # C+0x58 # U+0x0058 + 'Y' => '672', # C+0x59 # U+0x0059 + 'Z' => '683', # C+0x5A # U+0x005A + 'bracketleft' => '332', # C+0x5B # U+0x005B + 'backslash' => '278', # C+0x5C # U+0x005C + 'bracketright' => '332', # C+0x5D # U+0x005D + 'asciicircum' => '1000', # C+0x5E # U+0x005E + 'underscore' => '500', # C+0x5F # U+0x005F + 'grave' => '500', # C+0x60 # U+0x0060 + 'a' => '646', # C+0x61 # U+0x0061 + 'b' => '658', # C+0x62 # U+0x0062 + 'c' => '645', # C+0x63 # U+0x0063 + 'd' => '694', # C+0x64 # U+0x0064 + 'e' => '608', # C+0x65 # U+0x0065 + 'f' => '550', # C+0x66 # U+0x0066 + 'g' => '692', # C+0x67 # U+0x0067 + 'h' => '718', # C+0x68 # U+0x0068 + 'i' => '292', # C+0x69 # U+0x0069 + 'j' => '561', # C+0x6A # U+0x006A + 'k' => '621', # C+0x6B # U+0x006B + 'l' => '552', # C+0x6C # U+0x006C + 'm' => '768', # C+0x6D # U+0x006D + 'n' => '712', # C+0x6E # U+0x006E + 'o' => '715', # C+0x6F # U+0x006F + 'p' => '628', # C+0x70 # U+0x0070 + 'q' => '715', # C+0x71 # U+0x0071 + 'r' => '650', # C+0x72 # U+0x0072 + 's' => '664', # C+0x73 # U+0x0073 + 't' => '590', # C+0x74 # U+0x0074 + 'u' => '689', # C+0x75 # U+0x0075 + 'v' => '632', # C+0x76 # U+0x0076 + 'w' => '790', # C+0x77 # U+0x0077 + 'x' => '639', # C+0x78 # U+0x0078 + 'y' => '593', # C+0x79 # U+0x0079 + 'z' => '617', # C+0x7A # U+0x007A + 'braceleft' => '500', # C+0x7B # U+0x007B + 'bar' => '500', # C+0x7C # U+0x007C + 'braceright' => '500', # C+0x7D # U+0x007D + 'asciitilde' => '834', # C+0x7E # U+0x007E + 'bullet' => '590', # C+0x7F # U+0x2022 + 'quotesinglbase' => '332', # C+0x82 # U+0x201A + 'florin' => '773', # C+0x83 # U+0x0192 + 'quotedblbase' => '580', # C+0x84 # U+0x201E + 'ellipsis' => '1000', # C+0x85 # U+0x2026 + 'dagger' => '500', # C+0x86 # U+0x2020 + 'daggerdbl' => '500', # C+0x87 # U+0x2021 + 'circumflex' => '500', # C+0x88 # U+0x02C6 + 'perthousand' => '1161', # C+0x89 # U+0x2030 + 'Scaron' => '810', # C+0x8A # U+0x0160 + 'guilsinglleft' => '332', # C+0x8B # U+0x2039 + 'OE' => '1105', # C+0x8C # U+0x0152 + 'Zcaron' => '683', # C+0x8E # U+0x017D + 'quoteleft' => '332', # C+0x91 # U+0x2018 + 'quoteright' => '332', # C+0x92 # U+0x2019 + 'quotedblleft' => '580', # C+0x93 # U+0x201C + 'quotedblright' => '580', # C+0x94 # U+0x201D + 'endash' => '500', # C+0x96 # U+0x2013 + 'emdash' => '1000', # C+0x97 # U+0x2014 + 'tilde' => '500', # C+0x98 # U+0x02DC + 'trademark' => '834', # C+0x99 # U+0x2122 + 'scaron' => '664', # C+0x9A # U+0x0161 + 'guilsinglright' => '332', # C+0x9B # U+0x203A + 'oe' => '908', # C+0x9C # U+0x0153 + 'zcaron' => '617', # C+0x9E # U+0x017E + 'Ydieresis' => '672', # C+0x9F # U+0x0178 + 'exclamdown' => '384', # C+0xA1 # U+0x00A1 + 'cent' => '773', # C+0xA2 # U+0x00A2 + 'sterling' => '773', # C+0xA3 # U+0x00A3 + 'currency' => '773', # C+0xA4 # U+0x00A4 + 'yen' => '773', # C+0xA5 # U+0x00A5 + 'brokenbar' => '500', # C+0xA6 # U+0x00A6 + 'section' => '500', # C+0xA7 # U+0x00A7 + 'dieresis' => '500', # C+0xA8 # U+0x00A8 + 'copyright' => '834', # C+0xA9 # U+0x00A9 + 'ordfeminine' => '426', # C+0xAA # U+0x00AA + 'guillemotleft' => '563', # C+0xAB # U+0x00AB + 'logicalnot' => '834', # C+0xAC # U+0x00AC + 'registered' => '834', # C+0xAE # U+0x00AE + 'degree' => '330', # C+0xB0 # U+0x00B0 + 'plusminus' => '834', # C+0xB1 # U+0x00B1 + 'twosuperior' => '510', # C+0xB2 # U+0x00B2 + 'threesuperior' => '510', # C+0xB3 # U+0x00B3 + 'acute' => '500', # C+0xB4 # U+0x00B4 + 'paragraph' => '500', # C+0xB6 # U+0x00B6 + 'periodcentered' => '332', # C+0xB7 # U+0x00B7 + 'cedilla' => '500', # C+0xB8 # U+0x00B8 + 'onesuperior' => '510', # C+0xB9 # U+0x00B9 + 'ordmasculine' => '473', # C+0xBA # U+0x00BA + 'guillemotright' => '563', # C+0xBB # U+0x00BB + 'onequarter' => '1142', # C+0xBC # U+0x00BC + 'onehalf' => '1142', # C+0xBD # U+0x00BD + 'threequarters' => '1142', # C+0xBE # U+0x00BE + 'questiondown' => '663', # C+0xBF # U+0x00BF + 'Agrave' => '771', # C+0xC0 # U+0x00C0 + 'Aacute' => '771', # C+0xC1 # U+0x00C1 + 'Acircumflex' => '771', # C+0xC2 # U+0x00C2 + 'Atilde' => '771', # C+0xC3 # U+0x00C3 + 'Adieresis' => '771', # C+0xC4 # U+0x00C4 + 'Aring' => '771', # C+0xC5 # U+0x00C5 + 'AE' => '1069', # C+0xC6 # U+0x00C6 + 'Ccedilla' => '801', # C+0xC7 # U+0x00C7 + 'Egrave' => '755', # C+0xC8 # U+0x00C8 + 'Eacute' => '755', # C+0xC9 # U+0x00C9 + 'Ecircumflex' => '755', # C+0xCA # U+0x00CA + 'Edieresis' => '755', # C+0xCB # U+0x00CB + 'Igrave' => '384', # C+0xCC # U+0x00CC + 'Iacute' => '384', # C+0xCD # U+0x00CD + 'Icircumflex' => '384', # C+0xCE # U+0x00CE + 'Idieresis' => '384', # C+0xCF # U+0x00CF + 'Eth' => '848', # C+0xD0 # U+0x00D0 + 'Ntilde' => '870', # C+0xD1 # U+0x00D1 + 'Ograve' => '878', # C+0xD2 # U+0x00D2 + 'Oacute' => '878', # C+0xD3 # U+0x00D3 + 'Ocircumflex' => '878', # C+0xD4 # U+0x00D4 + 'Otilde' => '878', # C+0xD5 # U+0x00D5 + 'Odieresis' => '878', # C+0xD6 # U+0x00D6 + 'multiply' => '834', # C+0xD7 # U+0x00D7 + 'Oslash' => '878', # C+0xD8 # U+0x00D8 + 'Ugrave' => '847', # C+0xD9 # U+0x00D9 + 'Uacute' => '847', # C+0xDA # U+0x00DA + 'Ucircumflex' => '847', # C+0xDB # U+0x00DB + 'Udieresis' => '847', # C+0xDC # U+0x00DC + 'Yacute' => '672', # C+0xDD # U+0x00DD + 'Thorn' => '744', # C+0xDE # U+0x00DE + 'germandbls' => '1327', # C+0xDF # U+0x00DF + 'agrave' => '646', # C+0xE0 # U+0x00E0 + 'aacute' => '646', # C+0xE1 # U+0x00E1 + 'acircumflex' => '646', # C+0xE2 # U+0x00E2 + 'atilde' => '646', # C+0xE3 # U+0x00E3 + 'adieresis' => '646', # C+0xE4 # U+0x00E4 + 'aring' => '646', # C+0xE5 # U+0x00E5 + 'ae' => '898', # C+0xE6 # U+0x00E6 + 'ccedilla' => '645', # C+0xE7 # U+0x00E7 + 'egrave' => '608', # C+0xE8 # U+0x00E8 + 'eacute' => '608', # C+0xE9 # U+0x00E9 + 'ecircumflex' => '608', # C+0xEA # U+0x00EA + 'edieresis' => '608', # C+0xEB # U+0x00EB + 'igrave' => '292', # C+0xEC # U+0x00EC + 'iacute' => '292', # C+0xED # U+0x00ED + 'icircumflex' => '292', # C+0xEE # U+0x00EE + 'idieresis' => '292', # C+0xEF # U+0x00EF + 'eth' => '694', # C+0xF0 # U+0x00F0 + 'ntilde' => '712', # C+0xF1 # U+0x00F1 + 'ograve' => '715', # C+0xF2 # U+0x00F2 + 'oacute' => '715', # C+0xF3 # U+0x00F3 + 'ocircumflex' => '715', # C+0xF4 # U+0x00F4 + 'otilde' => '715', # C+0xF5 # U+0x00F5 + 'odieresis' => '715', # C+0xF6 # U+0x00F6 + 'divide' => '834', # C+0xF7 # U+0x00F7 + 'oslash' => '715', # C+0xF8 # U+0x00F8 + 'ugrave' => '689', # C+0xF9 # U+0x00F9 + 'uacute' => '689', # C+0xFA # U+0x00FA + 'ucircumflex' => '689', # C+0xFB # U+0x00FB + 'udieresis' => '689', # C+0xFC # U+0x00FC + 'yacute' => '593', # C+0xFD # U+0x00FD + 'thorn' => '628', # C+0xFE # U+0x00FE + 'ydieresis' => '593', # C+0xFF # U+0x00FF + 'dotlessi' => '292', # U+0x0131 + 'Lslash' => '684', # U+0x0141 + 'lslash' => '552', # U+0x0142 + 'caron' => '500', # U+0x02C7 + 'breve' => '500', # U+0x02D8 + 'dotaccent' => '500', # U+0x02D9 + 'ring' => '500', # U+0x02DA + 'ogonek' => '500', # U+0x02DB + 'hungarumlaut' => '500', # U+0x02DD + 'fraction' => '167', # U+0x2044 + 'Euro' => '773', # U+0x20AC + 'euro' => '773', # U+0x20AC + 'minus' => '834', # U+0x2212 + 'fi' => '841', # U+0xFB01 + 'fl' => '1103', # U+0xFB02 + }, # HORIZ. WIDTH TABLE +} }; + +1; diff --git a/lib/PDF/API2/Resource/Font/CoreFont/courier.pm b/lib/PDF/API2/Resource/Font/CoreFont/courier.pm new file mode 100644 index 0000000..c14bc31 --- /dev/null +++ b/lib/PDF/API2/Resource/Font/CoreFont/courier.pm @@ -0,0 +1,790 @@ +#line 1 "PDF/API2/Resource/Font/CoreFont/courier.pm" +#line 1 "PDF/API2/Resource/Font/CoreFont/courier.pm" +package PDF::API2::Resource::Font::CoreFont::courier; + +use strict; +use warnings; + +our $VERSION = '2.033'; # VERSION + +sub data { return { + 'fontname' => 'Courier', + 'type' => 'Type1', + 'apiname' => 'Cour', + 'ascender' => '629', + 'capheight' => '562', + 'descender' => '-157', + 'iscore' => '1', + 'isfixedpitch' => '1', + 'italicangle' => '0', + 'missingwidth' => '600', + 'underlineposition' => '-100', + 'underlinethickness' => '50', + 'xheight' => '426', + 'firstchar' => '32', + 'lastchar' => '255', + 'fontbbox' => [-23, -250, 715, 805], + 'char' => [ # DEF. ENCODING GLYPH TABLE + '.notdef', # C+0x00 # U+0x0000 + '.notdef', # C+0x01 # U+0x0000 + '.notdef', # C+0x02 # U+0x0000 + '.notdef', # C+0x03 # U+0x0000 + '.notdef', # C+0x04 # U+0x0000 + '.notdef', # C+0x05 # U+0x0000 + '.notdef', # C+0x06 # U+0x0000 + '.notdef', # C+0x07 # U+0x0000 + '.notdef', # C+0x08 # U+0x0000 + '.notdef', # C+0x09 # U+0x0000 + '.notdef', # C+0x0A # U+0x0000 + '.notdef', # C+0x0B # U+0x0000 + '.notdef', # C+0x0C # U+0x0000 + '.notdef', # C+0x0D # U+0x0000 + '.notdef', # C+0x0E # U+0x0000 + '.notdef', # C+0x0F # U+0x0000 + '.notdef', # C+0x10 # U+0x0000 + '.notdef', # C+0x11 # U+0x0000 + '.notdef', # C+0x12 # U+0x0000 + '.notdef', # C+0x13 # U+0x0000 + '.notdef', # C+0x14 # U+0x0000 + '.notdef', # C+0x15 # U+0x0000 + '.notdef', # C+0x16 # U+0x0000 + '.notdef', # C+0x17 # U+0x0000 + '.notdef', # C+0x18 # U+0x0000 + '.notdef', # C+0x19 # U+0x0000 + '.notdef', # C+0x1A # U+0x0000 + '.notdef', # C+0x1B # U+0x0000 + '.notdef', # C+0x1C # U+0x0000 + '.notdef', # C+0x1D # U+0x0000 + '.notdef', # C+0x1E # U+0x0000 + '.notdef', # C+0x1F # U+0x0000 + 'space', # C+0x20 # U+0x0020 + 'exclam', # C+0x21 # U+0x0021 + 'quotedbl', # C+0x22 # U+0x0022 + 'numbersign', # C+0x23 # U+0x0023 + 'dollar', # C+0x24 # U+0x0024 + 'percent', # C+0x25 # U+0x0025 + 'ampersand', # C+0x26 # U+0x0026 + 'quotesingle', # C+0x27 # U+0x0027 + 'parenleft', # C+0x28 # U+0x0028 + 'parenright', # C+0x29 # U+0x0029 + 'asterisk', # C+0x2A # U+0x002A + 'plus', # C+0x2B # U+0x002B + 'comma', # C+0x2C # U+0x002C + 'hyphen', # C+0x2D # U+0x002D + 'period', # C+0x2E # U+0x002E + 'slash', # C+0x2F # U+0x002F + 'zero', # C+0x30 # U+0x0030 + 'one', # C+0x31 # U+0x0031 + 'two', # C+0x32 # U+0x0032 + 'three', # C+0x33 # U+0x0033 + 'four', # C+0x34 # U+0x0034 + 'five', # C+0x35 # U+0x0035 + 'six', # C+0x36 # U+0x0036 + 'seven', # C+0x37 # U+0x0037 + 'eight', # C+0x38 # U+0x0038 + 'nine', # C+0x39 # U+0x0039 + 'colon', # C+0x3A # U+0x003A + 'semicolon', # C+0x3B # U+0x003B + 'less', # C+0x3C # U+0x003C + 'equal', # C+0x3D # U+0x003D + 'greater', # C+0x3E # U+0x003E + 'question', # C+0x3F # U+0x003F + 'at', # C+0x40 # U+0x0040 + 'A', # C+0x41 # U+0x0041 + 'B', # C+0x42 # U+0x0042 + 'C', # C+0x43 # U+0x0043 + 'D', # C+0x44 # U+0x0044 + 'E', # C+0x45 # U+0x0045 + 'F', # C+0x46 # U+0x0046 + 'G', # C+0x47 # U+0x0047 + 'H', # C+0x48 # U+0x0048 + 'I', # C+0x49 # U+0x0049 + 'J', # C+0x4A # U+0x004A + 'K', # C+0x4B # U+0x004B + 'L', # C+0x4C # U+0x004C + 'M', # C+0x4D # U+0x004D + 'N', # C+0x4E # U+0x004E + 'O', # C+0x4F # U+0x004F + 'P', # C+0x50 # U+0x0050 + 'Q', # C+0x51 # U+0x0051 + 'R', # C+0x52 # U+0x0052 + 'S', # C+0x53 # U+0x0053 + 'T', # C+0x54 # U+0x0054 + 'U', # C+0x55 # U+0x0055 + 'V', # C+0x56 # U+0x0056 + 'W', # C+0x57 # U+0x0057 + 'X', # C+0x58 # U+0x0058 + 'Y', # C+0x59 # U+0x0059 + 'Z', # C+0x5A # U+0x005A + 'bracketleft', # C+0x5B # U+0x005B + 'backslash', # C+0x5C # U+0x005C + 'bracketright', # C+0x5D # U+0x005D + 'asciicircum', # C+0x5E # U+0x005E + 'underscore', # C+0x5F # U+0x005F + 'grave', # C+0x60 # U+0x0060 + 'a', # C+0x61 # U+0x0061 + 'b', # C+0x62 # U+0x0062 + 'c', # C+0x63 # U+0x0063 + 'd', # C+0x64 # U+0x0064 + 'e', # C+0x65 # U+0x0065 + 'f', # C+0x66 # U+0x0066 + 'g', # C+0x67 # U+0x0067 + 'h', # C+0x68 # U+0x0068 + 'i', # C+0x69 # U+0x0069 + 'j', # C+0x6A # U+0x006A + 'k', # C+0x6B # U+0x006B + 'l', # C+0x6C # U+0x006C + 'm', # C+0x6D # U+0x006D + 'n', # C+0x6E # U+0x006E + 'o', # C+0x6F # U+0x006F + 'p', # C+0x70 # U+0x0070 + 'q', # C+0x71 # U+0x0071 + 'r', # C+0x72 # U+0x0072 + 's', # C+0x73 # U+0x0073 + 't', # C+0x74 # U+0x0074 + 'u', # C+0x75 # U+0x0075 + 'v', # C+0x76 # U+0x0076 + 'w', # C+0x77 # U+0x0077 + 'x', # C+0x78 # U+0x0078 + 'y', # C+0x79 # U+0x0079 + 'z', # C+0x7A # U+0x007A + 'braceleft', # C+0x7B # U+0x007B + 'bar', # C+0x7C # U+0x007C + 'braceright', # C+0x7D # U+0x007D + 'asciitilde', # C+0x7E # U+0x007E + 'bullet', # C+0x7F # U+0x2022 + 'Euro', # C+0x80 # U+0x20AC + 'bullet', # C+0x81 # U+0x2022 + 'quotesinglbase', # C+0x82 # U+0x201A + 'florin', # C+0x83 # U+0x0192 + 'quotedblbase', # C+0x84 # U+0x201E + 'ellipsis', # C+0x85 # U+0x2026 + 'dagger', # C+0x86 # U+0x2020 + 'daggerdbl', # C+0x87 # U+0x2021 + 'circumflex', # C+0x88 # U+0x02C6 + 'perthousand', # C+0x89 # U+0x2030 + 'Scaron', # C+0x8A # U+0x0160 + 'guilsinglleft', # C+0x8B # U+0x2039 + 'OE', # C+0x8C # U+0x0152 + 'bullet', # C+0x8D # U+0x2022 + 'Zcaron', # C+0x8E # U+0x017D + 'bullet', # C+0x8F # U+0x2022 + 'bullet', # C+0x90 # U+0x2022 + 'quoteleft', # C+0x91 # U+0x2018 + 'quoteright', # C+0x92 # U+0x2019 + 'quotedblleft', # C+0x93 # U+0x201C + 'quotedblright', # C+0x94 # U+0x201D + 'bullet', # C+0x95 # U+0x2022 + 'endash', # C+0x96 # U+0x2013 + 'emdash', # C+0x97 # U+0x2014 + 'tilde', # C+0x98 # U+0x02DC + 'trademark', # C+0x99 # U+0x2122 + 'scaron', # C+0x9A # U+0x0161 + 'guilsinglright', # C+0x9B # U+0x203A + 'oe', # C+0x9C # U+0x0153 + 'bullet', # C+0x9D # U+0x2022 + 'zcaron', # C+0x9E # U+0x017E + 'Ydieresis', # C+0x9F # U+0x0178 + 'space', # C+0xA0 # U+0x0020 + 'exclamdown', # C+0xA1 # U+0x00A1 + 'cent', # C+0xA2 # U+0x00A2 + 'sterling', # C+0xA3 # U+0x00A3 + 'currency', # C+0xA4 # U+0x00A4 + 'yen', # C+0xA5 # U+0x00A5 + 'brokenbar', # C+0xA6 # U+0x00A6 + 'section', # C+0xA7 # U+0x00A7 + 'dieresis', # C+0xA8 # U+0x00A8 + 'copyright', # C+0xA9 # U+0x00A9 + 'ordfeminine', # C+0xAA # U+0x00AA + 'guillemotleft', # C+0xAB # U+0x00AB + 'logicalnot', # C+0xAC # U+0x00AC + 'hyphen', # C+0xAD # U+0x002D + 'registered', # C+0xAE # U+0x00AE + 'macron', # C+0xAF # U+0x00AF + 'degree', # C+0xB0 # U+0x00B0 + 'plusminus', # C+0xB1 # U+0x00B1 + 'twosuperior', # C+0xB2 # U+0x00B2 + 'threesuperior', # C+0xB3 # U+0x00B3 + 'acute', # C+0xB4 # U+0x00B4 + 'mu', # C+0xB5 # U+0x00B5 + 'paragraph', # C+0xB6 # U+0x00B6 + 'periodcentered', # C+0xB7 # U+0x00B7 + 'cedilla', # C+0xB8 # U+0x00B8 + 'onesuperior', # C+0xB9 # U+0x00B9 + 'ordmasculine', # C+0xBA # U+0x00BA + 'guillemotright', # C+0xBB # U+0x00BB + 'onequarter', # C+0xBC # U+0x00BC + 'onehalf', # C+0xBD # U+0x00BD + 'threequarters', # C+0xBE # U+0x00BE + 'questiondown', # C+0xBF # U+0x00BF + 'Agrave', # C+0xC0 # U+0x00C0 + 'Aacute', # C+0xC1 # U+0x00C1 + 'Acircumflex', # C+0xC2 # U+0x00C2 + 'Atilde', # C+0xC3 # U+0x00C3 + 'Adieresis', # C+0xC4 # U+0x00C4 + 'Aring', # C+0xC5 # U+0x00C5 + 'AE', # C+0xC6 # U+0x00C6 + 'Ccedilla', # C+0xC7 # U+0x00C7 + 'Egrave', # C+0xC8 # U+0x00C8 + 'Eacute', # C+0xC9 # U+0x00C9 + 'Ecircumflex', # C+0xCA # U+0x00CA + 'Edieresis', # C+0xCB # U+0x00CB + 'Igrave', # C+0xCC # U+0x00CC + 'Iacute', # C+0xCD # U+0x00CD + 'Icircumflex', # C+0xCE # U+0x00CE + 'Idieresis', # C+0xCF # U+0x00CF + 'Eth', # C+0xD0 # U+0x00D0 + 'Ntilde', # C+0xD1 # U+0x00D1 + 'Ograve', # C+0xD2 # U+0x00D2 + 'Oacute', # C+0xD3 # U+0x00D3 + 'Ocircumflex', # C+0xD4 # U+0x00D4 + 'Otilde', # C+0xD5 # U+0x00D5 + 'Odieresis', # C+0xD6 # U+0x00D6 + 'multiply', # C+0xD7 # U+0x00D7 + 'Oslash', # C+0xD8 # U+0x00D8 + 'Ugrave', # C+0xD9 # U+0x00D9 + 'Uacute', # C+0xDA # U+0x00DA + 'Ucircumflex', # C+0xDB # U+0x00DB + 'Udieresis', # C+0xDC # U+0x00DC + 'Yacute', # C+0xDD # U+0x00DD + 'Thorn', # C+0xDE # U+0x00DE + 'germandbls', # C+0xDF # U+0x00DF + 'agrave', # C+0xE0 # U+0x00E0 + 'aacute', # C+0xE1 # U+0x00E1 + 'acircumflex', # C+0xE2 # U+0x00E2 + 'atilde', # C+0xE3 # U+0x00E3 + 'adieresis', # C+0xE4 # U+0x00E4 + 'aring', # C+0xE5 # U+0x00E5 + 'ae', # C+0xE6 # U+0x00E6 + 'ccedilla', # C+0xE7 # U+0x00E7 + 'egrave', # C+0xE8 # U+0x00E8 + 'eacute', # C+0xE9 # U+0x00E9 + 'ecircumflex', # C+0xEA # U+0x00EA + 'edieresis', # C+0xEB # U+0x00EB + 'igrave', # C+0xEC # U+0x00EC + 'iacute', # C+0xED # U+0x00ED + 'icircumflex', # C+0xEE # U+0x00EE + 'idieresis', # C+0xEF # U+0x00EF + 'eth', # C+0xF0 # U+0x00F0 + 'ntilde', # C+0xF1 # U+0x00F1 + 'ograve', # C+0xF2 # U+0x00F2 + 'oacute', # C+0xF3 # U+0x00F3 + 'ocircumflex', # C+0xF4 # U+0x00F4 + 'otilde', # C+0xF5 # U+0x00F5 + 'odieresis', # C+0xF6 # U+0x00F6 + 'divide', # C+0xF7 # U+0x00F7 + 'oslash', # C+0xF8 # U+0x00F8 + 'ugrave', # C+0xF9 # U+0x00F9 + 'uacute', # C+0xFA # U+0x00FA + 'ucircumflex', # C+0xFB # U+0x00FB + 'udieresis', # C+0xFC # U+0x00FC + 'yacute', # C+0xFD # U+0x00FD + 'thorn', # C+0xFE # U+0x00FE + 'ydieresis', # C+0xFF # U+0x00FF + ], # DEF. ENCODING GLYPH TABLE + 'wx' => { + 'A' => '600', # U=0041 + 'a' => '600', # U=0061 + 'Aacute' => '600', # U=00C1 + 'aacute' => '600', # U=00E1 + 'Abreve' => '600', # U=0102 + 'abreve' => '600', # U=0103 + 'Acircumflex' => '600', # U=00C2 + 'acircumflex' => '600', # U=00E2 + 'acute' => '600', # U=00B4 + 'Adieresis' => '600', # U=00C4 + 'adieresis' => '600', # U=00E4 + 'AE' => '600', # U=00C6 + 'ae' => '600', # U=00E6 + 'Agrave' => '600', # U=00C0 + 'agrave' => '600', # U=00E0 + 'Amacron' => '600', # U=0100 + 'amacron' => '600', # U=0101 + 'ampersand' => '600', # U=0026 + 'Aogonek' => '600', # U=0104 + 'aogonek' => '600', # U=0105 + 'Aring' => '600', # U=00C5 + 'aring' => '600', # U=00E5 + 'asciicircum' => '600', # U=005E + 'asciitilde' => '600', # U=007E + 'asterisk' => '600', # U=002A + 'at' => '600', # U=0040 + 'Atilde' => '600', # U=00C3 + 'atilde' => '600', # U=00E3 + 'B' => '600', # U=0042 + 'b' => '600', # U=0062 + 'backslash' => '600', # U=005C + 'bar' => '600', # U=007C + 'braceleft' => '600', # U=007B + 'braceright' => '600', # U=007D + 'bracketleft' => '600', # U=005B + 'bracketright' => '600', # U=005D + 'breve' => '600', # U=02D8 + 'brokenbar' => '600', # U=00A6 + 'bullet' => '600', # U=2022 + 'C' => '600', # U=0043 + 'c' => '600', # U=0063 + 'Cacute' => '600', # U=0106 + 'cacute' => '600', # U=0107 + 'caron' => '600', # U=02C7 + 'Ccaron' => '600', # U=010C + 'ccaron' => '600', # U=010D + 'Ccedilla' => '600', # U=00C7 + 'ccedilla' => '600', # U=00E7 + 'cedilla' => '600', # U=00B8 + 'cent' => '600', # U=00A2 + 'circumflex' => '600', # U=02C6 + 'colon' => '600', # U=003A + 'comma' => '600', # U=002C + 'commaaccent' => '600', # U=F6C3 + 'copyright' => '600', # U=00A9 + 'currency' => '600', # U=00A4 + 'D' => '600', # U=0044 + 'd' => '600', # U=0064 + 'dagger' => '600', # U=2020 + 'daggerdbl' => '600', # U=2021 + 'Dcaron' => '600', # U=010E + 'dcaron' => '600', # U=010F + 'Dcroat' => '600', # U=0110 + 'dcroat' => '600', # U=0111 + 'degree' => '600', # U=00B0 + 'Delta' => '600', # U=0394 + 'dieresis' => '600', # U=00A8 + 'divide' => '600', # U=00F7 + 'dollar' => '600', # U=0024 + 'dotaccent' => '600', # U=02D9 + 'dotlessi' => '600', # U=0131 + 'E' => '600', # U=0045 + 'e' => '600', # U=0065 + 'Eacute' => '600', # U=00C9 + 'eacute' => '600', # U=00E9 + 'Ecaron' => '600', # U=011A + 'ecaron' => '600', # U=011B + 'Ecircumflex' => '600', # U=00CA + 'ecircumflex' => '600', # U=00EA + 'Edieresis' => '600', # U=00CB + 'edieresis' => '600', # U=00EB + 'Edotaccent' => '600', # U=0116 + 'edotaccent' => '600', # U=0117 + 'Egrave' => '600', # U=00C8 + 'egrave' => '600', # U=00E8 + 'eight' => '600', # U=0038 + 'ellipsis' => '600', # U=2026 + 'Emacron' => '600', # U=0112 + 'emacron' => '600', # U=0113 + 'emdash' => '600', # U=2014 + 'endash' => '600', # U=2013 + 'Eogonek' => '600', # U=0118 + 'eogonek' => '600', # U=0119 + 'equal' => '600', # U=003D + 'Eth' => '600', # U=00D0 + 'eth' => '600', # U=00F0 + 'Euro' => '600', # U=20AC + 'exclam' => '600', # U=0021 + 'exclamdown' => '600', # U=00A1 + 'F' => '600', # U=0046 + 'f' => '600', # U=0066 + 'fi' => '600', # U=FB01 + 'five' => '600', # U=0035 + 'fl' => '600', # U=FB02 + 'florin' => '600', # U=0192 + 'four' => '600', # U=0034 + 'fraction' => '600', # U=2044 + 'G' => '600', # U=0047 + 'g' => '600', # U=0067 + 'Gbreve' => '600', # U=011E + 'gbreve' => '600', # U=011F + 'Gcommaaccent' => '600', # U=0122 + 'gcommaaccent' => '600', # U=0123 + 'germandbls' => '600', # U=00DF + 'grave' => '600', # U=0060 + 'greater' => '600', # U=003E + 'greaterequal' => '600', # U=2265 + 'guillemotleft' => '600', # U=00AB + 'guillemotright' => '600', # U=00BB + 'guilsinglleft' => '600', # U=2039 + 'guilsinglright' => '600', # U=203A + 'H' => '600', # U=0048 + 'h' => '600', # U=0068 + 'hungarumlaut' => '600', # U=02DD + 'hyphen' => '600', # U=002D + 'I' => '600', # U=0049 + 'i' => '600', # U=0069 + 'Iacute' => '600', # U=00CD + 'iacute' => '600', # U=00ED + 'Icircumflex' => '600', # U=00CE + 'icircumflex' => '600', # U=00EE + 'Idieresis' => '600', # U=00CF + 'idieresis' => '600', # U=00EF + 'Idotaccent' => '600', # U=0130 + 'Igrave' => '600', # U=00CC + 'igrave' => '600', # U=00EC + 'Imacron' => '600', # U=012A + 'imacron' => '600', # U=012B + 'Iogonek' => '600', # U=012E + 'iogonek' => '600', # U=012F + 'J' => '600', # U=004A + 'j' => '600', # U=006A + 'K' => '600', # U=004B + 'k' => '600', # U=006B + 'Kcommaaccent' => '600', # U=0136 + 'kcommaaccent' => '600', # U=0137 + 'L' => '600', # U=004C + 'l' => '600', # U=006C + 'Lacute' => '600', # U=0139 + 'lacute' => '600', # U=013A + 'Lcaron' => '600', # U=013D + 'lcaron' => '600', # U=013E + 'Lcommaaccent' => '600', # U=013B + 'lcommaaccent' => '600', # U=013C + 'less' => '600', # U=003C + 'lessequal' => '600', # U=2264 + 'logicalnot' => '600', # U=00AC + 'lozenge' => '600', # U=25CA + 'Lslash' => '600', # U=0141 + 'lslash' => '600', # U=0142 + 'M' => '600', # U=004D + 'm' => '600', # U=006D + 'macron' => '600', # U=00AF + 'minus' => '600', # U=2212 + 'mu' => '600', # U=00B5 + 'multiply' => '600', # U=00D7 + 'N' => '600', # U=004E + 'n' => '600', # U=006E + 'Nacute' => '600', # U=0143 + 'nacute' => '600', # U=0144 + 'Ncaron' => '600', # U=0147 + 'ncaron' => '600', # U=0148 + 'Ncommaaccent' => '600', # U=0145 + 'ncommaaccent' => '600', # U=0146 + 'nine' => '600', # U=0039 + 'notequal' => '600', # U=2260 + 'Ntilde' => '600', # U=00D1 + 'ntilde' => '600', # U=00F1 + 'numbersign' => '600', # U=0023 + 'O' => '600', # U=004F + 'o' => '600', # U=006F + 'Oacute' => '600', # U=00D3 + 'oacute' => '600', # U=00F3 + 'Ocircumflex' => '600', # U=00D4 + 'ocircumflex' => '600', # U=00F4 + 'Odieresis' => '600', # U=00D6 + 'odieresis' => '600', # U=00F6 + 'OE' => '600', # U=0152 + 'oe' => '600', # U=0153 + 'ogonek' => '600', # U=02DB + 'Ograve' => '600', # U=00D2 + 'ograve' => '600', # U=00F2 + 'Ohungarumlaut' => '600', # U=0150 + 'ohungarumlaut' => '600', # U=0151 + 'Omacron' => '600', # U=014C + 'omacron' => '600', # U=014D + 'one' => '600', # U=0031 + 'onehalf' => '600', # U=00BD + 'onequarter' => '600', # U=00BC + 'onesuperior' => '600', # U=00B9 + 'ordfeminine' => '600', # U=00AA + 'ordmasculine' => '600', # U=00BA + 'Oslash' => '600', # U=00D8 + 'oslash' => '600', # U=00F8 + 'Otilde' => '600', # U=00D5 + 'otilde' => '600', # U=00F5 + 'P' => '600', # U=0050 + 'p' => '600', # U=0070 + 'paragraph' => '600', # U=00B6 + 'parenleft' => '600', # U=0028 + 'parenright' => '600', # U=0029 + 'partialdiff' => '600', # U=2202 + 'percent' => '600', # U=0025 + 'period' => '600', # U=002E + 'periodcentered' => '600', # U=00B7 + 'perthousand' => '600', # U=2030 + 'plus' => '600', # U=002B + 'plusminus' => '600', # U=00B1 + 'Q' => '600', # U=0051 + 'q' => '600', # U=0071 + 'question' => '600', # U=003F + 'questiondown' => '600', # U=00BF + 'quotedbl' => '600', # U=0022 + 'quotedblbase' => '600', # U=201E + 'quotedblleft' => '600', # U=201C + 'quotedblright' => '600', # U=201D + 'quoteleft' => '600', # U=2018 + 'quoteright' => '600', # U=2019 + 'quotesinglbase' => '600', # U=201A + 'quotesingle' => '600', # U=0027 + 'R' => '600', # U=0052 + 'r' => '600', # U=0072 + 'Racute' => '600', # U=0154 + 'racute' => '600', # U=0155 + 'radical' => '600', # U=221A + 'Rcaron' => '600', # U=0158 + 'rcaron' => '600', # U=0159 + 'Rcommaaccent' => '600', # U=0156 + 'rcommaaccent' => '600', # U=0157 + 'registered' => '600', # U=00AE + 'ring' => '600', # U=02DA + 'S' => '600', # U=0053 + 's' => '600', # U=0073 + 'Sacute' => '600', # U=015A + 'sacute' => '600', # U=015B + 'Scaron' => '600', # U=0160 + 'scaron' => '600', # U=0161 + 'Scedilla' => '600', # U=015E + 'scedilla' => '600', # U=015F + 'Scommaaccent' => '600', # U=0218 + 'scommaaccent' => '600', # U=0219 + 'section' => '600', # U=00A7 + 'semicolon' => '600', # U=003B + 'seven' => '600', # U=0037 + 'six' => '600', # U=0036 + 'slash' => '600', # U=002F + 'space' => '600', # U=0020 + 'sterling' => '600', # U=00A3 + 'summation' => '600', # U=2211 + 'T' => '600', # U=0054 + 't' => '600', # U=0074 + 'Tcaron' => '600', # U=0164 + 'tcaron' => '600', # U=0165 + 'Tcommaaccent' => '600', # U=021A + 'tcommaaccent' => '600', # U=021B + 'Thorn' => '600', # U=00DE + 'thorn' => '600', # U=00FE + 'three' => '600', # U=0033 + 'threequarters' => '600', # U=00BE + 'threesuperior' => '600', # U=00B3 + 'tilde' => '600', # U=02DC + 'trademark' => '600', # U=2122 + 'two' => '600', # U=0032 + 'twosuperior' => '600', # U=00B2 + 'U' => '600', # U=0055 + 'u' => '600', # U=0075 + 'Uacute' => '600', # U=00DA + 'uacute' => '600', # U=00FA + 'Ucircumflex' => '600', # U=00DB + 'ucircumflex' => '600', # U=00FB + 'Udieresis' => '600', # U=00DC + 'udieresis' => '600', # U=00FC + 'Ugrave' => '600', # U=00D9 + 'ugrave' => '600', # U=00F9 + 'Uhungarumlaut' => '600', # U=0170 + 'uhungarumlaut' => '600', # U=0171 + 'Umacron' => '600', # U=016A + 'umacron' => '600', # U=016B + 'underscore' => '600', # U=005F + 'Uogonek' => '600', # U=0172 + 'uogonek' => '600', # U=0173 + 'Uring' => '600', # U=016E + 'uring' => '600', # U=016F + 'V' => '600', # U=0056 + 'v' => '600', # U=0076 + 'W' => '600', # U=0057 + 'w' => '600', # U=0077 + 'X' => '600', # U=0058 + 'x' => '600', # U=0078 + 'Y' => '600', # U=0059 + 'y' => '600', # U=0079 + 'Yacute' => '600', # U=00DD + 'yacute' => '600', # U=00FD + 'Ydieresis' => '600', # U=0178 + 'ydieresis' => '600', # U=00FF + 'yen' => '600', # U=00A5 + 'Z' => '600', # U=005A + 'z' => '600', # U=007A + 'Zacute' => '600', # U=0179 + 'zacute' => '600', # U=017A + 'Zcaron' => '600', # U=017D + 'zcaron' => '600', # U=017E + 'Zdotaccent' => '600', # U=017B + 'zdotaccent' => '600', # U=017C + 'zero' => '600', # U=0030 + }, + 'comps' => { + 'Abreve' => [ 'A', '0', '0', 'breve', '0', '130' ], # U=0102 + 'abreve' => [ 'A', '0', '0', 'breve', '0', '0' ], # U=0103 + 'Acaron' => [ 'A', '0', '0', 'caron', '0', '130' ], # U=01CD + 'acaron' => [ 'A', '0', '0', 'caron', '0', '0' ], # U=01CE + 'Amacron' => [ 'A', '0', '0', 'macron', '0', '130' ], # U=0100 + 'amacron' => [ 'A', '0', '0', 'macron', '0', '0' ], # U=0101 + 'Aogonek' => [ 'A', '0', '0', 'ogonek', '0', '0' ], # U=0104 + 'aogonek' => [ 'A', '0', '0', 'ogonek', '0', '0' ], # U=0105 + 'Bdotaccent' => [ 'B', '0', '0', 'dotaccent', '0', '130' ], # U=1E02 + 'bdotaccent' => [ 'B', '0', '0', 'dotaccent', '0', '0' ], # U=1E03 + 'Cacute' => [ 'C', '0', '0', 'acute', '0', '130' ], # U=0106 + 'cacute' => [ 'C', '0', '0', 'acute', '0', '0' ], # U=0107 + 'Ccaron' => [ 'C', '0', '0', 'caron', '0', '130' ], # U=010C + 'ccaron' => [ 'C', '0', '0', 'caron', '0', '0' ], # U=010D + 'Ccircumflex' => [ 'C', '0', '0', 'circumflex', '0', '130' ], # U=0108 + 'ccircumflex' => [ 'C', '0', '0', 'circumflex', '0', '0' ], # U=0109 + 'Cdotaccent' => [ 'C', '0', '0', 'dotaccent', '0', '130' ], # U=010A + 'cdotaccent' => [ 'C', '0', '0', 'dotaccent', '0', '0' ], # U=010B + 'Dcaron' => [ 'D', '0', '0', 'caron', '0', '130' ], # U=010E + 'dcaron' => [ 'D', '0', '0', 'caron', '0', '0' ], # U=010F + 'Dcedilla' => [ 'D', '0', '0', 'cedilla', '0', '130' ], # U=1E10 + 'dcedilla' => [ 'D', '0', '0', 'cedilla', '0', '0' ], # U=1E11 + 'Ddotaccent' => [ 'D', '0', '0', 'dotaccent', '0', '130' ], # U=1E0A + 'ddotaccent' => [ 'D', '0', '0', 'dotaccent', '0', '0' ], # U=1E0B + 'Ebreve' => [ 'E', '0', '0', 'breve', '0', '130' ], # U=0114 + 'ebreve' => [ 'E', '0', '0', 'breve', '0', '0' ], # U=0115 + 'Ecaron' => [ 'E', '0', '0', 'caron', '0', '130' ], # U=011A + 'ecaron' => [ 'E', '0', '0', 'caron', '0', '0' ], # U=011B + 'Edotaccent' => [ 'E', '0', '0', 'dotaccent', '0', '130' ], # U=0116 + 'edotaccent' => [ 'E', '0', '0', 'dotaccent', '0', '0' ], # U=0117 + 'Emacron' => [ 'E', '0', '0', 'macron', '0', '130' ], # U=0112 + 'emacron' => [ 'E', '0', '0', 'macron', '0', '0' ], # U=0113 + 'Eogonek' => [ 'E', '0', '0', 'ogonek', '0', '0' ], # U=0118 + 'eogonek' => [ 'E', '0', '0', 'ogonek', '0', '0' ], # U=0119 + 'Etilde' => [ 'E', '0', '0', 'tilde', '0', '130' ], # U=1EBC + 'etilde' => [ 'E', '0', '0', 'tilde', '0', '0' ], # U=1EBD + 'Fdotaccent' => [ 'F', '0', '0', 'dotaccent', '0', '130' ], # U=1E1E + 'fdotaccent' => [ 'F', '0', '0', 'dotaccent', '0', '0' ], # U=1E1F + 'Gacute' => [ 'G', '0', '0', 'acute', '0', '130' ], # U=01F4 + 'gacute' => [ 'G', '0', '0', 'acute', '0', '0' ], # U=01F5 + 'Gbreve' => [ 'G', '0', '0', 'breve', '0', '130' ], # U=011E + 'gbreve' => [ 'G', '0', '0', 'breve', '0', '0' ], # U=011F + 'Gcaron' => [ 'G', '0', '0', 'caron', '0', '136' ], # U=01E6 + 'gcaron' => [ 'g', '0', '0', 'caron', '-30', '0' ], # U=01E7 + 'Gcedilla' => [ 'G', '0', '0', 'cedilla', '0', '130' ], # U=0122 + 'gcedilla' => [ 'G', '0', '0', 'cedilla', '0', '0' ], # U=0123 + 'Gcircumflex' => [ 'G', '0', '0', 'circumflex', '0', '130' ], # U=011C + 'gcircumflex' => [ 'G', '0', '0', 'circumflex', '0', '0' ], # U=011D + 'Gdotaccent' => [ 'G', '0', '0', 'dotaccent', '0', '130' ], # U=0120 + 'gdotaccent' => [ 'G', '0', '0', 'dotaccent', '0', '0' ], # U=0121 + 'Gmacron' => [ 'G', '0', '0', 'macron', '0', '130' ], # U=1E20 + 'gmacron' => [ 'G', '0', '0', 'macron', '0', '0' ], # U=1E21 + 'Hcedilla' => [ 'H', '0', '0', 'cedilla', '0', '130' ], # U=1E28 + 'hcedilla' => [ 'H', '0', '0', 'cedilla', '0', '0' ], # U=1E29 + 'Hcircumflex' => [ 'H', '0', '0', 'circumflex', '0', '130' ], # U=0124 + 'hcircumflex' => [ 'H', '0', '0', 'circumflex', '0', '0' ], # U=0125 + 'Hdieresis' => [ 'H', '0', '0', 'dieresis', '0', '130' ], # U=1E26 + 'hdieresis' => [ 'H', '0', '0', 'dieresis', '0', '0' ], # U=1E27 + 'Hdotaccent' => [ 'H', '0', '0', 'dotaccent', '0', '130' ], # U=1E22 + 'hdotaccent' => [ 'H', '0', '0', 'dotaccent', '0', '0' ], # U=1E23 + 'Ibreve' => [ 'I', '0', '0', 'breve', '0', '130' ], # U=012C + 'ibreve' => [ 'I', '0', '0', 'breve', '0', '0' ], # U=012D + 'Icaron' => [ 'I', '0', '0', 'caron', '0', '130' ], # U=01CF + 'icaron' => [ 'I', '0', '0', 'caron', '0', '0' ], # U=01D0 + 'Idotaccent' => [ 'I', '0', '0', 'dotaccent', '0', '130' ], # U=0130 + 'Imacron' => [ 'I', '0', '0', 'macron', '0', '130' ], # U=012A + 'imacron' => [ 'I', '0', '0', 'macron', '0', '0' ], # U=012B + 'Iogonek' => [ 'I', '0', '0', 'ogonek', '0', '0' ], # U=012E + 'iogonek' => [ 'I', '0', '0', 'ogonek', '0', '0' ], # U=012F + 'Itilde' => [ 'I', '0', '0', 'tilde', '0', '130' ], # U=0128 + 'itilde' => [ 'I', '0', '0', 'tilde', '0', '0' ], # U=0129 + 'Jcircumflex' => [ 'J', '0', '0', 'circumflex', '0', '130' ], # U=0134 + 'jcircumflex' => [ 'J', '0', '0', 'circumflex', '0', '0' ], # U=0135 + 'Kacute' => [ 'K', '0', '0', 'acute', '0', '130' ], # U=1E30 + 'kacute' => [ 'K', '0', '0', 'acute', '0', '0' ], # U=1E31 + 'Kcaron' => [ 'K', '0', '0', 'caron', '0', '130' ], # U=01E8 + 'kcaron' => [ 'K', '0', '0', 'caron', '0', '0' ], # U=01E9 + 'Kcedilla' => [ 'K', '0', '0', 'cedilla', '0', '130' ], # U=0136 + 'kcedilla' => [ 'K', '0', '0', 'cedilla', '0', '0' ], # U=0137 + 'Lacute' => [ 'L', '0', '0', 'acute', '0', '130' ], # U=0139 + 'lacute' => [ 'L', '0', '0', 'acute', '0', '0' ], # U=013A + 'Lcaron' => [ 'L', '0', '0', 'caron', '0', '130' ], # U=013D + 'lcaron' => [ 'L', '0', '0', 'caron', '0', '0' ], # U=013E + 'Lcedilla' => [ 'L', '0', '0', 'cedilla', '0', '130' ], # U=013B + 'lcedilla' => [ 'L', '0', '0', 'cedilla', '0', '0' ], # U=013C + 'Ldotaccent' => [ 'L', '0', '0', 'dotaccent', '0', '130' ], # U=013F + 'ldotaccent' => [ 'L', '0', '0', 'dotaccent', '0', '0' ], # U=0140 + 'Macute' => [ 'M', '0', '0', 'acute', '0', '130' ], # U=1E3E + 'macute' => [ 'M', '0', '0', 'acute', '0', '0' ], # U=1E3F + 'Mdotaccent' => [ 'M', '0', '0', 'dotaccent', '0', '130' ], # U=1E40 + 'mdotaccent' => [ 'M', '0', '0', 'dotaccent', '0', '0' ], # U=1E41 + 'Nacute' => [ 'N', '0', '0', 'acute', '0', '130' ], # U=0143 + 'nacute' => [ 'N', '0', '0', 'acute', '0', '0' ], # U=0144 + 'Ncaron' => [ 'N', '0', '0', 'caron', '0', '130' ], # U=0147 + 'ncaron' => [ 'N', '0', '0', 'caron', '0', '0' ], # U=0148 + 'Ncedilla' => [ 'N', '0', '0', 'cedilla', '0', '130' ], # U=0145 + 'ncedilla' => [ 'N', '0', '0', 'cedilla', '0', '0' ], # U=0146 + 'Ndotaccent' => [ 'N', '0', '0', 'dotaccent', '0', '130' ], # U=1E44 + 'ndotaccent' => [ 'N', '0', '0', 'dotaccent', '0', '0' ], # U=1E45 + 'Obreve' => [ 'O', '0', '0', 'breve', '0', '130' ], # U=014E + 'obreve' => [ 'O', '0', '0', 'breve', '0', '0' ], # U=014F + 'Ocaron' => [ 'O', '0', '0', 'caron', '0', '130' ], # U=01D1 + 'ocaron' => [ 'O', '0', '0', 'caron', '0', '0' ], # U=01D2 + 'Ohungarumlaut' => [ 'O', '0', '0', 'hungarumlaut', '0', '130' ], # U=0150 + 'ohungarumlaut' => [ 'O', '0', '0', 'hungarumlaut', '0', '0' ], # U=0151 + 'Omacron' => [ 'O', '0', '0', 'macron', '0', '130' ], # U=014C + 'omacron' => [ 'O', '0', '0', 'macron', '0', '0' ], # U=014D + 'Oogonek' => [ 'O', '0', '0', 'ogonek', '0', '0' ], # U=01EA + 'oogonek' => [ 'O', '0', '0', 'ogonek', '0', '0' ], # U=01EB + 'Pacute' => [ 'P', '0', '0', 'acute', '0', '130' ], # U=1E54 + 'pacute' => [ 'P', '0', '0', 'acute', '0', '0' ], # U=1E55 + 'Pdotaccent' => [ 'P', '0', '0', 'dotaccent', '0', '130' ], # U=1E56 + 'pdotaccent' => [ 'P', '0', '0', 'dotaccent', '0', '0' ], # U=1E57 + 'Racute' => [ 'R', '0', '0', 'acute', '0', '130' ], # U=0154 + 'racute' => [ 'R', '0', '0', 'acute', '0', '0' ], # U=0155 + 'Rcaron' => [ 'R', '0', '0', 'caron', '0', '130' ], # U=0158 + 'rcaron' => [ 'R', '0', '0', 'caron', '0', '0' ], # U=0159 + 'Rcedilla' => [ 'R', '0', '0', 'cedilla', '0', '130' ], # U=0156 + 'rcedilla' => [ 'R', '0', '0', 'cedilla', '0', '0' ], # U=0157 + 'Rdotaccent' => [ 'R', '0', '0', 'dotaccent', '0', '130' ], # U=1E58 + 'rdotaccent' => [ 'R', '0', '0', 'dotaccent', '0', '0' ], # U=1E59 + 'Sacute' => [ 'S', '0', '0', 'acute', '0', '130' ], # U=015A + 'sacute' => [ 'S', '0', '0', 'acute', '0', '0' ], # U=015B + 'Scaron' => [ 'S', '0', '0', 'caron', '30', '136' ], # U=0160 + 'scaron' => [ 's', '0', '0', 'caron', '0', '0' ], # U=0161 + 'Scedilla' => [ 'S', '0', '0', 'cedilla', '0', '130' ], # U=015E + 'scedilla' => [ 'S', '0', '0', 'cedilla', '0', '0' ], # U=015F + 'Scircumflex' => [ 'S', '0', '0', 'circumflex', '0', '130' ], # U=015C + 'scircumflex' => [ 'S', '0', '0', 'circumflex', '0', '0' ], # U=015D + 'Sdotaccent' => [ 'S', '0', '0', 'dotaccent', '0', '130' ], # U=1E60 + 'sdotaccent' => [ 'S', '0', '0', 'dotaccent', '0', '0' ], # U=1E61 + 'Tcaron' => [ 'T', '0', '0', 'caron', '0', '130' ], # U=0164 + 'tcaron' => [ 'T', '0', '0', 'caron', '0', '0' ], # U=0165 + 'Tcedilla' => [ 'T', '0', '0', 'cedilla', '0', '130' ], # U=0162 + 'tcedilla' => [ 'T', '0', '0', 'cedilla', '0', '0' ], # U=0163 + 'Tdotaccent' => [ 'T', '0', '0', 'dotaccent', '0', '130' ], # U=1E6A + 'tdotaccent' => [ 'T', '0', '0', 'dotaccent', '0', '0' ], # U=1E6B + 'Ubreve' => [ 'U', '0', '0', 'breve', '0', '130' ], # U=016C + 'ubreve' => [ 'U', '0', '0', 'breve', '0', '0' ], # U=016D + 'Ucaron' => [ 'U', '0', '0', 'caron', '0', '130' ], # U=01D3 + 'ucaron' => [ 'U', '0', '0', 'caron', '0', '0' ], # U=01D4 + 'Uhungarumlaut' => [ 'U', '0', '0', 'hungarumlaut', '0', '130' ], # U=0170 + 'uhungarumlaut' => [ 'U', '0', '0', 'hungarumlaut', '0', '0' ], # U=0171 + 'Umacron' => [ 'U', '0', '0', 'macron', '0', '130' ], # U=016A + 'umacron' => [ 'U', '0', '0', 'macron', '0', '0' ], # U=016B + 'Uogonek' => [ 'U', '0', '0', 'ogonek', '0', '0' ], # U=0172 + 'uogonek' => [ 'U', '0', '0', 'ogonek', '0', '0' ], # U=0173 + 'Uring' => [ 'U', '0', '0', 'ring', '0', '130' ], # U=016E + 'uring' => [ 'U', '0', '0', 'ring', '0', '0' ], # U=016F + 'Utilde' => [ 'U', '0', '0', 'tilde', '0', '130' ], # U=0168 + 'utilde' => [ 'U', '0', '0', 'tilde', '0', '0' ], # U=0169 + 'Vtilde' => [ 'V', '0', '0', 'tilde', '0', '130' ], # U=1E7C + 'vtilde' => [ 'V', '0', '0', 'tilde', '0', '0' ], # U=1E7D + 'Wacute' => [ 'W', '0', '0', 'acute', '0', '130' ], # U=1E82 + 'wacute' => [ 'W', '0', '0', 'acute', '0', '0' ], # U=1E83 + 'Wcircumflex' => [ 'W', '0', '0', 'circumflex', '0', '130' ], # U=0174 + 'wcircumflex' => [ 'W', '0', '0', 'circumflex', '0', '0' ], # U=0175 + 'Wdieresis' => [ 'W', '0', '0', 'dieresis', '0', '130' ], # U=1E84 + 'wdieresis' => [ 'W', '0', '0', 'dieresis', '0', '0' ], # U=1E85 + 'Wdotaccent' => [ 'W', '0', '0', 'dotaccent', '0', '130' ], # U=1E86 + 'wdotaccent' => [ 'W', '0', '0', 'dotaccent', '0', '0' ], # U=1E87 + 'Wgrave' => [ 'W', '0', '0', 'grave', '0', '130' ], # U=1E80 + 'wgrave' => [ 'W', '0', '0', 'grave', '0', '0' ], # U=1E81 + 'Xdieresis' => [ 'X', '0', '0', 'dieresis', '0', '130' ], # U=1E8C + 'xdieresis' => [ 'X', '0', '0', 'dieresis', '0', '0' ], # U=1E8D + 'Xdotaccent' => [ 'X', '0', '0', 'dotaccent', '0', '130' ], # U=1E8A + 'xdotaccent' => [ 'X', '0', '0', 'dotaccent', '0', '0' ], # U=1E8B + 'Ycircumflex' => [ 'Y', '0', '0', 'circumflex', '0', '130' ], # U=0176 + 'ycircumflex' => [ 'Y', '0', '0', 'circumflex', '0', '0' ], # U=0177 + 'Ydieresis' => [ 'Y', '0', '0', 'dieresis', '0', '136' ], # U=0178 + 'Ydotaccent' => [ 'Y', '0', '0', 'dotaccent', '0', '130' ], # U=1E8E + 'ydotaccent' => [ 'Y', '0', '0', 'dotaccent', '0', '0' ], # U=1E8F + 'Ygrave' => [ 'Y', '0', '0', 'grave', '0', '130' ], # U=1EF2 + 'ygrave' => [ 'Y', '0', '0', 'grave', '0', '0' ], # U=1EF3 + 'Ytilde' => [ 'Y', '0', '0', 'tilde', '0', '130' ], # U=1EF8 + 'ytilde' => [ 'Y', '0', '0', 'tilde', '0', '0' ], # U=1EF9 + 'Zacute' => [ 'Z', '0', '0', 'acute', '0', '130' ], # U=0179 + 'zacute' => [ 'Z', '0', '0', 'acute', '0', '0' ], # U=017A + 'Zcaron' => [ 'Z', '0', '0', 'caron', '0', '136' ], # U=017D + 'zcaron' => [ 'z', '0', '0', 'caron', '10', '0' ], # U=017E + 'Zcircumflex' => [ 'Z', '0', '0', 'circumflex', '0', '130' ], # U=1E90 + 'zcircumflex' => [ 'Z', '0', '0', 'circumflex', '0', '0' ], # U=1E91 + 'Zdotaccent' => [ 'Z', '0', '0', 'dotaccent', '0', '130' ], # U=017B + 'zdotaccent' => [ 'Z', '0', '0', 'dotaccent', '0', '0' ], # U=017C + }, +} }; + +1; diff --git a/lib/PDF/API2/Resource/Font/CoreFont/courierbold.pm b/lib/PDF/API2/Resource/Font/CoreFont/courierbold.pm new file mode 100644 index 0000000..d31ed9a --- /dev/null +++ b/lib/PDF/API2/Resource/Font/CoreFont/courierbold.pm @@ -0,0 +1,520 @@ +#line 1 "PDF/API2/Resource/Font/CoreFont/courierbold.pm" +#line 1 "PDF/API2/Resource/Font/CoreFont/courierbold.pm" +package PDF::API2::Resource::Font::CoreFont::courierbold; + +use strict; +use warnings; + +our $VERSION = '2.033'; # VERSION + +sub data { return { + 'fontname' => 'Courier-Bold', + 'type' => 'Type1', + 'apiname' => 'CoBo', + 'ascender' => '629', + 'capheight' => '562', + 'descender' => '-157', + 'iscore' => '1', + 'isfixedpitch' => '1', + 'italicangle' => '0', + 'missingwidth' => '600', + 'stdhw' => '84', + 'stdvw' => '106', + 'underlineposition' => '-100', + 'underlinethickness' => '50', + 'xheight' => '439', + 'firstchar' => '32', + 'lastchar' => '255', + 'char' => [ # DEF. ENCODING GLYPH TABLE + '.notdef', # C+0x00 # U+0x0000 + '.notdef', # C+0x01 # U+0x0000 + '.notdef', # C+0x02 # U+0x0000 + '.notdef', # C+0x03 # U+0x0000 + '.notdef', # C+0x04 # U+0x0000 + '.notdef', # C+0x05 # U+0x0000 + '.notdef', # C+0x06 # U+0x0000 + '.notdef', # C+0x07 # U+0x0000 + '.notdef', # C+0x08 # U+0x0000 + '.notdef', # C+0x09 # U+0x0000 + '.notdef', # C+0x0A # U+0x0000 + '.notdef', # C+0x0B # U+0x0000 + '.notdef', # C+0x0C # U+0x0000 + '.notdef', # C+0x0D # U+0x0000 + '.notdef', # C+0x0E # U+0x0000 + '.notdef', # C+0x0F # U+0x0000 + '.notdef', # C+0x10 # U+0x0000 + '.notdef', # C+0x11 # U+0x0000 + '.notdef', # C+0x12 # U+0x0000 + '.notdef', # C+0x13 # U+0x0000 + '.notdef', # C+0x14 # U+0x0000 + '.notdef', # C+0x15 # U+0x0000 + '.notdef', # C+0x16 # U+0x0000 + '.notdef', # C+0x17 # U+0x0000 + '.notdef', # C+0x18 # U+0x0000 + '.notdef', # C+0x19 # U+0x0000 + '.notdef', # C+0x1A # U+0x0000 + '.notdef', # C+0x1B # U+0x0000 + '.notdef', # C+0x1C # U+0x0000 + '.notdef', # C+0x1D # U+0x0000 + '.notdef', # C+0x1E # U+0x0000 + '.notdef', # C+0x1F # U+0x0000 + 'space', # C+0x20 # U+0x0020 + 'exclam', # C+0x21 # U+0x0021 + 'quotedbl', # C+0x22 # U+0x0022 + 'numbersign', # C+0x23 # U+0x0023 + 'dollar', # C+0x24 # U+0x0024 + 'percent', # C+0x25 # U+0x0025 + 'ampersand', # C+0x26 # U+0x0026 + 'quotesingle', # C+0x27 # U+0x0027 + 'parenleft', # C+0x28 # U+0x0028 + 'parenright', # C+0x29 # U+0x0029 + 'asterisk', # C+0x2A # U+0x002A + 'plus', # C+0x2B # U+0x002B + 'comma', # C+0x2C # U+0x002C + 'hyphen', # C+0x2D # U+0x002D + 'period', # C+0x2E # U+0x002E + 'slash', # C+0x2F # U+0x002F + 'zero', # C+0x30 # U+0x0030 + 'one', # C+0x31 # U+0x0031 + 'two', # C+0x32 # U+0x0032 + 'three', # C+0x33 # U+0x0033 + 'four', # C+0x34 # U+0x0034 + 'five', # C+0x35 # U+0x0035 + 'six', # C+0x36 # U+0x0036 + 'seven', # C+0x37 # U+0x0037 + 'eight', # C+0x38 # U+0x0038 + 'nine', # C+0x39 # U+0x0039 + 'colon', # C+0x3A # U+0x003A + 'semicolon', # C+0x3B # U+0x003B + 'less', # C+0x3C # U+0x003C + 'equal', # C+0x3D # U+0x003D + 'greater', # C+0x3E # U+0x003E + 'question', # C+0x3F # U+0x003F + 'at', # C+0x40 # U+0x0040 + 'A', # C+0x41 # U+0x0041 + 'B', # C+0x42 # U+0x0042 + 'C', # C+0x43 # U+0x0043 + 'D', # C+0x44 # U+0x0044 + 'E', # C+0x45 # U+0x0045 + 'F', # C+0x46 # U+0x0046 + 'G', # C+0x47 # U+0x0047 + 'H', # C+0x48 # U+0x0048 + 'I', # C+0x49 # U+0x0049 + 'J', # C+0x4A # U+0x004A + 'K', # C+0x4B # U+0x004B + 'L', # C+0x4C # U+0x004C + 'M', # C+0x4D # U+0x004D + 'N', # C+0x4E # U+0x004E + 'O', # C+0x4F # U+0x004F + 'P', # C+0x50 # U+0x0050 + 'Q', # C+0x51 # U+0x0051 + 'R', # C+0x52 # U+0x0052 + 'S', # C+0x53 # U+0x0053 + 'T', # C+0x54 # U+0x0054 + 'U', # C+0x55 # U+0x0055 + 'V', # C+0x56 # U+0x0056 + 'W', # C+0x57 # U+0x0057 + 'X', # C+0x58 # U+0x0058 + 'Y', # C+0x59 # U+0x0059 + 'Z', # C+0x5A # U+0x005A + 'bracketleft', # C+0x5B # U+0x005B + 'backslash', # C+0x5C # U+0x005C + 'bracketright', # C+0x5D # U+0x005D + 'asciicircum', # C+0x5E # U+0x005E + 'underscore', # C+0x5F # U+0x005F + 'grave', # C+0x60 # U+0x0060 + 'a', # C+0x61 # U+0x0061 + 'b', # C+0x62 # U+0x0062 + 'c', # C+0x63 # U+0x0063 + 'd', # C+0x64 # U+0x0064 + 'e', # C+0x65 # U+0x0065 + 'f', # C+0x66 # U+0x0066 + 'g', # C+0x67 # U+0x0067 + 'h', # C+0x68 # U+0x0068 + 'i', # C+0x69 # U+0x0069 + 'j', # C+0x6A # U+0x006A + 'k', # C+0x6B # U+0x006B + 'l', # C+0x6C # U+0x006C + 'm', # C+0x6D # U+0x006D + 'n', # C+0x6E # U+0x006E + 'o', # C+0x6F # U+0x006F + 'p', # C+0x70 # U+0x0070 + 'q', # C+0x71 # U+0x0071 + 'r', # C+0x72 # U+0x0072 + 's', # C+0x73 # U+0x0073 + 't', # C+0x74 # U+0x0074 + 'u', # C+0x75 # U+0x0075 + 'v', # C+0x76 # U+0x0076 + 'w', # C+0x77 # U+0x0077 + 'x', # C+0x78 # U+0x0078 + 'y', # C+0x79 # U+0x0079 + 'z', # C+0x7A # U+0x007A + 'braceleft', # C+0x7B # U+0x007B + 'bar', # C+0x7C # U+0x007C + 'braceright', # C+0x7D # U+0x007D + 'asciitilde', # C+0x7E # U+0x007E + 'bullet', # C+0x7F # U+0x2022 + 'Euro', # C+0x80 # U+0x20AC + 'bullet', # C+0x81 # U+0x2022 + 'quotesinglbase', # C+0x82 # U+0x201A + 'florin', # C+0x83 # U+0x0192 + 'quotedblbase', # C+0x84 # U+0x201E + 'ellipsis', # C+0x85 # U+0x2026 + 'dagger', # C+0x86 # U+0x2020 + 'daggerdbl', # C+0x87 # U+0x2021 + 'circumflex', # C+0x88 # U+0x02C6 + 'perthousand', # C+0x89 # U+0x2030 + 'Scaron', # C+0x8A # U+0x0160 + 'guilsinglleft', # C+0x8B # U+0x2039 + 'OE', # C+0x8C # U+0x0152 + 'bullet', # C+0x8D # U+0x2022 + 'Zcaron', # C+0x8E # U+0x017D + 'bullet', # C+0x8F # U+0x2022 + 'bullet', # C+0x90 # U+0x2022 + 'quoteleft', # C+0x91 # U+0x2018 + 'quoteright', # C+0x92 # U+0x2019 + 'quotedblleft', # C+0x93 # U+0x201C + 'quotedblright', # C+0x94 # U+0x201D + 'bullet', # C+0x95 # U+0x2022 + 'endash', # C+0x96 # U+0x2013 + 'emdash', # C+0x97 # U+0x2014 + 'tilde', # C+0x98 # U+0x02DC + 'trademark', # C+0x99 # U+0x2122 + 'scaron', # C+0x9A # U+0x0161 + 'guilsinglright', # C+0x9B # U+0x203A + 'oe', # C+0x9C # U+0x0153 + 'bullet', # C+0x9D # U+0x2022 + 'zcaron', # C+0x9E # U+0x017E + 'Ydieresis', # C+0x9F # U+0x0178 + 'space', # C+0xA0 # U+0x0020 + 'exclamdown', # C+0xA1 # U+0x00A1 + 'cent', # C+0xA2 # U+0x00A2 + 'sterling', # C+0xA3 # U+0x00A3 + 'currency', # C+0xA4 # U+0x00A4 + 'yen', # C+0xA5 # U+0x00A5 + 'brokenbar', # C+0xA6 # U+0x00A6 + 'section', # C+0xA7 # U+0x00A7 + 'dieresis', # C+0xA8 # U+0x00A8 + 'copyright', # C+0xA9 # U+0x00A9 + 'ordfeminine', # C+0xAA # U+0x00AA + 'guillemotleft', # C+0xAB # U+0x00AB + 'logicalnot', # C+0xAC # U+0x00AC + 'hyphen', # C+0xAD # U+0x002D + 'registered', # C+0xAE # U+0x00AE + 'macron', # C+0xAF # U+0x00AF + 'degree', # C+0xB0 # U+0x00B0 + 'plusminus', # C+0xB1 # U+0x00B1 + 'twosuperior', # C+0xB2 # U+0x00B2 + 'threesuperior', # C+0xB3 # U+0x00B3 + 'acute', # C+0xB4 # U+0x00B4 + 'mu', # C+0xB5 # U+0x00B5 + 'paragraph', # C+0xB6 # U+0x00B6 + 'periodcentered', # C+0xB7 # U+0x00B7 + 'cedilla', # C+0xB8 # U+0x00B8 + 'onesuperior', # C+0xB9 # U+0x00B9 + 'ordmasculine', # C+0xBA # U+0x00BA + 'guillemotright', # C+0xBB # U+0x00BB + 'onequarter', # C+0xBC # U+0x00BC + 'onehalf', # C+0xBD # U+0x00BD + 'threequarters', # C+0xBE # U+0x00BE + 'questiondown', # C+0xBF # U+0x00BF + 'Agrave', # C+0xC0 # U+0x00C0 + 'Aacute', # C+0xC1 # U+0x00C1 + 'Acircumflex', # C+0xC2 # U+0x00C2 + 'Atilde', # C+0xC3 # U+0x00C3 + 'Adieresis', # C+0xC4 # U+0x00C4 + 'Aring', # C+0xC5 # U+0x00C5 + 'AE', # C+0xC6 # U+0x00C6 + 'Ccedilla', # C+0xC7 # U+0x00C7 + 'Egrave', # C+0xC8 # U+0x00C8 + 'Eacute', # C+0xC9 # U+0x00C9 + 'Ecircumflex', # C+0xCA # U+0x00CA + 'Edieresis', # C+0xCB # U+0x00CB + 'Igrave', # C+0xCC # U+0x00CC + 'Iacute', # C+0xCD # U+0x00CD + 'Icircumflex', # C+0xCE # U+0x00CE + 'Idieresis', # C+0xCF # U+0x00CF + 'Eth', # C+0xD0 # U+0x00D0 + 'Ntilde', # C+0xD1 # U+0x00D1 + 'Ograve', # C+0xD2 # U+0x00D2 + 'Oacute', # C+0xD3 # U+0x00D3 + 'Ocircumflex', # C+0xD4 # U+0x00D4 + 'Otilde', # C+0xD5 # U+0x00D5 + 'Odieresis', # C+0xD6 # U+0x00D6 + 'multiply', # C+0xD7 # U+0x00D7 + 'Oslash', # C+0xD8 # U+0x00D8 + 'Ugrave', # C+0xD9 # U+0x00D9 + 'Uacute', # C+0xDA # U+0x00DA + 'Ucircumflex', # C+0xDB # U+0x00DB + 'Udieresis', # C+0xDC # U+0x00DC + 'Yacute', # C+0xDD # U+0x00DD + 'Thorn', # C+0xDE # U+0x00DE + 'germandbls', # C+0xDF # U+0x00DF + 'agrave', # C+0xE0 # U+0x00E0 + 'aacute', # C+0xE1 # U+0x00E1 + 'acircumflex', # C+0xE2 # U+0x00E2 + 'atilde', # C+0xE3 # U+0x00E3 + 'adieresis', # C+0xE4 # U+0x00E4 + 'aring', # C+0xE5 # U+0x00E5 + 'ae', # C+0xE6 # U+0x00E6 + 'ccedilla', # C+0xE7 # U+0x00E7 + 'egrave', # C+0xE8 # U+0x00E8 + 'eacute', # C+0xE9 # U+0x00E9 + 'ecircumflex', # C+0xEA # U+0x00EA + 'edieresis', # C+0xEB # U+0x00EB + 'igrave', # C+0xEC # U+0x00EC + 'iacute', # C+0xED # U+0x00ED + 'icircumflex', # C+0xEE # U+0x00EE + 'idieresis', # C+0xEF # U+0x00EF + 'eth', # C+0xF0 # U+0x00F0 + 'ntilde', # C+0xF1 # U+0x00F1 + 'ograve', # C+0xF2 # U+0x00F2 + 'oacute', # C+0xF3 # U+0x00F3 + 'ocircumflex', # C+0xF4 # U+0x00F4 + 'otilde', # C+0xF5 # U+0x00F5 + 'odieresis', # C+0xF6 # U+0x00F6 + 'divide', # C+0xF7 # U+0x00F7 + 'oslash', # C+0xF8 # U+0x00F8 + 'ugrave', # C+0xF9 # U+0x00F9 + 'uacute', # C+0xFA # U+0x00FA + 'ucircumflex', # C+0xFB # U+0x00FB + 'udieresis', # C+0xFC # U+0x00FC + 'yacute', # C+0xFD # U+0x00FD + 'thorn', # C+0xFE # U+0x00FE + 'ydieresis', # C+0xFF # U+0x00FF + ], # DEF. ENCODING GLYPH TABLE + 'fontbbox' => [ -113, -250, 749, 801 ], + 'wx' => { # HORIZ. WIDTH TABLE + 'space' => '600', # C+0x20 # U+0x0020 + 'exclam' => '600', # C+0x21 # U+0x0021 + 'quotedbl' => '600', # C+0x22 # U+0x0022 + 'numbersign' => '600', # C+0x23 # U+0x0023 + 'dollar' => '600', # C+0x24 # U+0x0024 + 'percent' => '600', # C+0x25 # U+0x0025 + 'ampersand' => '600', # C+0x26 # U+0x0026 + 'quotesingle' => '600', # C+0x27 # U+0x0027 + 'parenleft' => '600', # C+0x28 # U+0x0028 + 'parenright' => '600', # C+0x29 # U+0x0029 + 'asterisk' => '600', # C+0x2A # U+0x002A + 'plus' => '600', # C+0x2B # U+0x002B + 'comma' => '600', # C+0x2C # U+0x002C + 'hyphen' => '600', # C+0x2D # U+0x002D + 'period' => '600', # C+0x2E # U+0x002E + 'slash' => '600', # C+0x2F # U+0x002F + 'zero' => '600', # C+0x30 # U+0x0030 + 'one' => '600', # C+0x31 # U+0x0031 + 'two' => '600', # C+0x32 # U+0x0032 + 'three' => '600', # C+0x33 # U+0x0033 + 'four' => '600', # C+0x34 # U+0x0034 + 'five' => '600', # C+0x35 # U+0x0035 + 'six' => '600', # C+0x36 # U+0x0036 + 'seven' => '600', # C+0x37 # U+0x0037 + 'eight' => '600', # C+0x38 # U+0x0038 + 'nine' => '600', # C+0x39 # U+0x0039 + 'colon' => '600', # C+0x3A # U+0x003A + 'semicolon' => '600', # C+0x3B # U+0x003B + 'less' => '600', # C+0x3C # U+0x003C + 'equal' => '600', # C+0x3D # U+0x003D + 'greater' => '600', # C+0x3E # U+0x003E + 'question' => '600', # C+0x3F # U+0x003F + 'at' => '600', # C+0x40 # U+0x0040 + 'A' => '600', # C+0x41 # U+0x0041 + 'B' => '600', # C+0x42 # U+0x0042 + 'C' => '600', # C+0x43 # U+0x0043 + 'D' => '600', # C+0x44 # U+0x0044 + 'E' => '600', # C+0x45 # U+0x0045 + 'F' => '600', # C+0x46 # U+0x0046 + 'G' => '600', # C+0x47 # U+0x0047 + 'H' => '600', # C+0x48 # U+0x0048 + 'I' => '600', # C+0x49 # U+0x0049 + 'J' => '600', # C+0x4A # U+0x004A + 'K' => '600', # C+0x4B # U+0x004B + 'L' => '600', # C+0x4C # U+0x004C + 'M' => '600', # C+0x4D # U+0x004D + 'N' => '600', # C+0x4E # U+0x004E + 'O' => '600', # C+0x4F # U+0x004F + 'P' => '600', # C+0x50 # U+0x0050 + 'Q' => '600', # C+0x51 # U+0x0051 + 'R' => '600', # C+0x52 # U+0x0052 + 'S' => '600', # C+0x53 # U+0x0053 + 'T' => '600', # C+0x54 # U+0x0054 + 'U' => '600', # C+0x55 # U+0x0055 + 'V' => '600', # C+0x56 # U+0x0056 + 'W' => '600', # C+0x57 # U+0x0057 + 'X' => '600', # C+0x58 # U+0x0058 + 'Y' => '600', # C+0x59 # U+0x0059 + 'Z' => '600', # C+0x5A # U+0x005A + 'bracketleft' => '600', # C+0x5B # U+0x005B + 'backslash' => '600', # C+0x5C # U+0x005C + 'bracketright' => '600', # C+0x5D # U+0x005D + 'asciicircum' => '600', # C+0x5E # U+0x005E + 'underscore' => '600', # C+0x5F # U+0x005F + 'grave' => '600', # C+0x60 # U+0x0060 + 'a' => '600', # C+0x61 # U+0x0061 + 'b' => '600', # C+0x62 # U+0x0062 + 'c' => '600', # C+0x63 # U+0x0063 + 'd' => '600', # C+0x64 # U+0x0064 + 'e' => '600', # C+0x65 # U+0x0065 + 'f' => '600', # C+0x66 # U+0x0066 + 'g' => '600', # C+0x67 # U+0x0067 + 'h' => '600', # C+0x68 # U+0x0068 + 'i' => '600', # C+0x69 # U+0x0069 + 'j' => '600', # C+0x6A # U+0x006A + 'k' => '600', # C+0x6B # U+0x006B + 'l' => '600', # C+0x6C # U+0x006C + 'm' => '600', # C+0x6D # U+0x006D + 'n' => '600', # C+0x6E # U+0x006E + 'o' => '600', # C+0x6F # U+0x006F + 'p' => '600', # C+0x70 # U+0x0070 + 'q' => '600', # C+0x71 # U+0x0071 + 'r' => '600', # C+0x72 # U+0x0072 + 's' => '600', # C+0x73 # U+0x0073 + 't' => '600', # C+0x74 # U+0x0074 + 'u' => '600', # C+0x75 # U+0x0075 + 'v' => '600', # C+0x76 # U+0x0076 + 'w' => '600', # C+0x77 # U+0x0077 + 'x' => '600', # C+0x78 # U+0x0078 + 'y' => '600', # C+0x79 # U+0x0079 + 'z' => '600', # C+0x7A # U+0x007A + 'braceleft' => '600', # C+0x7B # U+0x007B + 'bar' => '600', # C+0x7C # U+0x007C + 'braceright' => '600', # C+0x7D # U+0x007D + 'asciitilde' => '600', # C+0x7E # U+0x007E + 'bullet' => '600', # C+0x7F # U+0x2022 + 'Euro' => '600', # C+0x80 # U+0x20AC + 'quotesinglbase' => '600', # C+0x82 # U+0x201A + 'florin' => '600', # C+0x83 # U+0x0192 + 'quotedblbase' => '600', # C+0x84 # U+0x201E + 'ellipsis' => '600', # C+0x85 # U+0x2026 + 'dagger' => '600', # C+0x86 # U+0x2020 + 'daggerdbl' => '600', # C+0x87 # U+0x2021 + 'circumflex' => '600', # C+0x88 # U+0x02C6 + 'perthousand' => '600', # C+0x89 # U+0x2030 + 'Scaron' => '600', # C+0x8A # U+0x0160 + 'guilsinglleft' => '600', # C+0x8B # U+0x2039 + 'OE' => '600', # C+0x8C # U+0x0152 + 'Zcaron' => '600', # C+0x8E # U+0x017D + 'quoteleft' => '600', # C+0x91 # U+0x2018 + 'quoteright' => '600', # C+0x92 # U+0x2019 + 'quotedblleft' => '600', # C+0x93 # U+0x201C + 'quotedblright' => '600', # C+0x94 # U+0x201D + 'endash' => '600', # C+0x96 # U+0x2013 + 'emdash' => '600', # C+0x97 # U+0x2014 + 'tilde' => '600', # C+0x98 # U+0x02DC + 'trademark' => '600', # C+0x99 # U+0x2122 + 'scaron' => '600', # C+0x9A # U+0x0161 + 'guilsinglright' => '600', # C+0x9B # U+0x203A + 'oe' => '600', # C+0x9C # U+0x0153 + 'zcaron' => '600', # C+0x9E # U+0x017E + 'Ydieresis' => '600', # C+0x9F # U+0x0178 + 'exclamdown' => '600', # C+0xA1 # U+0x00A1 + 'cent' => '600', # C+0xA2 # U+0x00A2 + 'sterling' => '600', # C+0xA3 # U+0x00A3 + 'currency' => '600', # C+0xA4 # U+0x00A4 + 'yen' => '600', # C+0xA5 # U+0x00A5 + 'brokenbar' => '600', # C+0xA6 # U+0x00A6 + 'section' => '600', # C+0xA7 # U+0x00A7 + 'dieresis' => '600', # C+0xA8 # U+0x00A8 + 'copyright' => '600', # C+0xA9 # U+0x00A9 + 'ordfeminine' => '600', # C+0xAA # U+0x00AA + 'guillemotleft' => '600', # C+0xAB # U+0x00AB + 'logicalnot' => '600', # C+0xAC # U+0x00AC + 'registered' => '600', # C+0xAE # U+0x00AE + 'macron' => '600', # C+0xAF # U+0x00AF + 'degree' => '600', # C+0xB0 # U+0x00B0 + 'plusminus' => '600', # C+0xB1 # U+0x00B1 + 'twosuperior' => '600', # C+0xB2 # U+0x00B2 + 'threesuperior' => '600', # C+0xB3 # U+0x00B3 + 'acute' => '600', # C+0xB4 # U+0x00B4 + 'mu' => '600', # C+0xB5 # U+0x00B5 + 'paragraph' => '600', # C+0xB6 # U+0x00B6 + 'periodcentered' => '600', # C+0xB7 # U+0x00B7 + 'cedilla' => '600', # C+0xB8 # U+0x00B8 + 'onesuperior' => '600', # C+0xB9 # U+0x00B9 + 'ordmasculine' => '600', # C+0xBA # U+0x00BA + 'guillemotright' => '600', # C+0xBB # U+0x00BB + 'onequarter' => '600', # C+0xBC # U+0x00BC + 'onehalf' => '600', # C+0xBD # U+0x00BD + 'threequarters' => '600', # C+0xBE # U+0x00BE + 'questiondown' => '600', # C+0xBF # U+0x00BF + 'Agrave' => '600', # C+0xC0 # U+0x00C0 + 'Aacute' => '600', # C+0xC1 # U+0x00C1 + 'Acircumflex' => '600', # C+0xC2 # U+0x00C2 + 'Atilde' => '600', # C+0xC3 # U+0x00C3 + 'Adieresis' => '600', # C+0xC4 # U+0x00C4 + 'Aring' => '600', # C+0xC5 # U+0x00C5 + 'AE' => '600', # C+0xC6 # U+0x00C6 + 'Ccedilla' => '600', # C+0xC7 # U+0x00C7 + 'Egrave' => '600', # C+0xC8 # U+0x00C8 + 'Eacute' => '600', # C+0xC9 # U+0x00C9 + 'Ecircumflex' => '600', # C+0xCA # U+0x00CA + 'Edieresis' => '600', # C+0xCB # U+0x00CB + 'Igrave' => '600', # C+0xCC # U+0x00CC + 'Iacute' => '600', # C+0xCD # U+0x00CD + 'Icircumflex' => '600', # C+0xCE # U+0x00CE + 'Idieresis' => '600', # C+0xCF # U+0x00CF + 'Eth' => '600', # C+0xD0 # U+0x00D0 + 'Ntilde' => '600', # C+0xD1 # U+0x00D1 + 'Ograve' => '600', # C+0xD2 # U+0x00D2 + 'Oacute' => '600', # C+0xD3 # U+0x00D3 + 'Ocircumflex' => '600', # C+0xD4 # U+0x00D4 + 'Otilde' => '600', # C+0xD5 # U+0x00D5 + 'Odieresis' => '600', # C+0xD6 # U+0x00D6 + 'multiply' => '600', # C+0xD7 # U+0x00D7 + 'Oslash' => '600', # C+0xD8 # U+0x00D8 + 'Ugrave' => '600', # C+0xD9 # U+0x00D9 + 'Uacute' => '600', # C+0xDA # U+0x00DA + 'Ucircumflex' => '600', # C+0xDB # U+0x00DB + 'Udieresis' => '600', # C+0xDC # U+0x00DC + 'Yacute' => '600', # C+0xDD # U+0x00DD + 'Thorn' => '600', # C+0xDE # U+0x00DE + 'germandbls' => '600', # C+0xDF # U+0x00DF + 'agrave' => '600', # C+0xE0 # U+0x00E0 + 'aacute' => '600', # C+0xE1 # U+0x00E1 + 'acircumflex' => '600', # C+0xE2 # U+0x00E2 + 'atilde' => '600', # C+0xE3 # U+0x00E3 + 'adieresis' => '600', # C+0xE4 # U+0x00E4 + 'aring' => '600', # C+0xE5 # U+0x00E5 + 'ae' => '600', # C+0xE6 # U+0x00E6 + 'ccedilla' => '600', # C+0xE7 # U+0x00E7 + 'egrave' => '600', # C+0xE8 # U+0x00E8 + 'eacute' => '600', # C+0xE9 # U+0x00E9 + 'ecircumflex' => '600', # C+0xEA # U+0x00EA + 'edieresis' => '600', # C+0xEB # U+0x00EB + 'igrave' => '600', # C+0xEC # U+0x00EC + 'iacute' => '600', # C+0xED # U+0x00ED + 'icircumflex' => '600', # C+0xEE # U+0x00EE + 'idieresis' => '600', # C+0xEF # U+0x00EF + 'eth' => '600', # C+0xF0 # U+0x00F0 + 'ntilde' => '600', # C+0xF1 # U+0x00F1 + 'ograve' => '600', # C+0xF2 # U+0x00F2 + 'oacute' => '600', # C+0xF3 # U+0x00F3 + 'ocircumflex' => '600', # C+0xF4 # U+0x00F4 + 'otilde' => '600', # C+0xF5 # U+0x00F5 + 'odieresis' => '600', # C+0xF6 # U+0x00F6 + 'divide' => '600', # C+0xF7 # U+0x00F7 + 'oslash' => '600', # C+0xF8 # U+0x00F8 + 'ugrave' => '600', # C+0xF9 # U+0x00F9 + 'uacute' => '600', # C+0xFA # U+0x00FA + 'ucircumflex' => '600', # C+0xFB # U+0x00FB + 'udieresis' => '600', # C+0xFC # U+0x00FC + 'yacute' => '600', # C+0xFD # U+0x00FD + 'thorn' => '600', # C+0xFE # U+0x00FE + 'ydieresis' => '600', # C+0xFF # U+0x00FF + 'dotlessi' => '600', # U+0x0131 + 'Lslash' => '600', # U+0x0141 + 'lslash' => '600', # U+0x0142 + 'caron' => '600', # U+0x02C7 + 'breve' => '600', # U+0x02D8 + 'dotaccent' => '600', # U+0x02D9 + 'ring' => '600', # U+0x02DA + 'ogonek' => '600', # U+0x02DB + 'hungarumlaut' => '600', # U+0x02DD + 'fraction' => '600', # U+0x2044 + 'minus' => '600', # U+0x2212 + 'fi' => '600', # U+0xFB01 + 'fl' => '600', # U+0xFB02 + }, # HORIZ. WIDTH TABLE +} }; + +1; diff --git a/lib/PDF/API2/Resource/Font/CoreFont/courierboldoblique.pm b/lib/PDF/API2/Resource/Font/CoreFont/courierboldoblique.pm new file mode 100644 index 0000000..97ad474 --- /dev/null +++ b/lib/PDF/API2/Resource/Font/CoreFont/courierboldoblique.pm @@ -0,0 +1,520 @@ +#line 1 "PDF/API2/Resource/Font/CoreFont/courierboldoblique.pm" +#line 1 "PDF/API2/Resource/Font/CoreFont/courierboldoblique.pm" +package PDF::API2::Resource::Font::CoreFont::courierboldoblique; + +use strict; +use warnings; + +our $VERSION = '2.033'; # VERSION + +sub data { return { + 'fontname' => 'Courier-BoldOblique', + 'type' => 'Type1', + 'apiname' => 'CoBoIt', + 'ascender' => '629', + 'capheight' => '562', + 'descender' => '-157', + 'iscore' => '1', + 'isfixedpitch' => '1', + 'italicangle' => '-12', + 'missingwidth' => '600', + 'stdhw' => '84', + 'stdvw' => '106', + 'underlineposition' => '-100', + 'underlinethickness' => '50', + 'xheight' => '439', + 'firstchar' => '32', + 'lastchar' => '255', + 'char' => [ # DEF. ENCODING GLYPH TABLE + '.notdef', # C+0x00 # U+0x0000 + '.notdef', # C+0x01 # U+0x0000 + '.notdef', # C+0x02 # U+0x0000 + '.notdef', # C+0x03 # U+0x0000 + '.notdef', # C+0x04 # U+0x0000 + '.notdef', # C+0x05 # U+0x0000 + '.notdef', # C+0x06 # U+0x0000 + '.notdef', # C+0x07 # U+0x0000 + '.notdef', # C+0x08 # U+0x0000 + '.notdef', # C+0x09 # U+0x0000 + '.notdef', # C+0x0A # U+0x0000 + '.notdef', # C+0x0B # U+0x0000 + '.notdef', # C+0x0C # U+0x0000 + '.notdef', # C+0x0D # U+0x0000 + '.notdef', # C+0x0E # U+0x0000 + '.notdef', # C+0x0F # U+0x0000 + '.notdef', # C+0x10 # U+0x0000 + '.notdef', # C+0x11 # U+0x0000 + '.notdef', # C+0x12 # U+0x0000 + '.notdef', # C+0x13 # U+0x0000 + '.notdef', # C+0x14 # U+0x0000 + '.notdef', # C+0x15 # U+0x0000 + '.notdef', # C+0x16 # U+0x0000 + '.notdef', # C+0x17 # U+0x0000 + '.notdef', # C+0x18 # U+0x0000 + '.notdef', # C+0x19 # U+0x0000 + '.notdef', # C+0x1A # U+0x0000 + '.notdef', # C+0x1B # U+0x0000 + '.notdef', # C+0x1C # U+0x0000 + '.notdef', # C+0x1D # U+0x0000 + '.notdef', # C+0x1E # U+0x0000 + '.notdef', # C+0x1F # U+0x0000 + 'space', # C+0x20 # U+0x0020 + 'exclam', # C+0x21 # U+0x0021 + 'quotedbl', # C+0x22 # U+0x0022 + 'numbersign', # C+0x23 # U+0x0023 + 'dollar', # C+0x24 # U+0x0024 + 'percent', # C+0x25 # U+0x0025 + 'ampersand', # C+0x26 # U+0x0026 + 'quotesingle', # C+0x27 # U+0x0027 + 'parenleft', # C+0x28 # U+0x0028 + 'parenright', # C+0x29 # U+0x0029 + 'asterisk', # C+0x2A # U+0x002A + 'plus', # C+0x2B # U+0x002B + 'comma', # C+0x2C # U+0x002C + 'hyphen', # C+0x2D # U+0x002D + 'period', # C+0x2E # U+0x002E + 'slash', # C+0x2F # U+0x002F + 'zero', # C+0x30 # U+0x0030 + 'one', # C+0x31 # U+0x0031 + 'two', # C+0x32 # U+0x0032 + 'three', # C+0x33 # U+0x0033 + 'four', # C+0x34 # U+0x0034 + 'five', # C+0x35 # U+0x0035 + 'six', # C+0x36 # U+0x0036 + 'seven', # C+0x37 # U+0x0037 + 'eight', # C+0x38 # U+0x0038 + 'nine', # C+0x39 # U+0x0039 + 'colon', # C+0x3A # U+0x003A + 'semicolon', # C+0x3B # U+0x003B + 'less', # C+0x3C # U+0x003C + 'equal', # C+0x3D # U+0x003D + 'greater', # C+0x3E # U+0x003E + 'question', # C+0x3F # U+0x003F + 'at', # C+0x40 # U+0x0040 + 'A', # C+0x41 # U+0x0041 + 'B', # C+0x42 # U+0x0042 + 'C', # C+0x43 # U+0x0043 + 'D', # C+0x44 # U+0x0044 + 'E', # C+0x45 # U+0x0045 + 'F', # C+0x46 # U+0x0046 + 'G', # C+0x47 # U+0x0047 + 'H', # C+0x48 # U+0x0048 + 'I', # C+0x49 # U+0x0049 + 'J', # C+0x4A # U+0x004A + 'K', # C+0x4B # U+0x004B + 'L', # C+0x4C # U+0x004C + 'M', # C+0x4D # U+0x004D + 'N', # C+0x4E # U+0x004E + 'O', # C+0x4F # U+0x004F + 'P', # C+0x50 # U+0x0050 + 'Q', # C+0x51 # U+0x0051 + 'R', # C+0x52 # U+0x0052 + 'S', # C+0x53 # U+0x0053 + 'T', # C+0x54 # U+0x0054 + 'U', # C+0x55 # U+0x0055 + 'V', # C+0x56 # U+0x0056 + 'W', # C+0x57 # U+0x0057 + 'X', # C+0x58 # U+0x0058 + 'Y', # C+0x59 # U+0x0059 + 'Z', # C+0x5A # U+0x005A + 'bracketleft', # C+0x5B # U+0x005B + 'backslash', # C+0x5C # U+0x005C + 'bracketright', # C+0x5D # U+0x005D + 'asciicircum', # C+0x5E # U+0x005E + 'underscore', # C+0x5F # U+0x005F + 'grave', # C+0x60 # U+0x0060 + 'a', # C+0x61 # U+0x0061 + 'b', # C+0x62 # U+0x0062 + 'c', # C+0x63 # U+0x0063 + 'd', # C+0x64 # U+0x0064 + 'e', # C+0x65 # U+0x0065 + 'f', # C+0x66 # U+0x0066 + 'g', # C+0x67 # U+0x0067 + 'h', # C+0x68 # U+0x0068 + 'i', # C+0x69 # U+0x0069 + 'j', # C+0x6A # U+0x006A + 'k', # C+0x6B # U+0x006B + 'l', # C+0x6C # U+0x006C + 'm', # C+0x6D # U+0x006D + 'n', # C+0x6E # U+0x006E + 'o', # C+0x6F # U+0x006F + 'p', # C+0x70 # U+0x0070 + 'q', # C+0x71 # U+0x0071 + 'r', # C+0x72 # U+0x0072 + 's', # C+0x73 # U+0x0073 + 't', # C+0x74 # U+0x0074 + 'u', # C+0x75 # U+0x0075 + 'v', # C+0x76 # U+0x0076 + 'w', # C+0x77 # U+0x0077 + 'x', # C+0x78 # U+0x0078 + 'y', # C+0x79 # U+0x0079 + 'z', # C+0x7A # U+0x007A + 'braceleft', # C+0x7B # U+0x007B + 'bar', # C+0x7C # U+0x007C + 'braceright', # C+0x7D # U+0x007D + 'asciitilde', # C+0x7E # U+0x007E + 'bullet', # C+0x7F # U+0x2022 + 'Euro', # C+0x80 # U+0x20AC + 'bullet', # C+0x81 # U+0x2022 + 'quotesinglbase', # C+0x82 # U+0x201A + 'florin', # C+0x83 # U+0x0192 + 'quotedblbase', # C+0x84 # U+0x201E + 'ellipsis', # C+0x85 # U+0x2026 + 'dagger', # C+0x86 # U+0x2020 + 'daggerdbl', # C+0x87 # U+0x2021 + 'circumflex', # C+0x88 # U+0x02C6 + 'perthousand', # C+0x89 # U+0x2030 + 'Scaron', # C+0x8A # U+0x0160 + 'guilsinglleft', # C+0x8B # U+0x2039 + 'OE', # C+0x8C # U+0x0152 + 'bullet', # C+0x8D # U+0x2022 + 'Zcaron', # C+0x8E # U+0x017D + 'bullet', # C+0x8F # U+0x2022 + 'bullet', # C+0x90 # U+0x2022 + 'quoteleft', # C+0x91 # U+0x2018 + 'quoteright', # C+0x92 # U+0x2019 + 'quotedblleft', # C+0x93 # U+0x201C + 'quotedblright', # C+0x94 # U+0x201D + 'bullet', # C+0x95 # U+0x2022 + 'endash', # C+0x96 # U+0x2013 + 'emdash', # C+0x97 # U+0x2014 + 'tilde', # C+0x98 # U+0x02DC + 'trademark', # C+0x99 # U+0x2122 + 'scaron', # C+0x9A # U+0x0161 + 'guilsinglright', # C+0x9B # U+0x203A + 'oe', # C+0x9C # U+0x0153 + 'bullet', # C+0x9D # U+0x2022 + 'zcaron', # C+0x9E # U+0x017E + 'Ydieresis', # C+0x9F # U+0x0178 + 'space', # C+0xA0 # U+0x0020 + 'exclamdown', # C+0xA1 # U+0x00A1 + 'cent', # C+0xA2 # U+0x00A2 + 'sterling', # C+0xA3 # U+0x00A3 + 'currency', # C+0xA4 # U+0x00A4 + 'yen', # C+0xA5 # U+0x00A5 + 'brokenbar', # C+0xA6 # U+0x00A6 + 'section', # C+0xA7 # U+0x00A7 + 'dieresis', # C+0xA8 # U+0x00A8 + 'copyright', # C+0xA9 # U+0x00A9 + 'ordfeminine', # C+0xAA # U+0x00AA + 'guillemotleft', # C+0xAB # U+0x00AB + 'logicalnot', # C+0xAC # U+0x00AC + 'hyphen', # C+0xAD # U+0x002D + 'registered', # C+0xAE # U+0x00AE + 'macron', # C+0xAF # U+0x00AF + 'degree', # C+0xB0 # U+0x00B0 + 'plusminus', # C+0xB1 # U+0x00B1 + 'twosuperior', # C+0xB2 # U+0x00B2 + 'threesuperior', # C+0xB3 # U+0x00B3 + 'acute', # C+0xB4 # U+0x00B4 + 'mu', # C+0xB5 # U+0x00B5 + 'paragraph', # C+0xB6 # U+0x00B6 + 'periodcentered', # C+0xB7 # U+0x00B7 + 'cedilla', # C+0xB8 # U+0x00B8 + 'onesuperior', # C+0xB9 # U+0x00B9 + 'ordmasculine', # C+0xBA # U+0x00BA + 'guillemotright', # C+0xBB # U+0x00BB + 'onequarter', # C+0xBC # U+0x00BC + 'onehalf', # C+0xBD # U+0x00BD + 'threequarters', # C+0xBE # U+0x00BE + 'questiondown', # C+0xBF # U+0x00BF + 'Agrave', # C+0xC0 # U+0x00C0 + 'Aacute', # C+0xC1 # U+0x00C1 + 'Acircumflex', # C+0xC2 # U+0x00C2 + 'Atilde', # C+0xC3 # U+0x00C3 + 'Adieresis', # C+0xC4 # U+0x00C4 + 'Aring', # C+0xC5 # U+0x00C5 + 'AE', # C+0xC6 # U+0x00C6 + 'Ccedilla', # C+0xC7 # U+0x00C7 + 'Egrave', # C+0xC8 # U+0x00C8 + 'Eacute', # C+0xC9 # U+0x00C9 + 'Ecircumflex', # C+0xCA # U+0x00CA + 'Edieresis', # C+0xCB # U+0x00CB + 'Igrave', # C+0xCC # U+0x00CC + 'Iacute', # C+0xCD # U+0x00CD + 'Icircumflex', # C+0xCE # U+0x00CE + 'Idieresis', # C+0xCF # U+0x00CF + 'Eth', # C+0xD0 # U+0x00D0 + 'Ntilde', # C+0xD1 # U+0x00D1 + 'Ograve', # C+0xD2 # U+0x00D2 + 'Oacute', # C+0xD3 # U+0x00D3 + 'Ocircumflex', # C+0xD4 # U+0x00D4 + 'Otilde', # C+0xD5 # U+0x00D5 + 'Odieresis', # C+0xD6 # U+0x00D6 + 'multiply', # C+0xD7 # U+0x00D7 + 'Oslash', # C+0xD8 # U+0x00D8 + 'Ugrave', # C+0xD9 # U+0x00D9 + 'Uacute', # C+0xDA # U+0x00DA + 'Ucircumflex', # C+0xDB # U+0x00DB + 'Udieresis', # C+0xDC # U+0x00DC + 'Yacute', # C+0xDD # U+0x00DD + 'Thorn', # C+0xDE # U+0x00DE + 'germandbls', # C+0xDF # U+0x00DF + 'agrave', # C+0xE0 # U+0x00E0 + 'aacute', # C+0xE1 # U+0x00E1 + 'acircumflex', # C+0xE2 # U+0x00E2 + 'atilde', # C+0xE3 # U+0x00E3 + 'adieresis', # C+0xE4 # U+0x00E4 + 'aring', # C+0xE5 # U+0x00E5 + 'ae', # C+0xE6 # U+0x00E6 + 'ccedilla', # C+0xE7 # U+0x00E7 + 'egrave', # C+0xE8 # U+0x00E8 + 'eacute', # C+0xE9 # U+0x00E9 + 'ecircumflex', # C+0xEA # U+0x00EA + 'edieresis', # C+0xEB # U+0x00EB + 'igrave', # C+0xEC # U+0x00EC + 'iacute', # C+0xED # U+0x00ED + 'icircumflex', # C+0xEE # U+0x00EE + 'idieresis', # C+0xEF # U+0x00EF + 'eth', # C+0xF0 # U+0x00F0 + 'ntilde', # C+0xF1 # U+0x00F1 + 'ograve', # C+0xF2 # U+0x00F2 + 'oacute', # C+0xF3 # U+0x00F3 + 'ocircumflex', # C+0xF4 # U+0x00F4 + 'otilde', # C+0xF5 # U+0x00F5 + 'odieresis', # C+0xF6 # U+0x00F6 + 'divide', # C+0xF7 # U+0x00F7 + 'oslash', # C+0xF8 # U+0x00F8 + 'ugrave', # C+0xF9 # U+0x00F9 + 'uacute', # C+0xFA # U+0x00FA + 'ucircumflex', # C+0xFB # U+0x00FB + 'udieresis', # C+0xFC # U+0x00FC + 'yacute', # C+0xFD # U+0x00FD + 'thorn', # C+0xFE # U+0x00FE + 'ydieresis', # C+0xFF # U+0x00FF + ], # DEF. ENCODING GLYPH TABLE + 'fontbbox' => [ -57, -250, 869, 801 ], + 'wx' => { # HORIZ. WIDTH TABLE + 'space' => '600', # C+0x20 # U+0x0020 + 'exclam' => '600', # C+0x21 # U+0x0021 + 'quotedbl' => '600', # C+0x22 # U+0x0022 + 'numbersign' => '600', # C+0x23 # U+0x0023 + 'dollar' => '600', # C+0x24 # U+0x0024 + 'percent' => '600', # C+0x25 # U+0x0025 + 'ampersand' => '600', # C+0x26 # U+0x0026 + 'quotesingle' => '600', # C+0x27 # U+0x0027 + 'parenleft' => '600', # C+0x28 # U+0x0028 + 'parenright' => '600', # C+0x29 # U+0x0029 + 'asterisk' => '600', # C+0x2A # U+0x002A + 'plus' => '600', # C+0x2B # U+0x002B + 'comma' => '600', # C+0x2C # U+0x002C + 'hyphen' => '600', # C+0x2D # U+0x002D + 'period' => '600', # C+0x2E # U+0x002E + 'slash' => '600', # C+0x2F # U+0x002F + 'zero' => '600', # C+0x30 # U+0x0030 + 'one' => '600', # C+0x31 # U+0x0031 + 'two' => '600', # C+0x32 # U+0x0032 + 'three' => '600', # C+0x33 # U+0x0033 + 'four' => '600', # C+0x34 # U+0x0034 + 'five' => '600', # C+0x35 # U+0x0035 + 'six' => '600', # C+0x36 # U+0x0036 + 'seven' => '600', # C+0x37 # U+0x0037 + 'eight' => '600', # C+0x38 # U+0x0038 + 'nine' => '600', # C+0x39 # U+0x0039 + 'colon' => '600', # C+0x3A # U+0x003A + 'semicolon' => '600', # C+0x3B # U+0x003B + 'less' => '600', # C+0x3C # U+0x003C + 'equal' => '600', # C+0x3D # U+0x003D + 'greater' => '600', # C+0x3E # U+0x003E + 'question' => '600', # C+0x3F # U+0x003F + 'at' => '600', # C+0x40 # U+0x0040 + 'A' => '600', # C+0x41 # U+0x0041 + 'B' => '600', # C+0x42 # U+0x0042 + 'C' => '600', # C+0x43 # U+0x0043 + 'D' => '600', # C+0x44 # U+0x0044 + 'E' => '600', # C+0x45 # U+0x0045 + 'F' => '600', # C+0x46 # U+0x0046 + 'G' => '600', # C+0x47 # U+0x0047 + 'H' => '600', # C+0x48 # U+0x0048 + 'I' => '600', # C+0x49 # U+0x0049 + 'J' => '600', # C+0x4A # U+0x004A + 'K' => '600', # C+0x4B # U+0x004B + 'L' => '600', # C+0x4C # U+0x004C + 'M' => '600', # C+0x4D # U+0x004D + 'N' => '600', # C+0x4E # U+0x004E + 'O' => '600', # C+0x4F # U+0x004F + 'P' => '600', # C+0x50 # U+0x0050 + 'Q' => '600', # C+0x51 # U+0x0051 + 'R' => '600', # C+0x52 # U+0x0052 + 'S' => '600', # C+0x53 # U+0x0053 + 'T' => '600', # C+0x54 # U+0x0054 + 'U' => '600', # C+0x55 # U+0x0055 + 'V' => '600', # C+0x56 # U+0x0056 + 'W' => '600', # C+0x57 # U+0x0057 + 'X' => '600', # C+0x58 # U+0x0058 + 'Y' => '600', # C+0x59 # U+0x0059 + 'Z' => '600', # C+0x5A # U+0x005A + 'bracketleft' => '600', # C+0x5B # U+0x005B + 'backslash' => '600', # C+0x5C # U+0x005C + 'bracketright' => '600', # C+0x5D # U+0x005D + 'asciicircum' => '600', # C+0x5E # U+0x005E + 'underscore' => '600', # C+0x5F # U+0x005F + 'grave' => '600', # C+0x60 # U+0x0060 + 'a' => '600', # C+0x61 # U+0x0061 + 'b' => '600', # C+0x62 # U+0x0062 + 'c' => '600', # C+0x63 # U+0x0063 + 'd' => '600', # C+0x64 # U+0x0064 + 'e' => '600', # C+0x65 # U+0x0065 + 'f' => '600', # C+0x66 # U+0x0066 + 'g' => '600', # C+0x67 # U+0x0067 + 'h' => '600', # C+0x68 # U+0x0068 + 'i' => '600', # C+0x69 # U+0x0069 + 'j' => '600', # C+0x6A # U+0x006A + 'k' => '600', # C+0x6B # U+0x006B + 'l' => '600', # C+0x6C # U+0x006C + 'm' => '600', # C+0x6D # U+0x006D + 'n' => '600', # C+0x6E # U+0x006E + 'o' => '600', # C+0x6F # U+0x006F + 'p' => '600', # C+0x70 # U+0x0070 + 'q' => '600', # C+0x71 # U+0x0071 + 'r' => '600', # C+0x72 # U+0x0072 + 's' => '600', # C+0x73 # U+0x0073 + 't' => '600', # C+0x74 # U+0x0074 + 'u' => '600', # C+0x75 # U+0x0075 + 'v' => '600', # C+0x76 # U+0x0076 + 'w' => '600', # C+0x77 # U+0x0077 + 'x' => '600', # C+0x78 # U+0x0078 + 'y' => '600', # C+0x79 # U+0x0079 + 'z' => '600', # C+0x7A # U+0x007A + 'braceleft' => '600', # C+0x7B # U+0x007B + 'bar' => '600', # C+0x7C # U+0x007C + 'braceright' => '600', # C+0x7D # U+0x007D + 'asciitilde' => '600', # C+0x7E # U+0x007E + 'bullet' => '600', # C+0x7F # U+0x2022 + 'Euro' => '600', # C+0x80 # U+0x20AC + 'quotesinglbase' => '600', # C+0x82 # U+0x201A + 'florin' => '600', # C+0x83 # U+0x0192 + 'quotedblbase' => '600', # C+0x84 # U+0x201E + 'ellipsis' => '600', # C+0x85 # U+0x2026 + 'dagger' => '600', # C+0x86 # U+0x2020 + 'daggerdbl' => '600', # C+0x87 # U+0x2021 + 'circumflex' => '600', # C+0x88 # U+0x02C6 + 'perthousand' => '600', # C+0x89 # U+0x2030 + 'Scaron' => '600', # C+0x8A # U+0x0160 + 'guilsinglleft' => '600', # C+0x8B # U+0x2039 + 'OE' => '600', # C+0x8C # U+0x0152 + 'Zcaron' => '600', # C+0x8E # U+0x017D + 'quoteleft' => '600', # C+0x91 # U+0x2018 + 'quoteright' => '600', # C+0x92 # U+0x2019 + 'quotedblleft' => '600', # C+0x93 # U+0x201C + 'quotedblright' => '600', # C+0x94 # U+0x201D + 'endash' => '600', # C+0x96 # U+0x2013 + 'emdash' => '600', # C+0x97 # U+0x2014 + 'tilde' => '600', # C+0x98 # U+0x02DC + 'trademark' => '600', # C+0x99 # U+0x2122 + 'scaron' => '600', # C+0x9A # U+0x0161 + 'guilsinglright' => '600', # C+0x9B # U+0x203A + 'oe' => '600', # C+0x9C # U+0x0153 + 'zcaron' => '600', # C+0x9E # U+0x017E + 'Ydieresis' => '600', # C+0x9F # U+0x0178 + 'exclamdown' => '600', # C+0xA1 # U+0x00A1 + 'cent' => '600', # C+0xA2 # U+0x00A2 + 'sterling' => '600', # C+0xA3 # U+0x00A3 + 'currency' => '600', # C+0xA4 # U+0x00A4 + 'yen' => '600', # C+0xA5 # U+0x00A5 + 'brokenbar' => '600', # C+0xA6 # U+0x00A6 + 'section' => '600', # C+0xA7 # U+0x00A7 + 'dieresis' => '600', # C+0xA8 # U+0x00A8 + 'copyright' => '600', # C+0xA9 # U+0x00A9 + 'ordfeminine' => '600', # C+0xAA # U+0x00AA + 'guillemotleft' => '600', # C+0xAB # U+0x00AB + 'logicalnot' => '600', # C+0xAC # U+0x00AC + 'registered' => '600', # C+0xAE # U+0x00AE + 'macron' => '600', # C+0xAF # U+0x00AF + 'degree' => '600', # C+0xB0 # U+0x00B0 + 'plusminus' => '600', # C+0xB1 # U+0x00B1 + 'twosuperior' => '600', # C+0xB2 # U+0x00B2 + 'threesuperior' => '600', # C+0xB3 # U+0x00B3 + 'acute' => '600', # C+0xB4 # U+0x00B4 + 'mu' => '600', # C+0xB5 # U+0x00B5 + 'paragraph' => '600', # C+0xB6 # U+0x00B6 + 'periodcentered' => '600', # C+0xB7 # U+0x00B7 + 'cedilla' => '600', # C+0xB8 # U+0x00B8 + 'onesuperior' => '600', # C+0xB9 # U+0x00B9 + 'ordmasculine' => '600', # C+0xBA # U+0x00BA + 'guillemotright' => '600', # C+0xBB # U+0x00BB + 'onequarter' => '600', # C+0xBC # U+0x00BC + 'onehalf' => '600', # C+0xBD # U+0x00BD + 'threequarters' => '600', # C+0xBE # U+0x00BE + 'questiondown' => '600', # C+0xBF # U+0x00BF + 'Agrave' => '600', # C+0xC0 # U+0x00C0 + 'Aacute' => '600', # C+0xC1 # U+0x00C1 + 'Acircumflex' => '600', # C+0xC2 # U+0x00C2 + 'Atilde' => '600', # C+0xC3 # U+0x00C3 + 'Adieresis' => '600', # C+0xC4 # U+0x00C4 + 'Aring' => '600', # C+0xC5 # U+0x00C5 + 'AE' => '600', # C+0xC6 # U+0x00C6 + 'Ccedilla' => '600', # C+0xC7 # U+0x00C7 + 'Egrave' => '600', # C+0xC8 # U+0x00C8 + 'Eacute' => '600', # C+0xC9 # U+0x00C9 + 'Ecircumflex' => '600', # C+0xCA # U+0x00CA + 'Edieresis' => '600', # C+0xCB # U+0x00CB + 'Igrave' => '600', # C+0xCC # U+0x00CC + 'Iacute' => '600', # C+0xCD # U+0x00CD + 'Icircumflex' => '600', # C+0xCE # U+0x00CE + 'Idieresis' => '600', # C+0xCF # U+0x00CF + 'Eth' => '600', # C+0xD0 # U+0x00D0 + 'Ntilde' => '600', # C+0xD1 # U+0x00D1 + 'Ograve' => '600', # C+0xD2 # U+0x00D2 + 'Oacute' => '600', # C+0xD3 # U+0x00D3 + 'Ocircumflex' => '600', # C+0xD4 # U+0x00D4 + 'Otilde' => '600', # C+0xD5 # U+0x00D5 + 'Odieresis' => '600', # C+0xD6 # U+0x00D6 + 'multiply' => '600', # C+0xD7 # U+0x00D7 + 'Oslash' => '600', # C+0xD8 # U+0x00D8 + 'Ugrave' => '600', # C+0xD9 # U+0x00D9 + 'Uacute' => '600', # C+0xDA # U+0x00DA + 'Ucircumflex' => '600', # C+0xDB # U+0x00DB + 'Udieresis' => '600', # C+0xDC # U+0x00DC + 'Yacute' => '600', # C+0xDD # U+0x00DD + 'Thorn' => '600', # C+0xDE # U+0x00DE + 'germandbls' => '600', # C+0xDF # U+0x00DF + 'agrave' => '600', # C+0xE0 # U+0x00E0 + 'aacute' => '600', # C+0xE1 # U+0x00E1 + 'acircumflex' => '600', # C+0xE2 # U+0x00E2 + 'atilde' => '600', # C+0xE3 # U+0x00E3 + 'adieresis' => '600', # C+0xE4 # U+0x00E4 + 'aring' => '600', # C+0xE5 # U+0x00E5 + 'ae' => '600', # C+0xE6 # U+0x00E6 + 'ccedilla' => '600', # C+0xE7 # U+0x00E7 + 'egrave' => '600', # C+0xE8 # U+0x00E8 + 'eacute' => '600', # C+0xE9 # U+0x00E9 + 'ecircumflex' => '600', # C+0xEA # U+0x00EA + 'edieresis' => '600', # C+0xEB # U+0x00EB + 'igrave' => '600', # C+0xEC # U+0x00EC + 'iacute' => '600', # C+0xED # U+0x00ED + 'icircumflex' => '600', # C+0xEE # U+0x00EE + 'idieresis' => '600', # C+0xEF # U+0x00EF + 'eth' => '600', # C+0xF0 # U+0x00F0 + 'ntilde' => '600', # C+0xF1 # U+0x00F1 + 'ograve' => '600', # C+0xF2 # U+0x00F2 + 'oacute' => '600', # C+0xF3 # U+0x00F3 + 'ocircumflex' => '600', # C+0xF4 # U+0x00F4 + 'otilde' => '600', # C+0xF5 # U+0x00F5 + 'odieresis' => '600', # C+0xF6 # U+0x00F6 + 'divide' => '600', # C+0xF7 # U+0x00F7 + 'oslash' => '600', # C+0xF8 # U+0x00F8 + 'ugrave' => '600', # C+0xF9 # U+0x00F9 + 'uacute' => '600', # C+0xFA # U+0x00FA + 'ucircumflex' => '600', # C+0xFB # U+0x00FB + 'udieresis' => '600', # C+0xFC # U+0x00FC + 'yacute' => '600', # C+0xFD # U+0x00FD + 'thorn' => '600', # C+0xFE # U+0x00FE + 'ydieresis' => '600', # C+0xFF # U+0x00FF + 'dotlessi' => '600', # U+0x0131 + 'Lslash' => '600', # U+0x0141 + 'lslash' => '600', # U+0x0142 + 'caron' => '600', # U+0x02C7 + 'breve' => '600', # U+0x02D8 + 'dotaccent' => '600', # U+0x02D9 + 'ring' => '600', # U+0x02DA + 'ogonek' => '600', # U+0x02DB + 'hungarumlaut' => '600', # U+0x02DD + 'fraction' => '600', # U+0x2044 + 'minus' => '600', # U+0x2212 + 'fi' => '600', # U+0xFB01 + 'fl' => '600', # U+0xFB02 + }, # HORIZ. WIDTH TABLE +} }; + +1; diff --git a/lib/PDF/API2/Resource/Font/CoreFont/courieroblique.pm b/lib/PDF/API2/Resource/Font/CoreFont/courieroblique.pm new file mode 100644 index 0000000..00754dc --- /dev/null +++ b/lib/PDF/API2/Resource/Font/CoreFont/courieroblique.pm @@ -0,0 +1,520 @@ +#line 1 "PDF/API2/Resource/Font/CoreFont/courieroblique.pm" +#line 1 "PDF/API2/Resource/Font/CoreFont/courieroblique.pm" +package PDF::API2::Resource::Font::CoreFont::courieroblique; + +use strict; +use warnings; + +our $VERSION = '2.033'; # VERSION + +sub data { return { + 'fontname' => 'Courier-Oblique', + 'type' => 'Type1', + 'apiname' => 'CoIt', + 'ascender' => '629', + 'capheight' => '562', + 'descender' => '-157', + 'iscore' => '1', + 'isfixedpitch' => '1', + 'italicangle' => '-12', + 'missingwidth' => '600', + 'stdhw' => '51', + 'stdvw' => '51', + 'underlineposition' => '-100', + 'underlinethickness' => '50', + 'xheight' => '426', + 'firstchar' => '32', + 'lastchar' => '255', + 'char' => [ # DEF. ENCODING GLYPH TABLE + '.notdef', # C+0x00 # U+0x0000 + '.notdef', # C+0x01 # U+0x0000 + '.notdef', # C+0x02 # U+0x0000 + '.notdef', # C+0x03 # U+0x0000 + '.notdef', # C+0x04 # U+0x0000 + '.notdef', # C+0x05 # U+0x0000 + '.notdef', # C+0x06 # U+0x0000 + '.notdef', # C+0x07 # U+0x0000 + '.notdef', # C+0x08 # U+0x0000 + '.notdef', # C+0x09 # U+0x0000 + '.notdef', # C+0x0A # U+0x0000 + '.notdef', # C+0x0B # U+0x0000 + '.notdef', # C+0x0C # U+0x0000 + '.notdef', # C+0x0D # U+0x0000 + '.notdef', # C+0x0E # U+0x0000 + '.notdef', # C+0x0F # U+0x0000 + '.notdef', # C+0x10 # U+0x0000 + '.notdef', # C+0x11 # U+0x0000 + '.notdef', # C+0x12 # U+0x0000 + '.notdef', # C+0x13 # U+0x0000 + '.notdef', # C+0x14 # U+0x0000 + '.notdef', # C+0x15 # U+0x0000 + '.notdef', # C+0x16 # U+0x0000 + '.notdef', # C+0x17 # U+0x0000 + '.notdef', # C+0x18 # U+0x0000 + '.notdef', # C+0x19 # U+0x0000 + '.notdef', # C+0x1A # U+0x0000 + '.notdef', # C+0x1B # U+0x0000 + '.notdef', # C+0x1C # U+0x0000 + '.notdef', # C+0x1D # U+0x0000 + '.notdef', # C+0x1E # U+0x0000 + '.notdef', # C+0x1F # U+0x0000 + 'space', # C+0x20 # U+0x0020 + 'exclam', # C+0x21 # U+0x0021 + 'quotedbl', # C+0x22 # U+0x0022 + 'numbersign', # C+0x23 # U+0x0023 + 'dollar', # C+0x24 # U+0x0024 + 'percent', # C+0x25 # U+0x0025 + 'ampersand', # C+0x26 # U+0x0026 + 'quotesingle', # C+0x27 # U+0x0027 + 'parenleft', # C+0x28 # U+0x0028 + 'parenright', # C+0x29 # U+0x0029 + 'asterisk', # C+0x2A # U+0x002A + 'plus', # C+0x2B # U+0x002B + 'comma', # C+0x2C # U+0x002C + 'hyphen', # C+0x2D # U+0x002D + 'period', # C+0x2E # U+0x002E + 'slash', # C+0x2F # U+0x002F + 'zero', # C+0x30 # U+0x0030 + 'one', # C+0x31 # U+0x0031 + 'two', # C+0x32 # U+0x0032 + 'three', # C+0x33 # U+0x0033 + 'four', # C+0x34 # U+0x0034 + 'five', # C+0x35 # U+0x0035 + 'six', # C+0x36 # U+0x0036 + 'seven', # C+0x37 # U+0x0037 + 'eight', # C+0x38 # U+0x0038 + 'nine', # C+0x39 # U+0x0039 + 'colon', # C+0x3A # U+0x003A + 'semicolon', # C+0x3B # U+0x003B + 'less', # C+0x3C # U+0x003C + 'equal', # C+0x3D # U+0x003D + 'greater', # C+0x3E # U+0x003E + 'question', # C+0x3F # U+0x003F + 'at', # C+0x40 # U+0x0040 + 'A', # C+0x41 # U+0x0041 + 'B', # C+0x42 # U+0x0042 + 'C', # C+0x43 # U+0x0043 + 'D', # C+0x44 # U+0x0044 + 'E', # C+0x45 # U+0x0045 + 'F', # C+0x46 # U+0x0046 + 'G', # C+0x47 # U+0x0047 + 'H', # C+0x48 # U+0x0048 + 'I', # C+0x49 # U+0x0049 + 'J', # C+0x4A # U+0x004A + 'K', # C+0x4B # U+0x004B + 'L', # C+0x4C # U+0x004C + 'M', # C+0x4D # U+0x004D + 'N', # C+0x4E # U+0x004E + 'O', # C+0x4F # U+0x004F + 'P', # C+0x50 # U+0x0050 + 'Q', # C+0x51 # U+0x0051 + 'R', # C+0x52 # U+0x0052 + 'S', # C+0x53 # U+0x0053 + 'T', # C+0x54 # U+0x0054 + 'U', # C+0x55 # U+0x0055 + 'V', # C+0x56 # U+0x0056 + 'W', # C+0x57 # U+0x0057 + 'X', # C+0x58 # U+0x0058 + 'Y', # C+0x59 # U+0x0059 + 'Z', # C+0x5A # U+0x005A + 'bracketleft', # C+0x5B # U+0x005B + 'backslash', # C+0x5C # U+0x005C + 'bracketright', # C+0x5D # U+0x005D + 'asciicircum', # C+0x5E # U+0x005E + 'underscore', # C+0x5F # U+0x005F + 'grave', # C+0x60 # U+0x0060 + 'a', # C+0x61 # U+0x0061 + 'b', # C+0x62 # U+0x0062 + 'c', # C+0x63 # U+0x0063 + 'd', # C+0x64 # U+0x0064 + 'e', # C+0x65 # U+0x0065 + 'f', # C+0x66 # U+0x0066 + 'g', # C+0x67 # U+0x0067 + 'h', # C+0x68 # U+0x0068 + 'i', # C+0x69 # U+0x0069 + 'j', # C+0x6A # U+0x006A + 'k', # C+0x6B # U+0x006B + 'l', # C+0x6C # U+0x006C + 'm', # C+0x6D # U+0x006D + 'n', # C+0x6E # U+0x006E + 'o', # C+0x6F # U+0x006F + 'p', # C+0x70 # U+0x0070 + 'q', # C+0x71 # U+0x0071 + 'r', # C+0x72 # U+0x0072 + 's', # C+0x73 # U+0x0073 + 't', # C+0x74 # U+0x0074 + 'u', # C+0x75 # U+0x0075 + 'v', # C+0x76 # U+0x0076 + 'w', # C+0x77 # U+0x0077 + 'x', # C+0x78 # U+0x0078 + 'y', # C+0x79 # U+0x0079 + 'z', # C+0x7A # U+0x007A + 'braceleft', # C+0x7B # U+0x007B + 'bar', # C+0x7C # U+0x007C + 'braceright', # C+0x7D # U+0x007D + 'asciitilde', # C+0x7E # U+0x007E + 'bullet', # C+0x7F # U+0x2022 + 'Euro', # C+0x80 # U+0x20AC + 'bullet', # C+0x81 # U+0x2022 + 'quotesinglbase', # C+0x82 # U+0x201A + 'florin', # C+0x83 # U+0x0192 + 'quotedblbase', # C+0x84 # U+0x201E + 'ellipsis', # C+0x85 # U+0x2026 + 'dagger', # C+0x86 # U+0x2020 + 'daggerdbl', # C+0x87 # U+0x2021 + 'circumflex', # C+0x88 # U+0x02C6 + 'perthousand', # C+0x89 # U+0x2030 + 'Scaron', # C+0x8A # U+0x0160 + 'guilsinglleft', # C+0x8B # U+0x2039 + 'OE', # C+0x8C # U+0x0152 + 'bullet', # C+0x8D # U+0x2022 + 'Zcaron', # C+0x8E # U+0x017D + 'bullet', # C+0x8F # U+0x2022 + 'bullet', # C+0x90 # U+0x2022 + 'quoteleft', # C+0x91 # U+0x2018 + 'quoteright', # C+0x92 # U+0x2019 + 'quotedblleft', # C+0x93 # U+0x201C + 'quotedblright', # C+0x94 # U+0x201D + 'bullet', # C+0x95 # U+0x2022 + 'endash', # C+0x96 # U+0x2013 + 'emdash', # C+0x97 # U+0x2014 + 'tilde', # C+0x98 # U+0x02DC + 'trademark', # C+0x99 # U+0x2122 + 'scaron', # C+0x9A # U+0x0161 + 'guilsinglright', # C+0x9B # U+0x203A + 'oe', # C+0x9C # U+0x0153 + 'bullet', # C+0x9D # U+0x2022 + 'zcaron', # C+0x9E # U+0x017E + 'Ydieresis', # C+0x9F # U+0x0178 + 'space', # C+0xA0 # U+0x0020 + 'exclamdown', # C+0xA1 # U+0x00A1 + 'cent', # C+0xA2 # U+0x00A2 + 'sterling', # C+0xA3 # U+0x00A3 + 'currency', # C+0xA4 # U+0x00A4 + 'yen', # C+0xA5 # U+0x00A5 + 'brokenbar', # C+0xA6 # U+0x00A6 + 'section', # C+0xA7 # U+0x00A7 + 'dieresis', # C+0xA8 # U+0x00A8 + 'copyright', # C+0xA9 # U+0x00A9 + 'ordfeminine', # C+0xAA # U+0x00AA + 'guillemotleft', # C+0xAB # U+0x00AB + 'logicalnot', # C+0xAC # U+0x00AC + 'hyphen', # C+0xAD # U+0x002D + 'registered', # C+0xAE # U+0x00AE + 'macron', # C+0xAF # U+0x00AF + 'degree', # C+0xB0 # U+0x00B0 + 'plusminus', # C+0xB1 # U+0x00B1 + 'twosuperior', # C+0xB2 # U+0x00B2 + 'threesuperior', # C+0xB3 # U+0x00B3 + 'acute', # C+0xB4 # U+0x00B4 + 'mu', # C+0xB5 # U+0x00B5 + 'paragraph', # C+0xB6 # U+0x00B6 + 'periodcentered', # C+0xB7 # U+0x00B7 + 'cedilla', # C+0xB8 # U+0x00B8 + 'onesuperior', # C+0xB9 # U+0x00B9 + 'ordmasculine', # C+0xBA # U+0x00BA + 'guillemotright', # C+0xBB # U+0x00BB + 'onequarter', # C+0xBC # U+0x00BC + 'onehalf', # C+0xBD # U+0x00BD + 'threequarters', # C+0xBE # U+0x00BE + 'questiondown', # C+0xBF # U+0x00BF + 'Agrave', # C+0xC0 # U+0x00C0 + 'Aacute', # C+0xC1 # U+0x00C1 + 'Acircumflex', # C+0xC2 # U+0x00C2 + 'Atilde', # C+0xC3 # U+0x00C3 + 'Adieresis', # C+0xC4 # U+0x00C4 + 'Aring', # C+0xC5 # U+0x00C5 + 'AE', # C+0xC6 # U+0x00C6 + 'Ccedilla', # C+0xC7 # U+0x00C7 + 'Egrave', # C+0xC8 # U+0x00C8 + 'Eacute', # C+0xC9 # U+0x00C9 + 'Ecircumflex', # C+0xCA # U+0x00CA + 'Edieresis', # C+0xCB # U+0x00CB + 'Igrave', # C+0xCC # U+0x00CC + 'Iacute', # C+0xCD # U+0x00CD + 'Icircumflex', # C+0xCE # U+0x00CE + 'Idieresis', # C+0xCF # U+0x00CF + 'Eth', # C+0xD0 # U+0x00D0 + 'Ntilde', # C+0xD1 # U+0x00D1 + 'Ograve', # C+0xD2 # U+0x00D2 + 'Oacute', # C+0xD3 # U+0x00D3 + 'Ocircumflex', # C+0xD4 # U+0x00D4 + 'Otilde', # C+0xD5 # U+0x00D5 + 'Odieresis', # C+0xD6 # U+0x00D6 + 'multiply', # C+0xD7 # U+0x00D7 + 'Oslash', # C+0xD8 # U+0x00D8 + 'Ugrave', # C+0xD9 # U+0x00D9 + 'Uacute', # C+0xDA # U+0x00DA + 'Ucircumflex', # C+0xDB # U+0x00DB + 'Udieresis', # C+0xDC # U+0x00DC + 'Yacute', # C+0xDD # U+0x00DD + 'Thorn', # C+0xDE # U+0x00DE + 'germandbls', # C+0xDF # U+0x00DF + 'agrave', # C+0xE0 # U+0x00E0 + 'aacute', # C+0xE1 # U+0x00E1 + 'acircumflex', # C+0xE2 # U+0x00E2 + 'atilde', # C+0xE3 # U+0x00E3 + 'adieresis', # C+0xE4 # U+0x00E4 + 'aring', # C+0xE5 # U+0x00E5 + 'ae', # C+0xE6 # U+0x00E6 + 'ccedilla', # C+0xE7 # U+0x00E7 + 'egrave', # C+0xE8 # U+0x00E8 + 'eacute', # C+0xE9 # U+0x00E9 + 'ecircumflex', # C+0xEA # U+0x00EA + 'edieresis', # C+0xEB # U+0x00EB + 'igrave', # C+0xEC # U+0x00EC + 'iacute', # C+0xED # U+0x00ED + 'icircumflex', # C+0xEE # U+0x00EE + 'idieresis', # C+0xEF # U+0x00EF + 'eth', # C+0xF0 # U+0x00F0 + 'ntilde', # C+0xF1 # U+0x00F1 + 'ograve', # C+0xF2 # U+0x00F2 + 'oacute', # C+0xF3 # U+0x00F3 + 'ocircumflex', # C+0xF4 # U+0x00F4 + 'otilde', # C+0xF5 # U+0x00F5 + 'odieresis', # C+0xF6 # U+0x00F6 + 'divide', # C+0xF7 # U+0x00F7 + 'oslash', # C+0xF8 # U+0x00F8 + 'ugrave', # C+0xF9 # U+0x00F9 + 'uacute', # C+0xFA # U+0x00FA + 'ucircumflex', # C+0xFB # U+0x00FB + 'udieresis', # C+0xFC # U+0x00FC + 'yacute', # C+0xFD # U+0x00FD + 'thorn', # C+0xFE # U+0x00FE + 'ydieresis', # C+0xFF # U+0x00FF + ], # DEF. ENCODING GLYPH TABLE + 'fontbbox' => [ -27, -250, 849, 805 ], + 'wx' => { # HORIZ. WIDTH TABLE + 'space' => '600', # C+0x20 # U+0x0020 + 'exclam' => '600', # C+0x21 # U+0x0021 + 'quotedbl' => '600', # C+0x22 # U+0x0022 + 'numbersign' => '600', # C+0x23 # U+0x0023 + 'dollar' => '600', # C+0x24 # U+0x0024 + 'percent' => '600', # C+0x25 # U+0x0025 + 'ampersand' => '600', # C+0x26 # U+0x0026 + 'quotesingle' => '600', # C+0x27 # U+0x0027 + 'parenleft' => '600', # C+0x28 # U+0x0028 + 'parenright' => '600', # C+0x29 # U+0x0029 + 'asterisk' => '600', # C+0x2A # U+0x002A + 'plus' => '600', # C+0x2B # U+0x002B + 'comma' => '600', # C+0x2C # U+0x002C + 'hyphen' => '600', # C+0x2D # U+0x002D + 'period' => '600', # C+0x2E # U+0x002E + 'slash' => '600', # C+0x2F # U+0x002F + 'zero' => '600', # C+0x30 # U+0x0030 + 'one' => '600', # C+0x31 # U+0x0031 + 'two' => '600', # C+0x32 # U+0x0032 + 'three' => '600', # C+0x33 # U+0x0033 + 'four' => '600', # C+0x34 # U+0x0034 + 'five' => '600', # C+0x35 # U+0x0035 + 'six' => '600', # C+0x36 # U+0x0036 + 'seven' => '600', # C+0x37 # U+0x0037 + 'eight' => '600', # C+0x38 # U+0x0038 + 'nine' => '600', # C+0x39 # U+0x0039 + 'colon' => '600', # C+0x3A # U+0x003A + 'semicolon' => '600', # C+0x3B # U+0x003B + 'less' => '600', # C+0x3C # U+0x003C + 'equal' => '600', # C+0x3D # U+0x003D + 'greater' => '600', # C+0x3E # U+0x003E + 'question' => '600', # C+0x3F # U+0x003F + 'at' => '600', # C+0x40 # U+0x0040 + 'A' => '600', # C+0x41 # U+0x0041 + 'B' => '600', # C+0x42 # U+0x0042 + 'C' => '600', # C+0x43 # U+0x0043 + 'D' => '600', # C+0x44 # U+0x0044 + 'E' => '600', # C+0x45 # U+0x0045 + 'F' => '600', # C+0x46 # U+0x0046 + 'G' => '600', # C+0x47 # U+0x0047 + 'H' => '600', # C+0x48 # U+0x0048 + 'I' => '600', # C+0x49 # U+0x0049 + 'J' => '600', # C+0x4A # U+0x004A + 'K' => '600', # C+0x4B # U+0x004B + 'L' => '600', # C+0x4C # U+0x004C + 'M' => '600', # C+0x4D # U+0x004D + 'N' => '600', # C+0x4E # U+0x004E + 'O' => '600', # C+0x4F # U+0x004F + 'P' => '600', # C+0x50 # U+0x0050 + 'Q' => '600', # C+0x51 # U+0x0051 + 'R' => '600', # C+0x52 # U+0x0052 + 'S' => '600', # C+0x53 # U+0x0053 + 'T' => '600', # C+0x54 # U+0x0054 + 'U' => '600', # C+0x55 # U+0x0055 + 'V' => '600', # C+0x56 # U+0x0056 + 'W' => '600', # C+0x57 # U+0x0057 + 'X' => '600', # C+0x58 # U+0x0058 + 'Y' => '600', # C+0x59 # U+0x0059 + 'Z' => '600', # C+0x5A # U+0x005A + 'bracketleft' => '600', # C+0x5B # U+0x005B + 'backslash' => '600', # C+0x5C # U+0x005C + 'bracketright' => '600', # C+0x5D # U+0x005D + 'asciicircum' => '600', # C+0x5E # U+0x005E + 'underscore' => '600', # C+0x5F # U+0x005F + 'grave' => '600', # C+0x60 # U+0x0060 + 'a' => '600', # C+0x61 # U+0x0061 + 'b' => '600', # C+0x62 # U+0x0062 + 'c' => '600', # C+0x63 # U+0x0063 + 'd' => '600', # C+0x64 # U+0x0064 + 'e' => '600', # C+0x65 # U+0x0065 + 'f' => '600', # C+0x66 # U+0x0066 + 'g' => '600', # C+0x67 # U+0x0067 + 'h' => '600', # C+0x68 # U+0x0068 + 'i' => '600', # C+0x69 # U+0x0069 + 'j' => '600', # C+0x6A # U+0x006A + 'k' => '600', # C+0x6B # U+0x006B + 'l' => '600', # C+0x6C # U+0x006C + 'm' => '600', # C+0x6D # U+0x006D + 'n' => '600', # C+0x6E # U+0x006E + 'o' => '600', # C+0x6F # U+0x006F + 'p' => '600', # C+0x70 # U+0x0070 + 'q' => '600', # C+0x71 # U+0x0071 + 'r' => '600', # C+0x72 # U+0x0072 + 's' => '600', # C+0x73 # U+0x0073 + 't' => '600', # C+0x74 # U+0x0074 + 'u' => '600', # C+0x75 # U+0x0075 + 'v' => '600', # C+0x76 # U+0x0076 + 'w' => '600', # C+0x77 # U+0x0077 + 'x' => '600', # C+0x78 # U+0x0078 + 'y' => '600', # C+0x79 # U+0x0079 + 'z' => '600', # C+0x7A # U+0x007A + 'braceleft' => '600', # C+0x7B # U+0x007B + 'bar' => '600', # C+0x7C # U+0x007C + 'braceright' => '600', # C+0x7D # U+0x007D + 'asciitilde' => '600', # C+0x7E # U+0x007E + 'bullet' => '600', # C+0x7F # U+0x2022 + 'Euro' => '600', # C+0x80 # U+0x20AC + 'quotesinglbase' => '600', # C+0x82 # U+0x201A + 'florin' => '600', # C+0x83 # U+0x0192 + 'quotedblbase' => '600', # C+0x84 # U+0x201E + 'ellipsis' => '600', # C+0x85 # U+0x2026 + 'dagger' => '600', # C+0x86 # U+0x2020 + 'daggerdbl' => '600', # C+0x87 # U+0x2021 + 'circumflex' => '600', # C+0x88 # U+0x02C6 + 'perthousand' => '600', # C+0x89 # U+0x2030 + 'Scaron' => '600', # C+0x8A # U+0x0160 + 'guilsinglleft' => '600', # C+0x8B # U+0x2039 + 'OE' => '600', # C+0x8C # U+0x0152 + 'Zcaron' => '600', # C+0x8E # U+0x017D + 'quoteleft' => '600', # C+0x91 # U+0x2018 + 'quoteright' => '600', # C+0x92 # U+0x2019 + 'quotedblleft' => '600', # C+0x93 # U+0x201C + 'quotedblright' => '600', # C+0x94 # U+0x201D + 'endash' => '600', # C+0x96 # U+0x2013 + 'emdash' => '600', # C+0x97 # U+0x2014 + 'tilde' => '600', # C+0x98 # U+0x02DC + 'trademark' => '600', # C+0x99 # U+0x2122 + 'scaron' => '600', # C+0x9A # U+0x0161 + 'guilsinglright' => '600', # C+0x9B # U+0x203A + 'oe' => '600', # C+0x9C # U+0x0153 + 'zcaron' => '600', # C+0x9E # U+0x017E + 'Ydieresis' => '600', # C+0x9F # U+0x0178 + 'exclamdown' => '600', # C+0xA1 # U+0x00A1 + 'cent' => '600', # C+0xA2 # U+0x00A2 + 'sterling' => '600', # C+0xA3 # U+0x00A3 + 'currency' => '600', # C+0xA4 # U+0x00A4 + 'yen' => '600', # C+0xA5 # U+0x00A5 + 'brokenbar' => '600', # C+0xA6 # U+0x00A6 + 'section' => '600', # C+0xA7 # U+0x00A7 + 'dieresis' => '600', # C+0xA8 # U+0x00A8 + 'copyright' => '600', # C+0xA9 # U+0x00A9 + 'ordfeminine' => '600', # C+0xAA # U+0x00AA + 'guillemotleft' => '600', # C+0xAB # U+0x00AB + 'logicalnot' => '600', # C+0xAC # U+0x00AC + 'registered' => '600', # C+0xAE # U+0x00AE + 'macron' => '600', # C+0xAF # U+0x00AF + 'degree' => '600', # C+0xB0 # U+0x00B0 + 'plusminus' => '600', # C+0xB1 # U+0x00B1 + 'twosuperior' => '600', # C+0xB2 # U+0x00B2 + 'threesuperior' => '600', # C+0xB3 # U+0x00B3 + 'acute' => '600', # C+0xB4 # U+0x00B4 + 'mu' => '600', # C+0xB5 # U+0x00B5 + 'paragraph' => '600', # C+0xB6 # U+0x00B6 + 'periodcentered' => '600', # C+0xB7 # U+0x00B7 + 'cedilla' => '600', # C+0xB8 # U+0x00B8 + 'onesuperior' => '600', # C+0xB9 # U+0x00B9 + 'ordmasculine' => '600', # C+0xBA # U+0x00BA + 'guillemotright' => '600', # C+0xBB # U+0x00BB + 'onequarter' => '600', # C+0xBC # U+0x00BC + 'onehalf' => '600', # C+0xBD # U+0x00BD + 'threequarters' => '600', # C+0xBE # U+0x00BE + 'questiondown' => '600', # C+0xBF # U+0x00BF + 'Agrave' => '600', # C+0xC0 # U+0x00C0 + 'Aacute' => '600', # C+0xC1 # U+0x00C1 + 'Acircumflex' => '600', # C+0xC2 # U+0x00C2 + 'Atilde' => '600', # C+0xC3 # U+0x00C3 + 'Adieresis' => '600', # C+0xC4 # U+0x00C4 + 'Aring' => '600', # C+0xC5 # U+0x00C5 + 'AE' => '600', # C+0xC6 # U+0x00C6 + 'Ccedilla' => '600', # C+0xC7 # U+0x00C7 + 'Egrave' => '600', # C+0xC8 # U+0x00C8 + 'Eacute' => '600', # C+0xC9 # U+0x00C9 + 'Ecircumflex' => '600', # C+0xCA # U+0x00CA + 'Edieresis' => '600', # C+0xCB # U+0x00CB + 'Igrave' => '600', # C+0xCC # U+0x00CC + 'Iacute' => '600', # C+0xCD # U+0x00CD + 'Icircumflex' => '600', # C+0xCE # U+0x00CE + 'Idieresis' => '600', # C+0xCF # U+0x00CF + 'Eth' => '600', # C+0xD0 # U+0x00D0 + 'Ntilde' => '600', # C+0xD1 # U+0x00D1 + 'Ograve' => '600', # C+0xD2 # U+0x00D2 + 'Oacute' => '600', # C+0xD3 # U+0x00D3 + 'Ocircumflex' => '600', # C+0xD4 # U+0x00D4 + 'Otilde' => '600', # C+0xD5 # U+0x00D5 + 'Odieresis' => '600', # C+0xD6 # U+0x00D6 + 'multiply' => '600', # C+0xD7 # U+0x00D7 + 'Oslash' => '600', # C+0xD8 # U+0x00D8 + 'Ugrave' => '600', # C+0xD9 # U+0x00D9 + 'Uacute' => '600', # C+0xDA # U+0x00DA + 'Ucircumflex' => '600', # C+0xDB # U+0x00DB + 'Udieresis' => '600', # C+0xDC # U+0x00DC + 'Yacute' => '600', # C+0xDD # U+0x00DD + 'Thorn' => '600', # C+0xDE # U+0x00DE + 'germandbls' => '600', # C+0xDF # U+0x00DF + 'agrave' => '600', # C+0xE0 # U+0x00E0 + 'aacute' => '600', # C+0xE1 # U+0x00E1 + 'acircumflex' => '600', # C+0xE2 # U+0x00E2 + 'atilde' => '600', # C+0xE3 # U+0x00E3 + 'adieresis' => '600', # C+0xE4 # U+0x00E4 + 'aring' => '600', # C+0xE5 # U+0x00E5 + 'ae' => '600', # C+0xE6 # U+0x00E6 + 'ccedilla' => '600', # C+0xE7 # U+0x00E7 + 'egrave' => '600', # C+0xE8 # U+0x00E8 + 'eacute' => '600', # C+0xE9 # U+0x00E9 + 'ecircumflex' => '600', # C+0xEA # U+0x00EA + 'edieresis' => '600', # C+0xEB # U+0x00EB + 'igrave' => '600', # C+0xEC # U+0x00EC + 'iacute' => '600', # C+0xED # U+0x00ED + 'icircumflex' => '600', # C+0xEE # U+0x00EE + 'idieresis' => '600', # C+0xEF # U+0x00EF + 'eth' => '600', # C+0xF0 # U+0x00F0 + 'ntilde' => '600', # C+0xF1 # U+0x00F1 + 'ograve' => '600', # C+0xF2 # U+0x00F2 + 'oacute' => '600', # C+0xF3 # U+0x00F3 + 'ocircumflex' => '600', # C+0xF4 # U+0x00F4 + 'otilde' => '600', # C+0xF5 # U+0x00F5 + 'odieresis' => '600', # C+0xF6 # U+0x00F6 + 'divide' => '600', # C+0xF7 # U+0x00F7 + 'oslash' => '600', # C+0xF8 # U+0x00F8 + 'ugrave' => '600', # C+0xF9 # U+0x00F9 + 'uacute' => '600', # C+0xFA # U+0x00FA + 'ucircumflex' => '600', # C+0xFB # U+0x00FB + 'udieresis' => '600', # C+0xFC # U+0x00FC + 'yacute' => '600', # C+0xFD # U+0x00FD + 'thorn' => '600', # C+0xFE # U+0x00FE + 'ydieresis' => '600', # C+0xFF # U+0x00FF + 'dotlessi' => '600', # U+0x0131 + 'Lslash' => '600', # U+0x0141 + 'lslash' => '600', # U+0x0142 + 'caron' => '600', # U+0x02C7 + 'breve' => '600', # U+0x02D8 + 'dotaccent' => '600', # U+0x02D9 + 'ring' => '600', # U+0x02DA + 'ogonek' => '600', # U+0x02DB + 'hungarumlaut' => '600', # U+0x02DD + 'fraction' => '600', # U+0x2044 + 'minus' => '600', # U+0x2212 + 'fi' => '600', # U+0xFB01 + 'fl' => '600', # U+0xFB02 + }, # HORIZ. WIDTH TABLE +} }; + +1; diff --git a/lib/PDF/API2/Resource/Font/CoreFont/georgia.pm b/lib/PDF/API2/Resource/Font/CoreFont/georgia.pm new file mode 100644 index 0000000..3c3c608 --- /dev/null +++ b/lib/PDF/API2/Resource/Font/CoreFont/georgia.pm @@ -0,0 +1,863 @@ +#line 1 "PDF/API2/Resource/Font/CoreFont/georgia.pm" +#line 1 "PDF/API2/Resource/Font/CoreFont/georgia.pm" +package PDF::API2::Resource::Font::CoreFont::georgia; + +use strict; +use warnings; + +our $VERSION = '2.033'; # VERSION + +sub data { return { + 'fontname' => 'Georgia', + 'type' => 'TrueType', + 'apiname' => 'Geor', + 'ascender' => '916', + 'capheight' => '692', + 'descender' => '-219', + 'isfixedpitch' => '0', + 'issymbol' => '0', + 'italicangle' => '0', + 'underlineposition' => '-181', + 'underlinethickness' => '101', + 'xheight' => '481', + 'firstchar' => '32', + 'lastchar' => '255', + 'flags' => '34', + 'char' => [ # DEF. ENCODING GLYPH TABLE + '.notdef', # C+0x00 # U+0x0000 + '.notdef', # C+0x01 # U+0x0000 + '.notdef', # C+0x02 # U+0x0000 + '.notdef', # C+0x03 # U+0x0000 + '.notdef', # C+0x04 # U+0x0000 + '.notdef', # C+0x05 # U+0x0000 + '.notdef', # C+0x06 # U+0x0000 + '.notdef', # C+0x07 # U+0x0000 + '.notdef', # C+0x08 # U+0x0000 + '.notdef', # C+0x09 # U+0x0000 + '.notdef', # C+0x0A # U+0x0000 + '.notdef', # C+0x0B # U+0x0000 + '.notdef', # C+0x0C # U+0x0000 + '.notdef', # C+0x0D # U+0x0000 + '.notdef', # C+0x0E # U+0x0000 + '.notdef', # C+0x0F # U+0x0000 + '.notdef', # C+0x10 # U+0x0000 + '.notdef', # C+0x11 # U+0x0000 + '.notdef', # C+0x12 # U+0x0000 + '.notdef', # C+0x13 # U+0x0000 + '.notdef', # C+0x14 # U+0x0000 + '.notdef', # C+0x15 # U+0x0000 + '.notdef', # C+0x16 # U+0x0000 + '.notdef', # C+0x17 # U+0x0000 + '.notdef', # C+0x18 # U+0x0000 + '.notdef', # C+0x19 # U+0x0000 + '.notdef', # C+0x1A # U+0x0000 + '.notdef', # C+0x1B # U+0x0000 + '.notdef', # C+0x1C # U+0x0000 + '.notdef', # C+0x1D # U+0x0000 + '.notdef', # C+0x1E # U+0x0000 + '.notdef', # C+0x1F # U+0x0000 + 'space', # C+0x20 # U+0x0020 + 'exclam', # C+0x21 # U+0x0021 + 'quotedbl', # C+0x22 # U+0x0022 + 'numbersign', # C+0x23 # U+0x0023 + 'dollar', # C+0x24 # U+0x0024 + 'percent', # C+0x25 # U+0x0025 + 'ampersand', # C+0x26 # U+0x0026 + 'quotesingle', # C+0x27 # U+0x0027 + 'parenleft', # C+0x28 # U+0x0028 + 'parenright', # C+0x29 # U+0x0029 + 'asterisk', # C+0x2A # U+0x002A + 'plus', # C+0x2B # U+0x002B + 'comma', # C+0x2C # U+0x002C + 'hyphen', # C+0x2D # U+0x002D + 'period', # C+0x2E # U+0x002E + 'slash', # C+0x2F # U+0x002F + 'zero', # C+0x30 # U+0x0030 + 'one', # C+0x31 # U+0x0031 + 'two', # C+0x32 # U+0x0032 + 'three', # C+0x33 # U+0x0033 + 'four', # C+0x34 # U+0x0034 + 'five', # C+0x35 # U+0x0035 + 'six', # C+0x36 # U+0x0036 + 'seven', # C+0x37 # U+0x0037 + 'eight', # C+0x38 # U+0x0038 + 'nine', # C+0x39 # U+0x0039 + 'colon', # C+0x3A # U+0x003A + 'semicolon', # C+0x3B # U+0x003B + 'less', # C+0x3C # U+0x003C + 'equal', # C+0x3D # U+0x003D + 'greater', # C+0x3E # U+0x003E + 'question', # C+0x3F # U+0x003F + 'at', # C+0x40 # U+0x0040 + 'A', # C+0x41 # U+0x0041 + 'B', # C+0x42 # U+0x0042 + 'C', # C+0x43 # U+0x0043 + 'D', # C+0x44 # U+0x0044 + 'E', # C+0x45 # U+0x0045 + 'F', # C+0x46 # U+0x0046 + 'G', # C+0x47 # U+0x0047 + 'H', # C+0x48 # U+0x0048 + 'I', # C+0x49 # U+0x0049 + 'J', # C+0x4A # U+0x004A + 'K', # C+0x4B # U+0x004B + 'L', # C+0x4C # U+0x004C + 'M', # C+0x4D # U+0x004D + 'N', # C+0x4E # U+0x004E + 'O', # C+0x4F # U+0x004F + 'P', # C+0x50 # U+0x0050 + 'Q', # C+0x51 # U+0x0051 + 'R', # C+0x52 # U+0x0052 + 'S', # C+0x53 # U+0x0053 + 'T', # C+0x54 # U+0x0054 + 'U', # C+0x55 # U+0x0055 + 'V', # C+0x56 # U+0x0056 + 'W', # C+0x57 # U+0x0057 + 'X', # C+0x58 # U+0x0058 + 'Y', # C+0x59 # U+0x0059 + 'Z', # C+0x5A # U+0x005A + 'bracketleft', # C+0x5B # U+0x005B + 'backslash', # C+0x5C # U+0x005C + 'bracketright', # C+0x5D # U+0x005D + 'asciicircum', # C+0x5E # U+0x005E + 'underscore', # C+0x5F # U+0x005F + 'grave', # C+0x60 # U+0x0060 + 'a', # C+0x61 # U+0x0061 + 'b', # C+0x62 # U+0x0062 + 'c', # C+0x63 # U+0x0063 + 'd', # C+0x64 # U+0x0064 + 'e', # C+0x65 # U+0x0065 + 'f', # C+0x66 # U+0x0066 + 'g', # C+0x67 # U+0x0067 + 'h', # C+0x68 # U+0x0068 + 'i', # C+0x69 # U+0x0069 + 'j', # C+0x6A # U+0x006A + 'k', # C+0x6B # U+0x006B + 'l', # C+0x6C # U+0x006C + 'm', # C+0x6D # U+0x006D + 'n', # C+0x6E # U+0x006E + 'o', # C+0x6F # U+0x006F + 'p', # C+0x70 # U+0x0070 + 'q', # C+0x71 # U+0x0071 + 'r', # C+0x72 # U+0x0072 + 's', # C+0x73 # U+0x0073 + 't', # C+0x74 # U+0x0074 + 'u', # C+0x75 # U+0x0075 + 'v', # C+0x76 # U+0x0076 + 'w', # C+0x77 # U+0x0077 + 'x', # C+0x78 # U+0x0078 + 'y', # C+0x79 # U+0x0079 + 'z', # C+0x7A # U+0x007A + 'braceleft', # C+0x7B # U+0x007B + 'bar', # C+0x7C # U+0x007C + 'braceright', # C+0x7D # U+0x007D + 'asciitilde', # C+0x7E # U+0x007E + 'bullet', # C+0x7F # U+0x2022 + 'Euro', # C+0x80 # U+0x20AC + 'bullet', # C+0x81 # U+0x2022 + 'quotesinglbase', # C+0x82 # U+0x201A + 'florin', # C+0x83 # U+0x0192 + 'quotedblbase', # C+0x84 # U+0x201E + 'ellipsis', # C+0x85 # U+0x2026 + 'dagger', # C+0x86 # U+0x2020 + 'daggerdbl', # C+0x87 # U+0x2021 + 'circumflex', # C+0x88 # U+0x02C6 + 'perthousand', # C+0x89 # U+0x2030 + 'Scaron', # C+0x8A # U+0x0160 + 'guilsinglleft', # C+0x8B # U+0x2039 + 'OE', # C+0x8C # U+0x0152 + 'bullet', # C+0x8D # U+0x2022 + 'Zcaron', # C+0x8E # U+0x017D + 'bullet', # C+0x8F # U+0x2022 + 'bullet', # C+0x90 # U+0x2022 + 'quoteleft', # C+0x91 # U+0x2018 + 'quoteright', # C+0x92 # U+0x2019 + 'quotedblleft', # C+0x93 # U+0x201C + 'quotedblright', # C+0x94 # U+0x201D + 'bullet', # C+0x95 # U+0x2022 + 'endash', # C+0x96 # U+0x2013 + 'emdash', # C+0x97 # U+0x2014 + 'tilde', # C+0x98 # U+0x02DC + 'trademark', # C+0x99 # U+0x2122 + 'scaron', # C+0x9A # U+0x0161 + 'guilsinglright', # C+0x9B # U+0x203A + 'oe', # C+0x9C # U+0x0153 + 'bullet', # C+0x9D # U+0x2022 + 'zcaron', # C+0x9E # U+0x017E + 'Ydieresis', # C+0x9F # U+0x0178 + 'space', # C+0xA0 # U+0x0020 + 'exclamdown', # C+0xA1 # U+0x00A1 + 'cent', # C+0xA2 # U+0x00A2 + 'sterling', # C+0xA3 # U+0x00A3 + 'currency', # C+0xA4 # U+0x00A4 + 'yen', # C+0xA5 # U+0x00A5 + 'brokenbar', # C+0xA6 # U+0x00A6 + 'section', # C+0xA7 # U+0x00A7 + 'dieresis', # C+0xA8 # U+0x00A8 + 'copyright', # C+0xA9 # U+0x00A9 + 'ordfeminine', # C+0xAA # U+0x00AA + 'guillemotleft', # C+0xAB # U+0x00AB + 'logicalnot', # C+0xAC # U+0x00AC + 'hyphen', # C+0xAD # U+0x002D + 'registered', # C+0xAE # U+0x00AE + 'macron', # C+0xAF # U+0x00AF + 'degree', # C+0xB0 # U+0x00B0 + 'plusminus', # C+0xB1 # U+0x00B1 + 'twosuperior', # C+0xB2 # U+0x00B2 + 'threesuperior', # C+0xB3 # U+0x00B3 + 'acute', # C+0xB4 # U+0x00B4 + 'mu', # C+0xB5 # U+0x00B5 + 'paragraph', # C+0xB6 # U+0x00B6 + 'periodcentered', # C+0xB7 # U+0x00B7 + 'cedilla', # C+0xB8 # U+0x00B8 + 'onesuperior', # C+0xB9 # U+0x00B9 + 'ordmasculine', # C+0xBA # U+0x00BA + 'guillemotright', # C+0xBB # U+0x00BB + 'onequarter', # C+0xBC # U+0x00BC + 'onehalf', # C+0xBD # U+0x00BD + 'threequarters', # C+0xBE # U+0x00BE + 'questiondown', # C+0xBF # U+0x00BF + 'Agrave', # C+0xC0 # U+0x00C0 + 'Aacute', # C+0xC1 # U+0x00C1 + 'Acircumflex', # C+0xC2 # U+0x00C2 + 'Atilde', # C+0xC3 # U+0x00C3 + 'Adieresis', # C+0xC4 # U+0x00C4 + 'Aring', # C+0xC5 # U+0x00C5 + 'AE', # C+0xC6 # U+0x00C6 + 'Ccedilla', # C+0xC7 # U+0x00C7 + 'Egrave', # C+0xC8 # U+0x00C8 + 'Eacute', # C+0xC9 # U+0x00C9 + 'Ecircumflex', # C+0xCA # U+0x00CA + 'Edieresis', # C+0xCB # U+0x00CB + 'Igrave', # C+0xCC # U+0x00CC + 'Iacute', # C+0xCD # U+0x00CD + 'Icircumflex', # C+0xCE # U+0x00CE + 'Idieresis', # C+0xCF # U+0x00CF + 'Eth', # C+0xD0 # U+0x00D0 + 'Ntilde', # C+0xD1 # U+0x00D1 + 'Ograve', # C+0xD2 # U+0x00D2 + 'Oacute', # C+0xD3 # U+0x00D3 + 'Ocircumflex', # C+0xD4 # U+0x00D4 + 'Otilde', # C+0xD5 # U+0x00D5 + 'Odieresis', # C+0xD6 # U+0x00D6 + 'multiply', # C+0xD7 # U+0x00D7 + 'Oslash', # C+0xD8 # U+0x00D8 + 'Ugrave', # C+0xD9 # U+0x00D9 + 'Uacute', # C+0xDA # U+0x00DA + 'Ucircumflex', # C+0xDB # U+0x00DB + 'Udieresis', # C+0xDC # U+0x00DC + 'Yacute', # C+0xDD # U+0x00DD + 'Thorn', # C+0xDE # U+0x00DE + 'germandbls', # C+0xDF # U+0x00DF + 'agrave', # C+0xE0 # U+0x00E0 + 'aacute', # C+0xE1 # U+0x00E1 + 'acircumflex', # C+0xE2 # U+0x00E2 + 'atilde', # C+0xE3 # U+0x00E3 + 'adieresis', # C+0xE4 # U+0x00E4 + 'aring', # C+0xE5 # U+0x00E5 + 'ae', # C+0xE6 # U+0x00E6 + 'ccedilla', # C+0xE7 # U+0x00E7 + 'egrave', # C+0xE8 # U+0x00E8 + 'eacute', # C+0xE9 # U+0x00E9 + 'ecircumflex', # C+0xEA # U+0x00EA + 'edieresis', # C+0xEB # U+0x00EB + 'igrave', # C+0xEC # U+0x00EC + 'iacute', # C+0xED # U+0x00ED + 'icircumflex', # C+0xEE # U+0x00EE + 'idieresis', # C+0xEF # U+0x00EF + 'eth', # C+0xF0 # U+0x00F0 + 'ntilde', # C+0xF1 # U+0x00F1 + 'ograve', # C+0xF2 # U+0x00F2 + 'oacute', # C+0xF3 # U+0x00F3 + 'ocircumflex', # C+0xF4 # U+0x00F4 + 'otilde', # C+0xF5 # U+0x00F5 + 'odieresis', # C+0xF6 # U+0x00F6 + 'divide', # C+0xF7 # U+0x00F7 + 'oslash', # C+0xF8 # U+0x00F8 + 'ugrave', # C+0xF9 # U+0x00F9 + 'uacute', # C+0xFA # U+0x00FA + 'ucircumflex', # C+0xFB # U+0x00FB + 'udieresis', # C+0xFC # U+0x00FC + 'yacute', # C+0xFD # U+0x00FD + 'thorn', # C+0xFE # U+0x00FE + 'ydieresis', # C+0xFF # U+0x00FF + ], # DEF. ENCODING GLYPH TABLE + 'fontbbox' => [ -173, -216, 1166, 912 ], + 'wx' => { # HORIZ. WIDTH TABLE + 'space' => '241', # C+0x20 # U+0x0020 + 'exclam' => '331', # C+0x21 # U+0x0021 + 'quotedbl' => '411', # C+0x22 # U+0x0022 + 'numbersign' => '643', # C+0x23 # U+0x0023 + 'dollar' => '609', # C+0x24 # U+0x0024 + 'percent' => '817', # C+0x25 # U+0x0025 + 'ampersand' => '710', # C+0x26 # U+0x0026 + 'quotesingle' => '215', # C+0x27 # U+0x0027 + 'parenleft' => '375', # C+0x28 # U+0x0028 + 'parenright' => '375', # C+0x29 # U+0x0029 + 'asterisk' => '472', # C+0x2A # U+0x002A + 'plus' => '643', # C+0x2B # U+0x002B + 'comma' => '269', # C+0x2C # U+0x002C + 'hyphen' => '374', # C+0x2D # U+0x002D + 'period' => '269', # C+0x2E # U+0x002E + 'slash' => '468', # C+0x2F # U+0x002F + 'zero' => '613', # C+0x30 # U+0x0030 + 'one' => '429', # C+0x31 # U+0x0031 + 'two' => '558', # C+0x32 # U+0x0032 + 'three' => '551', # C+0x33 # U+0x0033 + 'four' => '564', # C+0x34 # U+0x0034 + 'five' => '528', # C+0x35 # U+0x0035 + 'six' => '565', # C+0x36 # U+0x0036 + 'seven' => '502', # C+0x37 # U+0x0037 + 'eight' => '596', # C+0x38 # U+0x0038 + 'nine' => '565', # C+0x39 # U+0x0039 + 'colon' => '312', # C+0x3A # U+0x003A + 'semicolon' => '312', # C+0x3B # U+0x003B + 'less' => '643', # C+0x3C # U+0x003C + 'equal' => '643', # C+0x3D # U+0x003D + 'greater' => '643', # C+0x3E # U+0x003E + 'question' => '478', # C+0x3F # U+0x003F + 'at' => '928', # C+0x40 # U+0x0040 + 'A' => '670', # C+0x41 # U+0x0041 + 'B' => '653', # C+0x42 # U+0x0042 + 'C' => '642', # C+0x43 # U+0x0043 + 'D' => '749', # C+0x44 # U+0x0044 + 'E' => '653', # C+0x45 # U+0x0045 + 'F' => '599', # C+0x46 # U+0x0046 + 'G' => '725', # C+0x47 # U+0x0047 + 'H' => '814', # C+0x48 # U+0x0048 + 'I' => '389', # C+0x49 # U+0x0049 + 'J' => '517', # C+0x4A # U+0x004A + 'K' => '694', # C+0x4B # U+0x004B + 'L' => '603', # C+0x4C # U+0x004C + 'M' => '927', # C+0x4D # U+0x004D + 'N' => '767', # C+0x4E # U+0x004E + 'O' => '744', # C+0x4F # U+0x004F + 'P' => '609', # C+0x50 # U+0x0050 + 'Q' => '744', # C+0x51 # U+0x0051 + 'R' => '701', # C+0x52 # U+0x0052 + 'S' => '561', # C+0x53 # U+0x0053 + 'T' => '618', # C+0x54 # U+0x0054 + 'U' => '756', # C+0x55 # U+0x0055 + 'V' => '666', # C+0x56 # U+0x0056 + 'W' => '975', # C+0x57 # U+0x0057 + 'X' => '710', # C+0x58 # U+0x0058 + 'Y' => '615', # C+0x59 # U+0x0059 + 'Z' => '601', # C+0x5A # U+0x005A + 'bracketleft' => '375', # C+0x5B # U+0x005B + 'backslash' => '468', # C+0x5C # U+0x005C + 'bracketright' => '375', # C+0x5D # U+0x005D + 'asciicircum' => '643', # C+0x5E # U+0x005E + 'underscore' => '643', # C+0x5F # U+0x005F + 'grave' => '500', # C+0x60 # U+0x0060 + 'a' => '503', # C+0x61 # U+0x0061 + 'b' => '560', # C+0x62 # U+0x0062 + 'c' => '454', # C+0x63 # U+0x0063 + 'd' => '574', # C+0x64 # U+0x0064 + 'e' => '483', # C+0x65 # U+0x0065 + 'f' => '325', # C+0x66 # U+0x0066 + 'g' => '509', # C+0x67 # U+0x0067 + 'h' => '582', # C+0x68 # U+0x0068 + 'i' => '292', # C+0x69 # U+0x0069 + 'j' => '291', # C+0x6A # U+0x006A + 'k' => '535', # C+0x6B # U+0x006B + 'l' => '286', # C+0x6C # U+0x006C + 'm' => '880', # C+0x6D # U+0x006D + 'n' => '590', # C+0x6E # U+0x006E + 'o' => '539', # C+0x6F # U+0x006F + 'p' => '571', # C+0x70 # U+0x0070 + 'q' => '559', # C+0x71 # U+0x0071 + 'r' => '409', # C+0x72 # U+0x0072 + 's' => '432', # C+0x73 # U+0x0073 + 't' => '345', # C+0x74 # U+0x0074 + 'u' => '575', # C+0x75 # U+0x0075 + 'v' => '496', # C+0x76 # U+0x0076 + 'w' => '737', # C+0x77 # U+0x0077 + 'x' => '504', # C+0x78 # U+0x0078 + 'y' => '492', # C+0x79 # U+0x0079 + 'z' => '443', # C+0x7A # U+0x007A + 'braceleft' => '430', # C+0x7B # U+0x007B + 'bar' => '375', # C+0x7C # U+0x007C + 'braceright' => '430', # C+0x7D # U+0x007D + 'asciitilde' => '643', # C+0x7E # U+0x007E + 'bullet' => '392', # C+0x7F # U+0x2022 + 'Euro' => '642', # C+0x80 # U+0x20AC + 'quotesinglbase' => '226', # C+0x82 # U+0x201A + 'florin' => '519', # C+0x83 # U+0x0192 + 'quotedblbase' => '410', # C+0x84 # U+0x201E + 'ellipsis' => '807', # C+0x85 # U+0x2026 + 'dagger' => '472', # C+0x86 # U+0x2020 + 'daggerdbl' => '472', # C+0x87 # U+0x2021 + 'circumflex' => '500', # C+0x88 # U+0x02C6 + 'perthousand' => '1205', # C+0x89 # U+0x2030 + 'Scaron' => '561', # C+0x8A # U+0x0160 + 'guilsinglleft' => '415', # C+0x8B # U+0x2039 + 'OE' => '998', # C+0x8C # U+0x0152 + 'Zcaron' => '601', # C+0x8E # U+0x017D + 'quoteleft' => '226', # C+0x91 # U+0x2018 + 'quoteright' => '226', # C+0x92 # U+0x2019 + 'quotedblleft' => '410', # C+0x93 # U+0x201C + 'quotedblright' => '410', # C+0x94 # U+0x201D + 'endash' => '643', # C+0x96 # U+0x2013 + 'emdash' => '856', # C+0x97 # U+0x2014 + 'tilde' => '500', # C+0x98 # U+0x02DC + 'trademark' => '942', # C+0x99 # U+0x2122 + 'scaron' => '432', # C+0x9A # U+0x0161 + 'guilsinglright' => '415', # C+0x9B # U+0x203A + 'oe' => '816', # C+0x9C # U+0x0153 + 'zcaron' => '443', # C+0x9E # U+0x017E + 'Ydieresis' => '615', # C+0x9F # U+0x0178 + 'exclamdown' => '331', # C+0xA1 # U+0x00A1 + 'cent' => '555', # C+0xA2 # U+0x00A2 + 'sterling' => '622', # C+0xA3 # U+0x00A3 + 'currency' => '571', # C+0xA4 # U+0x00A4 + 'yen' => '614', # C+0xA5 # U+0x00A5 + 'brokenbar' => '375', # C+0xA6 # U+0x00A6 + 'section' => '500', # C+0xA7 # U+0x00A7 + 'dieresis' => '500', # C+0xA8 # U+0x00A8 + 'copyright' => '941', # C+0xA9 # U+0x00A9 + 'ordfeminine' => '500', # C+0xAA # U+0x00AA + 'guillemotleft' => '581', # C+0xAB # U+0x00AB + 'logicalnot' => '643', # C+0xAC # U+0x00AC + 'registered' => '941', # C+0xAE # U+0x00AE + 'macron' => '500', # C+0xAF # U+0x00AF + 'degree' => '419', # C+0xB0 # U+0x00B0 + 'plusminus' => '643', # C+0xB1 # U+0x00B1 + 'twosuperior' => '500', # C+0xB2 # U+0x00B2 + 'threesuperior' => '500', # C+0xB3 # U+0x00B3 + 'acute' => '500', # C+0xB4 # U+0x00B4 + 'mu' => '579', # C+0xB5 # U+0x00B5 + 'paragraph' => '500', # C+0xB6 # U+0x00B6 + 'periodcentered' => '279', # C+0xB7 # U+0x00B7 + 'cedilla' => '500', # C+0xB8 # U+0x00B8 + 'onesuperior' => '500', # C+0xB9 # U+0x00B9 + 'ordmasculine' => '500', # C+0xBA # U+0x00BA + 'guillemotright' => '581', # C+0xBB # U+0x00BB + 'onequarter' => '1049', # C+0xBC # U+0x00BC + 'onehalf' => '1049', # C+0xBD # U+0x00BD + 'threequarters' => '1049', # C+0xBE # U+0x00BE + 'questiondown' => '478', # C+0xBF # U+0x00BF + 'Agrave' => '670', # C+0xC0 # U+0x00C0 + 'Aacute' => '670', # C+0xC1 # U+0x00C1 + 'Acircumflex' => '670', # C+0xC2 # U+0x00C2 + 'Atilde' => '670', # C+0xC3 # U+0x00C3 + 'Adieresis' => '670', # C+0xC4 # U+0x00C4 + 'Aring' => '670', # C+0xC5 # U+0x00C5 + 'AE' => '970', # C+0xC6 # U+0x00C6 + 'Ccedilla' => '642', # C+0xC7 # U+0x00C7 + 'Egrave' => '653', # C+0xC8 # U+0x00C8 + 'Eacute' => '653', # C+0xC9 # U+0x00C9 + 'Ecircumflex' => '653', # C+0xCA # U+0x00CA + 'Edieresis' => '653', # C+0xCB # U+0x00CB + 'Igrave' => '389', # C+0xCC # U+0x00CC + 'Iacute' => '389', # C+0xCD # U+0x00CD + 'Icircumflex' => '389', # C+0xCE # U+0x00CE + 'Idieresis' => '389', # C+0xCF # U+0x00CF + 'Eth' => '749', # C+0xD0 # U+0x00D0 + 'Ntilde' => '767', # C+0xD1 # U+0x00D1 + 'Ograve' => '744', # C+0xD2 # U+0x00D2 + 'Oacute' => '744', # C+0xD3 # U+0x00D3 + 'Ocircumflex' => '744', # C+0xD4 # U+0x00D4 + 'Otilde' => '744', # C+0xD5 # U+0x00D5 + 'Odieresis' => '744', # C+0xD6 # U+0x00D6 + 'multiply' => '643', # C+0xD7 # U+0x00D7 + 'Oslash' => '744', # C+0xD8 # U+0x00D8 + 'Ugrave' => '756', # C+0xD9 # U+0x00D9 + 'Uacute' => '756', # C+0xDA # U+0x00DA + 'Ucircumflex' => '756', # C+0xDB # U+0x00DB + 'Udieresis' => '756', # C+0xDC # U+0x00DC + 'Yacute' => '615', # C+0xDD # U+0x00DD + 'Thorn' => '614', # C+0xDE # U+0x00DE + 'germandbls' => '548', # C+0xDF # U+0x00DF + 'agrave' => '503', # C+0xE0 # U+0x00E0 + 'aacute' => '503', # C+0xE1 # U+0x00E1 + 'acircumflex' => '503', # C+0xE2 # U+0x00E2 + 'atilde' => '503', # C+0xE3 # U+0x00E3 + 'adieresis' => '503', # C+0xE4 # U+0x00E4 + 'aring' => '503', # C+0xE5 # U+0x00E5 + 'ae' => '736', # C+0xE6 # U+0x00E6 + 'ccedilla' => '454', # C+0xE7 # U+0x00E7 + 'egrave' => '483', # C+0xE8 # U+0x00E8 + 'eacute' => '483', # C+0xE9 # U+0x00E9 + 'ecircumflex' => '483', # C+0xEA # U+0x00EA + 'edieresis' => '483', # C+0xEB # U+0x00EB + 'igrave' => '292', # C+0xEC # U+0x00EC + 'iacute' => '292', # C+0xED # U+0x00ED + 'icircumflex' => '292', # C+0xEE # U+0x00EE + 'idieresis' => '292', # C+0xEF # U+0x00EF + 'eth' => '531', # C+0xF0 # U+0x00F0 + 'ntilde' => '590', # C+0xF1 # U+0x00F1 + 'ograve' => '539', # C+0xF2 # U+0x00F2 + 'oacute' => '539', # C+0xF3 # U+0x00F3 + 'ocircumflex' => '539', # C+0xF4 # U+0x00F4 + 'otilde' => '539', # C+0xF5 # U+0x00F5 + 'odieresis' => '539', # C+0xF6 # U+0x00F6 + 'divide' => '643', # C+0xF7 # U+0x00F7 + 'oslash' => '539', # C+0xF8 # U+0x00F8 + 'ugrave' => '575', # C+0xF9 # U+0x00F9 + 'uacute' => '575', # C+0xFA # U+0x00FA + 'ucircumflex' => '575', # C+0xFB # U+0x00FB + 'udieresis' => '575', # C+0xFC # U+0x00FC + 'yacute' => '492', # C+0xFD # U+0x00FD + 'thorn' => '559', # C+0xFE # U+0x00FE + 'ydieresis' => '492', # C+0xFF # U+0x00FF + 'middot' => '279', # U+0x00B7 + 'Amacron' => '670', # U+0x0100 + 'amacron' => '503', # U+0x0101 + 'Abreve' => '670', # U+0x0102 + 'abreve' => '503', # U+0x0103 + 'Aogonek' => '670', # U+0x0104 + 'aogonek' => '503', # U+0x0105 + 'Cacute' => '642', # U+0x0106 + 'cacute' => '454', # U+0x0107 + 'Ccircumflex' => '642', # U+0x0108 + 'ccircumflex' => '454', # U+0x0109 + 'Cdotaccent' => '642', # U+0x010A + 'cdotaccent' => '454', # U+0x010B + 'Ccaron' => '642', # U+0x010C + 'ccaron' => '454', # U+0x010D + 'Dcaron' => '749', # U+0x010E + 'dcaron' => '665', # U+0x010F + 'Dcroat' => '749', # U+0x0110 + 'dcroat' => '574', # U+0x0111 + 'Emacron' => '653', # U+0x0112 + 'emacron' => '483', # U+0x0113 + 'Ebreve' => '653', # U+0x0114 + 'ebreve' => '483', # U+0x0115 + 'Edotaccent' => '653', # U+0x0116 + 'edotaccent' => '483', # U+0x0117 + 'Eogonek' => '653', # U+0x0118 + 'eogonek' => '483', # U+0x0119 + 'Ecaron' => '653', # U+0x011A + 'ecaron' => '483', # U+0x011B + 'Gcircumflex' => '725', # U+0x011C + 'gcircumflex' => '509', # U+0x011D + 'Gbreve' => '725', # U+0x011E + 'gbreve' => '509', # U+0x011F + 'Gdotaccent' => '725', # U+0x0120 + 'gdotaccent' => '509', # U+0x0121 + 'Gcommaaccent' => '725', # U+0x0122 + 'gcommaaccent' => '509', # U+0x0123 + 'Hcircumflex' => '814', # U+0x0124 + 'hcircumflex' => '582', # U+0x0125 + 'Hbar' => '814', # U+0x0126 + 'hbar' => '582', # U+0x0127 + 'Itilde' => '389', # U+0x0128 + 'itilde' => '292', # U+0x0129 + 'Imacron' => '389', # U+0x012A + 'imacron' => '292', # U+0x012B + 'Ibreve' => '389', # U+0x012C + 'ibreve' => '292', # U+0x012D + 'Iogonek' => '389', # U+0x012E + 'iogonek' => '292', # U+0x012F + 'Idotaccent' => '389', # U+0x0130 + 'dotlessi' => '292', # U+0x0131 + 'IJ' => '887', # U+0x0132 + 'ij' => '572', # U+0x0133 + 'Jcircumflex' => '517', # U+0x0134 + 'jcircumflex' => '291', # U+0x0135 + 'Kcommaaccent' => '694', # U+0x0136 + 'kcommaaccent' => '535', # U+0x0137 + 'kgreenlandic' => '544', # U+0x0138 + 'Lacute' => '603', # U+0x0139 + 'lacute' => '286', # U+0x013A + 'Lcommaaccent' => '603', # U+0x013B + 'lcommaaccent' => '286', # U+0x013C + 'Lcaron' => '603', # U+0x013D + 'lcaron' => '376', # U+0x013E + 'Ldot' => '603', # U+0x013F + 'ldot' => '420', # U+0x0140 + 'Lslash' => '603', # U+0x0141 + 'lslash' => '286', # U+0x0142 + 'Nacute' => '767', # U+0x0143 + 'nacute' => '590', # U+0x0144 + 'Ncommaaccent' => '767', # U+0x0145 + 'ncommaaccent' => '590', # U+0x0146 + 'Ncaron' => '767', # U+0x0147 + 'ncaron' => '590', # U+0x0148 + 'napostrophe' => '644', # U+0x0149 + 'Eng' => '767', # U+0x014A + 'eng' => '578', # U+0x014B + 'Omacron' => '744', # U+0x014C + 'omacron' => '539', # U+0x014D + 'Obreve' => '744', # U+0x014E + 'obreve' => '539', # U+0x014F + 'Ohungarumlaut' => '744', # U+0x0150 + 'ohungarumlaut' => '539', # U+0x0151 + 'Racute' => '701', # U+0x0154 + 'racute' => '409', # U+0x0155 + 'Rcommaaccent' => '701', # U+0x0156 + 'rcommaaccent' => '409', # U+0x0157 + 'Rcaron' => '701', # U+0x0158 + 'rcaron' => '409', # U+0x0159 + 'Sacute' => '561', # U+0x015A + 'sacute' => '432', # U+0x015B + 'Scircumflex' => '561', # U+0x015C + 'scircumflex' => '432', # U+0x015D + 'Scedilla' => '561', # U+0x015E + 'scedilla' => '432', # U+0x015F + 'Tcommaaccent' => '618', # U+0x0162 + 'tcommaaccent' => '345', # U+0x0163 + 'Tcaron' => '618', # U+0x0164 + 'tcaron' => '345', # U+0x0165 + 'Tbar' => '618', # U+0x0166 + 'tbar' => '345', # U+0x0167 + 'Utilde' => '756', # U+0x0168 + 'utilde' => '575', # U+0x0169 + 'Umacron' => '756', # U+0x016A + 'umacron' => '575', # U+0x016B + 'Ubreve' => '756', # U+0x016C + 'ubreve' => '575', # U+0x016D + 'Uring' => '756', # U+0x016E + 'uring' => '575', # U+0x016F + 'Uhungarumlaut' => '756', # U+0x0170 + 'uhungarumlaut' => '575', # U+0x0171 + 'Uogonek' => '756', # U+0x0172 + 'uogonek' => '575', # U+0x0173 + 'Wcircumflex' => '975', # U+0x0174 + 'wcircumflex' => '737', # U+0x0175 + 'Ycircumflex' => '615', # U+0x0176 + 'ycircumflex' => '492', # U+0x0177 + 'Zacute' => '601', # U+0x0179 + 'zacute' => '443', # U+0x017A + 'Zdotaccent' => '601', # U+0x017B + 'zdotaccent' => '443', # U+0x017C + 'longs' => '299', # U+0x017F + 'Aringacute' => '670', # U+0x01FA + 'aringacute' => '503', # U+0x01FB + 'AEacute' => '970', # U+0x01FC + 'aeacute' => '736', # U+0x01FD + 'Oslashacute' => '744', # U+0x01FE + 'oslashacute' => '539', # U+0x01FF + 'Scommaaccent' => '561', # U+0x0218 + 'scommaaccent' => '432', # U+0x0219 + 'caron' => '500', # U+0x02C7 + 'breve' => '500', # U+0x02D8 + 'dotaccent' => '500', # U+0x02D9 + 'ring' => '500', # U+0x02DA + 'ogonek' => '500', # U+0x02DB + 'hungarumlaut' => '500', # U+0x02DD + 'tonos' => '500', # U+0x0384 + 'dieresistonos' => '500', # U+0x0385 + 'Alphatonos' => '675', # U+0x0386 + 'anoteleia' => '312', # U+0x0387 + 'Epsilontonos' => '798', # U+0x0388 + 'Etatonos' => '959', # U+0x0389 + 'Iotatonos' => '532', # U+0x038A + 'Omicrontonos' => '851', # U+0x038C + 'Upsilontonos' => '800', # U+0x038E + 'Omegatonos' => '876', # U+0x038F + 'iotadieresistonos' => '295', # U+0x0390 + 'Alpha' => '670', # U+0x0391 + 'Beta' => '653', # U+0x0392 + 'Gamma' => '583', # U+0x0393 + 'Delta' => '660', # U+0x0394 + 'Epsilon' => '653', # U+0x0395 + 'Zeta' => '601', # U+0x0396 + 'Eta' => '814', # U+0x0397 + 'Theta' => '744', # U+0x0398 + 'Iota' => '389', # U+0x0399 + 'Kappa' => '694', # U+0x039A + 'Lambda' => '673', # U+0x039B + 'Mu' => '927', # U+0x039C + 'Nu' => '767', # U+0x039D + 'Xi' => '693', # U+0x039E + 'Omicron' => '744', # U+0x039F + 'Pi' => '808', # U+0x03A0 + 'Rho' => '609', # U+0x03A1 + 'Sigma' => '603', # U+0x03A3 + 'Tau' => '618', # U+0x03A4 + 'Upsilon' => '615', # U+0x03A5 + 'Phi' => '766', # U+0x03A6 + 'Chi' => '710', # U+0x03A7 + 'Psi' => '874', # U+0x03A8 + 'Omega' => '778', # U+0x03A9 + 'Iotadieresis' => '389', # U+0x03AA + 'Upsilondieresis' => '615', # U+0x03AB + 'alphatonos' => '597', # U+0x03AC + 'epsilontonos' => '468', # U+0x03AD + 'etatonos' => '570', # U+0x03AE + 'iotatonos' => '295', # U+0x03AF + 'upsilondieresistonos' => '541', # U+0x03B0 + 'alpha' => '597', # U+0x03B1 + 'beta' => '565', # U+0x03B2 + 'gamma' => '513', # U+0x03B3 + 'delta' => '539', # U+0x03B4 + 'epsilon' => '468', # U+0x03B5 + 'zeta' => '403', # U+0x03B6 + 'eta' => '570', # U+0x03B7 + 'theta' => '556', # U+0x03B8 + 'iota' => '295', # U+0x03B9 + 'kappa' => '536', # U+0x03BA + 'lambda' => '487', # U+0x03BB + 'nu' => '501', # U+0x03BD + 'xi' => '440', # U+0x03BE + 'omicron' => '539', # U+0x03BF + 'pi' => '601', # U+0x03C0 + 'rho' => '557', # U+0x03C1 + 'sigma1' => '445', # U+0x03C2 + 'sigma' => '572', # U+0x03C3 + 'tau' => '450', # U+0x03C4 + 'upsilon' => '541', # U+0x03C5 + 'phi' => '695', # U+0x03C6 + 'chi' => '506', # U+0x03C7 + 'psi' => '730', # U+0x03C8 + 'omega' => '714', # U+0x03C9 + 'iotadieresis' => '295', # U+0x03CA + 'upsilondieresis' => '541', # U+0x03CB + 'omicrontonos' => '539', # U+0x03CC + 'upsilontonos' => '541', # U+0x03CD + 'omegatonos' => '714', # U+0x03CE + 'afii10023' => '653', # U+0x0401 + 'afii10051' => '785', # U+0x0402 + 'afii10052' => '583', # U+0x0403 + 'afii10053' => '656', # U+0x0404 + 'afii10054' => '561', # U+0x0405 + 'afii10055' => '389', # U+0x0406 + 'afii10056' => '389', # U+0x0407 + 'afii10057' => '517', # U+0x0408 + 'afii10058' => '1011', # U+0x0409 + 'afii10059' => '1065', # U+0x040A + 'afii10060' => '839', # U+0x040B + 'afii10061' => '694', # U+0x040C + 'afii10062' => '656', # U+0x040E + 'afii10145' => '810', # U+0x040F + 'afii10017' => '670', # U+0x0410 + 'afii10018' => '651', # U+0x0411 + 'afii10019' => '653', # U+0x0412 + 'afii10020' => '583', # U+0x0413 + 'afii10021' => '722', # U+0x0414 + 'afii10022' => '653', # U+0x0415 + 'afii10024' => '984', # U+0x0416 + 'afii10025' => '609', # U+0x0417 + 'afii10026' => '818', # U+0x0418 + 'afii10027' => '818', # U+0x0419 + 'afii10028' => '694', # U+0x041A + 'afii10029' => '756', # U+0x041B + 'afii10030' => '927', # U+0x041C + 'afii10031' => '814', # U+0x041D + 'afii10032' => '744', # U+0x041E + 'afii10033' => '808', # U+0x041F + 'afii10034' => '609', # U+0x0420 + 'afii10035' => '642', # U+0x0421 + 'afii10036' => '618', # U+0x0422 + 'afii10037' => '656', # U+0x0423 + 'afii10038' => '766', # U+0x0424 + 'afii10039' => '710', # U+0x0425 + 'afii10040' => '808', # U+0x0426 + 'afii10041' => '748', # U+0x0427 + 'afii10042' => '1098', # U+0x0428 + 'afii10043' => '1098', # U+0x0429 + 'afii10044' => '762', # U+0x042A + 'afii10045' => '967', # U+0x042B + 'afii10046' => '640', # U+0x042C + 'afii10047' => '657', # U+0x042D + 'afii10048' => '1065', # U+0x042E + 'afii10049' => '696', # U+0x042F + 'afii10065' => '503', # U+0x0430 + 'afii10066' => '540', # U+0x0431 + 'afii10067' => '518', # U+0x0432 + 'afii10068' => '439', # U+0x0433 + 'afii10069' => '559', # U+0x0434 + 'afii10070' => '483', # U+0x0435 + 'afii10072' => '787', # U+0x0436 + 'afii10073' => '473', # U+0x0437 + 'afii10074' => '612', # U+0x0438 + 'afii10075' => '612', # U+0x0439 + 'afii10076' => '551', # U+0x043A + 'afii10077' => '581', # U+0x043B + 'afii10078' => '715', # U+0x043C + 'afii10079' => '608', # U+0x043D + 'afii10080' => '539', # U+0x043E + 'afii10081' => '601', # U+0x043F + 'afii10082' => '571', # U+0x0440 + 'afii10083' => '454', # U+0x0441 + 'afii10084' => '470', # U+0x0442 + 'afii10085' => '492', # U+0x0443 + 'afii10086' => '752', # U+0x0444 + 'afii10087' => '504', # U+0x0445 + 'afii10088' => '602', # U+0x0446 + 'afii10089' => '572', # U+0x0447 + 'afii10090' => '863', # U+0x0448 + 'afii10091' => '864', # U+0x0449 + 'afii10092' => '577', # U+0x044A + 'afii10093' => '757', # U+0x044B + 'afii10094' => '497', # U+0x044C + 'afii10095' => '486', # U+0x044D + 'afii10096' => '789', # U+0x044E + 'afii10097' => '547', # U+0x044F + 'afii10071' => '483', # U+0x0451 + 'afii10099' => '570', # U+0x0452 + 'afii10100' => '439', # U+0x0453 + 'afii10101' => '486', # U+0x0454 + 'afii10102' => '432', # U+0x0455 + 'afii10103' => '292', # U+0x0456 + 'afii10104' => '292', # U+0x0457 + 'afii10105' => '291', # U+0x0458 + 'afii10106' => '773', # U+0x0459 + 'afii10107' => '797', # U+0x045A + 'afii10108' => '582', # U+0x045B + 'afii10109' => '551', # U+0x045C + 'afii10110' => '492', # U+0x045E + 'afii10193' => '603', # U+0x045F + 'afii10050' => '576', # U+0x0490 + 'afii10098' => '430', # U+0x0491 + 'Wgrave' => '975', # U+0x1E80 + 'wgrave' => '737', # U+0x1E81 + 'Wacute' => '975', # U+0x1E82 + 'wacute' => '737', # U+0x1E83 + 'Wdieresis' => '975', # U+0x1E84 + 'wdieresis' => '737', # U+0x1E85 + 'Ygrave' => '615', # U+0x1EF2 + 'ygrave' => '492', # U+0x1EF3 + 'afii00208' => '856', # U+0x2015 + 'underscoredbl' => '643', # U+0x2017 + 'quotereversed' => '195', # U+0x201B + 'minute' => '321', # U+0x2032 + 'second' => '517', # U+0x2033 + 'exclamdbl' => '575', # U+0x203C + 'fraction' => '81', # U+0x2044 + 'foursuperior' => '500', # U+0x2074 + 'fivesuperior' => '500', # U+0x2075 + 'sevensuperior' => '500', # U+0x2077 + 'eightsuperior' => '500', # U+0x2078 + 'nsuperior' => '525', # U+0x207F + 'franc' => '622', # U+0x20A3 + 'lira' => '622', # U+0x20A4 + 'peseta' => '1204', # U+0x20A7 + 'afii61248' => '817', # U+0x2105 + 'afii61289' => '323', # U+0x2113 + 'afii61352' => '1220', # U+0x2116 + 'estimated' => '615', # U+0x212E + 'oneeighth' => '1049', # U+0x215B + 'threeeighths' => '1049', # U+0x215C + 'fiveeighths' => '1049', # U+0x215D + 'seveneighths' => '1049', # U+0x215E + 'partialdiff' => '576', # U+0x2202 + 'product' => '834', # U+0x220F + 'summation' => '705', # U+0x2211 + 'minus' => '643', # U+0x2212 + 'radical' => '668', # U+0x221A + 'infinity' => '716', # U+0x221E + 'integral' => '499', # U+0x222B + 'approxequal' => '643', # U+0x2248 + 'notequal' => '643', # U+0x2260 + 'lessequal' => '643', # U+0x2264 + 'greaterequal' => '643', # U+0x2265 + 'H22073' => '604', # U+0x25A1 + 'H18543' => '354', # U+0x25AA + 'H18551' => '354', # U+0x25AB + 'lozenge' => '561', # U+0x25CA + 'H18533' => '604', # U+0x25CF + 'openbullet' => '354', # U+0x25E6 + 'commaaccent' => '604', # U+0xF6C3 + 'Acute' => '500', # U+0xF6C9 + 'Caron' => '500', # U+0xF6CA + 'Dieresis' => '500', # U+0xF6CB + 'Grave' => '500', # U+0xF6CE + 'Hungarumlaut' => '500', # U+0xF6CF + 'radicalex' => '643', # U+0xF8E5 + 'fi' => '582', # U+0xFB01 + 'fl' => '589', # U+0xFB02 + }, # HORIZ. WIDTH TABLE +} }; + +1; diff --git a/lib/PDF/API2/Resource/Font/CoreFont/georgiabold.pm b/lib/PDF/API2/Resource/Font/CoreFont/georgiabold.pm new file mode 100644 index 0000000..b24c908 --- /dev/null +++ b/lib/PDF/API2/Resource/Font/CoreFont/georgiabold.pm @@ -0,0 +1,863 @@ +#line 1 "PDF/API2/Resource/Font/CoreFont/georgiabold.pm" +#line 1 "PDF/API2/Resource/Font/CoreFont/georgiabold.pm" +package PDF::API2::Resource::Font::CoreFont::georgiabold; + +use strict; +use warnings; + +our $VERSION = '2.033'; # VERSION + +sub data { return { + 'fontname' => 'Georgia,Bold', + 'type' => 'TrueType', + 'apiname' => 'GeBo', + 'ascender' => '916', + 'capheight' => '692', + 'descender' => '-219', + 'isfixedpitch' => '0', + 'issymbol' => '0', + 'italicangle' => '0', + 'underlineposition' => '-180', + 'underlinethickness' => '122', + 'xheight' => '484', + 'firstchar' => '32', + 'lastchar' => '255', + 'flags' => '262178', + 'char' => [ # DEF. ENCODING GLYPH TABLE + '.notdef', # C+0x00 # U+0x0000 + '.notdef', # C+0x01 # U+0x0000 + '.notdef', # C+0x02 # U+0x0000 + '.notdef', # C+0x03 # U+0x0000 + '.notdef', # C+0x04 # U+0x0000 + '.notdef', # C+0x05 # U+0x0000 + '.notdef', # C+0x06 # U+0x0000 + '.notdef', # C+0x07 # U+0x0000 + '.notdef', # C+0x08 # U+0x0000 + '.notdef', # C+0x09 # U+0x0000 + '.notdef', # C+0x0A # U+0x0000 + '.notdef', # C+0x0B # U+0x0000 + '.notdef', # C+0x0C # U+0x0000 + '.notdef', # C+0x0D # U+0x0000 + '.notdef', # C+0x0E # U+0x0000 + '.notdef', # C+0x0F # U+0x0000 + '.notdef', # C+0x10 # U+0x0000 + '.notdef', # C+0x11 # U+0x0000 + '.notdef', # C+0x12 # U+0x0000 + '.notdef', # C+0x13 # U+0x0000 + '.notdef', # C+0x14 # U+0x0000 + '.notdef', # C+0x15 # U+0x0000 + '.notdef', # C+0x16 # U+0x0000 + '.notdef', # C+0x17 # U+0x0000 + '.notdef', # C+0x18 # U+0x0000 + '.notdef', # C+0x19 # U+0x0000 + '.notdef', # C+0x1A # U+0x0000 + '.notdef', # C+0x1B # U+0x0000 + '.notdef', # C+0x1C # U+0x0000 + '.notdef', # C+0x1D # U+0x0000 + '.notdef', # C+0x1E # U+0x0000 + '.notdef', # C+0x1F # U+0x0000 + 'space', # C+0x20 # U+0x0020 + 'exclam', # C+0x21 # U+0x0021 + 'quotedbl', # C+0x22 # U+0x0022 + 'numbersign', # C+0x23 # U+0x0023 + 'dollar', # C+0x24 # U+0x0024 + 'percent', # C+0x25 # U+0x0025 + 'ampersand', # C+0x26 # U+0x0026 + 'quotesingle', # C+0x27 # U+0x0027 + 'parenleft', # C+0x28 # U+0x0028 + 'parenright', # C+0x29 # U+0x0029 + 'asterisk', # C+0x2A # U+0x002A + 'plus', # C+0x2B # U+0x002B + 'comma', # C+0x2C # U+0x002C + 'hyphen', # C+0x2D # U+0x002D + 'period', # C+0x2E # U+0x002E + 'slash', # C+0x2F # U+0x002F + 'zero', # C+0x30 # U+0x0030 + 'one', # C+0x31 # U+0x0031 + 'two', # C+0x32 # U+0x0032 + 'three', # C+0x33 # U+0x0033 + 'four', # C+0x34 # U+0x0034 + 'five', # C+0x35 # U+0x0035 + 'six', # C+0x36 # U+0x0036 + 'seven', # C+0x37 # U+0x0037 + 'eight', # C+0x38 # U+0x0038 + 'nine', # C+0x39 # U+0x0039 + 'colon', # C+0x3A # U+0x003A + 'semicolon', # C+0x3B # U+0x003B + 'less', # C+0x3C # U+0x003C + 'equal', # C+0x3D # U+0x003D + 'greater', # C+0x3E # U+0x003E + 'question', # C+0x3F # U+0x003F + 'at', # C+0x40 # U+0x0040 + 'A', # C+0x41 # U+0x0041 + 'B', # C+0x42 # U+0x0042 + 'C', # C+0x43 # U+0x0043 + 'D', # C+0x44 # U+0x0044 + 'E', # C+0x45 # U+0x0045 + 'F', # C+0x46 # U+0x0046 + 'G', # C+0x47 # U+0x0047 + 'H', # C+0x48 # U+0x0048 + 'I', # C+0x49 # U+0x0049 + 'J', # C+0x4A # U+0x004A + 'K', # C+0x4B # U+0x004B + 'L', # C+0x4C # U+0x004C + 'M', # C+0x4D # U+0x004D + 'N', # C+0x4E # U+0x004E + 'O', # C+0x4F # U+0x004F + 'P', # C+0x50 # U+0x0050 + 'Q', # C+0x51 # U+0x0051 + 'R', # C+0x52 # U+0x0052 + 'S', # C+0x53 # U+0x0053 + 'T', # C+0x54 # U+0x0054 + 'U', # C+0x55 # U+0x0055 + 'V', # C+0x56 # U+0x0056 + 'W', # C+0x57 # U+0x0057 + 'X', # C+0x58 # U+0x0058 + 'Y', # C+0x59 # U+0x0059 + 'Z', # C+0x5A # U+0x005A + 'bracketleft', # C+0x5B # U+0x005B + 'backslash', # C+0x5C # U+0x005C + 'bracketright', # C+0x5D # U+0x005D + 'asciicircum', # C+0x5E # U+0x005E + 'underscore', # C+0x5F # U+0x005F + 'grave', # C+0x60 # U+0x0060 + 'a', # C+0x61 # U+0x0061 + 'b', # C+0x62 # U+0x0062 + 'c', # C+0x63 # U+0x0063 + 'd', # C+0x64 # U+0x0064 + 'e', # C+0x65 # U+0x0065 + 'f', # C+0x66 # U+0x0066 + 'g', # C+0x67 # U+0x0067 + 'h', # C+0x68 # U+0x0068 + 'i', # C+0x69 # U+0x0069 + 'j', # C+0x6A # U+0x006A + 'k', # C+0x6B # U+0x006B + 'l', # C+0x6C # U+0x006C + 'm', # C+0x6D # U+0x006D + 'n', # C+0x6E # U+0x006E + 'o', # C+0x6F # U+0x006F + 'p', # C+0x70 # U+0x0070 + 'q', # C+0x71 # U+0x0071 + 'r', # C+0x72 # U+0x0072 + 's', # C+0x73 # U+0x0073 + 't', # C+0x74 # U+0x0074 + 'u', # C+0x75 # U+0x0075 + 'v', # C+0x76 # U+0x0076 + 'w', # C+0x77 # U+0x0077 + 'x', # C+0x78 # U+0x0078 + 'y', # C+0x79 # U+0x0079 + 'z', # C+0x7A # U+0x007A + 'braceleft', # C+0x7B # U+0x007B + 'bar', # C+0x7C # U+0x007C + 'braceright', # C+0x7D # U+0x007D + 'asciitilde', # C+0x7E # U+0x007E + 'bullet', # C+0x7F # U+0x2022 + 'Euro', # C+0x80 # U+0x20AC + 'bullet', # C+0x81 # U+0x2022 + 'quotesinglbase', # C+0x82 # U+0x201A + 'florin', # C+0x83 # U+0x0192 + 'quotedblbase', # C+0x84 # U+0x201E + 'ellipsis', # C+0x85 # U+0x2026 + 'dagger', # C+0x86 # U+0x2020 + 'daggerdbl', # C+0x87 # U+0x2021 + 'circumflex', # C+0x88 # U+0x02C6 + 'perthousand', # C+0x89 # U+0x2030 + 'Scaron', # C+0x8A # U+0x0160 + 'guilsinglleft', # C+0x8B # U+0x2039 + 'OE', # C+0x8C # U+0x0152 + 'bullet', # C+0x8D # U+0x2022 + 'Zcaron', # C+0x8E # U+0x017D + 'bullet', # C+0x8F # U+0x2022 + 'bullet', # C+0x90 # U+0x2022 + 'quoteleft', # C+0x91 # U+0x2018 + 'quoteright', # C+0x92 # U+0x2019 + 'quotedblleft', # C+0x93 # U+0x201C + 'quotedblright', # C+0x94 # U+0x201D + 'bullet', # C+0x95 # U+0x2022 + 'endash', # C+0x96 # U+0x2013 + 'emdash', # C+0x97 # U+0x2014 + 'tilde', # C+0x98 # U+0x02DC + 'trademark', # C+0x99 # U+0x2122 + 'scaron', # C+0x9A # U+0x0161 + 'guilsinglright', # C+0x9B # U+0x203A + 'oe', # C+0x9C # U+0x0153 + 'bullet', # C+0x9D # U+0x2022 + 'zcaron', # C+0x9E # U+0x017E + 'Ydieresis', # C+0x9F # U+0x0178 + 'space', # C+0xA0 # U+0x0020 + 'exclamdown', # C+0xA1 # U+0x00A1 + 'cent', # C+0xA2 # U+0x00A2 + 'sterling', # C+0xA3 # U+0x00A3 + 'currency', # C+0xA4 # U+0x00A4 + 'yen', # C+0xA5 # U+0x00A5 + 'brokenbar', # C+0xA6 # U+0x00A6 + 'section', # C+0xA7 # U+0x00A7 + 'dieresis', # C+0xA8 # U+0x00A8 + 'copyright', # C+0xA9 # U+0x00A9 + 'ordfeminine', # C+0xAA # U+0x00AA + 'guillemotleft', # C+0xAB # U+0x00AB + 'logicalnot', # C+0xAC # U+0x00AC + 'hyphen', # C+0xAD # U+0x002D + 'registered', # C+0xAE # U+0x00AE + 'macron', # C+0xAF # U+0x00AF + 'degree', # C+0xB0 # U+0x00B0 + 'plusminus', # C+0xB1 # U+0x00B1 + 'twosuperior', # C+0xB2 # U+0x00B2 + 'threesuperior', # C+0xB3 # U+0x00B3 + 'acute', # C+0xB4 # U+0x00B4 + 'mu', # C+0xB5 # U+0x00B5 + 'paragraph', # C+0xB6 # U+0x00B6 + 'periodcentered', # C+0xB7 # U+0x00B7 + 'cedilla', # C+0xB8 # U+0x00B8 + 'onesuperior', # C+0xB9 # U+0x00B9 + 'ordmasculine', # C+0xBA # U+0x00BA + 'guillemotright', # C+0xBB # U+0x00BB + 'onequarter', # C+0xBC # U+0x00BC + 'onehalf', # C+0xBD # U+0x00BD + 'threequarters', # C+0xBE # U+0x00BE + 'questiondown', # C+0xBF # U+0x00BF + 'Agrave', # C+0xC0 # U+0x00C0 + 'Aacute', # C+0xC1 # U+0x00C1 + 'Acircumflex', # C+0xC2 # U+0x00C2 + 'Atilde', # C+0xC3 # U+0x00C3 + 'Adieresis', # C+0xC4 # U+0x00C4 + 'Aring', # C+0xC5 # U+0x00C5 + 'AE', # C+0xC6 # U+0x00C6 + 'Ccedilla', # C+0xC7 # U+0x00C7 + 'Egrave', # C+0xC8 # U+0x00C8 + 'Eacute', # C+0xC9 # U+0x00C9 + 'Ecircumflex', # C+0xCA # U+0x00CA + 'Edieresis', # C+0xCB # U+0x00CB + 'Igrave', # C+0xCC # U+0x00CC + 'Iacute', # C+0xCD # U+0x00CD + 'Icircumflex', # C+0xCE # U+0x00CE + 'Idieresis', # C+0xCF # U+0x00CF + 'Eth', # C+0xD0 # U+0x00D0 + 'Ntilde', # C+0xD1 # U+0x00D1 + 'Ograve', # C+0xD2 # U+0x00D2 + 'Oacute', # C+0xD3 # U+0x00D3 + 'Ocircumflex', # C+0xD4 # U+0x00D4 + 'Otilde', # C+0xD5 # U+0x00D5 + 'Odieresis', # C+0xD6 # U+0x00D6 + 'multiply', # C+0xD7 # U+0x00D7 + 'Oslash', # C+0xD8 # U+0x00D8 + 'Ugrave', # C+0xD9 # U+0x00D9 + 'Uacute', # C+0xDA # U+0x00DA + 'Ucircumflex', # C+0xDB # U+0x00DB + 'Udieresis', # C+0xDC # U+0x00DC + 'Yacute', # C+0xDD # U+0x00DD + 'Thorn', # C+0xDE # U+0x00DE + 'germandbls', # C+0xDF # U+0x00DF + 'agrave', # C+0xE0 # U+0x00E0 + 'aacute', # C+0xE1 # U+0x00E1 + 'acircumflex', # C+0xE2 # U+0x00E2 + 'atilde', # C+0xE3 # U+0x00E3 + 'adieresis', # C+0xE4 # U+0x00E4 + 'aring', # C+0xE5 # U+0x00E5 + 'ae', # C+0xE6 # U+0x00E6 + 'ccedilla', # C+0xE7 # U+0x00E7 + 'egrave', # C+0xE8 # U+0x00E8 + 'eacute', # C+0xE9 # U+0x00E9 + 'ecircumflex', # C+0xEA # U+0x00EA + 'edieresis', # C+0xEB # U+0x00EB + 'igrave', # C+0xEC # U+0x00EC + 'iacute', # C+0xED # U+0x00ED + 'icircumflex', # C+0xEE # U+0x00EE + 'idieresis', # C+0xEF # U+0x00EF + 'eth', # C+0xF0 # U+0x00F0 + 'ntilde', # C+0xF1 # U+0x00F1 + 'ograve', # C+0xF2 # U+0x00F2 + 'oacute', # C+0xF3 # U+0x00F3 + 'ocircumflex', # C+0xF4 # U+0x00F4 + 'otilde', # C+0xF5 # U+0x00F5 + 'odieresis', # C+0xF6 # U+0x00F6 + 'divide', # C+0xF7 # U+0x00F7 + 'oslash', # C+0xF8 # U+0x00F8 + 'ugrave', # C+0xF9 # U+0x00F9 + 'uacute', # C+0xFA # U+0x00FA + 'ucircumflex', # C+0xFB # U+0x00FB + 'udieresis', # C+0xFC # U+0x00FC + 'yacute', # C+0xFD # U+0x00FD + 'thorn', # C+0xFE # U+0x00FE + 'ydieresis', # C+0xFF # U+0x00FF + ], # DEF. ENCODING GLYPH TABLE + 'fontbbox' => [ -190, -216, 1295, 912 ], + 'wx' => { # HORIZ. WIDTH TABLE + 'space' => '253', # C+0x20 # U+0x0020 + 'exclam' => '376', # C+0x21 # U+0x0021 + 'quotedbl' => '509', # C+0x22 # U+0x0022 + 'numbersign' => '703', # C+0x23 # U+0x0023 + 'dollar' => '640', # C+0x24 # U+0x0024 + 'percent' => '879', # C+0x25 # U+0x0025 + 'ampersand' => '799', # C+0x26 # U+0x0026 + 'quotesingle' => '269', # C+0x27 # U+0x0027 + 'parenleft' => '446', # C+0x28 # U+0x0028 + 'parenright' => '446', # C+0x29 # U+0x0029 + 'asterisk' => '481', # C+0x2A # U+0x002A + 'plus' => '703', # C+0x2B # U+0x002B + 'comma' => '328', # C+0x2C # U+0x002C + 'hyphen' => '378', # C+0x2D # U+0x002D + 'period' => '328', # C+0x2E # U+0x002E + 'slash' => '471', # C+0x2F # U+0x002F + 'zero' => '701', # C+0x30 # U+0x0030 + 'one' => '489', # C+0x31 # U+0x0031 + 'two' => '626', # C+0x32 # U+0x0032 + 'three' => '624', # C+0x33 # U+0x0033 + 'four' => '649', # C+0x34 # U+0x0034 + 'five' => '599', # C+0x35 # U+0x0035 + 'six' => '647', # C+0x36 # U+0x0036 + 'seven' => '554', # C+0x37 # U+0x0037 + 'eight' => '676', # C+0x38 # U+0x0038 + 'nine' => '647', # C+0x39 # U+0x0039 + 'colon' => '367', # C+0x3A # U+0x003A + 'semicolon' => '367', # C+0x3B # U+0x003B + 'less' => '703', # C+0x3C # U+0x003C + 'equal' => '703', # C+0x3D # U+0x003D + 'greater' => '703', # C+0x3E # U+0x003E + 'question' => '548', # C+0x3F # U+0x003F + 'at' => '966', # C+0x40 # U+0x0040 + 'A' => '758', # C+0x41 # U+0x0041 + 'B' => '757', # C+0x42 # U+0x0042 + 'C' => '715', # C+0x43 # U+0x0043 + 'D' => '833', # C+0x44 # U+0x0044 + 'E' => '721', # C+0x45 # U+0x0045 + 'F' => '671', # C+0x46 # U+0x0046 + 'G' => '807', # C+0x47 # U+0x0047 + 'H' => '913', # C+0x48 # U+0x0048 + 'I' => '445', # C+0x49 # U+0x0049 + 'J' => '595', # C+0x4A # U+0x004A + 'K' => '816', # C+0x4B # U+0x004B + 'L' => '685', # C+0x4C # U+0x004C + 'M' => '1023', # C+0x4D # U+0x004D + 'N' => '839', # C+0x4E # U+0x004E + 'O' => '819', # C+0x4F # U+0x004F + 'P' => '701', # C+0x50 # U+0x0050 + 'Q' => '819', # C+0x51 # U+0x0051 + 'R' => '797', # C+0x52 # U+0x0052 + 'S' => '648', # C+0x53 # U+0x0053 + 'T' => '684', # C+0x54 # U+0x0054 + 'U' => '833', # C+0x55 # U+0x0055 + 'V' => '762', # C+0x56 # U+0x0056 + 'W' => '1126', # C+0x57 # U+0x0057 + 'X' => '808', # C+0x58 # U+0x0058 + 'Y' => '731', # C+0x59 # U+0x0059 + 'Z' => '689', # C+0x5A # U+0x005A + 'bracketleft' => '446', # C+0x5B # U+0x005B + 'backslash' => '471', # C+0x5C # U+0x005C + 'bracketright' => '446', # C+0x5D # U+0x005D + 'asciicircum' => '703', # C+0x5E # U+0x005E + 'underscore' => '703', # C+0x5F # U+0x005F + 'grave' => '500', # C+0x60 # U+0x0060 + 'a' => '595', # C+0x61 # U+0x0061 + 'b' => '645', # C+0x62 # U+0x0062 + 'c' => '531', # C+0x63 # U+0x0063 + 'd' => '663', # C+0x64 # U+0x0064 + 'e' => '571', # C+0x65 # U+0x0065 + 'f' => '393', # C+0x66 # U+0x0066 + 'g' => '576', # C+0x67 # U+0x0067 + 'h' => '679', # C+0x68 # U+0x0068 + 'i' => '353', # C+0x69 # U+0x0069 + 'j' => '346', # C+0x6A # U+0x006A + 'k' => '631', # C+0x6B # U+0x006B + 'l' => '344', # C+0x6C # U+0x006C + 'm' => '1015', # C+0x6D # U+0x006D + 'n' => '689', # C+0x6E # U+0x006E + 'o' => '635', # C+0x6F # U+0x006F + 'p' => '657', # C+0x70 # U+0x0070 + 'q' => '648', # C+0x71 # U+0x0071 + 'r' => '520', # C+0x72 # U+0x0072 + 's' => '512', # C+0x73 # U+0x0073 + 't' => '397', # C+0x74 # U+0x0074 + 'u' => '676', # C+0x75 # U+0x0075 + 'v' => '566', # C+0x76 # U+0x0076 + 'w' => '863', # C+0x77 # U+0x0077 + 'x' => '587', # C+0x78 # U+0x0078 + 'y' => '562', # C+0x79 # U+0x0079 + 'z' => '525', # C+0x7A # U+0x007A + 'braceleft' => '500', # C+0x7B # U+0x007B + 'bar' => '387', # C+0x7C # U+0x007C + 'braceright' => '500', # C+0x7D # U+0x007D + 'asciitilde' => '703', # C+0x7E # U+0x007E + 'bullet' => '437', # C+0x7F # U+0x2022 + 'Euro' => '715', # C+0x80 # U+0x20AC + 'quotesinglbase' => '268', # C+0x82 # U+0x201A + 'florin' => '579', # C+0x83 # U+0x0192 + 'quotedblbase' => '519', # C+0x84 # U+0x201E + 'ellipsis' => '941', # C+0x85 # U+0x2026 + 'dagger' => '481', # C+0x86 # U+0x2020 + 'daggerdbl' => '481', # C+0x87 # U+0x2021 + 'circumflex' => '500', # C+0x88 # U+0x02C6 + 'perthousand' => '1308', # C+0x89 # U+0x2030 + 'Scaron' => '648', # C+0x8A # U+0x0160 + 'guilsinglleft' => '395', # C+0x8B # U+0x2039 + 'OE' => '1100', # C+0x8C # U+0x0152 + 'Zcaron' => '689', # C+0x8E # U+0x017D + 'quoteleft' => '268', # C+0x91 # U+0x2018 + 'quoteright' => '268', # C+0x92 # U+0x2019 + 'quotedblleft' => '519', # C+0x93 # U+0x201C + 'quotedblright' => '519', # C+0x94 # U+0x201D + 'endash' => '703', # C+0x96 # U+0x2013 + 'emdash' => '927', # C+0x97 # U+0x2014 + 'tilde' => '500', # C+0x98 # U+0x02DC + 'trademark' => '947', # C+0x99 # U+0x2122 + 'scaron' => '512', # C+0x9A # U+0x0161 + 'guilsinglright' => '395', # C+0x9B # U+0x203A + 'oe' => '937', # C+0x9C # U+0x0153 + 'zcaron' => '525', # C+0x9E # U+0x017E + 'Ydieresis' => '731', # C+0x9F # U+0x0178 + 'exclamdown' => '376', # C+0xA1 # U+0x00A1 + 'cent' => '605', # C+0xA2 # U+0x00A2 + 'sterling' => '689', # C+0xA3 # U+0x00A3 + 'currency' => '703', # C+0xA4 # U+0x00A4 + 'yen' => '732', # C+0xA5 # U+0x00A5 + 'brokenbar' => '387', # C+0xA6 # U+0x00A6 + 'section' => '563', # C+0xA7 # U+0x00A7 + 'dieresis' => '500', # C+0xA8 # U+0x00A8 + 'copyright' => '941', # C+0xA9 # U+0x00A9 + 'ordfeminine' => '551', # C+0xAA # U+0x00AA + 'guillemotleft' => '610', # C+0xAB # U+0x00AB + 'logicalnot' => '703', # C+0xAC # U+0x00AC + 'registered' => '941', # C+0xAE # U+0x00AE + 'macron' => '500', # C+0xAF # U+0x00AF + 'degree' => '419', # C+0xB0 # U+0x00B0 + 'plusminus' => '703', # C+0xB1 # U+0x00B1 + 'twosuperior' => '551', # C+0xB2 # U+0x00B2 + 'threesuperior' => '551', # C+0xB3 # U+0x00B3 + 'acute' => '500', # C+0xB4 # U+0x00B4 + 'mu' => '669', # C+0xB5 # U+0x00B5 + 'paragraph' => '548', # C+0xB6 # U+0x00B6 + 'periodcentered' => '337', # C+0xB7 # U+0x00B7 + 'cedilla' => '500', # C+0xB8 # U+0x00B8 + 'onesuperior' => '551', # C+0xB9 # U+0x00B9 + 'ordmasculine' => '551', # C+0xBA # U+0x00BA + 'guillemotright' => '610', # C+0xBB # U+0x00BB + 'onequarter' => '1071', # C+0xBC # U+0x00BC + 'onehalf' => '1071', # C+0xBD # U+0x00BD + 'threequarters' => '1071', # C+0xBE # U+0x00BE + 'questiondown' => '548', # C+0xBF # U+0x00BF + 'Agrave' => '758', # C+0xC0 # U+0x00C0 + 'Aacute' => '758', # C+0xC1 # U+0x00C1 + 'Acircumflex' => '758', # C+0xC2 # U+0x00C2 + 'Atilde' => '758', # C+0xC3 # U+0x00C3 + 'Adieresis' => '758', # C+0xC4 # U+0x00C4 + 'Aring' => '758', # C+0xC5 # U+0x00C5 + 'AE' => '1069', # C+0xC6 # U+0x00C6 + 'Ccedilla' => '715', # C+0xC7 # U+0x00C7 + 'Egrave' => '721', # C+0xC8 # U+0x00C8 + 'Eacute' => '721', # C+0xC9 # U+0x00C9 + 'Ecircumflex' => '721', # C+0xCA # U+0x00CA + 'Edieresis' => '721', # C+0xCB # U+0x00CB + 'Igrave' => '445', # C+0xCC # U+0x00CC + 'Iacute' => '445', # C+0xCD # U+0x00CD + 'Icircumflex' => '445', # C+0xCE # U+0x00CE + 'Idieresis' => '445', # C+0xCF # U+0x00CF + 'Eth' => '833', # C+0xD0 # U+0x00D0 + 'Ntilde' => '839', # C+0xD1 # U+0x00D1 + 'Ograve' => '819', # C+0xD2 # U+0x00D2 + 'Oacute' => '819', # C+0xD3 # U+0x00D3 + 'Ocircumflex' => '819', # C+0xD4 # U+0x00D4 + 'Otilde' => '819', # C+0xD5 # U+0x00D5 + 'Odieresis' => '819', # C+0xD6 # U+0x00D6 + 'multiply' => '703', # C+0xD7 # U+0x00D7 + 'Oslash' => '819', # C+0xD8 # U+0x00D8 + 'Ugrave' => '833', # C+0xD9 # U+0x00D9 + 'Uacute' => '833', # C+0xDA # U+0x00DA + 'Ucircumflex' => '833', # C+0xDB # U+0x00DB + 'Udieresis' => '833', # C+0xDC # U+0x00DC + 'Yacute' => '731', # C+0xDD # U+0x00DD + 'Thorn' => '708', # C+0xDE # U+0x00DE + 'germandbls' => '657', # C+0xDF # U+0x00DF + 'agrave' => '595', # C+0xE0 # U+0x00E0 + 'aacute' => '595', # C+0xE1 # U+0x00E1 + 'acircumflex' => '595', # C+0xE2 # U+0x00E2 + 'atilde' => '595', # C+0xE3 # U+0x00E3 + 'adieresis' => '595', # C+0xE4 # U+0x00E4 + 'aring' => '595', # C+0xE5 # U+0x00E5 + 'ae' => '857', # C+0xE6 # U+0x00E6 + 'ccedilla' => '531', # C+0xE7 # U+0x00E7 + 'egrave' => '571', # C+0xE8 # U+0x00E8 + 'eacute' => '571', # C+0xE9 # U+0x00E9 + 'ecircumflex' => '571', # C+0xEA # U+0x00EA + 'edieresis' => '571', # C+0xEB # U+0x00EB + 'igrave' => '353', # C+0xEC # U+0x00EC + 'iacute' => '353', # C+0xED # U+0x00ED + 'icircumflex' => '353', # C+0xEE # U+0x00EE + 'idieresis' => '353', # C+0xEF # U+0x00EF + 'eth' => '637', # C+0xF0 # U+0x00F0 + 'ntilde' => '689', # C+0xF1 # U+0x00F1 + 'ograve' => '635', # C+0xF2 # U+0x00F2 + 'oacute' => '635', # C+0xF3 # U+0x00F3 + 'ocircumflex' => '635', # C+0xF4 # U+0x00F4 + 'otilde' => '635', # C+0xF5 # U+0x00F5 + 'odieresis' => '635', # C+0xF6 # U+0x00F6 + 'divide' => '703', # C+0xF7 # U+0x00F7 + 'oslash' => '635', # C+0xF8 # U+0x00F8 + 'ugrave' => '676', # C+0xF9 # U+0x00F9 + 'uacute' => '676', # C+0xFA # U+0x00FA + 'ucircumflex' => '676', # C+0xFB # U+0x00FB + 'udieresis' => '676', # C+0xFC # U+0x00FC + 'yacute' => '562', # C+0xFD # U+0x00FD + 'thorn' => '645', # C+0xFE # U+0x00FE + 'ydieresis' => '562', # C+0xFF # U+0x00FF + 'middot' => '337', # U+0x00B7 + 'Amacron' => '758', # U+0x0100 + 'amacron' => '595', # U+0x0101 + 'Abreve' => '758', # U+0x0102 + 'abreve' => '595', # U+0x0103 + 'Aogonek' => '758', # U+0x0104 + 'aogonek' => '595', # U+0x0105 + 'Cacute' => '715', # U+0x0106 + 'cacute' => '531', # U+0x0107 + 'Ccircumflex' => '715', # U+0x0108 + 'ccircumflex' => '531', # U+0x0109 + 'Cdotaccent' => '715', # U+0x010A + 'cdotaccent' => '531', # U+0x010B + 'Ccaron' => '715', # U+0x010C + 'ccaron' => '531', # U+0x010D + 'Dcaron' => '833', # U+0x010E + 'dcaron' => '825', # U+0x010F + 'Dcroat' => '833', # U+0x0110 + 'dcroat' => '663', # U+0x0111 + 'Emacron' => '721', # U+0x0112 + 'emacron' => '571', # U+0x0113 + 'Ebreve' => '721', # U+0x0114 + 'ebreve' => '571', # U+0x0115 + 'Edotaccent' => '721', # U+0x0116 + 'edotaccent' => '571', # U+0x0117 + 'Eogonek' => '721', # U+0x0118 + 'eogonek' => '571', # U+0x0119 + 'Ecaron' => '721', # U+0x011A + 'ecaron' => '571', # U+0x011B + 'Gcircumflex' => '807', # U+0x011C + 'gcircumflex' => '576', # U+0x011D + 'Gbreve' => '807', # U+0x011E + 'gbreve' => '576', # U+0x011F + 'Gdotaccent' => '807', # U+0x0120 + 'gdotaccent' => '576', # U+0x0121 + 'Gcommaaccent' => '807', # U+0x0122 + 'gcommaaccent' => '576', # U+0x0123 + 'Hcircumflex' => '913', # U+0x0124 + 'hcircumflex' => '679', # U+0x0125 + 'Hbar' => '913', # U+0x0126 + 'hbar' => '679', # U+0x0127 + 'Itilde' => '445', # U+0x0128 + 'itilde' => '353', # U+0x0129 + 'Imacron' => '445', # U+0x012A + 'imacron' => '353', # U+0x012B + 'Ibreve' => '445', # U+0x012C + 'ibreve' => '353', # U+0x012D + 'Iogonek' => '445', # U+0x012E + 'iogonek' => '353', # U+0x012F + 'Idotaccent' => '445', # U+0x0130 + 'dotlessi' => '353', # U+0x0131 + 'IJ' => '996', # U+0x0132 + 'ij' => '676', # U+0x0133 + 'Jcircumflex' => '595', # U+0x0134 + 'jcircumflex' => '346', # U+0x0135 + 'Kcommaaccent' => '816', # U+0x0136 + 'kcommaaccent' => '631', # U+0x0137 + 'kgreenlandic' => '642', # U+0x0138 + 'Lacute' => '685', # U+0x0139 + 'lacute' => '344', # U+0x013A + 'Lcommaaccent' => '685', # U+0x013B + 'lcommaaccent' => '344', # U+0x013C + 'Lcaron' => '685', # U+0x013D + 'lcaron' => '507', # U+0x013E + 'Ldot' => '685', # U+0x013F + 'ldot' => '536', # U+0x0140 + 'Lslash' => '685', # U+0x0141 + 'lslash' => '344', # U+0x0142 + 'Nacute' => '839', # U+0x0143 + 'nacute' => '689', # U+0x0144 + 'Ncommaaccent' => '839', # U+0x0145 + 'ncommaaccent' => '689', # U+0x0146 + 'Ncaron' => '839', # U+0x0147 + 'ncaron' => '689', # U+0x0148 + 'napostrophe' => '827', # U+0x0149 + 'Eng' => '839', # U+0x014A + 'eng' => '680', # U+0x014B + 'Omacron' => '819', # U+0x014C + 'omacron' => '635', # U+0x014D + 'Obreve' => '819', # U+0x014E + 'obreve' => '635', # U+0x014F + 'Ohungarumlaut' => '819', # U+0x0150 + 'ohungarumlaut' => '635', # U+0x0151 + 'Racute' => '797', # U+0x0154 + 'racute' => '520', # U+0x0155 + 'Rcommaaccent' => '797', # U+0x0156 + 'rcommaaccent' => '520', # U+0x0157 + 'Rcaron' => '797', # U+0x0158 + 'rcaron' => '520', # U+0x0159 + 'Sacute' => '648', # U+0x015A + 'sacute' => '512', # U+0x015B + 'Scircumflex' => '648', # U+0x015C + 'scircumflex' => '512', # U+0x015D + 'Scedilla' => '648', # U+0x015E + 'scedilla' => '512', # U+0x015F + 'Tcommaaccent' => '684', # U+0x0162 + 'tcommaaccent' => '397', # U+0x0163 + 'Tcaron' => '684', # U+0x0164 + 'tcaron' => '397', # U+0x0165 + 'Tbar' => '684', # U+0x0166 + 'tbar' => '397', # U+0x0167 + 'Utilde' => '833', # U+0x0168 + 'utilde' => '676', # U+0x0169 + 'Umacron' => '833', # U+0x016A + 'umacron' => '676', # U+0x016B + 'Ubreve' => '833', # U+0x016C + 'ubreve' => '676', # U+0x016D + 'Uring' => '833', # U+0x016E + 'uring' => '676', # U+0x016F + 'Uhungarumlaut' => '833', # U+0x0170 + 'uhungarumlaut' => '676', # U+0x0171 + 'Uogonek' => '833', # U+0x0172 + 'uogonek' => '676', # U+0x0173 + 'Wcircumflex' => '1126', # U+0x0174 + 'wcircumflex' => '863', # U+0x0175 + 'Ycircumflex' => '731', # U+0x0176 + 'ycircumflex' => '562', # U+0x0177 + 'Zacute' => '689', # U+0x0179 + 'zacute' => '525', # U+0x017A + 'Zdotaccent' => '689', # U+0x017B + 'zdotaccent' => '525', # U+0x017C + 'longs' => '353', # U+0x017F + 'Aringacute' => '758', # U+0x01FA + 'aringacute' => '595', # U+0x01FB + 'AEacute' => '1069', # U+0x01FC + 'aeacute' => '857', # U+0x01FD + 'Oslashacute' => '819', # U+0x01FE + 'oslashacute' => '635', # U+0x01FF + 'Scommaaccent' => '648', # U+0x0218 + 'scommaaccent' => '512', # U+0x0219 + 'caron' => '500', # U+0x02C7 + 'breve' => '500', # U+0x02D8 + 'dotaccent' => '500', # U+0x02D9 + 'ring' => '500', # U+0x02DA + 'ogonek' => '500', # U+0x02DB + 'hungarumlaut' => '500', # U+0x02DD + 'tonos' => '500', # U+0x0384 + 'dieresistonos' => '500', # U+0x0385 + 'Alphatonos' => '758', # U+0x0386 + 'anoteleia' => '367', # U+0x0387 + 'Epsilontonos' => '880', # U+0x0388 + 'Etatonos' => '1072', # U+0x0389 + 'Iotatonos' => '604', # U+0x038A + 'Omicrontonos' => '922', # U+0x038C + 'Upsilontonos' => '935', # U+0x038E + 'Omegatonos' => '960', # U+0x038F + 'iotadieresistonos' => '342', # U+0x0390 + 'Alpha' => '758', # U+0x0391 + 'Beta' => '757', # U+0x0392 + 'Gamma' => '657', # U+0x0393 + 'Delta' => '739', # U+0x0394 + 'Epsilon' => '721', # U+0x0395 + 'Zeta' => '689', # U+0x0396 + 'Eta' => '913', # U+0x0397 + 'Theta' => '822', # U+0x0398 + 'Iota' => '445', # U+0x0399 + 'Kappa' => '816', # U+0x039A + 'Lambda' => '752', # U+0x039B + 'Mu' => '1023', # U+0x039C + 'Nu' => '839', # U+0x039D + 'Xi' => '766', # U+0x039E + 'Omicron' => '819', # U+0x039F + 'Pi' => '900', # U+0x03A0 + 'Rho' => '701', # U+0x03A1 + 'Sigma' => '679', # U+0x03A3 + 'Tau' => '684', # U+0x03A4 + 'Upsilon' => '731', # U+0x03A5 + 'Phi' => '911', # U+0x03A6 + 'Chi' => '808', # U+0x03A7 + 'Psi' => '1011', # U+0x03A8 + 'Omega' => '874', # U+0x03A9 + 'Iotadieresis' => '445', # U+0x03AA + 'Upsilondieresis' => '731', # U+0x03AB + 'alphatonos' => '679', # U+0x03AC + 'epsilontonos' => '535', # U+0x03AD + 'etatonos' => '660', # U+0x03AE + 'iotatonos' => '342', # U+0x03AF + 'upsilondieresistonos' => '592', # U+0x03B0 + 'alpha' => '679', # U+0x03B1 + 'beta' => '656', # U+0x03B2 + 'gamma' => '570', # U+0x03B3 + 'delta' => '635', # U+0x03B4 + 'epsilon' => '535', # U+0x03B5 + 'zeta' => '462', # U+0x03B6 + 'eta' => '660', # U+0x03B7 + 'theta' => '640', # U+0x03B8 + 'iota' => '342', # U+0x03B9 + 'kappa' => '630', # U+0x03BA + 'lambda' => '527', # U+0x03BB + 'nu' => '561', # U+0x03BD + 'xi' => '498', # U+0x03BE + 'omicron' => '635', # U+0x03BF + 'pi' => '659', # U+0x03C0 + 'rho' => '646', # U+0x03C1 + 'sigma1' => '513', # U+0x03C2 + 'sigma' => '669', # U+0x03C3 + 'tau' => '485', # U+0x03C4 + 'upsilon' => '592', # U+0x03C5 + 'phi' => '823', # U+0x03C6 + 'chi' => '566', # U+0x03C7 + 'psi' => '840', # U+0x03C8 + 'omega' => '812', # U+0x03C9 + 'iotadieresis' => '342', # U+0x03CA + 'upsilondieresis' => '592', # U+0x03CB + 'omicrontonos' => '635', # U+0x03CC + 'upsilontonos' => '592', # U+0x03CD + 'omegatonos' => '812', # U+0x03CE + 'afii10023' => '721', # U+0x0401 + 'afii10051' => '883', # U+0x0402 + 'afii10052' => '657', # U+0x0403 + 'afii10053' => '733', # U+0x0404 + 'afii10054' => '648', # U+0x0405 + 'afii10055' => '445', # U+0x0406 + 'afii10056' => '445', # U+0x0407 + 'afii10057' => '595', # U+0x0408 + 'afii10058' => '1124', # U+0x0409 + 'afii10059' => '1197', # U+0x040A + 'afii10060' => '935', # U+0x040B + 'afii10061' => '799', # U+0x040C + 'afii10062' => '727', # U+0x040E + 'afii10145' => '901', # U+0x040F + 'afii10017' => '758', # U+0x0410 + 'afii10018' => '747', # U+0x0411 + 'afii10019' => '757', # U+0x0412 + 'afii10020' => '657', # U+0x0413 + 'afii10021' => '800', # U+0x0414 + 'afii10022' => '721', # U+0x0415 + 'afii10024' => '1129', # U+0x0416 + 'afii10025' => '676', # U+0x0417 + 'afii10026' => '921', # U+0x0418 + 'afii10027' => '921', # U+0x0419 + 'afii10028' => '799', # U+0x041A + 'afii10029' => '834', # U+0x041B + 'afii10030' => '1023', # U+0x041C + 'afii10031' => '913', # U+0x041D + 'afii10032' => '819', # U+0x041E + 'afii10033' => '900', # U+0x041F + 'afii10034' => '701', # U+0x0420 + 'afii10035' => '715', # U+0x0421 + 'afii10036' => '684', # U+0x0422 + 'afii10037' => '727', # U+0x0423 + 'afii10038' => '911', # U+0x0424 + 'afii10039' => '808', # U+0x0425 + 'afii10040' => '901', # U+0x0426 + 'afii10041' => '832', # U+0x0427 + 'afii10042' => '1288', # U+0x0428 + 'afii10043' => '1288', # U+0x0429 + 'afii10044' => '863', # U+0x042A + 'afii10045' => '1103', # U+0x042B + 'afii10046' => '733', # U+0x042C + 'afii10047' => '729', # U+0x042D + 'afii10048' => '1181', # U+0x042E + 'afii10049' => '792', # U+0x042F + 'afii10065' => '595', # U+0x0430 + 'afii10066' => '625', # U+0x0431 + 'afii10067' => '619', # U+0x0432 + 'afii10068' => '497', # U+0x0433 + 'afii10069' => '615', # U+0x0434 + 'afii10070' => '571', # U+0x0435 + 'afii10072' => '891', # U+0x0436 + 'afii10073' => '539', # U+0x0437 + 'afii10074' => '717', # U+0x0438 + 'afii10075' => '717', # U+0x0439 + 'afii10076' => '640', # U+0x043A + 'afii10077' => '656', # U+0x043B + 'afii10078' => '802', # U+0x043C + 'afii10079' => '709', # U+0x043D + 'afii10080' => '635', # U+0x043E + 'afii10081' => '699', # U+0x043F + 'afii10082' => '657', # U+0x0440 + 'afii10083' => '531', # U+0x0441 + 'afii10084' => '545', # U+0x0442 + 'afii10085' => '562', # U+0x0443 + 'afii10086' => '875', # U+0x0444 + 'afii10087' => '587', # U+0x0445 + 'afii10088' => '702', # U+0x0446 + 'afii10089' => '666', # U+0x0447 + 'afii10090' => '989', # U+0x0448 + 'afii10091' => '992', # U+0x0449 + 'afii10092' => '680', # U+0x044A + 'afii10093' => '915', # U+0x044B + 'afii10094' => '592', # U+0x044C + 'afii10095' => '546', # U+0x044D + 'afii10096' => '937', # U+0x044E + 'afii10097' => '639', # U+0x044F + 'afii10071' => '571', # U+0x0451 + 'afii10099' => '670', # U+0x0452 + 'afii10100' => '497', # U+0x0453 + 'afii10101' => '558', # U+0x0454 + 'afii10102' => '512', # U+0x0455 + 'afii10103' => '353', # U+0x0456 + 'afii10104' => '353', # U+0x0457 + 'afii10105' => '346', # U+0x0458 + 'afii10106' => '882', # U+0x0459 + 'afii10107' => '932', # U+0x045A + 'afii10108' => '679', # U+0x045B + 'afii10109' => '640', # U+0x045C + 'afii10110' => '562', # U+0x045E + 'afii10193' => '699', # U+0x045F + 'afii10050' => '649', # U+0x0490 + 'afii10098' => '495', # U+0x0491 + 'Wgrave' => '1126', # U+0x1E80 + 'wgrave' => '863', # U+0x1E81 + 'Wacute' => '1126', # U+0x1E82 + 'wacute' => '863', # U+0x1E83 + 'Wdieresis' => '1126', # U+0x1E84 + 'wdieresis' => '863', # U+0x1E85 + 'Ygrave' => '731', # U+0x1EF2 + 'ygrave' => '562', # U+0x1EF3 + 'afii00208' => '927', # U+0x2015 + 'underscoredbl' => '703', # U+0x2017 + 'quotereversed' => '268', # U+0x201B + 'minute' => '321', # U+0x2032 + 'second' => '532', # U+0x2033 + 'exclamdbl' => '664', # U+0x203C + 'fraction' => '94', # U+0x2044 + 'foursuperior' => '551', # U+0x2074 + 'fivesuperior' => '551', # U+0x2075 + 'sevensuperior' => '551', # U+0x2077 + 'eightsuperior' => '551', # U+0x2078 + 'nsuperior' => '588', # U+0x207F + 'franc' => '689', # U+0x20A3 + 'lira' => '689', # U+0x20A4 + 'peseta' => '1355', # U+0x20A7 + 'afii61248' => '879', # U+0x2105 + 'afii61289' => '323', # U+0x2113 + 'afii61352' => '1279', # U+0x2116 + 'estimated' => '649', # U+0x212E + 'oneeighth' => '1071', # U+0x215B + 'threeeighths' => '1071', # U+0x215C + 'fiveeighths' => '1071', # U+0x215D + 'seveneighths' => '1071', # U+0x215E + 'partialdiff' => '646', # U+0x2202 + 'product' => '932', # U+0x220F + 'summation' => '729', # U+0x2211 + 'minus' => '703', # U+0x2212 + 'radical' => '716', # U+0x221A + 'infinity' => '798', # U+0x221E + 'integral' => '627', # U+0x222B + 'approxequal' => '703', # U+0x2248 + 'notequal' => '703', # U+0x2260 + 'lessequal' => '703', # U+0x2264 + 'greaterequal' => '703', # U+0x2265 + 'H22073' => '604', # U+0x25A1 + 'H18543' => '354', # U+0x25AA + 'H18551' => '354', # U+0x25AB + 'lozenge' => '717', # U+0x25CA + 'H18533' => '604', # U+0x25CF + 'openbullet' => '354', # U+0x25E6 + 'commaaccent' => '500', # U+0xF6C3 + 'Acute' => '500', # U+0xF6C9 + 'Caron' => '500', # U+0xF6CA + 'Dieresis' => '500', # U+0xF6CB + 'Grave' => '500', # U+0xF6CE + 'Hungarumlaut' => '500', # U+0xF6CF + 'radicalex' => '703', # U+0xF8E5 + 'fi' => '694', # U+0xFB01 + 'fl' => '705', # U+0xFB02 + }, # HORIZ. WIDTH TABLE +} }; + +1; diff --git a/lib/PDF/API2/Resource/Font/CoreFont/georgiabolditalic.pm b/lib/PDF/API2/Resource/Font/CoreFont/georgiabolditalic.pm new file mode 100644 index 0000000..134534c --- /dev/null +++ b/lib/PDF/API2/Resource/Font/CoreFont/georgiabolditalic.pm @@ -0,0 +1,863 @@ +#line 1 "PDF/API2/Resource/Font/CoreFont/georgiabolditalic.pm" +#line 1 "PDF/API2/Resource/Font/CoreFont/georgiabolditalic.pm" +package PDF::API2::Resource::Font::CoreFont::georgiabolditalic; + +use strict; +use warnings; + +our $VERSION = '2.033'; # VERSION + +sub data { return { + 'fontname' => 'Georgia,BoldItalic', + 'type' => 'TrueType', + 'apiname' => 'GeBoIt', + 'ascender' => '916', + 'capheight' => '692', + 'descender' => '-219', + 'isfixedpitch' => '0', + 'issymbol' => '0', + 'italicangle' => '-13', + 'underlineposition' => '-181', + 'underlinethickness' => '120', + 'xheight' => '495', + 'firstchar' => '32', + 'lastchar' => '255', + 'flags' => '262242', + 'char' => [ # DEF. ENCODING GLYPH TABLE + '.notdef', # C+0x00 # U+0x0000 + '.notdef', # C+0x01 # U+0x0000 + '.notdef', # C+0x02 # U+0x0000 + '.notdef', # C+0x03 # U+0x0000 + '.notdef', # C+0x04 # U+0x0000 + '.notdef', # C+0x05 # U+0x0000 + '.notdef', # C+0x06 # U+0x0000 + '.notdef', # C+0x07 # U+0x0000 + '.notdef', # C+0x08 # U+0x0000 + '.notdef', # C+0x09 # U+0x0000 + '.notdef', # C+0x0A # U+0x0000 + '.notdef', # C+0x0B # U+0x0000 + '.notdef', # C+0x0C # U+0x0000 + '.notdef', # C+0x0D # U+0x0000 + '.notdef', # C+0x0E # U+0x0000 + '.notdef', # C+0x0F # U+0x0000 + '.notdef', # C+0x10 # U+0x0000 + '.notdef', # C+0x11 # U+0x0000 + '.notdef', # C+0x12 # U+0x0000 + '.notdef', # C+0x13 # U+0x0000 + '.notdef', # C+0x14 # U+0x0000 + '.notdef', # C+0x15 # U+0x0000 + '.notdef', # C+0x16 # U+0x0000 + '.notdef', # C+0x17 # U+0x0000 + '.notdef', # C+0x18 # U+0x0000 + '.notdef', # C+0x19 # U+0x0000 + '.notdef', # C+0x1A # U+0x0000 + '.notdef', # C+0x1B # U+0x0000 + '.notdef', # C+0x1C # U+0x0000 + '.notdef', # C+0x1D # U+0x0000 + '.notdef', # C+0x1E # U+0x0000 + '.notdef', # C+0x1F # U+0x0000 + 'space', # C+0x20 # U+0x0020 + 'exclam', # C+0x21 # U+0x0021 + 'quotedbl', # C+0x22 # U+0x0022 + 'numbersign', # C+0x23 # U+0x0023 + 'dollar', # C+0x24 # U+0x0024 + 'percent', # C+0x25 # U+0x0025 + 'ampersand', # C+0x26 # U+0x0026 + 'quotesingle', # C+0x27 # U+0x0027 + 'parenleft', # C+0x28 # U+0x0028 + 'parenright', # C+0x29 # U+0x0029 + 'asterisk', # C+0x2A # U+0x002A + 'plus', # C+0x2B # U+0x002B + 'comma', # C+0x2C # U+0x002C + 'hyphen', # C+0x2D # U+0x002D + 'period', # C+0x2E # U+0x002E + 'slash', # C+0x2F # U+0x002F + 'zero', # C+0x30 # U+0x0030 + 'one', # C+0x31 # U+0x0031 + 'two', # C+0x32 # U+0x0032 + 'three', # C+0x33 # U+0x0033 + 'four', # C+0x34 # U+0x0034 + 'five', # C+0x35 # U+0x0035 + 'six', # C+0x36 # U+0x0036 + 'seven', # C+0x37 # U+0x0037 + 'eight', # C+0x38 # U+0x0038 + 'nine', # C+0x39 # U+0x0039 + 'colon', # C+0x3A # U+0x003A + 'semicolon', # C+0x3B # U+0x003B + 'less', # C+0x3C # U+0x003C + 'equal', # C+0x3D # U+0x003D + 'greater', # C+0x3E # U+0x003E + 'question', # C+0x3F # U+0x003F + 'at', # C+0x40 # U+0x0040 + 'A', # C+0x41 # U+0x0041 + 'B', # C+0x42 # U+0x0042 + 'C', # C+0x43 # U+0x0043 + 'D', # C+0x44 # U+0x0044 + 'E', # C+0x45 # U+0x0045 + 'F', # C+0x46 # U+0x0046 + 'G', # C+0x47 # U+0x0047 + 'H', # C+0x48 # U+0x0048 + 'I', # C+0x49 # U+0x0049 + 'J', # C+0x4A # U+0x004A + 'K', # C+0x4B # U+0x004B + 'L', # C+0x4C # U+0x004C + 'M', # C+0x4D # U+0x004D + 'N', # C+0x4E # U+0x004E + 'O', # C+0x4F # U+0x004F + 'P', # C+0x50 # U+0x0050 + 'Q', # C+0x51 # U+0x0051 + 'R', # C+0x52 # U+0x0052 + 'S', # C+0x53 # U+0x0053 + 'T', # C+0x54 # U+0x0054 + 'U', # C+0x55 # U+0x0055 + 'V', # C+0x56 # U+0x0056 + 'W', # C+0x57 # U+0x0057 + 'X', # C+0x58 # U+0x0058 + 'Y', # C+0x59 # U+0x0059 + 'Z', # C+0x5A # U+0x005A + 'bracketleft', # C+0x5B # U+0x005B + 'backslash', # C+0x5C # U+0x005C + 'bracketright', # C+0x5D # U+0x005D + 'asciicircum', # C+0x5E # U+0x005E + 'underscore', # C+0x5F # U+0x005F + 'grave', # C+0x60 # U+0x0060 + 'a', # C+0x61 # U+0x0061 + 'b', # C+0x62 # U+0x0062 + 'c', # C+0x63 # U+0x0063 + 'd', # C+0x64 # U+0x0064 + 'e', # C+0x65 # U+0x0065 + 'f', # C+0x66 # U+0x0066 + 'g', # C+0x67 # U+0x0067 + 'h', # C+0x68 # U+0x0068 + 'i', # C+0x69 # U+0x0069 + 'j', # C+0x6A # U+0x006A + 'k', # C+0x6B # U+0x006B + 'l', # C+0x6C # U+0x006C + 'm', # C+0x6D # U+0x006D + 'n', # C+0x6E # U+0x006E + 'o', # C+0x6F # U+0x006F + 'p', # C+0x70 # U+0x0070 + 'q', # C+0x71 # U+0x0071 + 'r', # C+0x72 # U+0x0072 + 's', # C+0x73 # U+0x0073 + 't', # C+0x74 # U+0x0074 + 'u', # C+0x75 # U+0x0075 + 'v', # C+0x76 # U+0x0076 + 'w', # C+0x77 # U+0x0077 + 'x', # C+0x78 # U+0x0078 + 'y', # C+0x79 # U+0x0079 + 'z', # C+0x7A # U+0x007A + 'braceleft', # C+0x7B # U+0x007B + 'bar', # C+0x7C # U+0x007C + 'braceright', # C+0x7D # U+0x007D + 'asciitilde', # C+0x7E # U+0x007E + 'bullet', # C+0x7F # U+0x2022 + 'Euro', # C+0x80 # U+0x20AC + 'bullet', # C+0x81 # U+0x2022 + 'quotesinglbase', # C+0x82 # U+0x201A + 'florin', # C+0x83 # U+0x0192 + 'quotedblbase', # C+0x84 # U+0x201E + 'ellipsis', # C+0x85 # U+0x2026 + 'dagger', # C+0x86 # U+0x2020 + 'daggerdbl', # C+0x87 # U+0x2021 + 'circumflex', # C+0x88 # U+0x02C6 + 'perthousand', # C+0x89 # U+0x2030 + 'Scaron', # C+0x8A # U+0x0160 + 'guilsinglleft', # C+0x8B # U+0x2039 + 'OE', # C+0x8C # U+0x0152 + 'bullet', # C+0x8D # U+0x2022 + 'Zcaron', # C+0x8E # U+0x017D + 'bullet', # C+0x8F # U+0x2022 + 'bullet', # C+0x90 # U+0x2022 + 'quoteleft', # C+0x91 # U+0x2018 + 'quoteright', # C+0x92 # U+0x2019 + 'quotedblleft', # C+0x93 # U+0x201C + 'quotedblright', # C+0x94 # U+0x201D + 'bullet', # C+0x95 # U+0x2022 + 'endash', # C+0x96 # U+0x2013 + 'emdash', # C+0x97 # U+0x2014 + 'tilde', # C+0x98 # U+0x02DC + 'trademark', # C+0x99 # U+0x2122 + 'scaron', # C+0x9A # U+0x0161 + 'guilsinglright', # C+0x9B # U+0x203A + 'oe', # C+0x9C # U+0x0153 + 'bullet', # C+0x9D # U+0x2022 + 'zcaron', # C+0x9E # U+0x017E + 'Ydieresis', # C+0x9F # U+0x0178 + 'space', # C+0xA0 # U+0x0020 + 'exclamdown', # C+0xA1 # U+0x00A1 + 'cent', # C+0xA2 # U+0x00A2 + 'sterling', # C+0xA3 # U+0x00A3 + 'currency', # C+0xA4 # U+0x00A4 + 'yen', # C+0xA5 # U+0x00A5 + 'brokenbar', # C+0xA6 # U+0x00A6 + 'section', # C+0xA7 # U+0x00A7 + 'dieresis', # C+0xA8 # U+0x00A8 + 'copyright', # C+0xA9 # U+0x00A9 + 'ordfeminine', # C+0xAA # U+0x00AA + 'guillemotleft', # C+0xAB # U+0x00AB + 'logicalnot', # C+0xAC # U+0x00AC + 'hyphen', # C+0xAD # U+0x002D + 'registered', # C+0xAE # U+0x00AE + 'macron', # C+0xAF # U+0x00AF + 'degree', # C+0xB0 # U+0x00B0 + 'plusminus', # C+0xB1 # U+0x00B1 + 'twosuperior', # C+0xB2 # U+0x00B2 + 'threesuperior', # C+0xB3 # U+0x00B3 + 'acute', # C+0xB4 # U+0x00B4 + 'mu', # C+0xB5 # U+0x00B5 + 'paragraph', # C+0xB6 # U+0x00B6 + 'periodcentered', # C+0xB7 # U+0x00B7 + 'cedilla', # C+0xB8 # U+0x00B8 + 'onesuperior', # C+0xB9 # U+0x00B9 + 'ordmasculine', # C+0xBA # U+0x00BA + 'guillemotright', # C+0xBB # U+0x00BB + 'onequarter', # C+0xBC # U+0x00BC + 'onehalf', # C+0xBD # U+0x00BD + 'threequarters', # C+0xBE # U+0x00BE + 'questiondown', # C+0xBF # U+0x00BF + 'Agrave', # C+0xC0 # U+0x00C0 + 'Aacute', # C+0xC1 # U+0x00C1 + 'Acircumflex', # C+0xC2 # U+0x00C2 + 'Atilde', # C+0xC3 # U+0x00C3 + 'Adieresis', # C+0xC4 # U+0x00C4 + 'Aring', # C+0xC5 # U+0x00C5 + 'AE', # C+0xC6 # U+0x00C6 + 'Ccedilla', # C+0xC7 # U+0x00C7 + 'Egrave', # C+0xC8 # U+0x00C8 + 'Eacute', # C+0xC9 # U+0x00C9 + 'Ecircumflex', # C+0xCA # U+0x00CA + 'Edieresis', # C+0xCB # U+0x00CB + 'Igrave', # C+0xCC # U+0x00CC + 'Iacute', # C+0xCD # U+0x00CD + 'Icircumflex', # C+0xCE # U+0x00CE + 'Idieresis', # C+0xCF # U+0x00CF + 'Eth', # C+0xD0 # U+0x00D0 + 'Ntilde', # C+0xD1 # U+0x00D1 + 'Ograve', # C+0xD2 # U+0x00D2 + 'Oacute', # C+0xD3 # U+0x00D3 + 'Ocircumflex', # C+0xD4 # U+0x00D4 + 'Otilde', # C+0xD5 # U+0x00D5 + 'Odieresis', # C+0xD6 # U+0x00D6 + 'multiply', # C+0xD7 # U+0x00D7 + 'Oslash', # C+0xD8 # U+0x00D8 + 'Ugrave', # C+0xD9 # U+0x00D9 + 'Uacute', # C+0xDA # U+0x00DA + 'Ucircumflex', # C+0xDB # U+0x00DB + 'Udieresis', # C+0xDC # U+0x00DC + 'Yacute', # C+0xDD # U+0x00DD + 'Thorn', # C+0xDE # U+0x00DE + 'germandbls', # C+0xDF # U+0x00DF + 'agrave', # C+0xE0 # U+0x00E0 + 'aacute', # C+0xE1 # U+0x00E1 + 'acircumflex', # C+0xE2 # U+0x00E2 + 'atilde', # C+0xE3 # U+0x00E3 + 'adieresis', # C+0xE4 # U+0x00E4 + 'aring', # C+0xE5 # U+0x00E5 + 'ae', # C+0xE6 # U+0x00E6 + 'ccedilla', # C+0xE7 # U+0x00E7 + 'egrave', # C+0xE8 # U+0x00E8 + 'eacute', # C+0xE9 # U+0x00E9 + 'ecircumflex', # C+0xEA # U+0x00EA + 'edieresis', # C+0xEB # U+0x00EB + 'igrave', # C+0xEC # U+0x00EC + 'iacute', # C+0xED # U+0x00ED + 'icircumflex', # C+0xEE # U+0x00EE + 'idieresis', # C+0xEF # U+0x00EF + 'eth', # C+0xF0 # U+0x00F0 + 'ntilde', # C+0xF1 # U+0x00F1 + 'ograve', # C+0xF2 # U+0x00F2 + 'oacute', # C+0xF3 # U+0x00F3 + 'ocircumflex', # C+0xF4 # U+0x00F4 + 'otilde', # C+0xF5 # U+0x00F5 + 'odieresis', # C+0xF6 # U+0x00F6 + 'divide', # C+0xF7 # U+0x00F7 + 'oslash', # C+0xF8 # U+0x00F8 + 'ugrave', # C+0xF9 # U+0x00F9 + 'uacute', # C+0xFA # U+0x00FA + 'ucircumflex', # C+0xFB # U+0x00FB + 'udieresis', # C+0xFC # U+0x00FC + 'yacute', # C+0xFD # U+0x00FD + 'thorn', # C+0xFE # U+0x00FE + 'ydieresis', # C+0xFF # U+0x00FF + ], # DEF. ENCODING GLYPH TABLE + 'fontbbox' => [ -242, -216, 1354, 914 ], + 'wx' => { # HORIZ. WIDTH TABLE + 'space' => '253', # C+0x20 # U+0x0020 + 'exclam' => '376', # C+0x21 # U+0x0021 + 'quotedbl' => '509', # C+0x22 # U+0x0022 + 'numbersign' => '703', # C+0x23 # U+0x0023 + 'dollar' => '640', # C+0x24 # U+0x0024 + 'percent' => '879', # C+0x25 # U+0x0025 + 'ampersand' => '799', # C+0x26 # U+0x0026 + 'quotesingle' => '269', # C+0x27 # U+0x0027 + 'parenleft' => '446', # C+0x28 # U+0x0028 + 'parenright' => '446', # C+0x29 # U+0x0029 + 'asterisk' => '481', # C+0x2A # U+0x002A + 'plus' => '703', # C+0x2B # U+0x002B + 'comma' => '328', # C+0x2C # U+0x002C + 'hyphen' => '378', # C+0x2D # U+0x002D + 'period' => '328', # C+0x2E # U+0x002E + 'slash' => '471', # C+0x2F # U+0x002F + 'zero' => '701', # C+0x30 # U+0x0030 + 'one' => '489', # C+0x31 # U+0x0031 + 'two' => '626', # C+0x32 # U+0x0032 + 'three' => '624', # C+0x33 # U+0x0033 + 'four' => '649', # C+0x34 # U+0x0034 + 'five' => '599', # C+0x35 # U+0x0035 + 'six' => '647', # C+0x36 # U+0x0036 + 'seven' => '566', # C+0x37 # U+0x0037 + 'eight' => '676', # C+0x38 # U+0x0038 + 'nine' => '647', # C+0x39 # U+0x0039 + 'colon' => '367', # C+0x3A # U+0x003A + 'semicolon' => '367', # C+0x3B # U+0x003B + 'less' => '703', # C+0x3C # U+0x003C + 'equal' => '703', # C+0x3D # U+0x003D + 'greater' => '703', # C+0x3E # U+0x003E + 'question' => '548', # C+0x3F # U+0x003F + 'at' => '966', # C+0x40 # U+0x0040 + 'A' => '758', # C+0x41 # U+0x0041 + 'B' => '759', # C+0x42 # U+0x0042 + 'C' => '715', # C+0x43 # U+0x0043 + 'D' => '833', # C+0x44 # U+0x0044 + 'E' => '721', # C+0x45 # U+0x0045 + 'F' => '671', # C+0x46 # U+0x0046 + 'G' => '807', # C+0x47 # U+0x0047 + 'H' => '913', # C+0x48 # U+0x0048 + 'I' => '450', # C+0x49 # U+0x0049 + 'J' => '595', # C+0x4A # U+0x004A + 'K' => '816', # C+0x4B # U+0x004B + 'L' => '685', # C+0x4C # U+0x004C + 'M' => '1033', # C+0x4D # U+0x004D + 'N' => '829', # C+0x4E # U+0x004E + 'O' => '819', # C+0x4F # U+0x004F + 'P' => '706', # C+0x50 # U+0x0050 + 'Q' => '819', # C+0x51 # U+0x0051 + 'R' => '797', # C+0x52 # U+0x0052 + 'S' => '652', # C+0x53 # U+0x0053 + 'T' => '684', # C+0x54 # U+0x0054 + 'U' => '833', # C+0x55 # U+0x0055 + 'V' => '762', # C+0x56 # U+0x0056 + 'W' => '1126', # C+0x57 # U+0x0057 + 'X' => '802', # C+0x58 # U+0x0058 + 'Y' => '731', # C+0x59 # U+0x0059 + 'Z' => '689', # C+0x5A # U+0x005A + 'bracketleft' => '446', # C+0x5B # U+0x005B + 'backslash' => '471', # C+0x5C # U+0x005C + 'bracketright' => '446', # C+0x5D # U+0x005D + 'asciicircum' => '703', # C+0x5E # U+0x005E + 'underscore' => '703', # C+0x5F # U+0x005F + 'grave' => '500', # C+0x60 # U+0x0060 + 'a' => '660', # C+0x61 # U+0x0061 + 'b' => '648', # C+0x62 # U+0x0062 + 'c' => '535', # C+0x63 # U+0x0063 + 'd' => '662', # C+0x64 # U+0x0064 + 'e' => '557', # C+0x65 # U+0x0065 + 'f' => '380', # C+0x66 # U+0x0066 + 'g' => '649', # C+0x67 # U+0x0067 + 'h' => '675', # C+0x68 # U+0x0068 + 'i' => '365', # C+0x69 # U+0x0069 + 'j' => '364', # C+0x6A # U+0x006A + 'k' => '641', # C+0x6B # U+0x006B + 'l' => '354', # C+0x6C # U+0x006C + 'm' => '1001', # C+0x6D # U+0x006D + 'n' => '689', # C+0x6E # U+0x006E + 'o' => '635', # C+0x6F # U+0x006F + 'p' => '662', # C+0x70 # U+0x0070 + 'q' => '649', # C+0x71 # U+0x0071 + 'r' => '533', # C+0x72 # U+0x0072 + 's' => '517', # C+0x73 # U+0x0073 + 't' => '416', # C+0x74 # U+0x0074 + 'u' => '685', # C+0x75 # U+0x0075 + 'v' => '612', # C+0x76 # U+0x0076 + 'w' => '933', # C+0x77 # U+0x0077 + 'x' => '583', # C+0x78 # U+0x0078 + 'y' => '669', # C+0x79 # U+0x0079 + 'z' => '517', # C+0x7A # U+0x007A + 'braceleft' => '500', # C+0x7B # U+0x007B + 'bar' => '387', # C+0x7C # U+0x007C + 'braceright' => '500', # C+0x7D # U+0x007D + 'asciitilde' => '703', # C+0x7E # U+0x007E + 'bullet' => '437', # C+0x7F # U+0x2022 + 'Euro' => '715', # C+0x80 # U+0x20AC + 'quotesinglbase' => '268', # C+0x82 # U+0x201A + 'florin' => '579', # C+0x83 # U+0x0192 + 'quotedblbase' => '519', # C+0x84 # U+0x201E + 'ellipsis' => '941', # C+0x85 # U+0x2026 + 'dagger' => '481', # C+0x86 # U+0x2020 + 'daggerdbl' => '481', # C+0x87 # U+0x2021 + 'circumflex' => '500', # C+0x88 # U+0x02C6 + 'perthousand' => '1316', # C+0x89 # U+0x2030 + 'Scaron' => '648', # C+0x8A # U+0x0160 + 'guilsinglleft' => '395', # C+0x8B # U+0x2039 + 'OE' => '1105', # C+0x8C # U+0x0152 + 'Zcaron' => '689', # C+0x8E # U+0x017D + 'quoteleft' => '268', # C+0x91 # U+0x2018 + 'quoteright' => '268', # C+0x92 # U+0x2019 + 'quotedblleft' => '519', # C+0x93 # U+0x201C + 'quotedblright' => '519', # C+0x94 # U+0x201D + 'endash' => '703', # C+0x96 # U+0x2013 + 'emdash' => '927', # C+0x97 # U+0x2014 + 'tilde' => '500', # C+0x98 # U+0x02DC + 'trademark' => '947', # C+0x99 # U+0x2122 + 'scaron' => '517', # C+0x9A # U+0x0161 + 'guilsinglright' => '395', # C+0x9B # U+0x203A + 'oe' => '932', # C+0x9C # U+0x0153 + 'zcaron' => '517', # C+0x9E # U+0x017E + 'Ydieresis' => '731', # C+0x9F # U+0x0178 + 'exclamdown' => '376', # C+0xA1 # U+0x00A1 + 'cent' => '605', # C+0xA2 # U+0x00A2 + 'sterling' => '689', # C+0xA3 # U+0x00A3 + 'currency' => '703', # C+0xA4 # U+0x00A4 + 'yen' => '732', # C+0xA5 # U+0x00A5 + 'brokenbar' => '387', # C+0xA6 # U+0x00A6 + 'section' => '563', # C+0xA7 # U+0x00A7 + 'dieresis' => '500', # C+0xA8 # U+0x00A8 + 'copyright' => '941', # C+0xA9 # U+0x00A9 + 'ordfeminine' => '551', # C+0xAA # U+0x00AA + 'guillemotleft' => '610', # C+0xAB # U+0x00AB + 'logicalnot' => '703', # C+0xAC # U+0x00AC + 'registered' => '941', # C+0xAE # U+0x00AE + 'macron' => '500', # C+0xAF # U+0x00AF + 'degree' => '419', # C+0xB0 # U+0x00B0 + 'plusminus' => '703', # C+0xB1 # U+0x00B1 + 'twosuperior' => '551', # C+0xB2 # U+0x00B2 + 'threesuperior' => '551', # C+0xB3 # U+0x00B3 + 'acute' => '500', # C+0xB4 # U+0x00B4 + 'mu' => '669', # C+0xB5 # U+0x00B5 + 'paragraph' => '622', # C+0xB6 # U+0x00B6 + 'periodcentered' => '337', # C+0xB7 # U+0x00B7 + 'cedilla' => '500', # C+0xB8 # U+0x00B8 + 'onesuperior' => '551', # C+0xB9 # U+0x00B9 + 'ordmasculine' => '551', # C+0xBA # U+0x00BA + 'guillemotright' => '610', # C+0xBB # U+0x00BB + 'onequarter' => '1071', # C+0xBC # U+0x00BC + 'onehalf' => '1071', # C+0xBD # U+0x00BD + 'threequarters' => '1071', # C+0xBE # U+0x00BE + 'questiondown' => '548', # C+0xBF # U+0x00BF + 'Agrave' => '758', # C+0xC0 # U+0x00C0 + 'Aacute' => '758', # C+0xC1 # U+0x00C1 + 'Acircumflex' => '758', # C+0xC2 # U+0x00C2 + 'Atilde' => '758', # C+0xC3 # U+0x00C3 + 'Adieresis' => '758', # C+0xC4 # U+0x00C4 + 'Aring' => '758', # C+0xC5 # U+0x00C5 + 'AE' => '1074', # C+0xC6 # U+0x00C6 + 'Ccedilla' => '715', # C+0xC7 # U+0x00C7 + 'Egrave' => '721', # C+0xC8 # U+0x00C8 + 'Eacute' => '721', # C+0xC9 # U+0x00C9 + 'Ecircumflex' => '721', # C+0xCA # U+0x00CA + 'Edieresis' => '721', # C+0xCB # U+0x00CB + 'Igrave' => '445', # C+0xCC # U+0x00CC + 'Iacute' => '445', # C+0xCD # U+0x00CD + 'Icircumflex' => '445', # C+0xCE # U+0x00CE + 'Idieresis' => '450', # C+0xCF # U+0x00CF + 'Eth' => '833', # C+0xD0 # U+0x00D0 + 'Ntilde' => '829', # C+0xD1 # U+0x00D1 + 'Ograve' => '819', # C+0xD2 # U+0x00D2 + 'Oacute' => '819', # C+0xD3 # U+0x00D3 + 'Ocircumflex' => '819', # C+0xD4 # U+0x00D4 + 'Otilde' => '819', # C+0xD5 # U+0x00D5 + 'Odieresis' => '819', # C+0xD6 # U+0x00D6 + 'multiply' => '703', # C+0xD7 # U+0x00D7 + 'Oslash' => '819', # C+0xD8 # U+0x00D8 + 'Ugrave' => '833', # C+0xD9 # U+0x00D9 + 'Uacute' => '833', # C+0xDA # U+0x00DA + 'Ucircumflex' => '833', # C+0xDB # U+0x00DB + 'Udieresis' => '833', # C+0xDC # U+0x00DC + 'Yacute' => '731', # C+0xDD # U+0x00DD + 'Thorn' => '708', # C+0xDE # U+0x00DE + 'germandbls' => '655', # C+0xDF # U+0x00DF + 'agrave' => '660', # C+0xE0 # U+0x00E0 + 'aacute' => '660', # C+0xE1 # U+0x00E1 + 'acircumflex' => '660', # C+0xE2 # U+0x00E2 + 'atilde' => '660', # C+0xE3 # U+0x00E3 + 'adieresis' => '660', # C+0xE4 # U+0x00E4 + 'aring' => '660', # C+0xE5 # U+0x00E5 + 'ae' => '856', # C+0xE6 # U+0x00E6 + 'ccedilla' => '535', # C+0xE7 # U+0x00E7 + 'egrave' => '557', # C+0xE8 # U+0x00E8 + 'eacute' => '557', # C+0xE9 # U+0x00E9 + 'ecircumflex' => '557', # C+0xEA # U+0x00EA + 'edieresis' => '557', # C+0xEB # U+0x00EB + 'igrave' => '365', # C+0xEC # U+0x00EC + 'iacute' => '365', # C+0xED # U+0x00ED + 'icircumflex' => '365', # C+0xEE # U+0x00EE + 'idieresis' => '365', # C+0xEF # U+0x00EF + 'eth' => '637', # C+0xF0 # U+0x00F0 + 'ntilde' => '689', # C+0xF1 # U+0x00F1 + 'ograve' => '635', # C+0xF2 # U+0x00F2 + 'oacute' => '635', # C+0xF3 # U+0x00F3 + 'ocircumflex' => '635', # C+0xF4 # U+0x00F4 + 'otilde' => '635', # C+0xF5 # U+0x00F5 + 'odieresis' => '635', # C+0xF6 # U+0x00F6 + 'divide' => '703', # C+0xF7 # U+0x00F7 + 'oslash' => '635', # C+0xF8 # U+0x00F8 + 'ugrave' => '685', # C+0xF9 # U+0x00F9 + 'uacute' => '685', # C+0xFA # U+0x00FA + 'ucircumflex' => '685', # C+0xFB # U+0x00FB + 'udieresis' => '685', # C+0xFC # U+0x00FC + 'yacute' => '669', # C+0xFD # U+0x00FD + 'thorn' => '647', # C+0xFE # U+0x00FE + 'ydieresis' => '669', # C+0xFF # U+0x00FF + 'middot' => '337', # U+0x00B7 + 'Amacron' => '758', # U+0x0100 + 'amacron' => '660', # U+0x0101 + 'Abreve' => '758', # U+0x0102 + 'abreve' => '660', # U+0x0103 + 'Aogonek' => '758', # U+0x0104 + 'aogonek' => '660', # U+0x0105 + 'Cacute' => '715', # U+0x0106 + 'cacute' => '535', # U+0x0107 + 'Ccircumflex' => '715', # U+0x0108 + 'ccircumflex' => '535', # U+0x0109 + 'Cdotaccent' => '715', # U+0x010A + 'cdotaccent' => '535', # U+0x010B + 'Ccaron' => '715', # U+0x010C + 'ccaron' => '535', # U+0x010D + 'Dcaron' => '833', # U+0x010E + 'dcaron' => '825', # U+0x010F + 'Dcroat' => '833', # U+0x0110 + 'dcroat' => '662', # U+0x0111 + 'Emacron' => '721', # U+0x0112 + 'emacron' => '557', # U+0x0113 + 'Ebreve' => '721', # U+0x0114 + 'ebreve' => '557', # U+0x0115 + 'Edotaccent' => '721', # U+0x0116 + 'edotaccent' => '557', # U+0x0117 + 'Eogonek' => '721', # U+0x0118 + 'eogonek' => '557', # U+0x0119 + 'Ecaron' => '721', # U+0x011A + 'ecaron' => '557', # U+0x011B + 'Gcircumflex' => '807', # U+0x011C + 'gcircumflex' => '649', # U+0x011D + 'Gbreve' => '807', # U+0x011E + 'gbreve' => '649', # U+0x011F + 'Gdotaccent' => '807', # U+0x0120 + 'gdotaccent' => '649', # U+0x0121 + 'Gcommaaccent' => '807', # U+0x0122 + 'gcommaaccent' => '649', # U+0x0123 + 'Hcircumflex' => '913', # U+0x0124 + 'hcircumflex' => '675', # U+0x0125 + 'Hbar' => '913', # U+0x0126 + 'hbar' => '675', # U+0x0127 + 'Itilde' => '450', # U+0x0128 + 'itilde' => '365', # U+0x0129 + 'Imacron' => '450', # U+0x012A + 'imacron' => '365', # U+0x012B + 'Ibreve' => '450', # U+0x012C + 'ibreve' => '365', # U+0x012D + 'Iogonek' => '450', # U+0x012E + 'iogonek' => '365', # U+0x012F + 'Idotaccent' => '450', # U+0x0130 + 'dotlessi' => '365', # U+0x0131 + 'IJ' => '996', # U+0x0132 + 'ij' => '682', # U+0x0133 + 'Jcircumflex' => '595', # U+0x0134 + 'jcircumflex' => '364', # U+0x0135 + 'Kcommaaccent' => '816', # U+0x0136 + 'kcommaaccent' => '641', # U+0x0137 + 'kgreenlandic' => '655', # U+0x0138 + 'Lacute' => '685', # U+0x0139 + 'lacute' => '354', # U+0x013A + 'Lcommaaccent' => '685', # U+0x013B + 'lcommaaccent' => '354', # U+0x013C + 'Lcaron' => '685', # U+0x013D + 'lcaron' => '511', # U+0x013E + 'Ldot' => '685', # U+0x013F + 'ldot' => '546', # U+0x0140 + 'Lslash' => '685', # U+0x0141 + 'lslash' => '354', # U+0x0142 + 'Nacute' => '829', # U+0x0143 + 'nacute' => '689', # U+0x0144 + 'Ncommaaccent' => '829', # U+0x0145 + 'ncommaaccent' => '689', # U+0x0146 + 'Ncaron' => '829', # U+0x0147 + 'ncaron' => '689', # U+0x0148 + 'napostrophe' => '832', # U+0x0149 + 'Eng' => '829', # U+0x014A + 'eng' => '677', # U+0x014B + 'Omacron' => '819', # U+0x014C + 'omacron' => '635', # U+0x014D + 'Obreve' => '819', # U+0x014E + 'obreve' => '635', # U+0x014F + 'Ohungarumlaut' => '819', # U+0x0150 + 'ohungarumlaut' => '635', # U+0x0151 + 'Racute' => '797', # U+0x0154 + 'racute' => '533', # U+0x0155 + 'Rcommaaccent' => '797', # U+0x0156 + 'rcommaaccent' => '533', # U+0x0157 + 'Rcaron' => '797', # U+0x0158 + 'rcaron' => '533', # U+0x0159 + 'Sacute' => '652', # U+0x015A + 'sacute' => '517', # U+0x015B + 'Scircumflex' => '652', # U+0x015C + 'scircumflex' => '517', # U+0x015D + 'Scedilla' => '652', # U+0x015E + 'scedilla' => '517', # U+0x015F + 'Tcommaaccent' => '684', # U+0x0162 + 'tcommaaccent' => '416', # U+0x0163 + 'Tcaron' => '684', # U+0x0164 + 'tcaron' => '416', # U+0x0165 + 'Tbar' => '684', # U+0x0166 + 'tbar' => '416', # U+0x0167 + 'Utilde' => '833', # U+0x0168 + 'utilde' => '685', # U+0x0169 + 'Umacron' => '833', # U+0x016A + 'umacron' => '685', # U+0x016B + 'Ubreve' => '833', # U+0x016C + 'ubreve' => '685', # U+0x016D + 'Uring' => '833', # U+0x016E + 'uring' => '685', # U+0x016F + 'Uhungarumlaut' => '833', # U+0x0170 + 'uhungarumlaut' => '685', # U+0x0171 + 'Uogonek' => '833', # U+0x0172 + 'uogonek' => '685', # U+0x0173 + 'Wcircumflex' => '1126', # U+0x0174 + 'wcircumflex' => '933', # U+0x0175 + 'Ycircumflex' => '731', # U+0x0176 + 'ycircumflex' => '669', # U+0x0177 + 'Zacute' => '689', # U+0x0179 + 'zacute' => '517', # U+0x017A + 'Zdotaccent' => '689', # U+0x017B + 'zdotaccent' => '517', # U+0x017C + 'longs' => '361', # U+0x017F + 'Aringacute' => '758', # U+0x01FA + 'aringacute' => '660', # U+0x01FB + 'AEacute' => '1074', # U+0x01FC + 'aeacute' => '856', # U+0x01FD + 'Oslashacute' => '819', # U+0x01FE + 'oslashacute' => '635', # U+0x01FF + 'Scommaaccent' => '652', # U+0x0218 + 'scommaaccent' => '517', # U+0x0219 + 'caron' => '500', # U+0x02C7 + 'breve' => '500', # U+0x02D8 + 'dotaccent' => '500', # U+0x02D9 + 'ring' => '500', # U+0x02DA + 'ogonek' => '500', # U+0x02DB + 'hungarumlaut' => '500', # U+0x02DD + 'tonos' => '500', # U+0x0384 + 'dieresistonos' => '500', # U+0x0385 + 'Alphatonos' => '758', # U+0x0386 + 'anoteleia' => '367', # U+0x0387 + 'Epsilontonos' => '880', # U+0x0388 + 'Etatonos' => '1072', # U+0x0389 + 'Iotatonos' => '609', # U+0x038A + 'Omicrontonos' => '922', # U+0x038C + 'Upsilontonos' => '935', # U+0x038E + 'Omegatonos' => '960', # U+0x038F + 'iotadieresistonos' => '345', # U+0x0390 + 'Alpha' => '758', # U+0x0391 + 'Beta' => '759', # U+0x0392 + 'Gamma' => '655', # U+0x0393 + 'Delta' => '743', # U+0x0394 + 'Epsilon' => '721', # U+0x0395 + 'Zeta' => '689', # U+0x0396 + 'Eta' => '913', # U+0x0397 + 'Theta' => '822', # U+0x0398 + 'Iota' => '450', # U+0x0399 + 'Kappa' => '816', # U+0x039A + 'Lambda' => '752', # U+0x039B + 'Mu' => '1033', # U+0x039C + 'Nu' => '829', # U+0x039D + 'Xi' => '766', # U+0x039E + 'Omicron' => '819', # U+0x039F + 'Pi' => '900', # U+0x03A0 + 'Rho' => '706', # U+0x03A1 + 'Sigma' => '679', # U+0x03A3 + 'Tau' => '684', # U+0x03A4 + 'Upsilon' => '731', # U+0x03A5 + 'Phi' => '911', # U+0x03A6 + 'Chi' => '802', # U+0x03A7 + 'Psi' => '1011', # U+0x03A8 + 'Omega' => '877', # U+0x03A9 + 'Iotadieresis' => '450', # U+0x03AA + 'Upsilondieresis' => '731', # U+0x03AB + 'alphatonos' => '679', # U+0x03AC + 'epsilontonos' => '535', # U+0x03AD + 'etatonos' => '665', # U+0x03AE + 'iotatonos' => '345', # U+0x03AF + 'upsilondieresistonos' => '604', # U+0x03B0 + 'alpha' => '679', # U+0x03B1 + 'beta' => '658', # U+0x03B2 + 'gamma' => '570', # U+0x03B3 + 'delta' => '635', # U+0x03B4 + 'epsilon' => '535', # U+0x03B5 + 'zeta' => '462', # U+0x03B6 + 'eta' => '665', # U+0x03B7 + 'theta' => '640', # U+0x03B8 + 'iota' => '345', # U+0x03B9 + 'kappa' => '655', # U+0x03BA + 'lambda' => '527', # U+0x03BB + 'nu' => '561', # U+0x03BD + 'xi' => '498', # U+0x03BE + 'omicron' => '635', # U+0x03BF + 'pi' => '659', # U+0x03C0 + 'rho' => '645', # U+0x03C1 + 'sigma1' => '513', # U+0x03C2 + 'sigma' => '669', # U+0x03C3 + 'tau' => '485', # U+0x03C4 + 'upsilon' => '604', # U+0x03C5 + 'phi' => '830', # U+0x03C6 + 'chi' => '566', # U+0x03C7 + 'psi' => '857', # U+0x03C8 + 'omega' => '804', # U+0x03C9 + 'iotadieresis' => '345', # U+0x03CA + 'upsilondieresis' => '604', # U+0x03CB + 'omicrontonos' => '635', # U+0x03CC + 'upsilontonos' => '604', # U+0x03CD + 'omegatonos' => '804', # U+0x03CE + 'afii10023' => '721', # U+0x0401 + 'afii10051' => '883', # U+0x0402 + 'afii10052' => '655', # U+0x0403 + 'afii10053' => '730', # U+0x0404 + 'afii10054' => '652', # U+0x0405 + 'afii10055' => '450', # U+0x0406 + 'afii10056' => '450', # U+0x0407 + 'afii10057' => '595', # U+0x0408 + 'afii10058' => '1112', # U+0x0409 + 'afii10059' => '1184', # U+0x040A + 'afii10060' => '935', # U+0x040B + 'afii10061' => '794', # U+0x040C + 'afii10062' => '712', # U+0x040E + 'afii10145' => '901', # U+0x040F + 'afii10017' => '758', # U+0x0410 + 'afii10018' => '743', # U+0x0411 + 'afii10019' => '759', # U+0x0412 + 'afii10020' => '655', # U+0x0413 + 'afii10021' => '800', # U+0x0414 + 'afii10022' => '721', # U+0x0415 + 'afii10024' => '1127', # U+0x0416 + 'afii10025' => '684', # U+0x0417 + 'afii10026' => '921', # U+0x0418 + 'afii10027' => '921', # U+0x0419 + 'afii10028' => '794', # U+0x041A + 'afii10029' => '832', # U+0x041B + 'afii10030' => '1033', # U+0x041C + 'afii10031' => '913', # U+0x041D + 'afii10032' => '819', # U+0x041E + 'afii10033' => '900', # U+0x041F + 'afii10034' => '706', # U+0x0420 + 'afii10035' => '715', # U+0x0421 + 'afii10036' => '684', # U+0x0422 + 'afii10037' => '712', # U+0x0423 + 'afii10038' => '911', # U+0x0424 + 'afii10039' => '802', # U+0x0425 + 'afii10040' => '901', # U+0x0426 + 'afii10041' => '832', # U+0x0427 + 'afii10042' => '1283', # U+0x0428 + 'afii10043' => '1284', # U+0x0429 + 'afii10044' => '855', # U+0x042A + 'afii10045' => '1106', # U+0x042B + 'afii10046' => '726', # U+0x042C + 'afii10047' => '729', # U+0x042D + 'afii10048' => '1183', # U+0x042E + 'afii10049' => '803', # U+0x042F + 'afii10065' => '660', # U+0x0430 + 'afii10066' => '627', # U+0x0431 + 'afii10067' => '598', # U+0x0432 + 'afii10068' => '520', # U+0x0433 + 'afii10069' => '620', # U+0x0434 + 'afii10070' => '557', # U+0x0435 + 'afii10072' => '1091', # U+0x0436 + 'afii10073' => '539', # U+0x0437 + 'afii10074' => '685', # U+0x0438 + 'afii10075' => '685', # U+0x0439 + 'afii10076' => '646', # U+0x043A + 'afii10077' => '647', # U+0x043B + 'afii10078' => '875', # U+0x043C + 'afii10079' => '688', # U+0x043D + 'afii10080' => '635', # U+0x043E + 'afii10081' => '689', # U+0x043F + 'afii10082' => '662', # U+0x0440 + 'afii10083' => '535', # U+0x0441 + 'afii10084' => '1001', # U+0x0442 + 'afii10085' => '669', # U+0x0443 + 'afii10086' => '886', # U+0x0444 + 'afii10087' => '583', # U+0x0445 + 'afii10088' => '685', # U+0x0446 + 'afii10089' => '656', # U+0x0447 + 'afii10090' => '982', # U+0x0448 + 'afii10091' => '982', # U+0x0449 + 'afii10092' => '668', # U+0x044A + 'afii10093' => '925', # U+0x044B + 'afii10094' => '614', # U+0x044C + 'afii10095' => '539', # U+0x044D + 'afii10096' => '919', # U+0x044E + 'afii10097' => '642', # U+0x044F + 'afii10071' => '557', # U+0x0451 + 'afii10099' => '663', # U+0x0452 + 'afii10100' => '520', # U+0x0453 + 'afii10101' => '535', # U+0x0454 + 'afii10102' => '517', # U+0x0455 + 'afii10103' => '365', # U+0x0456 + 'afii10104' => '365', # U+0x0457 + 'afii10105' => '364', # U+0x0458 + 'afii10106' => '895', # U+0x0459 + 'afii10107' => '937', # U+0x045A + 'afii10108' => '675', # U+0x045B + 'afii10109' => '646', # U+0x045C + 'afii10110' => '669', # U+0x045E + 'afii10193' => '685', # U+0x045F + 'afii10050' => '645', # U+0x0490 + 'afii10098' => '510', # U+0x0491 + 'Wgrave' => '1126', # U+0x1E80 + 'wgrave' => '933', # U+0x1E81 + 'Wacute' => '1126', # U+0x1E82 + 'wacute' => '933', # U+0x1E83 + 'Wdieresis' => '1126', # U+0x1E84 + 'wdieresis' => '933', # U+0x1E85 + 'Ygrave' => '731', # U+0x1EF2 + 'ygrave' => '669', # U+0x1EF3 + 'afii00208' => '927', # U+0x2015 + 'underscoredbl' => '703', # U+0x2017 + 'quotereversed' => '268', # U+0x201B + 'minute' => '321', # U+0x2032 + 'second' => '532', # U+0x2033 + 'exclamdbl' => '664', # U+0x203C + 'fraction' => '94', # U+0x2044 + 'foursuperior' => '551', # U+0x2074 + 'fivesuperior' => '551', # U+0x2075 + 'sevensuperior' => '551', # U+0x2077 + 'eightsuperior' => '551', # U+0x2078 + 'nsuperior' => '551', # U+0x207F + 'franc' => '689', # U+0x20A3 + 'lira' => '689', # U+0x20A4 + 'peseta' => '1355', # U+0x20A7 + 'afii61248' => '879', # U+0x2105 + 'afii61289' => '323', # U+0x2113 + 'afii61352' => '1401', # U+0x2116 + 'estimated' => '649', # U+0x212E + 'oneeighth' => '1071', # U+0x215B + 'threeeighths' => '1071', # U+0x215C + 'fiveeighths' => '1071', # U+0x215D + 'seveneighths' => '1071', # U+0x215E + 'partialdiff' => '646', # U+0x2202 + 'product' => '932', # U+0x220F + 'summation' => '729', # U+0x2211 + 'minus' => '703', # U+0x2212 + 'radical' => '703', # U+0x221A + 'infinity' => '798', # U+0x221E + 'integral' => '627', # U+0x222B + 'approxequal' => '703', # U+0x2248 + 'notequal' => '703', # U+0x2260 + 'lessequal' => '703', # U+0x2264 + 'greaterequal' => '703', # U+0x2265 + 'H22073' => '604', # U+0x25A1 + 'H18543' => '354', # U+0x25AA + 'H18551' => '354', # U+0x25AB + 'lozenge' => '717', # U+0x25CA + 'H18533' => '604', # U+0x25CF + 'openbullet' => '354', # U+0x25E6 + 'commaaccent' => '500', # U+0xF6C3 + 'Acute' => '500', # U+0xF6C9 + 'Caron' => '500', # U+0xF6CA + 'Dieresis' => '500', # U+0xF6CB + 'Grave' => '500', # U+0xF6CE + 'Hungarumlaut' => '500', # U+0xF6CF + 'radicalex' => '703', # U+0xF8E5 + 'fi' => '701', # U+0xFB01 + 'fl' => '720', # U+0xFB02 + }, # HORIZ. WIDTH TABLE +} }; + +1; diff --git a/lib/PDF/API2/Resource/Font/CoreFont/georgiaitalic.pm b/lib/PDF/API2/Resource/Font/CoreFont/georgiaitalic.pm new file mode 100644 index 0000000..bf5934a --- /dev/null +++ b/lib/PDF/API2/Resource/Font/CoreFont/georgiaitalic.pm @@ -0,0 +1,863 @@ +#line 1 "PDF/API2/Resource/Font/CoreFont/georgiaitalic.pm" +#line 1 "PDF/API2/Resource/Font/CoreFont/georgiaitalic.pm" +package PDF::API2::Resource::Font::CoreFont::georgiaitalic; + +use strict; +use warnings; + +our $VERSION = '2.033'; # VERSION + +sub data { return { + 'fontname' => 'Georgia,Italic', + 'type' => 'TrueType', + 'apiname' => 'GeIt', + 'ascender' => '916', + 'capheight' => '692', + 'descender' => '-219', + 'isfixedpitch' => '0', + 'issymbol' => '0', + 'italicangle' => '-13', + 'underlineposition' => '-183', + 'underlinethickness' => '96', + 'xheight' => '488', + 'firstchar' => '32', + 'lastchar' => '255', + 'flags' => '98', + 'char' => [ # DEF. ENCODING GLYPH TABLE + '.notdef', # C+0x00 # U+0x0000 + '.notdef', # C+0x01 # U+0x0000 + '.notdef', # C+0x02 # U+0x0000 + '.notdef', # C+0x03 # U+0x0000 + '.notdef', # C+0x04 # U+0x0000 + '.notdef', # C+0x05 # U+0x0000 + '.notdef', # C+0x06 # U+0x0000 + '.notdef', # C+0x07 # U+0x0000 + '.notdef', # C+0x08 # U+0x0000 + '.notdef', # C+0x09 # U+0x0000 + '.notdef', # C+0x0A # U+0x0000 + '.notdef', # C+0x0B # U+0x0000 + '.notdef', # C+0x0C # U+0x0000 + '.notdef', # C+0x0D # U+0x0000 + '.notdef', # C+0x0E # U+0x0000 + '.notdef', # C+0x0F # U+0x0000 + '.notdef', # C+0x10 # U+0x0000 + '.notdef', # C+0x11 # U+0x0000 + '.notdef', # C+0x12 # U+0x0000 + '.notdef', # C+0x13 # U+0x0000 + '.notdef', # C+0x14 # U+0x0000 + '.notdef', # C+0x15 # U+0x0000 + '.notdef', # C+0x16 # U+0x0000 + '.notdef', # C+0x17 # U+0x0000 + '.notdef', # C+0x18 # U+0x0000 + '.notdef', # C+0x19 # U+0x0000 + '.notdef', # C+0x1A # U+0x0000 + '.notdef', # C+0x1B # U+0x0000 + '.notdef', # C+0x1C # U+0x0000 + '.notdef', # C+0x1D # U+0x0000 + '.notdef', # C+0x1E # U+0x0000 + '.notdef', # C+0x1F # U+0x0000 + 'space', # C+0x20 # U+0x0020 + 'exclam', # C+0x21 # U+0x0021 + 'quotedbl', # C+0x22 # U+0x0022 + 'numbersign', # C+0x23 # U+0x0023 + 'dollar', # C+0x24 # U+0x0024 + 'percent', # C+0x25 # U+0x0025 + 'ampersand', # C+0x26 # U+0x0026 + 'quotesingle', # C+0x27 # U+0x0027 + 'parenleft', # C+0x28 # U+0x0028 + 'parenright', # C+0x29 # U+0x0029 + 'asterisk', # C+0x2A # U+0x002A + 'plus', # C+0x2B # U+0x002B + 'comma', # C+0x2C # U+0x002C + 'hyphen', # C+0x2D # U+0x002D + 'period', # C+0x2E # U+0x002E + 'slash', # C+0x2F # U+0x002F + 'zero', # C+0x30 # U+0x0030 + 'one', # C+0x31 # U+0x0031 + 'two', # C+0x32 # U+0x0032 + 'three', # C+0x33 # U+0x0033 + 'four', # C+0x34 # U+0x0034 + 'five', # C+0x35 # U+0x0035 + 'six', # C+0x36 # U+0x0036 + 'seven', # C+0x37 # U+0x0037 + 'eight', # C+0x38 # U+0x0038 + 'nine', # C+0x39 # U+0x0039 + 'colon', # C+0x3A # U+0x003A + 'semicolon', # C+0x3B # U+0x003B + 'less', # C+0x3C # U+0x003C + 'equal', # C+0x3D # U+0x003D + 'greater', # C+0x3E # U+0x003E + 'question', # C+0x3F # U+0x003F + 'at', # C+0x40 # U+0x0040 + 'A', # C+0x41 # U+0x0041 + 'B', # C+0x42 # U+0x0042 + 'C', # C+0x43 # U+0x0043 + 'D', # C+0x44 # U+0x0044 + 'E', # C+0x45 # U+0x0045 + 'F', # C+0x46 # U+0x0046 + 'G', # C+0x47 # U+0x0047 + 'H', # C+0x48 # U+0x0048 + 'I', # C+0x49 # U+0x0049 + 'J', # C+0x4A # U+0x004A + 'K', # C+0x4B # U+0x004B + 'L', # C+0x4C # U+0x004C + 'M', # C+0x4D # U+0x004D + 'N', # C+0x4E # U+0x004E + 'O', # C+0x4F # U+0x004F + 'P', # C+0x50 # U+0x0050 + 'Q', # C+0x51 # U+0x0051 + 'R', # C+0x52 # U+0x0052 + 'S', # C+0x53 # U+0x0053 + 'T', # C+0x54 # U+0x0054 + 'U', # C+0x55 # U+0x0055 + 'V', # C+0x56 # U+0x0056 + 'W', # C+0x57 # U+0x0057 + 'X', # C+0x58 # U+0x0058 + 'Y', # C+0x59 # U+0x0059 + 'Z', # C+0x5A # U+0x005A + 'bracketleft', # C+0x5B # U+0x005B + 'backslash', # C+0x5C # U+0x005C + 'bracketright', # C+0x5D # U+0x005D + 'asciicircum', # C+0x5E # U+0x005E + 'underscore', # C+0x5F # U+0x005F + 'grave', # C+0x60 # U+0x0060 + 'a', # C+0x61 # U+0x0061 + 'b', # C+0x62 # U+0x0062 + 'c', # C+0x63 # U+0x0063 + 'd', # C+0x64 # U+0x0064 + 'e', # C+0x65 # U+0x0065 + 'f', # C+0x66 # U+0x0066 + 'g', # C+0x67 # U+0x0067 + 'h', # C+0x68 # U+0x0068 + 'i', # C+0x69 # U+0x0069 + 'j', # C+0x6A # U+0x006A + 'k', # C+0x6B # U+0x006B + 'l', # C+0x6C # U+0x006C + 'm', # C+0x6D # U+0x006D + 'n', # C+0x6E # U+0x006E + 'o', # C+0x6F # U+0x006F + 'p', # C+0x70 # U+0x0070 + 'q', # C+0x71 # U+0x0071 + 'r', # C+0x72 # U+0x0072 + 's', # C+0x73 # U+0x0073 + 't', # C+0x74 # U+0x0074 + 'u', # C+0x75 # U+0x0075 + 'v', # C+0x76 # U+0x0076 + 'w', # C+0x77 # U+0x0077 + 'x', # C+0x78 # U+0x0078 + 'y', # C+0x79 # U+0x0079 + 'z', # C+0x7A # U+0x007A + 'braceleft', # C+0x7B # U+0x007B + 'bar', # C+0x7C # U+0x007C + 'braceright', # C+0x7D # U+0x007D + 'asciitilde', # C+0x7E # U+0x007E + 'bullet', # C+0x7F # U+0x2022 + 'Euro', # C+0x80 # U+0x20AC + 'bullet', # C+0x81 # U+0x2022 + 'quotesinglbase', # C+0x82 # U+0x201A + 'florin', # C+0x83 # U+0x0192 + 'quotedblbase', # C+0x84 # U+0x201E + 'ellipsis', # C+0x85 # U+0x2026 + 'dagger', # C+0x86 # U+0x2020 + 'daggerdbl', # C+0x87 # U+0x2021 + 'circumflex', # C+0x88 # U+0x02C6 + 'perthousand', # C+0x89 # U+0x2030 + 'Scaron', # C+0x8A # U+0x0160 + 'guilsinglleft', # C+0x8B # U+0x2039 + 'OE', # C+0x8C # U+0x0152 + 'bullet', # C+0x8D # U+0x2022 + 'Zcaron', # C+0x8E # U+0x017D + 'bullet', # C+0x8F # U+0x2022 + 'bullet', # C+0x90 # U+0x2022 + 'quoteleft', # C+0x91 # U+0x2018 + 'quoteright', # C+0x92 # U+0x2019 + 'quotedblleft', # C+0x93 # U+0x201C + 'quotedblright', # C+0x94 # U+0x201D + 'bullet', # C+0x95 # U+0x2022 + 'endash', # C+0x96 # U+0x2013 + 'emdash', # C+0x97 # U+0x2014 + 'tilde', # C+0x98 # U+0x02DC + 'trademark', # C+0x99 # U+0x2122 + 'scaron', # C+0x9A # U+0x0161 + 'guilsinglright', # C+0x9B # U+0x203A + 'oe', # C+0x9C # U+0x0153 + 'bullet', # C+0x9D # U+0x2022 + 'zcaron', # C+0x9E # U+0x017E + 'Ydieresis', # C+0x9F # U+0x0178 + 'space', # C+0xA0 # U+0x0020 + 'exclamdown', # C+0xA1 # U+0x00A1 + 'cent', # C+0xA2 # U+0x00A2 + 'sterling', # C+0xA3 # U+0x00A3 + 'currency', # C+0xA4 # U+0x00A4 + 'yen', # C+0xA5 # U+0x00A5 + 'brokenbar', # C+0xA6 # U+0x00A6 + 'section', # C+0xA7 # U+0x00A7 + 'dieresis', # C+0xA8 # U+0x00A8 + 'copyright', # C+0xA9 # U+0x00A9 + 'ordfeminine', # C+0xAA # U+0x00AA + 'guillemotleft', # C+0xAB # U+0x00AB + 'logicalnot', # C+0xAC # U+0x00AC + 'hyphen', # C+0xAD # U+0x002D + 'registered', # C+0xAE # U+0x00AE + 'macron', # C+0xAF # U+0x00AF + 'degree', # C+0xB0 # U+0x00B0 + 'plusminus', # C+0xB1 # U+0x00B1 + 'twosuperior', # C+0xB2 # U+0x00B2 + 'threesuperior', # C+0xB3 # U+0x00B3 + 'acute', # C+0xB4 # U+0x00B4 + 'mu', # C+0xB5 # U+0x00B5 + 'paragraph', # C+0xB6 # U+0x00B6 + 'periodcentered', # C+0xB7 # U+0x00B7 + 'cedilla', # C+0xB8 # U+0x00B8 + 'onesuperior', # C+0xB9 # U+0x00B9 + 'ordmasculine', # C+0xBA # U+0x00BA + 'guillemotright', # C+0xBB # U+0x00BB + 'onequarter', # C+0xBC # U+0x00BC + 'onehalf', # C+0xBD # U+0x00BD + 'threequarters', # C+0xBE # U+0x00BE + 'questiondown', # C+0xBF # U+0x00BF + 'Agrave', # C+0xC0 # U+0x00C0 + 'Aacute', # C+0xC1 # U+0x00C1 + 'Acircumflex', # C+0xC2 # U+0x00C2 + 'Atilde', # C+0xC3 # U+0x00C3 + 'Adieresis', # C+0xC4 # U+0x00C4 + 'Aring', # C+0xC5 # U+0x00C5 + 'AE', # C+0xC6 # U+0x00C6 + 'Ccedilla', # C+0xC7 # U+0x00C7 + 'Egrave', # C+0xC8 # U+0x00C8 + 'Eacute', # C+0xC9 # U+0x00C9 + 'Ecircumflex', # C+0xCA # U+0x00CA + 'Edieresis', # C+0xCB # U+0x00CB + 'Igrave', # C+0xCC # U+0x00CC + 'Iacute', # C+0xCD # U+0x00CD + 'Icircumflex', # C+0xCE # U+0x00CE + 'Idieresis', # C+0xCF # U+0x00CF + 'Eth', # C+0xD0 # U+0x00D0 + 'Ntilde', # C+0xD1 # U+0x00D1 + 'Ograve', # C+0xD2 # U+0x00D2 + 'Oacute', # C+0xD3 # U+0x00D3 + 'Ocircumflex', # C+0xD4 # U+0x00D4 + 'Otilde', # C+0xD5 # U+0x00D5 + 'Odieresis', # C+0xD6 # U+0x00D6 + 'multiply', # C+0xD7 # U+0x00D7 + 'Oslash', # C+0xD8 # U+0x00D8 + 'Ugrave', # C+0xD9 # U+0x00D9 + 'Uacute', # C+0xDA # U+0x00DA + 'Ucircumflex', # C+0xDB # U+0x00DB + 'Udieresis', # C+0xDC # U+0x00DC + 'Yacute', # C+0xDD # U+0x00DD + 'Thorn', # C+0xDE # U+0x00DE + 'germandbls', # C+0xDF # U+0x00DF + 'agrave', # C+0xE0 # U+0x00E0 + 'aacute', # C+0xE1 # U+0x00E1 + 'acircumflex', # C+0xE2 # U+0x00E2 + 'atilde', # C+0xE3 # U+0x00E3 + 'adieresis', # C+0xE4 # U+0x00E4 + 'aring', # C+0xE5 # U+0x00E5 + 'ae', # C+0xE6 # U+0x00E6 + 'ccedilla', # C+0xE7 # U+0x00E7 + 'egrave', # C+0xE8 # U+0x00E8 + 'eacute', # C+0xE9 # U+0x00E9 + 'ecircumflex', # C+0xEA # U+0x00EA + 'edieresis', # C+0xEB # U+0x00EB + 'igrave', # C+0xEC # U+0x00EC + 'iacute', # C+0xED # U+0x00ED + 'icircumflex', # C+0xEE # U+0x00EE + 'idieresis', # C+0xEF # U+0x00EF + 'eth', # C+0xF0 # U+0x00F0 + 'ntilde', # C+0xF1 # U+0x00F1 + 'ograve', # C+0xF2 # U+0x00F2 + 'oacute', # C+0xF3 # U+0x00F3 + 'ocircumflex', # C+0xF4 # U+0x00F4 + 'otilde', # C+0xF5 # U+0x00F5 + 'odieresis', # C+0xF6 # U+0x00F6 + 'divide', # C+0xF7 # U+0x00F7 + 'oslash', # C+0xF8 # U+0x00F8 + 'ugrave', # C+0xF9 # U+0x00F9 + 'uacute', # C+0xFA # U+0x00FA + 'ucircumflex', # C+0xFB # U+0x00FB + 'udieresis', # C+0xFC # U+0x00FC + 'yacute', # C+0xFD # U+0x00FD + 'thorn', # C+0xFE # U+0x00FE + 'ydieresis', # C+0xFF # U+0x00FF + ], # DEF. ENCODING GLYPH TABLE + 'fontbbox' => [ -195, -216, 1196, 912 ], + 'wx' => { # HORIZ. WIDTH TABLE + 'space' => '241', # C+0x20 # U+0x0020 + 'exclam' => '331', # C+0x21 # U+0x0021 + 'quotedbl' => '411', # C+0x22 # U+0x0022 + 'numbersign' => '643', # C+0x23 # U+0x0023 + 'dollar' => '609', # C+0x24 # U+0x0024 + 'percent' => '817', # C+0x25 # U+0x0025 + 'ampersand' => '710', # C+0x26 # U+0x0026 + 'quotesingle' => '215', # C+0x27 # U+0x0027 + 'parenleft' => '375', # C+0x28 # U+0x0028 + 'parenright' => '375', # C+0x29 # U+0x0029 + 'asterisk' => '472', # C+0x2A # U+0x002A + 'plus' => '643', # C+0x2B # U+0x002B + 'comma' => '269', # C+0x2C # U+0x002C + 'hyphen' => '374', # C+0x2D # U+0x002D + 'period' => '269', # C+0x2E # U+0x002E + 'slash' => '468', # C+0x2F # U+0x002F + 'zero' => '613', # C+0x30 # U+0x0030 + 'one' => '429', # C+0x31 # U+0x0031 + 'two' => '558', # C+0x32 # U+0x0032 + 'three' => '551', # C+0x33 # U+0x0033 + 'four' => '564', # C+0x34 # U+0x0034 + 'five' => '528', # C+0x35 # U+0x0035 + 'six' => '565', # C+0x36 # U+0x0036 + 'seven' => '496', # C+0x37 # U+0x0037 + 'eight' => '596', # C+0x38 # U+0x0038 + 'nine' => '565', # C+0x39 # U+0x0039 + 'colon' => '383', # C+0x3A # U+0x003A + 'semicolon' => '383', # C+0x3B # U+0x003B + 'less' => '643', # C+0x3C # U+0x003C + 'equal' => '643', # C+0x3D # U+0x003D + 'greater' => '643', # C+0x3E # U+0x003E + 'question' => '478', # C+0x3F # U+0x003F + 'at' => '928', # C+0x40 # U+0x0040 + 'A' => '670', # C+0x41 # U+0x0041 + 'B' => '653', # C+0x42 # U+0x0042 + 'C' => '642', # C+0x43 # U+0x0043 + 'D' => '749', # C+0x44 # U+0x0044 + 'E' => '653', # C+0x45 # U+0x0045 + 'F' => '599', # C+0x46 # U+0x0046 + 'G' => '725', # C+0x47 # U+0x0047 + 'H' => '814', # C+0x48 # U+0x0048 + 'I' => '389', # C+0x49 # U+0x0049 + 'J' => '517', # C+0x4A # U+0x004A + 'K' => '694', # C+0x4B # U+0x004B + 'L' => '603', # C+0x4C # U+0x004C + 'M' => '927', # C+0x4D # U+0x004D + 'N' => '767', # C+0x4E # U+0x004E + 'O' => '730', # C+0x4F # U+0x004F + 'P' => '609', # C+0x50 # U+0x0050 + 'Q' => '730', # C+0x51 # U+0x0051 + 'R' => '701', # C+0x52 # U+0x0052 + 'S' => '561', # C+0x53 # U+0x0053 + 'T' => '618', # C+0x54 # U+0x0054 + 'U' => '756', # C+0x55 # U+0x0055 + 'V' => '666', # C+0x56 # U+0x0056 + 'W' => '975', # C+0x57 # U+0x0057 + 'X' => '710', # C+0x58 # U+0x0058 + 'Y' => '615', # C+0x59 # U+0x0059 + 'Z' => '601', # C+0x5A # U+0x005A + 'bracketleft' => '375', # C+0x5B # U+0x005B + 'backslash' => '468', # C+0x5C # U+0x005C + 'bracketright' => '375', # C+0x5D # U+0x005D + 'asciicircum' => '643', # C+0x5E # U+0x005E + 'underscore' => '643', # C+0x5F # U+0x005F + 'grave' => '500', # C+0x60 # U+0x0060 + 'a' => '572', # C+0x61 # U+0x0061 + 'b' => '553', # C+0x62 # U+0x0062 + 'c' => '453', # C+0x63 # U+0x0063 + 'd' => '575', # C+0x64 # U+0x0064 + 'e' => '471', # C+0x65 # U+0x0065 + 'f' => '328', # C+0x66 # U+0x0066 + 'g' => '572', # C+0x67 # U+0x0067 + 'h' => '562', # C+0x68 # U+0x0068 + 'i' => '297', # C+0x69 # U+0x0069 + 'j' => '291', # C+0x6A # U+0x006A + 'k' => '527', # C+0x6B # U+0x006B + 'l' => '285', # C+0x6C # U+0x006C + 'm' => '879', # C+0x6D # U+0x006D + 'n' => '589', # C+0x6E # U+0x006E + 'o' => '537', # C+0x6F # U+0x006F + 'p' => '578', # C+0x70 # U+0x0070 + 'q' => '555', # C+0x71 # U+0x0071 + 'r' => '461', # C+0x72 # U+0x0072 + 's' => '431', # C+0x73 # U+0x0073 + 't' => '347', # C+0x74 # U+0x0074 + 'u' => '575', # C+0x75 # U+0x0075 + 'v' => '538', # C+0x76 # U+0x0076 + 'w' => '822', # C+0x77 # U+0x0077 + 'x' => '500', # C+0x78 # U+0x0078 + 'y' => '559', # C+0x79 # U+0x0079 + 'z' => '443', # C+0x7A # U+0x007A + 'braceleft' => '430', # C+0x7B # U+0x007B + 'bar' => '375', # C+0x7C # U+0x007C + 'braceright' => '430', # C+0x7D # U+0x007D + 'asciitilde' => '643', # C+0x7E # U+0x007E + 'bullet' => '392', # C+0x7F # U+0x2022 + 'Euro' => '642', # C+0x80 # U+0x20AC + 'quotesinglbase' => '195', # C+0x82 # U+0x201A + 'florin' => '519', # C+0x83 # U+0x0192 + 'quotedblbase' => '385', # C+0x84 # U+0x201E + 'ellipsis' => '807', # C+0x85 # U+0x2026 + 'dagger' => '472', # C+0x86 # U+0x2020 + 'daggerdbl' => '472', # C+0x87 # U+0x2021 + 'circumflex' => '500', # C+0x88 # U+0x02C6 + 'perthousand' => '1227', # C+0x89 # U+0x2030 + 'Scaron' => '561', # C+0x8A # U+0x0160 + 'guilsinglleft' => '415', # C+0x8B # U+0x2039 + 'OE' => '998', # C+0x8C # U+0x0152 + 'Zcaron' => '601', # C+0x8E # U+0x017D + 'quoteleft' => '195', # C+0x91 # U+0x2018 + 'quoteright' => '195', # C+0x92 # U+0x2019 + 'quotedblleft' => '385', # C+0x93 # U+0x201C + 'quotedblright' => '385', # C+0x94 # U+0x201D + 'endash' => '643', # C+0x96 # U+0x2013 + 'emdash' => '856', # C+0x97 # U+0x2014 + 'tilde' => '500', # C+0x98 # U+0x02DC + 'trademark' => '942', # C+0x99 # U+0x2122 + 'scaron' => '431', # C+0x9A # U+0x0161 + 'guilsinglright' => '415', # C+0x9B # U+0x203A + 'oe' => '825', # C+0x9C # U+0x0153 + 'zcaron' => '443', # C+0x9E # U+0x017E + 'Ydieresis' => '615', # C+0x9F # U+0x0178 + 'exclamdown' => '331', # C+0xA1 # U+0x00A1 + 'cent' => '555', # C+0xA2 # U+0x00A2 + 'sterling' => '622', # C+0xA3 # U+0x00A3 + 'currency' => '571', # C+0xA4 # U+0x00A4 + 'yen' => '614', # C+0xA5 # U+0x00A5 + 'brokenbar' => '375', # C+0xA6 # U+0x00A6 + 'section' => '500', # C+0xA7 # U+0x00A7 + 'dieresis' => '500', # C+0xA8 # U+0x00A8 + 'copyright' => '941', # C+0xA9 # U+0x00A9 + 'ordfeminine' => '500', # C+0xAA # U+0x00AA + 'guillemotleft' => '581', # C+0xAB # U+0x00AB + 'logicalnot' => '643', # C+0xAC # U+0x00AC + 'registered' => '941', # C+0xAE # U+0x00AE + 'macron' => '500', # C+0xAF # U+0x00AF + 'degree' => '419', # C+0xB0 # U+0x00B0 + 'plusminus' => '643', # C+0xB1 # U+0x00B1 + 'twosuperior' => '500', # C+0xB2 # U+0x00B2 + 'threesuperior' => '500', # C+0xB3 # U+0x00B3 + 'acute' => '500', # C+0xB4 # U+0x00B4 + 'mu' => '575', # C+0xB5 # U+0x00B5 + 'paragraph' => '500', # C+0xB6 # U+0x00B6 + 'periodcentered' => '279', # C+0xB7 # U+0x00B7 + 'cedilla' => '500', # C+0xB8 # U+0x00B8 + 'onesuperior' => '500', # C+0xB9 # U+0x00B9 + 'ordmasculine' => '500', # C+0xBA # U+0x00BA + 'guillemotright' => '581', # C+0xBB # U+0x00BB + 'onequarter' => '1049', # C+0xBC # U+0x00BC + 'onehalf' => '1049', # C+0xBD # U+0x00BD + 'threequarters' => '1049', # C+0xBE # U+0x00BE + 'questiondown' => '478', # C+0xBF # U+0x00BF + 'Agrave' => '670', # C+0xC0 # U+0x00C0 + 'Aacute' => '670', # C+0xC1 # U+0x00C1 + 'Acircumflex' => '670', # C+0xC2 # U+0x00C2 + 'Atilde' => '670', # C+0xC3 # U+0x00C3 + 'Adieresis' => '670', # C+0xC4 # U+0x00C4 + 'Aring' => '670', # C+0xC5 # U+0x00C5 + 'AE' => '970', # C+0xC6 # U+0x00C6 + 'Ccedilla' => '642', # C+0xC7 # U+0x00C7 + 'Egrave' => '653', # C+0xC8 # U+0x00C8 + 'Eacute' => '653', # C+0xC9 # U+0x00C9 + 'Ecircumflex' => '653', # C+0xCA # U+0x00CA + 'Edieresis' => '653', # C+0xCB # U+0x00CB + 'Igrave' => '389', # C+0xCC # U+0x00CC + 'Iacute' => '389', # C+0xCD # U+0x00CD + 'Icircumflex' => '389', # C+0xCE # U+0x00CE + 'Idieresis' => '389', # C+0xCF # U+0x00CF + 'Eth' => '749', # C+0xD0 # U+0x00D0 + 'Ntilde' => '767', # C+0xD1 # U+0x00D1 + 'Ograve' => '744', # C+0xD2 # U+0x00D2 + 'Oacute' => '744', # C+0xD3 # U+0x00D3 + 'Ocircumflex' => '744', # C+0xD4 # U+0x00D4 + 'Otilde' => '730', # C+0xD5 # U+0x00D5 + 'Odieresis' => '744', # C+0xD6 # U+0x00D6 + 'multiply' => '643', # C+0xD7 # U+0x00D7 + 'Oslash' => '744', # C+0xD8 # U+0x00D8 + 'Ugrave' => '756', # C+0xD9 # U+0x00D9 + 'Uacute' => '756', # C+0xDA # U+0x00DA + 'Ucircumflex' => '756', # C+0xDB # U+0x00DB + 'Udieresis' => '756', # C+0xDC # U+0x00DC + 'Yacute' => '615', # C+0xDD # U+0x00DD + 'Thorn' => '614', # C+0xDE # U+0x00DE + 'germandbls' => '541', # C+0xDF # U+0x00DF + 'agrave' => '572', # C+0xE0 # U+0x00E0 + 'aacute' => '572', # C+0xE1 # U+0x00E1 + 'acircumflex' => '572', # C+0xE2 # U+0x00E2 + 'atilde' => '572', # C+0xE3 # U+0x00E3 + 'adieresis' => '572', # C+0xE4 # U+0x00E4 + 'aring' => '572', # C+0xE5 # U+0x00E5 + 'ae' => '764', # C+0xE6 # U+0x00E6 + 'ccedilla' => '453', # C+0xE7 # U+0x00E7 + 'egrave' => '471', # C+0xE8 # U+0x00E8 + 'eacute' => '471', # C+0xE9 # U+0x00E9 + 'ecircumflex' => '471', # C+0xEA # U+0x00EA + 'edieresis' => '471', # C+0xEB # U+0x00EB + 'igrave' => '297', # C+0xEC # U+0x00EC + 'iacute' => '297', # C+0xED # U+0x00ED + 'icircumflex' => '297', # C+0xEE # U+0x00EE + 'idieresis' => '297', # C+0xEF # U+0x00EF + 'eth' => '546', # C+0xF0 # U+0x00F0 + 'ntilde' => '589', # C+0xF1 # U+0x00F1 + 'ograve' => '537', # C+0xF2 # U+0x00F2 + 'oacute' => '537', # C+0xF3 # U+0x00F3 + 'ocircumflex' => '537', # C+0xF4 # U+0x00F4 + 'otilde' => '537', # C+0xF5 # U+0x00F5 + 'odieresis' => '537', # C+0xF6 # U+0x00F6 + 'divide' => '643', # C+0xF7 # U+0x00F7 + 'oslash' => '537', # C+0xF8 # U+0x00F8 + 'ugrave' => '575', # C+0xF9 # U+0x00F9 + 'uacute' => '575', # C+0xFA # U+0x00FA + 'ucircumflex' => '575', # C+0xFB # U+0x00FB + 'udieresis' => '575', # C+0xFC # U+0x00FC + 'yacute' => '559', # C+0xFD # U+0x00FD + 'thorn' => '552', # C+0xFE # U+0x00FE + 'ydieresis' => '559', # C+0xFF # U+0x00FF + 'middot' => '279', # U+0x00B7 + 'Amacron' => '670', # U+0x0100 + 'amacron' => '572', # U+0x0101 + 'Abreve' => '670', # U+0x0102 + 'abreve' => '572', # U+0x0103 + 'Aogonek' => '670', # U+0x0104 + 'aogonek' => '572', # U+0x0105 + 'Cacute' => '642', # U+0x0106 + 'cacute' => '453', # U+0x0107 + 'Ccircumflex' => '642', # U+0x0108 + 'ccircumflex' => '453', # U+0x0109 + 'Cdotaccent' => '642', # U+0x010A + 'cdotaccent' => '453', # U+0x010B + 'Ccaron' => '642', # U+0x010C + 'ccaron' => '453', # U+0x010D + 'Dcaron' => '749', # U+0x010E + 'dcaron' => '686', # U+0x010F + 'Dcroat' => '749', # U+0x0110 + 'dcroat' => '575', # U+0x0111 + 'Emacron' => '653', # U+0x0112 + 'emacron' => '471', # U+0x0113 + 'Ebreve' => '653', # U+0x0114 + 'ebreve' => '471', # U+0x0115 + 'Edotaccent' => '653', # U+0x0116 + 'edotaccent' => '471', # U+0x0117 + 'Eogonek' => '653', # U+0x0118 + 'eogonek' => '471', # U+0x0119 + 'Ecaron' => '653', # U+0x011A + 'ecaron' => '471', # U+0x011B + 'Gcircumflex' => '725', # U+0x011C + 'gcircumflex' => '572', # U+0x011D + 'Gbreve' => '725', # U+0x011E + 'gbreve' => '572', # U+0x011F + 'Gdotaccent' => '725', # U+0x0120 + 'gdotaccent' => '572', # U+0x0121 + 'Gcommaaccent' => '725', # U+0x0122 + 'gcommaaccent' => '572', # U+0x0123 + 'Hcircumflex' => '814', # U+0x0124 + 'hcircumflex' => '562', # U+0x0125 + 'Hbar' => '814', # U+0x0126 + 'hbar' => '562', # U+0x0127 + 'Itilde' => '389', # U+0x0128 + 'itilde' => '297', # U+0x0129 + 'Imacron' => '389', # U+0x012A + 'imacron' => '297', # U+0x012B + 'Ibreve' => '389', # U+0x012C + 'ibreve' => '297', # U+0x012D + 'Iogonek' => '389', # U+0x012E + 'iogonek' => '297', # U+0x012F + 'Idotaccent' => '389', # U+0x0130 + 'dotlessi' => '297', # U+0x0131 + 'IJ' => '877', # U+0x0132 + 'ij' => '576', # U+0x0133 + 'Jcircumflex' => '517', # U+0x0134 + 'jcircumflex' => '291', # U+0x0135 + 'Kcommaaccent' => '694', # U+0x0136 + 'kcommaaccent' => '527', # U+0x0137 + 'kgreenlandic' => '555', # U+0x0138 + 'Lacute' => '603', # U+0x0139 + 'lacute' => '285', # U+0x013A + 'Lcommaaccent' => '603', # U+0x013B + 'lcommaaccent' => '285', # U+0x013C + 'Lcaron' => '603', # U+0x013D + 'lcaron' => '389', # U+0x013E + 'Ldot' => '603', # U+0x013F + 'ldot' => '420', # U+0x0140 + 'Lslash' => '603', # U+0x0141 + 'lslash' => '285', # U+0x0142 + 'Nacute' => '767', # U+0x0143 + 'nacute' => '589', # U+0x0144 + 'Ncommaaccent' => '767', # U+0x0145 + 'ncommaaccent' => '589', # U+0x0146 + 'Ncaron' => '767', # U+0x0147 + 'ncaron' => '589', # U+0x0148 + 'napostrophe' => '628', # U+0x0149 + 'Eng' => '767', # U+0x014A + 'eng' => '578', # U+0x014B + 'Omacron' => '730', # U+0x014C + 'omacron' => '537', # U+0x014D + 'Obreve' => '730', # U+0x014E + 'obreve' => '537', # U+0x014F + 'Ohungarumlaut' => '730', # U+0x0150 + 'ohungarumlaut' => '537', # U+0x0151 + 'Racute' => '701', # U+0x0154 + 'racute' => '461', # U+0x0155 + 'Rcommaaccent' => '701', # U+0x0156 + 'rcommaaccent' => '461', # U+0x0157 + 'Rcaron' => '701', # U+0x0158 + 'rcaron' => '461', # U+0x0159 + 'Sacute' => '561', # U+0x015A + 'sacute' => '431', # U+0x015B + 'Scircumflex' => '561', # U+0x015C + 'scircumflex' => '431', # U+0x015D + 'Scedilla' => '561', # U+0x015E + 'scedilla' => '431', # U+0x015F + 'Tcommaaccent' => '618', # U+0x0162 + 'tcommaaccent' => '347', # U+0x0163 + 'Tcaron' => '618', # U+0x0164 + 'tcaron' => '347', # U+0x0165 + 'Tbar' => '618', # U+0x0166 + 'tbar' => '347', # U+0x0167 + 'Utilde' => '756', # U+0x0168 + 'utilde' => '575', # U+0x0169 + 'Umacron' => '756', # U+0x016A + 'umacron' => '575', # U+0x016B + 'Ubreve' => '756', # U+0x016C + 'ubreve' => '575', # U+0x016D + 'Uring' => '756', # U+0x016E + 'uring' => '575', # U+0x016F + 'Uhungarumlaut' => '756', # U+0x0170 + 'uhungarumlaut' => '575', # U+0x0171 + 'Uogonek' => '756', # U+0x0172 + 'uogonek' => '575', # U+0x0173 + 'Wcircumflex' => '975', # U+0x0174 + 'wcircumflex' => '822', # U+0x0175 + 'Ycircumflex' => '615', # U+0x0176 + 'ycircumflex' => '559', # U+0x0177 + 'Zacute' => '601', # U+0x0179 + 'zacute' => '443', # U+0x017A + 'Zdotaccent' => '601', # U+0x017B + 'zdotaccent' => '443', # U+0x017C + 'longs' => '294', # U+0x017F + 'Aringacute' => '670', # U+0x01FA + 'aringacute' => '572', # U+0x01FB + 'AEacute' => '970', # U+0x01FC + 'aeacute' => '764', # U+0x01FD + 'Oslashacute' => '744', # U+0x01FE + 'oslashacute' => '537', # U+0x01FF + 'Scommaaccent' => '561', # U+0x0218 + 'scommaaccent' => '431', # U+0x0219 + 'caron' => '500', # U+0x02C7 + 'breve' => '500', # U+0x02D8 + 'dotaccent' => '500', # U+0x02D9 + 'ring' => '572', # U+0x02DA + 'ogonek' => '500', # U+0x02DB + 'hungarumlaut' => '500', # U+0x02DD + 'tonos' => '500', # U+0x0384 + 'dieresistonos' => '500', # U+0x0385 + 'Alphatonos' => '675', # U+0x0386 + 'anoteleia' => '383', # U+0x0387 + 'Epsilontonos' => '798', # U+0x0388 + 'Etatonos' => '959', # U+0x0389 + 'Iotatonos' => '532', # U+0x038A + 'Omicrontonos' => '848', # U+0x038C + 'Upsilontonos' => '800', # U+0x038E + 'Omegatonos' => '885', # U+0x038F + 'iotadieresistonos' => '280', # U+0x0390 + 'Alpha' => '670', # U+0x0391 + 'Beta' => '653', # U+0x0392 + 'Gamma' => '583', # U+0x0393 + 'Delta' => '668', # U+0x0394 + 'Epsilon' => '653', # U+0x0395 + 'Zeta' => '601', # U+0x0396 + 'Eta' => '814', # U+0x0397 + 'Theta' => '730', # U+0x0398 + 'Iota' => '389', # U+0x0399 + 'Kappa' => '694', # U+0x039A + 'Lambda' => '673', # U+0x039B + 'Mu' => '927', # U+0x039C + 'Nu' => '767', # U+0x039D + 'Xi' => '693', # U+0x039E + 'Omicron' => '730', # U+0x039F + 'Pi' => '808', # U+0x03A0 + 'Rho' => '609', # U+0x03A1 + 'Sigma' => '603', # U+0x03A3 + 'Tau' => '618', # U+0x03A4 + 'Upsilon' => '615', # U+0x03A5 + 'Phi' => '766', # U+0x03A6 + 'Chi' => '710', # U+0x03A7 + 'Psi' => '874', # U+0x03A8 + 'Omega' => '778', # U+0x03A9 + 'Iotadieresis' => '389', # U+0x03AA + 'Upsilondieresis' => '615', # U+0x03AB + 'alphatonos' => '598', # U+0x03AC + 'epsilontonos' => '463', # U+0x03AD + 'etatonos' => '578', # U+0x03AE + 'iotatonos' => '280', # U+0x03AF + 'upsilondieresistonos' => '538', # U+0x03B0 + 'alpha' => '598', # U+0x03B1 + 'beta' => '566', # U+0x03B2 + 'gamma' => '508', # U+0x03B3 + 'delta' => '538', # U+0x03B4 + 'epsilon' => '463', # U+0x03B5 + 'zeta' => '401', # U+0x03B6 + 'eta' => '578', # U+0x03B7 + 'theta' => '551', # U+0x03B8 + 'iota' => '280', # U+0x03B9 + 'kappa' => '555', # U+0x03BA + 'lambda' => '487', # U+0x03BB + 'nu' => '501', # U+0x03BD + 'xi' => '438', # U+0x03BE + 'omicron' => '537', # U+0x03BF + 'pi' => '603', # U+0x03C0 + 'rho' => '562', # U+0x03C1 + 'sigma1' => '440', # U+0x03C2 + 'sigma' => '569', # U+0x03C3 + 'tau' => '449', # U+0x03C4 + 'upsilon' => '538', # U+0x03C5 + 'phi' => '708', # U+0x03C6 + 'chi' => '506', # U+0x03C7 + 'psi' => '735', # U+0x03C8 + 'omega' => '725', # U+0x03C9 + 'iotadieresis' => '280', # U+0x03CA + 'upsilondieresis' => '538', # U+0x03CB + 'omicrontonos' => '537', # U+0x03CC + 'upsilontonos' => '538', # U+0x03CD + 'omegatonos' => '725', # U+0x03CE + 'afii10023' => '653', # U+0x0401 + 'afii10051' => '785', # U+0x0402 + 'afii10052' => '583', # U+0x0403 + 'afii10053' => '656', # U+0x0404 + 'afii10054' => '561', # U+0x0405 + 'afii10055' => '389', # U+0x0406 + 'afii10056' => '389', # U+0x0407 + 'afii10057' => '517', # U+0x0408 + 'afii10058' => '1013', # U+0x0409 + 'afii10059' => '1066', # U+0x040A + 'afii10060' => '839', # U+0x040B + 'afii10061' => '694', # U+0x040C + 'afii10062' => '656', # U+0x040E + 'afii10145' => '810', # U+0x040F + 'afii10017' => '670', # U+0x0410 + 'afii10018' => '655', # U+0x0411 + 'afii10019' => '653', # U+0x0412 + 'afii10020' => '583', # U+0x0413 + 'afii10021' => '722', # U+0x0414 + 'afii10022' => '653', # U+0x0415 + 'afii10024' => '983', # U+0x0416 + 'afii10025' => '609', # U+0x0417 + 'afii10026' => '818', # U+0x0418 + 'afii10027' => '818', # U+0x0419 + 'afii10028' => '694', # U+0x041A + 'afii10029' => '756', # U+0x041B + 'afii10030' => '927', # U+0x041C + 'afii10031' => '814', # U+0x041D + 'afii10032' => '730', # U+0x041E + 'afii10033' => '808', # U+0x041F + 'afii10034' => '609', # U+0x0420 + 'afii10035' => '642', # U+0x0421 + 'afii10036' => '618', # U+0x0422 + 'afii10037' => '656', # U+0x0423 + 'afii10038' => '766', # U+0x0424 + 'afii10039' => '710', # U+0x0425 + 'afii10040' => '808', # U+0x0426 + 'afii10041' => '748', # U+0x0427 + 'afii10042' => '1088', # U+0x0428 + 'afii10043' => '1088', # U+0x0429 + 'afii10044' => '763', # U+0x042A + 'afii10045' => '970', # U+0x042B + 'afii10046' => '642', # U+0x042C + 'afii10047' => '657', # U+0x042D + 'afii10048' => '1065', # U+0x042E + 'afii10049' => '696', # U+0x042F + 'afii10065' => '572', # U+0x0430 + 'afii10066' => '537', # U+0x0431 + 'afii10067' => '515', # U+0x0432 + 'afii10068' => '458', # U+0x0433 + 'afii10069' => '532', # U+0x0434 + 'afii10070' => '471', # U+0x0435 + 'afii10072' => '893', # U+0x0436 + 'afii10073' => '473', # U+0x0437 + 'afii10074' => '575', # U+0x0438 + 'afii10075' => '575', # U+0x0439 + 'afii10076' => '539', # U+0x043A + 'afii10077' => '564', # U+0x043B + 'afii10078' => '739', # U+0x043C + 'afii10079' => '588', # U+0x043D + 'afii10080' => '537', # U+0x043E + 'afii10081' => '589', # U+0x043F + 'afii10082' => '578', # U+0x0440 + 'afii10083' => '453', # U+0x0441 + 'afii10084' => '879', # U+0x0442 + 'afii10085' => '559', # U+0x0443 + 'afii10086' => '740', # U+0x0444 + 'afii10087' => '500', # U+0x0445 + 'afii10088' => '575', # U+0x0446 + 'afii10089' => '558', # U+0x0447 + 'afii10090' => '856', # U+0x0448 + 'afii10091' => '856', # U+0x0449 + 'afii10092' => '537', # U+0x044A + 'afii10093' => '736', # U+0x044B + 'afii10094' => '486', # U+0x044C + 'afii10095' => '486', # U+0x044D + 'afii10096' => '791', # U+0x044E + 'afii10097' => '546', # U+0x044F + 'afii10071' => '471', # U+0x0451 + 'afii10099' => '551', # U+0x0452 + 'afii10100' => '458', # U+0x0453 + 'afii10101' => '488', # U+0x0454 + 'afii10102' => '431', # U+0x0455 + 'afii10103' => '297', # U+0x0456 + 'afii10104' => '297', # U+0x0457 + 'afii10105' => '291', # U+0x0458 + 'afii10106' => '762', # U+0x0459 + 'afii10107' => '783', # U+0x045A + 'afii10108' => '562', # U+0x045B + 'afii10109' => '539', # U+0x045C + 'afii10110' => '559', # U+0x045E + 'afii10193' => '575', # U+0x045F + 'afii10050' => '576', # U+0x0490 + 'afii10098' => '430', # U+0x0491 + 'Wgrave' => '975', # U+0x1E80 + 'wgrave' => '822', # U+0x1E81 + 'Wacute' => '975', # U+0x1E82 + 'wacute' => '822', # U+0x1E83 + 'Wdieresis' => '975', # U+0x1E84 + 'wdieresis' => '822', # U+0x1E85 + 'Ygrave' => '615', # U+0x1EF2 + 'ygrave' => '559', # U+0x1EF3 + 'afii00208' => '856', # U+0x2015 + 'underscoredbl' => '643', # U+0x2017 + 'quotereversed' => '195', # U+0x201B + 'minute' => '321', # U+0x2032 + 'second' => '517', # U+0x2033 + 'exclamdbl' => '575', # U+0x203C + 'fraction' => '143', # U+0x2044 + 'foursuperior' => '500', # U+0x2074 + 'fivesuperior' => '500', # U+0x2075 + 'sevensuperior' => '500', # U+0x2077 + 'eightsuperior' => '500', # U+0x2078 + 'nsuperior' => '500', # U+0x207F + 'franc' => '599', # U+0x20A3 + 'lira' => '622', # U+0x20A4 + 'peseta' => '1204', # U+0x20A7 + 'afii61248' => '817', # U+0x2105 + 'afii61289' => '323', # U+0x2113 + 'afii61352' => '1220', # U+0x2116 + 'estimated' => '615', # U+0x212E + 'oneeighth' => '1049', # U+0x215B + 'threeeighths' => '1049', # U+0x215C + 'fiveeighths' => '1049', # U+0x215D + 'seveneighths' => '1049', # U+0x215E + 'partialdiff' => '576', # U+0x2202 + 'product' => '834', # U+0x220F + 'summation' => '705', # U+0x2211 + 'minus' => '643', # U+0x2212 + 'radical' => '668', # U+0x221A + 'infinity' => '716', # U+0x221E + 'integral' => '499', # U+0x222B + 'approxequal' => '643', # U+0x2248 + 'notequal' => '643', # U+0x2260 + 'lessequal' => '643', # U+0x2264 + 'greaterequal' => '643', # U+0x2265 + 'H22073' => '604', # U+0x25A1 + 'H18543' => '354', # U+0x25AA + 'H18551' => '354', # U+0x25AB + 'lozenge' => '561', # U+0x25CA + 'H18533' => '604', # U+0x25CF + 'openbullet' => '354', # U+0x25E6 + 'commaaccent' => '604', # U+0xF6C3 + 'Acute' => '500', # U+0xF6C9 + 'Caron' => '500', # U+0xF6CA + 'Dieresis' => '500', # U+0xF6CB + 'Grave' => '500', # U+0xF6CE + 'Hungarumlaut' => '500', # U+0xF6CF + 'radicalex' => '596', # U+0xF8E5 + 'fi' => '583', # U+0xFB01 + 'fl' => '602', # U+0xFB02 + }, # HORIZ. WIDTH TABLE +} }; + +1; diff --git a/lib/PDF/API2/Resource/Font/CoreFont/helvetica.pm b/lib/PDF/API2/Resource/Font/CoreFont/helvetica.pm new file mode 100644 index 0000000..4239813 --- /dev/null +++ b/lib/PDF/API2/Resource/Font/CoreFont/helvetica.pm @@ -0,0 +1,520 @@ +#line 1 "PDF/API2/Resource/Font/CoreFont/helvetica.pm" +#line 1 "PDF/API2/Resource/Font/CoreFont/helvetica.pm" +package PDF::API2::Resource::Font::CoreFont::helvetica; + +use strict; +use warnings; + +our $VERSION = '2.033'; # VERSION + +sub data { return { + 'fontname' => 'Helvetica', + 'type' => 'Type1', + 'apiname' => 'Helv', + 'ascender' => '718', + 'capheight' => '718', + 'descender' => '-207', + 'iscore' => '1', + 'isfixedpitch' => '0', + 'italicangle' => '0', + 'missingwidth' => '278', + 'stdhw' => '76', + 'stdvw' => '88', + 'underlineposition' => '-100', + 'underlinethickness' => '50', + 'xheight' => '523', + 'firstchar' => '32', + 'lastchar' => '255', + 'char' => [ # DEF. ENCODING GLYPH TABLE + '.notdef', # C+0x00 # U+0x0000 + '.notdef', # C+0x01 # U+0x0000 + '.notdef', # C+0x02 # U+0x0000 + '.notdef', # C+0x03 # U+0x0000 + '.notdef', # C+0x04 # U+0x0000 + '.notdef', # C+0x05 # U+0x0000 + '.notdef', # C+0x06 # U+0x0000 + '.notdef', # C+0x07 # U+0x0000 + '.notdef', # C+0x08 # U+0x0000 + '.notdef', # C+0x09 # U+0x0000 + '.notdef', # C+0x0A # U+0x0000 + '.notdef', # C+0x0B # U+0x0000 + '.notdef', # C+0x0C # U+0x0000 + '.notdef', # C+0x0D # U+0x0000 + '.notdef', # C+0x0E # U+0x0000 + '.notdef', # C+0x0F # U+0x0000 + '.notdef', # C+0x10 # U+0x0000 + '.notdef', # C+0x11 # U+0x0000 + '.notdef', # C+0x12 # U+0x0000 + '.notdef', # C+0x13 # U+0x0000 + '.notdef', # C+0x14 # U+0x0000 + '.notdef', # C+0x15 # U+0x0000 + '.notdef', # C+0x16 # U+0x0000 + '.notdef', # C+0x17 # U+0x0000 + '.notdef', # C+0x18 # U+0x0000 + '.notdef', # C+0x19 # U+0x0000 + '.notdef', # C+0x1A # U+0x0000 + '.notdef', # C+0x1B # U+0x0000 + '.notdef', # C+0x1C # U+0x0000 + '.notdef', # C+0x1D # U+0x0000 + '.notdef', # C+0x1E # U+0x0000 + '.notdef', # C+0x1F # U+0x0000 + 'space', # C+0x20 # U+0x0020 + 'exclam', # C+0x21 # U+0x0021 + 'quotedbl', # C+0x22 # U+0x0022 + 'numbersign', # C+0x23 # U+0x0023 + 'dollar', # C+0x24 # U+0x0024 + 'percent', # C+0x25 # U+0x0025 + 'ampersand', # C+0x26 # U+0x0026 + 'quotesingle', # C+0x27 # U+0x0027 + 'parenleft', # C+0x28 # U+0x0028 + 'parenright', # C+0x29 # U+0x0029 + 'asterisk', # C+0x2A # U+0x002A + 'plus', # C+0x2B # U+0x002B + 'comma', # C+0x2C # U+0x002C + 'hyphen', # C+0x2D # U+0x002D + 'period', # C+0x2E # U+0x002E + 'slash', # C+0x2F # U+0x002F + 'zero', # C+0x30 # U+0x0030 + 'one', # C+0x31 # U+0x0031 + 'two', # C+0x32 # U+0x0032 + 'three', # C+0x33 # U+0x0033 + 'four', # C+0x34 # U+0x0034 + 'five', # C+0x35 # U+0x0035 + 'six', # C+0x36 # U+0x0036 + 'seven', # C+0x37 # U+0x0037 + 'eight', # C+0x38 # U+0x0038 + 'nine', # C+0x39 # U+0x0039 + 'colon', # C+0x3A # U+0x003A + 'semicolon', # C+0x3B # U+0x003B + 'less', # C+0x3C # U+0x003C + 'equal', # C+0x3D # U+0x003D + 'greater', # C+0x3E # U+0x003E + 'question', # C+0x3F # U+0x003F + 'at', # C+0x40 # U+0x0040 + 'A', # C+0x41 # U+0x0041 + 'B', # C+0x42 # U+0x0042 + 'C', # C+0x43 # U+0x0043 + 'D', # C+0x44 # U+0x0044 + 'E', # C+0x45 # U+0x0045 + 'F', # C+0x46 # U+0x0046 + 'G', # C+0x47 # U+0x0047 + 'H', # C+0x48 # U+0x0048 + 'I', # C+0x49 # U+0x0049 + 'J', # C+0x4A # U+0x004A + 'K', # C+0x4B # U+0x004B + 'L', # C+0x4C # U+0x004C + 'M', # C+0x4D # U+0x004D + 'N', # C+0x4E # U+0x004E + 'O', # C+0x4F # U+0x004F + 'P', # C+0x50 # U+0x0050 + 'Q', # C+0x51 # U+0x0051 + 'R', # C+0x52 # U+0x0052 + 'S', # C+0x53 # U+0x0053 + 'T', # C+0x54 # U+0x0054 + 'U', # C+0x55 # U+0x0055 + 'V', # C+0x56 # U+0x0056 + 'W', # C+0x57 # U+0x0057 + 'X', # C+0x58 # U+0x0058 + 'Y', # C+0x59 # U+0x0059 + 'Z', # C+0x5A # U+0x005A + 'bracketleft', # C+0x5B # U+0x005B + 'backslash', # C+0x5C # U+0x005C + 'bracketright', # C+0x5D # U+0x005D + 'asciicircum', # C+0x5E # U+0x005E + 'underscore', # C+0x5F # U+0x005F + 'grave', # C+0x60 # U+0x0060 + 'a', # C+0x61 # U+0x0061 + 'b', # C+0x62 # U+0x0062 + 'c', # C+0x63 # U+0x0063 + 'd', # C+0x64 # U+0x0064 + 'e', # C+0x65 # U+0x0065 + 'f', # C+0x66 # U+0x0066 + 'g', # C+0x67 # U+0x0067 + 'h', # C+0x68 # U+0x0068 + 'i', # C+0x69 # U+0x0069 + 'j', # C+0x6A # U+0x006A + 'k', # C+0x6B # U+0x006B + 'l', # C+0x6C # U+0x006C + 'm', # C+0x6D # U+0x006D + 'n', # C+0x6E # U+0x006E + 'o', # C+0x6F # U+0x006F + 'p', # C+0x70 # U+0x0070 + 'q', # C+0x71 # U+0x0071 + 'r', # C+0x72 # U+0x0072 + 's', # C+0x73 # U+0x0073 + 't', # C+0x74 # U+0x0074 + 'u', # C+0x75 # U+0x0075 + 'v', # C+0x76 # U+0x0076 + 'w', # C+0x77 # U+0x0077 + 'x', # C+0x78 # U+0x0078 + 'y', # C+0x79 # U+0x0079 + 'z', # C+0x7A # U+0x007A + 'braceleft', # C+0x7B # U+0x007B + 'bar', # C+0x7C # U+0x007C + 'braceright', # C+0x7D # U+0x007D + 'asciitilde', # C+0x7E # U+0x007E + 'bullet', # C+0x7F # U+0x2022 + 'Euro', # C+0x80 # U+0x20AC + 'bullet', # C+0x81 # U+0x2022 + 'quotesinglbase', # C+0x82 # U+0x201A + 'florin', # C+0x83 # U+0x0192 + 'quotedblbase', # C+0x84 # U+0x201E + 'ellipsis', # C+0x85 # U+0x2026 + 'dagger', # C+0x86 # U+0x2020 + 'daggerdbl', # C+0x87 # U+0x2021 + 'circumflex', # C+0x88 # U+0x02C6 + 'perthousand', # C+0x89 # U+0x2030 + 'Scaron', # C+0x8A # U+0x0160 + 'guilsinglleft', # C+0x8B # U+0x2039 + 'OE', # C+0x8C # U+0x0152 + 'bullet', # C+0x8D # U+0x2022 + 'Zcaron', # C+0x8E # U+0x017D + 'bullet', # C+0x8F # U+0x2022 + 'bullet', # C+0x90 # U+0x2022 + 'quoteleft', # C+0x91 # U+0x2018 + 'quoteright', # C+0x92 # U+0x2019 + 'quotedblleft', # C+0x93 # U+0x201C + 'quotedblright', # C+0x94 # U+0x201D + 'bullet', # C+0x95 # U+0x2022 + 'endash', # C+0x96 # U+0x2013 + 'emdash', # C+0x97 # U+0x2014 + 'tilde', # C+0x98 # U+0x02DC + 'trademark', # C+0x99 # U+0x2122 + 'scaron', # C+0x9A # U+0x0161 + 'guilsinglright', # C+0x9B # U+0x203A + 'oe', # C+0x9C # U+0x0153 + 'bullet', # C+0x9D # U+0x2022 + 'zcaron', # C+0x9E # U+0x017E + 'Ydieresis', # C+0x9F # U+0x0178 + 'space', # C+0xA0 # U+0x0020 + 'exclamdown', # C+0xA1 # U+0x00A1 + 'cent', # C+0xA2 # U+0x00A2 + 'sterling', # C+0xA3 # U+0x00A3 + 'currency', # C+0xA4 # U+0x00A4 + 'yen', # C+0xA5 # U+0x00A5 + 'brokenbar', # C+0xA6 # U+0x00A6 + 'section', # C+0xA7 # U+0x00A7 + 'dieresis', # C+0xA8 # U+0x00A8 + 'copyright', # C+0xA9 # U+0x00A9 + 'ordfeminine', # C+0xAA # U+0x00AA + 'guillemotleft', # C+0xAB # U+0x00AB + 'logicalnot', # C+0xAC # U+0x00AC + 'hyphen', # C+0xAD # U+0x002D + 'registered', # C+0xAE # U+0x00AE + 'macron', # C+0xAF # U+0x00AF + 'degree', # C+0xB0 # U+0x00B0 + 'plusminus', # C+0xB1 # U+0x00B1 + 'twosuperior', # C+0xB2 # U+0x00B2 + 'threesuperior', # C+0xB3 # U+0x00B3 + 'acute', # C+0xB4 # U+0x00B4 + 'mu', # C+0xB5 # U+0x00B5 + 'paragraph', # C+0xB6 # U+0x00B6 + 'periodcentered', # C+0xB7 # U+0x00B7 + 'cedilla', # C+0xB8 # U+0x00B8 + 'onesuperior', # C+0xB9 # U+0x00B9 + 'ordmasculine', # C+0xBA # U+0x00BA + 'guillemotright', # C+0xBB # U+0x00BB + 'onequarter', # C+0xBC # U+0x00BC + 'onehalf', # C+0xBD # U+0x00BD + 'threequarters', # C+0xBE # U+0x00BE + 'questiondown', # C+0xBF # U+0x00BF + 'Agrave', # C+0xC0 # U+0x00C0 + 'Aacute', # C+0xC1 # U+0x00C1 + 'Acircumflex', # C+0xC2 # U+0x00C2 + 'Atilde', # C+0xC3 # U+0x00C3 + 'Adieresis', # C+0xC4 # U+0x00C4 + 'Aring', # C+0xC5 # U+0x00C5 + 'AE', # C+0xC6 # U+0x00C6 + 'Ccedilla', # C+0xC7 # U+0x00C7 + 'Egrave', # C+0xC8 # U+0x00C8 + 'Eacute', # C+0xC9 # U+0x00C9 + 'Ecircumflex', # C+0xCA # U+0x00CA + 'Edieresis', # C+0xCB # U+0x00CB + 'Igrave', # C+0xCC # U+0x00CC + 'Iacute', # C+0xCD # U+0x00CD + 'Icircumflex', # C+0xCE # U+0x00CE + 'Idieresis', # C+0xCF # U+0x00CF + 'Eth', # C+0xD0 # U+0x00D0 + 'Ntilde', # C+0xD1 # U+0x00D1 + 'Ograve', # C+0xD2 # U+0x00D2 + 'Oacute', # C+0xD3 # U+0x00D3 + 'Ocircumflex', # C+0xD4 # U+0x00D4 + 'Otilde', # C+0xD5 # U+0x00D5 + 'Odieresis', # C+0xD6 # U+0x00D6 + 'multiply', # C+0xD7 # U+0x00D7 + 'Oslash', # C+0xD8 # U+0x00D8 + 'Ugrave', # C+0xD9 # U+0x00D9 + 'Uacute', # C+0xDA # U+0x00DA + 'Ucircumflex', # C+0xDB # U+0x00DB + 'Udieresis', # C+0xDC # U+0x00DC + 'Yacute', # C+0xDD # U+0x00DD + 'Thorn', # C+0xDE # U+0x00DE + 'germandbls', # C+0xDF # U+0x00DF + 'agrave', # C+0xE0 # U+0x00E0 + 'aacute', # C+0xE1 # U+0x00E1 + 'acircumflex', # C+0xE2 # U+0x00E2 + 'atilde', # C+0xE3 # U+0x00E3 + 'adieresis', # C+0xE4 # U+0x00E4 + 'aring', # C+0xE5 # U+0x00E5 + 'ae', # C+0xE6 # U+0x00E6 + 'ccedilla', # C+0xE7 # U+0x00E7 + 'egrave', # C+0xE8 # U+0x00E8 + 'eacute', # C+0xE9 # U+0x00E9 + 'ecircumflex', # C+0xEA # U+0x00EA + 'edieresis', # C+0xEB # U+0x00EB + 'igrave', # C+0xEC # U+0x00EC + 'iacute', # C+0xED # U+0x00ED + 'icircumflex', # C+0xEE # U+0x00EE + 'idieresis', # C+0xEF # U+0x00EF + 'eth', # C+0xF0 # U+0x00F0 + 'ntilde', # C+0xF1 # U+0x00F1 + 'ograve', # C+0xF2 # U+0x00F2 + 'oacute', # C+0xF3 # U+0x00F3 + 'ocircumflex', # C+0xF4 # U+0x00F4 + 'otilde', # C+0xF5 # U+0x00F5 + 'odieresis', # C+0xF6 # U+0x00F6 + 'divide', # C+0xF7 # U+0x00F7 + 'oslash', # C+0xF8 # U+0x00F8 + 'ugrave', # C+0xF9 # U+0x00F9 + 'uacute', # C+0xFA # U+0x00FA + 'ucircumflex', # C+0xFB # U+0x00FB + 'udieresis', # C+0xFC # U+0x00FC + 'yacute', # C+0xFD # U+0x00FD + 'thorn', # C+0xFE # U+0x00FE + 'ydieresis', # C+0xFF # U+0x00FF + ], # DEF. ENCODING GLYPH TABLE + 'fontbbox' => [ -166, -225, 1000, 931 ], + 'wx' => { # HORIZ. WIDTH TABLE + 'space' => '278', # C+0x20 # U+0x0020 + 'exclam' => '278', # C+0x21 # U+0x0021 + 'quotedbl' => '355', # C+0x22 # U+0x0022 + 'numbersign' => '556', # C+0x23 # U+0x0023 + 'dollar' => '556', # C+0x24 # U+0x0024 + 'percent' => '889', # C+0x25 # U+0x0025 + 'ampersand' => '667', # C+0x26 # U+0x0026 + 'quotesingle' => '191', # C+0x27 # U+0x0027 + 'parenleft' => '333', # C+0x28 # U+0x0028 + 'parenright' => '333', # C+0x29 # U+0x0029 + 'asterisk' => '389', # C+0x2A # U+0x002A + 'plus' => '584', # C+0x2B # U+0x002B + 'comma' => '278', # C+0x2C # U+0x002C + 'hyphen' => '333', # C+0x2D # U+0x002D + 'period' => '278', # C+0x2E # U+0x002E + 'slash' => '278', # C+0x2F # U+0x002F + 'zero' => '556', # C+0x30 # U+0x0030 + 'one' => '556', # C+0x31 # U+0x0031 + 'two' => '556', # C+0x32 # U+0x0032 + 'three' => '556', # C+0x33 # U+0x0033 + 'four' => '556', # C+0x34 # U+0x0034 + 'five' => '556', # C+0x35 # U+0x0035 + 'six' => '556', # C+0x36 # U+0x0036 + 'seven' => '556', # C+0x37 # U+0x0037 + 'eight' => '556', # C+0x38 # U+0x0038 + 'nine' => '556', # C+0x39 # U+0x0039 + 'colon' => '278', # C+0x3A # U+0x003A + 'semicolon' => '278', # C+0x3B # U+0x003B + 'less' => '584', # C+0x3C # U+0x003C + 'equal' => '584', # C+0x3D # U+0x003D + 'greater' => '584', # C+0x3E # U+0x003E + 'question' => '556', # C+0x3F # U+0x003F + 'at' => '1015', # C+0x40 # U+0x0040 + 'A' => '667', # C+0x41 # U+0x0041 + 'B' => '667', # C+0x42 # U+0x0042 + 'C' => '722', # C+0x43 # U+0x0043 + 'D' => '722', # C+0x44 # U+0x0044 + 'E' => '667', # C+0x45 # U+0x0045 + 'F' => '611', # C+0x46 # U+0x0046 + 'G' => '778', # C+0x47 # U+0x0047 + 'H' => '722', # C+0x48 # U+0x0048 + 'I' => '278', # C+0x49 # U+0x0049 + 'J' => '500', # C+0x4A # U+0x004A + 'K' => '667', # C+0x4B # U+0x004B + 'L' => '556', # C+0x4C # U+0x004C + 'M' => '833', # C+0x4D # U+0x004D + 'N' => '722', # C+0x4E # U+0x004E + 'O' => '778', # C+0x4F # U+0x004F + 'P' => '667', # C+0x50 # U+0x0050 + 'Q' => '778', # C+0x51 # U+0x0051 + 'R' => '722', # C+0x52 # U+0x0052 + 'S' => '667', # C+0x53 # U+0x0053 + 'T' => '611', # C+0x54 # U+0x0054 + 'U' => '722', # C+0x55 # U+0x0055 + 'V' => '667', # C+0x56 # U+0x0056 + 'W' => '944', # C+0x57 # U+0x0057 + 'X' => '667', # C+0x58 # U+0x0058 + 'Y' => '667', # C+0x59 # U+0x0059 + 'Z' => '611', # C+0x5A # U+0x005A + 'bracketleft' => '278', # C+0x5B # U+0x005B + 'backslash' => '278', # C+0x5C # U+0x005C + 'bracketright' => '278', # C+0x5D # U+0x005D + 'asciicircum' => '469', # C+0x5E # U+0x005E + 'underscore' => '556', # C+0x5F # U+0x005F + 'grave' => '333', # C+0x60 # U+0x0060 + 'a' => '556', # C+0x61 # U+0x0061 + 'b' => '556', # C+0x62 # U+0x0062 + 'c' => '500', # C+0x63 # U+0x0063 + 'd' => '556', # C+0x64 # U+0x0064 + 'e' => '556', # C+0x65 # U+0x0065 + 'f' => '278', # C+0x66 # U+0x0066 + 'g' => '556', # C+0x67 # U+0x0067 + 'h' => '556', # C+0x68 # U+0x0068 + 'i' => '222', # C+0x69 # U+0x0069 + 'j' => '222', # C+0x6A # U+0x006A + 'k' => '500', # C+0x6B # U+0x006B + 'l' => '222', # C+0x6C # U+0x006C + 'm' => '833', # C+0x6D # U+0x006D + 'n' => '556', # C+0x6E # U+0x006E + 'o' => '556', # C+0x6F # U+0x006F + 'p' => '556', # C+0x70 # U+0x0070 + 'q' => '556', # C+0x71 # U+0x0071 + 'r' => '333', # C+0x72 # U+0x0072 + 's' => '500', # C+0x73 # U+0x0073 + 't' => '278', # C+0x74 # U+0x0074 + 'u' => '556', # C+0x75 # U+0x0075 + 'v' => '500', # C+0x76 # U+0x0076 + 'w' => '722', # C+0x77 # U+0x0077 + 'x' => '500', # C+0x78 # U+0x0078 + 'y' => '500', # C+0x79 # U+0x0079 + 'z' => '500', # C+0x7A # U+0x007A + 'braceleft' => '334', # C+0x7B # U+0x007B + 'bar' => '260', # C+0x7C # U+0x007C + 'braceright' => '334', # C+0x7D # U+0x007D + 'asciitilde' => '584', # C+0x7E # U+0x007E + 'bullet' => '350', # C+0x7F # U+0x2022 + 'Euro' => '556', # C+0x80 # U+0x20AC + 'quotesinglbase' => '222', # C+0x82 # U+0x201A + 'florin' => '556', # C+0x83 # U+0x0192 + 'quotedblbase' => '333', # C+0x84 # U+0x201E + 'ellipsis' => '1000', # C+0x85 # U+0x2026 + 'dagger' => '556', # C+0x86 # U+0x2020 + 'daggerdbl' => '556', # C+0x87 # U+0x2021 + 'circumflex' => '333', # C+0x88 # U+0x02C6 + 'perthousand' => '1000', # C+0x89 # U+0x2030 + 'Scaron' => '667', # C+0x8A # U+0x0160 + 'guilsinglleft' => '333', # C+0x8B # U+0x2039 + 'OE' => '1000', # C+0x8C # U+0x0152 + 'Zcaron' => '611', # C+0x8E # U+0x017D + 'quoteleft' => '222', # C+0x91 # U+0x2018 + 'quoteright' => '222', # C+0x92 # U+0x2019 + 'quotedblleft' => '333', # C+0x93 # U+0x201C + 'quotedblright' => '333', # C+0x94 # U+0x201D + 'endash' => '556', # C+0x96 # U+0x2013 + 'emdash' => '1000', # C+0x97 # U+0x2014 + 'tilde' => '333', # C+0x98 # U+0x02DC + 'trademark' => '1000', # C+0x99 # U+0x2122 + 'scaron' => '500', # C+0x9A # U+0x0161 + 'guilsinglright' => '333', # C+0x9B # U+0x203A + 'oe' => '944', # C+0x9C # U+0x0153 + 'zcaron' => '500', # C+0x9E # U+0x017E + 'Ydieresis' => '667', # C+0x9F # U+0x0178 + 'exclamdown' => '333', # C+0xA1 # U+0x00A1 + 'cent' => '556', # C+0xA2 # U+0x00A2 + 'sterling' => '556', # C+0xA3 # U+0x00A3 + 'currency' => '556', # C+0xA4 # U+0x00A4 + 'yen' => '556', # C+0xA5 # U+0x00A5 + 'brokenbar' => '260', # C+0xA6 # U+0x00A6 + 'section' => '556', # C+0xA7 # U+0x00A7 + 'dieresis' => '333', # C+0xA8 # U+0x00A8 + 'copyright' => '737', # C+0xA9 # U+0x00A9 + 'ordfeminine' => '370', # C+0xAA # U+0x00AA + 'guillemotleft' => '556', # C+0xAB # U+0x00AB + 'logicalnot' => '584', # C+0xAC # U+0x00AC + 'registered' => '737', # C+0xAE # U+0x00AE + 'macron' => '333', # C+0xAF # U+0x00AF + 'degree' => '400', # C+0xB0 # U+0x00B0 + 'plusminus' => '584', # C+0xB1 # U+0x00B1 + 'twosuperior' => '333', # C+0xB2 # U+0x00B2 + 'threesuperior' => '333', # C+0xB3 # U+0x00B3 + 'acute' => '333', # C+0xB4 # U+0x00B4 + 'mu' => '556', # C+0xB5 # U+0x00B5 + 'paragraph' => '537', # C+0xB6 # U+0x00B6 + 'periodcentered' => '278', # C+0xB7 # U+0x00B7 + 'cedilla' => '333', # C+0xB8 # U+0x00B8 + 'onesuperior' => '333', # C+0xB9 # U+0x00B9 + 'ordmasculine' => '365', # C+0xBA # U+0x00BA + 'guillemotright' => '556', # C+0xBB # U+0x00BB + 'onequarter' => '834', # C+0xBC # U+0x00BC + 'onehalf' => '834', # C+0xBD # U+0x00BD + 'threequarters' => '834', # C+0xBE # U+0x00BE + 'questiondown' => '611', # C+0xBF # U+0x00BF + 'Agrave' => '667', # C+0xC0 # U+0x00C0 + 'Aacute' => '667', # C+0xC1 # U+0x00C1 + 'Acircumflex' => '667', # C+0xC2 # U+0x00C2 + 'Atilde' => '667', # C+0xC3 # U+0x00C3 + 'Adieresis' => '667', # C+0xC4 # U+0x00C4 + 'Aring' => '667', # C+0xC5 # U+0x00C5 + 'AE' => '1000', # C+0xC6 # U+0x00C6 + 'Ccedilla' => '722', # C+0xC7 # U+0x00C7 + 'Egrave' => '667', # C+0xC8 # U+0x00C8 + 'Eacute' => '667', # C+0xC9 # U+0x00C9 + 'Ecircumflex' => '667', # C+0xCA # U+0x00CA + 'Edieresis' => '667', # C+0xCB # U+0x00CB + 'Igrave' => '278', # C+0xCC # U+0x00CC + 'Iacute' => '278', # C+0xCD # U+0x00CD + 'Icircumflex' => '278', # C+0xCE # U+0x00CE + 'Idieresis' => '278', # C+0xCF # U+0x00CF + 'Eth' => '722', # C+0xD0 # U+0x00D0 + 'Ntilde' => '722', # C+0xD1 # U+0x00D1 + 'Ograve' => '778', # C+0xD2 # U+0x00D2 + 'Oacute' => '778', # C+0xD3 # U+0x00D3 + 'Ocircumflex' => '778', # C+0xD4 # U+0x00D4 + 'Otilde' => '778', # C+0xD5 # U+0x00D5 + 'Odieresis' => '778', # C+0xD6 # U+0x00D6 + 'multiply' => '584', # C+0xD7 # U+0x00D7 + 'Oslash' => '778', # C+0xD8 # U+0x00D8 + 'Ugrave' => '722', # C+0xD9 # U+0x00D9 + 'Uacute' => '722', # C+0xDA # U+0x00DA + 'Ucircumflex' => '722', # C+0xDB # U+0x00DB + 'Udieresis' => '722', # C+0xDC # U+0x00DC + 'Yacute' => '667', # C+0xDD # U+0x00DD + 'Thorn' => '667', # C+0xDE # U+0x00DE + 'germandbls' => '611', # C+0xDF # U+0x00DF + 'agrave' => '556', # C+0xE0 # U+0x00E0 + 'aacute' => '556', # C+0xE1 # U+0x00E1 + 'acircumflex' => '556', # C+0xE2 # U+0x00E2 + 'atilde' => '556', # C+0xE3 # U+0x00E3 + 'adieresis' => '556', # C+0xE4 # U+0x00E4 + 'aring' => '556', # C+0xE5 # U+0x00E5 + 'ae' => '889', # C+0xE6 # U+0x00E6 + 'ccedilla' => '500', # C+0xE7 # U+0x00E7 + 'egrave' => '556', # C+0xE8 # U+0x00E8 + 'eacute' => '556', # C+0xE9 # U+0x00E9 + 'ecircumflex' => '556', # C+0xEA # U+0x00EA + 'edieresis' => '556', # C+0xEB # U+0x00EB + 'igrave' => '278', # C+0xEC # U+0x00EC + 'iacute' => '278', # C+0xED # U+0x00ED + 'icircumflex' => '278', # C+0xEE # U+0x00EE + 'idieresis' => '278', # C+0xEF # U+0x00EF + 'eth' => '556', # C+0xF0 # U+0x00F0 + 'ntilde' => '556', # C+0xF1 # U+0x00F1 + 'ograve' => '556', # C+0xF2 # U+0x00F2 + 'oacute' => '556', # C+0xF3 # U+0x00F3 + 'ocircumflex' => '556', # C+0xF4 # U+0x00F4 + 'otilde' => '556', # C+0xF5 # U+0x00F5 + 'odieresis' => '556', # C+0xF6 # U+0x00F6 + 'divide' => '584', # C+0xF7 # U+0x00F7 + 'oslash' => '611', # C+0xF8 # U+0x00F8 + 'ugrave' => '556', # C+0xF9 # U+0x00F9 + 'uacute' => '556', # C+0xFA # U+0x00FA + 'ucircumflex' => '556', # C+0xFB # U+0x00FB + 'udieresis' => '556', # C+0xFC # U+0x00FC + 'yacute' => '500', # C+0xFD # U+0x00FD + 'thorn' => '556', # C+0xFE # U+0x00FE + 'ydieresis' => '500', # C+0xFF # U+0x00FF + 'dotlessi' => '278', # U+0x0131 + 'Lslash' => '556', # U+0x0141 + 'lslash' => '222', # U+0x0142 + 'caron' => '333', # U+0x02C7 + 'breve' => '333', # U+0x02D8 + 'dotaccent' => '333', # U+0x02D9 + 'ring' => '333', # U+0x02DA + 'ogonek' => '333', # U+0x02DB + 'hungarumlaut' => '333', # U+0x02DD + 'fraction' => '167', # U+0x2044 + 'minus' => '584', # U+0x2212 + 'fi' => '500', # U+0xFB01 + 'fl' => '500', # U+0xFB02 + }, # HORIZ. WIDTH TABLE +} }; + +1; diff --git a/lib/PDF/API2/Resource/Font/CoreFont/helveticabold.pm b/lib/PDF/API2/Resource/Font/CoreFont/helveticabold.pm new file mode 100644 index 0000000..88f3c2f --- /dev/null +++ b/lib/PDF/API2/Resource/Font/CoreFont/helveticabold.pm @@ -0,0 +1,520 @@ +#line 1 "PDF/API2/Resource/Font/CoreFont/helveticabold.pm" +#line 1 "PDF/API2/Resource/Font/CoreFont/helveticabold.pm" +package PDF::API2::Resource::Font::CoreFont::helveticabold; + +use strict; +use warnings; + +our $VERSION = '2.033'; # VERSION + +sub data { return { + 'fontname' => 'Helvetica-Bold', + 'type' => 'Type1', + 'apiname' => 'HeBo', + 'ascender' => '718', + 'capheight' => '718', + 'descender' => '-207', + 'iscore' => '1', + 'isfixedpitch' => '0', + 'italicangle' => '0', + 'missingwidth' => '278', + 'stdhw' => '118', + 'stdvw' => '140', + 'underlineposition' => '-100', + 'underlinethickness' => '50', + 'xheight' => '532', + 'firstchar' => '32', + 'lastchar' => '255', + 'char' => [ # DEF. ENCODING GLYPH TABLE + '.notdef', # C+0x00 # U+0x0000 + '.notdef', # C+0x01 # U+0x0000 + '.notdef', # C+0x02 # U+0x0000 + '.notdef', # C+0x03 # U+0x0000 + '.notdef', # C+0x04 # U+0x0000 + '.notdef', # C+0x05 # U+0x0000 + '.notdef', # C+0x06 # U+0x0000 + '.notdef', # C+0x07 # U+0x0000 + '.notdef', # C+0x08 # U+0x0000 + '.notdef', # C+0x09 # U+0x0000 + '.notdef', # C+0x0A # U+0x0000 + '.notdef', # C+0x0B # U+0x0000 + '.notdef', # C+0x0C # U+0x0000 + '.notdef', # C+0x0D # U+0x0000 + '.notdef', # C+0x0E # U+0x0000 + '.notdef', # C+0x0F # U+0x0000 + '.notdef', # C+0x10 # U+0x0000 + '.notdef', # C+0x11 # U+0x0000 + '.notdef', # C+0x12 # U+0x0000 + '.notdef', # C+0x13 # U+0x0000 + '.notdef', # C+0x14 # U+0x0000 + '.notdef', # C+0x15 # U+0x0000 + '.notdef', # C+0x16 # U+0x0000 + '.notdef', # C+0x17 # U+0x0000 + '.notdef', # C+0x18 # U+0x0000 + '.notdef', # C+0x19 # U+0x0000 + '.notdef', # C+0x1A # U+0x0000 + '.notdef', # C+0x1B # U+0x0000 + '.notdef', # C+0x1C # U+0x0000 + '.notdef', # C+0x1D # U+0x0000 + '.notdef', # C+0x1E # U+0x0000 + '.notdef', # C+0x1F # U+0x0000 + 'space', # C+0x20 # U+0x0020 + 'exclam', # C+0x21 # U+0x0021 + 'quotedbl', # C+0x22 # U+0x0022 + 'numbersign', # C+0x23 # U+0x0023 + 'dollar', # C+0x24 # U+0x0024 + 'percent', # C+0x25 # U+0x0025 + 'ampersand', # C+0x26 # U+0x0026 + 'quotesingle', # C+0x27 # U+0x0027 + 'parenleft', # C+0x28 # U+0x0028 + 'parenright', # C+0x29 # U+0x0029 + 'asterisk', # C+0x2A # U+0x002A + 'plus', # C+0x2B # U+0x002B + 'comma', # C+0x2C # U+0x002C + 'hyphen', # C+0x2D # U+0x002D + 'period', # C+0x2E # U+0x002E + 'slash', # C+0x2F # U+0x002F + 'zero', # C+0x30 # U+0x0030 + 'one', # C+0x31 # U+0x0031 + 'two', # C+0x32 # U+0x0032 + 'three', # C+0x33 # U+0x0033 + 'four', # C+0x34 # U+0x0034 + 'five', # C+0x35 # U+0x0035 + 'six', # C+0x36 # U+0x0036 + 'seven', # C+0x37 # U+0x0037 + 'eight', # C+0x38 # U+0x0038 + 'nine', # C+0x39 # U+0x0039 + 'colon', # C+0x3A # U+0x003A + 'semicolon', # C+0x3B # U+0x003B + 'less', # C+0x3C # U+0x003C + 'equal', # C+0x3D # U+0x003D + 'greater', # C+0x3E # U+0x003E + 'question', # C+0x3F # U+0x003F + 'at', # C+0x40 # U+0x0040 + 'A', # C+0x41 # U+0x0041 + 'B', # C+0x42 # U+0x0042 + 'C', # C+0x43 # U+0x0043 + 'D', # C+0x44 # U+0x0044 + 'E', # C+0x45 # U+0x0045 + 'F', # C+0x46 # U+0x0046 + 'G', # C+0x47 # U+0x0047 + 'H', # C+0x48 # U+0x0048 + 'I', # C+0x49 # U+0x0049 + 'J', # C+0x4A # U+0x004A + 'K', # C+0x4B # U+0x004B + 'L', # C+0x4C # U+0x004C + 'M', # C+0x4D # U+0x004D + 'N', # C+0x4E # U+0x004E + 'O', # C+0x4F # U+0x004F + 'P', # C+0x50 # U+0x0050 + 'Q', # C+0x51 # U+0x0051 + 'R', # C+0x52 # U+0x0052 + 'S', # C+0x53 # U+0x0053 + 'T', # C+0x54 # U+0x0054 + 'U', # C+0x55 # U+0x0055 + 'V', # C+0x56 # U+0x0056 + 'W', # C+0x57 # U+0x0057 + 'X', # C+0x58 # U+0x0058 + 'Y', # C+0x59 # U+0x0059 + 'Z', # C+0x5A # U+0x005A + 'bracketleft', # C+0x5B # U+0x005B + 'backslash', # C+0x5C # U+0x005C + 'bracketright', # C+0x5D # U+0x005D + 'asciicircum', # C+0x5E # U+0x005E + 'underscore', # C+0x5F # U+0x005F + 'grave', # C+0x60 # U+0x0060 + 'a', # C+0x61 # U+0x0061 + 'b', # C+0x62 # U+0x0062 + 'c', # C+0x63 # U+0x0063 + 'd', # C+0x64 # U+0x0064 + 'e', # C+0x65 # U+0x0065 + 'f', # C+0x66 # U+0x0066 + 'g', # C+0x67 # U+0x0067 + 'h', # C+0x68 # U+0x0068 + 'i', # C+0x69 # U+0x0069 + 'j', # C+0x6A # U+0x006A + 'k', # C+0x6B # U+0x006B + 'l', # C+0x6C # U+0x006C + 'm', # C+0x6D # U+0x006D + 'n', # C+0x6E # U+0x006E + 'o', # C+0x6F # U+0x006F + 'p', # C+0x70 # U+0x0070 + 'q', # C+0x71 # U+0x0071 + 'r', # C+0x72 # U+0x0072 + 's', # C+0x73 # U+0x0073 + 't', # C+0x74 # U+0x0074 + 'u', # C+0x75 # U+0x0075 + 'v', # C+0x76 # U+0x0076 + 'w', # C+0x77 # U+0x0077 + 'x', # C+0x78 # U+0x0078 + 'y', # C+0x79 # U+0x0079 + 'z', # C+0x7A # U+0x007A + 'braceleft', # C+0x7B # U+0x007B + 'bar', # C+0x7C # U+0x007C + 'braceright', # C+0x7D # U+0x007D + 'asciitilde', # C+0x7E # U+0x007E + 'bullet', # C+0x7F # U+0x2022 + 'Euro', # C+0x80 # U+0x20AC + 'bullet', # C+0x81 # U+0x2022 + 'quotesinglbase', # C+0x82 # U+0x201A + 'florin', # C+0x83 # U+0x0192 + 'quotedblbase', # C+0x84 # U+0x201E + 'ellipsis', # C+0x85 # U+0x2026 + 'dagger', # C+0x86 # U+0x2020 + 'daggerdbl', # C+0x87 # U+0x2021 + 'circumflex', # C+0x88 # U+0x02C6 + 'perthousand', # C+0x89 # U+0x2030 + 'Scaron', # C+0x8A # U+0x0160 + 'guilsinglleft', # C+0x8B # U+0x2039 + 'OE', # C+0x8C # U+0x0152 + 'bullet', # C+0x8D # U+0x2022 + 'Zcaron', # C+0x8E # U+0x017D + 'bullet', # C+0x8F # U+0x2022 + 'bullet', # C+0x90 # U+0x2022 + 'quoteleft', # C+0x91 # U+0x2018 + 'quoteright', # C+0x92 # U+0x2019 + 'quotedblleft', # C+0x93 # U+0x201C + 'quotedblright', # C+0x94 # U+0x201D + 'bullet', # C+0x95 # U+0x2022 + 'endash', # C+0x96 # U+0x2013 + 'emdash', # C+0x97 # U+0x2014 + 'tilde', # C+0x98 # U+0x02DC + 'trademark', # C+0x99 # U+0x2122 + 'scaron', # C+0x9A # U+0x0161 + 'guilsinglright', # C+0x9B # U+0x203A + 'oe', # C+0x9C # U+0x0153 + 'bullet', # C+0x9D # U+0x2022 + 'zcaron', # C+0x9E # U+0x017E + 'Ydieresis', # C+0x9F # U+0x0178 + 'space', # C+0xA0 # U+0x0020 + 'exclamdown', # C+0xA1 # U+0x00A1 + 'cent', # C+0xA2 # U+0x00A2 + 'sterling', # C+0xA3 # U+0x00A3 + 'currency', # C+0xA4 # U+0x00A4 + 'yen', # C+0xA5 # U+0x00A5 + 'brokenbar', # C+0xA6 # U+0x00A6 + 'section', # C+0xA7 # U+0x00A7 + 'dieresis', # C+0xA8 # U+0x00A8 + 'copyright', # C+0xA9 # U+0x00A9 + 'ordfeminine', # C+0xAA # U+0x00AA + 'guillemotleft', # C+0xAB # U+0x00AB + 'logicalnot', # C+0xAC # U+0x00AC + 'hyphen', # C+0xAD # U+0x002D + 'registered', # C+0xAE # U+0x00AE + 'macron', # C+0xAF # U+0x00AF + 'degree', # C+0xB0 # U+0x00B0 + 'plusminus', # C+0xB1 # U+0x00B1 + 'twosuperior', # C+0xB2 # U+0x00B2 + 'threesuperior', # C+0xB3 # U+0x00B3 + 'acute', # C+0xB4 # U+0x00B4 + 'mu', # C+0xB5 # U+0x00B5 + 'paragraph', # C+0xB6 # U+0x00B6 + 'periodcentered', # C+0xB7 # U+0x00B7 + 'cedilla', # C+0xB8 # U+0x00B8 + 'onesuperior', # C+0xB9 # U+0x00B9 + 'ordmasculine', # C+0xBA # U+0x00BA + 'guillemotright', # C+0xBB # U+0x00BB + 'onequarter', # C+0xBC # U+0x00BC + 'onehalf', # C+0xBD # U+0x00BD + 'threequarters', # C+0xBE # U+0x00BE + 'questiondown', # C+0xBF # U+0x00BF + 'Agrave', # C+0xC0 # U+0x00C0 + 'Aacute', # C+0xC1 # U+0x00C1 + 'Acircumflex', # C+0xC2 # U+0x00C2 + 'Atilde', # C+0xC3 # U+0x00C3 + 'Adieresis', # C+0xC4 # U+0x00C4 + 'Aring', # C+0xC5 # U+0x00C5 + 'AE', # C+0xC6 # U+0x00C6 + 'Ccedilla', # C+0xC7 # U+0x00C7 + 'Egrave', # C+0xC8 # U+0x00C8 + 'Eacute', # C+0xC9 # U+0x00C9 + 'Ecircumflex', # C+0xCA # U+0x00CA + 'Edieresis', # C+0xCB # U+0x00CB + 'Igrave', # C+0xCC # U+0x00CC + 'Iacute', # C+0xCD # U+0x00CD + 'Icircumflex', # C+0xCE # U+0x00CE + 'Idieresis', # C+0xCF # U+0x00CF + 'Eth', # C+0xD0 # U+0x00D0 + 'Ntilde', # C+0xD1 # U+0x00D1 + 'Ograve', # C+0xD2 # U+0x00D2 + 'Oacute', # C+0xD3 # U+0x00D3 + 'Ocircumflex', # C+0xD4 # U+0x00D4 + 'Otilde', # C+0xD5 # U+0x00D5 + 'Odieresis', # C+0xD6 # U+0x00D6 + 'multiply', # C+0xD7 # U+0x00D7 + 'Oslash', # C+0xD8 # U+0x00D8 + 'Ugrave', # C+0xD9 # U+0x00D9 + 'Uacute', # C+0xDA # U+0x00DA + 'Ucircumflex', # C+0xDB # U+0x00DB + 'Udieresis', # C+0xDC # U+0x00DC + 'Yacute', # C+0xDD # U+0x00DD + 'Thorn', # C+0xDE # U+0x00DE + 'germandbls', # C+0xDF # U+0x00DF + 'agrave', # C+0xE0 # U+0x00E0 + 'aacute', # C+0xE1 # U+0x00E1 + 'acircumflex', # C+0xE2 # U+0x00E2 + 'atilde', # C+0xE3 # U+0x00E3 + 'adieresis', # C+0xE4 # U+0x00E4 + 'aring', # C+0xE5 # U+0x00E5 + 'ae', # C+0xE6 # U+0x00E6 + 'ccedilla', # C+0xE7 # U+0x00E7 + 'egrave', # C+0xE8 # U+0x00E8 + 'eacute', # C+0xE9 # U+0x00E9 + 'ecircumflex', # C+0xEA # U+0x00EA + 'edieresis', # C+0xEB # U+0x00EB + 'igrave', # C+0xEC # U+0x00EC + 'iacute', # C+0xED # U+0x00ED + 'icircumflex', # C+0xEE # U+0x00EE + 'idieresis', # C+0xEF # U+0x00EF + 'eth', # C+0xF0 # U+0x00F0 + 'ntilde', # C+0xF1 # U+0x00F1 + 'ograve', # C+0xF2 # U+0x00F2 + 'oacute', # C+0xF3 # U+0x00F3 + 'ocircumflex', # C+0xF4 # U+0x00F4 + 'otilde', # C+0xF5 # U+0x00F5 + 'odieresis', # C+0xF6 # U+0x00F6 + 'divide', # C+0xF7 # U+0x00F7 + 'oslash', # C+0xF8 # U+0x00F8 + 'ugrave', # C+0xF9 # U+0x00F9 + 'uacute', # C+0xFA # U+0x00FA + 'ucircumflex', # C+0xFB # U+0x00FB + 'udieresis', # C+0xFC # U+0x00FC + 'yacute', # C+0xFD # U+0x00FD + 'thorn', # C+0xFE # U+0x00FE + 'ydieresis', # C+0xFF # U+0x00FF + ], # DEF. ENCODING GLYPH TABLE + 'fontbbox' => [ -170, -228, 1003, 962 ], + 'wx' => { # HORIZ. WIDTH TABLE + 'space' => '278', # C+0x20 # U+0x0020 + 'exclam' => '333', # C+0x21 # U+0x0021 + 'quotedbl' => '474', # C+0x22 # U+0x0022 + 'numbersign' => '556', # C+0x23 # U+0x0023 + 'dollar' => '556', # C+0x24 # U+0x0024 + 'percent' => '889', # C+0x25 # U+0x0025 + 'ampersand' => '722', # C+0x26 # U+0x0026 + 'quotesingle' => '238', # C+0x27 # U+0x0027 + 'parenleft' => '333', # C+0x28 # U+0x0028 + 'parenright' => '333', # C+0x29 # U+0x0029 + 'asterisk' => '389', # C+0x2A # U+0x002A + 'plus' => '584', # C+0x2B # U+0x002B + 'comma' => '278', # C+0x2C # U+0x002C + 'hyphen' => '333', # C+0x2D # U+0x002D + 'period' => '278', # C+0x2E # U+0x002E + 'slash' => '278', # C+0x2F # U+0x002F + 'zero' => '556', # C+0x30 # U+0x0030 + 'one' => '556', # C+0x31 # U+0x0031 + 'two' => '556', # C+0x32 # U+0x0032 + 'three' => '556', # C+0x33 # U+0x0033 + 'four' => '556', # C+0x34 # U+0x0034 + 'five' => '556', # C+0x35 # U+0x0035 + 'six' => '556', # C+0x36 # U+0x0036 + 'seven' => '556', # C+0x37 # U+0x0037 + 'eight' => '556', # C+0x38 # U+0x0038 + 'nine' => '556', # C+0x39 # U+0x0039 + 'colon' => '333', # C+0x3A # U+0x003A + 'semicolon' => '333', # C+0x3B # U+0x003B + 'less' => '584', # C+0x3C # U+0x003C + 'equal' => '584', # C+0x3D # U+0x003D + 'greater' => '584', # C+0x3E # U+0x003E + 'question' => '611', # C+0x3F # U+0x003F + 'at' => '975', # C+0x40 # U+0x0040 + 'A' => '722', # C+0x41 # U+0x0041 + 'B' => '722', # C+0x42 # U+0x0042 + 'C' => '722', # C+0x43 # U+0x0043 + 'D' => '722', # C+0x44 # U+0x0044 + 'E' => '667', # C+0x45 # U+0x0045 + 'F' => '611', # C+0x46 # U+0x0046 + 'G' => '778', # C+0x47 # U+0x0047 + 'H' => '722', # C+0x48 # U+0x0048 + 'I' => '278', # C+0x49 # U+0x0049 + 'J' => '556', # C+0x4A # U+0x004A + 'K' => '722', # C+0x4B # U+0x004B + 'L' => '611', # C+0x4C # U+0x004C + 'M' => '833', # C+0x4D # U+0x004D + 'N' => '722', # C+0x4E # U+0x004E + 'O' => '778', # C+0x4F # U+0x004F + 'P' => '667', # C+0x50 # U+0x0050 + 'Q' => '778', # C+0x51 # U+0x0051 + 'R' => '722', # C+0x52 # U+0x0052 + 'S' => '667', # C+0x53 # U+0x0053 + 'T' => '611', # C+0x54 # U+0x0054 + 'U' => '722', # C+0x55 # U+0x0055 + 'V' => '667', # C+0x56 # U+0x0056 + 'W' => '944', # C+0x57 # U+0x0057 + 'X' => '667', # C+0x58 # U+0x0058 + 'Y' => '667', # C+0x59 # U+0x0059 + 'Z' => '611', # C+0x5A # U+0x005A + 'bracketleft' => '333', # C+0x5B # U+0x005B + 'backslash' => '278', # C+0x5C # U+0x005C + 'bracketright' => '333', # C+0x5D # U+0x005D + 'asciicircum' => '584', # C+0x5E # U+0x005E + 'underscore' => '556', # C+0x5F # U+0x005F + 'grave' => '333', # C+0x60 # U+0x0060 + 'a' => '556', # C+0x61 # U+0x0061 + 'b' => '611', # C+0x62 # U+0x0062 + 'c' => '556', # C+0x63 # U+0x0063 + 'd' => '611', # C+0x64 # U+0x0064 + 'e' => '556', # C+0x65 # U+0x0065 + 'f' => '333', # C+0x66 # U+0x0066 + 'g' => '611', # C+0x67 # U+0x0067 + 'h' => '611', # C+0x68 # U+0x0068 + 'i' => '278', # C+0x69 # U+0x0069 + 'j' => '278', # C+0x6A # U+0x006A + 'k' => '556', # C+0x6B # U+0x006B + 'l' => '278', # C+0x6C # U+0x006C + 'm' => '889', # C+0x6D # U+0x006D + 'n' => '611', # C+0x6E # U+0x006E + 'o' => '611', # C+0x6F # U+0x006F + 'p' => '611', # C+0x70 # U+0x0070 + 'q' => '611', # C+0x71 # U+0x0071 + 'r' => '389', # C+0x72 # U+0x0072 + 's' => '556', # C+0x73 # U+0x0073 + 't' => '333', # C+0x74 # U+0x0074 + 'u' => '611', # C+0x75 # U+0x0075 + 'v' => '556', # C+0x76 # U+0x0076 + 'w' => '778', # C+0x77 # U+0x0077 + 'x' => '556', # C+0x78 # U+0x0078 + 'y' => '556', # C+0x79 # U+0x0079 + 'z' => '500', # C+0x7A # U+0x007A + 'braceleft' => '389', # C+0x7B # U+0x007B + 'bar' => '280', # C+0x7C # U+0x007C + 'braceright' => '389', # C+0x7D # U+0x007D + 'asciitilde' => '584', # C+0x7E # U+0x007E + 'bullet' => '350', # C+0x7F # U+0x2022 + 'Euro' => '556', # C+0x80 # U+0x20AC + 'quotesinglbase' => '278', # C+0x82 # U+0x201A + 'florin' => '556', # C+0x83 # U+0x0192 + 'quotedblbase' => '500', # C+0x84 # U+0x201E + 'ellipsis' => '1000', # C+0x85 # U+0x2026 + 'dagger' => '556', # C+0x86 # U+0x2020 + 'daggerdbl' => '556', # C+0x87 # U+0x2021 + 'circumflex' => '333', # C+0x88 # U+0x02C6 + 'perthousand' => '1000', # C+0x89 # U+0x2030 + 'Scaron' => '667', # C+0x8A # U+0x0160 + 'guilsinglleft' => '333', # C+0x8B # U+0x2039 + 'OE' => '1000', # C+0x8C # U+0x0152 + 'Zcaron' => '611', # C+0x8E # U+0x017D + 'quoteleft' => '278', # C+0x91 # U+0x2018 + 'quoteright' => '278', # C+0x92 # U+0x2019 + 'quotedblleft' => '500', # C+0x93 # U+0x201C + 'quotedblright' => '500', # C+0x94 # U+0x201D + 'endash' => '556', # C+0x96 # U+0x2013 + 'emdash' => '1000', # C+0x97 # U+0x2014 + 'tilde' => '333', # C+0x98 # U+0x02DC + 'trademark' => '1000', # C+0x99 # U+0x2122 + 'scaron' => '556', # C+0x9A # U+0x0161 + 'guilsinglright' => '333', # C+0x9B # U+0x203A + 'oe' => '944', # C+0x9C # U+0x0153 + 'zcaron' => '500', # C+0x9E # U+0x017E + 'Ydieresis' => '667', # C+0x9F # U+0x0178 + 'exclamdown' => '333', # C+0xA1 # U+0x00A1 + 'cent' => '556', # C+0xA2 # U+0x00A2 + 'sterling' => '556', # C+0xA3 # U+0x00A3 + 'currency' => '556', # C+0xA4 # U+0x00A4 + 'yen' => '556', # C+0xA5 # U+0x00A5 + 'brokenbar' => '280', # C+0xA6 # U+0x00A6 + 'section' => '556', # C+0xA7 # U+0x00A7 + 'dieresis' => '333', # C+0xA8 # U+0x00A8 + 'copyright' => '737', # C+0xA9 # U+0x00A9 + 'ordfeminine' => '370', # C+0xAA # U+0x00AA + 'guillemotleft' => '556', # C+0xAB # U+0x00AB + 'logicalnot' => '584', # C+0xAC # U+0x00AC + 'registered' => '737', # C+0xAE # U+0x00AE + 'macron' => '333', # C+0xAF # U+0x00AF + 'degree' => '400', # C+0xB0 # U+0x00B0 + 'plusminus' => '584', # C+0xB1 # U+0x00B1 + 'twosuperior' => '333', # C+0xB2 # U+0x00B2 + 'threesuperior' => '333', # C+0xB3 # U+0x00B3 + 'acute' => '333', # C+0xB4 # U+0x00B4 + 'mu' => '611', # C+0xB5 # U+0x00B5 + 'paragraph' => '556', # C+0xB6 # U+0x00B6 + 'periodcentered' => '278', # C+0xB7 # U+0x00B7 + 'cedilla' => '333', # C+0xB8 # U+0x00B8 + 'onesuperior' => '333', # C+0xB9 # U+0x00B9 + 'ordmasculine' => '365', # C+0xBA # U+0x00BA + 'guillemotright' => '556', # C+0xBB # U+0x00BB + 'onequarter' => '834', # C+0xBC # U+0x00BC + 'onehalf' => '834', # C+0xBD # U+0x00BD + 'threequarters' => '834', # C+0xBE # U+0x00BE + 'questiondown' => '611', # C+0xBF # U+0x00BF + 'Agrave' => '722', # C+0xC0 # U+0x00C0 + 'Aacute' => '722', # C+0xC1 # U+0x00C1 + 'Acircumflex' => '722', # C+0xC2 # U+0x00C2 + 'Atilde' => '722', # C+0xC3 # U+0x00C3 + 'Adieresis' => '722', # C+0xC4 # U+0x00C4 + 'Aring' => '722', # C+0xC5 # U+0x00C5 + 'AE' => '1000', # C+0xC6 # U+0x00C6 + 'Ccedilla' => '722', # C+0xC7 # U+0x00C7 + 'Egrave' => '667', # C+0xC8 # U+0x00C8 + 'Eacute' => '667', # C+0xC9 # U+0x00C9 + 'Ecircumflex' => '667', # C+0xCA # U+0x00CA + 'Edieresis' => '667', # C+0xCB # U+0x00CB + 'Igrave' => '278', # C+0xCC # U+0x00CC + 'Iacute' => '278', # C+0xCD # U+0x00CD + 'Icircumflex' => '278', # C+0xCE # U+0x00CE + 'Idieresis' => '278', # C+0xCF # U+0x00CF + 'Eth' => '722', # C+0xD0 # U+0x00D0 + 'Ntilde' => '722', # C+0xD1 # U+0x00D1 + 'Ograve' => '778', # C+0xD2 # U+0x00D2 + 'Oacute' => '778', # C+0xD3 # U+0x00D3 + 'Ocircumflex' => '778', # C+0xD4 # U+0x00D4 + 'Otilde' => '778', # C+0xD5 # U+0x00D5 + 'Odieresis' => '778', # C+0xD6 # U+0x00D6 + 'multiply' => '584', # C+0xD7 # U+0x00D7 + 'Oslash' => '778', # C+0xD8 # U+0x00D8 + 'Ugrave' => '722', # C+0xD9 # U+0x00D9 + 'Uacute' => '722', # C+0xDA # U+0x00DA + 'Ucircumflex' => '722', # C+0xDB # U+0x00DB + 'Udieresis' => '722', # C+0xDC # U+0x00DC + 'Yacute' => '667', # C+0xDD # U+0x00DD + 'Thorn' => '667', # C+0xDE # U+0x00DE + 'germandbls' => '611', # C+0xDF # U+0x00DF + 'agrave' => '556', # C+0xE0 # U+0x00E0 + 'aacute' => '556', # C+0xE1 # U+0x00E1 + 'acircumflex' => '556', # C+0xE2 # U+0x00E2 + 'atilde' => '556', # C+0xE3 # U+0x00E3 + 'adieresis' => '556', # C+0xE4 # U+0x00E4 + 'aring' => '556', # C+0xE5 # U+0x00E5 + 'ae' => '889', # C+0xE6 # U+0x00E6 + 'ccedilla' => '556', # C+0xE7 # U+0x00E7 + 'egrave' => '556', # C+0xE8 # U+0x00E8 + 'eacute' => '556', # C+0xE9 # U+0x00E9 + 'ecircumflex' => '556', # C+0xEA # U+0x00EA + 'edieresis' => '556', # C+0xEB # U+0x00EB + 'igrave' => '278', # C+0xEC # U+0x00EC + 'iacute' => '278', # C+0xED # U+0x00ED + 'icircumflex' => '278', # C+0xEE # U+0x00EE + 'idieresis' => '278', # C+0xEF # U+0x00EF + 'eth' => '611', # C+0xF0 # U+0x00F0 + 'ntilde' => '611', # C+0xF1 # U+0x00F1 + 'ograve' => '611', # C+0xF2 # U+0x00F2 + 'oacute' => '611', # C+0xF3 # U+0x00F3 + 'ocircumflex' => '611', # C+0xF4 # U+0x00F4 + 'otilde' => '611', # C+0xF5 # U+0x00F5 + 'odieresis' => '611', # C+0xF6 # U+0x00F6 + 'divide' => '584', # C+0xF7 # U+0x00F7 + 'oslash' => '611', # C+0xF8 # U+0x00F8 + 'ugrave' => '611', # C+0xF9 # U+0x00F9 + 'uacute' => '611', # C+0xFA # U+0x00FA + 'ucircumflex' => '611', # C+0xFB # U+0x00FB + 'udieresis' => '611', # C+0xFC # U+0x00FC + 'yacute' => '556', # C+0xFD # U+0x00FD + 'thorn' => '611', # C+0xFE # U+0x00FE + 'ydieresis' => '556', # C+0xFF # U+0x00FF + 'dotlessi' => '278', # U+0x0131 + 'Lslash' => '611', # U+0x0141 + 'lslash' => '278', # U+0x0142 + 'caron' => '333', # U+0x02C7 + 'breve' => '333', # U+0x02D8 + 'dotaccent' => '333', # U+0x02D9 + 'ring' => '333', # U+0x02DA + 'ogonek' => '333', # U+0x02DB + 'hungarumlaut' => '333', # U+0x02DD + 'fraction' => '167', # U+0x2044 + 'minus' => '584', # U+0x2212 + 'fi' => '611', # U+0xFB01 + 'fl' => '611', # U+0xFB02 + }, # HORIZ. WIDTH TABLE +} }; + +1; diff --git a/lib/PDF/API2/Resource/Font/CoreFont/helveticaboldoblique.pm b/lib/PDF/API2/Resource/Font/CoreFont/helveticaboldoblique.pm new file mode 100644 index 0000000..a27ce75 --- /dev/null +++ b/lib/PDF/API2/Resource/Font/CoreFont/helveticaboldoblique.pm @@ -0,0 +1,519 @@ +#line 1 "PDF/API2/Resource/Font/CoreFont/helveticaboldoblique.pm" +#line 1 "PDF/API2/Resource/Font/CoreFont/helveticaboldoblique.pm" +package PDF::API2::Resource::Font::CoreFont::helveticaboldoblique; + +use strict; +use warnings; + +our $VERSION = '2.033'; # VERSION + +sub data { return { + 'fontname' => 'Helvetica-BoldOblique', + 'type' => 'Type1', + 'apiname' => 'HeBi', + 'ascender' => '718', + 'capheight' => '718', + 'descender' => '-207', + 'iscore' => '1', + 'isfixedpitch' => '0', + 'italicangle' => '-12', + 'stdhw' => '118', + 'stdvw' => '140', + 'underlineposition' => '-100', + 'underlinethickness' => '50', + 'xheight' => '532', + 'firstchar' => '32', + 'lastchar' => '255', + 'char' => [ # DEF. ENCODING GLYPH TABLE + '.notdef', # C+0x00 # U+0x0000 + '.notdef', # C+0x01 # U+0x0000 + '.notdef', # C+0x02 # U+0x0000 + '.notdef', # C+0x03 # U+0x0000 + '.notdef', # C+0x04 # U+0x0000 + '.notdef', # C+0x05 # U+0x0000 + '.notdef', # C+0x06 # U+0x0000 + '.notdef', # C+0x07 # U+0x0000 + '.notdef', # C+0x08 # U+0x0000 + '.notdef', # C+0x09 # U+0x0000 + '.notdef', # C+0x0A # U+0x0000 + '.notdef', # C+0x0B # U+0x0000 + '.notdef', # C+0x0C # U+0x0000 + '.notdef', # C+0x0D # U+0x0000 + '.notdef', # C+0x0E # U+0x0000 + '.notdef', # C+0x0F # U+0x0000 + '.notdef', # C+0x10 # U+0x0000 + '.notdef', # C+0x11 # U+0x0000 + '.notdef', # C+0x12 # U+0x0000 + '.notdef', # C+0x13 # U+0x0000 + '.notdef', # C+0x14 # U+0x0000 + '.notdef', # C+0x15 # U+0x0000 + '.notdef', # C+0x16 # U+0x0000 + '.notdef', # C+0x17 # U+0x0000 + '.notdef', # C+0x18 # U+0x0000 + '.notdef', # C+0x19 # U+0x0000 + '.notdef', # C+0x1A # U+0x0000 + '.notdef', # C+0x1B # U+0x0000 + '.notdef', # C+0x1C # U+0x0000 + '.notdef', # C+0x1D # U+0x0000 + '.notdef', # C+0x1E # U+0x0000 + '.notdef', # C+0x1F # U+0x0000 + 'space', # C+0x20 # U+0x0020 + 'exclam', # C+0x21 # U+0x0021 + 'quotedbl', # C+0x22 # U+0x0022 + 'numbersign', # C+0x23 # U+0x0023 + 'dollar', # C+0x24 # U+0x0024 + 'percent', # C+0x25 # U+0x0025 + 'ampersand', # C+0x26 # U+0x0026 + 'quotesingle', # C+0x27 # U+0x0027 + 'parenleft', # C+0x28 # U+0x0028 + 'parenright', # C+0x29 # U+0x0029 + 'asterisk', # C+0x2A # U+0x002A + 'plus', # C+0x2B # U+0x002B + 'comma', # C+0x2C # U+0x002C + 'hyphen', # C+0x2D # U+0x002D + 'period', # C+0x2E # U+0x002E + 'slash', # C+0x2F # U+0x002F + 'zero', # C+0x30 # U+0x0030 + 'one', # C+0x31 # U+0x0031 + 'two', # C+0x32 # U+0x0032 + 'three', # C+0x33 # U+0x0033 + 'four', # C+0x34 # U+0x0034 + 'five', # C+0x35 # U+0x0035 + 'six', # C+0x36 # U+0x0036 + 'seven', # C+0x37 # U+0x0037 + 'eight', # C+0x38 # U+0x0038 + 'nine', # C+0x39 # U+0x0039 + 'colon', # C+0x3A # U+0x003A + 'semicolon', # C+0x3B # U+0x003B + 'less', # C+0x3C # U+0x003C + 'equal', # C+0x3D # U+0x003D + 'greater', # C+0x3E # U+0x003E + 'question', # C+0x3F # U+0x003F + 'at', # C+0x40 # U+0x0040 + 'A', # C+0x41 # U+0x0041 + 'B', # C+0x42 # U+0x0042 + 'C', # C+0x43 # U+0x0043 + 'D', # C+0x44 # U+0x0044 + 'E', # C+0x45 # U+0x0045 + 'F', # C+0x46 # U+0x0046 + 'G', # C+0x47 # U+0x0047 + 'H', # C+0x48 # U+0x0048 + 'I', # C+0x49 # U+0x0049 + 'J', # C+0x4A # U+0x004A + 'K', # C+0x4B # U+0x004B + 'L', # C+0x4C # U+0x004C + 'M', # C+0x4D # U+0x004D + 'N', # C+0x4E # U+0x004E + 'O', # C+0x4F # U+0x004F + 'P', # C+0x50 # U+0x0050 + 'Q', # C+0x51 # U+0x0051 + 'R', # C+0x52 # U+0x0052 + 'S', # C+0x53 # U+0x0053 + 'T', # C+0x54 # U+0x0054 + 'U', # C+0x55 # U+0x0055 + 'V', # C+0x56 # U+0x0056 + 'W', # C+0x57 # U+0x0057 + 'X', # C+0x58 # U+0x0058 + 'Y', # C+0x59 # U+0x0059 + 'Z', # C+0x5A # U+0x005A + 'bracketleft', # C+0x5B # U+0x005B + 'backslash', # C+0x5C # U+0x005C + 'bracketright', # C+0x5D # U+0x005D + 'asciicircum', # C+0x5E # U+0x005E + 'underscore', # C+0x5F # U+0x005F + 'grave', # C+0x60 # U+0x0060 + 'a', # C+0x61 # U+0x0061 + 'b', # C+0x62 # U+0x0062 + 'c', # C+0x63 # U+0x0063 + 'd', # C+0x64 # U+0x0064 + 'e', # C+0x65 # U+0x0065 + 'f', # C+0x66 # U+0x0066 + 'g', # C+0x67 # U+0x0067 + 'h', # C+0x68 # U+0x0068 + 'i', # C+0x69 # U+0x0069 + 'j', # C+0x6A # U+0x006A + 'k', # C+0x6B # U+0x006B + 'l', # C+0x6C # U+0x006C + 'm', # C+0x6D # U+0x006D + 'n', # C+0x6E # U+0x006E + 'o', # C+0x6F # U+0x006F + 'p', # C+0x70 # U+0x0070 + 'q', # C+0x71 # U+0x0071 + 'r', # C+0x72 # U+0x0072 + 's', # C+0x73 # U+0x0073 + 't', # C+0x74 # U+0x0074 + 'u', # C+0x75 # U+0x0075 + 'v', # C+0x76 # U+0x0076 + 'w', # C+0x77 # U+0x0077 + 'x', # C+0x78 # U+0x0078 + 'y', # C+0x79 # U+0x0079 + 'z', # C+0x7A # U+0x007A + 'braceleft', # C+0x7B # U+0x007B + 'bar', # C+0x7C # U+0x007C + 'braceright', # C+0x7D # U+0x007D + 'asciitilde', # C+0x7E # U+0x007E + 'bullet', # C+0x7F # U+0x2022 + 'Euro', # C+0x80 # U+0x20AC + 'bullet', # C+0x81 # U+0x2022 + 'quotesinglbase', # C+0x82 # U+0x201A + 'florin', # C+0x83 # U+0x0192 + 'quotedblbase', # C+0x84 # U+0x201E + 'ellipsis', # C+0x85 # U+0x2026 + 'dagger', # C+0x86 # U+0x2020 + 'daggerdbl', # C+0x87 # U+0x2021 + 'circumflex', # C+0x88 # U+0x02C6 + 'perthousand', # C+0x89 # U+0x2030 + 'Scaron', # C+0x8A # U+0x0160 + 'guilsinglleft', # C+0x8B # U+0x2039 + 'OE', # C+0x8C # U+0x0152 + 'bullet', # C+0x8D # U+0x2022 + 'Zcaron', # C+0x8E # U+0x017D + 'bullet', # C+0x8F # U+0x2022 + 'bullet', # C+0x90 # U+0x2022 + 'quoteleft', # C+0x91 # U+0x2018 + 'quoteright', # C+0x92 # U+0x2019 + 'quotedblleft', # C+0x93 # U+0x201C + 'quotedblright', # C+0x94 # U+0x201D + 'bullet', # C+0x95 # U+0x2022 + 'endash', # C+0x96 # U+0x2013 + 'emdash', # C+0x97 # U+0x2014 + 'tilde', # C+0x98 # U+0x02DC + 'trademark', # C+0x99 # U+0x2122 + 'scaron', # C+0x9A # U+0x0161 + 'guilsinglright', # C+0x9B # U+0x203A + 'oe', # C+0x9C # U+0x0153 + 'bullet', # C+0x9D # U+0x2022 + 'zcaron', # C+0x9E # U+0x017E + 'Ydieresis', # C+0x9F # U+0x0178 + 'space', # C+0xA0 # U+0x0020 + 'exclamdown', # C+0xA1 # U+0x00A1 + 'cent', # C+0xA2 # U+0x00A2 + 'sterling', # C+0xA3 # U+0x00A3 + 'currency', # C+0xA4 # U+0x00A4 + 'yen', # C+0xA5 # U+0x00A5 + 'brokenbar', # C+0xA6 # U+0x00A6 + 'section', # C+0xA7 # U+0x00A7 + 'dieresis', # C+0xA8 # U+0x00A8 + 'copyright', # C+0xA9 # U+0x00A9 + 'ordfeminine', # C+0xAA # U+0x00AA + 'guillemotleft', # C+0xAB # U+0x00AB + 'logicalnot', # C+0xAC # U+0x00AC + 'hyphen', # C+0xAD # U+0x002D + 'registered', # C+0xAE # U+0x00AE + 'macron', # C+0xAF # U+0x00AF + 'degree', # C+0xB0 # U+0x00B0 + 'plusminus', # C+0xB1 # U+0x00B1 + 'twosuperior', # C+0xB2 # U+0x00B2 + 'threesuperior', # C+0xB3 # U+0x00B3 + 'acute', # C+0xB4 # U+0x00B4 + 'mu', # C+0xB5 # U+0x00B5 + 'paragraph', # C+0xB6 # U+0x00B6 + 'periodcentered', # C+0xB7 # U+0x00B7 + 'cedilla', # C+0xB8 # U+0x00B8 + 'onesuperior', # C+0xB9 # U+0x00B9 + 'ordmasculine', # C+0xBA # U+0x00BA + 'guillemotright', # C+0xBB # U+0x00BB + 'onequarter', # C+0xBC # U+0x00BC + 'onehalf', # C+0xBD # U+0x00BD + 'threequarters', # C+0xBE # U+0x00BE + 'questiondown', # C+0xBF # U+0x00BF + 'Agrave', # C+0xC0 # U+0x00C0 + 'Aacute', # C+0xC1 # U+0x00C1 + 'Acircumflex', # C+0xC2 # U+0x00C2 + 'Atilde', # C+0xC3 # U+0x00C3 + 'Adieresis', # C+0xC4 # U+0x00C4 + 'Aring', # C+0xC5 # U+0x00C5 + 'AE', # C+0xC6 # U+0x00C6 + 'Ccedilla', # C+0xC7 # U+0x00C7 + 'Egrave', # C+0xC8 # U+0x00C8 + 'Eacute', # C+0xC9 # U+0x00C9 + 'Ecircumflex', # C+0xCA # U+0x00CA + 'Edieresis', # C+0xCB # U+0x00CB + 'Igrave', # C+0xCC # U+0x00CC + 'Iacute', # C+0xCD # U+0x00CD + 'Icircumflex', # C+0xCE # U+0x00CE + 'Idieresis', # C+0xCF # U+0x00CF + 'Eth', # C+0xD0 # U+0x00D0 + 'Ntilde', # C+0xD1 # U+0x00D1 + 'Ograve', # C+0xD2 # U+0x00D2 + 'Oacute', # C+0xD3 # U+0x00D3 + 'Ocircumflex', # C+0xD4 # U+0x00D4 + 'Otilde', # C+0xD5 # U+0x00D5 + 'Odieresis', # C+0xD6 # U+0x00D6 + 'multiply', # C+0xD7 # U+0x00D7 + 'Oslash', # C+0xD8 # U+0x00D8 + 'Ugrave', # C+0xD9 # U+0x00D9 + 'Uacute', # C+0xDA # U+0x00DA + 'Ucircumflex', # C+0xDB # U+0x00DB + 'Udieresis', # C+0xDC # U+0x00DC + 'Yacute', # C+0xDD # U+0x00DD + 'Thorn', # C+0xDE # U+0x00DE + 'germandbls', # C+0xDF # U+0x00DF + 'agrave', # C+0xE0 # U+0x00E0 + 'aacute', # C+0xE1 # U+0x00E1 + 'acircumflex', # C+0xE2 # U+0x00E2 + 'atilde', # C+0xE3 # U+0x00E3 + 'adieresis', # C+0xE4 # U+0x00E4 + 'aring', # C+0xE5 # U+0x00E5 + 'ae', # C+0xE6 # U+0x00E6 + 'ccedilla', # C+0xE7 # U+0x00E7 + 'egrave', # C+0xE8 # U+0x00E8 + 'eacute', # C+0xE9 # U+0x00E9 + 'ecircumflex', # C+0xEA # U+0x00EA + 'edieresis', # C+0xEB # U+0x00EB + 'igrave', # C+0xEC # U+0x00EC + 'iacute', # C+0xED # U+0x00ED + 'icircumflex', # C+0xEE # U+0x00EE + 'idieresis', # C+0xEF # U+0x00EF + 'eth', # C+0xF0 # U+0x00F0 + 'ntilde', # C+0xF1 # U+0x00F1 + 'ograve', # C+0xF2 # U+0x00F2 + 'oacute', # C+0xF3 # U+0x00F3 + 'ocircumflex', # C+0xF4 # U+0x00F4 + 'otilde', # C+0xF5 # U+0x00F5 + 'odieresis', # C+0xF6 # U+0x00F6 + 'divide', # C+0xF7 # U+0x00F7 + 'oslash', # C+0xF8 # U+0x00F8 + 'ugrave', # C+0xF9 # U+0x00F9 + 'uacute', # C+0xFA # U+0x00FA + 'ucircumflex', # C+0xFB # U+0x00FB + 'udieresis', # C+0xFC # U+0x00FC + 'yacute', # C+0xFD # U+0x00FD + 'thorn', # C+0xFE # U+0x00FE + 'ydieresis', # C+0xFF # U+0x00FF + ], # DEF. ENCODING GLYPH TABLE + 'fontbbox' => [ -174, -228, 1114, 962 ], + 'wx' => { # HORIZ. WIDTH TABLE + 'space' => '278', # C+0x20 # U+0x0020 + 'exclam' => '333', # C+0x21 # U+0x0021 + 'quotedbl' => '474', # C+0x22 # U+0x0022 + 'numbersign' => '556', # C+0x23 # U+0x0023 + 'dollar' => '556', # C+0x24 # U+0x0024 + 'percent' => '889', # C+0x25 # U+0x0025 + 'ampersand' => '722', # C+0x26 # U+0x0026 + 'quotesingle' => '238', # C+0x27 # U+0x0027 + 'parenleft' => '333', # C+0x28 # U+0x0028 + 'parenright' => '333', # C+0x29 # U+0x0029 + 'asterisk' => '389', # C+0x2A # U+0x002A + 'plus' => '584', # C+0x2B # U+0x002B + 'comma' => '278', # C+0x2C # U+0x002C + 'hyphen' => '333', # C+0x2D # U+0x002D + 'period' => '278', # C+0x2E # U+0x002E + 'slash' => '278', # C+0x2F # U+0x002F + 'zero' => '556', # C+0x30 # U+0x0030 + 'one' => '556', # C+0x31 # U+0x0031 + 'two' => '556', # C+0x32 # U+0x0032 + 'three' => '556', # C+0x33 # U+0x0033 + 'four' => '556', # C+0x34 # U+0x0034 + 'five' => '556', # C+0x35 # U+0x0035 + 'six' => '556', # C+0x36 # U+0x0036 + 'seven' => '556', # C+0x37 # U+0x0037 + 'eight' => '556', # C+0x38 # U+0x0038 + 'nine' => '556', # C+0x39 # U+0x0039 + 'colon' => '333', # C+0x3A # U+0x003A + 'semicolon' => '333', # C+0x3B # U+0x003B + 'less' => '584', # C+0x3C # U+0x003C + 'equal' => '584', # C+0x3D # U+0x003D + 'greater' => '584', # C+0x3E # U+0x003E + 'question' => '611', # C+0x3F # U+0x003F + 'at' => '975', # C+0x40 # U+0x0040 + 'A' => '722', # C+0x41 # U+0x0041 + 'B' => '722', # C+0x42 # U+0x0042 + 'C' => '722', # C+0x43 # U+0x0043 + 'D' => '722', # C+0x44 # U+0x0044 + 'E' => '667', # C+0x45 # U+0x0045 + 'F' => '611', # C+0x46 # U+0x0046 + 'G' => '778', # C+0x47 # U+0x0047 + 'H' => '722', # C+0x48 # U+0x0048 + 'I' => '278', # C+0x49 # U+0x0049 + 'J' => '556', # C+0x4A # U+0x004A + 'K' => '722', # C+0x4B # U+0x004B + 'L' => '611', # C+0x4C # U+0x004C + 'M' => '833', # C+0x4D # U+0x004D + 'N' => '722', # C+0x4E # U+0x004E + 'O' => '778', # C+0x4F # U+0x004F + 'P' => '667', # C+0x50 # U+0x0050 + 'Q' => '778', # C+0x51 # U+0x0051 + 'R' => '722', # C+0x52 # U+0x0052 + 'S' => '667', # C+0x53 # U+0x0053 + 'T' => '611', # C+0x54 # U+0x0054 + 'U' => '722', # C+0x55 # U+0x0055 + 'V' => '667', # C+0x56 # U+0x0056 + 'W' => '944', # C+0x57 # U+0x0057 + 'X' => '667', # C+0x58 # U+0x0058 + 'Y' => '667', # C+0x59 # U+0x0059 + 'Z' => '611', # C+0x5A # U+0x005A + 'bracketleft' => '333', # C+0x5B # U+0x005B + 'backslash' => '278', # C+0x5C # U+0x005C + 'bracketright' => '333', # C+0x5D # U+0x005D + 'asciicircum' => '584', # C+0x5E # U+0x005E + 'underscore' => '556', # C+0x5F # U+0x005F + 'grave' => '333', # C+0x60 # U+0x0060 + 'a' => '556', # C+0x61 # U+0x0061 + 'b' => '611', # C+0x62 # U+0x0062 + 'c' => '556', # C+0x63 # U+0x0063 + 'd' => '611', # C+0x64 # U+0x0064 + 'e' => '556', # C+0x65 # U+0x0065 + 'f' => '333', # C+0x66 # U+0x0066 + 'g' => '611', # C+0x67 # U+0x0067 + 'h' => '611', # C+0x68 # U+0x0068 + 'i' => '278', # C+0x69 # U+0x0069 + 'j' => '278', # C+0x6A # U+0x006A + 'k' => '556', # C+0x6B # U+0x006B + 'l' => '278', # C+0x6C # U+0x006C + 'm' => '889', # C+0x6D # U+0x006D + 'n' => '611', # C+0x6E # U+0x006E + 'o' => '611', # C+0x6F # U+0x006F + 'p' => '611', # C+0x70 # U+0x0070 + 'q' => '611', # C+0x71 # U+0x0071 + 'r' => '389', # C+0x72 # U+0x0072 + 's' => '556', # C+0x73 # U+0x0073 + 't' => '333', # C+0x74 # U+0x0074 + 'u' => '611', # C+0x75 # U+0x0075 + 'v' => '556', # C+0x76 # U+0x0076 + 'w' => '778', # C+0x77 # U+0x0077 + 'x' => '556', # C+0x78 # U+0x0078 + 'y' => '556', # C+0x79 # U+0x0079 + 'z' => '500', # C+0x7A # U+0x007A + 'braceleft' => '389', # C+0x7B # U+0x007B + 'bar' => '280', # C+0x7C # U+0x007C + 'braceright' => '389', # C+0x7D # U+0x007D + 'asciitilde' => '584', # C+0x7E # U+0x007E + 'bullet' => '350', # C+0x7F # U+0x2022 + 'Euro' => '556', # C+0x80 # U+0x20AC + 'quotesinglbase' => '278', # C+0x82 # U+0x201A + 'florin' => '556', # C+0x83 # U+0x0192 + 'quotedblbase' => '500', # C+0x84 # U+0x201E + 'ellipsis' => '1000', # C+0x85 # U+0x2026 + 'dagger' => '556', # C+0x86 # U+0x2020 + 'daggerdbl' => '556', # C+0x87 # U+0x2021 + 'circumflex' => '333', # C+0x88 # U+0x02C6 + 'perthousand' => '1000', # C+0x89 # U+0x2030 + 'Scaron' => '667', # C+0x8A # U+0x0160 + 'guilsinglleft' => '333', # C+0x8B # U+0x2039 + 'OE' => '1000', # C+0x8C # U+0x0152 + 'Zcaron' => '611', # C+0x8E # U+0x017D + 'quoteleft' => '278', # C+0x91 # U+0x2018 + 'quoteright' => '278', # C+0x92 # U+0x2019 + 'quotedblleft' => '500', # C+0x93 # U+0x201C + 'quotedblright' => '500', # C+0x94 # U+0x201D + 'endash' => '556', # C+0x96 # U+0x2013 + 'emdash' => '1000', # C+0x97 # U+0x2014 + 'tilde' => '333', # C+0x98 # U+0x02DC + 'trademark' => '1000', # C+0x99 # U+0x2122 + 'scaron' => '556', # C+0x9A # U+0x0161 + 'guilsinglright' => '333', # C+0x9B # U+0x203A + 'oe' => '944', # C+0x9C # U+0x0153 + 'zcaron' => '500', # C+0x9E # U+0x017E + 'Ydieresis' => '667', # C+0x9F # U+0x0178 + 'exclamdown' => '333', # C+0xA1 # U+0x00A1 + 'cent' => '556', # C+0xA2 # U+0x00A2 + 'sterling' => '556', # C+0xA3 # U+0x00A3 + 'currency' => '556', # C+0xA4 # U+0x00A4 + 'yen' => '556', # C+0xA5 # U+0x00A5 + 'brokenbar' => '280', # C+0xA6 # U+0x00A6 + 'section' => '556', # C+0xA7 # U+0x00A7 + 'dieresis' => '333', # C+0xA8 # U+0x00A8 + 'copyright' => '737', # C+0xA9 # U+0x00A9 + 'ordfeminine' => '370', # C+0xAA # U+0x00AA + 'guillemotleft' => '556', # C+0xAB # U+0x00AB + 'logicalnot' => '584', # C+0xAC # U+0x00AC + 'registered' => '737', # C+0xAE # U+0x00AE + 'macron' => '333', # C+0xAF # U+0x00AF + 'degree' => '400', # C+0xB0 # U+0x00B0 + 'plusminus' => '584', # C+0xB1 # U+0x00B1 + 'twosuperior' => '333', # C+0xB2 # U+0x00B2 + 'threesuperior' => '333', # C+0xB3 # U+0x00B3 + 'acute' => '333', # C+0xB4 # U+0x00B4 + 'mu' => '611', # C+0xB5 # U+0x00B5 + 'paragraph' => '556', # C+0xB6 # U+0x00B6 + 'periodcentered' => '278', # C+0xB7 # U+0x00B7 + 'cedilla' => '333', # C+0xB8 # U+0x00B8 + 'onesuperior' => '333', # C+0xB9 # U+0x00B9 + 'ordmasculine' => '365', # C+0xBA # U+0x00BA + 'guillemotright' => '556', # C+0xBB # U+0x00BB + 'onequarter' => '834', # C+0xBC # U+0x00BC + 'onehalf' => '834', # C+0xBD # U+0x00BD + 'threequarters' => '834', # C+0xBE # U+0x00BE + 'questiondown' => '611', # C+0xBF # U+0x00BF + 'Agrave' => '722', # C+0xC0 # U+0x00C0 + 'Aacute' => '722', # C+0xC1 # U+0x00C1 + 'Acircumflex' => '722', # C+0xC2 # U+0x00C2 + 'Atilde' => '722', # C+0xC3 # U+0x00C3 + 'Adieresis' => '722', # C+0xC4 # U+0x00C4 + 'Aring' => '722', # C+0xC5 # U+0x00C5 + 'AE' => '1000', # C+0xC6 # U+0x00C6 + 'Ccedilla' => '722', # C+0xC7 # U+0x00C7 + 'Egrave' => '667', # C+0xC8 # U+0x00C8 + 'Eacute' => '667', # C+0xC9 # U+0x00C9 + 'Ecircumflex' => '667', # C+0xCA # U+0x00CA + 'Edieresis' => '667', # C+0xCB # U+0x00CB + 'Igrave' => '278', # C+0xCC # U+0x00CC + 'Iacute' => '278', # C+0xCD # U+0x00CD + 'Icircumflex' => '278', # C+0xCE # U+0x00CE + 'Idieresis' => '278', # C+0xCF # U+0x00CF + 'Eth' => '722', # C+0xD0 # U+0x00D0 + 'Ntilde' => '722', # C+0xD1 # U+0x00D1 + 'Ograve' => '778', # C+0xD2 # U+0x00D2 + 'Oacute' => '778', # C+0xD3 # U+0x00D3 + 'Ocircumflex' => '778', # C+0xD4 # U+0x00D4 + 'Otilde' => '778', # C+0xD5 # U+0x00D5 + 'Odieresis' => '778', # C+0xD6 # U+0x00D6 + 'multiply' => '584', # C+0xD7 # U+0x00D7 + 'Oslash' => '778', # C+0xD8 # U+0x00D8 + 'Ugrave' => '722', # C+0xD9 # U+0x00D9 + 'Uacute' => '722', # C+0xDA # U+0x00DA + 'Ucircumflex' => '722', # C+0xDB # U+0x00DB + 'Udieresis' => '722', # C+0xDC # U+0x00DC + 'Yacute' => '667', # C+0xDD # U+0x00DD + 'Thorn' => '667', # C+0xDE # U+0x00DE + 'germandbls' => '611', # C+0xDF # U+0x00DF + 'agrave' => '556', # C+0xE0 # U+0x00E0 + 'aacute' => '556', # C+0xE1 # U+0x00E1 + 'acircumflex' => '556', # C+0xE2 # U+0x00E2 + 'atilde' => '556', # C+0xE3 # U+0x00E3 + 'adieresis' => '556', # C+0xE4 # U+0x00E4 + 'aring' => '556', # C+0xE5 # U+0x00E5 + 'ae' => '889', # C+0xE6 # U+0x00E6 + 'ccedilla' => '556', # C+0xE7 # U+0x00E7 + 'egrave' => '556', # C+0xE8 # U+0x00E8 + 'eacute' => '556', # C+0xE9 # U+0x00E9 + 'ecircumflex' => '556', # C+0xEA # U+0x00EA + 'edieresis' => '556', # C+0xEB # U+0x00EB + 'igrave' => '278', # C+0xEC # U+0x00EC + 'iacute' => '278', # C+0xED # U+0x00ED + 'icircumflex' => '278', # C+0xEE # U+0x00EE + 'idieresis' => '278', # C+0xEF # U+0x00EF + 'eth' => '611', # C+0xF0 # U+0x00F0 + 'ntilde' => '611', # C+0xF1 # U+0x00F1 + 'ograve' => '611', # C+0xF2 # U+0x00F2 + 'oacute' => '611', # C+0xF3 # U+0x00F3 + 'ocircumflex' => '611', # C+0xF4 # U+0x00F4 + 'otilde' => '611', # C+0xF5 # U+0x00F5 + 'odieresis' => '611', # C+0xF6 # U+0x00F6 + 'divide' => '584', # C+0xF7 # U+0x00F7 + 'oslash' => '611', # C+0xF8 # U+0x00F8 + 'ugrave' => '611', # C+0xF9 # U+0x00F9 + 'uacute' => '611', # C+0xFA # U+0x00FA + 'ucircumflex' => '611', # C+0xFB # U+0x00FB + 'udieresis' => '611', # C+0xFC # U+0x00FC + 'yacute' => '556', # C+0xFD # U+0x00FD + 'thorn' => '611', # C+0xFE # U+0x00FE + 'ydieresis' => '556', # C+0xFF # U+0x00FF + 'dotlessi' => '278', # U+0x0131 + 'Lslash' => '611', # U+0x0141 + 'lslash' => '278', # U+0x0142 + 'caron' => '333', # U+0x02C7 + 'breve' => '333', # U+0x02D8 + 'dotaccent' => '333', # U+0x02D9 + 'ring' => '333', # U+0x02DA + 'ogonek' => '333', # U+0x02DB + 'hungarumlaut' => '333', # U+0x02DD + 'fraction' => '167', # U+0x2044 + 'minus' => '584', # U+0x2212 + 'fi' => '611', # U+0xFB01 + 'fl' => '611', # U+0xFB02 + }, # HORIZ. WIDTH TABLE +} }; + +1; diff --git a/lib/PDF/API2/Resource/Font/CoreFont/helveticaoblique.pm b/lib/PDF/API2/Resource/Font/CoreFont/helveticaoblique.pm new file mode 100644 index 0000000..5adbe9a --- /dev/null +++ b/lib/PDF/API2/Resource/Font/CoreFont/helveticaoblique.pm @@ -0,0 +1,519 @@ +#line 1 "PDF/API2/Resource/Font/CoreFont/helveticaoblique.pm" +#line 1 "PDF/API2/Resource/Font/CoreFont/helveticaoblique.pm" +package PDF::API2::Resource::Font::CoreFont::helveticaoblique; + +use strict; +use warnings; + +our $VERSION = '2.033'; # VERSION + +sub data { return { + 'fontname' => 'Helvetica-Oblique', + 'type' => 'Type1', + 'apiname' => 'HeIt', + 'ascender' => '718', + 'capheight' => '718', + 'descender' => '-207', + 'iscore' => '1', + 'isfixedpitch' => '0', + 'italicangle' => '-12', + 'stdhw' => '76', + 'stdvw' => '88', + 'underlineposition' => '-100', + 'underlinethickness' => '50', + 'xheight' => '523', + 'firstchar' => '32', + 'lastchar' => '255', + 'char' => [ # DEF. ENCODING GLYPH TABLE + '.notdef', # C+0x00 # U+0x0000 + '.notdef', # C+0x01 # U+0x0000 + '.notdef', # C+0x02 # U+0x0000 + '.notdef', # C+0x03 # U+0x0000 + '.notdef', # C+0x04 # U+0x0000 + '.notdef', # C+0x05 # U+0x0000 + '.notdef', # C+0x06 # U+0x0000 + '.notdef', # C+0x07 # U+0x0000 + '.notdef', # C+0x08 # U+0x0000 + '.notdef', # C+0x09 # U+0x0000 + '.notdef', # C+0x0A # U+0x0000 + '.notdef', # C+0x0B # U+0x0000 + '.notdef', # C+0x0C # U+0x0000 + '.notdef', # C+0x0D # U+0x0000 + '.notdef', # C+0x0E # U+0x0000 + '.notdef', # C+0x0F # U+0x0000 + '.notdef', # C+0x10 # U+0x0000 + '.notdef', # C+0x11 # U+0x0000 + '.notdef', # C+0x12 # U+0x0000 + '.notdef', # C+0x13 # U+0x0000 + '.notdef', # C+0x14 # U+0x0000 + '.notdef', # C+0x15 # U+0x0000 + '.notdef', # C+0x16 # U+0x0000 + '.notdef', # C+0x17 # U+0x0000 + '.notdef', # C+0x18 # U+0x0000 + '.notdef', # C+0x19 # U+0x0000 + '.notdef', # C+0x1A # U+0x0000 + '.notdef', # C+0x1B # U+0x0000 + '.notdef', # C+0x1C # U+0x0000 + '.notdef', # C+0x1D # U+0x0000 + '.notdef', # C+0x1E # U+0x0000 + '.notdef', # C+0x1F # U+0x0000 + 'space', # C+0x20 # U+0x0020 + 'exclam', # C+0x21 # U+0x0021 + 'quotedbl', # C+0x22 # U+0x0022 + 'numbersign', # C+0x23 # U+0x0023 + 'dollar', # C+0x24 # U+0x0024 + 'percent', # C+0x25 # U+0x0025 + 'ampersand', # C+0x26 # U+0x0026 + 'quotesingle', # C+0x27 # U+0x0027 + 'parenleft', # C+0x28 # U+0x0028 + 'parenright', # C+0x29 # U+0x0029 + 'asterisk', # C+0x2A # U+0x002A + 'plus', # C+0x2B # U+0x002B + 'comma', # C+0x2C # U+0x002C + 'hyphen', # C+0x2D # U+0x002D + 'period', # C+0x2E # U+0x002E + 'slash', # C+0x2F # U+0x002F + 'zero', # C+0x30 # U+0x0030 + 'one', # C+0x31 # U+0x0031 + 'two', # C+0x32 # U+0x0032 + 'three', # C+0x33 # U+0x0033 + 'four', # C+0x34 # U+0x0034 + 'five', # C+0x35 # U+0x0035 + 'six', # C+0x36 # U+0x0036 + 'seven', # C+0x37 # U+0x0037 + 'eight', # C+0x38 # U+0x0038 + 'nine', # C+0x39 # U+0x0039 + 'colon', # C+0x3A # U+0x003A + 'semicolon', # C+0x3B # U+0x003B + 'less', # C+0x3C # U+0x003C + 'equal', # C+0x3D # U+0x003D + 'greater', # C+0x3E # U+0x003E + 'question', # C+0x3F # U+0x003F + 'at', # C+0x40 # U+0x0040 + 'A', # C+0x41 # U+0x0041 + 'B', # C+0x42 # U+0x0042 + 'C', # C+0x43 # U+0x0043 + 'D', # C+0x44 # U+0x0044 + 'E', # C+0x45 # U+0x0045 + 'F', # C+0x46 # U+0x0046 + 'G', # C+0x47 # U+0x0047 + 'H', # C+0x48 # U+0x0048 + 'I', # C+0x49 # U+0x0049 + 'J', # C+0x4A # U+0x004A + 'K', # C+0x4B # U+0x004B + 'L', # C+0x4C # U+0x004C + 'M', # C+0x4D # U+0x004D + 'N', # C+0x4E # U+0x004E + 'O', # C+0x4F # U+0x004F + 'P', # C+0x50 # U+0x0050 + 'Q', # C+0x51 # U+0x0051 + 'R', # C+0x52 # U+0x0052 + 'S', # C+0x53 # U+0x0053 + 'T', # C+0x54 # U+0x0054 + 'U', # C+0x55 # U+0x0055 + 'V', # C+0x56 # U+0x0056 + 'W', # C+0x57 # U+0x0057 + 'X', # C+0x58 # U+0x0058 + 'Y', # C+0x59 # U+0x0059 + 'Z', # C+0x5A # U+0x005A + 'bracketleft', # C+0x5B # U+0x005B + 'backslash', # C+0x5C # U+0x005C + 'bracketright', # C+0x5D # U+0x005D + 'asciicircum', # C+0x5E # U+0x005E + 'underscore', # C+0x5F # U+0x005F + 'grave', # C+0x60 # U+0x0060 + 'a', # C+0x61 # U+0x0061 + 'b', # C+0x62 # U+0x0062 + 'c', # C+0x63 # U+0x0063 + 'd', # C+0x64 # U+0x0064 + 'e', # C+0x65 # U+0x0065 + 'f', # C+0x66 # U+0x0066 + 'g', # C+0x67 # U+0x0067 + 'h', # C+0x68 # U+0x0068 + 'i', # C+0x69 # U+0x0069 + 'j', # C+0x6A # U+0x006A + 'k', # C+0x6B # U+0x006B + 'l', # C+0x6C # U+0x006C + 'm', # C+0x6D # U+0x006D + 'n', # C+0x6E # U+0x006E + 'o', # C+0x6F # U+0x006F + 'p', # C+0x70 # U+0x0070 + 'q', # C+0x71 # U+0x0071 + 'r', # C+0x72 # U+0x0072 + 's', # C+0x73 # U+0x0073 + 't', # C+0x74 # U+0x0074 + 'u', # C+0x75 # U+0x0075 + 'v', # C+0x76 # U+0x0076 + 'w', # C+0x77 # U+0x0077 + 'x', # C+0x78 # U+0x0078 + 'y', # C+0x79 # U+0x0079 + 'z', # C+0x7A # U+0x007A + 'braceleft', # C+0x7B # U+0x007B + 'bar', # C+0x7C # U+0x007C + 'braceright', # C+0x7D # U+0x007D + 'asciitilde', # C+0x7E # U+0x007E + 'bullet', # C+0x7F # U+0x2022 + 'Euro', # C+0x80 # U+0x20AC + 'bullet', # C+0x81 # U+0x2022 + 'quotesinglbase', # C+0x82 # U+0x201A + 'florin', # C+0x83 # U+0x0192 + 'quotedblbase', # C+0x84 # U+0x201E + 'ellipsis', # C+0x85 # U+0x2026 + 'dagger', # C+0x86 # U+0x2020 + 'daggerdbl', # C+0x87 # U+0x2021 + 'circumflex', # C+0x88 # U+0x02C6 + 'perthousand', # C+0x89 # U+0x2030 + 'Scaron', # C+0x8A # U+0x0160 + 'guilsinglleft', # C+0x8B # U+0x2039 + 'OE', # C+0x8C # U+0x0152 + 'bullet', # C+0x8D # U+0x2022 + 'Zcaron', # C+0x8E # U+0x017D + 'bullet', # C+0x8F # U+0x2022 + 'bullet', # C+0x90 # U+0x2022 + 'quoteleft', # C+0x91 # U+0x2018 + 'quoteright', # C+0x92 # U+0x2019 + 'quotedblleft', # C+0x93 # U+0x201C + 'quotedblright', # C+0x94 # U+0x201D + 'bullet', # C+0x95 # U+0x2022 + 'endash', # C+0x96 # U+0x2013 + 'emdash', # C+0x97 # U+0x2014 + 'tilde', # C+0x98 # U+0x02DC + 'trademark', # C+0x99 # U+0x2122 + 'scaron', # C+0x9A # U+0x0161 + 'guilsinglright', # C+0x9B # U+0x203A + 'oe', # C+0x9C # U+0x0153 + 'bullet', # C+0x9D # U+0x2022 + 'zcaron', # C+0x9E # U+0x017E + 'Ydieresis', # C+0x9F # U+0x0178 + 'space', # C+0xA0 # U+0x0020 + 'exclamdown', # C+0xA1 # U+0x00A1 + 'cent', # C+0xA2 # U+0x00A2 + 'sterling', # C+0xA3 # U+0x00A3 + 'currency', # C+0xA4 # U+0x00A4 + 'yen', # C+0xA5 # U+0x00A5 + 'brokenbar', # C+0xA6 # U+0x00A6 + 'section', # C+0xA7 # U+0x00A7 + 'dieresis', # C+0xA8 # U+0x00A8 + 'copyright', # C+0xA9 # U+0x00A9 + 'ordfeminine', # C+0xAA # U+0x00AA + 'guillemotleft', # C+0xAB # U+0x00AB + 'logicalnot', # C+0xAC # U+0x00AC + 'hyphen', # C+0xAD # U+0x002D + 'registered', # C+0xAE # U+0x00AE + 'macron', # C+0xAF # U+0x00AF + 'degree', # C+0xB0 # U+0x00B0 + 'plusminus', # C+0xB1 # U+0x00B1 + 'twosuperior', # C+0xB2 # U+0x00B2 + 'threesuperior', # C+0xB3 # U+0x00B3 + 'acute', # C+0xB4 # U+0x00B4 + 'mu', # C+0xB5 # U+0x00B5 + 'paragraph', # C+0xB6 # U+0x00B6 + 'periodcentered', # C+0xB7 # U+0x00B7 + 'cedilla', # C+0xB8 # U+0x00B8 + 'onesuperior', # C+0xB9 # U+0x00B9 + 'ordmasculine', # C+0xBA # U+0x00BA + 'guillemotright', # C+0xBB # U+0x00BB + 'onequarter', # C+0xBC # U+0x00BC + 'onehalf', # C+0xBD # U+0x00BD + 'threequarters', # C+0xBE # U+0x00BE + 'questiondown', # C+0xBF # U+0x00BF + 'Agrave', # C+0xC0 # U+0x00C0 + 'Aacute', # C+0xC1 # U+0x00C1 + 'Acircumflex', # C+0xC2 # U+0x00C2 + 'Atilde', # C+0xC3 # U+0x00C3 + 'Adieresis', # C+0xC4 # U+0x00C4 + 'Aring', # C+0xC5 # U+0x00C5 + 'AE', # C+0xC6 # U+0x00C6 + 'Ccedilla', # C+0xC7 # U+0x00C7 + 'Egrave', # C+0xC8 # U+0x00C8 + 'Eacute', # C+0xC9 # U+0x00C9 + 'Ecircumflex', # C+0xCA # U+0x00CA + 'Edieresis', # C+0xCB # U+0x00CB + 'Igrave', # C+0xCC # U+0x00CC + 'Iacute', # C+0xCD # U+0x00CD + 'Icircumflex', # C+0xCE # U+0x00CE + 'Idieresis', # C+0xCF # U+0x00CF + 'Eth', # C+0xD0 # U+0x00D0 + 'Ntilde', # C+0xD1 # U+0x00D1 + 'Ograve', # C+0xD2 # U+0x00D2 + 'Oacute', # C+0xD3 # U+0x00D3 + 'Ocircumflex', # C+0xD4 # U+0x00D4 + 'Otilde', # C+0xD5 # U+0x00D5 + 'Odieresis', # C+0xD6 # U+0x00D6 + 'multiply', # C+0xD7 # U+0x00D7 + 'Oslash', # C+0xD8 # U+0x00D8 + 'Ugrave', # C+0xD9 # U+0x00D9 + 'Uacute', # C+0xDA # U+0x00DA + 'Ucircumflex', # C+0xDB # U+0x00DB + 'Udieresis', # C+0xDC # U+0x00DC + 'Yacute', # C+0xDD # U+0x00DD + 'Thorn', # C+0xDE # U+0x00DE + 'germandbls', # C+0xDF # U+0x00DF + 'agrave', # C+0xE0 # U+0x00E0 + 'aacute', # C+0xE1 # U+0x00E1 + 'acircumflex', # C+0xE2 # U+0x00E2 + 'atilde', # C+0xE3 # U+0x00E3 + 'adieresis', # C+0xE4 # U+0x00E4 + 'aring', # C+0xE5 # U+0x00E5 + 'ae', # C+0xE6 # U+0x00E6 + 'ccedilla', # C+0xE7 # U+0x00E7 + 'egrave', # C+0xE8 # U+0x00E8 + 'eacute', # C+0xE9 # U+0x00E9 + 'ecircumflex', # C+0xEA # U+0x00EA + 'edieresis', # C+0xEB # U+0x00EB + 'igrave', # C+0xEC # U+0x00EC + 'iacute', # C+0xED # U+0x00ED + 'icircumflex', # C+0xEE # U+0x00EE + 'idieresis', # C+0xEF # U+0x00EF + 'eth', # C+0xF0 # U+0x00F0 + 'ntilde', # C+0xF1 # U+0x00F1 + 'ograve', # C+0xF2 # U+0x00F2 + 'oacute', # C+0xF3 # U+0x00F3 + 'ocircumflex', # C+0xF4 # U+0x00F4 + 'otilde', # C+0xF5 # U+0x00F5 + 'odieresis', # C+0xF6 # U+0x00F6 + 'divide', # C+0xF7 # U+0x00F7 + 'oslash', # C+0xF8 # U+0x00F8 + 'ugrave', # C+0xF9 # U+0x00F9 + 'uacute', # C+0xFA # U+0x00FA + 'ucircumflex', # C+0xFB # U+0x00FB + 'udieresis', # C+0xFC # U+0x00FC + 'yacute', # C+0xFD # U+0x00FD + 'thorn', # C+0xFE # U+0x00FE + 'ydieresis', # C+0xFF # U+0x00FF + ], # DEF. ENCODING GLYPH TABLE + 'fontbbox' => [ -170, -225, 1116, 931 ], + 'wx' => { # HORIZ. WIDTH TABLE + 'space' => '278', # C+0x20 # U+0x0020 + 'exclam' => '278', # C+0x21 # U+0x0021 + 'quotedbl' => '355', # C+0x22 # U+0x0022 + 'numbersign' => '556', # C+0x23 # U+0x0023 + 'dollar' => '556', # C+0x24 # U+0x0024 + 'percent' => '889', # C+0x25 # U+0x0025 + 'ampersand' => '667', # C+0x26 # U+0x0026 + 'quotesingle' => '191', # C+0x27 # U+0x0027 + 'parenleft' => '333', # C+0x28 # U+0x0028 + 'parenright' => '333', # C+0x29 # U+0x0029 + 'asterisk' => '389', # C+0x2A # U+0x002A + 'plus' => '584', # C+0x2B # U+0x002B + 'comma' => '278', # C+0x2C # U+0x002C + 'hyphen' => '333', # C+0x2D # U+0x002D + 'period' => '278', # C+0x2E # U+0x002E + 'slash' => '278', # C+0x2F # U+0x002F + 'zero' => '556', # C+0x30 # U+0x0030 + 'one' => '556', # C+0x31 # U+0x0031 + 'two' => '556', # C+0x32 # U+0x0032 + 'three' => '556', # C+0x33 # U+0x0033 + 'four' => '556', # C+0x34 # U+0x0034 + 'five' => '556', # C+0x35 # U+0x0035 + 'six' => '556', # C+0x36 # U+0x0036 + 'seven' => '556', # C+0x37 # U+0x0037 + 'eight' => '556', # C+0x38 # U+0x0038 + 'nine' => '556', # C+0x39 # U+0x0039 + 'colon' => '278', # C+0x3A # U+0x003A + 'semicolon' => '278', # C+0x3B # U+0x003B + 'less' => '584', # C+0x3C # U+0x003C + 'equal' => '584', # C+0x3D # U+0x003D + 'greater' => '584', # C+0x3E # U+0x003E + 'question' => '556', # C+0x3F # U+0x003F + 'at' => '1015', # C+0x40 # U+0x0040 + 'A' => '667', # C+0x41 # U+0x0041 + 'B' => '667', # C+0x42 # U+0x0042 + 'C' => '722', # C+0x43 # U+0x0043 + 'D' => '722', # C+0x44 # U+0x0044 + 'E' => '667', # C+0x45 # U+0x0045 + 'F' => '611', # C+0x46 # U+0x0046 + 'G' => '778', # C+0x47 # U+0x0047 + 'H' => '722', # C+0x48 # U+0x0048 + 'I' => '278', # C+0x49 # U+0x0049 + 'J' => '500', # C+0x4A # U+0x004A + 'K' => '667', # C+0x4B # U+0x004B + 'L' => '556', # C+0x4C # U+0x004C + 'M' => '833', # C+0x4D # U+0x004D + 'N' => '722', # C+0x4E # U+0x004E + 'O' => '778', # C+0x4F # U+0x004F + 'P' => '667', # C+0x50 # U+0x0050 + 'Q' => '778', # C+0x51 # U+0x0051 + 'R' => '722', # C+0x52 # U+0x0052 + 'S' => '667', # C+0x53 # U+0x0053 + 'T' => '611', # C+0x54 # U+0x0054 + 'U' => '722', # C+0x55 # U+0x0055 + 'V' => '667', # C+0x56 # U+0x0056 + 'W' => '944', # C+0x57 # U+0x0057 + 'X' => '667', # C+0x58 # U+0x0058 + 'Y' => '667', # C+0x59 # U+0x0059 + 'Z' => '611', # C+0x5A # U+0x005A + 'bracketleft' => '278', # C+0x5B # U+0x005B + 'backslash' => '278', # C+0x5C # U+0x005C + 'bracketright' => '278', # C+0x5D # U+0x005D + 'asciicircum' => '469', # C+0x5E # U+0x005E + 'underscore' => '556', # C+0x5F # U+0x005F + 'grave' => '333', # C+0x60 # U+0x0060 + 'a' => '556', # C+0x61 # U+0x0061 + 'b' => '556', # C+0x62 # U+0x0062 + 'c' => '500', # C+0x63 # U+0x0063 + 'd' => '556', # C+0x64 # U+0x0064 + 'e' => '556', # C+0x65 # U+0x0065 + 'f' => '278', # C+0x66 # U+0x0066 + 'g' => '556', # C+0x67 # U+0x0067 + 'h' => '556', # C+0x68 # U+0x0068 + 'i' => '222', # C+0x69 # U+0x0069 + 'j' => '222', # C+0x6A # U+0x006A + 'k' => '500', # C+0x6B # U+0x006B + 'l' => '222', # C+0x6C # U+0x006C + 'm' => '833', # C+0x6D # U+0x006D + 'n' => '556', # C+0x6E # U+0x006E + 'o' => '556', # C+0x6F # U+0x006F + 'p' => '556', # C+0x70 # U+0x0070 + 'q' => '556', # C+0x71 # U+0x0071 + 'r' => '333', # C+0x72 # U+0x0072 + 's' => '500', # C+0x73 # U+0x0073 + 't' => '278', # C+0x74 # U+0x0074 + 'u' => '556', # C+0x75 # U+0x0075 + 'v' => '500', # C+0x76 # U+0x0076 + 'w' => '722', # C+0x77 # U+0x0077 + 'x' => '500', # C+0x78 # U+0x0078 + 'y' => '500', # C+0x79 # U+0x0079 + 'z' => '500', # C+0x7A # U+0x007A + 'braceleft' => '334', # C+0x7B # U+0x007B + 'bar' => '260', # C+0x7C # U+0x007C + 'braceright' => '334', # C+0x7D # U+0x007D + 'asciitilde' => '584', # C+0x7E # U+0x007E + 'bullet' => '350', # C+0x7F # U+0x2022 + 'Euro' => '556', # C+0x80 # U+0x20AC + 'quotesinglbase' => '222', # C+0x82 # U+0x201A + 'florin' => '556', # C+0x83 # U+0x0192 + 'quotedblbase' => '333', # C+0x84 # U+0x201E + 'ellipsis' => '1000', # C+0x85 # U+0x2026 + 'dagger' => '556', # C+0x86 # U+0x2020 + 'daggerdbl' => '556', # C+0x87 # U+0x2021 + 'circumflex' => '333', # C+0x88 # U+0x02C6 + 'perthousand' => '1000', # C+0x89 # U+0x2030 + 'Scaron' => '667', # C+0x8A # U+0x0160 + 'guilsinglleft' => '333', # C+0x8B # U+0x2039 + 'OE' => '1000', # C+0x8C # U+0x0152 + 'Zcaron' => '611', # C+0x8E # U+0x017D + 'quoteleft' => '222', # C+0x91 # U+0x2018 + 'quoteright' => '222', # C+0x92 # U+0x2019 + 'quotedblleft' => '333', # C+0x93 # U+0x201C + 'quotedblright' => '333', # C+0x94 # U+0x201D + 'endash' => '556', # C+0x96 # U+0x2013 + 'emdash' => '1000', # C+0x97 # U+0x2014 + 'tilde' => '333', # C+0x98 # U+0x02DC + 'trademark' => '1000', # C+0x99 # U+0x2122 + 'scaron' => '500', # C+0x9A # U+0x0161 + 'guilsinglright' => '333', # C+0x9B # U+0x203A + 'oe' => '944', # C+0x9C # U+0x0153 + 'zcaron' => '500', # C+0x9E # U+0x017E + 'Ydieresis' => '667', # C+0x9F # U+0x0178 + 'exclamdown' => '333', # C+0xA1 # U+0x00A1 + 'cent' => '556', # C+0xA2 # U+0x00A2 + 'sterling' => '556', # C+0xA3 # U+0x00A3 + 'currency' => '556', # C+0xA4 # U+0x00A4 + 'yen' => '556', # C+0xA5 # U+0x00A5 + 'brokenbar' => '260', # C+0xA6 # U+0x00A6 + 'section' => '556', # C+0xA7 # U+0x00A7 + 'dieresis' => '333', # C+0xA8 # U+0x00A8 + 'copyright' => '737', # C+0xA9 # U+0x00A9 + 'ordfeminine' => '370', # C+0xAA # U+0x00AA + 'guillemotleft' => '556', # C+0xAB # U+0x00AB + 'logicalnot' => '584', # C+0xAC # U+0x00AC + 'registered' => '737', # C+0xAE # U+0x00AE + 'macron' => '333', # C+0xAF # U+0x00AF + 'degree' => '400', # C+0xB0 # U+0x00B0 + 'plusminus' => '584', # C+0xB1 # U+0x00B1 + 'twosuperior' => '333', # C+0xB2 # U+0x00B2 + 'threesuperior' => '333', # C+0xB3 # U+0x00B3 + 'acute' => '333', # C+0xB4 # U+0x00B4 + 'mu' => '556', # C+0xB5 # U+0x00B5 + 'paragraph' => '537', # C+0xB6 # U+0x00B6 + 'periodcentered' => '278', # C+0xB7 # U+0x00B7 + 'cedilla' => '333', # C+0xB8 # U+0x00B8 + 'onesuperior' => '333', # C+0xB9 # U+0x00B9 + 'ordmasculine' => '365', # C+0xBA # U+0x00BA + 'guillemotright' => '556', # C+0xBB # U+0x00BB + 'onequarter' => '834', # C+0xBC # U+0x00BC + 'onehalf' => '834', # C+0xBD # U+0x00BD + 'threequarters' => '834', # C+0xBE # U+0x00BE + 'questiondown' => '611', # C+0xBF # U+0x00BF + 'Agrave' => '667', # C+0xC0 # U+0x00C0 + 'Aacute' => '667', # C+0xC1 # U+0x00C1 + 'Acircumflex' => '667', # C+0xC2 # U+0x00C2 + 'Atilde' => '667', # C+0xC3 # U+0x00C3 + 'Adieresis' => '667', # C+0xC4 # U+0x00C4 + 'Aring' => '667', # C+0xC5 # U+0x00C5 + 'AE' => '1000', # C+0xC6 # U+0x00C6 + 'Ccedilla' => '722', # C+0xC7 # U+0x00C7 + 'Egrave' => '667', # C+0xC8 # U+0x00C8 + 'Eacute' => '667', # C+0xC9 # U+0x00C9 + 'Ecircumflex' => '667', # C+0xCA # U+0x00CA + 'Edieresis' => '667', # C+0xCB # U+0x00CB + 'Igrave' => '278', # C+0xCC # U+0x00CC + 'Iacute' => '278', # C+0xCD # U+0x00CD + 'Icircumflex' => '278', # C+0xCE # U+0x00CE + 'Idieresis' => '278', # C+0xCF # U+0x00CF + 'Eth' => '722', # C+0xD0 # U+0x00D0 + 'Ntilde' => '722', # C+0xD1 # U+0x00D1 + 'Ograve' => '778', # C+0xD2 # U+0x00D2 + 'Oacute' => '778', # C+0xD3 # U+0x00D3 + 'Ocircumflex' => '778', # C+0xD4 # U+0x00D4 + 'Otilde' => '778', # C+0xD5 # U+0x00D5 + 'Odieresis' => '778', # C+0xD6 # U+0x00D6 + 'multiply' => '584', # C+0xD7 # U+0x00D7 + 'Oslash' => '778', # C+0xD8 # U+0x00D8 + 'Ugrave' => '722', # C+0xD9 # U+0x00D9 + 'Uacute' => '722', # C+0xDA # U+0x00DA + 'Ucircumflex' => '722', # C+0xDB # U+0x00DB + 'Udieresis' => '722', # C+0xDC # U+0x00DC + 'Yacute' => '667', # C+0xDD # U+0x00DD + 'Thorn' => '667', # C+0xDE # U+0x00DE + 'germandbls' => '611', # C+0xDF # U+0x00DF + 'agrave' => '556', # C+0xE0 # U+0x00E0 + 'aacute' => '556', # C+0xE1 # U+0x00E1 + 'acircumflex' => '556', # C+0xE2 # U+0x00E2 + 'atilde' => '556', # C+0xE3 # U+0x00E3 + 'adieresis' => '556', # C+0xE4 # U+0x00E4 + 'aring' => '556', # C+0xE5 # U+0x00E5 + 'ae' => '889', # C+0xE6 # U+0x00E6 + 'ccedilla' => '500', # C+0xE7 # U+0x00E7 + 'egrave' => '556', # C+0xE8 # U+0x00E8 + 'eacute' => '556', # C+0xE9 # U+0x00E9 + 'ecircumflex' => '556', # C+0xEA # U+0x00EA + 'edieresis' => '556', # C+0xEB # U+0x00EB + 'igrave' => '278', # C+0xEC # U+0x00EC + 'iacute' => '278', # C+0xED # U+0x00ED + 'icircumflex' => '278', # C+0xEE # U+0x00EE + 'idieresis' => '278', # C+0xEF # U+0x00EF + 'eth' => '556', # C+0xF0 # U+0x00F0 + 'ntilde' => '556', # C+0xF1 # U+0x00F1 + 'ograve' => '556', # C+0xF2 # U+0x00F2 + 'oacute' => '556', # C+0xF3 # U+0x00F3 + 'ocircumflex' => '556', # C+0xF4 # U+0x00F4 + 'otilde' => '556', # C+0xF5 # U+0x00F5 + 'odieresis' => '556', # C+0xF6 # U+0x00F6 + 'divide' => '584', # C+0xF7 # U+0x00F7 + 'oslash' => '611', # C+0xF8 # U+0x00F8 + 'ugrave' => '556', # C+0xF9 # U+0x00F9 + 'uacute' => '556', # C+0xFA # U+0x00FA + 'ucircumflex' => '556', # C+0xFB # U+0x00FB + 'udieresis' => '556', # C+0xFC # U+0x00FC + 'yacute' => '500', # C+0xFD # U+0x00FD + 'thorn' => '556', # C+0xFE # U+0x00FE + 'ydieresis' => '500', # C+0xFF # U+0x00FF + 'dotlessi' => '278', # U+0x0131 + 'Lslash' => '556', # U+0x0141 + 'lslash' => '222', # U+0x0142 + 'caron' => '333', # U+0x02C7 + 'breve' => '333', # U+0x02D8 + 'dotaccent' => '333', # U+0x02D9 + 'ring' => '333', # U+0x02DA + 'ogonek' => '333', # U+0x02DB + 'hungarumlaut' => '333', # U+0x02DD + 'fraction' => '167', # U+0x2044 + 'minus' => '584', # U+0x2212 + 'fi' => '500', # U+0xFB01 + 'fl' => '500', # U+0xFB02 + }, # HORIZ. WIDTH TABLE +} }; + +1; diff --git a/lib/PDF/API2/Resource/Font/CoreFont/symbol.pm b/lib/PDF/API2/Resource/Font/CoreFont/symbol.pm new file mode 100644 index 0000000..20f2852 --- /dev/null +++ b/lib/PDF/API2/Resource/Font/CoreFont/symbol.pm @@ -0,0 +1,481 @@ +#line 1 "PDF/API2/Resource/Font/CoreFont/symbol.pm" +#line 1 "PDF/API2/Resource/Font/CoreFont/symbol.pm" +package PDF::API2::Resource::Font::CoreFont::symbol; + +use strict; +use warnings; + +our $VERSION = '2.033'; # VERSION + +sub data { return { + 'fontname' => 'Symbol', + 'type' => 'Type1', + 'apiname' => 'Sym', + 'ascender' => '600', + 'capheight' => '600', + 'descender' => '-200', + 'iscore' => '1', + 'isfixedpitch' => '0', + 'issymbol' => '1', + 'italicangle' => '0', + 'stdhw' => '92', + 'stdvw' => '85', + 'underlineposition' => '-100', + 'underlinethickness' => '50', + 'xheight' => '450', + 'firstchar' => '32', + 'lastchar' => '255', + 'char' => [ # DEF. ENCODING GLYPH TABLE + '.notdef', # C+0x00 # U+0x0000 + '.notdef', # C+0x01 # U+0x0000 + '.notdef', # C+0x02 # U+0x0000 + '.notdef', # C+0x03 # U+0x0000 + '.notdef', # C+0x04 # U+0x0000 + '.notdef', # C+0x05 # U+0x0000 + '.notdef', # C+0x06 # U+0x0000 + '.notdef', # C+0x07 # U+0x0000 + '.notdef', # C+0x08 # U+0x0000 + '.notdef', # C+0x09 # U+0x0000 + '.notdef', # C+0x0A # U+0x0000 + '.notdef', # C+0x0B # U+0x0000 + '.notdef', # C+0x0C # U+0x0000 + '.notdef', # C+0x0D # U+0x0000 + '.notdef', # C+0x0E # U+0x0000 + '.notdef', # C+0x0F # U+0x0000 + '.notdef', # C+0x10 # U+0x0000 + '.notdef', # C+0x11 # U+0x0000 + '.notdef', # C+0x12 # U+0x0000 + '.notdef', # C+0x13 # U+0x0000 + '.notdef', # C+0x14 # U+0x0000 + '.notdef', # C+0x15 # U+0x0000 + '.notdef', # C+0x16 # U+0x0000 + '.notdef', # C+0x17 # U+0x0000 + '.notdef', # C+0x18 # U+0x0000 + '.notdef', # C+0x19 # U+0x0000 + '.notdef', # C+0x1A # U+0x0000 + '.notdef', # C+0x1B # U+0x0000 + '.notdef', # C+0x1C # U+0x0000 + '.notdef', # C+0x1D # U+0x0000 + '.notdef', # C+0x1E # U+0x0000 + '.notdef', # C+0x1F # U+0x0000 + 'space', # C+0x20 # U+0xF020 + 'exclam', # C+0x21 # U+0xF021 + 'universal', # C+0x22 # U+0xF022 + 'numbersign', # C+0x23 # U+0xF023 + 'existential', # C+0x24 # U+0xF024 + 'percent', # C+0x25 # U+0xF025 + 'ampersand', # C+0x26 # U+0xF026 + 'suchthat', # C+0x27 # U+0xF027 + 'parenleft', # C+0x28 # U+0xF028 + 'parenright', # C+0x29 # U+0xF029 + 'asteriskmath', # C+0x2A # U+0xF02A + 'plus', # C+0x2B # U+0xF02B + 'comma', # C+0x2C # U+0xF02C + 'minus', # C+0x2D # U+0xF02D + 'period', # C+0x2E # U+0xF02E + 'slash', # C+0x2F # U+0xF02F + 'zero', # C+0x30 # U+0xF030 + 'one', # C+0x31 # U+0xF031 + 'two', # C+0x32 # U+0xF032 + 'three', # C+0x33 # U+0xF033 + 'four', # C+0x34 # U+0xF034 + 'five', # C+0x35 # U+0xF035 + 'six', # C+0x36 # U+0xF036 + 'seven', # C+0x37 # U+0xF037 + 'eight', # C+0x38 # U+0xF038 + 'nine', # C+0x39 # U+0xF039 + 'colon', # C+0x3A # U+0xF03A + 'semicolon', # C+0x3B # U+0xF03B + 'less', # C+0x3C # U+0xF03C + 'equal', # C+0x3D # U+0xF03D + 'greater', # C+0x3E # U+0xF03E + 'question', # C+0x3F # U+0xF03F + 'congruent', # C+0x40 # U+0xF040 + 'Alpha', # C+0x41 # U+0xF041 + 'Beta', # C+0x42 # U+0xF042 + 'Chi', # C+0x43 # U+0xF043 + 'Delta', # C+0x44 # U+0xF044 + 'Epsilon', # C+0x45 # U+0xF045 + 'Phi', # C+0x46 # U+0xF046 + 'Gamma', # C+0x47 # U+0xF047 + 'Eta', # C+0x48 # U+0xF048 + 'Iota', # C+0x49 # U+0xF049 + 'theta1', # C+0x4A # U+0xF04A + 'Kappa', # C+0x4B # U+0xF04B + 'Lambda', # C+0x4C # U+0xF04C + 'Mu', # C+0x4D # U+0xF04D + 'Nu', # C+0x4E # U+0xF04E + 'Omicron', # C+0x4F # U+0xF04F + 'Pi', # C+0x50 # U+0xF050 + 'Theta', # C+0x51 # U+0xF051 + 'Rho', # C+0x52 # U+0xF052 + 'Sigma', # C+0x53 # U+0xF053 + 'Tau', # C+0x54 # U+0xF054 + 'Upsilon', # C+0x55 # U+0xF055 + 'sigma1', # C+0x56 # U+0xF056 + 'Omega', # C+0x57 # U+0xF057 + 'Xi', # C+0x58 # U+0xF058 + 'Psi', # C+0x59 # U+0xF059 + 'Zeta', # C+0x5A # U+0xF05A + 'bracketleft', # C+0x5B # U+0xF05B + 'therefore', # C+0x5C # U+0xF05C + 'bracketright', # C+0x5D # U+0xF05D + 'perpendicular', # C+0x5E # U+0xF05E + 'underscore', # C+0x5F # U+0xF05F + 'radicalex', # C+0x60 # U+0xF060 + 'alpha', # C+0x61 # U+0xF061 + 'beta', # C+0x62 # U+0xF062 + 'chi', # C+0x63 # U+0xF063 + 'delta', # C+0x64 # U+0xF064 + 'epsilon', # C+0x65 # U+0xF065 + 'phi', # C+0x66 # U+0xF066 + 'gamma', # C+0x67 # U+0xF067 + 'eta', # C+0x68 # U+0xF068 + 'iota', # C+0x69 # U+0xF069 + 'phi1', # C+0x6A # U+0xF06A + 'kappa', # C+0x6B # U+0xF06B + 'lambda', # C+0x6C # U+0xF06C + 'mu', # C+0x6D # U+0xF06D + 'nu', # C+0x6E # U+0xF06E + 'omicron', # C+0x6F # U+0xF06F + 'pi', # C+0x70 # U+0xF070 + 'theta', # C+0x71 # U+0xF071 + 'rho', # C+0x72 # U+0xF072 + 'sigma', # C+0x73 # U+0xF073 + 'tau', # C+0x74 # U+0xF074 + 'upsilon', # C+0x75 # U+0xF075 + 'omega1', # C+0x76 # U+0xF076 + 'omega', # C+0x77 # U+0xF077 + 'xi', # C+0x78 # U+0xF078 + 'psi', # C+0x79 # U+0xF079 + 'zeta', # C+0x7A # U+0xF07A + 'braceleft', # C+0x7B # U+0xF07B + 'bar', # C+0x7C # U+0xF07C + 'braceright', # C+0x7D # U+0xF07D + 'similar', # C+0x7E # U+0xF07E + '.notdef', # C+0x7F # U+0x0000 + '.notdef', # C+0x80 # U+0x0000 + '.notdef', # C+0x81 # U+0x0000 + '.notdef', # C+0x82 # U+0x0000 + '.notdef', # C+0x83 # U+0x0000 + '.notdef', # C+0x84 # U+0x0000 + '.notdef', # C+0x85 # U+0x0000 + '.notdef', # C+0x86 # U+0x0000 + '.notdef', # C+0x87 # U+0x0000 + '.notdef', # C+0x88 # U+0x0000 + '.notdef', # C+0x89 # U+0x0000 + '.notdef', # C+0x8A # U+0x0000 + '.notdef', # C+0x8B # U+0x0000 + '.notdef', # C+0x8C # U+0x0000 + '.notdef', # C+0x8D # U+0x0000 + '.notdef', # C+0x8E # U+0x0000 + '.notdef', # C+0x8F # U+0x0000 + '.notdef', # C+0x90 # U+0x0000 + '.notdef', # C+0x91 # U+0x0000 + '.notdef', # C+0x92 # U+0x0000 + '.notdef', # C+0x93 # U+0x0000 + '.notdef', # C+0x94 # U+0x0000 + '.notdef', # C+0x95 # U+0x0000 + '.notdef', # C+0x96 # U+0x0000 + '.notdef', # C+0x97 # U+0x0000 + '.notdef', # C+0x98 # U+0x0000 + '.notdef', # C+0x99 # U+0x0000 + '.notdef', # C+0x9A # U+0x0000 + '.notdef', # C+0x9B # U+0x0000 + '.notdef', # C+0x9C # U+0x0000 + '.notdef', # C+0x9D # U+0x0000 + '.notdef', # C+0x9E # U+0x0000 + '.notdef', # C+0x9F # U+0x0000 + 'Euro', # C+0xA0 # U+0xF0A0 + 'Upsilon1', # C+0xA1 # U+0xF0A1 + 'minute', # C+0xA2 # U+0xF0A2 + 'lessequal', # C+0xA3 # U+0xF0A3 + 'fraction', # C+0xA4 # U+0xF0A4 + 'infinity', # C+0xA5 # U+0xF0A5 + 'florin', # C+0xA6 # U+0xF0A6 + 'club', # C+0xA7 # U+0xF0A7 + 'diamond', # C+0xA8 # U+0xF0A8 + 'heart', # C+0xA9 # U+0xF0A9 + 'spade', # C+0xAA # U+0xF0AA + 'arrowboth', # C+0xAB # U+0xF0AB + 'arrowleft', # C+0xAC # U+0xF0AC + 'arrowup', # C+0xAD # U+0xF0AD + 'arrowright', # C+0xAE # U+0xF0AE + 'arrowdown', # C+0xAF # U+0xF0AF + 'degree', # C+0xB0 # U+0xF0B0 + 'plusminus', # C+0xB1 # U+0xF0B1 + 'second', # C+0xB2 # U+0xF0B2 + 'greaterequal', # C+0xB3 # U+0xF0B3 + 'multiply', # C+0xB4 # U+0xF0B4 + 'proportional', # C+0xB5 # U+0xF0B5 + 'partialdiff', # C+0xB6 # U+0xF0B6 + 'bullet', # C+0xB7 # U+0xF0B7 + 'divide', # C+0xB8 # U+0xF0B8 + 'notequal', # C+0xB9 # U+0xF0B9 + 'equivalence', # C+0xBA # U+0xF0BA + 'approxequal', # C+0xBB # U+0xF0BB + 'ellipsis', # C+0xBC # U+0xF0BC + 'arrowvertex', # C+0xBD # U+0xF0BD + 'arrowhorizex', # C+0xBE # U+0xF0BE + 'carriagereturn', # C+0xBF # U+0xF0BF + 'aleph', # C+0xC0 # U+0xF0C0 + 'Ifraktur', # C+0xC1 # U+0xF0C1 + 'Rfraktur', # C+0xC2 # U+0xF0C2 + 'weierstrass', # C+0xC3 # U+0xF0C3 + 'circlemultiply', # C+0xC4 # U+0xF0C4 + 'circleplus', # C+0xC5 # U+0xF0C5 + 'emptyset', # C+0xC6 # U+0xF0C6 + 'intersection', # C+0xC7 # U+0xF0C7 + 'union', # C+0xC8 # U+0xF0C8 + 'propersuperset', # C+0xC9 # U+0xF0C9 + 'reflexsuperset', # C+0xCA # U+0xF0CA + 'notsubset', # C+0xCB # U+0xF0CB + 'propersubset', # C+0xCC # U+0xF0CC + 'reflexsubset', # C+0xCD # U+0xF0CD + 'element', # C+0xCE # U+0xF0CE + 'notelement', # C+0xCF # U+0xF0CF + 'angle', # C+0xD0 # U+0xF0D0 + 'gradient', # C+0xD1 # U+0xF0D1 + 'registerserif', # C+0xD2 # U+0xF0D2 + 'copyrightserif', # C+0xD3 # U+0xF0D3 + 'trademarkserif', # C+0xD4 # U+0xF0D4 + 'product', # C+0xD5 # U+0xF0D5 + 'radical', # C+0xD6 # U+0xF0D6 + 'dotmath', # C+0xD7 # U+0xF0D7 + 'logicalnot', # C+0xD8 # U+0xF0D8 + 'logicaland', # C+0xD9 # U+0xF0D9 + 'logicalor', # C+0xDA # U+0xF0DA + 'arrowdblboth', # C+0xDB # U+0xF0DB + 'arrowdblleft', # C+0xDC # U+0xF0DC + 'arrowdblup', # C+0xDD # U+0xF0DD + 'arrowdblright', # C+0xDE # U+0xF0DE + 'arrowdbldown', # C+0xDF # U+0xF0DF + 'lozenge', # C+0xE0 # U+0xF0E0 + 'angleleft', # C+0xE1 # U+0xF0E1 + 'registersans', # C+0xE2 # U+0xF0E2 + 'copyrightsans', # C+0xE3 # U+0xF0E3 + 'trademarksans', # C+0xE4 # U+0xF0E4 + 'summation', # C+0xE5 # U+0xF0E5 + 'parenlefttp', # C+0xE6 # U+0xF0E6 + 'parenleftex', # C+0xE7 # U+0xF0E7 + 'parenleftbt', # C+0xE8 # U+0xF0E8 + 'bracketlefttp', # C+0xE9 # U+0xF0E9 + 'bracketleftex', # C+0xEA # U+0xF0EA + 'bracketleftbt', # C+0xEB # U+0xF0EB + 'bracelefttp', # C+0xEC # U+0xF0EC + 'braceleftmid', # C+0xED # U+0xF0ED + 'braceleftbt', # C+0xEE # U+0xF0EE + 'braceex', # C+0xEF # U+0xF0EF + '.notdef', # C+0xF0 # U+0x0000 + 'angleright', # C+0xF1 # U+0xF0F1 + 'integral', # C+0xF2 # U+0xF0F2 + 'integraltp', # C+0xF3 # U+0xF0F3 + 'integralex', # C+0xF4 # U+0xF0F4 + 'integralbt', # C+0xF5 # U+0xF0F5 + 'parenrighttp', # C+0xF6 # U+0xF0F6 + 'parenrightex', # C+0xF7 # U+0xF0F7 + 'parenrightbt', # C+0xF8 # U+0xF0F8 + 'bracketrighttp', # C+0xF9 # U+0xF0F9 + 'bracketrightex', # C+0xFA # U+0xF0FA + 'bracketrightbt', # C+0xFB # U+0xF0FB + 'bracerighttp', # C+0xFC # U+0xF0FC + 'bracerightmid', # C+0xFD # U+0xF0FD + 'bracerightbt', # C+0xFE # U+0xF0FE + 'apple', # C+0xFF # U+0xF0FF + ], # DEF. ENCODING GLYPH TABLE + 'fontbbox' => [ -180, -293, 1090, 1010 ], + 'wx' => { # HORIZ. WIDTH TABLE + 'space' => '250', # C+0x20 # U+0xF020 + 'exclam' => '333', # C+0x21 # U+0xF021 + 'universal' => '713', # C+0x22 # U+0xF022 + 'numbersign' => '500', # C+0x23 # U+0xF023 + 'existential' => '549', # C+0x24 # U+0xF024 + 'percent' => '833', # C+0x25 # U+0xF025 + 'ampersand' => '778', # C+0x26 # U+0xF026 + 'suchthat' => '439', # C+0x27 # U+0xF027 + 'parenleft' => '333', # C+0x28 # U+0xF028 + 'parenright' => '333', # C+0x29 # U+0xF029 + 'asteriskmath' => '500', # C+0x2A # U+0xF02A + 'plus' => '549', # C+0x2B # U+0xF02B + 'comma' => '250', # C+0x2C # U+0xF02C + 'minus' => '549', # C+0x2D # U+0xF02D + 'period' => '250', # C+0x2E # U+0xF02E + 'slash' => '278', # C+0x2F # U+0xF02F + 'zero' => '500', # C+0x30 # U+0xF030 + 'one' => '500', # C+0x31 # U+0xF031 + 'two' => '500', # C+0x32 # U+0xF032 + 'three' => '500', # C+0x33 # U+0xF033 + 'four' => '500', # C+0x34 # U+0xF034 + 'five' => '500', # C+0x35 # U+0xF035 + 'six' => '500', # C+0x36 # U+0xF036 + 'seven' => '500', # C+0x37 # U+0xF037 + 'eight' => '500', # C+0x38 # U+0xF038 + 'nine' => '500', # C+0x39 # U+0xF039 + 'colon' => '278', # C+0x3A # U+0xF03A + 'semicolon' => '278', # C+0x3B # U+0xF03B + 'less' => '549', # C+0x3C # U+0xF03C + 'equal' => '549', # C+0x3D # U+0xF03D + 'greater' => '549', # C+0x3E # U+0xF03E + 'question' => '444', # C+0x3F # U+0xF03F + 'congruent' => '549', # C+0x40 # U+0xF040 + 'Alpha' => '722', # C+0x41 # U+0xF041 + 'Beta' => '667', # C+0x42 # U+0xF042 + 'Chi' => '722', # C+0x43 # U+0xF043 + 'Delta' => '612', # C+0x44 # U+0xF044 + 'Epsilon' => '611', # C+0x45 # U+0xF045 + 'Phi' => '763', # C+0x46 # U+0xF046 + 'Gamma' => '603', # C+0x47 # U+0xF047 + 'Eta' => '722', # C+0x48 # U+0xF048 + 'Iota' => '333', # C+0x49 # U+0xF049 + 'theta1' => '631', # C+0x4A # U+0xF04A + 'Kappa' => '722', # C+0x4B # U+0xF04B + 'Lambda' => '686', # C+0x4C # U+0xF04C + 'Mu' => '889', # C+0x4D # U+0xF04D + 'Nu' => '722', # C+0x4E # U+0xF04E + 'Omicron' => '722', # C+0x4F # U+0xF04F + 'Pi' => '768', # C+0x50 # U+0xF050 + 'Theta' => '741', # C+0x51 # U+0xF051 + 'Rho' => '556', # C+0x52 # U+0xF052 + 'Sigma' => '592', # C+0x53 # U+0xF053 + 'Tau' => '611', # C+0x54 # U+0xF054 + 'Upsilon' => '690', # C+0x55 # U+0xF055 + 'sigma1' => '439', # C+0x56 # U+0xF056 + 'Omega' => '768', # C+0x57 # U+0xF057 + 'Xi' => '645', # C+0x58 # U+0xF058 + 'Psi' => '795', # C+0x59 # U+0xF059 + 'Zeta' => '611', # C+0x5A # U+0xF05A + 'bracketleft' => '333', # C+0x5B # U+0xF05B + 'therefore' => '863', # C+0x5C # U+0xF05C + 'bracketright' => '333', # C+0x5D # U+0xF05D + 'perpendicular' => '658', # C+0x5E # U+0xF05E + 'underscore' => '500', # C+0x5F # U+0xF05F + 'radicalex' => '500', # C+0x60 # U+0xF060 + 'alpha' => '631', # C+0x61 # U+0xF061 + 'beta' => '549', # C+0x62 # U+0xF062 + 'chi' => '549', # C+0x63 # U+0xF063 + 'delta' => '494', # C+0x64 # U+0xF064 + 'epsilon' => '439', # C+0x65 # U+0xF065 + 'phi' => '521', # C+0x66 # U+0xF066 + 'gamma' => '411', # C+0x67 # U+0xF067 + 'eta' => '603', # C+0x68 # U+0xF068 + 'iota' => '329', # C+0x69 # U+0xF069 + 'phi1' => '603', # C+0x6A # U+0xF06A + 'kappa' => '549', # C+0x6B # U+0xF06B + 'lambda' => '549', # C+0x6C # U+0xF06C + 'mu' => '576', # C+0x6D # U+0xF06D + 'nu' => '521', # C+0x6E # U+0xF06E + 'omicron' => '549', # C+0x6F # U+0xF06F + 'pi' => '549', # C+0x70 # U+0xF070 + 'theta' => '521', # C+0x71 # U+0xF071 + 'rho' => '549', # C+0x72 # U+0xF072 + 'sigma' => '603', # C+0x73 # U+0xF073 + 'tau' => '439', # C+0x74 # U+0xF074 + 'upsilon' => '576', # C+0x75 # U+0xF075 + 'omega1' => '713', # C+0x76 # U+0xF076 + 'omega' => '686', # C+0x77 # U+0xF077 + 'xi' => '493', # C+0x78 # U+0xF078 + 'psi' => '686', # C+0x79 # U+0xF079 + 'zeta' => '494', # C+0x7A # U+0xF07A + 'braceleft' => '480', # C+0x7B # U+0xF07B + 'bar' => '200', # C+0x7C # U+0xF07C + 'braceright' => '480', # C+0x7D # U+0xF07D + 'similar' => '549', # C+0x7E # U+0xF07E + 'Euro' => '750', # C+0xA0 # U+0xF0A0 + 'Upsilon1' => '620', # C+0xA1 # U+0xF0A1 + 'minute' => '247', # C+0xA2 # U+0xF0A2 + 'lessequal' => '549', # C+0xA3 # U+0xF0A3 + 'fraction' => '167', # C+0xA4 # U+0xF0A4 + 'infinity' => '713', # C+0xA5 # U+0xF0A5 + 'florin' => '500', # C+0xA6 # U+0xF0A6 + 'club' => '753', # C+0xA7 # U+0xF0A7 + 'diamond' => '753', # C+0xA8 # U+0xF0A8 + 'heart' => '753', # C+0xA9 # U+0xF0A9 + 'spade' => '753', # C+0xAA # U+0xF0AA + 'arrowboth' => '1042', # C+0xAB # U+0xF0AB + 'arrowleft' => '987', # C+0xAC # U+0xF0AC + 'arrowup' => '603', # C+0xAD # U+0xF0AD + 'arrowright' => '987', # C+0xAE # U+0xF0AE + 'arrowdown' => '603', # C+0xAF # U+0xF0AF + 'degree' => '400', # C+0xB0 # U+0xF0B0 + 'plusminus' => '549', # C+0xB1 # U+0xF0B1 + 'second' => '411', # C+0xB2 # U+0xF0B2 + 'greaterequal' => '549', # C+0xB3 # U+0xF0B3 + 'multiply' => '549', # C+0xB4 # U+0xF0B4 + 'proportional' => '713', # C+0xB5 # U+0xF0B5 + 'partialdiff' => '494', # C+0xB6 # U+0xF0B6 + 'bullet' => '460', # C+0xB7 # U+0xF0B7 + 'divide' => '549', # C+0xB8 # U+0xF0B8 + 'notequal' => '549', # C+0xB9 # U+0xF0B9 + 'equivalence' => '549', # C+0xBA # U+0xF0BA + 'approxequal' => '549', # C+0xBB # U+0xF0BB + 'ellipsis' => '1000', # C+0xBC # U+0xF0BC + 'arrowvertex' => '603', # C+0xBD # U+0xF0BD + 'arrowhorizex' => '1000', # C+0xBE # U+0xF0BE + 'carriagereturn' => '658', # C+0xBF # U+0xF0BF + 'aleph' => '823', # C+0xC0 # U+0xF0C0 + 'Ifraktur' => '686', # C+0xC1 # U+0xF0C1 + 'Rfraktur' => '795', # C+0xC2 # U+0xF0C2 + 'weierstrass' => '987', # C+0xC3 # U+0xF0C3 + 'circlemultiply' => '768', # C+0xC4 # U+0xF0C4 + 'circleplus' => '768', # C+0xC5 # U+0xF0C5 + 'emptyset' => '823', # C+0xC6 # U+0xF0C6 + 'intersection' => '768', # C+0xC7 # U+0xF0C7 + 'union' => '768', # C+0xC8 # U+0xF0C8 + 'propersuperset' => '713', # C+0xC9 # U+0xF0C9 + 'reflexsuperset' => '713', # C+0xCA # U+0xF0CA + 'notsubset' => '713', # C+0xCB # U+0xF0CB + 'propersubset' => '713', # C+0xCC # U+0xF0CC + 'reflexsubset' => '713', # C+0xCD # U+0xF0CD + 'element' => '713', # C+0xCE # U+0xF0CE + 'notelement' => '713', # C+0xCF # U+0xF0CF + 'angle' => '768', # C+0xD0 # U+0xF0D0 + 'gradient' => '713', # C+0xD1 # U+0xF0D1 + 'registerserif' => '790', # C+0xD2 # U+0xF0D2 + 'copyrightserif' => '790', # C+0xD3 # U+0xF0D3 + 'trademarkserif' => '890', # C+0xD4 # U+0xF0D4 + 'product' => '823', # C+0xD5 # U+0xF0D5 + 'radical' => '549', # C+0xD6 # U+0xF0D6 + 'dotmath' => '250', # C+0xD7 # U+0xF0D7 + 'logicalnot' => '713', # C+0xD8 # U+0xF0D8 + 'logicaland' => '603', # C+0xD9 # U+0xF0D9 + 'logicalor' => '603', # C+0xDA # U+0xF0DA + 'arrowdblboth' => '1042', # C+0xDB # U+0xF0DB + 'arrowdblleft' => '987', # C+0xDC # U+0xF0DC + 'arrowdblup' => '603', # C+0xDD # U+0xF0DD + 'arrowdblright' => '987', # C+0xDE # U+0xF0DE + 'arrowdbldown' => '603', # C+0xDF # U+0xF0DF + 'lozenge' => '494', # C+0xE0 # U+0xF0E0 + 'angleleft' => '329', # C+0xE1 # U+0xF0E1 + 'registersans' => '790', # C+0xE2 # U+0xF0E2 + 'copyrightsans' => '790', # C+0xE3 # U+0xF0E3 + 'trademarksans' => '786', # C+0xE4 # U+0xF0E4 + 'summation' => '713', # C+0xE5 # U+0xF0E5 + 'parenlefttp' => '384', # C+0xE6 # U+0xF0E6 + 'parenleftex' => '384', # C+0xE7 # U+0xF0E7 + 'parenleftbt' => '384', # C+0xE8 # U+0xF0E8 + 'bracketlefttp' => '384', # C+0xE9 # U+0xF0E9 + 'bracketleftex' => '384', # C+0xEA # U+0xF0EA + 'bracketleftbt' => '384', # C+0xEB # U+0xF0EB + 'bracelefttp' => '494', # C+0xEC # U+0xF0EC + 'braceleftmid' => '494', # C+0xED # U+0xF0ED + 'braceleftbt' => '494', # C+0xEE # U+0xF0EE + 'braceex' => '494', # C+0xEF # U+0xF0EF + 'angleright' => '329', # C+0xF1 # U+0xF0F1 + 'integral' => '274', # C+0xF2 # U+0xF0F2 + 'integraltp' => '686', # C+0xF3 # U+0xF0F3 + 'integralex' => '686', # C+0xF4 # U+0xF0F4 + 'integralbt' => '686', # C+0xF5 # U+0xF0F5 + 'parenrighttp' => '384', # C+0xF6 # U+0xF0F6 + 'parenrightex' => '384', # C+0xF7 # U+0xF0F7 + 'parenrightbt' => '384', # C+0xF8 # U+0xF0F8 + 'bracketrighttp' => '384', # C+0xF9 # U+0xF0F9 + 'bracketrightex' => '384', # C+0xFA # U+0xF0FA + 'bracketrightbt' => '384', # C+0xFB # U+0xF0FB + 'bracerighttp' => '494', # C+0xFC # U+0xF0FC + 'bracerightmid' => '494', # C+0xFD # U+0xF0FD + 'bracerightbt' => '494', # C+0xFE # U+0xF0FE + 'apple' => '790', # C+0xFF # U+0xF0FF + }, # HORIZ. WIDTH TABLE +} }; + +1; diff --git a/lib/PDF/API2/Resource/Font/CoreFont/timesbold.pm b/lib/PDF/API2/Resource/Font/CoreFont/timesbold.pm new file mode 100644 index 0000000..f41c72e --- /dev/null +++ b/lib/PDF/API2/Resource/Font/CoreFont/timesbold.pm @@ -0,0 +1,520 @@ +#line 1 "PDF/API2/Resource/Font/CoreFont/timesbold.pm" +#line 1 "PDF/API2/Resource/Font/CoreFont/timesbold.pm" +package PDF::API2::Resource::Font::CoreFont::timesbold; + +use strict; +use warnings; + +our $VERSION = '2.033'; # VERSION + +sub data { return { + 'fontname' => 'Times-Bold', + 'type' => 'Type1', + 'apiname' => 'TiBo', + 'ascender' => '683', + 'capheight' => '676', + 'descender' => '-217', + 'iscore' => '1', + 'isfixedpitch' => '0', + 'italicangle' => '0', + 'missingwidth' => '250', + 'stdhw' => '44', + 'stdvw' => '139', + 'underlineposition' => '-100', + 'underlinethickness' => '50', + 'xheight' => '461', + 'firstchar' => '32', + 'lastchar' => '255', + 'char' => [ # DEF. ENCODING GLYPH TABLE + '.notdef', # C+0x00 # U+0x0000 + '.notdef', # C+0x01 # U+0x0000 + '.notdef', # C+0x02 # U+0x0000 + '.notdef', # C+0x03 # U+0x0000 + '.notdef', # C+0x04 # U+0x0000 + '.notdef', # C+0x05 # U+0x0000 + '.notdef', # C+0x06 # U+0x0000 + '.notdef', # C+0x07 # U+0x0000 + '.notdef', # C+0x08 # U+0x0000 + '.notdef', # C+0x09 # U+0x0000 + '.notdef', # C+0x0A # U+0x0000 + '.notdef', # C+0x0B # U+0x0000 + '.notdef', # C+0x0C # U+0x0000 + '.notdef', # C+0x0D # U+0x0000 + '.notdef', # C+0x0E # U+0x0000 + '.notdef', # C+0x0F # U+0x0000 + '.notdef', # C+0x10 # U+0x0000 + '.notdef', # C+0x11 # U+0x0000 + '.notdef', # C+0x12 # U+0x0000 + '.notdef', # C+0x13 # U+0x0000 + '.notdef', # C+0x14 # U+0x0000 + '.notdef', # C+0x15 # U+0x0000 + '.notdef', # C+0x16 # U+0x0000 + '.notdef', # C+0x17 # U+0x0000 + '.notdef', # C+0x18 # U+0x0000 + '.notdef', # C+0x19 # U+0x0000 + '.notdef', # C+0x1A # U+0x0000 + '.notdef', # C+0x1B # U+0x0000 + '.notdef', # C+0x1C # U+0x0000 + '.notdef', # C+0x1D # U+0x0000 + '.notdef', # C+0x1E # U+0x0000 + '.notdef', # C+0x1F # U+0x0000 + 'space', # C+0x20 # U+0x0020 + 'exclam', # C+0x21 # U+0x0021 + 'quotedbl', # C+0x22 # U+0x0022 + 'numbersign', # C+0x23 # U+0x0023 + 'dollar', # C+0x24 # U+0x0024 + 'percent', # C+0x25 # U+0x0025 + 'ampersand', # C+0x26 # U+0x0026 + 'quotesingle', # C+0x27 # U+0x0027 + 'parenleft', # C+0x28 # U+0x0028 + 'parenright', # C+0x29 # U+0x0029 + 'asterisk', # C+0x2A # U+0x002A + 'plus', # C+0x2B # U+0x002B + 'comma', # C+0x2C # U+0x002C + 'hyphen', # C+0x2D # U+0x002D + 'period', # C+0x2E # U+0x002E + 'slash', # C+0x2F # U+0x002F + 'zero', # C+0x30 # U+0x0030 + 'one', # C+0x31 # U+0x0031 + 'two', # C+0x32 # U+0x0032 + 'three', # C+0x33 # U+0x0033 + 'four', # C+0x34 # U+0x0034 + 'five', # C+0x35 # U+0x0035 + 'six', # C+0x36 # U+0x0036 + 'seven', # C+0x37 # U+0x0037 + 'eight', # C+0x38 # U+0x0038 + 'nine', # C+0x39 # U+0x0039 + 'colon', # C+0x3A # U+0x003A + 'semicolon', # C+0x3B # U+0x003B + 'less', # C+0x3C # U+0x003C + 'equal', # C+0x3D # U+0x003D + 'greater', # C+0x3E # U+0x003E + 'question', # C+0x3F # U+0x003F + 'at', # C+0x40 # U+0x0040 + 'A', # C+0x41 # U+0x0041 + 'B', # C+0x42 # U+0x0042 + 'C', # C+0x43 # U+0x0043 + 'D', # C+0x44 # U+0x0044 + 'E', # C+0x45 # U+0x0045 + 'F', # C+0x46 # U+0x0046 + 'G', # C+0x47 # U+0x0047 + 'H', # C+0x48 # U+0x0048 + 'I', # C+0x49 # U+0x0049 + 'J', # C+0x4A # U+0x004A + 'K', # C+0x4B # U+0x004B + 'L', # C+0x4C # U+0x004C + 'M', # C+0x4D # U+0x004D + 'N', # C+0x4E # U+0x004E + 'O', # C+0x4F # U+0x004F + 'P', # C+0x50 # U+0x0050 + 'Q', # C+0x51 # U+0x0051 + 'R', # C+0x52 # U+0x0052 + 'S', # C+0x53 # U+0x0053 + 'T', # C+0x54 # U+0x0054 + 'U', # C+0x55 # U+0x0055 + 'V', # C+0x56 # U+0x0056 + 'W', # C+0x57 # U+0x0057 + 'X', # C+0x58 # U+0x0058 + 'Y', # C+0x59 # U+0x0059 + 'Z', # C+0x5A # U+0x005A + 'bracketleft', # C+0x5B # U+0x005B + 'backslash', # C+0x5C # U+0x005C + 'bracketright', # C+0x5D # U+0x005D + 'asciicircum', # C+0x5E # U+0x005E + 'underscore', # C+0x5F # U+0x005F + 'grave', # C+0x60 # U+0x0060 + 'a', # C+0x61 # U+0x0061 + 'b', # C+0x62 # U+0x0062 + 'c', # C+0x63 # U+0x0063 + 'd', # C+0x64 # U+0x0064 + 'e', # C+0x65 # U+0x0065 + 'f', # C+0x66 # U+0x0066 + 'g', # C+0x67 # U+0x0067 + 'h', # C+0x68 # U+0x0068 + 'i', # C+0x69 # U+0x0069 + 'j', # C+0x6A # U+0x006A + 'k', # C+0x6B # U+0x006B + 'l', # C+0x6C # U+0x006C + 'm', # C+0x6D # U+0x006D + 'n', # C+0x6E # U+0x006E + 'o', # C+0x6F # U+0x006F + 'p', # C+0x70 # U+0x0070 + 'q', # C+0x71 # U+0x0071 + 'r', # C+0x72 # U+0x0072 + 's', # C+0x73 # U+0x0073 + 't', # C+0x74 # U+0x0074 + 'u', # C+0x75 # U+0x0075 + 'v', # C+0x76 # U+0x0076 + 'w', # C+0x77 # U+0x0077 + 'x', # C+0x78 # U+0x0078 + 'y', # C+0x79 # U+0x0079 + 'z', # C+0x7A # U+0x007A + 'braceleft', # C+0x7B # U+0x007B + 'bar', # C+0x7C # U+0x007C + 'braceright', # C+0x7D # U+0x007D + 'asciitilde', # C+0x7E # U+0x007E + 'bullet', # C+0x7F # U+0x2022 + 'Euro', # C+0x80 # U+0x20AC + 'bullet', # C+0x81 # U+0x2022 + 'quotesinglbase', # C+0x82 # U+0x201A + 'florin', # C+0x83 # U+0x0192 + 'quotedblbase', # C+0x84 # U+0x201E + 'ellipsis', # C+0x85 # U+0x2026 + 'dagger', # C+0x86 # U+0x2020 + 'daggerdbl', # C+0x87 # U+0x2021 + 'circumflex', # C+0x88 # U+0x02C6 + 'perthousand', # C+0x89 # U+0x2030 + 'Scaron', # C+0x8A # U+0x0160 + 'guilsinglleft', # C+0x8B # U+0x2039 + 'OE', # C+0x8C # U+0x0152 + 'bullet', # C+0x8D # U+0x2022 + 'Zcaron', # C+0x8E # U+0x017D + 'bullet', # C+0x8F # U+0x2022 + 'bullet', # C+0x90 # U+0x2022 + 'quoteleft', # C+0x91 # U+0x2018 + 'quoteright', # C+0x92 # U+0x2019 + 'quotedblleft', # C+0x93 # U+0x201C + 'quotedblright', # C+0x94 # U+0x201D + 'bullet', # C+0x95 # U+0x2022 + 'endash', # C+0x96 # U+0x2013 + 'emdash', # C+0x97 # U+0x2014 + 'tilde', # C+0x98 # U+0x02DC + 'trademark', # C+0x99 # U+0x2122 + 'scaron', # C+0x9A # U+0x0161 + 'guilsinglright', # C+0x9B # U+0x203A + 'oe', # C+0x9C # U+0x0153 + 'bullet', # C+0x9D # U+0x2022 + 'zcaron', # C+0x9E # U+0x017E + 'Ydieresis', # C+0x9F # U+0x0178 + 'space', # C+0xA0 # U+0x0020 + 'exclamdown', # C+0xA1 # U+0x00A1 + 'cent', # C+0xA2 # U+0x00A2 + 'sterling', # C+0xA3 # U+0x00A3 + 'currency', # C+0xA4 # U+0x00A4 + 'yen', # C+0xA5 # U+0x00A5 + 'brokenbar', # C+0xA6 # U+0x00A6 + 'section', # C+0xA7 # U+0x00A7 + 'dieresis', # C+0xA8 # U+0x00A8 + 'copyright', # C+0xA9 # U+0x00A9 + 'ordfeminine', # C+0xAA # U+0x00AA + 'guillemotleft', # C+0xAB # U+0x00AB + 'logicalnot', # C+0xAC # U+0x00AC + 'hyphen', # C+0xAD # U+0x002D + 'registered', # C+0xAE # U+0x00AE + 'macron', # C+0xAF # U+0x00AF + 'degree', # C+0xB0 # U+0x00B0 + 'plusminus', # C+0xB1 # U+0x00B1 + 'twosuperior', # C+0xB2 # U+0x00B2 + 'threesuperior', # C+0xB3 # U+0x00B3 + 'acute', # C+0xB4 # U+0x00B4 + 'mu', # C+0xB5 # U+0x00B5 + 'paragraph', # C+0xB6 # U+0x00B6 + 'periodcentered', # C+0xB7 # U+0x00B7 + 'cedilla', # C+0xB8 # U+0x00B8 + 'onesuperior', # C+0xB9 # U+0x00B9 + 'ordmasculine', # C+0xBA # U+0x00BA + 'guillemotright', # C+0xBB # U+0x00BB + 'onequarter', # C+0xBC # U+0x00BC + 'onehalf', # C+0xBD # U+0x00BD + 'threequarters', # C+0xBE # U+0x00BE + 'questiondown', # C+0xBF # U+0x00BF + 'Agrave', # C+0xC0 # U+0x00C0 + 'Aacute', # C+0xC1 # U+0x00C1 + 'Acircumflex', # C+0xC2 # U+0x00C2 + 'Atilde', # C+0xC3 # U+0x00C3 + 'Adieresis', # C+0xC4 # U+0x00C4 + 'Aring', # C+0xC5 # U+0x00C5 + 'AE', # C+0xC6 # U+0x00C6 + 'Ccedilla', # C+0xC7 # U+0x00C7 + 'Egrave', # C+0xC8 # U+0x00C8 + 'Eacute', # C+0xC9 # U+0x00C9 + 'Ecircumflex', # C+0xCA # U+0x00CA + 'Edieresis', # C+0xCB # U+0x00CB + 'Igrave', # C+0xCC # U+0x00CC + 'Iacute', # C+0xCD # U+0x00CD + 'Icircumflex', # C+0xCE # U+0x00CE + 'Idieresis', # C+0xCF # U+0x00CF + 'Eth', # C+0xD0 # U+0x00D0 + 'Ntilde', # C+0xD1 # U+0x00D1 + 'Ograve', # C+0xD2 # U+0x00D2 + 'Oacute', # C+0xD3 # U+0x00D3 + 'Ocircumflex', # C+0xD4 # U+0x00D4 + 'Otilde', # C+0xD5 # U+0x00D5 + 'Odieresis', # C+0xD6 # U+0x00D6 + 'multiply', # C+0xD7 # U+0x00D7 + 'Oslash', # C+0xD8 # U+0x00D8 + 'Ugrave', # C+0xD9 # U+0x00D9 + 'Uacute', # C+0xDA # U+0x00DA + 'Ucircumflex', # C+0xDB # U+0x00DB + 'Udieresis', # C+0xDC # U+0x00DC + 'Yacute', # C+0xDD # U+0x00DD + 'Thorn', # C+0xDE # U+0x00DE + 'germandbls', # C+0xDF # U+0x00DF + 'agrave', # C+0xE0 # U+0x00E0 + 'aacute', # C+0xE1 # U+0x00E1 + 'acircumflex', # C+0xE2 # U+0x00E2 + 'atilde', # C+0xE3 # U+0x00E3 + 'adieresis', # C+0xE4 # U+0x00E4 + 'aring', # C+0xE5 # U+0x00E5 + 'ae', # C+0xE6 # U+0x00E6 + 'ccedilla', # C+0xE7 # U+0x00E7 + 'egrave', # C+0xE8 # U+0x00E8 + 'eacute', # C+0xE9 # U+0x00E9 + 'ecircumflex', # C+0xEA # U+0x00EA + 'edieresis', # C+0xEB # U+0x00EB + 'igrave', # C+0xEC # U+0x00EC + 'iacute', # C+0xED # U+0x00ED + 'icircumflex', # C+0xEE # U+0x00EE + 'idieresis', # C+0xEF # U+0x00EF + 'eth', # C+0xF0 # U+0x00F0 + 'ntilde', # C+0xF1 # U+0x00F1 + 'ograve', # C+0xF2 # U+0x00F2 + 'oacute', # C+0xF3 # U+0x00F3 + 'ocircumflex', # C+0xF4 # U+0x00F4 + 'otilde', # C+0xF5 # U+0x00F5 + 'odieresis', # C+0xF6 # U+0x00F6 + 'divide', # C+0xF7 # U+0x00F7 + 'oslash', # C+0xF8 # U+0x00F8 + 'ugrave', # C+0xF9 # U+0x00F9 + 'uacute', # C+0xFA # U+0x00FA + 'ucircumflex', # C+0xFB # U+0x00FB + 'udieresis', # C+0xFC # U+0x00FC + 'yacute', # C+0xFD # U+0x00FD + 'thorn', # C+0xFE # U+0x00FE + 'ydieresis', # C+0xFF # U+0x00FF + ], # DEF. ENCODING GLYPH TABLE + 'fontbbox' => [ -168, -218, 1000, 935 ], + 'wx' => { # HORIZ. WIDTH TABLE + 'space' => '250', # C+0x20 # U+0x0020 + 'exclam' => '333', # C+0x21 # U+0x0021 + 'quotedbl' => '555', # C+0x22 # U+0x0022 + 'numbersign' => '500', # C+0x23 # U+0x0023 + 'dollar' => '500', # C+0x24 # U+0x0024 + 'percent' => '1000', # C+0x25 # U+0x0025 + 'ampersand' => '833', # C+0x26 # U+0x0026 + 'quotesingle' => '278', # C+0x27 # U+0x0027 + 'parenleft' => '333', # C+0x28 # U+0x0028 + 'parenright' => '333', # C+0x29 # U+0x0029 + 'asterisk' => '500', # C+0x2A # U+0x002A + 'plus' => '570', # C+0x2B # U+0x002B + 'comma' => '250', # C+0x2C # U+0x002C + 'hyphen' => '333', # C+0x2D # U+0x002D + 'period' => '250', # C+0x2E # U+0x002E + 'slash' => '278', # C+0x2F # U+0x002F + 'zero' => '500', # C+0x30 # U+0x0030 + 'one' => '500', # C+0x31 # U+0x0031 + 'two' => '500', # C+0x32 # U+0x0032 + 'three' => '500', # C+0x33 # U+0x0033 + 'four' => '500', # C+0x34 # U+0x0034 + 'five' => '500', # C+0x35 # U+0x0035 + 'six' => '500', # C+0x36 # U+0x0036 + 'seven' => '500', # C+0x37 # U+0x0037 + 'eight' => '500', # C+0x38 # U+0x0038 + 'nine' => '500', # C+0x39 # U+0x0039 + 'colon' => '333', # C+0x3A # U+0x003A + 'semicolon' => '333', # C+0x3B # U+0x003B + 'less' => '570', # C+0x3C # U+0x003C + 'equal' => '570', # C+0x3D # U+0x003D + 'greater' => '570', # C+0x3E # U+0x003E + 'question' => '500', # C+0x3F # U+0x003F + 'at' => '930', # C+0x40 # U+0x0040 + 'A' => '722', # C+0x41 # U+0x0041 + 'B' => '667', # C+0x42 # U+0x0042 + 'C' => '722', # C+0x43 # U+0x0043 + 'D' => '722', # C+0x44 # U+0x0044 + 'E' => '667', # C+0x45 # U+0x0045 + 'F' => '611', # C+0x46 # U+0x0046 + 'G' => '778', # C+0x47 # U+0x0047 + 'H' => '778', # C+0x48 # U+0x0048 + 'I' => '389', # C+0x49 # U+0x0049 + 'J' => '500', # C+0x4A # U+0x004A + 'K' => '778', # C+0x4B # U+0x004B + 'L' => '667', # C+0x4C # U+0x004C + 'M' => '944', # C+0x4D # U+0x004D + 'N' => '722', # C+0x4E # U+0x004E + 'O' => '778', # C+0x4F # U+0x004F + 'P' => '611', # C+0x50 # U+0x0050 + 'Q' => '778', # C+0x51 # U+0x0051 + 'R' => '722', # C+0x52 # U+0x0052 + 'S' => '556', # C+0x53 # U+0x0053 + 'T' => '667', # C+0x54 # U+0x0054 + 'U' => '722', # C+0x55 # U+0x0055 + 'V' => '722', # C+0x56 # U+0x0056 + 'W' => '1000', # C+0x57 # U+0x0057 + 'X' => '722', # C+0x58 # U+0x0058 + 'Y' => '722', # C+0x59 # U+0x0059 + 'Z' => '667', # C+0x5A # U+0x005A + 'bracketleft' => '333', # C+0x5B # U+0x005B + 'backslash' => '278', # C+0x5C # U+0x005C + 'bracketright' => '333', # C+0x5D # U+0x005D + 'asciicircum' => '581', # C+0x5E # U+0x005E + 'underscore' => '500', # C+0x5F # U+0x005F + 'grave' => '333', # C+0x60 # U+0x0060 + 'a' => '500', # C+0x61 # U+0x0061 + 'b' => '556', # C+0x62 # U+0x0062 + 'c' => '444', # C+0x63 # U+0x0063 + 'd' => '556', # C+0x64 # U+0x0064 + 'e' => '444', # C+0x65 # U+0x0065 + 'f' => '333', # C+0x66 # U+0x0066 + 'g' => '500', # C+0x67 # U+0x0067 + 'h' => '556', # C+0x68 # U+0x0068 + 'i' => '278', # C+0x69 # U+0x0069 + 'j' => '333', # C+0x6A # U+0x006A + 'k' => '556', # C+0x6B # U+0x006B + 'l' => '278', # C+0x6C # U+0x006C + 'm' => '833', # C+0x6D # U+0x006D + 'n' => '556', # C+0x6E # U+0x006E + 'o' => '500', # C+0x6F # U+0x006F + 'p' => '556', # C+0x70 # U+0x0070 + 'q' => '556', # C+0x71 # U+0x0071 + 'r' => '444', # C+0x72 # U+0x0072 + 's' => '389', # C+0x73 # U+0x0073 + 't' => '333', # C+0x74 # U+0x0074 + 'u' => '556', # C+0x75 # U+0x0075 + 'v' => '500', # C+0x76 # U+0x0076 + 'w' => '722', # C+0x77 # U+0x0077 + 'x' => '500', # C+0x78 # U+0x0078 + 'y' => '500', # C+0x79 # U+0x0079 + 'z' => '444', # C+0x7A # U+0x007A + 'braceleft' => '394', # C+0x7B # U+0x007B + 'bar' => '220', # C+0x7C # U+0x007C + 'braceright' => '394', # C+0x7D # U+0x007D + 'asciitilde' => '520', # C+0x7E # U+0x007E + 'bullet' => '350', # C+0x7F # U+0x2022 + 'Euro' => '500', # C+0x80 # U+0x20AC + 'quotesinglbase' => '333', # C+0x82 # U+0x201A + 'florin' => '500', # C+0x83 # U+0x0192 + 'quotedblbase' => '500', # C+0x84 # U+0x201E + 'ellipsis' => '1000', # C+0x85 # U+0x2026 + 'dagger' => '500', # C+0x86 # U+0x2020 + 'daggerdbl' => '500', # C+0x87 # U+0x2021 + 'circumflex' => '333', # C+0x88 # U+0x02C6 + 'perthousand' => '1000', # C+0x89 # U+0x2030 + 'Scaron' => '556', # C+0x8A # U+0x0160 + 'guilsinglleft' => '333', # C+0x8B # U+0x2039 + 'OE' => '1000', # C+0x8C # U+0x0152 + 'Zcaron' => '667', # C+0x8E # U+0x017D + 'quoteleft' => '333', # C+0x91 # U+0x2018 + 'quoteright' => '333', # C+0x92 # U+0x2019 + 'quotedblleft' => '500', # C+0x93 # U+0x201C + 'quotedblright' => '500', # C+0x94 # U+0x201D + 'endash' => '500', # C+0x96 # U+0x2013 + 'emdash' => '1000', # C+0x97 # U+0x2014 + 'tilde' => '333', # C+0x98 # U+0x02DC + 'trademark' => '1000', # C+0x99 # U+0x2122 + 'scaron' => '389', # C+0x9A # U+0x0161 + 'guilsinglright' => '333', # C+0x9B # U+0x203A + 'oe' => '722', # C+0x9C # U+0x0153 + 'zcaron' => '444', # C+0x9E # U+0x017E + 'Ydieresis' => '722', # C+0x9F # U+0x0178 + 'exclamdown' => '333', # C+0xA1 # U+0x00A1 + 'cent' => '500', # C+0xA2 # U+0x00A2 + 'sterling' => '500', # C+0xA3 # U+0x00A3 + 'currency' => '500', # C+0xA4 # U+0x00A4 + 'yen' => '500', # C+0xA5 # U+0x00A5 + 'brokenbar' => '220', # C+0xA6 # U+0x00A6 + 'section' => '500', # C+0xA7 # U+0x00A7 + 'dieresis' => '333', # C+0xA8 # U+0x00A8 + 'copyright' => '747', # C+0xA9 # U+0x00A9 + 'ordfeminine' => '300', # C+0xAA # U+0x00AA + 'guillemotleft' => '500', # C+0xAB # U+0x00AB + 'logicalnot' => '570', # C+0xAC # U+0x00AC + 'registered' => '747', # C+0xAE # U+0x00AE + 'macron' => '333', # C+0xAF # U+0x00AF + 'degree' => '400', # C+0xB0 # U+0x00B0 + 'plusminus' => '570', # C+0xB1 # U+0x00B1 + 'twosuperior' => '300', # C+0xB2 # U+0x00B2 + 'threesuperior' => '300', # C+0xB3 # U+0x00B3 + 'acute' => '333', # C+0xB4 # U+0x00B4 + 'mu' => '556', # C+0xB5 # U+0x00B5 + 'paragraph' => '540', # C+0xB6 # U+0x00B6 + 'periodcentered' => '250', # C+0xB7 # U+0x00B7 + 'cedilla' => '333', # C+0xB8 # U+0x00B8 + 'onesuperior' => '300', # C+0xB9 # U+0x00B9 + 'ordmasculine' => '330', # C+0xBA # U+0x00BA + 'guillemotright' => '500', # C+0xBB # U+0x00BB + 'onequarter' => '750', # C+0xBC # U+0x00BC + 'onehalf' => '750', # C+0xBD # U+0x00BD + 'threequarters' => '750', # C+0xBE # U+0x00BE + 'questiondown' => '500', # C+0xBF # U+0x00BF + 'Agrave' => '722', # C+0xC0 # U+0x00C0 + 'Aacute' => '722', # C+0xC1 # U+0x00C1 + 'Acircumflex' => '722', # C+0xC2 # U+0x00C2 + 'Atilde' => '722', # C+0xC3 # U+0x00C3 + 'Adieresis' => '722', # C+0xC4 # U+0x00C4 + 'Aring' => '722', # C+0xC5 # U+0x00C5 + 'AE' => '1000', # C+0xC6 # U+0x00C6 + 'Ccedilla' => '722', # C+0xC7 # U+0x00C7 + 'Egrave' => '667', # C+0xC8 # U+0x00C8 + 'Eacute' => '667', # C+0xC9 # U+0x00C9 + 'Ecircumflex' => '667', # C+0xCA # U+0x00CA + 'Edieresis' => '667', # C+0xCB # U+0x00CB + 'Igrave' => '389', # C+0xCC # U+0x00CC + 'Iacute' => '389', # C+0xCD # U+0x00CD + 'Icircumflex' => '389', # C+0xCE # U+0x00CE + 'Idieresis' => '389', # C+0xCF # U+0x00CF + 'Eth' => '722', # C+0xD0 # U+0x00D0 + 'Ntilde' => '722', # C+0xD1 # U+0x00D1 + 'Ograve' => '778', # C+0xD2 # U+0x00D2 + 'Oacute' => '778', # C+0xD3 # U+0x00D3 + 'Ocircumflex' => '778', # C+0xD4 # U+0x00D4 + 'Otilde' => '778', # C+0xD5 # U+0x00D5 + 'Odieresis' => '778', # C+0xD6 # U+0x00D6 + 'multiply' => '570', # C+0xD7 # U+0x00D7 + 'Oslash' => '778', # C+0xD8 # U+0x00D8 + 'Ugrave' => '722', # C+0xD9 # U+0x00D9 + 'Uacute' => '722', # C+0xDA # U+0x00DA + 'Ucircumflex' => '722', # C+0xDB # U+0x00DB + 'Udieresis' => '722', # C+0xDC # U+0x00DC + 'Yacute' => '722', # C+0xDD # U+0x00DD + 'Thorn' => '611', # C+0xDE # U+0x00DE + 'germandbls' => '556', # C+0xDF # U+0x00DF + 'agrave' => '500', # C+0xE0 # U+0x00E0 + 'aacute' => '500', # C+0xE1 # U+0x00E1 + 'acircumflex' => '500', # C+0xE2 # U+0x00E2 + 'atilde' => '500', # C+0xE3 # U+0x00E3 + 'adieresis' => '500', # C+0xE4 # U+0x00E4 + 'aring' => '500', # C+0xE5 # U+0x00E5 + 'ae' => '722', # C+0xE6 # U+0x00E6 + 'ccedilla' => '444', # C+0xE7 # U+0x00E7 + 'egrave' => '444', # C+0xE8 # U+0x00E8 + 'eacute' => '444', # C+0xE9 # U+0x00E9 + 'ecircumflex' => '444', # C+0xEA # U+0x00EA + 'edieresis' => '444', # C+0xEB # U+0x00EB + 'igrave' => '278', # C+0xEC # U+0x00EC + 'iacute' => '278', # C+0xED # U+0x00ED + 'icircumflex' => '278', # C+0xEE # U+0x00EE + 'idieresis' => '278', # C+0xEF # U+0x00EF + 'eth' => '500', # C+0xF0 # U+0x00F0 + 'ntilde' => '556', # C+0xF1 # U+0x00F1 + 'ograve' => '500', # C+0xF2 # U+0x00F2 + 'oacute' => '500', # C+0xF3 # U+0x00F3 + 'ocircumflex' => '500', # C+0xF4 # U+0x00F4 + 'otilde' => '500', # C+0xF5 # U+0x00F5 + 'odieresis' => '500', # C+0xF6 # U+0x00F6 + 'divide' => '570', # C+0xF7 # U+0x00F7 + 'oslash' => '500', # C+0xF8 # U+0x00F8 + 'ugrave' => '556', # C+0xF9 # U+0x00F9 + 'uacute' => '556', # C+0xFA # U+0x00FA + 'ucircumflex' => '556', # C+0xFB # U+0x00FB + 'udieresis' => '556', # C+0xFC # U+0x00FC + 'yacute' => '500', # C+0xFD # U+0x00FD + 'thorn' => '556', # C+0xFE # U+0x00FE + 'ydieresis' => '500', # C+0xFF # U+0x00FF + 'dotlessi' => '278', # U+0x0131 + 'Lslash' => '667', # U+0x0141 + 'lslash' => '278', # U+0x0142 + 'caron' => '333', # U+0x02C7 + 'breve' => '333', # U+0x02D8 + 'dotaccent' => '333', # U+0x02D9 + 'ring' => '333', # U+0x02DA + 'ogonek' => '333', # U+0x02DB + 'hungarumlaut' => '333', # U+0x02DD + 'fraction' => '167', # U+0x2044 + 'minus' => '570', # U+0x2212 + 'fi' => '556', # U+0xFB01 + 'fl' => '556', # U+0xFB02 + }, # HORIZ. WIDTH TABLE +} }; + +1; diff --git a/lib/PDF/API2/Resource/Font/CoreFont/timesbolditalic.pm b/lib/PDF/API2/Resource/Font/CoreFont/timesbolditalic.pm new file mode 100644 index 0000000..75cfa35 --- /dev/null +++ b/lib/PDF/API2/Resource/Font/CoreFont/timesbolditalic.pm @@ -0,0 +1,519 @@ +#line 1 "PDF/API2/Resource/Font/CoreFont/timesbolditalic.pm" +#line 1 "PDF/API2/Resource/Font/CoreFont/timesbolditalic.pm" +package PDF::API2::Resource::Font::CoreFont::timesbolditalic; + +use strict; +use warnings; + +our $VERSION = '2.033'; # VERSION + +sub data { return { + 'fontname' => 'Times-BoldItalic', + 'type' => 'Type1', + 'apiname' => 'TiBoIt', + 'ascender' => '683', + 'capheight' => '669', + 'descender' => '-217', + 'iscore' => '1', + 'isfixedpitch' => '0', + 'italicangle' => '-15', + 'stdhw' => '42', + 'stdvw' => '121', + 'underlineposition' => '-100', + 'underlinethickness' => '50', + 'xheight' => '462', + 'firstchar' => '32', + 'lastchar' => '255', + 'char' => [ # DEF. ENCODING GLYPH TABLE + '.notdef', # C+0x00 # U+0x0000 + '.notdef', # C+0x01 # U+0x0000 + '.notdef', # C+0x02 # U+0x0000 + '.notdef', # C+0x03 # U+0x0000 + '.notdef', # C+0x04 # U+0x0000 + '.notdef', # C+0x05 # U+0x0000 + '.notdef', # C+0x06 # U+0x0000 + '.notdef', # C+0x07 # U+0x0000 + '.notdef', # C+0x08 # U+0x0000 + '.notdef', # C+0x09 # U+0x0000 + '.notdef', # C+0x0A # U+0x0000 + '.notdef', # C+0x0B # U+0x0000 + '.notdef', # C+0x0C # U+0x0000 + '.notdef', # C+0x0D # U+0x0000 + '.notdef', # C+0x0E # U+0x0000 + '.notdef', # C+0x0F # U+0x0000 + '.notdef', # C+0x10 # U+0x0000 + '.notdef', # C+0x11 # U+0x0000 + '.notdef', # C+0x12 # U+0x0000 + '.notdef', # C+0x13 # U+0x0000 + '.notdef', # C+0x14 # U+0x0000 + '.notdef', # C+0x15 # U+0x0000 + '.notdef', # C+0x16 # U+0x0000 + '.notdef', # C+0x17 # U+0x0000 + '.notdef', # C+0x18 # U+0x0000 + '.notdef', # C+0x19 # U+0x0000 + '.notdef', # C+0x1A # U+0x0000 + '.notdef', # C+0x1B # U+0x0000 + '.notdef', # C+0x1C # U+0x0000 + '.notdef', # C+0x1D # U+0x0000 + '.notdef', # C+0x1E # U+0x0000 + '.notdef', # C+0x1F # U+0x0000 + 'space', # C+0x20 # U+0x0020 + 'exclam', # C+0x21 # U+0x0021 + 'quotedbl', # C+0x22 # U+0x0022 + 'numbersign', # C+0x23 # U+0x0023 + 'dollar', # C+0x24 # U+0x0024 + 'percent', # C+0x25 # U+0x0025 + 'ampersand', # C+0x26 # U+0x0026 + 'quotesingle', # C+0x27 # U+0x0027 + 'parenleft', # C+0x28 # U+0x0028 + 'parenright', # C+0x29 # U+0x0029 + 'asterisk', # C+0x2A # U+0x002A + 'plus', # C+0x2B # U+0x002B + 'comma', # C+0x2C # U+0x002C + 'hyphen', # C+0x2D # U+0x002D + 'period', # C+0x2E # U+0x002E + 'slash', # C+0x2F # U+0x002F + 'zero', # C+0x30 # U+0x0030 + 'one', # C+0x31 # U+0x0031 + 'two', # C+0x32 # U+0x0032 + 'three', # C+0x33 # U+0x0033 + 'four', # C+0x34 # U+0x0034 + 'five', # C+0x35 # U+0x0035 + 'six', # C+0x36 # U+0x0036 + 'seven', # C+0x37 # U+0x0037 + 'eight', # C+0x38 # U+0x0038 + 'nine', # C+0x39 # U+0x0039 + 'colon', # C+0x3A # U+0x003A + 'semicolon', # C+0x3B # U+0x003B + 'less', # C+0x3C # U+0x003C + 'equal', # C+0x3D # U+0x003D + 'greater', # C+0x3E # U+0x003E + 'question', # C+0x3F # U+0x003F + 'at', # C+0x40 # U+0x0040 + 'A', # C+0x41 # U+0x0041 + 'B', # C+0x42 # U+0x0042 + 'C', # C+0x43 # U+0x0043 + 'D', # C+0x44 # U+0x0044 + 'E', # C+0x45 # U+0x0045 + 'F', # C+0x46 # U+0x0046 + 'G', # C+0x47 # U+0x0047 + 'H', # C+0x48 # U+0x0048 + 'I', # C+0x49 # U+0x0049 + 'J', # C+0x4A # U+0x004A + 'K', # C+0x4B # U+0x004B + 'L', # C+0x4C # U+0x004C + 'M', # C+0x4D # U+0x004D + 'N', # C+0x4E # U+0x004E + 'O', # C+0x4F # U+0x004F + 'P', # C+0x50 # U+0x0050 + 'Q', # C+0x51 # U+0x0051 + 'R', # C+0x52 # U+0x0052 + 'S', # C+0x53 # U+0x0053 + 'T', # C+0x54 # U+0x0054 + 'U', # C+0x55 # U+0x0055 + 'V', # C+0x56 # U+0x0056 + 'W', # C+0x57 # U+0x0057 + 'X', # C+0x58 # U+0x0058 + 'Y', # C+0x59 # U+0x0059 + 'Z', # C+0x5A # U+0x005A + 'bracketleft', # C+0x5B # U+0x005B + 'backslash', # C+0x5C # U+0x005C + 'bracketright', # C+0x5D # U+0x005D + 'asciicircum', # C+0x5E # U+0x005E + 'underscore', # C+0x5F # U+0x005F + 'grave', # C+0x60 # U+0x0060 + 'a', # C+0x61 # U+0x0061 + 'b', # C+0x62 # U+0x0062 + 'c', # C+0x63 # U+0x0063 + 'd', # C+0x64 # U+0x0064 + 'e', # C+0x65 # U+0x0065 + 'f', # C+0x66 # U+0x0066 + 'g', # C+0x67 # U+0x0067 + 'h', # C+0x68 # U+0x0068 + 'i', # C+0x69 # U+0x0069 + 'j', # C+0x6A # U+0x006A + 'k', # C+0x6B # U+0x006B + 'l', # C+0x6C # U+0x006C + 'm', # C+0x6D # U+0x006D + 'n', # C+0x6E # U+0x006E + 'o', # C+0x6F # U+0x006F + 'p', # C+0x70 # U+0x0070 + 'q', # C+0x71 # U+0x0071 + 'r', # C+0x72 # U+0x0072 + 's', # C+0x73 # U+0x0073 + 't', # C+0x74 # U+0x0074 + 'u', # C+0x75 # U+0x0075 + 'v', # C+0x76 # U+0x0076 + 'w', # C+0x77 # U+0x0077 + 'x', # C+0x78 # U+0x0078 + 'y', # C+0x79 # U+0x0079 + 'z', # C+0x7A # U+0x007A + 'braceleft', # C+0x7B # U+0x007B + 'bar', # C+0x7C # U+0x007C + 'braceright', # C+0x7D # U+0x007D + 'asciitilde', # C+0x7E # U+0x007E + 'bullet', # C+0x7F # U+0x2022 + 'Euro', # C+0x80 # U+0x20AC + 'bullet', # C+0x81 # U+0x2022 + 'quotesinglbase', # C+0x82 # U+0x201A + 'florin', # C+0x83 # U+0x0192 + 'quotedblbase', # C+0x84 # U+0x201E + 'ellipsis', # C+0x85 # U+0x2026 + 'dagger', # C+0x86 # U+0x2020 + 'daggerdbl', # C+0x87 # U+0x2021 + 'circumflex', # C+0x88 # U+0x02C6 + 'perthousand', # C+0x89 # U+0x2030 + 'Scaron', # C+0x8A # U+0x0160 + 'guilsinglleft', # C+0x8B # U+0x2039 + 'OE', # C+0x8C # U+0x0152 + 'bullet', # C+0x8D # U+0x2022 + 'Zcaron', # C+0x8E # U+0x017D + 'bullet', # C+0x8F # U+0x2022 + 'bullet', # C+0x90 # U+0x2022 + 'quoteleft', # C+0x91 # U+0x2018 + 'quoteright', # C+0x92 # U+0x2019 + 'quotedblleft', # C+0x93 # U+0x201C + 'quotedblright', # C+0x94 # U+0x201D + 'bullet', # C+0x95 # U+0x2022 + 'endash', # C+0x96 # U+0x2013 + 'emdash', # C+0x97 # U+0x2014 + 'tilde', # C+0x98 # U+0x02DC + 'trademark', # C+0x99 # U+0x2122 + 'scaron', # C+0x9A # U+0x0161 + 'guilsinglright', # C+0x9B # U+0x203A + 'oe', # C+0x9C # U+0x0153 + 'bullet', # C+0x9D # U+0x2022 + 'zcaron', # C+0x9E # U+0x017E + 'Ydieresis', # C+0x9F # U+0x0178 + 'space', # C+0xA0 # U+0x0020 + 'exclamdown', # C+0xA1 # U+0x00A1 + 'cent', # C+0xA2 # U+0x00A2 + 'sterling', # C+0xA3 # U+0x00A3 + 'currency', # C+0xA4 # U+0x00A4 + 'yen', # C+0xA5 # U+0x00A5 + 'brokenbar', # C+0xA6 # U+0x00A6 + 'section', # C+0xA7 # U+0x00A7 + 'dieresis', # C+0xA8 # U+0x00A8 + 'copyright', # C+0xA9 # U+0x00A9 + 'ordfeminine', # C+0xAA # U+0x00AA + 'guillemotleft', # C+0xAB # U+0x00AB + 'logicalnot', # C+0xAC # U+0x00AC + 'hyphen', # C+0xAD # U+0x002D + 'registered', # C+0xAE # U+0x00AE + 'macron', # C+0xAF # U+0x00AF + 'degree', # C+0xB0 # U+0x00B0 + 'plusminus', # C+0xB1 # U+0x00B1 + 'twosuperior', # C+0xB2 # U+0x00B2 + 'threesuperior', # C+0xB3 # U+0x00B3 + 'acute', # C+0xB4 # U+0x00B4 + 'mu', # C+0xB5 # U+0x00B5 + 'paragraph', # C+0xB6 # U+0x00B6 + 'periodcentered', # C+0xB7 # U+0x00B7 + 'cedilla', # C+0xB8 # U+0x00B8 + 'onesuperior', # C+0xB9 # U+0x00B9 + 'ordmasculine', # C+0xBA # U+0x00BA + 'guillemotright', # C+0xBB # U+0x00BB + 'onequarter', # C+0xBC # U+0x00BC + 'onehalf', # C+0xBD # U+0x00BD + 'threequarters', # C+0xBE # U+0x00BE + 'questiondown', # C+0xBF # U+0x00BF + 'Agrave', # C+0xC0 # U+0x00C0 + 'Aacute', # C+0xC1 # U+0x00C1 + 'Acircumflex', # C+0xC2 # U+0x00C2 + 'Atilde', # C+0xC3 # U+0x00C3 + 'Adieresis', # C+0xC4 # U+0x00C4 + 'Aring', # C+0xC5 # U+0x00C5 + 'AE', # C+0xC6 # U+0x00C6 + 'Ccedilla', # C+0xC7 # U+0x00C7 + 'Egrave', # C+0xC8 # U+0x00C8 + 'Eacute', # C+0xC9 # U+0x00C9 + 'Ecircumflex', # C+0xCA # U+0x00CA + 'Edieresis', # C+0xCB # U+0x00CB + 'Igrave', # C+0xCC # U+0x00CC + 'Iacute', # C+0xCD # U+0x00CD + 'Icircumflex', # C+0xCE # U+0x00CE + 'Idieresis', # C+0xCF # U+0x00CF + 'Eth', # C+0xD0 # U+0x00D0 + 'Ntilde', # C+0xD1 # U+0x00D1 + 'Ograve', # C+0xD2 # U+0x00D2 + 'Oacute', # C+0xD3 # U+0x00D3 + 'Ocircumflex', # C+0xD4 # U+0x00D4 + 'Otilde', # C+0xD5 # U+0x00D5 + 'Odieresis', # C+0xD6 # U+0x00D6 + 'multiply', # C+0xD7 # U+0x00D7 + 'Oslash', # C+0xD8 # U+0x00D8 + 'Ugrave', # C+0xD9 # U+0x00D9 + 'Uacute', # C+0xDA # U+0x00DA + 'Ucircumflex', # C+0xDB # U+0x00DB + 'Udieresis', # C+0xDC # U+0x00DC + 'Yacute', # C+0xDD # U+0x00DD + 'Thorn', # C+0xDE # U+0x00DE + 'germandbls', # C+0xDF # U+0x00DF + 'agrave', # C+0xE0 # U+0x00E0 + 'aacute', # C+0xE1 # U+0x00E1 + 'acircumflex', # C+0xE2 # U+0x00E2 + 'atilde', # C+0xE3 # U+0x00E3 + 'adieresis', # C+0xE4 # U+0x00E4 + 'aring', # C+0xE5 # U+0x00E5 + 'ae', # C+0xE6 # U+0x00E6 + 'ccedilla', # C+0xE7 # U+0x00E7 + 'egrave', # C+0xE8 # U+0x00E8 + 'eacute', # C+0xE9 # U+0x00E9 + 'ecircumflex', # C+0xEA # U+0x00EA + 'edieresis', # C+0xEB # U+0x00EB + 'igrave', # C+0xEC # U+0x00EC + 'iacute', # C+0xED # U+0x00ED + 'icircumflex', # C+0xEE # U+0x00EE + 'idieresis', # C+0xEF # U+0x00EF + 'eth', # C+0xF0 # U+0x00F0 + 'ntilde', # C+0xF1 # U+0x00F1 + 'ograve', # C+0xF2 # U+0x00F2 + 'oacute', # C+0xF3 # U+0x00F3 + 'ocircumflex', # C+0xF4 # U+0x00F4 + 'otilde', # C+0xF5 # U+0x00F5 + 'odieresis', # C+0xF6 # U+0x00F6 + 'divide', # C+0xF7 # U+0x00F7 + 'oslash', # C+0xF8 # U+0x00F8 + 'ugrave', # C+0xF9 # U+0x00F9 + 'uacute', # C+0xFA # U+0x00FA + 'ucircumflex', # C+0xFB # U+0x00FB + 'udieresis', # C+0xFC # U+0x00FC + 'yacute', # C+0xFD # U+0x00FD + 'thorn', # C+0xFE # U+0x00FE + 'ydieresis', # C+0xFF # U+0x00FF + ], # DEF. ENCODING GLYPH TABLE + 'fontbbox' => [ -200, -218, 996, 921 ], + 'wx' => { # HORIZ. WIDTH TABLE + 'space' => '250', # C+0x20 # U+0x0020 + 'exclam' => '389', # C+0x21 # U+0x0021 + 'quotedbl' => '555', # C+0x22 # U+0x0022 + 'numbersign' => '500', # C+0x23 # U+0x0023 + 'dollar' => '500', # C+0x24 # U+0x0024 + 'percent' => '833', # C+0x25 # U+0x0025 + 'ampersand' => '777', # C+0x26 # U+0x0026 + 'quotesingle' => '277', # C+0x27 # U+0x0027 + 'parenleft' => '333', # C+0x28 # U+0x0028 + 'parenright' => '333', # C+0x29 # U+0x0029 + 'asterisk' => '500', # C+0x2A # U+0x002A + 'plus' => '569', # C+0x2B # U+0x002B + 'comma' => '250', # C+0x2C # U+0x002C + 'hyphen' => '333', # C+0x2D # U+0x002D + 'period' => '250', # C+0x2E # U+0x002E + 'slash' => '277', # C+0x2F # U+0x002F + 'zero' => '500', # C+0x30 # U+0x0030 + 'one' => '500', # C+0x31 # U+0x0031 + 'two' => '500', # C+0x32 # U+0x0032 + 'three' => '500', # C+0x33 # U+0x0033 + 'four' => '500', # C+0x34 # U+0x0034 + 'five' => '500', # C+0x35 # U+0x0035 + 'six' => '500', # C+0x36 # U+0x0036 + 'seven' => '500', # C+0x37 # U+0x0037 + 'eight' => '500', # C+0x38 # U+0x0038 + 'nine' => '500', # C+0x39 # U+0x0039 + 'colon' => '333', # C+0x3A # U+0x003A + 'semicolon' => '333', # C+0x3B # U+0x003B + 'less' => '569', # C+0x3C # U+0x003C + 'equal' => '569', # C+0x3D # U+0x003D + 'greater' => '569', # C+0x3E # U+0x003E + 'question' => '500', # C+0x3F # U+0x003F + 'at' => '832', # C+0x40 # U+0x0040 + 'A' => '666', # C+0x41 # U+0x0041 + 'B' => '666', # C+0x42 # U+0x0042 + 'C' => '666', # C+0x43 # U+0x0043 + 'D' => '722', # C+0x44 # U+0x0044 + 'E' => '666', # C+0x45 # U+0x0045 + 'F' => '666', # C+0x46 # U+0x0046 + 'G' => '722', # C+0x47 # U+0x0047 + 'H' => '777', # C+0x48 # U+0x0048 + 'I' => '389', # C+0x49 # U+0x0049 + 'J' => '500', # C+0x4A # U+0x004A + 'K' => '666', # C+0x4B # U+0x004B + 'L' => '610', # C+0x4C # U+0x004C + 'M' => '889', # C+0x4D # U+0x004D + 'N' => '722', # C+0x4E # U+0x004E + 'O' => '722', # C+0x4F # U+0x004F + 'P' => '610', # C+0x50 # U+0x0050 + 'Q' => '722', # C+0x51 # U+0x0051 + 'R' => '666', # C+0x52 # U+0x0052 + 'S' => '556', # C+0x53 # U+0x0053 + 'T' => '610', # C+0x54 # U+0x0054 + 'U' => '722', # C+0x55 # U+0x0055 + 'V' => '666', # C+0x56 # U+0x0056 + 'W' => '889', # C+0x57 # U+0x0057 + 'X' => '666', # C+0x58 # U+0x0058 + 'Y' => '610', # C+0x59 # U+0x0059 + 'Z' => '610', # C+0x5A # U+0x005A + 'bracketleft' => '333', # C+0x5B # U+0x005B + 'backslash' => '277', # C+0x5C # U+0x005C + 'bracketright' => '333', # C+0x5D # U+0x005D + 'asciicircum' => '569', # C+0x5E # U+0x005E + 'underscore' => '500', # C+0x5F # U+0x005F + 'grave' => '333', # C+0x60 # U+0x0060 + 'a' => '500', # C+0x61 # U+0x0061 + 'b' => '500', # C+0x62 # U+0x0062 + 'c' => '443', # C+0x63 # U+0x0063 + 'd' => '500', # C+0x64 # U+0x0064 + 'e' => '443', # C+0x65 # U+0x0065 + 'f' => '333', # C+0x66 # U+0x0066 + 'g' => '500', # C+0x67 # U+0x0067 + 'h' => '556', # C+0x68 # U+0x0068 + 'i' => '277', # C+0x69 # U+0x0069 + 'j' => '277', # C+0x6A # U+0x006A + 'k' => '500', # C+0x6B # U+0x006B + 'l' => '277', # C+0x6C # U+0x006C + 'm' => '777', # C+0x6D # U+0x006D + 'n' => '556', # C+0x6E # U+0x006E + 'o' => '500', # C+0x6F # U+0x006F + 'p' => '500', # C+0x70 # U+0x0070 + 'q' => '500', # C+0x71 # U+0x0071 + 'r' => '389', # C+0x72 # U+0x0072 + 's' => '389', # C+0x73 # U+0x0073 + 't' => '277', # C+0x74 # U+0x0074 + 'u' => '556', # C+0x75 # U+0x0075 + 'v' => '443', # C+0x76 # U+0x0076 + 'w' => '666', # C+0x77 # U+0x0077 + 'x' => '500', # C+0x78 # U+0x0078 + 'y' => '443', # C+0x79 # U+0x0079 + 'z' => '389', # C+0x7A # U+0x007A + 'braceleft' => '348', # C+0x7B # U+0x007B + 'bar' => '220', # C+0x7C # U+0x007C + 'braceright' => '348', # C+0x7D # U+0x007D + 'asciitilde' => '569', # C+0x7E # U+0x007E + 'bullet' => '350', # C+0x7F # U+0x2022 + 'Euro' => '500', # C+0x80 # U+0x20AC + 'quotesinglbase' => '333', # C+0x82 # U+0x201A + 'florin' => '500', # C+0x83 # U+0x0192 + 'quotedblbase' => '500', # C+0x84 # U+0x201E + 'ellipsis' => '1000', # C+0x85 # U+0x2026 + 'dagger' => '500', # C+0x86 # U+0x2020 + 'daggerdbl' => '500', # C+0x87 # U+0x2021 + 'circumflex' => '333', # C+0x88 # U+0x02C6 + 'perthousand' => '1000', # C+0x89 # U+0x2030 + 'Scaron' => '556', # C+0x8A # U+0x0160 + 'guilsinglleft' => '333', # C+0x8B # U+0x2039 + 'OE' => '943', # C+0x8C # U+0x0152 + 'Zcaron' => '610', # C+0x8E # U+0x017D + 'quoteleft' => '333', # C+0x91 # U+0x2018 + 'quoteright' => '333', # C+0x92 # U+0x2019 + 'quotedblleft' => '500', # C+0x93 # U+0x201C + 'quotedblright' => '500', # C+0x94 # U+0x201D + 'endash' => '500', # C+0x96 # U+0x2013 + 'emdash' => '1000', # C+0x97 # U+0x2014 + 'tilde' => '333', # C+0x98 # U+0x02DC + 'trademark' => '1000', # C+0x99 # U+0x2122 + 'scaron' => '389', # C+0x9A # U+0x0161 + 'guilsinglright' => '333', # C+0x9B # U+0x203A + 'oe' => '722', # C+0x9C # U+0x0153 + 'zcaron' => '389', # C+0x9E # U+0x017E + 'Ydieresis' => '610', # C+0x9F # U+0x0178 + 'exclamdown' => '389', # C+0xA1 # U+0x00A1 + 'cent' => '500', # C+0xA2 # U+0x00A2 + 'sterling' => '500', # C+0xA3 # U+0x00A3 + 'currency' => '500', # C+0xA4 # U+0x00A4 + 'yen' => '500', # C+0xA5 # U+0x00A5 + 'brokenbar' => '220', # C+0xA6 # U+0x00A6 + 'section' => '500', # C+0xA7 # U+0x00A7 + 'dieresis' => '333', # C+0xA8 # U+0x00A8 + 'copyright' => '747', # C+0xA9 # U+0x00A9 + 'ordfeminine' => '266', # C+0xAA # U+0x00AA + 'guillemotleft' => '500', # C+0xAB # U+0x00AB + 'logicalnot' => '605', # C+0xAC # U+0x00AC + 'registered' => '747', # C+0xAE # U+0x00AE + 'macron' => '333', # C+0xAF # U+0x00AF + 'degree' => '399', # C+0xB0 # U+0x00B0 + 'plusminus' => '548', # C+0xB1 # U+0x00B1 + 'twosuperior' => '299', # C+0xB2 # U+0x00B2 + 'threesuperior' => '299', # C+0xB3 # U+0x00B3 + 'acute' => '333', # C+0xB4 # U+0x00B4 + 'mu' => '556', # C+0xB5 # U+0x00B5 + 'paragraph' => '500', # C+0xB6 # U+0x00B6 + 'periodcentered' => '250', # C+0xB7 # U+0x00B7 + 'cedilla' => '333', # C+0xB8 # U+0x00B8 + 'onesuperior' => '299', # C+0xB9 # U+0x00B9 + 'ordmasculine' => '299', # C+0xBA # U+0x00BA + 'guillemotright' => '500', # C+0xBB # U+0x00BB + 'onequarter' => '750', # C+0xBC # U+0x00BC + 'onehalf' => '750', # C+0xBD # U+0x00BD + 'threequarters' => '750', # C+0xBE # U+0x00BE + 'questiondown' => '500', # C+0xBF # U+0x00BF + 'Agrave' => '666', # C+0xC0 # U+0x00C0 + 'Aacute' => '666', # C+0xC1 # U+0x00C1 + 'Acircumflex' => '666', # C+0xC2 # U+0x00C2 + 'Atilde' => '666', # C+0xC3 # U+0x00C3 + 'Adieresis' => '666', # C+0xC4 # U+0x00C4 + 'Aring' => '666', # C+0xC5 # U+0x00C5 + 'AE' => '943', # C+0xC6 # U+0x00C6 + 'Ccedilla' => '666', # C+0xC7 # U+0x00C7 + 'Egrave' => '666', # C+0xC8 # U+0x00C8 + 'Eacute' => '666', # C+0xC9 # U+0x00C9 + 'Ecircumflex' => '666', # C+0xCA # U+0x00CA + 'Edieresis' => '666', # C+0xCB # U+0x00CB + 'Igrave' => '389', # C+0xCC # U+0x00CC + 'Iacute' => '389', # C+0xCD # U+0x00CD + 'Icircumflex' => '389', # C+0xCE # U+0x00CE + 'Idieresis' => '389', # C+0xCF # U+0x00CF + 'Eth' => '722', # C+0xD0 # U+0x00D0 + 'Ntilde' => '722', # C+0xD1 # U+0x00D1 + 'Ograve' => '722', # C+0xD2 # U+0x00D2 + 'Oacute' => '722', # C+0xD3 # U+0x00D3 + 'Ocircumflex' => '722', # C+0xD4 # U+0x00D4 + 'Otilde' => '722', # C+0xD5 # U+0x00D5 + 'Odieresis' => '722', # C+0xD6 # U+0x00D6 + 'multiply' => '569', # C+0xD7 # U+0x00D7 + 'Oslash' => '722', # C+0xD8 # U+0x00D8 + 'Ugrave' => '722', # C+0xD9 # U+0x00D9 + 'Uacute' => '722', # C+0xDA # U+0x00DA + 'Ucircumflex' => '722', # C+0xDB # U+0x00DB + 'Udieresis' => '722', # C+0xDC # U+0x00DC + 'Yacute' => '610', # C+0xDD # U+0x00DD + 'Thorn' => '610', # C+0xDE # U+0x00DE + 'germandbls' => '500', # C+0xDF # U+0x00DF + 'agrave' => '500', # C+0xE0 # U+0x00E0 + 'aacute' => '500', # C+0xE1 # U+0x00E1 + 'acircumflex' => '500', # C+0xE2 # U+0x00E2 + 'atilde' => '500', # C+0xE3 # U+0x00E3 + 'adieresis' => '500', # C+0xE4 # U+0x00E4 + 'aring' => '500', # C+0xE5 # U+0x00E5 + 'ae' => '722', # C+0xE6 # U+0x00E6 + 'ccedilla' => '443', # C+0xE7 # U+0x00E7 + 'egrave' => '443', # C+0xE8 # U+0x00E8 + 'eacute' => '443', # C+0xE9 # U+0x00E9 + 'ecircumflex' => '443', # C+0xEA # U+0x00EA + 'edieresis' => '443', # C+0xEB # U+0x00EB + 'igrave' => '277', # C+0xEC # U+0x00EC + 'iacute' => '277', # C+0xED # U+0x00ED + 'icircumflex' => '277', # C+0xEE # U+0x00EE + 'idieresis' => '277', # C+0xEF # U+0x00EF + 'eth' => '500', # C+0xF0 # U+0x00F0 + 'ntilde' => '556', # C+0xF1 # U+0x00F1 + 'ograve' => '500', # C+0xF2 # U+0x00F2 + 'oacute' => '500', # C+0xF3 # U+0x00F3 + 'ocircumflex' => '500', # C+0xF4 # U+0x00F4 + 'otilde' => '500', # C+0xF5 # U+0x00F5 + 'odieresis' => '500', # C+0xF6 # U+0x00F6 + 'divide' => '548', # C+0xF7 # U+0x00F7 + 'oslash' => '500', # C+0xF8 # U+0x00F8 + 'ugrave' => '556', # C+0xF9 # U+0x00F9 + 'uacute' => '556', # C+0xFA # U+0x00FA + 'ucircumflex' => '556', # C+0xFB # U+0x00FB + 'udieresis' => '556', # C+0xFC # U+0x00FC + 'yacute' => '443', # C+0xFD # U+0x00FD + 'thorn' => '500', # C+0xFE # U+0x00FE + 'ydieresis' => '443', # C+0xFF # U+0x00FF + 'dotlessi' => '277', # U+0x0131 + 'Lslash' => '610', # U+0x0141 + 'lslash' => '277', # U+0x0142 + 'caron' => '333', # U+0x02C7 + 'breve' => '333', # U+0x02D8 + 'dotaccent' => '333', # U+0x02D9 + 'ring' => '333', # U+0x02DA + 'ogonek' => '333', # U+0x02DB + 'hungarumlaut' => '333', # U+0x02DD + 'fraction' => '166', # U+0x2044 + 'minus' => '605', # U+0x2212 + 'fi' => '556', # U+0xFB01 + 'fl' => '556', # U+0xFB02 + }, # HORIZ. WIDTH TABLE +} }; + +1; diff --git a/lib/PDF/API2/Resource/Font/CoreFont/timesitalic.pm b/lib/PDF/API2/Resource/Font/CoreFont/timesitalic.pm new file mode 100644 index 0000000..31a7407 --- /dev/null +++ b/lib/PDF/API2/Resource/Font/CoreFont/timesitalic.pm @@ -0,0 +1,521 @@ +#line 1 "PDF/API2/Resource/Font/CoreFont/timesitalic.pm" +#line 1 "PDF/API2/Resource/Font/CoreFont/timesitalic.pm" +package PDF::API2::Resource::Font::CoreFont::timesitalic; + +use strict; +use warnings; + +our $VERSION = '2.033'; # VERSION + +sub data { return { + 'fontname' => 'Times-Italic', + 'type' => 'Type1', + 'apiname' => 'TiIt', + 'ascender' => '683', + 'capheight' => '653', + 'descender' => '-217', + 'iscore' => '1', + 'isfixedpitch' => '0', + 'issymbol' => '0', + 'italicangle' => '-15.5', + 'stdhw' => '32', + 'stdvw' => '76', + 'underlineposition' => '-100', + 'underlinethickness' => '50', + 'xheight' => '441', + 'firstchar' => '32', + 'lastchar' => '255', + 'flags' => '106', + 'char' => [ # DEF. ENCODING GLYPH TABLE + '.notdef', # C+0x00 # U+0x0000 + '.notdef', # C+0x01 # U+0x0000 + '.notdef', # C+0x02 # U+0x0000 + '.notdef', # C+0x03 # U+0x0000 + '.notdef', # C+0x04 # U+0x0000 + '.notdef', # C+0x05 # U+0x0000 + '.notdef', # C+0x06 # U+0x0000 + '.notdef', # C+0x07 # U+0x0000 + '.notdef', # C+0x08 # U+0x0000 + '.notdef', # C+0x09 # U+0x0000 + '.notdef', # C+0x0A # U+0x0000 + '.notdef', # C+0x0B # U+0x0000 + '.notdef', # C+0x0C # U+0x0000 + '.notdef', # C+0x0D # U+0x0000 + '.notdef', # C+0x0E # U+0x0000 + '.notdef', # C+0x0F # U+0x0000 + '.notdef', # C+0x10 # U+0x0000 + '.notdef', # C+0x11 # U+0x0000 + '.notdef', # C+0x12 # U+0x0000 + '.notdef', # C+0x13 # U+0x0000 + '.notdef', # C+0x14 # U+0x0000 + '.notdef', # C+0x15 # U+0x0000 + '.notdef', # C+0x16 # U+0x0000 + '.notdef', # C+0x17 # U+0x0000 + '.notdef', # C+0x18 # U+0x0000 + '.notdef', # C+0x19 # U+0x0000 + '.notdef', # C+0x1A # U+0x0000 + '.notdef', # C+0x1B # U+0x0000 + '.notdef', # C+0x1C # U+0x0000 + '.notdef', # C+0x1D # U+0x0000 + '.notdef', # C+0x1E # U+0x0000 + '.notdef', # C+0x1F # U+0x0000 + 'space', # C+0x20 # U+0x0020 + 'exclam', # C+0x21 # U+0x0021 + 'quotedbl', # C+0x22 # U+0x0022 + 'numbersign', # C+0x23 # U+0x0023 + 'dollar', # C+0x24 # U+0x0024 + 'percent', # C+0x25 # U+0x0025 + 'ampersand', # C+0x26 # U+0x0026 + 'quotesingle', # C+0x27 # U+0x0027 + 'parenleft', # C+0x28 # U+0x0028 + 'parenright', # C+0x29 # U+0x0029 + 'asterisk', # C+0x2A # U+0x002A + 'plus', # C+0x2B # U+0x002B + 'comma', # C+0x2C # U+0x002C + 'hyphen', # C+0x2D # U+0x002D + 'period', # C+0x2E # U+0x002E + 'slash', # C+0x2F # U+0x002F + 'zero', # C+0x30 # U+0x0030 + 'one', # C+0x31 # U+0x0031 + 'two', # C+0x32 # U+0x0032 + 'three', # C+0x33 # U+0x0033 + 'four', # C+0x34 # U+0x0034 + 'five', # C+0x35 # U+0x0035 + 'six', # C+0x36 # U+0x0036 + 'seven', # C+0x37 # U+0x0037 + 'eight', # C+0x38 # U+0x0038 + 'nine', # C+0x39 # U+0x0039 + 'colon', # C+0x3A # U+0x003A + 'semicolon', # C+0x3B # U+0x003B + 'less', # C+0x3C # U+0x003C + 'equal', # C+0x3D # U+0x003D + 'greater', # C+0x3E # U+0x003E + 'question', # C+0x3F # U+0x003F + 'at', # C+0x40 # U+0x0040 + 'A', # C+0x41 # U+0x0041 + 'B', # C+0x42 # U+0x0042 + 'C', # C+0x43 # U+0x0043 + 'D', # C+0x44 # U+0x0044 + 'E', # C+0x45 # U+0x0045 + 'F', # C+0x46 # U+0x0046 + 'G', # C+0x47 # U+0x0047 + 'H', # C+0x48 # U+0x0048 + 'I', # C+0x49 # U+0x0049 + 'J', # C+0x4A # U+0x004A + 'K', # C+0x4B # U+0x004B + 'L', # C+0x4C # U+0x004C + 'M', # C+0x4D # U+0x004D + 'N', # C+0x4E # U+0x004E + 'O', # C+0x4F # U+0x004F + 'P', # C+0x50 # U+0x0050 + 'Q', # C+0x51 # U+0x0051 + 'R', # C+0x52 # U+0x0052 + 'S', # C+0x53 # U+0x0053 + 'T', # C+0x54 # U+0x0054 + 'U', # C+0x55 # U+0x0055 + 'V', # C+0x56 # U+0x0056 + 'W', # C+0x57 # U+0x0057 + 'X', # C+0x58 # U+0x0058 + 'Y', # C+0x59 # U+0x0059 + 'Z', # C+0x5A # U+0x005A + 'bracketleft', # C+0x5B # U+0x005B + 'backslash', # C+0x5C # U+0x005C + 'bracketright', # C+0x5D # U+0x005D + 'asciicircum', # C+0x5E # U+0x005E + 'underscore', # C+0x5F # U+0x005F + 'grave', # C+0x60 # U+0x0060 + 'a', # C+0x61 # U+0x0061 + 'b', # C+0x62 # U+0x0062 + 'c', # C+0x63 # U+0x0063 + 'd', # C+0x64 # U+0x0064 + 'e', # C+0x65 # U+0x0065 + 'f', # C+0x66 # U+0x0066 + 'g', # C+0x67 # U+0x0067 + 'h', # C+0x68 # U+0x0068 + 'i', # C+0x69 # U+0x0069 + 'j', # C+0x6A # U+0x006A + 'k', # C+0x6B # U+0x006B + 'l', # C+0x6C # U+0x006C + 'm', # C+0x6D # U+0x006D + 'n', # C+0x6E # U+0x006E + 'o', # C+0x6F # U+0x006F + 'p', # C+0x70 # U+0x0070 + 'q', # C+0x71 # U+0x0071 + 'r', # C+0x72 # U+0x0072 + 's', # C+0x73 # U+0x0073 + 't', # C+0x74 # U+0x0074 + 'u', # C+0x75 # U+0x0075 + 'v', # C+0x76 # U+0x0076 + 'w', # C+0x77 # U+0x0077 + 'x', # C+0x78 # U+0x0078 + 'y', # C+0x79 # U+0x0079 + 'z', # C+0x7A # U+0x007A + 'braceleft', # C+0x7B # U+0x007B + 'bar', # C+0x7C # U+0x007C + 'braceright', # C+0x7D # U+0x007D + 'asciitilde', # C+0x7E # U+0x007E + 'bullet', # C+0x7F # U+0x2022 + 'Euro', # C+0x80 # U+0x20AC + 'bullet', # C+0x81 # U+0x2022 + 'quotesinglbase', # C+0x82 # U+0x201A + 'florin', # C+0x83 # U+0x0192 + 'quotedblbase', # C+0x84 # U+0x201E + 'ellipsis', # C+0x85 # U+0x2026 + 'dagger', # C+0x86 # U+0x2020 + 'daggerdbl', # C+0x87 # U+0x2021 + 'circumflex', # C+0x88 # U+0x02C6 + 'perthousand', # C+0x89 # U+0x2030 + 'Scaron', # C+0x8A # U+0x0160 + 'guilsinglleft', # C+0x8B # U+0x2039 + 'OE', # C+0x8C # U+0x0152 + 'bullet', # C+0x8D # U+0x2022 + 'Zcaron', # C+0x8E # U+0x017D + 'bullet', # C+0x8F # U+0x2022 + 'bullet', # C+0x90 # U+0x2022 + 'quoteleft', # C+0x91 # U+0x2018 + 'quoteright', # C+0x92 # U+0x2019 + 'quotedblleft', # C+0x93 # U+0x201C + 'quotedblright', # C+0x94 # U+0x201D + 'bullet', # C+0x95 # U+0x2022 + 'endash', # C+0x96 # U+0x2013 + 'emdash', # C+0x97 # U+0x2014 + 'tilde', # C+0x98 # U+0x02DC + 'trademark', # C+0x99 # U+0x2122 + 'scaron', # C+0x9A # U+0x0161 + 'guilsinglright', # C+0x9B # U+0x203A + 'oe', # C+0x9C # U+0x0153 + 'bullet', # C+0x9D # U+0x2022 + 'zcaron', # C+0x9E # U+0x017E + 'Ydieresis', # C+0x9F # U+0x0178 + 'space', # C+0xA0 # U+0x0020 + 'exclamdown', # C+0xA1 # U+0x00A1 + 'cent', # C+0xA2 # U+0x00A2 + 'sterling', # C+0xA3 # U+0x00A3 + 'currency', # C+0xA4 # U+0x00A4 + 'yen', # C+0xA5 # U+0x00A5 + 'brokenbar', # C+0xA6 # U+0x00A6 + 'section', # C+0xA7 # U+0x00A7 + 'dieresis', # C+0xA8 # U+0x00A8 + 'copyright', # C+0xA9 # U+0x00A9 + 'ordfeminine', # C+0xAA # U+0x00AA + 'guillemotleft', # C+0xAB # U+0x00AB + 'logicalnot', # C+0xAC # U+0x00AC + 'hyphen', # C+0xAD # U+0x002D + 'registered', # C+0xAE # U+0x00AE + 'macron', # C+0xAF # U+0x00AF + 'degree', # C+0xB0 # U+0x00B0 + 'plusminus', # C+0xB1 # U+0x00B1 + 'twosuperior', # C+0xB2 # U+0x00B2 + 'threesuperior', # C+0xB3 # U+0x00B3 + 'acute', # C+0xB4 # U+0x00B4 + 'mu', # C+0xB5 # U+0x00B5 + 'paragraph', # C+0xB6 # U+0x00B6 + 'periodcentered', # C+0xB7 # U+0x00B7 + 'cedilla', # C+0xB8 # U+0x00B8 + 'onesuperior', # C+0xB9 # U+0x00B9 + 'ordmasculine', # C+0xBA # U+0x00BA + 'guillemotright', # C+0xBB # U+0x00BB + 'onequarter', # C+0xBC # U+0x00BC + 'onehalf', # C+0xBD # U+0x00BD + 'threequarters', # C+0xBE # U+0x00BE + 'questiondown', # C+0xBF # U+0x00BF + 'Agrave', # C+0xC0 # U+0x00C0 + 'Aacute', # C+0xC1 # U+0x00C1 + 'Acircumflex', # C+0xC2 # U+0x00C2 + 'Atilde', # C+0xC3 # U+0x00C3 + 'Adieresis', # C+0xC4 # U+0x00C4 + 'Aring', # C+0xC5 # U+0x00C5 + 'AE', # C+0xC6 # U+0x00C6 + 'Ccedilla', # C+0xC7 # U+0x00C7 + 'Egrave', # C+0xC8 # U+0x00C8 + 'Eacute', # C+0xC9 # U+0x00C9 + 'Ecircumflex', # C+0xCA # U+0x00CA + 'Edieresis', # C+0xCB # U+0x00CB + 'Igrave', # C+0xCC # U+0x00CC + 'Iacute', # C+0xCD # U+0x00CD + 'Icircumflex', # C+0xCE # U+0x00CE + 'Idieresis', # C+0xCF # U+0x00CF + 'Eth', # C+0xD0 # U+0x00D0 + 'Ntilde', # C+0xD1 # U+0x00D1 + 'Ograve', # C+0xD2 # U+0x00D2 + 'Oacute', # C+0xD3 # U+0x00D3 + 'Ocircumflex', # C+0xD4 # U+0x00D4 + 'Otilde', # C+0xD5 # U+0x00D5 + 'Odieresis', # C+0xD6 # U+0x00D6 + 'multiply', # C+0xD7 # U+0x00D7 + 'Oslash', # C+0xD8 # U+0x00D8 + 'Ugrave', # C+0xD9 # U+0x00D9 + 'Uacute', # C+0xDA # U+0x00DA + 'Ucircumflex', # C+0xDB # U+0x00DB + 'Udieresis', # C+0xDC # U+0x00DC + 'Yacute', # C+0xDD # U+0x00DD + 'Thorn', # C+0xDE # U+0x00DE + 'germandbls', # C+0xDF # U+0x00DF + 'agrave', # C+0xE0 # U+0x00E0 + 'aacute', # C+0xE1 # U+0x00E1 + 'acircumflex', # C+0xE2 # U+0x00E2 + 'atilde', # C+0xE3 # U+0x00E3 + 'adieresis', # C+0xE4 # U+0x00E4 + 'aring', # C+0xE5 # U+0x00E5 + 'ae', # C+0xE6 # U+0x00E6 + 'ccedilla', # C+0xE7 # U+0x00E7 + 'egrave', # C+0xE8 # U+0x00E8 + 'eacute', # C+0xE9 # U+0x00E9 + 'ecircumflex', # C+0xEA # U+0x00EA + 'edieresis', # C+0xEB # U+0x00EB + 'igrave', # C+0xEC # U+0x00EC + 'iacute', # C+0xED # U+0x00ED + 'icircumflex', # C+0xEE # U+0x00EE + 'idieresis', # C+0xEF # U+0x00EF + 'eth', # C+0xF0 # U+0x00F0 + 'ntilde', # C+0xF1 # U+0x00F1 + 'ograve', # C+0xF2 # U+0x00F2 + 'oacute', # C+0xF3 # U+0x00F3 + 'ocircumflex', # C+0xF4 # U+0x00F4 + 'otilde', # C+0xF5 # U+0x00F5 + 'odieresis', # C+0xF6 # U+0x00F6 + 'divide', # C+0xF7 # U+0x00F7 + 'oslash', # C+0xF8 # U+0x00F8 + 'ugrave', # C+0xF9 # U+0x00F9 + 'uacute', # C+0xFA # U+0x00FA + 'ucircumflex', # C+0xFB # U+0x00FB + 'udieresis', # C+0xFC # U+0x00FC + 'yacute', # C+0xFD # U+0x00FD + 'thorn', # C+0xFE # U+0x00FE + 'ydieresis', # C+0xFF # U+0x00FF + ], # DEF. ENCODING GLYPH TABLE + 'fontbbox' => [ -169, -217, 1010, 883 ], + 'wx' => { # HORIZ. WIDTH TABLE + 'space' => '250', # C+0x20 # U+0x0020 + 'exclam' => '333', # C+0x21 # U+0x0021 + 'quotedbl' => '419', # C+0x22 # U+0x0022 + 'numbersign' => '500', # C+0x23 # U+0x0023 + 'dollar' => '500', # C+0x24 # U+0x0024 + 'percent' => '833', # C+0x25 # U+0x0025 + 'ampersand' => '777', # C+0x26 # U+0x0026 + 'quotesingle' => '213', # C+0x27 # U+0x0027 + 'parenleft' => '333', # C+0x28 # U+0x0028 + 'parenright' => '333', # C+0x29 # U+0x0029 + 'asterisk' => '500', # C+0x2A # U+0x002A + 'plus' => '674', # C+0x2B # U+0x002B + 'comma' => '250', # C+0x2C # U+0x002C + 'hyphen' => '333', # C+0x2D # U+0x002D + 'period' => '250', # C+0x2E # U+0x002E + 'slash' => '277', # C+0x2F # U+0x002F + 'zero' => '500', # C+0x30 # U+0x0030 + 'one' => '500', # C+0x31 # U+0x0031 + 'two' => '500', # C+0x32 # U+0x0032 + 'three' => '500', # C+0x33 # U+0x0033 + 'four' => '500', # C+0x34 # U+0x0034 + 'five' => '500', # C+0x35 # U+0x0035 + 'six' => '500', # C+0x36 # U+0x0036 + 'seven' => '500', # C+0x37 # U+0x0037 + 'eight' => '500', # C+0x38 # U+0x0038 + 'nine' => '500', # C+0x39 # U+0x0039 + 'colon' => '333', # C+0x3A # U+0x003A + 'semicolon' => '333', # C+0x3B # U+0x003B + 'less' => '674', # C+0x3C # U+0x003C + 'equal' => '674', # C+0x3D # U+0x003D + 'greater' => '674', # C+0x3E # U+0x003E + 'question' => '500', # C+0x3F # U+0x003F + 'at' => '919', # C+0x40 # U+0x0040 + 'A' => '610', # C+0x41 # U+0x0041 + 'B' => '610', # C+0x42 # U+0x0042 + 'C' => '666', # C+0x43 # U+0x0043 + 'D' => '722', # C+0x44 # U+0x0044 + 'E' => '610', # C+0x45 # U+0x0045 + 'F' => '610', # C+0x46 # U+0x0046 + 'G' => '722', # C+0x47 # U+0x0047 + 'H' => '722', # C+0x48 # U+0x0048 + 'I' => '333', # C+0x49 # U+0x0049 + 'J' => '443', # C+0x4A # U+0x004A + 'K' => '666', # C+0x4B # U+0x004B + 'L' => '556', # C+0x4C # U+0x004C + 'M' => '833', # C+0x4D # U+0x004D + 'N' => '666', # C+0x4E # U+0x004E + 'O' => '722', # C+0x4F # U+0x004F + 'P' => '610', # C+0x50 # U+0x0050 + 'Q' => '722', # C+0x51 # U+0x0051 + 'R' => '610', # C+0x52 # U+0x0052 + 'S' => '500', # C+0x53 # U+0x0053 + 'T' => '556', # C+0x54 # U+0x0054 + 'U' => '722', # C+0x55 # U+0x0055 + 'V' => '610', # C+0x56 # U+0x0056 + 'W' => '833', # C+0x57 # U+0x0057 + 'X' => '610', # C+0x58 # U+0x0058 + 'Y' => '556', # C+0x59 # U+0x0059 + 'Z' => '556', # C+0x5A # U+0x005A + 'bracketleft' => '389', # C+0x5B # U+0x005B + 'backslash' => '277', # C+0x5C # U+0x005C + 'bracketright' => '389', # C+0x5D # U+0x005D + 'asciicircum' => '421', # C+0x5E # U+0x005E + 'underscore' => '500', # C+0x5F # U+0x005F + 'grave' => '333', # C+0x60 # U+0x0060 + 'a' => '500', # C+0x61 # U+0x0061 + 'b' => '500', # C+0x62 # U+0x0062 + 'c' => '443', # C+0x63 # U+0x0063 + 'd' => '500', # C+0x64 # U+0x0064 + 'e' => '443', # C+0x65 # U+0x0065 + 'f' => '277', # C+0x66 # U+0x0066 + 'g' => '500', # C+0x67 # U+0x0067 + 'h' => '500', # C+0x68 # U+0x0068 + 'i' => '277', # C+0x69 # U+0x0069 + 'j' => '277', # C+0x6A # U+0x006A + 'k' => '443', # C+0x6B # U+0x006B + 'l' => '277', # C+0x6C # U+0x006C + 'm' => '722', # C+0x6D # U+0x006D + 'n' => '500', # C+0x6E # U+0x006E + 'o' => '500', # C+0x6F # U+0x006F + 'p' => '500', # C+0x70 # U+0x0070 + 'q' => '500', # C+0x71 # U+0x0071 + 'r' => '389', # C+0x72 # U+0x0072 + 's' => '389', # C+0x73 # U+0x0073 + 't' => '277', # C+0x74 # U+0x0074 + 'u' => '500', # C+0x75 # U+0x0075 + 'v' => '443', # C+0x76 # U+0x0076 + 'w' => '666', # C+0x77 # U+0x0077 + 'x' => '443', # C+0x78 # U+0x0078 + 'y' => '443', # C+0x79 # U+0x0079 + 'z' => '389', # C+0x7A # U+0x007A + 'braceleft' => '399', # C+0x7B # U+0x007B + 'bar' => '274', # C+0x7C # U+0x007C + 'braceright' => '399', # C+0x7D # U+0x007D + 'asciitilde' => '541', # C+0x7E # U+0x007E + 'bullet' => '350', # C+0x7F # U+0x2022 + 'Euro' => '500', # C+0x80 # U+0x20AC + 'quotesinglbase' => '333', # C+0x82 # U+0x201A + 'florin' => '500', # C+0x83 # U+0x0192 + 'quotedblbase' => '556', # C+0x84 # U+0x201E + 'ellipsis' => '889', # C+0x85 # U+0x2026 + 'dagger' => '500', # C+0x86 # U+0x2020 + 'daggerdbl' => '500', # C+0x87 # U+0x2021 + 'circumflex' => '333', # C+0x88 # U+0x02C6 + 'perthousand' => '1000', # C+0x89 # U+0x2030 + 'Scaron' => '500', # C+0x8A # U+0x0160 + 'guilsinglleft' => '333', # C+0x8B # U+0x2039 + 'OE' => '943', # C+0x8C # U+0x0152 + 'Zcaron' => '556', # C+0x8E # U+0x017D + 'quoteleft' => '333', # C+0x91 # U+0x2018 + 'quoteright' => '333', # C+0x92 # U+0x2019 + 'quotedblleft' => '556', # C+0x93 # U+0x201C + 'quotedblright' => '556', # C+0x94 # U+0x201D + 'endash' => '500', # C+0x96 # U+0x2013 + 'emdash' => '889', # C+0x97 # U+0x2014 + 'tilde' => '333', # C+0x98 # U+0x02DC + 'trademark' => '979', # C+0x99 # U+0x2122 + 'scaron' => '389', # C+0x9A # U+0x0161 + 'guilsinglright' => '333', # C+0x9B # U+0x203A + 'oe' => '666', # C+0x9C # U+0x0153 + 'zcaron' => '389', # C+0x9E # U+0x017E + 'Ydieresis' => '556', # C+0x9F # U+0x0178 + 'exclamdown' => '389', # C+0xA1 # U+0x00A1 + 'cent' => '500', # C+0xA2 # U+0x00A2 + 'sterling' => '500', # C+0xA3 # U+0x00A3 + 'currency' => '500', # C+0xA4 # U+0x00A4 + 'yen' => '500', # C+0xA5 # U+0x00A5 + 'brokenbar' => '274', # C+0xA6 # U+0x00A6 + 'section' => '500', # C+0xA7 # U+0x00A7 + 'dieresis' => '333', # C+0xA8 # U+0x00A8 + 'copyright' => '759', # C+0xA9 # U+0x00A9 + 'ordfeminine' => '275', # C+0xAA # U+0x00AA + 'guillemotleft' => '500', # C+0xAB # U+0x00AB + 'logicalnot' => '674', # C+0xAC # U+0x00AC + 'registered' => '759', # C+0xAE # U+0x00AE + 'macron' => '333', # C+0xAF # U+0x00AF + 'degree' => '399', # C+0xB0 # U+0x00B0 + 'plusminus' => '548', # C+0xB1 # U+0x00B1 + 'twosuperior' => '299', # C+0xB2 # U+0x00B2 + 'threesuperior' => '299', # C+0xB3 # U+0x00B3 + 'acute' => '333', # C+0xB4 # U+0x00B4 + 'mu' => '501', # C+0xB5 # U+0x00B5 + 'paragraph' => '522', # C+0xB6 # U+0x00B6 + 'periodcentered' => '250', # C+0xB7 # U+0x00B7 + 'cedilla' => '333', # C+0xB8 # U+0x00B8 + 'onesuperior' => '299', # C+0xB9 # U+0x00B9 + 'ordmasculine' => '310', # C+0xBA # U+0x00BA + 'guillemotright' => '500', # C+0xBB # U+0x00BB + 'onequarter' => '750', # C+0xBC # U+0x00BC + 'onehalf' => '750', # C+0xBD # U+0x00BD + 'threequarters' => '750', # C+0xBE # U+0x00BE + 'questiondown' => '500', # C+0xBF # U+0x00BF + 'Agrave' => '610', # C+0xC0 # U+0x00C0 + 'Aacute' => '610', # C+0xC1 # U+0x00C1 + 'Acircumflex' => '610', # C+0xC2 # U+0x00C2 + 'Atilde' => '610', # C+0xC3 # U+0x00C3 + 'Adieresis' => '610', # C+0xC4 # U+0x00C4 + 'Aring' => '610', # C+0xC5 # U+0x00C5 + 'AE' => '889', # C+0xC6 # U+0x00C6 + 'Ccedilla' => '666', # C+0xC7 # U+0x00C7 + 'Egrave' => '610', # C+0xC8 # U+0x00C8 + 'Eacute' => '610', # C+0xC9 # U+0x00C9 + 'Ecircumflex' => '610', # C+0xCA # U+0x00CA + 'Edieresis' => '610', # C+0xCB # U+0x00CB + 'Igrave' => '333', # C+0xCC # U+0x00CC + 'Iacute' => '333', # C+0xCD # U+0x00CD + 'Icircumflex' => '333', # C+0xCE # U+0x00CE + 'Idieresis' => '333', # C+0xCF # U+0x00CF + 'Eth' => '722', # C+0xD0 # U+0x00D0 + 'Ntilde' => '666', # C+0xD1 # U+0x00D1 + 'Ograve' => '722', # C+0xD2 # U+0x00D2 + 'Oacute' => '722', # C+0xD3 # U+0x00D3 + 'Ocircumflex' => '722', # C+0xD4 # U+0x00D4 + 'Otilde' => '722', # C+0xD5 # U+0x00D5 + 'Odieresis' => '722', # C+0xD6 # U+0x00D6 + 'multiply' => '674', # C+0xD7 # U+0x00D7 + 'Oslash' => '722', # C+0xD8 # U+0x00D8 + 'Ugrave' => '722', # C+0xD9 # U+0x00D9 + 'Uacute' => '722', # C+0xDA # U+0x00DA + 'Ucircumflex' => '722', # C+0xDB # U+0x00DB + 'Udieresis' => '722', # C+0xDC # U+0x00DC + 'Yacute' => '556', # C+0xDD # U+0x00DD + 'Thorn' => '610', # C+0xDE # U+0x00DE + 'germandbls' => '500', # C+0xDF # U+0x00DF + 'agrave' => '500', # C+0xE0 # U+0x00E0 + 'aacute' => '500', # C+0xE1 # U+0x00E1 + 'acircumflex' => '500', # C+0xE2 # U+0x00E2 + 'atilde' => '500', # C+0xE3 # U+0x00E3 + 'adieresis' => '500', # C+0xE4 # U+0x00E4 + 'aring' => '500', # C+0xE5 # U+0x00E5 + 'ae' => '666', # C+0xE6 # U+0x00E6 + 'ccedilla' => '443', # C+0xE7 # U+0x00E7 + 'egrave' => '443', # C+0xE8 # U+0x00E8 + 'eacute' => '443', # C+0xE9 # U+0x00E9 + 'ecircumflex' => '443', # C+0xEA # U+0x00EA + 'edieresis' => '443', # C+0xEB # U+0x00EB + 'igrave' => '277', # C+0xEC # U+0x00EC + 'iacute' => '277', # C+0xED # U+0x00ED + 'icircumflex' => '277', # C+0xEE # U+0x00EE + 'idieresis' => '277', # C+0xEF # U+0x00EF + 'eth' => '500', # C+0xF0 # U+0x00F0 + 'ntilde' => '500', # C+0xF1 # U+0x00F1 + 'ograve' => '500', # C+0xF2 # U+0x00F2 + 'oacute' => '500', # C+0xF3 # U+0x00F3 + 'ocircumflex' => '500', # C+0xF4 # U+0x00F4 + 'otilde' => '500', # C+0xF5 # U+0x00F5 + 'odieresis' => '500', # C+0xF6 # U+0x00F6 + 'divide' => '548', # C+0xF7 # U+0x00F7 + 'oslash' => '500', # C+0xF8 # U+0x00F8 + 'ugrave' => '500', # C+0xF9 # U+0x00F9 + 'uacute' => '500', # C+0xFA # U+0x00FA + 'ucircumflex' => '500', # C+0xFB # U+0x00FB + 'udieresis' => '500', # C+0xFC # U+0x00FC + 'yacute' => '443', # C+0xFD # U+0x00FD + 'thorn' => '500', # C+0xFE # U+0x00FE + 'ydieresis' => '443', # C+0xFF # U+0x00FF + 'dotlessi' => '277', # U+0x0131 + 'Lslash' => '556', # U+0x0141 + 'lslash' => '277', # U+0x0142 + 'caron' => '333', # U+0x02C7 + 'breve' => '333', # U+0x02D8 + 'dotaccent' => '333', # U+0x02D9 + 'ring' => '333', # U+0x02DA + 'ogonek' => '333', # U+0x02DB + 'hungarumlaut' => '333', # U+0x02DD + 'fraction' => '166', # U+0x2044 + 'minus' => '674', # U+0x2212 + 'fi' => '500', # U+0xFB01 + 'fl' => '500', # U+0xFB02 + }, # HORIZ. WIDTH TABLE +} }; + +1; diff --git a/lib/PDF/API2/Resource/Font/CoreFont/timesroman.pm b/lib/PDF/API2/Resource/Font/CoreFont/timesroman.pm new file mode 100644 index 0000000..ec13f8c --- /dev/null +++ b/lib/PDF/API2/Resource/Font/CoreFont/timesroman.pm @@ -0,0 +1,606 @@ +#line 1 "PDF/API2/Resource/Font/CoreFont/timesroman.pm" +#line 1 "PDF/API2/Resource/Font/CoreFont/timesroman.pm" +package PDF::API2::Resource::Font::CoreFont::timesroman; + +use strict; +use warnings; + +our $VERSION = '2.033'; # VERSION + +sub data { return { + 'fontname' => 'Times-Roman', + 'type' => 'Type1', + 'apiname' => 'TiRo', + 'ascender' => '683', + 'capheight' => '662', + 'descender' => '-217', + 'iscore' => '1', + 'isfixedpitch' => '0', + 'italicangle' => '0', + 'missingwidth' => '250', + 'stdhw' => '28', + 'stdvw' => '84', + 'underlineposition' => '-100', + 'underlinethickness' => '50', + 'xheight' => '450', + 'firstchar' => '32', + 'lastchar' => '255', + 'fontbbox' => [-168, -218, 1000, 898], + 'char' => [ # DEF. ENCODING GLYPH TABLE + '.notdef', # C+0x00 # U+0x0000 + '.notdef', # C+0x01 # U+0x0000 + '.notdef', # C+0x02 # U+0x0000 + '.notdef', # C+0x03 # U+0x0000 + '.notdef', # C+0x04 # U+0x0000 + '.notdef', # C+0x05 # U+0x0000 + '.notdef', # C+0x06 # U+0x0000 + '.notdef', # C+0x07 # U+0x0000 + '.notdef', # C+0x08 # U+0x0000 + '.notdef', # C+0x09 # U+0x0000 + '.notdef', # C+0x0A # U+0x0000 + '.notdef', # C+0x0B # U+0x0000 + '.notdef', # C+0x0C # U+0x0000 + '.notdef', # C+0x0D # U+0x0000 + '.notdef', # C+0x0E # U+0x0000 + '.notdef', # C+0x0F # U+0x0000 + '.notdef', # C+0x10 # U+0x0000 + '.notdef', # C+0x11 # U+0x0000 + '.notdef', # C+0x12 # U+0x0000 + '.notdef', # C+0x13 # U+0x0000 + '.notdef', # C+0x14 # U+0x0000 + '.notdef', # C+0x15 # U+0x0000 + '.notdef', # C+0x16 # U+0x0000 + '.notdef', # C+0x17 # U+0x0000 + '.notdef', # C+0x18 # U+0x0000 + '.notdef', # C+0x19 # U+0x0000 + '.notdef', # C+0x1A # U+0x0000 + '.notdef', # C+0x1B # U+0x0000 + '.notdef', # C+0x1C # U+0x0000 + '.notdef', # C+0x1D # U+0x0000 + '.notdef', # C+0x1E # U+0x0000 + '.notdef', # C+0x1F # U+0x0000 + 'space', # C+0x20 # U+0x0020 + 'exclam', # C+0x21 # U+0x0021 + 'quotedbl', # C+0x22 # U+0x0022 + 'numbersign', # C+0x23 # U+0x0023 + 'dollar', # C+0x24 # U+0x0024 + 'percent', # C+0x25 # U+0x0025 + 'ampersand', # C+0x26 # U+0x0026 + 'quotesingle', # C+0x27 # U+0x0027 + 'parenleft', # C+0x28 # U+0x0028 + 'parenright', # C+0x29 # U+0x0029 + 'asterisk', # C+0x2A # U+0x002A + 'plus', # C+0x2B # U+0x002B + 'comma', # C+0x2C # U+0x002C + 'hyphen', # C+0x2D # U+0x002D + 'period', # C+0x2E # U+0x002E + 'slash', # C+0x2F # U+0x002F + 'zero', # C+0x30 # U+0x0030 + 'one', # C+0x31 # U+0x0031 + 'two', # C+0x32 # U+0x0032 + 'three', # C+0x33 # U+0x0033 + 'four', # C+0x34 # U+0x0034 + 'five', # C+0x35 # U+0x0035 + 'six', # C+0x36 # U+0x0036 + 'seven', # C+0x37 # U+0x0037 + 'eight', # C+0x38 # U+0x0038 + 'nine', # C+0x39 # U+0x0039 + 'colon', # C+0x3A # U+0x003A + 'semicolon', # C+0x3B # U+0x003B + 'less', # C+0x3C # U+0x003C + 'equal', # C+0x3D # U+0x003D + 'greater', # C+0x3E # U+0x003E + 'question', # C+0x3F # U+0x003F + 'at', # C+0x40 # U+0x0040 + 'A', # C+0x41 # U+0x0041 + 'B', # C+0x42 # U+0x0042 + 'C', # C+0x43 # U+0x0043 + 'D', # C+0x44 # U+0x0044 + 'E', # C+0x45 # U+0x0045 + 'F', # C+0x46 # U+0x0046 + 'G', # C+0x47 # U+0x0047 + 'H', # C+0x48 # U+0x0048 + 'I', # C+0x49 # U+0x0049 + 'J', # C+0x4A # U+0x004A + 'K', # C+0x4B # U+0x004B + 'L', # C+0x4C # U+0x004C + 'M', # C+0x4D # U+0x004D + 'N', # C+0x4E # U+0x004E + 'O', # C+0x4F # U+0x004F + 'P', # C+0x50 # U+0x0050 + 'Q', # C+0x51 # U+0x0051 + 'R', # C+0x52 # U+0x0052 + 'S', # C+0x53 # U+0x0053 + 'T', # C+0x54 # U+0x0054 + 'U', # C+0x55 # U+0x0055 + 'V', # C+0x56 # U+0x0056 + 'W', # C+0x57 # U+0x0057 + 'X', # C+0x58 # U+0x0058 + 'Y', # C+0x59 # U+0x0059 + 'Z', # C+0x5A # U+0x005A + 'bracketleft', # C+0x5B # U+0x005B + 'backslash', # C+0x5C # U+0x005C + 'bracketright', # C+0x5D # U+0x005D + 'asciicircum', # C+0x5E # U+0x005E + 'underscore', # C+0x5F # U+0x005F + 'grave', # C+0x60 # U+0x0060 + 'a', # C+0x61 # U+0x0061 + 'b', # C+0x62 # U+0x0062 + 'c', # C+0x63 # U+0x0063 + 'd', # C+0x64 # U+0x0064 + 'e', # C+0x65 # U+0x0065 + 'f', # C+0x66 # U+0x0066 + 'g', # C+0x67 # U+0x0067 + 'h', # C+0x68 # U+0x0068 + 'i', # C+0x69 # U+0x0069 + 'j', # C+0x6A # U+0x006A + 'k', # C+0x6B # U+0x006B + 'l', # C+0x6C # U+0x006C + 'm', # C+0x6D # U+0x006D + 'n', # C+0x6E # U+0x006E + 'o', # C+0x6F # U+0x006F + 'p', # C+0x70 # U+0x0070 + 'q', # C+0x71 # U+0x0071 + 'r', # C+0x72 # U+0x0072 + 's', # C+0x73 # U+0x0073 + 't', # C+0x74 # U+0x0074 + 'u', # C+0x75 # U+0x0075 + 'v', # C+0x76 # U+0x0076 + 'w', # C+0x77 # U+0x0077 + 'x', # C+0x78 # U+0x0078 + 'y', # C+0x79 # U+0x0079 + 'z', # C+0x7A # U+0x007A + 'braceleft', # C+0x7B # U+0x007B + 'bar', # C+0x7C # U+0x007C + 'braceright', # C+0x7D # U+0x007D + 'asciitilde', # C+0x7E # U+0x007E + 'bullet', # C+0x7F # U+0x2022 + 'Euro', # C+0x80 # U+0x20AC + 'bullet', # C+0x81 # U+0x2022 + 'quotesinglbase', # C+0x82 # U+0x201A + 'florin', # C+0x83 # U+0x0192 + 'quotedblbase', # C+0x84 # U+0x201E + 'ellipsis', # C+0x85 # U+0x2026 + 'dagger', # C+0x86 # U+0x2020 + 'daggerdbl', # C+0x87 # U+0x2021 + 'circumflex', # C+0x88 # U+0x02C6 + 'perthousand', # C+0x89 # U+0x2030 + 'Scaron', # C+0x8A # U+0x0160 + 'guilsinglleft', # C+0x8B # U+0x2039 + 'OE', # C+0x8C # U+0x0152 + 'bullet', # C+0x8D # U+0x2022 + 'Zcaron', # C+0x8E # U+0x017D + 'bullet', # C+0x8F # U+0x2022 + 'bullet', # C+0x90 # U+0x2022 + 'quoteleft', # C+0x91 # U+0x2018 + 'quoteright', # C+0x92 # U+0x2019 + 'quotedblleft', # C+0x93 # U+0x201C + 'quotedblright', # C+0x94 # U+0x201D + 'bullet', # C+0x95 # U+0x2022 + 'endash', # C+0x96 # U+0x2013 + 'emdash', # C+0x97 # U+0x2014 + 'tilde', # C+0x98 # U+0x02DC + 'trademark', # C+0x99 # U+0x2122 + 'scaron', # C+0x9A # U+0x0161 + 'guilsinglright', # C+0x9B # U+0x203A + 'oe', # C+0x9C # U+0x0153 + 'bullet', # C+0x9D # U+0x2022 + 'zcaron', # C+0x9E # U+0x017E + 'Ydieresis', # C+0x9F # U+0x0178 + 'space', # C+0xA0 # U+0x0020 + 'exclamdown', # C+0xA1 # U+0x00A1 + 'cent', # C+0xA2 # U+0x00A2 + 'sterling', # C+0xA3 # U+0x00A3 + 'currency', # C+0xA4 # U+0x00A4 + 'yen', # C+0xA5 # U+0x00A5 + 'brokenbar', # C+0xA6 # U+0x00A6 + 'section', # C+0xA7 # U+0x00A7 + 'dieresis', # C+0xA8 # U+0x00A8 + 'copyright', # C+0xA9 # U+0x00A9 + 'ordfeminine', # C+0xAA # U+0x00AA + 'guillemotleft', # C+0xAB # U+0x00AB + 'logicalnot', # C+0xAC # U+0x00AC + 'hyphen', # C+0xAD # U+0x002D + 'registered', # C+0xAE # U+0x00AE + 'macron', # C+0xAF # U+0x00AF + 'degree', # C+0xB0 # U+0x00B0 + 'plusminus', # C+0xB1 # U+0x00B1 + 'twosuperior', # C+0xB2 # U+0x00B2 + 'threesuperior', # C+0xB3 # U+0x00B3 + 'acute', # C+0xB4 # U+0x00B4 + 'mu', # C+0xB5 # U+0x00B5 + 'paragraph', # C+0xB6 # U+0x00B6 + 'periodcentered', # C+0xB7 # U+0x00B7 + 'cedilla', # C+0xB8 # U+0x00B8 + 'onesuperior', # C+0xB9 # U+0x00B9 + 'ordmasculine', # C+0xBA # U+0x00BA + 'guillemotright', # C+0xBB # U+0x00BB + 'onequarter', # C+0xBC # U+0x00BC + 'onehalf', # C+0xBD # U+0x00BD + 'threequarters', # C+0xBE # U+0x00BE + 'questiondown', # C+0xBF # U+0x00BF + 'Agrave', # C+0xC0 # U+0x00C0 + 'Aacute', # C+0xC1 # U+0x00C1 + 'Acircumflex', # C+0xC2 # U+0x00C2 + 'Atilde', # C+0xC3 # U+0x00C3 + 'Adieresis', # C+0xC4 # U+0x00C4 + 'Aring', # C+0xC5 # U+0x00C5 + 'AE', # C+0xC6 # U+0x00C6 + 'Ccedilla', # C+0xC7 # U+0x00C7 + 'Egrave', # C+0xC8 # U+0x00C8 + 'Eacute', # C+0xC9 # U+0x00C9 + 'Ecircumflex', # C+0xCA # U+0x00CA + 'Edieresis', # C+0xCB # U+0x00CB + 'Igrave', # C+0xCC # U+0x00CC + 'Iacute', # C+0xCD # U+0x00CD + 'Icircumflex', # C+0xCE # U+0x00CE + 'Idieresis', # C+0xCF # U+0x00CF + 'Eth', # C+0xD0 # U+0x00D0 + 'Ntilde', # C+0xD1 # U+0x00D1 + 'Ograve', # C+0xD2 # U+0x00D2 + 'Oacute', # C+0xD3 # U+0x00D3 + 'Ocircumflex', # C+0xD4 # U+0x00D4 + 'Otilde', # C+0xD5 # U+0x00D5 + 'Odieresis', # C+0xD6 # U+0x00D6 + 'multiply', # C+0xD7 # U+0x00D7 + 'Oslash', # C+0xD8 # U+0x00D8 + 'Ugrave', # C+0xD9 # U+0x00D9 + 'Uacute', # C+0xDA # U+0x00DA + 'Ucircumflex', # C+0xDB # U+0x00DB + 'Udieresis', # C+0xDC # U+0x00DC + 'Yacute', # C+0xDD # U+0x00DD + 'Thorn', # C+0xDE # U+0x00DE + 'germandbls', # C+0xDF # U+0x00DF + 'agrave', # C+0xE0 # U+0x00E0 + 'aacute', # C+0xE1 # U+0x00E1 + 'acircumflex', # C+0xE2 # U+0x00E2 + 'atilde', # C+0xE3 # U+0x00E3 + 'adieresis', # C+0xE4 # U+0x00E4 + 'aring', # C+0xE5 # U+0x00E5 + 'ae', # C+0xE6 # U+0x00E6 + 'ccedilla', # C+0xE7 # U+0x00E7 + 'egrave', # C+0xE8 # U+0x00E8 + 'eacute', # C+0xE9 # U+0x00E9 + 'ecircumflex', # C+0xEA # U+0x00EA + 'edieresis', # C+0xEB # U+0x00EB + 'igrave', # C+0xEC # U+0x00EC + 'iacute', # C+0xED # U+0x00ED + 'icircumflex', # C+0xEE # U+0x00EE + 'idieresis', # C+0xEF # U+0x00EF + 'eth', # C+0xF0 # U+0x00F0 + 'ntilde', # C+0xF1 # U+0x00F1 + 'ograve', # C+0xF2 # U+0x00F2 + 'oacute', # C+0xF3 # U+0x00F3 + 'ocircumflex', # C+0xF4 # U+0x00F4 + 'otilde', # C+0xF5 # U+0x00F5 + 'odieresis', # C+0xF6 # U+0x00F6 + 'divide', # C+0xF7 # U+0x00F7 + 'oslash', # C+0xF8 # U+0x00F8 + 'ugrave', # C+0xF9 # U+0x00F9 + 'uacute', # C+0xFA # U+0x00FA + 'ucircumflex', # C+0xFB # U+0x00FB + 'udieresis', # C+0xFC # U+0x00FC + 'yacute', # C+0xFD # U+0x00FD + 'thorn', # C+0xFE # U+0x00FE + 'ydieresis', # C+0xFF # U+0x00FF + ], # DEF. ENCODING GLYPH TABLE + 'wx' => { + 'a' => 444, + 'A' => 722, + 'Aacute' => 722, + 'aacute' => 444, + 'abreve' => 444, + 'Abreve' => 722, + 'acircumflex' => 444, + 'Acircumflex' => 722, + 'acute' => 333, + 'adieresis' => 444, + 'Adieresis' => 722, + 'AE' => 889, + 'ae' => 667, + 'agrave' => 444, + 'Agrave' => 722, + 'amacron' => 444, + 'Amacron' => 722, + 'ampersand' => 778, + 'Aogonek' => 722, + 'aogonek' => 444, + 'aring' => 444, + 'Aring' => 722, + 'asciicircum' => 469, + 'asciitilde' => 541, + 'asterisk' => 500, + 'at' => 921, + 'atilde' => 444, + 'Atilde' => 722, + 'B' => 667, + 'b' => 500, + 'backslash' => 278, + 'bar' => 200, + 'braceleft' => 480, + 'braceright' => 480, + 'bracketleft' => 333, + 'bracketright' => 333, + 'breve' => 333, + 'brokenbar' => 200, + 'bullet' => 350, + 'C' => 667, + 'c' => 444, + 'cacute' => 444, + 'Cacute' => 667, + 'caron' => 333, + 'Ccaron' => 667, + 'ccaron' => 444, + 'ccedilla' => 444, + 'Ccedilla' => 667, + 'cedilla' => 333, + 'cent' => 500, + 'circumflex' => 333, + 'colon' => 278, + 'comma' => 250, + 'commaaccent' => 250, + 'copyright' => 760, + 'currency' => 500, + 'd' => 500, + 'D' => 722, + 'dagger' => 500, + 'daggerdbl' => 500, + 'dcaron' => 588, + 'Dcaron' => 722, + 'dcroat' => 500, + 'Dcroat' => 722, + 'degree' => 400, + 'Delta' => 612, + 'dieresis' => 333, + 'divide' => 564, + 'dollar' => 500, + 'dotaccent' => 333, + 'dotlessi' => 278, + 'e' => 444, + 'E' => 611, + 'eacute' => 444, + 'Eacute' => 611, + 'ecaron' => 444, + 'Ecaron' => 611, + 'ecircumflex' => 444, + 'Ecircumflex' => 611, + 'edieresis' => 444, + 'Edieresis' => 611, + 'Edotaccent' => 611, + 'edotaccent' => 444, + 'egrave' => 444, + 'Egrave' => 611, + 'eight' => 500, + 'ellipsis' => 1000, + 'Emacron' => 611, + 'emacron' => 444, + 'emdash' => 1000, + 'endash' => 500, + 'eogonek' => 444, + 'Eogonek' => 611, + 'equal' => 564, + 'Eth' => 722, + 'eth' => 500, + 'Euro' => 500, + 'exclam' => 333, + 'exclamdown' => 333, + 'F' => 556, + 'f' => 333, + 'fi' => 556, + 'five' => 500, + 'fl' => 556, + 'florin' => 500, + 'four' => 500, + 'fraction' => 167, + 'G' => 722, + 'g' => 500, + 'Gbreve' => 722, + 'gbreve' => 500, + 'gcommaaccent' => 500, + 'Gcommaaccent' => 722, + 'germandbls' => 500, + 'grave' => 333, + 'greater' => 564, + 'greaterequal' => 549, + 'guillemotleft' => 500, + 'guillemotright' => 500, + 'guilsinglleft' => 333, + 'guilsinglright' => 333, + 'H' => 722, + 'h' => 500, + 'hungarumlaut' => 333, + 'hyphen' => 333, + 'I' => 333, + 'i' => 278, + 'Iacute' => 333, + 'iacute' => 278, + 'Icircumflex' => 333, + 'icircumflex' => 278, + 'idieresis' => 278, + 'Idieresis' => 333, + 'Idotaccent' => 333, + 'igrave' => 278, + 'Igrave' => 333, + 'Imacron' => 333, + 'imacron' => 278, + 'Iogonek' => 333, + 'iogonek' => 278, + 'j' => 278, + 'J' => 389, + 'k' => 500, + 'K' => 722, + 'Kcommaaccent' => 722, + 'kcommaaccent' => 500, + 'L' => 611, + 'l' => 278, + 'lacute' => 278, + 'Lacute' => 611, + 'lcaron' => 344, + 'Lcaron' => 611, + 'lcommaaccent' => 278, + 'Lcommaaccent' => 611, + 'less' => 564, + 'lessequal' => 549, + 'logicalnot' => 564, + 'lozenge' => 471, + 'Lslash' => 611, + 'lslash' => 278, + 'M' => 889, + 'm' => 778, + 'macron' => 333, + 'minus' => 564, + 'mu' => 500, + 'multiply' => 564, + 'n' => 500, + 'N' => 722, + 'nacute' => 500, + 'Nacute' => 722, + 'ncaron' => 500, + 'Ncaron' => 722, + 'ncommaaccent' => 500, + 'Ncommaaccent' => 722, + 'nine' => 500, + 'notequal' => 549, + 'ntilde' => 500, + 'Ntilde' => 722, + 'numbersign' => 500, + 'o' => 500, + 'O' => 722, + 'oacute' => 500, + 'Oacute' => 722, + 'Ocircumflex' => 722, + 'ocircumflex' => 500, + 'Odieresis' => 722, + 'odieresis' => 500, + 'oe' => 722, + 'OE' => 889, + 'ogonek' => 333, + 'ograve' => 500, + 'Ograve' => 722, + 'ohungarumlaut' => 500, + 'Ohungarumlaut' => 722, + 'Omacron' => 722, + 'omacron' => 500, + 'one' => 500, + 'onehalf' => 750, + 'onequarter' => 750, + 'onesuperior' => 300, + 'ordfeminine' => 276, + 'ordmasculine' => 310, + 'Oslash' => 722, + 'oslash' => 500, + 'Otilde' => 722, + 'otilde' => 500, + 'P' => 556, + 'p' => 500, + 'paragraph' => 453, + 'parenleft' => 333, + 'parenright' => 333, + 'partialdiff' => 476, + 'percent' => 833, + 'period' => 250, + 'periodcentered' => 250, + 'perthousand' => 1000, + 'plus' => 564, + 'plusminus' => 564, + 'Q' => 722, + 'q' => 500, + 'question' => 444, + 'questiondown' => 444, + 'quotedbl' => 408, + 'quotedblbase' => 444, + 'quotedblleft' => 444, + 'quotedblright' => 444, + 'quoteleft' => 333, + 'quoteright' => 333, + 'quotesinglbase' => 333, + 'quotesingle' => 180, + 'R' => 667, + 'r' => 333, + 'racute' => 333, + 'Racute' => 667, + 'radical' => 453, + 'rcaron' => 333, + 'Rcaron' => 667, + 'rcommaaccent' => 333, + 'Rcommaaccent' => 667, + 'registered' => 760, + 'ring' => 333, + 'S' => 556, + 's' => 389, + 'Sacute' => 556, + 'sacute' => 389, + 'Scaron' => 556, + 'scaron' => 389, + 'Scedilla' => 556, + 'scedilla' => 389, + 'Scommaaccent' => 556, + 'scommaaccent' => 389, + 'section' => 500, + 'semicolon' => 278, + 'seven' => 500, + 'six' => 500, + 'slash' => 278, + 'space' => 250, + 'sterling' => 500, + 'summation' => 600, + 'T' => 611, + 't' => 278, + 'Tcaron' => 611, + 'tcaron' => 326, + 'tcommaaccent' => 278, + 'Tcommaaccent' => 611, + 'Thorn' => 556, + 'thorn' => 500, + 'three' => 500, + 'threequarters' => 750, + 'threesuperior' => 300, + 'tilde' => 333, + 'trademark' => 980, + 'two' => 500, + 'twosuperior' => 300, + 'u' => 500, + 'U' => 722, + 'Uacute' => 722, + 'uacute' => 500, + 'ucircumflex' => 500, + 'Ucircumflex' => 722, + 'udieresis' => 500, + 'Udieresis' => 722, + 'Ugrave' => 722, + 'ugrave' => 500, + 'uhungarumlaut' => 500, + 'Uhungarumlaut' => 722, + 'umacron' => 500, + 'Umacron' => 722, + 'underscore' => 500, + 'Uogonek' => 722, + 'uogonek' => 500, + 'Uring' => 722, + 'uring' => 500, + 'V' => 722, + 'v' => 500, + 'w' => 722, + 'W' => 944, + 'X' => 722, + 'x' => 500, + 'y' => 500, + 'Y' => 722, + 'yacute' => 500, + 'Yacute' => 722, + 'Ydieresis' => 722, + 'ydieresis' => 500, + 'yen' => 500, + 'Z' => 611, + 'z' => 444, + 'zacute' => 444, + 'Zacute' => 611, + 'Zcaron' => 611, + 'zcaron' => 444, + 'Zdotaccent' => 611, + 'zdotaccent' => 444, + 'zero' => 500, + }, +} }; + +1; diff --git a/lib/PDF/API2/Resource/Font/CoreFont/trebuchet.pm b/lib/PDF/API2/Resource/Font/CoreFont/trebuchet.pm new file mode 100644 index 0000000..11e18f1 --- /dev/null +++ b/lib/PDF/API2/Resource/Font/CoreFont/trebuchet.pm @@ -0,0 +1,577 @@ +#line 1 "PDF/API2/Resource/Font/CoreFont/trebuchet.pm" +#line 1 "PDF/API2/Resource/Font/CoreFont/trebuchet.pm" +package PDF::API2::Resource::Font::CoreFont::trebuchet; + +use strict; +use warnings; + +our $VERSION = '2.033'; # VERSION + +sub data { return { + 'fontname' => 'TrebuchetMS', + 'type' => 'TrueType', + 'apiname' => 'Treb', + 'ascender' => '938', + 'capheight' => '715', + 'descender' => '-222', + 'isfixedpitch' => '0', + 'issymbol' => '0', + 'italicangle' => '0', + 'underlineposition' => '-261', + 'underlinethickness' => '127', + 'xheight' => '522', + 'firstchar' => '32', + 'lastchar' => '255', + 'flags' => '34', + 'char' => [ # DEF. ENCODING GLYPH TABLE + '.notdef', # C+0x00 # U+0x0000 + '.notdef', # C+0x01 # U+0x0000 + '.notdef', # C+0x02 # U+0x0000 + '.notdef', # C+0x03 # U+0x0000 + '.notdef', # C+0x04 # U+0x0000 + '.notdef', # C+0x05 # U+0x0000 + '.notdef', # C+0x06 # U+0x0000 + '.notdef', # C+0x07 # U+0x0000 + '.notdef', # C+0x08 # U+0x0000 + '.notdef', # C+0x09 # U+0x0000 + '.notdef', # C+0x0A # U+0x0000 + '.notdef', # C+0x0B # U+0x0000 + '.notdef', # C+0x0C # U+0x0000 + '.notdef', # C+0x0D # U+0x0000 + '.notdef', # C+0x0E # U+0x0000 + '.notdef', # C+0x0F # U+0x0000 + '.notdef', # C+0x10 # U+0x0000 + '.notdef', # C+0x11 # U+0x0000 + '.notdef', # C+0x12 # U+0x0000 + '.notdef', # C+0x13 # U+0x0000 + '.notdef', # C+0x14 # U+0x0000 + '.notdef', # C+0x15 # U+0x0000 + '.notdef', # C+0x16 # U+0x0000 + '.notdef', # C+0x17 # U+0x0000 + '.notdef', # C+0x18 # U+0x0000 + '.notdef', # C+0x19 # U+0x0000 + '.notdef', # C+0x1A # U+0x0000 + '.notdef', # C+0x1B # U+0x0000 + '.notdef', # C+0x1C # U+0x0000 + '.notdef', # C+0x1D # U+0x0000 + '.notdef', # C+0x1E # U+0x0000 + '.notdef', # C+0x1F # U+0x0000 + 'space', # C+0x20 # U+0x0020 + 'exclam', # C+0x21 # U+0x0021 + 'quotedbl', # C+0x22 # U+0x0022 + 'numbersign', # C+0x23 # U+0x0023 + 'dollar', # C+0x24 # U+0x0024 + 'percent', # C+0x25 # U+0x0025 + 'ampersand', # C+0x26 # U+0x0026 + 'quotesingle', # C+0x27 # U+0x0027 + 'parenleft', # C+0x28 # U+0x0028 + 'parenright', # C+0x29 # U+0x0029 + 'asterisk', # C+0x2A # U+0x002A + 'plus', # C+0x2B # U+0x002B + 'comma', # C+0x2C # U+0x002C + 'hyphen', # C+0x2D # U+0x002D + 'period', # C+0x2E # U+0x002E + 'slash', # C+0x2F # U+0x002F + 'zero', # C+0x30 # U+0x0030 + 'one', # C+0x31 # U+0x0031 + 'two', # C+0x32 # U+0x0032 + 'three', # C+0x33 # U+0x0033 + 'four', # C+0x34 # U+0x0034 + 'five', # C+0x35 # U+0x0035 + 'six', # C+0x36 # U+0x0036 + 'seven', # C+0x37 # U+0x0037 + 'eight', # C+0x38 # U+0x0038 + 'nine', # C+0x39 # U+0x0039 + 'colon', # C+0x3A # U+0x003A + 'semicolon', # C+0x3B # U+0x003B + 'less', # C+0x3C # U+0x003C + 'equal', # C+0x3D # U+0x003D + 'greater', # C+0x3E # U+0x003E + 'question', # C+0x3F # U+0x003F + 'at', # C+0x40 # U+0x0040 + 'A', # C+0x41 # U+0x0041 + 'B', # C+0x42 # U+0x0042 + 'C', # C+0x43 # U+0x0043 + 'D', # C+0x44 # U+0x0044 + 'E', # C+0x45 # U+0x0045 + 'F', # C+0x46 # U+0x0046 + 'G', # C+0x47 # U+0x0047 + 'H', # C+0x48 # U+0x0048 + 'I', # C+0x49 # U+0x0049 + 'J', # C+0x4A # U+0x004A + 'K', # C+0x4B # U+0x004B + 'L', # C+0x4C # U+0x004C + 'M', # C+0x4D # U+0x004D + 'N', # C+0x4E # U+0x004E + 'O', # C+0x4F # U+0x004F + 'P', # C+0x50 # U+0x0050 + 'Q', # C+0x51 # U+0x0051 + 'R', # C+0x52 # U+0x0052 + 'S', # C+0x53 # U+0x0053 + 'T', # C+0x54 # U+0x0054 + 'U', # C+0x55 # U+0x0055 + 'V', # C+0x56 # U+0x0056 + 'W', # C+0x57 # U+0x0057 + 'X', # C+0x58 # U+0x0058 + 'Y', # C+0x59 # U+0x0059 + 'Z', # C+0x5A # U+0x005A + 'bracketleft', # C+0x5B # U+0x005B + 'backslash', # C+0x5C # U+0x005C + 'bracketright', # C+0x5D # U+0x005D + 'asciicircum', # C+0x5E # U+0x005E + 'underscore', # C+0x5F # U+0x005F + 'grave', # C+0x60 # U+0x0060 + 'a', # C+0x61 # U+0x0061 + 'b', # C+0x62 # U+0x0062 + 'c', # C+0x63 # U+0x0063 + 'd', # C+0x64 # U+0x0064 + 'e', # C+0x65 # U+0x0065 + 'f', # C+0x66 # U+0x0066 + 'g', # C+0x67 # U+0x0067 + 'h', # C+0x68 # U+0x0068 + 'i', # C+0x69 # U+0x0069 + 'j', # C+0x6A # U+0x006A + 'k', # C+0x6B # U+0x006B + 'l', # C+0x6C # U+0x006C + 'm', # C+0x6D # U+0x006D + 'n', # C+0x6E # U+0x006E + 'o', # C+0x6F # U+0x006F + 'p', # C+0x70 # U+0x0070 + 'q', # C+0x71 # U+0x0071 + 'r', # C+0x72 # U+0x0072 + 's', # C+0x73 # U+0x0073 + 't', # C+0x74 # U+0x0074 + 'u', # C+0x75 # U+0x0075 + 'v', # C+0x76 # U+0x0076 + 'w', # C+0x77 # U+0x0077 + 'x', # C+0x78 # U+0x0078 + 'y', # C+0x79 # U+0x0079 + 'z', # C+0x7A # U+0x007A + 'braceleft', # C+0x7B # U+0x007B + 'bar', # C+0x7C # U+0x007C + 'braceright', # C+0x7D # U+0x007D + 'asciitilde', # C+0x7E # U+0x007E + 'bullet', # C+0x7F # U+0x2022 + 'Euro', # C+0x80 # U+0x20AC + 'bullet', # C+0x81 # U+0x2022 + 'quotesinglbase', # C+0x82 # U+0x201A + 'florin', # C+0x83 # U+0x0192 + 'quotedblbase', # C+0x84 # U+0x201E + 'ellipsis', # C+0x85 # U+0x2026 + 'dagger', # C+0x86 # U+0x2020 + 'daggerdbl', # C+0x87 # U+0x2021 + 'circumflex', # C+0x88 # U+0x02C6 + 'perthousand', # C+0x89 # U+0x2030 + 'Scaron', # C+0x8A # U+0x0160 + 'guilsinglleft', # C+0x8B # U+0x2039 + 'OE', # C+0x8C # U+0x0152 + 'bullet', # C+0x8D # U+0x2022 + 'Zcaron', # C+0x8E # U+0x017D + 'bullet', # C+0x8F # U+0x2022 + 'bullet', # C+0x90 # U+0x2022 + 'quoteleft', # C+0x91 # U+0x2018 + 'quoteright', # C+0x92 # U+0x2019 + 'quotedblleft', # C+0x93 # U+0x201C + 'quotedblright', # C+0x94 # U+0x201D + 'bullet', # C+0x95 # U+0x2022 + 'endash', # C+0x96 # U+0x2013 + 'emdash', # C+0x97 # U+0x2014 + 'tilde', # C+0x98 # U+0x02DC + 'trademark', # C+0x99 # U+0x2122 + 'scaron', # C+0x9A # U+0x0161 + 'guilsinglright', # C+0x9B # U+0x203A + 'oe', # C+0x9C # U+0x0153 + 'bullet', # C+0x9D # U+0x2022 + 'zcaron', # C+0x9E # U+0x017E + 'Ydieresis', # C+0x9F # U+0x0178 + 'space', # C+0xA0 # U+0x0020 + 'exclamdown', # C+0xA1 # U+0x00A1 + 'cent', # C+0xA2 # U+0x00A2 + 'sterling', # C+0xA3 # U+0x00A3 + 'currency', # C+0xA4 # U+0x00A4 + 'yen', # C+0xA5 # U+0x00A5 + 'brokenbar', # C+0xA6 # U+0x00A6 + 'section', # C+0xA7 # U+0x00A7 + 'dieresis', # C+0xA8 # U+0x00A8 + 'copyright', # C+0xA9 # U+0x00A9 + 'ordfeminine', # C+0xAA # U+0x00AA + 'guillemotleft', # C+0xAB # U+0x00AB + 'logicalnot', # C+0xAC # U+0x00AC + 'hyphen', # C+0xAD # U+0x002D + 'registered', # C+0xAE # U+0x00AE + 'macron', # C+0xAF # U+0x00AF + 'degree', # C+0xB0 # U+0x00B0 + 'plusminus', # C+0xB1 # U+0x00B1 + 'twosuperior', # C+0xB2 # U+0x00B2 + 'threesuperior', # C+0xB3 # U+0x00B3 + 'acute', # C+0xB4 # U+0x00B4 + 'mu', # C+0xB5 # U+0x00B5 + 'paragraph', # C+0xB6 # U+0x00B6 + 'periodcentered', # C+0xB7 # U+0x00B7 + 'cedilla', # C+0xB8 # U+0x00B8 + 'onesuperior', # C+0xB9 # U+0x00B9 + 'ordmasculine', # C+0xBA # U+0x00BA + 'guillemotright', # C+0xBB # U+0x00BB + 'onequarter', # C+0xBC # U+0x00BC + 'onehalf', # C+0xBD # U+0x00BD + 'threequarters', # C+0xBE # U+0x00BE + 'questiondown', # C+0xBF # U+0x00BF + 'Agrave', # C+0xC0 # U+0x00C0 + 'Aacute', # C+0xC1 # U+0x00C1 + 'Acircumflex', # C+0xC2 # U+0x00C2 + 'Atilde', # C+0xC3 # U+0x00C3 + 'Adieresis', # C+0xC4 # U+0x00C4 + 'Aring', # C+0xC5 # U+0x00C5 + 'AE', # C+0xC6 # U+0x00C6 + 'Ccedilla', # C+0xC7 # U+0x00C7 + 'Egrave', # C+0xC8 # U+0x00C8 + 'Eacute', # C+0xC9 # U+0x00C9 + 'Ecircumflex', # C+0xCA # U+0x00CA + 'Edieresis', # C+0xCB # U+0x00CB + 'Igrave', # C+0xCC # U+0x00CC + 'Iacute', # C+0xCD # U+0x00CD + 'Icircumflex', # C+0xCE # U+0x00CE + 'Idieresis', # C+0xCF # U+0x00CF + 'Eth', # C+0xD0 # U+0x00D0 + 'Ntilde', # C+0xD1 # U+0x00D1 + 'Ograve', # C+0xD2 # U+0x00D2 + 'Oacute', # C+0xD3 # U+0x00D3 + 'Ocircumflex', # C+0xD4 # U+0x00D4 + 'Otilde', # C+0xD5 # U+0x00D5 + 'Odieresis', # C+0xD6 # U+0x00D6 + 'multiply', # C+0xD7 # U+0x00D7 + 'Oslash', # C+0xD8 # U+0x00D8 + 'Ugrave', # C+0xD9 # U+0x00D9 + 'Uacute', # C+0xDA # U+0x00DA + 'Ucircumflex', # C+0xDB # U+0x00DB + 'Udieresis', # C+0xDC # U+0x00DC + 'Yacute', # C+0xDD # U+0x00DD + 'Thorn', # C+0xDE # U+0x00DE + 'germandbls', # C+0xDF # U+0x00DF + 'agrave', # C+0xE0 # U+0x00E0 + 'aacute', # C+0xE1 # U+0x00E1 + 'acircumflex', # C+0xE2 # U+0x00E2 + 'atilde', # C+0xE3 # U+0x00E3 + 'adieresis', # C+0xE4 # U+0x00E4 + 'aring', # C+0xE5 # U+0x00E5 + 'ae', # C+0xE6 # U+0x00E6 + 'ccedilla', # C+0xE7 # U+0x00E7 + 'egrave', # C+0xE8 # U+0x00E8 + 'eacute', # C+0xE9 # U+0x00E9 + 'ecircumflex', # C+0xEA # U+0x00EA + 'edieresis', # C+0xEB # U+0x00EB + 'igrave', # C+0xEC # U+0x00EC + 'iacute', # C+0xED # U+0x00ED + 'icircumflex', # C+0xEE # U+0x00EE + 'idieresis', # C+0xEF # U+0x00EF + 'eth', # C+0xF0 # U+0x00F0 + 'ntilde', # C+0xF1 # U+0x00F1 + 'ograve', # C+0xF2 # U+0x00F2 + 'oacute', # C+0xF3 # U+0x00F3 + 'ocircumflex', # C+0xF4 # U+0x00F4 + 'otilde', # C+0xF5 # U+0x00F5 + 'odieresis', # C+0xF6 # U+0x00F6 + 'divide', # C+0xF7 # U+0x00F7 + 'oslash', # C+0xF8 # U+0x00F8 + 'ugrave', # C+0xF9 # U+0x00F9 + 'uacute', # C+0xFA # U+0x00FA + 'ucircumflex', # C+0xFB # U+0x00FB + 'udieresis', # C+0xFC # U+0x00FC + 'yacute', # C+0xFD # U+0x00FD + 'thorn', # C+0xFE # U+0x00FE + 'ydieresis', # C+0xFF # U+0x00FF + ], # DEF. ENCODING GLYPH TABLE + 'fontbbox' => [ -85, -262, 1082, 942 ], + 'wx' => { # HORIZ. WIDTH TABLE + 'space' => '301', # C+0x20 # U+0x0020 + 'exclam' => '367', # C+0x21 # U+0x0021 + 'quotedbl' => '324', # C+0x22 # U+0x0022 + 'numbersign' => '524', # C+0x23 # U+0x0023 + 'dollar' => '524', # C+0x24 # U+0x0024 + 'percent' => '600', # C+0x25 # U+0x0025 + 'ampersand' => '706', # C+0x26 # U+0x0026 + 'quotesingle' => '159', # C+0x27 # U+0x0027 + 'parenleft' => '367', # C+0x28 # U+0x0028 + 'parenright' => '367', # C+0x29 # U+0x0029 + 'asterisk' => '367', # C+0x2A # U+0x002A + 'plus' => '524', # C+0x2B # U+0x002B + 'comma' => '367', # C+0x2C # U+0x002C + 'hyphen' => '367', # C+0x2D # U+0x002D + 'period' => '367', # C+0x2E # U+0x002E + 'slash' => '524', # C+0x2F # U+0x002F + 'zero' => '524', # C+0x30 # U+0x0030 + 'one' => '524', # C+0x31 # U+0x0031 + 'two' => '524', # C+0x32 # U+0x0032 + 'three' => '524', # C+0x33 # U+0x0033 + 'four' => '524', # C+0x34 # U+0x0034 + 'five' => '524', # C+0x35 # U+0x0035 + 'six' => '524', # C+0x36 # U+0x0036 + 'seven' => '524', # C+0x37 # U+0x0037 + 'eight' => '524', # C+0x38 # U+0x0038 + 'nine' => '524', # C+0x39 # U+0x0039 + 'colon' => '367', # C+0x3A # U+0x003A + 'semicolon' => '367', # C+0x3B # U+0x003B + 'less' => '524', # C+0x3C # U+0x003C + 'equal' => '524', # C+0x3D # U+0x003D + 'greater' => '524', # C+0x3E # U+0x003E + 'question' => '367', # C+0x3F # U+0x003F + 'at' => '770', # C+0x40 # U+0x0040 + 'A' => '589', # C+0x41 # U+0x0041 + 'B' => '565', # C+0x42 # U+0x0042 + 'C' => '598', # C+0x43 # U+0x0043 + 'D' => '613', # C+0x44 # U+0x0044 + 'E' => '535', # C+0x45 # U+0x0045 + 'F' => '524', # C+0x46 # U+0x0046 + 'G' => '676', # C+0x47 # U+0x0047 + 'H' => '654', # C+0x48 # U+0x0048 + 'I' => '278', # C+0x49 # U+0x0049 + 'J' => '476', # C+0x4A # U+0x004A + 'K' => '575', # C+0x4B # U+0x004B + 'L' => '506', # C+0x4C # U+0x004C + 'M' => '709', # C+0x4D # U+0x004D + 'N' => '638', # C+0x4E # U+0x004E + 'O' => '673', # C+0x4F # U+0x004F + 'P' => '557', # C+0x50 # U+0x0050 + 'Q' => '675', # C+0x51 # U+0x0051 + 'R' => '582', # C+0x52 # U+0x0052 + 'S' => '480', # C+0x53 # U+0x0053 + 'T' => '580', # C+0x54 # U+0x0054 + 'U' => '648', # C+0x55 # U+0x0055 + 'V' => '587', # C+0x56 # U+0x0056 + 'W' => '852', # C+0x57 # U+0x0057 + 'X' => '556', # C+0x58 # U+0x0058 + 'Y' => '570', # C+0x59 # U+0x0059 + 'Z' => '550', # C+0x5A # U+0x005A + 'bracketleft' => '367', # C+0x5B # U+0x005B + 'backslash' => '355', # C+0x5C # U+0x005C + 'bracketright' => '367', # C+0x5D # U+0x005D + 'asciicircum' => '524', # C+0x5E # U+0x005E + 'underscore' => '524', # C+0x5F # U+0x005F + 'grave' => '524', # C+0x60 # U+0x0060 + 'a' => '525', # C+0x61 # U+0x0061 + 'b' => '557', # C+0x62 # U+0x0062 + 'c' => '495', # C+0x63 # U+0x0063 + 'd' => '557', # C+0x64 # U+0x0064 + 'e' => '545', # C+0x65 # U+0x0065 + 'f' => '369', # C+0x66 # U+0x0066 + 'g' => '501', # C+0x67 # U+0x0067 + 'h' => '546', # C+0x68 # U+0x0068 + 'i' => '285', # C+0x69 # U+0x0069 + 'j' => '366', # C+0x6A # U+0x006A + 'k' => '504', # C+0x6B # U+0x006B + 'l' => '294', # C+0x6C # U+0x006C + 'm' => '830', # C+0x6D # U+0x006D + 'n' => '546', # C+0x6E # U+0x006E + 'o' => '536', # C+0x6F # U+0x006F + 'p' => '557', # C+0x70 # U+0x0070 + 'q' => '557', # C+0x71 # U+0x0071 + 'r' => '388', # C+0x72 # U+0x0072 + 's' => '404', # C+0x73 # U+0x0073 + 't' => '396', # C+0x74 # U+0x0074 + 'u' => '546', # C+0x75 # U+0x0075 + 'v' => '489', # C+0x76 # U+0x0076 + 'w' => '744', # C+0x77 # U+0x0077 + 'x' => '500', # C+0x78 # U+0x0078 + 'y' => '493', # C+0x79 # U+0x0079 + 'z' => '474', # C+0x7A # U+0x007A + 'braceleft' => '367', # C+0x7B # U+0x007B + 'bar' => '524', # C+0x7C # U+0x007C + 'braceright' => '367', # C+0x7D # U+0x007D + 'asciitilde' => '524', # C+0x7E # U+0x007E + 'bullet' => '524', # C+0x7F # U+0x2022 + 'Euro' => '524', # C+0x80 # U+0x20AC + 'quotesinglbase' => '367', # C+0x82 # U+0x201A + 'florin' => '388', # C+0x83 # U+0x0192 + 'quotedblbase' => '524', # C+0x84 # U+0x201E + 'ellipsis' => '734', # C+0x85 # U+0x2026 + 'dagger' => '458', # C+0x86 # U+0x2020 + 'daggerdbl' => '458', # C+0x87 # U+0x2021 + 'circumflex' => '524', # C+0x88 # U+0x02C6 + 'perthousand' => '912', # C+0x89 # U+0x2030 + 'Scaron' => '480', # C+0x8A # U+0x0160 + 'guilsinglleft' => '367', # C+0x8B # U+0x2039 + 'OE' => '993', # C+0x8C # U+0x0152 + 'Zcaron' => '550', # C+0x8E # U+0x017D + 'quoteleft' => '367', # C+0x91 # U+0x2018 + 'quoteright' => '367', # C+0x92 # U+0x2019 + 'quotedblleft' => '524', # C+0x93 # U+0x201C + 'quotedblright' => '524', # C+0x94 # U+0x201D + 'endash' => '367', # C+0x96 # U+0x2013 + 'emdash' => '734', # C+0x97 # U+0x2014 + 'tilde' => '524', # C+0x98 # U+0x02DC + 'trademark' => '634', # C+0x99 # U+0x2122 + 'scaron' => '404', # C+0x9A # U+0x0161 + 'guilsinglright' => '367', # C+0x9B # U+0x203A + 'oe' => '924', # C+0x9C # U+0x0153 + 'zcaron' => '474', # C+0x9E # U+0x017E + 'Ydieresis' => '570', # C+0x9F # U+0x0178 + 'exclamdown' => '367', # C+0xA1 # U+0x00A1 + 'cent' => '524', # C+0xA2 # U+0x00A2 + 'sterling' => '524', # C+0xA3 # U+0x00A3 + 'currency' => '524', # C+0xA4 # U+0x00A4 + 'yen' => '570', # C+0xA5 # U+0x00A5 + 'brokenbar' => '524', # C+0xA6 # U+0x00A6 + 'section' => '453', # C+0xA7 # U+0x00A7 + 'dieresis' => '524', # C+0xA8 # U+0x00A8 + 'copyright' => '712', # C+0xA9 # U+0x00A9 + 'ordfeminine' => '367', # C+0xAA # U+0x00AA + 'guillemotleft' => '524', # C+0xAB # U+0x00AB + 'logicalnot' => '524', # C+0xAC # U+0x00AC + 'registered' => '712', # C+0xAE # U+0x00AE + 'macron' => '524', # C+0xAF # U+0x00AF + 'degree' => '524', # C+0xB0 # U+0x00B0 + 'plusminus' => '524', # C+0xB1 # U+0x00B1 + 'twosuperior' => '451', # C+0xB2 # U+0x00B2 + 'threesuperior' => '453', # C+0xB3 # U+0x00B3 + 'acute' => '524', # C+0xB4 # U+0x00B4 + 'mu' => '546', # C+0xB5 # U+0x00B5 + 'paragraph' => '524', # C+0xB6 # U+0x00B6 + 'periodcentered' => '367', # C+0xB7 # U+0x00B7 + 'cedilla' => '524', # C+0xB8 # U+0x00B8 + 'onesuperior' => '451', # C+0xB9 # U+0x00B9 + 'ordmasculine' => '367', # C+0xBA # U+0x00BA + 'guillemotright' => '524', # C+0xBB # U+0x00BB + 'onequarter' => '814', # C+0xBC # U+0x00BC + 'onehalf' => '814', # C+0xBD # U+0x00BD + 'threequarters' => '814', # C+0xBE # U+0x00BE + 'questiondown' => '367', # C+0xBF # U+0x00BF + 'Agrave' => '589', # C+0xC0 # U+0x00C0 + 'Aacute' => '589', # C+0xC1 # U+0x00C1 + 'Acircumflex' => '589', # C+0xC2 # U+0x00C2 + 'Atilde' => '589', # C+0xC3 # U+0x00C3 + 'Adieresis' => '589', # C+0xC4 # U+0x00C4 + 'Aring' => '589', # C+0xC5 # U+0x00C5 + 'AE' => '866', # C+0xC6 # U+0x00C6 + 'Ccedilla' => '598', # C+0xC7 # U+0x00C7 + 'Egrave' => '535', # C+0xC8 # U+0x00C8 + 'Eacute' => '535', # C+0xC9 # U+0x00C9 + 'Ecircumflex' => '535', # C+0xCA # U+0x00CA + 'Edieresis' => '535', # C+0xCB # U+0x00CB + 'Igrave' => '278', # C+0xCC # U+0x00CC + 'Iacute' => '278', # C+0xCD # U+0x00CD + 'Icircumflex' => '278', # C+0xCE # U+0x00CE + 'Idieresis' => '278', # C+0xCF # U+0x00CF + 'Eth' => '613', # C+0xD0 # U+0x00D0 + 'Ntilde' => '638', # C+0xD1 # U+0x00D1 + 'Ograve' => '673', # C+0xD2 # U+0x00D2 + 'Oacute' => '673', # C+0xD3 # U+0x00D3 + 'Ocircumflex' => '673', # C+0xD4 # U+0x00D4 + 'Otilde' => '673', # C+0xD5 # U+0x00D5 + 'Odieresis' => '673', # C+0xD6 # U+0x00D6 + 'multiply' => '524', # C+0xD7 # U+0x00D7 + 'Oslash' => '656', # C+0xD8 # U+0x00D8 + 'Ugrave' => '648', # C+0xD9 # U+0x00D9 + 'Uacute' => '648', # C+0xDA # U+0x00DA + 'Ucircumflex' => '648', # C+0xDB # U+0x00DB + 'Udieresis' => '648', # C+0xDC # U+0x00DC + 'Yacute' => '570', # C+0xDD # U+0x00DD + 'Thorn' => '555', # C+0xDE # U+0x00DE + 'germandbls' => '546', # C+0xDF # U+0x00DF + 'agrave' => '525', # C+0xE0 # U+0x00E0 + 'aacute' => '525', # C+0xE1 # U+0x00E1 + 'acircumflex' => '525', # C+0xE2 # U+0x00E2 + 'atilde' => '525', # C+0xE3 # U+0x00E3 + 'adieresis' => '525', # C+0xE4 # U+0x00E4 + 'aring' => '525', # C+0xE5 # U+0x00E5 + 'ae' => '873', # C+0xE6 # U+0x00E6 + 'ccedilla' => '495', # C+0xE7 # U+0x00E7 + 'egrave' => '545', # C+0xE8 # U+0x00E8 + 'eacute' => '545', # C+0xE9 # U+0x00E9 + 'ecircumflex' => '545', # C+0xEA # U+0x00EA + 'edieresis' => '545', # C+0xEB # U+0x00EB + 'igrave' => '285', # C+0xEC # U+0x00EC + 'iacute' => '285', # C+0xED # U+0x00ED + 'icircumflex' => '285', # C+0xEE # U+0x00EE + 'idieresis' => '285', # C+0xEF # U+0x00EF + 'eth' => '549', # C+0xF0 # U+0x00F0 + 'ntilde' => '546', # C+0xF1 # U+0x00F1 + 'ograve' => '536', # C+0xF2 # U+0x00F2 + 'oacute' => '536', # C+0xF3 # U+0x00F3 + 'ocircumflex' => '536', # C+0xF4 # U+0x00F4 + 'otilde' => '536', # C+0xF5 # U+0x00F5 + 'odieresis' => '536', # C+0xF6 # U+0x00F6 + 'divide' => '524', # C+0xF7 # U+0x00F7 + 'oslash' => '545', # C+0xF8 # U+0x00F8 + 'ugrave' => '546', # C+0xF9 # U+0x00F9 + 'uacute' => '546', # C+0xFA # U+0x00FA + 'ucircumflex' => '546', # C+0xFB # U+0x00FB + 'udieresis' => '546', # C+0xFC # U+0x00FC + 'yacute' => '493', # C+0xFD # U+0x00FD + 'thorn' => '553', # C+0xFE # U+0x00FE + 'ydieresis' => '493', # C+0xFF # U+0x00FF + 'middot' => '367', # U+0x00B7 + 'Abreve' => '589', # U+0x0102 + 'abreve' => '525', # U+0x0103 + 'Aogonek' => '589', # U+0x0104 + 'aogonek' => '525', # U+0x0105 + 'Cacute' => '598', # U+0x0106 + 'cacute' => '495', # U+0x0107 + 'Ccaron' => '598', # U+0x010C + 'ccaron' => '495', # U+0x010D + 'Dcaron' => '613', # U+0x010E + 'dcaron' => '691', # U+0x010F + 'Eogonek' => '535', # U+0x0118 + 'eogonek' => '545', # U+0x0119 + 'Ecaron' => '535', # U+0x011A + 'ecaron' => '545', # U+0x011B + 'Gbreve' => '676', # U+0x011E + 'gbreve' => '501', # U+0x011F + 'dotlessi' => '285', # U+0x0131 + 'Lacute' => '506', # U+0x0139 + 'lacute' => '294', # U+0x013A + 'Lcaron' => '506', # U+0x013D + 'lcaron' => '294', # U+0x013E + 'Ldot' => '506', # U+0x013F + 'ldot' => '329', # U+0x0140 + 'Lslash' => '506', # U+0x0141 + 'lslash' => '297', # U+0x0142 + 'Nacute' => '638', # U+0x0143 + 'nacute' => '546', # U+0x0144 + 'Ncaron' => '638', # U+0x0147 + 'ncaron' => '546', # U+0x0148 + 'Racute' => '582', # U+0x0154 + 'racute' => '388', # U+0x0155 + 'Rcaron' => '582', # U+0x0158 + 'rcaron' => '388', # U+0x0159 + 'Sacute' => '480', # U+0x015A + 'sacute' => '404', # U+0x015B + 'Scedilla' => '480', # U+0x015E + 'scedilla' => '404', # U+0x015F + 'Tcaron' => '580', # U+0x0164 + 'tcaron' => '496', # U+0x0165 + 'Uring' => '648', # U+0x016E + 'uring' => '546', # U+0x016F + 'Zacute' => '550', # U+0x0179 + 'zacute' => '474', # U+0x017A + 'Zdot' => '550', # U+0x017B + 'zdot' => '474', # U+0x017C + 'caron' => '524', # U+0x02C7 + 'breve' => '524', # U+0x02D8 + 'dotaccent' => '524', # U+0x02D9 + 'ring' => '524', # U+0x02DA + 'ogonek' => '524', # U+0x02DB + 'hungarumlaut' => '524', # U+0x02DD + 'Delta' => '584', # U+0x0394 + 'Omega' => '668', # U+0x03A9 + 'pi' => '601', # U+0x03C0 + 'fraction' => '528', # U+0x2044 + 'franc' => '524', # U+0x20A3 + 'partialdiff' => '549', # U+0x2202 + 'product' => '552', # U+0x220F + 'summation' => '524', # U+0x2211 + 'minus' => '524', # U+0x2212 + 'radical' => '524', # U+0x221A + 'infinity' => '524', # U+0x221E + 'integral' => '524', # U+0x222B + 'approxequal' => '524', # U+0x2248 + 'notequal' => '524', # U+0x2260 + 'lessequal' => '524', # U+0x2264 + 'greaterequal' => '524', # U+0x2265 + 'lozenge' => '494', # U+0x25CA + 'dotlessj' => '366', # U+0xF6BE + 'fi' => '579', # U+0xFB01 + 'fl' => '600', # U+0xFB02 + }, # HORIZ. WIDTH TABLE +} }; + +1; diff --git a/lib/PDF/API2/Resource/Font/CoreFont/trebuchetbold.pm b/lib/PDF/API2/Resource/Font/CoreFont/trebuchetbold.pm new file mode 100644 index 0000000..9134a2e --- /dev/null +++ b/lib/PDF/API2/Resource/Font/CoreFont/trebuchetbold.pm @@ -0,0 +1,577 @@ +#line 1 "PDF/API2/Resource/Font/CoreFont/trebuchetbold.pm" +#line 1 "PDF/API2/Resource/Font/CoreFont/trebuchetbold.pm" +package PDF::API2::Resource::Font::CoreFont::trebuchetbold; + +use strict; +use warnings; + +our $VERSION = '2.033'; # VERSION + +sub data { return { + 'fontname' => 'TrebuchetMS,Bold', + 'type' => 'TrueType', + 'apiname' => 'TrBo', + 'ascender' => '938', + 'capheight' => '715', + 'descender' => '-222', + 'isfixedpitch' => '0', + 'issymbol' => '0', + 'italicangle' => '0', + 'underlineposition' => '-261', + 'underlinethickness' => '200', + 'xheight' => '522', + 'firstchar' => '32', + 'lastchar' => '255', + 'flags' => '262178', + 'char' => [ # DEF. ENCODING GLYPH TABLE + '.notdef', # C+0x00 # U+0x0000 + '.notdef', # C+0x01 # U+0x0000 + '.notdef', # C+0x02 # U+0x0000 + '.notdef', # C+0x03 # U+0x0000 + '.notdef', # C+0x04 # U+0x0000 + '.notdef', # C+0x05 # U+0x0000 + '.notdef', # C+0x06 # U+0x0000 + '.notdef', # C+0x07 # U+0x0000 + '.notdef', # C+0x08 # U+0x0000 + '.notdef', # C+0x09 # U+0x0000 + '.notdef', # C+0x0A # U+0x0000 + '.notdef', # C+0x0B # U+0x0000 + '.notdef', # C+0x0C # U+0x0000 + '.notdef', # C+0x0D # U+0x0000 + '.notdef', # C+0x0E # U+0x0000 + '.notdef', # C+0x0F # U+0x0000 + '.notdef', # C+0x10 # U+0x0000 + '.notdef', # C+0x11 # U+0x0000 + '.notdef', # C+0x12 # U+0x0000 + '.notdef', # C+0x13 # U+0x0000 + '.notdef', # C+0x14 # U+0x0000 + '.notdef', # C+0x15 # U+0x0000 + '.notdef', # C+0x16 # U+0x0000 + '.notdef', # C+0x17 # U+0x0000 + '.notdef', # C+0x18 # U+0x0000 + '.notdef', # C+0x19 # U+0x0000 + '.notdef', # C+0x1A # U+0x0000 + '.notdef', # C+0x1B # U+0x0000 + '.notdef', # C+0x1C # U+0x0000 + '.notdef', # C+0x1D # U+0x0000 + '.notdef', # C+0x1E # U+0x0000 + '.notdef', # C+0x1F # U+0x0000 + 'space', # C+0x20 # U+0x0020 + 'exclam', # C+0x21 # U+0x0021 + 'quotedbl', # C+0x22 # U+0x0022 + 'numbersign', # C+0x23 # U+0x0023 + 'dollar', # C+0x24 # U+0x0024 + 'percent', # C+0x25 # U+0x0025 + 'ampersand', # C+0x26 # U+0x0026 + 'quotesingle', # C+0x27 # U+0x0027 + 'parenleft', # C+0x28 # U+0x0028 + 'parenright', # C+0x29 # U+0x0029 + 'asterisk', # C+0x2A # U+0x002A + 'plus', # C+0x2B # U+0x002B + 'comma', # C+0x2C # U+0x002C + 'hyphen', # C+0x2D # U+0x002D + 'period', # C+0x2E # U+0x002E + 'slash', # C+0x2F # U+0x002F + 'zero', # C+0x30 # U+0x0030 + 'one', # C+0x31 # U+0x0031 + 'two', # C+0x32 # U+0x0032 + 'three', # C+0x33 # U+0x0033 + 'four', # C+0x34 # U+0x0034 + 'five', # C+0x35 # U+0x0035 + 'six', # C+0x36 # U+0x0036 + 'seven', # C+0x37 # U+0x0037 + 'eight', # C+0x38 # U+0x0038 + 'nine', # C+0x39 # U+0x0039 + 'colon', # C+0x3A # U+0x003A + 'semicolon', # C+0x3B # U+0x003B + 'less', # C+0x3C # U+0x003C + 'equal', # C+0x3D # U+0x003D + 'greater', # C+0x3E # U+0x003E + 'question', # C+0x3F # U+0x003F + 'at', # C+0x40 # U+0x0040 + 'A', # C+0x41 # U+0x0041 + 'B', # C+0x42 # U+0x0042 + 'C', # C+0x43 # U+0x0043 + 'D', # C+0x44 # U+0x0044 + 'E', # C+0x45 # U+0x0045 + 'F', # C+0x46 # U+0x0046 + 'G', # C+0x47 # U+0x0047 + 'H', # C+0x48 # U+0x0048 + 'I', # C+0x49 # U+0x0049 + 'J', # C+0x4A # U+0x004A + 'K', # C+0x4B # U+0x004B + 'L', # C+0x4C # U+0x004C + 'M', # C+0x4D # U+0x004D + 'N', # C+0x4E # U+0x004E + 'O', # C+0x4F # U+0x004F + 'P', # C+0x50 # U+0x0050 + 'Q', # C+0x51 # U+0x0051 + 'R', # C+0x52 # U+0x0052 + 'S', # C+0x53 # U+0x0053 + 'T', # C+0x54 # U+0x0054 + 'U', # C+0x55 # U+0x0055 + 'V', # C+0x56 # U+0x0056 + 'W', # C+0x57 # U+0x0057 + 'X', # C+0x58 # U+0x0058 + 'Y', # C+0x59 # U+0x0059 + 'Z', # C+0x5A # U+0x005A + 'bracketleft', # C+0x5B # U+0x005B + 'backslash', # C+0x5C # U+0x005C + 'bracketright', # C+0x5D # U+0x005D + 'asciicircum', # C+0x5E # U+0x005E + 'underscore', # C+0x5F # U+0x005F + 'grave', # C+0x60 # U+0x0060 + 'a', # C+0x61 # U+0x0061 + 'b', # C+0x62 # U+0x0062 + 'c', # C+0x63 # U+0x0063 + 'd', # C+0x64 # U+0x0064 + 'e', # C+0x65 # U+0x0065 + 'f', # C+0x66 # U+0x0066 + 'g', # C+0x67 # U+0x0067 + 'h', # C+0x68 # U+0x0068 + 'i', # C+0x69 # U+0x0069 + 'j', # C+0x6A # U+0x006A + 'k', # C+0x6B # U+0x006B + 'l', # C+0x6C # U+0x006C + 'm', # C+0x6D # U+0x006D + 'n', # C+0x6E # U+0x006E + 'o', # C+0x6F # U+0x006F + 'p', # C+0x70 # U+0x0070 + 'q', # C+0x71 # U+0x0071 + 'r', # C+0x72 # U+0x0072 + 's', # C+0x73 # U+0x0073 + 't', # C+0x74 # U+0x0074 + 'u', # C+0x75 # U+0x0075 + 'v', # C+0x76 # U+0x0076 + 'w', # C+0x77 # U+0x0077 + 'x', # C+0x78 # U+0x0078 + 'y', # C+0x79 # U+0x0079 + 'z', # C+0x7A # U+0x007A + 'braceleft', # C+0x7B # U+0x007B + 'bar', # C+0x7C # U+0x007C + 'braceright', # C+0x7D # U+0x007D + 'asciitilde', # C+0x7E # U+0x007E + 'bullet', # C+0x7F # U+0x2022 + 'Euro', # C+0x80 # U+0x20AC + 'bullet', # C+0x81 # U+0x2022 + 'quotesinglbase', # C+0x82 # U+0x201A + 'florin', # C+0x83 # U+0x0192 + 'quotedblbase', # C+0x84 # U+0x201E + 'ellipsis', # C+0x85 # U+0x2026 + 'dagger', # C+0x86 # U+0x2020 + 'daggerdbl', # C+0x87 # U+0x2021 + 'circumflex', # C+0x88 # U+0x02C6 + 'perthousand', # C+0x89 # U+0x2030 + 'Scaron', # C+0x8A # U+0x0160 + 'guilsinglleft', # C+0x8B # U+0x2039 + 'OE', # C+0x8C # U+0x0152 + 'bullet', # C+0x8D # U+0x2022 + 'Zcaron', # C+0x8E # U+0x017D + 'bullet', # C+0x8F # U+0x2022 + 'bullet', # C+0x90 # U+0x2022 + 'quoteleft', # C+0x91 # U+0x2018 + 'quoteright', # C+0x92 # U+0x2019 + 'quotedblleft', # C+0x93 # U+0x201C + 'quotedblright', # C+0x94 # U+0x201D + 'bullet', # C+0x95 # U+0x2022 + 'endash', # C+0x96 # U+0x2013 + 'emdash', # C+0x97 # U+0x2014 + 'tilde', # C+0x98 # U+0x02DC + 'trademark', # C+0x99 # U+0x2122 + 'scaron', # C+0x9A # U+0x0161 + 'guilsinglright', # C+0x9B # U+0x203A + 'oe', # C+0x9C # U+0x0153 + 'bullet', # C+0x9D # U+0x2022 + 'zcaron', # C+0x9E # U+0x017E + 'Ydieresis', # C+0x9F # U+0x0178 + 'space', # C+0xA0 # U+0x0020 + 'exclamdown', # C+0xA1 # U+0x00A1 + 'cent', # C+0xA2 # U+0x00A2 + 'sterling', # C+0xA3 # U+0x00A3 + 'currency', # C+0xA4 # U+0x00A4 + 'yen', # C+0xA5 # U+0x00A5 + 'brokenbar', # C+0xA6 # U+0x00A6 + 'section', # C+0xA7 # U+0x00A7 + 'dieresis', # C+0xA8 # U+0x00A8 + 'copyright', # C+0xA9 # U+0x00A9 + 'ordfeminine', # C+0xAA # U+0x00AA + 'guillemotleft', # C+0xAB # U+0x00AB + 'logicalnot', # C+0xAC # U+0x00AC + 'hyphen', # C+0xAD # U+0x002D + 'registered', # C+0xAE # U+0x00AE + 'macron', # C+0xAF # U+0x00AF + 'degree', # C+0xB0 # U+0x00B0 + 'plusminus', # C+0xB1 # U+0x00B1 + 'twosuperior', # C+0xB2 # U+0x00B2 + 'threesuperior', # C+0xB3 # U+0x00B3 + 'acute', # C+0xB4 # U+0x00B4 + 'mu', # C+0xB5 # U+0x00B5 + 'paragraph', # C+0xB6 # U+0x00B6 + 'periodcentered', # C+0xB7 # U+0x00B7 + 'cedilla', # C+0xB8 # U+0x00B8 + 'onesuperior', # C+0xB9 # U+0x00B9 + 'ordmasculine', # C+0xBA # U+0x00BA + 'guillemotright', # C+0xBB # U+0x00BB + 'onequarter', # C+0xBC # U+0x00BC + 'onehalf', # C+0xBD # U+0x00BD + 'threequarters', # C+0xBE # U+0x00BE + 'questiondown', # C+0xBF # U+0x00BF + 'Agrave', # C+0xC0 # U+0x00C0 + 'Aacute', # C+0xC1 # U+0x00C1 + 'Acircumflex', # C+0xC2 # U+0x00C2 + 'Atilde', # C+0xC3 # U+0x00C3 + 'Adieresis', # C+0xC4 # U+0x00C4 + 'Aring', # C+0xC5 # U+0x00C5 + 'AE', # C+0xC6 # U+0x00C6 + 'Ccedilla', # C+0xC7 # U+0x00C7 + 'Egrave', # C+0xC8 # U+0x00C8 + 'Eacute', # C+0xC9 # U+0x00C9 + 'Ecircumflex', # C+0xCA # U+0x00CA + 'Edieresis', # C+0xCB # U+0x00CB + 'Igrave', # C+0xCC # U+0x00CC + 'Iacute', # C+0xCD # U+0x00CD + 'Icircumflex', # C+0xCE # U+0x00CE + 'Idieresis', # C+0xCF # U+0x00CF + 'Eth', # C+0xD0 # U+0x00D0 + 'Ntilde', # C+0xD1 # U+0x00D1 + 'Ograve', # C+0xD2 # U+0x00D2 + 'Oacute', # C+0xD3 # U+0x00D3 + 'Ocircumflex', # C+0xD4 # U+0x00D4 + 'Otilde', # C+0xD5 # U+0x00D5 + 'Odieresis', # C+0xD6 # U+0x00D6 + 'multiply', # C+0xD7 # U+0x00D7 + 'Oslash', # C+0xD8 # U+0x00D8 + 'Ugrave', # C+0xD9 # U+0x00D9 + 'Uacute', # C+0xDA # U+0x00DA + 'Ucircumflex', # C+0xDB # U+0x00DB + 'Udieresis', # C+0xDC # U+0x00DC + 'Yacute', # C+0xDD # U+0x00DD + 'Thorn', # C+0xDE # U+0x00DE + 'germandbls', # C+0xDF # U+0x00DF + 'agrave', # C+0xE0 # U+0x00E0 + 'aacute', # C+0xE1 # U+0x00E1 + 'acircumflex', # C+0xE2 # U+0x00E2 + 'atilde', # C+0xE3 # U+0x00E3 + 'adieresis', # C+0xE4 # U+0x00E4 + 'aring', # C+0xE5 # U+0x00E5 + 'ae', # C+0xE6 # U+0x00E6 + 'ccedilla', # C+0xE7 # U+0x00E7 + 'egrave', # C+0xE8 # U+0x00E8 + 'eacute', # C+0xE9 # U+0x00E9 + 'ecircumflex', # C+0xEA # U+0x00EA + 'edieresis', # C+0xEB # U+0x00EB + 'igrave', # C+0xEC # U+0x00EC + 'iacute', # C+0xED # U+0x00ED + 'icircumflex', # C+0xEE # U+0x00EE + 'idieresis', # C+0xEF # U+0x00EF + 'eth', # C+0xF0 # U+0x00F0 + 'ntilde', # C+0xF1 # U+0x00F1 + 'ograve', # C+0xF2 # U+0x00F2 + 'oacute', # C+0xF3 # U+0x00F3 + 'ocircumflex', # C+0xF4 # U+0x00F4 + 'otilde', # C+0xF5 # U+0x00F5 + 'odieresis', # C+0xF6 # U+0x00F6 + 'divide', # C+0xF7 # U+0x00F7 + 'oslash', # C+0xF8 # U+0x00F8 + 'ugrave', # C+0xF9 # U+0x00F9 + 'uacute', # C+0xFA # U+0x00FA + 'ucircumflex', # C+0xFB # U+0x00FB + 'udieresis', # C+0xFC # U+0x00FC + 'yacute', # C+0xFD # U+0x00FD + 'thorn', # C+0xFE # U+0x00FE + 'ydieresis', # C+0xFF # U+0x00FF + ], # DEF. ENCODING GLYPH TABLE + 'fontbbox' => [ -100, -269, 1129, 980 ], + 'wx' => { # HORIZ. WIDTH TABLE + 'space' => '301', # C+0x20 # U+0x0020 + 'exclam' => '367', # C+0x21 # U+0x0021 + 'quotedbl' => '366', # C+0x22 # U+0x0022 + 'numbersign' => '585', # C+0x23 # U+0x0023 + 'dollar' => '585', # C+0x24 # U+0x0024 + 'percent' => '684', # C+0x25 # U+0x0025 + 'ampersand' => '706', # C+0x26 # U+0x0026 + 'quotesingle' => '229', # C+0x27 # U+0x0027 + 'parenleft' => '367', # C+0x28 # U+0x0028 + 'parenright' => '367', # C+0x29 # U+0x0029 + 'asterisk' => '432', # C+0x2A # U+0x002A + 'plus' => '585', # C+0x2B # U+0x002B + 'comma' => '367', # C+0x2C # U+0x002C + 'hyphen' => '367', # C+0x2D # U+0x002D + 'period' => '367', # C+0x2E # U+0x002E + 'slash' => '390', # C+0x2F # U+0x002F + 'zero' => '585', # C+0x30 # U+0x0030 + 'one' => '585', # C+0x31 # U+0x0031 + 'two' => '585', # C+0x32 # U+0x0032 + 'three' => '585', # C+0x33 # U+0x0033 + 'four' => '585', # C+0x34 # U+0x0034 + 'five' => '585', # C+0x35 # U+0x0035 + 'six' => '585', # C+0x36 # U+0x0036 + 'seven' => '585', # C+0x37 # U+0x0037 + 'eight' => '585', # C+0x38 # U+0x0038 + 'nine' => '585', # C+0x39 # U+0x0039 + 'colon' => '367', # C+0x3A # U+0x003A + 'semicolon' => '367', # C+0x3B # U+0x003B + 'less' => '585', # C+0x3C # U+0x003C + 'equal' => '585', # C+0x3D # U+0x003D + 'greater' => '585', # C+0x3E # U+0x003E + 'question' => '437', # C+0x3F # U+0x003F + 'at' => '770', # C+0x40 # U+0x0040 + 'A' => '633', # C+0x41 # U+0x0041 + 'B' => '595', # C+0x42 # U+0x0042 + 'C' => '611', # C+0x43 # U+0x0043 + 'D' => '642', # C+0x44 # U+0x0044 + 'E' => '568', # C+0x45 # U+0x0045 + 'F' => '583', # C+0x46 # U+0x0046 + 'G' => '671', # C+0x47 # U+0x0047 + 'H' => '683', # C+0x48 # U+0x0048 + 'I' => '278', # C+0x49 # U+0x0049 + 'J' => '532', # C+0x4A # U+0x004A + 'K' => '617', # C+0x4B # U+0x004B + 'L' => '552', # C+0x4C # U+0x004C + 'M' => '745', # C+0x4D # U+0x004D + 'N' => '667', # C+0x4E # U+0x004E + 'O' => '703', # C+0x4F # U+0x004F + 'P' => '586', # C+0x50 # U+0x0050 + 'Q' => '708', # C+0x51 # U+0x0051 + 'R' => '610', # C+0x52 # U+0x0052 + 'S' => '511', # C+0x53 # U+0x0053 + 'T' => '611', # C+0x54 # U+0x0054 + 'U' => '677', # C+0x55 # U+0x0055 + 'V' => '621', # C+0x56 # U+0x0056 + 'W' => '883', # C+0x57 # U+0x0057 + 'X' => '600', # C+0x58 # U+0x0058 + 'Y' => '613', # C+0x59 # U+0x0059 + 'Z' => '560', # C+0x5A # U+0x005A + 'bracketleft' => '401', # C+0x5B # U+0x005B + 'backslash' => '355', # C+0x5C # U+0x005C + 'bracketright' => '401', # C+0x5D # U+0x005D + 'asciicircum' => '585', # C+0x5E # U+0x005E + 'underscore' => '585', # C+0x5F # U+0x005F + 'grave' => '585', # C+0x60 # U+0x0060 + 'a' => '532', # C+0x61 # U+0x0061 + 'b' => '581', # C+0x62 # U+0x0062 + 'c' => '511', # C+0x63 # U+0x0063 + 'd' => '580', # C+0x64 # U+0x0064 + 'e' => '574', # C+0x65 # U+0x0065 + 'f' => '369', # C+0x66 # U+0x0066 + 'g' => '501', # C+0x67 # U+0x0067 + 'h' => '592', # C+0x68 # U+0x0068 + 'i' => '298', # C+0x69 # U+0x0069 + 'j' => '366', # C+0x6A # U+0x006A + 'k' => '547', # C+0x6B # U+0x006B + 'l' => '294', # C+0x6C # U+0x006C + 'm' => '859', # C+0x6D # U+0x006D + 'n' => '590', # C+0x6E # U+0x006E + 'o' => '565', # C+0x6F # U+0x006F + 'p' => '582', # C+0x70 # U+0x0070 + 'q' => '583', # C+0x71 # U+0x0071 + 'r' => '427', # C+0x72 # U+0x0072 + 's' => '430', # C+0x73 # U+0x0073 + 't' => '396', # C+0x74 # U+0x0074 + 'u' => '590', # C+0x75 # U+0x0075 + 'v' => '527', # C+0x76 # U+0x0076 + 'w' => '783', # C+0x77 # U+0x0077 + 'x' => '552', # C+0x78 # U+0x0078 + 'y' => '533', # C+0x79 # U+0x0079 + 'z' => '528', # C+0x7A # U+0x007A + 'braceleft' => '433', # C+0x7B # U+0x007B + 'bar' => '585', # C+0x7C # U+0x007C + 'braceright' => '433', # C+0x7D # U+0x007D + 'asciitilde' => '585', # C+0x7E # U+0x007E + 'bullet' => '524', # C+0x7F # U+0x2022 + 'Euro' => '585', # C+0x80 # U+0x20AC + 'quotesinglbase' => '367', # C+0x82 # U+0x201A + 'florin' => '388', # C+0x83 # U+0x0192 + 'quotedblbase' => '524', # C+0x84 # U+0x201E + 'ellipsis' => '734', # C+0x85 # U+0x2026 + 'dagger' => '458', # C+0x86 # U+0x2020 + 'daggerdbl' => '458', # C+0x87 # U+0x2021 + 'circumflex' => '585', # C+0x88 # U+0x02C6 + 'perthousand' => '1035', # C+0x89 # U+0x2030 + 'Scaron' => '511', # C+0x8A # U+0x0160 + 'guilsinglleft' => '367', # C+0x8B # U+0x2039 + 'OE' => '1003', # C+0x8C # U+0x0152 + 'Zcaron' => '560', # C+0x8E # U+0x017D + 'quoteleft' => '367', # C+0x91 # U+0x2018 + 'quoteright' => '367', # C+0x92 # U+0x2019 + 'quotedblleft' => '585', # C+0x93 # U+0x201C + 'quotedblright' => '585', # C+0x94 # U+0x201D + 'endash' => '367', # C+0x96 # U+0x2013 + 'emdash' => '734', # C+0x97 # U+0x2014 + 'tilde' => '585', # C+0x98 # U+0x02DC + 'trademark' => '644', # C+0x99 # U+0x2122 + 'scaron' => '430', # C+0x9A # U+0x0161 + 'guilsinglright' => '367', # C+0x9B # U+0x203A + 'oe' => '920', # C+0x9C # U+0x0153 + 'zcaron' => '528', # C+0x9E # U+0x017E + 'Ydieresis' => '613', # C+0x9F # U+0x0178 + 'exclamdown' => '367', # C+0xA1 # U+0x00A1 + 'cent' => '585', # C+0xA2 # U+0x00A2 + 'sterling' => '524', # C+0xA3 # U+0x00A3 + 'currency' => '585', # C+0xA4 # U+0x00A4 + 'yen' => '570', # C+0xA5 # U+0x00A5 + 'brokenbar' => '585', # C+0xA6 # U+0x00A6 + 'section' => '453', # C+0xA7 # U+0x00A7 + 'dieresis' => '585', # C+0xA8 # U+0x00A8 + 'copyright' => '712', # C+0xA9 # U+0x00A9 + 'ordfeminine' => '429', # C+0xAA # U+0x00AA + 'guillemotleft' => '585', # C+0xAB # U+0x00AB + 'logicalnot' => '585', # C+0xAC # U+0x00AC + 'registered' => '712', # C+0xAE # U+0x00AE + 'macron' => '585', # C+0xAF # U+0x00AF + 'degree' => '585', # C+0xB0 # U+0x00B0 + 'plusminus' => '585', # C+0xB1 # U+0x00B1 + 'twosuperior' => '451', # C+0xB2 # U+0x00B2 + 'threesuperior' => '453', # C+0xB3 # U+0x00B3 + 'acute' => '585', # C+0xB4 # U+0x00B4 + 'mu' => '546', # C+0xB5 # U+0x00B5 + 'paragraph' => '524', # C+0xB6 # U+0x00B6 + 'periodcentered' => '367', # C+0xB7 # U+0x00B7 + 'cedilla' => '585', # C+0xB8 # U+0x00B8 + 'onesuperior' => '451', # C+0xB9 # U+0x00B9 + 'ordmasculine' => '429', # C+0xBA # U+0x00BA + 'guillemotright' => '585', # C+0xBB # U+0x00BB + 'onequarter' => '814', # C+0xBC # U+0x00BC + 'onehalf' => '814', # C+0xBD # U+0x00BD + 'threequarters' => '814', # C+0xBE # U+0x00BE + 'questiondown' => '437', # C+0xBF # U+0x00BF + 'Agrave' => '633', # C+0xC0 # U+0x00C0 + 'Aacute' => '633', # C+0xC1 # U+0x00C1 + 'Acircumflex' => '633', # C+0xC2 # U+0x00C2 + 'Atilde' => '633', # C+0xC3 # U+0x00C3 + 'Adieresis' => '633', # C+0xC4 # U+0x00C4 + 'Aring' => '633', # C+0xC5 # U+0x00C5 + 'AE' => '935', # C+0xC6 # U+0x00C6 + 'Ccedilla' => '611', # C+0xC7 # U+0x00C7 + 'Egrave' => '568', # C+0xC8 # U+0x00C8 + 'Eacute' => '568', # C+0xC9 # U+0x00C9 + 'Ecircumflex' => '568', # C+0xCA # U+0x00CA + 'Edieresis' => '568', # C+0xCB # U+0x00CB + 'Igrave' => '278', # C+0xCC # U+0x00CC + 'Iacute' => '278', # C+0xCD # U+0x00CD + 'Icircumflex' => '278', # C+0xCE # U+0x00CE + 'Idieresis' => '278', # C+0xCF # U+0x00CF + 'Eth' => '642', # C+0xD0 # U+0x00D0 + 'Ntilde' => '667', # C+0xD1 # U+0x00D1 + 'Ograve' => '703', # C+0xD2 # U+0x00D2 + 'Oacute' => '703', # C+0xD3 # U+0x00D3 + 'Ocircumflex' => '703', # C+0xD4 # U+0x00D4 + 'Otilde' => '703', # C+0xD5 # U+0x00D5 + 'Odieresis' => '703', # C+0xD6 # U+0x00D6 + 'multiply' => '585', # C+0xD7 # U+0x00D7 + 'Oslash' => '683', # C+0xD8 # U+0x00D8 + 'Ugrave' => '677', # C+0xD9 # U+0x00D9 + 'Uacute' => '677', # C+0xDA # U+0x00DA + 'Ucircumflex' => '677', # C+0xDB # U+0x00DB + 'Udieresis' => '677', # C+0xDC # U+0x00DC + 'Yacute' => '613', # C+0xDD # U+0x00DD + 'Thorn' => '557', # C+0xDE # U+0x00DE + 'germandbls' => '546', # C+0xDF # U+0x00DF + 'agrave' => '532', # C+0xE0 # U+0x00E0 + 'aacute' => '532', # C+0xE1 # U+0x00E1 + 'acircumflex' => '532', # C+0xE2 # U+0x00E2 + 'atilde' => '532', # C+0xE3 # U+0x00E3 + 'adieresis' => '532', # C+0xE4 # U+0x00E4 + 'aring' => '532', # C+0xE5 # U+0x00E5 + 'ae' => '862', # C+0xE6 # U+0x00E6 + 'ccedilla' => '511', # C+0xE7 # U+0x00E7 + 'egrave' => '574', # C+0xE8 # U+0x00E8 + 'eacute' => '574', # C+0xE9 # U+0x00E9 + 'ecircumflex' => '574', # C+0xEA # U+0x00EA + 'edieresis' => '574', # C+0xEB # U+0x00EB + 'igrave' => '298', # C+0xEC # U+0x00EC + 'iacute' => '298', # C+0xED # U+0x00ED + 'icircumflex' => '298', # C+0xEE # U+0x00EE + 'idieresis' => '298', # C+0xEF # U+0x00EF + 'eth' => '565', # C+0xF0 # U+0x00F0 + 'ntilde' => '590', # C+0xF1 # U+0x00F1 + 'ograve' => '565', # C+0xF2 # U+0x00F2 + 'oacute' => '565', # C+0xF3 # U+0x00F3 + 'ocircumflex' => '565', # C+0xF4 # U+0x00F4 + 'otilde' => '565', # C+0xF5 # U+0x00F5 + 'odieresis' => '565', # C+0xF6 # U+0x00F6 + 'divide' => '585', # C+0xF7 # U+0x00F7 + 'oslash' => '565', # C+0xF8 # U+0x00F8 + 'ugrave' => '590', # C+0xF9 # U+0x00F9 + 'uacute' => '590', # C+0xFA # U+0x00FA + 'ucircumflex' => '590', # C+0xFB # U+0x00FB + 'udieresis' => '590', # C+0xFC # U+0x00FC + 'yacute' => '533', # C+0xFD # U+0x00FD + 'thorn' => '582', # C+0xFE # U+0x00FE + 'ydieresis' => '533', # C+0xFF # U+0x00FF + 'middot' => '367', # U+0x00B7 + 'Abreve' => '633', # U+0x0102 + 'abreve' => '532', # U+0x0103 + 'Aogonek' => '633', # U+0x0104 + 'aogonek' => '532', # U+0x0105 + 'Cacute' => '611', # U+0x0106 + 'cacute' => '511', # U+0x0107 + 'Ccaron' => '611', # U+0x010C + 'ccaron' => '511', # U+0x010D + 'Dcaron' => '642', # U+0x010E + 'dcaron' => '733', # U+0x010F + 'Eogonek' => '568', # U+0x0118 + 'eogonek' => '574', # U+0x0119 + 'Ecaron' => '568', # U+0x011A + 'ecaron' => '574', # U+0x011B + 'Gbreve' => '671', # U+0x011E + 'gbreve' => '501', # U+0x011F + 'dotlessi' => '298', # U+0x0131 + 'Lacute' => '552', # U+0x0139 + 'lacute' => '294', # U+0x013A + 'Lcaron' => '552', # U+0x013D + 'lcaron' => '377', # U+0x013E + 'Ldot' => '552', # U+0x013F + 'ldot' => '436', # U+0x0140 + 'Lslash' => '552', # U+0x0141 + 'lslash' => '294', # U+0x0142 + 'Nacute' => '667', # U+0x0143 + 'nacute' => '590', # U+0x0144 + 'Ncaron' => '667', # U+0x0147 + 'ncaron' => '590', # U+0x0148 + 'Racute' => '610', # U+0x0154 + 'racute' => '427', # U+0x0155 + 'Rcaron' => '610', # U+0x0158 + 'rcaron' => '427', # U+0x0159 + 'Sacute' => '511', # U+0x015A + 'sacute' => '430', # U+0x015B + 'Scedilla' => '511', # U+0x015E + 'scedilla' => '430', # U+0x015F + 'Tcaron' => '611', # U+0x0164 + 'tcaron' => '545', # U+0x0165 + 'Uring' => '677', # U+0x016E + 'uring' => '590', # U+0x016F + 'Zacute' => '560', # U+0x0179 + 'zacute' => '528', # U+0x017A + 'Zdot' => '560', # U+0x017B + 'zdot' => '528', # U+0x017C + 'caron' => '585', # U+0x02C7 + 'breve' => '585', # U+0x02D8 + 'dotaccent' => '585', # U+0x02D9 + 'ring' => '585', # U+0x02DA + 'ogonek' => '585', # U+0x02DB + 'hungarumlaut' => '585', # U+0x02DD + 'Delta' => '584', # U+0x0394 + 'Omega' => '668', # U+0x03A9 + 'pi' => '601', # U+0x03C0 + 'fraction' => '585', # U+0x2044 + 'franc' => '583', # U+0x20A3 + 'partialdiff' => '585', # U+0x2202 + 'product' => '636', # U+0x220F + 'summation' => '524', # U+0x2211 + 'minus' => '585', # U+0x2212 + 'radical' => '585', # U+0x221A + 'infinity' => '585', # U+0x221E + 'integral' => '524', # U+0x222B + 'approxequal' => '585', # U+0x2248 + 'notequal' => '585', # U+0x2260 + 'lessequal' => '585', # U+0x2264 + 'greaterequal' => '585', # U+0x2265 + 'lozenge' => '600', # U+0x25CA + 'dotlessj' => '366', # U+0xF6BE + 'fi' => '622', # U+0xFB01 + 'fl' => '636', # U+0xFB02 + }, # HORIZ. WIDTH TABLE +} }; + +1; diff --git a/lib/PDF/API2/Resource/Font/CoreFont/trebuchetbolditalic.pm b/lib/PDF/API2/Resource/Font/CoreFont/trebuchetbolditalic.pm new file mode 100644 index 0000000..5def86c --- /dev/null +++ b/lib/PDF/API2/Resource/Font/CoreFont/trebuchetbolditalic.pm @@ -0,0 +1,635 @@ +#line 1 "PDF/API2/Resource/Font/CoreFont/trebuchetbolditalic.pm" +#line 1 "PDF/API2/Resource/Font/CoreFont/trebuchetbolditalic.pm" +package PDF::API2::Resource::Font::CoreFont::trebuchetbolditalic; + +use strict; +use warnings; + +our $VERSION = '2.033'; # VERSION + +sub data { return { + 'fontname' => 'TrebuchetMS,BoldItalic', + 'type' => 'TrueType', + 'apiname' => 'TrBoIt', + 'ascender' => '938', + 'capheight' => '715', + 'descender' => '-222', + 'isfixedpitch' => '0', + 'issymbol' => '0', + 'italicangle' => '-10', + 'underlineposition' => '-261', + 'underlinethickness' => '200', + 'xheight' => '522', + 'firstchar' => '32', + 'lastchar' => '255', + 'flags' => '262242', + 'char' => [ # DEF. ENCODING GLYPH TABLE + '.notdef', # C+0x00 # U+0x0000 + '.notdef', # C+0x01 # U+0x0000 + '.notdef', # C+0x02 # U+0x0000 + '.notdef', # C+0x03 # U+0x0000 + '.notdef', # C+0x04 # U+0x0000 + '.notdef', # C+0x05 # U+0x0000 + '.notdef', # C+0x06 # U+0x0000 + '.notdef', # C+0x07 # U+0x0000 + '.notdef', # C+0x08 # U+0x0000 + '.notdef', # C+0x09 # U+0x0000 + '.notdef', # C+0x0A # U+0x0000 + '.notdef', # C+0x0B # U+0x0000 + '.notdef', # C+0x0C # U+0x0000 + '.notdef', # C+0x0D # U+0x0000 + '.notdef', # C+0x0E # U+0x0000 + '.notdef', # C+0x0F # U+0x0000 + '.notdef', # C+0x10 # U+0x0000 + '.notdef', # C+0x11 # U+0x0000 + '.notdef', # C+0x12 # U+0x0000 + '.notdef', # C+0x13 # U+0x0000 + '.notdef', # C+0x14 # U+0x0000 + '.notdef', # C+0x15 # U+0x0000 + '.notdef', # C+0x16 # U+0x0000 + '.notdef', # C+0x17 # U+0x0000 + '.notdef', # C+0x18 # U+0x0000 + '.notdef', # C+0x19 # U+0x0000 + '.notdef', # C+0x1A # U+0x0000 + '.notdef', # C+0x1B # U+0x0000 + '.notdef', # C+0x1C # U+0x0000 + '.notdef', # C+0x1D # U+0x0000 + '.notdef', # C+0x1E # U+0x0000 + '.notdef', # C+0x1F # U+0x0000 + 'space', # C+0x20 # U+0x0020 + 'exclam', # C+0x21 # U+0x0021 + 'quotedbl', # C+0x22 # U+0x0022 + 'numbersign', # C+0x23 # U+0x0023 + 'dollar', # C+0x24 # U+0x0024 + 'percent', # C+0x25 # U+0x0025 + 'ampersand', # C+0x26 # U+0x0026 + 'quotesingle', # C+0x27 # U+0x0027 + 'parenleft', # C+0x28 # U+0x0028 + 'parenright', # C+0x29 # U+0x0029 + 'asterisk', # C+0x2A # U+0x002A + 'plus', # C+0x2B # U+0x002B + 'comma', # C+0x2C # U+0x002C + 'hyphen', # C+0x2D # U+0x002D + 'period', # C+0x2E # U+0x002E + 'slash', # C+0x2F # U+0x002F + 'zero', # C+0x30 # U+0x0030 + 'one', # C+0x31 # U+0x0031 + 'two', # C+0x32 # U+0x0032 + 'three', # C+0x33 # U+0x0033 + 'four', # C+0x34 # U+0x0034 + 'five', # C+0x35 # U+0x0035 + 'six', # C+0x36 # U+0x0036 + 'seven', # C+0x37 # U+0x0037 + 'eight', # C+0x38 # U+0x0038 + 'nine', # C+0x39 # U+0x0039 + 'colon', # C+0x3A # U+0x003A + 'semicolon', # C+0x3B # U+0x003B + 'less', # C+0x3C # U+0x003C + 'equal', # C+0x3D # U+0x003D + 'greater', # C+0x3E # U+0x003E + 'question', # C+0x3F # U+0x003F + 'at', # C+0x40 # U+0x0040 + 'A', # C+0x41 # U+0x0041 + 'B', # C+0x42 # U+0x0042 + 'C', # C+0x43 # U+0x0043 + 'D', # C+0x44 # U+0x0044 + 'E', # C+0x45 # U+0x0045 + 'F', # C+0x46 # U+0x0046 + 'G', # C+0x47 # U+0x0047 + 'H', # C+0x48 # U+0x0048 + 'I', # C+0x49 # U+0x0049 + 'J', # C+0x4A # U+0x004A + 'K', # C+0x4B # U+0x004B + 'L', # C+0x4C # U+0x004C + 'M', # C+0x4D # U+0x004D + 'N', # C+0x4E # U+0x004E + 'O', # C+0x4F # U+0x004F + 'P', # C+0x50 # U+0x0050 + 'Q', # C+0x51 # U+0x0051 + 'R', # C+0x52 # U+0x0052 + 'S', # C+0x53 # U+0x0053 + 'T', # C+0x54 # U+0x0054 + 'U', # C+0x55 # U+0x0055 + 'V', # C+0x56 # U+0x0056 + 'W', # C+0x57 # U+0x0057 + 'X', # C+0x58 # U+0x0058 + 'Y', # C+0x59 # U+0x0059 + 'Z', # C+0x5A # U+0x005A + 'bracketleft', # C+0x5B # U+0x005B + 'backslash', # C+0x5C # U+0x005C + 'bracketright', # C+0x5D # U+0x005D + 'asciicircum', # C+0x5E # U+0x005E + 'underscore', # C+0x5F # U+0x005F + 'grave', # C+0x60 # U+0x0060 + 'a', # C+0x61 # U+0x0061 + 'b', # C+0x62 # U+0x0062 + 'c', # C+0x63 # U+0x0063 + 'd', # C+0x64 # U+0x0064 + 'e', # C+0x65 # U+0x0065 + 'f', # C+0x66 # U+0x0066 + 'g', # C+0x67 # U+0x0067 + 'h', # C+0x68 # U+0x0068 + 'i', # C+0x69 # U+0x0069 + 'j', # C+0x6A # U+0x006A + 'k', # C+0x6B # U+0x006B + 'l', # C+0x6C # U+0x006C + 'm', # C+0x6D # U+0x006D + 'n', # C+0x6E # U+0x006E + 'o', # C+0x6F # U+0x006F + 'p', # C+0x70 # U+0x0070 + 'q', # C+0x71 # U+0x0071 + 'r', # C+0x72 # U+0x0072 + 's', # C+0x73 # U+0x0073 + 't', # C+0x74 # U+0x0074 + 'u', # C+0x75 # U+0x0075 + 'v', # C+0x76 # U+0x0076 + 'w', # C+0x77 # U+0x0077 + 'x', # C+0x78 # U+0x0078 + 'y', # C+0x79 # U+0x0079 + 'z', # C+0x7A # U+0x007A + 'braceleft', # C+0x7B # U+0x007B + 'bar', # C+0x7C # U+0x007C + 'braceright', # C+0x7D # U+0x007D + 'asciitilde', # C+0x7E # U+0x007E + 'bullet', # C+0x7F # U+0x2022 + 'Euro', # C+0x80 # U+0x20AC + 'bullet', # C+0x81 # U+0x2022 + 'quotesinglbase', # C+0x82 # U+0x201A + 'florin', # C+0x83 # U+0x0192 + 'quotedblbase', # C+0x84 # U+0x201E + 'ellipsis', # C+0x85 # U+0x2026 + 'dagger', # C+0x86 # U+0x2020 + 'daggerdbl', # C+0x87 # U+0x2021 + 'circumflex', # C+0x88 # U+0x02C6 + 'perthousand', # C+0x89 # U+0x2030 + 'Scaron', # C+0x8A # U+0x0160 + 'guilsinglleft', # C+0x8B # U+0x2039 + 'OE', # C+0x8C # U+0x0152 + 'bullet', # C+0x8D # U+0x2022 + 'Zcaron', # C+0x8E # U+0x017D + 'bullet', # C+0x8F # U+0x2022 + 'bullet', # C+0x90 # U+0x2022 + 'quoteleft', # C+0x91 # U+0x2018 + 'quoteright', # C+0x92 # U+0x2019 + 'quotedblleft', # C+0x93 # U+0x201C + 'quotedblright', # C+0x94 # U+0x201D + 'bullet', # C+0x95 # U+0x2022 + 'endash', # C+0x96 # U+0x2013 + 'emdash', # C+0x97 # U+0x2014 + 'tilde', # C+0x98 # U+0x02DC + 'trademark', # C+0x99 # U+0x2122 + 'scaron', # C+0x9A # U+0x0161 + 'guilsinglright', # C+0x9B # U+0x203A + 'oe', # C+0x9C # U+0x0153 + 'bullet', # C+0x9D # U+0x2022 + 'zcaron', # C+0x9E # U+0x017E + 'Ydieresis', # C+0x9F # U+0x0178 + 'space', # C+0xA0 # U+0x0020 + 'exclamdown', # C+0xA1 # U+0x00A1 + 'cent', # C+0xA2 # U+0x00A2 + 'sterling', # C+0xA3 # U+0x00A3 + 'currency', # C+0xA4 # U+0x00A4 + 'yen', # C+0xA5 # U+0x00A5 + 'brokenbar', # C+0xA6 # U+0x00A6 + 'section', # C+0xA7 # U+0x00A7 + 'dieresis', # C+0xA8 # U+0x00A8 + 'copyright', # C+0xA9 # U+0x00A9 + 'ordfeminine', # C+0xAA # U+0x00AA + 'guillemotleft', # C+0xAB # U+0x00AB + 'logicalnot', # C+0xAC # U+0x00AC + 'hyphen', # C+0xAD # U+0x002D + 'registered', # C+0xAE # U+0x00AE + 'macron', # C+0xAF # U+0x00AF + 'degree', # C+0xB0 # U+0x00B0 + 'plusminus', # C+0xB1 # U+0x00B1 + 'twosuperior', # C+0xB2 # U+0x00B2 + 'threesuperior', # C+0xB3 # U+0x00B3 + 'acute', # C+0xB4 # U+0x00B4 + 'mu', # C+0xB5 # U+0x00B5 + 'paragraph', # C+0xB6 # U+0x00B6 + 'periodcentered', # C+0xB7 # U+0x00B7 + 'cedilla', # C+0xB8 # U+0x00B8 + 'onesuperior', # C+0xB9 # U+0x00B9 + 'ordmasculine', # C+0xBA # U+0x00BA + 'guillemotright', # C+0xBB # U+0x00BB + 'onequarter', # C+0xBC # U+0x00BC + 'onehalf', # C+0xBD # U+0x00BD + 'threequarters', # C+0xBE # U+0x00BE + 'questiondown', # C+0xBF # U+0x00BF + 'Agrave', # C+0xC0 # U+0x00C0 + 'Aacute', # C+0xC1 # U+0x00C1 + 'Acircumflex', # C+0xC2 # U+0x00C2 + 'Atilde', # C+0xC3 # U+0x00C3 + 'Adieresis', # C+0xC4 # U+0x00C4 + 'Aring', # C+0xC5 # U+0x00C5 + 'AE', # C+0xC6 # U+0x00C6 + 'Ccedilla', # C+0xC7 # U+0x00C7 + 'Egrave', # C+0xC8 # U+0x00C8 + 'Eacute', # C+0xC9 # U+0x00C9 + 'Ecircumflex', # C+0xCA # U+0x00CA + 'Edieresis', # C+0xCB # U+0x00CB + 'Igrave', # C+0xCC # U+0x00CC + 'Iacute', # C+0xCD # U+0x00CD + 'Icircumflex', # C+0xCE # U+0x00CE + 'Idieresis', # C+0xCF # U+0x00CF + 'Eth', # C+0xD0 # U+0x00D0 + 'Ntilde', # C+0xD1 # U+0x00D1 + 'Ograve', # C+0xD2 # U+0x00D2 + 'Oacute', # C+0xD3 # U+0x00D3 + 'Ocircumflex', # C+0xD4 # U+0x00D4 + 'Otilde', # C+0xD5 # U+0x00D5 + 'Odieresis', # C+0xD6 # U+0x00D6 + 'multiply', # C+0xD7 # U+0x00D7 + 'Oslash', # C+0xD8 # U+0x00D8 + 'Ugrave', # C+0xD9 # U+0x00D9 + 'Uacute', # C+0xDA # U+0x00DA + 'Ucircumflex', # C+0xDB # U+0x00DB + 'Udieresis', # C+0xDC # U+0x00DC + 'Yacute', # C+0xDD # U+0x00DD + 'Thorn', # C+0xDE # U+0x00DE + 'germandbls', # C+0xDF # U+0x00DF + 'agrave', # C+0xE0 # U+0x00E0 + 'aacute', # C+0xE1 # U+0x00E1 + 'acircumflex', # C+0xE2 # U+0x00E2 + 'atilde', # C+0xE3 # U+0x00E3 + 'adieresis', # C+0xE4 # U+0x00E4 + 'aring', # C+0xE5 # U+0x00E5 + 'ae', # C+0xE6 # U+0x00E6 + 'ccedilla', # C+0xE7 # U+0x00E7 + 'egrave', # C+0xE8 # U+0x00E8 + 'eacute', # C+0xE9 # U+0x00E9 + 'ecircumflex', # C+0xEA # U+0x00EA + 'edieresis', # C+0xEB # U+0x00EB + 'igrave', # C+0xEC # U+0x00EC + 'iacute', # C+0xED # U+0x00ED + 'icircumflex', # C+0xEE # U+0x00EE + 'idieresis', # C+0xEF # U+0x00EF + 'eth', # C+0xF0 # U+0x00F0 + 'ntilde', # C+0xF1 # U+0x00F1 + 'ograve', # C+0xF2 # U+0x00F2 + 'oacute', # C+0xF3 # U+0x00F3 + 'ocircumflex', # C+0xF4 # U+0x00F4 + 'otilde', # C+0xF5 # U+0x00F5 + 'odieresis', # C+0xF6 # U+0x00F6 + 'divide', # C+0xF7 # U+0x00F7 + 'oslash', # C+0xF8 # U+0x00F8 + 'ugrave', # C+0xF9 # U+0x00F9 + 'uacute', # C+0xFA # U+0x00FA + 'ucircumflex', # C+0xFB # U+0x00FB + 'udieresis', # C+0xFC # U+0x00FC + 'yacute', # C+0xFD # U+0x00FD + 'thorn', # C+0xFE # U+0x00FE + 'ydieresis', # C+0xFF # U+0x00FF + ], # DEF. ENCODING GLYPH TABLE + 'fontbbox' => [ -107, -269, 1155, 965 ], + 'wx' => { # HORIZ. WIDTH TABLE + 'space' => '301', # C+0x20 # U+0x0020 + 'exclam' => '367', # C+0x21 # U+0x0021 + 'quotedbl' => '390', # C+0x22 # U+0x0022 + 'numbersign' => '585', # C+0x23 # U+0x0023 + 'dollar' => '585', # C+0x24 # U+0x0024 + 'percent' => '732', # C+0x25 # U+0x0025 + 'ampersand' => '706', # C+0x26 # U+0x0026 + 'quotesingle' => '301', # C+0x27 # U+0x0027 + 'parenleft' => '367', # C+0x28 # U+0x0028 + 'parenright' => '367', # C+0x29 # U+0x0029 + 'asterisk' => '432', # C+0x2A # U+0x002A + 'plus' => '585', # C+0x2B # U+0x002B + 'comma' => '367', # C+0x2C # U+0x002C + 'hyphen' => '367', # C+0x2D # U+0x002D + 'period' => '367', # C+0x2E # U+0x002E + 'slash' => '396', # C+0x2F # U+0x002F + 'zero' => '585', # C+0x30 # U+0x0030 + 'one' => '585', # C+0x31 # U+0x0031 + 'two' => '585', # C+0x32 # U+0x0032 + 'three' => '585', # C+0x33 # U+0x0033 + 'four' => '585', # C+0x34 # U+0x0034 + 'five' => '585', # C+0x35 # U+0x0035 + 'six' => '585', # C+0x36 # U+0x0036 + 'seven' => '585', # C+0x37 # U+0x0037 + 'eight' => '585', # C+0x38 # U+0x0038 + 'nine' => '585', # C+0x39 # U+0x0039 + 'colon' => '367', # C+0x3A # U+0x003A + 'semicolon' => '367', # C+0x3B # U+0x003B + 'less' => '585', # C+0x3C # U+0x003C + 'equal' => '585', # C+0x3D # U+0x003D + 'greater' => '585', # C+0x3E # U+0x003E + 'question' => '396', # C+0x3F # U+0x003F + 'at' => '770', # C+0x40 # U+0x0040 + 'A' => '613', # C+0x41 # U+0x0041 + 'B' => '589', # C+0x42 # U+0x0042 + 'C' => '612', # C+0x43 # U+0x0043 + 'D' => '632', # C+0x44 # U+0x0044 + 'E' => '593', # C+0x45 # U+0x0045 + 'F' => '585', # C+0x46 # U+0x0046 + 'G' => '676', # C+0x47 # U+0x0047 + 'H' => '678', # C+0x48 # U+0x0048 + 'I' => '278', # C+0x49 # U+0x0049 + 'J' => '498', # C+0x4A # U+0x004A + 'K' => '649', # C+0x4B # U+0x004B + 'L' => '528', # C+0x4C # U+0x004C + 'M' => '786', # C+0x4D # U+0x004D + 'N' => '660', # C+0x4E # U+0x004E + 'O' => '702', # C+0x4F # U+0x004F + 'P' => '583', # C+0x50 # U+0x0050 + 'Q' => '769', # C+0x51 # U+0x0051 + 'R' => '623', # C+0x52 # U+0x0052 + 'S' => '501', # C+0x53 # U+0x0053 + 'T' => '685', # C+0x54 # U+0x0054 + 'U' => '661', # C+0x55 # U+0x0055 + 'V' => '683', # C+0x56 # U+0x0056 + 'W' => '926', # C+0x57 # U+0x0057 + 'X' => '656', # C+0x58 # U+0x0058 + 'Y' => '683', # C+0x59 # U+0x0059 + 'Z' => '611', # C+0x5A # U+0x005A + 'bracketleft' => '485', # C+0x5B # U+0x005B + 'backslash' => '477', # C+0x5C # U+0x005C + 'bracketright' => '485', # C+0x5D # U+0x005D + 'asciicircum' => '585', # C+0x5E # U+0x005E + 'underscore' => '585', # C+0x5F # U+0x005F + 'grave' => '585', # C+0x60 # U+0x0060 + 'a' => '592', # C+0x61 # U+0x0061 + 'b' => '593', # C+0x62 # U+0x0062 + 'c' => '492', # C+0x63 # U+0x0063 + 'd' => '593', # C+0x64 # U+0x0064 + 'e' => '551', # C+0x65 # U+0x0065 + 'f' => '410', # C+0x66 # U+0x0066 + 'g' => '535', # C+0x67 # U+0x0067 + 'h' => '562', # C+0x68 # U+0x0068 + 'i' => '326', # C+0x69 # U+0x0069 + 'j' => '387', # C+0x6A # U+0x006A + 'k' => '539', # C+0x6B # U+0x006B + 'l' => '319', # C+0x6C # U+0x006C + 'm' => '830', # C+0x6D # U+0x006D + 'n' => '562', # C+0x6E # U+0x006E + 'o' => '569', # C+0x6F # U+0x006F + 'p' => '598', # C+0x70 # U+0x0070 + 'q' => '598', # C+0x71 # U+0x0071 + 'r' => '446', # C+0x72 # U+0x0072 + 's' => '458', # C+0x73 # U+0x0073 + 't' => '437', # C+0x74 # U+0x0074 + 'u' => '557', # C+0x75 # U+0x0075 + 'v' => '552', # C+0x76 # U+0x0076 + 'w' => '773', # C+0x77 # U+0x0077 + 'x' => '575', # C+0x78 # U+0x0078 + 'y' => '563', # C+0x79 # U+0x0079 + 'z' => '532', # C+0x7A # U+0x007A + 'braceleft' => '485', # C+0x7B # U+0x007B + 'bar' => '585', # C+0x7C # U+0x007C + 'braceright' => '485', # C+0x7D # U+0x007D + 'asciitilde' => '585', # C+0x7E # U+0x007E + 'bullet' => '524', # C+0x7F # U+0x2022 + 'Euro' => '585', # C+0x80 # U+0x20AC + 'quotesinglbase' => '367', # C+0x82 # U+0x201A + 'florin' => '585', # C+0x83 # U+0x0192 + 'quotedblbase' => '585', # C+0x84 # U+0x201E + 'ellipsis' => '734', # C+0x85 # U+0x2026 + 'dagger' => '458', # C+0x86 # U+0x2020 + 'daggerdbl' => '458', # C+0x87 # U+0x2021 + 'circumflex' => '585', # C+0x88 # U+0x02C6 + 'perthousand' => '1042', # C+0x89 # U+0x2030 + 'Scaron' => '501', # C+0x8A # U+0x0160 + 'guilsinglleft' => '367', # C+0x8B # U+0x2039 + 'OE' => '1058', # C+0x8C # U+0x0152 + 'Zcaron' => '611', # C+0x8E # U+0x017D + 'quoteleft' => '367', # C+0x91 # U+0x2018 + 'quoteright' => '367', # C+0x92 # U+0x2019 + 'quotedblleft' => '585', # C+0x93 # U+0x201C + 'quotedblright' => '585', # C+0x94 # U+0x201D + 'endash' => '367', # C+0x96 # U+0x2013 + 'emdash' => '734', # C+0x97 # U+0x2014 + 'tilde' => '585', # C+0x98 # U+0x02DC + 'trademark' => '644', # C+0x99 # U+0x2122 + 'scaron' => '458', # C+0x9A # U+0x0161 + 'guilsinglright' => '367', # C+0x9B # U+0x203A + 'oe' => '927', # C+0x9C # U+0x0153 + 'zcaron' => '532', # C+0x9E # U+0x017E + 'Ydieresis' => '683', # C+0x9F # U+0x0178 + 'exclamdown' => '367', # C+0xA1 # U+0x00A1 + 'cent' => '585', # C+0xA2 # U+0x00A2 + 'sterling' => '585', # C+0xA3 # U+0x00A3 + 'currency' => '585', # C+0xA4 # U+0x00A4 + 'yen' => '585', # C+0xA5 # U+0x00A5 + 'brokenbar' => '585', # C+0xA6 # U+0x00A6 + 'section' => '585', # C+0xA7 # U+0x00A7 + 'dieresis' => '585', # C+0xA8 # U+0x00A8 + 'copyright' => '712', # C+0xA9 # U+0x00A9 + 'ordfeminine' => '427', # C+0xAA # U+0x00AA + 'guillemotleft' => '524', # C+0xAB # U+0x00AB + 'logicalnot' => '585', # C+0xAC # U+0x00AC + 'registered' => '712', # C+0xAE # U+0x00AE + 'macron' => '585', # C+0xAF # U+0x00AF + 'degree' => '585', # C+0xB0 # U+0x00B0 + 'plusminus' => '585', # C+0xB1 # U+0x00B1 + 'twosuperior' => '464', # C+0xB2 # U+0x00B2 + 'threesuperior' => '463', # C+0xB3 # U+0x00B3 + 'acute' => '585', # C+0xB4 # U+0x00B4 + 'mu' => '557', # C+0xB5 # U+0x00B5 + 'paragraph' => '585', # C+0xB6 # U+0x00B6 + 'periodcentered' => '367', # C+0xB7 # U+0x00B7 + 'cedilla' => '585', # C+0xB8 # U+0x00B8 + 'onesuperior' => '478', # C+0xB9 # U+0x00B9 + 'ordmasculine' => '433', # C+0xBA # U+0x00BA + 'guillemotright' => '524', # C+0xBB # U+0x00BB + 'onequarter' => '876', # C+0xBC # U+0x00BC + 'onehalf' => '876', # C+0xBD # U+0x00BD + 'threequarters' => '876', # C+0xBE # U+0x00BE + 'questiondown' => '367', # C+0xBF # U+0x00BF + 'Agrave' => '613', # C+0xC0 # U+0x00C0 + 'Aacute' => '613', # C+0xC1 # U+0x00C1 + 'Acircumflex' => '613', # C+0xC2 # U+0x00C2 + 'Atilde' => '613', # C+0xC3 # U+0x00C3 + 'Adieresis' => '613', # C+0xC4 # U+0x00C4 + 'Aring' => '613', # C+0xC5 # U+0x00C5 + 'AE' => '959', # C+0xC6 # U+0x00C6 + 'Ccedilla' => '612', # C+0xC7 # U+0x00C7 + 'Egrave' => '593', # C+0xC8 # U+0x00C8 + 'Eacute' => '593', # C+0xC9 # U+0x00C9 + 'Ecircumflex' => '593', # C+0xCA # U+0x00CA + 'Edieresis' => '593', # C+0xCB # U+0x00CB + 'Igrave' => '278', # C+0xCC # U+0x00CC + 'Iacute' => '278', # C+0xCD # U+0x00CD + 'Icircumflex' => '278', # C+0xCE # U+0x00CE + 'Idieresis' => '278', # C+0xCF # U+0x00CF + 'Eth' => '654', # C+0xD0 # U+0x00D0 + 'Ntilde' => '660', # C+0xD1 # U+0x00D1 + 'Ograve' => '702', # C+0xD2 # U+0x00D2 + 'Oacute' => '702', # C+0xD3 # U+0x00D3 + 'Ocircumflex' => '702', # C+0xD4 # U+0x00D4 + 'Otilde' => '702', # C+0xD5 # U+0x00D5 + 'Odieresis' => '702', # C+0xD6 # U+0x00D6 + 'multiply' => '585', # C+0xD7 # U+0x00D7 + 'Oslash' => '702', # C+0xD8 # U+0x00D8 + 'Ugrave' => '661', # C+0xD9 # U+0x00D9 + 'Uacute' => '661', # C+0xDA # U+0x00DA + 'Ucircumflex' => '661', # C+0xDB # U+0x00DB + 'Udieresis' => '661', # C+0xDC # U+0x00DC + 'Yacute' => '683', # C+0xDD # U+0x00DD + 'Thorn' => '561', # C+0xDE # U+0x00DE + 'germandbls' => '577', # C+0xDF # U+0x00DF + 'agrave' => '592', # C+0xE0 # U+0x00E0 + 'aacute' => '592', # C+0xE1 # U+0x00E1 + 'acircumflex' => '592', # C+0xE2 # U+0x00E2 + 'atilde' => '592', # C+0xE3 # U+0x00E3 + 'adieresis' => '592', # C+0xE4 # U+0x00E4 + 'aring' => '592', # C+0xE5 # U+0x00E5 + 'ae' => '893', # C+0xE6 # U+0x00E6 + 'ccedilla' => '492', # C+0xE7 # U+0x00E7 + 'egrave' => '551', # C+0xE8 # U+0x00E8 + 'eacute' => '551', # C+0xE9 # U+0x00E9 + 'ecircumflex' => '551', # C+0xEA # U+0x00EA + 'edieresis' => '551', # C+0xEB # U+0x00EB + 'igrave' => '326', # C+0xEC # U+0x00EC + 'iacute' => '326', # C+0xED # U+0x00ED + 'icircumflex' => '326', # C+0xEE # U+0x00EE + 'idieresis' => '326', # C+0xEF # U+0x00EF + 'eth' => '569', # C+0xF0 # U+0x00F0 + 'ntilde' => '562', # C+0xF1 # U+0x00F1 + 'ograve' => '569', # C+0xF2 # U+0x00F2 + 'oacute' => '569', # C+0xF3 # U+0x00F3 + 'ocircumflex' => '569', # C+0xF4 # U+0x00F4 + 'otilde' => '569', # C+0xF5 # U+0x00F5 + 'odieresis' => '569', # C+0xF6 # U+0x00F6 + 'divide' => '585', # C+0xF7 # U+0x00F7 + 'oslash' => '569', # C+0xF8 # U+0x00F8 + 'ugrave' => '557', # C+0xF9 # U+0x00F9 + 'uacute' => '557', # C+0xFA # U+0x00FA + 'ucircumflex' => '557', # C+0xFB # U+0x00FB + 'udieresis' => '557', # C+0xFC # U+0x00FC + 'yacute' => '563', # C+0xFD # U+0x00FD + 'thorn' => '598', # C+0xFE # U+0x00FE + 'ydieresis' => '563', # C+0xFF # U+0x00FF + 'middot' => '367', # U+0x00B7 + 'Amacron' => '613', # U+0x0100 + 'amacron' => '592', # U+0x0101 + 'Abreve' => '613', # U+0x0102 + 'abreve' => '592', # U+0x0103 + 'Aogonek' => '613', # U+0x0104 + 'aogonek' => '592', # U+0x0105 + 'Cacute' => '612', # U+0x0106 + 'cacute' => '492', # U+0x0107 + 'Ccircumflex' => '612', # U+0x0108 + 'ccircumflex' => '492', # U+0x0109 + 'Cdot' => '612', # U+0x010A + 'cdot' => '492', # U+0x010B + 'Ccaron' => '612', # U+0x010C + 'ccaron' => '492', # U+0x010D + 'Dcaron' => '632', # U+0x010E + 'dcaron' => '706', # U+0x010F + 'dcroat' => '593', # U+0x0111 + 'Emacron' => '593', # U+0x0112 + 'emacron' => '551', # U+0x0113 + 'Ebreve' => '593', # U+0x0114 + 'ebreve' => '551', # U+0x0115 + 'Edot' => '593', # U+0x0116 + 'edot' => '551', # U+0x0117 + 'Eogonek' => '593', # U+0x0118 + 'eogonek' => '551', # U+0x0119 + 'Ecaron' => '593', # U+0x011A + 'ecaron' => '551', # U+0x011B + 'Gcircumflex' => '676', # U+0x011C + 'gcircumflex' => '535', # U+0x011D + 'Gbreve' => '676', # U+0x011E + 'gbreve' => '535', # U+0x011F + 'Gdot' => '676', # U+0x0120 + 'gdot' => '535', # U+0x0121 + 'Hcircumflex' => '678', # U+0x0124 + 'hcircumflex' => '562', # U+0x0125 + 'Hbar' => '699', # U+0x0126 + 'hbar' => '562', # U+0x0127 + 'Itilde' => '278', # U+0x0128 + 'itilde' => '326', # U+0x0129 + 'Imacron' => '278', # U+0x012A + 'imacron' => '326', # U+0x012B + 'Ibreve' => '278', # U+0x012C + 'ibreve' => '326', # U+0x012D + 'Iogonek' => '278', # U+0x012E + 'iogonek' => '326', # U+0x012F + 'Idotaccent' => '278', # U+0x0130 + 'dotlessi' => '326', # U+0x0131 + 'IJ' => '756', # U+0x0132 + 'ij' => '629', # U+0x0133 + 'Jcircumflex' => '498', # U+0x0134 + 'jcircumflex' => '387', # U+0x0135 + 'kgreenlandic' => '574', # U+0x0138 + 'Lacute' => '528', # U+0x0139 + 'lacute' => '319', # U+0x013A + 'Lcaron' => '528', # U+0x013D + 'lcaron' => '405', # U+0x013E + 'Ldot' => '528', # U+0x013F + 'ldot' => '446', # U+0x0140 + 'Lslash' => '528', # U+0x0141 + 'lslash' => '319', # U+0x0142 + 'Nacute' => '660', # U+0x0143 + 'nacute' => '562', # U+0x0144 + 'Ncaron' => '660', # U+0x0147 + 'ncaron' => '562', # U+0x0148 + 'napostrophe' => '654', # U+0x0149 + 'Eng' => '672', # U+0x014A + 'eng' => '562', # U+0x014B + 'Omacron' => '702', # U+0x014C + 'omacron' => '569', # U+0x014D + 'Obreve' => '702', # U+0x014E + 'obreve' => '569', # U+0x014F + 'Racute' => '623', # U+0x0154 + 'racute' => '446', # U+0x0155 + 'Rcaron' => '623', # U+0x0158 + 'rcaron' => '446', # U+0x0159 + 'Sacute' => '501', # U+0x015A + 'sacute' => '458', # U+0x015B + 'Scircumflex' => '501', # U+0x015C + 'scircumflex' => '458', # U+0x015D + 'Scedilla' => '501', # U+0x015E + 'scedilla' => '458', # U+0x015F + 'Tcaron' => '685', # U+0x0164 + 'tcaron' => '604', # U+0x0165 + 'Tbar' => '685', # U+0x0166 + 'tbar' => '437', # U+0x0167 + 'Utilde' => '661', # U+0x0168 + 'utilde' => '557', # U+0x0169 + 'Umacron' => '661', # U+0x016A + 'umacron' => '557', # U+0x016B + 'Ubreve' => '661', # U+0x016C + 'ubreve' => '557', # U+0x016D + 'Uring' => '661', # U+0x016E + 'uring' => '557', # U+0x016F + 'Uogonek' => '661', # U+0x0172 + 'uogonek' => '557', # U+0x0173 + 'Wcircumflex' => '926', # U+0x0174 + 'wcircumflex' => '773', # U+0x0175 + 'Ycircumflex' => '683', # U+0x0176 + 'ycircumflex' => '563', # U+0x0177 + 'Zacute' => '611', # U+0x0179 + 'zacute' => '532', # U+0x017A + 'Zdot' => '611', # U+0x017B + 'zdot' => '532', # U+0x017C + 'caron' => '585', # U+0x02C7 + 'breve' => '585', # U+0x02D8 + 'dotaccent' => '585', # U+0x02D9 + 'ring' => '585', # U+0x02DA + 'ogonek' => '585', # U+0x02DB + 'hungarumlaut' => '585', # U+0x02DD + 'Delta' => '584', # U+0x0394 + 'Omega' => '668', # U+0x03A9 + 'pi' => '601', # U+0x03C0 + 'fraction' => '585', # U+0x2044 + 'franc' => '882', # U+0x20A3 + 'partialdiff' => '576', # U+0x2202 + 'product' => '636', # U+0x220F + 'summation' => '524', # U+0x2211 + 'minus' => '585', # U+0x2212 + 'radical' => '585', # U+0x221A + 'infinity' => '585', # U+0x221E + 'integral' => '524', # U+0x222B + 'approxequal' => '585', # U+0x2248 + 'notequal' => '585', # U+0x2260 + 'lessequal' => '585', # U+0x2264 + 'greaterequal' => '585', # U+0x2265 + 'lozenge' => '600', # U+0x25CA + 'dotlessj' => '387', # U+0xF6BE + 'fi' => '668', # U+0xFB01 + 'fl' => '644', # U+0xFB02 + }, # HORIZ. WIDTH TABLE +} }; + +1; diff --git a/lib/PDF/API2/Resource/Font/CoreFont/trebuchetitalic.pm b/lib/PDF/API2/Resource/Font/CoreFont/trebuchetitalic.pm new file mode 100644 index 0000000..dc362ae --- /dev/null +++ b/lib/PDF/API2/Resource/Font/CoreFont/trebuchetitalic.pm @@ -0,0 +1,635 @@ +#line 1 "PDF/API2/Resource/Font/CoreFont/trebuchetitalic.pm" +#line 1 "PDF/API2/Resource/Font/CoreFont/trebuchetitalic.pm" +package PDF::API2::Resource::Font::CoreFont::trebuchetitalic; + +use strict; +use warnings; + +our $VERSION = '2.033'; # VERSION + +sub data { return { + 'fontname' => 'TrebuchetMS,Italic', + 'type' => 'TrueType', + 'apiname' => 'TrIt', + 'ascender' => '938', + 'capheight' => '715', + 'descender' => '-222', + 'isfixedpitch' => '0', + 'issymbol' => '0', + 'italicangle' => '-10', + 'underlineposition' => '-261', + 'underlinethickness' => '127', + 'xheight' => '522', + 'firstchar' => '32', + 'lastchar' => '255', + 'flags' => '104', + 'char' => [ # DEF. ENCODING GLYPH TABLE + '.notdef', # C+0x00 # U+0x0000 + '.notdef', # C+0x01 # U+0x0000 + '.notdef', # C+0x02 # U+0x0000 + '.notdef', # C+0x03 # U+0x0000 + '.notdef', # C+0x04 # U+0x0000 + '.notdef', # C+0x05 # U+0x0000 + '.notdef', # C+0x06 # U+0x0000 + '.notdef', # C+0x07 # U+0x0000 + '.notdef', # C+0x08 # U+0x0000 + '.notdef', # C+0x09 # U+0x0000 + '.notdef', # C+0x0A # U+0x0000 + '.notdef', # C+0x0B # U+0x0000 + '.notdef', # C+0x0C # U+0x0000 + '.notdef', # C+0x0D # U+0x0000 + '.notdef', # C+0x0E # U+0x0000 + '.notdef', # C+0x0F # U+0x0000 + '.notdef', # C+0x10 # U+0x0000 + '.notdef', # C+0x11 # U+0x0000 + '.notdef', # C+0x12 # U+0x0000 + '.notdef', # C+0x13 # U+0x0000 + '.notdef', # C+0x14 # U+0x0000 + '.notdef', # C+0x15 # U+0x0000 + '.notdef', # C+0x16 # U+0x0000 + '.notdef', # C+0x17 # U+0x0000 + '.notdef', # C+0x18 # U+0x0000 + '.notdef', # C+0x19 # U+0x0000 + '.notdef', # C+0x1A # U+0x0000 + '.notdef', # C+0x1B # U+0x0000 + '.notdef', # C+0x1C # U+0x0000 + '.notdef', # C+0x1D # U+0x0000 + '.notdef', # C+0x1E # U+0x0000 + '.notdef', # C+0x1F # U+0x0000 + 'space', # C+0x20 # U+0x0020 + 'exclam', # C+0x21 # U+0x0021 + 'quotedbl', # C+0x22 # U+0x0022 + 'numbersign', # C+0x23 # U+0x0023 + 'dollar', # C+0x24 # U+0x0024 + 'percent', # C+0x25 # U+0x0025 + 'ampersand', # C+0x26 # U+0x0026 + 'quotesingle', # C+0x27 # U+0x0027 + 'parenleft', # C+0x28 # U+0x0028 + 'parenright', # C+0x29 # U+0x0029 + 'asterisk', # C+0x2A # U+0x002A + 'plus', # C+0x2B # U+0x002B + 'comma', # C+0x2C # U+0x002C + 'hyphen', # C+0x2D # U+0x002D + 'period', # C+0x2E # U+0x002E + 'slash', # C+0x2F # U+0x002F + 'zero', # C+0x30 # U+0x0030 + 'one', # C+0x31 # U+0x0031 + 'two', # C+0x32 # U+0x0032 + 'three', # C+0x33 # U+0x0033 + 'four', # C+0x34 # U+0x0034 + 'five', # C+0x35 # U+0x0035 + 'six', # C+0x36 # U+0x0036 + 'seven', # C+0x37 # U+0x0037 + 'eight', # C+0x38 # U+0x0038 + 'nine', # C+0x39 # U+0x0039 + 'colon', # C+0x3A # U+0x003A + 'semicolon', # C+0x3B # U+0x003B + 'less', # C+0x3C # U+0x003C + 'equal', # C+0x3D # U+0x003D + 'greater', # C+0x3E # U+0x003E + 'question', # C+0x3F # U+0x003F + 'at', # C+0x40 # U+0x0040 + 'A', # C+0x41 # U+0x0041 + 'B', # C+0x42 # U+0x0042 + 'C', # C+0x43 # U+0x0043 + 'D', # C+0x44 # U+0x0044 + 'E', # C+0x45 # U+0x0045 + 'F', # C+0x46 # U+0x0046 + 'G', # C+0x47 # U+0x0047 + 'H', # C+0x48 # U+0x0048 + 'I', # C+0x49 # U+0x0049 + 'J', # C+0x4A # U+0x004A + 'K', # C+0x4B # U+0x004B + 'L', # C+0x4C # U+0x004C + 'M', # C+0x4D # U+0x004D + 'N', # C+0x4E # U+0x004E + 'O', # C+0x4F # U+0x004F + 'P', # C+0x50 # U+0x0050 + 'Q', # C+0x51 # U+0x0051 + 'R', # C+0x52 # U+0x0052 + 'S', # C+0x53 # U+0x0053 + 'T', # C+0x54 # U+0x0054 + 'U', # C+0x55 # U+0x0055 + 'V', # C+0x56 # U+0x0056 + 'W', # C+0x57 # U+0x0057 + 'X', # C+0x58 # U+0x0058 + 'Y', # C+0x59 # U+0x0059 + 'Z', # C+0x5A # U+0x005A + 'bracketleft', # C+0x5B # U+0x005B + 'backslash', # C+0x5C # U+0x005C + 'bracketright', # C+0x5D # U+0x005D + 'asciicircum', # C+0x5E # U+0x005E + 'underscore', # C+0x5F # U+0x005F + 'grave', # C+0x60 # U+0x0060 + 'a', # C+0x61 # U+0x0061 + 'b', # C+0x62 # U+0x0062 + 'c', # C+0x63 # U+0x0063 + 'd', # C+0x64 # U+0x0064 + 'e', # C+0x65 # U+0x0065 + 'f', # C+0x66 # U+0x0066 + 'g', # C+0x67 # U+0x0067 + 'h', # C+0x68 # U+0x0068 + 'i', # C+0x69 # U+0x0069 + 'j', # C+0x6A # U+0x006A + 'k', # C+0x6B # U+0x006B + 'l', # C+0x6C # U+0x006C + 'm', # C+0x6D # U+0x006D + 'n', # C+0x6E # U+0x006E + 'o', # C+0x6F # U+0x006F + 'p', # C+0x70 # U+0x0070 + 'q', # C+0x71 # U+0x0071 + 'r', # C+0x72 # U+0x0072 + 's', # C+0x73 # U+0x0073 + 't', # C+0x74 # U+0x0074 + 'u', # C+0x75 # U+0x0075 + 'v', # C+0x76 # U+0x0076 + 'w', # C+0x77 # U+0x0077 + 'x', # C+0x78 # U+0x0078 + 'y', # C+0x79 # U+0x0079 + 'z', # C+0x7A # U+0x007A + 'braceleft', # C+0x7B # U+0x007B + 'bar', # C+0x7C # U+0x007C + 'braceright', # C+0x7D # U+0x007D + 'asciitilde', # C+0x7E # U+0x007E + 'bullet', # C+0x7F # U+0x2022 + 'Euro', # C+0x80 # U+0x20AC + 'bullet', # C+0x81 # U+0x2022 + 'quotesinglbase', # C+0x82 # U+0x201A + 'florin', # C+0x83 # U+0x0192 + 'quotedblbase', # C+0x84 # U+0x201E + 'ellipsis', # C+0x85 # U+0x2026 + 'dagger', # C+0x86 # U+0x2020 + 'daggerdbl', # C+0x87 # U+0x2021 + 'circumflex', # C+0x88 # U+0x02C6 + 'perthousand', # C+0x89 # U+0x2030 + 'Scaron', # C+0x8A # U+0x0160 + 'guilsinglleft', # C+0x8B # U+0x2039 + 'OE', # C+0x8C # U+0x0152 + 'bullet', # C+0x8D # U+0x2022 + 'Zcaron', # C+0x8E # U+0x017D + 'bullet', # C+0x8F # U+0x2022 + 'bullet', # C+0x90 # U+0x2022 + 'quoteleft', # C+0x91 # U+0x2018 + 'quoteright', # C+0x92 # U+0x2019 + 'quotedblleft', # C+0x93 # U+0x201C + 'quotedblright', # C+0x94 # U+0x201D + 'bullet', # C+0x95 # U+0x2022 + 'endash', # C+0x96 # U+0x2013 + 'emdash', # C+0x97 # U+0x2014 + 'tilde', # C+0x98 # U+0x02DC + 'trademark', # C+0x99 # U+0x2122 + 'scaron', # C+0x9A # U+0x0161 + 'guilsinglright', # C+0x9B # U+0x203A + 'oe', # C+0x9C # U+0x0153 + 'bullet', # C+0x9D # U+0x2022 + 'zcaron', # C+0x9E # U+0x017E + 'Ydieresis', # C+0x9F # U+0x0178 + 'space', # C+0xA0 # U+0x0020 + 'exclamdown', # C+0xA1 # U+0x00A1 + 'cent', # C+0xA2 # U+0x00A2 + 'sterling', # C+0xA3 # U+0x00A3 + 'currency', # C+0xA4 # U+0x00A4 + 'yen', # C+0xA5 # U+0x00A5 + 'brokenbar', # C+0xA6 # U+0x00A6 + 'section', # C+0xA7 # U+0x00A7 + 'dieresis', # C+0xA8 # U+0x00A8 + 'copyright', # C+0xA9 # U+0x00A9 + 'ordfeminine', # C+0xAA # U+0x00AA + 'guillemotleft', # C+0xAB # U+0x00AB + 'logicalnot', # C+0xAC # U+0x00AC + 'hyphen', # C+0xAD # U+0x002D + 'registered', # C+0xAE # U+0x00AE + 'macron', # C+0xAF # U+0x00AF + 'degree', # C+0xB0 # U+0x00B0 + 'plusminus', # C+0xB1 # U+0x00B1 + 'twosuperior', # C+0xB2 # U+0x00B2 + 'threesuperior', # C+0xB3 # U+0x00B3 + 'acute', # C+0xB4 # U+0x00B4 + 'mu', # C+0xB5 # U+0x00B5 + 'paragraph', # C+0xB6 # U+0x00B6 + 'periodcentered', # C+0xB7 # U+0x00B7 + 'cedilla', # C+0xB8 # U+0x00B8 + 'onesuperior', # C+0xB9 # U+0x00B9 + 'ordmasculine', # C+0xBA # U+0x00BA + 'guillemotright', # C+0xBB # U+0x00BB + 'onequarter', # C+0xBC # U+0x00BC + 'onehalf', # C+0xBD # U+0x00BD + 'threequarters', # C+0xBE # U+0x00BE + 'questiondown', # C+0xBF # U+0x00BF + 'Agrave', # C+0xC0 # U+0x00C0 + 'Aacute', # C+0xC1 # U+0x00C1 + 'Acircumflex', # C+0xC2 # U+0x00C2 + 'Atilde', # C+0xC3 # U+0x00C3 + 'Adieresis', # C+0xC4 # U+0x00C4 + 'Aring', # C+0xC5 # U+0x00C5 + 'AE', # C+0xC6 # U+0x00C6 + 'Ccedilla', # C+0xC7 # U+0x00C7 + 'Egrave', # C+0xC8 # U+0x00C8 + 'Eacute', # C+0xC9 # U+0x00C9 + 'Ecircumflex', # C+0xCA # U+0x00CA + 'Edieresis', # C+0xCB # U+0x00CB + 'Igrave', # C+0xCC # U+0x00CC + 'Iacute', # C+0xCD # U+0x00CD + 'Icircumflex', # C+0xCE # U+0x00CE + 'Idieresis', # C+0xCF # U+0x00CF + 'Eth', # C+0xD0 # U+0x00D0 + 'Ntilde', # C+0xD1 # U+0x00D1 + 'Ograve', # C+0xD2 # U+0x00D2 + 'Oacute', # C+0xD3 # U+0x00D3 + 'Ocircumflex', # C+0xD4 # U+0x00D4 + 'Otilde', # C+0xD5 # U+0x00D5 + 'Odieresis', # C+0xD6 # U+0x00D6 + 'multiply', # C+0xD7 # U+0x00D7 + 'Oslash', # C+0xD8 # U+0x00D8 + 'Ugrave', # C+0xD9 # U+0x00D9 + 'Uacute', # C+0xDA # U+0x00DA + 'Ucircumflex', # C+0xDB # U+0x00DB + 'Udieresis', # C+0xDC # U+0x00DC + 'Yacute', # C+0xDD # U+0x00DD + 'Thorn', # C+0xDE # U+0x00DE + 'germandbls', # C+0xDF # U+0x00DF + 'agrave', # C+0xE0 # U+0x00E0 + 'aacute', # C+0xE1 # U+0x00E1 + 'acircumflex', # C+0xE2 # U+0x00E2 + 'atilde', # C+0xE3 # U+0x00E3 + 'adieresis', # C+0xE4 # U+0x00E4 + 'aring', # C+0xE5 # U+0x00E5 + 'ae', # C+0xE6 # U+0x00E6 + 'ccedilla', # C+0xE7 # U+0x00E7 + 'egrave', # C+0xE8 # U+0x00E8 + 'eacute', # C+0xE9 # U+0x00E9 + 'ecircumflex', # C+0xEA # U+0x00EA + 'edieresis', # C+0xEB # U+0x00EB + 'igrave', # C+0xEC # U+0x00EC + 'iacute', # C+0xED # U+0x00ED + 'icircumflex', # C+0xEE # U+0x00EE + 'idieresis', # C+0xEF # U+0x00EF + 'eth', # C+0xF0 # U+0x00F0 + 'ntilde', # C+0xF1 # U+0x00F1 + 'ograve', # C+0xF2 # U+0x00F2 + 'oacute', # C+0xF3 # U+0x00F3 + 'ocircumflex', # C+0xF4 # U+0x00F4 + 'otilde', # C+0xF5 # U+0x00F5 + 'odieresis', # C+0xF6 # U+0x00F6 + 'divide', # C+0xF7 # U+0x00F7 + 'oslash', # C+0xF8 # U+0x00F8 + 'ugrave', # C+0xF9 # U+0x00F9 + 'uacute', # C+0xFA # U+0x00FA + 'ucircumflex', # C+0xFB # U+0x00FB + 'udieresis', # C+0xFC # U+0x00FC + 'yacute', # C+0xFD # U+0x00FD + 'thorn', # C+0xFE # U+0x00FE + 'ydieresis', # C+0xFF # U+0x00FF + ], # DEF. ENCODING GLYPH TABLE + 'fontbbox' => [ -109, -257, 1107, 945 ], + 'wx' => { # HORIZ. WIDTH TABLE + 'space' => '301', # C+0x20 # U+0x0020 + 'exclam' => '367', # C+0x21 # U+0x0021 + 'quotedbl' => '324', # C+0x22 # U+0x0022 + 'numbersign' => '524', # C+0x23 # U+0x0023 + 'dollar' => '480', # C+0x24 # U+0x0024 + 'percent' => '600', # C+0x25 # U+0x0025 + 'ampersand' => '706', # C+0x26 # U+0x0026 + 'quotesingle' => '159', # C+0x27 # U+0x0027 + 'parenleft' => '367', # C+0x28 # U+0x0028 + 'parenright' => '367', # C+0x29 # U+0x0029 + 'asterisk' => '367', # C+0x2A # U+0x002A + 'plus' => '524', # C+0x2B # U+0x002B + 'comma' => '367', # C+0x2C # U+0x002C + 'hyphen' => '367', # C+0x2D # U+0x002D + 'period' => '367', # C+0x2E # U+0x002E + 'slash' => '524', # C+0x2F # U+0x002F + 'zero' => '524', # C+0x30 # U+0x0030 + 'one' => '524', # C+0x31 # U+0x0031 + 'two' => '524', # C+0x32 # U+0x0032 + 'three' => '524', # C+0x33 # U+0x0033 + 'four' => '524', # C+0x34 # U+0x0034 + 'five' => '524', # C+0x35 # U+0x0035 + 'six' => '524', # C+0x36 # U+0x0036 + 'seven' => '524', # C+0x37 # U+0x0037 + 'eight' => '524', # C+0x38 # U+0x0038 + 'nine' => '524', # C+0x39 # U+0x0039 + 'colon' => '367', # C+0x3A # U+0x003A + 'semicolon' => '367', # C+0x3B # U+0x003B + 'less' => '524', # C+0x3C # U+0x003C + 'equal' => '524', # C+0x3D # U+0x003D + 'greater' => '524', # C+0x3E # U+0x003E + 'question' => '367', # C+0x3F # U+0x003F + 'at' => '770', # C+0x40 # U+0x0040 + 'A' => '610', # C+0x41 # U+0x0041 + 'B' => '565', # C+0x42 # U+0x0042 + 'C' => '598', # C+0x43 # U+0x0043 + 'D' => '613', # C+0x44 # U+0x0044 + 'E' => '535', # C+0x45 # U+0x0045 + 'F' => '524', # C+0x46 # U+0x0046 + 'G' => '676', # C+0x47 # U+0x0047 + 'H' => '654', # C+0x48 # U+0x0048 + 'I' => '278', # C+0x49 # U+0x0049 + 'J' => '476', # C+0x4A # U+0x004A + 'K' => '575', # C+0x4B # U+0x004B + 'L' => '506', # C+0x4C # U+0x004C + 'M' => '761', # C+0x4D # U+0x004D + 'N' => '638', # C+0x4E # U+0x004E + 'O' => '673', # C+0x4F # U+0x004F + 'P' => '543', # C+0x50 # U+0x0050 + 'Q' => '673', # C+0x51 # U+0x0051 + 'R' => '582', # C+0x52 # U+0x0052 + 'S' => '480', # C+0x53 # U+0x0053 + 'T' => '580', # C+0x54 # U+0x0054 + 'U' => '648', # C+0x55 # U+0x0055 + 'V' => '587', # C+0x56 # U+0x0056 + 'W' => '852', # C+0x57 # U+0x0057 + 'X' => '556', # C+0x58 # U+0x0058 + 'Y' => '570', # C+0x59 # U+0x0059 + 'Z' => '550', # C+0x5A # U+0x005A + 'bracketleft' => '367', # C+0x5B # U+0x005B + 'backslash' => '355', # C+0x5C # U+0x005C + 'bracketright' => '367', # C+0x5D # U+0x005D + 'asciicircum' => '524', # C+0x5E # U+0x005E + 'underscore' => '524', # C+0x5F # U+0x005F + 'grave' => '524', # C+0x60 # U+0x0060 + 'a' => '525', # C+0x61 # U+0x0061 + 'b' => '557', # C+0x62 # U+0x0062 + 'c' => '459', # C+0x63 # U+0x0063 + 'd' => '557', # C+0x64 # U+0x0064 + 'e' => '537', # C+0x65 # U+0x0065 + 'f' => '401', # C+0x66 # U+0x0066 + 'g' => '501', # C+0x67 # U+0x0067 + 'h' => '557', # C+0x68 # U+0x0068 + 'i' => '306', # C+0x69 # U+0x0069 + 'j' => '366', # C+0x6A # U+0x006A + 'k' => '504', # C+0x6B # U+0x006B + 'l' => '320', # C+0x6C # U+0x006C + 'm' => '830', # C+0x6D # U+0x006D + 'n' => '546', # C+0x6E # U+0x006E + 'o' => '536', # C+0x6F # U+0x006F + 'p' => '557', # C+0x70 # U+0x0070 + 'q' => '557', # C+0x71 # U+0x0071 + 'r' => '416', # C+0x72 # U+0x0072 + 's' => '404', # C+0x73 # U+0x0073 + 't' => '419', # C+0x74 # U+0x0074 + 'u' => '556', # C+0x75 # U+0x0075 + 'v' => '489', # C+0x76 # U+0x0076 + 'w' => '744', # C+0x77 # U+0x0077 + 'x' => '500', # C+0x78 # U+0x0078 + 'y' => '493', # C+0x79 # U+0x0079 + 'z' => '474', # C+0x7A # U+0x007A + 'braceleft' => '367', # C+0x7B # U+0x007B + 'bar' => '524', # C+0x7C # U+0x007C + 'braceright' => '367', # C+0x7D # U+0x007D + 'asciitilde' => '524', # C+0x7E # U+0x007E + 'bullet' => '524', # C+0x7F # U+0x2022 + 'Euro' => '524', # C+0x80 # U+0x20AC + 'quotesinglbase' => '367', # C+0x82 # U+0x201A + 'florin' => '401', # C+0x83 # U+0x0192 + 'quotedblbase' => '524', # C+0x84 # U+0x201E + 'ellipsis' => '734', # C+0x85 # U+0x2026 + 'dagger' => '458', # C+0x86 # U+0x2020 + 'daggerdbl' => '458', # C+0x87 # U+0x2021 + 'circumflex' => '524', # C+0x88 # U+0x02C6 + 'perthousand' => '912', # C+0x89 # U+0x2030 + 'Scaron' => '480', # C+0x8A # U+0x0160 + 'guilsinglleft' => '367', # C+0x8B # U+0x2039 + 'OE' => '993', # C+0x8C # U+0x0152 + 'Zcaron' => '550', # C+0x8E # U+0x017D + 'quoteleft' => '367', # C+0x91 # U+0x2018 + 'quoteright' => '367', # C+0x92 # U+0x2019 + 'quotedblleft' => '524', # C+0x93 # U+0x201C + 'quotedblright' => '524', # C+0x94 # U+0x201D + 'endash' => '367', # C+0x96 # U+0x2013 + 'emdash' => '734', # C+0x97 # U+0x2014 + 'tilde' => '524', # C+0x98 # U+0x02DC + 'trademark' => '634', # C+0x99 # U+0x2122 + 'scaron' => '404', # C+0x9A # U+0x0161 + 'guilsinglright' => '367', # C+0x9B # U+0x203A + 'oe' => '891', # C+0x9C # U+0x0153 + 'zcaron' => '474', # C+0x9E # U+0x017E + 'Ydieresis' => '570', # C+0x9F # U+0x0178 + 'exclamdown' => '367', # C+0xA1 # U+0x00A1 + 'cent' => '524', # C+0xA2 # U+0x00A2 + 'sterling' => '529', # C+0xA3 # U+0x00A3 + 'currency' => '524', # C+0xA4 # U+0x00A4 + 'yen' => '556', # C+0xA5 # U+0x00A5 + 'brokenbar' => '524', # C+0xA6 # U+0x00A6 + 'section' => '453', # C+0xA7 # U+0x00A7 + 'dieresis' => '524', # C+0xA8 # U+0x00A8 + 'copyright' => '712', # C+0xA9 # U+0x00A9 + 'ordfeminine' => '452', # C+0xAA # U+0x00AA + 'guillemotleft' => '524', # C+0xAB # U+0x00AB + 'logicalnot' => '524', # C+0xAC # U+0x00AC + 'registered' => '712', # C+0xAE # U+0x00AE + 'macron' => '524', # C+0xAF # U+0x00AF + 'degree' => '524', # C+0xB0 # U+0x00B0 + 'plusminus' => '524', # C+0xB1 # U+0x00B1 + 'twosuperior' => '451', # C+0xB2 # U+0x00B2 + 'threesuperior' => '451', # C+0xB3 # U+0x00B3 + 'acute' => '524', # C+0xB4 # U+0x00B4 + 'mu' => '556', # C+0xB5 # U+0x00B5 + 'paragraph' => '598', # C+0xB6 # U+0x00B6 + 'periodcentered' => '367', # C+0xB7 # U+0x00B7 + 'cedilla' => '524', # C+0xB8 # U+0x00B8 + 'onesuperior' => '451', # C+0xB9 # U+0x00B9 + 'ordmasculine' => '458', # C+0xBA # U+0x00BA + 'guillemotright' => '524', # C+0xBB # U+0x00BB + 'onequarter' => '814', # C+0xBC # U+0x00BC + 'onehalf' => '814', # C+0xBD # U+0x00BD + 'threequarters' => '814', # C+0xBE # U+0x00BE + 'questiondown' => '367', # C+0xBF # U+0x00BF + 'Agrave' => '610', # C+0xC0 # U+0x00C0 + 'Aacute' => '610', # C+0xC1 # U+0x00C1 + 'Acircumflex' => '610', # C+0xC2 # U+0x00C2 + 'Atilde' => '610', # C+0xC3 # U+0x00C3 + 'Adieresis' => '610', # C+0xC4 # U+0x00C4 + 'Aring' => '610', # C+0xC5 # U+0x00C5 + 'AE' => '866', # C+0xC6 # U+0x00C6 + 'Ccedilla' => '598', # C+0xC7 # U+0x00C7 + 'Egrave' => '535', # C+0xC8 # U+0x00C8 + 'Eacute' => '535', # C+0xC9 # U+0x00C9 + 'Ecircumflex' => '535', # C+0xCA # U+0x00CA + 'Edieresis' => '535', # C+0xCB # U+0x00CB + 'Igrave' => '278', # C+0xCC # U+0x00CC + 'Iacute' => '278', # C+0xCD # U+0x00CD + 'Icircumflex' => '278', # C+0xCE # U+0x00CE + 'Idieresis' => '278', # C+0xCF # U+0x00CF + 'Eth' => '613', # C+0xD0 # U+0x00D0 + 'Ntilde' => '638', # C+0xD1 # U+0x00D1 + 'Ograve' => '673', # C+0xD2 # U+0x00D2 + 'Oacute' => '673', # C+0xD3 # U+0x00D3 + 'Ocircumflex' => '673', # C+0xD4 # U+0x00D4 + 'Otilde' => '673', # C+0xD5 # U+0x00D5 + 'Odieresis' => '673', # C+0xD6 # U+0x00D6 + 'multiply' => '524', # C+0xD7 # U+0x00D7 + 'Oslash' => '673', # C+0xD8 # U+0x00D8 + 'Ugrave' => '648', # C+0xD9 # U+0x00D9 + 'Uacute' => '648', # C+0xDA # U+0x00DA + 'Ucircumflex' => '648', # C+0xDB # U+0x00DB + 'Udieresis' => '648', # C+0xDC # U+0x00DC + 'Yacute' => '570', # C+0xDD # U+0x00DD + 'Thorn' => '543', # C+0xDE # U+0x00DE + 'germandbls' => '546', # C+0xDF # U+0x00DF + 'agrave' => '525', # C+0xE0 # U+0x00E0 + 'aacute' => '525', # C+0xE1 # U+0x00E1 + 'acircumflex' => '525', # C+0xE2 # U+0x00E2 + 'atilde' => '525', # C+0xE3 # U+0x00E3 + 'adieresis' => '525', # C+0xE4 # U+0x00E4 + 'aring' => '525', # C+0xE5 # U+0x00E5 + 'ae' => '844', # C+0xE6 # U+0x00E6 + 'ccedilla' => '459', # C+0xE7 # U+0x00E7 + 'egrave' => '537', # C+0xE8 # U+0x00E8 + 'eacute' => '537', # C+0xE9 # U+0x00E9 + 'ecircumflex' => '537', # C+0xEA # U+0x00EA + 'edieresis' => '537', # C+0xEB # U+0x00EB + 'igrave' => '306', # C+0xEC # U+0x00EC + 'iacute' => '306', # C+0xED # U+0x00ED + 'icircumflex' => '306', # C+0xEE # U+0x00EE + 'idieresis' => '306', # C+0xEF # U+0x00EF + 'eth' => '549', # C+0xF0 # U+0x00F0 + 'ntilde' => '546', # C+0xF1 # U+0x00F1 + 'ograve' => '536', # C+0xF2 # U+0x00F2 + 'oacute' => '536', # C+0xF3 # U+0x00F3 + 'ocircumflex' => '536', # C+0xF4 # U+0x00F4 + 'otilde' => '536', # C+0xF5 # U+0x00F5 + 'odieresis' => '536', # C+0xF6 # U+0x00F6 + 'divide' => '524', # C+0xF7 # U+0x00F7 + 'oslash' => '536', # C+0xF8 # U+0x00F8 + 'ugrave' => '556', # C+0xF9 # U+0x00F9 + 'uacute' => '556', # C+0xFA # U+0x00FA + 'ucircumflex' => '556', # C+0xFB # U+0x00FB + 'udieresis' => '556', # C+0xFC # U+0x00FC + 'yacute' => '493', # C+0xFD # U+0x00FD + 'thorn' => '557', # C+0xFE # U+0x00FE + 'ydieresis' => '493', # C+0xFF # U+0x00FF + 'middot' => '367', # U+0x00B7 + 'Amacron' => '610', # U+0x0100 + 'amacron' => '525', # U+0x0101 + 'Abreve' => '610', # U+0x0102 + 'abreve' => '525', # U+0x0103 + 'Aogonek' => '610', # U+0x0104 + 'aogonek' => '525', # U+0x0105 + 'Cacute' => '598', # U+0x0106 + 'cacute' => '459', # U+0x0107 + 'Ccircumflex' => '598', # U+0x0108 + 'ccircumflex' => '459', # U+0x0109 + 'Cdot' => '598', # U+0x010A + 'cdot' => '459', # U+0x010B + 'Ccaron' => '598', # U+0x010C + 'ccaron' => '459', # U+0x010D + 'Dcaron' => '613', # U+0x010E + 'dcaron' => '691', # U+0x010F + 'dcroat' => '557', # U+0x0111 + 'Emacron' => '535', # U+0x0112 + 'emacron' => '537', # U+0x0113 + 'Ebreve' => '535', # U+0x0114 + 'ebreve' => '537', # U+0x0115 + 'Edot' => '535', # U+0x0116 + 'edot' => '537', # U+0x0117 + 'Eogonek' => '535', # U+0x0118 + 'eogonek' => '537', # U+0x0119 + 'Ecaron' => '535', # U+0x011A + 'ecaron' => '537', # U+0x011B + 'Gcircumflex' => '676', # U+0x011C + 'gcircumflex' => '501', # U+0x011D + 'Gbreve' => '676', # U+0x011E + 'gbreve' => '501', # U+0x011F + 'Gdot' => '676', # U+0x0120 + 'gdot' => '501', # U+0x0121 + 'Hcircumflex' => '654', # U+0x0124 + 'hcircumflex' => '557', # U+0x0125 + 'Hbar' => '682', # U+0x0126 + 'hbar' => '553', # U+0x0127 + 'Itilde' => '278', # U+0x0128 + 'itilde' => '306', # U+0x0129 + 'Imacron' => '278', # U+0x012A + 'imacron' => '306', # U+0x012B + 'Ibreve' => '278', # U+0x012C + 'ibreve' => '306', # U+0x012D + 'Iogonek' => '278', # U+0x012E + 'iogonek' => '306', # U+0x012F + 'Idotaccent' => '278', # U+0x0130 + 'dotlessi' => '306', # U+0x0131 + 'IJ' => '727', # U+0x0132 + 'ij' => '585', # U+0x0133 + 'Jcircumflex' => '476', # U+0x0134 + 'jcircumflex' => '366', # U+0x0135 + 'kgreenlandic' => '537', # U+0x0138 + 'Lacute' => '506', # U+0x0139 + 'lacute' => '320', # U+0x013A + 'Lcaron' => '506', # U+0x013D + 'lcaron' => '320', # U+0x013E + 'Ldot' => '506', # U+0x013F + 'ldot' => '506', # U+0x0140 + 'Lslash' => '506', # U+0x0141 + 'lslash' => '294', # U+0x0142 + 'Nacute' => '638', # U+0x0143 + 'nacute' => '546', # U+0x0144 + 'Ncaron' => '638', # U+0x0147 + 'ncaron' => '546', # U+0x0148 + 'napostrophe' => '604', # U+0x0149 + 'Eng' => '651', # U+0x014A + 'eng' => '546', # U+0x014B + 'Omacron' => '673', # U+0x014C + 'omacron' => '536', # U+0x014D + 'Obreve' => '673', # U+0x014E + 'obreve' => '536', # U+0x014F + 'Racute' => '582', # U+0x0154 + 'racute' => '416', # U+0x0155 + 'Rcaron' => '582', # U+0x0158 + 'rcaron' => '416', # U+0x0159 + 'Sacute' => '480', # U+0x015A + 'sacute' => '404', # U+0x015B + 'Scircumflex' => '480', # U+0x015C + 'scircumflex' => '404', # U+0x015D + 'Scedilla' => '480', # U+0x015E + 'scedilla' => '404', # U+0x015F + 'Tcaron' => '580', # U+0x0164 + 'tcaron' => '496', # U+0x0165 + 'Tbar' => '580', # U+0x0166 + 'tbar' => '419', # U+0x0167 + 'Utilde' => '648', # U+0x0168 + 'utilde' => '556', # U+0x0169 + 'Umacron' => '648', # U+0x016A + 'umacron' => '556', # U+0x016B + 'Ubreve' => '648', # U+0x016C + 'ubreve' => '556', # U+0x016D + 'Uring' => '648', # U+0x016E + 'uring' => '556', # U+0x016F + 'Uogonek' => '648', # U+0x0172 + 'uogonek' => '556', # U+0x0173 + 'Wcircumflex' => '852', # U+0x0174 + 'wcircumflex' => '744', # U+0x0175 + 'Ycircumflex' => '570', # U+0x0176 + 'ycircumflex' => '493', # U+0x0177 + 'Zacute' => '550', # U+0x0179 + 'zacute' => '474', # U+0x017A + 'Zdot' => '550', # U+0x017B + 'zdot' => '474', # U+0x017C + 'caron' => '524', # U+0x02C7 + 'breve' => '524', # U+0x02D8 + 'dotaccent' => '524', # U+0x02D9 + 'ring' => '524', # U+0x02DA + 'ogonek' => '524', # U+0x02DB + 'hungarumlaut' => '524', # U+0x02DD + 'Delta' => '584', # U+0x0394 + 'Omega' => '668', # U+0x03A9 + 'pi' => '601', # U+0x03C0 + 'fraction' => '528', # U+0x2044 + 'franc' => '941', # U+0x20A3 + 'partialdiff' => '549', # U+0x2202 + 'product' => '552', # U+0x220F + 'summation' => '524', # U+0x2211 + 'minus' => '524', # U+0x2212 + 'radical' => '524', # U+0x221A + 'infinity' => '524', # U+0x221E + 'integral' => '524', # U+0x222B + 'approxequal' => '524', # U+0x2248 + 'notequal' => '524', # U+0x2260 + 'lessequal' => '524', # U+0x2264 + 'greaterequal' => '524', # U+0x2265 + 'lozenge' => '494', # U+0x25CA + 'dotlessj' => '366', # U+0xF6BE + 'fi' => '636', # U+0xFB01 + 'fl' => '672', # U+0xFB02 + }, # HORIZ. WIDTH TABLE +} }; + +1; diff --git a/lib/PDF/API2/Resource/Font/CoreFont/verdana.pm b/lib/PDF/API2/Resource/Font/CoreFont/verdana.pm new file mode 100644 index 0000000..245a4f9 --- /dev/null +++ b/lib/PDF/API2/Resource/Font/CoreFont/verdana.pm @@ -0,0 +1,844 @@ +#line 1 "PDF/API2/Resource/Font/CoreFont/verdana.pm" +#line 1 "PDF/API2/Resource/Font/CoreFont/verdana.pm" +package PDF::API2::Resource::Font::CoreFont::verdana; + +use strict; +use warnings; + +our $VERSION = '2.033'; # VERSION + +sub data { return { + 'fontname' => 'Verdana', + 'type' => 'TrueType', + 'apiname' => 'Verd', + 'ascender' => '1005', + 'capheight' => '727', + 'descender' => '-209', + 'isfixedpitch' => '0', + 'issymbol' => '0', + 'italicangle' => '0', + 'underlineposition' => '-180', + 'underlinethickness' => '120', + 'xheight' => '545', + 'firstchar' => '32', + 'lastchar' => '255', + 'flags' => '40', + 'char' => [ # DEF. ENCODING GLYPH TABLE + '.notdef', # C+0x00 # U+0x0000 + '.notdef', # C+0x01 # U+0x0000 + '.notdef', # C+0x02 # U+0x0000 + '.notdef', # C+0x03 # U+0x0000 + '.notdef', # C+0x04 # U+0x0000 + '.notdef', # C+0x05 # U+0x0000 + '.notdef', # C+0x06 # U+0x0000 + '.notdef', # C+0x07 # U+0x0000 + '.notdef', # C+0x08 # U+0x0000 + '.notdef', # C+0x09 # U+0x0000 + '.notdef', # C+0x0A # U+0x0000 + '.notdef', # C+0x0B # U+0x0000 + '.notdef', # C+0x0C # U+0x0000 + '.notdef', # C+0x0D # U+0x0000 + '.notdef', # C+0x0E # U+0x0000 + '.notdef', # C+0x0F # U+0x0000 + '.notdef', # C+0x10 # U+0x0000 + '.notdef', # C+0x11 # U+0x0000 + '.notdef', # C+0x12 # U+0x0000 + '.notdef', # C+0x13 # U+0x0000 + '.notdef', # C+0x14 # U+0x0000 + '.notdef', # C+0x15 # U+0x0000 + '.notdef', # C+0x16 # U+0x0000 + '.notdef', # C+0x17 # U+0x0000 + '.notdef', # C+0x18 # U+0x0000 + '.notdef', # C+0x19 # U+0x0000 + '.notdef', # C+0x1A # U+0x0000 + '.notdef', # C+0x1B # U+0x0000 + '.notdef', # C+0x1C # U+0x0000 + '.notdef', # C+0x1D # U+0x0000 + '.notdef', # C+0x1E # U+0x0000 + '.notdef', # C+0x1F # U+0x0000 + 'space', # C+0x20 # U+0x0020 + 'exclam', # C+0x21 # U+0x0021 + 'quotedbl', # C+0x22 # U+0x0022 + 'numbersign', # C+0x23 # U+0x0023 + 'dollar', # C+0x24 # U+0x0024 + 'percent', # C+0x25 # U+0x0025 + 'ampersand', # C+0x26 # U+0x0026 + 'quotesingle', # C+0x27 # U+0x0027 + 'parenleft', # C+0x28 # U+0x0028 + 'parenright', # C+0x29 # U+0x0029 + 'asterisk', # C+0x2A # U+0x002A + 'plus', # C+0x2B # U+0x002B + 'comma', # C+0x2C # U+0x002C + 'hyphen', # C+0x2D # U+0x002D + 'period', # C+0x2E # U+0x002E + 'slash', # C+0x2F # U+0x002F + 'zero', # C+0x30 # U+0x0030 + 'one', # C+0x31 # U+0x0031 + 'two', # C+0x32 # U+0x0032 + 'three', # C+0x33 # U+0x0033 + 'four', # C+0x34 # U+0x0034 + 'five', # C+0x35 # U+0x0035 + 'six', # C+0x36 # U+0x0036 + 'seven', # C+0x37 # U+0x0037 + 'eight', # C+0x38 # U+0x0038 + 'nine', # C+0x39 # U+0x0039 + 'colon', # C+0x3A # U+0x003A + 'semicolon', # C+0x3B # U+0x003B + 'less', # C+0x3C # U+0x003C + 'equal', # C+0x3D # U+0x003D + 'greater', # C+0x3E # U+0x003E + 'question', # C+0x3F # U+0x003F + 'at', # C+0x40 # U+0x0040 + 'A', # C+0x41 # U+0x0041 + 'B', # C+0x42 # U+0x0042 + 'C', # C+0x43 # U+0x0043 + 'D', # C+0x44 # U+0x0044 + 'E', # C+0x45 # U+0x0045 + 'F', # C+0x46 # U+0x0046 + 'G', # C+0x47 # U+0x0047 + 'H', # C+0x48 # U+0x0048 + 'I', # C+0x49 # U+0x0049 + 'J', # C+0x4A # U+0x004A + 'K', # C+0x4B # U+0x004B + 'L', # C+0x4C # U+0x004C + 'M', # C+0x4D # U+0x004D + 'N', # C+0x4E # U+0x004E + 'O', # C+0x4F # U+0x004F + 'P', # C+0x50 # U+0x0050 + 'Q', # C+0x51 # U+0x0051 + 'R', # C+0x52 # U+0x0052 + 'S', # C+0x53 # U+0x0053 + 'T', # C+0x54 # U+0x0054 + 'U', # C+0x55 # U+0x0055 + 'V', # C+0x56 # U+0x0056 + 'W', # C+0x57 # U+0x0057 + 'X', # C+0x58 # U+0x0058 + 'Y', # C+0x59 # U+0x0059 + 'Z', # C+0x5A # U+0x005A + 'bracketleft', # C+0x5B # U+0x005B + 'backslash', # C+0x5C # U+0x005C + 'bracketright', # C+0x5D # U+0x005D + 'asciicircum', # C+0x5E # U+0x005E + 'underscore', # C+0x5F # U+0x005F + 'grave', # C+0x60 # U+0x0060 + 'a', # C+0x61 # U+0x0061 + 'b', # C+0x62 # U+0x0062 + 'c', # C+0x63 # U+0x0063 + 'd', # C+0x64 # U+0x0064 + 'e', # C+0x65 # U+0x0065 + 'f', # C+0x66 # U+0x0066 + 'g', # C+0x67 # U+0x0067 + 'h', # C+0x68 # U+0x0068 + 'i', # C+0x69 # U+0x0069 + 'j', # C+0x6A # U+0x006A + 'k', # C+0x6B # U+0x006B + 'l', # C+0x6C # U+0x006C + 'm', # C+0x6D # U+0x006D + 'n', # C+0x6E # U+0x006E + 'o', # C+0x6F # U+0x006F + 'p', # C+0x70 # U+0x0070 + 'q', # C+0x71 # U+0x0071 + 'r', # C+0x72 # U+0x0072 + 's', # C+0x73 # U+0x0073 + 't', # C+0x74 # U+0x0074 + 'u', # C+0x75 # U+0x0075 + 'v', # C+0x76 # U+0x0076 + 'w', # C+0x77 # U+0x0077 + 'x', # C+0x78 # U+0x0078 + 'y', # C+0x79 # U+0x0079 + 'z', # C+0x7A # U+0x007A + 'braceleft', # C+0x7B # U+0x007B + 'bar', # C+0x7C # U+0x007C + 'braceright', # C+0x7D # U+0x007D + 'asciitilde', # C+0x7E # U+0x007E + 'bullet', # C+0x7F # U+0x2022 + 'Euro', # C+0x80 # U+0x20AC + 'bullet', # C+0x81 # U+0x2022 + 'quotesinglbase', # C+0x82 # U+0x201A + 'florin', # C+0x83 # U+0x0192 + 'quotedblbase', # C+0x84 # U+0x201E + 'ellipsis', # C+0x85 # U+0x2026 + 'dagger', # C+0x86 # U+0x2020 + 'daggerdbl', # C+0x87 # U+0x2021 + 'circumflex', # C+0x88 # U+0x02C6 + 'perthousand', # C+0x89 # U+0x2030 + 'Scaron', # C+0x8A # U+0x0160 + 'guilsinglleft', # C+0x8B # U+0x2039 + 'OE', # C+0x8C # U+0x0152 + 'bullet', # C+0x8D # U+0x2022 + 'Zcaron', # C+0x8E # U+0x017D + 'bullet', # C+0x8F # U+0x2022 + 'bullet', # C+0x90 # U+0x2022 + 'quoteleft', # C+0x91 # U+0x2018 + 'quoteright', # C+0x92 # U+0x2019 + 'quotedblleft', # C+0x93 # U+0x201C + 'quotedblright', # C+0x94 # U+0x201D + 'bullet', # C+0x95 # U+0x2022 + 'endash', # C+0x96 # U+0x2013 + 'emdash', # C+0x97 # U+0x2014 + 'tilde', # C+0x98 # U+0x02DC + 'trademark', # C+0x99 # U+0x2122 + 'scaron', # C+0x9A # U+0x0161 + 'guilsinglright', # C+0x9B # U+0x203A + 'oe', # C+0x9C # U+0x0153 + 'bullet', # C+0x9D # U+0x2022 + 'zcaron', # C+0x9E # U+0x017E + 'Ydieresis', # C+0x9F # U+0x0178 + 'space', # C+0xA0 # U+0x0020 + 'exclamdown', # C+0xA1 # U+0x00A1 + 'cent', # C+0xA2 # U+0x00A2 + 'sterling', # C+0xA3 # U+0x00A3 + 'currency', # C+0xA4 # U+0x00A4 + 'yen', # C+0xA5 # U+0x00A5 + 'brokenbar', # C+0xA6 # U+0x00A6 + 'section', # C+0xA7 # U+0x00A7 + 'dieresis', # C+0xA8 # U+0x00A8 + 'copyright', # C+0xA9 # U+0x00A9 + 'ordfeminine', # C+0xAA # U+0x00AA + 'guillemotleft', # C+0xAB # U+0x00AB + 'logicalnot', # C+0xAC # U+0x00AC + 'hyphen', # C+0xAD # U+0x002D + 'registered', # C+0xAE # U+0x00AE + 'macron', # C+0xAF # U+0x00AF + 'degree', # C+0xB0 # U+0x00B0 + 'plusminus', # C+0xB1 # U+0x00B1 + 'twosuperior', # C+0xB2 # U+0x00B2 + 'threesuperior', # C+0xB3 # U+0x00B3 + 'acute', # C+0xB4 # U+0x00B4 + 'mu', # C+0xB5 # U+0x00B5 + 'paragraph', # C+0xB6 # U+0x00B6 + 'periodcentered', # C+0xB7 # U+0x00B7 + 'cedilla', # C+0xB8 # U+0x00B8 + 'onesuperior', # C+0xB9 # U+0x00B9 + 'ordmasculine', # C+0xBA # U+0x00BA + 'guillemotright', # C+0xBB # U+0x00BB + 'onequarter', # C+0xBC # U+0x00BC + 'onehalf', # C+0xBD # U+0x00BD + 'threequarters', # C+0xBE # U+0x00BE + 'questiondown', # C+0xBF # U+0x00BF + 'Agrave', # C+0xC0 # U+0x00C0 + 'Aacute', # C+0xC1 # U+0x00C1 + 'Acircumflex', # C+0xC2 # U+0x00C2 + 'Atilde', # C+0xC3 # U+0x00C3 + 'Adieresis', # C+0xC4 # U+0x00C4 + 'Aring', # C+0xC5 # U+0x00C5 + 'AE', # C+0xC6 # U+0x00C6 + 'Ccedilla', # C+0xC7 # U+0x00C7 + 'Egrave', # C+0xC8 # U+0x00C8 + 'Eacute', # C+0xC9 # U+0x00C9 + 'Ecircumflex', # C+0xCA # U+0x00CA + 'Edieresis', # C+0xCB # U+0x00CB + 'Igrave', # C+0xCC # U+0x00CC + 'Iacute', # C+0xCD # U+0x00CD + 'Icircumflex', # C+0xCE # U+0x00CE + 'Idieresis', # C+0xCF # U+0x00CF + 'Eth', # C+0xD0 # U+0x00D0 + 'Ntilde', # C+0xD1 # U+0x00D1 + 'Ograve', # C+0xD2 # U+0x00D2 + 'Oacute', # C+0xD3 # U+0x00D3 + 'Ocircumflex', # C+0xD4 # U+0x00D4 + 'Otilde', # C+0xD5 # U+0x00D5 + 'Odieresis', # C+0xD6 # U+0x00D6 + 'multiply', # C+0xD7 # U+0x00D7 + 'Oslash', # C+0xD8 # U+0x00D8 + 'Ugrave', # C+0xD9 # U+0x00D9 + 'Uacute', # C+0xDA # U+0x00DA + 'Ucircumflex', # C+0xDB # U+0x00DB + 'Udieresis', # C+0xDC # U+0x00DC + 'Yacute', # C+0xDD # U+0x00DD + 'Thorn', # C+0xDE # U+0x00DE + 'germandbls', # C+0xDF # U+0x00DF + 'agrave', # C+0xE0 # U+0x00E0 + 'aacute', # C+0xE1 # U+0x00E1 + 'acircumflex', # C+0xE2 # U+0x00E2 + 'atilde', # C+0xE3 # U+0x00E3 + 'adieresis', # C+0xE4 # U+0x00E4 + 'aring', # C+0xE5 # U+0x00E5 + 'ae', # C+0xE6 # U+0x00E6 + 'ccedilla', # C+0xE7 # U+0x00E7 + 'egrave', # C+0xE8 # U+0x00E8 + 'eacute', # C+0xE9 # U+0x00E9 + 'ecircumflex', # C+0xEA # U+0x00EA + 'edieresis', # C+0xEB # U+0x00EB + 'igrave', # C+0xEC # U+0x00EC + 'iacute', # C+0xED # U+0x00ED + 'icircumflex', # C+0xEE # U+0x00EE + 'idieresis', # C+0xEF # U+0x00EF + 'eth', # C+0xF0 # U+0x00F0 + 'ntilde', # C+0xF1 # U+0x00F1 + 'ograve', # C+0xF2 # U+0x00F2 + 'oacute', # C+0xF3 # U+0x00F3 + 'ocircumflex', # C+0xF4 # U+0x00F4 + 'otilde', # C+0xF5 # U+0x00F5 + 'odieresis', # C+0xF6 # U+0x00F6 + 'divide', # C+0xF7 # U+0x00F7 + 'oslash', # C+0xF8 # U+0x00F8 + 'ugrave', # C+0xF9 # U+0x00F9 + 'uacute', # C+0xFA # U+0x00FA + 'ucircumflex', # C+0xFB # U+0x00FB + 'udieresis', # C+0xFC # U+0x00FC + 'yacute', # C+0xFD # U+0x00FD + 'thorn', # C+0xFE # U+0x00FE + 'ydieresis', # C+0xFF # U+0x00FF + ], # DEF. ENCODING GLYPH TABLE + 'fontbbox' => [ -49, -206, 1446, 1000 ], + 'wx' => { # HORIZ. WIDTH TABLE + 'space' => '351', # C+0x20 # U+0x0020 + 'exclam' => '393', # C+0x21 # U+0x0021 + 'quotedbl' => '458', # C+0x22 # U+0x0022 + 'numbersign' => '818', # C+0x23 # U+0x0023 + 'dollar' => '635', # C+0x24 # U+0x0024 + 'percent' => '1076', # C+0x25 # U+0x0025 + 'ampersand' => '726', # C+0x26 # U+0x0026 + 'quotesingle' => '268', # C+0x27 # U+0x0027 + 'parenleft' => '454', # C+0x28 # U+0x0028 + 'parenright' => '454', # C+0x29 # U+0x0029 + 'asterisk' => '635', # C+0x2A # U+0x002A + 'plus' => '818', # C+0x2B # U+0x002B + 'comma' => '363', # C+0x2C # U+0x002C + 'hyphen' => '454', # C+0x2D # U+0x002D + 'period' => '363', # C+0x2E # U+0x002E + 'slash' => '454', # C+0x2F # U+0x002F + 'zero' => '635', # C+0x30 # U+0x0030 + 'one' => '635', # C+0x31 # U+0x0031 + 'two' => '635', # C+0x32 # U+0x0032 + 'three' => '635', # C+0x33 # U+0x0033 + 'four' => '635', # C+0x34 # U+0x0034 + 'five' => '635', # C+0x35 # U+0x0035 + 'six' => '635', # C+0x36 # U+0x0036 + 'seven' => '635', # C+0x37 # U+0x0037 + 'eight' => '635', # C+0x38 # U+0x0038 + 'nine' => '635', # C+0x39 # U+0x0039 + 'colon' => '454', # C+0x3A # U+0x003A + 'semicolon' => '454', # C+0x3B # U+0x003B + 'less' => '818', # C+0x3C # U+0x003C + 'equal' => '818', # C+0x3D # U+0x003D + 'greater' => '818', # C+0x3E # U+0x003E + 'question' => '545', # C+0x3F # U+0x003F + 'at' => '1000', # C+0x40 # U+0x0040 + 'A' => '683', # C+0x41 # U+0x0041 + 'B' => '685', # C+0x42 # U+0x0042 + 'C' => '698', # C+0x43 # U+0x0043 + 'D' => '770', # C+0x44 # U+0x0044 + 'E' => '632', # C+0x45 # U+0x0045 + 'F' => '574', # C+0x46 # U+0x0046 + 'G' => '775', # C+0x47 # U+0x0047 + 'H' => '751', # C+0x48 # U+0x0048 + 'I' => '420', # C+0x49 # U+0x0049 + 'J' => '454', # C+0x4A # U+0x004A + 'K' => '692', # C+0x4B # U+0x004B + 'L' => '556', # C+0x4C # U+0x004C + 'M' => '842', # C+0x4D # U+0x004D + 'N' => '748', # C+0x4E # U+0x004E + 'O' => '787', # C+0x4F # U+0x004F + 'P' => '603', # C+0x50 # U+0x0050 + 'Q' => '787', # C+0x51 # U+0x0051 + 'R' => '695', # C+0x52 # U+0x0052 + 'S' => '683', # C+0x53 # U+0x0053 + 'T' => '616', # C+0x54 # U+0x0054 + 'U' => '731', # C+0x55 # U+0x0055 + 'V' => '683', # C+0x56 # U+0x0056 + 'W' => '988', # C+0x57 # U+0x0057 + 'X' => '685', # C+0x58 # U+0x0058 + 'Y' => '615', # C+0x59 # U+0x0059 + 'Z' => '685', # C+0x5A # U+0x005A + 'bracketleft' => '454', # C+0x5B # U+0x005B + 'backslash' => '454', # C+0x5C # U+0x005C + 'bracketright' => '454', # C+0x5D # U+0x005D + 'asciicircum' => '818', # C+0x5E # U+0x005E + 'underscore' => '635', # C+0x5F # U+0x005F + 'grave' => '635', # C+0x60 # U+0x0060 + 'a' => '600', # C+0x61 # U+0x0061 + 'b' => '623', # C+0x62 # U+0x0062 + 'c' => '520', # C+0x63 # U+0x0063 + 'd' => '623', # C+0x64 # U+0x0064 + 'e' => '595', # C+0x65 # U+0x0065 + 'f' => '351', # C+0x66 # U+0x0066 + 'g' => '623', # C+0x67 # U+0x0067 + 'h' => '632', # C+0x68 # U+0x0068 + 'i' => '274', # C+0x69 # U+0x0069 + 'j' => '344', # C+0x6A # U+0x006A + 'k' => '591', # C+0x6B # U+0x006B + 'l' => '274', # C+0x6C # U+0x006C + 'm' => '972', # C+0x6D # U+0x006D + 'n' => '632', # C+0x6E # U+0x006E + 'o' => '606', # C+0x6F # U+0x006F + 'p' => '623', # C+0x70 # U+0x0070 + 'q' => '623', # C+0x71 # U+0x0071 + 'r' => '426', # C+0x72 # U+0x0072 + 's' => '520', # C+0x73 # U+0x0073 + 't' => '394', # C+0x74 # U+0x0074 + 'u' => '632', # C+0x75 # U+0x0075 + 'v' => '591', # C+0x76 # U+0x0076 + 'w' => '818', # C+0x77 # U+0x0077 + 'x' => '591', # C+0x78 # U+0x0078 + 'y' => '591', # C+0x79 # U+0x0079 + 'z' => '525', # C+0x7A # U+0x007A + 'braceleft' => '634', # C+0x7B # U+0x007B + 'bar' => '454', # C+0x7C # U+0x007C + 'braceright' => '634', # C+0x7D # U+0x007D + 'asciitilde' => '818', # C+0x7E # U+0x007E + 'bullet' => '545', # C+0x7F # U+0x2022 + 'Euro' => '635', # C+0x80 # U+0x20AC + 'quotesinglbase' => '268', # C+0x82 # U+0x201A + 'florin' => '635', # C+0x83 # U+0x0192 + 'quotedblbase' => '458', # C+0x84 # U+0x201E + 'ellipsis' => '818', # C+0x85 # U+0x2026 + 'dagger' => '635', # C+0x86 # U+0x2020 + 'daggerdbl' => '635', # C+0x87 # U+0x2021 + 'circumflex' => '635', # C+0x88 # U+0x02C6 + 'perthousand' => '1521', # C+0x89 # U+0x2030 + 'Scaron' => '683', # C+0x8A # U+0x0160 + 'guilsinglleft' => '454', # C+0x8B # U+0x2039 + 'OE' => '1069', # C+0x8C # U+0x0152 + 'Zcaron' => '685', # C+0x8E # U+0x017D + 'quoteleft' => '268', # C+0x91 # U+0x2018 + 'quoteright' => '268', # C+0x92 # U+0x2019 + 'quotedblleft' => '458', # C+0x93 # U+0x201C + 'quotedblright' => '458', # C+0x94 # U+0x201D + 'endash' => '635', # C+0x96 # U+0x2013 + 'emdash' => '1000', # C+0x97 # U+0x2014 + 'tilde' => '635', # C+0x98 # U+0x02DC + 'trademark' => '976', # C+0x99 # U+0x2122 + 'scaron' => '520', # C+0x9A # U+0x0161 + 'guilsinglright' => '454', # C+0x9B # U+0x203A + 'oe' => '981', # C+0x9C # U+0x0153 + 'zcaron' => '525', # C+0x9E # U+0x017E + 'Ydieresis' => '615', # C+0x9F # U+0x0178 + 'exclamdown' => '393', # C+0xA1 # U+0x00A1 + 'cent' => '635', # C+0xA2 # U+0x00A2 + 'sterling' => '635', # C+0xA3 # U+0x00A3 + 'currency' => '635', # C+0xA4 # U+0x00A4 + 'yen' => '635', # C+0xA5 # U+0x00A5 + 'brokenbar' => '454', # C+0xA6 # U+0x00A6 + 'section' => '635', # C+0xA7 # U+0x00A7 + 'dieresis' => '635', # C+0xA8 # U+0x00A8 + 'copyright' => '1000', # C+0xA9 # U+0x00A9 + 'ordfeminine' => '545', # C+0xAA # U+0x00AA + 'guillemotleft' => '644', # C+0xAB # U+0x00AB + 'logicalnot' => '818', # C+0xAC # U+0x00AC + 'registered' => '1000', # C+0xAE # U+0x00AE + 'macron' => '635', # C+0xAF # U+0x00AF + 'degree' => '541', # C+0xB0 # U+0x00B0 + 'plusminus' => '818', # C+0xB1 # U+0x00B1 + 'twosuperior' => '541', # C+0xB2 # U+0x00B2 + 'threesuperior' => '541', # C+0xB3 # U+0x00B3 + 'acute' => '635', # C+0xB4 # U+0x00B4 + 'mu' => '639', # C+0xB5 # U+0x00B5 + 'paragraph' => '635', # C+0xB6 # U+0x00B6 + 'periodcentered' => '363', # C+0xB7 # U+0x00B7 + 'cedilla' => '635', # C+0xB8 # U+0x00B8 + 'onesuperior' => '541', # C+0xB9 # U+0x00B9 + 'ordmasculine' => '545', # C+0xBA # U+0x00BA + 'guillemotright' => '644', # C+0xBB # U+0x00BB + 'onequarter' => '1000', # C+0xBC # U+0x00BC + 'onehalf' => '1000', # C+0xBD # U+0x00BD + 'threequarters' => '1000', # C+0xBE # U+0x00BE + 'questiondown' => '545', # C+0xBF # U+0x00BF + 'Agrave' => '683', # C+0xC0 # U+0x00C0 + 'Aacute' => '683', # C+0xC1 # U+0x00C1 + 'Acircumflex' => '683', # C+0xC2 # U+0x00C2 + 'Atilde' => '683', # C+0xC3 # U+0x00C3 + 'Adieresis' => '683', # C+0xC4 # U+0x00C4 + 'Aring' => '683', # C+0xC5 # U+0x00C5 + 'AE' => '984', # C+0xC6 # U+0x00C6 + 'Ccedilla' => '698', # C+0xC7 # U+0x00C7 + 'Egrave' => '632', # C+0xC8 # U+0x00C8 + 'Eacute' => '632', # C+0xC9 # U+0x00C9 + 'Ecircumflex' => '632', # C+0xCA # U+0x00CA + 'Edieresis' => '632', # C+0xCB # U+0x00CB + 'Igrave' => '420', # C+0xCC # U+0x00CC + 'Iacute' => '420', # C+0xCD # U+0x00CD + 'Icircumflex' => '420', # C+0xCE # U+0x00CE + 'Idieresis' => '420', # C+0xCF # U+0x00CF + 'Eth' => '775', # C+0xD0 # U+0x00D0 + 'Ntilde' => '748', # C+0xD1 # U+0x00D1 + 'Ograve' => '787', # C+0xD2 # U+0x00D2 + 'Oacute' => '787', # C+0xD3 # U+0x00D3 + 'Ocircumflex' => '787', # C+0xD4 # U+0x00D4 + 'Otilde' => '787', # C+0xD5 # U+0x00D5 + 'Odieresis' => '787', # C+0xD6 # U+0x00D6 + 'multiply' => '818', # C+0xD7 # U+0x00D7 + 'Oslash' => '787', # C+0xD8 # U+0x00D8 + 'Ugrave' => '731', # C+0xD9 # U+0x00D9 + 'Uacute' => '731', # C+0xDA # U+0x00DA + 'Ucircumflex' => '731', # C+0xDB # U+0x00DB + 'Udieresis' => '731', # C+0xDC # U+0x00DC + 'Yacute' => '615', # C+0xDD # U+0x00DD + 'Thorn' => '605', # C+0xDE # U+0x00DE + 'germandbls' => '620', # C+0xDF # U+0x00DF + 'agrave' => '600', # C+0xE0 # U+0x00E0 + 'aacute' => '600', # C+0xE1 # U+0x00E1 + 'acircumflex' => '600', # C+0xE2 # U+0x00E2 + 'atilde' => '600', # C+0xE3 # U+0x00E3 + 'adieresis' => '600', # C+0xE4 # U+0x00E4 + 'aring' => '600', # C+0xE5 # U+0x00E5 + 'ae' => '955', # C+0xE6 # U+0x00E6 + 'ccedilla' => '520', # C+0xE7 # U+0x00E7 + 'egrave' => '595', # C+0xE8 # U+0x00E8 + 'eacute' => '595', # C+0xE9 # U+0x00E9 + 'ecircumflex' => '595', # C+0xEA # U+0x00EA + 'edieresis' => '595', # C+0xEB # U+0x00EB + 'igrave' => '274', # C+0xEC # U+0x00EC + 'iacute' => '274', # C+0xED # U+0x00ED + 'icircumflex' => '274', # C+0xEE # U+0x00EE + 'idieresis' => '274', # C+0xEF # U+0x00EF + 'eth' => '611', # C+0xF0 # U+0x00F0 + 'ntilde' => '632', # C+0xF1 # U+0x00F1 + 'ograve' => '606', # C+0xF2 # U+0x00F2 + 'oacute' => '606', # C+0xF3 # U+0x00F3 + 'ocircumflex' => '606', # C+0xF4 # U+0x00F4 + 'otilde' => '606', # C+0xF5 # U+0x00F5 + 'odieresis' => '606', # C+0xF6 # U+0x00F6 + 'divide' => '818', # C+0xF7 # U+0x00F7 + 'oslash' => '606', # C+0xF8 # U+0x00F8 + 'ugrave' => '632', # C+0xF9 # U+0x00F9 + 'uacute' => '632', # C+0xFA # U+0x00FA + 'ucircumflex' => '632', # C+0xFB # U+0x00FB + 'udieresis' => '632', # C+0xFC # U+0x00FC + 'yacute' => '591', # C+0xFD # U+0x00FD + 'thorn' => '623', # C+0xFE # U+0x00FE + 'ydieresis' => '591', # C+0xFF # U+0x00FF + 'middot' => '363', # U+0x00B7 + 'Amacron' => '683', # U+0x0100 + 'amacron' => '600', # U+0x0101 + 'Abreve' => '683', # U+0x0102 + 'abreve' => '600', # U+0x0103 + 'Aogonek' => '683', # U+0x0104 + 'aogonek' => '600', # U+0x0105 + 'Cacute' => '698', # U+0x0106 + 'cacute' => '520', # U+0x0107 + 'Ccircumflex' => '698', # U+0x0108 + 'ccircumflex' => '520', # U+0x0109 + 'Cdot' => '698', # U+0x010A + 'cdot' => '520', # U+0x010B + 'Ccaron' => '698', # U+0x010C + 'ccaron' => '520', # U+0x010D + 'Dcaron' => '770', # U+0x010E + 'dcaron' => '647', # U+0x010F + 'Emacron' => '632', # U+0x0112 + 'emacron' => '595', # U+0x0113 + 'Ebreve' => '632', # U+0x0114 + 'ebreve' => '595', # U+0x0115 + 'Edot' => '632', # U+0x0116 + 'edot' => '595', # U+0x0117 + 'Eogonek' => '632', # U+0x0118 + 'eogonek' => '595', # U+0x0119 + 'Ecaron' => '632', # U+0x011A + 'ecaron' => '595', # U+0x011B + 'Gcircumflex' => '775', # U+0x011C + 'gcircumflex' => '623', # U+0x011D + 'Gbreve' => '775', # U+0x011E + 'gbreve' => '623', # U+0x011F + 'Gdot' => '775', # U+0x0120 + 'gdot' => '623', # U+0x0121 + 'Hcircumflex' => '751', # U+0x0124 + 'hcircumflex' => '632', # U+0x0125 + 'Hbar' => '751', # U+0x0126 + 'hbar' => '632', # U+0x0127 + 'Itilde' => '420', # U+0x0128 + 'itilde' => '274', # U+0x0129 + 'Imacron' => '420', # U+0x012A + 'imacron' => '274', # U+0x012B + 'Ibreve' => '420', # U+0x012C + 'ibreve' => '274', # U+0x012D + 'Iogonek' => '420', # U+0x012E + 'iogonek' => '274', # U+0x012F + 'Idot' => '420', # U+0x0130 + 'dotlessi' => '274', # U+0x0131 + 'IJ' => '870', # U+0x0132 + 'ij' => '613', # U+0x0133 + 'Jcircumflex' => '454', # U+0x0134 + 'jcircumflex' => '344', # U+0x0135 + 'kgreenlandic' => '591', # U+0x0138 + 'Lacute' => '556', # U+0x0139 + 'lacute' => '274', # U+0x013A + 'Lcaron' => '556', # U+0x013D + 'lcaron' => '295', # U+0x013E + 'Ldot' => '556', # U+0x013F + 'ldot' => '458', # U+0x0140 + 'Lslash' => '561', # U+0x0141 + 'lslash' => '284', # U+0x0142 + 'Nacute' => '748', # U+0x0143 + 'nacute' => '632', # U+0x0144 + 'Ncaron' => '748', # U+0x0147 + 'ncaron' => '632', # U+0x0148 + 'napostrophe' => '730', # U+0x0149 + 'Eng' => '748', # U+0x014A + 'eng' => '632', # U+0x014B + 'Omacron' => '787', # U+0x014C + 'omacron' => '606', # U+0x014D + 'Obreve' => '787', # U+0x014E + 'obreve' => '606', # U+0x014F + 'Racute' => '695', # U+0x0154 + 'racute' => '426', # U+0x0155 + 'Rcaron' => '695', # U+0x0158 + 'rcaron' => '426', # U+0x0159 + 'Sacute' => '683', # U+0x015A + 'sacute' => '520', # U+0x015B + 'Scircumflex' => '683', # U+0x015C + 'scircumflex' => '520', # U+0x015D + 'Scedilla' => '683', # U+0x015E + 'scedilla' => '520', # U+0x015F + 'Tcaron' => '616', # U+0x0164 + 'tcaron' => '394', # U+0x0165 + 'Tbar' => '616', # U+0x0166 + 'tbar' => '394', # U+0x0167 + 'Utilde' => '731', # U+0x0168 + 'utilde' => '632', # U+0x0169 + 'Umacron' => '731', # U+0x016A + 'umacron' => '632', # U+0x016B + 'Ubreve' => '731', # U+0x016C + 'ubreve' => '630', # U+0x016D + 'Uring' => '731', # U+0x016E + 'uring' => '632', # U+0x016F + 'Uogonek' => '731', # U+0x0172 + 'uogonek' => '630', # U+0x0173 + 'Wcircumflex' => '988', # U+0x0174 + 'wcircumflex' => '818', # U+0x0175 + 'Ycircumflex' => '615', # U+0x0176 + 'ycircumflex' => '591', # U+0x0177 + 'Zacute' => '685', # U+0x0179 + 'zacute' => '525', # U+0x017A + 'Zdot' => '685', # U+0x017B + 'zdot' => '525', # U+0x017C + 'longs' => '300', # U+0x017F + 'Ohorn' => '806', # U+0x01A0 + 'ohorn' => '606', # U+0x01A1 + 'Uhorn' => '756', # U+0x01AF + 'uhorn' => '659', # U+0x01B0 + 'Aringacute' => '683', # U+0x01FA + 'aringacute' => '600', # U+0x01FB + 'AEacute' => '984', # U+0x01FC + 'aeacute' => '955', # U+0x01FD + 'Oslashacute' => '787', # U+0x01FE + 'oslashacute' => '606', # U+0x01FF + 'caron' => '635', # U+0x02C7 + 'breve' => '635', # U+0x02D8 + 'dotaccent' => '635', # U+0x02D9 + 'ring' => '635', # U+0x02DA + 'ogonek' => '635', # U+0x02DB + 'hungarumlaut' => '635', # U+0x02DD + 'gravecomb' => '0', # U+0x0300 + 'acutecomb' => '0', # U+0x0301 + 'tildecomb' => '0', # U+0x0303 + 'hookabovecomb' => '0', # U+0x0309 + 'dotbelowcomb' => '0', # U+0x0323 + 'tonos' => '635', # U+0x0384 + 'dieresistonos' => '635', # U+0x0385 + 'Alphatonos' => '683', # U+0x0386 + 'anoteleia' => '454', # U+0x0387 + 'Epsilontonos' => '750', # U+0x0388 + 'Etatonos' => '870', # U+0x0389 + 'Iotatonos' => '539', # U+0x038A + 'Omicrontonos' => '880', # U+0x038C + 'Upsilontonos' => '753', # U+0x038E + 'Omegatonos' => '907', # U+0x038F + 'iotadieresistonos' => '274', # U+0x0390 + 'Alpha' => '683', # U+0x0391 + 'Beta' => '685', # U+0x0392 + 'Gamma' => '566', # U+0x0393 + 'Delta' => '703', # U+0x0394 + 'Epsilon' => '632', # U+0x0395 + 'Zeta' => '685', # U+0x0396 + 'Eta' => '751', # U+0x0397 + 'Theta' => '787', # U+0x0398 + 'Iota' => '420', # U+0x0399 + 'Kappa' => '692', # U+0x039A + 'Lambda' => '685', # U+0x039B + 'Mu' => '842', # U+0x039C + 'Nu' => '748', # U+0x039D + 'Xi' => '648', # U+0x039E + 'Omicron' => '787', # U+0x039F + 'Pi' => '751', # U+0x03A0 + 'Rho' => '603', # U+0x03A1 + 'Sigma' => '672', # U+0x03A3 + 'Tau' => '616', # U+0x03A4 + 'Upsilon' => '615', # U+0x03A5 + 'Phi' => '818', # U+0x03A6 + 'Chi' => '685', # U+0x03A7 + 'Psi' => '870', # U+0x03A8 + 'Omega' => '818', # U+0x03A9 + 'Iotadieresis' => '420', # U+0x03AA + 'Upsilondieresis' => '615', # U+0x03AB + 'alphatonos' => '623', # U+0x03AC + 'epsilontonos' => '512', # U+0x03AD + 'etatonos' => '632', # U+0x03AE + 'iotatonos' => '274', # U+0x03AF + 'upsilondieresistonos' => '631', # U+0x03B0 + 'alpha' => '623', # U+0x03B1 + 'beta' => '620', # U+0x03B2 + 'gamma' => '591', # U+0x03B3 + 'delta' => '607', # U+0x03B4 + 'epsilon' => '512', # U+0x03B5 + 'zeta' => '457', # U+0x03B6 + 'eta' => '632', # U+0x03B7 + 'theta' => '624', # U+0x03B8 + 'iota' => '274', # U+0x03B9 + 'kappa' => '591', # U+0x03BA + 'lambda' => '591', # U+0x03BB + 'nu' => '591', # U+0x03BD + 'xi' => '502', # U+0x03BE + 'omicron' => '606', # U+0x03BF + 'pi' => '637', # U+0x03C0 + 'rho' => '625', # U+0x03C1 + 'sigma1' => '507', # U+0x03C2 + 'sigma' => '630', # U+0x03C3 + 'tau' => '496', # U+0x03C4 + 'upsilon' => '631', # U+0x03C5 + 'phi' => '790', # U+0x03C6 + 'chi' => '589', # U+0x03C7 + 'psi' => '821', # U+0x03C8 + 'omega' => '813', # U+0x03C9 + 'iotadieresis' => '274', # U+0x03CA + 'upsilondieresis' => '631', # U+0x03CB + 'omicrontonos' => '606', # U+0x03CC + 'upsilontonos' => '631', # U+0x03CD + 'omegatonos' => '813', # U+0x03CE + 'afii10023' => '632', # U+0x0401 + 'afii10051' => '792', # U+0x0402 + 'afii10052' => '566', # U+0x0403 + 'afii10053' => '700', # U+0x0404 + 'afii10054' => '683', # U+0x0405 + 'afii10055' => '420', # U+0x0406 + 'afii10056' => '420', # U+0x0407 + 'afii10057' => '454', # U+0x0408 + 'afii10058' => '1118', # U+0x0409 + 'afii10059' => '1103', # U+0x040A + 'afii10060' => '817', # U+0x040B + 'afii10061' => '692', # U+0x040C + 'afii10062' => '615', # U+0x040E + 'afii10145' => '751', # U+0x040F + 'afii10017' => '683', # U+0x0410 + 'afii10018' => '685', # U+0x0411 + 'afii10019' => '685', # U+0x0412 + 'afii10020' => '566', # U+0x0413 + 'afii10021' => '745', # U+0x0414 + 'afii10022' => '632', # U+0x0415 + 'afii10024' => '973', # U+0x0416 + 'afii10025' => '615', # U+0x0417 + 'afii10026' => '750', # U+0x0418 + 'afii10027' => '750', # U+0x0419 + 'afii10028' => '692', # U+0x041A + 'afii10029' => '734', # U+0x041B + 'afii10030' => '842', # U+0x041C + 'afii10031' => '751', # U+0x041D + 'afii10032' => '787', # U+0x041E + 'afii10033' => '751', # U+0x041F + 'afii10034' => '603', # U+0x0420 + 'afii10035' => '698', # U+0x0421 + 'afii10036' => '616', # U+0x0422 + 'afii10037' => '615', # U+0x0423 + 'afii10038' => '818', # U+0x0424 + 'afii10039' => '685', # U+0x0425 + 'afii10040' => '761', # U+0x0426 + 'afii10041' => '711', # U+0x0427 + 'afii10042' => '1030', # U+0x0428 + 'afii10043' => '1044', # U+0x0429 + 'afii10044' => '783', # U+0x042A + 'afii10045' => '920', # U+0x042B + 'afii10046' => '680', # U+0x042C + 'afii10047' => '701', # U+0x042D + 'afii10048' => '1034', # U+0x042E + 'afii10049' => '706', # U+0x042F + 'afii10065' => '600', # U+0x0430 + 'afii10066' => '614', # U+0x0431 + 'afii10067' => '594', # U+0x0432 + 'afii10068' => '471', # U+0x0433 + 'afii10069' => '621', # U+0x0434 + 'afii10070' => '595', # U+0x0435 + 'afii10072' => '797', # U+0x0436 + 'afii10073' => '524', # U+0x0437 + 'afii10074' => '640', # U+0x0438 + 'afii10075' => '640', # U+0x0439 + 'afii10076' => '591', # U+0x043A + 'afii10077' => '620', # U+0x043B + 'afii10078' => '696', # U+0x043C + 'afii10079' => '637', # U+0x043D + 'afii10080' => '606', # U+0x043E + 'afii10081' => '637', # U+0x043F + 'afii10082' => '623', # U+0x0440 + 'afii10083' => '534', # U+0x0441 + 'afii10084' => '496', # U+0x0442 + 'afii10085' => '591', # U+0x0443 + 'afii10086' => '840', # U+0x0444 + 'afii10087' => '591', # U+0x0445 + 'afii10088' => '644', # U+0x0446 + 'afii10089' => '605', # U+0x0447 + 'afii10090' => '875', # U+0x0448 + 'afii10091' => '887', # U+0x0449 + 'afii10092' => '640', # U+0x044A + 'afii10093' => '794', # U+0x044B + 'afii10094' => '570', # U+0x044C + 'afii10095' => '546', # U+0x044D + 'afii10096' => '838', # U+0x044E + 'afii10097' => '599', # U+0x044F + 'afii10071' => '595', # U+0x0451 + 'afii10099' => '632', # U+0x0452 + 'afii10100' => '471', # U+0x0453 + 'afii10101' => '546', # U+0x0454 + 'afii10102' => '520', # U+0x0455 + 'afii10103' => '274', # U+0x0456 + 'afii10104' => '274', # U+0x0457 + 'afii10105' => '344', # U+0x0458 + 'afii10106' => '914', # U+0x0459 + 'afii10107' => '914', # U+0x045A + 'afii10108' => '632', # U+0x045B + 'afii10109' => '591', # U+0x045C + 'afii10110' => '591', # U+0x045E + 'afii10193' => '637', # U+0x045F + 'afii10050' => '566', # U+0x0490 + 'afii10098' => '471', # U+0x0491 + 'Wgrave' => '988', # U+0x1E80 + 'wgrave' => '818', # U+0x1E81 + 'Wacute' => '988', # U+0x1E82 + 'wacute' => '818', # U+0x1E83 + 'Wdieresis' => '988', # U+0x1E84 + 'wdieresis' => '818', # U+0x1E85 + 'Ygrave' => '615', # U+0x1EF2 + 'ygrave' => '591', # U+0x1EF3 + 'afii00208' => '1000', # U+0x2015 + 'underscoredbl' => '635', # U+0x2017 + 'quotereversed' => '268', # U+0x201B + 'minute' => '361', # U+0x2032 + 'second' => '557', # U+0x2033 + 'exclamdbl' => '624', # U+0x203C + 'fraction' => '361', # U+0x2044 + 'nsuperior' => '545', # U+0x207F + 'franc' => '635', # U+0x20A3 + 'peseta' => '1163', # U+0x20A7 + 'dong' => '623', # U+0x20AB + 'afii61248' => '1076', # U+0x2105 + 'afii61289' => '323', # U+0x2113 + 'afii61352' => '1171', # U+0x2116 + 'estimated' => '717', # U+0x212E + 'gimel' => '0', # U+0x2137 + 'oneeighth' => '1000', # U+0x215B + 'threeeighths' => '1000', # U+0x215C + 'fiveeighths' => '1000', # U+0x215D + 'seveneighths' => '1000', # U+0x215E + 'partialdiff' => '635', # U+0x2202 + 'product' => '818', # U+0x220F + 'summation' => '727', # U+0x2211 + 'minus' => '818', # U+0x2212 + 'radical' => '818', # U+0x221A + 'infinity' => '1000', # U+0x221E + 'integral' => '635', # U+0x222B + 'approxequal' => '818', # U+0x2248 + 'notequal' => '818', # U+0x2260 + 'lessequal' => '818', # U+0x2264 + 'greaterequal' => '818', # U+0x2265 + 'H22073' => '604', # U+0x25A1 + 'H18543' => '354', # U+0x25AA + 'H18551' => '354', # U+0x25AB + 'lozenge' => '818', # U+0x25CA + 'H18533' => '604', # U+0x25CF + 'openbullet' => '354', # U+0x25E6 + 'commaaccent' => '210', # U+0xF6C3 + 'radicalex' => '635', # U+0xF8E5 + 'fi' => '625', # U+0xFB01 + 'fl' => '625', # U+0xFB02 + }, # HORIZ. WIDTH TABLE +} }; + +1; diff --git a/lib/PDF/API2/Resource/Font/CoreFont/verdanabold.pm b/lib/PDF/API2/Resource/Font/CoreFont/verdanabold.pm new file mode 100644 index 0000000..54a8ebc --- /dev/null +++ b/lib/PDF/API2/Resource/Font/CoreFont/verdanabold.pm @@ -0,0 +1,848 @@ +#line 1 "PDF/API2/Resource/Font/CoreFont/verdanabold.pm" +#line 1 "PDF/API2/Resource/Font/CoreFont/verdanabold.pm" +package PDF::API2::Resource::Font::CoreFont::verdanabold; + +use strict; +use warnings; + +our $VERSION = '2.033'; # VERSION + +sub data { return { + 'fontname' => 'Verdana,Bold', + 'type' => 'TrueType', + 'apiname' => 'VeBo', + 'ascender' => '1005', + 'capheight' => '727', + 'descender' => '-209', + 'isfixedpitch' => '0', + 'issymbol' => '0', + 'italicangle' => '0', + 'underlineposition' => '-139', + 'underlinethickness' => '211', + 'xheight' => '548', + 'firstchar' => '32', + 'lastchar' => '255', + 'flags' => '262176', + 'char' => [ # DEF. ENCODING GLYPH TABLE + '.notdef', # C+0x00 # U+0x0000 + '.notdef', # C+0x01 # U+0x0000 + '.notdef', # C+0x02 # U+0x0000 + '.notdef', # C+0x03 # U+0x0000 + '.notdef', # C+0x04 # U+0x0000 + '.notdef', # C+0x05 # U+0x0000 + '.notdef', # C+0x06 # U+0x0000 + '.notdef', # C+0x07 # U+0x0000 + '.notdef', # C+0x08 # U+0x0000 + '.notdef', # C+0x09 # U+0x0000 + '.notdef', # C+0x0A # U+0x0000 + '.notdef', # C+0x0B # U+0x0000 + '.notdef', # C+0x0C # U+0x0000 + '.notdef', # C+0x0D # U+0x0000 + '.notdef', # C+0x0E # U+0x0000 + '.notdef', # C+0x0F # U+0x0000 + '.notdef', # C+0x10 # U+0x0000 + '.notdef', # C+0x11 # U+0x0000 + '.notdef', # C+0x12 # U+0x0000 + '.notdef', # C+0x13 # U+0x0000 + '.notdef', # C+0x14 # U+0x0000 + '.notdef', # C+0x15 # U+0x0000 + '.notdef', # C+0x16 # U+0x0000 + '.notdef', # C+0x17 # U+0x0000 + '.notdef', # C+0x18 # U+0x0000 + '.notdef', # C+0x19 # U+0x0000 + '.notdef', # C+0x1A # U+0x0000 + '.notdef', # C+0x1B # U+0x0000 + '.notdef', # C+0x1C # U+0x0000 + '.notdef', # C+0x1D # U+0x0000 + '.notdef', # C+0x1E # U+0x0000 + '.notdef', # C+0x1F # U+0x0000 + 'space', # C+0x20 # U+0x0020 + 'exclam', # C+0x21 # U+0x0021 + 'quotedbl', # C+0x22 # U+0x0022 + 'numbersign', # C+0x23 # U+0x0023 + 'dollar', # C+0x24 # U+0x0024 + 'percent', # C+0x25 # U+0x0025 + 'ampersand', # C+0x26 # U+0x0026 + 'quotesingle', # C+0x27 # U+0x0027 + 'parenleft', # C+0x28 # U+0x0028 + 'parenright', # C+0x29 # U+0x0029 + 'asterisk', # C+0x2A # U+0x002A + 'plus', # C+0x2B # U+0x002B + 'comma', # C+0x2C # U+0x002C + 'hyphen', # C+0x2D # U+0x002D + 'period', # C+0x2E # U+0x002E + 'slash', # C+0x2F # U+0x002F + 'zero', # C+0x30 # U+0x0030 + 'one', # C+0x31 # U+0x0031 + 'two', # C+0x32 # U+0x0032 + 'three', # C+0x33 # U+0x0033 + 'four', # C+0x34 # U+0x0034 + 'five', # C+0x35 # U+0x0035 + 'six', # C+0x36 # U+0x0036 + 'seven', # C+0x37 # U+0x0037 + 'eight', # C+0x38 # U+0x0038 + 'nine', # C+0x39 # U+0x0039 + 'colon', # C+0x3A # U+0x003A + 'semicolon', # C+0x3B # U+0x003B + 'less', # C+0x3C # U+0x003C + 'equal', # C+0x3D # U+0x003D + 'greater', # C+0x3E # U+0x003E + 'question', # C+0x3F # U+0x003F + 'at', # C+0x40 # U+0x0040 + 'A', # C+0x41 # U+0x0041 + 'B', # C+0x42 # U+0x0042 + 'C', # C+0x43 # U+0x0043 + 'D', # C+0x44 # U+0x0044 + 'E', # C+0x45 # U+0x0045 + 'F', # C+0x46 # U+0x0046 + 'G', # C+0x47 # U+0x0047 + 'H', # C+0x48 # U+0x0048 + 'I', # C+0x49 # U+0x0049 + 'J', # C+0x4A # U+0x004A + 'K', # C+0x4B # U+0x004B + 'L', # C+0x4C # U+0x004C + 'M', # C+0x4D # U+0x004D + 'N', # C+0x4E # U+0x004E + 'O', # C+0x4F # U+0x004F + 'P', # C+0x50 # U+0x0050 + 'Q', # C+0x51 # U+0x0051 + 'R', # C+0x52 # U+0x0052 + 'S', # C+0x53 # U+0x0053 + 'T', # C+0x54 # U+0x0054 + 'U', # C+0x55 # U+0x0055 + 'V', # C+0x56 # U+0x0056 + 'W', # C+0x57 # U+0x0057 + 'X', # C+0x58 # U+0x0058 + 'Y', # C+0x59 # U+0x0059 + 'Z', # C+0x5A # U+0x005A + 'bracketleft', # C+0x5B # U+0x005B + 'backslash', # C+0x5C # U+0x005C + 'bracketright', # C+0x5D # U+0x005D + 'asciicircum', # C+0x5E # U+0x005E + 'underscore', # C+0x5F # U+0x005F + 'grave', # C+0x60 # U+0x0060 + 'a', # C+0x61 # U+0x0061 + 'b', # C+0x62 # U+0x0062 + 'c', # C+0x63 # U+0x0063 + 'd', # C+0x64 # U+0x0064 + 'e', # C+0x65 # U+0x0065 + 'f', # C+0x66 # U+0x0066 + 'g', # C+0x67 # U+0x0067 + 'h', # C+0x68 # U+0x0068 + 'i', # C+0x69 # U+0x0069 + 'j', # C+0x6A # U+0x006A + 'k', # C+0x6B # U+0x006B + 'l', # C+0x6C # U+0x006C + 'm', # C+0x6D # U+0x006D + 'n', # C+0x6E # U+0x006E + 'o', # C+0x6F # U+0x006F + 'p', # C+0x70 # U+0x0070 + 'q', # C+0x71 # U+0x0071 + 'r', # C+0x72 # U+0x0072 + 's', # C+0x73 # U+0x0073 + 't', # C+0x74 # U+0x0074 + 'u', # C+0x75 # U+0x0075 + 'v', # C+0x76 # U+0x0076 + 'w', # C+0x77 # U+0x0077 + 'x', # C+0x78 # U+0x0078 + 'y', # C+0x79 # U+0x0079 + 'z', # C+0x7A # U+0x007A + 'braceleft', # C+0x7B # U+0x007B + 'bar', # C+0x7C # U+0x007C + 'braceright', # C+0x7D # U+0x007D + 'asciitilde', # C+0x7E # U+0x007E + 'bullet', # C+0x7F # U+0x2022 + 'Euro', # C+0x80 # U+0x20AC + 'bullet', # C+0x81 # U+0x2022 + 'quotesinglbase', # C+0x82 # U+0x201A + 'florin', # C+0x83 # U+0x0192 + 'quotedblbase', # C+0x84 # U+0x201E + 'ellipsis', # C+0x85 # U+0x2026 + 'dagger', # C+0x86 # U+0x2020 + 'daggerdbl', # C+0x87 # U+0x2021 + 'circumflex', # C+0x88 # U+0x02C6 + 'perthousand', # C+0x89 # U+0x2030 + 'Scaron', # C+0x8A # U+0x0160 + 'guilsinglleft', # C+0x8B # U+0x2039 + 'OE', # C+0x8C # U+0x0152 + 'bullet', # C+0x8D # U+0x2022 + 'Zcaron', # C+0x8E # U+0x017D + 'bullet', # C+0x8F # U+0x2022 + 'bullet', # C+0x90 # U+0x2022 + 'quoteleft', # C+0x91 # U+0x2018 + 'quoteright', # C+0x92 # U+0x2019 + 'quotedblleft', # C+0x93 # U+0x201C + 'quotedblright', # C+0x94 # U+0x201D + 'bullet', # C+0x95 # U+0x2022 + 'endash', # C+0x96 # U+0x2013 + 'emdash', # C+0x97 # U+0x2014 + 'tilde', # C+0x98 # U+0x02DC + 'trademark', # C+0x99 # U+0x2122 + 'scaron', # C+0x9A # U+0x0161 + 'guilsinglright', # C+0x9B # U+0x203A + 'oe', # C+0x9C # U+0x0153 + 'bullet', # C+0x9D # U+0x2022 + 'zcaron', # C+0x9E # U+0x017E + 'Ydieresis', # C+0x9F # U+0x0178 + 'space', # C+0xA0 # U+0x0020 + 'exclamdown', # C+0xA1 # U+0x00A1 + 'cent', # C+0xA2 # U+0x00A2 + 'sterling', # C+0xA3 # U+0x00A3 + 'currency', # C+0xA4 # U+0x00A4 + 'yen', # C+0xA5 # U+0x00A5 + 'brokenbar', # C+0xA6 # U+0x00A6 + 'section', # C+0xA7 # U+0x00A7 + 'dieresis', # C+0xA8 # U+0x00A8 + 'copyright', # C+0xA9 # U+0x00A9 + 'ordfeminine', # C+0xAA # U+0x00AA + 'guillemotleft', # C+0xAB # U+0x00AB + 'logicalnot', # C+0xAC # U+0x00AC + 'hyphen', # C+0xAD # U+0x002D + 'registered', # C+0xAE # U+0x00AE + 'macron', # C+0xAF # U+0x00AF + 'degree', # C+0xB0 # U+0x00B0 + 'plusminus', # C+0xB1 # U+0x00B1 + 'twosuperior', # C+0xB2 # U+0x00B2 + 'threesuperior', # C+0xB3 # U+0x00B3 + 'acute', # C+0xB4 # U+0x00B4 + 'mu', # C+0xB5 # U+0x00B5 + 'paragraph', # C+0xB6 # U+0x00B6 + 'periodcentered', # C+0xB7 # U+0x00B7 + 'cedilla', # C+0xB8 # U+0x00B8 + 'onesuperior', # C+0xB9 # U+0x00B9 + 'ordmasculine', # C+0xBA # U+0x00BA + 'guillemotright', # C+0xBB # U+0x00BB + 'onequarter', # C+0xBC # U+0x00BC + 'onehalf', # C+0xBD # U+0x00BD + 'threequarters', # C+0xBE # U+0x00BE + 'questiondown', # C+0xBF # U+0x00BF + 'Agrave', # C+0xC0 # U+0x00C0 + 'Aacute', # C+0xC1 # U+0x00C1 + 'Acircumflex', # C+0xC2 # U+0x00C2 + 'Atilde', # C+0xC3 # U+0x00C3 + 'Adieresis', # C+0xC4 # U+0x00C4 + 'Aring', # C+0xC5 # U+0x00C5 + 'AE', # C+0xC6 # U+0x00C6 + 'Ccedilla', # C+0xC7 # U+0x00C7 + 'Egrave', # C+0xC8 # U+0x00C8 + 'Eacute', # C+0xC9 # U+0x00C9 + 'Ecircumflex', # C+0xCA # U+0x00CA + 'Edieresis', # C+0xCB # U+0x00CB + 'Igrave', # C+0xCC # U+0x00CC + 'Iacute', # C+0xCD # U+0x00CD + 'Icircumflex', # C+0xCE # U+0x00CE + 'Idieresis', # C+0xCF # U+0x00CF + 'Eth', # C+0xD0 # U+0x00D0 + 'Ntilde', # C+0xD1 # U+0x00D1 + 'Ograve', # C+0xD2 # U+0x00D2 + 'Oacute', # C+0xD3 # U+0x00D3 + 'Ocircumflex', # C+0xD4 # U+0x00D4 + 'Otilde', # C+0xD5 # U+0x00D5 + 'Odieresis', # C+0xD6 # U+0x00D6 + 'multiply', # C+0xD7 # U+0x00D7 + 'Oslash', # C+0xD8 # U+0x00D8 + 'Ugrave', # C+0xD9 # U+0x00D9 + 'Uacute', # C+0xDA # U+0x00DA + 'Ucircumflex', # C+0xDB # U+0x00DB + 'Udieresis', # C+0xDC # U+0x00DC + 'Yacute', # C+0xDD # U+0x00DD + 'Thorn', # C+0xDE # U+0x00DE + 'germandbls', # C+0xDF # U+0x00DF + 'agrave', # C+0xE0 # U+0x00E0 + 'aacute', # C+0xE1 # U+0x00E1 + 'acircumflex', # C+0xE2 # U+0x00E2 + 'atilde', # C+0xE3 # U+0x00E3 + 'adieresis', # C+0xE4 # U+0x00E4 + 'aring', # C+0xE5 # U+0x00E5 + 'ae', # C+0xE6 # U+0x00E6 + 'ccedilla', # C+0xE7 # U+0x00E7 + 'egrave', # C+0xE8 # U+0x00E8 + 'eacute', # C+0xE9 # U+0x00E9 + 'ecircumflex', # C+0xEA # U+0x00EA + 'edieresis', # C+0xEB # U+0x00EB + 'igrave', # C+0xEC # U+0x00EC + 'iacute', # C+0xED # U+0x00ED + 'icircumflex', # C+0xEE # U+0x00EE + 'idieresis', # C+0xEF # U+0x00EF + 'eth', # C+0xF0 # U+0x00F0 + 'ntilde', # C+0xF1 # U+0x00F1 + 'ograve', # C+0xF2 # U+0x00F2 + 'oacute', # C+0xF3 # U+0x00F3 + 'ocircumflex', # C+0xF4 # U+0x00F4 + 'otilde', # C+0xF5 # U+0x00F5 + 'odieresis', # C+0xF6 # U+0x00F6 + 'divide', # C+0xF7 # U+0x00F7 + 'oslash', # C+0xF8 # U+0x00F8 + 'ugrave', # C+0xF9 # U+0x00F9 + 'uacute', # C+0xFA # U+0x00FA + 'ucircumflex', # C+0xFB # U+0x00FB + 'udieresis', # C+0xFC # U+0x00FC + 'yacute', # C+0xFD # U+0x00FD + 'thorn', # C+0xFE # U+0x00FE + 'ydieresis', # C+0xFF # U+0x00FF + ], # DEF. ENCODING GLYPH TABLE + 'fontbbox' => [ -73, -207, 1707, 1000 ], + 'wx' => { # HORIZ. WIDTH TABLE + 'space' => '341', # C+0x20 # U+0x0020 + 'exclam' => '402', # C+0x21 # U+0x0021 + 'quotedbl' => '587', # C+0x22 # U+0x0022 + 'numbersign' => '867', # C+0x23 # U+0x0023 + 'dollar' => '710', # C+0x24 # U+0x0024 + 'percent' => '1271', # C+0x25 # U+0x0025 + 'ampersand' => '862', # C+0x26 # U+0x0026 + 'quotesingle' => '332', # C+0x27 # U+0x0027 + 'parenleft' => '543', # C+0x28 # U+0x0028 + 'parenright' => '543', # C+0x29 # U+0x0029 + 'asterisk' => '710', # C+0x2A # U+0x002A + 'plus' => '867', # C+0x2B # U+0x002B + 'comma' => '361', # C+0x2C # U+0x002C + 'hyphen' => '479', # C+0x2D # U+0x002D + 'period' => '361', # C+0x2E # U+0x002E + 'slash' => '689', # C+0x2F # U+0x002F + 'zero' => '710', # C+0x30 # U+0x0030 + 'one' => '710', # C+0x31 # U+0x0031 + 'two' => '710', # C+0x32 # U+0x0032 + 'three' => '710', # C+0x33 # U+0x0033 + 'four' => '710', # C+0x34 # U+0x0034 + 'five' => '710', # C+0x35 # U+0x0035 + 'six' => '710', # C+0x36 # U+0x0036 + 'seven' => '710', # C+0x37 # U+0x0037 + 'eight' => '710', # C+0x38 # U+0x0038 + 'nine' => '710', # C+0x39 # U+0x0039 + 'colon' => '402', # C+0x3A # U+0x003A + 'semicolon' => '402', # C+0x3B # U+0x003B + 'less' => '867', # C+0x3C # U+0x003C + 'equal' => '867', # C+0x3D # U+0x003D + 'greater' => '867', # C+0x3E # U+0x003E + 'question' => '616', # C+0x3F # U+0x003F + 'at' => '963', # C+0x40 # U+0x0040 + 'A' => '776', # C+0x41 # U+0x0041 + 'B' => '761', # C+0x42 # U+0x0042 + 'C' => '723', # C+0x43 # U+0x0043 + 'D' => '830', # C+0x44 # U+0x0044 + 'E' => '683', # C+0x45 # U+0x0045 + 'F' => '650', # C+0x46 # U+0x0046 + 'G' => '811', # C+0x47 # U+0x0047 + 'H' => '837', # C+0x48 # U+0x0048 + 'I' => '545', # C+0x49 # U+0x0049 + 'J' => '555', # C+0x4A # U+0x004A + 'K' => '770', # C+0x4B # U+0x004B + 'L' => '637', # C+0x4C # U+0x004C + 'M' => '947', # C+0x4D # U+0x004D + 'N' => '846', # C+0x4E # U+0x004E + 'O' => '850', # C+0x4F # U+0x004F + 'P' => '732', # C+0x50 # U+0x0050 + 'Q' => '850', # C+0x51 # U+0x0051 + 'R' => '782', # C+0x52 # U+0x0052 + 'S' => '710', # C+0x53 # U+0x0053 + 'T' => '681', # C+0x54 # U+0x0054 + 'U' => '812', # C+0x55 # U+0x0055 + 'V' => '763', # C+0x56 # U+0x0056 + 'W' => '1128', # C+0x57 # U+0x0057 + 'X' => '763', # C+0x58 # U+0x0058 + 'Y' => '736', # C+0x59 # U+0x0059 + 'Z' => '691', # C+0x5A # U+0x005A + 'bracketleft' => '543', # C+0x5B # U+0x005B + 'backslash' => '689', # C+0x5C # U+0x005C + 'bracketright' => '543', # C+0x5D # U+0x005D + 'asciicircum' => '867', # C+0x5E # U+0x005E + 'underscore' => '710', # C+0x5F # U+0x005F + 'grave' => '710', # C+0x60 # U+0x0060 + 'a' => '667', # C+0x61 # U+0x0061 + 'b' => '699', # C+0x62 # U+0x0062 + 'c' => '588', # C+0x63 # U+0x0063 + 'd' => '699', # C+0x64 # U+0x0064 + 'e' => '664', # C+0x65 # U+0x0065 + 'f' => '422', # C+0x66 # U+0x0066 + 'g' => '699', # C+0x67 # U+0x0067 + 'h' => '712', # C+0x68 # U+0x0068 + 'i' => '341', # C+0x69 # U+0x0069 + 'j' => '402', # C+0x6A # U+0x006A + 'k' => '670', # C+0x6B # U+0x006B + 'l' => '341', # C+0x6C # U+0x006C + 'm' => '1058', # C+0x6D # U+0x006D + 'n' => '712', # C+0x6E # U+0x006E + 'o' => '686', # C+0x6F # U+0x006F + 'p' => '699', # C+0x70 # U+0x0070 + 'q' => '699', # C+0x71 # U+0x0071 + 'r' => '497', # C+0x72 # U+0x0072 + 's' => '593', # C+0x73 # U+0x0073 + 't' => '455', # C+0x74 # U+0x0074 + 'u' => '712', # C+0x75 # U+0x0075 + 'v' => '649', # C+0x76 # U+0x0076 + 'w' => '979', # C+0x77 # U+0x0077 + 'x' => '668', # C+0x78 # U+0x0078 + 'y' => '650', # C+0x79 # U+0x0079 + 'z' => '596', # C+0x7A # U+0x007A + 'braceleft' => '710', # C+0x7B # U+0x007B + 'bar' => '543', # C+0x7C # U+0x007C + 'braceright' => '710', # C+0x7D # U+0x007D + 'asciitilde' => '867', # C+0x7E # U+0x007E + 'bullet' => '710', # C+0x7F # U+0x2022 + 'Euro' => '710', # C+0x80 # U+0x20AC + 'quotesinglbase' => '332', # C+0x82 # U+0x201A + 'florin' => '710', # C+0x83 # U+0x0192 + 'quotedblbase' => '587', # C+0x84 # U+0x201E + 'ellipsis' => '1048', # C+0x85 # U+0x2026 + 'dagger' => '710', # C+0x86 # U+0x2020 + 'daggerdbl' => '710', # C+0x87 # U+0x2021 + 'circumflex' => '710', # C+0x88 # U+0x02C6 + 'perthousand' => '1777', # C+0x89 # U+0x2030 + 'Scaron' => '710', # C+0x8A # U+0x0160 + 'guilsinglleft' => '543', # C+0x8B # U+0x2039 + 'OE' => '1135', # C+0x8C # U+0x0152 + 'Zcaron' => '691', # C+0x8E # U+0x017D + 'quoteleft' => '332', # C+0x91 # U+0x2018 + 'quoteright' => '332', # C+0x92 # U+0x2019 + 'quotedblleft' => '587', # C+0x93 # U+0x201C + 'quotedblright' => '587', # C+0x94 # U+0x201D + 'endash' => '710', # C+0x96 # U+0x2013 + 'emdash' => '1000', # C+0x97 # U+0x2014 + 'tilde' => '710', # C+0x98 # U+0x02DC + 'trademark' => '963', # C+0x99 # U+0x2122 + 'scaron' => '593', # C+0x9A # U+0x0161 + 'guilsinglright' => '543', # C+0x9B # U+0x203A + 'oe' => '1067', # C+0x9C # U+0x0153 + 'zcaron' => '596', # C+0x9E # U+0x017E + 'Ydieresis' => '736', # C+0x9F # U+0x0178 + 'exclamdown' => '402', # C+0xA1 # U+0x00A1 + 'cent' => '710', # C+0xA2 # U+0x00A2 + 'sterling' => '710', # C+0xA3 # U+0x00A3 + 'currency' => '710', # C+0xA4 # U+0x00A4 + 'yen' => '710', # C+0xA5 # U+0x00A5 + 'brokenbar' => '543', # C+0xA6 # U+0x00A6 + 'section' => '710', # C+0xA7 # U+0x00A7 + 'dieresis' => '710', # C+0xA8 # U+0x00A8 + 'copyright' => '963', # C+0xA9 # U+0x00A9 + 'ordfeminine' => '597', # C+0xAA # U+0x00AA + 'guillemotleft' => '849', # C+0xAB # U+0x00AB + 'logicalnot' => '867', # C+0xAC # U+0x00AC + 'registered' => '963', # C+0xAE # U+0x00AE + 'macron' => '710', # C+0xAF # U+0x00AF + 'degree' => '587', # C+0xB0 # U+0x00B0 + 'plusminus' => '867', # C+0xB1 # U+0x00B1 + 'twosuperior' => '597', # C+0xB2 # U+0x00B2 + 'threesuperior' => '597', # C+0xB3 # U+0x00B3 + 'acute' => '710', # C+0xB4 # U+0x00B4 + 'mu' => '721', # C+0xB5 # U+0x00B5 + 'paragraph' => '710', # C+0xB6 # U+0x00B6 + 'periodcentered' => '361', # C+0xB7 # U+0x00B7 + 'cedilla' => '710', # C+0xB8 # U+0x00B8 + 'onesuperior' => '597', # C+0xB9 # U+0x00B9 + 'ordmasculine' => '597', # C+0xBA # U+0x00BA + 'guillemotright' => '849', # C+0xBB # U+0x00BB + 'onequarter' => '1181', # C+0xBC # U+0x00BC + 'onehalf' => '1181', # C+0xBD # U+0x00BD + 'threequarters' => '1181', # C+0xBE # U+0x00BE + 'questiondown' => '616', # C+0xBF # U+0x00BF + 'Agrave' => '776', # C+0xC0 # U+0x00C0 + 'Aacute' => '776', # C+0xC1 # U+0x00C1 + 'Acircumflex' => '776', # C+0xC2 # U+0x00C2 + 'Atilde' => '776', # C+0xC3 # U+0x00C3 + 'Adieresis' => '776', # C+0xC4 # U+0x00C4 + 'Aring' => '776', # C+0xC5 # U+0x00C5 + 'AE' => '1093', # C+0xC6 # U+0x00C6 + 'Ccedilla' => '723', # C+0xC7 # U+0x00C7 + 'Egrave' => '683', # C+0xC8 # U+0x00C8 + 'Eacute' => '683', # C+0xC9 # U+0x00C9 + 'Ecircumflex' => '683', # C+0xCA # U+0x00CA + 'Edieresis' => '683', # C+0xCB # U+0x00CB + 'Igrave' => '545', # C+0xCC # U+0x00CC + 'Iacute' => '545', # C+0xCD # U+0x00CD + 'Icircumflex' => '545', # C+0xCE # U+0x00CE + 'Idieresis' => '545', # C+0xCF # U+0x00CF + 'Eth' => '830', # C+0xD0 # U+0x00D0 + 'Ntilde' => '846', # C+0xD1 # U+0x00D1 + 'Ograve' => '850', # C+0xD2 # U+0x00D2 + 'Oacute' => '850', # C+0xD3 # U+0x00D3 + 'Ocircumflex' => '850', # C+0xD4 # U+0x00D4 + 'Otilde' => '850', # C+0xD5 # U+0x00D5 + 'Odieresis' => '850', # C+0xD6 # U+0x00D6 + 'multiply' => '867', # C+0xD7 # U+0x00D7 + 'Oslash' => '850', # C+0xD8 # U+0x00D8 + 'Ugrave' => '812', # C+0xD9 # U+0x00D9 + 'Uacute' => '812', # C+0xDA # U+0x00DA + 'Ucircumflex' => '812', # C+0xDB # U+0x00DB + 'Udieresis' => '812', # C+0xDC # U+0x00DC + 'Yacute' => '736', # C+0xDD # U+0x00DD + 'Thorn' => '734', # C+0xDE # U+0x00DE + 'germandbls' => '712', # C+0xDF # U+0x00DF + 'agrave' => '667', # C+0xE0 # U+0x00E0 + 'aacute' => '667', # C+0xE1 # U+0x00E1 + 'acircumflex' => '667', # C+0xE2 # U+0x00E2 + 'atilde' => '667', # C+0xE3 # U+0x00E3 + 'adieresis' => '667', # C+0xE4 # U+0x00E4 + 'aring' => '667', # C+0xE5 # U+0x00E5 + 'ae' => '1018', # C+0xE6 # U+0x00E6 + 'ccedilla' => '588', # C+0xE7 # U+0x00E7 + 'egrave' => '664', # C+0xE8 # U+0x00E8 + 'eacute' => '664', # C+0xE9 # U+0x00E9 + 'ecircumflex' => '664', # C+0xEA # U+0x00EA + 'edieresis' => '664', # C+0xEB # U+0x00EB + 'igrave' => '341', # C+0xEC # U+0x00EC + 'iacute' => '341', # C+0xED # U+0x00ED + 'icircumflex' => '341', # C+0xEE # U+0x00EE + 'idieresis' => '341', # C+0xEF # U+0x00EF + 'eth' => '679', # C+0xF0 # U+0x00F0 + 'ntilde' => '712', # C+0xF1 # U+0x00F1 + 'ograve' => '686', # C+0xF2 # U+0x00F2 + 'oacute' => '686', # C+0xF3 # U+0x00F3 + 'ocircumflex' => '686', # C+0xF4 # U+0x00F4 + 'otilde' => '686', # C+0xF5 # U+0x00F5 + 'odieresis' => '686', # C+0xF6 # U+0x00F6 + 'divide' => '867', # C+0xF7 # U+0x00F7 + 'oslash' => '686', # C+0xF8 # U+0x00F8 + 'ugrave' => '712', # C+0xF9 # U+0x00F9 + 'uacute' => '712', # C+0xFA # U+0x00FA + 'ucircumflex' => '712', # C+0xFB # U+0x00FB + 'udieresis' => '712', # C+0xFC # U+0x00FC + 'yacute' => '650', # C+0xFD # U+0x00FD + 'thorn' => '699', # C+0xFE # U+0x00FE + 'ydieresis' => '650', # C+0xFF # U+0x00FF + 'middot' => '361', # U+0x00B7 + 'Amacron' => '776', # U+0x0100 + 'amacron' => '667', # U+0x0101 + 'Abreve' => '776', # U+0x0102 + 'abreve' => '667', # U+0x0103 + 'Aogonek' => '776', # U+0x0104 + 'aogonek' => '667', # U+0x0105 + 'Cacute' => '723', # U+0x0106 + 'cacute' => '588', # U+0x0107 + 'Ccircumflex' => '723', # U+0x0108 + 'ccircumflex' => '588', # U+0x0109 + 'Cdot' => '723', # U+0x010A + 'cdot' => '588', # U+0x010B + 'Ccaron' => '723', # U+0x010C + 'ccaron' => '588', # U+0x010D + 'Dcaron' => '830', # U+0x010E + 'dcaron' => '879', # U+0x010F + 'Emacron' => '683', # U+0x0112 + 'emacron' => '664', # U+0x0113 + 'Ebreve' => '683', # U+0x0114 + 'ebreve' => '664', # U+0x0115 + 'Edot' => '683', # U+0x0116 + 'edot' => '664', # U+0x0117 + 'Eogonek' => '683', # U+0x0118 + 'eogonek' => '664', # U+0x0119 + 'Ecaron' => '683', # U+0x011A + 'ecaron' => '664', # U+0x011B + 'Gcircumflex' => '811', # U+0x011C + 'gcircumflex' => '699', # U+0x011D + 'Gbreve' => '811', # U+0x011E + 'gbreve' => '699', # U+0x011F + 'Gdot' => '811', # U+0x0120 + 'gdot' => '699', # U+0x0121 + 'Hcircumflex' => '837', # U+0x0124 + 'hcircumflex' => '712', # U+0x0125 + 'Hbar' => '837', # U+0x0126 + 'hbar' => '712', # U+0x0127 + 'Itilde' => '545', # U+0x0128 + 'itilde' => '341', # U+0x0129 + 'Imacron' => '545', # U+0x012A + 'imacron' => '341', # U+0x012B + 'Ibreve' => '545', # U+0x012C + 'ibreve' => '341', # U+0x012D + 'Iogonek' => '545', # U+0x012E + 'iogonek' => '341', # U+0x012F + 'Idot' => '545', # U+0x0130 + 'dotlessi' => '341', # U+0x0131 + 'IJ' => '1007', # U+0x0132 + 'ij' => '727', # U+0x0133 + 'Jcircumflex' => '555', # U+0x0134 + 'jcircumflex' => '402', # U+0x0135 + 'kgreenlandic' => '670', # U+0x0138 + 'Lacute' => '637', # U+0x0139 + 'lacute' => '341', # U+0x013A + 'Lcaron' => '637', # U+0x013D + 'lcaron' => '522', # U+0x013E + 'Ldot' => '637', # U+0x013F + 'ldot' => '556', # U+0x0140 + 'Lslash' => '642', # U+0x0141 + 'lslash' => '351', # U+0x0142 + 'Nacute' => '846', # U+0x0143 + 'nacute' => '712', # U+0x0144 + 'Ncaron' => '846', # U+0x0147 + 'ncaron' => '712', # U+0x0148 + 'napostrophe' => '825', # U+0x0149 + 'Eng' => '846', # U+0x014A + 'eng' => '712', # U+0x014B + 'Omacron' => '850', # U+0x014C + 'omacron' => '686', # U+0x014D + 'Obreve' => '850', # U+0x014E + 'obreve' => '686', # U+0x014F + 'Racute' => '782', # U+0x0154 + 'racute' => '497', # U+0x0155 + 'Rcaron' => '782', # U+0x0158 + 'rcaron' => '497', # U+0x0159 + 'Sacute' => '710', # U+0x015A + 'sacute' => '593', # U+0x015B + 'Scircumflex' => '710', # U+0x015C + 'scircumflex' => '593', # U+0x015D + 'Scedilla' => '710', # U+0x015E + 'scedilla' => '593', # U+0x015F + 'Tcaron' => '681', # U+0x0164 + 'tcaron' => '465', # U+0x0165 + 'Tbar' => '681', # U+0x0166 + 'tbar' => '455', # U+0x0167 + 'Utilde' => '812', # U+0x0168 + 'utilde' => '712', # U+0x0169 + 'Umacron' => '812', # U+0x016A + 'umacron' => '712', # U+0x016B + 'Ubreve' => '812', # U+0x016C + 'ubreve' => '712', # U+0x016D + 'Uring' => '812', # U+0x016E + 'uring' => '712', # U+0x016F + 'Uogonek' => '812', # U+0x0172 + 'uogonek' => '712', # U+0x0173 + 'Wcircumflex' => '1128', # U+0x0174 + 'wcircumflex' => '979', # U+0x0175 + 'Ycircumflex' => '736', # U+0x0176 + 'ycircumflex' => '650', # U+0x0177 + 'Zacute' => '691', # U+0x0179 + 'zacute' => '596', # U+0x017A + 'Zdot' => '691', # U+0x017B + 'zdot' => '596', # U+0x017C + 'longs' => '344', # U+0x017F + 'Ohorn' => '913', # U+0x01A0 + 'ohorn' => '686', # U+0x01A1 + 'Uhorn' => '846', # U+0x01AF + 'uhorn' => '741', # U+0x01B0 + 'Aringacute' => '776', # U+0x01FA + 'aringacute' => '667', # U+0x01FB + 'AEacute' => '1093', # U+0x01FC + 'aeacute' => '1018', # U+0x01FD + 'Oslashacute' => '850', # U+0x01FE + 'oslashacute' => '686', # U+0x01FF + 'caron' => '710', # U+0x02C7 + 'breve' => '710', # U+0x02D8 + 'dotaccent' => '710', # U+0x02D9 + 'ring' => '710', # U+0x02DA + 'ogonek' => '710', # U+0x02DB + 'hungarumlaut' => '710', # U+0x02DD + 'gravecomb' => '0', # U+0x0300 + 'acutecomb' => '0', # U+0x0301 + 'tildecomb' => '0', # U+0x0303 + 'hookabovecomb' => '0', # U+0x0309 + 'dotbelowcomb' => '0', # U+0x0323 + 'tonos' => '710', # U+0x0384 + 'dieresistonos' => '710', # U+0x0385 + 'Alphatonos' => '797', # U+0x0386 + 'anoteleia' => '402', # U+0x0387 + 'Epsilontonos' => '847', # U+0x0388 + 'Etatonos' => '1000', # U+0x0389 + 'Iotatonos' => '705', # U+0x038A + 'Omicrontonos' => '968', # U+0x038C + 'Upsilontonos' => '939', # U+0x038E + 'Omegatonos' => '970', # U+0x038F + 'iotadieresistonos' => '341', # U+0x0390 + 'Alpha' => '776', # U+0x0391 + 'Beta' => '761', # U+0x0392 + 'Gamma' => '637', # U+0x0393 + 'Delta' => '805', # U+0x0394 + 'Epsilon' => '683', # U+0x0395 + 'Zeta' => '691', # U+0x0396 + 'Eta' => '837', # U+0x0397 + 'Theta' => '850', # U+0x0398 + 'Iota' => '545', # U+0x0399 + 'Kappa' => '770', # U+0x039A + 'Lambda' => '776', # U+0x039B + 'Mu' => '947', # U+0x039C + 'Nu' => '846', # U+0x039D + 'Xi' => '714', # U+0x039E + 'Omicron' => '850', # U+0x039F + 'Pi' => '837', # U+0x03A0 + 'Rho' => '732', # U+0x03A1 + 'Sigma' => '683', # U+0x03A3 + 'Tau' => '681', # U+0x03A4 + 'Upsilon' => '736', # U+0x03A5 + 'Phi' => '952', # U+0x03A6 + 'Chi' => '763', # U+0x03A7 + 'Psi' => '976', # U+0x03A8 + 'Omega' => '843', # U+0x03A9 + 'Iotadieresis' => '545', # U+0x03AA + 'Upsilondieresis' => '736', # U+0x03AB + 'alphatonos' => '699', # U+0x03AC + 'epsilontonos' => '584', # U+0x03AD + 'etatonos' => '712', # U+0x03AE + 'iotatonos' => '341', # U+0x03AF + 'upsilondieresistonos' => '706', # U+0x03B0 + 'alpha' => '699', # U+0x03B1 + 'beta' => '716', # U+0x03B2 + 'gamma' => '650', # U+0x03B3 + 'delta' => '686', # U+0x03B4 + 'epsilon' => '584', # U+0x03B5 + 'zeta' => '549', # U+0x03B6 + 'eta' => '712', # U+0x03B7 + 'theta' => '700', # U+0x03B8 + 'iota' => '341', # U+0x03B9 + 'kappa' => '670', # U+0x03BA + 'lambda' => '650', # U+0x03BB + 'nu' => '649', # U+0x03BD + 'xi' => '580', # U+0x03BE + 'omicron' => '686', # U+0x03BF + 'pi' => '719', # U+0x03C0 + 'rho' => '699', # U+0x03C1 + 'sigma1' => '562', # U+0x03C2 + 'sigma' => '725', # U+0x03C3 + 'tau' => '535', # U+0x03C4 + 'upsilon' => '706', # U+0x03C5 + 'phi' => '914', # U+0x03C6 + 'chi' => '635', # U+0x03C7 + 'psi' => '941', # U+0x03C8 + 'omega' => '894', # U+0x03C9 + 'iotadieresis' => '341', # U+0x03CA + 'upsilondieresis' => '706', # U+0x03CB + 'omicrontonos' => '686', # U+0x03CC + 'upsilontonos' => '706', # U+0x03CD + 'omegatonos' => '894', # U+0x03CE + 'afii10023' => '683', # U+0x0401 + 'afii10051' => '910', # U+0x0402 + 'afii10052' => '637', # U+0x0403 + 'afii10053' => '741', # U+0x0404 + 'afii10054' => '710', # U+0x0405 + 'afii10055' => '545', # U+0x0406 + 'afii10056' => '545', # U+0x0407 + 'afii10057' => '555', # U+0x0408 + 'afii10058' => '1222', # U+0x0409 + 'afii10059' => '1214', # U+0x040A + 'afii10060' => '936', # U+0x040B + 'afii10061' => '770', # U+0x040C + 'afii10062' => '736', # U+0x040E + 'afii10145' => '837', # U+0x040F + 'afii10017' => '776', # U+0x0410 + 'afii10018' => '757', # U+0x0411 + 'afii10019' => '761', # U+0x0412 + 'afii10020' => '637', # U+0x0413 + 'afii10021' => '841', # U+0x0414 + 'afii10022' => '683', # U+0x0415 + 'afii10024' => '1115', # U+0x0416 + 'afii10025' => '706', # U+0x0417 + 'afii10026' => '845', # U+0x0418 + 'afii10027' => '845', # U+0x0419 + 'afii10028' => '770', # U+0x041A + 'afii10029' => '845', # U+0x041B + 'afii10030' => '947', # U+0x041C + 'afii10031' => '837', # U+0x041D + 'afii10032' => '850', # U+0x041E + 'afii10033' => '837', # U+0x041F + 'afii10034' => '732', # U+0x0420 + 'afii10035' => '723', # U+0x0421 + 'afii10036' => '681', # U+0x0422 + 'afii10037' => '736', # U+0x0423 + 'afii10038' => '952', # U+0x0424 + 'afii10039' => '763', # U+0x0425 + 'afii10040' => '849', # U+0x0426 + 'afii10041' => '787', # U+0x0427 + 'afii10042' => '1163', # U+0x0428 + 'afii10043' => '1177', # U+0x0429 + 'afii10044' => '907', # U+0x042A + 'afii10045' => '1062', # U+0x042B + 'afii10046' => '757', # U+0x042C + 'afii10047' => '741', # U+0x042D + 'afii10048' => '1195', # U+0x042E + 'afii10049' => '794', # U+0x042F + 'afii10065' => '667', # U+0x0430 + 'afii10066' => '696', # U+0x0431 + 'afii10067' => '677', # U+0x0432 + 'afii10068' => '531', # U+0x0433 + 'afii10069' => '691', # U+0x0434 + 'afii10070' => '664', # U+0x0435 + 'afii10072' => '999', # U+0x0436 + 'afii10073' => '587', # U+0x0437 + 'afii10074' => '720', # U+0x0438 + 'afii10075' => '720', # U+0x0439 + 'afii10076' => '670', # U+0x043A + 'afii10077' => '709', # U+0x043B + 'afii10078' => '830', # U+0x043C + 'afii10079' => '719', # U+0x043D + 'afii10080' => '686', # U+0x043E + 'afii10081' => '719', # U+0x043F + 'afii10082' => '699', # U+0x0440 + 'afii10083' => '598', # U+0x0441 + 'afii10084' => '535', # U+0x0442 + 'afii10085' => '650', # U+0x0443 + 'afii10086' => '965', # U+0x0444 + 'afii10087' => '668', # U+0x0445 + 'afii10088' => '729', # U+0x0446 + 'afii10089' => '684', # U+0x0447 + 'afii10090' => '1002', # U+0x0448 + 'afii10091' => '1012', # U+0x0449 + 'afii10092' => '743', # U+0x044A + 'afii10093' => '937', # U+0x044B + 'afii10094' => '649', # U+0x044C + 'afii10095' => '605', # U+0x044D + 'afii10096' => '994', # U+0x044E + 'afii10097' => '681', # U+0x044F + 'afii10071' => '664', # U+0x0451 + 'afii10099' => '712', # U+0x0452 + 'afii10100' => '531', # U+0x0453 + 'afii10101' => '605', # U+0x0454 + 'afii10102' => '593', # U+0x0455 + 'afii10103' => '341', # U+0x0456 + 'afii10104' => '341', # U+0x0457 + 'afii10105' => '402', # U+0x0458 + 'afii10106' => '1012', # U+0x0459 + 'afii10107' => '1019', # U+0x045A + 'afii10108' => '712', # U+0x045B + 'afii10109' => '670', # U+0x045C + 'afii10110' => '650', # U+0x045E + 'afii10193' => '719', # U+0x045F + 'afii10050' => '637', # U+0x0490 + 'afii10098' => '531', # U+0x0491 + 'Wgrave' => '1128', # U+0x1E80 + 'wgrave' => '979', # U+0x1E81 + 'Wacute' => '1128', # U+0x1E82 + 'wacute' => '979', # U+0x1E83 + 'Wdieresis' => '1128', # U+0x1E84 + 'wdieresis' => '979', # U+0x1E85 + 'Ygrave' => '736', # U+0x1EF2 + 'ygrave' => '650', # U+0x1EF3 + 'afii00208' => '1000', # U+0x2015 + 'underscoredbl' => '710', # U+0x2017 + 'quotereversed' => '332', # U+0x201B + 'minute' => '352', # U+0x2032 + 'second' => '616', # U+0x2033 + 'exclamdbl' => '703', # U+0x203C + 'fraction' => '439', # U+0x2044 + 'foursuperior' => '597', # U+0x2074 + 'fivesuperior' => '597', # U+0x2075 + 'sevensuperior' => '597', # U+0x2077 + 'eightsuperior' => '597', # U+0x2078 + 'nsuperior' => '597', # U+0x207F + 'franc' => '710', # U+0x20A3 + 'peseta' => '1343', # U+0x20A7 + 'dong' => '699', # U+0x20AB + 'afii61248' => '1271', # U+0x2105 + 'afii61289' => '414', # U+0x2113 + 'afii61352' => '1293', # U+0x2116 + 'estimated' => '748', # U+0x212E + 'gimel' => '0', # U+0x2137 + 'oneeighth' => '1181', # U+0x215B + 'threeeighths' => '1181', # U+0x215C + 'fiveeighths' => '1181', # U+0x215D + 'seveneighths' => '1181', # U+0x215E + 'partialdiff' => '710', # U+0x2202 + 'product' => '869', # U+0x220F + 'summation' => '698', # U+0x2211 + 'minus' => '867', # U+0x2212 + 'radical' => '867', # U+0x221A + 'infinity' => '1058', # U+0x221E + 'integral' => '538', # U+0x222B + 'approxequal' => '867', # U+0x2248 + 'notequal' => '867', # U+0x2260 + 'lessequal' => '867', # U+0x2264 + 'greaterequal' => '867', # U+0x2265 + 'H22073' => '604', # U+0x25A1 + 'H18543' => '354', # U+0x25AA + 'H18551' => '354', # U+0x25AB + 'lozenge' => '867', # U+0x25CA + 'H18533' => '604', # U+0x25CF + 'openbullet' => '354', # U+0x25E6 + 'commaaccent' => '332', # U+0xF6C3 + 'radicalex' => '710', # U+0xF8E5 + 'fi' => '727', # U+0xFB01 + 'fl' => '730', # U+0xFB02 + }, # HORIZ. WIDTH TABLE +} }; + +1; diff --git a/lib/PDF/API2/Resource/Font/CoreFont/verdanabolditalic.pm b/lib/PDF/API2/Resource/Font/CoreFont/verdanabolditalic.pm new file mode 100644 index 0000000..7739e60 --- /dev/null +++ b/lib/PDF/API2/Resource/Font/CoreFont/verdanabolditalic.pm @@ -0,0 +1,848 @@ +#line 1 "PDF/API2/Resource/Font/CoreFont/verdanabolditalic.pm" +#line 1 "PDF/API2/Resource/Font/CoreFont/verdanabolditalic.pm" +package PDF::API2::Resource::Font::CoreFont::verdanabolditalic; + +use strict; +use warnings; + +our $VERSION = '2.033'; # VERSION + +sub data { return { + 'fontname' => 'Verdana,BoldItalic', + 'type' => 'TrueType', + 'apiname' => 'VeBoIt', + 'ascender' => '1005', + 'capheight' => '727', + 'descender' => '-209', + 'isfixedpitch' => '0', + 'issymbol' => '0', + 'italicangle' => '-13', + 'underlineposition' => '-139', + 'underlinethickness' => '211', + 'xheight' => '548', + 'firstchar' => '32', + 'lastchar' => '255', + 'flags' => '262240', + 'char' => [ # DEF. ENCODING GLYPH TABLE + '.notdef', # C+0x00 # U+0x0000 + '.notdef', # C+0x01 # U+0x0000 + '.notdef', # C+0x02 # U+0x0000 + '.notdef', # C+0x03 # U+0x0000 + '.notdef', # C+0x04 # U+0x0000 + '.notdef', # C+0x05 # U+0x0000 + '.notdef', # C+0x06 # U+0x0000 + '.notdef', # C+0x07 # U+0x0000 + '.notdef', # C+0x08 # U+0x0000 + '.notdef', # C+0x09 # U+0x0000 + '.notdef', # C+0x0A # U+0x0000 + '.notdef', # C+0x0B # U+0x0000 + '.notdef', # C+0x0C # U+0x0000 + '.notdef', # C+0x0D # U+0x0000 + '.notdef', # C+0x0E # U+0x0000 + '.notdef', # C+0x0F # U+0x0000 + '.notdef', # C+0x10 # U+0x0000 + '.notdef', # C+0x11 # U+0x0000 + '.notdef', # C+0x12 # U+0x0000 + '.notdef', # C+0x13 # U+0x0000 + '.notdef', # C+0x14 # U+0x0000 + '.notdef', # C+0x15 # U+0x0000 + '.notdef', # C+0x16 # U+0x0000 + '.notdef', # C+0x17 # U+0x0000 + '.notdef', # C+0x18 # U+0x0000 + '.notdef', # C+0x19 # U+0x0000 + '.notdef', # C+0x1A # U+0x0000 + '.notdef', # C+0x1B # U+0x0000 + '.notdef', # C+0x1C # U+0x0000 + '.notdef', # C+0x1D # U+0x0000 + '.notdef', # C+0x1E # U+0x0000 + '.notdef', # C+0x1F # U+0x0000 + 'space', # C+0x20 # U+0x0020 + 'exclam', # C+0x21 # U+0x0021 + 'quotedbl', # C+0x22 # U+0x0022 + 'numbersign', # C+0x23 # U+0x0023 + 'dollar', # C+0x24 # U+0x0024 + 'percent', # C+0x25 # U+0x0025 + 'ampersand', # C+0x26 # U+0x0026 + 'quotesingle', # C+0x27 # U+0x0027 + 'parenleft', # C+0x28 # U+0x0028 + 'parenright', # C+0x29 # U+0x0029 + 'asterisk', # C+0x2A # U+0x002A + 'plus', # C+0x2B # U+0x002B + 'comma', # C+0x2C # U+0x002C + 'hyphen', # C+0x2D # U+0x002D + 'period', # C+0x2E # U+0x002E + 'slash', # C+0x2F # U+0x002F + 'zero', # C+0x30 # U+0x0030 + 'one', # C+0x31 # U+0x0031 + 'two', # C+0x32 # U+0x0032 + 'three', # C+0x33 # U+0x0033 + 'four', # C+0x34 # U+0x0034 + 'five', # C+0x35 # U+0x0035 + 'six', # C+0x36 # U+0x0036 + 'seven', # C+0x37 # U+0x0037 + 'eight', # C+0x38 # U+0x0038 + 'nine', # C+0x39 # U+0x0039 + 'colon', # C+0x3A # U+0x003A + 'semicolon', # C+0x3B # U+0x003B + 'less', # C+0x3C # U+0x003C + 'equal', # C+0x3D # U+0x003D + 'greater', # C+0x3E # U+0x003E + 'question', # C+0x3F # U+0x003F + 'at', # C+0x40 # U+0x0040 + 'A', # C+0x41 # U+0x0041 + 'B', # C+0x42 # U+0x0042 + 'C', # C+0x43 # U+0x0043 + 'D', # C+0x44 # U+0x0044 + 'E', # C+0x45 # U+0x0045 + 'F', # C+0x46 # U+0x0046 + 'G', # C+0x47 # U+0x0047 + 'H', # C+0x48 # U+0x0048 + 'I', # C+0x49 # U+0x0049 + 'J', # C+0x4A # U+0x004A + 'K', # C+0x4B # U+0x004B + 'L', # C+0x4C # U+0x004C + 'M', # C+0x4D # U+0x004D + 'N', # C+0x4E # U+0x004E + 'O', # C+0x4F # U+0x004F + 'P', # C+0x50 # U+0x0050 + 'Q', # C+0x51 # U+0x0051 + 'R', # C+0x52 # U+0x0052 + 'S', # C+0x53 # U+0x0053 + 'T', # C+0x54 # U+0x0054 + 'U', # C+0x55 # U+0x0055 + 'V', # C+0x56 # U+0x0056 + 'W', # C+0x57 # U+0x0057 + 'X', # C+0x58 # U+0x0058 + 'Y', # C+0x59 # U+0x0059 + 'Z', # C+0x5A # U+0x005A + 'bracketleft', # C+0x5B # U+0x005B + 'backslash', # C+0x5C # U+0x005C + 'bracketright', # C+0x5D # U+0x005D + 'asciicircum', # C+0x5E # U+0x005E + 'underscore', # C+0x5F # U+0x005F + 'grave', # C+0x60 # U+0x0060 + 'a', # C+0x61 # U+0x0061 + 'b', # C+0x62 # U+0x0062 + 'c', # C+0x63 # U+0x0063 + 'd', # C+0x64 # U+0x0064 + 'e', # C+0x65 # U+0x0065 + 'f', # C+0x66 # U+0x0066 + 'g', # C+0x67 # U+0x0067 + 'h', # C+0x68 # U+0x0068 + 'i', # C+0x69 # U+0x0069 + 'j', # C+0x6A # U+0x006A + 'k', # C+0x6B # U+0x006B + 'l', # C+0x6C # U+0x006C + 'm', # C+0x6D # U+0x006D + 'n', # C+0x6E # U+0x006E + 'o', # C+0x6F # U+0x006F + 'p', # C+0x70 # U+0x0070 + 'q', # C+0x71 # U+0x0071 + 'r', # C+0x72 # U+0x0072 + 's', # C+0x73 # U+0x0073 + 't', # C+0x74 # U+0x0074 + 'u', # C+0x75 # U+0x0075 + 'v', # C+0x76 # U+0x0076 + 'w', # C+0x77 # U+0x0077 + 'x', # C+0x78 # U+0x0078 + 'y', # C+0x79 # U+0x0079 + 'z', # C+0x7A # U+0x007A + 'braceleft', # C+0x7B # U+0x007B + 'bar', # C+0x7C # U+0x007C + 'braceright', # C+0x7D # U+0x007D + 'asciitilde', # C+0x7E # U+0x007E + 'bullet', # C+0x7F # U+0x2022 + 'Euro', # C+0x80 # U+0x20AC + 'bullet', # C+0x81 # U+0x2022 + 'quotesinglbase', # C+0x82 # U+0x201A + 'florin', # C+0x83 # U+0x0192 + 'quotedblbase', # C+0x84 # U+0x201E + 'ellipsis', # C+0x85 # U+0x2026 + 'dagger', # C+0x86 # U+0x2020 + 'daggerdbl', # C+0x87 # U+0x2021 + 'circumflex', # C+0x88 # U+0x02C6 + 'perthousand', # C+0x89 # U+0x2030 + 'Scaron', # C+0x8A # U+0x0160 + 'guilsinglleft', # C+0x8B # U+0x2039 + 'OE', # C+0x8C # U+0x0152 + 'bullet', # C+0x8D # U+0x2022 + 'Zcaron', # C+0x8E # U+0x017D + 'bullet', # C+0x8F # U+0x2022 + 'bullet', # C+0x90 # U+0x2022 + 'quoteleft', # C+0x91 # U+0x2018 + 'quoteright', # C+0x92 # U+0x2019 + 'quotedblleft', # C+0x93 # U+0x201C + 'quotedblright', # C+0x94 # U+0x201D + 'bullet', # C+0x95 # U+0x2022 + 'endash', # C+0x96 # U+0x2013 + 'emdash', # C+0x97 # U+0x2014 + 'tilde', # C+0x98 # U+0x02DC + 'trademark', # C+0x99 # U+0x2122 + 'scaron', # C+0x9A # U+0x0161 + 'guilsinglright', # C+0x9B # U+0x203A + 'oe', # C+0x9C # U+0x0153 + 'bullet', # C+0x9D # U+0x2022 + 'zcaron', # C+0x9E # U+0x017E + 'Ydieresis', # C+0x9F # U+0x0178 + 'space', # C+0xA0 # U+0x0020 + 'exclamdown', # C+0xA1 # U+0x00A1 + 'cent', # C+0xA2 # U+0x00A2 + 'sterling', # C+0xA3 # U+0x00A3 + 'currency', # C+0xA4 # U+0x00A4 + 'yen', # C+0xA5 # U+0x00A5 + 'brokenbar', # C+0xA6 # U+0x00A6 + 'section', # C+0xA7 # U+0x00A7 + 'dieresis', # C+0xA8 # U+0x00A8 + 'copyright', # C+0xA9 # U+0x00A9 + 'ordfeminine', # C+0xAA # U+0x00AA + 'guillemotleft', # C+0xAB # U+0x00AB + 'logicalnot', # C+0xAC # U+0x00AC + 'hyphen', # C+0xAD # U+0x002D + 'registered', # C+0xAE # U+0x00AE + 'macron', # C+0xAF # U+0x00AF + 'degree', # C+0xB0 # U+0x00B0 + 'plusminus', # C+0xB1 # U+0x00B1 + 'twosuperior', # C+0xB2 # U+0x00B2 + 'threesuperior', # C+0xB3 # U+0x00B3 + 'acute', # C+0xB4 # U+0x00B4 + 'mu', # C+0xB5 # U+0x00B5 + 'paragraph', # C+0xB6 # U+0x00B6 + 'periodcentered', # C+0xB7 # U+0x00B7 + 'cedilla', # C+0xB8 # U+0x00B8 + 'onesuperior', # C+0xB9 # U+0x00B9 + 'ordmasculine', # C+0xBA # U+0x00BA + 'guillemotright', # C+0xBB # U+0x00BB + 'onequarter', # C+0xBC # U+0x00BC + 'onehalf', # C+0xBD # U+0x00BD + 'threequarters', # C+0xBE # U+0x00BE + 'questiondown', # C+0xBF # U+0x00BF + 'Agrave', # C+0xC0 # U+0x00C0 + 'Aacute', # C+0xC1 # U+0x00C1 + 'Acircumflex', # C+0xC2 # U+0x00C2 + 'Atilde', # C+0xC3 # U+0x00C3 + 'Adieresis', # C+0xC4 # U+0x00C4 + 'Aring', # C+0xC5 # U+0x00C5 + 'AE', # C+0xC6 # U+0x00C6 + 'Ccedilla', # C+0xC7 # U+0x00C7 + 'Egrave', # C+0xC8 # U+0x00C8 + 'Eacute', # C+0xC9 # U+0x00C9 + 'Ecircumflex', # C+0xCA # U+0x00CA + 'Edieresis', # C+0xCB # U+0x00CB + 'Igrave', # C+0xCC # U+0x00CC + 'Iacute', # C+0xCD # U+0x00CD + 'Icircumflex', # C+0xCE # U+0x00CE + 'Idieresis', # C+0xCF # U+0x00CF + 'Eth', # C+0xD0 # U+0x00D0 + 'Ntilde', # C+0xD1 # U+0x00D1 + 'Ograve', # C+0xD2 # U+0x00D2 + 'Oacute', # C+0xD3 # U+0x00D3 + 'Ocircumflex', # C+0xD4 # U+0x00D4 + 'Otilde', # C+0xD5 # U+0x00D5 + 'Odieresis', # C+0xD6 # U+0x00D6 + 'multiply', # C+0xD7 # U+0x00D7 + 'Oslash', # C+0xD8 # U+0x00D8 + 'Ugrave', # C+0xD9 # U+0x00D9 + 'Uacute', # C+0xDA # U+0x00DA + 'Ucircumflex', # C+0xDB # U+0x00DB + 'Udieresis', # C+0xDC # U+0x00DC + 'Yacute', # C+0xDD # U+0x00DD + 'Thorn', # C+0xDE # U+0x00DE + 'germandbls', # C+0xDF # U+0x00DF + 'agrave', # C+0xE0 # U+0x00E0 + 'aacute', # C+0xE1 # U+0x00E1 + 'acircumflex', # C+0xE2 # U+0x00E2 + 'atilde', # C+0xE3 # U+0x00E3 + 'adieresis', # C+0xE4 # U+0x00E4 + 'aring', # C+0xE5 # U+0x00E5 + 'ae', # C+0xE6 # U+0x00E6 + 'ccedilla', # C+0xE7 # U+0x00E7 + 'egrave', # C+0xE8 # U+0x00E8 + 'eacute', # C+0xE9 # U+0x00E9 + 'ecircumflex', # C+0xEA # U+0x00EA + 'edieresis', # C+0xEB # U+0x00EB + 'igrave', # C+0xEC # U+0x00EC + 'iacute', # C+0xED # U+0x00ED + 'icircumflex', # C+0xEE # U+0x00EE + 'idieresis', # C+0xEF # U+0x00EF + 'eth', # C+0xF0 # U+0x00F0 + 'ntilde', # C+0xF1 # U+0x00F1 + 'ograve', # C+0xF2 # U+0x00F2 + 'oacute', # C+0xF3 # U+0x00F3 + 'ocircumflex', # C+0xF4 # U+0x00F4 + 'otilde', # C+0xF5 # U+0x00F5 + 'odieresis', # C+0xF6 # U+0x00F6 + 'divide', # C+0xF7 # U+0x00F7 + 'oslash', # C+0xF8 # U+0x00F8 + 'ugrave', # C+0xF9 # U+0x00F9 + 'uacute', # C+0xFA # U+0x00FA + 'ucircumflex', # C+0xFB # U+0x00FB + 'udieresis', # C+0xFC # U+0x00FC + 'yacute', # C+0xFD # U+0x00FD + 'thorn', # C+0xFE # U+0x00FE + 'ydieresis', # C+0xFF # U+0x00FF + ], # DEF. ENCODING GLYPH TABLE + 'fontbbox' => [ -166, -207, 1704, 1000 ], + 'wx' => { # HORIZ. WIDTH TABLE + 'space' => '341', # C+0x20 # U+0x0020 + 'exclam' => '402', # C+0x21 # U+0x0021 + 'quotedbl' => '587', # C+0x22 # U+0x0022 + 'numbersign' => '867', # C+0x23 # U+0x0023 + 'dollar' => '710', # C+0x24 # U+0x0024 + 'percent' => '1271', # C+0x25 # U+0x0025 + 'ampersand' => '862', # C+0x26 # U+0x0026 + 'quotesingle' => '332', # C+0x27 # U+0x0027 + 'parenleft' => '543', # C+0x28 # U+0x0028 + 'parenright' => '543', # C+0x29 # U+0x0029 + 'asterisk' => '710', # C+0x2A # U+0x002A + 'plus' => '867', # C+0x2B # U+0x002B + 'comma' => '361', # C+0x2C # U+0x002C + 'hyphen' => '479', # C+0x2D # U+0x002D + 'period' => '361', # C+0x2E # U+0x002E + 'slash' => '689', # C+0x2F # U+0x002F + 'zero' => '710', # C+0x30 # U+0x0030 + 'one' => '710', # C+0x31 # U+0x0031 + 'two' => '710', # C+0x32 # U+0x0032 + 'three' => '710', # C+0x33 # U+0x0033 + 'four' => '710', # C+0x34 # U+0x0034 + 'five' => '710', # C+0x35 # U+0x0035 + 'six' => '710', # C+0x36 # U+0x0036 + 'seven' => '710', # C+0x37 # U+0x0037 + 'eight' => '710', # C+0x38 # U+0x0038 + 'nine' => '710', # C+0x39 # U+0x0039 + 'colon' => '402', # C+0x3A # U+0x003A + 'semicolon' => '402', # C+0x3B # U+0x003B + 'less' => '867', # C+0x3C # U+0x003C + 'equal' => '867', # C+0x3D # U+0x003D + 'greater' => '867', # C+0x3E # U+0x003E + 'question' => '616', # C+0x3F # U+0x003F + 'at' => '963', # C+0x40 # U+0x0040 + 'A' => '776', # C+0x41 # U+0x0041 + 'B' => '761', # C+0x42 # U+0x0042 + 'C' => '723', # C+0x43 # U+0x0043 + 'D' => '830', # C+0x44 # U+0x0044 + 'E' => '683', # C+0x45 # U+0x0045 + 'F' => '650', # C+0x46 # U+0x0046 + 'G' => '811', # C+0x47 # U+0x0047 + 'H' => '837', # C+0x48 # U+0x0048 + 'I' => '545', # C+0x49 # U+0x0049 + 'J' => '555', # C+0x4A # U+0x004A + 'K' => '770', # C+0x4B # U+0x004B + 'L' => '637', # C+0x4C # U+0x004C + 'M' => '947', # C+0x4D # U+0x004D + 'N' => '846', # C+0x4E # U+0x004E + 'O' => '850', # C+0x4F # U+0x004F + 'P' => '732', # C+0x50 # U+0x0050 + 'Q' => '850', # C+0x51 # U+0x0051 + 'R' => '782', # C+0x52 # U+0x0052 + 'S' => '710', # C+0x53 # U+0x0053 + 'T' => '681', # C+0x54 # U+0x0054 + 'U' => '812', # C+0x55 # U+0x0055 + 'V' => '763', # C+0x56 # U+0x0056 + 'W' => '1128', # C+0x57 # U+0x0057 + 'X' => '763', # C+0x58 # U+0x0058 + 'Y' => '736', # C+0x59 # U+0x0059 + 'Z' => '691', # C+0x5A # U+0x005A + 'bracketleft' => '543', # C+0x5B # U+0x005B + 'backslash' => '689', # C+0x5C # U+0x005C + 'bracketright' => '543', # C+0x5D # U+0x005D + 'asciicircum' => '867', # C+0x5E # U+0x005E + 'underscore' => '710', # C+0x5F # U+0x005F + 'grave' => '710', # C+0x60 # U+0x0060 + 'a' => '667', # C+0x61 # U+0x0061 + 'b' => '699', # C+0x62 # U+0x0062 + 'c' => '588', # C+0x63 # U+0x0063 + 'd' => '699', # C+0x64 # U+0x0064 + 'e' => '664', # C+0x65 # U+0x0065 + 'f' => '422', # C+0x66 # U+0x0066 + 'g' => '699', # C+0x67 # U+0x0067 + 'h' => '712', # C+0x68 # U+0x0068 + 'i' => '341', # C+0x69 # U+0x0069 + 'j' => '402', # C+0x6A # U+0x006A + 'k' => '670', # C+0x6B # U+0x006B + 'l' => '341', # C+0x6C # U+0x006C + 'm' => '1058', # C+0x6D # U+0x006D + 'n' => '712', # C+0x6E # U+0x006E + 'o' => '685', # C+0x6F # U+0x006F + 'p' => '699', # C+0x70 # U+0x0070 + 'q' => '699', # C+0x71 # U+0x0071 + 'r' => '497', # C+0x72 # U+0x0072 + 's' => '593', # C+0x73 # U+0x0073 + 't' => '455', # C+0x74 # U+0x0074 + 'u' => '712', # C+0x75 # U+0x0075 + 'v' => '648', # C+0x76 # U+0x0076 + 'w' => '979', # C+0x77 # U+0x0077 + 'x' => '668', # C+0x78 # U+0x0078 + 'y' => '650', # C+0x79 # U+0x0079 + 'z' => '596', # C+0x7A # U+0x007A + 'braceleft' => '710', # C+0x7B # U+0x007B + 'bar' => '543', # C+0x7C # U+0x007C + 'braceright' => '710', # C+0x7D # U+0x007D + 'asciitilde' => '867', # C+0x7E # U+0x007E + 'bullet' => '710', # C+0x7F # U+0x2022 + 'Euro' => '710', # C+0x80 # U+0x20AC + 'quotesinglbase' => '332', # C+0x82 # U+0x201A + 'florin' => '710', # C+0x83 # U+0x0192 + 'quotedblbase' => '587', # C+0x84 # U+0x201E + 'ellipsis' => '1048', # C+0x85 # U+0x2026 + 'dagger' => '710', # C+0x86 # U+0x2020 + 'daggerdbl' => '710', # C+0x87 # U+0x2021 + 'circumflex' => '710', # C+0x88 # U+0x02C6 + 'perthousand' => '1777', # C+0x89 # U+0x2030 + 'Scaron' => '710', # C+0x8A # U+0x0160 + 'guilsinglleft' => '543', # C+0x8B # U+0x2039 + 'OE' => '1135', # C+0x8C # U+0x0152 + 'Zcaron' => '691', # C+0x8E # U+0x017D + 'quoteleft' => '332', # C+0x91 # U+0x2018 + 'quoteright' => '332', # C+0x92 # U+0x2019 + 'quotedblleft' => '587', # C+0x93 # U+0x201C + 'quotedblright' => '587', # C+0x94 # U+0x201D + 'endash' => '710', # C+0x96 # U+0x2013 + 'emdash' => '1000', # C+0x97 # U+0x2014 + 'tilde' => '710', # C+0x98 # U+0x02DC + 'trademark' => '963', # C+0x99 # U+0x2122 + 'scaron' => '593', # C+0x9A # U+0x0161 + 'guilsinglright' => '543', # C+0x9B # U+0x203A + 'oe' => '1067', # C+0x9C # U+0x0153 + 'zcaron' => '596', # C+0x9E # U+0x017E + 'Ydieresis' => '736', # C+0x9F # U+0x0178 + 'exclamdown' => '402', # C+0xA1 # U+0x00A1 + 'cent' => '710', # C+0xA2 # U+0x00A2 + 'sterling' => '710', # C+0xA3 # U+0x00A3 + 'currency' => '710', # C+0xA4 # U+0x00A4 + 'yen' => '710', # C+0xA5 # U+0x00A5 + 'brokenbar' => '543', # C+0xA6 # U+0x00A6 + 'section' => '710', # C+0xA7 # U+0x00A7 + 'dieresis' => '710', # C+0xA8 # U+0x00A8 + 'copyright' => '963', # C+0xA9 # U+0x00A9 + 'ordfeminine' => '597', # C+0xAA # U+0x00AA + 'guillemotleft' => '849', # C+0xAB # U+0x00AB + 'logicalnot' => '867', # C+0xAC # U+0x00AC + 'registered' => '963', # C+0xAE # U+0x00AE + 'macron' => '710', # C+0xAF # U+0x00AF + 'degree' => '587', # C+0xB0 # U+0x00B0 + 'plusminus' => '867', # C+0xB1 # U+0x00B1 + 'twosuperior' => '597', # C+0xB2 # U+0x00B2 + 'threesuperior' => '597', # C+0xB3 # U+0x00B3 + 'acute' => '710', # C+0xB4 # U+0x00B4 + 'mu' => '719', # C+0xB5 # U+0x00B5 + 'paragraph' => '710', # C+0xB6 # U+0x00B6 + 'periodcentered' => '361', # C+0xB7 # U+0x00B7 + 'cedilla' => '710', # C+0xB8 # U+0x00B8 + 'onesuperior' => '597', # C+0xB9 # U+0x00B9 + 'ordmasculine' => '597', # C+0xBA # U+0x00BA + 'guillemotright' => '849', # C+0xBB # U+0x00BB + 'onequarter' => '1181', # C+0xBC # U+0x00BC + 'onehalf' => '1181', # C+0xBD # U+0x00BD + 'threequarters' => '1181', # C+0xBE # U+0x00BE + 'questiondown' => '616', # C+0xBF # U+0x00BF + 'Agrave' => '776', # C+0xC0 # U+0x00C0 + 'Aacute' => '776', # C+0xC1 # U+0x00C1 + 'Acircumflex' => '776', # C+0xC2 # U+0x00C2 + 'Atilde' => '776', # C+0xC3 # U+0x00C3 + 'Adieresis' => '776', # C+0xC4 # U+0x00C4 + 'Aring' => '776', # C+0xC5 # U+0x00C5 + 'AE' => '1093', # C+0xC6 # U+0x00C6 + 'Ccedilla' => '723', # C+0xC7 # U+0x00C7 + 'Egrave' => '683', # C+0xC8 # U+0x00C8 + 'Eacute' => '683', # C+0xC9 # U+0x00C9 + 'Ecircumflex' => '683', # C+0xCA # U+0x00CA + 'Edieresis' => '683', # C+0xCB # U+0x00CB + 'Igrave' => '545', # C+0xCC # U+0x00CC + 'Iacute' => '545', # C+0xCD # U+0x00CD + 'Icircumflex' => '545', # C+0xCE # U+0x00CE + 'Idieresis' => '545', # C+0xCF # U+0x00CF + 'Eth' => '830', # C+0xD0 # U+0x00D0 + 'Ntilde' => '846', # C+0xD1 # U+0x00D1 + 'Ograve' => '850', # C+0xD2 # U+0x00D2 + 'Oacute' => '850', # C+0xD3 # U+0x00D3 + 'Ocircumflex' => '850', # C+0xD4 # U+0x00D4 + 'Otilde' => '850', # C+0xD5 # U+0x00D5 + 'Odieresis' => '850', # C+0xD6 # U+0x00D6 + 'multiply' => '867', # C+0xD7 # U+0x00D7 + 'Oslash' => '850', # C+0xD8 # U+0x00D8 + 'Ugrave' => '812', # C+0xD9 # U+0x00D9 + 'Uacute' => '812', # C+0xDA # U+0x00DA + 'Ucircumflex' => '812', # C+0xDB # U+0x00DB + 'Udieresis' => '812', # C+0xDC # U+0x00DC + 'Yacute' => '736', # C+0xDD # U+0x00DD + 'Thorn' => '734', # C+0xDE # U+0x00DE + 'germandbls' => '712', # C+0xDF # U+0x00DF + 'agrave' => '667', # C+0xE0 # U+0x00E0 + 'aacute' => '667', # C+0xE1 # U+0x00E1 + 'acircumflex' => '667', # C+0xE2 # U+0x00E2 + 'atilde' => '667', # C+0xE3 # U+0x00E3 + 'adieresis' => '667', # C+0xE4 # U+0x00E4 + 'aring' => '667', # C+0xE5 # U+0x00E5 + 'ae' => '1018', # C+0xE6 # U+0x00E6 + 'ccedilla' => '588', # C+0xE7 # U+0x00E7 + 'egrave' => '664', # C+0xE8 # U+0x00E8 + 'eacute' => '664', # C+0xE9 # U+0x00E9 + 'ecircumflex' => '664', # C+0xEA # U+0x00EA + 'edieresis' => '664', # C+0xEB # U+0x00EB + 'igrave' => '341', # C+0xEC # U+0x00EC + 'iacute' => '341', # C+0xED # U+0x00ED + 'icircumflex' => '341', # C+0xEE # U+0x00EE + 'idieresis' => '341', # C+0xEF # U+0x00EF + 'eth' => '679', # C+0xF0 # U+0x00F0 + 'ntilde' => '712', # C+0xF1 # U+0x00F1 + 'ograve' => '685', # C+0xF2 # U+0x00F2 + 'oacute' => '685', # C+0xF3 # U+0x00F3 + 'ocircumflex' => '685', # C+0xF4 # U+0x00F4 + 'otilde' => '685', # C+0xF5 # U+0x00F5 + 'odieresis' => '685', # C+0xF6 # U+0x00F6 + 'divide' => '867', # C+0xF7 # U+0x00F7 + 'oslash' => '685', # C+0xF8 # U+0x00F8 + 'ugrave' => '712', # C+0xF9 # U+0x00F9 + 'uacute' => '712', # C+0xFA # U+0x00FA + 'ucircumflex' => '712', # C+0xFB # U+0x00FB + 'udieresis' => '712', # C+0xFC # U+0x00FC + 'yacute' => '650', # C+0xFD # U+0x00FD + 'thorn' => '699', # C+0xFE # U+0x00FE + 'ydieresis' => '650', # C+0xFF # U+0x00FF + 'middot' => '361', # U+0x00B7 + 'Amacron' => '776', # U+0x0100 + 'amacron' => '667', # U+0x0101 + 'Abreve' => '776', # U+0x0102 + 'abreve' => '667', # U+0x0103 + 'Aogonek' => '776', # U+0x0104 + 'aogonek' => '667', # U+0x0105 + 'Cacute' => '723', # U+0x0106 + 'cacute' => '588', # U+0x0107 + 'Ccircumflex' => '723', # U+0x0108 + 'ccircumflex' => '588', # U+0x0109 + 'Cdot' => '723', # U+0x010A + 'cdot' => '588', # U+0x010B + 'Ccaron' => '723', # U+0x010C + 'ccaron' => '588', # U+0x010D + 'Dcaron' => '830', # U+0x010E + 'dcaron' => '879', # U+0x010F + 'Emacron' => '683', # U+0x0112 + 'emacron' => '664', # U+0x0113 + 'Ebreve' => '683', # U+0x0114 + 'ebreve' => '664', # U+0x0115 + 'Edot' => '683', # U+0x0116 + 'edot' => '664', # U+0x0117 + 'Eogonek' => '683', # U+0x0118 + 'eogonek' => '664', # U+0x0119 + 'Ecaron' => '683', # U+0x011A + 'ecaron' => '664', # U+0x011B + 'Gcircumflex' => '811', # U+0x011C + 'gcircumflex' => '699', # U+0x011D + 'Gbreve' => '811', # U+0x011E + 'gbreve' => '699', # U+0x011F + 'Gdot' => '811', # U+0x0120 + 'gdot' => '699', # U+0x0121 + 'Hcircumflex' => '837', # U+0x0124 + 'hcircumflex' => '712', # U+0x0125 + 'Hbar' => '837', # U+0x0126 + 'hbar' => '712', # U+0x0127 + 'Itilde' => '545', # U+0x0128 + 'itilde' => '341', # U+0x0129 + 'Imacron' => '545', # U+0x012A + 'imacron' => '341', # U+0x012B + 'Ibreve' => '545', # U+0x012C + 'ibreve' => '341', # U+0x012D + 'Iogonek' => '545', # U+0x012E + 'iogonek' => '341', # U+0x012F + 'Idot' => '545', # U+0x0130 + 'dotlessi' => '341', # U+0x0131 + 'IJ' => '1007', # U+0x0132 + 'ij' => '727', # U+0x0133 + 'Jcircumflex' => '555', # U+0x0134 + 'jcircumflex' => '402', # U+0x0135 + 'kgreenlandic' => '670', # U+0x0138 + 'Lacute' => '637', # U+0x0139 + 'lacute' => '341', # U+0x013A + 'Lcaron' => '637', # U+0x013D + 'lcaron' => '522', # U+0x013E + 'Ldot' => '637', # U+0x013F + 'ldot' => '556', # U+0x0140 + 'Lslash' => '637', # U+0x0141 + 'lslash' => '351', # U+0x0142 + 'Nacute' => '846', # U+0x0143 + 'nacute' => '712', # U+0x0144 + 'Ncaron' => '846', # U+0x0147 + 'ncaron' => '712', # U+0x0148 + 'napostrophe' => '825', # U+0x0149 + 'Eng' => '846', # U+0x014A + 'eng' => '712', # U+0x014B + 'Omacron' => '850', # U+0x014C + 'omacron' => '685', # U+0x014D + 'Obreve' => '850', # U+0x014E + 'obreve' => '685', # U+0x014F + 'Racute' => '782', # U+0x0154 + 'racute' => '497', # U+0x0155 + 'Rcaron' => '782', # U+0x0158 + 'rcaron' => '497', # U+0x0159 + 'Sacute' => '710', # U+0x015A + 'sacute' => '593', # U+0x015B + 'Scircumflex' => '710', # U+0x015C + 'scircumflex' => '593', # U+0x015D + 'Scedilla' => '710', # U+0x015E + 'scedilla' => '593', # U+0x015F + 'Tcaron' => '681', # U+0x0164 + 'tcaron' => '465', # U+0x0165 + 'Tbar' => '681', # U+0x0166 + 'tbar' => '455', # U+0x0167 + 'Utilde' => '812', # U+0x0168 + 'utilde' => '712', # U+0x0169 + 'Umacron' => '812', # U+0x016A + 'umacron' => '712', # U+0x016B + 'Ubreve' => '812', # U+0x016C + 'ubreve' => '712', # U+0x016D + 'Uring' => '812', # U+0x016E + 'uring' => '712', # U+0x016F + 'Uogonek' => '812', # U+0x0172 + 'uogonek' => '712', # U+0x0173 + 'Wcircumflex' => '1128', # U+0x0174 + 'wcircumflex' => '979', # U+0x0175 + 'Ycircumflex' => '736', # U+0x0176 + 'ycircumflex' => '650', # U+0x0177 + 'Zacute' => '691', # U+0x0179 + 'zacute' => '596', # U+0x017A + 'Zdot' => '691', # U+0x017B + 'zdot' => '596', # U+0x017C + 'longs' => '344', # U+0x017F + 'Ohorn' => '913', # U+0x01A0 + 'ohorn' => '685', # U+0x01A1 + 'Uhorn' => '846', # U+0x01AF + 'uhorn' => '741', # U+0x01B0 + 'Aringacute' => '776', # U+0x01FA + 'aringacute' => '667', # U+0x01FB + 'AEacute' => '1093', # U+0x01FC + 'aeacute' => '1018', # U+0x01FD + 'Oslashacute' => '850', # U+0x01FE + 'oslashacute' => '685', # U+0x01FF + 'caron' => '710', # U+0x02C7 + 'breve' => '710', # U+0x02D8 + 'dotaccent' => '710', # U+0x02D9 + 'ring' => '710', # U+0x02DA + 'ogonek' => '710', # U+0x02DB + 'hungarumlaut' => '710', # U+0x02DD + 'gravecomb' => '0', # U+0x0300 + 'acutecomb' => '0', # U+0x0301 + 'tildecomb' => '0', # U+0x0303 + 'hookabovecomb' => '0', # U+0x0309 + 'dotbelowcomb' => '0', # U+0x0323 + 'tonos' => '710', # U+0x0384 + 'dieresistonos' => '710', # U+0x0385 + 'Alphatonos' => '797', # U+0x0386 + 'anoteleia' => '402', # U+0x0387 + 'Epsilontonos' => '847', # U+0x0388 + 'Etatonos' => '1000', # U+0x0389 + 'Iotatonos' => '705', # U+0x038A + 'Omicrontonos' => '968', # U+0x038C + 'Upsilontonos' => '939', # U+0x038E + 'Omegatonos' => '970', # U+0x038F + 'iotadieresistonos' => '341', # U+0x0390 + 'Alpha' => '776', # U+0x0391 + 'Beta' => '761', # U+0x0392 + 'Gamma' => '637', # U+0x0393 + 'Delta' => '805', # U+0x0394 + 'Epsilon' => '683', # U+0x0395 + 'Zeta' => '691', # U+0x0396 + 'Eta' => '837', # U+0x0397 + 'Theta' => '850', # U+0x0398 + 'Iota' => '545', # U+0x0399 + 'Kappa' => '770', # U+0x039A + 'Lambda' => '776', # U+0x039B + 'Mu' => '947', # U+0x039C + 'Nu' => '846', # U+0x039D + 'Xi' => '714', # U+0x039E + 'Omicron' => '850', # U+0x039F + 'Pi' => '837', # U+0x03A0 + 'Rho' => '732', # U+0x03A1 + 'Sigma' => '683', # U+0x03A3 + 'Tau' => '681', # U+0x03A4 + 'Upsilon' => '736', # U+0x03A5 + 'Phi' => '952', # U+0x03A6 + 'Chi' => '763', # U+0x03A7 + 'Psi' => '976', # U+0x03A8 + 'Omega' => '843', # U+0x03A9 + 'Iotadieresis' => '545', # U+0x03AA + 'Upsilondieresis' => '736', # U+0x03AB + 'alphatonos' => '699', # U+0x03AC + 'epsilontonos' => '584', # U+0x03AD + 'etatonos' => '712', # U+0x03AE + 'iotatonos' => '341', # U+0x03AF + 'upsilondieresistonos' => '706', # U+0x03B0 + 'alpha' => '699', # U+0x03B1 + 'beta' => '716', # U+0x03B2 + 'gamma' => '650', # U+0x03B3 + 'delta' => '686', # U+0x03B4 + 'epsilon' => '584', # U+0x03B5 + 'zeta' => '549', # U+0x03B6 + 'eta' => '712', # U+0x03B7 + 'theta' => '700', # U+0x03B8 + 'iota' => '341', # U+0x03B9 + 'kappa' => '670', # U+0x03BA + 'lambda' => '650', # U+0x03BB + 'nu' => '648', # U+0x03BD + 'xi' => '580', # U+0x03BE + 'omicron' => '685', # U+0x03BF + 'pi' => '719', # U+0x03C0 + 'rho' => '699', # U+0x03C1 + 'sigma1' => '562', # U+0x03C2 + 'sigma' => '725', # U+0x03C3 + 'tau' => '535', # U+0x03C4 + 'upsilon' => '706', # U+0x03C5 + 'phi' => '914', # U+0x03C6 + 'chi' => '635', # U+0x03C7 + 'psi' => '941', # U+0x03C8 + 'omega' => '894', # U+0x03C9 + 'iotadieresis' => '341', # U+0x03CA + 'upsilondieresis' => '706', # U+0x03CB + 'omicrontonos' => '685', # U+0x03CC + 'upsilontonos' => '706', # U+0x03CD + 'omegatonos' => '894', # U+0x03CE + 'afii10023' => '683', # U+0x0401 + 'afii10051' => '910', # U+0x0402 + 'afii10052' => '637', # U+0x0403 + 'afii10053' => '741', # U+0x0404 + 'afii10054' => '710', # U+0x0405 + 'afii10055' => '545', # U+0x0406 + 'afii10056' => '545', # U+0x0407 + 'afii10057' => '555', # U+0x0408 + 'afii10058' => '1222', # U+0x0409 + 'afii10059' => '1214', # U+0x040A + 'afii10060' => '936', # U+0x040B + 'afii10061' => '770', # U+0x040C + 'afii10062' => '736', # U+0x040E + 'afii10145' => '837', # U+0x040F + 'afii10017' => '776', # U+0x0410 + 'afii10018' => '757', # U+0x0411 + 'afii10019' => '761', # U+0x0412 + 'afii10020' => '637', # U+0x0413 + 'afii10021' => '841', # U+0x0414 + 'afii10022' => '683', # U+0x0415 + 'afii10024' => '1115', # U+0x0416 + 'afii10025' => '706', # U+0x0417 + 'afii10026' => '848', # U+0x0418 + 'afii10027' => '848', # U+0x0419 + 'afii10028' => '770', # U+0x041A + 'afii10029' => '845', # U+0x041B + 'afii10030' => '947', # U+0x041C + 'afii10031' => '837', # U+0x041D + 'afii10032' => '850', # U+0x041E + 'afii10033' => '837', # U+0x041F + 'afii10034' => '732', # U+0x0420 + 'afii10035' => '723', # U+0x0421 + 'afii10036' => '681', # U+0x0422 + 'afii10037' => '736', # U+0x0423 + 'afii10038' => '952', # U+0x0424 + 'afii10039' => '763', # U+0x0425 + 'afii10040' => '849', # U+0x0426 + 'afii10041' => '787', # U+0x0427 + 'afii10042' => '1163', # U+0x0428 + 'afii10043' => '1177', # U+0x0429 + 'afii10044' => '907', # U+0x042A + 'afii10045' => '1062', # U+0x042B + 'afii10046' => '757', # U+0x042C + 'afii10047' => '741', # U+0x042D + 'afii10048' => '1195', # U+0x042E + 'afii10049' => '794', # U+0x042F + 'afii10065' => '667', # U+0x0430 + 'afii10066' => '696', # U+0x0431 + 'afii10067' => '677', # U+0x0432 + 'afii10068' => '531', # U+0x0433 + 'afii10069' => '691', # U+0x0434 + 'afii10070' => '664', # U+0x0435 + 'afii10072' => '999', # U+0x0436 + 'afii10073' => '587', # U+0x0437 + 'afii10074' => '722', # U+0x0438 + 'afii10075' => '722', # U+0x0439 + 'afii10076' => '670', # U+0x043A + 'afii10077' => '709', # U+0x043B + 'afii10078' => '830', # U+0x043C + 'afii10079' => '719', # U+0x043D + 'afii10080' => '685', # U+0x043E + 'afii10081' => '719', # U+0x043F + 'afii10082' => '699', # U+0x0440 + 'afii10083' => '588', # U+0x0441 + 'afii10084' => '535', # U+0x0442 + 'afii10085' => '650', # U+0x0443 + 'afii10086' => '965', # U+0x0444 + 'afii10087' => '668', # U+0x0445 + 'afii10088' => '729', # U+0x0446 + 'afii10089' => '684', # U+0x0447 + 'afii10090' => '1002', # U+0x0448 + 'afii10091' => '1012', # U+0x0449 + 'afii10092' => '743', # U+0x044A + 'afii10093' => '937', # U+0x044B + 'afii10094' => '649', # U+0x044C + 'afii10095' => '608', # U+0x044D + 'afii10096' => '994', # U+0x044E + 'afii10097' => '681', # U+0x044F + 'afii10071' => '664', # U+0x0451 + 'afii10099' => '712', # U+0x0452 + 'afii10100' => '531', # U+0x0453 + 'afii10101' => '605', # U+0x0454 + 'afii10102' => '593', # U+0x0455 + 'afii10103' => '341', # U+0x0456 + 'afii10104' => '341', # U+0x0457 + 'afii10105' => '402', # U+0x0458 + 'afii10106' => '1012', # U+0x0459 + 'afii10107' => '1019', # U+0x045A + 'afii10108' => '712', # U+0x045B + 'afii10109' => '670', # U+0x045C + 'afii10110' => '650', # U+0x045E + 'afii10193' => '719', # U+0x045F + 'afii10050' => '637', # U+0x0490 + 'afii10098' => '531', # U+0x0491 + 'Wgrave' => '1128', # U+0x1E80 + 'wgrave' => '979', # U+0x1E81 + 'Wacute' => '1128', # U+0x1E82 + 'wacute' => '979', # U+0x1E83 + 'Wdieresis' => '1128', # U+0x1E84 + 'wdieresis' => '979', # U+0x1E85 + 'Ygrave' => '736', # U+0x1EF2 + 'ygrave' => '650', # U+0x1EF3 + 'afii00208' => '1000', # U+0x2015 + 'underscoredbl' => '710', # U+0x2017 + 'quotereversed' => '332', # U+0x201B + 'minute' => '352', # U+0x2032 + 'second' => '616', # U+0x2033 + 'exclamdbl' => '703', # U+0x203C + 'fraction' => '321', # U+0x2044 + 'foursuperior' => '597', # U+0x2074 + 'fivesuperior' => '597', # U+0x2075 + 'sevensuperior' => '597', # U+0x2077 + 'eightsuperior' => '597', # U+0x2078 + 'nsuperior' => '597', # U+0x207F + 'franc' => '710', # U+0x20A3 + 'peseta' => '1343', # U+0x20A7 + 'dong' => '699', # U+0x20AB + 'afii61248' => '1271', # U+0x2105 + 'afii61289' => '414', # U+0x2113 + 'afii61352' => '1293', # U+0x2116 + 'estimated' => '748', # U+0x212E + 'gimel' => '0', # U+0x2137 + 'oneeighth' => '1181', # U+0x215B + 'threeeighths' => '1181', # U+0x215C + 'fiveeighths' => '1181', # U+0x215D + 'seveneighths' => '1181', # U+0x215E + 'partialdiff' => '710', # U+0x2202 + 'product' => '869', # U+0x220F + 'summation' => '698', # U+0x2211 + 'minus' => '867', # U+0x2212 + 'radical' => '867', # U+0x221A + 'infinity' => '1058', # U+0x221E + 'integral' => '538', # U+0x222B + 'approxequal' => '867', # U+0x2248 + 'notequal' => '867', # U+0x2260 + 'lessequal' => '867', # U+0x2264 + 'greaterequal' => '867', # U+0x2265 + 'H22073' => '604', # U+0x25A1 + 'H18543' => '354', # U+0x25AA + 'H18551' => '354', # U+0x25AB + 'lozenge' => '867', # U+0x25CA + 'H18533' => '604', # U+0x25CF + 'openbullet' => '354', # U+0x25E6 + 'commaaccent' => '361', # U+0xF6C3 + 'radicalex' => '710', # U+0xF8E5 + 'fi' => '727', # U+0xFB01 + 'fl' => '730', # U+0xFB02 + }, # HORIZ. WIDTH TABLE +} }; + +1; diff --git a/lib/PDF/API2/Resource/Font/CoreFont/verdanaitalic.pm b/lib/PDF/API2/Resource/Font/CoreFont/verdanaitalic.pm new file mode 100644 index 0000000..5bd18c4 --- /dev/null +++ b/lib/PDF/API2/Resource/Font/CoreFont/verdanaitalic.pm @@ -0,0 +1,847 @@ +#line 1 "PDF/API2/Resource/Font/CoreFont/verdanaitalic.pm" +#line 1 "PDF/API2/Resource/Font/CoreFont/verdanaitalic.pm" +package PDF::API2::Resource::Font::CoreFont::verdanaitalic; + +use strict; +use warnings; + +our $VERSION = '2.033'; # VERSION + +sub data { return { + 'fontname' => 'Verdana,Italic', + 'type' => 'TrueType', + 'apiname' => 'VeIt', + 'ascender' => '1005', + 'capheight' => '727', + 'descender' => '-209', + 'isfixedpitch' => '0', + 'issymbol' => '0', + 'italicangle' => '-13', + 'underlineposition' => '-180', + 'underlinethickness' => '120', + 'xheight' => '545', + 'firstchar' => '32', + 'lastchar' => '255', + 'flags' => '96', + 'char' => [ # DEF. ENCODING GLYPH TABLE + '.notdef', # C+0x00 # U+0x0000 + '.notdef', # C+0x01 # U+0x0000 + '.notdef', # C+0x02 # U+0x0000 + '.notdef', # C+0x03 # U+0x0000 + '.notdef', # C+0x04 # U+0x0000 + '.notdef', # C+0x05 # U+0x0000 + '.notdef', # C+0x06 # U+0x0000 + '.notdef', # C+0x07 # U+0x0000 + '.notdef', # C+0x08 # U+0x0000 + '.notdef', # C+0x09 # U+0x0000 + '.notdef', # C+0x0A # U+0x0000 + '.notdef', # C+0x0B # U+0x0000 + '.notdef', # C+0x0C # U+0x0000 + '.notdef', # C+0x0D # U+0x0000 + '.notdef', # C+0x0E # U+0x0000 + '.notdef', # C+0x0F # U+0x0000 + '.notdef', # C+0x10 # U+0x0000 + '.notdef', # C+0x11 # U+0x0000 + '.notdef', # C+0x12 # U+0x0000 + '.notdef', # C+0x13 # U+0x0000 + '.notdef', # C+0x14 # U+0x0000 + '.notdef', # C+0x15 # U+0x0000 + '.notdef', # C+0x16 # U+0x0000 + '.notdef', # C+0x17 # U+0x0000 + '.notdef', # C+0x18 # U+0x0000 + '.notdef', # C+0x19 # U+0x0000 + '.notdef', # C+0x1A # U+0x0000 + '.notdef', # C+0x1B # U+0x0000 + '.notdef', # C+0x1C # U+0x0000 + '.notdef', # C+0x1D # U+0x0000 + '.notdef', # C+0x1E # U+0x0000 + '.notdef', # C+0x1F # U+0x0000 + 'space', # C+0x20 # U+0x0020 + 'exclam', # C+0x21 # U+0x0021 + 'quotedbl', # C+0x22 # U+0x0022 + 'numbersign', # C+0x23 # U+0x0023 + 'dollar', # C+0x24 # U+0x0024 + 'percent', # C+0x25 # U+0x0025 + 'ampersand', # C+0x26 # U+0x0026 + 'quotesingle', # C+0x27 # U+0x0027 + 'parenleft', # C+0x28 # U+0x0028 + 'parenright', # C+0x29 # U+0x0029 + 'asterisk', # C+0x2A # U+0x002A + 'plus', # C+0x2B # U+0x002B + 'comma', # C+0x2C # U+0x002C + 'hyphen', # C+0x2D # U+0x002D + 'period', # C+0x2E # U+0x002E + 'slash', # C+0x2F # U+0x002F + 'zero', # C+0x30 # U+0x0030 + 'one', # C+0x31 # U+0x0031 + 'two', # C+0x32 # U+0x0032 + 'three', # C+0x33 # U+0x0033 + 'four', # C+0x34 # U+0x0034 + 'five', # C+0x35 # U+0x0035 + 'six', # C+0x36 # U+0x0036 + 'seven', # C+0x37 # U+0x0037 + 'eight', # C+0x38 # U+0x0038 + 'nine', # C+0x39 # U+0x0039 + 'colon', # C+0x3A # U+0x003A + 'semicolon', # C+0x3B # U+0x003B + 'less', # C+0x3C # U+0x003C + 'equal', # C+0x3D # U+0x003D + 'greater', # C+0x3E # U+0x003E + 'question', # C+0x3F # U+0x003F + 'at', # C+0x40 # U+0x0040 + 'A', # C+0x41 # U+0x0041 + 'B', # C+0x42 # U+0x0042 + 'C', # C+0x43 # U+0x0043 + 'D', # C+0x44 # U+0x0044 + 'E', # C+0x45 # U+0x0045 + 'F', # C+0x46 # U+0x0046 + 'G', # C+0x47 # U+0x0047 + 'H', # C+0x48 # U+0x0048 + 'I', # C+0x49 # U+0x0049 + 'J', # C+0x4A # U+0x004A + 'K', # C+0x4B # U+0x004B + 'L', # C+0x4C # U+0x004C + 'M', # C+0x4D # U+0x004D + 'N', # C+0x4E # U+0x004E + 'O', # C+0x4F # U+0x004F + 'P', # C+0x50 # U+0x0050 + 'Q', # C+0x51 # U+0x0051 + 'R', # C+0x52 # U+0x0052 + 'S', # C+0x53 # U+0x0053 + 'T', # C+0x54 # U+0x0054 + 'U', # C+0x55 # U+0x0055 + 'V', # C+0x56 # U+0x0056 + 'W', # C+0x57 # U+0x0057 + 'X', # C+0x58 # U+0x0058 + 'Y', # C+0x59 # U+0x0059 + 'Z', # C+0x5A # U+0x005A + 'bracketleft', # C+0x5B # U+0x005B + 'backslash', # C+0x5C # U+0x005C + 'bracketright', # C+0x5D # U+0x005D + 'asciicircum', # C+0x5E # U+0x005E + 'underscore', # C+0x5F # U+0x005F + 'grave', # C+0x60 # U+0x0060 + 'a', # C+0x61 # U+0x0061 + 'b', # C+0x62 # U+0x0062 + 'c', # C+0x63 # U+0x0063 + 'd', # C+0x64 # U+0x0064 + 'e', # C+0x65 # U+0x0065 + 'f', # C+0x66 # U+0x0066 + 'g', # C+0x67 # U+0x0067 + 'h', # C+0x68 # U+0x0068 + 'i', # C+0x69 # U+0x0069 + 'j', # C+0x6A # U+0x006A + 'k', # C+0x6B # U+0x006B + 'l', # C+0x6C # U+0x006C + 'm', # C+0x6D # U+0x006D + 'n', # C+0x6E # U+0x006E + 'o', # C+0x6F # U+0x006F + 'p', # C+0x70 # U+0x0070 + 'q', # C+0x71 # U+0x0071 + 'r', # C+0x72 # U+0x0072 + 's', # C+0x73 # U+0x0073 + 't', # C+0x74 # U+0x0074 + 'u', # C+0x75 # U+0x0075 + 'v', # C+0x76 # U+0x0076 + 'w', # C+0x77 # U+0x0077 + 'x', # C+0x78 # U+0x0078 + 'y', # C+0x79 # U+0x0079 + 'z', # C+0x7A # U+0x007A + 'braceleft', # C+0x7B # U+0x007B + 'bar', # C+0x7C # U+0x007C + 'braceright', # C+0x7D # U+0x007D + 'asciitilde', # C+0x7E # U+0x007E + 'bullet', # C+0x7F # U+0x2022 + 'Euro', # C+0x80 # U+0x20AC + 'bullet', # C+0x81 # U+0x2022 + 'quotesinglbase', # C+0x82 # U+0x201A + 'florin', # C+0x83 # U+0x0192 + 'quotedblbase', # C+0x84 # U+0x201E + 'ellipsis', # C+0x85 # U+0x2026 + 'dagger', # C+0x86 # U+0x2020 + 'daggerdbl', # C+0x87 # U+0x2021 + 'circumflex', # C+0x88 # U+0x02C6 + 'perthousand', # C+0x89 # U+0x2030 + 'Scaron', # C+0x8A # U+0x0160 + 'guilsinglleft', # C+0x8B # U+0x2039 + 'OE', # C+0x8C # U+0x0152 + 'bullet', # C+0x8D # U+0x2022 + 'Zcaron', # C+0x8E # U+0x017D + 'bullet', # C+0x8F # U+0x2022 + 'bullet', # C+0x90 # U+0x2022 + 'quoteleft', # C+0x91 # U+0x2018 + 'quoteright', # C+0x92 # U+0x2019 + 'quotedblleft', # C+0x93 # U+0x201C + 'quotedblright', # C+0x94 # U+0x201D + 'bullet', # C+0x95 # U+0x2022 + 'endash', # C+0x96 # U+0x2013 + 'emdash', # C+0x97 # U+0x2014 + 'tilde', # C+0x98 # U+0x02DC + 'trademark', # C+0x99 # U+0x2122 + 'scaron', # C+0x9A # U+0x0161 + 'guilsinglright', # C+0x9B # U+0x203A + 'oe', # C+0x9C # U+0x0153 + 'bullet', # C+0x9D # U+0x2022 + 'zcaron', # C+0x9E # U+0x017E + 'Ydieresis', # C+0x9F # U+0x0178 + 'space', # C+0xA0 # U+0x0020 + 'exclamdown', # C+0xA1 # U+0x00A1 + 'cent', # C+0xA2 # U+0x00A2 + 'sterling', # C+0xA3 # U+0x00A3 + 'currency', # C+0xA4 # U+0x00A4 + 'yen', # C+0xA5 # U+0x00A5 + 'brokenbar', # C+0xA6 # U+0x00A6 + 'section', # C+0xA7 # U+0x00A7 + 'dieresis', # C+0xA8 # U+0x00A8 + 'copyright', # C+0xA9 # U+0x00A9 + 'ordfeminine', # C+0xAA # U+0x00AA + 'guillemotleft', # C+0xAB # U+0x00AB + 'logicalnot', # C+0xAC # U+0x00AC + 'hyphen', # C+0xAD # U+0x002D + 'registered', # C+0xAE # U+0x00AE + 'macron', # C+0xAF # U+0x00AF + 'degree', # C+0xB0 # U+0x00B0 + 'plusminus', # C+0xB1 # U+0x00B1 + 'twosuperior', # C+0xB2 # U+0x00B2 + 'threesuperior', # C+0xB3 # U+0x00B3 + 'acute', # C+0xB4 # U+0x00B4 + 'mu', # C+0xB5 # U+0x00B5 + 'paragraph', # C+0xB6 # U+0x00B6 + 'periodcentered', # C+0xB7 # U+0x00B7 + 'cedilla', # C+0xB8 # U+0x00B8 + 'onesuperior', # C+0xB9 # U+0x00B9 + 'ordmasculine', # C+0xBA # U+0x00BA + 'guillemotright', # C+0xBB # U+0x00BB + 'onequarter', # C+0xBC # U+0x00BC + 'onehalf', # C+0xBD # U+0x00BD + 'threequarters', # C+0xBE # U+0x00BE + 'questiondown', # C+0xBF # U+0x00BF + 'Agrave', # C+0xC0 # U+0x00C0 + 'Aacute', # C+0xC1 # U+0x00C1 + 'Acircumflex', # C+0xC2 # U+0x00C2 + 'Atilde', # C+0xC3 # U+0x00C3 + 'Adieresis', # C+0xC4 # U+0x00C4 + 'Aring', # C+0xC5 # U+0x00C5 + 'AE', # C+0xC6 # U+0x00C6 + 'Ccedilla', # C+0xC7 # U+0x00C7 + 'Egrave', # C+0xC8 # U+0x00C8 + 'Eacute', # C+0xC9 # U+0x00C9 + 'Ecircumflex', # C+0xCA # U+0x00CA + 'Edieresis', # C+0xCB # U+0x00CB + 'Igrave', # C+0xCC # U+0x00CC + 'Iacute', # C+0xCD # U+0x00CD + 'Icircumflex', # C+0xCE # U+0x00CE + 'Idieresis', # C+0xCF # U+0x00CF + 'Eth', # C+0xD0 # U+0x00D0 + 'Ntilde', # C+0xD1 # U+0x00D1 + 'Ograve', # C+0xD2 # U+0x00D2 + 'Oacute', # C+0xD3 # U+0x00D3 + 'Ocircumflex', # C+0xD4 # U+0x00D4 + 'Otilde', # C+0xD5 # U+0x00D5 + 'Odieresis', # C+0xD6 # U+0x00D6 + 'multiply', # C+0xD7 # U+0x00D7 + 'Oslash', # C+0xD8 # U+0x00D8 + 'Ugrave', # C+0xD9 # U+0x00D9 + 'Uacute', # C+0xDA # U+0x00DA + 'Ucircumflex', # C+0xDB # U+0x00DB + 'Udieresis', # C+0xDC # U+0x00DC + 'Yacute', # C+0xDD # U+0x00DD + 'Thorn', # C+0xDE # U+0x00DE + 'germandbls', # C+0xDF # U+0x00DF + 'agrave', # C+0xE0 # U+0x00E0 + 'aacute', # C+0xE1 # U+0x00E1 + 'acircumflex', # C+0xE2 # U+0x00E2 + 'atilde', # C+0xE3 # U+0x00E3 + 'adieresis', # C+0xE4 # U+0x00E4 + 'aring', # C+0xE5 # U+0x00E5 + 'ae', # C+0xE6 # U+0x00E6 + 'ccedilla', # C+0xE7 # U+0x00E7 + 'egrave', # C+0xE8 # U+0x00E8 + 'eacute', # C+0xE9 # U+0x00E9 + 'ecircumflex', # C+0xEA # U+0x00EA + 'edieresis', # C+0xEB # U+0x00EB + 'igrave', # C+0xEC # U+0x00EC + 'iacute', # C+0xED # U+0x00ED + 'icircumflex', # C+0xEE # U+0x00EE + 'idieresis', # C+0xEF # U+0x00EF + 'eth', # C+0xF0 # U+0x00F0 + 'ntilde', # C+0xF1 # U+0x00F1 + 'ograve', # C+0xF2 # U+0x00F2 + 'oacute', # C+0xF3 # U+0x00F3 + 'ocircumflex', # C+0xF4 # U+0x00F4 + 'otilde', # C+0xF5 # U+0x00F5 + 'odieresis', # C+0xF6 # U+0x00F6 + 'divide', # C+0xF7 # U+0x00F7 + 'oslash', # C+0xF8 # U+0x00F8 + 'ugrave', # C+0xF9 # U+0x00F9 + 'uacute', # C+0xFA # U+0x00FA + 'ucircumflex', # C+0xFB # U+0x00FB + 'udieresis', # C+0xFC # U+0x00FC + 'yacute', # C+0xFD # U+0x00FD + 'thorn', # C+0xFE # U+0x00FE + 'ydieresis', # C+0xFF # U+0x00FF + ], # DEF. ENCODING GLYPH TABLE + 'fontbbox' => [ -131, -206, 1460, 1000 ], + 'wx' => { # HORIZ. WIDTH TABLE + 'space' => '351', # C+0x20 # U+0x0020 + 'exclam' => '393', # C+0x21 # U+0x0021 + 'quotedbl' => '458', # C+0x22 # U+0x0022 + 'numbersign' => '818', # C+0x23 # U+0x0023 + 'dollar' => '635', # C+0x24 # U+0x0024 + 'percent' => '1076', # C+0x25 # U+0x0025 + 'ampersand' => '726', # C+0x26 # U+0x0026 + 'quotesingle' => '268', # C+0x27 # U+0x0027 + 'parenleft' => '454', # C+0x28 # U+0x0028 + 'parenright' => '454', # C+0x29 # U+0x0029 + 'asterisk' => '635', # C+0x2A # U+0x002A + 'plus' => '818', # C+0x2B # U+0x002B + 'comma' => '363', # C+0x2C # U+0x002C + 'hyphen' => '454', # C+0x2D # U+0x002D + 'period' => '363', # C+0x2E # U+0x002E + 'slash' => '454', # C+0x2F # U+0x002F + 'zero' => '635', # C+0x30 # U+0x0030 + 'one' => '635', # C+0x31 # U+0x0031 + 'two' => '635', # C+0x32 # U+0x0032 + 'three' => '635', # C+0x33 # U+0x0033 + 'four' => '635', # C+0x34 # U+0x0034 + 'five' => '635', # C+0x35 # U+0x0035 + 'six' => '635', # C+0x36 # U+0x0036 + 'seven' => '635', # C+0x37 # U+0x0037 + 'eight' => '635', # C+0x38 # U+0x0038 + 'nine' => '635', # C+0x39 # U+0x0039 + 'colon' => '454', # C+0x3A # U+0x003A + 'semicolon' => '454', # C+0x3B # U+0x003B + 'less' => '818', # C+0x3C # U+0x003C + 'equal' => '818', # C+0x3D # U+0x003D + 'greater' => '818', # C+0x3E # U+0x003E + 'question' => '545', # C+0x3F # U+0x003F + 'at' => '1000', # C+0x40 # U+0x0040 + 'A' => '682', # C+0x41 # U+0x0041 + 'B' => '685', # C+0x42 # U+0x0042 + 'C' => '698', # C+0x43 # U+0x0043 + 'D' => '765', # C+0x44 # U+0x0044 + 'E' => '632', # C+0x45 # U+0x0045 + 'F' => '574', # C+0x46 # U+0x0046 + 'G' => '775', # C+0x47 # U+0x0047 + 'H' => '751', # C+0x48 # U+0x0048 + 'I' => '420', # C+0x49 # U+0x0049 + 'J' => '454', # C+0x4A # U+0x004A + 'K' => '692', # C+0x4B # U+0x004B + 'L' => '556', # C+0x4C # U+0x004C + 'M' => '842', # C+0x4D # U+0x004D + 'N' => '748', # C+0x4E # U+0x004E + 'O' => '787', # C+0x4F # U+0x004F + 'P' => '603', # C+0x50 # U+0x0050 + 'Q' => '787', # C+0x51 # U+0x0051 + 'R' => '695', # C+0x52 # U+0x0052 + 'S' => '683', # C+0x53 # U+0x0053 + 'T' => '616', # C+0x54 # U+0x0054 + 'U' => '731', # C+0x55 # U+0x0055 + 'V' => '682', # C+0x56 # U+0x0056 + 'W' => '990', # C+0x57 # U+0x0057 + 'X' => '685', # C+0x58 # U+0x0058 + 'Y' => '615', # C+0x59 # U+0x0059 + 'Z' => '685', # C+0x5A # U+0x005A + 'bracketleft' => '454', # C+0x5B # U+0x005B + 'backslash' => '454', # C+0x5C # U+0x005C + 'bracketright' => '454', # C+0x5D # U+0x005D + 'asciicircum' => '818', # C+0x5E # U+0x005E + 'underscore' => '635', # C+0x5F # U+0x005F + 'grave' => '635', # C+0x60 # U+0x0060 + 'a' => '600', # C+0x61 # U+0x0061 + 'b' => '623', # C+0x62 # U+0x0062 + 'c' => '520', # C+0x63 # U+0x0063 + 'd' => '623', # C+0x64 # U+0x0064 + 'e' => '595', # C+0x65 # U+0x0065 + 'f' => '351', # C+0x66 # U+0x0066 + 'g' => '621', # C+0x67 # U+0x0067 + 'h' => '632', # C+0x68 # U+0x0068 + 'i' => '274', # C+0x69 # U+0x0069 + 'j' => '344', # C+0x6A # U+0x006A + 'k' => '586', # C+0x6B # U+0x006B + 'l' => '274', # C+0x6C # U+0x006C + 'm' => '973', # C+0x6D # U+0x006D + 'n' => '632', # C+0x6E # U+0x006E + 'o' => '606', # C+0x6F # U+0x006F + 'p' => '623', # C+0x70 # U+0x0070 + 'q' => '623', # C+0x71 # U+0x0071 + 'r' => '426', # C+0x72 # U+0x0072 + 's' => '520', # C+0x73 # U+0x0073 + 't' => '394', # C+0x74 # U+0x0074 + 'u' => '632', # C+0x75 # U+0x0075 + 'v' => '590', # C+0x76 # U+0x0076 + 'w' => '818', # C+0x77 # U+0x0077 + 'x' => '591', # C+0x78 # U+0x0078 + 'y' => '590', # C+0x79 # U+0x0079 + 'z' => '525', # C+0x7A # U+0x007A + 'braceleft' => '634', # C+0x7B # U+0x007B + 'bar' => '454', # C+0x7C # U+0x007C + 'braceright' => '634', # C+0x7D # U+0x007D + 'asciitilde' => '818', # C+0x7E # U+0x007E + 'bullet' => '545', # C+0x7F # U+0x2022 + 'Euro' => '635', # C+0x80 # U+0x20AC + 'quotesinglbase' => '268', # C+0x82 # U+0x201A + 'florin' => '635', # C+0x83 # U+0x0192 + 'quotedblbase' => '458', # C+0x84 # U+0x201E + 'ellipsis' => '818', # C+0x85 # U+0x2026 + 'dagger' => '635', # C+0x86 # U+0x2020 + 'daggerdbl' => '635', # C+0x87 # U+0x2021 + 'circumflex' => '635', # C+0x88 # U+0x02C6 + 'perthousand' => '1518', # C+0x89 # U+0x2030 + 'Scaron' => '683', # C+0x8A # U+0x0160 + 'guilsinglleft' => '454', # C+0x8B # U+0x2039 + 'OE' => '1069', # C+0x8C # U+0x0152 + 'Zcaron' => '685', # C+0x8E # U+0x017D + 'quoteleft' => '268', # C+0x91 # U+0x2018 + 'quoteright' => '268', # C+0x92 # U+0x2019 + 'quotedblleft' => '458', # C+0x93 # U+0x201C + 'quotedblright' => '458', # C+0x94 # U+0x201D + 'endash' => '635', # C+0x96 # U+0x2013 + 'emdash' => '1000', # C+0x97 # U+0x2014 + 'tilde' => '635', # C+0x98 # U+0x02DC + 'trademark' => '976', # C+0x99 # U+0x2122 + 'scaron' => '520', # C+0x9A # U+0x0161 + 'guilsinglright' => '454', # C+0x9B # U+0x203A + 'oe' => '980', # C+0x9C # U+0x0153 + 'zcaron' => '525', # C+0x9E # U+0x017E + 'Ydieresis' => '615', # C+0x9F # U+0x0178 + 'exclamdown' => '393', # C+0xA1 # U+0x00A1 + 'cent' => '635', # C+0xA2 # U+0x00A2 + 'sterling' => '635', # C+0xA3 # U+0x00A3 + 'currency' => '635', # C+0xA4 # U+0x00A4 + 'yen' => '635', # C+0xA5 # U+0x00A5 + 'brokenbar' => '454', # C+0xA6 # U+0x00A6 + 'section' => '635', # C+0xA7 # U+0x00A7 + 'dieresis' => '635', # C+0xA8 # U+0x00A8 + 'copyright' => '1000', # C+0xA9 # U+0x00A9 + 'ordfeminine' => '545', # C+0xAA # U+0x00AA + 'guillemotleft' => '644', # C+0xAB # U+0x00AB + 'logicalnot' => '818', # C+0xAC # U+0x00AC + 'registered' => '1000', # C+0xAE # U+0x00AE + 'macron' => '635', # C+0xAF # U+0x00AF + 'degree' => '541', # C+0xB0 # U+0x00B0 + 'plusminus' => '818', # C+0xB1 # U+0x00B1 + 'twosuperior' => '541', # C+0xB2 # U+0x00B2 + 'threesuperior' => '541', # C+0xB3 # U+0x00B3 + 'acute' => '635', # C+0xB4 # U+0x00B4 + 'mu' => '638', # C+0xB5 # U+0x00B5 + 'paragraph' => '635', # C+0xB6 # U+0x00B6 + 'periodcentered' => '363', # C+0xB7 # U+0x00B7 + 'cedilla' => '635', # C+0xB8 # U+0x00B8 + 'onesuperior' => '541', # C+0xB9 # U+0x00B9 + 'ordmasculine' => '545', # C+0xBA # U+0x00BA + 'guillemotright' => '644', # C+0xBB # U+0x00BB + 'onequarter' => '1000', # C+0xBC # U+0x00BC + 'onehalf' => '1000', # C+0xBD # U+0x00BD + 'threequarters' => '1000', # C+0xBE # U+0x00BE + 'questiondown' => '545', # C+0xBF # U+0x00BF + 'Agrave' => '682', # C+0xC0 # U+0x00C0 + 'Aacute' => '682', # C+0xC1 # U+0x00C1 + 'Acircumflex' => '682', # C+0xC2 # U+0x00C2 + 'Atilde' => '682', # C+0xC3 # U+0x00C3 + 'Adieresis' => '682', # C+0xC4 # U+0x00C4 + 'Aring' => '682', # C+0xC5 # U+0x00C5 + 'AE' => '989', # C+0xC6 # U+0x00C6 + 'Ccedilla' => '698', # C+0xC7 # U+0x00C7 + 'Egrave' => '632', # C+0xC8 # U+0x00C8 + 'Eacute' => '632', # C+0xC9 # U+0x00C9 + 'Ecircumflex' => '632', # C+0xCA # U+0x00CA + 'Edieresis' => '632', # C+0xCB # U+0x00CB + 'Igrave' => '420', # C+0xCC # U+0x00CC + 'Iacute' => '420', # C+0xCD # U+0x00CD + 'Icircumflex' => '420', # C+0xCE # U+0x00CE + 'Idieresis' => '420', # C+0xCF # U+0x00CF + 'Eth' => '765', # C+0xD0 # U+0x00D0 + 'Ntilde' => '748', # C+0xD1 # U+0x00D1 + 'Ograve' => '787', # C+0xD2 # U+0x00D2 + 'Oacute' => '787', # C+0xD3 # U+0x00D3 + 'Ocircumflex' => '787', # C+0xD4 # U+0x00D4 + 'Otilde' => '787', # C+0xD5 # U+0x00D5 + 'Odieresis' => '787', # C+0xD6 # U+0x00D6 + 'multiply' => '818', # C+0xD7 # U+0x00D7 + 'Oslash' => '787', # C+0xD8 # U+0x00D8 + 'Ugrave' => '731', # C+0xD9 # U+0x00D9 + 'Uacute' => '731', # C+0xDA # U+0x00DA + 'Ucircumflex' => '731', # C+0xDB # U+0x00DB + 'Udieresis' => '731', # C+0xDC # U+0x00DC + 'Yacute' => '615', # C+0xDD # U+0x00DD + 'Thorn' => '605', # C+0xDE # U+0x00DE + 'germandbls' => '620', # C+0xDF # U+0x00DF + 'agrave' => '600', # C+0xE0 # U+0x00E0 + 'aacute' => '600', # C+0xE1 # U+0x00E1 + 'acircumflex' => '600', # C+0xE2 # U+0x00E2 + 'atilde' => '600', # C+0xE3 # U+0x00E3 + 'adieresis' => '600', # C+0xE4 # U+0x00E4 + 'aring' => '600', # C+0xE5 # U+0x00E5 + 'ae' => '954', # C+0xE6 # U+0x00E6 + 'ccedilla' => '520', # C+0xE7 # U+0x00E7 + 'egrave' => '595', # C+0xE8 # U+0x00E8 + 'eacute' => '595', # C+0xE9 # U+0x00E9 + 'ecircumflex' => '595', # C+0xEA # U+0x00EA + 'edieresis' => '595', # C+0xEB # U+0x00EB + 'igrave' => '274', # C+0xEC # U+0x00EC + 'iacute' => '274', # C+0xED # U+0x00ED + 'icircumflex' => '274', # C+0xEE # U+0x00EE + 'idieresis' => '274', # C+0xEF # U+0x00EF + 'eth' => '611', # C+0xF0 # U+0x00F0 + 'ntilde' => '632', # C+0xF1 # U+0x00F1 + 'ograve' => '606', # C+0xF2 # U+0x00F2 + 'oacute' => '606', # C+0xF3 # U+0x00F3 + 'ocircumflex' => '606', # C+0xF4 # U+0x00F4 + 'otilde' => '606', # C+0xF5 # U+0x00F5 + 'odieresis' => '606', # C+0xF6 # U+0x00F6 + 'divide' => '818', # C+0xF7 # U+0x00F7 + 'oslash' => '606', # C+0xF8 # U+0x00F8 + 'ugrave' => '632', # C+0xF9 # U+0x00F9 + 'uacute' => '632', # C+0xFA # U+0x00FA + 'ucircumflex' => '632', # C+0xFB # U+0x00FB + 'udieresis' => '632', # C+0xFC # U+0x00FC + 'yacute' => '590', # C+0xFD # U+0x00FD + 'thorn' => '623', # C+0xFE # U+0x00FE + 'ydieresis' => '590', # C+0xFF # U+0x00FF + 'middot' => '363', # U+0x00B7 + 'Amacron' => '682', # U+0x0100 + 'amacron' => '600', # U+0x0101 + 'Abreve' => '682', # U+0x0102 + 'abreve' => '600', # U+0x0103 + 'Aogonek' => '682', # U+0x0104 + 'aogonek' => '600', # U+0x0105 + 'Cacute' => '698', # U+0x0106 + 'cacute' => '520', # U+0x0107 + 'Ccircumflex' => '698', # U+0x0108 + 'ccircumflex' => '520', # U+0x0109 + 'Cdot' => '698', # U+0x010A + 'cdot' => '520', # U+0x010B + 'Ccaron' => '698', # U+0x010C + 'ccaron' => '520', # U+0x010D + 'Dcaron' => '765', # U+0x010E + 'dcaron' => '647', # U+0x010F + 'Emacron' => '632', # U+0x0112 + 'emacron' => '595', # U+0x0113 + 'Ebreve' => '632', # U+0x0114 + 'ebreve' => '595', # U+0x0115 + 'Edot' => '632', # U+0x0116 + 'edot' => '595', # U+0x0117 + 'Eogonek' => '632', # U+0x0118 + 'eogonek' => '595', # U+0x0119 + 'Ecaron' => '632', # U+0x011A + 'ecaron' => '595', # U+0x011B + 'Gcircumflex' => '775', # U+0x011C + 'gcircumflex' => '621', # U+0x011D + 'Gbreve' => '775', # U+0x011E + 'gbreve' => '621', # U+0x011F + 'Gdot' => '775', # U+0x0120 + 'gdot' => '621', # U+0x0121 + 'Hcircumflex' => '751', # U+0x0124 + 'hcircumflex' => '632', # U+0x0125 + 'Hbar' => '751', # U+0x0126 + 'hbar' => '632', # U+0x0127 + 'Itilde' => '420', # U+0x0128 + 'itilde' => '274', # U+0x0129 + 'Imacron' => '420', # U+0x012A + 'imacron' => '274', # U+0x012B + 'Ibreve' => '420', # U+0x012C + 'ibreve' => '274', # U+0x012D + 'Iogonek' => '420', # U+0x012E + 'iogonek' => '274', # U+0x012F + 'Idot' => '420', # U+0x0130 + 'dotlessi' => '274', # U+0x0131 + 'IJ' => '870', # U+0x0132 + 'ij' => '613', # U+0x0133 + 'Jcircumflex' => '454', # U+0x0134 + 'jcircumflex' => '344', # U+0x0135 + 'kgreenlandic' => '586', # U+0x0138 + 'Lacute' => '556', # U+0x0139 + 'lacute' => '274', # U+0x013A + 'Lcaron' => '556', # U+0x013D + 'lcaron' => '295', # U+0x013E + 'Ldot' => '556', # U+0x013F + 'ldot' => '458', # U+0x0140 + 'Lslash' => '556', # U+0x0141 + 'lslash' => '274', # U+0x0142 + 'Nacute' => '748', # U+0x0143 + 'nacute' => '632', # U+0x0144 + 'Ncaron' => '748', # U+0x0147 + 'ncaron' => '632', # U+0x0148 + 'napostrophe' => '730', # U+0x0149 + 'Eng' => '748', # U+0x014A + 'eng' => '632', # U+0x014B + 'Omacron' => '787', # U+0x014C + 'omacron' => '606', # U+0x014D + 'Obreve' => '787', # U+0x014E + 'obreve' => '606', # U+0x014F + 'Racute' => '695', # U+0x0154 + 'racute' => '426', # U+0x0155 + 'Rcaron' => '695', # U+0x0158 + 'rcaron' => '426', # U+0x0159 + 'Sacute' => '683', # U+0x015A + 'sacute' => '520', # U+0x015B + 'Scircumflex' => '683', # U+0x015C + 'scircumflex' => '520', # U+0x015D + 'Scedilla' => '683', # U+0x015E + 'scedilla' => '520', # U+0x015F + 'Tcaron' => '616', # U+0x0164 + 'tcaron' => '394', # U+0x0165 + 'Tbar' => '616', # U+0x0166 + 'tbar' => '394', # U+0x0167 + 'Utilde' => '731', # U+0x0168 + 'utilde' => '632', # U+0x0169 + 'Umacron' => '731', # U+0x016A + 'umacron' => '632', # U+0x016B + 'Ubreve' => '731', # U+0x016C + 'ubreve' => '630', # U+0x016D + 'Uring' => '731', # U+0x016E + 'uring' => '632', # U+0x016F + 'Uogonek' => '731', # U+0x0172 + 'uogonek' => '632', # U+0x0173 + 'Wcircumflex' => '990', # U+0x0174 + 'wcircumflex' => '818', # U+0x0175 + 'Ycircumflex' => '615', # U+0x0176 + 'ycircumflex' => '590', # U+0x0177 + 'Zacute' => '685', # U+0x0179 + 'zacute' => '525', # U+0x017A + 'Zdot' => '685', # U+0x017B + 'zdot' => '525', # U+0x017C + 'longs' => '300', # U+0x017F + 'Ohorn' => '806', # U+0x01A0 + 'ohorn' => '606', # U+0x01A1 + 'Uhorn' => '756', # U+0x01AF + 'uhorn' => '659', # U+0x01B0 + 'Aringacute' => '682', # U+0x01FA + 'aringacute' => '600', # U+0x01FB + 'AEacute' => '989', # U+0x01FC + 'aeacute' => '954', # U+0x01FD + 'Oslashacute' => '787', # U+0x01FE + 'oslashacute' => '606', # U+0x01FF + 'caron' => '635', # U+0x02C7 + 'breve' => '635', # U+0x02D8 + 'dotaccent' => '635', # U+0x02D9 + 'ring' => '635', # U+0x02DA + 'ogonek' => '635', # U+0x02DB + 'hungarumlaut' => '635', # U+0x02DD + 'gravecomb' => '0', # U+0x0300 + 'acutecomb' => '0', # U+0x0301 + 'tildecomb' => '0', # U+0x0303 + 'hookabovecomb' => '0', # U+0x0309 + 'dotbelowcomb' => '0', # U+0x0323 + 'tonos' => '635', # U+0x0384 + 'dieresistonos' => '635', # U+0x0385 + 'Alphatonos' => '683', # U+0x0386 + 'anoteleia' => '454', # U+0x0387 + 'Epsilontonos' => '750', # U+0x0388 + 'Etatonos' => '870', # U+0x0389 + 'Iotatonos' => '539', # U+0x038A + 'Omicrontonos' => '880', # U+0x038C + 'Upsilontonos' => '753', # U+0x038E + 'Omegatonos' => '907', # U+0x038F + 'iotadieresistonos' => '274', # U+0x0390 + 'Alpha' => '682', # U+0x0391 + 'Beta' => '685', # U+0x0392 + 'Gamma' => '566', # U+0x0393 + 'Delta' => '726', # U+0x0394 + 'Epsilon' => '632', # U+0x0395 + 'Zeta' => '685', # U+0x0396 + 'Eta' => '751', # U+0x0397 + 'Theta' => '787', # U+0x0398 + 'Iota' => '420', # U+0x0399 + 'Kappa' => '692', # U+0x039A + 'Lambda' => '685', # U+0x039B + 'Mu' => '842', # U+0x039C + 'Nu' => '748', # U+0x039D + 'Xi' => '648', # U+0x039E + 'Omicron' => '787', # U+0x039F + 'Pi' => '751', # U+0x03A0 + 'Rho' => '603', # U+0x03A1 + 'Sigma' => '672', # U+0x03A3 + 'Tau' => '616', # U+0x03A4 + 'Upsilon' => '615', # U+0x03A5 + 'Phi' => '814', # U+0x03A6 + 'Chi' => '685', # U+0x03A7 + 'Psi' => '870', # U+0x03A8 + 'Omega' => '818', # U+0x03A9 + 'Iotadieresis' => '420', # U+0x03AA + 'Upsilondieresis' => '615', # U+0x03AB + 'alphatonos' => '623', # U+0x03AC + 'epsilontonos' => '512', # U+0x03AD + 'etatonos' => '632', # U+0x03AE + 'iotatonos' => '274', # U+0x03AF + 'upsilondieresistonos' => '630', # U+0x03B0 + 'alpha' => '623', # U+0x03B1 + 'beta' => '620', # U+0x03B2 + 'gamma' => '590', # U+0x03B3 + 'delta' => '607', # U+0x03B4 + 'epsilon' => '512', # U+0x03B5 + 'zeta' => '457', # U+0x03B6 + 'eta' => '632', # U+0x03B7 + 'theta' => '624', # U+0x03B8 + 'iota' => '274', # U+0x03B9 + 'kappa' => '591', # U+0x03BA + 'lambda' => '591', # U+0x03BB + 'nu' => '590', # U+0x03BD + 'xi' => '502', # U+0x03BE + 'omicron' => '606', # U+0x03BF + 'pi' => '637', # U+0x03C0 + 'rho' => '624', # U+0x03C1 + 'sigma1' => '507', # U+0x03C2 + 'sigma' => '630', # U+0x03C3 + 'tau' => '496', # U+0x03C4 + 'upsilon' => '630', # U+0x03C5 + 'phi' => '790', # U+0x03C6 + 'chi' => '589', # U+0x03C7 + 'psi' => '821', # U+0x03C8 + 'omega' => '813', # U+0x03C9 + 'iotadieresis' => '274', # U+0x03CA + 'upsilondieresis' => '630', # U+0x03CB + 'omicrontonos' => '606', # U+0x03CC + 'upsilontonos' => '630', # U+0x03CD + 'omegatonos' => '813', # U+0x03CE + 'afii10023' => '632', # U+0x0401 + 'afii10051' => '792', # U+0x0402 + 'afii10052' => '566', # U+0x0403 + 'afii10053' => '700', # U+0x0404 + 'afii10054' => '683', # U+0x0405 + 'afii10055' => '420', # U+0x0406 + 'afii10056' => '420', # U+0x0407 + 'afii10057' => '454', # U+0x0408 + 'afii10058' => '1118', # U+0x0409 + 'afii10059' => '1103', # U+0x040A + 'afii10060' => '817', # U+0x040B + 'afii10061' => '692', # U+0x040C + 'afii10062' => '615', # U+0x040E + 'afii10145' => '751', # U+0x040F + 'afii10017' => '682', # U+0x0410 + 'afii10018' => '685', # U+0x0411 + 'afii10019' => '685', # U+0x0412 + 'afii10020' => '566', # U+0x0413 + 'afii10021' => '745', # U+0x0414 + 'afii10022' => '632', # U+0x0415 + 'afii10024' => '973', # U+0x0416 + 'afii10025' => '615', # U+0x0417 + 'afii10026' => '750', # U+0x0418 + 'afii10027' => '750', # U+0x0419 + 'afii10028' => '692', # U+0x041A + 'afii10029' => '734', # U+0x041B + 'afii10030' => '842', # U+0x041C + 'afii10031' => '751', # U+0x041D + 'afii10032' => '787', # U+0x041E + 'afii10033' => '751', # U+0x041F + 'afii10034' => '603', # U+0x0420 + 'afii10035' => '698', # U+0x0421 + 'afii10036' => '616', # U+0x0422 + 'afii10037' => '615', # U+0x0423 + 'afii10038' => '814', # U+0x0424 + 'afii10039' => '685', # U+0x0425 + 'afii10040' => '761', # U+0x0426 + 'afii10041' => '711', # U+0x0427 + 'afii10042' => '1030', # U+0x0428 + 'afii10043' => '1044', # U+0x0429 + 'afii10044' => '788', # U+0x042A + 'afii10045' => '920', # U+0x042B + 'afii10046' => '680', # U+0x042C + 'afii10047' => '701', # U+0x042D + 'afii10048' => '1034', # U+0x042E + 'afii10049' => '706', # U+0x042F + 'afii10065' => '600', # U+0x0430 + 'afii10066' => '614', # U+0x0431 + 'afii10067' => '594', # U+0x0432 + 'afii10068' => '471', # U+0x0433 + 'afii10069' => '621', # U+0x0434 + 'afii10070' => '595', # U+0x0435 + 'afii10072' => '797', # U+0x0436 + 'afii10073' => '524', # U+0x0437 + 'afii10074' => '640', # U+0x0438 + 'afii10075' => '640', # U+0x0439 + 'afii10076' => '591', # U+0x043A + 'afii10077' => '620', # U+0x043B + 'afii10078' => '696', # U+0x043C + 'afii10079' => '637', # U+0x043D + 'afii10080' => '606', # U+0x043E + 'afii10081' => '637', # U+0x043F + 'afii10082' => '623', # U+0x0440 + 'afii10083' => '530', # U+0x0441 + 'afii10084' => '496', # U+0x0442 + 'afii10085' => '590', # U+0x0443 + 'afii10086' => '840', # U+0x0444 + 'afii10087' => '591', # U+0x0445 + 'afii10088' => '644', # U+0x0446 + 'afii10089' => '605', # U+0x0447 + 'afii10090' => '875', # U+0x0448 + 'afii10091' => '887', # U+0x0449 + 'afii10092' => '640', # U+0x044A + 'afii10093' => '794', # U+0x044B + 'afii10094' => '570', # U+0x044C + 'afii10095' => '546', # U+0x044D + 'afii10096' => '838', # U+0x044E + 'afii10097' => '599', # U+0x044F + 'afii10071' => '595', # U+0x0451 + 'afii10099' => '632', # U+0x0452 + 'afii10100' => '471', # U+0x0453 + 'afii10101' => '546', # U+0x0454 + 'afii10102' => '520', # U+0x0455 + 'afii10103' => '274', # U+0x0456 + 'afii10104' => '274', # U+0x0457 + 'afii10105' => '344', # U+0x0458 + 'afii10106' => '914', # U+0x0459 + 'afii10107' => '914', # U+0x045A + 'afii10108' => '632', # U+0x045B + 'afii10109' => '591', # U+0x045C + 'afii10110' => '590', # U+0x045E + 'afii10193' => '637', # U+0x045F + 'afii10050' => '566', # U+0x0490 + 'afii10098' => '471', # U+0x0491 + 'Wgrave' => '990', # U+0x1E80 + 'wgrave' => '818', # U+0x1E81 + 'Wacute' => '990', # U+0x1E82 + 'wacute' => '818', # U+0x1E83 + 'Wdieresis' => '990', # U+0x1E84 + 'wdieresis' => '818', # U+0x1E85 + 'Ygrave' => '615', # U+0x1EF2 + 'ygrave' => '590', # U+0x1EF3 + 'afii00208' => '1000', # U+0x2015 + 'underscoredbl' => '635', # U+0x2017 + 'quotereversed' => '268', # U+0x201B + 'minute' => '361', # U+0x2032 + 'second' => '557', # U+0x2033 + 'exclamdbl' => '624', # U+0x203C + 'fraction' => '361', # U+0x2044 + 'foursuperior' => '541', # U+0x2074 + 'fivesuperior' => '541', # U+0x2075 + 'sevensuperior' => '541', # U+0x2077 + 'eightsuperior' => '541', # U+0x2078 + 'nsuperior' => '545', # U+0x207F + 'franc' => '635', # U+0x20A3 + 'peseta' => '1163', # U+0x20A7 + 'dong' => '623', # U+0x20AB + 'afii61248' => '1076', # U+0x2105 + 'afii61289' => '323', # U+0x2113 + 'afii61352' => '1171', # U+0x2116 + 'estimated' => '717', # U+0x212E + 'oneeighth' => '1000', # U+0x215B + 'threeeighths' => '1000', # U+0x215C + 'fiveeighths' => '1000', # U+0x215D + 'seveneighths' => '1000', # U+0x215E + 'partialdiff' => '635', # U+0x2202 + 'product' => '818', # U+0x220F + 'summation' => '727', # U+0x2211 + 'minus' => '818', # U+0x2212 + 'radical' => '818', # U+0x221A + 'infinity' => '1000', # U+0x221E + 'integral' => '635', # U+0x222B + 'approxequal' => '818', # U+0x2248 + 'notequal' => '818', # U+0x2260 + 'lessequal' => '818', # U+0x2264 + 'greaterequal' => '818', # U+0x2265 + 'H22073' => '604', # U+0x25A1 + 'H18543' => '354', # U+0x25AA + 'H18551' => '354', # U+0x25AB + 'lozenge' => '818', # U+0x25CA + 'H18533' => '604', # U+0x25CF + 'openbullet' => '354', # U+0x25E6 + 'commaaccent' => '363', # U+0xF6C3 + 'radicalex' => '635', # U+0xF8E5 + 'fi' => '625', # U+0xFB01 + 'fl' => '625', # U+0xFB02 + }, # HORIZ. WIDTH TABLE +} }; + +1; diff --git a/lib/PDF/API2/Resource/Font/CoreFont/webdings.pm b/lib/PDF/API2/Resource/Font/CoreFont/webdings.pm new file mode 100644 index 0000000..d3e115e --- /dev/null +++ b/lib/PDF/API2/Resource/Font/CoreFont/webdings.pm @@ -0,0 +1,770 @@ +#line 1 "PDF/API2/Resource/Font/CoreFont/webdings.pm" +#line 1 "PDF/API2/Resource/Font/CoreFont/webdings.pm" +package PDF::API2::Resource::Font::CoreFont::webdings; + +use strict; +use warnings; + +our $VERSION = '2.033'; # VERSION + +sub data { return { + 'fontname' => 'Webdings', + 'type' => 'TrueType', + 'apiname' => 'Web', + 'ascender' => '799', + 'capheight' => '604', + 'descender' => '-200', + 'isfixedpitch' => '0', + 'issymbol' => '1', + 'italicangle' => '0', + 'underlineposition' => '-273', + 'underlinethickness' => '100', + 'xheight' => '604', + 'firstchar' => '32', + 'lastchar' => '255', + 'flags' => '4', + 'char' => [ # DEF. ENCODING GLYPH TABLE + '.notdef', # C+0x00 # U+0x0000 + '.notdef', # C+0x01 # U+0x0000 + '.notdef', # C+0x02 # U+0x0000 + '.notdef', # C+0x03 # U+0x0000 + '.notdef', # C+0x04 # U+0x0000 + '.notdef', # C+0x05 # U+0x0000 + '.notdef', # C+0x06 # U+0x0000 + '.notdef', # C+0x07 # U+0x0000 + '.notdef', # C+0x08 # U+0x0000 + '.notdef', # C+0x09 # U+0x0000 + '.notdef', # C+0x0A # U+0x0000 + '.notdef', # C+0x0B # U+0x0000 + '.notdef', # C+0x0C # U+0x0000 + '.notdef', # C+0x0D # U+0x0000 + '.notdef', # C+0x0E # U+0x0000 + '.notdef', # C+0x0F # U+0x0000 + '.notdef', # C+0x10 # U+0x0000 + '.notdef', # C+0x11 # U+0x0000 + '.notdef', # C+0x12 # U+0x0000 + '.notdef', # C+0x13 # U+0x0000 + '.notdef', # C+0x14 # U+0x0000 + '.notdef', # C+0x15 # U+0x0000 + '.notdef', # C+0x16 # U+0x0000 + '.notdef', # C+0x17 # U+0x0000 + '.notdef', # C+0x18 # U+0x0000 + '.notdef', # C+0x19 # U+0x0000 + '.notdef', # C+0x1A # U+0x0000 + '.notdef', # C+0x1B # U+0x0000 + '.notdef', # C+0x1C # U+0x0000 + '.notdef', # C+0x1D # U+0x0000 + '.notdef', # C+0x1E # U+0x0000 + '.notdef', # C+0x1F # U+0x0000 + 'space', # C+0x20 # U+0xF020 + 'spider', # C+0x21 # U+0xF021 + 'web', # C+0x22 # U+0xF022 + 'nopiracy', # C+0x23 # U+0xF023 + 'cool', # C+0x24 # U+0xF024 + 'trophy', # C+0x25 # U+0xF025 + 'award', # C+0x26 # U+0xF026 + 'links', # C+0x27 # U+0xF027 + 'talkleft', # C+0x28 # U+0xF028 + 'talkright', # C+0x29 # U+0xF029 + 'new', # C+0x2A # U+0xF02A + 'updated', # C+0x2B # U+0xF02B + 'hot', # C+0x2C # U+0xF02C + 'ribbon', # C+0x2D # U+0xF02D + 'checkerboard', # C+0x2E # U+0xF02E + 'slash', # C+0x2F # U+0xF02F + 'UIminimize', # C+0x30 # U+0xF030 + 'UImaximize', # C+0x31 # U+0xF031 + 'UItile', # C+0x32 # U+0xF032 + 'UIback', # C+0x33 # U+0xF033 + 'UIforward', # C+0x34 # U+0xF034 + 'UIup', # C+0x35 # U+0xF035 + 'UIdown', # C+0x36 # U+0xF036 + 'UIreverse', # C+0x37 # U+0xF037 + 'UIfastforward', # C+0x38 # U+0xF038 + 'UIbegin', # C+0x39 # U+0xF039 + 'UIend', # C+0x3A # U+0xF03A + 'UIpause', # C+0x3B # U+0xF03B + 'UIstop', # C+0x3C # U+0xF03C + 'UIrecord', # C+0x3D # U+0xF03D + 'fontsize', # C+0x3E # U+0xF03E + 'vote', # C+0x3F # U+0xF03F + 'tools', # C+0x40 # U+0xF040 + 'underconstruction', # C+0x41 # U+0xF041 + 'town', # C+0x42 # U+0xF042 + 'city', # C+0x43 # U+0xF043 + 'derelictsite', # C+0x44 # U+0xF044 + 'desert', # C+0x45 # U+0xF045 + 'factory', # C+0x46 # U+0xF046 + 'publicbuilding', # C+0x47 # U+0xF047 + 'home', # C+0x48 # U+0xF048 + 'beach', # C+0x49 # U+0xF049 + 'island', # C+0x4A # U+0xF04A + 'motorway', # C+0x4B # U+0xF04B + 'search', # C+0x4C # U+0xF04C + 'mountain', # C+0x4D # U+0xF04D + 'sight', # C+0x4E # U+0xF04E + 'hearing', # C+0x4F # U+0xF04F + 'park', # C+0x50 # U+0xF050 + 'camping', # C+0x51 # U+0xF051 + 'railroad', # C+0x52 # U+0xF052 + 'stadium', # C+0x53 # U+0xF053 + 'ship', # C+0x54 # U+0xF054 + 'soundon', # C+0x55 # U+0xF055 + 'soundoff', # C+0x56 # U+0xF056 + 'soundleft', # C+0x57 # U+0xF057 + 'soundright', # C+0x58 # U+0xF058 + 'favorite', # C+0x59 # U+0xF059 + 'occasion', # C+0x5A # U+0xF05A + 'thoughtleft', # C+0x5B # U+0xF05B + 'backslash', # C+0x5C # U+0xF05C + 'thoughtright', # C+0x5D # U+0xF05D + 'chat', # C+0x5E # U+0xF05E + 'conference', # C+0x5F # U+0xF05F + 'loop', # C+0x60 # U+0xF060 + 'UIcheck', # C+0x61 # U+0xF061 + 'bicycle', # C+0x62 # U+0xF062 + 'boxopen', # C+0x63 # U+0xF063 + 'sheild', # C+0x64 # U+0xF064 + 'package', # C+0x65 # U+0xF065 + 'fire', # C+0x66 # U+0xF066 + 'boxsolid', # C+0x67 # U+0xF067 + 'medical', # C+0x68 # U+0xF068 + 'information', # C+0x69 # U+0xF069 + 'planesmall', # C+0x6A # U+0xF06A + 'satellite', # C+0x6B # U+0xF06B + 'navigate', # C+0x6C # U+0xF06C + 'jump', # C+0x6D # U+0xF06D + 'circlesolid', # C+0x6E # U+0xF06E + 'boat', # C+0x6F # U+0xF06F + 'police', # C+0x70 # U+0xF070 + 'UIrefresh', # C+0x71 # U+0xF071 + 'UIclose', # C+0x72 # U+0xF072 + 'UIhelp', # C+0x73 # U+0xF073 + 'train', # C+0x74 # U+0xF074 + 'metro', # C+0x75 # U+0xF075 + 'bus', # C+0x76 # U+0xF076 + 'flag', # C+0x77 # U+0xF077 + 'not', # C+0x78 # U+0xF078 + 'noentry', # C+0x79 # U+0xF079 + 'nosmoking', # C+0x7A # U+0xF07A + 'shoutleft', # C+0x7B # U+0xF07B + 'bar', # C+0x7C # U+0xF07C + 'shoutright', # C+0x7D # U+0xF07D + 'lightningbolt', # C+0x7E # U+0xF07E + '.notdef', # C+0x7F # U+0x0000 + 'man', # C+0x80 # U+0xF080 + 'woman', # C+0x81 # U+0xF081 + 'boy', # C+0x82 # U+0xF082 + 'girl', # C+0x83 # U+0xF083 + 'baby', # C+0x84 # U+0xF084 + 'scifi', # C+0x85 # U+0xF085 + 'health', # C+0x86 # U+0xF086 + 'skier', # C+0x87 # U+0xF087 + 'hobby', # C+0x88 # U+0xF088 + 'golfer', # C+0x89 # U+0xF089 + 'pool', # C+0x8A # U+0xF08A + 'surf', # C+0x8B # U+0xF08B + 'motorcycle', # C+0x8C # U+0xF08C + 'racecar', # C+0x8D # U+0xF08D + 'auto', # C+0x8E # U+0xF08E + 'finance', # C+0x8F # U+0xF08F + 'commodities', # C+0x90 # U+0xF090 + 'money', # C+0x91 # U+0xF091 + 'price', # C+0x92 # U+0xF092 + 'creditcard', # C+0x93 # U+0xF093 + 'ratingfamily', # C+0x94 # U+0xF094 + 'ratingviolence', # C+0x95 # U+0xF095 + 'ratingsex', # C+0x96 # U+0xF096 + 'ratinglanguage', # C+0x97 # U+0xF097 + 'ratingquality', # C+0x98 # U+0xF098 + 'email', # C+0x99 # U+0xF099 + 'send', # C+0x9A # U+0xF09A + 'mail', # C+0x9B # U+0xF09B + 'write', # C+0x9C # U+0xF09C + 'textdoc', # C+0x9D # U+0xF09D + 'textgraphicdoc', # C+0x9E # U+0xF09E + 'graphicdoc', # C+0x9F # U+0xF09F + 'investigate', # C+0xA0 # U+0xF0A0 + 'clock', # C+0xA1 # U+0xF0A1 + 'frames', # C+0xA2 # U+0xF0A2 + 'noframes', # C+0xA3 # U+0xF0A3 + 'clipboard', # C+0xA4 # U+0xF0A4 + 'note', # C+0xA5 # U+0xF0A5 + 'calender', # C+0xA6 # U+0xF0A6 + 'book', # C+0xA7 # U+0xF0A7 + 'reference', # C+0xA8 # U+0xF0A8 + 'news', # C+0xA9 # U+0xF0A9 + 'classified', # C+0xAA # U+0xF0AA + 'archive', # C+0xAB # U+0xF0AB + 'index', # C+0xAC # U+0xF0AC + 'art', # C+0xAD # U+0xF0AD + 'theatre', # C+0xAE # U+0xF0AE + 'music', # C+0xAF # U+0xF0AF + 'MIDI', # C+0xB0 # U+0xF0B0 + 'microphone', # C+0xB1 # U+0xF0B1 + 'headphones', # C+0xB2 # U+0xF0B2 + 'CDROM', # C+0xB3 # U+0xF0B3 + 'filmclip', # C+0xB4 # U+0xF0B4 + 'pointofinterest', # C+0xB5 # U+0xF0B5 + 'ticket', # C+0xB6 # U+0xF0B6 + 'film', # C+0xB7 # U+0xF0B7 + 'movies', # C+0xB8 # U+0xF0B8 + 'video', # C+0xB9 # U+0xF0B9 + 'stereo', # C+0xBA # U+0xF0BA + 'radio', # C+0xBB # U+0xF0BB + 'levelcontrol', # C+0xBC # U+0xF0BC + 'audiocontrol', # C+0xBD # U+0xF0BD + 'television', # C+0xBE # U+0xF0BE + 'computers1', # C+0xBF # U+0xF0BF + 'computers2', # C+0xC0 # U+0xF0C0 + 'computers3', # C+0xC1 # U+0xF0C1 + 'computers4', # C+0xC2 # U+0xF0C2 + 'joystick', # C+0xC3 # U+0xF0C3 + 'gamepad', # C+0xC4 # U+0xF0C4 + 'phone', # C+0xC5 # U+0xF0C5 + 'fax', # C+0xC6 # U+0xF0C6 + 'pager', # C+0xC7 # U+0xF0C7 + 'cellularphone', # C+0xC8 # U+0xF0C8 + 'modem', # C+0xC9 # U+0xF0C9 + 'printer', # C+0xCA # U+0xF0CA + 'calculator', # C+0xCB # U+0xF0CB + 'folder', # C+0xCC # U+0xF0CC + 'disk', # C+0xCD # U+0xF0CD + 'compression', # C+0xCE # U+0xF0CE + 'locked', # C+0xCF # U+0xF0CF + 'unlocked', # C+0xD0 # U+0xF0D0 + 'encryption', # C+0xD1 # U+0xF0D1 + 'inbox', # C+0xD2 # U+0xF0D2 + 'outbox', # C+0xD3 # U+0xF0D3 + 'ovalshape', # C+0xD4 # U+0xF0D4 + 'sunny', # C+0xD5 # U+0xF0D5 + 'mostlysunny', # C+0xD6 # U+0xF0D6 + 'mostlycloudy', # C+0xD7 # U+0xF0D7 + 'showers', # C+0xD8 # U+0xF0D8 + 'cloudy', # C+0xD9 # U+0xF0D9 + 'snow', # C+0xDA # U+0xF0DA + 'rain', # C+0xDB # U+0xF0DB + 'lightning', # C+0xDC # U+0xF0DC + 'twister', # C+0xDD # U+0xF0DD + 'wind', # C+0xDE # U+0xF0DE + 'fog', # C+0xDF # U+0xF0DF + 'moon', # C+0xE0 # U+0xF0E0 + 'temperature', # C+0xE1 # U+0xF0E1 + 'lifestyles', # C+0xE2 # U+0xF0E2 + 'guestrooms', # C+0xE3 # U+0xF0E3 + 'dining', # C+0xE4 # U+0xF0E4 + 'lounge', # C+0xE5 # U+0xF0E5 + 'services', # C+0xE6 # U+0xF0E6 + 'shopping', # C+0xE7 # U+0xF0E7 + 'parking', # C+0xE8 # U+0xF0E8 + 'handycap', # C+0xE9 # U+0xF0E9 + 'caution', # C+0xEA # U+0xF0EA + 'marker', # C+0xEB # U+0xF0EB + 'education', # C+0xEC # U+0xF0EC + 'raysabove', # C+0xED # U+0xF0ED + 'raysbelow', # C+0xEE # U+0xF0EE + 'raysleft', # C+0xEF # U+0xF0EF + 'raysright', # C+0xF0 # U+0xF0F0 + 'airplane', # C+0xF1 # U+0xF0F1 + 'animal1', # C+0xF2 # U+0xF0F2 + 'bird', # C+0xF3 # U+0xF0F3 + 'fish', # C+0xF4 # U+0xF0F4 + 'dog', # C+0xF5 # U+0xF0F5 + 'cat', # C+0xF6 # U+0xF0F6 + 'rocketleft', # C+0xF7 # U+0xF0F7 + 'rocketright', # C+0xF8 # U+0xF0F8 + 'rocketup', # C+0xF9 # U+0xF0F9 + 'rocketdown', # C+0xFA # U+0xF0FA + 'worldmap', # C+0xFB # U+0xF0FB + 'globe1', # C+0xFC # U+0xF0FC + 'globe2', # C+0xFD # U+0xF0FD + 'globe3', # C+0xFE # U+0xF0FE + 'peace', # C+0xFF # U+0xF0FF + ], # DEF. ENCODING GLYPH TABLE + 'fontbbox' => [ -1, -200, 4000, 799 ], + 'wx' => { # HORIZ. WIDTH TABLE + 'space' => '500', # C+0x20 # U+0xF020 + 'spider' => '1000', # C+0x21 # U+0xF021 + 'web' => '1000', # C+0x22 # U+0xF022 + 'nopiracy' => '1000', # C+0x23 # U+0xF023 + 'cool' => '1000', # C+0x24 # U+0xF024 + 'trophy' => '990', # C+0x25 # U+0xF025 + 'award' => '1000', # C+0x26 # U+0xF026 + 'links' => '1000', # C+0x27 # U+0xF027 + 'talkleft' => '1000', # C+0x28 # U+0xF028 + 'talkright' => '1000', # C+0x29 # U+0xF029 + 'new' => '1000', # C+0x2A # U+0xF02A + 'updated' => '1000', # C+0x2B # U+0xF02B + 'hot' => '1000', # C+0x2C # U+0xF02C + 'ribbon' => '1000', # C+0x2D # U+0xF02D + 'checkerboard' => '1000', # C+0x2E # U+0xF02E + 'slash' => '1000', # C+0x2F # U+0xF02F + 'UIminimize' => '1000', # C+0x30 # U+0xF030 + 'UImaximize' => '1000', # C+0x31 # U+0xF031 + 'UItile' => '1000', # C+0x32 # U+0xF032 + 'UIback' => '1000', # C+0x33 # U+0xF033 + 'UIforward' => '1000', # C+0x34 # U+0xF034 + 'UIup' => '1000', # C+0x35 # U+0xF035 + 'UIdown' => '1000', # C+0x36 # U+0xF036 + 'UIreverse' => '1000', # C+0x37 # U+0xF037 + 'UIfastforward' => '1000', # C+0x38 # U+0xF038 + 'UIbegin' => '1000', # C+0x39 # U+0xF039 + 'UIend' => '1000', # C+0x3A # U+0xF03A + 'UIpause' => '1000', # C+0x3B # U+0xF03B + 'UIstop' => '1000', # C+0x3C # U+0xF03C + 'UIrecord' => '1000', # C+0x3D # U+0xF03D + 'fontsize' => '1000', # C+0x3E # U+0xF03E + 'vote' => '1000', # C+0x3F # U+0xF03F + 'tools' => '1000', # C+0x40 # U+0xF040 + 'underconstruction' => '1000', # C+0x41 # U+0xF041 + 'town' => '1000', # C+0x42 # U+0xF042 + 'city' => '1000', # C+0x43 # U+0xF043 + 'derelictsite' => '1000', # C+0x44 # U+0xF044 + 'desert' => '1000', # C+0x45 # U+0xF045 + 'factory' => '1000', # C+0x46 # U+0xF046 + 'publicbuilding' => '1000', # C+0x47 # U+0xF047 + 'home' => '1000', # C+0x48 # U+0xF048 + 'beach' => '1000', # C+0x49 # U+0xF049 + 'island' => '1000', # C+0x4A # U+0xF04A + 'motorway' => '1000', # C+0x4B # U+0xF04B + 'search' => '1000', # C+0x4C # U+0xF04C + 'mountain' => '1000', # C+0x4D # U+0xF04D + 'sight' => '1000', # C+0x4E # U+0xF04E + 'hearing' => '1000', # C+0x4F # U+0xF04F + 'park' => '1000', # C+0x50 # U+0xF050 + 'camping' => '1000', # C+0x51 # U+0xF051 + 'railroad' => '1000', # C+0x52 # U+0xF052 + 'stadium' => '1000', # C+0x53 # U+0xF053 + 'ship' => '1000', # C+0x54 # U+0xF054 + 'soundon' => '1000', # C+0x55 # U+0xF055 + 'soundoff' => '1000', # C+0x56 # U+0xF056 + 'soundleft' => '537', # C+0x57 # U+0xF057 + 'soundright' => '537', # C+0x58 # U+0xF058 + 'favorite' => '1000', # C+0x59 # U+0xF059 + 'occasion' => '1000', # C+0x5A # U+0xF05A + 'thoughtleft' => '1000', # C+0x5B # U+0xF05B + 'backslash' => '1000', # C+0x5C # U+0xF05C + 'thoughtright' => '1000', # C+0x5D # U+0xF05D + 'chat' => '1000', # C+0x5E # U+0xF05E + 'conference' => '1000', # C+0x5F # U+0xF05F + 'loop' => '1000', # C+0x60 # U+0xF060 + 'UIcheck' => '1000', # C+0x61 # U+0xF061 + 'bicycle' => '1000', # C+0x62 # U+0xF062 + 'boxopen' => '1000', # C+0x63 # U+0xF063 + 'sheild' => '1000', # C+0x64 # U+0xF064 + 'package' => '1000', # C+0x65 # U+0xF065 + 'fire' => '1000', # C+0x66 # U+0xF066 + 'boxsolid' => '1000', # C+0x67 # U+0xF067 + 'medical' => '1000', # C+0x68 # U+0xF068 + 'information' => '1000', # C+0x69 # U+0xF069 + 'planesmall' => '1000', # C+0x6A # U+0xF06A + 'satellite' => '1000', # C+0x6B # U+0xF06B + 'navigate' => '1000', # C+0x6C # U+0xF06C + 'jump' => '558', # C+0x6D # U+0xF06D + 'circlesolid' => '1000', # C+0x6E # U+0xF06E + 'boat' => '1000', # C+0x6F # U+0xF06F + 'police' => '1000', # C+0x70 # U+0xF070 + 'UIrefresh' => '1000', # C+0x71 # U+0xF071 + 'UIclose' => '1000', # C+0x72 # U+0xF072 + 'UIhelp' => '1000', # C+0x73 # U+0xF073 + 'train' => '1000', # C+0x74 # U+0xF074 + 'metro' => '1000', # C+0x75 # U+0xF075 + 'bus' => '1000', # C+0x76 # U+0xF076 + 'flag' => '1000', # C+0x77 # U+0xF077 + 'not' => '1000', # C+0x78 # U+0xF078 + 'noentry' => '1000', # C+0x79 # U+0xF079 + 'nosmoking' => '1000', # C+0x7A # U+0xF07A + 'shoutleft' => '1000', # C+0x7B # U+0xF07B + 'bar' => '1000', # C+0x7C # U+0xF07C + 'shoutright' => '1000', # C+0x7D # U+0xF07D + 'lightningbolt' => '1000', # C+0x7E # U+0xF07E + 'man' => '1000', # C+0x80 # U+0xF080 + 'woman' => '1000', # C+0x81 # U+0xF081 + 'boy' => '1000', # C+0x82 # U+0xF082 + 'girl' => '1000', # C+0x83 # U+0xF083 + 'baby' => '1000', # C+0x84 # U+0xF084 + 'scifi' => '1000', # C+0x85 # U+0xF085 + 'health' => '1000', # C+0x86 # U+0xF086 + 'skier' => '1000', # C+0x87 # U+0xF087 + 'hobby' => '1000', # C+0x88 # U+0xF088 + 'golfer' => '1000', # C+0x89 # U+0xF089 + 'pool' => '1000', # C+0x8A # U+0xF08A + 'surf' => '1000', # C+0x8B # U+0xF08B + 'motorcycle' => '1000', # C+0x8C # U+0xF08C + 'racecar' => '1220', # C+0x8D # U+0xF08D + 'auto' => '1000', # C+0x8E # U+0xF08E + 'finance' => '1000', # C+0x8F # U+0xF08F + 'commodities' => '1000', # C+0x90 # U+0xF090 + 'money' => '1000', # C+0x91 # U+0xF091 + 'price' => '1000', # C+0x92 # U+0xF092 + 'creditcard' => '1000', # C+0x93 # U+0xF093 + 'ratingfamily' => '1000', # C+0x94 # U+0xF094 + 'ratingviolence' => '1000', # C+0x95 # U+0xF095 + 'ratingsex' => '1000', # C+0x96 # U+0xF096 + 'ratinglanguage' => '1000', # C+0x97 # U+0xF097 + 'ratingquality' => '1000', # C+0x98 # U+0xF098 + 'email' => '1000', # C+0x99 # U+0xF099 + 'send' => '1000', # C+0x9A # U+0xF09A + 'mail' => '1000', # C+0x9B # U+0xF09B + 'write' => '1000', # C+0x9C # U+0xF09C + 'textdoc' => '1000', # C+0x9D # U+0xF09D + 'textgraphicdoc' => '1000', # C+0x9E # U+0xF09E + 'graphicdoc' => '1000', # C+0x9F # U+0xF09F + 'investigate' => '1000', # C+0xA0 # U+0xF0A0 + 'clock' => '1000', # C+0xA1 # U+0xF0A1 + 'frames' => '1000', # C+0xA2 # U+0xF0A2 + 'noframes' => '1000', # C+0xA3 # U+0xF0A3 + 'clipboard' => '1000', # C+0xA4 # U+0xF0A4 + 'note' => '1000', # C+0xA5 # U+0xF0A5 + 'calender' => '1000', # C+0xA6 # U+0xF0A6 + 'book' => '1000', # C+0xA7 # U+0xF0A7 + 'reference' => '1000', # C+0xA8 # U+0xF0A8 + 'news' => '1000', # C+0xA9 # U+0xF0A9 + 'classified' => '1000', # C+0xAA # U+0xF0AA + 'archive' => '1000', # C+0xAB # U+0xF0AB + 'index' => '1000', # C+0xAC # U+0xF0AC + 'art' => '1000', # C+0xAD # U+0xF0AD + 'theatre' => '1000', # C+0xAE # U+0xF0AE + 'music' => '1000', # C+0xAF # U+0xF0AF + 'MIDI' => '1000', # C+0xB0 # U+0xF0B0 + 'microphone' => '1000', # C+0xB1 # U+0xF0B1 + 'headphones' => '1000', # C+0xB2 # U+0xF0B2 + 'CDROM' => '1000', # C+0xB3 # U+0xF0B3 + 'filmclip' => '1000', # C+0xB4 # U+0xF0B4 + 'pointofinterest' => '1000', # C+0xB5 # U+0xF0B5 + 'ticket' => '1000', # C+0xB6 # U+0xF0B6 + 'film' => '1000', # C+0xB7 # U+0xF0B7 + 'movies' => '1000', # C+0xB8 # U+0xF0B8 + 'video' => '1000', # C+0xB9 # U+0xF0B9 + 'stereo' => '1000', # C+0xBA # U+0xF0BA + 'radio' => '1000', # C+0xBB # U+0xF0BB + 'levelcontrol' => '672', # C+0xBC # U+0xF0BC + 'audiocontrol' => '672', # C+0xBD # U+0xF0BD + 'television' => '1000', # C+0xBE # U+0xF0BE + 'computers1' => '842', # C+0xBF # U+0xF0BF + 'computers2' => '516', # C+0xC0 # U+0xF0C0 + 'computers3' => '1000', # C+0xC1 # U+0xF0C1 + 'computers4' => '1000', # C+0xC2 # U+0xF0C2 + 'joystick' => '1000', # C+0xC3 # U+0xF0C3 + 'gamepad' => '1000', # C+0xC4 # U+0xF0C4 + 'phone' => '428', # C+0xC5 # U+0xF0C5 + 'fax' => '605', # C+0xC6 # U+0xF0C6 + 'pager' => '1000', # C+0xC7 # U+0xF0C7 + 'cellularphone' => '1000', # C+0xC8 # U+0xF0C8 + 'modem' => '1000', # C+0xC9 # U+0xF0C9 + 'printer' => '1000', # C+0xCA # U+0xF0CA + 'calculator' => '662', # C+0xCB # U+0xF0CB + 'folder' => '1000', # C+0xCC # U+0xF0CC + 'disk' => '1000', # C+0xCD # U+0xF0CD + 'compression' => '1000', # C+0xCE # U+0xF0CE + 'locked' => '1000', # C+0xCF # U+0xF0CF + 'unlocked' => '1000', # C+0xD0 # U+0xF0D0 + 'encryption' => '1000', # C+0xD1 # U+0xF0D1 + 'inbox' => '1000', # C+0xD2 # U+0xF0D2 + 'outbox' => '1000', # C+0xD3 # U+0xF0D3 + 'ovalshape' => '1000', # C+0xD4 # U+0xF0D4 + 'sunny' => '1000', # C+0xD5 # U+0xF0D5 + 'mostlysunny' => '1000', # C+0xD6 # U+0xF0D6 + 'mostlycloudy' => '1000', # C+0xD7 # U+0xF0D7 + 'showers' => '1000', # C+0xD8 # U+0xF0D8 + 'cloudy' => '1000', # C+0xD9 # U+0xF0D9 + 'snow' => '1000', # C+0xDA # U+0xF0DA + 'rain' => '1000', # C+0xDB # U+0xF0DB + 'lightning' => '1000', # C+0xDC # U+0xF0DC + 'twister' => '1000', # C+0xDD # U+0xF0DD + 'wind' => '1000', # C+0xDE # U+0xF0DE + 'fog' => '1000', # C+0xDF # U+0xF0DF + 'moon' => '1000', # C+0xE0 # U+0xF0E0 + 'temperature' => '1000', # C+0xE1 # U+0xF0E1 + 'lifestyles' => '1000', # C+0xE2 # U+0xF0E2 + 'guestrooms' => '1000', # C+0xE3 # U+0xF0E3 + 'dining' => '1000', # C+0xE4 # U+0xF0E4 + 'lounge' => '1000', # C+0xE5 # U+0xF0E5 + 'services' => '1000', # C+0xE6 # U+0xF0E6 + 'shopping' => '1000', # C+0xE7 # U+0xF0E7 + 'parking' => '1000', # C+0xE8 # U+0xF0E8 + 'handycap' => '1000', # C+0xE9 # U+0xF0E9 + 'caution' => '1000', # C+0xEA # U+0xF0EA + 'marker' => '1000', # C+0xEB # U+0xF0EB + 'education' => '1000', # C+0xEC # U+0xF0EC + 'raysabove' => '1000', # C+0xED # U+0xF0ED + 'raysbelow' => '1000', # C+0xEE # U+0xF0EE + 'raysleft' => '1000', # C+0xEF # U+0xF0EF + 'raysright' => '1000', # C+0xF0 # U+0xF0F0 + 'airplane' => '1000', # C+0xF1 # U+0xF0F1 + 'animal1' => '1000', # C+0xF2 # U+0xF0F2 + 'bird' => '1000', # C+0xF3 # U+0xF0F3 + 'fish' => '1000', # C+0xF4 # U+0xF0F4 + 'dog' => '1000', # C+0xF5 # U+0xF0F5 + 'cat' => '1000', # C+0xF6 # U+0xF0F6 + 'rocketleft' => '1000', # C+0xF7 # U+0xF0F7 + 'rocketright' => '1000', # C+0xF8 # U+0xF0F8 + 'rocketup' => '1000', # C+0xF9 # U+0xF0F9 + 'rocketdown' => '1000', # C+0xFA # U+0xF0FA + 'worldmap' => '1291', # C+0xFB # U+0xF0FB + 'globe1' => '1000', # C+0xFC # U+0xF0FC + 'globe2' => '1000', # C+0xFD # U+0xF0FD + 'globe3' => '1000', # C+0xFE # U+0xF0FE + 'peace' => '1000', # C+0xFF # U+0xF0FF + }, # UNICODE COMPAT TABLE + 'uni' => [ + 0xF000, + 0xF001, + 0xF002, + 0xF003, + 0xF004, + 0xF005, + 0xF006, + 0xF007, + 0xF008, + 0xF009, + 0xF00A, + 0xF00B, + 0xF00C, + 0xF00D, + 0xF00E, + 0xF00F, + 0xF010, + 0xF011, + 0xF012, + 0xF013, + 0xF014, + 0xF015, + 0xF016, + 0xF017, + 0xF018, + 0xF019, + 0xF01A, + 0xF01B, + 0xF01C, + 0xF01D, + 0xF01E, + 0xF01F, + 0xF020, + 0xF021, + 0xF022, + 0xF023, + 0xF024, + 0xF025, + 0xF026, + 0xF027, + 0xF028, + 0xF029, + 0xF02A, + 0xF02B, + 0xF02C, + 0xF02D, + 0xF02E, + 0xF02F, + 0xF030, + 0xF031, + 0xF032, + 0xF033, + 0xF034, + 0xF035, + 0xF036, + 0xF037, + 0xF038, + 0xF039, + 0xF03A, + 0xF03B, + 0xF03C, + 0xF03D, + 0xF03E, + 0xF03F, + 0xF040, + 0xF041, + 0xF042, + 0xF043, + 0xF044, + 0xF045, + 0xF046, + 0xF047, + 0xF048, + 0xF049, + 0xF04A, + 0xF04B, + 0xF04C, + 0xF04D, + 0xF04E, + 0xF04F, + 0xF050, + 0xF051, + 0xF052, + 0xF053, + 0xF054, + 0xF055, + 0xF056, + 0xF057, + 0xF058, + 0xF059, + 0xF05A, + 0xF05B, + 0xF05C, + 0xF05D, + 0xF05E, + 0xF05F, + 0xF060, + 0xF061, + 0xF062, + 0xF063, + 0xF064, + 0xF065, + 0xF066, + 0xF067, + 0xF068, + 0xF069, + 0xF06A, + 0xF06B, + 0xF06C, + 0xF06D, + 0xF06E, + 0xF06F, + 0xF070, + 0xF071, + 0xF072, + 0xF073, + 0xF074, + 0xF075, + 0xF076, + 0xF077, + 0xF078, + 0xF079, + 0xF07A, + 0xF07B, + 0xF07C, + 0xF07D, + 0xF07E, + 0xF07F, + 0xF080, + 0xF081, + 0xF082, + 0xF083, + 0xF084, + 0xF085, + 0xF086, + 0xF087, + 0xF088, + 0xF089, + 0xF08A, + 0xF08B, + 0xF08C, + 0xF08D, + 0xF08E, + 0xF08F, + 0xF090, + 0xF091, + 0xF092, + 0xF093, + 0xF094, + 0xF095, + 0xF096, + 0xF097, + 0xF098, + 0xF099, + 0xF09A, + 0xF09B, + 0xF09C, + 0xF09D, + 0xF09E, + 0xF09F, + 0xF0A0, + 0xF0A1, + 0xF0A2, + 0xF0A3, + 0xF0A4, + 0xF0A5, + 0xF0A6, + 0xF0A7, + 0xF0A8, + 0xF0A9, + 0xF0AA, + 0xF0AB, + 0xF0AC, + 0xF0AD, + 0xF0AE, + 0xF0AF, + 0xF0B0, + 0xF0B1, + 0xF0B2, + 0xF0B3, + 0xF0B4, + 0xF0B5, + 0xF0B6, + 0xF0B7, + 0xF0B8, + 0xF0B9, + 0xF0BA, + 0xF0BB, + 0xF0BC, + 0xF0BD, + 0xF0BE, + 0xF0BF, + 0xF0C0, + 0xF0C1, + 0xF0C2, + 0xF0C3, + 0xF0C4, + 0xF0C5, + 0xF0C6, + 0xF0C7, + 0xF0C8, + 0xF0C9, + 0xF0CA, + 0xF0CB, + 0xF0CC, + 0xF0CD, + 0xF0CE, + 0xF0CF, + 0xF0D0, + 0xF0D1, + 0xF0D2, + 0xF0D3, + 0xF0D4, + 0xF0D5, + 0xF0D6, + 0xF0D7, + 0xF0D8, + 0xF0D9, + 0xF0DA, + 0xF0DB, + 0xF0DC, + 0xF0DD, + 0xF0DE, + 0xF0DF, + 0xF0E0, + 0xF0E1, + 0xF0E2, + 0xF0E3, + 0xF0E4, + 0xF0E5, + 0xF0E6, + 0xF0E7, + 0xF0E8, + 0xF0E9, + 0xF0EA, + 0xF0EB, + 0xF0EC, + 0xF0ED, + 0xF0EE, + 0xF0EF, + 0xF0F0, + 0xF0F1, + 0xF0F2, + 0xF0F3, + 0xF0F4, + 0xF0F5, + 0xF0F6, + 0xF0F7, + 0xF0F8, + 0xF0F9, + 0xF0FA, + 0xF0FB, + 0xF0FC, + 0xF0FD, + 0xF0FE, + 0xF0FF, + ], +} }; + +1; diff --git a/lib/PDF/API2/Resource/Font/CoreFont/wingdings.pm b/lib/PDF/API2/Resource/Font/CoreFont/wingdings.pm new file mode 100644 index 0000000..479e500 --- /dev/null +++ b/lib/PDF/API2/Resource/Font/CoreFont/wingdings.pm @@ -0,0 +1,512 @@ +#line 1 "PDF/API2/Resource/Font/CoreFont/wingdings.pm" +#line 1 "PDF/API2/Resource/Font/CoreFont/wingdings.pm" +package PDF::API2::Resource::Font::CoreFont::wingdings; + +use strict; +use warnings; + +our $VERSION = '2.033'; # VERSION + +sub data { return { + 'fontname' => 'Wingdings', + 'type' => 'TrueType', + 'apiname' => 'WiDi', + 'ascender' => '898', + 'capheight' => '722', + 'descender' => '-210', + 'isfixedpitch' => '0', + 'issymbol' => '1', + 'italicangle' => '0', + 'underlineposition' => '-200', + 'underlinethickness' => '100', + 'xheight' => '722', + 'firstchar' => '32', + 'lastchar' => '255', + 'flags' => '4', + 'char' => [ # DEF. ENCODING GLYPH TABLE + '.notdef', # C+0x00 # U+0x0000 + '.notdef', # C+0x01 # U+0x0000 + '.notdef', # C+0x02 # U+0x0000 + '.notdef', # C+0x03 # U+0x0000 + '.notdef', # C+0x04 # U+0x0000 + '.notdef', # C+0x05 # U+0x0000 + '.notdef', # C+0x06 # U+0x0000 + '.notdef', # C+0x07 # U+0x0000 + '.notdef', # C+0x08 # U+0x0000 + '.notdef', # C+0x09 # U+0x0000 + '.notdef', # C+0x0A # U+0x0000 + '.notdef', # C+0x0B # U+0x0000 + '.notdef', # C+0x0C # U+0x0000 + '.notdef', # C+0x0D # U+0x0000 + '.notdef', # C+0x0E # U+0x0000 + '.notdef', # C+0x0F # U+0x0000 + '.notdef', # C+0x10 # U+0x0000 + '.notdef', # C+0x11 # U+0x0000 + '.notdef', # C+0x12 # U+0x0000 + '.notdef', # C+0x13 # U+0x0000 + '.notdef', # C+0x14 # U+0x0000 + '.notdef', # C+0x15 # U+0x0000 + '.notdef', # C+0x16 # U+0x0000 + '.notdef', # C+0x17 # U+0x0000 + '.notdef', # C+0x18 # U+0x0000 + '.notdef', # C+0x19 # U+0x0000 + '.notdef', # C+0x1A # U+0x0000 + '.notdef', # C+0x1B # U+0x0000 + '.notdef', # C+0x1C # U+0x0000 + '.notdef', # C+0x1D # U+0x0000 + '.notdef', # C+0x1E # U+0x0000 + '.notdef', # C+0x1F # U+0x0000 + 'space', # C+0x20 # U+0xF020 + 'pencil', # C+0x21 # U+0xF021 + 'scissors', # C+0x22 # U+0xF022 + 'scissorscutting', # C+0x23 # U+0xF023 + 'readingglasses', # C+0x24 # U+0xF024 + 'bell', # C+0x25 # U+0xF025 + 'book', # C+0x26 # U+0xF026 + 'candle', # C+0x27 # U+0xF027 + 'telephonesolid', # C+0x28 # U+0xF028 + 'telhandsetcirc', # C+0x29 # U+0xF029 + 'envelopeback', # C+0x2A # U+0xF02A + 'envelopefront', # C+0x2B # U+0xF02B + 'mailboxflagdwn', # C+0x2C # U+0xF02C + 'mailboxflagup', # C+0x2D # U+0xF02D + 'mailbxopnflgup', # C+0x2E # U+0xF02E + 'mailbxopnflgdwn', # C+0x2F # U+0xF02F + 'folder', # C+0x30 # U+0xF030 + 'folderopen', # C+0x31 # U+0xF031 + 'filetalltext1', # C+0x32 # U+0xF032 + 'filetalltext', # C+0x33 # U+0xF033 + 'filetalltext3', # C+0x34 # U+0xF034 + 'filecabinet', # C+0x35 # U+0xF035 + 'hourglass', # C+0x36 # U+0xF036 + 'keyboard', # C+0x37 # U+0xF037 + 'mouse2button', # C+0x38 # U+0xF038 + 'ballpoint', # C+0x39 # U+0xF039 + 'pc', # C+0x3A # U+0xF03A + 'harddisk', # C+0x3B # U+0xF03B + 'floppy3', # C+0x3C # U+0xF03C + 'floppy5', # C+0x3D # U+0xF03D + 'tapereel', # C+0x3E # U+0xF03E + 'handwrite', # C+0x3F # U+0xF03F + 'handwriteleft', # C+0x40 # U+0xF040 + 'handv', # C+0x41 # U+0xF041 + 'handok', # C+0x42 # U+0xF042 + 'thumbup', # C+0x43 # U+0xF043 + 'thumbdown', # C+0x44 # U+0xF044 + 'handptleft', # C+0x45 # U+0xF045 + 'handptright', # C+0x46 # U+0xF046 + 'handptup', # C+0x47 # U+0xF047 + 'handptdwn', # C+0x48 # U+0xF048 + 'handhalt', # C+0x49 # U+0xF049 + 'smileface', # C+0x4A # U+0xF04A + 'neutralface', # C+0x4B # U+0xF04B + 'frownface', # C+0x4C # U+0xF04C + 'bomb', # C+0x4D # U+0xF04D + 'skullcrossbones', # C+0x4E # U+0xF04E + 'flag', # C+0x4F # U+0xF04F + 'pennant', # C+0x50 # U+0xF050 + 'airplane', # C+0x51 # U+0xF051 + 'sunshine', # C+0x52 # U+0xF052 + 'droplet', # C+0x53 # U+0xF053 + 'snowflake', # C+0x54 # U+0xF054 + 'crossoutline', # C+0x55 # U+0xF055 + 'crossshadow', # C+0x56 # U+0xF056 + 'crossceltic', # C+0x57 # U+0xF057 + 'crossmaltese', # C+0x58 # U+0xF058 + 'starofdavid', # C+0x59 # U+0xF059 + 'crescentstar', # C+0x5A # U+0xF05A + 'yinyang', # C+0x5B # U+0xF05B + 'om', # C+0x5C # U+0xF05C + 'wheel', # C+0x5D # U+0xF05D + 'aries', # C+0x5E # U+0xF05E + 'taurus', # C+0x5F # U+0xF05F + 'gemini', # C+0x60 # U+0xF060 + 'cancer', # C+0x61 # U+0xF061 + 'leo', # C+0x62 # U+0xF062 + 'virgo', # C+0x63 # U+0xF063 + 'libra', # C+0x64 # U+0xF064 + 'scorpio', # C+0x65 # U+0xF065 + 'saggitarius', # C+0x66 # U+0xF066 + 'capricorn', # C+0x67 # U+0xF067 + 'aquarius', # C+0x68 # U+0xF068 + 'pisces', # C+0x69 # U+0xF069 + 'ampersanditlc', # C+0x6A # U+0xF06A + 'ampersandit', # C+0x6B # U+0xF06B + 'circle6', # C+0x6C # U+0xF06C + 'circleshadowdwn', # C+0x6D # U+0xF06D + 'square6', # C+0x6E # U+0xF06E + 'box3', # C+0x6F # U+0xF06F + 'box4', # C+0x70 # U+0xF070 + 'boxshadowdwn', # C+0x71 # U+0xF071 + 'boxshadowup', # C+0x72 # U+0xF072 + 'lozenge4', # C+0x73 # U+0xF073 + 'lozenge6', # C+0x74 # U+0xF074 + 'rhombus6', # C+0x75 # U+0xF075 + 'xrhombus', # C+0x76 # U+0xF076 + 'rhombus4', # C+0x77 # U+0xF077 + 'clear', # C+0x78 # U+0xF078 + 'escape', # C+0x79 # U+0xF079 + 'command', # C+0x7A # U+0xF07A + 'rosette', # C+0x7B # U+0xF07B + 'rosettesolid', # C+0x7C # U+0xF07C + 'quotedbllftbld', # C+0x7D # U+0xF07D + 'quotedblrtbld', # C+0x7E # U+0xF07E + '.notdef', # C+0x7F # U+0x0000 + 'zerosans', # C+0x80 # U+0xF080 + 'onesans', # C+0x81 # U+0xF081 + 'twosans', # C+0x82 # U+0xF082 + 'threesans', # C+0x83 # U+0xF083 + 'foursans', # C+0x84 # U+0xF084 + 'fivesans', # C+0x85 # U+0xF085 + 'sixsans', # C+0x86 # U+0xF086 + 'sevensans', # C+0x87 # U+0xF087 + 'eightsans', # C+0x88 # U+0xF088 + 'ninesans', # C+0x89 # U+0xF089 + 'tensans', # C+0x8A # U+0xF08A + 'zerosansinv', # C+0x8B # U+0xF08B + 'onesansinv', # C+0x8C # U+0xF08C + 'twosansinv', # C+0x8D # U+0xF08D + 'threesansinv', # C+0x8E # U+0xF08E + 'foursansinv', # C+0x8F # U+0xF08F + 'fivesansinv', # C+0x90 # U+0xF090 + 'sixsansinv', # C+0x91 # U+0xF091 + 'sevensansinv', # C+0x92 # U+0xF092 + 'eightsansinv', # C+0x93 # U+0xF093 + 'ninesansinv', # C+0x94 # U+0xF094 + 'tensansinv', # C+0x95 # U+0xF095 + 'budleafne', # C+0x96 # U+0xF096 + 'budleafnw', # C+0x97 # U+0xF097 + 'budleafsw', # C+0x98 # U+0xF098 + 'budleafse', # C+0x99 # U+0xF099 + 'vineleafboldne', # C+0x9A # U+0xF09A + 'vineleafboldnw', # C+0x9B # U+0xF09B + 'vineleafboldsw', # C+0x9C # U+0xF09C + 'vineleafboldse', # C+0x9D # U+0xF09D + 'circle2', # C+0x9E # U+0xF09E + 'circle4', # C+0x9F # U+0xF09F + 'square2', # C+0xA0 # U+0xF0A0 + 'ring2', # C+0xA1 # U+0xF0A1 + 'ring4', # C+0xA2 # U+0xF0A2 + 'ring6', # C+0xA3 # U+0xF0A3 + 'ringbutton2', # C+0xA4 # U+0xF0A4 + 'target', # C+0xA5 # U+0xF0A5 + 'circleshadowup', # C+0xA6 # U+0xF0A6 + 'square4', # C+0xA7 # U+0xF0A7 + 'box2', # C+0xA8 # U+0xF0A8 + 'tristar2', # C+0xA9 # U+0xF0A9 + 'crosstar2', # C+0xAA # U+0xF0AA + 'pentastar2', # C+0xAB # U+0xF0AB + 'hexstar2', # C+0xAC # U+0xF0AC + 'octastar2', # C+0xAD # U+0xF0AD + 'dodecastar3', # C+0xAE # U+0xF0AE + 'octastar4', # C+0xAF # U+0xF0AF + 'registersquare', # C+0xB0 # U+0xF0B0 + 'registercircle', # C+0xB1 # U+0xF0B1 + 'cuspopen', # C+0xB2 # U+0xF0B2 + 'cuspopen1', # C+0xB3 # U+0xF0B3 + 'query', # C+0xB4 # U+0xF0B4 + 'circlestar', # C+0xB5 # U+0xF0B5 + 'starshadow', # C+0xB6 # U+0xF0B6 + 'oneoclock', # C+0xB7 # U+0xF0B7 + 'twooclock', # C+0xB8 # U+0xF0B8 + 'threeoclock', # C+0xB9 # U+0xF0B9 + 'fouroclock', # C+0xBA # U+0xF0BA + 'fiveoclock', # C+0xBB # U+0xF0BB + 'sixoclock', # C+0xBC # U+0xF0BC + 'sevenoclock', # C+0xBD # U+0xF0BD + 'eightoclock', # C+0xBE # U+0xF0BE + 'nineoclock', # C+0xBF # U+0xF0BF + 'tenoclock', # C+0xC0 # U+0xF0C0 + 'elevenoclock', # C+0xC1 # U+0xF0C1 + 'twelveoclock', # C+0xC2 # U+0xF0C2 + 'arrowdwnleft1', # C+0xC3 # U+0xF0C3 + 'arrowdwnrt1', # C+0xC4 # U+0xF0C4 + 'arrowupleft1', # C+0xC5 # U+0xF0C5 + 'arrowuprt1', # C+0xC6 # U+0xF0C6 + 'arrowleftup1', # C+0xC7 # U+0xF0C7 + 'arrowrtup1', # C+0xC8 # U+0xF0C8 + 'arrowleftdwn1', # C+0xC9 # U+0xF0C9 + 'arrowrtdwn1', # C+0xCA # U+0xF0CA + 'quiltsquare2', # C+0xCB # U+0xF0CB + 'quiltsquare2inv', # C+0xCC # U+0xF0CC + 'leafccwsw', # C+0xCD # U+0xF0CD + 'leafccwnw', # C+0xCE # U+0xF0CE + 'leafccwse', # C+0xCF # U+0xF0CF + 'leafccwne', # C+0xD0 # U+0xF0D0 + 'leafnw', # C+0xD1 # U+0xF0D1 + 'leafsw', # C+0xD2 # U+0xF0D2 + 'leafne', # C+0xD3 # U+0xF0D3 + 'leafse', # C+0xD4 # U+0xF0D4 + 'deleteleft', # C+0xD5 # U+0xF0D5 + 'deleteright', # C+0xD6 # U+0xF0D6 + 'head2left', # C+0xD7 # U+0xF0D7 + 'head2right', # C+0xD8 # U+0xF0D8 + 'head2up', # C+0xD9 # U+0xF0D9 + 'head2down', # C+0xDA # U+0xF0DA + 'circleleft', # C+0xDB # U+0xF0DB + 'circleright', # C+0xDC # U+0xF0DC + 'circleup', # C+0xDD # U+0xF0DD + 'circledown', # C+0xDE # U+0xF0DE + 'barb2left', # C+0xDF # U+0xF0DF + 'barb2right', # C+0xE0 # U+0xF0E0 + 'barb2up', # C+0xE1 # U+0xF0E1 + 'barb2down', # C+0xE2 # U+0xF0E2 + 'barb2nw', # C+0xE3 # U+0xF0E3 + 'barb2ne', # C+0xE4 # U+0xF0E4 + 'barb2sw', # C+0xE5 # U+0xF0E5 + 'barb2se', # C+0xE6 # U+0xF0E6 + 'barb4left', # C+0xE7 # U+0xF0E7 + 'barb4right', # C+0xE8 # U+0xF0E8 + 'barb4up', # C+0xE9 # U+0xF0E9 + 'barb4down', # C+0xEA # U+0xF0EA + 'barb4nw', # C+0xEB # U+0xF0EB + 'barb4ne', # C+0xEC # U+0xF0EC + 'barb4sw', # C+0xED # U+0xF0ED + 'barb4se', # C+0xEE # U+0xF0EE + 'bleft', # C+0xEF # U+0xF0EF + 'bright', # C+0xF0 # U+0xF0F0 + 'bup', # C+0xF1 # U+0xF0F1 + 'bdown', # C+0xF2 # U+0xF0F2 + 'bleftright', # C+0xF3 # U+0xF0F3 + 'bupdown', # C+0xF4 # U+0xF0F4 + 'bnw', # C+0xF5 # U+0xF0F5 + 'bne', # C+0xF6 # U+0xF0F6 + 'bsw', # C+0xF7 # U+0xF0F7 + 'bse', # C+0xF8 # U+0xF0F8 + 'bdash1', # C+0xF9 # U+0xF0F9 + 'bdash2', # C+0xFA # U+0xF0FA + 'xmarkbld', # C+0xFB # U+0xF0FB + 'checkbld', # C+0xFC # U+0xF0FC + 'boxxmarkbld', # C+0xFD # U+0xF0FD + 'boxcheckbld', # C+0xFE # U+0xF0FE + 'windowslogo', # C+0xFF # U+0xF0FF + ], # DEF. ENCODING GLYPH TABLE + 'fontbbox' => [ 0, -210, 1358, 898 ], + 'wx' => { # HORIZ. WIDTH TABLE + 'space' => '1000', # C+0x20 # U+0xF020 + 'pencil' => '1030', # C+0x21 # U+0xF021 + 'scissors' => '1144', # C+0x22 # U+0xF022 + 'scissorscutting' => '1301', # C+0x23 # U+0xF023 + 'readingglasses' => '1343', # C+0x24 # U+0xF024 + 'bell' => '893', # C+0x25 # U+0xF025 + 'book' => '1216', # C+0x26 # U+0xF026 + 'candle' => '458', # C+0x27 # U+0xF027 + 'telephonesolid' => '1083', # C+0x28 # U+0xF028 + 'telhandsetcirc' => '891', # C+0x29 # U+0xF029 + 'envelopeback' => '1132', # C+0x2A # U+0xF02A + 'envelopefront' => '1132', # C+0x2B # U+0xF02B + 'mailboxflagdwn' => '1171', # C+0x2C # U+0xF02C + 'mailboxflagup' => '1171', # C+0x2D # U+0xF02D + 'mailbxopnflgup' => '1440', # C+0x2E # U+0xF02E + 'mailbxopnflgdwn' => '1443', # C+0x2F # U+0xF02F + 'folder' => '1096', # C+0x30 # U+0xF030 + 'folderopen' => '1343', # C+0x31 # U+0xF031 + 'filetalltext1' => '698', # C+0x32 # U+0xF032 + 'filetalltext' => '698', # C+0x33 # U+0xF033 + 'filetalltext3' => '891', # C+0x34 # U+0xF034 + 'filecabinet' => '554', # C+0x35 # U+0xF035 + 'hourglass' => '602', # C+0x36 # U+0xF036 + 'keyboard' => '1072', # C+0x37 # U+0xF037 + 'mouse2button' => '947', # C+0x38 # U+0xF038 + 'ballpoint' => '1078', # C+0x39 # U+0xF039 + 'pc' => '939', # C+0x3A # U+0xF03A + 'harddisk' => '891', # C+0x3B # U+0xF03B + 'floppy3' => '891', # C+0x3C # U+0xF03C + 'floppy5' => '891', # C+0x3D # U+0xF03D + 'tapereel' => '891', # C+0x3E # U+0xF03E + 'handwrite' => '909', # C+0x3F # U+0xF03F + 'handwriteleft' => '909', # C+0x40 # U+0xF040 + 'handv' => '587', # C+0x41 # U+0xF041 + 'handok' => '792', # C+0x42 # U+0xF042 + 'thumbup' => '674', # C+0x43 # U+0xF043 + 'thumbdown' => '674', # C+0x44 # U+0xF044 + 'handptleft' => '941', # C+0x45 # U+0xF045 + 'handptright' => '941', # C+0x46 # U+0xF046 + 'handptup' => '548', # C+0x47 # U+0xF047 + 'handptdwn' => '548', # C+0x48 # U+0xF048 + 'handhalt' => '891', # C+0x49 # U+0xF049 + 'smileface' => '843', # C+0x4A # U+0xF04A + 'neutralface' => '843', # C+0x4B # U+0xF04B + 'frownface' => '843', # C+0x4C # U+0xF04C + 'bomb' => '1110', # C+0x4D # U+0xF04D + 'skullcrossbones' => '660', # C+0x4E # U+0xF04E + 'flag' => '849', # C+0x4F # U+0xF04F + 'pennant' => '1088', # C+0x50 # U+0xF050 + 'airplane' => '888', # C+0x51 # U+0xF051 + 'sunshine' => '880', # C+0x52 # U+0xF052 + 'droplet' => '650', # C+0x53 # U+0xF053 + 'snowflake' => '812', # C+0x54 # U+0xF054 + 'crossoutline' => '746', # C+0x55 # U+0xF055 + 'crossshadow' => '746', # C+0x56 # U+0xF056 + 'crossceltic' => '722', # C+0x57 # U+0xF057 + 'crossmaltese' => '693', # C+0x58 # U+0xF058 + 'starofdavid' => '794', # C+0x59 # U+0xF059 + 'crescentstar' => '885', # C+0x5A # U+0xF05A + 'yinyang' => '891', # C+0x5B # U+0xF05B + 'om' => '895', # C+0x5C # U+0xF05C + 'wheel' => '891', # C+0x5D # U+0xF05D + 'aries' => '1156', # C+0x5E # U+0xF05E + 'taurus' => '1054', # C+0x5F # U+0xF05F + 'gemini' => '963', # C+0x60 # U+0xF060 + 'cancer' => '1090', # C+0x61 # U+0xF061 + 'leo' => '940', # C+0x62 # U+0xF062 + 'virgo' => '933', # C+0x63 # U+0xF063 + 'libra' => '945', # C+0x64 # U+0xF064 + 'scorpio' => '1024', # C+0x65 # U+0xF065 + 'saggitarius' => '928', # C+0x66 # U+0xF066 + 'capricorn' => '1096', # C+0x67 # U+0xF067 + 'aquarius' => '1064', # C+0x68 # U+0xF068 + 'pisces' => '779', # C+0x69 # U+0xF069 + 'ampersanditlc' => '1049', # C+0x6A # U+0xF06A + 'ampersandit' => '1270', # C+0x6B # U+0xF06B + 'circle6' => '746', # C+0x6C # U+0xF06C + 'circleshadowdwn' => '952', # C+0x6D # U+0xF06D + 'square6' => '746', # C+0x6E # U+0xF06E + 'box3' => '891', # C+0x6F # U+0xF06F + 'box4' => '891', # C+0x70 # U+0xF070 + 'boxshadowdwn' => '891', # C+0x71 # U+0xF071 + 'boxshadowup' => '891', # C+0x72 # U+0xF072 + 'lozenge4' => '457', # C+0x73 # U+0xF073 + 'lozenge6' => '746', # C+0x74 # U+0xF074 + 'rhombus6' => '986', # C+0x75 # U+0xF075 + 'xrhombus' => '891', # C+0x76 # U+0xF076 + 'rhombus4' => '577', # C+0x77 # U+0xF077 + 'clear' => '1060', # C+0x78 # U+0xF078 + 'escape' => '1060', # C+0x79 # U+0xF079 + 'command' => '891', # C+0x7A # U+0xF07A + 'rosette' => '891', # C+0x7B # U+0xF07B + 'rosettesolid' => '891', # C+0x7C # U+0xF07C + 'quotedbllftbld' => '530', # C+0x7D # U+0xF07D + 'quotedblrtbld' => '530', # C+0x7E # U+0xF07E + 'zerosans' => '891', # C+0x80 # U+0xF080 + 'onesans' => '891', # C+0x81 # U+0xF081 + 'twosans' => '891', # C+0x82 # U+0xF082 + 'threesans' => '891', # C+0x83 # U+0xF083 + 'foursans' => '891', # C+0x84 # U+0xF084 + 'fivesans' => '891', # C+0x85 # U+0xF085 + 'sixsans' => '891', # C+0x86 # U+0xF086 + 'sevensans' => '891', # C+0x87 # U+0xF087 + 'eightsans' => '891', # C+0x88 # U+0xF088 + 'ninesans' => '891', # C+0x89 # U+0xF089 + 'tensans' => '891', # C+0x8A # U+0xF08A + 'zerosansinv' => '891', # C+0x8B # U+0xF08B + 'onesansinv' => '891', # C+0x8C # U+0xF08C + 'twosansinv' => '891', # C+0x8D # U+0xF08D + 'threesansinv' => '891', # C+0x8E # U+0xF08E + 'foursansinv' => '891', # C+0x8F # U+0xF08F + 'fivesansinv' => '891', # C+0x90 # U+0xF090 + 'sixsansinv' => '891', # C+0x91 # U+0xF091 + 'sevensansinv' => '891', # C+0x92 # U+0xF092 + 'eightsansinv' => '891', # C+0x93 # U+0xF093 + 'ninesansinv' => '891', # C+0x94 # U+0xF094 + 'tensansinv' => '891', # C+0x95 # U+0xF095 + 'budleafne' => '1000', # C+0x96 # U+0xF096 + 'budleafnw' => '1000', # C+0x97 # U+0xF097 + 'budleafsw' => '1000', # C+0x98 # U+0xF098 + 'budleafse' => '1000', # C+0x99 # U+0xF099 + 'vineleafboldne' => '1000', # C+0x9A # U+0xF09A + 'vineleafboldnw' => '1000', # C+0x9B # U+0xF09B + 'vineleafboldsw' => '1000', # C+0x9C # U+0xF09C + 'vineleafboldse' => '1000', # C+0x9D # U+0xF09D + 'circle2' => '312', # C+0x9E # U+0xF09E + 'circle4' => '457', # C+0x9F # U+0xF09F + 'square2' => '312', # C+0xA0 # U+0xF0A0 + 'ring2' => '891', # C+0xA1 # U+0xF0A1 + 'ring4' => '891', # C+0xA2 # U+0xF0A2 + 'ring6' => '891', # C+0xA3 # U+0xF0A3 + 'ringbutton2' => '891', # C+0xA4 # U+0xF0A4 + 'target' => '891', # C+0xA5 # U+0xF0A5 + 'circleshadowup' => '952', # C+0xA6 # U+0xF0A6 + 'square4' => '457', # C+0xA7 # U+0xF0A7 + 'box2' => '891', # C+0xA8 # U+0xF0A8 + 'tristar2' => '891', # C+0xA9 # U+0xF0A9 + 'crosstar2' => '891', # C+0xAA # U+0xF0AA + 'pentastar2' => '891', # C+0xAB # U+0xF0AB + 'hexstar2' => '891', # C+0xAC # U+0xF0AC + 'octastar2' => '891', # C+0xAD # U+0xF0AD + 'dodecastar3' => '891', # C+0xAE # U+0xF0AE + 'octastar4' => '891', # C+0xAF # U+0xF0AF + 'registersquare' => '891', # C+0xB0 # U+0xF0B0 + 'registercircle' => '891', # C+0xB1 # U+0xF0B1 + 'cuspopen' => '891', # C+0xB2 # U+0xF0B2 + 'cuspopen1' => '891', # C+0xB3 # U+0xF0B3 + 'query' => '891', # C+0xB4 # U+0xF0B4 + 'circlestar' => '891', # C+0xB5 # U+0xF0B5 + 'starshadow' => '891', # C+0xB6 # U+0xF0B6 + 'oneoclock' => '891', # C+0xB7 # U+0xF0B7 + 'twooclock' => '891', # C+0xB8 # U+0xF0B8 + 'threeoclock' => '891', # C+0xB9 # U+0xF0B9 + 'fouroclock' => '891', # C+0xBA # U+0xF0BA + 'fiveoclock' => '891', # C+0xBB # U+0xF0BB + 'sixoclock' => '891', # C+0xBC # U+0xF0BC + 'sevenoclock' => '891', # C+0xBD # U+0xF0BD + 'eightoclock' => '891', # C+0xBE # U+0xF0BE + 'nineoclock' => '891', # C+0xBF # U+0xF0BF + 'tenoclock' => '891', # C+0xC0 # U+0xF0C0 + 'elevenoclock' => '891', # C+0xC1 # U+0xF0C1 + 'twelveoclock' => '891', # C+0xC2 # U+0xF0C2 + 'arrowdwnleft1' => '891', # C+0xC3 # U+0xF0C3 + 'arrowdwnrt1' => '891', # C+0xC4 # U+0xF0C4 + 'arrowupleft1' => '891', # C+0xC5 # U+0xF0C5 + 'arrowuprt1' => '891', # C+0xC6 # U+0xF0C6 + 'arrowleftup1' => '1047', # C+0xC7 # U+0xF0C7 + 'arrowrtup1' => '1047', # C+0xC8 # U+0xF0C8 + 'arrowleftdwn1' => '1047', # C+0xC9 # U+0xF0C9 + 'arrowrtdwn1' => '1047', # C+0xCA # U+0xF0CA + 'quiltsquare2' => '1000', # C+0xCB # U+0xF0CB + 'quiltsquare2inv' => '1000', # C+0xCC # U+0xF0CC + 'leafccwsw' => '1000', # C+0xCD # U+0xF0CD + 'leafccwnw' => '1000', # C+0xCE # U+0xF0CE + 'leafccwse' => '1000', # C+0xCF # U+0xF0CF + 'leafccwne' => '1000', # C+0xD0 # U+0xF0D0 + 'leafnw' => '1000', # C+0xD1 # U+0xF0D1 + 'leafsw' => '1000', # C+0xD2 # U+0xF0D2 + 'leafne' => '1000', # C+0xD3 # U+0xF0D3 + 'leafse' => '1000', # C+0xD4 # U+0xF0D4 + 'deleteleft' => '1252', # C+0xD5 # U+0xF0D5 + 'deleteright' => '1252', # C+0xD6 # U+0xF0D6 + 'head2left' => '794', # C+0xD7 # U+0xF0D7 + 'head2right' => '794', # C+0xD8 # U+0xF0D8 + 'head2up' => '891', # C+0xD9 # U+0xF0D9 + 'head2down' => '891', # C+0xDA # U+0xF0DA + 'circleleft' => '891', # C+0xDB # U+0xF0DB + 'circleright' => '891', # C+0xDC # U+0xF0DC + 'circleup' => '891', # C+0xDD # U+0xF0DD + 'circledown' => '891', # C+0xDE # U+0xF0DE + 'barb2left' => '979', # C+0xDF # U+0xF0DF + 'barb2right' => '979', # C+0xE0 # U+0xF0E0 + 'barb2up' => '891', # C+0xE1 # U+0xF0E1 + 'barb2down' => '891', # C+0xE2 # U+0xF0E2 + 'barb2nw' => '775', # C+0xE3 # U+0xF0E3 + 'barb2ne' => '775', # C+0xE4 # U+0xF0E4 + 'barb2sw' => '775', # C+0xE5 # U+0xF0E5 + 'barb2se' => '775', # C+0xE6 # U+0xF0E6 + 'barb4left' => '1067', # C+0xE7 # U+0xF0E7 + 'barb4right' => '1067', # C+0xE8 # U+0xF0E8 + 'barb4up' => '891', # C+0xE9 # U+0xF0E9 + 'barb4down' => '891', # C+0xEA # U+0xF0EA + 'barb4nw' => '872', # C+0xEB # U+0xF0EB + 'barb4ne' => '872', # C+0xEC # U+0xF0EC + 'barb4sw' => '872', # C+0xED # U+0xF0ED + 'barb4se' => '872', # C+0xEE # U+0xF0EE + 'bleft' => '891', # C+0xEF # U+0xF0EF + 'bright' => '891', # C+0xF0 # U+0xF0F0 + 'bup' => '810', # C+0xF1 # U+0xF0F1 + 'bdown' => '810', # C+0xF2 # U+0xF0F2 + 'bleftright' => '1060', # C+0xF3 # U+0xF0F3 + 'bupdown' => '810', # C+0xF4 # U+0xF0F4 + 'bnw' => '781', # C+0xF5 # U+0xF0F5 + 'bne' => '781', # C+0xF6 # U+0xF0F6 + 'bsw' => '781', # C+0xF7 # U+0xF0F7 + 'bse' => '781', # C+0xF8 # U+0xF0F8 + 'bdash1' => '481', # C+0xF9 # U+0xF0F9 + 'bdash2' => '385', # C+0xFA # U+0xF0FA + 'xmarkbld' => '635', # C+0xFB # U+0xF0FB + 'checkbld' => '785', # C+0xFC # U+0xF0FC + 'boxxmarkbld' => '891', # C+0xFD # U+0xF0FD + 'boxcheckbld' => '891', # C+0xFE # U+0xF0FE + 'windowslogo' => '1034', # C+0xFF # U+0xF0FF + }, # HORIZ. WIDTH TABLE +} }; + +1; diff --git a/lib/PDF/API2/Resource/Font/CoreFont/zapfdingbats.pm b/lib/PDF/API2/Resource/Font/CoreFont/zapfdingbats.pm new file mode 100644 index 0000000..cbb5a5a --- /dev/null +++ b/lib/PDF/API2/Resource/Font/CoreFont/zapfdingbats.pm @@ -0,0 +1,494 @@ +#line 1 "PDF/API2/Resource/Font/CoreFont/zapfdingbats.pm" +#line 1 "PDF/API2/Resource/Font/CoreFont/zapfdingbats.pm" +package PDF::API2::Resource::Font::CoreFont::zapfdingbats; + +use strict; +use warnings; + +our $VERSION = '2.033'; # VERSION + +sub data { return { + 'fontname' => 'ZapfDingbats', + 'type' => 'Type1', + 'apiname' => 'Zapf', + 'ascender' => '806', + 'capheight' => '705', + 'descender' => '-198', + 'iscore' => '1', + 'isfixedpitch' => '0', + 'issymbol' => '1', + 'italicangle' => '0', + 'missingwidth' => '278', + 'stdhw' => '28', + 'stdvw' => '90', + 'underlineposition' => '-205', + 'underlinethickness' => '123', + 'xheight' => '705', + 'firstchar' => '32', + 'lastchar' => '255', + 'char' => [ # DEF. ENCODING GLYPH TABLE + '.notdef', # C+0x00 # U+0x0000 + '.notdef', # C+0x01 # U+0x0000 + '.notdef', # C+0x02 # U+0x0000 + '.notdef', # C+0x03 # U+0x0000 + '.notdef', # C+0x04 # U+0x0000 + '.notdef', # C+0x05 # U+0x0000 + '.notdef', # C+0x06 # U+0x0000 + '.notdef', # C+0x07 # U+0x0000 + '.notdef', # C+0x08 # U+0x0000 + '.notdef', # C+0x09 # U+0x0000 + '.notdef', # C+0x0A # U+0x0000 + '.notdef', # C+0x0B # U+0x0000 + '.notdef', # C+0x0C # U+0x0000 + '.notdef', # C+0x0D # U+0x0000 + '.notdef', # C+0x0E # U+0x0000 + '.notdef', # C+0x0F # U+0x0000 + '.notdef', # C+0x10 # U+0x0000 + '.notdef', # C+0x11 # U+0x0000 + '.notdef', # C+0x12 # U+0x0000 + '.notdef', # C+0x13 # U+0x0000 + '.notdef', # C+0x14 # U+0x0000 + '.notdef', # C+0x15 # U+0x0000 + '.notdef', # C+0x16 # U+0x0000 + '.notdef', # C+0x17 # U+0x0000 + '.notdef', # C+0x18 # U+0x0000 + '.notdef', # C+0x19 # U+0x0000 + '.notdef', # C+0x1A # U+0x0000 + '.notdef', # C+0x1B # U+0x0000 + '.notdef', # C+0x1C # U+0x0000 + '.notdef', # C+0x1D # U+0x0000 + '.notdef', # C+0x1E # U+0x0000 + '.notdef', # C+0x1F # U+0x0000 + 'space', # C+0x20 # U+0xF020 + 'a1', # C+0x21 # U+0xF021 + 'a2', # C+0x22 # U+0xF022 + 'a202', # C+0x23 # U+0xF023 + 'a3', # C+0x24 # U+0xF024 + 'a4', # C+0x25 # U+0xF025 + 'a5', # C+0x26 # U+0xF026 + 'a119', # C+0x27 # U+0xF027 + 'a118', # C+0x28 # U+0xF028 + 'a117', # C+0x29 # U+0xF029 + 'a11', # C+0x2A # U+0xF02A + 'a12', # C+0x2B # U+0xF02B + 'a13', # C+0x2C # U+0xF02C + 'a14', # C+0x2D # U+0xF02D + 'a15', # C+0x2E # U+0xF02E + 'a16', # C+0x2F # U+0xF02F + 'a105', # C+0x30 # U+0xF030 + 'a17', # C+0x31 # U+0xF031 + 'a18', # C+0x32 # U+0xF032 + 'a19', # C+0x33 # U+0xF033 + 'a20', # C+0x34 # U+0xF034 + 'a21', # C+0x35 # U+0xF035 + 'a22', # C+0x36 # U+0xF036 + 'a23', # C+0x37 # U+0xF037 + 'a24', # C+0x38 # U+0xF038 + 'a25', # C+0x39 # U+0xF039 + 'a26', # C+0x3A # U+0xF03A + 'a27', # C+0x3B # U+0xF03B + 'a28', # C+0x3C # U+0xF03C + 'a6', # C+0x3D # U+0xF03D + 'a7', # C+0x3E # U+0xF03E + 'a8', # C+0x3F # U+0xF03F + 'a9', # C+0x40 # U+0xF040 + 'a10', # C+0x41 # U+0xF041 + 'a29', # C+0x42 # U+0xF042 + 'a30', # C+0x43 # U+0xF043 + 'a31', # C+0x44 # U+0xF044 + 'a32', # C+0x45 # U+0xF045 + 'a33', # C+0x46 # U+0xF046 + 'a34', # C+0x47 # U+0xF047 + 'a35', # C+0x48 # U+0xF048 + 'a36', # C+0x49 # U+0xF049 + 'a37', # C+0x4A # U+0xF04A + 'a38', # C+0x4B # U+0xF04B + 'a39', # C+0x4C # U+0xF04C + 'a40', # C+0x4D # U+0xF04D + 'a41', # C+0x4E # U+0xF04E + 'a42', # C+0x4F # U+0xF04F + 'a43', # C+0x50 # U+0xF050 + 'a44', # C+0x51 # U+0xF051 + 'a45', # C+0x52 # U+0xF052 + 'a46', # C+0x53 # U+0xF053 + 'a47', # C+0x54 # U+0xF054 + 'a48', # C+0x55 # U+0xF055 + 'a49', # C+0x56 # U+0xF056 + 'a50', # C+0x57 # U+0xF057 + 'a51', # C+0x58 # U+0xF058 + 'a52', # C+0x59 # U+0xF059 + 'a53', # C+0x5A # U+0xF05A + 'a54', # C+0x5B # U+0xF05B + 'a55', # C+0x5C # U+0xF05C + 'a56', # C+0x5D # U+0xF05D + 'a57', # C+0x5E # U+0xF05E + 'a58', # C+0x5F # U+0xF05F + 'a59', # C+0x60 # U+0xF060 + 'a60', # C+0x61 # U+0xF061 + 'a61', # C+0x62 # U+0xF062 + 'a62', # C+0x63 # U+0xF063 + 'a63', # C+0x64 # U+0xF064 + 'a64', # C+0x65 # U+0xF065 + 'a65', # C+0x66 # U+0xF066 + 'a66', # C+0x67 # U+0xF067 + 'a67', # C+0x68 # U+0xF068 + 'a68', # C+0x69 # U+0xF069 + 'a69', # C+0x6A # U+0xF06A + 'a70', # C+0x6B # U+0xF06B + 'a71', # C+0x6C # U+0xF06C + 'a72', # C+0x6D # U+0xF06D + 'a73', # C+0x6E # U+0xF06E + 'a74', # C+0x6F # U+0xF06F + 'a203', # C+0x70 # U+0xF070 + 'a75', # C+0x71 # U+0xF071 + 'a204', # C+0x72 # U+0xF072 + 'a76', # C+0x73 # U+0xF073 + 'a77', # C+0x74 # U+0xF074 + 'a78', # C+0x75 # U+0xF075 + 'a79', # C+0x76 # U+0xF076 + 'a81', # C+0x77 # U+0xF077 + 'a82', # C+0x78 # U+0xF078 + 'a83', # C+0x79 # U+0xF079 + 'a84', # C+0x7A # U+0xF07A + 'a97', # C+0x7B # U+0xF07B + 'a98', # C+0x7C # U+0xF07C + 'a99', # C+0x7D # U+0xF07D + 'a100', # C+0x7E # U+0xF07E + '.notdef', # C+0x7F # U+0x0000 + 'a89', # C+0x80 # U+0xF080 + 'a90', # C+0x81 # U+0xF081 + 'a93', # C+0x82 # U+0xF082 + 'a94', # C+0x83 # U+0xF083 + 'a91', # C+0x84 # U+0xF084 + 'a92', # C+0x85 # U+0xF085 + 'a205', # C+0x86 # U+0xF086 + 'a85', # C+0x87 # U+0xF087 + 'a206', # C+0x88 # U+0xF088 + 'a86', # C+0x89 # U+0xF089 + 'a87', # C+0x8A # U+0xF08A + 'a88', # C+0x8B # U+0xF08B + 'a95', # C+0x8C # U+0xF08C + 'a96', # C+0x8D # U+0xF08D + '.notdef', # C+0x8E # U+0x0000 + '.notdef', # C+0x8F # U+0x0000 + '.notdef', # C+0x90 # U+0x0000 + '.notdef', # C+0x91 # U+0x0000 + '.notdef', # C+0x92 # U+0x0000 + '.notdef', # C+0x93 # U+0x0000 + '.notdef', # C+0x94 # U+0x0000 + '.notdef', # C+0x95 # U+0x0000 + '.notdef', # C+0x96 # U+0x0000 + '.notdef', # C+0x97 # U+0x0000 + '.notdef', # C+0x98 # U+0x0000 + '.notdef', # C+0x99 # U+0x0000 + '.notdef', # C+0x9A # U+0x0000 + '.notdef', # C+0x9B # U+0x0000 + '.notdef', # C+0x9C # U+0x0000 + '.notdef', # C+0x9D # U+0x0000 + '.notdef', # C+0x9E # U+0x0000 + '.notdef', # C+0x9F # U+0x0000 + '.notdef', # C+0xA0 # U+0x0000 + 'a101', # C+0xA1 # U+0xF0A1 + 'a102', # C+0xA2 # U+0xF0A2 + 'a103', # C+0xA3 # U+0xF0A3 + 'a104', # C+0xA4 # U+0xF0A4 + 'a106', # C+0xA5 # U+0xF0A5 + 'a107', # C+0xA6 # U+0xF0A6 + 'a108', # C+0xA7 # U+0xF0A7 + 'a112', # C+0xA8 # U+0xF0A8 + 'a111', # C+0xA9 # U+0xF0A9 + 'a110', # C+0xAA # U+0xF0AA + 'a109', # C+0xAB # U+0xF0AB + 'a120', # C+0xAC # U+0xF0AC + 'a121', # C+0xAD # U+0xF0AD + 'a122', # C+0xAE # U+0xF0AE + 'a123', # C+0xAF # U+0xF0AF + 'a124', # C+0xB0 # U+0xF0B0 + 'a125', # C+0xB1 # U+0xF0B1 + 'a126', # C+0xB2 # U+0xF0B2 + 'a127', # C+0xB3 # U+0xF0B3 + 'a128', # C+0xB4 # U+0xF0B4 + 'a129', # C+0xB5 # U+0xF0B5 + 'a130', # C+0xB6 # U+0xF0B6 + 'a131', # C+0xB7 # U+0xF0B7 + 'a132', # C+0xB8 # U+0xF0B8 + 'a133', # C+0xB9 # U+0xF0B9 + 'a134', # C+0xBA # U+0xF0BA + 'a135', # C+0xBB # U+0xF0BB + 'a136', # C+0xBC # U+0xF0BC + 'a137', # C+0xBD # U+0xF0BD + 'a138', # C+0xBE # U+0xF0BE + 'a139', # C+0xBF # U+0xF0BF + 'a140', # C+0xC0 # U+0xF0C0 + 'a141', # C+0xC1 # U+0xF0C1 + 'a142', # C+0xC2 # U+0xF0C2 + 'a143', # C+0xC3 # U+0xF0C3 + 'a144', # C+0xC4 # U+0xF0C4 + 'a145', # C+0xC5 # U+0xF0C5 + 'a146', # C+0xC6 # U+0xF0C6 + 'a147', # C+0xC7 # U+0xF0C7 + 'a148', # C+0xC8 # U+0xF0C8 + 'a149', # C+0xC9 # U+0xF0C9 + 'a150', # C+0xCA # U+0xF0CA + 'a151', # C+0xCB # U+0xF0CB + 'a152', # C+0xCC # U+0xF0CC + 'a153', # C+0xCD # U+0xF0CD + 'a154', # C+0xCE # U+0xF0CE + 'a155', # C+0xCF # U+0xF0CF + 'a156', # C+0xD0 # U+0xF0D0 + 'a157', # C+0xD1 # U+0xF0D1 + 'a158', # C+0xD2 # U+0xF0D2 + 'a159', # C+0xD3 # U+0xF0D3 + 'a160', # C+0xD4 # U+0xF0D4 + 'a161', # C+0xD5 # U+0xF0D5 + 'a163', # C+0xD6 # U+0xF0D6 + 'a164', # C+0xD7 # U+0xF0D7 + 'a196', # C+0xD8 # U+0xF0D8 + 'a165', # C+0xD9 # U+0xF0D9 + 'a192', # C+0xDA # U+0xF0DA + 'a166', # C+0xDB # U+0xF0DB + 'a167', # C+0xDC # U+0xF0DC + 'a168', # C+0xDD # U+0xF0DD + 'a169', # C+0xDE # U+0xF0DE + 'a170', # C+0xDF # U+0xF0DF + 'a171', # C+0xE0 # U+0xF0E0 + 'a172', # C+0xE1 # U+0xF0E1 + 'a173', # C+0xE2 # U+0xF0E2 + 'a162', # C+0xE3 # U+0xF0E3 + 'a174', # C+0xE4 # U+0xF0E4 + 'a175', # C+0xE5 # U+0xF0E5 + 'a176', # C+0xE6 # U+0xF0E6 + 'a177', # C+0xE7 # U+0xF0E7 + 'a178', # C+0xE8 # U+0xF0E8 + 'a179', # C+0xE9 # U+0xF0E9 + 'a193', # C+0xEA # U+0xF0EA + 'a180', # C+0xEB # U+0xF0EB + 'a199', # C+0xEC # U+0xF0EC + 'a181', # C+0xED # U+0xF0ED + 'a200', # C+0xEE # U+0xF0EE + 'a182', # C+0xEF # U+0xF0EF + '.notdef', # C+0xF0 # U+0x0000 + 'a201', # C+0xF1 # U+0xF0F1 + 'a183', # C+0xF2 # U+0xF0F2 + 'a184', # C+0xF3 # U+0xF0F3 + 'a197', # C+0xF4 # U+0xF0F4 + 'a185', # C+0xF5 # U+0xF0F5 + 'a194', # C+0xF6 # U+0xF0F6 + 'a198', # C+0xF7 # U+0xF0F7 + 'a186', # C+0xF8 # U+0xF0F8 + 'a195', # C+0xF9 # U+0xF0F9 + 'a187', # C+0xFA # U+0xF0FA + 'a188', # C+0xFB # U+0xF0FB + 'a189', # C+0xFC # U+0xF0FC + 'a190', # C+0xFD # U+0xF0FD + 'a191', # C+0xFE # U+0xF0FE + '.notdef', # C+0xFF # U+0x0000 + ], # DEF. ENCODING GLYPH TABLE + 'fontbbox' => [ 0, -143, 981, 820 ], + 'wx' => { # HORIZ. WIDTH TABLE + 'space' => 278, + 'a1' => 974, + 'a10' => 692, + 'a100' => 668, + 'a101' => 732, + 'a102' => 544, + 'a103' => 544, + 'a104' => 910, + 'a105' => 911, + 'a106' => 667, + 'a107' => 760, + 'a108' => 760, + 'a109' => 626, + 'a11' => 960, + 'a110' => 694, + 'a111' => 595, + 'a112' => 776, + 'a117' => 690, + 'a118' => 791, + 'a119' => 790, + 'a12' => 939, + 'a120' => 788, + 'a121' => 788, + 'a122' => 788, + 'a123' => 788, + 'a124' => 788, + 'a125' => 788, + 'a126' => 788, + 'a127' => 788, + 'a128' => 788, + 'a129' => 788, + 'a13' => 549, + 'a130' => 788, + 'a131' => 788, + 'a132' => 788, + 'a133' => 788, + 'a134' => 788, + 'a135' => 788, + 'a136' => 788, + 'a137' => 788, + 'a138' => 788, + 'a139' => 788, + 'a14' => 855, + 'a140' => 788, + 'a141' => 788, + 'a142' => 788, + 'a143' => 788, + 'a144' => 788, + 'a145' => 788, + 'a146' => 788, + 'a147' => 788, + 'a148' => 788, + 'a149' => 788, + 'a15' => 911, + 'a150' => 788, + 'a151' => 788, + 'a152' => 788, + 'a153' => 788, + 'a154' => 788, + 'a155' => 788, + 'a156' => 788, + 'a157' => 788, + 'a158' => 788, + 'a159' => 788, + 'a16' => 933, + 'a160' => 894, + 'a161' => 838, + 'a162' => 924, + 'a163' => 1016, + 'a164' => 458, + 'a165' => 924, + 'a166' => 918, + 'a167' => 927, + 'a168' => 928, + 'a169' => 928, + 'a17' => 945, + 'a170' => 834, + 'a171' => 873, + 'a172' => 828, + 'a173' => 924, + 'a174' => 917, + 'a175' => 930, + 'a176' => 931, + 'a177' => 463, + 'a178' => 883, + 'a179' => 836, + 'a18' => 974, + 'a180' => 867, + 'a181' => 696, + 'a182' => 874, + 'a183' => 760, + 'a184' => 946, + 'a185' => 865, + 'a186' => 967, + 'a187' => 831, + 'a188' => 873, + 'a189' => 927, + 'a19' => 755, + 'a190' => 970, + 'a191' => 918, + 'a192' => 748, + 'a193' => 836, + 'a194' => 771, + 'a195' => 888, + 'a196' => 748, + 'a197' => 771, + 'a198' => 888, + 'a199' => 867, + 'a2' => 961, + 'a20' => 846, + 'a200' => 696, + 'a201' => 874, + 'a202' => 974, + 'a203' => 762, + 'a204' => 759, + 'a205' => 509, + 'a206' => 410, + 'a21' => 762, + 'a22' => 761, + 'a23' => 571, + 'a24' => 677, + 'a25' => 763, + 'a26' => 760, + 'a27' => 759, + 'a28' => 754, + 'a29' => 786, + 'a3' => 980, + 'a30' => 788, + 'a31' => 788, + 'a32' => 790, + 'a33' => 793, + 'a34' => 794, + 'a35' => 816, + 'a36' => 823, + 'a37' => 789, + 'a38' => 841, + 'a39' => 823, + 'a4' => 719, + 'a40' => 833, + 'a41' => 816, + 'a42' => 831, + 'a43' => 923, + 'a44' => 744, + 'a45' => 723, + 'a46' => 749, + 'a47' => 790, + 'a48' => 792, + 'a49' => 695, + 'a5' => 789, + 'a50' => 776, + 'a51' => 768, + 'a52' => 792, + 'a53' => 759, + 'a54' => 707, + 'a55' => 708, + 'a56' => 682, + 'a57' => 701, + 'a58' => 826, + 'a59' => 815, + 'a6' => 494, + 'a60' => 789, + 'a61' => 789, + 'a62' => 707, + 'a63' => 687, + 'a64' => 696, + 'a65' => 689, + 'a66' => 786, + 'a67' => 787, + 'a68' => 713, + 'a69' => 791, + 'a7' => 552, + 'a70' => 785, + 'a71' => 791, + 'a72' => 873, + 'a73' => 761, + 'a74' => 762, + 'a75' => 759, + 'a76' => 892, + 'a77' => 892, + 'a78' => 788, + 'a79' => 784, + 'a8' => 537, + 'a81' => 438, + 'a82' => 138, + 'a83' => 277, + 'a84' => 415, + 'a85' => 509, + 'a86' => 410, + 'a87' => 234, + 'a88' => 234, + 'a89' => 390, + 'a9' => 577, + 'a90' => 390, + 'a91' => 276, + 'a92' => 276, + 'a93' => 317, + 'a94' => 317, + 'a95' => 334, + 'a96' => 334, + 'a97' => 392, + 'a98' => 392, + 'a99' => 668, + }, # HORIZ. WIDTH TABLE +} }; + +1; diff --git a/lib/PDF/API2/Resource/Font/Postscript.pm b/lib/PDF/API2/Resource/Font/Postscript.pm new file mode 100644 index 0000000..b63efd3 --- /dev/null +++ b/lib/PDF/API2/Resource/Font/Postscript.pm @@ -0,0 +1,499 @@ +#line 1 "PDF/API2/Resource/Font/Postscript.pm" +#line 1 "PDF/API2/Resource/Font/Postscript.pm" +package PDF::API2::Resource::Font::Postscript; + +use base 'PDF::API2::Resource::Font'; + +use strict; +no warnings qw[ deprecated recursion uninitialized ]; + +our $VERSION = '2.033'; # VERSION + +use Encode qw(:all); +use IO::File qw(); + +use PDF::API2::Util; +use PDF::API2::Basic::PDF::Utils; + +sub new { + my ($class, $pdf, $psfile, %opts) = @_; + my ($self,$encoding); + my (@w,$data); + + if(defined $opts{-afmfile}) { + $data = $class->readAFM($opts{-afmfile}); + } elsif(defined $opts{-pfmfile}) { + $data = $class->readPFM($opts{-pfmfile}); + } elsif(defined $opts{-xfmfile}) { + $data = $class->readXFM($opts{-xfmfile}); + } else { + die "no proper font-metrics file specified for '$psfile'."; + } + + $class = ref $class if ref $class; + $self = $class->SUPER::new($pdf, $data->{apiname}.pdfkey().'~'.time()); + $pdf->new_obj($self) unless($self->is_obj($pdf)); + $self->{' data'}=$data; + + if($opts{-pdfname}) { + $self->name($opts{-pdfname}); + } + + $self->{'Subtype'} = PDFName("Type1"); + $self->{'FontDescriptor'}=$self->descrByData(); + if(-f $psfile) + { + $self->{'BaseFont'} = PDFName(pdfkey().'+'.($self->fontname).'~'.time()); + + my ($l1,$l2,$l3,$stream)=$self->readPFAPFB($psfile); + + my $s = PDFDict(); + $self->{'FontDescriptor'}->{'FontFile'} = $s; + $s->{'Length1'} = PDFNum($l1); + $s->{'Length2'} = PDFNum($l2); + $s->{'Length3'} = PDFNum($l3); + $s->{'Filter'} = PDFArray(PDFName("FlateDecode")); + $s->{' stream'} = $stream; + if(defined $pdf) { + $pdf->new_obj($s); + } + } + else + { + $self->{'BaseFont'} = PDFName($self->fontname); + } + + $self->encodeByData($opts{-encode}); + + $self->{-nocomps}=1 if($opts{-nocomps}); + $self->{-dokern}=1 if($opts{-dokern}); + + return($self); +} + +sub readPFAPFB { + my ($self,$file) = @_; + my ($l1,$l2,$l3,$stream,$t1stream,@lines,$line,$head,$body,$tail); + + die "cannot find font '$file' ..." unless(-f $file); + + my $l=-s $file; + + open(my $inf, "<", $file) or die "$!: $file"; + binmode($inf,':raw'); + read($inf,$line,2); + @lines=unpack('C*',$line); + if(($lines[0]==0x80) && ($lines[1]==1)) { + read($inf,$line,4); + $l1=unpack('V',$line); + seek($inf,$l1,1); + read($inf,$line,2); + @lines=unpack('C*',$line); + if(($lines[0]==0x80) && ($lines[1]==2)) { + read($inf,$line,4); + $l2=unpack('V',$line); + } else { + die "corrupt pfb in file '$file' at marker='2'."; + } + seek($inf,$l2,1); + read($inf,$line,2); + @lines=unpack('C*',$line); + if(($lines[0]==0x80) && ($lines[1]==1)) { + read($inf,$line,4); + $l3=unpack('V',$line); + } else { + die "corrupt pfb in file '$file' at marker='3'."; + } + seek($inf,0,0); + @lines=<$inf>; + $stream=join('',@lines); + $t1stream=substr($stream,6,$l1); + $t1stream.=substr($stream,12+$l1,$l2); + $t1stream.=substr($stream,18+$l1+$l2,$l3); + } elsif($line eq '%!') { + seek($inf,0,0); + while($line=<$inf>) { + if(!$l1) { + $head.=$line; + if($line=~/eexec$/){ + chomp($head); + $head.="\x0d"; + $l1=length($head); + } + } elsif(!$l2) { + if($line=~/^0+$/) { + $l2=length($body); + $tail=$line; + } else { + chomp($line); + $body.=pack('H*',$line); + } + } else { + $tail.=$line; + } + } + $l3=length($tail); + $t1stream="$head$body$tail"; + } else { + die "unsupported font-format in file '$file' at marker='1'."; + } + close($inf); + + return($l1,$l2,$l3,$t1stream); +} + + +# $datahashref = $self->readAFM( $afmfile ); + +sub readAFM +{ + my ($self,$file)=@_; + my $data={}; + $data->{wx}={}; + $data->{bbox}={}; + $data->{char}=[]; + $data->{firstchar}=255; + $data->{lastchar}=0; + + if(! -e $file) {die "file='$file' not existant.";} + open(my $afmf, "<", $file) or die "Can't find the AFM file for $file"; + local($/, $_) = ("\n", undef); # ensure correct $INPUT_RECORD_SEPARATOR + while ($_=<$afmf>) + { + if (/^StartCharMetrics/ .. /^EndCharMetrics/) + { + # only lines that start with "C" or "CH" are parsed + next unless $_=~/^CH?\s/; + my($ch) = $_=~/^CH?\s+(\d+)\s*;/; + $ch=$ch||0; + my($name) = $_=~/\bN\s+(\.?\w+)\s*;/; + my($wx) = $_=~/\bWX\s+(\d+)\s*;/; + my($bbox) = $_=~/\bB\s+([^;]+);/; + $bbox =~ s/\s+$//; + # Should also parse lingature data (format: L successor lignature) + $data->{avgwidth2} += $wx ; + $data->{maxwidth} = $data->{maxwidth}<$wx ? $wx : $data->{maxwidth}; + $data->{wx}->{$name} = $wx ; + $data->{bbox}->{$name} = [split(/\s+/,$bbox)]; + if($ch>0) { + $data->{'char'}->[$ch]=$name ; + } + $data->{lastchar} = $data->{lastchar}<$ch ? $ch : $data->{lastchar}; + $data->{firstchar} = $data->{firstchar}>$ch ? $ch : $data->{firstchar}; + next; + } + elsif(/^StartKernData/ .. /^EndKernData/) + { + $data->{kern}||={}; + if($_=~m|^KPX\s+(\S+)\s+(\S+)\s+(\S+)\s*$|i) + { + $data->{kern}->{"$1:$2"}=$3; + } + } + elsif(/^StartComposites/ .. /^EndComposites/) + { + $data->{comps}||={}; + if($_=~m|^CC\s+(\S+)\s+(\S+)\s+;|i) + { + my ($name,$comp)=($1,$2); + my @cv=split(/;/,$_); + shift @cv; + my $rng=[]; + foreach (1..$comp) + { + my @c1=split(/\s+/,shift @cv); + push @{$rng},$c1[1],$c1[2],$c1[3]; + } + $data->{comps}->{$name}=$rng; + } + } + last if $_=~/^EndFontMetrics/; + if (/(^\w+)\s+(.*)/) + { + my($key,$val) = ($1, $2); + $key = lc $key; + if (defined $data->{$key}) + { + # $data->{$key} = [ $data->{$key} ] unless ref $data->{$key}; + # push(@{$data->{$key}}, $val); + } + else + { + $val=~s/[\x00\x1f]+//g; + $data->{$key} = $val; + } + } + else + { + ## print STDERR "Can't parse: $_"; + } + } + close($afmf); + unless (exists $data->{wx}->{'.notdef'}) + { + $data->{wx}->{'.notdef'} = 0; + $data->{bbox}{'.notdef'} = [0, 0, 0, 0]; + } + + $data->{avgwidth2} /= scalar keys %{$data->{bbox}} ; + $data->{avgwidth2} = int($data->{avgwidth2}); + + $data->{fontname}=~s/[\x00-\x20]+//og; + ## $data->{fontname}=~s/[^A-Za-z0-9]+//og; + + if(defined $data->{fullname}) + { + $data->{altname}=$data->{fullname}; + } + else + { + $data->{altname}=$data->{familyname}; + $data->{altname}.=' Italic' if($data->{italicangle}<0); + $data->{altname}.=' Oblique' if($data->{italicangle}>0); + $data->{altname}.=' '.$data->{weight}; + } + $data->{apiname}=$data->{altname}; + $data->{altname}=~s/[^A-Za-z0-9]+//og; + + $data->{subname}=$data->{weight}; + $data->{subname}.=' Italic' if($data->{italicangle}<0); + $data->{subname}.=' Oblique' if($data->{italicangle}>0); + $data->{subname}=~s/[^A-Za-z0-9]+//og; + + $data->{missingwidth}||=$data->{avgwidth2}; + + $data->{issymbol} = 0; + $data->{fontbbox} = [ split(/\s+/,$data->{fontbbox}) ]; + + $data->{apiname}=join('', map { ucfirst(lc(substr($_, 0, 2))) } split m/[^A-Za-z0-9\s]+/, $data->{apiname}); + + $data->{flags} = 34; + + $data->{uni}||=[]; + foreach my $n (0..255) + { + $data->{uni}->[$n]=uniByName($data->{char}->[$n] || '.notdef') || 0; + } + delete $data->{bbox}; + + return($data); +} + +sub readPFM { + my ($self,$file)=@_; + if(! -e $file) {die "pfmfile='$file' not existant.";} + my $fh=IO::File->new(); + my $data={}; + + $data->{issymbol} = 0; + + $data->{wx}={}; + $data->{bbox}={}; + $data->{kern}={}; + $data->{char}=[]; + + my $buf; + open($fh, "<", $file) || return; + binmode($fh,':raw'); + read($fh,$buf,117 + 30); + + my %df; + # Packing structure for PFM Header + ( $df{Version}, + $df{Size}, + $df{Copyright}, + $df{Type}, + $df{Point}, + $df{VertRes}, + $df{HorizRes}, + $df{Ascent}, + $df{InternalLeading}, + $df{ExternalLeading}, + $df{Italic}, + $df{Underline}, + $df{StrikeOut}, + $df{Weight}, +#define FW_DONTCARE 0 +#define FW_THIN 100 +#define FW_EXTRALIGHT 200 +#define FW_ULTRALIGHT FW_EXTRALIGHT +#define FW_LIGHT 300 +#define FW_NORMAL 400 +#define FW_REGULAR 400 +#define FW_MEDIUM 500 +#define FW_SEMIBOLD 600 +#define FW_DEMIBOLD FW_SEMIBOLD +#define FW_BOLD 700 +#define FW_EXTRABOLD 800 +#define FW_ULTRABOLD FW_EXTRABOLD +#define FW_HEAVY 900 +#define FW_BLACK FW_HEAVY + $df{CharSet}, +#define ANSI_CHARSET 0 +#define DEFAULT_CHARSET 1 +#define SYMBOL_CHARSET 2 +#define SHIFTJIS_CHARSET 128 +#define HANGEUL_CHARSET 129 +#define HANGUL_CHARSET 129 +#define GB2312_CHARSET 134 +#define CHINESEBIG5_CHARSET 136 +#define GREEK_CHARSET 161 +#define TURKISH_CHARSET 162 +#define HEBREW_CHARSET 177 +#define ARABIC_CHARSET 178 +#define BALTIC_CHARSET 186 +#define RUSSIAN_CHARSET 204 +#define THAI_CHARSET 222 +#define EASTEUROPE_CHARSET 238 +#define OEM_CHARSET 255 +#define JOHAB_CHARSET 130 +#define VIETNAMESE_CHARSET 163 +#define MAC_CHARSET 77 +#define BALTIC_CHARSET 186 +#define JOHAB_CHARSET 130 +#define VIETNAMESE_CHARSET 163 + $df{PixWidth}, + $df{PixHeight}, + $df{PitchAndFamily}, +#define DEFAULT_PITCH 0 +#define FIXED_PITCH 1 +#define VARIABLE_PITCH 2 +#define MONO_FONT 8 +#define FF_DECORATIVE 80 +#define FF_DONTCARE 0 +#define FF_MODERN 48 +#define FF_ROMAN 16 +#define FF_SCRIPT 64 +#define FF_SWISS 32 + $df{AvgWidth}, + $df{MaxWidth}, + $df{FirstChar}, + $df{LastChar}, + $df{DefaultChar}, + $df{BreakChar}, + $df{WidthBytes}, + $df{Device}, + $df{Face}, + $df{BitsPointer}, + $df{BitsOffset}, + $df{SizeFields}, # Two bytes, the size of extension section + $df{ExtMetricsOffset}, # Four bytes, offset value to the 'Extended Text Metrics' section + $df{ExtentTable}, # Four bytes Offset value to the Extent Table + $df{OriginTable}, # Four bytes 0 + $df{PairKernTable}, # Four bytes 0 + $df{TrackKernTable}, # Four bytes 0 + $df{DriverInfo}, # Four bytes Offset value to the PostScript font name string + $df{Reserved}, # Four bytes 0 + ) = unpack("vVa60vvvvvvvCCCvCvvCvvCCCCvVVVV vVVVVVVV",$buf); # PFM Header + Ext + + seek($fh,$df{Device},0); + read($fh,$buf,250); + + ($df{postScript}) = unpack("Z*",$buf); + $buf=substr($buf,length($df{postScript})+1,250); + ($df{windowsName}) = unpack("Z*",$buf); + $buf=substr($buf,length($df{windowsName})+1,250); + ($df{psName}) = unpack("Z*",$buf); + + seek($fh,$df{ExtMetricsOffset},0); + read($fh,$buf,52); + + ( $df{etmSize}, + $df{PointSize}, + $df{Orientation}, + $df{MasterHeight}, + $df{MinScale}, + $df{MaxScale}, + $df{MasterUnits}, + $df{CapHeight}, + $df{xHeight}, + $df{LowerCaseAscent}, + $df{LowerCaseDescent}, + $df{Slant}, + $df{SuperScript}, + $df{SubScript}, + $df{SuperScriptSize}, + $df{SubScriptSize}, + $df{UnderlineOffset}, + $df{UnderlineWidth}, + $df{DoubleUpperUnderlineOffset}, + $df{DoubleLowerUnderlineOffset}, + $df{DoubleUpperUnderlineWidth}, + $df{DoubleLowerUnderlineWidth}, + $df{StrikeOutOffset}, + $df{StrikeOutWidth}, + $df{KernPairs}, + $df{KernTracks} ) = unpack('v*',$buf); + + $data->{fontname}=$df{psName}; + $data->{fontname}=~s/[^A-Za-z0-9]+//og; + $data->{apiname}=join('', map { ucfirst(lc(substr($_, 0, 2))) } split m/[^A-Za-z0-9\s]+/, $df{windowsName}); + + $data->{upem}=1000; + + $data->{fontbbox}=[-100,-100,$df{MaxWidth},$df{Ascent}]; + + $data->{stemv}=0; + $data->{stemh}=0; + + $data->{lastchar}=$df{LastChar}; + $data->{firstchar}=$df{FirstChar}; + + $data->{missingwidth}=$df{AvgWidth}; + $data->{maxwidth}=$df{MaxWidth}; + $data->{ascender}=$df{Ascent}; + $data->{descender}=-$df{LowerCaseDescent}; + + $data->{flags} = 0; + # FixedPitch 1 + $data->{flags} |= 1 if((($df{PitchAndFamily} & 1) || ($df{PitchAndFamily} & 8)) && !($df{PitchAndFamily} & 2)); + # Serif 2 + $data->{flags} |= 2 if(($df{PitchAndFamily} & 16) && !($df{PitchAndFamily} & 32)); + # Symbolic 4 + $data->{flags} |= 4 if($df{PitchAndFamily} & 80); + # Script 8 + $data->{flags} |= 8 if($df{PitchAndFamily} & 64); + # Nonsymbolic 32 + $data->{flags} |= 32 unless($df{PitchAndFamily} & 80); + # Italic 64 + $data->{flags} |= 64 if($df{Italic}); + + #bit 17 AllCap + #bit 18 SmallCap + #bit 19 ForceBold + + $data->{capheight}=$df{CapHeight}; + $data->{xheight}=$df{xHeight}; + + $data->{uni}=[ unpack('U*',decode('cp1252',pack('C*',(0..255)))) ]; + $data->{char}=[ map { nameByUni($_) || '.notdef' } @{$data->{uni}} ]; + + $data->{italicangle}=-12*$df{Italic}; + $data->{isfixedpitch}=(($df{PitchAndFamily} & 8) || ($df{PitchAndFamily} & 1)); + $data->{underlineposition}=-$df{UnderlineOffset}; + $data->{underlinethickness}=$df{UnderlineWidth}; + + seek($fh,$df{ExtentTable},0); + + foreach my $k ($df{FirstChar} .. $df{LastChar}) { + read($fh,$buf,2); + my ($wx)=unpack('v',$buf); + $data->{wx}->{$data->{char}->[$k]}=$wx; +# print STDERR "e: c=$k n='".$data->{char}->[$k]."' wx='$wx'\n"; + } + $data->{pfm}=\%df; + close($fh); + + return($data); +} + +sub readXFM { + my ($class,$xfmfile) = @_; + die "cannot find font '$xfmfile' ..." unless(-f $xfmfile); + + my $data={}; + + return($data); +} + +1; diff --git a/lib/PDF/API2/Resource/Font/SynFont.pm b/lib/PDF/API2/Resource/Font/SynFont.pm new file mode 100644 index 0000000..f0c891e --- /dev/null +++ b/lib/PDF/API2/Resource/Font/SynFont.pm @@ -0,0 +1,197 @@ +#line 1 "PDF/API2/Resource/Font/SynFont.pm" +#line 1 "PDF/API2/Resource/Font/SynFont.pm" +package PDF::API2::Resource::Font::SynFont; + +use base 'PDF::API2::Resource::Font'; + +use strict; +no warnings qw[ deprecated recursion uninitialized ]; + +our $VERSION = '2.033'; # VERSION + +use Math::Trig; +use Unicode::UCD 'charinfo'; + +use PDF::API2::Util; +use PDF::API2::Basic::PDF::Utils; + +#line 34 + +#line 40 + +#line 72 + +sub new +{ + my ($class,$pdf,$font,@opts) = @_; + my ($self,$data); + my %opts=@opts; + my $first=1; + my $last=255; + my $slant=$opts{-slant}||1; + my $oblique=$opts{-oblique}||0; + my $space=$opts{-space}||'0'; + my $bold=($opts{-bold}||0)*10; # convert to em + + $self->{' slant'}=$slant; + $self->{' oblique'}=$oblique; + $self->{' bold'}=$bold; + $self->{' boldmove'}=0.001; + $self->{' space'}=$space; + + $class = ref $class if ref $class; + $self = $class->SUPER::new($pdf, + pdfkey() + .'+'.($font->name) + .($opts{-caps} ? '+Caps' : '') + .($opts{-vname} ? '+'.$opts{-vname} : '') + ); + $pdf->new_obj($self) unless($self->is_obj($pdf)); + $self->{' font'}=$font; + $self->{' data'}={ + 'type' => 'Type3', + 'ascender' => $font->ascender, + 'capheight' => $font->capheight, + 'descender' => $font->descender, + 'iscore' => '0', + 'isfixedpitch' => $font->isfixedpitch, + 'italicangle' => $font->italicangle + $oblique, + 'missingwidth' => $font->missingwidth * $slant, + 'underlineposition' => $font->underlineposition, + 'underlinethickness' => $font->underlinethickness, + 'xheight' => $font->xheight, + 'firstchar' => $first, + 'lastchar' => $last, + 'char' => [ '.notdef' ], + 'uni' => [ 0 ], + 'u2e' => { 0 => 0 }, + 'fontbbox' => '', + 'wx' => { 'space' => '600' }, + }; + + if(ref($font->fontbbox)) + { + $self->data->{fontbbox}=[ @{$font->fontbbox} ]; + } + else + { + $self->data->{fontbbox}=[ $font->fontbbox ]; + } + $self->data->{fontbbox}->[0]*=$slant; + $self->data->{fontbbox}->[2]*=$slant; + + $self->{'Subtype'} = PDFName('Type3'); + $self->{'FirstChar'} = PDFNum($first); + $self->{'LastChar'} = PDFNum($last); + $self->{'FontMatrix'} = PDFArray(map { PDFNum($_) } ( 0.001, 0, 0, 0.001, 0, 0 ) ); + $self->{'FontBBox'} = PDFArray(map { PDFNum($_) } ( $self->fontbbox ) ); + + my $procs=PDFDict(); + $pdf->new_obj($procs); + $self->{'CharProcs'} = $procs; + + $self->{Resources}=PDFDict(); + $self->{Resources}->{ProcSet}=PDFArray(map { PDFName($_) } qw[ PDF Text ImageB ImageC ImageI ]); + my $xo=PDFDict(); + $self->{Resources}->{Font}=$xo; + $self->{Resources}->{Font}->{FSN}=$font; + foreach my $w ($first..$last) + { + $self->data->{char}->[$w]=$font->glyphByEnc($w); + $self->data->{uni}->[$w]=uniByName($self->data->{char}->[$w]); + $self->data->{u2e}->{$self->data->{uni}->[$w]}=$w; + } + + if($font->isa('PDF::API2::Resource::CIDFont')) + { + $self->{'Encoding'}=PDFDict(); + $self->{'Encoding'}->{Type}=PDFName('Encoding'); + $self->{'Encoding'}->{Differences}=PDFArray(); + foreach my $w ($first..$last) + { + if(defined $self->data->{char}->[$w] && $self->data->{char}->[$w] ne '.notdef') + { + $self->{'Encoding'}->{Differences}->add_elements(PDFNum($w),PDFName($self->data->{char}->[$w])); + } + } + } + else + { + $self->{'Encoding'}=$font->{Encoding}; + } + + my @widths=(); + foreach my $w ($first..$last) + { + if($self->data->{char}->[$w] eq '.notdef') + { + push @widths,$self->missingwidth; + next; + } + my $char=PDFDict(); + my $wth=int($font->width(chr($w))*1000*$slant+2*$space); + $procs->{$font->glyphByEnc($w)}=$char; + #$char->{Filter}=PDFArray(PDFName('FlateDecode')); + $char->{' stream'}=$wth." 0 ".join(' ',map { int($_) } $self->fontbbox)." d1\n"; + $char->{' stream'}.="BT\n"; + $char->{' stream'}.=join(' ',1,0,tan(deg2rad($oblique)),1,0,0)." Tm\n" if($oblique); + $char->{' stream'}.="2 Tr ".($bold)." w\n" if($bold); + # my $ci = charinfo($self->data->{uni}->[$w]); + my $ci={}; + if ($self->data->{uni}->[$w] ne '') + { + $ci = charinfo($self->data->{uni}->[$w]); + } + if($opts{-caps} && $ci->{upper}) + { + $char->{' stream'}.="/FSN 800 Tf\n"; + $char->{' stream'}.=($slant*110)." Tz\n"; + $char->{' stream'}.=" [ -$space ] TJ\n" if($space); + my $ch=$self->encByUni(hex($ci->{upper})); + $wth=int($font->width(chr($ch))*800*$slant*1.1+2*$space); + $char->{' stream'}.=$font->text(chr($ch)); + } + else + { + $char->{' stream'}.="/FSN 1000 Tf\n"; + $char->{' stream'}.=($slant*100)." Tz\n" if($slant!=1); + $char->{' stream'}.=" [ -$space ] TJ\n" if($space); + $char->{' stream'}.=$font->text(chr($w)); + } + $char->{' stream'}.=" Tj\nET\n"; + push @widths,$wth; + $self->data->{wx}->{$font->glyphByEnc($w)}=$wth; + $pdf->new_obj($char); + } + + $procs->{'.notdef'}=$procs->{$font->data->{char}->[32]}; + $self->{Widths}=PDFArray(map { PDFNum($_) } @widths); + $self->data->{e2n}=$self->data->{char}; + $self->data->{e2u}=$self->data->{uni}; + + $self->data->{u2c}={}; + $self->data->{u2e}={}; + $self->data->{u2n}={}; + $self->data->{n2c}={}; + $self->data->{n2e}={}; + $self->data->{n2u}={}; + + foreach my $n (reverse 0..255) + { + $self->data->{n2c}->{$self->data->{char}->[$n] || '.notdef'}=$n unless(defined $self->data->{n2c}->{$self->data->{char}->[$n] || '.notdef'}); + $self->data->{n2e}->{$self->data->{e2n}->[$n] || '.notdef'}=$n unless(defined $self->data->{n2e}->{$self->data->{e2n}->[$n] || '.notdef'}); + + $self->data->{n2u}->{$self->data->{e2n}->[$n] || '.notdef'}=$self->data->{e2u}->[$n] unless(defined $self->data->{n2u}->{$self->data->{e2n}->[$n] || '.notdef'}); + $self->data->{n2u}->{$self->data->{char}->[$n] || '.notdef'}=$self->data->{uni}->[$n] unless(defined $self->data->{n2u}->{$self->data->{char}->[$n] || '.notdef'}); + + $self->data->{u2c}->{$self->data->{uni}->[$n]}=$n unless(defined $self->data->{u2c}->{$self->data->{uni}->[$n]}); + $self->data->{u2e}->{$self->data->{e2u}->[$n]}=$n unless(defined $self->data->{u2e}->{$self->data->{e2u}->[$n]}); + + $self->data->{u2n}->{$self->data->{e2u}->[$n]}=($self->data->{e2n}->[$n] || '.notdef') unless(defined $self->data->{u2n}->{$self->data->{e2u}->[$n]}); + $self->data->{u2n}->{$self->data->{uni}->[$n]}=($self->data->{char}->[$n] || '.notdef') unless(defined $self->data->{u2n}->{$self->data->{uni}->[$n]}); + } + + return($self); +} + +1; diff --git a/lib/PDF/API2/Resource/Glyphs.pm b/lib/PDF/API2/Resource/Glyphs.pm new file mode 100644 index 0000000..e73ca94 --- /dev/null +++ b/lib/PDF/API2/Resource/Glyphs.pm @@ -0,0 +1,9782 @@ +#line 1 "PDF/API2/Resource/Glyphs.pm" +#line 1 "PDF/API2/Resource/Glyphs.pm" +package PDF::API2::Resource::Glyphs; + +use strict; +use warnings; + +our $VERSION = '2.033'; # VERSION + +# The data in this file is generated from uniglyph.txt. In earlier +# versions of PDF::API2, this file was parsed and sorted every time +# the module was loaded, which was inefficient. +# +# There's probably a way to remove this information from the module +# altogether, but in the meantime, the file now only needs to be +# parsed when it changes. +# +# If uniglyph.txt changes, use _generate to create new hashes, and +# paste the output into this file. + +sub _generate { + my $uniglyph_file = shift(); + die 'uniglyph.txt not found' unless -f $uniglyph_file; + + my $fh; + open $fh, '<', $uniglyph_file; + my $uuu = {}; + while (my $line = <$fh>) { + next if $line =~ m|^#|; + chomp $line; + $line =~ s|\s+\#.+$||go; + my ($uni, $name, $prio) = split(/\s+;\s+/, $line); + $uni = hex($uni); + $uuu->{u}->{$uni} ||= []; + $uuu->{g}->{$name} ||= []; + push @{$uuu->{u}->{$uni}}, { uni => $uni, name => $name, prio => $prio }; + push @{$uuu->{g}->{$name}}, { uni => $uni, name => $name, prio => $prio }; + } + close($fh); + + my %u2n; + foreach my $k (keys %{$uuu->{u}}) { + $u2n{$k} = $uuu->{u}->{$k}->[0]->{'name'}; + } + print "our \$u2n = {\n"; + foreach my $key (sort { $a <=> $b } keys %u2n) { + print " '$key' => '$u2n{$key}',\n"; + } + print "};\n\n"; + + my %n2u; + foreach my $k (keys %{$uuu->{g}}) { + my ($r) = sort { $a->{prio} <=> $b->{prio}} @{$uuu->{g}->{$k}}; + $n2u{$k} = $r->{'uni'}; + } + print "our \$n2u = {\n"; + foreach my $key (sort { $a cmp $b } keys %n2u) { + print " '$key' => '$n2u{$key}',\n"; + } + print "};\n\n"; +} + +our $u2n = { + '0' => '.notdef', + '1' => 'acute', + '2' => 'caron', + '3' => 'circumflex', + '4' => 'dieresis', + '5' => 'grave', + '6' => 'macron', + '7' => 'ring', + '8' => 'tilde', + '9' => 'breve', + '10' => 'ogonek', + '11' => 'dotaccent', + '12' => 'hungarumlaut', + '13' => 'cedilla', + '14' => 'dblgrave', + '15' => 'controlSI', + '16' => 'controlDLE', + '17' => 'controlDC1', + '18' => 'controlDC2', + '19' => 'controlDC3', + '20' => 'controlDC4', + '21' => 'controlNAK', + '22' => 'controlSYN', + '23' => 'controlETB', + '24' => 'controlCAN', + '25' => 'controlEM', + '26' => 'controlSUB', + '27' => 'controlESC', + '28' => 'controlFS', + '29' => 'controlGS', + '30' => 'dotlessi', + '31' => 'dotlessj', + '32' => 'space', + '33' => 'exclam', + '34' => 'quotedbl', + '35' => 'numbersign', + '36' => 'dollar', + '37' => 'percent', + '38' => 'ampersand', + '39' => 'quotesingle', + '40' => 'parenleft', + '41' => 'parenright', + '42' => 'asterisk', + '43' => 'plus', + '44' => 'comma', + '45' => 'hyphen', + '46' => 'period', + '47' => 'slash', + '48' => 'zero', + '49' => 'one', + '50' => 'two', + '51' => 'three', + '52' => 'four', + '53' => 'five', + '54' => 'six', + '55' => 'seven', + '56' => 'eight', + '57' => 'nine', + '58' => 'colon', + '59' => 'semicolon', + '60' => 'less', + '61' => 'equal', + '62' => 'greater', + '63' => 'question', + '64' => 'at', + '65' => 'A', + '66' => 'B', + '67' => 'C', + '68' => 'D', + '69' => 'E', + '70' => 'F', + '71' => 'G', + '72' => 'H', + '73' => 'I', + '74' => 'J', + '75' => 'K', + '76' => 'L', + '77' => 'M', + '78' => 'N', + '79' => 'O', + '80' => 'P', + '81' => 'Q', + '82' => 'R', + '83' => 'S', + '84' => 'T', + '85' => 'U', + '86' => 'V', + '87' => 'W', + '88' => 'X', + '89' => 'Y', + '90' => 'Z', + '91' => 'bracketleft', + '92' => 'backslash', + '93' => 'bracketright', + '94' => 'asciicircum', + '95' => 'underscore', + '96' => 'grave', + '97' => 'a', + '98' => 'b', + '99' => 'c', + '100' => 'd', + '101' => 'e', + '102' => 'f', + '103' => 'g', + '104' => 'h', + '105' => 'i', + '106' => 'j', + '107' => 'k', + '108' => 'l', + '109' => 'm', + '110' => 'n', + '111' => 'o', + '112' => 'p', + '113' => 'q', + '114' => 'r', + '115' => 's', + '116' => 't', + '117' => 'u', + '118' => 'v', + '119' => 'w', + '120' => 'x', + '121' => 'y', + '122' => 'z', + '123' => 'braceleft', + '124' => 'bar', + '125' => 'braceright', + '126' => 'asciitilde', + '127' => 'controlDEL', + '128' => 'Euro', + '129' => 'bullet', + '130' => 'quotesinglbase', + '131' => 'florin', + '132' => 'quotedblbase', + '133' => 'ellipsis', + '134' => 'dagger', + '135' => 'daggerdbl', + '136' => 'circumflex', + '137' => 'perthousand', + '138' => 'Scaron', + '139' => 'guilsinglleft', + '140' => 'OE', + '141' => 'bullet', + '142' => 'Zcaron', + '143' => 'bullet', + '144' => 'bullet', + '145' => 'quoteleft', + '146' => 'quoteright', + '147' => 'quotedblleft', + '148' => 'quotedblright', + '149' => 'bullet', + '150' => 'endash', + '151' => 'emdash', + '152' => 'tilde', + '153' => 'trademark', + '154' => 'scaron', + '155' => 'guilsinglright', + '156' => 'oe', + '157' => 'bullet', + '158' => 'zcaron', + '159' => 'Ydieresis', + '160' => 'space', + '161' => 'exclamdown', + '162' => 'cent', + '163' => 'sterling', + '164' => 'currency', + '165' => 'yen', + '166' => 'brokenbar', + '167' => 'section', + '168' => 'dieresis', + '169' => 'copyright', + '170' => 'ordfeminine', + '171' => 'guillemotleft', + '172' => 'logicalnot', + '173' => 'hyphen', + '174' => 'registered', + '175' => 'macron', + '176' => 'degree', + '177' => 'plusminus', + '178' => 'twosuperior', + '179' => 'threesuperior', + '180' => 'acute', + '181' => 'mu', + '182' => 'paragraph', + '183' => 'periodcentered', + '184' => 'cedilla', + '185' => 'onesuperior', + '186' => 'ordmasculine', + '187' => 'guillemotright', + '188' => 'onequarter', + '189' => 'onehalf', + '190' => 'threequarters', + '191' => 'questiondown', + '192' => 'Agrave', + '193' => 'Aacute', + '194' => 'Acircumflex', + '195' => 'Atilde', + '196' => 'Adieresis', + '197' => 'Aring', + '198' => 'AE', + '199' => 'Ccedilla', + '200' => 'Egrave', + '201' => 'Eacute', + '202' => 'Ecircumflex', + '203' => 'Edieresis', + '204' => 'Igrave', + '205' => 'Iacute', + '206' => 'Icircumflex', + '207' => 'Idieresis', + '208' => 'Eth', + '209' => 'Ntilde', + '210' => 'Ograve', + '211' => 'Oacute', + '212' => 'Ocircumflex', + '213' => 'Otilde', + '214' => 'Odieresis', + '215' => 'multiply', + '216' => 'Oslash', + '217' => 'Ugrave', + '218' => 'Uacute', + '219' => 'Ucircumflex', + '220' => 'Udieresis', + '221' => 'Yacute', + '222' => 'Thorn', + '223' => 'germandbls', + '224' => 'agrave', + '225' => 'aacute', + '226' => 'acircumflex', + '227' => 'atilde', + '228' => 'adieresis', + '229' => 'aring', + '230' => 'ae', + '231' => 'ccedilla', + '232' => 'egrave', + '233' => 'eacute', + '234' => 'ecircumflex', + '235' => 'edieresis', + '236' => 'igrave', + '237' => 'iacute', + '238' => 'icircumflex', + '239' => 'idieresis', + '240' => 'eth', + '241' => 'ntilde', + '242' => 'ograve', + '243' => 'oacute', + '244' => 'ocircumflex', + '245' => 'otilde', + '246' => 'odieresis', + '247' => 'divide', + '248' => 'oslash', + '249' => 'ugrave', + '250' => 'uacute', + '251' => 'ucircumflex', + '252' => 'udieresis', + '253' => 'yacute', + '254' => 'thorn', + '255' => 'ydieresis', + '256' => 'Amacron', + '257' => 'amacron', + '258' => 'Abreve', + '259' => 'abreve', + '260' => 'Aogonek', + '261' => 'aogonek', + '262' => 'Cacute', + '263' => 'cacute', + '264' => 'Ccircumflex', + '265' => 'ccircumflex', + '266' => 'Cdotaccent', + '267' => 'cdotaccent', + '268' => 'Ccaron', + '269' => 'ccaron', + '270' => 'Dcaron', + '271' => 'dcaron', + '272' => 'Dcroat', + '273' => 'dcroat', + '274' => 'Emacron', + '275' => 'emacron', + '276' => 'Ebreve', + '277' => 'ebreve', + '278' => 'Edotaccent', + '279' => 'edotaccent', + '280' => 'Eogonek', + '281' => 'eogonek', + '282' => 'Ecaron', + '283' => 'ecaron', + '284' => 'Gcircumflex', + '285' => 'gcircumflex', + '286' => 'Gbreve', + '287' => 'gbreve', + '288' => 'Gdotaccent', + '289' => 'gdotaccent', + '290' => 'Gcommaaccent', + '291' => 'gcommaaccent', + '292' => 'Hcircumflex', + '293' => 'hcircumflex', + '294' => 'Hbar', + '295' => 'hbar', + '296' => 'Itilde', + '297' => 'itilde', + '298' => 'Imacron', + '299' => 'imacron', + '300' => 'Ibreve', + '301' => 'ibreve', + '302' => 'Iogonek', + '303' => 'iogonek', + '304' => 'Idotaccent', + '305' => 'dotlessi', + '306' => 'IJ', + '307' => 'ij', + '308' => 'Jcircumflex', + '309' => 'jcircumflex', + '310' => 'Kcommaaccent', + '311' => 'kcommaaccent', + '312' => 'kgreenlandic', + '313' => 'Lacute', + '314' => 'lacute', + '315' => 'Lcommaaccent', + '316' => 'lcommaaccent', + '317' => 'Lcaron', + '318' => 'lcaron', + '319' => 'Ldot', + '320' => 'ldot', + '321' => 'Lslash', + '322' => 'lslash', + '323' => 'Nacute', + '324' => 'nacute', + '325' => 'Ncommaaccent', + '326' => 'ncommaaccent', + '327' => 'Ncaron', + '328' => 'ncaron', + '329' => 'napostrophe', + '330' => 'Eng', + '331' => 'eng', + '332' => 'Omacron', + '333' => 'omacron', + '334' => 'Obreve', + '335' => 'obreve', + '336' => 'Ohungarumlaut', + '337' => 'ohungarumlaut', + '338' => 'OE', + '339' => 'oe', + '340' => 'Racute', + '341' => 'racute', + '342' => 'Rcommaaccent', + '343' => 'rcommaaccent', + '344' => 'Rcaron', + '345' => 'rcaron', + '346' => 'Sacute', + '347' => 'sacute', + '348' => 'Scircumflex', + '349' => 'scircumflex', + '350' => 'Scedilla', + '351' => 'scedilla', + '352' => 'Scaron', + '353' => 'scaron', + '354' => 'Tcedilla', + '355' => 'tcedilla', + '356' => 'Tcaron', + '357' => 'tcaron', + '358' => 'Tbar', + '359' => 'tbar', + '360' => 'Utilde', + '361' => 'utilde', + '362' => 'Umacron', + '363' => 'umacron', + '364' => 'Ubreve', + '365' => 'ubreve', + '366' => 'Uring', + '367' => 'uring', + '368' => 'Uhungarumlaut', + '369' => 'uhungarumlaut', + '370' => 'Uogonek', + '371' => 'uogonek', + '372' => 'Wcircumflex', + '373' => 'wcircumflex', + '374' => 'Ycircumflex', + '375' => 'ycircumflex', + '376' => 'Ydieresis', + '377' => 'Zacute', + '378' => 'zacute', + '379' => 'Zdotaccent', + '380' => 'zdotaccent', + '381' => 'Zcaron', + '382' => 'zcaron', + '383' => 'longs', + '384' => 'bstroke', + '385' => 'Bhook', + '386' => 'Btopbar', + '387' => 'btopbar', + '388' => 'Tonesix', + '389' => 'tonesix', + '390' => 'Oopen', + '391' => 'Chook', + '392' => 'chook', + '393' => 'Dafrican', + '394' => 'Dhook', + '395' => 'Dtopbar', + '396' => 'dtopbar', + '397' => 'deltaturned', + '398' => 'Ereversed', + '399' => 'Schwa', + '400' => 'Eopen', + '401' => 'Fhook', + '402' => 'florin', + '403' => 'Ghook', + '404' => 'Gammaafrican', + '405' => 'hv', + '406' => 'Iotaafrican', + '407' => 'Istroke', + '408' => 'Khook', + '409' => 'khook', + '410' => 'lbar', + '411' => 'lambdastroke', + '412' => 'Mturned', + '413' => 'Nhookleft', + '414' => 'nlegrightlong', + '415' => 'Ocenteredtilde', + '416' => 'Ohorn', + '417' => 'ohorn', + '418' => 'Oi', + '419' => 'oi', + '420' => 'Phook', + '421' => 'phook', + '422' => 'yr', + '423' => 'Tonetwo', + '424' => 'tonetwo', + '425' => 'Esh', + '426' => 'eshreversedloop', + '427' => 'tpalatalhook', + '428' => 'Thook', + '429' => 'thook', + '430' => 'Tretroflexhook', + '431' => 'Uhorn', + '432' => 'uhorn', + '433' => 'Upsilonafrican', + '434' => 'Vhook', + '435' => 'Yhook', + '436' => 'yhook', + '437' => 'Zstroke', + '438' => 'zstroke', + '439' => 'Ezh', + '440' => 'Ezhreversed', + '441' => 'ezhreversed', + '442' => 'ezhtail', + '443' => 'twostroke', + '444' => 'Tonefive', + '445' => 'tonefive', + '446' => 'glottalinvertedstroke', + '447' => 'wynn', + '448' => 'clickdental', + '449' => 'clicklateral', + '450' => 'clickalveolar', + '451' => 'clickretroflex', + '452' => 'DZcaron', + '453' => 'Dzcaron', + '454' => 'dzcaron', + '455' => 'LJ', + '456' => 'Lj', + '457' => 'lj', + '458' => 'NJ', + '459' => 'Nj', + '460' => 'nj', + '461' => 'Acaron', + '462' => 'acaron', + '463' => 'Icaron', + '464' => 'icaron', + '465' => 'Ocaron', + '466' => 'ocaron', + '467' => 'Ucaron', + '468' => 'ucaron', + '469' => 'Udieresismacron', + '470' => 'udieresismacron', + '471' => 'Udieresisacute', + '472' => 'udieresisacute', + '473' => 'Udieresiscaron', + '474' => 'udieresiscaron', + '475' => 'Udieresisgrave', + '476' => 'udieresisgrave', + '477' => 'eturned', + '478' => 'Adieresismacron', + '479' => 'adieresismacron', + '480' => 'Adotmacron', + '481' => 'adotmacron', + '482' => 'AEmacron', + '483' => 'aemacron', + '484' => 'Gstroke', + '485' => 'gstroke', + '486' => 'Gcaron', + '487' => 'gcaron', + '488' => 'Kcaron', + '489' => 'kcaron', + '490' => 'Oogonek', + '491' => 'oogonek', + '492' => 'Oogonekmacron', + '493' => 'oogonekmacron', + '494' => 'Ezhcaron', + '495' => 'ezhcaron', + '496' => 'jcaron', + '497' => 'DZ', + '498' => 'Dz', + '499' => 'dz', + '500' => 'Gacute', + '501' => 'gacute', + '506' => 'Aringacute', + '507' => 'aringacute', + '508' => 'AEacute', + '509' => 'aeacute', + '510' => 'Oslashacute', + '511' => 'oslashacute', + '512' => 'Adblgrave', + '513' => 'adblgrave', + '514' => 'Ainvertedbreve', + '515' => 'ainvertedbreve', + '516' => 'Edblgrave', + '517' => 'edblgrave', + '518' => 'Einvertedbreve', + '519' => 'einvertedbreve', + '520' => 'Idblgrave', + '521' => 'idblgrave', + '522' => 'Iinvertedbreve', + '523' => 'iinvertedbreve', + '524' => 'Odblgrave', + '525' => 'odblgrave', + '526' => 'Oinvertedbreve', + '527' => 'oinvertedbreve', + '528' => 'Rdblgrave', + '529' => 'rdblgrave', + '530' => 'Rinvertedbreve', + '531' => 'rinvertedbreve', + '532' => 'Udblgrave', + '533' => 'udblgrave', + '534' => 'Uinvertedbreve', + '535' => 'uinvertedbreve', + '536' => 'Scommaaccent', + '537' => 'scommaaccent', + '538' => 'Tcommaaccent', + '539' => 'tcommaaccent', + '592' => 'aturned', + '593' => 'ascript', + '594' => 'ascriptturned', + '595' => 'bhook', + '596' => 'oopen', + '597' => 'ccurl', + '598' => 'dtail', + '599' => 'dhook', + '600' => 'ereversed', + '601' => 'schwa', + '602' => 'schwahook', + '603' => 'eopen', + '604' => 'eopenreversed', + '605' => 'eopenreversedhook', + '606' => 'eopenreversedclosed', + '607' => 'jdotlessstroke', + '608' => 'ghook', + '609' => 'gscript', + '611' => 'gammalatinsmall', + '612' => 'ramshorn', + '613' => 'hturned', + '614' => 'hhook', + '615' => 'henghook', + '616' => 'istroke', + '617' => 'iotalatin', + '619' => 'lmiddletilde', + '620' => 'lbelt', + '621' => 'lhookretroflex', + '622' => 'lezh', + '623' => 'mturned', + '624' => 'mlonglegturned', + '625' => 'mhook', + '626' => 'nhookleft', + '627' => 'nhookretroflex', + '629' => 'obarred', + '631' => 'omegalatinclosed', + '632' => 'philatin', + '633' => 'rturned', + '634' => 'rlonglegturned', + '635' => 'rhookturned', + '636' => 'rlongleg', + '637' => 'rhook', + '638' => 'rfishhook', + '639' => 'rfishhookreversed', + '641' => 'Rsmallinverted', + '642' => 'shook', + '643' => 'esh', + '644' => 'dotlessjstrokehook', + '645' => 'eshsquatreversed', + '646' => 'eshcurl', + '647' => 'tturned', + '648' => 'tretroflexhook', + '649' => 'ubar', + '650' => 'upsilonlatin', + '651' => 'vhook', + '652' => 'vturned', + '653' => 'wturned', + '654' => 'yturned', + '656' => 'zretroflexhook', + '657' => 'zcurl', + '658' => 'ezh', + '659' => 'ezhcurl', + '660' => 'glottalstop', + '661' => 'glottalstopreversed', + '662' => 'glottalstopinverted', + '663' => 'cstretched', + '664' => 'bilabialclick', + '666' => 'eopenclosed', + '667' => 'Gsmallhook', + '669' => 'jcrossedtail', + '670' => 'kturned', + '672' => 'qhook', + '673' => 'glottalstopstroke', + '674' => 'glottalstopstrokereversed', + '675' => 'dzaltone', + '676' => 'dezh', + '677' => 'dzcurl', + '678' => 'ts', + '679' => 'tesh', + '680' => 'tccurl', + '688' => 'hsuperior', + '689' => 'hhooksuperior', + '690' => 'jsuperior', + '692' => 'rturnedsuperior', + '693' => 'rhookturnedsuperior', + '694' => 'Rsmallinvertedsuperior', + '695' => 'wsuperior', + '696' => 'ysuperior', + '697' => 'primemod', + '698' => 'dblprimemod', + '699' => 'commaturnedmod', + '700' => 'afii57929', + '701' => 'afii64937', + '702' => 'ringhalfright', + '703' => 'ringhalfleft', + '704' => 'glottalstopmod', + '705' => 'glottalstopreversedmod', + '706' => 'arrowheadleftmod', + '707' => 'arrowheadrightmod', + '708' => 'arrowheadupmod', + '709' => 'arrowheaddownmod', + '710' => 'circumflex', + '711' => 'caron', + '712' => 'verticallinemod', + '713' => 'macron', + '714' => 'secondtonechinese', + '715' => 'fourthtonechinese', + '716' => 'verticallinelowmod', + '717' => 'macronlowmod', + '718' => 'gravelowmod', + '719' => 'acutelowmod', + '720' => 'colontriangularmod', + '721' => 'colontriangularhalfmod', + '722' => 'ringhalfrightcentered', + '723' => 'ringhalfleftcentered', + '724' => 'uptackmod', + '725' => 'downtackmod', + '726' => 'plusmod', + '727' => 'minusmod', + '728' => 'breve', + '729' => 'dotaccent', + '730' => 'ring', + '731' => 'ogonek', + '732' => 'tilde', + '733' => 'hungarumlaut', + '734' => 'rhotichookmod', + '736' => 'gammasuperior', + '739' => 'xsuperior', + '740' => 'glottalstopreversedsuperior', + '741' => 'tonebarextrahighmod', + '742' => 'tonebarhighmod', + '743' => 'tonebarmidmod', + '744' => 'tonebarlowmod', + '745' => 'tonebarextralowmod', + '768' => 'gravecomb', + '769' => 'acutecomb', + '770' => 'circumflexcmb', + '771' => 'tildecomb', + '772' => 'macroncmb', + '773' => 'overlinecmb', + '774' => 'brevecmb', + '775' => 'dotaccentcmb', + '776' => 'dieresiscmb', + '777' => 'hookabovecomb', + '778' => 'ringcmb', + '779' => 'hungarumlautcmb', + '780' => 'caroncmb', + '781' => 'verticallineabovecmb', + '782' => 'dblverticallineabovecmb', + '783' => 'dblgravecmb', + '784' => 'candrabinducmb', + '785' => 'breveinvertedcmb', + '786' => 'commaturnedabovecmb', + '787' => 'commaabovecmb', + '788' => 'commareversedabovecmb', + '789' => 'commaaboverightcmb', + '790' => 'gravebelowcmb', + '791' => 'acutebelowcmb', + '792' => 'lefttackbelowcmb', + '793' => 'righttackbelowcmb', + '794' => 'leftangleabovecmb', + '795' => 'horncmb', + '796' => 'ringhalfleftbelowcmb', + '797' => 'uptackbelowcmb', + '798' => 'downtackbelowcmb', + '799' => 'plusbelowcmb', + '800' => 'minusbelowcmb', + '801' => 'hookpalatalizedbelowcmb', + '802' => 'hookretroflexbelowcmb', + '803' => 'dotbelowcomb', + '804' => 'dieresisbelowcmb', + '805' => 'ringbelowcmb', + '807' => 'cedillacmb', + '808' => 'ogonekcmb', + '809' => 'verticallinebelowcmb', + '810' => 'bridgebelowcmb', + '811' => 'dblarchinvertedbelowcmb', + '812' => 'caronbelowcmb', + '813' => 'circumflexbelowcmb', + '814' => 'brevebelowcmb', + '815' => 'breveinvertedbelowcmb', + '816' => 'tildebelowcmb', + '817' => 'macronbelowcmb', + '818' => 'lowlinecmb', + '819' => 'dbllowlinecmb', + '820' => 'tildeoverlaycmb', + '821' => 'strokeshortoverlaycmb', + '822' => 'strokelongoverlaycmb', + '823' => 'solidusshortoverlaycmb', + '824' => 'soliduslongoverlaycmb', + '825' => 'ringhalfrightbelowcmb', + '826' => 'bridgeinvertedbelowcmb', + '827' => 'squarebelowcmb', + '828' => 'seagullbelowcmb', + '829' => 'xabovecmb', + '830' => 'tildeverticalcmb', + '831' => 'dbloverlinecmb', + '832' => 'gravetonecmb', + '833' => 'acutetonecmb', + '834' => 'perispomenigreekcmb', + '835' => 'koroniscmb', + '836' => 'dialytikatonoscmb', + '837' => 'ypogegrammenigreekcmb', + '864' => 'tildedoublecmb', + '865' => 'breveinverteddoublecmb', + '884' => 'numeralsigngreek', + '885' => 'numeralsignlowergreek', + '890' => 'ypogegrammeni', + '894' => 'questiongreek', + '900' => 'tonos', + '901' => 'dieresistonos', + '902' => 'Alphatonos', + '903' => 'anoteleia', + '904' => 'Epsilontonos', + '905' => 'Etatonos', + '906' => 'Iotatonos', + '908' => 'Omicrontonos', + '910' => 'Upsilontonos', + '911' => 'Omegatonos', + '912' => 'iotadieresistonos', + '913' => 'Alpha', + '914' => 'Beta', + '915' => 'Gamma', + '916' => 'Delta', + '917' => 'Epsilon', + '918' => 'Zeta', + '919' => 'Eta', + '920' => 'Theta', + '921' => 'Iota', + '922' => 'Kappa', + '923' => 'Lambda', + '924' => 'Mu', + '925' => 'Nu', + '926' => 'Xi', + '927' => 'Omicron', + '928' => 'Pi', + '929' => 'Rho', + '931' => 'Sigma', + '932' => 'Tau', + '933' => 'Upsilon', + '934' => 'Phi', + '935' => 'Chi', + '936' => 'Psi', + '937' => 'Omega', + '938' => 'Iotadieresis', + '939' => 'Upsilondieresis', + '940' => 'alphatonos', + '941' => 'epsilontonos', + '942' => 'etatonos', + '943' => 'iotatonos', + '944' => 'upsilondieresistonos', + '945' => 'alpha', + '946' => 'beta', + '947' => 'gamma', + '948' => 'delta', + '949' => 'epsilon', + '950' => 'zeta', + '951' => 'eta', + '952' => 'theta', + '953' => 'iota', + '954' => 'kappa', + '955' => 'lambda', + '956' => 'mu', + '957' => 'nu', + '958' => 'xi', + '959' => 'omicron', + '960' => 'pi', + '961' => 'rho', + '962' => 'sigma1', + '963' => 'sigma', + '964' => 'tau', + '965' => 'upsilon', + '966' => 'phi', + '967' => 'chi', + '968' => 'psi', + '969' => 'omega', + '970' => 'iotadieresis', + '971' => 'upsilondieresis', + '972' => 'omicrontonos', + '973' => 'upsilontonos', + '974' => 'omegatonos', + '976' => 'betasymbolgreek', + '977' => 'theta1', + '978' => 'Upsilon1', + '979' => 'Upsilonacutehooksymbolgreek', + '980' => 'Upsilondieresishooksymbolgreek', + '981' => 'phi1', + '982' => 'omega1', + '986' => 'Stigmagreek', + '988' => 'Digammagreek', + '989' => 'gammad', + '990' => 'Koppagreek', + '992' => 'Sampigreek', + '994' => 'Sheicoptic', + '995' => 'sheicoptic', + '996' => 'Feicoptic', + '997' => 'feicoptic', + '998' => 'Kheicoptic', + '999' => 'kheicoptic', + '1000' => 'Horicoptic', + '1001' => 'horicoptic', + '1002' => 'Gangiacoptic', + '1003' => 'gangiacoptic', + '1004' => 'Shimacoptic', + '1005' => 'shimacoptic', + '1006' => 'Deicoptic', + '1007' => 'deicoptic', + '1008' => 'kappasymbolgreek', + '1009' => 'rhosymbolgreek', + '1010' => 'sigmalunatesymbolgreek', + '1011' => 'yotgreek', + '1025' => 'afii10023', + '1026' => 'afii10051', + '1027' => 'afii10052', + '1028' => 'afii10053', + '1029' => 'afii10054', + '1030' => 'afii10055', + '1031' => 'afii10056', + '1032' => 'afii10057', + '1033' => 'afii10058', + '1034' => 'afii10059', + '1035' => 'afii10060', + '1036' => 'afii10061', + '1038' => 'afii10062', + '1039' => 'afii10145', + '1040' => 'afii10017', + '1041' => 'afii10018', + '1042' => 'afii10019', + '1043' => 'afii10020', + '1044' => 'afii10021', + '1045' => 'afii10022', + '1046' => 'afii10024', + '1047' => 'afii10025', + '1048' => 'afii10026', + '1049' => 'afii10027', + '1050' => 'afii10028', + '1051' => 'afii10029', + '1052' => 'afii10030', + '1053' => 'afii10031', + '1054' => 'afii10032', + '1055' => 'afii10033', + '1056' => 'afii10034', + '1057' => 'afii10035', + '1058' => 'afii10036', + '1059' => 'afii10037', + '1060' => 'afii10038', + '1061' => 'afii10039', + '1062' => 'afii10040', + '1063' => 'afii10041', + '1064' => 'afii10042', + '1065' => 'afii10043', + '1066' => 'afii10044', + '1067' => 'afii10045', + '1068' => 'afii10046', + '1069' => 'afii10047', + '1070' => 'afii10048', + '1071' => 'afii10049', + '1072' => 'afii10065', + '1073' => 'afii10066', + '1074' => 'afii10067', + '1075' => 'afii10068', + '1076' => 'afii10069', + '1077' => 'afii10070', + '1078' => 'afii10072', + '1079' => 'afii10073', + '1080' => 'afii10074', + '1081' => 'afii10075', + '1082' => 'afii10076', + '1083' => 'afii10077', + '1084' => 'afii10078', + '1085' => 'afii10079', + '1086' => 'afii10080', + '1087' => 'afii10081', + '1088' => 'afii10082', + '1089' => 'afii10083', + '1090' => 'afii10084', + '1091' => 'afii10085', + '1092' => 'afii10086', + '1093' => 'afii10087', + '1094' => 'afii10088', + '1095' => 'afii10089', + '1096' => 'afii10090', + '1097' => 'afii10091', + '1098' => 'afii10092', + '1099' => 'afii10093', + '1100' => 'afii10094', + '1101' => 'afii10095', + '1102' => 'afii10096', + '1103' => 'afii10097', + '1105' => 'afii10071', + '1106' => 'afii10099', + '1107' => 'afii10100', + '1108' => 'afii10101', + '1109' => 'afii10102', + '1110' => 'afii10103', + '1111' => 'afii10104', + '1112' => 'afii10105', + '1113' => 'afii10106', + '1114' => 'afii10107', + '1115' => 'afii10108', + '1116' => 'afii10109', + '1118' => 'afii10110', + '1119' => 'afii10193', + '1120' => 'Omegacyrillic', + '1121' => 'omegacyrillic', + '1122' => 'afii10146', + '1123' => 'afii10194', + '1124' => 'Eiotifiedcyrillic', + '1125' => 'eiotifiedcyrillic', + '1126' => 'Yuslittlecyrillic', + '1127' => 'yuslittlecyrillic', + '1128' => 'Yuslittleiotifiedcyrillic', + '1129' => 'yuslittleiotifiedcyrillic', + '1130' => 'Yusbigcyrillic', + '1131' => 'yusbigcyrillic', + '1132' => 'Yusbigiotifiedcyrillic', + '1133' => 'yusbigiotifiedcyrillic', + '1134' => 'Ksicyrillic', + '1135' => 'ksicyrillic', + '1136' => 'Psicyrillic', + '1137' => 'psicyrillic', + '1138' => 'afii10147', + '1139' => 'afii10195', + '1140' => 'afii10148', + '1141' => 'afii10196', + '1142' => 'Izhitsadblgravecyrillic', + '1143' => 'izhitsadblgravecyrillic', + '1144' => 'Ukcyrillic', + '1145' => 'ukcyrillic', + '1146' => 'Omegaroundcyrillic', + '1147' => 'omegaroundcyrillic', + '1148' => 'Omegatitlocyrillic', + '1149' => 'omegatitlocyrillic', + '1150' => 'Otcyrillic', + '1151' => 'otcyrillic', + '1152' => 'Koppacyrillic', + '1153' => 'koppacyrillic', + '1154' => 'thousandcyrillic', + '1155' => 'titlocyrilliccmb', + '1156' => 'palatalizationcyrilliccmb', + '1157' => 'dasiapneumatacyrilliccmb', + '1158' => 'psilipneumatacyrilliccmb', + '1168' => 'afii10050', + '1169' => 'afii10098', + '1170' => 'Ghestrokecyrillic', + '1171' => 'ghestrokecyrillic', + '1172' => 'Ghemiddlehookcyrillic', + '1173' => 'ghemiddlehookcyrillic', + '1174' => 'Zhedescendercyrillic', + '1175' => 'zhedescendercyrillic', + '1176' => 'Zedescendercyrillic', + '1177' => 'zedescendercyrillic', + '1178' => 'Kadescendercyrillic', + '1179' => 'kadescendercyrillic', + '1180' => 'Kaverticalstrokecyrillic', + '1181' => 'kaverticalstrokecyrillic', + '1182' => 'Kastrokecyrillic', + '1183' => 'kastrokecyrillic', + '1184' => 'Kabashkircyrillic', + '1185' => 'kabashkircyrillic', + '1186' => 'Endescendercyrillic', + '1187' => 'endescendercyrillic', + '1188' => 'Enghecyrillic', + '1189' => 'enghecyrillic', + '1190' => 'Pemiddlehookcyrillic', + '1191' => 'pemiddlehookcyrillic', + '1192' => 'Haabkhasiancyrillic', + '1193' => 'haabkhasiancyrillic', + '1194' => 'Esdescendercyrillic', + '1195' => 'esdescendercyrillic', + '1196' => 'Tedescendercyrillic', + '1197' => 'tedescendercyrillic', + '1198' => 'Ustraightcyrillic', + '1199' => 'ustraightcyrillic', + '1200' => 'Ustraightstrokecyrillic', + '1201' => 'ustraightstrokecyrillic', + '1202' => 'Hadescendercyrillic', + '1203' => 'hadescendercyrillic', + '1204' => 'Tetsecyrillic', + '1205' => 'tetsecyrillic', + '1206' => 'Chedescendercyrillic', + '1207' => 'chedescendercyrillic', + '1208' => 'Cheverticalstrokecyrillic', + '1209' => 'cheverticalstrokecyrillic', + '1210' => 'Shhacyrillic', + '1211' => 'shhacyrillic', + '1212' => 'Cheabkhasiancyrillic', + '1213' => 'cheabkhasiancyrillic', + '1214' => 'Chedescenderabkhasiancyrillic', + '1215' => 'chedescenderabkhasiancyrillic', + '1216' => 'palochkacyrillic', + '1217' => 'Zhebrevecyrillic', + '1218' => 'zhebrevecyrillic', + '1219' => 'Kahookcyrillic', + '1220' => 'kahookcyrillic', + '1223' => 'Enhookcyrillic', + '1224' => 'enhookcyrillic', + '1227' => 'Chekhakassiancyrillic', + '1228' => 'chekhakassiancyrillic', + '1232' => 'Abrevecyrillic', + '1233' => 'abrevecyrillic', + '1234' => 'Adieresiscyrillic', + '1235' => 'adieresiscyrillic', + '1236' => 'Aiecyrillic', + '1237' => 'aiecyrillic', + '1238' => 'Iebrevecyrillic', + '1239' => 'iebrevecyrillic', + '1240' => 'Schwacyrillic', + '1241' => 'afii10846', + '1242' => 'Schwadieresiscyrillic', + '1243' => 'schwadieresiscyrillic', + '1244' => 'Zhedieresiscyrillic', + '1245' => 'zhedieresiscyrillic', + '1246' => 'Zedieresiscyrillic', + '1247' => 'zedieresiscyrillic', + '1248' => 'Dzeabkhasiancyrillic', + '1249' => 'dzeabkhasiancyrillic', + '1250' => 'Imacroncyrillic', + '1251' => 'imacroncyrillic', + '1252' => 'Idieresiscyrillic', + '1253' => 'idieresiscyrillic', + '1254' => 'Odieresiscyrillic', + '1255' => 'odieresiscyrillic', + '1256' => 'Obarredcyrillic', + '1257' => 'obarredcyrillic', + '1258' => 'Obarreddieresiscyrillic', + '1259' => 'obarreddieresiscyrillic', + '1262' => 'Umacroncyrillic', + '1263' => 'umacroncyrillic', + '1264' => 'Udieresiscyrillic', + '1265' => 'udieresiscyrillic', + '1266' => 'Uhungarumlautcyrillic', + '1267' => 'uhungarumlautcyrillic', + '1268' => 'Chedieresiscyrillic', + '1269' => 'chedieresiscyrillic', + '1272' => 'Yerudieresiscyrillic', + '1273' => 'yerudieresiscyrillic', + '1329' => 'Aybarmenian', + '1330' => 'Benarmenian', + '1331' => 'Gimarmenian', + '1332' => 'Daarmenian', + '1333' => 'Echarmenian', + '1334' => 'Zaarmenian', + '1335' => 'Eharmenian', + '1336' => 'Etarmenian', + '1337' => 'Toarmenian', + '1338' => 'Zhearmenian', + '1339' => 'Iniarmenian', + '1340' => 'Liwnarmenian', + '1341' => 'Xeharmenian', + '1342' => 'Caarmenian', + '1343' => 'Kenarmenian', + '1344' => 'Hoarmenian', + '1345' => 'Jaarmenian', + '1346' => 'Ghadarmenian', + '1347' => 'Cheharmenian', + '1348' => 'Menarmenian', + '1349' => 'Yiarmenian', + '1350' => 'Nowarmenian', + '1351' => 'Shaarmenian', + '1352' => 'Voarmenian', + '1353' => 'Chaarmenian', + '1354' => 'Peharmenian', + '1355' => 'Jheharmenian', + '1356' => 'Raarmenian', + '1357' => 'Seharmenian', + '1358' => 'Vewarmenian', + '1359' => 'Tiwnarmenian', + '1360' => 'Reharmenian', + '1361' => 'Coarmenian', + '1362' => 'Yiwnarmenian', + '1363' => 'Piwrarmenian', + '1364' => 'Keharmenian', + '1365' => 'Oharmenian', + '1366' => 'Feharmenian', + '1369' => 'ringhalfleftarmenian', + '1370' => 'apostrophearmenian', + '1371' => 'emphasismarkarmenian', + '1372' => 'exclamarmenian', + '1373' => 'commaarmenian', + '1374' => 'questionarmenian', + '1375' => 'abbreviationmarkarmenian', + '1377' => 'aybarmenian', + '1378' => 'benarmenian', + '1379' => 'gimarmenian', + '1380' => 'daarmenian', + '1381' => 'echarmenian', + '1382' => 'zaarmenian', + '1383' => 'eharmenian', + '1384' => 'etarmenian', + '1385' => 'toarmenian', + '1386' => 'zhearmenian', + '1387' => 'iniarmenian', + '1388' => 'liwnarmenian', + '1389' => 'xeharmenian', + '1390' => 'caarmenian', + '1391' => 'kenarmenian', + '1392' => 'hoarmenian', + '1393' => 'jaarmenian', + '1394' => 'ghadarmenian', + '1395' => 'cheharmenian', + '1396' => 'menarmenian', + '1397' => 'yiarmenian', + '1398' => 'nowarmenian', + '1399' => 'shaarmenian', + '1400' => 'voarmenian', + '1401' => 'chaarmenian', + '1402' => 'peharmenian', + '1403' => 'jheharmenian', + '1404' => 'raarmenian', + '1405' => 'seharmenian', + '1406' => 'vewarmenian', + '1407' => 'tiwnarmenian', + '1408' => 'reharmenian', + '1409' => 'coarmenian', + '1410' => 'yiwnarmenian', + '1411' => 'piwrarmenian', + '1412' => 'keharmenian', + '1413' => 'oharmenian', + '1414' => 'feharmenian', + '1415' => 'echyiwnarmenian', + '1417' => 'periodarmenian', + '1425' => 'etnahtafoukhhebrew', + '1426' => 'segoltahebrew', + '1427' => 'shalshelethebrew', + '1428' => 'zaqefqatanhebrew', + '1429' => 'zaqefgadolhebrew', + '1430' => 'tipehahebrew', + '1431' => 'reviahebrew', + '1432' => 'zarqahebrew', + '1433' => 'pashtahebrew', + '1434' => 'yetivhebrew', + '1435' => 'tevirhebrew', + '1436' => 'gereshaccenthebrew', + '1437' => 'gereshmuqdamhebrew', + '1438' => 'gershayimaccenthebrew', + '1439' => 'qarneyparahebrew', + '1440' => 'telishagedolahebrew', + '1441' => 'pazerhebrew', + '1443' => 'munahhebrew', + '1444' => 'mahapakhhebrew', + '1445' => 'merkhahebrew', + '1446' => 'merkhakefulahebrew', + '1447' => 'dargahebrew', + '1448' => 'qadmahebrew', + '1449' => 'telishaqetanahebrew', + '1450' => 'yerahbenyomohebrew', + '1451' => 'olehebrew', + '1452' => 'iluyhebrew', + '1453' => 'dehihebrew', + '1454' => 'zinorhebrew', + '1455' => 'masoracirclehebrew', + '1456' => 'afii57799', + '1457' => 'afii57801', + '1458' => 'afii57800', + '1459' => 'afii57802', + '1460' => 'afii57793', + '1461' => 'afii57794', + '1462' => 'afii57795', + '1463' => 'afii57798', + '1464' => 'afii57797', + '1465' => 'afii57806', + '1467' => 'afii57796', + '1468' => 'afii57807', + '1469' => 'afii57839', + '1470' => 'afii57645', + '1471' => 'afii57841', + '1472' => 'afii57842', + '1473' => 'afii57804', + '1474' => 'afii57803', + '1475' => 'afii57658', + '1476' => 'upperdothebrew', + '1488' => 'afii57664', + '1489' => 'afii57665', + '1490' => 'afii57666', + '1491' => 'afii57667', + '1492' => 'afii57668', + '1493' => 'afii57669', + '1494' => 'afii57670', + '1495' => 'afii57671', + '1496' => 'afii57672', + '1497' => 'afii57673', + '1498' => 'afii57674', + '1499' => 'afii57675', + '1500' => 'afii57676', + '1501' => 'afii57677', + '1502' => 'afii57678', + '1503' => 'afii57679', + '1504' => 'afii57680', + '1505' => 'afii57681', + '1506' => 'afii57682', + '1507' => 'afii57683', + '1508' => 'afii57684', + '1509' => 'afii57685', + '1510' => 'afii57686', + '1511' => 'afii57687', + '1512' => 'afii57688', + '1513' => 'afii57689', + '1514' => 'afii57690', + '1520' => 'afii57716', + '1521' => 'afii57717', + '1522' => 'afii57718', + '1523' => 'gereshhebrew', + '1524' => 'gershayimhebrew', + '1548' => 'afii57388', + '1563' => 'afii57403', + '1567' => 'afii57407', + '1569' => 'afii57409', + '1570' => 'afii57410', + '1571' => 'afii57411', + '1572' => 'afii57412', + '1573' => 'afii57413', + '1574' => 'afii57414', + '1575' => 'afii57415', + '1576' => 'afii57416', + '1577' => 'afii57417', + '1578' => 'afii57418', + '1579' => 'afii57419', + '1580' => 'afii57420', + '1581' => 'afii57421', + '1582' => 'afii57422', + '1583' => 'afii57423', + '1584' => 'afii57424', + '1585' => 'afii57425', + '1586' => 'afii57426', + '1587' => 'afii57427', + '1588' => 'afii57428', + '1589' => 'afii57429', + '1590' => 'afii57430', + '1591' => 'afii57431', + '1592' => 'afii57432', + '1593' => 'afii57433', + '1594' => 'afii57434', + '1600' => 'afii57440', + '1601' => 'afii57441', + '1602' => 'afii57442', + '1603' => 'afii57443', + '1604' => 'afii57444', + '1605' => 'afii57445', + '1606' => 'afii57446', + '1607' => 'afii57470', + '1608' => 'afii57448', + '1609' => 'afii57449', + '1610' => 'afii57450', + '1611' => 'afii57451', + '1612' => 'afii57452', + '1613' => 'afii57453', + '1614' => 'afii57454', + '1615' => 'afii57455', + '1616' => 'afii57456', + '1617' => 'afii57457', + '1618' => 'afii57458', + '1632' => 'afii57392', + '1633' => 'afii57393', + '1634' => 'afii57394', + '1635' => 'afii57395', + '1636' => 'afii57396', + '1637' => 'afii57397', + '1638' => 'afii57398', + '1639' => 'afii57399', + '1640' => 'afii57400', + '1641' => 'afii57401', + '1642' => 'afii57381', + '1643' => 'decimalseparatorarabic', + '1644' => 'thousandsseparatorarabic', + '1645' => 'afii63167', + '1657' => 'afii57511', + '1662' => 'afii57506', + '1670' => 'afii57507', + '1672' => 'afii57512', + '1681' => 'afii57513', + '1688' => 'afii57508', + '1700' => 'afii57505', + '1711' => 'afii57509', + '1722' => 'afii57514', + '1729' => 'haaltonearabic', + '1745' => 'yehthreedotsbelowarabic', + '1746' => 'afii57519', + '1749' => 'afii57534', + '1776' => 'zeropersian', + '1777' => 'onepersian', + '1778' => 'twopersian', + '1779' => 'threepersian', + '1780' => 'fourpersian', + '1781' => 'fivepersian', + '1782' => 'sixpersian', + '1783' => 'sevenpersian', + '1784' => 'eightpersian', + '1785' => 'ninepersian', + '2305' => 'candrabindudeva', + '2306' => 'anusvaradeva', + '2307' => 'visargadeva', + '2309' => 'adeva', + '2310' => 'aadeva', + '2311' => 'ideva', + '2312' => 'iideva', + '2313' => 'udeva', + '2314' => 'uudeva', + '2315' => 'rvocalicdeva', + '2316' => 'lvocalicdeva', + '2317' => 'ecandradeva', + '2318' => 'eshortdeva', + '2319' => 'edeva', + '2320' => 'aideva', + '2321' => 'ocandradeva', + '2322' => 'oshortdeva', + '2323' => 'odeva', + '2324' => 'audeva', + '2325' => 'kadeva', + '2326' => 'khadeva', + '2327' => 'gadeva', + '2328' => 'ghadeva', + '2329' => 'ngadeva', + '2330' => 'cadeva', + '2331' => 'chadeva', + '2332' => 'jadeva', + '2333' => 'jhadeva', + '2334' => 'nyadeva', + '2335' => 'ttadeva', + '2336' => 'tthadeva', + '2337' => 'ddadeva', + '2338' => 'ddhadeva', + '2339' => 'nnadeva', + '2340' => 'tadeva', + '2341' => 'thadeva', + '2342' => 'dadeva', + '2343' => 'dhadeva', + '2344' => 'nadeva', + '2345' => 'nnnadeva', + '2346' => 'padeva', + '2347' => 'phadeva', + '2348' => 'badeva', + '2349' => 'bhadeva', + '2350' => 'madeva', + '2351' => 'yadeva', + '2352' => 'radeva', + '2353' => 'rradeva', + '2354' => 'ladeva', + '2355' => 'lladeva', + '2356' => 'llladeva', + '2357' => 'vadeva', + '2358' => 'shadeva', + '2359' => 'ssadeva', + '2360' => 'sadeva', + '2361' => 'hadeva', + '2364' => 'nuktadeva', + '2365' => 'avagrahadeva', + '2366' => 'aavowelsigndeva', + '2367' => 'ivowelsigndeva', + '2368' => 'iivowelsigndeva', + '2369' => 'uvowelsigndeva', + '2370' => 'uuvowelsigndeva', + '2371' => 'rvocalicvowelsigndeva', + '2372' => 'rrvocalicvowelsigndeva', + '2373' => 'ecandravowelsigndeva', + '2374' => 'eshortvowelsigndeva', + '2375' => 'evowelsigndeva', + '2376' => 'aivowelsigndeva', + '2377' => 'ocandravowelsigndeva', + '2378' => 'oshortvowelsigndeva', + '2379' => 'ovowelsigndeva', + '2380' => 'auvowelsigndeva', + '2381' => 'viramadeva', + '2384' => 'omdeva', + '2385' => 'udattadeva', + '2386' => 'anudattadeva', + '2387' => 'gravedeva', + '2388' => 'acutedeva', + '2392' => 'qadeva', + '2393' => 'khhadeva', + '2394' => 'ghhadeva', + '2395' => 'zadeva', + '2396' => 'dddhadeva', + '2397' => 'rhadeva', + '2398' => 'fadeva', + '2399' => 'yyadeva', + '2400' => 'rrvocalicdeva', + '2401' => 'llvocalicdeva', + '2402' => 'lvocalicvowelsigndeva', + '2403' => 'llvocalicvowelsigndeva', + '2404' => 'danda', + '2405' => 'dbldanda', + '2406' => 'zerodeva', + '2407' => 'onedeva', + '2408' => 'twodeva', + '2409' => 'threedeva', + '2410' => 'fourdeva', + '2411' => 'fivedeva', + '2412' => 'sixdeva', + '2413' => 'sevendeva', + '2414' => 'eightdeva', + '2415' => 'ninedeva', + '2416' => 'abbreviationsigndeva', + '2433' => 'candrabindubengali', + '2434' => 'anusvarabengali', + '2435' => 'visargabengali', + '2437' => 'abengali', + '2438' => 'aabengali', + '2439' => 'ibengali', + '2440' => 'iibengali', + '2441' => 'ubengali', + '2442' => 'uubengali', + '2443' => 'rvocalicbengali', + '2444' => 'lvocalicbengali', + '2447' => 'ebengali', + '2448' => 'aibengali', + '2451' => 'obengali', + '2452' => 'aubengali', + '2453' => 'kabengali', + '2454' => 'khabengali', + '2455' => 'gabengali', + '2456' => 'ghabengali', + '2457' => 'ngabengali', + '2458' => 'cabengali', + '2459' => 'chabengali', + '2460' => 'jabengali', + '2461' => 'jhabengali', + '2462' => 'nyabengali', + '2463' => 'ttabengali', + '2464' => 'tthabengali', + '2465' => 'ddabengali', + '2466' => 'ddhabengali', + '2467' => 'nnabengali', + '2468' => 'tabengali', + '2469' => 'thabengali', + '2470' => 'dabengali', + '2471' => 'dhabengali', + '2472' => 'nabengali', + '2474' => 'pabengali', + '2475' => 'phabengali', + '2476' => 'babengali', + '2477' => 'bhabengali', + '2478' => 'mabengali', + '2479' => 'yabengali', + '2480' => 'rabengali', + '2482' => 'labengali', + '2486' => 'shabengali', + '2487' => 'ssabengali', + '2488' => 'sabengali', + '2489' => 'habengali', + '2492' => 'nuktabengali', + '2494' => 'aavowelsignbengali', + '2495' => 'ivowelsignbengali', + '2496' => 'iivowelsignbengali', + '2497' => 'uvowelsignbengali', + '2498' => 'uuvowelsignbengali', + '2499' => 'rvocalicvowelsignbengali', + '2500' => 'rrvocalicvowelsignbengali', + '2503' => 'evowelsignbengali', + '2504' => 'aivowelsignbengali', + '2507' => 'ovowelsignbengali', + '2508' => 'auvowelsignbengali', + '2509' => 'viramabengali', + '2519' => 'aulengthmarkbengali', + '2524' => 'rrabengali', + '2525' => 'rhabengali', + '2527' => 'yyabengali', + '2528' => 'rrvocalicbengali', + '2529' => 'llvocalicbengali', + '2530' => 'lvocalicvowelsignbengali', + '2531' => 'llvocalicvowelsignbengali', + '2534' => 'zerobengali', + '2535' => 'onebengali', + '2536' => 'twobengali', + '2537' => 'threebengali', + '2538' => 'fourbengali', + '2539' => 'fivebengali', + '2540' => 'sixbengali', + '2541' => 'sevenbengali', + '2542' => 'eightbengali', + '2543' => 'ninebengali', + '2544' => 'ramiddlediagonalbengali', + '2545' => 'ralowerdiagonalbengali', + '2546' => 'rupeemarkbengali', + '2547' => 'rupeesignbengali', + '2548' => 'onenumeratorbengali', + '2549' => 'twonumeratorbengali', + '2550' => 'threenumeratorbengali', + '2551' => 'fournumeratorbengali', + '2552' => 'denominatorminusonenumeratorbengali', + '2553' => 'sixteencurrencydenominatorbengali', + '2554' => 'issharbengali', + '2562' => 'bindigurmukhi', + '2565' => 'agurmukhi', + '2566' => 'aagurmukhi', + '2567' => 'igurmukhi', + '2568' => 'iigurmukhi', + '2569' => 'ugurmukhi', + '2570' => 'uugurmukhi', + '2575' => 'eegurmukhi', + '2576' => 'aigurmukhi', + '2579' => 'oogurmukhi', + '2580' => 'augurmukhi', + '2581' => 'kagurmukhi', + '2582' => 'khagurmukhi', + '2583' => 'gagurmukhi', + '2584' => 'ghagurmukhi', + '2585' => 'ngagurmukhi', + '2586' => 'cagurmukhi', + '2587' => 'chagurmukhi', + '2588' => 'jagurmukhi', + '2589' => 'jhagurmukhi', + '2590' => 'nyagurmukhi', + '2591' => 'ttagurmukhi', + '2592' => 'tthagurmukhi', + '2593' => 'ddagurmukhi', + '2594' => 'ddhagurmukhi', + '2595' => 'nnagurmukhi', + '2596' => 'tagurmukhi', + '2597' => 'thagurmukhi', + '2598' => 'dagurmukhi', + '2599' => 'dhagurmukhi', + '2600' => 'nagurmukhi', + '2602' => 'pagurmukhi', + '2603' => 'phagurmukhi', + '2604' => 'bagurmukhi', + '2605' => 'bhagurmukhi', + '2606' => 'magurmukhi', + '2607' => 'yagurmukhi', + '2608' => 'ragurmukhi', + '2610' => 'lagurmukhi', + '2613' => 'vagurmukhi', + '2614' => 'shagurmukhi', + '2616' => 'sagurmukhi', + '2617' => 'hagurmukhi', + '2620' => 'nuktagurmukhi', + '2622' => 'aamatragurmukhi', + '2623' => 'imatragurmukhi', + '2624' => 'iimatragurmukhi', + '2625' => 'umatragurmukhi', + '2626' => 'uumatragurmukhi', + '2631' => 'eematragurmukhi', + '2632' => 'aimatragurmukhi', + '2635' => 'oomatragurmukhi', + '2636' => 'aumatragurmukhi', + '2637' => 'halantgurmukhi', + '2649' => 'khhagurmukhi', + '2650' => 'ghhagurmukhi', + '2651' => 'zagurmukhi', + '2652' => 'rragurmukhi', + '2654' => 'fagurmukhi', + '2662' => 'zerogurmukhi', + '2663' => 'onegurmukhi', + '2664' => 'twogurmukhi', + '2665' => 'threegurmukhi', + '2666' => 'fourgurmukhi', + '2667' => 'fivegurmukhi', + '2668' => 'sixgurmukhi', + '2669' => 'sevengurmukhi', + '2670' => 'eightgurmukhi', + '2671' => 'ninegurmukhi', + '2672' => 'tippigurmukhi', + '2673' => 'addakgurmukhi', + '2674' => 'irigurmukhi', + '2675' => 'uragurmukhi', + '2676' => 'ekonkargurmukhi', + '2689' => 'candrabindugujarati', + '2690' => 'anusvaragujarati', + '2691' => 'visargagujarati', + '2693' => 'agujarati', + '2694' => 'aagujarati', + '2695' => 'igujarati', + '2696' => 'iigujarati', + '2697' => 'ugujarati', + '2698' => 'uugujarati', + '2699' => 'rvocalicgujarati', + '2701' => 'ecandragujarati', + '2703' => 'egujarati', + '2704' => 'aigujarati', + '2705' => 'ocandragujarati', + '2707' => 'ogujarati', + '2708' => 'augujarati', + '2709' => 'kagujarati', + '2710' => 'khagujarati', + '2711' => 'gagujarati', + '2712' => 'ghagujarati', + '2713' => 'ngagujarati', + '2714' => 'cagujarati', + '2715' => 'chagujarati', + '2716' => 'jagujarati', + '2717' => 'jhagujarati', + '2718' => 'nyagujarati', + '2719' => 'ttagujarati', + '2720' => 'tthagujarati', + '2721' => 'ddagujarati', + '2722' => 'ddhagujarati', + '2723' => 'nnagujarati', + '2724' => 'tagujarati', + '2725' => 'thagujarati', + '2726' => 'dagujarati', + '2727' => 'dhagujarati', + '2728' => 'nagujarati', + '2730' => 'pagujarati', + '2731' => 'phagujarati', + '2732' => 'bagujarati', + '2733' => 'bhagujarati', + '2734' => 'magujarati', + '2735' => 'yagujarati', + '2736' => 'ragujarati', + '2738' => 'lagujarati', + '2739' => 'llagujarati', + '2741' => 'vagujarati', + '2742' => 'shagujarati', + '2743' => 'ssagujarati', + '2744' => 'sagujarati', + '2745' => 'hagujarati', + '2748' => 'nuktagujarati', + '2750' => 'aavowelsigngujarati', + '2751' => 'ivowelsigngujarati', + '2752' => 'iivowelsigngujarati', + '2753' => 'uvowelsigngujarati', + '2754' => 'uuvowelsigngujarati', + '2755' => 'rvocalicvowelsigngujarati', + '2756' => 'rrvocalicvowelsigngujarati', + '2757' => 'ecandravowelsigngujarati', + '2759' => 'evowelsigngujarati', + '2760' => 'aivowelsigngujarati', + '2761' => 'ocandravowelsigngujarati', + '2763' => 'ovowelsigngujarati', + '2764' => 'auvowelsigngujarati', + '2765' => 'viramagujarati', + '2768' => 'omgujarati', + '2784' => 'rrvocalicgujarati', + '2790' => 'zerogujarati', + '2791' => 'onegujarati', + '2792' => 'twogujarati', + '2793' => 'threegujarati', + '2794' => 'fourgujarati', + '2795' => 'fivegujarati', + '2796' => 'sixgujarati', + '2797' => 'sevengujarati', + '2798' => 'eightgujarati', + '2799' => 'ninegujarati', + '3585' => 'kokaithai', + '3586' => 'khokhaithai', + '3587' => 'khokhuatthai', + '3588' => 'khokhwaithai', + '3589' => 'khokhonthai', + '3590' => 'khorakhangthai', + '3591' => 'ngonguthai', + '3592' => 'chochanthai', + '3593' => 'chochingthai', + '3594' => 'chochangthai', + '3595' => 'sosothai', + '3596' => 'chochoethai', + '3597' => 'yoyingthai', + '3598' => 'dochadathai', + '3599' => 'topatakthai', + '3600' => 'thothanthai', + '3601' => 'thonangmonthothai', + '3602' => 'thophuthaothai', + '3603' => 'nonenthai', + '3604' => 'dodekthai', + '3605' => 'totaothai', + '3606' => 'thothungthai', + '3607' => 'thothahanthai', + '3608' => 'thothongthai', + '3609' => 'nonuthai', + '3610' => 'bobaimaithai', + '3611' => 'poplathai', + '3612' => 'phophungthai', + '3613' => 'fofathai', + '3614' => 'phophanthai', + '3615' => 'fofanthai', + '3616' => 'phosamphaothai', + '3617' => 'momathai', + '3618' => 'yoyakthai', + '3619' => 'roruathai', + '3620' => 'ruthai', + '3621' => 'lolingthai', + '3622' => 'luthai', + '3623' => 'wowaenthai', + '3624' => 'sosalathai', + '3625' => 'sorusithai', + '3626' => 'sosuathai', + '3627' => 'hohipthai', + '3628' => 'lochulathai', + '3629' => 'oangthai', + '3630' => 'honokhukthai', + '3631' => 'paiyannoithai', + '3632' => 'saraathai', + '3633' => 'maihanakatthai', + '3634' => 'saraaathai', + '3635' => 'saraamthai', + '3636' => 'saraithai', + '3637' => 'saraiithai', + '3638' => 'sarauethai', + '3639' => 'saraueethai', + '3640' => 'sarauthai', + '3641' => 'sarauuthai', + '3642' => 'phinthuthai', + '3647' => 'bahtthai', + '3648' => 'saraethai', + '3649' => 'saraaethai', + '3650' => 'saraothai', + '3651' => 'saraaimaimuanthai', + '3652' => 'saraaimaimalaithai', + '3653' => 'lakkhangyaothai', + '3654' => 'maiyamokthai', + '3655' => 'maitaikhuthai', + '3656' => 'maiekthai', + '3657' => 'maithothai', + '3658' => 'maitrithai', + '3659' => 'maichattawathai', + '3660' => 'thanthakhatthai', + '3661' => 'nikhahitthai', + '3662' => 'yamakkanthai', + '3663' => 'fongmanthai', + '3664' => 'zerothai', + '3665' => 'onethai', + '3666' => 'twothai', + '3667' => 'threethai', + '3668' => 'fourthai', + '3669' => 'fivethai', + '3670' => 'sixthai', + '3671' => 'seventhai', + '3672' => 'eightthai', + '3673' => 'ninethai', + '3674' => 'angkhankhuthai', + '3675' => 'khomutthai', + '7680' => 'Aringbelow', + '7681' => 'aringbelow', + '7682' => 'Bdotaccent', + '7683' => 'bdotaccent', + '7684' => 'Bdotbelow', + '7685' => 'bdotbelow', + '7686' => 'Blinebelow', + '7687' => 'blinebelow', + '7688' => 'Ccedillaacute', + '7689' => 'ccedillaacute', + '7690' => 'Ddotaccent', + '7691' => 'ddotaccent', + '7692' => 'Ddotbelow', + '7693' => 'ddotbelow', + '7694' => 'Dlinebelow', + '7695' => 'dlinebelow', + '7696' => 'Dcedilla', + '7697' => 'dcedilla', + '7698' => 'Dcircumflexbelow', + '7699' => 'dcircumflexbelow', + '7700' => 'Emacrongrave', + '7701' => 'emacrongrave', + '7702' => 'Emacronacute', + '7703' => 'emacronacute', + '7704' => 'Ecircumflexbelow', + '7705' => 'ecircumflexbelow', + '7706' => 'Etildebelow', + '7707' => 'etildebelow', + '7708' => 'Ecedillabreve', + '7709' => 'ecedillabreve', + '7710' => 'Fdotaccent', + '7711' => 'fdotaccent', + '7712' => 'Gmacron', + '7713' => 'gmacron', + '7714' => 'Hdotaccent', + '7715' => 'hdotaccent', + '7716' => 'Hdotbelow', + '7717' => 'hdotbelow', + '7718' => 'Hdieresis', + '7719' => 'hdieresis', + '7720' => 'Hcedilla', + '7721' => 'hcedilla', + '7722' => 'Hbrevebelow', + '7723' => 'hbrevebelow', + '7724' => 'Itildebelow', + '7725' => 'itildebelow', + '7726' => 'Idieresisacute', + '7727' => 'idieresisacute', + '7728' => 'Kacute', + '7729' => 'kacute', + '7730' => 'Kdotbelow', + '7731' => 'kdotbelow', + '7732' => 'Klinebelow', + '7733' => 'klinebelow', + '7734' => 'Ldotbelow', + '7735' => 'ldotbelow', + '7736' => 'Ldotbelowmacron', + '7737' => 'ldotbelowmacron', + '7738' => 'Llinebelow', + '7739' => 'llinebelow', + '7740' => 'Lcircumflexbelow', + '7741' => 'lcircumflexbelow', + '7742' => 'Macute', + '7743' => 'macute', + '7744' => 'Mdotaccent', + '7745' => 'mdotaccent', + '7746' => 'Mdotbelow', + '7747' => 'mdotbelow', + '7748' => 'Ndotaccent', + '7749' => 'ndotaccent', + '7750' => 'Ndotbelow', + '7751' => 'ndotbelow', + '7752' => 'Nlinebelow', + '7753' => 'nlinebelow', + '7754' => 'Ncircumflexbelow', + '7755' => 'ncircumflexbelow', + '7756' => 'Otildeacute', + '7757' => 'otildeacute', + '7758' => 'Otildedieresis', + '7759' => 'otildedieresis', + '7760' => 'Omacrongrave', + '7761' => 'omacrongrave', + '7762' => 'Omacronacute', + '7763' => 'omacronacute', + '7764' => 'Pacute', + '7765' => 'pacute', + '7766' => 'Pdotaccent', + '7767' => 'pdotaccent', + '7768' => 'Rdotaccent', + '7769' => 'rdotaccent', + '7770' => 'Rdotbelow', + '7771' => 'rdotbelow', + '7772' => 'Rdotbelowmacron', + '7773' => 'rdotbelowmacron', + '7774' => 'Rlinebelow', + '7775' => 'rlinebelow', + '7776' => 'Sdotaccent', + '7777' => 'sdotaccent', + '7778' => 'Sdotbelow', + '7779' => 'sdotbelow', + '7780' => 'Sacutedotaccent', + '7781' => 'sacutedotaccent', + '7782' => 'Scarondotaccent', + '7783' => 'scarondotaccent', + '7784' => 'Sdotbelowdotaccent', + '7785' => 'sdotbelowdotaccent', + '7786' => 'Tdotaccent', + '7787' => 'tdotaccent', + '7788' => 'Tdotbelow', + '7789' => 'tdotbelow', + '7790' => 'Tlinebelow', + '7791' => 'tlinebelow', + '7792' => 'Tcircumflexbelow', + '7793' => 'tcircumflexbelow', + '7794' => 'Udieresisbelow', + '7795' => 'udieresisbelow', + '7796' => 'Utildebelow', + '7797' => 'utildebelow', + '7798' => 'Ucircumflexbelow', + '7799' => 'ucircumflexbelow', + '7800' => 'Utildeacute', + '7801' => 'utildeacute', + '7802' => 'Umacrondieresis', + '7803' => 'umacrondieresis', + '7804' => 'Vtilde', + '7805' => 'vtilde', + '7806' => 'Vdotbelow', + '7807' => 'vdotbelow', + '7808' => 'Wgrave', + '7809' => 'wgrave', + '7810' => 'Wacute', + '7811' => 'wacute', + '7812' => 'Wdieresis', + '7813' => 'wdieresis', + '7814' => 'Wdotaccent', + '7815' => 'wdotaccent', + '7816' => 'Wdotbelow', + '7817' => 'wdotbelow', + '7818' => 'Xdotaccent', + '7819' => 'xdotaccent', + '7820' => 'Xdieresis', + '7821' => 'xdieresis', + '7822' => 'Ydotaccent', + '7823' => 'ydotaccent', + '7824' => 'Zcircumflex', + '7825' => 'zcircumflex', + '7826' => 'Zdotbelow', + '7827' => 'zdotbelow', + '7828' => 'Zlinebelow', + '7829' => 'zlinebelow', + '7830' => 'hlinebelow', + '7831' => 'tdieresis', + '7832' => 'wring', + '7833' => 'yring', + '7834' => 'arighthalfring', + '7835' => 'slongdotaccent', + '7840' => 'Adotbelow', + '7841' => 'adotbelow', + '7842' => 'Ahookabove', + '7843' => 'ahookabove', + '7844' => 'Acircumflexacute', + '7845' => 'acircumflexacute', + '7846' => 'Acircumflexgrave', + '7847' => 'acircumflexgrave', + '7848' => 'Acircumflexhookabove', + '7849' => 'acircumflexhookabove', + '7850' => 'Acircumflextilde', + '7851' => 'acircumflextilde', + '7852' => 'Acircumflexdotbelow', + '7853' => 'acircumflexdotbelow', + '7854' => 'Abreveacute', + '7855' => 'abreveacute', + '7856' => 'Abrevegrave', + '7857' => 'abrevegrave', + '7858' => 'Abrevehookabove', + '7859' => 'abrevehookabove', + '7860' => 'Abrevetilde', + '7861' => 'abrevetilde', + '7862' => 'Abrevedotbelow', + '7863' => 'abrevedotbelow', + '7864' => 'Edotbelow', + '7865' => 'edotbelow', + '7866' => 'Ehookabove', + '7867' => 'ehookabove', + '7868' => 'Etilde', + '7869' => 'etilde', + '7870' => 'Ecircumflexacute', + '7871' => 'ecircumflexacute', + '7872' => 'Ecircumflexgrave', + '7873' => 'ecircumflexgrave', + '7874' => 'Ecircumflexhookabove', + '7875' => 'ecircumflexhookabove', + '7876' => 'Ecircumflextilde', + '7877' => 'ecircumflextilde', + '7878' => 'Ecircumflexdotbelow', + '7879' => 'ecircumflexdotbelow', + '7880' => 'Ihookabove', + '7881' => 'ihookabove', + '7882' => 'Idotbelow', + '7883' => 'idotbelow', + '7884' => 'Odotbelow', + '7885' => 'odotbelow', + '7886' => 'Ohookabove', + '7887' => 'ohookabove', + '7888' => 'Ocircumflexacute', + '7889' => 'ocircumflexacute', + '7890' => 'Ocircumflexgrave', + '7891' => 'ocircumflexgrave', + '7892' => 'Ocircumflexhookabove', + '7893' => 'ocircumflexhookabove', + '7894' => 'Ocircumflextilde', + '7895' => 'ocircumflextilde', + '7896' => 'Ocircumflexdotbelow', + '7897' => 'ocircumflexdotbelow', + '7898' => 'Ohornacute', + '7899' => 'ohornacute', + '7900' => 'Ohorngrave', + '7901' => 'ohorngrave', + '7902' => 'Ohornhookabove', + '7903' => 'ohornhookabove', + '7904' => 'Ohorntilde', + '7905' => 'ohorntilde', + '7906' => 'Ohorndotbelow', + '7907' => 'ohorndotbelow', + '7908' => 'Udotbelow', + '7909' => 'udotbelow', + '7910' => 'Uhookabove', + '7911' => 'uhookabove', + '7912' => 'Uhornacute', + '7913' => 'uhornacute', + '7914' => 'Uhorngrave', + '7915' => 'uhorngrave', + '7916' => 'Uhornhookabove', + '7917' => 'uhornhookabove', + '7918' => 'Uhorntilde', + '7919' => 'uhorntilde', + '7920' => 'Uhorndotbelow', + '7921' => 'uhorndotbelow', + '7922' => 'Ygrave', + '7923' => 'ygrave', + '7924' => 'Ydotbelow', + '7925' => 'ydotbelow', + '7926' => 'Yhookabove', + '7927' => 'yhookabove', + '7928' => 'Ytilde', + '7929' => 'ytilde', + '8194' => 'enspace', + '8195' => 'emsp', + '8196' => 'emsp13', + '8197' => 'emsp14', + '8199' => 'numsp', + '8200' => 'puncsp', + '8201' => 'thinsp', + '8202' => 'hairsp', + '8203' => 'zerowidthspace', + '8204' => 'afii61664', + '8205' => 'afii301', + '8206' => 'afii299', + '8207' => 'afii300', + '8208' => 'hyphentwo', + '8210' => 'figuredash', + '8211' => 'endash', + '8212' => 'emdash', + '8213' => 'afii00208', + '8214' => 'dblverticalbar', + '8215' => 'underscoredbl', + '8216' => 'quoteleft', + '8217' => 'quoteright', + '8218' => 'quotesinglbase', + '8219' => 'quotereversed', + '8220' => 'quotedblleft', + '8221' => 'quotedblright', + '8222' => 'quotedblbase', + '8224' => 'dagger', + '8225' => 'daggerdbl', + '8226' => 'bullet', + '8228' => 'onedotenleader', + '8229' => 'twodotenleader', + '8230' => 'ellipsis', + '8236' => 'afii61573', + '8237' => 'afii61574', + '8238' => 'afii61575', + '8240' => 'perthousand', + '8242' => 'minute', + '8243' => 'second', + '8244' => 'tprime', + '8245' => 'primereversed', + '8249' => 'guilsinglleft', + '8250' => 'guilsinglright', + '8251' => 'referencemark', + '8252' => 'exclamdbl', + '8254' => 'overline', + '8257' => 'caret', + '8258' => 'asterism', + '8259' => 'hybull', + '8260' => 'fraction', + '8304' => 'zerosuperior', + '8308' => 'foursuperior', + '8309' => 'fivesuperior', + '8310' => 'sixsuperior', + '8311' => 'sevensuperior', + '8312' => 'eightsuperior', + '8313' => 'ninesuperior', + '8314' => 'plussuperior', + '8316' => 'equalsuperior', + '8317' => 'parenleftsuperior', + '8318' => 'parenrightsuperior', + '8319' => 'nsuperior', + '8320' => 'zeroinferior', + '8321' => 'oneinferior', + '8322' => 'twoinferior', + '8323' => 'threeinferior', + '8324' => 'fourinferior', + '8325' => 'fiveinferior', + '8326' => 'sixinferior', + '8327' => 'seveninferior', + '8328' => 'eightinferior', + '8329' => 'nineinferior', + '8333' => 'parenleftinferior', + '8334' => 'parenrightinferior', + '8353' => 'colonmonetary', + '8354' => 'cruzeiro', + '8355' => 'franc', + '8356' => 'lira', + '8359' => 'peseta', + '8361' => 'won', + '8362' => 'afii57636', + '8363' => 'dong', + '8364' => 'Euro', + '8411' => 'tdot', + '8412' => 'DotDot', + '8451' => 'centigrade', + '8453' => 'afii61248', + '8457' => 'fahrenheit', + '8459' => 'hamilt', + '8463' => 'planck', + '8465' => 'Ifraktur', + '8466' => 'lagran', + '8467' => 'afii61289', + '8470' => 'afii61352', + '8471' => 'copysr', + '8472' => 'weierstrass', + '8476' => 'Rfraktur', + '8478' => 'prescription', + '8481' => 'telephone', + '8482' => 'trademark', + '8486' => 'Omega', + '8491' => 'angstrom', + '8492' => 'bernou', + '8494' => 'estimated', + '8499' => 'phmmat', + '8500' => 'order', + '8501' => 'aleph', + '8502' => 'beth', + '8503' => 'gimel', + '8504' => 'daleth', + '8531' => 'onethird', + '8532' => 'twothirds', + '8533' => 'frac15', + '8534' => 'frac25', + '8535' => 'frac35', + '8536' => 'frac45', + '8537' => 'frac16', + '8538' => 'frac56', + '8539' => 'oneeighth', + '8540' => 'threeeighths', + '8541' => 'fiveeighths', + '8542' => 'seveneighths', + '8544' => 'Oneroman', + '8545' => 'Tworoman', + '8546' => 'Threeroman', + '8547' => 'Fourroman', + '8548' => 'Fiveroman', + '8549' => 'Sixroman', + '8550' => 'Sevenroman', + '8551' => 'Eightroman', + '8552' => 'Nineroman', + '8553' => 'Tenroman', + '8554' => 'Elevenroman', + '8555' => 'Twelveroman', + '8560' => 'oneroman', + '8561' => 'tworoman', + '8562' => 'threeroman', + '8563' => 'fourroman', + '8564' => 'fiveroman', + '8565' => 'sixroman', + '8566' => 'sevenroman', + '8567' => 'eightroman', + '8568' => 'nineroman', + '8569' => 'tenroman', + '8570' => 'elevenroman', + '8571' => 'twelveroman', + '8592' => 'arrowleft', + '8593' => 'arrowup', + '8594' => 'arrowright', + '8595' => 'arrowdown', + '8596' => 'arrowboth', + '8597' => 'arrowupdn', + '8598' => 'arrowupleft', + '8599' => 'arrowupright', + '8600' => 'arrowdownright', + '8601' => 'arrowdownleft', + '8602' => 'nlarr', + '8603' => 'nrarr', + '8605' => 'rarrw', + '8606' => 'Larr', + '8608' => 'Rarr', + '8610' => 'larrtl', + '8611' => 'rarrtl', + '8614' => 'map', + '8616' => 'arrowupdnbse', + '8617' => 'larrhk', + '8618' => 'rarrhk', + '8619' => 'larrlp', + '8620' => 'rarrlp', + '8621' => 'harrw', + '8622' => 'nharr', + '8624' => 'lsh', + '8625' => 'rsh', + '8629' => 'carriagereturn', + '8630' => 'cularr', + '8631' => 'curarr', + '8634' => 'olarr', + '8635' => 'orarr', + '8636' => 'harpoonleftbarbup', + '8637' => 'lhard', + '8638' => 'uharr', + '8639' => 'uharl', + '8640' => 'harpoonrightbarbup', + '8641' => 'rhard', + '8642' => 'dharr', + '8643' => 'dharl', + '8644' => 'arrowrightoverleft', + '8645' => 'arrowupleftofdown', + '8646' => 'arrowleftoverright', + '8647' => 'larr2', + '8648' => 'uarr2', + '8649' => 'rarr2', + '8650' => 'darr2', + '8651' => 'lrhar2', + '8652' => 'rlhar2', + '8653' => 'arrowleftdblstroke', + '8654' => 'nhArr', + '8655' => 'arrowrightdblstroke', + '8656' => 'arrowdblleft', + '8657' => 'arrowdblup', + '8658' => 'arrowdblright', + '8659' => 'arrowdbldown', + '8660' => 'arrowdblboth', + '8661' => 'vArr', + '8666' => 'lAarr', + '8667' => 'rAarr', + '8670' => 'pageup', + '8671' => 'pagedown', + '8672' => 'arrowdashleft', + '8673' => 'arrowdashup', + '8674' => 'arrowdashright', + '8675' => 'arrowdashdown', + '8676' => 'arrowtableft', + '8677' => 'arrowtabright', + '8678' => 'arrowleftwhite', + '8679' => 'arrowupwhite', + '8680' => 'arrowrightwhite', + '8681' => 'arrowdownwhite', + '8682' => 'capslock', + '8704' => 'universal', + '8705' => 'comp', + '8706' => 'partialdiff', + '8707' => 'existential', + '8708' => 'nexist', + '8709' => 'emptyset', + '8710' => 'Delta', + '8711' => 'gradient', + '8712' => 'element', + '8713' => 'notelement', + '8714' => 'epsis', + '8715' => 'suchthat', + '8716' => 'notcontains', + '8717' => 'bepsi', + '8719' => 'product', + '8720' => 'samalg', + '8721' => 'summation', + '8722' => 'minus', + '8723' => 'minusplus', + '8724' => 'plusdo', + '8725' => 'fraction', + '8726' => 'setmn', + '8727' => 'asteriskmath', + '8728' => 'compfn', + '8729' => 'periodcentered', + '8730' => 'radical', + '8733' => 'proportional', + '8734' => 'infinity', + '8735' => 'orthogonal', + '8736' => 'angle', + '8737' => 'angmsd', + '8738' => 'angsph', + '8739' => 'divides', + '8740' => 'nmid', + '8741' => 'parallel', + '8742' => 'notparallel', + '8743' => 'logicaland', + '8744' => 'logicalor', + '8745' => 'intersection', + '8746' => 'union', + '8747' => 'integral', + '8748' => 'dblintegral', + '8750' => 'contourintegral', + '8756' => 'therefore', + '8757' => 'because', + '8758' => 'ratio', + '8759' => 'proportion', + '8764' => 'similar', + '8765' => 'reversedtilde', + '8768' => 'wreath', + '8769' => 'nsim', + '8771' => 'asymptoticallyequal', + '8772' => 'nsime', + '8773' => 'congruent', + '8775' => 'ncong', + '8776' => 'approxequal', + '8777' => 'nap', + '8778' => 'ape', + '8780' => 'allequal', + '8782' => 'bump', + '8783' => 'bumpe', + '8784' => 'approaches', + '8785' => 'geometricallyequal', + '8786' => 'approxequalorimage', + '8787' => 'imageorapproximatelyequal', + '8788' => 'colone', + '8789' => 'ecolon', + '8790' => 'ecir', + '8791' => 'cire', + '8793' => 'wedgeq', + '8796' => 'trie', + '8800' => 'notequal', + '8801' => 'equivalence', + '8802' => 'notidentical', + '8804' => 'lessequal', + '8805' => 'greaterequal', + '8806' => 'lessoverequal', + '8807' => 'greateroverequal', + '8808' => 'lvnE', + '8809' => 'gvnE', + '8810' => 'muchless', + '8811' => 'muchgreater', + '8812' => 'twixt', + '8814' => 'notless', + '8815' => 'notgreater', + '8816' => 'notlessnorequal', + '8817' => 'notgreaternorequal', + '8818' => 'lessorequivalent', + '8819' => 'greaterorequivalent', + '8822' => 'lessorgreater', + '8823' => 'greaterorless', + '8825' => 'notgreaternorless', + '8826' => 'precedes', + '8827' => 'succeeds', + '8828' => 'cupre', + '8829' => 'sccue', + '8830' => 'prsim', + '8831' => 'scsim', + '8832' => 'notprecedes', + '8833' => 'notsucceeds', + '8834' => 'propersubset', + '8835' => 'propersuperset', + '8836' => 'notsubset', + '8837' => 'notsuperset', + '8838' => 'reflexsubset', + '8839' => 'reflexsuperset', + '8840' => 'nsube', + '8841' => 'nsupe', + '8842' => 'subsetnotequal', + '8843' => 'supersetnotequal', + '8846' => 'uplus', + '8847' => 'sqsub', + '8848' => 'sqsup', + '8849' => 'sqsube', + '8850' => 'sqsupe', + '8851' => 'sqcap', + '8852' => 'sqcup', + '8853' => 'circleplus', + '8854' => 'minuscircle', + '8855' => 'circlemultiply', + '8856' => 'osol', + '8857' => 'circleot', + '8858' => 'ocir', + '8859' => 'oast', + '8861' => 'odash', + '8862' => 'plusb', + '8863' => 'minusb', + '8864' => 'timesb', + '8865' => 'sdotb', + '8866' => 'vdash', + '8867' => 'tackleft', + '8868' => 'tackdown', + '8869' => 'perpendicular', + '8871' => 'models', + '8872' => 'vDash', + '8873' => 'Vdash', + '8874' => 'Vvdash', + '8876' => 'nvdash', + '8877' => 'nvDash', + '8878' => 'nVdash', + '8879' => 'nVDash', + '8882' => 'vltri', + '8883' => 'vrtri', + '8884' => 'ltrie', + '8885' => 'rtrie', + '8888' => 'mumap', + '8890' => 'intcal', + '8891' => 'veebar', + '8892' => 'barwed', + '8895' => 'righttriangle', + '8900' => 'diam', + '8901' => 'dotmath', + '8902' => 'sstarf', + '8903' => 'divonx', + '8904' => 'bowtie', + '8905' => 'ltimes', + '8906' => 'rtimes', + '8907' => 'lthree', + '8908' => 'rthree', + '8909' => 'bsime', + '8910' => 'curlyor', + '8911' => 'curlyand', + '8912' => 'Sub', + '8913' => 'Sup', + '8914' => 'Cap', + '8915' => 'Cup', + '8916' => 'fork', + '8919' => 'gsdot', + '8920' => 'Ll', + '8921' => 'Gg', + '8922' => 'lessequalorgreater', + '8923' => 'greaterequalorless', + '8924' => 'els', + '8925' => 'egs', + '8926' => 'cuepr', + '8927' => 'cuesc', + '8928' => 'npre', + '8929' => 'nsce', + '8934' => 'lnsim', + '8935' => 'gnsim', + '8936' => 'prnsim', + '8937' => 'scnsim', + '8938' => 'nltri', + '8939' => 'nrtri', + '8940' => 'nltrie', + '8941' => 'nrtrie', + '8942' => 'ellipsisvertical', + '8962' => 'house', + '8963' => 'control', + '8965' => 'projective', + '8966' => 'Barwed', + '8968' => 'lceil', + '8969' => 'rceil', + '8970' => 'lfloor', + '8971' => 'rfloor', + '8972' => 'drcrop', + '8973' => 'dlcrop', + '8974' => 'urcrop', + '8975' => 'ulcrop', + '8976' => 'revlogicalnot', + '8978' => 'arc', + '8981' => 'telrec', + '8984' => 'propellor', + '8988' => 'ulcorn', + '8989' => 'urcorn', + '8990' => 'dlcorn', + '8991' => 'drcorn', + '8992' => 'integraltp', + '8993' => 'integralbt', + '8994' => 'frown', + '8995' => 'smile', + '8997' => 'option', + '8998' => 'deleteright', + '8999' => 'clear', + '9001' => 'angleleft', + '9002' => 'angleright', + '9003' => 'deleteleft', + '9251' => 'blank', + '9312' => 'onecircle', + '9313' => 'twocircle', + '9314' => 'threecircle', + '9315' => 'fourcircle', + '9316' => 'fivecircle', + '9317' => 'sixcircle', + '9318' => 'sevencircle', + '9319' => 'eightcircle', + '9320' => 'ninecircle', + '9321' => 'tencircle', + '9322' => 'elevencircle', + '9323' => 'twelvecircle', + '9324' => 'thirteencircle', + '9325' => 'fourteencircle', + '9326' => 'fifteencircle', + '9327' => 'sixteencircle', + '9328' => 'seventeencircle', + '9329' => 'eighteencircle', + '9330' => 'nineteencircle', + '9331' => 'twentycircle', + '9332' => 'oneparen', + '9333' => 'twoparen', + '9334' => 'threeparen', + '9335' => 'fourparen', + '9336' => 'fiveparen', + '9337' => 'sixparen', + '9338' => 'sevenparen', + '9339' => 'eightparen', + '9340' => 'nineparen', + '9341' => 'tenparen', + '9342' => 'elevenparen', + '9343' => 'twelveparen', + '9344' => 'thirteenparen', + '9345' => 'fourteenparen', + '9346' => 'fifteenparen', + '9347' => 'sixteenparen', + '9348' => 'seventeenparen', + '9349' => 'eighteenparen', + '9350' => 'nineteenparen', + '9351' => 'twentyparen', + '9352' => 'oneperiod', + '9353' => 'twoperiod', + '9354' => 'threeperiod', + '9355' => 'fourperiod', + '9356' => 'fiveperiod', + '9357' => 'sixperiod', + '9358' => 'sevenperiod', + '9359' => 'eightperiod', + '9360' => 'nineperiod', + '9361' => 'tenperiod', + '9362' => 'elevenperiod', + '9363' => 'twelveperiod', + '9364' => 'thirteenperiod', + '9365' => 'fourteenperiod', + '9366' => 'fifteenperiod', + '9367' => 'sixteenperiod', + '9368' => 'seventeenperiod', + '9369' => 'eighteenperiod', + '9370' => 'nineteenperiod', + '9371' => 'twentyperiod', + '9372' => 'aparen', + '9373' => 'bparen', + '9374' => 'cparen', + '9375' => 'dparen', + '9376' => 'eparen', + '9377' => 'fparen', + '9378' => 'gparen', + '9379' => 'hparen', + '9380' => 'iparen', + '9381' => 'jparen', + '9382' => 'kparen', + '9383' => 'lparen', + '9384' => 'mparen', + '9385' => 'nparen', + '9386' => 'oparen', + '9387' => 'pparen', + '9388' => 'qparen', + '9389' => 'rparen', + '9390' => 'sparen', + '9391' => 'tparen', + '9392' => 'uparen', + '9393' => 'vparen', + '9394' => 'wparen', + '9395' => 'xparen', + '9396' => 'yparen', + '9397' => 'zparen', + '9398' => 'Acircle', + '9399' => 'Bcircle', + '9400' => 'Ccircle', + '9401' => 'Dcircle', + '9402' => 'Ecircle', + '9403' => 'Fcircle', + '9404' => 'Gcircle', + '9405' => 'Hcircle', + '9406' => 'Icircle', + '9407' => 'Jcircle', + '9408' => 'Kcircle', + '9409' => 'Lcircle', + '9410' => 'Mcircle', + '9411' => 'Ncircle', + '9412' => 'Ocircle', + '9413' => 'Pcircle', + '9414' => 'Qcircle', + '9415' => 'Rcircle', + '9416' => 'Scircle', + '9417' => 'Tcircle', + '9418' => 'Ucircle', + '9419' => 'Vcircle', + '9420' => 'Wcircle', + '9421' => 'Xcircle', + '9422' => 'Ycircle', + '9423' => 'Zcircle', + '9424' => 'acircle', + '9425' => 'bcircle', + '9426' => 'ccircle', + '9427' => 'dcircle', + '9428' => 'ecircle', + '9429' => 'fcircle', + '9430' => 'gcircle', + '9431' => 'hcircle', + '9432' => 'icircle', + '9433' => 'jcircle', + '9434' => 'kcircle', + '9435' => 'lcircle', + '9436' => 'mcircle', + '9437' => 'ncircle', + '9438' => 'ocircle', + '9439' => 'pcircle', + '9440' => 'qcircle', + '9441' => 'rcircle', + '9442' => 'scircle', + '9443' => 'tcircle', + '9444' => 'ucircle', + '9445' => 'vcircle', + '9446' => 'wcircle', + '9447' => 'xcircle', + '9448' => 'ycircle', + '9449' => 'zcircle', + '9472' => 'SF100000', + '9474' => 'SF110000', + '9484' => 'SF010000', + '9488' => 'SF030000', + '9492' => 'SF020000', + '9496' => 'SF040000', + '9500' => 'SF080000', + '9508' => 'SF090000', + '9516' => 'SF060000', + '9524' => 'SF070000', + '9532' => 'SF050000', + '9552' => 'SF430000', + '9553' => 'SF240000', + '9554' => 'SF510000', + '9555' => 'SF520000', + '9556' => 'SF390000', + '9557' => 'SF220000', + '9558' => 'SF210000', + '9559' => 'SF250000', + '9560' => 'SF500000', + '9561' => 'SF490000', + '9562' => 'SF380000', + '9563' => 'SF280000', + '9564' => 'SF270000', + '9565' => 'SF260000', + '9566' => 'SF360000', + '9567' => 'SF370000', + '9568' => 'SF420000', + '9569' => 'SF190000', + '9570' => 'SF200000', + '9571' => 'SF230000', + '9572' => 'SF470000', + '9573' => 'SF480000', + '9574' => 'SF410000', + '9575' => 'SF450000', + '9576' => 'SF460000', + '9577' => 'SF400000', + '9578' => 'SF540000', + '9579' => 'SF530000', + '9580' => 'SF440000', + '9600' => 'upblock', + '9604' => 'dnblock', + '9608' => 'block', + '9612' => 'lfblock', + '9616' => 'rtblock', + '9617' => 'ltshade', + '9618' => 'shade', + '9619' => 'dkshade', + '9632' => 'filledbox', + '9633' => 'H22073', + '9635' => 'squarewhitewithsmallblack', + '9636' => 'squarehorizontalfill', + '9637' => 'squareverticalfill', + '9638' => 'squareorthogonalcrosshatchfill', + '9639' => 'squareupperlefttolowerrightfill', + '9640' => 'squareupperrighttolowerleftfill', + '9641' => 'squarediagonalcrosshatchfill', + '9642' => 'H18543', + '9643' => 'H18551', + '9644' => 'filledrect', + '9645' => 'rect', + '9646' => 'marker', + '9650' => 'triagup', + '9651' => 'whiteuppointingtriangle', + '9652' => 'blackuppointingsmalltriangle', + '9653' => 'whiteuppointingsmalltriangle', + '9654' => 'blackrightpointingtriangle', + '9655' => 'whiterightpointingtriangle', + '9656' => 'rtrif', + '9657' => 'whiterightpointingsmalltriangle', + '9658' => 'triagrt', + '9660' => 'triagdn', + '9661' => 'whitedownpointingtriangle', + '9662' => 'dtrif', + '9663' => 'whitedownpointingsmalltriangle', + '9664' => 'blackleftpointingtriangle', + '9665' => 'whiteleftpointingtriangle', + '9666' => 'ltrif', + '9667' => 'whiteleftpointingsmalltriangle', + '9668' => 'triaglf', + '9670' => 'blackdiamond', + '9671' => 'whitediamond', + '9672' => 'whitediamondcontainingblacksmalldiamond', + '9673' => 'fisheye', + '9674' => 'lozenge', + '9675' => 'circle', + '9676' => 'dottedcircle', + '9678' => 'bullseye', + '9679' => 'H18533', + '9680' => 'circlewithlefthalfblack', + '9681' => 'circlewithrighthalfblack', + '9687' => 'a81', + '9688' => 'invbullet', + '9689' => 'invcircle', + '9698' => 'blacklowerrighttriangle', + '9699' => 'blacklowerlefttriangle', + '9700' => 'blackupperlefttriangle', + '9701' => 'blackupperrighttriangle', + '9702' => 'openbullet', + '9711' => 'largecircle', + '9733' => 'blackstar', + '9734' => 'whitestar', + '9742' => 'telephoneblack', + '9743' => 'whitetelephone', + '9755' => 'a11', + '9756' => 'pointingindexleftwhite', + '9757' => 'pointingindexupwhite', + '9758' => 'pointingindexrightwhite', + '9759' => 'pointingindexdownwhite', + '9775' => 'yinyang', + '9786' => 'smileface', + '9787' => 'invsmileface', + '9788' => 'sun', + '9792' => 'female', + '9793' => 'earth', + '9794' => 'male', + '9824' => 'spade', + '9825' => 'heartsuitwhite', + '9826' => 'diamondsuitwhite', + '9827' => 'club', + '9828' => 'spadesuitwhite', + '9829' => 'heart', + '9830' => 'diamond', + '9831' => 'clubsuitwhite', + '9832' => 'hotsprings', + '9833' => 'quarternote', + '9834' => 'musicalnote', + '9835' => 'musicalnotedbl', + '9836' => 'beamedsixteenthnotes', + '9837' => 'musicflatsign', + '9838' => 'natur', + '9839' => 'musicsharpsign', + '9985' => 'a1', + '9986' => 'a2', + '9987' => 'a202', + '9988' => 'a3', + '9990' => 'a5', + '9991' => 'a119', + '9992' => 'a118', + '9993' => 'a117', + '9996' => 'a13', + '9997' => 'a14', + '9998' => 'a15', + '9999' => 'a16', + '10000' => 'a105', + '10001' => 'a17', + '10002' => 'a18', + '10003' => 'checkmark', + '10004' => 'a20', + '10005' => 'a21', + '10006' => 'a22', + '10007' => 'a23', + '10008' => 'a24', + '10009' => 'a25', + '10010' => 'a26', + '10011' => 'a27', + '10012' => 'a28', + '10013' => 'a6', + '10014' => 'a7', + '10015' => 'a8', + '10016' => 'a9', + '10017' => 'a10', + '10018' => 'a29', + '10019' => 'a30', + '10020' => 'a31', + '10021' => 'a32', + '10022' => 'a33', + '10023' => 'a34', + '10025' => 'a36', + '10026' => 'a37', + '10027' => 'a38', + '10028' => 'a39', + '10029' => 'a40', + '10030' => 'a41', + '10031' => 'a42', + '10032' => 'a43', + '10033' => 'a44', + '10034' => 'a45', + '10035' => 'a46', + '10036' => 'a47', + '10037' => 'a48', + '10038' => 'a49', + '10039' => 'a50', + '10040' => 'a51', + '10041' => 'a52', + '10042' => 'a53', + '10043' => 'a54', + '10044' => 'a55', + '10045' => 'a56', + '10046' => 'a57', + '10047' => 'a58', + '10048' => 'a59', + '10049' => 'a60', + '10050' => 'a61', + '10051' => 'a62', + '10052' => 'a63', + '10053' => 'a64', + '10054' => 'a65', + '10055' => 'a66', + '10056' => 'a67', + '10057' => 'a68', + '10058' => 'a69', + '10059' => 'a70', + '10061' => 'a72', + '10063' => 'a74', + '10064' => 'a203', + '10065' => 'a75', + '10066' => 'a204', + '10070' => 'a79', + '10072' => 'a82', + '10073' => 'a83', + '10074' => 'a84', + '10075' => 'a97', + '10076' => 'a98', + '10077' => 'a99', + '10078' => 'a100', + '10081' => 'a101', + '10082' => 'a102', + '10083' => 'a103', + '10084' => 'a104', + '10085' => 'a106', + '10086' => 'a107', + '10087' => 'a108', + '10102' => 'a130', + '10103' => 'a131', + '10104' => 'a132', + '10105' => 'a133', + '10106' => 'a134', + '10107' => 'a135', + '10108' => 'a136', + '10109' => 'a137', + '10110' => 'a138', + '10111' => 'a139', + '10112' => 'a140', + '10113' => 'a141', + '10114' => 'a142', + '10115' => 'a143', + '10116' => 'a144', + '10117' => 'a145', + '10118' => 'a146', + '10119' => 'a147', + '10120' => 'a148', + '10121' => 'a149', + '10122' => 'onecircleinversesansserif', + '10123' => 'twocircleinversesansserif', + '10124' => 'threecircleinversesansserif', + '10125' => 'fourcircleinversesansserif', + '10126' => 'fivecircleinversesansserif', + '10127' => 'sixcircleinversesansserif', + '10128' => 'sevencircleinversesansserif', + '10129' => 'eightcircleinversesansserif', + '10130' => 'ninecircleinversesansserif', + '10131' => 'a159', + '10132' => 'a160', + '10136' => 'a196', + '10137' => 'a165', + '10138' => 'a192', + '10139' => 'a166', + '10140' => 'a167', + '10141' => 'a168', + '10142' => 'arrowrightheavy', + '10143' => 'a170', + '10144' => 'a171', + '10145' => 'a172', + '10146' => 'a173', + '10147' => 'a162', + '10148' => 'a174', + '10149' => 'a175', + '10150' => 'a176', + '10151' => 'a177', + '10152' => 'a178', + '10153' => 'a179', + '10154' => 'a193', + '10155' => 'a180', + '10156' => 'a199', + '10157' => 'a181', + '10158' => 'a200', + '10159' => 'a182', + '10161' => 'a201', + '10162' => 'a183', + '10163' => 'a184', + '10164' => 'a197', + '10165' => 'a185', + '10166' => 'a194', + '10167' => 'a198', + '10168' => 'a186', + '10169' => 'a195', + '10170' => 'a187', + '10171' => 'a188', + '10172' => 'a189', + '10173' => 'a190', + '10174' => 'a191', + '12288' => 'ideographicspace', + '12289' => 'ideographiccomma', + '12290' => 'ideographicperiod', + '12291' => 'dittomark', + '12292' => 'jis', + '12293' => 'ideographiciterationmark', + '12294' => 'ideographicclose', + '12295' => 'ideographiczero', + '12296' => 'anglebracketleft', + '12297' => 'anglebracketright', + '12298' => 'dblanglebracketleft', + '12299' => 'dblanglebracketright', + '12300' => 'cornerbracketleft', + '12301' => 'cornerbracketright', + '12302' => 'whitecornerbracketleft', + '12303' => 'whitecornerbracketright', + '12304' => 'blacklenticularbracketleft', + '12305' => 'blacklenticularbracketright', + '12306' => 'postalmark', + '12307' => 'getamark', + '12308' => 'tortoiseshellbracketleft', + '12309' => 'tortoiseshellbracketright', + '12310' => 'whitelenticularbracketleft', + '12311' => 'whitelenticularbracketright', + '12312' => 'whitetortoiseshellbracketleft', + '12313' => 'whitetortoiseshellbracketright', + '12316' => 'wavedash', + '12317' => 'quotedblprimereversed', + '12318' => 'quotedblprime', + '12320' => 'postalmarkface', + '12321' => 'onehangzhou', + '12322' => 'twohangzhou', + '12323' => 'threehangzhou', + '12324' => 'fourhangzhou', + '12325' => 'fivehangzhou', + '12326' => 'sixhangzhou', + '12327' => 'sevenhangzhou', + '12328' => 'eighthangzhou', + '12329' => 'ninehangzhou', + '12342' => 'circlepostalmark', + '12353' => 'asmallhiragana', + '12354' => 'ahiragana', + '12355' => 'ismallhiragana', + '12356' => 'ihiragana', + '12357' => 'usmallhiragana', + '12358' => 'uhiragana', + '12359' => 'esmallhiragana', + '12360' => 'ehiragana', + '12361' => 'osmallhiragana', + '12362' => 'ohiragana', + '12363' => 'kahiragana', + '12364' => 'gahiragana', + '12365' => 'kihiragana', + '12366' => 'gihiragana', + '12367' => 'kuhiragana', + '12368' => 'guhiragana', + '12369' => 'kehiragana', + '12370' => 'gehiragana', + '12371' => 'kohiragana', + '12372' => 'gohiragana', + '12373' => 'sahiragana', + '12374' => 'zahiragana', + '12375' => 'sihiragana', + '12376' => 'zihiragana', + '12377' => 'suhiragana', + '12378' => 'zuhiragana', + '12379' => 'sehiragana', + '12380' => 'zehiragana', + '12381' => 'sohiragana', + '12382' => 'zohiragana', + '12383' => 'tahiragana', + '12384' => 'dahiragana', + '12385' => 'tihiragana', + '12386' => 'dihiragana', + '12387' => 'tusmallhiragana', + '12388' => 'tuhiragana', + '12389' => 'duhiragana', + '12390' => 'tehiragana', + '12391' => 'dehiragana', + '12392' => 'tohiragana', + '12393' => 'dohiragana', + '12394' => 'nahiragana', + '12395' => 'nihiragana', + '12396' => 'nuhiragana', + '12397' => 'nehiragana', + '12398' => 'nohiragana', + '12399' => 'hahiragana', + '12400' => 'bahiragana', + '12401' => 'pahiragana', + '12402' => 'hihiragana', + '12403' => 'bihiragana', + '12404' => 'pihiragana', + '12405' => 'huhiragana', + '12406' => 'buhiragana', + '12407' => 'puhiragana', + '12408' => 'hehiragana', + '12409' => 'behiragana', + '12410' => 'pehiragana', + '12411' => 'hohiragana', + '12412' => 'bohiragana', + '12413' => 'pohiragana', + '12414' => 'mahiragana', + '12415' => 'mihiragana', + '12416' => 'muhiragana', + '12417' => 'mehiragana', + '12418' => 'mohiragana', + '12419' => 'yasmallhiragana', + '12420' => 'yahiragana', + '12421' => 'yusmallhiragana', + '12422' => 'yuhiragana', + '12423' => 'yosmallhiragana', + '12424' => 'yohiragana', + '12425' => 'rahiragana', + '12426' => 'rihiragana', + '12427' => 'ruhiragana', + '12428' => 'rehiragana', + '12429' => 'rohiragana', + '12430' => 'wasmallhiragana', + '12431' => 'wahiragana', + '12432' => 'wihiragana', + '12433' => 'wehiragana', + '12434' => 'wohiragana', + '12435' => 'nhiragana', + '12436' => 'vuhiragana', + '12443' => 'voicedmarkkana', + '12444' => 'semivoicedmarkkana', + '12445' => 'iterationhiragana', + '12446' => 'voicediterationhiragana', + '12449' => 'asmallkatakana', + '12450' => 'akatakana', + '12451' => 'ismallkatakana', + '12452' => 'ikatakana', + '12453' => 'usmallkatakana', + '12454' => 'ukatakana', + '12455' => 'esmallkatakana', + '12456' => 'ekatakana', + '12457' => 'osmallkatakana', + '12458' => 'okatakana', + '12459' => 'kakatakana', + '12460' => 'gakatakana', + '12461' => 'kikatakana', + '12462' => 'gikatakana', + '12463' => 'kukatakana', + '12464' => 'gukatakana', + '12465' => 'kekatakana', + '12466' => 'gekatakana', + '12467' => 'kokatakana', + '12468' => 'gokatakana', + '12469' => 'sakatakana', + '12470' => 'zakatakana', + '12471' => 'sikatakana', + '12472' => 'zikatakana', + '12473' => 'sukatakana', + '12474' => 'zukatakana', + '12475' => 'sekatakana', + '12476' => 'zekatakana', + '12477' => 'sokatakana', + '12478' => 'zokatakana', + '12479' => 'takatakana', + '12480' => 'dakatakana', + '12481' => 'tikatakana', + '12482' => 'dikatakana', + '12483' => 'tusmallkatakana', + '12484' => 'tukatakana', + '12485' => 'dukatakana', + '12486' => 'tekatakana', + '12487' => 'dekatakana', + '12488' => 'tokatakana', + '12489' => 'dokatakana', + '12490' => 'nakatakana', + '12491' => 'nikatakana', + '12492' => 'nukatakana', + '12493' => 'nekatakana', + '12494' => 'nokatakana', + '12495' => 'hakatakana', + '12496' => 'bakatakana', + '12497' => 'pakatakana', + '12498' => 'hikatakana', + '12499' => 'bikatakana', + '12500' => 'pikatakana', + '12501' => 'hukatakana', + '12502' => 'bukatakana', + '12503' => 'pukatakana', + '12504' => 'hekatakana', + '12505' => 'bekatakana', + '12506' => 'pekatakana', + '12507' => 'hokatakana', + '12508' => 'bokatakana', + '12509' => 'pokatakana', + '12510' => 'makatakana', + '12511' => 'mikatakana', + '12512' => 'mukatakana', + '12513' => 'mekatakana', + '12514' => 'mokatakana', + '12515' => 'yasmallkatakana', + '12516' => 'yakatakana', + '12517' => 'yusmallkatakana', + '12518' => 'yukatakana', + '12519' => 'yosmallkatakana', + '12520' => 'yokatakana', + '12521' => 'rakatakana', + '12522' => 'rikatakana', + '12523' => 'rukatakana', + '12524' => 'rekatakana', + '12525' => 'rokatakana', + '12526' => 'wasmallkatakana', + '12527' => 'wakatakana', + '12528' => 'wikatakana', + '12529' => 'wekatakana', + '12530' => 'wokatakana', + '12531' => 'nkatakana', + '12532' => 'vukatakana', + '12533' => 'kasmallkatakana', + '12534' => 'kesmallkatakana', + '12535' => 'vakatakana', + '12536' => 'vikatakana', + '12537' => 'vekatakana', + '12538' => 'vokatakana', + '12539' => 'dotkatakana', + '12540' => 'prolongedkana', + '12541' => 'iterationkatakana', + '12542' => 'voicediterationkatakana', + '12549' => 'bbopomofo', + '12550' => 'pbopomofo', + '12551' => 'mbopomofo', + '12552' => 'fbopomofo', + '12553' => 'dbopomofo', + '12554' => 'tbopomofo', + '12555' => 'nbopomofo', + '12556' => 'lbopomofo', + '12557' => 'gbopomofo', + '12558' => 'kbopomofo', + '12559' => 'hbopomofo', + '12560' => 'jbopomofo', + '12561' => 'qbopomofo', + '12562' => 'xbopomofo', + '12563' => 'zhbopomofo', + '12564' => 'chbopomofo', + '12565' => 'shbopomofo', + '12566' => 'rbopomofo', + '12567' => 'zbopomofo', + '12568' => 'cbopomofo', + '12569' => 'sbopomofo', + '12570' => 'abopomofo', + '12571' => 'obopomofo', + '12572' => 'ebopomofo', + '12573' => 'ehbopomofo', + '12574' => 'aibopomofo', + '12575' => 'eibopomofo', + '12576' => 'aubopomofo', + '12577' => 'oubopomofo', + '12578' => 'anbopomofo', + '12579' => 'enbopomofo', + '12580' => 'angbopomofo', + '12581' => 'engbopomofo', + '12582' => 'erbopomofo', + '12583' => 'ibopomofo', + '12584' => 'ubopomofo', + '12585' => 'iubopomofo', + '12593' => 'kiyeokkorean', + '12594' => 'ssangkiyeokkorean', + '12595' => 'kiyeoksioskorean', + '12596' => 'nieunkorean', + '12597' => 'nieuncieuckorean', + '12598' => 'nieunhieuhkorean', + '12599' => 'tikeutkorean', + '12600' => 'ssangtikeutkorean', + '12601' => 'rieulkorean', + '12602' => 'rieulkiyeokkorean', + '12603' => 'rieulmieumkorean', + '12604' => 'rieulpieupkorean', + '12605' => 'rieulsioskorean', + '12606' => 'rieulthieuthkorean', + '12607' => 'rieulphieuphkorean', + '12608' => 'rieulhieuhkorean', + '12609' => 'mieumkorean', + '12610' => 'pieupkorean', + '12611' => 'ssangpieupkorean', + '12612' => 'pieupsioskorean', + '12613' => 'sioskorean', + '12614' => 'ssangsioskorean', + '12615' => 'ieungkorean', + '12616' => 'cieuckorean', + '12617' => 'ssangcieuckorean', + '12618' => 'chieuchkorean', + '12619' => 'khieukhkorean', + '12620' => 'thieuthkorean', + '12621' => 'phieuphkorean', + '12622' => 'hieuhkorean', + '12623' => 'akorean', + '12624' => 'aekorean', + '12625' => 'yakorean', + '12626' => 'yaekorean', + '12627' => 'eokorean', + '12628' => 'ekorean', + '12629' => 'yeokorean', + '12630' => 'yekorean', + '12631' => 'okorean', + '12632' => 'wakorean', + '12633' => 'waekorean', + '12634' => 'oekorean', + '12635' => 'yokorean', + '12636' => 'ukorean', + '12637' => 'weokorean', + '12638' => 'wekorean', + '12639' => 'wikorean', + '12640' => 'yukorean', + '12641' => 'eukorean', + '12642' => 'yikorean', + '12643' => 'ikorean', + '12644' => 'hangulfiller', + '12645' => 'ssangnieunkorean', + '12646' => 'nieuntikeutkorean', + '12647' => 'nieunsioskorean', + '12648' => 'nieunpansioskorean', + '12649' => 'rieulkiyeoksioskorean', + '12650' => 'rieultikeutkorean', + '12651' => 'rieulpieupsioskorean', + '12652' => 'rieulpansioskorean', + '12653' => 'rieulyeorinhieuhkorean', + '12654' => 'mieumpieupkorean', + '12655' => 'mieumsioskorean', + '12656' => 'mieumpansioskorean', + '12657' => 'kapyeounmieumkorean', + '12658' => 'pieupkiyeokkorean', + '12659' => 'pieuptikeutkorean', + '12660' => 'pieupsioskiyeokkorean', + '12661' => 'pieupsiostikeutkorean', + '12662' => 'pieupcieuckorean', + '12663' => 'pieupthieuthkorean', + '12664' => 'kapyeounpieupkorean', + '12665' => 'kapyeounssangpieupkorean', + '12666' => 'sioskiyeokkorean', + '12667' => 'siosnieunkorean', + '12668' => 'siostikeutkorean', + '12669' => 'siospieupkorean', + '12670' => 'sioscieuckorean', + '12671' => 'pansioskorean', + '12672' => 'ssangieungkorean', + '12673' => 'yesieungkorean', + '12674' => 'yesieungsioskorean', + '12675' => 'yesieungpansioskorean', + '12676' => 'kapyeounphieuphkorean', + '12677' => 'ssanghieuhkorean', + '12678' => 'yeorinhieuhkorean', + '12679' => 'yoyakorean', + '12680' => 'yoyaekorean', + '12681' => 'yoikorean', + '12682' => 'yuyeokorean', + '12683' => 'yuyekorean', + '12684' => 'yuikorean', + '12685' => 'araeakorean', + '12686' => 'araeaekorean', + '12800' => 'kiyeokparenkorean', + '12801' => 'nieunparenkorean', + '12802' => 'tikeutparenkorean', + '12803' => 'rieulparenkorean', + '12804' => 'mieumparenkorean', + '12805' => 'pieupparenkorean', + '12806' => 'siosparenkorean', + '12807' => 'ieungparenkorean', + '12808' => 'cieucparenkorean', + '12809' => 'chieuchparenkorean', + '12810' => 'khieukhparenkorean', + '12811' => 'thieuthparenkorean', + '12812' => 'phieuphparenkorean', + '12813' => 'hieuhparenkorean', + '12814' => 'kiyeokaparenkorean', + '12815' => 'nieunaparenkorean', + '12816' => 'tikeutaparenkorean', + '12817' => 'rieulaparenkorean', + '12818' => 'mieumaparenkorean', + '12819' => 'pieupaparenkorean', + '12820' => 'siosaparenkorean', + '12821' => 'ieungaparenkorean', + '12822' => 'cieucaparenkorean', + '12823' => 'chieuchaparenkorean', + '12824' => 'khieukhaparenkorean', + '12825' => 'thieuthaparenkorean', + '12826' => 'phieuphaparenkorean', + '12827' => 'hieuhaparenkorean', + '12828' => 'cieucuparenkorean', + '12832' => 'oneideographicparen', + '12833' => 'twoideographicparen', + '12834' => 'threeideographicparen', + '12835' => 'fourideographicparen', + '12836' => 'fiveideographicparen', + '12837' => 'sixideographicparen', + '12838' => 'sevenideographicparen', + '12839' => 'eightideographicparen', + '12840' => 'nineideographicparen', + '12841' => 'tenideographicparen', + '12842' => 'ideographicmoonparen', + '12843' => 'ideographicfireparen', + '12844' => 'ideographicwaterparen', + '12845' => 'ideographicwoodparen', + '12846' => 'ideographicmetalparen', + '12847' => 'ideographicearthparen', + '12848' => 'ideographicsunparen', + '12849' => 'ideographicstockparen', + '12850' => 'ideographichaveparen', + '12851' => 'ideographicsocietyparen', + '12852' => 'ideographicnameparen', + '12853' => 'ideographicspecialparen', + '12854' => 'ideographicfinancialparen', + '12855' => 'ideographiccongratulationparen', + '12856' => 'ideographiclaborparen', + '12857' => 'ideographicrepresentparen', + '12858' => 'ideographiccallparen', + '12859' => 'ideographicstudyparen', + '12860' => 'ideographicsuperviseparen', + '12861' => 'ideographicenterpriseparen', + '12862' => 'ideographicresourceparen', + '12863' => 'ideographicallianceparen', + '12864' => 'ideographicfestivalparen', + '12866' => 'ideographicselfparen', + '12867' => 'ideographicreachparen', + '12896' => 'kiyeokcirclekorean', + '12897' => 'nieuncirclekorean', + '12898' => 'tikeutcirclekorean', + '12899' => 'rieulcirclekorean', + '12900' => 'mieumcirclekorean', + '12901' => 'pieupcirclekorean', + '12902' => 'sioscirclekorean', + '12903' => 'ieungcirclekorean', + '12904' => 'cieuccirclekorean', + '12905' => 'chieuchcirclekorean', + '12906' => 'khieukhcirclekorean', + '12907' => 'thieuthcirclekorean', + '12908' => 'phieuphcirclekorean', + '12909' => 'hieuhcirclekorean', + '12910' => 'kiyeokacirclekorean', + '12911' => 'nieunacirclekorean', + '12912' => 'tikeutacirclekorean', + '12913' => 'rieulacirclekorean', + '12914' => 'mieumacirclekorean', + '12915' => 'pieupacirclekorean', + '12916' => 'siosacirclekorean', + '12917' => 'ieungacirclekorean', + '12918' => 'cieucacirclekorean', + '12919' => 'chieuchacirclekorean', + '12920' => 'khieukhacirclekorean', + '12921' => 'thieuthacirclekorean', + '12922' => 'phieuphacirclekorean', + '12923' => 'hieuhacirclekorean', + '12927' => 'koreanstandardsymbol', + '12938' => 'ideographmooncircle', + '12939' => 'ideographfirecircle', + '12940' => 'ideographwatercircle', + '12941' => 'ideographwoodcircle', + '12942' => 'ideographmetalcircle', + '12943' => 'ideographearthcircle', + '12944' => 'ideographsuncircle', + '12948' => 'ideographnamecircle', + '12950' => 'ideographicfinancialcircle', + '12952' => 'ideographiclaborcircle', + '12953' => 'ideographicsecretcircle', + '12957' => 'ideographicexcellentcircle', + '12958' => 'ideographicprintcircle', + '12963' => 'ideographiccorrectcircle', + '12964' => 'ideographichighcircle', + '12965' => 'ideographiccentrecircle', + '12966' => 'ideographiclowcircle', + '12967' => 'ideographicleftcircle', + '12968' => 'ideographicrightcircle', + '12969' => 'ideographicmedicinecircle', + '13056' => 'apaatosquare', + '13059' => 'aarusquare', + '13061' => 'intisquare', + '13069' => 'karoriisquare', + '13076' => 'kirosquare', + '13077' => 'kiroguramusquare', + '13078' => 'kiromeetorusquare', + '13080' => 'guramusquare', + '13086' => 'kooposquare', + '13090' => 'sentisquare', + '13091' => 'sentosquare', + '13094' => 'dorusquare', + '13095' => 'tonsquare', + '13098' => 'haitusquare', + '13099' => 'paasentosquare', + '13105' => 'birusquare', + '13107' => 'huiitosquare', + '13110' => 'hekutaarusquare', + '13113' => 'herutusquare', + '13115' => 'peezisquare', + '13122' => 'hoonsquare', + '13127' => 'mansyonsquare', + '13129' => 'mirisquare', + '13130' => 'miribaarusquare', + '13133' => 'meetorusquare', + '13134' => 'yaadosquare', + '13137' => 'rittorusquare', + '13143' => 'wattosquare', + '13179' => 'heiseierasquare', + '13180' => 'syouwaerasquare', + '13181' => 'taisyouerasquare', + '13182' => 'meizierasquare', + '13183' => 'corporationsquare', + '13184' => 'paampssquare', + '13185' => 'nasquare', + '13186' => 'muasquare', + '13187' => 'masquare', + '13188' => 'kasquare', + '13189' => 'KBsquare', + '13190' => 'MBsquare', + '13191' => 'GBsquare', + '13192' => 'calsquare', + '13193' => 'kcalsquare', + '13194' => 'pfsquare', + '13195' => 'nfsquare', + '13196' => 'mufsquare', + '13197' => 'mugsquare', + '13198' => 'squaremg', + '13199' => 'squarekg', + '13200' => 'Hzsquare', + '13201' => 'khzsquare', + '13202' => 'mhzsquare', + '13203' => 'ghzsquare', + '13204' => 'thzsquare', + '13205' => 'mulsquare', + '13206' => 'mlsquare', + '13207' => 'dlsquare', + '13208' => 'klsquare', + '13209' => 'fmsquare', + '13210' => 'nmsquare', + '13211' => 'mumsquare', + '13212' => 'squaremm', + '13213' => 'squarecm', + '13214' => 'squarekm', + '13215' => 'mmsquaredsquare', + '13216' => 'cmsquaredsquare', + '13217' => 'squaremsquared', + '13218' => 'kmsquaredsquare', + '13219' => 'mmcubedsquare', + '13220' => 'cmcubedsquare', + '13221' => 'mcubedsquare', + '13222' => 'kmcubedsquare', + '13223' => 'moverssquare', + '13224' => 'moverssquaredsquare', + '13225' => 'pasquare', + '13226' => 'kpasquare', + '13227' => 'mpasquare', + '13228' => 'gpasquare', + '13229' => 'radsquare', + '13230' => 'radoverssquare', + '13231' => 'radoverssquaredsquare', + '13232' => 'pssquare', + '13233' => 'nssquare', + '13234' => 'mussquare', + '13235' => 'mssquare', + '13236' => 'pvsquare', + '13237' => 'nvsquare', + '13238' => 'muvsquare', + '13239' => 'mvsquare', + '13240' => 'kvsquare', + '13241' => 'mvmegasquare', + '13242' => 'pwsquare', + '13243' => 'nwsquare', + '13244' => 'muwsquare', + '13245' => 'mwsquare', + '13246' => 'kwsquare', + '13247' => 'mwmegasquare', + '13248' => 'kohmsquare', + '13249' => 'mohmsquare', + '13250' => 'amsquare', + '13251' => 'bqsquare', + '13252' => 'squarecc', + '13253' => 'cdsquare', + '13254' => 'coverkgsquare', + '13255' => 'cosquare', + '13256' => 'dbsquare', + '13257' => 'gysquare', + '13258' => 'hasquare', + '13259' => 'HPsquare', + '13261' => 'KKsquare', + '13262' => 'squarekmcapital', + '13263' => 'ktsquare', + '13264' => 'lmsquare', + '13265' => 'squareln', + '13266' => 'squarelog', + '13267' => 'lxsquare', + '13268' => 'mbsquare', + '13269' => 'squaremil', + '13270' => 'molsquare', + '13272' => 'pmsquare', + '13275' => 'srsquare', + '13276' => 'svsquare', + '13277' => 'wbsquare', + '21316' => 'twentyhangzhou', + '61441' => 'fi', + '61442' => 'fl', + '61472' => 'space', + '61473' => 'pencil', + '61474' => 'scissors', + '61475' => 'scissorscutting', + '61476' => 'readingglasses', + '61477' => 'bell', + '61478' => 'book', + '61479' => 'candle', + '61480' => 'telephonesolid', + '61481' => 'telhandsetcirc', + '61482' => 'envelopeback', + '61483' => 'envelopefront', + '61484' => 'mailboxflagdwn', + '61485' => 'mailboxflagup', + '61486' => 'mailbxopnflgup', + '61487' => 'mailbxopnflgdwn', + '61488' => 'folder', + '61489' => 'folderopen', + '61490' => 'filetalltext1', + '61491' => 'filetalltext', + '61492' => 'filetalltext3', + '61493' => 'filecabinet', + '61494' => 'hourglass', + '61495' => 'keyboard', + '61496' => 'mouse2button', + '61497' => 'ballpoint', + '61498' => 'pc', + '61499' => 'harddisk', + '61500' => 'floppy3', + '61501' => 'floppy5', + '61502' => 'tapereel', + '61503' => 'handwrite', + '61504' => 'handwriteleft', + '61505' => 'handv', + '61506' => 'handok', + '61507' => 'thumbup', + '61508' => 'thumbdown', + '61509' => 'handptleft', + '61510' => 'handptright', + '61511' => 'handptup', + '61512' => 'handptdwn', + '61513' => 'handhalt', + '61514' => 'smileface', + '61515' => 'neutralface', + '61516' => 'frownface', + '61517' => 'bomb', + '61518' => 'skullcrossbones', + '61519' => 'flag', + '61520' => 'pennant', + '61521' => 'airplane', + '61522' => 'sunshine', + '61523' => 'droplet', + '61524' => 'snowflake', + '61525' => 'crossoutline', + '61526' => 'crossshadow', + '61527' => 'crossceltic', + '61528' => 'crossmaltese', + '61529' => 'starofdavid', + '61530' => 'crescentstar', + '61531' => 'yinyang', + '61532' => 'om', + '61533' => 'wheel', + '61534' => 'aries', + '61535' => 'taurus', + '61536' => 'gemini', + '61537' => 'cancer', + '61538' => 'leo', + '61539' => 'virgo', + '61540' => 'libra', + '61541' => 'scorpio', + '61542' => 'saggitarius', + '61543' => 'capricorn', + '61544' => 'aquarius', + '61545' => 'pisces', + '61546' => 'ampersanditlc', + '61547' => 'ampersandit', + '61548' => 'circle6', + '61549' => 'circleshadowdwn', + '61550' => 'square6', + '61551' => 'box3', + '61552' => 'box4', + '61553' => 'boxshadowdwn', + '61554' => 'boxshadowup', + '61555' => 'lozenge4', + '61556' => 'lozenge6', + '61557' => 'rhombus6', + '61558' => 'xrhombus', + '61559' => 'rhombus4', + '61560' => 'clear', + '61561' => 'escape', + '61562' => 'command', + '61563' => 'rosette', + '61564' => 'rosettesolid', + '61565' => 'quotedbllftbld', + '61566' => 'quotedblrtbld', + '61568' => 'zerosans', + '61569' => 'onesans', + '61570' => 'twosans', + '61571' => 'threesans', + '61572' => 'foursans', + '61573' => 'fivesans', + '61574' => 'sixsans', + '61575' => 'sevensans', + '61576' => 'eightsans', + '61577' => 'ninesans', + '61578' => 'tensans', + '61579' => 'zerosansinv', + '61580' => 'onesansinv', + '61581' => 'twosansinv', + '61582' => 'threesansinv', + '61583' => 'foursansinv', + '61584' => 'fivesansinv', + '61585' => 'sixsansinv', + '61586' => 'sevensansinv', + '61587' => 'eightsansinv', + '61588' => 'ninesansinv', + '61589' => 'tensansinv', + '61590' => 'budleafne', + '61591' => 'budleafnw', + '61592' => 'budleafsw', + '61593' => 'budleafse', + '61594' => 'vineleafboldne', + '61595' => 'vineleafboldnw', + '61596' => 'vineleafboldsw', + '61597' => 'vineleafboldse', + '61598' => 'circle2', + '61599' => 'circle4', + '61600' => 'square2', + '61601' => 'ring2', + '61602' => 'ring4', + '61603' => 'ring6', + '61604' => 'ringbutton2', + '61605' => 'target', + '61606' => 'circleshadowup', + '61607' => 'square4', + '61608' => 'box2', + '61609' => 'tristar2', + '61610' => 'crosstar2', + '61611' => 'pentastar2', + '61612' => 'hexstar2', + '61613' => 'octastar2', + '61614' => 'dodecastar3', + '61615' => 'octastar4', + '61616' => 'registersquare', + '61617' => 'registercircle', + '61618' => 'cuspopen', + '61619' => 'cuspopen1', + '61620' => 'query', + '61621' => 'circlestar', + '61622' => 'starshadow', + '61623' => 'oneoclock', + '61624' => 'twooclock', + '61625' => 'threeoclock', + '61626' => 'fouroclock', + '61627' => 'fiveoclock', + '61628' => 'sixoclock', + '61629' => 'sevenoclock', + '61630' => 'eightoclock', + '61631' => 'nineoclock', + '61632' => 'tenoclock', + '61633' => 'elevenoclock', + '61634' => 'twelveoclock', + '61635' => 'arrowdwnleft1', + '61636' => 'arrowdwnrt1', + '61637' => 'arrowupleft1', + '61638' => 'arrowuprt1', + '61639' => 'arrowleftup1', + '61640' => 'arrowrtup1', + '61641' => 'arrowleftdwn1', + '61642' => 'arrowrtdwn1', + '61643' => 'quiltsquare2', + '61644' => 'quiltsquare2inv', + '61645' => 'leafccwsw', + '61646' => 'leafccwnw', + '61647' => 'leafccwse', + '61648' => 'leafccwne', + '61649' => 'leafnw', + '61650' => 'leafsw', + '61651' => 'leafne', + '61652' => 'leafse', + '61653' => 'deleteleft', + '61654' => 'deleteright', + '61655' => 'head2left', + '61656' => 'head2right', + '61657' => 'head2up', + '61658' => 'head2down', + '61659' => 'circleleft', + '61660' => 'circleright', + '61661' => 'circleup', + '61662' => 'circledown', + '61663' => 'barb2left', + '61664' => 'barb2right', + '61665' => 'barb2up', + '61666' => 'barb2down', + '61667' => 'barb2nw', + '61668' => 'barb2ne', + '61669' => 'barb2sw', + '61670' => 'barb2se', + '61671' => 'barb4left', + '61672' => 'barb4right', + '61673' => 'barb4up', + '61674' => 'barb4down', + '61675' => 'barb4nw', + '61676' => 'barb4ne', + '61677' => 'barb4sw', + '61678' => 'barb4se', + '61679' => 'bleft', + '61680' => 'bright', + '61681' => 'bup', + '61682' => 'bdown', + '61683' => 'bleftright', + '61684' => 'bupdown', + '61685' => 'bnw', + '61686' => 'bne', + '61687' => 'bsw', + '61688' => 'bse', + '61689' => 'bdash1', + '61690' => 'bdash2', + '61691' => 'xmarkbld', + '61692' => 'checkbld', + '61693' => 'boxxmarkbld', + '61694' => 'boxcheckbld', + '61695' => 'windowslogo', + '63166' => 'dotlessj', + '63167' => 'LL', + '63168' => 'll', + '63169' => 'Scedilla', + '63170' => 'scedilla', + '63171' => 'commaaccent', + '63172' => 'afii10063', + '63173' => 'afii10064', + '63174' => 'afii10192', + '63175' => 'afii10831', + '63176' => 'afii10832', + '63177' => 'Acute', + '63178' => 'Caron', + '63179' => 'Dieresis', + '63180' => 'DieresisAcute', + '63181' => 'DieresisGrave', + '63182' => 'Grave', + '63183' => 'Hungarumlaut', + '63184' => 'Macron', + '63185' => 'cyrBreve', + '63186' => 'cyrFlex', + '63187' => 'dblGrave', + '63188' => 'cyrbreve', + '63189' => 'cyrflex', + '63190' => 'dblgrave', + '63191' => 'dieresisacute', + '63192' => 'dieresisgrave', + '63193' => 'copyrightserif', + '63194' => 'registerserif', + '63195' => 'trademarkserif', + '63196' => 'onefitted', + '63197' => 'rupiah', + '63198' => 'threequartersemdash', + '63199' => 'centinferior', + '63200' => 'centsuperior', + '63201' => 'commainferior', + '63202' => 'commasuperior', + '63203' => 'dollarinferior', + '63204' => 'dollarsuperior', + '63205' => 'hypheninferior', + '63206' => 'hyphensuperior', + '63207' => 'periodinferior', + '63208' => 'periodsuperior', + '63209' => 'asuperior', + '63210' => 'bsuperior', + '63211' => 'dsuperior', + '63212' => 'esuperior', + '63213' => 'isuperior', + '63214' => 'lsuperior', + '63215' => 'msuperior', + '63216' => 'osuperior', + '63217' => 'rsuperior', + '63218' => 'ssuperior', + '63219' => 'tsuperior', + '63220' => 'Brevesmall', + '63221' => 'Caronsmall', + '63222' => 'Circumflexsmall', + '63223' => 'Dotaccentsmall', + '63224' => 'Hungarumlautsmall', + '63225' => 'Lslashsmall', + '63226' => 'OEsmall', + '63227' => 'Ogoneksmall', + '63228' => 'Ringsmall', + '63229' => 'Scaronsmall', + '63230' => 'Tildesmall', + '63231' => 'Zcaronsmall', + '63265' => 'exclamsmall', + '63268' => 'dollaroldstyle', + '63270' => 'ampersandsmall', + '63280' => 'zerooldstyle', + '63281' => 'oneoldstyle', + '63282' => 'twooldstyle', + '63283' => 'threeoldstyle', + '63284' => 'fouroldstyle', + '63285' => 'fiveoldstyle', + '63286' => 'sixoldstyle', + '63287' => 'sevenoldstyle', + '63288' => 'eightoldstyle', + '63289' => 'nineoldstyle', + '63295' => 'questionsmall', + '63328' => 'Gravesmall', + '63329' => 'Asmall', + '63330' => 'Bsmall', + '63331' => 'Csmall', + '63332' => 'Dsmall', + '63333' => 'Esmall', + '63334' => 'Fsmall', + '63335' => 'Gsmall', + '63336' => 'Hsmall', + '63337' => 'Ismall', + '63338' => 'Jsmall', + '63339' => 'Ksmall', + '63340' => 'Lsmall', + '63341' => 'Msmall', + '63342' => 'Nsmall', + '63343' => 'Osmall', + '63344' => 'Psmall', + '63345' => 'Qsmall', + '63346' => 'Rsmall', + '63347' => 'Ssmall', + '63348' => 'Tsmall', + '63349' => 'Usmall', + '63350' => 'Vsmall', + '63351' => 'Wsmall', + '63352' => 'Xsmall', + '63353' => 'Ysmall', + '63354' => 'Zsmall', + '63393' => 'exclamdownsmall', + '63394' => 'centoldstyle', + '63400' => 'Dieresissmall', + '63407' => 'Macronsmall', + '63412' => 'Acutesmall', + '63416' => 'Cedillasmall', + '63423' => 'questiondownsmall', + '63456' => 'Agravesmall', + '63457' => 'Aacutesmall', + '63458' => 'Acircumflexsmall', + '63459' => 'Atildesmall', + '63460' => 'Adieresissmall', + '63461' => 'Aringsmall', + '63462' => 'AEsmall', + '63463' => 'Ccedillasmall', + '63464' => 'Egravesmall', + '63465' => 'Eacutesmall', + '63466' => 'Ecircumflexsmall', + '63467' => 'Edieresissmall', + '63468' => 'Igravesmall', + '63469' => 'Iacutesmall', + '63470' => 'Icircumflexsmall', + '63471' => 'Idieresissmall', + '63472' => 'Ethsmall', + '63473' => 'Ntildesmall', + '63474' => 'Ogravesmall', + '63475' => 'Oacutesmall', + '63476' => 'Ocircumflexsmall', + '63477' => 'Otildesmall', + '63478' => 'Odieresissmall', + '63480' => 'Oslashsmall', + '63481' => 'Ugravesmall', + '63482' => 'Uacutesmall', + '63483' => 'Ucircumflexsmall', + '63484' => 'Udieresissmall', + '63485' => 'Yacutesmall', + '63486' => 'Thornsmall', + '63487' => 'Ydieresissmall', + '63620' => 'maihanakatleftthai', + '63621' => 'saraileftthai', + '63622' => 'saraiileftthai', + '63623' => 'saraueleftthai', + '63624' => 'saraueeleftthai', + '63625' => 'maitaikhuleftthai', + '63626' => 'maiekupperleftthai', + '63627' => 'maieklowrightthai', + '63628' => 'maieklowleftthai', + '63629' => 'maithoupperleftthai', + '63630' => 'maitholowrightthai', + '63631' => 'maitholowleftthai', + '63632' => 'maitriupperleftthai', + '63633' => 'maitrilowrightthai', + '63634' => 'maitrilowleftthai', + '63635' => 'maichattawaupperleftthai', + '63636' => 'maichattawalowrightthai', + '63637' => 'maichattawalowleftthai', + '63638' => 'thanthakhatupperleftthai', + '63639' => 'thanthakhatlowrightthai', + '63640' => 'thanthakhatlowleftthai', + '63641' => 'nikhahitleftthai', + '63703' => 'a89', + '63704' => 'a90', + '63705' => 'a93', + '63706' => 'a94', + '63707' => 'a91', + '63708' => 'a92', + '63709' => 'a205', + '63710' => 'a85', + '63711' => 'a206', + '63712' => 'a86', + '63713' => 'a87', + '63714' => 'a88', + '63715' => 'a95', + '63716' => 'a96', + '63717' => 'radicalex', + '63718' => 'arrowvertex', + '63719' => 'arrowhorizex', + '63720' => 'registersans', + '63721' => 'copyrightsans', + '63722' => 'trademarksans', + '63723' => 'parenlefttp', + '63724' => 'parenleftex', + '63725' => 'parenleftbt', + '63726' => 'bracketlefttp', + '63727' => 'bracketleftex', + '63728' => 'bracketleftbt', + '63729' => 'bracelefttp', + '63730' => 'braceleftmid', + '63731' => 'braceleftbt', + '63732' => 'braceex', + '63733' => 'integralex', + '63734' => 'parenrighttp', + '63735' => 'parenrightex', + '63736' => 'parenrightbt', + '63737' => 'bracketrighttp', + '63738' => 'bracketrightex', + '63739' => 'bracketrightbt', + '63740' => 'bracerighttp', + '63741' => 'bracerightmid', + '63742' => 'bracerightbt', + '63743' => 'apple', + '64256' => 'ff', + '64257' => 'fi', + '64258' => 'fl', + '64259' => 'ffi', + '64260' => 'ffl', + '64287' => 'afii57705', + '64288' => 'ayinaltonehebrew', + '64298' => 'afii57694', + '64299' => 'afii57695', + '64300' => 'shindageshshindot', + '64301' => 'shindageshsindot', + '64302' => 'alefpatahhebrew', + '64303' => 'alefqamatshebrew', + '64304' => 'alefdageshhebrew', + '64305' => 'betdagesh', + '64306' => 'gimeldagesh', + '64307' => 'daletdagesh', + '64308' => 'hedagesh', + '64309' => 'afii57723', + '64310' => 'zayindagesh', + '64312' => 'tetdagesh', + '64313' => 'yoddagesh', + '64314' => 'finalkafdagesh', + '64315' => 'kafdagesh', + '64316' => 'lameddagesh', + '64318' => 'memdagesh', + '64320' => 'nundagesh', + '64321' => 'samekhdagesh', + '64323' => 'pefinaldageshhebrew', + '64324' => 'pedagesh', + '64326' => 'tsadidagesh', + '64327' => 'qofdagesh', + '64328' => 'reshdageshhebrew', + '64329' => 'shindagesh', + '64330' => 'tavdages', + '64331' => 'afii57700', + '64332' => 'betrafehebrew', + '64333' => 'kafrafehebrew', + '64334' => 'perafehebrew', + '64335' => 'aleflamedhebrew', + '64343' => 'pehfinalarabic', + '64344' => 'pehinitialarabic', + '64345' => 'pehmedialarabic', + '64359' => 'ttehfinalarabic', + '64360' => 'ttehinitialarabic', + '64361' => 'ttehmedialarabic', + '64363' => 'vehfinalarabic', + '64364' => 'vehinitialarabic', + '64365' => 'vehmedialarabic', + '64379' => 'tchehfinalarabic', + '64380' => 'tchehinitialarabic', + '64381' => 'tchehmedialarabic', + '64393' => 'ddalfinalarabic', + '64395' => 'jehfinalarabic', + '64397' => 'rrehfinalarabic', + '64403' => 'gaffinalarabic', + '64404' => 'gafinitialarabic', + '64405' => 'gafmedialarabic', + '64415' => 'noonghunnafinalarabic', + '64420' => 'hehhamzaaboveisolatedarabic', + '64421' => 'hehhamzaabovefinalarabic', + '64423' => 'hehfinalaltonearabic', + '64424' => 'hehinitialaltonearabic', + '64425' => 'hehmedialaltonearabic', + '64431' => 'yehbarreefinalarabic', + '64520' => 'behmeemisolatedarabic', + '64523' => 'tehjeemisolatedarabic', + '64524' => 'tehhahisolatedarabic', + '64526' => 'tehmeemisolatedarabic', + '64584' => 'meemmeemisolatedarabic', + '64587' => 'noonjeemisolatedarabic', + '64590' => 'noonmeemisolatedarabic', + '64600' => 'yehmeemisolatedarabic', + '64606' => 'shaddadammatanarabic', + '64607' => 'shaddakasratanarabic', + '64608' => 'shaddafathaarabic', + '64609' => 'shaddadammaarabic', + '64610' => 'shaddakasraarabic', + '64621' => 'behnoonfinalarabic', + '64627' => 'tehnoonfinalarabic', + '64653' => 'noonnoonfinalarabic', + '64660' => 'yehnoonfinalarabic', + '64671' => 'behmeeminitialarabic', + '64673' => 'tehjeeminitialarabic', + '64674' => 'tehhahinitialarabic', + '64676' => 'tehmeeminitialarabic', + '64713' => 'lamjeeminitialarabic', + '64714' => 'lamhahinitialarabic', + '64715' => 'lamkhahinitialarabic', + '64716' => 'lammeeminitialarabic', + '64721' => 'meemmeeminitialarabic', + '64722' => 'noonjeeminitialarabic', + '64725' => 'noonmeeminitialarabic', + '64733' => 'yehmeeminitialarabic', + '64830' => 'parenleftaltonearabic', + '64831' => 'parenrightaltonearabic', + '64904' => 'lammeemhahinitialarabic', + '65010' => 'lamlamhehisolatedarabic', + '65018' => 'sallallahoualayhewasallamarabic', + '65072' => 'twodotleadervertical', + '65073' => 'emdashvertical', + '65074' => 'endashvertical', + '65075' => 'underscorevertical', + '65076' => 'wavyunderscorevertical', + '65077' => 'parenleftvertical', + '65078' => 'parenrightvertical', + '65079' => 'braceleftvertical', + '65080' => 'bracerightvertical', + '65081' => 'tortoiseshellbracketleftvertical', + '65082' => 'tortoiseshellbracketrightvertical', + '65083' => 'blacklenticularbracketleftvertical', + '65084' => 'blacklenticularbracketrightvertical', + '65085' => 'dblanglebracketleftvertical', + '65086' => 'dblanglebracketrightvertical', + '65087' => 'anglebracketleftvertical', + '65088' => 'anglebracketrightvertical', + '65089' => 'cornerbracketleftvertical', + '65090' => 'cornerbracketrightvertical', + '65091' => 'whitecornerbracketleftvertical', + '65092' => 'whitecornerbracketrightvertical', + '65097' => 'overlinedashed', + '65098' => 'overlinecenterline', + '65099' => 'overlinewavy', + '65100' => 'overlinedblwavy', + '65101' => 'lowlinedashed', + '65102' => 'lowlinecenterline', + '65103' => 'underscorewavy', + '65104' => 'commasmall', + '65106' => 'periodsmall', + '65108' => 'semicolonsmall', + '65109' => 'colonsmall', + '65113' => 'parenleftsmall', + '65114' => 'parenrightsmall', + '65115' => 'braceleftsmall', + '65116' => 'bracerightsmall', + '65117' => 'tortoiseshellbracketleftsmall', + '65118' => 'tortoiseshellbracketrightsmall', + '65119' => 'numbersignsmall', + '65121' => 'asterisksmall', + '65122' => 'plussmall', + '65123' => 'hyphensmall', + '65124' => 'lesssmall', + '65125' => 'greatersmall', + '65126' => 'equalsmall', + '65129' => 'dollarsmall', + '65130' => 'percentsmall', + '65131' => 'atsmall', + '65154' => 'alefmaddaabovefinalarabic', + '65156' => 'alefhamzaabovefinalarabic', + '65158' => 'wawhamzaabovefinalarabic', + '65160' => 'alefhamzabelowfinalarabic', + '65162' => 'yehhamzaabovefinalarabic', + '65163' => 'yehhamzaaboveinitialarabic', + '65164' => 'yehhamzaabovemedialarabic', + '65166' => 'aleffinalarabic', + '65168' => 'behfinalarabic', + '65169' => 'behinitialarabic', + '65170' => 'behmedialarabic', + '65172' => 'tehmarbutafinalarabic', + '65174' => 'tehfinalarabic', + '65175' => 'tehinitialarabic', + '65176' => 'tehmedialarabic', + '65178' => 'thehfinalarabic', + '65179' => 'thehinitialarabic', + '65180' => 'thehmedialarabic', + '65182' => 'jeemfinalarabic', + '65183' => 'jeeminitialarabic', + '65184' => 'jeemmedialarabic', + '65186' => 'hahfinalarabic', + '65187' => 'hahinitialarabic', + '65188' => 'hahmedialarabic', + '65190' => 'khahfinalarabic', + '65191' => 'khahinitialarabic', + '65192' => 'khahmedialarabic', + '65194' => 'dalfinalarabic', + '65196' => 'thalfinalarabic', + '65198' => 'rehfinalarabic', + '65200' => 'zainfinalarabic', + '65202' => 'seenfinalarabic', + '65203' => 'seeninitialarabic', + '65204' => 'seenmedialarabic', + '65206' => 'sheenfinalarabic', + '65207' => 'sheeninitialarabic', + '65208' => 'sheenmedialarabic', + '65210' => 'sadfinalarabic', + '65211' => 'sadinitialarabic', + '65212' => 'sadmedialarabic', + '65214' => 'dadfinalarabic', + '65215' => 'dadinitialarabic', + '65216' => 'dadmedialarabic', + '65218' => 'tahfinalarabic', + '65219' => 'tahinitialarabic', + '65220' => 'tahmedialarabic', + '65222' => 'zahfinalarabic', + '65223' => 'zahinitialarabic', + '65224' => 'zahmedialarabic', + '65226' => 'ainfinalarabic', + '65227' => 'aininitialarabic', + '65228' => 'ainmedialarabic', + '65230' => 'ghainfinalarabic', + '65231' => 'ghaininitialarabic', + '65232' => 'ghainmedialarabic', + '65234' => 'fehfinalarabic', + '65235' => 'fehinitialarabic', + '65236' => 'fehmedialarabic', + '65238' => 'qaffinalarabic', + '65239' => 'qafinitialarabic', + '65240' => 'qafmedialarabic', + '65242' => 'kaffinalarabic', + '65243' => 'kafinitialarabic', + '65244' => 'kafmedialarabic', + '65246' => 'lamfinalarabic', + '65247' => 'laminitialarabic', + '65248' => 'lammedialarabic', + '65250' => 'meemfinalarabic', + '65251' => 'meeminitialarabic', + '65252' => 'meemmedialarabic', + '65254' => 'noonfinalarabic', + '65255' => 'noonhehinitialarabic', + '65256' => 'noonmedialarabic', + '65258' => 'hehfinalalttwoarabic', + '65259' => 'hehinitialarabic', + '65260' => 'hehmedialarabic', + '65262' => 'wawfinalarabic', + '65264' => 'alefmaksurafinalarabic', + '65266' => 'yehfinalarabic', + '65267' => 'alefmaksurainitialarabic', + '65268' => 'alefmaksuramedialarabic', + '65269' => 'lamalefmaddaaboveisolatedarabic', + '65270' => 'lamalefmaddaabovefinalarabic', + '65271' => 'lamalefhamzaaboveisolatedarabic', + '65272' => 'lamalefhamzaabovefinalarabic', + '65273' => 'lamalefhamzabelowisolatedarabic', + '65274' => 'lamalefhamzabelowfinalarabic', + '65275' => 'lamalefisolatedarabic', + '65276' => 'lamaleffinalarabic', + '65279' => 'zerowidthjoiner', + '65281' => 'exclammonospace', + '65282' => 'quotedblmonospace', + '65283' => 'numbersignmonospace', + '65284' => 'dollarmonospace', + '65285' => 'percentmonospace', + '65286' => 'ampersandmonospace', + '65287' => 'quotesinglemonospace', + '65288' => 'parenleftmonospace', + '65289' => 'parenrightmonospace', + '65290' => 'asteriskmonospace', + '65291' => 'plusmonospace', + '65292' => 'commamonospace', + '65293' => 'hyphenmonospace', + '65294' => 'periodmonospace', + '65295' => 'slashmonospace', + '65296' => 'zeromonospace', + '65297' => 'onemonospace', + '65298' => 'twomonospace', + '65299' => 'threemonospace', + '65300' => 'fourmonospace', + '65301' => 'fivemonospace', + '65302' => 'sixmonospace', + '65303' => 'sevenmonospace', + '65304' => 'eightmonospace', + '65305' => 'ninemonospace', + '65306' => 'colonmonospace', + '65307' => 'semicolonmonospace', + '65308' => 'lessmonospace', + '65309' => 'equalmonospace', + '65310' => 'greatermonospace', + '65311' => 'questionmonospace', + '65312' => 'atmonospace', + '65313' => 'Amonospace', + '65314' => 'Bmonospace', + '65315' => 'Cmonospace', + '65316' => 'Dmonospace', + '65317' => 'Emonospace', + '65318' => 'Fmonospace', + '65319' => 'Gmonospace', + '65320' => 'Hmonospace', + '65321' => 'Imonospace', + '65322' => 'Jmonospace', + '65323' => 'Kmonospace', + '65324' => 'Lmonospace', + '65325' => 'Mmonospace', + '65326' => 'Nmonospace', + '65327' => 'Omonospace', + '65328' => 'Pmonospace', + '65329' => 'Qmonospace', + '65330' => 'Rmonospace', + '65331' => 'Smonospace', + '65332' => 'Tmonospace', + '65333' => 'Umonospace', + '65334' => 'Vmonospace', + '65335' => 'Wmonospace', + '65336' => 'Xmonospace', + '65337' => 'Ymonospace', + '65338' => 'Zmonospace', + '65339' => 'bracketleftmonospace', + '65340' => 'backslashmonospace', + '65341' => 'bracketrightmonospace', + '65342' => 'asciicircummonospace', + '65343' => 'underscoremonospace', + '65344' => 'gravemonospace', + '65345' => 'amonospace', + '65346' => 'bmonospace', + '65347' => 'cmonospace', + '65348' => 'dmonospace', + '65349' => 'emonospace', + '65350' => 'fmonospace', + '65351' => 'gmonospace', + '65352' => 'hmonospace', + '65353' => 'imonospace', + '65354' => 'jmonospace', + '65355' => 'kmonospace', + '65356' => 'lmonospace', + '65357' => 'mmonospace', + '65358' => 'nmonospace', + '65359' => 'omonospace', + '65360' => 'pmonospace', + '65361' => 'qmonospace', + '65362' => 'rmonospace', + '65363' => 'smonospace', + '65364' => 'tmonospace', + '65365' => 'umonospace', + '65366' => 'vmonospace', + '65367' => 'wmonospace', + '65368' => 'xmonospace', + '65369' => 'ymonospace', + '65370' => 'zmonospace', + '65371' => 'braceleftmonospace', + '65372' => 'barmonospace', + '65373' => 'bracerightmonospace', + '65374' => 'asciitildemonospace', + '65377' => 'periodhalfwidth', + '65378' => 'cornerbracketlefthalfwidth', + '65379' => 'cornerbracketrighthalfwidth', + '65380' => 'ideographiccommaleft', + '65381' => 'middledotkatakanahalfwidth', + '65382' => 'wokatakanahalfwidth', + '65383' => 'asmallkatakanahalfwidth', + '65384' => 'ismallkatakanahalfwidth', + '65385' => 'usmallkatakanahalfwidth', + '65386' => 'esmallkatakanahalfwidth', + '65387' => 'osmallkatakanahalfwidth', + '65388' => 'yasmallkatakanahalfwidth', + '65389' => 'yusmallkatakanahalfwidth', + '65390' => 'yosmallkatakanahalfwidth', + '65391' => 'tusmallkatakanahalfwidth', + '65392' => 'katahiraprolongmarkhalfwidth', + '65393' => 'akatakanahalfwidth', + '65394' => 'ikatakanahalfwidth', + '65395' => 'ukatakanahalfwidth', + '65396' => 'ekatakanahalfwidth', + '65397' => 'okatakanahalfwidth', + '65398' => 'kakatakanahalfwidth', + '65399' => 'kikatakanahalfwidth', + '65400' => 'kukatakanahalfwidth', + '65401' => 'kekatakanahalfwidth', + '65402' => 'kokatakanahalfwidth', + '65403' => 'sakatakanahalfwidth', + '65404' => 'sikatakanahalfwidth', + '65405' => 'sukatakanahalfwidth', + '65406' => 'sekatakanahalfwidth', + '65407' => 'sokatakanahalfwidth', + '65408' => 'takatakanahalfwidth', + '65409' => 'tikatakanahalfwidth', + '65410' => 'tukatakanahalfwidth', + '65411' => 'tekatakanahalfwidth', + '65412' => 'tokatakanahalfwidth', + '65413' => 'nakatakanahalfwidth', + '65414' => 'nikatakanahalfwidth', + '65415' => 'nukatakanahalfwidth', + '65416' => 'nekatakanahalfwidth', + '65417' => 'nokatakanahalfwidth', + '65418' => 'hakatakanahalfwidth', + '65419' => 'hikatakanahalfwidth', + '65420' => 'hukatakanahalfwidth', + '65421' => 'hekatakanahalfwidth', + '65422' => 'hokatakanahalfwidth', + '65423' => 'makatakanahalfwidth', + '65424' => 'mikatakanahalfwidth', + '65425' => 'mukatakanahalfwidth', + '65426' => 'mekatakanahalfwidth', + '65427' => 'mokatakanahalfwidth', + '65428' => 'yakatakanahalfwidth', + '65429' => 'yukatakanahalfwidth', + '65430' => 'yokatakanahalfwidth', + '65431' => 'rakatakanahalfwidth', + '65432' => 'rikatakanahalfwidth', + '65433' => 'rukatakanahalfwidth', + '65434' => 'rekatakanahalfwidth', + '65435' => 'rokatakanahalfwidth', + '65436' => 'wakatakanahalfwidth', + '65437' => 'nkatakanahalfwidth', + '65438' => 'voicedmarkkanahalfwidth', + '65439' => 'semivoicedmarkkanahalfwidth', + '65504' => 'centmonospace', + '65505' => 'sterlingmonospace', + '65507' => 'macronmonospace', + '65509' => 'yenmonospace', + '65510' => 'wonmonospace', +}; + +our $n2u = { + '.notdef' => '0', + 'A' => '65', + 'AE' => '198', + 'AEacute' => '508', + 'AElig' => '198', + 'AEmacron' => '482', + 'AEsmall' => '63462', + 'Aacgr' => '902', + 'Aacute' => '193', + 'Aacutesmall' => '63457', + 'Abreve' => '258', + 'Abreveacute' => '7854', + 'Abrevecyrillic' => '1232', + 'Abrevedotbelow' => '7862', + 'Abrevegrave' => '7856', + 'Abrevehookabove' => '7858', + 'Abrevetilde' => '7860', + 'Acaron' => '461', + 'Acirc' => '194', + 'Acircle' => '9398', + 'Acircumflex' => '194', + 'Acircumflexacute' => '7844', + 'Acircumflexdotbelow' => '7852', + 'Acircumflexgrave' => '7846', + 'Acircumflexhookabove' => '7848', + 'Acircumflexsmall' => '63458', + 'Acircumflextilde' => '7850', + 'Acute' => '63177', + 'Acutesmall' => '63412', + 'Acy' => '1040', + 'Acyrillic' => '1040', + 'Adblgrave' => '512', + 'Adieresis' => '196', + 'Adieresiscyrillic' => '1234', + 'Adieresismacron' => '478', + 'Adieresissmall' => '63460', + 'Adotbelow' => '7840', + 'Adotmacron' => '480', + 'Agr' => '913', + 'Agrave' => '192', + 'Agravesmall' => '63456', + 'Ahookabove' => '7842', + 'Aiecyrillic' => '1236', + 'Ainvertedbreve' => '514', + 'Alpha' => '913', + 'Alphatonos' => '902', + 'Amacr' => '256', + 'Amacron' => '256', + 'Amonospace' => '65313', + 'Aogon' => '260', + 'Aogonek' => '260', + 'Aring' => '197', + 'Aringacute' => '506', + 'Aringbelow' => '7680', + 'Aringsmall' => '63461', + 'Asmall' => '63329', + 'Atilde' => '195', + 'Atildesmall' => '63459', + 'Auml' => '196', + 'Aybarmenian' => '1329', + 'B' => '66', + 'Barwed' => '8966', + 'Bcircle' => '9399', + 'Bcy' => '1041', + 'Bdotaccent' => '7682', + 'Bdotbelow' => '7684', + 'Becyrillic' => '1041', + 'Benarmenian' => '1330', + 'Beta' => '914', + 'Bgr' => '914', + 'Bhook' => '385', + 'Blinebelow' => '7686', + 'Bmonospace' => '65314', + 'Brevesmall' => '63220', + 'Bsmall' => '63330', + 'Btopbar' => '386', + 'C' => '67', + 'CHcy' => '1063', + 'Caarmenian' => '1342', + 'Cacute' => '262', + 'Cap' => '8914', + 'Caron' => '63178', + 'Caronsmall' => '63221', + 'Ccaron' => '268', + 'Ccedil' => '199', + 'Ccedilla' => '199', + 'Ccedillaacute' => '7688', + 'Ccedillasmall' => '63463', + 'Ccirc' => '264', + 'Ccircle' => '9400', + 'Ccircumflex' => '264', + 'Cdot' => '266', + 'Cdotaccent' => '266', + 'Cedillasmall' => '63416', + 'Chaarmenian' => '1353', + 'Cheabkhasiancyrillic' => '1212', + 'Checyrillic' => '1063', + 'Chedescenderabkhasiancyrillic' => '1214', + 'Chedescendercyrillic' => '1206', + 'Chedieresiscyrillic' => '1268', + 'Cheharmenian' => '1347', + 'Chekhakassiancyrillic' => '1227', + 'Cheverticalstrokecyrillic' => '1208', + 'Chi' => '935', + 'Chook' => '391', + 'Circumflexsmall' => '63222', + 'Cmonospace' => '65315', + 'Coarmenian' => '1361', + 'Csmall' => '63331', + 'Cup' => '8915', + 'D' => '68', + 'DJcy' => '1026', + 'DScy' => '1029', + 'DZ' => '497', + 'DZcaron' => '452', + 'DZcy' => '1039', + 'Daarmenian' => '1332', + 'Dafrican' => '393', + 'Dagger' => '8225', + 'Dcaron' => '270', + 'Dcedilla' => '7696', + 'Dcircle' => '9401', + 'Dcircumflexbelow' => '7698', + 'Dcroat' => '272', + 'Ddotaccent' => '7690', + 'Ddotbelow' => '7692', + 'Decyrillic' => '1044', + 'Deicoptic' => '1006', + 'Delta' => '916', + 'Deltagreek' => '916', + 'Dgr' => '916', + 'Dhook' => '394', + 'Dieresis' => '63179', + 'DieresisAcute' => '63180', + 'DieresisGrave' => '63181', + 'Dieresissmall' => '63400', + 'Digammagreek' => '988', + 'Djecyrillic' => '1026', + 'Dlinebelow' => '7694', + 'Dmonospace' => '65316', + 'DotDot' => '8412', + 'Dotaccentsmall' => '63223', + 'Dslash' => '272', + 'Dsmall' => '63332', + 'Dstrok' => '272', + 'Dtopbar' => '395', + 'Dz' => '498', + 'Dzcaron' => '453', + 'Dzeabkhasiancyrillic' => '1248', + 'Dzecyrillic' => '1029', + 'Dzhecyrillic' => '1039', + 'E' => '69', + 'EEacgr' => '905', + 'EEgr' => '919', + 'ENG' => '330', + 'ETH' => '208', + 'Eacgr' => '904', + 'Eacute' => '201', + 'Eacutesmall' => '63465', + 'Ebreve' => '276', + 'Ecaron' => '282', + 'Ecedillabreve' => '7708', + 'Echarmenian' => '1333', + 'Ecirc' => '202', + 'Ecircle' => '9402', + 'Ecircumflex' => '202', + 'Ecircumflexacute' => '7870', + 'Ecircumflexbelow' => '7704', + 'Ecircumflexdotbelow' => '7878', + 'Ecircumflexgrave' => '7872', + 'Ecircumflexhookabove' => '7874', + 'Ecircumflexsmall' => '63466', + 'Ecircumflextilde' => '7876', + 'Ecy' => '1069', + 'Ecyrillic' => '1028', + 'Edblgrave' => '516', + 'Edieresis' => '203', + 'Edieresissmall' => '63467', + 'Edot' => '278', + 'Edotaccent' => '278', + 'Edotbelow' => '7864', + 'Efcyrillic' => '1060', + 'Egr' => '917', + 'Egrave' => '200', + 'Egravesmall' => '63464', + 'Eharmenian' => '1335', + 'Ehookabove' => '7866', + 'Eightroman' => '8551', + 'Einvertedbreve' => '518', + 'Eiotifiedcyrillic' => '1124', + 'Elcyrillic' => '1051', + 'Elevenroman' => '8554', + 'Emacr' => '274', + 'Emacron' => '274', + 'Emacronacute' => '7702', + 'Emacrongrave' => '7700', + 'Emcyrillic' => '1052', + 'Emonospace' => '65317', + 'Encyrillic' => '1053', + 'Endescendercyrillic' => '1186', + 'Eng' => '330', + 'Enghecyrillic' => '1188', + 'Enhookcyrillic' => '1223', + 'Eogon' => '280', + 'Eogonek' => '280', + 'Eopen' => '400', + 'Epsilon' => '917', + 'Epsilontonos' => '904', + 'Ercyrillic' => '1056', + 'Ereversed' => '398', + 'Ereversedcyrillic' => '1069', + 'Escyrillic' => '1057', + 'Esdescendercyrillic' => '1194', + 'Esh' => '425', + 'Esmall' => '63333', + 'Eta' => '919', + 'Etarmenian' => '1336', + 'Etatonos' => '905', + 'Eth' => '208', + 'Ethsmall' => '63472', + 'Etilde' => '7868', + 'Etildebelow' => '7706', + 'Euml' => '203', + 'Euro' => '8364', + 'Ezh' => '439', + 'Ezhcaron' => '494', + 'Ezhreversed' => '440', + 'F' => '70', + 'Fcircle' => '9403', + 'Fcy' => '1060', + 'Fdotaccent' => '7710', + 'Feharmenian' => '1366', + 'Feicoptic' => '996', + 'Fhook' => '401', + 'Fitacyrillic' => '1138', + 'Fiveroman' => '8548', + 'Fmonospace' => '65318', + 'Fourroman' => '8547', + 'Fsmall' => '63334', + 'G' => '71', + 'GBsquare' => '13191', + 'GJcy' => '1027', + 'Gacute' => '500', + 'Gamma' => '915', + 'Gammaafrican' => '404', + 'Gangiacoptic' => '1002', + 'Gbreve' => '286', + 'Gcaron' => '486', + 'Gcedil' => '290', + 'Gcedilla' => '290', + 'Gcirc' => '284', + 'Gcircle' => '9404', + 'Gcircumflex' => '284', + 'Gcommaaccent' => '290', + 'Gcy' => '1043', + 'Gdot' => '288', + 'Gdotaccent' => '288', + 'Gecyrillic' => '1043', + 'Gg' => '8921', + 'Ggr' => '915', + 'Ghadarmenian' => '1346', + 'Ghemiddlehookcyrillic' => '1172', + 'Ghestrokecyrillic' => '1170', + 'Gheupturncyrillic' => '1168', + 'Ghook' => '403', + 'Gimarmenian' => '1331', + 'Gjecyrillic' => '1027', + 'Gmacron' => '7712', + 'Gmonospace' => '65319', + 'Grave' => '63182', + 'Gravesmall' => '63328', + 'Gsmall' => '63335', + 'Gsmallhook' => '667', + 'Gstroke' => '484', + 'Gt' => '8811', + 'H' => '72', + 'H18533' => '9679', + 'H18543' => '9642', + 'H18551' => '9643', + 'H22073' => '9633', + 'HARDcy' => '1066', + 'HPsquare' => '13259', + 'Haabkhasiancyrillic' => '1192', + 'Hadescendercyrillic' => '1202', + 'Hardsigncyrillic' => '1066', + 'Hbar' => '294', + 'Hbrevebelow' => '7722', + 'Hcedilla' => '7720', + 'Hcirc' => '292', + 'Hcircle' => '9405', + 'Hcircumflex' => '292', + 'Hdieresis' => '7718', + 'Hdotaccent' => '7714', + 'Hdotbelow' => '7716', + 'Hmonospace' => '65320', + 'Hoarmenian' => '1344', + 'Horicoptic' => '1000', + 'Hsmall' => '63336', + 'Hstrok' => '294', + 'Hungarumlaut' => '63183', + 'Hungarumlautsmall' => '63224', + 'Hzsquare' => '13200', + 'I' => '73', + 'IAcyrillic' => '1071', + 'IEcy' => '1045', + 'IJ' => '306', + 'IJlig' => '306', + 'IOcy' => '1025', + 'IUcyrillic' => '1070', + 'Iacgr' => '906', + 'Iacute' => '205', + 'Iacutesmall' => '63469', + 'Ibreve' => '300', + 'Icaron' => '463', + 'Icirc' => '206', + 'Icircle' => '9406', + 'Icircumflex' => '206', + 'Icircumflexsmall' => '63470', + 'Icy' => '1048', + 'Icyrillic' => '1030', + 'Idblgrave' => '520', + 'Idieresis' => '207', + 'Idieresisacute' => '7726', + 'Idieresiscyrillic' => '1252', + 'Idieresissmall' => '63471', + 'Idigr' => '938', + 'Idot' => '304', + 'Idotaccent' => '304', + 'Idotbelow' => '7882', + 'Iebrevecyrillic' => '1238', + 'Iecyrillic' => '1045', + 'Ifraktur' => '8465', + 'Igr' => '921', + 'Igrave' => '204', + 'Igravesmall' => '63468', + 'Ihookabove' => '7880', + 'Iicyrillic' => '1048', + 'Iinvertedbreve' => '522', + 'Iishortcyrillic' => '1049', + 'Imacr' => '298', + 'Imacron' => '298', + 'Imacroncyrillic' => '1250', + 'Imonospace' => '65321', + 'Iniarmenian' => '1339', + 'Iocyrillic' => '1025', + 'Iogon' => '302', + 'Iogonek' => '302', + 'Iota' => '921', + 'Iotaafrican' => '406', + 'Iotadieresis' => '938', + 'Iotatonos' => '906', + 'Ismall' => '63337', + 'Istroke' => '407', + 'Itilde' => '296', + 'Itildebelow' => '7724', + 'Iukcy' => '1030', + 'Iuml' => '207', + 'Izhitsacyrillic' => '1140', + 'Izhitsadblgravecyrillic' => '1142', + 'J' => '74', + 'Jaarmenian' => '1345', + 'Jcirc' => '308', + 'Jcircle' => '9407', + 'Jcircumflex' => '308', + 'Jcy' => '1049', + 'Jecyrillic' => '1032', + 'Jheharmenian' => '1355', + 'Jmonospace' => '65322', + 'Jsercy' => '1032', + 'Jsmall' => '63338', + 'Jukcy' => '1028', + 'K' => '75', + 'KBsquare' => '13189', + 'KHcy' => '1061', + 'KHgr' => '935', + 'KJcy' => '1036', + 'KKsquare' => '13261', + 'Kabashkircyrillic' => '1184', + 'Kacute' => '7728', + 'Kacyrillic' => '1050', + 'Kadescendercyrillic' => '1178', + 'Kahookcyrillic' => '1219', + 'Kappa' => '922', + 'Kastrokecyrillic' => '1182', + 'Kaverticalstrokecyrillic' => '1180', + 'Kcaron' => '488', + 'Kcedil' => '310', + 'Kcedilla' => '310', + 'Kcircle' => '9408', + 'Kcommaaccent' => '310', + 'Kcy' => '1050', + 'Kdotbelow' => '7730', + 'Keharmenian' => '1364', + 'Kenarmenian' => '1343', + 'Kgr' => '922', + 'Khacyrillic' => '1061', + 'Kheicoptic' => '998', + 'Khook' => '408', + 'Kjecyrillic' => '1036', + 'Klinebelow' => '7732', + 'Kmonospace' => '65323', + 'Koppacyrillic' => '1152', + 'Koppagreek' => '990', + 'Ksicyrillic' => '1134', + 'Ksmall' => '63339', + 'L' => '76', + 'LJ' => '455', + 'LJcy' => '1033', + 'LL' => '63167', + 'Lacute' => '313', + 'Lambda' => '923', + 'Larr' => '8606', + 'Lcaron' => '317', + 'Lcedil' => '315', + 'Lcedilla' => '315', + 'Lcircle' => '9409', + 'Lcircumflexbelow' => '7740', + 'Lcommaaccent' => '315', + 'Lcy' => '1051', + 'Ldot' => '319', + 'Ldotaccent' => '319', + 'Ldotbelow' => '7734', + 'Ldotbelowmacron' => '7736', + 'Lgr' => '923', + 'Liwnarmenian' => '1340', + 'Lj' => '456', + 'Ljecyrillic' => '1033', + 'Ll' => '8920', + 'Llinebelow' => '7738', + 'Lmidot' => '319', + 'Lmonospace' => '65324', + 'Lslash' => '321', + 'Lslashsmall' => '63225', + 'Lsmall' => '63340', + 'Lstrok' => '321', + 'Lt' => '8810', + 'M' => '77', + 'MBsquare' => '13190', + 'Macron' => '63184', + 'Macronsmall' => '63407', + 'Macute' => '7742', + 'Mcircle' => '9410', + 'Mcy' => '1052', + 'Mdotaccent' => '7744', + 'Mdotbelow' => '7746', + 'Menarmenian' => '1348', + 'Mgr' => '924', + 'Mmonospace' => '65325', + 'Msmall' => '63341', + 'Mturned' => '412', + 'Mu' => '924', + 'N' => '78', + 'NJ' => '458', + 'NJcy' => '1034', + 'Nacute' => '323', + 'Ncaron' => '327', + 'Ncedil' => '325', + 'Ncedilla' => '325', + 'Ncircle' => '9411', + 'Ncircumflexbelow' => '7754', + 'Ncommaaccent' => '325', + 'Ncy' => '1053', + 'Ndotaccent' => '7748', + 'Ndotbelow' => '7750', + 'Ngr' => '925', + 'Nhookleft' => '413', + 'Nineroman' => '8552', + 'Nj' => '459', + 'Njecyrillic' => '1034', + 'Nlinebelow' => '7752', + 'Nmonospace' => '65326', + 'Nowarmenian' => '1350', + 'Nsmall' => '63342', + 'Ntilde' => '209', + 'Ntildesmall' => '63473', + 'Nu' => '925', + 'O' => '79', + 'OE' => '338', + 'OElig' => '338', + 'OEsmall' => '63226', + 'OHacgr' => '911', + 'OHgr' => '937', + 'Oacgr' => '908', + 'Oacute' => '211', + 'Oacutesmall' => '63475', + 'Obarredcyrillic' => '1256', + 'Obarreddieresiscyrillic' => '1258', + 'Obreve' => '334', + 'Ocaron' => '465', + 'Ocenteredtilde' => '415', + 'Ocirc' => '212', + 'Ocircle' => '9412', + 'Ocircumflex' => '212', + 'Ocircumflexacute' => '7888', + 'Ocircumflexdotbelow' => '7896', + 'Ocircumflexgrave' => '7890', + 'Ocircumflexhookabove' => '7892', + 'Ocircumflexsmall' => '63476', + 'Ocircumflextilde' => '7894', + 'Ocy' => '1054', + 'Ocyrillic' => '1054', + 'Odblac' => '336', + 'Odblacute' => '336', + 'Odblgrave' => '524', + 'Odieresis' => '214', + 'Odieresiscyrillic' => '1254', + 'Odieresissmall' => '63478', + 'Odotbelow' => '7884', + 'Ogoneksmall' => '63227', + 'Ogr' => '927', + 'Ograve' => '210', + 'Ogravesmall' => '63474', + 'Oharmenian' => '1365', + 'Ohm' => '8486', + 'Ohookabove' => '7886', + 'Ohorn' => '416', + 'Ohornacute' => '7898', + 'Ohorndotbelow' => '7906', + 'Ohorngrave' => '7900', + 'Ohornhookabove' => '7902', + 'Ohorntilde' => '7904', + 'Ohungarumlaut' => '336', + 'Oi' => '418', + 'Oinvertedbreve' => '526', + 'Omacr' => '332', + 'Omacron' => '332', + 'Omacronacute' => '7762', + 'Omacrongrave' => '7760', + 'Omega' => '937', + 'Omegacyrillic' => '1120', + 'Omegagreek' => '937', + 'Omegaroundcyrillic' => '1146', + 'Omegatitlocyrillic' => '1148', + 'Omegatonos' => '911', + 'Omicron' => '927', + 'Omicrontonos' => '908', + 'Omonospace' => '65327', + 'Oneroman' => '8544', + 'Oogonek' => '490', + 'Oogonekmacron' => '492', + 'Oopen' => '390', + 'Oslash' => '216', + 'Oslashacute' => '510', + 'Oslashsmall' => '63480', + 'Osmall' => '63343', + 'Ostrokeacute' => '510', + 'Otcyrillic' => '1150', + 'Otilde' => '213', + 'Otildeacute' => '7756', + 'Otildedieresis' => '7758', + 'Otildesmall' => '63477', + 'Ouml' => '214', + 'P' => '80', + 'PHgr' => '934', + 'PSgr' => '936', + 'Pacute' => '7764', + 'Pcircle' => '9413', + 'Pcy' => '1055', + 'Pdotaccent' => '7766', + 'Pecyrillic' => '1055', + 'Peharmenian' => '1354', + 'Pemiddlehookcyrillic' => '1190', + 'Pgr' => '928', + 'Phi' => '934', + 'Phook' => '420', + 'Pi' => '928', + 'Piwrarmenian' => '1363', + 'Pmonospace' => '65328', + 'Prime' => '8243', + 'Psi' => '936', + 'Psicyrillic' => '1136', + 'Psmall' => '63344', + 'Q' => '81', + 'Qcircle' => '9414', + 'Qmonospace' => '65329', + 'Qsmall' => '63345', + 'R' => '82', + 'Raarmenian' => '1356', + 'Racute' => '340', + 'Rarr' => '8608', + 'Rcaron' => '344', + 'Rcedil' => '342', + 'Rcedilla' => '342', + 'Rcircle' => '9415', + 'Rcommaaccent' => '342', + 'Rcy' => '1056', + 'Rdblgrave' => '528', + 'Rdotaccent' => '7768', + 'Rdotbelow' => '7770', + 'Rdotbelowmacron' => '7772', + 'Reharmenian' => '1360', + 'Rfraktur' => '8476', + 'Rgr' => '929', + 'Rho' => '929', + 'Ringsmall' => '63228', + 'Rinvertedbreve' => '530', + 'Rlinebelow' => '7774', + 'Rmonospace' => '65330', + 'Rsmall' => '63346', + 'Rsmallinverted' => '641', + 'Rsmallinvertedsuperior' => '694', + 'S' => '83', + 'SF010000' => '9484', + 'SF020000' => '9492', + 'SF030000' => '9488', + 'SF040000' => '9496', + 'SF050000' => '9532', + 'SF060000' => '9516', + 'SF070000' => '9524', + 'SF080000' => '9500', + 'SF090000' => '9508', + 'SF100000' => '9472', + 'SF110000' => '9474', + 'SF190000' => '9569', + 'SF200000' => '9570', + 'SF210000' => '9558', + 'SF220000' => '9557', + 'SF230000' => '9571', + 'SF240000' => '9553', + 'SF250000' => '9559', + 'SF260000' => '9565', + 'SF270000' => '9564', + 'SF280000' => '9563', + 'SF360000' => '9566', + 'SF370000' => '9567', + 'SF380000' => '9562', + 'SF390000' => '9556', + 'SF400000' => '9577', + 'SF410000' => '9574', + 'SF420000' => '9568', + 'SF430000' => '9552', + 'SF440000' => '9580', + 'SF450000' => '9575', + 'SF460000' => '9576', + 'SF470000' => '9572', + 'SF480000' => '9573', + 'SF490000' => '9561', + 'SF500000' => '9560', + 'SF510000' => '9554', + 'SF520000' => '9555', + 'SF530000' => '9579', + 'SF540000' => '9578', + 'SHCHcy' => '1065', + 'SHcy' => '1064', + 'SOFTcy' => '1068', + 'Sacute' => '346', + 'Sacutedotaccent' => '7780', + 'Sampigreek' => '992', + 'Scaron' => '352', + 'Scarondotaccent' => '7782', + 'Scaronsmall' => '63229', + 'Scedil' => '350', + 'Scedilla' => '350', + 'Schwa' => '399', + 'Schwacyrillic' => '1240', + 'Schwadieresiscyrillic' => '1242', + 'Scirc' => '348', + 'Scircle' => '9416', + 'Scircumflex' => '348', + 'Scommaaccent' => '536', + 'Scy' => '1057', + 'Sdotaccent' => '7776', + 'Sdotbelow' => '7778', + 'Sdotbelowdotaccent' => '7784', + 'Seharmenian' => '1357', + 'Sevenroman' => '8550', + 'Sgr' => '931', + 'Shaarmenian' => '1351', + 'Shacyrillic' => '1064', + 'Shchacyrillic' => '1065', + 'Sheicoptic' => '994', + 'Shhacyrillic' => '1210', + 'Shimacoptic' => '1004', + 'Sigma' => '931', + 'Sixroman' => '8549', + 'Smonospace' => '65331', + 'Softsigncyrillic' => '1068', + 'Ssmall' => '63347', + 'Stigmagreek' => '986', + 'Sub' => '8912', + 'Sup' => '8913', + 'T' => '84', + 'THORN' => '222', + 'THgr' => '920', + 'TSHcy' => '1035', + 'TScy' => '1062', + 'Tau' => '932', + 'Tbar' => '358', + 'Tcaron' => '356', + 'Tcedil' => '354', + 'Tcedilla' => '354', + 'Tcircle' => '9417', + 'Tcircumflexbelow' => '7792', + 'Tcommaaccent' => '538', + 'Tcy' => '1058', + 'Tdotaccent' => '7786', + 'Tdotbelow' => '7788', + 'Tecyrillic' => '1058', + 'Tedescendercyrillic' => '1196', + 'Tenroman' => '8553', + 'Tetsecyrillic' => '1204', + 'Tgr' => '932', + 'Theta' => '920', + 'Thook' => '428', + 'Thorn' => '222', + 'Thornsmall' => '63486', + 'Threeroman' => '8546', + 'Tildesmall' => '63230', + 'Tiwnarmenian' => '1359', + 'Tlinebelow' => '7790', + 'Tmonospace' => '65332', + 'Toarmenian' => '1337', + 'Tonefive' => '444', + 'Tonesix' => '388', + 'Tonetwo' => '423', + 'Tretroflexhook' => '430', + 'Tsecyrillic' => '1062', + 'Tshecyrillic' => '1035', + 'Tsmall' => '63348', + 'Tstrok' => '358', + 'Twelveroman' => '8555', + 'Tworoman' => '8545', + 'U' => '85', + 'Uacgr' => '910', + 'Uacute' => '218', + 'Uacutesmall' => '63482', + 'Ubrcy' => '1038', + 'Ubreve' => '364', + 'Ucaron' => '467', + 'Ucirc' => '219', + 'Ucircle' => '9418', + 'Ucircumflex' => '219', + 'Ucircumflexbelow' => '7798', + 'Ucircumflexsmall' => '63483', + 'Ucy' => '1059', + 'Ucyrillic' => '1059', + 'Udblac' => '368', + 'Udblacute' => '368', + 'Udblgrave' => '532', + 'Udieresis' => '220', + 'Udieresisacute' => '471', + 'Udieresisbelow' => '7794', + 'Udieresiscaron' => '473', + 'Udieresiscyrillic' => '1264', + 'Udieresisgrave' => '475', + 'Udieresismacron' => '469', + 'Udieresissmall' => '63484', + 'Udigr' => '939', + 'Udotbelow' => '7908', + 'Ugrave' => '217', + 'Ugravesmall' => '63481', + 'Uhookabove' => '7910', + 'Uhorn' => '431', + 'Uhornacute' => '7912', + 'Uhorndotbelow' => '7920', + 'Uhorngrave' => '7914', + 'Uhornhookabove' => '7916', + 'Uhorntilde' => '7918', + 'Uhungarumlaut' => '368', + 'Uhungarumlautcyrillic' => '1266', + 'Uinvertedbreve' => '534', + 'Ukcyrillic' => '1144', + 'Umacr' => '362', + 'Umacron' => '362', + 'Umacroncyrillic' => '1262', + 'Umacrondieresis' => '7802', + 'Umonospace' => '65333', + 'Uogon' => '370', + 'Uogonek' => '370', + 'Upsi' => '933', + 'Upsilon' => '933', + 'Upsilon1' => '978', + 'Upsilonacutehooksymbolgreek' => '979', + 'Upsilonafrican' => '433', + 'Upsilondieresis' => '939', + 'Upsilondieresishooksymbolgreek' => '980', + 'Upsilonhooksymbol' => '978', + 'Upsilontonos' => '910', + 'Uring' => '366', + 'Ushortcyrillic' => '1038', + 'Usmall' => '63349', + 'Ustraightcyrillic' => '1198', + 'Ustraightstrokecyrillic' => '1200', + 'Utilde' => '360', + 'Utildeacute' => '7800', + 'Utildebelow' => '7796', + 'Uuml' => '220', + 'V' => '86', + 'Vcircle' => '9419', + 'Vcy' => '1042', + 'Vdash' => '8873', + 'Vdotbelow' => '7806', + 'Vecyrillic' => '1042', + 'Verbar' => '8214', + 'Vewarmenian' => '1358', + 'Vhook' => '434', + 'Vmonospace' => '65334', + 'Voarmenian' => '1352', + 'Vsmall' => '63350', + 'Vtilde' => '7804', + 'Vvdash' => '8874', + 'W' => '87', + 'Wacute' => '7810', + 'Wcirc' => '372', + 'Wcircle' => '9420', + 'Wcircumflex' => '372', + 'Wdieresis' => '7812', + 'Wdotaccent' => '7814', + 'Wdotbelow' => '7816', + 'Wgrave' => '7808', + 'Wmonospace' => '65335', + 'Wsmall' => '63351', + 'X' => '88', + 'Xcircle' => '9421', + 'Xdieresis' => '7820', + 'Xdotaccent' => '7818', + 'Xeharmenian' => '1341', + 'Xgr' => '926', + 'Xi' => '926', + 'Xmonospace' => '65336', + 'Xsmall' => '63352', + 'Y' => '89', + 'YAcy' => '1071', + 'YIcy' => '1031', + 'YUcy' => '1070', + 'Yacute' => '221', + 'Yacutesmall' => '63485', + 'Yatcyrillic' => '1122', + 'Ycirc' => '374', + 'Ycircle' => '9422', + 'Ycircumflex' => '374', + 'Ycy' => '1067', + 'Ydieresis' => '376', + 'Ydieresissmall' => '63487', + 'Ydotaccent' => '7822', + 'Ydotbelow' => '7924', + 'Yericyrillic' => '1067', + 'Yerudieresiscyrillic' => '1272', + 'Ygrave' => '7922', + 'Yhook' => '435', + 'Yhookabove' => '7926', + 'Yiarmenian' => '1349', + 'Yicyrillic' => '1031', + 'Yiwnarmenian' => '1362', + 'Ymonospace' => '65337', + 'Ysmall' => '63353', + 'Ytilde' => '7928', + 'Yuml' => '376', + 'Yusbigcyrillic' => '1130', + 'Yusbigiotifiedcyrillic' => '1132', + 'Yuslittlecyrillic' => '1126', + 'Yuslittleiotifiedcyrillic' => '1128', + 'Z' => '90', + 'ZHcy' => '1046', + 'Zaarmenian' => '1334', + 'Zacute' => '377', + 'Zcaron' => '381', + 'Zcaronsmall' => '63231', + 'Zcircle' => '9423', + 'Zcircumflex' => '7824', + 'Zcy' => '1047', + 'Zdot' => '379', + 'Zdotaccent' => '379', + 'Zdotbelow' => '7826', + 'Zecyrillic' => '1047', + 'Zedescendercyrillic' => '1176', + 'Zedieresiscyrillic' => '1246', + 'Zeta' => '918', + 'Zgr' => '918', + 'Zhearmenian' => '1338', + 'Zhebrevecyrillic' => '1217', + 'Zhecyrillic' => '1046', + 'Zhedescendercyrillic' => '1174', + 'Zhedieresiscyrillic' => '1244', + 'Zlinebelow' => '7828', + 'Zmonospace' => '65338', + 'Zsmall' => '63354', + 'Zstroke' => '437', + 'a' => '97', + 'a1' => '9985', + 'a10' => '10017', + 'a100' => '10078', + 'a101' => '10081', + 'a102' => '10082', + 'a103' => '10083', + 'a104' => '10084', + 'a105' => '10000', + 'a106' => '10085', + 'a107' => '10086', + 'a108' => '10087', + 'a11' => '9755', + 'a117' => '9993', + 'a118' => '9992', + 'a119' => '9991', + 'a12' => '9758', + 'a120' => '9312', + 'a121' => '9313', + 'a122' => '9314', + 'a123' => '9315', + 'a124' => '9316', + 'a125' => '9317', + 'a126' => '9318', + 'a127' => '9319', + 'a128' => '9320', + 'a129' => '9321', + 'a13' => '9996', + 'a130' => '10102', + 'a131' => '10103', + 'a132' => '10104', + 'a133' => '10105', + 'a134' => '10106', + 'a135' => '10107', + 'a136' => '10108', + 'a137' => '10109', + 'a138' => '10110', + 'a139' => '10111', + 'a14' => '9997', + 'a140' => '10112', + 'a141' => '10113', + 'a142' => '10114', + 'a143' => '10115', + 'a144' => '10116', + 'a145' => '10117', + 'a146' => '10118', + 'a147' => '10119', + 'a148' => '10120', + 'a149' => '10121', + 'a15' => '9998', + 'a150' => '10122', + 'a151' => '10123', + 'a152' => '10124', + 'a153' => '10125', + 'a154' => '10126', + 'a155' => '10127', + 'a156' => '10128', + 'a157' => '10129', + 'a158' => '10130', + 'a159' => '10131', + 'a16' => '9999', + 'a160' => '10132', + 'a162' => '10147', + 'a165' => '10137', + 'a166' => '10139', + 'a167' => '10140', + 'a168' => '10141', + 'a169' => '10142', + 'a17' => '10001', + 'a170' => '10143', + 'a171' => '10144', + 'a172' => '10145', + 'a173' => '10146', + 'a174' => '10148', + 'a175' => '10149', + 'a176' => '10150', + 'a177' => '10151', + 'a178' => '10152', + 'a179' => '10153', + 'a18' => '10002', + 'a180' => '10155', + 'a181' => '10157', + 'a182' => '10159', + 'a183' => '10162', + 'a184' => '10163', + 'a185' => '10165', + 'a186' => '10168', + 'a187' => '10170', + 'a188' => '10171', + 'a189' => '10172', + 'a19' => '10003', + 'a190' => '10173', + 'a191' => '10174', + 'a192' => '10138', + 'a193' => '10154', + 'a194' => '10166', + 'a195' => '10169', + 'a196' => '10136', + 'a197' => '10164', + 'a198' => '10167', + 'a199' => '10156', + 'a2' => '9986', + 'a20' => '10004', + 'a200' => '10158', + 'a201' => '10161', + 'a202' => '9987', + 'a203' => '10064', + 'a204' => '10066', + 'a205' => '63709', + 'a206' => '63711', + 'a21' => '10005', + 'a22' => '10006', + 'a23' => '10007', + 'a24' => '10008', + 'a25' => '10009', + 'a26' => '10010', + 'a27' => '10011', + 'a28' => '10012', + 'a29' => '10018', + 'a3' => '9988', + 'a30' => '10019', + 'a31' => '10020', + 'a32' => '10021', + 'a33' => '10022', + 'a34' => '10023', + 'a35' => '9733', + 'a36' => '10025', + 'a37' => '10026', + 'a38' => '10027', + 'a39' => '10028', + 'a4' => '9742', + 'a40' => '10029', + 'a41' => '10030', + 'a42' => '10031', + 'a43' => '10032', + 'a44' => '10033', + 'a45' => '10034', + 'a46' => '10035', + 'a47' => '10036', + 'a48' => '10037', + 'a49' => '10038', + 'a5' => '9990', + 'a50' => '10039', + 'a51' => '10040', + 'a52' => '10041', + 'a53' => '10042', + 'a54' => '10043', + 'a55' => '10044', + 'a56' => '10045', + 'a57' => '10046', + 'a58' => '10047', + 'a59' => '10048', + 'a6' => '10013', + 'a60' => '10049', + 'a61' => '10050', + 'a62' => '10051', + 'a63' => '10052', + 'a64' => '10053', + 'a65' => '10054', + 'a66' => '10055', + 'a67' => '10056', + 'a68' => '10057', + 'a69' => '10058', + 'a7' => '10014', + 'a70' => '10059', + 'a72' => '10061', + 'a74' => '10063', + 'a75' => '10065', + 'a78' => '9670', + 'a79' => '10070', + 'a8' => '10015', + 'a81' => '9687', + 'a82' => '10072', + 'a83' => '10073', + 'a84' => '10074', + 'a85' => '63710', + 'a86' => '63712', + 'a87' => '63713', + 'a88' => '63714', + 'a89' => '63703', + 'a9' => '10016', + 'a90' => '63704', + 'a91' => '63707', + 'a92' => '63708', + 'a93' => '63705', + 'a94' => '63706', + 'a95' => '63715', + 'a96' => '63716', + 'a97' => '10075', + 'a98' => '10076', + 'a99' => '10077', + 'aabengali' => '2438', + 'aacgr' => '940', + 'aacute' => '225', + 'aadeva' => '2310', + 'aagujarati' => '2694', + 'aagurmukhi' => '2566', + 'aamatragurmukhi' => '2622', + 'aarusquare' => '13059', + 'aavowelsignbengali' => '2494', + 'aavowelsigndeva' => '2366', + 'aavowelsigngujarati' => '2750', + 'abbreviationmarkarmenian' => '1375', + 'abbreviationsigndeva' => '2416', + 'abengali' => '2437', + 'abopomofo' => '12570', + 'abreve' => '259', + 'abreveacute' => '7855', + 'abrevecyrillic' => '1233', + 'abrevedotbelow' => '7863', + 'abrevegrave' => '7857', + 'abrevehookabove' => '7859', + 'abrevetilde' => '7861', + 'acaron' => '462', + 'acirc' => '226', + 'acircle' => '9424', + 'acircumflex' => '226', + 'acircumflexacute' => '7845', + 'acircumflexdotbelow' => '7853', + 'acircumflexgrave' => '7847', + 'acircumflexhookabove' => '7849', + 'acircumflextilde' => '7851', + 'acute' => '180', + 'acutebelowcmb' => '791', + 'acutecmb' => '769', + 'acutecomb' => '769', + 'acutedeva' => '2388', + 'acutelowmod' => '719', + 'acutetonecmb' => '833', + 'acy' => '1072', + 'acyrillic' => '1072', + 'adblgrave' => '513', + 'addakgurmukhi' => '2673', + 'adeva' => '2309', + 'adieresis' => '228', + 'adieresiscyrillic' => '1235', + 'adieresismacron' => '479', + 'adotbelow' => '7841', + 'adotmacron' => '481', + 'ae' => '230', + 'aeacute' => '509', + 'aekorean' => '12624', + 'aelig' => '230', + 'aemacron' => '483', + 'afii00208' => '8213', + 'afii08941' => '8356', + 'afii10017' => '1040', + 'afii10018' => '1041', + 'afii10019' => '1042', + 'afii10020' => '1043', + 'afii10021' => '1044', + 'afii10022' => '1045', + 'afii10023' => '1025', + 'afii10024' => '1046', + 'afii10025' => '1047', + 'afii10026' => '1048', + 'afii10027' => '1049', + 'afii10028' => '1050', + 'afii10029' => '1051', + 'afii10030' => '1052', + 'afii10031' => '1053', + 'afii10032' => '1054', + 'afii10033' => '1055', + 'afii10034' => '1056', + 'afii10035' => '1057', + 'afii10036' => '1058', + 'afii10037' => '1059', + 'afii10038' => '1060', + 'afii10039' => '1061', + 'afii10040' => '1062', + 'afii10041' => '1063', + 'afii10042' => '1064', + 'afii10043' => '1065', + 'afii10044' => '1066', + 'afii10045' => '1067', + 'afii10046' => '1068', + 'afii10047' => '1069', + 'afii10048' => '1070', + 'afii10049' => '1071', + 'afii10050' => '1168', + 'afii10051' => '1026', + 'afii10052' => '1027', + 'afii10053' => '1028', + 'afii10054' => '1029', + 'afii10055' => '1030', + 'afii10056' => '1031', + 'afii10057' => '1032', + 'afii10058' => '1033', + 'afii10059' => '1034', + 'afii10060' => '1035', + 'afii10061' => '1036', + 'afii10062' => '1038', + 'afii10063' => '63172', + 'afii10064' => '63173', + 'afii10065' => '1072', + 'afii10066' => '1073', + 'afii10067' => '1074', + 'afii10068' => '1075', + 'afii10069' => '1076', + 'afii10070' => '1077', + 'afii10071' => '1105', + 'afii10072' => '1078', + 'afii10073' => '1079', + 'afii10074' => '1080', + 'afii10075' => '1081', + 'afii10076' => '1082', + 'afii10077' => '1083', + 'afii10078' => '1084', + 'afii10079' => '1085', + 'afii10080' => '1086', + 'afii10081' => '1087', + 'afii10082' => '1088', + 'afii10083' => '1089', + 'afii10084' => '1090', + 'afii10085' => '1091', + 'afii10086' => '1092', + 'afii10087' => '1093', + 'afii10088' => '1094', + 'afii10089' => '1095', + 'afii10090' => '1096', + 'afii10091' => '1097', + 'afii10092' => '1098', + 'afii10093' => '1099', + 'afii10094' => '1100', + 'afii10095' => '1101', + 'afii10096' => '1102', + 'afii10097' => '1103', + 'afii10098' => '1169', + 'afii10099' => '1106', + 'afii10100' => '1107', + 'afii10101' => '1108', + 'afii10102' => '1109', + 'afii10103' => '1110', + 'afii10104' => '1111', + 'afii10105' => '1112', + 'afii10106' => '1113', + 'afii10107' => '1114', + 'afii10108' => '1115', + 'afii10109' => '1116', + 'afii10110' => '1118', + 'afii10145' => '1039', + 'afii10146' => '1122', + 'afii10147' => '1138', + 'afii10148' => '1140', + 'afii10192' => '63174', + 'afii10193' => '1119', + 'afii10194' => '1123', + 'afii10195' => '1139', + 'afii10196' => '1141', + 'afii10831' => '63175', + 'afii10832' => '63176', + 'afii10846' => '1241', + 'afii299' => '8206', + 'afii300' => '8207', + 'afii301' => '8205', + 'afii57381' => '1642', + 'afii57388' => '1548', + 'afii57392' => '1632', + 'afii57393' => '1633', + 'afii57394' => '1634', + 'afii57395' => '1635', + 'afii57396' => '1636', + 'afii57397' => '1637', + 'afii57398' => '1638', + 'afii57399' => '1639', + 'afii57400' => '1640', + 'afii57401' => '1641', + 'afii57403' => '1563', + 'afii57407' => '1567', + 'afii57409' => '1569', + 'afii57410' => '1570', + 'afii57411' => '1571', + 'afii57412' => '1572', + 'afii57413' => '1573', + 'afii57414' => '1574', + 'afii57415' => '1575', + 'afii57416' => '1576', + 'afii57417' => '1577', + 'afii57418' => '1578', + 'afii57419' => '1579', + 'afii57420' => '1580', + 'afii57421' => '1581', + 'afii57422' => '1582', + 'afii57423' => '1583', + 'afii57424' => '1584', + 'afii57425' => '1585', + 'afii57426' => '1586', + 'afii57427' => '1587', + 'afii57428' => '1588', + 'afii57429' => '1589', + 'afii57430' => '1590', + 'afii57431' => '1591', + 'afii57432' => '1592', + 'afii57433' => '1593', + 'afii57434' => '1594', + 'afii57440' => '1600', + 'afii57441' => '1601', + 'afii57442' => '1602', + 'afii57443' => '1603', + 'afii57444' => '1604', + 'afii57445' => '1605', + 'afii57446' => '1606', + 'afii57448' => '1608', + 'afii57449' => '1609', + 'afii57450' => '1610', + 'afii57451' => '1611', + 'afii57452' => '1612', + 'afii57453' => '1613', + 'afii57454' => '1614', + 'afii57455' => '1615', + 'afii57456' => '1616', + 'afii57457' => '1617', + 'afii57458' => '1618', + 'afii57470' => '1607', + 'afii57505' => '1700', + 'afii57506' => '1662', + 'afii57507' => '1670', + 'afii57508' => '1688', + 'afii57509' => '1711', + 'afii57511' => '1657', + 'afii57512' => '1672', + 'afii57513' => '1681', + 'afii57514' => '1722', + 'afii57519' => '1746', + 'afii57534' => '1749', + 'afii57636' => '8362', + 'afii57645' => '1470', + 'afii57658' => '1475', + 'afii57664' => '1488', + 'afii57665' => '1489', + 'afii57666' => '1490', + 'afii57667' => '1491', + 'afii57668' => '1492', + 'afii57669' => '1493', + 'afii57670' => '1494', + 'afii57671' => '1495', + 'afii57672' => '1496', + 'afii57673' => '1497', + 'afii57674' => '1498', + 'afii57675' => '1499', + 'afii57676' => '1500', + 'afii57677' => '1501', + 'afii57678' => '1502', + 'afii57679' => '1503', + 'afii57680' => '1504', + 'afii57681' => '1505', + 'afii57682' => '1506', + 'afii57683' => '1507', + 'afii57684' => '1508', + 'afii57685' => '1509', + 'afii57686' => '1510', + 'afii57687' => '1511', + 'afii57688' => '1512', + 'afii57689' => '1513', + 'afii57690' => '1514', + 'afii57694' => '64298', + 'afii57695' => '64299', + 'afii57700' => '64331', + 'afii57705' => '64287', + 'afii57716' => '1520', + 'afii57717' => '1521', + 'afii57718' => '1522', + 'afii57723' => '64309', + 'afii57793' => '1460', + 'afii57794' => '1461', + 'afii57795' => '1462', + 'afii57796' => '1467', + 'afii57797' => '1464', + 'afii57798' => '1463', + 'afii57799' => '1456', + 'afii57800' => '1458', + 'afii57801' => '1457', + 'afii57802' => '1459', + 'afii57803' => '1474', + 'afii57804' => '1473', + 'afii57806' => '1465', + 'afii57807' => '1468', + 'afii57839' => '1469', + 'afii57841' => '1471', + 'afii57842' => '1472', + 'afii57929' => '700', + 'afii61248' => '8453', + 'afii61289' => '8467', + 'afii61352' => '8470', + 'afii61573' => '8236', + 'afii61574' => '8237', + 'afii61575' => '8238', + 'afii61664' => '8204', + 'afii63167' => '1645', + 'afii64937' => '701', + 'agr' => '945', + 'agrave' => '224', + 'agujarati' => '2693', + 'agurmukhi' => '2565', + 'ahiragana' => '12354', + 'ahookabove' => '7843', + 'aibengali' => '2448', + 'aibopomofo' => '12574', + 'aideva' => '2320', + 'aiecyrillic' => '1237', + 'aigujarati' => '2704', + 'aigurmukhi' => '2576', + 'aimatragurmukhi' => '2632', + 'ainarabic' => '1593', + 'ainfinalarabic' => '65226', + 'aininitialarabic' => '65227', + 'ainmedialarabic' => '65228', + 'ainvertedbreve' => '515', + 'airplane' => '61521', + 'aivowelsignbengali' => '2504', + 'aivowelsigndeva' => '2376', + 'aivowelsigngujarati' => '2760', + 'akatakana' => '12450', + 'akatakanahalfwidth' => '65393', + 'akorean' => '12623', + 'alef' => '1488', + 'alefarabic' => '1575', + 'alefdageshhebrew' => '64304', + 'aleffinalarabic' => '65166', + 'alefhamzaabovearabic' => '1571', + 'alefhamzaabovefinalarabic' => '65156', + 'alefhamzabelowarabic' => '1573', + 'alefhamzabelowfinalarabic' => '65160', + 'alefhebrew' => '1488', + 'aleflamedhebrew' => '64335', + 'alefmaddaabovearabic' => '1570', + 'alefmaddaabovefinalarabic' => '65154', + 'alefmaksuraarabic' => '1609', + 'alefmaksurafinalarabic' => '65264', + 'alefmaksurainitialarabic' => '65267', + 'alefmaksuramedialarabic' => '65268', + 'alefpatahhebrew' => '64302', + 'alefqamatshebrew' => '64303', + 'alefsym' => '8501', + 'aleph' => '8501', + 'allequal' => '8780', + 'alpha' => '945', + 'alphatonos' => '940', + 'amacr' => '257', + 'amacron' => '257', + 'amonospace' => '65345', + 'amp' => '38', + 'ampersand' => '38', + 'ampersandit' => '61547', + 'ampersanditlc' => '61546', + 'ampersandmonospace' => '65286', + 'ampersandsmall' => '63270', + 'amsquare' => '13250', + 'anbopomofo' => '12578', + 'and' => '8743', + 'ang' => '8736', + 'ang90' => '8735', + 'angbopomofo' => '12580', + 'angkhankhuthai' => '3674', + 'angle' => '8736', + 'anglebracketleft' => '12296', + 'anglebracketleftvertical' => '65087', + 'anglebracketright' => '12297', + 'anglebracketrightvertical' => '65088', + 'angleleft' => '9001', + 'angleright' => '9002', + 'angmsd' => '8737', + 'angsph' => '8738', + 'angst' => '8491', + 'angstrom' => '8491', + 'anoteleia' => '903', + 'anudattadeva' => '2386', + 'anusvarabengali' => '2434', + 'anusvaradeva' => '2306', + 'anusvaragujarati' => '2690', + 'aogon' => '261', + 'aogonek' => '261', + 'apaatosquare' => '13056', + 'aparen' => '9372', + 'ape' => '8778', + 'apos' => '39', + 'apostrophearmenian' => '1370', + 'apostrophemod' => '700', + 'apple' => '63743', + 'approaches' => '8784', + 'approxequal' => '8776', + 'approxequalorimage' => '8786', + 'approximatelyequal' => '8773', + 'aquarius' => '61544', + 'araeaekorean' => '12686', + 'araeakorean' => '12685', + 'arc' => '8978', + 'aries' => '61534', + 'arighthalfring' => '7834', + 'aring' => '229', + 'aringacute' => '507', + 'aringbelow' => '7681', + 'arrowboth' => '8596', + 'arrowdashdown' => '8675', + 'arrowdashleft' => '8672', + 'arrowdashright' => '8674', + 'arrowdashup' => '8673', + 'arrowdblboth' => '8660', + 'arrowdbldown' => '8659', + 'arrowdblleft' => '8656', + 'arrowdblright' => '8658', + 'arrowdblup' => '8657', + 'arrowdown' => '8595', + 'arrowdownleft' => '8601', + 'arrowdownright' => '8600', + 'arrowdownwhite' => '8681', + 'arrowdwnleft1' => '61635', + 'arrowdwnrt1' => '61636', + 'arrowheaddownmod' => '709', + 'arrowheadleftmod' => '706', + 'arrowheadrightmod' => '707', + 'arrowheadupmod' => '708', + 'arrowhorizex' => '63719', + 'arrowleft' => '8592', + 'arrowleftdbl' => '8656', + 'arrowleftdblstroke' => '8653', + 'arrowleftdwn1' => '61641', + 'arrowleftoverright' => '8646', + 'arrowleftup1' => '61639', + 'arrowleftwhite' => '8678', + 'arrowright' => '8594', + 'arrowrightdblstroke' => '8655', + 'arrowrightheavy' => '10142', + 'arrowrightoverleft' => '8644', + 'arrowrightwhite' => '8680', + 'arrowrtdwn1' => '61642', + 'arrowrtup1' => '61640', + 'arrowtableft' => '8676', + 'arrowtabright' => '8677', + 'arrowup' => '8593', + 'arrowupdn' => '8597', + 'arrowupdnbse' => '8616', + 'arrowupdownbase' => '8616', + 'arrowupleft' => '8598', + 'arrowupleft1' => '61637', + 'arrowupleftofdown' => '8645', + 'arrowupright' => '8599', + 'arrowuprt1' => '61638', + 'arrowupwhite' => '8679', + 'arrowvertex' => '63718', + 'asciicircum' => '94', + 'asciicircummonospace' => '65342', + 'asciitilde' => '126', + 'asciitildemonospace' => '65374', + 'ascript' => '593', + 'ascriptturned' => '594', + 'asmallhiragana' => '12353', + 'asmallkatakana' => '12449', + 'asmallkatakanahalfwidth' => '65383', + 'ast' => '42', + 'asterisk' => '42', + 'asteriskaltonearabic' => '1645', + 'asteriskarabic' => '1645', + 'asteriskmath' => '8727', + 'asteriskmonospace' => '65290', + 'asterisksmall' => '65121', + 'asterism' => '8258', + 'asuperior' => '63209', + 'asymp' => '8776', + 'asymptoticallyequal' => '8771', + 'at' => '64', + 'atilde' => '227', + 'atmonospace' => '65312', + 'atsmall' => '65131', + 'aturned' => '592', + 'aubengali' => '2452', + 'aubopomofo' => '12576', + 'audeva' => '2324', + 'augujarati' => '2708', + 'augurmukhi' => '2580', + 'aulengthmarkbengali' => '2519', + 'aumatragurmukhi' => '2636', + 'auml' => '228', + 'auvowelsignbengali' => '2508', + 'auvowelsigndeva' => '2380', + 'auvowelsigngujarati' => '2764', + 'avagrahadeva' => '2365', + 'aybarmenian' => '1377', + 'ayin' => '1506', + 'ayinaltonehebrew' => '64288', + 'ayinhebrew' => '1506', + 'b' => '98', + 'babengali' => '2476', + 'backslash' => '92', + 'backslashmonospace' => '65340', + 'badeva' => '2348', + 'bagujarati' => '2732', + 'bagurmukhi' => '2604', + 'bahiragana' => '12400', + 'bahtthai' => '3647', + 'bakatakana' => '12496', + 'ballpoint' => '61497', + 'bar' => '124', + 'barb2down' => '61666', + 'barb2left' => '61663', + 'barb2ne' => '61668', + 'barb2nw' => '61667', + 'barb2right' => '61664', + 'barb2se' => '61670', + 'barb2sw' => '61669', + 'barb2up' => '61665', + 'barb4down' => '61674', + 'barb4left' => '61671', + 'barb4ne' => '61676', + 'barb4nw' => '61675', + 'barb4right' => '61672', + 'barb4se' => '61678', + 'barb4sw' => '61677', + 'barb4up' => '61673', + 'barmonospace' => '65372', + 'barwed' => '8892', + 'bbopomofo' => '12549', + 'bcircle' => '9425', + 'bcong' => '8780', + 'bcy' => '1073', + 'bdash1' => '61689', + 'bdash2' => '61690', + 'bdotaccent' => '7683', + 'bdotbelow' => '7685', + 'bdown' => '61682', + 'bdquo' => '8222', + 'beamedsixteenthnotes' => '9836', + 'becaus' => '8757', + 'because' => '8757', + 'becyrillic' => '1073', + 'beharabic' => '1576', + 'behfinalarabic' => '65168', + 'behinitialarabic' => '65169', + 'behiragana' => '12409', + 'behmedialarabic' => '65170', + 'behmeeminitialarabic' => '64671', + 'behmeemisolatedarabic' => '64520', + 'behnoonfinalarabic' => '64621', + 'bekatakana' => '12505', + 'bell' => '61477', + 'benarmenian' => '1378', + 'bepsi' => '8717', + 'bernou' => '8492', + 'bet' => '1489', + 'beta' => '946', + 'betasymbolgreek' => '976', + 'betdagesh' => '64305', + 'betdageshhebrew' => '64305', + 'beth' => '8502', + 'bethebrew' => '1489', + 'betrafehebrew' => '64332', + 'bgr' => '946', + 'bhabengali' => '2477', + 'bhadeva' => '2349', + 'bhagujarati' => '2733', + 'bhagurmukhi' => '2605', + 'bhook' => '595', + 'bihiragana' => '12403', + 'bikatakana' => '12499', + 'bilabialclick' => '664', + 'bindigurmukhi' => '2562', + 'birusquare' => '13105', + 'blackcircle' => '9679', + 'blackdiamond' => '9670', + 'blackdownpointingtriangle' => '9660', + 'blackleftpointingpointer' => '9668', + 'blackleftpointingtriangle' => '9664', + 'blacklenticularbracketleft' => '12304', + 'blacklenticularbracketleftvertical' => '65083', + 'blacklenticularbracketright' => '12305', + 'blacklenticularbracketrightvertical' => '65084', + 'blacklowerlefttriangle' => '9699', + 'blacklowerrighttriangle' => '9698', + 'blackrectangle' => '9644', + 'blackrightpointingpointer' => '9658', + 'blackrightpointingtriangle' => '9654', + 'blacksmallsquare' => '9642', + 'blacksmilingface' => '9787', + 'blacksquare' => '9632', + 'blackstar' => '9733', + 'blackupperlefttriangle' => '9700', + 'blackupperrighttriangle' => '9701', + 'blackuppointingsmalltriangle' => '9652', + 'blackuppointingtriangle' => '9650', + 'blank' => '9251', + 'bleft' => '61679', + 'bleftright' => '61683', + 'blinebelow' => '7687', + 'blk12' => '9618', + 'blk14' => '9617', + 'blk34' => '9619', + 'block' => '9608', + 'bmonospace' => '65346', + 'bne' => '61686', + 'bnw' => '61685', + 'bobaimaithai' => '3610', + 'bohiragana' => '12412', + 'bokatakana' => '12508', + 'bomb' => '61517', + 'book' => '61478', + 'bottom' => '8869', + 'bowtie' => '8904', + 'box2' => '61608', + 'box3' => '61551', + 'box4' => '61552', + 'boxDL' => '9559', + 'boxDR' => '9556', + 'boxDl' => '9558', + 'boxDr' => '9555', + 'boxH' => '9552', + 'boxHD' => '9574', + 'boxHU' => '9577', + 'boxHd' => '9572', + 'boxHu' => '9575', + 'boxUL' => '9565', + 'boxUR' => '9562', + 'boxUl' => '9564', + 'boxUr' => '9561', + 'boxV' => '9553', + 'boxVH' => '9580', + 'boxVL' => '9571', + 'boxVR' => '9568', + 'boxVh' => '9579', + 'boxVl' => '9570', + 'boxVr' => '9567', + 'boxcheckbld' => '61694', + 'boxdL' => '9557', + 'boxdR' => '9554', + 'boxdl' => '9488', + 'boxdr' => '9484', + 'boxh' => '9472', + 'boxhD' => '9573', + 'boxhU' => '9576', + 'boxhd' => '9516', + 'boxhu' => '9524', + 'boxshadowdwn' => '61553', + 'boxshadowup' => '61554', + 'boxuL' => '9563', + 'boxuR' => '9560', + 'boxul' => '9496', + 'boxur' => '9492', + 'boxv' => '9474', + 'boxvH' => '9578', + 'boxvL' => '9569', + 'boxvR' => '9566', + 'boxvh' => '9532', + 'boxvl' => '9508', + 'boxvr' => '9500', + 'boxxmarkbld' => '61693', + 'bparen' => '9373', + 'bprime' => '8245', + 'bqsquare' => '13251', + 'braceex' => '63732', + 'braceleft' => '123', + 'braceleftbt' => '63731', + 'braceleftmid' => '63730', + 'braceleftmonospace' => '65371', + 'braceleftsmall' => '65115', + 'bracelefttp' => '63729', + 'braceleftvertical' => '65079', + 'braceright' => '125', + 'bracerightbt' => '63742', + 'bracerightmid' => '63741', + 'bracerightmonospace' => '65373', + 'bracerightsmall' => '65116', + 'bracerighttp' => '63740', + 'bracerightvertical' => '65080', + 'bracketleft' => '91', + 'bracketleftbt' => '63728', + 'bracketleftex' => '63727', + 'bracketleftmonospace' => '65339', + 'bracketlefttp' => '63726', + 'bracketright' => '93', + 'bracketrightbt' => '63739', + 'bracketrightex' => '63738', + 'bracketrightmonospace' => '65341', + 'bracketrighttp' => '63737', + 'breve' => '728', + 'brevebelowcmb' => '814', + 'brevecmb' => '774', + 'breveinvertedbelowcmb' => '815', + 'breveinvertedcmb' => '785', + 'breveinverteddoublecmb' => '865', + 'bridgebelowcmb' => '810', + 'bridgeinvertedbelowcmb' => '826', + 'bright' => '61680', + 'brokenbar' => '166', + 'brvbar' => '166', + 'bse' => '61688', + 'bsim' => '8765', + 'bsime' => '8909', + 'bsol' => '92', + 'bstroke' => '384', + 'bsuperior' => '63210', + 'bsw' => '61687', + 'btopbar' => '387', + 'budleafne' => '61590', + 'budleafnw' => '61591', + 'budleafse' => '61593', + 'budleafsw' => '61592', + 'buhiragana' => '12406', + 'bukatakana' => '12502', + 'bull' => '8226', + 'bullet' => '8226', + 'bulletinverse' => '9688', + 'bulletoperator' => '8729', + 'bullseye' => '9678', + 'bump' => '8782', + 'bumpe' => '8783', + 'bup' => '61681', + 'bupdown' => '61684', + 'c' => '99', + 'caarmenian' => '1390', + 'cabengali' => '2458', + 'cacute' => '263', + 'cadeva' => '2330', + 'cagujarati' => '2714', + 'cagurmukhi' => '2586', + 'calsquare' => '13192', + 'cancer' => '61537', + 'candle' => '61479', + 'candrabindubengali' => '2433', + 'candrabinducmb' => '784', + 'candrabindudeva' => '2305', + 'candrabindugujarati' => '2689', + 'cap' => '8745', + 'capricorn' => '61543', + 'capslock' => '8682', + 'careof' => '8453', + 'caret' => '8257', + 'caron' => '711', + 'caronbelowcmb' => '812', + 'caroncmb' => '780', + 'carriagereturn' => '8629', + 'cbopomofo' => '12568', + 'ccaron' => '269', + 'ccedil' => '231', + 'ccedilla' => '231', + 'ccedillaacute' => '7689', + 'ccirc' => '265', + 'ccircle' => '9426', + 'ccircumflex' => '265', + 'ccurl' => '597', + 'cdot' => '267', + 'cdotaccent' => '267', + 'cdsquare' => '13253', + 'cedil' => '184', + 'cedilla' => '184', + 'cedillacmb' => '807', + 'cent' => '162', + 'centigrade' => '8451', + 'centinferior' => '63199', + 'centmonospace' => '65504', + 'centoldstyle' => '63394', + 'centsuperior' => '63200', + 'chaarmenian' => '1401', + 'chabengali' => '2459', + 'chadeva' => '2331', + 'chagujarati' => '2715', + 'chagurmukhi' => '2587', + 'chbopomofo' => '12564', + 'chcy' => '1095', + 'cheabkhasiancyrillic' => '1213', + 'check' => '10003', + 'checkbld' => '61692', + 'checkmark' => '10003', + 'checyrillic' => '1095', + 'chedescenderabkhasiancyrillic' => '1215', + 'chedescendercyrillic' => '1207', + 'chedieresiscyrillic' => '1269', + 'cheharmenian' => '1395', + 'chekhakassiancyrillic' => '1228', + 'cheverticalstrokecyrillic' => '1209', + 'chi' => '967', + 'chieuchacirclekorean' => '12919', + 'chieuchaparenkorean' => '12823', + 'chieuchcirclekorean' => '12905', + 'chieuchkorean' => '12618', + 'chieuchparenkorean' => '12809', + 'chochangthai' => '3594', + 'chochanthai' => '3592', + 'chochingthai' => '3593', + 'chochoethai' => '3596', + 'chook' => '392', + 'cieucacirclekorean' => '12918', + 'cieucaparenkorean' => '12822', + 'cieuccirclekorean' => '12904', + 'cieuckorean' => '12616', + 'cieucparenkorean' => '12808', + 'cieucuparenkorean' => '12828', + 'circ' => '710', + 'circle' => '9675', + 'circle2' => '61598', + 'circle4' => '61599', + 'circle6' => '61548', + 'circledown' => '61662', + 'circleleft' => '61659', + 'circlemultiply' => '8855', + 'circleot' => '8857', + 'circleplus' => '8853', + 'circlepostalmark' => '12342', + 'circleright' => '61660', + 'circleshadowdwn' => '61549', + 'circleshadowup' => '61606', + 'circlestar' => '61621', + 'circleup' => '61661', + 'circlewithlefthalfblack' => '9680', + 'circlewithrighthalfblack' => '9681', + 'circumflex' => '710', + 'circumflexbelowcmb' => '813', + 'circumflexcmb' => '770', + 'cire' => '8791', + 'clear' => '8999', + 'clickalveolar' => '450', + 'clickdental' => '448', + 'clicklateral' => '449', + 'clickretroflex' => '451', + 'club' => '9827', + 'clubs' => '9827', + 'clubsuitblack' => '9827', + 'clubsuitwhite' => '9831', + 'cmcubedsquare' => '13220', + 'cmonospace' => '65347', + 'cmsquaredsquare' => '13216', + 'coarmenian' => '1409', + 'colon' => '58', + 'colone' => '8788', + 'colonmonetary' => '8353', + 'colonmonospace' => '65306', + 'colonsign' => '8353', + 'colonsmall' => '65109', + 'colontriangularhalfmod' => '721', + 'colontriangularmod' => '720', + 'comma' => '44', + 'commaabovecmb' => '787', + 'commaaboverightcmb' => '789', + 'commaaccent' => '63171', + 'commaarabic' => '1548', + 'commaarmenian' => '1373', + 'commainferior' => '63201', + 'commamonospace' => '65292', + 'command' => '61562', + 'commareversedabovecmb' => '788', + 'commareversedmod' => '701', + 'commasmall' => '65104', + 'commasuperior' => '63202', + 'commat' => '64', + 'commaturnedabovecmb' => '786', + 'commaturnedmod' => '699', + 'comp' => '8705', + 'compass' => '9788', + 'compfn' => '8728', + 'cong' => '8773', + 'congruent' => '8773', + 'conint' => '8750', + 'contourintegral' => '8750', + 'control' => '8963', + 'controlACK' => '6', + 'controlBEL' => '7', + 'controlBS' => '8', + 'controlCAN' => '24', + 'controlCR' => '13', + 'controlDC1' => '17', + 'controlDC2' => '18', + 'controlDC3' => '19', + 'controlDC4' => '20', + 'controlDEL' => '127', + 'controlDLE' => '16', + 'controlEM' => '25', + 'controlENQ' => '5', + 'controlEOT' => '4', + 'controlESC' => '27', + 'controlETB' => '23', + 'controlETX' => '3', + 'controlFF' => '12', + 'controlFS' => '28', + 'controlGS' => '29', + 'controlHT' => '9', + 'controlLF' => '10', + 'controlNAK' => '21', + 'controlRS' => '30', + 'controlSI' => '15', + 'controlSO' => '14', + 'controlSOT' => '2', + 'controlSTX' => '1', + 'controlSUB' => '26', + 'controlSYN' => '22', + 'controlUS' => '31', + 'controlVT' => '11', + 'copy' => '169', + 'copyright' => '169', + 'copyrightsans' => '63721', + 'copyrightserif' => '63193', + 'copysr' => '8471', + 'cornerbracketleft' => '12300', + 'cornerbracketlefthalfwidth' => '65378', + 'cornerbracketleftvertical' => '65089', + 'cornerbracketright' => '12301', + 'cornerbracketrighthalfwidth' => '65379', + 'cornerbracketrightvertical' => '65090', + 'corporationsquare' => '13183', + 'cosquare' => '13255', + 'coverkgsquare' => '13254', + 'cparen' => '9374', + 'crarr' => '8629', + 'crescentstar' => '61530', + 'cross' => '10007', + 'crossceltic' => '61527', + 'crossmaltese' => '61528', + 'crossoutline' => '61525', + 'crossshadow' => '61526', + 'crosstar2' => '61610', + 'cruzeiro' => '8354', + 'cstretched' => '663', + 'cuepr' => '8926', + 'cuesc' => '8927', + 'cularr' => '8630', + 'cup' => '8746', + 'cupre' => '8828', + 'curarr' => '8631', + 'curlyand' => '8911', + 'curlyor' => '8910', + 'curren' => '164', + 'currency' => '164', + 'cuspopen' => '61618', + 'cuspopen1' => '61619', + 'cuvee' => '8910', + 'cuwed' => '8911', + 'cyrBreve' => '63185', + 'cyrFlex' => '63186', + 'cyrbreve' => '63188', + 'cyrflex' => '63189', + 'd' => '100', + 'dArr' => '8659', + 'daarmenian' => '1380', + 'dabengali' => '2470', + 'dadarabic' => '1590', + 'dadeva' => '2342', + 'dadfinalarabic' => '65214', + 'dadinitialarabic' => '65215', + 'dadmedialarabic' => '65216', + 'dagesh' => '1468', + 'dageshhebrew' => '1468', + 'dagger' => '8224', + 'daggerdbl' => '8225', + 'dagujarati' => '2726', + 'dagurmukhi' => '2598', + 'dahiragana' => '12384', + 'dakatakana' => '12480', + 'dalarabic' => '1583', + 'dalet' => '1491', + 'daletdagesh' => '64307', + 'daletdageshhebrew' => '64307', + 'daleth' => '8504', + 'dalethatafpatah' => '1491', + 'dalethatafpatahhebrew' => '1491', + 'dalethatafsegol' => '1491', + 'dalethatafsegolhebrew' => '1491', + 'dalethebrew' => '1491', + 'dalethiriq' => '1491', + 'dalethiriqhebrew' => '1491', + 'daletholam' => '1491', + 'daletholamhebrew' => '1491', + 'daletpatah' => '1491', + 'daletpatahhebrew' => '1491', + 'daletqamats' => '1491', + 'daletqamatshebrew' => '1491', + 'daletqubuts' => '1491', + 'daletqubutshebrew' => '1491', + 'daletsegol' => '1491', + 'daletsegolhebrew' => '1491', + 'daletsheva' => '1491', + 'daletshevahebrew' => '1491', + 'dalettsere' => '1491', + 'dalettserehebrew' => '1491', + 'dalfinalarabic' => '65194', + 'dammaarabic' => '1615', + 'dammalowarabic' => '1615', + 'dammatanaltonearabic' => '1612', + 'dammatanarabic' => '1612', + 'danda' => '2404', + 'dargahebrew' => '1447', + 'dargalefthebrew' => '1447', + 'darr' => '8595', + 'darr2' => '8650', + 'dash' => '8208', + 'dashv' => '8867', + 'dasiapneumatacyrilliccmb' => '1157', + 'dblGrave' => '63187', + 'dblac' => '733', + 'dblanglebracketleft' => '12298', + 'dblanglebracketleftvertical' => '65085', + 'dblanglebracketright' => '12299', + 'dblanglebracketrightvertical' => '65086', + 'dblarchinvertedbelowcmb' => '811', + 'dblarrowleft' => '8660', + 'dblarrowright' => '8658', + 'dbldanda' => '2405', + 'dblgrave' => '63190', + 'dblgravecmb' => '783', + 'dblintegral' => '8748', + 'dbllowline' => '8215', + 'dbllowlinecmb' => '819', + 'dbloverlinecmb' => '831', + 'dblprimemod' => '698', + 'dblverticalbar' => '8214', + 'dblverticallineabovecmb' => '782', + 'dbopomofo' => '12553', + 'dbsquare' => '13256', + 'dcaron' => '271', + 'dcedilla' => '7697', + 'dcircle' => '9427', + 'dcircumflexbelow' => '7699', + 'dcroat' => '273', + 'dcy' => '1044', + 'ddabengali' => '2465', + 'ddadeva' => '2337', + 'ddagujarati' => '2721', + 'ddagurmukhi' => '2593', + 'ddalarabic' => '1672', + 'ddalfinalarabic' => '64393', + 'dddhadeva' => '2396', + 'ddhabengali' => '2466', + 'ddhadeva' => '2338', + 'ddhagujarati' => '2722', + 'ddhagurmukhi' => '2594', + 'ddotaccent' => '7691', + 'ddotbelow' => '7693', + 'decimalseparatorarabic' => '1643', + 'decimalseparatorpersian' => '1643', + 'decyrillic' => '1076', + 'deg' => '176', + 'degree' => '176', + 'dehihebrew' => '1453', + 'dehiragana' => '12391', + 'deicoptic' => '1007', + 'dekatakana' => '12487', + 'deleteleft' => '9003', + 'deleteright' => '8998', + 'delta' => '948', + 'deltaturned' => '397', + 'denominatorminusonenumeratorbengali' => '2552', + 'dezh' => '676', + 'dgr' => '948', + 'dhabengali' => '2471', + 'dhadeva' => '2343', + 'dhagujarati' => '2727', + 'dhagurmukhi' => '2599', + 'dharl' => '8643', + 'dharr' => '8642', + 'dhook' => '599', + 'dialytikatonos' => '901', + 'dialytikatonoscmb' => '836', + 'diam' => '8900', + 'diamond' => '9830', + 'diamondsuitwhite' => '9826', + 'diams' => '9830', + 'die' => '168', + 'dieresis' => '168', + 'dieresisacute' => '63191', + 'dieresisbelowcmb' => '804', + 'dieresiscmb' => '776', + 'dieresisgrave' => '63192', + 'dieresistonos' => '901', + 'dihiragana' => '12386', + 'dikatakana' => '12482', + 'dittomark' => '12291', + 'divide' => '247', + 'divides' => '8739', + 'divisionslash' => '8725', + 'divonx' => '8903', + 'djcy' => '1106', + 'djecyrillic' => '1106', + 'dkshade' => '9619', + 'dlarr' => '8601', + 'dlcorn' => '8990', + 'dlcrop' => '8973', + 'dlinebelow' => '7695', + 'dlsquare' => '13207', + 'dmacron' => '273', + 'dmonospace' => '65348', + 'dnblock' => '9604', + 'dochadathai' => '3598', + 'dodecastar3' => '61614', + 'dodekthai' => '3604', + 'dohiragana' => '12393', + 'dokatakana' => '12489', + 'dollar' => '36', + 'dollarinferior' => '63203', + 'dollarmonospace' => '65284', + 'dollaroldstyle' => '63268', + 'dollarsmall' => '65129', + 'dollarsuperior' => '63204', + 'dong' => '8363', + 'dorusquare' => '13094', + 'dot' => '729', + 'dotaccent' => '729', + 'dotaccentcmb' => '775', + 'dotbelowcmb' => '803', + 'dotbelowcomb' => '803', + 'dotkatakana' => '12539', + 'dotlessi' => '305', + 'dotlessj' => '63166', + 'dotlessjstrokehook' => '644', + 'dotmath' => '8901', + 'dottedcircle' => '9676', + 'doubleyodpatah' => '64287', + 'doubleyodpatahhebrew' => '64287', + 'downtackbelowcmb' => '798', + 'downtackmod' => '725', + 'dparen' => '9375', + 'drarr' => '8600', + 'drcorn' => '8991', + 'drcrop' => '8972', + 'droplet' => '61523', + 'dscy' => '1109', + 'dstrok' => '273', + 'dsuperior' => '63211', + 'dtail' => '598', + 'dtopbar' => '396', + 'dtri' => '9663', + 'dtrif' => '9662', + 'duhiragana' => '12389', + 'dukatakana' => '12485', + 'dz' => '499', + 'dzaltone' => '675', + 'dzcaron' => '454', + 'dzcurl' => '677', + 'dzcy' => '1119', + 'dzeabkhasiancyrillic' => '1249', + 'dzecyrillic' => '1109', + 'dzhecyrillic' => '1119', + 'e' => '101', + 'eDot' => '8785', + 'eacgr' => '941', + 'eacute' => '233', + 'earth' => '9793', + 'ebengali' => '2447', + 'ebopomofo' => '12572', + 'ebreve' => '277', + 'ecandradeva' => '2317', + 'ecandragujarati' => '2701', + 'ecandravowelsigndeva' => '2373', + 'ecandravowelsigngujarati' => '2757', + 'ecaron' => '283', + 'ecedillabreve' => '7709', + 'echarmenian' => '1381', + 'echyiwnarmenian' => '1415', + 'ecir' => '8790', + 'ecirc' => '234', + 'ecircle' => '9428', + 'ecircumflex' => '234', + 'ecircumflexacute' => '7871', + 'ecircumflexbelow' => '7705', + 'ecircumflexdotbelow' => '7879', + 'ecircumflexgrave' => '7873', + 'ecircumflexhookabove' => '7875', + 'ecircumflextilde' => '7877', + 'ecolon' => '8789', + 'ecy' => '1101', + 'ecyrillic' => '1108', + 'edblgrave' => '517', + 'edeva' => '2319', + 'edieresis' => '235', + 'edot' => '279', + 'edotaccent' => '279', + 'edotbelow' => '7865', + 'eeacgr' => '942', + 'eegr' => '951', + 'eegurmukhi' => '2575', + 'eematragurmukhi' => '2631', + 'efDot' => '8786', + 'efcyrillic' => '1092', + 'egrave' => '232', + 'egs' => '8925', + 'egujarati' => '2703', + 'eharmenian' => '1383', + 'ehbopomofo' => '12573', + 'ehiragana' => '12360', + 'ehookabove' => '7867', + 'eibopomofo' => '12575', + 'eight' => '56', + 'eightarabic' => '1640', + 'eightbengali' => '2542', + 'eightcircle' => '9319', + 'eightcircleinversesansserif' => '10129', + 'eightdeva' => '2414', + 'eighteencircle' => '9329', + 'eighteenparen' => '9349', + 'eighteenperiod' => '9369', + 'eightgujarati' => '2798', + 'eightgurmukhi' => '2670', + 'eighthackarabic' => '1640', + 'eighthangzhou' => '12328', + 'eighthnotebeamed' => '9835', + 'eightideographicparen' => '12839', + 'eightinferior' => '8328', + 'eightmonospace' => '65304', + 'eightoclock' => '61630', + 'eightoldstyle' => '63288', + 'eightparen' => '9339', + 'eightperiod' => '9359', + 'eightpersian' => '1784', + 'eightroman' => '8567', + 'eightsans' => '61576', + 'eightsansinv' => '61587', + 'eightsuperior' => '8312', + 'eightthai' => '3672', + 'einvertedbreve' => '519', + 'eiotifiedcyrillic' => '1125', + 'ekatakana' => '12456', + 'ekatakanahalfwidth' => '65396', + 'ekonkargurmukhi' => '2676', + 'ekorean' => '12628', + 'elcyrillic' => '1083', + 'element' => '8712', + 'elevencircle' => '9322', + 'elevenoclock' => '61633', + 'elevenparen' => '9342', + 'elevenperiod' => '9362', + 'elevenroman' => '8570', + 'ell' => '8467', + 'ellipsis' => '8230', + 'ellipsisvertical' => '8942', + 'els' => '8924', + 'emacr' => '275', + 'emacron' => '275', + 'emacronacute' => '7703', + 'emacrongrave' => '7701', + 'emcyrillic' => '1084', + 'emdash' => '8212', + 'emdashvertical' => '65073', + 'emonospace' => '65349', + 'emphasismarkarmenian' => '1371', + 'empty' => '8709', + 'emptyset' => '8709', + 'emsp' => '8195', + 'emsp13' => '8196', + 'emsp14' => '8197', + 'enbopomofo' => '12579', + 'encyrillic' => '1085', + 'endash' => '8211', + 'endashvertical' => '65074', + 'endescendercyrillic' => '1187', + 'eng' => '331', + 'engbopomofo' => '12581', + 'enghecyrillic' => '1189', + 'enhookcyrillic' => '1224', + 'ensp' => '8194', + 'enspace' => '8194', + 'envelopeback' => '61482', + 'envelopefront' => '61483', + 'eogon' => '281', + 'eogonek' => '281', + 'eokorean' => '12627', + 'eopen' => '603', + 'eopenclosed' => '666', + 'eopenreversed' => '604', + 'eopenreversedclosed' => '606', + 'eopenreversedhook' => '605', + 'eparen' => '9376', + 'epsi' => '949', + 'epsilon' => '949', + 'epsilontonos' => '941', + 'epsis' => '8714', + 'equal' => '61', + 'equalmonospace' => '65309', + 'equals' => '61', + 'equalsmall' => '65126', + 'equalsuperior' => '8316', + 'equiv' => '8801', + 'equivalence' => '8801', + 'erDot' => '8787', + 'erbopomofo' => '12582', + 'ercyrillic' => '1088', + 'ereversed' => '600', + 'ereversedcyrillic' => '1101', + 'escape' => '61561', + 'escyrillic' => '1089', + 'esdescendercyrillic' => '1195', + 'esdot' => '8784', + 'esh' => '643', + 'eshcurl' => '646', + 'eshortdeva' => '2318', + 'eshortvowelsigndeva' => '2374', + 'eshreversedloop' => '426', + 'eshsquatreversed' => '645', + 'esmallhiragana' => '12359', + 'esmallkatakana' => '12455', + 'esmallkatakanahalfwidth' => '65386', + 'estimated' => '8494', + 'esuperior' => '63212', + 'eta' => '951', + 'etarmenian' => '1384', + 'etatonos' => '942', + 'eth' => '240', + 'etilde' => '7869', + 'etildebelow' => '7707', + 'etnahtafoukhhebrew' => '1425', + 'etnahtafoukhlefthebrew' => '1425', + 'etnahtahebrew' => '1425', + 'etnahtalefthebrew' => '1425', + 'eturned' => '477', + 'eukorean' => '12641', + 'euml' => '235', + 'euro' => '8364', + 'evowelsignbengali' => '2503', + 'evowelsigndeva' => '2375', + 'evowelsigngujarati' => '2759', + 'excl' => '33', + 'exclam' => '33', + 'exclamarmenian' => '1372', + 'exclamdbl' => '8252', + 'exclamdown' => '161', + 'exclamdownsmall' => '63393', + 'exclammonospace' => '65281', + 'exclamsmall' => '63265', + 'exist' => '8707', + 'existential' => '8707', + 'ezh' => '658', + 'ezhcaron' => '495', + 'ezhcurl' => '659', + 'ezhreversed' => '441', + 'ezhtail' => '442', + 'f' => '102', + 'fadeva' => '2398', + 'fagurmukhi' => '2654', + 'fahrenheit' => '8457', + 'fathaarabic' => '1614', + 'fathalowarabic' => '1614', + 'fathatanarabic' => '1611', + 'fbopomofo' => '12552', + 'fcircle' => '9429', + 'fcy' => '1092', + 'fdotaccent' => '7711', + 'feharabic' => '1601', + 'feharmenian' => '1414', + 'fehfinalarabic' => '65234', + 'fehinitialarabic' => '65235', + 'fehmedialarabic' => '65236', + 'feicoptic' => '997', + 'female' => '9792', + 'ff' => '64256', + 'ffi' => '64259', + 'ffl' => '64260', + 'fi' => '64257', + 'fifteencircle' => '9326', + 'fifteenparen' => '9346', + 'fifteenperiod' => '9366', + 'figuredash' => '8210', + 'filecabinet' => '61493', + 'filetalltext' => '61491', + 'filetalltext1' => '61490', + 'filetalltext3' => '61492', + 'filledbox' => '9632', + 'filledrect' => '9644', + 'finalkaf' => '1498', + 'finalkafdagesh' => '64314', + 'finalkafdageshhebrew' => '64314', + 'finalkafhebrew' => '1498', + 'finalkafqamats' => '1498', + 'finalkafqamatshebrew' => '1498', + 'finalkafsheva' => '1498', + 'finalkafshevahebrew' => '1498', + 'finalmem' => '1501', + 'finalmemhebrew' => '1501', + 'finalnun' => '1503', + 'finalnunhebrew' => '1503', + 'finalpe' => '1507', + 'finalpehebrew' => '1507', + 'finaltsadi' => '1509', + 'finaltsadihebrew' => '1509', + 'firsttonechinese' => '713', + 'fisheye' => '9673', + 'fitacyrillic' => '1139', + 'five' => '53', + 'fivearabic' => '1637', + 'fivebengali' => '2539', + 'fivecircle' => '9316', + 'fivecircleinversesansserif' => '10126', + 'fivedeva' => '2411', + 'fiveeighths' => '8541', + 'fivegujarati' => '2795', + 'fivegurmukhi' => '2667', + 'fivehackarabic' => '1637', + 'fivehangzhou' => '12325', + 'fiveideographicparen' => '12836', + 'fiveinferior' => '8325', + 'fivemonospace' => '65301', + 'fiveoclock' => '61627', + 'fiveoldstyle' => '63285', + 'fiveparen' => '9336', + 'fiveperiod' => '9356', + 'fivepersian' => '1781', + 'fiveroman' => '8564', + 'fivesans' => '61573', + 'fivesansinv' => '61584', + 'fivesuperior' => '8309', + 'fivethai' => '3669', + 'fl' => '64258', + 'flag' => '61519', + 'flat' => '9837', + 'floppy3' => '61500', + 'floppy5' => '61501', + 'florin' => '402', + 'fmonospace' => '65350', + 'fmsquare' => '13209', + 'fnof' => '402', + 'fofanthai' => '3615', + 'fofathai' => '3613', + 'folder' => '61488', + 'folderopen' => '61489', + 'fongmanthai' => '3663', + 'forall' => '8704', + 'fork' => '8916', + 'four' => '52', + 'fourarabic' => '1636', + 'fourbengali' => '2538', + 'fourcircle' => '9315', + 'fourcircleinversesansserif' => '10125', + 'fourdeva' => '2410', + 'fourgujarati' => '2794', + 'fourgurmukhi' => '2666', + 'fourhackarabic' => '1636', + 'fourhangzhou' => '12324', + 'fourideographicparen' => '12835', + 'fourinferior' => '8324', + 'fourmonospace' => '65300', + 'fournumeratorbengali' => '2551', + 'fouroclock' => '61626', + 'fouroldstyle' => '63284', + 'fourparen' => '9335', + 'fourperiod' => '9355', + 'fourpersian' => '1780', + 'fourroman' => '8563', + 'foursans' => '61572', + 'foursansinv' => '61583', + 'foursuperior' => '8308', + 'fourteencircle' => '9325', + 'fourteenparen' => '9345', + 'fourteenperiod' => '9365', + 'fourthai' => '3668', + 'fourthtonechinese' => '715', + 'fparen' => '9377', + 'frac12' => '189', + 'frac13' => '8531', + 'frac14' => '188', + 'frac15' => '8533', + 'frac16' => '8537', + 'frac18' => '8539', + 'frac23' => '8532', + 'frac25' => '8534', + 'frac34' => '190', + 'frac35' => '8535', + 'frac38' => '8540', + 'frac45' => '8536', + 'frac56' => '8538', + 'frac58' => '8541', + 'frac78' => '8542', + 'fraction' => '8260', + 'franc' => '8355', + 'frasl' => '8260', + 'frown' => '8994', + 'frownface' => '61516', + 'g' => '103', + 'gE' => '8807', + 'gabengali' => '2455', + 'gacute' => '501', + 'gadeva' => '2327', + 'gafarabic' => '1711', + 'gaffinalarabic' => '64403', + 'gafinitialarabic' => '64404', + 'gafmedialarabic' => '64405', + 'gagujarati' => '2711', + 'gagurmukhi' => '2583', + 'gahiragana' => '12364', + 'gakatakana' => '12460', + 'gamma' => '947', + 'gammad' => '989', + 'gammalatinsmall' => '611', + 'gammasuperior' => '736', + 'gangiacoptic' => '1003', + 'gbopomofo' => '12557', + 'gbreve' => '287', + 'gcaron' => '487', + 'gcedil' => '291', + 'gcedilla' => '291', + 'gcirc' => '285', + 'gcircle' => '9430', + 'gcircumflex' => '285', + 'gcommaaccent' => '291', + 'gcy' => '1075', + 'gdot' => '289', + 'gdotaccent' => '289', + 'ge' => '8805', + 'gecyrillic' => '1075', + 'gehiragana' => '12370', + 'gekatakana' => '12466', + 'gel' => '8923', + 'gemini' => '61536', + 'geometricallyequal' => '8785', + 'gereshaccenthebrew' => '1436', + 'gereshhebrew' => '1523', + 'gereshmuqdamhebrew' => '1437', + 'germandbls' => '223', + 'gershayimaccenthebrew' => '1438', + 'gershayimhebrew' => '1524', + 'ges' => '8805', + 'getamark' => '12307', + 'ggr' => '947', + 'ghabengali' => '2456', + 'ghadarmenian' => '1394', + 'ghadeva' => '2328', + 'ghagujarati' => '2712', + 'ghagurmukhi' => '2584', + 'ghainarabic' => '1594', + 'ghainfinalarabic' => '65230', + 'ghaininitialarabic' => '65231', + 'ghainmedialarabic' => '65232', + 'ghemiddlehookcyrillic' => '1173', + 'ghestrokecyrillic' => '1171', + 'gheupturncyrillic' => '1169', + 'ghhadeva' => '2394', + 'ghhagurmukhi' => '2650', + 'ghook' => '608', + 'ghzsquare' => '13203', + 'gihiragana' => '12366', + 'gikatakana' => '12462', + 'gimarmenian' => '1379', + 'gimel' => '8503', + 'gimeldagesh' => '64306', + 'gimeldageshhebrew' => '64306', + 'gimelhebrew' => '1490', + 'gjcy' => '1107', + 'gjecyrillic' => '1107', + 'gl' => '8823', + 'glottalinvertedstroke' => '446', + 'glottalstop' => '660', + 'glottalstopinverted' => '662', + 'glottalstopmod' => '704', + 'glottalstopreversed' => '661', + 'glottalstopreversedmod' => '705', + 'glottalstopreversedsuperior' => '740', + 'glottalstopstroke' => '673', + 'glottalstopstrokereversed' => '674', + 'gmacron' => '7713', + 'gmonospace' => '65351', + 'gnsim' => '8935', + 'gohiragana' => '12372', + 'gokatakana' => '12468', + 'gparen' => '9378', + 'gpasquare' => '13228', + 'gradient' => '8711', + 'grave' => '96', + 'gravebelowcmb' => '790', + 'gravecmb' => '768', + 'gravecomb' => '768', + 'gravedeva' => '2387', + 'gravelowmod' => '718', + 'gravemonospace' => '65344', + 'gravetonecmb' => '832', + 'greater' => '62', + 'greaterequal' => '8805', + 'greaterequalorless' => '8923', + 'greatermonospace' => '65310', + 'greaterorequivalent' => '8819', + 'greaterorless' => '8823', + 'greateroverequal' => '8807', + 'greatersmall' => '65125', + 'gscript' => '609', + 'gsdot' => '8919', + 'gsim' => '8819', + 'gstroke' => '485', + 'gt' => '62', + 'guhiragana' => '12368', + 'guillemotleft' => '171', + 'guillemotright' => '187', + 'guilsinglleft' => '8249', + 'guilsinglright' => '8250', + 'gukatakana' => '12464', + 'guramusquare' => '13080', + 'gvnE' => '8809', + 'gysquare' => '13257', + 'h' => '104', + 'hArr' => '8660', + 'haabkhasiancyrillic' => '1193', + 'haaltonearabic' => '1729', + 'habengali' => '2489', + 'hadescendercyrillic' => '1203', + 'hadeva' => '2361', + 'hagujarati' => '2745', + 'hagurmukhi' => '2617', + 'haharabic' => '1581', + 'hahfinalarabic' => '65186', + 'hahinitialarabic' => '65187', + 'hahiragana' => '12399', + 'hahmedialarabic' => '65188', + 'hairsp' => '8202', + 'haitusquare' => '13098', + 'hakatakana' => '12495', + 'hakatakanahalfwidth' => '65418', + 'halantgurmukhi' => '2637', + 'hamilt' => '8459', + 'hamzaarabic' => '1569', + 'hamzadammaarabic' => '1569', + 'hamzadammatanarabic' => '1569', + 'hamzafathaarabic' => '1569', + 'hamzafathatanarabic' => '1569', + 'hamzalowarabic' => '1569', + 'hamzalowkasraarabic' => '1569', + 'hamzalowkasratanarabic' => '1569', + 'hamzasukunarabic' => '1569', + 'handhalt' => '61513', + 'handok' => '61506', + 'handptdwn' => '61512', + 'handptleft' => '61509', + 'handptright' => '61510', + 'handptup' => '61511', + 'handv' => '61505', + 'handwrite' => '61503', + 'handwriteleft' => '61504', + 'hangulfiller' => '12644', + 'hardcy' => '1098', + 'harddisk' => '61499', + 'hardsigncyrillic' => '1098', + 'harpoonleftbarbup' => '8636', + 'harpoonrightbarbup' => '8640', + 'harr' => '8596', + 'harrw' => '8621', + 'hasquare' => '13258', + 'hatafpatah' => '1458', + 'hatafpatah16' => '1458', + 'hatafpatah23' => '1458', + 'hatafpatah2f' => '1458', + 'hatafpatahhebrew' => '1458', + 'hatafpatahnarrowhebrew' => '1458', + 'hatafpatahquarterhebrew' => '1458', + 'hatafpatahwidehebrew' => '1458', + 'hatafqamats' => '1459', + 'hatafqamats1b' => '1459', + 'hatafqamats28' => '1459', + 'hatafqamats34' => '1459', + 'hatafqamatshebrew' => '1459', + 'hatafqamatsnarrowhebrew' => '1459', + 'hatafqamatsquarterhebrew' => '1459', + 'hatafqamatswidehebrew' => '1459', + 'hatafsegol' => '1457', + 'hatafsegol17' => '1457', + 'hatafsegol24' => '1457', + 'hatafsegol30' => '1457', + 'hatafsegolhebrew' => '1457', + 'hatafsegolnarrowhebrew' => '1457', + 'hatafsegolquarterhebrew' => '1457', + 'hatafsegolwidehebrew' => '1457', + 'hbar' => '295', + 'hbopomofo' => '12559', + 'hbrevebelow' => '7723', + 'hcedilla' => '7721', + 'hcirc' => '293', + 'hcircle' => '9431', + 'hcircumflex' => '293', + 'hdieresis' => '7719', + 'hdotaccent' => '7715', + 'hdotbelow' => '7717', + 'he' => '1492', + 'head2down' => '61658', + 'head2left' => '61655', + 'head2right' => '61656', + 'head2up' => '61657', + 'heart' => '9829', + 'hearts' => '9829', + 'heartsuitblack' => '9829', + 'heartsuitwhite' => '9825', + 'hedagesh' => '64308', + 'hedageshhebrew' => '64308', + 'hehaltonearabic' => '1729', + 'heharabic' => '1607', + 'hehebrew' => '1492', + 'hehfinalaltonearabic' => '64423', + 'hehfinalalttwoarabic' => '65258', + 'hehfinalarabic' => '65258', + 'hehhamzaabovefinalarabic' => '64421', + 'hehhamzaaboveisolatedarabic' => '64420', + 'hehinitialaltonearabic' => '64424', + 'hehinitialarabic' => '65259', + 'hehiragana' => '12408', + 'hehmedialaltonearabic' => '64425', + 'hehmedialarabic' => '65260', + 'heiseierasquare' => '13179', + 'hekatakana' => '12504', + 'hekatakanahalfwidth' => '65421', + 'hekutaarusquare' => '13110', + 'hellip' => '8230', + 'henghook' => '615', + 'herutusquare' => '13113', + 'het' => '1495', + 'hethebrew' => '1495', + 'hexstar2' => '61612', + 'hhook' => '614', + 'hhooksuperior' => '689', + 'hieuhacirclekorean' => '12923', + 'hieuhaparenkorean' => '12827', + 'hieuhcirclekorean' => '12909', + 'hieuhkorean' => '12622', + 'hieuhparenkorean' => '12813', + 'hihiragana' => '12402', + 'hikatakana' => '12498', + 'hikatakanahalfwidth' => '65419', + 'hiriq' => '1460', + 'hiriq14' => '1460', + 'hiriq21' => '1460', + 'hiriq2d' => '1460', + 'hiriqhebrew' => '1460', + 'hiriqnarrowhebrew' => '1460', + 'hiriqquarterhebrew' => '1460', + 'hiriqwidehebrew' => '1460', + 'hlinebelow' => '7830', + 'hmonospace' => '65352', + 'hoarmenian' => '1392', + 'hohipthai' => '3627', + 'hohiragana' => '12411', + 'hokatakana' => '12507', + 'hokatakanahalfwidth' => '65422', + 'holam' => '1465', + 'holam19' => '1465', + 'holam26' => '1465', + 'holam32' => '1465', + 'holamhebrew' => '1465', + 'holamnarrowhebrew' => '1465', + 'holamquarterhebrew' => '1465', + 'holamwidehebrew' => '1465', + 'honokhukthai' => '3630', + 'hookabovecomb' => '777', + 'hookcmb' => '777', + 'hookpalatalizedbelowcmb' => '801', + 'hookretroflexbelowcmb' => '802', + 'hoonsquare' => '13122', + 'horbar' => '8213', + 'horicoptic' => '1001', + 'horizontalbar' => '8213', + 'horncmb' => '795', + 'hotsprings' => '9832', + 'hourglass' => '61494', + 'house' => '8962', + 'hparen' => '9379', + 'hstrok' => '295', + 'hsuperior' => '688', + 'hturned' => '613', + 'huhiragana' => '12405', + 'huiitosquare' => '13107', + 'hukatakana' => '12501', + 'hukatakanahalfwidth' => '65420', + 'hungarumlaut' => '733', + 'hungarumlautcmb' => '779', + 'hv' => '405', + 'hybull' => '8259', + 'hyphen' => '45', + 'hypheninferior' => '63205', + 'hyphenmonospace' => '65293', + 'hyphensmall' => '65123', + 'hyphensuperior' => '63206', + 'hyphentwo' => '8208', + 'i' => '105', + 'iacgr' => '943', + 'iacute' => '237', + 'iacyrillic' => '1103', + 'ibengali' => '2439', + 'ibopomofo' => '12583', + 'ibreve' => '301', + 'icaron' => '464', + 'icirc' => '238', + 'icircle' => '9432', + 'icircumflex' => '238', + 'icy' => '1080', + 'icyrillic' => '1110', + 'idblgrave' => '521', + 'ideographearthcircle' => '12943', + 'ideographfirecircle' => '12939', + 'ideographicallianceparen' => '12863', + 'ideographiccallparen' => '12858', + 'ideographiccentrecircle' => '12965', + 'ideographicclose' => '12294', + 'ideographiccomma' => '12289', + 'ideographiccommaleft' => '65380', + 'ideographiccongratulationparen' => '12855', + 'ideographiccorrectcircle' => '12963', + 'ideographicearthparen' => '12847', + 'ideographicenterpriseparen' => '12861', + 'ideographicexcellentcircle' => '12957', + 'ideographicfestivalparen' => '12864', + 'ideographicfinancialcircle' => '12950', + 'ideographicfinancialparen' => '12854', + 'ideographicfireparen' => '12843', + 'ideographichaveparen' => '12850', + 'ideographichighcircle' => '12964', + 'ideographiciterationmark' => '12293', + 'ideographiclaborcircle' => '12952', + 'ideographiclaborparen' => '12856', + 'ideographicleftcircle' => '12967', + 'ideographiclowcircle' => '12966', + 'ideographicmedicinecircle' => '12969', + 'ideographicmetalparen' => '12846', + 'ideographicmoonparen' => '12842', + 'ideographicnameparen' => '12852', + 'ideographicperiod' => '12290', + 'ideographicprintcircle' => '12958', + 'ideographicreachparen' => '12867', + 'ideographicrepresentparen' => '12857', + 'ideographicresourceparen' => '12862', + 'ideographicrightcircle' => '12968', + 'ideographicsecretcircle' => '12953', + 'ideographicselfparen' => '12866', + 'ideographicsocietyparen' => '12851', + 'ideographicspace' => '12288', + 'ideographicspecialparen' => '12853', + 'ideographicstockparen' => '12849', + 'ideographicstudyparen' => '12859', + 'ideographicsunparen' => '12848', + 'ideographicsuperviseparen' => '12860', + 'ideographicwaterparen' => '12844', + 'ideographicwoodparen' => '12845', + 'ideographiczero' => '12295', + 'ideographmetalcircle' => '12942', + 'ideographmooncircle' => '12938', + 'ideographnamecircle' => '12948', + 'ideographsuncircle' => '12944', + 'ideographwatercircle' => '12940', + 'ideographwoodcircle' => '12941', + 'ideva' => '2311', + 'idiagr' => '912', + 'idieresis' => '239', + 'idieresisacute' => '7727', + 'idieresiscyrillic' => '1253', + 'idigr' => '970', + 'idotbelow' => '7883', + 'iebrevecyrillic' => '1239', + 'iecy' => '1077', + 'iecyrillic' => '1077', + 'ieungacirclekorean' => '12917', + 'ieungaparenkorean' => '12821', + 'ieungcirclekorean' => '12903', + 'ieungkorean' => '12615', + 'ieungparenkorean' => '12807', + 'iexcl' => '161', + 'iff' => '8660', + 'igr' => '953', + 'igrave' => '236', + 'igujarati' => '2695', + 'igurmukhi' => '2567', + 'ihiragana' => '12356', + 'ihookabove' => '7881', + 'iibengali' => '2440', + 'iicyrillic' => '1080', + 'iideva' => '2312', + 'iigujarati' => '2696', + 'iigurmukhi' => '2568', + 'iimatragurmukhi' => '2624', + 'iinvertedbreve' => '523', + 'iishortcyrillic' => '1081', + 'iivowelsignbengali' => '2496', + 'iivowelsigndeva' => '2368', + 'iivowelsigngujarati' => '2752', + 'ij' => '307', + 'ijlig' => '307', + 'ikatakana' => '12452', + 'ikatakanahalfwidth' => '65394', + 'ikorean' => '12643', + 'ilde' => '732', + 'iluyhebrew' => '1452', + 'imacr' => '299', + 'imacron' => '299', + 'imacroncyrillic' => '1251', + 'image' => '8465', + 'imageorapproximatelyequal' => '8787', + 'imatragurmukhi' => '2623', + 'imonospace' => '65353', + 'incare' => '8453', + 'increment' => '8710', + 'infin' => '8734', + 'infinity' => '8734', + 'iniarmenian' => '1387', + 'inodot' => '305', + 'int' => '8747', + 'intcal' => '8890', + 'integral' => '8747', + 'integralbottom' => '8993', + 'integralbt' => '8993', + 'integralex' => '63733', + 'integraltop' => '8992', + 'integraltp' => '8992', + 'intersection' => '8745', + 'intisquare' => '13061', + 'invbullet' => '9688', + 'invcircle' => '9689', + 'invsmileface' => '9787', + 'iocy' => '1105', + 'iocyrillic' => '1105', + 'iogon' => '303', + 'iogonek' => '303', + 'iota' => '953', + 'iotadieresis' => '970', + 'iotadieresistonos' => '912', + 'iotalatin' => '617', + 'iotatonos' => '943', + 'iparen' => '9380', + 'iquest' => '191', + 'irigurmukhi' => '2674', + 'isin' => '8712', + 'ismallhiragana' => '12355', + 'ismallkatakana' => '12451', + 'ismallkatakanahalfwidth' => '65384', + 'issharbengali' => '2554', + 'istroke' => '616', + 'isuperior' => '63213', + 'iterationhiragana' => '12445', + 'iterationkatakana' => '12541', + 'itilde' => '297', + 'itildebelow' => '7725', + 'iubopomofo' => '12585', + 'iucyrillic' => '1102', + 'iukcy' => '1110', + 'iuml' => '239', + 'ivowelsignbengali' => '2495', + 'ivowelsigndeva' => '2367', + 'ivowelsigngujarati' => '2751', + 'izhitsacyrillic' => '1141', + 'izhitsadblgravecyrillic' => '1143', + 'j' => '106', + 'jaarmenian' => '1393', + 'jabengali' => '2460', + 'jadeva' => '2332', + 'jagujarati' => '2716', + 'jagurmukhi' => '2588', + 'jbopomofo' => '12560', + 'jcaron' => '496', + 'jcirc' => '309', + 'jcircle' => '9433', + 'jcircumflex' => '309', + 'jcrossedtail' => '669', + 'jcy' => '1081', + 'jdotlessstroke' => '607', + 'jecyrillic' => '1112', + 'jeemarabic' => '1580', + 'jeemfinalarabic' => '65182', + 'jeeminitialarabic' => '65183', + 'jeemmedialarabic' => '65184', + 'jeharabic' => '1688', + 'jehfinalarabic' => '64395', + 'jhabengali' => '2461', + 'jhadeva' => '2333', + 'jhagujarati' => '2717', + 'jhagurmukhi' => '2589', + 'jheharmenian' => '1403', + 'jis' => '12292', + 'jmonospace' => '65354', + 'jparen' => '9381', + 'jsercy' => '1112', + 'jsuperior' => '690', + 'jukcy' => '1108', + 'k' => '107', + 'kabashkircyrillic' => '1185', + 'kabengali' => '2453', + 'kacute' => '7729', + 'kacyrillic' => '1082', + 'kadescendercyrillic' => '1179', + 'kadeva' => '2325', + 'kaf' => '1499', + 'kafarabic' => '1603', + 'kafdagesh' => '64315', + 'kafdageshhebrew' => '64315', + 'kaffinalarabic' => '65242', + 'kafhebrew' => '1499', + 'kafinitialarabic' => '65243', + 'kafmedialarabic' => '65244', + 'kafrafehebrew' => '64333', + 'kagujarati' => '2709', + 'kagurmukhi' => '2581', + 'kahiragana' => '12363', + 'kahookcyrillic' => '1220', + 'kakatakana' => '12459', + 'kakatakanahalfwidth' => '65398', + 'kappa' => '954', + 'kappasymbolgreek' => '1008', + 'kappav' => '1008', + 'kapyeounmieumkorean' => '12657', + 'kapyeounphieuphkorean' => '12676', + 'kapyeounpieupkorean' => '12664', + 'kapyeounssangpieupkorean' => '12665', + 'karoriisquare' => '13069', + 'kashidaautoarabic' => '1600', + 'kashidaautonosidebearingarabic' => '1600', + 'kasmallkatakana' => '12533', + 'kasquare' => '13188', + 'kasraarabic' => '1616', + 'kasratanarabic' => '1613', + 'kastrokecyrillic' => '1183', + 'katahiraprolongmarkhalfwidth' => '65392', + 'kaverticalstrokecyrillic' => '1181', + 'kbopomofo' => '12558', + 'kcalsquare' => '13193', + 'kcaron' => '489', + 'kcedil' => '311', + 'kcedilla' => '311', + 'kcircle' => '9434', + 'kcommaaccent' => '311', + 'kcy' => '1082', + 'kdotbelow' => '7731', + 'keharmenian' => '1412', + 'kehiragana' => '12369', + 'kekatakana' => '12465', + 'kekatakanahalfwidth' => '65401', + 'kenarmenian' => '1391', + 'kesmallkatakana' => '12534', + 'keyboard' => '61495', + 'kgr' => '954', + 'kgreen' => '312', + 'kgreenlandic' => '312', + 'khabengali' => '2454', + 'khacyrillic' => '1093', + 'khadeva' => '2326', + 'khagujarati' => '2710', + 'khagurmukhi' => '2582', + 'khaharabic' => '1582', + 'khahfinalarabic' => '65190', + 'khahinitialarabic' => '65191', + 'khahmedialarabic' => '65192', + 'khcy' => '1093', + 'kheicoptic' => '999', + 'khgr' => '967', + 'khhadeva' => '2393', + 'khhagurmukhi' => '2649', + 'khieukhacirclekorean' => '12920', + 'khieukhaparenkorean' => '12824', + 'khieukhcirclekorean' => '12906', + 'khieukhkorean' => '12619', + 'khieukhparenkorean' => '12810', + 'khokhaithai' => '3586', + 'khokhonthai' => '3589', + 'khokhuatthai' => '3587', + 'khokhwaithai' => '3588', + 'khomutthai' => '3675', + 'khook' => '409', + 'khorakhangthai' => '3590', + 'khzsquare' => '13201', + 'kihiragana' => '12365', + 'kikatakana' => '12461', + 'kikatakanahalfwidth' => '65399', + 'kiroguramusquare' => '13077', + 'kiromeetorusquare' => '13078', + 'kirosquare' => '13076', + 'kiyeokacirclekorean' => '12910', + 'kiyeokaparenkorean' => '12814', + 'kiyeokcirclekorean' => '12896', + 'kiyeokkorean' => '12593', + 'kiyeokparenkorean' => '12800', + 'kiyeoksioskorean' => '12595', + 'kjcy' => '1116', + 'kjecyrillic' => '1116', + 'klinebelow' => '7733', + 'klsquare' => '13208', + 'kmcubedsquare' => '13222', + 'kmonospace' => '65355', + 'kmsquaredsquare' => '13218', + 'kohiragana' => '12371', + 'kohmsquare' => '13248', + 'kokaithai' => '3585', + 'kokatakana' => '12467', + 'kokatakanahalfwidth' => '65402', + 'kooposquare' => '13086', + 'koppacyrillic' => '1153', + 'koreanstandardsymbol' => '12927', + 'koroniscmb' => '835', + 'kparen' => '9382', + 'kpasquare' => '13226', + 'ksicyrillic' => '1135', + 'ktsquare' => '13263', + 'kturned' => '670', + 'kuhiragana' => '12367', + 'kukatakana' => '12463', + 'kukatakanahalfwidth' => '65400', + 'kvsquare' => '13240', + 'kwsquare' => '13246', + 'l' => '108', + 'lAarr' => '8666', + 'lArr' => '8656', + 'lE' => '8806', + 'labengali' => '2482', + 'lacute' => '314', + 'ladeva' => '2354', + 'lagran' => '8466', + 'lagujarati' => '2738', + 'lagurmukhi' => '2610', + 'lakkhangyaothai' => '3653', + 'lamaleffinalarabic' => '65276', + 'lamalefhamzaabovefinalarabic' => '65272', + 'lamalefhamzaaboveisolatedarabic' => '65271', + 'lamalefhamzabelowfinalarabic' => '65274', + 'lamalefhamzabelowisolatedarabic' => '65273', + 'lamalefisolatedarabic' => '65275', + 'lamalefmaddaabovefinalarabic' => '65270', + 'lamalefmaddaaboveisolatedarabic' => '65269', + 'lamarabic' => '1604', + 'lambda' => '955', + 'lambdastroke' => '411', + 'lamed' => '1500', + 'lameddagesh' => '64316', + 'lameddageshhebrew' => '64316', + 'lamedhebrew' => '1500', + 'lamedholam' => '1500', + 'lamedholamdagesh' => '1500', + 'lamedholamdageshhebrew' => '1500', + 'lamedholamhebrew' => '1500', + 'lamfinalarabic' => '65246', + 'lamhahinitialarabic' => '64714', + 'laminitialarabic' => '65247', + 'lamjeeminitialarabic' => '64713', + 'lamkhahinitialarabic' => '64715', + 'lamlamhehisolatedarabic' => '65010', + 'lammedialarabic' => '65248', + 'lammeemhahinitialarabic' => '64904', + 'lammeeminitialarabic' => '64716', + 'lammeemjeeminitialarabic' => '65247', + 'lammeemkhahinitialarabic' => '65247', + 'lang' => '9001', + 'laquo' => '171', + 'largecircle' => '9711', + 'larr' => '8592', + 'larr2' => '8647', + 'larrhk' => '8617', + 'larrlp' => '8619', + 'larrtl' => '8610', + 'lbar' => '410', + 'lbelt' => '620', + 'lbopomofo' => '12556', + 'lcaron' => '318', + 'lcedil' => '316', + 'lcedilla' => '316', + 'lceil' => '8968', + 'lcircle' => '9435', + 'lcircumflexbelow' => '7741', + 'lcommaaccent' => '316', + 'lcub' => '123', + 'lcy' => '1083', + 'ldot' => '320', + 'ldotaccent' => '320', + 'ldotbelow' => '7735', + 'ldotbelowmacron' => '7737', + 'ldquo' => '8220', + 'ldquor' => '8222', + 'le' => '8804', + 'leafccwne' => '61648', + 'leafccwnw' => '61646', + 'leafccwse' => '61647', + 'leafccwsw' => '61645', + 'leafne' => '61651', + 'leafnw' => '61649', + 'leafse' => '61652', + 'leafsw' => '61650', + 'leftangleabovecmb' => '794', + 'lefttackbelowcmb' => '792', + 'leg' => '8922', + 'leo' => '61538', + 'les' => '8804', + 'less' => '60', + 'lessequal' => '8804', + 'lessequalorgreater' => '8922', + 'lessmonospace' => '65308', + 'lessorequivalent' => '8818', + 'lessorgreater' => '8822', + 'lessoverequal' => '8806', + 'lesssmall' => '65124', + 'lezh' => '622', + 'lfblock' => '9612', + 'lfloor' => '8970', + 'lg' => '8822', + 'lgr' => '955', + 'lhard' => '8637', + 'lharu' => '8636', + 'lhblk' => '9604', + 'lhookretroflex' => '621', + 'libra' => '61540', + 'lira' => '8356', + 'liwnarmenian' => '1388', + 'lj' => '457', + 'ljcy' => '1113', + 'ljecyrillic' => '1113', + 'll' => '63168', + 'lladeva' => '2355', + 'llagujarati' => '2739', + 'llinebelow' => '7739', + 'llladeva' => '2356', + 'llvocalicbengali' => '2529', + 'llvocalicdeva' => '2401', + 'llvocalicvowelsignbengali' => '2531', + 'llvocalicvowelsigndeva' => '2403', + 'lmiddletilde' => '619', + 'lmidot' => '320', + 'lmonospace' => '65356', + 'lmsquare' => '13264', + 'lnsim' => '8934', + 'lochulathai' => '3628', + 'logicaland' => '8743', + 'logicalnot' => '172', + 'logicalnotreversed' => '8976', + 'logicalor' => '8744', + 'lolingthai' => '3621', + 'longs' => '383', + 'lowast' => '8727', + 'lowbar' => '95', + 'lowlinecenterline' => '65102', + 'lowlinecmb' => '818', + 'lowlinedashed' => '65101', + 'loz' => '9674', + 'lozenge' => '9674', + 'lozenge4' => '61555', + 'lozenge6' => '61556', + 'lozf' => '10022', + 'lpar' => '40', + 'lparen' => '9383', + 'lrarr2' => '8646', + 'lrhar2' => '8651', + 'lsaquo' => '8249', + 'lsh' => '8624', + 'lsim' => '8818', + 'lslash' => '322', + 'lsqb' => '91', + 'lsquare' => '8467', + 'lsquo' => '8216', + 'lsquor' => '8218', + 'lstrok' => '322', + 'lsuperior' => '63214', + 'lt' => '60', + 'lthree' => '8907', + 'ltimes' => '8905', + 'ltri' => '9667', + 'ltrie' => '8884', + 'ltrif' => '9666', + 'ltshade' => '9617', + 'luthai' => '3622', + 'lvnE' => '8808', + 'lvocalicbengali' => '2444', + 'lvocalicdeva' => '2316', + 'lvocalicvowelsignbengali' => '2530', + 'lvocalicvowelsigndeva' => '2402', + 'lxsquare' => '13267', + 'm' => '109', + 'mabengali' => '2478', + 'macr' => '175', + 'macron' => '175', + 'macronbelowcmb' => '817', + 'macroncmb' => '772', + 'macronlowmod' => '717', + 'macronmonospace' => '65507', + 'macute' => '7743', + 'madeva' => '2350', + 'magujarati' => '2734', + 'magurmukhi' => '2606', + 'mahapakhhebrew' => '1444', + 'mahapakhlefthebrew' => '1444', + 'mahiragana' => '12414', + 'maichattawalowleftthai' => '63637', + 'maichattawalowrightthai' => '63636', + 'maichattawathai' => '3659', + 'maichattawaupperleftthai' => '63635', + 'maieklowleftthai' => '63628', + 'maieklowrightthai' => '63627', + 'maiekthai' => '3656', + 'maiekupperleftthai' => '63626', + 'maihanakatleftthai' => '63620', + 'maihanakatthai' => '3633', + 'mailboxflagdwn' => '61484', + 'mailboxflagup' => '61485', + 'mailbxopnflgdwn' => '61487', + 'mailbxopnflgup' => '61486', + 'maitaikhuleftthai' => '63625', + 'maitaikhuthai' => '3655', + 'maitholowleftthai' => '63631', + 'maitholowrightthai' => '63630', + 'maithothai' => '3657', + 'maithoupperleftthai' => '63629', + 'maitrilowleftthai' => '63634', + 'maitrilowrightthai' => '63633', + 'maitrithai' => '3658', + 'maitriupperleftthai' => '63632', + 'maiyamokthai' => '3654', + 'makatakana' => '12510', + 'makatakanahalfwidth' => '65423', + 'male' => '9794', + 'malt' => '10016', + 'mansyonsquare' => '13127', + 'map' => '8614', + 'maqafhebrew' => '1470', + 'marker' => '9646', + 'mars' => '9794', + 'masoracirclehebrew' => '1455', + 'masquare' => '13187', + 'mbopomofo' => '12551', + 'mbsquare' => '13268', + 'mcircle' => '9436', + 'mcubedsquare' => '13221', + 'mcy' => '1084', + 'mdash' => '8212', + 'mdotaccent' => '7745', + 'mdotbelow' => '7747', + 'meemarabic' => '1605', + 'meemfinalarabic' => '65250', + 'meeminitialarabic' => '65251', + 'meemmedialarabic' => '65252', + 'meemmeeminitialarabic' => '64721', + 'meemmeemisolatedarabic' => '64584', + 'meetorusquare' => '13133', + 'mehiragana' => '12417', + 'meizierasquare' => '13182', + 'mekatakana' => '12513', + 'mekatakanahalfwidth' => '65426', + 'mem' => '1502', + 'memdagesh' => '64318', + 'memdageshhebrew' => '64318', + 'memhebrew' => '1502', + 'menarmenian' => '1396', + 'merkhahebrew' => '1445', + 'merkhakefulahebrew' => '1446', + 'merkhakefulalefthebrew' => '1446', + 'merkhalefthebrew' => '1445', + 'mgr' => '956', + 'mhook' => '625', + 'mhzsquare' => '13202', + 'micro' => '181', + 'mid' => '8739', + 'middledotkatakanahalfwidth' => '65381', + 'middot' => '183', + 'mieumacirclekorean' => '12914', + 'mieumaparenkorean' => '12818', + 'mieumcirclekorean' => '12900', + 'mieumkorean' => '12609', + 'mieumpansioskorean' => '12656', + 'mieumparenkorean' => '12804', + 'mieumpieupkorean' => '12654', + 'mieumsioskorean' => '12655', + 'mihiragana' => '12415', + 'mikatakana' => '12511', + 'mikatakanahalfwidth' => '65424', + 'minus' => '8722', + 'minusb' => '8863', + 'minusbelowcmb' => '800', + 'minuscircle' => '8854', + 'minusmod' => '727', + 'minusplus' => '8723', + 'minute' => '8242', + 'miribaarusquare' => '13130', + 'mirisquare' => '13129', + 'mldr' => '8230', + 'mlonglegturned' => '624', + 'mlsquare' => '13206', + 'mmcubedsquare' => '13219', + 'mmonospace' => '65357', + 'mmsquaredsquare' => '13215', + 'mnplus' => '8723', + 'models' => '8871', + 'mohiragana' => '12418', + 'mohmsquare' => '13249', + 'mokatakana' => '12514', + 'mokatakanahalfwidth' => '65427', + 'molsquare' => '13270', + 'momathai' => '3617', + 'mouse2button' => '61496', + 'moverssquare' => '13223', + 'moverssquaredsquare' => '13224', + 'mparen' => '9384', + 'mpasquare' => '13227', + 'mssquare' => '13235', + 'msuperior' => '63215', + 'mturned' => '623', + 'mu' => '181', + 'mu1' => '181', + 'muasquare' => '13186', + 'muchgreater' => '8811', + 'muchless' => '8810', + 'mufsquare' => '13196', + 'mugreek' => '956', + 'mugsquare' => '13197', + 'muhiragana' => '12416', + 'mukatakana' => '12512', + 'mukatakanahalfwidth' => '65425', + 'mulsquare' => '13205', + 'multiply' => '215', + 'mumap' => '8888', + 'mumsquare' => '13211', + 'munahhebrew' => '1443', + 'munahlefthebrew' => '1443', + 'musicalnote' => '9834', + 'musicalnotedbl' => '9835', + 'musicflatsign' => '9837', + 'musicsharpsign' => '9839', + 'mussquare' => '13234', + 'muvsquare' => '13238', + 'muwsquare' => '13244', + 'mvmegasquare' => '13241', + 'mvsquare' => '13239', + 'mwmegasquare' => '13247', + 'mwsquare' => '13245', + 'n' => '110', + 'nVDash' => '8879', + 'nVdash' => '8878', + 'nabengali' => '2472', + 'nabla' => '8711', + 'nacute' => '324', + 'nadeva' => '2344', + 'nagujarati' => '2728', + 'nagurmukhi' => '2600', + 'nahiragana' => '12394', + 'nakatakana' => '12490', + 'nakatakanahalfwidth' => '65413', + 'nap' => '8777', + 'napos' => '329', + 'napostrophe' => '329', + 'nasquare' => '13185', + 'natur' => '9838', + 'nbopomofo' => '12555', + 'nbsp' => '160', + 'nbspace' => '160', + 'ncaron' => '328', + 'ncedil' => '326', + 'ncedilla' => '326', + 'ncircle' => '9437', + 'ncircumflexbelow' => '7755', + 'ncommaaccent' => '326', + 'ncong' => '8775', + 'ncy' => '1085', + 'ndash' => '8211', + 'ndotaccent' => '7749', + 'ndotbelow' => '7751', + 'ne' => '8800', + 'nearr' => '8599', + 'nehiragana' => '12397', + 'nekatakana' => '12493', + 'nekatakanahalfwidth' => '65416', + 'nequiv' => '8802', + 'neutralface' => '61515', + 'newsheqelsign' => '8362', + 'nexist' => '8708', + 'nfsquare' => '13195', + 'ngabengali' => '2457', + 'ngadeva' => '2329', + 'ngagujarati' => '2713', + 'ngagurmukhi' => '2585', + 'nges' => '8817', + 'ngonguthai' => '3591', + 'ngr' => '957', + 'ngt' => '8815', + 'nhArr' => '8654', + 'nharr' => '8622', + 'nhiragana' => '12435', + 'nhookleft' => '626', + 'nhookretroflex' => '627', + 'ni' => '8715', + 'nieunacirclekorean' => '12911', + 'nieunaparenkorean' => '12815', + 'nieuncieuckorean' => '12597', + 'nieuncirclekorean' => '12897', + 'nieunhieuhkorean' => '12598', + 'nieunkorean' => '12596', + 'nieunpansioskorean' => '12648', + 'nieunparenkorean' => '12801', + 'nieunsioskorean' => '12647', + 'nieuntikeutkorean' => '12646', + 'nihiragana' => '12395', + 'nikatakana' => '12491', + 'nikatakanahalfwidth' => '65414', + 'nikhahitleftthai' => '63641', + 'nikhahitthai' => '3661', + 'nine' => '57', + 'ninearabic' => '1641', + 'ninebengali' => '2543', + 'ninecircle' => '9320', + 'ninecircleinversesansserif' => '10130', + 'ninedeva' => '2415', + 'ninegujarati' => '2799', + 'ninegurmukhi' => '2671', + 'ninehackarabic' => '1641', + 'ninehangzhou' => '12329', + 'nineideographicparen' => '12840', + 'nineinferior' => '8329', + 'ninemonospace' => '65305', + 'nineoclock' => '61631', + 'nineoldstyle' => '63289', + 'nineparen' => '9340', + 'nineperiod' => '9360', + 'ninepersian' => '1785', + 'nineroman' => '8568', + 'ninesans' => '61577', + 'ninesansinv' => '61588', + 'ninesuperior' => '8313', + 'nineteencircle' => '9330', + 'nineteenparen' => '9350', + 'nineteenperiod' => '9370', + 'ninethai' => '3673', + 'nj' => '460', + 'njcy' => '1114', + 'njecyrillic' => '1114', + 'nkatakana' => '12531', + 'nkatakanahalfwidth' => '65437', + 'nlArr' => '8653', + 'nlarr' => '8602', + 'nldr' => '8229', + 'nlegrightlong' => '414', + 'nles' => '8816', + 'nlinebelow' => '7753', + 'nlt' => '8814', + 'nltri' => '8938', + 'nltrie' => '8940', + 'nmid' => '8740', + 'nmonospace' => '65358', + 'nmsquare' => '13210', + 'nnabengali' => '2467', + 'nnadeva' => '2339', + 'nnagujarati' => '2723', + 'nnagurmukhi' => '2595', + 'nnnadeva' => '2345', + 'nohiragana' => '12398', + 'nokatakana' => '12494', + 'nokatakanahalfwidth' => '65417', + 'nonbreakingspace' => '160', + 'nonenthai' => '3603', + 'nonuthai' => '3609', + 'noonarabic' => '1606', + 'noonfinalarabic' => '65254', + 'noonghunnaarabic' => '1722', + 'noonghunnafinalarabic' => '64415', + 'noonhehinitialarabic' => '65255', + 'nooninitialarabic' => '65255', + 'noonjeeminitialarabic' => '64722', + 'noonjeemisolatedarabic' => '64587', + 'noonmedialarabic' => '65256', + 'noonmeeminitialarabic' => '64725', + 'noonmeemisolatedarabic' => '64590', + 'noonnoonfinalarabic' => '64653', + 'not' => '172', + 'notcontains' => '8716', + 'notelement' => '8713', + 'notelementof' => '8713', + 'notequal' => '8800', + 'notgreater' => '8815', + 'notgreaternorequal' => '8817', + 'notgreaternorless' => '8825', + 'notidentical' => '8802', + 'notin' => '8713', + 'notless' => '8814', + 'notlessnorequal' => '8816', + 'notparallel' => '8742', + 'notprecedes' => '8832', + 'notsubset' => '8836', + 'notsucceeds' => '8833', + 'notsuperset' => '8837', + 'nowarmenian' => '1398', + 'npar' => '8742', + 'nparen' => '9385', + 'npr' => '8832', + 'npre' => '8928', + 'nrArr' => '8655', + 'nrarr' => '8603', + 'nrtri' => '8939', + 'nrtrie' => '8941', + 'nsc' => '8833', + 'nsce' => '8929', + 'nsim' => '8769', + 'nsime' => '8772', + 'nssquare' => '13233', + 'nsub' => '8836', + 'nsube' => '8840', + 'nsup' => '8837', + 'nsupe' => '8841', + 'nsuperior' => '8319', + 'ntilde' => '241', + 'nu' => '957', + 'nuhiragana' => '12396', + 'nukatakana' => '12492', + 'nukatakanahalfwidth' => '65415', + 'nuktabengali' => '2492', + 'nuktadeva' => '2364', + 'nuktagujarati' => '2748', + 'nuktagurmukhi' => '2620', + 'num' => '35', + 'numbersign' => '35', + 'numbersignmonospace' => '65283', + 'numbersignsmall' => '65119', + 'numeralsigngreek' => '884', + 'numeralsignlowergreek' => '885', + 'numero' => '8470', + 'numsp' => '8199', + 'nun' => '1504', + 'nundagesh' => '64320', + 'nundageshhebrew' => '64320', + 'nunhebrew' => '1504', + 'nvDash' => '8877', + 'nvdash' => '8876', + 'nvsquare' => '13237', + 'nwarr' => '8598', + 'nwsquare' => '13243', + 'nyabengali' => '2462', + 'nyadeva' => '2334', + 'nyagujarati' => '2718', + 'nyagurmukhi' => '2590', + 'o' => '111', + 'oS' => '9416', + 'oacgr' => '972', + 'oacute' => '243', + 'oangthai' => '3629', + 'oast' => '8859', + 'obarred' => '629', + 'obarredcyrillic' => '1257', + 'obarreddieresiscyrillic' => '1259', + 'obengali' => '2451', + 'obopomofo' => '12571', + 'obreve' => '335', + 'ocandradeva' => '2321', + 'ocandragujarati' => '2705', + 'ocandravowelsigndeva' => '2377', + 'ocandravowelsigngujarati' => '2761', + 'ocaron' => '466', + 'ocir' => '8858', + 'ocirc' => '244', + 'ocircle' => '9438', + 'ocircumflex' => '244', + 'ocircumflexacute' => '7889', + 'ocircumflexdotbelow' => '7897', + 'ocircumflexgrave' => '7891', + 'ocircumflexhookabove' => '7893', + 'ocircumflextilde' => '7895', + 'octastar2' => '61613', + 'octastar4' => '61615', + 'ocy' => '1086', + 'ocyrillic' => '1086', + 'odash' => '8861', + 'odblac' => '337', + 'odblacute' => '337', + 'odblgrave' => '525', + 'odeva' => '2323', + 'odieresis' => '246', + 'odieresiscyrillic' => '1255', + 'odot' => '8857', + 'odotbelow' => '7885', + 'oe' => '339', + 'oekorean' => '12634', + 'oelig' => '339', + 'ogon' => '731', + 'ogonek' => '731', + 'ogonekcmb' => '808', + 'ogr' => '959', + 'ograve' => '242', + 'ogujarati' => '2707', + 'ohacgr' => '974', + 'oharmenian' => '1413', + 'ohgr' => '969', + 'ohiragana' => '12362', + 'ohm' => '8486', + 'ohookabove' => '7887', + 'ohorn' => '417', + 'ohornacute' => '7899', + 'ohorndotbelow' => '7907', + 'ohorngrave' => '7901', + 'ohornhookabove' => '7903', + 'ohorntilde' => '7905', + 'ohungarumlaut' => '337', + 'oi' => '419', + 'oinvertedbreve' => '527', + 'okatakana' => '12458', + 'okatakanahalfwidth' => '65397', + 'okorean' => '12631', + 'olarr' => '8634', + 'olehebrew' => '1451', + 'oline' => '8254', + 'om' => '61532', + 'omacr' => '333', + 'omacron' => '333', + 'omacronacute' => '7763', + 'omacrongrave' => '7761', + 'omdeva' => '2384', + 'omega' => '969', + 'omega1' => '982', + 'omegacyrillic' => '1121', + 'omegalatinclosed' => '631', + 'omegaroundcyrillic' => '1147', + 'omegatitlocyrillic' => '1149', + 'omegatonos' => '974', + 'omgujarati' => '2768', + 'omicron' => '959', + 'omicrontonos' => '972', + 'ominus' => '8854', + 'omonospace' => '65359', + 'one' => '49', + 'onearabic' => '1633', + 'onebengali' => '2535', + 'onecircle' => '9312', + 'onecircleinversesansserif' => '10122', + 'onedeva' => '2407', + 'onedotenleader' => '8228', + 'oneeighth' => '8539', + 'onefitted' => '63196', + 'onegujarati' => '2791', + 'onegurmukhi' => '2663', + 'onehackarabic' => '1633', + 'onehalf' => '189', + 'onehangzhou' => '12321', + 'oneideographicparen' => '12832', + 'oneinferior' => '8321', + 'onemonospace' => '65297', + 'onenumeratorbengali' => '2548', + 'oneoclock' => '61623', + 'oneoldstyle' => '63281', + 'oneparen' => '9332', + 'oneperiod' => '9352', + 'onepersian' => '1777', + 'onequarter' => '188', + 'oneroman' => '8560', + 'onesans' => '61569', + 'onesansinv' => '61580', + 'onesuperior' => '185', + 'onethai' => '3665', + 'onethird' => '8531', + 'oogonek' => '491', + 'oogonekmacron' => '493', + 'oogurmukhi' => '2579', + 'oomatragurmukhi' => '2635', + 'oopen' => '596', + 'oparen' => '9386', + 'openbullet' => '9702', + 'oplus' => '8853', + 'option' => '8997', + 'or' => '8744', + 'orarr' => '8635', + 'order' => '8500', + 'ordf' => '170', + 'ordfeminine' => '170', + 'ordm' => '186', + 'ordmasculine' => '186', + 'orthogonal' => '8735', + 'oshortdeva' => '2322', + 'oshortvowelsigndeva' => '2378', + 'oslash' => '248', + 'oslashacute' => '511', + 'osmallhiragana' => '12361', + 'osmallkatakana' => '12457', + 'osmallkatakanahalfwidth' => '65387', + 'osol' => '8856', + 'ostrokeacute' => '511', + 'osuperior' => '63216', + 'otcyrillic' => '1151', + 'otilde' => '245', + 'otildeacute' => '7757', + 'otildedieresis' => '7759', + 'otimes' => '8855', + 'oubopomofo' => '12577', + 'ouml' => '246', + 'overline' => '8254', + 'overlinecenterline' => '65098', + 'overlinecmb' => '773', + 'overlinedashed' => '65097', + 'overlinedblwavy' => '65100', + 'overlinewavy' => '65099', + 'overscore' => '175', + 'ovowelsignbengali' => '2507', + 'ovowelsigndeva' => '2379', + 'ovowelsigngujarati' => '2763', + 'p' => '112', + 'paampssquare' => '13184', + 'paasentosquare' => '13099', + 'pabengali' => '2474', + 'pacute' => '7765', + 'padeva' => '2346', + 'pagedown' => '8671', + 'pageup' => '8670', + 'pagujarati' => '2730', + 'pagurmukhi' => '2602', + 'pahiragana' => '12401', + 'paiyannoithai' => '3631', + 'pakatakana' => '12497', + 'palatalizationcyrilliccmb' => '1156', + 'palochkacyrillic' => '1216', + 'pansioskorean' => '12671', + 'par' => '8741', + 'para' => '182', + 'paragraph' => '182', + 'parallel' => '8741', + 'parenleft' => '40', + 'parenleftaltonearabic' => '64830', + 'parenleftbt' => '63725', + 'parenleftex' => '63724', + 'parenleftinferior' => '8333', + 'parenleftmonospace' => '65288', + 'parenleftsmall' => '65113', + 'parenleftsuperior' => '8317', + 'parenlefttp' => '63723', + 'parenleftvertical' => '65077', + 'parenright' => '41', + 'parenrightaltonearabic' => '64831', + 'parenrightbt' => '63736', + 'parenrightex' => '63735', + 'parenrightinferior' => '8334', + 'parenrightmonospace' => '65289', + 'parenrightsmall' => '65114', + 'parenrightsuperior' => '8318', + 'parenrighttp' => '63734', + 'parenrightvertical' => '65078', + 'part' => '8706', + 'partialdiff' => '8706', + 'paseqhebrew' => '1472', + 'pashtahebrew' => '1433', + 'pasquare' => '13225', + 'patah' => '1463', + 'patah11' => '1463', + 'patah1d' => '1463', + 'patah2a' => '1463', + 'patahhebrew' => '1463', + 'patahnarrowhebrew' => '1463', + 'patahquarterhebrew' => '1463', + 'patahwidehebrew' => '1463', + 'pazerhebrew' => '1441', + 'pbopomofo' => '12550', + 'pc' => '61498', + 'pcircle' => '9439', + 'pcy' => '1087', + 'pdotaccent' => '7767', + 'pe' => '1508', + 'pecyrillic' => '1087', + 'pedagesh' => '64324', + 'pedageshhebrew' => '64324', + 'peezisquare' => '13115', + 'pefinaldageshhebrew' => '64323', + 'peharabic' => '1662', + 'peharmenian' => '1402', + 'pehebrew' => '1508', + 'pehfinalarabic' => '64343', + 'pehinitialarabic' => '64344', + 'pehiragana' => '12410', + 'pehmedialarabic' => '64345', + 'pekatakana' => '12506', + 'pemiddlehookcyrillic' => '1191', + 'pencil' => '61473', + 'pennant' => '61520', + 'pentastar2' => '61611', + 'perafehebrew' => '64334', + 'percent' => '37', + 'percentarabic' => '1642', + 'percentmonospace' => '65285', + 'percentsmall' => '65130', + 'percnt' => '37', + 'period' => '46', + 'periodarmenian' => '1417', + 'periodcentered' => '183', + 'periodhalfwidth' => '65377', + 'periodinferior' => '63207', + 'periodmonospace' => '65294', + 'periodsmall' => '65106', + 'periodsuperior' => '63208', + 'perispomenigreekcmb' => '834', + 'permil' => '8240', + 'perp' => '8869', + 'perpendicular' => '8869', + 'perthousand' => '8240', + 'peseta' => '8359', + 'pfsquare' => '13194', + 'pgr' => '960', + 'phabengali' => '2475', + 'phadeva' => '2347', + 'phagujarati' => '2731', + 'phagurmukhi' => '2603', + 'phi' => '966', + 'phi1' => '981', + 'phieuphacirclekorean' => '12922', + 'phieuphaparenkorean' => '12826', + 'phieuphcirclekorean' => '12908', + 'phieuphkorean' => '12621', + 'phieuphparenkorean' => '12812', + 'philatin' => '632', + 'phinthuthai' => '3642', + 'phis' => '966', + 'phisymbolgreek' => '981', + 'phiv' => '981', + 'phmmat' => '8499', + 'phone' => '9742', + 'phook' => '421', + 'phophanthai' => '3614', + 'phophungthai' => '3612', + 'phosamphaothai' => '3616', + 'pi' => '960', + 'pieupacirclekorean' => '12915', + 'pieupaparenkorean' => '12819', + 'pieupcieuckorean' => '12662', + 'pieupcirclekorean' => '12901', + 'pieupkiyeokkorean' => '12658', + 'pieupkorean' => '12610', + 'pieupparenkorean' => '12805', + 'pieupsioskiyeokkorean' => '12660', + 'pieupsioskorean' => '12612', + 'pieupsiostikeutkorean' => '12661', + 'pieupthieuthkorean' => '12663', + 'pieuptikeutkorean' => '12659', + 'pihiragana' => '12404', + 'pikatakana' => '12500', + 'pisces' => '61545', + 'pisymbolgreek' => '982', + 'piv' => '982', + 'piwrarmenian' => '1411', + 'planck' => '8463', + 'plus' => '43', + 'plusb' => '8862', + 'plusbelowcmb' => '799', + 'pluscircle' => '8853', + 'plusdo' => '8724', + 'plusminus' => '177', + 'plusmn' => '177', + 'plusmod' => '726', + 'plusmonospace' => '65291', + 'plussmall' => '65122', + 'plussuperior' => '8314', + 'pmonospace' => '65360', + 'pmsquare' => '13272', + 'pohiragana' => '12413', + 'pointingindexdownwhite' => '9759', + 'pointingindexleftwhite' => '9756', + 'pointingindexrightwhite' => '9758', + 'pointingindexupwhite' => '9757', + 'pokatakana' => '12509', + 'poplathai' => '3611', + 'postalmark' => '12306', + 'postalmarkface' => '12320', + 'pound' => '163', + 'pparen' => '9387', + 'pr' => '8826', + 'precedes' => '8826', + 'prescription' => '8478', + 'prime' => '8242', + 'primemod' => '697', + 'primereversed' => '8245', + 'prnsim' => '8936', + 'prod' => '8719', + 'product' => '8719', + 'projective' => '8965', + 'prolongedkana' => '12540', + 'prop' => '8733', + 'propellor' => '8984', + 'propersubset' => '8834', + 'propersuperset' => '8835', + 'proportion' => '8759', + 'proportional' => '8733', + 'prsim' => '8830', + 'psgr' => '968', + 'psi' => '968', + 'psicyrillic' => '1137', + 'psilipneumatacyrilliccmb' => '1158', + 'pssquare' => '13232', + 'puhiragana' => '12407', + 'pukatakana' => '12503', + 'puncsp' => '8200', + 'pvsquare' => '13236', + 'pwsquare' => '13242', + 'q' => '113', + 'qadeva' => '2392', + 'qadmahebrew' => '1448', + 'qafarabic' => '1602', + 'qaffinalarabic' => '65238', + 'qafinitialarabic' => '65239', + 'qafmedialarabic' => '65240', + 'qamats' => '1464', + 'qamats10' => '1464', + 'qamats1a' => '1464', + 'qamats1c' => '1464', + 'qamats27' => '1464', + 'qamats29' => '1464', + 'qamats33' => '1464', + 'qamatsde' => '1464', + 'qamatshebrew' => '1464', + 'qamatsnarrowhebrew' => '1464', + 'qamatsqatanhebrew' => '1464', + 'qamatsqatannarrowhebrew' => '1464', + 'qamatsqatanquarterhebrew' => '1464', + 'qamatsqatanwidehebrew' => '1464', + 'qamatsquarterhebrew' => '1464', + 'qamatswidehebrew' => '1464', + 'qarneyparahebrew' => '1439', + 'qbopomofo' => '12561', + 'qcircle' => '9440', + 'qhook' => '672', + 'qmonospace' => '65361', + 'qof' => '1511', + 'qofdagesh' => '64327', + 'qofdageshhebrew' => '64327', + 'qofhatafpatah' => '1511', + 'qofhatafpatahhebrew' => '1511', + 'qofhatafsegol' => '1511', + 'qofhatafsegolhebrew' => '1511', + 'qofhebrew' => '1511', + 'qofhiriq' => '1511', + 'qofhiriqhebrew' => '1511', + 'qofholam' => '1511', + 'qofholamhebrew' => '1511', + 'qofpatah' => '1511', + 'qofpatahhebrew' => '1511', + 'qofqamats' => '1511', + 'qofqamatshebrew' => '1511', + 'qofqubuts' => '1511', + 'qofqubutshebrew' => '1511', + 'qofsegol' => '1511', + 'qofsegolhebrew' => '1511', + 'qofsheva' => '1511', + 'qofshevahebrew' => '1511', + 'qoftsere' => '1511', + 'qoftserehebrew' => '1511', + 'qparen' => '9388', + 'quarternote' => '9833', + 'qubuts' => '1467', + 'qubuts18' => '1467', + 'qubuts25' => '1467', + 'qubuts31' => '1467', + 'qubutshebrew' => '1467', + 'qubutsnarrowhebrew' => '1467', + 'qubutsquarterhebrew' => '1467', + 'qubutswidehebrew' => '1467', + 'query' => '61620', + 'quest' => '63', + 'question' => '63', + 'questionarabic' => '1567', + 'questionarmenian' => '1374', + 'questiondown' => '191', + 'questiondownsmall' => '63423', + 'questiongreek' => '894', + 'questionmonospace' => '65311', + 'questionsmall' => '63295', + 'quiltsquare2' => '61643', + 'quiltsquare2inv' => '61644', + 'quot' => '34', + 'quotedbl' => '34', + 'quotedblbase' => '8222', + 'quotedblleft' => '8220', + 'quotedbllftbld' => '61565', + 'quotedblmonospace' => '65282', + 'quotedblprime' => '12318', + 'quotedblprimereversed' => '12317', + 'quotedblright' => '8221', + 'quotedblrtbld' => '61566', + 'quoteleft' => '8216', + 'quoteleftreversed' => '8219', + 'quotereversed' => '8219', + 'quoteright' => '8217', + 'quoterightn' => '329', + 'quotesinglbase' => '8218', + 'quotesingle' => '39', + 'quotesinglemonospace' => '65287', + 'r' => '114', + 'rAarr' => '8667', + 'rArr' => '8658', + 'raarmenian' => '1404', + 'rabengali' => '2480', + 'racute' => '341', + 'radeva' => '2352', + 'radic' => '8730', + 'radical' => '8730', + 'radicalex' => '63717', + 'radoverssquare' => '13230', + 'radoverssquaredsquare' => '13231', + 'radsquare' => '13229', + 'rafe' => '1471', + 'rafehebrew' => '1471', + 'ragujarati' => '2736', + 'ragurmukhi' => '2608', + 'rahiragana' => '12425', + 'rakatakana' => '12521', + 'rakatakanahalfwidth' => '65431', + 'ralowerdiagonalbengali' => '2545', + 'ramiddlediagonalbengali' => '2544', + 'ramshorn' => '612', + 'rang' => '9002', + 'raquo' => '187', + 'rarr' => '8594', + 'rarr2' => '8649', + 'rarrhk' => '8618', + 'rarrlp' => '8620', + 'rarrtl' => '8611', + 'rarrw' => '8605', + 'ratio' => '8758', + 'rbopomofo' => '12566', + 'rcaron' => '345', + 'rcedil' => '343', + 'rcedilla' => '343', + 'rceil' => '8969', + 'rcircle' => '9441', + 'rcommaaccent' => '343', + 'rcub' => '125', + 'rcy' => '1088', + 'rdblgrave' => '529', + 'rdotaccent' => '7769', + 'rdotbelow' => '7771', + 'rdotbelowmacron' => '7773', + 'rdquo' => '8221', + 'rdquor' => '8220', + 'readingglasses' => '61476', + 'real' => '8476', + 'rect' => '9645', + 'referencemark' => '8251', + 'reflexsubset' => '8838', + 'reflexsuperset' => '8839', + 'reg' => '174', + 'registercircle' => '61617', + 'registered' => '174', + 'registersans' => '63720', + 'registerserif' => '63194', + 'registersquare' => '61616', + 'reharabic' => '1585', + 'reharmenian' => '1408', + 'rehfinalarabic' => '65198', + 'rehiragana' => '12428', + 'rehyehaleflamarabic' => '1585', + 'rekatakana' => '12524', + 'rekatakanahalfwidth' => '65434', + 'resh' => '1512', + 'reshdageshhebrew' => '64328', + 'reshhatafpatah' => '1512', + 'reshhatafpatahhebrew' => '1512', + 'reshhatafsegol' => '1512', + 'reshhatafsegolhebrew' => '1512', + 'reshhebrew' => '1512', + 'reshhiriq' => '1512', + 'reshhiriqhebrew' => '1512', + 'reshholam' => '1512', + 'reshholamhebrew' => '1512', + 'reshpatah' => '1512', + 'reshpatahhebrew' => '1512', + 'reshqamats' => '1512', + 'reshqamatshebrew' => '1512', + 'reshqubuts' => '1512', + 'reshqubutshebrew' => '1512', + 'reshsegol' => '1512', + 'reshsegolhebrew' => '1512', + 'reshsheva' => '1512', + 'reshshevahebrew' => '1512', + 'reshtsere' => '1512', + 'reshtserehebrew' => '1512', + 'reversedtilde' => '8765', + 'reviahebrew' => '1431', + 'reviamugrashhebrew' => '1431', + 'revlogicalnot' => '8976', + 'rfishhook' => '638', + 'rfishhookreversed' => '639', + 'rfloor' => '8971', + 'rgr' => '961', + 'rhabengali' => '2525', + 'rhadeva' => '2397', + 'rhard' => '8641', + 'rharu' => '8640', + 'rho' => '961', + 'rhombus4' => '61559', + 'rhombus6' => '61557', + 'rhook' => '637', + 'rhookturned' => '635', + 'rhookturnedsuperior' => '693', + 'rhosymbolgreek' => '1009', + 'rhotichookmod' => '734', + 'rhov' => '1009', + 'rieulacirclekorean' => '12913', + 'rieulaparenkorean' => '12817', + 'rieulcirclekorean' => '12899', + 'rieulhieuhkorean' => '12608', + 'rieulkiyeokkorean' => '12602', + 'rieulkiyeoksioskorean' => '12649', + 'rieulkorean' => '12601', + 'rieulmieumkorean' => '12603', + 'rieulpansioskorean' => '12652', + 'rieulparenkorean' => '12803', + 'rieulphieuphkorean' => '12607', + 'rieulpieupkorean' => '12604', + 'rieulpieupsioskorean' => '12651', + 'rieulsioskorean' => '12605', + 'rieulthieuthkorean' => '12606', + 'rieultikeutkorean' => '12650', + 'rieulyeorinhieuhkorean' => '12653', + 'rightangle' => '8735', + 'righttackbelowcmb' => '793', + 'righttriangle' => '8895', + 'rihiragana' => '12426', + 'rikatakana' => '12522', + 'rikatakanahalfwidth' => '65432', + 'ring' => '730', + 'ring2' => '61601', + 'ring4' => '61602', + 'ring6' => '61603', + 'ringbelowcmb' => '805', + 'ringbutton2' => '61604', + 'ringcmb' => '778', + 'ringhalfleft' => '703', + 'ringhalfleftarmenian' => '1369', + 'ringhalfleftbelowcmb' => '796', + 'ringhalfleftcentered' => '723', + 'ringhalfright' => '702', + 'ringhalfrightbelowcmb' => '825', + 'ringhalfrightcentered' => '722', + 'rinvertedbreve' => '531', + 'rittorusquare' => '13137', + 'rlarr2' => '8644', + 'rlhar2' => '8652', + 'rlinebelow' => '7775', + 'rlongleg' => '636', + 'rlonglegturned' => '634', + 'rmonospace' => '65362', + 'rohiragana' => '12429', + 'rokatakana' => '12525', + 'rokatakanahalfwidth' => '65435', + 'roruathai' => '3619', + 'rosette' => '61563', + 'rosettesolid' => '61564', + 'rpar' => '41', + 'rparen' => '9389', + 'rrabengali' => '2524', + 'rradeva' => '2353', + 'rragurmukhi' => '2652', + 'rreharabic' => '1681', + 'rrehfinalarabic' => '64397', + 'rrvocalicbengali' => '2528', + 'rrvocalicdeva' => '2400', + 'rrvocalicgujarati' => '2784', + 'rrvocalicvowelsignbengali' => '2500', + 'rrvocalicvowelsigndeva' => '2372', + 'rrvocalicvowelsigngujarati' => '2756', + 'rsaquo' => '8250', + 'rsh' => '8625', + 'rsqb' => '93', + 'rsquo' => '8217', + 'rsquor' => '8216', + 'rsuperior' => '63217', + 'rtblock' => '9616', + 'rthree' => '8908', + 'rtimes' => '8906', + 'rtri' => '9657', + 'rtrie' => '8885', + 'rtrif' => '9656', + 'rturned' => '633', + 'rturnedsuperior' => '692', + 'ruhiragana' => '12427', + 'rukatakana' => '12523', + 'rukatakanahalfwidth' => '65433', + 'rupeemarkbengali' => '2546', + 'rupeesignbengali' => '2547', + 'rupiah' => '63197', + 'ruthai' => '3620', + 'rvocalicbengali' => '2443', + 'rvocalicdeva' => '2315', + 'rvocalicgujarati' => '2699', + 'rvocalicvowelsignbengali' => '2499', + 'rvocalicvowelsigndeva' => '2371', + 'rvocalicvowelsigngujarati' => '2755', + 'rx' => '8478', + 's' => '115', + 'sabengali' => '2488', + 'sacute' => '347', + 'sacutedotaccent' => '7781', + 'sadarabic' => '1589', + 'sadeva' => '2360', + 'sadfinalarabic' => '65210', + 'sadinitialarabic' => '65211', + 'sadmedialarabic' => '65212', + 'saggitarius' => '61542', + 'sagujarati' => '2744', + 'sagurmukhi' => '2616', + 'sahiragana' => '12373', + 'sakatakana' => '12469', + 'sakatakanahalfwidth' => '65403', + 'sallallahoualayhewasallamarabic' => '65018', + 'samalg' => '8720', + 'samekh' => '1505', + 'samekhdagesh' => '64321', + 'samekhdageshhebrew' => '64321', + 'samekhhebrew' => '1505', + 'saraaathai' => '3634', + 'saraaethai' => '3649', + 'saraaimaimalaithai' => '3652', + 'saraaimaimuanthai' => '3651', + 'saraamthai' => '3635', + 'saraathai' => '3632', + 'saraethai' => '3648', + 'saraiileftthai' => '63622', + 'saraiithai' => '3637', + 'saraileftthai' => '63621', + 'saraithai' => '3636', + 'saraothai' => '3650', + 'saraueeleftthai' => '63624', + 'saraueethai' => '3639', + 'saraueleftthai' => '63623', + 'sarauethai' => '3638', + 'sarauthai' => '3640', + 'sarauuthai' => '3641', + 'sbopomofo' => '12569', + 'sbquo' => '8218', + 'sc' => '8827', + 'scaron' => '353', + 'scarondotaccent' => '7783', + 'sccue' => '8829', + 'scedil' => '351', + 'scedilla' => '351', + 'schwa' => '601', + 'schwacyrillic' => '1241', + 'schwadieresiscyrillic' => '1243', + 'schwahook' => '602', + 'scirc' => '349', + 'scircle' => '9442', + 'scircumflex' => '349', + 'scissors' => '61474', + 'scissorscutting' => '61475', + 'scnsim' => '8937', + 'scommaaccent' => '537', + 'scorpio' => '61541', + 'scsim' => '8831', + 'scy' => '1089', + 'sdot' => '8901', + 'sdotaccent' => '7777', + 'sdotb' => '8865', + 'sdotbelow' => '7779', + 'sdotbelowdotaccent' => '7785', + 'seagullbelowcmb' => '828', + 'second' => '8243', + 'secondtonechinese' => '714', + 'sect' => '167', + 'section' => '167', + 'seenarabic' => '1587', + 'seenfinalarabic' => '65202', + 'seeninitialarabic' => '65203', + 'seenmedialarabic' => '65204', + 'segol' => '1462', + 'segol13' => '1462', + 'segol1f' => '1462', + 'segol2c' => '1462', + 'segolhebrew' => '1462', + 'segolnarrowhebrew' => '1462', + 'segolquarterhebrew' => '1462', + 'segoltahebrew' => '1426', + 'segolwidehebrew' => '1462', + 'seharmenian' => '1405', + 'sehiragana' => '12379', + 'sekatakana' => '12475', + 'sekatakanahalfwidth' => '65406', + 'semi' => '59', + 'semicolon' => '59', + 'semicolonarabic' => '1563', + 'semicolonmonospace' => '65307', + 'semicolonsmall' => '65108', + 'semivoicedmarkkana' => '12444', + 'semivoicedmarkkanahalfwidth' => '65439', + 'sentisquare' => '13090', + 'sentosquare' => '13091', + 'setmn' => '8726', + 'seven' => '55', + 'sevenarabic' => '1639', + 'sevenbengali' => '2541', + 'sevencircle' => '9318', + 'sevencircleinversesansserif' => '10128', + 'sevendeva' => '2413', + 'seveneighths' => '8542', + 'sevengujarati' => '2797', + 'sevengurmukhi' => '2669', + 'sevenhackarabic' => '1639', + 'sevenhangzhou' => '12327', + 'sevenideographicparen' => '12838', + 'seveninferior' => '8327', + 'sevenmonospace' => '65303', + 'sevenoclock' => '61629', + 'sevenoldstyle' => '63287', + 'sevenparen' => '9338', + 'sevenperiod' => '9358', + 'sevenpersian' => '1783', + 'sevenroman' => '8566', + 'sevensans' => '61575', + 'sevensansinv' => '61586', + 'sevensuperior' => '8311', + 'seventeencircle' => '9328', + 'seventeenparen' => '9348', + 'seventeenperiod' => '9368', + 'seventhai' => '3671', + 'sextile' => '10038', + 'sfthyphen' => '173', + 'sgr' => '963', + 'shaarmenian' => '1399', + 'shabengali' => '2486', + 'shacyrillic' => '1096', + 'shaddaarabic' => '1617', + 'shaddadammaarabic' => '64609', + 'shaddadammatanarabic' => '64606', + 'shaddafathaarabic' => '64608', + 'shaddafathatanarabic' => '1617', + 'shaddakasraarabic' => '64610', + 'shaddakasratanarabic' => '64607', + 'shade' => '9618', + 'shadedark' => '9619', + 'shadelight' => '9617', + 'shademedium' => '9618', + 'shadeva' => '2358', + 'shagujarati' => '2742', + 'shagurmukhi' => '2614', + 'shalshelethebrew' => '1427', + 'sharp' => '9839', + 'shbopomofo' => '12565', + 'shchacyrillic' => '1097', + 'shchcy' => '1097', + 'shcy' => '1096', + 'sheenarabic' => '1588', + 'sheenfinalarabic' => '65206', + 'sheeninitialarabic' => '65207', + 'sheenmedialarabic' => '65208', + 'sheicoptic' => '995', + 'sheqel' => '8362', + 'sheqelhebrew' => '8362', + 'sheva' => '1456', + 'sheva115' => '1456', + 'sheva15' => '1456', + 'sheva22' => '1456', + 'sheva2e' => '1456', + 'shevahebrew' => '1456', + 'shevanarrowhebrew' => '1456', + 'shevaquarterhebrew' => '1456', + 'shevawidehebrew' => '1456', + 'shhacyrillic' => '1211', + 'shimacoptic' => '1005', + 'shin' => '1513', + 'shindagesh' => '64329', + 'shindageshhebrew' => '64329', + 'shindageshshindot' => '64300', + 'shindageshshindothebrew' => '64300', + 'shindageshsindot' => '64301', + 'shindageshsindothebrew' => '64301', + 'shindothebrew' => '1473', + 'shinhebrew' => '1513', + 'shinshindot' => '64298', + 'shinshindothebrew' => '64298', + 'shinsindot' => '64299', + 'shinsindothebrew' => '64299', + 'shook' => '642', + 'shy' => '173', + 'sigma' => '963', + 'sigma1' => '962', + 'sigmafinal' => '962', + 'sigmalunatesymbolgreek' => '1010', + 'sigmav' => '962', + 'sihiragana' => '12375', + 'sikatakana' => '12471', + 'sikatakanahalfwidth' => '65404', + 'siluqhebrew' => '1469', + 'siluqlefthebrew' => '1469', + 'sim' => '8764', + 'sime' => '8771', + 'similar' => '8764', + 'sindothebrew' => '1474', + 'siosacirclekorean' => '12916', + 'siosaparenkorean' => '12820', + 'sioscieuckorean' => '12670', + 'sioscirclekorean' => '12902', + 'sioskiyeokkorean' => '12666', + 'sioskorean' => '12613', + 'siosnieunkorean' => '12667', + 'siosparenkorean' => '12806', + 'siospieupkorean' => '12669', + 'siostikeutkorean' => '12668', + 'six' => '54', + 'sixarabic' => '1638', + 'sixbengali' => '2540', + 'sixcircle' => '9317', + 'sixcircleinversesansserif' => '10127', + 'sixdeva' => '2412', + 'sixgujarati' => '2796', + 'sixgurmukhi' => '2668', + 'sixhackarabic' => '1638', + 'sixhangzhou' => '12326', + 'sixideographicparen' => '12837', + 'sixinferior' => '8326', + 'sixmonospace' => '65302', + 'sixoclock' => '61628', + 'sixoldstyle' => '63286', + 'sixparen' => '9337', + 'sixperiod' => '9357', + 'sixpersian' => '1782', + 'sixroman' => '8565', + 'sixsans' => '61574', + 'sixsansinv' => '61585', + 'sixsuperior' => '8310', + 'sixteencircle' => '9327', + 'sixteencurrencydenominatorbengali' => '2553', + 'sixteenparen' => '9347', + 'sixteenperiod' => '9367', + 'sixthai' => '3670', + 'skullcrossbones' => '61518', + 'slash' => '47', + 'slashmonospace' => '65295', + 'slong' => '383', + 'slongdotaccent' => '7835', + 'smile' => '8995', + 'smileface' => '9786', + 'smonospace' => '65363', + 'snowflake' => '61524', + 'sofpasuqhebrew' => '1475', + 'softcy' => '1100', + 'softhyphen' => '173', + 'softsigncyrillic' => '1100', + 'sohiragana' => '12381', + 'sokatakana' => '12477', + 'sokatakanahalfwidth' => '65407', + 'sol' => '47', + 'soliduslongoverlaycmb' => '824', + 'solidusshortoverlaycmb' => '823', + 'sorusithai' => '3625', + 'sosalathai' => '3624', + 'sosothai' => '3595', + 'sosuathai' => '3626', + 'space' => '32', + 'spacehackarabic' => '32', + 'spade' => '9824', + 'spades' => '9824', + 'spadesuitblack' => '9824', + 'spadesuitwhite' => '9828', + 'sparen' => '9390', + 'sqcap' => '8851', + 'sqcup' => '8852', + 'sqsub' => '8847', + 'sqsube' => '8849', + 'sqsup' => '8848', + 'sqsupe' => '8850', + 'square' => '9633', + 'square2' => '61600', + 'square4' => '61607', + 'square6' => '61550', + 'squarebelowcmb' => '827', + 'squarecc' => '13252', + 'squarecm' => '13213', + 'squarediagonalcrosshatchfill' => '9641', + 'squarehorizontalfill' => '9636', + 'squarekg' => '13199', + 'squarekm' => '13214', + 'squarekmcapital' => '13262', + 'squareln' => '13265', + 'squarelog' => '13266', + 'squaremg' => '13198', + 'squaremil' => '13269', + 'squaremm' => '13212', + 'squaremsquared' => '13217', + 'squareorthogonalcrosshatchfill' => '9638', + 'squareupperlefttolowerrightfill' => '9639', + 'squareupperrighttolowerleftfill' => '9640', + 'squareverticalfill' => '9637', + 'squarewhitewithsmallblack' => '9635', + 'squf' => '9642', + 'srsquare' => '13275', + 'ssabengali' => '2487', + 'ssadeva' => '2359', + 'ssagujarati' => '2743', + 'ssangcieuckorean' => '12617', + 'ssanghieuhkorean' => '12677', + 'ssangieungkorean' => '12672', + 'ssangkiyeokkorean' => '12594', + 'ssangnieunkorean' => '12645', + 'ssangpieupkorean' => '12611', + 'ssangsioskorean' => '12614', + 'ssangtikeutkorean' => '12600', + 'sstarf' => '8902', + 'ssuperior' => '63218', + 'star' => '9734', + 'starf' => '9733', + 'starofdavid' => '61529', + 'starshadow' => '61622', + 'sterling' => '163', + 'sterlingmonospace' => '65505', + 'strokelongoverlaycmb' => '822', + 'strokeshortoverlaycmb' => '821', + 'sub' => '8834', + 'sube' => '8838', + 'subnE' => '8842', + 'subset' => '8834', + 'subsetnotequal' => '8842', + 'subsetorequal' => '8838', + 'succeeds' => '8827', + 'suchthat' => '8715', + 'suhiragana' => '12377', + 'sukatakana' => '12473', + 'sukatakanahalfwidth' => '65405', + 'sukunarabic' => '1618', + 'sum' => '8721', + 'summation' => '8721', + 'sun' => '9788', + 'sung' => '9834', + 'sunshine' => '61522', + 'sup' => '8835', + 'sup1' => '185', + 'sup2' => '178', + 'sup3' => '179', + 'supe' => '8839', + 'superset' => '8835', + 'supersetnotequal' => '8843', + 'supersetorequal' => '8839', + 'supnE' => '8843', + 'svsquare' => '13276', + 'syouwaerasquare' => '13180', + 'szlig' => '223', + 't' => '116', + 'tabengali' => '2468', + 'tackdown' => '8868', + 'tackleft' => '8867', + 'tadeva' => '2340', + 'tagujarati' => '2724', + 'tagurmukhi' => '2596', + 'taharabic' => '1591', + 'tahfinalarabic' => '65218', + 'tahinitialarabic' => '65219', + 'tahiragana' => '12383', + 'tahmedialarabic' => '65220', + 'taisyouerasquare' => '13181', + 'takatakana' => '12479', + 'takatakanahalfwidth' => '65408', + 'tapereel' => '61502', + 'target' => '61605', + 'tatweelarabic' => '1600', + 'tau' => '964', + 'taurus' => '61535', + 'tav' => '1514', + 'tavdages' => '64330', + 'tavdagesh' => '64330', + 'tavdageshhebrew' => '64330', + 'tavhebrew' => '1514', + 'tbar' => '359', + 'tbopomofo' => '12554', + 'tcaron' => '357', + 'tccurl' => '680', + 'tcedil' => '355', + 'tcedilla' => '355', + 'tcheharabic' => '1670', + 'tchehfinalarabic' => '64379', + 'tchehinitialarabic' => '64380', + 'tchehmedialarabic' => '64381', + 'tchehmeeminitialarabic' => '64380', + 'tcircle' => '9443', + 'tcircumflexbelow' => '7793', + 'tcommaaccent' => '539', + 'tcy' => '1090', + 'tdieresis' => '7831', + 'tdot' => '8411', + 'tdotaccent' => '7787', + 'tdotbelow' => '7789', + 'tecyrillic' => '1090', + 'tedescendercyrillic' => '1197', + 'teharabic' => '1578', + 'tehfinalarabic' => '65174', + 'tehhahinitialarabic' => '64674', + 'tehhahisolatedarabic' => '64524', + 'tehinitialarabic' => '65175', + 'tehiragana' => '12390', + 'tehjeeminitialarabic' => '64673', + 'tehjeemisolatedarabic' => '64523', + 'tehmarbutaarabic' => '1577', + 'tehmarbutafinalarabic' => '65172', + 'tehmedialarabic' => '65176', + 'tehmeeminitialarabic' => '64676', + 'tehmeemisolatedarabic' => '64526', + 'tehnoonfinalarabic' => '64627', + 'tekatakana' => '12486', + 'tekatakanahalfwidth' => '65411', + 'telephone' => '8481', + 'telephoneblack' => '9742', + 'telephonesolid' => '61480', + 'telhandsetcirc' => '61481', + 'telishagedolahebrew' => '1440', + 'telishaqetanahebrew' => '1449', + 'telrec' => '8981', + 'tencircle' => '9321', + 'tenideographicparen' => '12841', + 'tenoclock' => '61632', + 'tenparen' => '9341', + 'tenperiod' => '9361', + 'tenroman' => '8569', + 'tensans' => '61578', + 'tensansinv' => '61589', + 'tesh' => '679', + 'tet' => '1496', + 'tetdagesh' => '64312', + 'tetdageshhebrew' => '64312', + 'tethebrew' => '1496', + 'tetsecyrillic' => '1205', + 'tevirhebrew' => '1435', + 'tevirlefthebrew' => '1435', + 'tgr' => '964', + 'thabengali' => '2469', + 'thadeva' => '2341', + 'thagujarati' => '2725', + 'thagurmukhi' => '2597', + 'thalarabic' => '1584', + 'thalfinalarabic' => '65196', + 'thanthakhatlowleftthai' => '63640', + 'thanthakhatlowrightthai' => '63639', + 'thanthakhatthai' => '3660', + 'thanthakhatupperleftthai' => '63638', + 'theharabic' => '1579', + 'thehfinalarabic' => '65178', + 'thehinitialarabic' => '65179', + 'thehmedialarabic' => '65180', + 'there4' => '8756', + 'thereexists' => '8707', + 'therefore' => '8756', + 'theta' => '952', + 'theta1' => '977', + 'thetasym' => '977', + 'thetasymbolgreek' => '977', + 'thetav' => '977', + 'thgr' => '952', + 'thieuthacirclekorean' => '12921', + 'thieuthaparenkorean' => '12825', + 'thieuthcirclekorean' => '12907', + 'thieuthkorean' => '12620', + 'thieuthparenkorean' => '12811', + 'thinsp' => '8201', + 'thirteencircle' => '9324', + 'thirteenparen' => '9344', + 'thirteenperiod' => '9364', + 'thkap' => '8776', + 'thksim' => '8764', + 'thonangmonthothai' => '3601', + 'thook' => '429', + 'thophuthaothai' => '3602', + 'thorn' => '254', + 'thothahanthai' => '3607', + 'thothanthai' => '3600', + 'thothongthai' => '3608', + 'thothungthai' => '3606', + 'thousandcyrillic' => '1154', + 'thousandsseparatorarabic' => '1644', + 'thousandsseparatorpersian' => '1644', + 'three' => '51', + 'threearabic' => '1635', + 'threebengali' => '2537', + 'threecircle' => '9314', + 'threecircleinversesansserif' => '10124', + 'threedeva' => '2409', + 'threeeighths' => '8540', + 'threegujarati' => '2793', + 'threegurmukhi' => '2665', + 'threehackarabic' => '1635', + 'threehangzhou' => '12323', + 'threeideographicparen' => '12834', + 'threeinferior' => '8323', + 'threemonospace' => '65299', + 'threenumeratorbengali' => '2550', + 'threeoclock' => '61625', + 'threeoldstyle' => '63283', + 'threeparen' => '9334', + 'threeperiod' => '9354', + 'threepersian' => '1779', + 'threequarters' => '190', + 'threequartersemdash' => '63198', + 'threeroman' => '8562', + 'threesans' => '61571', + 'threesansinv' => '61582', + 'threesuperior' => '179', + 'threethai' => '3667', + 'thumbdown' => '61508', + 'thumbup' => '61507', + 'thzsquare' => '13204', + 'tihiragana' => '12385', + 'tikatakana' => '12481', + 'tikatakanahalfwidth' => '65409', + 'tikeutacirclekorean' => '12912', + 'tikeutaparenkorean' => '12816', + 'tikeutcirclekorean' => '12898', + 'tikeutkorean' => '12599', + 'tikeutparenkorean' => '12802', + 'tilde' => '732', + 'tildebelowcmb' => '816', + 'tildecmb' => '771', + 'tildecomb' => '771', + 'tildedoublecmb' => '864', + 'tildeoperator' => '8764', + 'tildeoverlaycmb' => '820', + 'tildeverticalcmb' => '830', + 'times' => '215', + 'timesb' => '8864', + 'timescircle' => '8855', + 'tipehahebrew' => '1430', + 'tipehalefthebrew' => '1430', + 'tippigurmukhi' => '2672', + 'titlocyrilliccmb' => '1155', + 'tiwnarmenian' => '1407', + 'tlinebelow' => '7791', + 'tmonospace' => '65364', + 'toarmenian' => '1385', + 'tohiragana' => '12392', + 'tokatakana' => '12488', + 'tokatakanahalfwidth' => '65412', + 'tonebarextrahighmod' => '741', + 'tonebarextralowmod' => '745', + 'tonebarhighmod' => '742', + 'tonebarlowmod' => '744', + 'tonebarmidmod' => '743', + 'tonefive' => '445', + 'tonesix' => '389', + 'tonetwo' => '424', + 'tonos' => '900', + 'tonsquare' => '13095', + 'top' => '8868', + 'topatakthai' => '3599', + 'tortoiseshellbracketleft' => '12308', + 'tortoiseshellbracketleftsmall' => '65117', + 'tortoiseshellbracketleftvertical' => '65081', + 'tortoiseshellbracketright' => '12309', + 'tortoiseshellbracketrightsmall' => '65118', + 'tortoiseshellbracketrightvertical' => '65082', + 'totaothai' => '3605', + 'tpalatalhook' => '427', + 'tparen' => '9391', + 'tprime' => '8244', + 'trade' => '8482', + 'trademark' => '8482', + 'trademarksans' => '63722', + 'trademarkserif' => '63195', + 'tretroflexhook' => '648', + 'triagdn' => '9660', + 'triaglf' => '9668', + 'triagrt' => '9658', + 'triagup' => '9650', + 'trie' => '8796', + 'tristar2' => '61609', + 'ts' => '678', + 'tsadi' => '1510', + 'tsadidagesh' => '64326', + 'tsadidageshhebrew' => '64326', + 'tsadihebrew' => '1510', + 'tscy' => '1094', + 'tsecyrillic' => '1094', + 'tsere' => '1461', + 'tsere12' => '1461', + 'tsere1e' => '1461', + 'tsere2b' => '1461', + 'tserehebrew' => '1461', + 'tserenarrowhebrew' => '1461', + 'tserequarterhebrew' => '1461', + 'tserewidehebrew' => '1461', + 'tshcy' => '1115', + 'tshecyrillic' => '1115', + 'tstrok' => '359', + 'tsuperior' => '63219', + 'ttabengali' => '2463', + 'ttadeva' => '2335', + 'ttagujarati' => '2719', + 'ttagurmukhi' => '2591', + 'tteharabic' => '1657', + 'ttehfinalarabic' => '64359', + 'ttehinitialarabic' => '64360', + 'ttehmedialarabic' => '64361', + 'tthabengali' => '2464', + 'tthadeva' => '2336', + 'tthagujarati' => '2720', + 'tthagurmukhi' => '2592', + 'tturned' => '647', + 'tuhiragana' => '12388', + 'tukatakana' => '12484', + 'tukatakanahalfwidth' => '65410', + 'tusmallhiragana' => '12387', + 'tusmallkatakana' => '12483', + 'tusmallkatakanahalfwidth' => '65391', + 'twelvecircle' => '9323', + 'twelveoclock' => '61634', + 'twelveparen' => '9343', + 'twelveperiod' => '9363', + 'twelveroman' => '8571', + 'twentycircle' => '9331', + 'twentyhangzhou' => '21316', + 'twentyparen' => '9351', + 'twentyperiod' => '9371', + 'twixt' => '8812', + 'two' => '50', + 'twoarabic' => '1634', + 'twobengali' => '2536', + 'twocircle' => '9313', + 'twocircleinversesansserif' => '10123', + 'twodeva' => '2408', + 'twodotenleader' => '8229', + 'twodotleader' => '8229', + 'twodotleadervertical' => '65072', + 'twogujarati' => '2792', + 'twogurmukhi' => '2664', + 'twohackarabic' => '1634', + 'twohangzhou' => '12322', + 'twoideographicparen' => '12833', + 'twoinferior' => '8322', + 'twomonospace' => '65298', + 'twonumeratorbengali' => '2549', + 'twooclock' => '61624', + 'twooldstyle' => '63282', + 'twoparen' => '9333', + 'twoperiod' => '9353', + 'twopersian' => '1778', + 'tworoman' => '8561', + 'twosans' => '61570', + 'twosansinv' => '61581', + 'twostroke' => '443', + 'twosuperior' => '178', + 'twothai' => '3666', + 'twothirds' => '8532', + 'u' => '117', + 'uArr' => '8657', + 'uacgr' => '973', + 'uacute' => '250', + 'uarr' => '8593', + 'uarr2' => '8648', + 'ubar' => '649', + 'ubengali' => '2441', + 'ubopomofo' => '12584', + 'ubrcy' => '1118', + 'ubreve' => '365', + 'ucaron' => '468', + 'ucirc' => '251', + 'ucircle' => '9444', + 'ucircumflex' => '251', + 'ucircumflexbelow' => '7799', + 'ucy' => '1091', + 'ucyrillic' => '1091', + 'udattadeva' => '2385', + 'udblac' => '369', + 'udblacute' => '369', + 'udblgrave' => '533', + 'udeva' => '2313', + 'udiagr' => '944', + 'udieresis' => '252', + 'udieresisacute' => '472', + 'udieresisbelow' => '7795', + 'udieresiscaron' => '474', + 'udieresiscyrillic' => '1265', + 'udieresisgrave' => '476', + 'udieresismacron' => '470', + 'udigr' => '971', + 'udotbelow' => '7909', + 'ugrave' => '249', + 'ugujarati' => '2697', + 'ugurmukhi' => '2569', + 'uharl' => '8639', + 'uharr' => '8638', + 'uhblk' => '9600', + 'uhiragana' => '12358', + 'uhookabove' => '7911', + 'uhorn' => '432', + 'uhornacute' => '7913', + 'uhorndotbelow' => '7921', + 'uhorngrave' => '7915', + 'uhornhookabove' => '7917', + 'uhorntilde' => '7919', + 'uhungarumlaut' => '369', + 'uhungarumlautcyrillic' => '1267', + 'uinvertedbreve' => '535', + 'ukatakana' => '12454', + 'ukatakanahalfwidth' => '65395', + 'ukcyrillic' => '1145', + 'ukorean' => '12636', + 'ulcorn' => '8988', + 'ulcrop' => '8975', + 'umacr' => '363', + 'umacron' => '363', + 'umacroncyrillic' => '1263', + 'umacrondieresis' => '7803', + 'umatragurmukhi' => '2625', + 'uml' => '168', + 'umonospace' => '65365', + 'underscore' => '95', + 'underscoredbl' => '8215', + 'underscoremonospace' => '65343', + 'underscorevertical' => '65075', + 'underscorewavy' => '65103', + 'union' => '8746', + 'universal' => '8704', + 'uogon' => '371', + 'uogonek' => '371', + 'uparen' => '9392', + 'upblock' => '9600', + 'uplus' => '8846', + 'upperdothebrew' => '1476', + 'upsi' => '965', + 'upsih' => '978', + 'upsilon' => '965', + 'upsilondieresis' => '971', + 'upsilondieresistonos' => '944', + 'upsilonlatin' => '650', + 'upsilontonos' => '973', + 'uptackbelowcmb' => '797', + 'uptackmod' => '724', + 'uragurmukhi' => '2675', + 'urcorn' => '8989', + 'urcrop' => '8974', + 'uring' => '367', + 'ushortcyrillic' => '1118', + 'usmallhiragana' => '12357', + 'usmallkatakana' => '12453', + 'usmallkatakanahalfwidth' => '65385', + 'ustraightcyrillic' => '1199', + 'ustraightstrokecyrillic' => '1201', + 'utilde' => '361', + 'utildeacute' => '7801', + 'utildebelow' => '7797', + 'utri' => '9653', + 'utrif' => '9652', + 'uubengali' => '2442', + 'uudeva' => '2314', + 'uugujarati' => '2698', + 'uugurmukhi' => '2570', + 'uumatragurmukhi' => '2626', + 'uuml' => '252', + 'uuvowelsignbengali' => '2498', + 'uuvowelsigndeva' => '2370', + 'uuvowelsigngujarati' => '2754', + 'uvowelsignbengali' => '2497', + 'uvowelsigndeva' => '2369', + 'uvowelsigngujarati' => '2753', + 'v' => '118', + 'vArr' => '8661', + 'vDash' => '8872', + 'vadeva' => '2357', + 'vagujarati' => '2741', + 'vagurmukhi' => '2613', + 'vakatakana' => '12535', + 'varr' => '8597', + 'vav' => '1493', + 'vavdagesh' => '64309', + 'vavdagesh65' => '64309', + 'vavdageshhebrew' => '64309', + 'vavhebrew' => '1493', + 'vavholam' => '64331', + 'vavholamhebrew' => '64331', + 'vavvavhebrew' => '1520', + 'vavyodhebrew' => '1521', + 'vcircle' => '9445', + 'vcy' => '1074', + 'vdash' => '8866', + 'vdotbelow' => '7807', + 'vecyrillic' => '1074', + 'veebar' => '8891', + 'veharabic' => '1700', + 'vehfinalarabic' => '64363', + 'vehinitialarabic' => '64364', + 'vehmedialarabic' => '64365', + 'vekatakana' => '12537', + 'vellip' => '8942', + 'venus' => '9792', + 'verbar' => '124', + 'verticalbar' => '124', + 'verticallineabovecmb' => '781', + 'verticallinebelowcmb' => '809', + 'verticallinelowmod' => '716', + 'verticallinemod' => '712', + 'vewarmenian' => '1406', + 'vhook' => '651', + 'vikatakana' => '12536', + 'vineleafboldne' => '61594', + 'vineleafboldnw' => '61595', + 'vineleafboldse' => '61597', + 'vineleafboldsw' => '61596', + 'viramabengali' => '2509', + 'viramadeva' => '2381', + 'viramagujarati' => '2765', + 'virgo' => '61539', + 'visargabengali' => '2435', + 'visargadeva' => '2307', + 'visargagujarati' => '2691', + 'vltri' => '8882', + 'vmonospace' => '65366', + 'voarmenian' => '1400', + 'voicediterationhiragana' => '12446', + 'voicediterationkatakana' => '12542', + 'voicedmarkkana' => '12443', + 'voicedmarkkanahalfwidth' => '65438', + 'vokatakana' => '12538', + 'vparen' => '9393', + 'vprime' => '8242', + 'vprop' => '8733', + 'vrtri' => '8883', + 'vtilde' => '7805', + 'vturned' => '652', + 'vuhiragana' => '12436', + 'vukatakana' => '12532', + 'w' => '119', + 'wacute' => '7811', + 'waekorean' => '12633', + 'wahiragana' => '12431', + 'wakatakana' => '12527', + 'wakatakanahalfwidth' => '65436', + 'wakorean' => '12632', + 'wasmallhiragana' => '12430', + 'wasmallkatakana' => '12526', + 'wattosquare' => '13143', + 'wavedash' => '12316', + 'wavyunderscorevertical' => '65076', + 'wawarabic' => '1608', + 'wawfinalarabic' => '65262', + 'wawhamzaabovearabic' => '1572', + 'wawhamzaabovefinalarabic' => '65158', + 'wbsquare' => '13277', + 'wcirc' => '373', + 'wcircle' => '9446', + 'wcircumflex' => '373', + 'wdieresis' => '7813', + 'wdotaccent' => '7815', + 'wdotbelow' => '7817', + 'wedgeq' => '8793', + 'wehiragana' => '12433', + 'weierp' => '8472', + 'weierstrass' => '8472', + 'wekatakana' => '12529', + 'wekorean' => '12638', + 'weokorean' => '12637', + 'wgrave' => '7809', + 'wheel' => '61533', + 'whitebullet' => '9702', + 'whitecircle' => '9675', + 'whitecircleinverse' => '9689', + 'whitecornerbracketleft' => '12302', + 'whitecornerbracketleftvertical' => '65091', + 'whitecornerbracketright' => '12303', + 'whitecornerbracketrightvertical' => '65092', + 'whitediamond' => '9671', + 'whitediamondcontainingblacksmalldiamond' => '9672', + 'whitedownpointingsmalltriangle' => '9663', + 'whitedownpointingtriangle' => '9661', + 'whiteleftpointingsmalltriangle' => '9667', + 'whiteleftpointingtriangle' => '9665', + 'whitelenticularbracketleft' => '12310', + 'whitelenticularbracketright' => '12311', + 'whiterightpointingsmalltriangle' => '9657', + 'whiterightpointingtriangle' => '9655', + 'whitesmallsquare' => '9643', + 'whitesmilingface' => '9786', + 'whitesquare' => '9633', + 'whitestar' => '9734', + 'whitetelephone' => '9743', + 'whitetortoiseshellbracketleft' => '12312', + 'whitetortoiseshellbracketright' => '12313', + 'whiteuppointingsmalltriangle' => '9653', + 'whiteuppointingtriangle' => '9651', + 'wihiragana' => '12432', + 'wikatakana' => '12528', + 'wikorean' => '12639', + 'windowslogo' => '61695', + 'wmonospace' => '65367', + 'wohiragana' => '12434', + 'wokatakana' => '12530', + 'wokatakanahalfwidth' => '65382', + 'won' => '8361', + 'wonmonospace' => '65510', + 'wowaenthai' => '3623', + 'wparen' => '9394', + 'wreath' => '8768', + 'wring' => '7832', + 'wsuperior' => '695', + 'wturned' => '653', + 'wynn' => '447', + 'x' => '120', + 'xabovecmb' => '829', + 'xbopomofo' => '12562', + 'xcirc' => '9675', + 'xcircle' => '9447', + 'xdieresis' => '7821', + 'xdotaccent' => '7819', + 'xdtri' => '9661', + 'xeharmenian' => '1389', + 'xgr' => '958', + 'xi' => '958', + 'xmarkbld' => '61691', + 'xmonospace' => '65368', + 'xparen' => '9395', + 'xrhombus' => '61558', + 'xsuperior' => '739', + 'xutri' => '9651', + 'y' => '121', + 'yaadosquare' => '13134', + 'yabengali' => '2479', + 'yacute' => '253', + 'yacy' => '1103', + 'yadeva' => '2351', + 'yaekorean' => '12626', + 'yagujarati' => '2735', + 'yagurmukhi' => '2607', + 'yahiragana' => '12420', + 'yakatakana' => '12516', + 'yakatakanahalfwidth' => '65428', + 'yakorean' => '12625', + 'yamakkanthai' => '3662', + 'yasmallhiragana' => '12419', + 'yasmallkatakana' => '12515', + 'yasmallkatakanahalfwidth' => '65388', + 'yatcyrillic' => '1123', + 'ycirc' => '375', + 'ycircle' => '9448', + 'ycircumflex' => '375', + 'ycy' => '1099', + 'ydieresis' => '255', + 'ydotaccent' => '7823', + 'ydotbelow' => '7925', + 'yeharabic' => '1610', + 'yehbarreearabic' => '1746', + 'yehbarreefinalarabic' => '64431', + 'yehfinalarabic' => '65266', + 'yehhamzaabovearabic' => '1574', + 'yehhamzaabovefinalarabic' => '65162', + 'yehhamzaaboveinitialarabic' => '65163', + 'yehhamzaabovemedialarabic' => '65164', + 'yehinitialarabic' => '65267', + 'yehmedialarabic' => '65268', + 'yehmeeminitialarabic' => '64733', + 'yehmeemisolatedarabic' => '64600', + 'yehnoonfinalarabic' => '64660', + 'yehthreedotsbelowarabic' => '1745', + 'yekorean' => '12630', + 'yen' => '165', + 'yenmonospace' => '65509', + 'yeokorean' => '12629', + 'yeorinhieuhkorean' => '12678', + 'yerahbenyomohebrew' => '1450', + 'yerahbenyomolefthebrew' => '1450', + 'yericyrillic' => '1099', + 'yerudieresiscyrillic' => '1273', + 'yesieungkorean' => '12673', + 'yesieungpansioskorean' => '12675', + 'yesieungsioskorean' => '12674', + 'yetivhebrew' => '1434', + 'ygrave' => '7923', + 'yhook' => '436', + 'yhookabove' => '7927', + 'yiarmenian' => '1397', + 'yicy' => '1111', + 'yicyrillic' => '1111', + 'yikorean' => '12642', + 'yinyang' => '9775', + 'yiwnarmenian' => '1410', + 'ymonospace' => '65369', + 'yod' => '1497', + 'yoddagesh' => '64313', + 'yoddageshhebrew' => '64313', + 'yodhebrew' => '1497', + 'yodyodhebrew' => '1522', + 'yodyodpatahhebrew' => '64287', + 'yohiragana' => '12424', + 'yoikorean' => '12681', + 'yokatakana' => '12520', + 'yokatakanahalfwidth' => '65430', + 'yokorean' => '12635', + 'yosmallhiragana' => '12423', + 'yosmallkatakana' => '12519', + 'yosmallkatakanahalfwidth' => '65390', + 'yotgreek' => '1011', + 'yoyaekorean' => '12680', + 'yoyakorean' => '12679', + 'yoyakthai' => '3618', + 'yoyingthai' => '3597', + 'yparen' => '9396', + 'ypogegrammeni' => '890', + 'ypogegrammenigreekcmb' => '837', + 'yr' => '422', + 'yring' => '7833', + 'ysuperior' => '696', + 'ytilde' => '7929', + 'yturned' => '654', + 'yucy' => '1102', + 'yuhiragana' => '12422', + 'yuikorean' => '12684', + 'yukatakana' => '12518', + 'yukatakanahalfwidth' => '65429', + 'yukorean' => '12640', + 'yuml' => '255', + 'yusbigcyrillic' => '1131', + 'yusbigiotifiedcyrillic' => '1133', + 'yuslittlecyrillic' => '1127', + 'yuslittleiotifiedcyrillic' => '1129', + 'yusmallhiragana' => '12421', + 'yusmallkatakana' => '12517', + 'yusmallkatakanahalfwidth' => '65389', + 'yuyekorean' => '12683', + 'yuyeokorean' => '12682', + 'yyabengali' => '2527', + 'yyadeva' => '2399', + 'z' => '122', + 'zaarmenian' => '1382', + 'zacute' => '378', + 'zadeva' => '2395', + 'zagurmukhi' => '2651', + 'zaharabic' => '1592', + 'zahfinalarabic' => '65222', + 'zahinitialarabic' => '65223', + 'zahiragana' => '12374', + 'zahmedialarabic' => '65224', + 'zainarabic' => '1586', + 'zainfinalarabic' => '65200', + 'zakatakana' => '12470', + 'zaqefgadolhebrew' => '1429', + 'zaqefqatanhebrew' => '1428', + 'zarqahebrew' => '1432', + 'zayin' => '1494', + 'zayindagesh' => '64310', + 'zayindageshhebrew' => '64310', + 'zayinhebrew' => '1494', + 'zbopomofo' => '12567', + 'zcaron' => '382', + 'zcircle' => '9449', + 'zcircumflex' => '7825', + 'zcurl' => '657', + 'zcy' => '1079', + 'zdot' => '380', + 'zdotaccent' => '380', + 'zdotbelow' => '7827', + 'zecyrillic' => '1079', + 'zedescendercyrillic' => '1177', + 'zedieresiscyrillic' => '1247', + 'zehiragana' => '12380', + 'zekatakana' => '12476', + 'zero' => '48', + 'zeroarabic' => '1632', + 'zerobengali' => '2534', + 'zerodeva' => '2406', + 'zerogujarati' => '2790', + 'zerogurmukhi' => '2662', + 'zerohackarabic' => '1632', + 'zeroinferior' => '8320', + 'zeromonospace' => '65296', + 'zerooldstyle' => '63280', + 'zeropersian' => '1776', + 'zerosans' => '61568', + 'zerosansinv' => '61579', + 'zerosuperior' => '8304', + 'zerothai' => '3664', + 'zerowidthjoiner' => '65279', + 'zerowidthnonjoiner' => '8204', + 'zerowidthspace' => '8203', + 'zeta' => '950', + 'zgr' => '950', + 'zhbopomofo' => '12563', + 'zhcy' => '1078', + 'zhearmenian' => '1386', + 'zhebrevecyrillic' => '1218', + 'zhecyrillic' => '1078', + 'zhedescendercyrillic' => '1175', + 'zhedieresiscyrillic' => '1245', + 'zihiragana' => '12376', + 'zikatakana' => '12472', + 'zinorhebrew' => '1454', + 'zlinebelow' => '7829', + 'zmonospace' => '65370', + 'zohiragana' => '12382', + 'zokatakana' => '12478', + 'zparen' => '9397', + 'zretroflexhook' => '656', + 'zstroke' => '438', + 'zuhiragana' => '12378', + 'zukatakana' => '12474', + 'zwnj' => '8204', +}; + +1; diff --git a/lib/PDF/API2/Resource/PaperSizes.pm b/lib/PDF/API2/Resource/PaperSizes.pm new file mode 100644 index 0000000..f9462cd --- /dev/null +++ b/lib/PDF/API2/Resource/PaperSizes.pm @@ -0,0 +1,49 @@ +#line 1 "PDF/API2/Resource/PaperSizes.pm" +#line 1 "PDF/API2/Resource/PaperSizes.pm" +package PDF::API2::Resource::PaperSizes; + +use strict; +use warnings; + +our $VERSION = '2.033'; # VERSION + +sub get_paper_sizes { + return ( + # Metric sizes + '4a' => [ 4760, 6716 ], # deprecated, non-standard name + '2a' => [ 3368, 4760 ], # deprecated, non-standard name + '4a0' => [ 4760, 6716 ], + '2a0' => [ 3368, 4760 ], + 'a0' => [ 2380, 3368 ], + 'a1' => [ 1684, 2380 ], + 'a2' => [ 1190, 1684 ], + 'a3' => [ 842, 1190 ], + 'a4' => [ 595, 842 ], + 'a5' => [ 421, 595 ], + 'a6' => [ 297, 421 ], + '4b' => [ 5656, 8000 ], # deprecated, non-standard name + '2b' => [ 4000, 5656 ], # deprecated, non-standard name + '4b0' => [ 5656, 8000 ], + '2b0' => [ 4000, 5656 ], + 'b0' => [ 2828, 4000 ], + 'b1' => [ 2000, 2828 ], + 'b2' => [ 1414, 2000 ], + 'b3' => [ 1000, 1414 ], + 'b4' => [ 707, 1000 ], + 'b5' => [ 500, 707 ], + 'b6' => [ 353, 500 ], + + # US sizes + 'letter' => [ 612, 792 ], + 'broadsheet' => [ 1296, 1584 ], + 'ledger' => [ 1224, 792 ], + 'tabloid' => [ 792, 1224 ], + 'legal' => [ 612, 1008 ], + 'executive' => [ 522, 756 ], + + # Other + '36x36' => [ 2592, 2592 ], + ); +} + +1; diff --git a/lib/PDF/API2/Resource/Pattern.pm b/lib/PDF/API2/Resource/Pattern.pm new file mode 100644 index 0000000..d8e0384 --- /dev/null +++ b/lib/PDF/API2/Resource/Pattern.pm @@ -0,0 +1,21 @@ +#line 1 "PDF/API2/Resource/Pattern.pm" +#line 1 "PDF/API2/Resource/Pattern.pm" +package PDF::API2::Resource::Pattern; + +use base 'PDF::API2::Resource'; + +use strict; +use warnings; + +our $VERSION = '2.033'; # VERSION + +sub new { + my ($class, $pdf, $name) = @_; + my $self = $class->SUPER::new($pdf, $name); + + $self->type('Pattern'); + + return $self; +} + +1; diff --git a/lib/PDF/API2/Resource/Shading.pm b/lib/PDF/API2/Resource/Shading.pm new file mode 100644 index 0000000..3ff4712 --- /dev/null +++ b/lib/PDF/API2/Resource/Shading.pm @@ -0,0 +1,12 @@ +#line 1 "PDF/API2/Resource/Shading.pm" +#line 1 "PDF/API2/Resource/Shading.pm" +package PDF::API2::Resource::Shading; + +use base 'PDF::API2::Resource'; + +use strict; +use warnings; + +our $VERSION = '2.033'; # VERSION + +1; diff --git a/lib/PDF/API2/Resource/UniFont.pm b/lib/PDF/API2/Resource/UniFont.pm new file mode 100644 index 0000000..9e1e971 --- /dev/null +++ b/lib/PDF/API2/Resource/UniFont.pm @@ -0,0 +1,229 @@ +#line 1 "PDF/API2/Resource/UniFont.pm" +#line 1 "PDF/API2/Resource/UniFont.pm" +package PDF::API2::Resource::UniFont; + +use strict; +no warnings qw[ deprecated recursion uninitialized ]; + +our $VERSION = '2.033'; # VERSION + +use Encode qw(:all); + +#line 23 + +#line 57 + +sub new { + my ($class,$pdf,@fonts) = @_; + + $class = ref $class if ref $class; + my $self={ + fonts=>[], + block=>{}, + code=>{}, + }; + bless $self,$class; + + $self->{pdf}=$pdf; + + # look at all fonts + my $fn=0; + while (ref $fonts[0]) + { + my $font=shift @fonts; + if(ref($font) eq 'ARRAY') + { + push @{$self->{fonts}},$font->[0]; + shift @{$font}; + while(defined $font->[0]) + { + my $r0=shift @{$font}; + if(ref $r0) + { + foreach my $b ($r0->[0]..$r0->[-1]) + { + $self->{block}->{$b}=$fn; + } + } + else + { + $self->{block}->{$r0}=$fn; + } + } + } + elsif(ref($font) eq 'HASH') + { + push @{$self->{fonts}},$font->{font}; + + if(defined $font->{blocks} && ref($font->{blocks}) eq 'ARRAY') + { + foreach my $r0 (@{$font->{blocks}}) + { + if(ref $r0) + { + foreach my $b ($r0->[0]..$r0->[-1]) + { + $self->{block}->{$b}=$fn; + } + } + else + { + $self->{block}->{$r0}=$fn; + } + } + } + + if(defined $font->{codes} && ref($font->{codes}) eq 'ARRAY') + { + foreach my $r0 (@{$font->{codes}}) + { + if(ref $r0) + { + foreach my $b ($r0->[0]..$r0->[-1]) + { + $self->{code}->{$b}=$fn; + } + } + else + { + $self->{code}->{$r0}=$fn; + } + } + } + } + else + { + push @{$self->{fonts}},$font; + foreach my $b (0..255) + { + $self->{block}->{$b}=$fn; + } + } + $fn++; + } + + my %opts=@fonts; + + $self->{encode}=$opts{-encode} if(defined $opts{-encode}); + + return($self); +} + +sub isvirtual { return(1); } + +sub fontlist +{ + my ($self)=@_; + return [@{$self->{fonts}}]; +} + +sub width { + my ($self,$text)=@_; + $text=decode($self->{encode},$text) unless(is_utf8($text)); + my $width=0; + if(1) + { + my @blks=(); + foreach my $u (unpack('U*',$text)) + { + my $fn=0; + if(defined $self->{code}->{$u}) + { + $fn=$self->{code}->{$u}; + } + elsif(defined $self->{block}->{($u>>8)}) + { + $fn=$self->{block}->{($u>>8)}; + } + else + { + $fn=0; + } + if(scalar @blks==0 || $blks[-1]->[0]!=$fn) + { + push @blks,[$fn,pack('U',$u)]; + } + else + { + $blks[-1]->[1].=pack('U',$u); + } + } + foreach my $blk (@blks) + { + $width+=$self->fontlist->[$blk->[0]]->width($blk->[1]); + } + } + else + { + foreach my $u (unpack('U*',$text)) + { + if(defined $self->{code}->{$u}) + { + $width+=$self->fontlist->[$self->{code}->{$u}]->width(pack('U',$u)); + } + elsif(defined $self->{block}->{($u>>8)}) + { + $width+=$self->fontlist->[$self->{block}->{($u>>8)}]->width(pack('U',$u)); + } + else + { + $width+=$self->fontlist->[0]->width(pack('U',$u)); + } + } + } + + return($width); +} + +sub text +{ + my ($self,$text,$size,$ident)=@_; + $text=decode($self->{encode},$text) unless(is_utf8($text)); + die 'textsize not specified' unless(defined $size); + my $newtext=''; + my $lastfont=-1; + my @codes=(); + + foreach my $u (unpack('U*',$text)) + { + my $thisfont=0; + if(defined $self->{code}->{$u}) + { + $thisfont=$self->{code}->{$u}; + } + elsif(defined $self->{block}->{($u>>8)}) + { + $thisfont=$self->{block}->{($u>>8)}; + } + + if($thisfont!=$lastfont && $lastfont!=-1) + { + my $f=$self->fontlist->[$lastfont]; + if(defined($ident) && $ident!=0) + { + $newtext.='/'.$f->name.' '.$size.' Tf ['.$ident.' '.$f->text(pack('U*',@codes)).'] TJ '; + $ident=undef; + } + else + { + $newtext.='/'.$f->name.' '.$size.' Tf '.$f->text(pack('U*',@codes)).' Tj '; + } + @codes=(); + } + + push(@codes,$u); + $lastfont=$thisfont; + } + + if(scalar @codes > 0) + { + my $f=$self->fontlist->[$lastfont]; + $newtext.='/'.$f->name.' '.$size.' Tf '.$f->text(pack('U*',@codes),$size).' '; + } + + return($newtext); +} + +#line 272 + +1; diff --git a/lib/PDF/API2/Resource/XObject.pm b/lib/PDF/API2/Resource/XObject.pm new file mode 100644 index 0000000..178dc58 --- /dev/null +++ b/lib/PDF/API2/Resource/XObject.pm @@ -0,0 +1,37 @@ +#line 1 "PDF/API2/Resource/XObject.pm" +#line 1 "PDF/API2/Resource/XObject.pm" +package PDF::API2::Resource::XObject; + +use base 'PDF::API2::Resource'; + +use strict; +use warnings; + +our $VERSION = '2.033'; # VERSION + +use PDF::API2::Basic::PDF::Utils; + +#line 25 + +sub new { + my ($class, $pdf, $name) = @_; + my $self = $class->SUPER::new($pdf, $name); + + $self->type('XObject'); + + return $self; +} + +#line 40 + +sub subtype { + my $self = shift(); + if (scalar @_) { + $self->{'Subtype'} = PDFName(shift()); + } + return $self->{'Subtype'}->val(); +} + +#line 52 + +1; diff --git a/lib/PDF/API2/Resource/XObject/Form.pm b/lib/PDF/API2/Resource/XObject/Form.pm new file mode 100644 index 0000000..c6fc95e --- /dev/null +++ b/lib/PDF/API2/Resource/XObject/Form.pm @@ -0,0 +1,68 @@ +#line 1 "PDF/API2/Resource/XObject/Form.pm" +#line 1 "PDF/API2/Resource/XObject/Form.pm" +package PDF::API2::Resource::XObject::Form; + +use base 'PDF::API2::Resource::XObject'; + +use strict; +use warnings; + +our $VERSION = '2.033'; # VERSION + +use PDF::API2::Basic::PDF::Utils; + +#line 25 + +sub new { + my ($class, $pdf, $name) = @_; + my $self = $class->SUPER::new($pdf, $name); + + $self->subtype('Form'); + $self->{'FormType'} = PDFNum(1); + + return $self; +} + +#line 41 + +sub bbox { + my $self = shift(); + + if (scalar @_) { + $self->{'BBox'} = PDFArray(map { PDFNum($_) } @_); + } + + return map { $_->val() } $self->{'BBox'}->elements(); +} + +#line 61 + +sub resource { + my ($self, $type, $key, $object, $force) = @_; + # we are a self-contained content stream. + + $self->{'Resources'} ||= PDFDict(); + + my $dict = $self->{'Resources'}; + $dict->realise() if ref($dict) =~ /Objind$/; + + $dict->{$type} ||= PDFDict(); + $dict->{$type}->realise() if ref($dict->{$type}) =~ /Objind$/; + + unless (defined $object) { + return $dict->{$type}->{$key} || undef; + } + + if ($force) { + $dict->{$type}->{$key} = $object; + } + else { + $dict->{$type}->{$key} ||= $object; + } + + return $dict; +} + +#line 91 + +1; diff --git a/lib/PDF/API2/Resource/XObject/Form/BarCode.pm b/lib/PDF/API2/Resource/XObject/Form/BarCode.pm new file mode 100644 index 0000000..ff1da3d --- /dev/null +++ b/lib/PDF/API2/Resource/XObject/Form/BarCode.pm @@ -0,0 +1,174 @@ +#line 1 "PDF/API2/Resource/XObject/Form/BarCode.pm" +#line 1 "PDF/API2/Resource/XObject/Form/BarCode.pm" +package PDF::API2::Resource::XObject::Form::BarCode; + +use base 'PDF::API2::Resource::XObject::Form::Hybrid'; + +use strict; +use warnings; + +our $VERSION = '2.033'; # VERSION + +use PDF::API2::Util; +use PDF::API2::Basic::PDF::Utils; + +#line 26 + +sub new { + my ($class, $pdf, %options) = @_; + my $self = $class->SUPER::new($pdf); + + $self->{' bfont'} = $options{'-font'}; + + $self->{' umzn'} = $options{'-umzn'} || 0; # (u)pper (m)ending (z)o(n)e + $self->{' lmzn'} = $options{'-lmzn'} || 0; # (l)ower (m)ending (z)o(n)e + $self->{' zone'} = $options{'-zone'} || 0; # barcode height + $self->{' quzn'} = $options{'-quzn'} || 0; # (qu)iet (z)o(n)e + $self->{' ofwt'} = $options{'-ofwt'} || 0.01; # (o)ver(f)low (w)id(t)h + $self->{' fnsz'} = $options{'-fnsz'}; # (f)o(n)t(s)i(z)e + $self->{' spcr'} = $options{'-spcr'} || ''; # (sp)a(c)e(r) between chars in label + $self->{' mils'} = $options{'-mils'} || 1000/72; # single barcode unit width. 1 mil = 1/1000 of one inch. 1000/72 - for backward compatibility + $self->{' color'} = $options{'-color'} || 'black'; # barcode color + + return $self; +} + +my %bar_widths = ( + 0 => 0, + 1 => 1, 'a' => 1, 'A' => 1, + 2 => 2, 'b' => 2, 'B' => 2, + 3 => 3, 'c' => 3, 'C' => 3, + 4 => 4, 'd' => 4, 'D' => 4, + 5 => 5, 'e' => 5, 'E' => 5, + 6 => 6, 'f' => 6, 'F' => 6, + 7 => 7, 'g' => 7, 'G' => 7, + 8 => 8, 'h' => 8, 'H' => 8, + 9 => 9, 'i' => 9, 'I' => 9, +); + +sub encode { + my ($self, $string) = @_; + my @bars = map { [ $self->encode_string($_), $_ ] } split //, $string; + return @bars; +} + +sub encode_string { + my ($self, $string) = @_; + + my $bar; + foreach my $character (split //, $string) { + $bar .= $self->encode_char($character); + } + return $bar; +} + +sub drawbar { + my $self = shift(); + my @sets = @{shift()}; + my $caption = shift(); + + $self->fillcolor($self->{' color'}); + $self->strokecolor($self->{' color'}); + $self->linedash(); + + my $x = $self->{' quzn'}; + my $is_space_next = 0; + my $wdt_factor = $self->{' mils'} / 1000 * 72; + foreach my $set (@sets) { + my ($code, $label); + if (ref($set)) { + ($code, $label) = @{$set}; + } + else { + $code = $set; + $label = undef; + } + + my $code_width = 0; + my ($font_size, $y_label); + foreach my $bar (split //, $code) { + my $bar_width = $bar_widths{$bar} * $wdt_factor; + + my ($y0, $y1); + if ($bar =~ /[0-9]/) { + $y0 = $self->{' quzn'} + $self->{' lmzn'}; + $y1 = $self->{' quzn'} + $self->{' lmzn'} + $self->{' zone'} + $self->{' umzn'}; + $y_label = $self->{' quzn'}; + $font_size = $self->{' fnsz'} || $self->{' lmzn'}; + } + elsif ($bar =~ /[a-z]/) { + $y0 = $self->{' quzn'}; + $y1 = $self->{' quzn'} + $self->{' lmzn'} + $self->{' zone'} + $self->{' umzn'}; + $y_label = $self->{' quzn'} + $self->{' lmzn'} + $self->{' zone'} + $self->{' umzn'}; + $font_size = $self->{' fnsz'} || $self->{' umzn'}; + } + elsif ($bar =~ /[A-Z]/) { + $y0 = $self->{' quzn'}; + $y1 = $self->{' quzn'} + $self->{' lmzn'} + $self->{' zone'}; + $font_size = $self->{' fnsz'} || $self->{' umzn'}; + $y_label = $self->{' quzn'} + $self->{' lmzn'} + $self->{' zone'} + $self->{' umzn'} - $font_size; + } + else { + $y0 = $self->{' quzn'} + $self->{' lmzn'}; + $y1 = $self->{' quzn'} + $self->{' lmzn'} + $self->{' zone'} + $self->{' umzn'}; + $y_label = $self->{' quzn'}; + $font_size = $self->{' fnsz'} || $self->{' lmzn'}; + } + + unless ($is_space_next or $bar eq '0') { + $self->linewidth($bar_width - $self->{' ofwt'}); + $self->move($x + $code_width + $bar_width / 2, $y0); + $self->line($x + $code_width + $bar_width / 2, $y1); + $self->stroke(); + } + $is_space_next = not $is_space_next; + + $code_width += $bar_width; + } + + if (defined($label) and $self->{' lmzn'}) { + $label = join($self->{' spcr'}, split //, $label); + $self->textstart(); + $self->translate($x + ($code_width / 2), $y_label); + $self->font($self->{' bfont'}, $font_size); + $self->text_center($label); + $self->textend(); + } + + $x += $code_width; + } + + $x += $self->{' quzn'}; + + if (defined $caption) { + my $font_size = $self->{' fnsz'} || $self->{' lmzn'}; + my $y_caption = $self->{' quzn'} - $font_size; + $self->textstart(); + $self->translate($x / 2, $y_caption); + $self->font($self->{' bfont'}, $font_size); + $self->text_center($caption); + $self->textend(); + } + + $self->{' w'} = $x; + $self->{' h'} = 2 * $self->{' quzn'} + $self->{' lmzn'} + $self->{' zone'} + $self->{' umzn'}; + $self->bbox(0, 0, $self->{' w'}, $self->{' h'}); +} + +#line 171 + +sub width { + my $self = shift(); + return $self->{' w'}; +} + +#line 180 + +sub height { + my $self = shift(); + return $self->{' h'}; +} + +#line 189 + +1; diff --git a/lib/PDF/API2/Resource/XObject/Form/BarCode/codabar.pm b/lib/PDF/API2/Resource/XObject/Form/BarCode/codabar.pm new file mode 100644 index 0000000..e1f6621 --- /dev/null +++ b/lib/PDF/API2/Resource/XObject/Form/BarCode/codabar.pm @@ -0,0 +1,38 @@ +#line 1 "PDF/API2/Resource/XObject/Form/BarCode/codabar.pm" +#line 1 "PDF/API2/Resource/XObject/Form/BarCode/codabar.pm" +package PDF::API2::Resource::XObject::Form::BarCode::codabar; + +use base 'PDF::API2::Resource::XObject::Form::BarCode'; + +use strict; +use warnings; + +our $VERSION = '2.033'; # VERSION + +sub new { + my ($class, $pdf, %options) = @_; + my $self = $class->SUPER::new($pdf, %options); + + my @bars = $self->encode($options{'-code'}); + + $self->drawbar([@bars], $options{'caption'}); + + return $self; +} + +my $codabar = q|0123456789-$:/.+ABCD|; + +my @barcodabar = qw( + 11111221 11112211 11121121 22111111 11211211 + 21111211 12111121 12112111 12211111 21121111 + 11122111 11221111 21112121 21211121 21212111 + 11212121 aabbabaa ababaaba ababaaba aaabbbaa +); + +sub encode_char { + my $self = shift(); + my $char = uc shift(); + return $barcodabar[index($codabar, $char)]; +} + +1; diff --git a/lib/PDF/API2/Resource/XObject/Form/BarCode/code128.pm b/lib/PDF/API2/Resource/XObject/Form/BarCode/code128.pm new file mode 100644 index 0000000..13512c7 --- /dev/null +++ b/lib/PDF/API2/Resource/XObject/Form/BarCode/code128.pm @@ -0,0 +1,227 @@ +#line 1 "PDF/API2/Resource/XObject/Form/BarCode/code128.pm" +#line 1 "PDF/API2/Resource/XObject/Form/BarCode/code128.pm" +package PDF::API2::Resource::XObject::Form::BarCode::code128; + +use base 'PDF::API2::Resource::XObject::Form::BarCode'; + +use strict; +use warnings; + +our $VERSION = '2.033'; # VERSION + +#line 25 + +sub new { + my ($class, $pdf, %options) = @_; + $class = ref($class) if ref($class); + + my $self = $class->SUPER::new($pdf, %options); + + my @bars; + if ($options{'-ean'}) { + @bars = $self->encode_ean128($options{'-code'}); + } + else { + @bars = $self->encode_128($options{'-type'}, $options{'-code'}); + } + + $self->drawbar(\@bars, $options{'caption'}); + + return $self; +} + +# CODE-A Encoding Table +my $code128a = q| !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_| . join('', map { chr($_) } (0..31)) . qq/\xf3\xf2\x80\xcc\xcb\xf4\xf1\x8a\x8b\x8c\xff/; + +# CODE-B Encoding Table +my $code128b = q| !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|.qq/|}~\x7f\xf3\xf2\x80\xcc\xf4\xca\xf1\x8a\x8b\x8c\xff/; + +# CODE-C Encoding Table (00-99 are placeholders) +my $code128c = ("\xfe" x 100) . qq/\xcb\xca\xf1\x8a\x8b\x8c\xff/; + +# START A-C +my $bar128Sa = "\x8a"; +my $bar128Sb = "\x8b"; +my $bar128Sc = "\x8c"; + +# FNC1-FNC4 +my $bar128F1 = "\xf1"; +my $bar128F2 = "\xf2"; +my $bar128F3 = "\xf3"; +my $bar128F4 = "\xf4"; + +# CODE A-C +my $bar128Ca = "\xca"; +my $bar128Cb = "\xcb"; +my $bar128Cc = "\xcc"; + +# SHIFT +my $bar128sh = "\x80"; + +# STOP +my $bar128St = "\xff"; + +# Note: The stop code (last position) is longer than the other codes because it also has the +# termination bar appended, rather than requiring it be added as a separate call. +my @bar128 = qw( + 212222 222122 222221 121223 121322 131222 122213 122312 132212 221213 + 221312 231212 112232 122132 122231 113222 123122 123221 223211 221132 + 221231 213212 223112 312131 311222 321122 321221 312212 322112 322211 + 212123 212321 232121 111323 131123 131321 112313 132113 132311 211313 + 231113 231311 112133 112331 132131 113123 113321 133121 313121 211331 + 231131 213113 213311 213131 311123 311321 331121 312113 312311 332111 + 314111 221411 431111 111224 111422 121124 121421 141122 141221 112214 + 112412 122114 122411 142112 142211 241211 221114 413111 241112 134111 + 111242 121142 121241 114212 124112 124211 411212 421112 421211 212141 + 214121 412121 111143 111341 131141 114113 114311 411113 411311 113141 + 114131 311141 411131 b1a4a2 b1a2a4 b1a2c2 b3c1a1b +); + +sub encode_128_char_idx { + my ($code, $char) = @_; + my $index; + + if (lc($code) eq 'a') { + # Ignore CODE-A request if we're already in CODE-A + return if $char eq $bar128Ca; + + $index = index($code128a, $char); + } + elsif (lc($code) eq 'b') { + # Ignore CODE-B request if we're already in CODE-B + return if $char eq $bar128Cb; + $index = index($code128b, $char); + } + elsif (lc($code) eq 'c') { + # Ignore CODE-C request if we're already in CODE-C + return if $char eq $bar128Cc; + + if ($char =~ /^([0-9][0-9])$/) { + $index = $1; + } + else { + $index = index($code128c, $char); + } + } + + return ($bar128[$index], $index); +} + +sub encode_128_char { + my ($code, $char) = @_; + my ($b) = encode_128_char_idx($code, $char); + return $b; +} + +sub encode_128_string { + my ($code, $string) = @_; + my ($bar, $index, @bars, @checksum); + my @characters = split(//, $string); + + my $character; + while (defined($character = shift @characters)) { + if ($character =~ /[\xf1-\xf4]/) { + # CODE-C doesn't have FNC2-FNC4 + if ($character =~ /[\xf2-\xf4]/ and $code eq 'c') { + ($bar, $index) = encode_128_char_idx($code, "\xCB"); + push @bars, $bar; + push @checksum, $index; + $code = 'b'; + } + + ($bar, $index) = encode_128_char_idx($code, $character); + } + elsif ($character =~ /[\xCA-\xCC]/) { + ($bar, $index) = encode_128_char_idx($code, $character); + $code = ($character eq "\xCA" ? 'a' : + $character eq "\xCB" ? 'b' : 'c'); + } + else { + if ($code ne 'c') { + # SHIFT: Switch codes for the following character only + if ($character eq $bar128sh) { + ($bar, $index) = encode_128_char_idx($code, $character); + push @bars, $bar; + push @checksum, $index; + $character = shift(@characters); + ($bar, $index) = encode_128_char_idx($code eq 'a' ? 'b' : 'a', $character); + } + else { + ($bar, $index) = encode_128_char_idx($code, $character); + } + } + else { + $character .= shift(@characters) if $character =~ /\d/ and scalar @characters; + if ($character =~ /^[^\d]*$/ or $character =~ /^\d[^\d]*$/) { + ($bar, $index) = encode_128_char_idx($code, "\xCB"); + push @bars, $bar; + push @checksum, $index; + $code = 'b'; + } + if ($character =~ /^\d[^\d]*$/) { + unshift(@characters, substr($character, 1, 1)) if length($character) > 1; + $character = substr($character, 0, 1); + } + ($bar, $index) = encode_128_char_idx($code, $character); + } + } + $character = '' if $character =~ /[^\x20-\x7e]/; + push @bars, [$bar, $character]; + push @checksum, $index; + } + return ([@bars], @checksum); +} + +sub encode_128 { + my ($self, $code, $string) = @_; + my @bars; + my $checksum_value; + + # Default to Code C if all characters are digits (and there are at + # least two of them). Otherwise, default to Code B. + $code ||= $string =~ /^\d{2,}$/ ? 'c' : 'b'; + + # Allow the character set to be passed as a capital letter + # (consistent with the specification). + $code = lc($code) if $code =~ /^[A-C]$/; + + # Ensure a valid character set has been chosen. + die "Character set must be A, B, or C (not '$code')" unless $code =~ /^[a-c]$/; + + if ($code eq 'a') { + push @bars, encode_128_char($code, $bar128Sa); + $checksum_value = 103; + } + elsif ($code eq 'b') { + push @bars, encode_128_char($code, $bar128Sb); + $checksum_value = 104; + } + elsif ($code eq 'c') { + push @bars, encode_128_char($code, $bar128Sc); + $checksum_value = 105; + } + my ($bar, @checksum_values) = encode_128_string($code, $string); + + push @bars, @{$bar}; + + # Calculate the checksum value + foreach my $i (1 .. scalar @checksum_values) { + $checksum_value += $i * $checksum_values[$i - 1]; + } + $checksum_value %= 103; + push @bars, $bar128[$checksum_value]; + push @bars, encode_128_char($code, $bar128St); + + return @bars; +} + +sub encode_ean128 { + my ($self, $string) = @_; + $string =~ s/[^a-zA-Z\d]+//g; + $string =~ s/(\d+)([a-zA-Z]+)/$1\xcb$2/g; + $string =~ s/([a-zA-Z]+)(\d+)/$1\xcc$2/g; + + return $self->encode_128('c', "\xf1$string"); +} + +1; diff --git a/lib/PDF/API2/Resource/XObject/Form/BarCode/code3of9.pm b/lib/PDF/API2/Resource/XObject/Form/BarCode/code3of9.pm new file mode 100644 index 0000000..f699614 --- /dev/null +++ b/lib/PDF/API2/Resource/XObject/Form/BarCode/code3of9.pm @@ -0,0 +1,115 @@ +#line 1 "PDF/API2/Resource/XObject/Form/BarCode/code3of9.pm" +#line 1 "PDF/API2/Resource/XObject/Form/BarCode/code3of9.pm" +package PDF::API2::Resource::XObject::Form::BarCode::code3of9; + +use base 'PDF::API2::Resource::XObject::Form::BarCode'; + +use strict; +use warnings; + +our $VERSION = '2.033'; # VERSION + +sub new { + my ($class, $pdf, %options) = @_; + my $self = $class->SUPER::new($pdf, %options); + + my @bars = encode_3of9($options{'-code'}, + $options{'-chk'} ? 1 : 0, + $options{'-ext'} ? 1 : 0); + + $self->drawbar([@bars], $options{'caption'}); + + return $self; +} + +my $code3of9 = q(0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ-. $/+%*); + +my @bar3of9 = qw( + 1112212111 2112111121 1122111121 2122111111 + 1112211121 2112211111 1122211111 1112112121 + 2112112111 1122112111 2111121121 1121121121 + 2121121111 1111221121 2111221111 1121221111 + 1111122121 2111122111 1121122111 1111222111 + 2111111221 1121111221 2121111211 1111211221 + 2111211211 1121211211 1111112221 2111112211 + 1121112211 1111212211 2211111121 1221111121 + 2221111111 1211211121 2211211111 1221211111 + 1211112121 2211112111 1221112111 1212121111 + 1212111211 1211121211 1112121211 abaababaa1 +); + +my @extended_map = ( + '%U', '$A', '$B', '$C', '$D', '$E', '$F', '$G', '$H', '$I', + '$J', '$K', '$L', '$M', '$N', '$O', '$P', '$Q', '$R', '$S', + '$T', '$U', '$V', '$W', '$X', '$Y', '$Z', '%A', '%B', '%C', + '%D', '$E', ' ', '/A', '/B', '/C', '/D', '/E', '/F', '/G', + '/H', '/I', '/J', '/K', '/L', '-', '.', '/O', '0', '1', + '2', '3', '4', '5', '6', '7', '8', '9', '/Z', '%F', + '%G', '%H', '%I', '%J', '%V', 'A', 'B', 'C', 'D', 'E', + 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', + 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', + 'Z', '%K', '%L', '%M', '%N', '%O', '%W', '+A', '+B', '+C', + '+D', '+E', '+F', '+G', '+H', '+I', '+J', '+K', '+L', '+M', + '+N', '+O', '+P', '+Q', '+R', '+S', '+T', '+U', '+V', '+W', + '+X', '+Y', '+Z', '%P', '%Q', '%R', '%S', '%T' +); + +sub encode_3of9_char { + my $character = shift(); + return $bar3of9[index($code3of9, $character)]; +} + +sub encode_3of9_string { + my ($string, $is_mod43) = @_; + + my $bar; + my $checksum = 0; + foreach my $char (split //, $string) { + $bar .= encode_3of9_char($char); + $checksum += index($code3of9, $char); + } + + if ($is_mod43) { + $checksum %= 43; + $bar .= $bar3of9[$checksum]; + } + + return $bar; +} + +# Deprecated (rolled into encode_3of9_string) +sub encode_3of9_string_w_chk { return encode_3of9_string(shift(), 1); } + +sub encode_3of9 { + my ($string, $is_mod43, $is_extended) = @_; + + my $display; + unless ($is_extended) { + $string = uc $string; + $string =~ s/[^0-9A-Z\-\.\ \$\/\+\%]+//g; + $display = $string; + } + else { + # Extended Code39 supports all 7-bit ASCII characters + $string =~ s/[^\x00-\x7f]//g; + $display = $string; + + # Encode, but don't display, non-printable characters + $display =~ s/[[:cntrl:]]//g; + + $string = join('', map { $extended_map[ord($_)] } split //, $string); + } + + my @bars; + push @bars, encode_3of9_char('*'); + push @bars, [ encode_3of9_string($string, $is_mod43), $display ]; + push @bars, encode_3of9_char('*'); + return @bars; +} + +# Deprecated (rolled into encode_3of9) +sub encode_3of9_w_chk { return encode_3of9(shift(), 1, 0); } +sub encode_3of9_ext { return encode_3of9(shift(), 0, 1); } +sub encode_3of9_ext_w_chk { return encode_3of9(shift(), 1, 1); } + +1; diff --git a/lib/PDF/API2/Resource/XObject/Form/BarCode/ean13.pm b/lib/PDF/API2/Resource/XObject/Form/BarCode/ean13.pm new file mode 100644 index 0000000..c9196ae --- /dev/null +++ b/lib/PDF/API2/Resource/XObject/Form/BarCode/ean13.pm @@ -0,0 +1,80 @@ +#line 1 "PDF/API2/Resource/XObject/Form/BarCode/ean13.pm" +#line 1 "PDF/API2/Resource/XObject/Form/BarCode/ean13.pm" +package PDF::API2::Resource::XObject::Form::BarCode::ean13; + +use base 'PDF::API2::Resource::XObject::Form::BarCode'; + +use strict; +use warnings; + +our $VERSION = '2.033'; # VERSION + +sub new { + my ($class, $pdf, %options) = @_; + my $self = $class->SUPER::new($pdf, %options); + + my @bars = $self->encode($options{'-code'}); + + $self->drawbar([@bars], $options{'caption'}); + + return $self; +} + +my @ean_code_odd = qw(3211 2221 2122 1411 1132 1231 1114 1312 1213 3112); +my @ean_code_even = qw(1123 1222 2212 1141 2311 1321 4111 2131 3121 2113); +my @parity = qw(OOOOOO OOEOEE OOEEOE OOEEEO OEOOEE OEEOOE OEEEOO OEOEOE OEOEEO OEEOEO); + +sub encode { + my ($self, $string) = @_; + my @digits = split //, $string; + + # The first digit determines the even/odd pattern of the next six + # digits, and is printed to the left of the barcode + my $first = shift @digits; + my @bars = (['07', $first]); + + # Start Guard + push @bars, 'a1a'; + + # Digits 2-7 + foreach my $i (0 .. 5) { + my $digit = shift @digits; + if (substr($parity[$first], $i, 1) eq 'O') { + push @bars, [$ean_code_odd[$digit], $digit]; + } + else { + push @bars, [$ean_code_even[$digit], $digit]; + } + } + + # Center Guard + push @bars, '1a1a1'; + + # Digits 8-13 + for (0..5) { + my $digit = shift @digits; + push @bars, [$ean_code_odd[$digit], $digit]; + } + + # Right Guard + push @bars, 'a1a'; + + return @bars; +} + +sub calculate_check_digit { + my ($self, $string) = @_; + my @digits = split //, $string; + my $weight = 1; + my $checksum = 0; + foreach my $i (0..11) { + $checksum += $digits[$i] * $weight; + $weight = $weight == 1 ? 3 : 1; + } + + $checksum = $checksum % 10; + return 0 unless $checksum; + return 10 - $checksum; +} + +1; diff --git a/lib/PDF/API2/Resource/XObject/Form/BarCode/int2of5.pm b/lib/PDF/API2/Resource/XObject/Form/BarCode/int2of5.pm new file mode 100644 index 0000000..1a27e0b --- /dev/null +++ b/lib/PDF/API2/Resource/XObject/Form/BarCode/int2of5.pm @@ -0,0 +1,64 @@ +#line 1 "PDF/API2/Resource/XObject/Form/BarCode/int2of5.pm" +#line 1 "PDF/API2/Resource/XObject/Form/BarCode/int2of5.pm" +package PDF::API2::Resource::XObject::Form::BarCode::int2of5; + +use base 'PDF::API2::Resource::XObject::Form::BarCode'; + +use strict; +use warnings; + +our $VERSION = '2.033'; # VERSION + +# Interleaved 2 of 5 Barcodes + +# Pairs of digits are encoded; the first digit is represented by five +# bars, and the second digit is represented by five spaces interleaved +# with the bars. + +sub new { + my ($class, $pdf, %options) = @_; + my $self = $class->SUPER::new($pdf,%options); + + my @bars = $self->encode($options{'-code'}); + + $self->drawbar([@bars], $options{'caption'}); + + return $self; +} + +my @bar25interleaved = qw(11221 21112 12112 22111 11212 21211 12211 11122 21121 12121); + +sub encode { + my ($self, $string) = @_; + + # Remove any character that isn't a digit + $string =~ s/[^0-9]//g; + + # Prepend a 0 if there is an odd number of digits + $string = '0' . $string if length($string) % 2; + + # Start Code + my @bars = ('aaaa'); + + # Encode pairs of digits + my ($c1, $c2, $s1, $s2, $pair); + while (length($string)) { + ($c1, $c2, $string) = split //, $string, 3; + + $s1 = $bar25interleaved[$c1]; + $s2 = $bar25interleaved[$c2]; + $pair = ''; + foreach my $i (0 .. 4) { + $pair .= substr($s1, $i, 1); + $pair .= substr($s2, $i, 1); + } + push @bars, [$pair, ($c1 . $c2)]; + } + + # Stop Code + push @bars, 'baaa'; + + return @bars; +} + +1; diff --git a/lib/PDF/API2/Resource/XObject/Form/Hybrid.pm b/lib/PDF/API2/Resource/XObject/Form/Hybrid.pm new file mode 100644 index 0000000..951eb47 --- /dev/null +++ b/lib/PDF/API2/Resource/XObject/Form/Hybrid.pm @@ -0,0 +1,60 @@ +#line 1 "PDF/API2/Resource/XObject/Form/Hybrid.pm" +#line 1 "PDF/API2/Resource/XObject/Form/Hybrid.pm" +package PDF::API2::Resource::XObject::Form::Hybrid; + +use base qw(PDF::API2::Content PDF::API2::Resource::XObject::Form); + +use strict; +use warnings; + +our $VERSION = '2.033'; # VERSION + +use PDF::API2::Basic::PDF::Dict; +use PDF::API2::Basic::PDF::Utils; +use PDF::API2::Resource::XObject::Form; + +sub new { + my $self = PDF::API2::Resource::XObject::Form::new(@_); + + $self->{' stream'} = ''; + $self->{' poststream'} = ''; + $self->{' font'} = undef; + $self->{' fontsize'} = 0; + $self->{' charspace'} = 0; + $self->{' hscale'} = 100; + $self->{' wordspace'} = 0; + $self->{' lead'} = 0; + $self->{' rise'} = 0; + $self->{' render'} = 0; + $self->{' matrix'} = [1, 0, 0, 1, 0, 0]; + $self->{' fillcolor'} = [0]; + $self->{' strokecolor'} = [0]; + $self->{' translate'} = [0, 0]; + $self->{' scale'} = [1, 1]; + $self->{' skew'} = [0, 0]; + $self->{' rotate'} = 0; + $self->{' apiistext'} = 0; + + $self->{'Resources'} = PDFDict(); + $self->{'Resources'}->{'ProcSet'} = PDFArray(map { PDFName($_) } qw(PDF Text ImageB ImageC ImageI)); + + $self->compressFlate(); + + return $self; +} + +sub outobjdeep { + my ($self, @options) = @_; + $self->textend() unless $self->{' nofilt'}; + + # Maintainer's Note: This list of keys isn't the same as the list + # in new(). Should it be? + foreach my $key (qw(api apipdf apipage font fontsize charspace hscale + wordspace lead rise render matrix fillcolor + strokecolor translate scale skew rotate)) { + delete $self->{" $key"}; + } + return PDF::API2::Basic::PDF::Dict::outobjdeep($self, @options); +} + +1; diff --git a/lib/PDF/API2/Resource/XObject/Image.pm b/lib/PDF/API2/Resource/XObject/Image.pm new file mode 100644 index 0000000..60fcc55 --- /dev/null +++ b/lib/PDF/API2/Resource/XObject/Image.pm @@ -0,0 +1,98 @@ +#line 1 "PDF/API2/Resource/XObject/Image.pm" +#line 1 "PDF/API2/Resource/XObject/Image.pm" +package PDF::API2::Resource::XObject::Image; + +use base 'PDF::API2::Resource::XObject'; + +use strict; +use warnings; + +our $VERSION = '2.033'; # VERSION + +use PDF::API2::Basic::PDF::Utils; + +#line 25 + +sub new { + my ($class, $pdf, $name) = @_; + my $self = $class->SUPER::new($pdf, $name); + + $self->subtype('Image'); + + return $self; +} + +#line 40 + +sub width { + my $self = shift(); + $self->{'Width'} = PDFNum(shift()) if scalar @_; + return $self->{'Width'}->val(); +} + +#line 52 + +sub height { + my $self = shift(); + $self->{'Height'} = PDFNum(shift()) if scalar @_; + return $self->{'Height'}->val(); +} + +#line 64 + +sub smask { + my $self = shift(); + $self->{'SMask'} = shift(); + + return $self; +} + +#line 80 + +sub mask { + my $self = shift(); + if (ref($_[0])) { + $self->{'Mask'} = shift(); + } + else { + $self->{'Mask'} = PDFArray(map { PDFNum($_) } @_); + } + + return $self; +} + +# Deprecated (rolled into mask) +sub imask { return mask(@_); } + +#line 109 + +sub colorspace { + my ($self, @values) = @_; + if (scalar @values == 1 and ref($values[0])) { + $self->{'ColorSpace'} = $values[0]; + } + elsif (scalar @values == 1) { + $self->{'ColorSpace'} = PDFName($values[0]); + } + else { + $self->{'ColorSpace'} = PDFArray(@values); + } + + return $self; +} + +#line 130 + +sub bits_per_component { + my $self = shift(); + $self->{'BitsPerComponent'} = PDFNum(shift()); + + return $self; +} + +# Deprecated (renamed) +sub bpc { return bits_per_component(@_); } + +#line 144 + +1; diff --git a/lib/PDF/API2/Resource/XObject/Image/GD.pm b/lib/PDF/API2/Resource/XObject/Image/GD.pm new file mode 100644 index 0000000..174a9c4 --- /dev/null +++ b/lib/PDF/API2/Resource/XObject/Image/GD.pm @@ -0,0 +1,74 @@ +#line 1 "PDF/API2/Resource/XObject/Image/GD.pm" +#line 1 "PDF/API2/Resource/XObject/Image/GD.pm" +package PDF::API2::Resource::XObject::Image::GD; + +use base 'PDF::API2::Resource::XObject::Image'; + +use strict; +no warnings qw[ deprecated recursion uninitialized ]; + +our $VERSION = '2.033'; # VERSION + +use PDF::API2::Util; +use PDF::API2::Basic::PDF::Utils; +use Scalar::Util qw(weaken); + +sub new { + my ($class,$pdf,$obj,$name,@opts) = @_; + my $self; + + $class = ref $class if ref $class; + + $self=$class->SUPER::new($pdf,$name|| 'Jx'.pdfkey()); + $pdf->new_obj($self) unless($self->is_obj($pdf)); + + $self->{' apipdf'}=$pdf; + weaken $self->{' apipdf'}; + + $self->read_gd($obj,@opts); + + return($self); +} + +sub read_gd { + my $self = shift @_; + my $gd = shift @_; + my %opts = @_; + + my ($w,$h) = $gd->getBounds(); + my $c = $gd->colorsTotal(); + + $self->width($w); + $self->height($h); + + $self->bpc(8); + $self->colorspace('DeviceRGB'); + + if($gd->can('jpeg') && ($c > 256) && !$opts{-lossless}) { + + $self->filters('DCTDecode'); + $self->{' nofilt'}=1; + $self->{' stream'}=$gd->jpeg(75); + + } elsif($gd->can('raw')) { + + $self->filters('FlateDecode'); + $self->{' stream'}=$gd->raw; + + } else { + + $self->filters('FlateDecode'); + for(my $y=0;$y<$h;$y++) { + for(my $x=0;$x<$w;$x++) { + my $index=$gd->getPixel($x,$y); + my @rgb=$gd->rgb($index); + $self->{' stream'}.=pack('CCC',@rgb); + } + } + + } + + return($self); +} + +1; diff --git a/lib/PDF/API2/Resource/XObject/Image/GIF.pm b/lib/PDF/API2/Resource/XObject/Image/GIF.pm new file mode 100644 index 0000000..c151f7d --- /dev/null +++ b/lib/PDF/API2/Resource/XObject/Image/GIF.pm @@ -0,0 +1,229 @@ +#line 1 "PDF/API2/Resource/XObject/Image/GIF.pm" +#line 1 "PDF/API2/Resource/XObject/Image/GIF.pm" +package PDF::API2::Resource::XObject::Image::GIF; + +use base 'PDF::API2::Resource::XObject::Image'; + +use strict; +no warnings qw[ deprecated recursion uninitialized ]; + +our $VERSION = '2.033'; # VERSION + +use IO::File; +use PDF::API2::Util; +use PDF::API2::Basic::PDF::Utils; +use Scalar::Util qw(weaken); + +# added from PDF::Create: +# PDF::Image::GIFImage - GIF image support +# Author: Michael Gross <mdgrosse@sbox.tugraz.at> +# modified for internal use. (c) 2004 fredo. +sub unInterlace { + my $self = shift; + my $data = $self->{' stream'}; + my $row; + my @result; + my $width = $self->width; + my $height = $self->height; + my $idx = 0; + + #Pass 1 - every 8th row, starting with row 0 + $row = 0; + while ($row < $height) { + $result[$row] = substr($data, $idx*$width, $width); + $row+=8; + $idx++; + } + + #Pass 2 - every 8th row, starting with row 4 + $row = 4; + while ($row < $height) { + $result[$row] = substr($data, $idx*$width, $width); + $row+=8; + $idx++; + } + + #Pass 3 - every 4th row, starting with row 2 + $row = 2; + while ($row < $height) { + $result[$row] = substr($data, $idx*$width, $width); + $row+=4; + $idx++; + } + + #Pass 4 - every 2th row, starting with row 1 + $row = 1; + while ($row < $height) { + $result[$row] = substr($data, $idx*$width, $width); + $row+=2; + $idx++; + } + + $self->{' stream'}=join('', @result); +} + +sub deGIF { + my ($ibits,$stream)=@_; + my $bits=$ibits; + my $resetcode=1<<($ibits-1); + my $endcode=$resetcode+1; + my $nextcode=$endcode+1; + my $ptr=0; + my $maxptr=8*length($stream); + my $tag; + my $out=''; + my $outptr=0; + + # print STDERR "reset=$resetcode\nend=$endcode\nmax=$maxptr\n"; + + my @d=map { chr($_) } (0..$resetcode-1); + + while(($ptr+$bits)<=$maxptr) { + $tag=0; + foreach my $off (reverse 0..$bits-1) { + $tag<<=1; + $tag|=vec($stream,$ptr+$off,1); + } + # foreach my $off (0..$bits-1) { + # $tag<<=1; + # $tag|=vec($stream,$ptr+$off,1); + # } + # print STDERR "ptr=$ptr,tag=$tag,bits=$bits,next=$nextcode\n"; + # print STDERR "tag to large\n" if($tag>$nextcode); + $ptr+=$bits; + $bits++ if $nextcode == 1<<$bits and $bits < 12; + if($tag==$resetcode) { + $bits=$ibits; + $nextcode=$endcode+1; + next; + } elsif($tag==$endcode) { + last; + } elsif($tag<$resetcode) { + $d[$nextcode]=$d[$tag]; + $out.=$d[$nextcode]; + $nextcode++; + } elsif($tag>$endcode) { + $d[$nextcode]=$d[$tag]; + $d[$nextcode].=substr($d[$tag+1],0,1); + $out.=$d[$nextcode]; + $nextcode++; + } + } + return($out); +} + +sub new { + my ($class,$pdf,$file,$name,%opts) = @_; + my $self; + my $inter=0; + + $class = ref $class if ref $class; + + $self=$class->SUPER::new($pdf,$name || 'Gx'.pdfkey()); + $pdf->new_obj($self) unless($self->is_obj($pdf)); + + $self->{' apipdf'}=$pdf; + weaken $self->{' apipdf'}; + + my $fh = IO::File->new; + if (ref($file)) { + $fh = $file; + } + else { + open $fh, "<", $file or die "$!: $file"; + } + binmode $fh, ':raw'; + my $buf; + $fh->seek(0,0); + $fh->read($buf,6); # signature + die "unknown image signature '$buf' -- not a gif." unless($buf=~/^GIF[0-9][0-9][a-b]/); + + $fh->read($buf,7); # logical descr. + my($wg,$hg,$flags,$bgColorIndex,$aspect)=unpack('vvCCC',$buf); + + if($flags&0x80) { + my $colSize=2**(($flags&0x7)+1); + my $dict=PDFDict(); + $pdf->new_obj($dict); + $self->colorspace(PDFArray(PDFName('Indexed'),PDFName('DeviceRGB'),PDFNum($colSize-1),$dict)); + $fh->read($dict->{' stream'},3*$colSize); # color-table + } + + while(!$fh->eof) { + $fh->read($buf,1); # tag. + my $sep=unpack('C',$buf); + if($sep==0x2C){ + $fh->read($buf,9); # image-descr. + my ($left,$top,$w,$h,$flags)=unpack('vvvvC',$buf); + + $self->width($w||$wg); + $self->height($h||$hg); + $self->bpc(8); + + if($flags&0x80) { # local colormap + my $colSize=2**(($flags&0x7)+1); + my $dict=PDFDict(); + $pdf->new_obj($dict); + $self->colorspace(PDFArray(PDFName('Indexed'),PDFName('DeviceRGB'),PDFNum($colSize-1),$dict)); + $fh->read($dict->{' stream'},3*$colSize); # color-table + } + if($flags&0x40) { # need de-interlace + $inter=1; + } + + $fh->read($buf,1); # image-lzw-start (should be 9). + my ($sep)=unpack('C',$buf); + + $fh->read($buf,1); # first chunk. + my ($len)=unpack('C',$buf); + my $stream=''; + while($len>0) { + $fh->read($buf,$len); + $stream.=$buf; + $fh->read($buf,1); + $len=unpack('C',$buf); + } + $self->{' stream'}=deGIF($sep+1,$stream); + $self->unInterlace if($inter); + last; + } elsif($sep==0x3b) { + last; + } elsif($sep==0x21) { + # Graphic Control Extension + $fh->read($buf,1); # tag. + my $tag=unpack('C',$buf); + die "unsupported graphic control extension ($tag)" unless($tag==0xF9); + $fh->read($buf,1); # len. + my $len=unpack('C',$buf); + my $stream=''; + while($len>0) { + $fh->read($buf,$len); + $stream.=$buf; + $fh->read($buf,1); + $len=unpack('C',$buf); + } + my ($cFlags,$delay,$transIndex)=unpack('CvC',$stream); + if(($cFlags&0x01) && !$opts{-notrans}) { + $self->{Mask}=PDFArray(PDFNum($transIndex),PDFNum($transIndex)); + } + } else { + # extension + $fh->read($buf,1); # tag. + my $tag=unpack('C',$buf); + $fh->read($buf,1); # tag. + my $len=unpack('C',$buf); + while($len>0) { + $fh->read($buf,$len); + $fh->read($buf,1); + $len=unpack('C',$buf); + } + } + } + $fh->close; + + $self->filters('FlateDecode'); + + return($self); +} + +1; diff --git a/lib/PDF/API2/Resource/XObject/Image/JPEG.pm b/lib/PDF/API2/Resource/XObject/Image/JPEG.pm new file mode 100644 index 0000000..ff42f78 --- /dev/null +++ b/lib/PDF/API2/Resource/XObject/Image/JPEG.pm @@ -0,0 +1,99 @@ +#line 1 "PDF/API2/Resource/XObject/Image/JPEG.pm" +#line 1 "PDF/API2/Resource/XObject/Image/JPEG.pm" +package PDF::API2::Resource::XObject::Image::JPEG; + +use base 'PDF::API2::Resource::XObject::Image'; + +use strict; +use warnings; + +our $VERSION = '2.033'; # VERSION + +use IO::File; +use PDF::API2::Util; +use PDF::API2::Basic::PDF::Utils; +use Scalar::Util qw(weaken); + +sub new { + my ($class, $pdf, $file, $name) = @_; + my $fh = IO::File->new(); + + $class = ref($class) if ref($class); + + my $self = $class->SUPER::new($pdf, $name || 'Jx' . pdfkey()); + $pdf->new_obj($self) unless $self->is_obj($pdf); + + $self->{' apipdf'} = $pdf; + weaken $self->{' apipdf'}; + + if (ref($file)) { + $fh = $file; + } + else { + open $fh, "<", $file or die "$!: $file"; + } + binmode $fh, ':raw'; + + $self->read_jpeg($fh); + + if (ref($file)) { + seek $fh, 0, 0; + $self->{' stream'} = ''; + my $buf = ''; + while (!eof($fh)) { + read $fh, $buf, 512; + $self->{' stream'} .= $buf; + } + $self->{'Length'} = PDFNum(length $self->{' stream'}); + } + else { + $self->{'Length'} = PDFNum(-s $file); + $self->{' streamfile'} = $file; + } + + $self->filters('DCTDecode'); + $self->{' nofilt'} = 1; + + return $self; +} + +sub read_jpeg { + my ($self, $fh) = @_; + my ($buf, $p, $h, $w, $c, $ff, $mark, $len); + + $fh->seek(0,0); + $fh->read($buf,2); + while (1) { + $fh->read($buf, 4); + my ($ff, $mark, $len) = unpack('CCn', $buf); + last if $ff != 0xFF; + last if $mark == 0xDA || $mark == 0xD9; # SOS/EOI + last if $len < 2; + last if $fh->eof(); + $fh->read($buf, $len - 2); + next if $mark == 0xFE; + next if $mark >= 0xE0 && $mark <= 0xEF; + if ($mark >= 0xC0 && $mark <= 0xCF && $mark != 0xC4 && $mark != 0xC8 && $mark != 0xCC) { + ($p, $h, $w, $c) = unpack('CnnC', substr($buf, 0, 6)); + last; + } + } + + $self->width($w); + $self->height($h); + $self->bpc($p); + + if ($c == 3) { + $self->colorspace('DeviceRGB'); + } + elsif ($c == 4) { + $self->colorspace('DeviceCMYK'); + } + elsif ($c == 1) { + $self->colorspace('DeviceGray'); + } + + return $self; +} + +1; diff --git a/lib/PDF/API2/Resource/XObject/Image/PNG.pm b/lib/PDF/API2/Resource/XObject/Image/PNG.pm new file mode 100644 index 0000000..edeeed2 --- /dev/null +++ b/lib/PDF/API2/Resource/XObject/Image/PNG.pm @@ -0,0 +1,694 @@ +#line 1 "PDF/API2/Resource/XObject/Image/PNG.pm" +#line 1 "PDF/API2/Resource/XObject/Image/PNG.pm" +package PDF::API2::Resource::XObject::Image::PNG; + +use base 'PDF::API2::Resource::XObject::Image'; + +use strict; +use warnings; + +our $VERSION = '2.033'; # VERSION + +use Compress::Zlib; +use POSIX qw(ceil floor); + +use IO::File; +use PDF::API2::Util; +use PDF::API2::Basic::PDF::Utils; +use Scalar::Util qw(weaken); + +sub new { + my ($class, $pdf, $file, $name, %opts) = @_; + my $self; + + $class = ref($class) if ref($class); + + $self = $class->SUPER::new($pdf, $name || 'Px' . pdfkey()); + $pdf->new_obj($self) unless $self->is_obj($pdf); + + $self->{' apipdf'} = $pdf; + weaken $self->{' apipdf'}; + + my $fh = IO::File->new(); + if (ref($file)) { + $fh = $file; + } + else { + open $fh, '<', $file or die "$!: $file"; + } + binmode $fh, ':raw'; + + my ($buf, $l, $crc, $w, $h, $bpc, $cs, $cm, $fm, $im, $palete, $trns); + seek($fh, 8, 0); + $self->{' stream'} = ''; + $self->{' nofilt'} = 1; + while (!eof($fh)) { + read($fh, $buf, 4); + $l = unpack('N', $buf); + read($fh, $buf, 4); + if ($buf eq 'IHDR') { + read($fh, $buf, $l); + ($w, $h, $bpc, $cs, $cm, $fm, $im) = unpack('NNCCCCC', $buf); + die "Unsupported Compression($cm) Method" if $cm; + die "Unsupported Interlace($im) Method" if $im; + die "Unsupported Filter($fm) Method" if $fm; + } + elsif ($buf eq 'PLTE') { + read($fh, $buf, $l); + $palete = $buf; + } + elsif($buf eq 'IDAT') { + read($fh, $buf, $l); + $self->{' stream'} .= $buf; + } + elsif($buf eq 'tRNS') { + read($fh, $buf, $l); + $trns = $buf; + } + elsif($buf eq 'IEND') { + last; + } + else { + # skip ahead + seek($fh, $l, 1); + } + read($fh, $buf, 4); + $crc = $buf; + } + close $fh; + + $self->width($w); + $self->height($h); + + if ($cs == 0) { # greyscale + # scanline = ceil(bpc * comp / 8)+1 + if ($bpc > 8) { + die "16-bits of greylevel in png not supported."; + } + else { + $self->filters('FlateDecode'); + $self->colorspace('DeviceGray'); + $self->bpc($bpc); + my $dict = PDFDict(); + $self->{'DecodeParms'} = PDFArray($dict); + $dict->{'Predictor'} = PDFNum(15); + $dict->{'BitsPerComponent'} = PDFNum($bpc); + $dict->{'Colors'} = PDFNum(1); + $dict->{'Columns'} = PDFNum($w); + if (defined $trns && !$opts{-notrans}) { + my $m = mMax(unpack('n*', $trns)); + my $n = mMin(unpack('n*', $trns)); + $self->{'Mask'} = PDFArray(PDFNum($n), PDFNum($m)); + } + } + } + elsif ($cs == 2) { # rgb 8/16 bits + if ($bpc > 8) { + die "16-bits of rgb in png not supported."; + } + else { + $self->filters('FlateDecode'); + $self->colorspace('DeviceRGB'); + $self->bpc($bpc); + my $dict = PDFDict(); + $self->{'DecodeParms'} = PDFArray($dict); + $dict->{'Predictor'} = PDFNum(15); + $dict->{'BitsPerComponent'} = PDFNum($bpc); + $dict->{'Colors'} = PDFNum(3); + $dict->{'Columns'} = PDFNum($w); + if (defined $trns && !$opts{-notrans}) { + my @v = unpack('n*', $trns); + my (@cr, @cg, @cb, $m, $n); + while (scalar @v > 0) { + push @cr, shift(@v); + push @cg, shift(@v); + push @cb, shift(@v); + } + @v = (); + $m = mMax(@cr); + $n = mMin(@cr); + push @v, $n, $m; + $m = mMax(@cg); + $n = mMin(@cg); + push @v, $n, $m; + $m = mMax(@cb); + $n = mMin(@cb); + push @v, $n, $m; + $self->{'Mask'} = PDFArray(map { PDFNum($_) } @v); + } + } + } + elsif ($cs == 3){ # palette + if ($bpc > 8) { + die 'bits>8 of palette in png not supported.'; + } + else { + my $dict = PDFDict(); + $pdf->new_obj($dict); + $dict->{'Filter'} = PDFArray(PDFName('FlateDecode')); + $dict->{' stream'} = $palete; + $palete = ''; + $self->filters('FlateDecode'); + $self->colorspace(PDFArray(PDFName('Indexed'), PDFName('DeviceRGB'), PDFNum(int(length($dict->{' stream'}) / 3) - 1), $dict)); + $self->bpc($bpc); + $dict = PDFDict(); + $self->{'DecodeParms'} = PDFArray($dict); + $dict->{'Predictor'} = PDFNum(15); + $dict->{'BitsPerComponent'} = PDFNum($bpc); + $dict->{'Colors'} = PDFNum(1); + $dict->{'Columns'} = PDFNum($w); + if (defined $trns && !$opts{-notrans}) { + $trns .= "\xFF" x 256; + $dict = PDFDict(); + $pdf->new_obj($dict); + $dict->{'Type'} = PDFName('XObject'); + $dict->{'Subtype'} = PDFName('Image'); + $dict->{'Width'} = PDFNum($w); + $dict->{'Height'} = PDFNum($h); + $dict->{'ColorSpace'} = PDFName('DeviceGray'); + $dict->{'Filter'} = PDFArray(PDFName('FlateDecode')); + $dict->{'BitsPerComponent'} = PDFNum(8); + $self->{'SMask'} = $dict; + my $scanline = 1 + ceil($bpc * $w / 8); + my $bpp = ceil($bpc / 8); + my $clearstream = unprocess($bpc, $bpp, 1, $w, $h, $scanline, \$self->{' stream'}); + foreach my $n (0 .. ($h * $w) - 1) { + vec($dict->{' stream'}, $n, 8) = vec($trns, vec($clearstream, $n, $bpc), 8); + } + } + } + } + elsif ($cs == 4) { # greyscale+alpha + if ($bpc > 8) { + die '16-bits of greylevel+alpha in png not supported.'; + } + else { + $self->filters('FlateDecode'); + $self->colorspace('DeviceGray'); + $self->bpc($bpc); + my $dict = PDFDict(); + $self->{'DecodeParms'} = PDFArray($dict); + # $dict->{'Predictor'} = PDFNum(15); + $dict->{'BitsPerComponent'} = PDFNum($bpc); + $dict->{'Colors'} = PDFNum(1); + $dict->{'Columns'} = PDFNum($w); + + $dict = PDFDict(); + unless ($opts{-notrans}) { + $pdf->new_obj($dict); + $dict->{'Type'} = PDFName('XObject'); + $dict->{'Subtype'} = PDFName('Image'); + $dict->{'Width'} = PDFNum($w); + $dict->{'Height'} = PDFNum($h); + $dict->{'ColorSpace'} = PDFName('DeviceGray'); + $dict->{'Filter'} = PDFArray(PDFName('FlateDecode')); + $dict->{'BitsPerComponent'} = PDFNum($bpc); + $self->{'SMask'} = $dict; + } + my $scanline = 1 + ceil($bpc * 2 * $w / 8); + my $bpp = ceil($bpc * 2 / 8); + my $clearstream = unprocess($bpc, $bpp, 2, $w, $h, $scanline, \$self->{' stream'}); + delete $self->{' nofilt'}; + delete $self->{' stream'}; + foreach my $n (0 .. ($h * $w) - 1) { + vec($dict->{' stream'}, $n, $bpc) = vec($clearstream, ($n * 2) + 1, $bpc); + vec($self->{' stream'}, $n, $bpc) = vec($clearstream, $n * 2, $bpc); + } + } + } + elsif ($cs == 6) { # rgb+alpha + if ($bpc > 8) { + die '16-bits of rgb+alpha in png not supported.'; + } + else { + $self->filters('FlateDecode'); + $self->colorspace('DeviceRGB'); + $self->bpc($bpc); + my $dict = PDFDict(); + $self->{'DecodeParms'} = PDFArray($dict); + # $dict->{'Predictor'} = PDFNum(15); + $dict->{'BitsPerComponent'} = PDFNum($bpc); + $dict->{'Colors'} = PDFNum(3); + $dict->{'Columns'} = PDFNum($w); + + $dict = PDFDict(); + unless($opts{-notrans}) { + $pdf->new_obj($dict); + $dict->{'Type'} = PDFName('XObject'); + $dict->{'Subtype'} = PDFName('Image'); + $dict->{'Width'} = PDFNum($w); + $dict->{'Height'} = PDFNum($h); + $dict->{'ColorSpace'} = PDFName('DeviceGray'); + $dict->{'Filter'} = PDFArray(PDFName('FlateDecode')); + $dict->{'BitsPerComponent'} = PDFNum($bpc); + $self->{'SMask'} = $dict; + } + my $scanline = 1 + ceil($bpc * 4 * $w / 8); + my $bpp = ceil($bpc * 4 / 8); + my $clearstream = unprocess($bpc, $bpp, 4, $w, $h, $scanline, \$self->{' stream'}); + delete $self->{' nofilt'}; + delete $self->{' stream'}; + foreach my $n (0 .. ($h * $w) - 1) { + vec($dict->{' stream'}, $n, $bpc) = vec($clearstream, ($n * 4) + 3, $bpc); + vec($self->{' stream'}, ($n * 3), $bpc) = vec($clearstream, ($n * 4), $bpc); + vec($self->{' stream'}, ($n * 3) + 1, $bpc) = vec($clearstream, ($n * 4) + 1, $bpc); + vec($self->{' stream'}, ($n * 3) + 2, $bpc) = vec($clearstream, ($n * 4) + 2, $bpc); + } + } + } + else { + die "unsupported png-type ($cs)."; + } + + return $self; +} + +sub PaethPredictor { + my ($a, $b, $c) = @_; + my $p = $a + $b - $c; + my $pa = abs($p - $a); + my $pb = abs($p - $b); + my $pc = abs($p - $c); + if (($pa <= $pb) && ($pa <= $pc)) { + return $a; + } + elsif ($pb <= $pc) { + return $b; + } + else { + return $c; + } +} + +sub unprocess { + my ($bpc, $bpp, $comp, $width, $height, $scanline, $sstream) = @_; + my $stream = uncompress($$sstream); + my $prev = ''; + my $clearstream = ''; + foreach my $n (0 .. $height - 1) { + # print STDERR "line $n:"; + my $line = substr($stream, $n * $scanline, $scanline); + my $filter = vec($line, 0, 8); + my $clear = ''; + $line = substr($line, 1); + # print STDERR " filter=$filter"; + if ($filter == 0) { + $clear = $line; + } + elsif ($filter == 1) { + foreach my $x (0 .. length($line) - 1) { + vec($clear, $x, 8) = (vec($line, $x, 8) + vec($clear, $x - $bpp, 8)) % 256; + } + } + elsif ($filter == 2) { + foreach my $x (0 .. length($line) - 1) { + vec($clear, $x, 8) = (vec($line, $x, 8) + vec($prev, $x, 8)) % 256; + } + } + elsif ($filter == 3) { + foreach my $x (0 .. length($line) - 1) { + vec($clear, $x, 8) = (vec($line, $x, 8) + floor((vec($clear, $x - $bpp, 8) + vec($prev, $x, 8)) / 2)) % 256; + } + } + elsif ($filter == 4) { + foreach my $x (0 .. length($line) - 1) { + vec($clear,$x,8) = (vec($line, $x, 8) + PaethPredictor(vec($clear, $x - $bpp, 8), vec($prev, $x, 8), vec($prev, $x - $bpp, 8))) % 256; + } + } + $prev = $clear; + foreach my $x (0 .. ($width * $comp) - 1) { + vec($clearstream, ($n * $width * $comp) + $x, $bpc) = vec($clear, $x, $bpc); + } + } + return $clearstream; +} + +1; + +__END__ + +RFC 2083 +PNG: Portable Network Graphics +January 1997 + + +4.1.3. IDAT Image data + + The IDAT chunk contains the actual image data. To create this + data: + + * Begin with image scanlines represented as described in + Image layout (Section 2.3); the layout and total size of + this raw data are determined by the fields of IHDR. + * Filter the image data according to the filtering method + specified by the IHDR chunk. (Note that with filter + method 0, the only one currently defined, this implies + prepending a filter type byte to each scanline.) + * Compress the filtered data using the compression method + specified by the IHDR chunk. + + The IDAT chunk contains the output datastream of the compression + algorithm. + + To read the image data, reverse this process. + + There can be multiple IDAT chunks; if so, they must appear + consecutively with no other intervening chunks. The compressed + datastream is then the concatenation of the contents of all the + IDAT chunks. The encoder can divide the compressed datastream + into IDAT chunks however it wishes. (Multiple IDAT chunks are + allowed so that encoders can work in a fixed amount of memory; + typically the chunk size will correspond to the encoder's buffer + size.) It is important to emphasize that IDAT chunk boundaries + have no semantic significance and can occur at any point in the + compressed datastream. A PNG file in which each IDAT chunk + contains only one data byte is legal, though remarkably wasteful + of space. (For that matter, zero-length IDAT chunks are legal, + though even more wasteful.) + + +4.2.9. tRNS Transparency + + The tRNS chunk specifies that the image uses simple + transparency: either alpha values associated with palette + entries (for indexed-color images) or a single transparent + color (for grayscale and truecolor images). Although simple + transparency is not as elegant as the full alpha channel, it + requires less storage space and is sufficient for many common + cases. + + For color type 3 (indexed color), the tRNS chunk contains a + series of one-byte alpha values, corresponding to entries in + the PLTE chunk: + + Alpha for palette index 0: 1 byte + Alpha for palette index 1: 1 byte + ... etc ... + + Each entry indicates that pixels of the corresponding palette + index must be treated as having the specified alpha value. + Alpha values have the same interpretation as in an 8-bit full + alpha channel: 0 is fully transparent, 255 is fully opaque, + regardless of image bit depth. The tRNS chunk must not contain + more alpha values than there are palette entries, but tRNS can + contain fewer values than there are palette entries. In this + case, the alpha value for all remaining palette entries is + assumed to be 255. In the common case in which only palette + index 0 need be made transparent, only a one-byte tRNS chunk is + needed. + + For color type 0 (grayscale), the tRNS chunk contains a single + gray level value, stored in the format: + + Gray: 2 bytes, range 0 .. (2^bitdepth)-1 + + (For consistency, 2 bytes are used regardless of the image bit + depth.) Pixels of the specified gray level are to be treated as + transparent (equivalent to alpha value 0); all other pixels are + to be treated as fully opaque (alpha value (2^bitdepth)-1). + + For color type 2 (truecolor), the tRNS chunk contains a single + RGB color value, stored in the format: + + Red: 2 bytes, range 0 .. (2^bitdepth)-1 + Green: 2 bytes, range 0 .. (2^bitdepth)-1 + Blue: 2 bytes, range 0 .. (2^bitdepth)-1 + + (For consistency, 2 bytes per sample are used regardless of the + image bit depth.) Pixels of the specified color value are to be + treated as transparent (equivalent to alpha value 0); all other + pixels are to be treated as fully opaque (alpha value + 2^bitdepth)-1). + + tRNS is prohibited for color types 4 and 6, since a full alpha + channel is already present in those cases. + + Note: when dealing with 16-bit grayscale or truecolor data, it + is important to compare both bytes of the sample values to + determine whether a pixel is transparent. Although decoders + may drop the low-order byte of the samples for display, this + must not occur until after the data has been tested for + transparency. For example, if the grayscale level 0x0001 is + specified to be transparent, it would be incorrect to compare + only the high-order byte and decide that 0x0002 is also + transparent. + + When present, the tRNS chunk must precede the first IDAT chunk, + and must follow the PLTE chunk, if any. + + +6. Filter Algorithms + + This chapter describes the filter algorithms that can be applied + before compression. The purpose of these filters is to prepare the + image data for optimum compression. + + +6.1. Filter types + + PNG filter method 0 defines five basic filter types: + + Type Name + + 0 None + 1 Sub + 2 Up + 3 Average + 4 Paeth + + (Note that filter method 0 in IHDR specifies exactly this set of + five filter types. If the set of filter types is ever extended, a + different filter method number will be assigned to the extended + set, so that decoders need not decompress the data to discover + that it contains unsupported filter types.) + + The encoder can choose which of these filter algorithms to apply + on a scanline-by-scanline basis. In the image data sent to the + compression step, each scanline is preceded by a filter type byte + that specifies the filter algorithm used for that scanline. + + Filtering algorithms are applied to bytes, not to pixels, + regardless of the bit depth or color type of the image. The + filtering algorithms work on the byte sequence formed by a + scanline that has been represented as described in Image layout + (Section 2.3). If the image includes an alpha channel, the alpha + data is filtered in the same way as the image data. + + When the image is interlaced, each pass of the interlace pattern + is treated as an independent image for filtering purposes. The + filters work on the byte sequences formed by the pixels actually + transmitted during a pass, and the "previous scanline" is the one + previously transmitted in the same pass, not the one adjacent in + the complete image. Note that the subimage transmitted in any one + pass is always rectangular, but is of smaller width and/or height + than the complete image. Filtering is not applied when this + subimage is empty. + + For all filters, the bytes "to the left of" the first pixel in a + scanline must be treated as being zero. For filters that refer to + the prior scanline, the entire prior scanline must be treated as + being zeroes for the first scanline of an image (or of a pass of + an interlaced image). + + To reverse the effect of a filter, the decoder must use the + decoded values of the prior pixel on the same line, the pixel + immediately above the current pixel on the prior line, and the + pixel just to the left of the pixel above. This implies that at + least one scanline's worth of image data will have to be stored by + the decoder at all times. Even though some filter types do not + refer to the prior scanline, the decoder will always need to store + each scanline as it is decoded, since the next scanline might use + a filter that refers to it. + + PNG imposes no restriction on which filter types can be applied to + an image. However, the filters are not equally effective on all + types of data. See Recommendations for Encoders: Filter selection + (Section 9.6). + + See also Rationale: Filtering (Section 12.9). + + + +6.2. Filter type 0: None + + With the None filter, the scanline is transmitted unmodified; it + is only necessary to insert a filter type byte before the data. + + +6.3. Filter type 1: Sub + + The Sub filter transmits the difference between each byte and the + value of the corresponding byte of the prior pixel. + + To compute the Sub filter, apply the following formula to each + byte of the scanline: + + Sub(x) = Raw(x) - Raw(x-bpp) + + where x ranges from zero to the number of bytes representing the + scanline minus one, Raw(x) refers to the raw data byte at that + byte position in the scanline, and bpp is defined as the number of + bytes per complete pixel, rounding up to one. For example, for + color type 2 with a bit depth of 16, bpp is equal to 6 (three + samples, two bytes per sample); for color type 0 with a bit depth + of 2, bpp is equal to 1 (rounding up); for color type 4 with a bit + depth of 16, bpp is equal to 4 (two-byte grayscale sample, plus + two-byte alpha sample). + + Note this computation is done for each byte, regardless of bit + depth. In a 16-bit image, each MSB is predicted from the + preceding MSB and each LSB from the preceding LSB, because of the + way that bpp is defined. + + Unsigned arithmetic modulo 256 is used, so that both the inputs + and outputs fit into bytes. The sequence of Sub values is + transmitted as the filtered scanline. + + For all x < 0, assume Raw(x) = 0. + + To reverse the effect of the Sub filter after decompression, + output the following value: + + Sub(x) + Raw(x-bpp) + + (computed mod 256), where Raw refers to the bytes already decoded. + + +6.4. Filter type 2: Up + + The Up filter is just like the Sub filter except that the pixel + immediately above the current pixel, rather than just to its left, + is used as the predictor. + + To compute the Up filter, apply the following formula to each byte + of the scanline: + + Up(x) = Raw(x) - Prior(x) + + where x ranges from zero to the number of bytes representing the + scanline minus one, Raw(x) refers to the raw data byte at that + byte position in the scanline, and Prior(x) refers to the + unfiltered bytes of the prior scanline. + + Note this is done for each byte, regardless of bit depth. + Unsigned arithmetic modulo 256 is used, so that both the inputs + and outputs fit into bytes. The sequence of Up values is + transmitted as the filtered scanline. + + On the first scanline of an image (or of a pass of an interlaced + image), assume Prior(x) = 0 for all x. + + To reverse the effect of the Up filter after decompression, output + the following value: + + Up(x) + Prior(x) + + (computed mod 256), where Prior refers to the decoded bytes of the + prior scanline. + + +6.5. Filter type 3: Average + + The Average filter uses the average of the two neighboring pixels + (left and above) to predict the value of a pixel. + + To compute the Average filter, apply the following formula to each + byte of the scanline: + + Average(x) = Raw(x) - floor((Raw(x-bpp)+Prior(x))/2) + + where x ranges from zero to the number of bytes representing the + scanline minus one, Raw(x) refers to the raw data byte at that + byte position in the scanline, Prior(x) refers to the unfiltered + bytes of the prior scanline, and bpp is defined as for the Sub + filter. + + Note this is done for each byte, regardless of bit depth. The + sequence of Average values is transmitted as the filtered + scanline. + + The subtraction of the predicted value from the raw byte must be + done modulo 256, so that both the inputs and outputs fit into + bytes. However, the sum Raw(x-bpp)+Prior(x) must be formed + without overflow (using at least nine-bit arithmetic). floor() + indicates that the result of the division is rounded to the next + lower integer if fractional; in other words, it is an integer + division or right shift operation. + + For all x < 0, assume Raw(x) = 0. On the first scanline of an + image (or of a pass of an interlaced image), assume Prior(x) = 0 + for all x. + + To reverse the effect of the Average filter after decompression, + output the following value: + + Average(x) + floor((Raw(x-bpp)+Prior(x))/2) + + where the result is computed mod 256, but the prediction is + calculated in the same way as for encoding. Raw refers to the + bytes already decoded, and Prior refers to the decoded bytes of + the prior scanline. + + +6.6. Filter type 4: Paeth + + The Paeth filter computes a simple linear function of the three + neighboring pixels (left, above, upper left), then chooses as + predictor the neighboring pixel closest to the computed value. + This technique is due to Alan W. Paeth [PAETH]. + + To compute the Paeth filter, apply the following formula to each + byte of the scanline: + + Paeth(x) = Raw(x) - PaethPredictor(Raw(x-bpp), Prior(x), Prior(x-bpp)) + + where x ranges from zero to the number of bytes representing the + scanline minus one, Raw(x) refers to the raw data byte at that + byte position in the scanline, Prior(x) refers to the unfiltered + bytes of the prior scanline, and bpp is defined as for the Sub + filter. + + Note this is done for each byte, regardless of bit depth. + Unsigned arithmetic modulo 256 is used, so that both the inputs + and outputs fit into bytes. The sequence of Paeth values is + transmitted as the filtered scanline. + + The PaethPredictor function is defined by the following + pseudocode: + + function PaethPredictor (a, b, c) + begin + ; a = left, b = above, c = upper left + p := a + b - c ; initial estimate + pa := abs(p - a) ; distances to a, b, c + pb := abs(p - b) + pc := abs(p - c) + ; return nearest of a,b,c, + ; breaking ties in order a,b,c. + if pa <= pb AND pa <= pc then return a + else if pb <= pc then return b + else return c + end + + The calculations within the PaethPredictor function must be + performed exactly, without overflow. Arithmetic modulo 256 is to + be used only for the final step of subtracting the function result + from the target byte value. + + Note that the order in which ties are broken is critical and must + not be altered. The tie break order is: pixel to the left, pixel + above, pixel to the upper left. (This order differs from that + given in Paeth's article.) + + For all x < 0, assume Raw(x) = 0 and Prior(x) = 0. On the first + scanline of an image (or of a pass of an interlaced image), assume + Prior(x) = 0 for all x. + + To reverse the effect of the Paeth filter after decompression, + output the following value: + + Paeth(x) + PaethPredictor(Raw(x-bpp), Prior(x), Prior(x-bpp)) + + (computed mod 256), where Raw and Prior refer to bytes already + decoded. Exactly the same PaethPredictor function is used by both + encoder and decoder. diff --git a/lib/PDF/API2/Resource/XObject/Image/PNM.pm b/lib/PDF/API2/Resource/XObject/Image/PNM.pm new file mode 100644 index 0000000..2a14072 --- /dev/null +++ b/lib/PDF/API2/Resource/XObject/Image/PNM.pm @@ -0,0 +1,187 @@ +#line 1 "PDF/API2/Resource/XObject/Image/PNM.pm" +#line 1 "PDF/API2/Resource/XObject/Image/PNM.pm" +package PDF::API2::Resource::XObject::Image::PNM; + +# For spec details, see man pages pam(5), pbm(5), pgm(5), pnm(5), +# ppm(5), which were pasted into the __END__ of this file in an +# earlier revision. + +use base 'PDF::API2::Resource::XObject::Image'; + +use strict; +no warnings qw[ deprecated recursion uninitialized ]; + +our $VERSION = '2.033'; # VERSION + +use IO::File; +use PDF::API2::Util; +use PDF::API2::Basic::PDF::Utils; +use Scalar::Util qw(weaken); + +sub new { + my ($class,$pdf,$file,$name) = @_; + my $self; + + $class = ref $class if ref $class; + + $self=$class->SUPER::new($pdf,$name || 'Nx'.pdfkey()); + $pdf->new_obj($self) unless($self->is_obj($pdf)); + + $self->{' apipdf'}=$pdf; + weaken $self->{' apipdf'}; + + $self->read_pnm($pdf,$file); + + return($self); +} + +# READPPMHEADER +# taken from Image::PBMLib +# Copyright by Benjamin Elijah Griffin (28 Feb 2003) +# +sub readppmheader { + my $gr = shift; # input file glob ref + my $in = ''; + my $no_comments; + my %info; + my $rc; + $info{error} = undef; + + $rc = read($gr, $in, 3); + + if (!defined($rc) or $rc != 3) { + $info{error} = 'Read error or EOF'; + return \%info; + } + + if ($in =~ /^P([123456])\s/) { + $info{type} = $1; + if ($info{type} > 3) { + $info{raw} = 1; + } else { + $info{raw} = 0; + } + + if ($info{type} == 1 or $info{type} == 4) { + $info{max} = 1; + $info{bgp} = 'b'; + } elsif ($info{type} == 2 or $info{type} == 5) { + $info{bgp} = 'g'; + } else { + $info{bgp} = 'p'; + } + + while(1) { + $rc = read($gr, $in, 1, length($in)); + if (!defined($rc) or $rc != 1) { + $info{error} = 'Read error or EOF'; + return \%info; + } + + $no_comments = $in; + $info{comments} = ''; + while ($no_comments =~ /#.*\n/) { + $no_comments =~ s/#(.*\n)/ /; + $info{comments} .= $1; + } + + if ($info{bgp} eq 'b') { + if ($no_comments =~ /^P\d\s+(\d+)\s+(\d+)\s/) { + $info{width} = $1; + $info{height} = $2; + last; + } + } else { + if ($no_comments =~ /^P\d\s+(\d+)\s+(\d+)\s+(\d+)\s/) { + $info{width} = $1; + $info{height} = $2; + $info{max} = $3; + last; + } + } + } # while reading header + + $info{fullheader} = $in; + + } else { + $info{error} = 'Wrong magic number'; + } + + return \%info; +} + +sub read_pnm { + my $self = shift @_; + my $pdf = shift @_; + my $file = shift @_; + + my ($buf,$t,$s,$line); + my ($w,$h,$bpc,$cs,$img,@img)=(0,0,'','',''); + my $inf; + if (ref($file)) { + $inf = $file; + } + else { + open $inf, "<", $file or die "$!: $file"; + } + binmode($inf,':raw'); + $inf->seek(0,0); + my $info=readppmheader($inf); + if($info->{type} == 4) { + $bpc=1; + read($inf,$self->{' stream'},($info->{width}*$info->{height}/8)); + $cs='DeviceGray'; + $self->{Decode}=PDFArray(PDFNum(1),PDFNum(0)); + } elsif($info->{type} == 5) { + $buf.=<$inf>; + if($info->{max}==255){ + $s=0; + } else { + $s=255/$info->{max}; + } + $bpc=8; + if($s>0) { + for($line=($info->{width}*$info->{height});$line>0;$line--) { + read($inf,$buf,1); + $self->{' stream'}.=pack('C',(unpack('C',$buf)*$s)); + } + } else { + read($inf,$self->{' stream'},$info->{width}*$info->{height}); + } + $cs='DeviceGray'; + } elsif($info->{type} == 6) { + if($info->{max}==255){ + $s=0; + } else { + $s=255/$info->{max}; + } + $bpc=8; + if($s>0) { + for($line=($info->{width}*$info->{height});$line>0;$line--) { + read($inf,$buf,1); + $self->{' stream'}.=pack('C',(unpack('C',$buf)*$s)); + read($inf,$buf,1); + $self->{' stream'}.=pack('C',(unpack('C',$buf)*$s)); + read($inf,$buf,1); + $self->{' stream'}.=pack('C',(unpack('C',$buf)*$s)); + } + } else { + read($inf,$self->{' stream'},$info->{width}*$info->{height}*3); + } + $cs='DeviceRGB'; + } + close($inf); + + $self->width($info->{width}); + $self->height($info->{height}); + + $self->bpc($bpc); + + $self->filters('FlateDecode'); + + $self->colorspace($cs); + + return($self); +} + +1; diff --git a/lib/PDF/API2/Resource/XObject/Image/TIFF.pm b/lib/PDF/API2/Resource/XObject/Image/TIFF.pm new file mode 100644 index 0000000..e5df34c --- /dev/null +++ b/lib/PDF/API2/Resource/XObject/Image/TIFF.pm @@ -0,0 +1,295 @@ +#line 1 "PDF/API2/Resource/XObject/Image/TIFF.pm" +#line 1 "PDF/API2/Resource/XObject/Image/TIFF.pm" +package PDF::API2::Resource::XObject::Image::TIFF; + +use base 'PDF::API2::Resource::XObject::Image'; + +use strict; +use warnings; + +no warnings 'uninitialized'; + +our $VERSION = '2.033'; # VERSION + +use Compress::Zlib; + +use PDF::API2::Basic::PDF::Utils; +use PDF::API2::Resource::XObject::Image::TIFF::File; +use PDF::API2::Util; +use Scalar::Util qw(weaken); + +#line 32 + +sub new { + my ($class, $pdf, $file, $name) = @_; + my $self; + + my $tif = PDF::API2::Resource::XObject::Image::TIFF::File->new($file); + + # in case of problematic things + # proxy to other modules + + $class = ref($class) if ref($class); + + $self = $class->SUPER::new($pdf, $name || 'Ix' . pdfkey()); + $pdf->new_obj($self) unless $self->is_obj($pdf); + + $self->{' apipdf'} = $pdf; + weaken $self->{' apipdf'}; + + $self->read_tiff($pdf, $tif); + + $tif->close(); + + return $self; +} + +sub deLZW { + my ($ibits, $stream) = @_; + my $bits = $ibits; + my $resetcode = 1 << ($ibits - 1); + my $endcode = $resetcode + 1; + my $nextcode = $endcode + 1; + my $ptr = 0; + $stream = unpack('B*', $stream); + my $maxptr = length($stream); + my $tag; + my $out = ''; + my $outptr = 0; + + # print STDERR "reset=$resetcode\nend=$endcode\nmax=$maxptr\n"; + + my @d = map { chr($_) } (0 .. $resetcode - 1); + + while (($ptr + $bits) <= $maxptr) { + $tag=0; + foreach my $off (reverse 1 .. $bits) { + $tag <<= 1; + $tag |= substr($stream, $ptr + $bits - $off, 1); + } + # print STDERR "ptr=$ptr,tag=$tag,bits=$bits,next=$nextcode\n"; + # print STDERR "tag to large\n" if($tag>$nextcode); + $ptr += $bits; + if ($tag == $resetcode) { + $bits = $ibits; + $nextcode = $endcode + 1; + next; + } + elsif ($tag == $endcode) { + last; + } + elsif ($tag < $resetcode) { + $d[$nextcode] = $d[$tag]; + $out .= $d[$nextcode]; + $nextcode++; + } + elsif ($tag > $endcode) { + $d[$nextcode] = $d[$tag]; + $d[$nextcode] .= substr($d[$tag + 1], 0, 1); + $out .= $d[$nextcode]; + $nextcode++; + } + $bits++ if $nextcode == (1 << $bits); + } + return $out; +} + +sub handle_generic { + my ($self, $pdf, $tif) = @_; + + if ($tif->{'filter'}) { + # should we die here? + # die "unknown tiff-compression"; + $self->filters($tif->{filter}); + $self->{' nofilt'} = 1; + } + else { + $self->filters('FlateDecode'); + } + + if (ref($tif->{'imageOffset'})) { + $self->{' stream'} = ''; + my $d = scalar @{$tif->{'imageOffset'}}; + foreach (1..$d) { + my $buf; + $tif->{'fh'}->seek(shift(@{$tif->{'imageOffset'}}), 0); + $tif->{'fh'}->read($buf, shift(@{$tif->{'imageLength'}})); + $self->{' stream'} .= $buf; + } + } + else { + $tif->{'fh'}->seek($tif->{'imageOffset'}, 0); + $tif->{'fh'}->read($self->{' stream'}, $tif->{'imageLength'}); + } + + return $self; +} + +sub handle_flate { + my ($self, $pdf, $tif) = @_; + $self->filters('FlateDecode'); + + if (ref($tif->{'imageOffset'})) { + $self->{' stream'} = ''; + my $d = scalar @{$tif->{'imageOffset'}}; + foreach (1 .. $d) { + my $buf; + $tif->{'fh'}->seek(shift(@{$tif->{'imageOffset'}}),0); + $tif->{'fh'}->read($buf, shift(@{$tif->{'imageLength'}})); + $buf=uncompress($buf); + $self->{' stream'} .= $buf; + } + } + else { + $tif->{'fh'}->seek($tif->{'imageOffset'}, 0); + $tif->{'fh'}->read($self->{' stream'}, $tif->{'imageLength'}); + $self->{' stream'} = uncompress($self->{' stream'}); + } + + return $self; +} + +sub handle_lzw { + my ($self, $pdf, $tif) = @_; + $self->filters('FlateDecode'); + my $imageWidth = $tif->{'imageWidth'}; + my $mod = $imageWidth % 8; + if ($mod > 0) { + $imageWidth += 8 - $mod; + } + my $max_raw_strip = $imageWidth * $tif->{'bitsPerSample'} * $tif->{'RowsPerStrip'} / 8; + + if (ref($tif->{'imageOffset'})) { + $self->{' stream'}=''; + my $d = scalar @{$tif->{'imageOffset'}}; + foreach (1 .. $d) { + my $buf; + $tif->{'fh'}->seek(shift(@{$tif->{imageOffset}}), 0); + $tif->{'fh'}->read($buf, shift(@{$tif->{'imageLength'}})); + $buf = deLZW(9, $buf); + if (length($buf) > $max_raw_strip) { + $buf = substr($buf, 0, $max_raw_strip); + } + $self->{' stream'} .= $buf; + } + } + else { + $tif->{'fh'}->seek($tif->{'imageOffset'}, 0); + $tif->{'fh'}->read($self->{' stream'}, $tif->{'imageLength'}); + $self->{' stream'} = deLZW(9, $self->{' stream'}); + } + + return $self; +} + +sub handle_ccitt { + my ($self, $pdf, $tif) = @_; + + $self->{' nofilt'} = 1; + $self->{'Filter'} = PDFName('CCITTFaxDecode'); + $self->{'DecodeParms'} = PDFDict(); + $self->{'DecodeParms'}->{'K'} = (($tif->{'ccitt'} == 4 || ($tif->{'g3Options'} & 0x1)) ? PDFNum(-1) : PDFNum(0)); + $self->{'DecodeParms'}->{'Columns'} = PDFNum($tif->{'imageWidth'}); + $self->{'DecodeParms'}->{'Rows'} = PDFNum($tif->{'imageHeight'}); + $self->{'DecodeParms'}->{'Blackls1'} = PDFBool($tif->{'whiteIsZero'} == 1 ? 1 : 0); + if (defined($tif->{'g3Options'}) && ($tif->{'g3Options'} & 0x4)) { + $self->{'DecodeParms'}->{'EndOfLine'} = PDFBool(1); + $self->{'DecodeParms'}->{'EncodedByteAlign'} = PDFBool(1); + } + # $self->{'DecodeParms'} = PDFArray($self->{'DecodeParms'}); + $self->{'DecodeParms'}->{'DamagedRowsBeforeError'} = PDFNum(100); + + if (ref($tif->{'imageOffset'})) { + die "chunked ccitt g4 tif not supported."; + } + else { + $tif->{'fh'}->seek($tif->{'imageOffset'}, 0); + $tif->{'fh'}->read($self->{' stream'}, $tif->{'imageLength'}); + } + + return $self; +} + +sub read_tiff { + my ($self, $pdf, $tif) = @_; + + $self->width($tif->{'imageWidth'}); + $self->height($tif->{'imageHeight'}); + if ($tif->{'colorSpace'} eq 'Indexed') { + my $dict = PDFDict(); + $pdf->new_obj($dict); + $self->colorspace(PDFArray(PDFName($tif->{'colorSpace'}), PDFName('DeviceRGB'), PDFNum(255), $dict)); + $dict->{'Filter'} = PDFArray(PDFName('FlateDecode')); + $tif->{'fh'}->seek($tif->{'colorMapOffset'}, 0); + my $colormap; + my $straight; + $tif->{'fh'}->read($colormap, $tif->{'colorMapLength'}); + $dict->{' stream'} = ''; + $straight .= pack('C', ($_ / 256)) for unpack($tif->{'short'} . '*', $colormap); + foreach my $c (0 .. (($tif->{'colorMapSamples'} / 3) - 1)) { + $dict->{' stream'} .= substr($straight, $c, 1); + $dict->{' stream'} .= substr($straight, $c + ($tif->{'colorMapSamples'} / 3), 1); + $dict->{' stream'} .= substr($straight, $c + ($tif->{'colorMapSamples'} / 3) * 2, 1); + } + } + else { + $self->colorspace($tif->{'colorSpace'}); + } + + $self->{'Interpolate'} = PDFBool(1); + $self->bpc($tif->{'bitsPerSample'}); + + if ($tif->{'whiteIsZero'} == 1 && $tif->{'filter'} ne 'CCITTFaxDecode') { + $self->{'Decode'} = PDFArray(PDFNum(1), PDFNum(0)); + } + + # check filters and handle seperately + if (defined $tif->{'filter'} and $tif->{'filter'} eq 'CCITTFaxDecode') { + $self->handle_ccitt($pdf, $tif); + } + elsif (defined $tif->{'filter'} and $tif->{'filter'} eq 'LZWDecode') { + $self->handle_lzw($pdf, $tif); + } + elsif (defined $tif->{'filter'} and $tif->{filter} eq 'FlateDecode') { + $self->handle_flate($pdf, $tif); + } + else { + $self->handle_generic($pdf, $tif); + } + + if ($tif->{'fillOrder'} == 2) { + my @bl = (); + foreach my $n (0 .. 255) { + my $b = $n; + my $f = 0; + foreach (0 .. 7) { + my $bit = 0; + if ($b & 0x1) { + $bit = 1; + } + $b >>= 1; + $f <<= 1; + $f |= $bit; + } + $bl[$n] = $f; + } + my $l = length($self->{' stream'}) - 1; + foreach my $n (0 .. $l) { + vec($self->{' stream'}, $n, 8) = $bl[vec($self->{' stream'}, $n, 8)]; + } + } + $self->{' tiff'} = $tif; + + return $self; +} + +#line 307 + +sub tiffTag { + my ($self, $tag) = @_; + return $self->{' tiff'}->{$tag}; +} + +#line 316 + +1; diff --git a/lib/PDF/API2/Resource/XObject/Image/TIFF/File.pm b/lib/PDF/API2/Resource/XObject/Image/TIFF/File.pm new file mode 100644 index 0000000..6596c4f --- /dev/null +++ b/lib/PDF/API2/Resource/XObject/Image/TIFF/File.pm @@ -0,0 +1,283 @@ +#line 1 "PDF/API2/Resource/XObject/Image/TIFF/File.pm" +#line 1 "PDF/API2/Resource/XObject/Image/TIFF/File.pm" +package PDF::API2::Resource::XObject::Image::TIFF::File; + +use strict; +use warnings; + +our $VERSION = '2.033'; # VERSION + +use IO::File; + +sub new { + my ($class, $file) = @_; + + my $self = {}; + bless($self, $class); + if (ref($file)) { + $self->{'fh'} = $file; + seek($self->{'fh'}, 0, 0); + } + else { + $self->{'fh'} = IO::File->new(); + open($self->{'fh'}, '<', $file) or die "$!: $file"; + } + binmode($self->{'fh'}, ':raw'); + my $fh = $self->{'fh'}; + + $self->{'offset'} = 0; + $fh->seek($self->{'offset'}, 0); + + # checking byte order of data + $fh->read($self->{'byteOrder'}, 2); + $self->{'byte'} = 'C'; + $self->{'short'} = (($self->{'byteOrder'} eq 'MM') ? 'n' : 'v' ); + $self->{'long'} = (($self->{'byteOrder'} eq 'MM') ? 'N' : 'V' ); + $self->{'rational'} = (($self->{'byteOrder'} eq 'MM') ? 'NN' : 'VV' ); + + # get/check version id + $fh->read($self->{'version'}, 2); + $self->{'version'} = unpack($self->{'short'}, $self->{'version'}); + die "Wrong TIFF Id '$self->{version}' (should be 42)." if $self->{'version'} != 42; + + # get the offset to the first tag directory. + $fh->read($self->{'ifdOffset'}, 4); + $self->{'ifdOffset'} = unpack($self->{'long'}, $self->{'ifdOffset'}); + + $self->readTags(); + + return $self; +} + +sub readTag { + my $self = shift(); + my $fh = $self->{'fh'}; + my $buf; + $fh->read($buf, 12); + my $tag = unpack($self->{'short'}, substr($buf, 0, 2)); + my $type = unpack($self->{'short'}, substr($buf, 2, 2)); + my $count = unpack($self->{'long'}, substr($buf, 4, 4)); + my $len = 0; + + $len = ($type == 1 ? $count : # byte + $type == 2 ? $count : # char2 + $type == 3 ? $count * 2 : # int16 + $type == 4 ? $count * 4 : # int32 + $type == 5 ? $count * 8 : # rational: 2 * int32 + $count); + + my $off = substr($buf, 8, 4); + + if ($len > 4) { + $off = unpack($self->{'long'}, $off); + } + else { + $off = ($type == 1 ? unpack($self->{'byte'}, $off) : + $type == 2 ? unpack($self->{'long'}, $off) : + $type == 3 ? unpack($self->{'short'}, $off) : + $type == 4 ? unpack($self->{'long'}, $off) : unpack($self->{'short'}, $off)); + } + + return ($tag, $type, $count, $len, $off); +} + +sub close { ## no critic + my $self = shift(); + return $self->{'fh'}->close(); +} + +sub readTags { + my $self = shift(); + my $fh = $self->{'fh'}; + $self->{'fillOrder'} = 1; + $self->{'ifd'} = $self->{'ifdOffset'}; + + while ($self->{'ifd'} > 0) { + $fh->seek($self->{'ifd'}, 0); + $fh->read($self->{'ifdNum'}, 2); + $self->{'ifdNum'} = unpack($self->{'short'}, $self->{'ifdNum'}); + $self->{'bitsPerSample'} = 1; + foreach (1 .. $self->{'ifdNum'}) { + my ($valTag, $valType, $valCount, $valLen, $valOffset) = $self->readTag(); + # print "tag=$valTag type=$valType count=$valCount len=$valLen off=$valOffset\n"; + if ($valTag == 0) { + } + elsif ($valTag == 256) { + $self->{'imageWidth'} = $valOffset; + } + elsif ($valTag == 257) { + $self->{'imageHeight'} = $valOffset; + } + elsif ($valTag == 258) { + # bits per sample + if ($valCount > 1) { + my $here = $fh->tell(); + my $val; + $fh->seek($valOffset, 0); + $fh->read($val, 2); + $self->{'bitsPerSample'} = unpack($self->{'short'}, $val); + $fh->seek($here, 0); + } + else { + $self->{'bitsPerSample'} = $valOffset; + } + } + elsif ($valTag == 259) { + # compression + $self->{'filter'} = $valOffset; + if ($valOffset == 1) { + delete $self->{'filter'}; + } + elsif ($valOffset == 3 || $valOffset == 4) { + $self->{'filter'} = 'CCITTFaxDecode'; + $self->{'ccitt'} = $valOffset; + } + elsif ($valOffset == 5) { + $self->{'filter'} = 'LZWDecode'; + } + elsif ($valOffset == 6 || $valOffset == 7) { + $self->{'filter'} = 'DCTDecode'; + } + elsif ($valOffset == 8 || $valOffset == 0x80b2) { + $self->{'filter'} = 'FlateDecode'; + } + elsif ($valOffset == 32773) { + $self->{'filter'} = 'RunLengthDecode'; + } + else { + die "unknown/unsupported TIFF compression method with id '$self->{filter}'."; + } + } + elsif ($valTag == 262) { + # photometric interpretation + $self->{'colorSpace'} = $valOffset; + if ($valOffset == 0) { + $self->{'colorSpace'} = 'DeviceGray'; + $self->{'whiteIsZero'} = 1; + } + elsif ($valOffset == 1) { + $self->{'colorSpace'} = 'DeviceGray'; + $self->{'blackIsZero'} = 1; + } + elsif ($valOffset == 2) { + $self->{'colorSpace'} = 'DeviceRGB'; + } + elsif($valOffset == 3) { + $self->{'colorSpace'} = 'Indexed'; + } + # elsif($valOffset == 4) { + # $self->{'colorSpace'} = 'TransMask'; + # } + elsif ($valOffset == 5) { + $self->{'colorSpace'} = 'DeviceCMYK'; + } + elsif($valOffset == 6) { + $self->{'colorSpace'} = 'DeviceRGB'; + } + elsif ($valOffset == 8) { + $self->{'colorSpace'} = 'Lab'; + } + else { + die "unknown/unsupported TIFF photometric interpretation with id '$self->{colorSpace}'."; + } + } + elsif ($valTag == 266) { + $self->{'fillOrder'} = $valOffset; + } + elsif ($valTag == 270) { + # ImageDescription + my $here = $fh->tell(); + $fh->seek($valOffset, 0); + $fh->read($self->{'imageDescription'}, $valLen); + $fh->seek($here, 0); + } + elsif($valTag == 282) { + # xRes + my $here = $fh->tell(); + $fh->seek($valOffset, 0); + $fh->read($self->{'xRes'}, $valLen); + $fh->seek($here, 0); + $self->{'xRes'} = [unpack($self->{'rational'}, $self->{'xRes'})]; + $self->{'xRes'} = ($self->{'xRes'}->[0] / $self->{'xRes'}->[1]); + } + elsif($valTag == 283) { + # yRes + my $here = $fh->tell(); + $fh->seek($valOffset, 0); + $fh->read($self->{'yRes'}, $valLen); + $fh->seek($here, 0); + $self->{'yRes'} = [unpack($self->{'rational'}, $self->{'yRes'})]; + $self->{'yRes'} = ($self->{'yRes'}->[0] / $self->{'yRes'}->[1]); + } + elsif ($valTag == 296) { + # resolution Unit + $self->{'resUnit'} = $valOffset; + } + elsif ($valTag == 273) { + # image data offset/strip offsets + if ($valCount == 1) { + $self->{'imageOffset'} = $valOffset; + } + else { + my $here =$fh->tell(); + my $val; + $fh->seek($valOffset, 0); + $fh->read($val, $valLen); + $fh->seek($here, 0); + $self->{'imageOffset'} = [unpack($self->{'long'} . '*', $val)]; + } + } + elsif ($valTag == 277) { + $self->{'samplesPerPixel'} = $valOffset; + } + elsif ($valTag == 278) { + $self->{'RowsPerStrip'} = $valOffset; + } + elsif ($valTag == 279) { + # image data length/strip lengths + if ($valCount == 1) { + $self->{'imageLength'} = $valOffset; + } + else { + my $here = $fh->tell(); + my $val; + $fh->seek($valOffset, 0); + $fh->read($val, $valLen); + $fh->seek($here, 0); + $self->{'imageLength'} = [unpack($self->{'long'} . '*', $val)]; + } + } + elsif ($valTag == 292) { + $self->{'g3Options'} = $valOffset; + } + elsif ($valTag == 293) { + $self->{'g4Options'} = $valOffset; + } + elsif ($valTag == 320) { + # color map + $self->{'colorMapOffset'} = $valOffset; + $self->{'colorMapSamples'} = $valCount; + $self->{'colorMapLength'} = $valCount * 2; # shorts! + } + elsif ($valTag == 317) { + $self->{'lzwPredictor'} = $valOffset; + } + elsif ($valTag == 0x800d) { + # imageID + my $here = $fh->tell(); + $fh->seek($valOffset, 0); + $fh->read($self->{'imageId'}, $valLen); + $fh->seek($here, 0); + } + # else { + # print "tag=$valTag, type=$valType, len=$valLen\n"; + # } + } + $fh->read($self->{'ifd'}, 4); + $self->{'ifd'} = unpack($self->{'long'}, $self->{'ifd'}); + } + + return $self; +} + +1; diff --git a/lib/PDF/API2/Util.pm b/lib/PDF/API2/Util.pm new file mode 100644 index 0000000..d873367 --- /dev/null +++ b/lib/PDF/API2/Util.pm @@ -0,0 +1,684 @@ +#line 1 "PDF/API2/Util.pm" +#line 1 "PDF/API2/Util.pm" +package PDF::API2::Util; + +use strict; +no warnings qw[ recursion uninitialized ]; + +our $VERSION = '2.033'; # VERSION + +BEGIN { + use Encode qw(:all); + use Math::Trig; + use List::Util qw(min max); + use PDF::API2::Basic::PDF::Utils; + use PDF::API2::Basic::PDF::Filter; + use PDF::API2::Resource::Colors; + use PDF::API2::Resource::Glyphs; + use PDF::API2::Resource::PaperSizes; + use POSIX qw( HUGE_VAL floor ); + + use vars qw( + @ISA + @EXPORT + @EXPORT_OK + %colors + $key_var + %u2n + %n2u + $pua + %PaperSizes + ); + + use Exporter; + @ISA = qw(Exporter); + @EXPORT = qw( + pdfkey + float floats floats5 intg intgs + mMin mMax + HSVtoRGB RGBtoHSV HSLtoRGB RGBtoHSL RGBtoLUM + namecolor namecolor_cmyk namecolor_lab optInvColor defineColor + dofilter unfilter + nameByUni uniByName initNameTable defineName + page_size + getPaperSizes + ); + @EXPORT_OK = qw( + pdfkey + digest digestx digest16 digest32 + float floats floats5 intg intgs + mMin mMax + cRGB cRGB8 RGBasCMYK + HSVtoRGB RGBtoHSV HSLtoRGB RGBtoHSL RGBtoLUM + namecolor namecolor_cmyk namecolor_lab optInvColor defineColor + dofilter unfilter + nameByUni uniByName initNameTable defineName + page_size + ); + + %colors = PDF::API2::Resource::Colors->get_colors(); + %PaperSizes = PDF::API2::Resource::PaperSizes->get_paper_sizes(); + + no warnings qw[ recursion uninitialized ]; + + $key_var = 'CBA'; + + $pua = 0xE000; + + %u2n = %{$PDF::API2::Resource::Glyphs::u2n}; + %n2u = %{$PDF::API2::Resource::Glyphs::n2u}; +} + +sub pdfkey { + return $PDF::API2::Util::key_var++; +} + +sub digestx { + my $len = shift(); + my $mask = $len - 1; + my $ddata = join('', @_); + my $mdkey = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789gT'; + my $xdata = '0' x $len; + my $off = 0; + foreach my $set (0 .. (length($ddata) << 1)) { + $off += vec($ddata, $set, 4); + $off += vec($xdata, ($set & $mask), 8); + vec($xdata, ($set & ($mask << 1 | 1)), 4) = vec($mdkey, ($off & 0x7f), 4); + } + + # foreach $set (0 .. $mask) { + # vec($xdata, $set, 8) = (vec($xdata, $set, 8) & 0x7f) | 0x40; + # } + + # $off = 0; + # foreach $set (0 .. $mask) { + # $off += vec($xdata, $set, 8); + # vec($xdata, $set, 8) = vec($mdkey, ($off & 0x3f), 8); + # } + + return $xdata; +} + +sub digest { + return digestx(32, @_); +} + +sub digest16 { + return digestx(16, @_); +} + +sub digest32 { + return digestx(32, @_); +} + +sub xlog10 { + my $n = shift(); + if ($n) { + return log(abs($n)) / log(10); + } + else { + return 0; + } +} + +sub float { + my $f = shift(); + my $mxd = shift() || 4; + $f = 0 if abs($f) < 0.0000000000000001; + my $ad = floor(xlog10($f) - $mxd); + if (abs($f - int($f)) < (10 ** (-$mxd))) { + # just in case we have an integer + return sprintf('%i', $f); + } + elsif ($ad > 0) { + my $value = sprintf('%f', $f); + # Remove trailing zeros + $value =~ s/(\.\d*?)0+$/$1/; + $value =~ s/\.$//; + return $value; + } + else { + my $value = sprintf('%.*f', abs($ad), $f); + # Remove trailing zeros + $value =~ s/(\.\d*?)0+$/$1/; + $value =~ s/\.$//; + return $value; + } +} +sub floats { return map { float($_) } @_; } +sub floats5 { return map { float($_, 5) } @_; } + +sub intg { + my $f = shift(); + return sprintf('%i', $f); +} +sub intgs { return map { intg($_) } @_; } + +sub mMin { + my $n = HUGE_VAL(); + map { $n = ($n > $_) ? $_ : $n } @_; + return $n; +} + +sub mMax { + my $n = -HUGE_VAL(); + map { $n = ($n < $_) ? $_ : $n } @_; + return $n; +} + +sub cRGB { + my @cmy = (map { 1 - $_ } @_); + my $k = mMin(@cmy); + return (map { $_ - $k } @cmy), $k; +} + +sub cRGB8 { + return cRGB(map { $_ / 255 } @_); +} + +sub RGBtoLUM { + my ($r, $g, $b) = @_; + return $r * 0.299 + $g * 0.587 + $b * 0.114; +} + +sub RGBasCMYK { + my @rgb = @_; + my @cmy = map { 1 - $_ } @rgb; + my $k = mMin(@cmy) * 0.44; + return (map { $_ - $k } @cmy), $k; +} + +sub HSVtoRGB { + my ($h, $s, $v) = @_; + my ($r, $g, $b, $i, $f, $p, $q, $t); + + if ($s == 0) { + # achromatic (grey) + return ($v, $v, $v); + } + + $h %= 360; + $h /= 60; ## sector 0 to 5 + $i = POSIX::floor($h); + $f = $h - $i; ## factorial part of h + $p = $v * (1 - $s); + $q = $v * (1 - $s * $f); + $t = $v * (1 - $s * (1 - $f)); + + if ($i < 1) { + $r = $v; + $g = $t; + $b = $p; + } + elsif ($i < 2) { + $r = $q; + $g = $v; + $b = $p; + } + elsif ($i < 3) { + $r = $p; + $g = $v; + $b = $t; + } + elsif ($i < 4) { + $r = $p; + $g = $q; + $b = $v; + } + elsif ($i < 5) { + $r = $t; + $g = $p; + $b = $v; + } + else { + $r = $v; + $g = $p; + $b = $q; + } + + return ($r, $g, $b); +} + +sub RGBquant { + my ($q1, $q2, $h) = @_; + while ($h < 0){ + $h += 360; + } + $h %= 360; + if ($h < 60) { + return $q1 + (($q2 - $q1) * $h / 60); + } + elsif ($h < 180) { + return $q2; + } + elsif ($h < 240) { + return $q1 + (($q2 - $q1) * (240 - $h) / 60); + } + else { + return $q1; + } +} + +sub RGBtoHSV { + my ($r, $g, $b) = @_; + my ($h, $s, $v, $min, $max, $delta); + + $min = mMin($r, $g, $b); + $max = mMax($r, $g, $b); + + $v = $max; + + $delta = $max - $min; + + if ($delta > 0.000000001) { + $s = $delta / $max; + } + else { + $s = 0; + $h = 0; + return ($h, $s, $v); + } + + if ($r == $max) { + $h = ($g - $b) / $delta; + } + elsif ($g == $max) { + $h = 2 + ($b - $r) / $delta; + } + else { + $h = 4 + ($r - $g) / $delta; + } + $h *= 60; + if ($h < 0) { + $h += 360; + } + return ($h, $s, $v); +} + +sub RGBtoHSL { + my ($r, $g, $b) = @_; + my ($h, $s, $v, $l, $min, $max, $delta); + + $min = mMin($r, $g, $b); + $max = mMax($r, $g, $b); + ($h, $s, $v) = RGBtoHSV($r, $g, $b); + $l = ($max + $min) / 2.0; + $delta = $max - $min; + if ($delta < 0.00000000001) { + return (0, 0, $l); + } + else { + if ($l <= 0.5) { + $s = $delta / ($max + $min); + } + else { + $s = $delta / (2 - $max - $min); + } + } + return ($h, $s, $l); +} + +sub HSLtoRGB { + my ($h, $s, $l, $r, $g, $b, $p1, $p2) = @_; + if ($l <= 0.5) { + $p2 = $l * (1 + $s); + } + else { + $p2 = $l + $s - ($l * $s); + } + $p1 = 2 * $l - $p2; + if ($s < 0.0000000000001) { + $r = $g = $b = $l; + } + else { + $r = RGBquant($p1, $p2, $h + 120); + $g = RGBquant($p1, $p2, $h); + $b = RGBquant($p1, $p2, $h - 120); + } + return ($r, $g, $b); +} + +sub optInvColor { + my ($r, $g, $b) = @_; + + my $ab = (0.2 * $r) + (0.7 * $g) + (0.1 * $b); + + if ($ab > 0.45) { + return (0, 0, 0); + } + else { + return (1, 1, 1); + } +} + +sub defineColor { + my ($name, $mx, $r, $g, $b) = @_; + $colors{$name} ||= [ map {$_ / $mx} ($r, $g, $b) ]; + return $colors{$name}; +} + +sub rgbHexValues { + my $name = lc(shift()); + my ($r, $g, $b); + if (length($name) < 5) { # zb. #fa4, #cf0 + $r = hex(substr($name, 1, 1)) / 0xf; + $g = hex(substr($name, 2, 1)) / 0xf; + $b = hex(substr($name, 3, 1)) / 0xf; + } + elsif (length($name) < 8) { # zb. #ffaa44, #ccff00 + $r = hex(substr($name, 1, 2)) / 0xff; + $g = hex(substr($name, 3, 2)) / 0xff; + $b = hex(substr($name, 5, 2)) / 0xff; + } + elsif(length($name) < 11) { # zb. #fffaaa444, #cccfff000 + $r = hex(substr($name, 1, 3)) / 0xfff; + $g = hex(substr($name, 4, 3)) / 0xfff; + $b = hex(substr($name, 7, 3)) / 0xfff; + } + else { # zb. #ffffaaaa4444, #ccccffff0000 + $r = hex(substr($name, 1, 4)) / 0xffff; + $g = hex(substr($name, 5, 4)) / 0xffff; + $b = hex(substr($name, 9, 4)) / 0xffff; + } + return ($r, $g, $b); +} + +sub cmykHexValues { + my $name = lc(shift()); + my ($c, $m, $y, $k); + if (length($name) < 6) { # zb. %cmyk + $c = hex(substr($name, 1, 1)) / 0xf; + $m = hex(substr($name, 2, 1)) / 0xf; + $y = hex(substr($name, 3, 1)) / 0xf; + $k = hex(substr($name, 4, 1)) / 0xf; + } + elsif (length($name) < 10) { # zb. %ccmmyykk + $c = hex(substr($name, 1, 2)) / 0xff; + $m = hex(substr($name, 3, 2)) / 0xff; + $y = hex(substr($name, 5, 2)) / 0xff; + $k = hex(substr($name, 7, 2)) / 0xff; + } + elsif (length($name) < 14) { # zb. %cccmmmyyykkk + $c = hex(substr($name, 1, 3)) / 0xfff; + $m = hex(substr($name, 4, 3)) / 0xfff; + $y = hex(substr($name, 7, 3)) / 0xfff; + $k = hex(substr($name, 10, 3)) / 0xfff; + } + else { # zb. %ccccmmmmyyyykkkk + $c = hex(substr($name, 1, 4)) / 0xffff; + $m = hex(substr($name, 5, 4)) / 0xffff; + $y = hex(substr($name, 9, 4)) / 0xffff; + $k = hex(substr($name, 13, 4)) / 0xffff; + } + return ($c, $m, $y, $k); +} + +sub hsvHexValues { + my $name = lc(shift()); + my ($h, $s, $v); + if (length($name) < 5) { + $h = 360 * hex(substr($name, 1, 1)) / 0x10; + $s = hex(substr($name, 2, 1)) / 0xf; + $v = hex(substr($name, 3, 1)) / 0xf; + } + elsif (length($name) < 8) { + $h = 360 * hex(substr($name, 1, 2)) / 0x100; + $s = hex(substr($name, 3, 2)) / 0xff; + $v = hex(substr($name, 5, 2)) / 0xff; + } + elsif (length($name) < 11) { + $h = 360 * hex(substr($name, 1, 3)) / 0x1000; + $s = hex(substr($name, 4, 3)) / 0xfff; + $v = hex(substr($name, 7, 3)) / 0xfff; + } + else { + $h = 360 * hex(substr($name, 1, 4)) / 0x10000; + $s = hex(substr($name, 5, 4)) / 0xffff; + $v = hex(substr($name, 9, 4)) / 0xffff; + } + return ($h, $s, $v); +} + +sub labHexValues { + my $name = lc(shift()); + my ($l, $a, $b); + if (length($name) < 5) { + $l = 100 * hex(substr($name, 1, 1)) / 0xf; + $a = (200 * hex(substr($name, 2, 1)) / 0xf) - 100; + $b = (200 * hex(substr($name, 3, 1)) / 0xf) - 100; + } + elsif (length($name) < 8) { + $l = 100 * hex(substr($name, 1, 2)) / 0xff; + $a = (200 * hex(substr($name, 3, 2)) / 0xff) - 100; + $b = (200 * hex(substr($name, 5, 2)) / 0xff) - 100; + } + elsif (length($name) < 11) { + $l = 100 * hex(substr($name, 1, 3)) / 0xfff; + $a = (200 * hex(substr($name, 4, 3)) / 0xfff) - 100; + $b = (200 * hex(substr($name, 7, 3)) / 0xfff) - 100; + } + else { + $l = 100 * hex(substr($name, 1, 4)) / 0xffff; + $a = (200 * hex(substr($name, 5, 4)) / 0xffff) - 100; + $b = (200 * hex(substr($name, 9, 4)) / 0xffff) - 100; + } + + return ($l, $a, $b); +} + +sub namecolor { + my $name = shift(); + unless (ref($name)) { + $name = lc($name); + $name =~ s/[^\#!%\&\$a-z0-9]//g; + } + if ($name =~ /^[a-z]/) { # name spec. + return namecolor($colors{$name}); + } + elsif ($name =~ /^#/) { # rgb spec. + return floats5(rgbHexValues($name)); + } + elsif ($name =~ /^%/) { # cmyk spec. + return floats5(cmykHexValues($name)); + } + elsif ($name =~ /^!/) { # hsv spec. + return floats5(HSVtoRGB(hsvHexValues($name))); + } + elsif ($name =~ /^&/) { # hsl spec. + return floats5(HSLtoRGB(hsvHexValues($name))); + } + else { # or it is a ref ? + return floats5(@{$name || [0.5, 0.5, 0.5]}); + } +} + +sub namecolor_cmyk { + my $name = shift(); + unless (ref($name)) { + $name = lc($name); + $name =~ s/[^\#!%\&\$a-z0-9]//g; + } + if ($name =~ /^[a-z]/) { # name spec. + return namecolor_cmyk($colors{$name}); + } + elsif ($name =~ /^#/) { # rgb spec. + return floats5(RGBasCMYK(rgbHexValues($name))); + } + elsif ($name =~ /^%/) { # cmyk spec. + return floats5(cmykHexValues($name)); + } + elsif ($name =~ /^!/) { # hsv spec. + return floats5(RGBasCMYK(HSVtoRGB(hsvHexValues($name)))); + } + elsif ($name =~ /^&/) { # hsl spec. + return floats5(RGBasCMYK(HSLtoRGB(hsvHexValues($name)))); + } + else { # or it is a ref ? + return floats5(RGBasCMYK(@{$name || [0.5, 0.5, 0.5]})); + } +} + +sub namecolor_lab { + my $name = shift(); + unless (ref($name)) { + $name = lc($name); + $name =~ s/[^\#!%\&\$a-z0-9]//g; + } + if ($name =~ /^[a-z]/) { # name spec. + return namecolor_lab($colors{$name}); + } + elsif ($name =~ /^\$/) { # lab spec. + return floats5(labHexValues($name)); + } + elsif ($name =~ /^#/) { # rgb spec. + my ($h, $s, $v) = RGBtoHSV(rgbHexValues($name)); + my $a = cos(deg2rad($h)) * $s * 100; + my $b = sin(deg2rad($h)) * $s * 100; + my $l = 100 * $v; + return floats5($l,$a,$b); + } + elsif ($name =~ /^!/) { # hsv spec. + # fake conversion + my ($h, $s, $v) = hsvHexValues($name); + my $a = cos(deg2rad($h)) * $s * 100; + my $b = sin(deg2rad($h)) * $s * 100; + my $l = 100 * $v; + return floats5($l,$a,$b); + } + elsif ($name =~ /^&/) { # hsl spec. + my ($h, $s, $v) = hsvHexValues($name); + my $a = cos(deg2rad($h)) * $s * 100; + my $b = sin(deg2rad($h)) * $s * 100; + ($h, $s, $v) = RGBtoHSV(HSLtoRGB($h, $s, $v)); + my $l = 100 * $v; + return floats5($l,$a,$b); + } + else { # or it is a ref ? + my ($h, $s, $v) = RGBtoHSV(@{$name || [0.5, 0.5, 0.5]}); + my $a = cos(deg2rad($h)) * $s * 100; + my $b = sin(deg2rad($h)) * $s * 100; + my $l = 100 * $v; + return floats5($l,$a,$b); + } +} + +sub unfilter { + my ($filter, $stream) = @_; + + if (defined $filter) { + # we need to fix filter because it MAY be + # an array BUT IT COULD BE only a name + if (ref($filter) !~ /Array$/) { + $filter = PDFArray($filter); + } + my @filts; + my ($hasflate) = -1; + my ($temp, $i, $temp1); + + @filts = map { ("PDF::API2::Basic::PDF::Filter::" . $_->val())->new() } $filter->elementsof(); + + foreach my $f (@filts) { + $stream = $f->infilt($stream, 1); + } + } + + return $stream; +} + +sub dofilter { + my ($filter, $stream) = @_; + + if (defined $filter) { + # we need to fix filter because it MAY be + # an array BUT IT COULD BE only a name + if (ref($filter) !~ /Array$/) { + $filter = PDFArray($filter); + } + my @filts; + my $hasflate = -1; + my ($temp, $i, $temp1); + + @filts = map { ("PDF::API2::Basic::PDF::Filter::" . $_->val())->new() } $filter->elementsof(); + + foreach my $f (@filts) { + $stream = $f->outfilt($stream, 1); + } + } + + return $stream; +} + +sub nameByUni { + my $e = shift(); + return $u2n{$e} || sprintf('uni%04X', $e); +} + +sub uniByName { + my $e = shift(); + if ($e =~ /^uni([0-9A-F]{4})$/) { + return hex($1); + } + return $n2u{$e} || undef; +} + +sub initNameTable { + %u2n = %{$PDF::API2::Resource::Glyphs::u2n}; + %n2u = %{$PDF::API2::Resource::Glyphs::n2u}; + $pua = 0xE000; + return; +} + +sub defineName { + my $name = shift(); + return $n2u{$name} if defined $n2u{$name}; + + $pua++ while defined $u2n{$pua}; + + $u2n{$pua} = $name; + $n2u{$name} = $pua; + + return $pua; +} + +sub page_size { + my ($x1, $y1, $x2, $y2) = @_; + + # full bbox + if (defined $x2) { + return ($x1, $y1, $x2, $y2); + } + + # half bbox + elsif (defined $y1) { + return (0, 0, $x1, $y1); + } + + # textual spec. + elsif (defined $PaperSizes{lc $x1}) { + return (0, 0, @{$PaperSizes{lc $x1}}); + } + + # single quadratic + elsif ($x1 =~ /^[\d\.]+$/) { + return(0, 0, $x1, $x1); + } + + # pdf default. + else { + return (0, 0, 612, 792); + } +} + +sub getPaperSizes { + my %sizes = (); + foreach my $type (keys %PaperSizes) { + $sizes{$type} = [@{$PaperSizes{$type}}]; + } + return %sizes; +} + +1; + +__END__ + +#line 713 diff --git a/lib/PDF/Table.pm b/lib/PDF/Table.pm new file mode 100644 index 0000000..006d4de --- /dev/null +++ b/lib/PDF/Table.pm @@ -0,0 +1,942 @@ +#!/usr/bin/env perl +#line 2 "PDF/Table.pm" +# vim: softtabstop=4 tabstop=4 shiftwidth=4 ft=perl expandtab smarttab + +use 5.006; +use strict; +use warnings; + +package PDF::Table; + +use Carp; +our $VERSION = '0.10.1'; + +print __PACKAGE__.' is version: '.$VERSION.$/ if($ENV{'PDF_TABLE_DEBUG'}); + +############################################################ +# +# new - Constructor +# +# Parameters are meta information about the PDF +# +# $pdf = PDF::Table->new(); +# +############################################################ + +sub new +{ + my $type = shift(@_); + my $class = ref($type) || $type; + my $self = {}; + bless ($self, $class); + + # Pass all the rest to init for validation and initialisation + $self->_init(@_); + + return $self; +} + +sub _init +{ + my ($self, $pdf, $page, $data, %options ) = @_; + + # Check and set default values + $self->set_defaults(); + + # Check and set mandatory params + $self->set_pdf($pdf); + $self->set_page($page); + $self->set_data($data); + $self->set_options(\%options); + + return; +} + +sub set_defaults{ + my $self = shift; + + $self->{'font_size'} = 12; +} + +sub set_pdf{ + my ($self, $pdf) = @_; + $self->{'pdf'} = $pdf; +} + +sub set_page{ + my ($self, $page) = @_; + if ( defined($page) && ref($page) ne 'PDF::API2::Page' ){ + + if( ref($self->{'pdf'}) eq 'PDF::API2' ){ + $self->{'page'} = $self->{'pdf'}->page(); + } else { + carp 'Warning: Page must be a PDF::API2::Page object but it seems to be: '.ref($page).$/; + carp 'Error: Cannot set page from passed PDF object either as it is invalid!'.$/; + } + return; + } + $self->{'page'} = $page; + +} + +sub set_data{ + my ($self, $data) = @_; + #TODO: implement +} + +sub set_options{ + my ($self, $options) = @_; + #TODO: implement +} + +############################################################ +# +# text_block - utility method to build multi-paragraph blocks of text +# +############################################################ + +sub text_block +{ + my $self = shift; + my $text_object = shift; + my $text = shift; # The text to be displayed + my %arg = @_; # Additional Arguments + + my ( $align, $xpos, $ypos, $xbase, $ybase, $line_width, $wordspace, $endw , $width, $height) = + ( undef , undef, undef, undef , undef , undef , undef , undef , undef , undef ); + my @line = (); # Temp data array with words on one line + my %width = (); # The width of every unique word in the givven text + + # Try to provide backward compatibility + foreach my $key (keys %arg) + { + my $newkey = $key; + if($newkey =~ s#^-##) + { + $arg{$newkey} = $arg{$key}; + delete $arg{$key}; + } + } + ##### + + #--- + # Lets check mandatory parameters with no default values + #--- + $xbase = $arg{'x'} || -1; + $ybase = $arg{'y'} || -1; + $width = $arg{'w'} || -1; + $height = $arg{'h'} || -1; + unless( $xbase > 0 ){ carp "Error: Left Edge of Block is NOT defined!\n"; return; } + unless( $ybase > 0 ){ carp "Error: Base Line of Block is NOT defined!\n"; return; } + unless( $width > 0 ){ carp "Error: Width of Block is NOT defined!\n"; return; } + unless( $height > 0 ){ carp "Error: Height of Block is NOT defined!\n"; return; } + # Check if any text to display + unless( defined( $text) and length($text) > 0 ) + { + carp "Warning: No input text found. Trying to add dummy '-' and not to break everything.\n"; + $text = '-'; + } + + # Strip any <CR> and Split the text into paragraphs + $text =~ s/\r//g; + my @paragraphs = split(/\n/, $text); + + # Width between lines in pixels + my $line_space = defined $arg{'lead'} && $arg{'lead'} > 0 ? $arg{'lead'} : 12; + + # Calculate width of all words + my $space_width = $text_object->advancewidth("\x20"); + my @words = split(/\s+/, $text); + foreach (@words) + { + next if exists $width{$_}; + $width{$_} = $text_object->advancewidth($_); + } + + my @paragraph = split(' ', shift(@paragraphs)); + my $first_line = 1; + my $first_paragraph = 1; + + # Little Init + $xpos = $xbase; + $ypos = $ybase; + $ypos = $ybase + $line_space; + my $bottom_border = $ypos - $height; + # While we can add another line + while ( $ypos >= $bottom_border + $line_space ) + { + # Is there any text to render ? + unless (@paragraph) + { + # Finish if nothing left + last unless scalar @paragraphs; + # Else take one line from the text + @paragraph = split(' ', shift( @paragraphs ) ); + + $ypos -= $arg{'parspace'} if $arg{'parspace'}; + last unless $ypos >= $bottom_border; + } + $ypos -= $line_space; + $xpos = $xbase; + + # While there's room on the line, add another word + @line = (); + $line_width = 0; + if( $first_line && exists $arg{'hang'} ) + { + my $hang_width = $text_object->advancewidth($arg{'hang'}); + + $text_object->translate( $xpos, $ypos ); + $text_object->text( $arg{'hang'} ); + + $xpos += $hang_width; + $line_width += $hang_width; + $arg{'indent'} += $hang_width if $first_paragraph; + } + elsif( $first_line && exists $arg{'flindent'} && $arg{'flindent'} > 0 ) + { + $xpos += $arg{'flindent'}; + $line_width += $arg{'flindent'}; + } + elsif( $first_paragraph && exists $arg{'fpindent'} && $arg{'fpindent'} > 0 ) + { + $xpos += $arg{'fpindent'}; + $line_width += $arg{'fpindent'}; + } + elsif (exists $arg{'indent'} && $arg{'indent'} > 0 ) + { + $xpos += $arg{'indent'}; + $line_width += $arg{'indent'}; + } + + # Lets take from paragraph as many words as we can put into $width - $indent; + while ( @paragraph and $text_object->advancewidth( join("\x20", @line)."\x20" . $paragraph[0]) + + $line_width < $width ) + { + push(@line, shift(@paragraph)); + } + $line_width += $text_object->advancewidth(join('', @line)); + + # calculate the space width + if( $arg{'align'} eq 'fulljustify' or ($arg{'align'} eq 'justify' and @paragraph)) + { + @line = split(//,$line[0]) if (scalar(@line) == 1) ; + $wordspace = ($width - $line_width) / (scalar(@line) - 1); + $align='justify'; + } + else + { + $align=($arg{'align'} eq 'justify') ? 'left' : $arg{'align'}; + $wordspace = $space_width; + } + $line_width += $wordspace * (scalar(@line) - 1); + + if( $align eq 'justify') + { + foreach my $word (@line) + { + $text_object->translate( $xpos, $ypos ); + $text_object->text( $word ); + $xpos += ($width{$word} + $wordspace) if (@line); + } + $endw = $width; + } + else + { + # calculate the left hand position of the line + if( $align eq 'right' ) + { + $xpos += $width - $line_width; + } + elsif( $align eq 'center' ) + { + $xpos += ( $width / 2 ) - ( $line_width / 2 ); + } + + # render the line + $text_object->translate( $xpos, $ypos ); + $endw = $text_object->text( join("\x20", @line)); + } + $first_line = 0; + }#End of while( + unshift(@paragraphs, join(' ',@paragraph)) if scalar(@paragraph); + return ($endw, $ypos, join("\n", @paragraphs)) +} + + +################################################################ +# table - utility method to build multi-row, multicolumn tables +################################################################ +sub table +{ + my $self = shift; + my $pdf = shift; + my $page = shift; + my $data = shift; + my %arg = @_; + + #===================================== + # Mandatory Arguments Section + #===================================== + unless($pdf and $page and $data) + { + carp "Error: Mandatory parameter is missing pdf/page/data object!\n"; + return; + } + + # Validate mandatory argument data type + croak "Error: Invalid pdf object received." unless (ref($pdf) eq 'PDF::API2'); + croak "Error: Invalid page object received." unless (ref($page) eq 'PDF::API2::Page'); + croak "Error: Invalid data received." unless ((ref($data) eq 'ARRAY') && scalar(@$data)); + croak "Error: Missing required settings." unless (scalar(keys %arg)); + + # Validate settings key + my %valid_settings_key = ( + x => 1, + w => 1, + start_y => 1, + start_h => 1, + next_y => 1, + next_h => 1, + lead => 1, + padding => 1, + padding_right => 1, + padding_left => 1, + padding_top => 1, + padding_bottom => 1, + background_color => 1, + background_color_odd => 1, + background_color_even => 1, + border => 1, + border_color => 1, + horizontal_borders => 1, + vertical_borders => 1, + font => 1, + font_size => 1, + font_underline => 1, + font_color => 1, + font_color_even => 1, + font_color_odd => 1, + background_color_odd => 1, + background_color_even => 1, + row_height => 1, + new_page_func => 1, + header_props => 1, + column_props => 1, + cell_props => 1, + max_word_length => 1, + cell_render_hook => 1, + default_text => 1, + ); + foreach my $key (keys %arg) + { + # Provide backward compatibility + $arg{$key} = delete $arg{"-$key"} if $key =~ s/^-//; + + croak "Error: Invalid setting key '$key' received." + unless exists $valid_settings_key{$key}; + } + + + ###### + #TODO: Add code for header props compatibility and col_props comp.... + ###### + my ( $xbase, $ybase, $width, $height ) = ( undef, undef, undef, undef ); + # Could be 'int' or 'real' values + $xbase = $arg{'x' } || -1; + $ybase = $arg{'start_y'} || -1; + $width = $arg{'w' } || -1; + $height = $arg{'start_h'} || -1; + + # Global geometry parameters are also mandatory. + unless( $xbase > 0 ){ carp "Error: Left Edge of Table is NOT defined!\n"; return; } + unless( $ybase > 0 ){ carp "Error: Base Line of Table is NOT defined!\n"; return; } + unless( $width > 0 ){ carp "Error: Width of Table is NOT defined!\n"; return; } + unless( $height > 0 ){ carp "Error: Height of Table is NOT defined!\n"; return; } + + # Ensure default values for -next_y and -next_h + my $next_y = $arg{'next_y'} || $arg{'start_y'} || 0; + my $next_h = $arg{'next_h'} || $arg{'start_h'} || 0; + + # Create Text Object + my $txt = $page->text; + + # Set Default Properties + my $fnt_name = $arg{'font' } || $pdf->corefont('Times',-encode => 'utf8'); + my $fnt_size = $arg{'font_size' } || 12; + my $fnt_underline = $arg{'font_underline' } || undef; # merely stating undef is the intended default + my $max_word_len = $arg{'max_word_length' } || 20; + + #===================================== + # Table Header Section + #===================================== + # Disable header row into the table + my $header_props = undef; + + # Check if the user enabled it ? + if(defined $arg{'header_props'} and ref( $arg{'header_props'}) eq 'HASH') + { + # Transfer the reference to local variable + $header_props = $arg{'header_props'}; + + # Check other params and put defaults if needed + $header_props->{'repeat' } = $header_props->{'repeat' } || 0; + $header_props->{'font' } = $header_props->{'font' } || $fnt_name; + $header_props->{'font_color' } = $header_props->{'font_color' } || '#000066'; + $header_props->{'font_size' } = $header_props->{'font_size' } || $fnt_size + 2; + $header_props->{'font_underline'} = $header_props->{'font_underline'} || $fnt_underline; + $header_props->{'bg_color' } = $header_props->{'bg_color' } || '#FFFFAA'; + $header_props->{'justify' } = $header_props->{'justify' }; + } + + my $header_row = undef; + #===================================== + # Other Parameters check + #===================================== + my $lead = $arg{'lead' } || $fnt_size; + my $pad_left = $arg{'padding_left' } || $arg{'padding'} || 0; + my $pad_right = $arg{'padding_right' } || $arg{'padding'} || 0; + my $pad_top = $arg{'padding_top' } || $arg{'padding'} || 0; + my $pad_bot = $arg{'padding_bottom'} || $arg{'padding'} || 0; + my $default_text = $arg{'default_text' } // '-'; + my $line_w = defined $arg{'border'} ? $arg{'border'} : 1 ; + my $horiz_borders = defined $arg{'horizontal_borders'} + ? $arg{'horizontal_borders'} + : $line_w; + my $vert_borders = defined $arg{'vertical_borders'} + ? $arg{'vertical_borders'} + : $line_w; + + my $background_color_even = $arg{'background_color_even' } || $arg{'background_color'} || undef; + my $background_color_odd = $arg{'background_color_odd' } || $arg{'background_color'} || undef; + my $font_color_even = $arg{'font_color_even' } || $arg{'font_color' } || 'black'; + my $font_color_odd = $arg{'font_color_odd' } || $arg{'font_color' } || 'black'; + my $border_color = $arg{'border_color' } || 'black'; + + my $min_row_h = $fnt_size + $pad_top + $pad_bot; + my $row_h = defined ($arg{'row_height'}) + && + ($arg{'row_height'} > $min_row_h) + ? + $arg{'row_height'} : $min_row_h; + + my $pg_cnt = 1; + my $cur_y = $ybase; + my $cell_props = $arg{cell_props} || []; # per cell properties + + #If there is no valid data array reference warn and return! + if(ref $data ne 'ARRAY') + { + carp "Passed table data is not an ARRAY reference. It's actually a ref to ".ref($data); + return ($page,0,$cur_y); + } + + # Copy the header row if header is enabled + @$header_row = $$data[0] if defined $header_props; + # Determine column widths based on content + + # an arrayref whose values are a hashref holding + # the minimum and maximum width of that column + my $col_props = $arg{'column_props'} || []; + + # An array ref of arrayrefs whose values are + # the actual widths of the column/row intersection + my $row_col_widths = []; + # An array ref with the widths of the header row + my $header_row_props = []; + + # Scalars that hold sum of the maximum and minimum widths of all columns + my ( $max_col_w , $min_col_w ) = ( 0,0 ); + my ( $row, $col_name, $col_fnt_size, $col_fnt_underline, $space_w ); + + my $word_widths = {}; + my $rows_height = []; + my $first_row = 1; + + for( my $row_idx = 0; $row_idx < scalar(@$data) ; $row_idx++ ) + { + my $column_widths = []; #holds the width of each column + # Init the height for this row + $rows_height->[$row_idx] = 0; + + for( my $column_idx = 0; $column_idx < scalar(@{$data->[$row_idx]}) ; $column_idx++ ) + { + # look for font information for this column + my ($cell_font, $cell_font_size, $cell_font_underline); + + if( !$row_idx and ref $header_props ) + { + $cell_font = $header_props->{'font'}; + $cell_font_size = $header_props->{'font_size'}; + $cell_font_underline = $header_props->{'font_underline'}; + } + + # Get the most specific value if none was already set from header_props + $cell_font ||= $cell_props->[$row_idx][$column_idx]->{'font'} + || $col_props->[$column_idx]->{'font'} + || $fnt_name; + + $cell_font_size ||= $cell_props->[$row_idx][$column_idx]->{'font_size'} + || $col_props->[$column_idx]->{'font_size'} + || $fnt_size; + + $cell_font_underline ||= $cell_props->[$row_idx][$column_idx]->{'font_underline'} + || $col_props->[$column_idx]->{'font_underline'} + || $fnt_underline; + + # Set Font + + # Set Font + $txt->font( $cell_font, $cell_font_size ); + + # Set row height to biggest font size from row's cells + if( $cell_font_size > $rows_height->[$row_idx] ) + { + $rows_height->[$row_idx] = $cell_font_size; + } + + # This should fix a bug with very long words like serial numbers etc. + if( $max_word_len > 0 ) + { + $data->[$row_idx][$column_idx] =~ s#(\S{$max_word_len})(?=\S)#$1 #g; + } + + # Init cell size limits + $space_w = $txt->advancewidth( "\x20" ); + $column_widths->[$column_idx] = 0; + $max_col_w = 0; + $min_col_w = 0; + + my @words = split( /\s+/, $data->[$row_idx][$column_idx] ); + + foreach( @words ) + { + unless( exists $word_widths->{$_} ) + { # Calculate the width of every word and add the space width to it + $word_widths->{$_} = $txt->advancewidth( $_ ) + $space_w; + } + + $column_widths->[$column_idx] += $word_widths->{$_}; + $min_col_w = $word_widths->{$_} if( $word_widths->{$_} > $min_col_w ); + $max_col_w += $word_widths->{$_}; + } + + $min_col_w += $pad_left + $pad_right; + $max_col_w += $pad_left + $pad_right; + $column_widths->[$column_idx] += $pad_left + $pad_right; + + # Keep a running total of the overall min and max widths + $col_props->[$column_idx]->{'min_w'} ||= 0; + $col_props->[$column_idx]->{'max_w'} ||= 0; + + if( $min_col_w > $col_props->[$column_idx]->{'min_w'} ) + { # Calculated Minimum Column Width is more than user-defined + $col_props->[$column_idx]->{'min_w'} = $min_col_w ; + } + + if( $max_col_w > $col_props->[$column_idx]->{'max_w'} ) + { # Calculated Maximum Column Width is more than user-defined + $col_props->[$column_idx]->{'max_w'} = $max_col_w ; + } + }#End of for(my $column_idx.... + + $row_col_widths->[$row_idx] = $column_widths; + + # Copy the calculated row properties of header row. + @$header_row_props = @$column_widths if(!$row_idx and ref $header_props); + } + + # Calc real column widths and expand table width if needed. + my $calc_column_widths; + ($calc_column_widths, $width) = CalcColumnWidths( $col_props, $width ); + + # Lets draw what we have! + my $row_index = 0; + # Store header row height for later use if headers have to be repeated + my $header_row_height = $rows_height->[0]; + + my ( $gfx, $gfx_bg, $background_color, $font_color, $bot_marg, $table_top_y, $text_start); + + # Each iteration adds a new page as neccessary + while(scalar(@{$data})) + { + my ($page_header); + my $columns_number = 0; + + if($pg_cnt == 1) + { + $table_top_y = $ybase; + $bot_marg = $table_top_y - $height; + + # Check for safety reasons + if( $bot_marg < 0 ) + { # This warning should remain i think + carp "!!! Warning: !!! Incorrect Table Geometry! start_h (${height}) is above start_y (${table_top_y}). Setting bottom margin to end of sheet!\n"; + $bot_marg = 0; + } + + } + else + { + if(ref $arg{'new_page_func'}) + { + $page = &{$arg{'new_page_func'}}; + } + else + { + $page = $pdf->page; + } + + $table_top_y = $next_y; + $bot_marg = $table_top_y - $next_h; + + # Check for safety reasons + if( $bot_marg < 0 ) + { # This warning should remain i think + carp "!!! Warning: !!! Incorrect Table Geometry! next_y or start_y (${next_y}) is above next_h or start_h (${next_h}). Setting bottom margin to end of sheet!\n"; + $bot_marg = 0; + } + + if( ref $header_props and $header_props->{'repeat'}) + { + # Copy Header Data + @$page_header = @$header_row; + my $hrp ; + @$hrp = @$header_row_props ; + # Then prepend it to master data array + unshift @$data, @$page_header; + unshift @$row_col_widths, $hrp; + unshift @$rows_height, $header_row_height; + + $first_row = 1; # Means YES + $row_index--; # Rollback the row_index because a new header row has been added + } + } + + $gfx_bg = $page->gfx; + $txt = $page->text; + $txt->font($fnt_name, $fnt_size); + + $cur_y = $table_top_y; + + if ($line_w) + { + $gfx = $page->gfx; + $gfx->strokecolor($border_color); + $gfx->linewidth($line_w); + + # Draw the top line + if ($horiz_borders) + { + $gfx->move( $xbase , $cur_y ); + $gfx->hline($xbase + $width ); + } + } + else + { + $gfx = undef; + } + + # Each iteration adds a row to the current page until the page is full + # or there are no more rows to add + # Row_Loop + while(scalar(@{$data}) and $cur_y-$row_h > $bot_marg) + { + # Remove the next item from $data + my $record = shift @{$data}; + + # Get max columns number to know later how many vertical lines to draw + $columns_number = scalar(@$record) + if scalar(@$record) > $columns_number; + + # Get the next set of row related settings + # Row Height + my $pre_calculated_row_height = shift @$rows_height; + + # Row cell widths + my $record_widths = shift @$row_col_widths; + + # Row coloumn props - TODO in another commit + + # Row cell props - TODO in another commit + + + # Choose colors for this row + $background_color = $row_index % 2 ? $background_color_even : $background_color_odd; + $font_color = $row_index % 2 ? $font_color_even : $font_color_odd; + + #Determine current row height + my $current_row_height = $pad_top + $pre_calculated_row_height + $pad_bot; + + # $row_h is the calculated global user requested row height. + # It will be honored, only if it has bigger value than the calculated one. + # TODO: It's questionable if padding should be inclided in this calculation or not + if($current_row_height < $row_h){ + $current_row_height = $row_h; + } + + # Define the font y base position for this line. + $text_start = $cur_y - ($current_row_height - $pad_bot); + + my $cur_x = $xbase; + my $leftovers = undef; # Reference to text that is returned from textblock() + my $do_leftovers = 0; + + # Process every cell(column) from current row + for( my $column_idx = 0; $column_idx < scalar( @$record); $column_idx++ ) + { + next unless $col_props->[$column_idx]->{'max_w'}; + next unless $col_props->[$column_idx]->{'min_w'}; + $leftovers->[$column_idx] = undef; + + # look for font information for this cell + my ($cell_font, $cell_font_size, $cell_font_color, $cell_font_underline, $justify); + + if( $first_row and ref $header_props) + { + $cell_font = $header_props->{'font'}; + $cell_font_size = $header_props->{'font_size'}; + $cell_font_color = $header_props->{'font_color'}; + $cell_font_underline = $header_props->{'font_underline'}; + $justify = $header_props->{'justify'}; + } + + # Get the most specific value if none was already set from header_props + $cell_font ||= $cell_props->[$row_index][$column_idx]->{'font'} + || $col_props->[$column_idx]->{'font'} + || $fnt_name; + + $cell_font_size ||= $cell_props->[$row_index][$column_idx]->{'font_size'} + || $col_props->[$column_idx]->{'font_size'} + || $fnt_size; + + $cell_font_color ||= $cell_props->[$row_index][$column_idx]->{'font_color'} + || $col_props->[$column_idx]->{'font_color'} + || $font_color; + + $cell_font_underline ||= $cell_props->[$row_index][$column_idx]->{'font_underline'} + || $col_props->[$column_idx]->{'font_underline'} + || $fnt_underline; + + + $justify ||= $cell_props->[$row_index][$column_idx]->{'justify'} + || $col_props->[$column_idx]->{'justify'} + || $arg{'justify'} + || 'left'; + + # Init cell font object + $txt->font( $cell_font, $cell_font_size ); + $txt->fillcolor($cell_font_color); + + # Added to resolve infite loop bug with returned undef values + $record->[$column_idx] //= $cell_props->[$row_index][$column_idx]->{'default_text'} + // $col_props->[$column_idx]->{'default_text'} + // $default_text; + + # If the content is wider than the specified width, we need to add the text as a text block + if( $record->[$column_idx] !~ m/(.\n.)/ and + $record_widths->[$column_idx] and + $record_widths->[$column_idx] <= $calc_column_widths->[$column_idx] + ){ + my $space = $pad_left; + if ($justify eq 'right') + { + $space = $calc_column_widths->[$column_idx] -($txt->advancewidth($record->[$column_idx]) + $pad_right); + } + elsif ($justify eq 'center') + { + $space = ($calc_column_widths->[$column_idx] - $txt->advancewidth($record->[$column_idx])) / 2; + } + $txt->translate( $cur_x + $space, $text_start ); + my %text_options; + $text_options{'-underline'} = $cell_font_underline if $cell_font_underline; + $txt->text( $record->[$column_idx], %text_options ); + } + # Otherwise just use the $page->text() method + else + { + my ($width_of_last_line, $ypos_of_last_line, $left_over_text) = $self->text_block( + $txt, + $record->[$column_idx], + x => $cur_x + $pad_left, + y => $text_start, + w => $calc_column_widths->[$column_idx] - $pad_left - $pad_right, + h => $cur_y - $bot_marg - $pad_top - $pad_bot, + align => $justify, + lead => $lead + ); + # Desi - Removed $lead because of fixed incorrect ypos bug in text_block + my $current_cell_height = $cur_y - $ypos_of_last_line + $pad_bot; + if( $current_cell_height > $current_row_height ) + { + $current_row_height = $current_cell_height; + } + + if( $left_over_text ) + { + $leftovers->[$column_idx] = $left_over_text; + $do_leftovers = 1; + } + } + + # Hook to pass coordinates back - http://www.perlmonks.org/?node_id=754777 + if (ref $arg{cell_render_hook} eq 'CODE') { + $arg{cell_render_hook}->( + $page, + $first_row, + $row_index, + $column_idx, + $cur_x, + $cur_y-$row_h, + $calc_column_widths->[$column_idx], + $row_h + ); + } + + $cur_x += $calc_column_widths->[$column_idx]; + } + if( $do_leftovers ) + { + unshift @$data, $leftovers; + unshift @$row_col_widths, $record_widths; + unshift @$rows_height, $pre_calculated_row_height; + } + + # Draw cell bgcolor + # This has to be separately from the text loop + # because we do not know the final height of the cell until all text has been drawn + $cur_x = $xbase; + for(my $column_idx = 0 ; $column_idx < scalar(@$record) ; $column_idx++) + { + my $cell_bg_color; + + if( $first_row and ref $header_props) + { #Compatibility Consistency with other props + $cell_bg_color = $header_props->{'bg_color'} || $header_props->{'background_color'}; + } + + # Get the most specific value if none was already set from header_props + $cell_bg_color ||= $cell_props->[$row_index][$column_idx]->{'background_color'} + || $col_props->[$column_idx]->{'background_color'} + || $background_color; + + if ($cell_bg_color) + { + $gfx_bg->rect( $cur_x, $cur_y-$current_row_height, $calc_column_widths->[$column_idx], $current_row_height); + $gfx_bg->fillcolor($cell_bg_color); + $gfx_bg->fill(); + } + $cur_x += $calc_column_widths->[$column_idx]; + }#End of for(my $column_idx.... + + $cur_y -= $current_row_height; + if ($gfx && $horiz_borders) + { + $gfx->move( $xbase , $cur_y ); + $gfx->hline( $xbase + $width ); + } + + $row_index++ unless ( $do_leftovers ); + $first_row = 0; + }# End of Row_Loop + + if ($gfx) + { + # Draw vertical lines + if ($vert_borders) + { + $gfx->move( $xbase, $table_top_y); + $gfx->vline( $cur_y ); + my $cur_x = $xbase; + for( my $j = 0; $j < $columns_number; $j++ ) + { + $cur_x += $calc_column_widths->[$j]; + $gfx->move( $cur_x, $table_top_y ); + $gfx->vline( $cur_y ); + } + } + + # ACTUALLY draw all the lines + $gfx->fillcolor( $border_color); + $gfx->stroke; + } + $pg_cnt++; + }# End of while(scalar(@{$data})) + + return ($page,--$pg_cnt,$cur_y); +} + + +# calculate the column widths +sub CalcColumnWidths +{ + my $col_props = shift; + my $avail_width = shift; + my $min_width = 0; + + my $calc_widths ; + + for(my $j = 0; $j < scalar( @$col_props); $j++) + { + $min_width += $col_props->[$j]->{min_w} || 0; + } + + # I think this is the optimal variant when good view can be guaranateed + if($avail_width < $min_width) + { + carp "!!! Warning !!!\n Calculated Mininal width($min_width) > Table width($avail_width).\n", + ' Expanding table width to:',int($min_width)+1,' but this could lead to unexpected results.',"\n", + ' Possible solutions:',"\n", + ' 0)Increase table width.',"\n", + ' 1)Decrease font size.',"\n", + ' 2)Choose a more narrow font.',"\n", + ' 3)Decrease "max_word_length" parameter.',"\n", + ' 4)Rotate page to landscape(if it is portrait).',"\n", + ' 5)Use larger paper size.',"\n", + '!!! --------- !!!',"\n"; + $avail_width = int( $min_width) + 1; + + } + + # Calculate how much can be added to every column to fit the available width. + for(my $j = 0; $j < scalar(@$col_props); $j++ ) + { + $calc_widths->[$j] = $col_props->[$j]->{min_w} || 0;; + } + + # Allow columns to expand to max_w before applying extra space equally. + my $is_last_iter; + for (;;) + { + my $span = ($avail_width - $min_width) / scalar( @$col_props); + last if $span <= 0; + + $min_width = 0; + my $next_will_be_last_iter = 1; + for(my $j = 0; $j < scalar(@$col_props); $j++ ) + { + my $new_w = $calc_widths->[$j] + $span; + + if (!$is_last_iter && $new_w > $col_props->[$j]->{max_w}) + { + $new_w = $col_props->[$j]->{max_w} + } + if ($calc_widths->[$j] != $new_w ) + { + $calc_widths->[$j] = $new_w; + $next_will_be_last_iter = 0; + } + $min_width += $new_w; + } + last if $is_last_iter; + $is_last_iter = $next_will_be_last_iter; + } + + return ($calc_widths,$avail_width); +} +1; + +__END__ + +#line 1582 + diff --git a/lib/URI/Encode.pm b/lib/URI/Encode.pm index 2fc004e..60a8131 100644 --- a/lib/URI/Encode.pm +++ b/lib/URI/Encode.pm @@ -1,4 +1,6 @@ #line 1 "URI/Encode.pm" +#line 1 "URI/Encode.pm" +#line 1 "URI/Encode.pm" package URI::Encode; ####################### diff --git a/tmpl/page/rendezvous.tt b/tmpl/page/rendezvous.tt new file mode 100644 index 0000000..e69de29 -- 2.39.5